diff --git a/Gopkg.lock b/Gopkg.lock index 44614dc45..cad217fc8 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,6 +2,7 @@ [[projects]] + digest = "1:5fecf403b2c8151d1142acee2ca7de61e819675e67a63cdd407ffab5ec20d40b" name = "github.com/aws/aws-sdk-go" packages = [ "aws", @@ -25,108 +26,165 @@ "internal/sdkrand", "internal/shareddefaults", "private/protocol", + "private/protocol/eventstream", + "private/protocol/eventstream/eventstreamapi", "private/protocol/query", "private/protocol/query/queryutil", "private/protocol/rest", + "private/protocol/restxml", "private/protocol/xml/xmlutil", "service/cloudformation", + "service/s3", "service/sns", "service/sqs", - "service/sts" + "service/sts", ] + pruneopts = "" revision = "e79e9fd4ec11ccc242a472f980be78830f9eba80" version = "v1.14.13" [[projects]] branch = "master" + digest = "1:61eda50b1c7785c6d876b3d31053a677313d5a85309668f29f7cb6d7ac0f0ab6" name = "github.com/christopherhein/go-version" packages = ["."] - revision = "5fdeffe57a3a31bed39a910291143d7d4d3cc463" + pruneopts = "" + revision = "fee8dd1f7c24da23508e26347694be0acce5631b" [[projects]] branch = "master" + digest = "1:6750a96828487595e7012e8e403a68b443d63b0a4596be623346a22bf9d3d9e0" name = "github.com/christopherhein/operator-kit" packages = ["."] - revision = "f612660f2de31eed446c00b9fcd9e92cbeb5850f" + pruneopts = "" + revision = "656879a55790116c7db2488cf0786378e21c27a8" [[projects]] + digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b" name = "github.com/davecgh/go-spew" packages = ["spew"] + pruneopts = "" revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" [[projects]] + digest = "1:eb53021a8aa3f599d29c7102e65026242bdedce998a54837dc67f14b6a97c5fd" name = "github.com/fsnotify/fsnotify" packages = ["."] + pruneopts = "" revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" version = "v1.4.7" [[projects]] + digest = "1:b13707423743d41665fd23f0c36b2f37bb49c30e94adb813319c44188a51ba22" name = "github.com/ghodss/yaml" packages = ["."] + pruneopts = "" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] + digest = "1:617b3e0f5989d4ff866a1820480990c65dfc9257eb080da749a45e2d76681b02" name = "github.com/go-ini/ini" packages = ["."] + pruneopts = "" revision = "06f5f3d67269ccec1fe5fe4134ba6e982984f7f5" version = "v1.37.0" [[projects]] + digest = "1:0a3f6a0c68ab8f3d455f8892295503b179e571b7fefe47cc6c556405d1f83411" name = "github.com/gogo/protobuf" packages = [ "proto", - "sortkeys" + "sortkeys", ] + pruneopts = "" revision = "1adfc126b41513cc696b209667c8656ea7aac67c" version = "v1.0.0" [[projects]] branch = "master" + digest = "1:107b233e45174dbab5b1324201d092ea9448e58243ab9f039e4c0f332e121e3a" name = "github.com/golang/glog" packages = ["."] + pruneopts = "" revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" [[projects]] + branch = "master" + digest = "1:9854532d7b2fee9414d4fcd8d8bccd6b1c1e1663d8ec0337af63a19aaf4a778e" + name = "github.com/golang/groupcache" + packages = ["lru"] + pruneopts = "" + revision = "6f2cf27854a4a29e3811b0371547be335d411b8b" + +[[projects]] + digest = "1:f958a1c137db276e52f0b50efee41a1a389dcdded59a69711f3e872757dab34b" name = "github.com/golang/protobuf" packages = [ "proto", "ptypes", "ptypes/any", "ptypes/duration", - "ptypes/timestamp" + "ptypes/timestamp", ] + pruneopts = "" revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" version = "v1.1.0" [[projects]] branch = "master" + digest = "1:1e5b1e14524ed08301977b7b8e10c719ed853cbf3f24ecb66fae783a46f207a6" + name = "github.com/google/btree" + packages = ["."] + pruneopts = "" + revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306" + +[[projects]] + branch = "master" + digest = "1:754f77e9c839b24778a4b64422236d38515301d2baeb63113aa3edc42e6af692" name = "github.com/google/gofuzz" packages = ["."] + pruneopts = "" revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" [[projects]] + digest = "1:16b2837c8b3cf045fa2cdc82af0cf78b19582701394484ae76b2c3bc3c99ad73" name = "github.com/googleapis/gnostic" packages = [ "OpenAPIv2", "compiler", - "extensions" + "extensions", ] + pruneopts = "" revision = "7c663266750e7d82587642f65e60bc4083f1f84e" version = "v0.2.0" [[projects]] branch = "master" + digest = "1:009a1928b8c096338b68b5822d838a72b4d8520715c1463614476359f3282ec8" + name = "github.com/gregjones/httpcache" + packages = [ + ".", + "diskcache", + ] + pruneopts = "" + revision = "9cad4c3443a7200dd6400aef47183728de563a38" + +[[projects]] + branch = "master" + digest = "1:9c776d7d9c54b7ed89f119e449983c3f24c0023e75001d6092442412ebca6b94" name = "github.com/hashicorp/golang-lru" packages = [ ".", - "simplelru" + "simplelru", ] + pruneopts = "" revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3" [[projects]] branch = "master" + digest = "1:9b7c5846d70f425d7fe279595e32a20994c6075e87be03b5c367ed07280877c5" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -138,148 +196,207 @@ "hcl/token", "json/parser", "json/scanner", - "json/token" + "json/token", ] + pruneopts = "" revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" [[projects]] branch = "master" - name = "github.com/howeyc/gopass" + digest = "1:67bcf41677f33b22aee1b82e9460aa093a96cfe4877445dd19ea950c200a47ab" + name = "github.com/iancoleman/strcase" packages = ["."] - revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8" + pruneopts = "" + revision = "3605ed457bf7f8caa1371b4fafadadc026673479" [[projects]] + digest = "1:302c6eb8e669c997bec516a138b8fc496018faa1ece4c13e445a2749fbe079bb" name = "github.com/imdario/mergo" packages = ["."] + pruneopts = "" revision = "9316a62528ac99aaecb4e47eadd6dc8aa6533d58" version = "v0.3.5" [[projects]] + digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" name = "github.com/inconshreveable/mousetrap" packages = ["."] + pruneopts = "" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" [[projects]] + digest = "1:6f49eae0c1e5dab1dafafee34b207aeb7a42303105960944828c2079b92fc88e" name = "github.com/jmespath/go-jmespath" packages = ["."] + pruneopts = "" revision = "0b12d6b5" [[projects]] + digest = "1:31c6f3c4f1e15fcc24fcfc9f5f24603ff3963c56d6fa162116493b4025fb6acc" name = "github.com/json-iterator/go" packages = ["."] - revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4" - version = "1.1.3" + pruneopts = "" + revision = "f2b4162afba35581b6d4a50d3b8f34e33c144682" [[projects]] + digest = "1:961dc3b1d11f969370533390fdf203813162980c858e1dabe827b60940c909a5" name = "github.com/magiconair/properties" packages = ["."] + pruneopts = "" revision = "c2353362d570a7bfa228149c62842019201cfb71" version = "v1.8.0" [[projects]] branch = "master" + digest = "1:99651e95333755cbe5c9768c1b80031300acca64a80870b40309202b32585a5a" name = "github.com/mitchellh/go-homedir" packages = ["."] + pruneopts = "" revision = "3864e76763d94a6df2f9960b16a20a33da9f9a66" [[projects]] branch = "master" + digest = "1:eb9117392ee8e7aa44f78e0db603f70b1050ee0ebda4bd40040befb5b218c546" name = "github.com/mitchellh/mapstructure" packages = ["."] + pruneopts = "" revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b" [[projects]] + digest = "1:0c0ff2a89c1bb0d01887e1dac043ad7efbf3ec77482ef058ac423d13497e16fd" name = "github.com/modern-go/concurrent" packages = ["."] + pruneopts = "" revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" version = "1.0.3" [[projects]] + digest = "1:420f9231f816eeca3ff5aab070caac3ed7f27e4d37ded96ce9de3d7a7a2e31ad" name = "github.com/modern-go/reflect2" packages = ["."] + pruneopts = "" revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f" version = "1.0.0" [[projects]] + digest = "1:894aef961c056b6d85d12bac890bf60c44e99b46292888bfa66caf529f804457" name = "github.com/pelletier/go-toml" packages = ["."] + pruneopts = "" revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194" version = "v1.2.0" [[projects]] + branch = "master" + digest = "1:c24598ffeadd2762552269271b3b1510df2d83ee6696c1e543a0ff653af494bc" + name = "github.com/petar/GoLLRB" + packages = ["llrb"] + pruneopts = "" + revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" + +[[projects]] + digest = "1:b46305723171710475f2dd37547edd57b67b9de9f2a6267cafdd98331fd6897f" + name = "github.com/peterbourgon/diskv" + packages = ["."] + pruneopts = "" + revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" + version = "v2.0.1" + +[[projects]] + digest = "1:8cf46b6c18a91068d446e26b67512cf16f1540b45d90b28b9533706a127f0ca6" name = "github.com/sirupsen/logrus" packages = ["."] + pruneopts = "" revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" version = "v1.0.5" [[projects]] + digest = "1:7ba2551c9a8de293bc575dbe2c0d862c52252d26f267f784547f059f512471c8" name = "github.com/spf13/afero" packages = [ ".", - "mem" + "mem", ] + pruneopts = "" revision = "787d034dfe70e44075ccc060d346146ef53270ad" version = "v1.1.1" [[projects]] + digest = "1:d0b38ba6da419a6d4380700218eeec8623841d44a856bb57369c172fbf692ab4" name = "github.com/spf13/cast" packages = ["."] + pruneopts = "" revision = "8965335b8c7107321228e3e3702cab9832751bac" version = "v1.2.0" [[projects]] + digest = "1:a1403cc8a94b8d7956ee5e9694badef0e7b051af289caad1cf668331e3ffa4f6" name = "github.com/spf13/cobra" packages = ["."] + pruneopts = "" revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385" version = "v0.0.3" [[projects]] branch = "master" + digest = "1:104517520aab91164020ab6524a5d6b7cafc641b2e42ac6236f6ac1deac4f66a" name = "github.com/spf13/jwalterweatherman" packages = ["."] + pruneopts = "" revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" [[projects]] + digest = "1:8e243c568f36b09031ec18dff5f7d2769dcf5ca4d624ea511c8e3197dc3d352d" name = "github.com/spf13/pflag" packages = ["."] + pruneopts = "" revision = "583c0c0531f06d5278b7d917446061adc344b5cd" version = "v1.0.1" [[projects]] + digest = "1:3dab237cd3263a290d771d133fed777bb56c22e380b00ebe92e6531d5c8d3d0c" name = "github.com/spf13/viper" packages = ["."] + pruneopts = "" revision = "b5e8006cbee93ec955a89ab31e0e3ce3204f3736" version = "v1.0.2" [[projects]] branch = "master" + digest = "1:6ef14be530be39b6b9d75d54ce1d546ae9231e652d9e3eef198cbb19ce8ed3e7" name = "golang.org/x/crypto" packages = ["ssh/terminal"] + pruneopts = "" revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" [[projects]] branch = "master" + digest = "1:4656104e65eed39be4ad82d1c2d31ccb391ba51817ccfbb6140562b141392b71" name = "golang.org/x/net" packages = [ "context", "http/httpguts", "http2", "http2/hpack", - "idna" + "idna", ] + pruneopts = "" revision = "afe8f62b1d6bbd81f31868121a50b06d8188e1f9" [[projects]] branch = "master" + digest = "1:60c3915cfa691dc713534798a10a8893a425c4ab8c569aeca2bd4a51ae81638c" name = "golang.org/x/sys" packages = [ "unix", - "windows" + "windows", ] + pruneopts = "" revision = "63fc586f45fe72d95d5240a5d5eb95e6503907d3" [[projects]] + digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4" name = "golang.org/x/text" packages = [ "collate", @@ -295,41 +412,50 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable" + "unicode/rangetable", ] + pruneopts = "" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" + digest = "1:55a681cb66f28755765fa5fa5104cbd8dc85c55c02d206f9f89566451e3fe1aa" name = "golang.org/x/time" packages = ["rate"] + pruneopts = "" revision = "fbb02b2291d28baffd63558aa44b4b56f178d650" [[projects]] branch = "master" + digest = "1:cddd9fefc3e3d7e08c25df4566b40899b955f1a636dfc7587770eee774481561" name = "golang.org/x/tools" packages = [ "go/ast/astutil", "imports", - "internal/fastwalk" + "internal/fastwalk", ] + pruneopts = "" revision = "25b95b48224cce18163c7d49dcfb89a2d5ecd209" [[projects]] + digest = "1:75fb3fcfc73a8c723efde7777b40e8e8ff9babf30d8c56160d01beffea8a95a6" name = "gopkg.in/inf.v0" packages = ["."] + pruneopts = "" revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" version = "v0.9.1" [[projects]] + digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2" name = "gopkg.in/yaml.v2" packages = ["."] + pruneopts = "" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [[projects]] - branch = "release-1.10" + digest = "1:77c0f2ebdb247964329c2495dea64be895fcc22de75f0fd719f092b6f869af53" name = "k8s.io/api" packages = [ "admissionregistration/v1alpha1", @@ -356,26 +482,32 @@ "rbac/v1alpha1", "rbac/v1beta1", "scheduling/v1alpha1", + "scheduling/v1beta1", "settings/v1alpha1", "storage/v1", "storage/v1alpha1", - "storage/v1beta1" + "storage/v1beta1", ] - revision = "8b7507fac302640dd5f1efbf9643199952cc58db" + pruneopts = "" + revision = "4e7be11eab3ffcfc1876898b8272df53785a9504" + version = "kubernetes-1.11.3" [[projects]] + digest = "1:f9f73d3b579f131a678448e39345e45f7e911f6ba75777a42df45e2e9995ad2b" name = "k8s.io/apiextensions-apiserver" packages = [ "pkg/apis/apiextensions", "pkg/apis/apiextensions/v1beta1", "pkg/client/clientset/clientset", "pkg/client/clientset/clientset/scheme", - "pkg/client/clientset/clientset/typed/apiextensions/v1beta1" + "pkg/client/clientset/clientset/typed/apiextensions/v1beta1", ] - revision = "8e7f43002fec5394a8d96ebca781aa9d4b37aaef" - version = "kubernetes-1.10.4" + pruneopts = "" + revision = "b05d9bb7cc74a62c5daac9cef31894343e5d2c9b" + version = "kubernetes-1.11.3" [[projects]] + digest = "1:36e48db24a383a02683a57b7a48d5c3e8937b1f5a71ccfb7e52ee5d77d796147" name = "k8s.io/apimachinery" packages = [ "pkg/api/errors", @@ -406,21 +538,26 @@ "pkg/util/framer", "pkg/util/intstr", "pkg/util/json", + "pkg/util/mergepatch", "pkg/util/net", "pkg/util/runtime", "pkg/util/sets", + "pkg/util/strategicpatch", "pkg/util/validation", "pkg/util/validation/field", "pkg/util/wait", "pkg/util/yaml", "pkg/version", "pkg/watch", - "third_party/forked/golang/reflect" + "third_party/forked/golang/json", + "third_party/forked/golang/reflect", ] - revision = "17529ec7eadb8de8e7dc835201455f53571f655a" - version = "kubernetes-1.10.4" + pruneopts = "" + revision = "def12e63c512da17043b4f0293f52d1006603d9f" + version = "kubernetes-1.11.3" [[projects]] + digest = "1:d04779a8de7d5465e0463bd986506348de5e89677c74777f695d3145a7a8d15e" name = "k8s.io/client-go" packages = [ "discovery", @@ -451,12 +588,14 @@ "kubernetes/typed/rbac/v1alpha1", "kubernetes/typed/rbac/v1beta1", "kubernetes/typed/scheduling/v1alpha1", + "kubernetes/typed/scheduling/v1beta1", "kubernetes/typed/settings/v1alpha1", "kubernetes/typed/storage/v1", "kubernetes/typed/storage/v1alpha1", "kubernetes/typed/storage/v1beta1", "pkg/apis/clientauthentication", "pkg/apis/clientauthentication/v1alpha1", + "pkg/apis/clientauthentication/v1beta1", "pkg/version", "plugin/pkg/client/auth/exec", "rest", @@ -470,20 +609,23 @@ "tools/clientcmd/api/v1", "tools/metrics", "tools/pager", + "tools/record", "tools/reference", "transport", "util/buffer", "util/cert", + "util/connrotation", "util/flowcontrol", "util/homedir", "util/integer", - "util/retry" + "util/retry", ] - revision = "23781f4d6632d88e869066eaebb743857aa1ef9b" - version = "v7.0.0" + pruneopts = "" + revision = "7d04d0e2a0a1a4d4a1cd6baa432a2301492e4e65" + version = "v8.0.0" [[projects]] - branch = "release-1.10" + digest = "1:3b981f69134219063c9fe062302d777a99c784d8ef3ee0f40fe191717d2f4541" name = "k8s.io/code-generator" packages = [ "cmd/client-gen", @@ -494,31 +636,87 @@ "cmd/client-gen/generators/util", "cmd/client-gen/path", "cmd/client-gen/types", - "pkg/util" + "pkg/util", ] - revision = "9de8e796a74d16d2a285165727d04c185ebca6dc" + pruneopts = "" + revision = "8c97d6ab64da020f8b151e9d3ed8af3172f5c390" + version = "kubernetes-1.11.3" [[projects]] branch = "master" + digest = "1:d1e2c209e5b2a0fee08e687a43e63f81767817b7dd8a42af7667e5d58bf6844a" name = "k8s.io/gengo" packages = [ "args", "generator", "namer", "parser", - "types" + "types", ] + pruneopts = "" revision = "f659ec9d5207b3bf034eb9b7e22720d360d28712" [[projects]] + branch = "master" + digest = "1:7b06ff480fd71dead51f0f243b573c448c372ec086b790ec7ed4f8a78f2c1cbf" + name = "k8s.io/kube-openapi" + packages = ["pkg/util/proto"] + pruneopts = "" + revision = "9dfdf9be683f61f82cda12362c44c784e0778b56" + +[[projects]] + digest = "1:3d1deed8c48ccedf522fafc1b12b53f51ab9d343d989aacd8007fa9e4ae29cae" name = "k8s.io/kubernetes" packages = ["pkg/util/version"] - revision = "5ca598b4ba5abb89bb773071ce452e33fb66339d" - version = "v1.10.4" + pruneopts = "" + revision = "a4529464e4629c21224b3d52edfe0ea91b072862" + version = "v1.11.3" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "661d884c9d561bdb749d8bf3cbf47569c1d2b29f49e4d664184a3334ddc9a855" + input-imports = [ + "github.com/aws/aws-sdk-go/aws", + "github.com/aws/aws-sdk-go/aws/ec2metadata", + "github.com/aws/aws-sdk-go/aws/session", + "github.com/aws/aws-sdk-go/service/cloudformation", + "github.com/aws/aws-sdk-go/service/s3", + "github.com/aws/aws-sdk-go/service/sns", + "github.com/aws/aws-sdk-go/service/sqs", + "github.com/christopherhein/go-version", + "github.com/christopherhein/operator-kit", + "github.com/golang/glog", + "github.com/iancoleman/strcase", + "github.com/mitchellh/go-homedir", + "github.com/sirupsen/logrus", + "github.com/spf13/cobra", + "github.com/spf13/viper", + "gopkg.in/yaml.v2", + "k8s.io/api/core/v1", + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1", + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset", + "k8s.io/apimachinery/pkg/api/errors", + "k8s.io/apimachinery/pkg/apis/meta/v1", + "k8s.io/apimachinery/pkg/labels", + "k8s.io/apimachinery/pkg/runtime", + "k8s.io/apimachinery/pkg/runtime/schema", + "k8s.io/apimachinery/pkg/runtime/serializer", + "k8s.io/apimachinery/pkg/types", + "k8s.io/apimachinery/pkg/watch", + "k8s.io/client-go/discovery", + "k8s.io/client-go/discovery/fake", + "k8s.io/client-go/kubernetes", + "k8s.io/client-go/kubernetes/scheme", + "k8s.io/client-go/kubernetes/typed/core/v1", + "k8s.io/client-go/rest", + "k8s.io/client-go/testing", + "k8s.io/client-go/tools/cache", + "k8s.io/client-go/tools/clientcmd", + "k8s.io/client-go/tools/record", + "k8s.io/client-go/util/flowcontrol", + "k8s.io/code-generator/cmd/client-gen", + "k8s.io/gengo/namer", + "k8s.io/gengo/types", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 9c8603a56..c22685a38 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -36,20 +36,24 @@ required = ["k8s.io/code-generator/cmd/client-gen"] [[constraint]] name = "k8s.io/api" - version = "kubernetes-1.10.4" + version = "kubernetes-1.11.3" [[constraint]] name = "k8s.io/apiextensions-apiserver" - version = "kubernetes-1.10.4" + version = "kubernetes-1.11.3" [[constraint]] name = "k8s.io/apimachinery" - version = "kubernetes-1.10.4" + version = "kubernetes-1.11.3" [[constraint]] name = "k8s.io/client-go" - version = "7.0.0" + version = "8.0.0" [[constraint]] name = "k8s.io/code-generator" - version = "kubernetes-1.10.4" + version = "kubernetes-1.11.3" + +[[override]] + name = "github.com/json-iterator/go" + revision = "f2b4162afba35581b6d4a50d3b8f34e33c144682" \ No newline at end of file diff --git a/Makefile b/Makefile index 80f01a40b..e18287e9f 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ aws-codegen: .PHONY: k8s-codegen k8s-codegen: - ./codegen.sh + ./hack/update-codegen.sh .PHONY: codegen codegen: aws-codegen k8s-codegen diff --git a/cmd/aws-service-operator/main.go b/cmd/aws-service-operator/main.go index d80a77ed4..065b0d3b6 100644 --- a/cmd/aws-service-operator/main.go +++ b/cmd/aws-service-operator/main.go @@ -20,7 +20,8 @@ var ( rootCmd = &cobra.Command{ Use: "aws-operator", Short: "AWS Operator manages your AWS Infrastructure using CRDs and Operators", - Long: `TODO WRITE THIS`, + Long: `AWS Operator manages your AWS Infrastructure using CRDs and Operators. +With a single manifest file you can now model both the application and the resource necessary to run it.`, Run: func(c *cobra.Command, _ []string) { c.Help() }, diff --git a/code-generation/pkg/codegen/assets/controller.go.templ b/code-generation/pkg/codegen/assets/controller.go.templ index 6c991c238..42a9f8e50 100644 --- a/code-generation/pkg/codegen/assets/controller.go.templ +++ b/code-generation/pkg/codegen/assets/controller.go.templ @@ -14,7 +14,10 @@ import ( "github.com/awslabs/aws-service-operator/pkg/config" {{- if .Spec.Queue}} - "github.com/awslabs/aws-service-operator/pkg/queue" + "github.com/awslabs/aws-service-operator/pkg/queue" + corev1 "k8s.io/api/core/v1" + "github.com/iancoleman/strcase" + "strings" {{- end}} opkit "github.com/christopherhein/operator-kit" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" @@ -50,7 +53,7 @@ type Controller struct { config *config.Config context *opkit.Context awsclientset awsclient.ServiceoperatorV1alpha1Interface - topicARN string + topicARN string } // NewController create controller for watching object store custom resources created @@ -106,27 +109,35 @@ func QueueUpdater(config *config.Config, msg *queue.MessageBody) error { } if name != "" && namespace != "" { + annotations := map[string]string{ + "StackID": msg.ParsedMessage["StackId"], + "StackName": msg.ParsedMessage["StackName"], + "ResourceType": msg.ParsedMessage["ResourceType"], + } if msg.ParsedMessage["ResourceStatus"] == "ROLLBACK_COMPLETE" { - err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) + obj, err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } else if msg.ParsedMessage["ResourceStatus"] == "DELETE_COMPLETE" { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } - + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) err = incrementRollbackCount(config, name, namespace) if err != nil { return err } } else { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeNormal, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } + } return nil @@ -147,7 +158,7 @@ func (c *Controller) onAdd(obj interface{}) { c.config.Logger.Infof("added {{.Spec.Resource.Name}} '%s' with stackID '%s'", s.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -176,7 +187,7 @@ func (c *Controller) onUpdate(oldObj, newObj interface{}) { c.config.Logger.Infof("updated {{.Spec.Resource.Name}} '%s' with params '%s'", no.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -225,13 +236,13 @@ func incrementRollbackCount(config *config.Config, name string, namespace string return nil } -func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) error { +func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) (*awsV1alpha1.{{.Spec.Kind}}, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.{{.Spec.PluralName}}(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting {{.Spec.Resource.Plural}}") - return err + return nil, err } resourceCopy := resource.DeepCopy() @@ -259,7 +270,7 @@ func updateStatus(config *config.Config, name string, namespace string, stackID _, err = clientSet.{{.Spec.PluralName}}(namespace).Update(resourceCopy) if err != nil { logger.WithError(err).Error("error updating resource") - return err + return nil, err } if helpers.IsStackComplete(status, false) { @@ -268,26 +279,26 @@ func updateStatus(config *config.Config, name string, namespace string, stackID logger.WithError(err).Info("error syncing resources") } } - return nil + return resourceCopy, nil } -func deleteStack(config *config.Config, name string, namespace string, stackID string) error { +func deleteStack(config *config.Config, name string, namespace string, stackID string) (*awsV1alpha1.{{.Spec.Kind}}, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.{{.Spec.PluralName}}(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting {{.Spec.Resource.Plural}}") - return err + return nil, err } cft := New(config, resource, "") err = cft.DeleteStack() if err != nil { - return err + return nil, err } err = cft.WaitUntilStackDeleted() - return err + return resource, err } func syncAdditionalResources(config *config.Config, s *awsV1alpha1.{{.Spec.Kind}}) (err error) { diff --git a/code-generation/pkg/codegen/templates.go b/code-generation/pkg/codegen/templates.go index c2f9ba1a4..f38510ad1 100644 --- a/code-generation/pkg/codegen/templates.go +++ b/code-generation/pkg/codegen/templates.go @@ -86,12 +86,12 @@ func cftGoTempl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cft.go.templ", size: 9390, mode: os.FileMode(420), modTime: time.Unix(1538385198, 0)} + info := bindataFileInfo{name: "cft.go.templ", size: 9390, mode: os.FileMode(436), modTime: time.Unix(1538638943, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _controllerGoTempl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x6d\x73\xdb\x36\xf2\x7f\x4d\x7e\x0a\x94\xff\x36\x25\x53\x99\xfc\xe7\xdd\x8d\xe7\x7c\x1d\x57\x56\x53\x4f\x53\xdb\x67\x3b\xcd\x8b\x4c\xc6\x85\xc9\x95\x84\x98\x22\x58\x00\x92\xe2\xaa\xfa\xee\x37\x8b\x05\x28\x52\x96\x14\xa9\xcd\x65\xe6\x3a\xcd\x64\xc6\x24\xb0\x58\xec\xc3\x6f\x1f\x00\x2a\xcb\xd8\xbf\xe8\x1f\x3b\xbb\x64\x17\x97\xb7\x6c\x70\x76\x7e\xcb\x6e\x7f\x38\xbf\x61\xdf\x9f\xbf\x1a\xb0\x7f\x36\xff\xc2\x2c\x63\xb7\x63\xa1\xd9\x50\x94\xc0\x84\x66\x7c\x6a\xe4\x08\x2a\x50\xdc\x40\xc1\x66\x82\xb3\x5f\xf8\x5c\x1f\xc9\x1a\x47\xa4\x62\x7e\xee\x17\x5c\x79\x3e\x64\x8f\x72\xfa\x75\xc1\x4a\xf1\x00\xcc\x8c\x81\xe5\x63\x5e\x8d\x80\xf1\xea\xd1\x8c\x45\x35\x62\xfc\x5e\x4e\x0d\x33\xcd\x0e\x13\xfe\x00\x0c\x0a\x61\x34\x33\xd2\xae\x48\x0d\x4c\xea\x12\xb9\x91\x08\x95\x1d\xad\x1f\x46\x59\x2e\x0b\x18\x41\x95\x71\xad\xc1\x68\x56\x08\x05\xb9\x91\xea\x31\x0d\xc3\x9a\xe7\x0f\x7c\x04\x6c\xb1\x48\x6f\x6a\xc8\xd3\x6b\xd0\x72\xaa\x72\x48\x2f\xf8\x04\x96\xcb\x30\x14\x93\x5a\x2a\xc3\xe2\x30\x58\x2c\x8e\x98\x18\x32\xa2\x3b\xd7\xfd\xa9\x36\x72\x22\x7e\x83\x62\xb9\x0c\x03\x36\x01\xc3\x67\x2f\x58\xf4\xf0\x0f\x9d\x0a\x99\xf1\x5a\x4c\x78\x3e\x16\x15\xa8\xc7\x0c\x65\xe0\xb5\xd0\x19\x12\x65\xb3\x17\x51\x18\x44\x23\x61\xc6\xd3\xfb\x34\x97\x93\x8c\xcf\x75\xc9\xef\x35\xfe\x3d\xd2\xa0\x66\x22\x87\xc6\x4c\x76\xed\x18\xca\x1a\x94\x8e\x48\x06\xa8\xec\x8e\x91\x82\x61\x09\xb9\x89\xc2\x03\xb9\xe5\xb2\x1a\x8a\x51\xb4\xa6\xd0\xbf\xa7\x30\x45\x85\x19\x3b\x88\xd9\xaf\xb8\xac\x2b\x98\xac\x1f\x84\xe9\x70\xc9\xc7\x4a\x68\x23\xeb\x31\xa8\x31\x88\x2a\xf3\x1c\x8e\x1e\x84\x89\xc2\x80\xd7\x02\x3e\x18\xa8\xb4\x90\x95\x9e\xbd\xb8\x07\xc3\x3b\x86\x5c\x4d\x1e\xa1\x15\x41\xcd\x40\xad\x6c\xda\x21\xc8\xdc\x72\xb4\xb0\x63\x90\x97\x02\x2a\x73\x34\x92\x99\x91\xb2\xd4\x59\xce\xf3\x31\xa0\xd1\xf8\x5c\xf3\x5a\x1c\xa6\xae\xdd\x71\x7d\x26\xe5\x73\xf4\x0d\x9f\xeb\x9f\x5f\xf0\xb2\x1e\xa3\xf4\x9f\x84\x69\x36\x73\xfc\x88\x3b\x69\x72\x18\x6f\x5a\xe3\xfe\x68\x30\xd9\x0c\x14\x5a\x0a\x8a\xcc\x3c\xd6\x50\x7c\x74\xdf\x0e\x48\x3c\xe6\xb9\x41\x63\xa7\x57\x14\x3c\x84\x1a\x1f\x41\xdb\x68\x3a\x20\x49\x42\x8c\x53\x1f\x6c\x98\x2e\x30\x56\xe5\xfd\x7b\xc8\x0d\xd3\x46\x2a\x60\x05\x0c\x45\x25\x90\x49\x38\xe3\x6a\x45\x7b\xc2\x2c\xc0\xdc\x3e\x7e\x78\x11\x06\x18\xb1\xc7\x8c\xfe\x45\x5b\xe2\x39\xea\x85\xc1\x55\x39\x55\xbc\x3c\xde\x42\x47\xb3\x44\xf9\x52\xc9\x69\xed\x58\x12\x5a\x52\x3b\x84\xbc\x7a\x61\xf0\x33\x99\xf2\xb8\x35\xed\x86\x7a\x61\x70\x93\xcb\xda\x8b\xb3\x09\xe0\x56\x20\x5d\xf3\x1c\x2c\x65\xd1\x0b\x83\x1f\x45\x55\x78\x05\x5c\x70\xa7\xb7\x8f\x35\x5c\x0e\xe3\x16\xb6\x52\x2f\x32\x92\x2f\x97\x8b\x65\x62\x59\xc5\x09\x6e\x3a\x96\xca\x58\xc6\xc7\xec\xed\x3b\x6d\x94\xa8\x46\x8b\xb0\xe3\xc2\x46\x51\x4b\x5b\x21\x2d\x3b\xc2\xb0\x45\x2a\x65\x73\xee\x76\x42\xa4\x0b\xd0\x66\x2b\x6b\xae\x7c\xda\x4a\x01\xcb\x5e\xb8\xb4\x1e\xee\xcb\xca\x28\x59\x96\xa0\x98\x82\x5a\x81\x46\x14\x32\xce\xf2\xd5\xb8\x73\xfa\x50\xaa\xae\xff\x73\xeb\x5f\xa6\x9c\x18\x3a\x44\xbc\xb6\x19\x6a\xa3\xa6\xb9\x61\x8b\x30\xa0\x8c\xe6\x2c\xf7\x9c\xde\xd2\xbe\xfd\x63\x27\x0d\x7c\x30\x6e\xd2\x61\x87\xc6\x5a\x51\xa5\xc1\xb0\xe6\x25\xbd\xa1\xa0\xf0\x31\xe1\x4d\x7f\x5e\x19\x50\x43\x9e\x43\xc8\x98\x91\xb5\xc8\x4f\xaf\x2f\x2c\x5b\xb2\xb4\xd3\xf9\x02\xe6\x2d\x29\x73\x05\xdc\x40\x5b\x61\xd4\x74\xce\x4d\x6e\xcb\xda\x4e\x95\xdd\xe2\x22\x1c\x4e\xab\xbc\xcb\x37\x76\x3a\x77\xb5\xed\x31\xaf\x6d\x57\xd1\x1e\xfb\x83\x8a\x26\xec\x79\x4b\x97\x45\x18\x28\x30\x53\x55\xb1\x67\xab\xd1\x45\x18\x38\x07\x78\xec\xd2\x5b\x8f\xc6\x71\xfb\xe3\x66\xdc\x0a\x13\x06\x1d\xbb\x1f\x77\x84\xeb\x85\xc1\xd2\x19\xf2\xc6\x70\x65\xde\xa0\xa5\xc8\x5e\xa0\xad\xed\x44\xa5\x0d\xaf\xd0\x3c\x72\xc8\x2e\xc9\x7e\x37\x9b\xed\xc7\xab\x82\xf1\xdc\x68\x26\x6d\x33\x30\x21\x43\xc6\x79\x5b\xab\xa4\xb5\x4f\x5c\xf9\xa0\x74\x2e\xed\xa1\x67\xea\xfe\xd8\xb6\x23\x0e\x71\x8b\x65\xc2\x40\x29\xe9\xec\x41\x7b\xfd\xc0\xab\xa2\x04\xa5\xd9\xf1\x09\xb3\x15\xa6\x89\x9f\xc1\x0c\x2a\xe3\xa6\xbf\x9f\x56\xb9\x46\x83\x9d\x16\x05\x3e\x5b\xc3\xe4\xa9\xac\x4e\x0b\x4c\x00\xc1\xeb\xba\xe0\x06\x68\x06\x87\xe9\x1d\x67\xce\xa0\x84\xf6\x0c\xbd\x5b\x63\x6d\xae\xe3\x81\xad\xcc\xb9\x51\x25\x8a\x64\x5f\xd2\x0b\x98\xc7\x79\x9a\x7b\xa8\xa4\xde\x21\x2c\x4f\x3b\x2e\x60\x2f\x92\x30\xc8\x53\x0f\xf1\x1e\xbb\xa3\xff\xcc\x31\x42\xae\xe9\x35\x8c\x84\x36\xa0\xe2\xed\xb9\x96\x3d\xdb\x99\xb7\xc2\x60\x24\x5b\x0c\x5b\x6e\x20\x71\x5b\x46\x8b\xad\x5a\x64\x0e\x95\x78\xaf\x24\xed\xf4\x63\x7d\x61\xfa\x54\x23\xd1\x0b\x1d\x9d\xd2\xeb\xc1\xcd\x2d\x4d\xc6\x49\x18\x10\x9e\x14\xd2\x51\xa0\x5c\xc0\xfc\x0d\x8d\xc5\x5e\x8d\x1e\x6b\xd0\xd0\x63\xeb\x7e\xb6\x23\x6e\x37\x52\xc4\xb1\x4c\x49\x83\x9d\x9a\xaf\xe4\x6f\x02\xaa\x12\x25\xa2\x7e\xa3\x2b\xb3\x8c\xb5\xd5\x67\x73\x51\x96\xcc\x70\xd7\x28\x4f\x40\x6b\x3e\xc2\xd8\x50\x72\x62\x47\xac\xf5\x2c\xf6\x6b\x25\x73\xd0\xba\x85\xfd\x36\xa3\x6d\x39\x64\xa2\x47\xec\x39\xb9\xe0\x27\x62\xfe\x9d\x2c\x1e\x5b\xa0\x2f\xe5\x68\x44\xc6\x73\x2b\x5f\xd9\x81\x30\xc0\x42\x8d\x46\x6b\x99\xce\xe7\xc6\x40\x0c\x91\x71\x6a\xf7\xe6\xf7\x25\x20\xa3\x00\xc9\xd8\x89\x9d\xf0\x66\x47\xf0\xb8\x19\x62\x40\xd3\x4d\xb9\x0c\x83\x25\x83\x52\xd3\x7a\xf2\xef\x0d\x62\xf6\x0e\xe5\x59\x65\xb6\x0b\x98\x7f\x2f\x15\xa9\xe4\x14\x25\x0c\xd8\xc7\x24\x0c\x9a\xd0\xd5\x3d\xd4\xcc\x6a\xe3\xb9\x35\x1e\xa3\x6e\x80\xf0\x1c\x47\x51\x92\xbe\x12\xda\xc4\xd4\xeb\xdb\xe7\xcb\xda\xb6\x39\x16\xcd\xa8\x22\x72\xfa\xe2\x04\xdd\x69\xe5\x73\xa6\x4a\xdf\x08\x33\x1e\xa0\xf9\x62\x50\x2a\x49\xe9\x31\x22\x83\x8e\xc0\x18\x2c\x05\xdb\x5b\x11\xe4\xed\x81\x02\x4a\x85\x01\x46\x7d\x80\xb9\xf0\x6e\x85\x4c\x54\x80\xea\x77\xa3\x58\x7a\x6e\x60\xa2\x49\x10\x31\x6c\xc6\x31\xd2\xcc\x54\xe3\x9f\xfc\xe1\xfc\x8c\x9d\x90\x85\xaf\xb8\xd2\x50\x38\x8f\xbf\x8d\x68\xb6\x88\xde\xd1\x7a\xef\x2a\xd5\x0e\xf2\x66\xc2\x7b\xaa\x33\xeb\xdc\x45\xd2\x62\x57\x10\x5a\x14\x58\x46\x5f\x9c\xb0\x28\x62\xcf\x9e\xb5\x80\x42\x43\x0b\xb2\xe3\x06\x81\xbc\x5d\x48\xfa\xe8\x1d\xca\x1d\x5d\x5f\xbe\x7a\xf5\xdd\x69\xff\xc7\xbb\xfe\xe5\x4f\x57\xaf\x06\xb7\x03\xe2\x10\x38\x8f\x16\x36\x4d\x5a\x55\x62\x9f\xf7\xd6\x00\xda\xdb\xa9\x7c\xe2\x6c\xb7\xee\xd7\xae\x3b\x48\x43\x82\xe5\x01\xc2\x9f\x0d\x50\xe2\x2d\xa2\x4f\x6d\x90\x12\xfd\x1f\x93\x7d\xe3\xec\xba\x20\x7b\x10\x5d\x03\xd7\xb2\x3a\xc0\x16\x5e\x8b\x13\x26\xaa\x5c\xc1\x04\x2a\x73\x2d\xcb\xf2\x9e\xe7\x0f\x7d\x39\xad\xcc\x36\x75\x0e\x37\xf6\x5f\xc4\x60\x4d\x78\x74\xaa\x41\xab\xb6\x6d\xec\x5b\x6c\xdb\x10\xcb\xfb\xf7\x4c\xf8\x7e\x0d\x7b\x93\x45\x18\xd8\x36\x44\xde\xbf\x4f\xe3\xe7\xdb\xeb\x50\x92\x9e\x01\xd4\x7d\x59\x3f\xc6\x58\x88\x5c\xe9\xa9\xa4\xd9\x7c\xd8\x3b\x2d\x0a\x7b\xd0\x13\x43\xa6\x7d\x06\xe9\xaa\x6d\x31\x1d\xb1\xdf\x7f\xdf\x49\xb0\x01\xf4\xb6\x0b\x1a\xda\xaa\xdd\x6d\x51\x34\xb6\x26\xbe\x0d\x49\x2c\x9d\x9c\x9a\x7a\x6a\x56\x29\x7b\x68\xd2\xbe\xed\x92\x29\xc8\x89\x68\xdd\xe6\xae\xff\x4c\x3b\xe5\x6a\x63\x52\x1e\xfa\xac\x6c\x5b\xef\x8d\x69\x99\xaa\x01\xfb\xfa\x2b\xfd\x75\xd4\x63\xda\xbe\x27\xa1\x3f\xb6\xa1\xff\xec\xcb\x32\xdc\xb4\xe7\x79\x35\x94\xc3\x38\xe2\x45\x01\xc5\x4e\xd6\x6c\x2e\xcc\x98\x69\x97\xa2\x3b\x9b\xf5\x5c\x4d\x8d\x9f\x93\x31\x5c\x22\x2f\x92\x64\xd7\x96\x33\x01\x73\xc6\x0d\x1b\x1b\x53\xeb\xe3\x2c\xcb\x65\xa5\x65\x09\xd8\x25\xa5\x7c\xc2\x7f\x93\x15\xdd\xd5\x94\x72\x5a\x0c\xa5\x9a\x58\xb7\x67\x63\x39\x81\x6f\xff\x2f\xb3\x72\x64\x05\x18\x2e\xca\x6f\x49\xa8\xe2\xe4\x2b\x1d\xed\x10\x25\xf4\x39\xa0\x1b\x97\x2b\xdf\x7a\x5d\x56\xb5\x62\x2b\xb7\x1e\x8b\xfa\xd7\x83\xd3\xdb\xc1\xdd\xf9\xc5\xdd\xd5\xf5\xe5\xcb\xeb\xc1\xcd\x4d\xd4\x63\x51\xb4\xa5\xec\xee\xe3\x6a\xef\x69\x2b\x1f\x7a\x5a\x53\x84\x27\x36\x1c\xd1\x81\xd4\x5d\x96\x1a\xe8\x7c\xbc\x3d\x2c\xda\x6a\x75\x9a\xd2\xed\xa1\x4b\x3d\x58\x2c\xcb\xe2\xf2\xfe\x7d\x8f\x55\x30\xbf\xdc\x10\xc8\x52\xda\x48\xb6\x44\xfb\x07\x73\x50\xd9\x65\xc4\xf3\x90\x1c\x60\xe3\xff\xb0\xd8\x45\x5b\x53\x22\xaa\x64\x62\xad\xf6\xf1\x54\x42\xba\xfb\x6c\xe2\x6e\x37\xd3\x73\x6d\xdd\xdd\x97\x93\x1a\x8b\x76\x2c\xb7\x48\xd2\x63\x43\x5e\x6a\x48\xb0\x7b\xf8\xc2\xdf\x93\xa0\x1a\x83\x5f\xa7\xbc\xc4\x65\x5e\xc7\xdb\xc7\x1a\x96\xcb\x1e\xea\xd4\x1d\x4a\x76\x25\x1d\x29\xf7\xca\x3a\xaf\x3d\xac\xf3\x07\xa7\xfa\x27\xc9\x3b\x0d\x1a\x3f\x9e\x1c\x2a\x98\xb3\x9a\x2b\x3e\xd1\xec\xab\x6f\x66\xb6\xe1\x97\x65\x81\xcf\x91\xd5\x99\xe2\xab\x92\xa8\xd2\xa1\x09\x8a\x82\x76\x9f\x14\xe5\x24\x70\x19\xaa\xd9\xf6\xaf\x90\xa2\xa4\x57\xc6\x3d\x7c\x34\x49\xbd\xbe\x3a\xfb\xec\x49\x8a\xb1\x3d\xb2\x94\x8f\xb8\x35\x98\x23\x6e\xf7\xca\x56\x74\xdd\xf0\xd9\x7a\x0d\xda\x0e\xf5\xd9\xa7\x2d\x08\x5a\x51\x79\xd6\x6a\xf8\x93\x70\x83\xd5\x0f\x0a\x46\x7b\x7c\x38\xa0\x09\xf0\x9d\x1d\x35\x73\x5b\x50\x4e\x67\x92\xdd\xa1\xd5\xe6\xb9\x87\x7b\xbd\xbd\x76\xd5\xa1\x70\xd7\xf7\x2b\xeb\xf6\x9d\xcd\xfa\x93\x5b\x02\x7b\x8c\xf3\xb7\x64\xeb\xc7\xfd\x7d\x2e\x0b\xfe\xc4\xd9\x5d\x35\x57\x34\xfb\x9d\xdc\x57\x27\x8c\xf4\x25\x98\x98\x0e\x05\xee\x14\xff\x12\x3a\x87\xf8\xa7\x88\xf9\x64\x47\xf8\x76\xd7\xef\xee\xab\x2c\x15\x86\x85\x3d\xbd\xfb\x55\xed\x52\xde\x26\x72\xcc\xdb\xde\x69\x9d\xb9\xb7\x50\x7c\xf3\x22\x0c\x83\x3b\xb2\xd4\x21\x86\x72\x0d\x4a\x9b\xfb\x1f\x35\x4f\x93\xbc\x3c\xb3\x0d\xe6\x58\xbb\x08\xb3\x80\xdc\x70\xa2\x3b\x0c\x86\xbd\xa6\x81\x6e\xbd\x63\x33\xe3\x5f\x95\x3d\xa9\xfd\x0d\xda\xff\x2a\x68\x37\xb7\x93\xce\x15\xfb\x10\xd3\x79\xda\x42\x1d\x1f\x36\x2f\x69\x6e\xb3\xbc\xcf\xa9\x9f\xdd\xd6\x5d\xea\x6e\x2f\x69\x4b\x43\xab\xd6\x38\x74\xb5\x37\xf2\x95\x9c\xca\xbe\xee\x34\x83\xe8\x0f\x1a\x8e\xff\xfc\x45\xa0\xdb\xc0\xd5\xf8\x30\x68\x7d\x9a\xfb\xb2\x56\xb2\xc6\x4d\xc9\x65\x97\xae\x03\xc9\xc7\x30\xe1\xe9\x95\x92\x35\x28\x23\xfc\x87\x3a\x97\xf0\xed\x9a\xf4\x16\x26\x75\xc9\x8d\xff\xbd\x42\xb0\x58\xd0\xf8\x8f\xf0\x88\x2d\xb2\x05\xb3\xb7\xd5\x8a\x36\x8e\x3c\x9d\x1b\xa3\x7b\x7d\x4f\x78\xc6\x0d\x5f\x5c\xde\xbf\x3f\x5e\x33\x54\xdf\x7d\x0f\x22\x33\x2e\xdb\xb7\xad\xd6\x65\x4e\x6e\xcf\xfb\xc6\x7e\x57\xb1\x92\xb0\x13\xd6\x91\xcc\xa9\xe1\xeb\xdf\x01\x6c\x9c\x15\xdf\x3e\xd1\xc0\x12\x44\xef\x3c\xe7\xaa\x58\xed\xe2\xbe\x5e\xfe\x4f\x24\xcc\x43\xd1\x4d\xea\xe8\xc7\x2a\x3f\x2d\x0a\xfb\x5d\x9d\x97\x3e\xcc\xf4\x46\xc0\x1f\x84\x64\x6c\x6e\xbc\xf8\xb8\x49\x5b\x7a\x0f\xe5\x2d\x69\xfe\xe9\x25\xed\x9f\xcb\xf2\x7f\xe7\xf1\x3d\xf2\xf8\x8e\x64\xe7\x12\x9d\xc3\xff\x3e\x4d\xf5\x3a\xf3\xd5\xd2\x37\x5c\x98\xd7\x95\x11\xa5\x5d\x4d\x8c\x0a\x2a\x11\xcd\x12\x8f\x83\xdd\xd8\x7c\x82\x09\xcd\x76\x1d\x38\x18\x5a\x8a\x80\x60\xf1\xff\x19\x1d\xde\xba\xd1\x22\x97\xfb\xab\xae\x7d\x9d\xfe\xa4\x33\x6a\x7e\xfa\xb2\xa9\xda\x62\x9f\xbf\x6a\xec\x37\x18\xd0\x7f\xe5\xc7\xb2\xa0\xfd\xe3\xf1\xc9\xea\x17\x22\xcb\xc5\xc2\xa5\xbe\x56\xa5\x69\x7f\x57\xda\x8b\x75\x73\xac\x83\x5f\x57\xab\xed\x85\x0b\x8b\x06\x1f\x0c\xa8\x8a\x2c\x14\x11\xe9\x97\x6a\xed\xdc\xd3\x2a\x40\x74\xa3\xdb\x5e\xe4\xf6\x89\x5b\x47\xc0\x8d\x17\x88\x51\x9b\x71\x9b\x81\xad\x5b\x8b\x45\x2c\xaa\x02\x3e\xb4\xe4\xbb\x92\xca\x68\xf6\xff\x89\x7d\x58\xa2\x3f\x1a\x13\x9d\x30\x5e\xd7\x50\x15\xb1\x1f\x41\x06\xeb\x62\x77\x8e\x59\xdd\xc7\x7d\x7d\xd2\x70\xdc\x49\x77\xc2\xbc\x18\xde\x5b\x1f\x77\x3c\x41\xf8\x27\x5e\xe3\x36\x64\xba\x09\xbe\x7c\x22\xe7\x77\xd8\x6f\xf2\x29\xf6\x07\xc8\x62\xc2\xeb\xb7\xb4\x5d\xf3\xa3\xa4\x4e\x57\x23\x0c\x4c\x90\x6e\xb5\xde\xae\xf4\x3f\x37\xb2\xf3\xd4\x0f\x44\xc7\xac\x19\xf8\x99\x97\x53\xf7\x2b\xa4\x6e\xf9\xde\x0b\x5d\x8d\xf0\x1f\xc5\xd4\x66\xbd\x12\xff\xbb\x23\x6b\xd1\x06\x2b\xab\xb1\x7d\xd0\xb2\xbf\xf7\x76\x82\xa4\x45\xe9\x2b\x1d\x4a\xd0\x00\x65\xff\x7e\xa6\x93\xbb\xd6\x3a\x9a\x3d\x72\x95\xbf\x60\x7c\xf2\x05\xeb\x3f\x01\x00\x00\xff\xff\x0c\x47\x71\xfc\x4a\x2c\x00\x00") +var _controllerGoTempl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x6d\x73\xdb\x36\xf2\x7f\x4d\x7e\x0a\x94\xff\x36\x25\x53\x85\xfa\xe7\xdd\x8d\xe7\x7c\x1d\x57\x76\x53\x4f\x5d\xdb\x67\x3b\xcd\x8b\x4c\xc6\x85\xc9\x95\xc4\x98\x02\x58\x00\xb2\xe2\xaa\xfa\xee\x37\x8b\x05\x28\x50\x96\x14\xa9\xc9\xf4\x6e\xee\x9a\xc9\x8c\x49\x60\xb1\xd8\x87\xdf\x3e\x00\x54\xbf\xcf\xfe\x41\xff\xd8\xf1\x05\x3b\xbf\xb8\x61\x27\xc7\xa7\x37\xec\xe6\x87\xd3\x6b\xf6\xfd\xe9\xd9\x09\xfb\x7b\xfb\x2f\xee\xf7\xd9\xcd\xb8\xd2\x6c\x58\xd5\xc0\x2a\xcd\xf8\xd4\xc8\x11\x08\x50\xdc\x40\xc9\x1e\x2a\xce\x7e\xe1\x33\xfd\x42\x36\x38\x22\x15\xf3\x73\xbf\xe0\xca\xd3\x21\x7b\x94\xd3\xaf\x4b\x56\x57\xf7\xc0\xcc\x18\x58\x31\xe6\x62\x04\x8c\x8b\x47\x33\xae\xc4\x88\xf1\x3b\x39\x35\xcc\xb4\x3b\x4c\xf8\x3d\x30\x28\x2b\xa3\x99\x91\x76\x45\x6e\x60\xd2\xd4\xc8\x8d\x44\x10\x76\xb4\xb9\x1f\xf5\x0b\x59\xc2\x08\x44\x9f\x6b\x0d\x46\xb3\xb2\x52\x50\x18\xa9\x1e\xf3\x38\x6e\x78\x71\xcf\x47\xc0\xe6\xf3\xfc\xba\x81\x22\xbf\x02\x2d\xa7\xaa\x80\xfc\x9c\x4f\x60\xb1\x88\xe3\x6a\xd2\x48\x65\x58\x1a\x47\xf3\xf9\x0b\x56\x0d\x19\xd1\x9d\xea\xc1\x54\x1b\x39\xa9\x7e\x83\x72\xb1\x88\x23\x36\x01\xc3\x1f\x5e\xb2\xe4\xfe\x6f\x3a\xaf\x64\x9f\x37\xd5\x84\x17\xe3\x4a\x80\x7a\xec\xa3\x0c\xbc\xa9\x74\x1f\x89\xfa\x0f\x2f\x93\x38\x4a\x46\x95\x19\x4f\xef\xf2\x42\x4e\xfa\x7c\xa6\x6b\x7e\xa7\xf1\xef\x0b\x0d\xea\xa1\x2a\xa0\x35\x93\x5d\x3b\x86\xba\x01\xa5\x13\x92\x01\x84\xdd\x31\x51\x30\xac\xa1\x30\x49\xbc\x27\xb7\x42\x8a\x61\x35\x4a\x56\x14\xfa\xe7\x14\xa6\xa8\x30\x63\x8c\xed\xc5\xee\x57\x5c\x98\xd8\x75\x85\x54\xd0\xb5\x41\x1f\x87\xac\xc6\xab\x7c\x2b\x2e\x0a\x59\xc3\x84\x8b\xbe\x36\xaa\xe0\xda\xf1\x48\xb4\x51\x95\x18\xad\x28\x2b\x9b\xfb\xca\x74\xd6\x17\x63\x55\x69\x23\x9b\x31\xa8\x31\x54\xa2\xef\x65\x7a\x71\x5f\x99\x24\x8e\x78\x53\xc1\x07\x03\x42\x57\x52\xe8\x87\x97\x77\x60\x78\x47\xb0\xe5\xe4\x0b\xf4\x0c\xa8\x07\x50\x4b\x3f\x75\x08\xfa\x6e\x39\x7a\xcd\x31\x28\xea\x0a\x84\x79\x31\x92\x7d\x23\x65\xad\xfb\x05\x2f\xc6\x80\x8e\xe0\x33\xcd\x9b\x6a\x3f\x03\xda\x1d\x57\x67\x72\x3e\x43\x13\xf0\x99\xfe\xf9\x25\xaf\x9b\x31\x4a\xff\x59\x98\xf6\x1f\x1c\x3f\xe2\x4e\x9a\xec\xc7\x9b\xd6\xb8\x3f\x1a\x4c\xff\x01\x14\x5a\x0a\xca\xbe\x79\x6c\xa0\xfc\xe8\xbe\x1d\xe0\xf9\x38\xe2\x06\x8d\x9d\x5f\x52\x40\x5a\x24\x26\x3e\x2a\x37\xd1\x74\x40\x92\xc5\x18\xfb\x3e\x80\x31\x05\x61\xfc\xcb\xbb\xf7\x50\x18\xa6\x8d\x54\xc0\x4a\x18\x56\xa2\x42\x26\xf1\x03\x57\x4b\xda\x43\x66\x01\xe6\xf6\xf1\xc3\xf3\x38\xc2\x2c\x70\xc0\xe8\x5f\xb2\x21\x47\x24\xbd\x38\xba\xac\xa7\x8a\xd7\x07\x1b\xe8\x68\x96\x28\x5f\x29\x39\x6d\x1c\x4b\x42\x4b\x6e\x87\x90\x57\x2f\x8e\x7e\x26\x53\x1e\x04\xd3\x6e\xa8\x17\x47\xd7\x85\x6c\xbc\x38\xeb\x00\x6e\x05\xd2\x0d\x2f\xc0\x52\x96\xbd\x38\xfa\xb1\x12\xa5\x57\xc0\x25\x8c\xfc\xe6\xb1\x81\x8b\x61\x1a\x60\x2b\xf7\x22\x23\xf9\x62\x31\x5f\x64\x96\x55\x9a\xe1\xa6\x63\xa9\x8c\x65\x7c\xc0\xde\xbe\xa3\xe8\x9c\xc7\x1d\x17\xb6\x8a\x5a\x5a\x81\xb4\xec\x05\x86\x2d\x52\x29\x9b\xc7\x37\x13\x22\x5d\x84\x36\x5b\x5a\x73\xe9\xd3\x20\x05\x2c\x7a\xf1\xc2\x7a\x78\x20\x85\x51\xb2\xae\x41\x31\x05\x8d\x02\x8d\x28\x64\x9c\x15\xcb\x71\xe7\xf4\xa1\x54\x5d\xff\x17\xd6\xbf\x4c\x39\x31\x74\x8c\x78\x0d\x19\x6a\xa3\xa6\x85\x61\xf3\x38\xa2\x2c\xe9\x2c\xf7\x9c\xde\xf2\x81\xfd\x63\x27\x0d\x7c\x30\x6e\xd2\x61\x87\xc6\x82\xa8\xd2\x60\x58\xfb\x92\x5f\x53\x50\xf8\x98\xf0\xa6\x3f\x15\x06\xd4\x90\x17\x10\x47\x46\x36\x55\x71\x74\x75\x6e\xb9\x92\xa1\x9d\xca\xe7\x30\x0b\x84\x2c\x14\x70\x03\xa1\xbe\xa8\xe8\x8c\x9b\xc2\x56\xca\xad\x1a\xbb\xc5\x65\x3c\x9c\x8a\xa2\xcb\x37\x75\x2a\x77\x95\xed\x31\xaf\x6c\x57\xcf\x1e\xfb\x83\x7a\x66\xec\x79\xa0\xcb\x3c\x8e\x14\x98\xa9\x12\xec\xd9\x72\x74\x1e\x47\xce\xfe\x1e\xba\xf4\xd6\xa3\x71\xdc\xfe\xa0\x1d\xb7\xc2\xc4\x51\xc7\xec\x07\x1d\xe1\x7a\x71\xb4\x70\x86\xbc\x36\x5c\x99\x37\x68\x29\xb2\x17\x68\x6b\xbb\x4a\x68\xc3\x05\x9a\x47\x0e\xd9\x05\xd9\xef\x7a\xbd\xfd\xb8\x28\x19\x2f\x8c\x66\xd2\xf6\x17\x13\x32\x64\x5a\x84\x5a\x65\xc1\x3e\xa9\xf0\x31\xe9\x5c\xda\x43\xcf\x34\x83\xb1\xed\x70\x1c\xe0\xe6\x8b\x8c\x81\x52\xd2\xd9\x83\xf6\xfa\x81\x8b\xb2\x06\xa5\xd9\xc1\x21\xb3\x05\xa6\x0d\x9f\x93\x07\x10\xc6\x4d\x7f\x3f\x15\x85\x46\x83\x1d\x95\x25\x3e\x5b\xc3\x14\xb9\x14\x47\x25\xc6\x7f\xf4\xba\x29\xb9\x01\x9a\xc1\x61\x7a\xc7\x99\x63\xa8\x21\x9c\xa1\x77\x6b\xac\xf5\xad\x41\x64\x4b\x7d\x61\x54\x8d\x22\xd9\x97\xfc\x1c\x66\x69\x91\x17\x1e\x2a\xb9\x77\x08\x2b\xf2\x8e\x0b\xd8\xcb\x2c\x8e\x8a\xdc\x43\xbc\xc7\x6e\xe9\x3f\x73\x8c\x90\x6b\x7e\x05\xa3\x4a\x1b\x50\xe9\xe6\x54\xcb\x9e\x6d\x4d\x5b\x71\x34\x92\x01\xc3\xc0\x0d\x24\x6e\x60\xb4\xd4\xaa\x45\xe6\x50\x99\xf7\x4a\x16\x66\x1f\xeb\x0b\x33\xa0\x12\x89\x5e\xe8\xe8\x94\x5f\x9d\x5c\xdf\xd0\x64\x9a\xc5\x11\xe1\x49\x21\x1d\x05\xca\x39\xcc\xde\xd0\x58\xea\xd5\xe8\xb1\x16\x0d\x3d\xb6\xea\x67\x3b\xe2\x76\x23\x45\x1c\xcb\x9c\x34\xd8\xaa\xf9\x52\xfe\x36\xa0\x44\x55\x23\xea\xd7\xba\xb2\xdf\x67\xa1\xfa\x6c\x56\xd5\x35\x33\xdc\xf5\xde\x13\xd0\x9a\x8f\x30\x36\x94\x9c\xd8\x11\x6b\x3d\x8b\xfd\x46\xc9\x02\xb4\x0e\xb0\x1f\x32\xda\x94\x43\x26\x7a\xc4\x9e\x93\x0b\x7e\x22\xe6\xdf\xc9\xf2\x31\x00\x7d\x2d\x47\x23\x32\x9e\x5b\x79\x66\x07\xe2\x08\xeb\x34\x1a\x2d\x30\x9d\xcf\x8d\x51\x35\x44\xc6\xb9\xdd\x9b\xdf\xd5\x80\x8c\x22\x24\x63\x87\x76\xc2\x9b\x1d\xc1\xe3\x66\x88\x01\x4d\xb7\xd5\x32\x8e\x16\x0c\x6a\x4d\xeb\xc9\xbf\xd7\x88\xd9\x5b\x94\x67\x99\xd9\xce\x61\xf6\xbd\x54\xa4\x92\x53\x94\x30\x60\x1f\xb3\x38\x6a\x43\x57\xf7\x50\x33\xab\x8d\xe7\xd6\x7a\x8c\x9a\x01\xc2\x73\x9a\x24\x59\x7e\x56\x69\x93\xd2\xf1\xc1\x3e\x5f\x34\xb6\xcb\xb1\x68\x46\x15\x91\xd3\x17\x87\xe8\x4e\x2b\x9f\x33\x55\xfe\xa6\x32\xe3\x13\x34\x5f\x0a\x4a\x65\x39\x3d\x26\x64\xd0\x11\x18\x83\xa5\x60\x73\x27\x82\xbc\x3d\x50\x40\xa9\x38\xc2\xa8\x8f\x30\x17\xde\x2e\x91\x89\x0a\x50\xf9\x6e\x15\xcb\x4f\x0d\x4c\x34\x09\x52\x0d\xdb\x71\x8c\x34\x33\xd5\xf8\xa7\xb8\x3f\x3d\x66\x87\x64\xe1\x4b\xae\x34\x94\xce\xe3\x6f\x13\x9a\x2d\x93\x77\xb4\xde\xbb\x4a\x85\x41\xde\x4e\x78\x4f\x75\x66\x9d\xbb\x48\x5a\x6c\x0a\x62\x8b\x02\xcb\xe8\x8b\x43\x96\x24\xec\xd9\xb3\x00\x28\x34\x84\x9b\x71\x21\xa4\xa1\xf6\x11\xb5\x9a\xf0\xe6\x2d\xa1\xa8\xed\x68\xa2\x28\x72\x02\x1e\x27\x07\x5b\xa5\xef\x2d\x69\x51\xa6\x2d\xd4\x76\xda\xd1\x7b\x1f\x60\xf7\xb5\x7e\x49\x87\xc2\xae\x5a\x10\x02\xb6\xd0\x92\xdd\x93\x77\x68\xf1\xe4\xea\xe2\xec\xec\xbb\xa3\xc1\x8f\xb7\x83\x8b\x9f\x2e\xcf\x4e\x6e\x4e\x48\xf7\x48\xde\xbd\x6f\x01\x59\xda\x2c\x6f\xa5\x4b\x7d\xda\x5e\x89\xaf\xde\x56\xed\x33\xe7\xfa\x55\x58\x76\xd1\x64\x45\x8f\x7c\x90\x40\x21\x55\x09\x2a\x3f\x22\x2f\x40\x69\x2b\xd8\x30\xb5\x82\x05\xae\xe9\xb9\x23\x64\x6e\xe7\xd1\x0e\x6f\xb8\x12\xae\x68\xda\x43\x62\x7e\x23\x07\x7c\x02\x75\xea\x8e\x89\xf9\x8d\x3c\x93\x33\x50\xe9\x0e\x36\xca\xb2\xb5\x9a\x75\xc9\xae\x80\x6b\x29\x48\x4d\x97\x15\xf6\xf0\xc0\xf1\x09\x9a\x7d\x9b\xfd\xa7\x36\x51\xd2\xa2\x3f\xe6\x80\x1d\x94\xd8\x89\x28\xd4\xf4\x7f\xc4\xa1\x11\xea\x78\xc8\x2a\x51\x28\x98\x80\x30\x57\xb2\xae\xef\x78\x71\x3f\x90\x53\x61\x36\x79\x63\x0f\xfb\x04\x65\xe4\x2f\xa7\x07\x4e\x3f\x97\x6a\xc2\xeb\x7f\x53\x10\xc7\x51\x44\x85\xa2\xd3\x17\x05\x5d\xde\xda\x0e\xde\x36\xd0\xa8\x1a\xab\xfc\xc9\x05\xbb\xf4\x79\x1c\xd9\x02\x22\xef\xde\xe7\xe9\xf3\xcd\x1d\x59\x96\x1f\x03\x34\x03\xd9\x3c\xa6\xd8\x92\xb9\x26\x4c\x48\xb3\xfe\xd6\xe3\xa8\x2c\xed\x8d\x47\x35\x64\xda\xd7\xd2\xae\x4a\x36\xbd\x24\xec\xf7\xdf\xb7\x12\xac\xc9\x3f\xf6\x3c\x30\xb4\xfd\x6b\xb7\x59\x47\x3f\xb5\x0d\x79\x66\xe9\xe4\xd4\x34\x53\xb3\x6c\x5e\x86\x26\x1f\xd8\xf3\x22\xd5\x0b\x22\x5a\x45\x8d\x3b\x89\xe5\x9d\xc6\x6d\x6d\x7b\x32\xf4\xfd\x89\x3d\x84\xae\x6d\x50\xa8\x2f\x62\x5f\x7f\xa5\xbf\x4e\x7a\x4c\xdb\xf7\x2c\xf6\xf7\x17\xe8\x3f\xfb\x42\xf7\x94\xab\x7b\x9e\x8a\xa1\x1c\xa6\x09\x2f\x4b\x28\xb7\xb2\x66\xb3\xca\x8c\x99\x76\xcd\x4a\x67\xb3\x9e\xeb\x2e\xd3\xe7\x64\x0c\xd7\xd2\x94\x59\xb6\x6d\xcb\x87\x0a\x66\x8c\x1b\x36\x36\xa6\xd1\x07\xfd\x7e\x21\x85\x96\x35\xe0\x79\x21\xe7\x13\xfe\x9b\x14\x74\x69\x59\xcb\x69\x39\xc4\x60\x40\xb7\xf7\xc7\x72\x02\xdf\xfe\x5f\xdf\xca\xd1\x2f\xc1\xf0\xaa\xfe\x96\x84\x2a\x0f\xbf\xd2\xc9\x16\x51\xe2\x28\xba\x25\x37\xad\x26\x97\xa5\x7b\xbd\x3a\xcb\xc6\x69\x23\xc3\x1e\x4b\x06\x57\x27\x47\x37\x27\xb7\xa7\xe7\xb7\x97\x57\x17\xaf\xae\x4e\xae\xaf\x93\x1e\x4b\x92\x0d\x3d\xe8\x2e\xde\xf6\xce\xb6\xf2\xa1\xb3\x35\x85\x30\x05\x25\xfa\x90\x8e\x5a\xb5\x06\xba\x2b\xda\x1c\x19\xa1\x5a\x9d\x13\xda\xe6\xe8\xa5\x03\x49\x2a\xeb\xf2\x02\xd3\x93\x80\xd9\xc5\x9a\x58\x96\xd2\x06\xb3\x25\xda\x3d\x9e\x23\x61\x97\x11\xcf\x7d\xd2\x80\x4d\x01\xfb\x85\x2f\xda\x9a\x72\x91\x90\x99\xb5\xda\xc7\xb3\x09\xe9\xee\x13\x8a\xfb\x7a\x90\x9f\x6a\xeb\xee\x81\x9c\x34\xd8\x02\xa6\x72\x83\x24\x3d\x36\xe4\xb5\x86\x0c\x5b\xe9\x2f\xfc\x9d\x21\xaa\x71\xf2\xeb\x94\xd7\xb8\xcc\xeb\x88\xa9\x7d\xb1\xe8\xa1\x4e\xdd\xa1\x6c\x5b\xde\x91\x72\xa7\xc4\xf3\xda\xc3\xba\xb8\x77\xaa\x7f\x96\xd4\xd3\xa2\xf1\xe3\xf9\x41\xc0\x8c\x35\x5c\xf1\x89\x66\x5f\x7d\xf3\x60\x4f\xbf\xb2\x2e\xf1\x39\xb1\x3a\x53\x7c\x09\x89\x2a\xed\x9b\xa3\x28\x68\x77\xc9\x52\x4e\x02\x97\xa4\xda\x6d\xff\x4b\xb2\x94\xf4\xfa\xb8\x87\x8f\xe6\xa9\xd7\x97\xc7\x7f\x7a\x9e\x62\x6c\x87\x44\xe5\x83\x6e\x05\xe9\x08\xdd\x9d\x12\x16\x5d\xbf\xfd\x69\x1d\x07\x6d\x87\xfa\xec\xd2\x1c\x44\x41\x60\x1e\x07\x27\xc8\x2c\x5e\x63\xf5\xbd\xe2\xd1\x9e\x47\xf7\x68\x05\x7c\x87\x4a\x2d\xdd\x06\xa0\xd3\x21\x77\x7b\x74\x85\x3c\x77\x70\xaf\xb7\xd7\xb6\x52\x14\x6f\xfb\x44\x6c\xdd\xbe\xf5\xe4\xf1\xe4\xd6\xcc\x5e\x6b\xf8\x5b\xe3\xd5\xeb\xaf\x5d\x2e\xcf\x3e\xe1\x2e\x4b\xb5\x57\x96\xbb\xdd\x64\x2d\x8f\x4b\xf9\x2b\x30\x29\x1d\x6e\xdc\xad\xd6\x2b\xe8\x5c\x6a\x3d\x45\xcc\x67\xbb\xd2\x0a\x4f\x2f\xee\xfe\xd6\x52\x61\x58\xd8\xdb\x2c\xbf\x2a\xac\xe6\x21\x91\x63\x1e\x7a\x27\xb8\x83\xda\x40\xf1\xcd\xcb\x38\x5e\x66\xba\xdd\x0d\xe5\x7a\x94\x90\xfb\x1f\x35\x4f\x9b\xbc\x3c\xb3\x35\xe6\x58\xb9\x18\xb6\x80\x5c\x73\x32\xdd\x0f\x86\xbd\xb6\x8d\x0e\xde\xb1\x9f\xf1\xaf\xca\x9e\xc5\x5a\xd0\x6e\x4b\x61\x3d\x82\x74\xf6\x17\xa6\xd7\x60\x5a\x54\x75\xef\x93\x80\xbd\xbe\xeb\x74\xee\xda\x85\x98\x4e\xd5\x36\x1c\xf0\x61\xfd\x92\xf6\x06\xd8\xe3\x82\xda\xde\x4d\x4d\xa8\xee\xb6\x9c\xb6\x7c\x04\xf5\xc8\x21\x30\xdc\xc8\x57\x7b\x6a\x0d\x74\xa7\x67\x44\xa7\xd0\x70\xfa\xe9\x97\xe7\x6e\x03\xd7\x07\xc4\x51\xf0\x35\xfb\xcb\x46\xc9\x06\x37\x25\xbf\x5d\xb8\x2e\xa5\x18\xc3\x84\xe7\x97\x4a\x36\xa0\x4c\xe5\xbf\x6d\xbb\xa2\x60\xd7\xe4\x37\x30\x69\x6a\x6e\xfc\xcf\x86\xa2\xf9\x9c\xc6\x7f\x84\x47\xc4\xbf\x45\xb4\xb7\xd5\x92\x36\x4d\x3c\x9d\x1b\xa3\x6f\x61\x9e\xf0\x98\x1b\x3e\xbf\xb8\x7b\x7f\xb0\x62\xa8\x81\xfb\x86\x4a\x66\x5c\x84\x5f\x28\xac\xcb\x9c\xdc\x9e\xf7\xb5\xfd\x16\x69\x25\x61\x87\xac\x23\x99\x53\xc3\xd7\xc8\x3d\xd8\x38\x2b\xbe\x7d\xa2\x81\x25\x48\xde\x79\xce\xa2\x5c\xee\xe2\x3e\xf8\xff\x67\x27\xd5\x6e\x3c\xee\x07\x71\xd2\x49\x3f\x8a\xe2\xa8\x2c\xed\xef\x51\x78\xed\x63\x4d\xaf\x45\xfd\x5e\x70\xc6\x2e\xc8\xeb\x80\x9b\x84\x2a\x78\x3c\x07\xf5\xa0\x0b\x9a\xb0\x3a\x3c\xfd\x58\xf0\x69\xc5\xe1\xaf\xf4\xff\x99\xd2\xff\x96\x1c\xe9\xf2\xa3\x0b\x9b\x5d\xfa\xf5\xb5\x3b\x2c\xd7\xbf\xe1\x95\x79\x2d\x4c\x55\x5b\x16\xc4\xad\xa4\xf2\xd2\x81\x0f\x2d\xf6\xd0\xd9\x0e\xee\x27\x30\xd2\x6c\xdb\xd1\x86\xa1\xf5\x02\x74\xfc\x89\x20\x08\xae\xcf\x08\x06\xfe\x5e\x6d\x57\x20\x3c\xe9\xc1\xda\xdf\x9c\xad\xab\xd9\x78\xa2\x58\x1e\x21\xd6\x18\xd0\xff\xbe\x06\x8b\x8b\xf6\x8f\x07\x87\xcb\x9f\x66\x2d\xe6\x73\x97\x40\x83\x7a\x15\x7e\xd1\xdd\x89\x75\x7b\x80\x84\x5f\x97\xab\xed\xed\x0e\x4b\x4e\x3e\x18\x50\x82\x2c\x94\x10\xe9\x97\x6a\xe5\x84\x15\x94\x31\xba\x41\x0e\x17\xb9\x7d\xd2\xe0\xb0\xb9\xf6\xb6\x32\x09\x19\x87\x0c\x6c\xf5\x9b\xcf\xd3\x4a\x94\xf0\x21\x90\xef\x52\x2a\xa3\xd9\xff\x67\xf6\x61\x81\xfe\x68\x4d\x74\xc8\x78\xd3\x80\x28\x53\x3f\x82\x0c\x56\xc5\xee\x1c\xe8\xba\x8f\xbb\xfa\xa4\xe5\xb8\x95\xee\x90\x79\x31\xbc\xb7\x3e\xee\x78\x82\xf0\x4f\xbc\xc1\x6d\xc8\x74\x13\x7c\xf9\x4c\xce\xef\xb0\x5f\xe7\x53\xec\x32\x36\x7e\x3b\x0f\xb6\xab\x0c\x4c\x90\x6e\xb9\xde\xae\xf4\xbf\xf3\xb3\xf3\xd4\x55\x24\x07\xac\x1d\xf8\x99\xd7\x53\xf7\xf3\xbf\x6e\x13\xb0\x13\xba\x5a\xe1\x3f\x8a\xa9\xf5\x7a\x65\xfe\x07\x7f\xd6\xa2\x2d\x56\x96\x63\xbb\xa0\x65\x77\xef\x6d\x05\x49\x40\xe9\xab\x1f\x4a\xd0\x02\x65\xf7\xae\xa8\x93\xbb\x56\xfa\xa2\x1d\x72\x95\xbf\xcd\x7c\xf2\xc5\xec\x5f\x01\x00\x00\xff\xff\xaf\xce\x6e\xce\x17\x30\x00\x00") func controllerGoTemplBytes() ([]byte, error) { return bindataRead( @@ -106,7 +106,7 @@ func controllerGoTempl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "controller.go.templ", size: 11338, mode: os.FileMode(420), modTime: time.Unix(1538385198, 0)} + info := bindataFileInfo{name: "controller.go.templ", size: 12311, mode: os.FileMode(436), modTime: time.Unix(1538650854, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -126,7 +126,7 @@ func template_functionsGoTempl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "template_functions.go.templ", size: 1584, mode: os.FileMode(420), modTime: time.Unix(1538385198, 0)} + info := bindataFileInfo{name: "template_functions.go.templ", size: 1584, mode: os.FileMode(436), modTime: time.Unix(1538540481, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -146,7 +146,7 @@ func typesGoTempl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "types.go.templ", size: 3173, mode: os.FileMode(420), modTime: time.Unix(1538384745, 0)} + info := bindataFileInfo{name: "types.go.templ", size: 3173, mode: os.FileMode(436), modTime: time.Unix(1538540481, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -203,10 +203,10 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "cft.go.templ": cftGoTempl, - "controller.go.templ": controllerGoTempl, + "cft.go.templ": cftGoTempl, + "controller.go.templ": controllerGoTempl, "template_functions.go.templ": template_functionsGoTempl, - "types.go.templ": typesGoTempl, + "types.go.templ": typesGoTempl, } // AssetDir returns the file names below a certain @@ -248,11 +248,12 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ - "cft.go.templ": &bintree{cftGoTempl, map[string]*bintree{}}, - "controller.go.templ": &bintree{controllerGoTempl, map[string]*bintree{}}, + "cft.go.templ": &bintree{cftGoTempl, map[string]*bintree{}}, + "controller.go.templ": &bintree{controllerGoTempl, map[string]*bintree{}}, "template_functions.go.templ": &bintree{template_functionsGoTempl, map[string]*bintree{}}, - "types.go.templ": &bintree{typesGoTempl, map[string]*bintree{}}, + "types.go.templ": &bintree{typesGoTempl, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory @@ -301,4 +302,3 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } - diff --git a/codegen.sh b/codegen.sh deleted file mode 100755 index 53fadbcb9..000000000 --- a/codegen.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -e - -# 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. - -scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -projectdir="$(pwd | sed "s#$GOPATH\/src\/##g")" -cd ${scriptdir}/vendor/k8s.io/code-generator && ./generate-groups.sh \ - all \ - ${projectdir}/pkg/client \ - ${projectdir}/pkg/apis \ - "service-operator.aws:v1alpha1" \ diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt new file mode 100644 index 000000000..e2fe4d13b --- /dev/null +++ b/hack/boilerplate.go.txt @@ -0,0 +1,13 @@ +/* +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. +*/ \ No newline at end of file diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh new file mode 100755 index 000000000..c80899b89 --- /dev/null +++ b/hack/update-codegen.sh @@ -0,0 +1,17 @@ +set -o errexit +set -o nounset +set -o pipefail + +SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. +CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} + +# generate the code with: +# --output-base because this script should also be able to run inside the vendor dir of +# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir +# instead of the $GOPATH directly. For normal projects this can be dropped. +${CODEGEN_PKG}/generate-groups.sh all \ + github.com/awslabs/aws-service-operator/pkg/client \ + github.com/awslabs/aws-service-operator/pkg/apis \ + "service-operator.aws:v1alpha1" \ + --output-base "$(dirname ${BASH_SOURCE})/../../.." \ + --go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt diff --git a/pkg/config/types.go b/pkg/config/types.go index 03e643c94..c9093c987 100644 --- a/pkg/config/types.go +++ b/pkg/config/types.go @@ -6,6 +6,7 @@ import ( opkit "github.com/christopherhein/operator-kit" "github.com/sirupsen/logrus" "k8s.io/client-go/rest" + "k8s.io/client-go/tools/record" ) // Config defines the configuration for the operator @@ -22,6 +23,7 @@ type Config struct { ClusterName string Bucket string AccountID string + Recorder record.EventRecorder } // LoggingConfig defines the attributes for the logger diff --git a/pkg/operator/dynamodb/controller.go b/pkg/operator/dynamodb/controller.go index a59eda1d0..d462808cf 100644 --- a/pkg/operator/dynamodb/controller.go +++ b/pkg/operator/dynamodb/controller.go @@ -13,8 +13,11 @@ import ( "github.com/awslabs/aws-service-operator/pkg/config" "github.com/awslabs/aws-service-operator/pkg/queue" opkit "github.com/christopherhein/operator-kit" + "github.com/iancoleman/strcase" + corev1 "k8s.io/api/core/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/client-go/tools/cache" + "strings" awsapi "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws" awsV1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" @@ -96,27 +99,35 @@ func QueueUpdater(config *config.Config, msg *queue.MessageBody) error { } if name != "" && namespace != "" { + annotations := map[string]string{ + "StackID": msg.ParsedMessage["StackId"], + "StackName": msg.ParsedMessage["StackName"], + "ResourceType": msg.ParsedMessage["ResourceType"], + } if msg.ParsedMessage["ResourceStatus"] == "ROLLBACK_COMPLETE" { - err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) + obj, err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } else if msg.ParsedMessage["ResourceStatus"] == "DELETE_COMPLETE" { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } - + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) err = incrementRollbackCount(config, name, namespace) if err != nil { return err } } else { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeNormal, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } + } return nil @@ -134,7 +145,7 @@ func (c *Controller) onAdd(obj interface{}) { c.config.Logger.Infof("added dynamodb '%s' with stackID '%s'", s.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -158,7 +169,7 @@ func (c *Controller) onUpdate(oldObj, newObj interface{}) { c.config.Logger.Infof("updated dynamodb '%s' with params '%s'", no.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -196,13 +207,13 @@ func incrementRollbackCount(config *config.Config, name string, namespace string return nil } -func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) error { +func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) (*awsV1alpha1.DynamoDB, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.DynamoDBs(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting dynamodbs") - return err + return nil, err } resourceCopy := resource.DeepCopy() @@ -223,7 +234,7 @@ func updateStatus(config *config.Config, name string, namespace string, stackID _, err = clientSet.DynamoDBs(namespace).Update(resourceCopy) if err != nil { logger.WithError(err).Error("error updating resource") - return err + return nil, err } if helpers.IsStackComplete(status, false) { @@ -232,26 +243,26 @@ func updateStatus(config *config.Config, name string, namespace string, stackID logger.WithError(err).Info("error syncing resources") } } - return nil + return resourceCopy, nil } -func deleteStack(config *config.Config, name string, namespace string, stackID string) error { +func deleteStack(config *config.Config, name string, namespace string, stackID string) (*awsV1alpha1.DynamoDB, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.DynamoDBs(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting dynamodbs") - return err + return nil, err } cft := New(config, resource, "") err = cft.DeleteStack() if err != nil { - return err + return nil, err } err = cft.WaitUntilStackDeleted() - return err + return resource, err } func syncAdditionalResources(config *config.Config, s *awsV1alpha1.DynamoDB) (err error) { diff --git a/pkg/operator/ecrrepository/controller.go b/pkg/operator/ecrrepository/controller.go index 78322ef92..cdb261bc3 100644 --- a/pkg/operator/ecrrepository/controller.go +++ b/pkg/operator/ecrrepository/controller.go @@ -13,8 +13,11 @@ import ( "github.com/awslabs/aws-service-operator/pkg/config" "github.com/awslabs/aws-service-operator/pkg/queue" opkit "github.com/christopherhein/operator-kit" + "github.com/iancoleman/strcase" + corev1 "k8s.io/api/core/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/client-go/tools/cache" + "strings" awsapi "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws" awsV1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" @@ -93,27 +96,35 @@ func QueueUpdater(config *config.Config, msg *queue.MessageBody) error { } if name != "" && namespace != "" { + annotations := map[string]string{ + "StackID": msg.ParsedMessage["StackId"], + "StackName": msg.ParsedMessage["StackName"], + "ResourceType": msg.ParsedMessage["ResourceType"], + } if msg.ParsedMessage["ResourceStatus"] == "ROLLBACK_COMPLETE" { - err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) + obj, err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } else if msg.ParsedMessage["ResourceStatus"] == "DELETE_COMPLETE" { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } - + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) err = incrementRollbackCount(config, name, namespace) if err != nil { return err } } else { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeNormal, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } + } return nil @@ -131,7 +142,7 @@ func (c *Controller) onAdd(obj interface{}) { c.config.Logger.Infof("added ecrrepository '%s' with stackID '%s'", s.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -155,7 +166,7 @@ func (c *Controller) onUpdate(oldObj, newObj interface{}) { c.config.Logger.Infof("updated ecrrepository '%s' with params '%s'", no.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -193,13 +204,13 @@ func incrementRollbackCount(config *config.Config, name string, namespace string return nil } -func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) error { +func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) (*awsV1alpha1.ECRRepository, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.ECRRepositories(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting ecrrepositories") - return err + return nil, err } resourceCopy := resource.DeepCopy() @@ -222,7 +233,7 @@ func updateStatus(config *config.Config, name string, namespace string, stackID _, err = clientSet.ECRRepositories(namespace).Update(resourceCopy) if err != nil { logger.WithError(err).Error("error updating resource") - return err + return nil, err } if helpers.IsStackComplete(status, false) { @@ -231,26 +242,26 @@ func updateStatus(config *config.Config, name string, namespace string, stackID logger.WithError(err).Info("error syncing resources") } } - return nil + return resourceCopy, nil } -func deleteStack(config *config.Config, name string, namespace string, stackID string) error { +func deleteStack(config *config.Config, name string, namespace string, stackID string) (*awsV1alpha1.ECRRepository, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.ECRRepositories(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting ecrrepositories") - return err + return nil, err } cft := New(config, resource, "") err = cft.DeleteStack() if err != nil { - return err + return nil, err } err = cft.WaitUntilStackDeleted() - return err + return resource, err } func syncAdditionalResources(config *config.Config, s *awsV1alpha1.ECRRepository) (err error) { diff --git a/pkg/operator/s3bucket/controller.go b/pkg/operator/s3bucket/controller.go index b21274d1d..d6065da3f 100644 --- a/pkg/operator/s3bucket/controller.go +++ b/pkg/operator/s3bucket/controller.go @@ -13,8 +13,11 @@ import ( "github.com/awslabs/aws-service-operator/pkg/config" "github.com/awslabs/aws-service-operator/pkg/queue" opkit "github.com/christopherhein/operator-kit" + "github.com/iancoleman/strcase" + corev1 "k8s.io/api/core/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/client-go/tools/cache" + "strings" awsapi "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws" awsV1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" @@ -94,27 +97,35 @@ func QueueUpdater(config *config.Config, msg *queue.MessageBody) error { } if name != "" && namespace != "" { + annotations := map[string]string{ + "StackID": msg.ParsedMessage["StackId"], + "StackName": msg.ParsedMessage["StackName"], + "ResourceType": msg.ParsedMessage["ResourceType"], + } if msg.ParsedMessage["ResourceStatus"] == "ROLLBACK_COMPLETE" { - err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) + obj, err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } else if msg.ParsedMessage["ResourceStatus"] == "DELETE_COMPLETE" { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } - + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) err = incrementRollbackCount(config, name, namespace) if err != nil { return err } } else { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeNormal, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } + } return nil @@ -132,7 +143,7 @@ func (c *Controller) onAdd(obj interface{}) { c.config.Logger.Infof("added s3bucket '%s' with stackID '%s'", s.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -156,7 +167,7 @@ func (c *Controller) onUpdate(oldObj, newObj interface{}) { c.config.Logger.Infof("updated s3bucket '%s' with params '%s'", no.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -194,13 +205,13 @@ func incrementRollbackCount(config *config.Config, name string, namespace string return nil } -func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) error { +func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) (*awsV1alpha1.S3Bucket, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.S3Buckets(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting s3buckets") - return err + return nil, err } resourceCopy := resource.DeepCopy() @@ -222,7 +233,7 @@ func updateStatus(config *config.Config, name string, namespace string, stackID _, err = clientSet.S3Buckets(namespace).Update(resourceCopy) if err != nil { logger.WithError(err).Error("error updating resource") - return err + return nil, err } if helpers.IsStackComplete(status, false) { @@ -231,26 +242,26 @@ func updateStatus(config *config.Config, name string, namespace string, stackID logger.WithError(err).Info("error syncing resources") } } - return nil + return resourceCopy, nil } -func deleteStack(config *config.Config, name string, namespace string, stackID string) error { +func deleteStack(config *config.Config, name string, namespace string, stackID string) (*awsV1alpha1.S3Bucket, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.S3Buckets(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting s3buckets") - return err + return nil, err } cft := New(config, resource, "") err = cft.DeleteStack() if err != nil { - return err + return nil, err } err = cft.WaitUntilStackDeleted() - return err + return resource, err } func syncAdditionalResources(config *config.Config, s *awsV1alpha1.S3Bucket) (err error) { diff --git a/pkg/operator/snssubscription/controller.go b/pkg/operator/snssubscription/controller.go index 78f4757f9..b1fa97a32 100644 --- a/pkg/operator/snssubscription/controller.go +++ b/pkg/operator/snssubscription/controller.go @@ -13,8 +13,11 @@ import ( "github.com/awslabs/aws-service-operator/pkg/config" "github.com/awslabs/aws-service-operator/pkg/queue" opkit "github.com/christopherhein/operator-kit" + "github.com/iancoleman/strcase" + corev1 "k8s.io/api/core/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/client-go/tools/cache" + "strings" awsapi "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws" awsV1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" @@ -92,27 +95,35 @@ func QueueUpdater(config *config.Config, msg *queue.MessageBody) error { } if name != "" && namespace != "" { + annotations := map[string]string{ + "StackID": msg.ParsedMessage["StackId"], + "StackName": msg.ParsedMessage["StackName"], + "ResourceType": msg.ParsedMessage["ResourceType"], + } if msg.ParsedMessage["ResourceStatus"] == "ROLLBACK_COMPLETE" { - err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) + obj, err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } else if msg.ParsedMessage["ResourceStatus"] == "DELETE_COMPLETE" { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } - + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) err = incrementRollbackCount(config, name, namespace) if err != nil { return err } } else { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeNormal, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } + } return nil @@ -130,7 +141,7 @@ func (c *Controller) onAdd(obj interface{}) { c.config.Logger.Infof("added snssubscription '%s' with stackID '%s'", s.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -154,7 +165,7 @@ func (c *Controller) onUpdate(oldObj, newObj interface{}) { c.config.Logger.Infof("updated snssubscription '%s' with params '%s'", no.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -192,13 +203,13 @@ func incrementRollbackCount(config *config.Config, name string, namespace string return nil } -func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) error { +func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) (*awsV1alpha1.SNSSubscription, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.SNSSubscriptions(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting snssubscriptions") - return err + return nil, err } resourceCopy := resource.DeepCopy() @@ -218,7 +229,7 @@ func updateStatus(config *config.Config, name string, namespace string, stackID _, err = clientSet.SNSSubscriptions(namespace).Update(resourceCopy) if err != nil { logger.WithError(err).Error("error updating resource") - return err + return nil, err } if helpers.IsStackComplete(status, false) { @@ -227,26 +238,26 @@ func updateStatus(config *config.Config, name string, namespace string, stackID logger.WithError(err).Info("error syncing resources") } } - return nil + return resourceCopy, nil } -func deleteStack(config *config.Config, name string, namespace string, stackID string) error { +func deleteStack(config *config.Config, name string, namespace string, stackID string) (*awsV1alpha1.SNSSubscription, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.SNSSubscriptions(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting snssubscriptions") - return err + return nil, err } cft := New(config, resource, "") err = cft.DeleteStack() if err != nil { - return err + return nil, err } err = cft.WaitUntilStackDeleted() - return err + return resource, err } func syncAdditionalResources(config *config.Config, s *awsV1alpha1.SNSSubscription) (err error) { diff --git a/pkg/operator/snstopic/controller.go b/pkg/operator/snstopic/controller.go index a29c1bbea..645976654 100644 --- a/pkg/operator/snstopic/controller.go +++ b/pkg/operator/snstopic/controller.go @@ -13,8 +13,11 @@ import ( "github.com/awslabs/aws-service-operator/pkg/config" "github.com/awslabs/aws-service-operator/pkg/queue" opkit "github.com/christopherhein/operator-kit" + "github.com/iancoleman/strcase" + corev1 "k8s.io/api/core/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/client-go/tools/cache" + "strings" awsapi "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws" awsV1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" @@ -94,27 +97,35 @@ func QueueUpdater(config *config.Config, msg *queue.MessageBody) error { } if name != "" && namespace != "" { + annotations := map[string]string{ + "StackID": msg.ParsedMessage["StackId"], + "StackName": msg.ParsedMessage["StackName"], + "ResourceType": msg.ParsedMessage["ResourceType"], + } if msg.ParsedMessage["ResourceStatus"] == "ROLLBACK_COMPLETE" { - err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) + obj, err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } else if msg.ParsedMessage["ResourceStatus"] == "DELETE_COMPLETE" { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } - + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) err = incrementRollbackCount(config, name, namespace) if err != nil { return err } } else { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeNormal, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } + } return nil @@ -132,7 +143,7 @@ func (c *Controller) onAdd(obj interface{}) { c.config.Logger.Infof("added snstopic '%s' with stackID '%s'", s.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -156,7 +167,7 @@ func (c *Controller) onUpdate(oldObj, newObj interface{}) { c.config.Logger.Infof("updated snstopic '%s' with params '%s'", no.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -194,13 +205,13 @@ func incrementRollbackCount(config *config.Config, name string, namespace string return nil } -func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) error { +func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) (*awsV1alpha1.SNSTopic, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.SNSTopics(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting snstopics") - return err + return nil, err } resourceCopy := resource.DeepCopy() @@ -220,7 +231,7 @@ func updateStatus(config *config.Config, name string, namespace string, stackID _, err = clientSet.SNSTopics(namespace).Update(resourceCopy) if err != nil { logger.WithError(err).Error("error updating resource") - return err + return nil, err } if helpers.IsStackComplete(status, false) { @@ -229,26 +240,26 @@ func updateStatus(config *config.Config, name string, namespace string, stackID logger.WithError(err).Info("error syncing resources") } } - return nil + return resourceCopy, nil } -func deleteStack(config *config.Config, name string, namespace string, stackID string) error { +func deleteStack(config *config.Config, name string, namespace string, stackID string) (*awsV1alpha1.SNSTopic, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.SNSTopics(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting snstopics") - return err + return nil, err } cft := New(config, resource, "") err = cft.DeleteStack() if err != nil { - return err + return nil, err } err = cft.WaitUntilStackDeleted() - return err + return resource, err } func syncAdditionalResources(config *config.Config, s *awsV1alpha1.SNSTopic) (err error) { diff --git a/pkg/operator/sqsqueue/controller.go b/pkg/operator/sqsqueue/controller.go index 395096f5c..affbcb399 100644 --- a/pkg/operator/sqsqueue/controller.go +++ b/pkg/operator/sqsqueue/controller.go @@ -13,8 +13,11 @@ import ( "github.com/awslabs/aws-service-operator/pkg/config" "github.com/awslabs/aws-service-operator/pkg/queue" opkit "github.com/christopherhein/operator-kit" + "github.com/iancoleman/strcase" + corev1 "k8s.io/api/core/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/client-go/tools/cache" + "strings" awsapi "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws" awsV1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" @@ -94,27 +97,35 @@ func QueueUpdater(config *config.Config, msg *queue.MessageBody) error { } if name != "" && namespace != "" { + annotations := map[string]string{ + "StackID": msg.ParsedMessage["StackId"], + "StackName": msg.ParsedMessage["StackName"], + "ResourceType": msg.ParsedMessage["ResourceType"], + } if msg.ParsedMessage["ResourceStatus"] == "ROLLBACK_COMPLETE" { - err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) + obj, err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } else if msg.ParsedMessage["ResourceStatus"] == "DELETE_COMPLETE" { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } - + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) err = incrementRollbackCount(config, name, namespace) if err != nil { return err } } else { - err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) if err != nil { return err } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeNormal, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) } + } return nil @@ -132,7 +143,7 @@ func (c *Controller) onAdd(obj interface{}) { c.config.Logger.Infof("added sqsqueue '%s' with stackID '%s'", s.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -156,7 +167,7 @@ func (c *Controller) onUpdate(oldObj, newObj interface{}) { c.config.Logger.Infof("updated sqsqueue '%s' with params '%s'", no.Name, string(*output.StackId)) c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) - err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") + _, err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") if err != nil { c.config.Logger.WithError(err).Error("error updating status") } @@ -194,13 +205,13 @@ func incrementRollbackCount(config *config.Config, name string, namespace string return nil } -func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) error { +func updateStatus(config *config.Config, name string, namespace string, stackID string, status string, reason string) (*awsV1alpha1.SQSQueue, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.SQSQueues(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting sqsqueues") - return err + return nil, err } resourceCopy := resource.DeepCopy() @@ -225,7 +236,7 @@ func updateStatus(config *config.Config, name string, namespace string, stackID _, err = clientSet.SQSQueues(namespace).Update(resourceCopy) if err != nil { logger.WithError(err).Error("error updating resource") - return err + return nil, err } if helpers.IsStackComplete(status, false) { @@ -234,26 +245,26 @@ func updateStatus(config *config.Config, name string, namespace string, stackID logger.WithError(err).Info("error syncing resources") } } - return nil + return resourceCopy, nil } -func deleteStack(config *config.Config, name string, namespace string, stackID string) error { +func deleteStack(config *config.Config, name string, namespace string, stackID string) (*awsV1alpha1.SQSQueue, error) { logger := config.Logger clientSet, _ := awsclient.NewForConfig(config.RESTConfig) resource, err := clientSet.SQSQueues(namespace).Get(name, metav1.GetOptions{}) if err != nil { logger.WithError(err).Error("error getting sqsqueues") - return err + return nil, err } cft := New(config, resource, "") err = cft.DeleteStack() if err != nil { - return err + return nil, err } err = cft.WaitUntilStackDeleted() - return err + return resource, err } func syncAdditionalResources(config *config.Config, s *awsV1alpha1.SQSQueue) (err error) { diff --git a/pkg/queue/queue.go b/pkg/queue/queue.go index f42ba4b7b..894be03a3 100644 --- a/pkg/queue/queue.go +++ b/pkg/queue/queue.go @@ -230,7 +230,7 @@ func process(q *Queue, svc *sqs.SQS, h Handler, stopCh <-chan struct{}) error { if err != nil { logger.WithError(err).Error("error processing message") } - logger.Infof("stackID %v updated status to %v", mb.ParsedMessage["StackId"], mb.ParsedMessage["ResourceStatus"]) + logger.Debugf("stackID %v updated status to %v", mb.ParsedMessage["StackId"], mb.ParsedMessage["ResourceStatus"]) _, err = svc.DeleteMessage(&sqs.DeleteMessageInput{ QueueUrl: aws.String(q.queueURL), ReceiptHandle: message.ReceiptHandle, diff --git a/pkg/server/server.go b/pkg/server/server.go index f749291d1..04edd3432 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "time" + awsscheme "github.com/awslabs/aws-service-operator/pkg/client/clientset/versioned/scheme" awsclient "github.com/awslabs/aws-service-operator/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1" "github.com/awslabs/aws-service-operator/pkg/config" "github.com/awslabs/aws-service-operator/pkg/operator/cloudformationtemplate" @@ -17,13 +18,18 @@ import ( "github.com/awslabs/aws-service-operator/pkg/operator/snstopic" "github.com/awslabs/aws-service-operator/pkg/operator/sqsqueue" opkit "github.com/christopherhein/operator-kit" - "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/record" ) +const controllerName = "aws-service-operator" + // New creates a new server from a config func New(config *config.Config) *Server { return &Server{ @@ -36,7 +42,7 @@ func (c *Server) Run(stopChan chan struct{}) { config := c.Config logger := config.Logger logger.Info("Getting kubernetes context") - context, restConfig, awsClientset, err := createContext(config.Kubeconfig) + context, restConfig, kubeclientset, awsClientset, err := createContext(config.Kubeconfig) if err != nil { logger.Fatalf("failed to create context. %+v\n", err) } @@ -84,28 +90,35 @@ func (c *Server) Run(stopChan chan struct{}) { } config.AWSSession = sess + awsscheme.AddToScheme(scheme.Scheme) + eventBroadcaster := record.NewBroadcaster() + eventBroadcaster.StartLogging(logger.Infof) + eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeclientset.CoreV1().Events("")}) + recorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerName}) + config.Recorder = recorder + // start watching the aws operator resources logger.Info("Watching the resources") cftcontroller := cloudformationtemplate.NewController(config, context, awsClientset) - cftcontroller.StartWatch(v1.NamespaceAll, stopChan) + cftcontroller.StartWatch(corev1.NamespaceAll, stopChan) s3controller := s3bucket.NewController(config, context, awsClientset) - s3controller.StartWatch(v1.NamespaceAll, stopChan) + s3controller.StartWatch(corev1.NamespaceAll, stopChan) ddbcontroller := dynamodb.NewController(config, context, awsClientset) - ddbcontroller.StartWatch(v1.NamespaceAll, stopChan) + ddbcontroller.StartWatch(corev1.NamespaceAll, stopChan) sqscontroller := sqsqueue.NewController(config, context, awsClientset) - sqscontroller.StartWatch(v1.NamespaceAll, stopChan) + sqscontroller.StartWatch(corev1.NamespaceAll, stopChan) ecrcontroller := ecrrepository.NewController(config, context, awsClientset) - ecrcontroller.StartWatch(v1.NamespaceAll, stopChan) + ecrcontroller.StartWatch(corev1.NamespaceAll, stopChan) snscontroller := snstopic.NewController(config, context, awsClientset) - snscontroller.StartWatch(v1.NamespaceAll, stopChan) + snscontroller.StartWatch(corev1.NamespaceAll, stopChan) snssubcontroller := snssubscription.NewController(config, context, awsClientset) - snssubcontroller.StartWatch(v1.NamespaceAll, stopChan) + snssubcontroller.StartWatch(corev1.NamespaceAll, stopChan) } func getClientConfig(kubeconfig string) (*rest.Config, error) { @@ -115,25 +128,25 @@ func getClientConfig(kubeconfig string) (*rest.Config, error) { return rest.InClusterConfig() } -func createContext(kubeconfig string) (*opkit.Context, *rest.Config, awsclient.ServiceoperatorV1alpha1Interface, error) { +func createContext(kubeconfig string) (*opkit.Context, *rest.Config, kubernetes.Interface, awsclient.ServiceoperatorV1alpha1Interface, error) { config, err := getClientConfig(kubeconfig) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to get k8s config. %+v", err) + return nil, nil, nil, nil, fmt.Errorf("failed to get k8s config. %+v", err) } clientset, err := kubernetes.NewForConfig(config) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to get k8s client. %+v", err) + return nil, nil, nil, nil, fmt.Errorf("failed to get k8s client. %+v", err) } apiExtClientset, err := apiextensionsclient.NewForConfig(config) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to create k8s API extension clientset. %+v", err) + return nil, nil, nil, nil, fmt.Errorf("failed to create k8s API extension clientset. %+v", err) } awsclientset, err := awsclient.NewForConfig(config) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to create object store clientset. %+v", err) + return nil, nil, nil, nil, fmt.Errorf("failed to create object store clientset. %+v", err) } context := &opkit.Context{ @@ -142,5 +155,5 @@ func createContext(kubeconfig string) (*opkit.Context, *rest.Config, awsclient.S Interval: 500 * time.Millisecond, Timeout: 60 * time.Second, } - return context, config, awsclientset, nil + return context, config, clientset, awsclientset, nil } diff --git a/vendor/github.com/christopherhein/go-version/CONTRIBUTING.adoc b/vendor/github.com/christopherhein/go-version/CONTRIBUTING.adoc new file mode 100644 index 000000000..9b12c8dcc --- /dev/null +++ b/vendor/github.com/christopherhein/go-version/CONTRIBUTING.adoc @@ -0,0 +1,31 @@ += Contributing + +⭐️⭐️⭐️⭐️⭐️ First off thanks for taking the time to contribute ⭐️⭐️⭐️⭐️⭐️ + +This project is extremely simple and gives a generic way to get a version out of +your `goreleaser` and `cobra` projects. All the code is contained in a single +package `version.go`. + +== Roadmap + +If you are interested in contributing to this project here are a couple things +that I would like to add. + +1. **Issue: link:https://github.com/christopherhein/go-version/issues/1[#1]** + Support for custom attributes `-X main.foobar=` and updating + `goVersion.New()` to take a splat or map of addition params. +2. **Issue: https://github.com/christopherhein/go-version/issues/2[#2]** + Ability to Output to `yaml` +3. **Issue: https://github.com/christopherhein/go-version/issues/3[#3]** + Func for taking in a type string and outputting the right response ++ +**Example:** ++ +[source,go] +---- +info := goVersion.New(...) +info.Output('json') +---- +4. **Issue: https://github.com/christopherhein/go-version/issues/4[#4]** + Tests 😳 + diff --git a/vendor/github.com/christopherhein/go-version/readme.adoc b/vendor/github.com/christopherhein/go-version/readme.adoc index 1cd901226..89f2638ad 100644 --- a/vendor/github.com/christopherhein/go-version/readme.adoc +++ b/vendor/github.com/christopherhein/go-version/readme.adoc @@ -26,7 +26,7 @@ var ( date = "unknown" versionCmd = &cobra.Command{ Use: "version", - Short: "Version will output the current aws-operator build information", + Short: "Version will output the current build information", Long: ``, Run: func(_ *cobra.Command, _ []string) { var response string @@ -74,3 +74,8 @@ Version: dev Commit: Date: ---- + +== Contributing + +If you want to contribute check out +https://github.com/christopherhein/go-version/blob/master/CONTRIBUTING.adoc diff --git a/vendor/github.com/christopherhein/go-version/version.go b/vendor/github.com/christopherhein/go-version/version.go index 2a7561914..934b8d116 100644 --- a/vendor/github.com/christopherhein/go-version/version.go +++ b/vendor/github.com/christopherhein/go-version/version.go @@ -2,14 +2,14 @@ package version import ( "encoding/json" - "fmt" + "strings" ) // Info creates a formattable struct for output type Info struct { - Version string - Commit string - Date string + Version string `json:"Version,omitempty"` + Commit string `json:"Commit,omitempty"` + Date string `json:"Date,omitempty"` } // New will create a pointer to a new version object @@ -28,7 +28,29 @@ func (v *Info) ToJSON() string { } // ToShortened converts the Info into a JSON String -func (v *Info) ToShortened() string { - str := fmt.Sprintf("Version: %v\nCommit: %v\nDate: %v\n", v.Version, v.Commit, v.Date) - return str +func (v *Info) ToShortened() (str string) { + var version, commit, date string + if v.Version != "" { + version = "Version: " + v.Version + } + if v.Commit != "" { + commit = "Commit: " + v.Commit + } + if v.Date != "" { + date = "Date: " + v.Date + } + values := []string{version, commit, date} + values = deleteEmpty(values) + str = strings.Join(values, "\n") + return str + "\n" +} + +func deleteEmpty(s []string) []string { + var r []string + for _, str := range s { + if str != "" { + r = append(r, str) + } + } + return r } diff --git a/vendor/github.com/christopherhein/operator-kit/Gopkg.lock b/vendor/github.com/christopherhein/operator-kit/Gopkg.lock index 0b5a39e3c..550d491cd 100644 --- a/vendor/github.com/christopherhein/operator-kit/Gopkg.lock +++ b/vendor/github.com/christopherhein/operator-kit/Gopkg.lock @@ -2,133 +2,226 @@ [[projects]] + digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b" name = "github.com/davecgh/go-spew" packages = ["spew"] + pruneopts = "" revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" [[projects]] + digest = "1:b13707423743d41665fd23f0c36b2f37bb49c30e94adb813319c44188a51ba22" name = "github.com/ghodss/yaml" packages = ["."] + pruneopts = "" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] + digest = "1:0a3f6a0c68ab8f3d455f8892295503b179e571b7fefe47cc6c556405d1f83411" name = "github.com/gogo/protobuf" packages = [ "proto", - "sortkeys" + "sortkeys", ] + pruneopts = "" revision = "1adfc126b41513cc696b209667c8656ea7aac67c" version = "v1.0.0" [[projects]] branch = "master" + digest = "1:107b233e45174dbab5b1324201d092ea9448e58243ab9f039e4c0f332e121e3a" name = "github.com/golang/glog" packages = ["."] + pruneopts = "" revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" [[projects]] + digest = "1:f958a1c137db276e52f0b50efee41a1a389dcdded59a69711f3e872757dab34b" name = "github.com/golang/protobuf" packages = [ "proto", "ptypes", "ptypes/any", "ptypes/duration", - "ptypes/timestamp" + "ptypes/timestamp", ] + pruneopts = "" revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" version = "v1.1.0" [[projects]] branch = "master" + digest = "1:1e5b1e14524ed08301977b7b8e10c719ed853cbf3f24ecb66fae783a46f207a6" + name = "github.com/google/btree" + packages = ["."] + pruneopts = "" + revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306" + +[[projects]] + branch = "master" + digest = "1:754f77e9c839b24778a4b64422236d38515301d2baeb63113aa3edc42e6af692" name = "github.com/google/gofuzz" packages = ["."] + pruneopts = "" revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" [[projects]] + digest = "1:16b2837c8b3cf045fa2cdc82af0cf78b19582701394484ae76b2c3bc3c99ad73" name = "github.com/googleapis/gnostic" packages = [ "OpenAPIv2", "compiler", - "extensions" + "extensions", ] + pruneopts = "" revision = "7c663266750e7d82587642f65e60bc4083f1f84e" version = "v0.2.0" [[projects]] branch = "master" + digest = "1:009a1928b8c096338b68b5822d838a72b4d8520715c1463614476359f3282ec8" + name = "github.com/gregjones/httpcache" + packages = [ + ".", + "diskcache", + ] + pruneopts = "" + revision = "9cad4c3443a7200dd6400aef47183728de563a38" + +[[projects]] + branch = "master" + digest = "1:9c776d7d9c54b7ed89f119e449983c3f24c0023e75001d6092442412ebca6b94" name = "github.com/hashicorp/golang-lru" packages = [ ".", - "simplelru" + "simplelru", ] + pruneopts = "" revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3" [[projects]] + digest = "1:7ab38c15bd21e056e3115c8b526d201eaf74e0308da9370997c6b3c187115d36" + name = "github.com/imdario/mergo" + packages = ["."] + pruneopts = "" + revision = "9f23e2d6bd2a77f959b2bf6acdbefd708a83a4a4" + version = "v0.3.6" + +[[projects]] + digest = "1:9eab2325abbed0ebcee9d44bb3660a69d5d10e42d5ac4a0e77f7a6ea22bfce88" name = "github.com/json-iterator/go" packages = ["."] + pruneopts = "" revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4" version = "1.1.3" [[projects]] + digest = "1:0c0ff2a89c1bb0d01887e1dac043ad7efbf3ec77482ef058ac423d13497e16fd" name = "github.com/modern-go/concurrent" packages = ["."] + pruneopts = "" revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" version = "1.0.3" [[projects]] + digest = "1:420f9231f816eeca3ff5aab070caac3ed7f27e4d37ded96ce9de3d7a7a2e31ad" name = "github.com/modern-go/reflect2" packages = ["."] + pruneopts = "" revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f" version = "1.0.0" [[projects]] + branch = "master" + digest = "1:c24598ffeadd2762552269271b3b1510df2d83ee6696c1e543a0ff653af494bc" + name = "github.com/petar/GoLLRB" + packages = ["llrb"] + pruneopts = "" + revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" + +[[projects]] + digest = "1:b46305723171710475f2dd37547edd57b67b9de9f2a6267cafdd98331fd6897f" + name = "github.com/peterbourgon/diskv" + packages = ["."] + pruneopts = "" + revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" + version = "v2.0.1" + +[[projects]] + digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411" name = "github.com/pmezard/go-difflib" packages = ["difflib"] + pruneopts = "" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] + branch = "master" + digest = "1:cf0a45e8ad5f10d0351ed4e74478504b28cb18625101d0fe895a56a5cbc21483" + name = "github.com/rook/operator-kit" + packages = [ + ".", + "sample-operator/pkg/apis/myproject/v1alpha1", + "sample-operator/pkg/client/clientset/versioned", + "sample-operator/pkg/client/clientset/versioned/scheme", + "sample-operator/pkg/client/clientset/versioned/typed/myproject/v1alpha1", + "sample-operator/pkg/client/clientset/versioned/typed/myproject/v1alpha1/fake", + ] + pruneopts = "" + revision = "36b0c11f5765bf475052768bb0ee7e685cad5606" + +[[projects]] + digest = "1:8e243c568f36b09031ec18dff5f7d2769dcf5ca4d624ea511c8e3197dc3d352d" name = "github.com/spf13/pflag" packages = ["."] + pruneopts = "" revision = "583c0c0531f06d5278b7d917446061adc344b5cd" version = "v1.0.1" [[projects]] + digest = "1:c587772fb8ad29ad4db67575dad25ba17a51f072ff18a22b4f0257a4d9c24f75" name = "github.com/stretchr/testify" packages = ["assert"] + pruneopts = "" revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" version = "v1.2.2" [[projects]] branch = "master" + digest = "1:6ef14be530be39b6b9d75d54ce1d546ae9231e652d9e3eef198cbb19ce8ed3e7" name = "golang.org/x/crypto" packages = ["ssh/terminal"] + pruneopts = "" revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" [[projects]] branch = "master" + digest = "1:4656104e65eed39be4ad82d1c2d31ccb391ba51817ccfbb6140562b141392b71" name = "golang.org/x/net" packages = [ "context", "http/httpguts", "http2", "http2/hpack", - "idna" + "idna", ] + pruneopts = "" revision = "afe8f62b1d6bbd81f31868121a50b06d8188e1f9" [[projects]] branch = "master" + digest = "1:60c3915cfa691dc713534798a10a8893a425c4ab8c569aeca2bd4a51ae81638c" name = "golang.org/x/sys" packages = [ "unix", - "windows" + "windows", ] + pruneopts = "" revision = "63fc586f45fe72d95d5240a5d5eb95e6503907d3" [[projects]] + digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4" name = "golang.org/x/text" packages = [ "collate", @@ -144,41 +237,50 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable" + "unicode/rangetable", ] + pruneopts = "" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" + digest = "1:55a681cb66f28755765fa5fa5104cbd8dc85c55c02d206f9f89566451e3fe1aa" name = "golang.org/x/time" packages = ["rate"] + pruneopts = "" revision = "fbb02b2291d28baffd63558aa44b4b56f178d650" [[projects]] branch = "master" + digest = "1:cddd9fefc3e3d7e08c25df4566b40899b955f1a636dfc7587770eee774481561" name = "golang.org/x/tools" packages = [ "go/ast/astutil", "imports", - "internal/fastwalk" + "internal/fastwalk", ] + pruneopts = "" revision = "25b95b48224cce18163c7d49dcfb89a2d5ecd209" [[projects]] + digest = "1:75fb3fcfc73a8c723efde7777b40e8e8ff9babf30d8c56160d01beffea8a95a6" name = "gopkg.in/inf.v0" packages = ["."] + pruneopts = "" revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" version = "v0.9.1" [[projects]] + digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2" name = "gopkg.in/yaml.v2" packages = ["."] + pruneopts = "" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [[projects]] - branch = "release-1.10" + digest = "1:77c0f2ebdb247964329c2495dea64be895fcc22de75f0fd719f092b6f869af53" name = "k8s.io/api" packages = [ "admissionregistration/v1alpha1", @@ -205,14 +307,18 @@ "rbac/v1alpha1", "rbac/v1beta1", "scheduling/v1alpha1", + "scheduling/v1beta1", "settings/v1alpha1", "storage/v1", "storage/v1alpha1", - "storage/v1beta1" + "storage/v1beta1", ] - revision = "8b7507fac302640dd5f1efbf9643199952cc58db" + pruneopts = "" + revision = "4e7be11eab3ffcfc1876898b8272df53785a9504" + version = "kubernetes-1.11.3" [[projects]] + digest = "1:f9f73d3b579f131a678448e39345e45f7e911f6ba75777a42df45e2e9995ad2b" name = "k8s.io/apiextensions-apiserver" packages = [ "pkg/apis/apiextensions", @@ -221,12 +327,14 @@ "pkg/client/clientset/clientset/fake", "pkg/client/clientset/clientset/scheme", "pkg/client/clientset/clientset/typed/apiextensions/v1beta1", - "pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake" + "pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake", ] - revision = "8e7f43002fec5394a8d96ebca781aa9d4b37aaef" - version = "kubernetes-1.10.4" + pruneopts = "" + revision = "b05d9bb7cc74a62c5daac9cef31894343e5d2c9b" + version = "kubernetes-1.11.3" [[projects]] + digest = "1:36e48db24a383a02683a57b7a48d5c3e8937b1f5a71ccfb7e52ee5d77d796147" name = "k8s.io/apimachinery" packages = [ "pkg/api/errors", @@ -257,21 +365,26 @@ "pkg/util/framer", "pkg/util/intstr", "pkg/util/json", + "pkg/util/mergepatch", "pkg/util/net", "pkg/util/runtime", "pkg/util/sets", + "pkg/util/strategicpatch", "pkg/util/validation", "pkg/util/validation/field", "pkg/util/wait", "pkg/util/yaml", "pkg/version", "pkg/watch", - "third_party/forked/golang/reflect" + "third_party/forked/golang/json", + "third_party/forked/golang/reflect", ] - revision = "17529ec7eadb8de8e7dc835201455f53571f655a" - version = "kubernetes-1.10.4" + pruneopts = "" + revision = "def12e63c512da17043b4f0293f52d1006603d9f" + version = "kubernetes-1.11.3" [[projects]] + digest = "1:d04779a8de7d5465e0463bd986506348de5e89677c74777f695d3145a7a8d15e" name = "k8s.io/client-go" packages = [ "discovery", @@ -327,6 +440,8 @@ "kubernetes/typed/rbac/v1beta1/fake", "kubernetes/typed/scheduling/v1alpha1", "kubernetes/typed/scheduling/v1alpha1/fake", + "kubernetes/typed/scheduling/v1beta1", + "kubernetes/typed/scheduling/v1beta1/fake", "kubernetes/typed/settings/v1alpha1", "kubernetes/typed/settings/v1alpha1/fake", "kubernetes/typed/storage/v1", @@ -337,28 +452,36 @@ "kubernetes/typed/storage/v1beta1/fake", "pkg/apis/clientauthentication", "pkg/apis/clientauthentication/v1alpha1", + "pkg/apis/clientauthentication/v1beta1", "pkg/version", "plugin/pkg/client/auth/exec", "rest", "rest/watch", "testing", + "tools/auth", "tools/cache", + "tools/clientcmd", "tools/clientcmd/api", + "tools/clientcmd/api/latest", + "tools/clientcmd/api/v1", "tools/metrics", "tools/pager", "tools/reference", "transport", "util/buffer", "util/cert", + "util/connrotation", "util/flowcontrol", + "util/homedir", "util/integer", - "util/retry" + "util/retry", ] - revision = "23781f4d6632d88e869066eaebb743857aa1ef9b" - version = "v7.0.0" + pruneopts = "" + revision = "7d04d0e2a0a1a4d4a1cd6baa432a2301492e4e65" + version = "v8.0.0" [[projects]] - branch = "release-1.10" + digest = "1:3b981f69134219063c9fe062302d777a99c784d8ef3ee0f40fe191717d2f4541" name = "k8s.io/code-generator" packages = [ "cmd/client-gen", @@ -369,31 +492,79 @@ "cmd/client-gen/generators/util", "cmd/client-gen/path", "cmd/client-gen/types", - "pkg/util" + "pkg/util", ] - revision = "9de8e796a74d16d2a285165727d04c185ebca6dc" + pruneopts = "" + revision = "8c97d6ab64da020f8b151e9d3ed8af3172f5c390" + version = "kubernetes-1.11.3" [[projects]] branch = "master" + digest = "1:d1e2c209e5b2a0fee08e687a43e63f81767817b7dd8a42af7667e5d58bf6844a" name = "k8s.io/gengo" packages = [ "args", "generator", "namer", "parser", - "types" + "types", ] + pruneopts = "" revision = "f659ec9d5207b3bf034eb9b7e22720d360d28712" [[projects]] + branch = "master" + digest = "1:7b06ff480fd71dead51f0f243b573c448c372ec086b790ec7ed4f8a78f2c1cbf" + name = "k8s.io/kube-openapi" + packages = ["pkg/util/proto"] + pruneopts = "" + revision = "9dfdf9be683f61f82cda12362c44c784e0778b56" + +[[projects]] + digest = "1:3d1deed8c48ccedf522fafc1b12b53f51ab9d343d989aacd8007fa9e4ae29cae" name = "k8s.io/kubernetes" packages = ["pkg/util/version"] - revision = "5ca598b4ba5abb89bb773071ce452e33fb66339d" - version = "v1.10.4" + pruneopts = "" + revision = "a4529464e4629c21224b3d52edfe0ea91b072862" + version = "v1.11.3" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "6c26d70893ab155c92037d35bfdd32c30f6778db1500adfd66e050c917b757a4" + input-imports = [ + "github.com/golang/glog", + "github.com/rook/operator-kit", + "github.com/rook/operator-kit/sample-operator/pkg/apis/myproject/v1alpha1", + "github.com/rook/operator-kit/sample-operator/pkg/client/clientset/versioned", + "github.com/rook/operator-kit/sample-operator/pkg/client/clientset/versioned/scheme", + "github.com/rook/operator-kit/sample-operator/pkg/client/clientset/versioned/typed/myproject/v1alpha1", + "github.com/rook/operator-kit/sample-operator/pkg/client/clientset/versioned/typed/myproject/v1alpha1/fake", + "github.com/stretchr/testify/assert", + "k8s.io/api/core/v1", + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1", + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset", + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake", + "k8s.io/apimachinery/pkg/api/errors", + "k8s.io/apimachinery/pkg/apis/meta/v1", + "k8s.io/apimachinery/pkg/fields", + "k8s.io/apimachinery/pkg/labels", + "k8s.io/apimachinery/pkg/runtime", + "k8s.io/apimachinery/pkg/runtime/schema", + "k8s.io/apimachinery/pkg/runtime/serializer", + "k8s.io/apimachinery/pkg/types", + "k8s.io/apimachinery/pkg/util/wait", + "k8s.io/apimachinery/pkg/watch", + "k8s.io/client-go/discovery", + "k8s.io/client-go/discovery/fake", + "k8s.io/client-go/kubernetes", + "k8s.io/client-go/kubernetes/fake", + "k8s.io/client-go/rest", + "k8s.io/client-go/testing", + "k8s.io/client-go/tools/cache", + "k8s.io/client-go/tools/clientcmd", + "k8s.io/client-go/util/flowcontrol", + "k8s.io/code-generator/cmd/client-gen", + "k8s.io/kubernetes/pkg/util/version", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/christopherhein/operator-kit/Gopkg.toml b/vendor/github.com/christopherhein/operator-kit/Gopkg.toml index 9eff06f89..97a998210 100644 --- a/vendor/github.com/christopherhein/operator-kit/Gopkg.toml +++ b/vendor/github.com/christopherhein/operator-kit/Gopkg.toml @@ -26,29 +26,29 @@ required = ["k8s.io/code-generator/cmd/client-gen"] [[constraint]] name = "k8s.io/kubernetes" - version = "=v1.10.4" + version = "=v1.11.3" [[constraint]] name = "k8s.io/api" - version = "kubernetes-1.10.4" + version = "kubernetes-1.11.3" [[constraint]] name = "k8s.io/apiextensions-apiserver" - version = "kubernetes-1.10.4" + version = "kubernetes-1.11.3" [[constraint]] name = "k8s.io/apimachinery" - version = "kubernetes-1.10.4" + version = "kubernetes-1.11.3" [[constraint]] name = "k8s.io/apiserver" - version = "kubernetes-1.10.4" + version = "kubernetes-1.11.3" [[constraint]] name = "k8s.io/client-go" - version = "v7.0.0" + version = "v8.0.0" [[constraint]] name = "k8s.io/code-generator" - version = "kubernetes-1.10.4" + version = "kubernetes-1.11.3" diff --git a/vendor/github.com/christopherhein/operator-kit/sample-operator/main.go b/vendor/github.com/christopherhein/operator-kit/sample-operator/main.go index adee7de91..ce8ad41ea 100644 --- a/vendor/github.com/christopherhein/operator-kit/sample-operator/main.go +++ b/vendor/github.com/christopherhein/operator-kit/sample-operator/main.go @@ -89,7 +89,7 @@ func getClientConfig(kubeconfig string) (*rest.Config, error) { func createContext(kubeconfig string) (*opkit.Context, sampleclient.MyprojectV1alpha1Interface, error) { config, err := getClientConfig(kubeconfig) if err != nil { - return nil, nil, fmt.Errorf("failed to get k8s local config. %+v", err) + return nil, nil, fmt.Errorf("failed to get k8s config. %+v", err) } clientset, err := kubernetes.NewForConfig(config) diff --git a/vendor/github.com/golang/groupcache/.gitignore b/vendor/github.com/golang/groupcache/.gitignore new file mode 100644 index 000000000..b25c15b81 --- /dev/null +++ b/vendor/github.com/golang/groupcache/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/vendor/github.com/golang/groupcache/.travis.yml b/vendor/github.com/golang/groupcache/.travis.yml new file mode 100644 index 000000000..ef6e67633 --- /dev/null +++ b/vendor/github.com/golang/groupcache/.travis.yml @@ -0,0 +1,18 @@ +language: go +go_import_path: github.com/golang/groupcache + +os: linux +dist: trusty +sudo: false + +script: + - go test ./... + +go: + - 1.9.x + - 1.10.x + - master + +cache: + directories: + - $GOPATH/pkg diff --git a/vendor/github.com/golang/groupcache/LICENSE b/vendor/github.com/golang/groupcache/LICENSE new file mode 100644 index 000000000..37ec93a14 --- /dev/null +++ b/vendor/github.com/golang/groupcache/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/golang/groupcache/README.md b/vendor/github.com/golang/groupcache/README.md new file mode 100644 index 000000000..70c29da16 --- /dev/null +++ b/vendor/github.com/golang/groupcache/README.md @@ -0,0 +1,73 @@ +# groupcache + +## Summary + +groupcache is a caching and cache-filling library, intended as a +replacement for memcached in many cases. + +For API docs and examples, see http://godoc.org/github.com/golang/groupcache + +## Comparison to memcached + +### **Like memcached**, groupcache: + + * shards by key to select which peer is responsible for that key + +### **Unlike memcached**, groupcache: + + * does not require running a separate set of servers, thus massively + reducing deployment/configuration pain. groupcache is a client + library as well as a server. It connects to its own peers. + + * comes with a cache filling mechanism. Whereas memcached just says + "Sorry, cache miss", often resulting in a thundering herd of + database (or whatever) loads from an unbounded number of clients + (which has resulted in several fun outages), groupcache coordinates + cache fills such that only one load in one process of an entire + replicated set of processes populates the cache, then multiplexes + the loaded value to all callers. + + * does not support versioned values. If key "foo" is value "bar", + key "foo" must always be "bar". There are neither cache expiration + times, nor explicit cache evictions. Thus there is also no CAS, + nor Increment/Decrement. This also means that groupcache.... + + * ... supports automatic mirroring of super-hot items to multiple + processes. This prevents memcached hot spotting where a machine's + CPU and/or NIC are overloaded by very popular keys/values. + + * is currently only available for Go. It's very unlikely that I + (bradfitz@) will port the code to any other language. + +## Loading process + +In a nutshell, a groupcache lookup of **Get("foo")** looks like: + +(On machine #5 of a set of N machines running the same code) + + 1. Is the value of "foo" in local memory because it's super hot? If so, use it. + + 2. Is the value of "foo" in local memory because peer #5 (the current + peer) is the owner of it? If so, use it. + + 3. Amongst all the peers in my set of N, am I the owner of the key + "foo"? (e.g. does it consistent hash to 5?) If so, load it. If + other callers come in, via the same process or via RPC requests + from peers, they block waiting for the load to finish and get the + same answer. If not, RPC to the peer that's the owner and get + the answer. If the RPC fails, just load it locally (still with + local dup suppression). + +## Users + +groupcache is in production use by dl.google.com (its original user), +parts of Blogger, parts of Google Code, parts of Google Fiber, parts +of Google production monitoring systems, etc. + +## Presentations + +See http://talks.golang.org/2013/oscon-dl.slide + +## Help + +Use the golang-nuts mailing list for any discussion or questions. diff --git a/vendor/github.com/golang/groupcache/byteview.go b/vendor/github.com/golang/groupcache/byteview.go new file mode 100644 index 000000000..a2c2c493d --- /dev/null +++ b/vendor/github.com/golang/groupcache/byteview.go @@ -0,0 +1,175 @@ +/* +Copyright 2012 Google Inc. + +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 groupcache + +import ( + "bytes" + "errors" + "io" + "strings" +) + +// A ByteView holds an immutable view of bytes. +// Internally it wraps either a []byte or a string, +// but that detail is invisible to callers. +// +// A ByteView is meant to be used as a value type, not +// a pointer (like a time.Time). +type ByteView struct { + // If b is non-nil, b is used, else s is used. + b []byte + s string +} + +// Len returns the view's length. +func (v ByteView) Len() int { + if v.b != nil { + return len(v.b) + } + return len(v.s) +} + +// ByteSlice returns a copy of the data as a byte slice. +func (v ByteView) ByteSlice() []byte { + if v.b != nil { + return cloneBytes(v.b) + } + return []byte(v.s) +} + +// String returns the data as a string, making a copy if necessary. +func (v ByteView) String() string { + if v.b != nil { + return string(v.b) + } + return v.s +} + +// At returns the byte at index i. +func (v ByteView) At(i int) byte { + if v.b != nil { + return v.b[i] + } + return v.s[i] +} + +// Slice slices the view between the provided from and to indices. +func (v ByteView) Slice(from, to int) ByteView { + if v.b != nil { + return ByteView{b: v.b[from:to]} + } + return ByteView{s: v.s[from:to]} +} + +// SliceFrom slices the view from the provided index until the end. +func (v ByteView) SliceFrom(from int) ByteView { + if v.b != nil { + return ByteView{b: v.b[from:]} + } + return ByteView{s: v.s[from:]} +} + +// Copy copies b into dest and returns the number of bytes copied. +func (v ByteView) Copy(dest []byte) int { + if v.b != nil { + return copy(dest, v.b) + } + return copy(dest, v.s) +} + +// Equal returns whether the bytes in b are the same as the bytes in +// b2. +func (v ByteView) Equal(b2 ByteView) bool { + if b2.b == nil { + return v.EqualString(b2.s) + } + return v.EqualBytes(b2.b) +} + +// EqualString returns whether the bytes in b are the same as the bytes +// in s. +func (v ByteView) EqualString(s string) bool { + if v.b == nil { + return v.s == s + } + l := v.Len() + if len(s) != l { + return false + } + for i, bi := range v.b { + if bi != s[i] { + return false + } + } + return true +} + +// EqualBytes returns whether the bytes in b are the same as the bytes +// in b2. +func (v ByteView) EqualBytes(b2 []byte) bool { + if v.b != nil { + return bytes.Equal(v.b, b2) + } + l := v.Len() + if len(b2) != l { + return false + } + for i, bi := range b2 { + if bi != v.s[i] { + return false + } + } + return true +} + +// Reader returns an io.ReadSeeker for the bytes in v. +func (v ByteView) Reader() io.ReadSeeker { + if v.b != nil { + return bytes.NewReader(v.b) + } + return strings.NewReader(v.s) +} + +// ReadAt implements io.ReaderAt on the bytes in v. +func (v ByteView) ReadAt(p []byte, off int64) (n int, err error) { + if off < 0 { + return 0, errors.New("view: invalid offset") + } + if off >= int64(v.Len()) { + return 0, io.EOF + } + n = v.SliceFrom(int(off)).Copy(p) + if n < len(p) { + err = io.EOF + } + return +} + +// WriteTo implements io.WriterTo on the bytes in v. +func (v ByteView) WriteTo(w io.Writer) (n int64, err error) { + var m int + if v.b != nil { + m, err = w.Write(v.b) + } else { + m, err = io.WriteString(w, v.s) + } + if err == nil && m < v.Len() { + err = io.ErrShortWrite + } + n = int64(m) + return +} diff --git a/vendor/github.com/golang/groupcache/byteview_test.go b/vendor/github.com/golang/groupcache/byteview_test.go new file mode 100644 index 000000000..a09757aa8 --- /dev/null +++ b/vendor/github.com/golang/groupcache/byteview_test.go @@ -0,0 +1,147 @@ +/* +Copyright 2012 Google Inc. + +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 groupcache + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "testing" +) + +func TestByteView(t *testing.T) { + for _, s := range []string{"", "x", "yy"} { + for _, v := range []ByteView{of([]byte(s)), of(s)} { + name := fmt.Sprintf("string %q, view %+v", s, v) + if v.Len() != len(s) { + t.Errorf("%s: Len = %d; want %d", name, v.Len(), len(s)) + } + if v.String() != s { + t.Errorf("%s: String = %q; want %q", name, v.String(), s) + } + var longDest [3]byte + if n := v.Copy(longDest[:]); n != len(s) { + t.Errorf("%s: long Copy = %d; want %d", name, n, len(s)) + } + var shortDest [1]byte + if n := v.Copy(shortDest[:]); n != min(len(s), 1) { + t.Errorf("%s: short Copy = %d; want %d", name, n, min(len(s), 1)) + } + if got, err := ioutil.ReadAll(v.Reader()); err != nil || string(got) != s { + t.Errorf("%s: Reader = %q, %v; want %q", name, got, err, s) + } + if got, err := ioutil.ReadAll(io.NewSectionReader(v, 0, int64(len(s)))); err != nil || string(got) != s { + t.Errorf("%s: SectionReader of ReaderAt = %q, %v; want %q", name, got, err, s) + } + var dest bytes.Buffer + if _, err := v.WriteTo(&dest); err != nil || !bytes.Equal(dest.Bytes(), []byte(s)) { + t.Errorf("%s: WriteTo = %q, %v; want %q", name, dest.Bytes(), err, s) + } + } + } +} + +// of returns a byte view of the []byte or string in x. +func of(x interface{}) ByteView { + if bytes, ok := x.([]byte); ok { + return ByteView{b: bytes} + } + return ByteView{s: x.(string)} +} + +func TestByteViewEqual(t *testing.T) { + tests := []struct { + a interface{} // string or []byte + b interface{} // string or []byte + want bool + }{ + {"x", "x", true}, + {"x", "y", false}, + {"x", "yy", false}, + {[]byte("x"), []byte("x"), true}, + {[]byte("x"), []byte("y"), false}, + {[]byte("x"), []byte("yy"), false}, + {[]byte("x"), "x", true}, + {[]byte("x"), "y", false}, + {[]byte("x"), "yy", false}, + {"x", []byte("x"), true}, + {"x", []byte("y"), false}, + {"x", []byte("yy"), false}, + } + for i, tt := range tests { + va := of(tt.a) + if bytes, ok := tt.b.([]byte); ok { + if got := va.EqualBytes(bytes); got != tt.want { + t.Errorf("%d. EqualBytes = %v; want %v", i, got, tt.want) + } + } else { + if got := va.EqualString(tt.b.(string)); got != tt.want { + t.Errorf("%d. EqualString = %v; want %v", i, got, tt.want) + } + } + if got := va.Equal(of(tt.b)); got != tt.want { + t.Errorf("%d. Equal = %v; want %v", i, got, tt.want) + } + } +} + +func TestByteViewSlice(t *testing.T) { + tests := []struct { + in string + from int + to interface{} // nil to mean the end (SliceFrom); else int + want string + }{ + { + in: "abc", + from: 1, + to: 2, + want: "b", + }, + { + in: "abc", + from: 1, + want: "bc", + }, + { + in: "abc", + to: 2, + want: "ab", + }, + } + for i, tt := range tests { + for _, v := range []ByteView{of([]byte(tt.in)), of(tt.in)} { + name := fmt.Sprintf("test %d, view %+v", i, v) + if tt.to != nil { + v = v.Slice(tt.from, tt.to.(int)) + } else { + v = v.SliceFrom(tt.from) + } + if v.String() != tt.want { + t.Errorf("%s: got %q; want %q", name, v.String(), tt.want) + } + } + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/vendor/github.com/golang/groupcache/consistenthash/consistenthash.go b/vendor/github.com/golang/groupcache/consistenthash/consistenthash.go new file mode 100644 index 000000000..a9c56f076 --- /dev/null +++ b/vendor/github.com/golang/groupcache/consistenthash/consistenthash.go @@ -0,0 +1,81 @@ +/* +Copyright 2013 Google Inc. + +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 consistenthash provides an implementation of a ring hash. +package consistenthash + +import ( + "hash/crc32" + "sort" + "strconv" +) + +type Hash func(data []byte) uint32 + +type Map struct { + hash Hash + replicas int + keys []int // Sorted + hashMap map[int]string +} + +func New(replicas int, fn Hash) *Map { + m := &Map{ + replicas: replicas, + hash: fn, + hashMap: make(map[int]string), + } + if m.hash == nil { + m.hash = crc32.ChecksumIEEE + } + return m +} + +// Returns true if there are no items available. +func (m *Map) IsEmpty() bool { + return len(m.keys) == 0 +} + +// Adds some keys to the hash. +func (m *Map) Add(keys ...string) { + for _, key := range keys { + for i := 0; i < m.replicas; i++ { + hash := int(m.hash([]byte(strconv.Itoa(i) + key))) + m.keys = append(m.keys, hash) + m.hashMap[hash] = key + } + } + sort.Ints(m.keys) +} + +// Gets the closest item in the hash to the provided key. +func (m *Map) Get(key string) string { + if m.IsEmpty() { + return "" + } + + hash := int(m.hash([]byte(key))) + + // Binary search for appropriate replica. + idx := sort.Search(len(m.keys), func(i int) bool { return m.keys[i] >= hash }) + + // Means we have cycled back to the first replica. + if idx == len(m.keys) { + idx = 0 + } + + return m.hashMap[m.keys[idx]] +} diff --git a/vendor/github.com/golang/groupcache/consistenthash/consistenthash_test.go b/vendor/github.com/golang/groupcache/consistenthash/consistenthash_test.go new file mode 100644 index 000000000..1a37fd7ff --- /dev/null +++ b/vendor/github.com/golang/groupcache/consistenthash/consistenthash_test.go @@ -0,0 +1,110 @@ +/* +Copyright 2013 Google Inc. + +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 consistenthash + +import ( + "fmt" + "strconv" + "testing" +) + +func TestHashing(t *testing.T) { + + // Override the hash function to return easier to reason about values. Assumes + // the keys can be converted to an integer. + hash := New(3, func(key []byte) uint32 { + i, err := strconv.Atoi(string(key)) + if err != nil { + panic(err) + } + return uint32(i) + }) + + // Given the above hash function, this will give replicas with "hashes": + // 2, 4, 6, 12, 14, 16, 22, 24, 26 + hash.Add("6", "4", "2") + + testCases := map[string]string{ + "2": "2", + "11": "2", + "23": "4", + "27": "2", + } + + for k, v := range testCases { + if hash.Get(k) != v { + t.Errorf("Asking for %s, should have yielded %s", k, v) + } + } + + // Adds 8, 18, 28 + hash.Add("8") + + // 27 should now map to 8. + testCases["27"] = "8" + + for k, v := range testCases { + if hash.Get(k) != v { + t.Errorf("Asking for %s, should have yielded %s", k, v) + } + } + +} + +func TestConsistency(t *testing.T) { + hash1 := New(1, nil) + hash2 := New(1, nil) + + hash1.Add("Bill", "Bob", "Bonny") + hash2.Add("Bob", "Bonny", "Bill") + + if hash1.Get("Ben") != hash2.Get("Ben") { + t.Errorf("Fetching 'Ben' from both hashes should be the same") + } + + hash2.Add("Becky", "Ben", "Bobby") + + if hash1.Get("Ben") != hash2.Get("Ben") || + hash1.Get("Bob") != hash2.Get("Bob") || + hash1.Get("Bonny") != hash2.Get("Bonny") { + t.Errorf("Direct matches should always return the same entry") + } + +} + +func BenchmarkGet8(b *testing.B) { benchmarkGet(b, 8) } +func BenchmarkGet32(b *testing.B) { benchmarkGet(b, 32) } +func BenchmarkGet128(b *testing.B) { benchmarkGet(b, 128) } +func BenchmarkGet512(b *testing.B) { benchmarkGet(b, 512) } + +func benchmarkGet(b *testing.B, shards int) { + + hash := New(50, nil) + + var buckets []string + for i := 0; i < shards; i++ { + buckets = append(buckets, fmt.Sprintf("shard-%d", i)) + } + + hash.Add(buckets...) + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + hash.Get(buckets[i&(shards-1)]) + } +} diff --git a/vendor/github.com/golang/groupcache/groupcache.go b/vendor/github.com/golang/groupcache/groupcache.go new file mode 100644 index 000000000..316ca4940 --- /dev/null +++ b/vendor/github.com/golang/groupcache/groupcache.go @@ -0,0 +1,491 @@ +/* +Copyright 2012 Google Inc. + +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 groupcache provides a data loading mechanism with caching +// and de-duplication that works across a set of peer processes. +// +// Each data Get first consults its local cache, otherwise delegates +// to the requested key's canonical owner, which then checks its cache +// or finally gets the data. In the common case, many concurrent +// cache misses across a set of peers for the same key result in just +// one cache fill. +package groupcache + +import ( + "errors" + "math/rand" + "strconv" + "sync" + "sync/atomic" + + pb "github.com/golang/groupcache/groupcachepb" + "github.com/golang/groupcache/lru" + "github.com/golang/groupcache/singleflight" +) + +// A Getter loads data for a key. +type Getter interface { + // Get returns the value identified by key, populating dest. + // + // The returned data must be unversioned. That is, key must + // uniquely describe the loaded data, without an implicit + // current time, and without relying on cache expiration + // mechanisms. + Get(ctx Context, key string, dest Sink) error +} + +// A GetterFunc implements Getter with a function. +type GetterFunc func(ctx Context, key string, dest Sink) error + +func (f GetterFunc) Get(ctx Context, key string, dest Sink) error { + return f(ctx, key, dest) +} + +var ( + mu sync.RWMutex + groups = make(map[string]*Group) + + initPeerServerOnce sync.Once + initPeerServer func() +) + +// GetGroup returns the named group previously created with NewGroup, or +// nil if there's no such group. +func GetGroup(name string) *Group { + mu.RLock() + g := groups[name] + mu.RUnlock() + return g +} + +// NewGroup creates a coordinated group-aware Getter from a Getter. +// +// The returned Getter tries (but does not guarantee) to run only one +// Get call at once for a given key across an entire set of peer +// processes. Concurrent callers both in the local process and in +// other processes receive copies of the answer once the original Get +// completes. +// +// The group name must be unique for each getter. +func NewGroup(name string, cacheBytes int64, getter Getter) *Group { + return newGroup(name, cacheBytes, getter, nil) +} + +// If peers is nil, the peerPicker is called via a sync.Once to initialize it. +func newGroup(name string, cacheBytes int64, getter Getter, peers PeerPicker) *Group { + if getter == nil { + panic("nil Getter") + } + mu.Lock() + defer mu.Unlock() + initPeerServerOnce.Do(callInitPeerServer) + if _, dup := groups[name]; dup { + panic("duplicate registration of group " + name) + } + g := &Group{ + name: name, + getter: getter, + peers: peers, + cacheBytes: cacheBytes, + loadGroup: &singleflight.Group{}, + } + if fn := newGroupHook; fn != nil { + fn(g) + } + groups[name] = g + return g +} + +// newGroupHook, if non-nil, is called right after a new group is created. +var newGroupHook func(*Group) + +// RegisterNewGroupHook registers a hook that is run each time +// a group is created. +func RegisterNewGroupHook(fn func(*Group)) { + if newGroupHook != nil { + panic("RegisterNewGroupHook called more than once") + } + newGroupHook = fn +} + +// RegisterServerStart registers a hook that is run when the first +// group is created. +func RegisterServerStart(fn func()) { + if initPeerServer != nil { + panic("RegisterServerStart called more than once") + } + initPeerServer = fn +} + +func callInitPeerServer() { + if initPeerServer != nil { + initPeerServer() + } +} + +// A Group is a cache namespace and associated data loaded spread over +// a group of 1 or more machines. +type Group struct { + name string + getter Getter + peersOnce sync.Once + peers PeerPicker + cacheBytes int64 // limit for sum of mainCache and hotCache size + + // mainCache is a cache of the keys for which this process + // (amongst its peers) is authoritative. That is, this cache + // contains keys which consistent hash on to this process's + // peer number. + mainCache cache + + // hotCache contains keys/values for which this peer is not + // authoritative (otherwise they would be in mainCache), but + // are popular enough to warrant mirroring in this process to + // avoid going over the network to fetch from a peer. Having + // a hotCache avoids network hotspotting, where a peer's + // network card could become the bottleneck on a popular key. + // This cache is used sparingly to maximize the total number + // of key/value pairs that can be stored globally. + hotCache cache + + // loadGroup ensures that each key is only fetched once + // (either locally or remotely), regardless of the number of + // concurrent callers. + loadGroup flightGroup + + _ int32 // force Stats to be 8-byte aligned on 32-bit platforms + + // Stats are statistics on the group. + Stats Stats +} + +// flightGroup is defined as an interface which flightgroup.Group +// satisfies. We define this so that we may test with an alternate +// implementation. +type flightGroup interface { + // Done is called when Do is done. + Do(key string, fn func() (interface{}, error)) (interface{}, error) +} + +// Stats are per-group statistics. +type Stats struct { + Gets AtomicInt // any Get request, including from peers + CacheHits AtomicInt // either cache was good + PeerLoads AtomicInt // either remote load or remote cache hit (not an error) + PeerErrors AtomicInt + Loads AtomicInt // (gets - cacheHits) + LoadsDeduped AtomicInt // after singleflight + LocalLoads AtomicInt // total good local loads + LocalLoadErrs AtomicInt // total bad local loads + ServerRequests AtomicInt // gets that came over the network from peers +} + +// Name returns the name of the group. +func (g *Group) Name() string { + return g.name +} + +func (g *Group) initPeers() { + if g.peers == nil { + g.peers = getPeers(g.name) + } +} + +func (g *Group) Get(ctx Context, key string, dest Sink) error { + g.peersOnce.Do(g.initPeers) + g.Stats.Gets.Add(1) + if dest == nil { + return errors.New("groupcache: nil dest Sink") + } + value, cacheHit := g.lookupCache(key) + + if cacheHit { + g.Stats.CacheHits.Add(1) + return setSinkView(dest, value) + } + + // Optimization to avoid double unmarshalling or copying: keep + // track of whether the dest was already populated. One caller + // (if local) will set this; the losers will not. The common + // case will likely be one caller. + destPopulated := false + value, destPopulated, err := g.load(ctx, key, dest) + if err != nil { + return err + } + if destPopulated { + return nil + } + return setSinkView(dest, value) +} + +// load loads key either by invoking the getter locally or by sending it to another machine. +func (g *Group) load(ctx Context, key string, dest Sink) (value ByteView, destPopulated bool, err error) { + g.Stats.Loads.Add(1) + viewi, err := g.loadGroup.Do(key, func() (interface{}, error) { + // Check the cache again because singleflight can only dedup calls + // that overlap concurrently. It's possible for 2 concurrent + // requests to miss the cache, resulting in 2 load() calls. An + // unfortunate goroutine scheduling would result in this callback + // being run twice, serially. If we don't check the cache again, + // cache.nbytes would be incremented below even though there will + // be only one entry for this key. + // + // Consider the following serialized event ordering for two + // goroutines in which this callback gets called twice for hte + // same key: + // 1: Get("key") + // 2: Get("key") + // 1: lookupCache("key") + // 2: lookupCache("key") + // 1: load("key") + // 2: load("key") + // 1: loadGroup.Do("key", fn) + // 1: fn() + // 2: loadGroup.Do("key", fn) + // 2: fn() + if value, cacheHit := g.lookupCache(key); cacheHit { + g.Stats.CacheHits.Add(1) + return value, nil + } + g.Stats.LoadsDeduped.Add(1) + var value ByteView + var err error + if peer, ok := g.peers.PickPeer(key); ok { + value, err = g.getFromPeer(ctx, peer, key) + if err == nil { + g.Stats.PeerLoads.Add(1) + return value, nil + } + g.Stats.PeerErrors.Add(1) + // TODO(bradfitz): log the peer's error? keep + // log of the past few for /groupcachez? It's + // probably boring (normal task movement), so not + // worth logging I imagine. + } + value, err = g.getLocally(ctx, key, dest) + if err != nil { + g.Stats.LocalLoadErrs.Add(1) + return nil, err + } + g.Stats.LocalLoads.Add(1) + destPopulated = true // only one caller of load gets this return value + g.populateCache(key, value, &g.mainCache) + return value, nil + }) + if err == nil { + value = viewi.(ByteView) + } + return +} + +func (g *Group) getLocally(ctx Context, key string, dest Sink) (ByteView, error) { + err := g.getter.Get(ctx, key, dest) + if err != nil { + return ByteView{}, err + } + return dest.view() +} + +func (g *Group) getFromPeer(ctx Context, peer ProtoGetter, key string) (ByteView, error) { + req := &pb.GetRequest{ + Group: &g.name, + Key: &key, + } + res := &pb.GetResponse{} + err := peer.Get(ctx, req, res) + if err != nil { + return ByteView{}, err + } + value := ByteView{b: res.Value} + // TODO(bradfitz): use res.MinuteQps or something smart to + // conditionally populate hotCache. For now just do it some + // percentage of the time. + if rand.Intn(10) == 0 { + g.populateCache(key, value, &g.hotCache) + } + return value, nil +} + +func (g *Group) lookupCache(key string) (value ByteView, ok bool) { + if g.cacheBytes <= 0 { + return + } + value, ok = g.mainCache.get(key) + if ok { + return + } + value, ok = g.hotCache.get(key) + return +} + +func (g *Group) populateCache(key string, value ByteView, cache *cache) { + if g.cacheBytes <= 0 { + return + } + cache.add(key, value) + + // Evict items from cache(s) if necessary. + for { + mainBytes := g.mainCache.bytes() + hotBytes := g.hotCache.bytes() + if mainBytes+hotBytes <= g.cacheBytes { + return + } + + // TODO(bradfitz): this is good-enough-for-now logic. + // It should be something based on measurements and/or + // respecting the costs of different resources. + victim := &g.mainCache + if hotBytes > mainBytes/8 { + victim = &g.hotCache + } + victim.removeOldest() + } +} + +// CacheType represents a type of cache. +type CacheType int + +const ( + // The MainCache is the cache for items that this peer is the + // owner for. + MainCache CacheType = iota + 1 + + // The HotCache is the cache for items that seem popular + // enough to replicate to this node, even though it's not the + // owner. + HotCache +) + +// CacheStats returns stats about the provided cache within the group. +func (g *Group) CacheStats(which CacheType) CacheStats { + switch which { + case MainCache: + return g.mainCache.stats() + case HotCache: + return g.hotCache.stats() + default: + return CacheStats{} + } +} + +// cache is a wrapper around an *lru.Cache that adds synchronization, +// makes values always be ByteView, and counts the size of all keys and +// values. +type cache struct { + mu sync.RWMutex + nbytes int64 // of all keys and values + lru *lru.Cache + nhit, nget int64 + nevict int64 // number of evictions +} + +func (c *cache) stats() CacheStats { + c.mu.RLock() + defer c.mu.RUnlock() + return CacheStats{ + Bytes: c.nbytes, + Items: c.itemsLocked(), + Gets: c.nget, + Hits: c.nhit, + Evictions: c.nevict, + } +} + +func (c *cache) add(key string, value ByteView) { + c.mu.Lock() + defer c.mu.Unlock() + if c.lru == nil { + c.lru = &lru.Cache{ + OnEvicted: func(key lru.Key, value interface{}) { + val := value.(ByteView) + c.nbytes -= int64(len(key.(string))) + int64(val.Len()) + c.nevict++ + }, + } + } + c.lru.Add(key, value) + c.nbytes += int64(len(key)) + int64(value.Len()) +} + +func (c *cache) get(key string) (value ByteView, ok bool) { + c.mu.Lock() + defer c.mu.Unlock() + c.nget++ + if c.lru == nil { + return + } + vi, ok := c.lru.Get(key) + if !ok { + return + } + c.nhit++ + return vi.(ByteView), true +} + +func (c *cache) removeOldest() { + c.mu.Lock() + defer c.mu.Unlock() + if c.lru != nil { + c.lru.RemoveOldest() + } +} + +func (c *cache) bytes() int64 { + c.mu.RLock() + defer c.mu.RUnlock() + return c.nbytes +} + +func (c *cache) items() int64 { + c.mu.RLock() + defer c.mu.RUnlock() + return c.itemsLocked() +} + +func (c *cache) itemsLocked() int64 { + if c.lru == nil { + return 0 + } + return int64(c.lru.Len()) +} + +// An AtomicInt is an int64 to be accessed atomically. +type AtomicInt int64 + +// Add atomically adds n to i. +func (i *AtomicInt) Add(n int64) { + atomic.AddInt64((*int64)(i), n) +} + +// Get atomically gets the value of i. +func (i *AtomicInt) Get() int64 { + return atomic.LoadInt64((*int64)(i)) +} + +func (i *AtomicInt) String() string { + return strconv.FormatInt(i.Get(), 10) +} + +// CacheStats are returned by stats accessors on Group. +type CacheStats struct { + Bytes int64 + Items int64 + Gets int64 + Hits int64 + Evictions int64 +} diff --git a/vendor/github.com/golang/groupcache/groupcache_test.go b/vendor/github.com/golang/groupcache/groupcache_test.go new file mode 100644 index 000000000..ea05cac4a --- /dev/null +++ b/vendor/github.com/golang/groupcache/groupcache_test.go @@ -0,0 +1,456 @@ +/* +Copyright 2012 Google Inc. + +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. +*/ + +// Tests for groupcache. + +package groupcache + +import ( + "errors" + "fmt" + "hash/crc32" + "math/rand" + "reflect" + "sync" + "testing" + "time" + "unsafe" + + "github.com/golang/protobuf/proto" + + pb "github.com/golang/groupcache/groupcachepb" + testpb "github.com/golang/groupcache/testpb" +) + +var ( + once sync.Once + stringGroup, protoGroup Getter + + stringc = make(chan string) + + dummyCtx Context + + // cacheFills is the number of times stringGroup or + // protoGroup's Getter have been called. Read using the + // cacheFills function. + cacheFills AtomicInt +) + +const ( + stringGroupName = "string-group" + protoGroupName = "proto-group" + testMessageType = "google3/net/groupcache/go/test_proto.TestMessage" + fromChan = "from-chan" + cacheSize = 1 << 20 +) + +func testSetup() { + stringGroup = NewGroup(stringGroupName, cacheSize, GetterFunc(func(_ Context, key string, dest Sink) error { + if key == fromChan { + key = <-stringc + } + cacheFills.Add(1) + return dest.SetString("ECHO:" + key) + })) + + protoGroup = NewGroup(protoGroupName, cacheSize, GetterFunc(func(_ Context, key string, dest Sink) error { + if key == fromChan { + key = <-stringc + } + cacheFills.Add(1) + return dest.SetProto(&testpb.TestMessage{ + Name: proto.String("ECHO:" + key), + City: proto.String("SOME-CITY"), + }) + })) +} + +// tests that a Getter's Get method is only called once with two +// outstanding callers. This is the string variant. +func TestGetDupSuppressString(t *testing.T) { + once.Do(testSetup) + // Start two getters. The first should block (waiting reading + // from stringc) and the second should latch on to the first + // one. + resc := make(chan string, 2) + for i := 0; i < 2; i++ { + go func() { + var s string + if err := stringGroup.Get(dummyCtx, fromChan, StringSink(&s)); err != nil { + resc <- "ERROR:" + err.Error() + return + } + resc <- s + }() + } + + // Wait a bit so both goroutines get merged together via + // singleflight. + // TODO(bradfitz): decide whether there are any non-offensive + // debug/test hooks that could be added to singleflight to + // make a sleep here unnecessary. + time.Sleep(250 * time.Millisecond) + + // Unblock the first getter, which should unblock the second + // as well. + stringc <- "foo" + + for i := 0; i < 2; i++ { + select { + case v := <-resc: + if v != "ECHO:foo" { + t.Errorf("got %q; want %q", v, "ECHO:foo") + } + case <-time.After(5 * time.Second): + t.Errorf("timeout waiting on getter #%d of 2", i+1) + } + } +} + +// tests that a Getter's Get method is only called once with two +// outstanding callers. This is the proto variant. +func TestGetDupSuppressProto(t *testing.T) { + once.Do(testSetup) + // Start two getters. The first should block (waiting reading + // from stringc) and the second should latch on to the first + // one. + resc := make(chan *testpb.TestMessage, 2) + for i := 0; i < 2; i++ { + go func() { + tm := new(testpb.TestMessage) + if err := protoGroup.Get(dummyCtx, fromChan, ProtoSink(tm)); err != nil { + tm.Name = proto.String("ERROR:" + err.Error()) + } + resc <- tm + }() + } + + // Wait a bit so both goroutines get merged together via + // singleflight. + // TODO(bradfitz): decide whether there are any non-offensive + // debug/test hooks that could be added to singleflight to + // make a sleep here unnecessary. + time.Sleep(250 * time.Millisecond) + + // Unblock the first getter, which should unblock the second + // as well. + stringc <- "Fluffy" + want := &testpb.TestMessage{ + Name: proto.String("ECHO:Fluffy"), + City: proto.String("SOME-CITY"), + } + for i := 0; i < 2; i++ { + select { + case v := <-resc: + if !reflect.DeepEqual(v, want) { + t.Errorf(" Got: %v\nWant: %v", proto.CompactTextString(v), proto.CompactTextString(want)) + } + case <-time.After(5 * time.Second): + t.Errorf("timeout waiting on getter #%d of 2", i+1) + } + } +} + +func countFills(f func()) int64 { + fills0 := cacheFills.Get() + f() + return cacheFills.Get() - fills0 +} + +func TestCaching(t *testing.T) { + once.Do(testSetup) + fills := countFills(func() { + for i := 0; i < 10; i++ { + var s string + if err := stringGroup.Get(dummyCtx, "TestCaching-key", StringSink(&s)); err != nil { + t.Fatal(err) + } + } + }) + if fills != 1 { + t.Errorf("expected 1 cache fill; got %d", fills) + } +} + +func TestCacheEviction(t *testing.T) { + once.Do(testSetup) + testKey := "TestCacheEviction-key" + getTestKey := func() { + var res string + for i := 0; i < 10; i++ { + if err := stringGroup.Get(dummyCtx, testKey, StringSink(&res)); err != nil { + t.Fatal(err) + } + } + } + fills := countFills(getTestKey) + if fills != 1 { + t.Fatalf("expected 1 cache fill; got %d", fills) + } + + g := stringGroup.(*Group) + evict0 := g.mainCache.nevict + + // Trash the cache with other keys. + var bytesFlooded int64 + // cacheSize/len(testKey) is approximate + for bytesFlooded < cacheSize+1024 { + var res string + key := fmt.Sprintf("dummy-key-%d", bytesFlooded) + stringGroup.Get(dummyCtx, key, StringSink(&res)) + bytesFlooded += int64(len(key) + len(res)) + } + evicts := g.mainCache.nevict - evict0 + if evicts <= 0 { + t.Errorf("evicts = %v; want more than 0", evicts) + } + + // Test that the key is gone. + fills = countFills(getTestKey) + if fills != 1 { + t.Fatalf("expected 1 cache fill after cache trashing; got %d", fills) + } +} + +type fakePeer struct { + hits int + fail bool +} + +func (p *fakePeer) Get(_ Context, in *pb.GetRequest, out *pb.GetResponse) error { + p.hits++ + if p.fail { + return errors.New("simulated error from peer") + } + out.Value = []byte("got:" + in.GetKey()) + return nil +} + +type fakePeers []ProtoGetter + +func (p fakePeers) PickPeer(key string) (peer ProtoGetter, ok bool) { + if len(p) == 0 { + return + } + n := crc32.Checksum([]byte(key), crc32.IEEETable) % uint32(len(p)) + return p[n], p[n] != nil +} + +// tests that peers (virtual, in-process) are hit, and how much. +func TestPeers(t *testing.T) { + once.Do(testSetup) + rand.Seed(123) + peer0 := &fakePeer{} + peer1 := &fakePeer{} + peer2 := &fakePeer{} + peerList := fakePeers([]ProtoGetter{peer0, peer1, peer2, nil}) + const cacheSize = 0 // disabled + localHits := 0 + getter := func(_ Context, key string, dest Sink) error { + localHits++ + return dest.SetString("got:" + key) + } + testGroup := newGroup("TestPeers-group", cacheSize, GetterFunc(getter), peerList) + run := func(name string, n int, wantSummary string) { + // Reset counters + localHits = 0 + for _, p := range []*fakePeer{peer0, peer1, peer2} { + p.hits = 0 + } + + for i := 0; i < n; i++ { + key := fmt.Sprintf("key-%d", i) + want := "got:" + key + var got string + err := testGroup.Get(dummyCtx, key, StringSink(&got)) + if err != nil { + t.Errorf("%s: error on key %q: %v", name, key, err) + continue + } + if got != want { + t.Errorf("%s: for key %q, got %q; want %q", name, key, got, want) + } + } + summary := func() string { + return fmt.Sprintf("localHits = %d, peers = %d %d %d", localHits, peer0.hits, peer1.hits, peer2.hits) + } + if got := summary(); got != wantSummary { + t.Errorf("%s: got %q; want %q", name, got, wantSummary) + } + } + resetCacheSize := func(maxBytes int64) { + g := testGroup + g.cacheBytes = maxBytes + g.mainCache = cache{} + g.hotCache = cache{} + } + + // Base case; peers all up, with no problems. + resetCacheSize(1 << 20) + run("base", 200, "localHits = 49, peers = 51 49 51") + + // Verify cache was hit. All localHits are gone, and some of + // the peer hits (the ones randomly selected to be maybe hot) + run("cached_base", 200, "localHits = 0, peers = 49 47 48") + resetCacheSize(0) + + // With one of the peers being down. + // TODO(bradfitz): on a peer number being unavailable, the + // consistent hashing should maybe keep trying others to + // spread the load out. Currently it fails back to local + // execution if the first consistent-hash slot is unavailable. + peerList[0] = nil + run("one_peer_down", 200, "localHits = 100, peers = 0 49 51") + + // Failing peer + peerList[0] = peer0 + peer0.fail = true + run("peer0_failing", 200, "localHits = 100, peers = 51 49 51") +} + +func TestTruncatingByteSliceTarget(t *testing.T) { + var buf [100]byte + s := buf[:] + if err := stringGroup.Get(dummyCtx, "short", TruncatingByteSliceSink(&s)); err != nil { + t.Fatal(err) + } + if want := "ECHO:short"; string(s) != want { + t.Errorf("short key got %q; want %q", s, want) + } + + s = buf[:6] + if err := stringGroup.Get(dummyCtx, "truncated", TruncatingByteSliceSink(&s)); err != nil { + t.Fatal(err) + } + if want := "ECHO:t"; string(s) != want { + t.Errorf("truncated key got %q; want %q", s, want) + } +} + +func TestAllocatingByteSliceTarget(t *testing.T) { + var dst []byte + sink := AllocatingByteSliceSink(&dst) + + inBytes := []byte("some bytes") + sink.SetBytes(inBytes) + if want := "some bytes"; string(dst) != want { + t.Errorf("SetBytes resulted in %q; want %q", dst, want) + } + v, err := sink.view() + if err != nil { + t.Fatalf("view after SetBytes failed: %v", err) + } + if &inBytes[0] == &dst[0] { + t.Error("inBytes and dst share memory") + } + if &inBytes[0] == &v.b[0] { + t.Error("inBytes and view share memory") + } + if &dst[0] == &v.b[0] { + t.Error("dst and view share memory") + } +} + +// orderedFlightGroup allows the caller to force the schedule of when +// orig.Do will be called. This is useful to serialize calls such +// that singleflight cannot dedup them. +type orderedFlightGroup struct { + mu sync.Mutex + stage1 chan bool + stage2 chan bool + orig flightGroup +} + +func (g *orderedFlightGroup) Do(key string, fn func() (interface{}, error)) (interface{}, error) { + <-g.stage1 + <-g.stage2 + g.mu.Lock() + defer g.mu.Unlock() + return g.orig.Do(key, fn) +} + +// TestNoDedup tests invariants on the cache size when singleflight is +// unable to dedup calls. +func TestNoDedup(t *testing.T) { + const testkey = "testkey" + const testval = "testval" + g := newGroup("testgroup", 1024, GetterFunc(func(_ Context, key string, dest Sink) error { + return dest.SetString(testval) + }), nil) + + orderedGroup := &orderedFlightGroup{ + stage1: make(chan bool), + stage2: make(chan bool), + orig: g.loadGroup, + } + // Replace loadGroup with our wrapper so we can control when + // loadGroup.Do is entered for each concurrent request. + g.loadGroup = orderedGroup + + // Issue two idential requests concurrently. Since the cache is + // empty, it will miss. Both will enter load(), but we will only + // allow one at a time to enter singleflight.Do, so the callback + // function will be called twice. + resc := make(chan string, 2) + for i := 0; i < 2; i++ { + go func() { + var s string + if err := g.Get(dummyCtx, testkey, StringSink(&s)); err != nil { + resc <- "ERROR:" + err.Error() + return + } + resc <- s + }() + } + + // Ensure both goroutines have entered the Do routine. This implies + // both concurrent requests have checked the cache, found it empty, + // and called load(). + orderedGroup.stage1 <- true + orderedGroup.stage1 <- true + orderedGroup.stage2 <- true + orderedGroup.stage2 <- true + + for i := 0; i < 2; i++ { + if s := <-resc; s != testval { + t.Errorf("result is %s want %s", s, testval) + } + } + + const wantItems = 1 + if g.mainCache.items() != wantItems { + t.Errorf("mainCache has %d items, want %d", g.mainCache.items(), wantItems) + } + + // If the singleflight callback doesn't double-check the cache again + // upon entry, we would increment nbytes twice but the entry would + // only be in the cache once. + const wantBytes = int64(len(testkey) + len(testval)) + if g.mainCache.nbytes != wantBytes { + t.Errorf("cache has %d bytes, want %d", g.mainCache.nbytes, wantBytes) + } +} + +func TestGroupStatsAlignment(t *testing.T) { + var g Group + off := unsafe.Offsetof(g.Stats) + if off%8 != 0 { + t.Fatal("Stats structure is not 8-byte aligned.") + } +} + +// TODO(bradfitz): port the Google-internal full integration test into here, +// using HTTP requests instead of our RPC system. diff --git a/vendor/github.com/golang/groupcache/groupcachepb/groupcache.pb.go b/vendor/github.com/golang/groupcache/groupcachepb/groupcache.pb.go new file mode 100644 index 000000000..520d1ee9a --- /dev/null +++ b/vendor/github.com/golang/groupcache/groupcachepb/groupcache.pb.go @@ -0,0 +1,65 @@ +// Code generated by protoc-gen-go. +// source: groupcache.proto +// DO NOT EDIT! + +package groupcachepb + +import proto "github.com/golang/protobuf/proto" +import json "encoding/json" +import math "math" + +// Reference proto, json, and math imports to suppress error if they are not otherwise used. +var _ = proto.Marshal +var _ = &json.SyntaxError{} +var _ = math.Inf + +type GetRequest struct { + Group *string `protobuf:"bytes,1,req,name=group" json:"group,omitempty"` + Key *string `protobuf:"bytes,2,req,name=key" json:"key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetRequest) Reset() { *m = GetRequest{} } +func (m *GetRequest) String() string { return proto.CompactTextString(m) } +func (*GetRequest) ProtoMessage() {} + +func (m *GetRequest) GetGroup() string { + if m != nil && m.Group != nil { + return *m.Group + } + return "" +} + +func (m *GetRequest) GetKey() string { + if m != nil && m.Key != nil { + return *m.Key + } + return "" +} + +type GetResponse struct { + Value []byte `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` + MinuteQps *float64 `protobuf:"fixed64,2,opt,name=minute_qps" json:"minute_qps,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GetResponse) Reset() { *m = GetResponse{} } +func (m *GetResponse) String() string { return proto.CompactTextString(m) } +func (*GetResponse) ProtoMessage() {} + +func (m *GetResponse) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *GetResponse) GetMinuteQps() float64 { + if m != nil && m.MinuteQps != nil { + return *m.MinuteQps + } + return 0 +} + +func init() { +} diff --git a/vendor/github.com/golang/groupcache/groupcachepb/groupcache.proto b/vendor/github.com/golang/groupcache/groupcachepb/groupcache.proto new file mode 100644 index 000000000..b5bdff94f --- /dev/null +++ b/vendor/github.com/golang/groupcache/groupcachepb/groupcache.proto @@ -0,0 +1,34 @@ +/* +Copyright 2012 Google Inc. + +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. +*/ + +syntax = "proto2"; + +package groupcachepb; + +message GetRequest { + required string group = 1; + required string key = 2; // not actually required/guaranteed to be UTF-8 +} + +message GetResponse { + optional bytes value = 1; + optional double minute_qps = 2; +} + +service GroupCache { + rpc Get(GetRequest) returns (GetResponse) { + }; +} diff --git a/vendor/github.com/golang/groupcache/http.go b/vendor/github.com/golang/groupcache/http.go new file mode 100644 index 000000000..f37467a78 --- /dev/null +++ b/vendor/github.com/golang/groupcache/http.go @@ -0,0 +1,227 @@ +/* +Copyright 2013 Google Inc. + +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 groupcache + +import ( + "bytes" + "fmt" + "io" + "net/http" + "net/url" + "strings" + "sync" + + "github.com/golang/groupcache/consistenthash" + pb "github.com/golang/groupcache/groupcachepb" + "github.com/golang/protobuf/proto" +) + +const defaultBasePath = "/_groupcache/" + +const defaultReplicas = 50 + +// HTTPPool implements PeerPicker for a pool of HTTP peers. +type HTTPPool struct { + // Context optionally specifies a context for the server to use when it + // receives a request. + // If nil, the server uses a nil Context. + Context func(*http.Request) Context + + // Transport optionally specifies an http.RoundTripper for the client + // to use when it makes a request. + // If nil, the client uses http.DefaultTransport. + Transport func(Context) http.RoundTripper + + // this peer's base URL, e.g. "https://example.net:8000" + self string + + // opts specifies the options. + opts HTTPPoolOptions + + mu sync.Mutex // guards peers and httpGetters + peers *consistenthash.Map + httpGetters map[string]*httpGetter // keyed by e.g. "http://10.0.0.2:8008" +} + +// HTTPPoolOptions are the configurations of a HTTPPool. +type HTTPPoolOptions struct { + // BasePath specifies the HTTP path that will serve groupcache requests. + // If blank, it defaults to "/_groupcache/". + BasePath string + + // Replicas specifies the number of key replicas on the consistent hash. + // If blank, it defaults to 50. + Replicas int + + // HashFn specifies the hash function of the consistent hash. + // If blank, it defaults to crc32.ChecksumIEEE. + HashFn consistenthash.Hash +} + +// NewHTTPPool initializes an HTTP pool of peers, and registers itself as a PeerPicker. +// For convenience, it also registers itself as an http.Handler with http.DefaultServeMux. +// The self argument should be a valid base URL that points to the current server, +// for example "http://example.net:8000". +func NewHTTPPool(self string) *HTTPPool { + p := NewHTTPPoolOpts(self, nil) + http.Handle(p.opts.BasePath, p) + return p +} + +var httpPoolMade bool + +// NewHTTPPoolOpts initializes an HTTP pool of peers with the given options. +// Unlike NewHTTPPool, this function does not register the created pool as an HTTP handler. +// The returned *HTTPPool implements http.Handler and must be registered using http.Handle. +func NewHTTPPoolOpts(self string, o *HTTPPoolOptions) *HTTPPool { + if httpPoolMade { + panic("groupcache: NewHTTPPool must be called only once") + } + httpPoolMade = true + + p := &HTTPPool{ + self: self, + httpGetters: make(map[string]*httpGetter), + } + if o != nil { + p.opts = *o + } + if p.opts.BasePath == "" { + p.opts.BasePath = defaultBasePath + } + if p.opts.Replicas == 0 { + p.opts.Replicas = defaultReplicas + } + p.peers = consistenthash.New(p.opts.Replicas, p.opts.HashFn) + + RegisterPeerPicker(func() PeerPicker { return p }) + return p +} + +// Set updates the pool's list of peers. +// Each peer value should be a valid base URL, +// for example "http://example.net:8000". +func (p *HTTPPool) Set(peers ...string) { + p.mu.Lock() + defer p.mu.Unlock() + p.peers = consistenthash.New(p.opts.Replicas, p.opts.HashFn) + p.peers.Add(peers...) + p.httpGetters = make(map[string]*httpGetter, len(peers)) + for _, peer := range peers { + p.httpGetters[peer] = &httpGetter{transport: p.Transport, baseURL: peer + p.opts.BasePath} + } +} + +func (p *HTTPPool) PickPeer(key string) (ProtoGetter, bool) { + p.mu.Lock() + defer p.mu.Unlock() + if p.peers.IsEmpty() { + return nil, false + } + if peer := p.peers.Get(key); peer != p.self { + return p.httpGetters[peer], true + } + return nil, false +} + +func (p *HTTPPool) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Parse request. + if !strings.HasPrefix(r.URL.Path, p.opts.BasePath) { + panic("HTTPPool serving unexpected path: " + r.URL.Path) + } + parts := strings.SplitN(r.URL.Path[len(p.opts.BasePath):], "/", 2) + if len(parts) != 2 { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + groupName := parts[0] + key := parts[1] + + // Fetch the value for this group/key. + group := GetGroup(groupName) + if group == nil { + http.Error(w, "no such group: "+groupName, http.StatusNotFound) + return + } + var ctx Context + if p.Context != nil { + ctx = p.Context(r) + } + + group.Stats.ServerRequests.Add(1) + var value []byte + err := group.Get(ctx, key, AllocatingByteSliceSink(&value)) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Write the value to the response body as a proto message. + body, err := proto.Marshal(&pb.GetResponse{Value: value}) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/x-protobuf") + w.Write(body) +} + +type httpGetter struct { + transport func(Context) http.RoundTripper + baseURL string +} + +var bufferPool = sync.Pool{ + New: func() interface{} { return new(bytes.Buffer) }, +} + +func (h *httpGetter) Get(context Context, in *pb.GetRequest, out *pb.GetResponse) error { + u := fmt.Sprintf( + "%v%v/%v", + h.baseURL, + url.QueryEscape(in.GetGroup()), + url.QueryEscape(in.GetKey()), + ) + req, err := http.NewRequest("GET", u, nil) + if err != nil { + return err + } + tr := http.DefaultTransport + if h.transport != nil { + tr = h.transport(context) + } + res, err := tr.RoundTrip(req) + if err != nil { + return err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return fmt.Errorf("server returned: %v", res.Status) + } + b := bufferPool.Get().(*bytes.Buffer) + b.Reset() + defer bufferPool.Put(b) + _, err = io.Copy(b, res.Body) + if err != nil { + return fmt.Errorf("reading response body: %v", err) + } + err = proto.Unmarshal(b.Bytes(), out) + if err != nil { + return fmt.Errorf("decoding response body: %v", err) + } + return nil +} diff --git a/vendor/github.com/golang/groupcache/http_test.go b/vendor/github.com/golang/groupcache/http_test.go new file mode 100644 index 000000000..b42edd7f0 --- /dev/null +++ b/vendor/github.com/golang/groupcache/http_test.go @@ -0,0 +1,166 @@ +/* +Copyright 2013 Google Inc. + +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 groupcache + +import ( + "errors" + "flag" + "log" + "net" + "net/http" + "os" + "os/exec" + "strconv" + "strings" + "sync" + "testing" + "time" +) + +var ( + peerAddrs = flag.String("test_peer_addrs", "", "Comma-separated list of peer addresses; used by TestHTTPPool") + peerIndex = flag.Int("test_peer_index", -1, "Index of which peer this child is; used by TestHTTPPool") + peerChild = flag.Bool("test_peer_child", false, "True if running as a child process; used by TestHTTPPool") +) + +func TestHTTPPool(t *testing.T) { + if *peerChild { + beChildForTestHTTPPool() + os.Exit(0) + } + + const ( + nChild = 4 + nGets = 100 + ) + + var childAddr []string + for i := 0; i < nChild; i++ { + childAddr = append(childAddr, pickFreeAddr(t)) + } + + var cmds []*exec.Cmd + var wg sync.WaitGroup + for i := 0; i < nChild; i++ { + cmd := exec.Command(os.Args[0], + "--test.run=TestHTTPPool", + "--test_peer_child", + "--test_peer_addrs="+strings.Join(childAddr, ","), + "--test_peer_index="+strconv.Itoa(i), + ) + cmds = append(cmds, cmd) + wg.Add(1) + if err := cmd.Start(); err != nil { + t.Fatal("failed to start child process: ", err) + } + go awaitAddrReady(t, childAddr[i], &wg) + } + defer func() { + for i := 0; i < nChild; i++ { + if cmds[i].Process != nil { + cmds[i].Process.Kill() + } + } + }() + wg.Wait() + + // Use a dummy self address so that we don't handle gets in-process. + p := NewHTTPPool("should-be-ignored") + p.Set(addrToURL(childAddr)...) + + // Dummy getter function. Gets should go to children only. + // The only time this process will handle a get is when the + // children can't be contacted for some reason. + getter := GetterFunc(func(ctx Context, key string, dest Sink) error { + return errors.New("parent getter called; something's wrong") + }) + g := NewGroup("httpPoolTest", 1<<20, getter) + + for _, key := range testKeys(nGets) { + var value string + if err := g.Get(nil, key, StringSink(&value)); err != nil { + t.Fatal(err) + } + if suffix := ":" + key; !strings.HasSuffix(value, suffix) { + t.Errorf("Get(%q) = %q, want value ending in %q", key, value, suffix) + } + t.Logf("Get key=%q, value=%q (peer:key)", key, value) + } +} + +func testKeys(n int) (keys []string) { + keys = make([]string, n) + for i := range keys { + keys[i] = strconv.Itoa(i) + } + return +} + +func beChildForTestHTTPPool() { + addrs := strings.Split(*peerAddrs, ",") + + p := NewHTTPPool("http://" + addrs[*peerIndex]) + p.Set(addrToURL(addrs)...) + + getter := GetterFunc(func(ctx Context, key string, dest Sink) error { + dest.SetString(strconv.Itoa(*peerIndex) + ":" + key) + return nil + }) + NewGroup("httpPoolTest", 1<<20, getter) + + log.Fatal(http.ListenAndServe(addrs[*peerIndex], p)) +} + +// This is racy. Another process could swoop in and steal the port between the +// call to this function and the next listen call. Should be okay though. +// The proper way would be to pass the l.File() as ExtraFiles to the child +// process, and then close your copy once the child starts. +func pickFreeAddr(t *testing.T) string { + l, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatal(err) + } + defer l.Close() + return l.Addr().String() +} + +func addrToURL(addr []string) []string { + url := make([]string, len(addr)) + for i := range addr { + url[i] = "http://" + addr[i] + } + return url +} + +func awaitAddrReady(t *testing.T, addr string, wg *sync.WaitGroup) { + defer wg.Done() + const max = 1 * time.Second + tries := 0 + for { + tries++ + c, err := net.Dial("tcp", addr) + if err == nil { + c.Close() + return + } + delay := time.Duration(tries) * 25 * time.Millisecond + if delay > max { + delay = max + } + time.Sleep(delay) + } +} diff --git a/vendor/github.com/golang/groupcache/lru/lru.go b/vendor/github.com/golang/groupcache/lru/lru.go new file mode 100644 index 000000000..532cc45e6 --- /dev/null +++ b/vendor/github.com/golang/groupcache/lru/lru.go @@ -0,0 +1,133 @@ +/* +Copyright 2013 Google Inc. + +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 lru implements an LRU cache. +package lru + +import "container/list" + +// Cache is an LRU cache. It is not safe for concurrent access. +type Cache struct { + // MaxEntries is the maximum number of cache entries before + // an item is evicted. Zero means no limit. + MaxEntries int + + // OnEvicted optionally specificies a callback function to be + // executed when an entry is purged from the cache. + OnEvicted func(key Key, value interface{}) + + ll *list.List + cache map[interface{}]*list.Element +} + +// A Key may be any value that is comparable. See http://golang.org/ref/spec#Comparison_operators +type Key interface{} + +type entry struct { + key Key + value interface{} +} + +// New creates a new Cache. +// If maxEntries is zero, the cache has no limit and it's assumed +// that eviction is done by the caller. +func New(maxEntries int) *Cache { + return &Cache{ + MaxEntries: maxEntries, + ll: list.New(), + cache: make(map[interface{}]*list.Element), + } +} + +// Add adds a value to the cache. +func (c *Cache) Add(key Key, value interface{}) { + if c.cache == nil { + c.cache = make(map[interface{}]*list.Element) + c.ll = list.New() + } + if ee, ok := c.cache[key]; ok { + c.ll.MoveToFront(ee) + ee.Value.(*entry).value = value + return + } + ele := c.ll.PushFront(&entry{key, value}) + c.cache[key] = ele + if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries { + c.RemoveOldest() + } +} + +// Get looks up a key's value from the cache. +func (c *Cache) Get(key Key) (value interface{}, ok bool) { + if c.cache == nil { + return + } + if ele, hit := c.cache[key]; hit { + c.ll.MoveToFront(ele) + return ele.Value.(*entry).value, true + } + return +} + +// Remove removes the provided key from the cache. +func (c *Cache) Remove(key Key) { + if c.cache == nil { + return + } + if ele, hit := c.cache[key]; hit { + c.removeElement(ele) + } +} + +// RemoveOldest removes the oldest item from the cache. +func (c *Cache) RemoveOldest() { + if c.cache == nil { + return + } + ele := c.ll.Back() + if ele != nil { + c.removeElement(ele) + } +} + +func (c *Cache) removeElement(e *list.Element) { + c.ll.Remove(e) + kv := e.Value.(*entry) + delete(c.cache, kv.key) + if c.OnEvicted != nil { + c.OnEvicted(kv.key, kv.value) + } +} + +// Len returns the number of items in the cache. +func (c *Cache) Len() int { + if c.cache == nil { + return 0 + } + return c.ll.Len() +} + +// Clear purges all stored items from the cache. +func (c *Cache) Clear() { + if c.OnEvicted != nil { + for _, e := range c.cache { + kv := e.Value.(*entry) + c.OnEvicted(kv.key, kv.value) + } + } + c.ll = nil + c.cache = nil +} diff --git a/vendor/github.com/golang/groupcache/lru/lru_test.go b/vendor/github.com/golang/groupcache/lru/lru_test.go new file mode 100644 index 000000000..a14f439e8 --- /dev/null +++ b/vendor/github.com/golang/groupcache/lru/lru_test.go @@ -0,0 +1,97 @@ +/* +Copyright 2013 Google Inc. + +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 lru + +import ( + "fmt" + "testing" +) + +type simpleStruct struct { + int + string +} + +type complexStruct struct { + int + simpleStruct +} + +var getTests = []struct { + name string + keyToAdd interface{} + keyToGet interface{} + expectedOk bool +}{ + {"string_hit", "myKey", "myKey", true}, + {"string_miss", "myKey", "nonsense", false}, + {"simple_struct_hit", simpleStruct{1, "two"}, simpleStruct{1, "two"}, true}, + {"simple_struct_miss", simpleStruct{1, "two"}, simpleStruct{0, "noway"}, false}, + {"complex_struct_hit", complexStruct{1, simpleStruct{2, "three"}}, + complexStruct{1, simpleStruct{2, "three"}}, true}, +} + +func TestGet(t *testing.T) { + for _, tt := range getTests { + lru := New(0) + lru.Add(tt.keyToAdd, 1234) + val, ok := lru.Get(tt.keyToGet) + if ok != tt.expectedOk { + t.Fatalf("%s: cache hit = %v; want %v", tt.name, ok, !ok) + } else if ok && val != 1234 { + t.Fatalf("%s expected get to return 1234 but got %v", tt.name, val) + } + } +} + +func TestRemove(t *testing.T) { + lru := New(0) + lru.Add("myKey", 1234) + if val, ok := lru.Get("myKey"); !ok { + t.Fatal("TestRemove returned no match") + } else if val != 1234 { + t.Fatalf("TestRemove failed. Expected %d, got %v", 1234, val) + } + + lru.Remove("myKey") + if _, ok := lru.Get("myKey"); ok { + t.Fatal("TestRemove returned a removed entry") + } +} + +func TestEvict(t *testing.T) { + evictedKeys := make([]Key, 0) + onEvictedFun := func(key Key, value interface{}) { + evictedKeys = append(evictedKeys, key) + } + + lru := New(20) + lru.OnEvicted = onEvictedFun + for i := 0; i < 22; i++ { + lru.Add(fmt.Sprintf("myKey%d", i), 1234) + } + + if len(evictedKeys) != 2 { + t.Fatalf("got %d evicted keys; want 2", len(evictedKeys)) + } + if evictedKeys[0] != Key("myKey0") { + t.Fatalf("got %v in first evicted key; want %s", evictedKeys[0], "myKey0") + } + if evictedKeys[1] != Key("myKey1") { + t.Fatalf("got %v in second evicted key; want %s", evictedKeys[1], "myKey1") + } +} diff --git a/vendor/github.com/golang/groupcache/peers.go b/vendor/github.com/golang/groupcache/peers.go new file mode 100644 index 000000000..1625ff043 --- /dev/null +++ b/vendor/github.com/golang/groupcache/peers.go @@ -0,0 +1,85 @@ +/* +Copyright 2012 Google Inc. + +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. +*/ + +// peers.go defines how processes find and communicate with their peers. + +package groupcache + +import ( + pb "github.com/golang/groupcache/groupcachepb" +) + +// Context is an opaque value passed through calls to the +// ProtoGetter. It may be nil if your ProtoGetter implementation does +// not require a context. +type Context interface{} + +// ProtoGetter is the interface that must be implemented by a peer. +type ProtoGetter interface { + Get(context Context, in *pb.GetRequest, out *pb.GetResponse) error +} + +// PeerPicker is the interface that must be implemented to locate +// the peer that owns a specific key. +type PeerPicker interface { + // PickPeer returns the peer that owns the specific key + // and true to indicate that a remote peer was nominated. + // It returns nil, false if the key owner is the current peer. + PickPeer(key string) (peer ProtoGetter, ok bool) +} + +// NoPeers is an implementation of PeerPicker that never finds a peer. +type NoPeers struct{} + +func (NoPeers) PickPeer(key string) (peer ProtoGetter, ok bool) { return } + +var ( + portPicker func(groupName string) PeerPicker +) + +// RegisterPeerPicker registers the peer initialization function. +// It is called once, when the first group is created. +// Either RegisterPeerPicker or RegisterPerGroupPeerPicker should be +// called exactly once, but not both. +func RegisterPeerPicker(fn func() PeerPicker) { + if portPicker != nil { + panic("RegisterPeerPicker called more than once") + } + portPicker = func(_ string) PeerPicker { return fn() } +} + +// RegisterPerGroupPeerPicker registers the peer initialization function, +// which takes the groupName, to be used in choosing a PeerPicker. +// It is called once, when the first group is created. +// Either RegisterPeerPicker or RegisterPerGroupPeerPicker should be +// called exactly once, but not both. +func RegisterPerGroupPeerPicker(fn func(groupName string) PeerPicker) { + if portPicker != nil { + panic("RegisterPeerPicker called more than once") + } + portPicker = fn +} + +func getPeers(groupName string) PeerPicker { + if portPicker == nil { + return NoPeers{} + } + pk := portPicker(groupName) + if pk == nil { + pk = NoPeers{} + } + return pk +} diff --git a/vendor/github.com/golang/groupcache/singleflight/singleflight.go b/vendor/github.com/golang/groupcache/singleflight/singleflight.go new file mode 100644 index 000000000..ff2c2ee4f --- /dev/null +++ b/vendor/github.com/golang/groupcache/singleflight/singleflight.go @@ -0,0 +1,64 @@ +/* +Copyright 2012 Google Inc. + +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 singleflight provides a duplicate function call suppression +// mechanism. +package singleflight + +import "sync" + +// call is an in-flight or completed Do call +type call struct { + wg sync.WaitGroup + val interface{} + err error +} + +// Group represents a class of work and forms a namespace in which +// units of work can be executed with duplicate suppression. +type Group struct { + mu sync.Mutex // protects m + m map[string]*call // lazily initialized +} + +// Do executes and returns the results of the given function, making +// sure that only one execution is in-flight for a given key at a +// time. If a duplicate comes in, the duplicate caller waits for the +// original to complete and receives the same results. +func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) { + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + g.mu.Unlock() + c.wg.Wait() + return c.val, c.err + } + c := new(call) + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + c.val, c.err = fn() + c.wg.Done() + + g.mu.Lock() + delete(g.m, key) + g.mu.Unlock() + + return c.val, c.err +} diff --git a/vendor/github.com/golang/groupcache/singleflight/singleflight_test.go b/vendor/github.com/golang/groupcache/singleflight/singleflight_test.go new file mode 100644 index 000000000..47b4d3dc0 --- /dev/null +++ b/vendor/github.com/golang/groupcache/singleflight/singleflight_test.go @@ -0,0 +1,85 @@ +/* +Copyright 2012 Google Inc. + +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 singleflight + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + "testing" + "time" +) + +func TestDo(t *testing.T) { + var g Group + v, err := g.Do("key", func() (interface{}, error) { + return "bar", nil + }) + if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want { + t.Errorf("Do = %v; want %v", got, want) + } + if err != nil { + t.Errorf("Do error = %v", err) + } +} + +func TestDoErr(t *testing.T) { + var g Group + someErr := errors.New("Some error") + v, err := g.Do("key", func() (interface{}, error) { + return nil, someErr + }) + if err != someErr { + t.Errorf("Do error = %v; want someErr", err) + } + if v != nil { + t.Errorf("unexpected non-nil value %#v", v) + } +} + +func TestDoDupSuppress(t *testing.T) { + var g Group + c := make(chan string) + var calls int32 + fn := func() (interface{}, error) { + atomic.AddInt32(&calls, 1) + return <-c, nil + } + + const n = 10 + var wg sync.WaitGroup + for i := 0; i < n; i++ { + wg.Add(1) + go func() { + v, err := g.Do("key", fn) + if err != nil { + t.Errorf("Do error: %v", err) + } + if v.(string) != "bar" { + t.Errorf("got %q; want %q", v, "bar") + } + wg.Done() + }() + } + time.Sleep(100 * time.Millisecond) // let goroutines above block + c <- "bar" + wg.Wait() + if got := atomic.LoadInt32(&calls); got != 1 { + t.Errorf("number of calls = %d; want 1", got) + } +} diff --git a/vendor/github.com/golang/groupcache/sinks.go b/vendor/github.com/golang/groupcache/sinks.go new file mode 100644 index 000000000..6c0b8be5c --- /dev/null +++ b/vendor/github.com/golang/groupcache/sinks.go @@ -0,0 +1,322 @@ +/* +Copyright 2012 Google Inc. + +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 groupcache + +import ( + "errors" + + "github.com/golang/protobuf/proto" +) + +// A Sink receives data from a Get call. +// +// Implementation of Getter must call exactly one of the Set methods +// on success. +type Sink interface { + // SetString sets the value to s. + SetString(s string) error + + // SetBytes sets the value to the contents of v. + // The caller retains ownership of v. + SetBytes(v []byte) error + + // SetProto sets the value to the encoded version of m. + // The caller retains ownership of m. + SetProto(m proto.Message) error + + // view returns a frozen view of the bytes for caching. + view() (ByteView, error) +} + +func cloneBytes(b []byte) []byte { + c := make([]byte, len(b)) + copy(c, b) + return c +} + +func setSinkView(s Sink, v ByteView) error { + // A viewSetter is a Sink that can also receive its value from + // a ByteView. This is a fast path to minimize copies when the + // item was already cached locally in memory (where it's + // cached as a ByteView) + type viewSetter interface { + setView(v ByteView) error + } + if vs, ok := s.(viewSetter); ok { + return vs.setView(v) + } + if v.b != nil { + return s.SetBytes(v.b) + } + return s.SetString(v.s) +} + +// StringSink returns a Sink that populates the provided string pointer. +func StringSink(sp *string) Sink { + return &stringSink{sp: sp} +} + +type stringSink struct { + sp *string + v ByteView + // TODO(bradfitz): track whether any Sets were called. +} + +func (s *stringSink) view() (ByteView, error) { + // TODO(bradfitz): return an error if no Set was called + return s.v, nil +} + +func (s *stringSink) SetString(v string) error { + s.v.b = nil + s.v.s = v + *s.sp = v + return nil +} + +func (s *stringSink) SetBytes(v []byte) error { + return s.SetString(string(v)) +} + +func (s *stringSink) SetProto(m proto.Message) error { + b, err := proto.Marshal(m) + if err != nil { + return err + } + s.v.b = b + *s.sp = string(b) + return nil +} + +// ByteViewSink returns a Sink that populates a ByteView. +func ByteViewSink(dst *ByteView) Sink { + if dst == nil { + panic("nil dst") + } + return &byteViewSink{dst: dst} +} + +type byteViewSink struct { + dst *ByteView + + // if this code ever ends up tracking that at least one set* + // method was called, don't make it an error to call set + // methods multiple times. Lorry's payload.go does that, and + // it makes sense. The comment at the top of this file about + // "exactly one of the Set methods" is overly strict. We + // really care about at least once (in a handler), but if + // multiple handlers fail (or multiple functions in a program + // using a Sink), it's okay to re-use the same one. +} + +func (s *byteViewSink) setView(v ByteView) error { + *s.dst = v + return nil +} + +func (s *byteViewSink) view() (ByteView, error) { + return *s.dst, nil +} + +func (s *byteViewSink) SetProto(m proto.Message) error { + b, err := proto.Marshal(m) + if err != nil { + return err + } + *s.dst = ByteView{b: b} + return nil +} + +func (s *byteViewSink) SetBytes(b []byte) error { + *s.dst = ByteView{b: cloneBytes(b)} + return nil +} + +func (s *byteViewSink) SetString(v string) error { + *s.dst = ByteView{s: v} + return nil +} + +// ProtoSink returns a sink that unmarshals binary proto values into m. +func ProtoSink(m proto.Message) Sink { + return &protoSink{ + dst: m, + } +} + +type protoSink struct { + dst proto.Message // authoritative value + typ string + + v ByteView // encoded +} + +func (s *protoSink) view() (ByteView, error) { + return s.v, nil +} + +func (s *protoSink) SetBytes(b []byte) error { + err := proto.Unmarshal(b, s.dst) + if err != nil { + return err + } + s.v.b = cloneBytes(b) + s.v.s = "" + return nil +} + +func (s *protoSink) SetString(v string) error { + b := []byte(v) + err := proto.Unmarshal(b, s.dst) + if err != nil { + return err + } + s.v.b = b + s.v.s = "" + return nil +} + +func (s *protoSink) SetProto(m proto.Message) error { + b, err := proto.Marshal(m) + if err != nil { + return err + } + // TODO(bradfitz): optimize for same-task case more and write + // right through? would need to document ownership rules at + // the same time. but then we could just assign *dst = *m + // here. This works for now: + err = proto.Unmarshal(b, s.dst) + if err != nil { + return err + } + s.v.b = b + s.v.s = "" + return nil +} + +// AllocatingByteSliceSink returns a Sink that allocates +// a byte slice to hold the received value and assigns +// it to *dst. The memory is not retained by groupcache. +func AllocatingByteSliceSink(dst *[]byte) Sink { + return &allocBytesSink{dst: dst} +} + +type allocBytesSink struct { + dst *[]byte + v ByteView +} + +func (s *allocBytesSink) view() (ByteView, error) { + return s.v, nil +} + +func (s *allocBytesSink) setView(v ByteView) error { + if v.b != nil { + *s.dst = cloneBytes(v.b) + } else { + *s.dst = []byte(v.s) + } + s.v = v + return nil +} + +func (s *allocBytesSink) SetProto(m proto.Message) error { + b, err := proto.Marshal(m) + if err != nil { + return err + } + return s.setBytesOwned(b) +} + +func (s *allocBytesSink) SetBytes(b []byte) error { + return s.setBytesOwned(cloneBytes(b)) +} + +func (s *allocBytesSink) setBytesOwned(b []byte) error { + if s.dst == nil { + return errors.New("nil AllocatingByteSliceSink *[]byte dst") + } + *s.dst = cloneBytes(b) // another copy, protecting the read-only s.v.b view + s.v.b = b + s.v.s = "" + return nil +} + +func (s *allocBytesSink) SetString(v string) error { + if s.dst == nil { + return errors.New("nil AllocatingByteSliceSink *[]byte dst") + } + *s.dst = []byte(v) + s.v.b = nil + s.v.s = v + return nil +} + +// TruncatingByteSliceSink returns a Sink that writes up to len(*dst) +// bytes to *dst. If more bytes are available, they're silently +// truncated. If fewer bytes are available than len(*dst), *dst +// is shrunk to fit the number of bytes available. +func TruncatingByteSliceSink(dst *[]byte) Sink { + return &truncBytesSink{dst: dst} +} + +type truncBytesSink struct { + dst *[]byte + v ByteView +} + +func (s *truncBytesSink) view() (ByteView, error) { + return s.v, nil +} + +func (s *truncBytesSink) SetProto(m proto.Message) error { + b, err := proto.Marshal(m) + if err != nil { + return err + } + return s.setBytesOwned(b) +} + +func (s *truncBytesSink) SetBytes(b []byte) error { + return s.setBytesOwned(cloneBytes(b)) +} + +func (s *truncBytesSink) setBytesOwned(b []byte) error { + if s.dst == nil { + return errors.New("nil TruncatingByteSliceSink *[]byte dst") + } + n := copy(*s.dst, b) + if n < len(*s.dst) { + *s.dst = (*s.dst)[:n] + } + s.v.b = b + s.v.s = "" + return nil +} + +func (s *truncBytesSink) SetString(v string) error { + if s.dst == nil { + return errors.New("nil TruncatingByteSliceSink *[]byte dst") + } + n := copy(*s.dst, v) + if n < len(*s.dst) { + *s.dst = (*s.dst)[:n] + } + s.v.b = nil + s.v.s = v + return nil +} diff --git a/vendor/github.com/golang/groupcache/testpb/test.pb.go b/vendor/github.com/golang/groupcache/testpb/test.pb.go new file mode 100644 index 000000000..038040d15 --- /dev/null +++ b/vendor/github.com/golang/groupcache/testpb/test.pb.go @@ -0,0 +1,235 @@ +// Code generated by protoc-gen-go. +// source: test.proto +// DO NOT EDIT! + +package testpb + +import proto "github.com/golang/protobuf/proto" +import json "encoding/json" +import math "math" + +// Reference proto, json, and math imports to suppress error if they are not otherwise used. +var _ = proto.Marshal +var _ = &json.SyntaxError{} +var _ = math.Inf + +type TestMessage struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + City *string `protobuf:"bytes,2,opt,name=city" json:"city,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TestMessage) Reset() { *m = TestMessage{} } +func (m *TestMessage) String() string { return proto.CompactTextString(m) } +func (*TestMessage) ProtoMessage() {} + +func (m *TestMessage) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *TestMessage) GetCity() string { + if m != nil && m.City != nil { + return *m.City + } + return "" +} + +type TestRequest struct { + Lower *string `protobuf:"bytes,1,req,name=lower" json:"lower,omitempty"` + RepeatCount *int32 `protobuf:"varint,2,opt,name=repeat_count,def=1" json:"repeat_count,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TestRequest) Reset() { *m = TestRequest{} } +func (m *TestRequest) String() string { return proto.CompactTextString(m) } +func (*TestRequest) ProtoMessage() {} + +const Default_TestRequest_RepeatCount int32 = 1 + +func (m *TestRequest) GetLower() string { + if m != nil && m.Lower != nil { + return *m.Lower + } + return "" +} + +func (m *TestRequest) GetRepeatCount() int32 { + if m != nil && m.RepeatCount != nil { + return *m.RepeatCount + } + return Default_TestRequest_RepeatCount +} + +type TestResponse struct { + Value *string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *TestResponse) Reset() { *m = TestResponse{} } +func (m *TestResponse) String() string { return proto.CompactTextString(m) } +func (*TestResponse) ProtoMessage() {} + +func (m *TestResponse) GetValue() string { + if m != nil && m.Value != nil { + return *m.Value + } + return "" +} + +type CacheStats struct { + Items *int64 `protobuf:"varint,1,opt,name=items" json:"items,omitempty"` + Bytes *int64 `protobuf:"varint,2,opt,name=bytes" json:"bytes,omitempty"` + Gets *int64 `protobuf:"varint,3,opt,name=gets" json:"gets,omitempty"` + Hits *int64 `protobuf:"varint,4,opt,name=hits" json:"hits,omitempty"` + Evicts *int64 `protobuf:"varint,5,opt,name=evicts" json:"evicts,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CacheStats) Reset() { *m = CacheStats{} } +func (m *CacheStats) String() string { return proto.CompactTextString(m) } +func (*CacheStats) ProtoMessage() {} + +func (m *CacheStats) GetItems() int64 { + if m != nil && m.Items != nil { + return *m.Items + } + return 0 +} + +func (m *CacheStats) GetBytes() int64 { + if m != nil && m.Bytes != nil { + return *m.Bytes + } + return 0 +} + +func (m *CacheStats) GetGets() int64 { + if m != nil && m.Gets != nil { + return *m.Gets + } + return 0 +} + +func (m *CacheStats) GetHits() int64 { + if m != nil && m.Hits != nil { + return *m.Hits + } + return 0 +} + +func (m *CacheStats) GetEvicts() int64 { + if m != nil && m.Evicts != nil { + return *m.Evicts + } + return 0 +} + +type StatsResponse struct { + Gets *int64 `protobuf:"varint,1,opt,name=gets" json:"gets,omitempty"` + CacheHits *int64 `protobuf:"varint,12,opt,name=cache_hits" json:"cache_hits,omitempty"` + Fills *int64 `protobuf:"varint,2,opt,name=fills" json:"fills,omitempty"` + TotalAlloc *uint64 `protobuf:"varint,3,opt,name=total_alloc" json:"total_alloc,omitempty"` + MainCache *CacheStats `protobuf:"bytes,4,opt,name=main_cache" json:"main_cache,omitempty"` + HotCache *CacheStats `protobuf:"bytes,5,opt,name=hot_cache" json:"hot_cache,omitempty"` + ServerIn *int64 `protobuf:"varint,6,opt,name=server_in" json:"server_in,omitempty"` + Loads *int64 `protobuf:"varint,8,opt,name=loads" json:"loads,omitempty"` + PeerLoads *int64 `protobuf:"varint,9,opt,name=peer_loads" json:"peer_loads,omitempty"` + PeerErrors *int64 `protobuf:"varint,10,opt,name=peer_errors" json:"peer_errors,omitempty"` + LocalLoads *int64 `protobuf:"varint,11,opt,name=local_loads" json:"local_loads,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *StatsResponse) Reset() { *m = StatsResponse{} } +func (m *StatsResponse) String() string { return proto.CompactTextString(m) } +func (*StatsResponse) ProtoMessage() {} + +func (m *StatsResponse) GetGets() int64 { + if m != nil && m.Gets != nil { + return *m.Gets + } + return 0 +} + +func (m *StatsResponse) GetCacheHits() int64 { + if m != nil && m.CacheHits != nil { + return *m.CacheHits + } + return 0 +} + +func (m *StatsResponse) GetFills() int64 { + if m != nil && m.Fills != nil { + return *m.Fills + } + return 0 +} + +func (m *StatsResponse) GetTotalAlloc() uint64 { + if m != nil && m.TotalAlloc != nil { + return *m.TotalAlloc + } + return 0 +} + +func (m *StatsResponse) GetMainCache() *CacheStats { + if m != nil { + return m.MainCache + } + return nil +} + +func (m *StatsResponse) GetHotCache() *CacheStats { + if m != nil { + return m.HotCache + } + return nil +} + +func (m *StatsResponse) GetServerIn() int64 { + if m != nil && m.ServerIn != nil { + return *m.ServerIn + } + return 0 +} + +func (m *StatsResponse) GetLoads() int64 { + if m != nil && m.Loads != nil { + return *m.Loads + } + return 0 +} + +func (m *StatsResponse) GetPeerLoads() int64 { + if m != nil && m.PeerLoads != nil { + return *m.PeerLoads + } + return 0 +} + +func (m *StatsResponse) GetPeerErrors() int64 { + if m != nil && m.PeerErrors != nil { + return *m.PeerErrors + } + return 0 +} + +func (m *StatsResponse) GetLocalLoads() int64 { + if m != nil && m.LocalLoads != nil { + return *m.LocalLoads + } + return 0 +} + +type Empty struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Empty) Reset() { *m = Empty{} } +func (m *Empty) String() string { return proto.CompactTextString(m) } +func (*Empty) ProtoMessage() {} + +func init() { +} diff --git a/vendor/github.com/golang/groupcache/testpb/test.proto b/vendor/github.com/golang/groupcache/testpb/test.proto new file mode 100644 index 000000000..b9dc6c9a0 --- /dev/null +++ b/vendor/github.com/golang/groupcache/testpb/test.proto @@ -0,0 +1,63 @@ +/* +Copyright 2012 Google Inc. + +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. +*/ + +syntax = "proto2"; + +package testpb; + +message TestMessage { + optional string name = 1; + optional string city = 2; +} + +message TestRequest { + required string lower = 1; // to be returned upper case + optional int32 repeat_count = 2 [default = 1]; // .. this many times +} + +message TestResponse { + optional string value = 1; +} + +message CacheStats { + optional int64 items = 1; + optional int64 bytes = 2; + optional int64 gets = 3; + optional int64 hits = 4; + optional int64 evicts = 5; +} + +message StatsResponse { + optional int64 gets = 1; + optional int64 cache_hits = 12; + optional int64 fills = 2; + optional uint64 total_alloc = 3; + optional CacheStats main_cache = 4; + optional CacheStats hot_cache = 5; + optional int64 server_in = 6; + optional int64 loads = 8; + optional int64 peer_loads = 9; + optional int64 peer_errors = 10; + optional int64 local_loads = 11; +} + +message Empty {} + +service GroupCacheTest { + rpc InitPeers(Empty) returns (Empty) {}; + rpc Get(TestRequest) returns (TestResponse) {}; + rpc GetStats(Empty) returns (StatsResponse) {}; +} diff --git a/vendor/github.com/google/btree/.travis.yml b/vendor/github.com/google/btree/.travis.yml new file mode 100644 index 000000000..4f2ee4d97 --- /dev/null +++ b/vendor/github.com/google/btree/.travis.yml @@ -0,0 +1 @@ +language: go diff --git a/vendor/github.com/google/btree/LICENSE b/vendor/github.com/google/btree/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/google/btree/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/google/btree/README.md b/vendor/github.com/google/btree/README.md new file mode 100644 index 000000000..6062a4dac --- /dev/null +++ b/vendor/github.com/google/btree/README.md @@ -0,0 +1,12 @@ +# BTree implementation for Go + +![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master) + +This package provides an in-memory B-Tree implementation for Go, useful as +an ordered, mutable data structure. + +The API is based off of the wonderful +http://godoc.org/github.com/petar/GoLLRB/llrb, and is meant to allow btree to +act as a drop-in replacement for gollrb trees. + +See http://godoc.org/github.com/google/btree for documentation. diff --git a/vendor/github.com/google/btree/btree.go b/vendor/github.com/google/btree/btree.go new file mode 100644 index 000000000..6ff062f9b --- /dev/null +++ b/vendor/github.com/google/btree/btree.go @@ -0,0 +1,890 @@ +// Copyright 2014 Google Inc. +// +// 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 btree implements in-memory B-Trees of arbitrary degree. +// +// btree implements an in-memory B-Tree for use as an ordered data structure. +// It is not meant for persistent storage solutions. +// +// It has a flatter structure than an equivalent red-black or other binary tree, +// which in some cases yields better memory usage and/or performance. +// See some discussion on the matter here: +// http://google-opensource.blogspot.com/2013/01/c-containers-that-save-memory-and-time.html +// Note, though, that this project is in no way related to the C++ B-Tree +// implementation written about there. +// +// Within this tree, each node contains a slice of items and a (possibly nil) +// slice of children. For basic numeric values or raw structs, this can cause +// efficiency differences when compared to equivalent C++ template code that +// stores values in arrays within the node: +// * Due to the overhead of storing values as interfaces (each +// value needs to be stored as the value itself, then 2 words for the +// interface pointing to that value and its type), resulting in higher +// memory use. +// * Since interfaces can point to values anywhere in memory, values are +// most likely not stored in contiguous blocks, resulting in a higher +// number of cache misses. +// These issues don't tend to matter, though, when working with strings or other +// heap-allocated structures, since C++-equivalent structures also must store +// pointers and also distribute their values across the heap. +// +// This implementation is designed to be a drop-in replacement to gollrb.LLRB +// trees, (http://github.com/petar/gollrb), an excellent and probably the most +// widely used ordered tree implementation in the Go ecosystem currently. +// Its functions, therefore, exactly mirror those of +// llrb.LLRB where possible. Unlike gollrb, though, we currently don't +// support storing multiple equivalent values. +package btree + +import ( + "fmt" + "io" + "sort" + "strings" + "sync" +) + +// Item represents a single object in the tree. +type Item interface { + // Less tests whether the current item is less than the given argument. + // + // This must provide a strict weak ordering. + // If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only + // hold one of either a or b in the tree). + Less(than Item) bool +} + +const ( + DefaultFreeListSize = 32 +) + +var ( + nilItems = make(items, 16) + nilChildren = make(children, 16) +) + +// FreeList represents a free list of btree nodes. By default each +// BTree has its own FreeList, but multiple BTrees can share the same +// FreeList. +// Two Btrees using the same freelist are safe for concurrent write access. +type FreeList struct { + mu sync.Mutex + freelist []*node +} + +// NewFreeList creates a new free list. +// size is the maximum size of the returned free list. +func NewFreeList(size int) *FreeList { + return &FreeList{freelist: make([]*node, 0, size)} +} + +func (f *FreeList) newNode() (n *node) { + f.mu.Lock() + index := len(f.freelist) - 1 + if index < 0 { + f.mu.Unlock() + return new(node) + } + n = f.freelist[index] + f.freelist[index] = nil + f.freelist = f.freelist[:index] + f.mu.Unlock() + return +} + +// freeNode adds the given node to the list, returning true if it was added +// and false if it was discarded. +func (f *FreeList) freeNode(n *node) (out bool) { + f.mu.Lock() + if len(f.freelist) < cap(f.freelist) { + f.freelist = append(f.freelist, n) + out = true + } + f.mu.Unlock() + return +} + +// ItemIterator allows callers of Ascend* to iterate in-order over portions of +// the tree. When this function returns false, iteration will stop and the +// associated Ascend* function will immediately return. +type ItemIterator func(i Item) bool + +// New creates a new B-Tree with the given degree. +// +// New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items +// and 2-4 children). +func New(degree int) *BTree { + return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize)) +} + +// NewWithFreeList creates a new B-Tree that uses the given node free list. +func NewWithFreeList(degree int, f *FreeList) *BTree { + if degree <= 1 { + panic("bad degree") + } + return &BTree{ + degree: degree, + cow: ©OnWriteContext{freelist: f}, + } +} + +// items stores items in a node. +type items []Item + +// insertAt inserts a value into the given index, pushing all subsequent values +// forward. +func (s *items) insertAt(index int, item Item) { + *s = append(*s, nil) + if index < len(*s) { + copy((*s)[index+1:], (*s)[index:]) + } + (*s)[index] = item +} + +// removeAt removes a value at a given index, pulling all subsequent values +// back. +func (s *items) removeAt(index int) Item { + item := (*s)[index] + copy((*s)[index:], (*s)[index+1:]) + (*s)[len(*s)-1] = nil + *s = (*s)[:len(*s)-1] + return item +} + +// pop removes and returns the last element in the list. +func (s *items) pop() (out Item) { + index := len(*s) - 1 + out = (*s)[index] + (*s)[index] = nil + *s = (*s)[:index] + return +} + +// truncate truncates this instance at index so that it contains only the +// first index items. index must be less than or equal to length. +func (s *items) truncate(index int) { + var toClear items + *s, toClear = (*s)[:index], (*s)[index:] + for len(toClear) > 0 { + toClear = toClear[copy(toClear, nilItems):] + } +} + +// find returns the index where the given item should be inserted into this +// list. 'found' is true if the item already exists in the list at the given +// index. +func (s items) find(item Item) (index int, found bool) { + i := sort.Search(len(s), func(i int) bool { + return item.Less(s[i]) + }) + if i > 0 && !s[i-1].Less(item) { + return i - 1, true + } + return i, false +} + +// children stores child nodes in a node. +type children []*node + +// insertAt inserts a value into the given index, pushing all subsequent values +// forward. +func (s *children) insertAt(index int, n *node) { + *s = append(*s, nil) + if index < len(*s) { + copy((*s)[index+1:], (*s)[index:]) + } + (*s)[index] = n +} + +// removeAt removes a value at a given index, pulling all subsequent values +// back. +func (s *children) removeAt(index int) *node { + n := (*s)[index] + copy((*s)[index:], (*s)[index+1:]) + (*s)[len(*s)-1] = nil + *s = (*s)[:len(*s)-1] + return n +} + +// pop removes and returns the last element in the list. +func (s *children) pop() (out *node) { + index := len(*s) - 1 + out = (*s)[index] + (*s)[index] = nil + *s = (*s)[:index] + return +} + +// truncate truncates this instance at index so that it contains only the +// first index children. index must be less than or equal to length. +func (s *children) truncate(index int) { + var toClear children + *s, toClear = (*s)[:index], (*s)[index:] + for len(toClear) > 0 { + toClear = toClear[copy(toClear, nilChildren):] + } +} + +// node is an internal node in a tree. +// +// It must at all times maintain the invariant that either +// * len(children) == 0, len(items) unconstrained +// * len(children) == len(items) + 1 +type node struct { + items items + children children + cow *copyOnWriteContext +} + +func (n *node) mutableFor(cow *copyOnWriteContext) *node { + if n.cow == cow { + return n + } + out := cow.newNode() + if cap(out.items) >= len(n.items) { + out.items = out.items[:len(n.items)] + } else { + out.items = make(items, len(n.items), cap(n.items)) + } + copy(out.items, n.items) + // Copy children + if cap(out.children) >= len(n.children) { + out.children = out.children[:len(n.children)] + } else { + out.children = make(children, len(n.children), cap(n.children)) + } + copy(out.children, n.children) + return out +} + +func (n *node) mutableChild(i int) *node { + c := n.children[i].mutableFor(n.cow) + n.children[i] = c + return c +} + +// split splits the given node at the given index. The current node shrinks, +// and this function returns the item that existed at that index and a new node +// containing all items/children after it. +func (n *node) split(i int) (Item, *node) { + item := n.items[i] + next := n.cow.newNode() + next.items = append(next.items, n.items[i+1:]...) + n.items.truncate(i) + if len(n.children) > 0 { + next.children = append(next.children, n.children[i+1:]...) + n.children.truncate(i + 1) + } + return item, next +} + +// maybeSplitChild checks if a child should be split, and if so splits it. +// Returns whether or not a split occurred. +func (n *node) maybeSplitChild(i, maxItems int) bool { + if len(n.children[i].items) < maxItems { + return false + } + first := n.mutableChild(i) + item, second := first.split(maxItems / 2) + n.items.insertAt(i, item) + n.children.insertAt(i+1, second) + return true +} + +// insert inserts an item into the subtree rooted at this node, making sure +// no nodes in the subtree exceed maxItems items. Should an equivalent item be +// be found/replaced by insert, it will be returned. +func (n *node) insert(item Item, maxItems int) Item { + i, found := n.items.find(item) + if found { + out := n.items[i] + n.items[i] = item + return out + } + if len(n.children) == 0 { + n.items.insertAt(i, item) + return nil + } + if n.maybeSplitChild(i, maxItems) { + inTree := n.items[i] + switch { + case item.Less(inTree): + // no change, we want first split node + case inTree.Less(item): + i++ // we want second split node + default: + out := n.items[i] + n.items[i] = item + return out + } + } + return n.mutableChild(i).insert(item, maxItems) +} + +// get finds the given key in the subtree and returns it. +func (n *node) get(key Item) Item { + i, found := n.items.find(key) + if found { + return n.items[i] + } else if len(n.children) > 0 { + return n.children[i].get(key) + } + return nil +} + +// min returns the first item in the subtree. +func min(n *node) Item { + if n == nil { + return nil + } + for len(n.children) > 0 { + n = n.children[0] + } + if len(n.items) == 0 { + return nil + } + return n.items[0] +} + +// max returns the last item in the subtree. +func max(n *node) Item { + if n == nil { + return nil + } + for len(n.children) > 0 { + n = n.children[len(n.children)-1] + } + if len(n.items) == 0 { + return nil + } + return n.items[len(n.items)-1] +} + +// toRemove details what item to remove in a node.remove call. +type toRemove int + +const ( + removeItem toRemove = iota // removes the given item + removeMin // removes smallest item in the subtree + removeMax // removes largest item in the subtree +) + +// remove removes an item from the subtree rooted at this node. +func (n *node) remove(item Item, minItems int, typ toRemove) Item { + var i int + var found bool + switch typ { + case removeMax: + if len(n.children) == 0 { + return n.items.pop() + } + i = len(n.items) + case removeMin: + if len(n.children) == 0 { + return n.items.removeAt(0) + } + i = 0 + case removeItem: + i, found = n.items.find(item) + if len(n.children) == 0 { + if found { + return n.items.removeAt(i) + } + return nil + } + default: + panic("invalid type") + } + // If we get to here, we have children. + if len(n.children[i].items) <= minItems { + return n.growChildAndRemove(i, item, minItems, typ) + } + child := n.mutableChild(i) + // Either we had enough items to begin with, or we've done some + // merging/stealing, because we've got enough now and we're ready to return + // stuff. + if found { + // The item exists at index 'i', and the child we've selected can give us a + // predecessor, since if we've gotten here it's got > minItems items in it. + out := n.items[i] + // We use our special-case 'remove' call with typ=maxItem to pull the + // predecessor of item i (the rightmost leaf of our immediate left child) + // and set it into where we pulled the item from. + n.items[i] = child.remove(nil, minItems, removeMax) + return out + } + // Final recursive call. Once we're here, we know that the item isn't in this + // node and that the child is big enough to remove from. + return child.remove(item, minItems, typ) +} + +// growChildAndRemove grows child 'i' to make sure it's possible to remove an +// item from it while keeping it at minItems, then calls remove to actually +// remove it. +// +// Most documentation says we have to do two sets of special casing: +// 1) item is in this node +// 2) item is in child +// In both cases, we need to handle the two subcases: +// A) node has enough values that it can spare one +// B) node doesn't have enough values +// For the latter, we have to check: +// a) left sibling has node to spare +// b) right sibling has node to spare +// c) we must merge +// To simplify our code here, we handle cases #1 and #2 the same: +// If a node doesn't have enough items, we make sure it does (using a,b,c). +// We then simply redo our remove call, and the second time (regardless of +// whether we're in case 1 or 2), we'll have enough items and can guarantee +// that we hit case A. +func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove) Item { + if i > 0 && len(n.children[i-1].items) > minItems { + // Steal from left child + child := n.mutableChild(i) + stealFrom := n.mutableChild(i - 1) + stolenItem := stealFrom.items.pop() + child.items.insertAt(0, n.items[i-1]) + n.items[i-1] = stolenItem + if len(stealFrom.children) > 0 { + child.children.insertAt(0, stealFrom.children.pop()) + } + } else if i < len(n.items) && len(n.children[i+1].items) > minItems { + // steal from right child + child := n.mutableChild(i) + stealFrom := n.mutableChild(i + 1) + stolenItem := stealFrom.items.removeAt(0) + child.items = append(child.items, n.items[i]) + n.items[i] = stolenItem + if len(stealFrom.children) > 0 { + child.children = append(child.children, stealFrom.children.removeAt(0)) + } + } else { + if i >= len(n.items) { + i-- + } + child := n.mutableChild(i) + // merge with right child + mergeItem := n.items.removeAt(i) + mergeChild := n.children.removeAt(i + 1) + child.items = append(child.items, mergeItem) + child.items = append(child.items, mergeChild.items...) + child.children = append(child.children, mergeChild.children...) + n.cow.freeNode(mergeChild) + } + return n.remove(item, minItems, typ) +} + +type direction int + +const ( + descend = direction(-1) + ascend = direction(+1) +) + +// iterate provides a simple method for iterating over elements in the tree. +// +// When ascending, the 'start' should be less than 'stop' and when descending, +// the 'start' should be greater than 'stop'. Setting 'includeStart' to true +// will force the iterator to include the first item when it equals 'start', +// thus creating a "greaterOrEqual" or "lessThanEqual" rather than just a +// "greaterThan" or "lessThan" queries. +func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit bool, iter ItemIterator) (bool, bool) { + var ok, found bool + var index int + switch dir { + case ascend: + if start != nil { + index, _ = n.items.find(start) + } + for i := index; i < len(n.items); i++ { + if len(n.children) > 0 { + if hit, ok = n.children[i].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + if !includeStart && !hit && start != nil && !start.Less(n.items[i]) { + hit = true + continue + } + hit = true + if stop != nil && !n.items[i].Less(stop) { + return hit, false + } + if !iter(n.items[i]) { + return hit, false + } + } + if len(n.children) > 0 { + if hit, ok = n.children[len(n.children)-1].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + case descend: + if start != nil { + index, found = n.items.find(start) + if !found { + index = index - 1 + } + } else { + index = len(n.items) - 1 + } + for i := index; i >= 0; i-- { + if start != nil && !n.items[i].Less(start) { + if !includeStart || hit || start.Less(n.items[i]) { + continue + } + } + if len(n.children) > 0 { + if hit, ok = n.children[i+1].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + if stop != nil && !stop.Less(n.items[i]) { + return hit, false // continue + } + hit = true + if !iter(n.items[i]) { + return hit, false + } + } + if len(n.children) > 0 { + if hit, ok = n.children[0].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + } + return hit, true +} + +// Used for testing/debugging purposes. +func (n *node) print(w io.Writer, level int) { + fmt.Fprintf(w, "%sNODE:%v\n", strings.Repeat(" ", level), n.items) + for _, c := range n.children { + c.print(w, level+1) + } +} + +// BTree is an implementation of a B-Tree. +// +// BTree stores Item instances in an ordered structure, allowing easy insertion, +// removal, and iteration. +// +// Write operations are not safe for concurrent mutation by multiple +// goroutines, but Read operations are. +type BTree struct { + degree int + length int + root *node + cow *copyOnWriteContext +} + +// copyOnWriteContext pointers determine node ownership... a tree with a write +// context equivalent to a node's write context is allowed to modify that node. +// A tree whose write context does not match a node's is not allowed to modify +// it, and must create a new, writable copy (IE: it's a Clone). +// +// When doing any write operation, we maintain the invariant that the current +// node's context is equal to the context of the tree that requested the write. +// We do this by, before we descend into any node, creating a copy with the +// correct context if the contexts don't match. +// +// Since the node we're currently visiting on any write has the requesting +// tree's context, that node is modifiable in place. Children of that node may +// not share context, but before we descend into them, we'll make a mutable +// copy. +type copyOnWriteContext struct { + freelist *FreeList +} + +// Clone clones the btree, lazily. Clone should not be called concurrently, +// but the original tree (t) and the new tree (t2) can be used concurrently +// once the Clone call completes. +// +// The internal tree structure of b is marked read-only and shared between t and +// t2. Writes to both t and t2 use copy-on-write logic, creating new nodes +// whenever one of b's original nodes would have been modified. Read operations +// should have no performance degredation. Write operations for both t and t2 +// will initially experience minor slow-downs caused by additional allocs and +// copies due to the aforementioned copy-on-write logic, but should converge to +// the original performance characteristics of the original tree. +func (t *BTree) Clone() (t2 *BTree) { + // Create two entirely new copy-on-write contexts. + // This operation effectively creates three trees: + // the original, shared nodes (old b.cow) + // the new b.cow nodes + // the new out.cow nodes + cow1, cow2 := *t.cow, *t.cow + out := *t + t.cow = &cow1 + out.cow = &cow2 + return &out +} + +// maxItems returns the max number of items to allow per node. +func (t *BTree) maxItems() int { + return t.degree*2 - 1 +} + +// minItems returns the min number of items to allow per node (ignored for the +// root node). +func (t *BTree) minItems() int { + return t.degree - 1 +} + +func (c *copyOnWriteContext) newNode() (n *node) { + n = c.freelist.newNode() + n.cow = c + return +} + +type freeType int + +const ( + ftFreelistFull freeType = iota // node was freed (available for GC, not stored in freelist) + ftStored // node was stored in the freelist for later use + ftNotOwned // node was ignored by COW, since it's owned by another one +) + +// freeNode frees a node within a given COW context, if it's owned by that +// context. It returns what happened to the node (see freeType const +// documentation). +func (c *copyOnWriteContext) freeNode(n *node) freeType { + if n.cow == c { + // clear to allow GC + n.items.truncate(0) + n.children.truncate(0) + n.cow = nil + if c.freelist.freeNode(n) { + return ftStored + } else { + return ftFreelistFull + } + } else { + return ftNotOwned + } +} + +// ReplaceOrInsert adds the given item to the tree. If an item in the tree +// already equals the given one, it is removed from the tree and returned. +// Otherwise, nil is returned. +// +// nil cannot be added to the tree (will panic). +func (t *BTree) ReplaceOrInsert(item Item) Item { + if item == nil { + panic("nil item being added to BTree") + } + if t.root == nil { + t.root = t.cow.newNode() + t.root.items = append(t.root.items, item) + t.length++ + return nil + } else { + t.root = t.root.mutableFor(t.cow) + if len(t.root.items) >= t.maxItems() { + item2, second := t.root.split(t.maxItems() / 2) + oldroot := t.root + t.root = t.cow.newNode() + t.root.items = append(t.root.items, item2) + t.root.children = append(t.root.children, oldroot, second) + } + } + out := t.root.insert(item, t.maxItems()) + if out == nil { + t.length++ + } + return out +} + +// Delete removes an item equal to the passed in item from the tree, returning +// it. If no such item exists, returns nil. +func (t *BTree) Delete(item Item) Item { + return t.deleteItem(item, removeItem) +} + +// DeleteMin removes the smallest item in the tree and returns it. +// If no such item exists, returns nil. +func (t *BTree) DeleteMin() Item { + return t.deleteItem(nil, removeMin) +} + +// DeleteMax removes the largest item in the tree and returns it. +// If no such item exists, returns nil. +func (t *BTree) DeleteMax() Item { + return t.deleteItem(nil, removeMax) +} + +func (t *BTree) deleteItem(item Item, typ toRemove) Item { + if t.root == nil || len(t.root.items) == 0 { + return nil + } + t.root = t.root.mutableFor(t.cow) + out := t.root.remove(item, t.minItems(), typ) + if len(t.root.items) == 0 && len(t.root.children) > 0 { + oldroot := t.root + t.root = t.root.children[0] + t.cow.freeNode(oldroot) + } + if out != nil { + t.length-- + } + return out +} + +// AscendRange calls the iterator for every value in the tree within the range +// [greaterOrEqual, lessThan), until iterator returns false. +func (t *BTree) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, greaterOrEqual, lessThan, true, false, iterator) +} + +// AscendLessThan calls the iterator for every value in the tree within the range +// [first, pivot), until iterator returns false. +func (t *BTree) AscendLessThan(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, nil, pivot, false, false, iterator) +} + +// AscendGreaterOrEqual calls the iterator for every value in the tree within +// the range [pivot, last], until iterator returns false. +func (t *BTree) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, pivot, nil, true, false, iterator) +} + +// Ascend calls the iterator for every value in the tree within the range +// [first, last], until iterator returns false. +func (t *BTree) Ascend(iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, nil, nil, false, false, iterator) +} + +// DescendRange calls the iterator for every value in the tree within the range +// [lessOrEqual, greaterThan), until iterator returns false. +func (t *BTree) DescendRange(lessOrEqual, greaterThan Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, lessOrEqual, greaterThan, true, false, iterator) +} + +// DescendLessOrEqual calls the iterator for every value in the tree within the range +// [pivot, first], until iterator returns false. +func (t *BTree) DescendLessOrEqual(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, pivot, nil, true, false, iterator) +} + +// DescendGreaterThan calls the iterator for every value in the tree within +// the range (pivot, last], until iterator returns false. +func (t *BTree) DescendGreaterThan(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, nil, pivot, false, false, iterator) +} + +// Descend calls the iterator for every value in the tree within the range +// [last, first], until iterator returns false. +func (t *BTree) Descend(iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, nil, nil, false, false, iterator) +} + +// Get looks for the key item in the tree, returning it. It returns nil if +// unable to find that item. +func (t *BTree) Get(key Item) Item { + if t.root == nil { + return nil + } + return t.root.get(key) +} + +// Min returns the smallest item in the tree, or nil if the tree is empty. +func (t *BTree) Min() Item { + return min(t.root) +} + +// Max returns the largest item in the tree, or nil if the tree is empty. +func (t *BTree) Max() Item { + return max(t.root) +} + +// Has returns true if the given key is in the tree. +func (t *BTree) Has(key Item) bool { + return t.Get(key) != nil +} + +// Len returns the number of items currently in the tree. +func (t *BTree) Len() int { + return t.length +} + +// Clear removes all items from the btree. If addNodesToFreelist is true, +// t's nodes are added to its freelist as part of this call, until the freelist +// is full. Otherwise, the root node is simply dereferenced and the subtree +// left to Go's normal GC processes. +// +// This can be much faster +// than calling Delete on all elements, because that requires finding/removing +// each element in the tree and updating the tree accordingly. It also is +// somewhat faster than creating a new tree to replace the old one, because +// nodes from the old tree are reclaimed into the freelist for use by the new +// one, instead of being lost to the garbage collector. +// +// This call takes: +// O(1): when addNodesToFreelist is false, this is a single operation. +// O(1): when the freelist is already full, it breaks out immediately +// O(freelist size): when the freelist is empty and the nodes are all owned +// by this tree, nodes are added to the freelist until full. +// O(tree size): when all nodes are owned by another tree, all nodes are +// iterated over looking for nodes to add to the freelist, and due to +// ownership, none are. +func (t *BTree) Clear(addNodesToFreelist bool) { + if t.root != nil && addNodesToFreelist { + t.root.reset(t.cow) + } + t.root, t.length = nil, 0 +} + +// reset returns a subtree to the freelist. It breaks out immediately if the +// freelist is full, since the only benefit of iterating is to fill that +// freelist up. Returns true if parent reset call should continue. +func (n *node) reset(c *copyOnWriteContext) bool { + for _, child := range n.children { + if !child.reset(c) { + return false + } + } + return c.freeNode(n) != ftFreelistFull +} + +// Int implements the Item interface for integers. +type Int int + +// Less returns true if int(a) < int(b). +func (a Int) Less(b Item) bool { + return a < b.(Int) +} diff --git a/vendor/github.com/google/btree/btree_mem.go b/vendor/github.com/google/btree/btree_mem.go new file mode 100644 index 000000000..cb95b7fa1 --- /dev/null +++ b/vendor/github.com/google/btree/btree_mem.go @@ -0,0 +1,76 @@ +// Copyright 2014 Google Inc. +// +// 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. + +// +build ignore + +// This binary compares memory usage between btree and gollrb. +package main + +import ( + "flag" + "fmt" + "math/rand" + "runtime" + "time" + + "github.com/google/btree" + "github.com/petar/GoLLRB/llrb" +) + +var ( + size = flag.Int("size", 1000000, "size of the tree to build") + degree = flag.Int("degree", 8, "degree of btree") + gollrb = flag.Bool("llrb", false, "use llrb instead of btree") +) + +func main() { + flag.Parse() + vals := rand.Perm(*size) + var t, v interface{} + v = vals + var stats runtime.MemStats + for i := 0; i < 10; i++ { + runtime.GC() + } + fmt.Println("-------- BEFORE ----------") + runtime.ReadMemStats(&stats) + fmt.Printf("%+v\n", stats) + start := time.Now() + if *gollrb { + tr := llrb.New() + for _, v := range vals { + tr.ReplaceOrInsert(llrb.Int(v)) + } + t = tr // keep it around + } else { + tr := btree.New(*degree) + for _, v := range vals { + tr.ReplaceOrInsert(btree.Int(v)) + } + t = tr // keep it around + } + fmt.Printf("%v inserts in %v\n", *size, time.Since(start)) + fmt.Println("-------- AFTER ----------") + runtime.ReadMemStats(&stats) + fmt.Printf("%+v\n", stats) + for i := 0; i < 10; i++ { + runtime.GC() + } + fmt.Println("-------- AFTER GC ----------") + runtime.ReadMemStats(&stats) + fmt.Printf("%+v\n", stats) + if t == v { + fmt.Println("to make sure vals and tree aren't GC'd") + } +} diff --git a/vendor/github.com/google/btree/btree_test.go b/vendor/github.com/google/btree/btree_test.go new file mode 100644 index 000000000..78a90cd8a --- /dev/null +++ b/vendor/github.com/google/btree/btree_test.go @@ -0,0 +1,785 @@ +// Copyright 2014 Google Inc. +// +// 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 btree + +import ( + "flag" + "fmt" + "math/rand" + "reflect" + "sort" + "sync" + "testing" + "time" +) + +func init() { + seed := time.Now().Unix() + fmt.Println(seed) + rand.Seed(seed) +} + +// perm returns a random permutation of n Int items in the range [0, n). +func perm(n int) (out []Item) { + for _, v := range rand.Perm(n) { + out = append(out, Int(v)) + } + return +} + +// rang returns an ordered list of Int items in the range [0, n). +func rang(n int) (out []Item) { + for i := 0; i < n; i++ { + out = append(out, Int(i)) + } + return +} + +// all extracts all items from a tree in order as a slice. +func all(t *BTree) (out []Item) { + t.Ascend(func(a Item) bool { + out = append(out, a) + return true + }) + return +} + +// rangerev returns a reversed ordered list of Int items in the range [0, n). +func rangrev(n int) (out []Item) { + for i := n - 1; i >= 0; i-- { + out = append(out, Int(i)) + } + return +} + +// allrev extracts all items from a tree in reverse order as a slice. +func allrev(t *BTree) (out []Item) { + t.Descend(func(a Item) bool { + out = append(out, a) + return true + }) + return +} + +var btreeDegree = flag.Int("degree", 32, "B-Tree degree") + +func TestBTree(t *testing.T) { + tr := New(*btreeDegree) + const treeSize = 10000 + for i := 0; i < 10; i++ { + if min := tr.Min(); min != nil { + t.Fatalf("empty min, got %+v", min) + } + if max := tr.Max(); max != nil { + t.Fatalf("empty max, got %+v", max) + } + for _, item := range perm(treeSize) { + if x := tr.ReplaceOrInsert(item); x != nil { + t.Fatal("insert found item", item) + } + } + for _, item := range perm(treeSize) { + if x := tr.ReplaceOrInsert(item); x == nil { + t.Fatal("insert didn't find item", item) + } + } + if min, want := tr.Min(), Item(Int(0)); min != want { + t.Fatalf("min: want %+v, got %+v", want, min) + } + if max, want := tr.Max(), Item(Int(treeSize-1)); max != want { + t.Fatalf("max: want %+v, got %+v", want, max) + } + got := all(tr) + want := rang(treeSize) + if !reflect.DeepEqual(got, want) { + t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want) + } + + gotrev := allrev(tr) + wantrev := rangrev(treeSize) + if !reflect.DeepEqual(gotrev, wantrev) { + t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want) + } + + for _, item := range perm(treeSize) { + if x := tr.Delete(item); x == nil { + t.Fatalf("didn't find %v", item) + } + } + if got = all(tr); len(got) > 0 { + t.Fatalf("some left!: %v", got) + } + } +} + +func ExampleBTree() { + tr := New(*btreeDegree) + for i := Int(0); i < 10; i++ { + tr.ReplaceOrInsert(i) + } + fmt.Println("len: ", tr.Len()) + fmt.Println("get3: ", tr.Get(Int(3))) + fmt.Println("get100: ", tr.Get(Int(100))) + fmt.Println("del4: ", tr.Delete(Int(4))) + fmt.Println("del100: ", tr.Delete(Int(100))) + fmt.Println("replace5: ", tr.ReplaceOrInsert(Int(5))) + fmt.Println("replace100:", tr.ReplaceOrInsert(Int(100))) + fmt.Println("min: ", tr.Min()) + fmt.Println("delmin: ", tr.DeleteMin()) + fmt.Println("max: ", tr.Max()) + fmt.Println("delmax: ", tr.DeleteMax()) + fmt.Println("len: ", tr.Len()) + // Output: + // len: 10 + // get3: 3 + // get100: + // del4: 4 + // del100: + // replace5: 5 + // replace100: + // min: 0 + // delmin: 0 + // max: 100 + // delmax: 100 + // len: 8 +} + +func TestDeleteMin(t *testing.T) { + tr := New(3) + for _, v := range perm(100) { + tr.ReplaceOrInsert(v) + } + var got []Item + for v := tr.DeleteMin(); v != nil; v = tr.DeleteMin() { + got = append(got, v) + } + if want := rang(100); !reflect.DeepEqual(got, want) { + t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want) + } +} + +func TestDeleteMax(t *testing.T) { + tr := New(3) + for _, v := range perm(100) { + tr.ReplaceOrInsert(v) + } + var got []Item + for v := tr.DeleteMax(); v != nil; v = tr.DeleteMax() { + got = append(got, v) + } + // Reverse our list. + for i := 0; i < len(got)/2; i++ { + got[i], got[len(got)-i-1] = got[len(got)-i-1], got[i] + } + if want := rang(100); !reflect.DeepEqual(got, want) { + t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want) + } +} + +func TestAscendRange(t *testing.T) { + tr := New(2) + for _, v := range perm(100) { + tr.ReplaceOrInsert(v) + } + var got []Item + tr.AscendRange(Int(40), Int(60), func(a Item) bool { + got = append(got, a) + return true + }) + if want := rang(100)[40:60]; !reflect.DeepEqual(got, want) { + t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want) + } + got = got[:0] + tr.AscendRange(Int(40), Int(60), func(a Item) bool { + if a.(Int) > 50 { + return false + } + got = append(got, a) + return true + }) + if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) { + t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want) + } +} + +func TestDescendRange(t *testing.T) { + tr := New(2) + for _, v := range perm(100) { + tr.ReplaceOrInsert(v) + } + var got []Item + tr.DescendRange(Int(60), Int(40), func(a Item) bool { + got = append(got, a) + return true + }) + if want := rangrev(100)[39:59]; !reflect.DeepEqual(got, want) { + t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want) + } + got = got[:0] + tr.DescendRange(Int(60), Int(40), func(a Item) bool { + if a.(Int) < 50 { + return false + } + got = append(got, a) + return true + }) + if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) { + t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want) + } +} +func TestAscendLessThan(t *testing.T) { + tr := New(*btreeDegree) + for _, v := range perm(100) { + tr.ReplaceOrInsert(v) + } + var got []Item + tr.AscendLessThan(Int(60), func(a Item) bool { + got = append(got, a) + return true + }) + if want := rang(100)[:60]; !reflect.DeepEqual(got, want) { + t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want) + } + got = got[:0] + tr.AscendLessThan(Int(60), func(a Item) bool { + if a.(Int) > 50 { + return false + } + got = append(got, a) + return true + }) + if want := rang(100)[:51]; !reflect.DeepEqual(got, want) { + t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want) + } +} + +func TestDescendLessOrEqual(t *testing.T) { + tr := New(*btreeDegree) + for _, v := range perm(100) { + tr.ReplaceOrInsert(v) + } + var got []Item + tr.DescendLessOrEqual(Int(40), func(a Item) bool { + got = append(got, a) + return true + }) + if want := rangrev(100)[59:]; !reflect.DeepEqual(got, want) { + t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want) + } + got = got[:0] + tr.DescendLessOrEqual(Int(60), func(a Item) bool { + if a.(Int) < 50 { + return false + } + got = append(got, a) + return true + }) + if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) { + t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want) + } +} +func TestAscendGreaterOrEqual(t *testing.T) { + tr := New(*btreeDegree) + for _, v := range perm(100) { + tr.ReplaceOrInsert(v) + } + var got []Item + tr.AscendGreaterOrEqual(Int(40), func(a Item) bool { + got = append(got, a) + return true + }) + if want := rang(100)[40:]; !reflect.DeepEqual(got, want) { + t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want) + } + got = got[:0] + tr.AscendGreaterOrEqual(Int(40), func(a Item) bool { + if a.(Int) > 50 { + return false + } + got = append(got, a) + return true + }) + if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) { + t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want) + } +} + +func TestDescendGreaterThan(t *testing.T) { + tr := New(*btreeDegree) + for _, v := range perm(100) { + tr.ReplaceOrInsert(v) + } + var got []Item + tr.DescendGreaterThan(Int(40), func(a Item) bool { + got = append(got, a) + return true + }) + if want := rangrev(100)[:59]; !reflect.DeepEqual(got, want) { + t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want) + } + got = got[:0] + tr.DescendGreaterThan(Int(40), func(a Item) bool { + if a.(Int) < 50 { + return false + } + got = append(got, a) + return true + }) + if want := rangrev(100)[:50]; !reflect.DeepEqual(got, want) { + t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want) + } +} + +const benchmarkTreeSize = 10000 + +func BenchmarkInsert(b *testing.B) { + b.StopTimer() + insertP := perm(benchmarkTreeSize) + b.StartTimer() + i := 0 + for i < b.N { + tr := New(*btreeDegree) + for _, item := range insertP { + tr.ReplaceOrInsert(item) + i++ + if i >= b.N { + return + } + } + } +} + +func BenchmarkSeek(b *testing.B) { + b.StopTimer() + size := 100000 + insertP := perm(size) + tr := New(*btreeDegree) + for _, item := range insertP { + tr.ReplaceOrInsert(item) + } + b.StartTimer() + + for i := 0; i < b.N; i++ { + tr.AscendGreaterOrEqual(Int(i%size), func(i Item) bool { return false }) + } +} + +func BenchmarkDeleteInsert(b *testing.B) { + b.StopTimer() + insertP := perm(benchmarkTreeSize) + tr := New(*btreeDegree) + for _, item := range insertP { + tr.ReplaceOrInsert(item) + } + b.StartTimer() + for i := 0; i < b.N; i++ { + tr.Delete(insertP[i%benchmarkTreeSize]) + tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize]) + } +} + +func BenchmarkDeleteInsertCloneOnce(b *testing.B) { + b.StopTimer() + insertP := perm(benchmarkTreeSize) + tr := New(*btreeDegree) + for _, item := range insertP { + tr.ReplaceOrInsert(item) + } + tr = tr.Clone() + b.StartTimer() + for i := 0; i < b.N; i++ { + tr.Delete(insertP[i%benchmarkTreeSize]) + tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize]) + } +} + +func BenchmarkDeleteInsertCloneEachTime(b *testing.B) { + b.StopTimer() + insertP := perm(benchmarkTreeSize) + tr := New(*btreeDegree) + for _, item := range insertP { + tr.ReplaceOrInsert(item) + } + b.StartTimer() + for i := 0; i < b.N; i++ { + tr = tr.Clone() + tr.Delete(insertP[i%benchmarkTreeSize]) + tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize]) + } +} + +func BenchmarkDelete(b *testing.B) { + b.StopTimer() + insertP := perm(benchmarkTreeSize) + removeP := perm(benchmarkTreeSize) + b.StartTimer() + i := 0 + for i < b.N { + b.StopTimer() + tr := New(*btreeDegree) + for _, v := range insertP { + tr.ReplaceOrInsert(v) + } + b.StartTimer() + for _, item := range removeP { + tr.Delete(item) + i++ + if i >= b.N { + return + } + } + if tr.Len() > 0 { + panic(tr.Len()) + } + } +} + +func BenchmarkGet(b *testing.B) { + b.StopTimer() + insertP := perm(benchmarkTreeSize) + removeP := perm(benchmarkTreeSize) + b.StartTimer() + i := 0 + for i < b.N { + b.StopTimer() + tr := New(*btreeDegree) + for _, v := range insertP { + tr.ReplaceOrInsert(v) + } + b.StartTimer() + for _, item := range removeP { + tr.Get(item) + i++ + if i >= b.N { + return + } + } + } +} + +func BenchmarkGetCloneEachTime(b *testing.B) { + b.StopTimer() + insertP := perm(benchmarkTreeSize) + removeP := perm(benchmarkTreeSize) + b.StartTimer() + i := 0 + for i < b.N { + b.StopTimer() + tr := New(*btreeDegree) + for _, v := range insertP { + tr.ReplaceOrInsert(v) + } + b.StartTimer() + for _, item := range removeP { + tr = tr.Clone() + tr.Get(item) + i++ + if i >= b.N { + return + } + } + } +} + +type byInts []Item + +func (a byInts) Len() int { + return len(a) +} + +func (a byInts) Less(i, j int) bool { + return a[i].(Int) < a[j].(Int) +} + +func (a byInts) Swap(i, j int) { + a[i], a[j] = a[j], a[i] +} + +func BenchmarkAscend(b *testing.B) { + arr := perm(benchmarkTreeSize) + tr := New(*btreeDegree) + for _, v := range arr { + tr.ReplaceOrInsert(v) + } + sort.Sort(byInts(arr)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + j := 0 + tr.Ascend(func(item Item) bool { + if item.(Int) != arr[j].(Int) { + b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int)) + } + j++ + return true + }) + } +} + +func BenchmarkDescend(b *testing.B) { + arr := perm(benchmarkTreeSize) + tr := New(*btreeDegree) + for _, v := range arr { + tr.ReplaceOrInsert(v) + } + sort.Sort(byInts(arr)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + j := len(arr) - 1 + tr.Descend(func(item Item) bool { + if item.(Int) != arr[j].(Int) { + b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int)) + } + j-- + return true + }) + } +} +func BenchmarkAscendRange(b *testing.B) { + arr := perm(benchmarkTreeSize) + tr := New(*btreeDegree) + for _, v := range arr { + tr.ReplaceOrInsert(v) + } + sort.Sort(byInts(arr)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + j := 100 + tr.AscendRange(Int(100), arr[len(arr)-100], func(item Item) bool { + if item.(Int) != arr[j].(Int) { + b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int)) + } + j++ + return true + }) + if j != len(arr)-100 { + b.Fatalf("expected: %v, got %v", len(arr)-100, j) + } + } +} + +func BenchmarkDescendRange(b *testing.B) { + arr := perm(benchmarkTreeSize) + tr := New(*btreeDegree) + for _, v := range arr { + tr.ReplaceOrInsert(v) + } + sort.Sort(byInts(arr)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + j := len(arr) - 100 + tr.DescendRange(arr[len(arr)-100], Int(100), func(item Item) bool { + if item.(Int) != arr[j].(Int) { + b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int)) + } + j-- + return true + }) + if j != 100 { + b.Fatalf("expected: %v, got %v", len(arr)-100, j) + } + } +} +func BenchmarkAscendGreaterOrEqual(b *testing.B) { + arr := perm(benchmarkTreeSize) + tr := New(*btreeDegree) + for _, v := range arr { + tr.ReplaceOrInsert(v) + } + sort.Sort(byInts(arr)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + j := 100 + k := 0 + tr.AscendGreaterOrEqual(Int(100), func(item Item) bool { + if item.(Int) != arr[j].(Int) { + b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int)) + } + j++ + k++ + return true + }) + if j != len(arr) { + b.Fatalf("expected: %v, got %v", len(arr), j) + } + if k != len(arr)-100 { + b.Fatalf("expected: %v, got %v", len(arr)-100, k) + } + } +} +func BenchmarkDescendLessOrEqual(b *testing.B) { + arr := perm(benchmarkTreeSize) + tr := New(*btreeDegree) + for _, v := range arr { + tr.ReplaceOrInsert(v) + } + sort.Sort(byInts(arr)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + j := len(arr) - 100 + k := len(arr) + tr.DescendLessOrEqual(arr[len(arr)-100], func(item Item) bool { + if item.(Int) != arr[j].(Int) { + b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int)) + } + j-- + k-- + return true + }) + if j != -1 { + b.Fatalf("expected: %v, got %v", -1, j) + } + if k != 99 { + b.Fatalf("expected: %v, got %v", 99, k) + } + } +} + +const cloneTestSize = 10000 + +func cloneTest(t *testing.T, b *BTree, start int, p []Item, wg *sync.WaitGroup, trees *[]*BTree) { + t.Logf("Starting new clone at %v", start) + *trees = append(*trees, b) + for i := start; i < cloneTestSize; i++ { + b.ReplaceOrInsert(p[i]) + if i%(cloneTestSize/5) == 0 { + wg.Add(1) + go cloneTest(t, b.Clone(), i+1, p, wg, trees) + } + } + wg.Done() +} + +func TestCloneConcurrentOperations(t *testing.T) { + b := New(*btreeDegree) + trees := []*BTree{} + p := perm(cloneTestSize) + var wg sync.WaitGroup + wg.Add(1) + go cloneTest(t, b, 0, p, &wg, &trees) + wg.Wait() + want := rang(cloneTestSize) + t.Logf("Starting equality checks on %d trees", len(trees)) + for i, tree := range trees { + if !reflect.DeepEqual(want, all(tree)) { + t.Errorf("tree %v mismatch", i) + } + } + t.Log("Removing half from first half") + toRemove := rang(cloneTestSize)[cloneTestSize/2:] + for i := 0; i < len(trees)/2; i++ { + tree := trees[i] + wg.Add(1) + go func() { + for _, item := range toRemove { + tree.Delete(item) + } + wg.Done() + }() + } + wg.Wait() + t.Log("Checking all values again") + for i, tree := range trees { + var wantpart []Item + if i < len(trees)/2 { + wantpart = want[:cloneTestSize/2] + } else { + wantpart = want + } + if got := all(tree); !reflect.DeepEqual(wantpart, got) { + t.Errorf("tree %v mismatch, want %v got %v", i, len(want), len(got)) + } + } +} + +func BenchmarkDeleteAndRestore(b *testing.B) { + items := perm(16392) + b.ResetTimer() + b.Run(`CopyBigFreeList`, func(b *testing.B) { + fl := NewFreeList(16392) + tr := NewWithFreeList(*btreeDegree, fl) + for _, v := range items { + tr.ReplaceOrInsert(v) + } + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + dels := make([]Item, 0, tr.Len()) + tr.Ascend(ItemIterator(func(b Item) bool { + dels = append(dels, b) + return true + })) + for _, del := range dels { + tr.Delete(del) + } + // tr is now empty, we make a new empty copy of it. + tr = NewWithFreeList(*btreeDegree, fl) + for _, v := range items { + tr.ReplaceOrInsert(v) + } + } + }) + b.Run(`Copy`, func(b *testing.B) { + tr := New(*btreeDegree) + for _, v := range items { + tr.ReplaceOrInsert(v) + } + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + dels := make([]Item, 0, tr.Len()) + tr.Ascend(ItemIterator(func(b Item) bool { + dels = append(dels, b) + return true + })) + for _, del := range dels { + tr.Delete(del) + } + // tr is now empty, we make a new empty copy of it. + tr = New(*btreeDegree) + for _, v := range items { + tr.ReplaceOrInsert(v) + } + } + }) + b.Run(`ClearBigFreelist`, func(b *testing.B) { + fl := NewFreeList(16392) + tr := NewWithFreeList(*btreeDegree, fl) + for _, v := range items { + tr.ReplaceOrInsert(v) + } + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + tr.Clear(true) + for _, v := range items { + tr.ReplaceOrInsert(v) + } + } + }) + b.Run(`Clear`, func(b *testing.B) { + tr := New(*btreeDegree) + for _, v := range items { + tr.ReplaceOrInsert(v) + } + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + tr.Clear(true) + for _, v := range items { + tr.ReplaceOrInsert(v) + } + } + }) +} diff --git a/vendor/github.com/gregjones/httpcache/.travis.yml b/vendor/github.com/gregjones/httpcache/.travis.yml new file mode 100644 index 000000000..b5ffbe03d --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/.travis.yml @@ -0,0 +1,19 @@ +sudo: false +language: go +go: + - 1.6.x + - 1.7.x + - 1.8.x + - 1.9.x + - master +matrix: + allow_failures: + - go: master + fast_finish: true +install: + - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d .) + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/gregjones/httpcache/LICENSE.txt b/vendor/github.com/gregjones/httpcache/LICENSE.txt new file mode 100644 index 000000000..81316beb0 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/LICENSE.txt @@ -0,0 +1,7 @@ +Copyright © 2012 Greg Jones (greg.jones@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/gregjones/httpcache/README.md b/vendor/github.com/gregjones/httpcache/README.md new file mode 100644 index 000000000..09c9e7c17 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/README.md @@ -0,0 +1,25 @@ +httpcache +========= + +[![Build Status](https://travis-ci.org/gregjones/httpcache.svg?branch=master)](https://travis-ci.org/gregjones/httpcache) [![GoDoc](https://godoc.org/github.com/gregjones/httpcache?status.svg)](https://godoc.org/github.com/gregjones/httpcache) + +Package httpcache provides a http.RoundTripper implementation that works as a mostly [RFC 7234](https://tools.ietf.org/html/rfc7234) compliant cache for http responses. + +It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client and not for a shared proxy). + +Cache Backends +-------------- + +- The built-in 'memory' cache stores responses in an in-memory map. +- [`github.com/gregjones/httpcache/diskcache`](https://github.com/gregjones/httpcache/tree/master/diskcache) provides a filesystem-backed cache using the [diskv](https://github.com/peterbourgon/diskv) library. +- [`github.com/gregjones/httpcache/memcache`](https://github.com/gregjones/httpcache/tree/master/memcache) provides memcache implementations, for both App Engine and 'normal' memcache servers. +- [`sourcegraph.com/sourcegraph/s3cache`](https://sourcegraph.com/github.com/sourcegraph/s3cache) uses Amazon S3 for storage. +- [`github.com/gregjones/httpcache/leveldbcache`](https://github.com/gregjones/httpcache/tree/master/leveldbcache) provides a filesystem-backed cache using [leveldb](https://github.com/syndtr/goleveldb/leveldb). +- [`github.com/die-net/lrucache`](https://github.com/die-net/lrucache) provides an in-memory cache that will evict least-recently used entries. +- [`github.com/die-net/lrucache/twotier`](https://github.com/die-net/lrucache/tree/master/twotier) allows caches to be combined, for example to use lrucache above with a persistent disk-cache. +- [`github.com/birkelund/boltdbcache`](https://github.com/birkelund/boltdbcache) provides a BoltDB implementation (based on the [bbolt](https://github.com/coreos/bbolt) fork). + +License +------- + +- [MIT License](LICENSE.txt) diff --git a/vendor/github.com/gregjones/httpcache/diskcache/diskcache.go b/vendor/github.com/gregjones/httpcache/diskcache/diskcache.go new file mode 100644 index 000000000..42e3129d8 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/diskcache/diskcache.go @@ -0,0 +1,61 @@ +// Package diskcache provides an implementation of httpcache.Cache that uses the diskv package +// to supplement an in-memory map with persistent storage +// +package diskcache + +import ( + "bytes" + "crypto/md5" + "encoding/hex" + "github.com/peterbourgon/diskv" + "io" +) + +// Cache is an implementation of httpcache.Cache that supplements the in-memory map with persistent storage +type Cache struct { + d *diskv.Diskv +} + +// Get returns the response corresponding to key if present +func (c *Cache) Get(key string) (resp []byte, ok bool) { + key = keyToFilename(key) + resp, err := c.d.Read(key) + if err != nil { + return []byte{}, false + } + return resp, true +} + +// Set saves a response to the cache as key +func (c *Cache) Set(key string, resp []byte) { + key = keyToFilename(key) + c.d.WriteStream(key, bytes.NewReader(resp), true) +} + +// Delete removes the response with key from the cache +func (c *Cache) Delete(key string) { + key = keyToFilename(key) + c.d.Erase(key) +} + +func keyToFilename(key string) string { + h := md5.New() + io.WriteString(h, key) + return hex.EncodeToString(h.Sum(nil)) +} + +// New returns a new Cache that will store files in basePath +func New(basePath string) *Cache { + return &Cache{ + d: diskv.New(diskv.Options{ + BasePath: basePath, + CacheSizeMax: 100 * 1024 * 1024, // 100MB + }), + } +} + +// NewWithDiskv returns a new Cache using the provided Diskv as underlying +// storage. +func NewWithDiskv(d *diskv.Diskv) *Cache { + return &Cache{d} +} diff --git a/vendor/github.com/gregjones/httpcache/diskcache/diskcache_test.go b/vendor/github.com/gregjones/httpcache/diskcache/diskcache_test.go new file mode 100644 index 000000000..35c76cbd1 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/diskcache/diskcache_test.go @@ -0,0 +1,42 @@ +package diskcache + +import ( + "bytes" + "io/ioutil" + "os" + "testing" +) + +func TestDiskCache(t *testing.T) { + tempDir, err := ioutil.TempDir("", "httpcache") + if err != nil { + t.Fatalf("TempDir: %v", err) + } + defer os.RemoveAll(tempDir) + + cache := New(tempDir) + + key := "testKey" + _, ok := cache.Get(key) + if ok { + t.Fatal("retrieved key before adding it") + } + + val := []byte("some bytes") + cache.Set(key, val) + + retVal, ok := cache.Get(key) + if !ok { + t.Fatal("could not retrieve an element we just added") + } + if !bytes.Equal(retVal, val) { + t.Fatal("retrieved a different value than what we put in") + } + + cache.Delete(key) + + _, ok = cache.Get(key) + if ok { + t.Fatal("deleted key still present") + } +} diff --git a/vendor/github.com/gregjones/httpcache/httpcache.go b/vendor/github.com/gregjones/httpcache/httpcache.go new file mode 100644 index 000000000..f6a2ec4a5 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/httpcache.go @@ -0,0 +1,551 @@ +// Package httpcache provides a http.RoundTripper implementation that works as a +// mostly RFC-compliant cache for http responses. +// +// It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client +// and not for a shared proxy). +// +package httpcache + +import ( + "bufio" + "bytes" + "errors" + "io" + "io/ioutil" + "net/http" + "net/http/httputil" + "strings" + "sync" + "time" +) + +const ( + stale = iota + fresh + transparent + // XFromCache is the header added to responses that are returned from the cache + XFromCache = "X-From-Cache" +) + +// A Cache interface is used by the Transport to store and retrieve responses. +type Cache interface { + // Get returns the []byte representation of a cached response and a bool + // set to true if the value isn't empty + Get(key string) (responseBytes []byte, ok bool) + // Set stores the []byte representation of a response against a key + Set(key string, responseBytes []byte) + // Delete removes the value associated with the key + Delete(key string) +} + +// cacheKey returns the cache key for req. +func cacheKey(req *http.Request) string { + if req.Method == http.MethodGet { + return req.URL.String() + } else { + return req.Method + " " + req.URL.String() + } +} + +// CachedResponse returns the cached http.Response for req if present, and nil +// otherwise. +func CachedResponse(c Cache, req *http.Request) (resp *http.Response, err error) { + cachedVal, ok := c.Get(cacheKey(req)) + if !ok { + return + } + + b := bytes.NewBuffer(cachedVal) + return http.ReadResponse(bufio.NewReader(b), req) +} + +// MemoryCache is an implemtation of Cache that stores responses in an in-memory map. +type MemoryCache struct { + mu sync.RWMutex + items map[string][]byte +} + +// Get returns the []byte representation of the response and true if present, false if not +func (c *MemoryCache) Get(key string) (resp []byte, ok bool) { + c.mu.RLock() + resp, ok = c.items[key] + c.mu.RUnlock() + return resp, ok +} + +// Set saves response resp to the cache with key +func (c *MemoryCache) Set(key string, resp []byte) { + c.mu.Lock() + c.items[key] = resp + c.mu.Unlock() +} + +// Delete removes key from the cache +func (c *MemoryCache) Delete(key string) { + c.mu.Lock() + delete(c.items, key) + c.mu.Unlock() +} + +// NewMemoryCache returns a new Cache that will store items in an in-memory map +func NewMemoryCache() *MemoryCache { + c := &MemoryCache{items: map[string][]byte{}} + return c +} + +// Transport is an implementation of http.RoundTripper that will return values from a cache +// where possible (avoiding a network request) and will additionally add validators (etag/if-modified-since) +// to repeated requests allowing servers to return 304 / Not Modified +type Transport struct { + // The RoundTripper interface actually used to make requests + // If nil, http.DefaultTransport is used + Transport http.RoundTripper + Cache Cache + // If true, responses returned from the cache will be given an extra header, X-From-Cache + MarkCachedResponses bool +} + +// NewTransport returns a new Transport with the +// provided Cache implementation and MarkCachedResponses set to true +func NewTransport(c Cache) *Transport { + return &Transport{Cache: c, MarkCachedResponses: true} +} + +// Client returns an *http.Client that caches responses. +func (t *Transport) Client() *http.Client { + return &http.Client{Transport: t} +} + +// varyMatches will return false unless all of the cached values for the headers listed in Vary +// match the new request +func varyMatches(cachedResp *http.Response, req *http.Request) bool { + for _, header := range headerAllCommaSepValues(cachedResp.Header, "vary") { + header = http.CanonicalHeaderKey(header) + if header != "" && req.Header.Get(header) != cachedResp.Header.Get("X-Varied-"+header) { + return false + } + } + return true +} + +// RoundTrip takes a Request and returns a Response +// +// If there is a fresh Response already in cache, then it will be returned without connecting to +// the server. +// +// If there is a stale Response, then any validators it contains will be set on the new request +// to give the server a chance to respond with NotModified. If this happens, then the cached Response +// will be returned. +func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) { + cacheKey := cacheKey(req) + cacheable := (req.Method == "GET" || req.Method == "HEAD") && req.Header.Get("range") == "" + var cachedResp *http.Response + if cacheable { + cachedResp, err = CachedResponse(t.Cache, req) + } else { + // Need to invalidate an existing value + t.Cache.Delete(cacheKey) + } + + transport := t.Transport + if transport == nil { + transport = http.DefaultTransport + } + + if cacheable && cachedResp != nil && err == nil { + if t.MarkCachedResponses { + cachedResp.Header.Set(XFromCache, "1") + } + + if varyMatches(cachedResp, req) { + // Can only use cached value if the new request doesn't Vary significantly + freshness := getFreshness(cachedResp.Header, req.Header) + if freshness == fresh { + return cachedResp, nil + } + + if freshness == stale { + var req2 *http.Request + // Add validators if caller hasn't already done so + etag := cachedResp.Header.Get("etag") + if etag != "" && req.Header.Get("etag") == "" { + req2 = cloneRequest(req) + req2.Header.Set("if-none-match", etag) + } + lastModified := cachedResp.Header.Get("last-modified") + if lastModified != "" && req.Header.Get("last-modified") == "" { + if req2 == nil { + req2 = cloneRequest(req) + } + req2.Header.Set("if-modified-since", lastModified) + } + if req2 != nil { + req = req2 + } + } + } + + resp, err = transport.RoundTrip(req) + if err == nil && req.Method == "GET" && resp.StatusCode == http.StatusNotModified { + // Replace the 304 response with the one from cache, but update with some new headers + endToEndHeaders := getEndToEndHeaders(resp.Header) + for _, header := range endToEndHeaders { + cachedResp.Header[header] = resp.Header[header] + } + resp = cachedResp + } else if (err != nil || (cachedResp != nil && resp.StatusCode >= 500)) && + req.Method == "GET" && canStaleOnError(cachedResp.Header, req.Header) { + // In case of transport failure and stale-if-error activated, returns cached content + // when available + return cachedResp, nil + } else { + if err != nil || resp.StatusCode != http.StatusOK { + t.Cache.Delete(cacheKey) + } + if err != nil { + return nil, err + } + } + } else { + reqCacheControl := parseCacheControl(req.Header) + if _, ok := reqCacheControl["only-if-cached"]; ok { + resp = newGatewayTimeoutResponse(req) + } else { + resp, err = transport.RoundTrip(req) + if err != nil { + return nil, err + } + } + } + + if cacheable && canStore(parseCacheControl(req.Header), parseCacheControl(resp.Header)) { + for _, varyKey := range headerAllCommaSepValues(resp.Header, "vary") { + varyKey = http.CanonicalHeaderKey(varyKey) + fakeHeader := "X-Varied-" + varyKey + reqValue := req.Header.Get(varyKey) + if reqValue != "" { + resp.Header.Set(fakeHeader, reqValue) + } + } + switch req.Method { + case "GET": + // Delay caching until EOF is reached. + resp.Body = &cachingReadCloser{ + R: resp.Body, + OnEOF: func(r io.Reader) { + resp := *resp + resp.Body = ioutil.NopCloser(r) + respBytes, err := httputil.DumpResponse(&resp, true) + if err == nil { + t.Cache.Set(cacheKey, respBytes) + } + }, + } + default: + respBytes, err := httputil.DumpResponse(resp, true) + if err == nil { + t.Cache.Set(cacheKey, respBytes) + } + } + } else { + t.Cache.Delete(cacheKey) + } + return resp, nil +} + +// ErrNoDateHeader indicates that the HTTP headers contained no Date header. +var ErrNoDateHeader = errors.New("no Date header") + +// Date parses and returns the value of the Date header. +func Date(respHeaders http.Header) (date time.Time, err error) { + dateHeader := respHeaders.Get("date") + if dateHeader == "" { + err = ErrNoDateHeader + return + } + + return time.Parse(time.RFC1123, dateHeader) +} + +type realClock struct{} + +func (c *realClock) since(d time.Time) time.Duration { + return time.Since(d) +} + +type timer interface { + since(d time.Time) time.Duration +} + +var clock timer = &realClock{} + +// getFreshness will return one of fresh/stale/transparent based on the cache-control +// values of the request and the response +// +// fresh indicates the response can be returned +// stale indicates that the response needs validating before it is returned +// transparent indicates the response should not be used to fulfil the request +// +// Because this is only a private cache, 'public' and 'private' in cache-control aren't +// signficant. Similarly, smax-age isn't used. +func getFreshness(respHeaders, reqHeaders http.Header) (freshness int) { + respCacheControl := parseCacheControl(respHeaders) + reqCacheControl := parseCacheControl(reqHeaders) + if _, ok := reqCacheControl["no-cache"]; ok { + return transparent + } + if _, ok := respCacheControl["no-cache"]; ok { + return stale + } + if _, ok := reqCacheControl["only-if-cached"]; ok { + return fresh + } + + date, err := Date(respHeaders) + if err != nil { + return stale + } + currentAge := clock.since(date) + + var lifetime time.Duration + var zeroDuration time.Duration + + // If a response includes both an Expires header and a max-age directive, + // the max-age directive overrides the Expires header, even if the Expires header is more restrictive. + if maxAge, ok := respCacheControl["max-age"]; ok { + lifetime, err = time.ParseDuration(maxAge + "s") + if err != nil { + lifetime = zeroDuration + } + } else { + expiresHeader := respHeaders.Get("Expires") + if expiresHeader != "" { + expires, err := time.Parse(time.RFC1123, expiresHeader) + if err != nil { + lifetime = zeroDuration + } else { + lifetime = expires.Sub(date) + } + } + } + + if maxAge, ok := reqCacheControl["max-age"]; ok { + // the client is willing to accept a response whose age is no greater than the specified time in seconds + lifetime, err = time.ParseDuration(maxAge + "s") + if err != nil { + lifetime = zeroDuration + } + } + if minfresh, ok := reqCacheControl["min-fresh"]; ok { + // the client wants a response that will still be fresh for at least the specified number of seconds. + minfreshDuration, err := time.ParseDuration(minfresh + "s") + if err == nil { + currentAge = time.Duration(currentAge + minfreshDuration) + } + } + + if maxstale, ok := reqCacheControl["max-stale"]; ok { + // Indicates that the client is willing to accept a response that has exceeded its expiration time. + // If max-stale is assigned a value, then the client is willing to accept a response that has exceeded + // its expiration time by no more than the specified number of seconds. + // If no value is assigned to max-stale, then the client is willing to accept a stale response of any age. + // + // Responses served only because of a max-stale value are supposed to have a Warning header added to them, + // but that seems like a hassle, and is it actually useful? If so, then there needs to be a different + // return-value available here. + if maxstale == "" { + return fresh + } + maxstaleDuration, err := time.ParseDuration(maxstale + "s") + if err == nil { + currentAge = time.Duration(currentAge - maxstaleDuration) + } + } + + if lifetime > currentAge { + return fresh + } + + return stale +} + +// Returns true if either the request or the response includes the stale-if-error +// cache control extension: https://tools.ietf.org/html/rfc5861 +func canStaleOnError(respHeaders, reqHeaders http.Header) bool { + respCacheControl := parseCacheControl(respHeaders) + reqCacheControl := parseCacheControl(reqHeaders) + + var err error + lifetime := time.Duration(-1) + + if staleMaxAge, ok := respCacheControl["stale-if-error"]; ok { + if staleMaxAge != "" { + lifetime, err = time.ParseDuration(staleMaxAge + "s") + if err != nil { + return false + } + } else { + return true + } + } + if staleMaxAge, ok := reqCacheControl["stale-if-error"]; ok { + if staleMaxAge != "" { + lifetime, err = time.ParseDuration(staleMaxAge + "s") + if err != nil { + return false + } + } else { + return true + } + } + + if lifetime >= 0 { + date, err := Date(respHeaders) + if err != nil { + return false + } + currentAge := clock.since(date) + if lifetime > currentAge { + return true + } + } + + return false +} + +func getEndToEndHeaders(respHeaders http.Header) []string { + // These headers are always hop-by-hop + hopByHopHeaders := map[string]struct{}{ + "Connection": struct{}{}, + "Keep-Alive": struct{}{}, + "Proxy-Authenticate": struct{}{}, + "Proxy-Authorization": struct{}{}, + "Te": struct{}{}, + "Trailers": struct{}{}, + "Transfer-Encoding": struct{}{}, + "Upgrade": struct{}{}, + } + + for _, extra := range strings.Split(respHeaders.Get("connection"), ",") { + // any header listed in connection, if present, is also considered hop-by-hop + if strings.Trim(extra, " ") != "" { + hopByHopHeaders[http.CanonicalHeaderKey(extra)] = struct{}{} + } + } + endToEndHeaders := []string{} + for respHeader, _ := range respHeaders { + if _, ok := hopByHopHeaders[respHeader]; !ok { + endToEndHeaders = append(endToEndHeaders, respHeader) + } + } + return endToEndHeaders +} + +func canStore(reqCacheControl, respCacheControl cacheControl) (canStore bool) { + if _, ok := respCacheControl["no-store"]; ok { + return false + } + if _, ok := reqCacheControl["no-store"]; ok { + return false + } + return true +} + +func newGatewayTimeoutResponse(req *http.Request) *http.Response { + var braw bytes.Buffer + braw.WriteString("HTTP/1.1 504 Gateway Timeout\r\n\r\n") + resp, err := http.ReadResponse(bufio.NewReader(&braw), req) + if err != nil { + panic(err) + } + return resp +} + +// cloneRequest returns a clone of the provided *http.Request. +// The clone is a shallow copy of the struct and its Header map. +// (This function copyright goauth2 authors: https://code.google.com/p/goauth2) +func cloneRequest(r *http.Request) *http.Request { + // shallow copy of the struct + r2 := new(http.Request) + *r2 = *r + // deep copy of the Header + r2.Header = make(http.Header) + for k, s := range r.Header { + r2.Header[k] = s + } + return r2 +} + +type cacheControl map[string]string + +func parseCacheControl(headers http.Header) cacheControl { + cc := cacheControl{} + ccHeader := headers.Get("Cache-Control") + for _, part := range strings.Split(ccHeader, ",") { + part = strings.Trim(part, " ") + if part == "" { + continue + } + if strings.ContainsRune(part, '=') { + keyval := strings.Split(part, "=") + cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") + } else { + cc[part] = "" + } + } + return cc +} + +// headerAllCommaSepValues returns all comma-separated values (each +// with whitespace trimmed) for header name in headers. According to +// Section 4.2 of the HTTP/1.1 spec +// (http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2), +// values from multiple occurrences of a header should be concatenated, if +// the header's value is a comma-separated list. +func headerAllCommaSepValues(headers http.Header, name string) []string { + var vals []string + for _, val := range headers[http.CanonicalHeaderKey(name)] { + fields := strings.Split(val, ",") + for i, f := range fields { + fields[i] = strings.TrimSpace(f) + } + vals = append(vals, fields...) + } + return vals +} + +// cachingReadCloser is a wrapper around ReadCloser R that calls OnEOF +// handler with a full copy of the content read from R when EOF is +// reached. +type cachingReadCloser struct { + // Underlying ReadCloser. + R io.ReadCloser + // OnEOF is called with a copy of the content of R when EOF is reached. + OnEOF func(io.Reader) + + buf bytes.Buffer // buf stores a copy of the content of R. +} + +// Read reads the next len(p) bytes from R or until R is drained. The +// return value n is the number of bytes read. If R has no data to +// return, err is io.EOF and OnEOF is called with a full copy of what +// has been read so far. +func (r *cachingReadCloser) Read(p []byte) (n int, err error) { + n, err = r.R.Read(p) + r.buf.Write(p[:n]) + if err == io.EOF { + r.OnEOF(bytes.NewReader(r.buf.Bytes())) + } + return n, err +} + +func (r *cachingReadCloser) Close() error { + return r.R.Close() +} + +// NewMemoryCacheTransport returns a new Transport using the in-memory cache implementation +func NewMemoryCacheTransport() *Transport { + c := NewMemoryCache() + t := NewTransport(c) + return t +} diff --git a/vendor/github.com/gregjones/httpcache/httpcache_test.go b/vendor/github.com/gregjones/httpcache/httpcache_test.go new file mode 100644 index 000000000..a50464180 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/httpcache_test.go @@ -0,0 +1,1475 @@ +package httpcache + +import ( + "bytes" + "errors" + "flag" + "io" + "io/ioutil" + "net/http" + "net/http/httptest" + "os" + "strconv" + "testing" + "time" +) + +var s struct { + server *httptest.Server + client http.Client + transport *Transport + done chan struct{} // Closed to unlock infinite handlers. +} + +type fakeClock struct { + elapsed time.Duration +} + +func (c *fakeClock) since(t time.Time) time.Duration { + return c.elapsed +} + +func TestMain(m *testing.M) { + flag.Parse() + setup() + code := m.Run() + teardown() + os.Exit(code) +} + +func setup() { + tp := NewMemoryCacheTransport() + client := http.Client{Transport: tp} + s.transport = tp + s.client = client + s.done = make(chan struct{}) + + mux := http.NewServeMux() + s.server = httptest.NewServer(mux) + + mux.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Cache-Control", "max-age=3600") + })) + + mux.HandleFunc("/method", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Cache-Control", "max-age=3600") + w.Write([]byte(r.Method)) + })) + + mux.HandleFunc("/range", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + lm := "Fri, 14 Dec 2010 01:01:50 GMT" + if r.Header.Get("if-modified-since") == lm { + w.WriteHeader(http.StatusNotModified) + return + } + w.Header().Set("last-modified", lm) + if r.Header.Get("range") == "bytes=4-9" { + w.WriteHeader(http.StatusPartialContent) + w.Write([]byte(" text ")) + return + } + w.Write([]byte("Some text content")) + })) + + mux.HandleFunc("/nostore", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Cache-Control", "no-store") + })) + + mux.HandleFunc("/etag", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + etag := "124567" + if r.Header.Get("if-none-match") == etag { + w.WriteHeader(http.StatusNotModified) + return + } + w.Header().Set("etag", etag) + })) + + mux.HandleFunc("/lastmodified", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + lm := "Fri, 14 Dec 2010 01:01:50 GMT" + if r.Header.Get("if-modified-since") == lm { + w.WriteHeader(http.StatusNotModified) + return + } + w.Header().Set("last-modified", lm) + })) + + mux.HandleFunc("/varyaccept", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Cache-Control", "max-age=3600") + w.Header().Set("Content-Type", "text/plain") + w.Header().Set("Vary", "Accept") + w.Write([]byte("Some text content")) + })) + + mux.HandleFunc("/doublevary", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Cache-Control", "max-age=3600") + w.Header().Set("Content-Type", "text/plain") + w.Header().Set("Vary", "Accept, Accept-Language") + w.Write([]byte("Some text content")) + })) + mux.HandleFunc("/2varyheaders", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Cache-Control", "max-age=3600") + w.Header().Set("Content-Type", "text/plain") + w.Header().Add("Vary", "Accept") + w.Header().Add("Vary", "Accept-Language") + w.Write([]byte("Some text content")) + })) + mux.HandleFunc("/varyunused", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Cache-Control", "max-age=3600") + w.Header().Set("Content-Type", "text/plain") + w.Header().Set("Vary", "X-Madeup-Header") + w.Write([]byte("Some text content")) + })) + + mux.HandleFunc("/cachederror", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + etag := "abc" + if r.Header.Get("if-none-match") == etag { + w.WriteHeader(http.StatusNotModified) + return + } + w.Header().Set("etag", etag) + w.WriteHeader(http.StatusNotFound) + w.Write([]byte("Not found")) + })) + + updateFieldsCounter := 0 + mux.HandleFunc("/updatefields", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Counter", strconv.Itoa(updateFieldsCounter)) + w.Header().Set("Etag", `"e"`) + updateFieldsCounter++ + if r.Header.Get("if-none-match") != "" { + w.WriteHeader(http.StatusNotModified) + return + } + w.Write([]byte("Some text content")) + })) + + // Take 3 seconds to return 200 OK (for testing client timeouts). + mux.HandleFunc("/3seconds", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + time.Sleep(3 * time.Second) + })) + + mux.HandleFunc("/infinite", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + for { + select { + case <-s.done: + return + default: + w.Write([]byte{0}) + } + } + })) +} + +func teardown() { + close(s.done) + s.server.Close() +} + +func resetTest() { + s.transport.Cache = NewMemoryCache() + clock = &realClock{} +} + +// TestCacheableMethod ensures that uncacheable method does not get stored +// in cache and get incorrectly used for a following cacheable method request. +func TestCacheableMethod(t *testing.T) { + resetTest() + { + req, err := http.NewRequest("POST", s.server.URL+"/method", nil) + if err != nil { + t.Fatal(err) + } + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + var buf bytes.Buffer + _, err = io.Copy(&buf, resp.Body) + if err != nil { + t.Fatal(err) + } + err = resp.Body.Close() + if err != nil { + t.Fatal(err) + } + if got, want := buf.String(), "POST"; got != want { + t.Errorf("got %q, want %q", got, want) + } + if resp.StatusCode != http.StatusOK { + t.Errorf("response status code isn't 200 OK: %v", resp.StatusCode) + } + } + { + req, err := http.NewRequest("GET", s.server.URL+"/method", nil) + if err != nil { + t.Fatal(err) + } + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + var buf bytes.Buffer + _, err = io.Copy(&buf, resp.Body) + if err != nil { + t.Fatal(err) + } + err = resp.Body.Close() + if err != nil { + t.Fatal(err) + } + if got, want := buf.String(), "GET"; got != want { + t.Errorf("got wrong body %q, want %q", got, want) + } + if resp.StatusCode != http.StatusOK { + t.Errorf("response status code isn't 200 OK: %v", resp.StatusCode) + } + if resp.Header.Get(XFromCache) != "" { + t.Errorf("XFromCache header isn't blank") + } + } +} + +func TestDontServeHeadResponseToGetRequest(t *testing.T) { + resetTest() + url := s.server.URL + "/" + req, err := http.NewRequest(http.MethodHead, url, nil) + if err != nil { + t.Fatal(err) + } + _, err = s.client.Do(req) + if err != nil { + t.Fatal(err) + } + req, err = http.NewRequest(http.MethodGet, url, nil) + if err != nil { + t.Fatal(err) + } + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + if resp.Header.Get(XFromCache) != "" { + t.Errorf("Cache should not match") + } +} + +func TestDontStorePartialRangeInCache(t *testing.T) { + resetTest() + { + req, err := http.NewRequest("GET", s.server.URL+"/range", nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("range", "bytes=4-9") + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + var buf bytes.Buffer + _, err = io.Copy(&buf, resp.Body) + if err != nil { + t.Fatal(err) + } + err = resp.Body.Close() + if err != nil { + t.Fatal(err) + } + if got, want := buf.String(), " text "; got != want { + t.Errorf("got %q, want %q", got, want) + } + if resp.StatusCode != http.StatusPartialContent { + t.Errorf("response status code isn't 206 Partial Content: %v", resp.StatusCode) + } + } + { + req, err := http.NewRequest("GET", s.server.URL+"/range", nil) + if err != nil { + t.Fatal(err) + } + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + var buf bytes.Buffer + _, err = io.Copy(&buf, resp.Body) + if err != nil { + t.Fatal(err) + } + err = resp.Body.Close() + if err != nil { + t.Fatal(err) + } + if got, want := buf.String(), "Some text content"; got != want { + t.Errorf("got %q, want %q", got, want) + } + if resp.StatusCode != http.StatusOK { + t.Errorf("response status code isn't 200 OK: %v", resp.StatusCode) + } + if resp.Header.Get(XFromCache) != "" { + t.Error("XFromCache header isn't blank") + } + } + { + req, err := http.NewRequest("GET", s.server.URL+"/range", nil) + if err != nil { + t.Fatal(err) + } + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + var buf bytes.Buffer + _, err = io.Copy(&buf, resp.Body) + if err != nil { + t.Fatal(err) + } + err = resp.Body.Close() + if err != nil { + t.Fatal(err) + } + if got, want := buf.String(), "Some text content"; got != want { + t.Errorf("got %q, want %q", got, want) + } + if resp.StatusCode != http.StatusOK { + t.Errorf("response status code isn't 200 OK: %v", resp.StatusCode) + } + if resp.Header.Get(XFromCache) != "1" { + t.Errorf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + } + { + req, err := http.NewRequest("GET", s.server.URL+"/range", nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("range", "bytes=4-9") + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + var buf bytes.Buffer + _, err = io.Copy(&buf, resp.Body) + if err != nil { + t.Fatal(err) + } + err = resp.Body.Close() + if err != nil { + t.Fatal(err) + } + if got, want := buf.String(), " text "; got != want { + t.Errorf("got %q, want %q", got, want) + } + if resp.StatusCode != http.StatusPartialContent { + t.Errorf("response status code isn't 206 Partial Content: %v", resp.StatusCode) + } + } +} + +func TestCacheOnlyIfBodyRead(t *testing.T) { + resetTest() + { + req, err := http.NewRequest("GET", s.server.URL, nil) + if err != nil { + t.Fatal(err) + } + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + // We do not read the body + resp.Body.Close() + } + { + req, err := http.NewRequest("GET", s.server.URL, nil) + if err != nil { + t.Fatal(err) + } + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatalf("XFromCache header isn't blank") + } + } +} + +func TestOnlyReadBodyOnDemand(t *testing.T) { + resetTest() + + req, err := http.NewRequest("GET", s.server.URL+"/infinite", nil) + if err != nil { + t.Fatal(err) + } + resp, err := s.client.Do(req) // This shouldn't hang forever. + if err != nil { + t.Fatal(err) + } + buf := make([]byte, 10) // Only partially read the body. + _, err = resp.Body.Read(buf) + if err != nil { + t.Fatal(err) + } + resp.Body.Close() +} + +func TestGetOnlyIfCachedHit(t *testing.T) { + resetTest() + { + req, err := http.NewRequest("GET", s.server.URL, nil) + if err != nil { + t.Fatal(err) + } + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + } + { + req, err := http.NewRequest("GET", s.server.URL, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Add("cache-control", "only-if-cached") + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "1" { + t.Fatalf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + if resp.StatusCode != http.StatusOK { + t.Fatalf("response status code isn't 200 OK: %v", resp.StatusCode) + } + } +} + +func TestGetOnlyIfCachedMiss(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Add("cache-control", "only-if-cached") + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + if resp.StatusCode != http.StatusGatewayTimeout { + t.Fatalf("response status code isn't 504 GatewayTimeout: %v", resp.StatusCode) + } +} + +func TestGetNoStoreRequest(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Add("Cache-Control", "no-store") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } +} + +func TestGetNoStoreResponse(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL+"/nostore", nil) + if err != nil { + t.Fatal(err) + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } +} + +func TestGetWithEtag(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL+"/etag", nil) + if err != nil { + t.Fatal(err) + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "1" { + t.Fatalf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + // additional assertions to verify that 304 response is converted properly + if resp.StatusCode != http.StatusOK { + t.Fatalf("response status code isn't 200 OK: %v", resp.StatusCode) + } + if _, ok := resp.Header["Connection"]; ok { + t.Fatalf("Connection header isn't absent") + } + } +} + +func TestGetWithLastModified(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL+"/lastmodified", nil) + if err != nil { + t.Fatal(err) + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "1" { + t.Fatalf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + } +} + +func TestGetWithVary(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL+"/varyaccept", nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Accept", "text/plain") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get("Vary") != "Accept" { + t.Fatalf(`Vary header isn't "Accept": %v`, resp.Header.Get("Vary")) + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "1" { + t.Fatalf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + } + req.Header.Set("Accept", "text/html") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } + req.Header.Set("Accept", "") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } +} + +func TestGetWithDoubleVary(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL+"/doublevary", nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Accept", "text/plain") + req.Header.Set("Accept-Language", "da, en-gb;q=0.8, en;q=0.7") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get("Vary") == "" { + t.Fatalf(`Vary header is blank`) + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "1" { + t.Fatalf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + } + req.Header.Set("Accept-Language", "") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } + req.Header.Set("Accept-Language", "da") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } +} + +func TestGetWith2VaryHeaders(t *testing.T) { + resetTest() + // Tests that multiple Vary headers' comma-separated lists are + // merged. See https://github.com/gregjones/httpcache/issues/27. + const ( + accept = "text/plain" + acceptLanguage = "da, en-gb;q=0.8, en;q=0.7" + ) + req, err := http.NewRequest("GET", s.server.URL+"/2varyheaders", nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Accept", accept) + req.Header.Set("Accept-Language", acceptLanguage) + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get("Vary") == "" { + t.Fatalf(`Vary header is blank`) + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "1" { + t.Fatalf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + } + req.Header.Set("Accept-Language", "") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } + req.Header.Set("Accept-Language", "da") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } + req.Header.Set("Accept-Language", acceptLanguage) + req.Header.Set("Accept", "") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + } + req.Header.Set("Accept", "image/png") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "" { + t.Fatal("XFromCache header isn't blank") + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "1" { + t.Fatalf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + } +} + +func TestGetVaryUnused(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL+"/varyunused", nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Accept", "text/plain") + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get("Vary") == "" { + t.Fatalf(`Vary header is blank`) + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "1" { + t.Fatalf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + } +} + +func TestUpdateFields(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL+"/updatefields", nil) + if err != nil { + t.Fatal(err) + } + var counter, counter2 string + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + counter = resp.Header.Get("x-counter") + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.Header.Get(XFromCache) != "1" { + t.Fatalf(`XFromCache header isn't "1": %v`, resp.Header.Get(XFromCache)) + } + counter2 = resp.Header.Get("x-counter") + } + if counter == counter2 { + t.Fatalf(`both "x-counter" values are equal: %v %v`, counter, counter2) + } +} + +// This tests the fix for https://github.com/gregjones/httpcache/issues/74. +// Previously, after validating a cached response, its StatusCode +// was incorrectly being replaced. +func TestCachedErrorsKeepStatus(t *testing.T) { + resetTest() + req, err := http.NewRequest("GET", s.server.URL+"/cachederror", nil) + if err != nil { + t.Fatal(err) + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + io.Copy(ioutil.Discard, resp.Body) + } + { + resp, err := s.client.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusNotFound { + t.Fatalf("Status code isn't 404: %d", resp.StatusCode) + } + } +} + +func TestParseCacheControl(t *testing.T) { + resetTest() + h := http.Header{} + for range parseCacheControl(h) { + t.Fatal("cacheControl should be empty") + } + + h.Set("cache-control", "no-cache") + { + cc := parseCacheControl(h) + if _, ok := cc["foo"]; ok { + t.Error(`Value "foo" shouldn't exist`) + } + noCache, ok := cc["no-cache"] + if !ok { + t.Fatalf(`"no-cache" value isn't set`) + } + if noCache != "" { + t.Fatalf(`"no-cache" value isn't blank: %v`, noCache) + } + } + h.Set("cache-control", "no-cache, max-age=3600") + { + cc := parseCacheControl(h) + noCache, ok := cc["no-cache"] + if !ok { + t.Fatalf(`"no-cache" value isn't set`) + } + if noCache != "" { + t.Fatalf(`"no-cache" value isn't blank: %v`, noCache) + } + if cc["max-age"] != "3600" { + t.Fatalf(`"max-age" value isn't "3600": %v`, cc["max-age"]) + } + } +} + +func TestNoCacheRequestExpiration(t *testing.T) { + resetTest() + respHeaders := http.Header{} + respHeaders.Set("Cache-Control", "max-age=7200") + + reqHeaders := http.Header{} + reqHeaders.Set("Cache-Control", "no-cache") + if getFreshness(respHeaders, reqHeaders) != transparent { + t.Fatal("freshness isn't transparent") + } +} + +func TestNoCacheResponseExpiration(t *testing.T) { + resetTest() + respHeaders := http.Header{} + respHeaders.Set("Cache-Control", "no-cache") + respHeaders.Set("Expires", "Wed, 19 Apr 3000 11:43:00 GMT") + + reqHeaders := http.Header{} + if getFreshness(respHeaders, reqHeaders) != stale { + t.Fatal("freshness isn't stale") + } +} + +func TestReqMustRevalidate(t *testing.T) { + resetTest() + // not paying attention to request setting max-stale means never returning stale + // responses, so always acting as if must-revalidate is set + respHeaders := http.Header{} + + reqHeaders := http.Header{} + reqHeaders.Set("Cache-Control", "must-revalidate") + if getFreshness(respHeaders, reqHeaders) != stale { + t.Fatal("freshness isn't stale") + } +} + +func TestRespMustRevalidate(t *testing.T) { + resetTest() + respHeaders := http.Header{} + respHeaders.Set("Cache-Control", "must-revalidate") + + reqHeaders := http.Header{} + if getFreshness(respHeaders, reqHeaders) != stale { + t.Fatal("freshness isn't stale") + } +} + +func TestFreshExpiration(t *testing.T) { + resetTest() + now := time.Now() + respHeaders := http.Header{} + respHeaders.Set("date", now.Format(time.RFC1123)) + respHeaders.Set("expires", now.Add(time.Duration(2)*time.Second).Format(time.RFC1123)) + + reqHeaders := http.Header{} + if getFreshness(respHeaders, reqHeaders) != fresh { + t.Fatal("freshness isn't fresh") + } + + clock = &fakeClock{elapsed: 3 * time.Second} + if getFreshness(respHeaders, reqHeaders) != stale { + t.Fatal("freshness isn't stale") + } +} + +func TestMaxAge(t *testing.T) { + resetTest() + now := time.Now() + respHeaders := http.Header{} + respHeaders.Set("date", now.Format(time.RFC1123)) + respHeaders.Set("cache-control", "max-age=2") + + reqHeaders := http.Header{} + if getFreshness(respHeaders, reqHeaders) != fresh { + t.Fatal("freshness isn't fresh") + } + + clock = &fakeClock{elapsed: 3 * time.Second} + if getFreshness(respHeaders, reqHeaders) != stale { + t.Fatal("freshness isn't stale") + } +} + +func TestMaxAgeZero(t *testing.T) { + resetTest() + now := time.Now() + respHeaders := http.Header{} + respHeaders.Set("date", now.Format(time.RFC1123)) + respHeaders.Set("cache-control", "max-age=0") + + reqHeaders := http.Header{} + if getFreshness(respHeaders, reqHeaders) != stale { + t.Fatal("freshness isn't stale") + } +} + +func TestBothMaxAge(t *testing.T) { + resetTest() + now := time.Now() + respHeaders := http.Header{} + respHeaders.Set("date", now.Format(time.RFC1123)) + respHeaders.Set("cache-control", "max-age=2") + + reqHeaders := http.Header{} + reqHeaders.Set("cache-control", "max-age=0") + if getFreshness(respHeaders, reqHeaders) != stale { + t.Fatal("freshness isn't stale") + } +} + +func TestMinFreshWithExpires(t *testing.T) { + resetTest() + now := time.Now() + respHeaders := http.Header{} + respHeaders.Set("date", now.Format(time.RFC1123)) + respHeaders.Set("expires", now.Add(time.Duration(2)*time.Second).Format(time.RFC1123)) + + reqHeaders := http.Header{} + reqHeaders.Set("cache-control", "min-fresh=1") + if getFreshness(respHeaders, reqHeaders) != fresh { + t.Fatal("freshness isn't fresh") + } + + reqHeaders = http.Header{} + reqHeaders.Set("cache-control", "min-fresh=2") + if getFreshness(respHeaders, reqHeaders) != stale { + t.Fatal("freshness isn't stale") + } +} + +func TestEmptyMaxStale(t *testing.T) { + resetTest() + now := time.Now() + respHeaders := http.Header{} + respHeaders.Set("date", now.Format(time.RFC1123)) + respHeaders.Set("cache-control", "max-age=20") + + reqHeaders := http.Header{} + reqHeaders.Set("cache-control", "max-stale") + clock = &fakeClock{elapsed: 10 * time.Second} + if getFreshness(respHeaders, reqHeaders) != fresh { + t.Fatal("freshness isn't fresh") + } + + clock = &fakeClock{elapsed: 60 * time.Second} + if getFreshness(respHeaders, reqHeaders) != fresh { + t.Fatal("freshness isn't fresh") + } +} + +func TestMaxStaleValue(t *testing.T) { + resetTest() + now := time.Now() + respHeaders := http.Header{} + respHeaders.Set("date", now.Format(time.RFC1123)) + respHeaders.Set("cache-control", "max-age=10") + + reqHeaders := http.Header{} + reqHeaders.Set("cache-control", "max-stale=20") + clock = &fakeClock{elapsed: 5 * time.Second} + if getFreshness(respHeaders, reqHeaders) != fresh { + t.Fatal("freshness isn't fresh") + } + + clock = &fakeClock{elapsed: 15 * time.Second} + if getFreshness(respHeaders, reqHeaders) != fresh { + t.Fatal("freshness isn't fresh") + } + + clock = &fakeClock{elapsed: 30 * time.Second} + if getFreshness(respHeaders, reqHeaders) != stale { + t.Fatal("freshness isn't stale") + } +} + +func containsHeader(headers []string, header string) bool { + for _, v := range headers { + if http.CanonicalHeaderKey(v) == http.CanonicalHeaderKey(header) { + return true + } + } + return false +} + +func TestGetEndToEndHeaders(t *testing.T) { + resetTest() + var ( + headers http.Header + end2end []string + ) + + headers = http.Header{} + headers.Set("content-type", "text/html") + headers.Set("te", "deflate") + + end2end = getEndToEndHeaders(headers) + if !containsHeader(end2end, "content-type") { + t.Fatal(`doesn't contain "content-type" header`) + } + if containsHeader(end2end, "te") { + t.Fatal(`doesn't contain "te" header`) + } + + headers = http.Header{} + headers.Set("connection", "content-type") + headers.Set("content-type", "text/csv") + headers.Set("te", "deflate") + end2end = getEndToEndHeaders(headers) + if containsHeader(end2end, "connection") { + t.Fatal(`doesn't contain "connection" header`) + } + if containsHeader(end2end, "content-type") { + t.Fatal(`doesn't contain "content-type" header`) + } + if containsHeader(end2end, "te") { + t.Fatal(`doesn't contain "te" header`) + } + + headers = http.Header{} + end2end = getEndToEndHeaders(headers) + if len(end2end) != 0 { + t.Fatal(`non-zero end2end headers`) + } + + headers = http.Header{} + headers.Set("connection", "content-type") + end2end = getEndToEndHeaders(headers) + if len(end2end) != 0 { + t.Fatal(`non-zero end2end headers`) + } +} + +type transportMock struct { + response *http.Response + err error +} + +func (t transportMock) RoundTrip(req *http.Request) (resp *http.Response, err error) { + return t.response, t.err +} + +func TestStaleIfErrorRequest(t *testing.T) { + resetTest() + now := time.Now() + tmock := transportMock{ + response: &http.Response{ + Status: http.StatusText(http.StatusOK), + StatusCode: http.StatusOK, + Header: http.Header{ + "Date": []string{now.Format(time.RFC1123)}, + "Cache-Control": []string{"no-cache"}, + }, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte("some data"))), + }, + err: nil, + } + tp := NewMemoryCacheTransport() + tp.Transport = &tmock + + // First time, response is cached on success + r, _ := http.NewRequest("GET", "http://somewhere.com/", nil) + r.Header.Set("Cache-Control", "stale-if-error") + resp, err := tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + // On failure, response is returned from the cache + tmock.response = nil + tmock.err = errors.New("some error") + resp, err = tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } +} + +func TestStaleIfErrorRequestLifetime(t *testing.T) { + resetTest() + now := time.Now() + tmock := transportMock{ + response: &http.Response{ + Status: http.StatusText(http.StatusOK), + StatusCode: http.StatusOK, + Header: http.Header{ + "Date": []string{now.Format(time.RFC1123)}, + "Cache-Control": []string{"no-cache"}, + }, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte("some data"))), + }, + err: nil, + } + tp := NewMemoryCacheTransport() + tp.Transport = &tmock + + // First time, response is cached on success + r, _ := http.NewRequest("GET", "http://somewhere.com/", nil) + r.Header.Set("Cache-Control", "stale-if-error=100") + resp, err := tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + // On failure, response is returned from the cache + tmock.response = nil + tmock.err = errors.New("some error") + resp, err = tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } + + // Same for http errors + tmock.response = &http.Response{StatusCode: http.StatusInternalServerError} + tmock.err = nil + resp, err = tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } + + // If failure last more than max stale, error is returned + clock = &fakeClock{elapsed: 200 * time.Second} + _, err = tp.RoundTrip(r) + if err != tmock.err { + t.Fatalf("got err %v, want %v", err, tmock.err) + } +} + +func TestStaleIfErrorResponse(t *testing.T) { + resetTest() + now := time.Now() + tmock := transportMock{ + response: &http.Response{ + Status: http.StatusText(http.StatusOK), + StatusCode: http.StatusOK, + Header: http.Header{ + "Date": []string{now.Format(time.RFC1123)}, + "Cache-Control": []string{"no-cache, stale-if-error"}, + }, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte("some data"))), + }, + err: nil, + } + tp := NewMemoryCacheTransport() + tp.Transport = &tmock + + // First time, response is cached on success + r, _ := http.NewRequest("GET", "http://somewhere.com/", nil) + resp, err := tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + // On failure, response is returned from the cache + tmock.response = nil + tmock.err = errors.New("some error") + resp, err = tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } +} + +func TestStaleIfErrorResponseLifetime(t *testing.T) { + resetTest() + now := time.Now() + tmock := transportMock{ + response: &http.Response{ + Status: http.StatusText(http.StatusOK), + StatusCode: http.StatusOK, + Header: http.Header{ + "Date": []string{now.Format(time.RFC1123)}, + "Cache-Control": []string{"no-cache, stale-if-error=100"}, + }, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte("some data"))), + }, + err: nil, + } + tp := NewMemoryCacheTransport() + tp.Transport = &tmock + + // First time, response is cached on success + r, _ := http.NewRequest("GET", "http://somewhere.com/", nil) + resp, err := tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + // On failure, response is returned from the cache + tmock.response = nil + tmock.err = errors.New("some error") + resp, err = tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } + + // If failure last more than max stale, error is returned + clock = &fakeClock{elapsed: 200 * time.Second} + _, err = tp.RoundTrip(r) + if err != tmock.err { + t.Fatalf("got err %v, want %v", err, tmock.err) + } +} + +// This tests the fix for https://github.com/gregjones/httpcache/issues/74. +// Previously, after a stale response was used after encountering an error, +// its StatusCode was being incorrectly replaced. +func TestStaleIfErrorKeepsStatus(t *testing.T) { + resetTest() + now := time.Now() + tmock := transportMock{ + response: &http.Response{ + Status: http.StatusText(http.StatusNotFound), + StatusCode: http.StatusNotFound, + Header: http.Header{ + "Date": []string{now.Format(time.RFC1123)}, + "Cache-Control": []string{"no-cache"}, + }, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte("some data"))), + }, + err: nil, + } + tp := NewMemoryCacheTransport() + tp.Transport = &tmock + + // First time, response is cached on success + r, _ := http.NewRequest("GET", "http://somewhere.com/", nil) + r.Header.Set("Cache-Control", "stale-if-error") + resp, err := tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + // On failure, response is returned from the cache + tmock.response = nil + tmock.err = errors.New("some error") + resp, err = tp.RoundTrip(r) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("resp is nil") + } + if resp.StatusCode != http.StatusNotFound { + t.Fatalf("Status wasn't 404: %d", resp.StatusCode) + } +} + +// Test that http.Client.Timeout is respected when cache transport is used. +// That is so as long as request cancellation is propagated correctly. +// In the past, that required CancelRequest to be implemented correctly, +// but modern http.Client uses Request.Cancel (or request context) instead, +// so we don't have to do anything. +func TestClientTimeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping timeout test in short mode") // Because it takes at least 3 seconds to run. + } + resetTest() + client := &http.Client{ + Transport: NewMemoryCacheTransport(), + Timeout: time.Second, + } + started := time.Now() + resp, err := client.Get(s.server.URL + "/3seconds") + taken := time.Since(started) + if err == nil { + t.Error("got nil error, want timeout error") + } + if resp != nil { + t.Error("got non-nil resp, want nil resp") + } + if taken >= 2*time.Second { + t.Error("client.Do took 2+ seconds, want < 2 seconds") + } +} diff --git a/vendor/github.com/gregjones/httpcache/leveldbcache/leveldbcache.go b/vendor/github.com/gregjones/httpcache/leveldbcache/leveldbcache.go new file mode 100644 index 000000000..9bcb7e277 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/leveldbcache/leveldbcache.go @@ -0,0 +1,51 @@ +// Package leveldbcache provides an implementation of httpcache.Cache that +// uses github.com/syndtr/goleveldb/leveldb +package leveldbcache + +import ( + "github.com/syndtr/goleveldb/leveldb" +) + +// Cache is an implementation of httpcache.Cache with leveldb storage +type Cache struct { + db *leveldb.DB +} + +// Get returns the response corresponding to key if present +func (c *Cache) Get(key string) (resp []byte, ok bool) { + var err error + resp, err = c.db.Get([]byte(key), nil) + if err != nil { + return []byte{}, false + } + return resp, true +} + +// Set saves a response to the cache as key +func (c *Cache) Set(key string, resp []byte) { + c.db.Put([]byte(key), resp, nil) +} + +// Delete removes the response with key from the cache +func (c *Cache) Delete(key string) { + c.db.Delete([]byte(key), nil) +} + +// New returns a new Cache that will store leveldb in path +func New(path string) (*Cache, error) { + cache := &Cache{} + + var err error + cache.db, err = leveldb.OpenFile(path, nil) + + if err != nil { + return nil, err + } + return cache, nil +} + +// NewWithDB returns a new Cache using the provided leveldb as underlying +// storage. +func NewWithDB(db *leveldb.DB) *Cache { + return &Cache{db} +} diff --git a/vendor/github.com/gregjones/httpcache/leveldbcache/leveldbcache_test.go b/vendor/github.com/gregjones/httpcache/leveldbcache/leveldbcache_test.go new file mode 100644 index 000000000..b885c0169 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/leveldbcache/leveldbcache_test.go @@ -0,0 +1,46 @@ +package leveldbcache + +import ( + "bytes" + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +func TestDiskCache(t *testing.T) { + tempDir, err := ioutil.TempDir("", "httpcache") + if err != nil { + t.Fatalf("TempDir: %v", err) + } + defer os.RemoveAll(tempDir) + + cache, err := New(filepath.Join(tempDir, "db")) + if err != nil { + t.Fatalf("New leveldb,: %v", err) + } + + key := "testKey" + _, ok := cache.Get(key) + if ok { + t.Fatal("retrieved key before adding it") + } + + val := []byte("some bytes") + cache.Set(key, val) + + retVal, ok := cache.Get(key) + if !ok { + t.Fatal("could not retrieve an element we just added") + } + if !bytes.Equal(retVal, val) { + t.Fatal("retrieved a different value than what we put in") + } + + cache.Delete(key) + + _, ok = cache.Get(key) + if ok { + t.Fatal("deleted key still present") + } +} diff --git a/vendor/github.com/gregjones/httpcache/memcache/appengine.go b/vendor/github.com/gregjones/httpcache/memcache/appengine.go new file mode 100644 index 000000000..e68d9bc09 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/memcache/appengine.go @@ -0,0 +1,61 @@ +// +build appengine + +// Package memcache provides an implementation of httpcache.Cache that uses App +// Engine's memcache package to store cached responses. +// +// When not built for Google App Engine, this package will provide an +// implementation that connects to a specified memcached server. See the +// memcache.go file in this package for details. +package memcache + +import ( + "appengine" + "appengine/memcache" +) + +// Cache is an implementation of httpcache.Cache that caches responses in App +// Engine's memcache. +type Cache struct { + appengine.Context +} + +// cacheKey modifies an httpcache key for use in memcache. Specifically, it +// prefixes keys to avoid collision with other data stored in memcache. +func cacheKey(key string) string { + return "httpcache:" + key +} + +// Get returns the response corresponding to key if present. +func (c *Cache) Get(key string) (resp []byte, ok bool) { + item, err := memcache.Get(c.Context, cacheKey(key)) + if err != nil { + if err != memcache.ErrCacheMiss { + c.Context.Errorf("error getting cached response: %v", err) + } + return nil, false + } + return item.Value, true +} + +// Set saves a response to the cache as key. +func (c *Cache) Set(key string, resp []byte) { + item := &memcache.Item{ + Key: cacheKey(key), + Value: resp, + } + if err := memcache.Set(c.Context, item); err != nil { + c.Context.Errorf("error caching response: %v", err) + } +} + +// Delete removes the response with key from the cache. +func (c *Cache) Delete(key string) { + if err := memcache.Delete(c.Context, cacheKey(key)); err != nil { + c.Context.Errorf("error deleting cached response: %v", err) + } +} + +// New returns a new Cache for the given context. +func New(ctx appengine.Context) *Cache { + return &Cache{ctx} +} diff --git a/vendor/github.com/gregjones/httpcache/memcache/appengine_test.go b/vendor/github.com/gregjones/httpcache/memcache/appengine_test.go new file mode 100644 index 000000000..818b2776e --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/memcache/appengine_test.go @@ -0,0 +1,44 @@ +// +build appengine + +package memcache + +import ( + "bytes" + "testing" + + "appengine/aetest" +) + +func TestAppEngine(t *testing.T) { + ctx, err := aetest.NewContext(nil) + if err != nil { + t.Fatal(err) + } + defer ctx.Close() + + cache := New(ctx) + + key := "testKey" + _, ok := cache.Get(key) + if ok { + t.Fatal("retrieved key before adding it") + } + + val := []byte("some bytes") + cache.Set(key, val) + + retVal, ok := cache.Get(key) + if !ok { + t.Fatal("could not retrieve an element we just added") + } + if !bytes.Equal(retVal, val) { + t.Fatal("retrieved a different value than what we put in") + } + + cache.Delete(key) + + _, ok = cache.Get(key) + if ok { + t.Fatal("deleted key still present") + } +} diff --git a/vendor/github.com/gregjones/httpcache/memcache/memcache.go b/vendor/github.com/gregjones/httpcache/memcache/memcache.go new file mode 100644 index 000000000..462f0e541 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/memcache/memcache.go @@ -0,0 +1,60 @@ +// +build !appengine + +// Package memcache provides an implementation of httpcache.Cache that uses +// gomemcache to store cached responses. +// +// When built for Google App Engine, this package will provide an +// implementation that uses App Engine's memcache service. See the +// appengine.go file in this package for details. +package memcache + +import ( + "github.com/bradfitz/gomemcache/memcache" +) + +// Cache is an implementation of httpcache.Cache that caches responses in a +// memcache server. +type Cache struct { + *memcache.Client +} + +// cacheKey modifies an httpcache key for use in memcache. Specifically, it +// prefixes keys to avoid collision with other data stored in memcache. +func cacheKey(key string) string { + return "httpcache:" + key +} + +// Get returns the response corresponding to key if present. +func (c *Cache) Get(key string) (resp []byte, ok bool) { + item, err := c.Client.Get(cacheKey(key)) + if err != nil { + return nil, false + } + return item.Value, true +} + +// Set saves a response to the cache as key. +func (c *Cache) Set(key string, resp []byte) { + item := &memcache.Item{ + Key: cacheKey(key), + Value: resp, + } + c.Client.Set(item) +} + +// Delete removes the response with key from the cache. +func (c *Cache) Delete(key string) { + c.Client.Delete(cacheKey(key)) +} + +// New returns a new Cache using the provided memcache server(s) with equal +// weight. If a server is listed multiple times, it gets a proportional amount +// of weight. +func New(server ...string) *Cache { + return NewWithClient(memcache.New(server...)) +} + +// NewWithClient returns a new Cache with the given memcache client. +func NewWithClient(client *memcache.Client) *Cache { + return &Cache{client} +} diff --git a/vendor/github.com/gregjones/httpcache/memcache/memcache_test.go b/vendor/github.com/gregjones/httpcache/memcache/memcache_test.go new file mode 100644 index 000000000..4dcc547c6 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/memcache/memcache_test.go @@ -0,0 +1,47 @@ +// +build !appengine + +package memcache + +import ( + "bytes" + "net" + "testing" +) + +const testServer = "localhost:11211" + +func TestMemCache(t *testing.T) { + conn, err := net.Dial("tcp", testServer) + if err != nil { + // TODO: rather than skip the test, fall back to a faked memcached server + t.Skipf("skipping test; no server running at %s", testServer) + } + conn.Write([]byte("flush_all\r\n")) // flush memcache + conn.Close() + + cache := New(testServer) + + key := "testKey" + _, ok := cache.Get(key) + if ok { + t.Fatal("retrieved key before adding it") + } + + val := []byte("some bytes") + cache.Set(key, val) + + retVal, ok := cache.Get(key) + if !ok { + t.Fatal("could not retrieve an element we just added") + } + if !bytes.Equal(retVal, val) { + t.Fatal("retrieved a different value than what we put in") + } + + cache.Delete(key) + + _, ok = cache.Get(key) + if ok { + t.Fatal("deleted key still present") + } +} diff --git a/vendor/github.com/gregjones/httpcache/redis/redis.go b/vendor/github.com/gregjones/httpcache/redis/redis.go new file mode 100644 index 000000000..3143d4438 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/redis/redis.go @@ -0,0 +1,43 @@ +// Package redis provides a redis interface for http caching. +package redis + +import ( + "github.com/garyburd/redigo/redis" + "github.com/gregjones/httpcache" +) + +// cache is an implementation of httpcache.Cache that caches responses in a +// redis server. +type cache struct { + redis.Conn +} + +// cacheKey modifies an httpcache key for use in redis. Specifically, it +// prefixes keys to avoid collision with other data stored in redis. +func cacheKey(key string) string { + return "rediscache:" + key +} + +// Get returns the response corresponding to key if present. +func (c cache) Get(key string) (resp []byte, ok bool) { + item, err := redis.Bytes(c.Do("GET", cacheKey(key))) + if err != nil { + return nil, false + } + return item, true +} + +// Set saves a response to the cache as key. +func (c cache) Set(key string, resp []byte) { + c.Do("SET", cacheKey(key), resp) +} + +// Delete removes the response with key from the cache. +func (c cache) Delete(key string) { + c.Do("DEL", cacheKey(key)) +} + +// NewWithClient returns a new Cache with the given redis connection. +func NewWithClient(client redis.Conn) httpcache.Cache { + return cache{client} +} diff --git a/vendor/github.com/gregjones/httpcache/redis/redis_test.go b/vendor/github.com/gregjones/httpcache/redis/redis_test.go new file mode 100644 index 000000000..72f6f619a --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/redis/redis_test.go @@ -0,0 +1,43 @@ +package redis + +import ( + "bytes" + "testing" + + "github.com/garyburd/redigo/redis" +) + +func TestRedisCache(t *testing.T) { + conn, err := redis.Dial("tcp", "localhost:6379") + if err != nil { + // TODO: rather than skip the test, fall back to a faked redis server + t.Skipf("skipping test; no server running at localhost:6379") + } + conn.Do("FLUSHALL") + + cache := NewWithClient(conn) + + key := "testKey" + _, ok := cache.Get(key) + if ok { + t.Fatal("retrieved key before adding it") + } + + val := []byte("some bytes") + cache.Set(key, val) + + retVal, ok := cache.Get(key) + if !ok { + t.Fatal("could not retrieve an element we just added") + } + if !bytes.Equal(retVal, val) { + t.Fatal("retrieved a different value than what we put in") + } + + cache.Delete(key) + + _, ok = cache.Get(key) + if ok { + t.Fatal("deleted key still present") + } +} diff --git a/vendor/github.com/howeyc/gopass/.travis.yml b/vendor/github.com/howeyc/gopass/.travis.yml deleted file mode 100644 index cc5d509fd..000000000 --- a/vendor/github.com/howeyc/gopass/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: go - -os: - - linux - - osx - -go: - - 1.3 - - 1.4 - - 1.5 - - tip diff --git a/vendor/github.com/howeyc/gopass/LICENSE.txt b/vendor/github.com/howeyc/gopass/LICENSE.txt deleted file mode 100644 index 14f74708a..000000000 --- a/vendor/github.com/howeyc/gopass/LICENSE.txt +++ /dev/null @@ -1,15 +0,0 @@ -ISC License - -Copyright (c) 2012 Chris Howey - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/github.com/howeyc/gopass/OPENSOLARIS.LICENSE b/vendor/github.com/howeyc/gopass/OPENSOLARIS.LICENSE deleted file mode 100644 index da23621dc..000000000 --- a/vendor/github.com/howeyc/gopass/OPENSOLARIS.LICENSE +++ /dev/null @@ -1,384 +0,0 @@ -Unless otherwise noted, all files in this distribution are released -under the Common Development and Distribution License (CDDL). -Exceptions are noted within the associated source files. - --------------------------------------------------------------------- - - -COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0 - -1. Definitions. - - 1.1. "Contributor" means each individual or entity that creates - or contributes to the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Software, prior Modifications used by a Contributor (if any), - and the Modifications made by that particular Contributor. - - 1.3. "Covered Software" means (a) the Original Software, or (b) - Modifications, or (c) the combination of files containing - Original Software with files containing Modifications, in - each case including portions thereof. - - 1.4. "Executable" means the Covered Software in any form other - than Source Code. - - 1.5. "Initial Developer" means the individual or entity that first - makes Original Software available under this License. - - 1.6. "Larger Work" means a work which combines Covered Software or - portions thereof with code not governed by the terms of this - License. - - 1.7. "License" means this document. - - 1.8. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed - herein. - - 1.9. "Modifications" means the Source Code and Executable form of - any of the following: - - A. Any file that results from an addition to, deletion from or - modification of the contents of a file containing Original - Software or previous Modifications; - - B. Any new file that contains any part of the Original - Software or previous Modifications; or - - C. Any new file that is contributed or otherwise made - available under the terms of this License. - - 1.10. "Original Software" means the Source Code and Executable - form of computer software code that is originally released - under this License. - - 1.11. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, - process, and apparatus claims, in any patent Licensable by - grantor. - - 1.12. "Source Code" means (a) the common form of computer software - code in which modifications are made and (b) associated - documentation included in or with such code. - - 1.13. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms - of, this License. For legal entities, "You" includes any - entity which controls, is controlled by, or is under common - control with You. For purposes of this definition, - "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty - percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants. - - 2.1. The Initial Developer Grant. - - Conditioned upon Your compliance with Section 3.1 below and - subject to third party intellectual property claims, the Initial - Developer hereby grants You a world-wide, royalty-free, - non-exclusive license: - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer, to use, - reproduce, modify, display, perform, sublicense and - distribute the Original Software (or portions thereof), - with or without Modifications, and/or as part of a Larger - Work; and - - (b) under Patent Claims infringed by the making, using or - selling of Original Software, to make, have made, use, - practice, sell, and offer for sale, and/or otherwise - dispose of the Original Software (or portions thereof). - - (c) The licenses granted in Sections 2.1(a) and (b) are - effective on the date Initial Developer first distributes - or otherwise makes the Original Software available to a - third party under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: (1) for code that You delete from the Original - Software, or (2) for infringements caused by: (i) the - modification of the Original Software, or (ii) the - combination of the Original Software with other software - or devices. - - 2.2. Contributor Grant. - - Conditioned upon Your compliance with Section 3.1 below and - subject to third party intellectual property claims, each - Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor to use, reproduce, - modify, display, perform, sublicense and distribute the - Modifications created by such Contributor (or portions - thereof), either on an unmodified basis, with other - Modifications, as Covered Software and/or as part of a - Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either - alone and/or in combination with its Contributor Version - (or portions of such combination), to make, use, sell, - offer for sale, have made, and/or otherwise dispose of: - (1) Modifications made by that Contributor (or portions - thereof); and (2) the combination of Modifications made by - that Contributor with its Contributor Version (or portions - of such combination). - - (c) The licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first distributes or - otherwise makes the Modifications available to a third - party. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: (1) for any code that Contributor has deleted - from the Contributor Version; (2) for infringements caused - by: (i) third party modifications of Contributor Version, - or (ii) the combination of Modifications made by that - Contributor with other software (except as part of the - Contributor Version) or other devices; or (3) under Patent - Claims infringed by Covered Software in the absence of - Modifications made by that Contributor. - -3. Distribution Obligations. - - 3.1. Availability of Source Code. - - Any Covered Software that You distribute or otherwise make - available in Executable form must also be made available in Source - Code form and that Source Code form must be distributed only under - the terms of this License. You must include a copy of this - License with every copy of the Source Code form of the Covered - Software You distribute or otherwise make available. You must - inform recipients of any such Covered Software in Executable form - as to how they can obtain such Covered Software in Source Code - form in a reasonable manner on or through a medium customarily - used for software exchange. - - 3.2. Modifications. - - The Modifications that You create or to which You contribute are - governed by the terms of this License. You represent that You - believe Your Modifications are Your original creation(s) and/or - You have sufficient rights to grant the rights conveyed by this - License. - - 3.3. Required Notices. - - You must include a notice in each of Your Modifications that - identifies You as the Contributor of the Modification. You may - not remove or alter any copyright, patent or trademark notices - contained within the Covered Software, or any notices of licensing - or any descriptive text giving attribution to any Contributor or - the Initial Developer. - - 3.4. Application of Additional Terms. - - You may not offer or impose any terms on any Covered Software in - Source Code form that alters or restricts the applicable version - of this License or the recipients' rights hereunder. You may - choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of - Covered Software. However, you may do so only on Your own behalf, - and not on behalf of the Initial Developer or any Contributor. - You must make it absolutely clear that any such warranty, support, - indemnity or liability obligation is offered by You alone, and You - hereby agree to indemnify the Initial Developer and every - Contributor for any liability incurred by the Initial Developer or - such Contributor as a result of warranty, support, indemnity or - liability terms You offer. - - 3.5. Distribution of Executable Versions. - - You may distribute the Executable form of the Covered Software - under the terms of this License or under the terms of a license of - Your choice, which may contain terms different from this License, - provided that You are in compliance with the terms of this License - and that the license for the Executable form does not attempt to - limit or alter the recipient's rights in the Source Code form from - the rights set forth in this License. If You distribute the - Covered Software in Executable form under a different license, You - must make it absolutely clear that any terms which differ from - this License are offered by You alone, not by the Initial - Developer or Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred - by the Initial Developer or such Contributor as a result of any - such terms You offer. - - 3.6. Larger Works. - - You may create a Larger Work by combining Covered Software with - other code not governed by the terms of this License and - distribute the Larger Work as a single product. In such a case, - You must make sure the requirements of this License are fulfilled - for the Covered Software. - -4. Versions of the License. - - 4.1. New Versions. - - Sun Microsystems, Inc. is the initial license steward and may - publish revised and/or new versions of this License from time to - time. Each version will be given a distinguishing version number. - Except as provided in Section 4.3, no one other than the license - steward has the right to modify this License. - - 4.2. Effect of New Versions. - - You may always continue to use, distribute or otherwise make the - Covered Software available under the terms of the version of the - License under which You originally received the Covered Software. - If the Initial Developer includes a notice in the Original - Software prohibiting it from being distributed or otherwise made - available under any subsequent version of the License, You must - distribute and make the Covered Software available under the terms - of the version of the License under which You originally received - the Covered Software. Otherwise, You may also choose to use, - distribute or otherwise make the Covered Software available under - the terms of any subsequent version of the License published by - the license steward. - - 4.3. Modified Versions. - - When You are an Initial Developer and You want to create a new - license for Your Original Software, You may create and use a - modified version of this License if You: (a) rename the license - and remove any references to the name of the license steward - (except to note that the license differs from this License); and - (b) otherwise make it clear that the license contains terms which - differ from this License. - -5. DISCLAIMER OF WARRANTY. - - COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" - BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, - INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED - SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR - PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND - PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY - COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE - INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY - NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF - WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS - DISCLAIMER. - -6. TERMINATION. - - 6.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to - cure such breach within 30 days of becoming aware of the breach. - Provisions which, by their nature, must remain in effect beyond - the termination of this License shall survive. - - 6.2. If You assert a patent infringement claim (excluding - declaratory judgment actions) against Initial Developer or a - Contributor (the Initial Developer or Contributor against whom You - assert such claim is referred to as "Participant") alleging that - the Participant Software (meaning the Contributor Version where - the Participant is a Contributor or the Original Software where - the Participant is the Initial Developer) directly or indirectly - infringes any patent, then any and all rights granted directly or - indirectly to You by such Participant, the Initial Developer (if - the Initial Developer is not the Participant) and all Contributors - under Sections 2.1 and/or 2.2 of this License shall, upon 60 days - notice from Participant terminate prospectively and automatically - at the expiration of such 60 day notice period, unless if within - such 60 day period You withdraw Your claim with respect to the - Participant Software against such Participant either unilaterally - or pursuant to a written agreement with Participant. - - 6.3. In the event of termination under Sections 6.1 or 6.2 above, - all end user licenses that have been validly granted by You or any - distributor hereunder prior to termination (excluding licenses - granted to You by any distributor) shall survive termination. - -7. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE - INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF - COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE - LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR - CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT - LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK - STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL - INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT - APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO - NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR - CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT - APPLY TO YOU. - -8. U.S. GOVERNMENT END USERS. - - The Covered Software is a "commercial item," as that term is - defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial - computer software" (as that term is defined at 48 - C.F.R. 252.227-7014(a)(1)) and "commercial computer software - documentation" as such terms are used in 48 C.F.R. 12.212 - (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 - C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all - U.S. Government End Users acquire Covered Software with only those - rights set forth herein. This U.S. Government Rights clause is in - lieu of, and supersedes, any other FAR, DFAR, or other clause or - provision that addresses Government rights in computer software - under this License. - -9. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed - by the law of the jurisdiction specified in a notice contained - within the Original Software (except to the extent applicable law, - if any, provides otherwise), excluding such jurisdiction's - conflict-of-law provisions. Any litigation relating to this - License shall be subject to the jurisdiction of the courts located - in the jurisdiction and venue specified in a notice contained - within the Original Software, with the losing party responsible - for costs, including, without limitation, court costs and - reasonable attorneys' fees and expenses. The application of the - United Nations Convention on Contracts for the International Sale - of Goods is expressly excluded. Any law or regulation which - provides that the language of a contract shall be construed - against the drafter shall not apply to this License. You agree - that You alone are responsible for compliance with the United - States export administration regulations (and the export control - laws and regulation of any other countries) when You use, - distribute or otherwise make available any Covered Software. - -10. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or - indirectly, out of its utilization of rights under this License - and You agree to work with Initial Developer and Contributors to - distribute such responsibility on an equitable basis. Nothing - herein is intended or shall be deemed to constitute any admission - of liability. - --------------------------------------------------------------------- - -NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND -DISTRIBUTION LICENSE (CDDL) - -For Covered Software in this distribution, this License shall -be governed by the laws of the State of California (excluding -conflict-of-law provisions). - -Any litigation relating to this License shall be subject to the -jurisdiction of the Federal Courts of the Northern District of -California and the state courts of the State of California, with -venue lying in Santa Clara County, California. diff --git a/vendor/github.com/howeyc/gopass/README.md b/vendor/github.com/howeyc/gopass/README.md deleted file mode 100644 index 2d6a4e72c..000000000 --- a/vendor/github.com/howeyc/gopass/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# getpasswd in Go [![GoDoc](https://godoc.org/github.com/howeyc/gopass?status.svg)](https://godoc.org/github.com/howeyc/gopass) [![Build Status](https://secure.travis-ci.org/howeyc/gopass.png?branch=master)](http://travis-ci.org/howeyc/gopass) - -Retrieve password from user terminal or piped input without echo. - -Verified on BSD, Linux, and Windows. - -Example: -```go -package main - -import "fmt" -import "github.com/howeyc/gopass" - -func main() { - fmt.Printf("Password: ") - - // Silent. For printing *'s use gopass.GetPasswdMasked() - pass, err := gopass.GetPasswd() - if err != nil { - // Handle gopass.ErrInterrupted or getch() read error - } - - // Do something with pass -} -``` - -Caution: Multi-byte characters not supported! diff --git a/vendor/github.com/howeyc/gopass/pass.go b/vendor/github.com/howeyc/gopass/pass.go deleted file mode 100644 index f5bd5a51a..000000000 --- a/vendor/github.com/howeyc/gopass/pass.go +++ /dev/null @@ -1,110 +0,0 @@ -package gopass - -import ( - "errors" - "fmt" - "io" - "os" -) - -type FdReader interface { - io.Reader - Fd() uintptr -} - -var defaultGetCh = func(r io.Reader) (byte, error) { - buf := make([]byte, 1) - if n, err := r.Read(buf); n == 0 || err != nil { - if err != nil { - return 0, err - } - return 0, io.EOF - } - return buf[0], nil -} - -var ( - maxLength = 512 - ErrInterrupted = errors.New("interrupted") - ErrMaxLengthExceeded = fmt.Errorf("maximum byte limit (%v) exceeded", maxLength) - - // Provide variable so that tests can provide a mock implementation. - getch = defaultGetCh -) - -// getPasswd returns the input read from terminal. -// If prompt is not empty, it will be output as a prompt to the user -// If masked is true, typing will be matched by asterisks on the screen. -// Otherwise, typing will echo nothing. -func getPasswd(prompt string, masked bool, r FdReader, w io.Writer) ([]byte, error) { - var err error - var pass, bs, mask []byte - if masked { - bs = []byte("\b \b") - mask = []byte("*") - } - - if isTerminal(r.Fd()) { - if oldState, err := makeRaw(r.Fd()); err != nil { - return pass, err - } else { - defer func() { - restore(r.Fd(), oldState) - fmt.Fprintln(w) - }() - } - } - - if prompt != "" { - fmt.Fprint(w, prompt) - } - - // Track total bytes read, not just bytes in the password. This ensures any - // errors that might flood the console with nil or -1 bytes infinitely are - // capped. - var counter int - for counter = 0; counter <= maxLength; counter++ { - if v, e := getch(r); e != nil { - err = e - break - } else if v == 127 || v == 8 { - if l := len(pass); l > 0 { - pass = pass[:l-1] - fmt.Fprint(w, string(bs)) - } - } else if v == 13 || v == 10 { - break - } else if v == 3 { - err = ErrInterrupted - break - } else if v != 0 { - pass = append(pass, v) - fmt.Fprint(w, string(mask)) - } - } - - if counter > maxLength { - err = ErrMaxLengthExceeded - } - - return pass, err -} - -// GetPasswd returns the password read from the terminal without echoing input. -// The returned byte array does not include end-of-line characters. -func GetPasswd() ([]byte, error) { - return getPasswd("", false, os.Stdin, os.Stdout) -} - -// GetPasswdMasked returns the password read from the terminal, echoing asterisks. -// The returned byte array does not include end-of-line characters. -func GetPasswdMasked() ([]byte, error) { - return getPasswd("", true, os.Stdin, os.Stdout) -} - -// GetPasswdPrompt prompts the user and returns the password read from the terminal. -// If mask is true, then asterisks are echoed. -// The returned byte array does not include end-of-line characters. -func GetPasswdPrompt(prompt string, mask bool, r FdReader, w io.Writer) ([]byte, error) { - return getPasswd(prompt, mask, r, w) -} diff --git a/vendor/github.com/howeyc/gopass/pass_test.go b/vendor/github.com/howeyc/gopass/pass_test.go deleted file mode 100644 index 7ac315135..000000000 --- a/vendor/github.com/howeyc/gopass/pass_test.go +++ /dev/null @@ -1,225 +0,0 @@ -package gopass - -import ( - "bufio" - "bytes" - "fmt" - "io" - "io/ioutil" - "os" - "testing" - "time" -) - -// TestGetPasswd tests the password creation and output based on a byte buffer -// as input to mock the underlying getch() methods. -func TestGetPasswd(t *testing.T) { - type testData struct { - input []byte - - // Due to how backspaces are written, it is easier to manually write - // each expected output for the masked cases. - masked string - password string - byesLeft int - reason string - } - - ds := []testData{ - testData{[]byte("abc\n"), "***", "abc", 0, "Password parsing should stop at \\n"}, - testData{[]byte("abc\r"), "***", "abc", 0, "Password parsing should stop at \\r"}, - testData{[]byte("a\nbc\n"), "*", "a", 3, "Password parsing should stop at \\n"}, - testData{[]byte("*!]|\n"), "****", "*!]|", 0, "Special characters shouldn't affect the password."}, - - testData{[]byte("abc\r\n"), "***", "abc", 1, - "Password parsing should stop at \\r; Windows LINE_MODE should be unset so \\r is not converted to \\r\\n."}, - - testData{[]byte{'a', 'b', 'c', 8, '\n'}, "***\b \b", "ab", 0, "Backspace byte should remove the last read byte."}, - testData{[]byte{'a', 'b', 127, 'c', '\n'}, "**\b \b*", "ac", 0, "Delete byte should remove the last read byte."}, - testData{[]byte{'a', 'b', 127, 'c', 8, 127, '\n'}, "**\b \b*\b \b\b \b", "", 0, "Successive deletes continue to delete."}, - testData{[]byte{8, 8, 8, '\n'}, "", "", 0, "Deletes before characters are noops."}, - testData{[]byte{8, 8, 8, 'a', 'b', 'c', '\n'}, "***", "abc", 0, "Deletes before characters are noops."}, - - testData{[]byte{'a', 'b', 0, 'c', '\n'}, "***", "abc", 0, - "Nil byte should be ignored due; may get unintended nil bytes from syscalls on Windows."}, - } - - // Redirecting output for tests as they print to os.Stdout but we want to - // capture and test the output. - for _, masked := range []bool{true, false} { - for _, d := range ds { - pipeBytesToStdin(d.input) - - r, w, err := os.Pipe() - if err != nil { - t.Fatal(err.Error()) - } - - result, err := getPasswd("", masked, os.Stdin, w) - if err != nil { - t.Errorf("Error getting password: %s", err.Error()) - } - leftOnBuffer := flushStdin() - - // Test output (masked and unmasked). Delete/backspace actually - // deletes, overwrites and deletes again. As a result, we need to - // remove those from the pipe afterwards to mimic the console's - // interpretation of those bytes. - w.Close() - output, err := ioutil.ReadAll(r) - if err != nil { - t.Fatal(err.Error()) - } - var expectedOutput []byte - if masked { - expectedOutput = []byte(d.masked) - } else { - expectedOutput = []byte("") - } - if bytes.Compare(expectedOutput, output) != 0 { - t.Errorf("Expected output to equal %v (%q) but got %v (%q) instead when masked=%v. %s", expectedOutput, string(expectedOutput), output, string(output), masked, d.reason) - } - - if string(result) != d.password { - t.Errorf("Expected %q but got %q instead when masked=%v. %s", d.password, result, masked, d.reason) - } - - if leftOnBuffer != d.byesLeft { - t.Errorf("Expected %v bytes left on buffer but instead got %v when masked=%v. %s", d.byesLeft, leftOnBuffer, masked, d.reason) - } - } - } -} - -// TestPipe ensures we get our expected pipe behavior. -func TestPipe(t *testing.T) { - type testData struct { - input string - password string - expError error - } - ds := []testData{ - testData{"abc", "abc", io.EOF}, - testData{"abc\n", "abc", nil}, - testData{"abc\r", "abc", nil}, - testData{"abc\r\n", "abc", nil}, - } - - for _, d := range ds { - _, err := pipeToStdin(d.input) - if err != nil { - t.Log("Error writing input to stdin:", err) - t.FailNow() - } - pass, err := GetPasswd() - if string(pass) != d.password { - t.Errorf("Expected %q but got %q instead.", d.password, string(pass)) - } - if err != d.expError { - t.Errorf("Expected %v but got %q instead.", d.expError, err) - } - } -} - -// flushStdin reads from stdin for .5 seconds to ensure no bytes are left on -// the buffer. Returns the number of bytes read. -func flushStdin() int { - ch := make(chan byte) - go func(ch chan byte) { - reader := bufio.NewReader(os.Stdin) - for { - b, err := reader.ReadByte() - if err != nil { // Maybe log non io.EOF errors, if you want - close(ch) - return - } - ch <- b - } - close(ch) - }(ch) - - numBytes := 0 - for { - select { - case _, ok := <-ch: - if !ok { - return numBytes - } - numBytes++ - case <-time.After(500 * time.Millisecond): - return numBytes - } - } - return numBytes -} - -// pipeToStdin pipes the given string onto os.Stdin by replacing it with an -// os.Pipe. The write end of the pipe is closed so that EOF is read after the -// final byte. -func pipeToStdin(s string) (int, error) { - pipeReader, pipeWriter, err := os.Pipe() - if err != nil { - fmt.Println("Error getting os pipes:", err) - os.Exit(1) - } - os.Stdin = pipeReader - w, err := pipeWriter.WriteString(s) - pipeWriter.Close() - return w, err -} - -func pipeBytesToStdin(b []byte) (int, error) { - return pipeToStdin(string(b)) -} - -// TestGetPasswd_Err tests errors are properly handled from getch() -func TestGetPasswd_Err(t *testing.T) { - var inBuffer *bytes.Buffer - getch = func(io.Reader) (byte, error) { - b, err := inBuffer.ReadByte() - if err != nil { - return 13, err - } - if b == 'z' { - return 'z', fmt.Errorf("Forced error; byte returned should not be considered accurate.") - } - return b, nil - } - defer func() { getch = defaultGetCh }() - - for input, expectedPassword := range map[string]string{"abc": "abc", "abzc": "ab"} { - inBuffer = bytes.NewBufferString(input) - p, err := GetPasswdMasked() - if string(p) != expectedPassword { - t.Errorf("Expected %q but got %q instead.", expectedPassword, p) - } - if err == nil { - t.Errorf("Expected error to be returned.") - } - } -} - -func TestMaxPasswordLength(t *testing.T) { - type testData struct { - input []byte - expectedErr error - - // Helper field to output in case of failure; rather than hundreds of - // bytes. - inputDesc string - } - - ds := []testData{ - testData{append(bytes.Repeat([]byte{'a'}, maxLength), '\n'), nil, fmt.Sprintf("%v 'a' bytes followed by a newline", maxLength)}, - testData{append(bytes.Repeat([]byte{'a'}, maxLength+1), '\n'), ErrMaxLengthExceeded, fmt.Sprintf("%v 'a' bytes followed by a newline", maxLength+1)}, - testData{append(bytes.Repeat([]byte{0x00}, maxLength+1), '\n'), ErrMaxLengthExceeded, fmt.Sprintf("%v 0x00 bytes followed by a newline", maxLength+1)}, - } - - for _, d := range ds { - pipeBytesToStdin(d.input) - _, err := GetPasswd() - if err != d.expectedErr { - t.Errorf("Expected error to be %v; isntead got %v from %v", d.expectedErr, err, d.inputDesc) - } - } -} diff --git a/vendor/github.com/howeyc/gopass/terminal.go b/vendor/github.com/howeyc/gopass/terminal.go deleted file mode 100644 index 083564146..000000000 --- a/vendor/github.com/howeyc/gopass/terminal.go +++ /dev/null @@ -1,25 +0,0 @@ -// +build !solaris - -package gopass - -import "golang.org/x/crypto/ssh/terminal" - -type terminalState struct { - state *terminal.State -} - -func isTerminal(fd uintptr) bool { - return terminal.IsTerminal(int(fd)) -} - -func makeRaw(fd uintptr) (*terminalState, error) { - state, err := terminal.MakeRaw(int(fd)) - - return &terminalState{ - state: state, - }, err -} - -func restore(fd uintptr, oldState *terminalState) error { - return terminal.Restore(int(fd), oldState.state) -} diff --git a/vendor/github.com/howeyc/gopass/terminal_solaris.go b/vendor/github.com/howeyc/gopass/terminal_solaris.go deleted file mode 100644 index 257e1b4e8..000000000 --- a/vendor/github.com/howeyc/gopass/terminal_solaris.go +++ /dev/null @@ -1,69 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -// Below is derived from Solaris source, so CDDL license is included. - -package gopass - -import ( - "syscall" - - "golang.org/x/sys/unix" -) - -type terminalState struct { - state *unix.Termios -} - -// isTerminal returns true if there is a terminal attached to the given -// file descriptor. -// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c -func isTerminal(fd uintptr) bool { - var termio unix.Termio - err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) - return err == nil -} - -// makeRaw puts the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c -func makeRaw(fd uintptr) (*terminalState, error) { - oldTermiosPtr, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) - if err != nil { - return nil, err - } - oldTermios := *oldTermiosPtr - - newTermios := oldTermios - newTermios.Lflag &^= syscall.ECHO | syscall.ECHOE | syscall.ECHOK | syscall.ECHONL - if err := unix.IoctlSetTermios(int(fd), unix.TCSETS, &newTermios); err != nil { - return nil, err - } - - return &terminalState{ - state: oldTermiosPtr, - }, nil -} - -func restore(fd uintptr, oldState *terminalState) error { - return unix.IoctlSetTermios(int(fd), unix.TCSETS, oldState.state) -} diff --git a/vendor/github.com/iancoleman/strcase/.travis.yml b/vendor/github.com/iancoleman/strcase/.travis.yml new file mode 100644 index 000000000..9a3c1a851 --- /dev/null +++ b/vendor/github.com/iancoleman/strcase/.travis.yml @@ -0,0 +1,9 @@ +sudo: false +language: go +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - tip diff --git a/vendor/github.com/iancoleman/strcase/LICENSE b/vendor/github.com/iancoleman/strcase/LICENSE new file mode 100644 index 000000000..3e87ff70e --- /dev/null +++ b/vendor/github.com/iancoleman/strcase/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Ian Coleman +Copyright (c) 2018 Ma_124, + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, Subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or Substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/iancoleman/strcase/README.md b/vendor/github.com/iancoleman/strcase/README.md new file mode 100644 index 000000000..978b46dcd --- /dev/null +++ b/vendor/github.com/iancoleman/strcase/README.md @@ -0,0 +1,23 @@ +# strcase +[![Godoc Reference](https://godoc.org/github.com/iancoleman/strcase?status.svg)](http://godoc.org/github.com/iancoleman/strcase) +[![Build Status](https://travis-ci.org/iancoleman/strcase.svg)](https://travis-ci.org/iancoleman/strcase) +[![Coverage](http://gocover.io/_badge/github.com/iancoleman/strcase?0)](http://gocover.io/github.com/iancoleman/strcase) + +strcase is a go package for converting string case to [snake case](https://en.wikipedia.org/wiki/Snake_case) or [camel case](https://en.wikipedia.org/wiki/CamelCase). + +## Example + +```go +s := "AnyKind of_string" +``` + +| Function | Result | +|-----------------------------------|----------------------| +| `ToSnake(s)` | `any_kind_of_string` | +| `ToScreamingSnake(s)` | `ANY_KIND_OF_STRING` | +| `ToKebab(s)` | `any-kind-of-string` | +| `ToScreamingKebab(s)` | `ANY-KIND-OF-STRING` | +| `ToDelimited(s, '.')` | `any.kind.of.string` | +| `ToScreamingDelimited(s, '.')` | `ANY.KIND.OF.STRING` | +| `ToCamel(s)` | `AnyKindOfString` | +| `ToLowerCamel(s)` | `anyKindOfString` | diff --git a/vendor/github.com/iancoleman/strcase/camel.go b/vendor/github.com/iancoleman/strcase/camel.go new file mode 100644 index 000000000..7c2e2b748 --- /dev/null +++ b/vendor/github.com/iancoleman/strcase/camel.go @@ -0,0 +1,75 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * Copyright (c) 2018 Ma_124, + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package strcase + +import ( + "strings" +) + +// Converts a string to CamelCase +func toCamelInitCase(s string, initCase bool) string { + s = addWordBoundariesToNumbers(s) + s = strings.Trim(s, " ") + n := "" + capNext := initCase + for _, v := range s { + if v >= 'A' && v <= 'Z' { + n += string(v) + } + if v >= '0' && v <= '9' { + n += string(v) + } + if v >= 'a' && v <= 'z' { + if capNext { + n += strings.ToUpper(string(v)) + } else { + n += string(v) + } + } + if v == '_' || v == ' ' || v == '-' { + capNext = true + } else { + capNext = false + } + } + return n +} + +// Converts a string to CamelCase +func ToCamel(s string) string { + return toCamelInitCase(s, true) +} + +// Converts a string to lowerCamelCase +func ToLowerCamel(s string) string { + if s == "" { + return s + } + if r := rune(s[0]); r >= 'A' && r <= 'Z' { + s = strings.ToLower(string(r)) + s[1:] + } + return toCamelInitCase(s, false) +} diff --git a/vendor/github.com/iancoleman/strcase/camel_test.go b/vendor/github.com/iancoleman/strcase/camel_test.go new file mode 100644 index 000000000..b62b9c483 --- /dev/null +++ b/vendor/github.com/iancoleman/strcase/camel_test.go @@ -0,0 +1,68 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package strcase + +import ( + "testing" +) + +func TestToCamel(t *testing.T) { + cases := [][]string{ + []string{"test_case", "TestCase"}, + []string{"test", "Test"}, + []string{"TestCase", "TestCase"}, + []string{" test case ", "TestCase"}, + []string{"", ""}, + []string{"many_many_words", "ManyManyWords"}, + []string{"AnyKind of_string", "AnyKindOfString"}, + []string{"odd-fix", "OddFix"}, + []string{"numbers2And55with000", "Numbers2And55With000"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToCamel(in) + if result != out { + t.Error("'" + result + "' != '" + out + "'") + } + } +} + +func TestToLowerCamel(t *testing.T) { + cases := [][]string{ + []string{"foo-bar", "fooBar"}, + []string{"TestCase", "testCase"}, + []string{"", ""}, + []string{"AnyKind of_string", "anyKindOfString"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToLowerCamel(in) + if result != out { + t.Error("'" + result + "' != '" + out + "'") + } + } +} diff --git a/vendor/github.com/iancoleman/strcase/numbers.go b/vendor/github.com/iancoleman/strcase/numbers.go new file mode 100644 index 000000000..fdf07cb06 --- /dev/null +++ b/vendor/github.com/iancoleman/strcase/numbers.go @@ -0,0 +1,38 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package strcase + +import ( + "regexp" +) + +var numberSequence = regexp.MustCompile(`([a-zA-Z])(\d+)([a-zA-Z]?)`) +var numberReplacement = []byte(`$1 $2 $3`) + +func addWordBoundariesToNumbers(s string) string { + b := []byte(s) + b = numberSequence.ReplaceAll(b, numberReplacement) + return string(b) +} diff --git a/vendor/github.com/iancoleman/strcase/snake.go b/vendor/github.com/iancoleman/strcase/snake.go new file mode 100644 index 000000000..1d2f5206d --- /dev/null +++ b/vendor/github.com/iancoleman/strcase/snake.go @@ -0,0 +1,94 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * Copyright (c) 2018 Ma_124, + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// Package strcase converts strings to snake_case or CamelCase +package strcase + +import ( + "strings" +) + +// Converts a string to snake_case +func ToSnake(s string) string { + return ToDelimited(s, '_') +} + +// Converts a string to SCREAMING_SNAKE_CASE +func ToScreamingSnake(s string) string { + return ToScreamingDelimited(s, '_', true) +} + +// Converts a string to kebab-case +func ToKebab(s string) string { + return ToDelimited(s, '-') +} + +// Converts a string to SCREAMING-KEBAB-CASE +func ToScreamingKebab(s string) string { + return ToScreamingDelimited(s, '-', true) +} + +// Converts a string to delimited.snake.case (in this case `del = '.'`) +func ToDelimited(s string, del uint8) string { + return ToScreamingDelimited(s, del, false) +} + +// Converts a string to SCREAMING.DELIMITED.SNAKE.CASE (in this case `del = '.'; screaming = true`) or delimited.snake.case (in this case `del = '.'; screaming = false`) +func ToScreamingDelimited(s string, del uint8, screaming bool) string { + s = addWordBoundariesToNumbers(s) + s = strings.Trim(s, " ") + n := "" + for i, v := range s { + // treat acronyms as words, eg for JSONData -> JSON is a whole word + nextCaseIsChanged := false + if i+1 < len(s) { + next := s[i+1] + if (v >= 'A' && v <= 'Z' && next >= 'a' && next <= 'z') || (v >= 'a' && v <= 'z' && next >= 'A' && next <= 'Z') { + nextCaseIsChanged = true + } + } + + if i > 0 && n[len(n)-1] != del && nextCaseIsChanged { + // add underscore if next letter case type is changed + if v >= 'A' && v <= 'Z' { + n += string(del) + string(v) + } else if v >= 'a' && v <= 'z' { + n += string(v) + string(del) + } + } else if v == ' ' || v == '_' || v == '-' { + // replace spaces/underscores with delimiters + n += string(del) + } else { + n = n + string(v) + } + } + + if screaming { + n = strings.ToUpper(n) + } else { + n = strings.ToLower(n) + } + return n +} diff --git a/vendor/github.com/iancoleman/strcase/snake_test.go b/vendor/github.com/iancoleman/strcase/snake_test.go new file mode 100644 index 000000000..9c0f9d2e0 --- /dev/null +++ b/vendor/github.com/iancoleman/strcase/snake_test.go @@ -0,0 +1,147 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * Copyright (c) 2018 Ma_124, + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package strcase + +import ( + "testing" +) + +func TestToSnake(t *testing.T) { + cases := [][]string{ + []string{"testCase", "test_case"}, + []string{"TestCase", "test_case"}, + []string{"Test Case", "test_case"}, + []string{" Test Case", "test_case"}, + []string{"Test Case ", "test_case"}, + []string{" Test Case ", "test_case"}, + []string{"test", "test"}, + []string{"test_case", "test_case"}, + []string{"Test", "test"}, + []string{"", ""}, + []string{"ManyManyWords", "many_many_words"}, + []string{"manyManyWords", "many_many_words"}, + []string{"AnyKind of_string", "any_kind_of_string"}, + []string{"numbers2and55with000", "numbers_2_and_55_with_000"}, + []string{"JSONData", "json_data"}, + []string{"userID", "user_id"}, + []string{"AAAbbb", "aa_abbb"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToSnake(in) + if result != out { + t.Error("'" + in + "'('" + result + "' != '" + out + "')") + } + } +} + +func TestToDelimited(t *testing.T) { + cases := [][]string{ + []string{"testCase", "test@case"}, + []string{"TestCase", "test@case"}, + []string{"Test Case", "test@case"}, + []string{" Test Case", "test@case"}, + []string{"Test Case ", "test@case"}, + []string{" Test Case ", "test@case"}, + []string{"test", "test"}, + []string{"test_case", "test@case"}, + []string{"Test", "test"}, + []string{"", ""}, + []string{"ManyManyWords", "many@many@words"}, + []string{"manyManyWords", "many@many@words"}, + []string{"AnyKind of_string", "any@kind@of@string"}, + []string{"numbers2and55with000", "numbers@2@and@55@with@000"}, + []string{"JSONData", "json@data"}, + []string{"userID", "user@id"}, + []string{"AAAbbb", "aa@abbb"}, + []string{"test-case", "test@case"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToDelimited(in, '@') + if result != out { + t.Error("'" + in + "' ('" + result + "' != '" + out + "')") + } + } +} + +func TestToScreamingSnake(t *testing.T) { + cases := [][]string{ + []string{"testCase", "TEST_CASE"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToScreamingSnake(in) + if result != out { + t.Error("'" + result + "' != '" + out + "'") + } + } +} + +func TestToKebab(t *testing.T) { + cases := [][]string{ + []string{"testCase", "test-case"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToKebab(in) + if result != out { + t.Error("'" + result + "' != '" + out + "'") + } + } +} + +func TestToScreamingKebab(t *testing.T) { + cases := [][]string{ + []string{"testCase", "TEST-CASE"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToScreamingKebab(in) + if result != out { + t.Error("'" + result + "' != '" + out + "'") + } + } +} + +func TestToScreamingDelimited(t *testing.T) { + cases := [][]string{ + []string{"testCase", "TEST.CASE"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToScreamingDelimited(in, '.', true) + if result != out { + t.Error("'" + result + "' != '" + out + "'") + } + } +} diff --git a/vendor/github.com/json-iterator/go/Gopkg.lock b/vendor/github.com/json-iterator/go/Gopkg.lock index 338f1c68a..3719afe8e 100644 --- a/vendor/github.com/json-iterator/go/Gopkg.lock +++ b/vendor/github.com/json-iterator/go/Gopkg.lock @@ -1,6 +1,12 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + name = "github.com/json-iterator/go" + packages = ["."] + revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4" + version = "1.1.3" + [[projects]] name = "github.com/modern-go/concurrent" packages = ["."] @@ -16,6 +22,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "ac7003b5a981716353a43055ab7d4c5357403cb30a60de2dbdeb446c1544beaa" + inputs-digest = "56a0b9e9e61d2bc8af5e1b68537401b7f4d60805eda3d107058f3171aa5cf793" solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/json-iterator/go/README.md b/vendor/github.com/json-iterator/go/README.md index 9f404aaa3..54d5afe95 100644 --- a/vendor/github.com/json-iterator/go/README.md +++ b/vendor/github.com/json-iterator/go/README.md @@ -31,6 +31,9 @@ Raw Result (easyjson requires static code generation) | easyjson encode | 883 ns/op | 576 B/op | 3 allocs/op | | jsoniter encode | 837 ns/op | 384 B/op | 4 allocs/op | +Always benchmark with your own workload. +The result depends heavily on the data input. + # Usage 100% compatibility with standard lib diff --git a/vendor/github.com/json-iterator/go/adapter.go b/vendor/github.com/json-iterator/go/adapter.go index 3a494eeb4..f371bfed7 100644 --- a/vendor/github.com/json-iterator/go/adapter.go +++ b/vendor/github.com/json-iterator/go/adapter.go @@ -77,7 +77,14 @@ func (adapter *Decoder) Decode(obj interface{}) error { // More is there more? func (adapter *Decoder) More() bool { - return adapter.iter.head != adapter.iter.tail + iter := adapter.iter + if iter.Error != nil { + return false + } + if iter.head != iter.tail { + return true + } + return iter.loadMore() } // Buffered remaining buffer diff --git a/vendor/github.com/json-iterator/go/api_tests/config_test.go b/vendor/github.com/json-iterator/go/api_tests/config_test.go index d3e93e5c6..7aa349bee 100644 --- a/vendor/github.com/json-iterator/go/api_tests/config_test.go +++ b/vendor/github.com/json-iterator/go/api_tests/config_test.go @@ -2,9 +2,10 @@ package test import ( "encoding/json" + "testing" + "github.com/json-iterator/go" "github.com/stretchr/testify/require" - "testing" ) func Test_use_number_for_unmarshal(t *testing.T) { @@ -45,3 +46,129 @@ func Test_read_large_number_as_interface(t *testing.T) { should.Nil(err) should.Equal(`123456789123456789123456789`, output) } + +type caseSensitiveStruct struct { + A string `json:"a"` + B string `json:"b,omitempty"` + C *C `json:"C,omitempty"` +} + +type C struct { + D int64 `json:"D,omitempty"` + E *E `json:"e,omitempty"` +} + +type E struct { + F string `json:"F,omitempty"` +} + +func Test_CaseSensitive(t *testing.T) { + should := require.New(t) + + testCases := []struct { + input string + expectedOutput string + caseSensitive bool + }{ + { + input: `{"A":"foo","B":"bar"}`, + expectedOutput: `{"a":"foo","b":"bar"}`, + caseSensitive: false, + }, + { + input: `{"a":"foo","b":"bar"}`, + expectedOutput: `{"a":"foo","b":"bar"}`, + caseSensitive: true, + }, + { + input: `{"a":"foo","b":"bar","C":{"D":10}}`, + expectedOutput: `{"a":"foo","b":"bar","C":{"D":10}}`, + caseSensitive: true, + }, + { + input: `{"a":"foo","B":"bar","c":{"d":10}}`, + expectedOutput: `{"a":"foo"}`, + caseSensitive: true, + }, + { + input: `{"a":"foo","C":{"d":10}}`, + expectedOutput: `{"a":"foo","C":{}}`, + caseSensitive: true, + }, + { + input: `{"a":"foo","C":{"D":10,"e":{"f":"baz"}}}`, + expectedOutput: `{"a":"foo","C":{"D":10,"e":{}}}`, + caseSensitive: true, + }, + { + input: `{"a":"foo","C":{"D":10,"e":{"F":"baz"}}}`, + expectedOutput: `{"a":"foo","C":{"D":10,"e":{"F":"baz"}}}`, + caseSensitive: true, + }, + { + input: `{"A":"foo","c":{"d":10,"E":{"f":"baz"}}}`, + expectedOutput: `{"a":"foo","C":{"D":10,"e":{"F":"baz"}}}`, + caseSensitive: false, + }, + } + + for _, tc := range testCases { + val := caseSensitiveStruct{} + err := jsoniter.Config{CaseSensitive: tc.caseSensitive}.Froze().UnmarshalFromString(tc.input, &val) + should.Nil(err) + + output, err := jsoniter.MarshalToString(val) + should.Nil(err) + should.Equal(tc.expectedOutput, output) + } +} + +type structWithElevenFields struct { + A string `json:"A,omitempty"` + B string `json:"B,omitempty"` + C string `json:"C,omitempty"` + D string `json:"d,omitempty"` + E string `json:"e,omitempty"` + F string `json:"f,omitempty"` + G string `json:"g,omitempty"` + H string `json:"h,omitempty"` + I string `json:"i,omitempty"` + J string `json:"j,omitempty"` + K string `json:"k,omitempty"` +} + +func Test_CaseSensitive_MoreThanTenFields(t *testing.T) { + should := require.New(t) + + testCases := []struct { + input string + expectedOutput string + caseSensitive bool + }{ + { + input: `{"A":"1","B":"2","C":"3","d":"4","e":"5","f":"6","g":"7","h":"8","i":"9","j":"10","k":"11"}`, + expectedOutput: `{"A":"1","B":"2","C":"3","d":"4","e":"5","f":"6","g":"7","h":"8","i":"9","j":"10","k":"11"}`, + caseSensitive: true, + }, + { + input: `{"a":"1","b":"2","c":"3","D":"4","E":"5","F":"6"}`, + expectedOutput: `{"A":"1","B":"2","C":"3","d":"4","e":"5","f":"6"}`, + caseSensitive: false, + }, + { + input: `{"A":"1","b":"2","d":"4","E":"5"}`, + expectedOutput: `{"A":"1","d":"4"}`, + caseSensitive: true, + }, + } + + for _, tc := range testCases { + val := structWithElevenFields{} + err := jsoniter.Config{CaseSensitive: tc.caseSensitive}.Froze().UnmarshalFromString(tc.input, &val) + should.Nil(err) + + output, err := jsoniter.MarshalToString(val) + should.Nil(err) + should.Equal(tc.expectedOutput, output) + } +} diff --git a/vendor/github.com/json-iterator/go/api_tests/decoder_test.go b/vendor/github.com/json-iterator/go/api_tests/decoder_test.go index eecfddbc8..8e1c16078 100644 --- a/vendor/github.com/json-iterator/go/api_tests/decoder_test.go +++ b/vendor/github.com/json-iterator/go/api_tests/decoder_test.go @@ -56,3 +56,9 @@ func Test_use_number(t *testing.T) { should.Nil(decoder2.Decode(&obj2)) should.Equal(json.Number("123"), obj2) } + +func Test_decoder_more(t *testing.T) { + should := require.New(t) + decoder := jsoniter.NewDecoder(bytes.NewBufferString("abcde")) + should.True(decoder.More()) +} \ No newline at end of file diff --git a/vendor/github.com/json-iterator/go/config.go b/vendor/github.com/json-iterator/go/config.go index bd66947d7..835819129 100644 --- a/vendor/github.com/json-iterator/go/config.go +++ b/vendor/github.com/json-iterator/go/config.go @@ -2,12 +2,13 @@ package jsoniter import ( "encoding/json" - "github.com/modern-go/concurrent" - "github.com/modern-go/reflect2" "io" "reflect" "sync" "unsafe" + + "github.com/modern-go/concurrent" + "github.com/modern-go/reflect2" ) // Config customize how the API should behave. @@ -23,6 +24,7 @@ type Config struct { OnlyTaggedField bool ValidateJsonRawMessage bool ObjectFieldMustBeSimpleString bool + CaseSensitive bool } // API the public interface of this package. @@ -75,6 +77,7 @@ type frozenConfig struct { extensions []Extension streamPool *sync.Pool iteratorPool *sync.Pool + caseSensitive bool } func (cfg *frozenConfig) initCache() { @@ -128,6 +131,7 @@ func (cfg Config) Froze() API { objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString, onlyTaggedField: cfg.OnlyTaggedField, disallowUnknownFields: cfg.DisallowUnknownFields, + caseSensitive: cfg.CaseSensitive, } api.streamPool = &sync.Pool{ New: func() interface{} { diff --git a/vendor/github.com/json-iterator/go/extra/fuzzy_decoder.go b/vendor/github.com/json-iterator/go/extra/fuzzy_decoder.go index 8ff1cc3db..52546b11d 100644 --- a/vendor/github.com/json-iterator/go/extra/fuzzy_decoder.go +++ b/vendor/github.com/json-iterator/go/extra/fuzzy_decoder.go @@ -217,6 +217,9 @@ func (decoder *fuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It default: iter.ReportError("fuzzyIntegerDecoder", "not number or string") } + if len(str) == 0 { + str = "0" + } newIter := iter.Pool().BorrowIterator([]byte(str)) defer iter.Pool().ReturnIterator(newIter) isFloat := strings.IndexByte(str, '.') != -1 diff --git a/vendor/github.com/json-iterator/go/extra/fuzzy_decoder_test.go b/vendor/github.com/json-iterator/go/extra/fuzzy_decoder_test.go index 3490e3a23..69315adfb 100644 --- a/vendor/github.com/json-iterator/go/extra/fuzzy_decoder_test.go +++ b/vendor/github.com/json-iterator/go/extra/fuzzy_decoder_test.go @@ -37,6 +37,8 @@ func Test_any_to_int64(t *testing.T) { should.Equal(int64(10), val) should.Nil(jsoniter.UnmarshalFromString(`10`, &val)) should.Equal(int64(10), val) + should.Nil(jsoniter.UnmarshalFromString(`""`, &val)) + should.Equal(int64(0), val) // bool part should.Nil(jsoniter.UnmarshalFromString(`false`, &val)) diff --git a/vendor/github.com/json-iterator/go/extra/privat_fields.go b/vendor/github.com/json-iterator/go/extra/privat_fields.go index ac7096ff4..0cfd549e0 100644 --- a/vendor/github.com/json-iterator/go/extra/privat_fields.go +++ b/vendor/github.com/json-iterator/go/extra/privat_fields.go @@ -3,6 +3,7 @@ package extra import ( "github.com/json-iterator/go" "unicode" + "strings" ) // SupportPrivateFields include private fields when encoding/decoding @@ -18,8 +19,37 @@ func (extension *privateFieldsExtension) UpdateStructDescriptor(structDescriptor for _, binding := range structDescriptor.Fields { isPrivate := unicode.IsLower(rune(binding.Field.Name()[0])) if isPrivate { - binding.FromNames = []string{binding.Field.Name()} - binding.ToNames = []string{binding.Field.Name()} + tag, hastag := binding.Field.Tag().Lookup("json") + if !hastag { + binding.FromNames = []string{binding.Field.Name()} + binding.ToNames = []string{binding.Field.Name()} + continue + } + tagParts := strings.Split(tag, ",") + names := calcFieldNames(binding.Field.Name(), tagParts[0], tag) + binding.FromNames = names + binding.ToNames = names } } } + +func calcFieldNames(originalFieldName string, tagProvidedFieldName string, wholeTag string) []string { + // ignore? + if wholeTag == "-" { + return []string{} + } + // rename? + var fieldNames []string + if tagProvidedFieldName == "" { + fieldNames = []string{originalFieldName} + } else { + fieldNames = []string{tagProvidedFieldName} + } + // private? + isNotExported := unicode.IsLower(rune(originalFieldName[0])) + if isNotExported { + fieldNames = []string{} + } + return fieldNames +} + diff --git a/vendor/github.com/json-iterator/go/iter_object.go b/vendor/github.com/json-iterator/go/iter_object.go index ebd3da895..6e7c370ab 100644 --- a/vendor/github.com/json-iterator/go/iter_object.go +++ b/vendor/github.com/json-iterator/go/iter_object.go @@ -60,7 +60,7 @@ func (iter *Iterator) readFieldHash() int64 { if b == '\\' { iter.head = i for _, b := range iter.readStringSlowPath() { - if 'A' <= b && b <= 'Z' { + if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { b += 'a' - 'A' } hash ^= int64(b) @@ -82,7 +82,7 @@ func (iter *Iterator) readFieldHash() int64 { } return hash } - if 'A' <= b && b <= 'Z' { + if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { b += 'a' - 'A' } hash ^= int64(b) @@ -95,10 +95,14 @@ func (iter *Iterator) readFieldHash() int64 { } } -func calcHash(str string) int64 { +func calcHash(str string, caseSensitive bool) int64 { hash := int64(0x811c9dc5) for _, b := range str { - hash ^= int64(unicode.ToLower(b)) + if caseSensitive { + hash ^= int64(b) + } else { + hash ^= int64(unicode.ToLower(b)) + } hash *= 0x1000193 } return int64(hash) diff --git a/vendor/github.com/json-iterator/go/misc_tests/jsoniter_array_test.go b/vendor/github.com/json-iterator/go/misc_tests/jsoniter_array_test.go index ef467d184..56e3e12c0 100644 --- a/vendor/github.com/json-iterator/go/misc_tests/jsoniter_array_test.go +++ b/vendor/github.com/json-iterator/go/misc_tests/jsoniter_array_test.go @@ -3,9 +3,10 @@ package misc_tests import ( "bytes" "encoding/json" + "testing" + "github.com/json-iterator/go" "github.com/stretchr/testify/require" - "testing" ) func Test_empty_array(t *testing.T) { @@ -168,6 +169,17 @@ func Test_decode_byte_array_from_base64(t *testing.T) { should.Equal([]byte{1, 2, 3}, data) } +func Test_decode_byte_array_from_base64_with_newlines(t *testing.T) { + should := require.New(t) + data := []byte{} + err := json.Unmarshal([]byte(`"A\rQ\nID"`), &data) + should.Nil(err) + should.Equal([]byte{1, 2, 3}, data) + err = jsoniter.Unmarshal([]byte(`"A\rQ\nID"`), &data) + should.Nil(err) + should.Equal([]byte{1, 2, 3}, data) +} + func Test_decode_byte_array_from_array(t *testing.T) { should := require.New(t) data := []byte{} diff --git a/vendor/github.com/json-iterator/go/pool.go b/vendor/github.com/json-iterator/go/pool.go index 735062684..e2389b56c 100644 --- a/vendor/github.com/json-iterator/go/pool.go +++ b/vendor/github.com/json-iterator/go/pool.go @@ -23,6 +23,7 @@ func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream { } func (cfg *frozenConfig) ReturnStream(stream *Stream) { + stream.out = nil stream.Error = nil stream.Attachment = nil cfg.streamPool.Put(stream) diff --git a/vendor/github.com/json-iterator/go/reflect.go b/vendor/github.com/json-iterator/go/reflect.go index 5c7d3a8a0..be7a0e218 100644 --- a/vendor/github.com/json-iterator/go/reflect.go +++ b/vendor/github.com/json-iterator/go/reflect.go @@ -2,9 +2,10 @@ package jsoniter import ( "fmt" - "github.com/modern-go/reflect2" "reflect" "unsafe" + + "github.com/modern-go/reflect2" ) // ValDecoder is an internal type registered to cache as needed. @@ -40,6 +41,14 @@ type ctx struct { decoders map[reflect2.Type]ValDecoder } +func (b *ctx) caseSensitive() bool { + if b.frozenConfig == nil { + // default is case-insensitive + return false + } + return b.frozenConfig.caseSensitive +} + func (b *ctx) append(prefix string) *ctx { return &ctx{ frozenConfig: b.frozenConfig, diff --git a/vendor/github.com/json-iterator/go/reflect_native.go b/vendor/github.com/json-iterator/go/reflect_native.go index 7f1e2464d..9042eb0cb 100644 --- a/vendor/github.com/json-iterator/go/reflect_native.go +++ b/vendor/github.com/json-iterator/go/reflect_native.go @@ -2,10 +2,11 @@ package jsoniter import ( "encoding/base64" - "github.com/modern-go/reflect2" "reflect" "strconv" "unsafe" + + "github.com/modern-go/reflect2" ) const ptrSize = 32 << uintptr(^uintptr(0)>>63) @@ -416,16 +417,11 @@ func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { } switch iter.WhatIsNext() { case StringValue: - encoding := base64.StdEncoding - src := iter.SkipAndReturnBytes() - src = src[1 : len(src)-1] - decodedLen := encoding.DecodedLen(len(src)) - dst := make([]byte, decodedLen) - len, err := encoding.Decode(dst, src) + src := iter.ReadString() + dst, err := base64.StdEncoding.DecodeString(src) if err != nil { iter.ReportError("decode base64", err.Error()) } else { - dst = dst[:len] codec.sliceType.UnsafeSet(ptr, unsafe.Pointer(&dst)) } case ArrayValue: diff --git a/vendor/github.com/json-iterator/go/reflect_struct_decoder.go b/vendor/github.com/json-iterator/go/reflect_struct_decoder.go index e718722af..355d2d116 100644 --- a/vendor/github.com/json-iterator/go/reflect_struct_decoder.go +++ b/vendor/github.com/json-iterator/go/reflect_struct_decoder.go @@ -2,10 +2,11 @@ package jsoniter import ( "fmt" - "github.com/modern-go/reflect2" "io" "strings" "unsafe" + + "github.com/modern-go/reflect2" ) func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder { @@ -31,6 +32,15 @@ func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder { for k, binding := range bindings { fields[k] = binding.Decoder.(*structFieldDecoder) } + + if !ctx.caseSensitive() { + for k, binding := range bindings { + if _, found := fields[strings.ToLower(k)]; !found { + fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) + } + } + } + return createStructDecoder(ctx, typ, fields) } @@ -41,12 +51,13 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF knownHash := map[int64]struct{}{ 0: {}, } + switch len(fields) { case 0: return &skipObjectDecoder{typ} case 1: for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -60,7 +71,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -83,7 +94,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -114,7 +125,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -151,7 +162,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -194,7 +205,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -243,7 +254,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -298,7 +309,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder7 *structFieldDecoder var fieldDecoder8 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -359,7 +370,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder8 *structFieldDecoder var fieldDecoder9 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -426,7 +437,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF var fieldDecoder9 *structFieldDecoder var fieldDecoder10 *structFieldDecoder for fieldName, fieldDecoder := range fields { - fieldHash := calcHash(fieldName) + fieldHash := calcHash(fieldName, ctx.caseSensitive()) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields, false} @@ -489,13 +500,16 @@ func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) if !iter.readObjectStart() { return } - decoder.decodeOneField(ptr, iter) - for iter.nextToken() == ',' { + var c byte + for c = ','; c == ','; c = iter.nextToken() { decoder.decodeOneField(ptr, iter) } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) } + if c != '}' { + iter.ReportError("struct Decode", `expect }, but found `+string([]byte{c})) + } } func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *Iterator) { @@ -505,13 +519,13 @@ func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *It fieldBytes := iter.ReadStringAsSlice() field = *(*string)(unsafe.Pointer(&fieldBytes)) fieldDecoder = decoder.fields[field] - if fieldDecoder == nil { + if fieldDecoder == nil && !iter.cfg.caseSensitive { fieldDecoder = decoder.fields[strings.ToLower(field)] } } else { field = iter.ReadString() fieldDecoder = decoder.fields[field] - if fieldDecoder == nil { + if fieldDecoder == nil && !iter.cfg.caseSensitive { fieldDecoder = decoder.fields[strings.ToLower(field)] } } diff --git a/vendor/github.com/json-iterator/go/value_tests/error_test.go b/vendor/github.com/json-iterator/go/value_tests/error_test.go new file mode 100644 index 000000000..175a24e53 --- /dev/null +++ b/vendor/github.com/json-iterator/go/value_tests/error_test.go @@ -0,0 +1,36 @@ +package test + +import ( + "github.com/json-iterator/go" + "github.com/stretchr/testify/require" + "reflect" + "testing" +) + +func Test_errorInput(t *testing.T) { + for _, testCase := range unmarshalCases { + if testCase.obj != nil { + continue + } + valType := reflect.TypeOf(testCase.ptr).Elem() + t.Run(valType.String(), func(t *testing.T) { + for _, data := range []string{ + `x`, + `n`, + `nul`, + `{x}`, + `{"x"}`, + `{"x": "y"x}`, + `{"x": "y"`, + `{"x": "y", "a"}`, + `[`, + `[{"x": "y"}`, + } { + ptrVal := reflect.New(valType) + ptr := ptrVal.Interface() + err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(data), ptr) + require.Error(t, err, "on input %q", data) + } + }) + } +} diff --git a/vendor/github.com/json-iterator/go/value_tests/slice_test.go b/vendor/github.com/json-iterator/go/value_tests/slice_test.go index f504e851e..3731cbe15 100644 --- a/vendor/github.com/json-iterator/go/value_tests/slice_test.go +++ b/vendor/github.com/json-iterator/go/value_tests/slice_test.go @@ -20,5 +20,8 @@ func init() { }, unmarshalCase{ ptr: (*[]byte)(nil), input: `"aGVsbG8="`, + }, unmarshalCase{ + ptr: (*[]byte)(nil), + input: `"c3ViamVjdHM\/X2Q9MQ=="`, }) } diff --git a/vendor/github.com/json-iterator/go/value_tests/struct_test.go b/vendor/github.com/json-iterator/go/value_tests/struct_test.go index 2335d0786..067ad22f8 100644 --- a/vendor/github.com/json-iterator/go/value_tests/struct_test.go +++ b/vendor/github.com/json-iterator/go/value_tests/struct_test.go @@ -63,6 +63,36 @@ func init() { d *time.Timer })(nil), input: `{"a": 444, "b":"bad", "C":256, "d":{"not":"a timer"}}`, + }, unmarshalCase{ + ptr: (*struct { + A string + B string + C string + D string + E string + F string + G string + H string + I string + J string + K string + })(nil), + input: `{"a":"1","b":"2","c":"3","d":"4","e":"5","f":"6","g":"7","h":"8","i":"9","j":"10","k":"11"}`, + }, unmarshalCase{ + ptr: (*struct { + T float64 `json:"T"` + })(nil), + input: `{"t":10.0}`, + }, unmarshalCase{ + ptr: (*struct { + T float64 `json:"T"` + })(nil), + input: `{"T":10.0}`, + }, unmarshalCase{ + ptr: (*struct { + T float64 `json:"t"` + })(nil), + input: `{"T":10.0}`, }) marshalCases = append(marshalCases, struct { diff --git a/vendor/github.com/petar/GoLLRB/.gitignore b/vendor/github.com/petar/GoLLRB/.gitignore new file mode 100644 index 000000000..e333b2dbf --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/.gitignore @@ -0,0 +1,23 @@ +syntax:glob +*.[568ao] +*.ao +*.so +*.pyc +*.swp +*.swo +._* +.nfs.* +[568a].out +*~ +*.orig +*.pb.go +core +_obj +_test +src/pkg/Make.deps +_testmain.go + +syntax:regexp +^pkg/ +^src/cmd/(.*)/6?\1$ +^.*/core.[0-9]*$ diff --git a/vendor/github.com/petar/GoLLRB/AUTHORS b/vendor/github.com/petar/GoLLRB/AUTHORS new file mode 100644 index 000000000..78d1de495 --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/AUTHORS @@ -0,0 +1,4 @@ +Petar Maymounkov +Vadim Vygonets +Ian Smith +Martin Bruse diff --git a/vendor/github.com/petar/GoLLRB/LICENSE b/vendor/github.com/petar/GoLLRB/LICENSE new file mode 100644 index 000000000..b75312c78 --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2010, Petar Maymounkov +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +(*) Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. + +(*) Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +(*) Neither the name of Petar Maymounkov nor the names of its contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/petar/GoLLRB/README.md b/vendor/github.com/petar/GoLLRB/README.md new file mode 100644 index 000000000..742ca0bd5 --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/README.md @@ -0,0 +1,66 @@ +# GoLLRB + +GoLLRB is a Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary +search trees in Go Language. + +## Overview + +As of this writing and to the best of the author's knowledge, +Go still does not have a balanced binary search tree (BBST) data structure. +These data structures are quite useful in a variety of cases. A BBST maintains +elements in sorted order under dynamic updates (inserts and deletes) and can +support various order-specific queries. Furthermore, in practice one often +implements other common data structures like Priority Queues, using BBST's. + +2-3 trees (a type of BBST's), as well as the runtime-similar 2-3-4 trees, are +the de facto standard BBST algoritms found in implementations of Python, Java, +and other libraries. The LLRB method of implementing 2-3 trees is a recent +improvement over the traditional implementation. The LLRB approach was +discovered relatively recently (in 2008) by Robert Sedgewick of Princeton +University. + +GoLLRB is a Go implementation of LLRB 2-3 trees. + +## Maturity + +GoLLRB has been used in some pretty heavy-weight machine learning tasks over many gigabytes of data. +I consider it to be in stable, perhaps even production, shape. There are no known bugs. + +## Installation + +With a healthy Go Language installed, simply run `go get github.com/petar/GoLLRB/llrb` + +## Example + + package main + + import ( + "fmt" + "github.com/petar/GoLLRB/llrb" + ) + + func lessInt(a, b interface{}) bool { return a.(int) < b.(int) } + + func main() { + tree := llrb.New(lessInt) + tree.ReplaceOrInsert(1) + tree.ReplaceOrInsert(2) + tree.ReplaceOrInsert(3) + tree.ReplaceOrInsert(4) + tree.DeleteMin() + tree.Delete(4) + c := tree.IterAscend() + for { + u := <-c + if u == nil { + break + } + fmt.Printf("%d\n", int(u.(int))) + } + } + +## About + +GoLLRB was written by [Petar Maymounkov](http://pdos.csail.mit.edu/~petar/). + +Follow me on [Twitter @maymounkov](http://www.twitter.com/maymounkov)! diff --git a/vendor/github.com/petar/GoLLRB/doc/Sedgewick-LLRB.pdf b/vendor/github.com/petar/GoLLRB/doc/Sedgewick-LLRB.pdf new file mode 100644 index 000000000..a399b06ae Binary files /dev/null and b/vendor/github.com/petar/GoLLRB/doc/Sedgewick-LLRB.pdf differ diff --git a/vendor/github.com/petar/GoLLRB/doc/Sedgewick-RedBlackBST.java b/vendor/github.com/petar/GoLLRB/doc/Sedgewick-RedBlackBST.java new file mode 100644 index 000000000..55ac177f8 --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/doc/Sedgewick-RedBlackBST.java @@ -0,0 +1,475 @@ +public class RedBlackBST, Value> +{ + private static final int BST = 0; + private static final int TD234 = 1; + private static final int BU23 = 2; + private static final boolean RED = true; + private static final boolean BLACK = false; + + private Node root; // root of the BST + private int k; // ordinal for drawing + private final int species; // species kind of tree for insert + private int heightBLACK; // black height of tree + + RedBlackBST(int species) + { this.species = species; } + + private class Node + { + Key key; // key + Value value; // associated data + Node left, right; // left and right subtrees + boolean color; // color of parent link + private int N; // number of nodes in tree rooted here + private int height; // height of tree rooted here + private double xc, yc; // for drawing + + Node(Key key, Value value) + { + this.key = key; + this.value = value; + this.color = RED; + this.N = 1; + this.height = 1; + } + } + + public int size() + { return size(root); } + + private int size(Node x) + { + if (x == null) return 0; + else return x.N; + } + + public int rootRank() + { + if (root == null) return 0; + else return size(root.left); + } + + public int height() + { return height(root); } + + public int heightB() + { return heightBLACK; } + + private int height(Node x) + { + if (x == null) return 0; + else return x.height; + } + + public boolean contains(Key key) + { return (get(key) != null); } + + public Value get(Key key) + { return get(root, key); } + + private Value get(Node x, Key key) + { + if (x == null) return null; + if (eq (key, x.key)) return x.value; + if (less(key, x.key)) return get(x.left, key); + else return get(x.right, key); + } + + public Key min() + { + if (root == null) return null; + else return min(root); + } + + private Key min(Node x) + { + if (x.left == null) return x.key; + else return min(x.left); + } + + public Key max() + { + if (root == null) return null; + else return max(root); + } + + private Key max(Node x) + { + if (x.right == null) return x.key; + else return max(x.right); + } + + public void put(Key key, Value value) + { + root = insert(root, key, value); + if (isRed(root)) heightBLACK++; + root.color = BLACK; + } + + private Node insert(Node h, Key key, Value value) + { + if (h == null) + return new Node(key, value); + + if (species == TD234) + if (isRed(h.left) && isRed(h.right)) + colorFlip(h); + + if (eq(key, h.key)) + h.value = value; + else if (less(key, h.key)) + h.left = insert(h.left, key, value); + else + h.right = insert(h.right, key, value); + + if (species == BST) return setN(h); + + if (isRed(h.right)) + h = rotateLeft(h); + + if (isRed(h.left) && isRed(h.left.left)) + h = rotateRight(h); + + if (species == BU23) + if (isRed(h.left) && isRed(h.right)) + colorFlip(h); + + return setN(h); + } + + public void deleteMin() + { + root = deleteMin(root); + root.color = BLACK; + } + + private Node deleteMin(Node h) + { + if (h.left == null) + return null; + + if (!isRed(h.left) && !isRed(h.left.left)) + h = moveRedLeft(h); + + h.left = deleteMin(h.left); + + return fixUp(h); + } + + public void deleteMax() + { + root = deleteMax(root); + root.color = BLACK; + } + + private Node deleteMax(Node h) + { + // if (h.right == null) + // { + // if (h.left != null) + // h.left.color = BLACK; + // return h.left; + // } + + if (isRed(h.left)) + h = rotateRight(h); + + if (h.right == null) + return null; + + if (!isRed(h.right) && !isRed(h.right.left)) + h = moveRedRight(h); + + h.right = deleteMax(h.right); + + return fixUp(h); + } + + public void delete(Key key) + { + root = delete(root, key); + root.color = BLACK; + } + + private Node delete(Node h, Key key) + { + if (less(key, h.key)) + { + if (!isRed(h.left) && !isRed(h.left.left)) + h = moveRedLeft(h); + h.left = delete(h.left, key); + } + else + { + if (isRed(h.left)) + h = rotateRight(h); + if (eq(key, h.key) && (h.right == null)) + return null; + if (!isRed(h.right) && !isRed(h.right.left)) + h = moveRedRight(h); + if (eq(key, h.key)) + { + h.value = get(h.right, min(h.right)); + h.key = min(h.right); + h.right = deleteMin(h.right); + } + else h.right = delete(h.right, key); + } + + return fixUp(h); + } + +// Helper methods + + private boolean less(Key a, Key b) { return a.compareTo(b) < 0; } + private boolean eq (Key a, Key b) { return a.compareTo(b) == 0; } + + private boolean isRed(Node x) + { + if (x == null) return false; + return (x.color == RED); + } + + private void colorFlip(Node h) + { + h.color = !h.color; + h.left.color = !h.left.color; + h.right.color = !h.right.color; + } + + private Node rotateLeft(Node h) + { // Make a right-leaning 3-node lean to the left. + Node x = h.right; + h.right = x.left; + x.left = setN(h); + x.color = x.left.color; + x.left.color = RED; + return setN(x); + } + + private Node rotateRight(Node h) + { // Make a left-leaning 3-node lean to the right. + Node x = h.left; + h.left = x.right; + x.right = setN(h); + x.color = x.right.color; + x.right.color = RED; + return setN(x); + } + + private Node moveRedLeft(Node h) + { // Assuming that h is red and both h.left and h.left.left + // are black, make h.left or one of its children red. + colorFlip(h); + if (isRed(h.right.left)) + { + h.right = rotateRight(h.right); + h = rotateLeft(h); + colorFlip(h); + } + return h; + } + + private Node moveRedRight(Node h) + { // Assuming that h is red and both h.right and h.right.left + // are black, make h.right or one of its children red. + colorFlip(h); + if (isRed(h.left.left)) + { + h = rotateRight(h); + colorFlip(h); + } + return h; + } + + private Node fixUp(Node h) + { + if (isRed(h.right)) + h = rotateLeft(h); + + if (isRed(h.left) && isRed(h.left.left)) + h = rotateRight(h); + + if (isRed(h.left) && isRed(h.right)) + colorFlip(h); + + return setN(h); + } + + private Node setN(Node h) + { + h.N = size(h.left) + size(h.right) + 1; + if (height(h.left) > height(h.right)) h.height = height(h.left) + 1; + else h.height = height(h.right) + 1; + return h; + } + + public String toString() + { + if (root == null) return ""; + else return heightB() + " " + toString(root); + } + + public String toString(Node x) + { + String s = "("; + if (x.left == null) s += "("; else s += toString(x.left); + if (isRed(x)) s += "*"; + if (x.right == null) s += ")"; else s += toString(x.right); + return s + ")"; + } + +// Methods for tree drawing + + public void draw(double y, double lineWidth, double nodeSize) + { + k = 0; + setcoords(root, y); + StdDraw.setPenColor(StdDraw.BLACK); + StdDraw.setPenRadius(lineWidth); + drawlines(root); + StdDraw.setPenColor(StdDraw.WHITE); + drawnodes(root, nodeSize); + } + + public void setcoords(Node x, double d) + { + if (x == null) return; + setcoords(x.left, d-.04); + x.xc = (0.5 + k++)/size(); x.yc = d - .04; + setcoords(x.right, d-.04); + } + + public void drawlines(Node x) + { + if (x == null) return; + drawlines(x.left); + if (x.left != null) + { + if (x.left.color == RED) StdDraw.setPenColor(StdDraw.RED); + else StdDraw.setPenColor(StdDraw.BLACK); + StdDraw.line(x.xc, x.yc, x.left.xc, x.left.yc); + } + if (x.right != null) + { + if (x.right.color == RED) StdDraw.setPenColor(StdDraw.RED); + else StdDraw.setPenColor(StdDraw.BLACK); + StdDraw.line(x.xc, x.yc, x.right.xc, x.right.yc); + } + drawlines(x.right); + } + + public void drawnodes(Node x, double nodeSize) + { + if (x == null) return; + drawnodes(x.left, nodeSize); + StdDraw.filledCircle(x.xc, x.yc, nodeSize); + drawnodes(x.right, nodeSize); + } + + public void mark(Key key) + { + StdDraw.setPenColor(StdDraw.BLACK); + marknodes(key, root); + } + + public void marknodes(Key key, Node x) + { + if (x == null) return; + marknodes(key, x.left); + if (eq(key, x.key)) + StdDraw.filledCircle(x.xc, x.yc, .004); + marknodes(key, x.right); + } + + public int ipl() + { return ipl(root); } + + public int ipl(Node x) + { + if (x == null) return 0; + return size(x) - 1 + ipl(x.left) + ipl(x.right); + } + + public int sizeRed() + { return sizeRed(root); } + + public int sizeRed(Node x) + { + if (x == null) return 0; + if (isRed(x)) return 1 + sizeRed(x.left) + sizeRed(x.right); + else return sizeRed(x.left) + sizeRed(x.right); + } + +// Integrity checks + + public boolean check() + { // Is this tree a red-black tree? + return isBST() && is234() && isBalanced(); + } + + private boolean isBST() + { // Is this tree a BST? + return isBST(root, min(), max()); + } + + private boolean isBST(Node x, Key min, Key max) + { // Are all the values in the BST rooted at x between min and max, + // and does the same property hold for both subtrees? + if (x == null) return true; + if (less(x.key, min) || less(max, x.key)) return false; + return isBST(x.left, min, x.key) && isBST(x.right, x.key, max); + } + + private boolean is234() { return is234(root); } + private boolean is234(Node x) + { // Does the tree have no red right links, and at most two (left) + // red links in a row on any path? + if (x == null) return true; + if (isRed(x.right)) return false; + if (isRed(x)) + if (isRed(x.left)) + if (isRed(x.left.left)) return false; + return is234(x.left) && is234(x.right); + } + + private boolean isBalanced() + { // Do all paths from root to leaf have same number of black edges? + int black = 0; // number of black links on path from root to min + Node x = root; + while (x != null) + { + if (!isRed(x)) black++; + x = x.left; + } + return isBalanced(root, black); + } + + private boolean isBalanced(Node x, int black) + { // Does every path from the root to a leaf have the given number + // of black links? + if (x == null && black == 0) return true; + else if (x == null && black != 0) return false; + if (!isRed(x)) black--; + return isBalanced(x.left, black) && isBalanced(x.right, black); + } + + + public static void main(String[] args) + { + StdDraw.setPenRadius(.0025); + int species = Integer.parseInt(args[0]); + RedBlackBST st; + st = new RedBlackBST(species); + int[] a = { 3, 1, 4, 2, 5, 9, 6, 8, 7 }; + for (int i = 0; i < a.length; i++) + st.put(a[i], i); + StdOut.println(st); + StdDraw.clear(StdDraw.LIGHT_GRAY); + st.draw(.95, .0025, .008); + StdOut.println(st.min() + " " + st.max() + " " + st.check()); + StdOut.println(st.ipl()); + StdOut.println(st.heightB()); + } + +} diff --git a/vendor/github.com/petar/GoLLRB/doc/Sedgewick-Talk-Penn2008.pdf b/vendor/github.com/petar/GoLLRB/doc/Sedgewick-Talk-Penn2008.pdf new file mode 100644 index 000000000..07861abed Binary files /dev/null and b/vendor/github.com/petar/GoLLRB/doc/Sedgewick-Talk-Penn2008.pdf differ diff --git a/vendor/github.com/petar/GoLLRB/example/ex1.go b/vendor/github.com/petar/GoLLRB/example/ex1.go new file mode 100644 index 000000000..6ebe4a686 --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/example/ex1.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "github.com/petar/GoLLRB/llrb" +) + +func lessInt(a, b interface{}) bool { return a.(int) < b.(int) } + +func main() { + tree := llrb.New(lessInt) + tree.ReplaceOrInsert(1) + tree.ReplaceOrInsert(2) + tree.ReplaceOrInsert(3) + tree.ReplaceOrInsert(4) + tree.DeleteMin() + tree.Delete(4) + c := tree.IterAscend() + for { + u := <-c + if u == nil { + break + } + fmt.Printf("%d\n", int(u.(int))) + } +} diff --git a/vendor/github.com/petar/GoLLRB/llrb/avgvar.go b/vendor/github.com/petar/GoLLRB/llrb/avgvar.go new file mode 100644 index 000000000..2d7e2a326 --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/llrb/avgvar.go @@ -0,0 +1,39 @@ +// Copyright 2010 Petar Maymounkov. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package llrb + +import "math" + +// avgVar maintains the average and variance of a stream of numbers +// in a space-efficient manner. +type avgVar struct { + count int64 + sum, sumsq float64 +} + +func (av *avgVar) Init() { + av.count = 0 + av.sum = 0.0 + av.sumsq = 0.0 +} + +func (av *avgVar) Add(sample float64) { + av.count++ + av.sum += sample + av.sumsq += sample * sample +} + +func (av *avgVar) GetCount() int64 { return av.count } + +func (av *avgVar) GetAvg() float64 { return av.sum / float64(av.count) } + +func (av *avgVar) GetTotal() float64 { return av.sum } + +func (av *avgVar) GetVar() float64 { + a := av.GetAvg() + return av.sumsq/float64(av.count) - a*a +} + +func (av *avgVar) GetStdDev() float64 { return math.Sqrt(av.GetVar()) } diff --git a/vendor/github.com/petar/GoLLRB/llrb/iterator.go b/vendor/github.com/petar/GoLLRB/llrb/iterator.go new file mode 100644 index 000000000..ee7b27f44 --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/llrb/iterator.go @@ -0,0 +1,93 @@ +package llrb + +type ItemIterator func(i Item) bool + +//func (t *Tree) Ascend(iterator ItemIterator) { +// t.AscendGreaterOrEqual(Inf(-1), iterator) +//} + +func (t *LLRB) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator) { + t.ascendRange(t.root, greaterOrEqual, lessThan, iterator) +} + +func (t *LLRB) ascendRange(h *Node, inf, sup Item, iterator ItemIterator) bool { + if h == nil { + return true + } + if !less(h.Item, sup) { + return t.ascendRange(h.Left, inf, sup, iterator) + } + if less(h.Item, inf) { + return t.ascendRange(h.Right, inf, sup, iterator) + } + + if !t.ascendRange(h.Left, inf, sup, iterator) { + return false + } + if !iterator(h.Item) { + return false + } + return t.ascendRange(h.Right, inf, sup, iterator) +} + +// AscendGreaterOrEqual will call iterator once for each element greater or equal to +// pivot in ascending order. It will stop whenever the iterator returns false. +func (t *LLRB) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) { + t.ascendGreaterOrEqual(t.root, pivot, iterator) +} + +func (t *LLRB) ascendGreaterOrEqual(h *Node, pivot Item, iterator ItemIterator) bool { + if h == nil { + return true + } + if !less(h.Item, pivot) { + if !t.ascendGreaterOrEqual(h.Left, pivot, iterator) { + return false + } + if !iterator(h.Item) { + return false + } + } + return t.ascendGreaterOrEqual(h.Right, pivot, iterator) +} + +func (t *LLRB) AscendLessThan(pivot Item, iterator ItemIterator) { + t.ascendLessThan(t.root, pivot, iterator) +} + +func (t *LLRB) ascendLessThan(h *Node, pivot Item, iterator ItemIterator) bool { + if h == nil { + return true + } + if !t.ascendLessThan(h.Left, pivot, iterator) { + return false + } + if !iterator(h.Item) { + return false + } + if less(h.Item, pivot) { + return t.ascendLessThan(h.Left, pivot, iterator) + } + return true +} + +// DescendLessOrEqual will call iterator once for each element less than the +// pivot in descending order. It will stop whenever the iterator returns false. +func (t *LLRB) DescendLessOrEqual(pivot Item, iterator ItemIterator) { + t.descendLessOrEqual(t.root, pivot, iterator) +} + +func (t *LLRB) descendLessOrEqual(h *Node, pivot Item, iterator ItemIterator) bool { + if h == nil { + return true + } + if less(h.Item, pivot) || !less(pivot, h.Item) { + if !t.descendLessOrEqual(h.Right, pivot, iterator) { + return false + } + if !iterator(h.Item) { + return false + } + } + return t.descendLessOrEqual(h.Left, pivot, iterator) +} diff --git a/vendor/github.com/petar/GoLLRB/llrb/iterator_test.go b/vendor/github.com/petar/GoLLRB/llrb/iterator_test.go new file mode 100644 index 000000000..db5e12c92 --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/llrb/iterator_test.go @@ -0,0 +1,76 @@ +package llrb + +import ( + "reflect" + "testing" +) + +func TestAscendGreaterOrEqual(t *testing.T) { + tree := New() + tree.InsertNoReplace(Int(4)) + tree.InsertNoReplace(Int(6)) + tree.InsertNoReplace(Int(1)) + tree.InsertNoReplace(Int(3)) + var ary []Item + tree.AscendGreaterOrEqual(Int(-1), func(i Item) bool { + ary = append(ary, i) + return true + }) + expected := []Item{Int(1), Int(3), Int(4), Int(6)} + if !reflect.DeepEqual(ary, expected) { + t.Errorf("expected %v but got %v", expected, ary) + } + ary = nil + tree.AscendGreaterOrEqual(Int(3), func(i Item) bool { + ary = append(ary, i) + return true + }) + expected = []Item{Int(3), Int(4), Int(6)} + if !reflect.DeepEqual(ary, expected) { + t.Errorf("expected %v but got %v", expected, ary) + } + ary = nil + tree.AscendGreaterOrEqual(Int(2), func(i Item) bool { + ary = append(ary, i) + return true + }) + expected = []Item{Int(3), Int(4), Int(6)} + if !reflect.DeepEqual(ary, expected) { + t.Errorf("expected %v but got %v", expected, ary) + } +} + +func TestDescendLessOrEqual(t *testing.T) { + tree := New() + tree.InsertNoReplace(Int(4)) + tree.InsertNoReplace(Int(6)) + tree.InsertNoReplace(Int(1)) + tree.InsertNoReplace(Int(3)) + var ary []Item + tree.DescendLessOrEqual(Int(10), func(i Item) bool { + ary = append(ary, i) + return true + }) + expected := []Item{Int(6), Int(4), Int(3), Int(1)} + if !reflect.DeepEqual(ary, expected) { + t.Errorf("expected %v but got %v", expected, ary) + } + ary = nil + tree.DescendLessOrEqual(Int(4), func(i Item) bool { + ary = append(ary, i) + return true + }) + expected = []Item{Int(4), Int(3), Int(1)} + if !reflect.DeepEqual(ary, expected) { + t.Errorf("expected %v but got %v", expected, ary) + } + ary = nil + tree.DescendLessOrEqual(Int(5), func(i Item) bool { + ary = append(ary, i) + return true + }) + expected = []Item{Int(4), Int(3), Int(1)} + if !reflect.DeepEqual(ary, expected) { + t.Errorf("expected %v but got %v", expected, ary) + } +} diff --git a/vendor/github.com/petar/GoLLRB/llrb/llrb-stats.go b/vendor/github.com/petar/GoLLRB/llrb/llrb-stats.go new file mode 100644 index 000000000..47126a3be --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/llrb/llrb-stats.go @@ -0,0 +1,46 @@ +// Copyright 2010 Petar Maymounkov. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package llrb + +// GetHeight() returns an item in the tree with key @key, and it's height in the tree +func (t *LLRB) GetHeight(key Item) (result Item, depth int) { + return t.getHeight(t.root, key) +} + +func (t *LLRB) getHeight(h *Node, item Item) (Item, int) { + if h == nil { + return nil, 0 + } + if less(item, h.Item) { + result, depth := t.getHeight(h.Left, item) + return result, depth + 1 + } + if less(h.Item, item) { + result, depth := t.getHeight(h.Right, item) + return result, depth + 1 + } + return h.Item, 0 +} + +// HeightStats() returns the average and standard deviation of the height +// of elements in the tree +func (t *LLRB) HeightStats() (avg, stddev float64) { + av := &avgVar{} + heightStats(t.root, 0, av) + return av.GetAvg(), av.GetStdDev() +} + +func heightStats(h *Node, d int, av *avgVar) { + if h == nil { + return + } + av.Add(float64(d)) + if h.Left != nil { + heightStats(h.Left, d+1, av) + } + if h.Right != nil { + heightStats(h.Right, d+1, av) + } +} diff --git a/vendor/github.com/petar/GoLLRB/llrb/llrb.go b/vendor/github.com/petar/GoLLRB/llrb/llrb.go new file mode 100644 index 000000000..81373fbfd --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/llrb/llrb.go @@ -0,0 +1,456 @@ +// Copyright 2010 Petar Maymounkov. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// A Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary search trees, +// based on the following work: +// +// http://www.cs.princeton.edu/~rs/talks/LLRB/08Penn.pdf +// http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf +// http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java +// +// 2-3 trees (and the run-time equivalent 2-3-4 trees) are the de facto standard BST +// algoritms found in implementations of Python, Java, and other libraries. The LLRB +// implementation of 2-3 trees is a recent improvement on the traditional implementation, +// observed and documented by Robert Sedgewick. +// +package llrb + +// Tree is a Left-Leaning Red-Black (LLRB) implementation of 2-3 trees +type LLRB struct { + count int + root *Node +} + +type Node struct { + Item + Left, Right *Node // Pointers to left and right child nodes + Black bool // If set, the color of the link (incoming from the parent) is black + // In the LLRB, new nodes are always red, hence the zero-value for node +} + +type Item interface { + Less(than Item) bool +} + +// +func less(x, y Item) bool { + if x == pinf { + return false + } + if x == ninf { + return true + } + return x.Less(y) +} + +// Inf returns an Item that is "bigger than" any other item, if sign is positive. +// Otherwise it returns an Item that is "smaller than" any other item. +func Inf(sign int) Item { + if sign == 0 { + panic("sign") + } + if sign > 0 { + return pinf + } + return ninf +} + +var ( + ninf = nInf{} + pinf = pInf{} +) + +type nInf struct{} + +func (nInf) Less(Item) bool { + return true +} + +type pInf struct{} + +func (pInf) Less(Item) bool { + return false +} + +// New() allocates a new tree +func New() *LLRB { + return &LLRB{} +} + +// SetRoot sets the root node of the tree. +// It is intended to be used by functions that deserialize the tree. +func (t *LLRB) SetRoot(r *Node) { + t.root = r +} + +// Root returns the root node of the tree. +// It is intended to be used by functions that serialize the tree. +func (t *LLRB) Root() *Node { + return t.root +} + +// Len returns the number of nodes in the tree. +func (t *LLRB) Len() int { return t.count } + +// Has returns true if the tree contains an element whose order is the same as that of key. +func (t *LLRB) Has(key Item) bool { + return t.Get(key) != nil +} + +// Get retrieves an element from the tree whose order is the same as that of key. +func (t *LLRB) Get(key Item) Item { + h := t.root + for h != nil { + switch { + case less(key, h.Item): + h = h.Left + case less(h.Item, key): + h = h.Right + default: + return h.Item + } + } + return nil +} + +// Min returns the minimum element in the tree. +func (t *LLRB) Min() Item { + h := t.root + if h == nil { + return nil + } + for h.Left != nil { + h = h.Left + } + return h.Item +} + +// Max returns the maximum element in the tree. +func (t *LLRB) Max() Item { + h := t.root + if h == nil { + return nil + } + for h.Right != nil { + h = h.Right + } + return h.Item +} + +func (t *LLRB) ReplaceOrInsertBulk(items ...Item) { + for _, i := range items { + t.ReplaceOrInsert(i) + } +} + +func (t *LLRB) InsertNoReplaceBulk(items ...Item) { + for _, i := range items { + t.InsertNoReplace(i) + } +} + +// ReplaceOrInsert inserts item into the tree. If an existing +// element has the same order, it is removed from the tree and returned. +func (t *LLRB) ReplaceOrInsert(item Item) Item { + if item == nil { + panic("inserting nil item") + } + var replaced Item + t.root, replaced = t.replaceOrInsert(t.root, item) + t.root.Black = true + if replaced == nil { + t.count++ + } + return replaced +} + +func (t *LLRB) replaceOrInsert(h *Node, item Item) (*Node, Item) { + if h == nil { + return newNode(item), nil + } + + h = walkDownRot23(h) + + var replaced Item + if less(item, h.Item) { // BUG + h.Left, replaced = t.replaceOrInsert(h.Left, item) + } else if less(h.Item, item) { + h.Right, replaced = t.replaceOrInsert(h.Right, item) + } else { + replaced, h.Item = h.Item, item + } + + h = walkUpRot23(h) + + return h, replaced +} + +// InsertNoReplace inserts item into the tree. If an existing +// element has the same order, both elements remain in the tree. +func (t *LLRB) InsertNoReplace(item Item) { + if item == nil { + panic("inserting nil item") + } + t.root = t.insertNoReplace(t.root, item) + t.root.Black = true + t.count++ +} + +func (t *LLRB) insertNoReplace(h *Node, item Item) *Node { + if h == nil { + return newNode(item) + } + + h = walkDownRot23(h) + + if less(item, h.Item) { + h.Left = t.insertNoReplace(h.Left, item) + } else { + h.Right = t.insertNoReplace(h.Right, item) + } + + return walkUpRot23(h) +} + +// Rotation driver routines for 2-3 algorithm + +func walkDownRot23(h *Node) *Node { return h } + +func walkUpRot23(h *Node) *Node { + if isRed(h.Right) && !isRed(h.Left) { + h = rotateLeft(h) + } + + if isRed(h.Left) && isRed(h.Left.Left) { + h = rotateRight(h) + } + + if isRed(h.Left) && isRed(h.Right) { + flip(h) + } + + return h +} + +// Rotation driver routines for 2-3-4 algorithm + +func walkDownRot234(h *Node) *Node { + if isRed(h.Left) && isRed(h.Right) { + flip(h) + } + + return h +} + +func walkUpRot234(h *Node) *Node { + if isRed(h.Right) && !isRed(h.Left) { + h = rotateLeft(h) + } + + if isRed(h.Left) && isRed(h.Left.Left) { + h = rotateRight(h) + } + + return h +} + +// DeleteMin deletes the minimum element in the tree and returns the +// deleted item or nil otherwise. +func (t *LLRB) DeleteMin() Item { + var deleted Item + t.root, deleted = deleteMin(t.root) + if t.root != nil { + t.root.Black = true + } + if deleted != nil { + t.count-- + } + return deleted +} + +// deleteMin code for LLRB 2-3 trees +func deleteMin(h *Node) (*Node, Item) { + if h == nil { + return nil, nil + } + if h.Left == nil { + return nil, h.Item + } + + if !isRed(h.Left) && !isRed(h.Left.Left) { + h = moveRedLeft(h) + } + + var deleted Item + h.Left, deleted = deleteMin(h.Left) + + return fixUp(h), deleted +} + +// DeleteMax deletes the maximum element in the tree and returns +// the deleted item or nil otherwise +func (t *LLRB) DeleteMax() Item { + var deleted Item + t.root, deleted = deleteMax(t.root) + if t.root != nil { + t.root.Black = true + } + if deleted != nil { + t.count-- + } + return deleted +} + +func deleteMax(h *Node) (*Node, Item) { + if h == nil { + return nil, nil + } + if isRed(h.Left) { + h = rotateRight(h) + } + if h.Right == nil { + return nil, h.Item + } + if !isRed(h.Right) && !isRed(h.Right.Left) { + h = moveRedRight(h) + } + var deleted Item + h.Right, deleted = deleteMax(h.Right) + + return fixUp(h), deleted +} + +// Delete deletes an item from the tree whose key equals key. +// The deleted item is return, otherwise nil is returned. +func (t *LLRB) Delete(key Item) Item { + var deleted Item + t.root, deleted = t.delete(t.root, key) + if t.root != nil { + t.root.Black = true + } + if deleted != nil { + t.count-- + } + return deleted +} + +func (t *LLRB) delete(h *Node, item Item) (*Node, Item) { + var deleted Item + if h == nil { + return nil, nil + } + if less(item, h.Item) { + if h.Left == nil { // item not present. Nothing to delete + return h, nil + } + if !isRed(h.Left) && !isRed(h.Left.Left) { + h = moveRedLeft(h) + } + h.Left, deleted = t.delete(h.Left, item) + } else { + if isRed(h.Left) { + h = rotateRight(h) + } + // If @item equals @h.Item and no right children at @h + if !less(h.Item, item) && h.Right == nil { + return nil, h.Item + } + // PETAR: Added 'h.Right != nil' below + if h.Right != nil && !isRed(h.Right) && !isRed(h.Right.Left) { + h = moveRedRight(h) + } + // If @item equals @h.Item, and (from above) 'h.Right != nil' + if !less(h.Item, item) { + var subDeleted Item + h.Right, subDeleted = deleteMin(h.Right) + if subDeleted == nil { + panic("logic") + } + deleted, h.Item = h.Item, subDeleted + } else { // Else, @item is bigger than @h.Item + h.Right, deleted = t.delete(h.Right, item) + } + } + + return fixUp(h), deleted +} + +// Internal node manipulation routines + +func newNode(item Item) *Node { return &Node{Item: item} } + +func isRed(h *Node) bool { + if h == nil { + return false + } + return !h.Black +} + +func rotateLeft(h *Node) *Node { + x := h.Right + if x.Black { + panic("rotating a black link") + } + h.Right = x.Left + x.Left = h + x.Black = h.Black + h.Black = false + return x +} + +func rotateRight(h *Node) *Node { + x := h.Left + if x.Black { + panic("rotating a black link") + } + h.Left = x.Right + x.Right = h + x.Black = h.Black + h.Black = false + return x +} + +// REQUIRE: Left and Right children must be present +func flip(h *Node) { + h.Black = !h.Black + h.Left.Black = !h.Left.Black + h.Right.Black = !h.Right.Black +} + +// REQUIRE: Left and Right children must be present +func moveRedLeft(h *Node) *Node { + flip(h) + if isRed(h.Right.Left) { + h.Right = rotateRight(h.Right) + h = rotateLeft(h) + flip(h) + } + return h +} + +// REQUIRE: Left and Right children must be present +func moveRedRight(h *Node) *Node { + flip(h) + if isRed(h.Left.Left) { + h = rotateRight(h) + flip(h) + } + return h +} + +func fixUp(h *Node) *Node { + if isRed(h.Right) { + h = rotateLeft(h) + } + + if isRed(h.Left) && isRed(h.Left.Left) { + h = rotateRight(h) + } + + if isRed(h.Left) && isRed(h.Right) { + flip(h) + } + + return h +} diff --git a/vendor/github.com/petar/GoLLRB/llrb/llrb_test.go b/vendor/github.com/petar/GoLLRB/llrb/llrb_test.go new file mode 100644 index 000000000..b7bc97800 --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/llrb/llrb_test.go @@ -0,0 +1,239 @@ +// Copyright 2010 Petar Maymounkov. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package llrb + +import ( + "math" + "math/rand" + "testing" +) + +func TestCases(t *testing.T) { + tree := New() + tree.ReplaceOrInsert(Int(1)) + tree.ReplaceOrInsert(Int(1)) + if tree.Len() != 1 { + t.Errorf("expecting len 1") + } + if !tree.Has(Int(1)) { + t.Errorf("expecting to find key=1") + } + + tree.Delete(Int(1)) + if tree.Len() != 0 { + t.Errorf("expecting len 0") + } + if tree.Has(Int(1)) { + t.Errorf("not expecting to find key=1") + } + + tree.Delete(Int(1)) + if tree.Len() != 0 { + t.Errorf("expecting len 0") + } + if tree.Has(Int(1)) { + t.Errorf("not expecting to find key=1") + } +} + +func TestReverseInsertOrder(t *testing.T) { + tree := New() + n := 100 + for i := 0; i < n; i++ { + tree.ReplaceOrInsert(Int(n - i)) + } + i := 0 + tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { + i++ + if item.(Int) != Int(i) { + t.Errorf("bad order: got %d, expect %d", item.(Int), i) + } + return true + }) +} + +func TestRange(t *testing.T) { + tree := New() + order := []String{ + "ab", "aba", "abc", "a", "aa", "aaa", "b", "a-", "a!", + } + for _, i := range order { + tree.ReplaceOrInsert(i) + } + k := 0 + tree.AscendRange(String("ab"), String("ac"), func(item Item) bool { + if k > 3 { + t.Fatalf("returned more items than expected") + } + i1 := order[k] + i2 := item.(String) + if i1 != i2 { + t.Errorf("expecting %s, got %s", i1, i2) + } + k++ + return true + }) +} + +func TestRandomInsertOrder(t *testing.T) { + tree := New() + n := 1000 + perm := rand.Perm(n) + for i := 0; i < n; i++ { + tree.ReplaceOrInsert(Int(perm[i])) + } + j := 0 + tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { + if item.(Int) != Int(j) { + t.Fatalf("bad order") + } + j++ + return true + }) +} + +func TestRandomReplace(t *testing.T) { + tree := New() + n := 100 + perm := rand.Perm(n) + for i := 0; i < n; i++ { + tree.ReplaceOrInsert(Int(perm[i])) + } + perm = rand.Perm(n) + for i := 0; i < n; i++ { + if replaced := tree.ReplaceOrInsert(Int(perm[i])); replaced == nil || replaced.(Int) != Int(perm[i]) { + t.Errorf("error replacing") + } + } +} + +func TestRandomInsertSequentialDelete(t *testing.T) { + tree := New() + n := 1000 + perm := rand.Perm(n) + for i := 0; i < n; i++ { + tree.ReplaceOrInsert(Int(perm[i])) + } + for i := 0; i < n; i++ { + tree.Delete(Int(i)) + } +} + +func TestRandomInsertDeleteNonExistent(t *testing.T) { + tree := New() + n := 100 + perm := rand.Perm(n) + for i := 0; i < n; i++ { + tree.ReplaceOrInsert(Int(perm[i])) + } + if tree.Delete(Int(200)) != nil { + t.Errorf("deleted non-existent item") + } + if tree.Delete(Int(-2)) != nil { + t.Errorf("deleted non-existent item") + } + for i := 0; i < n; i++ { + if u := tree.Delete(Int(i)); u == nil || u.(Int) != Int(i) { + t.Errorf("delete failed") + } + } + if tree.Delete(Int(200)) != nil { + t.Errorf("deleted non-existent item") + } + if tree.Delete(Int(-2)) != nil { + t.Errorf("deleted non-existent item") + } +} + +func TestRandomInsertPartialDeleteOrder(t *testing.T) { + tree := New() + n := 100 + perm := rand.Perm(n) + for i := 0; i < n; i++ { + tree.ReplaceOrInsert(Int(perm[i])) + } + for i := 1; i < n-1; i++ { + tree.Delete(Int(i)) + } + j := 0 + tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { + switch j { + case 0: + if item.(Int) != Int(0) { + t.Errorf("expecting 0") + } + case 1: + if item.(Int) != Int(n-1) { + t.Errorf("expecting %d", n-1) + } + } + j++ + return true + }) +} + +func TestRandomInsertStats(t *testing.T) { + tree := New() + n := 100000 + perm := rand.Perm(n) + for i := 0; i < n; i++ { + tree.ReplaceOrInsert(Int(perm[i])) + } + avg, _ := tree.HeightStats() + expAvg := math.Log2(float64(n)) - 1.5 + if math.Abs(avg-expAvg) >= 2.0 { + t.Errorf("too much deviation from expected average height") + } +} + +func BenchmarkInsert(b *testing.B) { + tree := New() + for i := 0; i < b.N; i++ { + tree.ReplaceOrInsert(Int(b.N - i)) + } +} + +func BenchmarkDelete(b *testing.B) { + b.StopTimer() + tree := New() + for i := 0; i < b.N; i++ { + tree.ReplaceOrInsert(Int(b.N - i)) + } + b.StartTimer() + for i := 0; i < b.N; i++ { + tree.Delete(Int(i)) + } +} + +func BenchmarkDeleteMin(b *testing.B) { + b.StopTimer() + tree := New() + for i := 0; i < b.N; i++ { + tree.ReplaceOrInsert(Int(b.N - i)) + } + b.StartTimer() + for i := 0; i < b.N; i++ { + tree.DeleteMin() + } +} + +func TestInsertNoReplace(t *testing.T) { + tree := New() + n := 1000 + for q := 0; q < 2; q++ { + perm := rand.Perm(n) + for i := 0; i < n; i++ { + tree.InsertNoReplace(Int(perm[i])) + } + } + j := 0 + tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { + if item.(Int) != Int(j/2) { + t.Fatalf("bad order") + } + j++ + return true + }) +} diff --git a/vendor/github.com/petar/GoLLRB/llrb/util.go b/vendor/github.com/petar/GoLLRB/llrb/util.go new file mode 100644 index 000000000..63dbdb2df --- /dev/null +++ b/vendor/github.com/petar/GoLLRB/llrb/util.go @@ -0,0 +1,17 @@ +// Copyright 2010 Petar Maymounkov. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package llrb + +type Int int + +func (x Int) Less(than Item) bool { + return x < than.(Int) +} + +type String string + +func (x String) Less(than Item) bool { + return x < than.(String) +} diff --git a/vendor/github.com/peterbourgon/diskv/LICENSE b/vendor/github.com/peterbourgon/diskv/LICENSE new file mode 100644 index 000000000..41ce7f16e --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011-2012 Peter Bourgon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/peterbourgon/diskv/README.md b/vendor/github.com/peterbourgon/diskv/README.md new file mode 100644 index 000000000..3474739ed --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/README.md @@ -0,0 +1,141 @@ +# What is diskv? + +Diskv (disk-vee) is a simple, persistent key-value store written in the Go +language. It starts with an incredibly simple API for storing arbitrary data on +a filesystem by key, and builds several layers of performance-enhancing +abstraction on top. The end result is a conceptually simple, but highly +performant, disk-backed storage system. + +[![Build Status][1]][2] + +[1]: https://drone.io/github.com/peterbourgon/diskv/status.png +[2]: https://drone.io/github.com/peterbourgon/diskv/latest + + +# Installing + +Install [Go 1][3], either [from source][4] or [with a prepackaged binary][5]. +Then, + +```bash +$ go get github.com/peterbourgon/diskv +``` + +[3]: http://golang.org +[4]: http://golang.org/doc/install/source +[5]: http://golang.org/doc/install + + +# Usage + +```go +package main + +import ( + "fmt" + "github.com/peterbourgon/diskv" +) + +func main() { + // Simplest transform function: put all the data files into the base dir. + flatTransform := func(s string) []string { return []string{} } + + // Initialize a new diskv store, rooted at "my-data-dir", with a 1MB cache. + d := diskv.New(diskv.Options{ + BasePath: "my-data-dir", + Transform: flatTransform, + CacheSizeMax: 1024 * 1024, + }) + + // Write three bytes to the key "alpha". + key := "alpha" + d.Write(key, []byte{'1', '2', '3'}) + + // Read the value back out of the store. + value, _ := d.Read(key) + fmt.Printf("%v\n", value) + + // Erase the key+value from the store (and the disk). + d.Erase(key) +} +``` + +More complex examples can be found in the "examples" subdirectory. + + +# Theory + +## Basic idea + +At its core, diskv is a map of a key (`string`) to arbitrary data (`[]byte`). +The data is written to a single file on disk, with the same name as the key. +The key determines where that file will be stored, via a user-provided +`TransformFunc`, which takes a key and returns a slice (`[]string`) +corresponding to a path list where the key file will be stored. The simplest +TransformFunc, + +```go +func SimpleTransform (key string) []string { + return []string{} +} +``` + +will place all keys in the same, base directory. The design is inspired by +[Redis diskstore][6]; a TransformFunc which emulates the default diskstore +behavior is available in the content-addressable-storage example. + +[6]: http://groups.google.com/group/redis-db/browse_thread/thread/d444bc786689bde9?pli=1 + +**Note** that your TransformFunc should ensure that one valid key doesn't +transform to a subset of another valid key. That is, it shouldn't be possible +to construct valid keys that resolve to directory names. As a concrete example, +if your TransformFunc splits on every 3 characters, then + +```go +d.Write("abcabc", val) // OK: written to /abc/abc/abcabc +d.Write("abc", val) // Error: attempted write to /abc/abc, but it's a directory +``` + +This will be addressed in an upcoming version of diskv. + +Probably the most important design principle behind diskv is that your data is +always flatly available on the disk. diskv will never do anything that would +prevent you from accessing, copying, backing up, or otherwise interacting with +your data via common UNIX commandline tools. + +## Adding a cache + +An in-memory caching layer is provided by combining the BasicStore +functionality with a simple map structure, and keeping it up-to-date as +appropriate. Since the map structure in Go is not threadsafe, it's combined +with a RWMutex to provide safe concurrent access. + +## Adding order + +diskv is a key-value store and therefore inherently unordered. An ordering +system can be injected into the store by passing something which satisfies the +diskv.Index interface. (A default implementation, using Google's +[btree][7] package, is provided.) Basically, diskv keeps an ordered (by a +user-provided Less function) index of the keys, which can be queried. + +[7]: https://github.com/google/btree + +## Adding compression + +Something which implements the diskv.Compression interface may be passed +during store creation, so that all Writes and Reads are filtered through +a compression/decompression pipeline. Several default implementations, +using stdlib compression algorithms, are provided. Note that data is cached +compressed; the cost of decompression is borne with each Read. + +## Streaming + +diskv also now provides ReadStream and WriteStream methods, to allow very large +data to be handled efficiently. + + +# Future plans + + * Needs plenty of robust testing: huge datasets, etc... + * More thorough benchmarking + * Your suggestions for use-cases I haven't thought of diff --git a/vendor/github.com/peterbourgon/diskv/basic_test.go b/vendor/github.com/peterbourgon/diskv/basic_test.go new file mode 100644 index 000000000..0ef0b17fe --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/basic_test.go @@ -0,0 +1,336 @@ +package diskv + +import ( + "bytes" + "errors" + "testing" + "time" +) + +func cmpBytes(a, b []byte) bool { + if len(a) != len(b) { + return false + } + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false + } + } + return true +} + +func (d *Diskv) isCached(key string) bool { + d.mu.RLock() + defer d.mu.RUnlock() + _, ok := d.cache[key] + return ok +} + +func TestWriteReadErase(t *testing.T) { + d := New(Options{ + BasePath: "test-data", + CacheSizeMax: 1024, + }) + defer d.EraseAll() + k, v := "a", []byte{'b'} + if err := d.Write(k, v); err != nil { + t.Fatalf("write: %s", err) + } + if readVal, err := d.Read(k); err != nil { + t.Fatalf("read: %s", err) + } else if bytes.Compare(v, readVal) != 0 { + t.Fatalf("read: expected %s, got %s", v, readVal) + } + if err := d.Erase(k); err != nil { + t.Fatalf("erase: %s", err) + } +} + +func TestWRECache(t *testing.T) { + d := New(Options{ + BasePath: "test-data", + CacheSizeMax: 1024, + }) + defer d.EraseAll() + k, v := "xxx", []byte{' ', ' ', ' '} + if d.isCached(k) { + t.Fatalf("key cached before Write and Read") + } + if err := d.Write(k, v); err != nil { + t.Fatalf("write: %s", err) + } + if d.isCached(k) { + t.Fatalf("key cached before Read") + } + if readVal, err := d.Read(k); err != nil { + t.Fatalf("read: %s", err) + } else if bytes.Compare(v, readVal) != 0 { + t.Fatalf("read: expected %s, got %s", v, readVal) + } + for i := 0; i < 10 && !d.isCached(k); i++ { + time.Sleep(10 * time.Millisecond) + } + if !d.isCached(k) { + t.Fatalf("key not cached after Read") + } + if err := d.Erase(k); err != nil { + t.Fatalf("erase: %s", err) + } + if d.isCached(k) { + t.Fatalf("key cached after Erase") + } +} + +func TestStrings(t *testing.T) { + d := New(Options{ + BasePath: "test-data", + CacheSizeMax: 1024, + }) + defer d.EraseAll() + + keys := map[string]bool{"a": false, "b": false, "c": false, "d": false} + v := []byte{'1'} + for k := range keys { + if err := d.Write(k, v); err != nil { + t.Fatalf("write: %s: %s", k, err) + } + } + + for k := range d.Keys(nil) { + if _, present := keys[k]; present { + t.Logf("got: %s", k) + keys[k] = true + } else { + t.Fatalf("strings() returns unknown key: %s", k) + } + } + + for k, found := range keys { + if !found { + t.Errorf("never got %s", k) + } + } +} + +func TestZeroByteCache(t *testing.T) { + d := New(Options{ + BasePath: "test-data", + CacheSizeMax: 0, + }) + defer d.EraseAll() + + k, v := "a", []byte{'1', '2', '3'} + if err := d.Write(k, v); err != nil { + t.Fatalf("Write: %s", err) + } + + if d.isCached(k) { + t.Fatalf("key cached, expected not-cached") + } + + if _, err := d.Read(k); err != nil { + t.Fatalf("Read: %s", err) + } + + if d.isCached(k) { + t.Fatalf("key cached, expected not-cached") + } +} + +func TestOneByteCache(t *testing.T) { + d := New(Options{ + BasePath: "test-data", + CacheSizeMax: 1, + }) + defer d.EraseAll() + + k1, k2, v1, v2 := "a", "b", []byte{'1'}, []byte{'1', '2'} + if err := d.Write(k1, v1); err != nil { + t.Fatal(err) + } + + if v, err := d.Read(k1); err != nil { + t.Fatal(err) + } else if !cmpBytes(v, v1) { + t.Fatalf("Read: expected %s, got %s", string(v1), string(v)) + } + + for i := 0; i < 10 && !d.isCached(k1); i++ { + time.Sleep(10 * time.Millisecond) + } + if !d.isCached(k1) { + t.Fatalf("expected 1-byte value to be cached, but it wasn't") + } + + if err := d.Write(k2, v2); err != nil { + t.Fatal(err) + } + if _, err := d.Read(k2); err != nil { + t.Fatalf("--> %s", err) + } + + for i := 0; i < 10 && (!d.isCached(k1) || d.isCached(k2)); i++ { + time.Sleep(10 * time.Millisecond) // just wait for lazy-cache + } + if !d.isCached(k1) { + t.Fatalf("1-byte value was uncached for no reason") + } + + if d.isCached(k2) { + t.Fatalf("2-byte value was cached, but cache max size is 1") + } +} + +func TestStaleCache(t *testing.T) { + d := New(Options{ + BasePath: "test-data", + CacheSizeMax: 1, + }) + defer d.EraseAll() + + k, first, second := "a", "first", "second" + if err := d.Write(k, []byte(first)); err != nil { + t.Fatal(err) + } + + v, err := d.Read(k) + if err != nil { + t.Fatal(err) + } + if string(v) != first { + t.Errorf("expected '%s', got '%s'", first, v) + } + + if err := d.Write(k, []byte(second)); err != nil { + t.Fatal(err) + } + + v, err = d.Read(k) + if err != nil { + t.Fatal(err) + } + + if string(v) != second { + t.Errorf("expected '%s', got '%s'", second, v) + } +} + +func TestHas(t *testing.T) { + d := New(Options{ + BasePath: "test-data", + CacheSizeMax: 1024, + }) + defer d.EraseAll() + + for k, v := range map[string]string{ + "a": "1", + "foo": "2", + "012345": "3", + } { + d.Write(k, []byte(v)) + } + + d.Read("foo") // cache one of them + if !d.isCached("foo") { + t.Errorf("'foo' didn't get cached") + } + + for _, tuple := range []struct { + key string + expected bool + }{ + {"a", true}, + {"b", false}, + {"foo", true}, + {"bar", false}, + {"01234", false}, + {"012345", true}, + {"0123456", false}, + } { + if expected, got := tuple.expected, d.Has(tuple.key); expected != got { + t.Errorf("Has(%s): expected %v, got %v", tuple.key, expected, got) + } + } +} + +type BrokenReader struct{} + +func (BrokenReader) Read(p []byte) (n int, err error) { + return 0, errors.New("failed to read") +} + +func TestRemovesIncompleteFiles(t *testing.T) { + opts := Options{ + BasePath: "test-data", + CacheSizeMax: 1024, + } + d := New(opts) + defer d.EraseAll() + + key, stream, sync := "key", BrokenReader{}, false + + if err := d.WriteStream(key, stream, sync); err == nil { + t.Fatalf("Expected i/o copy error, none received.") + } + + if _, err := d.Read(key); err == nil { + t.Fatal("Could read the key, but it shouldn't exist") + } +} + +func TestTempDir(t *testing.T) { + opts := Options{ + BasePath: "test-data", + TempDir: "test-data-temp", + CacheSizeMax: 1024, + } + d := New(opts) + defer d.EraseAll() + + k, v := "a", []byte{'b'} + if err := d.Write(k, v); err != nil { + t.Fatalf("write: %s", err) + } + if readVal, err := d.Read(k); err != nil { + t.Fatalf("read: %s", err) + } else if bytes.Compare(v, readVal) != 0 { + t.Fatalf("read: expected %s, got %s", v, readVal) + } + if err := d.Erase(k); err != nil { + t.Fatalf("erase: %s", err) + } +} + +type CrashingReader struct{} + +func (CrashingReader) Read(p []byte) (n int, err error) { + panic("System has crashed while reading the stream") +} + +func TestAtomicWrite(t *testing.T) { + opts := Options{ + BasePath: "test-data", + // Test would fail if TempDir is not set here. + TempDir: "test-data-temp", + CacheSizeMax: 1024, + } + d := New(opts) + defer d.EraseAll() + + key := "key" + func() { + defer func() { + recover() // Ignore panicking error + }() + + stream := CrashingReader{} + d.WriteStream(key, stream, false) + }() + + if d.Has(key) { + t.Fatal("Has key, but it shouldn't exist") + } + if _, ok := <-d.Keys(nil); ok { + t.Fatal("Store isn't empty") + } +} diff --git a/vendor/github.com/peterbourgon/diskv/compression.go b/vendor/github.com/peterbourgon/diskv/compression.go new file mode 100644 index 000000000..5192b0273 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/compression.go @@ -0,0 +1,64 @@ +package diskv + +import ( + "compress/flate" + "compress/gzip" + "compress/zlib" + "io" +) + +// Compression is an interface that Diskv uses to implement compression of +// data. Writer takes a destination io.Writer and returns a WriteCloser that +// compresses all data written through it. Reader takes a source io.Reader and +// returns a ReadCloser that decompresses all data read through it. You may +// define these methods on your own type, or use one of the NewCompression +// helpers. +type Compression interface { + Writer(dst io.Writer) (io.WriteCloser, error) + Reader(src io.Reader) (io.ReadCloser, error) +} + +// NewGzipCompression returns a Gzip-based Compression. +func NewGzipCompression() Compression { + return NewGzipCompressionLevel(flate.DefaultCompression) +} + +// NewGzipCompressionLevel returns a Gzip-based Compression with the given level. +func NewGzipCompressionLevel(level int) Compression { + return &genericCompression{ + wf: func(w io.Writer) (io.WriteCloser, error) { return gzip.NewWriterLevel(w, level) }, + rf: func(r io.Reader) (io.ReadCloser, error) { return gzip.NewReader(r) }, + } +} + +// NewZlibCompression returns a Zlib-based Compression. +func NewZlibCompression() Compression { + return NewZlibCompressionLevel(flate.DefaultCompression) +} + +// NewZlibCompressionLevel returns a Zlib-based Compression with the given level. +func NewZlibCompressionLevel(level int) Compression { + return NewZlibCompressionLevelDict(level, nil) +} + +// NewZlibCompressionLevelDict returns a Zlib-based Compression with the given +// level, based on the given dictionary. +func NewZlibCompressionLevelDict(level int, dict []byte) Compression { + return &genericCompression{ + func(w io.Writer) (io.WriteCloser, error) { return zlib.NewWriterLevelDict(w, level, dict) }, + func(r io.Reader) (io.ReadCloser, error) { return zlib.NewReaderDict(r, dict) }, + } +} + +type genericCompression struct { + wf func(w io.Writer) (io.WriteCloser, error) + rf func(r io.Reader) (io.ReadCloser, error) +} + +func (g *genericCompression) Writer(dst io.Writer) (io.WriteCloser, error) { + return g.wf(dst) +} + +func (g *genericCompression) Reader(src io.Reader) (io.ReadCloser, error) { + return g.rf(src) +} diff --git a/vendor/github.com/peterbourgon/diskv/compression_test.go b/vendor/github.com/peterbourgon/diskv/compression_test.go new file mode 100644 index 000000000..2d6142037 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/compression_test.go @@ -0,0 +1,72 @@ +package diskv + +import ( + "compress/flate" + "fmt" + "math/rand" + "os" + "testing" + "time" +) + +func init() { + rand.Seed(time.Now().UnixNano()) +} + +func testCompressionWith(t *testing.T, c Compression, name string) { + d := New(Options{ + BasePath: "compression-test", + CacheSizeMax: 0, + Compression: c, + }) + defer d.EraseAll() + + sz := 4096 + val := make([]byte, sz) + for i := 0; i < sz; i++ { + val[i] = byte('a' + rand.Intn(26)) // {a-z}; should compress some + } + + key := "a" + if err := d.Write(key, val); err != nil { + t.Fatalf("write failed: %s", err) + } + + targetFile := fmt.Sprintf("%s%c%s", d.BasePath, os.PathSeparator, key) + fi, err := os.Stat(targetFile) + if err != nil { + t.Fatalf("%s: %s", targetFile, err) + } + + if fi.Size() >= int64(sz) { + t.Fatalf("%s: size=%d, expected smaller", targetFile, fi.Size()) + } + t.Logf("%s compressed %d to %d", name, sz, fi.Size()) + + readVal, err := d.Read(key) + if len(readVal) != sz { + t.Fatalf("read: expected size=%d, got size=%d", sz, len(readVal)) + } + + for i := 0; i < sz; i++ { + if readVal[i] != val[i] { + t.Fatalf("i=%d: expected %v, got %v", i, val[i], readVal[i]) + } + } +} + +func TestGzipDefault(t *testing.T) { + testCompressionWith(t, NewGzipCompression(), "gzip") +} + +func TestGzipBestCompression(t *testing.T) { + testCompressionWith(t, NewGzipCompressionLevel(flate.BestCompression), "gzip-max") +} + +func TestGzipBestSpeed(t *testing.T) { + testCompressionWith(t, NewGzipCompressionLevel(flate.BestSpeed), "gzip-min") +} + +func TestZlib(t *testing.T) { + testCompressionWith(t, NewZlibCompression(), "zlib") +} diff --git a/vendor/github.com/peterbourgon/diskv/diskv.go b/vendor/github.com/peterbourgon/diskv/diskv.go new file mode 100644 index 000000000..524dc0a6e --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/diskv.go @@ -0,0 +1,624 @@ +// Diskv (disk-vee) is a simple, persistent, key-value store. +// It stores all data flatly on the filesystem. + +package diskv + +import ( + "bytes" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "sync" + "syscall" +) + +const ( + defaultBasePath = "diskv" + defaultFilePerm os.FileMode = 0666 + defaultPathPerm os.FileMode = 0777 +) + +var ( + defaultTransform = func(s string) []string { return []string{} } + errCanceled = errors.New("canceled") + errEmptyKey = errors.New("empty key") + errBadKey = errors.New("bad key") + errImportDirectory = errors.New("can't import a directory") +) + +// TransformFunction transforms a key into a slice of strings, with each +// element in the slice representing a directory in the file path where the +// key's entry will eventually be stored. +// +// For example, if TransformFunc transforms "abcdef" to ["ab", "cde", "f"], +// the final location of the data file will be /ab/cde/f/abcdef +type TransformFunction func(s string) []string + +// Options define a set of properties that dictate Diskv behavior. +// All values are optional. +type Options struct { + BasePath string + Transform TransformFunction + CacheSizeMax uint64 // bytes + PathPerm os.FileMode + FilePerm os.FileMode + // If TempDir is set, it will enable filesystem atomic writes by + // writing temporary files to that location before being moved + // to BasePath. + // Note that TempDir MUST be on the same device/partition as + // BasePath. + TempDir string + + Index Index + IndexLess LessFunction + + Compression Compression +} + +// Diskv implements the Diskv interface. You shouldn't construct Diskv +// structures directly; instead, use the New constructor. +type Diskv struct { + Options + mu sync.RWMutex + cache map[string][]byte + cacheSize uint64 +} + +// New returns an initialized Diskv structure, ready to use. +// If the path identified by baseDir already contains data, +// it will be accessible, but not yet cached. +func New(o Options) *Diskv { + if o.BasePath == "" { + o.BasePath = defaultBasePath + } + if o.Transform == nil { + o.Transform = defaultTransform + } + if o.PathPerm == 0 { + o.PathPerm = defaultPathPerm + } + if o.FilePerm == 0 { + o.FilePerm = defaultFilePerm + } + + d := &Diskv{ + Options: o, + cache: map[string][]byte{}, + cacheSize: 0, + } + + if d.Index != nil && d.IndexLess != nil { + d.Index.Initialize(d.IndexLess, d.Keys(nil)) + } + + return d +} + +// Write synchronously writes the key-value pair to disk, making it immediately +// available for reads. Write relies on the filesystem to perform an eventual +// sync to physical media. If you need stronger guarantees, see WriteStream. +func (d *Diskv) Write(key string, val []byte) error { + return d.WriteStream(key, bytes.NewBuffer(val), false) +} + +// WriteStream writes the data represented by the io.Reader to the disk, under +// the provided key. If sync is true, WriteStream performs an explicit sync on +// the file as soon as it's written. +// +// bytes.Buffer provides io.Reader semantics for basic data types. +func (d *Diskv) WriteStream(key string, r io.Reader, sync bool) error { + if len(key) <= 0 { + return errEmptyKey + } + + d.mu.Lock() + defer d.mu.Unlock() + + return d.writeStreamWithLock(key, r, sync) +} + +// createKeyFileWithLock either creates the key file directly, or +// creates a temporary file in TempDir if it is set. +func (d *Diskv) createKeyFileWithLock(key string) (*os.File, error) { + if d.TempDir != "" { + if err := os.MkdirAll(d.TempDir, d.PathPerm); err != nil { + return nil, fmt.Errorf("temp mkdir: %s", err) + } + f, err := ioutil.TempFile(d.TempDir, "") + if err != nil { + return nil, fmt.Errorf("temp file: %s", err) + } + + if err := f.Chmod(d.FilePerm); err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return nil, fmt.Errorf("chmod: %s", err) + } + return f, nil + } + + mode := os.O_WRONLY | os.O_CREATE | os.O_TRUNC // overwrite if exists + f, err := os.OpenFile(d.completeFilename(key), mode, d.FilePerm) + if err != nil { + return nil, fmt.Errorf("open file: %s", err) + } + return f, nil +} + +// writeStream does no input validation checking. +func (d *Diskv) writeStreamWithLock(key string, r io.Reader, sync bool) error { + if err := d.ensurePathWithLock(key); err != nil { + return fmt.Errorf("ensure path: %s", err) + } + + f, err := d.createKeyFileWithLock(key) + if err != nil { + return fmt.Errorf("create key file: %s", err) + } + + wc := io.WriteCloser(&nopWriteCloser{f}) + if d.Compression != nil { + wc, err = d.Compression.Writer(f) + if err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("compression writer: %s", err) + } + } + + if _, err := io.Copy(wc, r); err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("i/o copy: %s", err) + } + + if err := wc.Close(); err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("compression close: %s", err) + } + + if sync { + if err := f.Sync(); err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("file sync: %s", err) + } + } + + if err := f.Close(); err != nil { + return fmt.Errorf("file close: %s", err) + } + + if f.Name() != d.completeFilename(key) { + if err := os.Rename(f.Name(), d.completeFilename(key)); err != nil { + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("rename: %s", err) + } + } + + if d.Index != nil { + d.Index.Insert(key) + } + + d.bustCacheWithLock(key) // cache only on read + + return nil +} + +// Import imports the source file into diskv under the destination key. If the +// destination key already exists, it's overwritten. If move is true, the +// source file is removed after a successful import. +func (d *Diskv) Import(srcFilename, dstKey string, move bool) (err error) { + if dstKey == "" { + return errEmptyKey + } + + if fi, err := os.Stat(srcFilename); err != nil { + return err + } else if fi.IsDir() { + return errImportDirectory + } + + d.mu.Lock() + defer d.mu.Unlock() + + if err := d.ensurePathWithLock(dstKey); err != nil { + return fmt.Errorf("ensure path: %s", err) + } + + if move { + if err := syscall.Rename(srcFilename, d.completeFilename(dstKey)); err == nil { + d.bustCacheWithLock(dstKey) + return nil + } else if err != syscall.EXDEV { + // If it failed due to being on a different device, fall back to copying + return err + } + } + + f, err := os.Open(srcFilename) + if err != nil { + return err + } + defer f.Close() + err = d.writeStreamWithLock(dstKey, f, false) + if err == nil && move { + err = os.Remove(srcFilename) + } + return err +} + +// Read reads the key and returns the value. +// If the key is available in the cache, Read won't touch the disk. +// If the key is not in the cache, Read will have the side-effect of +// lazily caching the value. +func (d *Diskv) Read(key string) ([]byte, error) { + rc, err := d.ReadStream(key, false) + if err != nil { + return []byte{}, err + } + defer rc.Close() + return ioutil.ReadAll(rc) +} + +// ReadStream reads the key and returns the value (data) as an io.ReadCloser. +// If the value is cached from a previous read, and direct is false, +// ReadStream will use the cached value. Otherwise, it will return a handle to +// the file on disk, and cache the data on read. +// +// If direct is true, ReadStream will lazily delete any cached value for the +// key, and return a direct handle to the file on disk. +// +// If compression is enabled, ReadStream taps into the io.Reader stream prior +// to decompression, and caches the compressed data. +func (d *Diskv) ReadStream(key string, direct bool) (io.ReadCloser, error) { + d.mu.RLock() + defer d.mu.RUnlock() + + if val, ok := d.cache[key]; ok { + if !direct { + buf := bytes.NewBuffer(val) + if d.Compression != nil { + return d.Compression.Reader(buf) + } + return ioutil.NopCloser(buf), nil + } + + go func() { + d.mu.Lock() + defer d.mu.Unlock() + d.uncacheWithLock(key, uint64(len(val))) + }() + } + + return d.readWithRLock(key) +} + +// read ignores the cache, and returns an io.ReadCloser representing the +// decompressed data for the given key, streamed from the disk. Clients should +// acquire a read lock on the Diskv and check the cache themselves before +// calling read. +func (d *Diskv) readWithRLock(key string) (io.ReadCloser, error) { + filename := d.completeFilename(key) + + fi, err := os.Stat(filename) + if err != nil { + return nil, err + } + if fi.IsDir() { + return nil, os.ErrNotExist + } + + f, err := os.Open(filename) + if err != nil { + return nil, err + } + + var r io.Reader + if d.CacheSizeMax > 0 { + r = newSiphon(f, d, key) + } else { + r = &closingReader{f} + } + + var rc = io.ReadCloser(ioutil.NopCloser(r)) + if d.Compression != nil { + rc, err = d.Compression.Reader(r) + if err != nil { + return nil, err + } + } + + return rc, nil +} + +// closingReader provides a Reader that automatically closes the +// embedded ReadCloser when it reaches EOF +type closingReader struct { + rc io.ReadCloser +} + +func (cr closingReader) Read(p []byte) (int, error) { + n, err := cr.rc.Read(p) + if err == io.EOF { + if closeErr := cr.rc.Close(); closeErr != nil { + return n, closeErr // close must succeed for Read to succeed + } + } + return n, err +} + +// siphon is like a TeeReader: it copies all data read through it to an +// internal buffer, and moves that buffer to the cache at EOF. +type siphon struct { + f *os.File + d *Diskv + key string + buf *bytes.Buffer +} + +// newSiphon constructs a siphoning reader that represents the passed file. +// When a successful series of reads ends in an EOF, the siphon will write +// the buffered data to Diskv's cache under the given key. +func newSiphon(f *os.File, d *Diskv, key string) io.Reader { + return &siphon{ + f: f, + d: d, + key: key, + buf: &bytes.Buffer{}, + } +} + +// Read implements the io.Reader interface for siphon. +func (s *siphon) Read(p []byte) (int, error) { + n, err := s.f.Read(p) + + if err == nil { + return s.buf.Write(p[0:n]) // Write must succeed for Read to succeed + } + + if err == io.EOF { + s.d.cacheWithoutLock(s.key, s.buf.Bytes()) // cache may fail + if closeErr := s.f.Close(); closeErr != nil { + return n, closeErr // close must succeed for Read to succeed + } + return n, err + } + + return n, err +} + +// Erase synchronously erases the given key from the disk and the cache. +func (d *Diskv) Erase(key string) error { + d.mu.Lock() + defer d.mu.Unlock() + + d.bustCacheWithLock(key) + + // erase from index + if d.Index != nil { + d.Index.Delete(key) + } + + // erase from disk + filename := d.completeFilename(key) + if s, err := os.Stat(filename); err == nil { + if s.IsDir() { + return errBadKey + } + if err = os.Remove(filename); err != nil { + return err + } + } else { + // Return err as-is so caller can do os.IsNotExist(err). + return err + } + + // clean up and return + d.pruneDirsWithLock(key) + return nil +} + +// EraseAll will delete all of the data from the store, both in the cache and on +// the disk. Note that EraseAll doesn't distinguish diskv-related data from non- +// diskv-related data. Care should be taken to always specify a diskv base +// directory that is exclusively for diskv data. +func (d *Diskv) EraseAll() error { + d.mu.Lock() + defer d.mu.Unlock() + d.cache = make(map[string][]byte) + d.cacheSize = 0 + if d.TempDir != "" { + os.RemoveAll(d.TempDir) // errors ignored + } + return os.RemoveAll(d.BasePath) +} + +// Has returns true if the given key exists. +func (d *Diskv) Has(key string) bool { + d.mu.Lock() + defer d.mu.Unlock() + + if _, ok := d.cache[key]; ok { + return true + } + + filename := d.completeFilename(key) + s, err := os.Stat(filename) + if err != nil { + return false + } + if s.IsDir() { + return false + } + + return true +} + +// Keys returns a channel that will yield every key accessible by the store, +// in undefined order. If a cancel channel is provided, closing it will +// terminate and close the keys channel. +func (d *Diskv) Keys(cancel <-chan struct{}) <-chan string { + return d.KeysPrefix("", cancel) +} + +// KeysPrefix returns a channel that will yield every key accessible by the +// store with the given prefix, in undefined order. If a cancel channel is +// provided, closing it will terminate and close the keys channel. If the +// provided prefix is the empty string, all keys will be yielded. +func (d *Diskv) KeysPrefix(prefix string, cancel <-chan struct{}) <-chan string { + var prepath string + if prefix == "" { + prepath = d.BasePath + } else { + prepath = d.pathFor(prefix) + } + c := make(chan string) + go func() { + filepath.Walk(prepath, walker(c, prefix, cancel)) + close(c) + }() + return c +} + +// walker returns a function which satisfies the filepath.WalkFunc interface. +// It sends every non-directory file entry down the channel c. +func walker(c chan<- string, prefix string, cancel <-chan struct{}) filepath.WalkFunc { + return func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() || !strings.HasPrefix(info.Name(), prefix) { + return nil // "pass" + } + + select { + case c <- info.Name(): + case <-cancel: + return errCanceled + } + + return nil + } +} + +// pathFor returns the absolute path for location on the filesystem where the +// data for the given key will be stored. +func (d *Diskv) pathFor(key string) string { + return filepath.Join(d.BasePath, filepath.Join(d.Transform(key)...)) +} + +// ensurePathWithLock is a helper function that generates all necessary +// directories on the filesystem for the given key. +func (d *Diskv) ensurePathWithLock(key string) error { + return os.MkdirAll(d.pathFor(key), d.PathPerm) +} + +// completeFilename returns the absolute path to the file for the given key. +func (d *Diskv) completeFilename(key string) string { + return filepath.Join(d.pathFor(key), key) +} + +// cacheWithLock attempts to cache the given key-value pair in the store's +// cache. It can fail if the value is larger than the cache's maximum size. +func (d *Diskv) cacheWithLock(key string, val []byte) error { + valueSize := uint64(len(val)) + if err := d.ensureCacheSpaceWithLock(valueSize); err != nil { + return fmt.Errorf("%s; not caching", err) + } + + // be very strict about memory guarantees + if (d.cacheSize + valueSize) > d.CacheSizeMax { + panic(fmt.Sprintf("failed to make room for value (%d/%d)", valueSize, d.CacheSizeMax)) + } + + d.cache[key] = val + d.cacheSize += valueSize + return nil +} + +// cacheWithoutLock acquires the store's (write) mutex and calls cacheWithLock. +func (d *Diskv) cacheWithoutLock(key string, val []byte) error { + d.mu.Lock() + defer d.mu.Unlock() + return d.cacheWithLock(key, val) +} + +func (d *Diskv) bustCacheWithLock(key string) { + if val, ok := d.cache[key]; ok { + d.uncacheWithLock(key, uint64(len(val))) + } +} + +func (d *Diskv) uncacheWithLock(key string, sz uint64) { + d.cacheSize -= sz + delete(d.cache, key) +} + +// pruneDirsWithLock deletes empty directories in the path walk leading to the +// key k. Typically this function is called after an Erase is made. +func (d *Diskv) pruneDirsWithLock(key string) error { + pathlist := d.Transform(key) + for i := range pathlist { + dir := filepath.Join(d.BasePath, filepath.Join(pathlist[:len(pathlist)-i]...)) + + // thanks to Steven Blenkinsop for this snippet + switch fi, err := os.Stat(dir); true { + case err != nil: + return err + case !fi.IsDir(): + panic(fmt.Sprintf("corrupt dirstate at %s", dir)) + } + + nlinks, err := filepath.Glob(filepath.Join(dir, "*")) + if err != nil { + return err + } else if len(nlinks) > 0 { + return nil // has subdirs -- do not prune + } + if err = os.Remove(dir); err != nil { + return err + } + } + + return nil +} + +// ensureCacheSpaceWithLock deletes entries from the cache in arbitrary order +// until the cache has at least valueSize bytes available. +func (d *Diskv) ensureCacheSpaceWithLock(valueSize uint64) error { + if valueSize > d.CacheSizeMax { + return fmt.Errorf("value size (%d bytes) too large for cache (%d bytes)", valueSize, d.CacheSizeMax) + } + + safe := func() bool { return (d.cacheSize + valueSize) <= d.CacheSizeMax } + + for key, val := range d.cache { + if safe() { + break + } + + d.uncacheWithLock(key, uint64(len(val))) + } + + if !safe() { + panic(fmt.Sprintf("%d bytes still won't fit in the cache! (max %d bytes)", valueSize, d.CacheSizeMax)) + } + + return nil +} + +// nopWriteCloser wraps an io.Writer and provides a no-op Close method to +// satisfy the io.WriteCloser interface. +type nopWriteCloser struct { + io.Writer +} + +func (wc *nopWriteCloser) Write(p []byte) (int, error) { return wc.Writer.Write(p) } +func (wc *nopWriteCloser) Close() error { return nil } diff --git a/vendor/github.com/peterbourgon/diskv/examples/content-addressable-store/cas.go b/vendor/github.com/peterbourgon/diskv/examples/content-addressable-store/cas.go new file mode 100644 index 000000000..a3abaaf77 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/examples/content-addressable-store/cas.go @@ -0,0 +1,63 @@ +package main + +import ( + "crypto/md5" + "fmt" + "io" + + "github.com/peterbourgon/diskv" +) + +const transformBlockSize = 2 // grouping of chars per directory depth + +func blockTransform(s string) []string { + var ( + sliceSize = len(s) / transformBlockSize + pathSlice = make([]string, sliceSize) + ) + for i := 0; i < sliceSize; i++ { + from, to := i*transformBlockSize, (i*transformBlockSize)+transformBlockSize + pathSlice[i] = s[from:to] + } + return pathSlice +} + +func main() { + d := diskv.New(diskv.Options{ + BasePath: "data", + Transform: blockTransform, + CacheSizeMax: 1024 * 1024, // 1MB + }) + + for _, valueStr := range []string{ + "I am the very model of a modern Major-General", + "I've information vegetable, animal, and mineral", + "I know the kings of England, and I quote the fights historical", + "From Marathon to Waterloo, in order categorical", + "I'm very well acquainted, too, with matters mathematical", + "I understand equations, both the simple and quadratical", + "About binomial theorem I'm teeming with a lot o' news", + "With many cheerful facts about the square of the hypotenuse", + } { + d.Write(md5sum(valueStr), []byte(valueStr)) + } + + var keyCount int + for key := range d.Keys(nil) { + val, err := d.Read(key) + if err != nil { + panic(fmt.Sprintf("key %s had no value", key)) + } + fmt.Printf("%s: %s\n", key, val) + keyCount++ + } + fmt.Printf("%d total keys\n", keyCount) + + // d.EraseAll() // leave it commented out to see how data is kept on disk +} + +func md5sum(s string) string { + h := md5.New() + io.WriteString(h, s) + return fmt.Sprintf("%x", h.Sum(nil)) +} diff --git a/vendor/github.com/peterbourgon/diskv/examples/super-simple-store/super-simple-store.go b/vendor/github.com/peterbourgon/diskv/examples/super-simple-store/super-simple-store.go new file mode 100644 index 000000000..b5da11d64 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/examples/super-simple-store/super-simple-store.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + + "github.com/peterbourgon/diskv" +) + +func main() { + d := diskv.New(diskv.Options{ + BasePath: "my-diskv-data-directory", + Transform: func(s string) []string { return []string{} }, + CacheSizeMax: 1024 * 1024, // 1MB + }) + + key := "alpha" + if err := d.Write(key, []byte{'1', '2', '3'}); err != nil { + panic(err) + } + + value, err := d.Read(key) + if err != nil { + panic(err) + } + fmt.Printf("%v\n", value) + + if err := d.Erase(key); err != nil { + panic(err) + } +} diff --git a/vendor/github.com/peterbourgon/diskv/import_test.go b/vendor/github.com/peterbourgon/diskv/import_test.go new file mode 100644 index 000000000..a08ac7c70 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/import_test.go @@ -0,0 +1,76 @@ +package diskv_test + +import ( + "bytes" + "io/ioutil" + "os" + + "github.com/peterbourgon/diskv" + + "testing" +) + +func TestImportMove(t *testing.T) { + b := []byte(`0123456789`) + f, err := ioutil.TempFile("", "temp-test") + if err != nil { + t.Fatal(err) + } + if _, err := f.Write(b); err != nil { + t.Fatal(err) + } + f.Close() + + d := diskv.New(diskv.Options{ + BasePath: "test-import-move", + }) + defer d.EraseAll() + + key := "key" + + if err := d.Write(key, []byte(`TBD`)); err != nil { + t.Fatal(err) + } + + if err := d.Import(f.Name(), key, true); err != nil { + t.Fatal(err) + } + + if _, err := os.Stat(f.Name()); err == nil || !os.IsNotExist(err) { + t.Errorf("expected temp file to be gone, but err = %v", err) + } + + if !d.Has(key) { + t.Errorf("%q not present", key) + } + + if buf, err := d.Read(key); err != nil || bytes.Compare(b, buf) != 0 { + t.Errorf("want %q, have %q (err = %v)", string(b), string(buf), err) + } +} + +func TestImportCopy(t *testing.T) { + b := []byte(`¡åéîòü!`) + + f, err := ioutil.TempFile("", "temp-test") + if err != nil { + t.Fatal(err) + } + if _, err := f.Write(b); err != nil { + t.Fatal(err) + } + f.Close() + + d := diskv.New(diskv.Options{ + BasePath: "test-import-copy", + }) + defer d.EraseAll() + + if err := d.Import(f.Name(), "key", false); err != nil { + t.Fatal(err) + } + + if _, err := os.Stat(f.Name()); err != nil { + t.Errorf("expected temp file to remain, but got err = %v", err) + } +} diff --git a/vendor/github.com/peterbourgon/diskv/index.go b/vendor/github.com/peterbourgon/diskv/index.go new file mode 100644 index 000000000..96fee5152 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/index.go @@ -0,0 +1,115 @@ +package diskv + +import ( + "sync" + + "github.com/google/btree" +) + +// Index is a generic interface for things that can +// provide an ordered list of keys. +type Index interface { + Initialize(less LessFunction, keys <-chan string) + Insert(key string) + Delete(key string) + Keys(from string, n int) []string +} + +// LessFunction is used to initialize an Index of keys in a specific order. +type LessFunction func(string, string) bool + +// btreeString is a custom data type that satisfies the BTree Less interface, +// making the strings it wraps sortable by the BTree package. +type btreeString struct { + s string + l LessFunction +} + +// Less satisfies the BTree.Less interface using the btreeString's LessFunction. +func (s btreeString) Less(i btree.Item) bool { + return s.l(s.s, i.(btreeString).s) +} + +// BTreeIndex is an implementation of the Index interface using google/btree. +type BTreeIndex struct { + sync.RWMutex + LessFunction + *btree.BTree +} + +// Initialize populates the BTree tree with data from the keys channel, +// according to the passed less function. It's destructive to the BTreeIndex. +func (i *BTreeIndex) Initialize(less LessFunction, keys <-chan string) { + i.Lock() + defer i.Unlock() + i.LessFunction = less + i.BTree = rebuild(less, keys) +} + +// Insert inserts the given key (only) into the BTree tree. +func (i *BTreeIndex) Insert(key string) { + i.Lock() + defer i.Unlock() + if i.BTree == nil || i.LessFunction == nil { + panic("uninitialized index") + } + i.BTree.ReplaceOrInsert(btreeString{s: key, l: i.LessFunction}) +} + +// Delete removes the given key (only) from the BTree tree. +func (i *BTreeIndex) Delete(key string) { + i.Lock() + defer i.Unlock() + if i.BTree == nil || i.LessFunction == nil { + panic("uninitialized index") + } + i.BTree.Delete(btreeString{s: key, l: i.LessFunction}) +} + +// Keys yields a maximum of n keys in order. If the passed 'from' key is empty, +// Keys will return the first n keys. If the passed 'from' key is non-empty, the +// first key in the returned slice will be the key that immediately follows the +// passed key, in key order. +func (i *BTreeIndex) Keys(from string, n int) []string { + i.RLock() + defer i.RUnlock() + + if i.BTree == nil || i.LessFunction == nil { + panic("uninitialized index") + } + + if i.BTree.Len() <= 0 { + return []string{} + } + + btreeFrom := btreeString{s: from, l: i.LessFunction} + skipFirst := true + if len(from) <= 0 || !i.BTree.Has(btreeFrom) { + // no such key, so fabricate an always-smallest item + btreeFrom = btreeString{s: "", l: func(string, string) bool { return true }} + skipFirst = false + } + + keys := []string{} + iterator := func(i btree.Item) bool { + keys = append(keys, i.(btreeString).s) + return len(keys) < n + } + i.BTree.AscendGreaterOrEqual(btreeFrom, iterator) + + if skipFirst && len(keys) > 0 { + keys = keys[1:] + } + + return keys +} + +// rebuildIndex does the work of regenerating the index +// with the given keys. +func rebuild(less LessFunction, keys <-chan string) *btree.BTree { + tree := btree.New(2) + for key := range keys { + tree.ReplaceOrInsert(btreeString{s: key, l: less}) + } + return tree +} diff --git a/vendor/github.com/peterbourgon/diskv/index_test.go b/vendor/github.com/peterbourgon/diskv/index_test.go new file mode 100644 index 000000000..72f52a9ff --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/index_test.go @@ -0,0 +1,148 @@ +package diskv + +import ( + "bytes" + "reflect" + "testing" + "time" +) + +func strLess(a, b string) bool { return a < b } + +func cmpStrings(a, b []string) bool { + if len(a) != len(b) { + return false + } + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false + } + } + return true +} + +func (d *Diskv) isIndexed(key string) bool { + if d.Index == nil { + return false + } + + for _, got := range d.Index.Keys("", 1000) { + if got == key { + return true + } + } + return false +} + +func TestIndexOrder(t *testing.T) { + d := New(Options{ + BasePath: "index-test", + Transform: func(string) []string { return []string{} }, + CacheSizeMax: 1024, + Index: &BTreeIndex{}, + IndexLess: strLess, + }) + defer d.EraseAll() + + v := []byte{'1', '2', '3'} + d.Write("a", v) + if !d.isIndexed("a") { + t.Fatalf("'a' not indexed after write") + } + d.Write("1", v) + d.Write("m", v) + d.Write("-", v) + d.Write("A", v) + + expectedKeys := []string{"-", "1", "A", "a", "m"} + keys := []string{} + for _, key := range d.Index.Keys("", 100) { + keys = append(keys, key) + } + + if !cmpStrings(keys, expectedKeys) { + t.Fatalf("got %s, expected %s", keys, expectedKeys) + } +} + +func TestIndexLoad(t *testing.T) { + d1 := New(Options{ + BasePath: "index-test", + Transform: func(string) []string { return []string{} }, + CacheSizeMax: 1024, + }) + defer d1.EraseAll() + + val := []byte{'1', '2', '3'} + keys := []string{"a", "b", "c", "d", "e", "f", "g"} + for _, key := range keys { + d1.Write(key, val) + } + + d2 := New(Options{ + BasePath: "index-test", + Transform: func(string) []string { return []string{} }, + CacheSizeMax: 1024, + Index: &BTreeIndex{}, + IndexLess: strLess, + }) + defer d2.EraseAll() + + // check d2 has properly loaded existing d1 data + for _, key := range keys { + if !d2.isIndexed(key) { + t.Fatalf("key '%s' not indexed on secondary", key) + } + } + + // cache one + if readValue, err := d2.Read(keys[0]); err != nil { + t.Fatalf("%s", err) + } else if bytes.Compare(val, readValue) != 0 { + t.Fatalf("%s: got %s, expected %s", keys[0], readValue, val) + } + + // make sure it got cached + for i := 0; i < 10 && !d2.isCached(keys[0]); i++ { + time.Sleep(10 * time.Millisecond) + } + if !d2.isCached(keys[0]) { + t.Fatalf("key '%s' not cached", keys[0]) + } + + // kill the disk + d1.EraseAll() + + // cached value should still be there in the second + if readValue, err := d2.Read(keys[0]); err != nil { + t.Fatalf("%s", err) + } else if bytes.Compare(val, readValue) != 0 { + t.Fatalf("%s: got %s, expected %s", keys[0], readValue, val) + } + + // but not in the original + if _, err := d1.Read(keys[0]); err == nil { + t.Fatalf("expected error reading from flushed store") + } +} + +func TestIndexKeysEmptyFrom(t *testing.T) { + d := New(Options{ + BasePath: "index-test", + Transform: func(string) []string { return []string{} }, + CacheSizeMax: 1024, + Index: &BTreeIndex{}, + IndexLess: strLess, + }) + defer d.EraseAll() + + for _, k := range []string{"a", "c", "z", "b", "x", "b", "y"} { + d.Write(k, []byte("1")) + } + + want := []string{"a", "b", "c", "x", "y", "z"} + have := d.Index.Keys("", 99) + if !reflect.DeepEqual(want, have) { + t.Errorf("want %v, have %v", want, have) + } +} diff --git a/vendor/github.com/peterbourgon/diskv/issues_test.go b/vendor/github.com/peterbourgon/diskv/issues_test.go new file mode 100644 index 000000000..0b0b10908 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/issues_test.go @@ -0,0 +1,121 @@ +package diskv + +import ( + "bytes" + "io/ioutil" + "sync" + "testing" + "time" +) + +// ReadStream from cache shouldn't panic on a nil dereference from a nonexistent +// Compression :) +func TestIssue2A(t *testing.T) { + d := New(Options{ + BasePath: "test-issue-2a", + Transform: func(string) []string { return []string{} }, + CacheSizeMax: 1024, + }) + defer d.EraseAll() + + input := "abcdefghijklmnopqrstuvwxy" + key, writeBuf, sync := "a", bytes.NewBufferString(input), false + if err := d.WriteStream(key, writeBuf, sync); err != nil { + t.Fatal(err) + } + + for i := 0; i < 2; i++ { + began := time.Now() + rc, err := d.ReadStream(key, false) + if err != nil { + t.Fatal(err) + } + buf, err := ioutil.ReadAll(rc) + if err != nil { + t.Fatal(err) + } + if !cmpBytes(buf, []byte(input)) { + t.Fatalf("read #%d: '%s' != '%s'", i+1, string(buf), input) + } + rc.Close() + t.Logf("read #%d in %s", i+1, time.Since(began)) + } +} + +// ReadStream on a key that resolves to a directory should return an error. +func TestIssue2B(t *testing.T) { + blockTransform := func(s string) []string { + transformBlockSize := 3 + sliceSize := len(s) / transformBlockSize + pathSlice := make([]string, sliceSize) + for i := 0; i < sliceSize; i++ { + from, to := i*transformBlockSize, (i*transformBlockSize)+transformBlockSize + pathSlice[i] = s[from:to] + } + return pathSlice + } + + d := New(Options{ + BasePath: "test-issue-2b", + Transform: blockTransform, + CacheSizeMax: 0, + }) + defer d.EraseAll() + + v := []byte{'1', '2', '3'} + if err := d.Write("abcabc", v); err != nil { + t.Fatal(err) + } + + _, err := d.ReadStream("abc", false) + if err == nil { + t.Fatal("ReadStream('abc') should return error") + } + t.Logf("ReadStream('abc') returned error: %v", err) +} + +// Ensure ReadStream with direct=true isn't racy. +func TestIssue17(t *testing.T) { + var ( + basePath = "test-data" + ) + + dWrite := New(Options{ + BasePath: basePath, + CacheSizeMax: 0, + }) + defer dWrite.EraseAll() + + dRead := New(Options{ + BasePath: basePath, + CacheSizeMax: 50, + }) + + cases := map[string]string{ + "a": `1234567890`, + "b": `2345678901`, + "c": `3456789012`, + "d": `4567890123`, + "e": `5678901234`, + } + + for k, v := range cases { + if err := dWrite.Write(k, []byte(v)); err != nil { + t.Fatalf("during write: %s", err) + } + dRead.Read(k) // ensure it's added to cache + } + + var wg sync.WaitGroup + start := make(chan struct{}) + for k, v := range cases { + wg.Add(1) + go func(k, v string) { + <-start + dRead.ReadStream(k, true) + wg.Done() + }(k, v) + } + close(start) + wg.Wait() +} diff --git a/vendor/github.com/peterbourgon/diskv/keys_test.go b/vendor/github.com/peterbourgon/diskv/keys_test.go new file mode 100644 index 000000000..222e1c444 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/keys_test.go @@ -0,0 +1,231 @@ +package diskv_test + +import ( + "reflect" + "runtime" + "strings" + "testing" + + "github.com/peterbourgon/diskv" +) + +var ( + keysTestData = map[string]string{ + "ab01cd01": "When we started building CoreOS", + "ab01cd02": "we looked at all the various components available to us", + "ab01cd03": "re-using the best tools", + "ef01gh04": "and building the ones that did not exist", + "ef02gh05": "We believe strongly in the Unix philosophy", + "xxxxxxxx": "tools should be independently useful", + } + + prefixes = []string{ + "", // all + "a", + "ab", + "ab0", + "ab01", + "ab01cd0", + "ab01cd01", + "ab01cd01x", // none + "b", // none + "b0", // none + "0", // none + "01", // none + "e", + "ef", + "efx", // none + "ef01gh0", + "ef01gh04", + "ef01gh05", + "ef01gh06", // none + } +) + +func TestKeysFlat(t *testing.T) { + transform := func(s string) []string { + if s == "" { + t.Fatalf(`transform should not be called with ""`) + } + return []string{} + } + d := diskv.New(diskv.Options{ + BasePath: "test-data", + Transform: transform, + }) + defer d.EraseAll() + + for k, v := range keysTestData { + d.Write(k, []byte(v)) + } + + checkKeys(t, d.Keys(nil), keysTestData) +} + +func TestKeysNested(t *testing.T) { + d := diskv.New(diskv.Options{ + BasePath: "test-data", + Transform: blockTransform(2), + }) + defer d.EraseAll() + + for k, v := range keysTestData { + d.Write(k, []byte(v)) + } + + checkKeys(t, d.Keys(nil), keysTestData) +} + +func TestKeysPrefixFlat(t *testing.T) { + d := diskv.New(diskv.Options{ + BasePath: "test-data", + }) + defer d.EraseAll() + + for k, v := range keysTestData { + d.Write(k, []byte(v)) + } + + for _, prefix := range prefixes { + checkKeys(t, d.KeysPrefix(prefix, nil), filterPrefix(keysTestData, prefix)) + } +} + +func TestKeysPrefixNested(t *testing.T) { + d := diskv.New(diskv.Options{ + BasePath: "test-data", + Transform: blockTransform(2), + }) + defer d.EraseAll() + + for k, v := range keysTestData { + d.Write(k, []byte(v)) + } + + for _, prefix := range prefixes { + checkKeys(t, d.KeysPrefix(prefix, nil), filterPrefix(keysTestData, prefix)) + } +} + +func TestKeysCancel(t *testing.T) { + d := diskv.New(diskv.Options{ + BasePath: "test-data", + }) + defer d.EraseAll() + + for k, v := range keysTestData { + d.Write(k, []byte(v)) + } + + var ( + cancel = make(chan struct{}) + received = 0 + cancelAfter = len(keysTestData) / 2 + ) + + for key := range d.Keys(cancel) { + received++ + + if received >= cancelAfter { + close(cancel) + runtime.Gosched() // allow walker to detect cancel + } + + t.Logf("received %d: %q", received, key) + } + + if want, have := cancelAfter, received; want != have { + t.Errorf("want %d, have %d") + } +} + +func checkKeys(t *testing.T, c <-chan string, want map[string]string) { + for k := range c { + if _, ok := want[k]; !ok { + t.Errorf("%q yielded but not expected", k) + continue + } + + delete(want, k) + t.Logf("%q yielded OK", k) + } + + if len(want) != 0 { + t.Errorf("%d expected key(s) not yielded: %s", len(want), strings.Join(flattenKeys(want), ", ")) + } +} + +func blockTransform(blockSize int) func(string) []string { + return func(s string) []string { + var ( + sliceSize = len(s) / blockSize + pathSlice = make([]string, sliceSize) + ) + for i := 0; i < sliceSize; i++ { + from, to := i*blockSize, (i*blockSize)+blockSize + pathSlice[i] = s[from:to] + } + return pathSlice + } +} + +func filterPrefix(in map[string]string, prefix string) map[string]string { + out := map[string]string{} + for k, v := range in { + if strings.HasPrefix(k, prefix) { + out[k] = v + } + } + return out +} + +func TestFilterPrefix(t *testing.T) { + input := map[string]string{ + "all": "", + "and": "", + "at": "", + "available": "", + "best": "", + "building": "", + "components": "", + "coreos": "", + "did": "", + "exist": "", + "looked": "", + "not": "", + "ones": "", + "re-using": "", + "started": "", + "that": "", + "the": "", + "to": "", + "tools": "", + "us": "", + "various": "", + "we": "", + "when": "", + } + + for prefix, want := range map[string]map[string]string{ + "a": map[string]string{"all": "", "and": "", "at": "", "available": ""}, + "al": map[string]string{"all": ""}, + "all": map[string]string{"all": ""}, + "alll": map[string]string{}, + "c": map[string]string{"components": "", "coreos": ""}, + "co": map[string]string{"components": "", "coreos": ""}, + "com": map[string]string{"components": ""}, + } { + have := filterPrefix(input, prefix) + if !reflect.DeepEqual(want, have) { + t.Errorf("%q: want %v, have %v", prefix, flattenKeys(want), flattenKeys(have)) + } + } +} + +func flattenKeys(m map[string]string) []string { + a := make([]string, 0, len(m)) + for k := range m { + a = append(a, k) + } + return a +} diff --git a/vendor/github.com/peterbourgon/diskv/speed_test.go b/vendor/github.com/peterbourgon/diskv/speed_test.go new file mode 100644 index 000000000..67d05ff27 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/speed_test.go @@ -0,0 +1,153 @@ +package diskv + +import ( + "fmt" + "math/rand" + "testing" +) + +func shuffle(keys []string) { + ints := rand.Perm(len(keys)) + for i := range keys { + keys[i], keys[ints[i]] = keys[ints[i]], keys[i] + } +} + +func genValue(size int) []byte { + v := make([]byte, size) + for i := 0; i < size; i++ { + v[i] = uint8((rand.Int() % 26) + 97) // a-z + } + return v +} + +const ( + keyCount = 1000 +) + +func genKeys() []string { + keys := make([]string, keyCount) + for i := 0; i < keyCount; i++ { + keys[i] = fmt.Sprintf("%d", i) + } + return keys +} + +func (d *Diskv) load(keys []string, val []byte) { + for _, key := range keys { + d.Write(key, val) + } +} + +func benchRead(b *testing.B, size, cachesz int) { + b.StopTimer() + d := New(Options{ + BasePath: "speed-test", + Transform: func(string) []string { return []string{} }, + CacheSizeMax: uint64(cachesz), + }) + defer d.EraseAll() + + keys := genKeys() + value := genValue(size) + d.load(keys, value) + shuffle(keys) + b.SetBytes(int64(size)) + + b.StartTimer() + for i := 0; i < b.N; i++ { + _, _ = d.Read(keys[i%len(keys)]) + } + b.StopTimer() +} + +func benchWrite(b *testing.B, size int, withIndex bool) { + b.StopTimer() + + options := Options{ + BasePath: "speed-test", + Transform: func(string) []string { return []string{} }, + CacheSizeMax: 0, + } + if withIndex { + options.Index = &BTreeIndex{} + options.IndexLess = strLess + } + + d := New(options) + defer d.EraseAll() + keys := genKeys() + value := genValue(size) + shuffle(keys) + b.SetBytes(int64(size)) + + b.StartTimer() + for i := 0; i < b.N; i++ { + d.Write(keys[i%len(keys)], value) + } + b.StopTimer() +} + +func BenchmarkWrite__32B_NoIndex(b *testing.B) { + benchWrite(b, 32, false) +} + +func BenchmarkWrite__1KB_NoIndex(b *testing.B) { + benchWrite(b, 1024, false) +} + +func BenchmarkWrite__4KB_NoIndex(b *testing.B) { + benchWrite(b, 4096, false) +} + +func BenchmarkWrite_10KB_NoIndex(b *testing.B) { + benchWrite(b, 10240, false) +} + +func BenchmarkWrite__32B_WithIndex(b *testing.B) { + benchWrite(b, 32, true) +} + +func BenchmarkWrite__1KB_WithIndex(b *testing.B) { + benchWrite(b, 1024, true) +} + +func BenchmarkWrite__4KB_WithIndex(b *testing.B) { + benchWrite(b, 4096, true) +} + +func BenchmarkWrite_10KB_WithIndex(b *testing.B) { + benchWrite(b, 10240, true) +} + +func BenchmarkRead__32B_NoCache(b *testing.B) { + benchRead(b, 32, 0) +} + +func BenchmarkRead__1KB_NoCache(b *testing.B) { + benchRead(b, 1024, 0) +} + +func BenchmarkRead__4KB_NoCache(b *testing.B) { + benchRead(b, 4096, 0) +} + +func BenchmarkRead_10KB_NoCache(b *testing.B) { + benchRead(b, 10240, 0) +} + +func BenchmarkRead__32B_WithCache(b *testing.B) { + benchRead(b, 32, keyCount*32*2) +} + +func BenchmarkRead__1KB_WithCache(b *testing.B) { + benchRead(b, 1024, keyCount*1024*2) +} + +func BenchmarkRead__4KB_WithCache(b *testing.B) { + benchRead(b, 4096, keyCount*4096*2) +} + +func BenchmarkRead_10KB_WithCache(b *testing.B) { + benchRead(b, 10240, keyCount*4096*2) +} diff --git a/vendor/github.com/peterbourgon/diskv/stream_test.go b/vendor/github.com/peterbourgon/diskv/stream_test.go new file mode 100644 index 000000000..7991dbff2 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/stream_test.go @@ -0,0 +1,117 @@ +package diskv + +import ( + "bytes" + "io/ioutil" + "testing" +) + +func TestBasicStreamCaching(t *testing.T) { + d := New(Options{ + BasePath: "test-data", + CacheSizeMax: 1024, + }) + defer d.EraseAll() + + input := "a1b2c3" + key, writeBuf, sync := "a", bytes.NewBufferString(input), true + if err := d.WriteStream(key, writeBuf, sync); err != nil { + t.Fatal(err) + } + + if d.isCached(key) { + t.Fatalf("'%s' cached, but shouldn't be (yet)", key) + } + + rc, err := d.ReadStream(key, false) + if err != nil { + t.Fatal(err) + } + + readBuf, err := ioutil.ReadAll(rc) + if err != nil { + t.Fatal(err) + } + + if !cmpBytes(readBuf, []byte(input)) { + t.Fatalf("'%s' != '%s'", string(readBuf), input) + } + + if !d.isCached(key) { + t.Fatalf("'%s' isn't cached, but should be", key) + } +} + +func TestReadStreamDirect(t *testing.T) { + var ( + basePath = "test-data" + ) + dWrite := New(Options{ + BasePath: basePath, + CacheSizeMax: 0, + }) + defer dWrite.EraseAll() + dRead := New(Options{ + BasePath: basePath, + CacheSizeMax: 1024, + }) + + // Write + key, val1, val2 := "a", []byte(`1234567890`), []byte(`aaaaaaaaaa`) + if err := dWrite.Write(key, val1); err != nil { + t.Fatalf("during first write: %s", err) + } + + // First, caching read. + val, err := dRead.Read(key) + if err != nil { + t.Fatalf("during initial read: %s", err) + } + t.Logf("read 1: %s => %s", key, string(val)) + if !cmpBytes(val1, val) { + t.Errorf("expected %q, got %q", string(val1), string(val)) + } + if !dRead.isCached(key) { + t.Errorf("%q should be cached, but isn't", key) + } + + // Write a different value. + if err := dWrite.Write(key, val2); err != nil { + t.Fatalf("during second write: %s", err) + } + + // Second read, should hit cache and get the old value. + val, err = dRead.Read(key) + if err != nil { + t.Fatalf("during second (cache-hit) read: %s", err) + } + t.Logf("read 2: %s => %s", key, string(val)) + if !cmpBytes(val1, val) { + t.Errorf("expected %q, got %q", string(val1), string(val)) + } + + // Third, direct read, should get the updated value. + rc, err := dRead.ReadStream(key, true) + if err != nil { + t.Fatalf("during third (direct) read, ReadStream: %s", err) + } + defer rc.Close() + val, err = ioutil.ReadAll(rc) + if err != nil { + t.Fatalf("during third (direct) read, ReadAll: %s", err) + } + t.Logf("read 3: %s => %s", key, string(val)) + if !cmpBytes(val2, val) { + t.Errorf("expected %q, got %q", string(val1), string(val)) + } + + // Fourth read, should hit cache and get the new value. + val, err = dRead.Read(key) + if err != nil { + t.Fatalf("during fourth (cache-hit) read: %s", err) + } + t.Logf("read 4: %s => %s", key, string(val)) + if !cmpBytes(val2, val) { + t.Errorf("expected %q, got %q", string(val1), string(val)) + } +} diff --git a/vendor/k8s.io/api/Godeps/Godeps.json b/vendor/k8s.io/api/Godeps/Godeps.json index 485313521..2078cdc70 100644 --- a/vendor/k8s.io/api/Godeps/Godeps.json +++ b/vendor/k8s.io/api/Godeps/Godeps.json @@ -1,11 +1,19 @@ { "ImportPath": "k8s.io/api", - "GoVersion": "go1.9", + "GoVersion": "go1.10", "GodepVersion": "v80", "Packages": [ "./..." ], "Deps": [ + { + "ImportPath": "github.com/davecgh/go-spew/spew", + "Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8" + }, + { + "ImportPath": "github.com/ghodss/yaml", + "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" + }, { "ImportPath": "github.com/gogo/protobuf/proto", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" @@ -18,10 +26,26 @@ "ImportPath": "github.com/golang/glog", "Rev": "44145f04b68cf362d9c4df2182967c2275eaefed" }, + { + "ImportPath": "github.com/golang/protobuf/proto", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, { "ImportPath": "github.com/google/gofuzz", "Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c" }, + { + "ImportPath": "github.com/json-iterator/go", + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" + }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, { "ImportPath": "github.com/spf13/pflag", "Rev": "583c0c0531f06d5278b7d917446061adc344b5cd" @@ -62,89 +86,157 @@ "ImportPath": "gopkg.in/inf.v0", "Rev": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" }, + { + "ImportPath": "gopkg.in/yaml.v2", + "Rev": "670d4cfef0544295bc27a114dbac37980d83185a" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/equality", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/meta", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, { "ImportPath": "k8s.io/apimachinery/pkg/api/resource", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/testing", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/conversion", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/fields", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/labels", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/selection", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/types", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/diff", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/errors", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/framer", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/intstr", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/json", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/net", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/runtime", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/sets", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation/field", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/wait", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/yaml", + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/watch", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" } ] } diff --git a/vendor/k8s.io/api/SECURITY_CONTACTS b/vendor/k8s.io/api/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/api/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/api/admission/v1beta1/generated.pb.go b/vendor/k8s.io/api/admission/v1beta1/generated.pb.go index f56a0f063..dc257afac 100644 --- a/vendor/k8s.io/api/admission/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/admission/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1157,52 +1157,51 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 739 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcd, 0x4e, 0xdb, 0x4a, - 0x14, 0x8e, 0x21, 0x7f, 0x9e, 0xa0, 0x0b, 0xcc, 0xdd, 0x58, 0xd1, 0x95, 0xc3, 0x65, 0x71, 0xc5, - 0x95, 0x60, 0x5c, 0x68, 0x8b, 0x50, 0xd5, 0x0d, 0x16, 0xa8, 0x42, 0x95, 0x00, 0x0d, 0xa4, 0x6a, - 0xbb, 0xa8, 0x34, 0x71, 0x86, 0x64, 0x9a, 0xd8, 0xe3, 0x7a, 0xc6, 0xa1, 0xec, 0xfa, 0x08, 0x7d, - 0x93, 0x3e, 0x44, 0x37, 0x2c, 0x59, 0xb2, 0x8a, 0x4a, 0xfa, 0x00, 0xdd, 0xb3, 0xaa, 0x3c, 0x1e, - 0xc7, 0x29, 0x34, 0x2d, 0xad, 0xba, 0xca, 0x9c, 0x73, 0xbe, 0xef, 0x3b, 0xf1, 0x77, 0xce, 0x0c, - 0xd8, 0xed, 0x6d, 0x09, 0xc4, 0xb8, 0xd3, 0x8b, 0x5b, 0x34, 0x0a, 0xa8, 0xa4, 0xc2, 0x19, 0xd0, - 0xa0, 0xcd, 0x23, 0x47, 0x17, 0x48, 0xc8, 0x1c, 0xd2, 0xf6, 0x99, 0x10, 0x8c, 0x07, 0xce, 0x60, - 0xbd, 0x45, 0x25, 0x59, 0x77, 0x3a, 0x34, 0xa0, 0x11, 0x91, 0xb4, 0x8d, 0xc2, 0x88, 0x4b, 0x0e, - 0xff, 0x49, 0xd1, 0x88, 0x84, 0x0c, 0x8d, 0xd1, 0x48, 0xa3, 0xeb, 0x6b, 0x1d, 0x26, 0xbb, 0x71, - 0x0b, 0x79, 0xdc, 0x77, 0x3a, 0xbc, 0xc3, 0x1d, 0x45, 0x6a, 0xc5, 0x27, 0x2a, 0x52, 0x81, 0x3a, - 0xa5, 0x62, 0xf5, 0xd5, 0xc9, 0xd6, 0xb1, 0xec, 0xd2, 0x40, 0x32, 0x8f, 0xc8, 0xb4, 0xff, 0xcd, - 0xd6, 0xf5, 0x07, 0x39, 0xda, 0x27, 0x5e, 0x97, 0x05, 0x34, 0x3a, 0x73, 0xc2, 0x5e, 0x27, 0x49, - 0x08, 0xc7, 0xa7, 0x92, 0x7c, 0x8f, 0xe5, 0x4c, 0x63, 0x45, 0x71, 0x20, 0x99, 0x4f, 0x6f, 0x11, - 0x36, 0x7f, 0x46, 0x10, 0x5e, 0x97, 0xfa, 0xe4, 0x16, 0xef, 0xfe, 0x34, 0x5e, 0x2c, 0x59, 0xdf, - 0x61, 0x81, 0x14, 0x32, 0xba, 0x49, 0x5a, 0xfe, 0x52, 0x02, 0x0b, 0xdb, 0x99, 0x8d, 0x98, 0xbe, - 0x89, 0xa9, 0x90, 0xd0, 0x05, 0xb3, 0x31, 0x6b, 0x5b, 0xc6, 0x92, 0xb1, 0x62, 0xba, 0xf7, 0xce, - 0x87, 0x8d, 0xc2, 0x68, 0xd8, 0x98, 0x6d, 0xee, 0xed, 0x5c, 0x0f, 0x1b, 0xff, 0x4e, 0xeb, 0x22, - 0xcf, 0x42, 0x2a, 0x50, 0x73, 0x6f, 0x07, 0x27, 0x64, 0xf8, 0x1c, 0x14, 0x7b, 0x2c, 0x68, 0x5b, - 0x33, 0x4b, 0xc6, 0x4a, 0x6d, 0x63, 0x13, 0xe5, 0x63, 0x1b, 0xd3, 0x50, 0xd8, 0xeb, 0x24, 0x09, - 0x81, 0x12, 0xef, 0xd0, 0x60, 0x1d, 0x3d, 0x89, 0x78, 0x1c, 0x3e, 0xa3, 0x51, 0xf2, 0x67, 0x9e, - 0xb2, 0xa0, 0xed, 0xce, 0xe9, 0xe6, 0xc5, 0x24, 0xc2, 0x4a, 0x11, 0x76, 0x41, 0x35, 0xa2, 0x82, - 0xc7, 0x91, 0x47, 0xad, 0x59, 0xa5, 0xfe, 0xe8, 0xd7, 0xd5, 0xb1, 0x56, 0x70, 0x17, 0x74, 0x87, - 0x6a, 0x96, 0xc1, 0x63, 0x75, 0xf8, 0x10, 0xd4, 0x44, 0xdc, 0xca, 0x0a, 0x56, 0x51, 0xf9, 0xf1, - 0xb7, 0x26, 0xd4, 0x8e, 0xf2, 0x12, 0x9e, 0xc4, 0xc1, 0x25, 0x50, 0x0c, 0x88, 0x4f, 0xad, 0x92, - 0xc2, 0x8f, 0x3f, 0x61, 0x9f, 0xf8, 0x14, 0xab, 0x0a, 0x74, 0x80, 0x99, 0xfc, 0x8a, 0x90, 0x78, - 0xd4, 0x2a, 0x2b, 0xd8, 0xa2, 0x86, 0x99, 0xfb, 0x59, 0x01, 0xe7, 0x18, 0xf8, 0x18, 0x98, 0x3c, - 0x4c, 0x06, 0xc7, 0x78, 0x60, 0x55, 0x14, 0xc1, 0xce, 0x08, 0x07, 0x59, 0xe1, 0x7a, 0x32, 0xc0, - 0x39, 0x01, 0x1e, 0x83, 0x6a, 0x2c, 0x68, 0xb4, 0x17, 0x9c, 0x70, 0xab, 0xaa, 0x1c, 0xfb, 0x0f, - 0x4d, 0x5e, 0xa3, 0x6f, 0x36, 0x3f, 0x71, 0xaa, 0xa9, 0xd1, 0xb9, 0x3b, 0x59, 0x06, 0x8f, 0x95, - 0x60, 0x13, 0x94, 0x79, 0xeb, 0x35, 0xf5, 0xa4, 0x65, 0x2a, 0xcd, 0xb5, 0xa9, 0x53, 0xd0, 0x8b, - 0x8b, 0x30, 0x39, 0xdd, 0x7d, 0x2b, 0x69, 0x90, 0x0c, 0xc0, 0xfd, 0x4b, 0x4b, 0x97, 0x0f, 0x94, - 0x08, 0xd6, 0x62, 0xf0, 0x15, 0x30, 0x79, 0xbf, 0x9d, 0x26, 0x2d, 0xf0, 0x3b, 0xca, 0x63, 0x2b, - 0x0f, 0x32, 0x1d, 0x9c, 0x4b, 0x2e, 0x7f, 0x98, 0x01, 0x8b, 0x13, 0x1b, 0x2f, 0x42, 0x1e, 0x08, - 0xfa, 0x47, 0x56, 0xfe, 0x7f, 0x50, 0x21, 0xfd, 0x3e, 0x3f, 0xa5, 0xe9, 0xd6, 0x57, 0xdd, 0x79, - 0xad, 0x53, 0xd9, 0x4e, 0xd3, 0x38, 0xab, 0xc3, 0x43, 0x50, 0x16, 0x92, 0xc8, 0x58, 0xe8, 0x0d, - 0x5e, 0xbd, 0xdb, 0x06, 0x1f, 0x29, 0x8e, 0x0b, 0x12, 0xdb, 0x30, 0x15, 0x71, 0x5f, 0x62, 0xad, - 0x03, 0x1b, 0xa0, 0x14, 0x12, 0xe9, 0x75, 0xd5, 0x96, 0xce, 0xb9, 0xe6, 0x68, 0xd8, 0x28, 0x1d, - 0x26, 0x09, 0x9c, 0xe6, 0xe1, 0x16, 0x30, 0xd5, 0xe1, 0xf8, 0x2c, 0xcc, 0x56, 0xb3, 0x9e, 0x98, - 0x74, 0x98, 0x25, 0xaf, 0x27, 0x03, 0x9c, 0x83, 0x97, 0x3f, 0x1a, 0x60, 0x7e, 0xc2, 0xb1, 0x01, - 0xa3, 0xa7, 0xb0, 0x09, 0x2a, 0x51, 0xfa, 0x5a, 0x28, 0xcf, 0x6a, 0x1b, 0x08, 0xfd, 0xe8, 0x61, - 0x46, 0x37, 0xdf, 0x18, 0xb7, 0x96, 0xf8, 0xa2, 0x03, 0x9c, 0x69, 0xc1, 0x17, 0xea, 0x6e, 0xab, - 0x91, 0xe8, 0x97, 0xc3, 0xb9, 0xb3, 0x6e, 0x4a, 0x73, 0xe7, 0xf4, 0x65, 0x56, 0x11, 0x1e, 0xcb, - 0xb9, 0x6b, 0xe7, 0x57, 0x76, 0xe1, 0xe2, 0xca, 0x2e, 0x5c, 0x5e, 0xd9, 0x85, 0x77, 0x23, 0xdb, - 0x38, 0x1f, 0xd9, 0xc6, 0xc5, 0xc8, 0x36, 0x2e, 0x47, 0xb6, 0xf1, 0x69, 0x64, 0x1b, 0xef, 0x3f, - 0xdb, 0x85, 0x97, 0x15, 0x2d, 0xfc, 0x35, 0x00, 0x00, 0xff, 0xff, 0x76, 0x21, 0xd5, 0x35, 0xaf, - 0x06, 0x00, 0x00, + // 728 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x4f, 0xdb, 0x48, + 0x14, 0x8f, 0x21, 0xff, 0x3c, 0x41, 0x0b, 0xcc, 0x5e, 0xac, 0x68, 0xe5, 0xb0, 0x1c, 0x56, 0xac, + 0x04, 0xe3, 0x05, 0xed, 0x22, 0xb4, 0xda, 0x0b, 0x16, 0x68, 0x85, 0x56, 0x02, 0x34, 0x90, 0x55, + 0xdb, 0x43, 0xa5, 0x89, 0xf3, 0x48, 0xdc, 0xc4, 0x1e, 0xd7, 0x33, 0x0e, 0xe5, 0xd6, 0x8f, 0xd0, + 0x6f, 0xd2, 0x0f, 0xd1, 0x0b, 0x47, 0x8e, 0x9c, 0xa2, 0x92, 0x7e, 0x80, 0xde, 0x39, 0x55, 0x1e, + 0x8f, 0xe3, 0x94, 0x96, 0x96, 0x56, 0x3d, 0x65, 0xde, 0x7b, 0xbf, 0xdf, 0xef, 0xc5, 0xbf, 0xf7, + 0x66, 0xd0, 0xfe, 0x60, 0x47, 0x10, 0x9f, 0x3b, 0x83, 0xa4, 0x03, 0x71, 0x08, 0x12, 0x84, 0x33, + 0x82, 0xb0, 0xcb, 0x63, 0x47, 0x17, 0x58, 0xe4, 0x3b, 0xac, 0x1b, 0xf8, 0x42, 0xf8, 0x3c, 0x74, + 0x46, 0x9b, 0x1d, 0x90, 0x6c, 0xd3, 0xe9, 0x41, 0x08, 0x31, 0x93, 0xd0, 0x25, 0x51, 0xcc, 0x25, + 0xc7, 0xbf, 0x64, 0x68, 0xc2, 0x22, 0x9f, 0x4c, 0xd1, 0x44, 0xa3, 0x9b, 0x1b, 0x3d, 0x5f, 0xf6, + 0x93, 0x0e, 0xf1, 0x78, 0xe0, 0xf4, 0x78, 0x8f, 0x3b, 0x8a, 0xd4, 0x49, 0xce, 0x54, 0xa4, 0x02, + 0x75, 0xca, 0xc4, 0x9a, 0xeb, 0xb3, 0xad, 0x13, 0xd9, 0x87, 0x50, 0xfa, 0x1e, 0x93, 0x59, 0xff, + 0xbb, 0xad, 0x9b, 0x7f, 0x16, 0xe8, 0x80, 0x79, 0x7d, 0x3f, 0x84, 0xf8, 0xc2, 0x89, 0x06, 0xbd, + 0x34, 0x21, 0x9c, 0x00, 0x24, 0xfb, 0x1c, 0xcb, 0xb9, 0x8f, 0x15, 0x27, 0xa1, 0xf4, 0x03, 0xf8, + 0x84, 0xb0, 0xfd, 0x35, 0x82, 0xf0, 0xfa, 0x10, 0xb0, 0xbb, 0xbc, 0xd5, 0xf7, 0x15, 0xb4, 0xb4, + 0x9b, 0x3b, 0x42, 0xe1, 0x79, 0x02, 0x42, 0x62, 0x17, 0xcd, 0x27, 0x7e, 0xd7, 0x32, 0x56, 0x8c, + 0x35, 0xd3, 0xfd, 0xe3, 0x72, 0xdc, 0x2a, 0x4d, 0xc6, 0xad, 0xf9, 0xf6, 0xc1, 0xde, 0xed, 0xb8, + 0xf5, 0xeb, 0x7d, 0x8d, 0xe4, 0x45, 0x04, 0x82, 0xb4, 0x0f, 0xf6, 0x68, 0x4a, 0xc6, 0x8f, 0x50, + 0x79, 0xe0, 0x87, 0x5d, 0x6b, 0x6e, 0xc5, 0x58, 0x6b, 0x6c, 0x6d, 0x93, 0x62, 0x02, 0x53, 0x1a, + 0x89, 0x06, 0xbd, 0x34, 0x21, 0x48, 0x6a, 0x03, 0x19, 0x6d, 0x92, 0x7f, 0x63, 0x9e, 0x44, 0xff, + 0x43, 0x9c, 0xfe, 0x99, 0xff, 0xfc, 0xb0, 0xeb, 0x2e, 0xe8, 0xe6, 0xe5, 0x34, 0xa2, 0x4a, 0x11, + 0xf7, 0x51, 0x3d, 0x06, 0xc1, 0x93, 0xd8, 0x03, 0x6b, 0x5e, 0xa9, 0xff, 0xfd, 0xed, 0xea, 0x54, + 0x2b, 0xb8, 0x4b, 0xba, 0x43, 0x3d, 0xcf, 0xd0, 0xa9, 0x3a, 0xfe, 0x0b, 0x35, 0x44, 0xd2, 0xc9, + 0x0b, 0x56, 0x59, 0xf9, 0xf1, 0xb3, 0x26, 0x34, 0x4e, 0x8a, 0x12, 0x9d, 0xc5, 0xe1, 0x15, 0x54, + 0x0e, 0x59, 0x00, 0x56, 0x45, 0xe1, 0xa7, 0x9f, 0x70, 0xc8, 0x02, 0xa0, 0xaa, 0x82, 0x1d, 0x64, + 0xa6, 0xbf, 0x22, 0x62, 0x1e, 0x58, 0x55, 0x05, 0x5b, 0xd6, 0x30, 0xf3, 0x30, 0x2f, 0xd0, 0x02, + 0x83, 0xff, 0x41, 0x26, 0x8f, 0xd2, 0xc1, 0xf9, 0x3c, 0xb4, 0x6a, 0x8a, 0x60, 0xe7, 0x84, 0xa3, + 0xbc, 0x70, 0x3b, 0x1b, 0xd0, 0x82, 0x80, 0x4f, 0x51, 0x3d, 0x11, 0x10, 0x1f, 0x84, 0x67, 0xdc, + 0xaa, 0x2b, 0xc7, 0x7e, 0x23, 0xb3, 0x37, 0xe2, 0xa3, 0x25, 0x4e, 0x9d, 0x6a, 0x6b, 0x74, 0xe1, + 0x4e, 0x9e, 0xa1, 0x53, 0x25, 0xdc, 0x46, 0x55, 0xde, 0x79, 0x06, 0x9e, 0xb4, 0x4c, 0xa5, 0xb9, + 0x71, 0xef, 0x14, 0xf4, 0x0e, 0x12, 0xca, 0xce, 0xf7, 0x5f, 0x48, 0x08, 0xd3, 0x01, 0xb8, 0x3f, + 0x69, 0xe9, 0xea, 0x91, 0x12, 0xa1, 0x5a, 0x0c, 0x3f, 0x45, 0x26, 0x1f, 0x76, 0xb3, 0xa4, 0x85, + 0xbe, 0x47, 0x79, 0x6a, 0xe5, 0x51, 0xae, 0x43, 0x0b, 0xc9, 0xd5, 0xd7, 0x73, 0x68, 0x79, 0x66, + 0xe3, 0x45, 0xc4, 0x43, 0x01, 0x3f, 0x64, 0xe5, 0x7f, 0x47, 0x35, 0x36, 0x1c, 0xf2, 0x73, 0xc8, + 0xb6, 0xbe, 0xee, 0x2e, 0x6a, 0x9d, 0xda, 0x6e, 0x96, 0xa6, 0x79, 0x1d, 0x1f, 0xa3, 0xaa, 0x90, + 0x4c, 0x26, 0x42, 0x6f, 0xf0, 0xfa, 0xc3, 0x36, 0xf8, 0x44, 0x71, 0x5c, 0x94, 0xda, 0x46, 0x41, + 0x24, 0x43, 0x49, 0xb5, 0x0e, 0x6e, 0xa1, 0x4a, 0xc4, 0xa4, 0xd7, 0x57, 0x5b, 0xba, 0xe0, 0x9a, + 0x93, 0x71, 0xab, 0x72, 0x9c, 0x26, 0x68, 0x96, 0xc7, 0x3b, 0xc8, 0x54, 0x87, 0xd3, 0x8b, 0x28, + 0x5f, 0xcd, 0x66, 0x6a, 0xd2, 0x71, 0x9e, 0xbc, 0x9d, 0x0d, 0x68, 0x01, 0x5e, 0x7d, 0x63, 0xa0, + 0xc5, 0x19, 0xc7, 0x46, 0x3e, 0x9c, 0xe3, 0x36, 0xaa, 0xc5, 0xd9, 0x6b, 0xa1, 0x3c, 0x6b, 0x6c, + 0x11, 0xf2, 0xa5, 0x37, 0x96, 0xdc, 0x7d, 0x63, 0xdc, 0x46, 0xea, 0x8b, 0x0e, 0x68, 0xae, 0x85, + 0x1f, 0xab, 0xbb, 0xad, 0x46, 0xa2, 0x5f, 0x0e, 0xe7, 0xc1, 0xba, 0x19, 0xcd, 0x5d, 0xd0, 0x97, + 0x59, 0x45, 0x74, 0x2a, 0xe7, 0x6e, 0x5c, 0xde, 0xd8, 0xa5, 0xab, 0x1b, 0xbb, 0x74, 0x7d, 0x63, + 0x97, 0x5e, 0x4e, 0x6c, 0xe3, 0x72, 0x62, 0x1b, 0x57, 0x13, 0xdb, 0xb8, 0x9e, 0xd8, 0xc6, 0xdb, + 0x89, 0x6d, 0xbc, 0x7a, 0x67, 0x97, 0x9e, 0xd4, 0xb4, 0xf0, 0x87, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xb6, 0xe9, 0xbc, 0x6f, 0x7a, 0x06, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/admission/v1beta1/generated.proto b/vendor/k8s.io/api/admission/v1beta1/generated.proto index a4e4ca266..dfc7f4474 100644 --- a/vendor/k8s.io/api/admission/v1beta1/generated.proto +++ b/vendor/k8s.io/api/admission/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/api/authentication/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go index 1f5313517..c22e3f63c 100644 --- a/vendor/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AdmissionRequest = map[string]string{ "": "AdmissionRequest describes the admission.Attributes for the admission request.", "uid": "UID is an identifier for the individual request/response. It allows us to distinguish instances of requests which are otherwise identical (parallel requests, requests when earlier requests did not modify etc) The UID is meant to track the round trip (request/response) between the KAS and the WebHook, not the user request. It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging.", diff --git a/vendor/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go index fc60e1909..e3bcc03a1 100644 --- a/vendor/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/admissionregistration/v1alpha1/generated.pb.go b/vendor/k8s.io/api/admissionregistration/v1alpha1/generated.pb.go index f5d4941d3..b87f74e52 100644 --- a/vendor/k8s.io/api/admissionregistration/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/api/admissionregistration/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -989,40 +989,39 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 545 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x51, 0x4d, 0x8b, 0x13, 0x3f, - 0x18, 0x6f, 0xfe, 0xdb, 0x42, 0x9b, 0x76, 0xf9, 0xcb, 0xe0, 0xa1, 0x14, 0x99, 0x96, 0x9e, 0x2a, - 0x62, 0x62, 0x57, 0x59, 0xbc, 0xee, 0xec, 0x41, 0x0a, 0xbe, 0x2c, 0x41, 0x3c, 0x88, 0x07, 0xd3, - 0xf6, 0xd9, 0x69, 0x6c, 0x27, 0x19, 0x92, 0x4c, 0x41, 0x4f, 0x5e, 0xbc, 0x0b, 0x7e, 0xa9, 0x1e, - 0xf7, 0xb8, 0xa7, 0x62, 0x47, 0xf0, 0xe8, 0x67, 0x90, 0x99, 0xe9, 0xec, 0xcc, 0x5a, 0x8b, 0xab, - 0xb7, 0x3c, 0xbf, 0x27, 0xbf, 0xb7, 0x04, 0xb3, 0xf9, 0x63, 0x43, 0x84, 0xa2, 0xf3, 0x68, 0x0c, - 0x5a, 0x82, 0x05, 0x43, 0x97, 0x20, 0xa7, 0x4a, 0xd3, 0xed, 0x82, 0x87, 0x82, 0xf2, 0x69, 0x20, - 0x8c, 0x11, 0x4a, 0x6a, 0xf0, 0x85, 0xb1, 0x9a, 0x5b, 0xa1, 0x24, 0x5d, 0x0e, 0xf9, 0x22, 0x9c, - 0xf1, 0x21, 0xf5, 0x41, 0x82, 0xe6, 0x16, 0xa6, 0x24, 0xd4, 0xca, 0x2a, 0xe7, 0x6e, 0x46, 0x25, - 0x3c, 0x14, 0xe4, 0xb7, 0x54, 0x92, 0x53, 0x3b, 0xf7, 0x7d, 0x61, 0x67, 0xd1, 0x98, 0x4c, 0x54, - 0x40, 0x7d, 0xe5, 0x2b, 0x9a, 0x2a, 0x8c, 0xa3, 0xf3, 0x74, 0x4a, 0x87, 0xf4, 0x94, 0x29, 0x77, - 0x1e, 0x15, 0xa1, 0x02, 0x3e, 0x99, 0x09, 0x09, 0xfa, 0x3d, 0x0d, 0xe7, 0x7e, 0x02, 0x18, 0x1a, - 0x80, 0xe5, 0x74, 0xb9, 0x93, 0xa7, 0x43, 0xf7, 0xb1, 0x74, 0x24, 0xad, 0x08, 0x60, 0x87, 0x70, - 0xfc, 0x27, 0x82, 0x99, 0xcc, 0x20, 0xe0, 0x3b, 0xbc, 0x87, 0xfb, 0x78, 0x91, 0x15, 0x0b, 0x2a, - 0xa4, 0x35, 0x56, 0xff, 0x4a, 0xea, 0x7f, 0x42, 0xb8, 0x39, 0x92, 0xc2, 0x0a, 0xbe, 0x10, 0x1f, - 0x40, 0x3b, 0x3d, 0x5c, 0x95, 0x3c, 0x80, 0x36, 0xea, 0xa1, 0x41, 0xc3, 0x6b, 0xad, 0xd6, 0xdd, - 0x4a, 0xbc, 0xee, 0x56, 0x9f, 0xf3, 0x00, 0x58, 0xba, 0x71, 0x5e, 0xe2, 0x9a, 0x8e, 0x16, 0x60, - 0xda, 0xff, 0xf5, 0x0e, 0x06, 0xcd, 0x23, 0x4a, 0x6e, 0xfc, 0xde, 0x84, 0x45, 0x0b, 0xf0, 0x0e, - 0xb7, 0x9a, 0xb5, 0x64, 0x32, 0x2c, 0x13, 0xeb, 0xff, 0x40, 0xb8, 0x5d, 0xca, 0x71, 0xaa, 0xe4, - 0xb9, 0xf0, 0xa3, 0x4c, 0xc0, 0x79, 0x8b, 0xeb, 0xc9, 0xeb, 0x4e, 0xb9, 0xe5, 0x69, 0xb0, 0xe6, - 0xd1, 0x83, 0x92, 0xeb, 0x55, 0x59, 0x12, 0xce, 0xfd, 0x04, 0x30, 0x24, 0xb9, 0x4d, 0x96, 0x43, - 0xf2, 0x62, 0xfc, 0x0e, 0x26, 0xf6, 0x19, 0x58, 0xee, 0x39, 0x5b, 0x5b, 0x5c, 0x60, 0xec, 0x4a, - 0xd5, 0x09, 0x71, 0x4b, 0x14, 0xee, 0x79, 0xb7, 0xe3, 0xbf, 0xe8, 0x56, 0x0a, 0xef, 0xdd, 0xde, - 0x7a, 0xb5, 0x4a, 0xa0, 0x61, 0xd7, 0x1c, 0xfa, 0xdf, 0x11, 0xbe, 0xb3, 0xaf, 0xf0, 0x53, 0x61, - 0xac, 0xf3, 0x66, 0xa7, 0x34, 0xb9, 0x59, 0xe9, 0x84, 0x9d, 0x56, 0xbe, 0xb5, 0x8d, 0x51, 0xcf, - 0x91, 0x52, 0xe1, 0x19, 0xae, 0x09, 0x0b, 0x41, 0xde, 0xf4, 0xf4, 0xdf, 0x9a, 0x5e, 0x4b, 0x5d, - 0xfc, 0xec, 0x28, 0x51, 0x66, 0x99, 0x41, 0xff, 0x0b, 0xc2, 0xd5, 0xe4, 0xab, 0x9d, 0x7b, 0xb8, - 0xc1, 0x43, 0xf1, 0x44, 0xab, 0x28, 0x34, 0x6d, 0xd4, 0x3b, 0x18, 0x34, 0xbc, 0xc3, 0x78, 0xdd, - 0x6d, 0x9c, 0x9c, 0x8d, 0x32, 0x90, 0x15, 0x7b, 0x67, 0x88, 0x9b, 0x3c, 0x14, 0xaf, 0x40, 0x27, - 0x39, 0xb2, 0x94, 0x0d, 0xef, 0xff, 0x78, 0xdd, 0x6d, 0x9e, 0x9c, 0x8d, 0x72, 0x98, 0x95, 0xef, - 0x24, 0xfa, 0x1a, 0x8c, 0x8a, 0xf4, 0x04, 0x4c, 0xfb, 0xa0, 0xd0, 0x67, 0x39, 0xc8, 0x8a, 0xbd, - 0x47, 0x56, 0x1b, 0xb7, 0x72, 0xb1, 0x71, 0x2b, 0x97, 0x1b, 0xb7, 0xf2, 0x31, 0x76, 0xd1, 0x2a, - 0x76, 0xd1, 0x45, 0xec, 0xa2, 0xcb, 0xd8, 0x45, 0x5f, 0x63, 0x17, 0x7d, 0xfe, 0xe6, 0x56, 0x5e, - 0xd7, 0xf3, 0xd2, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x1d, 0xfb, 0x23, 0x89, 0xaa, 0x04, 0x00, - 0x00, + // 531 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x51, 0x4d, 0x8b, 0x13, 0x31, + 0x18, 0x6e, 0x6c, 0x0b, 0x6d, 0xda, 0x45, 0x19, 0x3c, 0x94, 0x22, 0xd3, 0xd2, 0x53, 0x45, 0x4c, + 0xec, 0x22, 0x8b, 0xd7, 0x9d, 0x3d, 0x48, 0xc1, 0x8f, 0x25, 0x88, 0x07, 0xf1, 0x60, 0xda, 0xbe, + 0x3b, 0x8d, 0xed, 0x4c, 0x86, 0x24, 0x53, 0xd0, 0x93, 0x17, 0xef, 0x82, 0x7f, 0xaa, 0xc7, 0x3d, + 0xee, 0xa9, 0xd8, 0x11, 0x3c, 0xfa, 0x1b, 0x24, 0x33, 0x9d, 0x9d, 0x59, 0xeb, 0xe2, 0xea, 0x2d, + 0xef, 0xf3, 0xe6, 0xf9, 0x4a, 0x30, 0x5b, 0x3c, 0xd1, 0x44, 0x48, 0xba, 0x88, 0x27, 0xa0, 0x42, + 0x30, 0xa0, 0xe9, 0x0a, 0xc2, 0x99, 0x54, 0x74, 0xb7, 0xe0, 0x91, 0xa0, 0x7c, 0x16, 0x08, 0xad, + 0x85, 0x0c, 0x15, 0xf8, 0x42, 0x1b, 0xc5, 0x8d, 0x90, 0x21, 0x5d, 0x8d, 0xf8, 0x32, 0x9a, 0xf3, + 0x11, 0xf5, 0x21, 0x04, 0xc5, 0x0d, 0xcc, 0x48, 0xa4, 0xa4, 0x91, 0xce, 0xfd, 0x8c, 0x4a, 0x78, + 0x24, 0xc8, 0x1f, 0xa9, 0x24, 0xa7, 0x76, 0x1f, 0xfa, 0xc2, 0xcc, 0xe3, 0x09, 0x99, 0xca, 0x80, + 0xfa, 0xd2, 0x97, 0x34, 0x55, 0x98, 0xc4, 0x67, 0xe9, 0x94, 0x0e, 0xe9, 0x29, 0x53, 0xee, 0x3e, + 0x2e, 0x42, 0x05, 0x7c, 0x3a, 0x17, 0x21, 0xa8, 0x0f, 0x34, 0x5a, 0xf8, 0x16, 0xd0, 0x34, 0x00, + 0xc3, 0xe9, 0x6a, 0x2f, 0x4f, 0x97, 0x5e, 0xc7, 0x52, 0x71, 0x68, 0x44, 0x00, 0x7b, 0x84, 0xa3, + 0xbf, 0x11, 0xf4, 0x74, 0x0e, 0x01, 0xff, 0x9d, 0x37, 0xf8, 0x8c, 0x70, 0x6b, 0x1c, 0x0a, 0x23, + 0xf8, 0x52, 0x7c, 0x04, 0xe5, 0xf4, 0x71, 0x2d, 0xe4, 0x01, 0x74, 0x50, 0x1f, 0x0d, 0x9b, 0x5e, + 0x7b, 0xbd, 0xe9, 0x55, 0x92, 0x4d, 0xaf, 0xf6, 0x82, 0x07, 0xc0, 0xd2, 0x8d, 0xf3, 0x0a, 0xd7, + 0x55, 0xbc, 0x04, 0xdd, 0xb9, 0xd5, 0xaf, 0x0e, 0x5b, 0x87, 0x94, 0xdc, 0xf8, 0xe9, 0x08, 0x8b, + 0x97, 0xe0, 0x1d, 0xec, 0x34, 0xeb, 0x76, 0xd2, 0x2c, 0x13, 0x1b, 0xfc, 0x44, 0xb8, 0x53, 0xca, + 0x71, 0x22, 0xc3, 0x33, 0xe1, 0xc7, 0x99, 0x80, 0xf3, 0x0e, 0x37, 0xec, 0x43, 0xcd, 0xb8, 0xe1, + 0x69, 0xb0, 0xd6, 0xe1, 0xa3, 0x92, 0xeb, 0x65, 0x5f, 0x12, 0x2d, 0x7c, 0x0b, 0x68, 0x62, 0x6f, + 0x93, 0xd5, 0x88, 0xbc, 0x9c, 0xbc, 0x87, 0xa9, 0x79, 0x0e, 0x86, 0x7b, 0xce, 0xce, 0x16, 0x17, + 0x18, 0xbb, 0x54, 0x75, 0x22, 0xdc, 0x16, 0x85, 0x7b, 0xde, 0xed, 0xe8, 0x1f, 0xba, 0x95, 0xc2, + 0x7b, 0x77, 0x77, 0x5e, 0xed, 0x12, 0xa8, 0xd9, 0x15, 0x87, 0xc1, 0x0f, 0x84, 0xef, 0x5d, 0x57, + 0xf8, 0x99, 0xd0, 0xc6, 0x79, 0xbb, 0x57, 0x9a, 0xdc, 0xac, 0xb4, 0x65, 0xa7, 0x95, 0xef, 0xec, + 0x62, 0x34, 0x72, 0xa4, 0x54, 0x78, 0x8e, 0xeb, 0xc2, 0x40, 0x90, 0x37, 0x3d, 0xf9, 0xbf, 0xa6, + 0x57, 0x52, 0x17, 0x3f, 0x3b, 0xb6, 0xca, 0x2c, 0x33, 0x18, 0x7c, 0x45, 0xb8, 0x66, 0xbf, 0xda, + 0x79, 0x80, 0x9b, 0x3c, 0x12, 0x4f, 0x95, 0x8c, 0x23, 0xdd, 0x41, 0xfd, 0xea, 0xb0, 0xe9, 0x1d, + 0x24, 0x9b, 0x5e, 0xf3, 0xf8, 0x74, 0x9c, 0x81, 0xac, 0xd8, 0x3b, 0x23, 0xdc, 0xe2, 0x91, 0x78, + 0x0d, 0xca, 0xe6, 0xc8, 0x52, 0x36, 0xbd, 0xdb, 0xc9, 0xa6, 0xd7, 0x3a, 0x3e, 0x1d, 0xe7, 0x30, + 0x2b, 0xdf, 0xb1, 0xfa, 0x0a, 0xb4, 0x8c, 0xd5, 0x14, 0x74, 0xa7, 0x5a, 0xe8, 0xb3, 0x1c, 0x64, + 0xc5, 0xde, 0x23, 0xeb, 0xad, 0x5b, 0x39, 0xdf, 0xba, 0x95, 0x8b, 0xad, 0x5b, 0xf9, 0x94, 0xb8, + 0x68, 0x9d, 0xb8, 0xe8, 0x3c, 0x71, 0xd1, 0x45, 0xe2, 0xa2, 0x6f, 0x89, 0x8b, 0xbe, 0x7c, 0x77, + 0x2b, 0x6f, 0x1a, 0x79, 0xe9, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa2, 0x06, 0xa3, 0xcb, 0x75, + 0x04, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/admissionregistration/v1alpha1/generated.proto b/vendor/k8s.io/api/admissionregistration/v1alpha1/generated.proto index 11de02ff4..e17b55968 100644 --- a/vendor/k8s.io/api/admissionregistration/v1alpha1/generated.proto +++ b/vendor/k8s.io/api/admissionregistration/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.admissionregistration.v1alpha1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/api/admissionregistration/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/api/admissionregistration/v1alpha1/types_swagger_doc_generated.go index e2494e5d7..69e4b7c64 100644 --- a/vendor/k8s.io/api/admissionregistration/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/admissionregistration/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_Initializer = map[string]string{ "": "Initializer describes the name and the failure policy of an initializer, and what resources it applies to.", "name": "Name is the identifier of the initializer. It will be added to the object that needs to be initialized. Name should be fully qualified, e.g., alwayspullimages.kubernetes.io, where \"alwayspullimages\" is the name of the webhook, and kubernetes.io is the name of the organization. Required", diff --git a/vendor/k8s.io/api/admissionregistration/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/api/admissionregistration/v1alpha1/zz_generated.deepcopy.go index 2ca492946..9f636b484 100644 --- a/vendor/k8s.io/api/admissionregistration/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/admissionregistration/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/admissionregistration/v1beta1/generated.pb.go b/vendor/k8s.io/api/admissionregistration/v1beta1/generated.pb.go index 51e5762a8..8b289c4c5 100644 --- a/vendor/k8s.io/api/admissionregistration/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/admissionregistration/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2088,63 +2088,60 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 916 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x54, 0xcf, 0x6f, 0x1b, 0x45, - 0x14, 0xf6, 0xd6, 0x8e, 0x6c, 0x8f, 0x6d, 0xd1, 0x0c, 0x20, 0x99, 0xa8, 0xda, 0xb5, 0x7c, 0x40, - 0x96, 0x50, 0x76, 0x71, 0x8a, 0x10, 0x42, 0x20, 0x94, 0x8d, 0x54, 0x88, 0x94, 0xb4, 0x66, 0x02, - 0xad, 0x84, 0x38, 0x30, 0x5e, 0xbf, 0xd8, 0x83, 0xf7, 0x97, 0x66, 0x66, 0xdd, 0xe6, 0x86, 0xc4, - 0x3f, 0x80, 0xc4, 0x1f, 0xc1, 0x5f, 0xc1, 0x3d, 0x37, 0x7a, 0x41, 0xf4, 0xb4, 0x22, 0xcb, 0x99, - 0x03, 0xd7, 0x9e, 0xd0, 0xce, 0xae, 0xbd, 0x76, 0x1c, 0xa7, 0xee, 0x85, 0x03, 0x37, 0xcf, 0xf7, - 0xde, 0xf7, 0xbd, 0xf7, 0x3d, 0xbf, 0xb7, 0xe8, 0xcb, 0xe9, 0x47, 0xc2, 0x64, 0x81, 0x35, 0x8d, - 0x86, 0xc0, 0x7d, 0x90, 0x20, 0xac, 0x19, 0xf8, 0xa3, 0x80, 0x5b, 0x79, 0x80, 0x86, 0xcc, 0xa2, - 0x23, 0x8f, 0x09, 0xc1, 0x02, 0x9f, 0xc3, 0x98, 0x09, 0xc9, 0xa9, 0x64, 0x81, 0x6f, 0xcd, 0xfa, - 0x43, 0x90, 0xb4, 0x6f, 0x8d, 0xc1, 0x07, 0x4e, 0x25, 0x8c, 0xcc, 0x90, 0x07, 0x32, 0xc0, 0xbd, - 0x8c, 0x69, 0xd2, 0x90, 0x99, 0x37, 0x32, 0xcd, 0x9c, 0xb9, 0xb7, 0x3f, 0x66, 0x72, 0x12, 0x0d, - 0x4d, 0x27, 0xf0, 0xac, 0x71, 0x30, 0x0e, 0x2c, 0x25, 0x30, 0x8c, 0xce, 0xd5, 0x4b, 0x3d, 0xd4, - 0xaf, 0x4c, 0x78, 0xaf, 0xbb, 0xd4, 0x92, 0x13, 0x70, 0xb0, 0x66, 0x6b, 0xc5, 0xf7, 0x4e, 0x8b, - 0x1c, 0x78, 0x26, 0xc1, 0x4f, 0x6b, 0x8b, 0x7d, 0x1a, 0x32, 0x01, 0x7c, 0x06, 0xdc, 0x0a, 0xa7, - 0xe3, 0x34, 0x26, 0x56, 0x13, 0x36, 0x79, 0xd9, 0xfb, 0xa0, 0x90, 0xf3, 0xa8, 0x33, 0x61, 0x3e, - 0xf0, 0x8b, 0x42, 0xc3, 0x03, 0x49, 0x6f, 0x6a, 0xc2, 0xda, 0xc4, 0xe2, 0x91, 0x2f, 0x99, 0x07, - 0x6b, 0x84, 0x0f, 0x5f, 0x45, 0x10, 0xce, 0x04, 0x3c, 0xba, 0xc6, 0xbb, 0xbf, 0x89, 0x17, 0x49, - 0xe6, 0x5a, 0xcc, 0x97, 0x42, 0xf2, 0xeb, 0xa4, 0xee, 0xef, 0x1a, 0xba, 0x77, 0x1a, 0x49, 0x2a, - 0x99, 0x3f, 0x7e, 0x02, 0xc3, 0x49, 0x10, 0x4c, 0x8f, 0x02, 0xff, 0x9c, 0x8d, 0xa3, 0xec, 0xef, - 0xc1, 0xdf, 0xa1, 0x5a, 0xea, 0x6c, 0x44, 0x25, 0x6d, 0x6b, 0x1d, 0xad, 0xd7, 0x38, 0x78, 0xdf, - 0x2c, 0xfe, 0xd3, 0x45, 0x21, 0x33, 0x9c, 0x8e, 0x53, 0x40, 0x98, 0x69, 0xb6, 0x39, 0xeb, 0x9b, - 0x8f, 0x86, 0xdf, 0x83, 0x23, 0x4f, 0x41, 0x52, 0x1b, 0x5f, 0xc6, 0x46, 0x29, 0x89, 0x0d, 0x54, - 0x60, 0x64, 0xa1, 0x8a, 0xcf, 0x50, 0x2d, 0xaf, 0x2c, 0xda, 0x77, 0x3a, 0xe5, 0x5e, 0xe3, 0xa0, - 0x6f, 0x6e, 0xbb, 0x35, 0x66, 0xce, 0xb4, 0x2b, 0x69, 0x09, 0x52, 0x7b, 0x9a, 0x0b, 0x75, 0xff, - 0xd6, 0x50, 0xe7, 0x36, 0x5f, 0x27, 0x4c, 0x48, 0xfc, 0xed, 0x9a, 0x37, 0x73, 0x3b, 0x6f, 0x29, - 0x5b, 0x39, 0xbb, 0x9b, 0x3b, 0xab, 0xcd, 0x91, 0x25, 0x5f, 0x53, 0xb4, 0xc3, 0x24, 0x78, 0x73, - 0x53, 0x0f, 0xb6, 0x37, 0x75, 0x5b, 0xe3, 0x76, 0x2b, 0x2f, 0xb9, 0x73, 0x9c, 0x8a, 0x93, 0xac, - 0x46, 0xf7, 0x67, 0x0d, 0x55, 0x48, 0xe4, 0x02, 0x7e, 0x0f, 0xd5, 0x69, 0xc8, 0x3e, 0xe7, 0x41, - 0x14, 0x8a, 0xb6, 0xd6, 0x29, 0xf7, 0xea, 0x76, 0x2b, 0x89, 0x8d, 0xfa, 0xe1, 0xe0, 0x38, 0x03, - 0x49, 0x11, 0xc7, 0x7d, 0xd4, 0xa0, 0x21, 0x7b, 0x0c, 0x5c, 0x2d, 0xbe, 0x6a, 0xb4, 0x6e, 0xbf, - 0x91, 0xc4, 0x46, 0xe3, 0x70, 0x70, 0x3c, 0x87, 0xc9, 0x72, 0x4e, 0xaa, 0xcf, 0x41, 0x04, 0x11, - 0x77, 0x40, 0xb4, 0xcb, 0x85, 0x3e, 0x99, 0x83, 0xa4, 0x88, 0x77, 0x7f, 0xd1, 0x10, 0x4e, 0xbb, - 0x7a, 0xc2, 0xe4, 0xe4, 0x51, 0x08, 0x99, 0x03, 0x81, 0x3f, 0x43, 0x28, 0x58, 0xbc, 0xf2, 0x26, - 0x0d, 0xb5, 0x1f, 0x0b, 0xf4, 0x65, 0x6c, 0xb4, 0x16, 0xaf, 0xaf, 0x2e, 0x42, 0x20, 0x4b, 0x14, - 0x3c, 0x40, 0x15, 0x1e, 0xb9, 0xd0, 0xbe, 0xb3, 0xf6, 0xa7, 0xbd, 0x62, 0xb2, 0x69, 0x33, 0x76, - 0x33, 0x9f, 0xa0, 0x1a, 0x18, 0x51, 0x4a, 0xdd, 0x1f, 0x35, 0x74, 0xf7, 0x0c, 0xf8, 0x8c, 0x39, - 0x40, 0xe0, 0x1c, 0x38, 0xf8, 0x0e, 0x60, 0x0b, 0xd5, 0x7d, 0xea, 0x81, 0x08, 0xa9, 0x03, 0x6a, - 0x41, 0xea, 0xf6, 0x6e, 0xce, 0xad, 0x3f, 0x9c, 0x07, 0x48, 0x91, 0x83, 0x3b, 0xa8, 0x92, 0x3e, - 0x54, 0x5f, 0xf5, 0xa2, 0x4e, 0x9a, 0x4b, 0x54, 0x04, 0xdf, 0x43, 0x95, 0x90, 0xca, 0x49, 0xbb, - 0xac, 0x32, 0x6a, 0x69, 0x74, 0x40, 0xe5, 0x84, 0x28, 0xb4, 0xfb, 0x87, 0x86, 0xf4, 0xc7, 0xd4, - 0x65, 0xa3, 0xff, 0xdd, 0x3d, 0xfe, 0xa3, 0xa1, 0xee, 0xed, 0xce, 0xfe, 0x83, 0x8b, 0xf4, 0x56, - 0x2f, 0xf2, 0x8b, 0xed, 0x6d, 0xdd, 0xde, 0xfa, 0x86, 0x9b, 0xfc, 0xad, 0x8c, 0xaa, 0x79, 0xfa, - 0x62, 0x33, 0xb4, 0x8d, 0x9b, 0xf1, 0x14, 0x35, 0x1d, 0x97, 0x81, 0x2f, 0x33, 0xe9, 0x7c, 0xb7, - 0x3f, 0x7d, 0xed, 0xd1, 0x1f, 0x2d, 0x89, 0xd8, 0x6f, 0xe5, 0x85, 0x9a, 0xcb, 0x28, 0x59, 0x29, - 0x84, 0x29, 0xda, 0x49, 0x4f, 0x20, 0xbb, 0xe6, 0xc6, 0xc1, 0x27, 0xaf, 0x77, 0x4d, 0xab, 0xa7, - 0x5d, 0x4c, 0x22, 0x8d, 0x09, 0x92, 0x29, 0xe3, 0x13, 0xd4, 0x3a, 0xa7, 0xcc, 0x8d, 0x38, 0x0c, - 0x02, 0x97, 0x39, 0x17, 0xed, 0x8a, 0x1a, 0xc3, 0xbb, 0x49, 0x6c, 0xb4, 0x1e, 0x2c, 0x07, 0x5e, - 0xc6, 0xc6, 0xee, 0x0a, 0xa0, 0x4e, 0x7f, 0x95, 0x8c, 0x9f, 0xa1, 0xdd, 0xc5, 0xc9, 0x9d, 0x81, - 0x0b, 0x8e, 0x0c, 0x78, 0x7b, 0x47, 0x8d, 0xeb, 0xfe, 0x96, 0xdb, 0x42, 0x87, 0xe0, 0xce, 0xa9, - 0xf6, 0xdb, 0x49, 0x6c, 0xec, 0x3e, 0xbc, 0xae, 0x48, 0xd6, 0x8b, 0x74, 0x7f, 0xd5, 0xd0, 0x9b, - 0x37, 0x8c, 0x19, 0x53, 0x54, 0x15, 0xd9, 0xc7, 0x23, 0xdf, 0xda, 0x8f, 0xb7, 0x1f, 0xe2, 0xf5, - 0xaf, 0x8e, 0xdd, 0x48, 0x62, 0xa3, 0x3a, 0x47, 0xe7, 0xba, 0xb8, 0x87, 0x6a, 0x0e, 0xb5, 0x23, - 0x7f, 0x94, 0x7f, 0xf6, 0x9a, 0x76, 0x33, 0xdd, 0xf2, 0xa3, 0xc3, 0x0c, 0x23, 0x8b, 0x28, 0x7e, - 0x07, 0x95, 0x23, 0xee, 0xe6, 0x5f, 0x98, 0x6a, 0x12, 0x1b, 0xe5, 0xaf, 0xc9, 0x09, 0x49, 0x31, - 0x7b, 0xff, 0xf2, 0x4a, 0x2f, 0x3d, 0xbf, 0xd2, 0x4b, 0x2f, 0xae, 0xf4, 0xd2, 0x0f, 0x89, 0xae, - 0x5d, 0x26, 0xba, 0xf6, 0x3c, 0xd1, 0xb5, 0x17, 0x89, 0xae, 0xfd, 0x99, 0xe8, 0xda, 0x4f, 0x7f, - 0xe9, 0xa5, 0x6f, 0xaa, 0x79, 0x6b, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x78, 0x57, 0x76, 0x28, - 0x10, 0x0a, 0x00, 0x00, + // 872 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x54, 0xcf, 0x8f, 0xdb, 0x44, + 0x14, 0x8e, 0x9b, 0xac, 0x92, 0x4c, 0x12, 0xd1, 0x1d, 0x40, 0x0a, 0xab, 0xca, 0x8e, 0x72, 0x40, + 0x91, 0x50, 0x6d, 0xb2, 0x20, 0x84, 0x10, 0x08, 0xad, 0x57, 0x2a, 0xac, 0xb4, 0x6d, 0xc3, 0x2c, + 0xb4, 0x12, 0xe2, 0xc0, 0xc4, 0x79, 0xeb, 0x0c, 0xf1, 0x2f, 0x8d, 0xc7, 0x29, 0x7b, 0x43, 0xe2, + 0x1f, 0x40, 0xe2, 0x8f, 0xe0, 0xaf, 0xe0, 0xbe, 0x37, 0x7a, 0x41, 0xf4, 0x64, 0xb1, 0xe6, 0xcc, + 0x81, 0x6b, 0x4f, 0x68, 0xec, 0x49, 0x9c, 0x6c, 0xba, 0x69, 0x7a, 0xe1, 0xc0, 0xcd, 0xf3, 0xbd, + 0xf9, 0xbe, 0xf7, 0xbe, 0xe7, 0xf7, 0x06, 0x7d, 0x31, 0xfb, 0x30, 0x36, 0x59, 0x68, 0xcd, 0x92, + 0x31, 0xf0, 0x00, 0x04, 0xc4, 0xd6, 0x1c, 0x82, 0x49, 0xc8, 0x2d, 0x15, 0xa0, 0x11, 0xb3, 0xe8, + 0xc4, 0x67, 0x71, 0xcc, 0xc2, 0x80, 0x83, 0xcb, 0x62, 0xc1, 0xa9, 0x60, 0x61, 0x60, 0xcd, 0x87, + 0x63, 0x10, 0x74, 0x68, 0xb9, 0x10, 0x00, 0xa7, 0x02, 0x26, 0x66, 0xc4, 0x43, 0x11, 0xe2, 0x41, + 0xc1, 0x34, 0x69, 0xc4, 0xcc, 0x17, 0x32, 0x4d, 0xc5, 0x3c, 0xb8, 0xeb, 0x32, 0x31, 0x4d, 0xc6, + 0xa6, 0x13, 0xfa, 0x96, 0x1b, 0xba, 0xa1, 0x95, 0x0b, 0x8c, 0x93, 0xf3, 0xfc, 0x94, 0x1f, 0xf2, + 0xaf, 0x42, 0xf8, 0xe0, 0xfd, 0xb2, 0x24, 0x9f, 0x3a, 0x53, 0x16, 0x00, 0xbf, 0xb0, 0xa2, 0x99, + 0x2b, 0x81, 0xd8, 0xf2, 0x41, 0x50, 0x6b, 0xbe, 0x51, 0xce, 0x81, 0x75, 0x13, 0x8b, 0x27, 0x81, + 0x60, 0x3e, 0x6c, 0x10, 0x3e, 0x78, 0x19, 0x21, 0x76, 0xa6, 0xe0, 0xd3, 0xeb, 0xbc, 0xfe, 0xef, + 0x1a, 0xba, 0x73, 0x3f, 0x11, 0x54, 0xb0, 0xc0, 0x7d, 0x0c, 0xe3, 0x69, 0x18, 0xce, 0x8e, 0xc3, + 0xe0, 0x9c, 0xb9, 0x49, 0x61, 0x1b, 0x7f, 0x8b, 0x1a, 0xb2, 0xc8, 0x09, 0x15, 0xb4, 0xab, 0xf5, + 0xb4, 0x41, 0xeb, 0xf0, 0x5d, 0xb3, 0xec, 0xd5, 0x32, 0x97, 0x19, 0xcd, 0x5c, 0x09, 0xc4, 0xa6, + 0xbc, 0x6d, 0xce, 0x87, 0xe6, 0xc3, 0xf1, 0x77, 0xe0, 0x88, 0xfb, 0x20, 0xa8, 0x8d, 0x2f, 0x53, + 0xa3, 0x92, 0xa5, 0x06, 0x2a, 0x31, 0xb2, 0x54, 0xc5, 0x67, 0xa8, 0xa1, 0x32, 0xc7, 0xdd, 0x5b, + 0xbd, 0xea, 0xa0, 0x75, 0x38, 0x34, 0x77, 0xfd, 0x1b, 0xa6, 0x62, 0xda, 0x35, 0x99, 0x82, 0x34, + 0x9e, 0x28, 0xa1, 0xfe, 0xdf, 0x1a, 0xea, 0x6d, 0xf3, 0x75, 0xca, 0x62, 0x81, 0xbf, 0xd9, 0xf0, + 0x66, 0xee, 0xe6, 0x4d, 0xb2, 0x73, 0x67, 0xb7, 0x95, 0xb3, 0xc6, 0x02, 0x59, 0xf1, 0x35, 0x43, + 0x7b, 0x4c, 0x80, 0xbf, 0x30, 0x75, 0x6f, 0x77, 0x53, 0xdb, 0x0a, 0xb7, 0x3b, 0x2a, 0xe5, 0xde, + 0x89, 0x14, 0x27, 0x45, 0x8e, 0xfe, 0xcf, 0x1a, 0xaa, 0x91, 0xc4, 0x03, 0xfc, 0x0e, 0x6a, 0xd2, + 0x88, 0x7d, 0xc6, 0xc3, 0x24, 0x8a, 0xbb, 0x5a, 0xaf, 0x3a, 0x68, 0xda, 0x9d, 0x2c, 0x35, 0x9a, + 0x47, 0xa3, 0x93, 0x02, 0x24, 0x65, 0x1c, 0x0f, 0x51, 0x8b, 0x46, 0xec, 0x11, 0x70, 0x59, 0x4a, + 0x51, 0x68, 0xd3, 0x7e, 0x2d, 0x4b, 0x8d, 0xd6, 0xd1, 0xe8, 0x64, 0x01, 0x93, 0xd5, 0x3b, 0x52, + 0x9f, 0x43, 0x1c, 0x26, 0xdc, 0x81, 0xb8, 0x5b, 0x2d, 0xf5, 0xc9, 0x02, 0x24, 0x65, 0xbc, 0xff, + 0x8b, 0x86, 0xb0, 0xac, 0xea, 0x31, 0x13, 0xd3, 0x87, 0x11, 0x14, 0x0e, 0x62, 0xfc, 0x29, 0x42, + 0xe1, 0xf2, 0xa4, 0x8a, 0x34, 0xf2, 0xf9, 0x58, 0xa2, 0xcf, 0x53, 0xa3, 0xb3, 0x3c, 0x7d, 0x79, + 0x11, 0x01, 0x59, 0xa1, 0xe0, 0x11, 0xaa, 0xf1, 0xc4, 0x83, 0xee, 0xad, 0x8d, 0x9f, 0xf6, 0x92, + 0xce, 0xca, 0x62, 0xec, 0xb6, 0xea, 0x60, 0xde, 0x30, 0x92, 0x2b, 0xf5, 0x7f, 0xd4, 0xd0, 0xed, + 0x33, 0xe0, 0x73, 0xe6, 0x00, 0x81, 0x73, 0xe0, 0x10, 0x38, 0x80, 0x2d, 0xd4, 0x0c, 0xa8, 0x0f, + 0x71, 0x44, 0x1d, 0xc8, 0x07, 0xa4, 0x69, 0xef, 0x2b, 0x6e, 0xf3, 0xc1, 0x22, 0x40, 0xca, 0x3b, + 0xb8, 0x87, 0x6a, 0xf2, 0x90, 0xd7, 0xd5, 0x2c, 0xf3, 0xc8, 0xbb, 0x24, 0x8f, 0xe0, 0x3b, 0xa8, + 0x16, 0x51, 0x31, 0xed, 0x56, 0xf3, 0x1b, 0x0d, 0x19, 0x1d, 0x51, 0x31, 0x25, 0x39, 0xda, 0xff, + 0x43, 0x43, 0xfa, 0x23, 0xea, 0xb1, 0xc9, 0xff, 0x6e, 0x1f, 0xff, 0xd1, 0x50, 0x7f, 0xbb, 0xb3, + 0xff, 0x60, 0x23, 0xfd, 0xf5, 0x8d, 0xfc, 0x7c, 0x77, 0x5b, 0xdb, 0x4b, 0xbf, 0x61, 0x27, 0x7f, + 0xab, 0xa2, 0xba, 0xba, 0xbe, 0x9c, 0x0c, 0xed, 0xc6, 0xc9, 0x78, 0x82, 0xda, 0x8e, 0xc7, 0x20, + 0x10, 0x85, 0xb4, 0x9a, 0xed, 0x4f, 0x5e, 0xb9, 0xf5, 0xc7, 0x2b, 0x22, 0xf6, 0x1b, 0x2a, 0x51, + 0x7b, 0x15, 0x25, 0x6b, 0x89, 0x30, 0x45, 0x7b, 0x72, 0x05, 0x8a, 0x6d, 0x6e, 0x1d, 0x7e, 0xfc, + 0x6a, 0xdb, 0xb4, 0xbe, 0xda, 0x65, 0x27, 0x64, 0x2c, 0x26, 0x85, 0x32, 0x3e, 0x45, 0x9d, 0x73, + 0xca, 0xbc, 0x84, 0xc3, 0x28, 0xf4, 0x98, 0x73, 0xd1, 0xad, 0xe5, 0x6d, 0x78, 0x3b, 0x4b, 0x8d, + 0xce, 0xbd, 0xd5, 0xc0, 0xf3, 0xd4, 0xd8, 0x5f, 0x03, 0xf2, 0xd5, 0x5f, 0x27, 0xe3, 0xef, 0xd1, + 0xfe, 0x72, 0xe5, 0xce, 0xc0, 0x03, 0x47, 0x84, 0xbc, 0xbb, 0x97, 0xb7, 0xeb, 0xbd, 0x1d, 0xa7, + 0x85, 0x8e, 0xc1, 0x5b, 0x50, 0xed, 0x37, 0xb3, 0xd4, 0xd8, 0x7f, 0x70, 0x5d, 0x91, 0x6c, 0x26, + 0xe9, 0xff, 0xaa, 0xa1, 0xd7, 0x5f, 0xd0, 0x66, 0x4c, 0x51, 0x3d, 0x2e, 0x1e, 0x0f, 0x35, 0xb5, + 0x1f, 0xed, 0xde, 0xc4, 0xeb, 0xaf, 0x8e, 0xdd, 0xca, 0x52, 0xa3, 0xbe, 0x40, 0x17, 0xba, 0x78, + 0x80, 0x1a, 0x0e, 0xb5, 0x93, 0x60, 0xa2, 0x9e, 0xbd, 0xb6, 0xdd, 0x96, 0x53, 0x7e, 0x7c, 0x54, + 0x60, 0x64, 0x19, 0xc5, 0x6f, 0xa1, 0x6a, 0xc2, 0x3d, 0xf5, 0xc2, 0xd4, 0xb3, 0xd4, 0xa8, 0x7e, + 0x45, 0x4e, 0x89, 0xc4, 0xec, 0xbb, 0x97, 0x57, 0x7a, 0xe5, 0xe9, 0x95, 0x5e, 0x79, 0x76, 0xa5, + 0x57, 0x7e, 0xc8, 0x74, 0xed, 0x32, 0xd3, 0xb5, 0xa7, 0x99, 0xae, 0x3d, 0xcb, 0x74, 0xed, 0xcf, + 0x4c, 0xd7, 0x7e, 0xfa, 0x4b, 0xaf, 0x7c, 0x5d, 0x57, 0xa5, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, + 0xeb, 0x1f, 0xdb, 0x50, 0x68, 0x09, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/admissionregistration/v1beta1/generated.proto b/vendor/k8s.io/api/admissionregistration/v1beta1/generated.proto index 3d6cbc1e6..2866b8738 100644 --- a/vendor/k8s.io/api/admissionregistration/v1beta1/generated.proto +++ b/vendor/k8s.io/api/admissionregistration/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,12 +21,9 @@ syntax = 'proto2'; package k8s.io.api.admissionregistration.v1beta1; -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; @@ -250,9 +247,7 @@ message WebhookClientConfig { // // If the webhook is running within the cluster, then you should use `service`. // - // If there is only one port open for the service, that port will be - // used. If there are multiple ports open, port 443 will be used if it - // is open, otherwise it is an error. + // Port 443 will be used if it is open, otherwise it is an error. // // +optional optional ServiceReference service = 1; diff --git a/vendor/k8s.io/api/admissionregistration/v1beta1/types.go b/vendor/k8s.io/api/admissionregistration/v1beta1/types.go index 9a4a1ddb4..f209e7acc 100644 --- a/vendor/k8s.io/api/admissionregistration/v1beta1/types.go +++ b/vendor/k8s.io/api/admissionregistration/v1beta1/types.go @@ -254,9 +254,7 @@ type WebhookClientConfig struct { // // If the webhook is running within the cluster, then you should use `service`. // - // If there is only one port open for the service, that port will be - // used. If there are multiple ports open, port 443 will be used if it - // is open, otherwise it is an error. + // Port 443 will be used if it is open, otherwise it is an error. // // +optional Service *ServiceReference `json:"service" protobuf:"bytes,1,opt,name=service"` diff --git a/vendor/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go index b32051424..e90bdc911 100644 --- a/vendor/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_MutatingWebhookConfiguration = map[string]string{ "": "MutatingWebhookConfiguration describes the configuration of and admission webhook that accept or reject and may change the object.", "metadata": "Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata.", @@ -114,7 +114,7 @@ func (Webhook) SwaggerDoc() map[string]string { var map_WebhookClientConfig = map[string]string{ "": "WebhookClientConfig contains the information to make a TLS connection with the webhook", "url": "`url` gives the location of the webhook, in standard URL form (`[scheme://]host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.", - "service": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nIf there is only one port open for the service, that port will be used. If there are multiple ports open, port 443 will be used if it is open, otherwise it is an error.", + "service": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nPort 443 will be used if it is open, otherwise it is an error.", "caBundle": "`caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate. Required.", } diff --git a/vendor/k8s.io/api/admissionregistration/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/admissionregistration/v1beta1/zz_generated.deepcopy.go index d8345d209..d8c1e4f62 100644 --- a/vendor/k8s.io/api/admissionregistration/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/admissionregistration/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/apps/v1/generated.pb.go b/vendor/k8s.io/api/apps/v1/generated.pb.go index 02123859b..eac6ef2a1 100644 --- a/vendor/k8s.io/api/apps/v1/generated.pb.go +++ b/vendor/k8s.io/api/apps/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -61,7 +61,6 @@ import fmt "fmt" import math "math" import k8s_io_api_core_v1 "k8s.io/api/core/v1" - import k8s_io_apimachinery_pkg_apis_meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" import k8s_io_apimachinery_pkg_util_intstr "k8s.io/apimachinery/pkg/util/intstr" @@ -6812,134 +6811,133 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2051 bytes of a gzipped FileDescriptorProto + // 2037 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcd, 0x6f, 0x24, 0x47, 0x1d, 0x75, 0xcf, 0x87, 0x3d, 0x2e, 0xaf, 0xed, 0xdd, 0xb2, 0xb1, 0x27, 0xbb, 0x64, 0x66, 0x19, - 0x60, 0xe3, 0xcd, 0x66, 0x7b, 0xf0, 0x66, 0x13, 0xa1, 0x2c, 0x02, 0x79, 0xc6, 0x21, 0x84, 0x78, - 0x6c, 0x53, 0x5e, 0xef, 0x61, 0x09, 0x12, 0x35, 0x33, 0xb5, 0xe3, 0x8e, 0xfb, 0x4b, 0xdd, 0xd5, - 0xc3, 0x8e, 0xb8, 0x20, 0x24, 0x38, 0x71, 0xe0, 0x3f, 0x41, 0x08, 0xc1, 0x0d, 0x45, 0x88, 0xcb, - 0x5e, 0x90, 0x22, 0x2e, 0xe4, 0x64, 0xb1, 0x93, 0x13, 0x42, 0x39, 0x72, 0xc9, 0x05, 0x54, 0xd5, - 0xd5, 0xdf, 0xd5, 0x9e, 0xb1, 0x37, 0xeb, 0xa0, 0x68, 0x6f, 0x9e, 0xaa, 0xf7, 0x7b, 0xfd, 0xab, - 0xaa, 0x5f, 0xd5, 0x7b, 0x5d, 0x6d, 0x70, 0xef, 0xf8, 0xdb, 0xae, 0xaa, 0x59, 0xcd, 0x63, 0xaf, - 0x4b, 0x1c, 0x93, 0x50, 0xe2, 0x36, 0x87, 0xc4, 0xec, 0x5b, 0x4e, 0x53, 0x74, 0x60, 0x5b, 0x6b, - 0x62, 0xdb, 0x76, 0x9b, 0xc3, 0xcd, 0xe6, 0x80, 0x98, 0xc4, 0xc1, 0x94, 0xf4, 0x55, 0xdb, 0xb1, - 0xa8, 0x05, 0xa1, 0x8f, 0x51, 0xb1, 0xad, 0xa9, 0x0c, 0xa3, 0x0e, 0x37, 0xaf, 0xde, 0x1e, 0x68, - 0xf4, 0xc8, 0xeb, 0xaa, 0x3d, 0xcb, 0x68, 0x0e, 0xac, 0x81, 0xd5, 0xe4, 0xd0, 0xae, 0xf7, 0x88, - 0xff, 0xe2, 0x3f, 0xf8, 0x5f, 0x3e, 0xc5, 0xd5, 0x46, 0xec, 0x31, 0x3d, 0xcb, 0x21, 0x92, 0xc7, - 0x5c, 0xbd, 0x19, 0xc3, 0xd8, 0x96, 0xae, 0xf5, 0x46, 0xcd, 0xe1, 0x66, 0x97, 0x50, 0x9c, 0x85, - 0xde, 0x8d, 0xa0, 0x06, 0xee, 0x1d, 0x69, 0x26, 0x71, 0x46, 0x4d, 0xfb, 0x78, 0xc0, 0x1a, 0xdc, - 0xa6, 0x41, 0x28, 0x96, 0x3d, 0xa0, 0x99, 0x17, 0xe5, 0x78, 0x26, 0xd5, 0x0c, 0x92, 0x09, 0x78, - 0x73, 0x52, 0x80, 0xdb, 0x3b, 0x22, 0x06, 0xce, 0xc4, 0xbd, 0x9e, 0x17, 0xe7, 0x51, 0x4d, 0x6f, - 0x6a, 0x26, 0x75, 0xa9, 0x93, 0x0e, 0x6a, 0xfc, 0x47, 0x01, 0xb0, 0x6d, 0x99, 0xd4, 0xb1, 0x74, - 0x9d, 0x38, 0x88, 0x0c, 0x35, 0x57, 0xb3, 0x4c, 0xf8, 0x53, 0x50, 0x61, 0xe3, 0xe9, 0x63, 0x8a, - 0xab, 0xca, 0x75, 0x65, 0x63, 0xe1, 0xce, 0xb7, 0xd4, 0x68, 0x3d, 0x42, 0x7a, 0xd5, 0x3e, 0x1e, - 0xb0, 0x06, 0x57, 0x65, 0x68, 0x75, 0xb8, 0xa9, 0xee, 0x75, 0x3f, 0x20, 0x3d, 0xda, 0x21, 0x14, - 0xb7, 0xe0, 0x93, 0x93, 0xfa, 0xcc, 0xf8, 0xa4, 0x0e, 0xa2, 0x36, 0x14, 0xb2, 0xc2, 0x3d, 0x50, - 0xe2, 0xec, 0x05, 0xce, 0x7e, 0x3b, 0x97, 0x5d, 0x0c, 0x5a, 0x45, 0xf8, 0x67, 0x6f, 0x3f, 0xa6, - 0xc4, 0x64, 0xe9, 0xb5, 0x2e, 0x09, 0xea, 0xd2, 0x36, 0xa6, 0x18, 0x71, 0x22, 0xf8, 0x1a, 0xa8, - 0x38, 0x22, 0xfd, 0x6a, 0xf1, 0xba, 0xb2, 0x51, 0x6c, 0x5d, 0x16, 0xa8, 0x4a, 0x30, 0x2c, 0x14, - 0x22, 0x1a, 0x7f, 0x55, 0xc0, 0x5a, 0x76, 0xdc, 0x3b, 0x9a, 0x4b, 0xe1, 0xfb, 0x99, 0xb1, 0xab, - 0xd3, 0x8d, 0x9d, 0x45, 0xf3, 0x91, 0x87, 0x0f, 0x0e, 0x5a, 0x62, 0xe3, 0x7e, 0x0f, 0x94, 0x35, - 0x4a, 0x0c, 0xb7, 0x5a, 0xb8, 0x5e, 0xdc, 0x58, 0xb8, 0x73, 0x43, 0xcd, 0x96, 0xb9, 0x9a, 0x4d, - 0xac, 0xb5, 0x28, 0x28, 0xcb, 0xef, 0xb2, 0x60, 0xe4, 0x73, 0x34, 0xfe, 0xab, 0x80, 0xf9, 0x6d, - 0x4c, 0x0c, 0xcb, 0x3c, 0x20, 0xf4, 0x02, 0x16, 0xad, 0x0d, 0x4a, 0xae, 0x4d, 0x7a, 0x62, 0xd1, - 0xbe, 0x26, 0xcb, 0x3d, 0x4c, 0xe7, 0xc0, 0x26, 0xbd, 0x68, 0xa1, 0xd8, 0x2f, 0xc4, 0x83, 0xe1, - 0x7b, 0x60, 0xd6, 0xa5, 0x98, 0x7a, 0x2e, 0x5f, 0xa6, 0x85, 0x3b, 0x5f, 0x3f, 0x9d, 0x86, 0x43, - 0x5b, 0x4b, 0x82, 0x68, 0xd6, 0xff, 0x8d, 0x04, 0x45, 0xe3, 0x5f, 0x05, 0x00, 0x43, 0x6c, 0xdb, - 0x32, 0xfb, 0x1a, 0x65, 0xf5, 0xfb, 0x16, 0x28, 0xd1, 0x91, 0x4d, 0xf8, 0x34, 0xcc, 0xb7, 0x6e, - 0x04, 0x59, 0xdc, 0x1f, 0xd9, 0xe4, 0xb3, 0x93, 0xfa, 0x5a, 0x36, 0x82, 0xf5, 0x20, 0x1e, 0x03, - 0x77, 0xc2, 0xfc, 0x0a, 0x3c, 0xfa, 0x6e, 0xf2, 0xd1, 0x9f, 0x9d, 0xd4, 0x25, 0xe7, 0x8a, 0x1a, - 0x32, 0x25, 0x13, 0x84, 0x43, 0x00, 0x75, 0xec, 0xd2, 0xfb, 0x0e, 0x36, 0x5d, 0xff, 0x49, 0x9a, - 0x41, 0xc4, 0xc8, 0x5f, 0x9d, 0x6e, 0x79, 0x58, 0x44, 0xeb, 0xaa, 0xc8, 0x02, 0xee, 0x64, 0xd8, - 0x90, 0xe4, 0x09, 0xf0, 0x06, 0x98, 0x75, 0x08, 0x76, 0x2d, 0xb3, 0x5a, 0xe2, 0xa3, 0x08, 0x27, - 0x10, 0xf1, 0x56, 0x24, 0x7a, 0xe1, 0x4d, 0x30, 0x67, 0x10, 0xd7, 0xc5, 0x03, 0x52, 0x2d, 0x73, - 0xe0, 0xb2, 0x00, 0xce, 0x75, 0xfc, 0x66, 0x14, 0xf4, 0x37, 0x7e, 0xaf, 0x80, 0xc5, 0x70, 0xe6, - 0x2e, 0x60, 0xab, 0xb4, 0x92, 0x5b, 0xe5, 0xe5, 0x53, 0xeb, 0x24, 0x67, 0x87, 0x7c, 0x58, 0x8c, - 0xe5, 0xcc, 0x8a, 0x10, 0xfe, 0x04, 0x54, 0x5c, 0xa2, 0x93, 0x1e, 0xb5, 0x1c, 0x91, 0xf3, 0xeb, - 0x53, 0xe6, 0x8c, 0xbb, 0x44, 0x3f, 0x10, 0xa1, 0xad, 0x4b, 0x2c, 0xe9, 0xe0, 0x17, 0x0a, 0x29, - 0xe1, 0x8f, 0x40, 0x85, 0x12, 0xc3, 0xd6, 0x31, 0x25, 0x62, 0x9b, 0x24, 0xea, 0x9b, 0x95, 0x0b, - 0x23, 0xdb, 0xb7, 0xfa, 0xf7, 0x05, 0x8c, 0x6f, 0x94, 0x70, 0x1e, 0x82, 0x56, 0x14, 0xd2, 0xc0, - 0x63, 0xb0, 0xe4, 0xd9, 0x7d, 0x86, 0xa4, 0xec, 0xe8, 0x1e, 0x8c, 0x44, 0xf9, 0xdc, 0x3a, 0x75, - 0x42, 0x0e, 0x13, 0x21, 0xad, 0x35, 0xf1, 0x80, 0xa5, 0x64, 0x3b, 0x4a, 0x51, 0xc3, 0x2d, 0xb0, - 0x6c, 0x68, 0x26, 0x22, 0xb8, 0x3f, 0x3a, 0x20, 0x3d, 0xcb, 0xec, 0xbb, 0xbc, 0x80, 0xca, 0xad, - 0x75, 0x41, 0xb0, 0xdc, 0x49, 0x76, 0xa3, 0x34, 0x1e, 0xee, 0x80, 0xd5, 0xe0, 0x9c, 0xfd, 0x81, - 0xe6, 0x52, 0xcb, 0x19, 0xed, 0x68, 0x86, 0x46, 0xab, 0xb3, 0x9c, 0xa7, 0x3a, 0x3e, 0xa9, 0xaf, - 0x22, 0x49, 0x3f, 0x92, 0x46, 0x35, 0x7e, 0x33, 0x0b, 0x96, 0x53, 0xa7, 0x01, 0x7c, 0x00, 0xd6, - 0x7a, 0x9e, 0xe3, 0x10, 0x93, 0xee, 0x7a, 0x46, 0x97, 0x38, 0x07, 0xbd, 0x23, 0xd2, 0xf7, 0x74, - 0xd2, 0xe7, 0x2b, 0x5a, 0x6e, 0xd5, 0x44, 0xae, 0x6b, 0x6d, 0x29, 0x0a, 0xe5, 0x44, 0xc3, 0x1f, - 0x02, 0x68, 0xf2, 0xa6, 0x8e, 0xe6, 0xba, 0x21, 0x67, 0x81, 0x73, 0x86, 0x1b, 0x70, 0x37, 0x83, - 0x40, 0x92, 0x28, 0x96, 0x63, 0x9f, 0xb8, 0x9a, 0x43, 0xfa, 0xe9, 0x1c, 0x8b, 0xc9, 0x1c, 0xb7, - 0xa5, 0x28, 0x94, 0x13, 0x0d, 0xdf, 0x00, 0x0b, 0xfe, 0xd3, 0xf8, 0x9c, 0x8b, 0xc5, 0x59, 0x11, - 0x64, 0x0b, 0xbb, 0x51, 0x17, 0x8a, 0xe3, 0xd8, 0xd0, 0xac, 0xae, 0x4b, 0x9c, 0x21, 0xe9, 0xbf, - 0xe3, 0x7b, 0x00, 0x26, 0x94, 0x65, 0x2e, 0x94, 0xe1, 0xd0, 0xf6, 0x32, 0x08, 0x24, 0x89, 0x62, - 0x43, 0xf3, 0xab, 0x26, 0x33, 0xb4, 0xd9, 0xe4, 0xd0, 0x0e, 0xa5, 0x28, 0x94, 0x13, 0xcd, 0x6a, - 0xcf, 0x4f, 0x79, 0x6b, 0x88, 0x35, 0x1d, 0x77, 0x75, 0x52, 0x9d, 0x4b, 0xd6, 0xde, 0x6e, 0xb2, - 0x1b, 0xa5, 0xf1, 0xf0, 0x1d, 0x70, 0xc5, 0x6f, 0x3a, 0x34, 0x71, 0x48, 0x52, 0xe1, 0x24, 0x2f, - 0x09, 0x92, 0x2b, 0xbb, 0x69, 0x00, 0xca, 0xc6, 0xc0, 0xb7, 0xc0, 0x52, 0xcf, 0xd2, 0x75, 0x5e, - 0x8f, 0x6d, 0xcb, 0x33, 0x69, 0x75, 0x9e, 0xb3, 0x40, 0xb6, 0x87, 0xda, 0x89, 0x1e, 0x94, 0x42, - 0xc2, 0x87, 0x00, 0xf4, 0x02, 0x39, 0x70, 0xab, 0x20, 0x5f, 0xe8, 0xb3, 0x3a, 0x14, 0x09, 0x70, - 0xd8, 0xe4, 0xa2, 0x18, 0x5b, 0xe3, 0x43, 0x05, 0xac, 0xe7, 0xec, 0x71, 0xf8, 0xbd, 0x84, 0xea, - 0xdd, 0x4a, 0xa9, 0xde, 0xb5, 0x9c, 0xb0, 0x98, 0xf4, 0xf5, 0xc0, 0x22, 0xf3, 0x1d, 0x9a, 0x39, - 0xf0, 0x21, 0xe2, 0x04, 0x7b, 0x55, 0x96, 0x3b, 0x8a, 0x03, 0xa3, 0x63, 0xf8, 0xca, 0xf8, 0xa4, - 0xbe, 0x98, 0xe8, 0x43, 0x49, 0xce, 0xc6, 0x2f, 0x0b, 0x00, 0x6c, 0x13, 0x5b, 0xb7, 0x46, 0x06, - 0x31, 0x2f, 0xc2, 0xb5, 0x6c, 0x27, 0x5c, 0x4b, 0x43, 0xba, 0x10, 0x61, 0x3e, 0xb9, 0xb6, 0x65, - 0x27, 0x65, 0x5b, 0xbe, 0x31, 0x81, 0xe7, 0x74, 0xdf, 0xf2, 0x8f, 0x22, 0x58, 0x89, 0xc0, 0x91, - 0x71, 0xb9, 0x97, 0x58, 0xc2, 0x57, 0x52, 0x4b, 0xb8, 0x2e, 0x09, 0x79, 0x6e, 0xce, 0xe5, 0xf3, - 0x77, 0x10, 0xf0, 0x03, 0xb0, 0xc4, 0xac, 0x8a, 0x5f, 0x08, 0xdc, 0x08, 0xcd, 0x9e, 0xd9, 0x08, - 0x85, 0x42, 0xb6, 0x93, 0x60, 0x42, 0x29, 0xe6, 0x1c, 0xe3, 0x35, 0xf7, 0xbc, 0x8d, 0x57, 0xe3, - 0x0f, 0x0a, 0x58, 0x8a, 0x96, 0xe9, 0x02, 0x6c, 0x52, 0x3b, 0x69, 0x93, 0x6a, 0xa7, 0xd7, 0x65, - 0x8e, 0x4f, 0xfa, 0x7b, 0x29, 0x9e, 0x35, 0x37, 0x4a, 0x1b, 0xec, 0x85, 0xca, 0xd6, 0xb5, 0x1e, - 0x76, 0x85, 0xac, 0x5e, 0xf2, 0x5f, 0xa6, 0xfc, 0x36, 0x14, 0xf6, 0x26, 0x2c, 0x55, 0xe1, 0xf9, - 0x5a, 0xaa, 0xe2, 0xe7, 0x63, 0xa9, 0xee, 0x83, 0x8a, 0x1b, 0x98, 0xa9, 0x12, 0xa7, 0xbc, 0x31, - 0x69, 0x3b, 0x0b, 0x1f, 0x15, 0xb2, 0x86, 0x0e, 0x2a, 0x64, 0x92, 0x79, 0xa7, 0xf2, 0x17, 0xe9, - 0x9d, 0xd8, 0x16, 0xb6, 0xb1, 0xe7, 0x92, 0x3e, 0xaf, 0xfb, 0x4a, 0xb4, 0x85, 0xf7, 0x79, 0x2b, - 0x12, 0xbd, 0xf0, 0x10, 0xac, 0xdb, 0x8e, 0x35, 0x70, 0x88, 0xeb, 0x6e, 0x13, 0xdc, 0xd7, 0x35, - 0x93, 0x04, 0x03, 0xf0, 0x55, 0xef, 0xda, 0xf8, 0xa4, 0xbe, 0xbe, 0x2f, 0x87, 0xa0, 0xbc, 0xd8, - 0xc6, 0x9f, 0x4b, 0xe0, 0x72, 0xfa, 0x44, 0xcc, 0x31, 0x22, 0xca, 0xb9, 0x8c, 0xc8, 0x6b, 0xb1, - 0x12, 0xf5, 0x5d, 0x5a, 0xec, 0x9d, 0x3f, 0x53, 0xa6, 0x5b, 0x60, 0x59, 0x18, 0x8f, 0xa0, 0x53, - 0x58, 0xb1, 0x70, 0x79, 0x0e, 0x93, 0xdd, 0x28, 0x8d, 0x67, 0xf6, 0x22, 0x72, 0x0d, 0x01, 0x49, - 0x29, 0x69, 0x2f, 0xb6, 0xd2, 0x00, 0x94, 0x8d, 0x81, 0x1d, 0xb0, 0xe2, 0x99, 0x59, 0x2a, 0xbf, - 0x5c, 0xae, 0x09, 0xaa, 0x95, 0xc3, 0x2c, 0x04, 0xc9, 0xe2, 0xe0, 0x8f, 0x13, 0x8e, 0x63, 0x96, - 0x1f, 0x04, 0xaf, 0x9c, 0x5e, 0xd1, 0x53, 0x5b, 0x0e, 0x78, 0x0f, 0x2c, 0x3a, 0xdc, 0x50, 0x06, - 0x59, 0xfa, 0xa6, 0xec, 0x2b, 0x22, 0x6c, 0x11, 0xc5, 0x3b, 0x51, 0x12, 0x2b, 0xf1, 0x51, 0x95, - 0x69, 0x7d, 0x54, 0xe3, 0x4f, 0x0a, 0x80, 0xd9, 0x2d, 0x38, 0xf1, 0xe5, 0x3e, 0x13, 0x11, 0x93, - 0xc8, 0xbe, 0xdc, 0xe1, 0xdc, 0x9a, 0xec, 0x70, 0xa2, 0x13, 0x74, 0x3a, 0x8b, 0x23, 0x66, 0xe0, - 0x62, 0x2e, 0x66, 0xa6, 0xb0, 0x38, 0x51, 0x3e, 0xcf, 0x66, 0x71, 0x62, 0x3c, 0xa7, 0x5b, 0x9c, - 0x7f, 0x17, 0xc0, 0x4a, 0x04, 0x9e, 0xda, 0xe2, 0x48, 0x42, 0x5e, 0x5c, 0xce, 0x4c, 0xbe, 0x9c, - 0x61, 0xb6, 0x23, 0x9a, 0xba, 0xff, 0x13, 0xdb, 0x11, 0x25, 0x94, 0x63, 0x3b, 0x7e, 0x57, 0x88, - 0x67, 0xfd, 0xa5, 0xb7, 0x1d, 0xcf, 0x7e, 0xb9, 0xd2, 0xf8, 0x4b, 0x11, 0x5c, 0x4e, 0x6f, 0xc1, - 0x84, 0x0e, 0x2a, 0x13, 0x75, 0x70, 0x1f, 0xac, 0x3e, 0xf2, 0x74, 0x7d, 0xc4, 0xa7, 0x21, 0x26, - 0x86, 0xbe, 0x82, 0x7e, 0x55, 0x44, 0xae, 0x7e, 0x5f, 0x82, 0x41, 0xd2, 0xc8, 0x1c, 0x4d, 0x2f, - 0x9e, 0x4b, 0xd3, 0x33, 0x6a, 0x53, 0x3a, 0x83, 0xda, 0x48, 0xf5, 0xb9, 0x7c, 0x0e, 0x7d, 0x9e, - 0x5a, 0x50, 0x25, 0xc7, 0xd5, 0xc4, 0x77, 0xf8, 0x5f, 0x2b, 0x60, 0x4d, 0xfe, 0xfa, 0x0c, 0x75, - 0xb0, 0x64, 0xe0, 0xc7, 0xf1, 0xcb, 0x8b, 0x49, 0x82, 0xe1, 0x51, 0x4d, 0x57, 0xfd, 0xaf, 0x3b, - 0xea, 0xbb, 0x26, 0xdd, 0x73, 0x0e, 0xa8, 0xa3, 0x99, 0x03, 0x5f, 0x60, 0x3b, 0x09, 0x2e, 0x94, - 0xe2, 0x6e, 0x7c, 0xa2, 0x80, 0xf5, 0x1c, 0x95, 0xbb, 0xd8, 0x4c, 0xe0, 0x43, 0x50, 0x31, 0xf0, - 0xe3, 0x03, 0xcf, 0x19, 0x04, 0x92, 0x7c, 0xf6, 0xe7, 0xf0, 0x8d, 0xdc, 0x11, 0x2c, 0x28, 0xe4, - 0x6b, 0xec, 0x81, 0xeb, 0x89, 0x41, 0xb2, 0x4d, 0x43, 0x1e, 0x79, 0x3a, 0xdf, 0x3f, 0xc2, 0x53, - 0xdc, 0x02, 0xf3, 0x36, 0x76, 0xa8, 0x16, 0x9a, 0xd1, 0x72, 0x6b, 0x71, 0x7c, 0x52, 0x9f, 0xdf, - 0x0f, 0x1a, 0x51, 0xd4, 0xdf, 0xf8, 0x55, 0x01, 0x2c, 0xc4, 0x48, 0x2e, 0x40, 0xdf, 0xdf, 0x4e, - 0xe8, 0xbb, 0xf4, 0x8b, 0x49, 0x7c, 0x54, 0x79, 0x02, 0xdf, 0x49, 0x09, 0xfc, 0x37, 0x27, 0x11, - 0x9d, 0xae, 0xf0, 0x9f, 0x16, 0xc0, 0x6a, 0x0c, 0x1d, 0x49, 0xfc, 0x77, 0x12, 0x12, 0xbf, 0x91, - 0x92, 0xf8, 0xaa, 0x2c, 0xe6, 0x85, 0xc6, 0x4f, 0xd6, 0xf8, 0x3f, 0x2a, 0x60, 0x39, 0x36, 0x77, - 0x17, 0x20, 0xf2, 0xdb, 0x49, 0x91, 0xaf, 0x4f, 0xa8, 0x97, 0x1c, 0x95, 0x7f, 0x52, 0x4e, 0xe4, - 0xfd, 0xa5, 0x97, 0xf9, 0x9f, 0x83, 0xd5, 0xa1, 0xa5, 0x7b, 0x06, 0x69, 0xeb, 0x58, 0x33, 0x02, - 0x00, 0x53, 0x32, 0x36, 0x89, 0x37, 0xa5, 0xf4, 0xc4, 0x71, 0x35, 0x97, 0x12, 0x93, 0x3e, 0x88, - 0x22, 0x23, 0x2d, 0x7e, 0x20, 0xa1, 0x43, 0xd2, 0x87, 0xc0, 0x37, 0xc0, 0x02, 0xd3, 0x54, 0xad, - 0x47, 0x76, 0xb1, 0x11, 0xd4, 0x54, 0xf8, 0x7d, 0xe0, 0x20, 0xea, 0x42, 0x71, 0x1c, 0x3c, 0x02, - 0x2b, 0xb6, 0xd5, 0xef, 0x60, 0x13, 0x0f, 0x08, 0x3b, 0xff, 0xf7, 0xf9, 0xff, 0x42, 0xf0, 0x7b, - 0x87, 0xf9, 0xd6, 0x9b, 0xc1, 0x0b, 0xe9, 0x7e, 0x16, 0xc2, 0x3c, 0xbb, 0xa4, 0x99, 0xef, 0x67, - 0x19, 0x25, 0x34, 0x32, 0x9f, 0xb3, 0xe6, 0x32, 0xff, 0x03, 0x20, 0x2b, 0xae, 0x73, 0x7e, 0xd0, - 0xca, 0xbb, 0x51, 0xa9, 0x9c, 0xeb, 0x6b, 0xd4, 0xa7, 0x25, 0x70, 0x25, 0x73, 0x40, 0x7e, 0x81, - 0x77, 0x1a, 0x19, 0xb7, 0x54, 0x3c, 0x83, 0x5b, 0xda, 0x02, 0xcb, 0xe2, 0x43, 0x58, 0xca, 0x6c, - 0x85, 0x76, 0xb4, 0x9d, 0xec, 0x46, 0x69, 0xbc, 0xec, 0x4e, 0xa5, 0x7c, 0xc6, 0x3b, 0x95, 0x78, - 0x16, 0xe2, 0xff, 0x37, 0xfc, 0xaa, 0xcb, 0x66, 0x21, 0xfe, 0x8d, 0x23, 0x8d, 0x87, 0xdf, 0x0d, - 0x4a, 0x2a, 0x64, 0x98, 0xe3, 0x0c, 0xa9, 0x1a, 0x09, 0x09, 0x52, 0xe8, 0x67, 0xfa, 0xd8, 0xf3, - 0xbe, 0xe4, 0x63, 0xcf, 0xc6, 0x84, 0x52, 0x9e, 0xde, 0x2a, 0xfe, 0x4d, 0x01, 0x2f, 0xe5, 0xee, - 0x01, 0xb8, 0x95, 0xd0, 0xd9, 0xdb, 0x29, 0x9d, 0x7d, 0x39, 0x37, 0x30, 0x26, 0xb6, 0x86, 0xfc, - 0x42, 0xe4, 0xee, 0xc4, 0x0b, 0x11, 0x89, 0x8b, 0x9a, 0x7c, 0x33, 0xd2, 0xda, 0x78, 0xf2, 0xb4, - 0x36, 0xf3, 0xd1, 0xd3, 0xda, 0xcc, 0xc7, 0x4f, 0x6b, 0x33, 0xbf, 0x18, 0xd7, 0x94, 0x27, 0xe3, - 0x9a, 0xf2, 0xd1, 0xb8, 0xa6, 0x7c, 0x3c, 0xae, 0x29, 0xff, 0x1c, 0xd7, 0x94, 0xdf, 0x7e, 0x52, - 0x9b, 0x79, 0x58, 0x18, 0x6e, 0xfe, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x70, 0x5f, 0xbf, 0x58, 0x3d, - 0x26, 0x00, 0x00, + 0x60, 0xe3, 0x64, 0xb3, 0x3d, 0xec, 0x66, 0x13, 0xa1, 0x2c, 0x02, 0x79, 0xc6, 0x21, 0x84, 0x78, + 0x6c, 0x53, 0x5e, 0xef, 0x61, 0x09, 0x12, 0xe5, 0xe9, 0xda, 0x71, 0xc7, 0xfd, 0xa5, 0xee, 0xea, + 0x61, 0x47, 0x5c, 0x10, 0x12, 0x9c, 0x38, 0xf0, 0x9f, 0x20, 0x84, 0xe0, 0x86, 0x22, 0xc4, 0x65, + 0x2f, 0x48, 0x11, 0x17, 0x72, 0xb2, 0xd8, 0xc9, 0x09, 0xa1, 0x1c, 0xb9, 0xe4, 0x02, 0xaa, 0xea, + 0xea, 0xef, 0x6a, 0xcf, 0xd8, 0x9b, 0x75, 0x50, 0x94, 0x9b, 0xa7, 0xea, 0xfd, 0x5e, 0xff, 0xaa, + 0xea, 0x57, 0xf5, 0x5e, 0x57, 0x1b, 0xdc, 0x3b, 0xfe, 0xb6, 0xa7, 0xea, 0x76, 0xfb, 0xd8, 0x3f, + 0x24, 0xae, 0x45, 0x28, 0xf1, 0xda, 0x43, 0x62, 0x69, 0xb6, 0xdb, 0x16, 0x1d, 0xd8, 0xd1, 0xdb, + 0xd8, 0x71, 0xbc, 0xf6, 0xf0, 0x76, 0x7b, 0x40, 0x2c, 0xe2, 0x62, 0x4a, 0x34, 0xd5, 0x71, 0x6d, + 0x6a, 0x43, 0x18, 0x60, 0x54, 0xec, 0xe8, 0x2a, 0xc3, 0xa8, 0xc3, 0xdb, 0x57, 0x6f, 0x0d, 0x74, + 0x7a, 0xe4, 0x1f, 0xaa, 0x7d, 0xdb, 0x6c, 0x0f, 0xec, 0x81, 0xdd, 0xe6, 0xd0, 0x43, 0xff, 0x11, + 0xff, 0xc5, 0x7f, 0xf0, 0xbf, 0x02, 0x8a, 0xab, 0xad, 0xc4, 0x63, 0xfa, 0xb6, 0x4b, 0x24, 0x8f, + 0xb9, 0x7a, 0x37, 0xc6, 0x98, 0xb8, 0x7f, 0xa4, 0x5b, 0xc4, 0x1d, 0xb5, 0x9d, 0xe3, 0x01, 0x6b, + 0xf0, 0xda, 0x26, 0xa1, 0x58, 0x16, 0xd5, 0x2e, 0x8a, 0x72, 0x7d, 0x8b, 0xea, 0x26, 0xc9, 0x05, + 0xbc, 0x31, 0x29, 0xc0, 0xeb, 0x1f, 0x11, 0x13, 0xe7, 0xe2, 0x5e, 0x2b, 0x8a, 0xf3, 0xa9, 0x6e, + 0xb4, 0x75, 0x8b, 0x7a, 0xd4, 0xcd, 0x06, 0xb5, 0xfe, 0xa3, 0x00, 0xd8, 0xb5, 0x2d, 0xea, 0xda, + 0x86, 0x41, 0x5c, 0x44, 0x86, 0xba, 0xa7, 0xdb, 0x16, 0xfc, 0x29, 0xa8, 0xb1, 0xf1, 0x68, 0x98, + 0xe2, 0xba, 0x72, 0x5d, 0xd9, 0x58, 0xb8, 0xf3, 0x2d, 0x35, 0x9e, 0xe4, 0x88, 0x5e, 0x75, 0x8e, + 0x07, 0xac, 0xc1, 0x53, 0x19, 0x5a, 0x1d, 0xde, 0x56, 0x77, 0x0f, 0xdf, 0x27, 0x7d, 0xda, 0x23, + 0x14, 0x77, 0xe0, 0x93, 0x93, 0xe6, 0xcc, 0xf8, 0xa4, 0x09, 0xe2, 0x36, 0x14, 0xb1, 0xc2, 0x5d, + 0x50, 0xe1, 0xec, 0x25, 0xce, 0x7e, 0xab, 0x90, 0x5d, 0x0c, 0x5a, 0x45, 0xf8, 0x67, 0x6f, 0x3d, + 0xa6, 0xc4, 0x62, 0xe9, 0x75, 0x2e, 0x09, 0xea, 0xca, 0x16, 0xa6, 0x18, 0x71, 0x22, 0xf8, 0x2a, + 0xa8, 0xb9, 0x22, 0xfd, 0x7a, 0xf9, 0xba, 0xb2, 0x51, 0xee, 0x5c, 0x16, 0xa8, 0x5a, 0x38, 0x2c, + 0x14, 0x21, 0x5a, 0x7f, 0x55, 0xc0, 0x5a, 0x7e, 0xdc, 0xdb, 0xba, 0x47, 0xe1, 0x7b, 0xb9, 0xb1, + 0xab, 0xd3, 0x8d, 0x9d, 0x45, 0xf3, 0x91, 0x47, 0x0f, 0x0e, 0x5b, 0x12, 0xe3, 0x7e, 0x17, 0x54, + 0x75, 0x4a, 0x4c, 0xaf, 0x5e, 0xba, 0x5e, 0xde, 0x58, 0xb8, 0x73, 0x43, 0xcd, 0xd7, 0xae, 0x9a, + 0x4f, 0xac, 0xb3, 0x28, 0x28, 0xab, 0xef, 0xb0, 0x60, 0x14, 0x70, 0xb4, 0xfe, 0xab, 0x80, 0xf9, + 0x2d, 0x4c, 0x4c, 0xdb, 0xda, 0x27, 0xf4, 0x02, 0x16, 0xad, 0x0b, 0x2a, 0x9e, 0x43, 0xfa, 0x62, + 0xd1, 0xbe, 0x26, 0xcb, 0x3d, 0x4a, 0x67, 0xdf, 0x21, 0xfd, 0x78, 0xa1, 0xd8, 0x2f, 0xc4, 0x83, + 0xe1, 0xbb, 0x60, 0xd6, 0xa3, 0x98, 0xfa, 0x1e, 0x5f, 0xa6, 0x85, 0x3b, 0x5f, 0x3f, 0x9d, 0x86, + 0x43, 0x3b, 0x4b, 0x82, 0x68, 0x36, 0xf8, 0x8d, 0x04, 0x45, 0xeb, 0x5f, 0x25, 0x00, 0x23, 0x6c, + 0xd7, 0xb6, 0x34, 0x9d, 0xb2, 0xfa, 0x7d, 0x13, 0x54, 0xe8, 0xc8, 0x21, 0x7c, 0x1a, 0xe6, 0x3b, + 0x37, 0xc2, 0x2c, 0xee, 0x8f, 0x1c, 0xf2, 0xe9, 0x49, 0x73, 0x2d, 0x1f, 0xc1, 0x7a, 0x10, 0x8f, + 0x81, 0xdb, 0x51, 0x7e, 0x25, 0x1e, 0x7d, 0x37, 0xfd, 0xe8, 0x4f, 0x4f, 0x9a, 0x92, 0xc3, 0x42, + 0x8d, 0x98, 0xd2, 0x09, 0xc2, 0x21, 0x80, 0x06, 0xf6, 0xe8, 0x7d, 0x17, 0x5b, 0x5e, 0xf0, 0x24, + 0xdd, 0x24, 0x62, 0xe4, 0xaf, 0x4c, 0xb7, 0x3c, 0x2c, 0xa2, 0x73, 0x55, 0x64, 0x01, 0xb7, 0x73, + 0x6c, 0x48, 0xf2, 0x04, 0x78, 0x03, 0xcc, 0xba, 0x04, 0x7b, 0xb6, 0x55, 0xaf, 0xf0, 0x51, 0x44, + 0x13, 0x88, 0x78, 0x2b, 0x12, 0xbd, 0xf0, 0x65, 0x30, 0x67, 0x12, 0xcf, 0xc3, 0x03, 0x52, 0xaf, + 0x72, 0xe0, 0xb2, 0x00, 0xce, 0xf5, 0x82, 0x66, 0x14, 0xf6, 0xb7, 0x7e, 0xaf, 0x80, 0xc5, 0x68, + 0xe6, 0x2e, 0x60, 0xab, 0x74, 0xd2, 0x5b, 0xe5, 0xc5, 0x53, 0xeb, 0xa4, 0x60, 0x87, 0x7c, 0x50, + 0x4e, 0xe4, 0xcc, 0x8a, 0x10, 0xfe, 0x04, 0xd4, 0x3c, 0x62, 0x90, 0x3e, 0xb5, 0x5d, 0x91, 0xf3, + 0x6b, 0x53, 0xe6, 0x8c, 0x0f, 0x89, 0xb1, 0x2f, 0x42, 0x3b, 0x97, 0x58, 0xd2, 0xe1, 0x2f, 0x14, + 0x51, 0xc2, 0x1f, 0x81, 0x1a, 0x25, 0xa6, 0x63, 0x60, 0x4a, 0xc4, 0x36, 0x49, 0xd5, 0x37, 0x2b, + 0x17, 0x46, 0xb6, 0x67, 0x6b, 0xf7, 0x05, 0x8c, 0x6f, 0x94, 0x68, 0x1e, 0xc2, 0x56, 0x14, 0xd1, + 0xc0, 0x63, 0xb0, 0xe4, 0x3b, 0x1a, 0x43, 0x52, 0x76, 0x74, 0x0f, 0x46, 0xa2, 0x7c, 0x6e, 0x9e, + 0x3a, 0x21, 0x07, 0xa9, 0x90, 0xce, 0x9a, 0x78, 0xc0, 0x52, 0xba, 0x1d, 0x65, 0xa8, 0xe1, 0x26, + 0x58, 0x36, 0x75, 0x0b, 0x11, 0xac, 0x8d, 0xf6, 0x49, 0xdf, 0xb6, 0x34, 0x8f, 0x17, 0x50, 0xb5, + 0xb3, 0x2e, 0x08, 0x96, 0x7b, 0xe9, 0x6e, 0x94, 0xc5, 0xc3, 0x6d, 0xb0, 0x1a, 0x9e, 0xb3, 0x3f, + 0xd0, 0x3d, 0x6a, 0xbb, 0xa3, 0x6d, 0xdd, 0xd4, 0x69, 0x7d, 0x96, 0xf3, 0xd4, 0xc7, 0x27, 0xcd, + 0x55, 0x24, 0xe9, 0x47, 0xd2, 0xa8, 0xd6, 0x6f, 0x66, 0xc1, 0x72, 0xe6, 0x34, 0x80, 0x0f, 0xc0, + 0x5a, 0xdf, 0x77, 0x5d, 0x62, 0xd1, 0x1d, 0xdf, 0x3c, 0x24, 0xee, 0x7e, 0xff, 0x88, 0x68, 0xbe, + 0x41, 0x34, 0xbe, 0xa2, 0xd5, 0x4e, 0x43, 0xe4, 0xba, 0xd6, 0x95, 0xa2, 0x50, 0x41, 0x34, 0xfc, + 0x21, 0x80, 0x16, 0x6f, 0xea, 0xe9, 0x9e, 0x17, 0x71, 0x96, 0x38, 0x67, 0xb4, 0x01, 0x77, 0x72, + 0x08, 0x24, 0x89, 0x62, 0x39, 0x6a, 0xc4, 0xd3, 0x5d, 0xa2, 0x65, 0x73, 0x2c, 0xa7, 0x73, 0xdc, + 0x92, 0xa2, 0x50, 0x41, 0x34, 0x7c, 0x1d, 0x2c, 0x04, 0x4f, 0xe3, 0x73, 0x2e, 0x16, 0x67, 0x45, + 0x90, 0x2d, 0xec, 0xc4, 0x5d, 0x28, 0x89, 0x63, 0x43, 0xb3, 0x0f, 0x3d, 0xe2, 0x0e, 0x89, 0xf6, + 0x76, 0xe0, 0x01, 0x98, 0x50, 0x56, 0xb9, 0x50, 0x46, 0x43, 0xdb, 0xcd, 0x21, 0x90, 0x24, 0x8a, + 0x0d, 0x2d, 0xa8, 0x9a, 0xdc, 0xd0, 0x66, 0xd3, 0x43, 0x3b, 0x90, 0xa2, 0x50, 0x41, 0x34, 0xab, + 0xbd, 0x20, 0xe5, 0xcd, 0x21, 0xd6, 0x0d, 0x7c, 0x68, 0x90, 0xfa, 0x5c, 0xba, 0xf6, 0x76, 0xd2, + 0xdd, 0x28, 0x8b, 0x87, 0x6f, 0x83, 0x2b, 0x41, 0xd3, 0x81, 0x85, 0x23, 0x92, 0x1a, 0x27, 0x79, + 0x41, 0x90, 0x5c, 0xd9, 0xc9, 0x02, 0x50, 0x3e, 0x06, 0xbe, 0x09, 0x96, 0xfa, 0xb6, 0x61, 0xf0, + 0x7a, 0xec, 0xda, 0xbe, 0x45, 0xeb, 0xf3, 0x9c, 0x05, 0xb2, 0x3d, 0xd4, 0x4d, 0xf5, 0xa0, 0x0c, + 0x12, 0x3e, 0x04, 0xa0, 0x1f, 0xca, 0x81, 0x57, 0x07, 0xc5, 0x42, 0x9f, 0xd7, 0xa1, 0x58, 0x80, + 0xa3, 0x26, 0x0f, 0x25, 0xd8, 0x5a, 0x1f, 0x28, 0x60, 0xbd, 0x60, 0x8f, 0xc3, 0xef, 0xa5, 0x54, + 0xef, 0x66, 0x46, 0xf5, 0xae, 0x15, 0x84, 0x25, 0xa4, 0xaf, 0x0f, 0x16, 0x99, 0xef, 0xd0, 0xad, + 0x41, 0x00, 0x11, 0x27, 0xd8, 0x2b, 0xb2, 0xdc, 0x51, 0x12, 0x18, 0x1f, 0xc3, 0x57, 0xc6, 0x27, + 0xcd, 0xc5, 0x54, 0x1f, 0x4a, 0x73, 0xb6, 0x7e, 0x59, 0x02, 0x60, 0x8b, 0x38, 0x86, 0x3d, 0x32, + 0x89, 0x75, 0x11, 0xae, 0x65, 0x2b, 0xe5, 0x5a, 0x5a, 0xd2, 0x85, 0x88, 0xf2, 0x29, 0xb4, 0x2d, + 0xdb, 0x19, 0xdb, 0xf2, 0x8d, 0x09, 0x3c, 0xa7, 0xfb, 0x96, 0x7f, 0x94, 0xc1, 0x4a, 0x0c, 0x8e, + 0x8d, 0xcb, 0xbd, 0xd4, 0x12, 0xbe, 0x94, 0x59, 0xc2, 0x75, 0x49, 0xc8, 0x73, 0x73, 0x2e, 0x9f, + 0xbd, 0x83, 0x80, 0xef, 0x83, 0x25, 0x66, 0x55, 0x82, 0x42, 0xe0, 0x46, 0x68, 0xf6, 0xcc, 0x46, + 0x28, 0x12, 0xb2, 0xed, 0x14, 0x13, 0xca, 0x30, 0x17, 0x18, 0xaf, 0xb9, 0xe7, 0x6d, 0xbc, 0x5a, + 0x7f, 0x50, 0xc0, 0x52, 0xbc, 0x4c, 0x17, 0x60, 0x93, 0xba, 0x69, 0x9b, 0xd4, 0x38, 0xbd, 0x2e, + 0x0b, 0x7c, 0xd2, 0xdf, 0x2b, 0xc9, 0xac, 0xb9, 0x51, 0xda, 0x60, 0x2f, 0x54, 0x8e, 0xa1, 0xf7, + 0xb1, 0x27, 0x64, 0xf5, 0x52, 0xf0, 0x32, 0x15, 0xb4, 0xa1, 0xa8, 0x37, 0x65, 0xa9, 0x4a, 0xcf, + 0xd7, 0x52, 0x95, 0x3f, 0x1b, 0x4b, 0x75, 0x1f, 0xd4, 0xbc, 0xd0, 0x4c, 0x55, 0x38, 0xe5, 0x8d, + 0x49, 0xdb, 0x59, 0xf8, 0xa8, 0x88, 0x35, 0x72, 0x50, 0x11, 0x93, 0xcc, 0x3b, 0x55, 0x3f, 0x4f, + 0xef, 0xc4, 0xb6, 0xb0, 0x83, 0x7d, 0x8f, 0x68, 0xbc, 0xee, 0x6b, 0xf1, 0x16, 0xde, 0xe3, 0xad, + 0x48, 0xf4, 0xc2, 0x03, 0xb0, 0xee, 0xb8, 0xf6, 0xc0, 0x25, 0x9e, 0xb7, 0x45, 0xb0, 0x66, 0xe8, + 0x16, 0x09, 0x07, 0x10, 0xa8, 0xde, 0xb5, 0xf1, 0x49, 0x73, 0x7d, 0x4f, 0x0e, 0x41, 0x45, 0xb1, + 0xad, 0x3f, 0x57, 0xc0, 0xe5, 0xec, 0x89, 0x58, 0x60, 0x44, 0x94, 0x73, 0x19, 0x91, 0x57, 0x13, + 0x25, 0x1a, 0xb8, 0xb4, 0xc4, 0x3b, 0x7f, 0xae, 0x4c, 0x37, 0xc1, 0xb2, 0x30, 0x1e, 0x61, 0xa7, + 0xb0, 0x62, 0xd1, 0xf2, 0x1c, 0xa4, 0xbb, 0x51, 0x16, 0xcf, 0xec, 0x45, 0xec, 0x1a, 0x42, 0x92, + 0x4a, 0xda, 0x5e, 0x6c, 0x66, 0x01, 0x28, 0x1f, 0x03, 0x7b, 0x60, 0xc5, 0xb7, 0xf2, 0x54, 0x41, + 0xb9, 0x5c, 0x13, 0x54, 0x2b, 0x07, 0x79, 0x08, 0x92, 0xc5, 0xc1, 0x1f, 0xa7, 0x1c, 0xc7, 0x2c, + 0x3f, 0x08, 0x5e, 0x3a, 0xbd, 0xa2, 0xa7, 0xb6, 0x1c, 0xf0, 0x1e, 0x58, 0x74, 0xb9, 0xa1, 0x0c, + 0xb3, 0x0c, 0x4c, 0xd9, 0x57, 0x44, 0xd8, 0x22, 0x4a, 0x76, 0xa2, 0x34, 0x56, 0xe2, 0xa3, 0x6a, + 0xd3, 0xfa, 0xa8, 0xd6, 0x9f, 0x14, 0x00, 0xf3, 0x5b, 0x70, 0xe2, 0xcb, 0x7d, 0x2e, 0x22, 0x21, + 0x91, 0x9a, 0xdc, 0xe1, 0xdc, 0x9c, 0xec, 0x70, 0xe2, 0x13, 0x74, 0x3a, 0x8b, 0x23, 0x66, 0xe0, + 0x62, 0x2e, 0x66, 0xa6, 0xb0, 0x38, 0x71, 0x3e, 0xcf, 0x66, 0x71, 0x12, 0x3c, 0xa7, 0x5b, 0x9c, + 0x7f, 0x97, 0xc0, 0x4a, 0x0c, 0x9e, 0xda, 0xe2, 0x48, 0x42, 0xbe, 0xbc, 0x9c, 0x99, 0x7c, 0x39, + 0xc3, 0x6c, 0x47, 0x3c, 0x75, 0xff, 0x27, 0xb6, 0x23, 0x4e, 0xa8, 0xc0, 0x76, 0xfc, 0xae, 0x94, + 0xcc, 0xfa, 0x0b, 0x6f, 0x3b, 0x9e, 0xfd, 0x72, 0xa5, 0xf5, 0x97, 0x32, 0xb8, 0x9c, 0xdd, 0x82, + 0x29, 0x1d, 0x54, 0x26, 0xea, 0xe0, 0x1e, 0x58, 0x7d, 0xe4, 0x1b, 0xc6, 0x88, 0x4f, 0x43, 0x42, + 0x0c, 0x03, 0x05, 0xfd, 0xaa, 0x88, 0x5c, 0xfd, 0xbe, 0x04, 0x83, 0xa4, 0x91, 0x05, 0x9a, 0x5e, + 0x3e, 0x97, 0xa6, 0xe7, 0xd4, 0xa6, 0x72, 0x06, 0xb5, 0x91, 0xea, 0x73, 0xf5, 0x1c, 0xfa, 0x3c, + 0xb5, 0xa0, 0x4a, 0x8e, 0xab, 0x89, 0xef, 0xf0, 0xbf, 0x56, 0xc0, 0x9a, 0xfc, 0xf5, 0x19, 0x1a, + 0x60, 0xc9, 0xc4, 0x8f, 0x93, 0x97, 0x17, 0x93, 0x04, 0xc3, 0xa7, 0xba, 0xa1, 0x06, 0x5f, 0x77, + 0xd4, 0x77, 0x2c, 0xba, 0xeb, 0xee, 0x53, 0x57, 0xb7, 0x06, 0x81, 0xc0, 0xf6, 0x52, 0x5c, 0x28, + 0xc3, 0xdd, 0xfa, 0x58, 0x01, 0xeb, 0x05, 0x2a, 0x77, 0xb1, 0x99, 0xc0, 0x87, 0xa0, 0x66, 0xe2, + 0xc7, 0xfb, 0xbe, 0x3b, 0x08, 0x25, 0xf9, 0xec, 0xcf, 0xe1, 0x1b, 0xb9, 0x27, 0x58, 0x50, 0xc4, + 0xd7, 0xda, 0x05, 0xd7, 0x53, 0x83, 0x64, 0x9b, 0x86, 0x3c, 0xf2, 0x0d, 0xbe, 0x7f, 0x84, 0xa7, + 0xb8, 0x09, 0xe6, 0x1d, 0xec, 0x52, 0x3d, 0x32, 0xa3, 0xd5, 0xce, 0xe2, 0xf8, 0xa4, 0x39, 0xbf, + 0x17, 0x36, 0xa2, 0xb8, 0xbf, 0xf5, 0xab, 0x12, 0x58, 0x48, 0x90, 0x5c, 0x80, 0xbe, 0xbf, 0x95, + 0xd2, 0x77, 0xe9, 0x17, 0x93, 0xe4, 0xa8, 0x8a, 0x04, 0xbe, 0x97, 0x11, 0xf8, 0x6f, 0x4e, 0x22, + 0x3a, 0x5d, 0xe1, 0x3f, 0x29, 0x81, 0xd5, 0x04, 0x3a, 0x96, 0xf8, 0xef, 0xa4, 0x24, 0x7e, 0x23, + 0x23, 0xf1, 0x75, 0x59, 0xcc, 0x97, 0x1a, 0x3f, 0x59, 0xe3, 0xff, 0xa8, 0x80, 0xe5, 0xc4, 0xdc, + 0x5d, 0x80, 0xc8, 0x6f, 0xa5, 0x45, 0xbe, 0x39, 0xa1, 0x5e, 0x0a, 0x54, 0xfe, 0x49, 0x35, 0x95, + 0xf7, 0x17, 0x5e, 0xe6, 0x7f, 0x0e, 0x56, 0x87, 0xb6, 0xe1, 0x9b, 0xa4, 0x6b, 0x60, 0xdd, 0x0c, + 0x01, 0x4c, 0xc9, 0xd8, 0x24, 0xbe, 0x2c, 0xa5, 0x27, 0xae, 0xa7, 0x7b, 0x94, 0x58, 0xf4, 0x41, + 0x1c, 0x19, 0x6b, 0xf1, 0x03, 0x09, 0x1d, 0x92, 0x3e, 0x04, 0xbe, 0x0e, 0x16, 0x98, 0xa6, 0xea, + 0x7d, 0xb2, 0x83, 0xcd, 0xb0, 0xa6, 0xa2, 0xef, 0x03, 0xfb, 0x71, 0x17, 0x4a, 0xe2, 0xe0, 0x11, + 0x58, 0x71, 0x6c, 0xad, 0x87, 0x2d, 0x3c, 0x20, 0xec, 0xfc, 0xdf, 0xb3, 0x0d, 0xbd, 0x3f, 0xe2, + 0xf7, 0x0e, 0xf3, 0x9d, 0x37, 0xc2, 0x17, 0xd2, 0xbd, 0x3c, 0x84, 0x79, 0x76, 0x49, 0x33, 0xdf, + 0xcf, 0x32, 0x4a, 0x68, 0xe6, 0x3e, 0x67, 0xcd, 0xe5, 0xfe, 0x07, 0x40, 0x56, 0x5c, 0xe7, 0xfc, + 0xa0, 0x55, 0x74, 0xa3, 0x52, 0x3b, 0xd7, 0xd7, 0xa8, 0x4f, 0x2a, 0xe0, 0x4a, 0xee, 0x80, 0xfc, + 0x1c, 0xef, 0x34, 0x72, 0x6e, 0xa9, 0x7c, 0x06, 0xb7, 0xb4, 0x09, 0x96, 0xc5, 0x87, 0xb0, 0x8c, + 0xd9, 0x8a, 0xec, 0x68, 0x37, 0xdd, 0x8d, 0xb2, 0x78, 0xd9, 0x9d, 0x4a, 0xf5, 0x8c, 0x77, 0x2a, + 0xc9, 0x2c, 0xc4, 0xff, 0x6f, 0x04, 0x55, 0x97, 0xcf, 0x42, 0xfc, 0x1b, 0x47, 0x16, 0x0f, 0xbf, + 0x1b, 0x96, 0x54, 0xc4, 0x30, 0xc7, 0x19, 0x32, 0x35, 0x12, 0x11, 0x64, 0xd0, 0xcf, 0xf4, 0xb1, + 0xe7, 0x3d, 0xc9, 0xc7, 0x9e, 0x8d, 0x09, 0xa5, 0x3c, 0xbd, 0x55, 0xfc, 0x9b, 0x02, 0x5e, 0x28, + 0xdc, 0x03, 0x70, 0x33, 0xa5, 0xb3, 0xb7, 0x32, 0x3a, 0xfb, 0x62, 0x61, 0x60, 0x42, 0x6c, 0x4d, + 0xf9, 0x85, 0xc8, 0xdd, 0x89, 0x17, 0x22, 0x12, 0x17, 0x35, 0xf9, 0x66, 0xa4, 0xb3, 0xf1, 0xe4, + 0x69, 0x63, 0xe6, 0xc3, 0xa7, 0x8d, 0x99, 0x8f, 0x9e, 0x36, 0x66, 0x7e, 0x31, 0x6e, 0x28, 0x4f, + 0xc6, 0x0d, 0xe5, 0xc3, 0x71, 0x43, 0xf9, 0x68, 0xdc, 0x50, 0xfe, 0x39, 0x6e, 0x28, 0xbf, 0xfd, + 0xb8, 0x31, 0xf3, 0xb0, 0x34, 0xbc, 0xfd, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x6b, 0x01, + 0x7b, 0x12, 0x26, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/apps/v1/generated.proto b/vendor/k8s.io/api/apps/v1/generated.proto index 46473baa8..c8a957ac6 100644 --- a/vendor/k8s.io/api/apps/v1/generated.proto +++ b/vendor/k8s.io/api/apps/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,7 +22,6 @@ syntax = 'proto2'; package k8s.io.api.apps.v1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; @@ -501,9 +500,9 @@ message RollingUpdateDeployment { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -515,10 +514,10 @@ message RollingUpdateDeployment { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is at most 130% of desired pods. // +optional optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; diff --git a/vendor/k8s.io/api/apps/v1/types.go b/vendor/k8s.io/api/apps/v1/types.go index b5df22c6f..4431ca2c3 100644 --- a/vendor/k8s.io/api/apps/v1/types.go +++ b/vendor/k8s.io/api/apps/v1/types.go @@ -307,8 +307,8 @@ type DeploymentSpec struct { const ( // DefaultDeploymentUniqueLabelKey is the default key of the selector that is added - // to existing RCs (and label key that is added to its pods) to prevent the existing RCs - // to select new pods (and old pods being select by new RC). + // to existing ReplicaSets (and label key that is added to its pods) to prevent the existing ReplicaSets + // to select new pods (and old pods being select by new ReplicaSet). DefaultDeploymentUniqueLabelKey string = "pod-template-hash" ) @@ -333,7 +333,7 @@ const ( // Kill all existing pods before creating new ones. RecreateDeploymentStrategyType DeploymentStrategyType = "Recreate" - // Replace the old RCs by new one using rolling update i.e gradually scale down the old RCs and scale up the new one. + // Replace the old ReplicaSets by new one using rolling update i.e gradually scale down the old ReplicaSets and scale up the new one. RollingUpdateDeploymentStrategyType DeploymentStrategyType = "RollingUpdate" ) @@ -344,9 +344,9 @@ type RollingUpdateDeployment struct { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -358,10 +358,10 @@ type RollingUpdateDeployment struct { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is at most 130% of desired pods. // +optional MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` diff --git a/vendor/k8s.io/api/apps/v1/types_swagger_doc_generated.go b/vendor/k8s.io/api/apps/v1/types_swagger_doc_generated.go index 4dec6f2f8..85fb159dd 100644 --- a/vendor/k8s.io/api/apps/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/apps/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_ControllerRevision = map[string]string{ "": "ControllerRevision implements an immutable snapshot of state data. Clients are responsible for serializing and deserializing the objects that contain their internal state. Once a ControllerRevision has been successfully created, it can not be updated. The API Server will fail validation of all requests that attempt to mutate the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, it may be subject to name and representation changes in future releases, and clients should not depend on its stability. It is primarily for internal use by controllers.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -271,8 +271,8 @@ func (RollingUpdateDaemonSet) SwaggerDoc() map[string]string { var map_RollingUpdateDeployment = map[string]string{ "": "Spec to control the desired behavior of rolling update.", - "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", - "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.", + "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.", } func (RollingUpdateDeployment) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/api/apps/v1/zz_generated.deepcopy.go b/vendor/k8s.io/api/apps/v1/zz_generated.deepcopy.go index 62984cb89..ccbb29061 100644 --- a/vendor/k8s.io/api/apps/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/apps/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/apps/v1beta1/generated.pb.go b/vendor/k8s.io/api/apps/v1beta1/generated.pb.go index 04183fc2d..ef9aa8e09 100644 --- a/vendor/k8s.io/api/apps/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/apps/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -54,7 +54,6 @@ import fmt "fmt" import math "math" import k8s_io_api_core_v1 "k8s.io/api/core/v1" - import k8s_io_apimachinery_pkg_apis_meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" import k8s_io_apimachinery_pkg_util_intstr "k8s.io/apimachinery/pkg/util/intstr" @@ -5170,122 +5169,122 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1871 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0x4f, 0x6f, 0x1b, 0xc7, - 0x15, 0xd7, 0x52, 0xa4, 0x44, 0x3d, 0x45, 0x94, 0x3d, 0x52, 0x2d, 0x46, 0x69, 0x29, 0x61, 0x1b, - 0x24, 0x72, 0x12, 0x2d, 0x63, 0x25, 0x0d, 0x12, 0xbb, 0x08, 0x2a, 0xca, 0x6e, 0xe2, 0x40, 0xaa, - 0x94, 0xa1, 0x94, 0xa2, 0x69, 0x0b, 0x64, 0xb8, 0x1c, 0xd3, 0x1b, 0xed, 0x3f, 0xec, 0x0e, 0x59, - 0x13, 0xbd, 0xf4, 0x03, 0x14, 0x48, 0xcf, 0xfd, 0x14, 0x3d, 0x16, 0xed, 0xad, 0x27, 0x5f, 0x0a, - 0x04, 0xbd, 0x34, 0x27, 0xa1, 0xa6, 0xaf, 0x6d, 0x6f, 0xbd, 0x18, 0x28, 0x50, 0xcc, 0xec, 0xec, - 0xff, 0x5d, 0x89, 0x2a, 0x20, 0x1d, 0x72, 0xe3, 0xce, 0x7b, 0xef, 0xf7, 0xde, 0xcc, 0xbc, 0xf7, - 0xe6, 0xfd, 0x08, 0x3f, 0x3a, 0x7d, 0xdf, 0xd7, 0x0c, 0xa7, 0x7d, 0x3a, 0xec, 0x51, 0xcf, 0xa6, - 0x8c, 0xfa, 0xed, 0x11, 0xb5, 0xfb, 0x8e, 0xd7, 0x96, 0x02, 0xe2, 0x1a, 0x6d, 0xe2, 0xba, 0x7e, - 0x7b, 0x74, 0xa7, 0x47, 0x19, 0xb9, 0xd3, 0x1e, 0x50, 0x9b, 0x7a, 0x84, 0xd1, 0xbe, 0xe6, 0x7a, - 0x0e, 0x73, 0xd0, 0x5a, 0xa0, 0xa8, 0x11, 0xd7, 0xd0, 0xb8, 0xa2, 0x26, 0x15, 0xd7, 0xb7, 0x07, - 0x06, 0x7b, 0x3c, 0xec, 0x69, 0xba, 0x63, 0xb5, 0x07, 0xce, 0xc0, 0x69, 0x0b, 0xfd, 0xde, 0xf0, - 0x91, 0xf8, 0x12, 0x1f, 0xe2, 0x57, 0x80, 0xb3, 0xae, 0x26, 0x1c, 0xea, 0x8e, 0x47, 0xdb, 0xa3, - 0x9c, 0xaf, 0xf5, 0xdb, 0x09, 0x1d, 0xd7, 0x31, 0x0d, 0x7d, 0x5c, 0x16, 0xd6, 0xfa, 0xbb, 0xb1, - 0xaa, 0x45, 0xf4, 0xc7, 0x86, 0x4d, 0xbd, 0x71, 0xdb, 0x3d, 0x1d, 0xf0, 0x05, 0xbf, 0x6d, 0x51, - 0x46, 0x8a, 0x1c, 0xb4, 0xcb, 0xac, 0xbc, 0xa1, 0xcd, 0x0c, 0x8b, 0xe6, 0x0c, 0xde, 0xbb, 0xc8, - 0xc0, 0xd7, 0x1f, 0x53, 0x8b, 0xe4, 0xec, 0xde, 0x29, 0xb3, 0x1b, 0x32, 0xc3, 0x6c, 0x1b, 0x36, - 0xf3, 0x99, 0x97, 0x35, 0x52, 0xff, 0xa3, 0x00, 0xda, 0x73, 0x6c, 0xe6, 0x39, 0xa6, 0x49, 0x3d, - 0x4c, 0x47, 0x86, 0x6f, 0x38, 0x36, 0xfa, 0x02, 0xea, 0x7c, 0x3f, 0x7d, 0xc2, 0x48, 0x53, 0xd9, - 0x54, 0xb6, 0x16, 0x77, 0xde, 0xd6, 0xe2, 0x4b, 0x89, 0xe0, 0x35, 0xf7, 0x74, 0xc0, 0x17, 0x7c, - 0x8d, 0x6b, 0x6b, 0xa3, 0x3b, 0xda, 0x61, 0xef, 0x4b, 0xaa, 0xb3, 0x03, 0xca, 0x48, 0x07, 0x3d, - 0x3d, 0xdb, 0x98, 0x99, 0x9c, 0x6d, 0x40, 0xbc, 0x86, 0x23, 0x54, 0x74, 0x08, 0x55, 0x81, 0x5e, - 0x11, 0xe8, 0xdb, 0xa5, 0xe8, 0x72, 0xd3, 0x1a, 0x26, 0xbf, 0x7a, 0xf0, 0x84, 0x51, 0x9b, 0x87, - 0xd7, 0x79, 0x49, 0x42, 0x57, 0xef, 0x13, 0x46, 0xb0, 0x00, 0x42, 0x6f, 0x41, 0xdd, 0x93, 0xe1, - 0x37, 0x67, 0x37, 0x95, 0xad, 0xd9, 0xce, 0x0d, 0xa9, 0x55, 0x0f, 0xb7, 0x85, 0x23, 0x0d, 0xf5, - 0xa9, 0x02, 0xb7, 0xf2, 0xfb, 0xde, 0x37, 0x7c, 0x86, 0x7e, 0x91, 0xdb, 0xbb, 0x36, 0xdd, 0xde, - 0xb9, 0xb5, 0xd8, 0x79, 0xe4, 0x38, 0x5c, 0x49, 0xec, 0xfb, 0x08, 0x6a, 0x06, 0xa3, 0x96, 0xdf, - 0xac, 0x6c, 0xce, 0x6e, 0x2d, 0xee, 0xbc, 0xa9, 0x95, 0xe4, 0xba, 0x96, 0x8f, 0xae, 0xb3, 0x24, - 0x71, 0x6b, 0x0f, 0x39, 0x02, 0x0e, 0x80, 0xd4, 0xdf, 0x56, 0x00, 0xee, 0x53, 0xd7, 0x74, 0xc6, - 0x16, 0xb5, 0xd9, 0x35, 0x5c, 0xdd, 0x43, 0xa8, 0xfa, 0x2e, 0xd5, 0xe5, 0xd5, 0xbd, 0x5e, 0xba, - 0x83, 0x38, 0xa8, 0xae, 0x4b, 0xf5, 0xf8, 0xd2, 0xf8, 0x17, 0x16, 0x10, 0xe8, 0x53, 0x98, 0xf3, - 0x19, 0x61, 0x43, 0x5f, 0x5c, 0xd9, 0xe2, 0xce, 0xed, 0x69, 0xc0, 0x84, 0x41, 0xa7, 0x21, 0xe1, - 0xe6, 0x82, 0x6f, 0x2c, 0x81, 0xd4, 0xbf, 0xcf, 0xc2, 0x4a, 0xac, 0xbc, 0xe7, 0xd8, 0x7d, 0x83, - 0xf1, 0x94, 0xbe, 0x07, 0x55, 0x36, 0x76, 0xa9, 0x38, 0x93, 0x85, 0xce, 0xeb, 0x61, 0x30, 0xc7, - 0x63, 0x97, 0xbe, 0x38, 0xdb, 0x58, 0x2b, 0x30, 0xe1, 0x22, 0x2c, 0x8c, 0xd0, 0x7e, 0x14, 0x67, - 0x45, 0x98, 0xbf, 0x9b, 0x76, 0xfe, 0xe2, 0x6c, 0xa3, 0xa0, 0xd7, 0x68, 0x11, 0x52, 0x3a, 0x44, - 0xf4, 0x1a, 0xcc, 0x79, 0x94, 0xf8, 0x8e, 0xdd, 0xac, 0x0a, 0xb4, 0x68, 0x2b, 0x58, 0xac, 0x62, - 0x29, 0x45, 0xb7, 0x61, 0xde, 0xa2, 0xbe, 0x4f, 0x06, 0xb4, 0x59, 0x13, 0x8a, 0xcb, 0x52, 0x71, - 0xfe, 0x20, 0x58, 0xc6, 0xa1, 0x1c, 0x7d, 0x09, 0x0d, 0x93, 0xf8, 0xec, 0xc4, 0xed, 0x13, 0x46, - 0x8f, 0x0d, 0x8b, 0x36, 0xe7, 0xc4, 0x81, 0xbe, 0x31, 0xdd, 0xdd, 0x73, 0x8b, 0xce, 0x2d, 0x89, - 0xde, 0xd8, 0x4f, 0x21, 0xe1, 0x0c, 0x32, 0x1a, 0x01, 0xe2, 0x2b, 0xc7, 0x1e, 0xb1, 0xfd, 0xe0, - 0xa0, 0xb8, 0xbf, 0xf9, 0x4b, 0xfb, 0x5b, 0x97, 0xfe, 0xd0, 0x7e, 0x0e, 0x0d, 0x17, 0x78, 0x50, - 0xff, 0xa8, 0x40, 0x23, 0xbe, 0xa6, 0x6b, 0xa8, 0xd5, 0x8f, 0xd3, 0xb5, 0xfa, 0xfd, 0x29, 0x92, - 0xb3, 0xa4, 0x46, 0xff, 0x59, 0x01, 0x14, 0x2b, 0x61, 0xc7, 0x34, 0x7b, 0x44, 0x3f, 0x45, 0x9b, - 0x50, 0xb5, 0x89, 0x15, 0xe6, 0x64, 0x54, 0x20, 0x3f, 0x21, 0x16, 0xc5, 0x42, 0x82, 0xbe, 0x52, - 0x00, 0x0d, 0xc5, 0xd1, 0xf7, 0x77, 0x6d, 0xdb, 0x61, 0x84, 0x9f, 0x46, 0x18, 0xd0, 0xde, 0x14, - 0x01, 0x85, 0xbe, 0xb4, 0x93, 0x1c, 0xca, 0x03, 0x9b, 0x79, 0xe3, 0xf8, 0x16, 0xf2, 0x0a, 0xb8, - 0xc0, 0x35, 0xfa, 0x39, 0x80, 0x27, 0x31, 0x8f, 0x1d, 0x59, 0xb6, 0xe5, 0x3d, 0x20, 0x74, 0xbf, - 0xe7, 0xd8, 0x8f, 0x8c, 0x41, 0xdc, 0x58, 0x70, 0x04, 0x81, 0x13, 0x70, 0xeb, 0x0f, 0x60, 0xad, - 0x24, 0x4e, 0x74, 0x03, 0x66, 0x4f, 0xe9, 0x38, 0x38, 0x2a, 0xcc, 0x7f, 0xa2, 0x55, 0xa8, 0x8d, - 0x88, 0x39, 0xa4, 0x41, 0x4d, 0xe2, 0xe0, 0xe3, 0x6e, 0xe5, 0x7d, 0x45, 0xfd, 0x43, 0x2d, 0x99, - 0x29, 0xbc, 0xdf, 0xa0, 0x2d, 0xfe, 0x3c, 0xb8, 0xa6, 0xa1, 0x13, 0x5f, 0x60, 0xd4, 0x3a, 0x2f, - 0x05, 0x4f, 0x43, 0xb0, 0x86, 0x23, 0x29, 0xfa, 0x25, 0xd4, 0x7d, 0x6a, 0x52, 0x9d, 0x39, 0x9e, - 0x6c, 0x71, 0xef, 0x4c, 0x99, 0x53, 0xa4, 0x47, 0xcd, 0xae, 0x34, 0x0d, 0xe0, 0xc3, 0x2f, 0x1c, - 0x41, 0xa2, 0x4f, 0xa1, 0xce, 0xa8, 0xe5, 0x9a, 0x84, 0x51, 0x79, 0x7a, 0xa9, 0xbc, 0xe2, 0xbd, - 0x83, 0x83, 0x1d, 0x39, 0xfd, 0x63, 0xa9, 0x26, 0xba, 0x67, 0x94, 0xa7, 0xe1, 0x2a, 0x8e, 0x60, - 0xd0, 0xcf, 0xa0, 0xee, 0x33, 0xfe, 0xaa, 0x0f, 0xc6, 0xa2, 0xa3, 0x9c, 0xf7, 0xac, 0x24, 0xfb, - 0x68, 0x60, 0x12, 0x43, 0x87, 0x2b, 0x38, 0x82, 0x43, 0xbb, 0xb0, 0x6c, 0x19, 0x36, 0xa6, 0xa4, - 0x3f, 0xee, 0x52, 0xdd, 0xb1, 0xfb, 0xbe, 0x68, 0x45, 0xb5, 0xce, 0x9a, 0x34, 0x5a, 0x3e, 0x48, - 0x8b, 0x71, 0x56, 0x1f, 0xed, 0xc3, 0x6a, 0xf8, 0xec, 0x7e, 0x6c, 0xf8, 0xcc, 0xf1, 0xc6, 0xfb, - 0x86, 0x65, 0x30, 0xd1, 0xa0, 0x6a, 0x9d, 0xe6, 0xe4, 0x6c, 0x63, 0x15, 0x17, 0xc8, 0x71, 0xa1, - 0x15, 0xef, 0x9d, 0x2e, 0x19, 0xfa, 0xb4, 0x2f, 0x1a, 0x4e, 0x3d, 0xee, 0x9d, 0x47, 0x62, 0x15, - 0x4b, 0x29, 0xfa, 0x69, 0x2a, 0x4d, 0xeb, 0x97, 0x4b, 0xd3, 0x46, 0x79, 0x8a, 0xa2, 0x13, 0x58, - 0x73, 0x3d, 0x67, 0xe0, 0x51, 0xdf, 0xbf, 0x4f, 0x49, 0xdf, 0x34, 0x6c, 0x1a, 0x9e, 0xcc, 0x82, - 0xd8, 0xd1, 0x2b, 0x93, 0xb3, 0x8d, 0xb5, 0xa3, 0x62, 0x15, 0x5c, 0x66, 0xab, 0xfe, 0xa5, 0x0a, - 0x37, 0xb2, 0x6f, 0x1c, 0xfa, 0x04, 0x90, 0xd3, 0xf3, 0xa9, 0x37, 0xa2, 0xfd, 0x8f, 0x82, 0xc1, - 0x8d, 0x4f, 0x37, 0x8a, 0x98, 0x6e, 0xa2, 0xba, 0x3d, 0xcc, 0x69, 0xe0, 0x02, 0xab, 0x60, 0x3e, - 0x92, 0x05, 0x50, 0x11, 0x81, 0x26, 0xe6, 0xa3, 0x5c, 0x11, 0xec, 0xc2, 0xb2, 0xac, 0xfd, 0x50, - 0x28, 0x92, 0x35, 0x71, 0xef, 0x27, 0x69, 0x31, 0xce, 0xea, 0xa3, 0x8f, 0xe0, 0x26, 0x19, 0x11, - 0xc3, 0x24, 0x3d, 0x93, 0x46, 0x20, 0x55, 0x01, 0xf2, 0xb2, 0x04, 0xb9, 0xb9, 0x9b, 0x55, 0xc0, - 0x79, 0x1b, 0x74, 0x00, 0x2b, 0x43, 0x3b, 0x0f, 0x15, 0xe4, 0xe1, 0x2b, 0x12, 0x6a, 0xe5, 0x24, - 0xaf, 0x82, 0x8b, 0xec, 0xd0, 0x17, 0x00, 0x7a, 0xf8, 0x30, 0xfb, 0xcd, 0x39, 0xd1, 0x49, 0xdf, - 0x9a, 0xa2, 0x5e, 0xa2, 0xd7, 0x3c, 0xee, 0x62, 0xd1, 0x92, 0x8f, 0x13, 0x98, 0xe8, 0x1e, 0x2c, - 0x79, 0xbc, 0x02, 0xa2, 0x50, 0xe7, 0x45, 0xa8, 0xdf, 0x91, 0x66, 0x4b, 0x38, 0x29, 0xc4, 0x69, - 0x5d, 0x74, 0x17, 0x1a, 0xba, 0x63, 0x9a, 0x22, 0xf3, 0xf7, 0x9c, 0xa1, 0xcd, 0x44, 0xf2, 0xd6, - 0x3a, 0x88, 0xbf, 0xcc, 0x7b, 0x29, 0x09, 0xce, 0x68, 0xaa, 0x7f, 0x56, 0x92, 0xcf, 0x4c, 0x58, - 0xce, 0xe8, 0x6e, 0x6a, 0xf4, 0x79, 0x2d, 0x33, 0xfa, 0xdc, 0xca, 0x5b, 0x24, 0x26, 0x1f, 0x03, - 0x96, 0x78, 0xf2, 0x1b, 0xf6, 0x20, 0xb8, 0x70, 0xd9, 0x12, 0xdf, 0x3e, 0xb7, 0x94, 0x22, 0xed, - 0xc4, 0xc3, 0x78, 0x53, 0xec, 0x3c, 0x29, 0xc4, 0x69, 0x64, 0xf5, 0x43, 0x68, 0xa4, 0xeb, 0x30, - 0x35, 0xd3, 0x2b, 0x17, 0xce, 0xf4, 0xcf, 0x15, 0x58, 0x2b, 0xf1, 0x8e, 0x4c, 0x68, 0x58, 0xe4, - 0x49, 0x22, 0x47, 0x2e, 0x9c, 0x8d, 0x39, 0x6b, 0xd2, 0x02, 0xd6, 0xa4, 0x3d, 0xb4, 0xd9, 0xa1, - 0xd7, 0x65, 0x9e, 0x61, 0x0f, 0x82, 0x7b, 0x38, 0x48, 0x61, 0xe1, 0x0c, 0x36, 0xfa, 0x1c, 0xea, - 0x16, 0x79, 0xd2, 0x1d, 0x7a, 0x83, 0xa2, 0xf3, 0x9a, 0xce, 0x8f, 0x78, 0x3f, 0x0e, 0x24, 0x0a, - 0x8e, 0xf0, 0xd4, 0x43, 0xd8, 0x4c, 0x6d, 0x92, 0xb7, 0x0a, 0xfa, 0x68, 0x68, 0x76, 0x69, 0x7c, - 0xe1, 0x6f, 0xc2, 0x82, 0x4b, 0x3c, 0x66, 0x44, 0xed, 0xa2, 0xd6, 0x59, 0x9a, 0x9c, 0x6d, 0x2c, - 0x1c, 0x85, 0x8b, 0x38, 0x96, 0xab, 0xff, 0x55, 0xa0, 0xd6, 0xd5, 0x89, 0x49, 0xaf, 0x81, 0x3a, - 0xdc, 0x4f, 0x51, 0x07, 0xb5, 0x34, 0x89, 0x44, 0x3c, 0xa5, 0xac, 0x61, 0x3f, 0xc3, 0x1a, 0x5e, - 0xbd, 0x00, 0xe7, 0x7c, 0xc2, 0xf0, 0x01, 0x2c, 0x44, 0xee, 0x52, 0x5d, 0x52, 0xb9, 0xa8, 0x4b, - 0xaa, 0xbf, 0xaf, 0xc0, 0x62, 0xc2, 0xc5, 0xe5, 0xac, 0xf9, 0x71, 0x27, 0x06, 0x0d, 0xde, 0x86, - 0x76, 0xa6, 0xd9, 0x88, 0x16, 0x0e, 0x15, 0xc1, 0xfc, 0x16, 0xbf, 0xde, 0xf9, 0x59, 0xe3, 0x43, - 0x68, 0x30, 0xe2, 0x0d, 0x28, 0x0b, 0x65, 0xe2, 0xc0, 0x16, 0xe2, 0x49, 0xff, 0x38, 0x25, 0xc5, - 0x19, 0xed, 0xf5, 0x7b, 0xb0, 0x94, 0x72, 0x76, 0xa9, 0x21, 0xec, 0x2b, 0x7e, 0x38, 0x71, 0x72, - 0x5e, 0x43, 0x76, 0x7d, 0x92, 0xca, 0xae, 0xad, 0xf2, 0xc3, 0x4c, 0x94, 0x4c, 0x59, 0x8e, 0xe1, - 0x4c, 0x8e, 0xbd, 0x31, 0x15, 0xda, 0xf9, 0x99, 0xf6, 0xaf, 0x0a, 0xac, 0x26, 0xb4, 0x63, 0x6e, - 0xfa, 0xc3, 0x54, 0x83, 0xde, 0xca, 0x34, 0xe8, 0x66, 0x91, 0xcd, 0x95, 0x91, 0xd3, 0x62, 0x76, - 0x37, 0x7b, 0xd5, 0xec, 0xee, 0x0a, 0x48, 0xb1, 0xfa, 0x27, 0x05, 0x96, 0x13, 0x67, 0x77, 0x0d, - 0x8c, 0xf1, 0x61, 0x9a, 0x31, 0xbe, 0x3a, 0x4d, 0xd2, 0x94, 0x50, 0xc6, 0xbf, 0xd6, 0x52, 0xc1, - 0x7f, 0xeb, 0x49, 0xcc, 0xaf, 0x61, 0x75, 0xe4, 0x98, 0x43, 0x8b, 0xee, 0x99, 0xc4, 0xb0, 0x42, - 0x05, 0x3e, 0x31, 0xce, 0x66, 0xff, 0x18, 0x8a, 0xe0, 0xa9, 0xe7, 0x1b, 0x3e, 0xa3, 0x36, 0xfb, - 0x2c, 0xb6, 0xec, 0x7c, 0x57, 0x3a, 0x59, 0xfd, 0xac, 0x00, 0x0e, 0x17, 0x3a, 0x41, 0x3f, 0x80, - 0x45, 0x3e, 0x30, 0x1b, 0x3a, 0xe5, 0xdc, 0x5b, 0x26, 0xd6, 0x8a, 0x04, 0x5a, 0xec, 0xc6, 0x22, - 0x9c, 0xd4, 0x43, 0x8f, 0x61, 0xc5, 0x75, 0xfa, 0x07, 0xc4, 0x26, 0x03, 0xca, 0xc7, 0x8c, 0x23, - 0xf1, 0x07, 0xb2, 0x60, 0x36, 0x0b, 0x9d, 0xf7, 0xc2, 0xc9, 0xf4, 0x28, 0xaf, 0xf2, 0x82, 0x53, - 0x84, 0xfc, 0xb2, 0x28, 0xea, 0x22, 0x48, 0xe4, 0x41, 0x63, 0x28, 0x9f, 0x7b, 0x49, 0xf4, 0x82, - 0xff, 0x5b, 0x76, 0xa6, 0xc9, 0xb0, 0x93, 0x94, 0x65, 0xdc, 0xfd, 0xd3, 0xeb, 0x38, 0xe3, 0xa1, - 0x94, 0xb8, 0xd5, 0xff, 0x1f, 0xe2, 0xa6, 0xfe, 0xbb, 0x0a, 0x37, 0x73, 0xad, 0x12, 0xfd, 0xf8, - 0x1c, 0x86, 0x73, 0xeb, 0xca, 0xd8, 0x4d, 0x6e, 0x40, 0x9f, 0xbd, 0xc4, 0x80, 0xbe, 0x0b, 0xcb, - 0xfa, 0xd0, 0xf3, 0xa8, 0xcd, 0x32, 0xac, 0x26, 0xa2, 0x46, 0x7b, 0x69, 0x31, 0xce, 0xea, 0x17, - 0xb1, 0xab, 0xda, 0x25, 0xd9, 0x55, 0x32, 0x0a, 0x39, 0x21, 0x07, 0x69, 0x97, 0x8f, 0x42, 0x0e, - 0xca, 0x59, 0x7d, 0x3e, 0x1d, 0x04, 0xa8, 0x11, 0xc2, 0x7c, 0x7a, 0x3a, 0x38, 0x49, 0x49, 0x71, - 0x46, 0xbb, 0x80, 0xa9, 0x2c, 0x4c, 0xcb, 0x54, 0x10, 0x49, 0x91, 0x30, 0x10, 0x35, 0xbe, 0x3d, - 0x4d, 0x2e, 0x4f, 0xcd, 0xc2, 0xd4, 0xbf, 0x29, 0xf0, 0x72, 0x69, 0x11, 0xa0, 0xdd, 0xd4, 0x93, - 0xbb, 0x9d, 0x79, 0x72, 0xbf, 0x57, 0x6a, 0x98, 0x78, 0x77, 0xbd, 0x62, 0x6a, 0xf4, 0xc1, 0x74, - 0xd4, 0xa8, 0x60, 0x6e, 0xbf, 0x98, 0x23, 0x75, 0xb6, 0x9f, 0x3e, 0x6b, 0xcd, 0x7c, 0xfd, 0xac, - 0x35, 0xf3, 0xcd, 0xb3, 0xd6, 0xcc, 0x6f, 0x26, 0x2d, 0xe5, 0xe9, 0xa4, 0xa5, 0x7c, 0x3d, 0x69, - 0x29, 0xdf, 0x4c, 0x5a, 0xca, 0x3f, 0x26, 0x2d, 0xe5, 0x77, 0xcf, 0x5b, 0x33, 0x9f, 0xcf, 0x4b, - 0x8f, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x5d, 0x9e, 0x04, 0x8c, 0x1b, 0x00, 0x00, + // 1859 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0xcd, 0x6f, 0x24, 0x47, + 0x15, 0x77, 0x8f, 0x67, 0xec, 0xf1, 0x73, 0x3c, 0xde, 0x2d, 0x9b, 0xf5, 0xc4, 0x81, 0xb1, 0xd5, + 0x44, 0x89, 0xf3, 0xe1, 0x9e, 0xac, 0x13, 0xa2, 0x64, 0x17, 0x45, 0x78, 0xbc, 0x4b, 0xb2, 0x91, + 0x8d, 0x9d, 0xb2, 0x1d, 0x44, 0x00, 0x29, 0x35, 0x3d, 0xb5, 0xb3, 0x1d, 0xf7, 0x97, 0xba, 0x6b, + 0x86, 0x1d, 0x71, 0xe1, 0x0f, 0x40, 0x0a, 0x67, 0xfe, 0x0a, 0x8e, 0x08, 0x6e, 0x9c, 0xf6, 0x82, + 0x14, 0x71, 0x21, 0x27, 0x8b, 0x9d, 0x5c, 0x81, 0x1b, 0x97, 0x95, 0x90, 0x50, 0x55, 0x57, 0x7f, + 0x77, 0xdb, 0x6d, 0xa4, 0xf5, 0x21, 0xb7, 0xe9, 0x7a, 0xef, 0xfd, 0x5e, 0x7d, 0xbc, 0xaf, 0xdf, + 0xc0, 0x8f, 0xce, 0xde, 0xf3, 0x35, 0xc3, 0xe9, 0x9e, 0x8d, 0xfa, 0xd4, 0xb3, 0x29, 0xa3, 0x7e, + 0x77, 0x4c, 0xed, 0x81, 0xe3, 0x75, 0xa5, 0x80, 0xb8, 0x46, 0x97, 0xb8, 0xae, 0xdf, 0x1d, 0xdf, + 0xee, 0x53, 0x46, 0x6e, 0x77, 0x87, 0xd4, 0xa6, 0x1e, 0x61, 0x74, 0xa0, 0xb9, 0x9e, 0xc3, 0x1c, + 0xb4, 0x16, 0x28, 0x6a, 0xc4, 0x35, 0x34, 0xae, 0xa8, 0x49, 0xc5, 0xf5, 0xed, 0xa1, 0xc1, 0x1e, + 0x8d, 0xfa, 0x9a, 0xee, 0x58, 0xdd, 0xa1, 0x33, 0x74, 0xba, 0x42, 0xbf, 0x3f, 0x7a, 0x28, 0xbe, + 0xc4, 0x87, 0xf8, 0x15, 0xe0, 0xac, 0xab, 0x09, 0x87, 0xba, 0xe3, 0xd1, 0xee, 0x38, 0xe7, 0x6b, + 0xfd, 0x9d, 0x58, 0xc7, 0x22, 0xfa, 0x23, 0xc3, 0xa6, 0xde, 0xa4, 0xeb, 0x9e, 0x0d, 0xf9, 0x82, + 0xdf, 0xb5, 0x28, 0x23, 0x45, 0x56, 0xdd, 0x32, 0x2b, 0x6f, 0x64, 0x33, 0xc3, 0xa2, 0x39, 0x83, + 0x77, 0x2f, 0x33, 0xf0, 0xf5, 0x47, 0xd4, 0x22, 0x39, 0xbb, 0xb7, 0xcb, 0xec, 0x46, 0xcc, 0x30, + 0xbb, 0x86, 0xcd, 0x7c, 0xe6, 0x65, 0x8d, 0xd4, 0xff, 0x28, 0x80, 0xf6, 0x1c, 0x9b, 0x79, 0x8e, + 0x69, 0x52, 0x0f, 0xd3, 0xb1, 0xe1, 0x1b, 0x8e, 0x8d, 0x3e, 0x87, 0x26, 0x3f, 0xcf, 0x80, 0x30, + 0xd2, 0x56, 0x36, 0x95, 0xad, 0xc5, 0x9d, 0xb7, 0xb4, 0xf8, 0xa6, 0x23, 0x78, 0xcd, 0x3d, 0x1b, + 0xf2, 0x05, 0x5f, 0xe3, 0xda, 0xda, 0xf8, 0xb6, 0x76, 0xd8, 0xff, 0x82, 0xea, 0xec, 0x80, 0x32, + 0xd2, 0x43, 0x4f, 0xce, 0x37, 0x66, 0xa6, 0xe7, 0x1b, 0x10, 0xaf, 0xe1, 0x08, 0x15, 0x1d, 0x42, + 0x5d, 0xa0, 0xd7, 0x04, 0xfa, 0x76, 0x29, 0xba, 0x3c, 0xb4, 0x86, 0xc9, 0xaf, 0xee, 0x3f, 0x66, + 0xd4, 0xe6, 0xdb, 0xeb, 0xbd, 0x20, 0xa1, 0xeb, 0xf7, 0x08, 0x23, 0x58, 0x00, 0xa1, 0x37, 0xa1, + 0xe9, 0xc9, 0xed, 0xb7, 0x67, 0x37, 0x95, 0xad, 0xd9, 0xde, 0x0d, 0xa9, 0xd5, 0x0c, 0x8f, 0x85, + 0x23, 0x0d, 0xf5, 0x89, 0x02, 0xb7, 0xf2, 0xe7, 0xde, 0x37, 0x7c, 0x86, 0x7e, 0x91, 0x3b, 0xbb, + 0x56, 0xed, 0xec, 0xdc, 0x5a, 0x9c, 0x3c, 0x72, 0x1c, 0xae, 0x24, 0xce, 0x7d, 0x04, 0x0d, 0x83, + 0x51, 0xcb, 0x6f, 0xd7, 0x36, 0x67, 0xb7, 0x16, 0x77, 0xde, 0xd0, 0x4a, 0x02, 0x58, 0xcb, 0xef, + 0xae, 0xb7, 0x24, 0x71, 0x1b, 0x0f, 0x38, 0x02, 0x0e, 0x80, 0xd4, 0xdf, 0xd6, 0x00, 0xee, 0x51, + 0xd7, 0x74, 0x26, 0x16, 0xb5, 0xd9, 0x35, 0x3c, 0xdd, 0x03, 0xa8, 0xfb, 0x2e, 0xd5, 0xe5, 0xd3, + 0xbd, 0x5a, 0x7a, 0x82, 0x78, 0x53, 0xc7, 0x2e, 0xd5, 0xe3, 0x47, 0xe3, 0x5f, 0x58, 0x40, 0xa0, + 0x4f, 0x60, 0xce, 0x67, 0x84, 0x8d, 0x7c, 0xf1, 0x64, 0x8b, 0x3b, 0xaf, 0x55, 0x01, 0x13, 0x06, + 0xbd, 0x96, 0x84, 0x9b, 0x0b, 0xbe, 0xb1, 0x04, 0x52, 0xff, 0x3e, 0x0b, 0x2b, 0xb1, 0xf2, 0x9e, + 0x63, 0x0f, 0x0c, 0xc6, 0x43, 0xfa, 0x2e, 0xd4, 0xd9, 0xc4, 0xa5, 0xe2, 0x4e, 0x16, 0x7a, 0xaf, + 0x86, 0x9b, 0x39, 0x99, 0xb8, 0xf4, 0xd9, 0xf9, 0xc6, 0x5a, 0x81, 0x09, 0x17, 0x61, 0x61, 0x84, + 0xf6, 0xa3, 0x7d, 0xd6, 0x84, 0xf9, 0x3b, 0x69, 0xe7, 0xcf, 0xce, 0x37, 0x0a, 0x0a, 0x88, 0x16, + 0x21, 0xa5, 0xb7, 0x88, 0x5e, 0x81, 0x39, 0x8f, 0x12, 0xdf, 0xb1, 0xdb, 0x75, 0x81, 0x16, 0x1d, + 0x05, 0x8b, 0x55, 0x2c, 0xa5, 0xe8, 0x35, 0x98, 0xb7, 0xa8, 0xef, 0x93, 0x21, 0x6d, 0x37, 0x84, + 0xe2, 0xb2, 0x54, 0x9c, 0x3f, 0x08, 0x96, 0x71, 0x28, 0x47, 0x5f, 0x40, 0xcb, 0x24, 0x3e, 0x3b, + 0x75, 0x07, 0x84, 0xd1, 0x13, 0xc3, 0xa2, 0xed, 0x39, 0x71, 0xa1, 0xaf, 0x57, 0x7b, 0x7b, 0x6e, + 0xd1, 0xbb, 0x25, 0xd1, 0x5b, 0xfb, 0x29, 0x24, 0x9c, 0x41, 0x46, 0x63, 0x40, 0x7c, 0xe5, 0xc4, + 0x23, 0xb6, 0x1f, 0x5c, 0x14, 0xf7, 0x37, 0x7f, 0x65, 0x7f, 0xeb, 0xd2, 0x1f, 0xda, 0xcf, 0xa1, + 0xe1, 0x02, 0x0f, 0xea, 0x1f, 0x15, 0x68, 0xc5, 0xcf, 0x74, 0x0d, 0xb9, 0xfa, 0x51, 0x3a, 0x57, + 0xbf, 0x5f, 0x21, 0x38, 0x4b, 0x72, 0xf4, 0x9f, 0x35, 0x40, 0xb1, 0x12, 0x76, 0x4c, 0xb3, 0x4f, + 0xf4, 0x33, 0xb4, 0x09, 0x75, 0x9b, 0x58, 0x61, 0x4c, 0x46, 0x09, 0xf2, 0x13, 0x62, 0x51, 0x2c, + 0x24, 0xe8, 0x4b, 0x05, 0xd0, 0x48, 0x5c, 0xfd, 0x60, 0xd7, 0xb6, 0x1d, 0x46, 0xf8, 0x6d, 0x84, + 0x1b, 0xda, 0xab, 0xb0, 0xa1, 0xd0, 0x97, 0x76, 0x9a, 0x43, 0xb9, 0x6f, 0x33, 0x6f, 0x12, 0xbf, + 0x42, 0x5e, 0x01, 0x17, 0xb8, 0x46, 0x3f, 0x07, 0xf0, 0x24, 0xe6, 0x89, 0x23, 0xd3, 0xb6, 0xbc, + 0x06, 0x84, 0xee, 0xf7, 0x1c, 0xfb, 0xa1, 0x31, 0x8c, 0x0b, 0x0b, 0x8e, 0x20, 0x70, 0x02, 0x6e, + 0xfd, 0x3e, 0xac, 0x95, 0xec, 0x13, 0xdd, 0x80, 0xd9, 0x33, 0x3a, 0x09, 0xae, 0x0a, 0xf3, 0x9f, + 0x68, 0x15, 0x1a, 0x63, 0x62, 0x8e, 0x68, 0x90, 0x93, 0x38, 0xf8, 0xb8, 0x53, 0x7b, 0x4f, 0x51, + 0xff, 0xd0, 0x48, 0x46, 0x0a, 0xaf, 0x37, 0x68, 0x8b, 0xb7, 0x07, 0xd7, 0x34, 0x74, 0xe2, 0x0b, + 0x8c, 0x46, 0xef, 0x85, 0xa0, 0x35, 0x04, 0x6b, 0x38, 0x92, 0xa2, 0x5f, 0x42, 0xd3, 0xa7, 0x26, + 0xd5, 0x99, 0xe3, 0xc9, 0x12, 0xf7, 0x76, 0xc5, 0x98, 0x22, 0x7d, 0x6a, 0x1e, 0x4b, 0xd3, 0x00, + 0x3e, 0xfc, 0xc2, 0x11, 0x24, 0xfa, 0x04, 0x9a, 0x8c, 0x5a, 0xae, 0x49, 0x18, 0x95, 0xb7, 0x97, + 0x8a, 0x2b, 0x5e, 0x3b, 0x38, 0xd8, 0x91, 0x33, 0x38, 0x91, 0x6a, 0xa2, 0x7a, 0x46, 0x71, 0x1a, + 0xae, 0xe2, 0x08, 0x06, 0xfd, 0x0c, 0x9a, 0x3e, 0xe3, 0x5d, 0x7d, 0x38, 0x11, 0x15, 0xe5, 0xa2, + 0xb6, 0x92, 0xac, 0xa3, 0x81, 0x49, 0x0c, 0x1d, 0xae, 0xe0, 0x08, 0x0e, 0xed, 0xc2, 0xb2, 0x65, + 0xd8, 0x98, 0x92, 0xc1, 0xe4, 0x98, 0xea, 0x8e, 0x3d, 0xf0, 0x45, 0x29, 0x6a, 0xf4, 0xd6, 0xa4, + 0xd1, 0xf2, 0x41, 0x5a, 0x8c, 0xb3, 0xfa, 0x68, 0x1f, 0x56, 0xc3, 0xb6, 0xfb, 0x91, 0xe1, 0x33, + 0xc7, 0x9b, 0xec, 0x1b, 0x96, 0xc1, 0x44, 0x81, 0x6a, 0xf4, 0xda, 0xd3, 0xf3, 0x8d, 0x55, 0x5c, + 0x20, 0xc7, 0x85, 0x56, 0xbc, 0x76, 0xba, 0x64, 0xe4, 0xd3, 0x81, 0x28, 0x38, 0xcd, 0xb8, 0x76, + 0x1e, 0x89, 0x55, 0x2c, 0xa5, 0xe8, 0xa7, 0xa9, 0x30, 0x6d, 0x5e, 0x2d, 0x4c, 0x5b, 0xe5, 0x21, + 0x8a, 0x4e, 0x61, 0xcd, 0xf5, 0x9c, 0xa1, 0x47, 0x7d, 0xff, 0x1e, 0x25, 0x03, 0xd3, 0xb0, 0x69, + 0x78, 0x33, 0x0b, 0xe2, 0x44, 0x2f, 0x4d, 0xcf, 0x37, 0xd6, 0x8e, 0x8a, 0x55, 0x70, 0x99, 0xad, + 0xfa, 0x97, 0x3a, 0xdc, 0xc8, 0xf6, 0x38, 0xf4, 0x31, 0x20, 0xa7, 0xef, 0x53, 0x6f, 0x4c, 0x07, + 0x1f, 0x06, 0x83, 0x1b, 0x9f, 0x6e, 0x14, 0x31, 0xdd, 0x44, 0x79, 0x7b, 0x98, 0xd3, 0xc0, 0x05, + 0x56, 0xc1, 0x7c, 0x24, 0x13, 0xa0, 0x26, 0x36, 0x9a, 0x98, 0x8f, 0x72, 0x49, 0xb0, 0x0b, 0xcb, + 0x32, 0xf7, 0x43, 0xa1, 0x08, 0xd6, 0xc4, 0xbb, 0x9f, 0xa6, 0xc5, 0x38, 0xab, 0x8f, 0x3e, 0x84, + 0x9b, 0x64, 0x4c, 0x0c, 0x93, 0xf4, 0x4d, 0x1a, 0x81, 0xd4, 0x05, 0xc8, 0x8b, 0x12, 0xe4, 0xe6, + 0x6e, 0x56, 0x01, 0xe7, 0x6d, 0xd0, 0x01, 0xac, 0x8c, 0xec, 0x3c, 0x54, 0x10, 0x87, 0x2f, 0x49, + 0xa8, 0x95, 0xd3, 0xbc, 0x0a, 0x2e, 0xb2, 0x43, 0x9f, 0x03, 0xe8, 0x61, 0x63, 0xf6, 0xdb, 0x73, + 0xa2, 0x92, 0xbe, 0x59, 0x21, 0x5f, 0xa2, 0x6e, 0x1e, 0x57, 0xb1, 0x68, 0xc9, 0xc7, 0x09, 0x4c, + 0x74, 0x17, 0x96, 0x3c, 0x9e, 0x01, 0xd1, 0x56, 0xe7, 0xc5, 0x56, 0xbf, 0x23, 0xcd, 0x96, 0x70, + 0x52, 0x88, 0xd3, 0xba, 0xe8, 0x0e, 0xb4, 0x74, 0xc7, 0x34, 0x45, 0xe4, 0xef, 0x39, 0x23, 0x9b, + 0x89, 0xe0, 0x6d, 0xf4, 0x10, 0xef, 0xcc, 0x7b, 0x29, 0x09, 0xce, 0x68, 0xaa, 0x7f, 0x56, 0x92, + 0x6d, 0x26, 0x4c, 0x67, 0x74, 0x27, 0x35, 0xfa, 0xbc, 0x92, 0x19, 0x7d, 0x6e, 0xe5, 0x2d, 0x12, + 0x93, 0x8f, 0x01, 0x4b, 0x3c, 0xf8, 0x0d, 0x7b, 0x18, 0x3c, 0xb8, 0x2c, 0x89, 0x6f, 0x5d, 0x98, + 0x4a, 0x91, 0x76, 0xa2, 0x31, 0xde, 0x14, 0x27, 0x4f, 0x0a, 0x71, 0x1a, 0x59, 0xfd, 0x00, 0x5a, + 0xe9, 0x3c, 0x4c, 0xcd, 0xf4, 0xca, 0xa5, 0x33, 0xfd, 0x37, 0x0a, 0xac, 0x95, 0x78, 0x47, 0x26, + 0xb4, 0x2c, 0xf2, 0x38, 0x11, 0x23, 0x97, 0xce, 0xc6, 0x9c, 0x35, 0x69, 0x01, 0x6b, 0xd2, 0x1e, + 0xd8, 0xec, 0xd0, 0x3b, 0x66, 0x9e, 0x61, 0x0f, 0x83, 0x77, 0x38, 0x48, 0x61, 0xe1, 0x0c, 0x36, + 0xfa, 0x0c, 0x9a, 0x16, 0x79, 0x7c, 0x3c, 0xf2, 0x86, 0x45, 0xf7, 0x55, 0xcd, 0x8f, 0xe8, 0x1f, + 0x07, 0x12, 0x05, 0x47, 0x78, 0xea, 0x21, 0x6c, 0xa6, 0x0e, 0xc9, 0x4b, 0x05, 0x7d, 0x38, 0x32, + 0x8f, 0x69, 0xfc, 0xe0, 0x6f, 0xc0, 0x82, 0x4b, 0x3c, 0x66, 0x44, 0xe5, 0xa2, 0xd1, 0x5b, 0x9a, + 0x9e, 0x6f, 0x2c, 0x1c, 0x85, 0x8b, 0x38, 0x96, 0xab, 0xff, 0x55, 0xa0, 0x71, 0xac, 0x13, 0x93, + 0x5e, 0x03, 0x75, 0xb8, 0x97, 0xa2, 0x0e, 0x6a, 0x69, 0x10, 0x89, 0xfd, 0x94, 0xb2, 0x86, 0xfd, + 0x0c, 0x6b, 0x78, 0xf9, 0x12, 0x9c, 0x8b, 0x09, 0xc3, 0xfb, 0xb0, 0x10, 0xb9, 0x4b, 0x55, 0x49, + 0xe5, 0xb2, 0x2a, 0xa9, 0xfe, 0xbe, 0x06, 0x8b, 0x09, 0x17, 0x57, 0xb3, 0xe6, 0xd7, 0x9d, 0x18, + 0x34, 0x78, 0x19, 0xda, 0xa9, 0x72, 0x10, 0x2d, 0x1c, 0x2a, 0x82, 0xf9, 0x2d, 0xee, 0xde, 0xf9, + 0x59, 0xe3, 0x03, 0x68, 0x31, 0xe2, 0x0d, 0x29, 0x0b, 0x65, 0xe2, 0xc2, 0x16, 0xe2, 0x49, 0xff, + 0x24, 0x25, 0xc5, 0x19, 0xed, 0xf5, 0xbb, 0xb0, 0x94, 0x72, 0x76, 0xa5, 0x21, 0xec, 0x4b, 0x7e, + 0x39, 0x71, 0x70, 0x5e, 0x43, 0x74, 0x7d, 0x9c, 0x8a, 0xae, 0xad, 0xf2, 0xcb, 0x4c, 0xa4, 0x4c, + 0x59, 0x8c, 0xe1, 0x4c, 0x8c, 0xbd, 0x5e, 0x09, 0xed, 0xe2, 0x48, 0xfb, 0x57, 0x0d, 0x56, 0x13, + 0xda, 0x31, 0x37, 0xfd, 0x61, 0xaa, 0x40, 0x6f, 0x65, 0x0a, 0x74, 0xbb, 0xc8, 0xe6, 0xb9, 0x91, + 0xd3, 0x62, 0x76, 0x37, 0xfb, 0xbc, 0xd9, 0xdd, 0x73, 0x20, 0xc5, 0xea, 0x9f, 0x14, 0x58, 0x4e, + 0xdc, 0xdd, 0x35, 0x30, 0xc6, 0x07, 0x69, 0xc6, 0xf8, 0x72, 0x95, 0xa0, 0x29, 0xa1, 0x8c, 0x7f, + 0x6d, 0xa4, 0x36, 0xff, 0xad, 0x27, 0x31, 0xbf, 0x86, 0xd5, 0xb1, 0x63, 0x8e, 0x2c, 0xba, 0x67, + 0x12, 0xc3, 0x0a, 0x15, 0xf8, 0xc4, 0x38, 0x9b, 0xfd, 0x63, 0x28, 0x82, 0xa7, 0x9e, 0x6f, 0xf8, + 0x8c, 0xda, 0xec, 0xd3, 0xd8, 0xb2, 0xf7, 0x5d, 0xe9, 0x64, 0xf5, 0xd3, 0x02, 0x38, 0x5c, 0xe8, + 0x04, 0xfd, 0x00, 0x16, 0xf9, 0xc0, 0x6c, 0xe8, 0x94, 0x73, 0x6f, 0x19, 0x58, 0x2b, 0x12, 0x68, + 0xf1, 0x38, 0x16, 0xe1, 0xa4, 0x1e, 0x7a, 0x04, 0x2b, 0xae, 0x33, 0x38, 0x20, 0x36, 0x19, 0x52, + 0x3e, 0x66, 0x1c, 0x39, 0xa6, 0xa1, 0x4f, 0x04, 0xb3, 0x59, 0xe8, 0xbd, 0x1b, 0x4e, 0xa6, 0x47, + 0x79, 0x95, 0x67, 0x9c, 0x22, 0xe4, 0x97, 0x45, 0x52, 0x17, 0x41, 0x22, 0x0f, 0x5a, 0x23, 0xd9, + 0xee, 0x25, 0xd1, 0x0b, 0xfe, 0x6f, 0xd9, 0xa9, 0x12, 0x61, 0xa7, 0x29, 0xcb, 0xb8, 0xfa, 0xa7, + 0xd7, 0x71, 0xc6, 0x43, 0x29, 0x71, 0x6b, 0xfe, 0x3f, 0xc4, 0x4d, 0xfd, 0x77, 0x1d, 0x6e, 0xe6, + 0x4a, 0x25, 0xfa, 0xf1, 0x05, 0x0c, 0xe7, 0xd6, 0x73, 0x63, 0x37, 0xb9, 0x01, 0x7d, 0xf6, 0x0a, + 0x03, 0xfa, 0x2e, 0x2c, 0xeb, 0x23, 0xcf, 0xa3, 0x36, 0xcb, 0xb0, 0x9a, 0x88, 0x1a, 0xed, 0xa5, + 0xc5, 0x38, 0xab, 0x5f, 0xc4, 0xae, 0x1a, 0x57, 0x64, 0x57, 0xc9, 0x5d, 0xc8, 0x09, 0x39, 0x08, + 0xbb, 0xfc, 0x2e, 0xe4, 0xa0, 0x9c, 0xd5, 0xe7, 0xd3, 0x41, 0x80, 0x1a, 0x21, 0xcc, 0xa7, 0xa7, + 0x83, 0xd3, 0x94, 0x14, 0x67, 0xb4, 0x0b, 0x98, 0xca, 0x42, 0x55, 0xa6, 0x82, 0x48, 0x8a, 0x84, + 0x81, 0xc8, 0xf1, 0xed, 0x2a, 0xb1, 0x5c, 0x99, 0x85, 0xa9, 0x7f, 0x53, 0xe0, 0xc5, 0xd2, 0x24, + 0x40, 0xbb, 0xa9, 0x96, 0xbb, 0x9d, 0x69, 0xb9, 0xdf, 0x2b, 0x35, 0x4c, 0xf4, 0x5d, 0xaf, 0x98, + 0x1a, 0xbd, 0x5f, 0x8d, 0x1a, 0x15, 0xcc, 0xed, 0x97, 0x73, 0xa4, 0xde, 0xf6, 0x93, 0xa7, 0x9d, + 0x99, 0xaf, 0x9e, 0x76, 0x66, 0xbe, 0x7e, 0xda, 0x99, 0xf9, 0xcd, 0xb4, 0xa3, 0x3c, 0x99, 0x76, + 0x94, 0xaf, 0xa6, 0x1d, 0xe5, 0xeb, 0x69, 0x47, 0xf9, 0xc7, 0xb4, 0xa3, 0xfc, 0xee, 0x9b, 0xce, + 0xcc, 0x67, 0xf3, 0xd2, 0xe3, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe9, 0x89, 0x29, 0x5c, 0x61, + 0x1b, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/apps/v1beta1/generated.proto b/vendor/k8s.io/api/apps/v1beta1/generated.proto index da160922d..6f41f06bc 100644 --- a/vendor/k8s.io/api/apps/v1beta1/generated.proto +++ b/vendor/k8s.io/api/apps/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,7 +22,6 @@ syntax = 'proto2'; package k8s.io.api.apps.v1beta1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; @@ -245,9 +244,9 @@ message RollingUpdateDeployment { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -259,10 +258,10 @@ message RollingUpdateDeployment { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is atmost 130% of desired pods. // +optional optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; diff --git a/vendor/k8s.io/api/apps/v1beta1/types.go b/vendor/k8s.io/api/apps/v1beta1/types.go index dd9e97e10..d462604d7 100644 --- a/vendor/k8s.io/api/apps/v1beta1/types.go +++ b/vendor/k8s.io/api/apps/v1beta1/types.go @@ -379,8 +379,8 @@ type RollbackConfig struct { const ( // DefaultDeploymentUniqueLabelKey is the default key of the selector that is added - // to existing RCs (and label key that is added to its pods) to prevent the existing RCs - // to select new pods (and old pods being select by new RC). + // to existing ReplicaSets (and label key that is added to its pods) to prevent the existing ReplicaSets + // to select new pods (and old pods being select by new ReplicaSet). DefaultDeploymentUniqueLabelKey string = "pod-template-hash" ) @@ -405,7 +405,7 @@ const ( // Kill all existing pods before creating new ones. RecreateDeploymentStrategyType DeploymentStrategyType = "Recreate" - // Replace the old RCs by new one using rolling update i.e gradually scale down the old RCs and scale up the new one. + // Replace the old ReplicaSets by new one using rolling update i.e gradually scale down the old ReplicaSets and scale up the new one. RollingUpdateDeploymentStrategyType DeploymentStrategyType = "RollingUpdate" ) @@ -416,9 +416,9 @@ type RollingUpdateDeployment struct { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -430,10 +430,10 @@ type RollingUpdateDeployment struct { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is atmost 130% of desired pods. // +optional MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` diff --git a/vendor/k8s.io/api/apps/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/apps/v1beta1/types_swagger_doc_generated.go index d12baf39f..68ebef348 100644 --- a/vendor/k8s.io/api/apps/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/apps/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_ControllerRevision = map[string]string{ "": "DEPRECATED - This group version of ControllerRevision is deprecated by apps/v1beta2/ControllerRevision. See the release notes for more information. ControllerRevision implements an immutable snapshot of state data. Clients are responsible for serializing and deserializing the objects that contain their internal state. Once a ControllerRevision has been successfully created, it can not be updated. The API Server will fail validation of all requests that attempt to mutate the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, it may be subject to name and representation changes in future releases, and clients should not depend on its stability. It is primarily for internal use by controllers.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -148,8 +148,8 @@ func (RollbackConfig) SwaggerDoc() map[string]string { var map_RollingUpdateDeployment = map[string]string{ "": "Spec to control the desired behavior of rolling update.", - "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", - "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", + "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", } func (RollingUpdateDeployment) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/api/apps/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/apps/v1beta1/zz_generated.deepcopy.go index b06032e1e..dd37f8dd8 100644 --- a/vendor/k8s.io/api/apps/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/apps/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/apps/v1beta2/generated.pb.go b/vendor/k8s.io/api/apps/v1beta2/generated.pb.go index cfd422edb..72d832c34 100644 --- a/vendor/k8s.io/api/apps/v1beta2/generated.pb.go +++ b/vendor/k8s.io/api/apps/v1beta2/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -64,7 +64,6 @@ import fmt "fmt" import math "math" import k8s_io_api_core_v1 "k8s.io/api/core/v1" - import k8s_io_apimachinery_pkg_apis_meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" import k8s_io_apimachinery_pkg_util_intstr "k8s.io/apimachinery/pkg/util/intstr" @@ -7445,142 +7444,141 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2186 bytes of a gzipped FileDescriptorProto + // 2176 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcb, 0x6f, 0x1c, 0xb7, - 0x19, 0xf7, 0xec, 0x43, 0x5a, 0x51, 0x96, 0x64, 0x53, 0xaa, 0xb4, 0x91, 0xdb, 0x95, 0xb1, 0x09, - 0x1c, 0x39, 0xb6, 0x66, 0x6d, 0xe5, 0x81, 0xc4, 0x2e, 0xda, 0x6a, 0xa5, 0xd4, 0x76, 0xa0, 0x57, + 0x19, 0xd7, 0xec, 0x43, 0x5a, 0x51, 0x91, 0x64, 0x53, 0xaa, 0xb4, 0x91, 0xdb, 0x95, 0xb1, 0x09, + 0x1c, 0x25, 0xb6, 0x66, 0x6d, 0xe5, 0x81, 0xc4, 0x2e, 0xda, 0x6a, 0xa5, 0xd4, 0x76, 0xa0, 0x57, 0x28, 0xcb, 0x40, 0x83, 0x16, 0x35, 0xb5, 0x4b, 0xaf, 0x26, 0x9a, 0x17, 0x66, 0x38, 0x5b, 0x2f, 0x7a, 0xe9, 0xa9, 0x40, 0x81, 0x02, 0x6d, 0xaf, 0xfd, 0x27, 0x7a, 0x2b, 0x8a, 0xf6, 0x56, 0x04, 0x85, 0x2f, 0x05, 0x82, 0x5e, 0x92, 0x93, 0x50, 0x6f, 0x4e, 0x45, 0xd1, 0x4b, 0x81, 0x5e, 0x02, 0x14, 0x28, 0xc8, 0xe1, 0x3c, 0x38, 0x0f, 0xef, 0x48, 0xb1, 0x95, 0x22, 0xc8, 0x6d, 0x87, 0xfc, - 0x7d, 0x3f, 0x7e, 0x24, 0xbf, 0x8f, 0xdf, 0x6f, 0x38, 0x0b, 0xbe, 0x77, 0xf4, 0xb6, 0xab, 0x6a, - 0x56, 0xeb, 0xc8, 0x3b, 0x20, 0x8e, 0x49, 0x28, 0x71, 0x5b, 0x7d, 0x62, 0x76, 0x2d, 0xa7, 0x25, - 0x3a, 0xb0, 0xad, 0xb5, 0xb0, 0x6d, 0xbb, 0xad, 0xfe, 0xcd, 0x03, 0x42, 0xf1, 0x6a, 0xab, 0x47, - 0x4c, 0xe2, 0x60, 0x4a, 0xba, 0xaa, 0xed, 0x58, 0xd4, 0x82, 0x0b, 0x3e, 0x50, 0xc5, 0xb6, 0xa6, - 0x32, 0xa0, 0x2a, 0x80, 0x8b, 0x2b, 0x3d, 0x8d, 0x1e, 0x7a, 0x07, 0x6a, 0xc7, 0x32, 0x5a, 0x3d, - 0xab, 0x67, 0xb5, 0x38, 0xfe, 0xc0, 0x7b, 0xc4, 0x9f, 0xf8, 0x03, 0xff, 0xe5, 0xf3, 0x2c, 0x36, - 0x63, 0x03, 0x76, 0x2c, 0x87, 0xb4, 0xfa, 0x37, 0x93, 0x63, 0x2d, 0x5e, 0x8d, 0x61, 0x6c, 0x4b, - 0xd7, 0x3a, 0x03, 0xe1, 0x56, 0x1a, 0xfa, 0x46, 0x04, 0x35, 0x70, 0xe7, 0x50, 0x33, 0x89, 0x33, - 0x68, 0xd9, 0x47, 0x3d, 0xd6, 0xe0, 0xb6, 0x0c, 0x42, 0x71, 0xd6, 0x00, 0xad, 0x3c, 0x2b, 0xc7, - 0x33, 0xa9, 0x66, 0x90, 0x94, 0xc1, 0x5b, 0xa3, 0x0c, 0xdc, 0xce, 0x21, 0x31, 0x70, 0xca, 0xee, - 0xf5, 0x3c, 0x3b, 0x8f, 0x6a, 0x7a, 0x4b, 0x33, 0xa9, 0x4b, 0x9d, 0xa4, 0x51, 0xf3, 0x3f, 0x0a, - 0x80, 0xeb, 0x96, 0x49, 0x1d, 0x4b, 0xd7, 0x89, 0x83, 0x48, 0x5f, 0x73, 0x35, 0xcb, 0x84, 0x0f, - 0x41, 0x8d, 0xcd, 0xa7, 0x8b, 0x29, 0xae, 0x2b, 0x97, 0x95, 0xe5, 0xc9, 0xd5, 0x1b, 0x6a, 0xb4, - 0x29, 0x21, 0xbd, 0x6a, 0x1f, 0xf5, 0x58, 0x83, 0xab, 0x32, 0xb4, 0xda, 0xbf, 0xa9, 0xee, 0x1c, - 0x7c, 0x48, 0x3a, 0x74, 0x8b, 0x50, 0xdc, 0x86, 0x4f, 0x8e, 0x97, 0xce, 0x0d, 0x8f, 0x97, 0x40, - 0xd4, 0x86, 0x42, 0x56, 0xb8, 0x03, 0x2a, 0x9c, 0xbd, 0xc4, 0xd9, 0x57, 0x72, 0xd9, 0xc5, 0xa4, - 0x55, 0x84, 0x7f, 0xf2, 0xee, 0x63, 0x4a, 0x4c, 0xe6, 0x5e, 0xfb, 0xbc, 0xa0, 0xae, 0x6c, 0x60, - 0x8a, 0x11, 0x27, 0x82, 0xd7, 0x41, 0xcd, 0x11, 0xee, 0xd7, 0xcb, 0x97, 0x95, 0xe5, 0x72, 0xfb, - 0x82, 0x40, 0xd5, 0x82, 0x69, 0xa1, 0x10, 0xd1, 0x7c, 0xa2, 0x80, 0xf9, 0xf4, 0xbc, 0x37, 0x35, - 0x97, 0xc2, 0x1f, 0xa6, 0xe6, 0xae, 0x16, 0x9b, 0x3b, 0xb3, 0xe6, 0x33, 0x0f, 0x07, 0x0e, 0x5a, - 0x62, 0xf3, 0xde, 0x05, 0x55, 0x8d, 0x12, 0xc3, 0xad, 0x97, 0x2e, 0x97, 0x97, 0x27, 0x57, 0xaf, - 0xa9, 0x39, 0xb1, 0xae, 0xa6, 0xbd, 0x6b, 0x4f, 0x09, 0xde, 0xea, 0x3d, 0xc6, 0x80, 0x7c, 0xa2, - 0xe6, 0x2f, 0x4a, 0x60, 0x62, 0x03, 0x13, 0xc3, 0x32, 0xf7, 0x08, 0x3d, 0x83, 0x9d, 0xbb, 0x0b, - 0x2a, 0xae, 0x4d, 0x3a, 0x62, 0xe7, 0xae, 0xe4, 0x4e, 0x20, 0xf4, 0x69, 0xcf, 0x26, 0x9d, 0x68, - 0xcb, 0xd8, 0x13, 0xe2, 0x0c, 0x70, 0x17, 0x8c, 0xb9, 0x14, 0x53, 0xcf, 0xe5, 0x1b, 0x36, 0xb9, - 0xba, 0x5c, 0x80, 0x8b, 0xe3, 0xdb, 0xd3, 0x82, 0x6d, 0xcc, 0x7f, 0x46, 0x82, 0xa7, 0xf9, 0x8f, - 0x12, 0x80, 0x21, 0x76, 0xdd, 0x32, 0xbb, 0x1a, 0x65, 0xe1, 0x7c, 0x0b, 0x54, 0xe8, 0xc0, 0x26, - 0x7c, 0x41, 0x26, 0xda, 0x57, 0x02, 0x57, 0xee, 0x0f, 0x6c, 0xf2, 0xf9, 0xf1, 0xd2, 0x7c, 0xda, - 0x82, 0xf5, 0x20, 0x6e, 0x03, 0x37, 0x43, 0x27, 0x4b, 0xdc, 0xfa, 0x0d, 0x79, 0xe8, 0xcf, 0x8f, - 0x97, 0x32, 0x8e, 0x19, 0x35, 0x64, 0x92, 0x1d, 0x84, 0x7d, 0x00, 0x75, 0xec, 0xd2, 0xfb, 0x0e, - 0x36, 0x5d, 0x7f, 0x24, 0xcd, 0x20, 0x62, 0xfa, 0xaf, 0x15, 0xdb, 0x28, 0x66, 0xd1, 0x5e, 0x14, - 0x5e, 0xc0, 0xcd, 0x14, 0x1b, 0xca, 0x18, 0x01, 0x5e, 0x01, 0x63, 0x0e, 0xc1, 0xae, 0x65, 0xd6, - 0x2b, 0x7c, 0x16, 0xe1, 0x02, 0x22, 0xde, 0x8a, 0x44, 0x2f, 0xbc, 0x0a, 0xc6, 0x0d, 0xe2, 0xba, - 0xb8, 0x47, 0xea, 0x55, 0x0e, 0x9c, 0x11, 0xc0, 0xf1, 0x2d, 0xbf, 0x19, 0x05, 0xfd, 0xcd, 0xdf, - 0x2b, 0x60, 0x2a, 0x5c, 0xb9, 0x33, 0xc8, 0x9c, 0x3b, 0x72, 0xe6, 0x34, 0x47, 0x07, 0x4b, 0x4e, - 0xc2, 0x7c, 0x54, 0x8e, 0x39, 0xce, 0xc2, 0x11, 0xfe, 0x08, 0xd4, 0x5c, 0xa2, 0x93, 0x0e, 0xb5, - 0x1c, 0xe1, 0xf8, 0xeb, 0x05, 0x1d, 0xc7, 0x07, 0x44, 0xdf, 0x13, 0xa6, 0xed, 0xf3, 0xcc, 0xf3, - 0xe0, 0x09, 0x85, 0x94, 0xf0, 0x7d, 0x50, 0xa3, 0xc4, 0xb0, 0x75, 0x4c, 0x89, 0xc8, 0x9a, 0x97, - 0xe3, 0xce, 0xb3, 0x98, 0x61, 0x64, 0xbb, 0x56, 0xf7, 0xbe, 0x80, 0xf1, 0x94, 0x09, 0x17, 0x23, - 0x68, 0x45, 0x21, 0x0d, 0xb4, 0xc1, 0xb4, 0x67, 0x77, 0x19, 0x92, 0xb2, 0xe3, 0xbc, 0x37, 0x10, - 0x31, 0x74, 0x63, 0xf4, 0xaa, 0xec, 0x4b, 0x76, 0xed, 0x79, 0x31, 0xca, 0xb4, 0xdc, 0x8e, 0x12, - 0xfc, 0x70, 0x0d, 0xcc, 0x18, 0x9a, 0x89, 0x08, 0xee, 0x0e, 0xf6, 0x48, 0xc7, 0x32, 0xbb, 0x2e, - 0x0f, 0xa5, 0x6a, 0x7b, 0x41, 0x10, 0xcc, 0x6c, 0xc9, 0xdd, 0x28, 0x89, 0x87, 0x9b, 0x60, 0x2e, - 0x38, 0x80, 0xef, 0x6a, 0x2e, 0xb5, 0x9c, 0xc1, 0xa6, 0x66, 0x68, 0xb4, 0x3e, 0xc6, 0x79, 0xea, - 0xc3, 0xe3, 0xa5, 0x39, 0x94, 0xd1, 0x8f, 0x32, 0xad, 0x9a, 0xbf, 0x19, 0x03, 0x33, 0x89, 0x73, - 0x01, 0x3e, 0x00, 0xf3, 0x1d, 0xcf, 0x71, 0x88, 0x49, 0xb7, 0x3d, 0xe3, 0x80, 0x38, 0x7b, 0x9d, - 0x43, 0xd2, 0xf5, 0x74, 0xd2, 0xe5, 0xdb, 0x5a, 0x6d, 0x37, 0x84, 0xaf, 0xf3, 0xeb, 0x99, 0x28, - 0x94, 0x63, 0x0d, 0xdf, 0x03, 0xd0, 0xe4, 0x4d, 0x5b, 0x9a, 0xeb, 0x86, 0x9c, 0x25, 0xce, 0x19, - 0xa6, 0xe2, 0x76, 0x0a, 0x81, 0x32, 0xac, 0x98, 0x8f, 0x5d, 0xe2, 0x6a, 0x0e, 0xe9, 0x26, 0x7d, - 0x2c, 0xcb, 0x3e, 0x6e, 0x64, 0xa2, 0x50, 0x8e, 0x35, 0x7c, 0x13, 0x4c, 0xfa, 0xa3, 0xf1, 0x35, - 0x17, 0x9b, 0x33, 0x2b, 0xc8, 0x26, 0xb7, 0xa3, 0x2e, 0x14, 0xc7, 0xb1, 0xa9, 0x59, 0x07, 0x2e, - 0x71, 0xfa, 0xa4, 0x7b, 0xc7, 0x17, 0x07, 0xac, 0x82, 0x56, 0x79, 0x05, 0x0d, 0xa7, 0xb6, 0x93, - 0x42, 0xa0, 0x0c, 0x2b, 0x36, 0x35, 0x3f, 0x6a, 0x52, 0x53, 0x1b, 0x93, 0xa7, 0xb6, 0x9f, 0x89, - 0x42, 0x39, 0xd6, 0x2c, 0xf6, 0x7c, 0x97, 0xd7, 0xfa, 0x58, 0xd3, 0xf1, 0x81, 0x4e, 0xea, 0xe3, - 0x72, 0xec, 0x6d, 0xcb, 0xdd, 0x28, 0x89, 0x87, 0x77, 0xc0, 0x45, 0xbf, 0x69, 0xdf, 0xc4, 0x21, - 0x49, 0x8d, 0x93, 0xbc, 0x24, 0x48, 0x2e, 0x6e, 0x27, 0x01, 0x28, 0x6d, 0x03, 0x6f, 0x81, 0xe9, - 0x8e, 0xa5, 0xeb, 0x3c, 0x1e, 0xd7, 0x2d, 0xcf, 0xa4, 0xf5, 0x09, 0xce, 0x02, 0x59, 0x0e, 0xad, - 0x4b, 0x3d, 0x28, 0x81, 0x84, 0x3f, 0x06, 0xa0, 0x13, 0x14, 0x06, 0xb7, 0x0e, 0x46, 0x28, 0x80, - 0x74, 0x59, 0x8a, 0x2a, 0x73, 0xd8, 0xe4, 0xa2, 0x18, 0x65, 0xf3, 0x23, 0x05, 0x2c, 0xe4, 0x24, - 0x3a, 0xfc, 0xae, 0x54, 0x04, 0xaf, 0x25, 0x8a, 0xe0, 0xa5, 0x1c, 0xb3, 0x58, 0x25, 0x3c, 0x04, - 0x53, 0x4c, 0x90, 0x68, 0x66, 0xcf, 0x87, 0x88, 0xb3, 0xac, 0x95, 0x3b, 0x01, 0x14, 0x47, 0x47, - 0xa7, 0xf2, 0xc5, 0xe1, 0xf1, 0xd2, 0x94, 0xd4, 0x87, 0x64, 0xe2, 0xe6, 0x2f, 0x4b, 0x00, 0x6c, - 0x10, 0x5b, 0xb7, 0x06, 0x06, 0x31, 0xcf, 0x42, 0xd3, 0xdc, 0x93, 0x34, 0xcd, 0xab, 0xf9, 0x5b, - 0x12, 0x3a, 0x95, 0x2b, 0x6a, 0xde, 0x4f, 0x88, 0x9a, 0xab, 0x45, 0xc8, 0x9e, 0xad, 0x6a, 0x3e, - 0x29, 0x83, 0xd9, 0x08, 0x1c, 0xc9, 0x9a, 0xdb, 0xd2, 0x8e, 0xbe, 0x9a, 0xd8, 0xd1, 0x85, 0x0c, - 0x93, 0x17, 0xa6, 0x6b, 0x9e, 0xbf, 0xbe, 0x80, 0x1f, 0x82, 0x69, 0x26, 0x64, 0xfc, 0x90, 0xe0, - 0x32, 0x69, 0xec, 0xc4, 0x32, 0x29, 0x2c, 0x6e, 0x9b, 0x12, 0x13, 0x4a, 0x30, 0xe7, 0xc8, 0xb2, - 0xf1, 0x17, 0x2d, 0xcb, 0x9a, 0x7f, 0x50, 0xc0, 0x74, 0xb4, 0x4d, 0x67, 0x20, 0xa2, 0xee, 0xca, - 0x22, 0xea, 0xe5, 0x02, 0xc1, 0x99, 0xa3, 0xa2, 0x3e, 0xa9, 0xc4, 0x5d, 0xe7, 0x32, 0x6a, 0x99, - 0xbd, 0x82, 0xd9, 0xba, 0xd6, 0xc1, 0xae, 0xa8, 0xb7, 0xe7, 0xfd, 0xd7, 0x2f, 0xbf, 0x0d, 0x85, - 0xbd, 0x92, 0xe0, 0x2a, 0xbd, 0x58, 0xc1, 0x55, 0x7e, 0x3e, 0x82, 0xeb, 0x07, 0xa0, 0xe6, 0x06, - 0x52, 0xab, 0xc2, 0x29, 0xaf, 0x15, 0x4a, 0x6c, 0xa1, 0xb2, 0x42, 0xea, 0x50, 0x5f, 0x85, 0x74, - 0x59, 0xca, 0xaa, 0xfa, 0x65, 0x2a, 0x2b, 0x96, 0xcc, 0x36, 0xf6, 0x5c, 0xd2, 0xe5, 0x19, 0x50, - 0x8b, 0x92, 0x79, 0x97, 0xb7, 0x22, 0xd1, 0x0b, 0xf7, 0xc1, 0x82, 0xed, 0x58, 0x3d, 0x87, 0xb8, - 0xee, 0x06, 0xc1, 0x5d, 0x5d, 0x33, 0x49, 0x30, 0x01, 0xbf, 0x26, 0x5e, 0x1a, 0x1e, 0x2f, 0x2d, - 0xec, 0x66, 0x43, 0x50, 0x9e, 0x6d, 0xf3, 0xcf, 0x15, 0x70, 0x21, 0x79, 0x36, 0xe6, 0xc8, 0x14, - 0xe5, 0x54, 0x32, 0xe5, 0x7a, 0x2c, 0x4e, 0x7d, 0x0d, 0x17, 0xbb, 0x2a, 0x48, 0xc5, 0xea, 0x1a, - 0x98, 0x11, 0xb2, 0x24, 0xe8, 0x14, 0x42, 0x2d, 0xdc, 0x9e, 0x7d, 0xb9, 0x1b, 0x25, 0xf1, 0x4c, - 0x7c, 0x44, 0x9a, 0x22, 0x20, 0xa9, 0xc8, 0xe2, 0x63, 0x2d, 0x09, 0x40, 0x69, 0x1b, 0xb8, 0x05, - 0x66, 0x3d, 0x33, 0x4d, 0xe5, 0x87, 0xcb, 0x25, 0x41, 0x35, 0xbb, 0x9f, 0x86, 0xa0, 0x2c, 0x3b, - 0xf8, 0x50, 0xd2, 0x23, 0x63, 0xfc, 0x48, 0xb8, 0x5e, 0x20, 0xac, 0x0b, 0x0b, 0x12, 0x78, 0x1b, - 0x4c, 0x39, 0x5c, 0x73, 0x06, 0xae, 0xfa, 0xba, 0xed, 0x1b, 0xc2, 0x6c, 0x0a, 0xc5, 0x3b, 0x91, - 0x8c, 0xcd, 0x90, 0x5a, 0xb5, 0xa2, 0x52, 0xab, 0xf9, 0x27, 0x05, 0xc0, 0x74, 0x1e, 0x8e, 0xbc, - 0x09, 0x48, 0x59, 0xc4, 0x2a, 0xa6, 0x96, 0xad, 0x7f, 0x6e, 0x14, 0xd4, 0x3f, 0xd1, 0x81, 0x5a, - 0x4c, 0x00, 0x89, 0x65, 0x38, 0x9b, 0x4b, 0x9d, 0xa2, 0x02, 0x28, 0x72, 0xea, 0x39, 0x08, 0xa0, - 0x18, 0xd9, 0xb3, 0x05, 0xd0, 0x3f, 0x4b, 0x60, 0x36, 0x02, 0x17, 0x16, 0x40, 0x19, 0x26, 0x5f, - 0x5f, 0xec, 0x8c, 0xbe, 0xd8, 0x61, 0xa2, 0x24, 0x5a, 0xba, 0xff, 0x27, 0x51, 0x12, 0x79, 0x95, - 0x23, 0x4a, 0x7e, 0x57, 0x8a, 0xbb, 0xfe, 0x95, 0x17, 0x25, 0x5f, 0xfc, 0x4e, 0xa6, 0xf9, 0x97, - 0x32, 0xb8, 0x90, 0xcc, 0x43, 0xa9, 0x40, 0x2a, 0x23, 0x0b, 0xe4, 0x2e, 0x98, 0x7b, 0xe4, 0xe9, - 0xfa, 0x80, 0x2f, 0x43, 0xac, 0x4a, 0xfa, 0xa5, 0xf5, 0x9b, 0xc2, 0x72, 0xee, 0xfb, 0x19, 0x18, - 0x94, 0x69, 0x99, 0x53, 0xec, 0xcb, 0xa7, 0x2a, 0xf6, 0xa9, 0x0a, 0x54, 0x39, 0x41, 0x05, 0xca, - 0x2c, 0xdc, 0xd5, 0x53, 0x14, 0xee, 0x93, 0x55, 0xda, 0x8c, 0x83, 0x6b, 0xe4, 0xab, 0xff, 0xcf, - 0x15, 0x30, 0x9f, 0xfd, 0xc2, 0x0d, 0x75, 0x30, 0x6d, 0xe0, 0xc7, 0xf1, 0x8b, 0x8f, 0x51, 0x45, - 0xc4, 0xa3, 0x9a, 0xae, 0xfa, 0x9f, 0x8c, 0xd4, 0x7b, 0x26, 0xdd, 0x71, 0xf6, 0xa8, 0xa3, 0x99, - 0x3d, 0xbf, 0xf2, 0x6e, 0x49, 0x5c, 0x28, 0xc1, 0xdd, 0xfc, 0x4c, 0x01, 0x0b, 0x39, 0x95, 0xef, - 0x6c, 0x3d, 0x81, 0x1f, 0x80, 0x9a, 0x81, 0x1f, 0xef, 0x79, 0x4e, 0x2f, 0xab, 0x56, 0x17, 0x1b, - 0x87, 0x67, 0xf3, 0x96, 0x60, 0x41, 0x21, 0x5f, 0x73, 0x07, 0x5c, 0x96, 0x26, 0xc9, 0x32, 0x87, - 0x3c, 0xf2, 0x74, 0x9e, 0x44, 0x42, 0x6c, 0x5c, 0x03, 0x13, 0x36, 0x76, 0xa8, 0x16, 0x4a, 0xd5, - 0x6a, 0x7b, 0x6a, 0x78, 0xbc, 0x34, 0xb1, 0x1b, 0x34, 0xa2, 0xa8, 0xbf, 0xf9, 0x5f, 0x05, 0x54, - 0xf7, 0x3a, 0x58, 0x27, 0x67, 0x50, 0xed, 0x37, 0xa4, 0x6a, 0x9f, 0x7f, 0x93, 0xce, 0xfd, 0xc9, - 0x2d, 0xf4, 0x9b, 0x89, 0x42, 0xff, 0xca, 0x08, 0x9e, 0x67, 0xd7, 0xf8, 0x77, 0xc0, 0x44, 0x38, - 0xdc, 0xc9, 0x0e, 0xa0, 0xe6, 0x6f, 0x4b, 0x60, 0x32, 0x36, 0xc4, 0x09, 0x8f, 0xaf, 0x87, 0xd2, - 0xb1, 0xcf, 0x12, 0x73, 0xb5, 0xc8, 0x44, 0xd4, 0xe0, 0x88, 0x7f, 0xd7, 0xa4, 0x4e, 0xfc, 0x05, - 0x2f, 0x7d, 0xf2, 0x7f, 0x07, 0x4c, 0x53, 0xec, 0xf4, 0x08, 0x0d, 0xfa, 0xf8, 0x82, 0x4d, 0x44, - 0xb7, 0x13, 0xf7, 0xa5, 0x5e, 0x94, 0x40, 0x2f, 0xde, 0x06, 0x53, 0xd2, 0x60, 0xf0, 0x02, 0x28, - 0x1f, 0x91, 0x81, 0x2f, 0x7b, 0x10, 0xfb, 0x09, 0xe7, 0x40, 0xb5, 0x8f, 0x75, 0xcf, 0x8f, 0xf3, - 0x09, 0xe4, 0x3f, 0xdc, 0x2a, 0xbd, 0xad, 0x34, 0x7f, 0xc5, 0x16, 0x27, 0x0a, 0xce, 0x33, 0x88, - 0xae, 0xf7, 0xa4, 0xe8, 0xca, 0xff, 0xa8, 0x17, 0x4f, 0x99, 0xbc, 0x18, 0x43, 0x89, 0x18, 0x7b, - 0xad, 0x10, 0xdb, 0xb3, 0x23, 0xed, 0x5f, 0x25, 0x30, 0x17, 0x43, 0x47, 0x72, 0xf2, 0xdb, 0x92, - 0x9c, 0x5c, 0x4e, 0xc8, 0xc9, 0x7a, 0x96, 0xcd, 0xd7, 0x7a, 0x72, 0xb4, 0x9e, 0xfc, 0xa3, 0x02, - 0x66, 0x62, 0x6b, 0x77, 0x06, 0x82, 0xf2, 0x9e, 0x2c, 0x28, 0x5f, 0x29, 0x12, 0x34, 0x39, 0x8a, - 0xf2, 0xaf, 0x55, 0xc9, 0xf9, 0xaf, 0xbc, 0xa4, 0xfc, 0x29, 0x98, 0xeb, 0x5b, 0xba, 0x67, 0x90, - 0x75, 0x1d, 0x6b, 0x46, 0x00, 0x60, 0xaa, 0xa9, 0x9c, 0x7c, 0x97, 0x0b, 0xe9, 0x89, 0xe3, 0x6a, - 0x2e, 0x25, 0x26, 0x7d, 0x10, 0x59, 0x46, 0xba, 0xef, 0x41, 0x06, 0x1d, 0xca, 0x1c, 0x04, 0xbe, - 0x09, 0x26, 0x99, 0x7e, 0xd3, 0x3a, 0x64, 0x1b, 0x1b, 0x41, 0x60, 0x85, 0x9f, 0xb0, 0xf6, 0xa2, - 0x2e, 0x14, 0xc7, 0xc1, 0x43, 0x30, 0x6b, 0x5b, 0xdd, 0x2d, 0x6c, 0xe2, 0x1e, 0x61, 0x32, 0x63, - 0x97, 0xff, 0x8f, 0x87, 0x5f, 0x7e, 0x4d, 0xb4, 0xdf, 0x0a, 0x6e, 0x45, 0x76, 0xd3, 0x10, 0xf6, - 0x92, 0x98, 0xd1, 0xcc, 0x93, 0x3a, 0x8b, 0x12, 0x3a, 0xa9, 0xcf, 0xae, 0xfe, 0x1d, 0xf1, 0x6a, - 0x91, 0x08, 0x3b, 0xe5, 0x87, 0xd7, 0xbc, 0xbb, 0xbd, 0xda, 0xa9, 0xbe, 0x9a, 0xfe, 0xbb, 0x02, - 0x2e, 0xa6, 0x8e, 0xca, 0x2f, 0xf1, 0x76, 0x2d, 0x25, 0xcf, 0xcb, 0x27, 0x90, 0xe7, 0x6b, 0x60, - 0x46, 0x7c, 0xb0, 0x4d, 0xa8, 0xfb, 0xf0, 0xfd, 0x67, 0x5d, 0xee, 0x46, 0x49, 0x7c, 0xd6, 0xed, - 0x5e, 0xf5, 0x84, 0xb7, 0x7b, 0x71, 0x2f, 0xc4, 0x1f, 0x90, 0xfc, 0xd0, 0x4b, 0x7b, 0x21, 0xfe, - 0x87, 0x94, 0xc4, 0x33, 0x85, 0xe0, 0xb3, 0x86, 0x0c, 0xe3, 0xb2, 0x42, 0xd8, 0x97, 0x7a, 0x51, - 0x02, 0xfd, 0x85, 0x3e, 0x4a, 0xe2, 0x8c, 0x8f, 0x92, 0x2b, 0x45, 0xe2, 0xb9, 0xf8, 0xbb, 0xc9, - 0xdf, 0x14, 0xf0, 0x52, 0x6e, 0x22, 0xc0, 0x35, 0xa9, 0xec, 0xae, 0x24, 0xca, 0xee, 0xb7, 0x72, - 0x0d, 0x63, 0xb5, 0xd7, 0xc9, 0xbe, 0x9a, 0x7b, 0xa7, 0xd8, 0xd5, 0x5c, 0x86, 0x76, 0x1f, 0x7d, - 0x47, 0xd7, 0x5e, 0x79, 0xf2, 0xb4, 0x71, 0xee, 0xe3, 0xa7, 0x8d, 0x73, 0x9f, 0x3e, 0x6d, 0x9c, - 0xfb, 0xd9, 0xb0, 0xa1, 0x3c, 0x19, 0x36, 0x94, 0x8f, 0x87, 0x0d, 0xe5, 0xd3, 0x61, 0x43, 0xf9, - 0xfb, 0xb0, 0xa1, 0xfc, 0xfa, 0xb3, 0xc6, 0xb9, 0x0f, 0xc6, 0xc5, 0x88, 0xff, 0x0b, 0x00, 0x00, - 0xff, 0xff, 0xe4, 0x8f, 0x6a, 0x57, 0x17, 0x29, 0x00, 0x00, + 0x7d, 0x3f, 0x7e, 0x24, 0xbf, 0x8f, 0xdf, 0x6f, 0x38, 0x0b, 0xbe, 0x77, 0xfc, 0xb6, 0xab, 0x6a, + 0x56, 0xeb, 0xd8, 0x3b, 0x24, 0x8e, 0x49, 0x28, 0x71, 0x5b, 0x7d, 0x62, 0x76, 0x2d, 0xa7, 0x25, + 0x3a, 0xb0, 0xad, 0xb5, 0xb0, 0x6d, 0xbb, 0xad, 0xfe, 0x8d, 0x43, 0x42, 0xf1, 0x5a, 0xab, 0x47, + 0x4c, 0xe2, 0x60, 0x4a, 0xba, 0xaa, 0xed, 0x58, 0xd4, 0x82, 0x8b, 0x3e, 0x50, 0xc5, 0xb6, 0xa6, + 0x32, 0xa0, 0x2a, 0x80, 0x4b, 0xab, 0x3d, 0x8d, 0x1e, 0x79, 0x87, 0x6a, 0xc7, 0x32, 0x5a, 0x3d, + 0xab, 0x67, 0xb5, 0x38, 0xfe, 0xd0, 0x7b, 0xc8, 0x9f, 0xf8, 0x03, 0xff, 0xe5, 0xf3, 0x2c, 0x35, + 0x63, 0x03, 0x76, 0x2c, 0x87, 0xb4, 0xfa, 0x37, 0x92, 0x63, 0x2d, 0xbd, 0x11, 0x61, 0x0c, 0xdc, + 0x39, 0xd2, 0x4c, 0xe2, 0x0c, 0x5a, 0xf6, 0x71, 0x8f, 0x35, 0xb8, 0x2d, 0x83, 0x50, 0x9c, 0x65, + 0xd5, 0xca, 0xb3, 0x72, 0x3c, 0x93, 0x6a, 0x06, 0x49, 0x19, 0xbc, 0x35, 0xca, 0xc0, 0xed, 0x1c, + 0x11, 0x03, 0xa7, 0xec, 0x5e, 0xcf, 0xb3, 0xf3, 0xa8, 0xa6, 0xb7, 0x34, 0x93, 0xba, 0xd4, 0x49, + 0x1a, 0x35, 0xff, 0xa3, 0x00, 0xb8, 0x61, 0x99, 0xd4, 0xb1, 0x74, 0x9d, 0x38, 0x88, 0xf4, 0x35, + 0x57, 0xb3, 0x4c, 0xf8, 0x00, 0xd4, 0xd8, 0x7c, 0xba, 0x98, 0xe2, 0xba, 0x72, 0x59, 0x59, 0x99, + 0x5a, 0xbb, 0xae, 0x46, 0x2b, 0x1d, 0xd2, 0xab, 0xf6, 0x71, 0x8f, 0x35, 0xb8, 0x2a, 0x43, 0xab, + 0xfd, 0x1b, 0xea, 0xee, 0xe1, 0x87, 0xa4, 0x43, 0xb7, 0x09, 0xc5, 0x6d, 0xf8, 0xf8, 0x64, 0x79, + 0x6c, 0x78, 0xb2, 0x0c, 0xa2, 0x36, 0x14, 0xb2, 0xc2, 0x5d, 0x50, 0xe1, 0xec, 0x25, 0xce, 0xbe, + 0x9a, 0xcb, 0x2e, 0x26, 0xad, 0x22, 0xfc, 0x93, 0x77, 0x1f, 0x51, 0x62, 0x32, 0xf7, 0xda, 0x2f, + 0x08, 0xea, 0xca, 0x26, 0xa6, 0x18, 0x71, 0x22, 0x78, 0x0d, 0xd4, 0x1c, 0xe1, 0x7e, 0xbd, 0x7c, + 0x59, 0x59, 0x29, 0xb7, 0x2f, 0x08, 0x54, 0x2d, 0x98, 0x16, 0x0a, 0x11, 0xcd, 0xc7, 0x0a, 0x58, + 0x48, 0xcf, 0x7b, 0x4b, 0x73, 0x29, 0xfc, 0x61, 0x6a, 0xee, 0x6a, 0xb1, 0xb9, 0x33, 0x6b, 0x3e, + 0xf3, 0x70, 0xe0, 0xa0, 0x25, 0x36, 0xef, 0x3d, 0x50, 0xd5, 0x28, 0x31, 0xdc, 0x7a, 0xe9, 0x72, + 0x79, 0x65, 0x6a, 0xed, 0xaa, 0x9a, 0x13, 0xc0, 0x6a, 0xda, 0xbb, 0xf6, 0xb4, 0xe0, 0xad, 0xde, + 0x65, 0x0c, 0xc8, 0x27, 0x6a, 0xfe, 0xa2, 0x04, 0x26, 0x37, 0x31, 0x31, 0x2c, 0x73, 0x9f, 0xd0, + 0x73, 0xd8, 0xb9, 0x3b, 0xa0, 0xe2, 0xda, 0xa4, 0x23, 0x76, 0xee, 0x4a, 0xee, 0x04, 0x42, 0x9f, + 0xf6, 0x6d, 0xd2, 0x89, 0xb6, 0x8c, 0x3d, 0x21, 0xce, 0x00, 0xf7, 0xc0, 0xb8, 0x4b, 0x31, 0xf5, + 0x5c, 0xbe, 0x61, 0x53, 0x6b, 0x2b, 0x05, 0xb8, 0x38, 0xbe, 0x3d, 0x23, 0xd8, 0xc6, 0xfd, 0x67, + 0x24, 0x78, 0x9a, 0xff, 0x28, 0x01, 0x18, 0x62, 0x37, 0x2c, 0xb3, 0xab, 0x51, 0x16, 0xce, 0x37, + 0x41, 0x85, 0x0e, 0x6c, 0xc2, 0x17, 0x64, 0xb2, 0x7d, 0x25, 0x70, 0xe5, 0xde, 0xc0, 0x26, 0x9f, + 0x9f, 0x2c, 0x2f, 0xa4, 0x2d, 0x58, 0x0f, 0xe2, 0x36, 0x70, 0x2b, 0x74, 0xb2, 0xc4, 0xad, 0xdf, + 0x90, 0x87, 0xfe, 0xfc, 0x64, 0x39, 0xe3, 0xec, 0x50, 0x43, 0x26, 0xd9, 0x41, 0xd8, 0x07, 0x50, + 0xc7, 0x2e, 0xbd, 0xe7, 0x60, 0xd3, 0xf5, 0x47, 0xd2, 0x0c, 0x22, 0xa6, 0xff, 0x5a, 0xb1, 0x8d, + 0x62, 0x16, 0xed, 0x25, 0xe1, 0x05, 0xdc, 0x4a, 0xb1, 0xa1, 0x8c, 0x11, 0xe0, 0x15, 0x30, 0xee, + 0x10, 0xec, 0x5a, 0x66, 0xbd, 0xc2, 0x67, 0x11, 0x2e, 0x20, 0xe2, 0xad, 0x48, 0xf4, 0xc2, 0x57, + 0xc1, 0x84, 0x41, 0x5c, 0x17, 0xf7, 0x48, 0xbd, 0xca, 0x81, 0xb3, 0x02, 0x38, 0xb1, 0xed, 0x37, + 0xa3, 0xa0, 0xbf, 0xf9, 0x7b, 0x05, 0x4c, 0x87, 0x2b, 0x77, 0x0e, 0x99, 0x73, 0x5b, 0xce, 0x9c, + 0xe6, 0xe8, 0x60, 0xc9, 0x49, 0x98, 0x8f, 0xca, 0x31, 0xc7, 0x59, 0x38, 0xc2, 0x1f, 0x81, 0x9a, + 0x4b, 0x74, 0xd2, 0xa1, 0x96, 0x23, 0x1c, 0x7f, 0xbd, 0xa0, 0xe3, 0xf8, 0x90, 0xe8, 0xfb, 0xc2, + 0xb4, 0xfd, 0x02, 0xf3, 0x3c, 0x78, 0x42, 0x21, 0x25, 0x7c, 0x1f, 0xd4, 0x28, 0x31, 0x6c, 0x1d, + 0x53, 0x22, 0xb2, 0xe6, 0xa5, 0xb8, 0xf3, 0x2c, 0x66, 0x18, 0xd9, 0x9e, 0xd5, 0xbd, 0x27, 0x60, + 0x3c, 0x65, 0xc2, 0xc5, 0x08, 0x5a, 0x51, 0x48, 0x03, 0x6d, 0x30, 0xe3, 0xd9, 0x5d, 0x86, 0xa4, + 0xec, 0x38, 0xef, 0x0d, 0x44, 0x0c, 0x5d, 0x1f, 0xbd, 0x2a, 0x07, 0x92, 0x5d, 0x7b, 0x41, 0x8c, + 0x32, 0x23, 0xb7, 0xa3, 0x04, 0x3f, 0x5c, 0x07, 0xb3, 0x86, 0x66, 0x22, 0x82, 0xbb, 0x83, 0x7d, + 0xd2, 0xb1, 0xcc, 0xae, 0xcb, 0x43, 0xa9, 0xda, 0x5e, 0x14, 0x04, 0xb3, 0xdb, 0x72, 0x37, 0x4a, + 0xe2, 0xe1, 0x16, 0x98, 0x0f, 0x0e, 0xe0, 0x3b, 0x9a, 0x4b, 0x2d, 0x67, 0xb0, 0xa5, 0x19, 0x1a, + 0xad, 0x8f, 0x73, 0x9e, 0xfa, 0xf0, 0x64, 0x79, 0x1e, 0x65, 0xf4, 0xa3, 0x4c, 0xab, 0xe6, 0x6f, + 0xc6, 0xc1, 0x6c, 0xe2, 0x5c, 0x80, 0xf7, 0xc1, 0x42, 0xc7, 0x73, 0x1c, 0x62, 0xd2, 0x1d, 0xcf, + 0x38, 0x24, 0xce, 0x7e, 0xe7, 0x88, 0x74, 0x3d, 0x9d, 0x74, 0xf9, 0xb6, 0x56, 0xdb, 0x0d, 0xe1, + 0xeb, 0xc2, 0x46, 0x26, 0x0a, 0xe5, 0x58, 0xc3, 0xf7, 0x00, 0x34, 0x79, 0xd3, 0xb6, 0xe6, 0xba, + 0x21, 0x67, 0x89, 0x73, 0x86, 0xa9, 0xb8, 0x93, 0x42, 0xa0, 0x0c, 0x2b, 0xe6, 0x63, 0x97, 0xb8, + 0x9a, 0x43, 0xba, 0x49, 0x1f, 0xcb, 0xb2, 0x8f, 0x9b, 0x99, 0x28, 0x94, 0x63, 0x0d, 0xdf, 0x04, + 0x53, 0xfe, 0x68, 0x7c, 0xcd, 0xc5, 0xe6, 0xcc, 0x09, 0xb2, 0xa9, 0x9d, 0xa8, 0x0b, 0xc5, 0x71, + 0x6c, 0x6a, 0xd6, 0xa1, 0x4b, 0x9c, 0x3e, 0xe9, 0xde, 0xf6, 0xc5, 0x01, 0xab, 0xa0, 0x55, 0x5e, + 0x41, 0xc3, 0xa9, 0xed, 0xa6, 0x10, 0x28, 0xc3, 0x8a, 0x4d, 0xcd, 0x8f, 0x9a, 0xd4, 0xd4, 0xc6, + 0xe5, 0xa9, 0x1d, 0x64, 0xa2, 0x50, 0x8e, 0x35, 0x8b, 0x3d, 0xdf, 0xe5, 0xf5, 0x3e, 0xd6, 0x74, + 0x7c, 0xa8, 0x93, 0xfa, 0x84, 0x1c, 0x7b, 0x3b, 0x72, 0x37, 0x4a, 0xe2, 0xe1, 0x6d, 0x70, 0xd1, + 0x6f, 0x3a, 0x30, 0x71, 0x48, 0x52, 0xe3, 0x24, 0x2f, 0x0a, 0x92, 0x8b, 0x3b, 0x49, 0x00, 0x4a, + 0xdb, 0xc0, 0x9b, 0x60, 0xa6, 0x63, 0xe9, 0x3a, 0x8f, 0xc7, 0x0d, 0xcb, 0x33, 0x69, 0x7d, 0x92, + 0xb3, 0x40, 0x96, 0x43, 0x1b, 0x52, 0x0f, 0x4a, 0x20, 0xe1, 0x8f, 0x01, 0xe8, 0x04, 0x85, 0xc1, + 0xad, 0x83, 0x11, 0x0a, 0x20, 0x5d, 0x96, 0xa2, 0xca, 0x1c, 0x36, 0xb9, 0x28, 0x46, 0xd9, 0xfc, + 0x48, 0x01, 0x8b, 0x39, 0x89, 0x0e, 0xbf, 0x2b, 0x15, 0xc1, 0xab, 0x89, 0x22, 0x78, 0x29, 0xc7, + 0x2c, 0x56, 0x09, 0x8f, 0xc0, 0x34, 0x13, 0x24, 0x9a, 0xd9, 0xf3, 0x21, 0xe2, 0x2c, 0x6b, 0xe5, + 0x4e, 0x00, 0xc5, 0xd1, 0xd1, 0xa9, 0x7c, 0x71, 0x78, 0xb2, 0x3c, 0x2d, 0xf5, 0x21, 0x99, 0xb8, + 0xf9, 0xcb, 0x12, 0x00, 0x9b, 0xc4, 0xd6, 0xad, 0x81, 0x41, 0xcc, 0xf3, 0xd0, 0x34, 0x77, 0x25, + 0x4d, 0xf3, 0x4a, 0xfe, 0x96, 0x84, 0x4e, 0xe5, 0x8a, 0x9a, 0xf7, 0x13, 0xa2, 0xe6, 0xd5, 0x22, + 0x64, 0x4f, 0x57, 0x35, 0x9f, 0x94, 0xc1, 0x5c, 0x04, 0x8e, 0x64, 0xcd, 0x2d, 0x69, 0x47, 0x5f, + 0x49, 0xec, 0xe8, 0x62, 0x86, 0xc9, 0x73, 0xd3, 0x35, 0xcf, 0x5e, 0x5f, 0xc0, 0x0f, 0xc1, 0x0c, + 0x13, 0x32, 0x7e, 0x48, 0x70, 0x99, 0x34, 0x7e, 0x6a, 0x99, 0x14, 0x16, 0xb7, 0x2d, 0x89, 0x09, + 0x25, 0x98, 0x73, 0x64, 0xd9, 0xc4, 0xf3, 0x96, 0x65, 0xcd, 0x3f, 0x28, 0x60, 0x26, 0xda, 0xa6, + 0x73, 0x10, 0x51, 0x77, 0x64, 0x11, 0xf5, 0x52, 0x81, 0xe0, 0xcc, 0x51, 0x51, 0x9f, 0x54, 0xe2, + 0xae, 0x73, 0x19, 0xb5, 0xc2, 0x5e, 0xc1, 0x6c, 0x5d, 0xeb, 0x60, 0x57, 0xd4, 0xdb, 0x17, 0xfc, + 0xd7, 0x2f, 0xbf, 0x0d, 0x85, 0xbd, 0x92, 0xe0, 0x2a, 0x3d, 0x5f, 0xc1, 0x55, 0x7e, 0x36, 0x82, + 0xeb, 0x07, 0xa0, 0xe6, 0x06, 0x52, 0xab, 0xc2, 0x29, 0xaf, 0x16, 0x4a, 0x6c, 0xa1, 0xb2, 0x42, + 0xea, 0x50, 0x5f, 0x85, 0x74, 0x59, 0xca, 0xaa, 0xfa, 0x65, 0x2a, 0x2b, 0x96, 0xcc, 0x36, 0xf6, + 0x5c, 0xd2, 0xe5, 0x19, 0x50, 0x8b, 0x92, 0x79, 0x8f, 0xb7, 0x22, 0xd1, 0x0b, 0x0f, 0xc0, 0xa2, + 0xed, 0x58, 0x3d, 0x87, 0xb8, 0xee, 0x26, 0xc1, 0x5d, 0x5d, 0x33, 0x49, 0x30, 0x01, 0xbf, 0x26, + 0x5e, 0x1a, 0x9e, 0x2c, 0x2f, 0xee, 0x65, 0x43, 0x50, 0x9e, 0x6d, 0xf3, 0xcf, 0x15, 0x70, 0x21, + 0x79, 0x36, 0xe6, 0xc8, 0x14, 0xe5, 0x4c, 0x32, 0xe5, 0x5a, 0x2c, 0x4e, 0x7d, 0x0d, 0x17, 0xbb, + 0x2a, 0x48, 0xc5, 0xea, 0x3a, 0x98, 0x15, 0xb2, 0x24, 0xe8, 0x14, 0x42, 0x2d, 0xdc, 0x9e, 0x03, + 0xb9, 0x1b, 0x25, 0xf1, 0x4c, 0x7c, 0x44, 0x9a, 0x22, 0x20, 0xa9, 0xc8, 0xe2, 0x63, 0x3d, 0x09, + 0x40, 0x69, 0x1b, 0xb8, 0x0d, 0xe6, 0x3c, 0x33, 0x4d, 0xe5, 0x87, 0xcb, 0x25, 0x41, 0x35, 0x77, + 0x90, 0x86, 0xa0, 0x2c, 0x3b, 0xf8, 0x40, 0xd2, 0x23, 0xe3, 0xfc, 0x48, 0xb8, 0x56, 0x20, 0xac, + 0x0b, 0x0b, 0x12, 0x78, 0x0b, 0x4c, 0x3b, 0x5c, 0x73, 0x06, 0xae, 0xfa, 0xba, 0xed, 0x1b, 0xc2, + 0x6c, 0x1a, 0xc5, 0x3b, 0x91, 0x8c, 0xcd, 0x90, 0x5a, 0xb5, 0xa2, 0x52, 0xab, 0xf9, 0x27, 0x05, + 0xc0, 0x74, 0x1e, 0x8e, 0xbc, 0x09, 0x48, 0x59, 0xc4, 0x2a, 0xa6, 0x96, 0xad, 0x7f, 0xae, 0x17, + 0xd4, 0x3f, 0xd1, 0x81, 0x5a, 0x4c, 0x00, 0x89, 0x65, 0x38, 0x9f, 0x4b, 0x9d, 0xa2, 0x02, 0x28, + 0x72, 0xea, 0x19, 0x08, 0xa0, 0x18, 0xd9, 0xd3, 0x05, 0xd0, 0x3f, 0x4b, 0x60, 0x2e, 0x02, 0x17, + 0x16, 0x40, 0x19, 0x26, 0x5f, 0x5f, 0xec, 0x8c, 0xbe, 0xd8, 0x61, 0xa2, 0x24, 0x5a, 0xba, 0xff, + 0x27, 0x51, 0x12, 0x79, 0x95, 0x23, 0x4a, 0x7e, 0x57, 0x8a, 0xbb, 0xfe, 0x95, 0x17, 0x25, 0x5f, + 0xfc, 0x4e, 0xa6, 0xf9, 0x97, 0x32, 0xb8, 0x90, 0xcc, 0x43, 0xa9, 0x40, 0x2a, 0x23, 0x0b, 0xe4, + 0x1e, 0x98, 0x7f, 0xe8, 0xe9, 0xfa, 0x80, 0x2f, 0x43, 0xac, 0x4a, 0xfa, 0xa5, 0xf5, 0x9b, 0xc2, + 0x72, 0xfe, 0xfb, 0x19, 0x18, 0x94, 0x69, 0x99, 0x53, 0xec, 0xcb, 0x67, 0x2a, 0xf6, 0xa9, 0x0a, + 0x54, 0x39, 0x45, 0x05, 0xca, 0x2c, 0xdc, 0xd5, 0x33, 0x14, 0xee, 0xd3, 0x55, 0xda, 0x8c, 0x83, + 0x6b, 0xe4, 0xab, 0xff, 0xcf, 0x15, 0xb0, 0x90, 0xfd, 0xc2, 0x0d, 0x75, 0x30, 0x63, 0xe0, 0x47, + 0xf1, 0x8b, 0x8f, 0x51, 0x45, 0xc4, 0xa3, 0x9a, 0xae, 0xfa, 0x9f, 0x8c, 0xd4, 0xbb, 0x26, 0xdd, + 0x75, 0xf6, 0xa9, 0xa3, 0x99, 0x3d, 0xbf, 0xf2, 0x6e, 0x4b, 0x5c, 0x28, 0xc1, 0xdd, 0xfc, 0x4c, + 0x01, 0x8b, 0x39, 0x95, 0xef, 0x7c, 0x3d, 0x81, 0x1f, 0x80, 0x9a, 0x81, 0x1f, 0xed, 0x7b, 0x4e, + 0x2f, 0xab, 0x56, 0x17, 0x1b, 0x87, 0x67, 0xf3, 0xb6, 0x60, 0x41, 0x21, 0x5f, 0x73, 0x17, 0x5c, + 0x96, 0x26, 0xc9, 0x32, 0x87, 0x3c, 0xf4, 0x74, 0x9e, 0x44, 0x42, 0x6c, 0x5c, 0x05, 0x93, 0x36, + 0x76, 0xa8, 0x16, 0x4a, 0xd5, 0x6a, 0x7b, 0x7a, 0x78, 0xb2, 0x3c, 0xb9, 0x17, 0x34, 0xa2, 0xa8, + 0xbf, 0xf9, 0x5f, 0x05, 0x54, 0xf7, 0x3b, 0x58, 0x27, 0xe7, 0x50, 0xed, 0x37, 0xa5, 0x6a, 0x9f, + 0x7f, 0x93, 0xce, 0xfd, 0xc9, 0x2d, 0xf4, 0x5b, 0x89, 0x42, 0xff, 0xf2, 0x08, 0x9e, 0xa7, 0xd7, + 0xf8, 0x77, 0xc0, 0x64, 0x38, 0xdc, 0xe9, 0x0e, 0xa0, 0xe6, 0x6f, 0x4b, 0x60, 0x2a, 0x36, 0xc4, + 0x29, 0x8f, 0xaf, 0x07, 0xd2, 0xb1, 0xcf, 0x12, 0x73, 0xad, 0xc8, 0x44, 0xd4, 0xe0, 0x88, 0x7f, + 0xd7, 0xa4, 0x4e, 0xfc, 0x05, 0x2f, 0x7d, 0xf2, 0x7f, 0x07, 0xcc, 0x50, 0xec, 0xf4, 0x08, 0x0d, + 0xfa, 0xf8, 0x82, 0x4d, 0x46, 0xb7, 0x13, 0xf7, 0xa4, 0x5e, 0x94, 0x40, 0x2f, 0xdd, 0x02, 0xd3, + 0xd2, 0x60, 0xf0, 0x02, 0x28, 0x1f, 0x93, 0x81, 0x2f, 0x7b, 0x10, 0xfb, 0x09, 0xe7, 0x41, 0xb5, + 0x8f, 0x75, 0xcf, 0x8f, 0xf3, 0x49, 0xe4, 0x3f, 0xdc, 0x2c, 0xbd, 0xad, 0x34, 0x7f, 0xc5, 0x16, + 0x27, 0x0a, 0xce, 0x73, 0x88, 0xae, 0xf7, 0xa4, 0xe8, 0xca, 0xff, 0xa8, 0x17, 0x4f, 0x99, 0xbc, + 0x18, 0x43, 0x89, 0x18, 0x7b, 0xad, 0x10, 0xdb, 0xd3, 0x23, 0xed, 0x5f, 0x25, 0x30, 0x1f, 0x43, + 0x47, 0x72, 0xf2, 0xdb, 0x92, 0x9c, 0x5c, 0x49, 0xc8, 0xc9, 0x7a, 0x96, 0xcd, 0xd7, 0x7a, 0x72, + 0xb4, 0x9e, 0xfc, 0xa3, 0x02, 0x66, 0x63, 0x6b, 0x77, 0x0e, 0x82, 0xf2, 0xae, 0x2c, 0x28, 0x5f, + 0x2e, 0x12, 0x34, 0x39, 0x8a, 0xf2, 0xaf, 0x55, 0xc9, 0xf9, 0xaf, 0xbc, 0xa4, 0xfc, 0x29, 0x98, + 0xef, 0x5b, 0xba, 0x67, 0x90, 0x0d, 0x1d, 0x6b, 0x46, 0x00, 0x60, 0xaa, 0xa9, 0x9c, 0x7c, 0x97, + 0x0b, 0xe9, 0x89, 0xe3, 0x6a, 0x2e, 0x25, 0x26, 0xbd, 0x1f, 0x59, 0x46, 0xba, 0xef, 0x7e, 0x06, + 0x1d, 0xca, 0x1c, 0x04, 0xbe, 0x09, 0xa6, 0x98, 0x7e, 0xd3, 0x3a, 0x64, 0x07, 0x1b, 0x41, 0x60, + 0x85, 0x9f, 0xb0, 0xf6, 0xa3, 0x2e, 0x14, 0xc7, 0xc1, 0x23, 0x30, 0x67, 0x5b, 0xdd, 0x6d, 0x6c, + 0xe2, 0x1e, 0x61, 0x32, 0x63, 0xcf, 0xd2, 0xb5, 0xce, 0x80, 0x5f, 0x7e, 0x4d, 0xb6, 0xdf, 0x0a, + 0x6e, 0x45, 0xf6, 0xd2, 0x10, 0xf6, 0x92, 0x98, 0xd1, 0xcc, 0x93, 0x3a, 0x8b, 0x12, 0x3a, 0xa9, + 0xcf, 0xae, 0xfe, 0x1d, 0xf1, 0x5a, 0x91, 0x08, 0x3b, 0xe3, 0x87, 0xd7, 0xbc, 0xbb, 0xbd, 0xda, + 0x99, 0xbe, 0x9a, 0xfe, 0xbb, 0x02, 0x2e, 0xa6, 0x8e, 0xca, 0x2f, 0xf1, 0x76, 0x2d, 0x25, 0xcf, + 0xcb, 0xa7, 0x90, 0xe7, 0xeb, 0x60, 0x56, 0x7c, 0xb0, 0x4d, 0xa8, 0xfb, 0xf0, 0xfd, 0x67, 0x43, + 0xee, 0x46, 0x49, 0x7c, 0xd6, 0xed, 0x5e, 0xf5, 0x94, 0xb7, 0x7b, 0x71, 0x2f, 0xc4, 0x1f, 0x90, + 0xfc, 0xd0, 0x4b, 0x7b, 0x21, 0xfe, 0x87, 0x94, 0xc4, 0x33, 0x85, 0xe0, 0xb3, 0x86, 0x0c, 0x13, + 0xb2, 0x42, 0x38, 0x90, 0x7a, 0x51, 0x02, 0xfd, 0x85, 0x3e, 0x4a, 0xe2, 0x8c, 0x8f, 0x92, 0xab, + 0x45, 0xe2, 0xb9, 0xf8, 0xbb, 0xc9, 0xdf, 0x14, 0xf0, 0x62, 0x6e, 0x22, 0xc0, 0x75, 0xa9, 0xec, + 0xae, 0x26, 0xca, 0xee, 0xb7, 0x72, 0x0d, 0x63, 0xb5, 0xd7, 0xc9, 0xbe, 0x9a, 0x7b, 0xa7, 0xd8, + 0xd5, 0x5c, 0x86, 0x76, 0x1f, 0x7d, 0x47, 0xd7, 0x5e, 0x7d, 0xfc, 0xa4, 0x31, 0xf6, 0xf1, 0x93, + 0xc6, 0xd8, 0xa7, 0x4f, 0x1a, 0x63, 0x3f, 0x1b, 0x36, 0x94, 0xc7, 0xc3, 0x86, 0xf2, 0xf1, 0xb0, + 0xa1, 0x7c, 0x3a, 0x6c, 0x28, 0x7f, 0x1f, 0x36, 0x94, 0x5f, 0x7f, 0xd6, 0x18, 0xfb, 0x60, 0x42, + 0x8c, 0xf8, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x85, 0x43, 0x0a, 0xec, 0x28, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/apps/v1beta2/generated.proto b/vendor/k8s.io/api/apps/v1beta2/generated.proto index 4a8b28c15..cc3656d28 100644 --- a/vendor/k8s.io/api/apps/v1beta2/generated.proto +++ b/vendor/k8s.io/api/apps/v1beta2/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,7 +22,6 @@ syntax = 'proto2'; package k8s.io.api.apps.v1beta2; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; @@ -509,9 +508,9 @@ message RollingUpdateDeployment { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -523,10 +522,10 @@ message RollingUpdateDeployment { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is atmost 130% of desired pods. // +optional optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; diff --git a/vendor/k8s.io/api/apps/v1beta2/types.go b/vendor/k8s.io/api/apps/v1beta2/types.go index c8be2aaca..e5525222a 100644 --- a/vendor/k8s.io/api/apps/v1beta2/types.go +++ b/vendor/k8s.io/api/apps/v1beta2/types.go @@ -359,8 +359,8 @@ type DeploymentSpec struct { const ( // DefaultDeploymentUniqueLabelKey is the default key of the selector that is added - // to existing RCs (and label key that is added to its pods) to prevent the existing RCs - // to select new pods (and old pods being select by new RC). + // to existing ReplicaSets (and label key that is added to its pods) to prevent the existing ReplicaSets + // to select new pods (and old pods being select by new ReplicaSet). DefaultDeploymentUniqueLabelKey string = "pod-template-hash" ) @@ -385,7 +385,7 @@ const ( // Kill all existing pods before creating new ones. RecreateDeploymentStrategyType DeploymentStrategyType = "Recreate" - // Replace the old RCs by new one using rolling update i.e gradually scale down the old RCs and scale up the new one. + // Replace the old ReplicaSets by new one using rolling update i.e gradually scale down the old ReplicaSets and scale up the new one. RollingUpdateDeploymentStrategyType DeploymentStrategyType = "RollingUpdate" ) @@ -396,9 +396,9 @@ type RollingUpdateDeployment struct { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -410,10 +410,10 @@ type RollingUpdateDeployment struct { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is atmost 130% of desired pods. // +optional MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` diff --git a/vendor/k8s.io/api/apps/v1beta2/types_swagger_doc_generated.go b/vendor/k8s.io/api/apps/v1beta2/types_swagger_doc_generated.go index e2f133b51..627df3ab7 100644 --- a/vendor/k8s.io/api/apps/v1beta2/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/apps/v1beta2/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta2 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_ControllerRevision = map[string]string{ "": "DEPRECATED - This group version of ControllerRevision is deprecated by apps/v1/ControllerRevision. See the release notes for more information. ControllerRevision implements an immutable snapshot of state data. Clients are responsible for serializing and deserializing the objects that contain their internal state. Once a ControllerRevision has been successfully created, it can not be updated. The API Server will fail validation of all requests that attempt to mutate the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, it may be subject to name and representation changes in future releases, and clients should not depend on its stability. It is primarily for internal use by controllers.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -271,8 +271,8 @@ func (RollingUpdateDaemonSet) SwaggerDoc() map[string]string { var map_RollingUpdateDeployment = map[string]string{ "": "Spec to control the desired behavior of rolling update.", - "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", - "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", + "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", } func (RollingUpdateDeployment) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/api/apps/v1beta2/zz_generated.deepcopy.go b/vendor/k8s.io/api/apps/v1beta2/zz_generated.deepcopy.go index 3db38527d..a3bd8afdc 100644 --- a/vendor/k8s.io/api/apps/v1beta2/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/apps/v1beta2/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/authentication/v1/generated.pb.go b/vendor/k8s.io/api/authentication/v1/generated.pb.go index d090ce579..2ce2e2d78 100644 --- a/vendor/k8s.io/api/authentication/v1/generated.pb.go +++ b/vendor/k8s.io/api/authentication/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2087,62 +2087,61 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 905 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xcf, 0x6f, 0x1b, 0x45, - 0x14, 0xf6, 0xfa, 0x47, 0x64, 0x8f, 0x9b, 0x90, 0x4c, 0xa9, 0x64, 0x05, 0xb0, 0x8d, 0x91, 0x90, - 0x05, 0x74, 0xb7, 0x36, 0xa8, 0x54, 0x45, 0x42, 0xca, 0x12, 0x0b, 0x2c, 0x04, 0xad, 0xa6, 0x4d, - 0x40, 0x9c, 0x18, 0xdb, 0x2f, 0xce, 0xe0, 0xee, 0xec, 0x32, 0x3b, 0x6b, 0xea, 0x5b, 0xff, 0x04, - 0x8e, 0x20, 0x71, 0xe0, 0x8f, 0x40, 0xe2, 0xc8, 0x35, 0xc7, 0x8a, 0x53, 0x0f, 0xc8, 0x22, 0xcb, - 0xbf, 0xc0, 0x89, 0x13, 0x9a, 0xd9, 0x89, 0xd7, 0x3f, 0x12, 0xc7, 0xa7, 0xde, 0x3c, 0xef, 0x7d, - 0xef, 0x9b, 0xf7, 0xbe, 0xf9, 0xfc, 0x16, 0x75, 0x46, 0xf7, 0x42, 0x9b, 0xf9, 0xce, 0x28, 0xea, - 0x81, 0xe0, 0x20, 0x21, 0x74, 0xc6, 0xc0, 0x07, 0xbe, 0x70, 0x4c, 0x82, 0x06, 0xcc, 0xa1, 0x91, - 0x3c, 0x05, 0x2e, 0x59, 0x9f, 0x4a, 0xe6, 0x73, 0x67, 0xdc, 0x72, 0x86, 0xc0, 0x41, 0x50, 0x09, - 0x03, 0x3b, 0x10, 0xbe, 0xf4, 0xf1, 0xeb, 0x09, 0xda, 0xa6, 0x01, 0xb3, 0x17, 0xd1, 0xf6, 0xb8, - 0xb5, 0x7f, 0x7b, 0xc8, 0xe4, 0x69, 0xd4, 0xb3, 0xfb, 0xbe, 0xe7, 0x0c, 0xfd, 0xa1, 0xef, 0xe8, - 0xa2, 0x5e, 0x74, 0xa2, 0x4f, 0xfa, 0xa0, 0x7f, 0x25, 0x64, 0xfb, 0x1f, 0xa4, 0x57, 0x7b, 0xb4, - 0x7f, 0xca, 0x38, 0x88, 0x89, 0x13, 0x8c, 0x86, 0x2a, 0x10, 0x3a, 0x1e, 0x48, 0x7a, 0x49, 0x0b, - 0xfb, 0xce, 0x55, 0x55, 0x22, 0xe2, 0x92, 0x79, 0xb0, 0x52, 0x70, 0xf7, 0xba, 0x82, 0xb0, 0x7f, - 0x0a, 0x1e, 0x5d, 0xa9, 0x7b, 0xff, 0xaa, 0xba, 0x48, 0xb2, 0x27, 0x0e, 0xe3, 0x32, 0x94, 0x62, - 0xb9, 0xa8, 0xf1, 0xa7, 0x85, 0x5e, 0x75, 0xfd, 0x88, 0x0f, 0x1e, 0xf4, 0xbe, 0x83, 0xbe, 0x24, - 0x70, 0x02, 0x02, 0x78, 0x1f, 0x70, 0x1d, 0xe5, 0x47, 0x8c, 0x0f, 0x2a, 0x56, 0xdd, 0x6a, 0x96, - 0xdc, 0x1b, 0x67, 0xd3, 0x5a, 0x26, 0x9e, 0xd6, 0xf2, 0x9f, 0x33, 0x3e, 0x20, 0x3a, 0x83, 0xdb, - 0x08, 0xd1, 0x87, 0xdd, 0x63, 0x10, 0x21, 0xf3, 0x79, 0x25, 0xab, 0x71, 0xd8, 0xe0, 0xd0, 0xc1, - 0x2c, 0x43, 0xe6, 0x50, 0x8a, 0x95, 0x53, 0x0f, 0x2a, 0xb9, 0x45, 0xd6, 0x2f, 0xa9, 0x07, 0x44, - 0x67, 0xb0, 0x8b, 0x72, 0x51, 0xf7, 0xb0, 0x92, 0xd7, 0x80, 0x3b, 0x06, 0x90, 0x3b, 0xea, 0x1e, - 0xfe, 0x37, 0xad, 0xbd, 0x79, 0xd5, 0x84, 0x72, 0x12, 0x40, 0x68, 0x1f, 0x75, 0x0f, 0x89, 0x2a, - 0x6e, 0x7c, 0x88, 0x50, 0xe7, 0xa9, 0x14, 0xf4, 0x98, 0x3e, 0x89, 0x00, 0xd7, 0x50, 0x81, 0x49, - 0xf0, 0xc2, 0x8a, 0x55, 0xcf, 0x35, 0x4b, 0x6e, 0x29, 0x9e, 0xd6, 0x0a, 0x5d, 0x15, 0x20, 0x49, - 0xfc, 0x7e, 0xf1, 0xa7, 0x5f, 0x6b, 0x99, 0x67, 0x7f, 0xd5, 0x33, 0x8d, 0x5f, 0xb2, 0xe8, 0xc6, - 0x63, 0x7f, 0x04, 0x9c, 0xc0, 0xf7, 0x11, 0x84, 0x12, 0x7f, 0x8b, 0x8a, 0xea, 0x5d, 0x07, 0x54, - 0x52, 0xad, 0x44, 0xb9, 0x7d, 0xc7, 0x4e, 0x2d, 0x35, 0x6b, 0xc2, 0x0e, 0x46, 0x43, 0x15, 0x08, - 0x6d, 0x85, 0xb6, 0xc7, 0x2d, 0x3b, 0x91, 0xf3, 0x0b, 0x90, 0x34, 0xd5, 0x24, 0x8d, 0x91, 0x19, - 0x2b, 0x7e, 0x88, 0xf2, 0x61, 0x00, 0x7d, 0xad, 0x5f, 0xb9, 0x6d, 0xdb, 0xeb, 0x0c, 0x6b, 0xcf, - 0xf7, 0xf6, 0x28, 0x80, 0x7e, 0xaa, 0xa0, 0x3a, 0x11, 0xcd, 0x84, 0xbf, 0x46, 0x5b, 0xa1, 0xa4, - 0x32, 0x0a, 0xb5, 0xca, 0x8b, 0x1d, 0x5f, 0xc7, 0xa9, 0xeb, 0xdc, 0x1d, 0xc3, 0xba, 0x95, 0x9c, - 0x89, 0xe1, 0x6b, 0xfc, 0x6b, 0xa1, 0xdd, 0xe5, 0x16, 0xf0, 0xbb, 0xa8, 0x44, 0xa3, 0x01, 0x53, - 0xa6, 0xb9, 0x90, 0x78, 0x3b, 0x9e, 0xd6, 0x4a, 0x07, 0x17, 0x41, 0x92, 0xe6, 0x31, 0x47, 0x3b, - 0xbd, 0x05, 0xb7, 0x99, 0x1e, 0xdb, 0xeb, 0x7b, 0xbc, 0xcc, 0xa1, 0x2e, 0x8e, 0xa7, 0xb5, 0x9d, - 0xc5, 0x0c, 0x59, 0x62, 0xc7, 0x9f, 0xa0, 0x3d, 0x78, 0x1a, 0x30, 0xa1, 0x99, 0x1e, 0x41, 0xdf, - 0xe7, 0x83, 0x50, 0x7b, 0x2b, 0xe7, 0xde, 0x8a, 0xa7, 0xb5, 0xbd, 0xce, 0x72, 0x92, 0xac, 0xe2, - 0x1b, 0xbf, 0x59, 0x08, 0xaf, 0xaa, 0x84, 0xdf, 0x42, 0x05, 0xa9, 0xa2, 0xe6, 0x2f, 0xb2, 0x6d, - 0x44, 0x2b, 0x24, 0xd0, 0x24, 0x87, 0x27, 0xe8, 0x66, 0x4a, 0xf8, 0x98, 0x79, 0x10, 0x4a, 0xea, - 0x05, 0xe6, 0xb5, 0xdf, 0xd9, 0xcc, 0x4b, 0xaa, 0xcc, 0x7d, 0xcd, 0xd0, 0xdf, 0xec, 0xac, 0xd2, - 0x91, 0xcb, 0xee, 0x68, 0xfc, 0x9c, 0x45, 0x65, 0xd3, 0xf6, 0x98, 0xc1, 0x0f, 0x2f, 0xc1, 0xcb, - 0x0f, 0x16, 0xbc, 0x7c, 0x7b, 0x23, 0xdf, 0xa9, 0xd6, 0xae, 0xb4, 0xf2, 0x57, 0x4b, 0x56, 0x76, - 0x36, 0xa7, 0x5c, 0xef, 0xe4, 0xbb, 0xe8, 0x95, 0xa5, 0xfb, 0x37, 0x7a, 0xce, 0xc6, 0x1f, 0x16, - 0xda, 0x5b, 0xb9, 0x05, 0x7f, 0x84, 0xb6, 0xe7, 0x9a, 0x81, 0x64, 0x69, 0x16, 0xdd, 0x5b, 0x86, - 0x62, 0xfb, 0x60, 0x3e, 0x49, 0x16, 0xb1, 0xf8, 0x33, 0x94, 0x8f, 0x42, 0x10, 0x46, 0xb4, 0xb7, - 0xd7, 0x4f, 0x78, 0x14, 0x82, 0xe8, 0xf2, 0x13, 0x3f, 0x55, 0x4b, 0x45, 0x88, 0x66, 0x50, 0x13, - 0x80, 0x10, 0xbe, 0x30, 0xdb, 0x75, 0x36, 0x41, 0x47, 0x05, 0x49, 0x92, 0x6b, 0xfc, 0x9e, 0x45, - 0xc5, 0x0b, 0x16, 0xfc, 0x1e, 0x2a, 0xaa, 0x4a, 0xbd, 0x92, 0x93, 0xb1, 0x77, 0x4d, 0x91, 0xc6, - 0xa8, 0x38, 0x99, 0x21, 0xf0, 0x1b, 0x28, 0x17, 0xb1, 0x81, 0xd9, 0xf4, 0xe5, 0xb9, 0xd5, 0x4c, - 0x54, 0x1c, 0x37, 0xd0, 0xd6, 0x50, 0xf8, 0x51, 0xa0, 0x1e, 0x4b, 0x6d, 0x01, 0xa4, 0x74, 0xff, - 0x54, 0x47, 0x88, 0xc9, 0xe0, 0x63, 0x54, 0x00, 0xb5, 0x99, 0x2b, 0xf9, 0x7a, 0xae, 0x59, 0x6e, - 0xb7, 0x36, 0x9b, 0xd6, 0xd6, 0xdb, 0xbc, 0xc3, 0xa5, 0x98, 0xcc, 0x4d, 0xa5, 0x62, 0x24, 0xa1, - 0xdb, 0xef, 0x99, 0x8d, 0xaf, 0x31, 0x78, 0x17, 0xe5, 0x46, 0x30, 0x49, 0x26, 0x22, 0xea, 0x27, - 0xfe, 0x18, 0x15, 0xc6, 0xea, 0x63, 0x60, 0x54, 0x6e, 0xae, 0xbf, 0x37, 0xfd, 0x78, 0x90, 0xa4, - 0xec, 0x7e, 0xf6, 0x9e, 0xe5, 0x36, 0xcf, 0xce, 0xab, 0x99, 0xe7, 0xe7, 0xd5, 0xcc, 0x8b, 0xf3, - 0x6a, 0xe6, 0x59, 0x5c, 0xb5, 0xce, 0xe2, 0xaa, 0xf5, 0x3c, 0xae, 0x5a, 0x2f, 0xe2, 0xaa, 0xf5, - 0x77, 0x5c, 0xb5, 0x7e, 0xfc, 0xa7, 0x9a, 0xf9, 0x26, 0x3b, 0x6e, 0xfd, 0x1f, 0x00, 0x00, 0xff, - 0xff, 0x5f, 0x39, 0x60, 0xb1, 0xbd, 0x08, 0x00, 0x00, + // 892 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xcf, 0x8f, 0xdb, 0x44, + 0x14, 0x8e, 0xf3, 0x63, 0xb5, 0x99, 0x74, 0x97, 0xdd, 0x29, 0x95, 0xa2, 0x05, 0xec, 0x60, 0x24, + 0x14, 0x01, 0xb5, 0x9b, 0x08, 0x95, 0xaa, 0x48, 0x48, 0x6b, 0x36, 0x82, 0x08, 0x41, 0xab, 0x69, + 0x77, 0x41, 0x9c, 0x98, 0xd8, 0x6f, 0xb3, 0x26, 0x78, 0x6c, 0xec, 0x71, 0x68, 0x6e, 0xfd, 0x13, + 0x38, 0x82, 0xc4, 0x81, 0x3f, 0x02, 0x89, 0x23, 0xd7, 0x3d, 0x56, 0x9c, 0x7a, 0x40, 0x11, 0x6b, + 0xfe, 0x05, 0x4e, 0x9c, 0xd0, 0x8c, 0x67, 0xe3, 0xfc, 0xd8, 0x4d, 0x73, 0xea, 0x2d, 0xf3, 0xde, + 0xf7, 0xbe, 0x79, 0xef, 0x9b, 0x2f, 0xcf, 0xa8, 0x37, 0xba, 0x97, 0x58, 0x7e, 0x68, 0x8f, 0xd2, + 0x01, 0xc4, 0x0c, 0x38, 0x24, 0xf6, 0x18, 0x98, 0x17, 0xc6, 0xb6, 0x4a, 0xd0, 0xc8, 0xb7, 0x69, + 0xca, 0xcf, 0x80, 0x71, 0xdf, 0xa5, 0xdc, 0x0f, 0x99, 0x3d, 0xee, 0xd8, 0x43, 0x60, 0x10, 0x53, + 0x0e, 0x9e, 0x15, 0xc5, 0x21, 0x0f, 0xf1, 0xeb, 0x39, 0xda, 0xa2, 0x91, 0x6f, 0x2d, 0xa2, 0xad, + 0x71, 0xe7, 0xe0, 0xf6, 0xd0, 0xe7, 0x67, 0xe9, 0xc0, 0x72, 0xc3, 0xc0, 0x1e, 0x86, 0xc3, 0xd0, + 0x96, 0x45, 0x83, 0xf4, 0x54, 0x9e, 0xe4, 0x41, 0xfe, 0xca, 0xc9, 0x0e, 0xde, 0x2f, 0xae, 0x0e, + 0xa8, 0x7b, 0xe6, 0x33, 0x88, 0x27, 0x76, 0x34, 0x1a, 0x8a, 0x40, 0x62, 0x07, 0xc0, 0xe9, 0x15, + 0x2d, 0x1c, 0xd8, 0xd7, 0x55, 0xc5, 0x29, 0xe3, 0x7e, 0x00, 0x2b, 0x05, 0x77, 0x5f, 0x54, 0x90, + 0xb8, 0x67, 0x10, 0xd0, 0xe5, 0x3a, 0xf3, 0x4f, 0x0d, 0xbd, 0xea, 0x84, 0x29, 0xf3, 0x1e, 0x0c, + 0xbe, 0x05, 0x97, 0x13, 0x38, 0x85, 0x18, 0x98, 0x0b, 0xb8, 0x85, 0xaa, 0x23, 0x9f, 0x79, 0x4d, + 0xad, 0xa5, 0xb5, 0xeb, 0xce, 0x8d, 0xf3, 0xa9, 0x51, 0xca, 0xa6, 0x46, 0xf5, 0x33, 0x9f, 0x79, + 0x44, 0x66, 0x70, 0x17, 0x21, 0xfa, 0xb0, 0x7f, 0x02, 0x71, 0xe2, 0x87, 0xac, 0x59, 0x96, 0x38, + 0xac, 0x70, 0xe8, 0x70, 0x96, 0x21, 0x73, 0x28, 0xc1, 0xca, 0x68, 0x00, 0xcd, 0xca, 0x22, 0xeb, + 0x17, 0x34, 0x00, 0x22, 0x33, 0xd8, 0x41, 0x95, 0xb4, 0x7f, 0xd4, 0xac, 0x4a, 0xc0, 0x1d, 0x05, + 0xa8, 0x1c, 0xf7, 0x8f, 0xfe, 0x9b, 0x1a, 0x6f, 0x5e, 0x37, 0x24, 0x9f, 0x44, 0x90, 0x58, 0xc7, + 0xfd, 0x23, 0x22, 0x8a, 0xcd, 0x0f, 0x10, 0xea, 0x3d, 0xe1, 0x31, 0x3d, 0xa1, 0xdf, 0xa5, 0x80, + 0x0d, 0x54, 0xf3, 0x39, 0x04, 0x49, 0x53, 0x6b, 0x55, 0xda, 0x75, 0xa7, 0x9e, 0x4d, 0x8d, 0x5a, + 0x5f, 0x04, 0x48, 0x1e, 0xbf, 0xbf, 0xfd, 0xd3, 0xaf, 0x46, 0xe9, 0xe9, 0x5f, 0xad, 0x92, 0xf9, + 0x4b, 0x19, 0xdd, 0x78, 0x1c, 0x8e, 0x80, 0x11, 0xf8, 0x3e, 0x85, 0x84, 0xe3, 0x6f, 0xd0, 0xb6, + 0x78, 0x22, 0x8f, 0x72, 0x2a, 0x95, 0x68, 0x74, 0xef, 0x58, 0x85, 0x3b, 0x66, 0x4d, 0x58, 0xd1, + 0x68, 0x28, 0x02, 0x89, 0x25, 0xd0, 0xd6, 0xb8, 0x63, 0xe5, 0x72, 0x7e, 0x0e, 0x9c, 0x16, 0x9a, + 0x14, 0x31, 0x32, 0x63, 0xc5, 0x0f, 0x51, 0x35, 0x89, 0xc0, 0x95, 0xfa, 0x35, 0xba, 0x96, 0xb5, + 0xce, 0x7b, 0xd6, 0x7c, 0x6f, 0x8f, 0x22, 0x70, 0x0b, 0x05, 0xc5, 0x89, 0x48, 0x26, 0xfc, 0x15, + 0xda, 0x4a, 0x38, 0xe5, 0x69, 0x22, 0x55, 0x5e, 0xec, 0xf8, 0x45, 0x9c, 0xb2, 0xce, 0xd9, 0x55, + 0xac, 0x5b, 0xf9, 0x99, 0x28, 0x3e, 0xf3, 0x5f, 0x0d, 0xed, 0x2d, 0xb7, 0x80, 0xdf, 0x45, 0x75, + 0x9a, 0x7a, 0xbe, 0x30, 0xcd, 0xa5, 0xc4, 0x3b, 0xd9, 0xd4, 0xa8, 0x1f, 0x5e, 0x06, 0x49, 0x91, + 0xc7, 0x0c, 0xed, 0x0e, 0x16, 0xdc, 0xa6, 0x7a, 0xec, 0xae, 0xef, 0xf1, 0x2a, 0x87, 0x3a, 0x38, + 0x9b, 0x1a, 0xbb, 0x8b, 0x19, 0xb2, 0xc4, 0x8e, 0x3f, 0x46, 0xfb, 0xf0, 0x24, 0xf2, 0x63, 0xc9, + 0xf4, 0x08, 0xdc, 0x90, 0x79, 0x89, 0xf4, 0x56, 0xc5, 0xb9, 0x95, 0x4d, 0x8d, 0xfd, 0xde, 0x72, + 0x92, 0xac, 0xe2, 0xcd, 0xdf, 0x34, 0x84, 0x57, 0x55, 0xc2, 0x6f, 0xa1, 0x1a, 0x17, 0x51, 0xf5, + 0x17, 0xd9, 0x51, 0xa2, 0xd5, 0x72, 0x68, 0x9e, 0xc3, 0x13, 0x74, 0xb3, 0x20, 0x7c, 0xec, 0x07, + 0x90, 0x70, 0x1a, 0x44, 0xea, 0xb5, 0xdf, 0xd9, 0xcc, 0x4b, 0xa2, 0xcc, 0x79, 0x4d, 0xd1, 0xdf, + 0xec, 0xad, 0xd2, 0x91, 0xab, 0xee, 0x30, 0x7f, 0x2e, 0xa3, 0x86, 0x6a, 0x7b, 0xec, 0xc3, 0x0f, + 0x2f, 0xc1, 0xcb, 0x0f, 0x16, 0xbc, 0x7c, 0x7b, 0x23, 0xdf, 0x89, 0xd6, 0xae, 0xb5, 0xf2, 0x97, + 0x4b, 0x56, 0xb6, 0x37, 0xa7, 0x5c, 0xef, 0xe4, 0xbb, 0xe8, 0x95, 0xa5, 0xfb, 0x37, 0x7a, 0x4e, + 0xf3, 0x0f, 0x0d, 0xed, 0xaf, 0xdc, 0x82, 0x3f, 0x44, 0x3b, 0x73, 0xcd, 0x40, 0xbe, 0x34, 0xb7, + 0x9d, 0x5b, 0x8a, 0x62, 0xe7, 0x70, 0x3e, 0x49, 0x16, 0xb1, 0xf8, 0x53, 0x54, 0x4d, 0x13, 0x88, + 0x95, 0x68, 0x6f, 0xaf, 0x9f, 0xf0, 0x38, 0x81, 0xb8, 0xcf, 0x4e, 0xc3, 0x42, 0x2d, 0x11, 0x21, + 0x92, 0x41, 0x4c, 0x00, 0x71, 0x1c, 0xc6, 0x6a, 0xbb, 0xce, 0x26, 0xe8, 0x89, 0x20, 0xc9, 0x73, + 0xe6, 0xef, 0x65, 0xb4, 0x7d, 0xc9, 0x82, 0xdf, 0x43, 0xdb, 0xa2, 0x52, 0xae, 0xe4, 0x7c, 0xec, + 0x3d, 0x55, 0x24, 0x31, 0x22, 0x4e, 0x66, 0x08, 0xfc, 0x06, 0xaa, 0xa4, 0xbe, 0xa7, 0x36, 0x7d, + 0x63, 0x6e, 0x35, 0x13, 0x11, 0xc7, 0x26, 0xda, 0x1a, 0xc6, 0x61, 0x1a, 0x89, 0xc7, 0x12, 0x5b, + 0x00, 0x09, 0xdd, 0x3f, 0x91, 0x11, 0xa2, 0x32, 0xf8, 0x04, 0xd5, 0x40, 0x6c, 0xe6, 0x66, 0xb5, + 0x55, 0x69, 0x37, 0xba, 0x9d, 0xcd, 0xa6, 0xb5, 0xe4, 0x36, 0xef, 0x31, 0x1e, 0x4f, 0xe6, 0xa6, + 0x12, 0x31, 0x92, 0xd3, 0x1d, 0x0c, 0xd4, 0xc6, 0x97, 0x18, 0xbc, 0x87, 0x2a, 0x23, 0x98, 0xe4, + 0x13, 0x11, 0xf1, 0x13, 0x7f, 0x84, 0x6a, 0x63, 0xf1, 0x31, 0x50, 0x2a, 0xb7, 0xd7, 0xdf, 0x5b, + 0x7c, 0x3c, 0x48, 0x5e, 0x76, 0xbf, 0x7c, 0x4f, 0x73, 0xda, 0xe7, 0x17, 0x7a, 0xe9, 0xd9, 0x85, + 0x5e, 0x7a, 0x7e, 0xa1, 0x97, 0x9e, 0x66, 0xba, 0x76, 0x9e, 0xe9, 0xda, 0xb3, 0x4c, 0xd7, 0x9e, + 0x67, 0xba, 0xf6, 0x77, 0xa6, 0x6b, 0x3f, 0xfe, 0xa3, 0x97, 0xbe, 0x2e, 0x8f, 0x3b, 0xff, 0x07, + 0x00, 0x00, 0xff, 0xff, 0x5e, 0x8d, 0x94, 0x78, 0x88, 0x08, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/authentication/v1/generated.proto b/vendor/k8s.io/api/authentication/v1/generated.proto index 1fd432a70..10c792171 100644 --- a/vendor/k8s.io/api/authentication/v1/generated.proto +++ b/vendor/k8s.io/api/authentication/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.authentication.v1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/api/authentication/v1/types_swagger_doc_generated.go b/vendor/k8s.io/api/authentication/v1/types_swagger_doc_generated.go index 68ecea8ea..6632a5dd5 100644 --- a/vendor/k8s.io/api/authentication/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/authentication/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_BoundObjectReference = map[string]string{ "": "BoundObjectReference is a reference to an object that a token is bound to.", "kind": "Kind of the referent. Valid kinds are 'Pod' and 'Secret'.", diff --git a/vendor/k8s.io/api/authentication/v1/zz_generated.deepcopy.go b/vendor/k8s.io/api/authentication/v1/zz_generated.deepcopy.go index ad0df8ff4..4b9b94105 100644 --- a/vendor/k8s.io/api/authentication/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/authentication/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/authentication/v1beta1/generated.pb.go b/vendor/k8s.io/api/authentication/v1beta1/generated.pb.go index 86e362b87..8503d212b 100644 --- a/vendor/k8s.io/api/authentication/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/authentication/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1257,46 +1257,45 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 650 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x4d, 0x4f, 0x14, 0x4d, - 0x10, 0xc7, 0x67, 0xf6, 0x85, 0x67, 0xb7, 0xf7, 0x41, 0xb1, 0x13, 0x93, 0xcd, 0x26, 0xce, 0xae, - 0xeb, 0x85, 0x44, 0xe9, 0x11, 0x24, 0x48, 0xf0, 0xe4, 0x28, 0x31, 0x98, 0x10, 0x93, 0x16, 0x3c, - 0xa8, 0x07, 0x7b, 0x67, 0x8b, 0xd9, 0x76, 0x99, 0x97, 0xf4, 0xf4, 0xac, 0x72, 0xe3, 0x23, 0x78, - 0xf4, 0x68, 0xe2, 0x27, 0x31, 0xf1, 0xc0, 0x91, 0x23, 0x07, 0x43, 0x64, 0xfc, 0x22, 0xa6, 0x7b, - 0x5a, 0x76, 0x61, 0x43, 0x80, 0xdb, 0xf4, 0xbf, 0xea, 0xff, 0x9b, 0xaa, 0xea, 0x2e, 0xf4, 0x72, - 0xb8, 0x9a, 0x12, 0x1e, 0xbb, 0xc3, 0xac, 0x07, 0x22, 0x02, 0x09, 0xa9, 0x3b, 0x82, 0xa8, 0x1f, - 0x0b, 0xd7, 0x04, 0x58, 0xc2, 0x5d, 0x96, 0xc9, 0x01, 0x44, 0x92, 0xfb, 0x4c, 0xf2, 0x38, 0x72, - 0x47, 0x8b, 0x3d, 0x90, 0x6c, 0xd1, 0x0d, 0x20, 0x02, 0xc1, 0x24, 0xf4, 0x49, 0x22, 0x62, 0x19, - 0xe3, 0xbb, 0x85, 0x85, 0xb0, 0x84, 0x93, 0xb3, 0x16, 0x62, 0x2c, 0xad, 0x85, 0x80, 0xcb, 0x41, - 0xd6, 0x23, 0x7e, 0x1c, 0xba, 0x41, 0x1c, 0xc4, 0xae, 0x76, 0xf6, 0xb2, 0x1d, 0x7d, 0xd2, 0x07, - 0xfd, 0x55, 0x10, 0x5b, 0xcb, 0xe3, 0x22, 0x42, 0xe6, 0x0f, 0x78, 0x04, 0x62, 0xcf, 0x4d, 0x86, - 0x81, 0x12, 0x52, 0x37, 0x04, 0xc9, 0xdc, 0xd1, 0x54, 0x1d, 0x2d, 0xf7, 0x22, 0x97, 0xc8, 0x22, - 0xc9, 0x43, 0x98, 0x32, 0xac, 0x5c, 0x66, 0x48, 0xfd, 0x01, 0x84, 0x6c, 0xca, 0xf7, 0xe8, 0x22, - 0x5f, 0x26, 0xf9, 0xae, 0xcb, 0x23, 0x99, 0x4a, 0x71, 0xde, 0xd4, 0x7d, 0x8c, 0xd0, 0xfa, 0x67, - 0x29, 0xd8, 0x1b, 0xb6, 0x9b, 0x01, 0x6e, 0xa3, 0x2a, 0x97, 0x10, 0xa6, 0x4d, 0xbb, 0x53, 0x9e, - 0xaf, 0x7b, 0xf5, 0xfc, 0xb8, 0x5d, 0xdd, 0x50, 0x02, 0x2d, 0xf4, 0xb5, 0xda, 0xd7, 0x6f, 0x6d, - 0x6b, 0xff, 0x57, 0xc7, 0xea, 0x7e, 0x2f, 0xa1, 0xc6, 0x56, 0x3c, 0x84, 0x88, 0xc2, 0x88, 0xc3, - 0x27, 0xfc, 0x01, 0xd5, 0xd4, 0x04, 0xfa, 0x4c, 0xb2, 0xa6, 0xdd, 0xb1, 0xe7, 0x1b, 0x4b, 0x0f, - 0xc9, 0xf8, 0x06, 0x4e, 0x0b, 0x22, 0xc9, 0x30, 0x50, 0x42, 0x4a, 0x54, 0x36, 0x19, 0x2d, 0x92, - 0x57, 0xbd, 0x8f, 0xe0, 0xcb, 0x4d, 0x90, 0xcc, 0xc3, 0x07, 0xc7, 0x6d, 0x2b, 0x3f, 0x6e, 0xa3, - 0xb1, 0x46, 0x4f, 0xa9, 0x78, 0x0b, 0x55, 0xd2, 0x04, 0xfc, 0x66, 0x49, 0xd3, 0x97, 0xc8, 0xa5, - 0xf7, 0x4b, 0x26, 0xea, 0x7b, 0x9d, 0x80, 0xef, 0xfd, 0x6f, 0xf8, 0x15, 0x75, 0xa2, 0x9a, 0x86, - 0xdf, 0xa3, 0x99, 0x54, 0x32, 0x99, 0xa5, 0xcd, 0xb2, 0xe6, 0x2e, 0x5f, 0x93, 0xab, 0xbd, 0xde, - 0x0d, 0x43, 0x9e, 0x29, 0xce, 0xd4, 0x30, 0xbb, 0x2b, 0xe8, 0xe6, 0xb9, 0x22, 0xf0, 0x3d, 0x54, - 0x95, 0x4a, 0xd2, 0x53, 0xaa, 0x7b, 0xb3, 0xc6, 0x59, 0x2d, 0xf2, 0x8a, 0x58, 0xf7, 0xa7, 0x8d, - 0x6e, 0x4d, 0xfd, 0x05, 0x3f, 0x41, 0xb3, 0x13, 0x15, 0x41, 0x5f, 0x23, 0x6a, 0xde, 0x6d, 0x83, - 0x98, 0x7d, 0x3a, 0x19, 0xa4, 0x67, 0x73, 0xf1, 0x26, 0xaa, 0x64, 0x29, 0x08, 0x33, 0xbe, 0xfb, - 0x57, 0x68, 0x73, 0x3b, 0x05, 0xb1, 0x11, 0xed, 0xc4, 0xe3, 0xb9, 0x29, 0x85, 0x6a, 0x8c, 0x6a, - 0x03, 0x84, 0x88, 0x85, 0x1e, 0xdb, 0x44, 0x1b, 0xeb, 0x4a, 0xa4, 0x45, 0xac, 0xfb, 0xa3, 0x84, - 0x6a, 0xff, 0x28, 0xf8, 0x01, 0xaa, 0x29, 0x67, 0xc4, 0x42, 0x30, 0xbd, 0xcf, 0x19, 0x93, 0xce, - 0x51, 0x3a, 0x3d, 0xcd, 0xc0, 0x77, 0x50, 0x39, 0xe3, 0x7d, 0x5d, 0x6d, 0xdd, 0x6b, 0x98, 0xc4, - 0xf2, 0xf6, 0xc6, 0x73, 0xaa, 0x74, 0xdc, 0x45, 0x33, 0x81, 0x88, 0xb3, 0x44, 0x5d, 0x9b, 0x7a, - 0xaa, 0x48, 0x0d, 0xff, 0x85, 0x56, 0xa8, 0x89, 0xe0, 0x77, 0xa8, 0x0a, 0xea, 0x6d, 0x37, 0x2b, - 0x9d, 0xf2, 0x7c, 0x63, 0x69, 0xe5, 0x1a, 0x2d, 0x13, 0xbd, 0x14, 0xeb, 0x91, 0x14, 0x7b, 0x13, - 0xad, 0x29, 0x8d, 0x16, 0xcc, 0x56, 0x60, 0x16, 0x47, 0xe7, 0xe0, 0x39, 0x54, 0x1e, 0xc2, 0x5e, - 0xd1, 0x16, 0x55, 0x9f, 0xf8, 0x19, 0xaa, 0x8e, 0xd4, 0x4e, 0x99, 0x79, 0x2f, 0x5c, 0xe1, 0xe7, - 0xe3, 0x45, 0xa4, 0x85, 0x77, 0xad, 0xb4, 0x6a, 0x7b, 0x0b, 0x07, 0x27, 0x8e, 0x75, 0x78, 0xe2, - 0x58, 0x47, 0x27, 0x8e, 0xb5, 0x9f, 0x3b, 0xf6, 0x41, 0xee, 0xd8, 0x87, 0xb9, 0x63, 0x1f, 0xe5, - 0x8e, 0xfd, 0x3b, 0x77, 0xec, 0x2f, 0x7f, 0x1c, 0xeb, 0xed, 0x7f, 0x06, 0xf2, 0x37, 0x00, 0x00, - 0xff, 0xff, 0x36, 0x0e, 0x35, 0x2a, 0x43, 0x05, 0x00, 0x00, + // 635 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xcf, 0x4f, 0xd4, 0x40, + 0x14, 0x6e, 0xf7, 0x07, 0xee, 0xce, 0x8a, 0xe2, 0x24, 0x26, 0x9b, 0x4d, 0xec, 0xae, 0xeb, 0x85, + 0x44, 0x99, 0x0a, 0x21, 0x48, 0xf0, 0x64, 0x95, 0x18, 0x4c, 0x88, 0xc9, 0x08, 0x1e, 0xd4, 0x83, + 0xb3, 0xdd, 0x47, 0xb7, 0xae, 0xed, 0x34, 0xd3, 0x69, 0x95, 0x1b, 0x7f, 0x82, 0x47, 0x8f, 0x26, + 0xfe, 0x25, 0x26, 0x1e, 0x38, 0x72, 0xe4, 0x60, 0x88, 0xd4, 0x7f, 0xc4, 0xcc, 0x74, 0x64, 0x17, + 0x88, 0x01, 0x6e, 0xf3, 0xbe, 0xf7, 0xbe, 0x6f, 0xde, 0xf7, 0x66, 0x1e, 0x7a, 0x31, 0x5e, 0x4d, + 0x49, 0xc8, 0xdd, 0x71, 0x36, 0x00, 0x11, 0x83, 0x84, 0xd4, 0xcd, 0x21, 0x1e, 0x72, 0xe1, 0x9a, + 0x04, 0x4b, 0x42, 0x97, 0x65, 0x72, 0x04, 0xb1, 0x0c, 0x7d, 0x26, 0x43, 0x1e, 0xbb, 0xf9, 0xe2, + 0x00, 0x24, 0x5b, 0x74, 0x03, 0x88, 0x41, 0x30, 0x09, 0x43, 0x92, 0x08, 0x2e, 0x39, 0xbe, 0x5b, + 0x52, 0x08, 0x4b, 0x42, 0x72, 0x9a, 0x42, 0x0c, 0xa5, 0xb3, 0x10, 0x84, 0x72, 0x94, 0x0d, 0x88, + 0xcf, 0x23, 0x37, 0xe0, 0x01, 0x77, 0x35, 0x73, 0x90, 0xed, 0xe8, 0x48, 0x07, 0xfa, 0x54, 0x2a, + 0x76, 0x96, 0x27, 0x4d, 0x44, 0xcc, 0x1f, 0x85, 0x31, 0x88, 0x5d, 0x37, 0x19, 0x07, 0x0a, 0x48, + 0xdd, 0x08, 0x24, 0x73, 0xf3, 0x73, 0x7d, 0x74, 0xdc, 0xff, 0xb1, 0x44, 0x16, 0xcb, 0x30, 0x82, + 0x73, 0x84, 0x95, 0x8b, 0x08, 0xa9, 0x3f, 0x82, 0x88, 0x9d, 0xe5, 0xf5, 0x1f, 0x21, 0xb4, 0xfe, + 0x59, 0x0a, 0xf6, 0x9a, 0x7d, 0xcc, 0x00, 0x77, 0x51, 0x3d, 0x94, 0x10, 0xa5, 0x6d, 0xbb, 0x57, + 0x9d, 0x6f, 0x7a, 0xcd, 0xe2, 0xa8, 0x5b, 0xdf, 0x50, 0x00, 0x2d, 0xf1, 0xb5, 0xc6, 0xd7, 0x6f, + 0x5d, 0x6b, 0xef, 0x57, 0xcf, 0xea, 0x7f, 0xaf, 0xa0, 0xd6, 0x16, 0x1f, 0x43, 0x4c, 0x21, 0x0f, + 0xe1, 0x13, 0x7e, 0x8f, 0x1a, 0xca, 0xcc, 0x90, 0x49, 0xd6, 0xb6, 0x7b, 0xf6, 0x7c, 0x6b, 0xe9, + 0x21, 0x99, 0x0c, 0xf3, 0xa4, 0x27, 0x92, 0x8c, 0x03, 0x05, 0xa4, 0x44, 0x55, 0x93, 0x7c, 0x91, + 0xbc, 0x1c, 0x7c, 0x00, 0x5f, 0x6e, 0x82, 0x64, 0x1e, 0xde, 0x3f, 0xea, 0x5a, 0xc5, 0x51, 0x17, + 0x4d, 0x30, 0x7a, 0xa2, 0x8a, 0xb7, 0x50, 0x2d, 0x4d, 0xc0, 0x6f, 0x57, 0xb4, 0xfa, 0x12, 0xb9, + 0xf0, 0xa9, 0xc8, 0x54, 0x7f, 0xaf, 0x12, 0xf0, 0xbd, 0xeb, 0x46, 0xbf, 0xa6, 0x22, 0xaa, 0xd5, + 0xf0, 0x3b, 0x34, 0x93, 0x4a, 0x26, 0xb3, 0xb4, 0x5d, 0xd5, 0xba, 0xcb, 0x57, 0xd4, 0xd5, 0x5c, + 0xef, 0x86, 0x51, 0x9e, 0x29, 0x63, 0x6a, 0x34, 0xfb, 0x2b, 0xe8, 0xe6, 0x99, 0x26, 0xf0, 0x3d, + 0x54, 0x97, 0x0a, 0xd2, 0x53, 0x6a, 0x7a, 0xb3, 0x86, 0x59, 0x2f, 0xeb, 0xca, 0x5c, 0xff, 0xa7, + 0x8d, 0x6e, 0x9d, 0xbb, 0x05, 0x3f, 0x46, 0xb3, 0x53, 0x1d, 0xc1, 0x50, 0x4b, 0x34, 0xbc, 0xdb, + 0x46, 0x62, 0xf6, 0xc9, 0x74, 0x92, 0x9e, 0xae, 0xc5, 0x9b, 0xa8, 0x96, 0xa5, 0x20, 0xcc, 0xf8, + 0xee, 0x5f, 0xc2, 0xe6, 0x76, 0x0a, 0x62, 0x23, 0xde, 0xe1, 0x93, 0xb9, 0x29, 0x84, 0x6a, 0x19, + 0x65, 0x03, 0x84, 0xe0, 0x42, 0x8f, 0x6d, 0xca, 0xc6, 0xba, 0x02, 0x69, 0x99, 0xeb, 0xff, 0xa8, + 0xa0, 0xc6, 0x3f, 0x15, 0xfc, 0x00, 0x35, 0x14, 0x33, 0x66, 0x11, 0x18, 0xef, 0x73, 0x86, 0xa4, + 0x6b, 0x14, 0x4e, 0x4f, 0x2a, 0xf0, 0x1d, 0x54, 0xcd, 0xc2, 0xa1, 0xee, 0xb6, 0xe9, 0xb5, 0x4c, + 0x61, 0x75, 0x7b, 0xe3, 0x19, 0x55, 0x38, 0xee, 0xa3, 0x99, 0x40, 0xf0, 0x2c, 0x51, 0xcf, 0xa6, + 0xbe, 0x2a, 0x52, 0xc3, 0x7f, 0xae, 0x11, 0x6a, 0x32, 0xf8, 0x2d, 0xaa, 0x83, 0xfa, 0xdb, 0xed, + 0x5a, 0xaf, 0x3a, 0xdf, 0x5a, 0x5a, 0xb9, 0x82, 0x65, 0xa2, 0x97, 0x62, 0x3d, 0x96, 0x62, 0x77, + 0xca, 0x9a, 0xc2, 0x68, 0xa9, 0xd9, 0x09, 0xcc, 0xe2, 0xe8, 0x1a, 0x3c, 0x87, 0xaa, 0x63, 0xd8, + 0x2d, 0x6d, 0x51, 0x75, 0xc4, 0x4f, 0x51, 0x3d, 0x57, 0x3b, 0x65, 0xe6, 0xbd, 0x70, 0x89, 0xcb, + 0x27, 0x8b, 0x48, 0x4b, 0xee, 0x5a, 0x65, 0xd5, 0xf6, 0x16, 0xf6, 0x8f, 0x1d, 0xeb, 0xe0, 0xd8, + 0xb1, 0x0e, 0x8f, 0x1d, 0x6b, 0xaf, 0x70, 0xec, 0xfd, 0xc2, 0xb1, 0x0f, 0x0a, 0xc7, 0x3e, 0x2c, + 0x1c, 0xfb, 0x77, 0xe1, 0xd8, 0x5f, 0xfe, 0x38, 0xd6, 0x9b, 0x6b, 0x46, 0xe4, 0x6f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x39, 0x00, 0xe7, 0xfa, 0x0e, 0x05, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/authentication/v1beta1/generated.proto b/vendor/k8s.io/api/authentication/v1beta1/generated.proto index 3d0abd15d..a057bc591 100644 --- a/vendor/k8s.io/api/authentication/v1beta1/generated.proto +++ b/vendor/k8s.io/api/authentication/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.authentication.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/api/authentication/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/authentication/v1beta1/types_swagger_doc_generated.go index f910bea6f..968999d1e 100644 --- a/vendor/k8s.io/api/authentication/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/authentication/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_TokenReview = map[string]string{ "": "TokenReview attempts to authenticate a token to a known user. Note: TokenReview requests may be cached by the webhook token authenticator plugin in the kube-apiserver.", "spec": "Spec holds information about the request being evaluated", diff --git a/vendor/k8s.io/api/authentication/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/authentication/v1beta1/zz_generated.deepcopy.go index 57d878e9a..bb552ff63 100644 --- a/vendor/k8s.io/api/authentication/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/authentication/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/authorization/v1/generated.pb.go b/vendor/k8s.io/api/authorization/v1/generated.pb.go index bdb606c0b..e9145af02 100644 --- a/vendor/k8s.io/api/authorization/v1/generated.pb.go +++ b/vendor/k8s.io/api/authorization/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -3452,77 +3452,77 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1152 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xf7, 0xae, 0xed, 0xd4, 0x1e, 0x37, 0x24, 0x9d, 0x28, 0xcd, 0x36, 0x15, 0x76, 0xb4, 0x48, - 0x90, 0x8a, 0xb2, 0x4b, 0x4c, 0xdb, 0x44, 0x95, 0x2a, 0x14, 0x2b, 0x11, 0x8a, 0xd4, 0x96, 0x6a, - 0xa2, 0x44, 0xa2, 0x08, 0xc4, 0x78, 0x3d, 0xb1, 0x97, 0xd8, 0xbb, 0xcb, 0xcc, 0xac, 0x43, 0x38, - 0x55, 0xe2, 0x0b, 0x70, 0xe4, 0xc0, 0x81, 0x6f, 0xc0, 0x05, 0x89, 0x1b, 0x07, 0x0e, 0x28, 0xc7, - 0x1e, 0x8b, 0x84, 0x2c, 0xb2, 0x9c, 0xf9, 0x0e, 0x68, 0x66, 0xc7, 0xde, 0x75, 0xb2, 0x76, 0x13, - 0x0e, 0xf4, 0xd2, 0xdb, 0xee, 0xfb, 0xfd, 0xde, 0x9f, 0x79, 0x7f, 0x66, 0x1e, 0xd8, 0x3a, 0xdc, - 0x60, 0x96, 0xeb, 0xdb, 0x87, 0x61, 0x93, 0x50, 0x8f, 0x70, 0xc2, 0xec, 0x3e, 0xf1, 0x5a, 0x3e, - 0xb5, 0x15, 0x80, 0x03, 0xd7, 0xc6, 0x21, 0xef, 0xf8, 0xd4, 0xfd, 0x06, 0x73, 0xd7, 0xf7, 0xec, - 0xfe, 0x9a, 0xdd, 0x26, 0x1e, 0xa1, 0x98, 0x93, 0x96, 0x15, 0x50, 0x9f, 0xfb, 0xf0, 0x66, 0x4c, - 0xb6, 0x70, 0xe0, 0x5a, 0x63, 0x64, 0xab, 0xbf, 0xb6, 0xfc, 0x5e, 0xdb, 0xe5, 0x9d, 0xb0, 0x69, - 0x39, 0x7e, 0xcf, 0x6e, 0xfb, 0x6d, 0xdf, 0x96, 0x3a, 0xcd, 0xf0, 0x40, 0xfe, 0xc9, 0x1f, 0xf9, - 0x15, 0xdb, 0x5a, 0xbe, 0x93, 0x38, 0xee, 0x61, 0xa7, 0xe3, 0x7a, 0x84, 0x1e, 0xdb, 0xc1, 0x61, - 0x5b, 0x08, 0x98, 0xdd, 0x23, 0x1c, 0x67, 0x44, 0xb0, 0x6c, 0x4f, 0xd2, 0xa2, 0xa1, 0xc7, 0xdd, - 0x1e, 0x39, 0xa7, 0x70, 0xef, 0x65, 0x0a, 0xcc, 0xe9, 0x90, 0x1e, 0x3e, 0xa7, 0xf7, 0xc1, 0x24, - 0xbd, 0x90, 0xbb, 0x5d, 0xdb, 0xf5, 0x38, 0xe3, 0xf4, 0xac, 0x92, 0xb9, 0x0e, 0xc0, 0xf6, 0xd7, - 0x9c, 0xe2, 0x7d, 0xdc, 0x0d, 0x09, 0xac, 0x81, 0xa2, 0xcb, 0x49, 0x8f, 0x19, 0xda, 0x4a, 0x7e, - 0xb5, 0xdc, 0x28, 0x47, 0x83, 0x5a, 0x71, 0x47, 0x08, 0x50, 0x2c, 0xbf, 0x5f, 0xfa, 0xfe, 0xc7, - 0x5a, 0xee, 0xd9, 0x9f, 0x2b, 0x39, 0xf3, 0x67, 0x1d, 0x18, 0x0f, 0x7d, 0x07, 0x77, 0x77, 0xc3, - 0xe6, 0x97, 0xc4, 0xe1, 0x9b, 0x8e, 0x43, 0x18, 0x43, 0xa4, 0xef, 0x92, 0x23, 0xf8, 0x05, 0x28, - 0x89, 0x74, 0xb4, 0x30, 0xc7, 0x86, 0xb6, 0xa2, 0xad, 0x56, 0xea, 0xef, 0x5b, 0x49, 0x21, 0x46, - 0xd1, 0x59, 0xc1, 0x61, 0x5b, 0x08, 0x98, 0x25, 0xd8, 0x56, 0x7f, 0xcd, 0xfa, 0x58, 0xda, 0x7a, - 0x44, 0x38, 0x6e, 0xc0, 0x93, 0x41, 0x2d, 0x17, 0x0d, 0x6a, 0x20, 0x91, 0xa1, 0x91, 0x55, 0xb8, - 0x0f, 0x0a, 0x2c, 0x20, 0x8e, 0xa1, 0x4b, 0xeb, 0x77, 0xac, 0x29, 0x65, 0xb6, 0x32, 0x22, 0xdc, - 0x0d, 0x88, 0xd3, 0xb8, 0xaa, 0x3c, 0x14, 0xc4, 0x1f, 0x92, 0xf6, 0xe0, 0xe7, 0x60, 0x86, 0x71, - 0xcc, 0x43, 0x66, 0xe4, 0xa5, 0xe5, 0x7b, 0x97, 0xb6, 0x2c, 0xb5, 0x1b, 0x6f, 0x28, 0xdb, 0x33, - 0xf1, 0x3f, 0x52, 0x56, 0xcd, 0x4f, 0xc1, 0xe2, 0x63, 0xdf, 0x43, 0x84, 0xf9, 0x21, 0x75, 0xc8, - 0x26, 0xe7, 0xd4, 0x6d, 0x86, 0x9c, 0x30, 0xb8, 0x02, 0x0a, 0x01, 0xe6, 0x1d, 0x99, 0xae, 0x72, - 0x12, 0xda, 0x13, 0xcc, 0x3b, 0x48, 0x22, 0x82, 0xd1, 0x27, 0xb4, 0x29, 0x8f, 0x9c, 0x62, 0xec, - 0x13, 0xda, 0x44, 0x12, 0x31, 0xbf, 0x02, 0x73, 0x29, 0xe3, 0x28, 0xec, 0xca, 0x8a, 0x0a, 0x68, - 0xac, 0xa2, 0x42, 0x83, 0xa1, 0x58, 0x0e, 0x1f, 0x80, 0x39, 0x2f, 0xd1, 0xd9, 0x43, 0x0f, 0x99, - 0xa1, 0x4b, 0xea, 0x42, 0x34, 0xa8, 0xa5, 0xcd, 0x09, 0x08, 0x9d, 0xe5, 0x9a, 0xbf, 0xea, 0x00, - 0x66, 0x9c, 0xc6, 0x06, 0x65, 0x0f, 0xf7, 0x08, 0x0b, 0xb0, 0x43, 0xd4, 0x91, 0xae, 0xa9, 0x80, - 0xcb, 0x8f, 0x87, 0x00, 0x4a, 0x38, 0x2f, 0x3f, 0x1c, 0x7c, 0x0b, 0x14, 0xdb, 0xd4, 0x0f, 0x03, - 0x59, 0x98, 0x72, 0x63, 0x56, 0x51, 0x8a, 0x1f, 0x09, 0x21, 0x8a, 0x31, 0x78, 0x0b, 0x5c, 0xe9, - 0x13, 0xca, 0x5c, 0xdf, 0x33, 0x0a, 0x92, 0x36, 0xa7, 0x68, 0x57, 0xf6, 0x63, 0x31, 0x1a, 0xe2, - 0xf0, 0x36, 0x28, 0x51, 0x15, 0xb8, 0x51, 0x94, 0xdc, 0x79, 0xc5, 0x2d, 0x8d, 0x32, 0x38, 0x62, - 0xc0, 0xbb, 0xa0, 0xc2, 0xc2, 0xe6, 0x48, 0x61, 0x46, 0x2a, 0x2c, 0x28, 0x85, 0xca, 0x6e, 0x02, - 0xa1, 0x34, 0x4f, 0x1c, 0x4b, 0x9c, 0xd1, 0xb8, 0x32, 0x7e, 0x2c, 0x91, 0x02, 0x24, 0x11, 0xf3, - 0x37, 0x0d, 0x5c, 0xbd, 0x5c, 0xc5, 0xde, 0x05, 0x65, 0x1c, 0xb8, 0xf2, 0xd8, 0xc3, 0x5a, 0xcd, - 0x8a, 0xbc, 0x6e, 0x3e, 0xd9, 0x89, 0x85, 0x28, 0xc1, 0x05, 0x79, 0x18, 0x8c, 0x68, 0xe9, 0x11, - 0x79, 0xe8, 0x92, 0xa1, 0x04, 0x87, 0xeb, 0x60, 0x76, 0xf8, 0x23, 0x8b, 0x64, 0x14, 0xa4, 0xc2, - 0xb5, 0x68, 0x50, 0x9b, 0x45, 0x69, 0x00, 0x8d, 0xf3, 0xcc, 0x5f, 0x74, 0xb0, 0xb4, 0x4b, 0xba, - 0x07, 0xaf, 0xe6, 0x2e, 0x78, 0x3a, 0x76, 0x17, 0x6c, 0x4c, 0x9f, 0xd8, 0xec, 0x28, 0x5f, 0xd9, - 0x7d, 0xf0, 0x83, 0x0e, 0x6e, 0x4e, 0x89, 0x09, 0x1e, 0x01, 0x48, 0xcf, 0x8d, 0x97, 0xca, 0xa3, - 0x3d, 0x35, 0x96, 0xf3, 0x53, 0xd9, 0xb8, 0x1e, 0x0d, 0x6a, 0x19, 0xd3, 0x8a, 0x32, 0x5c, 0xc0, - 0x6f, 0x35, 0xb0, 0xe8, 0x65, 0xdd, 0x54, 0x2a, 0xcd, 0xf5, 0xa9, 0xce, 0x33, 0xef, 0xb8, 0xc6, - 0x8d, 0x68, 0x50, 0xcb, 0xbe, 0xfe, 0x50, 0xb6, 0x2f, 0xf1, 0xca, 0x5c, 0x4f, 0xa5, 0x47, 0x0c, - 0xc8, 0xff, 0xd7, 0x57, 0x9f, 0x8c, 0xf5, 0xd5, 0xfa, 0x45, 0xfb, 0x2a, 0x15, 0xe4, 0xc4, 0xb6, - 0xfa, 0xec, 0x4c, 0x5b, 0xdd, 0xbd, 0x48, 0x5b, 0xa5, 0x0d, 0x4f, 0xef, 0xaa, 0x47, 0x60, 0x79, - 0x72, 0x40, 0x97, 0xbe, 0x9c, 0xcd, 0x9f, 0x74, 0xb0, 0xf0, 0xfa, 0x99, 0xbf, 0xcc, 0x58, 0xff, - 0x5e, 0x00, 0x4b, 0xaf, 0x47, 0x7a, 0xd2, 0xa2, 0x13, 0x32, 0x42, 0xd5, 0x33, 0x3e, 0x2a, 0xce, - 0x1e, 0x23, 0x14, 0x49, 0x04, 0x9a, 0x60, 0xa6, 0x1d, 0xbf, 0x6e, 0xf1, 0xfb, 0x03, 0x44, 0x82, - 0xd5, 0xd3, 0xa6, 0x10, 0xd8, 0x02, 0x45, 0x22, 0xf6, 0x56, 0xa3, 0xb8, 0x92, 0x5f, 0xad, 0xd4, - 0x3f, 0xfc, 0x2f, 0x9d, 0x61, 0xc9, 0xcd, 0x77, 0xdb, 0xe3, 0xf4, 0x38, 0x59, 0x27, 0xa4, 0x0c, - 0xc5, 0xc6, 0xe1, 0x9b, 0x20, 0x1f, 0xba, 0x2d, 0xf5, 0xda, 0x57, 0x14, 0x25, 0xbf, 0xb7, 0xb3, - 0x85, 0x84, 0x7c, 0x19, 0xab, 0xe5, 0x59, 0x9a, 0x80, 0xf3, 0x20, 0x7f, 0x48, 0x8e, 0xe3, 0x81, - 0x42, 0xe2, 0x13, 0x3e, 0x00, 0xc5, 0xbe, 0xd8, 0xab, 0x55, 0x7e, 0xdf, 0x99, 0x1a, 0x64, 0xb2, - 0x86, 0xa3, 0x58, 0xeb, 0xbe, 0xbe, 0xa1, 0x99, 0x7f, 0x68, 0xe0, 0xc6, 0xc4, 0xf6, 0x13, 0xeb, - 0x0e, 0xee, 0x76, 0xfd, 0x23, 0xd2, 0x92, 0x6e, 0x4b, 0xc9, 0xba, 0xb3, 0x19, 0x8b, 0xd1, 0x10, - 0x87, 0x6f, 0x83, 0x19, 0x4a, 0x30, 0xf3, 0x3d, 0xb5, 0x62, 0x8d, 0x3a, 0x17, 0x49, 0x29, 0x52, - 0x28, 0xdc, 0x04, 0x73, 0x44, 0xb8, 0x97, 0x71, 0x6d, 0x53, 0xea, 0x0f, 0x2b, 0xb5, 0xa4, 0x14, - 0xe6, 0xb6, 0xc7, 0x61, 0x74, 0x96, 0x2f, 0x5c, 0xb5, 0x88, 0xe7, 0x92, 0x96, 0xdc, 0xc1, 0x4a, - 0x89, 0xab, 0x2d, 0x29, 0x45, 0x0a, 0x35, 0xff, 0xd1, 0x81, 0x31, 0xe9, 0x6a, 0x83, 0x07, 0xc9, - 0x2e, 0x22, 0x41, 0xb9, 0x0e, 0x55, 0xea, 0xb7, 0x2e, 0x34, 0x20, 0x42, 0xa3, 0xb1, 0xa8, 0xdc, - 0xce, 0xa6, 0xa5, 0xa9, 0xd5, 0x45, 0xfe, 0x42, 0x0a, 0xe6, 0xbd, 0xf1, 0x9d, 0x39, 0x5e, 0xaa, - 0x2a, 0xf5, 0xdb, 0x17, 0x1d, 0x07, 0xe9, 0xcd, 0x50, 0xde, 0xe6, 0xcf, 0x00, 0x0c, 0x9d, 0xb3, - 0x0f, 0xeb, 0x00, 0xb8, 0x9e, 0xe3, 0xf7, 0x82, 0x2e, 0xe1, 0x44, 0xa6, 0xb7, 0x94, 0xdc, 0x83, - 0x3b, 0x23, 0x04, 0xa5, 0x58, 0x59, 0x75, 0x29, 0x5c, 0xae, 0x2e, 0x8d, 0xd5, 0x93, 0xd3, 0x6a, - 0xee, 0xf9, 0x69, 0x35, 0xf7, 0xe2, 0xb4, 0x9a, 0x7b, 0x16, 0x55, 0xb5, 0x93, 0xa8, 0xaa, 0x3d, - 0x8f, 0xaa, 0xda, 0x8b, 0xa8, 0xaa, 0xfd, 0x15, 0x55, 0xb5, 0xef, 0xfe, 0xae, 0xe6, 0x9e, 0xea, - 0xfd, 0xb5, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd6, 0x0e, 0xab, 0x82, 0x7c, 0x0f, 0x00, 0x00, + // 1140 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4d, 0x6f, 0x1b, 0xc5, + 0x1b, 0xf7, 0xae, 0xed, 0xc4, 0x1e, 0x37, 0xff, 0xa4, 0x13, 0xa5, 0xd9, 0xa6, 0xfa, 0xdb, 0xd1, + 0x22, 0x41, 0x2a, 0xca, 0x2e, 0xb1, 0xda, 0x26, 0xaa, 0x54, 0xa1, 0x58, 0x89, 0x50, 0xa4, 0xb6, + 0x54, 0x13, 0x25, 0x12, 0x45, 0x20, 0xc6, 0xeb, 0x89, 0xbd, 0xc4, 0xde, 0x5d, 0x66, 0x66, 0x1d, + 0xc2, 0xa9, 0x12, 0x5f, 0x80, 0x23, 0x07, 0x0e, 0x7c, 0x03, 0x2e, 0x48, 0xdc, 0x38, 0x70, 0x40, + 0x39, 0xf6, 0x58, 0x24, 0x64, 0x91, 0xe5, 0xcc, 0x77, 0x40, 0x33, 0x3b, 0xf6, 0xae, 0x93, 0xb5, + 0x9b, 0x70, 0xa0, 0x97, 0xde, 0x76, 0x9f, 0xdf, 0xef, 0x79, 0x99, 0xe7, 0x65, 0xe6, 0x01, 0xdb, + 0x47, 0x9b, 0xcc, 0x72, 0x7d, 0xfb, 0x28, 0x6c, 0x12, 0xea, 0x11, 0x4e, 0x98, 0xdd, 0x27, 0x5e, + 0xcb, 0xa7, 0xb6, 0x02, 0x70, 0xe0, 0xda, 0x38, 0xe4, 0x1d, 0x9f, 0xba, 0x5f, 0x63, 0xee, 0xfa, + 0x9e, 0xdd, 0x5f, 0xb7, 0xdb, 0xc4, 0x23, 0x14, 0x73, 0xd2, 0xb2, 0x02, 0xea, 0x73, 0x1f, 0xde, + 0x8a, 0xc9, 0x16, 0x0e, 0x5c, 0x6b, 0x8c, 0x6c, 0xf5, 0xd7, 0x57, 0xde, 0x6b, 0xbb, 0xbc, 0x13, + 0x36, 0x2d, 0xc7, 0xef, 0xd9, 0x6d, 0xbf, 0xed, 0xdb, 0x52, 0xa7, 0x19, 0x1e, 0xca, 0x3f, 0xf9, + 0x23, 0xbf, 0x62, 0x5b, 0x2b, 0x77, 0x13, 0xc7, 0x3d, 0xec, 0x74, 0x5c, 0x8f, 0xd0, 0x13, 0x3b, + 0x38, 0x6a, 0x0b, 0x01, 0xb3, 0x7b, 0x84, 0xe3, 0x8c, 0x08, 0x56, 0xec, 0x49, 0x5a, 0x34, 0xf4, + 0xb8, 0xdb, 0x23, 0x17, 0x14, 0xee, 0xbf, 0x4a, 0x81, 0x39, 0x1d, 0xd2, 0xc3, 0xe7, 0xf5, 0xcc, + 0x0d, 0x00, 0x76, 0xbe, 0xe2, 0x14, 0x1f, 0xe0, 0x6e, 0x48, 0x60, 0x0d, 0x14, 0x5d, 0x4e, 0x7a, + 0xcc, 0xd0, 0x56, 0xf3, 0x6b, 0xe5, 0x46, 0x39, 0x1a, 0xd4, 0x8a, 0xbb, 0x42, 0x80, 0x62, 0xf9, + 0x83, 0xd2, 0x77, 0x3f, 0xd4, 0x72, 0xcf, 0xff, 0x58, 0xcd, 0x99, 0x3f, 0xe9, 0xc0, 0x78, 0xe4, + 0x3b, 0xb8, 0xbb, 0x17, 0x36, 0xbf, 0x20, 0x0e, 0xdf, 0x72, 0x1c, 0xc2, 0x18, 0x22, 0x7d, 0x97, + 0x1c, 0xc3, 0xcf, 0x41, 0x49, 0x9c, 0xac, 0x85, 0x39, 0x36, 0xb4, 0x55, 0x6d, 0xad, 0x52, 0x7f, + 0xdf, 0x4a, 0x72, 0x3a, 0x0a, 0xd0, 0x0a, 0x8e, 0xda, 0x42, 0xc0, 0x2c, 0xc1, 0xb6, 0xfa, 0xeb, + 0xd6, 0x47, 0xd2, 0xd6, 0x63, 0xc2, 0x71, 0x03, 0x9e, 0x0e, 0x6a, 0xb9, 0x68, 0x50, 0x03, 0x89, + 0x0c, 0x8d, 0xac, 0xc2, 0x03, 0x50, 0x60, 0x01, 0x71, 0x0c, 0x5d, 0x5a, 0xbf, 0x6b, 0x4d, 0xa9, + 0x98, 0x95, 0x11, 0xe1, 0x5e, 0x40, 0x9c, 0xc6, 0x35, 0xe5, 0xa1, 0x20, 0xfe, 0x90, 0xb4, 0x07, + 0x3f, 0x03, 0x33, 0x8c, 0x63, 0x1e, 0x32, 0x23, 0x2f, 0x2d, 0xdf, 0xbf, 0xb2, 0x65, 0xa9, 0xdd, + 0xf8, 0x9f, 0xb2, 0x3d, 0x13, 0xff, 0x23, 0x65, 0xd5, 0xfc, 0x04, 0x2c, 0x3d, 0xf1, 0x3d, 0x44, + 0x98, 0x1f, 0x52, 0x87, 0x6c, 0x71, 0x4e, 0xdd, 0x66, 0xc8, 0x09, 0x83, 0xab, 0xa0, 0x10, 0x60, + 0xde, 0x91, 0xe9, 0x2a, 0x27, 0xa1, 0x3d, 0xc5, 0xbc, 0x83, 0x24, 0x22, 0x18, 0x7d, 0x42, 0x9b, + 0xf2, 0xc8, 0x29, 0xc6, 0x01, 0xa1, 0x4d, 0x24, 0x11, 0xf3, 0x4b, 0x30, 0x9f, 0x32, 0x8e, 0xc2, + 0xae, 0xac, 0xa8, 0x80, 0xc6, 0x2a, 0x2a, 0x34, 0x18, 0x8a, 0xe5, 0xf0, 0x21, 0x98, 0xf7, 0x12, + 0x9d, 0x7d, 0xf4, 0x88, 0x19, 0xba, 0xa4, 0x2e, 0x46, 0x83, 0x5a, 0xda, 0x9c, 0x80, 0xd0, 0x79, + 0xae, 0xf9, 0x8b, 0x0e, 0x60, 0xc6, 0x69, 0x6c, 0x50, 0xf6, 0x70, 0x8f, 0xb0, 0x00, 0x3b, 0x44, + 0x1d, 0xe9, 0xba, 0x0a, 0xb8, 0xfc, 0x64, 0x08, 0xa0, 0x84, 0xf3, 0xea, 0xc3, 0xc1, 0xb7, 0x40, + 0xb1, 0x4d, 0xfd, 0x30, 0x90, 0x85, 0x29, 0x37, 0xe6, 0x14, 0xa5, 0xf8, 0xa1, 0x10, 0xa2, 0x18, + 0x83, 0xb7, 0xc1, 0x6c, 0x9f, 0x50, 0xe6, 0xfa, 0x9e, 0x51, 0x90, 0xb4, 0x79, 0x45, 0x9b, 0x3d, + 0x88, 0xc5, 0x68, 0x88, 0xc3, 0x3b, 0xa0, 0x44, 0x55, 0xe0, 0x46, 0x51, 0x72, 0x17, 0x14, 0xb7, + 0x34, 0xca, 0xe0, 0x88, 0x01, 0xef, 0x81, 0x0a, 0x0b, 0x9b, 0x23, 0x85, 0x19, 0xa9, 0xb0, 0xa8, + 0x14, 0x2a, 0x7b, 0x09, 0x84, 0xd2, 0x3c, 0x71, 0x2c, 0x71, 0x46, 0x63, 0x76, 0xfc, 0x58, 0x22, + 0x05, 0x48, 0x22, 0xe6, 0xaf, 0x1a, 0xb8, 0x76, 0xb5, 0x8a, 0xbd, 0x0b, 0xca, 0x38, 0x70, 0xe5, + 0xb1, 0x87, 0xb5, 0x9a, 0x13, 0x79, 0xdd, 0x7a, 0xba, 0x1b, 0x0b, 0x51, 0x82, 0x0b, 0xf2, 0x30, + 0x18, 0xd1, 0xd2, 0x23, 0xf2, 0xd0, 0x25, 0x43, 0x09, 0x0e, 0x37, 0xc0, 0xdc, 0xf0, 0x47, 0x16, + 0xc9, 0x28, 0x48, 0x85, 0xeb, 0xd1, 0xa0, 0x36, 0x87, 0xd2, 0x00, 0x1a, 0xe7, 0x99, 0x3f, 0xeb, + 0x60, 0x79, 0x8f, 0x74, 0x0f, 0x5f, 0xcf, 0x5d, 0xf0, 0x6c, 0xec, 0x2e, 0xd8, 0x9c, 0x3e, 0xb1, + 0xd9, 0x51, 0xbe, 0xb6, 0xfb, 0xe0, 0x7b, 0x1d, 0xdc, 0x9a, 0x12, 0x13, 0x3c, 0x06, 0x90, 0x5e, + 0x18, 0x2f, 0x95, 0x47, 0x7b, 0x6a, 0x2c, 0x17, 0xa7, 0xb2, 0x71, 0x23, 0x1a, 0xd4, 0x32, 0xa6, + 0x15, 0x65, 0xb8, 0x80, 0xdf, 0x68, 0x60, 0xc9, 0xcb, 0xba, 0xa9, 0x54, 0x9a, 0xeb, 0x53, 0x9d, + 0x67, 0xde, 0x71, 0x8d, 0x9b, 0xd1, 0xa0, 0x96, 0x7d, 0xfd, 0xa1, 0x6c, 0x5f, 0xe2, 0x95, 0xb9, + 0x91, 0x4a, 0x8f, 0x18, 0x90, 0xff, 0xae, 0xaf, 0x3e, 0x1e, 0xeb, 0xab, 0x8d, 0xcb, 0xf6, 0x55, + 0x2a, 0xc8, 0x89, 0x6d, 0xf5, 0xe9, 0xb9, 0xb6, 0xba, 0x77, 0x99, 0xb6, 0x4a, 0x1b, 0x9e, 0xde, + 0x55, 0x8f, 0xc1, 0xca, 0xe4, 0x80, 0xae, 0x7c, 0x39, 0x9b, 0x3f, 0xea, 0x60, 0xf1, 0xcd, 0x33, + 0x7f, 0x95, 0xb1, 0xfe, 0xad, 0x00, 0x96, 0xdf, 0x8c, 0xf4, 0xa4, 0x45, 0x27, 0x64, 0x84, 0xaa, + 0x67, 0x7c, 0x54, 0x9c, 0x7d, 0x46, 0x28, 0x92, 0x08, 0x34, 0xc1, 0x4c, 0x3b, 0x7e, 0xdd, 0xe2, + 0xf7, 0x07, 0x88, 0x04, 0xab, 0xa7, 0x4d, 0x21, 0xb0, 0x05, 0x8a, 0x44, 0xec, 0xad, 0x46, 0x71, + 0x35, 0xbf, 0x56, 0xa9, 0x7f, 0xf0, 0x6f, 0x3a, 0xc3, 0x92, 0x9b, 0xef, 0x8e, 0xc7, 0xe9, 0x49, + 0xb2, 0x4e, 0x48, 0x19, 0x8a, 0x8d, 0xc3, 0xff, 0x83, 0x7c, 0xe8, 0xb6, 0xd4, 0x6b, 0x5f, 0x51, + 0x94, 0xfc, 0xfe, 0xee, 0x36, 0x12, 0xf2, 0x15, 0xac, 0x96, 0x67, 0x69, 0x02, 0x2e, 0x80, 0xfc, + 0x11, 0x39, 0x89, 0x07, 0x0a, 0x89, 0x4f, 0xf8, 0x10, 0x14, 0xfb, 0x62, 0xaf, 0x56, 0xf9, 0x7d, + 0x67, 0x6a, 0x90, 0xc9, 0x1a, 0x8e, 0x62, 0xad, 0x07, 0xfa, 0xa6, 0x66, 0xfe, 0xae, 0x81, 0x9b, + 0x13, 0xdb, 0x4f, 0xac, 0x3b, 0xb8, 0xdb, 0xf5, 0x8f, 0x49, 0x4b, 0xba, 0x2d, 0x25, 0xeb, 0xce, + 0x56, 0x2c, 0x46, 0x43, 0x1c, 0xbe, 0x0d, 0x66, 0x28, 0xc1, 0xcc, 0xf7, 0xd4, 0x8a, 0x35, 0xea, + 0x5c, 0x24, 0xa5, 0x48, 0xa1, 0x70, 0x0b, 0xcc, 0x13, 0xe1, 0x5e, 0xc6, 0xb5, 0x43, 0xa9, 0x3f, + 0xac, 0xd4, 0xb2, 0x52, 0x98, 0xdf, 0x19, 0x87, 0xd1, 0x79, 0xbe, 0x70, 0xd5, 0x22, 0x9e, 0x4b, + 0x5a, 0x72, 0x07, 0x2b, 0x25, 0xae, 0xb6, 0xa5, 0x14, 0x29, 0xd4, 0xfc, 0x5b, 0x07, 0xc6, 0xa4, + 0xab, 0x0d, 0x1e, 0x26, 0xbb, 0x88, 0x04, 0xe5, 0x3a, 0x54, 0xa9, 0xdf, 0xbe, 0xd4, 0x80, 0x08, + 0x8d, 0xc6, 0x92, 0x72, 0x3b, 0x97, 0x96, 0xa6, 0x56, 0x17, 0xf9, 0x0b, 0x29, 0x58, 0xf0, 0xc6, + 0x77, 0xe6, 0x78, 0xa9, 0xaa, 0xd4, 0xef, 0x5c, 0x76, 0x1c, 0xa4, 0x37, 0x43, 0x79, 0x5b, 0x38, + 0x07, 0x30, 0x74, 0xc1, 0x3e, 0xac, 0x03, 0xe0, 0x7a, 0x8e, 0xdf, 0x0b, 0xba, 0x84, 0x13, 0x99, + 0xde, 0x52, 0x72, 0x0f, 0xee, 0x8e, 0x10, 0x94, 0x62, 0x65, 0xd5, 0xa5, 0x70, 0xb5, 0xba, 0x34, + 0xd6, 0x4e, 0xcf, 0xaa, 0xb9, 0x17, 0x67, 0xd5, 0xdc, 0xcb, 0xb3, 0x6a, 0xee, 0x79, 0x54, 0xd5, + 0x4e, 0xa3, 0xaa, 0xf6, 0x22, 0xaa, 0x6a, 0x2f, 0xa3, 0xaa, 0xf6, 0x67, 0x54, 0xd5, 0xbe, 0xfd, + 0xab, 0x9a, 0x7b, 0xa6, 0xf7, 0xd7, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x9f, 0x85, 0x45, 0x74, + 0x47, 0x0f, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/authorization/v1/generated.proto b/vendor/k8s.io/api/authorization/v1/generated.proto index 2cd4af0c0..f68a04e49 100644 --- a/vendor/k8s.io/api/authorization/v1/generated.proto +++ b/vendor/k8s.io/api/authorization/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.authorization.v1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/api/authorization/v1/types_swagger_doc_generated.go b/vendor/k8s.io/api/authorization/v1/types_swagger_doc_generated.go index 85503660c..8445f7116 100644 --- a/vendor/k8s.io/api/authorization/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/authorization/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_LocalSubjectAccessReview = map[string]string{ "": "LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions checking.", "spec": "Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace you made the request against. If empty, it is defaulted.", diff --git a/vendor/k8s.io/api/authorization/v1/zz_generated.deepcopy.go b/vendor/k8s.io/api/authorization/v1/zz_generated.deepcopy.go index 3df85934a..999933d74 100644 --- a/vendor/k8s.io/api/authorization/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/authorization/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/authorization/v1beta1/generated.pb.go b/vendor/k8s.io/api/authorization/v1beta1/generated.pb.go index a9a8116b3..75ee6cf91 100644 --- a/vendor/k8s.io/api/authorization/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/authorization/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -3452,78 +3452,77 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1154 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4d, 0x6f, 0x1b, 0xc5, - 0x1b, 0xf7, 0xfa, 0x25, 0xb1, 0xc7, 0xcd, 0x3f, 0xe9, 0x44, 0x69, 0xb6, 0xf9, 0x0b, 0xdb, 0x32, - 0x12, 0x0a, 0xa2, 0xdd, 0x25, 0xa1, 0x90, 0x12, 0xe8, 0x21, 0x56, 0x22, 0x14, 0xa9, 0x2d, 0xd5, - 0x44, 0xc9, 0x81, 0x4a, 0xc0, 0x78, 0x3d, 0xb1, 0x17, 0xdb, 0xbb, 0xcb, 0xcc, 0xac, 0x43, 0x10, - 0x87, 0x1e, 0x39, 0x72, 0xe4, 0xc8, 0x89, 0xef, 0xc0, 0x05, 0x09, 0x4e, 0x39, 0xf6, 0x18, 0x24, - 0x64, 0x91, 0xe5, 0x43, 0x70, 0x45, 0x33, 0x3b, 0xf6, 0xae, 0xe3, 0x75, 0x1c, 0xe7, 0x40, 0x2f, - 0xbd, 0xed, 0x3c, 0xbf, 0xe7, 0x6d, 0x9e, 0x97, 0xd9, 0x1f, 0xd8, 0x6f, 0x3f, 0x64, 0x86, 0xed, - 0x9a, 0x6d, 0xbf, 0x4e, 0xa8, 0x43, 0x38, 0x61, 0x66, 0x8f, 0x38, 0x0d, 0x97, 0x9a, 0x0a, 0xc0, - 0x9e, 0x6d, 0x62, 0x9f, 0xb7, 0x5c, 0x6a, 0x7f, 0x8b, 0xb9, 0xed, 0x3a, 0x66, 0x6f, 0xa3, 0x4e, - 0x38, 0xde, 0x30, 0x9b, 0xc4, 0x21, 0x14, 0x73, 0xd2, 0x30, 0x3c, 0xea, 0x72, 0x17, 0x56, 0x42, - 0x0b, 0x03, 0x7b, 0xb6, 0x31, 0x62, 0x61, 0x28, 0x8b, 0xb5, 0xfb, 0x4d, 0x9b, 0xb7, 0xfc, 0xba, - 0x61, 0xb9, 0x5d, 0xb3, 0xe9, 0x36, 0x5d, 0x53, 0x1a, 0xd6, 0xfd, 0x63, 0x79, 0x92, 0x07, 0xf9, - 0x15, 0x3a, 0x5c, 0x7b, 0x10, 0xa5, 0xd0, 0xc5, 0x56, 0xcb, 0x76, 0x08, 0x3d, 0x35, 0xbd, 0x76, - 0x53, 0x08, 0x98, 0xd9, 0x25, 0x1c, 0x9b, 0xbd, 0xb1, 0x34, 0xd6, 0xcc, 0x49, 0x56, 0xd4, 0x77, - 0xb8, 0xdd, 0x25, 0x63, 0x06, 0x1f, 0x4c, 0x33, 0x60, 0x56, 0x8b, 0x74, 0xf1, 0x98, 0xdd, 0x7b, - 0x93, 0xec, 0x7c, 0x6e, 0x77, 0x4c, 0xdb, 0xe1, 0x8c, 0xd3, 0xcb, 0x46, 0xd5, 0x2d, 0x00, 0xf6, - 0xbe, 0xe1, 0x14, 0x1f, 0xe1, 0x8e, 0x4f, 0x60, 0x19, 0xe4, 0x6c, 0x4e, 0xba, 0x4c, 0xd7, 0x2a, - 0x99, 0xf5, 0x42, 0xad, 0x10, 0xf4, 0xcb, 0xb9, 0x7d, 0x21, 0x40, 0xa1, 0x7c, 0x3b, 0xff, 0xe3, - 0x4f, 0xe5, 0xd4, 0x8b, 0x3f, 0x2b, 0xa9, 0xea, 0xaf, 0x69, 0xa0, 0x3f, 0x76, 0x2d, 0xdc, 0x39, - 0xf0, 0xeb, 0x5f, 0x11, 0x8b, 0xef, 0x58, 0x16, 0x61, 0x0c, 0x91, 0x9e, 0x4d, 0x4e, 0xe0, 0x97, - 0x20, 0x2f, 0xca, 0xd1, 0xc0, 0x1c, 0xeb, 0x5a, 0x45, 0x5b, 0x2f, 0x6e, 0xbe, 0x6b, 0x44, 0xdd, - 0x18, 0x66, 0x67, 0x78, 0xed, 0xa6, 0x10, 0x30, 0x43, 0x68, 0x1b, 0xbd, 0x0d, 0xe3, 0x53, 0xe9, - 0xeb, 0x09, 0xe1, 0xb8, 0x06, 0xcf, 0xfa, 0xe5, 0x54, 0xd0, 0x2f, 0x83, 0x48, 0x86, 0x86, 0x5e, - 0xe1, 0x73, 0x90, 0x65, 0x1e, 0xb1, 0xf4, 0xb4, 0xf4, 0xfe, 0xa1, 0x31, 0xad, 0xd7, 0x46, 0x42, - 0x9a, 0x07, 0x1e, 0xb1, 0x6a, 0xb7, 0x54, 0x98, 0xac, 0x38, 0x21, 0xe9, 0x14, 0x5a, 0x60, 0x8e, - 0x71, 0xcc, 0x7d, 0xa6, 0x67, 0xa4, 0xfb, 0x8f, 0x6e, 0xe6, 0x5e, 0xba, 0xa8, 0xfd, 0x4f, 0x05, - 0x98, 0x0b, 0xcf, 0x48, 0xb9, 0xae, 0x3e, 0x07, 0x2b, 0x4f, 0x5d, 0x07, 0x11, 0xe6, 0xfa, 0xd4, - 0x22, 0x3b, 0x9c, 0x53, 0xbb, 0xee, 0x73, 0xc2, 0x60, 0x05, 0x64, 0x3d, 0xcc, 0x5b, 0xb2, 0x70, - 0x85, 0x28, 0xbf, 0x67, 0x98, 0xb7, 0x90, 0x44, 0x84, 0x46, 0x8f, 0xd0, 0xba, 0xbc, 0x7c, 0x4c, - 0xe3, 0x88, 0xd0, 0x3a, 0x92, 0x48, 0xf5, 0x6b, 0xb0, 0x18, 0x73, 0x8e, 0xfc, 0x8e, 0xec, 0xad, - 0x80, 0x46, 0x7a, 0x2b, 0x2c, 0x18, 0x0a, 0xe5, 0xf0, 0x11, 0x58, 0x74, 0x22, 0x9b, 0x43, 0xf4, - 0x98, 0xe9, 0x69, 0xa9, 0xba, 0x1c, 0xf4, 0xcb, 0x71, 0x77, 0x02, 0x42, 0x97, 0x75, 0xc5, 0x40, - 0xc0, 0x84, 0xdb, 0x98, 0xa0, 0xe0, 0xe0, 0x2e, 0x61, 0x1e, 0xb6, 0x88, 0xba, 0xd2, 0x6d, 0x95, - 0x70, 0xe1, 0xe9, 0x00, 0x40, 0x91, 0xce, 0xf4, 0xcb, 0xc1, 0x37, 0x41, 0xae, 0x49, 0x5d, 0xdf, - 0x93, 0xdd, 0x29, 0xd4, 0x16, 0x94, 0x4a, 0xee, 0x13, 0x21, 0x44, 0x21, 0x06, 0xdf, 0x06, 0xf3, - 0x3d, 0x42, 0x99, 0xed, 0x3a, 0x7a, 0x56, 0xaa, 0x2d, 0x2a, 0xb5, 0xf9, 0xa3, 0x50, 0x8c, 0x06, - 0x38, 0xbc, 0x07, 0xf2, 0x54, 0x25, 0xae, 0xe7, 0xa4, 0xee, 0x92, 0xd2, 0xcd, 0x0f, 0x2b, 0x38, - 0xd4, 0x80, 0xef, 0x83, 0x22, 0xf3, 0xeb, 0x43, 0x83, 0x39, 0x69, 0xb0, 0xac, 0x0c, 0x8a, 0x07, - 0x11, 0x84, 0xe2, 0x7a, 0xe2, 0x5a, 0xe2, 0x8e, 0xfa, 0xfc, 0xe8, 0xb5, 0x44, 0x09, 0x90, 0x44, - 0xaa, 0xbf, 0x6b, 0xe0, 0xd6, 0x6c, 0x1d, 0x7b, 0x07, 0x14, 0xb0, 0x67, 0xcb, 0x6b, 0x0f, 0x7a, - 0xb5, 0x20, 0xea, 0xba, 0xf3, 0x6c, 0x3f, 0x14, 0xa2, 0x08, 0x17, 0xca, 0x83, 0x64, 0xc4, 0x5c, - 0x0f, 0x95, 0x07, 0x21, 0x19, 0x8a, 0x70, 0xb8, 0x05, 0x16, 0x06, 0x07, 0xd9, 0x24, 0x3d, 0x2b, - 0x0d, 0x6e, 0x07, 0xfd, 0xf2, 0x02, 0x8a, 0x03, 0x68, 0x54, 0xaf, 0xfa, 0x5b, 0x1a, 0xac, 0x1e, - 0x90, 0xce, 0xf1, 0xab, 0x79, 0x15, 0xbe, 0x18, 0x79, 0x15, 0x1e, 0x5d, 0x63, 0x6d, 0x93, 0x53, - 0x7d, 0xb5, 0x2f, 0xc3, 0xcf, 0x69, 0xf0, 0xff, 0x2b, 0x12, 0x83, 0xdf, 0x01, 0x48, 0xc7, 0x16, - 0x4d, 0x55, 0xf4, 0xc1, 0xf4, 0x84, 0xc6, 0x97, 0xb4, 0x76, 0x27, 0xe8, 0x97, 0x13, 0x96, 0x17, - 0x25, 0xc4, 0x81, 0xdf, 0x6b, 0x60, 0xc5, 0x49, 0x7a, 0xb8, 0x54, 0xd5, 0xb7, 0xa6, 0x67, 0x90, - 0xf8, 0xee, 0xd5, 0xee, 0x06, 0xfd, 0x72, 0xf2, 0x93, 0x88, 0x92, 0x03, 0x8a, 0x27, 0xe7, 0x4e, - 0xac, 0x50, 0x62, 0x69, 0xfe, 0xbb, 0x59, 0xfb, 0x7c, 0x64, 0xd6, 0x3e, 0x9e, 0x69, 0xd6, 0x62, - 0x99, 0x4e, 0x1c, 0xb5, 0xfa, 0xa5, 0x51, 0xdb, 0xbe, 0xf6, 0xa8, 0xc5, 0xbd, 0x5f, 0x3d, 0x69, - 0x4f, 0xc0, 0xda, 0xe4, 0xac, 0x66, 0x7e, 0xba, 0xab, 0xbf, 0xa4, 0xc1, 0xf2, 0x6b, 0x3a, 0x70, - 0xb3, 0xa5, 0x3f, 0xcf, 0x82, 0xd5, 0xd7, 0x0b, 0x7f, 0xf5, 0xc2, 0x8b, 0x9f, 0xa8, 0xcf, 0x08, - 0x55, 0x3f, 0xfe, 0x61, 0xaf, 0x0e, 0x19, 0xa1, 0x48, 0x22, 0xb0, 0x32, 0xe0, 0x06, 0xe1, 0x0f, - 0x0b, 0x88, 0x4a, 0xab, 0x7f, 0xa1, 0x22, 0x06, 0x36, 0xc8, 0x11, 0xc1, 0x78, 0xf5, 0x5c, 0x25, - 0xb3, 0x5e, 0xdc, 0xdc, 0xbd, 0xf1, 0xac, 0x18, 0x92, 0x38, 0xef, 0x39, 0x9c, 0x9e, 0x46, 0x1c, - 0x44, 0xca, 0x50, 0x18, 0x01, 0xbe, 0x01, 0x32, 0xbe, 0xdd, 0x50, 0x14, 0xa1, 0xa8, 0x54, 0x32, - 0x87, 0xfb, 0xbb, 0x48, 0xc8, 0xd7, 0x8e, 0x15, 0xf7, 0x96, 0x2e, 0xe0, 0x12, 0xc8, 0xb4, 0xc9, - 0x69, 0xb8, 0x67, 0x48, 0x7c, 0xc2, 0x1a, 0xc8, 0xf5, 0x04, 0x2d, 0x57, 0x75, 0xbe, 0x37, 0x3d, - 0xd3, 0x88, 0xca, 0xa3, 0xd0, 0x74, 0x3b, 0xfd, 0x50, 0xab, 0xfe, 0xa1, 0x81, 0xbb, 0x13, 0x07, - 0x52, 0x10, 0x25, 0xdc, 0xe9, 0xb8, 0x27, 0xa4, 0x21, 0x63, 0xe7, 0x23, 0xa2, 0xb4, 0x13, 0x8a, - 0xd1, 0x00, 0x87, 0x6f, 0x81, 0x39, 0x4a, 0x30, 0x73, 0x1d, 0x45, 0xce, 0x86, 0xb3, 0x8c, 0xa4, - 0x14, 0x29, 0x14, 0xee, 0x80, 0x45, 0x22, 0xc2, 0xcb, 0xe4, 0xf6, 0x28, 0x75, 0x07, 0x1d, 0x5b, - 0x55, 0x06, 0x8b, 0x7b, 0xa3, 0x30, 0xba, 0xac, 0x2f, 0x42, 0x35, 0x88, 0x63, 0x93, 0x86, 0x64, - 0x6f, 0xf9, 0x28, 0xd4, 0xae, 0x94, 0x22, 0x85, 0x56, 0xff, 0x49, 0x03, 0x7d, 0xd2, 0xb3, 0x07, - 0xdb, 0x11, 0x8b, 0x91, 0xa0, 0x24, 0x52, 0xc5, 0x4d, 0xe3, 0xfa, 0x2b, 0x23, 0xcc, 0x6a, 0x2b, - 0x2a, 0xf6, 0x42, 0x5c, 0x1a, 0x63, 0x3e, 0xf2, 0x08, 0x4f, 0xc0, 0x92, 0x33, 0x4a, 0xb9, 0x43, - 0x4e, 0x56, 0xdc, 0xdc, 0x98, 0x69, 0x41, 0x64, 0x48, 0x5d, 0x85, 0x5c, 0xba, 0x04, 0x30, 0x34, - 0x16, 0x04, 0x6e, 0x02, 0x60, 0x3b, 0x96, 0xdb, 0xf5, 0x3a, 0x84, 0x13, 0x59, 0xe8, 0x7c, 0xf4, - 0x5a, 0xee, 0x0f, 0x11, 0x14, 0xd3, 0x4a, 0xea, 0x50, 0x76, 0xb6, 0x0e, 0xd5, 0xee, 0x9f, 0x5d, - 0x94, 0x52, 0x2f, 0x2f, 0x4a, 0xa9, 0xf3, 0x8b, 0x52, 0xea, 0x45, 0x50, 0xd2, 0xce, 0x82, 0x92, - 0xf6, 0x32, 0x28, 0x69, 0xe7, 0x41, 0x49, 0xfb, 0x2b, 0x28, 0x69, 0x3f, 0xfc, 0x5d, 0x4a, 0x7d, - 0x36, 0xaf, 0x6e, 0xf8, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xb3, 0x5e, 0x05, 0xd9, 0x0f, - 0x00, 0x00, + // 1137 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0xcb, 0x6f, 0x1b, 0x45, + 0x18, 0xf7, 0xfa, 0x91, 0xd8, 0xe3, 0x86, 0xa4, 0x13, 0xa5, 0xd9, 0x06, 0x61, 0x5b, 0x46, 0x42, + 0x41, 0xb4, 0xbb, 0x24, 0x2a, 0xa4, 0x04, 0x7a, 0x88, 0x95, 0x08, 0x45, 0x6a, 0x4b, 0x35, 0x51, + 0x72, 0xa0, 0x12, 0x30, 0xbb, 0x9e, 0xd8, 0x8b, 0xed, 0xdd, 0x65, 0x66, 0xd6, 0x21, 0x88, 0x43, + 0x8f, 0x1c, 0x39, 0x72, 0xe4, 0xc4, 0xff, 0xc0, 0x05, 0x09, 0x4e, 0x39, 0xf6, 0x18, 0x24, 0x64, + 0x91, 0xe5, 0x8f, 0xe0, 0x8a, 0x66, 0x76, 0xec, 0x5d, 0x27, 0x9b, 0x38, 0xce, 0x81, 0x5e, 0x7a, + 0xdb, 0xf9, 0x7e, 0xdf, 0xfb, 0xb5, 0x1f, 0xd8, 0xed, 0x3c, 0x64, 0x86, 0xe3, 0x99, 0x9d, 0xc0, + 0x22, 0xd4, 0x25, 0x9c, 0x30, 0xb3, 0x4f, 0xdc, 0xa6, 0x47, 0x4d, 0x05, 0x60, 0xdf, 0x31, 0x71, + 0xc0, 0xdb, 0x1e, 0x75, 0xbe, 0xc3, 0xdc, 0xf1, 0x5c, 0xb3, 0xbf, 0x66, 0x11, 0x8e, 0xd7, 0xcc, + 0x16, 0x71, 0x09, 0xc5, 0x9c, 0x34, 0x0d, 0x9f, 0x7a, 0xdc, 0x83, 0xb5, 0x48, 0xc2, 0xc0, 0xbe, + 0x63, 0x8c, 0x49, 0x18, 0x4a, 0x62, 0xe5, 0x7e, 0xcb, 0xe1, 0xed, 0xc0, 0x32, 0x6c, 0xaf, 0x67, + 0xb6, 0xbc, 0x96, 0x67, 0x4a, 0x41, 0x2b, 0x38, 0x94, 0x2f, 0xf9, 0x90, 0x5f, 0x91, 0xc2, 0x95, + 0x07, 0xb1, 0x0b, 0x3d, 0x6c, 0xb7, 0x1d, 0x97, 0xd0, 0x63, 0xd3, 0xef, 0xb4, 0x04, 0x81, 0x99, + 0x3d, 0xc2, 0xb1, 0xd9, 0xbf, 0xe0, 0xc6, 0x8a, 0x79, 0x99, 0x14, 0x0d, 0x5c, 0xee, 0xf4, 0xc8, + 0x05, 0x81, 0x0f, 0x27, 0x09, 0x30, 0xbb, 0x4d, 0x7a, 0xf8, 0xbc, 0x5c, 0x7d, 0x03, 0x80, 0x9d, + 0x6f, 0x39, 0xc5, 0x07, 0xb8, 0x1b, 0x10, 0x58, 0x05, 0x05, 0x87, 0x93, 0x1e, 0xd3, 0xb5, 0x5a, + 0x6e, 0xb5, 0xd4, 0x28, 0x85, 0x83, 0x6a, 0x61, 0x57, 0x10, 0x50, 0x44, 0xdf, 0x2c, 0xfe, 0xf4, + 0x73, 0x35, 0xf3, 0xe2, 0xaf, 0x5a, 0xa6, 0xfe, 0x5b, 0x16, 0xe8, 0x8f, 0x3d, 0x1b, 0x77, 0xf7, + 0x02, 0xeb, 0x6b, 0x62, 0xf3, 0x2d, 0xdb, 0x26, 0x8c, 0x21, 0xd2, 0x77, 0xc8, 0x11, 0xfc, 0x0a, + 0x14, 0x45, 0x64, 0x4d, 0xcc, 0xb1, 0xae, 0xd5, 0xb4, 0xd5, 0xf2, 0xfa, 0xfb, 0x46, 0x9c, 0xd8, + 0x91, 0x83, 0x86, 0xdf, 0x69, 0x09, 0x02, 0x33, 0x04, 0xb7, 0xd1, 0x5f, 0x33, 0x3e, 0x93, 0xba, + 0x9e, 0x10, 0x8e, 0x1b, 0xf0, 0x64, 0x50, 0xcd, 0x84, 0x83, 0x2a, 0x88, 0x69, 0x68, 0xa4, 0x15, + 0x3e, 0x07, 0x79, 0xe6, 0x13, 0x5b, 0xcf, 0x4a, 0xed, 0x1f, 0x19, 0x93, 0xca, 0x66, 0xa4, 0xb8, + 0xb9, 0xe7, 0x13, 0xbb, 0x71, 0x4b, 0x99, 0xc9, 0x8b, 0x17, 0x92, 0x4a, 0xa1, 0x0d, 0x66, 0x18, + 0xc7, 0x3c, 0x60, 0x7a, 0x4e, 0xaa, 0xff, 0xf8, 0x66, 0xea, 0xa5, 0x8a, 0xc6, 0x1b, 0xca, 0xc0, + 0x4c, 0xf4, 0x46, 0x4a, 0x75, 0xfd, 0x39, 0x58, 0x7a, 0xea, 0xb9, 0x88, 0x30, 0x2f, 0xa0, 0x36, + 0xd9, 0xe2, 0x9c, 0x3a, 0x56, 0xc0, 0x09, 0x83, 0x35, 0x90, 0xf7, 0x31, 0x6f, 0xcb, 0xc4, 0x95, + 0x62, 0xff, 0x9e, 0x61, 0xde, 0x46, 0x12, 0x11, 0x1c, 0x7d, 0x42, 0x2d, 0x19, 0x7c, 0x82, 0xe3, + 0x80, 0x50, 0x0b, 0x49, 0xa4, 0xfe, 0x0d, 0x98, 0x4f, 0x28, 0x47, 0x41, 0x57, 0xd6, 0x56, 0x40, + 0x63, 0xb5, 0x15, 0x12, 0x0c, 0x45, 0x74, 0xf8, 0x08, 0xcc, 0xbb, 0xb1, 0xcc, 0x3e, 0x7a, 0xcc, + 0xf4, 0xac, 0x64, 0x5d, 0x0c, 0x07, 0xd5, 0xa4, 0x3a, 0x01, 0xa1, 0xf3, 0xbc, 0xa2, 0x21, 0x60, + 0x4a, 0x34, 0x26, 0x28, 0xb9, 0xb8, 0x47, 0x98, 0x8f, 0x6d, 0xa2, 0x42, 0xba, 0xad, 0x1c, 0x2e, + 0x3d, 0x1d, 0x02, 0x28, 0xe6, 0x99, 0x1c, 0x1c, 0x7c, 0x1b, 0x14, 0x5a, 0xd4, 0x0b, 0x7c, 0x59, + 0x9d, 0x52, 0x63, 0x4e, 0xb1, 0x14, 0x3e, 0x15, 0x44, 0x14, 0x61, 0xf0, 0x5d, 0x30, 0xdb, 0x27, + 0x94, 0x39, 0x9e, 0xab, 0xe7, 0x25, 0xdb, 0xbc, 0x62, 0x9b, 0x3d, 0x88, 0xc8, 0x68, 0x88, 0xc3, + 0x7b, 0xa0, 0x48, 0x95, 0xe3, 0x7a, 0x41, 0xf2, 0x2e, 0x28, 0xde, 0xe2, 0x28, 0x83, 0x23, 0x0e, + 0xf8, 0x01, 0x28, 0xb3, 0xc0, 0x1a, 0x09, 0xcc, 0x48, 0x81, 0x45, 0x25, 0x50, 0xde, 0x8b, 0x21, + 0x94, 0xe4, 0x13, 0x61, 0x89, 0x18, 0xf5, 0xd9, 0xf1, 0xb0, 0x44, 0x0a, 0x90, 0x44, 0xea, 0x7f, + 0x68, 0xe0, 0xd6, 0x74, 0x15, 0x7b, 0x0f, 0x94, 0xb0, 0xef, 0xc8, 0xb0, 0x87, 0xb5, 0x9a, 0x13, + 0x79, 0xdd, 0x7a, 0xb6, 0x1b, 0x11, 0x51, 0x8c, 0x0b, 0xe6, 0xa1, 0x33, 0xa2, 0xaf, 0x47, 0xcc, + 0x43, 0x93, 0x0c, 0xc5, 0x38, 0xdc, 0x00, 0x73, 0xc3, 0x87, 0x2c, 0x92, 0x9e, 0x97, 0x02, 0xb7, + 0xc3, 0x41, 0x75, 0x0e, 0x25, 0x01, 0x34, 0xce, 0x57, 0xff, 0x3d, 0x0b, 0x96, 0xf7, 0x48, 0xf7, + 0xf0, 0xd5, 0x6c, 0x85, 0x2f, 0xc7, 0xb6, 0xc2, 0xa3, 0x6b, 0x8c, 0x6d, 0xba, 0xab, 0xaf, 0x76, + 0x33, 0xfc, 0x92, 0x05, 0x6f, 0x5e, 0xe1, 0x18, 0xfc, 0x1e, 0x40, 0x7a, 0x61, 0xd0, 0x54, 0x46, + 0x1f, 0x4c, 0x76, 0xe8, 0xe2, 0x90, 0x36, 0xee, 0x84, 0x83, 0x6a, 0xca, 0xf0, 0xa2, 0x14, 0x3b, + 0xf0, 0x07, 0x0d, 0x2c, 0xb9, 0x69, 0x8b, 0x4b, 0x65, 0x7d, 0x63, 0xb2, 0x07, 0xa9, 0x7b, 0xaf, + 0x71, 0x37, 0x1c, 0x54, 0xd3, 0x57, 0x22, 0x4a, 0x37, 0x28, 0x56, 0xce, 0x9d, 0x44, 0xa2, 0xc4, + 0xd0, 0xfc, 0x7f, 0xbd, 0xf6, 0xc5, 0x58, 0xaf, 0x7d, 0x32, 0x55, 0xaf, 0x25, 0x3c, 0xbd, 0xb4, + 0xd5, 0xac, 0x73, 0xad, 0xb6, 0x79, 0xed, 0x56, 0x4b, 0x6a, 0xbf, 0xba, 0xd3, 0x9e, 0x80, 0x95, + 0xcb, 0xbd, 0x9a, 0x7a, 0x75, 0xd7, 0x7f, 0xcd, 0x82, 0xc5, 0xd7, 0xe7, 0xc0, 0xcd, 0x86, 0xfe, + 0x34, 0x0f, 0x96, 0x5f, 0x0f, 0xfc, 0xd5, 0x03, 0x2f, 0x7e, 0xa2, 0x01, 0x23, 0x54, 0xfd, 0xf8, + 0x47, 0xb5, 0xda, 0x67, 0x84, 0x22, 0x89, 0xc0, 0xda, 0xf0, 0x36, 0x88, 0x7e, 0x58, 0x40, 0x64, + 0x5a, 0xfd, 0x0b, 0xd5, 0x61, 0xe0, 0x80, 0x02, 0x11, 0x17, 0xaf, 0x5e, 0xa8, 0xe5, 0x56, 0xcb, + 0xeb, 0xdb, 0x37, 0xee, 0x15, 0x43, 0x1e, 0xce, 0x3b, 0x2e, 0xa7, 0xc7, 0xf1, 0x0d, 0x22, 0x69, + 0x28, 0xb2, 0x00, 0xdf, 0x02, 0xb9, 0xc0, 0x69, 0xaa, 0x13, 0xa1, 0xac, 0x58, 0x72, 0xfb, 0xbb, + 0xdb, 0x48, 0xd0, 0x57, 0x0e, 0xd5, 0xed, 0x2d, 0x55, 0xc0, 0x05, 0x90, 0xeb, 0x90, 0xe3, 0x68, + 0xce, 0x90, 0xf8, 0x84, 0x0d, 0x50, 0xe8, 0x8b, 0xb3, 0x5c, 0xe5, 0xf9, 0xde, 0x64, 0x4f, 0xe3, + 0x53, 0x1e, 0x45, 0xa2, 0x9b, 0xd9, 0x87, 0x5a, 0xfd, 0x4f, 0x0d, 0xdc, 0xbd, 0xb4, 0x21, 0xc5, + 0xa1, 0x84, 0xbb, 0x5d, 0xef, 0x88, 0x34, 0xa5, 0xed, 0x62, 0x7c, 0x28, 0x6d, 0x45, 0x64, 0x34, + 0xc4, 0xe1, 0x3b, 0x60, 0x86, 0x12, 0xcc, 0x3c, 0x57, 0x1d, 0x67, 0xa3, 0x5e, 0x46, 0x92, 0x8a, + 0x14, 0x0a, 0xb7, 0xc0, 0x3c, 0x11, 0xe6, 0xa5, 0x73, 0x3b, 0x94, 0x7a, 0xc3, 0x8a, 0x2d, 0x2b, + 0x81, 0xf9, 0x9d, 0x71, 0x18, 0x9d, 0xe7, 0x17, 0xa6, 0x9a, 0xc4, 0x75, 0x48, 0x53, 0x5e, 0x6f, + 0xc5, 0xd8, 0xd4, 0xb6, 0xa4, 0x22, 0x85, 0xd6, 0xff, 0xcd, 0x02, 0xfd, 0xb2, 0xb5, 0x07, 0x3b, + 0xf1, 0x15, 0x23, 0x41, 0x79, 0x48, 0x95, 0xd7, 0x8d, 0xeb, 0x8f, 0x8c, 0x10, 0x6b, 0x2c, 0x29, + 0xdb, 0x73, 0x49, 0x6a, 0xe2, 0xf2, 0x91, 0x4f, 0x78, 0x04, 0x16, 0xdc, 0xf1, 0x93, 0x3b, 0xba, + 0xc9, 0xca, 0xeb, 0x6b, 0x53, 0x0d, 0x88, 0x34, 0xa9, 0x2b, 0x93, 0x0b, 0xe7, 0x00, 0x86, 0x2e, + 0x18, 0x81, 0xeb, 0x00, 0x38, 0xae, 0xed, 0xf5, 0xfc, 0x2e, 0xe1, 0x44, 0x26, 0xba, 0x18, 0x6f, + 0xcb, 0xdd, 0x11, 0x82, 0x12, 0x5c, 0x69, 0x15, 0xca, 0x4f, 0x57, 0xa1, 0xc6, 0xfd, 0x93, 0xb3, + 0x4a, 0xe6, 0xe5, 0x59, 0x25, 0x73, 0x7a, 0x56, 0xc9, 0xbc, 0x08, 0x2b, 0xda, 0x49, 0x58, 0xd1, + 0x5e, 0x86, 0x15, 0xed, 0x34, 0xac, 0x68, 0x7f, 0x87, 0x15, 0xed, 0xc7, 0x7f, 0x2a, 0x99, 0xcf, + 0x67, 0x55, 0x84, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xc5, 0xba, 0xf8, 0x96, 0xa4, 0x0f, 0x00, + 0x00, } diff --git a/vendor/k8s.io/api/authorization/v1beta1/generated.proto b/vendor/k8s.io/api/authorization/v1beta1/generated.proto index b64c0642c..3876a3eeb 100644 --- a/vendor/k8s.io/api/authorization/v1beta1/generated.proto +++ b/vendor/k8s.io/api/authorization/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.authorization.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go index 2371b21c6..3ae6e7206 100644 --- a/vendor/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_LocalSubjectAccessReview = map[string]string{ "": "LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions checking.", "spec": "Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace you made the request against. If empty, it is defaulted.", diff --git a/vendor/k8s.io/api/authorization/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/authorization/v1beta1/zz_generated.deepcopy.go index 7c76b183b..eb14973cd 100644 --- a/vendor/k8s.io/api/authorization/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/authorization/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/autoscaling/v1/generated.pb.go b/vendor/k8s.io/api/autoscaling/v1/generated.pb.go index 9e2b235eb..8d67ef976 100644 --- a/vendor/k8s.io/api/autoscaling/v1/generated.pb.go +++ b/vendor/k8s.io/api/autoscaling/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -4323,98 +4323,97 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1485 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcb, 0x6f, 0x14, 0x47, - 0x13, 0xf7, 0x3e, 0x6c, 0xec, 0x5e, 0x63, 0xf3, 0x35, 0x08, 0x8c, 0xf9, 0xd8, 0xb1, 0xe6, 0x43, - 0x88, 0x2f, 0x09, 0x33, 0xb1, 0x21, 0x88, 0x1c, 0xbd, 0x9b, 0x10, 0x50, 0xbc, 0x60, 0xda, 0x86, - 0x90, 0x87, 0x22, 0xda, 0xb3, 0xcd, 0xba, 0xf1, 0xce, 0xcc, 0xaa, 0xa7, 0x77, 0x85, 0x91, 0x22, - 0x25, 0x87, 0x9c, 0x13, 0x45, 0x4a, 0x94, 0x63, 0xfe, 0x81, 0x9c, 0x39, 0x27, 0x52, 0x24, 0x8e, - 0x1c, 0x72, 0xe0, 0x34, 0x0a, 0x93, 0x63, 0xfe, 0x03, 0x4e, 0x51, 0x3f, 0x76, 0x76, 0x66, 0x77, - 0x67, 0xfd, 0xc0, 0x58, 0xc9, 0x6d, 0x7a, 0xaa, 0xea, 0x57, 0xdd, 0x55, 0xd5, 0xf5, 0x68, 0x50, - 0xd9, 0xba, 0x1a, 0x58, 0xd4, 0xb7, 0xb7, 0xda, 0x1b, 0x84, 0x79, 0x84, 0x93, 0xc0, 0xee, 0x10, - 0xaf, 0xee, 0x33, 0x5b, 0x13, 0x70, 0x8b, 0xda, 0xb8, 0xcd, 0xfd, 0xc0, 0xc1, 0x4d, 0xea, 0x35, - 0xec, 0xce, 0xa2, 0xdd, 0x20, 0x1e, 0x61, 0x98, 0x93, 0xba, 0xd5, 0x62, 0x3e, 0xf7, 0xe1, 0x69, - 0xc5, 0x6a, 0xe1, 0x16, 0xb5, 0x12, 0xac, 0x56, 0x67, 0x71, 0xfe, 0x62, 0x83, 0xf2, 0xcd, 0xf6, - 0x86, 0xe5, 0xf8, 0xae, 0xdd, 0xf0, 0x1b, 0xbe, 0x2d, 0x25, 0x36, 0xda, 0x0f, 0xe4, 0x4a, 0x2e, - 0xe4, 0x97, 0x42, 0x9a, 0x37, 0x13, 0x4a, 0x1d, 0x9f, 0x91, 0x21, 0xda, 0xe6, 0x2f, 0xf7, 0x78, - 0x5c, 0xec, 0x6c, 0x52, 0x8f, 0xb0, 0x6d, 0xbb, 0xb5, 0xd5, 0x90, 0x42, 0x8c, 0x04, 0x7e, 0x9b, - 0x39, 0x64, 0x4f, 0x52, 0x81, 0xed, 0x12, 0x8e, 0x87, 0xe9, 0xb2, 0xb3, 0xa4, 0x58, 0xdb, 0xe3, - 0xd4, 0x1d, 0x54, 0x73, 0x65, 0x27, 0x81, 0xc0, 0xd9, 0x24, 0x2e, 0x1e, 0x90, 0xbb, 0x94, 0x25, - 0xd7, 0xe6, 0xb4, 0x69, 0x53, 0x8f, 0x07, 0x9c, 0xf5, 0x0b, 0x99, 0xdf, 0xe7, 0xc0, 0x99, 0x2a, - 0xf3, 0x83, 0xe0, 0x2e, 0x61, 0x01, 0xf5, 0xbd, 0x5b, 0x1b, 0x0f, 0x89, 0xc3, 0x11, 0x79, 0x40, - 0x18, 0xf1, 0x1c, 0x02, 0x17, 0x40, 0x71, 0x8b, 0x7a, 0xf5, 0xb9, 0xdc, 0x42, 0xee, 0xc2, 0x54, - 0x65, 0xfa, 0x69, 0x68, 0x8c, 0x45, 0xa1, 0x51, 0xfc, 0x90, 0x7a, 0x75, 0x24, 0x29, 0x82, 0xc3, - 0xc3, 0x2e, 0x99, 0xcb, 0xa7, 0x39, 0x6e, 0x62, 0x97, 0x20, 0x49, 0x81, 0x4b, 0x00, 0xe0, 0x16, - 0xd5, 0x0a, 0xe6, 0x0a, 0x92, 0x0f, 0x6a, 0x3e, 0xb0, 0xbc, 0x7a, 0x43, 0x53, 0x50, 0x82, 0xcb, - 0xfc, 0xa1, 0x00, 0x4e, 0xbc, 0xff, 0x88, 0x13, 0xe6, 0xe1, 0x66, 0x8d, 0x70, 0x46, 0x9d, 0x35, - 0xe9, 0x14, 0x01, 0xe6, 0xca, 0xb5, 0x50, 0xa0, 0xb7, 0x15, 0x83, 0xd5, 0x62, 0x0a, 0x4a, 0x70, - 0x41, 0x1f, 0xcc, 0xa8, 0xd5, 0x1a, 0x69, 0x12, 0x87, 0xfb, 0x4c, 0x6e, 0xb6, 0xb4, 0x74, 0xc9, - 0xea, 0x45, 0x5d, 0x6c, 0x32, 0xab, 0xb5, 0xd5, 0x10, 0x3f, 0x02, 0x4b, 0x78, 0xd4, 0xea, 0x2c, - 0x5a, 0x2b, 0x78, 0x83, 0x34, 0xbb, 0xa2, 0x15, 0x18, 0x85, 0xc6, 0x4c, 0x2d, 0x05, 0x87, 0xfa, - 0xe0, 0x21, 0x06, 0x25, 0x8e, 0x59, 0x83, 0xf0, 0xbb, 0xb8, 0xd9, 0x26, 0xf2, 0xc8, 0xa5, 0x25, - 0x6b, 0x94, 0x36, 0xab, 0x1b, 0x75, 0xd6, 0xed, 0x36, 0xf6, 0x38, 0xe5, 0xdb, 0x95, 0xd9, 0x28, - 0x34, 0x4a, 0xeb, 0x3d, 0x18, 0x94, 0xc4, 0x84, 0x1d, 0x00, 0xd5, 0x72, 0xb9, 0x43, 0x18, 0x6e, - 0x10, 0xa5, 0xa9, 0xb8, 0x2f, 0x4d, 0x27, 0xa3, 0xd0, 0x80, 0xeb, 0x03, 0x68, 0x68, 0x88, 0x06, - 0xf3, 0xa7, 0x41, 0xc7, 0x70, 0xcc, 0xdb, 0xc1, 0xbf, 0xc3, 0x31, 0x9b, 0x60, 0xda, 0x69, 0x33, - 0x46, 0xbc, 0x57, 0xf2, 0xcc, 0x09, 0x7d, 0xac, 0xe9, 0x6a, 0x02, 0x0b, 0xa5, 0x90, 0xe1, 0x36, - 0x38, 0xae, 0xd7, 0x07, 0xe0, 0xa0, 0x53, 0x51, 0x68, 0x1c, 0xaf, 0x0e, 0xc2, 0xa1, 0x61, 0x3a, - 0xcc, 0x27, 0x79, 0x70, 0xea, 0xba, 0xcf, 0xe8, 0x63, 0xdf, 0xe3, 0xb8, 0xb9, 0xea, 0xd7, 0x97, - 0x75, 0x42, 0x25, 0x0c, 0xde, 0x07, 0x93, 0xc2, 0x7a, 0x75, 0xcc, 0xb1, 0xf4, 0x51, 0x69, 0xe9, - 0xed, 0xdd, 0xd9, 0x5a, 0x25, 0x86, 0x1a, 0xe1, 0xb8, 0xe7, 0xd5, 0xde, 0x3f, 0x14, 0xa3, 0xc2, - 0x7b, 0xa0, 0x18, 0xb4, 0x88, 0xa3, 0x3d, 0x79, 0xc5, 0xca, 0x4c, 0xec, 0x56, 0xc6, 0x1e, 0xd7, - 0x5a, 0xc4, 0xe9, 0xe5, 0x11, 0xb1, 0x42, 0x12, 0x11, 0xde, 0x07, 0x13, 0x81, 0x8c, 0x35, 0xed, - 0xb6, 0xab, 0xfb, 0xc0, 0x96, 0xf2, 0x95, 0x19, 0x8d, 0x3e, 0xa1, 0xd6, 0x48, 0xe3, 0x9a, 0x5f, - 0x17, 0xc0, 0x42, 0x86, 0x64, 0xd5, 0xf7, 0xea, 0x94, 0x53, 0xdf, 0x83, 0xd7, 0x41, 0x91, 0x6f, - 0xb7, 0xba, 0x21, 0x7e, 0xb9, 0xbb, 0xd1, 0xf5, 0xed, 0x16, 0x79, 0x19, 0x1a, 0xe7, 0x76, 0x92, - 0x17, 0x7c, 0x48, 0x22, 0xc0, 0x95, 0xf8, 0x40, 0xf9, 0x14, 0x96, 0xde, 0xd6, 0xcb, 0xd0, 0x18, - 0x52, 0xcc, 0xac, 0x18, 0x29, 0xbd, 0x79, 0x91, 0x11, 0x9a, 0x38, 0xe0, 0xeb, 0x0c, 0x7b, 0x81, - 0xd2, 0x44, 0xdd, 0x6e, 0x84, 0xbf, 0xb1, 0x3b, 0x27, 0x0b, 0x89, 0xca, 0xbc, 0xde, 0x05, 0x5c, - 0x19, 0x40, 0x43, 0x43, 0x34, 0xc0, 0xf3, 0x60, 0x82, 0x11, 0x1c, 0xf8, 0x9e, 0x0c, 0xee, 0xa9, - 0x9e, 0x71, 0x91, 0xfc, 0x8b, 0x34, 0x15, 0xfe, 0x1f, 0x1c, 0x71, 0x49, 0x10, 0xe0, 0x06, 0x99, - 0x1b, 0x97, 0x8c, 0xb3, 0x9a, 0xf1, 0x48, 0x4d, 0xfd, 0x46, 0x5d, 0xba, 0xf9, 0x7b, 0x0e, 0x9c, - 0xc9, 0xb0, 0xe3, 0x0a, 0x0d, 0x38, 0xfc, 0x6c, 0x20, 0x8a, 0xad, 0x5d, 0x66, 0x0c, 0x1a, 0xa8, - 0x18, 0x3e, 0xa6, 0x75, 0x4f, 0x76, 0xff, 0x24, 0x22, 0xf8, 0x23, 0x30, 0x4e, 0x39, 0x71, 0x85, - 0x57, 0x0a, 0x17, 0x4a, 0x4b, 0x4b, 0x7b, 0x0f, 0xb3, 0xca, 0x51, 0x0d, 0x3f, 0x7e, 0x43, 0x00, - 0x21, 0x85, 0x67, 0xfe, 0x95, 0xcf, 0x3c, 0x96, 0x08, 0x73, 0xd8, 0x01, 0x33, 0x72, 0xa5, 0x52, - 0x31, 0x22, 0x0f, 0xf4, 0xe1, 0x46, 0x5d, 0xa2, 0x11, 0xc5, 0xbb, 0x72, 0x52, 0xef, 0x62, 0x66, - 0x2d, 0x85, 0x8a, 0xfa, 0xb4, 0xc0, 0x45, 0x50, 0x72, 0xa9, 0x87, 0x48, 0xab, 0x49, 0x1d, 0xac, - 0x82, 0x71, 0x5c, 0x95, 0x9f, 0x5a, 0xef, 0x37, 0x4a, 0xf2, 0xc0, 0x77, 0x40, 0xc9, 0xc5, 0x8f, - 0x62, 0x91, 0x82, 0x14, 0x39, 0xae, 0xf5, 0x95, 0x6a, 0x3d, 0x12, 0x4a, 0xf2, 0xc1, 0x87, 0xa0, - 0xac, 0x6a, 0x4a, 0x75, 0xf5, 0xce, 0x1d, 0x4e, 0x9b, 0xf4, 0x31, 0x16, 0x71, 0xb4, 0x4a, 0x98, - 0x43, 0x3c, 0x2e, 0x42, 0xa3, 0x28, 0x91, 0xcc, 0x28, 0x34, 0xca, 0xeb, 0x23, 0x39, 0xd1, 0x0e, - 0x48, 0xe6, 0x2f, 0x05, 0x70, 0x76, 0x64, 0x1a, 0x80, 0xd7, 0x00, 0xf4, 0x37, 0x02, 0xc2, 0x3a, - 0xa4, 0xfe, 0x81, 0xea, 0x8b, 0x44, 0x83, 0x22, 0x6c, 0x5e, 0x50, 0x35, 0xf1, 0xd6, 0x00, 0x15, - 0x0d, 0x91, 0x80, 0x0e, 0x38, 0x2a, 0xee, 0x85, 0xb2, 0x32, 0xd5, 0xbd, 0xd0, 0xde, 0x2e, 0xdd, - 0x7f, 0xa2, 0xd0, 0x38, 0xba, 0x92, 0x04, 0x41, 0x69, 0x4c, 0xb8, 0x0c, 0x66, 0x75, 0xb2, 0xef, - 0xb3, 0xfa, 0x29, 0x6d, 0xf5, 0xd9, 0x6a, 0x9a, 0x8c, 0xfa, 0xf9, 0x05, 0x44, 0x9d, 0x04, 0x94, - 0x91, 0x7a, 0x0c, 0x51, 0x4c, 0x43, 0xbc, 0x97, 0x26, 0xa3, 0x7e, 0x7e, 0xe8, 0x02, 0x43, 0xa3, - 0x66, 0x7a, 0x70, 0x5c, 0x42, 0xfe, 0x2f, 0x0a, 0x0d, 0xa3, 0x3a, 0x9a, 0x15, 0xed, 0x84, 0x25, - 0xda, 0x40, 0xdd, 0x3b, 0xc8, 0x0b, 0x72, 0x39, 0x95, 0x7a, 0x17, 0xfa, 0x52, 0xef, 0xb1, 0x64, - 0xa3, 0x98, 0x48, 0xb3, 0xb7, 0xc1, 0x84, 0x2f, 0x6f, 0x86, 0xf6, 0xcb, 0xc5, 0x11, 0xd7, 0x29, - 0x2e, 0x69, 0x31, 0x50, 0x05, 0x88, 0x5c, 0xa6, 0xaf, 0x96, 0x06, 0x82, 0x37, 0x40, 0xb1, 0xe5, - 0xd7, 0xbb, 0x85, 0xe8, 0xcd, 0x11, 0x80, 0xab, 0x7e, 0x3d, 0x48, 0xc1, 0x4d, 0x8a, 0x1d, 0x8b, - 0xbf, 0x48, 0x42, 0xc0, 0x8f, 0xc1, 0x64, 0xb7, 0xe0, 0xeb, 0xee, 0xc0, 0x1e, 0x01, 0x87, 0x34, - 0x6b, 0x0a, 0x72, 0x5a, 0x24, 0xb2, 0x2e, 0x05, 0xc5, 0x70, 0x02, 0x9a, 0xe8, 0x56, 0x4d, 0x7a, - 0x65, 0x34, 0xf4, 0xb0, 0x76, 0x5b, 0x41, 0x77, 0x29, 0x28, 0x86, 0x33, 0x7f, 0x2c, 0x80, 0xe9, - 0x54, 0xfb, 0x77, 0xc8, 0xae, 0x51, 0x75, 0xfc, 0xc0, 0x5c, 0xa3, 0xe0, 0x0e, 0xd4, 0x35, 0x0a, - 0xf2, 0xb5, 0xb8, 0x26, 0x01, 0x3d, 0xc4, 0x35, 0xdf, 0xe4, 0x01, 0x1c, 0x0c, 0x63, 0xf8, 0x39, - 0x98, 0x50, 0x09, 0xf3, 0x15, 0x8b, 0x4a, 0x5c, 0xde, 0x75, 0xfd, 0xd0, 0xa8, 0x7d, 0xfd, 0x7f, - 0x7e, 0x57, 0xfd, 0x3f, 0x39, 0x88, 0x39, 0x29, 0xae, 0x3a, 0x59, 0xb3, 0x92, 0xf9, 0x5d, 0xbf, - 0x45, 0x54, 0xc8, 0xfe, 0x13, 0x2d, 0x72, 0x68, 0x03, 0x8a, 0xf9, 0x6b, 0x0e, 0x1c, 0xeb, 0x4f, - 0x4e, 0xfb, 0x1a, 0xe2, 0x1e, 0x0f, 0x9d, 0x44, 0xf3, 0xfb, 0xda, 0x78, 0xdc, 0x7b, 0xee, 0x72, - 0x1a, 0xfd, 0x2d, 0x7d, 0x88, 0xfd, 0x4f, 0xa2, 0x5f, 0x0c, 0x1f, 0xd7, 0xf6, 0x77, 0x8a, 0x33, - 0x5a, 0xd9, 0xee, 0x47, 0xb6, 0x9f, 0xf3, 0xe0, 0xc4, 0xb0, 0xd4, 0x0e, 0xab, 0xfa, 0x75, 0x45, - 0x9d, 0xc2, 0x4e, 0xbe, 0xae, 0xbc, 0x0c, 0x0d, 0x63, 0xc8, 0x78, 0xd0, 0x85, 0x49, 0x3c, 0xc0, - 0xdc, 0x03, 0x73, 0x29, 0xdb, 0x25, 0x6a, 0xad, 0x6e, 0xf6, 0xfe, 0x1b, 0x85, 0xc6, 0xdc, 0x7a, - 0x06, 0x0f, 0xca, 0x94, 0xce, 0x78, 0x85, 0x28, 0xbc, 0xf6, 0x57, 0x88, 0x27, 0x83, 0xf6, 0x52, - 0xbe, 0x3f, 0x10, 0x7b, 0x7d, 0x0a, 0x4e, 0xa7, 0x9d, 0x34, 0x68, 0xb0, 0xb3, 0x51, 0x68, 0x9c, - 0xae, 0x66, 0x31, 0xa1, 0x6c, 0xf9, 0xac, 0x48, 0x2b, 0x1c, 0x52, 0xa4, 0x7d, 0x95, 0x07, 0xe3, - 0xb2, 0xa9, 0x3c, 0x84, 0xa7, 0x80, 0x6b, 0xa9, 0xa7, 0x80, 0x73, 0x23, 0xd2, 0xab, 0xdc, 0x51, - 0xe6, 0xe0, 0x7f, 0xb3, 0x6f, 0xf0, 0x3f, 0xbf, 0x23, 0xd2, 0xe8, 0x31, 0xff, 0x5d, 0x30, 0x15, - 0x2b, 0x84, 0x6f, 0x89, 0x22, 0xaf, 0xbb, 0xe1, 0x9c, 0xf4, 0x6d, 0x3c, 0x1b, 0xc6, 0x6d, 0x70, - 0xcc, 0x61, 0x52, 0x50, 0x4a, 0x68, 0xd8, 0x9b, 0xb0, 0xe0, 0x0e, 0x92, 0x0f, 0x5d, 0x53, 0x3d, - 0xee, 0xf8, 0xc5, 0x2a, 0xe6, 0xa8, 0x5c, 0x78, 0xfa, 0xa2, 0x3c, 0xf6, 0xec, 0x45, 0x79, 0xec, - 0xf9, 0x8b, 0xf2, 0xd8, 0x97, 0x51, 0x39, 0xf7, 0x34, 0x2a, 0xe7, 0x9e, 0x45, 0xe5, 0xdc, 0xf3, - 0xa8, 0x9c, 0xfb, 0x23, 0x2a, 0xe7, 0xbe, 0xfd, 0xb3, 0x3c, 0xf6, 0x49, 0xbe, 0xb3, 0xf8, 0x77, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x61, 0x55, 0xfd, 0xeb, 0x81, 0x17, 0x00, 0x00, + // 1471 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0x4b, 0x6f, 0x14, 0xc7, + 0x13, 0xf7, 0x3e, 0x6c, 0xec, 0x5e, 0x63, 0xf3, 0x6f, 0x10, 0x18, 0xf3, 0x67, 0xc7, 0x9a, 0x20, + 0x44, 0x1e, 0xcc, 0xc6, 0x0e, 0x41, 0xe4, 0xe8, 0xdd, 0x84, 0x80, 0xe2, 0x05, 0xd3, 0x36, 0x84, + 0x3c, 0x14, 0xd1, 0x9e, 0x6d, 0xd6, 0x8d, 0x77, 0x66, 0x56, 0x3d, 0xbd, 0x2b, 0x8c, 0x14, 0x29, + 0x39, 0xe4, 0x9c, 0x28, 0x52, 0xa2, 0x1c, 0xf3, 0x05, 0x72, 0xe6, 0x9c, 0x48, 0x91, 0x38, 0x72, + 0xc8, 0x81, 0xd3, 0x28, 0x4c, 0x8e, 0xf9, 0x06, 0x9c, 0xa2, 0x7e, 0xec, 0xec, 0xcc, 0xee, 0xcc, + 0xfa, 0x81, 0xb1, 0x92, 0xdb, 0xf4, 0x54, 0xd5, 0xaf, 0xba, 0xab, 0xaa, 0xeb, 0xd1, 0xa0, 0xba, + 0x75, 0xc5, 0xb7, 0xa8, 0x57, 0xd9, 0xea, 0x6c, 0x10, 0xe6, 0x12, 0x4e, 0xfc, 0x4a, 0x97, 0xb8, + 0x0d, 0x8f, 0x55, 0x34, 0x01, 0xb7, 0x69, 0x05, 0x77, 0xb8, 0xe7, 0xdb, 0xb8, 0x45, 0xdd, 0x66, + 0xa5, 0xbb, 0x58, 0x69, 0x12, 0x97, 0x30, 0xcc, 0x49, 0xc3, 0x6a, 0x33, 0x8f, 0x7b, 0xf0, 0xb4, + 0x62, 0xb5, 0x70, 0x9b, 0x5a, 0x31, 0x56, 0xab, 0xbb, 0x38, 0x7f, 0xb1, 0x49, 0xf9, 0x66, 0x67, + 0xc3, 0xb2, 0x3d, 0xa7, 0xd2, 0xf4, 0x9a, 0x5e, 0x45, 0x4a, 0x6c, 0x74, 0xee, 0xcb, 0x95, 0x5c, + 0xc8, 0x2f, 0x85, 0x34, 0x6f, 0xc6, 0x94, 0xda, 0x1e, 0x23, 0x29, 0xda, 0xe6, 0x2f, 0xf5, 0x79, + 0x1c, 0x6c, 0x6f, 0x52, 0x97, 0xb0, 0xed, 0x4a, 0x7b, 0xab, 0x29, 0x85, 0x18, 0xf1, 0xbd, 0x0e, + 0xb3, 0xc9, 0x9e, 0xa4, 0xfc, 0x8a, 0x43, 0x38, 0x4e, 0xd3, 0x55, 0xc9, 0x92, 0x62, 0x1d, 0x97, + 0x53, 0x67, 0x58, 0xcd, 0xe5, 0x9d, 0x04, 0x7c, 0x7b, 0x93, 0x38, 0x78, 0x50, 0xce, 0xfc, 0x21, + 0x07, 0xce, 0xd4, 0x98, 0xe7, 0xfb, 0x77, 0x08, 0xf3, 0xa9, 0xe7, 0xde, 0xdc, 0x78, 0x40, 0x6c, + 0x8e, 0xc8, 0x7d, 0xc2, 0x88, 0x6b, 0x13, 0xb8, 0x00, 0x8a, 0x5b, 0xd4, 0x6d, 0xcc, 0xe5, 0x16, + 0x72, 0x17, 0xa6, 0xaa, 0xd3, 0x4f, 0x02, 0x63, 0x2c, 0x0c, 0x8c, 0xe2, 0x47, 0xd4, 0x6d, 0x20, + 0x49, 0x11, 0x1c, 0x2e, 0x76, 0xc8, 0x5c, 0x3e, 0xc9, 0x71, 0x03, 0x3b, 0x04, 0x49, 0x0a, 0x5c, + 0x02, 0x00, 0xb7, 0xa9, 0x56, 0x30, 0x57, 0x90, 0x7c, 0x50, 0xf3, 0x81, 0xe5, 0xd5, 0xeb, 0x9a, + 0x82, 0x62, 0x5c, 0xe6, 0x8f, 0x05, 0x70, 0xe2, 0x83, 0x87, 0x9c, 0x30, 0x17, 0xb7, 0xea, 0x84, + 0x33, 0x6a, 0xaf, 0x49, 0xfb, 0x0a, 0x30, 0x47, 0xae, 0x85, 0x02, 0xbd, 0xad, 0x08, 0xac, 0x1e, + 0x51, 0x50, 0x8c, 0x0b, 0x7a, 0x60, 0x46, 0xad, 0xd6, 0x48, 0x8b, 0xd8, 0xdc, 0x63, 0x72, 0xb3, + 0xa5, 0xa5, 0x77, 0xac, 0x7e, 0x00, 0x45, 0x56, 0xb3, 0xda, 0x5b, 0x4d, 0xf1, 0xc3, 0xb7, 0x84, + 0x73, 0xac, 0xee, 0xa2, 0xb5, 0x82, 0x37, 0x48, 0xab, 0x27, 0x5a, 0x85, 0x61, 0x60, 0xcc, 0xd4, + 0x13, 0x70, 0x68, 0x00, 0x1e, 0x62, 0x50, 0xe2, 0x98, 0x35, 0x09, 0xbf, 0x83, 0x5b, 0x1d, 0x22, + 0x8f, 0x5c, 0x5a, 0xb2, 0x46, 0x69, 0xb3, 0x7a, 0x01, 0x64, 0xdd, 0xea, 0x60, 0x97, 0x53, 0xbe, + 0x5d, 0x9d, 0x0d, 0x03, 0xa3, 0xb4, 0xde, 0x87, 0x41, 0x71, 0x4c, 0xd8, 0x05, 0x50, 0x2d, 0x97, + 0xbb, 0x84, 0xe1, 0x26, 0x51, 0x9a, 0x8a, 0xfb, 0xd2, 0x74, 0x32, 0x0c, 0x0c, 0xb8, 0x3e, 0x84, + 0x86, 0x52, 0x34, 0x98, 0x3f, 0x0f, 0x3b, 0x86, 0x63, 0xde, 0xf1, 0xff, 0x1b, 0x8e, 0xd9, 0x04, + 0xd3, 0x76, 0x87, 0x31, 0xe2, 0xbe, 0x94, 0x67, 0x4e, 0xe8, 0x63, 0x4d, 0xd7, 0x62, 0x58, 0x28, + 0x81, 0x0c, 0xb7, 0xc1, 0x71, 0xbd, 0x3e, 0x00, 0x07, 0x9d, 0x0a, 0x03, 0xe3, 0x78, 0x6d, 0x18, + 0x0e, 0xa5, 0xe9, 0x30, 0x1f, 0xe7, 0xc1, 0xa9, 0x6b, 0x1e, 0xa3, 0x8f, 0x3c, 0x97, 0xe3, 0xd6, + 0xaa, 0xd7, 0x58, 0xd6, 0xb9, 0x91, 0x30, 0x78, 0x0f, 0x4c, 0x0a, 0xeb, 0x35, 0x30, 0xc7, 0xd2, + 0x47, 0xa5, 0xa5, 0xb7, 0x77, 0x67, 0x6b, 0x95, 0x18, 0xea, 0x84, 0xe3, 0xbe, 0x57, 0xfb, 0xff, + 0x50, 0x84, 0x0a, 0xef, 0x82, 0xa2, 0xdf, 0x26, 0xb6, 0xf6, 0xe4, 0x65, 0x2b, 0x33, 0x47, 0x5b, + 0x19, 0x7b, 0x5c, 0x6b, 0x13, 0xbb, 0x9f, 0x47, 0xc4, 0x0a, 0x49, 0x44, 0x78, 0x0f, 0x4c, 0xf8, + 0x32, 0xd6, 0xb4, 0xdb, 0xae, 0xec, 0x03, 0x5b, 0xca, 0x57, 0x67, 0x34, 0xfa, 0x84, 0x5a, 0x23, + 0x8d, 0x6b, 0x7e, 0x53, 0x00, 0x0b, 0x19, 0x92, 0x35, 0xcf, 0x6d, 0x50, 0x4e, 0x3d, 0x17, 0x5e, + 0x03, 0x45, 0xbe, 0xdd, 0xee, 0x85, 0xf8, 0xa5, 0xde, 0x46, 0xd7, 0xb7, 0xdb, 0xe4, 0x45, 0x60, + 0x9c, 0xdb, 0x49, 0x5e, 0xf0, 0x21, 0x89, 0x00, 0x57, 0xa2, 0x03, 0xe5, 0x13, 0x58, 0x7a, 0x5b, + 0x2f, 0x02, 0x23, 0xa5, 0x2e, 0x59, 0x11, 0x52, 0x72, 0xf3, 0x22, 0x23, 0xb4, 0xb0, 0xcf, 0xd7, + 0x19, 0x76, 0x7d, 0xa5, 0x89, 0x3a, 0xbd, 0x08, 0x7f, 0x63, 0x77, 0x4e, 0x16, 0x12, 0xd5, 0x79, + 0xbd, 0x0b, 0xb8, 0x32, 0x84, 0x86, 0x52, 0x34, 0xc0, 0xf3, 0x60, 0x82, 0x11, 0xec, 0x7b, 0xae, + 0x0c, 0xee, 0xa9, 0xbe, 0x71, 0x91, 0xfc, 0x8b, 0x34, 0x15, 0xbe, 0x0e, 0x8e, 0x38, 0xc4, 0xf7, + 0x71, 0x93, 0xcc, 0x8d, 0x4b, 0xc6, 0x59, 0xcd, 0x78, 0xa4, 0xae, 0x7e, 0xa3, 0x1e, 0xdd, 0xfc, + 0x23, 0x07, 0xce, 0x64, 0xd8, 0x71, 0x85, 0xfa, 0x1c, 0x7e, 0x3e, 0x14, 0xc5, 0xd6, 0x2e, 0x33, + 0x06, 0xf5, 0x55, 0x0c, 0x1f, 0xd3, 0xba, 0x27, 0x7b, 0x7f, 0x62, 0x11, 0xfc, 0x31, 0x18, 0xa7, + 0x9c, 0x38, 0xc2, 0x2b, 0x85, 0x0b, 0xa5, 0xa5, 0xa5, 0xbd, 0x87, 0x59, 0xf5, 0xa8, 0x86, 0x1f, + 0xbf, 0x2e, 0x80, 0x90, 0xc2, 0x33, 0xff, 0xce, 0x67, 0x1e, 0x4b, 0x84, 0x39, 0xec, 0x82, 0x19, + 0xb9, 0x52, 0xa9, 0x18, 0x91, 0xfb, 0xfa, 0x70, 0xa3, 0x2e, 0xd1, 0x88, 0xe2, 0x5d, 0x3d, 0xa9, + 0x77, 0x31, 0xb3, 0x96, 0x40, 0x45, 0x03, 0x5a, 0xe0, 0x22, 0x28, 0x39, 0xd4, 0x45, 0xa4, 0xdd, + 0xa2, 0x36, 0x56, 0xc1, 0x38, 0xae, 0xca, 0x4f, 0xbd, 0xff, 0x1b, 0xc5, 0x79, 0xe0, 0xbb, 0xa0, + 0xe4, 0xe0, 0x87, 0x91, 0x48, 0x41, 0x8a, 0x1c, 0xd7, 0xfa, 0x4a, 0xf5, 0x3e, 0x09, 0xc5, 0xf9, + 0xe0, 0x03, 0x50, 0x56, 0x35, 0xa5, 0xb6, 0x7a, 0xfb, 0x36, 0xa7, 0x2d, 0xfa, 0x08, 0x8b, 0x38, + 0x5a, 0x25, 0xcc, 0x26, 0x2e, 0x17, 0xa1, 0x51, 0x94, 0x48, 0x66, 0x18, 0x18, 0xe5, 0xf5, 0x91, + 0x9c, 0x68, 0x07, 0x24, 0xf3, 0xd7, 0x02, 0x38, 0x3b, 0x32, 0x0d, 0xc0, 0xab, 0x00, 0x7a, 0x1b, + 0x3e, 0x61, 0x5d, 0xd2, 0xf8, 0x50, 0xf5, 0x45, 0xa2, 0x41, 0x11, 0x36, 0x2f, 0xa8, 0x9a, 0x78, + 0x73, 0x88, 0x8a, 0x52, 0x24, 0xa0, 0x0d, 0x8e, 0x8a, 0x7b, 0xa1, 0xac, 0x4c, 0x75, 0x2f, 0xb4, + 0xb7, 0x4b, 0xf7, 0xbf, 0x30, 0x30, 0x8e, 0xae, 0xc4, 0x41, 0x50, 0x12, 0x13, 0x2e, 0x83, 0x59, + 0x9d, 0xec, 0x07, 0xac, 0x7e, 0x4a, 0x5b, 0x7d, 0xb6, 0x96, 0x24, 0xa3, 0x41, 0x7e, 0x01, 0xd1, + 0x20, 0x3e, 0x65, 0xa4, 0x11, 0x41, 0x14, 0x93, 0x10, 0xef, 0x27, 0xc9, 0x68, 0x90, 0x1f, 0x3a, + 0xc0, 0xd0, 0xa8, 0x99, 0x1e, 0x1c, 0x97, 0x90, 0xaf, 0x85, 0x81, 0x61, 0xd4, 0x46, 0xb3, 0xa2, + 0x9d, 0xb0, 0x44, 0x1b, 0xa8, 0x7b, 0x07, 0x79, 0x41, 0x2e, 0x25, 0x52, 0xef, 0xc2, 0x40, 0xea, + 0x3d, 0x16, 0x6f, 0x14, 0x63, 0x69, 0xf6, 0x16, 0x98, 0xf0, 0xe4, 0xcd, 0xd0, 0x7e, 0xb9, 0x38, + 0xe2, 0x3a, 0x45, 0x25, 0x2d, 0x02, 0xaa, 0x02, 0x91, 0xcb, 0xf4, 0xd5, 0xd2, 0x40, 0xf0, 0x3a, + 0x28, 0xb6, 0xbd, 0x46, 0xaf, 0x10, 0xbd, 0x39, 0x02, 0x70, 0xd5, 0x6b, 0xf8, 0x09, 0xb8, 0x49, + 0xb1, 0x63, 0xf1, 0x17, 0x49, 0x08, 0xf8, 0x09, 0x98, 0xec, 0x15, 0x7c, 0xdd, 0x1d, 0x54, 0x46, + 0xc0, 0x21, 0xcd, 0x9a, 0x80, 0x9c, 0x16, 0x89, 0xac, 0x47, 0x41, 0x11, 0x9c, 0x80, 0x26, 0xba, + 0x55, 0x93, 0x5e, 0x19, 0x0d, 0x9d, 0xd6, 0x6e, 0x2b, 0xe8, 0x1e, 0x05, 0x45, 0x70, 0xe6, 0x4f, + 0x05, 0x30, 0x9d, 0x68, 0xff, 0x0e, 0xd9, 0x35, 0xaa, 0x8e, 0x1f, 0x98, 0x6b, 0x14, 0xdc, 0x81, + 0xba, 0x46, 0x41, 0xbe, 0x12, 0xd7, 0xc4, 0xa0, 0x53, 0x5c, 0xf3, 0x6d, 0x1e, 0xc0, 0xe1, 0x30, + 0x86, 0x5f, 0x80, 0x09, 0x95, 0x30, 0x5f, 0xb2, 0xa8, 0x44, 0xe5, 0x5d, 0xd7, 0x0f, 0x8d, 0x3a, + 0xd0, 0xff, 0xe7, 0x77, 0xd5, 0xff, 0x93, 0x83, 0x98, 0x93, 0xa2, 0xaa, 0x93, 0x35, 0x2b, 0x99, + 0xdf, 0x0f, 0x5a, 0x44, 0x85, 0xec, 0xbf, 0xd1, 0x22, 0x87, 0x36, 0xa0, 0x98, 0xbf, 0xe5, 0xc0, + 0xb1, 0xc1, 0xe4, 0xb4, 0xaf, 0x21, 0xee, 0x51, 0xea, 0x24, 0x9a, 0xdf, 0xd7, 0xc6, 0xa3, 0xde, + 0x73, 0x97, 0xd3, 0xe8, 0xef, 0xc9, 0x43, 0xec, 0x7f, 0x12, 0xfd, 0x32, 0x7d, 0x5c, 0xdb, 0xdf, + 0x29, 0xce, 0x68, 0x65, 0xbb, 0x1f, 0xd9, 0x7e, 0xc9, 0x83, 0x13, 0x69, 0xa9, 0x1d, 0xd6, 0xf4, + 0xeb, 0x8a, 0x3a, 0x45, 0x25, 0xfe, 0xba, 0xf2, 0x22, 0x30, 0x8c, 0x94, 0xf1, 0xa0, 0x07, 0x13, + 0x7b, 0x80, 0xb9, 0x0b, 0xe6, 0x12, 0xb6, 0x8b, 0xd5, 0x5a, 0xdd, 0xec, 0xfd, 0x3f, 0x0c, 0x8c, + 0xb9, 0xf5, 0x0c, 0x1e, 0x94, 0x29, 0x9d, 0xf1, 0x0a, 0x51, 0x78, 0xe5, 0xaf, 0x10, 0x8f, 0x87, + 0xed, 0xa5, 0x7c, 0x7f, 0x20, 0xf6, 0xfa, 0x0c, 0x9c, 0x4e, 0x3a, 0x69, 0xd8, 0x60, 0x67, 0xc3, + 0xc0, 0x38, 0x5d, 0xcb, 0x62, 0x42, 0xd9, 0xf2, 0x59, 0x91, 0x56, 0x38, 0xa4, 0x48, 0xfb, 0x3a, + 0x0f, 0xc6, 0x65, 0x53, 0x79, 0x08, 0x4f, 0x01, 0x57, 0x13, 0x4f, 0x01, 0xe7, 0x46, 0xa4, 0x57, + 0xb9, 0xa3, 0xcc, 0xc1, 0xff, 0xc6, 0xc0, 0xe0, 0x7f, 0x7e, 0x47, 0xa4, 0xd1, 0x63, 0xfe, 0x7b, + 0x60, 0x2a, 0x52, 0x08, 0xdf, 0x12, 0x45, 0x5e, 0x77, 0xc3, 0x39, 0xe9, 0xdb, 0x68, 0x36, 0x8c, + 0xda, 0xe0, 0x88, 0xc3, 0xa4, 0xa0, 0x14, 0xd3, 0xb0, 0x37, 0x61, 0xc1, 0xed, 0xc7, 0x1f, 0xba, + 0xa6, 0xfa, 0xdc, 0xd1, 0x8b, 0x55, 0xc4, 0x51, 0xbd, 0xf0, 0xe4, 0x79, 0x79, 0xec, 0xe9, 0xf3, + 0xf2, 0xd8, 0xb3, 0xe7, 0xe5, 0xb1, 0xaf, 0xc2, 0x72, 0xee, 0x49, 0x58, 0xce, 0x3d, 0x0d, 0xcb, + 0xb9, 0x67, 0x61, 0x39, 0xf7, 0x67, 0x58, 0xce, 0x7d, 0xf7, 0x57, 0x79, 0xec, 0xd3, 0x7c, 0x77, + 0xf1, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4d, 0x5f, 0x69, 0x0c, 0x4c, 0x17, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/autoscaling/v1/generated.proto b/vendor/k8s.io/api/autoscaling/v1/generated.proto index 64f01f477..a3c542de2 100644 --- a/vendor/k8s.io/api/autoscaling/v1/generated.proto +++ b/vendor/k8s.io/api/autoscaling/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/api/autoscaling/v1/types_swagger_doc_generated.go b/vendor/k8s.io/api/autoscaling/v1/types_swagger_doc_generated.go index ec364f53e..e84909269 100644 --- a/vendor/k8s.io/api/autoscaling/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/autoscaling/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CrossVersionObjectReference = map[string]string{ "": "CrossVersionObjectReference contains enough information to let you identify the referred resource.", "kind": "Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds\"", diff --git a/vendor/k8s.io/api/autoscaling/v1/zz_generated.deepcopy.go b/vendor/k8s.io/api/autoscaling/v1/zz_generated.deepcopy.go index 011275be4..ee9ac01de 100644 --- a/vendor/k8s.io/api/autoscaling/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/autoscaling/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/autoscaling/v2beta1/generated.pb.go b/vendor/k8s.io/api/autoscaling/v2beta1/generated.pb.go index 784e4be2b..33f67913a 100644 --- a/vendor/k8s.io/api/autoscaling/v2beta1/generated.pb.go +++ b/vendor/k8s.io/api/autoscaling/v2beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -3941,96 +3941,95 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1441 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcd, 0x8f, 0x1b, 0xc5, - 0x12, 0x5f, 0x7f, 0xec, 0x66, 0xd3, 0xde, 0xec, 0xe6, 0x75, 0xa2, 0xc4, 0xd9, 0xbc, 0xd8, 0xab, - 0xd1, 0xd3, 0x53, 0x88, 0xc8, 0x4c, 0xe2, 0x2c, 0x1f, 0x12, 0x42, 0x62, 0x6d, 0x20, 0x89, 0x58, - 0x27, 0xa1, 0x77, 0x13, 0x21, 0x08, 0x88, 0xf6, 0xb8, 0xe3, 0x6d, 0xd6, 0x33, 0x63, 0x75, 0xb7, - 0xad, 0x6c, 0x10, 0x12, 0x17, 0xee, 0x1c, 0xf8, 0xb8, 0x72, 0x46, 0x70, 0x85, 0x33, 0x48, 0x48, - 0x39, 0xe6, 0x18, 0x84, 0x64, 0x91, 0xe1, 0xbf, 0xc8, 0x09, 0x4d, 0x77, 0xcf, 0x78, 0xc6, 0xf6, - 0xac, 0x1d, 0xb3, 0x09, 0x70, 0x9b, 0xee, 0xaa, 0xfa, 0x55, 0x75, 0x55, 0x75, 0x75, 0xd5, 0x80, - 0xcb, 0xbb, 0x2f, 0x73, 0x93, 0x7a, 0xd6, 0x6e, 0xb7, 0x41, 0x98, 0x4b, 0x04, 0xe1, 0x56, 0x8f, - 0xb8, 0x4d, 0x8f, 0x59, 0x9a, 0x80, 0x3b, 0xd4, 0xc2, 0x5d, 0xe1, 0x71, 0x1b, 0xb7, 0xa9, 0xdb, - 0xb2, 0x7a, 0x95, 0x06, 0x11, 0xf8, 0xa2, 0xd5, 0x22, 0x2e, 0x61, 0x58, 0x90, 0xa6, 0xd9, 0x61, - 0x9e, 0xf0, 0x60, 0x49, 0xf1, 0x9b, 0xb8, 0x43, 0xcd, 0x18, 0xbf, 0xa9, 0xf9, 0x57, 0xcf, 0xb7, - 0xa8, 0xd8, 0xe9, 0x36, 0x4c, 0xdb, 0x73, 0xac, 0x96, 0xd7, 0xf2, 0x2c, 0x29, 0xd6, 0xe8, 0xde, - 0x91, 0x2b, 0xb9, 0x90, 0x5f, 0x0a, 0x6e, 0xd5, 0x88, 0xa9, 0xb7, 0x3d, 0x46, 0xac, 0xde, 0x88, - 0xca, 0xd5, 0xf5, 0x01, 0x8f, 0x83, 0xed, 0x1d, 0xea, 0x12, 0xb6, 0x67, 0x75, 0x76, 0x5b, 0x52, - 0x88, 0x11, 0xee, 0x75, 0x99, 0x4d, 0x9e, 0x48, 0x8a, 0x5b, 0x0e, 0x11, 0x78, 0x9c, 0x2e, 0x2b, - 0x4d, 0x8a, 0x75, 0x5d, 0x41, 0x9d, 0x51, 0x35, 0x2f, 0x4e, 0x12, 0xe0, 0xf6, 0x0e, 0x71, 0xf0, - 0x88, 0xdc, 0xa5, 0x34, 0xb9, 0xae, 0xa0, 0x6d, 0x8b, 0xba, 0x82, 0x0b, 0x36, 0x2c, 0x64, 0x7c, - 0x99, 0x01, 0xa7, 0x6b, 0xcc, 0xe3, 0xfc, 0x16, 0x61, 0x9c, 0x7a, 0xee, 0xf5, 0xc6, 0x47, 0xc4, - 0x16, 0x88, 0xdc, 0x21, 0x8c, 0xb8, 0x36, 0x81, 0x6b, 0x20, 0xbf, 0x4b, 0xdd, 0x66, 0x31, 0xb3, - 0x96, 0x39, 0x7b, 0xb8, 0xba, 0x74, 0xbf, 0x5f, 0x9e, 0xf3, 0xfb, 0xe5, 0xfc, 0x5b, 0xd4, 0x6d, - 0x22, 0x49, 0x09, 0x38, 0x5c, 0xec, 0x90, 0x62, 0x36, 0xc9, 0x71, 0x0d, 0x3b, 0x04, 0x49, 0x0a, - 0xac, 0x00, 0x80, 0x3b, 0x54, 0x2b, 0x28, 0xe6, 0x24, 0x1f, 0xd4, 0x7c, 0x60, 0xe3, 0xc6, 0x55, - 0x4d, 0x41, 0x31, 0x2e, 0xe3, 0xab, 0x1c, 0x38, 0xfe, 0xc6, 0x5d, 0x41, 0x98, 0x8b, 0xdb, 0x75, - 0x22, 0x18, 0xb5, 0xb7, 0x64, 0x50, 0x02, 0x30, 0x47, 0xae, 0x03, 0x05, 0xda, 0xac, 0x08, 0xac, - 0x1e, 0x51, 0x50, 0x8c, 0x0b, 0x7a, 0x60, 0x59, 0xad, 0xb6, 0x48, 0x9b, 0xd8, 0xc2, 0x63, 0xd2, - 0xd8, 0x42, 0xe5, 0x92, 0x39, 0x48, 0xbd, 0xc8, 0x65, 0x66, 0x67, 0xb7, 0x15, 0x6c, 0x70, 0x33, - 0x88, 0xa8, 0xd9, 0xbb, 0x68, 0x6e, 0xe2, 0x06, 0x69, 0x87, 0xa2, 0x55, 0xe8, 0xf7, 0xcb, 0xcb, - 0xf5, 0x04, 0x1c, 0x1a, 0x82, 0x87, 0x18, 0x14, 0x04, 0x66, 0x2d, 0x22, 0x6e, 0xe1, 0x76, 0x97, - 0xc8, 0x23, 0x17, 0x2a, 0xe6, 0x7e, 0xda, 0xcc, 0x30, 0xeb, 0xcc, 0xb7, 0xbb, 0xd8, 0x15, 0x54, - 0xec, 0x55, 0x57, 0xfc, 0x7e, 0xb9, 0xb0, 0x3d, 0x80, 0x41, 0x71, 0x4c, 0xd8, 0x03, 0x50, 0x2d, - 0x37, 0x7a, 0x84, 0xe1, 0x16, 0x51, 0x9a, 0xf2, 0x33, 0x69, 0x3a, 0xe1, 0xf7, 0xcb, 0x70, 0x7b, - 0x04, 0x0d, 0x8d, 0xd1, 0x60, 0x7c, 0x33, 0x1a, 0x18, 0x81, 0x45, 0x97, 0xff, 0x3b, 0x02, 0xb3, - 0x03, 0x96, 0xec, 0x2e, 0x63, 0xc4, 0xfd, 0x4b, 0x91, 0x39, 0xae, 0x8f, 0xb5, 0x54, 0x8b, 0x61, - 0xa1, 0x04, 0x32, 0xdc, 0x03, 0xc7, 0xf4, 0xfa, 0x00, 0x02, 0x74, 0xd2, 0xef, 0x97, 0x8f, 0xd5, - 0x46, 0xe1, 0xd0, 0x38, 0x1d, 0xc6, 0x4f, 0x59, 0x70, 0xf2, 0x8a, 0xc7, 0xe8, 0x3d, 0xcf, 0x15, - 0xb8, 0x7d, 0xc3, 0x6b, 0x6e, 0xe8, 0xaa, 0x4a, 0x18, 0xfc, 0x10, 0x2c, 0x06, 0xde, 0x6b, 0x62, - 0x81, 0x65, 0x8c, 0x0a, 0x95, 0x0b, 0xd3, 0xf9, 0x5a, 0x15, 0x86, 0x3a, 0x11, 0x78, 0x10, 0xd5, - 0xc1, 0x1e, 0x8a, 0x50, 0xe1, 0xfb, 0x20, 0xcf, 0x3b, 0xc4, 0xd6, 0x91, 0x7c, 0xc5, 0xdc, 0xbf, - 0xba, 0x9b, 0x29, 0x86, 0x6e, 0x75, 0x88, 0x3d, 0x28, 0x26, 0xc1, 0x0a, 0x49, 0x58, 0x48, 0xc0, - 0x02, 0x97, 0x09, 0xa7, 0x63, 0xf7, 0xea, 0xac, 0x0a, 0x24, 0x48, 0x75, 0x59, 0xab, 0x58, 0x50, - 0x6b, 0xa4, 0xc1, 0x8d, 0xcf, 0x72, 0x60, 0x2d, 0x45, 0xb2, 0xe6, 0xb9, 0x4d, 0x2a, 0xa8, 0xe7, - 0xc2, 0x2b, 0x20, 0x2f, 0xf6, 0x3a, 0x61, 0xb2, 0xaf, 0x87, 0xd6, 0x6e, 0xef, 0x75, 0xc8, 0xe3, - 0x7e, 0xf9, 0x7f, 0x93, 0xe4, 0x03, 0x3e, 0x24, 0x11, 0xe0, 0x66, 0x74, 0xaa, 0x6c, 0x02, 0x4b, - 0x9b, 0xf5, 0xb8, 0x5f, 0x1e, 0xf3, 0xac, 0x99, 0x11, 0x52, 0xd2, 0xf8, 0xa0, 0x36, 0xb4, 0x31, - 0x17, 0xdb, 0x0c, 0xbb, 0x5c, 0x69, 0xa2, 0x4e, 0x98, 0xeb, 0xe7, 0xa6, 0x0b, 0x77, 0x20, 0x51, - 0x5d, 0xd5, 0x56, 0xc0, 0xcd, 0x11, 0x34, 0x34, 0x46, 0x03, 0xfc, 0x3f, 0x58, 0x60, 0x04, 0x73, - 0xcf, 0x95, 0x69, 0x7e, 0x78, 0xe0, 0x5c, 0x24, 0x77, 0x91, 0xa6, 0xc2, 0xe7, 0xc0, 0x21, 0x87, - 0x70, 0x8e, 0x5b, 0xa4, 0x38, 0x2f, 0x19, 0x57, 0x34, 0xe3, 0xa1, 0xba, 0xda, 0x46, 0x21, 0xdd, - 0xf8, 0x35, 0x03, 0x4e, 0xa7, 0xf8, 0x71, 0x93, 0x72, 0x01, 0x6f, 0x8f, 0xe4, 0xb3, 0x39, 0x65, - 0xed, 0xa0, 0x5c, 0x65, 0xf3, 0x51, 0xad, 0x7b, 0x31, 0xdc, 0x89, 0xe5, 0xf2, 0x6d, 0x30, 0x4f, - 0x05, 0x71, 0x82, 0xa8, 0xe4, 0xce, 0x16, 0x2a, 0x2f, 0xcd, 0x98, 0x6b, 0xd5, 0x23, 0x5a, 0xc7, - 0xfc, 0xd5, 0x00, 0x0d, 0x29, 0x50, 0xe3, 0xb7, 0x6c, 0xea, 0xd9, 0x82, 0x84, 0x87, 0x1f, 0x83, - 0x65, 0xb9, 0x52, 0x95, 0x19, 0x91, 0x3b, 0xfa, 0x84, 0x13, 0xef, 0xd4, 0x3e, 0x0f, 0x7a, 0xf5, - 0x84, 0x36, 0x65, 0x79, 0x2b, 0x01, 0x8d, 0x86, 0x54, 0xc1, 0x8b, 0xa0, 0xe0, 0x50, 0x17, 0x91, - 0x4e, 0x9b, 0xda, 0x58, 0xa5, 0xe5, 0xbc, 0x7a, 0x92, 0xea, 0x83, 0x6d, 0x14, 0xe7, 0x81, 0x2f, - 0x80, 0x82, 0x83, 0xef, 0x46, 0x22, 0x39, 0x29, 0x72, 0x4c, 0xeb, 0x2b, 0xd4, 0x07, 0x24, 0x14, - 0xe7, 0x83, 0x37, 0x83, 0x6c, 0x08, 0xaa, 0x34, 0x2f, 0xe6, 0xa5, 0x9b, 0xcf, 0x4d, 0x3a, 0x9f, - 0x2e, 0xf2, 0x41, 0x89, 0x88, 0x65, 0x8e, 0x84, 0x40, 0x21, 0x96, 0xf1, 0x43, 0x1e, 0x9c, 0xd9, - 0xf7, 0xee, 0xc3, 0x37, 0x01, 0xf4, 0x1a, 0x9c, 0xb0, 0x1e, 0x69, 0x5e, 0x56, 0x6d, 0x51, 0xd0, - 0x9f, 0x04, 0x3e, 0xce, 0xa9, 0x27, 0xf1, 0xfa, 0x08, 0x15, 0x8d, 0x91, 0x80, 0x36, 0x38, 0x12, - 0x5c, 0x06, 0xe5, 0x50, 0xaa, 0x5b, 0xa1, 0x27, 0xbb, 0x69, 0xff, 0xf1, 0xfb, 0xe5, 0x23, 0x9b, - 0x71, 0x10, 0x94, 0xc4, 0x84, 0x1b, 0x60, 0x45, 0xd7, 0xfa, 0x21, 0x07, 0x9f, 0xd4, 0x1e, 0x58, - 0xa9, 0x25, 0xc9, 0x68, 0x98, 0x3f, 0x80, 0x68, 0x12, 0x4e, 0x19, 0x69, 0x46, 0x10, 0xf9, 0x24, - 0xc4, 0xeb, 0x49, 0x32, 0x1a, 0xe6, 0x87, 0x6d, 0xb0, 0xac, 0x51, 0xb5, 0xbf, 0x8b, 0xf3, 0x32, - 0x64, 0xcf, 0x4f, 0x19, 0x32, 0x55, 0x74, 0xa3, 0x1c, 0xac, 0x25, 0xb0, 0xd0, 0x10, 0x36, 0x14, - 0x00, 0xd8, 0x61, 0x89, 0xe3, 0xc5, 0x05, 0xa9, 0xe9, 0xb5, 0x19, 0xef, 0x60, 0x54, 0x2b, 0x07, - 0xcf, 0x57, 0xb4, 0xc5, 0x51, 0x4c, 0x8f, 0xf1, 0x6d, 0x0e, 0x80, 0x41, 0x86, 0xc1, 0xf5, 0x44, - 0x91, 0x5f, 0x1b, 0x2a, 0xf2, 0x47, 0xe3, 0xcd, 0x69, 0xac, 0xa0, 0xdf, 0x02, 0x0b, 0x9e, 0xbc, - 0x79, 0x3a, 0x19, 0x2a, 0x93, 0xcc, 0x8e, 0xde, 0xd2, 0x08, 0xad, 0x0a, 0x82, 0xd2, 0xa9, 0xef, - 0xaf, 0x46, 0x83, 0xd7, 0x40, 0xbe, 0xe3, 0x35, 0xc3, 0xc7, 0xef, 0xc2, 0x24, 0xd4, 0x1b, 0x5e, - 0x93, 0x27, 0x30, 0x17, 0x03, 0xdb, 0x83, 0x5d, 0x24, 0x71, 0xe0, 0x07, 0x60, 0x31, 0x6c, 0x37, - 0x74, 0x6f, 0xb2, 0x3e, 0x09, 0x13, 0x69, 0xfe, 0x04, 0xee, 0x52, 0x50, 0x41, 0x43, 0x0a, 0x8a, - 0x30, 0x03, 0x7c, 0xa2, 0xbb, 0x45, 0x59, 0xeb, 0xa7, 0xc0, 0x1f, 0xd7, 0xf6, 0x2b, 0xfc, 0x90, - 0x82, 0x22, 0x4c, 0xe3, 0xbb, 0x1c, 0x58, 0x4a, 0xb4, 0xa1, 0x7f, 0x47, 0xb8, 0x54, 0x56, 0x1f, - 0x6c, 0xb8, 0x14, 0xe6, 0xc1, 0x87, 0x4b, 0xe1, 0x3e, 0xbd, 0x70, 0xc5, 0xf0, 0xc7, 0x84, 0xeb, - 0x8b, 0x2c, 0x80, 0xa3, 0x99, 0x0e, 0x6d, 0xb0, 0xa0, 0x46, 0x8d, 0x83, 0x78, 0xe1, 0xa2, 0xae, - 0x43, 0x3f, 0x66, 0x1a, 0x7a, 0x68, 0x40, 0xc9, 0x4e, 0x35, 0xa0, 0x90, 0x83, 0x18, 0xe4, 0xa2, - 0x27, 0x30, 0x6d, 0x98, 0x33, 0xbe, 0x1e, 0x76, 0x8b, 0xca, 0xe5, 0x7f, 0xac, 0x5b, 0x9e, 0xd9, - 0x18, 0x65, 0xfc, 0x9c, 0x01, 0x47, 0x87, 0x8b, 0xd8, 0x4c, 0xa3, 0xe6, 0xbd, 0xb1, 0xf3, 0x72, - 0x76, 0x26, 0xc3, 0xa3, 0xbe, 0x78, 0xca, 0x99, 0xf9, 0x97, 0xe4, 0x21, 0x66, 0x9f, 0x97, 0x3f, - 0x19, 0x3f, 0x54, 0xce, 0x76, 0x8a, 0xd3, 0x5a, 0xd9, 0xf4, 0x83, 0xe5, 0xf7, 0x59, 0x70, 0x7c, - 0x5c, 0xf5, 0x87, 0x35, 0xfd, 0x0f, 0x48, 0x9d, 0xc2, 0x8a, 0xff, 0x03, 0x7a, 0xdc, 0x2f, 0x97, - 0xc7, 0x8c, 0x2e, 0x21, 0x4c, 0xec, 0x37, 0xd1, 0x3b, 0xa0, 0x98, 0xf0, 0xdd, 0x4d, 0x41, 0xdb, - 0xf4, 0x9e, 0x6a, 0xca, 0x54, 0xfb, 0xf9, 0x5f, 0xbf, 0x5f, 0x2e, 0x6e, 0xa7, 0xf0, 0xa0, 0x54, - 0xe9, 0x94, 0x7f, 0x25, 0xb9, 0xa7, 0xfe, 0xaf, 0xe4, 0xc7, 0x51, 0x7f, 0xa9, 0xd8, 0x1f, 0x88, - 0xbf, 0xde, 0x03, 0xa7, 0x92, 0x41, 0x1a, 0x75, 0xd8, 0x19, 0xbf, 0x5f, 0x3e, 0x55, 0x4b, 0x63, - 0x42, 0xe9, 0xf2, 0x69, 0x99, 0x96, 0x7b, 0x36, 0x99, 0x56, 0x3d, 0x7f, 0xff, 0x51, 0x69, 0xee, - 0xc1, 0xa3, 0xd2, 0xdc, 0xc3, 0x47, 0xa5, 0xb9, 0x4f, 0xfd, 0x52, 0xe6, 0xbe, 0x5f, 0xca, 0x3c, - 0xf0, 0x4b, 0x99, 0x87, 0x7e, 0x29, 0xf3, 0xbb, 0x5f, 0xca, 0x7c, 0xfe, 0x47, 0x69, 0xee, 0xdd, - 0x43, 0xba, 0xee, 0xfd, 0x19, 0x00, 0x00, 0xff, 0xff, 0x91, 0x09, 0xa9, 0x38, 0x8c, 0x16, 0x00, - 0x00, + // 1426 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcb, 0x8f, 0x1b, 0x45, + 0x13, 0x5f, 0x3f, 0x76, 0xb3, 0x69, 0x6f, 0x76, 0xf3, 0x75, 0xa2, 0xc4, 0xd9, 0x7c, 0xf1, 0xac, + 0x46, 0x08, 0x85, 0x88, 0xcc, 0x24, 0x66, 0x79, 0x48, 0x08, 0x89, 0xb5, 0x81, 0x24, 0x62, 0x9d, + 0x84, 0xde, 0x4d, 0x84, 0x20, 0x20, 0xda, 0xe3, 0x8e, 0xb7, 0x59, 0xcf, 0x8c, 0x35, 0xdd, 0xb6, + 0xb2, 0x41, 0x48, 0x5c, 0xb8, 0x73, 0xe0, 0x71, 0xe5, 0x8c, 0xe0, 0x0a, 0x67, 0x90, 0x90, 0x72, + 0xcc, 0x31, 0x08, 0xc9, 0x22, 0xc3, 0x7f, 0x91, 0x13, 0xea, 0xc7, 0x8c, 0x67, 0xfc, 0x58, 0x3b, + 0x66, 0x13, 0xe0, 0x36, 0xdd, 0x55, 0xf5, 0xab, 0xea, 0xaa, 0xea, 0xea, 0xaa, 0x01, 0x97, 0x76, + 0x5f, 0x61, 0x16, 0xf5, 0xed, 0xdd, 0x4e, 0x9d, 0x04, 0x1e, 0xe1, 0x84, 0xd9, 0x5d, 0xe2, 0x35, + 0xfc, 0xc0, 0xd6, 0x04, 0xdc, 0xa6, 0x36, 0xee, 0x70, 0x9f, 0x39, 0xb8, 0x45, 0xbd, 0xa6, 0xdd, + 0x2d, 0xd7, 0x09, 0xc7, 0x17, 0xed, 0x26, 0xf1, 0x48, 0x80, 0x39, 0x69, 0x58, 0xed, 0xc0, 0xe7, + 0x3e, 0x2c, 0x29, 0x7e, 0x0b, 0xb7, 0xa9, 0x95, 0xe0, 0xb7, 0x34, 0xff, 0xea, 0xf9, 0x26, 0xe5, + 0x3b, 0x9d, 0xba, 0xe5, 0xf8, 0xae, 0xdd, 0xf4, 0x9b, 0xbe, 0x2d, 0xc5, 0xea, 0x9d, 0xdb, 0x72, + 0x25, 0x17, 0xf2, 0x4b, 0xc1, 0xad, 0x9a, 0x09, 0xf5, 0x8e, 0x1f, 0x10, 0xbb, 0x3b, 0xa4, 0x72, + 0x75, 0xbd, 0xcf, 0xe3, 0x62, 0x67, 0x87, 0x7a, 0x24, 0xd8, 0xb3, 0xdb, 0xbb, 0x4d, 0x29, 0x14, + 0x10, 0xe6, 0x77, 0x02, 0x87, 0x3c, 0x96, 0x14, 0xb3, 0x5d, 0xc2, 0xf1, 0x28, 0x5d, 0xf6, 0x38, + 0xa9, 0xa0, 0xe3, 0x71, 0xea, 0x0e, 0xab, 0x79, 0x69, 0x92, 0x00, 0x73, 0x76, 0x88, 0x8b, 0x07, + 0xe5, 0xcc, 0xaf, 0x32, 0xe0, 0x74, 0x35, 0xf0, 0x19, 0xbb, 0x49, 0x02, 0x46, 0x7d, 0xef, 0x5a, + 0xfd, 0x63, 0xe2, 0x70, 0x44, 0x6e, 0x93, 0x80, 0x78, 0x0e, 0x81, 0x6b, 0x20, 0xbf, 0x4b, 0xbd, + 0x46, 0x31, 0xb3, 0x96, 0x39, 0x7b, 0xb8, 0xb2, 0x74, 0xaf, 0x67, 0xcc, 0x85, 0x3d, 0x23, 0xff, + 0x36, 0xf5, 0x1a, 0x48, 0x52, 0x04, 0x87, 0x87, 0x5d, 0x52, 0xcc, 0xa6, 0x39, 0xae, 0x62, 0x97, + 0x20, 0x49, 0x81, 0x65, 0x00, 0x70, 0x9b, 0x6a, 0x05, 0xc5, 0x9c, 0xe4, 0x83, 0x9a, 0x0f, 0x6c, + 0x5c, 0xbf, 0xa2, 0x29, 0x28, 0xc1, 0x65, 0x7e, 0x9d, 0x03, 0xc7, 0xdf, 0xbc, 0xc3, 0x49, 0xe0, + 0xe1, 0x56, 0x8d, 0xf0, 0x80, 0x3a, 0x5b, 0xd2, 0xbf, 0x02, 0xcc, 0x95, 0x6b, 0xa1, 0x40, 0x9b, + 0x15, 0x83, 0xd5, 0x62, 0x0a, 0x4a, 0x70, 0x41, 0x1f, 0x2c, 0xab, 0xd5, 0x16, 0x69, 0x11, 0x87, + 0xfb, 0x81, 0x34, 0xb6, 0x50, 0x7e, 0xc1, 0xea, 0x67, 0x51, 0xec, 0x35, 0xab, 0xbd, 0xdb, 0x14, + 0x1b, 0xcc, 0x12, 0xc1, 0xb1, 0xba, 0x17, 0xad, 0x4d, 0x5c, 0x27, 0xad, 0x48, 0xb4, 0x02, 0xc3, + 0x9e, 0xb1, 0x5c, 0x4b, 0xc1, 0xa1, 0x01, 0x78, 0x88, 0x41, 0x81, 0xe3, 0xa0, 0x49, 0xf8, 0x4d, + 0xdc, 0xea, 0x10, 0x79, 0xe4, 0x42, 0xd9, 0xda, 0x4f, 0x9b, 0x15, 0x25, 0x90, 0xf5, 0x4e, 0x07, + 0x7b, 0x9c, 0xf2, 0xbd, 0xca, 0x4a, 0xd8, 0x33, 0x0a, 0xdb, 0x7d, 0x18, 0x94, 0xc4, 0x84, 0x5d, + 0x00, 0xd5, 0x72, 0xa3, 0x4b, 0x02, 0xdc, 0x24, 0x4a, 0x53, 0x7e, 0x26, 0x4d, 0x27, 0xc2, 0x9e, + 0x01, 0xb7, 0x87, 0xd0, 0xd0, 0x08, 0x0d, 0xe6, 0xb7, 0xc3, 0x81, 0xe1, 0x98, 0x77, 0xd8, 0x7f, + 0x23, 0x30, 0x3b, 0x60, 0xc9, 0xe9, 0x04, 0x01, 0xf1, 0xfe, 0x56, 0x64, 0x8e, 0xeb, 0x63, 0x2d, + 0x55, 0x13, 0x58, 0x28, 0x85, 0x0c, 0xf7, 0xc0, 0x31, 0xbd, 0x3e, 0x80, 0x00, 0x9d, 0x0c, 0x7b, + 0xc6, 0xb1, 0xea, 0x30, 0x1c, 0x1a, 0xa5, 0xc3, 0xfc, 0x39, 0x0b, 0x4e, 0x5e, 0xf6, 0x03, 0x7a, + 0xd7, 0xf7, 0x38, 0x6e, 0x5d, 0xf7, 0x1b, 0x1b, 0xba, 0x40, 0x92, 0x00, 0x7e, 0x04, 0x16, 0x85, + 0xf7, 0x1a, 0x98, 0x63, 0x19, 0xa3, 0x42, 0xf9, 0xc2, 0x74, 0xbe, 0x56, 0x85, 0xa1, 0x46, 0x38, + 0xee, 0x47, 0xb5, 0xbf, 0x87, 0x62, 0x54, 0xf8, 0x01, 0xc8, 0xb3, 0x36, 0x71, 0x74, 0x24, 0x5f, + 0xb5, 0xf6, 0x2f, 0xd4, 0xd6, 0x18, 0x43, 0xb7, 0xda, 0xc4, 0xe9, 0x17, 0x13, 0xb1, 0x42, 0x12, + 0x16, 0x12, 0xb0, 0xc0, 0x64, 0xc2, 0xe9, 0xd8, 0xbd, 0x36, 0xab, 0x02, 0x09, 0x52, 0x59, 0xd6, + 0x2a, 0x16, 0xd4, 0x1a, 0x69, 0x70, 0xf3, 0xf3, 0x1c, 0x58, 0x1b, 0x23, 0x59, 0xf5, 0xbd, 0x06, + 0xe5, 0xd4, 0xf7, 0xe0, 0x65, 0x90, 0xe7, 0x7b, 0xed, 0x28, 0xd9, 0xd7, 0x23, 0x6b, 0xb7, 0xf7, + 0xda, 0xe4, 0x51, 0xcf, 0x78, 0x66, 0x92, 0xbc, 0xe0, 0x43, 0x12, 0x01, 0x6e, 0xc6, 0xa7, 0xca, + 0xa6, 0xb0, 0xb4, 0x59, 0x8f, 0x7a, 0xc6, 0x88, 0x17, 0xca, 0x8a, 0x91, 0xd2, 0xc6, 0x8b, 0xda, + 0xd0, 0xc2, 0x8c, 0x6f, 0x07, 0xd8, 0x63, 0x4a, 0x13, 0x75, 0xa3, 0x5c, 0x3f, 0x37, 0x5d, 0xb8, + 0x85, 0x44, 0x65, 0x55, 0x5b, 0x01, 0x37, 0x87, 0xd0, 0xd0, 0x08, 0x0d, 0xf0, 0x59, 0xb0, 0x10, + 0x10, 0xcc, 0x7c, 0x4f, 0xa6, 0xf9, 0xe1, 0xbe, 0x73, 0x91, 0xdc, 0x45, 0x9a, 0x0a, 0x9f, 0x03, + 0x87, 0x5c, 0xc2, 0x18, 0x6e, 0x92, 0xe2, 0xbc, 0x64, 0x5c, 0xd1, 0x8c, 0x87, 0x6a, 0x6a, 0x1b, + 0x45, 0x74, 0xf3, 0xb7, 0x0c, 0x38, 0x3d, 0xc6, 0x8f, 0x9b, 0x94, 0x71, 0x78, 0x6b, 0x28, 0x9f, + 0xad, 0x29, 0x6b, 0x07, 0x65, 0x2a, 0x9b, 0x8f, 0x6a, 0xdd, 0x8b, 0xd1, 0x4e, 0x22, 0x97, 0x6f, + 0x81, 0x79, 0xca, 0x89, 0x2b, 0xa2, 0x92, 0x3b, 0x5b, 0x28, 0xbf, 0x3c, 0x63, 0xae, 0x55, 0x8e, + 0x68, 0x1d, 0xf3, 0x57, 0x04, 0x1a, 0x52, 0xa0, 0xe6, 0xef, 0xd9, 0xb1, 0x67, 0x13, 0x09, 0x0f, + 0x3f, 0x01, 0xcb, 0x72, 0xa5, 0x2a, 0x33, 0x22, 0xb7, 0xf5, 0x09, 0x27, 0xde, 0xa9, 0x7d, 0x1e, + 0xf4, 0xca, 0x09, 0x6d, 0xca, 0xf2, 0x56, 0x0a, 0x1a, 0x0d, 0xa8, 0x82, 0x17, 0x41, 0xc1, 0xa5, + 0x1e, 0x22, 0xed, 0x16, 0x75, 0xb0, 0x4a, 0xcb, 0x79, 0xf5, 0x24, 0xd5, 0xfa, 0xdb, 0x28, 0xc9, + 0x03, 0x5f, 0x04, 0x05, 0x17, 0xdf, 0x89, 0x45, 0x72, 0x52, 0xe4, 0x98, 0xd6, 0x57, 0xa8, 0xf5, + 0x49, 0x28, 0xc9, 0x07, 0x6f, 0x88, 0x6c, 0x10, 0x55, 0x9a, 0x15, 0xf3, 0xd2, 0xcd, 0xe7, 0x26, + 0x9d, 0x4f, 0x17, 0x79, 0x51, 0x22, 0x12, 0x99, 0x23, 0x21, 0x50, 0x84, 0x65, 0xfe, 0x98, 0x07, + 0x67, 0xf6, 0xbd, 0xfb, 0xf0, 0x2d, 0x00, 0xfd, 0x3a, 0x23, 0x41, 0x97, 0x34, 0x2e, 0xa9, 0xb6, + 0x48, 0xf4, 0x27, 0xc2, 0xc7, 0x39, 0xf5, 0x24, 0x5e, 0x1b, 0xa2, 0xa2, 0x11, 0x12, 0xd0, 0x01, + 0x47, 0xc4, 0x65, 0x50, 0x0e, 0xa5, 0xba, 0x15, 0x7a, 0xbc, 0x9b, 0xf6, 0xbf, 0xb0, 0x67, 0x1c, + 0xd9, 0x4c, 0x82, 0xa0, 0x34, 0x26, 0xdc, 0x00, 0x2b, 0xba, 0xd6, 0x0f, 0x38, 0xf8, 0xa4, 0xf6, + 0xc0, 0x4a, 0x35, 0x4d, 0x46, 0x83, 0xfc, 0x02, 0xa2, 0x41, 0x18, 0x0d, 0x48, 0x23, 0x86, 0xc8, + 0xa7, 0x21, 0xde, 0x48, 0x93, 0xd1, 0x20, 0x3f, 0x6c, 0x81, 0x65, 0x8d, 0xaa, 0xfd, 0x5d, 0x9c, + 0x97, 0x21, 0x7b, 0x7e, 0xca, 0x90, 0xa9, 0xa2, 0x1b, 0xe7, 0x60, 0x35, 0x85, 0x85, 0x06, 0xb0, + 0x21, 0x07, 0xc0, 0x89, 0x4a, 0x1c, 0x2b, 0x2e, 0x48, 0x4d, 0xaf, 0xcf, 0x78, 0x07, 0xe3, 0x5a, + 0xd9, 0x7f, 0xbe, 0xe2, 0x2d, 0x86, 0x12, 0x7a, 0xcc, 0xef, 0x72, 0x00, 0xf4, 0x33, 0x0c, 0xae, + 0xa7, 0x8a, 0xfc, 0xda, 0x40, 0x91, 0x3f, 0x9a, 0x6c, 0x4e, 0x13, 0x05, 0xfd, 0x26, 0x58, 0xf0, + 0xe5, 0xcd, 0xd3, 0xc9, 0x50, 0x9e, 0x64, 0x76, 0xfc, 0x96, 0xc6, 0x68, 0x15, 0x20, 0x4a, 0xa7, + 0xbe, 0xbf, 0x1a, 0x0d, 0x5e, 0x05, 0xf9, 0xb6, 0xdf, 0x88, 0x1e, 0xbf, 0x0b, 0x93, 0x50, 0xaf, + 0xfb, 0x0d, 0x96, 0xc2, 0x5c, 0x14, 0xb6, 0x8b, 0x5d, 0x24, 0x71, 0xe0, 0x87, 0x60, 0x31, 0x6a, + 0x37, 0x74, 0x6f, 0xb2, 0x3e, 0x09, 0x13, 0x69, 0xfe, 0x14, 0xee, 0x92, 0xa8, 0xa0, 0x11, 0x05, + 0xc5, 0x98, 0x02, 0x9f, 0xe8, 0x6e, 0x51, 0xd6, 0xfa, 0x29, 0xf0, 0x47, 0xb5, 0xfd, 0x0a, 0x3f, + 0xa2, 0xa0, 0x18, 0xd3, 0xfc, 0x3e, 0x07, 0x96, 0x52, 0x6d, 0xe8, 0x3f, 0x11, 0x2e, 0x95, 0xd5, + 0x07, 0x1b, 0x2e, 0x85, 0x79, 0xf0, 0xe1, 0x52, 0xb8, 0x4f, 0x2e, 0x5c, 0x09, 0xfc, 0x11, 0xe1, + 0xfa, 0x32, 0x0b, 0xe0, 0x70, 0xa6, 0x43, 0x07, 0x2c, 0xa8, 0x51, 0xe3, 0x20, 0x5e, 0xb8, 0xb8, + 0xeb, 0xd0, 0x8f, 0x99, 0x86, 0x1e, 0x18, 0x50, 0xb2, 0x53, 0x0d, 0x28, 0xe4, 0x20, 0x06, 0xb9, + 0xf8, 0x09, 0x1c, 0x37, 0xcc, 0x99, 0xdf, 0x0c, 0xba, 0x45, 0xe5, 0xf2, 0xbf, 0xd6, 0x2d, 0x4f, + 0x6d, 0x8c, 0x32, 0x7f, 0xc9, 0x80, 0xa3, 0x83, 0x45, 0x6c, 0xa6, 0x51, 0xf3, 0xee, 0xc8, 0x79, + 0x39, 0x3b, 0x93, 0xe1, 0x71, 0x5f, 0x3c, 0xe5, 0xcc, 0xfc, 0x6b, 0xfa, 0x10, 0xb3, 0xcf, 0xcb, + 0x9f, 0x8e, 0x1e, 0x2a, 0x67, 0x3b, 0xc5, 0x69, 0xad, 0x6c, 0xfa, 0xc1, 0xf2, 0x87, 0x2c, 0x38, + 0x3e, 0xaa, 0xfa, 0xc3, 0xaa, 0xfe, 0x07, 0xa4, 0x4e, 0x61, 0x27, 0xff, 0x01, 0x3d, 0xea, 0x19, + 0xc6, 0x88, 0xd1, 0x25, 0x82, 0x49, 0xfc, 0x26, 0x7a, 0x17, 0x14, 0x53, 0xbe, 0xbb, 0xc1, 0x69, + 0x8b, 0xde, 0x55, 0x4d, 0x99, 0x6a, 0x3f, 0xff, 0x1f, 0xf6, 0x8c, 0xe2, 0xf6, 0x18, 0x1e, 0x34, + 0x56, 0x7a, 0xcc, 0xbf, 0x92, 0xdc, 0x13, 0xff, 0x57, 0xf2, 0xd3, 0xb0, 0xbf, 0x54, 0xec, 0x0f, + 0xc4, 0x5f, 0xef, 0x83, 0x53, 0xe9, 0x20, 0x0d, 0x3b, 0xec, 0x4c, 0xd8, 0x33, 0x4e, 0x55, 0xc7, + 0x31, 0xa1, 0xf1, 0xf2, 0xe3, 0x32, 0x2d, 0xf7, 0x74, 0x32, 0xad, 0x72, 0xfe, 0xde, 0xc3, 0xd2, + 0xdc, 0xfd, 0x87, 0xa5, 0xb9, 0x07, 0x0f, 0x4b, 0x73, 0x9f, 0x85, 0xa5, 0xcc, 0xbd, 0xb0, 0x94, + 0xb9, 0x1f, 0x96, 0x32, 0x0f, 0xc2, 0x52, 0xe6, 0x8f, 0xb0, 0x94, 0xf9, 0xe2, 0xcf, 0xd2, 0xdc, + 0x7b, 0x87, 0x74, 0xdd, 0xfb, 0x2b, 0x00, 0x00, 0xff, 0xff, 0xe1, 0xb1, 0xdd, 0xcd, 0x57, 0x16, + 0x00, 0x00, } diff --git a/vendor/k8s.io/api/autoscaling/v2beta1/generated.proto b/vendor/k8s.io/api/autoscaling/v2beta1/generated.proto index b565920c3..5cc6063d0 100644 --- a/vendor/k8s.io/api/autoscaling/v2beta1/generated.proto +++ b/vendor/k8s.io/api/autoscaling/v2beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v2beta1"; diff --git a/vendor/k8s.io/api/autoscaling/v2beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/autoscaling/v2beta1/types_swagger_doc_generated.go index 12cfa7649..6fa9385c2 100644 --- a/vendor/k8s.io/api/autoscaling/v2beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/autoscaling/v2beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v2beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CrossVersionObjectReference = map[string]string{ "": "CrossVersionObjectReference contains enough information to let you identify the referred resource.", "kind": "Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds\"", diff --git a/vendor/k8s.io/api/autoscaling/v2beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/autoscaling/v2beta1/zz_generated.deepcopy.go index dc59dc2d3..fd46bd892 100644 --- a/vendor/k8s.io/api/autoscaling/v2beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/autoscaling/v2beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/batch/v1/generated.pb.go b/vendor/k8s.io/api/batch/v1/generated.pb.go index 8599b6733..aa5cdf89b 100644 --- a/vendor/k8s.io/api/batch/v1/generated.pb.go +++ b/vendor/k8s.io/api/batch/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1554,62 +1554,61 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 907 bytes of a gzipped FileDescriptorProto + // 893 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x41, 0x6f, 0xe3, 0x44, - 0x18, 0x8d, 0x9b, 0xa6, 0x4d, 0x26, 0x69, 0x77, 0x19, 0x54, 0x29, 0x54, 0xc8, 0x59, 0x82, 0x84, - 0x0a, 0x12, 0x36, 0xe9, 0x56, 0x08, 0x21, 0x40, 0xc2, 0x45, 0x2b, 0x51, 0xa5, 0xda, 0x32, 0x29, - 0x42, 0x42, 0x20, 0x31, 0xb6, 0xbf, 0xa4, 0x43, 0x6c, 0x8f, 0xe5, 0x99, 0x44, 0xea, 0x8d, 0x9f, - 0xc0, 0x8f, 0x40, 0xfc, 0x14, 0xd4, 0xe3, 0x1e, 0xf7, 0x14, 0x51, 0xc3, 0x9d, 0xfb, 0x9e, 0xd0, - 0x8c, 0x1d, 0xdb, 0x69, 0x13, 0xd1, 0xe5, 0x66, 0xbf, 0x79, 0xef, 0x7d, 0x33, 0xf3, 0xbd, 0xf9, - 0xd0, 0x67, 0xd3, 0x4f, 0x84, 0xc5, 0xb8, 0x3d, 0x9d, 0xb9, 0x90, 0x44, 0x20, 0x41, 0xd8, 0x73, - 0x88, 0x7c, 0x9e, 0xd8, 0xf9, 0x02, 0x8d, 0x99, 0xed, 0x52, 0xe9, 0x5d, 0xd9, 0xf3, 0x81, 0x3d, - 0x81, 0x08, 0x12, 0x2a, 0xc1, 0xb7, 0xe2, 0x84, 0x4b, 0x8e, 0xdf, 0xcc, 0x48, 0x16, 0x8d, 0x99, - 0xa5, 0x49, 0xd6, 0x7c, 0x70, 0xf8, 0xe1, 0x84, 0xc9, 0xab, 0x99, 0x6b, 0x79, 0x3c, 0xb4, 0x27, - 0x7c, 0xc2, 0x6d, 0xcd, 0x75, 0x67, 0x63, 0xfd, 0xa7, 0x7f, 0xf4, 0x57, 0xe6, 0x71, 0xd8, 0xaf, - 0x14, 0xf2, 0x78, 0x02, 0x6b, 0xea, 0x1c, 0x9e, 0x94, 0x9c, 0x90, 0x7a, 0x57, 0x2c, 0x82, 0xe4, - 0xda, 0x8e, 0xa7, 0x13, 0x05, 0x08, 0x3b, 0x04, 0x49, 0xd7, 0xa9, 0xec, 0x4d, 0xaa, 0x64, 0x16, - 0x49, 0x16, 0xc2, 0x3d, 0xc1, 0xc7, 0xff, 0x25, 0x10, 0xde, 0x15, 0x84, 0xf4, 0x9e, 0xee, 0xe9, - 0x26, 0xdd, 0x4c, 0xb2, 0xc0, 0x66, 0x91, 0x14, 0x32, 0xb9, 0x2b, 0xea, 0xff, 0x63, 0xa0, 0xfa, - 0x19, 0x77, 0xf1, 0x4f, 0xa8, 0xa9, 0x0e, 0xe0, 0x53, 0x49, 0xbb, 0xc6, 0x13, 0xe3, 0xa8, 0x7d, - 0xfc, 0x91, 0x55, 0x5e, 0x6b, 0xe1, 0x67, 0xc5, 0xd3, 0x89, 0x02, 0x84, 0xa5, 0xd8, 0xd6, 0x7c, - 0x60, 0x3d, 0x77, 0x7f, 0x06, 0x4f, 0x9e, 0x83, 0xa4, 0x0e, 0xbe, 0x59, 0xf4, 0x6a, 0xe9, 0xa2, - 0x87, 0x4a, 0x8c, 0x14, 0xae, 0xf8, 0x0b, 0xb4, 0x2d, 0x62, 0xf0, 0xba, 0x5b, 0xda, 0xfd, 0x6d, - 0x6b, 0x4d, 0xd3, 0xac, 0x33, 0xee, 0x8e, 0x62, 0xf0, 0x9c, 0x4e, 0xee, 0xb4, 0xad, 0xfe, 0x88, - 0xd6, 0xe1, 0x67, 0x68, 0x47, 0x48, 0x2a, 0x67, 0xa2, 0x5b, 0xd7, 0x0e, 0xe6, 0x46, 0x07, 0xcd, - 0x72, 0xf6, 0x73, 0x8f, 0x9d, 0xec, 0x9f, 0xe4, 0xea, 0xfe, 0x1f, 0x75, 0xd4, 0x39, 0xe3, 0xee, - 0x29, 0x8f, 0x7c, 0x26, 0x19, 0x8f, 0xf0, 0x09, 0xda, 0x96, 0xd7, 0x31, 0xe8, 0x63, 0xb7, 0x9c, - 0x27, 0xcb, 0xd2, 0x97, 0xd7, 0x31, 0xbc, 0x5a, 0xf4, 0x1e, 0x57, 0xb9, 0x0a, 0x23, 0x9a, 0x8d, - 0x87, 0xc5, 0x76, 0xb6, 0xb4, 0xee, 0x64, 0xb5, 0xdc, 0xab, 0x45, 0x6f, 0x4d, 0xa4, 0xac, 0xc2, - 0x69, 0x75, 0x53, 0x78, 0x82, 0xf6, 0x02, 0x2a, 0xe4, 0x45, 0xc2, 0x5d, 0xb8, 0x64, 0x21, 0xe4, - 0x67, 0xfc, 0xe0, 0x61, 0x3d, 0x50, 0x0a, 0xe7, 0x20, 0xdf, 0xc0, 0xde, 0xb0, 0x6a, 0x44, 0x56, - 0x7d, 0xf1, 0x1c, 0x61, 0x05, 0x5c, 0x26, 0x34, 0x12, 0xd9, 0x91, 0x54, 0xb5, 0xed, 0xd7, 0xae, - 0x76, 0x98, 0x57, 0xc3, 0xc3, 0x7b, 0x6e, 0x64, 0x4d, 0x05, 0xfc, 0x1e, 0xda, 0x49, 0x80, 0x0a, - 0x1e, 0x75, 0x1b, 0xfa, 0xba, 0x8a, 0xee, 0x10, 0x8d, 0x92, 0x7c, 0x15, 0xbf, 0x8f, 0x76, 0x43, - 0x10, 0x82, 0x4e, 0xa0, 0xbb, 0xa3, 0x89, 0x8f, 0x72, 0xe2, 0xee, 0x79, 0x06, 0x93, 0xe5, 0x7a, - 0xff, 0x77, 0x03, 0xed, 0x9e, 0x71, 0x77, 0xc8, 0x84, 0xc4, 0x3f, 0xdc, 0x8b, 0xaf, 0xf5, 0xb0, - 0xc3, 0x28, 0xb5, 0x0e, 0xef, 0xe3, 0xbc, 0x4e, 0x73, 0x89, 0x54, 0xa2, 0xfb, 0x39, 0x6a, 0x30, - 0x09, 0xa1, 0x6a, 0x75, 0xfd, 0xa8, 0x7d, 0xdc, 0xdd, 0x94, 0x3c, 0x67, 0x2f, 0x37, 0x69, 0x7c, - 0xad, 0xe8, 0x24, 0x53, 0xf5, 0xff, 0xae, 0xeb, 0x8d, 0xaa, 0x2c, 0xe3, 0x01, 0x6a, 0xc7, 0x34, - 0xa1, 0x41, 0x00, 0x01, 0x13, 0xa1, 0xde, 0x6b, 0xc3, 0x79, 0x94, 0x2e, 0x7a, 0xed, 0x8b, 0x12, - 0x26, 0x55, 0x8e, 0x92, 0x78, 0x3c, 0x8c, 0x03, 0x50, 0x97, 0x99, 0xc5, 0x2d, 0x97, 0x9c, 0x96, - 0x30, 0xa9, 0x72, 0xf0, 0x73, 0x74, 0x40, 0x3d, 0xc9, 0xe6, 0xf0, 0x15, 0x50, 0x3f, 0x60, 0x11, - 0x8c, 0xc0, 0xe3, 0x91, 0x9f, 0x3d, 0x9d, 0xba, 0xf3, 0x56, 0xba, 0xe8, 0x1d, 0x7c, 0xb9, 0x8e, - 0x40, 0xd6, 0xeb, 0xf0, 0x8f, 0xa8, 0x29, 0x20, 0x00, 0x4f, 0xf2, 0x24, 0x0f, 0xcb, 0xd3, 0x07, - 0xde, 0x2f, 0x75, 0x21, 0x18, 0xe5, 0x52, 0xa7, 0xa3, 0x2e, 0x78, 0xf9, 0x47, 0x0a, 0x4b, 0xfc, - 0x29, 0xda, 0x0f, 0x69, 0x34, 0xa3, 0x05, 0x53, 0xa7, 0xa4, 0xe9, 0xe0, 0x74, 0xd1, 0xdb, 0x3f, - 0x5f, 0x59, 0x21, 0x77, 0x98, 0xf8, 0x1b, 0xd4, 0x94, 0x10, 0xc6, 0x01, 0x95, 0x59, 0x64, 0xda, - 0xc7, 0xef, 0x56, 0xfb, 0xa3, 0x5e, 0x9e, 0xda, 0xc8, 0x05, 0xf7, 0x2f, 0x73, 0x9a, 0x1e, 0x31, - 0x45, 0xbf, 0x97, 0x28, 0x29, 0x6c, 0xf0, 0x09, 0xea, 0xb8, 0xd4, 0x9b, 0xf2, 0xf1, 0x78, 0xc8, - 0x42, 0x26, 0xbb, 0xbb, 0xfa, 0xca, 0x1f, 0xa7, 0x8b, 0x5e, 0xc7, 0xa9, 0xe0, 0x64, 0x85, 0xd5, - 0xff, 0xad, 0x8e, 0x5a, 0xc5, 0xf8, 0xc1, 0xdf, 0x22, 0xe4, 0x2d, 0x1f, 0xbb, 0xe8, 0x1a, 0x3a, - 0x38, 0xef, 0x6c, 0x0a, 0x4e, 0x31, 0x16, 0xca, 0x19, 0x5a, 0x40, 0x82, 0x54, 0x8c, 0xf0, 0x77, - 0xa8, 0x25, 0x24, 0x4d, 0xa4, 0x7e, 0xb6, 0x5b, 0xaf, 0xfd, 0x6c, 0xf7, 0xd2, 0x45, 0xaf, 0x35, - 0x5a, 0x1a, 0x90, 0xd2, 0x0b, 0x8f, 0xd1, 0x7e, 0x99, 0xa0, 0xff, 0x39, 0x82, 0x74, 0xbb, 0x4e, - 0x57, 0x5c, 0xc8, 0x1d, 0x57, 0x35, 0x08, 0xb2, 0x88, 0xe9, 0x1c, 0x35, 0xca, 0x41, 0x90, 0xe5, - 0x91, 0xe4, 0xab, 0xd8, 0x46, 0x2d, 0x31, 0xf3, 0x3c, 0x00, 0x1f, 0x7c, 0x9d, 0x86, 0x86, 0xf3, - 0x46, 0x4e, 0x6d, 0x8d, 0x96, 0x0b, 0xa4, 0xe4, 0x28, 0xe3, 0x31, 0x65, 0x01, 0xf8, 0x3a, 0x05, - 0x15, 0xe3, 0x67, 0x1a, 0x25, 0xf9, 0xaa, 0x73, 0x74, 0x73, 0x6b, 0xd6, 0x5e, 0xdc, 0x9a, 0xb5, - 0x97, 0xb7, 0x66, 0xed, 0x97, 0xd4, 0x34, 0x6e, 0x52, 0xd3, 0x78, 0x91, 0x9a, 0xc6, 0xcb, 0xd4, - 0x34, 0xfe, 0x4c, 0x4d, 0xe3, 0xd7, 0xbf, 0xcc, 0xda, 0xf7, 0x5b, 0xf3, 0xc1, 0xbf, 0x01, 0x00, - 0x00, 0xff, 0xff, 0xce, 0x80, 0xf2, 0xbe, 0x96, 0x08, 0x00, 0x00, + 0x18, 0x8d, 0x9b, 0xa6, 0x4d, 0x26, 0x69, 0xb7, 0x0c, 0xaa, 0x14, 0x2a, 0xe4, 0x2c, 0x41, 0x42, + 0x05, 0x09, 0x9b, 0x94, 0x0a, 0x21, 0x04, 0x48, 0xb8, 0x68, 0x25, 0xaa, 0x54, 0x5b, 0x26, 0x45, + 0x48, 0x08, 0x24, 0xc6, 0xf6, 0x97, 0xd4, 0xc4, 0xf6, 0x58, 0x9e, 0x49, 0xa4, 0xde, 0xf8, 0x09, + 0xfc, 0x08, 0xc4, 0x4f, 0x41, 0x3d, 0xee, 0x71, 0x4f, 0x11, 0x35, 0xdc, 0xb9, 0xef, 0x09, 0xcd, + 0x78, 0x62, 0x3b, 0x6d, 0x2a, 0xda, 0xbd, 0x79, 0xde, 0xbc, 0xf7, 0xbe, 0xf1, 0x37, 0x6f, 0x3e, + 0xf4, 0xf9, 0xf4, 0x53, 0x6e, 0x05, 0xcc, 0x9e, 0xce, 0x5c, 0x48, 0x63, 0x10, 0xc0, 0xed, 0x39, + 0xc4, 0x3e, 0x4b, 0x6d, 0xbd, 0x41, 0x93, 0xc0, 0x76, 0xa9, 0xf0, 0x2e, 0xed, 0xf9, 0xc0, 0x9e, + 0x40, 0x0c, 0x29, 0x15, 0xe0, 0x5b, 0x49, 0xca, 0x04, 0xc3, 0x6f, 0xe6, 0x24, 0x8b, 0x26, 0x81, + 0xa5, 0x48, 0xd6, 0x7c, 0x70, 0xf0, 0xe1, 0x24, 0x10, 0x97, 0x33, 0xd7, 0xf2, 0x58, 0x64, 0x4f, + 0xd8, 0x84, 0xd9, 0x8a, 0xeb, 0xce, 0xc6, 0x6a, 0xa5, 0x16, 0xea, 0x2b, 0xf7, 0x38, 0xe8, 0x57, + 0x0a, 0x79, 0x2c, 0x85, 0x35, 0x75, 0x0e, 0x8e, 0x4b, 0x4e, 0x44, 0xbd, 0xcb, 0x20, 0x86, 0xf4, + 0xca, 0x4e, 0xa6, 0x13, 0x09, 0x70, 0x3b, 0x02, 0x41, 0xd7, 0xa9, 0xec, 0xfb, 0x54, 0xe9, 0x2c, + 0x16, 0x41, 0x04, 0x77, 0x04, 0x9f, 0xfc, 0x9f, 0x80, 0x7b, 0x97, 0x10, 0xd1, 0xdb, 0xba, 0xfe, + 0xbf, 0x06, 0xaa, 0x9f, 0x32, 0x17, 0xff, 0x8c, 0x9a, 0xf2, 0x2c, 0x3e, 0x15, 0xb4, 0x6b, 0x3c, + 0x35, 0x0e, 0xdb, 0x47, 0x1f, 0x59, 0x65, 0x87, 0x0a, 0x4b, 0x2b, 0x99, 0x4e, 0x24, 0xc0, 0x2d, + 0xc9, 0xb6, 0xe6, 0x03, 0xeb, 0xb9, 0xfb, 0x0b, 0x78, 0xe2, 0x0c, 0x04, 0x75, 0xf0, 0xf5, 0xa2, + 0x57, 0xcb, 0x16, 0x3d, 0x54, 0x62, 0xa4, 0x70, 0xc5, 0x5f, 0xa2, 0x4d, 0x9e, 0x80, 0xd7, 0xdd, + 0x50, 0xee, 0x6f, 0x5b, 0x6b, 0xfa, 0x6f, 0x9d, 0x32, 0x77, 0x94, 0x80, 0xe7, 0x74, 0xb4, 0xd3, + 0xa6, 0x5c, 0x11, 0xa5, 0xc3, 0xcf, 0xd0, 0x16, 0x17, 0x54, 0xcc, 0x78, 0xb7, 0xae, 0x1c, 0xcc, + 0x7b, 0x1d, 0x14, 0xcb, 0xd9, 0xd5, 0x1e, 0x5b, 0xf9, 0x9a, 0x68, 0x75, 0xff, 0xcf, 0x3a, 0xea, + 0x9c, 0x32, 0xf7, 0x84, 0xc5, 0x7e, 0x20, 0x02, 0x16, 0xe3, 0x63, 0xb4, 0x29, 0xae, 0x12, 0x50, + 0xbf, 0xdd, 0x72, 0x9e, 0x2e, 0x4b, 0x5f, 0x5c, 0x25, 0xf0, 0x6a, 0xd1, 0xdb, 0xab, 0x72, 0x25, + 0x46, 0x14, 0x1b, 0x0f, 0x8b, 0xe3, 0x6c, 0x28, 0xdd, 0xf1, 0x6a, 0xb9, 0x57, 0x8b, 0xde, 0x9a, + 0x74, 0x58, 0x85, 0xd3, 0xea, 0xa1, 0xf0, 0x04, 0xed, 0x84, 0x94, 0x8b, 0xf3, 0x94, 0xb9, 0x70, + 0x11, 0x44, 0xa0, 0xff, 0xf1, 0x83, 0x87, 0xdd, 0x81, 0x54, 0x38, 0xfb, 0xfa, 0x00, 0x3b, 0xc3, + 0xaa, 0x11, 0x59, 0xf5, 0xc5, 0x73, 0x84, 0x25, 0x70, 0x91, 0xd2, 0x98, 0xe7, 0xbf, 0x24, 0xab, + 0x6d, 0x3e, 0xba, 0xda, 0x81, 0xae, 0x86, 0x87, 0x77, 0xdc, 0xc8, 0x9a, 0x0a, 0xf8, 0x3d, 0xb4, + 0x95, 0x02, 0xe5, 0x2c, 0xee, 0x36, 0x54, 0xbb, 0x8a, 0xdb, 0x21, 0x0a, 0x25, 0x7a, 0x17, 0xbf, + 0x8f, 0xb6, 0x23, 0xe0, 0x9c, 0x4e, 0xa0, 0xbb, 0xa5, 0x88, 0x4f, 0x34, 0x71, 0xfb, 0x2c, 0x87, + 0xc9, 0x72, 0xbf, 0xff, 0x87, 0x81, 0xb6, 0x4f, 0x99, 0x3b, 0x0c, 0xb8, 0xc0, 0x3f, 0xde, 0x89, + 0xaf, 0xf5, 0xb0, 0x9f, 0x91, 0x6a, 0x15, 0xde, 0x3d, 0x5d, 0xa7, 0xb9, 0x44, 0x2a, 0xd1, 0xfd, + 0x02, 0x35, 0x02, 0x01, 0x91, 0xbc, 0xea, 0xfa, 0x61, 0xfb, 0xa8, 0x7b, 0x5f, 0xf2, 0x9c, 0x1d, + 0x6d, 0xd2, 0xf8, 0x46, 0xd2, 0x49, 0xae, 0xea, 0xff, 0x53, 0x57, 0x07, 0x95, 0x59, 0xc6, 0x03, + 0xd4, 0x4e, 0x68, 0x4a, 0xc3, 0x10, 0xc2, 0x80, 0x47, 0xea, 0xac, 0x0d, 0xe7, 0x49, 0xb6, 0xe8, + 0xb5, 0xcf, 0x4b, 0x98, 0x54, 0x39, 0x52, 0xe2, 0xb1, 0x28, 0x09, 0x41, 0x36, 0x33, 0x8f, 0x9b, + 0x96, 0x9c, 0x94, 0x30, 0xa9, 0x72, 0xf0, 0x73, 0xb4, 0x4f, 0x3d, 0x11, 0xcc, 0xe1, 0x6b, 0xa0, + 0x7e, 0x18, 0xc4, 0x30, 0x02, 0x8f, 0xc5, 0x7e, 0xfe, 0x74, 0xea, 0xce, 0x5b, 0xd9, 0xa2, 0xb7, + 0xff, 0xd5, 0x3a, 0x02, 0x59, 0xaf, 0xc3, 0x3f, 0xa1, 0x26, 0x87, 0x10, 0x3c, 0xc1, 0x52, 0x1d, + 0x96, 0x8f, 0x1f, 0xd8, 0x5f, 0xea, 0x42, 0x38, 0xd2, 0x52, 0xa7, 0x23, 0x1b, 0xbc, 0x5c, 0x91, + 0xc2, 0x12, 0x7f, 0x86, 0x76, 0x23, 0x1a, 0xcf, 0x68, 0xc1, 0x54, 0x29, 0x69, 0x3a, 0x38, 0x5b, + 0xf4, 0x76, 0xcf, 0x56, 0x76, 0xc8, 0x2d, 0x26, 0xfe, 0x16, 0x35, 0x05, 0x44, 0x49, 0x48, 0x45, + 0x1e, 0x99, 0xf6, 0xd1, 0xbb, 0xd5, 0xfb, 0x91, 0x2f, 0x4f, 0x1e, 0xe4, 0x9c, 0xf9, 0x17, 0x9a, + 0xa6, 0x46, 0x4c, 0x71, 0xdf, 0x4b, 0x94, 0x14, 0x36, 0xf8, 0x18, 0x75, 0x5c, 0xea, 0x4d, 0xd9, + 0x78, 0x3c, 0x0c, 0xa2, 0x40, 0x74, 0xb7, 0x55, 0xcb, 0xf7, 0xb2, 0x45, 0xaf, 0xe3, 0x54, 0x70, + 0xb2, 0xc2, 0xea, 0xff, 0x5e, 0x47, 0xad, 0x62, 0xfc, 0xe0, 0xef, 0x10, 0xf2, 0x96, 0x8f, 0x9d, + 0x77, 0x0d, 0x15, 0x9c, 0x77, 0xee, 0x0b, 0x4e, 0x31, 0x16, 0xca, 0x19, 0x5a, 0x40, 0x9c, 0x54, + 0x8c, 0xf0, 0xf7, 0xa8, 0xc5, 0x05, 0x4d, 0x85, 0x7a, 0xb6, 0x1b, 0x8f, 0x7e, 0xb6, 0x3b, 0xd9, + 0xa2, 0xd7, 0x1a, 0x2d, 0x0d, 0x48, 0xe9, 0x85, 0xc7, 0x68, 0xb7, 0x4c, 0xd0, 0x6b, 0x8e, 0x20, + 0x75, 0x5d, 0x27, 0x2b, 0x2e, 0xe4, 0x96, 0xab, 0x1c, 0x04, 0x79, 0xc4, 0x54, 0x8e, 0x1a, 0xe5, + 0x20, 0xc8, 0xf3, 0x48, 0xf4, 0x2e, 0xb6, 0x51, 0x8b, 0xcf, 0x3c, 0x0f, 0xc0, 0x07, 0x5f, 0xa5, + 0xa1, 0xe1, 0xbc, 0xa1, 0xa9, 0xad, 0xd1, 0x72, 0x83, 0x94, 0x1c, 0x69, 0x3c, 0xa6, 0x41, 0x08, + 0xbe, 0x4a, 0x41, 0xc5, 0xf8, 0x99, 0x42, 0x89, 0xde, 0x75, 0x0e, 0xaf, 0x6f, 0xcc, 0xda, 0x8b, + 0x1b, 0xb3, 0xf6, 0xf2, 0xc6, 0xac, 0xfd, 0x9a, 0x99, 0xc6, 0x75, 0x66, 0x1a, 0x2f, 0x32, 0xd3, + 0x78, 0x99, 0x99, 0xc6, 0x5f, 0x99, 0x69, 0xfc, 0xf6, 0xb7, 0x59, 0xfb, 0x61, 0x63, 0x3e, 0xf8, + 0x2f, 0x00, 0x00, 0xff, 0xff, 0xdd, 0xcc, 0x84, 0xd1, 0x61, 0x08, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/batch/v1/generated.proto b/vendor/k8s.io/api/batch/v1/generated.proto index b0306f3bc..91858b019 100644 --- a/vendor/k8s.io/api/batch/v1/generated.proto +++ b/vendor/k8s.io/api/batch/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/api/batch/v1/types_swagger_doc_generated.go b/vendor/k8s.io/api/batch/v1/types_swagger_doc_generated.go index 0ddf4b116..2bb794a5f 100644 --- a/vendor/k8s.io/api/batch/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/batch/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_Job = map[string]string{ "": "Job represents the configuration of a single job.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/api/batch/v1/zz_generated.deepcopy.go b/vendor/k8s.io/api/batch/v1/zz_generated.deepcopy.go index a7179849b..3e5250f37 100644 --- a/vendor/k8s.io/api/batch/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/batch/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/batch/v1beta1/generated.pb.go b/vendor/k8s.io/api/batch/v1beta1/generated.pb.go index 6544184db..ece2204f9 100644 --- a/vendor/k8s.io/api/batch/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/batch/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1456,54 +1456,54 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 784 bytes of a gzipped FileDescriptorProto + // 771 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0xcf, 0x6f, 0xe3, 0x44, 0x14, 0xc7, 0xe3, 0x34, 0xbf, 0x76, 0xc2, 0x42, 0xd7, 0xa0, 0x5d, 0x2b, 0x20, 0x27, 0x64, 0xb5, - 0x22, 0x20, 0x76, 0x4c, 0x0b, 0x42, 0x9c, 0x90, 0xd6, 0x8b, 0x16, 0x28, 0x45, 0x8b, 0x9c, 0x22, - 0x24, 0x54, 0xa1, 0x8e, 0xc7, 0x2f, 0xc9, 0x34, 0xb6, 0xc7, 0xf2, 0x8c, 0x23, 0xe5, 0xc6, 0x85, - 0x3b, 0xff, 0x08, 0x27, 0xfe, 0x89, 0x88, 0x53, 0x8f, 0x3d, 0x45, 0xd4, 0xfc, 0x17, 0x9c, 0x90, - 0x27, 0xce, 0x8f, 0xe6, 0x47, 0x5b, 0x2e, 0xbd, 0x79, 0x9e, 0xbf, 0xdf, 0xcf, 0xbc, 0x79, 0xef, - 0xcd, 0xa0, 0x17, 0xc3, 0x2f, 0x04, 0x66, 0xdc, 0x1a, 0x26, 0x2e, 0xc4, 0x21, 0x48, 0x10, 0xd6, - 0x08, 0x42, 0x8f, 0xc7, 0x56, 0xfe, 0x83, 0x44, 0xcc, 0x72, 0x89, 0xa4, 0x03, 0x6b, 0x74, 0xe0, - 0x82, 0x24, 0x07, 0x56, 0x1f, 0x42, 0x88, 0x89, 0x04, 0x0f, 0x47, 0x31, 0x97, 0x5c, 0x37, 0x66, - 0x4a, 0x4c, 0x22, 0x86, 0x95, 0x12, 0xe7, 0xca, 0xc6, 0xf3, 0x3e, 0x93, 0x83, 0xc4, 0xc5, 0x94, - 0x07, 0x56, 0x9f, 0xf7, 0xb9, 0xa5, 0x0c, 0x6e, 0xd2, 0x53, 0x2b, 0xb5, 0x50, 0x5f, 0x33, 0x50, - 0xe3, 0xe9, 0x96, 0x2d, 0xd7, 0x77, 0x6b, 0xb4, 0x57, 0x44, 0x94, 0xc7, 0xb0, 0x4d, 0xf3, 0xd9, - 0x52, 0x13, 0x10, 0x3a, 0x60, 0x21, 0xc4, 0x63, 0x2b, 0x1a, 0xf6, 0xb3, 0x80, 0xb0, 0x02, 0x90, - 0x64, 0x9b, 0xcb, 0xda, 0xe5, 0x8a, 0x93, 0x50, 0xb2, 0x00, 0x36, 0x0c, 0x9f, 0xdf, 0x66, 0x10, - 0x74, 0x00, 0x01, 0xd9, 0xf0, 0x7d, 0xba, 0xcb, 0x97, 0x48, 0xe6, 0x5b, 0x2c, 0x94, 0x42, 0xc6, - 0xeb, 0xa6, 0xf6, 0x6f, 0x45, 0x54, 0x7d, 0x19, 0xf3, 0xf0, 0x88, 0xbb, 0xfa, 0x19, 0xaa, 0x65, - 0x87, 0xf0, 0x88, 0x24, 0x86, 0xd6, 0xd2, 0x3a, 0xf5, 0xc3, 0x4f, 0xf0, 0xb2, 0x09, 0x0b, 0x26, - 0x8e, 0x86, 0xfd, 0x2c, 0x20, 0x70, 0xa6, 0xc6, 0xa3, 0x03, 0xfc, 0xda, 0x3d, 0x07, 0x2a, 0xbf, - 0x07, 0x49, 0x6c, 0x7d, 0x32, 0x6d, 0x16, 0xd2, 0x69, 0x13, 0x2d, 0x63, 0xce, 0x82, 0xaa, 0x7f, - 0x8d, 0x4a, 0x22, 0x02, 0x6a, 0x14, 0x15, 0xfd, 0x19, 0xde, 0xd5, 0x62, 0x9c, 0xa7, 0xd4, 0x8d, - 0x80, 0xda, 0x6f, 0xe4, 0xc8, 0x52, 0xb6, 0x72, 0x14, 0x40, 0x7f, 0x8d, 0x2a, 0x42, 0x12, 0x99, - 0x08, 0x63, 0x4f, 0xa1, 0x3e, 0xb8, 0x1d, 0xa5, 0xe4, 0xf6, 0x9b, 0x39, 0xac, 0x32, 0x5b, 0x3b, - 0x39, 0xa6, 0xfd, 0xa7, 0x86, 0xea, 0xb9, 0xf2, 0x98, 0x09, 0xa9, 0x9f, 0x6e, 0xd4, 0x02, 0xdf, - 0xad, 0x16, 0x99, 0x5b, 0x55, 0x62, 0x3f, 0xdf, 0xa9, 0x36, 0x8f, 0xac, 0xd4, 0xe1, 0x15, 0x2a, - 0x33, 0x09, 0x81, 0x30, 0x8a, 0xad, 0xbd, 0x4e, 0xfd, 0xf0, 0xfd, 0x5b, 0xb3, 0xb7, 0x1f, 0xe6, - 0xb4, 0xf2, 0xb7, 0x99, 0xcf, 0x99, 0xd9, 0xdb, 0x7f, 0x94, 0x16, 0x59, 0x67, 0xc5, 0xd1, 0x3f, - 0x46, 0xb5, 0x6c, 0x38, 0xbc, 0xc4, 0x07, 0x95, 0xf5, 0x83, 0x65, 0x16, 0xdd, 0x3c, 0xee, 0x2c, - 0x14, 0xfa, 0x8f, 0xe8, 0x89, 0x90, 0x24, 0x96, 0x2c, 0xec, 0x7f, 0x05, 0xc4, 0xf3, 0x59, 0x08, - 0x5d, 0xa0, 0x3c, 0xf4, 0x84, 0x6a, 0xd0, 0x9e, 0xfd, 0x6e, 0x3a, 0x6d, 0x3e, 0xe9, 0x6e, 0x97, - 0x38, 0xbb, 0xbc, 0xfa, 0x29, 0x7a, 0x44, 0x79, 0x48, 0x93, 0x38, 0x86, 0x90, 0x8e, 0x7f, 0xe0, - 0x3e, 0xa3, 0x63, 0xd5, 0xa6, 0x07, 0x36, 0xce, 0xb3, 0x79, 0xf4, 0x72, 0x5d, 0xf0, 0xef, 0xb6, - 0xa0, 0xb3, 0x09, 0xd2, 0x9f, 0xa1, 0xaa, 0x48, 0x44, 0x04, 0xa1, 0x67, 0x94, 0x5a, 0x5a, 0xa7, - 0x66, 0xd7, 0xd3, 0x69, 0xb3, 0xda, 0x9d, 0x85, 0x9c, 0xf9, 0x3f, 0xfd, 0x0c, 0xd5, 0xcf, 0xb9, - 0x7b, 0x02, 0x41, 0xe4, 0x13, 0x09, 0x46, 0x59, 0xb5, 0xf0, 0xc3, 0xdd, 0x75, 0x3e, 0x5a, 0x8a, - 0xd5, 0xd0, 0xbd, 0x9d, 0x67, 0x5a, 0x5f, 0xf9, 0xe1, 0xac, 0x22, 0xf5, 0x5f, 0x50, 0x43, 0x24, - 0x94, 0x82, 0x10, 0xbd, 0xc4, 0x3f, 0xe2, 0xae, 0xf8, 0x86, 0x09, 0xc9, 0xe3, 0xf1, 0x31, 0x0b, - 0x98, 0x34, 0x2a, 0x2d, 0xad, 0x53, 0xb6, 0xcd, 0x74, 0xda, 0x6c, 0x74, 0x77, 0xaa, 0x9c, 0x1b, - 0x08, 0xba, 0x83, 0x1e, 0xf7, 0x08, 0xf3, 0xc1, 0xdb, 0x60, 0x57, 0x15, 0xbb, 0x91, 0x4e, 0x9b, - 0x8f, 0x5f, 0x6d, 0x55, 0x38, 0x3b, 0x9c, 0xed, 0xbf, 0x34, 0xf4, 0xf0, 0xda, 0x7d, 0xd0, 0xbf, - 0x43, 0x15, 0x42, 0x25, 0x1b, 0x65, 0xf3, 0x92, 0x8d, 0xe2, 0xd3, 0xd5, 0x12, 0x65, 0x0f, 0xe1, - 0xf2, 0x7e, 0x3b, 0xd0, 0x83, 0xac, 0x13, 0xb0, 0xbc, 0x44, 0x2f, 0x94, 0xd5, 0xc9, 0x11, 0xba, - 0x8f, 0xf6, 0x7d, 0x22, 0xe4, 0x7c, 0xd4, 0x4e, 0x58, 0x00, 0xaa, 0x49, 0xf5, 0xc3, 0x8f, 0xee, - 0x76, 0x79, 0x32, 0x87, 0xfd, 0x4e, 0x3a, 0x6d, 0xee, 0x1f, 0xaf, 0x71, 0x9c, 0x0d, 0x72, 0x7b, - 0xa2, 0xa1, 0xd5, 0xee, 0xdc, 0xc3, 0xf3, 0xf5, 0x13, 0xaa, 0xc9, 0xf9, 0x44, 0x15, 0xff, 0xef, - 0x44, 0x2d, 0x6e, 0xe2, 0x62, 0x9c, 0x16, 0xb0, 0xec, 0xf5, 0x79, 0x6b, 0x4d, 0x7f, 0x0f, 0xc7, - 0xf9, 0xf2, 0xda, 0x6b, 0xfc, 0xde, 0xb6, 0xa3, 0xe0, 0x1b, 0x1e, 0x61, 0xfb, 0xf9, 0xe4, 0xca, - 0x2c, 0x5c, 0x5c, 0x99, 0x85, 0xcb, 0x2b, 0xb3, 0xf0, 0x6b, 0x6a, 0x6a, 0x93, 0xd4, 0xd4, 0x2e, - 0x52, 0x53, 0xbb, 0x4c, 0x4d, 0xed, 0xef, 0xd4, 0xd4, 0x7e, 0xff, 0xc7, 0x2c, 0xfc, 0x5c, 0xcd, - 0x0b, 0xf2, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x78, 0xe4, 0x62, 0x14, 0x08, 0x00, 0x00, + 0x22, 0x20, 0x76, 0x4c, 0x2b, 0x84, 0x38, 0x21, 0xad, 0x17, 0x2d, 0x50, 0x8a, 0x16, 0x39, 0x45, + 0x48, 0xa8, 0x42, 0x1d, 0x8f, 0x5f, 0x92, 0x69, 0x6c, 0x8f, 0xe5, 0x19, 0x47, 0xca, 0x8d, 0x0b, + 0x77, 0xfe, 0x11, 0x4e, 0xfc, 0x13, 0x11, 0xa7, 0x1e, 0x7b, 0x8a, 0xa8, 0xf9, 0x2f, 0x38, 0x21, + 0x4f, 0x9c, 0x1f, 0xcd, 0x8f, 0xb6, 0x7b, 0xe9, 0xcd, 0xf3, 0xe6, 0xfb, 0xfd, 0xcc, 0xf3, 0x7b, + 0x6f, 0x06, 0xbd, 0x18, 0x7e, 0x29, 0x30, 0xe3, 0xd6, 0x30, 0x71, 0x21, 0x0e, 0x41, 0x82, 0xb0, + 0x46, 0x10, 0x7a, 0x3c, 0xb6, 0xf2, 0x0d, 0x12, 0x31, 0xcb, 0x25, 0x92, 0x0e, 0xac, 0xd1, 0x81, + 0x0b, 0x92, 0x1c, 0x58, 0x7d, 0x08, 0x21, 0x26, 0x12, 0x3c, 0x1c, 0xc5, 0x5c, 0x72, 0xdd, 0x98, + 0x29, 0x31, 0x89, 0x18, 0x56, 0x4a, 0x9c, 0x2b, 0x1b, 0xcf, 0xfb, 0x4c, 0x0e, 0x12, 0x17, 0x53, + 0x1e, 0x58, 0x7d, 0xde, 0xe7, 0x96, 0x32, 0xb8, 0x49, 0x4f, 0xad, 0xd4, 0x42, 0x7d, 0xcd, 0x40, + 0x8d, 0xa7, 0x5b, 0x8e, 0x5c, 0x3f, 0xad, 0xd1, 0x5e, 0x11, 0x51, 0x1e, 0xc3, 0x36, 0xcd, 0xe7, + 0x4b, 0x4d, 0x40, 0xe8, 0x80, 0x85, 0x10, 0x8f, 0xad, 0x68, 0xd8, 0xcf, 0x02, 0xc2, 0x0a, 0x40, + 0x92, 0x6d, 0x2e, 0x6b, 0x97, 0x2b, 0x4e, 0x42, 0xc9, 0x02, 0xd8, 0x30, 0x7c, 0x71, 0x9b, 0x41, + 0xd0, 0x01, 0x04, 0x64, 0xdd, 0xd7, 0xfe, 0xbd, 0x88, 0xaa, 0x2f, 0x63, 0x1e, 0x1e, 0x71, 0x57, + 0x3f, 0x43, 0xb5, 0x2c, 0x1f, 0x8f, 0x48, 0x62, 0x68, 0x2d, 0xad, 0x53, 0x3f, 0xfc, 0x0c, 0x2f, + 0xeb, 0xb9, 0xc0, 0xe2, 0x68, 0xd8, 0xcf, 0x02, 0x02, 0x67, 0x6a, 0x3c, 0x3a, 0xc0, 0xaf, 0xdd, + 0x73, 0xa0, 0xf2, 0x07, 0x90, 0xc4, 0xd6, 0x27, 0xd3, 0x66, 0x21, 0x9d, 0x36, 0xd1, 0x32, 0xe6, + 0x2c, 0xa8, 0xfa, 0x37, 0xa8, 0x24, 0x22, 0xa0, 0x46, 0x51, 0xd1, 0x9f, 0xe1, 0x5d, 0xdd, 0xc2, + 0x79, 0x4a, 0xdd, 0x08, 0xa8, 0xfd, 0x56, 0x8e, 0x2c, 0x65, 0x2b, 0x47, 0x01, 0xf4, 0xd7, 0xa8, + 0x22, 0x24, 0x91, 0x89, 0x30, 0xf6, 0x14, 0xea, 0xa3, 0xdb, 0x51, 0x4a, 0x6e, 0xbf, 0x9d, 0xc3, + 0x2a, 0xb3, 0xb5, 0x93, 0x63, 0xda, 0x7f, 0x69, 0xa8, 0x9e, 0x2b, 0x8f, 0x99, 0x90, 0xfa, 0xe9, + 0x46, 0x2d, 0xf0, 0xdd, 0x6a, 0x91, 0xb9, 0x55, 0x25, 0xf6, 0xf3, 0x93, 0x6a, 0xf3, 0xc8, 0x4a, + 0x1d, 0x5e, 0xa1, 0x32, 0x93, 0x10, 0x08, 0xa3, 0xd8, 0xda, 0xeb, 0xd4, 0x0f, 0x3f, 0xbc, 0x35, + 0x7b, 0xfb, 0x61, 0x4e, 0x2b, 0x7f, 0x97, 0xf9, 0x9c, 0x99, 0xbd, 0xfd, 0x67, 0x69, 0x91, 0x75, + 0x56, 0x1c, 0xfd, 0x53, 0x54, 0xcb, 0xfa, 0xec, 0x25, 0x3e, 0xa8, 0xac, 0x1f, 0x2c, 0xb3, 0xe8, + 0xe6, 0x71, 0x67, 0xa1, 0xd0, 0x7f, 0x42, 0x4f, 0x84, 0x24, 0xb1, 0x64, 0x61, 0xff, 0x6b, 0x20, + 0x9e, 0xcf, 0x42, 0xe8, 0x02, 0xe5, 0xa1, 0x27, 0x54, 0x83, 0xf6, 0xec, 0xf7, 0xd3, 0x69, 0xf3, + 0x49, 0x77, 0xbb, 0xc4, 0xd9, 0xe5, 0xd5, 0x4f, 0xd1, 0x23, 0xca, 0x43, 0x9a, 0xc4, 0x31, 0x84, + 0x74, 0xfc, 0x23, 0xf7, 0x19, 0x1d, 0xab, 0x36, 0x3d, 0xb0, 0x71, 0x9e, 0xcd, 0xa3, 0x97, 0xeb, + 0x82, 0xff, 0xb6, 0x05, 0x9d, 0x4d, 0x90, 0xfe, 0x0c, 0x55, 0x45, 0x22, 0x22, 0x08, 0x3d, 0xa3, + 0xd4, 0xd2, 0x3a, 0x35, 0xbb, 0x9e, 0x4e, 0x9b, 0xd5, 0xee, 0x2c, 0xe4, 0xcc, 0xf7, 0xf4, 0x33, + 0x54, 0x3f, 0xe7, 0xee, 0x09, 0x04, 0x91, 0x4f, 0x24, 0x18, 0x65, 0xd5, 0xc2, 0x8f, 0x77, 0xd7, + 0xf9, 0x68, 0x29, 0x56, 0x43, 0xf7, 0x6e, 0x9e, 0x69, 0x7d, 0x65, 0xc3, 0x59, 0x45, 0xea, 0xbf, + 0xa2, 0x86, 0x48, 0x28, 0x05, 0x21, 0x7a, 0x89, 0x7f, 0xc4, 0x5d, 0xf1, 0x2d, 0x13, 0x92, 0xc7, + 0xe3, 0x63, 0x16, 0x30, 0x69, 0x54, 0x5a, 0x5a, 0xa7, 0x6c, 0x9b, 0xe9, 0xb4, 0xd9, 0xe8, 0xee, + 0x54, 0x39, 0x37, 0x10, 0x74, 0x07, 0x3d, 0xee, 0x11, 0xe6, 0x83, 0xb7, 0xc1, 0xae, 0x2a, 0x76, + 0x23, 0x9d, 0x36, 0x1f, 0xbf, 0xda, 0xaa, 0x70, 0x76, 0x38, 0xdb, 0x7f, 0x6b, 0xe8, 0xe1, 0xb5, + 0xfb, 0xa0, 0x7f, 0x8f, 0x2a, 0x84, 0x4a, 0x36, 0xca, 0xe6, 0x25, 0x1b, 0xc5, 0xa7, 0xab, 0x25, + 0xca, 0xde, 0xb4, 0xe5, 0xfd, 0x76, 0xa0, 0x07, 0x59, 0x27, 0x60, 0x79, 0x89, 0x5e, 0x28, 0xab, + 0x93, 0x23, 0x74, 0x1f, 0xed, 0xfb, 0x44, 0xc8, 0xf9, 0xa8, 0x9d, 0xb0, 0x00, 0x54, 0x93, 0xea, + 0x87, 0x9f, 0xdc, 0xed, 0xf2, 0x64, 0x0e, 0xfb, 0xbd, 0x74, 0xda, 0xdc, 0x3f, 0x5e, 0xe3, 0x38, + 0x1b, 0xe4, 0xf6, 0x44, 0x43, 0xab, 0xdd, 0xb9, 0x87, 0xe7, 0xeb, 0x67, 0x54, 0x93, 0xf3, 0x89, + 0x2a, 0xbe, 0xe9, 0x44, 0x2d, 0x6e, 0xe2, 0x62, 0x9c, 0x16, 0xb0, 0xec, 0xf5, 0x79, 0x67, 0x4d, + 0x7f, 0x0f, 0xbf, 0xf3, 0xd5, 0xb5, 0xd7, 0xf8, 0x83, 0x6d, 0xbf, 0x82, 0x6f, 0x78, 0x84, 0xed, + 0xe7, 0x93, 0x2b, 0xb3, 0x70, 0x71, 0x65, 0x16, 0x2e, 0xaf, 0xcc, 0xc2, 0x6f, 0xa9, 0xa9, 0x4d, + 0x52, 0x53, 0xbb, 0x48, 0x4d, 0xed, 0x32, 0x35, 0xb5, 0x7f, 0x52, 0x53, 0xfb, 0xe3, 0x5f, 0xb3, + 0xf0, 0x4b, 0x35, 0x2f, 0xc8, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf6, 0x9f, 0xb3, 0xdd, 0xdf, + 0x07, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/batch/v1beta1/generated.proto b/vendor/k8s.io/api/batch/v1beta1/generated.proto index 9278a3d9b..043b3551b 100644 --- a/vendor/k8s.io/api/batch/v1beta1/generated.proto +++ b/vendor/k8s.io/api/batch/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/api/batch/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/batch/v1beta1/types_swagger_doc_generated.go index 3b53ac08a..abbdfec01 100644 --- a/vendor/k8s.io/api/batch/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/batch/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CronJob = map[string]string{ "": "CronJob represents the configuration of a single cron job.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/api/batch/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/batch/v1beta1/zz_generated.deepcopy.go index 78e361aba..a33f4ffcf 100644 --- a/vendor/k8s.io/api/batch/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/batch/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/batch/v2alpha1/generated.pb.go b/vendor/k8s.io/api/batch/v2alpha1/generated.pb.go index 2560953eb..6ab41ebbc 100644 --- a/vendor/k8s.io/api/batch/v2alpha1/generated.pb.go +++ b/vendor/k8s.io/api/batch/v2alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1456,55 +1456,54 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 787 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0xcf, 0x6f, 0xe3, 0x44, - 0x14, 0xc7, 0xe3, 0x34, 0xbf, 0x3a, 0xa1, 0xd0, 0x1a, 0xd4, 0x86, 0x80, 0x9c, 0xc8, 0x15, 0x28, - 0x42, 0x30, 0xa6, 0x05, 0x21, 0x4e, 0x48, 0xb8, 0x08, 0x4a, 0x29, 0xa2, 0x72, 0x8a, 0x84, 0x50, - 0xb5, 0xda, 0xf1, 0x78, 0x92, 0x4c, 0x63, 0x7b, 0x2c, 0xcf, 0x38, 0x52, 0x6e, 0x7b, 0xdb, 0xeb, - 0xfe, 0x25, 0x7b, 0xd9, 0xfd, 0x23, 0xba, 0x7b, 0xea, 0xb1, 0xa7, 0x68, 0xeb, 0xfd, 0x2f, 0xf6, - 0xb4, 0xf2, 0xc4, 0xf9, 0xd1, 0x38, 0x69, 0xbb, 0x97, 0xde, 0x3c, 0xcf, 0xdf, 0xef, 0x67, 0xde, - 0xbc, 0xf7, 0x66, 0x80, 0xd9, 0xff, 0x99, 0x43, 0xca, 0x8c, 0x7e, 0x64, 0x93, 0xd0, 0x27, 0x82, - 0x70, 0x63, 0x40, 0x7c, 0x87, 0x85, 0x46, 0xfa, 0x03, 0x05, 0xd4, 0xb0, 0x91, 0xc0, 0x3d, 0x63, - 0xb0, 0x8f, 0xdc, 0xa0, 0x87, 0xf6, 0x8c, 0x2e, 0xf1, 0x49, 0x88, 0x04, 0x71, 0x60, 0x10, 0x32, - 0xc1, 0xd4, 0xcf, 0xc7, 0x52, 0x88, 0x02, 0x0a, 0xa5, 0x14, 0x4e, 0xa4, 0xf5, 0xef, 0xba, 0x54, - 0xf4, 0x22, 0x1b, 0x62, 0xe6, 0x19, 0x5d, 0xd6, 0x65, 0x86, 0x74, 0xd8, 0x51, 0x47, 0xae, 0xe4, - 0x42, 0x7e, 0x8d, 0x49, 0xf5, 0xdd, 0xec, 0xa6, 0x99, 0xed, 0xea, 0xfa, 0x9c, 0x08, 0xb3, 0x90, - 0x2c, 0xd3, 0xfc, 0x38, 0xd3, 0x78, 0x08, 0xf7, 0xa8, 0x4f, 0xc2, 0xa1, 0x11, 0xf4, 0xbb, 0x49, - 0x80, 0x1b, 0x1e, 0x11, 0x68, 0x99, 0xcb, 0x58, 0xe5, 0x0a, 0x23, 0x5f, 0x50, 0x8f, 0x64, 0x0c, - 0x3f, 0xdd, 0x65, 0xe0, 0xb8, 0x47, 0x3c, 0x94, 0xf1, 0xfd, 0xb0, 0xca, 0x17, 0x09, 0xea, 0x1a, - 0xd4, 0x17, 0x5c, 0x84, 0x8b, 0x26, 0xfd, 0x69, 0x1e, 0x94, 0x0f, 0x42, 0xe6, 0x1f, 0x31, 0x5b, - 0x7d, 0x0c, 0x2a, 0xc9, 0x21, 0x1c, 0x24, 0x50, 0x4d, 0x69, 0x2a, 0xad, 0xea, 0xfe, 0xf7, 0x70, - 0xd6, 0x85, 0x29, 0x13, 0x06, 0xfd, 0x6e, 0x12, 0xe0, 0x30, 0x51, 0xc3, 0xc1, 0x1e, 0xfc, 0xc7, - 0x3e, 0x27, 0x58, 0xfc, 0x4d, 0x04, 0x32, 0xd5, 0x8b, 0x51, 0x23, 0x17, 0x8f, 0x1a, 0x60, 0x16, - 0xb3, 0xa6, 0x54, 0xf5, 0x10, 0x14, 0x78, 0x40, 0x70, 0x2d, 0x2f, 0xe9, 0x5f, 0xc3, 0x95, 0x3d, - 0x86, 0x69, 0x4e, 0xed, 0x80, 0x60, 0xf3, 0xa3, 0x94, 0x59, 0x48, 0x56, 0x96, 0x24, 0xa8, 0x27, - 0xa0, 0xc4, 0x05, 0x12, 0x11, 0xaf, 0xad, 0x49, 0x56, 0xeb, 0x1e, 0x2c, 0xa9, 0x37, 0x3f, 0x4e, - 0x69, 0xa5, 0xf1, 0xda, 0x4a, 0x39, 0xfa, 0x4b, 0x05, 0x54, 0x53, 0xe5, 0x31, 0xe5, 0x42, 0x3d, - 0xcb, 0x54, 0x03, 0xde, 0xaf, 0x1a, 0x89, 0x5b, 0xd6, 0x62, 0x33, 0xdd, 0xa9, 0x32, 0x89, 0xcc, - 0x55, 0xe2, 0x0f, 0x50, 0xa4, 0x82, 0x78, 0xbc, 0x96, 0x6f, 0xae, 0xb5, 0xaa, 0xfb, 0xfa, 0xdd, - 0xe9, 0x9b, 0x1b, 0x29, 0xae, 0xf8, 0x67, 0x62, 0xb4, 0xc6, 0x7e, 0xfd, 0x79, 0x61, 0x9a, 0x76, - 0x52, 0x1e, 0xf5, 0x5b, 0x50, 0x49, 0xe6, 0xc3, 0x89, 0x5c, 0x22, 0xd3, 0x5e, 0x9f, 0xa5, 0xd1, - 0x4e, 0xe3, 0xd6, 0x54, 0xa1, 0xfe, 0x0b, 0x76, 0xb8, 0x40, 0xa1, 0xa0, 0x7e, 0xf7, 0x37, 0x82, - 0x1c, 0x97, 0xfa, 0xa4, 0x4d, 0x30, 0xf3, 0x1d, 0x2e, 0x7b, 0xb4, 0x66, 0x7e, 0x11, 0x8f, 0x1a, - 0x3b, 0xed, 0xe5, 0x12, 0x6b, 0x95, 0x57, 0x3d, 0x03, 0x5b, 0x98, 0xf9, 0x38, 0x0a, 0x43, 0xe2, - 0xe3, 0xe1, 0x09, 0x73, 0x29, 0x1e, 0xca, 0x46, 0xad, 0x9b, 0x30, 0xcd, 0x66, 0xeb, 0x60, 0x51, - 0xf0, 0x6e, 0x59, 0xd0, 0xca, 0x82, 0xd4, 0xaf, 0x40, 0x99, 0x47, 0x3c, 0x20, 0xbe, 0x53, 0x2b, - 0x34, 0x95, 0x56, 0xc5, 0xac, 0xc6, 0xa3, 0x46, 0xb9, 0x3d, 0x0e, 0x59, 0x93, 0x7f, 0x2a, 0x02, - 0xd5, 0x73, 0x66, 0x9f, 0x12, 0x2f, 0x70, 0x91, 0x20, 0xb5, 0xa2, 0xec, 0xe1, 0x37, 0xb7, 0x14, - 0xfa, 0x68, 0xa6, 0x96, 0x73, 0xf7, 0x69, 0x9a, 0x6a, 0x75, 0xee, 0x87, 0x35, 0xcf, 0x54, 0x1f, - 0x81, 0x3a, 0x8f, 0x30, 0x26, 0x9c, 0x77, 0x22, 0xf7, 0x88, 0xd9, 0xfc, 0x90, 0x72, 0xc1, 0xc2, - 0xe1, 0x31, 0xf5, 0xa8, 0xa8, 0x95, 0x9a, 0x4a, 0xab, 0x68, 0x6a, 0xf1, 0xa8, 0x51, 0x6f, 0xaf, - 0x54, 0x59, 0xb7, 0x10, 0x54, 0x0b, 0x6c, 0x77, 0x10, 0x75, 0x89, 0x93, 0x61, 0x97, 0x25, 0xbb, - 0x1e, 0x8f, 0x1a, 0xdb, 0xbf, 0x2f, 0x55, 0x58, 0x2b, 0x9c, 0xfa, 0x6b, 0x05, 0x6c, 0xdc, 0xb8, - 0x11, 0xea, 0x5f, 0xa0, 0x84, 0xb0, 0xa0, 0x83, 0x64, 0x60, 0x92, 0x61, 0xdc, 0x9d, 0xaf, 0x51, - 0xf2, 0x18, 0xce, 0xee, 0xb8, 0x45, 0x3a, 0x24, 0x69, 0x05, 0x99, 0x5d, 0xa3, 0x5f, 0xa5, 0xd5, - 0x4a, 0x11, 0xaa, 0x0b, 0x36, 0x5d, 0xc4, 0xc5, 0x64, 0xd6, 0x4e, 0xa9, 0x47, 0x64, 0x97, 0x6e, - 0x96, 0xfe, 0x96, 0xeb, 0x93, 0x38, 0xcc, 0xcf, 0xe2, 0x51, 0x63, 0xf3, 0x78, 0x81, 0x63, 0x65, - 0xc8, 0xfa, 0x2b, 0x05, 0xcc, 0x77, 0xe7, 0x01, 0x9e, 0xb0, 0xff, 0x40, 0x45, 0x4c, 0x46, 0x2a, - 0xff, 0xc1, 0x23, 0x35, 0xbd, 0x8b, 0xd3, 0x79, 0x9a, 0xd2, 0xf4, 0x17, 0x0a, 0xf8, 0x64, 0x41, - 0xff, 0x00, 0xe7, 0xf9, 0xe5, 0xc6, 0x93, 0xfc, 0xe5, 0x92, 0xb3, 0xc8, 0x53, 0xac, 0x7a, 0x88, - 0x4d, 0x78, 0x71, 0xad, 0xe5, 0x2e, 0xaf, 0xb5, 0xdc, 0xd5, 0xb5, 0x96, 0x7b, 0x12, 0x6b, 0xca, - 0x45, 0xac, 0x29, 0x97, 0xb1, 0xa6, 0x5c, 0xc5, 0x9a, 0xf2, 0x26, 0xd6, 0x94, 0x67, 0x6f, 0xb5, - 0xdc, 0xff, 0x95, 0x49, 0x45, 0xde, 0x07, 0x00, 0x00, 0xff, 0xff, 0x02, 0x60, 0xaa, 0x00, 0x1c, - 0x08, 0x00, 0x00, + // 774 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0x4d, 0x6f, 0xdb, 0x36, + 0x18, 0xc7, 0x2d, 0xc7, 0x6f, 0xa1, 0x97, 0x2d, 0xd1, 0x86, 0xc4, 0xf3, 0x06, 0xd9, 0x50, 0xb0, + 0xc1, 0x18, 0x36, 0x6a, 0x09, 0x86, 0x61, 0xa7, 0x01, 0x53, 0x86, 0x36, 0x4d, 0x53, 0x34, 0x90, + 0x53, 0xa0, 0x28, 0x82, 0xa2, 0x14, 0x45, 0xdb, 0x8c, 0x25, 0x51, 0x10, 0x29, 0x03, 0xbe, 0xf5, + 0xd6, 0x6b, 0x3f, 0x49, 0x2f, 0xed, 0x87, 0x48, 0x7b, 0xca, 0x31, 0x27, 0xa3, 0x51, 0xbf, 0x45, + 0x4f, 0x85, 0x68, 0xf9, 0x25, 0x7e, 0x49, 0xd2, 0x4b, 0x6e, 0xe2, 0xa3, 0xff, 0xff, 0xc7, 0x87, + 0xcf, 0xf3, 0x90, 0xc0, 0xec, 0xfe, 0xc3, 0x21, 0x65, 0x46, 0x37, 0xb2, 0x49, 0xe8, 0x13, 0x41, + 0xb8, 0xd1, 0x23, 0xbe, 0xc3, 0x42, 0x23, 0xfd, 0x81, 0x02, 0x6a, 0xd8, 0x48, 0xe0, 0x8e, 0xd1, + 0xdb, 0x45, 0x6e, 0xd0, 0x41, 0x3b, 0x46, 0x9b, 0xf8, 0x24, 0x44, 0x82, 0x38, 0x30, 0x08, 0x99, + 0x60, 0xea, 0x8f, 0x43, 0x29, 0x44, 0x01, 0x85, 0x52, 0x0a, 0x47, 0xd2, 0xea, 0x1f, 0x6d, 0x2a, + 0x3a, 0x91, 0x0d, 0x31, 0xf3, 0x8c, 0x36, 0x6b, 0x33, 0x43, 0x3a, 0xec, 0xa8, 0x25, 0x57, 0x72, + 0x21, 0xbf, 0x86, 0xa4, 0xea, 0xf6, 0xfc, 0xa6, 0x73, 0xdb, 0x55, 0xf5, 0x29, 0x11, 0x66, 0x21, + 0x59, 0xa4, 0xf9, 0x6b, 0xa2, 0xf1, 0x10, 0xee, 0x50, 0x9f, 0x84, 0x7d, 0x23, 0xe8, 0xb6, 0x93, + 0x00, 0x37, 0x3c, 0x22, 0xd0, 0x22, 0x97, 0xb1, 0xcc, 0x15, 0x46, 0xbe, 0xa0, 0x1e, 0x99, 0x33, + 0xfc, 0x7d, 0x93, 0x81, 0xe3, 0x0e, 0xf1, 0xd0, 0xac, 0x4f, 0x7f, 0x95, 0x05, 0xc5, 0xbd, 0x90, + 0xf9, 0x07, 0xcc, 0x56, 0x5f, 0x80, 0x52, 0x92, 0x8f, 0x83, 0x04, 0xaa, 0x28, 0x75, 0xa5, 0x51, + 0xde, 0xfd, 0x13, 0x4e, 0x0a, 0x3a, 0xc6, 0xc2, 0xa0, 0xdb, 0x4e, 0x02, 0x1c, 0x26, 0x6a, 0xd8, + 0xdb, 0x81, 0x8f, 0xed, 0x53, 0x82, 0xc5, 0x23, 0x22, 0x90, 0xa9, 0x9e, 0x0d, 0x6a, 0x99, 0x78, + 0x50, 0x03, 0x93, 0x98, 0x35, 0xa6, 0xaa, 0xfb, 0x20, 0xc7, 0x03, 0x82, 0x2b, 0x59, 0x49, 0xff, + 0x15, 0x2e, 0x6d, 0x17, 0x4c, 0x73, 0x6a, 0x06, 0x04, 0x9b, 0xdf, 0xa4, 0xcc, 0x5c, 0xb2, 0xb2, + 0x24, 0x41, 0x3d, 0x02, 0x05, 0x2e, 0x90, 0x88, 0x78, 0x65, 0x45, 0xb2, 0x1a, 0xb7, 0x60, 0x49, + 0xbd, 0xf9, 0x6d, 0x4a, 0x2b, 0x0c, 0xd7, 0x56, 0xca, 0xd1, 0xdf, 0x29, 0xa0, 0x9c, 0x2a, 0x0f, + 0x29, 0x17, 0xea, 0xc9, 0x5c, 0x35, 0xe0, 0xed, 0xaa, 0x91, 0xb8, 0x65, 0x2d, 0xd6, 0xd3, 0x9d, + 0x4a, 0xa3, 0xc8, 0x54, 0x25, 0xee, 0x83, 0x3c, 0x15, 0xc4, 0xe3, 0x95, 0x6c, 0x7d, 0xa5, 0x51, + 0xde, 0xd5, 0x6f, 0x4e, 0xdf, 0x5c, 0x4b, 0x71, 0xf9, 0x07, 0x89, 0xd1, 0x1a, 0xfa, 0xf5, 0x37, + 0xb9, 0x71, 0xda, 0x49, 0x79, 0xd4, 0xdf, 0x41, 0x29, 0x69, 0xb5, 0x13, 0xb9, 0x44, 0xa6, 0xbd, + 0x3a, 0x49, 0xa3, 0x99, 0xc6, 0xad, 0xb1, 0x42, 0x7d, 0x02, 0xb6, 0xb8, 0x40, 0xa1, 0xa0, 0x7e, + 0xfb, 0x7f, 0x82, 0x1c, 0x97, 0xfa, 0xa4, 0x49, 0x30, 0xf3, 0x1d, 0x2e, 0x7b, 0xb4, 0x62, 0xfe, + 0x14, 0x0f, 0x6a, 0x5b, 0xcd, 0xc5, 0x12, 0x6b, 0x99, 0x57, 0x3d, 0x01, 0x1b, 0x98, 0xf9, 0x38, + 0x0a, 0x43, 0xe2, 0xe3, 0xfe, 0x11, 0x73, 0x29, 0xee, 0xcb, 0x46, 0xad, 0x9a, 0x30, 0xcd, 0x66, + 0x63, 0x6f, 0x56, 0xf0, 0x79, 0x51, 0xd0, 0x9a, 0x07, 0xa9, 0xbf, 0x80, 0x22, 0x8f, 0x78, 0x40, + 0x7c, 0xa7, 0x92, 0xab, 0x2b, 0x8d, 0x92, 0x59, 0x8e, 0x07, 0xb5, 0x62, 0x73, 0x18, 0xb2, 0x46, + 0xff, 0x54, 0x04, 0xca, 0xa7, 0xcc, 0x3e, 0x26, 0x5e, 0xe0, 0x22, 0x41, 0x2a, 0x79, 0xd9, 0xc3, + 0xdf, 0xae, 0x29, 0xf4, 0xc1, 0x44, 0x2d, 0xe7, 0xee, 0xfb, 0x34, 0xd5, 0xf2, 0xd4, 0x0f, 0x6b, + 0x9a, 0xa9, 0x3e, 0x07, 0x55, 0x1e, 0x61, 0x4c, 0x38, 0x6f, 0x45, 0xee, 0x01, 0xb3, 0xf9, 0x3e, + 0xe5, 0x82, 0x85, 0xfd, 0x43, 0xea, 0x51, 0x51, 0x29, 0xd4, 0x95, 0x46, 0xde, 0xd4, 0xe2, 0x41, + 0xad, 0xda, 0x5c, 0xaa, 0xb2, 0xae, 0x21, 0xa8, 0x16, 0xd8, 0x6c, 0x21, 0xea, 0x12, 0x67, 0x8e, + 0x5d, 0x94, 0xec, 0x6a, 0x3c, 0xa8, 0x6d, 0xde, 0x5b, 0xa8, 0xb0, 0x96, 0x38, 0xf5, 0x0f, 0x0a, + 0x58, 0xbb, 0x72, 0x23, 0xd4, 0x87, 0xa0, 0x80, 0xb0, 0xa0, 0xbd, 0x64, 0x60, 0x92, 0x61, 0xdc, + 0x9e, 0xae, 0x51, 0xf2, 0xae, 0x4d, 0xee, 0xb8, 0x45, 0x5a, 0x24, 0x69, 0x05, 0x99, 0x5c, 0xa3, + 0xff, 0xa4, 0xd5, 0x4a, 0x11, 0xaa, 0x0b, 0xd6, 0x5d, 0xc4, 0xc5, 0x68, 0xd6, 0x8e, 0xa9, 0x47, + 0x64, 0x97, 0xae, 0x96, 0xfe, 0x9a, 0xeb, 0x93, 0x38, 0xcc, 0x1f, 0xe2, 0x41, 0x6d, 0xfd, 0x70, + 0x86, 0x63, 0xcd, 0x91, 0xf5, 0xf7, 0x0a, 0x98, 0xee, 0xce, 0x1d, 0x3c, 0x61, 0x4f, 0x41, 0x49, + 0x8c, 0x46, 0x2a, 0xfb, 0xd5, 0x23, 0x35, 0xbe, 0x8b, 0xe3, 0x79, 0x1a, 0xd3, 0xf4, 0xb7, 0x0a, + 0xf8, 0x6e, 0x46, 0x7f, 0x07, 0xe7, 0xf9, 0xf7, 0xca, 0x93, 0xfc, 0xf3, 0x82, 0xb3, 0xc8, 0x53, + 0x2c, 0x7b, 0x88, 0x4d, 0x78, 0x76, 0xa9, 0x65, 0xce, 0x2f, 0xb5, 0xcc, 0xc5, 0xa5, 0x96, 0x79, + 0x19, 0x6b, 0xca, 0x59, 0xac, 0x29, 0xe7, 0xb1, 0xa6, 0x5c, 0xc4, 0x9a, 0xf2, 0x31, 0xd6, 0x94, + 0xd7, 0x9f, 0xb4, 0xcc, 0xb3, 0xd2, 0xa8, 0x22, 0x5f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x20, 0x1c, + 0xcf, 0x94, 0xe7, 0x07, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/batch/v2alpha1/generated.proto b/vendor/k8s.io/api/batch/v2alpha1/generated.proto index e4de3644c..4321c3361 100644 --- a/vendor/k8s.io/api/batch/v2alpha1/generated.proto +++ b/vendor/k8s.io/api/batch/v2alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v2alpha1"; diff --git a/vendor/k8s.io/api/batch/v2alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/api/batch/v2alpha1/types_swagger_doc_generated.go index d166b807f..f448a92cf 100644 --- a/vendor/k8s.io/api/batch/v2alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/batch/v2alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v2alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CronJob = map[string]string{ "": "CronJob represents the configuration of a single cron job.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/api/batch/v2alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/api/batch/v2alpha1/zz_generated.deepcopy.go index d8352bfbe..bf0da8bf4 100644 --- a/vendor/k8s.io/api/batch/v2alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/batch/v2alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/certificates/v1beta1/generated.pb.go b/vendor/k8s.io/api/certificates/v1beta1/generated.pb.go index 7f704bf82..eda159900 100644 --- a/vendor/k8s.io/api/certificates/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/certificates/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1638,56 +1638,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 816 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x6f, 0x1b, 0x45, - 0x18, 0xf6, 0xfa, 0x2b, 0xf6, 0x38, 0xa4, 0xd5, 0x08, 0x55, 0x4b, 0xa4, 0xee, 0x46, 0x2b, 0x40, - 0xe1, 0xa3, 0xb3, 0xa4, 0x20, 0x88, 0x72, 0x40, 0xb0, 0xa1, 0x82, 0x88, 0x56, 0x48, 0xd3, 0x86, - 0x03, 0x42, 0xa2, 0xe3, 0xf5, 0xdb, 0xcd, 0xd4, 0xd9, 0x0f, 0x76, 0x66, 0x0d, 0xbe, 0xf5, 0x27, - 0x70, 0xe4, 0x82, 0xc4, 0x2f, 0xe1, 0x1c, 0x0e, 0x48, 0x3d, 0xf6, 0x80, 0x2c, 0x62, 0xfe, 0x45, - 0x4f, 0x68, 0x66, 0xc7, 0x5e, 0x63, 0xcb, 0x75, 0xd5, 0xdc, 0xf6, 0x7d, 0xde, 0xf7, 0x79, 0xde, - 0xcf, 0x59, 0xf4, 0xd5, 0xf0, 0x50, 0x10, 0x9e, 0xfa, 0xc3, 0xa2, 0x0f, 0x79, 0x02, 0x12, 0x84, - 0x3f, 0x82, 0x64, 0x90, 0xe6, 0xbe, 0x71, 0xb0, 0x8c, 0xfb, 0x21, 0xe4, 0x92, 0x3f, 0xe2, 0x21, - 0xd3, 0xee, 0x83, 0x3e, 0x48, 0x76, 0xe0, 0x47, 0x90, 0x40, 0xce, 0x24, 0x0c, 0x48, 0x96, 0xa7, - 0x32, 0xc5, 0x6e, 0x49, 0x20, 0x2c, 0xe3, 0x64, 0x91, 0x40, 0x0c, 0x61, 0xf7, 0x56, 0xc4, 0xe5, - 0x59, 0xd1, 0x27, 0x61, 0x1a, 0xfb, 0x51, 0x1a, 0xa5, 0xbe, 0xe6, 0xf5, 0x8b, 0x47, 0xda, 0xd2, - 0x86, 0xfe, 0x2a, 0xf5, 0x76, 0x3f, 0xaa, 0x0a, 0x88, 0x59, 0x78, 0xc6, 0x13, 0xc8, 0xc7, 0x7e, - 0x36, 0x8c, 0x14, 0x20, 0xfc, 0x18, 0x24, 0xf3, 0x47, 0x2b, 0x55, 0xec, 0xfa, 0xeb, 0x58, 0x79, - 0x91, 0x48, 0x1e, 0xc3, 0x0a, 0xe1, 0xe3, 0x4d, 0x04, 0x11, 0x9e, 0x41, 0xcc, 0x56, 0x78, 0x1f, - 0xae, 0xe3, 0x15, 0x92, 0x9f, 0xfb, 0x3c, 0x91, 0x42, 0xe6, 0xcb, 0x24, 0xef, 0xcf, 0x3a, 0x7a, - 0xe3, 0xb8, 0x9a, 0xcd, 0x7d, 0x1e, 0x25, 0x3c, 0x89, 0x28, 0xfc, 0x58, 0x80, 0x90, 0xf8, 0x21, - 0xea, 0xa8, 0xb6, 0x06, 0x4c, 0x32, 0xdb, 0xda, 0xb3, 0xf6, 0x7b, 0xb7, 0x3f, 0x20, 0xd5, 0x50, - 0xe7, 0x59, 0x48, 0x36, 0x8c, 0x14, 0x20, 0x88, 0x8a, 0x26, 0xa3, 0x03, 0xf2, 0x4d, 0xff, 0x31, - 0x84, 0xf2, 0x1e, 0x48, 0x16, 0xe0, 0x8b, 0x89, 0x5b, 0x9b, 0x4e, 0x5c, 0x54, 0x61, 0x74, 0xae, - 0x8a, 0x1f, 0xa2, 0xa6, 0xc8, 0x20, 0xb4, 0xeb, 0x5a, 0xfd, 0x53, 0xb2, 0x61, 0x65, 0x64, 0x6d, - 0xad, 0xf7, 0x33, 0x08, 0x83, 0x6d, 0x93, 0xab, 0xa9, 0x2c, 0xaa, 0x95, 0xf1, 0x19, 0x6a, 0x0b, - 0xc9, 0x64, 0x21, 0xec, 0x86, 0xce, 0xf1, 0xd9, 0x15, 0x72, 0x68, 0x9d, 0x60, 0xc7, 0x64, 0x69, - 0x97, 0x36, 0x35, 0xfa, 0xde, 0x6f, 0x75, 0xe4, 0xad, 0xe5, 0x1e, 0xa7, 0xc9, 0x80, 0x4b, 0x9e, - 0x26, 0xf8, 0x10, 0x35, 0xe5, 0x38, 0x03, 0x3d, 0xd0, 0x6e, 0xf0, 0xe6, 0xac, 0xe4, 0x07, 0xe3, - 0x0c, 0x9e, 0x4f, 0xdc, 0xd7, 0x97, 0xe3, 0x15, 0x4e, 0x35, 0x03, 0xbf, 0x8d, 0xda, 0x39, 0x30, - 0x91, 0x26, 0x7a, 0x5c, 0xdd, 0xaa, 0x10, 0xaa, 0x51, 0x6a, 0xbc, 0xf8, 0x1d, 0xb4, 0x15, 0x83, - 0x10, 0x2c, 0x02, 0xdd, 0x73, 0x37, 0xb8, 0x66, 0x02, 0xb7, 0xee, 0x95, 0x30, 0x9d, 0xf9, 0xf1, - 0x63, 0xb4, 0x73, 0xce, 0x84, 0x3c, 0xcd, 0x06, 0x4c, 0xc2, 0x03, 0x1e, 0x83, 0xdd, 0xd4, 0x53, - 0x7a, 0xf7, 0xe5, 0xf6, 0xac, 0x18, 0xc1, 0x0d, 0xa3, 0xbe, 0x73, 0xf7, 0x7f, 0x4a, 0x74, 0x49, - 0xd9, 0x9b, 0x58, 0xe8, 0xe6, 0xda, 0xf9, 0xdc, 0xe5, 0x42, 0xe2, 0xef, 0x57, 0xee, 0x8d, 0xbc, - 0x5c, 0x1d, 0x8a, 0xad, 0xaf, 0xed, 0xba, 0xa9, 0xa5, 0x33, 0x43, 0x16, 0x6e, 0xed, 0x07, 0xd4, - 0xe2, 0x12, 0x62, 0x61, 0xd7, 0xf7, 0x1a, 0xfb, 0xbd, 0xdb, 0x47, 0xaf, 0x7e, 0x08, 0xc1, 0x6b, - 0x26, 0x4d, 0xeb, 0x44, 0x09, 0xd2, 0x52, 0xd7, 0xfb, 0xa3, 0xf1, 0x82, 0x06, 0xd5, 0x49, 0xe2, - 0xb7, 0xd0, 0x56, 0x5e, 0x9a, 0xba, 0xbf, 0xed, 0xa0, 0xa7, 0xb6, 0x62, 0x22, 0xe8, 0xcc, 0x87, - 0xdf, 0x47, 0x9d, 0x42, 0x40, 0x9e, 0xb0, 0x18, 0xcc, 0xaa, 0xe7, 0x7d, 0x9d, 0x1a, 0x9c, 0xce, - 0x23, 0xf0, 0x4d, 0xd4, 0x28, 0xf8, 0xc0, 0xac, 0xba, 0x67, 0x02, 0x1b, 0xa7, 0x27, 0x5f, 0x50, - 0x85, 0x63, 0x0f, 0xb5, 0xa3, 0x3c, 0x2d, 0x32, 0x61, 0x37, 0xf7, 0x1a, 0xfb, 0xdd, 0x00, 0xa9, - 0x8b, 0xf9, 0x52, 0x23, 0xd4, 0x78, 0x30, 0x41, 0xed, 0x42, 0xdd, 0x83, 0xb0, 0x5b, 0x3a, 0xe6, - 0x86, 0x8a, 0x39, 0xd5, 0xc8, 0xf3, 0x89, 0xdb, 0xf9, 0x1a, 0xc6, 0xda, 0xa0, 0x26, 0x0a, 0x27, - 0xa8, 0x05, 0x3f, 0xcb, 0x9c, 0xd9, 0x6d, 0x3d, 0xca, 0x93, 0xab, 0xbd, 0x5b, 0x72, 0x47, 0x69, - 0xdd, 0x49, 0x64, 0x3e, 0xae, 0x26, 0xab, 0x31, 0x5a, 0xa6, 0xd9, 0x05, 0x84, 0xaa, 0x18, 0x7c, - 0x1d, 0x35, 0x86, 0x30, 0x2e, 0x1f, 0x10, 0x55, 0x9f, 0xf8, 0x73, 0xd4, 0x1a, 0xb1, 0xf3, 0x02, - 0xcc, 0x7f, 0xe4, 0xbd, 0x8d, 0xf5, 0x68, 0xb5, 0x6f, 0x15, 0x85, 0x96, 0xcc, 0xa3, 0xfa, 0xa1, - 0xe5, 0xfd, 0x65, 0x21, 0x77, 0xc3, 0xeb, 0xc7, 0x3f, 0x21, 0x14, 0xce, 0xde, 0xa6, 0xb0, 0x2d, - 0xdd, 0xff, 0xf1, 0xab, 0xf7, 0x3f, 0x7f, 0xe7, 0xd5, 0x8f, 0x72, 0x0e, 0x09, 0xba, 0x90, 0x0a, - 0x1f, 0xa0, 0xde, 0x82, 0xb4, 0xee, 0x74, 0x3b, 0xb8, 0x36, 0x9d, 0xb8, 0xbd, 0x05, 0x71, 0xba, - 0x18, 0xe3, 0x7d, 0x62, 0xc6, 0xa6, 0x1b, 0xc5, 0xee, 0xec, 0xfe, 0x2d, 0xbd, 0xe3, 0xee, 0xf2, - 0xfd, 0x1e, 0x75, 0x7e, 0xfd, 0xdd, 0xad, 0x3d, 0xf9, 0x7b, 0xaf, 0x16, 0xdc, 0xba, 0xb8, 0x74, - 0x6a, 0x4f, 0x2f, 0x9d, 0xda, 0xb3, 0x4b, 0xa7, 0xf6, 0x64, 0xea, 0x58, 0x17, 0x53, 0xc7, 0x7a, - 0x3a, 0x75, 0xac, 0x67, 0x53, 0xc7, 0xfa, 0x67, 0xea, 0x58, 0xbf, 0xfc, 0xeb, 0xd4, 0xbe, 0xdb, - 0x32, 0xdd, 0xfd, 0x17, 0x00, 0x00, 0xff, 0xff, 0x73, 0x7d, 0xca, 0x2a, 0xb4, 0x07, 0x00, 0x00, + // 804 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x8f, 0xdb, 0x44, + 0x18, 0x8e, 0xf3, 0xb5, 0xc9, 0x64, 0xd9, 0x56, 0x23, 0x54, 0x99, 0x95, 0x6a, 0xaf, 0x2c, 0x40, + 0xcb, 0x47, 0xc7, 0x6c, 0x85, 0x60, 0xb5, 0x07, 0x04, 0x5e, 0x2a, 0x58, 0xd1, 0x0a, 0x69, 0xda, + 0x70, 0x40, 0x48, 0x74, 0xe2, 0xbc, 0x75, 0xa6, 0xa9, 0x3f, 0xf0, 0x8c, 0x03, 0xb9, 0xf5, 0x27, + 0x70, 0xe4, 0x82, 0xc4, 0x2f, 0xe1, 0xbc, 0x1c, 0x90, 0x7a, 0xec, 0x01, 0x45, 0x6c, 0xf8, 0x17, + 0x3d, 0xa1, 0x19, 0x4f, 0xe2, 0x90, 0x55, 0x48, 0xd5, 0xbd, 0x79, 0x9e, 0xf7, 0x79, 0x9e, 0xf7, + 0x63, 0xde, 0x31, 0xfa, 0x72, 0x7c, 0x2c, 0x08, 0x4f, 0xfd, 0x71, 0x31, 0x80, 0x3c, 0x01, 0x09, + 0xc2, 0x9f, 0x40, 0x32, 0x4c, 0x73, 0xdf, 0x04, 0x58, 0xc6, 0xfd, 0x10, 0x72, 0xc9, 0x1f, 0xf1, + 0x90, 0xe9, 0xf0, 0xd1, 0x00, 0x24, 0x3b, 0xf2, 0x23, 0x48, 0x20, 0x67, 0x12, 0x86, 0x24, 0xcb, + 0x53, 0x99, 0x62, 0xb7, 0x14, 0x10, 0x96, 0x71, 0xb2, 0x2a, 0x20, 0x46, 0xb0, 0x7f, 0x2b, 0xe2, + 0x72, 0x54, 0x0c, 0x48, 0x98, 0xc6, 0x7e, 0x94, 0x46, 0xa9, 0xaf, 0x75, 0x83, 0xe2, 0x91, 0x3e, + 0xe9, 0x83, 0xfe, 0x2a, 0xfd, 0xf6, 0x3f, 0xac, 0x0a, 0x88, 0x59, 0x38, 0xe2, 0x09, 0xe4, 0x53, + 0x3f, 0x1b, 0x47, 0x0a, 0x10, 0x7e, 0x0c, 0x92, 0xf9, 0x93, 0x4b, 0x55, 0xec, 0xfb, 0x9b, 0x54, + 0x79, 0x91, 0x48, 0x1e, 0xc3, 0x25, 0xc1, 0x47, 0xdb, 0x04, 0x22, 0x1c, 0x41, 0xcc, 0xd6, 0x75, + 0xde, 0x1f, 0x75, 0xf4, 0xc6, 0x69, 0xd5, 0xe6, 0x7d, 0x1e, 0x25, 0x3c, 0x89, 0x28, 0xfc, 0x50, + 0x80, 0x90, 0xf8, 0x21, 0xea, 0xa8, 0x0a, 0x87, 0x4c, 0x32, 0xdb, 0x3a, 0xb0, 0x0e, 0x7b, 0xb7, + 0x3f, 0x20, 0xd5, 0x7c, 0x96, 0x89, 0x48, 0x36, 0x8e, 0x14, 0x20, 0x88, 0x62, 0x93, 0xc9, 0x11, + 0xf9, 0x7a, 0xf0, 0x18, 0x42, 0x79, 0x0f, 0x24, 0x0b, 0xf0, 0xf9, 0xcc, 0xad, 0xcd, 0x67, 0x2e, + 0xaa, 0x30, 0xba, 0x74, 0xc5, 0x0f, 0x51, 0x53, 0x64, 0x10, 0xda, 0x75, 0xed, 0xfe, 0x09, 0xd9, + 0x32, 0x7d, 0xb2, 0xb1, 0xd6, 0xfb, 0x19, 0x84, 0xc1, 0xae, 0xc9, 0xd5, 0x54, 0x27, 0xaa, 0x9d, + 0xf1, 0x08, 0xb5, 0x85, 0x64, 0xb2, 0x10, 0x76, 0x43, 0xe7, 0xf8, 0xf4, 0x0a, 0x39, 0xb4, 0x4f, + 0xb0, 0x67, 0xb2, 0xb4, 0xcb, 0x33, 0x35, 0xfe, 0xde, 0xaf, 0x75, 0xe4, 0x6d, 0xd4, 0x9e, 0xa6, + 0xc9, 0x90, 0x4b, 0x9e, 0x26, 0xf8, 0x18, 0x35, 0xe5, 0x34, 0x03, 0x3d, 0xd0, 0x6e, 0xf0, 0xe6, + 0xa2, 0xe4, 0x07, 0xd3, 0x0c, 0x5e, 0xcc, 0xdc, 0xd7, 0xd7, 0xf9, 0x0a, 0xa7, 0x5a, 0x81, 0xdf, + 0x46, 0xed, 0x1c, 0x98, 0x48, 0x13, 0x3d, 0xae, 0x6e, 0x55, 0x08, 0xd5, 0x28, 0x35, 0x51, 0xfc, + 0x0e, 0xda, 0x89, 0x41, 0x08, 0x16, 0x81, 0xee, 0xb9, 0x1b, 0x5c, 0x33, 0xc4, 0x9d, 0x7b, 0x25, + 0x4c, 0x17, 0x71, 0xfc, 0x18, 0xed, 0x3d, 0x61, 0x42, 0xf6, 0xb3, 0x21, 0x93, 0xf0, 0x80, 0xc7, + 0x60, 0x37, 0xf5, 0x94, 0xde, 0x7d, 0xb9, 0x7b, 0x56, 0x8a, 0xe0, 0x86, 0x71, 0xdf, 0xbb, 0xfb, + 0x1f, 0x27, 0xba, 0xe6, 0xec, 0xcd, 0x2c, 0x74, 0x73, 0xe3, 0x7c, 0xee, 0x72, 0x21, 0xf1, 0x77, + 0x97, 0xf6, 0x8d, 0xbc, 0x5c, 0x1d, 0x4a, 0xad, 0xb7, 0xed, 0xba, 0xa9, 0xa5, 0xb3, 0x40, 0x56, + 0x76, 0xed, 0x7b, 0xd4, 0xe2, 0x12, 0x62, 0x61, 0xd7, 0x0f, 0x1a, 0x87, 0xbd, 0xdb, 0x27, 0xaf, + 0xbe, 0x08, 0xc1, 0x6b, 0x26, 0x4d, 0xeb, 0x4c, 0x19, 0xd2, 0xd2, 0xd7, 0xfb, 0xbd, 0xf1, 0x3f, + 0x0d, 0xaa, 0x95, 0xc4, 0x6f, 0xa1, 0x9d, 0xbc, 0x3c, 0xea, 0xfe, 0x76, 0x83, 0x9e, 0xba, 0x15, + 0xc3, 0xa0, 0x8b, 0x18, 0x7e, 0x1f, 0x75, 0x0a, 0x01, 0x79, 0xc2, 0x62, 0x30, 0x57, 0xbd, 0xec, + 0xab, 0x6f, 0x70, 0xba, 0x64, 0xe0, 0x9b, 0xa8, 0x51, 0xf0, 0xa1, 0xb9, 0xea, 0x9e, 0x21, 0x36, + 0xfa, 0x67, 0x9f, 0x53, 0x85, 0x63, 0x0f, 0xb5, 0xa3, 0x3c, 0x2d, 0x32, 0x61, 0x37, 0x0f, 0x1a, + 0x87, 0xdd, 0x00, 0xa9, 0x8d, 0xf9, 0x42, 0x23, 0xd4, 0x44, 0x30, 0x41, 0xed, 0x42, 0xed, 0x83, + 0xb0, 0x5b, 0x9a, 0x73, 0x43, 0x71, 0xfa, 0x1a, 0x79, 0x31, 0x73, 0x3b, 0x5f, 0xc1, 0x54, 0x1f, + 0xa8, 0x61, 0xe1, 0x04, 0xb5, 0xe0, 0x27, 0x99, 0x33, 0xbb, 0xad, 0x47, 0x79, 0x76, 0xb5, 0x77, + 0x4b, 0xee, 0x28, 0xaf, 0x3b, 0x89, 0xcc, 0xa7, 0xd5, 0x64, 0x35, 0x46, 0xcb, 0x34, 0xfb, 0x80, + 0x50, 0xc5, 0xc1, 0xd7, 0x51, 0x63, 0x0c, 0xd3, 0xf2, 0x01, 0x51, 0xf5, 0x89, 0x3f, 0x43, 0xad, + 0x09, 0x7b, 0x52, 0x80, 0xf9, 0x8f, 0xbc, 0xb7, 0xb5, 0x1e, 0xed, 0xf6, 0x8d, 0x92, 0xd0, 0x52, + 0x79, 0x52, 0x3f, 0xb6, 0xbc, 0x3f, 0x2d, 0xe4, 0x6e, 0x79, 0xfd, 0xf8, 0x47, 0x84, 0xc2, 0xc5, + 0xdb, 0x14, 0xb6, 0xa5, 0xfb, 0x3f, 0x7d, 0xf5, 0xfe, 0x97, 0xef, 0xbc, 0xfa, 0x51, 0x2e, 0x21, + 0x41, 0x57, 0x52, 0xe1, 0x23, 0xd4, 0x5b, 0xb1, 0xd6, 0x9d, 0xee, 0x06, 0xd7, 0xe6, 0x33, 0xb7, + 0xb7, 0x62, 0x4e, 0x57, 0x39, 0xde, 0xc7, 0x66, 0x6c, 0xba, 0x51, 0xec, 0x2e, 0xf6, 0xdf, 0xd2, + 0x77, 0xdc, 0x5d, 0xdf, 0xdf, 0x93, 0xce, 0x2f, 0xbf, 0xb9, 0xb5, 0xa7, 0x7f, 0x1d, 0xd4, 0x82, + 0x5b, 0xe7, 0x17, 0x4e, 0xed, 0xd9, 0x85, 0x53, 0x7b, 0x7e, 0xe1, 0xd4, 0x9e, 0xce, 0x1d, 0xeb, + 0x7c, 0xee, 0x58, 0xcf, 0xe6, 0x8e, 0xf5, 0x7c, 0xee, 0x58, 0x7f, 0xcf, 0x1d, 0xeb, 0xe7, 0x7f, + 0x9c, 0xda, 0xb7, 0x3b, 0xa6, 0xbb, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x6b, 0x5b, 0xf9, + 0x7f, 0x07, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/certificates/v1beta1/generated.proto b/vendor/k8s.io/api/certificates/v1beta1/generated.proto index e3cd9000f..5200224a2 100644 --- a/vendor/k8s.io/api/certificates/v1beta1/generated.proto +++ b/vendor/k8s.io/api/certificates/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.certificates.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/api/certificates/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/certificates/v1beta1/types_swagger_doc_generated.go index 4fd91df06..f6a7e16ac 100644 --- a/vendor/k8s.io/api/certificates/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/certificates/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CertificateSigningRequest = map[string]string{ "": "Describes a certificate signing request", "spec": "The certificate request itself and any additional information.", diff --git a/vendor/k8s.io/api/certificates/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/certificates/v1beta1/zz_generated.deepcopy.go index 5848a255b..ffd24c30f 100644 --- a/vendor/k8s.io/api/certificates/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/certificates/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/core/v1/annotation_key_constants.go b/vendor/k8s.io/api/core/v1/annotation_key_constants.go index de4e3cee4..16a0cfced 100644 --- a/vendor/k8s.io/api/core/v1/annotation_key_constants.go +++ b/vendor/k8s.io/api/core/v1/annotation_key_constants.go @@ -45,24 +45,17 @@ const ( // to one container of a pod. SeccompContainerAnnotationKeyPrefix string = "container.seccomp.security.alpha.kubernetes.io/" + // SeccompProfileRuntimeDefault represents the default seccomp profile used by container runtime. + SeccompProfileRuntimeDefault string = "runtime/default" + + // DeprecatedSeccompProfileDockerDefault represents the default seccomp profile used by docker. + // This is now deprecated and should be replaced by SeccompProfileRuntimeDefault. + DeprecatedSeccompProfileDockerDefault string = "docker/default" + // PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized) // in the Annotations of a Node. PreferAvoidPodsAnnotationKey string = "scheduler.alpha.kubernetes.io/preferAvoidPods" - // SysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Only a limited set of whitelisted and isolated sysctls is supported by - // the kubelet. Pods with other sysctls will fail to launch. - SysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/sysctls" - - // UnsafeSysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Unsafe sysctls must be explicitly enabled for a kubelet. They are properly - // namespaced to a pod or a container, but their isolation is usually unclear or weak. Their use - // is at-your-own-risk. Pods that attempt to set an unsafe sysctl that is not enabled for a kubelet - // will fail to launch. - UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls" - // ObjectTTLAnnotations represents a suggestion for kubelet for how long it can cache // an object (e.g. secret, config map) before fetching it again from apiserver. // This annotation can be attached to node. diff --git a/vendor/k8s.io/api/core/v1/generated.pb.go b/vendor/k8s.io/api/core/v1/generated.pb.go index 85c7b634b..a809ceb0a 100644 --- a/vendor/k8s.io/api/core/v1/generated.pb.go +++ b/vendor/k8s.io/api/core/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -37,6 +37,7 @@ limitations under the License. Capabilities CephFSPersistentVolumeSource CephFSVolumeSource + CinderPersistentVolumeSource CinderVolumeSource ClientIPConfig ComponentCondition @@ -46,6 +47,7 @@ limitations under the License. ConfigMapEnvSource ConfigMapKeySelector ConfigMapList + ConfigMapNodeConfigSource ConfigMapProjection ConfigMapVolumeSource Container @@ -57,7 +59,6 @@ limitations under the License. ContainerStateWaiting ContainerStatus DaemonEndpoint - DeleteOptions DownwardAPIProjection DownwardAPIVolumeFile DownwardAPIVolumeSource @@ -96,7 +97,6 @@ limitations under the License. LimitRangeList LimitRangeSpec List - ListOptions LoadBalancerIngress LoadBalancerStatus LocalObjectReference @@ -111,6 +111,7 @@ limitations under the License. NodeAffinity NodeCondition NodeConfigSource + NodeConfigStatus NodeDaemonEndpoints NodeList NodeProxyOptions @@ -122,7 +123,6 @@ limitations under the License. NodeStatus NodeSystemInfo ObjectFieldSelector - ObjectMeta ObjectReference PersistentVolume PersistentVolumeClaim @@ -149,6 +149,7 @@ limitations under the License. PodLogOptions PodPortForwardOptions PodProxyOptions + PodReadinessGate PodSecurityContext PodSignature PodSpec @@ -181,6 +182,8 @@ limitations under the License. SELinuxOptions ScaleIOPersistentVolumeSource ScaleIOVolumeSource + ScopeSelector + ScopedResourceSelectorRequirement Secret SecretEnvSource SecretKeySelector @@ -193,6 +196,7 @@ limitations under the License. Service ServiceAccount ServiceAccountList + ServiceAccountTokenProjection ServiceList ServicePort ServiceProxyOptions @@ -205,6 +209,8 @@ limitations under the License. TCPSocketAction Taint Toleration + TopologySelectorLabelRequirement + TopologySelectorTerm Volume VolumeDevice VolumeMount @@ -300,255 +306,259 @@ func (m *CephFSVolumeSource) Reset() { *m = CephFSVolumeSourc func (*CephFSVolumeSource) ProtoMessage() {} func (*CephFSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } +func (m *CinderPersistentVolumeSource) Reset() { *m = CinderPersistentVolumeSource{} } +func (*CinderPersistentVolumeSource) ProtoMessage() {} +func (*CinderPersistentVolumeSource) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{12} +} + func (m *CinderVolumeSource) Reset() { *m = CinderVolumeSource{} } func (*CinderVolumeSource) ProtoMessage() {} -func (*CinderVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } +func (*CinderVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (m *ClientIPConfig) Reset() { *m = ClientIPConfig{} } func (*ClientIPConfig) ProtoMessage() {} -func (*ClientIPConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } +func (*ClientIPConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } func (m *ComponentCondition) Reset() { *m = ComponentCondition{} } func (*ComponentCondition) ProtoMessage() {} -func (*ComponentCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } +func (*ComponentCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } func (m *ComponentStatus) Reset() { *m = ComponentStatus{} } func (*ComponentStatus) ProtoMessage() {} -func (*ComponentStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } +func (*ComponentStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } func (m *ComponentStatusList) Reset() { *m = ComponentStatusList{} } func (*ComponentStatusList) ProtoMessage() {} -func (*ComponentStatusList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } +func (*ComponentStatusList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } func (m *ConfigMap) Reset() { *m = ConfigMap{} } func (*ConfigMap) ProtoMessage() {} -func (*ConfigMap) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } +func (*ConfigMap) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } func (m *ConfigMapEnvSource) Reset() { *m = ConfigMapEnvSource{} } func (*ConfigMapEnvSource) ProtoMessage() {} -func (*ConfigMapEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } +func (*ConfigMapEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } func (m *ConfigMapKeySelector) Reset() { *m = ConfigMapKeySelector{} } func (*ConfigMapKeySelector) ProtoMessage() {} -func (*ConfigMapKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } +func (*ConfigMapKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } func (m *ConfigMapList) Reset() { *m = ConfigMapList{} } func (*ConfigMapList) ProtoMessage() {} -func (*ConfigMapList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } +func (*ConfigMapList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } + +func (m *ConfigMapNodeConfigSource) Reset() { *m = ConfigMapNodeConfigSource{} } +func (*ConfigMapNodeConfigSource) ProtoMessage() {} +func (*ConfigMapNodeConfigSource) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{22} +} func (m *ConfigMapProjection) Reset() { *m = ConfigMapProjection{} } func (*ConfigMapProjection) ProtoMessage() {} -func (*ConfigMapProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } +func (*ConfigMapProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } func (m *ConfigMapVolumeSource) Reset() { *m = ConfigMapVolumeSource{} } func (*ConfigMapVolumeSource) ProtoMessage() {} -func (*ConfigMapVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} } +func (*ConfigMapVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } func (m *Container) Reset() { *m = Container{} } func (*Container) ProtoMessage() {} -func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } +func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } func (m *ContainerImage) Reset() { *m = ContainerImage{} } func (*ContainerImage) ProtoMessage() {} -func (*ContainerImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } +func (*ContainerImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } func (m *ContainerPort) Reset() { *m = ContainerPort{} } func (*ContainerPort) ProtoMessage() {} -func (*ContainerPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } +func (*ContainerPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } func (m *ContainerState) Reset() { *m = ContainerState{} } func (*ContainerState) ProtoMessage() {} -func (*ContainerState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } +func (*ContainerState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } func (m *ContainerStateRunning) Reset() { *m = ContainerStateRunning{} } func (*ContainerStateRunning) ProtoMessage() {} -func (*ContainerStateRunning) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } +func (*ContainerStateRunning) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } func (m *ContainerStateTerminated) Reset() { *m = ContainerStateTerminated{} } func (*ContainerStateTerminated) ProtoMessage() {} func (*ContainerStateTerminated) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{28} + return fileDescriptorGenerated, []int{30} } func (m *ContainerStateWaiting) Reset() { *m = ContainerStateWaiting{} } func (*ContainerStateWaiting) ProtoMessage() {} -func (*ContainerStateWaiting) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } +func (*ContainerStateWaiting) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } func (m *ContainerStatus) Reset() { *m = ContainerStatus{} } func (*ContainerStatus) ProtoMessage() {} -func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } +func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } func (m *DaemonEndpoint) Reset() { *m = DaemonEndpoint{} } func (*DaemonEndpoint) ProtoMessage() {} -func (*DaemonEndpoint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } - -func (m *DeleteOptions) Reset() { *m = DeleteOptions{} } -func (*DeleteOptions) ProtoMessage() {} -func (*DeleteOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } +func (*DaemonEndpoint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } func (m *DownwardAPIProjection) Reset() { *m = DownwardAPIProjection{} } func (*DownwardAPIProjection) ProtoMessage() {} -func (*DownwardAPIProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } +func (*DownwardAPIProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } func (m *DownwardAPIVolumeFile) Reset() { *m = DownwardAPIVolumeFile{} } func (*DownwardAPIVolumeFile) ProtoMessage() {} -func (*DownwardAPIVolumeFile) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } +func (*DownwardAPIVolumeFile) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{35} } func (m *DownwardAPIVolumeSource) Reset() { *m = DownwardAPIVolumeSource{} } func (*DownwardAPIVolumeSource) ProtoMessage() {} func (*DownwardAPIVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{35} + return fileDescriptorGenerated, []int{36} } func (m *EmptyDirVolumeSource) Reset() { *m = EmptyDirVolumeSource{} } func (*EmptyDirVolumeSource) ProtoMessage() {} -func (*EmptyDirVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{36} } +func (*EmptyDirVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{37} } func (m *EndpointAddress) Reset() { *m = EndpointAddress{} } func (*EndpointAddress) ProtoMessage() {} -func (*EndpointAddress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{37} } +func (*EndpointAddress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{38} } func (m *EndpointPort) Reset() { *m = EndpointPort{} } func (*EndpointPort) ProtoMessage() {} -func (*EndpointPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{38} } +func (*EndpointPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{39} } func (m *EndpointSubset) Reset() { *m = EndpointSubset{} } func (*EndpointSubset) ProtoMessage() {} -func (*EndpointSubset) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{39} } +func (*EndpointSubset) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{40} } func (m *Endpoints) Reset() { *m = Endpoints{} } func (*Endpoints) ProtoMessage() {} -func (*Endpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{40} } +func (*Endpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{41} } func (m *EndpointsList) Reset() { *m = EndpointsList{} } func (*EndpointsList) ProtoMessage() {} -func (*EndpointsList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{41} } +func (*EndpointsList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{42} } func (m *EnvFromSource) Reset() { *m = EnvFromSource{} } func (*EnvFromSource) ProtoMessage() {} -func (*EnvFromSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{42} } +func (*EnvFromSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{43} } func (m *EnvVar) Reset() { *m = EnvVar{} } func (*EnvVar) ProtoMessage() {} -func (*EnvVar) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{43} } +func (*EnvVar) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{44} } func (m *EnvVarSource) Reset() { *m = EnvVarSource{} } func (*EnvVarSource) ProtoMessage() {} -func (*EnvVarSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{44} } +func (*EnvVarSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{45} } func (m *Event) Reset() { *m = Event{} } func (*Event) ProtoMessage() {} -func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{45} } +func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{46} } func (m *EventList) Reset() { *m = EventList{} } func (*EventList) ProtoMessage() {} -func (*EventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{46} } +func (*EventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{47} } func (m *EventSeries) Reset() { *m = EventSeries{} } func (*EventSeries) ProtoMessage() {} -func (*EventSeries) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{47} } +func (*EventSeries) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{48} } func (m *EventSource) Reset() { *m = EventSource{} } func (*EventSource) ProtoMessage() {} -func (*EventSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{48} } +func (*EventSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{49} } func (m *ExecAction) Reset() { *m = ExecAction{} } func (*ExecAction) ProtoMessage() {} -func (*ExecAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{49} } +func (*ExecAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{50} } func (m *FCVolumeSource) Reset() { *m = FCVolumeSource{} } func (*FCVolumeSource) ProtoMessage() {} -func (*FCVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{50} } +func (*FCVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{51} } func (m *FlexPersistentVolumeSource) Reset() { *m = FlexPersistentVolumeSource{} } func (*FlexPersistentVolumeSource) ProtoMessage() {} func (*FlexPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{51} + return fileDescriptorGenerated, []int{52} } func (m *FlexVolumeSource) Reset() { *m = FlexVolumeSource{} } func (*FlexVolumeSource) ProtoMessage() {} -func (*FlexVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{52} } +func (*FlexVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{53} } func (m *FlockerVolumeSource) Reset() { *m = FlockerVolumeSource{} } func (*FlockerVolumeSource) ProtoMessage() {} -func (*FlockerVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{53} } +func (*FlockerVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{54} } func (m *GCEPersistentDiskVolumeSource) Reset() { *m = GCEPersistentDiskVolumeSource{} } func (*GCEPersistentDiskVolumeSource) ProtoMessage() {} func (*GCEPersistentDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{54} + return fileDescriptorGenerated, []int{55} } func (m *GitRepoVolumeSource) Reset() { *m = GitRepoVolumeSource{} } func (*GitRepoVolumeSource) ProtoMessage() {} -func (*GitRepoVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{55} } +func (*GitRepoVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{56} } func (m *GlusterfsVolumeSource) Reset() { *m = GlusterfsVolumeSource{} } func (*GlusterfsVolumeSource) ProtoMessage() {} -func (*GlusterfsVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{56} } +func (*GlusterfsVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{57} } func (m *HTTPGetAction) Reset() { *m = HTTPGetAction{} } func (*HTTPGetAction) ProtoMessage() {} -func (*HTTPGetAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{57} } +func (*HTTPGetAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{58} } func (m *HTTPHeader) Reset() { *m = HTTPHeader{} } func (*HTTPHeader) ProtoMessage() {} -func (*HTTPHeader) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{58} } +func (*HTTPHeader) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{59} } func (m *Handler) Reset() { *m = Handler{} } func (*Handler) ProtoMessage() {} -func (*Handler) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{59} } +func (*Handler) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{60} } func (m *HostAlias) Reset() { *m = HostAlias{} } func (*HostAlias) ProtoMessage() {} -func (*HostAlias) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{60} } +func (*HostAlias) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{61} } func (m *HostPathVolumeSource) Reset() { *m = HostPathVolumeSource{} } func (*HostPathVolumeSource) ProtoMessage() {} -func (*HostPathVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{61} } +func (*HostPathVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{62} } func (m *ISCSIPersistentVolumeSource) Reset() { *m = ISCSIPersistentVolumeSource{} } func (*ISCSIPersistentVolumeSource) ProtoMessage() {} func (*ISCSIPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{62} + return fileDescriptorGenerated, []int{63} } func (m *ISCSIVolumeSource) Reset() { *m = ISCSIVolumeSource{} } func (*ISCSIVolumeSource) ProtoMessage() {} -func (*ISCSIVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{63} } +func (*ISCSIVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{64} } func (m *KeyToPath) Reset() { *m = KeyToPath{} } func (*KeyToPath) ProtoMessage() {} -func (*KeyToPath) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{64} } +func (*KeyToPath) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{65} } func (m *Lifecycle) Reset() { *m = Lifecycle{} } func (*Lifecycle) ProtoMessage() {} -func (*Lifecycle) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{65} } +func (*Lifecycle) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{66} } func (m *LimitRange) Reset() { *m = LimitRange{} } func (*LimitRange) ProtoMessage() {} -func (*LimitRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{66} } +func (*LimitRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{67} } func (m *LimitRangeItem) Reset() { *m = LimitRangeItem{} } func (*LimitRangeItem) ProtoMessage() {} -func (*LimitRangeItem) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{67} } +func (*LimitRangeItem) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{68} } func (m *LimitRangeList) Reset() { *m = LimitRangeList{} } func (*LimitRangeList) ProtoMessage() {} -func (*LimitRangeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{68} } +func (*LimitRangeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{69} } func (m *LimitRangeSpec) Reset() { *m = LimitRangeSpec{} } func (*LimitRangeSpec) ProtoMessage() {} -func (*LimitRangeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{69} } +func (*LimitRangeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{70} } func (m *List) Reset() { *m = List{} } func (*List) ProtoMessage() {} -func (*List) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{70} } - -func (m *ListOptions) Reset() { *m = ListOptions{} } -func (*ListOptions) ProtoMessage() {} -func (*ListOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{71} } +func (*List) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{71} } func (m *LoadBalancerIngress) Reset() { *m = LoadBalancerIngress{} } func (*LoadBalancerIngress) ProtoMessage() {} @@ -606,55 +616,55 @@ func (m *NodeConfigSource) Reset() { *m = NodeConfigSource{} func (*NodeConfigSource) ProtoMessage() {} func (*NodeConfigSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{85} } +func (m *NodeConfigStatus) Reset() { *m = NodeConfigStatus{} } +func (*NodeConfigStatus) ProtoMessage() {} +func (*NodeConfigStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{86} } + func (m *NodeDaemonEndpoints) Reset() { *m = NodeDaemonEndpoints{} } func (*NodeDaemonEndpoints) ProtoMessage() {} -func (*NodeDaemonEndpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{86} } +func (*NodeDaemonEndpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{87} } func (m *NodeList) Reset() { *m = NodeList{} } func (*NodeList) ProtoMessage() {} -func (*NodeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{87} } +func (*NodeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{88} } func (m *NodeProxyOptions) Reset() { *m = NodeProxyOptions{} } func (*NodeProxyOptions) ProtoMessage() {} -func (*NodeProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{88} } +func (*NodeProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{89} } func (m *NodeResources) Reset() { *m = NodeResources{} } func (*NodeResources) ProtoMessage() {} -func (*NodeResources) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{89} } +func (*NodeResources) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{90} } func (m *NodeSelector) Reset() { *m = NodeSelector{} } func (*NodeSelector) ProtoMessage() {} -func (*NodeSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{90} } +func (*NodeSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{91} } func (m *NodeSelectorRequirement) Reset() { *m = NodeSelectorRequirement{} } func (*NodeSelectorRequirement) ProtoMessage() {} func (*NodeSelectorRequirement) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{91} + return fileDescriptorGenerated, []int{92} } func (m *NodeSelectorTerm) Reset() { *m = NodeSelectorTerm{} } func (*NodeSelectorTerm) ProtoMessage() {} -func (*NodeSelectorTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{92} } +func (*NodeSelectorTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{93} } func (m *NodeSpec) Reset() { *m = NodeSpec{} } func (*NodeSpec) ProtoMessage() {} -func (*NodeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{93} } +func (*NodeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{94} } func (m *NodeStatus) Reset() { *m = NodeStatus{} } func (*NodeStatus) ProtoMessage() {} -func (*NodeStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{94} } +func (*NodeStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{95} } func (m *NodeSystemInfo) Reset() { *m = NodeSystemInfo{} } func (*NodeSystemInfo) ProtoMessage() {} -func (*NodeSystemInfo) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{95} } +func (*NodeSystemInfo) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{96} } func (m *ObjectFieldSelector) Reset() { *m = ObjectFieldSelector{} } func (*ObjectFieldSelector) ProtoMessage() {} -func (*ObjectFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{96} } - -func (m *ObjectMeta) Reset() { *m = ObjectMeta{} } -func (*ObjectMeta) ProtoMessage() {} -func (*ObjectMeta) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{97} } +func (*ObjectFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{97} } func (m *ObjectReference) Reset() { *m = ObjectReference{} } func (*ObjectReference) ProtoMessage() {} @@ -776,280 +786,310 @@ func (m *PodProxyOptions) Reset() { *m = PodProxyOptions{} } func (*PodProxyOptions) ProtoMessage() {} func (*PodProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{123} } +func (m *PodReadinessGate) Reset() { *m = PodReadinessGate{} } +func (*PodReadinessGate) ProtoMessage() {} +func (*PodReadinessGate) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{124} } + func (m *PodSecurityContext) Reset() { *m = PodSecurityContext{} } func (*PodSecurityContext) ProtoMessage() {} -func (*PodSecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{124} } +func (*PodSecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{125} } func (m *PodSignature) Reset() { *m = PodSignature{} } func (*PodSignature) ProtoMessage() {} -func (*PodSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{125} } +func (*PodSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{126} } func (m *PodSpec) Reset() { *m = PodSpec{} } func (*PodSpec) ProtoMessage() {} -func (*PodSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{126} } +func (*PodSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{127} } func (m *PodStatus) Reset() { *m = PodStatus{} } func (*PodStatus) ProtoMessage() {} -func (*PodStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{127} } +func (*PodStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{128} } func (m *PodStatusResult) Reset() { *m = PodStatusResult{} } func (*PodStatusResult) ProtoMessage() {} -func (*PodStatusResult) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{128} } +func (*PodStatusResult) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{129} } func (m *PodTemplate) Reset() { *m = PodTemplate{} } func (*PodTemplate) ProtoMessage() {} -func (*PodTemplate) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{129} } +func (*PodTemplate) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{130} } func (m *PodTemplateList) Reset() { *m = PodTemplateList{} } func (*PodTemplateList) ProtoMessage() {} -func (*PodTemplateList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{130} } +func (*PodTemplateList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{131} } func (m *PodTemplateSpec) Reset() { *m = PodTemplateSpec{} } func (*PodTemplateSpec) ProtoMessage() {} -func (*PodTemplateSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{131} } +func (*PodTemplateSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{132} } func (m *PortworxVolumeSource) Reset() { *m = PortworxVolumeSource{} } func (*PortworxVolumeSource) ProtoMessage() {} -func (*PortworxVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{132} } +func (*PortworxVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{133} } func (m *Preconditions) Reset() { *m = Preconditions{} } func (*Preconditions) ProtoMessage() {} -func (*Preconditions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{133} } +func (*Preconditions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{134} } func (m *PreferAvoidPodsEntry) Reset() { *m = PreferAvoidPodsEntry{} } func (*PreferAvoidPodsEntry) ProtoMessage() {} -func (*PreferAvoidPodsEntry) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{134} } +func (*PreferAvoidPodsEntry) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{135} } func (m *PreferredSchedulingTerm) Reset() { *m = PreferredSchedulingTerm{} } func (*PreferredSchedulingTerm) ProtoMessage() {} func (*PreferredSchedulingTerm) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{135} + return fileDescriptorGenerated, []int{136} } func (m *Probe) Reset() { *m = Probe{} } func (*Probe) ProtoMessage() {} -func (*Probe) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{136} } +func (*Probe) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{137} } func (m *ProjectedVolumeSource) Reset() { *m = ProjectedVolumeSource{} } func (*ProjectedVolumeSource) ProtoMessage() {} -func (*ProjectedVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{137} } +func (*ProjectedVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{138} } func (m *QuobyteVolumeSource) Reset() { *m = QuobyteVolumeSource{} } func (*QuobyteVolumeSource) ProtoMessage() {} -func (*QuobyteVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{138} } +func (*QuobyteVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{139} } func (m *RBDPersistentVolumeSource) Reset() { *m = RBDPersistentVolumeSource{} } func (*RBDPersistentVolumeSource) ProtoMessage() {} func (*RBDPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{139} + return fileDescriptorGenerated, []int{140} } func (m *RBDVolumeSource) Reset() { *m = RBDVolumeSource{} } func (*RBDVolumeSource) ProtoMessage() {} -func (*RBDVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{140} } +func (*RBDVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{141} } func (m *RangeAllocation) Reset() { *m = RangeAllocation{} } func (*RangeAllocation) ProtoMessage() {} -func (*RangeAllocation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{141} } +func (*RangeAllocation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{142} } func (m *ReplicationController) Reset() { *m = ReplicationController{} } func (*ReplicationController) ProtoMessage() {} -func (*ReplicationController) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{142} } +func (*ReplicationController) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{143} } func (m *ReplicationControllerCondition) Reset() { *m = ReplicationControllerCondition{} } func (*ReplicationControllerCondition) ProtoMessage() {} func (*ReplicationControllerCondition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{143} + return fileDescriptorGenerated, []int{144} } func (m *ReplicationControllerList) Reset() { *m = ReplicationControllerList{} } func (*ReplicationControllerList) ProtoMessage() {} func (*ReplicationControllerList) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{144} + return fileDescriptorGenerated, []int{145} } func (m *ReplicationControllerSpec) Reset() { *m = ReplicationControllerSpec{} } func (*ReplicationControllerSpec) ProtoMessage() {} func (*ReplicationControllerSpec) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{145} + return fileDescriptorGenerated, []int{146} } func (m *ReplicationControllerStatus) Reset() { *m = ReplicationControllerStatus{} } func (*ReplicationControllerStatus) ProtoMessage() {} func (*ReplicationControllerStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{146} + return fileDescriptorGenerated, []int{147} } func (m *ResourceFieldSelector) Reset() { *m = ResourceFieldSelector{} } func (*ResourceFieldSelector) ProtoMessage() {} -func (*ResourceFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{147} } +func (*ResourceFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{148} } func (m *ResourceQuota) Reset() { *m = ResourceQuota{} } func (*ResourceQuota) ProtoMessage() {} -func (*ResourceQuota) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{148} } +func (*ResourceQuota) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{149} } func (m *ResourceQuotaList) Reset() { *m = ResourceQuotaList{} } func (*ResourceQuotaList) ProtoMessage() {} -func (*ResourceQuotaList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{149} } +func (*ResourceQuotaList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{150} } func (m *ResourceQuotaSpec) Reset() { *m = ResourceQuotaSpec{} } func (*ResourceQuotaSpec) ProtoMessage() {} -func (*ResourceQuotaSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{150} } +func (*ResourceQuotaSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{151} } func (m *ResourceQuotaStatus) Reset() { *m = ResourceQuotaStatus{} } func (*ResourceQuotaStatus) ProtoMessage() {} -func (*ResourceQuotaStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{151} } +func (*ResourceQuotaStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{152} } func (m *ResourceRequirements) Reset() { *m = ResourceRequirements{} } func (*ResourceRequirements) ProtoMessage() {} -func (*ResourceRequirements) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{152} } +func (*ResourceRequirements) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{153} } func (m *SELinuxOptions) Reset() { *m = SELinuxOptions{} } func (*SELinuxOptions) ProtoMessage() {} -func (*SELinuxOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{153} } +func (*SELinuxOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{154} } func (m *ScaleIOPersistentVolumeSource) Reset() { *m = ScaleIOPersistentVolumeSource{} } func (*ScaleIOPersistentVolumeSource) ProtoMessage() {} func (*ScaleIOPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{154} + return fileDescriptorGenerated, []int{155} } func (m *ScaleIOVolumeSource) Reset() { *m = ScaleIOVolumeSource{} } func (*ScaleIOVolumeSource) ProtoMessage() {} -func (*ScaleIOVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{155} } +func (*ScaleIOVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{156} } + +func (m *ScopeSelector) Reset() { *m = ScopeSelector{} } +func (*ScopeSelector) ProtoMessage() {} +func (*ScopeSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{157} } + +func (m *ScopedResourceSelectorRequirement) Reset() { *m = ScopedResourceSelectorRequirement{} } +func (*ScopedResourceSelectorRequirement) ProtoMessage() {} +func (*ScopedResourceSelectorRequirement) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{158} +} func (m *Secret) Reset() { *m = Secret{} } func (*Secret) ProtoMessage() {} -func (*Secret) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{156} } +func (*Secret) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{159} } func (m *SecretEnvSource) Reset() { *m = SecretEnvSource{} } func (*SecretEnvSource) ProtoMessage() {} -func (*SecretEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{157} } +func (*SecretEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{160} } func (m *SecretKeySelector) Reset() { *m = SecretKeySelector{} } func (*SecretKeySelector) ProtoMessage() {} -func (*SecretKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{158} } +func (*SecretKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{161} } func (m *SecretList) Reset() { *m = SecretList{} } func (*SecretList) ProtoMessage() {} -func (*SecretList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{159} } +func (*SecretList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{162} } func (m *SecretProjection) Reset() { *m = SecretProjection{} } func (*SecretProjection) ProtoMessage() {} -func (*SecretProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{160} } +func (*SecretProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{163} } func (m *SecretReference) Reset() { *m = SecretReference{} } func (*SecretReference) ProtoMessage() {} -func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{161} } +func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{164} } func (m *SecretVolumeSource) Reset() { *m = SecretVolumeSource{} } func (*SecretVolumeSource) ProtoMessage() {} -func (*SecretVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{162} } +func (*SecretVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{165} } func (m *SecurityContext) Reset() { *m = SecurityContext{} } func (*SecurityContext) ProtoMessage() {} -func (*SecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{163} } +func (*SecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{166} } func (m *SerializedReference) Reset() { *m = SerializedReference{} } func (*SerializedReference) ProtoMessage() {} -func (*SerializedReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{164} } +func (*SerializedReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{167} } func (m *Service) Reset() { *m = Service{} } func (*Service) ProtoMessage() {} -func (*Service) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{165} } +func (*Service) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{168} } func (m *ServiceAccount) Reset() { *m = ServiceAccount{} } func (*ServiceAccount) ProtoMessage() {} -func (*ServiceAccount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{166} } +func (*ServiceAccount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{169} } func (m *ServiceAccountList) Reset() { *m = ServiceAccountList{} } func (*ServiceAccountList) ProtoMessage() {} -func (*ServiceAccountList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{167} } +func (*ServiceAccountList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{170} } + +func (m *ServiceAccountTokenProjection) Reset() { *m = ServiceAccountTokenProjection{} } +func (*ServiceAccountTokenProjection) ProtoMessage() {} +func (*ServiceAccountTokenProjection) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{171} +} func (m *ServiceList) Reset() { *m = ServiceList{} } func (*ServiceList) ProtoMessage() {} -func (*ServiceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{168} } +func (*ServiceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{172} } func (m *ServicePort) Reset() { *m = ServicePort{} } func (*ServicePort) ProtoMessage() {} -func (*ServicePort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{169} } +func (*ServicePort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{173} } func (m *ServiceProxyOptions) Reset() { *m = ServiceProxyOptions{} } func (*ServiceProxyOptions) ProtoMessage() {} -func (*ServiceProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{170} } +func (*ServiceProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{174} } func (m *ServiceSpec) Reset() { *m = ServiceSpec{} } func (*ServiceSpec) ProtoMessage() {} -func (*ServiceSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{171} } +func (*ServiceSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{175} } func (m *ServiceStatus) Reset() { *m = ServiceStatus{} } func (*ServiceStatus) ProtoMessage() {} -func (*ServiceStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{172} } +func (*ServiceStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{176} } func (m *SessionAffinityConfig) Reset() { *m = SessionAffinityConfig{} } func (*SessionAffinityConfig) ProtoMessage() {} -func (*SessionAffinityConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{173} } +func (*SessionAffinityConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{177} } func (m *StorageOSPersistentVolumeSource) Reset() { *m = StorageOSPersistentVolumeSource{} } func (*StorageOSPersistentVolumeSource) ProtoMessage() {} func (*StorageOSPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{174} + return fileDescriptorGenerated, []int{178} } func (m *StorageOSVolumeSource) Reset() { *m = StorageOSVolumeSource{} } func (*StorageOSVolumeSource) ProtoMessage() {} -func (*StorageOSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{175} } +func (*StorageOSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{179} } func (m *Sysctl) Reset() { *m = Sysctl{} } func (*Sysctl) ProtoMessage() {} -func (*Sysctl) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{176} } +func (*Sysctl) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{180} } func (m *TCPSocketAction) Reset() { *m = TCPSocketAction{} } func (*TCPSocketAction) ProtoMessage() {} -func (*TCPSocketAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{177} } +func (*TCPSocketAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{181} } func (m *Taint) Reset() { *m = Taint{} } func (*Taint) ProtoMessage() {} -func (*Taint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{178} } +func (*Taint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{182} } func (m *Toleration) Reset() { *m = Toleration{} } func (*Toleration) ProtoMessage() {} -func (*Toleration) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{179} } +func (*Toleration) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{183} } + +func (m *TopologySelectorLabelRequirement) Reset() { *m = TopologySelectorLabelRequirement{} } +func (*TopologySelectorLabelRequirement) ProtoMessage() {} +func (*TopologySelectorLabelRequirement) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{184} +} + +func (m *TopologySelectorTerm) Reset() { *m = TopologySelectorTerm{} } +func (*TopologySelectorTerm) ProtoMessage() {} +func (*TopologySelectorTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{185} } func (m *Volume) Reset() { *m = Volume{} } func (*Volume) ProtoMessage() {} -func (*Volume) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{180} } +func (*Volume) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{186} } func (m *VolumeDevice) Reset() { *m = VolumeDevice{} } func (*VolumeDevice) ProtoMessage() {} -func (*VolumeDevice) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{181} } +func (*VolumeDevice) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{187} } func (m *VolumeMount) Reset() { *m = VolumeMount{} } func (*VolumeMount) ProtoMessage() {} -func (*VolumeMount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{182} } +func (*VolumeMount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{188} } func (m *VolumeNodeAffinity) Reset() { *m = VolumeNodeAffinity{} } func (*VolumeNodeAffinity) ProtoMessage() {} -func (*VolumeNodeAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{183} } +func (*VolumeNodeAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{189} } func (m *VolumeProjection) Reset() { *m = VolumeProjection{} } func (*VolumeProjection) ProtoMessage() {} -func (*VolumeProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{184} } +func (*VolumeProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{190} } func (m *VolumeSource) Reset() { *m = VolumeSource{} } func (*VolumeSource) ProtoMessage() {} -func (*VolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{185} } +func (*VolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{191} } func (m *VsphereVirtualDiskVolumeSource) Reset() { *m = VsphereVirtualDiskVolumeSource{} } func (*VsphereVirtualDiskVolumeSource) ProtoMessage() {} func (*VsphereVirtualDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{186} + return fileDescriptorGenerated, []int{192} } func (m *WeightedPodAffinityTerm) Reset() { *m = WeightedPodAffinityTerm{} } func (*WeightedPodAffinityTerm) ProtoMessage() {} func (*WeightedPodAffinityTerm) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{187} + return fileDescriptorGenerated, []int{193} } func init() { @@ -1065,6 +1105,7 @@ func init() { proto.RegisterType((*Capabilities)(nil), "k8s.io.api.core.v1.Capabilities") proto.RegisterType((*CephFSPersistentVolumeSource)(nil), "k8s.io.api.core.v1.CephFSPersistentVolumeSource") proto.RegisterType((*CephFSVolumeSource)(nil), "k8s.io.api.core.v1.CephFSVolumeSource") + proto.RegisterType((*CinderPersistentVolumeSource)(nil), "k8s.io.api.core.v1.CinderPersistentVolumeSource") proto.RegisterType((*CinderVolumeSource)(nil), "k8s.io.api.core.v1.CinderVolumeSource") proto.RegisterType((*ClientIPConfig)(nil), "k8s.io.api.core.v1.ClientIPConfig") proto.RegisterType((*ComponentCondition)(nil), "k8s.io.api.core.v1.ComponentCondition") @@ -1074,6 +1115,7 @@ func init() { proto.RegisterType((*ConfigMapEnvSource)(nil), "k8s.io.api.core.v1.ConfigMapEnvSource") proto.RegisterType((*ConfigMapKeySelector)(nil), "k8s.io.api.core.v1.ConfigMapKeySelector") proto.RegisterType((*ConfigMapList)(nil), "k8s.io.api.core.v1.ConfigMapList") + proto.RegisterType((*ConfigMapNodeConfigSource)(nil), "k8s.io.api.core.v1.ConfigMapNodeConfigSource") proto.RegisterType((*ConfigMapProjection)(nil), "k8s.io.api.core.v1.ConfigMapProjection") proto.RegisterType((*ConfigMapVolumeSource)(nil), "k8s.io.api.core.v1.ConfigMapVolumeSource") proto.RegisterType((*Container)(nil), "k8s.io.api.core.v1.Container") @@ -1085,7 +1127,6 @@ func init() { proto.RegisterType((*ContainerStateWaiting)(nil), "k8s.io.api.core.v1.ContainerStateWaiting") proto.RegisterType((*ContainerStatus)(nil), "k8s.io.api.core.v1.ContainerStatus") proto.RegisterType((*DaemonEndpoint)(nil), "k8s.io.api.core.v1.DaemonEndpoint") - proto.RegisterType((*DeleteOptions)(nil), "k8s.io.api.core.v1.DeleteOptions") proto.RegisterType((*DownwardAPIProjection)(nil), "k8s.io.api.core.v1.DownwardAPIProjection") proto.RegisterType((*DownwardAPIVolumeFile)(nil), "k8s.io.api.core.v1.DownwardAPIVolumeFile") proto.RegisterType((*DownwardAPIVolumeSource)(nil), "k8s.io.api.core.v1.DownwardAPIVolumeSource") @@ -1124,7 +1165,6 @@ func init() { proto.RegisterType((*LimitRangeList)(nil), "k8s.io.api.core.v1.LimitRangeList") proto.RegisterType((*LimitRangeSpec)(nil), "k8s.io.api.core.v1.LimitRangeSpec") proto.RegisterType((*List)(nil), "k8s.io.api.core.v1.List") - proto.RegisterType((*ListOptions)(nil), "k8s.io.api.core.v1.ListOptions") proto.RegisterType((*LoadBalancerIngress)(nil), "k8s.io.api.core.v1.LoadBalancerIngress") proto.RegisterType((*LoadBalancerStatus)(nil), "k8s.io.api.core.v1.LoadBalancerStatus") proto.RegisterType((*LocalObjectReference)(nil), "k8s.io.api.core.v1.LocalObjectReference") @@ -1139,6 +1179,7 @@ func init() { proto.RegisterType((*NodeAffinity)(nil), "k8s.io.api.core.v1.NodeAffinity") proto.RegisterType((*NodeCondition)(nil), "k8s.io.api.core.v1.NodeCondition") proto.RegisterType((*NodeConfigSource)(nil), "k8s.io.api.core.v1.NodeConfigSource") + proto.RegisterType((*NodeConfigStatus)(nil), "k8s.io.api.core.v1.NodeConfigStatus") proto.RegisterType((*NodeDaemonEndpoints)(nil), "k8s.io.api.core.v1.NodeDaemonEndpoints") proto.RegisterType((*NodeList)(nil), "k8s.io.api.core.v1.NodeList") proto.RegisterType((*NodeProxyOptions)(nil), "k8s.io.api.core.v1.NodeProxyOptions") @@ -1150,7 +1191,6 @@ func init() { proto.RegisterType((*NodeStatus)(nil), "k8s.io.api.core.v1.NodeStatus") proto.RegisterType((*NodeSystemInfo)(nil), "k8s.io.api.core.v1.NodeSystemInfo") proto.RegisterType((*ObjectFieldSelector)(nil), "k8s.io.api.core.v1.ObjectFieldSelector") - proto.RegisterType((*ObjectMeta)(nil), "k8s.io.api.core.v1.ObjectMeta") proto.RegisterType((*ObjectReference)(nil), "k8s.io.api.core.v1.ObjectReference") proto.RegisterType((*PersistentVolume)(nil), "k8s.io.api.core.v1.PersistentVolume") proto.RegisterType((*PersistentVolumeClaim)(nil), "k8s.io.api.core.v1.PersistentVolumeClaim") @@ -1177,6 +1217,7 @@ func init() { proto.RegisterType((*PodLogOptions)(nil), "k8s.io.api.core.v1.PodLogOptions") proto.RegisterType((*PodPortForwardOptions)(nil), "k8s.io.api.core.v1.PodPortForwardOptions") proto.RegisterType((*PodProxyOptions)(nil), "k8s.io.api.core.v1.PodProxyOptions") + proto.RegisterType((*PodReadinessGate)(nil), "k8s.io.api.core.v1.PodReadinessGate") proto.RegisterType((*PodSecurityContext)(nil), "k8s.io.api.core.v1.PodSecurityContext") proto.RegisterType((*PodSignature)(nil), "k8s.io.api.core.v1.PodSignature") proto.RegisterType((*PodSpec)(nil), "k8s.io.api.core.v1.PodSpec") @@ -1209,6 +1250,8 @@ func init() { proto.RegisterType((*SELinuxOptions)(nil), "k8s.io.api.core.v1.SELinuxOptions") proto.RegisterType((*ScaleIOPersistentVolumeSource)(nil), "k8s.io.api.core.v1.ScaleIOPersistentVolumeSource") proto.RegisterType((*ScaleIOVolumeSource)(nil), "k8s.io.api.core.v1.ScaleIOVolumeSource") + proto.RegisterType((*ScopeSelector)(nil), "k8s.io.api.core.v1.ScopeSelector") + proto.RegisterType((*ScopedResourceSelectorRequirement)(nil), "k8s.io.api.core.v1.ScopedResourceSelectorRequirement") proto.RegisterType((*Secret)(nil), "k8s.io.api.core.v1.Secret") proto.RegisterType((*SecretEnvSource)(nil), "k8s.io.api.core.v1.SecretEnvSource") proto.RegisterType((*SecretKeySelector)(nil), "k8s.io.api.core.v1.SecretKeySelector") @@ -1221,6 +1264,7 @@ func init() { proto.RegisterType((*Service)(nil), "k8s.io.api.core.v1.Service") proto.RegisterType((*ServiceAccount)(nil), "k8s.io.api.core.v1.ServiceAccount") proto.RegisterType((*ServiceAccountList)(nil), "k8s.io.api.core.v1.ServiceAccountList") + proto.RegisterType((*ServiceAccountTokenProjection)(nil), "k8s.io.api.core.v1.ServiceAccountTokenProjection") proto.RegisterType((*ServiceList)(nil), "k8s.io.api.core.v1.ServiceList") proto.RegisterType((*ServicePort)(nil), "k8s.io.api.core.v1.ServicePort") proto.RegisterType((*ServiceProxyOptions)(nil), "k8s.io.api.core.v1.ServiceProxyOptions") @@ -1233,6 +1277,8 @@ func init() { proto.RegisterType((*TCPSocketAction)(nil), "k8s.io.api.core.v1.TCPSocketAction") proto.RegisterType((*Taint)(nil), "k8s.io.api.core.v1.Taint") proto.RegisterType((*Toleration)(nil), "k8s.io.api.core.v1.Toleration") + proto.RegisterType((*TopologySelectorLabelRequirement)(nil), "k8s.io.api.core.v1.TopologySelectorLabelRequirement") + proto.RegisterType((*TopologySelectorTerm)(nil), "k8s.io.api.core.v1.TopologySelectorTerm") proto.RegisterType((*Volume)(nil), "k8s.io.api.core.v1.Volume") proto.RegisterType((*VolumeDevice)(nil), "k8s.io.api.core.v1.VolumeDevice") proto.RegisterType((*VolumeMount)(nil), "k8s.io.api.core.v1.VolumeMount") @@ -1809,6 +1855,50 @@ func (m *CephFSVolumeSource) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *CinderPersistentVolumeSource) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CinderPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.VolumeID))) + i += copy(dAtA[i:], m.VolumeID) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.FSType))) + i += copy(dAtA[i:], m.FSType) + dAtA[i] = 0x18 + i++ + if m.ReadOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + if m.SecretRef != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) + n11, err := m.SecretRef.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n11 + } + return i, nil +} + func (m *CinderVolumeSource) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1840,6 +1930,16 @@ func (m *CinderVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0 } i++ + if m.SecretRef != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) + n12, err := m.SecretRef.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n12 + } return i, nil } @@ -1918,11 +2018,11 @@ func (m *ComponentStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n11, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n13, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n11 + i += n13 if len(m.Conditions) > 0 { for _, msg := range m.Conditions { dAtA[i] = 0x12 @@ -1956,11 +2056,11 @@ func (m *ComponentStatusList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n12, err := m.ListMeta.MarshalTo(dAtA[i:]) + n14, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n12 + i += n14 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -1994,11 +2094,11 @@ func (m *ConfigMap) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n13, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n15, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n13 + i += n15 if len(m.Data) > 0 { keysForData := make([]string, 0, len(m.Data)) for k := range m.Data { @@ -2070,11 +2170,11 @@ func (m *ConfigMapEnvSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n14, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n16, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n14 + i += n16 if m.Optional != nil { dAtA[i] = 0x10 i++ @@ -2106,11 +2206,11 @@ func (m *ConfigMapKeySelector) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n15, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n17, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n15 + i += n17 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) @@ -2146,11 +2246,11 @@ func (m *ConfigMapList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n16, err := m.ListMeta.MarshalTo(dAtA[i:]) + n18, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n16 + i += n18 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -2166,6 +2266,44 @@ func (m *ConfigMapList) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ConfigMapNodeConfigSource) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConfigMapNodeConfigSource) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Namespace))) + i += copy(dAtA[i:], m.Namespace) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.UID))) + i += copy(dAtA[i:], m.UID) + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ResourceVersion))) + i += copy(dAtA[i:], m.ResourceVersion) + dAtA[i] = 0x2a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.KubeletConfigKey))) + i += copy(dAtA[i:], m.KubeletConfigKey) + return i, nil +} + func (m *ConfigMapProjection) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2184,11 +2322,11 @@ func (m *ConfigMapProjection) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n17, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n19, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n17 + i += n19 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -2232,11 +2370,11 @@ func (m *ConfigMapVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n18, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n20, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n18 + i += n20 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -2351,11 +2489,11 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x42 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Resources.Size())) - n19, err := m.Resources.MarshalTo(dAtA[i:]) + n21, err := m.Resources.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n19 + i += n21 if len(m.VolumeMounts) > 0 { for _, msg := range m.VolumeMounts { dAtA[i] = 0x4a @@ -2372,31 +2510,31 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LivenessProbe.Size())) - n20, err := m.LivenessProbe.MarshalTo(dAtA[i:]) + n22, err := m.LivenessProbe.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n20 + i += n22 } if m.ReadinessProbe != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ReadinessProbe.Size())) - n21, err := m.ReadinessProbe.MarshalTo(dAtA[i:]) + n23, err := m.ReadinessProbe.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n21 + i += n23 } if m.Lifecycle != nil { dAtA[i] = 0x62 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Lifecycle.Size())) - n22, err := m.Lifecycle.MarshalTo(dAtA[i:]) + n24, err := m.Lifecycle.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n22 + i += n24 } dAtA[i] = 0x6a i++ @@ -2410,11 +2548,11 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x7a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecurityContext.Size())) - n23, err := m.SecurityContext.MarshalTo(dAtA[i:]) + n25, err := m.SecurityContext.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n23 + i += n25 } dAtA[i] = 0x80 i++ @@ -2574,31 +2712,31 @@ func (m *ContainerState) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Waiting.Size())) - n24, err := m.Waiting.MarshalTo(dAtA[i:]) + n26, err := m.Waiting.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n24 + i += n26 } if m.Running != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Running.Size())) - n25, err := m.Running.MarshalTo(dAtA[i:]) + n27, err := m.Running.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n25 + i += n27 } if m.Terminated != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Terminated.Size())) - n26, err := m.Terminated.MarshalTo(dAtA[i:]) + n28, err := m.Terminated.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n26 + i += n28 } return i, nil } @@ -2621,11 +2759,11 @@ func (m *ContainerStateRunning) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StartedAt.Size())) - n27, err := m.StartedAt.MarshalTo(dAtA[i:]) + n29, err := m.StartedAt.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n27 + i += n29 return i, nil } @@ -2661,19 +2799,19 @@ func (m *ContainerStateTerminated) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StartedAt.Size())) - n28, err := m.StartedAt.MarshalTo(dAtA[i:]) + n30, err := m.StartedAt.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n28 + i += n30 dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FinishedAt.Size())) - n29, err := m.FinishedAt.MarshalTo(dAtA[i:]) + n31, err := m.FinishedAt.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n29 + i += n31 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.ContainerID))) @@ -2729,19 +2867,19 @@ func (m *ContainerStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.State.Size())) - n30, err := m.State.MarshalTo(dAtA[i:]) + n32, err := m.State.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n30 + i += n32 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTerminationState.Size())) - n31, err := m.LastTerminationState.MarshalTo(dAtA[i:]) + n33, err := m.LastTerminationState.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n31 + i += n33 dAtA[i] = 0x20 i++ if m.Ready { @@ -2789,55 +2927,6 @@ func (m *DaemonEndpoint) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *DeleteOptions) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *DeleteOptions) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.GracePeriodSeconds != nil { - dAtA[i] = 0x8 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(*m.GracePeriodSeconds)) - } - if m.Preconditions != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Preconditions.Size())) - n32, err := m.Preconditions.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n32 - } - if m.OrphanDependents != nil { - dAtA[i] = 0x18 - i++ - if *m.OrphanDependents { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - } - if m.PropagationPolicy != nil { - dAtA[i] = 0x22 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(*m.PropagationPolicy))) - i += copy(dAtA[i:], *m.PropagationPolicy) - } - return i, nil -} - func (m *DownwardAPIProjection) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2891,21 +2980,21 @@ func (m *DownwardAPIVolumeFile) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FieldRef.Size())) - n33, err := m.FieldRef.MarshalTo(dAtA[i:]) + n34, err := m.FieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n33 + i += n34 } if m.ResourceFieldRef != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ResourceFieldRef.Size())) - n34, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) + n35, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n34 + i += n35 } if m.Mode != nil { dAtA[i] = 0x20 @@ -2973,11 +3062,11 @@ func (m *EmptyDirVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SizeLimit.Size())) - n35, err := m.SizeLimit.MarshalTo(dAtA[i:]) + n36, err := m.SizeLimit.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n36 } return i, nil } @@ -3005,11 +3094,11 @@ func (m *EndpointAddress) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TargetRef.Size())) - n36, err := m.TargetRef.MarshalTo(dAtA[i:]) + n37, err := m.TargetRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n37 } dAtA[i] = 0x1a i++ @@ -3125,11 +3214,11 @@ func (m *Endpoints) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n37, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n38, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n38 if len(m.Subsets) > 0 { for _, msg := range m.Subsets { dAtA[i] = 0x12 @@ -3163,11 +3252,11 @@ func (m *EndpointsList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n38, err := m.ListMeta.MarshalTo(dAtA[i:]) + n39, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n39 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -3206,21 +3295,21 @@ func (m *EnvFromSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMapRef.Size())) - n39, err := m.ConfigMapRef.MarshalTo(dAtA[i:]) + n40, err := m.ConfigMapRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n40 } if m.SecretRef != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n40, err := m.SecretRef.MarshalTo(dAtA[i:]) + n41, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n41 } return i, nil } @@ -3252,11 +3341,11 @@ func (m *EnvVar) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ValueFrom.Size())) - n41, err := m.ValueFrom.MarshalTo(dAtA[i:]) + n42, err := m.ValueFrom.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n41 + i += n42 } return i, nil } @@ -3280,41 +3369,41 @@ func (m *EnvVarSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FieldRef.Size())) - n42, err := m.FieldRef.MarshalTo(dAtA[i:]) + n43, err := m.FieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n42 + i += n43 } if m.ResourceFieldRef != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ResourceFieldRef.Size())) - n43, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) + n44, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n43 + i += n44 } if m.ConfigMapKeyRef != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMapKeyRef.Size())) - n44, err := m.ConfigMapKeyRef.MarshalTo(dAtA[i:]) + n45, err := m.ConfigMapKeyRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n44 + i += n45 } if m.SecretKeyRef != nil { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretKeyRef.Size())) - n45, err := m.SecretKeyRef.MarshalTo(dAtA[i:]) + n46, err := m.SecretKeyRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n45 + i += n46 } return i, nil } @@ -3337,19 +3426,19 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n46, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n47, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n46 + i += n47 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.InvolvedObject.Size())) - n47, err := m.InvolvedObject.MarshalTo(dAtA[i:]) + n48, err := m.InvolvedObject.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n47 + i += n48 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -3361,27 +3450,27 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Source.Size())) - n48, err := m.Source.MarshalTo(dAtA[i:]) + n49, err := m.Source.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n48 + i += n49 dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FirstTimestamp.Size())) - n49, err := m.FirstTimestamp.MarshalTo(dAtA[i:]) + n50, err := m.FirstTimestamp.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n49 + i += n50 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTimestamp.Size())) - n50, err := m.LastTimestamp.MarshalTo(dAtA[i:]) + n51, err := m.LastTimestamp.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n50 + i += n51 dAtA[i] = 0x40 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Count)) @@ -3392,20 +3481,20 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.EventTime.Size())) - n51, err := m.EventTime.MarshalTo(dAtA[i:]) + n52, err := m.EventTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n51 + i += n52 if m.Series != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Series.Size())) - n52, err := m.Series.MarshalTo(dAtA[i:]) + n53, err := m.Series.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n52 + i += n53 } dAtA[i] = 0x62 i++ @@ -3415,11 +3504,11 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x6a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Related.Size())) - n53, err := m.Related.MarshalTo(dAtA[i:]) + n54, err := m.Related.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n53 + i += n54 } dAtA[i] = 0x72 i++ @@ -3450,11 +3539,11 @@ func (m *EventList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n54, err := m.ListMeta.MarshalTo(dAtA[i:]) + n55, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n54 + i += n55 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -3491,11 +3580,11 @@ func (m *EventSeries) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastObservedTime.Size())) - n55, err := m.LastObservedTime.MarshalTo(dAtA[i:]) + n56, err := m.LastObservedTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n55 + i += n56 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.State))) @@ -3654,11 +3743,11 @@ func (m *FlexPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n56, err := m.SecretRef.MarshalTo(dAtA[i:]) + n57, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n56 + i += n57 } dAtA[i] = 0x20 i++ @@ -3720,11 +3809,11 @@ func (m *FlexVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n57, err := m.SecretRef.MarshalTo(dAtA[i:]) + n58, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n57 + i += n58 } dAtA[i] = 0x20 i++ @@ -3908,11 +3997,11 @@ func (m *HTTPGetAction) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Port.Size())) - n58, err := m.Port.MarshalTo(dAtA[i:]) + n59, err := m.Port.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n58 + i += n59 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Host))) @@ -3981,31 +4070,31 @@ func (m *Handler) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Exec.Size())) - n59, err := m.Exec.MarshalTo(dAtA[i:]) + n60, err := m.Exec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n59 + i += n60 } if m.HTTPGet != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.HTTPGet.Size())) - n60, err := m.HTTPGet.MarshalTo(dAtA[i:]) + n61, err := m.HTTPGet.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n60 + i += n61 } if m.TCPSocket != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TCPSocket.Size())) - n61, err := m.TCPSocket.MarshalTo(dAtA[i:]) + n62, err := m.TCPSocket.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n61 + i += n62 } return i, nil } @@ -4144,11 +4233,11 @@ func (m *ISCSIPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n62, err := m.SecretRef.MarshalTo(dAtA[i:]) + n63, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n62 + i += n63 } dAtA[i] = 0x58 i++ @@ -4236,11 +4325,11 @@ func (m *ISCSIVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n63, err := m.SecretRef.MarshalTo(dAtA[i:]) + n64, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n63 + i += n64 } dAtA[i] = 0x58 i++ @@ -4309,21 +4398,21 @@ func (m *Lifecycle) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PostStart.Size())) - n64, err := m.PostStart.MarshalTo(dAtA[i:]) + n65, err := m.PostStart.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n64 + i += n65 } if m.PreStop != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PreStop.Size())) - n65, err := m.PreStop.MarshalTo(dAtA[i:]) + n66, err := m.PreStop.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n65 + i += n66 } return i, nil } @@ -4346,19 +4435,19 @@ func (m *LimitRange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n66, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n67, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n66 + i += n67 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n67, err := m.Spec.MarshalTo(dAtA[i:]) + n68, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n67 + i += n68 return i, nil } @@ -4405,37 +4494,6 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n68, err := (&v).MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n68 - } - } - if len(m.Min) > 0 { - keysForMin := make([]string, 0, len(m.Min)) - for k := range m.Min { - keysForMin = append(keysForMin, string(k)) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForMin) - for _, k := range keysForMin { - dAtA[i] = 0x1a - i++ - v := m.Min[ResourceName(k)] - msgSize := 0 - if (&v) != nil { - msgSize = (&v).Size() - msgSize += 1 + sovGenerated(uint64(msgSize)) - } - mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + msgSize - i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(k))) - i += copy(dAtA[i:], k) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) n69, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err @@ -4443,6 +4501,37 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { i += n69 } } + if len(m.Min) > 0 { + keysForMin := make([]string, 0, len(m.Min)) + for k := range m.Min { + keysForMin = append(keysForMin, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForMin) + for _, k := range keysForMin { + dAtA[i] = 0x1a + i++ + v := m.Min[ResourceName(k)] + msgSize := 0 + if (&v) != nil { + msgSize = (&v).Size() + msgSize += 1 + sovGenerated(uint64(msgSize)) + } + mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + msgSize + i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) + n70, err := (&v).MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n70 + } + } if len(m.Default) > 0 { keysForDefault := make([]string, 0, len(m.Default)) for k := range m.Default { @@ -4467,11 +4556,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n70, err := (&v).MarshalTo(dAtA[i:]) + n71, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n70 + i += n71 } } if len(m.DefaultRequest) > 0 { @@ -4498,11 +4587,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n71, err := (&v).MarshalTo(dAtA[i:]) + n72, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n71 + i += n72 } } if len(m.MaxLimitRequestRatio) > 0 { @@ -4529,11 +4618,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n72, err := (&v).MarshalTo(dAtA[i:]) + n73, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n72 + i += n73 } } return i, nil @@ -4557,11 +4646,11 @@ func (m *LimitRangeList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n73, err := m.ListMeta.MarshalTo(dAtA[i:]) + n74, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n73 + i += n74 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -4625,11 +4714,11 @@ func (m *List) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n74, err := m.ListMeta.MarshalTo(dAtA[i:]) + n75, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n74 + i += n75 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -4645,57 +4734,6 @@ func (m *List) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *ListOptions) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ListOptions) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.LabelSelector))) - i += copy(dAtA[i:], m.LabelSelector) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.FieldSelector))) - i += copy(dAtA[i:], m.FieldSelector) - dAtA[i] = 0x18 - i++ - if m.Watch { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - dAtA[i] = 0x22 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.ResourceVersion))) - i += copy(dAtA[i:], m.ResourceVersion) - if m.TimeoutSeconds != nil { - dAtA[i] = 0x28 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(*m.TimeoutSeconds)) - } - dAtA[i] = 0x30 - i++ - if m.IncludeUninitialized { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - return i, nil -} - func (m *LoadBalancerIngress) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -4848,27 +4886,27 @@ func (m *Namespace) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n75, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n76, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n75 + i += n76 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n76, err := m.Spec.MarshalTo(dAtA[i:]) + n77, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n76 + i += n77 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n77, err := m.Status.MarshalTo(dAtA[i:]) + n78, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n77 + i += n78 return i, nil } @@ -4890,11 +4928,11 @@ func (m *NamespaceList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n78, err := m.ListMeta.MarshalTo(dAtA[i:]) + n79, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n78 + i += n79 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -4983,27 +5021,27 @@ func (m *Node) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n79, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n80, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n79 + i += n80 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n80, err := m.Spec.MarshalTo(dAtA[i:]) + n81, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n80 + i += n81 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n81, err := m.Status.MarshalTo(dAtA[i:]) + n82, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n81 + i += n82 return i, nil } @@ -5052,11 +5090,11 @@ func (m *NodeAffinity) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.RequiredDuringSchedulingIgnoredDuringExecution.Size())) - n82, err := m.RequiredDuringSchedulingIgnoredDuringExecution.MarshalTo(dAtA[i:]) + n83, err := m.RequiredDuringSchedulingIgnoredDuringExecution.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n82 + i += n83 } if len(m.PreferredDuringSchedulingIgnoredDuringExecution) > 0 { for _, msg := range m.PreferredDuringSchedulingIgnoredDuringExecution { @@ -5099,19 +5137,19 @@ func (m *NodeCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastHeartbeatTime.Size())) - n83, err := m.LastHeartbeatTime.MarshalTo(dAtA[i:]) + n84, err := m.LastHeartbeatTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n83 + i += n84 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n84, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n85, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n84 + i += n85 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -5138,16 +5176,68 @@ func (m *NodeConfigSource) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.ConfigMapRef != nil { + if m.ConfigMap != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMap.Size())) + n86, err := m.ConfigMap.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n86 + } + return i, nil +} + +func (m *NodeConfigStatus) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NodeConfigStatus) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Assigned != nil { dAtA[i] = 0xa i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMapRef.Size())) - n85, err := m.ConfigMapRef.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.Assigned.Size())) + n87, err := m.Assigned.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n87 + } + if m.Active != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Active.Size())) + n88, err := m.Active.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n88 + } + if m.LastKnownGood != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.LastKnownGood.Size())) + n89, err := m.LastKnownGood.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n85 + i += n89 } + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Error))) + i += copy(dAtA[i:], m.Error) return i, nil } @@ -5169,11 +5259,11 @@ func (m *NodeDaemonEndpoints) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.KubeletEndpoint.Size())) - n86, err := m.KubeletEndpoint.MarshalTo(dAtA[i:]) + n90, err := m.KubeletEndpoint.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n86 + i += n90 return i, nil } @@ -5195,11 +5285,11 @@ func (m *NodeList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n87, err := m.ListMeta.MarshalTo(dAtA[i:]) + n91, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n87 + i += n91 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -5276,11 +5366,11 @@ func (m *NodeResources) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n88, err := (&v).MarshalTo(dAtA[i:]) + n92, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n88 + i += n92 } } return i, nil @@ -5384,6 +5474,18 @@ func (m *NodeSelectorTerm) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.MatchFields) > 0 { + for _, msg := range m.MatchFields { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -5408,8 +5510,8 @@ func (m *NodeSpec) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], m.PodCIDR) dAtA[i] = 0x12 i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.ExternalID))) - i += copy(dAtA[i:], m.ExternalID) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.DoNotUse_ExternalID))) + i += copy(dAtA[i:], m.DoNotUse_ExternalID) dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.ProviderID))) @@ -5438,11 +5540,11 @@ func (m *NodeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigSource.Size())) - n89, err := m.ConfigSource.MarshalTo(dAtA[i:]) + n93, err := m.ConfigSource.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n89 + i += n93 } return i, nil } @@ -5486,11 +5588,11 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n90, err := (&v).MarshalTo(dAtA[i:]) + n94, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n90 + i += n94 } } if len(m.Allocatable) > 0 { @@ -5517,11 +5619,11 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n91, err := (&v).MarshalTo(dAtA[i:]) + n95, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n91 + i += n95 } } dAtA[i] = 0x1a @@ -5555,19 +5657,19 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DaemonEndpoints.Size())) - n92, err := m.DaemonEndpoints.MarshalTo(dAtA[i:]) + n96, err := m.DaemonEndpoints.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n92 + i += n96 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NodeInfo.Size())) - n93, err := m.NodeInfo.MarshalTo(dAtA[i:]) + n97, err := m.NodeInfo.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n93 + i += n97 if len(m.Images) > 0 { for _, msg := range m.Images { dAtA[i] = 0x42 @@ -5607,6 +5709,16 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { i += n } } + if m.Config != nil { + dAtA[i] = 0x5a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Config.Size())) + n98, err := m.Config.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n98 + } return i, nil } @@ -5694,161 +5806,6 @@ func (m *ObjectFieldSelector) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *ObjectMeta) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ObjectMeta) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) - i += copy(dAtA[i:], m.Name) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.GenerateName))) - i += copy(dAtA[i:], m.GenerateName) - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Namespace))) - i += copy(dAtA[i:], m.Namespace) - dAtA[i] = 0x22 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.SelfLink))) - i += copy(dAtA[i:], m.SelfLink) - dAtA[i] = 0x2a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.UID))) - i += copy(dAtA[i:], m.UID) - dAtA[i] = 0x32 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.ResourceVersion))) - i += copy(dAtA[i:], m.ResourceVersion) - dAtA[i] = 0x38 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Generation)) - dAtA[i] = 0x42 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.CreationTimestamp.Size())) - n94, err := m.CreationTimestamp.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n94 - if m.DeletionTimestamp != nil { - dAtA[i] = 0x4a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.DeletionTimestamp.Size())) - n95, err := m.DeletionTimestamp.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n95 - } - if m.DeletionGracePeriodSeconds != nil { - dAtA[i] = 0x50 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(*m.DeletionGracePeriodSeconds)) - } - if len(m.Labels) > 0 { - keysForLabels := make([]string, 0, len(m.Labels)) - for k := range m.Labels { - keysForLabels = append(keysForLabels, string(k)) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) - for _, k := range keysForLabels { - dAtA[i] = 0x5a - i++ - v := m.Labels[string(k)] - mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) - i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(k))) - i += copy(dAtA[i:], k) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(v))) - i += copy(dAtA[i:], v) - } - } - if len(m.Annotations) > 0 { - keysForAnnotations := make([]string, 0, len(m.Annotations)) - for k := range m.Annotations { - keysForAnnotations = append(keysForAnnotations, string(k)) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations) - for _, k := range keysForAnnotations { - dAtA[i] = 0x62 - i++ - v := m.Annotations[string(k)] - mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) - i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(k))) - i += copy(dAtA[i:], k) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(v))) - i += copy(dAtA[i:], v) - } - } - if len(m.OwnerReferences) > 0 { - for _, msg := range m.OwnerReferences { - dAtA[i] = 0x6a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n - } - } - if len(m.Finalizers) > 0 { - for _, s := range m.Finalizers { - dAtA[i] = 0x72 - i++ - l = len(s) - for l >= 1<<7 { - dAtA[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - dAtA[i] = uint8(l) - i++ - i += copy(dAtA[i:], s) - } - } - dAtA[i] = 0x7a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.ClusterName))) - i += copy(dAtA[i:], m.ClusterName) - if m.Initializers != nil { - dAtA[i] = 0x82 - i++ - dAtA[i] = 0x1 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Initializers.Size())) - n96, err := m.Initializers.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n96 - } - return i, nil -} - func (m *ObjectReference) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -5913,27 +5870,27 @@ func (m *PersistentVolume) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n97, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n99, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n97 + i += n99 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n98, err := m.Spec.MarshalTo(dAtA[i:]) + n100, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n98 + i += n100 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n99, err := m.Status.MarshalTo(dAtA[i:]) + n101, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n99 + i += n101 return i, nil } @@ -5955,27 +5912,27 @@ func (m *PersistentVolumeClaim) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n100, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n102, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n100 + i += n102 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n101, err := m.Spec.MarshalTo(dAtA[i:]) + n103, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n101 + i += n103 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n102, err := m.Status.MarshalTo(dAtA[i:]) + n104, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n102 + i += n104 return i, nil } @@ -6005,19 +5962,19 @@ func (m *PersistentVolumeClaimCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastProbeTime.Size())) - n103, err := m.LastProbeTime.MarshalTo(dAtA[i:]) + n105, err := m.LastProbeTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n103 + i += n105 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n104, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n106, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n104 + i += n106 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -6047,11 +6004,11 @@ func (m *PersistentVolumeClaimList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n105, err := m.ListMeta.MarshalTo(dAtA[i:]) + n107, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n105 + i += n107 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -6100,11 +6057,11 @@ func (m *PersistentVolumeClaimSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Resources.Size())) - n106, err := m.Resources.MarshalTo(dAtA[i:]) + n108, err := m.Resources.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n106 + i += n108 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.VolumeName))) @@ -6113,11 +6070,11 @@ func (m *PersistentVolumeClaimSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Selector.Size())) - n107, err := m.Selector.MarshalTo(dAtA[i:]) + n109, err := m.Selector.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n107 + i += n109 } if m.StorageClassName != nil { dAtA[i] = 0x2a @@ -6192,11 +6149,11 @@ func (m *PersistentVolumeClaimStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n108, err := (&v).MarshalTo(dAtA[i:]) + n110, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n108 + i += n110 } } if len(m.Conditions) > 0 { @@ -6262,11 +6219,11 @@ func (m *PersistentVolumeList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n109, err := m.ListMeta.MarshalTo(dAtA[i:]) + n111, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n109 + i += n111 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -6301,151 +6258,151 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.GCEPersistentDisk.Size())) - n110, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) + n112, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n110 + i += n112 } if m.AWSElasticBlockStore != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AWSElasticBlockStore.Size())) - n111, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) + n113, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n111 + i += n113 } if m.HostPath != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.HostPath.Size())) - n112, err := m.HostPath.MarshalTo(dAtA[i:]) + n114, err := m.HostPath.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n112 + i += n114 } if m.Glusterfs != nil { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Glusterfs.Size())) - n113, err := m.Glusterfs.MarshalTo(dAtA[i:]) + n115, err := m.Glusterfs.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n113 + i += n115 } if m.NFS != nil { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NFS.Size())) - n114, err := m.NFS.MarshalTo(dAtA[i:]) + n116, err := m.NFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n114 + i += n116 } if m.RBD != nil { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.RBD.Size())) - n115, err := m.RBD.MarshalTo(dAtA[i:]) + n117, err := m.RBD.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n115 + i += n117 } if m.ISCSI != nil { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ISCSI.Size())) - n116, err := m.ISCSI.MarshalTo(dAtA[i:]) + n118, err := m.ISCSI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n116 + i += n118 } if m.Cinder != nil { dAtA[i] = 0x42 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Cinder.Size())) - n117, err := m.Cinder.MarshalTo(dAtA[i:]) + n119, err := m.Cinder.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n117 + i += n119 } if m.CephFS != nil { dAtA[i] = 0x4a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.CephFS.Size())) - n118, err := m.CephFS.MarshalTo(dAtA[i:]) + n120, err := m.CephFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n118 + i += n120 } if m.FC != nil { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FC.Size())) - n119, err := m.FC.MarshalTo(dAtA[i:]) + n121, err := m.FC.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n119 + i += n121 } if m.Flocker != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Flocker.Size())) - n120, err := m.Flocker.MarshalTo(dAtA[i:]) + n122, err := m.Flocker.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n120 + i += n122 } if m.FlexVolume != nil { dAtA[i] = 0x62 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FlexVolume.Size())) - n121, err := m.FlexVolume.MarshalTo(dAtA[i:]) + n123, err := m.FlexVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n121 + i += n123 } if m.AzureFile != nil { dAtA[i] = 0x6a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureFile.Size())) - n122, err := m.AzureFile.MarshalTo(dAtA[i:]) + n124, err := m.AzureFile.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n122 + i += n124 } if m.VsphereVolume != nil { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.VsphereVolume.Size())) - n123, err := m.VsphereVolume.MarshalTo(dAtA[i:]) + n125, err := m.VsphereVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n123 + i += n125 } if m.Quobyte != nil { dAtA[i] = 0x7a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Quobyte.Size())) - n124, err := m.Quobyte.MarshalTo(dAtA[i:]) + n126, err := m.Quobyte.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n124 + i += n126 } if m.AzureDisk != nil { dAtA[i] = 0x82 @@ -6453,11 +6410,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureDisk.Size())) - n125, err := m.AzureDisk.MarshalTo(dAtA[i:]) + n127, err := m.AzureDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n125 + i += n127 } if m.PhotonPersistentDisk != nil { dAtA[i] = 0x8a @@ -6465,11 +6422,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PhotonPersistentDisk.Size())) - n126, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) + n128, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n126 + i += n128 } if m.PortworxVolume != nil { dAtA[i] = 0x92 @@ -6477,11 +6434,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PortworxVolume.Size())) - n127, err := m.PortworxVolume.MarshalTo(dAtA[i:]) + n129, err := m.PortworxVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n127 + i += n129 } if m.ScaleIO != nil { dAtA[i] = 0x9a @@ -6489,11 +6446,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ScaleIO.Size())) - n128, err := m.ScaleIO.MarshalTo(dAtA[i:]) + n130, err := m.ScaleIO.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n128 + i += n130 } if m.Local != nil { dAtA[i] = 0xa2 @@ -6501,11 +6458,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Local.Size())) - n129, err := m.Local.MarshalTo(dAtA[i:]) + n131, err := m.Local.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n129 + i += n131 } if m.StorageOS != nil { dAtA[i] = 0xaa @@ -6513,11 +6470,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StorageOS.Size())) - n130, err := m.StorageOS.MarshalTo(dAtA[i:]) + n132, err := m.StorageOS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n130 + i += n132 } if m.CSI != nil { dAtA[i] = 0xb2 @@ -6525,11 +6482,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.CSI.Size())) - n131, err := m.CSI.MarshalTo(dAtA[i:]) + n133, err := m.CSI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n131 + i += n133 } return i, nil } @@ -6573,21 +6530,21 @@ func (m *PersistentVolumeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n132, err := (&v).MarshalTo(dAtA[i:]) + n134, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n132 + i += n134 } } dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PersistentVolumeSource.Size())) - n133, err := m.PersistentVolumeSource.MarshalTo(dAtA[i:]) + n135, err := m.PersistentVolumeSource.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n133 + i += n135 if len(m.AccessModes) > 0 { for _, s := range m.AccessModes { dAtA[i] = 0x1a @@ -6607,11 +6564,11 @@ func (m *PersistentVolumeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ClaimRef.Size())) - n134, err := m.ClaimRef.MarshalTo(dAtA[i:]) + n136, err := m.ClaimRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n134 + i += n136 } dAtA[i] = 0x2a i++ @@ -6646,11 +6603,11 @@ func (m *PersistentVolumeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x4a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NodeAffinity.Size())) - n135, err := m.NodeAffinity.MarshalTo(dAtA[i:]) + n137, err := m.NodeAffinity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n135 + i += n137 } return i, nil } @@ -6729,27 +6686,27 @@ func (m *Pod) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n136, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n138, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n136 + i += n138 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n137, err := m.Spec.MarshalTo(dAtA[i:]) + n139, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n137 + i += n139 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n138, err := m.Status.MarshalTo(dAtA[i:]) + n140, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n138 + i += n140 return i, nil } @@ -6814,11 +6771,11 @@ func (m *PodAffinityTerm) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LabelSelector.Size())) - n139, err := m.LabelSelector.MarshalTo(dAtA[i:]) + n141, err := m.LabelSelector.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n139 + i += n141 } if len(m.Namespaces) > 0 { for _, s := range m.Namespaces { @@ -6964,19 +6921,19 @@ func (m *PodCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastProbeTime.Size())) - n140, err := m.LastProbeTime.MarshalTo(dAtA[i:]) + n142, err := m.LastProbeTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n140 + i += n142 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n141, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n143, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n141 + i += n143 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -7163,11 +7120,11 @@ func (m *PodList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n142, err := m.ListMeta.MarshalTo(dAtA[i:]) + n144, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n142 + i += n144 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -7227,11 +7184,11 @@ func (m *PodLogOptions) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SinceTime.Size())) - n143, err := m.SinceTime.MarshalTo(dAtA[i:]) + n145, err := m.SinceTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n143 + i += n145 } dAtA[i] = 0x30 i++ @@ -7301,6 +7258,28 @@ func (m *PodProxyOptions) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *PodReadinessGate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodReadinessGate) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ConditionType))) + i += copy(dAtA[i:], m.ConditionType) + return i, nil +} + func (m *PodSecurityContext) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7320,11 +7299,11 @@ func (m *PodSecurityContext) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SELinuxOptions.Size())) - n144, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) + n146, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n144 + i += n146 } if m.RunAsUser != nil { dAtA[i] = 0x10 @@ -7358,6 +7337,18 @@ func (m *PodSecurityContext) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintGenerated(dAtA, i, uint64(*m.RunAsGroup)) } + if len(m.Sysctls) > 0 { + for _, msg := range m.Sysctls { + dAtA[i] = 0x3a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -7380,11 +7371,11 @@ func (m *PodSignature) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PodController.Size())) - n145, err := m.PodController.MarshalTo(dAtA[i:]) + n147, err := m.PodController.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n145 + i += n147 } return i, nil } @@ -7508,11 +7499,11 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecurityContext.Size())) - n146, err := m.SecurityContext.MarshalTo(dAtA[i:]) + n148, err := m.SecurityContext.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n146 + i += n148 } if len(m.ImagePullSecrets) > 0 { for _, msg := range m.ImagePullSecrets { @@ -7544,11 +7535,11 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Affinity.Size())) - n147, err := m.Affinity.MarshalTo(dAtA[i:]) + n149, err := m.Affinity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n147 + i += n149 } dAtA[i] = 0x9a i++ @@ -7629,11 +7620,11 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DNSConfig.Size())) - n148, err := m.DNSConfig.MarshalTo(dAtA[i:]) + n150, err := m.DNSConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n148 + i += n150 } if m.ShareProcessNamespace != nil { dAtA[i] = 0xd8 @@ -7647,6 +7638,20 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { } i++ } + if len(m.ReadinessGates) > 0 { + for _, msg := range m.ReadinessGates { + dAtA[i] = 0xe2 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -7701,11 +7706,11 @@ func (m *PodStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StartTime.Size())) - n149, err := m.StartTime.MarshalTo(dAtA[i:]) + n151, err := m.StartTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n149 + i += n151 } if len(m.ContainerStatuses) > 0 { for _, msg := range m.ContainerStatuses { @@ -7760,19 +7765,19 @@ func (m *PodStatusResult) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n150, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n152, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n150 + i += n152 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n151, err := m.Status.MarshalTo(dAtA[i:]) + n153, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n151 + i += n153 return i, nil } @@ -7794,19 +7799,19 @@ func (m *PodTemplate) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n152, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n154, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n152 + i += n154 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Template.Size())) - n153, err := m.Template.MarshalTo(dAtA[i:]) + n155, err := m.Template.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n153 + i += n155 return i, nil } @@ -7828,11 +7833,11 @@ func (m *PodTemplateList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n154, err := m.ListMeta.MarshalTo(dAtA[i:]) + n156, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n154 + i += n156 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -7866,19 +7871,19 @@ func (m *PodTemplateSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n155, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n157, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n155 + i += n157 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n156, err := m.Spec.MarshalTo(dAtA[i:]) + n158, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n156 + i += n158 return i, nil } @@ -7958,19 +7963,19 @@ func (m *PreferAvoidPodsEntry) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PodSignature.Size())) - n157, err := m.PodSignature.MarshalTo(dAtA[i:]) + n159, err := m.PodSignature.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n157 + i += n159 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.EvictionTime.Size())) - n158, err := m.EvictionTime.MarshalTo(dAtA[i:]) + n160, err := m.EvictionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n158 + i += n160 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -8003,11 +8008,11 @@ func (m *PreferredSchedulingTerm) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Preference.Size())) - n159, err := m.Preference.MarshalTo(dAtA[i:]) + n161, err := m.Preference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n159 + i += n161 return i, nil } @@ -8029,11 +8034,11 @@ func (m *Probe) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Handler.Size())) - n160, err := m.Handler.MarshalTo(dAtA[i:]) + n162, err := m.Handler.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n160 + i += n162 dAtA[i] = 0x10 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.InitialDelaySeconds)) @@ -8183,11 +8188,11 @@ func (m *RBDPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n161, err := m.SecretRef.MarshalTo(dAtA[i:]) + n163, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n161 + i += n163 } dAtA[i] = 0x40 i++ @@ -8254,11 +8259,11 @@ func (m *RBDVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n162, err := m.SecretRef.MarshalTo(dAtA[i:]) + n164, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n162 + i += n164 } dAtA[i] = 0x40 i++ @@ -8289,11 +8294,11 @@ func (m *RangeAllocation) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n163, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n165, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n163 + i += n165 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Range))) @@ -8325,27 +8330,27 @@ func (m *ReplicationController) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n164, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n166, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n164 + i += n166 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n165, err := m.Spec.MarshalTo(dAtA[i:]) + n167, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n165 + i += n167 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n166, err := m.Status.MarshalTo(dAtA[i:]) + n168, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n166 + i += n168 return i, nil } @@ -8375,11 +8380,11 @@ func (m *ReplicationControllerCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n167, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n169, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n167 + i += n169 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -8409,11 +8414,11 @@ func (m *ReplicationControllerList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n168, err := m.ListMeta.MarshalTo(dAtA[i:]) + n170, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n168 + i += n170 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -8475,11 +8480,11 @@ func (m *ReplicationControllerSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Template.Size())) - n169, err := m.Template.MarshalTo(dAtA[i:]) + n171, err := m.Template.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n169 + i += n171 } dAtA[i] = 0x20 i++ @@ -8558,11 +8563,11 @@ func (m *ResourceFieldSelector) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Divisor.Size())) - n170, err := m.Divisor.MarshalTo(dAtA[i:]) + n172, err := m.Divisor.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n170 + i += n172 return i, nil } @@ -8584,27 +8589,27 @@ func (m *ResourceQuota) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n171, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n173, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n171 + i += n173 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n172, err := m.Spec.MarshalTo(dAtA[i:]) + n174, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n172 + i += n174 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n173, err := m.Status.MarshalTo(dAtA[i:]) + n175, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n173 + i += n175 return i, nil } @@ -8626,11 +8631,11 @@ func (m *ResourceQuotaList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n174, err := m.ListMeta.MarshalTo(dAtA[i:]) + n176, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n174 + i += n176 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -8685,11 +8690,11 @@ func (m *ResourceQuotaSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n175, err := (&v).MarshalTo(dAtA[i:]) + n177, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n175 + i += n177 } } if len(m.Scopes) > 0 { @@ -8707,6 +8712,16 @@ func (m *ResourceQuotaSpec) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], s) } } + if m.ScopeSelector != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ScopeSelector.Size())) + n178, err := m.ScopeSelector.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n178 + } return i, nil } @@ -8749,11 +8764,11 @@ func (m *ResourceQuotaStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n176, err := (&v).MarshalTo(dAtA[i:]) + n179, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n176 + i += n179 } } if len(m.Used) > 0 { @@ -8780,11 +8795,11 @@ func (m *ResourceQuotaStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n177, err := (&v).MarshalTo(dAtA[i:]) + n180, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n177 + i += n180 } } return i, nil @@ -8829,11 +8844,11 @@ func (m *ResourceRequirements) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n178, err := (&v).MarshalTo(dAtA[i:]) + n181, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n178 + i += n181 } } if len(m.Requests) > 0 { @@ -8860,11 +8875,11 @@ func (m *ResourceRequirements) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n179, err := (&v).MarshalTo(dAtA[i:]) + n182, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n179 + i += n182 } } return i, nil @@ -8931,11 +8946,11 @@ func (m *ScaleIOPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n180, err := m.SecretRef.MarshalTo(dAtA[i:]) + n183, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n180 + i += n183 } dAtA[i] = 0x20 i++ @@ -9003,11 +9018,11 @@ func (m *ScaleIOVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n181, err := m.SecretRef.MarshalTo(dAtA[i:]) + n184, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n181 + i += n184 } dAtA[i] = 0x20 i++ @@ -9048,6 +9063,77 @@ func (m *ScaleIOVolumeSource) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ScopeSelector) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ScopeSelector) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.MatchExpressions) > 0 { + for _, msg := range m.MatchExpressions { + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *ScopedResourceSelectorRequirement) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ScopedResourceSelectorRequirement) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ScopeName))) + i += copy(dAtA[i:], m.ScopeName) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Operator))) + i += copy(dAtA[i:], m.Operator) + if len(m.Values) > 0 { + for _, s := range m.Values { + dAtA[i] = 0x1a + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + func (m *Secret) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -9066,11 +9152,11 @@ func (m *Secret) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n182, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n185, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n182 + i += n185 if len(m.Data) > 0 { keysForData := make([]string, 0, len(m.Data)) for k := range m.Data { @@ -9146,11 +9232,11 @@ func (m *SecretEnvSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n183, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n186, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n183 + i += n186 if m.Optional != nil { dAtA[i] = 0x10 i++ @@ -9182,11 +9268,11 @@ func (m *SecretKeySelector) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n184, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n187, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n184 + i += n187 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) @@ -9222,11 +9308,11 @@ func (m *SecretList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n185, err := m.ListMeta.MarshalTo(dAtA[i:]) + n188, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n185 + i += n188 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9260,11 +9346,11 @@ func (m *SecretProjection) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n186, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n189, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n186 + i += n189 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9384,11 +9470,11 @@ func (m *SecurityContext) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Capabilities.Size())) - n187, err := m.Capabilities.MarshalTo(dAtA[i:]) + n190, err := m.Capabilities.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n187 + i += n190 } if m.Privileged != nil { dAtA[i] = 0x10 @@ -9404,11 +9490,11 @@ func (m *SecurityContext) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SELinuxOptions.Size())) - n188, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) + n191, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n188 + i += n191 } if m.RunAsUser != nil { dAtA[i] = 0x20 @@ -9471,11 +9557,11 @@ func (m *SerializedReference) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Reference.Size())) - n189, err := m.Reference.MarshalTo(dAtA[i:]) + n192, err := m.Reference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n189 + i += n192 return i, nil } @@ -9497,27 +9583,27 @@ func (m *Service) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n190, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n193, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n190 + i += n193 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n191, err := m.Spec.MarshalTo(dAtA[i:]) + n194, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n191 + i += n194 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n192, err := m.Status.MarshalTo(dAtA[i:]) + n195, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n192 + i += n195 return i, nil } @@ -9539,11 +9625,11 @@ func (m *ServiceAccount) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n193, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n196, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n193 + i += n196 if len(m.Secrets) > 0 { for _, msg := range m.Secrets { dAtA[i] = 0x12 @@ -9599,11 +9685,11 @@ func (m *ServiceAccountList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n194, err := m.ListMeta.MarshalTo(dAtA[i:]) + n197, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n194 + i += n197 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9619,6 +9705,37 @@ func (m *ServiceAccountList) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ServiceAccountTokenProjection) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ServiceAccountTokenProjection) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Audience))) + i += copy(dAtA[i:], m.Audience) + if m.ExpirationSeconds != nil { + dAtA[i] = 0x10 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(*m.ExpirationSeconds)) + } + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Path))) + i += copy(dAtA[i:], m.Path) + return i, nil +} + func (m *ServiceList) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -9637,11 +9754,11 @@ func (m *ServiceList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n195, err := m.ListMeta.MarshalTo(dAtA[i:]) + n198, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n195 + i += n198 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9686,11 +9803,11 @@ func (m *ServicePort) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TargetPort.Size())) - n196, err := m.TargetPort.MarshalTo(dAtA[i:]) + n199, err := m.TargetPort.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n196 + i += n199 dAtA[i] = 0x28 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NodePort)) @@ -9837,11 +9954,11 @@ func (m *ServiceSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SessionAffinityConfig.Size())) - n197, err := m.SessionAffinityConfig.MarshalTo(dAtA[i:]) + n200, err := m.SessionAffinityConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n197 + i += n200 } return i, nil } @@ -9864,11 +9981,11 @@ func (m *ServiceStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LoadBalancer.Size())) - n198, err := m.LoadBalancer.MarshalTo(dAtA[i:]) + n201, err := m.LoadBalancer.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n198 + i += n201 return i, nil } @@ -9891,11 +10008,11 @@ func (m *SessionAffinityConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ClientIP.Size())) - n199, err := m.ClientIP.MarshalTo(dAtA[i:]) + n202, err := m.ClientIP.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n199 + i += n202 } return i, nil } @@ -9939,11 +10056,11 @@ func (m *StorageOSPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n200, err := m.SecretRef.MarshalTo(dAtA[i:]) + n203, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n200 + i += n203 } return i, nil } @@ -9987,11 +10104,11 @@ func (m *StorageOSVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n201, err := m.SecretRef.MarshalTo(dAtA[i:]) + n204, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n201 + i += n204 } return i, nil } @@ -10040,11 +10157,11 @@ func (m *TCPSocketAction) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Port.Size())) - n202, err := m.Port.MarshalTo(dAtA[i:]) + n205, err := m.Port.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n202 + i += n205 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Host))) @@ -10083,11 +10200,11 @@ func (m *Taint) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TimeAdded.Size())) - n203, err := m.TimeAdded.MarshalTo(dAtA[i:]) + n206, err := m.TimeAdded.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n203 + i += n206 } return i, nil } @@ -10131,6 +10248,73 @@ func (m *Toleration) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *TopologySelectorLabelRequirement) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TopologySelectorLabelRequirement) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) + i += copy(dAtA[i:], m.Key) + if len(m.Values) > 0 { + for _, s := range m.Values { + dAtA[i] = 0x12 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + +func (m *TopologySelectorTerm) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TopologySelectorTerm) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.MatchLabelExpressions) > 0 { + for _, msg := range m.MatchLabelExpressions { + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + func (m *Volume) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -10153,11 +10337,11 @@ func (m *Volume) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.VolumeSource.Size())) - n204, err := m.VolumeSource.MarshalTo(dAtA[i:]) + n207, err := m.VolumeSource.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n204 + i += n207 return i, nil } @@ -10250,11 +10434,11 @@ func (m *VolumeNodeAffinity) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Required.Size())) - n205, err := m.Required.MarshalTo(dAtA[i:]) + n208, err := m.Required.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n205 + i += n208 } return i, nil } @@ -10278,31 +10462,41 @@ func (m *VolumeProjection) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Secret.Size())) - n206, err := m.Secret.MarshalTo(dAtA[i:]) + n209, err := m.Secret.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n206 + i += n209 } if m.DownwardAPI != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DownwardAPI.Size())) - n207, err := m.DownwardAPI.MarshalTo(dAtA[i:]) + n210, err := m.DownwardAPI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n207 + i += n210 } if m.ConfigMap != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMap.Size())) - n208, err := m.ConfigMap.MarshalTo(dAtA[i:]) + n211, err := m.ConfigMap.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n208 + i += n211 + } + if m.ServiceAccountToken != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ServiceAccountToken.Size())) + n212, err := m.ServiceAccountToken.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n212 } return i, nil } @@ -10326,151 +10520,151 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.HostPath.Size())) - n209, err := m.HostPath.MarshalTo(dAtA[i:]) + n213, err := m.HostPath.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n209 + i += n213 } if m.EmptyDir != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.EmptyDir.Size())) - n210, err := m.EmptyDir.MarshalTo(dAtA[i:]) + n214, err := m.EmptyDir.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n210 + i += n214 } if m.GCEPersistentDisk != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.GCEPersistentDisk.Size())) - n211, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) + n215, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n211 + i += n215 } if m.AWSElasticBlockStore != nil { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AWSElasticBlockStore.Size())) - n212, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) + n216, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n212 + i += n216 } if m.GitRepo != nil { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.GitRepo.Size())) - n213, err := m.GitRepo.MarshalTo(dAtA[i:]) + n217, err := m.GitRepo.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n213 + i += n217 } if m.Secret != nil { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Secret.Size())) - n214, err := m.Secret.MarshalTo(dAtA[i:]) + n218, err := m.Secret.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n214 + i += n218 } if m.NFS != nil { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NFS.Size())) - n215, err := m.NFS.MarshalTo(dAtA[i:]) + n219, err := m.NFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n215 + i += n219 } if m.ISCSI != nil { dAtA[i] = 0x42 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ISCSI.Size())) - n216, err := m.ISCSI.MarshalTo(dAtA[i:]) + n220, err := m.ISCSI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n216 + i += n220 } if m.Glusterfs != nil { dAtA[i] = 0x4a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Glusterfs.Size())) - n217, err := m.Glusterfs.MarshalTo(dAtA[i:]) + n221, err := m.Glusterfs.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n217 + i += n221 } if m.PersistentVolumeClaim != nil { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PersistentVolumeClaim.Size())) - n218, err := m.PersistentVolumeClaim.MarshalTo(dAtA[i:]) + n222, err := m.PersistentVolumeClaim.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n218 + i += n222 } if m.RBD != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.RBD.Size())) - n219, err := m.RBD.MarshalTo(dAtA[i:]) + n223, err := m.RBD.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n219 + i += n223 } if m.FlexVolume != nil { dAtA[i] = 0x62 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FlexVolume.Size())) - n220, err := m.FlexVolume.MarshalTo(dAtA[i:]) + n224, err := m.FlexVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n220 + i += n224 } if m.Cinder != nil { dAtA[i] = 0x6a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Cinder.Size())) - n221, err := m.Cinder.MarshalTo(dAtA[i:]) + n225, err := m.Cinder.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n221 + i += n225 } if m.CephFS != nil { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.CephFS.Size())) - n222, err := m.CephFS.MarshalTo(dAtA[i:]) + n226, err := m.CephFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n222 + i += n226 } if m.Flocker != nil { dAtA[i] = 0x7a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Flocker.Size())) - n223, err := m.Flocker.MarshalTo(dAtA[i:]) + n227, err := m.Flocker.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n223 + i += n227 } if m.DownwardAPI != nil { dAtA[i] = 0x82 @@ -10478,11 +10672,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DownwardAPI.Size())) - n224, err := m.DownwardAPI.MarshalTo(dAtA[i:]) + n228, err := m.DownwardAPI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n224 + i += n228 } if m.FC != nil { dAtA[i] = 0x8a @@ -10490,11 +10684,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FC.Size())) - n225, err := m.FC.MarshalTo(dAtA[i:]) + n229, err := m.FC.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n225 + i += n229 } if m.AzureFile != nil { dAtA[i] = 0x92 @@ -10502,11 +10696,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureFile.Size())) - n226, err := m.AzureFile.MarshalTo(dAtA[i:]) + n230, err := m.AzureFile.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n226 + i += n230 } if m.ConfigMap != nil { dAtA[i] = 0x9a @@ -10514,11 +10708,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMap.Size())) - n227, err := m.ConfigMap.MarshalTo(dAtA[i:]) + n231, err := m.ConfigMap.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n227 + i += n231 } if m.VsphereVolume != nil { dAtA[i] = 0xa2 @@ -10526,11 +10720,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.VsphereVolume.Size())) - n228, err := m.VsphereVolume.MarshalTo(dAtA[i:]) + n232, err := m.VsphereVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n228 + i += n232 } if m.Quobyte != nil { dAtA[i] = 0xaa @@ -10538,11 +10732,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Quobyte.Size())) - n229, err := m.Quobyte.MarshalTo(dAtA[i:]) + n233, err := m.Quobyte.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n229 + i += n233 } if m.AzureDisk != nil { dAtA[i] = 0xb2 @@ -10550,11 +10744,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureDisk.Size())) - n230, err := m.AzureDisk.MarshalTo(dAtA[i:]) + n234, err := m.AzureDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n230 + i += n234 } if m.PhotonPersistentDisk != nil { dAtA[i] = 0xba @@ -10562,11 +10756,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PhotonPersistentDisk.Size())) - n231, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) + n235, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n231 + i += n235 } if m.PortworxVolume != nil { dAtA[i] = 0xc2 @@ -10574,11 +10768,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PortworxVolume.Size())) - n232, err := m.PortworxVolume.MarshalTo(dAtA[i:]) + n236, err := m.PortworxVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n232 + i += n236 } if m.ScaleIO != nil { dAtA[i] = 0xca @@ -10586,11 +10780,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ScaleIO.Size())) - n233, err := m.ScaleIO.MarshalTo(dAtA[i:]) + n237, err := m.ScaleIO.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n233 + i += n237 } if m.Projected != nil { dAtA[i] = 0xd2 @@ -10598,11 +10792,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Projected.Size())) - n234, err := m.Projected.MarshalTo(dAtA[i:]) + n238, err := m.Projected.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n234 + i += n238 } if m.StorageOS != nil { dAtA[i] = 0xda @@ -10610,11 +10804,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StorageOS.Size())) - n235, err := m.StorageOS.MarshalTo(dAtA[i:]) + n239, err := m.StorageOS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n235 + i += n239 } return i, nil } @@ -10674,11 +10868,11 @@ func (m *WeightedPodAffinityTerm) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PodAffinityTerm.Size())) - n236, err := m.PodAffinityTerm.MarshalTo(dAtA[i:]) + n240, err := m.PodAffinityTerm.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n236 + i += n240 return i, nil } @@ -10919,6 +11113,21 @@ func (m *CephFSVolumeSource) Size() (n int) { return n } +func (m *CinderPersistentVolumeSource) Size() (n int) { + var l int + _ = l + l = len(m.VolumeID) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.FSType) + n += 1 + l + sovGenerated(uint64(l)) + n += 2 + if m.SecretRef != nil { + l = m.SecretRef.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *CinderVolumeSource) Size() (n int) { var l int _ = l @@ -10927,6 +11136,10 @@ func (m *CinderVolumeSource) Size() (n int) { l = len(m.FSType) n += 1 + l + sovGenerated(uint64(l)) n += 2 + if m.SecretRef != nil { + l = m.SecretRef.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -11047,6 +11260,22 @@ func (m *ConfigMapList) Size() (n int) { return n } +func (m *ConfigMapNodeConfigSource) Size() (n int) { + var l int + _ = l + l = len(m.Namespace) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.UID) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.ResourceVersion) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.KubeletConfigKey) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *ConfigMapProjection) Size() (n int) { var l int _ = l @@ -11273,26 +11502,6 @@ func (m *DaemonEndpoint) Size() (n int) { return n } -func (m *DeleteOptions) Size() (n int) { - var l int - _ = l - if m.GracePeriodSeconds != nil { - n += 1 + sovGenerated(uint64(*m.GracePeriodSeconds)) - } - if m.Preconditions != nil { - l = m.Preconditions.Size() - n += 1 + l + sovGenerated(uint64(l)) - } - if m.OrphanDependents != nil { - n += 2 - } - if m.PropagationPolicy != nil { - l = len(*m.PropagationPolicy) - n += 1 + l + sovGenerated(uint64(l)) - } - return n -} - func (m *DownwardAPIProjection) Size() (n int) { var l int _ = l @@ -11953,23 +12162,6 @@ func (m *List) Size() (n int) { return n } -func (m *ListOptions) Size() (n int) { - var l int - _ = l - l = len(m.LabelSelector) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.FieldSelector) - n += 1 + l + sovGenerated(uint64(l)) - n += 2 - l = len(m.ResourceVersion) - n += 1 + l + sovGenerated(uint64(l)) - if m.TimeoutSeconds != nil { - n += 1 + sovGenerated(uint64(*m.TimeoutSeconds)) - } - n += 2 - return n -} - func (m *LoadBalancerIngress) Size() (n int) { var l int _ = l @@ -12124,10 +12316,30 @@ func (m *NodeCondition) Size() (n int) { func (m *NodeConfigSource) Size() (n int) { var l int _ = l - if m.ConfigMapRef != nil { - l = m.ConfigMapRef.Size() + if m.ConfigMap != nil { + l = m.ConfigMap.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + +func (m *NodeConfigStatus) Size() (n int) { + var l int + _ = l + if m.Assigned != nil { + l = m.Assigned.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.Active != nil { + l = m.Active.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.LastKnownGood != nil { + l = m.LastKnownGood.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + l = len(m.Error) + n += 1 + l + sovGenerated(uint64(l)) return n } @@ -12213,6 +12425,12 @@ func (m *NodeSelectorTerm) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if len(m.MatchFields) > 0 { + for _, e := range m.MatchFields { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -12221,7 +12439,7 @@ func (m *NodeSpec) Size() (n int) { _ = l l = len(m.PodCIDR) n += 1 + l + sovGenerated(uint64(l)) - l = len(m.ExternalID) + l = len(m.DoNotUse_ExternalID) n += 1 + l + sovGenerated(uint64(l)) l = len(m.ProviderID) n += 1 + l + sovGenerated(uint64(l)) @@ -12296,6 +12514,10 @@ func (m *NodeStatus) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if m.Config != nil { + l = m.Config.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -12335,68 +12557,6 @@ func (m *ObjectFieldSelector) Size() (n int) { return n } -func (m *ObjectMeta) Size() (n int) { - var l int - _ = l - l = len(m.Name) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.GenerateName) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.Namespace) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.SelfLink) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.UID) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.ResourceVersion) - n += 1 + l + sovGenerated(uint64(l)) - n += 1 + sovGenerated(uint64(m.Generation)) - l = m.CreationTimestamp.Size() - n += 1 + l + sovGenerated(uint64(l)) - if m.DeletionTimestamp != nil { - l = m.DeletionTimestamp.Size() - n += 1 + l + sovGenerated(uint64(l)) - } - if m.DeletionGracePeriodSeconds != nil { - n += 1 + sovGenerated(uint64(*m.DeletionGracePeriodSeconds)) - } - if len(m.Labels) > 0 { - for k, v := range m.Labels { - _ = k - _ = v - mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) - n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) - } - } - if len(m.Annotations) > 0 { - for k, v := range m.Annotations { - _ = k - _ = v - mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) - n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) - } - } - if len(m.OwnerReferences) > 0 { - for _, e := range m.OwnerReferences { - l = e.Size() - n += 1 + l + sovGenerated(uint64(l)) - } - } - if len(m.Finalizers) > 0 { - for _, s := range m.Finalizers { - l = len(s) - n += 1 + l + sovGenerated(uint64(l)) - } - } - l = len(m.ClusterName) - n += 1 + l + sovGenerated(uint64(l)) - if m.Initializers != nil { - l = m.Initializers.Size() - n += 2 + l + sovGenerated(uint64(l)) - } - return n -} - func (m *ObjectReference) Size() (n int) { var l int _ = l @@ -12921,6 +13081,14 @@ func (m *PodProxyOptions) Size() (n int) { return n } +func (m *PodReadinessGate) Size() (n int) { + var l int + _ = l + l = len(m.ConditionType) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *PodSecurityContext) Size() (n int) { var l int _ = l @@ -12945,6 +13113,12 @@ func (m *PodSecurityContext) Size() (n int) { if m.RunAsGroup != nil { n += 1 + sovGenerated(uint64(*m.RunAsGroup)) } + if len(m.Sysctls) > 0 { + for _, e := range m.Sysctls { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -13053,6 +13227,12 @@ func (m *PodSpec) Size() (n int) { if m.ShareProcessNamespace != nil { n += 3 } + if len(m.ReadinessGates) > 0 { + for _, e := range m.ReadinessGates { + l = e.Size() + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -13434,6 +13614,10 @@ func (m *ResourceQuotaSpec) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if m.ScopeSelector != nil { + l = m.ScopeSelector.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -13551,6 +13735,34 @@ func (m *ScaleIOVolumeSource) Size() (n int) { return n } +func (m *ScopeSelector) Size() (n int) { + var l int + _ = l + if len(m.MatchExpressions) > 0 { + for _, e := range m.MatchExpressions { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *ScopedResourceSelectorRequirement) Size() (n int) { + var l int + _ = l + l = len(m.ScopeName) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Operator) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Values) > 0 { + for _, s := range m.Values { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + func (m *Secret) Size() (n int) { var l int _ = l @@ -13755,6 +13967,19 @@ func (m *ServiceAccountList) Size() (n int) { return n } +func (m *ServiceAccountTokenProjection) Size() (n int) { + var l int + _ = l + l = len(m.Audience) + n += 1 + l + sovGenerated(uint64(l)) + if m.ExpirationSeconds != nil { + n += 1 + sovGenerated(uint64(*m.ExpirationSeconds)) + } + l = len(m.Path) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *ServiceList) Size() (n int) { var l int _ = l @@ -13946,6 +14171,32 @@ func (m *Toleration) Size() (n int) { return n } +func (m *TopologySelectorLabelRequirement) Size() (n int) { + var l int + _ = l + l = len(m.Key) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Values) > 0 { + for _, s := range m.Values { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *TopologySelectorTerm) Size() (n int) { + var l int + _ = l + if len(m.MatchLabelExpressions) > 0 { + for _, e := range m.MatchLabelExpressions { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + func (m *Volume) Size() (n int) { var l int _ = l @@ -14008,6 +14259,10 @@ func (m *VolumeProjection) Size() (n int) { l = m.ConfigMap.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.ServiceAccountToken != nil { + l = m.ServiceAccountToken.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -14326,6 +14581,19 @@ func (this *CephFSVolumeSource) String() string { }, "") return s } +func (this *CinderPersistentVolumeSource) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CinderPersistentVolumeSource{`, + `VolumeID:` + fmt.Sprintf("%v", this.VolumeID) + `,`, + `FSType:` + fmt.Sprintf("%v", this.FSType) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, + `SecretRef:` + strings.Replace(fmt.Sprintf("%v", this.SecretRef), "SecretReference", "SecretReference", 1) + `,`, + `}`, + }, "") + return s +} func (this *CinderVolumeSource) String() string { if this == nil { return "nil" @@ -14334,6 +14602,7 @@ func (this *CinderVolumeSource) String() string { `VolumeID:` + fmt.Sprintf("%v", this.VolumeID) + `,`, `FSType:` + fmt.Sprintf("%v", this.FSType) + `,`, `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, + `SecretRef:` + strings.Replace(fmt.Sprintf("%v", this.SecretRef), "LocalObjectReference", "LocalObjectReference", 1) + `,`, `}`, }, "") return s @@ -14449,6 +14718,20 @@ func (this *ConfigMapList) String() string { }, "") return s } +func (this *ConfigMapNodeConfigSource) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ConfigMapNodeConfigSource{`, + `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `UID:` + fmt.Sprintf("%v", this.UID) + `,`, + `ResourceVersion:` + fmt.Sprintf("%v", this.ResourceVersion) + `,`, + `KubeletConfigKey:` + fmt.Sprintf("%v", this.KubeletConfigKey) + `,`, + `}`, + }, "") + return s +} func (this *ConfigMapProjection) String() string { if this == nil { return "nil" @@ -14605,19 +14888,6 @@ func (this *DaemonEndpoint) String() string { }, "") return s } -func (this *DeleteOptions) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&DeleteOptions{`, - `GracePeriodSeconds:` + valueToStringGenerated(this.GracePeriodSeconds) + `,`, - `Preconditions:` + strings.Replace(fmt.Sprintf("%v", this.Preconditions), "Preconditions", "Preconditions", 1) + `,`, - `OrphanDependents:` + valueToStringGenerated(this.OrphanDependents) + `,`, - `PropagationPolicy:` + valueToStringGenerated(this.PropagationPolicy) + `,`, - `}`, - }, "") - return s -} func (this *DownwardAPIProjection) String() string { if this == nil { return "nil" @@ -15167,21 +15437,6 @@ func (this *List) String() string { }, "") return s } -func (this *ListOptions) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&ListOptions{`, - `LabelSelector:` + fmt.Sprintf("%v", this.LabelSelector) + `,`, - `FieldSelector:` + fmt.Sprintf("%v", this.FieldSelector) + `,`, - `Watch:` + fmt.Sprintf("%v", this.Watch) + `,`, - `ResourceVersion:` + fmt.Sprintf("%v", this.ResourceVersion) + `,`, - `TimeoutSeconds:` + valueToStringGenerated(this.TimeoutSeconds) + `,`, - `IncludeUninitialized:` + fmt.Sprintf("%v", this.IncludeUninitialized) + `,`, - `}`, - }, "") - return s -} func (this *LoadBalancerIngress) String() string { if this == nil { return "nil" @@ -15332,7 +15587,20 @@ func (this *NodeConfigSource) String() string { return "nil" } s := strings.Join([]string{`&NodeConfigSource{`, - `ConfigMapRef:` + strings.Replace(fmt.Sprintf("%v", this.ConfigMapRef), "ObjectReference", "ObjectReference", 1) + `,`, + `ConfigMap:` + strings.Replace(fmt.Sprintf("%v", this.ConfigMap), "ConfigMapNodeConfigSource", "ConfigMapNodeConfigSource", 1) + `,`, + `}`, + }, "") + return s +} +func (this *NodeConfigStatus) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&NodeConfigStatus{`, + `Assigned:` + strings.Replace(fmt.Sprintf("%v", this.Assigned), "NodeConfigSource", "NodeConfigSource", 1) + `,`, + `Active:` + strings.Replace(fmt.Sprintf("%v", this.Active), "NodeConfigSource", "NodeConfigSource", 1) + `,`, + `LastKnownGood:` + strings.Replace(fmt.Sprintf("%v", this.LastKnownGood), "NodeConfigSource", "NodeConfigSource", 1) + `,`, + `Error:` + fmt.Sprintf("%v", this.Error) + `,`, `}`, }, "") return s @@ -15416,6 +15684,7 @@ func (this *NodeSelectorTerm) String() string { } s := strings.Join([]string{`&NodeSelectorTerm{`, `MatchExpressions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchExpressions), "NodeSelectorRequirement", "NodeSelectorRequirement", 1), `&`, ``, 1) + `,`, + `MatchFields:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchFields), "NodeSelectorRequirement", "NodeSelectorRequirement", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -15426,7 +15695,7 @@ func (this *NodeSpec) String() string { } s := strings.Join([]string{`&NodeSpec{`, `PodCIDR:` + fmt.Sprintf("%v", this.PodCIDR) + `,`, - `ExternalID:` + fmt.Sprintf("%v", this.ExternalID) + `,`, + `DoNotUse_ExternalID:` + fmt.Sprintf("%v", this.DoNotUse_ExternalID) + `,`, `ProviderID:` + fmt.Sprintf("%v", this.ProviderID) + `,`, `Unschedulable:` + fmt.Sprintf("%v", this.Unschedulable) + `,`, `Taints:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Taints), "Taint", "Taint", 1), `&`, ``, 1) + `,`, @@ -15470,6 +15739,7 @@ func (this *NodeStatus) String() string { `Images:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Images), "ContainerImage", "ContainerImage", 1), `&`, ``, 1) + `,`, `VolumesInUse:` + fmt.Sprintf("%v", this.VolumesInUse) + `,`, `VolumesAttached:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.VolumesAttached), "AttachedVolume", "AttachedVolume", 1), `&`, ``, 1) + `,`, + `Config:` + strings.Replace(fmt.Sprintf("%v", this.Config), "NodeConfigStatus", "NodeConfigStatus", 1) + `,`, `}`, }, "") return s @@ -15504,51 +15774,6 @@ func (this *ObjectFieldSelector) String() string { }, "") return s } -func (this *ObjectMeta) String() string { - if this == nil { - return "nil" - } - keysForLabels := make([]string, 0, len(this.Labels)) - for k := range this.Labels { - keysForLabels = append(keysForLabels, k) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) - mapStringForLabels := "map[string]string{" - for _, k := range keysForLabels { - mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) - } - mapStringForLabels += "}" - keysForAnnotations := make([]string, 0, len(this.Annotations)) - for k := range this.Annotations { - keysForAnnotations = append(keysForAnnotations, k) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations) - mapStringForAnnotations := "map[string]string{" - for _, k := range keysForAnnotations { - mapStringForAnnotations += fmt.Sprintf("%v: %v,", k, this.Annotations[k]) - } - mapStringForAnnotations += "}" - s := strings.Join([]string{`&ObjectMeta{`, - `Name:` + fmt.Sprintf("%v", this.Name) + `,`, - `GenerateName:` + fmt.Sprintf("%v", this.GenerateName) + `,`, - `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, - `SelfLink:` + fmt.Sprintf("%v", this.SelfLink) + `,`, - `UID:` + fmt.Sprintf("%v", this.UID) + `,`, - `ResourceVersion:` + fmt.Sprintf("%v", this.ResourceVersion) + `,`, - `Generation:` + fmt.Sprintf("%v", this.Generation) + `,`, - `CreationTimestamp:` + strings.Replace(strings.Replace(this.CreationTimestamp.String(), "Time", "k8s_io_apimachinery_pkg_apis_meta_v1.Time", 1), `&`, ``, 1) + `,`, - `DeletionTimestamp:` + strings.Replace(fmt.Sprintf("%v", this.DeletionTimestamp), "Time", "k8s_io_apimachinery_pkg_apis_meta_v1.Time", 1) + `,`, - `DeletionGracePeriodSeconds:` + valueToStringGenerated(this.DeletionGracePeriodSeconds) + `,`, - `Labels:` + mapStringForLabels + `,`, - `Annotations:` + mapStringForAnnotations + `,`, - `OwnerReferences:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.OwnerReferences), "OwnerReference", "k8s_io_apimachinery_pkg_apis_meta_v1.OwnerReference", 1), `&`, ``, 1) + `,`, - `Finalizers:` + fmt.Sprintf("%v", this.Finalizers) + `,`, - `ClusterName:` + fmt.Sprintf("%v", this.ClusterName) + `,`, - `Initializers:` + strings.Replace(fmt.Sprintf("%v", this.Initializers), "Initializers", "k8s_io_apimachinery_pkg_apis_meta_v1.Initializers", 1) + `,`, - `}`, - }, "") - return s -} func (this *ObjectReference) String() string { if this == nil { return "nil" @@ -15687,7 +15912,7 @@ func (this *PersistentVolumeSource) String() string { `NFS:` + strings.Replace(fmt.Sprintf("%v", this.NFS), "NFSVolumeSource", "NFSVolumeSource", 1) + `,`, `RBD:` + strings.Replace(fmt.Sprintf("%v", this.RBD), "RBDPersistentVolumeSource", "RBDPersistentVolumeSource", 1) + `,`, `ISCSI:` + strings.Replace(fmt.Sprintf("%v", this.ISCSI), "ISCSIPersistentVolumeSource", "ISCSIPersistentVolumeSource", 1) + `,`, - `Cinder:` + strings.Replace(fmt.Sprintf("%v", this.Cinder), "CinderVolumeSource", "CinderVolumeSource", 1) + `,`, + `Cinder:` + strings.Replace(fmt.Sprintf("%v", this.Cinder), "CinderPersistentVolumeSource", "CinderPersistentVolumeSource", 1) + `,`, `CephFS:` + strings.Replace(fmt.Sprintf("%v", this.CephFS), "CephFSPersistentVolumeSource", "CephFSPersistentVolumeSource", 1) + `,`, `FC:` + strings.Replace(fmt.Sprintf("%v", this.FC), "FCVolumeSource", "FCVolumeSource", 1) + `,`, `Flocker:` + strings.Replace(fmt.Sprintf("%v", this.Flocker), "FlockerVolumeSource", "FlockerVolumeSource", 1) + `,`, @@ -15918,6 +16143,16 @@ func (this *PodProxyOptions) String() string { }, "") return s } +func (this *PodReadinessGate) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodReadinessGate{`, + `ConditionType:` + fmt.Sprintf("%v", this.ConditionType) + `,`, + `}`, + }, "") + return s +} func (this *PodSecurityContext) String() string { if this == nil { return "nil" @@ -15929,6 +16164,7 @@ func (this *PodSecurityContext) String() string { `SupplementalGroups:` + fmt.Sprintf("%v", this.SupplementalGroups) + `,`, `FSGroup:` + valueToStringGenerated(this.FSGroup) + `,`, `RunAsGroup:` + valueToStringGenerated(this.RunAsGroup) + `,`, + `Sysctls:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Sysctls), "Sysctl", "Sysctl", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -15985,6 +16221,7 @@ func (this *PodSpec) String() string { `Priority:` + valueToStringGenerated(this.Priority) + `,`, `DNSConfig:` + strings.Replace(fmt.Sprintf("%v", this.DNSConfig), "PodDNSConfig", "PodDNSConfig", 1) + `,`, `ShareProcessNamespace:` + valueToStringGenerated(this.ShareProcessNamespace) + `,`, + `ReadinessGates:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ReadinessGates), "PodReadinessGate", "PodReadinessGate", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -16312,6 +16549,7 @@ func (this *ResourceQuotaSpec) String() string { s := strings.Join([]string{`&ResourceQuotaSpec{`, `Hard:` + mapStringForHard + `,`, `Scopes:` + fmt.Sprintf("%v", this.Scopes) + `,`, + `ScopeSelector:` + strings.Replace(fmt.Sprintf("%v", this.ScopeSelector), "ScopeSelector", "ScopeSelector", 1) + `,`, `}`, }, "") return s @@ -16429,6 +16667,28 @@ func (this *ScaleIOVolumeSource) String() string { }, "") return s } +func (this *ScopeSelector) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ScopeSelector{`, + `MatchExpressions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchExpressions), "ScopedResourceSelectorRequirement", "ScopedResourceSelectorRequirement", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *ScopedResourceSelectorRequirement) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ScopedResourceSelectorRequirement{`, + `ScopeName:` + fmt.Sprintf("%v", this.ScopeName) + `,`, + `Operator:` + fmt.Sprintf("%v", this.Operator) + `,`, + `Values:` + fmt.Sprintf("%v", this.Values) + `,`, + `}`, + }, "") + return s +} func (this *Secret) String() string { if this == nil { return "nil" @@ -16595,6 +16855,18 @@ func (this *ServiceAccountList) String() string { }, "") return s } +func (this *ServiceAccountTokenProjection) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ServiceAccountTokenProjection{`, + `Audience:` + fmt.Sprintf("%v", this.Audience) + `,`, + `ExpirationSeconds:` + valueToStringGenerated(this.ExpirationSeconds) + `,`, + `Path:` + fmt.Sprintf("%v", this.Path) + `,`, + `}`, + }, "") + return s +} func (this *ServiceList) String() string { if this == nil { return "nil" @@ -16759,6 +17031,27 @@ func (this *Toleration) String() string { }, "") return s } +func (this *TopologySelectorLabelRequirement) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&TopologySelectorLabelRequirement{`, + `Key:` + fmt.Sprintf("%v", this.Key) + `,`, + `Values:` + fmt.Sprintf("%v", this.Values) + `,`, + `}`, + }, "") + return s +} +func (this *TopologySelectorTerm) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&TopologySelectorTerm{`, + `MatchLabelExpressions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchLabelExpressions), "TopologySelectorLabelRequirement", "TopologySelectorLabelRequirement", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} func (this *Volume) String() string { if this == nil { return "nil" @@ -16813,6 +17106,7 @@ func (this *VolumeProjection) String() string { `Secret:` + strings.Replace(fmt.Sprintf("%v", this.Secret), "SecretProjection", "SecretProjection", 1) + `,`, `DownwardAPI:` + strings.Replace(fmt.Sprintf("%v", this.DownwardAPI), "DownwardAPIProjection", "DownwardAPIProjection", 1) + `,`, `ConfigMap:` + strings.Replace(fmt.Sprintf("%v", this.ConfigMap), "ConfigMapProjection", "ConfigMapProjection", 1) + `,`, + `ServiceAccountToken:` + strings.Replace(fmt.Sprintf("%v", this.ServiceAccountToken), "ServiceAccountTokenProjection", "ServiceAccountTokenProjection", 1) + `,`, `}`, }, "") return s @@ -18903,7 +19197,7 @@ func (m *CephFSVolumeSource) Unmarshal(dAtA []byte) error { } return nil } -func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { +func (m *CinderPersistentVolumeSource) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -18926,10 +19220,10 @@ func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CinderVolumeSource: wiretype end group for non-group") + return fmt.Errorf("proto: CinderPersistentVolumeSource: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CinderVolumeSource: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CinderPersistentVolumeSource: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -19010,61 +19304,11 @@ func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { } } m.ReadOnly = bool(v != 0) - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ClientIPConfig) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ClientIPConfig: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientIPConfig: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TimeoutSeconds", wireType) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecretRef", wireType) } - var v int32 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -19074,12 +19318,256 @@ func (m *ClientIPConfig) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int32(b) & 0x7F) << shift + msglen |= (int(b) & 0x7F) << shift if b < 0x80 { break } } - m.TimeoutSeconds = &v + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SecretRef == nil { + m.SecretRef = &SecretReference{} + } + if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CinderVolumeSource: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CinderVolumeSource: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VolumeID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VolumeID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FSType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FSType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecretRef", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SecretRef == nil { + m.SecretRef = &LocalObjectReference{} + } + if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ClientIPConfig) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClientIPConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClientIPConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeoutSeconds", wireType) + } + var v int32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.TimeoutSeconds = &v default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -20144,7 +20632,7 @@ func (m *ConfigMapList) Unmarshal(dAtA []byte) error { } return nil } -func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { +func (m *ConfigMapNodeConfigSource) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -20167,17 +20655,17 @@ func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ConfigMapProjection: wiretype end group for non-group") + return fmt.Errorf("proto: ConfigMapNodeConfigSource: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ConfigMapProjection: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ConfigMapNodeConfigSource: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LocalObjectReference", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -20187,27 +20675,26 @@ func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.LocalObjectReference.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Namespace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -20217,28 +20704,55 @@ func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - m.Items = append(m.Items, KeyToPath{}) - if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UID = k8s_io_apimachinery_pkg_types.UID(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Optional", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceVersion", wireType) } - var v int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -20248,13 +20762,182 @@ func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - b := bool(v != 0) - m.Optional = &b + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ResourceVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field KubeletConfigKey", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.KubeletConfigKey = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConfigMapProjection: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConfigMapProjection: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalObjectReference", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LocalObjectReference.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, KeyToPath{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Optional", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.Optional = &b default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -22266,160 +22949,6 @@ func (m *DaemonEndpoint) Unmarshal(dAtA []byte) error { } return nil } -func (m *DeleteOptions) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: DeleteOptions: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteOptions: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field GracePeriodSeconds", wireType) - } - var v int64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.GracePeriodSeconds = &v - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Preconditions", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Preconditions == nil { - m.Preconditions = &Preconditions{} - } - if err := m.Preconditions.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OrphanDependents", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - b := bool(v != 0) - m.OrphanDependents = &b - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PropagationPolicy", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - s := DeletionPropagation(dAtA[iNdEx:postIndex]) - m.PropagationPolicy = &s - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *DownwardAPIProjection) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -28863,203 +29392,6 @@ func (m *List) Unmarshal(dAtA []byte) error { } return nil } -func (m *ListOptions) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ListOptions: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ListOptions: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LabelSelector", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.LabelSelector = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field FieldSelector", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.FieldSelector = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Watch", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.Watch = bool(v != 0) - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ResourceVersion", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ResourceVersion = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TimeoutSeconds", wireType) - } - var v int64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.TimeoutSeconds = &v - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IncludeUninitialized", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.IncludeUninitialized = bool(v != 0) - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *LoadBalancerIngress) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -30561,9 +30893,9 @@ func (m *NodeConfigSource) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: NodeConfigSource: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConfigMapRef", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ConfigMap", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -30587,10 +30919,10 @@ func (m *NodeConfigSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.ConfigMapRef == nil { - m.ConfigMapRef = &ObjectReference{} + if m.ConfigMap == nil { + m.ConfigMap = &ConfigMapNodeConfigSource{} } - if err := m.ConfigMapRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.ConfigMap.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -30615,7 +30947,7 @@ func (m *NodeConfigSource) Unmarshal(dAtA []byte) error { } return nil } -func (m *NodeDaemonEndpoints) Unmarshal(dAtA []byte) error { +func (m *NodeConfigStatus) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -30638,15 +30970,15 @@ func (m *NodeDaemonEndpoints) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: NodeDaemonEndpoints: wiretype end group for non-group") + return fmt.Errorf("proto: NodeConfigStatus: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: NodeDaemonEndpoints: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: NodeConfigStatus: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field KubeletEndpoint", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Assigned", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -30670,63 +31002,16 @@ func (m *NodeDaemonEndpoints) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.KubeletEndpoint.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + if m.Assigned == nil { + m.Assigned = &NodeConfigSource{} } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { + if err := m.Assigned.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *NodeList) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: NodeList: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: NodeList: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + iNdEx = postIndex + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Active", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -30750,13 +31035,238 @@ func (m *NodeList) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if m.Active == nil { + m.Active = &NodeConfigSource{} + } + if err := m.Active.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 2: + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field LastKnownGood", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LastKnownGood == nil { + m.LastKnownGood = &NodeConfigSource{} + } + if err := m.LastKnownGood.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NodeDaemonEndpoints) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NodeDaemonEndpoints: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NodeDaemonEndpoints: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field KubeletEndpoint", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.KubeletEndpoint.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NodeList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NodeList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NodeList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -31334,6 +31844,37 @@ func (m *NodeSelectorTerm) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchFields", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MatchFields = append(m.MatchFields, NodeSelectorRequirement{}) + if err := m.MatchFields[len(m.MatchFields)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -31415,7 +31956,7 @@ func (m *NodeSpec) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ExternalID", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DoNotUse_ExternalID", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -31440,7 +31981,7 @@ func (m *NodeSpec) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ExternalID = string(dAtA[iNdEx:postIndex]) + m.DoNotUse_ExternalID = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { @@ -32089,6 +32630,39 @@ func (m *NodeStatus) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Config", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Config == nil { + m.Config = &NodeConfigStatus{} + } + if err := m.Config.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -32558,686 +33132,6 @@ func (m *ObjectFieldSelector) Unmarshal(dAtA []byte) error { } return nil } -func (m *ObjectMeta) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ObjectMeta: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ObjectMeta: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field GenerateName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.GenerateName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Namespace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SelfLink", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SelfLink = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UID", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.UID = k8s_io_apimachinery_pkg_types.UID(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ResourceVersion", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ResourceVersion = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 7: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Generation", wireType) - } - m.Generation = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Generation |= (int64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CreationTimestamp", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.CreationTimestamp.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DeletionTimestamp", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.DeletionTimestamp == nil { - m.DeletionTimestamp = &k8s_io_apimachinery_pkg_apis_meta_v1.Time{} - } - if err := m.DeletionTimestamp.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 10: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DeletionGracePeriodSeconds", wireType) - } - var v int64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.DeletionGracePeriodSeconds = &v - case 11: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - if m.Labels == nil { - m.Labels = make(map[string]string) - } - if iNdEx < postIndex { - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Labels[mapkey] = mapvalue - } else { - var mapvalue string - m.Labels[mapkey] = mapvalue - } - iNdEx = postIndex - case 12: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - if m.Annotations == nil { - m.Annotations = make(map[string]string) - } - if iNdEx < postIndex { - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Annotations[mapkey] = mapvalue - } else { - var mapvalue string - m.Annotations[mapkey] = mapvalue - } - iNdEx = postIndex - case 13: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OwnerReferences", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.OwnerReferences = append(m.OwnerReferences, k8s_io_apimachinery_pkg_apis_meta_v1.OwnerReference{}) - if err := m.OwnerReferences[len(m.OwnerReferences)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 14: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Finalizers", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Finalizers = append(m.Finalizers, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 15: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClusterName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ClusterName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 16: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Initializers", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Initializers == nil { - m.Initializers = &k8s_io_apimachinery_pkg_apis_meta_v1.Initializers{} - } - if err := m.Initializers.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *ObjectReference) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -35096,7 +34990,7 @@ func (m *PersistentVolumeSource) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Cinder == nil { - m.Cinder = &CinderVolumeSource{} + m.Cinder = &CinderPersistentVolumeSource{} } if err := m.Cinder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -38103,6 +37997,85 @@ func (m *PodProxyOptions) Unmarshal(dAtA []byte) error { } return nil } +func (m *PodReadinessGate) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodReadinessGate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodReadinessGate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConditionType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConditionType = PodConditionType(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *PodSecurityContext) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -38308,6 +38281,37 @@ func (m *PodSecurityContext) Unmarshal(dAtA []byte) error { } } m.RunAsGroup = &v + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sysctls", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sysctls = append(m.Sysctls, Sysctl{}) + if err := m.Sysctls[len(m.Sysctls)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -38955,13 +38959,247 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Hostname = string(dAtA[iNdEx:postIndex]) + m.Hostname = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subdomain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Subdomain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 18: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Affinity", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Affinity == nil { + m.Affinity = &Affinity{} + } + if err := m.Affinity.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SchedulerName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SchedulerName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitContainers", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.InitContainers = append(m.InitContainers, Container{}) + if err := m.InitContainers[len(m.InitContainers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 21: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AutomountServiceAccountToken", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.AutomountServiceAccountToken = &b + case 22: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tolerations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tolerations = append(m.Tolerations, Toleration{}) + if err := m.Tolerations[len(m.Tolerations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 23: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostAliases", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostAliases = append(m.HostAliases, HostAlias{}) + if err := m.HostAliases[len(m.HostAliases)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 24: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PriorityClassName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PriorityClassName = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 17: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Subdomain", wireType) + case 25: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) } - var stringLen uint64 + var v int32 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -38971,24 +39209,15 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + v |= (int32(b) & 0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Subdomain = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 18: + m.Priority = &v + case 26: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Affinity", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DNSConfig", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -39012,76 +39241,16 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Affinity == nil { - m.Affinity = &Affinity{} - } - if err := m.Affinity.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 19: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SchedulerName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SchedulerName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 20: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field InitContainers", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF + if m.DNSConfig == nil { + m.DNSConfig = &PodDNSConfig{} } - m.InitContainers = append(m.InitContainers, Container{}) - if err := m.InitContainers[len(m.InitContainers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.DNSConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 21: + case 27: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AutomountServiceAccountToken", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ShareProcessNamespace", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -39099,121 +39268,10 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { } } b := bool(v != 0) - m.AutomountServiceAccountToken = &b - case 22: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tolerations", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Tolerations = append(m.Tolerations, Toleration{}) - if err := m.Tolerations[len(m.Tolerations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 23: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostAliases", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.HostAliases = append(m.HostAliases, HostAlias{}) - if err := m.HostAliases[len(m.HostAliases)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 24: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PriorityClassName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.PriorityClassName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 25: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) - } - var v int32 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.Priority = &v - case 26: + m.ShareProcessNamespace = &b + case 28: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DNSConfig", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ReadinessGates", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -39237,34 +39295,11 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.DNSConfig == nil { - m.DNSConfig = &PodDNSConfig{} - } - if err := m.DNSConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.ReadinessGates = append(m.ReadinessGates, PodReadinessGate{}) + if err := m.ReadinessGates[len(m.ReadinessGates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 27: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ShareProcessNamespace", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - b := bool(v != 0) - m.ShareProcessNamespace = &b default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -43166,6 +43201,39 @@ func (m *ResourceQuotaSpec) Unmarshal(dAtA []byte) error { } m.Scopes = append(m.Scopes, ResourceQuotaScope(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ScopeSelector", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ScopeSelector == nil { + m.ScopeSelector = &ScopeSelector{} + } + if err := m.ScopeSelector.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -44376,94 +44444,332 @@ func (m *ScaleIOVolumeSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.SecretRef == nil { - m.SecretRef = &LocalObjectReference{} - } - if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if m.SecretRef == nil { + m.SecretRef = &LocalObjectReference{} + } + if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SSLEnabled", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.SSLEnabled = bool(v != 0) + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProtectionDomain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProtectionDomain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StoragePool", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StoragePool = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StorageMode", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StorageMode = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VolumeName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VolumeName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FSType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FSType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ScopeSelector) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ScopeSelector: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ScopeSelector: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchExpressions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MatchExpressions = append(m.MatchExpressions, ScopedResourceSelectorRequirement{}) + if err := m.MatchExpressions[len(m.MatchExpressions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field SSLEnabled", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.SSLEnabled = bool(v != 0) - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProtectionDomain", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err } - intStringLen := int(stringLen) - if intStringLen < 0 { + if skippy < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + intStringLen - if postIndex > l { + if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } - m.ProtectionDomain = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field StoragePool", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ScopedResourceSelectorRequirement) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated } - postIndex := iNdEx + intStringLen - if postIndex > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - m.StoragePool = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 7: + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ScopedResourceSelectorRequirement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ScopedResourceSelectorRequirement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field StorageMode", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ScopeName", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -44488,11 +44794,11 @@ func (m *ScaleIOVolumeSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.StorageMode = string(dAtA[iNdEx:postIndex]) + m.ScopeName = ResourceQuotaScope(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 8: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field VolumeName", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Operator", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -44517,11 +44823,11 @@ func (m *ScaleIOVolumeSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.VolumeName = string(dAtA[iNdEx:postIndex]) + m.Operator = ScopeSelectorOperator(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 9: + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field FSType", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Values", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -44546,28 +44852,8 @@ func (m *ScaleIOVolumeSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.FSType = string(dAtA[iNdEx:postIndex]) + m.Values = append(m.Values, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 10: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.ReadOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -46310,17 +46596,128 @@ func (m *ServiceAccountList) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ServiceAccountList: wiretype end group for non-group") + return fmt.Errorf("proto: ServiceAccountList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ServiceAccountList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, ServiceAccount{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ServiceAccountTokenProjection) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ServiceAccountTokenProjection: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ServiceAccountList: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ServiceAccountTokenProjection: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Audience", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -46330,27 +46727,46 @@ func (m *ServiceAccountList) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Audience = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpirationSeconds", wireType) + } + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ExpirationSeconds = &v + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -46360,22 +46776,20 @@ func (m *ServiceAccountList) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - m.Items = append(m.Items, ServiceAccount{}) - if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Path = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -48381,6 +48795,195 @@ func (m *Toleration) Unmarshal(dAtA []byte) error { } return nil } +func (m *TopologySelectorLabelRequirement) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TopologySelectorLabelRequirement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TopologySelectorLabelRequirement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Values", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Values = append(m.Values, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TopologySelectorTerm) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TopologySelectorTerm: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TopologySelectorTerm: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchLabelExpressions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MatchLabelExpressions = append(m.MatchLabelExpressions, TopologySelectorLabelRequirement{}) + if err := m.MatchLabelExpressions[len(m.MatchLabelExpressions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Volume) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -48996,6 +49599,39 @@ func (m *VolumeProjection) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ServiceAccountToken", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ServiceAccountToken == nil { + m.ServiceAccountToken = &ServiceAccountTokenProjection{} + } + if err := m.ServiceAccountToken.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -50333,797 +50969,797 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 12666 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x70, 0x24, 0x49, - 0x56, 0xd8, 0x55, 0xb7, 0xbe, 0xfa, 0xe9, 0x3b, 0x67, 0x66, 0x57, 0xa3, 0xdd, 0x9d, 0x9e, 0xad, - 0xbd, 0x9b, 0x9b, 0xfd, 0x92, 0x6e, 0x67, 0x77, 0x6f, 0x97, 0xdb, 0xbb, 0x05, 0x49, 0x2d, 0xcd, - 0xf4, 0xce, 0x48, 0xd3, 0x9b, 0xad, 0x99, 0xb9, 0x5b, 0x96, 0xf3, 0x95, 0xba, 0x53, 0xad, 0x5a, - 0x95, 0xaa, 0x7a, 0xab, 0xaa, 0x35, 0xa3, 0x0d, 0x88, 0xb0, 0x8f, 0x0f, 0x1b, 0xc3, 0x8f, 0x0b, - 0x43, 0xd8, 0x18, 0x08, 0x1c, 0x61, 0xe3, 0x80, 0x33, 0xb6, 0x23, 0x30, 0x18, 0xf0, 0x81, 0x6d, - 0x8c, 0xfd, 0x03, 0xfe, 0x60, 0xf0, 0x9f, 0x23, 0x82, 0xb0, 0x0c, 0x82, 0xb0, 0x83, 0x1f, 0x76, - 0x38, 0x4c, 0x84, 0x23, 0x90, 0xb1, 0x71, 0xe4, 0x67, 0x65, 0x56, 0x57, 0x75, 0xb7, 0x66, 0x35, - 0xda, 0x85, 0xb8, 0x7f, 0xdd, 0xf9, 0x5e, 0xbe, 0xcc, 0xca, 0x8f, 0x97, 0x2f, 0x5f, 0xbe, 0x0f, - 0x78, 0x63, 0xf7, 0xf5, 0x68, 0xc1, 0x0d, 0x16, 0x77, 0x3b, 0x5b, 0x24, 0xf4, 0x49, 0x4c, 0xa2, - 0xc5, 0x7d, 0xe2, 0x37, 0x83, 0x70, 0x51, 0x00, 0x9c, 0xb6, 0xbb, 0xd8, 0x08, 0x42, 0xb2, 0xb8, - 0xff, 0xd2, 0x62, 0x8b, 0xf8, 0x24, 0x74, 0x62, 0xd2, 0x5c, 0x68, 0x87, 0x41, 0x1c, 0x20, 0xc4, - 0x71, 0x16, 0x9c, 0xb6, 0xbb, 0x40, 0x71, 0x16, 0xf6, 0x5f, 0x9a, 0x7f, 0xb1, 0xe5, 0xc6, 0x3b, - 0x9d, 0xad, 0x85, 0x46, 0xb0, 0xb7, 0xd8, 0x0a, 0x5a, 0xc1, 0x22, 0x43, 0xdd, 0xea, 0x6c, 0xb3, - 0x7f, 0xec, 0x0f, 0xfb, 0xc5, 0x49, 0xcc, 0xaf, 0x27, 0xcd, 0x90, 0x07, 0x31, 0xf1, 0x23, 0x37, - 0xf0, 0xa3, 0x17, 0x9d, 0xb6, 0x1b, 0x91, 0x70, 0x9f, 0x84, 0x8b, 0xed, 0xdd, 0x16, 0x85, 0x45, - 0x26, 0xc2, 0xe2, 0xfe, 0x4b, 0x5b, 0x24, 0x76, 0xba, 0x7a, 0x34, 0xff, 0x4a, 0x42, 0x6e, 0xcf, - 0x69, 0xec, 0xb8, 0x3e, 0x09, 0x0f, 0x24, 0x8d, 0xc5, 0x90, 0x44, 0x41, 0x27, 0x6c, 0x90, 0x13, - 0xd5, 0x8a, 0x16, 0xf7, 0x48, 0xec, 0x64, 0x7c, 0xfd, 0xfc, 0x62, 0x5e, 0xad, 0xb0, 0xe3, 0xc7, - 0xee, 0x5e, 0x77, 0x33, 0x9f, 0xed, 0x57, 0x21, 0x6a, 0xec, 0x90, 0x3d, 0xa7, 0xab, 0xde, 0xcb, - 0x79, 0xf5, 0x3a, 0xb1, 0xeb, 0x2d, 0xba, 0x7e, 0x1c, 0xc5, 0x61, 0xba, 0x92, 0xfd, 0x4d, 0x0b, - 0x2e, 0x2f, 0xdd, 0xab, 0xaf, 0x7a, 0x4e, 0x14, 0xbb, 0x8d, 0x65, 0x2f, 0x68, 0xec, 0xd6, 0xe3, - 0x20, 0x24, 0x77, 0x03, 0xaf, 0xb3, 0x47, 0xea, 0x6c, 0x20, 0xd0, 0x0b, 0x30, 0xb6, 0xcf, 0xfe, - 0x57, 0x2b, 0x73, 0xd6, 0x65, 0xeb, 0x6a, 0x69, 0x79, 0xe6, 0x37, 0x0f, 0xcb, 0x9f, 0x38, 0x3a, - 0x2c, 0x8f, 0xdd, 0x15, 0xe5, 0x58, 0x61, 0xa0, 0x2b, 0x30, 0xb2, 0x1d, 0x6d, 0x1e, 0xb4, 0xc9, - 0x5c, 0x81, 0xe1, 0x4e, 0x09, 0xdc, 0x91, 0xb5, 0x3a, 0x2d, 0xc5, 0x02, 0x8a, 0x16, 0xa1, 0xd4, - 0x76, 0xc2, 0xd8, 0x8d, 0xdd, 0xc0, 0x9f, 0x2b, 0x5e, 0xb6, 0xae, 0x0e, 0x2f, 0xcf, 0x0a, 0xd4, - 0x52, 0x4d, 0x02, 0x70, 0x82, 0x43, 0xbb, 0x11, 0x12, 0xa7, 0x79, 0xdb, 0xf7, 0x0e, 0xe6, 0x86, - 0x2e, 0x5b, 0x57, 0xc7, 0x92, 0x6e, 0x60, 0x51, 0x8e, 0x15, 0x86, 0xfd, 0xe3, 0x05, 0x18, 0x5b, - 0xda, 0xde, 0x76, 0x7d, 0x37, 0x3e, 0x40, 0x77, 0x61, 0xc2, 0x0f, 0x9a, 0x44, 0xfe, 0x67, 0x5f, - 0x31, 0x7e, 0xed, 0xf2, 0x42, 0xf7, 0xca, 0x5c, 0xd8, 0xd0, 0xf0, 0x96, 0x67, 0x8e, 0x0e, 0xcb, - 0x13, 0x7a, 0x09, 0x36, 0xe8, 0x20, 0x0c, 0xe3, 0xed, 0xa0, 0xa9, 0xc8, 0x16, 0x18, 0xd9, 0x72, - 0x16, 0xd9, 0x5a, 0x82, 0xb6, 0x3c, 0x7d, 0x74, 0x58, 0x1e, 0xd7, 0x0a, 0xb0, 0x4e, 0x04, 0x6d, - 0xc1, 0x34, 0xfd, 0xeb, 0xc7, 0xae, 0xa2, 0x5b, 0x64, 0x74, 0x9f, 0xc9, 0xa3, 0xab, 0xa1, 0x2e, - 0x9f, 0x3b, 0x3a, 0x2c, 0x4f, 0xa7, 0x0a, 0x71, 0x9a, 0xa0, 0xfd, 0x01, 0x4c, 0x2d, 0xc5, 0xb1, - 0xd3, 0xd8, 0x21, 0x4d, 0x3e, 0x83, 0xe8, 0x15, 0x18, 0xf2, 0x9d, 0x3d, 0x22, 0xe6, 0xf7, 0xb2, - 0x18, 0xd8, 0xa1, 0x0d, 0x67, 0x8f, 0x1c, 0x1f, 0x96, 0x67, 0xee, 0xf8, 0xee, 0xfb, 0x1d, 0xb1, - 0x2a, 0x68, 0x19, 0x66, 0xd8, 0xe8, 0x1a, 0x40, 0x93, 0xec, 0xbb, 0x0d, 0x52, 0x73, 0xe2, 0x1d, - 0x31, 0xdf, 0x48, 0xd4, 0x85, 0x8a, 0x82, 0x60, 0x0d, 0xcb, 0x7e, 0x00, 0xa5, 0xa5, 0xfd, 0xc0, - 0x6d, 0xd6, 0x82, 0x66, 0x84, 0x76, 0x61, 0xba, 0x1d, 0x92, 0x6d, 0x12, 0xaa, 0xa2, 0x39, 0xeb, - 0x72, 0xf1, 0xea, 0xf8, 0xb5, 0xab, 0x99, 0x1f, 0x6b, 0xa2, 0xae, 0xfa, 0x71, 0x78, 0xb0, 0xfc, - 0xb8, 0x68, 0x6f, 0x3a, 0x05, 0xc5, 0x69, 0xca, 0xf6, 0x7f, 0x28, 0xc0, 0x85, 0xa5, 0x0f, 0x3a, - 0x21, 0xa9, 0xb8, 0xd1, 0x6e, 0x7a, 0x85, 0x37, 0xdd, 0x68, 0x77, 0x23, 0x19, 0x01, 0xb5, 0xb4, - 0x2a, 0xa2, 0x1c, 0x2b, 0x0c, 0xf4, 0x22, 0x8c, 0xd2, 0xdf, 0x77, 0x70, 0x55, 0x7c, 0xf2, 0x39, - 0x81, 0x3c, 0x5e, 0x71, 0x62, 0xa7, 0xc2, 0x41, 0x58, 0xe2, 0xa0, 0x75, 0x18, 0x6f, 0xb0, 0x0d, - 0xd9, 0x5a, 0x0f, 0x9a, 0x84, 0x4d, 0x66, 0x69, 0xf9, 0x79, 0x8a, 0xbe, 0x92, 0x14, 0x1f, 0x1f, - 0x96, 0xe7, 0x78, 0xdf, 0x04, 0x09, 0x0d, 0x86, 0xf5, 0xfa, 0xc8, 0x56, 0xfb, 0x6b, 0x88, 0x51, - 0x82, 0x8c, 0xbd, 0x75, 0x55, 0xdb, 0x2a, 0xc3, 0x6c, 0xab, 0x4c, 0x64, 0x6f, 0x13, 0xf4, 0x12, - 0x0c, 0xed, 0xba, 0x7e, 0x73, 0x6e, 0x84, 0xd1, 0x7a, 0x8a, 0xce, 0xf9, 0x4d, 0xd7, 0x6f, 0x1e, - 0x1f, 0x96, 0x67, 0x8d, 0xee, 0xd0, 0x42, 0xcc, 0x50, 0xed, 0x3f, 0xb5, 0xa0, 0xcc, 0x60, 0x6b, - 0xae, 0x47, 0x6a, 0x24, 0x8c, 0xdc, 0x28, 0x26, 0x7e, 0x6c, 0x0c, 0xe8, 0x35, 0x80, 0x88, 0x34, - 0x42, 0x12, 0x6b, 0x43, 0xaa, 0x16, 0x46, 0x5d, 0x41, 0xb0, 0x86, 0x45, 0x19, 0x42, 0xb4, 0xe3, - 0x84, 0x6c, 0x7d, 0x89, 0x81, 0x55, 0x0c, 0xa1, 0x2e, 0x01, 0x38, 0xc1, 0x31, 0x18, 0x42, 0xb1, - 0x1f, 0x43, 0x40, 0x5f, 0x80, 0xe9, 0xa4, 0xb1, 0xa8, 0xed, 0x34, 0xe4, 0x00, 0xb2, 0x2d, 0x53, - 0x37, 0x41, 0x38, 0x8d, 0x6b, 0xff, 0x13, 0x4b, 0x2c, 0x1e, 0xfa, 0xd5, 0x1f, 0xf3, 0x6f, 0xb5, - 0x7f, 0xc5, 0x82, 0xd1, 0x65, 0xd7, 0x6f, 0xba, 0x7e, 0x0b, 0x7d, 0x05, 0xc6, 0xe8, 0xd9, 0xd4, - 0x74, 0x62, 0x47, 0xf0, 0xbd, 0xcf, 0x68, 0x7b, 0x4b, 0x1d, 0x15, 0x0b, 0xed, 0xdd, 0x16, 0x2d, - 0x88, 0x16, 0x28, 0x36, 0xdd, 0x6d, 0xb7, 0xb7, 0xde, 0x23, 0x8d, 0x78, 0x9d, 0xc4, 0x4e, 0xf2, - 0x39, 0x49, 0x19, 0x56, 0x54, 0xd1, 0x4d, 0x18, 0x89, 0x9d, 0xb0, 0x45, 0x62, 0xc1, 0x00, 0x33, - 0x19, 0x15, 0xaf, 0x89, 0xe9, 0x8e, 0x24, 0x7e, 0x83, 0x24, 0xc7, 0xc2, 0x26, 0xab, 0x8a, 0x05, - 0x09, 0xfb, 0x6f, 0x8f, 0xc0, 0xc5, 0x95, 0x7a, 0x35, 0x67, 0x5d, 0x5d, 0x81, 0x91, 0x66, 0xe8, - 0xee, 0x93, 0x50, 0x8c, 0xb3, 0xa2, 0x52, 0x61, 0xa5, 0x58, 0x40, 0xd1, 0xeb, 0x30, 0xc1, 0x0f, - 0xa4, 0x1b, 0x8e, 0xdf, 0xf4, 0xe4, 0x10, 0x9f, 0x17, 0xd8, 0x13, 0x77, 0x35, 0x18, 0x36, 0x30, - 0x4f, 0xb8, 0xa8, 0xae, 0xa4, 0x36, 0x63, 0xde, 0x61, 0xf7, 0x83, 0x16, 0xcc, 0xf0, 0x66, 0x96, - 0xe2, 0x38, 0x74, 0xb7, 0x3a, 0x31, 0x89, 0xe6, 0x86, 0x19, 0xa7, 0x5b, 0xc9, 0x1a, 0xad, 0xdc, - 0x11, 0x58, 0xb8, 0x9b, 0xa2, 0xc2, 0x99, 0xe0, 0x9c, 0x68, 0x77, 0x26, 0x0d, 0xc6, 0x5d, 0xcd, - 0xa2, 0xef, 0xb5, 0x60, 0xbe, 0x11, 0xf8, 0x71, 0x18, 0x78, 0x1e, 0x09, 0x6b, 0x9d, 0x2d, 0xcf, - 0x8d, 0x76, 0xf8, 0x3a, 0xc5, 0x64, 0x9b, 0x71, 0x82, 0x9c, 0x39, 0x54, 0x48, 0x62, 0x0e, 0x2f, - 0x1d, 0x1d, 0x96, 0xe7, 0x57, 0x72, 0x49, 0xe1, 0x1e, 0xcd, 0xa0, 0x5d, 0x40, 0xf4, 0x28, 0xad, - 0xc7, 0x4e, 0x8b, 0x24, 0x8d, 0x8f, 0x0e, 0xde, 0xf8, 0x63, 0x47, 0x87, 0x65, 0xb4, 0xd1, 0x45, - 0x02, 0x67, 0x90, 0x45, 0xef, 0xc3, 0x79, 0x5a, 0xda, 0xf5, 0xad, 0x63, 0x83, 0x37, 0x37, 0x77, - 0x74, 0x58, 0x3e, 0xbf, 0x91, 0x41, 0x04, 0x67, 0x92, 0x9e, 0x5f, 0x81, 0x0b, 0x99, 0x53, 0x85, - 0x66, 0xa0, 0xb8, 0x4b, 0xb8, 0x08, 0x52, 0xc2, 0xf4, 0x27, 0x3a, 0x0f, 0xc3, 0xfb, 0x8e, 0xd7, - 0x11, 0xab, 0x14, 0xf3, 0x3f, 0x9f, 0x2b, 0xbc, 0x6e, 0xd9, 0x0d, 0x98, 0x58, 0x71, 0xda, 0xce, - 0x96, 0xeb, 0xb9, 0xb1, 0x4b, 0x22, 0xf4, 0x69, 0x28, 0x3a, 0xcd, 0x26, 0x3b, 0x22, 0x4b, 0xcb, - 0x17, 0x8e, 0x0e, 0xcb, 0xc5, 0xa5, 0x26, 0xe5, 0xd5, 0xa0, 0xb0, 0x0e, 0x30, 0xc5, 0x40, 0xcf, - 0xc1, 0x50, 0x33, 0x0c, 0xda, 0x73, 0x05, 0x86, 0x49, 0x87, 0x6a, 0xa8, 0x12, 0x06, 0xed, 0x14, - 0x2a, 0xc3, 0xb1, 0x7f, 0xbd, 0x00, 0x4f, 0xae, 0x90, 0xf6, 0xce, 0x5a, 0x3d, 0x67, 0xd3, 0x5d, - 0x85, 0xb1, 0xbd, 0xc0, 0x77, 0xe3, 0x20, 0x8c, 0x44, 0xd3, 0xec, 0x34, 0x59, 0x17, 0x65, 0x58, - 0x41, 0xd1, 0x65, 0x18, 0x6a, 0x27, 0x92, 0xc0, 0x84, 0x94, 0x22, 0x98, 0x0c, 0xc0, 0x20, 0x14, - 0xa3, 0x13, 0x91, 0x50, 0x9c, 0x82, 0x0a, 0xe3, 0x4e, 0x44, 0x42, 0xcc, 0x20, 0x09, 0x3b, 0xa5, - 0x8c, 0x56, 0x6c, 0xab, 0x14, 0x3b, 0xa5, 0x10, 0xac, 0x61, 0xa1, 0x1a, 0x94, 0x22, 0x35, 0xa9, - 0xc3, 0x83, 0x4f, 0xea, 0x24, 0xe3, 0xb7, 0x6a, 0x26, 0x13, 0x22, 0x06, 0x1b, 0x18, 0xe9, 0xcb, - 0x6f, 0x7f, 0xb5, 0x00, 0x88, 0x0f, 0xe1, 0x5f, 0xb2, 0x81, 0xbb, 0xd3, 0x3d, 0x70, 0x99, 0x92, - 0xd7, 0xad, 0xa0, 0xe1, 0x78, 0x69, 0x16, 0x7e, 0x5a, 0xa3, 0xf7, 0x63, 0x16, 0xa0, 0x15, 0xd7, - 0x6f, 0x92, 0xf0, 0x0c, 0xae, 0x1d, 0x27, 0x3b, 0x48, 0x6f, 0xc1, 0xd4, 0x8a, 0xe7, 0x12, 0x3f, - 0xae, 0xd6, 0x56, 0x02, 0x7f, 0xdb, 0x6d, 0xa1, 0xcf, 0xc1, 0x14, 0xbd, 0x85, 0x05, 0x9d, 0xb8, - 0x4e, 0x1a, 0x81, 0xcf, 0x04, 0x56, 0x7a, 0x77, 0x41, 0x47, 0x87, 0xe5, 0xa9, 0x4d, 0x03, 0x82, - 0x53, 0x98, 0xf6, 0xef, 0xd3, 0x0f, 0x0d, 0xf6, 0xda, 0x81, 0x4f, 0xfc, 0x78, 0x25, 0xf0, 0x9b, - 0xfc, 0x62, 0xf3, 0x39, 0x18, 0x8a, 0x69, 0xc7, 0xf9, 0x47, 0x5e, 0x91, 0x53, 0x4b, 0xbb, 0x7b, - 0x7c, 0x58, 0x7e, 0xac, 0xbb, 0x06, 0xfb, 0x20, 0x56, 0x07, 0x7d, 0x1b, 0x8c, 0x44, 0xb1, 0x13, - 0x77, 0x22, 0xf1, 0xd9, 0x4f, 0xcb, 0xcf, 0xae, 0xb3, 0xd2, 0xe3, 0xc3, 0xf2, 0xb4, 0xaa, 0xc6, - 0x8b, 0xb0, 0xa8, 0x80, 0x9e, 0x85, 0xd1, 0x3d, 0x12, 0x45, 0x4e, 0x4b, 0xca, 0xa4, 0xd3, 0xa2, - 0xee, 0xe8, 0x3a, 0x2f, 0xc6, 0x12, 0x8e, 0x9e, 0x81, 0x61, 0x12, 0x86, 0x41, 0x28, 0x56, 0xd5, - 0xa4, 0x40, 0x1c, 0x5e, 0xa5, 0x85, 0x98, 0xc3, 0xec, 0xff, 0x68, 0xc1, 0xb4, 0xea, 0x2b, 0x6f, - 0xeb, 0x0c, 0x84, 0x8f, 0x77, 0x00, 0x1a, 0xf2, 0x03, 0x23, 0xc6, 0xef, 0xc6, 0xaf, 0x5d, 0xc9, - 0x3c, 0x52, 0xbb, 0x86, 0x31, 0xa1, 0xac, 0x8a, 0x22, 0xac, 0x51, 0xb3, 0xff, 0xb5, 0x05, 0xe7, - 0x52, 0x5f, 0x74, 0xcb, 0x8d, 0x62, 0xf4, 0x6e, 0xd7, 0x57, 0x2d, 0x0c, 0xf6, 0x55, 0xb4, 0x36, - 0xfb, 0x26, 0xb5, 0xe6, 0x64, 0x89, 0xf6, 0x45, 0x37, 0x60, 0xd8, 0x8d, 0xc9, 0x9e, 0xfc, 0x98, - 0x67, 0x7a, 0x7e, 0x0c, 0xef, 0x55, 0x32, 0x23, 0x55, 0x5a, 0x13, 0x73, 0x02, 0xf6, 0x8f, 0x14, - 0xa1, 0xc4, 0x97, 0xed, 0xba, 0xd3, 0x3e, 0x83, 0xb9, 0xa8, 0xc2, 0x10, 0xa3, 0xce, 0x3b, 0xfe, - 0xe9, 0xec, 0x8e, 0x8b, 0xee, 0x2c, 0xd0, 0x9b, 0x05, 0x17, 0x5e, 0x14, 0x33, 0xa3, 0x45, 0x98, - 0x91, 0x40, 0x0e, 0xc0, 0x96, 0xeb, 0x3b, 0xe1, 0x01, 0x2d, 0x9b, 0x2b, 0x32, 0x82, 0x2f, 0xf6, - 0x26, 0xb8, 0xac, 0xf0, 0x39, 0x59, 0xd5, 0xd7, 0x04, 0x80, 0x35, 0xa2, 0xf3, 0xaf, 0x41, 0x49, - 0x21, 0x9f, 0xe4, 0x54, 0x9e, 0xff, 0x02, 0x4c, 0xa7, 0xda, 0xea, 0x57, 0x7d, 0x42, 0x3f, 0xd4, - 0xbf, 0xc1, 0xb8, 0x80, 0xe8, 0xf5, 0xaa, 0xbf, 0x2f, 0xd8, 0xdd, 0x07, 0x70, 0xde, 0xcb, 0xe0, - 0xb2, 0x62, 0xaa, 0x06, 0xe7, 0xca, 0x4f, 0x8a, 0xcf, 0x3e, 0x9f, 0x05, 0xc5, 0x99, 0x6d, 0xd0, - 0x83, 0x2a, 0x68, 0xd3, 0x35, 0xef, 0x78, 0xac, 0xbf, 0xe2, 0xbe, 0x78, 0x5b, 0x94, 0x61, 0x05, - 0xa5, 0x2c, 0xec, 0xbc, 0xea, 0xfc, 0x4d, 0x72, 0x50, 0x27, 0x1e, 0x69, 0xc4, 0x41, 0xf8, 0x91, - 0x76, 0xff, 0x29, 0x3e, 0xfa, 0x9c, 0x03, 0x8e, 0x0b, 0x02, 0xc5, 0x9b, 0xe4, 0x80, 0x4f, 0x85, - 0xfe, 0x75, 0xc5, 0x9e, 0x5f, 0xf7, 0xf3, 0x16, 0x4c, 0xaa, 0xaf, 0x3b, 0x83, 0xad, 0xbe, 0x6c, - 0x6e, 0xf5, 0xa7, 0x7a, 0x2e, 0xf0, 0x9c, 0x4d, 0xfe, 0x17, 0x8c, 0x49, 0x09, 0x9c, 0x5a, 0x18, - 0xd0, 0xa1, 0xa1, 0xa7, 0xca, 0x47, 0x39, 0x21, 0x83, 0x7c, 0xd7, 0x4d, 0x72, 0xb0, 0x19, 0x50, - 0x01, 0x27, 0xfb, 0xbb, 0x8c, 0x59, 0x1b, 0xea, 0x39, 0x6b, 0xbf, 0x58, 0x80, 0x0b, 0x6a, 0x04, - 0x0c, 0x11, 0xe2, 0x2f, 0xfb, 0x18, 0xbc, 0x04, 0xe3, 0x4d, 0xb2, 0xed, 0x74, 0xbc, 0x58, 0xa9, - 0x8e, 0x86, 0xb9, 0xfa, 0xb0, 0x92, 0x14, 0x63, 0x1d, 0xe7, 0x04, 0xc3, 0xf6, 0xd3, 0xe3, 0xec, - 0x74, 0x88, 0x1d, 0xba, 0x82, 0xa9, 0x7c, 0xa9, 0x29, 0x00, 0x27, 0x74, 0x05, 0xa0, 0x50, 0xf6, - 0x3d, 0x03, 0xc3, 0xee, 0x1e, 0x95, 0x16, 0x0a, 0xa6, 0x10, 0x50, 0xa5, 0x85, 0x98, 0xc3, 0xd0, - 0xa7, 0x60, 0xb4, 0x11, 0xec, 0xed, 0x39, 0x7e, 0x93, 0x31, 0xed, 0xd2, 0xf2, 0x38, 0x15, 0x28, - 0x56, 0x78, 0x11, 0x96, 0x30, 0xf4, 0x24, 0x0c, 0x39, 0x61, 0x2b, 0x9a, 0x1b, 0x62, 0x38, 0x63, - 0xb4, 0xa5, 0xa5, 0xb0, 0x15, 0x61, 0x56, 0x4a, 0x25, 0xd9, 0xfb, 0x41, 0xb8, 0xeb, 0xfa, 0xad, - 0x8a, 0x1b, 0x32, 0xb1, 0x54, 0x93, 0x64, 0xef, 0x29, 0x08, 0xd6, 0xb0, 0xd0, 0x1a, 0x0c, 0xb7, - 0x83, 0x30, 0x8e, 0xe6, 0x46, 0xd8, 0x70, 0x3f, 0x9d, 0xb3, 0x95, 0xf8, 0xd7, 0xd6, 0x82, 0x30, - 0x4e, 0x3e, 0x80, 0xfe, 0x8b, 0x30, 0xaf, 0x8e, 0xbe, 0x0d, 0x8a, 0xc4, 0xdf, 0x9f, 0x1b, 0x65, - 0x54, 0xe6, 0xb3, 0xa8, 0xac, 0xfa, 0xfb, 0x77, 0x9d, 0x30, 0xe1, 0x33, 0xab, 0xfe, 0x3e, 0xa6, - 0x75, 0xd0, 0x97, 0xa0, 0x24, 0x1f, 0x0f, 0x22, 0x71, 0xb5, 0xcc, 0x5c, 0x62, 0x58, 0x20, 0x61, - 0xf2, 0x7e, 0xc7, 0x0d, 0xc9, 0x1e, 0xf1, 0xe3, 0x28, 0x51, 0xff, 0x48, 0x68, 0x84, 0x13, 0x6a, - 0xe8, 0x4b, 0x52, 0x9f, 0xb1, 0x1e, 0x74, 0xfc, 0x38, 0x9a, 0x2b, 0xb1, 0xee, 0x65, 0x6a, 0x9a, - 0xef, 0x26, 0x78, 0x69, 0x85, 0x07, 0xaf, 0x8c, 0x0d, 0x52, 0x08, 0xc3, 0xa4, 0xe7, 0xee, 0x13, - 0x9f, 0x44, 0x51, 0x2d, 0x0c, 0xb6, 0xc8, 0x1c, 0xb0, 0x9e, 0x5f, 0xcc, 0x56, 0xc0, 0x06, 0x5b, - 0x64, 0x79, 0xf6, 0xe8, 0xb0, 0x3c, 0x79, 0x4b, 0xaf, 0x83, 0x4d, 0x12, 0xe8, 0x0e, 0x4c, 0x51, - 0x11, 0xda, 0x4d, 0x88, 0x8e, 0xf7, 0x23, 0xca, 0xe4, 0x67, 0x6c, 0x54, 0xc2, 0x29, 0x22, 0xe8, - 0x2d, 0x28, 0x79, 0xee, 0x36, 0x69, 0x1c, 0x34, 0x3c, 0x32, 0x37, 0xc1, 0x28, 0x66, 0x6e, 0xab, - 0x5b, 0x12, 0x89, 0x5f, 0x51, 0xd4, 0x5f, 0x9c, 0x54, 0x47, 0x77, 0xe1, 0xb1, 0x98, 0x84, 0x7b, - 0xae, 0xef, 0xd0, 0xed, 0x20, 0x24, 0x5e, 0xa6, 0xc6, 0x9e, 0x64, 0xeb, 0xed, 0x92, 0x18, 0xba, - 0xc7, 0x36, 0x33, 0xb1, 0x70, 0x4e, 0x6d, 0x74, 0x1b, 0xa6, 0xd9, 0x4e, 0xa8, 0x75, 0x3c, 0xaf, - 0x16, 0x78, 0x6e, 0xe3, 0x60, 0x6e, 0x8a, 0x11, 0xfc, 0x94, 0xd4, 0x53, 0x57, 0x4d, 0x30, 0xbd, - 0x93, 0x27, 0xff, 0x70, 0xba, 0x36, 0xda, 0x62, 0x7a, 0xcb, 0x4e, 0xe8, 0xc6, 0x07, 0x74, 0xfd, - 0x92, 0x07, 0xf1, 0xdc, 0x74, 0xcf, 0x1b, 0xae, 0x8e, 0xaa, 0x94, 0x9b, 0x7a, 0x21, 0x4e, 0x13, - 0xa4, 0x5b, 0x3b, 0x8a, 0x9b, 0xae, 0x3f, 0x37, 0xc3, 0x38, 0x86, 0xda, 0x19, 0x75, 0x5a, 0x88, - 0x39, 0x8c, 0xe9, 0x2c, 0xe9, 0x8f, 0xdb, 0x94, 0x83, 0xce, 0x32, 0xc4, 0x44, 0x67, 0x29, 0x01, - 0x38, 0xc1, 0xa1, 0xc7, 0x72, 0x1c, 0x1f, 0xcc, 0x21, 0x86, 0xaa, 0xb6, 0xcb, 0xe6, 0xe6, 0x97, - 0x30, 0x2d, 0x47, 0xb7, 0x60, 0x94, 0xf8, 0xfb, 0x6b, 0x61, 0xb0, 0x37, 0x77, 0x2e, 0x7f, 0xcf, - 0xae, 0x72, 0x14, 0xce, 0xd0, 0x93, 0x2b, 0x8a, 0x28, 0xc6, 0x92, 0x04, 0x7a, 0x00, 0x73, 0x19, - 0x33, 0xc2, 0x27, 0xe0, 0x3c, 0x9b, 0x80, 0xcf, 0x8b, 0xba, 0x73, 0x9b, 0x39, 0x78, 0xc7, 0x3d, - 0x60, 0x38, 0x97, 0x3a, 0xfa, 0x2e, 0x98, 0xe4, 0x1b, 0x8a, 0x3f, 0x78, 0x44, 0x73, 0x17, 0xd8, - 0xd7, 0x5c, 0xce, 0xdf, 0x9c, 0x1c, 0x71, 0xf9, 0x82, 0xe8, 0xd0, 0xa4, 0x5e, 0x1a, 0x61, 0x93, - 0x9a, 0xbd, 0x05, 0x53, 0x8a, 0x6f, 0xb1, 0xa5, 0x83, 0xca, 0x30, 0x4c, 0x19, 0xb2, 0xd4, 0x29, - 0x94, 0xe8, 0x4c, 0x31, 0x45, 0x35, 0xe6, 0xe5, 0x6c, 0xa6, 0xdc, 0x0f, 0xc8, 0xf2, 0x41, 0x4c, - 0xf8, 0xbd, 0xb0, 0xa8, 0xcd, 0x94, 0x04, 0xe0, 0x04, 0xc7, 0xfe, 0x7f, 0x5c, 0xee, 0x49, 0x98, - 0xe3, 0x00, 0xc7, 0xc1, 0x0b, 0x30, 0xb6, 0x13, 0x44, 0x31, 0xc5, 0x66, 0x6d, 0x0c, 0x27, 0x92, - 0xce, 0x0d, 0x51, 0x8e, 0x15, 0x06, 0x7a, 0x03, 0x26, 0x1b, 0x7a, 0x03, 0xe2, 0x2c, 0x53, 0x43, - 0x60, 0xb4, 0x8e, 0x4d, 0x5c, 0xf4, 0x3a, 0x8c, 0xb1, 0xe7, 0xca, 0x46, 0xe0, 0x89, 0x1b, 0xa8, - 0x3c, 0x90, 0xc7, 0x6a, 0xa2, 0xfc, 0x58, 0xfb, 0x8d, 0x15, 0x36, 0xba, 0x02, 0x23, 0xb4, 0x0b, - 0xd5, 0x9a, 0x38, 0x45, 0x94, 0x56, 0xe0, 0x06, 0x2b, 0xc5, 0x02, 0x6a, 0xff, 0x9d, 0x82, 0x36, - 0xca, 0xf4, 0x4e, 0x45, 0x50, 0x0d, 0x46, 0xef, 0x3b, 0x6e, 0xec, 0xfa, 0x2d, 0x21, 0x2e, 0x3c, - 0xdb, 0xf3, 0x48, 0x61, 0x95, 0xee, 0xf1, 0x0a, 0xfc, 0xd0, 0x13, 0x7f, 0xb0, 0x24, 0x43, 0x29, - 0x86, 0x1d, 0xdf, 0xa7, 0x14, 0x0b, 0x83, 0x52, 0xc4, 0xbc, 0x02, 0xa7, 0x28, 0xfe, 0x60, 0x49, - 0x06, 0xbd, 0x0b, 0x20, 0x97, 0x25, 0x69, 0x8a, 0x67, 0xc2, 0x17, 0xfa, 0x13, 0xdd, 0x54, 0x75, - 0x96, 0xa7, 0xe8, 0x91, 0x9a, 0xfc, 0xc7, 0x1a, 0x3d, 0x3b, 0x66, 0x62, 0x55, 0x77, 0x67, 0xd0, - 0x77, 0x52, 0x4e, 0xe0, 0x84, 0x31, 0x69, 0x2e, 0xc5, 0x62, 0x70, 0x9e, 0x1b, 0x4c, 0x2a, 0xde, - 0x74, 0xf7, 0x88, 0xce, 0x35, 0x04, 0x11, 0x9c, 0xd0, 0xb3, 0x7f, 0xb9, 0x08, 0x73, 0x79, 0xdd, - 0xa5, 0x8b, 0x8e, 0x3c, 0x70, 0xe3, 0x15, 0x2a, 0x0d, 0x59, 0xe6, 0xa2, 0x5b, 0x15, 0xe5, 0x58, - 0x61, 0xd0, 0xd9, 0x8f, 0xdc, 0x96, 0xbc, 0xd4, 0x0c, 0x27, 0xb3, 0x5f, 0x67, 0xa5, 0x58, 0x40, - 0x29, 0x5e, 0x48, 0x9c, 0x48, 0xbc, 0x43, 0x6b, 0xab, 0x04, 0xb3, 0x52, 0x2c, 0xa0, 0xba, 0xc6, - 0x64, 0xa8, 0x8f, 0xc6, 0xc4, 0x18, 0xa2, 0xe1, 0xd3, 0x1d, 0x22, 0xf4, 0x65, 0x80, 0x6d, 0xd7, - 0x77, 0xa3, 0x1d, 0x46, 0x7d, 0xe4, 0xc4, 0xd4, 0x95, 0x2c, 0xb5, 0xa6, 0xa8, 0x60, 0x8d, 0x22, - 0x7a, 0x15, 0xc6, 0xd5, 0x06, 0xac, 0x56, 0x98, 0x52, 0x5e, 0x7b, 0xe4, 0x4c, 0xb8, 0x51, 0x05, - 0xeb, 0x78, 0xf6, 0x7b, 0xe9, 0xf5, 0x22, 0x76, 0x80, 0x36, 0xbe, 0xd6, 0xa0, 0xe3, 0x5b, 0xe8, - 0x3d, 0xbe, 0xf6, 0x6f, 0x14, 0x61, 0xda, 0x68, 0xac, 0x13, 0x0d, 0xc0, 0xb3, 0xae, 0xd3, 0x73, - 0xce, 0x89, 0x89, 0xd8, 0x7f, 0x76, 0xff, 0xad, 0xa2, 0x9f, 0x85, 0x74, 0x07, 0xf0, 0xfa, 0xe8, - 0xcb, 0x50, 0xf2, 0x9c, 0x88, 0x69, 0x5f, 0x88, 0xd8, 0x77, 0x83, 0x10, 0x4b, 0xee, 0x11, 0x4e, - 0x14, 0x6b, 0x47, 0x0d, 0xa7, 0x9d, 0x90, 0xa4, 0x07, 0x32, 0x95, 0x7d, 0xa4, 0xa1, 0x83, 0xea, - 0x04, 0x15, 0x90, 0x0e, 0x30, 0x87, 0xa1, 0xd7, 0x61, 0x22, 0x24, 0x6c, 0x55, 0xac, 0x50, 0x51, - 0x8e, 0x2d, 0xb3, 0xe1, 0x44, 0xe6, 0xc3, 0x1a, 0x0c, 0x1b, 0x98, 0x89, 0x28, 0x3f, 0xd2, 0x43, - 0x94, 0x7f, 0x16, 0x46, 0xd9, 0x0f, 0xb5, 0x02, 0xd4, 0x6c, 0x54, 0x79, 0x31, 0x96, 0xf0, 0xf4, - 0x82, 0x19, 0x1b, 0x70, 0xc1, 0x3c, 0x07, 0x53, 0x15, 0x87, 0xec, 0x05, 0xfe, 0xaa, 0xdf, 0x6c, - 0x07, 0xae, 0x1f, 0xa3, 0x39, 0x18, 0x62, 0xa7, 0x03, 0xdf, 0xdb, 0x43, 0x94, 0x02, 0x1e, 0xa2, - 0x82, 0xb9, 0xfd, 0xbb, 0x05, 0x98, 0xac, 0x10, 0x8f, 0xc4, 0x84, 0x5f, 0x65, 0x22, 0xb4, 0x06, - 0xa8, 0x15, 0x3a, 0x0d, 0x52, 0x23, 0xa1, 0x1b, 0x34, 0x75, 0x6d, 0x6c, 0x91, 0x3f, 0x0e, 0x5d, - 0xef, 0x82, 0xe2, 0x8c, 0x1a, 0xe8, 0x1d, 0x98, 0x6c, 0x87, 0xc4, 0x50, 0x22, 0x5a, 0x79, 0xd2, - 0x48, 0x4d, 0x47, 0xe4, 0x82, 0xb0, 0x51, 0x84, 0x4d, 0x52, 0xe8, 0x3b, 0x60, 0x26, 0x08, 0xdb, - 0x3b, 0x8e, 0x5f, 0x21, 0x6d, 0xe2, 0x37, 0xa9, 0xa4, 0x2f, 0x54, 0x10, 0xe7, 0x8f, 0x0e, 0xcb, - 0x33, 0xb7, 0x53, 0x30, 0xdc, 0x85, 0x8d, 0xde, 0x81, 0xd9, 0x76, 0x18, 0xb4, 0x9d, 0x16, 0x5b, - 0x28, 0x42, 0xa0, 0xe1, 0xdc, 0xe7, 0x85, 0xa3, 0xc3, 0xf2, 0x6c, 0x2d, 0x0d, 0x3c, 0x3e, 0x2c, - 0x9f, 0x63, 0x03, 0x45, 0x4b, 0x12, 0x20, 0xee, 0x26, 0x63, 0xb7, 0xe0, 0x42, 0x25, 0xb8, 0xef, - 0xdf, 0x77, 0xc2, 0xe6, 0x52, 0xad, 0xaa, 0xe9, 0x0e, 0x36, 0xe4, 0xdd, 0x95, 0x1b, 0x63, 0x64, - 0x9e, 0x53, 0x5a, 0x4d, 0x2e, 0xbf, 0xac, 0xb9, 0x1e, 0xc9, 0xd1, 0x51, 0xfc, 0xbd, 0x82, 0xd1, - 0x52, 0x82, 0xaf, 0x1e, 0x3e, 0xac, 0xdc, 0x87, 0x8f, 0xb7, 0x61, 0x6c, 0xdb, 0x25, 0x5e, 0x13, - 0x93, 0x6d, 0x31, 0x33, 0x9f, 0xce, 0x7f, 0x5f, 0x5e, 0xa3, 0x98, 0x52, 0x27, 0xc5, 0x6f, 0xbe, - 0x6b, 0xa2, 0x32, 0x56, 0x64, 0xd0, 0x2e, 0xcc, 0xc8, 0xab, 0x95, 0x84, 0x8a, 0x4d, 0xfc, 0x6c, - 0xaf, 0xfb, 0x9a, 0x49, 0x9c, 0x4d, 0x20, 0x4e, 0x91, 0xc1, 0x5d, 0x84, 0xe9, 0x55, 0x77, 0x8f, - 0x1e, 0x57, 0x43, 0x6c, 0x49, 0xb3, 0xab, 0x2e, 0xbb, 0xb5, 0xb3, 0x52, 0xfb, 0x27, 0x2d, 0x78, - 0xbc, 0x6b, 0x64, 0x84, 0xf6, 0xe2, 0x94, 0x67, 0x21, 0xad, 0x4d, 0x28, 0xf4, 0xd7, 0x26, 0xd8, - 0xff, 0xd4, 0x82, 0xf3, 0xab, 0x7b, 0xed, 0xf8, 0xa0, 0xe2, 0x9a, 0x8f, 0x33, 0xaf, 0xc1, 0xc8, - 0x1e, 0x69, 0xba, 0x9d, 0x3d, 0x31, 0x73, 0x65, 0xc9, 0xd2, 0xd7, 0x59, 0xe9, 0xf1, 0x61, 0x79, - 0xb2, 0x1e, 0x07, 0xa1, 0xd3, 0x22, 0xbc, 0x00, 0x0b, 0x74, 0x76, 0x30, 0xba, 0x1f, 0x90, 0x5b, - 0xee, 0x9e, 0x2b, 0xed, 0x05, 0x7a, 0x6a, 0xd4, 0x16, 0xe4, 0x80, 0x2e, 0xbc, 0xdd, 0x71, 0xfc, - 0xd8, 0x8d, 0x0f, 0xc4, 0xbb, 0x93, 0x24, 0x82, 0x13, 0x7a, 0xf6, 0x37, 0x2d, 0x98, 0x96, 0xbc, - 0x64, 0xa9, 0xd9, 0x0c, 0x49, 0x14, 0xa1, 0x79, 0x28, 0xb8, 0x6d, 0xd1, 0x4b, 0x10, 0xbd, 0x2c, - 0x54, 0x6b, 0xb8, 0xe0, 0xb6, 0x51, 0x0d, 0x4a, 0xdc, 0xec, 0x20, 0x59, 0x5c, 0x03, 0x19, 0x2f, - 0xb0, 0x1e, 0x6c, 0xca, 0x9a, 0x38, 0x21, 0x22, 0xa5, 0x62, 0x76, 0x0e, 0x15, 0xcd, 0x47, 0xab, - 0x1b, 0xa2, 0x1c, 0x2b, 0x0c, 0x74, 0x15, 0xc6, 0xfc, 0xa0, 0xc9, 0xad, 0x40, 0xf8, 0x9e, 0x66, - 0x4b, 0x76, 0x43, 0x94, 0x61, 0x05, 0xb5, 0x7f, 0xd8, 0x82, 0x09, 0xf9, 0x65, 0x03, 0x0a, 0xe8, - 0x74, 0x6b, 0x25, 0xc2, 0x79, 0xb2, 0xb5, 0xa8, 0x80, 0xcd, 0x20, 0x86, 0x5c, 0x5d, 0x3c, 0x89, - 0x5c, 0x6d, 0xff, 0x44, 0x01, 0xa6, 0x64, 0x77, 0xea, 0x9d, 0xad, 0x88, 0xc4, 0x68, 0x13, 0x4a, - 0x0e, 0x1f, 0x72, 0x22, 0x57, 0xec, 0x33, 0xd9, 0x17, 0x3a, 0x63, 0x7e, 0x12, 0x51, 0x67, 0x49, - 0xd6, 0xc6, 0x09, 0x21, 0xe4, 0xc1, 0xac, 0x1f, 0xc4, 0xec, 0xd8, 0x53, 0xf0, 0x5e, 0x0f, 0x23, - 0x69, 0xea, 0x17, 0x05, 0xf5, 0xd9, 0x8d, 0x34, 0x15, 0xdc, 0x4d, 0x18, 0xad, 0x4a, 0x25, 0x52, - 0x31, 0xff, 0x0a, 0xa7, 0xcf, 0x42, 0xb6, 0x0e, 0xc9, 0xfe, 0x35, 0x0b, 0x4a, 0x12, 0xed, 0x2c, - 0xde, 0xc0, 0xd6, 0x61, 0x34, 0x62, 0x93, 0x20, 0x87, 0xc6, 0xee, 0xd5, 0x71, 0x3e, 0x5f, 0xc9, - 0x69, 0xce, 0xff, 0x47, 0x58, 0xd2, 0x60, 0x5a, 0x70, 0xd5, 0xfd, 0x8f, 0x89, 0x16, 0x5c, 0xf5, - 0x27, 0xe7, 0x84, 0xf9, 0x6f, 0xac, 0xcf, 0x9a, 0xaa, 0x80, 0x0a, 0x9d, 0xed, 0x90, 0x6c, 0xbb, - 0x0f, 0xd2, 0x42, 0x67, 0x8d, 0x95, 0x62, 0x01, 0x45, 0xef, 0xc2, 0x44, 0x43, 0x2a, 0x8f, 0x13, - 0x36, 0x70, 0xa5, 0xa7, 0x2a, 0x5e, 0xbd, 0xda, 0x70, 0x0b, 0xd1, 0x15, 0xad, 0x3e, 0x36, 0xa8, - 0x99, 0x96, 0x09, 0xc5, 0x7e, 0x96, 0x09, 0x09, 0xdd, 0xdc, 0xb7, 0x75, 0xfb, 0xa7, 0x2c, 0x18, - 0xe1, 0x2a, 0xc8, 0xc1, 0x74, 0xb6, 0xda, 0x23, 0x56, 0x32, 0x76, 0x77, 0x69, 0xa1, 0x78, 0x94, - 0x42, 0xeb, 0x50, 0x62, 0x3f, 0x98, 0x2a, 0xa6, 0x98, 0x6f, 0x1a, 0xcb, 0x5b, 0xd5, 0x3b, 0x78, - 0x57, 0x56, 0xc3, 0x09, 0x05, 0xfb, 0x47, 0x8b, 0x94, 0x55, 0x25, 0xa8, 0xc6, 0x09, 0x6e, 0x3d, - 0xba, 0x13, 0xbc, 0xf0, 0xa8, 0x4e, 0xf0, 0x16, 0x4c, 0x37, 0xb4, 0x27, 0xaf, 0x64, 0x26, 0xaf, - 0xf6, 0x5c, 0x24, 0xda, 0xeb, 0x18, 0x57, 0xc3, 0xad, 0x98, 0x44, 0x70, 0x9a, 0x2a, 0xfa, 0x4e, - 0x98, 0xe0, 0xf3, 0x2c, 0x5a, 0x19, 0x62, 0xad, 0x7c, 0x2a, 0x7f, 0xbd, 0xe8, 0x4d, 0xb0, 0x95, - 0x58, 0xd7, 0xaa, 0x63, 0x83, 0x98, 0xfd, 0xcb, 0x63, 0x30, 0xbc, 0xba, 0x4f, 0xfc, 0xf8, 0x0c, - 0x18, 0x52, 0x03, 0xa6, 0x5c, 0x7f, 0x3f, 0xf0, 0xf6, 0x49, 0x93, 0xc3, 0x4f, 0x72, 0xb8, 0x3e, - 0x26, 0x48, 0x4f, 0x55, 0x0d, 0x12, 0x38, 0x45, 0xf2, 0x51, 0xdc, 0xda, 0xaf, 0xc3, 0x08, 0x9f, - 0x7b, 0x71, 0x65, 0xcf, 0x54, 0xb0, 0xb3, 0x41, 0x14, 0xbb, 0x20, 0xd1, 0x28, 0x70, 0x8d, 0xbe, - 0xa8, 0x8e, 0xde, 0x83, 0xa9, 0x6d, 0x37, 0x8c, 0x62, 0x7a, 0xdd, 0x8e, 0x62, 0x67, 0xaf, 0xfd, - 0x10, 0xb7, 0x74, 0x35, 0x0e, 0x6b, 0x06, 0x25, 0x9c, 0xa2, 0x8c, 0x5a, 0x30, 0x49, 0x2f, 0x8e, - 0x49, 0x53, 0xa3, 0x27, 0x6e, 0x4a, 0xa9, 0xe1, 0x6e, 0xe9, 0x84, 0xb0, 0x49, 0x97, 0x32, 0x93, - 0x06, 0xbb, 0x68, 0x8e, 0x31, 0x89, 0x42, 0x31, 0x13, 0x7e, 0xc3, 0xe4, 0x30, 0xca, 0x93, 0x98, - 0x31, 0x4b, 0xc9, 0xe4, 0x49, 0x9a, 0xc9, 0xca, 0x57, 0xa0, 0x44, 0xe8, 0x10, 0x52, 0xc2, 0xe2, - 0xb1, 0x61, 0x71, 0xb0, 0xbe, 0xae, 0xbb, 0x8d, 0x30, 0x30, 0xf5, 0x23, 0xab, 0x92, 0x12, 0x4e, - 0x88, 0xa2, 0x15, 0x18, 0x89, 0x48, 0xe8, 0x92, 0x48, 0x3c, 0x3b, 0xf4, 0x98, 0x46, 0x86, 0xc6, - 0x6d, 0xa8, 0xf9, 0x6f, 0x2c, 0xaa, 0xd2, 0xe5, 0xe5, 0xb0, 0xdb, 0x10, 0x7b, 0x69, 0xd0, 0x96, - 0xd7, 0x12, 0x2b, 0xc5, 0x02, 0x8a, 0xde, 0x82, 0xd1, 0x90, 0x78, 0x4c, 0x01, 0x37, 0x39, 0xf8, - 0x22, 0xe7, 0xfa, 0x3c, 0x5e, 0x0f, 0x4b, 0x02, 0xe8, 0x26, 0xa0, 0x90, 0x50, 0x19, 0xc2, 0xf5, - 0x5b, 0xca, 0xc4, 0x43, 0xbc, 0x1f, 0x3c, 0x21, 0xda, 0x3f, 0x87, 0x13, 0x0c, 0x69, 0x5d, 0x89, - 0x33, 0xaa, 0xa1, 0xeb, 0x30, 0xab, 0x4a, 0xab, 0x7e, 0x14, 0x3b, 0x7e, 0x83, 0xb0, 0xa7, 0x83, - 0x52, 0x22, 0x15, 0xe1, 0x34, 0x02, 0xee, 0xae, 0x63, 0x7f, 0x9d, 0x8a, 0x33, 0x74, 0xb4, 0xce, - 0x40, 0x16, 0x78, 0xd3, 0x94, 0x05, 0x2e, 0xe6, 0xce, 0x5c, 0x8e, 0x1c, 0x70, 0x64, 0xc1, 0xb8, - 0x36, 0xb3, 0xc9, 0x9a, 0xb5, 0x7a, 0xac, 0xd9, 0x0e, 0xcc, 0xd0, 0x95, 0x7e, 0x7b, 0x8b, 0xb9, - 0x13, 0x35, 0xd9, 0xc2, 0x2c, 0x3c, 0xdc, 0xc2, 0x54, 0x86, 0xb8, 0xb7, 0x52, 0x04, 0x71, 0x57, - 0x13, 0xe8, 0x35, 0xa9, 0x8d, 0x2a, 0x1a, 0xa6, 0x5b, 0x5c, 0xd3, 0x74, 0x7c, 0x58, 0x9e, 0xd1, - 0x3e, 0x44, 0xd7, 0x3e, 0xd9, 0x5f, 0x91, 0xdf, 0xc8, 0x99, 0xcd, 0x22, 0x94, 0x1a, 0x6a, 0xb1, - 0x58, 0xa6, 0x31, 0xb9, 0x5a, 0x0e, 0x38, 0xc1, 0xa1, 0x7b, 0x94, 0x5e, 0x41, 0xd2, 0xd6, 0x86, - 0xf4, 0x82, 0x82, 0x19, 0xc4, 0x7e, 0x19, 0x60, 0xf5, 0x01, 0x69, 0xf0, 0xa5, 0xae, 0x3f, 0xea, - 0x5a, 0xf9, 0x8f, 0xba, 0xf6, 0x7f, 0xb2, 0x60, 0x6a, 0x6d, 0xc5, 0xb8, 0x26, 0x2e, 0x00, 0xf0, - 0xbb, 0xd1, 0xbd, 0x7b, 0x1b, 0xf2, 0xbd, 0x82, 0xab, 0x9c, 0x55, 0x29, 0xd6, 0x30, 0xd0, 0x45, - 0x28, 0x7a, 0x1d, 0x5f, 0x5c, 0x59, 0x46, 0x8f, 0x0e, 0xcb, 0xc5, 0x5b, 0x1d, 0x1f, 0xd3, 0x32, - 0xcd, 0xc0, 0xaf, 0x38, 0xb0, 0x81, 0x5f, 0x5f, 0x37, 0x21, 0x54, 0x86, 0xe1, 0xfb, 0xf7, 0xdd, - 0x26, 0x37, 0xc6, 0x16, 0x6f, 0x29, 0xf7, 0xee, 0x55, 0x2b, 0x11, 0xe6, 0xe5, 0xf6, 0xd7, 0x8a, - 0x30, 0xbf, 0xe6, 0x91, 0x07, 0x1f, 0xd2, 0x20, 0x7d, 0x50, 0xf3, 0xc4, 0x93, 0xc9, 0x8b, 0x27, - 0xb5, 0xc5, 0xec, 0x3f, 0x1e, 0xdb, 0x30, 0xca, 0x0d, 0x04, 0xa4, 0x79, 0xfa, 0x1b, 0x59, 0xad, - 0xe7, 0x0f, 0xc8, 0x82, 0xd0, 0xce, 0x71, 0x13, 0x2c, 0x75, 0xd2, 0x8a, 0x52, 0x2c, 0x89, 0xcf, - 0x7f, 0x0e, 0x26, 0x74, 0xcc, 0x13, 0x59, 0x45, 0xff, 0x8d, 0x22, 0xcc, 0xd0, 0x1e, 0x3c, 0xd2, - 0x89, 0xb8, 0xd3, 0x3d, 0x11, 0xa7, 0x6d, 0x19, 0xdb, 0x7f, 0x36, 0xde, 0x4d, 0xcf, 0xc6, 0x4b, - 0x79, 0xb3, 0x71, 0xd6, 0x73, 0xf0, 0xbd, 0x16, 0x9c, 0x5b, 0xf3, 0x82, 0xc6, 0x6e, 0xca, 0x68, - 0xf7, 0x55, 0x18, 0xa7, 0x7c, 0x3c, 0x32, 0xbc, 0x61, 0x0c, 0xff, 0x28, 0x01, 0xc2, 0x3a, 0x9e, - 0x56, 0xed, 0xce, 0x9d, 0x6a, 0x25, 0xcb, 0xad, 0x4a, 0x80, 0xb0, 0x8e, 0x67, 0xff, 0xb6, 0x05, - 0x4f, 0x5d, 0x5f, 0x59, 0x4d, 0x96, 0x62, 0x97, 0x67, 0x17, 0xbd, 0x05, 0x36, 0xb5, 0xae, 0x24, - 0xb7, 0xc0, 0x0a, 0xeb, 0x85, 0x80, 0x7e, 0x5c, 0xbc, 0x16, 0x7f, 0xd6, 0x82, 0x73, 0xd7, 0xdd, - 0x98, 0x1e, 0xcb, 0x69, 0x1f, 0x23, 0x7a, 0x2e, 0x47, 0x6e, 0x1c, 0x84, 0x07, 0x69, 0x1f, 0x23, - 0xac, 0x20, 0x58, 0xc3, 0xe2, 0x2d, 0xef, 0xbb, 0x11, 0xed, 0x69, 0xc1, 0x54, 0x45, 0x61, 0x51, - 0x8e, 0x15, 0x06, 0xfd, 0xb0, 0xa6, 0x1b, 0xb2, 0xab, 0xc4, 0x81, 0xe0, 0xb0, 0xea, 0xc3, 0x2a, - 0x12, 0x80, 0x13, 0x1c, 0xfb, 0x27, 0x2d, 0xb8, 0x70, 0xdd, 0xeb, 0x44, 0x31, 0x09, 0xb7, 0x23, - 0xa3, 0xb3, 0x2f, 0x43, 0x89, 0xc8, 0xeb, 0xba, 0xe8, 0xab, 0x12, 0x30, 0xd5, 0x3d, 0x9e, 0x3b, - 0x38, 0x29, 0xbc, 0x01, 0x2c, 0xe0, 0x4f, 0x66, 0xb9, 0xfd, 0x0b, 0x05, 0x98, 0xbc, 0xb1, 0xb9, - 0x59, 0xbb, 0x4e, 0x62, 0x71, 0x8a, 0xf5, 0x57, 0x35, 0x63, 0x4d, 0x63, 0xd6, 0xeb, 0x52, 0xd4, - 0x89, 0x5d, 0x6f, 0x81, 0x7b, 0xd4, 0x2e, 0x54, 0xfd, 0xf8, 0x76, 0x58, 0x8f, 0x43, 0xd7, 0x6f, - 0x65, 0xea, 0xd8, 0xe4, 0x59, 0x5b, 0xcc, 0x3b, 0x6b, 0xd1, 0xcb, 0x30, 0xc2, 0x5c, 0x7a, 0xe5, - 0xf5, 0xe4, 0x09, 0x75, 0xa7, 0x60, 0xa5, 0xc7, 0x87, 0xe5, 0xd2, 0x1d, 0x5c, 0xe5, 0x7f, 0xb0, - 0x40, 0x45, 0x77, 0x60, 0x7c, 0x27, 0x8e, 0xdb, 0x37, 0x88, 0xd3, 0x24, 0xa1, 0xe4, 0x0e, 0x97, - 0xb2, 0xb8, 0x03, 0x1d, 0x04, 0x8e, 0x96, 0x6c, 0xa8, 0xa4, 0x2c, 0xc2, 0x3a, 0x1d, 0xbb, 0x0e, - 0x90, 0xc0, 0x4e, 0x49, 0xbf, 0x60, 0xff, 0x91, 0x05, 0xa3, 0xdc, 0xbb, 0x2a, 0x44, 0x9f, 0x87, - 0x21, 0xf2, 0x80, 0x34, 0x84, 0xe4, 0x98, 0xd9, 0xe1, 0x44, 0xf0, 0xe0, 0xda, 0x72, 0xfa, 0x1f, - 0xb3, 0x5a, 0xe8, 0x06, 0x8c, 0xd2, 0xde, 0x5e, 0x57, 0xae, 0x66, 0x4f, 0xe7, 0x7d, 0xb1, 0x9a, - 0x76, 0x2e, 0xab, 0x88, 0x22, 0x2c, 0xab, 0x33, 0xcd, 0x6f, 0xa3, 0x5d, 0xa7, 0x0c, 0x2c, 0xee, - 0x75, 0xce, 0x6e, 0xae, 0xd4, 0x38, 0x92, 0xa0, 0xc6, 0x35, 0xbf, 0xb2, 0x10, 0x27, 0x44, 0xec, - 0x4d, 0x28, 0xd1, 0x49, 0x5d, 0xf2, 0x5c, 0xa7, 0xb7, 0xd2, 0xf9, 0x79, 0x28, 0x49, 0x05, 0x70, - 0x24, 0x1c, 0x74, 0x18, 0x55, 0xa9, 0x1f, 0x8e, 0x70, 0x02, 0xb7, 0xb7, 0xe1, 0x3c, 0xb3, 0xa6, - 0x70, 0xe2, 0x1d, 0x63, 0x8f, 0xf5, 0x5f, 0xcc, 0x2f, 0x88, 0x8b, 0x18, 0x9f, 0x99, 0x39, 0xcd, - 0xa3, 0x60, 0x42, 0x52, 0x4c, 0x2e, 0x65, 0xf6, 0x9f, 0x0c, 0xc1, 0x13, 0xd5, 0x7a, 0xbe, 0xe3, - 0xdd, 0xeb, 0x30, 0xc1, 0xc5, 0x34, 0xba, 0xb4, 0x1d, 0x4f, 0xb4, 0xab, 0xde, 0x1a, 0x37, 0x35, - 0x18, 0x36, 0x30, 0xd1, 0x53, 0x50, 0x74, 0xdf, 0xf7, 0xd3, 0xc6, 0xb9, 0xd5, 0xb7, 0x37, 0x30, - 0x2d, 0xa7, 0x60, 0x2a, 0xf1, 0x71, 0x56, 0xaa, 0xc0, 0x4a, 0xea, 0x7b, 0x13, 0xa6, 0xdc, 0xa8, - 0x11, 0xb9, 0x55, 0x9f, 0xf2, 0x99, 0xc4, 0x69, 0x33, 0x51, 0x12, 0xd0, 0x4e, 0x2b, 0x28, 0x4e, - 0x61, 0x6b, 0x7c, 0x7d, 0x78, 0x60, 0xa9, 0xb1, 0xaf, 0xc7, 0x0a, 0x15, 0x88, 0xdb, 0xec, 0xeb, - 0x22, 0x66, 0x28, 0x28, 0x04, 0x62, 0xfe, 0xc1, 0x11, 0x96, 0x30, 0x7a, 0x03, 0x6b, 0xec, 0x38, - 0xed, 0xa5, 0x4e, 0xbc, 0x53, 0x71, 0xa3, 0x46, 0xb0, 0x4f, 0xc2, 0x03, 0x76, 0x79, 0x1e, 0x4b, - 0x6e, 0x60, 0x0a, 0xb0, 0x72, 0x63, 0xa9, 0x46, 0x31, 0x71, 0x77, 0x1d, 0x53, 0x2a, 0x84, 0xd3, - 0x90, 0x0a, 0x97, 0x60, 0x5a, 0x36, 0x53, 0x27, 0x11, 0x3b, 0x23, 0xc6, 0x59, 0xc7, 0x94, 0x3b, - 0xb5, 0x28, 0x56, 0xdd, 0x4a, 0xe3, 0xa3, 0xd7, 0x60, 0xd2, 0xf5, 0xdd, 0xd8, 0x75, 0xe2, 0x20, - 0x64, 0x27, 0x2c, 0xbf, 0x27, 0xb3, 0x47, 0xd1, 0xaa, 0x0e, 0xc0, 0x26, 0x9e, 0xfd, 0xc7, 0x43, - 0x30, 0xcb, 0xa6, 0xed, 0x5b, 0x2b, 0xec, 0x63, 0xb3, 0xc2, 0xee, 0x74, 0xaf, 0xb0, 0xd3, 0x10, - 0x77, 0x3f, 0xca, 0x65, 0xf6, 0x1e, 0x94, 0x94, 0x7d, 0xb5, 0x74, 0x11, 0xb0, 0x72, 0x5c, 0x04, - 0xfa, 0x4b, 0x1f, 0xf2, 0x19, 0xb7, 0x98, 0xf9, 0x8c, 0xfb, 0xf7, 0x2d, 0x48, 0xcc, 0x4c, 0xd1, - 0x0d, 0x28, 0xb5, 0x03, 0x66, 0xca, 0x11, 0x4a, 0xfb, 0xa8, 0x27, 0x32, 0x0f, 0x2a, 0x7e, 0x28, - 0xf2, 0xf1, 0xab, 0xc9, 0x1a, 0x38, 0xa9, 0x8c, 0x96, 0x61, 0xb4, 0x1d, 0x92, 0x7a, 0xcc, 0x5c, - 0x39, 0xfb, 0xd2, 0xe1, 0x6b, 0x84, 0xe3, 0x63, 0x59, 0xd1, 0xfe, 0x45, 0x0b, 0x80, 0xbf, 0x94, - 0x3a, 0x7e, 0x8b, 0x9c, 0x81, 0xf6, 0xb7, 0x02, 0x43, 0x51, 0x9b, 0x34, 0x7a, 0x19, 0xd9, 0x24, - 0xfd, 0xa9, 0xb7, 0x49, 0x23, 0x19, 0x70, 0xfa, 0x0f, 0xb3, 0xda, 0xf6, 0xf7, 0x03, 0x4c, 0x25, - 0x68, 0xd5, 0x98, 0xec, 0xa1, 0x17, 0x0d, 0x47, 0xb9, 0x8b, 0x29, 0x47, 0xb9, 0x12, 0xc3, 0xd6, - 0x14, 0x8d, 0xef, 0x41, 0x71, 0xcf, 0x79, 0x20, 0x34, 0x49, 0xcf, 0xf7, 0xee, 0x06, 0xa5, 0xbf, - 0xb0, 0xee, 0x3c, 0xe0, 0x77, 0xa6, 0xe7, 0xe5, 0x02, 0x59, 0x77, 0x1e, 0x1c, 0x73, 0x53, 0x1a, - 0xc6, 0xa4, 0x6e, 0xb9, 0x51, 0xfc, 0xd5, 0xff, 0x92, 0xfc, 0x67, 0xcb, 0x8e, 0x36, 0xc2, 0xda, - 0x72, 0x7d, 0xf1, 0x6e, 0x38, 0x50, 0x5b, 0xae, 0x9f, 0x6e, 0xcb, 0xf5, 0x07, 0x68, 0xcb, 0xf5, - 0xd1, 0x07, 0x30, 0x2a, 0xde, 0xe8, 0x99, 0xfd, 0xbc, 0xa9, 0xa5, 0xca, 0x6b, 0x4f, 0x3c, 0xf1, - 0xf3, 0x36, 0x17, 0xe5, 0x9d, 0x50, 0x94, 0xf6, 0x6d, 0x57, 0x36, 0x88, 0xfe, 0xae, 0x05, 0x53, - 0xe2, 0x37, 0x26, 0xef, 0x77, 0x48, 0x14, 0x0b, 0xd9, 0xf3, 0xb3, 0x83, 0xf7, 0x41, 0x54, 0xe4, - 0x5d, 0xf9, 0xac, 0x64, 0xb3, 0x26, 0xb0, 0x6f, 0x8f, 0x52, 0xbd, 0x40, 0xff, 0xdc, 0x82, 0xf3, - 0x7b, 0xce, 0x03, 0xde, 0x22, 0x2f, 0xc3, 0x4e, 0xec, 0x06, 0xc2, 0x1f, 0xe0, 0xf3, 0x83, 0x4d, - 0x7f, 0x57, 0x75, 0xde, 0x49, 0x69, 0x3a, 0x7c, 0x3e, 0x0b, 0xa5, 0x6f, 0x57, 0x33, 0xfb, 0x35, - 0xbf, 0x0d, 0x63, 0x72, 0xbd, 0x65, 0xdc, 0xbc, 0x2b, 0xba, 0x60, 0x7d, 0x62, 0x13, 0x09, 0xdd, - 0x5b, 0x8d, 0xb6, 0x23, 0xd6, 0xda, 0x23, 0x6d, 0xe7, 0x3d, 0x98, 0xd0, 0xd7, 0xd8, 0x23, 0x6d, - 0xeb, 0x7d, 0x38, 0x97, 0xb1, 0x96, 0x1e, 0x69, 0x93, 0xf7, 0xe1, 0x62, 0xee, 0xfa, 0x78, 0x94, - 0x0d, 0xdb, 0xbf, 0x60, 0xe9, 0x7c, 0xf0, 0x0c, 0x54, 0xf0, 0x2b, 0xa6, 0x0a, 0xfe, 0x52, 0xef, - 0x9d, 0x93, 0xa3, 0x87, 0x7f, 0x57, 0xef, 0x34, 0xe5, 0xea, 0xe8, 0x2d, 0x18, 0xf1, 0x68, 0x89, - 0x34, 0x0e, 0xb1, 0xfb, 0xef, 0xc8, 0x44, 0x96, 0x62, 0xe5, 0x11, 0x16, 0x14, 0xec, 0x5f, 0xb1, - 0x60, 0xe8, 0x0c, 0x46, 0x02, 0x9b, 0x23, 0xf1, 0x62, 0x2e, 0x69, 0x11, 0x9a, 0x6b, 0x01, 0x3b, - 0xf7, 0x57, 0x65, 0xf8, 0xb1, 0x9c, 0x81, 0xf9, 0xbf, 0x05, 0x18, 0xa7, 0x4d, 0x49, 0x2b, 0xc6, - 0x37, 0x60, 0xd2, 0x73, 0xb6, 0x88, 0x27, 0xdf, 0x71, 0xd3, 0x0a, 0x93, 0x5b, 0x3a, 0x10, 0x9b, - 0xb8, 0xb4, 0xf2, 0xb6, 0xfe, 0xa4, 0x2d, 0xe4, 0x17, 0x55, 0xd9, 0x78, 0xef, 0xc6, 0x26, 0x2e, - 0xbd, 0xbb, 0xdf, 0x77, 0xe2, 0xc6, 0x8e, 0x50, 0xa6, 0xa8, 0xee, 0xde, 0xa3, 0x85, 0x98, 0xc3, - 0xa8, 0x00, 0x27, 0x57, 0xe7, 0x5d, 0x7a, 0x33, 0x0c, 0x7c, 0x21, 0x1e, 0x2b, 0x01, 0x0e, 0x9b, - 0x60, 0x9c, 0xc6, 0xcf, 0xf0, 0x98, 0x1f, 0x66, 0x36, 0x9a, 0x03, 0x78, 0xcc, 0xa3, 0x1a, 0x9c, - 0x77, 0xfd, 0x86, 0xd7, 0x69, 0x92, 0x3b, 0x3e, 0x97, 0xee, 0x3c, 0xf7, 0x03, 0xd2, 0x14, 0x02, - 0xb4, 0x32, 0xa7, 0xad, 0x66, 0xe0, 0xe0, 0xcc, 0x9a, 0xf6, 0x5f, 0x83, 0x73, 0xb7, 0x02, 0xa7, - 0xb9, 0xec, 0x78, 0x8e, 0xdf, 0x20, 0x61, 0xd5, 0x6f, 0xf5, 0xb5, 0x12, 0xd3, 0x6d, 0xba, 0x0a, - 0xfd, 0x6c, 0xba, 0xec, 0x1d, 0x40, 0x7a, 0x03, 0xc2, 0x36, 0x19, 0xc3, 0xa8, 0xcb, 0x9b, 0x12, - 0xcb, 0xff, 0xd3, 0xd9, 0xd2, 0x75, 0x57, 0xcf, 0x34, 0xab, 0x5b, 0x5e, 0x80, 0x25, 0x21, 0xfb, - 0x75, 0xc8, 0xf4, 0x47, 0xec, 0xaf, 0xb6, 0xb1, 0x5f, 0x85, 0x59, 0x56, 0xf3, 0x64, 0x2a, 0x05, - 0xfb, 0x07, 0x2d, 0x98, 0xde, 0x48, 0xc5, 0xb8, 0xb8, 0xc2, 0xde, 0x5a, 0x33, 0xf4, 0xee, 0x75, - 0x56, 0x8a, 0x05, 0xf4, 0xd4, 0xf5, 0x7b, 0x7f, 0x61, 0x41, 0x49, 0x45, 0x67, 0x3a, 0x03, 0xa1, - 0x76, 0xc5, 0x10, 0x6a, 0x33, 0xf5, 0x4e, 0xaa, 0x3b, 0x79, 0x32, 0x2d, 0xba, 0xa9, 0xa2, 0x35, - 0xf4, 0x50, 0x39, 0x25, 0x64, 0xb8, 0x6f, 0xff, 0x94, 0x19, 0xd2, 0x41, 0xc6, 0x6f, 0x60, 0x66, - 0x5a, 0x0a, 0xf7, 0x63, 0x62, 0xa6, 0xa5, 0xfa, 0x93, 0xc3, 0xfd, 0x6a, 0x5a, 0x97, 0xd9, 0xa9, - 0xf0, 0xed, 0xcc, 0x95, 0x81, 0xed, 0x4d, 0x15, 0x24, 0xa5, 0x2c, 0x5c, 0x13, 0x44, 0xe9, 0x31, - 0x63, 0x64, 0xe2, 0x1f, 0x8f, 0xa4, 0x95, 0x54, 0xb1, 0x6f, 0xc0, 0x74, 0x6a, 0xc0, 0xd0, 0xab, - 0x30, 0xdc, 0xde, 0x71, 0x22, 0x92, 0x32, 0x4d, 0x1d, 0xae, 0xd1, 0xc2, 0xe3, 0xc3, 0xf2, 0x94, - 0xaa, 0xc0, 0x4a, 0x30, 0xc7, 0xb6, 0xff, 0xa7, 0x05, 0x43, 0x1b, 0x41, 0xf3, 0x2c, 0x16, 0xd3, - 0x9b, 0xc6, 0x62, 0x7a, 0x32, 0x2f, 0x0e, 0x61, 0xee, 0x3a, 0x5a, 0x4b, 0xad, 0xa3, 0x4b, 0xb9, - 0x14, 0x7a, 0x2f, 0xa1, 0x3d, 0x18, 0x67, 0xd1, 0x0d, 0x85, 0xa9, 0xec, 0xcb, 0xc6, 0xfd, 0xaa, - 0x9c, 0xba, 0x5f, 0x4d, 0x6b, 0xa8, 0xda, 0x2d, 0xeb, 0x59, 0x18, 0x15, 0xe6, 0x9a, 0x69, 0xa7, - 0x0d, 0x81, 0x8b, 0x25, 0xdc, 0xfe, 0xa9, 0x22, 0x18, 0xd1, 0x14, 0xd1, 0xaf, 0x59, 0xb0, 0x10, - 0x72, 0x2f, 0xd8, 0x66, 0xa5, 0x13, 0xba, 0x7e, 0xab, 0xde, 0xd8, 0x21, 0xcd, 0x8e, 0xe7, 0xfa, - 0xad, 0x6a, 0xcb, 0x0f, 0x54, 0xf1, 0xea, 0x03, 0xd2, 0xe8, 0xb0, 0x37, 0x97, 0x3e, 0xa1, 0x1b, - 0x95, 0x39, 0xd4, 0xb5, 0xa3, 0xc3, 0xf2, 0x02, 0x3e, 0x11, 0x6d, 0x7c, 0xc2, 0xbe, 0xa0, 0xdf, - 0xb6, 0x60, 0x91, 0x07, 0x19, 0x1c, 0xbc, 0xff, 0x3d, 0x6e, 0xa3, 0x35, 0x49, 0x2a, 0x21, 0xb2, - 0x49, 0xc2, 0xbd, 0xe5, 0xd7, 0xc4, 0x80, 0x2e, 0xd6, 0x4e, 0xd6, 0x16, 0x3e, 0x69, 0xe7, 0xec, - 0x7f, 0x57, 0x84, 0x49, 0x3a, 0x8a, 0x49, 0x6c, 0x9a, 0x57, 0x8d, 0x25, 0xf1, 0x74, 0x6a, 0x49, - 0xcc, 0x1a, 0xc8, 0xa7, 0x13, 0x96, 0x26, 0x82, 0x59, 0xcf, 0x89, 0xe2, 0x1b, 0xc4, 0x09, 0xe3, - 0x2d, 0xe2, 0x70, 0x33, 0xa1, 0xe2, 0x89, 0x4d, 0x9a, 0x94, 0xfa, 0xeb, 0x56, 0x9a, 0x18, 0xee, - 0xa6, 0x8f, 0xf6, 0x01, 0x31, 0x5b, 0xa7, 0xd0, 0xf1, 0x23, 0xfe, 0x2d, 0xae, 0x78, 0x8f, 0x39, - 0x59, 0xab, 0xf3, 0xa2, 0x55, 0x74, 0xab, 0x8b, 0x1a, 0xce, 0x68, 0x41, 0xb3, 0x61, 0x1b, 0x1e, - 0xd4, 0x86, 0x6d, 0xa4, 0x8f, 0x67, 0xd4, 0x1e, 0xcc, 0x88, 0x59, 0xd9, 0x76, 0x5b, 0xe2, 0x90, - 0xfe, 0x52, 0xca, 0xc6, 0xd5, 0x1a, 0xdc, 0x50, 0xa9, 0x8f, 0x81, 0xab, 0xfd, 0xdd, 0x70, 0x8e, - 0x36, 0x67, 0xfa, 0xf1, 0x44, 0x88, 0xc0, 0xf4, 0x6e, 0x67, 0x8b, 0x78, 0x24, 0x96, 0x65, 0xa2, - 0xd1, 0x4c, 0xb1, 0xdf, 0xac, 0x9d, 0xc8, 0x96, 0x37, 0x4d, 0x12, 0x38, 0x4d, 0xd3, 0xfe, 0x19, - 0x0b, 0x98, 0xb5, 0xfc, 0x19, 0x1c, 0x7f, 0x5f, 0x30, 0x8f, 0xbf, 0xb9, 0x3c, 0x0e, 0x94, 0x73, - 0xf2, 0xbd, 0xc2, 0xa7, 0xa5, 0x16, 0x06, 0x0f, 0x0e, 0xa4, 0xec, 0xdf, 0x5f, 0xe2, 0xfa, 0x3f, - 0x16, 0xdf, 0x90, 0x2a, 0x28, 0x00, 0xfa, 0x1e, 0x18, 0x6b, 0x38, 0x6d, 0xa7, 0xc1, 0xc3, 0xd8, - 0xe6, 0x6a, 0x7f, 0x8c, 0x4a, 0x0b, 0x2b, 0xa2, 0x06, 0xd7, 0x66, 0x7c, 0x46, 0x7e, 0xa5, 0x2c, - 0xee, 0xab, 0xc1, 0x50, 0x4d, 0xce, 0xef, 0xc2, 0xa4, 0x41, 0xec, 0x91, 0x5e, 0x7d, 0xbf, 0x87, - 0x1f, 0x17, 0xea, 0xc6, 0xb2, 0x07, 0xb3, 0xbe, 0xf6, 0x9f, 0x32, 0x47, 0x29, 0x4e, 0x7f, 0xb2, - 0xdf, 0x81, 0xc0, 0x38, 0xa9, 0xe6, 0x0d, 0x90, 0x22, 0x83, 0xbb, 0x29, 0xdb, 0xff, 0xd0, 0x82, - 0xc7, 0x75, 0x44, 0x2d, 0x5e, 0x43, 0x3f, 0x7d, 0x72, 0x05, 0xc6, 0x82, 0x36, 0x09, 0x9d, 0xe4, - 0x4e, 0x76, 0x55, 0x0e, 0xfa, 0x6d, 0x51, 0x7e, 0x2c, 0xe2, 0x09, 0x4a, 0xea, 0xb2, 0x1c, 0xab, - 0x9a, 0xc8, 0x86, 0x11, 0x36, 0x18, 0x91, 0x88, 0xa5, 0xc1, 0xcc, 0x14, 0xd9, 0xd3, 0x6a, 0x84, - 0x05, 0xc4, 0xfe, 0x7e, 0x8b, 0x2f, 0x2c, 0xbd, 0xeb, 0xe8, 0x7d, 0x98, 0xd9, 0xa3, 0xd7, 0xb7, - 0xd5, 0x07, 0xed, 0x90, 0xab, 0xd1, 0xe5, 0x38, 0x3d, 0xdf, 0x6f, 0x9c, 0xb4, 0x8f, 0x4c, 0x8c, - 0xd9, 0xd6, 0x53, 0xc4, 0x70, 0x17, 0x79, 0xfb, 0xcf, 0x0a, 0x7c, 0x27, 0x32, 0xa9, 0xee, 0x59, - 0x18, 0x6d, 0x07, 0xcd, 0x95, 0x6a, 0x05, 0x8b, 0x11, 0x52, 0xec, 0xaa, 0xc6, 0x8b, 0xb1, 0x84, - 0xa3, 0x6b, 0x00, 0xe4, 0x41, 0x4c, 0x42, 0xdf, 0xf1, 0x94, 0xe1, 0x87, 0x12, 0x9e, 0x56, 0x15, - 0x04, 0x6b, 0x58, 0xb4, 0x4e, 0x3b, 0x0c, 0xf6, 0xdd, 0x26, 0xf3, 0x36, 0x2c, 0x9a, 0x75, 0x6a, - 0x0a, 0x82, 0x35, 0x2c, 0x7a, 0x55, 0xee, 0xf8, 0x11, 0x3f, 0x00, 0x9d, 0x2d, 0x11, 0x20, 0x6f, - 0x2c, 0xb9, 0x2a, 0xdf, 0xd1, 0x81, 0xd8, 0xc4, 0x45, 0x4b, 0x30, 0x12, 0x3b, 0xcc, 0x9c, 0x61, - 0x38, 0xdf, 0x2c, 0x71, 0x93, 0x62, 0xe8, 0x71, 0x4d, 0x69, 0x05, 0x2c, 0x2a, 0xa2, 0x77, 0x24, - 0x0b, 0xe6, 0x2c, 0x59, 0xd8, 0x03, 0xe7, 0x2e, 0x5b, 0x9d, 0x7d, 0xeb, 0x3c, 0x58, 0xd8, 0x19, - 0x1b, 0xb4, 0xec, 0xef, 0x2b, 0x01, 0x24, 0xd2, 0x1e, 0xfa, 0xa0, 0x8b, 0x45, 0xbc, 0xd0, 0x5b, - 0x3e, 0x3c, 0x3d, 0xfe, 0x80, 0x7e, 0xc0, 0x82, 0x71, 0xc7, 0xf3, 0x82, 0x86, 0x13, 0xb3, 0x51, - 0x2e, 0xf4, 0x66, 0x51, 0xa2, 0xfd, 0xa5, 0xa4, 0x06, 0xef, 0xc2, 0xcb, 0xd2, 0x52, 0x41, 0x83, - 0xf4, 0xed, 0x85, 0xde, 0x30, 0xfa, 0x8c, 0xbc, 0x04, 0xf0, 0xe5, 0x31, 0x9f, 0xbe, 0x04, 0x94, - 0x18, 0x37, 0xd6, 0xe4, 0x7f, 0x74, 0xc7, 0x88, 0x24, 0x37, 0x94, 0x1f, 0x92, 0xc2, 0x10, 0x7a, - 0xfa, 0x05, 0x91, 0x43, 0x35, 0xdd, 0x2f, 0x6a, 0x38, 0x3f, 0x6e, 0x8b, 0x26, 0x5d, 0xf7, 0xf1, - 0x89, 0x7a, 0x0f, 0xa6, 0x9b, 0xe6, 0x71, 0x2b, 0x56, 0xd3, 0xa7, 0xf3, 0xe8, 0xa6, 0x4e, 0xe7, - 0xe4, 0x80, 0x4d, 0x01, 0x70, 0x9a, 0x30, 0xaa, 0x71, 0x0f, 0xb5, 0xaa, 0xbf, 0x1d, 0x08, 0xbb, - 0x72, 0x3b, 0x77, 0x2e, 0x0f, 0xa2, 0x98, 0xec, 0x51, 0xcc, 0xe4, 0x1c, 0xdd, 0x10, 0x75, 0xb1, - 0xa2, 0x82, 0xde, 0x82, 0x11, 0xe6, 0x36, 0x1c, 0xcd, 0x8d, 0xe5, 0xeb, 0x01, 0xcd, 0x88, 0x17, - 0xc9, 0xa6, 0x62, 0x7f, 0x23, 0x2c, 0x28, 0xa0, 0x1b, 0x32, 0x2c, 0x4e, 0x54, 0xf5, 0xef, 0x44, - 0x84, 0x85, 0xc5, 0x29, 0x2d, 0x7f, 0x32, 0x89, 0x78, 0xc3, 0xcb, 0x33, 0x23, 0x98, 0x1b, 0x35, - 0xa9, 0xbc, 0x22, 0xfe, 0xcb, 0xc0, 0xe8, 0x73, 0x90, 0xdf, 0x3d, 0x33, 0x78, 0x7a, 0x32, 0x9c, - 0x77, 0x4d, 0x12, 0x38, 0x4d, 0xf3, 0x4c, 0x8f, 0xcf, 0x79, 0x1f, 0x66, 0xd2, 0x1b, 0xeb, 0x91, - 0x1e, 0xd7, 0x7f, 0x34, 0x04, 0x53, 0xe6, 0x42, 0x40, 0x8b, 0x50, 0x12, 0x44, 0x54, 0x10, 0x4f, - 0xb5, 0xb6, 0xd7, 0x25, 0x00, 0x27, 0x38, 0x2c, 0x88, 0x29, 0xab, 0xae, 0xd9, 0x01, 0x26, 0x41, - 0x4c, 0x15, 0x04, 0x6b, 0x58, 0x54, 0x88, 0xde, 0x0a, 0x82, 0x58, 0x1d, 0x05, 0x6a, 0xb5, 0x2c, - 0xb3, 0x52, 0x2c, 0xa0, 0xf4, 0x08, 0xd8, 0x25, 0xa1, 0x4f, 0x3c, 0x53, 0x93, 0xa9, 0x8e, 0x80, - 0x9b, 0x3a, 0x10, 0x9b, 0xb8, 0xf4, 0x48, 0x0b, 0x22, 0xb6, 0xfc, 0x84, 0xa8, 0x9e, 0xd8, 0x55, - 0xd6, 0xb9, 0xdb, 0xbc, 0x84, 0xa3, 0x2f, 0xc1, 0xe3, 0xca, 0xcb, 0x1d, 0x73, 0xcd, 0xb0, 0x6c, - 0x71, 0xc4, 0xb8, 0x59, 0x3f, 0xbe, 0x92, 0x8d, 0x86, 0xf3, 0xea, 0xa3, 0x37, 0x61, 0x4a, 0x88, - 0xc0, 0x92, 0xe2, 0xa8, 0x69, 0xac, 0x70, 0xd3, 0x80, 0xe2, 0x14, 0x36, 0xaa, 0xc0, 0x0c, 0x2d, - 0x61, 0x52, 0xa8, 0xa4, 0xc0, 0xbd, 0xf5, 0xd5, 0x59, 0x7f, 0x33, 0x05, 0xc7, 0x5d, 0x35, 0xd0, - 0x12, 0x4c, 0x73, 0x19, 0x85, 0xde, 0x29, 0xd9, 0x3c, 0x08, 0x77, 0x0f, 0xb5, 0x11, 0x6e, 0x9b, - 0x60, 0x9c, 0xc6, 0x47, 0xaf, 0xc3, 0x84, 0x13, 0x36, 0x76, 0xdc, 0x98, 0x34, 0xe2, 0x4e, 0xc8, - 0xfd, 0x40, 0x34, 0x6b, 0x8f, 0x25, 0x0d, 0x86, 0x0d, 0x4c, 0xfb, 0x03, 0x38, 0x97, 0xe1, 0x29, - 0x46, 0x17, 0x8e, 0xd3, 0x76, 0xe5, 0x37, 0xa5, 0x2c, 0x24, 0x97, 0x6a, 0x55, 0xf9, 0x35, 0x1a, - 0x16, 0x5d, 0x9d, 0x4c, 0x25, 0xae, 0x65, 0x2f, 0x50, 0xab, 0x73, 0x4d, 0x02, 0x70, 0x82, 0x63, - 0xff, 0x16, 0x80, 0xa6, 0xd0, 0x19, 0xc0, 0x3e, 0xee, 0x75, 0x98, 0x90, 0x29, 0x37, 0xb4, 0x50, - 0xef, 0xea, 0x33, 0xaf, 0x6b, 0x30, 0x6c, 0x60, 0xd2, 0xbe, 0xf9, 0x2a, 0x50, 0x7d, 0xca, 0x1e, - 0x33, 0x09, 0x53, 0x9f, 0xe0, 0xa0, 0x17, 0x60, 0x2c, 0x22, 0xde, 0xf6, 0x2d, 0xd7, 0xdf, 0x15, - 0x0b, 0x5b, 0x71, 0xe1, 0xba, 0x28, 0xc7, 0x0a, 0x03, 0x2d, 0x43, 0xb1, 0xe3, 0x36, 0xc5, 0x52, - 0x96, 0x07, 0x7e, 0xf1, 0x4e, 0xb5, 0x72, 0x7c, 0x58, 0x7e, 0x3a, 0x2f, 0x93, 0x08, 0xbd, 0xda, - 0x47, 0x0b, 0x74, 0xfb, 0xd1, 0xca, 0x59, 0x6f, 0x03, 0x23, 0x27, 0x7c, 0x1b, 0xb8, 0x06, 0x20, - 0xbe, 0x5a, 0xae, 0xe5, 0x62, 0x32, 0x6b, 0xd7, 0x15, 0x04, 0x6b, 0x58, 0x28, 0x82, 0xd9, 0x46, - 0x48, 0x1c, 0x79, 0x87, 0xe6, 0x3e, 0x4f, 0x63, 0x0f, 0xaf, 0x20, 0x58, 0x49, 0x13, 0xc3, 0xdd, - 0xf4, 0x51, 0x00, 0xb3, 0x4d, 0x11, 0x54, 0x21, 0x69, 0xb4, 0x74, 0x72, 0x47, 0x2b, 0x66, 0x90, - 0x93, 0x26, 0x84, 0xbb, 0x69, 0xa3, 0x2f, 0xc3, 0xbc, 0x2c, 0xec, 0x8e, 0x63, 0xc1, 0xb6, 0x4b, - 0x91, 0xc7, 0x5f, 0xaf, 0xe4, 0x62, 0xe1, 0x1e, 0x14, 0x10, 0x86, 0x11, 0xf6, 0x96, 0x14, 0xcd, - 0x8d, 0xb3, 0x73, 0xee, 0xb9, 0x7c, 0x65, 0x00, 0x5d, 0xeb, 0x0b, 0xec, 0x1d, 0x4a, 0x98, 0x94, - 0x27, 0xcf, 0x72, 0xac, 0x10, 0x0b, 0x4a, 0x68, 0x1b, 0xc6, 0x1d, 0xdf, 0x0f, 0x62, 0x87, 0x8b, - 0x50, 0x13, 0xf9, 0xb2, 0x9f, 0x46, 0x78, 0x29, 0xa9, 0xc1, 0xa9, 0x2b, 0x2b, 0x55, 0x0d, 0x82, - 0x75, 0xc2, 0xe8, 0x3e, 0x4c, 0x07, 0xf7, 0x29, 0x73, 0x94, 0x5a, 0x8a, 0x68, 0x6e, 0x92, 0xb5, - 0xf5, 0xca, 0x80, 0x7a, 0x5a, 0xa3, 0xb2, 0xc6, 0xb5, 0x4c, 0xa2, 0x38, 0xdd, 0x0a, 0x5a, 0x30, - 0xb4, 0xd5, 0x53, 0x89, 0x3b, 0x4b, 0xa2, 0xad, 0xd6, 0x95, 0xd3, 0x2c, 0x2e, 0x0a, 0x37, 0x91, - 0x66, 0xbb, 0x7f, 0x3a, 0x15, 0x17, 0x25, 0x01, 0x61, 0x1d, 0x0f, 0xed, 0xc0, 0x44, 0xf2, 0x64, - 0x15, 0x46, 0x2c, 0x2a, 0xdb, 0xf8, 0xb5, 0x6b, 0x83, 0x7d, 0x5c, 0x55, 0xab, 0xc9, 0x6f, 0x0e, - 0x7a, 0x09, 0x36, 0x28, 0xcf, 0x7f, 0x1b, 0x8c, 0x6b, 0x13, 0x7b, 0xa2, 0x28, 0xb8, 0x6f, 0xc2, - 0x4c, 0x7a, 0xea, 0x4e, 0xe4, 0x41, 0xf0, 0xbf, 0x0a, 0x30, 0x9d, 0xf1, 0x72, 0xc5, 0xb2, 0x91, - 0xa4, 0x18, 0x6a, 0x92, 0x7c, 0xc4, 0x64, 0x8b, 0x85, 0x01, 0xd8, 0xa2, 0xe4, 0xd1, 0xc5, 0x5c, - 0x1e, 0x2d, 0x58, 0xe1, 0xd0, 0x87, 0x61, 0x85, 0xe6, 0xe9, 0x33, 0x3c, 0xd0, 0xe9, 0x73, 0x0a, - 0xec, 0xd3, 0x38, 0xc0, 0x46, 0x07, 0x38, 0xc0, 0x7e, 0xb4, 0x00, 0x33, 0x69, 0x0b, 0xdf, 0x33, - 0x78, 0xef, 0x78, 0xcb, 0x78, 0xef, 0xc8, 0xce, 0xed, 0x93, 0xb6, 0x3b, 0xce, 0x7b, 0xfb, 0xc0, - 0xa9, 0xb7, 0x8f, 0xe7, 0x06, 0xa2, 0xd6, 0xfb, 0x1d, 0xe4, 0x1f, 0x15, 0xe0, 0x42, 0xba, 0xca, - 0x8a, 0xe7, 0xb8, 0x7b, 0x67, 0x30, 0x36, 0xb7, 0x8d, 0xb1, 0x79, 0x71, 0x90, 0xaf, 0x61, 0x5d, - 0xcb, 0x1d, 0xa0, 0x7b, 0xa9, 0x01, 0x5a, 0x1c, 0x9c, 0x64, 0xef, 0x51, 0xfa, 0x66, 0x11, 0x2e, - 0x65, 0xd6, 0x4b, 0x9e, 0x0b, 0xd6, 0x8c, 0xe7, 0x82, 0x6b, 0xa9, 0xe7, 0x02, 0xbb, 0x77, 0xed, - 0xd3, 0x79, 0x3f, 0x10, 0xee, 0xd0, 0x2c, 0x62, 0xe8, 0x43, 0xbe, 0x1d, 0x18, 0xee, 0xd0, 0x8a, - 0x10, 0x36, 0xe9, 0xfe, 0x55, 0x7a, 0x33, 0xf8, 0x2d, 0x0b, 0x2e, 0x66, 0xce, 0xcd, 0x19, 0xe8, - 0xd5, 0x37, 0x4c, 0xbd, 0xfa, 0xb3, 0x03, 0xaf, 0xd6, 0x1c, 0x45, 0xfb, 0x1f, 0x17, 0x73, 0xbe, - 0x85, 0x69, 0x26, 0x6f, 0xc3, 0xb8, 0xd3, 0x68, 0x90, 0x28, 0x5a, 0x0f, 0x9a, 0x2a, 0x82, 0xe6, - 0x8b, 0x4c, 0xda, 0x48, 0x8a, 0x8f, 0x0f, 0xcb, 0xf3, 0x69, 0x12, 0x09, 0x18, 0xeb, 0x14, 0xcc, - 0xa0, 0xbf, 0x85, 0x53, 0x0d, 0xfa, 0x7b, 0x0d, 0x60, 0x5f, 0xe9, 0x2b, 0xd2, 0x6a, 0x4e, 0x4d, - 0x93, 0xa1, 0x61, 0xa1, 0xef, 0x62, 0xb7, 0x00, 0x6e, 0x0c, 0xc4, 0x97, 0xe2, 0xcb, 0x03, 0xce, - 0x95, 0x6e, 0x58, 0xc4, 0xe3, 0x6e, 0x28, 0x95, 0xb0, 0x22, 0x89, 0xbe, 0x03, 0x66, 0x22, 0x1e, - 0xd6, 0x69, 0xc5, 0x73, 0x22, 0xe6, 0xc4, 0x25, 0x56, 0x21, 0x0b, 0xa6, 0x51, 0x4f, 0xc1, 0x70, - 0x17, 0x36, 0x5a, 0x93, 0x1f, 0xc5, 0x62, 0x50, 0xf1, 0x85, 0x79, 0x25, 0xf9, 0x20, 0x91, 0x0b, - 0xed, 0x7c, 0x7a, 0xf8, 0xd9, 0xc0, 0x6b, 0x35, 0xed, 0x1f, 0x1d, 0x82, 0x27, 0x7a, 0x30, 0x31, - 0xb4, 0x64, 0x1a, 0x01, 0x3c, 0x9f, 0xd6, 0xff, 0xcd, 0x67, 0x56, 0x36, 0x14, 0x82, 0xa9, 0xb5, - 0x52, 0xf8, 0xd0, 0x6b, 0xe5, 0x87, 0x2c, 0x4d, 0x33, 0xcb, 0x4d, 0x85, 0xbf, 0x70, 0x42, 0xe6, - 0x7c, 0x8a, 0xaa, 0xda, 0xed, 0x0c, 0x7d, 0xe7, 0xb5, 0x81, 0xbb, 0x33, 0xb0, 0x02, 0xf4, 0x6c, - 0x9f, 0x8c, 0xbe, 0x6a, 0xc1, 0xd3, 0x99, 0xfd, 0x35, 0x8c, 0x96, 0x16, 0xa1, 0xd4, 0xa0, 0x85, - 0x9a, 0x63, 0x68, 0xe2, 0x31, 0x2f, 0x01, 0x38, 0xc1, 0x31, 0x6c, 0x93, 0x0a, 0x7d, 0x6d, 0x93, - 0xfe, 0xad, 0x05, 0x5d, 0x0b, 0xf8, 0x0c, 0x38, 0x69, 0xd5, 0xe4, 0xa4, 0x9f, 0x1c, 0x64, 0x2e, - 0x73, 0x98, 0xe8, 0xef, 0x4f, 0xc3, 0x63, 0x39, 0x9e, 0x60, 0xfb, 0x30, 0xdb, 0x6a, 0x10, 0xd3, - 0xe5, 0x56, 0x7c, 0x4c, 0xa6, 0x77, 0x72, 0x4f, 0xff, 0x5c, 0x7e, 0x21, 0xee, 0x42, 0xc1, 0xdd, - 0x4d, 0xa0, 0xaf, 0x5a, 0x70, 0xde, 0xb9, 0x1f, 0x75, 0xa5, 0x2a, 0x15, 0x6b, 0xe6, 0x95, 0x4c, - 0x3d, 0x6d, 0x9f, 0xd4, 0xa6, 0x3c, 0xab, 0x57, 0x16, 0x16, 0xce, 0x6c, 0x0b, 0x61, 0x11, 0xf4, - 0x98, 0xca, 0xdb, 0x3d, 0x9c, 0xc2, 0xb3, 0x5c, 0xf6, 0x38, 0x4f, 0x95, 0x10, 0xac, 0xe8, 0xa0, - 0xbb, 0x50, 0x6a, 0x49, 0x3f, 0x5a, 0xc1, 0xb3, 0x33, 0x0f, 0xc1, 0x4c, 0x67, 0x5b, 0xee, 0x3b, - 0xa2, 0x40, 0x38, 0x21, 0x85, 0xde, 0x84, 0xa2, 0xbf, 0x1d, 0xf5, 0x4a, 0x87, 0x95, 0xb2, 0xe5, - 0xe3, 0x01, 0x17, 0x36, 0xd6, 0xea, 0x98, 0x56, 0x44, 0x37, 0xa0, 0x18, 0x6e, 0x35, 0xc5, 0xd3, - 0x42, 0xa6, 0x5c, 0x8a, 0x97, 0x2b, 0xd9, 0x8b, 0x84, 0x53, 0xc2, 0xcb, 0x15, 0x4c, 0x49, 0xa0, - 0x1a, 0x0c, 0x33, 0xa7, 0x29, 0xf1, 0x82, 0x90, 0x29, 0x90, 0xf6, 0x70, 0x3e, 0xe4, 0x51, 0x19, - 0x18, 0x02, 0xe6, 0x84, 0xd0, 0x5b, 0x30, 0xd2, 0x60, 0x19, 0xa3, 0x84, 0xe2, 0x27, 0x3b, 0x5c, - 0x57, 0x57, 0x4e, 0x29, 0xfe, 0x82, 0xca, 0xcb, 0xb1, 0xa0, 0x80, 0x36, 0x61, 0xa4, 0x41, 0xda, - 0x3b, 0xdb, 0x91, 0xd0, 0xe7, 0x7c, 0x26, 0x93, 0x56, 0x8f, 0x04, 0x69, 0x82, 0x2a, 0xc3, 0xc0, - 0x82, 0x16, 0xfa, 0x1c, 0x14, 0xb6, 0x1b, 0xc2, 0x93, 0x2a, 0xf3, 0x0d, 0xc1, 0x8c, 0x94, 0xb1, - 0x3c, 0x72, 0x74, 0x58, 0x2e, 0xac, 0xad, 0xe0, 0xc2, 0x76, 0x03, 0x6d, 0xc0, 0xe8, 0x36, 0xf7, - 0xad, 0x17, 0x01, 0x6c, 0x3e, 0x9d, 0xed, 0xf6, 0xdf, 0xe5, 0x7e, 0xcf, 0x3d, 0x80, 0x04, 0x00, - 0x4b, 0x22, 0x2c, 0x5e, 0xb0, 0x8a, 0x11, 0x20, 0x02, 0xe7, 0x2f, 0x9c, 0x2c, 0xae, 0x83, 0x50, - 0x73, 0x28, 0x2a, 0x58, 0xa3, 0x88, 0xbe, 0x02, 0x25, 0x47, 0xa6, 0xc6, 0x14, 0x41, 0x70, 0x5e, - 0xce, 0xdc, 0x8e, 0xbd, 0xb3, 0x86, 0xf2, 0xb5, 0xac, 0x90, 0x70, 0x42, 0x14, 0xed, 0xc2, 0xe4, - 0x7e, 0xd4, 0xde, 0x21, 0x72, 0xfb, 0xb2, 0x98, 0x38, 0x39, 0xc7, 0xd5, 0x5d, 0x81, 0xe8, 0x86, - 0x71, 0xc7, 0xf1, 0xba, 0x38, 0x0e, 0x73, 0x1c, 0xbb, 0xab, 0x13, 0xc3, 0x26, 0x6d, 0x3a, 0xfc, - 0xef, 0x77, 0x82, 0xad, 0x83, 0x98, 0x88, 0x48, 0xfb, 0x99, 0xc3, 0xff, 0x36, 0x47, 0xe9, 0x1e, - 0x7e, 0x01, 0xc0, 0x92, 0x08, 0xdd, 0xe0, 0x8e, 0x4c, 0x3b, 0x2b, 0x74, 0x39, 0xcf, 0xe6, 0x0e, - 0x4f, 0x57, 0x7f, 0x93, 0x41, 0x61, 0x9c, 0x31, 0x21, 0xc5, 0x38, 0x62, 0x7b, 0x27, 0x88, 0x03, - 0x3f, 0xc5, 0x8d, 0x67, 0xf3, 0x39, 0x62, 0x2d, 0x03, 0xbf, 0x9b, 0x23, 0x66, 0x61, 0xe1, 0xcc, - 0xb6, 0x50, 0x13, 0xa6, 0xda, 0x41, 0x18, 0xdf, 0x0f, 0x42, 0xb9, 0xbe, 0x50, 0x8f, 0x4b, 0xbe, - 0x81, 0x29, 0x5a, 0x64, 0x76, 0xe0, 0x26, 0x04, 0xa7, 0x68, 0xa2, 0x2f, 0xc2, 0x68, 0xd4, 0x70, - 0x3c, 0x52, 0xbd, 0x3d, 0x77, 0x2e, 0xff, 0xa8, 0xa9, 0x73, 0x94, 0x9c, 0xd5, 0xc5, 0x26, 0x47, - 0xa0, 0x60, 0x49, 0x0e, 0xad, 0xc1, 0x30, 0x4b, 0xdf, 0xc2, 0x92, 0x04, 0xe4, 0x04, 0x5b, 0xeb, - 0xb2, 0x95, 0xe6, 0x1c, 0x89, 0x15, 0x63, 0x5e, 0x9d, 0xee, 0x01, 0x21, 0xeb, 0x06, 0xd1, 0xdc, - 0x85, 0xfc, 0x3d, 0x20, 0x44, 0xe4, 0xdb, 0xf5, 0x5e, 0x7b, 0x40, 0x21, 0xe1, 0x84, 0x28, 0xe5, - 0xc7, 0x94, 0x87, 0x3e, 0x96, 0xcf, 0x8f, 0xf3, 0x39, 0x28, 0xe3, 0xc7, 0x94, 0x7f, 0x52, 0x12, - 0xf6, 0x1f, 0x8c, 0x76, 0xcb, 0x27, 0xec, 0x76, 0xf4, 0x7d, 0x56, 0x97, 0xe9, 0xc0, 0x67, 0x07, - 0x55, 0xd6, 0x9c, 0xa2, 0x64, 0xfa, 0x55, 0x0b, 0x1e, 0x6b, 0x67, 0x7e, 0x88, 0x38, 0xec, 0x07, - 0xd3, 0xf9, 0xf0, 0x4f, 0x57, 0x89, 0x3c, 0xb2, 0xe1, 0x38, 0xa7, 0xa5, 0xb4, 0xf4, 0x5f, 0xfc, - 0xd0, 0xd2, 0xff, 0x3a, 0x8c, 0x31, 0x81, 0x32, 0x89, 0xec, 0x37, 0x90, 0x01, 0x1e, 0x13, 0x1b, - 0x56, 0x44, 0x45, 0xac, 0x48, 0xa0, 0x1f, 0xb6, 0xe0, 0xa9, 0x74, 0xd7, 0x31, 0x61, 0x60, 0x11, - 0x25, 0x9a, 0x5f, 0xcc, 0xd6, 0xc4, 0xf7, 0x3f, 0x55, 0xeb, 0x85, 0x7c, 0xdc, 0x0f, 0x01, 0xf7, - 0x6e, 0x0c, 0x55, 0x32, 0x6e, 0x86, 0x23, 0xe6, 0xcb, 0xe2, 0x00, 0xb7, 0xc3, 0x57, 0x60, 0x62, - 0x2f, 0xe8, 0xf8, 0xd2, 0x3b, 0x46, 0xf8, 0x3e, 0x33, 0x2d, 0xf6, 0xba, 0x56, 0x8e, 0x0d, 0xac, - 0xd4, 0x9d, 0x72, 0xec, 0x61, 0xef, 0x94, 0xe8, 0xdd, 0x54, 0x9a, 0xf8, 0x52, 0xbe, 0x6c, 0x21, - 0xae, 0xdf, 0x27, 0x48, 0x16, 0x7f, 0xb6, 0xf7, 0xa0, 0xaf, 0x5b, 0x19, 0x02, 0x3c, 0xbf, 0x19, - 0x7f, 0xde, 0xbc, 0x19, 0x5f, 0x49, 0xdf, 0x8c, 0xbb, 0x34, 0xa1, 0xc6, 0xa5, 0x78, 0xf0, 0x18, - 0xfd, 0x83, 0x06, 0x68, 0xb4, 0x3d, 0xb8, 0xdc, 0xef, 0x58, 0x62, 0xa6, 0x92, 0x4d, 0x65, 0x43, - 0x90, 0x98, 0x4a, 0x36, 0xab, 0x15, 0xcc, 0x20, 0x83, 0x46, 0xf0, 0xb1, 0xff, 0xbb, 0x05, 0xc5, - 0x5a, 0xd0, 0x3c, 0x03, 0xcd, 0xee, 0x17, 0x0c, 0xcd, 0xee, 0x13, 0x39, 0xe9, 0xfb, 0x73, 0xf5, - 0xb8, 0xab, 0x29, 0x3d, 0xee, 0x53, 0x79, 0x04, 0x7a, 0x6b, 0x6d, 0x7f, 0xba, 0x08, 0xe3, 0xb5, - 0xa0, 0xa9, 0x6c, 0xee, 0xff, 0xfd, 0xc3, 0xd8, 0xdc, 0xe7, 0xc6, 0x5b, 0xd6, 0x28, 0x33, 0x0b, - 0x4b, 0xe9, 0xce, 0xfb, 0x97, 0xcc, 0xf4, 0xfe, 0x1e, 0x71, 0x5b, 0x3b, 0x31, 0x69, 0xa6, 0x3f, - 0xe7, 0xec, 0x4c, 0xef, 0xff, 0xab, 0x05, 0xd3, 0xa9, 0xd6, 0x91, 0x97, 0xe5, 0x1b, 0xf8, 0x90, - 0x1a, 0xbd, 0xd9, 0xbe, 0xce, 0x84, 0x0b, 0x00, 0xea, 0xd9, 0x4c, 0x6a, 0xbb, 0x98, 0xd4, 0xaf, - 0xde, 0xd5, 0x22, 0xac, 0x61, 0xa0, 0x57, 0x61, 0x3c, 0x0e, 0xda, 0x81, 0x17, 0xb4, 0x0e, 0x6e, - 0x12, 0x19, 0x33, 0x4a, 0x3d, 0x6e, 0x6e, 0x26, 0x20, 0xac, 0xe3, 0xd9, 0x3f, 0x5b, 0xe4, 0x1f, - 0xea, 0xc7, 0xee, 0xb7, 0xd6, 0xe4, 0xc7, 0x7b, 0x4d, 0x7e, 0xd3, 0x82, 0x19, 0xda, 0x3a, 0xb3, - 0x5e, 0x93, 0x87, 0xad, 0xca, 0x15, 0x66, 0xf5, 0xc8, 0x15, 0x76, 0x85, 0xf2, 0xae, 0x66, 0xd0, - 0x89, 0x85, 0xb6, 0x4c, 0x63, 0x4e, 0xb4, 0x14, 0x0b, 0xa8, 0xc0, 0x23, 0x61, 0x28, 0x3c, 0xfe, - 0x74, 0x3c, 0x12, 0x86, 0x58, 0x40, 0x65, 0x2a, 0xb1, 0xa1, 0x9c, 0x54, 0x62, 0x2c, 0x02, 0xa6, - 0xb0, 0x98, 0x12, 0x62, 0x8f, 0x16, 0x01, 0x53, 0x9a, 0x52, 0x25, 0x38, 0xf6, 0x2f, 0x14, 0x61, - 0xa2, 0x16, 0x34, 0x93, 0x87, 0xab, 0x57, 0x8c, 0x87, 0xab, 0xcb, 0xa9, 0x87, 0xab, 0x19, 0x1d, - 0xf7, 0x5b, 0xcf, 0x54, 0x1f, 0xd5, 0x33, 0xd5, 0xbf, 0xb1, 0xd8, 0xac, 0x55, 0x36, 0xea, 0x22, - 0x19, 0xf7, 0x4b, 0x30, 0xce, 0x18, 0x12, 0x73, 0x31, 0x95, 0xaf, 0x39, 0x2c, 0xa3, 0xc5, 0x46, - 0x52, 0x8c, 0x75, 0x1c, 0x74, 0x15, 0xc6, 0x22, 0xe2, 0x84, 0x8d, 0x1d, 0xc5, 0xe3, 0xc4, 0x5b, - 0x07, 0x2f, 0xc3, 0x0a, 0x8a, 0xde, 0x4e, 0x82, 0x2f, 0x16, 0xf3, 0xd3, 0x4a, 0xeb, 0xfd, 0xe1, - 0x5b, 0x24, 0x3f, 0xe2, 0xa2, 0x7d, 0x0f, 0x50, 0x37, 0xfe, 0x00, 0x66, 0x64, 0x65, 0x33, 0xcc, - 0x5a, 0xa9, 0x2b, 0xc4, 0xda, 0x9f, 0x5b, 0x30, 0x55, 0x0b, 0x9a, 0x74, 0xeb, 0xfe, 0x55, 0xda, - 0xa7, 0x7a, 0xe4, 0xd9, 0x91, 0x1e, 0x91, 0x67, 0xff, 0xb1, 0x05, 0xa3, 0xb5, 0xa0, 0x79, 0x06, - 0x3a, 0xf6, 0xcf, 0x9b, 0x3a, 0xf6, 0xc7, 0x73, 0x96, 0x44, 0x8e, 0x5a, 0xfd, 0x97, 0x8a, 0x30, - 0x49, 0xfb, 0x19, 0xb4, 0xe4, 0x2c, 0x19, 0x23, 0x62, 0x0d, 0x30, 0x22, 0x54, 0xcc, 0x0d, 0x3c, - 0x2f, 0xb8, 0x9f, 0x9e, 0xb1, 0x35, 0x56, 0x8a, 0x05, 0x14, 0xbd, 0x00, 0x63, 0xed, 0x90, 0xec, - 0xbb, 0x41, 0x27, 0x4a, 0x7b, 0x53, 0xd7, 0x44, 0x39, 0x56, 0x18, 0xf4, 0xde, 0x15, 0xb9, 0x7e, - 0x83, 0x48, 0xfb, 0xb2, 0x21, 0x66, 0x5f, 0xc6, 0x43, 0xca, 0x6b, 0xe5, 0xd8, 0xc0, 0x42, 0xf7, - 0xa0, 0xc4, 0xfe, 0x33, 0x8e, 0x72, 0xf2, 0x24, 0x67, 0x22, 0x8f, 0x8b, 0x20, 0x80, 0x13, 0x5a, - 0xe8, 0x1a, 0x40, 0x2c, 0x2d, 0xe1, 0x22, 0xe1, 0xec, 0xaf, 0x64, 0x6d, 0x65, 0x23, 0x17, 0x61, - 0x0d, 0x0b, 0x3d, 0x0f, 0xa5, 0xd8, 0x71, 0xbd, 0x5b, 0xae, 0x4f, 0x22, 0x61, 0x49, 0x28, 0xd2, - 0xb4, 0x88, 0x42, 0x9c, 0xc0, 0xa9, 0xac, 0xc3, 0x42, 0x49, 0xf0, 0x14, 0x89, 0x63, 0x0c, 0x9b, - 0xc9, 0x3a, 0xb7, 0x54, 0x29, 0xd6, 0x30, 0xec, 0xd7, 0xe1, 0x42, 0x2d, 0x68, 0xd6, 0x82, 0x30, - 0x5e, 0x0b, 0xc2, 0xfb, 0x4e, 0xd8, 0x94, 0xf3, 0x57, 0x96, 0x19, 0x43, 0x28, 0xef, 0x19, 0xe6, - 0x3b, 0xd3, 0xc8, 0x05, 0xf2, 0x32, 0x93, 0x76, 0x4e, 0xe8, 0xf6, 0xf5, 0xbf, 0x0b, 0x8c, 0x51, - 0xa4, 0xf2, 0x76, 0xa2, 0x2f, 0xc3, 0x54, 0x44, 0x6e, 0xb9, 0x7e, 0xe7, 0x81, 0xbc, 0x1f, 0xf7, - 0xf0, 0xa9, 0xab, 0xaf, 0xea, 0x98, 0x5c, 0xcb, 0x66, 0x96, 0xe1, 0x14, 0x35, 0x3a, 0x84, 0x61, - 0xc7, 0x5f, 0x8a, 0xee, 0x44, 0x24, 0x14, 0x79, 0x23, 0xd9, 0x10, 0x62, 0x59, 0x88, 0x13, 0x38, - 0x5d, 0x32, 0xec, 0xcf, 0x46, 0xe0, 0xe3, 0x20, 0x88, 0xe5, 0x22, 0x63, 0x99, 0xc7, 0xb4, 0x72, - 0x6c, 0x60, 0xa1, 0x35, 0x40, 0x51, 0xa7, 0xdd, 0xf6, 0xd8, 0x03, 0xb8, 0xe3, 0x5d, 0x0f, 0x83, - 0x4e, 0x9b, 0x3f, 0x3e, 0x8a, 0xa4, 0x5d, 0xf5, 0x2e, 0x28, 0xce, 0xa8, 0x41, 0x19, 0xc3, 0x76, - 0xc4, 0x7e, 0x8b, 0x68, 0x12, 0x5c, 0xf3, 0x5d, 0x67, 0x45, 0x58, 0xc2, 0xe8, 0x3c, 0xb3, 0xe6, - 0x39, 0xe6, 0x48, 0x32, 0xcf, 0x58, 0x95, 0x62, 0x0d, 0xc3, 0xfe, 0x1e, 0x76, 0xc0, 0xb0, 0xf4, - 0x80, 0x71, 0x27, 0x24, 0x68, 0x0f, 0x26, 0xdb, 0xec, 0xe8, 0x17, 0x81, 0xd6, 0xc5, 0x80, 0x3f, - 0x9c, 0x9d, 0x21, 0x4f, 0x17, 0xa6, 0x93, 0xc3, 0x26, 0x75, 0xfb, 0xa7, 0x67, 0x18, 0x1f, 0xab, - 0xf3, 0xeb, 0xdf, 0xa8, 0xf0, 0x1e, 0x10, 0xb2, 0xee, 0x7c, 0xbe, 0x1e, 0x22, 0x39, 0x72, 0x84, - 0x07, 0x02, 0x96, 0x75, 0xd1, 0xdb, 0xec, 0x95, 0x97, 0x33, 0x8f, 0x7e, 0x79, 0xc6, 0x39, 0x96, - 0xf1, 0xa0, 0x2b, 0x2a, 0x62, 0x8d, 0x08, 0xba, 0x05, 0x93, 0x22, 0x9b, 0x9c, 0x50, 0x34, 0x15, - 0x0d, 0x45, 0xc2, 0x24, 0xd6, 0x81, 0xc7, 0xe9, 0x02, 0x6c, 0x56, 0x46, 0x2d, 0x78, 0x4a, 0x4b, - 0xad, 0x9a, 0x61, 0xeb, 0xca, 0x79, 0xd1, 0xd3, 0x47, 0x87, 0xe5, 0xa7, 0x36, 0x7b, 0x21, 0xe2, - 0xde, 0x74, 0xd0, 0x6d, 0xb8, 0xe0, 0x34, 0x62, 0x77, 0x9f, 0x54, 0x88, 0xd3, 0xf4, 0x5c, 0x9f, - 0x98, 0xe1, 0x48, 0x2e, 0x1e, 0x1d, 0x96, 0x2f, 0x2c, 0x65, 0x21, 0xe0, 0xec, 0x7a, 0xe8, 0xf3, - 0x50, 0x6a, 0xfa, 0x91, 0x18, 0x83, 0x11, 0x23, 0x6b, 0x70, 0xa9, 0xb2, 0x51, 0x57, 0xdf, 0x9f, - 0xfc, 0xc1, 0x49, 0x05, 0xd4, 0xe2, 0xca, 0x26, 0x75, 0xb7, 0x1b, 0xed, 0x8a, 0x31, 0x93, 0xd6, - 0x12, 0x18, 0x7e, 0x7a, 0x5c, 0xcb, 0xaa, 0x2c, 0xc9, 0x0d, 0x17, 0x3e, 0x83, 0x30, 0x7a, 0x0b, - 0x10, 0x15, 0x7e, 0xdc, 0x06, 0x59, 0x6a, 0xb0, 0x78, 0xf7, 0x4c, 0x37, 0x37, 0x66, 0xb8, 0x45, - 0xa1, 0x7a, 0x17, 0x06, 0xce, 0xa8, 0x85, 0x6e, 0x50, 0x0e, 0xa4, 0x97, 0x0a, 0xc3, 0x7f, 0x29, - 0x30, 0xcf, 0x55, 0x48, 0x3b, 0x24, 0x0d, 0x27, 0x26, 0x4d, 0x93, 0x22, 0x4e, 0xd5, 0xa3, 0xe7, - 0x93, 0x4a, 0x7d, 0x05, 0xa6, 0xb9, 0x7a, 0x77, 0xfa, 0x2b, 0x7a, 0xd7, 0xdc, 0x09, 0xa2, 0x78, - 0x83, 0xc4, 0xf7, 0x83, 0x70, 0x57, 0xc4, 0x10, 0x4c, 0xc2, 0xd9, 0x26, 0x20, 0xac, 0xe3, 0x51, - 0xd9, 0x92, 0x3d, 0xb3, 0x56, 0x2b, 0xec, 0xd5, 0x6b, 0x2c, 0xd9, 0x27, 0x37, 0x78, 0x31, 0x96, - 0x70, 0x89, 0x5a, 0xad, 0xad, 0xb0, 0x17, 0xac, 0x14, 0x6a, 0xb5, 0xb6, 0x82, 0x25, 0x1c, 0x91, - 0xee, 0x8c, 0xcc, 0x53, 0xf9, 0x9a, 0xc2, 0x6e, 0x3e, 0x3e, 0x60, 0x52, 0x66, 0x1f, 0x66, 0x54, - 0x2e, 0x68, 0x1e, 0x5c, 0x31, 0x9a, 0x9b, 0x66, 0x8b, 0x64, 0xf0, 0xc8, 0x8c, 0x4a, 0xf7, 0x5a, - 0x4d, 0x51, 0xc2, 0x5d, 0xb4, 0x8d, 0x30, 0x37, 0x33, 0x7d, 0x53, 0x97, 0x2d, 0x42, 0x29, 0xea, - 0x6c, 0x35, 0x83, 0x3d, 0xc7, 0xf5, 0xd9, 0x83, 0x93, 0x26, 0xb8, 0xd4, 0x25, 0x00, 0x27, 0x38, - 0x68, 0x0d, 0xc6, 0x1c, 0xa9, 0x58, 0x45, 0xf9, 0x71, 0x2f, 0x94, 0x3a, 0x95, 0x89, 0xe5, 0x4a, - 0x95, 0xaa, 0xea, 0xa2, 0x37, 0x60, 0x52, 0xb8, 0x66, 0x0a, 0xab, 0xea, 0x73, 0xa6, 0x17, 0x4f, - 0x5d, 0x07, 0x62, 0x13, 0x17, 0x7d, 0x17, 0x4c, 0x51, 0x2a, 0x09, 0x63, 0x9b, 0x3b, 0x3f, 0x08, - 0x47, 0xd4, 0x52, 0xd2, 0xe8, 0x95, 0x71, 0x8a, 0x18, 0x6a, 0xc2, 0x93, 0x4e, 0x27, 0x0e, 0x98, - 0x72, 0xda, 0x5c, 0xff, 0x9b, 0xc1, 0x2e, 0xf1, 0xd9, 0xbb, 0xd0, 0xd8, 0xf2, 0xe5, 0xa3, 0xc3, - 0xf2, 0x93, 0x4b, 0x3d, 0xf0, 0x70, 0x4f, 0x2a, 0xe8, 0x0e, 0x8c, 0xc7, 0x81, 0x27, 0xdc, 0x21, - 0xa2, 0xb9, 0xc7, 0xf2, 0xc3, 0x74, 0x6d, 0x2a, 0x34, 0x5d, 0x31, 0xa3, 0xaa, 0x62, 0x9d, 0x0e, - 0xda, 0xe4, 0x7b, 0x8c, 0x05, 0x30, 0x26, 0xd1, 0xdc, 0xe3, 0xf9, 0x03, 0xa3, 0xe2, 0x1c, 0x9b, - 0x5b, 0x50, 0xd4, 0xc4, 0x3a, 0x19, 0x74, 0x1d, 0x66, 0xdb, 0xa1, 0x1b, 0xb0, 0x85, 0xad, 0x1e, - 0x06, 0xe6, 0xcc, 0x2c, 0x24, 0xb5, 0x34, 0x02, 0xee, 0xae, 0x43, 0x2f, 0x6e, 0xb2, 0x70, 0xee, - 0x22, 0x4f, 0x69, 0xc7, 0x85, 0x59, 0x5e, 0x86, 0x15, 0x14, 0xad, 0x33, 0xbe, 0xcc, 0xaf, 0x58, - 0x73, 0xf3, 0xf9, 0xf1, 0x42, 0xf4, 0xab, 0x18, 0x17, 0x74, 0xd4, 0x5f, 0x9c, 0x50, 0xa0, 0xe7, - 0x46, 0xb4, 0xe3, 0x84, 0xa4, 0x16, 0x06, 0x0d, 0xc2, 0x3b, 0xc3, 0xcd, 0xcf, 0x9f, 0xe0, 0x71, - 0x56, 0xe9, 0xb9, 0x51, 0xcf, 0x42, 0xc0, 0xd9, 0xf5, 0xe6, 0xbf, 0x1d, 0x66, 0xbb, 0x38, 0xf9, - 0x89, 0x4c, 0xe7, 0xff, 0x6c, 0x18, 0x4a, 0x4a, 0xf1, 0x8b, 0x16, 0x4d, 0x7d, 0xfe, 0xc5, 0xb4, - 0x3e, 0x7f, 0x8c, 0xca, 0x9f, 0xba, 0x0a, 0x7f, 0xd3, 0x30, 0xfc, 0x2a, 0xe4, 0xa7, 0xba, 0xd3, - 0xb5, 0x1e, 0x7d, 0xfd, 0x5c, 0xb5, 0x7b, 0x7c, 0x71, 0xe0, 0x87, 0x81, 0xa1, 0x9e, 0xaa, 0x81, - 0x01, 0xb3, 0x77, 0xd3, 0xab, 0x6e, 0x3b, 0x68, 0x56, 0x6b, 0xe9, 0x74, 0xb6, 0x35, 0x5a, 0x88, - 0x39, 0x8c, 0x5d, 0x56, 0xa8, 0xd8, 0xc1, 0x2e, 0x2b, 0xa3, 0x0f, 0x79, 0x59, 0x91, 0x04, 0x70, - 0x42, 0x0b, 0x79, 0x30, 0xdb, 0x30, 0x33, 0x11, 0x2b, 0xdf, 0xd6, 0x67, 0xfa, 0xe6, 0x04, 0xee, - 0x68, 0x29, 0x0a, 0x57, 0xd2, 0x54, 0x70, 0x37, 0x61, 0xf4, 0x06, 0x8c, 0xbd, 0x1f, 0x44, 0x6c, - 0x5b, 0x88, 0xb3, 0x57, 0x7a, 0x13, 0x8e, 0xbd, 0x7d, 0xbb, 0xce, 0xca, 0x8f, 0x0f, 0xcb, 0xe3, - 0xb5, 0xa0, 0x29, 0xff, 0x62, 0x55, 0x01, 0x3d, 0x80, 0x0b, 0x06, 0xc7, 0x52, 0xdd, 0x85, 0xc1, - 0xbb, 0xfb, 0x94, 0x68, 0xee, 0x42, 0x35, 0x8b, 0x12, 0xce, 0x6e, 0x80, 0xb2, 0x01, 0x3f, 0x10, - 0x59, 0xbc, 0xe5, 0xf9, 0xce, 0x8e, 0xf1, 0x92, 0x1e, 0x94, 0x21, 0x85, 0x80, 0xbb, 0xeb, 0xd8, - 0xdf, 0xe0, 0x7a, 0x72, 0xa1, 0x4d, 0x23, 0x51, 0xc7, 0x3b, 0x8b, 0x84, 0x66, 0xab, 0x86, 0xa2, - 0xef, 0xa1, 0xdf, 0x62, 0x7e, 0xc3, 0x62, 0x6f, 0x31, 0x9b, 0x64, 0xaf, 0xed, 0x39, 0xf1, 0x59, - 0x78, 0x5e, 0xbc, 0x0d, 0x63, 0xb1, 0x68, 0xad, 0x57, 0x0e, 0x36, 0xad, 0x53, 0xec, 0x3d, 0x4a, - 0x9d, 0xfc, 0xb2, 0x14, 0x2b, 0x32, 0xf6, 0xbf, 0xe4, 0x33, 0x20, 0x21, 0x67, 0xa0, 0x74, 0xa9, - 0x98, 0x4a, 0x97, 0x72, 0x9f, 0x2f, 0xc8, 0x51, 0xbe, 0xfc, 0x0b, 0xb3, 0xdf, 0xec, 0x92, 0xf5, - 0x71, 0x7f, 0x04, 0xb4, 0x7f, 0xdc, 0x82, 0xf3, 0x59, 0x56, 0x33, 0x54, 0x5a, 0xe3, 0x57, 0x3c, - 0xf5, 0x28, 0xaa, 0x46, 0xf0, 0xae, 0x28, 0xc7, 0x0a, 0x63, 0xe0, 0xf4, 0x26, 0x27, 0x8b, 0xc1, - 0x77, 0x1b, 0xcc, 0xec, 0xd7, 0xe8, 0x4d, 0xee, 0x4a, 0x65, 0xa9, 0xf4, 0xd4, 0x27, 0x73, 0xa3, - 0xb2, 0x7f, 0xae, 0x00, 0xe7, 0xf9, 0xab, 0xc6, 0xd2, 0x7e, 0xe0, 0x36, 0x6b, 0x41, 0x53, 0x38, - 0x96, 0xbd, 0x03, 0x13, 0x6d, 0xed, 0x5e, 0xde, 0x2b, 0x0a, 0x98, 0x7e, 0x7f, 0x4f, 0xee, 0x47, - 0x7a, 0x29, 0x36, 0x68, 0xa1, 0x26, 0x4c, 0x90, 0x7d, 0xb7, 0xa1, 0x54, 0xe3, 0x85, 0x13, 0x9f, - 0x0d, 0xaa, 0x95, 0x55, 0x8d, 0x0e, 0x36, 0xa8, 0x3e, 0x82, 0x6c, 0x85, 0xf6, 0x4f, 0x58, 0xf0, - 0x78, 0x4e, 0xcc, 0x30, 0xda, 0xdc, 0x7d, 0xf6, 0x7e, 0x24, 0x12, 0x9f, 0xa9, 0xe6, 0xf8, 0xab, - 0x12, 0x16, 0x50, 0xf4, 0x45, 0x00, 0xfe, 0x2a, 0x44, 0xaf, 0x0b, 0xe2, 0xd3, 0x07, 0x8b, 0xa5, - 0xa3, 0x05, 0x5c, 0x91, 0xf5, 0xb1, 0x46, 0xcb, 0xfe, 0x99, 0x22, 0x0c, 0xb3, 0x57, 0x08, 0xb4, - 0x06, 0xa3, 0x3b, 0x3c, 0x42, 0xf9, 0x20, 0xc1, 0xd0, 0x93, 0x7b, 0x17, 0x2f, 0xc0, 0xb2, 0x32, - 0x5a, 0x87, 0x73, 0xc2, 0x79, 0xb1, 0x42, 0x3c, 0xe7, 0x40, 0x5e, 0xdf, 0x79, 0xb2, 0x30, 0x95, - 0x1e, 0xaf, 0xda, 0x8d, 0x82, 0xb3, 0xea, 0xa1, 0x37, 0xbb, 0xe2, 0x92, 0xf2, 0xd8, 0xee, 0x4a, - 0xd8, 0xef, 0x13, 0x9b, 0xf4, 0x0d, 0x98, 0x6c, 0x77, 0x29, 0x2a, 0x86, 0x93, 0x8b, 0x88, 0xa9, - 0x9c, 0x30, 0x71, 0x99, 0xb9, 0x4c, 0x87, 0x19, 0x07, 0x6d, 0xee, 0x84, 0x24, 0xda, 0x09, 0xbc, - 0xa6, 0xc8, 0xdf, 0x9f, 0x98, 0xcb, 0xa4, 0xe0, 0xb8, 0xab, 0x06, 0xa5, 0xb2, 0xed, 0xb8, 0x5e, - 0x27, 0x24, 0x09, 0x95, 0x11, 0x93, 0xca, 0x5a, 0x0a, 0x8e, 0xbb, 0x6a, 0xd0, 0x75, 0x74, 0x41, - 0x24, 0x7f, 0x97, 0x21, 0x2d, 0x94, 0x0d, 0xd4, 0xa8, 0x74, 0x6d, 0xe9, 0x11, 0x66, 0x49, 0x58, - 0x89, 0xa8, 0xf4, 0xf1, 0x5a, 0x6a, 0x61, 0xe1, 0xd4, 0x22, 0xa9, 0x3c, 0x4c, 0x0a, 0xf2, 0x3f, - 0xb0, 0xe0, 0x5c, 0x86, 0xad, 0x25, 0x67, 0x55, 0x2d, 0x37, 0x8a, 0x55, 0x42, 0x24, 0x8d, 0x55, - 0xf1, 0x72, 0xac, 0x30, 0xe8, 0x7e, 0xe0, 0xcc, 0x30, 0xcd, 0x00, 0x85, 0x2d, 0x93, 0x80, 0x9e, - 0x8c, 0x01, 0xa2, 0xcb, 0x30, 0xd4, 0x89, 0x48, 0x28, 0x73, 0x77, 0x4b, 0xfe, 0xcd, 0x54, 0xa5, - 0x0c, 0x42, 0x45, 0xd3, 0x96, 0xd2, 0x52, 0x6a, 0xa2, 0x29, 0x57, 0x3d, 0x72, 0x98, 0xfd, 0xb5, - 0x22, 0x5c, 0xcc, 0xb5, 0xa5, 0xa6, 0x5d, 0xda, 0x0b, 0x7c, 0x37, 0x0e, 0xd4, 0x0b, 0x17, 0x8f, - 0x07, 0x44, 0xda, 0x3b, 0xeb, 0xa2, 0x1c, 0x2b, 0x0c, 0x74, 0x05, 0x86, 0xd9, 0xcd, 0xbe, 0x2b, - 0xe5, 0xd3, 0x72, 0x85, 0x87, 0xa9, 0xe0, 0xe0, 0x81, 0xd3, 0xe9, 0x3d, 0x03, 0x43, 0xed, 0x20, - 0xf0, 0xd2, 0xcc, 0x88, 0x76, 0x37, 0x08, 0x3c, 0xcc, 0x80, 0xe8, 0x53, 0x62, 0x1c, 0x52, 0x4f, - 0x3a, 0xd8, 0x69, 0x06, 0x91, 0x36, 0x18, 0xcf, 0xc2, 0xe8, 0x2e, 0x39, 0x08, 0x5d, 0xbf, 0x95, - 0x7e, 0xea, 0xbb, 0xc9, 0x8b, 0xb1, 0x84, 0x9b, 0x19, 0x4f, 0x46, 0x4f, 0x3b, 0x0f, 0xde, 0x58, - 0xdf, 0xa3, 0xed, 0x87, 0x8a, 0x30, 0x8d, 0x97, 0x2b, 0xdf, 0x9a, 0x88, 0x3b, 0xdd, 0x13, 0x71, - 0xda, 0x79, 0xf0, 0xfa, 0xcf, 0xc6, 0x2f, 0x59, 0x30, 0xcd, 0xa2, 0x82, 0x8b, 0x78, 0x36, 0x6e, - 0xe0, 0x9f, 0x81, 0xe8, 0xf6, 0x0c, 0x0c, 0x87, 0xb4, 0xd1, 0x74, 0x72, 0x2b, 0xd6, 0x13, 0xcc, - 0x61, 0xe8, 0x49, 0x18, 0x62, 0x5d, 0xa0, 0x93, 0x37, 0xc1, 0xf3, 0x82, 0x54, 0x9c, 0xd8, 0xc1, - 0xac, 0x94, 0x39, 0x16, 0x63, 0xd2, 0xf6, 0x5c, 0xde, 0xe9, 0x44, 0xd5, 0xff, 0xf1, 0x70, 0x2c, - 0xce, 0xec, 0xda, 0x87, 0x73, 0x2c, 0xce, 0x26, 0xd9, 0xfb, 0x5a, 0xf4, 0x3f, 0x0a, 0x70, 0x29, - 0xb3, 0xde, 0xc0, 0x8e, 0xc5, 0xbd, 0x6b, 0x9f, 0x8e, 0xc5, 0x46, 0xb6, 0x21, 0x45, 0xf1, 0x0c, - 0x0d, 0x29, 0x86, 0x06, 0x95, 0x1c, 0x87, 0x07, 0xf0, 0xf7, 0xcd, 0x1c, 0xb2, 0x8f, 0x89, 0xbf, - 0x6f, 0x66, 0xdf, 0x72, 0xae, 0x75, 0x7f, 0x51, 0xc8, 0xf9, 0x16, 0x76, 0xc1, 0xbb, 0x4a, 0xf9, - 0x0c, 0x03, 0x46, 0x42, 0x12, 0x9e, 0xe0, 0x3c, 0x86, 0x97, 0x61, 0x05, 0x45, 0xae, 0xe6, 0x39, - 0x5b, 0xc8, 0x4f, 0x7d, 0x9a, 0xdb, 0xd4, 0x82, 0xf9, 0x32, 0xa3, 0x07, 0xdf, 0x49, 0x7b, 0xd1, - 0xae, 0x6b, 0x97, 0xf2, 0xe2, 0xe0, 0x97, 0xf2, 0x89, 0xec, 0x0b, 0x39, 0x5a, 0x82, 0xe9, 0x3d, - 0xd7, 0xa7, 0x6c, 0xf3, 0xc0, 0x14, 0x45, 0x55, 0x20, 0x89, 0x75, 0x13, 0x8c, 0xd3, 0xf8, 0xf3, - 0x6f, 0xc0, 0xe4, 0xc3, 0xab, 0x23, 0xbf, 0x59, 0x84, 0x27, 0x7a, 0x6c, 0x7b, 0xce, 0xeb, 0x8d, - 0x39, 0xd0, 0x78, 0x7d, 0xd7, 0x3c, 0xd4, 0xe0, 0xfc, 0x76, 0xc7, 0xf3, 0x0e, 0x98, 0xad, 0x22, - 0x69, 0x4a, 0x0c, 0x21, 0x2b, 0xaa, 0x90, 0xff, 0x6b, 0x19, 0x38, 0x38, 0xb3, 0x26, 0x7a, 0x0b, - 0x50, 0x20, 0xf2, 0x2e, 0x27, 0x21, 0x85, 0xd8, 0xc0, 0x17, 0x93, 0xcd, 0x78, 0xbb, 0x0b, 0x03, - 0x67, 0xd4, 0xa2, 0x42, 0x3f, 0x3d, 0x95, 0x0e, 0x54, 0xb7, 0x52, 0x42, 0x3f, 0xd6, 0x81, 0xd8, - 0xc4, 0x45, 0xd7, 0x61, 0xd6, 0xd9, 0x77, 0x5c, 0x1e, 0x62, 0x52, 0x12, 0xe0, 0x52, 0xbf, 0x52, - 0x82, 0x2d, 0xa5, 0x11, 0x70, 0x77, 0x9d, 0x94, 0xeb, 0xee, 0x48, 0xbe, 0xeb, 0x6e, 0x6f, 0xbe, - 0xd8, 0x4f, 0xa7, 0x6b, 0xff, 0x67, 0x8b, 0x1e, 0x5f, 0x5c, 0x78, 0x37, 0xc3, 0x6d, 0xbd, 0x01, - 0x93, 0x4a, 0x37, 0xa9, 0x79, 0xd1, 0xaa, 0x71, 0x58, 0xd1, 0x81, 0xd8, 0xc4, 0xe5, 0x0b, 0x22, - 0x4a, 0x1c, 0x3a, 0x0c, 0xd1, 0x5d, 0xb8, 0xc9, 0x2b, 0x0c, 0xf4, 0x25, 0x18, 0x6d, 0xba, 0xfb, - 0x6e, 0x14, 0x84, 0x62, 0xb3, 0x9c, 0xd0, 0x2c, 0x3e, 0xe1, 0x83, 0x15, 0x4e, 0x06, 0x4b, 0x7a, - 0xf6, 0x0f, 0x15, 0x60, 0x52, 0xb6, 0xf8, 0x76, 0x27, 0x88, 0x9d, 0x33, 0x38, 0x96, 0xaf, 0x1b, - 0xc7, 0xf2, 0xa7, 0x7a, 0xc5, 0x0a, 0x60, 0x5d, 0xca, 0x3d, 0x8e, 0x6f, 0xa7, 0x8e, 0xe3, 0x4f, - 0xf7, 0x27, 0xd5, 0xfb, 0x18, 0xfe, 0x57, 0x16, 0xcc, 0x1a, 0xf8, 0x67, 0x70, 0x1a, 0xac, 0x99, - 0xa7, 0xc1, 0xd3, 0x7d, 0xbf, 0x21, 0xe7, 0x14, 0xf8, 0x7a, 0x21, 0xd5, 0x77, 0xc6, 0xfd, 0xdf, - 0x87, 0xa1, 0x1d, 0x27, 0x6c, 0xf6, 0x0a, 0x94, 0xdc, 0x55, 0x69, 0xe1, 0x86, 0x13, 0x36, 0x39, - 0x0f, 0x7f, 0x41, 0x65, 0x6b, 0x75, 0xc2, 0x66, 0x5f, 0xff, 0x25, 0xd6, 0x14, 0x7a, 0x1d, 0x46, - 0xa2, 0x46, 0xd0, 0x56, 0xd6, 0x85, 0x97, 0x79, 0x26, 0x57, 0x5a, 0x72, 0x7c, 0x58, 0x46, 0x66, - 0x73, 0xb4, 0x18, 0x0b, 0xfc, 0xf9, 0x16, 0x94, 0x54, 0xd3, 0x8f, 0xd4, 0x37, 0xe4, 0x77, 0x8b, - 0x70, 0x2e, 0x63, 0x5d, 0xa0, 0xc8, 0x18, 0xad, 0x97, 0x06, 0x5c, 0x4e, 0x1f, 0x72, 0xbc, 0x22, - 0x76, 0x63, 0x69, 0x8a, 0xf9, 0x1f, 0xb8, 0xd1, 0x3b, 0x11, 0x49, 0x37, 0x4a, 0x8b, 0xfa, 0x37, - 0x4a, 0x1b, 0x3b, 0xb3, 0xa1, 0xa6, 0x0d, 0xa9, 0x9e, 0x3e, 0xd2, 0x39, 0xfd, 0xd3, 0x22, 0x9c, - 0xcf, 0x0a, 0x31, 0x82, 0xbe, 0x3b, 0x95, 0x76, 0xe9, 0x95, 0x41, 0x83, 0x93, 0xf0, 0x5c, 0x4c, - 0x22, 0x26, 0xdb, 0x82, 0x99, 0x88, 0xa9, 0xef, 0x30, 0x8b, 0x36, 0x99, 0x43, 0x61, 0xc8, 0xd3, - 0x65, 0xc9, 0x2d, 0xfe, 0xd9, 0x81, 0x3b, 0x20, 0xf2, 0x6c, 0x45, 0x29, 0x87, 0x42, 0x59, 0xdc, - 0xdf, 0xa1, 0x50, 0xb6, 0x3c, 0xef, 0xc2, 0xb8, 0xf6, 0x35, 0x8f, 0x74, 0xc6, 0x77, 0xe9, 0x89, - 0xa2, 0xf5, 0xfb, 0x91, 0xce, 0xfa, 0x4f, 0x58, 0x90, 0xb2, 0xe9, 0x53, 0x2a, 0x29, 0x2b, 0x57, - 0x25, 0x75, 0x19, 0x86, 0xc2, 0xc0, 0x23, 0xe9, 0x4c, 0x3c, 0x38, 0xf0, 0x08, 0x66, 0x10, 0x8a, - 0x11, 0x27, 0x0a, 0x89, 0x09, 0xfd, 0xb2, 0x25, 0xae, 0x51, 0xcf, 0xc0, 0xb0, 0x47, 0xf6, 0x89, - 0xd4, 0x46, 0x28, 0x9e, 0x7c, 0x8b, 0x16, 0x62, 0x0e, 0xb3, 0x7f, 0x69, 0x08, 0x9e, 0xea, 0xe9, - 0x92, 0x4b, 0xaf, 0x2c, 0x2d, 0x27, 0x26, 0xf7, 0x9d, 0x83, 0x74, 0x9c, 0xf0, 0xeb, 0xbc, 0x18, - 0x4b, 0x38, 0xb3, 0x40, 0xe6, 0xa1, 0x46, 0x53, 0x0a, 0x3c, 0x11, 0x61, 0x54, 0x40, 0x4d, 0xc5, - 0x51, 0xf1, 0x34, 0x14, 0x47, 0xd7, 0x00, 0xa2, 0xc8, 0x5b, 0xf5, 0xa9, 0x04, 0xd6, 0x14, 0xa6, - 0xcd, 0x49, 0x48, 0xda, 0xfa, 0x2d, 0x01, 0xc1, 0x1a, 0x16, 0xaa, 0xc0, 0x4c, 0x3b, 0x0c, 0x62, - 0xae, 0x0f, 0xad, 0x70, 0x23, 0x99, 0x61, 0xd3, 0x1b, 0xb2, 0x96, 0x82, 0xe3, 0xae, 0x1a, 0xe8, - 0x55, 0x18, 0x17, 0x1e, 0x92, 0xb5, 0x20, 0xf0, 0x84, 0xaa, 0x46, 0x99, 0x5c, 0xd4, 0x13, 0x10, - 0xd6, 0xf1, 0xb4, 0x6a, 0x4c, 0xc9, 0x3a, 0x9a, 0x59, 0x8d, 0x2b, 0x5a, 0x35, 0xbc, 0x54, 0xb8, - 0xa1, 0xb1, 0x81, 0xc2, 0x0d, 0x25, 0xca, 0xab, 0xd2, 0xc0, 0xef, 0x4a, 0xd0, 0x57, 0xdd, 0xf3, - 0xf3, 0x43, 0x70, 0x4e, 0x2c, 0x9c, 0x47, 0xbd, 0x5c, 0xee, 0x74, 0x2f, 0x97, 0xd3, 0x50, 0x6f, - 0x7d, 0x6b, 0xcd, 0x9c, 0xf5, 0x9a, 0xf9, 0x46, 0x11, 0x46, 0xf8, 0x54, 0x9c, 0x81, 0x0c, 0xbf, - 0x26, 0x94, 0x7e, 0x3d, 0x02, 0xed, 0xf0, 0xbe, 0x2c, 0x54, 0x9c, 0xd8, 0xe1, 0xe7, 0x97, 0x62, - 0xa3, 0x89, 0x7a, 0x10, 0x2d, 0x18, 0x8c, 0x76, 0x3e, 0xa5, 0xd5, 0x02, 0x4e, 0x43, 0x63, 0xbb, - 0x5f, 0x06, 0x88, 0xe2, 0xd0, 0xf5, 0x5b, 0x94, 0x86, 0x08, 0xd9, 0xf4, 0x5c, 0x8f, 0xd6, 0xeb, - 0x0a, 0x99, 0xf7, 0x21, 0x59, 0x82, 0x0a, 0x80, 0x35, 0x8a, 0xf3, 0xaf, 0x41, 0x49, 0x21, 0xf7, - 0x53, 0x01, 0x4c, 0xe8, 0xa7, 0xde, 0x17, 0x60, 0x3a, 0xd5, 0xd6, 0x89, 0x34, 0x08, 0xbf, 0x6c, - 0xc1, 0x34, 0xef, 0xf2, 0xaa, 0xbf, 0x2f, 0x36, 0xfb, 0x07, 0x70, 0xde, 0xcb, 0xd8, 0x74, 0x62, - 0x46, 0x07, 0xdf, 0xa4, 0x4a, 0x63, 0x90, 0x05, 0xc5, 0x99, 0x6d, 0xa0, 0xab, 0x30, 0xc6, 0x5d, - 0x76, 0x1c, 0x4f, 0xb8, 0x59, 0x4c, 0xf0, 0xd4, 0x1d, 0xbc, 0x0c, 0x2b, 0xa8, 0xfd, 0x7b, 0x16, - 0xcc, 0xf2, 0x9e, 0xdf, 0x24, 0x07, 0xea, 0x76, 0xfc, 0x51, 0xf6, 0x5d, 0x64, 0x26, 0x29, 0xe4, - 0x64, 0x26, 0xd1, 0x3f, 0xad, 0xd8, 0xf3, 0xd3, 0x7e, 0xce, 0x02, 0xb1, 0x02, 0xcf, 0xe0, 0x1e, - 0xf8, 0xed, 0xe6, 0x3d, 0x70, 0x3e, 0x7f, 0x51, 0xe7, 0x5c, 0x00, 0xff, 0xdc, 0x82, 0x19, 0x8e, - 0x90, 0x3c, 0x44, 0x7e, 0xa4, 0xf3, 0x30, 0x48, 0xba, 0x3c, 0x95, 0x9f, 0x3c, 0xfb, 0xa3, 0x8c, - 0xc9, 0x1a, 0xea, 0x39, 0x59, 0x4d, 0xb9, 0x81, 0x4e, 0x90, 0x06, 0xf2, 0xc4, 0xc1, 0x74, 0xed, - 0x3f, 0xb1, 0x00, 0xf1, 0x66, 0x8c, 0x73, 0x99, 0x9e, 0x76, 0xac, 0x54, 0xd3, 0x04, 0x25, 0xac, - 0x46, 0x41, 0xb0, 0x86, 0x75, 0x2a, 0xc3, 0x93, 0x7a, 0x4d, 0x2e, 0xf6, 0x7f, 0x4d, 0x3e, 0xc1, - 0x88, 0x7e, 0x63, 0x08, 0xd2, 0x36, 0xda, 0xe8, 0x2e, 0x4c, 0x34, 0x9c, 0xb6, 0xb3, 0xe5, 0x7a, - 0x6e, 0xec, 0x92, 0xa8, 0x97, 0x19, 0xca, 0x8a, 0x86, 0x27, 0xde, 0x09, 0xb5, 0x12, 0x6c, 0xd0, - 0x41, 0x0b, 0x00, 0xed, 0xd0, 0xdd, 0x77, 0x3d, 0xd2, 0x62, 0x57, 0x61, 0xe6, 0xd8, 0xc5, 0x6d, - 0x2b, 0x64, 0x29, 0xd6, 0x30, 0x32, 0x1c, 0x81, 0x8a, 0x8f, 0xce, 0x11, 0x68, 0xe8, 0x84, 0x8e, - 0x40, 0xc3, 0x03, 0x39, 0x02, 0x61, 0x78, 0x4c, 0x9e, 0xdd, 0xf4, 0xff, 0x9a, 0xeb, 0x11, 0x21, - 0xb0, 0x71, 0x77, 0xaf, 0xf9, 0xa3, 0xc3, 0xf2, 0x63, 0x38, 0x13, 0x03, 0xe7, 0xd4, 0x44, 0x5f, - 0x84, 0x39, 0xc7, 0xf3, 0x82, 0xfb, 0x6a, 0xd4, 0x56, 0xa3, 0x86, 0xe3, 0x25, 0xb1, 0xe5, 0xc7, - 0x96, 0x9f, 0x3c, 0x3a, 0x2c, 0xcf, 0x2d, 0xe5, 0xe0, 0xe0, 0xdc, 0xda, 0x29, 0x3f, 0xa2, 0xb1, - 0xbe, 0x7e, 0x44, 0xbb, 0x70, 0xae, 0x4e, 0x42, 0x99, 0x89, 0x56, 0x6d, 0xc9, 0x4d, 0x28, 0x85, - 0x29, 0x26, 0x34, 0x50, 0x0c, 0x18, 0x2d, 0x4e, 0xa8, 0x64, 0x3a, 0x09, 0x21, 0xfb, 0xcf, 0x2c, - 0x18, 0x15, 0x76, 0xe2, 0x67, 0x20, 0xfb, 0x2c, 0x19, 0xfa, 0xcb, 0x72, 0x36, 0xa3, 0x66, 0x9d, - 0xc9, 0xd5, 0x5c, 0x56, 0x53, 0x9a, 0xcb, 0xa7, 0x7b, 0x11, 0xe9, 0xad, 0xb3, 0xfc, 0xb1, 0x22, - 0x4c, 0x99, 0x36, 0xf2, 0x67, 0x30, 0x04, 0x1b, 0x30, 0x1a, 0x09, 0x87, 0x8c, 0x42, 0xbe, 0xe1, - 0x6c, 0x7a, 0x12, 0x13, 0xab, 0x18, 0xe1, 0x82, 0x21, 0x89, 0x64, 0x7a, 0x7a, 0x14, 0x1f, 0xa1, - 0xa7, 0x47, 0x3f, 0x37, 0x85, 0xa1, 0xd3, 0x70, 0x53, 0xb0, 0x7f, 0x95, 0x1d, 0x16, 0x7a, 0xf9, - 0x19, 0xc8, 0x11, 0xd7, 0xcd, 0x63, 0xc5, 0xee, 0xb1, 0xb2, 0x44, 0xa7, 0x72, 0xe4, 0x89, 0x7f, - 0x66, 0xc1, 0xb8, 0x40, 0x3c, 0x83, 0x6e, 0x7f, 0x87, 0xd9, 0xed, 0x27, 0x7a, 0x74, 0x3b, 0xa7, - 0xbf, 0xff, 0xa0, 0xa0, 0xfa, 0x5b, 0x0b, 0xc2, 0x78, 0xa0, 0xdc, 0x24, 0x63, 0xf4, 0xf6, 0x18, - 0x34, 0x02, 0x4f, 0x1c, 0xfe, 0x4f, 0x26, 0x1e, 0xc2, 0xbc, 0xfc, 0x58, 0xfb, 0x8d, 0x15, 0x36, - 0x73, 0x60, 0x0d, 0xc2, 0x58, 0x1c, 0xb8, 0x89, 0x03, 0x6b, 0x10, 0xc6, 0x98, 0x41, 0x50, 0x13, - 0x20, 0x76, 0xc2, 0x16, 0x89, 0x69, 0x99, 0x08, 0x36, 0x90, 0xbf, 0x0b, 0x3b, 0xb1, 0xeb, 0x2d, - 0xb8, 0x7e, 0x1c, 0xc5, 0xe1, 0x42, 0xd5, 0x8f, 0x6f, 0x87, 0xfc, 0x2e, 0xa1, 0xb9, 0xfc, 0x2a, - 0x5a, 0x58, 0xa3, 0x2b, 0x7d, 0xc8, 0x58, 0x1b, 0xc3, 0xe6, 0xc3, 0xe2, 0x86, 0x28, 0xc7, 0x0a, - 0xc3, 0x7e, 0x8d, 0xf1, 0x64, 0x36, 0x40, 0x27, 0xf3, 0xc6, 0xfd, 0xed, 0x31, 0x35, 0xb4, 0xec, - 0x55, 0xa1, 0xa2, 0xfb, 0xfc, 0xf6, 0x66, 0x81, 0xb4, 0x61, 0xdd, 0x1f, 0x21, 0x71, 0x0c, 0x46, - 0xdf, 0xd9, 0xf5, 0xde, 0xfc, 0x62, 0x1f, 0x5e, 0x7a, 0x82, 0x17, 0x66, 0x16, 0xe0, 0x96, 0x05, - 0x02, 0xad, 0xd6, 0xd2, 0xd9, 0x63, 0x56, 0x24, 0x00, 0x27, 0x38, 0x68, 0x51, 0xdc, 0x44, 0xb9, - 0x3e, 0xef, 0x89, 0xd4, 0x4d, 0x54, 0x7e, 0xbe, 0x76, 0x15, 0x7d, 0x09, 0xc6, 0x55, 0x46, 0xbe, - 0x1a, 0x4f, 0x6c, 0x26, 0x42, 0x2f, 0xac, 0x26, 0xc5, 0x58, 0xc7, 0x41, 0x9b, 0x30, 0x1d, 0xf1, - 0x74, 0x81, 0x2a, 0xc2, 0x16, 0xd7, 0x33, 0x3c, 0x27, 0xdf, 0xa9, 0xeb, 0x26, 0xf8, 0x98, 0x15, - 0xf1, 0xcd, 0x2a, 0x1d, 0xc1, 0xd2, 0x24, 0xd0, 0x9b, 0x30, 0xe5, 0xe9, 0x69, 0xd3, 0x6b, 0x42, - 0x0d, 0xa1, 0xcc, 0x38, 0x8d, 0xa4, 0xea, 0x35, 0x9c, 0xc2, 0xa6, 0x42, 0x83, 0x5e, 0x22, 0xa2, - 0xc2, 0x39, 0x7e, 0x8b, 0x44, 0x22, 0x9f, 0x18, 0x13, 0x1a, 0x6e, 0xe5, 0xe0, 0xe0, 0xdc, 0xda, - 0xe8, 0x75, 0x98, 0x90, 0x9f, 0xaf, 0xb9, 0x39, 0x26, 0xc6, 0xc2, 0x1a, 0x0c, 0x1b, 0x98, 0xe8, - 0x3e, 0x5c, 0x90, 0xff, 0x37, 0x43, 0x67, 0x7b, 0xdb, 0x6d, 0x08, 0x2f, 0x53, 0xee, 0x31, 0xb1, - 0x24, 0x5d, 0x30, 0x56, 0xb3, 0x90, 0x8e, 0x0f, 0xcb, 0x97, 0xc5, 0xa8, 0x65, 0xc2, 0xd9, 0x24, - 0x66, 0xd3, 0x47, 0xeb, 0x70, 0x6e, 0x87, 0x38, 0x5e, 0xbc, 0xb3, 0xb2, 0x43, 0x1a, 0xbb, 0x72, - 0x13, 0x31, 0xe7, 0x49, 0xcd, 0xc4, 0xf6, 0x46, 0x37, 0x0a, 0xce, 0xaa, 0x87, 0xde, 0x85, 0xb9, - 0x76, 0x67, 0xcb, 0x73, 0xa3, 0x9d, 0x8d, 0x20, 0x66, 0x4f, 0xe3, 0x2a, 0xa1, 0x9d, 0xf0, 0xb2, - 0x54, 0x8e, 0xa3, 0xb5, 0x1c, 0x3c, 0x9c, 0x4b, 0x01, 0x7d, 0x00, 0x17, 0x52, 0x8b, 0x41, 0xf8, - 0x7c, 0x4d, 0xe5, 0xc7, 0xd8, 0xac, 0x67, 0x55, 0x10, 0x3e, 0x5c, 0x59, 0x20, 0x9c, 0xdd, 0xc4, - 0x87, 0x33, 0x98, 0x78, 0x9f, 0x56, 0xd6, 0xa4, 0x1b, 0xf4, 0x15, 0x98, 0xd0, 0x57, 0x91, 0x38, - 0x60, 0xae, 0x64, 0x1f, 0xfe, 0xda, 0x6a, 0xe3, 0xb2, 0x91, 0x5a, 0x51, 0x3a, 0x0c, 0x1b, 0x14, - 0x6d, 0x02, 0xd9, 0xdf, 0x87, 0x6e, 0xc1, 0x58, 0xc3, 0x73, 0x89, 0x1f, 0x57, 0x6b, 0xbd, 0xa2, - 0x09, 0xac, 0x08, 0x1c, 0x31, 0x60, 0x22, 0x28, 0x21, 0x2f, 0xc3, 0x8a, 0x82, 0xfd, 0xeb, 0x05, - 0x28, 0xf7, 0x89, 0x70, 0x99, 0xd2, 0x19, 0x5a, 0x03, 0xe9, 0x0c, 0x97, 0x64, 0x7a, 0xbe, 0x8d, - 0xd4, 0x7d, 0x35, 0x95, 0x7a, 0x2f, 0xb9, 0xb5, 0xa6, 0xf1, 0x07, 0xb6, 0xb3, 0xd4, 0xd5, 0x8e, - 0x43, 0x7d, 0x2d, 0x80, 0x8d, 0xe7, 0x86, 0xe1, 0xc1, 0x25, 0xfa, 0x5c, 0xd5, 0xb1, 0xfd, 0xab, - 0x05, 0xb8, 0xa0, 0x86, 0xf0, 0xaf, 0xee, 0xc0, 0xdd, 0xe9, 0x1e, 0xb8, 0x53, 0x50, 0xbc, 0xdb, - 0xb7, 0x61, 0xa4, 0x7e, 0x10, 0x35, 0x62, 0x6f, 0x00, 0x01, 0xe8, 0x19, 0x33, 0xaa, 0x8e, 0x3a, - 0xa6, 0x8d, 0xc8, 0x3a, 0x7f, 0xd3, 0x82, 0xe9, 0xcd, 0x95, 0x5a, 0x3d, 0x68, 0xec, 0x92, 0x78, - 0x89, 0xab, 0x95, 0xb0, 0x90, 0x7f, 0xac, 0x87, 0x94, 0x6b, 0xb2, 0x24, 0xa6, 0xcb, 0x30, 0xb4, - 0x13, 0x44, 0x71, 0xfa, 0x55, 0xee, 0x46, 0x10, 0xc5, 0x98, 0x41, 0xec, 0xdf, 0xb7, 0x60, 0x98, - 0x25, 0x95, 0xed, 0x97, 0x7c, 0x78, 0x90, 0xef, 0x42, 0xaf, 0xc2, 0x08, 0xd9, 0xde, 0x26, 0x8d, - 0x58, 0xcc, 0xaa, 0x74, 0xeb, 0x1b, 0x59, 0x65, 0xa5, 0xf4, 0xd0, 0x67, 0x8d, 0xf1, 0xbf, 0x58, - 0x20, 0xa3, 0x7b, 0x50, 0x8a, 0xdd, 0x3d, 0xb2, 0xd4, 0x6c, 0x8a, 0x77, 0x8d, 0x87, 0xf0, 0xa2, - 0xdc, 0x94, 0x04, 0x70, 0x42, 0xcb, 0xfe, 0x5a, 0x01, 0x20, 0x71, 0x4d, 0xee, 0xf7, 0x89, 0xcb, - 0x5d, 0xf9, 0x95, 0xaf, 0x64, 0xe4, 0x57, 0x46, 0x09, 0xc1, 0x8c, 0xec, 0xca, 0x6a, 0x98, 0x8a, - 0x03, 0x0d, 0xd3, 0xd0, 0x49, 0x86, 0x69, 0x05, 0x66, 0x13, 0xd7, 0x6a, 0x33, 0xce, 0x04, 0x8b, - 0x78, 0xbf, 0x99, 0x06, 0xe2, 0x6e, 0x7c, 0xfb, 0x07, 0x2c, 0x10, 0xee, 0x09, 0x03, 0x2c, 0xe6, - 0x77, 0x64, 0x2a, 0x54, 0x23, 0x50, 0xee, 0xe5, 0x7c, 0x7f, 0x0d, 0x11, 0x1e, 0x57, 0x1d, 0x1e, - 0x46, 0x50, 0x5c, 0x83, 0x96, 0xdd, 0x04, 0x01, 0xad, 0x10, 0xa6, 0x64, 0xe8, 0xdf, 0x9b, 0x6b, - 0x00, 0x4d, 0x86, 0xab, 0xa5, 0x56, 0x54, 0xac, 0xaa, 0xa2, 0x20, 0x58, 0xc3, 0xb2, 0x7f, 0xa4, - 0x00, 0xe3, 0x32, 0x30, 0x2b, 0xbd, 0xc7, 0xf7, 0x6f, 0xe5, 0x44, 0x59, 0x19, 0x58, 0x2e, 0x52, - 0x4a, 0x58, 0x05, 0xef, 0xd7, 0x73, 0x91, 0x4a, 0x00, 0x4e, 0x70, 0xd0, 0xb3, 0x30, 0x1a, 0x75, - 0xb6, 0x18, 0x7a, 0xca, 0xe8, 0xbe, 0xce, 0x8b, 0xb1, 0x84, 0xa3, 0x2f, 0xc2, 0x0c, 0xaf, 0x17, - 0x06, 0x6d, 0xa7, 0xc5, 0x35, 0x4e, 0xc3, 0xca, 0x0b, 0x6e, 0x66, 0x3d, 0x05, 0x3b, 0x3e, 0x2c, - 0x9f, 0x4f, 0x97, 0x31, 0x5d, 0x65, 0x17, 0x15, 0xfb, 0x2b, 0x80, 0xba, 0x63, 0xcd, 0xa2, 0xb7, - 0xb8, 0x59, 0x85, 0x1b, 0x92, 0x66, 0x2f, 0x25, 0xa4, 0xee, 0xb4, 0x25, 0x0d, 0x5f, 0x79, 0x2d, - 0xac, 0xea, 0xd3, 0x9d, 0x37, 0x93, 0x76, 0xe1, 0x41, 0x37, 0x60, 0x84, 0x33, 0x55, 0x41, 0xbe, - 0xc7, 0x1b, 0x97, 0xe6, 0xf8, 0xc3, 0x02, 0xe1, 0x0b, 0xbe, 0x2c, 0xea, 0xa3, 0x77, 0x61, 0xbc, - 0x19, 0xdc, 0xf7, 0xef, 0x3b, 0x61, 0x73, 0xa9, 0x56, 0x15, 0xeb, 0x32, 0x53, 0x36, 0xab, 0x24, - 0x68, 0xba, 0x33, 0x11, 0xd3, 0xe7, 0x26, 0x20, 0xac, 0x93, 0x43, 0x9b, 0x2c, 0x7e, 0xd6, 0xb6, - 0xdb, 0x5a, 0x77, 0xda, 0xbd, 0xec, 0xe0, 0x56, 0x24, 0x92, 0x46, 0x79, 0x52, 0x04, 0xd9, 0xe2, - 0x00, 0x9c, 0x10, 0xb2, 0xbf, 0x7a, 0x0e, 0x8c, 0xfd, 0x60, 0xe4, 0x7d, 0xb0, 0x4e, 0x29, 0xef, - 0x03, 0x86, 0x31, 0xb2, 0xd7, 0x8e, 0x0f, 0x2a, 0x6e, 0xd8, 0x2b, 0x71, 0xd0, 0xaa, 0xc0, 0xe9, - 0xa6, 0x29, 0x21, 0x58, 0xd1, 0xc9, 0x4e, 0xce, 0x51, 0xfc, 0x08, 0x93, 0x73, 0x0c, 0x9d, 0x61, - 0x72, 0x8e, 0x0d, 0x18, 0x6d, 0xb9, 0x31, 0x26, 0xed, 0x40, 0x08, 0x14, 0x99, 0x2b, 0xe1, 0x3a, - 0x47, 0xe9, 0x0e, 0x0d, 0x2f, 0x00, 0x58, 0x12, 0x41, 0x6f, 0xa9, 0x3d, 0x30, 0x92, 0x2f, 0x8f, - 0x77, 0x3f, 0x87, 0x64, 0xee, 0x02, 0x91, 0x8c, 0x63, 0xf4, 0x61, 0x93, 0x71, 0xac, 0xc9, 0x14, - 0x1a, 0x63, 0xf9, 0x66, 0xa3, 0x2c, 0x43, 0x46, 0x9f, 0xc4, 0x19, 0x46, 0xb2, 0x91, 0xd2, 0xe9, - 0x25, 0x1b, 0xf9, 0x01, 0x0b, 0x2e, 0xb4, 0xb3, 0xf2, 0xee, 0x88, 0x14, 0x18, 0xaf, 0x0e, 0x9c, - 0x58, 0xc8, 0x68, 0x90, 0x5d, 0xcc, 0x32, 0xd1, 0x70, 0x76, 0x73, 0x74, 0xa0, 0xc3, 0xad, 0xa6, - 0xc8, 0x9b, 0xf1, 0x4c, 0x4e, 0xd6, 0x92, 0x1e, 0xb9, 0x4a, 0x36, 0x33, 0x72, 0x65, 0x7c, 0x32, - 0x2f, 0x57, 0xc6, 0xc0, 0x19, 0x32, 0x92, 0x7c, 0x25, 0x93, 0x1f, 0x3a, 0x5f, 0xc9, 0x5b, 0x2a, - 0x5f, 0x49, 0x8f, 0xa8, 0x43, 0x3c, 0x1b, 0x49, 0xdf, 0x2c, 0x25, 0x5a, 0xa6, 0x91, 0xe9, 0xd3, - 0xc9, 0x34, 0x62, 0x30, 0x7b, 0x9e, 0xec, 0xe2, 0xf9, 0x3e, 0xcc, 0xde, 0xa0, 0xdb, 0x9b, 0xdd, - 0xf3, 0xac, 0x2a, 0xb3, 0x0f, 0x95, 0x55, 0xe5, 0xae, 0x9e, 0xa5, 0x04, 0xf5, 0x49, 0xc3, 0x41, - 0x91, 0x06, 0xcc, 0x4d, 0x72, 0x57, 0x3f, 0x82, 0xce, 0xe5, 0xd3, 0x55, 0x27, 0x4d, 0x37, 0xdd, - 0xac, 0x43, 0xa8, 0x3b, 0xe7, 0xc9, 0xf9, 0xb3, 0xc9, 0x79, 0x72, 0xe1, 0xd4, 0x73, 0x9e, 0x3c, - 0x76, 0x06, 0x39, 0x4f, 0x1e, 0xff, 0x48, 0x73, 0x9e, 0xcc, 0x3d, 0x82, 0x9c, 0x27, 0x1b, 0x49, - 0xce, 0x93, 0x8b, 0xf9, 0x53, 0x92, 0x61, 0x27, 0x97, 0x93, 0xe9, 0xe4, 0x2e, 0x94, 0xda, 0xd2, - 0xcb, 0x5b, 0x84, 0x45, 0xca, 0x4e, 0xb6, 0x98, 0xe5, 0x0a, 0xce, 0xa7, 0x44, 0x81, 0x70, 0x42, - 0x8a, 0xd2, 0x4d, 0x32, 0x9f, 0x3c, 0xd1, 0x43, 0xf5, 0x96, 0xa5, 0xd4, 0xc8, 0xcf, 0x77, 0x62, - 0xff, 0xad, 0x02, 0x5c, 0xea, 0xbd, 0xae, 0x13, 0x8d, 0x48, 0x2d, 0xd1, 0xe0, 0xa7, 0x34, 0x22, - 0xfc, 0x9a, 0x91, 0x60, 0x0d, 0x1c, 0x0a, 0xe3, 0x3a, 0xcc, 0x2a, 0x03, 0x39, 0xcf, 0x6d, 0x1c, - 0x68, 0x49, 0x18, 0x95, 0xb3, 0x4e, 0x3d, 0x8d, 0x80, 0xbb, 0xeb, 0xa0, 0x25, 0x98, 0x36, 0x0a, - 0xab, 0x15, 0x71, 0x9d, 0x50, 0x2a, 0x98, 0xba, 0x09, 0xc6, 0x69, 0x7c, 0xfb, 0xeb, 0x16, 0x3c, - 0x9e, 0x13, 0x0e, 0x7c, 0xe0, 0x48, 0x0f, 0xdb, 0x30, 0xdd, 0x36, 0xab, 0xf6, 0x09, 0x08, 0x63, - 0x04, 0x1d, 0x57, 0x7d, 0x4d, 0x01, 0x70, 0x9a, 0xe8, 0xf2, 0xd5, 0xdf, 0xfc, 0xc3, 0x4b, 0x9f, - 0xf8, 0x9d, 0x3f, 0xbc, 0xf4, 0x89, 0xdf, 0xfb, 0xc3, 0x4b, 0x9f, 0xf8, 0xeb, 0x47, 0x97, 0xac, - 0xdf, 0x3c, 0xba, 0x64, 0xfd, 0xce, 0xd1, 0x25, 0xeb, 0xf7, 0x8e, 0x2e, 0x59, 0x7f, 0x70, 0x74, - 0xc9, 0xfa, 0xda, 0x1f, 0x5d, 0xfa, 0xc4, 0x3b, 0x85, 0xfd, 0x97, 0xfe, 0x7f, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0x93, 0x27, 0x7c, 0x56, 0xe4, 0x00, 0x00, + // 12669 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6b, 0x6c, 0x24, 0x57, + 0x76, 0x18, 0xbc, 0xd5, 0xdd, 0x7c, 0xf4, 0xe1, 0xfb, 0xce, 0x43, 0x1c, 0x4a, 0x33, 0x3d, 0x2a, + 0xed, 0x8e, 0x46, 0x2b, 0x89, 0xb3, 0x1a, 0x49, 0x2b, 0x79, 0xb5, 0x2b, 0x9b, 0x64, 0x93, 0x33, + 0xd4, 0x0c, 0x39, 0xad, 0xdb, 0x9c, 0xd1, 0xae, 0xac, 0x5d, 0x6f, 0xb1, 0xfb, 0xb2, 0x59, 0x62, + 0xb1, 0xaa, 0x55, 0x55, 0xcd, 0x19, 0xea, 0xb3, 0x81, 0x2f, 0xeb, 0xd8, 0x89, 0x1f, 0x08, 0x16, + 0xb1, 0x91, 0x87, 0x6d, 0x38, 0x80, 0xe3, 0xc0, 0x76, 0x9c, 0x04, 0x71, 0xec, 0xd8, 0xce, 0xae, + 0x9d, 0x38, 0x4e, 0x7e, 0x38, 0x7f, 0x36, 0x4e, 0x80, 0x60, 0x0d, 0x18, 0x61, 0x6c, 0xda, 0x49, + 0xe0, 0x1f, 0x79, 0x20, 0xce, 0x1f, 0x33, 0x46, 0x1c, 0xdc, 0x67, 0xdd, 0x5b, 0x5d, 0xd5, 0xdd, + 0x1c, 0x71, 0x28, 0xd9, 0xd8, 0x7f, 0xdd, 0xf7, 0x9c, 0x7b, 0xee, 0xad, 0xfb, 0x3c, 0xe7, 0xdc, + 0xf3, 0x80, 0xd7, 0x76, 0x5e, 0x8d, 0xe6, 0xdd, 0xe0, 0xda, 0x4e, 0x67, 0x93, 0x84, 0x3e, 0x89, + 0x49, 0x74, 0x6d, 0x8f, 0xf8, 0xcd, 0x20, 0xbc, 0x26, 0x00, 0x4e, 0xdb, 0xbd, 0xd6, 0x08, 0x42, + 0x72, 0x6d, 0xef, 0x85, 0x6b, 0x2d, 0xe2, 0x93, 0xd0, 0x89, 0x49, 0x73, 0xbe, 0x1d, 0x06, 0x71, + 0x80, 0x10, 0xc7, 0x99, 0x77, 0xda, 0xee, 0x3c, 0xc5, 0x99, 0xdf, 0x7b, 0x61, 0xee, 0xf9, 0x96, + 0x1b, 0x6f, 0x77, 0x36, 0xe7, 0x1b, 0xc1, 0xee, 0xb5, 0x56, 0xd0, 0x0a, 0xae, 0x31, 0xd4, 0xcd, + 0xce, 0x16, 0xfb, 0xc7, 0xfe, 0xb0, 0x5f, 0x9c, 0xc4, 0xdc, 0x4b, 0x49, 0x33, 0xbb, 0x4e, 0x63, + 0xdb, 0xf5, 0x49, 0xb8, 0x7f, 0xad, 0xbd, 0xd3, 0x62, 0xed, 0x86, 0x24, 0x0a, 0x3a, 0x61, 0x83, + 0xa4, 0x1b, 0xee, 0x59, 0x2b, 0xba, 0xb6, 0x4b, 0x62, 0x27, 0xa3, 0xbb, 0x73, 0xd7, 0xf2, 0x6a, + 0x85, 0x1d, 0x3f, 0x76, 0x77, 0xbb, 0x9b, 0xf9, 0x74, 0xbf, 0x0a, 0x51, 0x63, 0x9b, 0xec, 0x3a, + 0x5d, 0xf5, 0x5e, 0xcc, 0xab, 0xd7, 0x89, 0x5d, 0xef, 0x9a, 0xeb, 0xc7, 0x51, 0x1c, 0xa6, 0x2b, + 0xd9, 0xdf, 0xb4, 0xe0, 0xf2, 0xc2, 0x5b, 0xf5, 0x65, 0xcf, 0x89, 0x62, 0xb7, 0xb1, 0xe8, 0x05, + 0x8d, 0x9d, 0x7a, 0x1c, 0x84, 0xe4, 0x5e, 0xe0, 0x75, 0x76, 0x49, 0x9d, 0x0d, 0x04, 0x7a, 0x0e, + 0x46, 0xf7, 0xd8, 0xff, 0xd5, 0xea, 0xac, 0x75, 0xd9, 0xba, 0x5a, 0x5e, 0x9c, 0xfe, 0xad, 0x83, + 0xca, 0xc7, 0x0e, 0x0f, 0x2a, 0xa3, 0xf7, 0x44, 0x39, 0x56, 0x18, 0xe8, 0x0a, 0x0c, 0x6f, 0x45, + 0x1b, 0xfb, 0x6d, 0x32, 0x5b, 0x60, 0xb8, 0x93, 0x02, 0x77, 0x78, 0xa5, 0x4e, 0x4b, 0xb1, 0x80, + 0xa2, 0x6b, 0x50, 0x6e, 0x3b, 0x61, 0xec, 0xc6, 0x6e, 0xe0, 0xcf, 0x16, 0x2f, 0x5b, 0x57, 0x87, + 0x16, 0x67, 0x04, 0x6a, 0xb9, 0x26, 0x01, 0x38, 0xc1, 0xa1, 0xdd, 0x08, 0x89, 0xd3, 0xbc, 0xe3, + 0x7b, 0xfb, 0xb3, 0xa5, 0xcb, 0xd6, 0xd5, 0xd1, 0xa4, 0x1b, 0x58, 0x94, 0x63, 0x85, 0x61, 0xff, + 0x58, 0x01, 0x46, 0x17, 0xb6, 0xb6, 0x5c, 0xdf, 0x8d, 0xf7, 0xd1, 0x3d, 0x18, 0xf7, 0x83, 0x26, + 0x91, 0xff, 0xd9, 0x57, 0x8c, 0x5d, 0xbf, 0x3c, 0xdf, 0xbd, 0x94, 0xe6, 0xd7, 0x35, 0xbc, 0xc5, + 0xe9, 0xc3, 0x83, 0xca, 0xb8, 0x5e, 0x82, 0x0d, 0x3a, 0x08, 0xc3, 0x58, 0x3b, 0x68, 0x2a, 0xb2, + 0x05, 0x46, 0xb6, 0x92, 0x45, 0xb6, 0x96, 0xa0, 0x2d, 0x4e, 0x1d, 0x1e, 0x54, 0xc6, 0xb4, 0x02, + 0xac, 0x13, 0x41, 0x9b, 0x30, 0x45, 0xff, 0xfa, 0xb1, 0xab, 0xe8, 0x16, 0x19, 0xdd, 0xa7, 0xf2, + 0xe8, 0x6a, 0xa8, 0x8b, 0x67, 0x0e, 0x0f, 0x2a, 0x53, 0xa9, 0x42, 0x9c, 0x26, 0x68, 0xbf, 0x0f, + 0x93, 0x0b, 0x71, 0xec, 0x34, 0xb6, 0x49, 0x93, 0xcf, 0x20, 0x7a, 0x09, 0x4a, 0xbe, 0xb3, 0x4b, + 0xc4, 0xfc, 0x5e, 0x16, 0x03, 0x5b, 0x5a, 0x77, 0x76, 0xc9, 0xd1, 0x41, 0x65, 0xfa, 0xae, 0xef, + 0xbe, 0xd7, 0x11, 0xab, 0x82, 0x96, 0x61, 0x86, 0x8d, 0xae, 0x03, 0x34, 0xc9, 0x9e, 0xdb, 0x20, + 0x35, 0x27, 0xde, 0x16, 0xf3, 0x8d, 0x44, 0x5d, 0xa8, 0x2a, 0x08, 0xd6, 0xb0, 0xec, 0x07, 0x50, + 0x5e, 0xd8, 0x0b, 0xdc, 0x66, 0x2d, 0x68, 0x46, 0x68, 0x07, 0xa6, 0xda, 0x21, 0xd9, 0x22, 0xa1, + 0x2a, 0x9a, 0xb5, 0x2e, 0x17, 0xaf, 0x8e, 0x5d, 0xbf, 0x9a, 0xf9, 0xb1, 0x26, 0xea, 0xb2, 0x1f, + 0x87, 0xfb, 0x8b, 0x8f, 0x89, 0xf6, 0xa6, 0x52, 0x50, 0x9c, 0xa6, 0x6c, 0xff, 0xeb, 0x02, 0x9c, + 0x5b, 0x78, 0xbf, 0x13, 0x92, 0xaa, 0x1b, 0xed, 0xa4, 0x57, 0x78, 0xd3, 0x8d, 0x76, 0xd6, 0x93, + 0x11, 0x50, 0x4b, 0xab, 0x2a, 0xca, 0xb1, 0xc2, 0x40, 0xcf, 0xc3, 0x08, 0xfd, 0x7d, 0x17, 0xaf, + 0x8a, 0x4f, 0x3e, 0x23, 0x90, 0xc7, 0xaa, 0x4e, 0xec, 0x54, 0x39, 0x08, 0x4b, 0x1c, 0xb4, 0x06, + 0x63, 0x0d, 0xb6, 0x21, 0x5b, 0x6b, 0x41, 0x93, 0xb0, 0xc9, 0x2c, 0x2f, 0x3e, 0x4b, 0xd1, 0x97, + 0x92, 0xe2, 0xa3, 0x83, 0xca, 0x2c, 0xef, 0x9b, 0x20, 0xa1, 0xc1, 0xb0, 0x5e, 0x1f, 0xd9, 0x6a, + 0x7f, 0x95, 0x18, 0x25, 0xc8, 0xd8, 0x5b, 0x57, 0xb5, 0xad, 0x32, 0xc4, 0xb6, 0xca, 0x78, 0xf6, + 0x36, 0x41, 0x2f, 0x40, 0x69, 0xc7, 0xf5, 0x9b, 0xb3, 0xc3, 0x8c, 0xd6, 0x45, 0x3a, 0xe7, 0xb7, + 0x5c, 0xbf, 0x79, 0x74, 0x50, 0x99, 0x31, 0xba, 0x43, 0x0b, 0x31, 0x43, 0xb5, 0xff, 0xd8, 0x82, + 0x0a, 0x83, 0xad, 0xb8, 0x1e, 0xa9, 0x91, 0x30, 0x72, 0xa3, 0x98, 0xf8, 0xb1, 0x31, 0xa0, 0xd7, + 0x01, 0x22, 0xd2, 0x08, 0x49, 0xac, 0x0d, 0xa9, 0x5a, 0x18, 0x75, 0x05, 0xc1, 0x1a, 0x16, 0x3d, + 0x10, 0xa2, 0x6d, 0x27, 0x64, 0xeb, 0x4b, 0x0c, 0xac, 0x3a, 0x10, 0xea, 0x12, 0x80, 0x13, 0x1c, + 0xe3, 0x40, 0x28, 0xf6, 0x3b, 0x10, 0xd0, 0xe7, 0x60, 0x2a, 0x69, 0x2c, 0x6a, 0x3b, 0x0d, 0x39, + 0x80, 0x6c, 0xcb, 0xd4, 0x4d, 0x10, 0x4e, 0xe3, 0xda, 0x7f, 0xdf, 0x12, 0x8b, 0x87, 0x7e, 0xf5, + 0x47, 0xfc, 0x5b, 0xed, 0x5f, 0xb5, 0x60, 0x64, 0xd1, 0xf5, 0x9b, 0xae, 0xdf, 0x42, 0x5f, 0x86, + 0x51, 0x7a, 0x37, 0x35, 0x9d, 0xd8, 0x11, 0xe7, 0xde, 0xa7, 0xb4, 0xbd, 0xa5, 0xae, 0x8a, 0xf9, + 0xf6, 0x4e, 0x8b, 0x16, 0x44, 0xf3, 0x14, 0x9b, 0xee, 0xb6, 0x3b, 0x9b, 0xef, 0x92, 0x46, 0xbc, + 0x46, 0x62, 0x27, 0xf9, 0x9c, 0xa4, 0x0c, 0x2b, 0xaa, 0xe8, 0x16, 0x0c, 0xc7, 0x4e, 0xd8, 0x22, + 0xb1, 0x38, 0x00, 0x33, 0x0f, 0x2a, 0x5e, 0x13, 0xd3, 0x1d, 0x49, 0xfc, 0x06, 0x49, 0xae, 0x85, + 0x0d, 0x56, 0x15, 0x0b, 0x12, 0xf6, 0x0f, 0x0e, 0xc3, 0x85, 0xa5, 0xfa, 0x6a, 0xce, 0xba, 0xba, + 0x02, 0xc3, 0xcd, 0xd0, 0xdd, 0x23, 0xa1, 0x18, 0x67, 0x45, 0xa5, 0xca, 0x4a, 0xb1, 0x80, 0xa2, + 0x57, 0x61, 0x9c, 0x5f, 0x48, 0x37, 0x1d, 0xbf, 0xe9, 0xc9, 0x21, 0x3e, 0x2b, 0xb0, 0xc7, 0xef, + 0x69, 0x30, 0x6c, 0x60, 0x1e, 0x73, 0x51, 0x5d, 0x49, 0x6d, 0xc6, 0xbc, 0xcb, 0xee, 0x07, 0x2c, + 0x98, 0xe6, 0xcd, 0x2c, 0xc4, 0x71, 0xe8, 0x6e, 0x76, 0x62, 0x12, 0xcd, 0x0e, 0xb1, 0x93, 0x6e, + 0x29, 0x6b, 0xb4, 0x72, 0x47, 0x60, 0xfe, 0x5e, 0x8a, 0x0a, 0x3f, 0x04, 0x67, 0x45, 0xbb, 0xd3, + 0x69, 0x30, 0xee, 0x6a, 0x16, 0x7d, 0xaf, 0x05, 0x73, 0x8d, 0xc0, 0x8f, 0xc3, 0xc0, 0xf3, 0x48, + 0x58, 0xeb, 0x6c, 0x7a, 0x6e, 0xb4, 0xcd, 0xd7, 0x29, 0x26, 0x5b, 0xec, 0x24, 0xc8, 0x99, 0x43, + 0x85, 0x24, 0xe6, 0xf0, 0xd2, 0xe1, 0x41, 0x65, 0x6e, 0x29, 0x97, 0x14, 0xee, 0xd1, 0x0c, 0xda, + 0x01, 0x44, 0xaf, 0xd2, 0x7a, 0xec, 0xb4, 0x48, 0xd2, 0xf8, 0xc8, 0xe0, 0x8d, 0x9f, 0x3f, 0x3c, + 0xa8, 0xa0, 0xf5, 0x2e, 0x12, 0x38, 0x83, 0x2c, 0x7a, 0x0f, 0xce, 0xd2, 0xd2, 0xae, 0x6f, 0x1d, + 0x1d, 0xbc, 0xb9, 0xd9, 0xc3, 0x83, 0xca, 0xd9, 0xf5, 0x0c, 0x22, 0x38, 0x93, 0xf4, 0xdc, 0x12, + 0x9c, 0xcb, 0x9c, 0x2a, 0x34, 0x0d, 0xc5, 0x1d, 0xc2, 0x59, 0x90, 0x32, 0xa6, 0x3f, 0xd1, 0x59, + 0x18, 0xda, 0x73, 0xbc, 0x8e, 0x58, 0xa5, 0x98, 0xff, 0xf9, 0x4c, 0xe1, 0x55, 0xcb, 0x6e, 0xc0, + 0xf8, 0x92, 0xd3, 0x76, 0x36, 0x5d, 0xcf, 0x8d, 0x5d, 0x12, 0xa1, 0xa7, 0xa1, 0xe8, 0x34, 0x9b, + 0xec, 0x8a, 0x2c, 0x2f, 0x9e, 0x3b, 0x3c, 0xa8, 0x14, 0x17, 0x9a, 0xf4, 0xac, 0x06, 0x85, 0xb5, + 0x8f, 0x29, 0x06, 0xfa, 0x24, 0x94, 0x9a, 0x61, 0xd0, 0x9e, 0x2d, 0x30, 0x4c, 0x3a, 0x54, 0xa5, + 0x6a, 0x18, 0xb4, 0x53, 0xa8, 0x0c, 0xc7, 0xfe, 0x8d, 0x02, 0x3c, 0xb1, 0x44, 0xda, 0xdb, 0x2b, + 0xf5, 0x9c, 0x4d, 0x77, 0x15, 0x46, 0x77, 0x03, 0xdf, 0x8d, 0x83, 0x30, 0x12, 0x4d, 0xb3, 0xdb, + 0x64, 0x4d, 0x94, 0x61, 0x05, 0x45, 0x97, 0xa1, 0xd4, 0x4e, 0x38, 0x81, 0x71, 0xc9, 0x45, 0x30, + 0x1e, 0x80, 0x41, 0x28, 0x46, 0x27, 0x22, 0xa1, 0xb8, 0x05, 0x15, 0xc6, 0xdd, 0x88, 0x84, 0x98, + 0x41, 0x92, 0xe3, 0x94, 0x1e, 0xb4, 0x62, 0x5b, 0xa5, 0x8e, 0x53, 0x0a, 0xc1, 0x1a, 0x16, 0xaa, + 0x41, 0x39, 0x52, 0x93, 0x3a, 0x34, 0xf8, 0xa4, 0x4e, 0xb0, 0xf3, 0x56, 0xcd, 0x64, 0x42, 0xc4, + 0x38, 0x06, 0x86, 0xfb, 0x9e, 0xb7, 0x5f, 0x2f, 0x00, 0xe2, 0x43, 0xf8, 0xe7, 0x6c, 0xe0, 0xee, + 0x76, 0x0f, 0x5c, 0x26, 0xe7, 0x75, 0x3b, 0x68, 0x38, 0x5e, 0xfa, 0x08, 0x3f, 0xa9, 0xd1, 0xfb, + 0xdf, 0x16, 0x3c, 0xb1, 0xe4, 0xfa, 0x4d, 0x12, 0xe6, 0x2c, 0xc0, 0x47, 0x23, 0x80, 0x1c, 0xef, + 0xa4, 0x37, 0x96, 0x58, 0xe9, 0x04, 0x96, 0x98, 0xfd, 0x3f, 0x2c, 0x40, 0xfc, 0xb3, 0x3f, 0x72, + 0x1f, 0x7b, 0xb7, 0xfb, 0x63, 0x4f, 0x60, 0x59, 0xd8, 0xb7, 0x61, 0x72, 0xc9, 0x73, 0x89, 0x1f, + 0xaf, 0xd6, 0x96, 0x02, 0x7f, 0xcb, 0x6d, 0xa1, 0xcf, 0xc0, 0x24, 0x95, 0x69, 0x83, 0x4e, 0x5c, + 0x27, 0x8d, 0xc0, 0x67, 0xec, 0x3f, 0x95, 0x04, 0xd1, 0xe1, 0x41, 0x65, 0x72, 0xc3, 0x80, 0xe0, + 0x14, 0xa6, 0xfd, 0xbb, 0x74, 0xfc, 0x82, 0xdd, 0x76, 0xe0, 0x13, 0x3f, 0x5e, 0x0a, 0xfc, 0x26, + 0x17, 0x13, 0x3f, 0x03, 0xa5, 0x98, 0x8e, 0x07, 0x1f, 0xbb, 0x2b, 0x72, 0xa3, 0xd0, 0x51, 0x38, + 0x3a, 0xa8, 0x9c, 0xef, 0xae, 0xc1, 0xc6, 0x89, 0xd5, 0x41, 0xdf, 0x06, 0xc3, 0x51, 0xec, 0xc4, + 0x9d, 0x48, 0x8c, 0xe6, 0x93, 0x72, 0x34, 0xeb, 0xac, 0xf4, 0xe8, 0xa0, 0x32, 0xa5, 0xaa, 0xf1, + 0x22, 0x2c, 0x2a, 0xa0, 0x67, 0x60, 0x64, 0x97, 0x44, 0x91, 0xd3, 0x92, 0x1c, 0xfe, 0x94, 0xa8, + 0x3b, 0xb2, 0xc6, 0x8b, 0xb1, 0x84, 0xa3, 0xa7, 0x60, 0x88, 0x84, 0x61, 0x10, 0x8a, 0x3d, 0x3a, + 0x21, 0x10, 0x87, 0x96, 0x69, 0x21, 0xe6, 0x30, 0xfb, 0xdf, 0x5a, 0x30, 0xa5, 0xfa, 0xca, 0xdb, + 0x3a, 0x05, 0x56, 0xee, 0x6d, 0x80, 0x86, 0xfc, 0xc0, 0x88, 0xdd, 0x1e, 0x63, 0xd7, 0xaf, 0x64, + 0x32, 0x28, 0x5d, 0xc3, 0x98, 0x50, 0x56, 0x45, 0x11, 0xd6, 0xa8, 0xd9, 0xbf, 0x6e, 0xc1, 0x99, + 0xd4, 0x17, 0xdd, 0x76, 0xa3, 0x18, 0xbd, 0xd3, 0xf5, 0x55, 0xf3, 0x83, 0x7d, 0x15, 0xad, 0xcd, + 0xbe, 0x49, 0x2d, 0x65, 0x59, 0xa2, 0x7d, 0xd1, 0x4d, 0x18, 0x72, 0x63, 0xb2, 0x2b, 0x3f, 0xe6, + 0xa9, 0x9e, 0x1f, 0xc3, 0x7b, 0x95, 0xcc, 0xc8, 0x2a, 0xad, 0x89, 0x39, 0x01, 0xfb, 0x47, 0x8a, + 0x50, 0xe6, 0xcb, 0x76, 0xcd, 0x69, 0x9f, 0xc2, 0x5c, 0xac, 0x42, 0x89, 0x51, 0xe7, 0x1d, 0x7f, + 0x3a, 0xbb, 0xe3, 0xa2, 0x3b, 0xf3, 0x54, 0x4e, 0xe3, 0xac, 0xa0, 0xba, 0x1a, 0x68, 0x11, 0x66, + 0x24, 0x90, 0x03, 0xb0, 0xe9, 0xfa, 0x4e, 0xb8, 0x4f, 0xcb, 0x66, 0x8b, 0x8c, 0xe0, 0xf3, 0xbd, + 0x09, 0x2e, 0x2a, 0x7c, 0x4e, 0x56, 0xf5, 0x35, 0x01, 0x60, 0x8d, 0xe8, 0xdc, 0x2b, 0x50, 0x56, + 0xc8, 0xc7, 0xe1, 0x71, 0xe6, 0x3e, 0x07, 0x53, 0xa9, 0xb6, 0xfa, 0x55, 0x1f, 0xd7, 0x59, 0xa4, + 0xaf, 0xb1, 0x53, 0x40, 0xf4, 0x7a, 0xd9, 0xdf, 0x13, 0xa7, 0xe8, 0xfb, 0x70, 0xd6, 0xcb, 0x38, + 0x9c, 0xc4, 0x54, 0x0d, 0x7e, 0x98, 0x3d, 0x21, 0x3e, 0xfb, 0x6c, 0x16, 0x14, 0x67, 0xb6, 0x41, + 0xaf, 0xfd, 0xa0, 0x4d, 0xd7, 0xbc, 0xe3, 0xb1, 0xfe, 0x0a, 0xe9, 0xfb, 0x8e, 0x28, 0xc3, 0x0a, + 0x4a, 0x8f, 0xb0, 0xb3, 0xaa, 0xf3, 0xb7, 0xc8, 0x7e, 0x9d, 0x78, 0xa4, 0x11, 0x07, 0xe1, 0x87, + 0xda, 0xfd, 0x8b, 0x7c, 0xf4, 0xf9, 0x09, 0x38, 0x26, 0x08, 0x14, 0x6f, 0x91, 0x7d, 0x3e, 0x15, + 0xfa, 0xd7, 0x15, 0x7b, 0x7e, 0xdd, 0x2f, 0x58, 0x30, 0xa1, 0xbe, 0xee, 0x14, 0xb6, 0xfa, 0xa2, + 0xb9, 0xd5, 0x2f, 0xf6, 0x5c, 0xe0, 0x39, 0x9b, 0xfc, 0xeb, 0x05, 0xb8, 0xa0, 0x70, 0x28, 0xbb, + 0xcf, 0xff, 0x88, 0x55, 0x75, 0x0d, 0xca, 0xbe, 0xd2, 0x1e, 0x58, 0xa6, 0xd8, 0x9e, 0xe8, 0x0e, + 0x12, 0x1c, 0xca, 0xb5, 0xf9, 0x89, 0x88, 0x3f, 0xae, 0xab, 0xd5, 0x84, 0x0a, 0x6d, 0x11, 0x8a, + 0x1d, 0xb7, 0x29, 0xee, 0x8c, 0x4f, 0xc9, 0xd1, 0xbe, 0xbb, 0x5a, 0x3d, 0x3a, 0xa8, 0x3c, 0x99, + 0xa7, 0xd2, 0xa5, 0x97, 0x55, 0x34, 0x7f, 0x77, 0xb5, 0x8a, 0x69, 0x65, 0xb4, 0x00, 0x53, 0x52, + 0x6b, 0x7d, 0x8f, 0x72, 0x50, 0x81, 0x2f, 0xae, 0x16, 0xa5, 0x1b, 0xc3, 0x26, 0x18, 0xa7, 0xf1, + 0x51, 0x15, 0xa6, 0x77, 0x3a, 0x9b, 0xc4, 0x23, 0x31, 0xff, 0xe0, 0x5b, 0x84, 0x6b, 0x8e, 0xca, + 0x89, 0x68, 0x79, 0x2b, 0x05, 0xc7, 0x5d, 0x35, 0xec, 0x3f, 0x63, 0x47, 0xbc, 0x18, 0xbd, 0x5a, + 0x18, 0xd0, 0x85, 0x45, 0xa9, 0x7f, 0x98, 0xcb, 0x79, 0x90, 0x55, 0x71, 0x8b, 0xec, 0x6f, 0x04, + 0x94, 0xd9, 0xce, 0x5e, 0x15, 0xc6, 0x9a, 0x2f, 0xf5, 0x5c, 0xf3, 0xbf, 0x54, 0x80, 0x73, 0x6a, + 0x04, 0x0c, 0xbe, 0xee, 0xcf, 0xfb, 0x18, 0xbc, 0x00, 0x63, 0x4d, 0xb2, 0xe5, 0x74, 0xbc, 0x58, + 0xa9, 0x31, 0x87, 0xb8, 0x2a, 0xbb, 0x9a, 0x14, 0x63, 0x1d, 0xe7, 0x18, 0xc3, 0xf6, 0xd3, 0x63, + 0xec, 0x6e, 0x8d, 0x1d, 0xba, 0xc6, 0xd5, 0xae, 0xb1, 0x72, 0x77, 0xcd, 0x53, 0x30, 0xe4, 0xee, + 0x52, 0x5e, 0xab, 0x60, 0xb2, 0x50, 0xab, 0xb4, 0x10, 0x73, 0x18, 0xfa, 0x04, 0x8c, 0x34, 0x82, + 0xdd, 0x5d, 0xc7, 0x6f, 0xb2, 0x2b, 0xaf, 0xbc, 0x38, 0x46, 0xd9, 0xb1, 0x25, 0x5e, 0x84, 0x25, + 0x0c, 0x3d, 0x01, 0x25, 0x27, 0x6c, 0x45, 0xb3, 0x25, 0x86, 0x33, 0x4a, 0x5b, 0x5a, 0x08, 0x5b, + 0x11, 0x66, 0xa5, 0x54, 0xaa, 0xba, 0x1f, 0x84, 0x3b, 0xae, 0xdf, 0xaa, 0xba, 0xa1, 0xd8, 0x12, + 0xea, 0x2e, 0x7c, 0x4b, 0x41, 0xb0, 0x86, 0x85, 0x56, 0x60, 0xa8, 0x1d, 0x84, 0x71, 0x34, 0x3b, + 0xcc, 0x86, 0xfb, 0xc9, 0x9c, 0x83, 0x88, 0x7f, 0x6d, 0x2d, 0x08, 0xe3, 0xe4, 0x03, 0xe8, 0xbf, + 0x08, 0xf3, 0xea, 0xe8, 0xdb, 0xa0, 0x48, 0xfc, 0xbd, 0xd9, 0x11, 0x46, 0x65, 0x2e, 0x8b, 0xca, + 0xb2, 0xbf, 0x77, 0xcf, 0x09, 0x93, 0x53, 0x7a, 0xd9, 0xdf, 0xc3, 0xb4, 0x0e, 0xfa, 0x02, 0x94, + 0xe5, 0x16, 0x8f, 0x84, 0x9a, 0x23, 0x73, 0x89, 0xc9, 0x83, 0x01, 0x93, 0xf7, 0x3a, 0x6e, 0x48, + 0x76, 0x89, 0x1f, 0x47, 0xc9, 0x99, 0x26, 0xa1, 0x11, 0x4e, 0xa8, 0xa1, 0x2f, 0x48, 0xdd, 0xda, + 0x5a, 0xd0, 0xf1, 0xe3, 0x68, 0xb6, 0xcc, 0xba, 0x97, 0xf9, 0xea, 0x71, 0x2f, 0xc1, 0x4b, 0x2b, + 0xdf, 0x78, 0x65, 0x6c, 0x90, 0x42, 0x18, 0x26, 0x3c, 0x77, 0x8f, 0xf8, 0x24, 0x8a, 0x6a, 0x61, + 0xb0, 0x49, 0x66, 0x81, 0xf5, 0xfc, 0x42, 0xf6, 0x63, 0x40, 0xb0, 0x49, 0x16, 0x67, 0x0e, 0x0f, + 0x2a, 0x13, 0xb7, 0xf5, 0x3a, 0xd8, 0x24, 0x81, 0xee, 0xc2, 0x24, 0x95, 0x6b, 0xdc, 0x84, 0xe8, + 0x58, 0x3f, 0xa2, 0x4c, 0xfa, 0xc0, 0x46, 0x25, 0x9c, 0x22, 0x82, 0xde, 0x80, 0xb2, 0xe7, 0x6e, + 0x91, 0xc6, 0x7e, 0xc3, 0x23, 0xb3, 0xe3, 0x8c, 0x62, 0xe6, 0xb6, 0xba, 0x2d, 0x91, 0xb8, 0x5c, + 0xa4, 0xfe, 0xe2, 0xa4, 0x3a, 0xba, 0x07, 0xe7, 0x63, 0x12, 0xee, 0xba, 0xbe, 0x43, 0xb7, 0x83, + 0x90, 0x17, 0xd8, 0x93, 0xca, 0x04, 0x5b, 0x6f, 0x97, 0xc4, 0xd0, 0x9d, 0xdf, 0xc8, 0xc4, 0xc2, + 0x39, 0xb5, 0xd1, 0x1d, 0x98, 0x62, 0x3b, 0xa1, 0xd6, 0xf1, 0xbc, 0x5a, 0xe0, 0xb9, 0x8d, 0xfd, + 0xd9, 0x49, 0x46, 0xf0, 0x13, 0xf2, 0x5e, 0x58, 0x35, 0xc1, 0x47, 0x07, 0x15, 0x48, 0xfe, 0xe1, + 0x74, 0x6d, 0xb4, 0xc9, 0x74, 0xe8, 0x9d, 0xd0, 0x8d, 0xf7, 0xe9, 0xfa, 0x25, 0x0f, 0xe2, 0xd9, + 0xa9, 0x9e, 0xa2, 0xb0, 0x8e, 0xaa, 0x14, 0xed, 0x7a, 0x21, 0x4e, 0x13, 0xa4, 0x5b, 0x3b, 0x8a, + 0x9b, 0xae, 0x3f, 0x3b, 0xcd, 0x4e, 0x0c, 0xb5, 0x33, 0xea, 0xb4, 0x10, 0x73, 0x18, 0xd3, 0x9f, + 0xd3, 0x1f, 0x77, 0xe8, 0x09, 0x3a, 0xc3, 0x10, 0x13, 0xfd, 0xb9, 0x04, 0xe0, 0x04, 0x87, 0x32, + 0x35, 0x71, 0xbc, 0x3f, 0x8b, 0x18, 0xaa, 0xda, 0x2e, 0x1b, 0x1b, 0x5f, 0xc0, 0xb4, 0x1c, 0xdd, + 0x86, 0x11, 0xe2, 0xef, 0xad, 0x84, 0xc1, 0xee, 0xec, 0x99, 0xfc, 0x3d, 0xbb, 0xcc, 0x51, 0xf8, + 0x81, 0x9e, 0x08, 0x78, 0xa2, 0x18, 0x4b, 0x12, 0xe8, 0x01, 0xcc, 0x66, 0xcc, 0x08, 0x9f, 0x80, + 0xb3, 0x6c, 0x02, 0x3e, 0x2b, 0xea, 0xce, 0x6e, 0xe4, 0xe0, 0x1d, 0xf5, 0x80, 0xe1, 0x5c, 0xea, + 0xe8, 0x8b, 0x30, 0xc1, 0x37, 0x14, 0x7f, 0x7c, 0x8b, 0x66, 0xcf, 0xb1, 0xaf, 0xb9, 0x9c, 0xbf, + 0x39, 0x39, 0xe2, 0xe2, 0x39, 0xd1, 0xa1, 0x09, 0xbd, 0x34, 0xc2, 0x26, 0x35, 0x7b, 0x13, 0x26, + 0xd5, 0xb9, 0xc5, 0x96, 0x0e, 0xaa, 0xc0, 0x10, 0xe3, 0x76, 0x84, 0x7e, 0xab, 0x4c, 0x67, 0x8a, + 0x71, 0x42, 0x98, 0x97, 0xb3, 0x99, 0x72, 0xdf, 0x27, 0x8b, 0xfb, 0x31, 0xe1, 0x52, 0x75, 0x51, + 0x9b, 0x29, 0x09, 0xc0, 0x09, 0x8e, 0xfd, 0x7f, 0x39, 0xd7, 0x98, 0x1c, 0x8e, 0x03, 0x5c, 0x07, + 0xcf, 0xc1, 0xe8, 0x76, 0x10, 0xc5, 0x14, 0x9b, 0xb5, 0x31, 0x94, 0xf0, 0x89, 0x37, 0x45, 0x39, + 0x56, 0x18, 0xe8, 0x35, 0x98, 0x68, 0xe8, 0x0d, 0x88, 0xbb, 0x4c, 0x0d, 0x81, 0xd1, 0x3a, 0x36, + 0x71, 0xd1, 0xab, 0x30, 0xca, 0x9e, 0xce, 0x1b, 0x81, 0x27, 0x98, 0x2c, 0x79, 0x21, 0x8f, 0xd6, + 0x44, 0xf9, 0x91, 0xf6, 0x1b, 0x2b, 0x6c, 0x74, 0x05, 0x86, 0x69, 0x17, 0x56, 0x6b, 0xe2, 0x16, + 0x51, 0xaa, 0x9a, 0x9b, 0xac, 0x14, 0x0b, 0xa8, 0xfd, 0xd7, 0x0b, 0xda, 0x28, 0x53, 0x89, 0x94, + 0xa0, 0x1a, 0x8c, 0xdc, 0x77, 0xdc, 0xd8, 0xf5, 0x5b, 0x82, 0x5d, 0x78, 0xa6, 0xe7, 0x95, 0xc2, + 0x2a, 0xbd, 0xc5, 0x2b, 0xf0, 0x4b, 0x4f, 0xfc, 0xc1, 0x92, 0x0c, 0xa5, 0x18, 0x76, 0x7c, 0x9f, + 0x52, 0x2c, 0x0c, 0x4a, 0x11, 0xf3, 0x0a, 0x9c, 0xa2, 0xf8, 0x83, 0x25, 0x19, 0xf4, 0x0e, 0x80, + 0x5c, 0x96, 0xa4, 0x29, 0x9e, 0xac, 0x9f, 0xeb, 0x4f, 0x74, 0x43, 0xd5, 0x59, 0x9c, 0xa4, 0x57, + 0x6a, 0xf2, 0x1f, 0x6b, 0xf4, 0xec, 0x98, 0xb1, 0x55, 0xdd, 0x9d, 0x41, 0xdf, 0x49, 0x4f, 0x02, + 0x27, 0x8c, 0x49, 0x73, 0x21, 0x16, 0x83, 0xf3, 0xc9, 0xc1, 0x64, 0x8a, 0x0d, 0x77, 0x97, 0xe8, + 0xa7, 0x86, 0x20, 0x82, 0x13, 0x7a, 0xf6, 0xaf, 0x14, 0x61, 0x36, 0xaf, 0xbb, 0x74, 0xd1, 0x91, + 0x07, 0x6e, 0xbc, 0x44, 0xb9, 0x21, 0xcb, 0x5c, 0x74, 0xcb, 0xa2, 0x1c, 0x2b, 0x0c, 0x3a, 0xfb, + 0x91, 0xdb, 0x92, 0x22, 0xe1, 0x50, 0x32, 0xfb, 0x75, 0x56, 0x8a, 0x05, 0x94, 0xe2, 0x85, 0xc4, + 0x89, 0x84, 0x4d, 0x84, 0xb6, 0x4a, 0x30, 0x2b, 0xc5, 0x02, 0xaa, 0xeb, 0x9b, 0x4a, 0x7d, 0xf4, + 0x4d, 0xc6, 0x10, 0x0d, 0x9d, 0xec, 0x10, 0xa1, 0x2f, 0x01, 0x6c, 0xb9, 0xbe, 0x1b, 0x6d, 0x33, + 0xea, 0xc3, 0xc7, 0xa6, 0xae, 0x78, 0xa9, 0x15, 0x45, 0x05, 0x6b, 0x14, 0xd1, 0xcb, 0x30, 0xa6, + 0x36, 0xe0, 0x6a, 0x95, 0x3d, 0x10, 0x69, 0x0f, 0xee, 0xc9, 0x69, 0x54, 0xc5, 0x3a, 0x9e, 0xfd, + 0x6e, 0x7a, 0xbd, 0x88, 0x1d, 0xa0, 0x8d, 0xaf, 0x35, 0xe8, 0xf8, 0x16, 0x7a, 0x8f, 0xaf, 0xfd, + 0x9b, 0x45, 0x98, 0x32, 0x1a, 0xeb, 0x44, 0x03, 0x9c, 0x59, 0x37, 0xe8, 0x3d, 0xe7, 0xc4, 0x44, + 0xec, 0x3f, 0xbb, 0xff, 0x56, 0xd1, 0xef, 0x42, 0xba, 0x03, 0x78, 0x7d, 0xf4, 0x25, 0x28, 0x7b, + 0x4e, 0xc4, 0x74, 0x57, 0x44, 0xec, 0xbb, 0x41, 0x88, 0x25, 0x72, 0x84, 0x13, 0xc5, 0xda, 0x55, + 0xc3, 0x69, 0x27, 0x24, 0xe9, 0x85, 0x4c, 0x79, 0x1f, 0x69, 0x74, 0xa3, 0x3a, 0x41, 0x19, 0xa4, + 0x7d, 0xcc, 0x61, 0xe8, 0x55, 0x18, 0x0f, 0x09, 0x5b, 0x15, 0x4b, 0x94, 0x95, 0x63, 0xcb, 0x6c, + 0x28, 0xe1, 0xf9, 0xb0, 0x06, 0xc3, 0x06, 0x66, 0xc2, 0xca, 0x0f, 0xf7, 0x60, 0xe5, 0x9f, 0x81, + 0x11, 0xf6, 0x43, 0xad, 0x00, 0x35, 0x1b, 0xab, 0xbc, 0x18, 0x4b, 0x78, 0x7a, 0xc1, 0x8c, 0x0e, + 0xb8, 0x60, 0x3e, 0x09, 0x93, 0x55, 0x87, 0xec, 0x06, 0xfe, 0xb2, 0xdf, 0x6c, 0x07, 0xae, 0x1f, + 0xa3, 0x59, 0x28, 0xb1, 0xdb, 0x81, 0xef, 0xed, 0x12, 0xa5, 0x80, 0x4b, 0x94, 0x31, 0xb7, 0x5b, + 0x70, 0xae, 0x1a, 0xdc, 0xf7, 0xef, 0x3b, 0x61, 0x73, 0xa1, 0xb6, 0xaa, 0xc9, 0xb9, 0xeb, 0x52, + 0xce, 0xe2, 0x46, 0x2c, 0x99, 0x67, 0xaa, 0x56, 0x93, 0xdf, 0xb5, 0x2b, 0xae, 0x47, 0x72, 0xb4, + 0x11, 0x7f, 0xb3, 0x60, 0xb4, 0x94, 0xe0, 0xab, 0x07, 0x23, 0x2b, 0xf7, 0xc1, 0xe8, 0x4d, 0x18, + 0xdd, 0x72, 0x89, 0xd7, 0xc4, 0x64, 0x4b, 0x2c, 0xb1, 0xa7, 0xf3, 0xdf, 0xe5, 0x57, 0x28, 0xa6, + 0xd4, 0x3e, 0x71, 0x29, 0x6d, 0x45, 0x54, 0xc6, 0x8a, 0x0c, 0xda, 0x81, 0x69, 0x29, 0x06, 0x48, + 0xa8, 0x58, 0x70, 0xcf, 0xf4, 0x92, 0x2d, 0x4c, 0xe2, 0x67, 0x0f, 0x0f, 0x2a, 0xd3, 0x38, 0x45, + 0x06, 0x77, 0x11, 0xa6, 0x62, 0xd9, 0x2e, 0x3d, 0x5a, 0x4b, 0x6c, 0xf8, 0x99, 0x58, 0xc6, 0x24, + 0x4c, 0x56, 0x6a, 0xff, 0x84, 0x05, 0x8f, 0x75, 0x8d, 0x8c, 0x90, 0xb4, 0x4f, 0x78, 0x16, 0xd2, + 0x92, 0x6f, 0xa1, 0xbf, 0xe4, 0x6b, 0xff, 0x03, 0x0b, 0xce, 0x2e, 0xef, 0xb6, 0xe3, 0xfd, 0xaa, + 0x6b, 0xbe, 0xee, 0xbc, 0x02, 0xc3, 0xbb, 0xa4, 0xe9, 0x76, 0x76, 0xc5, 0xcc, 0x55, 0xe4, 0xf1, + 0xb3, 0xc6, 0x4a, 0x8f, 0x0e, 0x2a, 0x13, 0xf5, 0x38, 0x08, 0x9d, 0x16, 0xe1, 0x05, 0x58, 0xa0, + 0xb3, 0x43, 0xdc, 0x7d, 0x9f, 0xdc, 0x76, 0x77, 0x5d, 0x69, 0x67, 0xd1, 0x53, 0x77, 0x36, 0x2f, + 0x07, 0x74, 0xfe, 0xcd, 0x8e, 0xe3, 0xc7, 0x6e, 0xbc, 0x2f, 0x1e, 0x66, 0x24, 0x11, 0x9c, 0xd0, + 0xb3, 0xbf, 0x69, 0xc1, 0x94, 0x5c, 0xf7, 0x0b, 0xcd, 0x66, 0x48, 0xa2, 0x08, 0xcd, 0x41, 0xc1, + 0x6d, 0x8b, 0x5e, 0x82, 0xe8, 0x65, 0x61, 0xb5, 0x86, 0x0b, 0x6e, 0x1b, 0xd5, 0xa0, 0xcc, 0xcd, + 0x35, 0x92, 0xc5, 0x35, 0x90, 0xd1, 0x07, 0xeb, 0xc1, 0x86, 0xac, 0x89, 0x13, 0x22, 0x92, 0x83, + 0x63, 0x67, 0x66, 0xd1, 0x7c, 0xf5, 0xba, 0x29, 0xca, 0xb1, 0xc2, 0x40, 0x57, 0x61, 0xd4, 0x0f, + 0x9a, 0xdc, 0x7a, 0x86, 0xdf, 0x7e, 0x6c, 0xc9, 0xae, 0x8b, 0x32, 0xac, 0xa0, 0xf6, 0x0f, 0x5b, + 0x30, 0x2e, 0xbf, 0x6c, 0x40, 0x66, 0x92, 0x6e, 0xad, 0x84, 0x91, 0x4c, 0xb6, 0x16, 0x65, 0x06, + 0x19, 0xc4, 0xe0, 0x01, 0x8b, 0xc7, 0xe1, 0x01, 0xed, 0x1f, 0x2f, 0xc0, 0xa4, 0xec, 0x4e, 0xbd, + 0xb3, 0x19, 0x91, 0x18, 0x6d, 0x40, 0xd9, 0xe1, 0x43, 0x4e, 0xe4, 0x8a, 0x7d, 0x2a, 0x5b, 0xf8, + 0x30, 0xe6, 0x27, 0xb9, 0x96, 0x17, 0x64, 0x6d, 0x9c, 0x10, 0x42, 0x1e, 0xcc, 0xf8, 0x41, 0xcc, + 0x8e, 0x68, 0x05, 0xef, 0xf5, 0x04, 0x92, 0xa6, 0x7e, 0x41, 0x50, 0x9f, 0x59, 0x4f, 0x53, 0xc1, + 0xdd, 0x84, 0xd1, 0xb2, 0x54, 0x78, 0x14, 0xf3, 0xc5, 0x0d, 0x7d, 0x16, 0xb2, 0xf5, 0x1d, 0xf6, + 0xaf, 0x59, 0x50, 0x96, 0x68, 0xa7, 0xf1, 0xda, 0xb5, 0x06, 0x23, 0x11, 0x9b, 0x04, 0x39, 0x34, + 0x76, 0xaf, 0x8e, 0xf3, 0xf9, 0x4a, 0x6e, 0x1e, 0xfe, 0x3f, 0xc2, 0x92, 0x06, 0xd3, 0x77, 0xab, + 0xee, 0x7f, 0x44, 0xf4, 0xdd, 0xaa, 0x3f, 0x39, 0x37, 0xcc, 0x7f, 0x65, 0x7d, 0xd6, 0xc4, 0x5a, + 0xca, 0x20, 0xb5, 0x43, 0xb2, 0xe5, 0x3e, 0x48, 0x33, 0x48, 0x35, 0x56, 0x8a, 0x05, 0x14, 0xbd, + 0x03, 0xe3, 0x0d, 0xa9, 0xe8, 0x4c, 0x8e, 0x81, 0x2b, 0x3d, 0x95, 0xee, 0xea, 0x7d, 0x86, 0x5b, + 0xd6, 0x2e, 0x69, 0xf5, 0xb1, 0x41, 0xcd, 0x7c, 0x6e, 0x2f, 0xf6, 0x7b, 0x6e, 0x4f, 0xe8, 0xe6, + 0x3f, 0x3e, 0xff, 0xa4, 0x05, 0xc3, 0x5c, 0x5d, 0x36, 0x98, 0x7e, 0x51, 0x7b, 0xae, 0x4a, 0xc6, + 0xee, 0x1e, 0x2d, 0x14, 0xcf, 0x4f, 0x68, 0x0d, 0xca, 0xec, 0x07, 0x53, 0x1b, 0x14, 0xf3, 0x4d, + 0x8a, 0x79, 0xab, 0x7a, 0x07, 0xef, 0xc9, 0x6a, 0x38, 0xa1, 0x60, 0xff, 0x68, 0x91, 0x1e, 0x55, + 0x09, 0xaa, 0x71, 0x83, 0x5b, 0x8f, 0xee, 0x06, 0x2f, 0x3c, 0xaa, 0x1b, 0xbc, 0x05, 0x53, 0x0d, + 0xed, 0x71, 0x2b, 0x99, 0xc9, 0xab, 0x3d, 0x17, 0x89, 0xf6, 0x0e, 0xc6, 0x55, 0x46, 0x4b, 0x26, + 0x11, 0x9c, 0xa6, 0x8a, 0xbe, 0x13, 0xc6, 0xf9, 0x3c, 0x8b, 0x56, 0xb8, 0xc5, 0xc2, 0x27, 0xf2, + 0xd7, 0x8b, 0xde, 0x04, 0x5b, 0x89, 0x75, 0xad, 0x3a, 0x36, 0x88, 0xd9, 0xbf, 0x32, 0x0a, 0x43, + 0xcb, 0x7b, 0xc4, 0x8f, 0x4f, 0xe1, 0x40, 0x6a, 0xc0, 0xa4, 0xeb, 0xef, 0x05, 0xde, 0x1e, 0x69, + 0x72, 0xf8, 0x71, 0x2e, 0xd7, 0xf3, 0x82, 0xf4, 0xe4, 0xaa, 0x41, 0x02, 0xa7, 0x48, 0x3e, 0x0a, + 0x09, 0xf3, 0x06, 0x0c, 0xf3, 0xb9, 0x17, 0xe2, 0x65, 0xa6, 0x32, 0x98, 0x0d, 0xa2, 0xd8, 0x05, + 0x89, 0xf4, 0xcb, 0xb5, 0xcf, 0xa2, 0x3a, 0x7a, 0x17, 0x26, 0xb7, 0xdc, 0x30, 0x8a, 0xa9, 0x68, + 0x18, 0xc5, 0xce, 0x6e, 0xfb, 0x21, 0x24, 0x4a, 0x35, 0x0e, 0x2b, 0x06, 0x25, 0x9c, 0xa2, 0x8c, + 0x5a, 0x30, 0x41, 0x85, 0x9c, 0xa4, 0xa9, 0x91, 0x63, 0x37, 0xa5, 0x54, 0x46, 0xb7, 0x75, 0x42, + 0xd8, 0xa4, 0x4b, 0x0f, 0x93, 0x06, 0x13, 0x8a, 0x46, 0x19, 0x47, 0xa1, 0x0e, 0x13, 0x2e, 0x0d, + 0x71, 0x18, 0x3d, 0x93, 0x98, 0xd9, 0x4a, 0xd9, 0x3c, 0x93, 0x34, 0xe3, 0x94, 0x2f, 0x43, 0x99, + 0xd0, 0x21, 0xa4, 0x84, 0x85, 0x62, 0xfc, 0xda, 0x60, 0x7d, 0x5d, 0x73, 0x1b, 0x61, 0x60, 0xca, + 0xf2, 0xcb, 0x92, 0x12, 0x4e, 0x88, 0xa2, 0x25, 0x18, 0x8e, 0x48, 0xe8, 0x92, 0x48, 0xa8, 0xc8, + 0x7b, 0x4c, 0x23, 0x43, 0xe3, 0xb6, 0xe7, 0xfc, 0x37, 0x16, 0x55, 0xe9, 0xf2, 0x72, 0x98, 0x34, + 0xc4, 0xb4, 0xe2, 0xda, 0xf2, 0x5a, 0x60, 0xa5, 0x58, 0x40, 0xd1, 0x1b, 0x30, 0x12, 0x12, 0x8f, + 0x29, 0x8b, 0x26, 0x06, 0x5f, 0xe4, 0x5c, 0xf7, 0xc4, 0xeb, 0x61, 0x49, 0x00, 0xdd, 0x02, 0x14, + 0x12, 0xca, 0x43, 0xb8, 0x7e, 0x4b, 0x19, 0x73, 0x08, 0x5d, 0xf7, 0xe3, 0xa2, 0xfd, 0x33, 0x38, + 0xc1, 0x90, 0x56, 0xa9, 0x38, 0xa3, 0x1a, 0xba, 0x01, 0x33, 0xaa, 0x74, 0xd5, 0x8f, 0x62, 0xc7, + 0x6f, 0x10, 0xa6, 0xe6, 0x2e, 0x27, 0x5c, 0x11, 0x4e, 0x23, 0xe0, 0xee, 0x3a, 0xf6, 0xcf, 0x51, + 0x76, 0x86, 0x8e, 0xd6, 0x29, 0xf0, 0x02, 0xaf, 0x9b, 0xbc, 0xc0, 0x85, 0xdc, 0x99, 0xcb, 0xe1, + 0x03, 0x0e, 0x2d, 0x18, 0xd3, 0x66, 0x36, 0x59, 0xb3, 0x56, 0x8f, 0x35, 0xdb, 0x81, 0x69, 0xba, + 0xd2, 0xef, 0x6c, 0x46, 0x24, 0xdc, 0x23, 0x4d, 0xb6, 0x30, 0x0b, 0x0f, 0xb7, 0x30, 0xd5, 0x2b, + 0xf3, 0xed, 0x14, 0x41, 0xdc, 0xd5, 0x04, 0x7a, 0x45, 0x6a, 0x4e, 0x8a, 0x86, 0x91, 0x16, 0xd7, + 0x8a, 0x1c, 0x1d, 0x54, 0xa6, 0xb5, 0x0f, 0xd1, 0x35, 0x25, 0xf6, 0x97, 0xe5, 0x37, 0xaa, 0xd7, + 0xfc, 0x86, 0x5a, 0x2c, 0xa9, 0xd7, 0x7c, 0xb5, 0x1c, 0x70, 0x82, 0x43, 0xf7, 0x28, 0x15, 0x41, + 0xd2, 0xaf, 0xf9, 0x54, 0x40, 0xc1, 0x0c, 0x62, 0xbf, 0x08, 0xb0, 0xfc, 0x80, 0x34, 0xf8, 0x52, + 0xd7, 0x1f, 0x20, 0xad, 0xfc, 0x07, 0x48, 0xfb, 0xdf, 0x5b, 0x30, 0xb9, 0xb2, 0x64, 0x88, 0x89, + 0xf3, 0x00, 0x5c, 0x36, 0x7a, 0xeb, 0xad, 0x75, 0xa9, 0x5b, 0xe7, 0xea, 0x51, 0x55, 0x8a, 0x35, + 0x0c, 0x74, 0x01, 0x8a, 0x5e, 0xc7, 0x17, 0x22, 0xcb, 0xc8, 0xe1, 0x41, 0xa5, 0x78, 0xbb, 0xe3, + 0x63, 0x5a, 0xa6, 0x59, 0x08, 0x16, 0x07, 0xb6, 0x10, 0xec, 0xeb, 0x5e, 0x85, 0x2a, 0x30, 0x74, + 0xff, 0xbe, 0xdb, 0xe4, 0x46, 0xec, 0x42, 0xef, 0xff, 0xd6, 0x5b, 0xab, 0xd5, 0x08, 0xf3, 0x72, + 0xfb, 0xab, 0x45, 0x98, 0x5b, 0xf1, 0xc8, 0x83, 0x0f, 0x68, 0xc8, 0x3f, 0xa8, 0x7d, 0xe3, 0xf1, + 0xf8, 0xc5, 0xe3, 0xda, 0xb0, 0xf6, 0x1f, 0x8f, 0x2d, 0x18, 0xe1, 0x8f, 0xd9, 0xd2, 0xac, 0xff, + 0xb5, 0xac, 0xd6, 0xf3, 0x07, 0x64, 0x9e, 0x3f, 0x8a, 0x0b, 0x73, 0x7e, 0x75, 0xd3, 0x8a, 0x52, + 0x2c, 0x89, 0xcf, 0x7d, 0x06, 0xc6, 0x75, 0xcc, 0x63, 0x59, 0x93, 0xff, 0xa5, 0x22, 0x4c, 0xd3, + 0x1e, 0x3c, 0xd2, 0x89, 0xb8, 0xdb, 0x3d, 0x11, 0x27, 0x6d, 0x51, 0xdc, 0x7f, 0x36, 0xde, 0x49, + 0xcf, 0xc6, 0x0b, 0x79, 0xb3, 0x71, 0xda, 0x73, 0xf0, 0xbd, 0x16, 0x9c, 0x59, 0xf1, 0x82, 0xc6, + 0x4e, 0xca, 0xea, 0xf7, 0x65, 0x18, 0xa3, 0xe7, 0x78, 0x64, 0x78, 0x11, 0x19, 0x7e, 0x65, 0x02, + 0x84, 0x75, 0x3c, 0xad, 0xda, 0xdd, 0xbb, 0xab, 0xd5, 0x2c, 0x77, 0x34, 0x01, 0xc2, 0x3a, 0x9e, + 0xfd, 0x0d, 0x0b, 0x2e, 0xde, 0x58, 0x5a, 0x4e, 0x96, 0x62, 0x97, 0x47, 0x1c, 0x95, 0x02, 0x9b, + 0x5a, 0x57, 0x12, 0x29, 0xb0, 0xca, 0x7a, 0x21, 0xa0, 0x1f, 0x15, 0x6f, 0xcf, 0x9f, 0xb5, 0xe0, + 0xcc, 0x0d, 0x37, 0xa6, 0xd7, 0x72, 0xda, 0x37, 0x8b, 0xde, 0xcb, 0x91, 0x1b, 0x07, 0xe1, 0x7e, + 0xda, 0x37, 0x0b, 0x2b, 0x08, 0xd6, 0xb0, 0x78, 0xcb, 0x7b, 0x2e, 0x33, 0xa3, 0x2a, 0x98, 0xaa, + 0x28, 0x2c, 0xca, 0xb1, 0xc2, 0xa0, 0x1f, 0xd6, 0x74, 0x43, 0x26, 0x4a, 0xec, 0x8b, 0x13, 0x56, + 0x7d, 0x58, 0x55, 0x02, 0x70, 0x82, 0x63, 0xff, 0x84, 0x05, 0xe7, 0x6e, 0x78, 0x9d, 0x28, 0x26, + 0xe1, 0x56, 0x64, 0x74, 0xf6, 0x45, 0x28, 0x13, 0x29, 0xae, 0x8b, 0xbe, 0x2a, 0x06, 0x53, 0xc9, + 0xf1, 0xdc, 0x31, 0x4c, 0xe1, 0x0d, 0xe0, 0x39, 0x70, 0x3c, 0xd7, 0xb1, 0x5f, 0x2c, 0xc0, 0xc4, + 0xcd, 0x8d, 0x8d, 0xda, 0x0d, 0x12, 0x8b, 0x5b, 0xac, 0xbf, 0xaa, 0x19, 0x6b, 0x1a, 0xb3, 0x5e, + 0x42, 0x51, 0x27, 0x76, 0xbd, 0x79, 0xee, 0x89, 0x3c, 0xbf, 0xea, 0xc7, 0x77, 0xc2, 0x7a, 0x1c, + 0xba, 0x7e, 0x2b, 0x53, 0xc7, 0x26, 0xef, 0xda, 0x62, 0xde, 0x5d, 0x8b, 0x5e, 0x84, 0x61, 0xe6, + 0x0a, 0x2d, 0xc5, 0x93, 0xc7, 0x95, 0x4c, 0xc1, 0x4a, 0x8f, 0x0e, 0x2a, 0xe5, 0xbb, 0x78, 0x95, + 0xff, 0xc1, 0x02, 0x15, 0xdd, 0x85, 0xb1, 0xed, 0x38, 0x6e, 0xdf, 0x24, 0x4e, 0x93, 0x84, 0xf2, + 0x74, 0xb8, 0x94, 0x75, 0x3a, 0xd0, 0x41, 0xe0, 0x68, 0xc9, 0x86, 0x4a, 0xca, 0x22, 0xac, 0xd3, + 0xb1, 0xeb, 0x00, 0x09, 0xec, 0x84, 0xf4, 0x0b, 0xf6, 0x1f, 0x58, 0x30, 0xc2, 0xbd, 0xd2, 0x42, + 0xf4, 0x59, 0x28, 0x91, 0x07, 0xa4, 0x21, 0x38, 0xc7, 0xcc, 0x0e, 0x27, 0x8c, 0x07, 0xd7, 0x96, + 0xd3, 0xff, 0x98, 0xd5, 0x42, 0x37, 0x61, 0x84, 0xf6, 0xf6, 0x86, 0x72, 0xd1, 0x7b, 0x32, 0xef, + 0x8b, 0xd5, 0xb4, 0x73, 0x5e, 0x45, 0x14, 0x61, 0x59, 0x9d, 0x69, 0x7e, 0x1b, 0xed, 0x3a, 0x3d, + 0xc0, 0xe2, 0x5e, 0xf7, 0xec, 0xc6, 0x52, 0x8d, 0x23, 0x09, 0x6a, 0x5c, 0xf3, 0x2b, 0x0b, 0x71, + 0x42, 0xc4, 0xde, 0x80, 0x32, 0x9d, 0xd4, 0x05, 0xcf, 0x75, 0x7a, 0x2b, 0x9d, 0x9f, 0x85, 0xb2, + 0x54, 0x00, 0x47, 0xc2, 0xb1, 0x89, 0x51, 0x95, 0xfa, 0xe1, 0x08, 0x27, 0x70, 0x7b, 0x0b, 0xce, + 0xb2, 0x97, 0x7f, 0x27, 0xde, 0x36, 0xf6, 0x58, 0xff, 0xc5, 0xfc, 0x9c, 0x10, 0xc4, 0xf8, 0xcc, + 0xcc, 0x6a, 0xbe, 0x03, 0xe3, 0x92, 0x62, 0x22, 0x94, 0xd9, 0x7f, 0x54, 0x82, 0xc7, 0x57, 0xeb, + 0xf9, 0x0e, 0x8b, 0xaf, 0xc2, 0x38, 0x67, 0xd3, 0xe8, 0xd2, 0x76, 0x3c, 0xd1, 0xae, 0x7a, 0x17, + 0xdb, 0xd0, 0x60, 0xd8, 0xc0, 0x44, 0x17, 0xa1, 0xe8, 0xbe, 0xe7, 0xa7, 0xcd, 0x70, 0x57, 0xdf, + 0x5c, 0xc7, 0xb4, 0x9c, 0x82, 0x29, 0xc7, 0xc7, 0x8f, 0x52, 0x05, 0x56, 0x5c, 0xdf, 0xeb, 0x30, + 0xe9, 0x46, 0x8d, 0xc8, 0x5d, 0xf5, 0xe9, 0x39, 0x93, 0x38, 0xbb, 0x26, 0x4a, 0x02, 0xda, 0x69, + 0x05, 0xc5, 0x29, 0x6c, 0xed, 0x5c, 0x1f, 0x1a, 0x98, 0x6b, 0xec, 0xeb, 0xe9, 0x43, 0x19, 0xe2, + 0x36, 0xfb, 0xba, 0x88, 0x19, 0xb5, 0x09, 0x86, 0x98, 0x7f, 0x70, 0x84, 0x25, 0x8c, 0x4a, 0x60, + 0x8d, 0x6d, 0xa7, 0xbd, 0xd0, 0x89, 0xb7, 0xab, 0x6e, 0xd4, 0x08, 0xf6, 0x48, 0xb8, 0xcf, 0x84, + 0xe7, 0xd1, 0x44, 0x02, 0x53, 0x80, 0xa5, 0x9b, 0x0b, 0x35, 0x8a, 0x89, 0xbb, 0xeb, 0x98, 0x5c, + 0x21, 0x9c, 0x04, 0x57, 0xb8, 0x00, 0x53, 0xb2, 0x99, 0x3a, 0x89, 0xd8, 0x1d, 0x31, 0xc6, 0x3a, + 0xa6, 0x4c, 0x6d, 0x45, 0xb1, 0xea, 0x56, 0x1a, 0x1f, 0xbd, 0x02, 0x13, 0xae, 0xef, 0xc6, 0xae, + 0x13, 0x07, 0x21, 0xbb, 0x61, 0xb9, 0x9c, 0xcc, 0x2c, 0xd9, 0x56, 0x75, 0x00, 0x36, 0xf1, 0xec, + 0x3f, 0x2c, 0xc1, 0x0c, 0x9b, 0xb6, 0x6f, 0xad, 0xb0, 0x8f, 0xcc, 0x0a, 0xbb, 0xdb, 0xbd, 0xc2, + 0x4e, 0x82, 0xdd, 0xfd, 0x30, 0x97, 0xd9, 0xbb, 0x50, 0x56, 0xb6, 0xc0, 0xd2, 0x19, 0xc0, 0xca, + 0x71, 0x06, 0xe8, 0xcf, 0x7d, 0xc8, 0x67, 0xdc, 0x62, 0xe6, 0x33, 0xee, 0xdf, 0xb6, 0x20, 0x31, + 0x89, 0x44, 0x37, 0xa1, 0xdc, 0x0e, 0x98, 0xd9, 0x41, 0x28, 0x6d, 0x79, 0x1e, 0xcf, 0xbc, 0xa8, + 0xf8, 0xa5, 0xc8, 0xc7, 0xaf, 0x26, 0x6b, 0xe0, 0xa4, 0x32, 0x5a, 0x84, 0x91, 0x76, 0x48, 0xea, + 0x31, 0x73, 0x81, 0xed, 0x4b, 0x87, 0xaf, 0x11, 0x8e, 0x8f, 0x65, 0x45, 0xfb, 0x97, 0x2c, 0x00, + 0xfe, 0x52, 0xea, 0xf8, 0x2d, 0x72, 0x0a, 0xda, 0xdf, 0x2a, 0x94, 0xa2, 0x36, 0x69, 0xf4, 0x32, + 0x08, 0x49, 0xfa, 0x53, 0x6f, 0x93, 0x46, 0x32, 0xe0, 0xf4, 0x1f, 0x66, 0xb5, 0xed, 0xef, 0x03, + 0x98, 0x4c, 0xd0, 0x56, 0x63, 0xb2, 0x8b, 0x9e, 0x37, 0x5c, 0xe2, 0x2e, 0xa4, 0x5c, 0xe2, 0xca, + 0x0c, 0x5b, 0x53, 0x34, 0xbe, 0x0b, 0xc5, 0x5d, 0xe7, 0x81, 0xd0, 0x24, 0x3d, 0xdb, 0xbb, 0x1b, + 0x94, 0xfe, 0xfc, 0x9a, 0xf3, 0x80, 0xcb, 0x4c, 0xcf, 0xca, 0x05, 0xb2, 0xe6, 0x3c, 0x38, 0xe2, + 0x66, 0x1f, 0xec, 0x90, 0xba, 0xed, 0x46, 0xf1, 0x57, 0xfe, 0x53, 0xf2, 0x9f, 0x2d, 0x3b, 0xda, + 0x08, 0x6b, 0xcb, 0xf5, 0xc5, 0xbb, 0xe1, 0x40, 0x6d, 0xb9, 0x7e, 0xba, 0x2d, 0xd7, 0x1f, 0xa0, + 0x2d, 0xd7, 0x47, 0xef, 0xc3, 0x88, 0x78, 0xa3, 0x67, 0xb6, 0xde, 0xa6, 0x96, 0x2a, 0xaf, 0x3d, + 0xf1, 0xc4, 0xcf, 0xdb, 0xbc, 0x26, 0x65, 0x42, 0x51, 0xda, 0xb7, 0x5d, 0xd9, 0x20, 0xfa, 0x1b, + 0x16, 0x4c, 0x8a, 0xdf, 0x98, 0xbc, 0xd7, 0x21, 0x51, 0x2c, 0x78, 0xcf, 0x4f, 0x0f, 0xde, 0x07, + 0x51, 0x91, 0x77, 0xe5, 0xd3, 0xf2, 0x98, 0x35, 0x81, 0x7d, 0x7b, 0x94, 0xea, 0x05, 0xfa, 0x47, + 0x16, 0x9c, 0xdd, 0x75, 0x1e, 0xf0, 0x16, 0x79, 0x19, 0x76, 0x62, 0x37, 0x10, 0xb6, 0xeb, 0x9f, + 0x1d, 0x6c, 0xfa, 0xbb, 0xaa, 0xf3, 0x4e, 0x4a, 0x33, 0xd7, 0xb3, 0x59, 0x28, 0x7d, 0xbb, 0x9a, + 0xd9, 0xaf, 0xb9, 0x2d, 0x18, 0x95, 0xeb, 0x2d, 0x43, 0xf2, 0xae, 0xea, 0x8c, 0xf5, 0xb1, 0x4d, + 0x24, 0x74, 0xbf, 0x34, 0xda, 0x8e, 0x58, 0x6b, 0x8f, 0xb4, 0x9d, 0x77, 0x61, 0x5c, 0x5f, 0x63, + 0x8f, 0xb4, 0xad, 0xf7, 0xe0, 0x4c, 0xc6, 0x5a, 0x7a, 0xa4, 0x4d, 0xde, 0x87, 0x0b, 0xb9, 0xeb, + 0xe3, 0x51, 0x36, 0x6c, 0xff, 0xa2, 0xa5, 0x9f, 0x83, 0xa7, 0xa0, 0x82, 0x5f, 0x32, 0x55, 0xf0, + 0x97, 0x7a, 0xef, 0x9c, 0x1c, 0x3d, 0xfc, 0x3b, 0x7a, 0xa7, 0xe9, 0xa9, 0x8e, 0xde, 0x80, 0x61, + 0x8f, 0x96, 0x48, 0xe3, 0x10, 0xbb, 0xff, 0x8e, 0x4c, 0x78, 0x29, 0x56, 0x1e, 0x61, 0x41, 0xc1, + 0xfe, 0x55, 0x0b, 0x4a, 0xa7, 0x30, 0x12, 0xd8, 0x1c, 0x89, 0xe7, 0x73, 0x49, 0x8b, 0x90, 0x66, + 0xf3, 0xd8, 0xb9, 0xbf, 0xfc, 0x20, 0x26, 0x7e, 0xc4, 0x44, 0xc5, 0xcc, 0x81, 0xf9, 0x2e, 0x38, + 0x73, 0x3b, 0x70, 0x9a, 0x8b, 0x8e, 0xe7, 0xf8, 0x0d, 0x12, 0xae, 0xfa, 0xad, 0xbe, 0x56, 0x4a, + 0xba, 0x4d, 0x51, 0xa1, 0x9f, 0x4d, 0x91, 0xbd, 0x0d, 0x48, 0x6f, 0x40, 0xd8, 0x71, 0x62, 0x18, + 0x71, 0x79, 0x53, 0x62, 0xf8, 0x9f, 0xce, 0xe6, 0xee, 0xba, 0x7a, 0xa6, 0x59, 0x28, 0xf2, 0x02, + 0x2c, 0x09, 0xd9, 0xaf, 0x42, 0xa6, 0xef, 0x56, 0x7f, 0xb5, 0x81, 0xfd, 0x32, 0xcc, 0xb0, 0x9a, + 0xc7, 0x13, 0x69, 0xed, 0x1f, 0xb0, 0x60, 0x6a, 0x3d, 0x15, 0x9b, 0xe2, 0x0a, 0x7b, 0xeb, 0xcb, + 0xd0, 0xfb, 0xd6, 0x59, 0x29, 0x16, 0xd0, 0x13, 0xd7, 0x2f, 0xfd, 0x99, 0x05, 0x89, 0xab, 0xe4, + 0x29, 0x30, 0x55, 0x4b, 0x06, 0x53, 0x95, 0xa9, 0xf7, 0x50, 0xdd, 0xc9, 0xe3, 0xa9, 0xd0, 0x2d, + 0x15, 0x17, 0xa0, 0x87, 0xca, 0x23, 0x21, 0xc3, 0xbd, 0xc8, 0x27, 0xcd, 0xe0, 0x01, 0x32, 0x52, + 0x00, 0x33, 0x13, 0x52, 0xb8, 0x1f, 0x11, 0x33, 0x21, 0xd5, 0x9f, 0x9c, 0xdd, 0x57, 0xd3, 0xba, + 0xcc, 0x4e, 0xa5, 0x6f, 0x67, 0x66, 0xdf, 0x8e, 0xe7, 0xbe, 0x4f, 0x54, 0x70, 0x93, 0x8a, 0x30, + 0xe3, 0x16, 0xa5, 0x47, 0x07, 0x95, 0x09, 0xf5, 0x8f, 0x47, 0xc0, 0x4a, 0xaa, 0xd8, 0x37, 0x61, + 0x2a, 0x35, 0x60, 0xe8, 0x65, 0x18, 0x6a, 0x6f, 0x3b, 0x11, 0x49, 0x99, 0x46, 0x0e, 0xd5, 0x68, + 0xe1, 0xd1, 0x41, 0x65, 0x52, 0x55, 0x60, 0x25, 0x98, 0x63, 0xdb, 0xff, 0xd3, 0x82, 0xd2, 0x7a, + 0xd0, 0x3c, 0x8d, 0xc5, 0xf4, 0xba, 0xb1, 0x98, 0x9e, 0xc8, 0x8b, 0x1f, 0x98, 0xbb, 0x8e, 0x56, + 0x52, 0xeb, 0xe8, 0x52, 0x2e, 0x85, 0xde, 0x4b, 0x68, 0x17, 0xc6, 0x58, 0x54, 0x42, 0x61, 0xaa, + 0xf9, 0xa2, 0xc1, 0xdf, 0x57, 0x52, 0xfc, 0xfd, 0x94, 0x86, 0xaa, 0x71, 0xf9, 0xcf, 0xc0, 0x88, + 0x30, 0x17, 0x4c, 0x1b, 0xb8, 0x0b, 0x5c, 0x2c, 0xe1, 0xf6, 0x4f, 0x16, 0xc1, 0x88, 0x82, 0x88, + 0x7e, 0xcd, 0x82, 0xf9, 0x90, 0x7b, 0x0c, 0x36, 0xab, 0x9d, 0xd0, 0xf5, 0x5b, 0xf5, 0xc6, 0x36, + 0x69, 0x76, 0x3c, 0xd7, 0x6f, 0xad, 0xb6, 0xfc, 0x40, 0x15, 0x2f, 0x3f, 0x20, 0x8d, 0x0e, 0xd3, + 0xf9, 0xf7, 0x09, 0xb9, 0xa8, 0xcc, 0x71, 0xae, 0x1f, 0x1e, 0x54, 0xe6, 0xf1, 0xb1, 0x68, 0xe3, + 0x63, 0xf6, 0x05, 0x7d, 0xc3, 0x82, 0x6b, 0x3c, 0x38, 0xe0, 0xe0, 0xfd, 0xef, 0x21, 0x0d, 0xd5, + 0x24, 0xa9, 0x84, 0xc8, 0x06, 0x09, 0x77, 0x17, 0x5f, 0x11, 0x03, 0x7a, 0xad, 0x76, 0xbc, 0xb6, + 0xf0, 0x71, 0x3b, 0x67, 0xff, 0xcb, 0x22, 0x4c, 0x08, 0x67, 0x75, 0x11, 0x05, 0xe5, 0x65, 0x63, + 0x49, 0x3c, 0x99, 0x5a, 0x12, 0x33, 0x06, 0xf2, 0xc9, 0x04, 0x40, 0x89, 0x60, 0xc6, 0x73, 0xa2, + 0xf8, 0x26, 0x71, 0xc2, 0x78, 0x93, 0x38, 0xdc, 0x4c, 0xa5, 0x78, 0x6c, 0x93, 0x1a, 0xa5, 0x7e, + 0xb9, 0x9d, 0x26, 0x86, 0xbb, 0xe9, 0xa3, 0x3d, 0x40, 0xcc, 0xd6, 0x26, 0x74, 0xfc, 0x88, 0x7f, + 0x8b, 0x2b, 0xde, 0x03, 0x8e, 0xd7, 0xea, 0x9c, 0x68, 0x15, 0xdd, 0xee, 0xa2, 0x86, 0x33, 0x5a, + 0xd0, 0x6c, 0xa8, 0x86, 0x06, 0xb5, 0xa1, 0x1a, 0xee, 0xe3, 0x45, 0xe2, 0xc3, 0x74, 0x57, 0xbc, + 0x81, 0xb7, 0xa1, 0xac, 0x6c, 0xdd, 0xc4, 0xa1, 0xd3, 0x3b, 0x6c, 0x47, 0x9a, 0x02, 0x57, 0x91, + 0x24, 0x76, 0x96, 0x09, 0x39, 0xfb, 0x1f, 0x17, 0x8c, 0x06, 0xf9, 0x24, 0xae, 0xc3, 0xa8, 0x13, + 0x45, 0x6e, 0xcb, 0x27, 0x4d, 0xb1, 0x63, 0x3f, 0x9e, 0xb7, 0x63, 0x8d, 0x66, 0x98, 0xbd, 0xe1, + 0x82, 0xa8, 0x89, 0x15, 0x0d, 0x74, 0x93, 0x1b, 0x03, 0xed, 0x49, 0x7e, 0x7e, 0x30, 0x6a, 0x20, + 0xcd, 0x85, 0xf6, 0x08, 0x16, 0xf5, 0xd1, 0x17, 0xb9, 0xb5, 0xd6, 0x2d, 0x3f, 0xb8, 0xef, 0xdf, + 0x08, 0x02, 0xe9, 0x61, 0x36, 0x18, 0xc1, 0x19, 0x69, 0xa3, 0xa5, 0xaa, 0x63, 0x93, 0xda, 0x60, + 0x31, 0x79, 0xbe, 0x1b, 0xce, 0x50, 0xd2, 0xa6, 0x9f, 0x48, 0x84, 0x08, 0x4c, 0x89, 0x48, 0x08, + 0xb2, 0x4c, 0x8c, 0x5d, 0x26, 0xab, 0x6e, 0xd6, 0x4e, 0x14, 0x7a, 0xb7, 0x4c, 0x12, 0x38, 0x4d, + 0xd3, 0xfe, 0x19, 0x0b, 0x98, 0x85, 0xfb, 0x29, 0xb0, 0x0c, 0x9f, 0x33, 0x59, 0x86, 0xd9, 0xbc, + 0x41, 0xce, 0xe1, 0x16, 0x5e, 0xe2, 0x2b, 0xab, 0x16, 0x06, 0x0f, 0xf6, 0xc5, 0x4b, 0xf9, 0x00, + 0x5c, 0xea, 0xff, 0xb1, 0xf8, 0x21, 0xa6, 0x9c, 0xce, 0xd1, 0xf7, 0xc0, 0x68, 0xc3, 0x69, 0x3b, + 0x0d, 0x1e, 0xb2, 0x37, 0x57, 0x63, 0x63, 0x54, 0x9a, 0x5f, 0x12, 0x35, 0xb8, 0x06, 0x42, 0x46, + 0xd4, 0x18, 0x95, 0xc5, 0x7d, 0xb5, 0x0e, 0xaa, 0xc9, 0xb9, 0x1d, 0x98, 0x30, 0x88, 0x3d, 0x52, + 0x71, 0xf5, 0x7b, 0xf8, 0x15, 0xab, 0x22, 0xc0, 0xec, 0xc2, 0x8c, 0xaf, 0xfd, 0xa7, 0x17, 0x8a, + 0x14, 0x41, 0x3e, 0xde, 0xef, 0x12, 0x65, 0xb7, 0x8f, 0x66, 0xc1, 0x9f, 0x22, 0x83, 0xbb, 0x29, + 0xdb, 0x3f, 0x65, 0xc1, 0x63, 0x3a, 0xa2, 0x16, 0x0f, 0xa0, 0x9f, 0x0e, 0xb8, 0x0a, 0xa3, 0x41, + 0x9b, 0x84, 0x4e, 0x1c, 0x84, 0xe2, 0xd6, 0xb8, 0x2a, 0x07, 0xfd, 0x8e, 0x28, 0x3f, 0x12, 0xb1, + 0x13, 0x25, 0x75, 0x59, 0x8e, 0x55, 0x4d, 0x64, 0xc3, 0x30, 0x1b, 0x8c, 0x48, 0xc4, 0x6a, 0x60, + 0x67, 0x00, 0x7b, 0x0e, 0x8d, 0xb0, 0x80, 0xd8, 0x7f, 0x64, 0xf1, 0x85, 0xa5, 0x77, 0x1d, 0xbd, + 0x07, 0xd3, 0xbb, 0x4e, 0xdc, 0xd8, 0x5e, 0x7e, 0xd0, 0x0e, 0xb9, 0xea, 0x5b, 0x8e, 0xd3, 0xb3, + 0xfd, 0xc6, 0x49, 0xfb, 0xc8, 0xc4, 0x00, 0x6d, 0x2d, 0x45, 0x0c, 0x77, 0x91, 0x47, 0x9b, 0x30, + 0xc6, 0xca, 0x98, 0xa5, 0x73, 0xd4, 0x8b, 0x35, 0xc8, 0x6b, 0x4d, 0xbd, 0x28, 0xaf, 0x25, 0x74, + 0xb0, 0x4e, 0xd4, 0xfe, 0x4a, 0x91, 0xef, 0x76, 0xc6, 0x6d, 0x3f, 0x03, 0x23, 0xed, 0xa0, 0xb9, + 0xb4, 0x5a, 0xc5, 0x62, 0x16, 0xd4, 0x35, 0x52, 0xe3, 0xc5, 0x58, 0xc2, 0xd1, 0x6b, 0x00, 0xe4, + 0x41, 0x4c, 0x42, 0xdf, 0xf1, 0x94, 0x41, 0x88, 0x32, 0x81, 0xac, 0x06, 0xeb, 0x41, 0x7c, 0x37, + 0x22, 0xdf, 0xb5, 0xac, 0x50, 0xb0, 0x86, 0x8e, 0xae, 0x03, 0xb4, 0xc3, 0x60, 0xcf, 0x6d, 0x32, + 0xd7, 0xb9, 0xa2, 0x69, 0x2e, 0x51, 0x53, 0x10, 0xac, 0x61, 0xa1, 0xd7, 0x60, 0xa2, 0xe3, 0x47, + 0x9c, 0x43, 0x71, 0x36, 0x45, 0xe4, 0xc1, 0xd1, 0xc4, 0x72, 0xe1, 0xae, 0x0e, 0xc4, 0x26, 0x2e, + 0x5a, 0x80, 0xe1, 0xd8, 0x61, 0xf6, 0x0e, 0x43, 0xf9, 0x76, 0x8b, 0x1b, 0x14, 0x43, 0x0f, 0x18, + 0x4b, 0x2b, 0x60, 0x51, 0x11, 0xbd, 0x2d, 0xfd, 0x10, 0xf8, 0x59, 0x2f, 0x0c, 0x86, 0x07, 0xbb, + 0x17, 0x34, 0x2f, 0x04, 0x61, 0x88, 0x6c, 0xd0, 0xb2, 0xbf, 0x51, 0x06, 0x48, 0xd8, 0x71, 0xf4, + 0x7e, 0xd7, 0x79, 0xf4, 0x5c, 0x6f, 0x06, 0xfe, 0xe4, 0x0e, 0x23, 0xf4, 0xfd, 0x16, 0x8c, 0x39, + 0x9e, 0x17, 0x34, 0x9c, 0x98, 0x8d, 0x72, 0xa1, 0xf7, 0x79, 0x28, 0xda, 0x5f, 0x48, 0x6a, 0xf0, + 0x2e, 0xbc, 0x28, 0x17, 0x9e, 0x06, 0xe9, 0xdb, 0x0b, 0xbd, 0x61, 0xf4, 0x29, 0x29, 0xa5, 0xf1, + 0xe5, 0x31, 0x97, 0x96, 0xd2, 0xca, 0xec, 0xe8, 0xd7, 0x04, 0x34, 0x74, 0xd7, 0x08, 0x2a, 0x57, + 0xca, 0x8f, 0xaf, 0x60, 0x70, 0xa5, 0xfd, 0xe2, 0xc9, 0xa1, 0x9a, 0xee, 0x38, 0x35, 0x94, 0x1f, + 0x84, 0x44, 0x13, 0x7f, 0xfa, 0x38, 0x4d, 0xbd, 0x0b, 0x53, 0x4d, 0xf3, 0x6e, 0x17, 0xab, 0xe9, + 0xe9, 0x3c, 0xba, 0x29, 0x56, 0x20, 0xb9, 0xcd, 0x53, 0x00, 0x9c, 0x26, 0x8c, 0x6a, 0xdc, 0x85, + 0x6d, 0xd5, 0xdf, 0x0a, 0x84, 0xe1, 0xb9, 0x9d, 0x3b, 0x97, 0xfb, 0x51, 0x4c, 0x76, 0x29, 0x66, + 0x72, 0x69, 0xaf, 0x8b, 0xba, 0x58, 0x51, 0x41, 0x6f, 0xc0, 0x30, 0xf3, 0x81, 0x8d, 0x66, 0x47, + 0xf3, 0x15, 0x85, 0x66, 0xf8, 0x86, 0x64, 0x53, 0xb1, 0xbf, 0x11, 0x16, 0x14, 0xd0, 0x4d, 0x19, + 0xe3, 0x25, 0x5a, 0xf5, 0xef, 0x46, 0x84, 0xc5, 0x78, 0x29, 0x2f, 0x7e, 0x3c, 0x09, 0xdf, 0xc2, + 0xcb, 0x33, 0x43, 0xc3, 0x1b, 0x35, 0x29, 0x73, 0x24, 0xfe, 0xcb, 0x88, 0xf3, 0xb3, 0x90, 0xdf, + 0x3d, 0x33, 0x2a, 0x7d, 0x32, 0x9c, 0xf7, 0x4c, 0x12, 0x38, 0x4d, 0x93, 0x32, 0x9a, 0x7c, 0xe7, + 0x0a, 0xd3, 0xf5, 0x7e, 0xfb, 0x9f, 0xcb, 0xd7, 0xec, 0x92, 0xe1, 0x25, 0x58, 0xd4, 0x3f, 0xd5, + 0x5b, 0x7f, 0xce, 0x87, 0xe9, 0xf4, 0x16, 0x7d, 0xa4, 0x5c, 0xc6, 0x1f, 0x94, 0x60, 0xd2, 0x5c, + 0x52, 0xe8, 0x1a, 0x94, 0x05, 0x11, 0x15, 0x70, 0x54, 0xed, 0x92, 0x35, 0x09, 0xc0, 0x09, 0x0e, + 0x8b, 0x33, 0xcb, 0xaa, 0x6b, 0x26, 0x87, 0x49, 0x9c, 0x59, 0x05, 0xc1, 0x1a, 0x16, 0x95, 0x97, + 0x36, 0x83, 0x20, 0x56, 0x97, 0x8a, 0x5a, 0x77, 0x8b, 0xac, 0x14, 0x0b, 0x28, 0xbd, 0x4c, 0x76, + 0x48, 0xe8, 0x13, 0xcf, 0x8c, 0x63, 0xa6, 0x2e, 0x93, 0x5b, 0x3a, 0x10, 0x9b, 0xb8, 0xf4, 0x96, + 0x0c, 0x22, 0xb6, 0x90, 0x85, 0x54, 0x96, 0x98, 0x70, 0xd6, 0xb9, 0x37, 0xb9, 0x84, 0xa3, 0x2f, + 0xc0, 0x63, 0xca, 0xf9, 0x1b, 0x73, 0x25, 0xb4, 0x6c, 0x71, 0xd8, 0x50, 0xa2, 0x3c, 0xb6, 0x94, + 0x8d, 0x86, 0xf3, 0xea, 0xa3, 0xd7, 0x61, 0x52, 0x70, 0xee, 0x92, 0xe2, 0x88, 0x69, 0x17, 0x71, + 0xcb, 0x80, 0xe2, 0x14, 0xb6, 0x8c, 0xc4, 0xc6, 0x98, 0x67, 0x49, 0x61, 0xb4, 0x3b, 0x12, 0x9b, + 0x0e, 0xc7, 0x5d, 0x35, 0xd0, 0x02, 0x4c, 0x71, 0xd6, 0xca, 0xf5, 0x5b, 0x7c, 0x4e, 0x84, 0x67, + 0x89, 0xda, 0x52, 0x77, 0x4c, 0x30, 0x4e, 0xe3, 0xa3, 0x57, 0x61, 0xdc, 0x09, 0x1b, 0xdb, 0x6e, + 0x4c, 0x1a, 0x71, 0x27, 0xe4, 0x2e, 0x27, 0x9a, 0x61, 0xc9, 0x82, 0x06, 0xc3, 0x06, 0xa6, 0xfd, + 0x3e, 0x9c, 0xc9, 0x70, 0x4a, 0xa3, 0x0b, 0xc7, 0x69, 0xbb, 0xf2, 0x9b, 0x52, 0xc6, 0x98, 0x0b, + 0xb5, 0x55, 0xf9, 0x35, 0x1a, 0x16, 0x5d, 0x9d, 0xcc, 0x79, 0x4d, 0x4b, 0x30, 0xa1, 0x56, 0xe7, + 0x8a, 0x04, 0xe0, 0x04, 0xc7, 0xfe, 0x5f, 0x05, 0x98, 0xca, 0x50, 0xac, 0xb3, 0x24, 0x07, 0x29, + 0xd9, 0x23, 0xc9, 0x69, 0x60, 0x06, 0xf6, 0x2b, 0x1c, 0x23, 0xb0, 0x5f, 0xb1, 0x5f, 0x60, 0xbf, + 0xd2, 0x07, 0x09, 0xec, 0x67, 0x8e, 0xd8, 0xd0, 0x40, 0x23, 0x96, 0x11, 0x0c, 0x70, 0xf8, 0x98, + 0xc1, 0x00, 0x8d, 0x41, 0x1f, 0x19, 0x60, 0xd0, 0x7f, 0xb4, 0x00, 0xd3, 0x69, 0x03, 0xb8, 0x53, + 0x50, 0xc7, 0xbe, 0x61, 0xa8, 0x63, 0xb3, 0x53, 0x86, 0xa4, 0xcd, 0xf2, 0xf2, 0x54, 0xb3, 0x38, + 0xa5, 0x9a, 0xfd, 0xe4, 0x40, 0xd4, 0x7a, 0xab, 0x69, 0xff, 0x6e, 0x01, 0xce, 0xa5, 0xab, 0x2c, + 0x79, 0x8e, 0xbb, 0x7b, 0x0a, 0x63, 0x73, 0xc7, 0x18, 0x9b, 0xe7, 0x07, 0xf9, 0x1a, 0xd6, 0xb5, + 0xdc, 0x01, 0x7a, 0x2b, 0x35, 0x40, 0xd7, 0x06, 0x27, 0xd9, 0x7b, 0x94, 0xbe, 0x59, 0x84, 0x4b, + 0x99, 0xf5, 0x12, 0x6d, 0xe6, 0x8a, 0xa1, 0xcd, 0xbc, 0x9e, 0xd2, 0x66, 0xda, 0xbd, 0x6b, 0x9f, + 0x8c, 0x7a, 0x53, 0x78, 0x0b, 0xb2, 0xe0, 0x6f, 0x0f, 0xa9, 0xda, 0x34, 0xbc, 0x05, 0x15, 0x21, + 0x6c, 0xd2, 0xfd, 0x8b, 0xa4, 0xd2, 0xfc, 0x37, 0x16, 0x5c, 0xc8, 0x9c, 0x9b, 0x53, 0x50, 0x61, + 0xad, 0x9b, 0x2a, 0xac, 0x67, 0x06, 0x5e, 0xad, 0x39, 0x3a, 0xad, 0x3f, 0x2c, 0xe6, 0x7c, 0x0b, + 0x13, 0xd0, 0xef, 0xc0, 0x98, 0xd3, 0x68, 0x90, 0x28, 0x5a, 0x0b, 0x9a, 0x2a, 0x18, 0xda, 0xf3, + 0x4c, 0xce, 0x4a, 0x8a, 0x8f, 0x0e, 0x2a, 0x73, 0x69, 0x12, 0x09, 0x18, 0xeb, 0x14, 0xcc, 0xf8, + 0x8d, 0x85, 0x13, 0x8d, 0xdf, 0x78, 0x1d, 0x60, 0x4f, 0x71, 0xeb, 0x69, 0x21, 0x5f, 0xe3, 0xe3, + 0x35, 0x2c, 0xf4, 0x45, 0x18, 0x8d, 0xc4, 0x35, 0x2e, 0x96, 0xe2, 0x8b, 0x03, 0xce, 0x95, 0xb3, + 0x49, 0x3c, 0xd3, 0x2d, 0x5d, 0xe9, 0x43, 0x14, 0x49, 0xf4, 0x1d, 0x30, 0x1d, 0xf1, 0xa8, 0x27, + 0x4b, 0x9e, 0x13, 0x31, 0x1f, 0x07, 0xb1, 0x0a, 0x99, 0xaf, 0x79, 0x3d, 0x05, 0xc3, 0x5d, 0xd8, + 0x68, 0x45, 0x7e, 0x14, 0x0b, 0xd1, 0xc2, 0x17, 0xe6, 0x95, 0xe4, 0x83, 0x44, 0x8a, 0xa5, 0xb3, + 0xe9, 0xe1, 0x67, 0x03, 0xaf, 0xd5, 0xb4, 0x7f, 0xb4, 0x04, 0x8f, 0xf7, 0x38, 0xc4, 0xd0, 0x82, + 0xf9, 0x46, 0xf9, 0x6c, 0x5a, 0xfa, 0x9d, 0xcb, 0xac, 0x6c, 0x88, 0xc3, 0xa9, 0xb5, 0x52, 0xf8, + 0xc0, 0x6b, 0xe5, 0x87, 0x2c, 0x4d, 0x2f, 0xc1, 0x2d, 0xe9, 0x3e, 0x77, 0xcc, 0xc3, 0xf9, 0x04, + 0x15, 0x15, 0x5b, 0x19, 0xd2, 0xfe, 0xf5, 0x81, 0xbb, 0x33, 0xb0, 0xf8, 0x7f, 0xba, 0xda, 0xd9, + 0xaf, 0x58, 0xf0, 0x64, 0x66, 0x7f, 0x0d, 0x9b, 0x8a, 0x6b, 0x50, 0x6e, 0xd0, 0x42, 0xcd, 0x6f, + 0x2a, 0x71, 0x28, 0x95, 0x00, 0x9c, 0xe0, 0x18, 0xa6, 0x13, 0x85, 0xbe, 0xa6, 0x13, 0xff, 0xc2, + 0x82, 0xae, 0x05, 0x7c, 0x0a, 0x27, 0xe9, 0xaa, 0x79, 0x92, 0x7e, 0x7c, 0x90, 0xb9, 0xcc, 0x39, + 0x44, 0xff, 0xf3, 0x14, 0x9c, 0xcf, 0x71, 0x94, 0xd8, 0x83, 0x99, 0x56, 0x83, 0x98, 0x1e, 0x69, + 0xe2, 0x63, 0x32, 0x9d, 0xf7, 0x7a, 0xba, 0xaf, 0xb1, 0xdc, 0x38, 0x33, 0x5d, 0x28, 0xb8, 0xbb, + 0x09, 0xf4, 0x15, 0x0b, 0xce, 0x3a, 0xf7, 0xa3, 0xae, 0x0c, 0x88, 0x62, 0xcd, 0xbc, 0x94, 0xa9, + 0xa5, 0xe8, 0x93, 0x31, 0x91, 0x27, 0x0b, 0xca, 0xc2, 0xc2, 0x99, 0x6d, 0x21, 0x2c, 0xe2, 0x57, + 0x52, 0x7e, 0xbb, 0x87, 0xcf, 0x64, 0x96, 0x47, 0x0b, 0x3f, 0x53, 0x25, 0x04, 0x2b, 0x3a, 0xe8, + 0x1e, 0x94, 0x5b, 0xd2, 0xcd, 0x4c, 0x9c, 0xd9, 0x99, 0x97, 0x60, 0xa6, 0x2f, 0x1a, 0x7f, 0x37, + 0x54, 0x20, 0x9c, 0x90, 0x42, 0xaf, 0x43, 0xd1, 0xdf, 0x8a, 0x7a, 0x65, 0xd9, 0x49, 0x99, 0x1a, + 0x71, 0x7f, 0xe4, 0xf5, 0x95, 0x3a, 0xa6, 0x15, 0xd1, 0x4d, 0x28, 0x86, 0x9b, 0x4d, 0xa1, 0x58, + 0xcb, 0xe4, 0x4b, 0xf1, 0x62, 0x35, 0x7b, 0x91, 0x70, 0x4a, 0x78, 0xb1, 0x8a, 0x29, 0x09, 0x54, + 0x83, 0x21, 0xe6, 0x53, 0x20, 0xf4, 0x67, 0x99, 0x0c, 0x69, 0x0f, 0xdf, 0x1c, 0xee, 0xb4, 0xcc, + 0x10, 0x30, 0x27, 0x84, 0x36, 0x60, 0xb8, 0xc1, 0x32, 0xb2, 0x88, 0x90, 0xc9, 0x9f, 0xca, 0x54, + 0xa1, 0xf5, 0x48, 0x55, 0x23, 0x34, 0x4a, 0x0c, 0x03, 0x0b, 0x5a, 0x8c, 0x2a, 0x69, 0x6f, 0x6f, + 0x45, 0x4c, 0x04, 0xcf, 0xa3, 0xda, 0x23, 0x03, 0x93, 0xa0, 0xca, 0x30, 0xb0, 0xa0, 0x85, 0x3e, + 0x03, 0x85, 0xad, 0x86, 0x70, 0x39, 0xc8, 0xd4, 0xa5, 0x99, 0x2e, 0xe5, 0x8b, 0xc3, 0x87, 0x07, + 0x95, 0xc2, 0xca, 0x12, 0x2e, 0x6c, 0x35, 0xd0, 0x3a, 0x8c, 0x6c, 0x71, 0x27, 0x54, 0xa1, 0x2e, + 0x7b, 0x3a, 0xdb, 0x3f, 0xb6, 0xcb, 0x4f, 0x95, 0x9b, 0xca, 0x0b, 0x00, 0x96, 0x44, 0x58, 0x10, + 0x48, 0xe5, 0x4c, 0x2b, 0xa2, 0x21, 0xcf, 0x1f, 0xcf, 0x01, 0x9a, 0xbb, 0xb7, 0x27, 0x2e, 0xb9, + 0x58, 0xa3, 0x88, 0xbe, 0x0c, 0x65, 0x47, 0xe6, 0xde, 0x13, 0xd1, 0x22, 0x5e, 0xcc, 0xdc, 0x98, + 0xbd, 0xd3, 0x12, 0xf2, 0x55, 0xad, 0x90, 0x70, 0x42, 0x14, 0xed, 0xc0, 0xc4, 0x5e, 0xd4, 0xde, + 0x26, 0x72, 0x23, 0xb3, 0xe0, 0x11, 0x39, 0x17, 0xd7, 0x3d, 0x81, 0xe8, 0x86, 0x71, 0xc7, 0xf1, + 0xba, 0xce, 0x1e, 0xf6, 0xd8, 0x7c, 0x4f, 0x27, 0x86, 0x4d, 0xda, 0x74, 0xf8, 0xdf, 0xeb, 0x04, + 0x9b, 0xfb, 0x31, 0x11, 0xe1, 0x93, 0x33, 0x87, 0xff, 0x4d, 0x8e, 0xd2, 0x3d, 0xfc, 0x02, 0x80, + 0x25, 0x11, 0xba, 0xd5, 0x1d, 0x99, 0xd7, 0x92, 0x85, 0x4d, 0xce, 0xd9, 0xea, 0x99, 0xc9, 0x2f, + 0xb5, 0x41, 0x61, 0x67, 0x64, 0x42, 0x8a, 0x9d, 0x8d, 0xed, 0xed, 0x20, 0x0e, 0xfc, 0xd4, 0xb9, + 0x3c, 0x93, 0x7f, 0x36, 0xd6, 0x32, 0xf0, 0xbb, 0xcf, 0xc6, 0x2c, 0x2c, 0x9c, 0xd9, 0x16, 0x6a, + 0xc2, 0x64, 0x3b, 0x08, 0xe3, 0xfb, 0x41, 0x28, 0xd7, 0x17, 0xea, 0x21, 0xee, 0x1b, 0x98, 0xa2, + 0x45, 0x16, 0xce, 0xdb, 0x84, 0xe0, 0x14, 0x4d, 0xf4, 0x79, 0x18, 0x89, 0x1a, 0x8e, 0x47, 0x56, + 0xef, 0xcc, 0x9e, 0xc9, 0xbf, 0x74, 0xea, 0x1c, 0x25, 0x67, 0x75, 0xb1, 0xc9, 0x11, 0x28, 0x58, + 0x92, 0x43, 0x2b, 0x30, 0xc4, 0x62, 0xf2, 0xb3, 0xc8, 0xcf, 0x39, 0x51, 0x89, 0xba, 0x8c, 0x3a, + 0xf9, 0xd9, 0xc4, 0x8a, 0x31, 0xaf, 0x4e, 0xf7, 0x80, 0xe0, 0x7a, 0x83, 0x68, 0xf6, 0x5c, 0xfe, + 0x1e, 0x10, 0xcc, 0xf2, 0x9d, 0x7a, 0xaf, 0x3d, 0xa0, 0x90, 0x70, 0x42, 0x94, 0x9e, 0xcc, 0xf4, + 0x34, 0x3d, 0xdf, 0xc3, 0xce, 0x24, 0xf7, 0x2c, 0x65, 0x27, 0x33, 0x3d, 0x49, 0x29, 0x09, 0xfb, + 0xf7, 0x46, 0xba, 0x39, 0x15, 0x26, 0x27, 0xfd, 0x65, 0xab, 0xeb, 0x09, 0xed, 0xd3, 0x83, 0xaa, + 0x6d, 0x4e, 0x90, 0x47, 0xfd, 0x8a, 0x05, 0xe7, 0xdb, 0x99, 0x1f, 0x22, 0xae, 0xfd, 0xc1, 0xb4, + 0x3f, 0xfc, 0xd3, 0x55, 0x74, 0xf6, 0x6c, 0x38, 0xce, 0x69, 0x29, 0x2d, 0x07, 0x14, 0x3f, 0xb0, + 0x1c, 0xb0, 0x06, 0xa3, 0x8c, 0xb5, 0xec, 0x93, 0xa1, 0x2c, 0xed, 0x85, 0xc6, 0x18, 0x88, 0x25, + 0x51, 0x11, 0x2b, 0x12, 0xe8, 0x87, 0x2d, 0xb8, 0x98, 0xee, 0x3a, 0x26, 0x0c, 0x2c, 0x62, 0x99, + 0x73, 0x11, 0x6d, 0x45, 0x7c, 0xff, 0xc5, 0x5a, 0x2f, 0xe4, 0xa3, 0x7e, 0x08, 0xb8, 0x77, 0x63, + 0xa8, 0x9a, 0x21, 0x23, 0x0e, 0x9b, 0x7a, 0xf1, 0x01, 0xe4, 0xc4, 0x97, 0x60, 0x7c, 0x37, 0xe8, + 0xf8, 0xb1, 0x30, 0x4b, 0x11, 0x4e, 0x82, 0xec, 0x1d, 0x78, 0x4d, 0x2b, 0xc7, 0x06, 0x56, 0x4a, + 0xba, 0x1c, 0x7d, 0x58, 0xe9, 0x12, 0xbd, 0x93, 0xca, 0x43, 0x5d, 0xce, 0x8f, 0x99, 0x27, 0x04, + 0xf1, 0x63, 0x64, 0xa3, 0x3e, 0x5d, 0x89, 0xe8, 0xe7, 0xac, 0x0c, 0x56, 0x9e, 0xcb, 0xc8, 0x9f, + 0x35, 0x65, 0xe4, 0x2b, 0x69, 0x19, 0xb9, 0x4b, 0x27, 0x6a, 0x88, 0xc7, 0x83, 0x07, 0x5e, 0x1e, + 0x34, 0x92, 0x99, 0xed, 0xc1, 0xe5, 0x7e, 0xd7, 0x12, 0xb3, 0x4f, 0x6a, 0xaa, 0x17, 0xb0, 0xc4, + 0x3e, 0xa9, 0xb9, 0x5a, 0xc5, 0x0c, 0x32, 0x68, 0xa8, 0x0b, 0xfb, 0xbf, 0x59, 0x50, 0xac, 0x05, + 0xcd, 0x53, 0xd0, 0xf1, 0x7e, 0xce, 0xd0, 0xf1, 0x3e, 0x9e, 0x93, 0x1f, 0x3c, 0x57, 0xa3, 0xbb, + 0x9c, 0xd2, 0xe8, 0x5e, 0xcc, 0x23, 0xd0, 0x5b, 0x7f, 0xfb, 0xd3, 0x45, 0xd0, 0xb3, 0x99, 0xa3, + 0x7f, 0xf5, 0x30, 0xc6, 0xc1, 0xc5, 0x5e, 0x09, 0xce, 0x05, 0x65, 0x66, 0xd6, 0x24, 0xfd, 0xde, + 0xfe, 0x9c, 0xd9, 0x08, 0xbf, 0x45, 0xdc, 0xd6, 0x76, 0x4c, 0x9a, 0xe9, 0xcf, 0x39, 0x3d, 0x1b, + 0xe1, 0xff, 0x62, 0xc1, 0x54, 0xaa, 0x75, 0xe4, 0xc1, 0x84, 0xa7, 0x2b, 0xe8, 0xc4, 0x3a, 0x7d, + 0x28, 0xdd, 0x9e, 0xb0, 0xb1, 0xd4, 0x8a, 0xb0, 0x49, 0x1c, 0xcd, 0x03, 0xa8, 0x07, 0x34, 0xa9, + 0xf7, 0x62, 0x5c, 0xbf, 0x7a, 0x61, 0x8b, 0xb0, 0x86, 0x81, 0x5e, 0x86, 0xb1, 0x38, 0x68, 0x07, + 0x5e, 0xd0, 0xda, 0xbf, 0x45, 0x64, 0x70, 0x15, 0x65, 0x39, 0xb5, 0x91, 0x80, 0xb0, 0x8e, 0x67, + 0xff, 0x6c, 0x11, 0xd2, 0x19, 0xf0, 0xbf, 0xb5, 0x26, 0x3f, 0x9a, 0x6b, 0xf2, 0x9b, 0x16, 0x4c, + 0xd3, 0xd6, 0x99, 0x15, 0x87, 0xbc, 0x6c, 0x55, 0x02, 0x18, 0xab, 0x47, 0x02, 0x98, 0x2b, 0xf4, + 0xec, 0x6a, 0x06, 0x9d, 0x58, 0xe8, 0xcd, 0xb4, 0xc3, 0x89, 0x96, 0x62, 0x01, 0x15, 0x78, 0x24, + 0x0c, 0x85, 0x6b, 0x92, 0x8e, 0x47, 0xc2, 0x10, 0x0b, 0xa8, 0xcc, 0x0f, 0x53, 0xca, 0xc9, 0x0f, + 0xc3, 0x42, 0xc5, 0x89, 0xf7, 0x7e, 0xc1, 0xf6, 0x68, 0xa1, 0xe2, 0xa4, 0x21, 0x40, 0x82, 0x63, + 0xff, 0x62, 0x11, 0xc6, 0x6b, 0x41, 0x33, 0x79, 0xc2, 0x7a, 0xc9, 0x78, 0xc2, 0xba, 0x9c, 0x7a, + 0xc2, 0x9a, 0xd6, 0x71, 0xbf, 0xf5, 0x60, 0xf5, 0x61, 0x3d, 0x58, 0xfd, 0x73, 0x8b, 0xcd, 0x5a, + 0x75, 0xbd, 0x2e, 0xf2, 0xd3, 0xbe, 0x00, 0x63, 0xec, 0x40, 0x62, 0xbe, 0x70, 0xf2, 0x5d, 0x87, + 0x85, 0x7e, 0x5f, 0x4f, 0x8a, 0xb1, 0x8e, 0x83, 0xae, 0xc2, 0x68, 0x44, 0x9c, 0xb0, 0xb1, 0xad, + 0xce, 0x38, 0xf1, 0xea, 0xc1, 0xcb, 0xb0, 0x82, 0xa2, 0x37, 0x93, 0x28, 0x65, 0xc5, 0xfc, 0x4c, + 0xab, 0x7a, 0x7f, 0xf8, 0x16, 0xc9, 0x0f, 0x4d, 0x66, 0xbf, 0x05, 0xa8, 0x1b, 0x7f, 0x80, 0x78, + 0x44, 0x15, 0x33, 0x1e, 0x51, 0xb9, 0x2b, 0x16, 0xd1, 0x9f, 0x5a, 0x30, 0x59, 0x0b, 0x9a, 0x74, + 0xeb, 0xfe, 0x45, 0xda, 0xa7, 0x7a, 0x88, 0xc6, 0xe1, 0x1e, 0x21, 0x1a, 0xff, 0x9e, 0x05, 0x23, + 0xb5, 0xa0, 0x79, 0x0a, 0xda, 0xf6, 0xcf, 0x9a, 0xda, 0xf6, 0xc7, 0x72, 0x96, 0x44, 0x8e, 0x82, + 0xfd, 0x97, 0x8b, 0x30, 0x41, 0xfb, 0x19, 0xb4, 0xe4, 0x2c, 0x19, 0x23, 0x62, 0x0d, 0x30, 0x22, + 0x94, 0xcd, 0x0d, 0x3c, 0x2f, 0xb8, 0x9f, 0x9e, 0xb1, 0x15, 0x56, 0x8a, 0x05, 0x14, 0x3d, 0x07, + 0xa3, 0xed, 0x90, 0xec, 0xb9, 0x81, 0xe0, 0x1f, 0xb5, 0xb7, 0x8b, 0x9a, 0x28, 0xc7, 0x0a, 0x83, + 0xca, 0x5d, 0x91, 0xeb, 0x37, 0x88, 0x4c, 0xf3, 0x5c, 0x62, 0x99, 0xa0, 0x78, 0xec, 0x65, 0xad, + 0x1c, 0x1b, 0x58, 0xe8, 0x2d, 0x28, 0xb3, 0xff, 0xec, 0x44, 0x39, 0x7e, 0xe6, 0x1a, 0x91, 0xf0, + 0x40, 0x10, 0xc0, 0x09, 0x2d, 0x74, 0x1d, 0x20, 0x96, 0xf1, 0x79, 0x23, 0x11, 0x56, 0x46, 0xf1, + 0xda, 0x2a, 0x72, 0x6f, 0x84, 0x35, 0x2c, 0xf4, 0x2c, 0x94, 0x63, 0xc7, 0xf5, 0x6e, 0xbb, 0x3e, + 0x89, 0x98, 0xca, 0xb9, 0x28, 0xf3, 0x19, 0x88, 0x42, 0x9c, 0xc0, 0x29, 0xaf, 0xc3, 0x7c, 0xae, + 0x79, 0xde, 0xab, 0x51, 0x86, 0xcd, 0x78, 0x9d, 0xdb, 0xaa, 0x14, 0x6b, 0x18, 0xf6, 0xab, 0x70, + 0xae, 0x16, 0x34, 0x6b, 0x41, 0x18, 0xaf, 0x04, 0xe1, 0x7d, 0x27, 0x6c, 0xca, 0xf9, 0xab, 0xc8, + 0xd0, 0xfa, 0xf4, 0xec, 0x19, 0xe2, 0x3b, 0xd3, 0x08, 0x9a, 0xff, 0x22, 0xe3, 0x76, 0x8e, 0xe9, + 0x6b, 0xd1, 0x60, 0xf7, 0xae, 0x4a, 0x71, 0x77, 0xc3, 0x89, 0x09, 0xba, 0xc3, 0xd2, 0x62, 0x25, + 0x57, 0x90, 0xa8, 0xfe, 0x8c, 0x96, 0x16, 0x2b, 0x01, 0x66, 0xde, 0x59, 0x66, 0x7d, 0xfb, 0xd7, + 0x8b, 0xec, 0x34, 0x4a, 0x65, 0x7c, 0x43, 0x5f, 0x82, 0xc9, 0x88, 0xdc, 0x76, 0xfd, 0xce, 0x03, + 0x29, 0x84, 0xf7, 0xf0, 0x96, 0xa9, 0x2f, 0xeb, 0x98, 0x5c, 0x95, 0x67, 0x96, 0xe1, 0x14, 0x35, + 0x3a, 0x4f, 0x61, 0xc7, 0x5f, 0x88, 0xee, 0x46, 0x24, 0x14, 0x19, 0xc7, 0xd8, 0x3c, 0x61, 0x59, + 0x88, 0x13, 0x38, 0x5d, 0x97, 0xec, 0xcf, 0x7a, 0xe0, 0xe3, 0x20, 0x88, 0xe5, 0x4a, 0x66, 0x39, + 0x6b, 0xb4, 0x72, 0x6c, 0x60, 0xa1, 0x15, 0x40, 0x51, 0xa7, 0xdd, 0xf6, 0xd8, 0x7b, 0xbb, 0xe3, + 0xdd, 0x08, 0x83, 0x4e, 0x9b, 0xbf, 0x75, 0x16, 0x17, 0xcf, 0xd3, 0x2b, 0xac, 0xde, 0x05, 0xc5, + 0x19, 0x35, 0xe8, 0xe9, 0xb3, 0x15, 0xb1, 0xdf, 0x6c, 0x75, 0x17, 0x85, 0x7a, 0xbd, 0xce, 0x8a, + 0xb0, 0x84, 0xd1, 0xc5, 0xc4, 0x9a, 0xe7, 0x98, 0xc3, 0xc9, 0x62, 0xc2, 0xaa, 0x14, 0x6b, 0x18, + 0x68, 0x19, 0x46, 0xa2, 0xfd, 0xa8, 0x11, 0x8b, 0x20, 0x48, 0x39, 0xb9, 0x23, 0xeb, 0x0c, 0x45, + 0xcb, 0x67, 0xc0, 0xab, 0x60, 0x59, 0xd7, 0xfe, 0x1e, 0x76, 0x19, 0xb2, 0xfc, 0x54, 0x71, 0x27, + 0x24, 0x68, 0x17, 0x26, 0xda, 0x6c, 0xca, 0x45, 0xf4, 0x64, 0x31, 0x6f, 0x2f, 0x0d, 0x28, 0xd5, + 0xde, 0xa7, 0x07, 0x8d, 0xd2, 0x3a, 0x31, 0x71, 0xa1, 0xa6, 0x93, 0xc3, 0x26, 0x75, 0xfb, 0x07, + 0x67, 0xd8, 0x99, 0x5b, 0xe7, 0xa2, 0xea, 0x88, 0xb0, 0xf8, 0x15, 0x7c, 0xf9, 0x5c, 0xbe, 0xce, + 0x24, 0xf9, 0x22, 0x61, 0x35, 0x8c, 0x65, 0x5d, 0xf4, 0x26, 0x7b, 0x9b, 0xe6, 0x07, 0x5d, 0xbf, + 0x34, 0xc1, 0x1c, 0xcb, 0x78, 0x86, 0x16, 0x15, 0xb1, 0x46, 0x04, 0xdd, 0x86, 0x09, 0x91, 0xce, + 0x48, 0x28, 0xc5, 0x8a, 0x86, 0xd2, 0x63, 0x02, 0xeb, 0xc0, 0xa3, 0x74, 0x01, 0x36, 0x2b, 0xa3, + 0x16, 0x5c, 0xd4, 0x72, 0xfb, 0xdd, 0x08, 0x1d, 0xf6, 0x5e, 0xe9, 0xb2, 0x4d, 0xa4, 0x9d, 0x9b, + 0x4f, 0x1e, 0x1e, 0x54, 0x2e, 0x6e, 0xf4, 0x42, 0xc4, 0xbd, 0xe9, 0xa0, 0x3b, 0x70, 0x8e, 0x3b, + 0xd6, 0x55, 0x89, 0xd3, 0xf4, 0x5c, 0x5f, 0x1d, 0xcc, 0x7c, 0x1d, 0x5e, 0x38, 0x3c, 0xa8, 0x9c, + 0x5b, 0xc8, 0x42, 0xc0, 0xd9, 0xf5, 0xd0, 0x67, 0xa1, 0xdc, 0xf4, 0x23, 0x31, 0x06, 0xc3, 0x46, + 0xda, 0xca, 0x72, 0x75, 0xbd, 0xae, 0xbe, 0x3f, 0xf9, 0x83, 0x93, 0x0a, 0xa8, 0xc5, 0x15, 0x63, + 0x4a, 0x0e, 0x1d, 0xc9, 0x4f, 0x51, 0x2e, 0x96, 0x84, 0xe1, 0x5a, 0xc3, 0x35, 0xc2, 0xca, 0x34, + 0xd5, 0xf0, 0xba, 0x31, 0x08, 0xa3, 0x37, 0x00, 0x51, 0x46, 0xcd, 0x6d, 0x90, 0x85, 0x06, 0x0b, + 0x62, 0xcd, 0xf4, 0x88, 0xa3, 0x86, 0x2b, 0x03, 0xaa, 0x77, 0x61, 0xe0, 0x8c, 0x5a, 0xe8, 0x26, + 0x3d, 0xc8, 0xf4, 0x52, 0x61, 0x62, 0x2b, 0x99, 0xfb, 0xd9, 0x2a, 0x69, 0x87, 0xa4, 0xe1, 0xc4, + 0xa4, 0x69, 0x52, 0xc4, 0xa9, 0x7a, 0xf4, 0x2e, 0x55, 0xf9, 0x6c, 0xc0, 0x8c, 0x54, 0xd1, 0x9d, + 0xd3, 0x86, 0xca, 0xc5, 0xdb, 0x41, 0x14, 0xaf, 0x93, 0xf8, 0x7e, 0x10, 0xee, 0x88, 0xc0, 0x60, + 0x49, 0x8c, 0xca, 0x04, 0x84, 0x75, 0x3c, 0xca, 0x07, 0xb3, 0xc7, 0xe1, 0xd5, 0x2a, 0x7b, 0xa1, + 0x1b, 0x4d, 0xf6, 0xc9, 0x4d, 0x5e, 0x8c, 0x25, 0x5c, 0xa2, 0xae, 0xd6, 0x96, 0xd8, 0x6b, 0x5b, + 0x0a, 0x75, 0xb5, 0xb6, 0x84, 0x25, 0x1c, 0x91, 0xee, 0x94, 0xa0, 0x93, 0xf9, 0x5a, 0xcd, 0xee, + 0xeb, 0x60, 0xc0, 0xac, 0xa0, 0x3e, 0x4c, 0xab, 0x64, 0xa4, 0x3c, 0x62, 0x5a, 0x34, 0x3b, 0xc5, + 0x16, 0xc9, 0xe0, 0xe1, 0xd6, 0x94, 0x9e, 0x78, 0x35, 0x45, 0x09, 0x77, 0xd1, 0x36, 0x62, 0x87, + 0x4c, 0xf7, 0xcd, 0x47, 0x74, 0x0d, 0xca, 0x51, 0x67, 0xb3, 0x19, 0xec, 0x3a, 0xae, 0xcf, 0x1e, + 0xc7, 0x34, 0x26, 0xab, 0x2e, 0x01, 0x38, 0xc1, 0x41, 0x2b, 0x30, 0xea, 0x48, 0x25, 0x30, 0xca, + 0x0f, 0x26, 0xa0, 0x54, 0xbf, 0xdc, 0xbf, 0x56, 0xaa, 0x7d, 0x55, 0x5d, 0xf4, 0x1a, 0x4c, 0x08, + 0x77, 0x2a, 0x1e, 0x62, 0x81, 0x3d, 0x5e, 0x69, 0xf6, 0xf2, 0x75, 0x1d, 0x88, 0x4d, 0x5c, 0xf4, + 0x45, 0x98, 0xa4, 0x54, 0x92, 0x83, 0x6d, 0xf6, 0xec, 0x20, 0x27, 0xa2, 0x96, 0x67, 0x42, 0xaf, + 0x8c, 0x53, 0xc4, 0x50, 0x13, 0x9e, 0x70, 0x3a, 0x71, 0xc0, 0x14, 0xe9, 0xe6, 0xfa, 0xdf, 0x08, + 0x76, 0x88, 0xcf, 0xde, 0xb0, 0x46, 0x17, 0x2f, 0x1f, 0x1e, 0x54, 0x9e, 0x58, 0xe8, 0x81, 0x87, + 0x7b, 0x52, 0x41, 0x77, 0x61, 0x2c, 0x0e, 0x3c, 0x66, 0xb9, 0x4e, 0x59, 0x89, 0xf3, 0xf9, 0xb1, + 0x77, 0x36, 0x14, 0x9a, 0xae, 0x44, 0x52, 0x55, 0xb1, 0x4e, 0x07, 0x6d, 0xf0, 0x3d, 0xc6, 0xa2, + 0x92, 0x92, 0x68, 0xf6, 0xb1, 0xfc, 0x81, 0x51, 0xc1, 0x4b, 0xcd, 0x2d, 0x28, 0x6a, 0x62, 0x9d, + 0x0c, 0xba, 0x01, 0x33, 0xed, 0xd0, 0x0d, 0xd8, 0xc2, 0x56, 0x8f, 0x18, 0xb3, 0x66, 0x6a, 0x81, + 0x5a, 0x1a, 0x01, 0x77, 0xd7, 0xa1, 0x42, 0xa6, 0x2c, 0x9c, 0xbd, 0xc0, 0xf3, 0x54, 0x71, 0xc6, + 0x9b, 0x97, 0x61, 0x05, 0x45, 0x6b, 0xec, 0x5c, 0xe6, 0xe2, 0xe0, 0xec, 0x5c, 0x7e, 0x10, 0x06, + 0x5d, 0x6c, 0xe4, 0xfc, 0x92, 0xfa, 0x8b, 0x13, 0x0a, 0xf4, 0xde, 0x88, 0xb6, 0x9d, 0x90, 0xd4, + 0xc2, 0xa0, 0x41, 0x78, 0x67, 0xb8, 0xd1, 0xfc, 0xe3, 0x3c, 0x78, 0x22, 0xbd, 0x37, 0xea, 0x59, + 0x08, 0x38, 0xbb, 0x1e, 0x6a, 0x6a, 0xe9, 0x99, 0x29, 0x1b, 0x1a, 0xcd, 0x3e, 0xd1, 0xc3, 0xcc, + 0x28, 0xc5, 0xb3, 0x26, 0x6b, 0xd1, 0x28, 0x8e, 0x70, 0x8a, 0xe6, 0xdc, 0xb7, 0xc3, 0x4c, 0xd7, + 0x7d, 0x71, 0xac, 0xb8, 0xdd, 0x7f, 0x32, 0x04, 0x65, 0xa5, 0x0a, 0x47, 0xd7, 0xcc, 0x17, 0x8e, + 0x0b, 0xe9, 0x17, 0x8e, 0x51, 0xca, 0x91, 0xeb, 0x8f, 0x1a, 0x1b, 0x86, 0x51, 0x5c, 0x21, 0x3f, + 0x4b, 0x96, 0xce, 0x53, 0xf7, 0xf5, 0x80, 0xd3, 0x34, 0x1b, 0xc5, 0x81, 0x9f, 0x4a, 0x4a, 0x3d, + 0x95, 0x25, 0x03, 0x26, 0xa9, 0xa5, 0xc2, 0x7f, 0x3b, 0x68, 0xae, 0xd6, 0xd2, 0x59, 0x1b, 0x6b, + 0xb4, 0x10, 0x73, 0x18, 0x13, 0xdf, 0x28, 0x73, 0xc3, 0xc4, 0xb7, 0x91, 0x87, 0x14, 0xdf, 0x24, + 0x01, 0x9c, 0xd0, 0x42, 0x1e, 0xcc, 0x34, 0xcc, 0x84, 0x9b, 0xca, 0xeb, 0xed, 0xa9, 0xbe, 0xa9, + 0x2f, 0x3b, 0x5a, 0x76, 0xb3, 0xa5, 0x34, 0x15, 0xdc, 0x4d, 0x18, 0xbd, 0x06, 0xa3, 0xef, 0x05, + 0x11, 0xdb, 0x7c, 0xe2, 0x86, 0x97, 0xde, 0x41, 0xa3, 0x6f, 0xde, 0xa9, 0xb3, 0xf2, 0xa3, 0x83, + 0xca, 0x58, 0x2d, 0x68, 0xca, 0xbf, 0x58, 0x55, 0x40, 0x0f, 0xe0, 0x9c, 0x71, 0x2e, 0xaa, 0xee, + 0xc2, 0xe0, 0xdd, 0xbd, 0x28, 0x9a, 0x3b, 0xb7, 0x9a, 0x45, 0x09, 0x67, 0x37, 0x40, 0x0f, 0x1b, + 0x3f, 0x10, 0xc9, 0x6a, 0x25, 0x17, 0xc1, 0x98, 0x85, 0xb2, 0xee, 0x1b, 0x9e, 0x42, 0xc0, 0xdd, + 0x75, 0xec, 0xaf, 0xf1, 0x97, 0x03, 0xa1, 0x5f, 0x24, 0x51, 0xc7, 0x3b, 0x8d, 0x5c, 0x48, 0xcb, + 0x86, 0xea, 0xf3, 0xa1, 0x5f, 0xa7, 0x7e, 0xd3, 0x62, 0xaf, 0x53, 0x1b, 0x64, 0xb7, 0xed, 0x51, + 0x29, 0xf7, 0xd1, 0x77, 0xfc, 0x4d, 0x18, 0x8d, 0x45, 0x6b, 0xbd, 0xd2, 0x37, 0x69, 0x9d, 0x62, + 0x2f, 0x74, 0x8a, 0xbf, 0x90, 0xa5, 0x58, 0x91, 0xb1, 0xff, 0x29, 0x9f, 0x01, 0x09, 0x39, 0x05, + 0x35, 0x54, 0xd5, 0x54, 0x43, 0x55, 0xfa, 0x7c, 0x41, 0x8e, 0x3a, 0xea, 0x9f, 0x98, 0xfd, 0x66, + 0xa2, 0xdc, 0x47, 0xfd, 0x59, 0xd4, 0xfe, 0x31, 0x0b, 0xce, 0x66, 0xd9, 0x11, 0x51, 0x9e, 0x90, + 0x0b, 0x92, 0xea, 0x99, 0x58, 0x8d, 0xe0, 0x3d, 0x51, 0x8e, 0x15, 0xc6, 0xc0, 0x99, 0x11, 0x8e, + 0x17, 0x3e, 0xed, 0x0e, 0x4c, 0xd4, 0x42, 0xa2, 0xdd, 0x01, 0xaf, 0x73, 0x37, 0x33, 0xde, 0x9f, + 0xe7, 0x8e, 0xed, 0x62, 0x66, 0xff, 0x7c, 0x01, 0xce, 0xf2, 0x77, 0x9e, 0x85, 0xbd, 0xc0, 0x6d, + 0xd6, 0x82, 0xa6, 0xc8, 0x6a, 0xf1, 0x36, 0x8c, 0xb7, 0x35, 0xe9, 0xbf, 0x57, 0x00, 0x27, 0x5d, + 0x4b, 0x90, 0x48, 0x61, 0x7a, 0x29, 0x36, 0x68, 0xa1, 0x26, 0x8c, 0x93, 0x3d, 0xb7, 0xa1, 0x1e, + 0x0b, 0x0a, 0xc7, 0xbe, 0x1b, 0x54, 0x2b, 0xcb, 0x1a, 0x1d, 0x6c, 0x50, 0x7d, 0x04, 0x89, 0xce, + 0xec, 0x1f, 0xb7, 0xe0, 0xb1, 0x9c, 0x70, 0x4f, 0xb4, 0xb9, 0xfb, 0xec, 0x45, 0x4d, 0xe4, 0x4c, + 0x52, 0xcd, 0xf1, 0x77, 0x36, 0x2c, 0xa0, 0xe8, 0xf3, 0x00, 0xfc, 0x9d, 0x8c, 0x0a, 0x25, 0xfd, + 0xe2, 0xe2, 0x18, 0x21, 0x3d, 0xb4, 0x50, 0x0c, 0xb2, 0x3e, 0xd6, 0x68, 0xd9, 0x3f, 0x53, 0x84, + 0x21, 0xf6, 0x2e, 0x83, 0x56, 0x60, 0x64, 0x9b, 0x07, 0x37, 0x1e, 0x24, 0x8e, 0x72, 0x22, 0xdd, + 0xf1, 0x02, 0x2c, 0x2b, 0xa3, 0x35, 0x38, 0xc3, 0x83, 0x43, 0x7b, 0x55, 0xe2, 0x39, 0xfb, 0x52, + 0x49, 0xc0, 0xf3, 0x0c, 0xa9, 0xb0, 0x12, 0xab, 0xdd, 0x28, 0x38, 0xab, 0x1e, 0x7a, 0x1d, 0x26, + 0x63, 0x77, 0x97, 0x04, 0x9d, 0x58, 0x52, 0xe2, 0x61, 0xa1, 0x15, 0x1b, 0xb7, 0x61, 0x40, 0x71, + 0x0a, 0x9b, 0x8a, 0x3b, 0xed, 0x2e, 0x75, 0x88, 0x96, 0xb9, 0xdf, 0x54, 0x81, 0x98, 0xb8, 0xcc, + 0x80, 0xa8, 0xc3, 0xcc, 0xa5, 0x36, 0xb6, 0x43, 0x12, 0x6d, 0x07, 0x5e, 0x53, 0xa4, 0xa9, 0x4e, + 0x0c, 0x88, 0x52, 0x70, 0xdc, 0x55, 0x83, 0x52, 0xd9, 0x72, 0x5c, 0xaf, 0x13, 0x92, 0x84, 0xca, + 0xb0, 0x49, 0x65, 0x25, 0x05, 0xc7, 0x5d, 0x35, 0xe8, 0x3a, 0x3a, 0x27, 0xf2, 0x46, 0x4b, 0x67, + 0x77, 0x65, 0x15, 0x36, 0x22, 0xdd, 0x7e, 0x7a, 0x44, 0x7b, 0x11, 0x76, 0x33, 0x2a, 0xf3, 0xb4, + 0xa6, 0xc5, 0x13, 0x0e, 0x3f, 0x92, 0xca, 0xc3, 0x64, 0x2f, 0xfe, 0x3d, 0x0b, 0xce, 0x64, 0x58, + 0x9f, 0xf2, 0xa3, 0xaa, 0xe5, 0x46, 0xb1, 0xca, 0xa5, 0xa2, 0x1d, 0x55, 0xbc, 0x1c, 0x2b, 0x0c, + 0xba, 0x1f, 0xf8, 0x61, 0x98, 0x3e, 0x00, 0x85, 0x75, 0x97, 0x80, 0x1e, 0xef, 0x00, 0x44, 0x97, + 0xa1, 0xd4, 0x89, 0x88, 0x8c, 0xd3, 0xa4, 0xce, 0x6f, 0xa6, 0xd7, 0x65, 0x10, 0xca, 0x9a, 0xb6, + 0x94, 0x4a, 0x55, 0x63, 0x4d, 0xb9, 0x9e, 0x94, 0xc3, 0xec, 0xaf, 0x16, 0xe1, 0x42, 0xae, 0x9d, + 0x39, 0xed, 0xd2, 0x6e, 0xe0, 0xbb, 0x71, 0xa0, 0xde, 0xfc, 0x78, 0xa4, 0x10, 0xd2, 0xde, 0x5e, + 0x13, 0xe5, 0x58, 0x61, 0xa0, 0x2b, 0x32, 0x83, 0x79, 0x3a, 0x5b, 0xcc, 0x62, 0xd5, 0x48, 0x62, + 0x3e, 0x68, 0x26, 0xae, 0xa7, 0xa0, 0xd4, 0x0e, 0x02, 0x2f, 0x7d, 0x18, 0xd1, 0xee, 0x06, 0x81, + 0x87, 0x19, 0x10, 0x7d, 0x42, 0x8c, 0x43, 0xea, 0x91, 0x0b, 0x3b, 0xcd, 0x20, 0xd2, 0x06, 0xe3, + 0x19, 0x18, 0xd9, 0x21, 0xfb, 0xa1, 0xeb, 0xb7, 0xd2, 0x8f, 0x9f, 0xb7, 0x78, 0x31, 0x96, 0x70, + 0x33, 0x59, 0xc2, 0xc8, 0x49, 0xa7, 0xd0, 0x1a, 0xed, 0x7b, 0xb5, 0xfd, 0x50, 0x11, 0xa6, 0xf0, + 0x62, 0xf5, 0x5b, 0x13, 0x71, 0xb7, 0x7b, 0x22, 0x4e, 0x3a, 0x85, 0x56, 0xff, 0xd9, 0xf8, 0x65, + 0x0b, 0xa6, 0x58, 0x40, 0x61, 0x11, 0x9f, 0xc2, 0x0d, 0xfc, 0x53, 0x60, 0xdd, 0x9e, 0x82, 0xa1, + 0x90, 0x36, 0x9a, 0xce, 0x8b, 0xc3, 0x7a, 0x82, 0x39, 0x0c, 0x3d, 0x01, 0x25, 0xd6, 0x05, 0x3a, + 0x79, 0xe3, 0x3c, 0xa5, 0x40, 0xd5, 0x89, 0x1d, 0xcc, 0x4a, 0x99, 0xd3, 0x35, 0x26, 0x6d, 0xcf, + 0xe5, 0x9d, 0x4e, 0x1e, 0x14, 0x3e, 0x1a, 0x4e, 0xd7, 0x99, 0x5d, 0xfb, 0x60, 0x4e, 0xd7, 0xd9, + 0x24, 0x7b, 0x8b, 0x45, 0xff, 0xbd, 0x00, 0x97, 0x32, 0xeb, 0x0d, 0xec, 0x74, 0xdd, 0xbb, 0xf6, + 0xc9, 0xd8, 0xb0, 0x64, 0x9b, 0x96, 0x14, 0x4f, 0xd1, 0xb4, 0xa4, 0x34, 0x28, 0xe7, 0x38, 0x34, + 0x80, 0x2f, 0x74, 0xe6, 0x90, 0x7d, 0x44, 0x7c, 0xa1, 0x33, 0xfb, 0x96, 0x23, 0xd6, 0xfd, 0x59, + 0x21, 0xe7, 0x5b, 0x98, 0x80, 0x77, 0x95, 0x9e, 0x33, 0x0c, 0x18, 0x09, 0x4e, 0x78, 0x9c, 0x9f, + 0x31, 0xbc, 0x0c, 0x2b, 0x28, 0x72, 0x35, 0xaf, 0xe2, 0x42, 0x7e, 0xd6, 0xc4, 0xdc, 0xa6, 0xe6, + 0xcd, 0xf7, 0x1f, 0x35, 0x04, 0x19, 0x1e, 0xc6, 0x6b, 0x9a, 0x50, 0x5e, 0x1c, 0x5c, 0x28, 0x1f, + 0xcf, 0x16, 0xc8, 0xd1, 0x02, 0x4c, 0xed, 0xba, 0x3e, 0xcb, 0x82, 0x6f, 0xb2, 0xa2, 0x2a, 0xc8, + 0xc6, 0x9a, 0x09, 0xc6, 0x69, 0xfc, 0xb9, 0xd7, 0x60, 0xe2, 0xe1, 0xd5, 0x91, 0xdf, 0x2c, 0xc2, + 0xe3, 0x3d, 0xb6, 0x3d, 0x3f, 0xeb, 0x8d, 0x39, 0xd0, 0xce, 0xfa, 0xae, 0x79, 0xa8, 0xc1, 0xd9, + 0xad, 0x8e, 0xe7, 0xed, 0x33, 0xeb, 0x4d, 0xd2, 0x94, 0x18, 0x82, 0x57, 0x7c, 0x42, 0x26, 0x71, + 0x58, 0xc9, 0xc0, 0xc1, 0x99, 0x35, 0xd1, 0x1b, 0x80, 0x02, 0x91, 0xb2, 0xf5, 0x06, 0xf1, 0x85, + 0x56, 0x9d, 0x0d, 0x7c, 0x31, 0xd9, 0x8c, 0x77, 0xba, 0x30, 0x70, 0x46, 0x2d, 0xca, 0xf4, 0xd3, + 0x5b, 0x69, 0x5f, 0x75, 0x2b, 0xc5, 0xf4, 0x63, 0x1d, 0x88, 0x4d, 0x5c, 0x74, 0x03, 0x66, 0x9c, + 0x3d, 0xc7, 0xe5, 0xc1, 0xe7, 0x24, 0x01, 0xce, 0xf5, 0x2b, 0x25, 0xd8, 0x42, 0x1a, 0x01, 0x77, + 0xd7, 0x49, 0xb9, 0x35, 0x0f, 0xe7, 0xbb, 0x35, 0xf7, 0x3e, 0x17, 0xfb, 0xe9, 0x74, 0xed, 0xff, + 0x68, 0xd1, 0xeb, 0x2b, 0x23, 0xed, 0x3a, 0x1d, 0x07, 0xa5, 0x9b, 0xd4, 0x3c, 0x8c, 0xcf, 0x69, + 0xf6, 0x19, 0x09, 0x10, 0x9b, 0xb8, 0x7c, 0x41, 0x44, 0x89, 0x8b, 0x8b, 0xc1, 0xba, 0x8b, 0x10, + 0x02, 0x0a, 0x03, 0x7d, 0x01, 0x46, 0x9a, 0xee, 0x9e, 0x1b, 0x05, 0xa1, 0xd8, 0x2c, 0xc7, 0x74, + 0x14, 0x48, 0xce, 0xc1, 0x2a, 0x27, 0x83, 0x25, 0x3d, 0xfb, 0x87, 0x0a, 0x30, 0x21, 0x5b, 0x7c, + 0xb3, 0x13, 0xc4, 0xce, 0x29, 0x5c, 0xcb, 0x37, 0x8c, 0x6b, 0xf9, 0x13, 0xbd, 0xe2, 0x28, 0xb0, + 0x2e, 0xe5, 0x5e, 0xc7, 0x77, 0x52, 0xd7, 0xf1, 0xd3, 0xfd, 0x49, 0xf5, 0xbe, 0x86, 0xff, 0x99, + 0x05, 0x33, 0x06, 0xfe, 0x29, 0xdc, 0x06, 0x2b, 0xe6, 0x6d, 0xf0, 0x64, 0xdf, 0x6f, 0xc8, 0xb9, + 0x05, 0xbe, 0xaf, 0x98, 0xea, 0x3b, 0x3b, 0xfd, 0xdf, 0x83, 0xd2, 0xb6, 0x13, 0x36, 0x7b, 0xc5, + 0x6b, 0xed, 0xaa, 0x34, 0x7f, 0xd3, 0x09, 0x9b, 0xfc, 0x0c, 0x7f, 0x4e, 0x25, 0x7a, 0x74, 0xc2, + 0x66, 0x5f, 0x8f, 0x2e, 0xd6, 0x14, 0x7a, 0x15, 0x86, 0xa3, 0x46, 0xd0, 0x56, 0xf6, 0x96, 0x97, + 0x79, 0x12, 0x48, 0x5a, 0x72, 0x74, 0x50, 0x41, 0x66, 0x73, 0xb4, 0x18, 0x0b, 0x7c, 0xf4, 0x36, + 0x4c, 0xb0, 0x5f, 0xca, 0xee, 0xa0, 0x98, 0x9f, 0x25, 0xa0, 0xae, 0x23, 0x72, 0xf3, 0x15, 0xa3, + 0x08, 0x9b, 0xa4, 0xe6, 0x5a, 0x50, 0x56, 0x9f, 0xf5, 0x48, 0x3d, 0x71, 0xfe, 0x5d, 0x11, 0xce, + 0x64, 0xac, 0x39, 0x14, 0x19, 0x33, 0xf1, 0xc2, 0x80, 0x4b, 0xf5, 0x03, 0xce, 0x45, 0xc4, 0xa4, + 0xa1, 0xa6, 0x58, 0x5b, 0x03, 0x37, 0x7a, 0x37, 0x22, 0xe9, 0x46, 0x69, 0x51, 0xff, 0x46, 0x69, + 0x63, 0xa7, 0x36, 0xd4, 0xb4, 0x21, 0xd5, 0xd3, 0x47, 0x3a, 0xa7, 0x7f, 0x5c, 0x84, 0xb3, 0x59, + 0xa1, 0x5d, 0xd0, 0x77, 0xa7, 0xb2, 0xc1, 0xbc, 0x34, 0x68, 0x50, 0x18, 0x9e, 0x22, 0x46, 0xe4, + 0x36, 0x9e, 0x37, 0xf3, 0xc3, 0xf4, 0x1d, 0x66, 0xd1, 0x26, 0x73, 0xdf, 0x0c, 0x79, 0x16, 0x1f, + 0x79, 0x7c, 0x7c, 0x7a, 0xe0, 0x0e, 0x88, 0xf4, 0x3f, 0x51, 0xca, 0x7d, 0x53, 0x16, 0xf7, 0x77, + 0xdf, 0x94, 0x2d, 0xcf, 0xb9, 0x30, 0xa6, 0x7d, 0xcd, 0x23, 0x9d, 0xf1, 0x1d, 0x7a, 0x5b, 0x69, + 0xfd, 0x7e, 0xa4, 0xb3, 0xfe, 0xe3, 0x16, 0xa4, 0x8c, 0x1b, 0x95, 0xba, 0xcb, 0xca, 0x55, 0x77, + 0x5d, 0x86, 0x52, 0x18, 0x78, 0x24, 0x9d, 0xa0, 0x05, 0x07, 0x1e, 0xc1, 0x0c, 0x42, 0x31, 0xe2, + 0x44, 0xd9, 0x31, 0xae, 0x0b, 0x72, 0x42, 0x44, 0x7b, 0x0a, 0x86, 0x3c, 0xb2, 0x47, 0xbc, 0x74, + 0xf4, 0xf3, 0xdb, 0xb4, 0x10, 0x73, 0x98, 0xfd, 0xcb, 0x25, 0xb8, 0xd8, 0xd3, 0x01, 0x9a, 0x8a, + 0x43, 0x2d, 0x27, 0x26, 0xf7, 0x9d, 0xfd, 0x74, 0x98, 0xe2, 0x1b, 0xbc, 0x18, 0x4b, 0x38, 0xb3, + 0xf7, 0xe6, 0x61, 0x09, 0x53, 0xca, 0x41, 0x11, 0x8d, 0x50, 0x40, 0x1f, 0x41, 0x5e, 0xf7, 0xeb, + 0x00, 0x51, 0xe4, 0x2d, 0xfb, 0x94, 0xbb, 0x6b, 0x0a, 0x43, 0xf2, 0x24, 0x7c, 0x65, 0xfd, 0xb6, + 0x80, 0x60, 0x0d, 0x0b, 0x55, 0x61, 0xba, 0x1d, 0x06, 0x31, 0xd7, 0xb5, 0x56, 0xb9, 0x99, 0xcf, + 0x90, 0xe9, 0x7b, 0x5a, 0x4b, 0xc1, 0x71, 0x57, 0x0d, 0xf4, 0x32, 0x8c, 0x09, 0x7f, 0xd4, 0x5a, + 0x10, 0x78, 0x42, 0x0d, 0xa4, 0x8c, 0x46, 0xea, 0x09, 0x08, 0xeb, 0x78, 0x5a, 0x35, 0xa6, 0xc0, + 0x1d, 0xc9, 0xac, 0xc6, 0x95, 0xb8, 0x1a, 0x5e, 0x2a, 0xcc, 0xd3, 0xe8, 0x40, 0x61, 0x9e, 0x12, + 0xc5, 0x58, 0x79, 0xe0, 0x37, 0x2b, 0xe8, 0xab, 0x4a, 0xfa, 0x85, 0x12, 0x9c, 0x11, 0x0b, 0xe7, + 0x51, 0x2f, 0x97, 0x47, 0x94, 0x7d, 0xfe, 0x5b, 0x6b, 0xe6, 0xb4, 0xd7, 0xcc, 0x0f, 0x5b, 0x60, + 0xb2, 0x57, 0xe8, 0xff, 0xcb, 0x8d, 0xf3, 0xfe, 0x72, 0x2e, 0xbb, 0xd6, 0x94, 0x17, 0xc8, 0x07, + 0x8c, 0xf8, 0x6e, 0xff, 0x07, 0x0b, 0x9e, 0xec, 0x4b, 0x11, 0x2d, 0x43, 0x99, 0xf1, 0x80, 0x9a, + 0x74, 0xf6, 0xb4, 0x32, 0x03, 0x94, 0x80, 0x1c, 0x96, 0x34, 0xa9, 0x89, 0x96, 0xbb, 0x02, 0xea, + 0x3f, 0x93, 0x11, 0x50, 0xff, 0x9c, 0x31, 0x3c, 0x0f, 0x19, 0x51, 0xff, 0x6b, 0x45, 0x18, 0xe6, + 0x2b, 0xfe, 0x14, 0xc4, 0xb0, 0x15, 0xa1, 0xb7, 0xed, 0x11, 0x47, 0x8a, 0xf7, 0x65, 0xbe, 0xea, + 0xc4, 0x0e, 0x67, 0x13, 0xd4, 0x6d, 0x95, 0x68, 0x78, 0xd1, 0xbc, 0x71, 0x9f, 0xcd, 0xa5, 0x14, + 0x93, 0xc0, 0x69, 0x68, 0xb7, 0xdb, 0x97, 0x00, 0x22, 0x96, 0x68, 0x9e, 0xd2, 0x10, 0x11, 0xc9, + 0x3e, 0xd9, 0xa3, 0xf5, 0xba, 0x42, 0xe6, 0x7d, 0x48, 0x76, 0xba, 0x02, 0x60, 0x8d, 0xe2, 0xdc, + 0x2b, 0x50, 0x56, 0xc8, 0xfd, 0xb4, 0x38, 0xe3, 0x3a, 0x73, 0xf1, 0x39, 0x98, 0x4a, 0xb5, 0x75, + 0x2c, 0x25, 0xd0, 0xaf, 0x58, 0x30, 0xc5, 0xbb, 0xbc, 0xec, 0xef, 0x89, 0x33, 0xf5, 0x7d, 0x38, + 0xeb, 0x65, 0x9c, 0x6d, 0x62, 0x46, 0x07, 0x3f, 0x0b, 0x95, 0xd2, 0x27, 0x0b, 0x8a, 0x33, 0xdb, + 0x40, 0x57, 0xe9, 0xba, 0xa5, 0x67, 0x97, 0xe3, 0x09, 0xdf, 0xa1, 0x71, 0xbe, 0x66, 0x79, 0x19, + 0x56, 0x50, 0xfb, 0x77, 0x2c, 0x98, 0xe1, 0x3d, 0xbf, 0x45, 0xf6, 0xd5, 0x0e, 0xff, 0x30, 0xfb, + 0x2e, 0x72, 0x5c, 0x14, 0x72, 0x72, 0x5c, 0xe8, 0x9f, 0x56, 0xec, 0xf9, 0x69, 0x3f, 0x6f, 0x81, + 0x58, 0x81, 0xa7, 0x20, 0xca, 0x7f, 0xbb, 0x29, 0xca, 0xcf, 0xe5, 0x2f, 0xea, 0x1c, 0x19, 0xfe, + 0x4f, 0x2d, 0x98, 0xe6, 0x08, 0xc9, 0x5b, 0xf2, 0x87, 0x3a, 0x0f, 0x83, 0x24, 0xab, 0x53, 0xd9, + 0xa9, 0xb3, 0x3f, 0xca, 0x98, 0xac, 0x52, 0xcf, 0xc9, 0x6a, 0xca, 0x0d, 0x74, 0x8c, 0x24, 0x8c, + 0xc7, 0x8e, 0x15, 0x6d, 0xff, 0x91, 0x05, 0x88, 0x37, 0x63, 0xb0, 0x3f, 0x94, 0xa9, 0x60, 0xa5, + 0xda, 0x75, 0x91, 0x1c, 0x35, 0x0a, 0x82, 0x35, 0xac, 0x13, 0x19, 0x9e, 0x94, 0x41, 0x40, 0xb1, + 0xbf, 0x41, 0xc0, 0x31, 0x46, 0xf4, 0x6b, 0x25, 0x48, 0x1b, 0xf3, 0xa3, 0x7b, 0x30, 0xde, 0x70, + 0xda, 0xce, 0xa6, 0xeb, 0xb9, 0xb1, 0x4b, 0xa2, 0x5e, 0x96, 0x44, 0x4b, 0x1a, 0x9e, 0x78, 0xea, + 0xd5, 0x4a, 0xb0, 0x41, 0x07, 0xcd, 0x03, 0xb4, 0x43, 0x77, 0xcf, 0xf5, 0x48, 0x8b, 0x69, 0x1c, + 0x98, 0xb7, 0x22, 0x37, 0x8f, 0x91, 0xa5, 0x58, 0xc3, 0xc8, 0x70, 0x3c, 0x2b, 0x3e, 0x3a, 0xc7, + 0xb3, 0xd2, 0x31, 0x1d, 0xcf, 0x86, 0x06, 0x72, 0x3c, 0xc3, 0x70, 0x5e, 0xb2, 0x48, 0xf4, 0xff, + 0x8a, 0xeb, 0x11, 0xc1, 0x17, 0x73, 0x1f, 0xc6, 0xb9, 0xc3, 0x83, 0xca, 0x79, 0x9c, 0x89, 0x81, + 0x73, 0x6a, 0xa2, 0xcf, 0xc3, 0xac, 0xe3, 0x79, 0xc1, 0x7d, 0x35, 0x6a, 0xcb, 0x51, 0xc3, 0xf1, + 0xb8, 0xc6, 0x7e, 0x84, 0x51, 0x7d, 0xe2, 0xf0, 0xa0, 0x32, 0xbb, 0x90, 0x83, 0x83, 0x73, 0x6b, + 0xa7, 0xfc, 0xd6, 0x46, 0xfb, 0xf9, 0xad, 0xd9, 0x3b, 0x70, 0xa6, 0x4e, 0x42, 0x97, 0xa5, 0x88, + 0x6c, 0x26, 0x5b, 0x72, 0x03, 0xca, 0x61, 0xea, 0x10, 0x1a, 0x28, 0xb0, 0x91, 0x16, 0x06, 0x57, + 0x1e, 0x3a, 0x09, 0x21, 0xfb, 0x4f, 0x2c, 0x18, 0x11, 0x0e, 0x05, 0xa7, 0xc0, 0xfb, 0x2c, 0x18, + 0x2a, 0xe8, 0x4a, 0xf6, 0x41, 0xcd, 0x3a, 0x93, 0xab, 0x7c, 0x5e, 0x4d, 0x29, 0x9f, 0x9f, 0xec, + 0x45, 0xa4, 0xb7, 0xda, 0xf9, 0x6f, 0x15, 0x61, 0xd2, 0x74, 0xa6, 0x38, 0x85, 0x21, 0x58, 0x87, + 0x91, 0x48, 0x78, 0xee, 0x14, 0xf2, 0x6d, 0x9f, 0xd3, 0x93, 0x98, 0x18, 0x36, 0x09, 0x5f, 0x1d, + 0x49, 0x24, 0xd3, 0x25, 0xa8, 0xf8, 0x08, 0x5d, 0x82, 0xfa, 0xf9, 0xb3, 0x94, 0x4e, 0xc2, 0x9f, + 0xc5, 0xfe, 0x3a, 0xbb, 0x2c, 0xf4, 0xf2, 0x53, 0xe0, 0x23, 0x6e, 0x98, 0xd7, 0x8a, 0xdd, 0x63, + 0x65, 0x89, 0x4e, 0xe5, 0xf0, 0x13, 0xbf, 0x64, 0xc1, 0xc5, 0x8c, 0xaf, 0xd2, 0x98, 0x8b, 0xe7, + 0x60, 0xd4, 0xe9, 0x34, 0x5d, 0xb5, 0x97, 0xb5, 0x87, 0xa8, 0x05, 0x51, 0x8e, 0x15, 0x06, 0x5a, + 0x82, 0x19, 0xf2, 0xa0, 0xed, 0xf2, 0x97, 0x40, 0xdd, 0xfa, 0xb0, 0xc8, 0x43, 0xbc, 0x2e, 0xa7, + 0x81, 0xb8, 0x1b, 0x5f, 0xb9, 0x43, 0x17, 0x73, 0xdd, 0xa1, 0xff, 0xa1, 0x05, 0x63, 0xa2, 0xdb, + 0xa7, 0x30, 0xda, 0xdf, 0x61, 0x8e, 0xf6, 0xe3, 0x3d, 0x46, 0x3b, 0x67, 0x98, 0xff, 0x4e, 0x41, + 0xf5, 0xb7, 0x16, 0x84, 0xf1, 0x00, 0x4c, 0xcb, 0xab, 0x30, 0xda, 0x0e, 0x83, 0x38, 0x68, 0x04, + 0x9e, 0xe0, 0x59, 0x9e, 0x48, 0xbc, 0xf5, 0x79, 0xf9, 0x91, 0xf6, 0x1b, 0x2b, 0x6c, 0x36, 0x7a, + 0x41, 0x18, 0x0b, 0x3e, 0x21, 0x19, 0xbd, 0x20, 0x8c, 0x31, 0x83, 0xa0, 0x26, 0x40, 0xec, 0x84, + 0x2d, 0x12, 0xd3, 0x32, 0x11, 0xf8, 0x23, 0xff, 0xf0, 0xe8, 0xc4, 0xae, 0x37, 0xef, 0xfa, 0x71, + 0x14, 0x87, 0xf3, 0xab, 0x7e, 0x7c, 0x27, 0xe4, 0x22, 0x90, 0xe6, 0x7e, 0xaf, 0x68, 0x61, 0x8d, + 0xae, 0xf4, 0x91, 0x64, 0x6d, 0x0c, 0x99, 0x4f, 0xda, 0xeb, 0xa2, 0x1c, 0x2b, 0x0c, 0xfb, 0x15, + 0x76, 0x95, 0xb0, 0x01, 0x3a, 0x9e, 0x67, 0xfc, 0x37, 0x46, 0xd5, 0xd0, 0xb2, 0xf7, 0xac, 0xaa, + 0xee, 0x7f, 0xdf, 0xfb, 0xe4, 0xa6, 0x0d, 0xeb, 0x9e, 0x30, 0x89, 0x93, 0x3e, 0xfa, 0xce, 0x2e, + 0x4b, 0x87, 0xe7, 0xfb, 0x5c, 0x01, 0xc7, 0xb0, 0x6d, 0x60, 0x61, 0xa7, 0x59, 0x78, 0xde, 0xd5, + 0x9a, 0x58, 0xe4, 0x5a, 0xd8, 0x69, 0x01, 0xc0, 0x09, 0x0e, 0xba, 0x26, 0x04, 0xe8, 0x92, 0x91, + 0x1d, 0x4e, 0x0a, 0xd0, 0xf2, 0xf3, 0x35, 0x09, 0xfa, 0x05, 0x18, 0x53, 0x59, 0xe2, 0x6a, 0x3c, + 0xd9, 0x96, 0x08, 0x83, 0xb2, 0x9c, 0x14, 0x63, 0x1d, 0x07, 0x6d, 0xc0, 0x54, 0xc4, 0xb5, 0x27, + 0x2a, 0xda, 0x1d, 0xd7, 0x42, 0x7d, 0x52, 0x5a, 0x48, 0xd4, 0x4d, 0xf0, 0x11, 0x2b, 0xe2, 0x47, + 0x87, 0x74, 0x74, 0x4c, 0x93, 0x40, 0xaf, 0xc3, 0xa4, 0xa7, 0xe7, 0x5a, 0xaf, 0x09, 0x25, 0x95, + 0x32, 0x20, 0x36, 0x32, 0xb1, 0xd7, 0x70, 0x0a, 0x9b, 0xf2, 0x3a, 0x7a, 0x89, 0x88, 0xd0, 0xe8, + 0xf8, 0x2d, 0x12, 0x89, 0x1c, 0x57, 0x8c, 0xd7, 0xb9, 0x9d, 0x83, 0x83, 0x73, 0x6b, 0xa3, 0x57, + 0x61, 0x5c, 0x7e, 0xbe, 0xe6, 0xc6, 0x9b, 0x98, 0xa9, 0x6b, 0x30, 0x6c, 0x60, 0xa2, 0xfb, 0x70, + 0x4e, 0xfe, 0xdf, 0x08, 0x9d, 0xad, 0x2d, 0xb7, 0x21, 0xbc, 0xa8, 0xb9, 0xaf, 0xce, 0x82, 0x74, + 0xfe, 0x59, 0xce, 0x42, 0x3a, 0x3a, 0xa8, 0x5c, 0x16, 0xa3, 0x96, 0x09, 0x67, 0x93, 0x98, 0x4d, + 0x1f, 0xad, 0xc1, 0x99, 0x6d, 0xe2, 0x78, 0xf1, 0xf6, 0xd2, 0x36, 0x69, 0xec, 0xc8, 0x4d, 0xc4, + 0x9c, 0x83, 0x35, 0xe3, 0xee, 0x9b, 0xdd, 0x28, 0x38, 0xab, 0x1e, 0x7a, 0x07, 0x66, 0xdb, 0x9d, + 0x4d, 0xcf, 0x8d, 0xb6, 0xd7, 0x83, 0x98, 0x19, 0x65, 0xa8, 0x24, 0x6b, 0xc2, 0x8b, 0x58, 0x39, + 0x46, 0xd7, 0x72, 0xf0, 0x70, 0x2e, 0x05, 0xf4, 0x3e, 0x9c, 0x4b, 0x2d, 0x06, 0xe1, 0xd3, 0x38, + 0x99, 0x1f, 0xef, 0xb6, 0x9e, 0x55, 0x41, 0xf8, 0x28, 0x66, 0x81, 0x70, 0x76, 0x13, 0x1f, 0xcc, + 0x54, 0xe7, 0x3d, 0x5a, 0x59, 0x63, 0xca, 0xd0, 0x97, 0x61, 0x5c, 0x5f, 0x45, 0xe2, 0x82, 0xb9, + 0x92, 0xcd, 0xb3, 0x68, 0xab, 0x8d, 0xb3, 0x74, 0x6a, 0x45, 0xe9, 0x30, 0x6c, 0x50, 0xb4, 0x09, + 0x64, 0x7f, 0x1f, 0xba, 0x0d, 0xa3, 0x0d, 0xcf, 0x25, 0x7e, 0xbc, 0x5a, 0xeb, 0x15, 0x74, 0x63, + 0x49, 0xe0, 0x88, 0x01, 0x13, 0x01, 0x42, 0x79, 0x19, 0x56, 0x14, 0xec, 0xdf, 0x28, 0x40, 0xa5, + 0x4f, 0xb4, 0xd9, 0x94, 0x46, 0xd9, 0x1a, 0x48, 0xa3, 0xbc, 0x20, 0x53, 0xc6, 0xad, 0xa7, 0xc4, + 0xec, 0x54, 0x3a, 0xb8, 0x44, 0xd8, 0x4e, 0xe3, 0x0f, 0x6c, 0xe1, 0xab, 0x2b, 0xa5, 0x4b, 0x7d, + 0x6d, 0xcf, 0x8d, 0xc7, 0xa8, 0xa1, 0xc1, 0x05, 0x91, 0xdc, 0x87, 0x05, 0xfb, 0xeb, 0x05, 0x38, + 0xa7, 0x86, 0xf0, 0x2f, 0xee, 0xc0, 0xdd, 0xed, 0x1e, 0xb8, 0x13, 0x78, 0x96, 0xb1, 0xef, 0xc0, + 0x30, 0x0f, 0x5a, 0x32, 0x00, 0x03, 0xf4, 0x94, 0x19, 0xe1, 0x4a, 0x5d, 0xd3, 0x46, 0x94, 0xab, + 0xbf, 0x62, 0xc1, 0xd4, 0xc6, 0x52, 0xad, 0x1e, 0x34, 0x76, 0x48, 0xbc, 0xc0, 0x19, 0x56, 0x2c, + 0xf8, 0x1f, 0xeb, 0x21, 0xf9, 0x9a, 0x2c, 0x8e, 0xe9, 0x32, 0x94, 0xb6, 0x83, 0x28, 0x4e, 0xbf, + 0xd9, 0xde, 0x0c, 0xa2, 0x18, 0x33, 0x88, 0xfd, 0xbb, 0x16, 0x0c, 0xb1, 0x44, 0xa7, 0xfd, 0xb2, + 0xef, 0x0e, 0xf2, 0x5d, 0xe8, 0x65, 0x18, 0x26, 0x5b, 0x5b, 0xa4, 0x11, 0x8b, 0x59, 0x95, 0x0e, + 0xa5, 0xc3, 0xcb, 0xac, 0x94, 0x5e, 0xfa, 0xac, 0x31, 0xfe, 0x17, 0x0b, 0x64, 0xf4, 0x16, 0x94, + 0x63, 0x77, 0x97, 0x2c, 0x34, 0x9b, 0xe2, 0xd5, 0xeb, 0x21, 0xfc, 0x77, 0x37, 0x24, 0x01, 0x9c, + 0xd0, 0xb2, 0xbf, 0x5a, 0x00, 0x48, 0x5c, 0xef, 0xfb, 0x7d, 0xe2, 0x62, 0xd7, 0x7b, 0xc8, 0x95, + 0x8c, 0xf7, 0x10, 0x94, 0x10, 0xcc, 0x78, 0x0c, 0x51, 0xc3, 0x54, 0x1c, 0x68, 0x98, 0x4a, 0xc7, + 0x19, 0xa6, 0x25, 0x98, 0x49, 0x42, 0x07, 0x98, 0x71, 0x54, 0x98, 0x90, 0xb2, 0x91, 0x06, 0xe2, + 0x6e, 0x7c, 0x9b, 0xc0, 0x65, 0x19, 0xd1, 0x52, 0xde, 0x35, 0xcc, 0xa8, 0xf2, 0x18, 0x89, 0x98, + 0x93, 0x07, 0x9f, 0x42, 0xee, 0x83, 0xcf, 0x4f, 0x59, 0x70, 0x36, 0xdd, 0x0e, 0xf3, 0x5e, 0xfb, + 0x01, 0x0b, 0xce, 0xb1, 0x67, 0x2f, 0xd6, 0x6a, 0xf7, 0x23, 0xdb, 0x4b, 0xd9, 0x21, 0x15, 0x7a, + 0xf7, 0x38, 0xf1, 0x5c, 0x5e, 0xcb, 0x22, 0x8d, 0xb3, 0x5b, 0xb4, 0xbf, 0xdf, 0x02, 0xe1, 0x24, + 0x34, 0xc0, 0xc6, 0x7e, 0x5b, 0xa6, 0x2a, 0x35, 0x02, 0x78, 0x5f, 0xce, 0xf7, 0x9a, 0x12, 0x61, + 0xbb, 0xd5, 0x45, 0x6a, 0x04, 0xeb, 0x36, 0x68, 0xd9, 0x4d, 0x10, 0xd0, 0x2a, 0x61, 0x7a, 0xa2, + 0xfe, 0xbd, 0xb9, 0x0e, 0xd0, 0x64, 0xb8, 0x5a, 0xc2, 0x42, 0x75, 0x6c, 0x57, 0x15, 0x04, 0x6b, + 0x58, 0xf6, 0x8f, 0x14, 0x60, 0x4c, 0x06, 0x8c, 0xee, 0xf8, 0x83, 0x48, 0x73, 0xc7, 0xca, 0x1b, + 0xc3, 0x32, 0x7c, 0x52, 0xc2, 0xb5, 0x44, 0x08, 0x4e, 0x32, 0x7c, 0x4a, 0x00, 0x4e, 0x70, 0xd0, + 0x33, 0x30, 0x12, 0x75, 0x36, 0x19, 0x7a, 0xca, 0xf5, 0xa5, 0xce, 0x8b, 0xb1, 0x84, 0xa3, 0xcf, + 0xc3, 0x34, 0xaf, 0x17, 0x06, 0x6d, 0xa7, 0xc5, 0x95, 0x86, 0x43, 0xca, 0x17, 0x75, 0x7a, 0x2d, + 0x05, 0x3b, 0x3a, 0xa8, 0x9c, 0x4d, 0x97, 0x31, 0x75, 0x73, 0x17, 0x15, 0xfb, 0xcb, 0x80, 0xba, + 0x63, 0x60, 0xa3, 0x37, 0xb8, 0x01, 0x92, 0x1b, 0x92, 0x66, 0x2f, 0x3d, 0xb2, 0xee, 0x3a, 0x29, + 0xcd, 0xcf, 0x79, 0x2d, 0xac, 0xea, 0xdb, 0x7f, 0xad, 0x08, 0xd3, 0x69, 0x47, 0x3a, 0x74, 0x13, + 0x86, 0xf9, 0x05, 0x23, 0xc8, 0xf7, 0x78, 0xa6, 0xd4, 0xdc, 0xef, 0xd8, 0x56, 0x13, 0x77, 0x94, + 0xa8, 0x8f, 0xde, 0x81, 0xb1, 0x66, 0x70, 0xdf, 0xbf, 0xef, 0x84, 0xcd, 0x85, 0xda, 0xaa, 0x58, + 0x97, 0x99, 0x7c, 0x6a, 0x35, 0x41, 0xd3, 0x5d, 0xfa, 0x98, 0x4a, 0x3e, 0x01, 0x61, 0x9d, 0x1c, + 0xda, 0x60, 0x71, 0xfd, 0xb6, 0xdc, 0xd6, 0x9a, 0xd3, 0xee, 0x65, 0x8d, 0xba, 0x24, 0x91, 0x34, + 0xca, 0x13, 0x22, 0xf8, 0x1f, 0x07, 0xe0, 0x84, 0x10, 0xfa, 0x6e, 0x38, 0x13, 0xe5, 0xa8, 0xb6, + 0xf2, 0x52, 0x22, 0xf4, 0xd2, 0xf6, 0x2c, 0x3e, 0x46, 0x25, 0x88, 0x2c, 0x25, 0x58, 0x56, 0x33, + 0xf6, 0x57, 0xce, 0x80, 0xb1, 0x1b, 0x8d, 0xbc, 0x38, 0xd6, 0x09, 0xe5, 0xc5, 0xc1, 0x30, 0x4a, + 0x76, 0xdb, 0xf1, 0x7e, 0xd5, 0x0d, 0x7b, 0x25, 0x56, 0x5b, 0x16, 0x38, 0xdd, 0x34, 0x25, 0x04, + 0x2b, 0x3a, 0xd9, 0xc9, 0x8b, 0x8a, 0x1f, 0x62, 0xf2, 0xa2, 0xd2, 0x29, 0x26, 0x2f, 0x5a, 0x87, + 0x91, 0x96, 0x1b, 0x63, 0xd2, 0x0e, 0x04, 0x6b, 0x97, 0xb9, 0x0e, 0x6f, 0x70, 0x94, 0xee, 0x84, + 0x19, 0x02, 0x80, 0x25, 0x11, 0xf4, 0x86, 0xda, 0x81, 0xc3, 0xf9, 0x92, 0x51, 0xf7, 0x7b, 0x5a, + 0xe6, 0x1e, 0x14, 0xc9, 0x8a, 0x46, 0x1e, 0x36, 0x59, 0xd1, 0x8a, 0x4c, 0x31, 0x34, 0x9a, 0x6f, + 0x3a, 0xce, 0x32, 0x08, 0xf5, 0x49, 0x2c, 0x64, 0x24, 0x63, 0x2a, 0x9f, 0x5c, 0x32, 0xa6, 0xef, + 0xb7, 0xe0, 0x5c, 0x3b, 0x2b, 0x2f, 0x99, 0x48, 0x0c, 0xf4, 0xf2, 0xc0, 0x89, 0xd7, 0x8c, 0x06, + 0x99, 0x88, 0x9c, 0x89, 0x86, 0xb3, 0x9b, 0xa3, 0x03, 0x1d, 0x6e, 0x36, 0x45, 0x36, 0xa1, 0xa7, + 0x72, 0xb2, 0x3a, 0xf5, 0xc8, 0xe5, 0xb4, 0x91, 0x91, 0x41, 0xe8, 0xe3, 0x79, 0x19, 0x84, 0x06, + 0xce, 0x1b, 0xf4, 0x86, 0xca, 0xe7, 0x34, 0x91, 0xbf, 0x94, 0x78, 0xb6, 0xa6, 0xbe, 0x59, 0x9c, + 0xde, 0x50, 0x59, 0x9c, 0x7a, 0xc4, 0x37, 0xe3, 0x39, 0x9a, 0xfa, 0xe6, 0x6e, 0xd2, 0xf2, 0x2f, + 0x4d, 0x9d, 0x4c, 0xfe, 0x25, 0xe3, 0xaa, 0xe1, 0x29, 0x80, 0x9e, 0xed, 0x73, 0xd5, 0x18, 0x74, + 0x7b, 0x5f, 0x36, 0x3c, 0xd7, 0xd4, 0xcc, 0x43, 0xe5, 0x9a, 0xba, 0xa7, 0xe7, 0x6e, 0x42, 0x7d, + 0x92, 0x13, 0x51, 0xa4, 0x01, 0x33, 0x36, 0xdd, 0xd3, 0x2f, 0xc0, 0x33, 0xf9, 0x74, 0xd5, 0x3d, + 0xd7, 0x4d, 0x37, 0xf3, 0x0a, 0xec, 0xca, 0x04, 0x75, 0xf6, 0x74, 0x32, 0x41, 0x9d, 0x3b, 0xf1, + 0x4c, 0x50, 0xe7, 0x4f, 0x21, 0x13, 0xd4, 0x63, 0x1f, 0x6a, 0x26, 0xa8, 0xd9, 0x47, 0x90, 0x09, + 0x6a, 0x3d, 0xc9, 0x04, 0x75, 0x21, 0x7f, 0x4a, 0x32, 0xec, 0x59, 0x73, 0xf2, 0x3f, 0xdd, 0x83, + 0x72, 0x5b, 0x46, 0x7a, 0x10, 0x01, 0xd8, 0xb2, 0x93, 0xd1, 0x66, 0x85, 0x83, 0xe0, 0x53, 0xa2, + 0x40, 0x38, 0x21, 0x45, 0xe9, 0x26, 0xf9, 0xa0, 0x1e, 0xef, 0xa1, 0x04, 0xcd, 0x52, 0x2f, 0xe5, + 0x67, 0x81, 0xb2, 0xff, 0x6a, 0x01, 0x2e, 0xf5, 0x5e, 0xd7, 0x89, 0x6e, 0xaa, 0x96, 0xbc, 0xa5, + 0xa4, 0x74, 0x53, 0x5c, 0xc8, 0x49, 0xb0, 0x06, 0x0e, 0x87, 0x73, 0x03, 0x66, 0x94, 0x21, 0xab, + 0xe7, 0x36, 0xf6, 0xb5, 0x24, 0xb5, 0xca, 0x61, 0xaf, 0x9e, 0x46, 0xc0, 0xdd, 0x75, 0xd0, 0x02, + 0x4c, 0x19, 0x85, 0xab, 0x55, 0x21, 0xcc, 0x28, 0x65, 0x58, 0xdd, 0x04, 0xe3, 0x34, 0xbe, 0xfd, + 0x73, 0x16, 0x3c, 0x96, 0x93, 0x24, 0x61, 0xe0, 0x68, 0x2f, 0x5b, 0x30, 0xd5, 0x36, 0xab, 0xf6, + 0x09, 0x0a, 0x65, 0xa4, 0x62, 0x50, 0x7d, 0x4d, 0x01, 0x70, 0x9a, 0xe8, 0xe2, 0xd5, 0xdf, 0xfa, + 0xfd, 0x4b, 0x1f, 0xfb, 0xed, 0xdf, 0xbf, 0xf4, 0xb1, 0xdf, 0xf9, 0xfd, 0x4b, 0x1f, 0xfb, 0xff, + 0x0f, 0x2f, 0x59, 0xbf, 0x75, 0x78, 0xc9, 0xfa, 0xed, 0xc3, 0x4b, 0xd6, 0xef, 0x1c, 0x5e, 0xb2, + 0x7e, 0xef, 0xf0, 0x92, 0xf5, 0xd5, 0x3f, 0xb8, 0xf4, 0xb1, 0xb7, 0x0b, 0x7b, 0x2f, 0xfc, 0xbf, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x41, 0x99, 0x07, 0x31, 0x7e, 0xe5, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/core/v1/generated.proto b/vendor/k8s.io/api/core/v1/generated.proto index 845db97b1..9efa19621 100644 --- a/vendor/k8s.io/api/core/v1/generated.proto +++ b/vendor/k8s.io/api/core/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,7 +21,6 @@ syntax = 'proto2'; package k8s.io.api.core.v1; -import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; @@ -188,7 +187,7 @@ message CSIPersistentVolumeSource { // Filesystem type to mount. // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // Ex. "ext4", "xfs", "ntfs". // +optional optional string fsType = 4; @@ -298,6 +297,34 @@ message CephFSVolumeSource { optional bool readOnly = 6; } +// Represents a cinder volume resource in Openstack. +// A Cinder volume must exist before mounting to a container. +// The volume must also be in the same region as the kubelet. +// Cinder volumes support ownership management and SELinux relabeling. +message CinderPersistentVolumeSource { + // volume id used to identify the volume in cinder + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + optional string volumeID = 1; + + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + optional string fsType = 2; + + // Optional: Defaults to false (read/write). ReadOnly here will force + // the ReadOnly setting in VolumeMounts. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + optional bool readOnly = 3; + + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + optional SecretReference secretRef = 4; +} + // Represents a cinder volume resource in Openstack. // A Cinder volume must exist before mounting to a container. // The volume must also be in the same region as the kubelet. @@ -319,6 +346,11 @@ message CinderVolumeSource { // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional optional bool readOnly = 3; + + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + optional LocalObjectReference secretRef = 4; } // ClientIPConfig represents the configurations of Client IP based session affinity. @@ -439,6 +471,31 @@ message ConfigMapList { repeated ConfigMap items = 2; } +// ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node. +message ConfigMapNodeConfigSource { + // Namespace is the metadata.namespace of the referenced ConfigMap. + // This field is required in all cases. + optional string namespace = 1; + + // Name is the metadata.name of the referenced ConfigMap. + // This field is required in all cases. + optional string name = 2; + + // UID is the metadata.UID of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + optional string uid = 3; + + // ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + optional string resourceVersion = 4; + + // KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure + // This field is required in all cases. + optional string kubeletConfigKey = 5; +} + // Adapts a ConfigMap into a projected volume. // // The contents of the target ConfigMap's Data field will be presented in a @@ -809,41 +866,6 @@ message DaemonEndpoint { optional int32 Port = 1; } -// DeleteOptions may be provided when deleting an API object -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -// +k8s:openapi-gen=false -message DeleteOptions { - // The duration in seconds before the object should be deleted. Value must be non-negative integer. - // The value zero indicates delete immediately. If this value is nil, the default grace period for the - // specified type will be used. - // Defaults to a per object value if not specified. zero means delete immediately. - // +optional - optional int64 gracePeriodSeconds = 1; - - // Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be - // returned. - // +optional - optional Preconditions preconditions = 2; - - // Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. - // Should the dependent objects be orphaned. If true/false, the "orphan" - // finalizer will be added to/removed from the object's finalizers list. - // Either this field or PropagationPolicy may be set, but not both. - // +optional - optional bool orphanDependents = 3; - - // Whether and how garbage collection will be performed. - // Either this field or OrphanDependents may be set, but not both. - // The default policy is decided by the existing finalizer set in the - // metadata.finalizers and the resource-specific default policy. - // Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - - // allow the garbage collector to delete the dependents in the background; - // 'Foreground' - a cascading policy that deletes all dependents in the - // foreground. - // +optional - optional string propagationPolicy = 4; -} - // Represents downward API info for projecting into a projected volume. // Note that this is identical to a downwardAPI volume source without the default // mode. @@ -1328,6 +1350,10 @@ message GCEPersistentDiskVolumeSource { // Represents a volume that is populated with the contents of a git repository. // Git repo volumes do not support ownership management. // Git repo volumes support SELinux relabeling. +// +// DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an +// EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir +// into the Pod's container. message GitRepoVolumeSource { // Repository URL optional string repository = 1; @@ -1662,43 +1688,6 @@ message List { repeated k8s.io.apimachinery.pkg.runtime.RawExtension items = 2; } -// ListOptions is the query options to a standard REST list call. -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -// +k8s:openapi-gen=false -message ListOptions { - // A selector to restrict the list of returned objects by their labels. - // Defaults to everything. - // +optional - optional string labelSelector = 1; - - // A selector to restrict the list of returned objects by their fields. - // Defaults to everything. - // +optional - optional string fieldSelector = 2; - - // If true, partially initialized resources are included in the response. - // +optional - optional bool includeUninitialized = 6; - - // Watch for changes to the described resources and return them as a stream of - // add, update, and remove notifications. Specify resourceVersion. - // +optional - optional bool watch = 3; - - // When specified with a watch call, shows changes that occur after that particular version of a resource. - // Defaults to changes from the beginning of history. - // When specified for list: - // - if unset, then the result is returned from remote storage based on quorum-read flag; - // - if it's 0, then we simply return what we currently have in cache, no guarantee; - // - if set to non zero, then the result is at least as fresh as given rv. - // +optional - optional string resourceVersion = 4; - - // Timeout for the list/watch call. - // +optional - optional int64 timeoutSeconds = 5; -} - // LoadBalancerIngress represents the status of a load-balancer ingress point: // traffic intended for the service should be sent to an ingress point. message LoadBalancerIngress { @@ -1731,11 +1720,13 @@ message LocalObjectReference { optional string name = 1; } -// Local represents directly-attached storage with node affinity +// Local represents directly-attached storage with node affinity (Beta feature) message LocalVolumeSource { - // The full path to the volume on the node - // For alpha, this path must be a directory - // Once block as a source is supported, then this path can point to a block device + // The full path to the volume on the node. + // It can be either a directory or block device (disk, partition, ...). + // Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. + // Block devices can be represented only by VolumeMode=Block, which also requires the + // BlockVolume alpha feature gate to be enabled. optional string path = 1; } @@ -1885,7 +1876,58 @@ message NodeCondition { // NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil. message NodeConfigSource { - optional ObjectReference configMapRef = 1; + // ConfigMap is a reference to a Node's ConfigMap + optional ConfigMapNodeConfigSource configMap = 2; +} + +// NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource. +message NodeConfigStatus { + // Assigned reports the checkpointed config the node will try to use. + // When Node.Spec.ConfigSource is updated, the node checkpoints the associated + // config payload to local disk, along with a record indicating intended + // config. The node refers to this record to choose its config checkpoint, and + // reports this record in Assigned. Assigned only updates in the status after + // the record has been checkpointed to disk. When the Kubelet is restarted, + // it tries to make the Assigned config the Active config by loading and + // validating the checkpointed payload identified by Assigned. + // +optional + optional NodeConfigSource assigned = 1; + + // Active reports the checkpointed config the node is actively using. + // Active will represent either the current version of the Assigned config, + // or the current LastKnownGood config, depending on whether attempting to use the + // Assigned config results in an error. + // +optional + optional NodeConfigSource active = 2; + + // LastKnownGood reports the checkpointed config the node will fall back to + // when it encounters an error attempting to use the Assigned config. + // The Assigned config becomes the LastKnownGood config when the node determines + // that the Assigned config is stable and correct. + // This is currently implemented as a 10-minute soak period starting when the local + // record of Assigned config is updated. If the Assigned config is Active at the end + // of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is + // reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, + // because the local default config is always assumed good. + // You should not make assumptions about the node's method of determining config stability + // and correctness, as this may change or become configurable in the future. + // +optional + optional NodeConfigSource lastKnownGood = 3; + + // Error describes any problems reconciling the Spec.ConfigSource to the Active config. + // Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned + // record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting + // to load or validate the Assigned config, etc. + // Errors may occur at different points while syncing config. Earlier errors (e.g. download or + // checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across + // Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in + // a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error + // by fixing the config assigned in Spec.ConfigSource. + // You can find additional information for debugging by searching the error message in the Kubelet log. + // Error is a human-readable description of the error state; machines can check whether or not Error + // is empty, but should not rely on the stability of the Error text across Kubelet versions. + // +optional + optional string error = 4; } // NodeDaemonEndpoints lists ports opened by daemons running on the Node. @@ -1947,10 +1989,17 @@ message NodeSelectorRequirement { repeated string values = 3; } -// A null or empty node selector term matches no objects. +// A null or empty node selector term matches no objects. The requirements of +// them are ANDed. +// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. message NodeSelectorTerm { - // Required. A list of node selector requirements. The requirements are ANDed. + // A list of node selector requirements by node's labels. + // +optional repeated NodeSelectorRequirement matchExpressions = 1; + + // A list of node selector requirements by node's fields. + // +optional + repeated NodeSelectorRequirement matchFields = 2; } // NodeSpec describes the attributes that a node is created with. @@ -1959,11 +2008,6 @@ message NodeSpec { // +optional optional string podCIDR = 1; - // External ID of the node assigned by some machine database (e.g. a cloud provider). - // Deprecated. - // +optional - optional string externalID = 2; - // ID of the node assigned by the cloud provider in the format: :// // +optional optional string providerID = 3; @@ -1981,6 +2025,11 @@ message NodeSpec { // The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field // +optional optional NodeConfigSource configSource = 6; + + // Deprecated. Not all kubelets will set this field. Remove field after 1.13. + // see: https://issues.k8s.io/61966 + // +optional + optional string externalID = 2; } // NodeStatus is information about the current status of a node. @@ -2036,6 +2085,10 @@ message NodeStatus { // List of volumes that are attached to the node. // +optional repeated AttachedVolume volumesAttached = 10; + + // Status of the config assigned to the node via the dynamic Kubelet config feature. + // +optional + optional NodeConfigStatus config = 11; } // NodeSystemInfo is a set of ids/uuids to uniquely identify the node. @@ -2085,170 +2138,6 @@ message ObjectFieldSelector { optional string fieldPath = 2; } -// ObjectMeta is metadata that all persisted resources must have, which includes all objects -// users must create. -// DEPRECATED: Use k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta instead - this type will be removed soon. -// +k8s:openapi-gen=false -message ObjectMeta { - // Name must be unique within a namespace. Is required when creating resources, although - // some resources may allow a client to request the generation of an appropriate name - // automatically. Name is primarily intended for creation idempotence and configuration - // definition. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - // +optional - optional string name = 1; - - // GenerateName is an optional prefix, used by the server, to generate a unique - // name ONLY IF the Name field has not been provided. - // If this field is used, the name returned to the client will be different - // than the name passed. This value will also be combined with a unique suffix. - // The provided value has the same validation rules as the Name field, - // and may be truncated by the length of the suffix required to make the value - // unique on the server. - // - // If this field is specified and the generated name exists, the server will - // NOT return a 409 - instead, it will either return 201 Created or 500 with Reason - // ServerTimeout indicating a unique name could not be found in the time allotted, and the client - // should retry (optionally after the time indicated in the Retry-After header). - // - // Applied only if Name is not specified. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency - // +optional - optional string generateName = 2; - - // Namespace defines the space within each name must be unique. An empty namespace is - // equivalent to the "default" namespace, but "default" is the canonical representation. - // Not all objects are required to be scoped to a namespace - the value of this field for - // those objects will be empty. - // - // Must be a DNS_LABEL. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - // +optional - optional string namespace = 3; - - // SelfLink is a URL representing this object. - // Populated by the system. - // Read-only. - // +optional - optional string selfLink = 4; - - // UID is the unique in time and space value for this object. It is typically generated by - // the server on successful creation of a resource and is not allowed to change on PUT - // operations. - // - // Populated by the system. - // Read-only. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - // +optional - optional string uid = 5; - - // An opaque value that represents the internal version of this object that can - // be used by clients to determine when objects have changed. May be used for optimistic - // concurrency, change detection, and the watch operation on a resource or set of resources. - // Clients must treat these values as opaque and passed unmodified back to the server. - // They may only be valid for a particular resource or set of resources. - // - // Populated by the system. - // Read-only. - // Value must be treated as opaque by clients and . - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency - // +optional - optional string resourceVersion = 6; - - // A sequence number representing a specific generation of the desired state. - // Populated by the system. Read-only. - // +optional - optional int64 generation = 7; - - // CreationTimestamp is a timestamp representing the server time when this object was - // created. It is not guaranteed to be set in happens-before order across separate operations. - // Clients may not set this value. It is represented in RFC3339 form and is in UTC. - // - // Populated by the system. - // Read-only. - // Null for lists. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time creationTimestamp = 8; - - // DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This - // field is set by the server when a graceful deletion is requested by the user, and is not - // directly settable by a client. The resource is expected to be deleted (no longer visible - // from resource lists, and not reachable by name) after the time in this field. Once set, - // this value may not be unset or be set further into the future, although it may be shortened - // or the resource may be deleted prior to this time. For example, a user may request that - // a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination - // signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard - // termination signal (SIGKILL) to the container and after cleanup, remove the pod from the - // API. In the presence of network partitions, this object may still exist after this - // timestamp, until an administrator or automated process can determine the resource is - // fully terminated. - // If not set, graceful deletion of the object has not been requested. - // - // Populated by the system when a graceful deletion is requested. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time deletionTimestamp = 9; - - // Number of seconds allowed for this object to gracefully terminate before - // it will be removed from the system. Only set when deletionTimestamp is also set. - // May only be shortened. - // Read-only. - // +optional - optional int64 deletionGracePeriodSeconds = 10; - - // Map of string keys and values that can be used to organize and categorize - // (scope and select) objects. May match selectors of replication controllers - // and services. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - // +optional - map labels = 11; - - // Annotations is an unstructured key value map stored with a resource that may be - // set by external tools to store and retrieve arbitrary metadata. They are not - // queryable and should be preserved when modifying objects. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ - // +optional - map annotations = 12; - - // List of objects depended by this object. If ALL objects in the list have - // been deleted, this object will be garbage collected. If this object is managed by a controller, - // then an entry in this list will point to this controller, with the controller field set to true. - // There cannot be more than one managing controller. - // +optional - // +patchMergeKey=uid - // +patchStrategy=merge - repeated k8s.io.apimachinery.pkg.apis.meta.v1.OwnerReference ownerReferences = 13; - - // An initializer is a controller which enforces some system invariant at object creation time. - // This field is a list of initializers that have not yet acted on this object. If nil or empty, - // this object has been completely initialized. Otherwise, the object is considered uninitialized - // and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to - // observe uninitialized objects. - // - // When an object is created, the system will populate this list with the current set of initializers. - // Only privileged users may set or modify this list. Once it is empty, it may not be modified further - // by any user. - optional k8s.io.apimachinery.pkg.apis.meta.v1.Initializers initializers = 16; - - // Must be empty before the object is deleted from the registry. Each entry - // is an identifier for the responsible component that will remove the entry - // from the list. If the deletionTimestamp of the object is non-nil, entries - // in this list can only be removed. - // +optional - // +patchStrategy=merge - repeated string finalizers = 14; - - // The name of the cluster which the object belongs to. - // This is used to distinguish resources with same name and namespace in different clusters. - // This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. - // +optional - optional string clusterName = 15; -} - // ObjectReference contains enough information to let you inspect or modify the referred object. // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object message ObjectReference { @@ -2502,7 +2391,7 @@ message PersistentVolumeSource { // Cinder represents a cinder volume attached and mounted on kubelets host machine // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional - optional CinderVolumeSource cinder = 8; + optional CinderPersistentVolumeSource cinder = 8; // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime // +optional @@ -2775,7 +2664,6 @@ message PodAttachOptions { // PodCondition contains details for the current condition of this pod. message PodCondition { // Type is the type of the condition. - // Currently only Ready. // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions optional string type = 1; @@ -2944,6 +2832,12 @@ message PodProxyOptions { optional string path = 1; } +// PodReadinessGate contains the reference to a pod condition +message PodReadinessGate { + // ConditionType refers to a condition in the pod's condition list with matching type. + optional string conditionType = 1; +} + // PodSecurityContext holds pod-level security attributes and common container settings. // Some fields are also present in container.securityContext. Field values of // container.securityContext take precedence over field values of PodSecurityContext. @@ -2998,6 +2892,11 @@ message PodSecurityContext { // If unset, the Kubelet will not modify the ownership and permissions of any volume. // +optional optional int64 fsGroup = 5; + + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // +optional + repeated Sysctl sysctls = 7; } // Describes the class of pods that should avoid this node. @@ -3196,12 +3095,36 @@ message PodSpec { // configuration based on DNSPolicy. // +optional optional PodDNSConfig dnsConfig = 26; + + // If specified, all readiness gates will be evaluated for pod readiness. + // A pod is ready when all its containers are ready AND + // all conditions specified in the readiness gates have status equal to "True" + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md + // +optional + repeated PodReadinessGate readinessGates = 28; } // PodStatus represents information about the status of a pod. Status may trail the actual -// state of a system. +// state of a system, especially if the node that hosts the pod cannot contact the control +// plane. message PodStatus { - // Current condition of the pod. + // The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. + // The conditions array, the reason and message fields, and the individual container status + // arrays contain more detail about the pod's status. + // There are five possible phase values: + // + // Pending: The pod has been accepted by the Kubernetes system, but one or more of the + // container images has not been created. This includes time before being scheduled as + // well as time spent downloading images over the network, which could take a while. + // Running: The pod has been bound to a node, and all of the containers have been created. + // At least one container is still running, or is in the process of starting or restarting. + // Succeeded: All containers in the pod have terminated in success, and will not be restarted. + // Failed: All containers in the pod have terminated, and at least one container has + // terminated in failure. The container either exited with non-zero status or was terminated + // by the system. + // Unknown: For some reason the state of the pod could not be obtained, typically due to an + // error in communicating with the host of the pod. + // // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase // +optional optional string phase = 1; @@ -3721,7 +3644,7 @@ message ResourceQuotaList { // ResourceQuotaSpec defines the desired hard limits to enforce for Quota. message ResourceQuotaSpec { - // Hard is the set of desired hard limits for each named resource. + // hard is the set of desired hard limits for each named resource. // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ // +optional map hard = 1; @@ -3730,6 +3653,12 @@ message ResourceQuotaSpec { // If not specified, the quota matches all objects. // +optional repeated string scopes = 2; + + // scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota + // but expressed using ScopeSelectorOperator in combination with possible values. + // For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched. + // +optional + optional ScopeSelector scopeSelector = 3; } // ResourceQuotaStatus defines the enforced hard limits and observed use. @@ -3866,6 +3795,32 @@ message ScaleIOVolumeSource { optional bool readOnly = 10; } +// A scope selector represents the AND of the selectors represented +// by the scoped-resource selector requirements. +message ScopeSelector { + // A list of scope selector requirements by scope of the resources. + // +optional + repeated ScopedResourceSelectorRequirement matchExpressions = 1; +} + +// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator +// that relates the scope name and values. +message ScopedResourceSelectorRequirement { + // The name of the scope that the selector applies to. + optional string scopeName = 1; + + // Represents a scope's relationship to a set of values. + // Valid operators are In, NotIn, Exists, DoesNotExist. + optional string operator = 2; + + // An array of string values. If the operator is In or NotIn, + // the values array must be non-empty. If the operator is Exists or DoesNotExist, + // the values array must be empty. + // This array is replaced during a strategic merge patch. + // +optional + repeated string values = 3; +} + // Secret holds secret data of a certain type. The total bytes of the values in // the Data field must be less than MaxSecretSize bytes. message Secret { @@ -4134,6 +4089,32 @@ message ServiceAccountList { repeated ServiceAccount items = 2; } +// ServiceAccountTokenProjection represents a projected service account token +// volume. This projection can be used to insert a service account token into +// the pods runtime filesystem for use against APIs (Kubernetes API Server or +// otherwise). +message ServiceAccountTokenProjection { + // Audience is the intended audience of the token. A recipient of a token + // must identify itself with an identifier specified in the audience of the + // token, and otherwise should reject the token. The audience defaults to the + // identifier of the apiserver. + // +optional + optional string audience = 1; + + // ExpirationSeconds is the requested duration of validity of the service + // account token. As the token approaches expiration, the kubelet volume + // plugin will proactively rotate the service account token. The kubelet will + // start trying to rotate the token if the token is older than 80 percent of + // its time to live or if the token is older than 24 hours.Defaults to 1 hour + // and must be at least 10 minutes. + // +optional + optional int64 expirationSeconds = 2; + + // Path is the path relative to the mount point of the file to project the + // token into. + optional string path = 3; +} + // ServiceList holds a list of services. message ServiceList { // Standard list metadata. @@ -4300,9 +4281,6 @@ message ServiceSpec { // The primary use case for setting this field is to use a StatefulSet's Headless Service // to propagate SRV records for its Pods without respect to their readiness for purpose // of peer discovery. - // This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints - // when that annotation is deprecated and all clients have been converted to use this - // field. // +optional optional bool publishNotReadyAddresses = 13; @@ -4465,6 +4443,28 @@ message Toleration { optional int64 tolerationSeconds = 5; } +// A topology selector requirement is a selector that matches given label. +// This is an alpha feature and may change in the future. +message TopologySelectorLabelRequirement { + // The label key that the selector applies to. + optional string key = 1; + + // An array of string values. One value must match the label to be selected. + // Each entry in Values is ORed. + repeated string values = 2; +} + +// A topology selector term represents the result of label queries. +// A null or empty topology selector term matches no objects. +// The requirements of them are ANDed. +// It provides a subset of functionality as NodeSelectorTerm. +// This is an alpha feature and may change in the future. +message TopologySelectorTerm { + // A list of topology selector requirements by labels. + // +optional + repeated TopologySelectorLabelRequirement matchLabelExpressions = 1; +} + // Volume represents a named volume in a pod that may be accessed by any container in the pod. message Volume { // Volume's name. @@ -4508,7 +4508,7 @@ message VolumeMount { // mountPropagation determines how mounts are propagated from the host // to container and the other way around. - // When not set, MountPropagationHostToContainer is used. + // When not set, MountPropagationNone is used. // This field is beta in 1.10. // +optional optional string mountPropagation = 5; @@ -4523,13 +4523,20 @@ message VolumeNodeAffinity { // Projection that may be projected along with other supported volume types message VolumeProjection { // information about the secret data to project + // +optional optional SecretProjection secret = 1; // information about the downwardAPI data to project + // +optional optional DownwardAPIProjection downwardAPI = 2; // information about the configMap data to project + // +optional optional ConfigMapProjection configMap = 3; + + // information about the serviceAccountToken data to project + // +optional + optional ServiceAccountTokenProjection serviceAccountToken = 4; } // Represents the source of a volume to mount. @@ -4564,6 +4571,9 @@ message VolumeSource { optional AWSElasticBlockStoreVolumeSource awsElasticBlockStore = 4; // GitRepo represents a git repository at a particular revision. + // DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an + // EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir + // into the Pod's container. // +optional optional GitRepoVolumeSource gitRepo = 5; diff --git a/vendor/k8s.io/api/core/v1/meta.go b/vendor/k8s.io/api/core/v1/meta.go deleted file mode 100644 index 0e3f5d920..000000000 --- a/vendor/k8s.io/api/core/v1/meta.go +++ /dev/null @@ -1,108 +0,0 @@ -/* -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 ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" -) - -func (obj *ObjectMeta) GetObjectMeta() metav1.Object { return obj } - -// Namespace implements metav1.Object for any object with an ObjectMeta typed field. Allows -// fast, direct access to metadata fields for API objects. -func (meta *ObjectMeta) GetNamespace() string { return meta.Namespace } -func (meta *ObjectMeta) SetNamespace(namespace string) { meta.Namespace = namespace } -func (meta *ObjectMeta) GetName() string { return meta.Name } -func (meta *ObjectMeta) SetName(name string) { meta.Name = name } -func (meta *ObjectMeta) GetGenerateName() string { return meta.GenerateName } -func (meta *ObjectMeta) SetGenerateName(generateName string) { meta.GenerateName = generateName } -func (meta *ObjectMeta) GetUID() types.UID { return meta.UID } -func (meta *ObjectMeta) SetUID(uid types.UID) { meta.UID = uid } -func (meta *ObjectMeta) GetResourceVersion() string { return meta.ResourceVersion } -func (meta *ObjectMeta) SetResourceVersion(version string) { meta.ResourceVersion = version } -func (meta *ObjectMeta) GetGeneration() int64 { return meta.Generation } -func (meta *ObjectMeta) SetGeneration(generation int64) { meta.Generation = generation } -func (meta *ObjectMeta) GetSelfLink() string { return meta.SelfLink } -func (meta *ObjectMeta) SetSelfLink(selfLink string) { meta.SelfLink = selfLink } -func (meta *ObjectMeta) GetCreationTimestamp() metav1.Time { return meta.CreationTimestamp } -func (meta *ObjectMeta) SetCreationTimestamp(creationTimestamp metav1.Time) { - meta.CreationTimestamp = creationTimestamp -} -func (meta *ObjectMeta) GetDeletionTimestamp() *metav1.Time { return meta.DeletionTimestamp } -func (meta *ObjectMeta) SetDeletionTimestamp(deletionTimestamp *metav1.Time) { - meta.DeletionTimestamp = deletionTimestamp -} -func (meta *ObjectMeta) GetDeletionGracePeriodSeconds() *int64 { return meta.DeletionGracePeriodSeconds } -func (meta *ObjectMeta) SetDeletionGracePeriodSeconds(deletionGracePeriodSeconds *int64) { - meta.DeletionGracePeriodSeconds = deletionGracePeriodSeconds -} -func (meta *ObjectMeta) GetLabels() map[string]string { return meta.Labels } -func (meta *ObjectMeta) SetLabels(labels map[string]string) { meta.Labels = labels } -func (meta *ObjectMeta) GetAnnotations() map[string]string { return meta.Annotations } -func (meta *ObjectMeta) SetAnnotations(annotations map[string]string) { meta.Annotations = annotations } -func (meta *ObjectMeta) GetInitializers() *metav1.Initializers { return meta.Initializers } -func (meta *ObjectMeta) SetInitializers(initializers *metav1.Initializers) { - meta.Initializers = initializers -} -func (meta *ObjectMeta) GetFinalizers() []string { return meta.Finalizers } -func (meta *ObjectMeta) SetFinalizers(finalizers []string) { meta.Finalizers = finalizers } - -func (meta *ObjectMeta) GetOwnerReferences() []metav1.OwnerReference { - ret := make([]metav1.OwnerReference, len(meta.OwnerReferences)) - for i := 0; i < len(meta.OwnerReferences); i++ { - ret[i].Kind = meta.OwnerReferences[i].Kind - ret[i].Name = meta.OwnerReferences[i].Name - ret[i].UID = meta.OwnerReferences[i].UID - ret[i].APIVersion = meta.OwnerReferences[i].APIVersion - if meta.OwnerReferences[i].Controller != nil { - value := *meta.OwnerReferences[i].Controller - ret[i].Controller = &value - } - if meta.OwnerReferences[i].BlockOwnerDeletion != nil { - value := *meta.OwnerReferences[i].BlockOwnerDeletion - ret[i].BlockOwnerDeletion = &value - } - } - return ret -} - -func (meta *ObjectMeta) SetOwnerReferences(references []metav1.OwnerReference) { - newReferences := make([]metav1.OwnerReference, len(references)) - for i := 0; i < len(references); i++ { - newReferences[i].Kind = references[i].Kind - newReferences[i].Name = references[i].Name - newReferences[i].UID = references[i].UID - newReferences[i].APIVersion = references[i].APIVersion - if references[i].Controller != nil { - value := *references[i].Controller - newReferences[i].Controller = &value - } - if references[i].BlockOwnerDeletion != nil { - value := *references[i].BlockOwnerDeletion - newReferences[i].BlockOwnerDeletion = &value - } - } - meta.OwnerReferences = newReferences -} - -func (meta *ObjectMeta) GetClusterName() string { - return meta.ClusterName -} -func (meta *ObjectMeta) SetClusterName(clusterName string) { - meta.ClusterName = clusterName -} diff --git a/vendor/k8s.io/api/core/v1/register.go b/vendor/k8s.io/api/core/v1/register.go index 526e1320a..1aac0cb41 100644 --- a/vendor/k8s.io/api/core/v1/register.go +++ b/vendor/k8s.io/api/core/v1/register.go @@ -57,7 +57,6 @@ func addKnownTypes(scheme *runtime.Scheme) error { &Endpoints{}, &EndpointsList{}, &Node{}, - &NodeConfigSource{}, &NodeList{}, &NodeProxyOptions{}, &Binding{}, diff --git a/vendor/k8s.io/api/core/v1/resource.go b/vendor/k8s.io/api/core/v1/resource.go index 3bd6fec62..bb8041254 100644 --- a/vendor/k8s.io/api/core/v1/resource.go +++ b/vendor/k8s.io/api/core/v1/resource.go @@ -48,13 +48,6 @@ func (self *ResourceList) Pods() *resource.Quantity { return &resource.Quantity{} } -func (self *ResourceList) NvidiaGPU() *resource.Quantity { - if val, ok := (*self)[ResourceNvidiaGPU]; ok { - return &val - } - return &resource.Quantity{} -} - func (self *ResourceList) StorageEphemeral() *resource.Quantity { if val, ok := (*self)[ResourceEphemeralStorage]; ok { return &val diff --git a/vendor/k8s.io/api/core/v1/types.go b/vendor/k8s.io/api/core/v1/types.go index 8a69833f5..d9f4869fb 100644 --- a/vendor/k8s.io/api/core/v1/types.go +++ b/vendor/k8s.io/api/core/v1/types.go @@ -23,209 +23,6 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" ) -// The comments for the structs and fields can be used from go-restful to -// generate Swagger API documentation for its models. Please read this PR for more -// information on the implementation: https://github.com/emicklei/go-restful/pull/215 -// -// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if -// they are on one line! For multiple line or blocks that you want to ignore use ---. -// Any context after a --- is ignored and not exported to the SwaggerAPI. -// -// The aforementioned methods can be generated by hack/update-generated-swagger-docs.sh - -// Common string formats -// --------------------- -// Many fields in this API have formatting requirements. The commonly used -// formats are defined here. -// -// C_IDENTIFIER: This is a string that conforms to the definition of an "identifier" -// in the C language. This is captured by the following regex: -// [A-Za-z_][A-Za-z0-9_]* -// This defines the format, but not the length restriction, which should be -// specified at the definition of any field of this type. -// -// DNS_LABEL: This is a string, no more than 63 characters long, that conforms -// to the definition of a "label" in RFCs 1035 and 1123. This is captured -// by the following regex: -// [a-z0-9]([-a-z0-9]*[a-z0-9])? -// -// DNS_SUBDOMAIN: This is a string, no more than 253 characters long, that conforms -// to the definition of a "subdomain" in RFCs 1035 and 1123. This is captured -// by the following regex: -// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* -// or more simply: -// DNS_LABEL(\.DNS_LABEL)* -// -// IANA_SVC_NAME: This is a string, no more than 15 characters long, that -// conforms to the definition of IANA service name in RFC 6335. -// It must contains at least one letter [a-z] and it must contains only [a-z0-9-]. -// Hypens ('-') cannot be leading or trailing character of the string -// and cannot be adjacent to other hyphens. - -// ObjectMeta is metadata that all persisted resources must have, which includes all objects -// users must create. -// DEPRECATED: Use k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta instead - this type will be removed soon. -// +k8s:openapi-gen=false -type ObjectMeta struct { - // Name must be unique within a namespace. Is required when creating resources, although - // some resources may allow a client to request the generation of an appropriate name - // automatically. Name is primarily intended for creation idempotence and configuration - // definition. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - // +optional - Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"` - - // GenerateName is an optional prefix, used by the server, to generate a unique - // name ONLY IF the Name field has not been provided. - // If this field is used, the name returned to the client will be different - // than the name passed. This value will also be combined with a unique suffix. - // The provided value has the same validation rules as the Name field, - // and may be truncated by the length of the suffix required to make the value - // unique on the server. - // - // If this field is specified and the generated name exists, the server will - // NOT return a 409 - instead, it will either return 201 Created or 500 with Reason - // ServerTimeout indicating a unique name could not be found in the time allotted, and the client - // should retry (optionally after the time indicated in the Retry-After header). - // - // Applied only if Name is not specified. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency - // +optional - GenerateName string `json:"generateName,omitempty" protobuf:"bytes,2,opt,name=generateName"` - - // Namespace defines the space within each name must be unique. An empty namespace is - // equivalent to the "default" namespace, but "default" is the canonical representation. - // Not all objects are required to be scoped to a namespace - the value of this field for - // those objects will be empty. - // - // Must be a DNS_LABEL. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - // +optional - Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"` - - // SelfLink is a URL representing this object. - // Populated by the system. - // Read-only. - // +optional - SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,4,opt,name=selfLink"` - - // UID is the unique in time and space value for this object. It is typically generated by - // the server on successful creation of a resource and is not allowed to change on PUT - // operations. - // - // Populated by the system. - // Read-only. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - // +optional - UID types.UID `json:"uid,omitempty" protobuf:"bytes,5,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"` - - // An opaque value that represents the internal version of this object that can - // be used by clients to determine when objects have changed. May be used for optimistic - // concurrency, change detection, and the watch operation on a resource or set of resources. - // Clients must treat these values as opaque and passed unmodified back to the server. - // They may only be valid for a particular resource or set of resources. - // - // Populated by the system. - // Read-only. - // Value must be treated as opaque by clients and . - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency - // +optional - ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,6,opt,name=resourceVersion"` - - // A sequence number representing a specific generation of the desired state. - // Populated by the system. Read-only. - // +optional - Generation int64 `json:"generation,omitempty" protobuf:"varint,7,opt,name=generation"` - - // CreationTimestamp is a timestamp representing the server time when this object was - // created. It is not guaranteed to be set in happens-before order across separate operations. - // Clients may not set this value. It is represented in RFC3339 form and is in UTC. - // - // Populated by the system. - // Read-only. - // Null for lists. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - CreationTimestamp metav1.Time `json:"creationTimestamp,omitempty" protobuf:"bytes,8,opt,name=creationTimestamp"` - - // DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This - // field is set by the server when a graceful deletion is requested by the user, and is not - // directly settable by a client. The resource is expected to be deleted (no longer visible - // from resource lists, and not reachable by name) after the time in this field. Once set, - // this value may not be unset or be set further into the future, although it may be shortened - // or the resource may be deleted prior to this time. For example, a user may request that - // a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination - // signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard - // termination signal (SIGKILL) to the container and after cleanup, remove the pod from the - // API. In the presence of network partitions, this object may still exist after this - // timestamp, until an administrator or automated process can determine the resource is - // fully terminated. - // If not set, graceful deletion of the object has not been requested. - // - // Populated by the system when a graceful deletion is requested. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - DeletionTimestamp *metav1.Time `json:"deletionTimestamp,omitempty" protobuf:"bytes,9,opt,name=deletionTimestamp"` - - // Number of seconds allowed for this object to gracefully terminate before - // it will be removed from the system. Only set when deletionTimestamp is also set. - // May only be shortened. - // Read-only. - // +optional - DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty" protobuf:"varint,10,opt,name=deletionGracePeriodSeconds"` - - // Map of string keys and values that can be used to organize and categorize - // (scope and select) objects. May match selectors of replication controllers - // and services. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - // +optional - Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,11,rep,name=labels"` - - // Annotations is an unstructured key value map stored with a resource that may be - // set by external tools to store and retrieve arbitrary metadata. They are not - // queryable and should be preserved when modifying objects. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ - // +optional - Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,rep,name=annotations"` - - // List of objects depended by this object. If ALL objects in the list have - // been deleted, this object will be garbage collected. If this object is managed by a controller, - // then an entry in this list will point to this controller, with the controller field set to true. - // There cannot be more than one managing controller. - // +optional - // +patchMergeKey=uid - // +patchStrategy=merge - OwnerReferences []metav1.OwnerReference `json:"ownerReferences,omitempty" patchStrategy:"merge" patchMergeKey:"uid" protobuf:"bytes,13,rep,name=ownerReferences"` - - // An initializer is a controller which enforces some system invariant at object creation time. - // This field is a list of initializers that have not yet acted on this object. If nil or empty, - // this object has been completely initialized. Otherwise, the object is considered uninitialized - // and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to - // observe uninitialized objects. - // - // When an object is created, the system will populate this list with the current set of initializers. - // Only privileged users may set or modify this list. Once it is empty, it may not be modified further - // by any user. - Initializers *metav1.Initializers `json:"initializers,omitempty" patchStrategy:"merge" protobuf:"bytes,16,rep,name=initializers"` - - // Must be empty before the object is deleted from the registry. Each entry - // is an identifier for the responsible component that will remove the entry - // from the list. If the deletionTimestamp of the object is non-nil, entries - // in this list can only be removed. - // +optional - // +patchStrategy=merge - Finalizers []string `json:"finalizers,omitempty" patchStrategy:"merge" protobuf:"bytes,14,rep,name=finalizers"` - - // The name of the cluster which the object belongs to. - // This is used to distinguish resources with same name and namespace in different clusters. - // This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. - // +optional - ClusterName string `json:"clusterName,omitempty" protobuf:"bytes,15,opt,name=clusterName"` -} - const ( // NamespaceDefault means the object is in the default namespace which is applied when not specified by clients NamespaceDefault string = "default" @@ -273,6 +70,9 @@ type VolumeSource struct { // +optional AWSElasticBlockStore *AWSElasticBlockStoreVolumeSource `json:"awsElasticBlockStore,omitempty" protobuf:"bytes,4,opt,name=awsElasticBlockStore"` // GitRepo represents a git repository at a particular revision. + // DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an + // EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir + // into the Pod's container. // +optional GitRepo *GitRepoVolumeSource `json:"gitRepo,omitempty" protobuf:"bytes,5,opt,name=gitRepo"` // Secret represents a secret that should populate this volume. @@ -405,7 +205,7 @@ type PersistentVolumeSource struct { // Cinder represents a cinder volume attached and mounted on kubelets host machine // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional - Cinder *CinderVolumeSource `json:"cinder,omitempty" protobuf:"bytes,8,opt,name=cinder"` + Cinder *CinderPersistentVolumeSource `json:"cinder,omitempty" protobuf:"bytes,8,opt,name=cinder"` // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime // +optional CephFS *CephFSPersistentVolumeSource `json:"cephfs,omitempty" protobuf:"bytes,9,opt,name=cephfs"` @@ -458,10 +258,6 @@ const ( // MountOptionAnnotation defines mount option annotation used in PVs MountOptionAnnotation = "volume.beta.kubernetes.io/mount-options" - - // AlphaStorageNodeAffinityAnnotation defines node affinity policies for a PersistentVolume. - // Value is a string of the json representation of type NodeAffinity - AlphaStorageNodeAffinityAnnotation = "volume.alpha.kubernetes.io/node-affinity" ) // +genclient @@ -935,6 +731,35 @@ type CinderVolumeSource struct { // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *LocalObjectReference `json:"secretRef,omitempty" protobuf:"bytes,4,opt,name=secretRef"` +} + +// Represents a cinder volume resource in Openstack. +// A Cinder volume must exist before mounting to a container. +// The volume must also be in the same region as the kubelet. +// Cinder volumes support ownership management and SELinux relabeling. +type CinderPersistentVolumeSource struct { + // volume id used to identify the volume in cinder + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + VolumeID string `json:"volumeID" protobuf:"bytes,1,opt,name=volumeID"` + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + FSType string `json:"fsType,omitempty" protobuf:"bytes,2,opt,name=fsType"` + // Optional: Defaults to false (read/write). ReadOnly here will force + // the ReadOnly setting in VolumeMounts. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *SecretReference `json:"secretRef,omitempty" protobuf:"bytes,4,opt,name=secretRef"` } // Represents a Ceph Filesystem mount that lasts the lifetime of a pod @@ -1179,6 +1004,10 @@ type AWSElasticBlockStoreVolumeSource struct { // Represents a volume that is populated with the contents of a git repository. // Git repo volumes do not support ownership management. // Git repo volumes support SELinux relabeling. +// +// DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an +// EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir +// into the Pod's container. type GitRepoVolumeSource struct { // Repository URL Repository string `json:"repository" protobuf:"bytes,1,opt,name=repository"` @@ -1673,6 +1502,30 @@ type ConfigMapProjection struct { Optional *bool `json:"optional,omitempty" protobuf:"varint,4,opt,name=optional"` } +// ServiceAccountTokenProjection represents a projected service account token +// volume. This projection can be used to insert a service account token into +// the pods runtime filesystem for use against APIs (Kubernetes API Server or +// otherwise). +type ServiceAccountTokenProjection struct { + // Audience is the intended audience of the token. A recipient of a token + // must identify itself with an identifier specified in the audience of the + // token, and otherwise should reject the token. The audience defaults to the + // identifier of the apiserver. + //+optional + Audience string `json:"audience,omitempty" protobuf:"bytes,1,rep,name=audience"` + // ExpirationSeconds is the requested duration of validity of the service + // account token. As the token approaches expiration, the kubelet volume + // plugin will proactively rotate the service account token. The kubelet will + // start trying to rotate the token if the token is older than 80 percent of + // its time to live or if the token is older than 24 hours.Defaults to 1 hour + // and must be at least 10 minutes. + //+optional + ExpirationSeconds *int64 `json:"expirationSeconds,omitempty" protobuf:"varint,2,opt,name=expirationSeconds"` + // Path is the path relative to the mount point of the file to project the + // token into. + Path string `json:"path" protobuf:"bytes,3,opt,name=path"` +} + // Represents a projected volume source type ProjectedVolumeSource struct { // list of volume projections @@ -1691,11 +1544,17 @@ type VolumeProjection struct { // all types below are the supported types for projection into the same volume // information about the secret data to project + // +optional Secret *SecretProjection `json:"secret,omitempty" protobuf:"bytes,1,opt,name=secret"` // information about the downwardAPI data to project + // +optional DownwardAPI *DownwardAPIProjection `json:"downwardAPI,omitempty" protobuf:"bytes,2,opt,name=downwardAPI"` // information about the configMap data to project + // +optional ConfigMap *ConfigMapProjection `json:"configMap,omitempty" protobuf:"bytes,3,opt,name=configMap"` + // information about the serviceAccountToken data to project + // +optional + ServiceAccountToken *ServiceAccountTokenProjection `json:"serviceAccountToken,omitempty" protobuf:"bytes,4,opt,name=serviceAccountToken"` } const ( @@ -1720,11 +1579,13 @@ type KeyToPath struct { Mode *int32 `json:"mode,omitempty" protobuf:"varint,3,opt,name=mode"` } -// Local represents directly-attached storage with node affinity +// Local represents directly-attached storage with node affinity (Beta feature) type LocalVolumeSource struct { - // The full path to the volume on the node - // For alpha, this path must be a directory - // Once block as a source is supported, then this path can point to a block device + // The full path to the volume on the node. + // It can be either a directory or block device (disk, partition, ...). + // Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. + // Block devices can be represented only by VolumeMode=Block, which also requires the + // BlockVolume alpha feature gate to be enabled. Path string `json:"path" protobuf:"bytes,1,opt,name=path"` } @@ -1746,7 +1607,7 @@ type CSIPersistentVolumeSource struct { // Filesystem type to mount. // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // Ex. "ext4", "xfs", "ntfs". // +optional FSType string `json:"fsType,omitempty" protobuf:"bytes,4,opt,name=fsType"` @@ -1821,7 +1682,7 @@ type VolumeMount struct { SubPath string `json:"subPath,omitempty" protobuf:"bytes,4,opt,name=subPath"` // mountPropagation determines how mounts are propagated from the host // to container and the other way around. - // When not set, MountPropagationHostToContainer is used. + // When not set, MountPropagationNone is used. // This field is beta in 1.10. // +optional MountPropagation *MountPropagationMode `json:"mountPropagation,omitempty" protobuf:"bytes,5,opt,name=mountPropagation,casttype=MountPropagationMode"` @@ -2451,12 +2312,13 @@ const ( // PodReasonUnschedulable reason in PodScheduled PodCondition means that the scheduler // can't schedule the pod right now, for example due to insufficient resources in the cluster. PodReasonUnschedulable = "Unschedulable" + // ContainersReady indicates whether all containers in the pod are ready. + ContainersReady PodConditionType = "ContainersReady" ) // PodCondition contains details for the current condition of this pod. type PodCondition struct { // Type is the type of the condition. - // Currently only Ready. // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions Type PodConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=PodConditionType"` // Status is the status of the condition. @@ -2527,10 +2389,16 @@ type NodeSelector struct { NodeSelectorTerms []NodeSelectorTerm `json:"nodeSelectorTerms" protobuf:"bytes,1,rep,name=nodeSelectorTerms"` } -// A null or empty node selector term matches no objects. +// A null or empty node selector term matches no objects. The requirements of +// them are ANDed. +// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. type NodeSelectorTerm struct { - //Required. A list of node selector requirements. The requirements are ANDed. - MatchExpressions []NodeSelectorRequirement `json:"matchExpressions" protobuf:"bytes,1,rep,name=matchExpressions"` + // A list of node selector requirements by node's labels. + // +optional + MatchExpressions []NodeSelectorRequirement `json:"matchExpressions,omitempty" protobuf:"bytes,1,rep,name=matchExpressions"` + // A list of node selector requirements by node's fields. + // +optional + MatchFields []NodeSelectorRequirement `json:"matchFields,omitempty" protobuf:"bytes,2,rep,name=matchFields"` } // A node selector requirement is a selector that contains values, a key, and an operator @@ -2563,6 +2431,27 @@ const ( NodeSelectorOpLt NodeSelectorOperator = "Lt" ) +// A topology selector term represents the result of label queries. +// A null or empty topology selector term matches no objects. +// The requirements of them are ANDed. +// It provides a subset of functionality as NodeSelectorTerm. +// This is an alpha feature and may change in the future. +type TopologySelectorTerm struct { + // A list of topology selector requirements by labels. + // +optional + MatchLabelExpressions []TopologySelectorLabelRequirement `json:"matchLabelExpressions,omitempty" protobuf:"bytes,1,rep,name=matchLabelExpressions"` +} + +// A topology selector requirement is a selector that matches given label. +// This is an alpha feature and may change in the future. +type TopologySelectorLabelRequirement struct { + // The label key that the selector applies to. + Key string `json:"key" protobuf:"bytes,1,opt,name=key"` + // An array of string values. One value must match the label to be selected. + // Each entry in Values is ORed. + Values []string `json:"values" protobuf:"bytes,2,rep,name=values"` +} + // Affinity is a group of affinity scheduling rules. type Affinity struct { // Describes node affinity scheduling rules for the pod. @@ -2795,6 +2684,12 @@ const ( TolerationOpEqual TolerationOperator = "Equal" ) +// PodReadinessGate contains the reference to a pod condition +type PodReadinessGate struct { + // ConditionType refers to a condition in the pod's condition list with matching type. + ConditionType PodConditionType `json:"conditionType" protobuf:"bytes,1,opt,name=conditionType,casttype=PodConditionType"` +} + // PodSpec is a description of a pod. type PodSpec struct { // List of volumes that can be mounted by containers belonging to the pod. @@ -2959,6 +2854,13 @@ type PodSpec struct { // configuration based on DNSPolicy. // +optional DNSConfig *PodDNSConfig `json:"dnsConfig,omitempty" protobuf:"bytes,26,opt,name=dnsConfig"` + + // If specified, all readiness gates will be evaluated for pod readiness. + // A pod is ready when all its containers are ready AND + // all conditions specified in the readiness gates have status equal to "True" + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md + // +optional + ReadinessGates []PodReadinessGate `json:"readinessGates,omitempty" protobuf:"bytes,28,opt,name=readinessGates"` } // HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the @@ -3019,6 +2921,10 @@ type PodSecurityContext struct { // If unset, the Kubelet will not modify the ownership and permissions of any volume. // +optional FSGroup *int64 `json:"fsGroup,omitempty" protobuf:"varint,5,opt,name=fsGroup"` + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // +optional + Sysctls []Sysctl `json:"sysctls,omitempty" protobuf:"bytes,7,rep,name=sysctls"` } // PodQOSClass defines the supported qos classes of Pods. @@ -3063,9 +2969,26 @@ type PodDNSConfigOption struct { } // PodStatus represents information about the status of a pod. Status may trail the actual -// state of a system. +// state of a system, especially if the node that hosts the pod cannot contact the control +// plane. type PodStatus struct { - // Current condition of the pod. + // The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. + // The conditions array, the reason and message fields, and the individual container status + // arrays contain more detail about the pod's status. + // There are five possible phase values: + // + // Pending: The pod has been accepted by the Kubernetes system, but one or more of the + // container images has not been created. This includes time before being scheduled as + // well as time spent downloading images over the network, which could take a while. + // Running: The pod has been bound to a node, and all of the containers have been created. + // At least one container is still running, or is in the process of starting or restarting. + // Succeeded: All containers in the pod have terminated in success, and will not be restarted. + // Failed: All containers in the pod have terminated, and at least one container has + // terminated in failure. The container either exited with non-zero status or was terminated + // by the system. + // Unknown: For some reason the state of the pod could not be obtained, typically due to an + // error in communicating with the host of the pod. + // // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase // +optional Phase PodPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=PodPhase"` @@ -3562,9 +3485,6 @@ type ServiceSpec struct { // The primary use case for setting this field is to use a StatefulSet's Headless Service // to propagate SRV records for its Pods without respect to their readiness for purpose // of peer discovery. - // This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints - // when that annotation is deprecated and all clients have been converted to use this - // field. // +optional PublishNotReadyAddresses bool `json:"publishNotReadyAddresses,omitempty" protobuf:"varint,13,opt,name=publishNotReadyAddresses"` // sessionAffinityConfig contains the configurations of session affinity. @@ -3610,6 +3530,7 @@ type ServicePort struct { } // +genclient +// +genclient:skipVerbs=deleteCollection // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Service is a named abstraction of software service (for example, mysql) consisting of local port @@ -3819,10 +3740,6 @@ type NodeSpec struct { // PodCIDR represents the pod IP range assigned to the node. // +optional PodCIDR string `json:"podCIDR,omitempty" protobuf:"bytes,1,opt,name=podCIDR"` - // External ID of the node assigned by some machine database (e.g. a cloud provider). - // Deprecated. - // +optional - ExternalID string `json:"externalID,omitempty" protobuf:"bytes,2,opt,name=externalID"` // ID of the node assigned by the cloud provider in the format: :// // +optional ProviderID string `json:"providerID,omitempty" protobuf:"bytes,3,opt,name=providerID"` @@ -3837,14 +3754,53 @@ type NodeSpec struct { // The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field // +optional ConfigSource *NodeConfigSource `json:"configSource,omitempty" protobuf:"bytes,6,opt,name=configSource"` -} -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + // Deprecated. Not all kubelets will set this field. Remove field after 1.13. + // see: https://issues.k8s.io/61966 + // +optional + DoNotUse_ExternalID string `json:"externalID,omitempty" protobuf:"bytes,2,opt,name=externalID"` +} // NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil. type NodeConfigSource struct { - metav1.TypeMeta `json:",inline"` - ConfigMapRef *ObjectReference `json:"configMapRef,omitempty" protobuf:"bytes,1,opt,name=configMapRef"` + // For historical context, regarding the below kind, apiVersion, and configMapRef deprecation tags: + // 1. kind/apiVersion were used by the kubelet to persist this struct to disk (they had no protobuf tags) + // 2. configMapRef and proto tag 1 were used by the API to refer to a configmap, + // but used a generic ObjectReference type that didn't really have the fields we needed + // All uses/persistence of the NodeConfigSource struct prior to 1.11 were gated by alpha feature flags, + // so there was no persisted data for these fields that needed to be migrated/handled. + + // +k8s:deprecated=kind + // +k8s:deprecated=apiVersion + // +k8s:deprecated=configMapRef,protobuf=1 + + // ConfigMap is a reference to a Node's ConfigMap + ConfigMap *ConfigMapNodeConfigSource `json:"configMap,omitempty" protobuf:"bytes,2,opt,name=configMap"` +} + +// ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node. +type ConfigMapNodeConfigSource struct { + // Namespace is the metadata.namespace of the referenced ConfigMap. + // This field is required in all cases. + Namespace string `json:"namespace" protobuf:"bytes,1,opt,name=namespace"` + + // Name is the metadata.name of the referenced ConfigMap. + // This field is required in all cases. + Name string `json:"name" protobuf:"bytes,2,opt,name=name"` + + // UID is the metadata.UID of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + UID types.UID `json:"uid,omitempty" protobuf:"bytes,3,opt,name=uid"` + + // ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,4,opt,name=resourceVersion"` + + // KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure + // This field is required in all cases. + KubeletConfigKey string `json:"kubeletConfigKey" protobuf:"bytes,5,opt,name=kubeletConfigKey"` } // DaemonEndpoint contains information about a single Daemon endpoint. @@ -3894,6 +3850,53 @@ type NodeSystemInfo struct { Architecture string `json:"architecture" protobuf:"bytes,10,opt,name=architecture"` } +// NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource. +type NodeConfigStatus struct { + // Assigned reports the checkpointed config the node will try to use. + // When Node.Spec.ConfigSource is updated, the node checkpoints the associated + // config payload to local disk, along with a record indicating intended + // config. The node refers to this record to choose its config checkpoint, and + // reports this record in Assigned. Assigned only updates in the status after + // the record has been checkpointed to disk. When the Kubelet is restarted, + // it tries to make the Assigned config the Active config by loading and + // validating the checkpointed payload identified by Assigned. + // +optional + Assigned *NodeConfigSource `json:"assigned,omitempty" protobuf:"bytes,1,opt,name=assigned"` + // Active reports the checkpointed config the node is actively using. + // Active will represent either the current version of the Assigned config, + // or the current LastKnownGood config, depending on whether attempting to use the + // Assigned config results in an error. + // +optional + Active *NodeConfigSource `json:"active,omitempty" protobuf:"bytes,2,opt,name=active"` + // LastKnownGood reports the checkpointed config the node will fall back to + // when it encounters an error attempting to use the Assigned config. + // The Assigned config becomes the LastKnownGood config when the node determines + // that the Assigned config is stable and correct. + // This is currently implemented as a 10-minute soak period starting when the local + // record of Assigned config is updated. If the Assigned config is Active at the end + // of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is + // reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, + // because the local default config is always assumed good. + // You should not make assumptions about the node's method of determining config stability + // and correctness, as this may change or become configurable in the future. + // +optional + LastKnownGood *NodeConfigSource `json:"lastKnownGood,omitempty" protobuf:"bytes,3,opt,name=lastKnownGood"` + // Error describes any problems reconciling the Spec.ConfigSource to the Active config. + // Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned + // record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting + // to load or validate the Assigned config, etc. + // Errors may occur at different points while syncing config. Earlier errors (e.g. download or + // checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across + // Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in + // a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error + // by fixing the config assigned in Spec.ConfigSource. + // You can find additional information for debugging by searching the error message in the Kubelet log. + // Error is a human-readable description of the error state; machines can check whether or not Error + // is empty, but should not rely on the stability of the Error text across Kubelet versions. + // +optional + Error string `json:"error,omitempty" protobuf:"bytes,4,opt,name=error"` +} + // NodeStatus is information about the current status of a node. type NodeStatus struct { // Capacity represents the total resources of a node. @@ -3938,6 +3941,9 @@ type NodeStatus struct { // List of volumes that are attached to the node. // +optional VolumesAttached []AttachedVolume `json:"volumesAttached,omitempty" protobuf:"bytes,10,rep,name=volumesAttached"` + // Status of the config assigned to the node via the dynamic Kubelet config feature. + // +optional + Config *NodeConfigStatus `json:"config,omitempty" protobuf:"bytes,11,opt,name=config"` } type UniqueVolumeName string @@ -4025,8 +4031,6 @@ const ( NodePIDPressure NodeConditionType = "PIDPressure" // NodeNetworkUnavailable means that network for the node is not correctly configured. NodeNetworkUnavailable NodeConditionType = "NetworkUnavailable" - // NodeKubeletConfigOk indicates whether the kubelet is correctly configured - NodeKubeletConfigOk NodeConditionType = "KubeletConfigOk" ) // NodeCondition contains condition information for a node. @@ -4086,8 +4090,6 @@ const ( // Local ephemeral storage, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024) // The resource name for ResourceEphemeralStorage is alpha and it can change across releases. ResourceEphemeralStorage ResourceName = "ephemeral-storage" - // NVIDIA GPU, in devices. Alpha, might change: although fractional and allowing values >1, only one whole device per node is assigned. - ResourceNvidiaGPU ResourceName = "alpha.kubernetes.io/nvidia-gpu" ) const ( @@ -4095,6 +4097,8 @@ const ( ResourceDefaultNamespacePrefix = "kubernetes.io/" // Name prefix for huge page resources (alpha). ResourceHugePagesPrefix = "hugepages-" + // Name prefix for storage resource limits + ResourceAttachableVolumesPrefix = "attachable-volumes-" ) // ResourceList is a set of (resource name, quantity) pairs. @@ -4177,6 +4181,7 @@ const ( // +genclient // +genclient:nonNamespaced +// +genclient:skipVerbs=deleteCollection // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Namespace provides a scope for Names. @@ -4237,95 +4242,6 @@ type Preconditions struct { UID *types.UID `json:"uid,omitempty" protobuf:"bytes,1,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"` } -// DeletionPropagation decides if a deletion will propagate to the dependents of the object, and how the garbage collector will handle the propagation. -type DeletionPropagation string - -const ( - // Orphans the dependents. - DeletePropagationOrphan DeletionPropagation = "Orphan" - // Deletes the object from the key-value store, the garbage collector will delete the dependents in the background. - DeletePropagationBackground DeletionPropagation = "Background" - // The object exists in the key-value store until the garbage collector deletes all the dependents whose ownerReference.blockOwnerDeletion=true from the key-value store. - // API sever will put the "DeletingDependents" finalizer on the object, and sets its deletionTimestamp. - // This policy is cascading, i.e., the dependents will be deleted with Foreground. - DeletePropagationForeground DeletionPropagation = "Foreground" -) - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// DeleteOptions may be provided when deleting an API object -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -// +k8s:openapi-gen=false -type DeleteOptions struct { - metav1.TypeMeta `json:",inline"` - - // The duration in seconds before the object should be deleted. Value must be non-negative integer. - // The value zero indicates delete immediately. If this value is nil, the default grace period for the - // specified type will be used. - // Defaults to a per object value if not specified. zero means delete immediately. - // +optional - GracePeriodSeconds *int64 `json:"gracePeriodSeconds,omitempty" protobuf:"varint,1,opt,name=gracePeriodSeconds"` - - // Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be - // returned. - // +optional - Preconditions *Preconditions `json:"preconditions,omitempty" protobuf:"bytes,2,opt,name=preconditions"` - - // Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. - // Should the dependent objects be orphaned. If true/false, the "orphan" - // finalizer will be added to/removed from the object's finalizers list. - // Either this field or PropagationPolicy may be set, but not both. - // +optional - OrphanDependents *bool `json:"orphanDependents,omitempty" protobuf:"varint,3,opt,name=orphanDependents"` - - // Whether and how garbage collection will be performed. - // Either this field or OrphanDependents may be set, but not both. - // The default policy is decided by the existing finalizer set in the - // metadata.finalizers and the resource-specific default policy. - // Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - - // allow the garbage collector to delete the dependents in the background; - // 'Foreground' - a cascading policy that deletes all dependents in the - // foreground. - // +optional - PropagationPolicy *DeletionPropagation `protobuf:"bytes,4,opt,name=propagationPolicy,casttype=DeletionPropagation"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// ListOptions is the query options to a standard REST list call. -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -// +k8s:openapi-gen=false -type ListOptions struct { - metav1.TypeMeta `json:",inline"` - - // A selector to restrict the list of returned objects by their labels. - // Defaults to everything. - // +optional - LabelSelector string `json:"labelSelector,omitempty" protobuf:"bytes,1,opt,name=labelSelector"` - // A selector to restrict the list of returned objects by their fields. - // Defaults to everything. - // +optional - FieldSelector string `json:"fieldSelector,omitempty" protobuf:"bytes,2,opt,name=fieldSelector"` - // If true, partially initialized resources are included in the response. - // +optional - IncludeUninitialized bool `json:"includeUninitialized,omitempty" protobuf:"varint,6,opt,name=includeUninitialized"` - // Watch for changes to the described resources and return them as a stream of - // add, update, and remove notifications. Specify resourceVersion. - // +optional - Watch bool `json:"watch,omitempty" protobuf:"varint,3,opt,name=watch"` - // When specified with a watch call, shows changes that occur after that particular version of a resource. - // Defaults to changes from the beginning of history. - // When specified for list: - // - if unset, then the result is returned from remote storage based on quorum-read flag; - // - if it's 0, then we simply return what we currently have in cache, no guarantee; - // - if set to non zero, then the result is at least as fresh as given rv. - // +optional - ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,4,opt,name=resourceVersion"` - // Timeout for the list/watch call. - // +optional - TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty" protobuf:"varint,5,opt,name=timeoutSeconds"` -} - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // PodLogOptions is the query options for a Pod's logs REST call. @@ -4810,11 +4726,13 @@ const ( ResourceQuotaScopeBestEffort ResourceQuotaScope = "BestEffort" // Match all pod objects that do not have best effort quality of service ResourceQuotaScopeNotBestEffort ResourceQuotaScope = "NotBestEffort" + // Match all pod objects that have priority class mentioned + ResourceQuotaScopePriorityClass ResourceQuotaScope = "PriorityClass" ) // ResourceQuotaSpec defines the desired hard limits to enforce for Quota. type ResourceQuotaSpec struct { - // Hard is the set of desired hard limits for each named resource. + // hard is the set of desired hard limits for each named resource. // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ // +optional Hard ResourceList `json:"hard,omitempty" protobuf:"bytes,1,rep,name=hard,casttype=ResourceList,castkey=ResourceName"` @@ -4822,8 +4740,48 @@ type ResourceQuotaSpec struct { // If not specified, the quota matches all objects. // +optional Scopes []ResourceQuotaScope `json:"scopes,omitempty" protobuf:"bytes,2,rep,name=scopes,casttype=ResourceQuotaScope"` + // scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota + // but expressed using ScopeSelectorOperator in combination with possible values. + // For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched. + // +optional + ScopeSelector *ScopeSelector `json:"scopeSelector,omitempty" protobuf:"bytes,3,opt,name=scopeSelector"` +} + +// A scope selector represents the AND of the selectors represented +// by the scoped-resource selector requirements. +type ScopeSelector struct { + // A list of scope selector requirements by scope of the resources. + // +optional + MatchExpressions []ScopedResourceSelectorRequirement `json:"matchExpressions,omitempty" protobuf:"bytes,1,rep,name=matchExpressions"` } +// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator +// that relates the scope name and values. +type ScopedResourceSelectorRequirement struct { + // The name of the scope that the selector applies to. + ScopeName ResourceQuotaScope `json:"scopeName" protobuf:"bytes,1,opt,name=scopeName"` + // Represents a scope's relationship to a set of values. + // Valid operators are In, NotIn, Exists, DoesNotExist. + Operator ScopeSelectorOperator `json:"operator" protobuf:"bytes,2,opt,name=operator,casttype=ScopedResourceSelectorOperator"` + // An array of string values. If the operator is In or NotIn, + // the values array must be non-empty. If the operator is Exists or DoesNotExist, + // the values array must be empty. + // This array is replaced during a strategic merge patch. + // +optional + Values []string `json:"values,omitempty" protobuf:"bytes,3,rep,name=values"` +} + +// A scope selector operator is the set of operators that can be used in +// a scope selector requirement. +type ScopeSelectorOperator string + +const ( + ScopeSelectorOpIn ScopeSelectorOperator = "In" + ScopeSelectorOpNotIn ScopeSelectorOperator = "NotIn" + ScopeSelectorOpExists ScopeSelectorOperator = "Exists" + ScopeSelectorOpDoesNotExist ScopeSelectorOperator = "DoesNotExist" +) + // ResourceQuotaStatus defines the enforced hard limits and observed use. type ResourceQuotaStatus struct { // Hard is the set of enforced hard limits for each named resource. @@ -5251,9 +5209,9 @@ const ( // Sysctl defines a kernel parameter to be set type Sysctl struct { // Name of a property to set - Name string `protobuf:"bytes,1,opt,name=name"` + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` // Value of a property to set - Value string `protobuf:"bytes,2,opt,name=value"` + Value string `json:"value" protobuf:"bytes,2,opt,name=value"` } // NodeResources is an object for conveying resource information about a node. diff --git a/vendor/k8s.io/api/core/v1/types_swagger_doc_generated.go b/vendor/k8s.io/api/core/v1/types_swagger_doc_generated.go index 7b41f018a..59f1d1e7d 100644 --- a/vendor/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AWSElasticBlockStoreVolumeSource = map[string]string{ "": "Represents a Persistent Disk resource in AWS.\n\nAn AWS EBS disk must exist before mounting to a container. The disk must also be in the same AWS zone as the kubelet. An AWS EBS disk can only be mounted as read/write once. AWS EBS volumes support ownership management and SELinux relabeling.", "volumeID": "Unique ID of the persistent disk resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", @@ -121,7 +121,7 @@ var map_CSIPersistentVolumeSource = map[string]string{ "driver": "Driver is the name of the driver to use for this volume. Required.", "volumeHandle": "VolumeHandle is the unique volume name returned by the CSI volume plugin’s CreateVolume to refer to the volume on all subsequent calls. Required.", "readOnly": "Optional: The value to pass to ControllerPublishVolumeRequest. Defaults to false (read/write).", - "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\".", "volumeAttributes": "Attributes of the volume to publish.", "controllerPublishSecretRef": "ControllerPublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI ControllerPublishVolume and ControllerUnpublishVolume calls. This field is optional, and may be empty if no secret is required. If the secret object contains more than one secret, all secrets are passed.", "nodeStageSecretRef": "NodeStageSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodeStageVolume and NodeStageVolume and NodeUnstageVolume calls. This field is optional, and may be empty if no secret is required. If the secret object contains more than one secret, all secrets are passed.", @@ -170,11 +170,24 @@ func (CephFSVolumeSource) SwaggerDoc() map[string]string { return map_CephFSVolumeSource } +var map_CinderPersistentVolumeSource = map[string]string{ + "": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "volumeID": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "readOnly": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "secretRef": "Optional: points to a secret object containing parameters used to connect to OpenStack.", +} + +func (CinderPersistentVolumeSource) SwaggerDoc() map[string]string { + return map_CinderPersistentVolumeSource +} + var map_CinderVolumeSource = map[string]string{ - "": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", - "volumeID": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - "readOnly": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "volumeID": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "readOnly": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "secretRef": "Optional: points to a secret object containing parameters used to connect to OpenStack.", } func (CinderVolumeSource) SwaggerDoc() map[string]string { @@ -262,6 +275,19 @@ func (ConfigMapList) SwaggerDoc() map[string]string { return map_ConfigMapList } +var map_ConfigMapNodeConfigSource = map[string]string{ + "": "ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.", + "namespace": "Namespace is the metadata.namespace of the referenced ConfigMap. This field is required in all cases.", + "name": "Name is the metadata.name of the referenced ConfigMap. This field is required in all cases.", + "uid": "UID is the metadata.UID of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status.", + "resourceVersion": "ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status.", + "kubeletConfigKey": "KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure This field is required in all cases.", +} + +func (ConfigMapNodeConfigSource) SwaggerDoc() map[string]string { + return map_ConfigMapNodeConfigSource +} + var map_ConfigMapProjection = map[string]string{ "": "Adapts a ConfigMap into a projected volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a projected volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. Note that this is identical to a configmap volume source without the default mode.", "items": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", @@ -405,18 +431,6 @@ func (DaemonEndpoint) SwaggerDoc() map[string]string { return map_DaemonEndpoint } -var map_DeleteOptions = map[string]string{ - "": "DeleteOptions may be provided when deleting an API object DEPRECATED: This type has been moved to meta/v1 and will be removed soon.", - "gracePeriodSeconds": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", - "preconditions": "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned.", - "orphanDependents": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", - "PropagationPolicy": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", -} - -func (DeleteOptions) SwaggerDoc() map[string]string { - return map_DeleteOptions -} - var map_DownwardAPIProjection = map[string]string{ "": "Represents downward API info for projecting into a projected volume. Note that this is identical to a downwardAPI volume source without the default mode.", "items": "Items is a list of DownwardAPIVolume file", @@ -671,7 +685,7 @@ func (GCEPersistentDiskVolumeSource) SwaggerDoc() map[string]string { } var map_GitRepoVolumeSource = map[string]string{ - "": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "repository": "Repository URL", "revision": "Commit hash for the specified revision.", "directory": "Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name.", @@ -848,20 +862,6 @@ func (LimitRangeSpec) SwaggerDoc() map[string]string { return map_LimitRangeSpec } -var map_ListOptions = map[string]string{ - "": "ListOptions is the query options to a standard REST list call. DEPRECATED: This type has been moved to meta/v1 and will be removed soon.", - "labelSelector": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", - "fieldSelector": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", - "includeUninitialized": "If true, partially initialized resources are included in the response.", - "watch": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", - "resourceVersion": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", - "timeoutSeconds": "Timeout for the list/watch call.", -} - -func (ListOptions) SwaggerDoc() map[string]string { - return map_ListOptions -} - var map_LoadBalancerIngress = map[string]string{ "": "LoadBalancerIngress represents the status of a load-balancer ingress point: traffic intended for the service should be sent to an ingress point.", "ip": "IP is set for load-balancer ingress points that are IP based (typically GCE or OpenStack load-balancers)", @@ -891,8 +891,8 @@ func (LocalObjectReference) SwaggerDoc() map[string]string { } var map_LocalVolumeSource = map[string]string{ - "": "Local represents directly-attached storage with node affinity", - "path": "The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device", + "": "Local represents directly-attached storage with node affinity (Beta feature)", + "path": "The full path to the volume on the node. It can be either a directory or block device (disk, partition, ...). Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. Block devices can be represented only by VolumeMode=Block, which also requires the BlockVolume alpha feature gate to be enabled.", } func (LocalVolumeSource) SwaggerDoc() map[string]string { @@ -995,13 +995,26 @@ func (NodeCondition) SwaggerDoc() map[string]string { } var map_NodeConfigSource = map[string]string{ - "": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.", + "": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.", + "configMap": "ConfigMap is a reference to a Node's ConfigMap", } func (NodeConfigSource) SwaggerDoc() map[string]string { return map_NodeConfigSource } +var map_NodeConfigStatus = map[string]string{ + "": "NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource.", + "assigned": "Assigned reports the checkpointed config the node will try to use. When Node.Spec.ConfigSource is updated, the node checkpoints the associated config payload to local disk, along with a record indicating intended config. The node refers to this record to choose its config checkpoint, and reports this record in Assigned. Assigned only updates in the status after the record has been checkpointed to disk. When the Kubelet is restarted, it tries to make the Assigned config the Active config by loading and validating the checkpointed payload identified by Assigned.", + "active": "Active reports the checkpointed config the node is actively using. Active will represent either the current version of the Assigned config, or the current LastKnownGood config, depending on whether attempting to use the Assigned config results in an error.", + "lastKnownGood": "LastKnownGood reports the checkpointed config the node will fall back to when it encounters an error attempting to use the Assigned config. The Assigned config becomes the LastKnownGood config when the node determines that the Assigned config is stable and correct. This is currently implemented as a 10-minute soak period starting when the local record of Assigned config is updated. If the Assigned config is Active at the end of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, because the local default config is always assumed good. You should not make assumptions about the node's method of determining config stability and correctness, as this may change or become configurable in the future.", + "error": "Error describes any problems reconciling the Spec.ConfigSource to the Active config. Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting to load or validate the Assigned config, etc. Errors may occur at different points while syncing config. Earlier errors (e.g. download or checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error by fixing the config assigned in Spec.ConfigSource. You can find additional information for debugging by searching the error message in the Kubelet log. Error is a human-readable description of the error state; machines can check whether or not Error is empty, but should not rely on the stability of the Error text across Kubelet versions.", +} + +func (NodeConfigStatus) SwaggerDoc() map[string]string { + return map_NodeConfigStatus +} + var map_NodeDaemonEndpoints = map[string]string{ "": "NodeDaemonEndpoints lists ports opened by daemons running on the Node.", "kubeletEndpoint": "Endpoint on which Kubelet is listening.", @@ -1060,8 +1073,9 @@ func (NodeSelectorRequirement) SwaggerDoc() map[string]string { } var map_NodeSelectorTerm = map[string]string{ - "": "A null or empty node selector term matches no objects.", - "matchExpressions": "Required. A list of node selector requirements. The requirements are ANDed.", + "": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", + "matchExpressions": "A list of node selector requirements by node's labels.", + "matchFields": "A list of node selector requirements by node's fields.", } func (NodeSelectorTerm) SwaggerDoc() map[string]string { @@ -1071,11 +1085,11 @@ func (NodeSelectorTerm) SwaggerDoc() map[string]string { var map_NodeSpec = map[string]string{ "": "NodeSpec describes the attributes that a node is created with.", "podCIDR": "PodCIDR represents the pod IP range assigned to the node.", - "externalID": "External ID of the node assigned by some machine database (e.g. a cloud provider). Deprecated.", "providerID": "ID of the node assigned by the cloud provider in the format: ://", "unschedulable": "Unschedulable controls node schedulability of new pods. By default, node is schedulable. More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration", "taints": "If specified, the node's taints.", "configSource": "If specified, the source to get node configuration from The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field", + "externalID": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966", } func (NodeSpec) SwaggerDoc() map[string]string { @@ -1094,6 +1108,7 @@ var map_NodeStatus = map[string]string{ "images": "List of container images on this node", "volumesInUse": "List of attachable volumes in use (mounted) by the node.", "volumesAttached": "List of volumes that are attached to the node.", + "config": "Status of the config assigned to the node via the dynamic Kubelet config feature.", } func (NodeStatus) SwaggerDoc() map[string]string { @@ -1128,30 +1143,6 @@ func (ObjectFieldSelector) SwaggerDoc() map[string]string { return map_ObjectFieldSelector } -var map_ObjectMeta = map[string]string{ - "": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create. DEPRECATED: Use k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta instead - this type will be removed soon.", - "name": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", - "generateName": "GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.\n\nIf this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).\n\nApplied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency", - "namespace": "Namespace defines the space within each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", - "selfLink": "SelfLink is a URL representing this object. Populated by the system. Read-only.", - "uid": "UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.\n\nPopulated by the system. Read-only. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids", - "resourceVersion": "An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.\n\nPopulated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency", - "generation": "A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.", - "creationTimestamp": "CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "deletionTimestamp": "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field. Once set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "deletionGracePeriodSeconds": "Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.", - "labels": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/", - "annotations": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/", - "ownerReferences": "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.", - "initializers": "An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to observe uninitialized objects.\n\nWhen an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user.", - "finalizers": "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed.", - "clusterName": "The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.", -} - -func (ObjectMeta) SwaggerDoc() map[string]string { - return map_ObjectMeta -} - var map_ObjectReference = map[string]string{ "": "ObjectReference contains enough information to let you inspect or modify the referred object.", "kind": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", @@ -1381,7 +1372,7 @@ func (PodAttachOptions) SwaggerDoc() map[string]string { var map_PodCondition = map[string]string{ "": "PodCondition contains details for the current condition of this pod.", - "type": "Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "type": "Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "status": "Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "lastProbeTime": "Last time we probed the condition.", "lastTransitionTime": "Last time the condition transitioned from one status to another.", @@ -1471,6 +1462,15 @@ func (PodProxyOptions) SwaggerDoc() map[string]string { return map_PodProxyOptions } +var map_PodReadinessGate = map[string]string{ + "": "PodReadinessGate contains the reference to a pod condition", + "conditionType": "ConditionType refers to a condition in the pod's condition list with matching type.", +} + +func (PodReadinessGate) SwaggerDoc() map[string]string { + return map_PodReadinessGate +} + var map_PodSecurityContext = map[string]string{ "": "PodSecurityContext holds pod-level security attributes and common container settings. Some fields are also present in container.securityContext. Field values of container.securityContext take precedence over field values of PodSecurityContext.", "seLinuxOptions": "The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.", @@ -1479,6 +1479,7 @@ var map_PodSecurityContext = map[string]string{ "runAsNonRoot": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", "supplementalGroups": "A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container.", "fsGroup": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw ", + "sysctls": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.", } func (PodSecurityContext) SwaggerDoc() map[string]string { @@ -1523,6 +1524,7 @@ var map_PodSpec = map[string]string{ "priorityClassName": "If specified, indicates the pod's priority. \"system-node-critical\" and \"system-cluster-critical\" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.", "priority": "The priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.", "dnsConfig": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.", + "readinessGates": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md", } func (PodSpec) SwaggerDoc() map[string]string { @@ -1530,8 +1532,8 @@ func (PodSpec) SwaggerDoc() map[string]string { } var map_PodStatus = map[string]string{ - "": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system.", - "phase": "Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", + "": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system, especially if the node that hosts the pod cannot contact the control plane.", + "phase": "The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod's status. There are five possible phase values:\n\nPending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.\n\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", "conditions": "Current service state of pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "message": "A human readable message indicating details about why the pod is in this condition.", "reason": "A brief CamelCase message indicating details about why the pod is in this state. e.g. 'Evicted'", @@ -1802,9 +1804,10 @@ func (ResourceQuotaList) SwaggerDoc() map[string]string { } var map_ResourceQuotaSpec = map[string]string{ - "": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", - "hard": "Hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", - "scopes": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", + "": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", + "hard": "hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", + "scopes": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", + "scopeSelector": "scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota but expressed using ScopeSelectorOperator in combination with possible values. For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched.", } func (ResourceQuotaSpec) SwaggerDoc() map[string]string { @@ -1879,6 +1882,26 @@ func (ScaleIOVolumeSource) SwaggerDoc() map[string]string { return map_ScaleIOVolumeSource } +var map_ScopeSelector = map[string]string{ + "": "A scope selector represents the AND of the selectors represented by the scoped-resource selector requirements.", + "matchExpressions": "A list of scope selector requirements by scope of the resources.", +} + +func (ScopeSelector) SwaggerDoc() map[string]string { + return map_ScopeSelector +} + +var map_ScopedResourceSelectorRequirement = map[string]string{ + "": "A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.", + "scopeName": "The name of the scope that the selector applies to.", + "operator": "Represents a scope's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist.", + "values": "An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", +} + +func (ScopedResourceSelectorRequirement) SwaggerDoc() map[string]string { + return map_ScopedResourceSelectorRequirement +} + var map_Secret = map[string]string{ "": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -2010,6 +2033,17 @@ func (ServiceAccountList) SwaggerDoc() map[string]string { return map_ServiceAccountList } +var map_ServiceAccountTokenProjection = map[string]string{ + "": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "audience": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.", + "expirationSeconds": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.", + "path": "Path is the path relative to the mount point of the file to project the token into.", +} + +func (ServiceAccountTokenProjection) SwaggerDoc() map[string]string { + return map_ServiceAccountTokenProjection +} + var map_ServiceList = map[string]string{ "": "ServiceList holds a list of services.", "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", @@ -2055,7 +2089,7 @@ var map_ServiceSpec = map[string]string{ "externalName": "externalName is the external reference that kubedns or equivalent will return as a CNAME record for this service. No proxying will be involved. Must be a valid RFC-1123 hostname (https://tools.ietf.org/html/rfc1123) and requires Type to be ExternalName.", "externalTrafficPolicy": "externalTrafficPolicy denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints. \"Local\" preserves the client source IP and avoids a second hop for LoadBalancer and Nodeport type services, but risks potentially imbalanced traffic spreading. \"Cluster\" obscures the client source IP and may cause a second hop to another node, but should have good overall load-spreading.", "healthCheckNodePort": "healthCheckNodePort specifies the healthcheck nodePort for the service. If not specified, HealthCheckNodePort is created by the service api backend with the allocated nodePort. Will use user-specified nodePort value if specified by the client. Only effects when Type is set to LoadBalancer and ExternalTrafficPolicy is set to Local.", - "publishNotReadyAddresses": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery. This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints when that annotation is deprecated and all clients have been converted to use this field.", + "publishNotReadyAddresses": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery.", "sessionAffinityConfig": "sessionAffinityConfig contains the configurations of session affinity.", } @@ -2109,8 +2143,8 @@ func (StorageOSVolumeSource) SwaggerDoc() map[string]string { var map_Sysctl = map[string]string{ "": "Sysctl defines a kernel parameter to be set", - "Name": "Name of a property to set", - "Value": "Value of a property to set", + "name": "Name of a property to set", + "value": "Value of a property to set", } func (Sysctl) SwaggerDoc() map[string]string { @@ -2152,6 +2186,25 @@ func (Toleration) SwaggerDoc() map[string]string { return map_Toleration } +var map_TopologySelectorLabelRequirement = map[string]string{ + "": "A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.", + "key": "The label key that the selector applies to.", + "values": "An array of string values. One value must match the label to be selected. Each entry in Values is ORed.", +} + +func (TopologySelectorLabelRequirement) SwaggerDoc() map[string]string { + return map_TopologySelectorLabelRequirement +} + +var map_TopologySelectorTerm = map[string]string{ + "": "A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.", + "matchLabelExpressions": "A list of topology selector requirements by labels.", +} + +func (TopologySelectorTerm) SwaggerDoc() map[string]string { + return map_TopologySelectorTerm +} + var map_Volume = map[string]string{ "": "Volume represents a named volume in a pod that may be accessed by any container in the pod.", "name": "Volume's name. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", @@ -2177,7 +2230,7 @@ var map_VolumeMount = map[string]string{ "readOnly": "Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false.", "mountPath": "Path within the container at which the volume should be mounted. Must not contain ':'.", "subPath": "Path within the volume from which the container's volume should be mounted. Defaults to \"\" (volume's root).", - "mountPropagation": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.", + "mountPropagation": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.", } func (VolumeMount) SwaggerDoc() map[string]string { @@ -2194,10 +2247,11 @@ func (VolumeNodeAffinity) SwaggerDoc() map[string]string { } var map_VolumeProjection = map[string]string{ - "": "Projection that may be projected along with other supported volume types", - "secret": "information about the secret data to project", - "downwardAPI": "information about the downwardAPI data to project", - "configMap": "information about the configMap data to project", + "": "Projection that may be projected along with other supported volume types", + "secret": "information about the secret data to project", + "downwardAPI": "information about the downwardAPI data to project", + "configMap": "information about the configMap data to project", + "serviceAccountToken": "information about the serviceAccountToken data to project", } func (VolumeProjection) SwaggerDoc() map[string]string { @@ -2210,7 +2264,7 @@ var map_VolumeSource = map[string]string{ "emptyDir": "EmptyDir represents a temporary directory that shares a pod's lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir", "gcePersistentDisk": "GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", "awsElasticBlockStore": "AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", - "gitRepo": "GitRepo represents a git repository at a particular revision.", + "gitRepo": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "secret": "Secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret", "nfs": "NFS represents an NFS mount on the host that shares a pod's lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", "iscsi": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://releases.k8s.io/HEAD/examples/volumes/iscsi/README.md", diff --git a/vendor/k8s.io/api/core/v1/zz_generated.deepcopy.go b/vendor/k8s.io/api/core/v1/zz_generated.deepcopy.go index ebdcb890d..0501bbcb5 100644 --- a/vendor/k8s.io/api/core/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/core/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -380,9 +380,43 @@ func (in *CephFSVolumeSource) DeepCopy() *CephFSVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CinderPersistentVolumeSource) DeepCopyInto(out *CinderPersistentVolumeSource) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(SecretReference) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CinderPersistentVolumeSource. +func (in *CinderPersistentVolumeSource) DeepCopy() *CinderPersistentVolumeSource { + if in == nil { + return nil + } + out := new(CinderPersistentVolumeSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CinderVolumeSource) DeepCopyInto(out *CinderVolumeSource) { *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(LocalObjectReference) + **out = **in + } + } return } @@ -631,6 +665,22 @@ func (in *ConfigMapList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigMapNodeConfigSource) DeepCopyInto(out *ConfigMapNodeConfigSource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapNodeConfigSource. +func (in *ConfigMapNodeConfigSource) DeepCopy() *ConfigMapNodeConfigSource { + if in == nil { + return nil + } + out := new(ConfigMapNodeConfigSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConfigMapProjection) DeepCopyInto(out *ConfigMapProjection) { *out = *in @@ -965,67 +1015,6 @@ func (in *DaemonEndpoint) DeepCopy() *DaemonEndpoint { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DeleteOptions) DeepCopyInto(out *DeleteOptions) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.GracePeriodSeconds != nil { - in, out := &in.GracePeriodSeconds, &out.GracePeriodSeconds - if *in == nil { - *out = nil - } else { - *out = new(int64) - **out = **in - } - } - if in.Preconditions != nil { - in, out := &in.Preconditions, &out.Preconditions - if *in == nil { - *out = nil - } else { - *out = new(Preconditions) - (*in).DeepCopyInto(*out) - } - } - if in.OrphanDependents != nil { - in, out := &in.OrphanDependents, &out.OrphanDependents - if *in == nil { - *out = nil - } else { - *out = new(bool) - **out = **in - } - } - if in.PropagationPolicy != nil { - in, out := &in.PropagationPolicy, &out.PropagationPolicy - if *in == nil { - *out = nil - } else { - *out = new(DeletionPropagation) - **out = **in - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeleteOptions. -func (in *DeleteOptions) DeepCopy() *DeleteOptions { - if in == nil { - return nil - } - out := new(DeleteOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *DeleteOptions) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DownwardAPIProjection) DeepCopyInto(out *DownwardAPIProjection) { *out = *in @@ -2141,40 +2130,6 @@ func (in *List) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ListOptions) DeepCopyInto(out *ListOptions) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.TimeoutSeconds != nil { - in, out := &in.TimeoutSeconds, &out.TimeoutSeconds - if *in == nil { - *out = nil - } else { - *out = new(int64) - **out = **in - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListOptions. -func (in *ListOptions) DeepCopy() *ListOptions { - if in == nil { - return nil - } - out := new(ListOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ListOptions) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancerIngress) DeepCopyInto(out *LoadBalancerIngress) { *out = *in @@ -2455,13 +2410,12 @@ func (in *NodeCondition) DeepCopy() *NodeCondition { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeConfigSource) DeepCopyInto(out *NodeConfigSource) { *out = *in - out.TypeMeta = in.TypeMeta - if in.ConfigMapRef != nil { - in, out := &in.ConfigMapRef, &out.ConfigMapRef + if in.ConfigMap != nil { + in, out := &in.ConfigMap, &out.ConfigMap if *in == nil { *out = nil } else { - *out = new(ObjectReference) + *out = new(ConfigMapNodeConfigSource) **out = **in } } @@ -2478,12 +2432,47 @@ func (in *NodeConfigSource) DeepCopy() *NodeConfigSource { return out } -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NodeConfigSource) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeConfigStatus) DeepCopyInto(out *NodeConfigStatus) { + *out = *in + if in.Assigned != nil { + in, out := &in.Assigned, &out.Assigned + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigSource) + (*in).DeepCopyInto(*out) + } } - return nil + if in.Active != nil { + in, out := &in.Active, &out.Active + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigSource) + (*in).DeepCopyInto(*out) + } + } + if in.LastKnownGood != nil { + in, out := &in.LastKnownGood, &out.LastKnownGood + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigSource) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeConfigStatus. +func (in *NodeConfigStatus) DeepCopy() *NodeConfigStatus { + if in == nil { + return nil + } + out := new(NodeConfigStatus) + in.DeepCopyInto(out) + return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -2638,6 +2627,13 @@ func (in *NodeSelectorTerm) DeepCopyInto(out *NodeSelectorTerm) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.MatchFields != nil { + in, out := &in.MatchFields, &out.MatchFields + *out = make([]NodeSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -2731,6 +2727,15 @@ func (in *NodeStatus) DeepCopyInto(out *NodeStatus) { *out = make([]AttachedVolume, len(*in)) copy(*out, *in) } + if in.Config != nil { + in, out := &in.Config, &out.Config + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigStatus) + (*in).DeepCopyInto(*out) + } + } return } @@ -2776,75 +2781,6 @@ func (in *ObjectFieldSelector) DeepCopy() *ObjectFieldSelector { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ObjectMeta) DeepCopyInto(out *ObjectMeta) { - *out = *in - in.CreationTimestamp.DeepCopyInto(&out.CreationTimestamp) - if in.DeletionTimestamp != nil { - in, out := &in.DeletionTimestamp, &out.DeletionTimestamp - if *in == nil { - *out = nil - } else { - *out = (*in).DeepCopy() - } - } - if in.DeletionGracePeriodSeconds != nil { - in, out := &in.DeletionGracePeriodSeconds, &out.DeletionGracePeriodSeconds - if *in == nil { - *out = nil - } else { - *out = new(int64) - **out = **in - } - } - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Annotations != nil { - in, out := &in.Annotations, &out.Annotations - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.OwnerReferences != nil { - in, out := &in.OwnerReferences, &out.OwnerReferences - *out = make([]meta_v1.OwnerReference, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Initializers != nil { - in, out := &in.Initializers, &out.Initializers - if *in == nil { - *out = nil - } else { - *out = new(meta_v1.Initializers) - (*in).DeepCopyInto(*out) - } - } - if in.Finalizers != nil { - in, out := &in.Finalizers, &out.Finalizers - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectMeta. -func (in *ObjectMeta) DeepCopy() *ObjectMeta { - if in == nil { - return nil - } - out := new(ObjectMeta) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { *out = *in @@ -3180,8 +3116,8 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) { if *in == nil { *out = nil } else { - *out = new(CinderVolumeSource) - **out = **in + *out = new(CinderPersistentVolumeSource) + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { @@ -3813,6 +3749,22 @@ func (in *PodProxyOptions) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodReadinessGate) DeepCopyInto(out *PodReadinessGate) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodReadinessGate. +func (in *PodReadinessGate) DeepCopy() *PodReadinessGate { + if in == nil { + return nil + } + out := new(PodReadinessGate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { *out = *in @@ -3866,6 +3818,11 @@ func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { **out = **in } } + if in.Sysctls != nil { + in, out := &in.Sysctls, &out.Sysctls + *out = make([]Sysctl, len(*in)) + copy(*out, *in) + } return } @@ -4026,6 +3983,11 @@ func (in *PodSpec) DeepCopyInto(out *PodSpec) { (*in).DeepCopyInto(*out) } } + if in.ReadinessGates != nil { + in, out := &in.ReadinessGates, &out.ReadinessGates + *out = make([]PodReadinessGate, len(*in)) + copy(*out, *in) + } return } @@ -4678,6 +4640,15 @@ func (in *ResourceQuotaSpec) DeepCopyInto(out *ResourceQuotaSpec) { *out = make([]ResourceQuotaScope, len(*in)) copy(*out, *in) } + if in.ScopeSelector != nil { + in, out := &in.ScopeSelector, &out.ScopeSelector + if *in == nil { + *out = nil + } else { + *out = new(ScopeSelector) + (*in).DeepCopyInto(*out) + } + } return } @@ -4817,6 +4788,50 @@ func (in *ScaleIOVolumeSource) DeepCopy() *ScaleIOVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopeSelector) DeepCopyInto(out *ScopeSelector) { + *out = *in + if in.MatchExpressions != nil { + in, out := &in.MatchExpressions, &out.MatchExpressions + *out = make([]ScopedResourceSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopeSelector. +func (in *ScopeSelector) DeepCopy() *ScopeSelector { + if in == nil { + return nil + } + out := new(ScopeSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopedResourceSelectorRequirement) DeepCopyInto(out *ScopedResourceSelectorRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopedResourceSelectorRequirement. +func (in *ScopedResourceSelectorRequirement) DeepCopy() *ScopedResourceSelectorRequirement { + if in == nil { + return nil + } + out := new(ScopedResourceSelectorRequirement) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Secret) DeepCopyInto(out *Secret) { *out = *in @@ -5257,6 +5272,31 @@ func (in *ServiceAccountList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAccountTokenProjection) DeepCopyInto(out *ServiceAccountTokenProjection) { + *out = *in + if in.ExpirationSeconds != nil { + in, out := &in.ExpirationSeconds, &out.ExpirationSeconds + if *in == nil { + *out = nil + } else { + *out = new(int64) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountTokenProjection. +func (in *ServiceAccountTokenProjection) DeepCopy() *ServiceAccountTokenProjection { + if in == nil { + return nil + } + out := new(ServiceAccountTokenProjection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceList) DeepCopyInto(out *ServiceList) { *out = *in @@ -5553,6 +5593,50 @@ func (in *Toleration) DeepCopy() *Toleration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorLabelRequirement) DeepCopyInto(out *TopologySelectorLabelRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorLabelRequirement. +func (in *TopologySelectorLabelRequirement) DeepCopy() *TopologySelectorLabelRequirement { + if in == nil { + return nil + } + out := new(TopologySelectorLabelRequirement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorTerm) DeepCopyInto(out *TopologySelectorTerm) { + *out = *in + if in.MatchLabelExpressions != nil { + in, out := &in.MatchLabelExpressions, &out.MatchLabelExpressions + *out = make([]TopologySelectorLabelRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorTerm. +func (in *TopologySelectorTerm) DeepCopy() *TopologySelectorTerm { + if in == nil { + return nil + } + out := new(TopologySelectorTerm) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Volume) DeepCopyInto(out *Volume) { *out = *in @@ -5666,6 +5750,15 @@ func (in *VolumeProjection) DeepCopyInto(out *VolumeProjection) { (*in).DeepCopyInto(*out) } } + if in.ServiceAccountToken != nil { + in, out := &in.ServiceAccountToken, &out.ServiceAccountToken + if *in == nil { + *out = nil + } else { + *out = new(ServiceAccountTokenProjection) + (*in).DeepCopyInto(*out) + } + } return } @@ -5796,7 +5889,7 @@ func (in *VolumeSource) DeepCopyInto(out *VolumeSource) { *out = nil } else { *out = new(CinderVolumeSource) - **out = **in + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { diff --git a/vendor/k8s.io/api/events/v1beta1/generated.pb.go b/vendor/k8s.io/api/events/v1beta1/generated.pb.go index 9aac8420f..e24a82ab1 100644 --- a/vendor/k8s.io/api/events/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/events/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1251,56 +1251,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 814 bytes of a gzipped FileDescriptorProto + // 801 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcd, 0x6e, 0xdb, 0x46, - 0x10, 0x16, 0x13, 0x4b, 0xb6, 0x56, 0x49, 0x2c, 0x6f, 0x0e, 0xde, 0xb8, 0x00, 0xa5, 0x3a, 0x40, - 0x60, 0x14, 0x08, 0x59, 0xa7, 0x45, 0xdb, 0x6b, 0x18, 0xbb, 0x45, 0x02, 0xbb, 0x01, 0xd6, 0x3e, - 0x15, 0x3d, 0x64, 0x45, 0x4d, 0xe8, 0xad, 0xa5, 0x5d, 0x62, 0x77, 0x29, 0xc0, 0xb7, 0x5e, 0x0a, - 0xf4, 0xd8, 0x67, 0xe8, 0x13, 0xf4, 0x31, 0x7c, 0xcc, 0x31, 0x27, 0xa1, 0x66, 0xdf, 0xa2, 0xa7, - 0x82, 0xcb, 0x95, 0x28, 0x8b, 0x16, 0xec, 0x22, 0x37, 0x72, 0xe6, 0xfb, 0x99, 0x19, 0x0e, 0x07, - 0x45, 0xe7, 0xdf, 0xe9, 0x80, 0xcb, 0xf0, 0x3c, 0x1b, 0x80, 0x12, 0x60, 0x40, 0x87, 0x13, 0x10, - 0x43, 0xa9, 0x42, 0x97, 0x60, 0x29, 0x0f, 0x61, 0x02, 0xc2, 0xe8, 0x70, 0xb2, 0x3f, 0x00, 0xc3, - 0xf6, 0xc3, 0x04, 0x04, 0x28, 0x66, 0x60, 0x18, 0xa4, 0x4a, 0x1a, 0x89, 0x9f, 0x94, 0xd0, 0x80, - 0xa5, 0x3c, 0x28, 0xa1, 0x81, 0x83, 0xee, 0x3c, 0x4f, 0xb8, 0x39, 0xcb, 0x06, 0x41, 0x2c, 0xc7, - 0x61, 0x22, 0x13, 0x19, 0x5a, 0xc6, 0x20, 0x7b, 0x6f, 0xdf, 0xec, 0x8b, 0x7d, 0x2a, 0x95, 0x76, - 0x76, 0x17, 0x4c, 0x63, 0xa9, 0x20, 0x9c, 0xd4, 0xdc, 0x76, 0xbe, 0xae, 0x30, 0x63, 0x16, 0x9f, - 0x71, 0x01, 0xea, 0x22, 0x4c, 0xcf, 0x93, 0x22, 0xa0, 0xc3, 0x31, 0x18, 0x76, 0x13, 0x2b, 0x5c, - 0xc5, 0x52, 0x99, 0x30, 0x7c, 0x0c, 0x35, 0xc2, 0x37, 0xb7, 0x11, 0x74, 0x7c, 0x06, 0x63, 0x56, - 0xe3, 0x7d, 0xb5, 0x8a, 0x97, 0x19, 0x3e, 0x0a, 0xb9, 0x30, 0xda, 0xa8, 0x65, 0xd2, 0xee, 0x9f, - 0x6d, 0xd4, 0x3c, 0x2c, 0x26, 0x87, 0xdf, 0xa1, 0x8d, 0xa2, 0x85, 0x21, 0x33, 0x8c, 0x78, 0x7d, - 0x6f, 0xaf, 0xf3, 0xe2, 0xcb, 0xa0, 0x1a, 0xef, 0x5c, 0x31, 0x48, 0xcf, 0x93, 0x22, 0xa0, 0x83, - 0x02, 0x1d, 0x4c, 0xf6, 0x83, 0xb7, 0x83, 0x5f, 0x20, 0x36, 0xc7, 0x60, 0x58, 0x84, 0x2f, 0xa7, - 0xbd, 0x46, 0x3e, 0xed, 0xa1, 0x2a, 0x46, 0xe7, 0xaa, 0xf8, 0x1d, 0x6a, 0xdb, 0x8f, 0x74, 0xca, - 0xc7, 0x40, 0xee, 0x59, 0x8b, 0xf0, 0x6e, 0x16, 0xc7, 0x3c, 0x56, 0xb2, 0xa0, 0x45, 0x5b, 0xce, - 0xa1, 0x7d, 0x38, 0x53, 0xa2, 0x95, 0x28, 0x7e, 0x83, 0x5a, 0x1a, 0x14, 0x07, 0x4d, 0xee, 0x5b, - 0xf9, 0x67, 0xc1, 0xca, 0x05, 0x09, 0xac, 0xc0, 0x89, 0x45, 0x47, 0x28, 0x9f, 0xf6, 0x5a, 0xe5, - 0x33, 0x75, 0x0a, 0xf8, 0x18, 0x3d, 0x56, 0x90, 0x4a, 0x65, 0xb8, 0x48, 0x5e, 0x49, 0x61, 0x94, - 0x1c, 0x8d, 0x40, 0x91, 0xb5, 0xbe, 0xb7, 0xd7, 0x8e, 0x3e, 0x73, 0x65, 0x3c, 0xa6, 0x75, 0x08, - 0xbd, 0x89, 0x87, 0x7f, 0x40, 0x5b, 0xf3, 0xf0, 0x6b, 0xa1, 0x0d, 0x13, 0x31, 0x90, 0xa6, 0x15, - 0x7b, 0xe2, 0xc4, 0xb6, 0xe8, 0x32, 0x80, 0xd6, 0x39, 0xf8, 0x19, 0x6a, 0xb1, 0xd8, 0x70, 0x29, - 0x48, 0xcb, 0xb2, 0x1f, 0x39, 0x76, 0xeb, 0xa5, 0x8d, 0x52, 0x97, 0x2d, 0x70, 0x0a, 0x98, 0x96, - 0x82, 0xac, 0x5f, 0xc7, 0x51, 0x1b, 0xa5, 0x2e, 0x8b, 0x4f, 0x51, 0x5b, 0x41, 0xc2, 0xd4, 0x90, - 0x8b, 0x84, 0x6c, 0xd8, 0xb1, 0x3d, 0x5d, 0x1c, 0x5b, 0xf1, 0x37, 0x54, 0x9f, 0x99, 0xc2, 0x7b, - 0x50, 0x20, 0xe2, 0x85, 0x2f, 0x41, 0x67, 0x6c, 0x5a, 0x09, 0xe1, 0x37, 0x68, 0x5d, 0xc1, 0xa8, - 0x58, 0x34, 0xd2, 0xbe, 0xbb, 0x66, 0x27, 0x9f, 0xf6, 0xd6, 0x69, 0xc9, 0xa3, 0x33, 0x01, 0xdc, - 0x47, 0x6b, 0x42, 0x1a, 0x20, 0xc8, 0xf6, 0xf1, 0xc0, 0xf9, 0xae, 0xfd, 0x28, 0x0d, 0x50, 0x9b, - 0x29, 0x10, 0xe6, 0x22, 0x05, 0xd2, 0xb9, 0x8e, 0x38, 0xbd, 0x48, 0x81, 0xda, 0x0c, 0x06, 0xd4, - 0x1d, 0x42, 0xaa, 0x20, 0x2e, 0x14, 0x4f, 0x64, 0xa6, 0x62, 0x20, 0x0f, 0x6c, 0x61, 0xbd, 0x9b, - 0x0a, 0x2b, 0x97, 0xc3, 0xc2, 0x22, 0xe2, 0xe4, 0xba, 0x07, 0x4b, 0x02, 0xb4, 0x26, 0x89, 0x7f, - 0xf7, 0x10, 0xa9, 0x82, 0xdf, 0x73, 0xa5, 0xed, 0x62, 0x6a, 0xc3, 0xc6, 0x29, 0x79, 0x68, 0xfd, - 0xbe, 0xb8, 0xdb, 0xca, 0xdb, 0x6d, 0xef, 0x3b, 0x6b, 0x72, 0xb0, 0x42, 0x93, 0xae, 0x74, 0xc3, - 0xbf, 0x79, 0x68, 0xbb, 0x4a, 0x1e, 0xb1, 0xc5, 0x4a, 0x1e, 0xfd, 0xef, 0x4a, 0x7a, 0xae, 0x92, - 0xed, 0x83, 0x9b, 0x25, 0xe9, 0x2a, 0x2f, 0xfc, 0x12, 0x6d, 0x56, 0xa9, 0x57, 0x32, 0x13, 0x86, - 0x6c, 0xf6, 0xbd, 0xbd, 0x66, 0xb4, 0xed, 0x24, 0x37, 0x0f, 0xae, 0xa7, 0xe9, 0x32, 0x7e, 0xf7, - 0x2f, 0x0f, 0x95, 0xff, 0xfb, 0x11, 0xd7, 0x06, 0xff, 0x5c, 0x3b, 0x54, 0xc1, 0xdd, 0x1a, 0x29, - 0xd8, 0xf6, 0x4c, 0x75, 0x9d, 0xf3, 0xc6, 0x2c, 0xb2, 0x70, 0xa4, 0x0e, 0x51, 0x93, 0x1b, 0x18, - 0x6b, 0x72, 0xaf, 0x7f, 0x7f, 0xaf, 0xf3, 0xa2, 0x7f, 0xdb, 0x05, 0x89, 0x1e, 0x3a, 0xb1, 0xe6, - 0xeb, 0x82, 0x46, 0x4b, 0xf6, 0x6e, 0xee, 0xa1, 0xce, 0xc2, 0x85, 0xc1, 0x4f, 0x51, 0x33, 0xb6, - 0xbd, 0x7b, 0xb6, 0xf7, 0x39, 0xa9, 0xec, 0xb8, 0xcc, 0xe1, 0x0c, 0x75, 0x47, 0x4c, 0x9b, 0xb7, - 0x03, 0x0d, 0x6a, 0x02, 0xc3, 0x4f, 0xb9, 0x93, 0xf3, 0xa5, 0x3d, 0x5a, 0x12, 0xa4, 0x35, 0x0b, - 0xfc, 0x2d, 0x6a, 0x6a, 0xc3, 0x0c, 0xd8, 0xa3, 0xd9, 0x8e, 0x3e, 0x9f, 0xd5, 0x76, 0x52, 0x04, - 0xff, 0x9d, 0xf6, 0xba, 0x0b, 0x8d, 0xd8, 0x18, 0x2d, 0xf1, 0xd1, 0xf3, 0xcb, 0x2b, 0xbf, 0xf1, - 0xe1, 0xca, 0x6f, 0x7c, 0xbc, 0xf2, 0x1b, 0xbf, 0xe6, 0xbe, 0x77, 0x99, 0xfb, 0xde, 0x87, 0xdc, - 0xf7, 0x3e, 0xe6, 0xbe, 0xf7, 0x77, 0xee, 0x7b, 0x7f, 0xfc, 0xe3, 0x37, 0x7e, 0x5a, 0x77, 0xf3, - 0xfa, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x69, 0xa9, 0x7b, 0x6e, 0xf2, 0x07, 0x00, 0x00, + 0x10, 0x16, 0x13, 0x4b, 0xb2, 0x56, 0x49, 0x2c, 0x6f, 0x0e, 0xde, 0xb8, 0x00, 0xa5, 0x2a, 0x40, + 0x20, 0x14, 0x08, 0x59, 0x07, 0x45, 0xdb, 0x6b, 0x18, 0xb9, 0x45, 0x02, 0xbb, 0x01, 0xd6, 0x3e, + 0x15, 0x3d, 0x64, 0x45, 0x4d, 0x68, 0x56, 0xe2, 0x2e, 0xb1, 0xbb, 0x12, 0xe0, 0x5b, 0x2f, 0x05, + 0x7a, 0xec, 0x33, 0xf4, 0x09, 0xfa, 0x18, 0x3e, 0xe6, 0x98, 0x93, 0x50, 0xb3, 0x6f, 0xd1, 0x53, + 0xc1, 0xe5, 0x4a, 0x94, 0xf5, 0x83, 0xa8, 0xe8, 0x4d, 0x9c, 0xf9, 0x7e, 0x66, 0x66, 0x47, 0x83, + 0x82, 0xd1, 0xb7, 0xca, 0x8b, 0x85, 0x3f, 0x9a, 0x0c, 0x40, 0x72, 0xd0, 0xa0, 0xfc, 0x29, 0xf0, + 0xa1, 0x90, 0xbe, 0x4d, 0xb0, 0x34, 0xf6, 0x61, 0x0a, 0x5c, 0x2b, 0x7f, 0x7a, 0x32, 0x00, 0xcd, + 0x4e, 0xfc, 0x08, 0x38, 0x48, 0xa6, 0x61, 0xe8, 0xa5, 0x52, 0x68, 0x81, 0x9f, 0x14, 0x50, 0x8f, + 0xa5, 0xb1, 0x57, 0x40, 0x3d, 0x0b, 0x3d, 0x7e, 0x1e, 0xc5, 0xfa, 0x6a, 0x32, 0xf0, 0x42, 0x91, + 0xf8, 0x91, 0x88, 0x84, 0x6f, 0x18, 0x83, 0xc9, 0x7b, 0xf3, 0x65, 0x3e, 0xcc, 0xaf, 0x42, 0xe9, + 0xb8, 0xbb, 0x64, 0x1a, 0x0a, 0x09, 0xfe, 0x74, 0xcd, 0xed, 0xf8, 0xab, 0x12, 0x93, 0xb0, 0xf0, + 0x2a, 0xe6, 0x20, 0xaf, 0xfd, 0x74, 0x14, 0xe5, 0x01, 0xe5, 0x27, 0xa0, 0xd9, 0x26, 0x96, 0xbf, + 0x8d, 0x25, 0x27, 0x5c, 0xc7, 0x09, 0xac, 0x11, 0xbe, 0xfe, 0x14, 0x41, 0x85, 0x57, 0x90, 0xb0, + 0x55, 0x5e, 0xf7, 0x8f, 0x06, 0xaa, 0x9e, 0xe6, 0x43, 0xc0, 0xef, 0xd0, 0x7e, 0x5e, 0xcd, 0x90, + 0x69, 0x46, 0x9c, 0x8e, 0xd3, 0x6b, 0xbe, 0xf8, 0xd2, 0x2b, 0x27, 0xb5, 0x10, 0xf5, 0xd2, 0x51, + 0x94, 0x07, 0x94, 0x97, 0xa3, 0xbd, 0xe9, 0x89, 0xf7, 0x76, 0xf0, 0x33, 0x84, 0xfa, 0x1c, 0x34, + 0x0b, 0xf0, 0xcd, 0xac, 0x5d, 0xc9, 0x66, 0x6d, 0x54, 0xc6, 0xe8, 0x42, 0x15, 0xbf, 0x43, 0x0d, + 0x33, 0xef, 0xcb, 0x38, 0x01, 0x72, 0xcf, 0x58, 0xf8, 0xbb, 0x59, 0x9c, 0xc7, 0xa1, 0x14, 0x39, + 0x2d, 0x38, 0xb4, 0x0e, 0x8d, 0xd3, 0xb9, 0x12, 0x2d, 0x45, 0xf1, 0x1b, 0x54, 0x53, 0x20, 0x63, + 0x50, 0xe4, 0xbe, 0x91, 0x7f, 0xe6, 0x6d, 0x7d, 0x6b, 0xcf, 0x08, 0x5c, 0x18, 0x74, 0x80, 0xb2, + 0x59, 0xbb, 0x56, 0xfc, 0xa6, 0x56, 0x01, 0x9f, 0xa3, 0xc7, 0x12, 0x52, 0x21, 0x75, 0xcc, 0xa3, + 0x57, 0x82, 0x6b, 0x29, 0xc6, 0x63, 0x90, 0x64, 0xaf, 0xe3, 0xf4, 0x1a, 0xc1, 0x67, 0xb6, 0x8c, + 0xc7, 0x74, 0x1d, 0x42, 0x37, 0xf1, 0xf0, 0xf7, 0xe8, 0x70, 0x11, 0x7e, 0xcd, 0x95, 0x66, 0x3c, + 0x04, 0x52, 0x35, 0x62, 0x4f, 0xac, 0xd8, 0x21, 0x5d, 0x05, 0xd0, 0x75, 0x0e, 0x7e, 0x86, 0x6a, + 0x2c, 0xd4, 0xb1, 0xe0, 0xa4, 0x66, 0xd8, 0x8f, 0x2c, 0xbb, 0xf6, 0xd2, 0x44, 0xa9, 0xcd, 0xe6, + 0x38, 0x09, 0x4c, 0x09, 0x4e, 0xea, 0x77, 0x71, 0xd4, 0x44, 0xa9, 0xcd, 0xe2, 0x4b, 0xd4, 0x90, + 0x10, 0x31, 0x39, 0x8c, 0x79, 0x44, 0xf6, 0xcd, 0xd8, 0x9e, 0x2e, 0x8f, 0x2d, 0x5f, 0xec, 0xf2, + 0x99, 0x29, 0xbc, 0x07, 0x09, 0x3c, 0x5c, 0x7a, 0x09, 0x3a, 0x67, 0xd3, 0x52, 0x08, 0xbf, 0x41, + 0x75, 0x09, 0xe3, 0x7c, 0xd1, 0x48, 0x63, 0x77, 0xcd, 0x66, 0x36, 0x6b, 0xd7, 0x69, 0xc1, 0xa3, + 0x73, 0x01, 0xdc, 0x41, 0x7b, 0x5c, 0x68, 0x20, 0xc8, 0xf4, 0xf1, 0xc0, 0xfa, 0xee, 0xfd, 0x20, + 0x34, 0x50, 0x93, 0xc9, 0x11, 0xfa, 0x3a, 0x05, 0xd2, 0xbc, 0x8b, 0xb8, 0xbc, 0x4e, 0x81, 0x9a, + 0x0c, 0x06, 0xd4, 0x1a, 0x42, 0x2a, 0x21, 0xcc, 0x15, 0x2f, 0xc4, 0x44, 0x86, 0x40, 0x1e, 0x98, + 0xc2, 0xda, 0x9b, 0x0a, 0x2b, 0x96, 0xc3, 0xc0, 0x02, 0x62, 0xe5, 0x5a, 0xfd, 0x15, 0x01, 0xba, + 0x26, 0x89, 0x7f, 0x73, 0x10, 0x29, 0x83, 0xdf, 0xc5, 0x52, 0x99, 0xc5, 0x54, 0x9a, 0x25, 0x29, + 0x79, 0x68, 0xfc, 0xbe, 0xd8, 0x6d, 0xe5, 0xcd, 0xb6, 0x77, 0xac, 0x35, 0xe9, 0x6f, 0xd1, 0xa4, + 0x5b, 0xdd, 0xf0, 0xaf, 0x0e, 0x3a, 0x2a, 0x93, 0x67, 0x6c, 0xb9, 0x92, 0x47, 0xff, 0xb9, 0x92, + 0xb6, 0xad, 0xe4, 0xa8, 0xbf, 0x59, 0x92, 0x6e, 0xf3, 0xc2, 0x2f, 0xd1, 0x41, 0x99, 0x7a, 0x25, + 0x26, 0x5c, 0x93, 0x83, 0x8e, 0xd3, 0xab, 0x06, 0x47, 0x56, 0xf2, 0xa0, 0x7f, 0x37, 0x4d, 0x57, + 0xf1, 0xdd, 0x3f, 0x1d, 0x54, 0xfc, 0xdf, 0xcf, 0x62, 0xa5, 0xf1, 0x4f, 0x6b, 0x87, 0xca, 0xdb, + 0xad, 0x91, 0x9c, 0x6d, 0xce, 0x54, 0xcb, 0x3a, 0xef, 0xcf, 0x23, 0x4b, 0x47, 0xea, 0x14, 0x55, + 0x63, 0x0d, 0x89, 0x22, 0xf7, 0x3a, 0xf7, 0x7b, 0xcd, 0x17, 0x9d, 0x4f, 0x5d, 0x90, 0xe0, 0xa1, + 0x15, 0xab, 0xbe, 0xce, 0x69, 0xb4, 0x60, 0x77, 0x33, 0x07, 0x35, 0x97, 0x2e, 0x0c, 0x7e, 0x8a, + 0xaa, 0xa1, 0xe9, 0xdd, 0x31, 0xbd, 0x2f, 0x48, 0x45, 0xc7, 0x45, 0x0e, 0x4f, 0x50, 0x6b, 0xcc, + 0x94, 0x7e, 0x3b, 0x50, 0x20, 0xa7, 0x30, 0xfc, 0x3f, 0x77, 0x72, 0xb1, 0xb4, 0x67, 0x2b, 0x82, + 0x74, 0xcd, 0x02, 0x7f, 0x83, 0xaa, 0x4a, 0x33, 0x0d, 0xe6, 0x68, 0x36, 0x82, 0xcf, 0xe7, 0xb5, + 0x5d, 0xe4, 0xc1, 0x7f, 0x66, 0xed, 0xd6, 0x52, 0x23, 0x26, 0x46, 0x0b, 0x7c, 0xf0, 0xfc, 0xe6, + 0xd6, 0xad, 0x7c, 0xb8, 0x75, 0x2b, 0x1f, 0x6f, 0xdd, 0xca, 0x2f, 0x99, 0xeb, 0xdc, 0x64, 0xae, + 0xf3, 0x21, 0x73, 0x9d, 0x8f, 0x99, 0xeb, 0xfc, 0x95, 0xb9, 0xce, 0xef, 0x7f, 0xbb, 0x95, 0x1f, + 0xeb, 0x76, 0x5e, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x25, 0x9b, 0x14, 0x4d, 0xbd, 0x07, 0x00, + 0x00, } diff --git a/vendor/k8s.io/api/events/v1beta1/generated.proto b/vendor/k8s.io/api/events/v1beta1/generated.proto index 0637f780a..b3e565e67 100644 --- a/vendor/k8s.io/api/events/v1beta1/generated.proto +++ b/vendor/k8s.io/api/events/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/api/events/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/events/v1beta1/types_swagger_doc_generated.go index 17ec3d777..a15672c19 100644 --- a/vendor/k8s.io/api/events/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/events/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_Event = map[string]string{ "": "Event is a report of an event somewhere in the cluster. It generally denotes some state change in the system.", "eventTime": "Required. Time when this Event was first observed.", diff --git a/vendor/k8s.io/api/events/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/events/v1beta1/zz_generated.deepcopy.go index 546d69e7e..9652044b3 100644 --- a/vendor/k8s.io/api/events/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/events/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/extensions/v1beta1/generated.pb.go b/vendor/k8s.io/api/extensions/v1beta1/generated.pb.go index fcb80615f..9d76a5b93 100644 --- a/vendor/k8s.io/api/extensions/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/extensions/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -465,6 +465,14 @@ func (m *AllowedHostPath) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.PathPrefix))) i += copy(dAtA[i:], m.PathPrefix) + dAtA[i] = 0x10 + i++ + if m.ReadOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -2249,6 +2257,40 @@ func (m *PodSecurityPolicySpec) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + dAtA[i] = 0x9a + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + dAtA[i] = 0xa2 + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } return i, nil } @@ -2818,6 +2860,7 @@ func (m *AllowedHostPath) Size() (n int) { _ = l l = len(m.PathPrefix) n += 1 + l + sovGenerated(uint64(l)) + n += 2 return n } @@ -3457,6 +3500,18 @@ func (m *PodSecurityPolicySpec) Size() (n int) { n += 2 + l + sovGenerated(uint64(l)) } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -3677,6 +3732,7 @@ func (this *AllowedHostPath) String() string { } s := strings.Join([]string{`&AllowedHostPath{`, `PathPrefix:` + fmt.Sprintf("%v", this.PathPrefix) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, `}`, }, "") return s @@ -4189,6 +4245,8 @@ func (this *PodSecurityPolicySpec) String() string { `AllowPrivilegeEscalation:` + valueToStringGenerated(this.AllowPrivilegeEscalation) + `,`, `AllowedHostPaths:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedHostPaths), "AllowedHostPath", "AllowedHostPath", 1), `&`, ``, 1) + `,`, `AllowedFlexVolumes:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedFlexVolumes), "AllowedFlexVolume", "AllowedFlexVolume", 1), `&`, ``, 1) + `,`, + `AllowedUnsafeSysctls:` + fmt.Sprintf("%v", this.AllowedUnsafeSysctls) + `,`, + `ForbiddenSysctls:` + fmt.Sprintf("%v", this.ForbiddenSysctls) + `,`, `}`, }, "") return s @@ -4520,6 +4578,26 @@ func (m *AllowedHostPath) Unmarshal(dAtA []byte) error { } m.PathPrefix = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -10306,6 +10384,64 @@ func (m *PodSecurityPolicySpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedUnsafeSysctls", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedUnsafeSysctls = append(m.AllowedUnsafeSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ForbiddenSysctls", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ForbiddenSysctls = append(m.ForbiddenSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -12285,229 +12421,232 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 3571 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0xcd, 0x6f, 0x1c, 0x47, - 0x76, 0x57, 0xcf, 0x0c, 0x39, 0xc3, 0x47, 0xf1, 0xab, 0x28, 0x93, 0x63, 0xca, 0xe2, 0xc8, 0x6d, - 0x40, 0x91, 0x1c, 0x69, 0xc6, 0x92, 0x2d, 0x59, 0xb1, 0x10, 0x3b, 0x1c, 0x52, 0x1f, 0x74, 0xf8, - 0xa5, 0x1a, 0x52, 0x71, 0x8c, 0xc8, 0x71, 0x73, 0xa6, 0x38, 0x6c, 0xb1, 0xa7, 0xbb, 0xdd, 0x5d, - 0x4d, 0x73, 0x80, 0x20, 0xc8, 0x21, 0x08, 0x10, 0x20, 0x41, 0x92, 0x83, 0xf3, 0x71, 0x8b, 0x2f, - 0x39, 0x25, 0x48, 0x6e, 0xc9, 0xc1, 0x30, 0x10, 0xc0, 0x0b, 0x08, 0x0b, 0x2f, 0xe0, 0xdb, 0xfa, - 0x44, 0xac, 0xe9, 0xd3, 0x62, 0xff, 0x81, 0x85, 0x0e, 0x8b, 0x45, 0x55, 0x57, 0x7f, 0x77, 0x73, - 0x66, 0x68, 0x89, 0x58, 0x2c, 0xf6, 0xc6, 0xa9, 0xf7, 0xde, 0xef, 0xbd, 0x7a, 0xf5, 0xea, 0xbd, - 0xd7, 0x55, 0x45, 0xb8, 0xb7, 0x77, 0xdb, 0xae, 0xaa, 0x46, 0x6d, 0xcf, 0xd9, 0x26, 0x96, 0x4e, - 0x28, 0xb1, 0x6b, 0xfb, 0x44, 0x6f, 0x19, 0x56, 0x4d, 0x10, 0x14, 0x53, 0xad, 0x91, 0x03, 0x4a, - 0x74, 0x5b, 0x35, 0x74, 0xbb, 0xb6, 0x7f, 0x7d, 0x9b, 0x50, 0xe5, 0x7a, 0xad, 0x4d, 0x74, 0x62, - 0x29, 0x94, 0xb4, 0xaa, 0xa6, 0x65, 0x50, 0x03, 0x5d, 0x70, 0xd9, 0xab, 0x8a, 0xa9, 0x56, 0x03, - 0xf6, 0xaa, 0x60, 0x9f, 0xbb, 0xd6, 0x56, 0xe9, 0xae, 0xb3, 0x5d, 0x6d, 0x1a, 0x9d, 0x5a, 0xdb, - 0x68, 0x1b, 0x35, 0x2e, 0xb5, 0xed, 0xec, 0xf0, 0x5f, 0xfc, 0x07, 0xff, 0xcb, 0x45, 0x9b, 0x93, - 0x43, 0xca, 0x9b, 0x86, 0x45, 0x6a, 0xfb, 0x09, 0x8d, 0x73, 0x57, 0x42, 0x3c, 0xa6, 0xa1, 0xa9, - 0xcd, 0x6e, 0x96, 0x71, 0x73, 0x6f, 0x05, 0xac, 0x1d, 0xa5, 0xb9, 0xab, 0xea, 0xc4, 0xea, 0xd6, - 0xcc, 0xbd, 0x36, 0x97, 0xb5, 0x88, 0x6d, 0x38, 0x56, 0x93, 0x0c, 0x24, 0x65, 0xd7, 0x3a, 0x84, - 0x2a, 0x69, 0x66, 0xd5, 0xb2, 0xa4, 0x2c, 0x47, 0xa7, 0x6a, 0x27, 0xa9, 0xe6, 0x56, 0x2f, 0x01, - 0xbb, 0xb9, 0x4b, 0x3a, 0x4a, 0x42, 0xee, 0xcd, 0x2c, 0x39, 0x87, 0xaa, 0x5a, 0x4d, 0xd5, 0xa9, - 0x4d, 0xad, 0xb8, 0x90, 0x7c, 0x07, 0xa6, 0x16, 0x34, 0xcd, 0xf8, 0x94, 0xb4, 0xee, 0x69, 0xe4, - 0xe0, 0x91, 0xa1, 0x39, 0x1d, 0x82, 0x2e, 0xc1, 0x70, 0xcb, 0x52, 0xf7, 0x89, 0x55, 0x96, 0x2e, - 0x4a, 0x97, 0x47, 0xea, 0xe3, 0x4f, 0x0f, 0x2b, 0x67, 0x8e, 0x0e, 0x2b, 0xc3, 0x4b, 0x7c, 0x14, - 0x0b, 0xaa, 0x7c, 0x17, 0x26, 0x84, 0xf0, 0x03, 0xc3, 0xa6, 0x1b, 0x0a, 0xdd, 0x45, 0x37, 0x00, - 0x4c, 0x85, 0xee, 0x6e, 0x58, 0x64, 0x47, 0x3d, 0x10, 0xe2, 0x48, 0x88, 0xc3, 0x86, 0x4f, 0xc1, - 0x21, 0x2e, 0xf9, 0xdf, 0x24, 0x78, 0x79, 0xd1, 0xb1, 0xa9, 0xd1, 0x59, 0x25, 0xd4, 0x52, 0x9b, - 0x8b, 0x8e, 0x65, 0x11, 0x9d, 0x36, 0xa8, 0x42, 0x1d, 0x1b, 0x5d, 0x84, 0x82, 0xae, 0x74, 0x88, - 0xc0, 0x3a, 0x2b, 0xb0, 0x0a, 0x6b, 0x4a, 0x87, 0x60, 0x4e, 0x41, 0x1f, 0xc2, 0xd0, 0xbe, 0xa2, - 0x39, 0xa4, 0x9c, 0xbb, 0x28, 0x5d, 0x1e, 0xbd, 0x51, 0xad, 0x06, 0xa1, 0xe7, 0x3b, 0xa2, 0x6a, - 0xee, 0xb5, 0x79, 0x2c, 0x7a, 0xab, 0x5b, 0x7d, 0xe8, 0x28, 0x3a, 0x55, 0x69, 0xb7, 0x7e, 0x4e, - 0x40, 0x9e, 0x15, 0x7a, 0x1f, 0x31, 0x2c, 0xec, 0x42, 0xca, 0x7f, 0x09, 0x17, 0x32, 0x4d, 0x5b, - 0x51, 0x6d, 0x8a, 0x1e, 0xc3, 0x90, 0x4a, 0x49, 0xc7, 0x2e, 0x4b, 0x17, 0xf3, 0x97, 0x47, 0x6f, - 0xdc, 0xae, 0x1e, 0x1b, 0xf7, 0xd5, 0x4c, 0xb0, 0xfa, 0x98, 0x30, 0x63, 0x68, 0x99, 0xc1, 0x61, - 0x17, 0x55, 0xfe, 0x27, 0x09, 0x50, 0x58, 0x66, 0x53, 0xb1, 0xda, 0x84, 0xf6, 0xe1, 0x94, 0x3f, - 0xfd, 0x61, 0x4e, 0x99, 0x16, 0x90, 0xa3, 0xae, 0xc2, 0x88, 0x4f, 0x4c, 0x98, 0x49, 0x9a, 0xc4, - 0x9d, 0xf1, 0x28, 0xea, 0x8c, 0xeb, 0x03, 0x38, 0xc3, 0x45, 0xc9, 0xf0, 0xc2, 0x67, 0x39, 0x18, - 0x59, 0x52, 0x48, 0xc7, 0xd0, 0x1b, 0x84, 0xa2, 0x8f, 0xa1, 0xc4, 0x36, 0x5b, 0x4b, 0xa1, 0x0a, - 0x77, 0xc0, 0xe8, 0x8d, 0x37, 0x8e, 0x9b, 0x9d, 0x5d, 0x65, 0xdc, 0xd5, 0xfd, 0xeb, 0xd5, 0xf5, - 0xed, 0x27, 0xa4, 0x49, 0x57, 0x09, 0x55, 0x82, 0x98, 0x0c, 0xc6, 0xb0, 0x8f, 0x8a, 0xd6, 0xa0, - 0x60, 0x9b, 0xa4, 0x29, 0x7c, 0x77, 0xb5, 0xc7, 0x34, 0x7c, 0xcb, 0x1a, 0x26, 0x69, 0x06, 0x8b, - 0xc1, 0x7e, 0x61, 0x8e, 0x83, 0x1e, 0xc1, 0xb0, 0xcd, 0x57, 0xb9, 0x9c, 0x4f, 0xac, 0xc6, 0xf1, - 0x88, 0x6e, 0x6c, 0xf8, 0x1b, 0xd0, 0xfd, 0x8d, 0x05, 0x9a, 0xfc, 0xf3, 0x1c, 0x20, 0x9f, 0x77, - 0xd1, 0xd0, 0x5b, 0x2a, 0x55, 0x0d, 0x1d, 0xbd, 0x03, 0x05, 0xda, 0x35, 0xbd, 0xe8, 0xb8, 0xe4, - 0x19, 0xb4, 0xd9, 0x35, 0xc9, 0xb3, 0xc3, 0xca, 0x4c, 0x52, 0x82, 0x51, 0x30, 0x97, 0x41, 0x2b, - 0xbe, 0xa9, 0x39, 0x2e, 0xfd, 0x56, 0x54, 0xf5, 0xb3, 0xc3, 0x4a, 0x4a, 0x2e, 0xae, 0xfa, 0x48, - 0x51, 0x03, 0xd1, 0x3e, 0x20, 0x4d, 0xb1, 0xe9, 0xa6, 0xa5, 0xe8, 0xb6, 0xab, 0x49, 0xed, 0x10, - 0xe1, 0x84, 0xd7, 0xfb, 0x5b, 0x34, 0x26, 0x51, 0x9f, 0x13, 0x56, 0xa0, 0x95, 0x04, 0x1a, 0x4e, - 0xd1, 0xc0, 0x32, 0x98, 0x45, 0x14, 0xdb, 0xd0, 0xcb, 0x85, 0x68, 0x06, 0xc3, 0x7c, 0x14, 0x0b, - 0x2a, 0xba, 0x02, 0xc5, 0x0e, 0xb1, 0x6d, 0xa5, 0x4d, 0xca, 0x43, 0x9c, 0x71, 0x42, 0x30, 0x16, - 0x57, 0xdd, 0x61, 0xec, 0xd1, 0xe5, 0x2f, 0x24, 0x18, 0xf3, 0x3d, 0xc7, 0xa3, 0xfd, 0xcf, 0x12, - 0x71, 0x58, 0xed, 0x6f, 0x4a, 0x4c, 0x9a, 0x47, 0xe1, 0xa4, 0xd0, 0x56, 0xf2, 0x46, 0x42, 0x31, - 0xb8, 0xea, 0xed, 0xa5, 0x1c, 0xdf, 0x4b, 0x97, 0xfb, 0x0d, 0x99, 0x8c, 0x2d, 0xf4, 0xcf, 0x85, - 0x90, 0xf9, 0x2c, 0x34, 0xd1, 0x63, 0x28, 0xd9, 0x44, 0x23, 0x4d, 0x6a, 0x58, 0xc2, 0xfc, 0x37, - 0xfb, 0x34, 0x5f, 0xd9, 0x26, 0x5a, 0x43, 0x88, 0xd6, 0xcf, 0x32, 0xfb, 0xbd, 0x5f, 0xd8, 0x87, - 0x44, 0x0f, 0xa1, 0x44, 0x49, 0xc7, 0xd4, 0x14, 0xea, 0xe5, 0xa0, 0xd7, 0xc2, 0x53, 0x60, 0x91, - 0xc3, 0xc0, 0x36, 0x8c, 0xd6, 0xa6, 0x60, 0xe3, 0xdb, 0xc7, 0x77, 0x89, 0x37, 0x8a, 0x7d, 0x18, - 0xb4, 0x0f, 0xe3, 0x8e, 0xd9, 0x62, 0x9c, 0x94, 0xd5, 0xb0, 0x76, 0x57, 0x44, 0xd2, 0xad, 0x7e, - 0x7d, 0xb3, 0x15, 0x91, 0xae, 0xcf, 0x08, 0x5d, 0xe3, 0xd1, 0x71, 0x1c, 0xd3, 0x82, 0x16, 0x60, - 0xa2, 0xa3, 0xea, 0x98, 0x28, 0xad, 0x6e, 0x83, 0x34, 0x0d, 0xbd, 0x65, 0xf3, 0xb0, 0x1a, 0xaa, - 0xcf, 0x0a, 0x80, 0x89, 0xd5, 0x28, 0x19, 0xc7, 0xf9, 0xd1, 0xfb, 0x80, 0xbc, 0x69, 0xdc, 0x77, - 0x4b, 0xb0, 0x6a, 0xe8, 0x3c, 0xe6, 0xf2, 0x41, 0x70, 0x6f, 0x26, 0x38, 0x70, 0x8a, 0x14, 0x5a, - 0x81, 0x73, 0x16, 0xd9, 0x57, 0xd9, 0x1c, 0x1f, 0xa8, 0x36, 0x35, 0xac, 0xee, 0x8a, 0xda, 0x51, - 0x69, 0x79, 0x98, 0xdb, 0x54, 0x3e, 0x3a, 0xac, 0x9c, 0xc3, 0x29, 0x74, 0x9c, 0x2a, 0x25, 0xff, - 0xcb, 0x30, 0x4c, 0xc4, 0xf2, 0x0d, 0x7a, 0x04, 0x33, 0x4d, 0xb7, 0x38, 0xad, 0x39, 0x9d, 0x6d, - 0x62, 0x35, 0x9a, 0xbb, 0xa4, 0xe5, 0x68, 0xa4, 0xc5, 0x03, 0x65, 0xa8, 0x3e, 0x2f, 0x2c, 0x9e, - 0x59, 0x4c, 0xe5, 0xc2, 0x19, 0xd2, 0xcc, 0x0b, 0x3a, 0x1f, 0x5a, 0x55, 0x6d, 0xdb, 0xc7, 0xcc, - 0x71, 0x4c, 0xdf, 0x0b, 0x6b, 0x09, 0x0e, 0x9c, 0x22, 0xc5, 0x6c, 0x6c, 0x11, 0x5b, 0xb5, 0x48, - 0x2b, 0x6e, 0x63, 0x3e, 0x6a, 0xe3, 0x52, 0x2a, 0x17, 0xce, 0x90, 0x46, 0x37, 0x61, 0xd4, 0xd5, - 0xc6, 0xd7, 0x4f, 0x2c, 0xb4, 0x5f, 0x0e, 0xd7, 0x02, 0x12, 0x0e, 0xf3, 0xb1, 0xa9, 0x19, 0xdb, - 0x36, 0xb1, 0xf6, 0x49, 0x2b, 0x7b, 0x81, 0xd7, 0x13, 0x1c, 0x38, 0x45, 0x8a, 0x4d, 0xcd, 0x8d, - 0xc0, 0xc4, 0xd4, 0x86, 0xa3, 0x53, 0xdb, 0x4a, 0xe5, 0xc2, 0x19, 0xd2, 0x2c, 0x8e, 0x5d, 0x93, - 0x17, 0xf6, 0x15, 0x55, 0x53, 0xb6, 0x35, 0x52, 0x2e, 0x46, 0xe3, 0x78, 0x2d, 0x4a, 0xc6, 0x71, - 0x7e, 0x74, 0x1f, 0xa6, 0xdc, 0xa1, 0x2d, 0x5d, 0xf1, 0x41, 0x4a, 0x1c, 0xe4, 0x65, 0x01, 0x32, - 0xb5, 0x16, 0x67, 0xc0, 0x49, 0x19, 0xf4, 0x0e, 0x8c, 0x37, 0x0d, 0x4d, 0xe3, 0xf1, 0xb8, 0x68, - 0x38, 0x3a, 0x2d, 0x8f, 0x70, 0x14, 0xc4, 0xf6, 0xe3, 0x62, 0x84, 0x82, 0x63, 0x9c, 0x88, 0x00, - 0x34, 0xbd, 0x82, 0x63, 0x97, 0xa1, 0xaf, 0x5e, 0x23, 0x59, 0xf4, 0x82, 0x1e, 0xc0, 0x1f, 0xb2, - 0x71, 0x08, 0x58, 0xfe, 0xb1, 0x04, 0xb3, 0x19, 0xa9, 0x03, 0xbd, 0x17, 0x29, 0xb1, 0xbf, 0x1f, - 0x2b, 0xb1, 0xe7, 0x33, 0xc4, 0x42, 0x75, 0x56, 0x87, 0x31, 0x8b, 0xcd, 0x4a, 0x6f, 0xbb, 0x2c, - 0x22, 0x47, 0xde, 0xec, 0x31, 0x0d, 0x1c, 0x96, 0x09, 0x72, 0xfe, 0xd4, 0xd1, 0x61, 0x65, 0x2c, - 0x42, 0xc3, 0x51, 0x78, 0xf9, 0x5f, 0x73, 0x00, 0x4b, 0xc4, 0xd4, 0x8c, 0x6e, 0x87, 0xe8, 0xa7, - 0xd1, 0x43, 0xad, 0x47, 0x7a, 0xa8, 0x6b, 0xbd, 0x96, 0xc7, 0x37, 0x2d, 0xb3, 0x89, 0xfa, 0x93, - 0x58, 0x13, 0x55, 0xeb, 0x1f, 0xf2, 0xf8, 0x2e, 0xea, 0xa7, 0x79, 0x98, 0x0e, 0x98, 0x83, 0x36, - 0xea, 0x4e, 0x64, 0x8d, 0x7f, 0x2f, 0xb6, 0xc6, 0xb3, 0x29, 0x22, 0x2f, 0xac, 0x8f, 0x7a, 0xfe, - 0xfd, 0x0c, 0x7a, 0x02, 0xe3, 0xac, 0x71, 0x72, 0xc3, 0x83, 0xb7, 0x65, 0xc3, 0x03, 0xb7, 0x65, - 0x7e, 0x01, 0x5d, 0x89, 0x20, 0xe1, 0x18, 0x72, 0x46, 0x1b, 0x58, 0x7c, 0xd1, 0x6d, 0xa0, 0xfc, - 0xa5, 0x04, 0xe3, 0xc1, 0x32, 0x9d, 0x42, 0xd3, 0xb6, 0x16, 0x6d, 0xda, 0xae, 0xf4, 0x1d, 0xa2, - 0x19, 0x5d, 0xdb, 0x2f, 0x59, 0x83, 0xef, 0x33, 0xb1, 0x0d, 0xbe, 0xad, 0x34, 0xf7, 0xfa, 0xf8, - 0xfc, 0xfb, 0x4c, 0x02, 0x24, 0xaa, 0xc0, 0x82, 0xae, 0x1b, 0x54, 0x71, 0x73, 0xa5, 0x6b, 0xd6, - 0x72, 0xdf, 0x66, 0x79, 0x1a, 0xab, 0x5b, 0x09, 0xac, 0xbb, 0x3a, 0xb5, 0xba, 0xc1, 0x8a, 0x24, - 0x19, 0x70, 0x8a, 0x01, 0x48, 0x01, 0xb0, 0x04, 0xe6, 0xa6, 0x21, 0x36, 0xf2, 0xb5, 0x3e, 0x72, - 0x1e, 0x13, 0x58, 0x34, 0xf4, 0x1d, 0xb5, 0x1d, 0xa4, 0x1d, 0xec, 0x03, 0xe1, 0x10, 0xe8, 0xdc, - 0x5d, 0x98, 0xcd, 0xb0, 0x16, 0x4d, 0x42, 0x7e, 0x8f, 0x74, 0x5d, 0xb7, 0x61, 0xf6, 0x27, 0x3a, - 0x17, 0xfe, 0x4c, 0x1e, 0x11, 0x5f, 0xb8, 0xef, 0xe4, 0x6e, 0x4b, 0xf2, 0x17, 0x43, 0xe1, 0xd8, - 0xe1, 0x1d, 0xf3, 0x65, 0x28, 0x59, 0xc4, 0xd4, 0xd4, 0xa6, 0x62, 0x8b, 0x46, 0x88, 0x37, 0xbf, - 0x58, 0x8c, 0x61, 0x9f, 0x1a, 0xe9, 0xad, 0x73, 0x2f, 0xb6, 0xb7, 0xce, 0x3f, 0x9f, 0xde, 0xfa, - 0xcf, 0xa1, 0x64, 0x7b, 0x5d, 0x75, 0x81, 0x43, 0x5e, 0x1f, 0x20, 0xbf, 0x8a, 0x86, 0xda, 0x57, - 0xe0, 0xb7, 0xd2, 0x3e, 0x68, 0x5a, 0x13, 0x3d, 0x34, 0x60, 0x13, 0xfd, 0x5c, 0x1b, 0x5f, 0x96, - 0x53, 0x4d, 0xc5, 0xb1, 0x49, 0x8b, 0x27, 0xa2, 0x52, 0x90, 0x53, 0x37, 0xf8, 0x28, 0x16, 0x54, - 0xf4, 0x38, 0x12, 0xb2, 0xa5, 0x93, 0x84, 0xec, 0x78, 0x76, 0xb8, 0xa2, 0x2d, 0x98, 0x35, 0x2d, - 0xa3, 0x6d, 0x11, 0xdb, 0x5e, 0x22, 0x4a, 0x4b, 0x53, 0x75, 0xe2, 0xf9, 0xc7, 0xed, 0x88, 0xce, - 0x1f, 0x1d, 0x56, 0x66, 0x37, 0xd2, 0x59, 0x70, 0x96, 0xac, 0xfc, 0xb4, 0x00, 0x93, 0xf1, 0x0a, - 0x98, 0xd1, 0xa4, 0x4a, 0x27, 0x6a, 0x52, 0xaf, 0x86, 0x36, 0x83, 0xdb, 0xc1, 0xfb, 0xab, 0x9f, - 0xb2, 0x21, 0x16, 0x60, 0x42, 0x64, 0x03, 0x8f, 0x28, 0xda, 0x74, 0x7f, 0xf5, 0xb7, 0xa2, 0x64, - 0x1c, 0xe7, 0x67, 0xad, 0x67, 0xd0, 0x51, 0x7a, 0x20, 0x85, 0x68, 0xeb, 0xb9, 0x10, 0x67, 0xc0, - 0x49, 0x19, 0xb4, 0x0a, 0xd3, 0x8e, 0x9e, 0x84, 0x72, 0xa3, 0xf1, 0xbc, 0x80, 0x9a, 0xde, 0x4a, - 0xb2, 0xe0, 0x34, 0x39, 0xb4, 0x13, 0xe9, 0x46, 0x87, 0x79, 0x86, 0xbd, 0xd1, 0xf7, 0xde, 0xe9, - 0xbb, 0x1d, 0x45, 0x77, 0x60, 0xcc, 0xe2, 0xdf, 0x1d, 0x9e, 0xc1, 0x6e, 0xef, 0xfe, 0x92, 0x10, - 0x1b, 0xc3, 0x61, 0x22, 0x8e, 0xf2, 0xa6, 0xb4, 0xdb, 0xa5, 0x7e, 0xdb, 0x6d, 0xf9, 0xff, 0xa5, - 0x70, 0x11, 0xf2, 0x5b, 0xe0, 0x5e, 0xa7, 0x4c, 0x09, 0x89, 0x50, 0x77, 0x64, 0xa4, 0x77, 0xbf, - 0xb7, 0x06, 0xea, 0x7e, 0x83, 0xe2, 0xd9, 0xbb, 0xfd, 0xfd, 0x5c, 0x82, 0x99, 0x7b, 0x8d, 0xfb, - 0x96, 0xe1, 0x98, 0x9e, 0x39, 0xeb, 0xa6, 0xeb, 0xd7, 0xb7, 0xa1, 0x60, 0x39, 0x9a, 0x37, 0x8f, - 0xd7, 0xbc, 0x79, 0x60, 0x47, 0x63, 0xf3, 0x98, 0x8e, 0x49, 0xb9, 0x93, 0x60, 0x02, 0x68, 0x0d, - 0x86, 0x2d, 0x45, 0x6f, 0x13, 0xaf, 0xac, 0x5e, 0xea, 0x61, 0xfd, 0xf2, 0x12, 0x66, 0xec, 0xa1, - 0xe6, 0x8d, 0x4b, 0x63, 0x81, 0x22, 0xff, 0xbd, 0x04, 0x13, 0x0f, 0x36, 0x37, 0x37, 0x96, 0x75, - 0xbe, 0xa3, 0xf9, 0x79, 0xfa, 0x45, 0x28, 0x98, 0x0a, 0xdd, 0x8d, 0x57, 0x7a, 0x46, 0xc3, 0x9c, - 0x82, 0x3e, 0x80, 0x22, 0xcb, 0x24, 0x44, 0x6f, 0xf5, 0xd9, 0x6a, 0x0b, 0xf8, 0xba, 0x2b, 0x14, - 0x74, 0x88, 0x62, 0x00, 0x7b, 0x70, 0xf2, 0x1e, 0x9c, 0x0b, 0x99, 0xc3, 0xfc, 0xc1, 0x8f, 0x81, - 0x51, 0x03, 0x86, 0x98, 0x66, 0xef, 0x94, 0xb7, 0xd7, 0x61, 0x66, 0x6c, 0x4a, 0x41, 0xa7, 0xc3, - 0x7e, 0xd9, 0xd8, 0xc5, 0x92, 0x57, 0x61, 0x8c, 0x5f, 0x22, 0x18, 0x16, 0xe5, 0x6e, 0x41, 0x17, - 0x20, 0xdf, 0x51, 0x75, 0x51, 0x67, 0x47, 0x85, 0x4c, 0x9e, 0xd5, 0x08, 0x36, 0xce, 0xc9, 0xca, - 0x81, 0xc8, 0x3c, 0x01, 0x59, 0x39, 0xc0, 0x6c, 0x5c, 0xbe, 0x0f, 0x45, 0xe1, 0xee, 0x30, 0x50, - 0xfe, 0x78, 0xa0, 0x7c, 0x0a, 0xd0, 0x3a, 0x14, 0x97, 0x37, 0xea, 0x9a, 0xe1, 0x76, 0x5d, 0x4d, - 0xb5, 0x65, 0xc5, 0xd7, 0x62, 0x71, 0x79, 0x09, 0x63, 0x4e, 0x41, 0x32, 0x0c, 0x93, 0x83, 0x26, - 0x31, 0x29, 0x8f, 0x88, 0x91, 0x3a, 0xb0, 0x55, 0xbe, 0xcb, 0x47, 0xb0, 0xa0, 0xc8, 0xff, 0x90, - 0x83, 0xa2, 0x70, 0xc7, 0x29, 0x7c, 0x85, 0xad, 0x44, 0xbe, 0xc2, 0x5e, 0xef, 0x2f, 0x34, 0x32, - 0x3f, 0xc1, 0x36, 0x63, 0x9f, 0x60, 0x57, 0xfb, 0xc4, 0x3b, 0xfe, 0xfb, 0xeb, 0x7f, 0x24, 0x18, - 0x8f, 0x06, 0x25, 0xba, 0x09, 0xa3, 0xac, 0xe0, 0xa8, 0x4d, 0xb2, 0x16, 0xf4, 0xb9, 0xfe, 0x21, - 0x4c, 0x23, 0x20, 0xe1, 0x30, 0x1f, 0x6a, 0xfb, 0x62, 0x2c, 0x8e, 0xc4, 0xa4, 0xb3, 0x5d, 0xea, - 0x50, 0x55, 0xab, 0xba, 0x17, 0x63, 0xd5, 0x65, 0x9d, 0xae, 0x5b, 0x0d, 0x6a, 0xa9, 0x7a, 0x3b, - 0xa1, 0x88, 0x07, 0x65, 0x18, 0x59, 0xfe, 0x3f, 0x09, 0x46, 0x85, 0xc9, 0xa7, 0xf0, 0x55, 0xf1, - 0xc7, 0xd1, 0xaf, 0x8a, 0x4b, 0x7d, 0x6e, 0xf0, 0xf4, 0x4f, 0x8a, 0xff, 0x08, 0x4c, 0x67, 0x5b, - 0x9a, 0x45, 0xf5, 0xae, 0x61, 0xd3, 0x78, 0x54, 0xb3, 0xcd, 0x88, 0x39, 0x05, 0x39, 0x30, 0xa9, - 0xc6, 0x72, 0x80, 0x70, 0x6d, 0xad, 0x3f, 0x4b, 0x7c, 0xb1, 0x7a, 0x59, 0xc0, 0x4f, 0xc6, 0x29, - 0x38, 0xa1, 0x42, 0x26, 0x90, 0xe0, 0x42, 0x0f, 0xa1, 0xb0, 0x4b, 0xa9, 0x99, 0x72, 0x5e, 0xdd, - 0x23, 0xf3, 0x04, 0x26, 0x94, 0xf8, 0xec, 0x36, 0x37, 0x37, 0x30, 0x87, 0x92, 0x7f, 0x15, 0xf8, - 0xa3, 0xe1, 0xc6, 0xb8, 0x9f, 0x4f, 0xa5, 0x93, 0xe4, 0xd3, 0xd1, 0xb4, 0x5c, 0x8a, 0x1e, 0x40, - 0x9e, 0x6a, 0xfd, 0x7e, 0x16, 0x0a, 0xc4, 0xcd, 0x95, 0x46, 0x90, 0x90, 0x36, 0x57, 0x1a, 0x98, - 0x41, 0xa0, 0x75, 0x18, 0x62, 0xd5, 0x87, 0x6d, 0xc1, 0x7c, 0xff, 0x5b, 0x9a, 0xcd, 0x3f, 0x08, - 0x08, 0xf6, 0xcb, 0xc6, 0x2e, 0x8e, 0xfc, 0x09, 0x8c, 0x45, 0xf6, 0x29, 0xfa, 0x18, 0xce, 0x6a, - 0x86, 0xd2, 0xaa, 0x2b, 0x9a, 0xa2, 0x37, 0x89, 0x77, 0x39, 0x70, 0x29, 0xed, 0x0b, 0x63, 0x25, - 0xc4, 0x27, 0x76, 0xb9, 0x7f, 0x9d, 0x1a, 0xa6, 0xe1, 0x08, 0xa2, 0xac, 0x00, 0x04, 0x73, 0x44, - 0x15, 0x18, 0x62, 0x71, 0xe6, 0xd6, 0x93, 0x91, 0xfa, 0x08, 0xb3, 0x90, 0x85, 0x9f, 0x8d, 0xdd, - 0x71, 0x74, 0x03, 0xc0, 0x26, 0x4d, 0x8b, 0x50, 0x9e, 0x0c, 0x72, 0xd1, 0x4b, 0xe5, 0x86, 0x4f, - 0xc1, 0x21, 0x2e, 0xf9, 0x47, 0x12, 0x8c, 0xad, 0x11, 0xfa, 0xa9, 0x61, 0xed, 0x6d, 0xf0, 0xc7, - 0x00, 0xa7, 0x90, 0x6c, 0x71, 0x24, 0xd9, 0xbe, 0xd1, 0x63, 0x65, 0x22, 0xd6, 0x65, 0xa5, 0x5c, - 0xf9, 0x4b, 0x09, 0x66, 0x23, 0x9c, 0x77, 0x83, 0xad, 0xbb, 0x05, 0x43, 0xa6, 0x61, 0x51, 0xaf, - 0x10, 0x0f, 0xa4, 0x90, 0xa5, 0xb1, 0x50, 0x29, 0x66, 0x30, 0xd8, 0x45, 0x43, 0x2b, 0x90, 0xa3, - 0x86, 0x08, 0xd5, 0xc1, 0x30, 0x09, 0xb1, 0xea, 0x20, 0x30, 0x73, 0x9b, 0x06, 0xce, 0x51, 0x83, - 0x2d, 0x44, 0x39, 0xc2, 0x15, 0x4e, 0x3e, 0x2f, 0x68, 0x06, 0x18, 0x0a, 0x3b, 0x96, 0xd1, 0x39, - 0xf1, 0x1c, 0xfc, 0x85, 0xb8, 0x67, 0x19, 0x1d, 0xcc, 0xb1, 0xe4, 0xaf, 0x24, 0x98, 0x8a, 0x70, - 0x9e, 0x42, 0xe2, 0x7f, 0x18, 0x4d, 0xfc, 0x57, 0x07, 0x99, 0x48, 0x46, 0xfa, 0xff, 0x2a, 0x17, - 0x9b, 0x06, 0x9b, 0x30, 0xda, 0x81, 0x51, 0xd3, 0x68, 0x35, 0x9e, 0xc3, 0x75, 0xe0, 0x04, 0xab, - 0x9b, 0x1b, 0x01, 0x16, 0x0e, 0x03, 0xa3, 0x03, 0x98, 0xd2, 0x95, 0x0e, 0xb1, 0x4d, 0xa5, 0x49, - 0x1a, 0xcf, 0xe1, 0x80, 0xe4, 0x25, 0x7e, 0xdf, 0x10, 0x47, 0xc4, 0x49, 0x25, 0x68, 0x15, 0x8a, - 0xaa, 0xc9, 0xfb, 0x38, 0xd1, 0xbb, 0xf4, 0xac, 0xa2, 0x6e, 0xd7, 0xe7, 0xe6, 0x73, 0xf1, 0x03, - 0x7b, 0x18, 0xf2, 0x7f, 0xc6, 0xa3, 0x81, 0xc5, 0x1f, 0xba, 0x0f, 0x25, 0xfe, 0xac, 0xa6, 0x69, - 0x68, 0xde, 0xcd, 0x00, 0x5b, 0xd9, 0x0d, 0x31, 0xf6, 0xec, 0xb0, 0x72, 0x3e, 0xe5, 0xd0, 0xd7, - 0x23, 0x63, 0x5f, 0x18, 0xad, 0x41, 0xc1, 0xfc, 0x21, 0x1d, 0x0c, 0x2f, 0x72, 0xbc, 0x6d, 0xe1, - 0x38, 0xf2, 0x5f, 0xe7, 0x63, 0xe6, 0xf2, 0x52, 0xf7, 0xe4, 0xb9, 0xad, 0xba, 0xdf, 0x31, 0x65, - 0xae, 0xfc, 0x36, 0x14, 0x45, 0x85, 0x17, 0xc1, 0xfc, 0xf6, 0x20, 0xc1, 0x1c, 0xae, 0x62, 0xfe, - 0x07, 0x8b, 0x37, 0xe8, 0x01, 0xa3, 0x8f, 0x60, 0x98, 0xb8, 0x2a, 0xdc, 0xda, 0x78, 0x6b, 0x10, - 0x15, 0x41, 0x5e, 0x0d, 0x1a, 0x55, 0x31, 0x26, 0x50, 0xd1, 0x7b, 0xcc, 0x5f, 0x8c, 0x97, 0x7d, - 0x04, 0xda, 0xe5, 0x02, 0x2f, 0x57, 0x17, 0xdc, 0x69, 0xfb, 0xc3, 0xcf, 0x0e, 0x2b, 0x10, 0xfc, - 0xc4, 0x61, 0x09, 0xf9, 0x27, 0x12, 0x4c, 0x71, 0x0f, 0x35, 0x1d, 0x4b, 0xa5, 0xdd, 0x53, 0x2b, - 0x4c, 0x8f, 0x22, 0x85, 0xe9, 0xad, 0x1e, 0x6e, 0x49, 0x58, 0x98, 0x59, 0x9c, 0xbe, 0x96, 0xe0, - 0xa5, 0x04, 0xf7, 0x29, 0xe4, 0xc5, 0xad, 0x68, 0x5e, 0x7c, 0x63, 0xd0, 0x09, 0x65, 0xbd, 0x91, - 0x18, 0x4b, 0x99, 0x0e, 0xdf, 0x29, 0x37, 0x00, 0x4c, 0x4b, 0xdd, 0x57, 0x35, 0xd2, 0x16, 0x97, - 0xe0, 0xa5, 0xd0, 0xb3, 0x36, 0x9f, 0x82, 0x43, 0x5c, 0xc8, 0x86, 0x99, 0x16, 0xd9, 0x51, 0x1c, - 0x8d, 0x2e, 0xb4, 0x5a, 0x8b, 0x8a, 0xa9, 0x6c, 0xab, 0x9a, 0x4a, 0x55, 0x71, 0x5c, 0x30, 0x52, - 0xbf, 0xe3, 0x5e, 0x4e, 0xa7, 0x71, 0x3c, 0x3b, 0xac, 0x5c, 0x48, 0xbb, 0x1d, 0xf2, 0x58, 0xba, - 0x38, 0x03, 0x1a, 0x75, 0xa1, 0x6c, 0x91, 0x4f, 0x1c, 0xd5, 0x22, 0xad, 0x25, 0xcb, 0x30, 0x23, - 0x6a, 0xf3, 0x5c, 0xed, 0x1f, 0x1e, 0x1d, 0x56, 0xca, 0x38, 0x83, 0xa7, 0xb7, 0xe2, 0x4c, 0x78, - 0xf4, 0x04, 0xa6, 0x15, 0xf7, 0x35, 0x60, 0x44, 0xab, 0xbb, 0x4b, 0x6e, 0x1f, 0x1d, 0x56, 0xa6, - 0x17, 0x92, 0xe4, 0xde, 0x0a, 0xd3, 0x40, 0x51, 0x0d, 0x8a, 0xfb, 0xfc, 0xad, 0xa2, 0x5d, 0x1e, - 0xe2, 0xf8, 0xac, 0x10, 0x14, 0xdd, 0xe7, 0x8b, 0x0c, 0x73, 0xf8, 0x5e, 0x83, 0xef, 0x3e, 0x8f, - 0x8b, 0x7d, 0x50, 0xb2, 0x5e, 0x52, 0xec, 0x78, 0x7e, 0x62, 0x5c, 0x0a, 0xb2, 0xd6, 0x83, 0x80, - 0x84, 0xc3, 0x7c, 0xe8, 0x31, 0x8c, 0xec, 0x8a, 0x53, 0x09, 0xbb, 0x5c, 0xec, 0xab, 0x08, 0x47, - 0x4e, 0x31, 0xea, 0x53, 0x42, 0xc5, 0x88, 0x37, 0x6c, 0xe3, 0x00, 0x11, 0x5d, 0x81, 0x22, 0xff, - 0xb1, 0xbc, 0xc4, 0x8f, 0xe3, 0x4a, 0x41, 0x6e, 0x7b, 0xe0, 0x0e, 0x63, 0x8f, 0xee, 0xb1, 0x2e, - 0x6f, 0x2c, 0xf2, 0x63, 0xe1, 0x18, 0xeb, 0xf2, 0xc6, 0x22, 0xf6, 0xe8, 0xe8, 0x63, 0x28, 0xda, - 0x64, 0x45, 0xd5, 0x9d, 0x83, 0x32, 0xf4, 0x75, 0xa9, 0xdc, 0xb8, 0xcb, 0xb9, 0x63, 0x07, 0x63, - 0x81, 0x06, 0x41, 0xc7, 0x1e, 0x2c, 0xda, 0x85, 0x11, 0xcb, 0xd1, 0x17, 0xec, 0x2d, 0x9b, 0x58, - 0xe5, 0x51, 0xae, 0xa3, 0x57, 0x3a, 0xc7, 0x1e, 0x7f, 0x5c, 0x8b, 0xef, 0x21, 0x9f, 0x03, 0x07, - 0xe0, 0xe8, 0xef, 0x24, 0x40, 0xb6, 0x63, 0x9a, 0x1a, 0xe9, 0x10, 0x9d, 0x2a, 0x1a, 0x3f, 0x8b, - 0xb3, 0xcb, 0x67, 0xb9, 0xce, 0x3f, 0xea, 0x35, 0xaf, 0x84, 0x60, 0x5c, 0xb9, 0x7f, 0xe8, 0x9d, - 0x64, 0xc5, 0x29, 0x7a, 0x99, 0x6b, 0x77, 0x6c, 0xfe, 0x77, 0x79, 0xac, 0x2f, 0xd7, 0xa6, 0x9f, - 0x39, 0x06, 0xae, 0x15, 0x74, 0xec, 0xc1, 0xa2, 0x47, 0x30, 0x63, 0x11, 0xa5, 0xb5, 0xae, 0x6b, - 0x5d, 0x6c, 0x18, 0xf4, 0x9e, 0xaa, 0x11, 0xbb, 0x6b, 0x53, 0xd2, 0x29, 0x8f, 0xf3, 0x65, 0xf7, - 0xdf, 0x7e, 0xe0, 0x54, 0x2e, 0x9c, 0x21, 0x8d, 0x3a, 0x50, 0xf1, 0x52, 0x06, 0xdb, 0x4f, 0x7e, - 0xce, 0xba, 0x6b, 0x37, 0x15, 0xcd, 0xbd, 0x07, 0x98, 0xe0, 0x0a, 0x5e, 0x3b, 0x3a, 0xac, 0x54, - 0x96, 0x8e, 0x67, 0xc5, 0xbd, 0xb0, 0xd0, 0x07, 0x50, 0x56, 0xb2, 0xf4, 0x4c, 0x72, 0x3d, 0xaf, - 0xb0, 0x3c, 0x94, 0xa9, 0x20, 0x53, 0x1a, 0x51, 0x98, 0x54, 0xa2, 0x8f, 0x8e, 0xed, 0xf2, 0x54, - 0x5f, 0x07, 0x91, 0xb1, 0xb7, 0xca, 0xc1, 0x61, 0x44, 0x8c, 0x60, 0xe3, 0x84, 0x06, 0xf4, 0x17, - 0x80, 0x94, 0xf8, 0x3b, 0x69, 0xbb, 0x8c, 0xfa, 0x2a, 0x3f, 0x89, 0x07, 0xd6, 0x41, 0xd8, 0x25, - 0x48, 0x36, 0x4e, 0xd1, 0xc3, 0x1f, 0x6f, 0x88, 0xa3, 0xfc, 0xd3, 0x79, 0x00, 0x3b, 0xd8, 0xe3, - 0x8d, 0xc0, 0xb4, 0xe7, 0xf6, 0x78, 0x23, 0x04, 0x79, 0xfc, 0xe1, 0xe1, 0x2f, 0x72, 0x30, 0x1d, - 0x30, 0xf7, 0xfd, 0x78, 0x23, 0x45, 0xe4, 0x77, 0x8f, 0x60, 0x7b, 0x3f, 0x82, 0xfd, 0x52, 0x82, - 0xf1, 0xc0, 0x75, 0xbf, 0x79, 0x0f, 0x2a, 0x02, 0xdb, 0x32, 0x5a, 0xbc, 0xff, 0xce, 0x85, 0x27, - 0xf0, 0x5b, 0x7f, 0xab, 0xff, 0xc3, 0x5f, 0xae, 0xca, 0x5f, 0xe7, 0x61, 0x32, 0xbe, 0x1b, 0x23, - 0x97, 0xbf, 0x52, 0xcf, 0xcb, 0xdf, 0x0d, 0x38, 0xb7, 0xe3, 0x68, 0x5a, 0x97, 0xbb, 0x21, 0x74, - 0x03, 0xec, 0x5e, 0xde, 0xbc, 0x22, 0x24, 0xcf, 0xdd, 0x4b, 0xe1, 0xc1, 0xa9, 0x92, 0x19, 0x17, - 0xd9, 0xf9, 0x13, 0x5d, 0x64, 0x27, 0xee, 0x55, 0x0b, 0x03, 0xdc, 0xab, 0xa6, 0x5e, 0x4a, 0x0f, - 0x9d, 0xe0, 0x52, 0xfa, 0x24, 0xb7, 0xc8, 0x29, 0x49, 0xac, 0xe7, 0xa3, 0xc6, 0x57, 0x60, 0x4e, - 0x88, 0x51, 0x7e, 0xc1, 0xab, 0x53, 0xcb, 0xd0, 0x34, 0x62, 0x2d, 0x39, 0x9d, 0x4e, 0x57, 0x7e, - 0x17, 0xc6, 0xa3, 0x4f, 0x17, 0xdc, 0x95, 0x76, 0x5f, 0x4f, 0x88, 0x2b, 0xb4, 0xd0, 0x4a, 0xbb, - 0xe3, 0xd8, 0xe7, 0x90, 0xff, 0x46, 0x82, 0x99, 0xf4, 0x27, 0x8a, 0x48, 0x83, 0xf1, 0x8e, 0x72, - 0x10, 0x7e, 0x36, 0x2a, 0x9d, 0xf0, 0x70, 0x83, 0xdf, 0x59, 0xaf, 0x46, 0xb0, 0x70, 0x0c, 0x5b, - 0xfe, 0x5e, 0x82, 0xd9, 0x8c, 0xdb, 0xe2, 0xd3, 0xb5, 0x04, 0x7d, 0x08, 0xa5, 0x8e, 0x72, 0xd0, - 0x70, 0xac, 0x36, 0x39, 0xf1, 0x71, 0x0e, 0xcf, 0x18, 0xab, 0x02, 0x05, 0xfb, 0x78, 0xf2, 0xe7, - 0x12, 0x94, 0xb3, 0x1a, 0x6b, 0x74, 0x33, 0x72, 0xaf, 0xfd, 0x6a, 0xec, 0x5e, 0x7b, 0x2a, 0x21, - 0xf7, 0x82, 0x6e, 0xb5, 0xff, 0x4b, 0x82, 0x99, 0xf4, 0x0f, 0x0c, 0xf4, 0x66, 0xc4, 0xc2, 0x4a, - 0xcc, 0xc2, 0x89, 0x98, 0x94, 0xb0, 0xef, 0x23, 0x18, 0x17, 0x9f, 0x21, 0x02, 0x46, 0x78, 0x55, - 0x4e, 0xcb, 0x95, 0x02, 0xc2, 0x6b, 0xbb, 0xf9, 0x7a, 0x45, 0xc7, 0x70, 0x0c, 0x4d, 0xfe, 0xdb, - 0x1c, 0x0c, 0x35, 0x9a, 0x8a, 0x46, 0x4e, 0xa1, 0xcd, 0x7a, 0x3f, 0xd2, 0x66, 0xf5, 0xfa, 0x17, - 0x0f, 0x6e, 0x55, 0x66, 0x87, 0x85, 0x63, 0x1d, 0xd6, 0xeb, 0x7d, 0xa1, 0x1d, 0xdf, 0x5c, 0xfd, - 0x01, 0x8c, 0xf8, 0x4a, 0x07, 0xcb, 0xf9, 0xf2, 0xbf, 0xe7, 0x60, 0x34, 0xa4, 0x62, 0xc0, 0x8a, - 0xb1, 0x13, 0xa9, 0xb4, 0xfd, 0xfc, 0x63, 0x5d, 0x48, 0x57, 0xd5, 0xab, 0xad, 0xee, 0x13, 0xc5, - 0xe0, 0x51, 0x5a, 0xb2, 0xe4, 0xbe, 0x0b, 0xe3, 0x94, 0xff, 0xe3, 0x99, 0x7f, 0x08, 0x9a, 0xe7, - 0xb1, 0xe8, 0x3f, 0x6c, 0xdd, 0x8c, 0x50, 0x71, 0x8c, 0x7b, 0xee, 0x0e, 0x8c, 0x45, 0x94, 0x0d, - 0xf4, 0xc2, 0xf0, 0x7f, 0x25, 0x78, 0xb5, 0xe7, 0x27, 0x2a, 0xaa, 0x47, 0x36, 0x49, 0x35, 0xb6, - 0x49, 0xe6, 0xb3, 0x01, 0x5e, 0xdc, 0x4b, 0x95, 0xfa, 0xb5, 0xa7, 0xdf, 0xcd, 0x9f, 0xf9, 0xe6, - 0xbb, 0xf9, 0x33, 0xdf, 0x7e, 0x37, 0x7f, 0xe6, 0xaf, 0x8e, 0xe6, 0xa5, 0xa7, 0x47, 0xf3, 0xd2, - 0x37, 0x47, 0xf3, 0xd2, 0xb7, 0x47, 0xf3, 0xd2, 0xcf, 0x8e, 0xe6, 0xa5, 0x7f, 0xfc, 0x7e, 0xfe, - 0xcc, 0x87, 0x45, 0x01, 0xf7, 0xeb, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb1, 0xb3, 0xc8, 0xe2, 0x54, - 0x3c, 0x00, 0x00, + // 3627 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0xcd, 0x6f, 0x1c, 0xc7, + 0x72, 0xd7, 0xec, 0x2e, 0xb9, 0xcb, 0xa2, 0xf8, 0xd5, 0xa4, 0xc9, 0xb5, 0x64, 0x71, 0xe5, 0x31, + 0xa0, 0xc8, 0x8e, 0xb4, 0x6b, 0xc9, 0x96, 0xac, 0x58, 0x88, 0x6d, 0x2e, 0x29, 0x4a, 0x74, 0xf8, + 0xa5, 0x5e, 0x52, 0x71, 0x8c, 0xc8, 0xf1, 0x70, 0xb7, 0xb9, 0x1c, 0x71, 0x76, 0x66, 0x3c, 0xd3, + 0x43, 0x73, 0x81, 0x20, 0xc8, 0x21, 0x08, 0x10, 0x20, 0x41, 0x92, 0x83, 0xf3, 0x71, 0x8b, 0x2f, + 0x39, 0x25, 0x48, 0x6e, 0xc9, 0xc1, 0x30, 0x10, 0xc0, 0x01, 0x84, 0xc0, 0x01, 0x7c, 0x8b, 0x4f, + 0x44, 0x4c, 0x9f, 0x82, 0xfc, 0x03, 0x0f, 0x3a, 0x3c, 0x3c, 0x74, 0x4f, 0xcf, 0xf7, 0x0c, 0x77, + 0x97, 0x96, 0x88, 0x87, 0x87, 0x77, 0xe3, 0x76, 0x55, 0xfd, 0xaa, 0xba, 0xba, 0xba, 0xaa, 0xa6, + 0xbb, 0x09, 0xcb, 0xfb, 0x77, 0xec, 0xaa, 0x6a, 0xd4, 0xf6, 0x9d, 0x1d, 0x62, 0xe9, 0x84, 0x12, + 0xbb, 0x76, 0x40, 0xf4, 0x96, 0x61, 0xd5, 0x04, 0x41, 0x31, 0xd5, 0x1a, 0x39, 0xa4, 0x44, 0xb7, + 0x55, 0x43, 0xb7, 0x6b, 0x07, 0x37, 0x76, 0x08, 0x55, 0x6e, 0xd4, 0xda, 0x44, 0x27, 0x96, 0x42, + 0x49, 0xab, 0x6a, 0x5a, 0x06, 0x35, 0xd0, 0x25, 0x97, 0xbd, 0xaa, 0x98, 0x6a, 0x35, 0x60, 0xaf, + 0x0a, 0xf6, 0x0b, 0xd7, 0xdb, 0x2a, 0xdd, 0x73, 0x76, 0xaa, 0x4d, 0xa3, 0x53, 0x6b, 0x1b, 0x6d, + 0xa3, 0xc6, 0xa5, 0x76, 0x9c, 0x5d, 0xfe, 0x8b, 0xff, 0xe0, 0x7f, 0xb9, 0x68, 0x17, 0xe4, 0x90, + 0xf2, 0xa6, 0x61, 0x91, 0xda, 0x41, 0x42, 0xe3, 0x85, 0xb7, 0x03, 0x9e, 0x8e, 0xd2, 0xdc, 0x53, + 0x75, 0x62, 0x75, 0x6b, 0xe6, 0x7e, 0x9b, 0x0b, 0x59, 0xc4, 0x36, 0x1c, 0xab, 0x49, 0x06, 0x92, + 0xb2, 0x6b, 0x1d, 0x42, 0x95, 0x34, 0x5d, 0xb5, 0x2c, 0x29, 0xcb, 0xd1, 0xa9, 0xda, 0x49, 0xaa, + 0xb9, 0xdd, 0x4b, 0xc0, 0x6e, 0xee, 0x91, 0x8e, 0x92, 0x90, 0x7b, 0x2b, 0x4b, 0xce, 0xa1, 0xaa, + 0x56, 0x53, 0x75, 0x6a, 0x53, 0x2b, 0x2e, 0x24, 0xdf, 0x85, 0xa9, 0x05, 0x4d, 0x33, 0x3e, 0x27, + 0xad, 0x65, 0x8d, 0x1c, 0x3e, 0x32, 0x34, 0xa7, 0x43, 0xd0, 0x15, 0x18, 0x6e, 0x59, 0xea, 0x01, + 0xb1, 0xca, 0xd2, 0x65, 0xe9, 0xea, 0x48, 0x7d, 0xfc, 0xe9, 0x51, 0xe5, 0xdc, 0xf1, 0x51, 0x65, + 0x78, 0x89, 0x8f, 0x62, 0x41, 0x95, 0x6d, 0x98, 0x10, 0xc2, 0x0f, 0x0c, 0x9b, 0x6e, 0x2a, 0x74, + 0x0f, 0xdd, 0x04, 0x30, 0x15, 0xba, 0xb7, 0x69, 0x91, 0x5d, 0xf5, 0x50, 0x88, 0x23, 0x21, 0x0e, + 0x9b, 0x3e, 0x05, 0x87, 0xb8, 0xd0, 0x35, 0x28, 0x59, 0x44, 0x69, 0x6d, 0xe8, 0x5a, 0xb7, 0x9c, + 0xbb, 0x2c, 0x5d, 0x2d, 0xd5, 0x27, 0x85, 0x44, 0x09, 0x8b, 0x71, 0xec, 0x73, 0xc8, 0x7f, 0x2f, + 0xc1, 0xcb, 0x8b, 0x8e, 0x4d, 0x8d, 0xce, 0x1a, 0xa1, 0x96, 0xda, 0x5c, 0x74, 0x2c, 0x8b, 0xe8, + 0xb4, 0x41, 0x15, 0xea, 0xd8, 0xe8, 0x32, 0x14, 0x74, 0xa5, 0x43, 0x84, 0xe6, 0xf3, 0x02, 0xa7, + 0xb0, 0xae, 0x74, 0x08, 0xe6, 0x14, 0xf4, 0x31, 0x0c, 0x1d, 0x28, 0x9a, 0x43, 0xb8, 0xaa, 0xd1, + 0x9b, 0xd5, 0x6a, 0x10, 0x7d, 0xbe, 0xdb, 0xaa, 0xe6, 0x7e, 0x9b, 0x87, 0xa3, 0x17, 0x0b, 0xd5, + 0x87, 0x8e, 0xa2, 0x53, 0x95, 0x76, 0xeb, 0x33, 0x02, 0xf2, 0xbc, 0xd0, 0xfb, 0x88, 0x61, 0x61, + 0x17, 0x52, 0xfe, 0x23, 0xb8, 0x94, 0x69, 0xda, 0xaa, 0x6a, 0x53, 0xf4, 0x18, 0x86, 0x54, 0x4a, + 0x3a, 0x76, 0x59, 0xba, 0x9c, 0xbf, 0x3a, 0x7a, 0xf3, 0x4e, 0xf5, 0xc4, 0xd0, 0xaf, 0x66, 0x82, + 0xd5, 0xc7, 0x84, 0x19, 0x43, 0x2b, 0x0c, 0x0e, 0xbb, 0xa8, 0xf2, 0x5f, 0x4b, 0x80, 0xc2, 0x32, + 0x5b, 0x8a, 0xd5, 0x26, 0xb4, 0x0f, 0xa7, 0xfc, 0xde, 0x4f, 0x73, 0xca, 0xb4, 0x80, 0x1c, 0x75, + 0x15, 0x46, 0x7c, 0x62, 0xc2, 0x6c, 0xd2, 0x24, 0xee, 0x8c, 0x47, 0x51, 0x67, 0xdc, 0x18, 0xc0, + 0x19, 0x2e, 0x4a, 0x86, 0x17, 0xbe, 0xc8, 0xc1, 0xc8, 0x92, 0x42, 0x3a, 0x86, 0xde, 0x20, 0x14, + 0x7d, 0x0a, 0x25, 0xb6, 0x35, 0x5b, 0x0a, 0x55, 0xb8, 0x03, 0x46, 0x6f, 0xbe, 0x79, 0xd2, 0xec, + 0xec, 0x2a, 0xe3, 0xae, 0x1e, 0xdc, 0xa8, 0x6e, 0xec, 0x3c, 0x21, 0x4d, 0xba, 0x46, 0xa8, 0x12, + 0x44, 0x70, 0x30, 0x86, 0x7d, 0x54, 0xb4, 0x0e, 0x05, 0xdb, 0x24, 0x4d, 0xe1, 0xbb, 0x6b, 0x3d, + 0xa6, 0xe1, 0x5b, 0xd6, 0x30, 0x49, 0x33, 0x58, 0x0c, 0xf6, 0x0b, 0x73, 0x1c, 0xf4, 0x08, 0x86, + 0x6d, 0xbe, 0xca, 0xe5, 0x7c, 0x62, 0x35, 0x4e, 0x46, 0x74, 0x63, 0xc3, 0xdf, 0xae, 0xee, 0x6f, + 0x2c, 0xd0, 0xe4, 0xff, 0xcb, 0x01, 0xf2, 0x79, 0x17, 0x0d, 0xbd, 0xa5, 0x52, 0xd5, 0xd0, 0xd1, + 0xbb, 0x50, 0xa0, 0x5d, 0xd3, 0x8b, 0x8e, 0x2b, 0x9e, 0x41, 0x5b, 0x5d, 0x93, 0x3c, 0x3b, 0xaa, + 0xcc, 0x26, 0x25, 0x18, 0x05, 0x73, 0x19, 0xb4, 0xea, 0x9b, 0x9a, 0xe3, 0xd2, 0x6f, 0x47, 0x55, + 0x3f, 0x3b, 0xaa, 0xa4, 0xa4, 0xe3, 0xaa, 0x8f, 0x14, 0x35, 0x10, 0x1d, 0x00, 0xd2, 0x14, 0x9b, + 0x6e, 0x59, 0x8a, 0x6e, 0xbb, 0x9a, 0xd4, 0x0e, 0x11, 0x4e, 0x78, 0xa3, 0xbf, 0x45, 0x63, 0x12, + 0xf5, 0x0b, 0xc2, 0x0a, 0xb4, 0x9a, 0x40, 0xc3, 0x29, 0x1a, 0x58, 0xbe, 0xb3, 0x88, 0x62, 0x1b, + 0x7a, 0xb9, 0x10, 0xcd, 0x77, 0x98, 0x8f, 0x62, 0x41, 0x45, 0xaf, 0x43, 0xb1, 0x43, 0x6c, 0x5b, + 0x69, 0x93, 0xf2, 0x10, 0x67, 0x9c, 0x10, 0x8c, 0xc5, 0x35, 0x77, 0x18, 0x7b, 0x74, 0xf9, 0x2b, + 0x09, 0xc6, 0x7c, 0xcf, 0xf1, 0x68, 0xff, 0xfd, 0x44, 0x1c, 0x56, 0xfb, 0x9b, 0x12, 0x93, 0xe6, + 0x51, 0xe8, 0x67, 0x45, 0x6f, 0x24, 0x14, 0x83, 0x6b, 0xde, 0x5e, 0xca, 0xf1, 0xbd, 0x74, 0xb5, + 0xdf, 0x90, 0xc9, 0xd8, 0x42, 0x7f, 0x53, 0x08, 0x99, 0xcf, 0x42, 0x13, 0x3d, 0x86, 0x92, 0x4d, + 0x34, 0xd2, 0xa4, 0x86, 0x25, 0xcc, 0x7f, 0xab, 0x4f, 0xf3, 0x95, 0x1d, 0xa2, 0x35, 0x84, 0x68, + 0xfd, 0x3c, 0xb3, 0xdf, 0xfb, 0x85, 0x7d, 0x48, 0xf4, 0x10, 0x4a, 0x94, 0x74, 0x4c, 0x4d, 0xa1, + 0x5e, 0x0e, 0x7a, 0x2d, 0x3c, 0x05, 0x16, 0x39, 0x0c, 0x6c, 0xd3, 0x68, 0x6d, 0x09, 0x36, 0xbe, + 0x7d, 0x7c, 0x97, 0x78, 0xa3, 0xd8, 0x87, 0x41, 0x07, 0x30, 0xee, 0x98, 0x2d, 0xc6, 0x49, 0x59, + 0xc5, 0x6b, 0x77, 0x45, 0x24, 0xdd, 0xee, 0xd7, 0x37, 0xdb, 0x11, 0xe9, 0xfa, 0xac, 0xd0, 0x35, + 0x1e, 0x1d, 0xc7, 0x31, 0x2d, 0x68, 0x01, 0x26, 0x3a, 0xaa, 0xce, 0x2a, 0x57, 0xb7, 0x41, 0x9a, + 0x86, 0xde, 0xb2, 0x79, 0x58, 0x0d, 0xd5, 0xe7, 0x04, 0xc0, 0xc4, 0x5a, 0x94, 0x8c, 0xe3, 0xfc, + 0xe8, 0x43, 0x40, 0xde, 0x34, 0xee, 0xbb, 0x05, 0x5b, 0x35, 0x74, 0x1e, 0x73, 0xf9, 0x20, 0xb8, + 0xb7, 0x12, 0x1c, 0x38, 0x45, 0x0a, 0xad, 0xc2, 0x8c, 0x45, 0x0e, 0x54, 0x36, 0xc7, 0x07, 0xaa, + 0x4d, 0x0d, 0xab, 0xbb, 0xaa, 0x76, 0x54, 0x5a, 0x1e, 0xe6, 0x36, 0x95, 0x8f, 0x8f, 0x2a, 0x33, + 0x38, 0x85, 0x8e, 0x53, 0xa5, 0xe4, 0xbf, 0x1d, 0x86, 0x89, 0x58, 0xbe, 0x41, 0x8f, 0x60, 0xb6, + 0xe9, 0x16, 0xa7, 0x75, 0xa7, 0xb3, 0x43, 0xac, 0x46, 0x73, 0x8f, 0xb4, 0x1c, 0x8d, 0xb4, 0x78, + 0xa0, 0x0c, 0xd5, 0xe7, 0x85, 0xc5, 0xb3, 0x8b, 0xa9, 0x5c, 0x38, 0x43, 0x9a, 0x79, 0x41, 0xe7, + 0x43, 0x6b, 0xaa, 0x6d, 0xfb, 0x98, 0x39, 0x8e, 0xe9, 0x7b, 0x61, 0x3d, 0xc1, 0x81, 0x53, 0xa4, + 0x98, 0x8d, 0x2d, 0x62, 0xab, 0x16, 0x69, 0xc5, 0x6d, 0xcc, 0x47, 0x6d, 0x5c, 0x4a, 0xe5, 0xc2, + 0x19, 0xd2, 0xe8, 0x16, 0x8c, 0xba, 0xda, 0xf8, 0xfa, 0x89, 0x85, 0xf6, 0xcb, 0xe1, 0x7a, 0x40, + 0xc2, 0x61, 0x3e, 0x36, 0x35, 0x63, 0xc7, 0x26, 0xd6, 0x01, 0x69, 0x65, 0x2f, 0xf0, 0x46, 0x82, + 0x03, 0xa7, 0x48, 0xb1, 0xa9, 0xb9, 0x11, 0x98, 0x98, 0xda, 0x70, 0x74, 0x6a, 0xdb, 0xa9, 0x5c, + 0x38, 0x43, 0x9a, 0xc5, 0xb1, 0x6b, 0xf2, 0xc2, 0x81, 0xa2, 0x6a, 0xca, 0x8e, 0x46, 0xca, 0xc5, + 0x68, 0x1c, 0xaf, 0x47, 0xc9, 0x38, 0xce, 0x8f, 0xee, 0xc3, 0x94, 0x3b, 0xb4, 0xad, 0x2b, 0x3e, + 0x48, 0x89, 0x83, 0xbc, 0x2c, 0x40, 0xa6, 0xd6, 0xe3, 0x0c, 0x38, 0x29, 0x83, 0xde, 0x85, 0xf1, + 0xa6, 0xa1, 0x69, 0x3c, 0x1e, 0x17, 0x0d, 0x47, 0xa7, 0xe5, 0x11, 0x8e, 0x82, 0xd8, 0x7e, 0x5c, + 0x8c, 0x50, 0x70, 0x8c, 0x13, 0x11, 0x80, 0xa6, 0x57, 0x70, 0xec, 0x32, 0xf4, 0xd5, 0x6b, 0x24, + 0x8b, 0x5e, 0xd0, 0x03, 0xf8, 0x43, 0x36, 0x0e, 0x01, 0xcb, 0xff, 0x25, 0xc1, 0x5c, 0x46, 0xea, + 0x40, 0xef, 0x47, 0x4a, 0xec, 0x6f, 0xc6, 0x4a, 0xec, 0xc5, 0x0c, 0xb1, 0x50, 0x9d, 0xd5, 0x61, + 0xcc, 0x62, 0xb3, 0xd2, 0xdb, 0x2e, 0x8b, 0xc8, 0x91, 0xb7, 0x7a, 0x4c, 0x03, 0x87, 0x65, 0x82, + 0x9c, 0x3f, 0x75, 0x7c, 0x54, 0x19, 0x8b, 0xd0, 0x70, 0x14, 0x5e, 0xfe, 0xbb, 0x1c, 0xc0, 0x12, + 0x31, 0x35, 0xa3, 0xdb, 0x21, 0xfa, 0x59, 0xf4, 0x50, 0x1b, 0x91, 0x1e, 0xea, 0x7a, 0xaf, 0xe5, + 0xf1, 0x4d, 0xcb, 0x6c, 0xa2, 0x7e, 0x37, 0xd6, 0x44, 0xd5, 0xfa, 0x87, 0x3c, 0xb9, 0x8b, 0xfa, + 0x9f, 0x3c, 0x4c, 0x07, 0xcc, 0x41, 0x1b, 0x75, 0x37, 0xb2, 0xc6, 0xbf, 0x11, 0x5b, 0xe3, 0xb9, + 0x14, 0x91, 0x17, 0xd6, 0x47, 0x3d, 0xff, 0x7e, 0x06, 0x3d, 0x81, 0x71, 0xd6, 0x38, 0xb9, 0xe1, + 0xc1, 0xdb, 0xb2, 0xe1, 0x81, 0xdb, 0x32, 0xbf, 0x80, 0xae, 0x46, 0x90, 0x70, 0x0c, 0x39, 0xa3, + 0x0d, 0x2c, 0xbe, 0xe8, 0x36, 0x50, 0xfe, 0x5a, 0x82, 0xf1, 0x60, 0x99, 0xce, 0xa0, 0x69, 0x5b, + 0x8f, 0x36, 0x6d, 0xaf, 0xf7, 0x1d, 0xa2, 0x19, 0x5d, 0xdb, 0xcf, 0x58, 0x83, 0xef, 0x33, 0xb1, + 0x0d, 0xbe, 0xa3, 0x34, 0xf7, 0xfb, 0xf8, 0xfc, 0xfb, 0x42, 0x02, 0x24, 0xaa, 0xc0, 0x82, 0xae, + 0x1b, 0x54, 0x71, 0x73, 0xa5, 0x6b, 0xd6, 0x4a, 0xdf, 0x66, 0x79, 0x1a, 0xab, 0xdb, 0x09, 0xac, + 0x7b, 0x3a, 0xb5, 0xba, 0xc1, 0x8a, 0x24, 0x19, 0x70, 0x8a, 0x01, 0x48, 0x01, 0xb0, 0x04, 0xe6, + 0x96, 0x21, 0x36, 0xf2, 0xf5, 0x3e, 0x72, 0x1e, 0x13, 0x58, 0x34, 0xf4, 0x5d, 0xb5, 0x1d, 0xa4, + 0x1d, 0xec, 0x03, 0xe1, 0x10, 0xe8, 0x85, 0x7b, 0x30, 0x97, 0x61, 0x2d, 0x9a, 0x84, 0xfc, 0x3e, + 0xe9, 0xba, 0x6e, 0xc3, 0xec, 0x4f, 0x34, 0x13, 0xfe, 0x4c, 0x1e, 0x11, 0x5f, 0xb8, 0xef, 0xe6, + 0xee, 0x48, 0xf2, 0x57, 0x43, 0xe1, 0xd8, 0xe1, 0x1d, 0xf3, 0x55, 0x28, 0x59, 0xc4, 0xd4, 0xd4, + 0xa6, 0x62, 0x8b, 0x46, 0xe8, 0xbc, 0x7b, 0xa4, 0xe1, 0x8e, 0x61, 0x9f, 0x1a, 0xe9, 0xad, 0x73, + 0x2f, 0xb6, 0xb7, 0xce, 0x3f, 0x9f, 0xde, 0xfa, 0x0f, 0xa0, 0x64, 0x7b, 0x5d, 0x75, 0x81, 0x43, + 0xde, 0x18, 0x20, 0xbf, 0x8a, 0x86, 0xda, 0x57, 0xe0, 0xb7, 0xd2, 0x3e, 0x68, 0x5a, 0x13, 0x3d, + 0x34, 0x60, 0x13, 0xfd, 0x5c, 0x1b, 0x5f, 0x96, 0x53, 0x4d, 0xc5, 0xb1, 0x49, 0x8b, 0x27, 0xa2, + 0x52, 0x90, 0x53, 0x37, 0xf9, 0x28, 0x16, 0x54, 0xf4, 0x38, 0x12, 0xb2, 0xa5, 0xd3, 0x84, 0xec, + 0x78, 0x76, 0xb8, 0xa2, 0x6d, 0x98, 0x33, 0x2d, 0xa3, 0x6d, 0x11, 0xdb, 0x5e, 0x22, 0x4a, 0x4b, + 0x53, 0x75, 0xe2, 0xf9, 0xc7, 0xed, 0x88, 0x2e, 0x1e, 0x1f, 0x55, 0xe6, 0x36, 0xd3, 0x59, 0x70, + 0x96, 0xac, 0xfc, 0xb4, 0x00, 0x93, 0xf1, 0x0a, 0x98, 0xd1, 0xa4, 0x4a, 0xa7, 0x6a, 0x52, 0xaf, + 0x85, 0x36, 0x83, 0xdb, 0xc1, 0x87, 0xce, 0xf8, 0x12, 0x1b, 0x62, 0x01, 0x26, 0x44, 0x36, 0xf0, + 0x88, 0xa2, 0x4d, 0xf7, 0x57, 0x7f, 0x3b, 0x4a, 0xc6, 0x71, 0x7e, 0xd6, 0x7a, 0x06, 0x1d, 0xa5, + 0x07, 0x52, 0x88, 0xb6, 0x9e, 0x0b, 0x71, 0x06, 0x9c, 0x94, 0x41, 0x6b, 0x30, 0xed, 0xe8, 0x49, + 0x28, 0x37, 0x1a, 0x2f, 0x0a, 0xa8, 0xe9, 0xed, 0x24, 0x0b, 0x4e, 0x93, 0x43, 0xbb, 0x91, 0x6e, + 0x74, 0x98, 0x67, 0xd8, 0x9b, 0x7d, 0xef, 0x9d, 0xbe, 0xdb, 0x51, 0x74, 0x17, 0xc6, 0x2c, 0xfe, + 0xdd, 0xe1, 0x19, 0xec, 0xf6, 0xee, 0x2f, 0x09, 0xb1, 0x31, 0x1c, 0x26, 0xe2, 0x28, 0x6f, 0x4a, + 0xbb, 0x5d, 0xea, 0xb7, 0xdd, 0x96, 0xff, 0x43, 0x0a, 0x17, 0x21, 0xbf, 0x05, 0xee, 0x75, 0xca, + 0x94, 0x90, 0x08, 0x75, 0x47, 0x46, 0x7a, 0xf7, 0x7b, 0x7b, 0xa0, 0xee, 0x37, 0x28, 0x9e, 0xbd, + 0xdb, 0xdf, 0x2f, 0x25, 0x98, 0x5d, 0x6e, 0xdc, 0xb7, 0x0c, 0xc7, 0xf4, 0xcc, 0xd9, 0x30, 0x5d, + 0xbf, 0xbe, 0x03, 0x05, 0xcb, 0xd1, 0xbc, 0x79, 0xbc, 0xe6, 0xcd, 0x03, 0x3b, 0x1a, 0x9b, 0xc7, + 0x74, 0x4c, 0xca, 0x9d, 0x04, 0x13, 0x40, 0xeb, 0x30, 0x6c, 0x29, 0x7a, 0x9b, 0x78, 0x65, 0xf5, + 0x4a, 0x0f, 0xeb, 0x57, 0x96, 0x30, 0x63, 0x0f, 0x35, 0x6f, 0x5c, 0x1a, 0x0b, 0x14, 0xf9, 0x2f, + 0x24, 0x98, 0x78, 0xb0, 0xb5, 0xb5, 0xb9, 0xa2, 0xf3, 0x1d, 0xcd, 0x4f, 0xdf, 0x2f, 0x43, 0xc1, + 0x54, 0xe8, 0x5e, 0xbc, 0xd2, 0x33, 0x1a, 0xe6, 0x14, 0xf4, 0x11, 0x14, 0x59, 0x26, 0x21, 0x7a, + 0xab, 0xcf, 0x56, 0x5b, 0xc0, 0xd7, 0x5d, 0xa1, 0xa0, 0x43, 0x14, 0x03, 0xd8, 0x83, 0x93, 0xf7, + 0x61, 0x26, 0x64, 0x0e, 0xf3, 0x07, 0x3f, 0x06, 0x46, 0x0d, 0x18, 0x62, 0x9a, 0xbd, 0x53, 0xde, + 0x5e, 0x87, 0x99, 0xb1, 0x29, 0x05, 0x9d, 0x0e, 0xfb, 0x65, 0x63, 0x17, 0x4b, 0x5e, 0x83, 0x31, + 0x7e, 0xe5, 0x60, 0x58, 0x94, 0xbb, 0x05, 0x5d, 0x82, 0x7c, 0x47, 0xd5, 0x45, 0x9d, 0x1d, 0x15, + 0x32, 0x79, 0x56, 0x23, 0xd8, 0x38, 0x27, 0x2b, 0x87, 0x22, 0xf3, 0x04, 0x64, 0xe5, 0x10, 0xb3, + 0x71, 0xf9, 0x3e, 0x14, 0x85, 0xbb, 0xc3, 0x40, 0xf9, 0x93, 0x81, 0xf2, 0x29, 0x40, 0x1b, 0x50, + 0x5c, 0xd9, 0xac, 0x6b, 0x86, 0xdb, 0x75, 0x35, 0xd5, 0x96, 0x15, 0x5f, 0x8b, 0xc5, 0x95, 0x25, + 0x8c, 0x39, 0x05, 0xc9, 0x30, 0x4c, 0x0e, 0x9b, 0xc4, 0xa4, 0x3c, 0x22, 0x46, 0xea, 0xc0, 0x56, + 0xf9, 0x1e, 0x1f, 0xc1, 0x82, 0x22, 0xff, 0x65, 0x0e, 0x8a, 0xc2, 0x1d, 0x67, 0xf0, 0x15, 0xb6, + 0x1a, 0xf9, 0x0a, 0x7b, 0xa3, 0xbf, 0xd0, 0xc8, 0xfc, 0x04, 0xdb, 0x8a, 0x7d, 0x82, 0x5d, 0xeb, + 0x13, 0xef, 0xe4, 0xef, 0xaf, 0x7f, 0x95, 0x60, 0x3c, 0x1a, 0x94, 0xe8, 0x16, 0x8c, 0xb2, 0x82, + 0xa3, 0x36, 0xc9, 0x7a, 0xd0, 0xe7, 0xfa, 0x87, 0x30, 0x8d, 0x80, 0x84, 0xc3, 0x7c, 0xa8, 0xed, + 0x8b, 0xb1, 0x38, 0x12, 0x93, 0xce, 0x76, 0xa9, 0x43, 0x55, 0xad, 0xea, 0x5e, 0xa3, 0x55, 0x57, + 0x74, 0xba, 0x61, 0x35, 0xa8, 0xa5, 0xea, 0xed, 0x84, 0x22, 0x1e, 0x94, 0x61, 0x64, 0xf9, 0xdf, + 0x25, 0x18, 0x15, 0x26, 0x9f, 0xc1, 0x57, 0xc5, 0xef, 0x44, 0xbf, 0x2a, 0xae, 0xf4, 0xb9, 0xc1, + 0xd3, 0x3f, 0x29, 0xfe, 0x31, 0x30, 0x9d, 0x6d, 0x69, 0x16, 0xd5, 0x7b, 0x86, 0x4d, 0xe3, 0x51, + 0xcd, 0x36, 0x23, 0xe6, 0x14, 0xe4, 0xc0, 0xa4, 0x1a, 0xcb, 0x01, 0xc2, 0xb5, 0xb5, 0xfe, 0x2c, + 0xf1, 0xc5, 0xea, 0x65, 0x01, 0x3f, 0x19, 0xa7, 0xe0, 0x84, 0x0a, 0x99, 0x40, 0x82, 0x0b, 0x3d, + 0x84, 0xc2, 0x1e, 0xa5, 0x66, 0xca, 0x79, 0x75, 0x8f, 0xcc, 0x13, 0x98, 0x50, 0xe2, 0xb3, 0xdb, + 0xda, 0xda, 0xc4, 0x1c, 0x4a, 0xfe, 0x79, 0xe0, 0x8f, 0x86, 0x1b, 0xe3, 0x7e, 0x3e, 0x95, 0x4e, + 0x93, 0x4f, 0x47, 0xd3, 0x72, 0x29, 0x7a, 0x00, 0x79, 0xaa, 0xf5, 0xfb, 0x59, 0x28, 0x10, 0xb7, + 0x56, 0x1b, 0x41, 0x42, 0xda, 0x5a, 0x6d, 0x60, 0x06, 0x81, 0x36, 0x60, 0x88, 0x55, 0x1f, 0xb6, + 0x05, 0xf3, 0xfd, 0x6f, 0x69, 0x36, 0xff, 0x20, 0x20, 0xd8, 0x2f, 0x1b, 0xbb, 0x38, 0xf2, 0x67, + 0x30, 0x16, 0xd9, 0xa7, 0xe8, 0x53, 0x38, 0xaf, 0x19, 0x4a, 0xab, 0xae, 0x68, 0x8a, 0xde, 0x24, + 0xde, 0xe5, 0xc0, 0x95, 0xb4, 0x2f, 0x8c, 0xd5, 0x10, 0x9f, 0xd8, 0xe5, 0xfe, 0x75, 0x6a, 0x98, + 0x86, 0x23, 0x88, 0xb2, 0x02, 0x10, 0xcc, 0x11, 0x55, 0x60, 0x88, 0xc5, 0x99, 0x5b, 0x4f, 0x46, + 0xea, 0x23, 0xcc, 0x42, 0x16, 0x7e, 0x36, 0x76, 0xc7, 0xd1, 0x4d, 0x00, 0x9b, 0x34, 0x2d, 0x42, + 0x79, 0x32, 0xc8, 0x45, 0xaf, 0xa0, 0x1b, 0x3e, 0x05, 0x87, 0xb8, 0xe4, 0xff, 0x94, 0x60, 0x6c, + 0x9d, 0xd0, 0xcf, 0x0d, 0x6b, 0x7f, 0xd3, 0xd0, 0xd4, 0x66, 0xf7, 0x0c, 0x92, 0x2d, 0x8e, 0x24, + 0xdb, 0x37, 0x7b, 0xac, 0x4c, 0xc4, 0xba, 0xac, 0x94, 0x2b, 0x7f, 0x2d, 0xc1, 0x5c, 0x84, 0xf3, + 0x5e, 0xb0, 0x75, 0xb7, 0x61, 0xc8, 0x34, 0x2c, 0xea, 0x15, 0xe2, 0x81, 0x14, 0xb2, 0x34, 0x16, + 0x2a, 0xc5, 0x0c, 0x06, 0xbb, 0x68, 0x68, 0x15, 0x72, 0xd4, 0x10, 0xa1, 0x3a, 0x18, 0x26, 0x21, + 0x56, 0x1d, 0x04, 0x66, 0x6e, 0xcb, 0xc0, 0x39, 0x6a, 0xb0, 0x85, 0x28, 0x47, 0xb8, 0xc2, 0xc9, + 0xe7, 0x05, 0xcd, 0x00, 0x43, 0x61, 0xd7, 0x32, 0x3a, 0xa7, 0x9e, 0x83, 0xbf, 0x10, 0xcb, 0x96, + 0xd1, 0xc1, 0x1c, 0x4b, 0xfe, 0x46, 0x82, 0xa9, 0x08, 0xe7, 0x19, 0x24, 0xfe, 0x87, 0xd1, 0xc4, + 0x7f, 0x6d, 0x90, 0x89, 0x64, 0xa4, 0xff, 0x6f, 0x72, 0xb1, 0x69, 0xb0, 0x09, 0xa3, 0x5d, 0x18, + 0x35, 0x8d, 0x56, 0xe3, 0x39, 0x5c, 0x07, 0x4e, 0xb0, 0xba, 0xb9, 0x19, 0x60, 0xe1, 0x30, 0x30, + 0x3a, 0x84, 0x29, 0x5d, 0xe9, 0x10, 0xdb, 0x54, 0x9a, 0xa4, 0xf1, 0x1c, 0x0e, 0x48, 0x5e, 0xe2, + 0xf7, 0x0d, 0x71, 0x44, 0x9c, 0x54, 0x82, 0xd6, 0xa0, 0xa8, 0x9a, 0xbc, 0x8f, 0x13, 0xbd, 0x4b, + 0xcf, 0x2a, 0xea, 0x76, 0x7d, 0x6e, 0x3e, 0x17, 0x3f, 0xb0, 0x87, 0x21, 0xff, 0x53, 0x3c, 0x1a, + 0x58, 0xfc, 0xa1, 0xfb, 0x50, 0xe2, 0x8f, 0x70, 0x9a, 0x86, 0xe6, 0xdd, 0x0c, 0xb0, 0x95, 0xdd, + 0x14, 0x63, 0xcf, 0x8e, 0x2a, 0x17, 0x53, 0x0e, 0x7d, 0x3d, 0x32, 0xf6, 0x85, 0xd1, 0x3a, 0x14, + 0xcc, 0x9f, 0xd2, 0xc1, 0xf0, 0x22, 0xc7, 0xdb, 0x16, 0x8e, 0x23, 0xff, 0x49, 0x3e, 0x66, 0x2e, + 0x2f, 0x75, 0x4f, 0x9e, 0xdb, 0xaa, 0xfb, 0x1d, 0x53, 0xe6, 0xca, 0xef, 0x40, 0x51, 0x54, 0x78, + 0x11, 0xcc, 0xef, 0x0c, 0x12, 0xcc, 0xe1, 0x2a, 0xe6, 0x7f, 0xb0, 0x78, 0x83, 0x1e, 0x30, 0xfa, + 0x04, 0x86, 0x89, 0xab, 0xc2, 0xad, 0x8d, 0xb7, 0x07, 0x51, 0x11, 0xe4, 0xd5, 0xa0, 0x51, 0x15, + 0x63, 0x02, 0x15, 0xbd, 0xcf, 0xfc, 0xc5, 0x78, 0xd9, 0x47, 0xa0, 0x5d, 0x2e, 0xf0, 0x72, 0x75, + 0xc9, 0x9d, 0xb6, 0x3f, 0xfc, 0xec, 0xa8, 0x02, 0xc1, 0x4f, 0x1c, 0x96, 0x90, 0xff, 0x5b, 0x82, + 0x29, 0xee, 0xa1, 0xa6, 0x63, 0xa9, 0xb4, 0x7b, 0x66, 0x85, 0xe9, 0x51, 0xa4, 0x30, 0xbd, 0xdd, + 0xc3, 0x2d, 0x09, 0x0b, 0x33, 0x8b, 0xd3, 0xb7, 0x12, 0xbc, 0x94, 0xe0, 0x3e, 0x83, 0xbc, 0xb8, + 0x1d, 0xcd, 0x8b, 0x6f, 0x0e, 0x3a, 0xa1, 0xac, 0xd6, 0x78, 0x3c, 0x65, 0x3a, 0x7c, 0xa7, 0xdc, + 0x04, 0x30, 0x2d, 0xf5, 0x40, 0xd5, 0x48, 0x5b, 0x5c, 0x82, 0x97, 0x42, 0x8f, 0xe0, 0x7c, 0x0a, + 0x0e, 0x71, 0x21, 0x1b, 0x66, 0x5b, 0x64, 0x57, 0x71, 0x34, 0xba, 0xd0, 0x6a, 0x2d, 0x2a, 0xa6, + 0xb2, 0xa3, 0x6a, 0x2a, 0x55, 0xc5, 0x71, 0xc1, 0x48, 0xfd, 0xae, 0x7b, 0x39, 0x9d, 0xc6, 0xf1, + 0xec, 0xa8, 0x72, 0x29, 0xed, 0x76, 0xc8, 0x63, 0xe9, 0xe2, 0x0c, 0x68, 0xd4, 0x85, 0xb2, 0x45, + 0x3e, 0x73, 0x54, 0x8b, 0xb4, 0x96, 0x2c, 0xc3, 0x8c, 0xa8, 0xcd, 0x73, 0xb5, 0xbf, 0x7d, 0x7c, + 0x54, 0x29, 0xe3, 0x0c, 0x9e, 0xde, 0x8a, 0x33, 0xe1, 0xd1, 0x13, 0x98, 0x56, 0xdc, 0xb7, 0x83, + 0x11, 0xad, 0xee, 0x2e, 0xb9, 0x73, 0x7c, 0x54, 0x99, 0x5e, 0x48, 0x92, 0x7b, 0x2b, 0x4c, 0x03, + 0x45, 0x35, 0x28, 0x1e, 0xf0, 0x97, 0x8d, 0x76, 0x79, 0x88, 0xe3, 0xb3, 0x42, 0x50, 0x74, 0x1f, + 0x3b, 0x32, 0xcc, 0xe1, 0xe5, 0x06, 0xdf, 0x7d, 0x1e, 0x17, 0xfb, 0xa0, 0x64, 0xbd, 0xa4, 0xd8, + 0xf1, 0xfc, 0xc4, 0xb8, 0x14, 0x64, 0xad, 0x07, 0x01, 0x09, 0x87, 0xf9, 0xd0, 0x63, 0x18, 0xd9, + 0x13, 0xa7, 0x12, 0x76, 0xb9, 0xd8, 0x57, 0x11, 0x8e, 0x9c, 0x62, 0xd4, 0xa7, 0x84, 0x8a, 0x11, + 0x6f, 0xd8, 0xc6, 0x01, 0x22, 0x7a, 0x1d, 0x8a, 0xfc, 0xc7, 0xca, 0x12, 0x3f, 0x8e, 0x2b, 0x05, + 0xb9, 0xed, 0x81, 0x3b, 0x8c, 0x3d, 0xba, 0xc7, 0xba, 0xb2, 0xb9, 0xc8, 0x8f, 0x85, 0x63, 0xac, + 0x2b, 0x9b, 0x8b, 0xd8, 0xa3, 0xa3, 0x4f, 0xa1, 0x68, 0x93, 0x55, 0x55, 0x77, 0x0e, 0xcb, 0xd0, + 0xd7, 0xa5, 0x72, 0xe3, 0x1e, 0xe7, 0x8e, 0x1d, 0x8c, 0x05, 0x1a, 0x04, 0x1d, 0x7b, 0xb0, 0x68, + 0x0f, 0x46, 0x2c, 0x47, 0x5f, 0xb0, 0xb7, 0x6d, 0x62, 0x95, 0x47, 0xb9, 0x8e, 0x5e, 0xe9, 0x1c, + 0x7b, 0xfc, 0x71, 0x2d, 0xbe, 0x87, 0x7c, 0x0e, 0x1c, 0x80, 0xa3, 0x3f, 0x97, 0x00, 0xd9, 0x8e, + 0x69, 0x6a, 0xa4, 0x43, 0x74, 0xaa, 0x68, 0xfc, 0x2c, 0xce, 0x2e, 0x9f, 0xe7, 0x3a, 0x3f, 0xe8, + 0x35, 0xaf, 0x84, 0x60, 0x5c, 0xb9, 0x7f, 0xe8, 0x9d, 0x64, 0xc5, 0x29, 0x7a, 0x99, 0x6b, 0x77, + 0x6d, 0xfe, 0x77, 0x79, 0xac, 0x2f, 0xd7, 0xa6, 0x9f, 0x39, 0x06, 0xae, 0x15, 0x74, 0xec, 0xc1, + 0xa2, 0x47, 0x30, 0xeb, 0x3d, 0x8c, 0xc5, 0x86, 0x41, 0x97, 0x55, 0x8d, 0xd8, 0x5d, 0x9b, 0x92, + 0x4e, 0x79, 0x9c, 0x2f, 0xbb, 0xff, 0xf6, 0x03, 0xa7, 0x72, 0xe1, 0x0c, 0x69, 0xd4, 0x81, 0x8a, + 0x97, 0x32, 0xd8, 0x7e, 0xf2, 0x73, 0xd6, 0x3d, 0xbb, 0xa9, 0x68, 0xee, 0x3d, 0xc0, 0x04, 0x57, + 0xf0, 0xda, 0xf1, 0x51, 0xa5, 0xb2, 0x74, 0x32, 0x2b, 0xee, 0x85, 0x85, 0x3e, 0x82, 0xb2, 0x92, + 0xa5, 0x67, 0x92, 0xeb, 0x79, 0x85, 0xe5, 0xa1, 0x4c, 0x05, 0x99, 0xd2, 0x88, 0xc2, 0xa4, 0x12, + 0x7d, 0xa2, 0x6c, 0x97, 0xa7, 0xfa, 0x3a, 0x88, 0x8c, 0xbd, 0x6c, 0x0e, 0x0e, 0x23, 0x62, 0x04, + 0x1b, 0x27, 0x34, 0xa0, 0x3f, 0x04, 0xa4, 0xc4, 0x5f, 0x55, 0xdb, 0x65, 0xd4, 0x57, 0xf9, 0x49, + 0x3c, 0xc7, 0x0e, 0xc2, 0x2e, 0x41, 0xb2, 0x71, 0x8a, 0x1e, 0xb4, 0x0a, 0x33, 0x62, 0x74, 0x5b, + 0xb7, 0x95, 0x5d, 0xd2, 0xe8, 0xda, 0x4d, 0xaa, 0xd9, 0xe5, 0x69, 0x9e, 0xfb, 0xf8, 0xc5, 0xd7, + 0x42, 0x0a, 0x1d, 0xa7, 0x4a, 0xa1, 0x0f, 0x60, 0x72, 0xd7, 0xb0, 0x76, 0xd4, 0x56, 0x8b, 0xe8, + 0x1e, 0xd2, 0x0c, 0x47, 0x9a, 0x61, 0xde, 0x58, 0x8e, 0xd1, 0x70, 0x82, 0x9b, 0x3f, 0x26, 0x11, + 0x57, 0x0b, 0x67, 0xf3, 0x20, 0x77, 0xb0, 0xc7, 0x24, 0x81, 0x69, 0xcf, 0xed, 0x31, 0x49, 0x08, + 0xf2, 0xe4, 0xc3, 0xcc, 0xff, 0xcf, 0xc1, 0x74, 0xc0, 0xdc, 0xf7, 0x63, 0x92, 0x14, 0x91, 0x5f, + 0x3f, 0xca, 0xed, 0xfd, 0x28, 0xf7, 0x6b, 0x09, 0xc6, 0x03, 0xd7, 0xfd, 0xf2, 0x3d, 0xf0, 0x08, + 0x6c, 0xcb, 0x68, 0x39, 0xff, 0x25, 0x17, 0x9e, 0xc0, 0xaf, 0xfc, 0x2b, 0x83, 0x9f, 0xfe, 0x92, + 0x56, 0xfe, 0x36, 0x0f, 0x93, 0xf1, 0xdd, 0x18, 0xb9, 0x8c, 0x96, 0x7a, 0x5e, 0x46, 0x6f, 0xc2, + 0xcc, 0xae, 0xa3, 0x69, 0x5d, 0xee, 0x86, 0xd0, 0x8d, 0xb4, 0x7b, 0x99, 0xf4, 0x8a, 0x90, 0x9c, + 0x59, 0x4e, 0xe1, 0xc1, 0xa9, 0x92, 0x19, 0x17, 0xeb, 0xf9, 0x53, 0x5d, 0xac, 0x27, 0xee, 0x79, + 0x0b, 0x03, 0xdc, 0xf3, 0xa6, 0x5e, 0x92, 0x0f, 0x9d, 0xe2, 0x92, 0xfc, 0x34, 0xb7, 0xda, 0x29, + 0x49, 0xac, 0xe7, 0x23, 0xcb, 0x57, 0xe0, 0x82, 0x10, 0xa3, 0xfc, 0xc2, 0x59, 0xa7, 0x96, 0xa1, + 0x69, 0xc4, 0x5a, 0x72, 0x3a, 0x9d, 0xae, 0xfc, 0x1e, 0x8c, 0x47, 0x9f, 0x52, 0xb8, 0x2b, 0xed, + 0xbe, 0xe6, 0x10, 0x57, 0x7a, 0xa1, 0x95, 0x76, 0xc7, 0xb1, 0xcf, 0x21, 0xff, 0xa9, 0x04, 0xb3, + 0xe9, 0x4f, 0x26, 0x91, 0x06, 0xe3, 0x1d, 0xe5, 0x30, 0xfc, 0x8c, 0x55, 0x3a, 0xe5, 0x61, 0x0b, + 0xbf, 0x43, 0x5f, 0x8b, 0x60, 0xe1, 0x18, 0xb6, 0xfc, 0xa3, 0x04, 0x73, 0x19, 0xb7, 0xd7, 0x67, + 0x6b, 0x09, 0xfa, 0x18, 0x4a, 0x1d, 0xe5, 0xb0, 0xe1, 0x58, 0x6d, 0x72, 0xea, 0xe3, 0x25, 0x9e, + 0x31, 0xd6, 0x04, 0x0a, 0xf6, 0xf1, 0xe4, 0x2f, 0x25, 0x28, 0x67, 0x35, 0xfa, 0xe8, 0x56, 0xe4, + 0x9e, 0xfd, 0xd5, 0xd8, 0x3d, 0xfb, 0x54, 0x42, 0xee, 0x05, 0xdd, 0xb2, 0xff, 0xb3, 0x04, 0xb3, + 0xe9, 0x1f, 0x3c, 0xe8, 0xad, 0x88, 0x85, 0x95, 0x98, 0x85, 0x13, 0x31, 0x29, 0x61, 0xdf, 0x27, + 0x30, 0x2e, 0x3e, 0x8b, 0x04, 0x8c, 0xf0, 0xaa, 0x9c, 0x96, 0x2b, 0x05, 0x84, 0xf7, 0x19, 0xc0, + 0xd7, 0x2b, 0x3a, 0x86, 0x63, 0x68, 0xf2, 0x9f, 0xe5, 0x60, 0xa8, 0xd1, 0x54, 0x34, 0x72, 0x06, + 0x6d, 0xd6, 0x87, 0x91, 0x36, 0xab, 0xd7, 0xbf, 0x9c, 0x70, 0xab, 0x32, 0x3b, 0x2c, 0x1c, 0xeb, + 0xb0, 0xde, 0xe8, 0x0b, 0xed, 0xe4, 0xe6, 0xea, 0xb7, 0x60, 0xc4, 0x57, 0x3a, 0x58, 0xce, 0x97, + 0xff, 0x21, 0x07, 0xa3, 0x21, 0x15, 0x03, 0x56, 0x8c, 0xdd, 0x48, 0xa5, 0xed, 0xe7, 0x1f, 0xfd, + 0x42, 0xba, 0xaa, 0x5e, 0x6d, 0x75, 0x9f, 0x4c, 0x06, 0x8f, 0xe4, 0x92, 0x25, 0xf7, 0x3d, 0x18, + 0xa7, 0xfc, 0x1f, 0xe1, 0xfc, 0x43, 0xd9, 0x3c, 0x8f, 0x45, 0xff, 0xa1, 0xed, 0x56, 0x84, 0x8a, + 0x63, 0xdc, 0x17, 0xee, 0xc2, 0x58, 0x44, 0xd9, 0x40, 0x2f, 0x1e, 0xff, 0x4d, 0x82, 0x57, 0x7b, + 0x7e, 0x32, 0xa3, 0x7a, 0x64, 0x93, 0x54, 0x63, 0x9b, 0x64, 0x3e, 0x1b, 0xe0, 0xc5, 0xbd, 0x9c, + 0xa9, 0x5f, 0x7f, 0xfa, 0xc3, 0xfc, 0xb9, 0xef, 0x7e, 0x98, 0x3f, 0xf7, 0xfd, 0x0f, 0xf3, 0xe7, + 0xfe, 0xf8, 0x78, 0x5e, 0x7a, 0x7a, 0x3c, 0x2f, 0x7d, 0x77, 0x3c, 0x2f, 0x7d, 0x7f, 0x3c, 0x2f, + 0xfd, 0xef, 0xf1, 0xbc, 0xf4, 0x57, 0x3f, 0xce, 0x9f, 0xfb, 0xb8, 0x28, 0xe0, 0x7e, 0x11, 0x00, + 0x00, 0xff, 0xff, 0x26, 0xef, 0x73, 0xa6, 0xe7, 0x3c, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/extensions/v1beta1/generated.proto b/vendor/k8s.io/api/extensions/v1beta1/generated.proto index 8308786d1..1e0769f58 100644 --- a/vendor/k8s.io/api/extensions/v1beta1/generated.proto +++ b/vendor/k8s.io/api/extensions/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,7 +22,6 @@ syntax = 'proto2'; package k8s.io.api.extensions.v1beta1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; @@ -33,15 +32,17 @@ import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; option go_package = "v1beta1"; // AllowedFlexVolume represents a single Flexvolume that is allowed to be used. +// Deprecated: use AllowedFlexVolume from policy API Group instead. message AllowedFlexVolume { - // Driver is the name of the Flexvolume driver. + // driver is the name of the Flexvolume driver. optional string driver = 1; } -// defines the host volume conditions that will be enabled by a policy +// AllowedHostPath defines the host volume conditions that will be enabled by a policy // for pods to use. It requires the path prefix to be defined. +// Deprecated: use AllowedHostPath from policy API Group instead. message AllowedHostPath { - // is the path prefix that the host volume must match. + // pathPrefix is the path prefix that the host volume must match. // It does not support `*`. // Trailing slashes are trimmed when validating the path prefix with a host path. // @@ -49,6 +50,10 @@ message AllowedHostPath { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` optional string pathPrefix = 1; + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + optional bool readOnly = 2; } message CustomMetricCurrentStatus { @@ -409,13 +414,14 @@ message DeploymentStrategy { } // FSGroupStrategyOptions defines the strategy type and options used to create the strategy. +// Deprecated: use FSGroupStrategyOptions from policy API Group instead. message FSGroupStrategyOptions { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. // +optional optional string rule = 1; - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. + // ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } @@ -448,8 +454,9 @@ message HTTPIngressRuleValue { repeated HTTPIngressPath paths = 1; } -// Host Port Range defines a range of host ports that will be enabled by a policy +// HostPortRange defines a range of host ports that will be enabled by a policy // for pods to use. It requires both the start and end to be defined. +// Deprecated: use HostPortRange from policy API Group instead. message HostPortRange { // min is the start of the range, inclusive. optional int32 min = 1; @@ -458,12 +465,13 @@ message HostPortRange { optional int32 max = 2; } -// ID Range provides a min/max of an allowed range of IDs. +// IDRange provides a min/max of an allowed range of IDs. +// Deprecated: use IDRange from policy API Group instead. message IDRange { - // Min is the start of the range, inclusive. + // min is the start of the range, inclusive. optional int64 min = 1; - // Max is the end of the range, inclusive. + // max is the end of the range, inclusive. optional int64 max = 2; } @@ -678,20 +686,26 @@ message NetworkPolicyList { // DEPRECATED 1.9 - This group version of NetworkPolicyPeer is deprecated by networking/v1/NetworkPolicyPeer. message NetworkPolicyPeer { - // This is a label selector which selects Pods in this namespace. - // This field follows standard label selector semantics. - // If present but empty, this selector selects all pods in this namespace. + // This is a label selector which selects Pods. This field follows standard label + // selector semantics; if present but empty, it selects all pods. + // + // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector podSelector = 1; - // Selects Namespaces using cluster scoped-labels. This - // matches all pods in all namespaces selected by this label selector. - // This field follows standard label selector semantics. - // If present but empty, this selector selects all namespaces. + // Selects Namespaces using cluster-scoped labels. This field follows standard label + // selector semantics; if present but empty, it selects all namespaces. + // + // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector namespaceSelector = 2; - // IPBlock defines policy on a particular IPBlock + // IPBlock defines policy on a particular IPBlock. If this field is set then + // neither of the other fields can be. // +optional optional IPBlock ipBlock = 3; } @@ -755,8 +769,9 @@ message NetworkPolicySpec { repeated string policyTypes = 4; } -// Pod Security Policy governs the ability to make requests that affect the Security Context +// PodSecurityPolicy governs the ability to make requests that affect the Security Context // that will be applied to a pod and container. +// Deprecated: use PodSecurityPolicy from policy API Group instead. message PodSecurityPolicy { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata @@ -768,43 +783,45 @@ message PodSecurityPolicy { optional PodSecurityPolicySpec spec = 2; } -// Pod Security Policy List is a list of PodSecurityPolicy objects. +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. +// Deprecated: use PodSecurityPolicyList from policy API Group instead. message PodSecurityPolicyList { // Standard list metadata. // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - // Items is a list of schema objects. + // items is a list of schema objects. repeated PodSecurityPolicy items = 2; } -// Pod Security Policy Spec defines the policy enforced. +// PodSecurityPolicySpec defines the policy enforced. +// Deprecated: use PodSecurityPolicySpec from policy API Group instead. message PodSecurityPolicySpec { // privileged determines if a pod can request to be run as privileged. // +optional optional bool privileged = 1; - // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // defaultAddCapabilities is the default set of capabilities that will be added to the container // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. + // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the allowedCapabilities list. // +optional repeated string defaultAddCapabilities = 2; - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // requiredDropCapabilities are the capabilities that will be dropped from the container. These // are required to be dropped and cannot be added. // +optional repeated string requiredDropCapabilities = 3; - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // allowedCapabilities is a list of capabilities that can be requested to add to the container. // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. // +optional repeated string allowedCapabilities = 4; - // volumes is a white list of allowed volume plugins. Empty indicates that all plugins - // may be used. + // volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. // +optional repeated string volumes = 5; @@ -830,13 +847,13 @@ message PodSecurityPolicySpec { // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. optional RunAsUserStrategyOptions runAsUser = 11; - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. optional SupplementalGroupsStrategyOptions supplementalGroups = 12; - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. optional FSGroupStrategyOptions fsGroup = 13; - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // readOnlyRootFilesystem when set to true will force containers to run with a read only root file // system. If the container specifically requests to run with a non-read only root file system // the PSP should deny the pod. // If set to false the container may run with a read only root file system if it wishes but it @@ -844,25 +861,47 @@ message PodSecurityPolicySpec { // +optional optional bool readOnlyRootFilesystem = 14; - // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // defaultAllowPrivilegeEscalation controls the default setting for whether a // process can gain more privileges than its parent process. // +optional optional bool defaultAllowPrivilegeEscalation = 15; - // AllowPrivilegeEscalation determines if a pod can request to allow + // allowPrivilegeEscalation determines if a pod can request to allow // privilege escalation. If unspecified, defaults to true. // +optional optional bool allowPrivilegeEscalation = 16; - // is a white list of allowed host paths. Empty indicates that all host paths may be used. + // allowedHostPaths is a white list of allowed host paths. Empty indicates + // that all host paths may be used. // +optional repeated AllowedHostPath allowedHostPaths = 17; - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. + // is allowed in the "volumes" field. // +optional repeated AllowedFlexVolume allowedFlexVolumes = 18; + + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + repeated string allowedUnsafeSysctls = 19; + + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + repeated string forbiddenSysctls = 20; } // DEPRECATED - This group version of ReplicaSet is deprecated by apps/v1beta2/ReplicaSet. See the release notes for @@ -1041,19 +1080,22 @@ message RollingUpdateDeployment { optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; } -// Run A sUser Strategy Options defines the strategy type and any options used to create the strategy. +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. +// Deprecated: use RunAsUserStrategyOptions from policy API Group instead. message RunAsUserStrategyOptions { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + // rule is the strategy that will dictate the allowable RunAsUser values that may be set. optional string rule = 1; - // Ranges are the allowed ranges of uids that may be used. + // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } -// SELinux Strategy Options defines the strategy type and any options used to create the strategy. +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. +// Deprecated: use SELinuxStrategyOptions from policy API Group instead. message SELinuxStrategyOptions { - // type is the strategy that will dictate the allowable labels that may be set. + // rule is the strategy that will dictate the allowable labels that may be set. optional string rule = 1; // seLinuxOptions required to run as; required for MustRunAs @@ -1104,13 +1146,14 @@ message ScaleStatus { } // SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. +// Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead. message SupplementalGroupsStrategyOptions { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. // +optional optional string rule = 1; - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. + // ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } diff --git a/vendor/k8s.io/api/extensions/v1beta1/types.go b/vendor/k8s.io/api/extensions/v1beta1/types.go index c3d9f72d7..3a86ef43a 100644 --- a/vendor/k8s.io/api/extensions/v1beta1/types.go +++ b/vendor/k8s.io/api/extensions/v1beta1/types.go @@ -862,8 +862,9 @@ type ReplicaSetCondition struct { // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Pod Security Policy governs the ability to make requests that affect the Security Context +// PodSecurityPolicy governs the ability to make requests that affect the Security Context // that will be applied to a pod and container. +// Deprecated: use PodSecurityPolicy from policy API Group instead. type PodSecurityPolicy struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -876,28 +877,29 @@ type PodSecurityPolicy struct { Spec PodSecurityPolicySpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` } -// Pod Security Policy Spec defines the policy enforced. +// PodSecurityPolicySpec defines the policy enforced. +// Deprecated: use PodSecurityPolicySpec from policy API Group instead. type PodSecurityPolicySpec struct { // privileged determines if a pod can request to be run as privileged. // +optional Privileged bool `json:"privileged,omitempty" protobuf:"varint,1,opt,name=privileged"` - // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // defaultAddCapabilities is the default set of capabilities that will be added to the container // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. + // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the allowedCapabilities list. // +optional DefaultAddCapabilities []v1.Capability `json:"defaultAddCapabilities,omitempty" protobuf:"bytes,2,rep,name=defaultAddCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // requiredDropCapabilities are the capabilities that will be dropped from the container. These // are required to be dropped and cannot be added. // +optional RequiredDropCapabilities []v1.Capability `json:"requiredDropCapabilities,omitempty" protobuf:"bytes,3,rep,name=requiredDropCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // allowedCapabilities is a list of capabilities that can be requested to add to the container. // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. // +optional AllowedCapabilities []v1.Capability `json:"allowedCapabilities,omitempty" protobuf:"bytes,4,rep,name=allowedCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // volumes is a white list of allowed volume plugins. Empty indicates that all plugins - // may be used. + // volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. // +optional Volumes []FSType `json:"volumes,omitempty" protobuf:"bytes,5,rep,name=volumes,casttype=FSType"` // hostNetwork determines if the policy allows the use of HostNetwork in the pod spec. @@ -916,39 +918,60 @@ type PodSecurityPolicySpec struct { SELinux SELinuxStrategyOptions `json:"seLinux" protobuf:"bytes,10,opt,name=seLinux"` // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. RunAsUser RunAsUserStrategyOptions `json:"runAsUser" protobuf:"bytes,11,opt,name=runAsUser"` - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. SupplementalGroups SupplementalGroupsStrategyOptions `json:"supplementalGroups" protobuf:"bytes,12,opt,name=supplementalGroups"` - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. FSGroup FSGroupStrategyOptions `json:"fsGroup" protobuf:"bytes,13,opt,name=fsGroup"` - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // readOnlyRootFilesystem when set to true will force containers to run with a read only root file // system. If the container specifically requests to run with a non-read only root file system // the PSP should deny the pod. // If set to false the container may run with a read only root file system if it wishes but it // will not be forced to. // +optional ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem,omitempty" protobuf:"varint,14,opt,name=readOnlyRootFilesystem"` - // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // defaultAllowPrivilegeEscalation controls the default setting for whether a // process can gain more privileges than its parent process. // +optional DefaultAllowPrivilegeEscalation *bool `json:"defaultAllowPrivilegeEscalation,omitempty" protobuf:"varint,15,opt,name=defaultAllowPrivilegeEscalation"` - // AllowPrivilegeEscalation determines if a pod can request to allow + // allowPrivilegeEscalation determines if a pod can request to allow // privilege escalation. If unspecified, defaults to true. // +optional AllowPrivilegeEscalation *bool `json:"allowPrivilegeEscalation,omitempty" protobuf:"varint,16,opt,name=allowPrivilegeEscalation"` - // is a white list of allowed host paths. Empty indicates that all host paths may be used. + // allowedHostPaths is a white list of allowed host paths. Empty indicates + // that all host paths may be used. // +optional AllowedHostPaths []AllowedHostPath `json:"allowedHostPaths,omitempty" protobuf:"bytes,17,rep,name=allowedHostPaths"` - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. + // is allowed in the "volumes" field. // +optional AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"` + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + AllowedUnsafeSysctls []string `json:"allowedUnsafeSysctls,omitempty" protobuf:"bytes,19,rep,name=allowedUnsafeSysctls"` + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + ForbiddenSysctls []string `json:"forbiddenSysctls,omitempty" protobuf:"bytes,20,rep,name=forbiddenSysctls"` } -// defines the host volume conditions that will be enabled by a policy +// AllowedHostPath defines the host volume conditions that will be enabled by a policy // for pods to use. It requires the path prefix to be defined. +// Deprecated: use AllowedHostPath from policy API Group instead. type AllowedHostPath struct { - // is the path prefix that the host volume must match. + // pathPrefix is the path prefix that the host volume must match. // It does not support `*`. // Trailing slashes are trimmed when validating the path prefix with a host path. // @@ -956,9 +979,14 @@ type AllowedHostPath struct { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` PathPrefix string `json:"pathPrefix,omitempty" protobuf:"bytes,1,rep,name=pathPrefix"` + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,2,opt,name=readOnly"` } -// FS Type gives strong typing to different file systems that are used by volumes. +// FSType gives strong typing to different file systems that are used by volumes. +// Deprecated: use FSType from policy API Group instead. type FSType string var ( @@ -987,13 +1015,15 @@ var ( ) // AllowedFlexVolume represents a single Flexvolume that is allowed to be used. +// Deprecated: use AllowedFlexVolume from policy API Group instead. type AllowedFlexVolume struct { - // Driver is the name of the Flexvolume driver. + // driver is the name of the Flexvolume driver. Driver string `json:"driver" protobuf:"bytes,1,opt,name=driver"` } -// Host Port Range defines a range of host ports that will be enabled by a policy +// HostPortRange defines a range of host ports that will be enabled by a policy // for pods to use. It requires both the start and end to be defined. +// Deprecated: use HostPortRange from policy API Group instead. type HostPortRange struct { // min is the start of the range, inclusive. Min int32 `json:"min" protobuf:"varint,1,opt,name=min"` @@ -1001,9 +1031,10 @@ type HostPortRange struct { Max int32 `json:"max" protobuf:"varint,2,opt,name=max"` } -// SELinux Strategy Options defines the strategy type and any options used to create the strategy. +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. +// Deprecated: use SELinuxStrategyOptions from policy API Group instead. type SELinuxStrategyOptions struct { - // type is the strategy that will dictate the allowable labels that may be set. + // rule is the strategy that will dictate the allowable labels that may be set. Rule SELinuxStrategy `json:"rule" protobuf:"bytes,1,opt,name=rule,casttype=SELinuxStrategy"` // seLinuxOptions required to run as; required for MustRunAs // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ @@ -1013,92 +1044,111 @@ type SELinuxStrategyOptions struct { // SELinuxStrategy denotes strategy types for generating SELinux options for a // Security Context. +// Deprecated: use SELinuxStrategy from policy API Group instead. type SELinuxStrategy string const ( - // container must have SELinux labels of X applied. + // SELinuxStrategyMustRunAs means that container must have SELinux labels of X applied. + // Deprecated: use SELinuxStrategyMustRunAs from policy API Group instead. SELinuxStrategyMustRunAs SELinuxStrategy = "MustRunAs" - // container may make requests for any SELinux context labels. + // SELinuxStrategyRunAsAny means that container may make requests for any SELinux context labels. + // Deprecated: use SELinuxStrategyRunAsAny from policy API Group instead. SELinuxStrategyRunAsAny SELinuxStrategy = "RunAsAny" ) -// Run A sUser Strategy Options defines the strategy type and any options used to create the strategy. +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. +// Deprecated: use RunAsUserStrategyOptions from policy API Group instead. type RunAsUserStrategyOptions struct { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + // rule is the strategy that will dictate the allowable RunAsUser values that may be set. Rule RunAsUserStrategy `json:"rule" protobuf:"bytes,1,opt,name=rule,casttype=RunAsUserStrategy"` - // Ranges are the allowed ranges of uids that may be used. + // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } -// ID Range provides a min/max of an allowed range of IDs. +// IDRange provides a min/max of an allowed range of IDs. +// Deprecated: use IDRange from policy API Group instead. type IDRange struct { - // Min is the start of the range, inclusive. + // min is the start of the range, inclusive. Min int64 `json:"min" protobuf:"varint,1,opt,name=min"` - // Max is the end of the range, inclusive. + // max is the end of the range, inclusive. Max int64 `json:"max" protobuf:"varint,2,opt,name=max"` } // RunAsUserStrategy denotes strategy types for generating RunAsUser values for a // Security Context. +// Deprecated: use RunAsUserStrategy from policy API Group instead. type RunAsUserStrategy string const ( - // container must run as a particular uid. + // RunAsUserStrategyMustRunAs means that container must run as a particular uid. + // Deprecated: use RunAsUserStrategyMustRunAs from policy API Group instead. RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs" - // container must run as a non-root uid + // RunAsUserStrategyMustRunAsNonRoot means that container must run as a non-root uid. + // Deprecated: use RunAsUserStrategyMustRunAsNonRoot from policy API Group instead. RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot" - // container may make requests for any uid. + // RunAsUserStrategyRunAsAny means that container may make requests for any uid. + // Deprecated: use RunAsUserStrategyRunAsAny from policy API Group instead. RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny" ) // FSGroupStrategyOptions defines the strategy type and options used to create the strategy. +// Deprecated: use FSGroupStrategyOptions from policy API Group instead. type FSGroupStrategyOptions struct { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. // +optional Rule FSGroupStrategyType `json:"rule,omitempty" protobuf:"bytes,1,opt,name=rule,casttype=FSGroupStrategyType"` - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. + // ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } // FSGroupStrategyType denotes strategy types for generating FSGroup values for a // SecurityContext +// Deprecated: use FSGroupStrategyType from policy API Group instead. type FSGroupStrategyType string const ( - // container must have FSGroup of X applied. + // FSGroupStrategyMustRunAs meant that container must have FSGroup of X applied. + // Deprecated: use FSGroupStrategyMustRunAs from policy API Group instead. FSGroupStrategyMustRunAs FSGroupStrategyType = "MustRunAs" - // container may make requests for any FSGroup labels. + // FSGroupStrategyRunAsAny means that container may make requests for any FSGroup labels. + // Deprecated: use FSGroupStrategyRunAsAny from policy API Group instead. FSGroupStrategyRunAsAny FSGroupStrategyType = "RunAsAny" ) // SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. +// Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead. type SupplementalGroupsStrategyOptions struct { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. // +optional Rule SupplementalGroupsStrategyType `json:"rule,omitempty" protobuf:"bytes,1,opt,name=rule,casttype=SupplementalGroupsStrategyType"` - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. + // ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } // SupplementalGroupsStrategyType denotes strategy types for determining valid supplemental // groups for a SecurityContext. +// Deprecated: use SupplementalGroupsStrategyType from policy API Group instead. type SupplementalGroupsStrategyType string const ( - // container must run as a particular gid. + // SupplementalGroupsStrategyMustRunAs means that container must run as a particular gid. + // Deprecated: use SupplementalGroupsStrategyMustRunAs from policy API Group instead. SupplementalGroupsStrategyMustRunAs SupplementalGroupsStrategyType = "MustRunAs" - // container may make requests for any gid. + // SupplementalGroupsStrategyRunAsAny means that container may make requests for any gid. + // Deprecated: use SupplementalGroupsStrategyRunAsAny from policy API Group instead. SupplementalGroupsStrategyRunAsAny SupplementalGroupsStrategyType = "RunAsAny" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Pod Security Policy List is a list of PodSecurityPolicy objects. +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. +// Deprecated: use PodSecurityPolicyList from policy API Group instead. type PodSecurityPolicyList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata. @@ -1106,7 +1156,7 @@ type PodSecurityPolicyList struct { // +optional metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` - // Items is a list of schema objects. + // items is a list of schema objects. Items []PodSecurityPolicy `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -1256,22 +1306,26 @@ type IPBlock struct { // DEPRECATED 1.9 - This group version of NetworkPolicyPeer is deprecated by networking/v1/NetworkPolicyPeer. type NetworkPolicyPeer struct { - // Exactly one of the following must be specified. - - // This is a label selector which selects Pods in this namespace. - // This field follows standard label selector semantics. - // If present but empty, this selector selects all pods in this namespace. + // This is a label selector which selects Pods. This field follows standard label + // selector semantics; if present but empty, it selects all pods. + // + // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. // +optional PodSelector *metav1.LabelSelector `json:"podSelector,omitempty" protobuf:"bytes,1,opt,name=podSelector"` - // Selects Namespaces using cluster scoped-labels. This - // matches all pods in all namespaces selected by this label selector. - // This field follows standard label selector semantics. - // If present but empty, this selector selects all namespaces. + // Selects Namespaces using cluster-scoped labels. This field follows standard label + // selector semantics; if present but empty, it selects all namespaces. + // + // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. // +optional NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty" protobuf:"bytes,2,opt,name=namespaceSelector"` - // IPBlock defines policy on a particular IPBlock + // IPBlock defines policy on a particular IPBlock. If this field is set then + // neither of the other fields can be. // +optional IPBlock *IPBlock `json:"ipBlock,omitempty" protobuf:"bytes,3,rep,name=ipBlock"` } diff --git a/vendor/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go index 236d934fa..d261b4247 100644 --- a/vendor/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,10 +26,10 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AllowedFlexVolume = map[string]string{ - "": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used.", - "driver": "Driver is the name of the Flexvolume driver.", + "": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used. Deprecated: use AllowedFlexVolume from policy API Group instead.", + "driver": "driver is the name of the Flexvolume driver.", } func (AllowedFlexVolume) SwaggerDoc() map[string]string { @@ -37,8 +37,9 @@ func (AllowedFlexVolume) SwaggerDoc() map[string]string { } var map_AllowedHostPath = map[string]string{ - "": "defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", - "pathPrefix": "is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined. Deprecated: use AllowedHostPath from policy API Group instead.", + "pathPrefix": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "readOnly": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", } func (AllowedHostPath) SwaggerDoc() map[string]string { @@ -229,9 +230,9 @@ func (DeploymentStrategy) SwaggerDoc() map[string]string { } var map_FSGroupStrategyOptions = map[string]string{ - "": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy.", - "rule": "Rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", - "ranges": "Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end.", + "": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use FSGroupStrategyOptions from policy API Group instead.", + "rule": "rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", + "ranges": "ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs.", } func (FSGroupStrategyOptions) SwaggerDoc() map[string]string { @@ -258,7 +259,7 @@ func (HTTPIngressRuleValue) SwaggerDoc() map[string]string { } var map_HostPortRange = map[string]string{ - "": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", + "": "HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined. Deprecated: use HostPortRange from policy API Group instead.", "min": "min is the start of the range, inclusive.", "max": "max is the end of the range, inclusive.", } @@ -268,9 +269,9 @@ func (HostPortRange) SwaggerDoc() map[string]string { } var map_IDRange = map[string]string{ - "": "ID Range provides a min/max of an allowed range of IDs.", - "min": "Min is the start of the range, inclusive.", - "max": "Max is the end of the range, inclusive.", + "": "IDRange provides a min/max of an allowed range of IDs. Deprecated: use IDRange from policy API Group instead.", + "min": "min is the start of the range, inclusive.", + "max": "max is the end of the range, inclusive.", } func (IDRange) SwaggerDoc() map[string]string { @@ -407,9 +408,9 @@ func (NetworkPolicyList) SwaggerDoc() map[string]string { var map_NetworkPolicyPeer = map[string]string{ "": "DEPRECATED 1.9 - This group version of NetworkPolicyPeer is deprecated by networking/v1/NetworkPolicyPeer.", - "podSelector": "This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace.", - "namespaceSelector": "Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces.", - "ipBlock": "IPBlock defines policy on a particular IPBlock", + "podSelector": "This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.\n\nIf NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy's own Namespace.", + "namespaceSelector": "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector.", + "ipBlock": "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.", } func (NetworkPolicyPeer) SwaggerDoc() map[string]string { @@ -439,7 +440,7 @@ func (NetworkPolicySpec) SwaggerDoc() map[string]string { } var map_PodSecurityPolicy = map[string]string{ - "": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", + "": "PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container. Deprecated: use PodSecurityPolicy from policy API Group instead.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "spec": "spec defines the policy enforced.", } @@ -449,9 +450,9 @@ func (PodSecurityPolicy) SwaggerDoc() map[string]string { } var map_PodSecurityPolicyList = map[string]string{ - "": "Pod Security Policy List is a list of PodSecurityPolicy objects.", + "": "PodSecurityPolicyList is a list of PodSecurityPolicy objects. Deprecated: use PodSecurityPolicyList from policy API Group instead.", "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "items": "Items is a list of schema objects.", + "items": "items is a list of schema objects.", } func (PodSecurityPolicyList) SwaggerDoc() map[string]string { @@ -459,25 +460,27 @@ func (PodSecurityPolicyList) SwaggerDoc() map[string]string { } var map_PodSecurityPolicySpec = map[string]string{ - "": "Pod Security Policy Spec defines the policy enforced.", + "": "PodSecurityPolicySpec defines the policy enforced. Deprecated: use PodSecurityPolicySpec from policy API Group instead.", "privileged": "privileged determines if a pod can request to be run as privileged.", - "defaultAddCapabilities": "DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list.", - "requiredDropCapabilities": "RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", - "allowedCapabilities": "AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities.", - "volumes": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.", + "defaultAddCapabilities": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.", + "requiredDropCapabilities": "requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", + "allowedCapabilities": "allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities.", + "volumes": "volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use '*'.", "hostNetwork": "hostNetwork determines if the policy allows the use of HostNetwork in the pod spec.", "hostPorts": "hostPorts determines which host port ranges are allowed to be exposed.", "hostPID": "hostPID determines if the policy allows the use of HostPID in the pod spec.", "hostIPC": "hostIPC determines if the policy allows the use of HostIPC in the pod spec.", "seLinux": "seLinux is the strategy that will dictate the allowable labels that may be set.", "runAsUser": "runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set.", - "supplementalGroups": "SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", - "fsGroup": "FSGroup is the strategy that will dictate what fs group is used by the SecurityContext.", - "readOnlyRootFilesystem": "ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", - "defaultAllowPrivilegeEscalation": "DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", - "allowPrivilegeEscalation": "AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", - "allowedHostPaths": "is a white list of allowed host paths. Empty indicates that all host paths may be used.", - "allowedFlexVolumes": "AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"Volumes\" field.", + "supplementalGroups": "supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", + "fsGroup": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.", + "readOnlyRootFilesystem": "readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", + "defaultAllowPrivilegeEscalation": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", + "allowPrivilegeEscalation": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", + "allowedHostPaths": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.", + "allowedFlexVolumes": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field.", + "allowedUnsafeSysctls": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "forbiddenSysctls": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", } func (PodSecurityPolicySpec) SwaggerDoc() map[string]string { @@ -581,9 +584,9 @@ func (RollingUpdateDeployment) SwaggerDoc() map[string]string { } var map_RunAsUserStrategyOptions = map[string]string{ - "": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.", - "rule": "Rule is the strategy that will dictate the allowable RunAsUser values that may be set.", - "ranges": "Ranges are the allowed ranges of uids that may be used.", + "": "RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use RunAsUserStrategyOptions from policy API Group instead.", + "rule": "rule is the strategy that will dictate the allowable RunAsUser values that may be set.", + "ranges": "ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs.", } func (RunAsUserStrategyOptions) SwaggerDoc() map[string]string { @@ -591,8 +594,8 @@ func (RunAsUserStrategyOptions) SwaggerDoc() map[string]string { } var map_SELinuxStrategyOptions = map[string]string{ - "": "SELinux Strategy Options defines the strategy type and any options used to create the strategy.", - "rule": "type is the strategy that will dictate the allowable labels that may be set.", + "": "SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use SELinuxStrategyOptions from policy API Group instead.", + "rule": "rule is the strategy that will dictate the allowable labels that may be set.", "seLinuxOptions": "seLinuxOptions required to run as; required for MustRunAs More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/", } @@ -632,9 +635,9 @@ func (ScaleStatus) SwaggerDoc() map[string]string { } var map_SupplementalGroupsStrategyOptions = map[string]string{ - "": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy.", - "rule": "Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", - "ranges": "Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end.", + "": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead.", + "rule": "rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", + "ranges": "ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs.", } func (SupplementalGroupsStrategyOptions) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go index de1970c8f..8ec2b1ff7 100644 --- a/vendor/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1204,6 +1204,16 @@ func (in *PodSecurityPolicySpec) DeepCopyInto(out *PodSecurityPolicySpec) { *out = make([]AllowedFlexVolume, len(*in)) copy(*out, *in) } + if in.AllowedUnsafeSysctls != nil { + in, out := &in.AllowedUnsafeSysctls, &out.AllowedUnsafeSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ForbiddenSysctls != nil { + in, out := &in.ForbiddenSysctls, &out.ForbiddenSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go b/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go index f521979b7..ef2275443 100644 --- a/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1036,41 +1036,41 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 575 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xcf, 0x6e, 0xd4, 0x30, - 0x10, 0xc6, 0x37, 0xdb, 0xbf, 0xeb, 0x05, 0xda, 0x1a, 0x0e, 0xab, 0x3d, 0xa4, 0xd5, 0x22, 0xa1, - 0x72, 0xc0, 0xa6, 0x05, 0xa1, 0xc2, 0x01, 0xd4, 0x20, 0x24, 0x38, 0x00, 0x92, 0xb9, 0xf5, 0x84, - 0x37, 0x3b, 0xcd, 0x9a, 0x4d, 0xec, 0x28, 0x76, 0x52, 0xf6, 0xc6, 0x23, 0xf0, 0x06, 0xbc, 0x4e, - 0x8f, 0x3d, 0xf6, 0x54, 0xd1, 0x70, 0xe4, 0x25, 0x50, 0x9c, 0x6c, 0x13, 0xba, 0x54, 0x68, 0x6f, - 0x9e, 0x19, 0x7f, 0xbf, 0x19, 0x7f, 0x63, 0xf4, 0x76, 0x72, 0xa0, 0x89, 0x50, 0x74, 0x92, 0x0e, - 0x21, 0x91, 0x60, 0x40, 0xd3, 0x0c, 0xe4, 0x48, 0x25, 0xb4, 0x2a, 0xf0, 0x58, 0x50, 0x11, 0xf1, - 0x00, 0x62, 0x15, 0x0a, 0x7f, 0x4a, 0xb3, 0x3d, 0x1e, 0xc6, 0x63, 0xbe, 0x47, 0x03, 0x90, 0x90, - 0x70, 0x03, 0x23, 0x12, 0x27, 0xca, 0x28, 0xbc, 0x5d, 0x0a, 0x08, 0x8f, 0x05, 0x69, 0x08, 0xc8, - 0x4c, 0xd0, 0x7f, 0x14, 0x08, 0x33, 0x4e, 0x87, 0xc4, 0x57, 0x11, 0x0d, 0x54, 0xa0, 0xa8, 0xd5, - 0x0d, 0xd3, 0x63, 0x1b, 0xd9, 0xc0, 0x9e, 0x4a, 0x5e, 0xff, 0x69, 0x3d, 0x40, 0xc4, 0xfd, 0xb1, - 0x90, 0x90, 0x4c, 0x69, 0x3c, 0x09, 0x8a, 0x84, 0xa6, 0x11, 0x18, 0x4e, 0xb3, 0xb9, 0x29, 0xfa, - 0xf4, 0x26, 0x55, 0x92, 0x4a, 0x23, 0x22, 0x98, 0x13, 0x3c, 0xfb, 0x9f, 0x40, 0xfb, 0x63, 0x88, - 0xf8, 0x9c, 0xee, 0xc9, 0x4d, 0xba, 0xd4, 0x88, 0x90, 0x0a, 0x69, 0xb4, 0x49, 0xae, 0x8b, 0x06, - 0x3f, 0xda, 0xa8, 0xfb, 0xae, 0xf0, 0x86, 0x41, 0x26, 0xe0, 0x04, 0x7f, 0x46, 0xeb, 0xc5, 0x43, - 0x46, 0xdc, 0xf0, 0x9e, 0xb3, 0xe3, 0xec, 0x76, 0xf7, 0x1f, 0x93, 0xda, 0xc6, 0x2b, 0x2e, 0x89, - 0x27, 0x41, 0x91, 0xd0, 0xa4, 0xb8, 0x4d, 0xb2, 0x3d, 0xf2, 0x71, 0xf8, 0x05, 0x7c, 0xf3, 0x1e, - 0x0c, 0xf7, 0xf0, 0xe9, 0xc5, 0x76, 0x2b, 0xbf, 0xd8, 0x46, 0x75, 0x8e, 0x5d, 0x51, 0x31, 0x43, - 0xcb, 0x3a, 0x06, 0xbf, 0xd7, 0x9e, 0xa3, 0xff, 0x73, 0x49, 0xa4, 0x31, 0xdd, 0xa7, 0x18, 0x7c, - 0xef, 0x56, 0x45, 0x5f, 0x2e, 0x22, 0x66, 0x59, 0xf8, 0x08, 0xad, 0x6a, 0xc3, 0x4d, 0xaa, 0x7b, - 0x4b, 0x96, 0xba, 0xbf, 0x10, 0xd5, 0x2a, 0xbd, 0x3b, 0x15, 0x77, 0xb5, 0x8c, 0x59, 0x45, 0x1c, - 0xbc, 0x42, 0xbd, 0xc6, 0xe5, 0xd7, 0x4a, 0x1a, 0x5e, 0x58, 0x50, 0x74, 0xc7, 0xf7, 0xd1, 0x8a, - 0xa5, 0x5b, 0xab, 0x3a, 0xde, 0xed, 0x0a, 0xb1, 0x52, 0x0a, 0xca, 0xda, 0xe0, 0x77, 0x1b, 0x6d, - 0x5c, 0x7b, 0x04, 0x8e, 0x10, 0xf2, 0x67, 0x24, 0xdd, 0x73, 0x76, 0x96, 0x76, 0xbb, 0xfb, 0xcf, - 0x17, 0x19, 0xfa, 0xaf, 0x39, 0x6a, 0xc7, 0xaf, 0xd2, 0x9a, 0x35, 0x1a, 0xe0, 0xaf, 0xa8, 0xcb, - 0xa5, 0x54, 0x86, 0x1b, 0xa1, 0xa4, 0xee, 0xb5, 0x6d, 0xbf, 0xc3, 0x45, 0xad, 0x27, 0x87, 0x35, - 0xe3, 0x8d, 0x34, 0xc9, 0xd4, 0xbb, 0x5b, 0xf5, 0xed, 0x36, 0x2a, 0xac, 0xd9, 0x0a, 0x53, 0xd4, - 0x91, 0x3c, 0x02, 0x1d, 0x73, 0x1f, 0xec, 0x72, 0x3a, 0xde, 0x56, 0x25, 0xea, 0x7c, 0x98, 0x15, - 0x58, 0x7d, 0xa7, 0xff, 0x12, 0x6d, 0x5e, 0x6f, 0x83, 0x37, 0xd1, 0xd2, 0x04, 0xa6, 0xa5, 0xc9, - 0xac, 0x38, 0xe2, 0x7b, 0x68, 0x25, 0xe3, 0x61, 0x0a, 0xf6, 0x17, 0x75, 0x58, 0x19, 0xbc, 0x68, - 0x1f, 0x38, 0x83, 0x63, 0xb4, 0x35, 0xb7, 0x5b, 0xfc, 0x10, 0xad, 0xf1, 0x30, 0x54, 0x27, 0x30, - 0xb2, 0x90, 0x75, 0x6f, 0xa3, 0x9a, 0x61, 0xed, 0xb0, 0x4c, 0xb3, 0x59, 0x1d, 0x3f, 0x40, 0xab, - 0x09, 0x70, 0xad, 0x64, 0x89, 0xae, 0xbf, 0x05, 0xb3, 0x59, 0x56, 0x55, 0x3d, 0x72, 0x7a, 0xe9, - 0xb6, 0xce, 0x2e, 0xdd, 0xd6, 0xf9, 0xa5, 0xdb, 0xfa, 0x96, 0xbb, 0xce, 0x69, 0xee, 0x3a, 0x67, - 0xb9, 0xeb, 0x9c, 0xe7, 0xae, 0xf3, 0x33, 0x77, 0x9d, 0xef, 0xbf, 0xdc, 0xd6, 0xd1, 0xfa, 0xcc, - 0xcb, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x2d, 0x62, 0x44, 0xd7, 0x04, 0x00, 0x00, + // 562 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x4f, 0x6f, 0xd3, 0x30, + 0x18, 0xc6, 0x9b, 0xee, 0x6f, 0x5d, 0x60, 0x9b, 0xe1, 0x10, 0xf5, 0x90, 0x4d, 0x45, 0x42, 0xe3, + 0x80, 0xcd, 0x26, 0x84, 0x06, 0x07, 0x50, 0x83, 0x90, 0xe0, 0x00, 0x48, 0xe6, 0xb6, 0x13, 0x6e, + 0xfa, 0x2e, 0x0d, 0x6d, 0xec, 0x28, 0x76, 0x32, 0x7a, 0xe3, 0x23, 0xf0, 0x0d, 0xf8, 0x3a, 0x3d, + 0xee, 0xb8, 0xd3, 0x44, 0xc3, 0x91, 0x2f, 0x81, 0xe2, 0xa4, 0x4d, 0x68, 0x41, 0xa8, 0xb7, 0xbc, + 0xef, 0xeb, 0xe7, 0xf7, 0x3e, 0x79, 0x6c, 0xf4, 0x66, 0x74, 0xa6, 0x48, 0x20, 0xe9, 0x28, 0xe9, + 0x43, 0x2c, 0x40, 0x83, 0xa2, 0x29, 0x88, 0x81, 0x8c, 0x69, 0x39, 0xe0, 0x51, 0x40, 0x83, 0x90, + 0xfb, 0x10, 0xc9, 0x71, 0xe0, 0x4d, 0x68, 0x7a, 0xc2, 0xc7, 0xd1, 0x90, 0x9f, 0x50, 0x1f, 0x04, + 0xc4, 0x5c, 0xc3, 0x80, 0x44, 0xb1, 0xd4, 0x12, 0x1f, 0x16, 0x02, 0xc2, 0xa3, 0x80, 0xd4, 0x04, + 0x64, 0x2e, 0xe8, 0x3c, 0xf2, 0x03, 0x3d, 0x4c, 0xfa, 0xc4, 0x93, 0x21, 0xf5, 0xa5, 0x2f, 0xa9, + 0xd1, 0xf5, 0x93, 0x0b, 0x53, 0x99, 0xc2, 0x7c, 0x15, 0xbc, 0xce, 0x93, 0xca, 0x40, 0xc8, 0xbd, + 0x61, 0x20, 0x20, 0x9e, 0xd0, 0x68, 0xe4, 0xe7, 0x0d, 0x45, 0x43, 0xd0, 0x9c, 0xa6, 0x2b, 0x2e, + 0x3a, 0xf4, 0x5f, 0xaa, 0x38, 0x11, 0x3a, 0x08, 0x61, 0x45, 0xf0, 0xf4, 0x7f, 0x02, 0xe5, 0x0d, + 0x21, 0xe4, 0xcb, 0xba, 0xee, 0xf7, 0x26, 0x6a, 0xbf, 0xcd, 0x7f, 0x93, 0x41, 0x1a, 0xc0, 0x25, + 0xfe, 0x84, 0x76, 0x73, 0x4f, 0x03, 0xae, 0xb9, 0x6d, 0x1d, 0x59, 0xc7, 0xed, 0xd3, 0xc7, 0xa4, + 0x4a, 0x64, 0x81, 0x26, 0xd1, 0xc8, 0xcf, 0x1b, 0x8a, 0xe4, 0xa7, 0x49, 0x7a, 0x42, 0x3e, 0xf4, + 0x3f, 0x83, 0xa7, 0xdf, 0x81, 0xe6, 0x2e, 0x9e, 0xde, 0x1c, 0x36, 0xb2, 0x9b, 0x43, 0x54, 0xf5, + 0xd8, 0x82, 0x8a, 0x19, 0xda, 0x54, 0x11, 0x78, 0x76, 0x73, 0x85, 0xfe, 0xd7, 0xbc, 0x49, 0xcd, + 0xdd, 0xc7, 0x08, 0x3c, 0xf7, 0x56, 0x49, 0xdf, 0xcc, 0x2b, 0x66, 0x58, 0xf8, 0x1c, 0x6d, 0x2b, + 0xcd, 0x75, 0xa2, 0xec, 0x0d, 0x43, 0x3d, 0x5d, 0x8b, 0x6a, 0x94, 0xee, 0x9d, 0x92, 0xbb, 0x5d, + 0xd4, 0xac, 0x24, 0x76, 0x5f, 0x22, 0xbb, 0x76, 0xf8, 0x95, 0x14, 0x9a, 0xe7, 0x11, 0xe4, 0xdb, + 0xf1, 0x7d, 0xb4, 0x65, 0xe8, 0x26, 0xaa, 0x96, 0x7b, 0xbb, 0x44, 0x6c, 0x15, 0x82, 0x62, 0xd6, + 0xfd, 0xd5, 0x44, 0x7b, 0x4b, 0x3f, 0x81, 0x43, 0x84, 0xbc, 0x39, 0x49, 0xd9, 0xd6, 0xd1, 0xc6, + 0x71, 0xfb, 0xf4, 0xd9, 0x3a, 0xa6, 0xff, 0xf0, 0x51, 0x25, 0xbe, 0x68, 0x2b, 0x56, 0x5b, 0x80, + 0xbf, 0xa0, 0x36, 0x17, 0x42, 0x6a, 0xae, 0x03, 0x29, 0x94, 0xdd, 0x34, 0xfb, 0x7a, 0xeb, 0x46, + 0x4f, 0x7a, 0x15, 0xe3, 0xb5, 0xd0, 0xf1, 0xc4, 0xbd, 0x5b, 0xee, 0x6d, 0xd7, 0x26, 0xac, 0xbe, + 0x0a, 0x53, 0xd4, 0x12, 0x3c, 0x04, 0x15, 0x71, 0x0f, 0xcc, 0xe5, 0xb4, 0xdc, 0x83, 0x52, 0xd4, + 0x7a, 0x3f, 0x1f, 0xb0, 0xea, 0x4c, 0xe7, 0x05, 0xda, 0x5f, 0x5e, 0x83, 0xf7, 0xd1, 0xc6, 0x08, + 0x26, 0x45, 0xc8, 0x2c, 0xff, 0xc4, 0xf7, 0xd0, 0x56, 0xca, 0xc7, 0x09, 0x98, 0x57, 0xd4, 0x62, + 0x45, 0xf1, 0xbc, 0x79, 0x66, 0x75, 0x2f, 0xd0, 0xc1, 0xca, 0xdd, 0xe2, 0x87, 0x68, 0x87, 0x8f, + 0xc7, 0xf2, 0x12, 0x06, 0x06, 0xb2, 0xeb, 0xee, 0x95, 0x1e, 0x76, 0x7a, 0x45, 0x9b, 0xcd, 0xe7, + 0xf8, 0x01, 0xda, 0x8e, 0x81, 0x2b, 0x29, 0x0a, 0x74, 0xf5, 0x2c, 0x98, 0xe9, 0xb2, 0x72, 0xea, + 0x92, 0xe9, 0xcc, 0x69, 0x5c, 0xcd, 0x9c, 0xc6, 0xf5, 0xcc, 0x69, 0x7c, 0xcd, 0x1c, 0x6b, 0x9a, + 0x39, 0xd6, 0x55, 0xe6, 0x58, 0xd7, 0x99, 0x63, 0xfd, 0xc8, 0x1c, 0xeb, 0xdb, 0x4f, 0xa7, 0x71, + 0xbe, 0x3b, 0xcf, 0xf2, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdb, 0xb6, 0xff, 0xb4, 0xa2, 0x04, + 0x00, 0x00, } diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto b/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto index a19967cbe..ffd9512a9 100644 --- a/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.imagepolicy.v1alpha1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go index f4b26f5e8..129d63d08 100644 --- a/vendor/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_ImageReview = map[string]string{ "": "ImageReview checks if the set of images in a pod are allowed.", "spec": "Spec holds information about the pod being evaluated", diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go index 50f314886..a41d89700 100644 --- a/vendor/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/networking/v1/generated.pb.go b/vendor/k8s.io/api/networking/v1/generated.pb.go index 05aaf1d9a..7b1c04b29 100644 --- a/vendor/k8s.io/api/networking/v1/generated.pb.go +++ b/vendor/k8s.io/api/networking/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1813,57 +1813,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 829 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x4d, 0x6f, 0x1b, 0x45, - 0x18, 0xf6, 0x3a, 0xce, 0x47, 0x27, 0x94, 0x92, 0x41, 0x08, 0x2b, 0x88, 0x75, 0xd8, 0x0b, 0x41, - 0x55, 0x67, 0x71, 0x8b, 0x10, 0x37, 0xc4, 0x42, 0x29, 0x96, 0x9a, 0xc4, 0x9a, 0xf4, 0x02, 0x02, - 0x89, 0xf5, 0xfa, 0xcd, 0x66, 0x6a, 0xef, 0xce, 0x6a, 0x66, 0x6c, 0x92, 0x1b, 0x3f, 0x81, 0x1f, - 0xc2, 0x91, 0x1b, 0x87, 0x72, 0xcc, 0xb1, 0xc7, 0x9e, 0x56, 0x64, 0xf9, 0x17, 0x39, 0xa1, 0x99, - 0x1d, 0x7b, 0xfd, 0x51, 0x0b, 0xb7, 0xa2, 0x37, 0xcf, 0x3b, 0xcf, 0xf3, 0xbc, 0x1f, 0xf3, 0xf8, - 0x5d, 0xf4, 0xd5, 0xe0, 0x0b, 0x49, 0x18, 0xf7, 0x07, 0xa3, 0x1e, 0x88, 0x14, 0x14, 0x48, 0x7f, - 0x0c, 0x69, 0x9f, 0x0b, 0xdf, 0x5e, 0x84, 0x19, 0xf3, 0x53, 0x50, 0xbf, 0x70, 0x31, 0x60, 0x69, - 0xec, 0x8f, 0xdb, 0x7e, 0x0c, 0x29, 0x88, 0x50, 0x41, 0x9f, 0x64, 0x82, 0x2b, 0x8e, 0x9b, 0x25, - 0x92, 0x84, 0x19, 0x23, 0x15, 0x92, 0x8c, 0xdb, 0xfb, 0xf7, 0x62, 0xa6, 0xce, 0x47, 0x3d, 0x12, - 0xf1, 0xc4, 0x8f, 0x79, 0xcc, 0x7d, 0x43, 0xe8, 0x8d, 0xce, 0xcc, 0xc9, 0x1c, 0xcc, 0xaf, 0x52, - 0x68, 0xdf, 0x9b, 0x49, 0x19, 0x71, 0x01, 0x2f, 0x49, 0xb6, 0x7f, 0x6f, 0x06, 0x03, 0x17, 0x0a, - 0x52, 0xc9, 0x78, 0x2a, 0xfd, 0x71, 0xbb, 0x07, 0x2a, 0x5c, 0x86, 0x7f, 0x32, 0x03, 0xcf, 0xf8, - 0x90, 0x45, 0x97, 0x2b, 0xa1, 0x9f, 0x55, 0xd0, 0x24, 0x8c, 0xce, 0x59, 0x0a, 0xe2, 0xd2, 0xcf, - 0x06, 0xb1, 0x0e, 0x48, 0x3f, 0x01, 0x15, 0xbe, 0xac, 0x1e, 0x7f, 0x15, 0x4b, 0x8c, 0x52, 0xc5, - 0x12, 0x58, 0x22, 0x7c, 0xfe, 0x5f, 0x04, 0x19, 0x9d, 0x43, 0x12, 0x2e, 0xf1, 0x1e, 0xac, 0xe2, - 0x8d, 0x14, 0x1b, 0xfa, 0x2c, 0x55, 0x52, 0x89, 0x45, 0x92, 0x77, 0x82, 0xb6, 0x3b, 0xdd, 0x60, - 0xc8, 0xa3, 0x01, 0x3e, 0x40, 0x8d, 0x88, 0xf5, 0x45, 0xd3, 0x39, 0x70, 0x0e, 0x6f, 0x05, 0x6f, - 0x5d, 0xe5, 0xad, 0x5a, 0x91, 0xb7, 0x1a, 0x5f, 0x77, 0xbe, 0xa1, 0xd4, 0xdc, 0x60, 0x0f, 0x6d, - 0xc1, 0x45, 0x04, 0x99, 0x6a, 0xd6, 0x0f, 0x36, 0x0e, 0x6f, 0x05, 0xa8, 0xc8, 0x5b, 0x5b, 0x0f, - 0x4d, 0x84, 0xda, 0x1b, 0xef, 0x2f, 0x07, 0xdd, 0x3e, 0x2e, 0xdf, 0xb8, 0x6b, 0xc6, 0x89, 0x7f, - 0x46, 0x3b, 0x7a, 0x36, 0xfd, 0x50, 0x85, 0x46, 0x7b, 0xf7, 0xfe, 0xa7, 0xa4, 0x32, 0xc4, 0xb4, - 0x54, 0x92, 0x0d, 0x62, 0x1d, 0x90, 0x44, 0xa3, 0xc9, 0xb8, 0x4d, 0x4e, 0x7a, 0x4f, 0x21, 0x52, - 0x47, 0xa0, 0xc2, 0x00, 0xdb, 0x6a, 0x50, 0x15, 0xa3, 0x53, 0x55, 0x7c, 0x84, 0x1a, 0x32, 0x83, - 0xa8, 0x59, 0x37, 0xea, 0x77, 0xc9, 0x2a, 0xbb, 0x91, 0xb9, 0xc2, 0x4e, 0x33, 0x88, 0xaa, 0x36, - 0xf5, 0x89, 0x1a, 0x19, 0xef, 0x0f, 0x07, 0xbd, 0x3f, 0x87, 0x7c, 0x18, 0x0b, 0x90, 0x92, 0x8e, - 0x86, 0x80, 0xbb, 0x68, 0x33, 0xe3, 0x42, 0xc9, 0xa6, 0x73, 0xb0, 0xf1, 0x0a, 0xb9, 0xba, 0x5c, - 0xa8, 0xe0, 0xb6, 0xcd, 0xb5, 0xa9, 0x4f, 0x92, 0x96, 0x42, 0xf8, 0x11, 0xaa, 0x2b, 0x6e, 0x06, - 0xfa, 0x0a, 0x72, 0x00, 0x22, 0x40, 0x56, 0xae, 0xfe, 0x84, 0xd3, 0xba, 0xe2, 0xde, 0x9f, 0x0e, - 0x6a, 0xce, 0xa1, 0x3a, 0xe9, 0x9b, 0xac, 0xfb, 0x08, 0x35, 0xce, 0x04, 0x4f, 0x5e, 0xa7, 0xf2, - 0xe9, 0xd0, 0xbf, 0x15, 0x3c, 0xa1, 0x46, 0xc6, 0x7b, 0xe6, 0xa0, 0xbd, 0x39, 0xe4, 0x63, 0x26, - 0x15, 0xfe, 0x71, 0xc9, 0x3b, 0x64, 0x3d, 0xef, 0x68, 0xb6, 0x71, 0xce, 0x3b, 0x36, 0xd7, 0xce, - 0x24, 0x32, 0xe3, 0x9b, 0xc7, 0x68, 0x93, 0x29, 0x48, 0xa4, 0xed, 0xe1, 0xe3, 0x35, 0x7b, 0xa8, - 0x06, 0xd2, 0xd1, 0x6c, 0x5a, 0x8a, 0x78, 0xcf, 0xea, 0x0b, 0x1d, 0xe8, 0x5e, 0xf1, 0x19, 0xda, - 0xcd, 0x78, 0xff, 0x14, 0x86, 0x10, 0x29, 0x2e, 0x6c, 0x13, 0x0f, 0xd6, 0x6c, 0x22, 0xec, 0xc1, - 0x70, 0x42, 0x0d, 0xee, 0x14, 0x79, 0x6b, 0xb7, 0x5b, 0x69, 0xd1, 0x59, 0x61, 0x7c, 0x81, 0xf6, - 0xd2, 0x30, 0x01, 0x99, 0x85, 0x11, 0x4c, 0xb3, 0xd5, 0x5f, 0x3f, 0xdb, 0x7b, 0x45, 0xde, 0xda, - 0x3b, 0x5e, 0x54, 0xa4, 0xcb, 0x49, 0xf0, 0x77, 0x68, 0x9b, 0x65, 0x66, 0x85, 0x34, 0x37, 0x4c, - 0xbe, 0x8f, 0x56, 0xcf, 0xd1, 0xee, 0x9a, 0x60, 0xb7, 0xc8, 0x5b, 0x93, 0xc5, 0x43, 0x27, 0x74, - 0xef, 0xf7, 0x45, 0x0f, 0x68, 0xc3, 0xe1, 0x47, 0x68, 0xc7, 0xec, 0xaa, 0x88, 0x0f, 0xed, 0x6e, - 0xba, 0xab, 0xdf, 0xb3, 0x6b, 0x63, 0x37, 0x79, 0xeb, 0x83, 0xe5, 0xcf, 0x02, 0x99, 0x5c, 0xd3, - 0x29, 0x19, 0x1f, 0xa3, 0x86, 0xb6, 0xae, 0x9d, 0xca, 0xea, 0x25, 0xa4, 0xf7, 0x25, 0x29, 0xf7, - 0x25, 0xe9, 0xa4, 0xea, 0x44, 0x9c, 0x2a, 0xc1, 0xd2, 0x38, 0xd8, 0xd1, 0x96, 0xd5, 0x25, 0x51, - 0xa3, 0xe3, 0xdd, 0x2c, 0x3e, 0xb8, 0xde, 0x21, 0xf8, 0xe9, 0xff, 0xf6, 0xe0, 0xef, 0x5a, 0x9b, - 0xad, 0x7e, 0xf4, 0x9f, 0xd0, 0x36, 0x2b, 0xff, 0xe4, 0xd6, 0xc2, 0xf7, 0xd7, 0xb4, 0xf0, 0xcc, - 0x6a, 0x08, 0xee, 0xd8, 0x34, 0xdb, 0x93, 0xe0, 0x44, 0x13, 0x7f, 0x8f, 0xb6, 0xa0, 0x54, 0xdf, - 0x30, 0xea, 0xed, 0x35, 0xd5, 0xab, 0x7d, 0x19, 0xbc, 0x6d, 0xc5, 0xb7, 0x6c, 0xcc, 0x0a, 0xe2, - 0x2f, 0xf5, 0x94, 0x34, 0xf6, 0xc9, 0x65, 0x06, 0xb2, 0xd9, 0x30, 0xdf, 0x93, 0x0f, 0xcb, 0x66, - 0xa7, 0xe1, 0x9b, 0xbc, 0x85, 0xaa, 0x23, 0x9d, 0x65, 0x04, 0x87, 0x57, 0xd7, 0x6e, 0xed, 0xf9, - 0xb5, 0x5b, 0x7b, 0x71, 0xed, 0xd6, 0x7e, 0x2d, 0x5c, 0xe7, 0xaa, 0x70, 0x9d, 0xe7, 0x85, 0xeb, - 0xbc, 0x28, 0x5c, 0xe7, 0xef, 0xc2, 0x75, 0x7e, 0xfb, 0xc7, 0xad, 0xfd, 0x50, 0x1f, 0xb7, 0xff, - 0x0d, 0x00, 0x00, 0xff, 0xff, 0x48, 0x47, 0x24, 0xc9, 0xc1, 0x08, 0x00, 0x00, + // 804 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xcf, 0x8f, 0xdb, 0x44, + 0x14, 0x8e, 0x9d, 0x6c, 0x92, 0x4e, 0x28, 0x65, 0x07, 0x21, 0xac, 0x45, 0xd8, 0xc1, 0x17, 0x56, + 0xaa, 0x18, 0x93, 0x16, 0x21, 0x6e, 0x08, 0x43, 0x29, 0x91, 0xba, 0xbb, 0xd1, 0x6c, 0x2f, 0x20, + 0x90, 0x70, 0x9c, 0x59, 0xef, 0x34, 0xb1, 0xc7, 0x1a, 0x4f, 0x42, 0xf7, 0xc6, 0x9f, 0xc0, 0x1f, + 0xc2, 0x91, 0x1b, 0x87, 0x72, 0xdc, 0x63, 0x8f, 0x3d, 0x59, 0xac, 0xf9, 0x2f, 0xf6, 0x84, 0x66, + 0x3c, 0x89, 0xf3, 0xa3, 0x11, 0xd9, 0x15, 0xbd, 0x65, 0xde, 0xbc, 0xef, 0x7b, 0xf3, 0xde, 0xfb, + 0xf2, 0x19, 0x7c, 0x35, 0xfe, 0x22, 0x43, 0x94, 0x79, 0xe3, 0xe9, 0x90, 0xf0, 0x84, 0x08, 0x92, + 0x79, 0x33, 0x92, 0x8c, 0x18, 0xf7, 0xf4, 0x45, 0x90, 0x52, 0x2f, 0x21, 0xe2, 0x17, 0xc6, 0xc7, + 0x34, 0x89, 0xbc, 0x59, 0xcf, 0x8b, 0x48, 0x42, 0x78, 0x20, 0xc8, 0x08, 0xa5, 0x9c, 0x09, 0x06, + 0xad, 0x32, 0x13, 0x05, 0x29, 0x45, 0x55, 0x26, 0x9a, 0xf5, 0x0e, 0x3e, 0x89, 0xa8, 0x38, 0x9f, + 0x0e, 0x51, 0xc8, 0x62, 0x2f, 0x62, 0x11, 0xf3, 0x14, 0x60, 0x38, 0x3d, 0x53, 0x27, 0x75, 0x50, + 0xbf, 0x4a, 0xa2, 0x03, 0x77, 0xa9, 0x64, 0xc8, 0x38, 0x79, 0x4d, 0xb1, 0x83, 0xcf, 0xaa, 0x9c, + 0x38, 0x08, 0xcf, 0x69, 0x42, 0xf8, 0x85, 0x97, 0x8e, 0x23, 0x19, 0xc8, 0xbc, 0x98, 0x88, 0xe0, + 0x75, 0x28, 0x6f, 0x1b, 0x8a, 0x4f, 0x13, 0x41, 0x63, 0xb2, 0x01, 0xf8, 0xfc, 0xbf, 0x00, 0x59, + 0x78, 0x4e, 0xe2, 0x60, 0x03, 0xf7, 0x70, 0x1b, 0x6e, 0x2a, 0xe8, 0xc4, 0xa3, 0x89, 0xc8, 0x04, + 0x5f, 0x07, 0xb9, 0x27, 0xa0, 0xd5, 0x1f, 0xf8, 0x13, 0x16, 0x8e, 0x61, 0x17, 0x34, 0x42, 0x3a, + 0xe2, 0x96, 0xd1, 0x35, 0x0e, 0xef, 0xf8, 0x6f, 0x5d, 0xe6, 0x4e, 0xad, 0xc8, 0x9d, 0xc6, 0xd7, + 0xfd, 0x6f, 0x30, 0x56, 0x37, 0xd0, 0x05, 0x4d, 0xf2, 0x3c, 0x24, 0xa9, 0xb0, 0xcc, 0x6e, 0xfd, + 0xf0, 0x8e, 0x0f, 0x8a, 0xdc, 0x69, 0x3e, 0x52, 0x11, 0xac, 0x6f, 0xdc, 0xbf, 0x0c, 0x70, 0xf7, + 0xb8, 0xdc, 0xc4, 0x80, 0x4d, 0x68, 0x78, 0x01, 0x7f, 0x06, 0x6d, 0x39, 0x9b, 0x51, 0x20, 0x02, + 0xc5, 0xdd, 0x79, 0xf0, 0x29, 0xaa, 0xd6, 0xb6, 0x78, 0x2a, 0x4a, 0xc7, 0x91, 0x0c, 0x64, 0x48, + 0x66, 0xa3, 0x59, 0x0f, 0x9d, 0x0c, 0x9f, 0x91, 0x50, 0x1c, 0x11, 0x11, 0xf8, 0x50, 0xbf, 0x06, + 0x54, 0x31, 0xbc, 0x60, 0x85, 0x47, 0xa0, 0x91, 0xa5, 0x24, 0xb4, 0x4c, 0xc5, 0x7e, 0x1f, 0x6d, + 0x13, 0x05, 0x5a, 0x79, 0xd8, 0x69, 0x4a, 0xc2, 0xaa, 0x4d, 0x79, 0xc2, 0x8a, 0xc6, 0xfd, 0xc3, + 0x00, 0xef, 0xaf, 0x64, 0x3e, 0x8a, 0x38, 0xc9, 0x32, 0x3c, 0x9d, 0x10, 0x38, 0x00, 0x7b, 0x29, + 0xe3, 0x22, 0xb3, 0x8c, 0x6e, 0xfd, 0x06, 0xb5, 0x06, 0x8c, 0x0b, 0xff, 0xae, 0xae, 0xb5, 0x27, + 0x4f, 0x19, 0x2e, 0x89, 0xe0, 0x63, 0x60, 0x0a, 0xa6, 0x06, 0x7a, 0x03, 0x3a, 0x42, 0xb8, 0x0f, + 0x34, 0x9d, 0xf9, 0x94, 0x61, 0x53, 0x30, 0xf7, 0x4f, 0x03, 0x58, 0x2b, 0x59, 0xfd, 0xe4, 0x4d, + 0xbe, 0xfb, 0x08, 0x34, 0xce, 0x38, 0x8b, 0x6f, 0xf3, 0xf2, 0xc5, 0xd0, 0xbf, 0xe5, 0x2c, 0xc6, + 0x8a, 0xc6, 0x7d, 0x61, 0x80, 0xfd, 0x95, 0xcc, 0x27, 0x34, 0x13, 0xf0, 0xc7, 0x0d, 0xed, 0xa0, + 0xdd, 0xb4, 0x23, 0xd1, 0x4a, 0x39, 0xef, 0xe8, 0x5a, 0xed, 0x79, 0x64, 0x49, 0x37, 0x4f, 0xc0, + 0x1e, 0x15, 0x24, 0xce, 0x74, 0x0f, 0x1f, 0xef, 0xd8, 0x43, 0x35, 0x90, 0xbe, 0x44, 0xe3, 0x92, + 0xc4, 0x7d, 0x61, 0xae, 0x75, 0x20, 0x7b, 0x85, 0x67, 0xa0, 0x93, 0xb2, 0xd1, 0x29, 0x99, 0x90, + 0x50, 0x30, 0xae, 0x9b, 0x78, 0xb8, 0x63, 0x13, 0xc1, 0x90, 0x4c, 0xe6, 0x50, 0xff, 0x5e, 0x91, + 0x3b, 0x9d, 0x41, 0xc5, 0x85, 0x97, 0x89, 0xe1, 0x73, 0xb0, 0x9f, 0x04, 0x31, 0xc9, 0xd2, 0x20, + 0x24, 0x8b, 0x6a, 0xe6, 0xed, 0xab, 0xbd, 0x57, 0xe4, 0xce, 0xfe, 0xf1, 0x3a, 0x23, 0xde, 0x2c, + 0x02, 0xbf, 0x03, 0x2d, 0x9a, 0x2a, 0x0b, 0xb1, 0xea, 0xaa, 0xde, 0x47, 0xdb, 0xe7, 0xa8, 0xbd, + 0xc6, 0xef, 0x14, 0xb9, 0x33, 0x37, 0x1e, 0x3c, 0x87, 0xbb, 0xbf, 0xaf, 0x6b, 0x40, 0x0a, 0x0e, + 0x3e, 0x06, 0x6d, 0xe5, 0x55, 0x21, 0x9b, 0x68, 0x6f, 0xba, 0x2f, 0xf7, 0x39, 0xd0, 0xb1, 0xeb, + 0xdc, 0xf9, 0x60, 0xd3, 0xbc, 0xd1, 0xfc, 0x1a, 0x2f, 0xc0, 0xf0, 0x18, 0x34, 0xa4, 0x74, 0xf5, + 0x54, 0xb6, 0x9b, 0x90, 0xf4, 0x4b, 0x54, 0xfa, 0x25, 0xea, 0x27, 0xe2, 0x84, 0x9f, 0x0a, 0x4e, + 0x93, 0xc8, 0x6f, 0x4b, 0xc9, 0xca, 0x27, 0x61, 0xc5, 0xe3, 0x5e, 0xaf, 0x2f, 0x5c, 0x7a, 0x08, + 0x7c, 0xf6, 0xbf, 0x2d, 0xfc, 0x5d, 0x2d, 0xb3, 0xed, 0x4b, 0xff, 0x09, 0xb4, 0x68, 0xf9, 0x27, + 0xd7, 0x12, 0x7e, 0xb0, 0xa3, 0x84, 0x97, 0xac, 0xc1, 0xbf, 0xa7, 0xcb, 0xb4, 0xe6, 0xc1, 0x39, + 0x27, 0xfc, 0x1e, 0x34, 0x49, 0xc9, 0x5e, 0x57, 0xec, 0xbd, 0x1d, 0xd9, 0x2b, 0xbf, 0xf4, 0xdf, + 0xd6, 0xe4, 0x4d, 0x1d, 0xd3, 0x84, 0xf0, 0x4b, 0x39, 0x25, 0x99, 0xfb, 0xf4, 0x22, 0x25, 0x99, + 0xd5, 0x50, 0xdf, 0x93, 0x0f, 0xcb, 0x66, 0x17, 0xe1, 0xeb, 0xdc, 0x01, 0xd5, 0x11, 0x2f, 0x23, + 0xfc, 0xc3, 0xcb, 0x2b, 0xbb, 0xf6, 0xf2, 0xca, 0xae, 0xbd, 0xba, 0xb2, 0x6b, 0xbf, 0x16, 0xb6, + 0x71, 0x59, 0xd8, 0xc6, 0xcb, 0xc2, 0x36, 0x5e, 0x15, 0xb6, 0xf1, 0x77, 0x61, 0x1b, 0xbf, 0xfd, + 0x63, 0xd7, 0x7e, 0x30, 0x67, 0xbd, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x7b, 0xc9, 0x59, + 0x67, 0x08, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/networking/v1/generated.proto b/vendor/k8s.io/api/networking/v1/generated.proto index 06365ebe3..eacf0ed90 100644 --- a/vendor/k8s.io/api/networking/v1/generated.proto +++ b/vendor/k8s.io/api/networking/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,8 +22,6 @@ syntax = 'proto2'; package k8s.io.api.networking.v1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/extensions/v1beta1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; @@ -111,22 +109,29 @@ message NetworkPolicyList { repeated NetworkPolicy items = 2; } -// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields -// must be specified. +// NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of +// fields are allowed message NetworkPolicyPeer { - // This is a label selector which selects Pods in this namespace. This field - // follows standard label selector semantics. If present but empty, this selector - // selects all pods in this namespace. + // This is a label selector which selects Pods. This field follows standard label + // selector semantics; if present but empty, it selects all pods. + // + // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector podSelector = 1; - // Selects Namespaces using cluster scoped-labels. This matches all pods in all - // namespaces selected by this label selector. This field follows standard label - // selector semantics. If present but empty, this selector selects all namespaces. + // Selects Namespaces using cluster-scoped labels. This field follows standard label + // selector semantics; if present but empty, it selects all namespaces. + // + // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector namespaceSelector = 2; - // IPBlock defines policy on a particular IPBlock + // IPBlock defines policy on a particular IPBlock. If this field is set then + // neither of the other fields can be. // +optional optional IPBlock ipBlock = 3; } diff --git a/vendor/k8s.io/api/networking/v1/types.go b/vendor/k8s.io/api/networking/v1/types.go index 57bc8005e..e1b81fdc7 100644 --- a/vendor/k8s.io/api/networking/v1/types.go +++ b/vendor/k8s.io/api/networking/v1/types.go @@ -161,22 +161,29 @@ type IPBlock struct { Except []string `json:"except,omitempty" protobuf:"bytes,2,rep,name=except"` } -// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields -// must be specified. +// NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of +// fields are allowed type NetworkPolicyPeer struct { - // This is a label selector which selects Pods in this namespace. This field - // follows standard label selector semantics. If present but empty, this selector - // selects all pods in this namespace. + // This is a label selector which selects Pods. This field follows standard label + // selector semantics; if present but empty, it selects all pods. + // + // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. // +optional PodSelector *metav1.LabelSelector `json:"podSelector,omitempty" protobuf:"bytes,1,opt,name=podSelector"` - // Selects Namespaces using cluster scoped-labels. This matches all pods in all - // namespaces selected by this label selector. This field follows standard label - // selector semantics. If present but empty, this selector selects all namespaces. + // Selects Namespaces using cluster-scoped labels. This field follows standard label + // selector semantics; if present but empty, it selects all namespaces. + // + // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. // +optional NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty" protobuf:"bytes,2,opt,name=namespaceSelector"` - // IPBlock defines policy on a particular IPBlock + // IPBlock defines policy on a particular IPBlock. If this field is set then + // neither of the other fields can be. // +optional IPBlock *IPBlock `json:"ipBlock,omitempty" protobuf:"bytes,3,rep,name=ipBlock"` } diff --git a/vendor/k8s.io/api/networking/v1/types_swagger_doc_generated.go b/vendor/k8s.io/api/networking/v1/types_swagger_doc_generated.go index ad0bafeac..af2553a9d 100644 --- a/vendor/k8s.io/api/networking/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/networking/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_IPBlock = map[string]string{ "": "IPBlock describes a particular CIDR (Ex. \"192.168.1.1/24\") that is allowed to the pods matched by a NetworkPolicySpec's podSelector. The except entry describes CIDRs that should not be included within this rule.", "cidr": "CIDR is a string representing the IP Block Valid examples are \"192.168.1.1/24\"", @@ -78,10 +78,10 @@ func (NetworkPolicyList) SwaggerDoc() map[string]string { } var map_NetworkPolicyPeer = map[string]string{ - "": "NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields must be specified.", - "podSelector": "This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace.", - "namespaceSelector": "Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces.", - "ipBlock": "IPBlock defines policy on a particular IPBlock", + "": "NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of fields are allowed", + "podSelector": "This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.\n\nIf NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy's own Namespace.", + "namespaceSelector": "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector.", + "ipBlock": "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.", } func (NetworkPolicyPeer) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/api/networking/v1/zz_generated.deepcopy.go b/vendor/k8s.io/api/networking/v1/zz_generated.deepcopy.go index 8a7c1530e..0037638a8 100644 --- a/vendor/k8s.io/api/networking/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/networking/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/policy/v1beta1/generated.pb.go b/vendor/k8s.io/api/policy/v1beta1/generated.pb.go index 24bbe8975..505fb0e03 100644 --- a/vendor/k8s.io/api/policy/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/policy/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -200,6 +200,14 @@ func (m *AllowedHostPath) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.PathPrefix))) i += copy(dAtA[i:], m.PathPrefix) + dAtA[i] = 0x10 + i++ + if m.ReadOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -794,6 +802,40 @@ func (m *PodSecurityPolicySpec) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + dAtA[i] = 0x9a + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + dAtA[i] = 0xa2 + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } return i, nil } @@ -937,6 +979,7 @@ func (m *AllowedHostPath) Size() (n int) { _ = l l = len(m.PathPrefix) n += 1 + l + sovGenerated(uint64(l)) + n += 2 return n } @@ -1134,6 +1177,18 @@ func (m *PodSecurityPolicySpec) Size() (n int) { n += 2 + l + sovGenerated(uint64(l)) } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -1206,6 +1261,7 @@ func (this *AllowedHostPath) String() string { } s := strings.Join([]string{`&AllowedHostPath{`, `PathPrefix:` + fmt.Sprintf("%v", this.PathPrefix) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, `}`, }, "") return s @@ -1359,6 +1415,8 @@ func (this *PodSecurityPolicySpec) String() string { `AllowPrivilegeEscalation:` + valueToStringGenerated(this.AllowPrivilegeEscalation) + `,`, `AllowedHostPaths:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedHostPaths), "AllowedHostPath", "AllowedHostPath", 1), `&`, ``, 1) + `,`, `AllowedFlexVolumes:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedFlexVolumes), "AllowedFlexVolume", "AllowedFlexVolume", 1), `&`, ``, 1) + `,`, + `AllowedUnsafeSysctls:` + fmt.Sprintf("%v", this.AllowedUnsafeSysctls) + `,`, + `ForbiddenSysctls:` + fmt.Sprintf("%v", this.ForbiddenSysctls) + `,`, `}`, }, "") return s @@ -1541,6 +1599,26 @@ func (m *AllowedHostPath) Unmarshal(dAtA []byte) error { } m.PathPrefix = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -3348,6 +3426,64 @@ func (m *PodSecurityPolicySpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedUnsafeSysctls", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedUnsafeSysctls = append(m.AllowedUnsafeSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ForbiddenSysctls", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ForbiddenSysctls = append(m.ForbiddenSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -3811,106 +3947,110 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1605 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4f, 0x6f, 0x1b, 0xb9, - 0x15, 0xf7, 0x58, 0xb6, 0x65, 0xd3, 0xf2, 0x3f, 0xba, 0x76, 0x27, 0x46, 0x23, 0x35, 0x0a, 0x50, - 0xa4, 0x41, 0x33, 0x8a, 0x9d, 0xa4, 0x35, 0x9a, 0xb6, 0xa8, 0xc7, 0xf2, 0xbf, 0x20, 0xae, 0x55, - 0x2a, 0x09, 0xda, 0x22, 0x2d, 0x4a, 0x69, 0x68, 0x89, 0xf1, 0x68, 0x66, 0x4a, 0x72, 0x14, 0xe9, - 0xd6, 0x43, 0x0f, 0x3d, 0xf6, 0x0b, 0xf4, 0x13, 0x14, 0x3d, 0xed, 0x97, 0xf0, 0x02, 0x8b, 0x45, - 0x8e, 0xc1, 0x1e, 0x84, 0x8d, 0x16, 0xfb, 0x25, 0x72, 0x5a, 0x0c, 0xc5, 0x91, 0x34, 0x33, 0x92, - 0x1c, 0x07, 0x48, 0x6e, 0x1a, 0xbe, 0xdf, 0xef, 0xf7, 0x1e, 0x1f, 0xc9, 0xc7, 0x47, 0x01, 0xf3, - 0x62, 0x97, 0x1b, 0xd4, 0x2d, 0x5c, 0xf8, 0x15, 0xc2, 0x1c, 0x22, 0x08, 0x2f, 0x34, 0x89, 0x63, - 0xb9, 0xac, 0xa0, 0x0c, 0xd8, 0xa3, 0x05, 0xcf, 0xb5, 0x69, 0xb5, 0x5d, 0x68, 0x6e, 0x57, 0x88, - 0xc0, 0xdb, 0x85, 0x1a, 0x71, 0x08, 0xc3, 0x82, 0x58, 0x86, 0xc7, 0x5c, 0xe1, 0xc2, 0x1b, 0x3d, - 0xa8, 0x81, 0x3d, 0x6a, 0xf4, 0xa0, 0x86, 0x82, 0x6e, 0xdd, 0xab, 0x51, 0x51, 0xf7, 0x2b, 0x46, - 0xd5, 0x6d, 0x14, 0x6a, 0x6e, 0xcd, 0x2d, 0x48, 0x46, 0xc5, 0x3f, 0x97, 0x5f, 0xf2, 0x43, 0xfe, - 0xea, 0x29, 0x6d, 0xe5, 0x87, 0x9c, 0x56, 0x5d, 0x46, 0x0a, 0xcd, 0x84, 0xb7, 0xad, 0x87, 0x03, - 0x4c, 0x03, 0x57, 0xeb, 0xd4, 0x21, 0xac, 0x5d, 0xf0, 0x2e, 0x6a, 0xc1, 0x00, 0x2f, 0x34, 0x88, - 0xc0, 0xa3, 0x58, 0x85, 0x71, 0x2c, 0xe6, 0x3b, 0x82, 0x36, 0x48, 0x82, 0xf0, 0xcb, 0xab, 0x08, - 0xbc, 0x5a, 0x27, 0x0d, 0x9c, 0xe0, 0x3d, 0x18, 0xc7, 0xf3, 0x05, 0xb5, 0x0b, 0xd4, 0x11, 0x5c, - 0xb0, 0x38, 0x29, 0xff, 0x18, 0xac, 0xed, 0xd9, 0xb6, 0xfb, 0x9a, 0x58, 0x87, 0x36, 0x69, 0xbd, - 0x70, 0x6d, 0xbf, 0x41, 0xe0, 0xcf, 0xc0, 0x9c, 0xc5, 0x68, 0x93, 0x30, 0x5d, 0xfb, 0xa9, 0x76, - 0x67, 0xc1, 0x5c, 0xbe, 0xec, 0xe4, 0xa6, 0xba, 0x9d, 0xdc, 0x5c, 0x51, 0x8e, 0x22, 0x65, 0xcd, - 0x1f, 0x80, 0x15, 0x45, 0x3e, 0x76, 0xb9, 0x28, 0x61, 0x51, 0x87, 0x3b, 0x00, 0x78, 0x58, 0xd4, - 0x4b, 0x8c, 0x9c, 0xd3, 0x96, 0xa2, 0x43, 0x45, 0x07, 0xa5, 0xbe, 0x05, 0x0d, 0xa1, 0xf2, 0xdf, - 0x68, 0x60, 0xfe, 0xa0, 0x49, 0xab, 0x82, 0xba, 0x0e, 0xfc, 0x3b, 0x98, 0x0f, 0x32, 0x69, 0x61, - 0x81, 0x25, 0x7d, 0x71, 0xe7, 0xbe, 0x31, 0x58, 0xe5, 0xfe, 0xc4, 0x0c, 0xef, 0xa2, 0x16, 0x0c, - 0x70, 0x23, 0x40, 0x1b, 0xcd, 0x6d, 0xe3, 0xac, 0xf2, 0x8a, 0x54, 0xc5, 0x29, 0x11, 0x78, 0xe0, - 0x70, 0x30, 0x86, 0xfa, 0xaa, 0xd0, 0x06, 0x4b, 0x16, 0xb1, 0x89, 0x20, 0x67, 0x5e, 0xe0, 0x91, - 0xeb, 0xd3, 0xd2, 0xcd, 0x83, 0x0f, 0x73, 0x53, 0x1c, 0xa6, 0x9a, 0x6b, 0xdd, 0x4e, 0x6e, 0x29, - 0x32, 0x84, 0xa2, 0xe2, 0xf9, 0xff, 0x6a, 0x60, 0xf3, 0xb0, 0x7c, 0xc4, 0x5c, 0xdf, 0x2b, 0x8b, - 0x20, 0xf3, 0xb5, 0xb6, 0x32, 0xc1, 0x5f, 0x81, 0x19, 0xe6, 0xdb, 0x44, 0x65, 0xe9, 0xb6, 0x0a, - 0x7a, 0x06, 0xf9, 0x36, 0x79, 0xdf, 0xc9, 0xad, 0xc7, 0x58, 0xcf, 0xda, 0x1e, 0x41, 0x92, 0x00, - 0x9f, 0x80, 0x39, 0x86, 0x9d, 0x1a, 0x09, 0x42, 0x4f, 0xdd, 0x59, 0xdc, 0xc9, 0x1b, 0x63, 0xcf, - 0x81, 0x71, 0x52, 0x44, 0x01, 0x74, 0xb0, 0x86, 0xf2, 0x93, 0x23, 0xa5, 0x90, 0x3f, 0x05, 0x4b, - 0x72, 0xf1, 0x5c, 0x26, 0xa4, 0x05, 0xde, 0x04, 0xa9, 0x06, 0x75, 0x64, 0x50, 0xb3, 0xe6, 0xa2, - 0x62, 0xa5, 0x4e, 0xa9, 0x83, 0x82, 0x71, 0x69, 0xc6, 0x2d, 0x99, 0xb3, 0x61, 0x33, 0x6e, 0xa1, - 0x60, 0x3c, 0x7f, 0x04, 0xd2, 0xca, 0xe3, 0xb0, 0x50, 0x6a, 0xb2, 0x50, 0x6a, 0x84, 0xd0, 0xff, - 0xa6, 0xc1, 0x7a, 0xc9, 0xb5, 0x8a, 0x94, 0x33, 0x5f, 0xe6, 0xcb, 0xf4, 0xad, 0x1a, 0x11, 0x9f, - 0x61, 0x7f, 0x3c, 0x03, 0x33, 0xdc, 0x23, 0x55, 0xb5, 0x2d, 0x76, 0x26, 0xe4, 0x76, 0x44, 0x7c, - 0x65, 0x8f, 0x54, 0xcd, 0x4c, 0xb8, 0x94, 0xc1, 0x17, 0x92, 0x6a, 0xf0, 0x25, 0x98, 0xe3, 0x02, - 0x0b, 0x9f, 0xeb, 0x29, 0xa9, 0xfb, 0xf0, 0x9a, 0xba, 0x92, 0x3b, 0x58, 0xc5, 0xde, 0x37, 0x52, - 0x9a, 0xf9, 0xaf, 0x34, 0xf0, 0xe3, 0x11, 0xac, 0xa7, 0x94, 0x0b, 0xf8, 0x32, 0x91, 0x31, 0xe3, - 0xc3, 0x32, 0x16, 0xb0, 0x65, 0xbe, 0x56, 0x95, 0xd7, 0xf9, 0x70, 0x64, 0x28, 0x5b, 0x65, 0x30, - 0x4b, 0x05, 0x69, 0x84, 0x5b, 0xd1, 0xb8, 0xde, 0xb4, 0xcc, 0x25, 0x25, 0x3d, 0x7b, 0x12, 0x88, - 0xa0, 0x9e, 0x56, 0xfe, 0xeb, 0xe9, 0x91, 0xd3, 0x09, 0xd2, 0x09, 0xcf, 0x41, 0xa6, 0x41, 0x9d, - 0xbd, 0x26, 0xa6, 0x36, 0xae, 0xa8, 0xd3, 0x33, 0x69, 0x13, 0x04, 0xd5, 0xcf, 0xe8, 0x55, 0x3f, - 0xe3, 0xc4, 0x11, 0x67, 0xac, 0x2c, 0x18, 0x75, 0x6a, 0xe6, 0x6a, 0xb7, 0x93, 0xcb, 0x9c, 0x0e, - 0x29, 0xa1, 0x88, 0x2e, 0xfc, 0x2b, 0x98, 0xe7, 0xc4, 0x26, 0x55, 0xe1, 0xb2, 0xeb, 0x55, 0x88, - 0xa7, 0xb8, 0x42, 0xec, 0xb2, 0xa2, 0x9a, 0x99, 0x20, 0x6f, 0xe1, 0x17, 0xea, 0x4b, 0x42, 0x1b, - 0x2c, 0x37, 0x70, 0xeb, 0xb9, 0x83, 0xfb, 0x13, 0x49, 0x7d, 0xe4, 0x44, 0x60, 0xb7, 0x93, 0x5b, - 0x3e, 0x8d, 0x68, 0xa1, 0x98, 0x76, 0xfe, 0xfb, 0x19, 0x70, 0x63, 0xec, 0xae, 0x82, 0x4f, 0x00, - 0x74, 0x2b, 0x9c, 0xb0, 0x26, 0xb1, 0x8e, 0x7a, 0xf7, 0x03, 0x75, 0xc3, 0x83, 0xbb, 0xa5, 0x16, - 0x08, 0x9e, 0x25, 0x10, 0x68, 0x04, 0x0b, 0xfe, 0x4b, 0x03, 0x4b, 0x56, 0xcf, 0x0d, 0xb1, 0x4a, - 0xae, 0x15, 0x6e, 0x8c, 0xa3, 0x8f, 0xd9, 0xef, 0x46, 0x71, 0x58, 0xe9, 0xc0, 0x11, 0xac, 0x6d, - 0x6e, 0xa8, 0x80, 0x96, 0x22, 0x36, 0x14, 0x75, 0x0a, 0x4f, 0x01, 0xb4, 0xfa, 0x92, 0x5c, 0xdd, - 0x52, 0x32, 0xc5, 0xb3, 0xe6, 0x4d, 0xa5, 0xb0, 0x11, 0xf1, 0x1b, 0x82, 0xd0, 0x08, 0x22, 0xfc, - 0x1d, 0x58, 0xae, 0xfa, 0x8c, 0x11, 0x47, 0x1c, 0x13, 0x6c, 0x8b, 0x7a, 0x5b, 0x9f, 0x91, 0x52, - 0x9b, 0x4a, 0x6a, 0x79, 0x3f, 0x62, 0x45, 0x31, 0x74, 0xc0, 0xb7, 0x08, 0xa7, 0x8c, 0x58, 0x21, - 0x7f, 0x36, 0xca, 0x2f, 0x46, 0xac, 0x28, 0x86, 0x86, 0xbb, 0x20, 0x43, 0x5a, 0x1e, 0xa9, 0x86, - 0x39, 0x9d, 0x93, 0xec, 0x1f, 0x29, 0x76, 0xe6, 0x60, 0xc8, 0x86, 0x22, 0xc8, 0x2d, 0x1b, 0xc0, - 0x64, 0x12, 0xe1, 0x2a, 0x48, 0x5d, 0x90, 0x76, 0xef, 0xe6, 0x41, 0xc1, 0x4f, 0xf8, 0x7b, 0x30, - 0xdb, 0xc4, 0xb6, 0x4f, 0xd4, 0x5e, 0xbf, 0xfb, 0x61, 0x7b, 0xfd, 0x19, 0x6d, 0x10, 0xd4, 0x23, - 0xfe, 0x7a, 0x7a, 0x57, 0xcb, 0x7f, 0xa9, 0x81, 0xb5, 0x92, 0x6b, 0x95, 0x49, 0xd5, 0x67, 0x54, - 0xb4, 0x4b, 0x72, 0x9d, 0x3f, 0x43, 0xcd, 0x46, 0x91, 0x9a, 0x7d, 0x7f, 0xf2, 0x5e, 0x8b, 0x46, - 0x37, 0xae, 0x62, 0xe7, 0x2f, 0x35, 0xb0, 0x91, 0x40, 0x7f, 0x86, 0x8a, 0xfa, 0xc7, 0x68, 0x45, - 0xfd, 0xc5, 0x75, 0x26, 0x33, 0xa6, 0x9e, 0xbe, 0xcf, 0x8c, 0x98, 0x8a, 0xac, 0xa6, 0x41, 0xbf, - 0xc6, 0x68, 0x93, 0xda, 0xa4, 0x46, 0x2c, 0x39, 0x99, 0xf9, 0xa1, 0x7e, 0xad, 0x6f, 0x41, 0x43, - 0x28, 0xc8, 0xc1, 0xa6, 0x45, 0xce, 0xb1, 0x6f, 0x8b, 0x3d, 0xcb, 0xda, 0xc7, 0x1e, 0xae, 0x50, - 0x9b, 0x0a, 0xaa, 0xda, 0x91, 0x05, 0xf3, 0x71, 0xb7, 0x93, 0xdb, 0x2c, 0x8e, 0x44, 0xbc, 0xef, - 0xe4, 0x6e, 0x26, 0x3b, 0x6d, 0xa3, 0x0f, 0x69, 0xa3, 0x31, 0xd2, 0xb0, 0x0d, 0x74, 0x46, 0xfe, - 0xe1, 0x07, 0x87, 0xa2, 0xc8, 0x5c, 0x2f, 0xe2, 0x36, 0x25, 0xdd, 0xfe, 0xb6, 0xdb, 0xc9, 0xe9, - 0x68, 0x0c, 0xe6, 0x6a, 0xc7, 0x63, 0xe5, 0xe1, 0x2b, 0xb0, 0x8e, 0x7b, 0x75, 0x20, 0xe2, 0x75, - 0x46, 0x7a, 0xdd, 0xed, 0x76, 0x72, 0xeb, 0x7b, 0x49, 0xf3, 0xd5, 0x0e, 0x47, 0x89, 0xc2, 0x02, - 0x48, 0x37, 0x65, 0x13, 0xce, 0xf5, 0x59, 0xa9, 0xbf, 0xd1, 0xed, 0xe4, 0xd2, 0xbd, 0xbe, 0x3c, - 0xd0, 0x9c, 0x3b, 0x2c, 0xcb, 0x46, 0x30, 0x44, 0xc1, 0x47, 0x60, 0xb1, 0xee, 0x72, 0xf1, 0x07, - 0x22, 0x5e, 0xbb, 0xec, 0x42, 0x16, 0x86, 0x79, 0x73, 0x5d, 0xad, 0xe0, 0xe2, 0xf1, 0xc0, 0x84, - 0x86, 0x71, 0xf0, 0xcf, 0x60, 0xa1, 0xae, 0xda, 0x3e, 0xae, 0xa7, 0xe5, 0x46, 0xbb, 0x33, 0x61, - 0xa3, 0x45, 0x5a, 0x44, 0x73, 0x4d, 0xc9, 0x2f, 0x84, 0xc3, 0x1c, 0x0d, 0xd4, 0xe0, 0xcf, 0x41, - 0x5a, 0x7e, 0x9c, 0x14, 0xf5, 0x79, 0x19, 0xcd, 0x8a, 0x82, 0xa7, 0x8f, 0x7b, 0xc3, 0x28, 0xb4, - 0x87, 0xd0, 0x93, 0xd2, 0xbe, 0xbe, 0x90, 0x84, 0x9e, 0x94, 0xf6, 0x51, 0x68, 0x87, 0x2f, 0x41, - 0x9a, 0x93, 0xa7, 0xd4, 0xf1, 0x5b, 0x3a, 0x90, 0x47, 0x6e, 0x7b, 0x42, 0xb8, 0xe5, 0x03, 0x89, - 0x8c, 0x35, 0xdc, 0x03, 0x75, 0x65, 0x47, 0xa1, 0x24, 0xb4, 0xc0, 0x02, 0xf3, 0x9d, 0x3d, 0xfe, - 0x9c, 0x13, 0xa6, 0x2f, 0x26, 0x6e, 0xfb, 0xb8, 0x3e, 0x0a, 0xb1, 0x71, 0x0f, 0xfd, 0xcc, 0xf4, - 0x11, 0x68, 0x20, 0x0c, 0xff, 0xad, 0x01, 0xc8, 0x7d, 0xcf, 0xb3, 0x49, 0x83, 0x38, 0x02, 0xdb, - 0xb2, 0xbf, 0xe7, 0x7a, 0x46, 0xfa, 0xfb, 0xcd, 0xa4, 0xf9, 0x24, 0x48, 0x71, 0xc7, 0xfd, 0x6b, - 0x3a, 0x09, 0x45, 0x23, 0x7c, 0x06, 0xe9, 0x3c, 0xe7, 0xf2, 0xb7, 0xbe, 0x74, 0x65, 0x3a, 0x47, - 0xbf, 0x5f, 0x06, 0xe9, 0x54, 0x76, 0x14, 0x4a, 0xc2, 0x17, 0x60, 0x93, 0x11, 0x6c, 0x9d, 0x39, - 0x76, 0x1b, 0xb9, 0xae, 0x38, 0xa4, 0x36, 0xe1, 0x6d, 0x2e, 0x48, 0x43, 0x5f, 0x96, 0xcb, 0x9c, - 0x55, 0xcc, 0x4d, 0x34, 0x12, 0x85, 0xc6, 0xb0, 0x61, 0x03, 0xe4, 0xc2, 0xf2, 0x10, 0x9c, 0x9d, - 0x7e, 0x7d, 0x3a, 0xe0, 0x55, 0x6c, 0xf7, 0xba, 0x96, 0x15, 0xe9, 0xe0, 0x76, 0xb7, 0x93, 0xcb, - 0x15, 0x27, 0x43, 0xd1, 0x55, 0x5a, 0xf0, 0x4f, 0x40, 0xc7, 0xe3, 0xfc, 0xac, 0x4a, 0x3f, 0x3f, - 0x09, 0x6a, 0xce, 0x58, 0x07, 0x63, 0xd9, 0xd0, 0x03, 0xab, 0x38, 0xfa, 0x72, 0xe6, 0xfa, 0x9a, - 0x3c, 0x85, 0x77, 0x27, 0xac, 0x43, 0xec, 0xb1, 0x6d, 0xea, 0x2a, 0x8d, 0xab, 0x31, 0x03, 0x47, - 0x09, 0x75, 0xd8, 0x02, 0x10, 0xc7, 0x1f, 0xfa, 0x5c, 0x87, 0x57, 0x5e, 0x31, 0x89, 0x7f, 0x07, - 0x06, 0x5b, 0x2d, 0x61, 0xe2, 0x68, 0x84, 0x8f, 0xe0, 0x05, 0xac, 0x8f, 0x3b, 0x30, 0xf0, 0x51, - 0xe4, 0x0d, 0x7c, 0x2b, 0xf6, 0x06, 0x5e, 0x4b, 0xf0, 0x3e, 0xc1, 0x0b, 0xf8, 0xff, 0x1a, 0xd8, - 0x1c, 0x5d, 0x30, 0xe0, 0x83, 0x48, 0x74, 0xb9, 0x58, 0x74, 0x2b, 0x31, 0x96, 0x8a, 0xed, 0x6f, - 0x60, 0x59, 0x95, 0x95, 0xe8, 0x1f, 0x0c, 0x91, 0x18, 0x83, 0xfb, 0x20, 0xe8, 0x08, 0x94, 0x44, - 0x78, 0xa4, 0x64, 0x2f, 0x1f, 0x1d, 0x43, 0x31, 0xb5, 0xfc, 0x17, 0x1a, 0xb8, 0x75, 0x65, 0x41, - 0x80, 0x66, 0x24, 0x74, 0x23, 0x16, 0x7a, 0x76, 0xbc, 0xc0, 0xa7, 0xf9, 0x9f, 0xc1, 0xbc, 0x77, - 0xf9, 0x2e, 0x3b, 0xf5, 0xe6, 0x5d, 0x76, 0xea, 0xed, 0xbb, 0xec, 0xd4, 0x3f, 0xbb, 0x59, 0xed, - 0xb2, 0x9b, 0xd5, 0xde, 0x74, 0xb3, 0xda, 0xdb, 0x6e, 0x56, 0xfb, 0xb6, 0x9b, 0xd5, 0xfe, 0xf3, - 0x5d, 0x76, 0xea, 0x2f, 0x69, 0x25, 0xf7, 0x43, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x7d, 0x0b, - 0x1d, 0x1e, 0x14, 0x00, 0x00, + // 1679 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4f, 0x6f, 0x23, 0xb7, + 0x15, 0xf7, 0xac, 0x6c, 0x4b, 0xa6, 0x6d, 0xad, 0x4d, 0x7b, 0xdd, 0x89, 0xd1, 0xd5, 0x24, 0x0a, + 0x50, 0x6c, 0x83, 0x64, 0x14, 0x7b, 0x93, 0xd6, 0x68, 0xda, 0x22, 0x1e, 0xcb, 0xff, 0x02, 0xbb, + 0x56, 0xa9, 0xdd, 0xa0, 0x2d, 0xb6, 0x45, 0x29, 0x0d, 0x2d, 0x31, 0x1e, 0xcd, 0x4c, 0x49, 0x8e, + 0x22, 0xdd, 0x7a, 0xe8, 0xa1, 0xe8, 0xa9, 0x5f, 0xa0, 0x9f, 0xa0, 0xe8, 0xa9, 0x5f, 0xc2, 0x05, + 0x8a, 0x22, 0xc7, 0xa0, 0x07, 0xa1, 0xab, 0xa2, 0x5f, 0x22, 0xa7, 0x62, 0x28, 0x8e, 0xa4, 0xf9, + 0x23, 0x79, 0x1d, 0x60, 0xf7, 0xa6, 0xe1, 0xfb, 0xfd, 0x7e, 0xef, 0xf1, 0xf1, 0xf1, 0x91, 0x14, + 0xb0, 0x6e, 0x0e, 0xb8, 0x49, 0xbd, 0xca, 0x4d, 0xd0, 0x20, 0xcc, 0x25, 0x82, 0xf0, 0x4a, 0x97, + 0xb8, 0xb6, 0xc7, 0x2a, 0xca, 0x80, 0x7d, 0x5a, 0xf1, 0x3d, 0x87, 0x36, 0xfb, 0x95, 0xee, 0x5e, + 0x83, 0x08, 0xbc, 0x57, 0x69, 0x11, 0x97, 0x30, 0x2c, 0x88, 0x6d, 0xfa, 0xcc, 0x13, 0x1e, 0x7c, + 0x6b, 0x04, 0x35, 0xb1, 0x4f, 0xcd, 0x11, 0xd4, 0x54, 0xd0, 0xdd, 0x0f, 0x5a, 0x54, 0xb4, 0x83, + 0x86, 0xd9, 0xf4, 0x3a, 0x95, 0x96, 0xd7, 0xf2, 0x2a, 0x92, 0xd1, 0x08, 0xae, 0xe5, 0x97, 0xfc, + 0x90, 0xbf, 0x46, 0x4a, 0xbb, 0xe5, 0x29, 0xa7, 0x4d, 0x8f, 0x91, 0x4a, 0x37, 0xe5, 0x6d, 0xf7, + 0xa3, 0x09, 0xa6, 0x83, 0x9b, 0x6d, 0xea, 0x12, 0xd6, 0xaf, 0xf8, 0x37, 0xad, 0x70, 0x80, 0x57, + 0x3a, 0x44, 0xe0, 0x2c, 0x56, 0x65, 0x16, 0x8b, 0x05, 0xae, 0xa0, 0x1d, 0x92, 0x22, 0xfc, 0xe0, + 0x2e, 0x02, 0x6f, 0xb6, 0x49, 0x07, 0xa7, 0x78, 0x4f, 0x67, 0xf1, 0x02, 0x41, 0x9d, 0x0a, 0x75, + 0x05, 0x17, 0x2c, 0x49, 0x2a, 0x7f, 0x02, 0x36, 0x0f, 0x1d, 0xc7, 0xfb, 0x92, 0xd8, 0x27, 0x0e, + 0xe9, 0x7d, 0xee, 0x39, 0x41, 0x87, 0xc0, 0xef, 0x81, 0x65, 0x9b, 0xd1, 0x2e, 0x61, 0xba, 0xf6, + 0xb6, 0xf6, 0x64, 0xc5, 0x2a, 0xde, 0x0e, 0x8c, 0x85, 0xe1, 0xc0, 0x58, 0xae, 0xca, 0x51, 0xa4, + 0xac, 0x65, 0x0e, 0x1e, 0x2a, 0xf2, 0x99, 0xc7, 0x45, 0x0d, 0x8b, 0x36, 0xdc, 0x07, 0xc0, 0xc7, + 0xa2, 0x5d, 0x63, 0xe4, 0x9a, 0xf6, 0x14, 0x1d, 0x2a, 0x3a, 0xa8, 0x8d, 0x2d, 0x68, 0x0a, 0x05, + 0xdf, 0x07, 0x05, 0x46, 0xb0, 0x7d, 0xe5, 0x3a, 0x7d, 0xfd, 0xc1, 0xdb, 0xda, 0x93, 0x82, 0xb5, + 0xa1, 0x18, 0x05, 0xa4, 0xc6, 0xd1, 0x18, 0x51, 0xfe, 0xb7, 0x06, 0x0a, 0xc7, 0x5d, 0xda, 0x14, + 0xd4, 0x73, 0xe1, 0x6f, 0x41, 0x21, 0xcc, 0xbb, 0x8d, 0x05, 0x96, 0xce, 0x56, 0xf7, 0x3f, 0x34, + 0x27, 0x35, 0x31, 0x4e, 0x83, 0xe9, 0xdf, 0xb4, 0xc2, 0x01, 0x6e, 0x86, 0x68, 0xb3, 0xbb, 0x67, + 0x5e, 0x35, 0xbe, 0x20, 0x4d, 0x71, 0x49, 0x04, 0x9e, 0x84, 0x37, 0x19, 0x43, 0x63, 0x55, 0xe8, + 0x80, 0x75, 0x9b, 0x38, 0x44, 0x90, 0x2b, 0x3f, 0xf4, 0xc8, 0x65, 0x84, 0xab, 0xfb, 0x4f, 0x5f, + 0xcd, 0x4d, 0x75, 0x9a, 0x6a, 0x6d, 0x0e, 0x07, 0xc6, 0x7a, 0x6c, 0x08, 0xc5, 0xc5, 0xcb, 0x7f, + 0xd1, 0xc0, 0xce, 0x49, 0xfd, 0x94, 0x79, 0x81, 0x5f, 0x17, 0xe1, 0x3a, 0xb5, 0xfa, 0xca, 0x04, + 0x7f, 0x08, 0x16, 0x59, 0xe0, 0x10, 0x95, 0xd3, 0x77, 0x55, 0xd0, 0x8b, 0x28, 0x70, 0xc8, 0x37, + 0x03, 0x63, 0x2b, 0xc1, 0x7a, 0xd6, 0xf7, 0x09, 0x92, 0x04, 0xf8, 0x19, 0x58, 0x66, 0xd8, 0x6d, + 0x91, 0x30, 0xf4, 0xdc, 0x93, 0xd5, 0xfd, 0xb2, 0x39, 0x73, 0xd7, 0x98, 0xe7, 0x55, 0x14, 0x42, + 0x27, 0x2b, 0x2e, 0x3f, 0x39, 0x52, 0x0a, 0xe5, 0x4b, 0xb0, 0x2e, 0x97, 0xda, 0x63, 0x42, 0x5a, + 0xe0, 0x63, 0x90, 0xeb, 0x50, 0x57, 0x06, 0xb5, 0x64, 0xad, 0x2a, 0x56, 0xee, 0x92, 0xba, 0x28, + 0x1c, 0x97, 0x66, 0xdc, 0x93, 0x39, 0x9b, 0x36, 0xe3, 0x1e, 0x0a, 0xc7, 0xcb, 0xa7, 0x20, 0xaf, + 0x3c, 0x4e, 0x0b, 0xe5, 0xe6, 0x0b, 0xe5, 0x32, 0x84, 0xfe, 0xfa, 0x00, 0x6c, 0xd5, 0x3c, 0xbb, + 0x4a, 0x39, 0x0b, 0x64, 0xbe, 0xac, 0xc0, 0x6e, 0x11, 0xf1, 0x06, 0xea, 0xe3, 0x19, 0x58, 0xe4, + 0x3e, 0x69, 0xaa, 0xb2, 0xd8, 0x9f, 0x93, 0xdb, 0x8c, 0xf8, 0xea, 0x3e, 0x69, 0x5a, 0x6b, 0xd1, + 0x52, 0x86, 0x5f, 0x48, 0xaa, 0xc1, 0x17, 0x60, 0x99, 0x0b, 0x2c, 0x02, 0xae, 0xe7, 0xa4, 0xee, + 0x47, 0xf7, 0xd4, 0x95, 0xdc, 0xc9, 0x2a, 0x8e, 0xbe, 0x91, 0xd2, 0x2c, 0xff, 0x53, 0x03, 0xdf, + 0xc9, 0x60, 0x5d, 0x50, 0x2e, 0xe0, 0x8b, 0x54, 0xc6, 0xcc, 0x57, 0xcb, 0x58, 0xc8, 0x96, 0xf9, + 0x1a, 0x6f, 0xde, 0x68, 0x64, 0x2a, 0x5b, 0x75, 0xb0, 0x44, 0x05, 0xe9, 0x44, 0xa5, 0x68, 0xde, + 0x6f, 0x5a, 0xd6, 0xba, 0x92, 0x5e, 0x3a, 0x0f, 0x45, 0xd0, 0x48, 0xab, 0xfc, 0xaf, 0x07, 0x99, + 0xd3, 0x09, 0xd3, 0x09, 0xaf, 0xc1, 0x5a, 0x87, 0xba, 0x87, 0x5d, 0x4c, 0x1d, 0xdc, 0x50, 0xbb, + 0x67, 0x5e, 0x11, 0x84, 0xbd, 0xd2, 0x1c, 0xf5, 0x4a, 0xf3, 0xdc, 0x15, 0x57, 0xac, 0x2e, 0x18, + 0x75, 0x5b, 0xd6, 0xc6, 0x70, 0x60, 0xac, 0x5d, 0x4e, 0x29, 0xa1, 0x98, 0x2e, 0xfc, 0x35, 0x28, + 0x70, 0xe2, 0x90, 0xa6, 0xf0, 0xd8, 0xfd, 0x3a, 0xc4, 0x05, 0x6e, 0x10, 0xa7, 0xae, 0xa8, 0xd6, + 0x5a, 0x98, 0xb7, 0xe8, 0x0b, 0x8d, 0x25, 0xa1, 0x03, 0x8a, 0x1d, 0xdc, 0x7b, 0xee, 0xe2, 0xf1, + 0x44, 0x72, 0xdf, 0x72, 0x22, 0x70, 0x38, 0x30, 0x8a, 0x97, 0x31, 0x2d, 0x94, 0xd0, 0x2e, 0xff, + 0x6f, 0x11, 0xbc, 0x35, 0xb3, 0xaa, 0xe0, 0x67, 0x00, 0x7a, 0x0d, 0x4e, 0x58, 0x97, 0xd8, 0xa7, + 0xa3, 0xd3, 0x84, 0x7a, 0xd1, 0xc6, 0xdd, 0x55, 0x0b, 0x04, 0xaf, 0x52, 0x08, 0x94, 0xc1, 0x82, + 0x7f, 0xd0, 0xc0, 0xba, 0x3d, 0x72, 0x43, 0xec, 0x9a, 0x67, 0x47, 0x85, 0x71, 0xfa, 0x6d, 0xea, + 0xdd, 0xac, 0x4e, 0x2b, 0x1d, 0xbb, 0x82, 0xf5, 0xad, 0x47, 0x2a, 0xa0, 0xf5, 0x98, 0x0d, 0xc5, + 0x9d, 0xc2, 0x4b, 0x00, 0xed, 0xb1, 0x24, 0x57, 0x67, 0x9a, 0x4c, 0xf1, 0x92, 0xf5, 0x58, 0x29, + 0x3c, 0x8a, 0xf9, 0x8d, 0x40, 0x28, 0x83, 0x08, 0x7f, 0x0a, 0x8a, 0xcd, 0x80, 0x31, 0xe2, 0x8a, + 0x33, 0x82, 0x1d, 0xd1, 0xee, 0xeb, 0x8b, 0x52, 0x6a, 0x47, 0x49, 0x15, 0x8f, 0x62, 0x56, 0x94, + 0x40, 0x87, 0x7c, 0x9b, 0x70, 0xca, 0x88, 0x1d, 0xf1, 0x97, 0xe2, 0xfc, 0x6a, 0xcc, 0x8a, 0x12, + 0x68, 0x78, 0x00, 0xd6, 0x48, 0xcf, 0x27, 0xcd, 0x28, 0xa7, 0xcb, 0x92, 0xbd, 0xad, 0xd8, 0x6b, + 0xc7, 0x53, 0x36, 0x14, 0x43, 0xee, 0x3a, 0x00, 0xa6, 0x93, 0x08, 0x37, 0x40, 0xee, 0x86, 0xf4, + 0x47, 0x27, 0x0f, 0x0a, 0x7f, 0xc2, 0x4f, 0xc1, 0x52, 0x17, 0x3b, 0x01, 0x51, 0xb5, 0xfe, 0xde, + 0xab, 0xd5, 0xfa, 0x33, 0xda, 0x21, 0x68, 0x44, 0xfc, 0xd1, 0x83, 0x03, 0xad, 0xfc, 0x0f, 0x0d, + 0x6c, 0xd6, 0x3c, 0xbb, 0x4e, 0x9a, 0x01, 0xa3, 0xa2, 0x5f, 0x93, 0xeb, 0xfc, 0x06, 0x7a, 0x36, + 0x8a, 0xf5, 0xec, 0x0f, 0xe7, 0xd7, 0x5a, 0x3c, 0xba, 0x59, 0x1d, 0xbb, 0x7c, 0xab, 0x81, 0x47, + 0x29, 0xf4, 0x1b, 0xe8, 0xa8, 0x3f, 0x8f, 0x77, 0xd4, 0xf7, 0xef, 0x33, 0x99, 0x19, 0xfd, 0xf4, + 0x4f, 0xc5, 0x8c, 0xa9, 0xc8, 0x6e, 0x1a, 0xde, 0xee, 0x18, 0xed, 0x52, 0x87, 0xb4, 0x88, 0x2d, + 0x27, 0x53, 0x98, 0xba, 0xdd, 0x8d, 0x2d, 0x68, 0x0a, 0x05, 0x39, 0xd8, 0xb1, 0xc9, 0x35, 0x0e, + 0x1c, 0x71, 0x68, 0xdb, 0x47, 0xd8, 0xc7, 0x0d, 0xea, 0x50, 0x41, 0xd5, 0x75, 0x64, 0xc5, 0xfa, + 0x64, 0x38, 0x30, 0x76, 0xaa, 0x99, 0x88, 0x6f, 0x06, 0xc6, 0xe3, 0xf4, 0xbd, 0xdc, 0x1c, 0x43, + 0xfa, 0x68, 0x86, 0x34, 0xec, 0x03, 0x9d, 0x91, 0xdf, 0x05, 0xe1, 0xa6, 0xa8, 0x32, 0xcf, 0x8f, + 0xb9, 0xcd, 0x49, 0xb7, 0x3f, 0x19, 0x0e, 0x0c, 0x1d, 0xcd, 0xc0, 0xdc, 0xed, 0x78, 0xa6, 0x3c, + 0xfc, 0x02, 0x6c, 0xe1, 0x51, 0x1f, 0x88, 0x79, 0x5d, 0x94, 0x5e, 0x0f, 0x86, 0x03, 0x63, 0xeb, + 0x30, 0x6d, 0xbe, 0xdb, 0x61, 0x96, 0x28, 0xac, 0x80, 0x7c, 0x57, 0x5e, 0xd9, 0xb9, 0xbe, 0x24, + 0xf5, 0x1f, 0x0d, 0x07, 0x46, 0x7e, 0x74, 0x8b, 0x0f, 0x35, 0x97, 0x4f, 0xea, 0xf2, 0x22, 0x18, + 0xa1, 0xe0, 0xc7, 0x60, 0xb5, 0xed, 0x71, 0xf1, 0x33, 0x22, 0xbe, 0xf4, 0xd8, 0x8d, 0x6c, 0x0c, + 0x05, 0x6b, 0x4b, 0xad, 0xe0, 0xea, 0xd9, 0xc4, 0x84, 0xa6, 0x71, 0xf0, 0x97, 0x60, 0xa5, 0xad, + 0xae, 0x7d, 0x5c, 0xcf, 0xcb, 0x42, 0x7b, 0x32, 0xa7, 0xd0, 0x62, 0x57, 0x44, 0x6b, 0x53, 0xc9, + 0xaf, 0x44, 0xc3, 0x1c, 0x4d, 0xd4, 0xe0, 0xf7, 0x41, 0x5e, 0x7e, 0x9c, 0x57, 0xf5, 0x82, 0x8c, + 0xe6, 0xa1, 0x82, 0xe7, 0xcf, 0x46, 0xc3, 0x28, 0xb2, 0x47, 0xd0, 0xf3, 0xda, 0x91, 0xbe, 0x92, + 0x86, 0x9e, 0xd7, 0x8e, 0x50, 0x64, 0x87, 0x2f, 0x40, 0x9e, 0x93, 0x0b, 0xea, 0x06, 0x3d, 0x1d, + 0xc8, 0x2d, 0xb7, 0x37, 0x27, 0xdc, 0xfa, 0xb1, 0x44, 0x26, 0x2e, 0xdc, 0x13, 0x75, 0x65, 0x47, + 0x91, 0x24, 0xb4, 0xc1, 0x0a, 0x0b, 0xdc, 0x43, 0xfe, 0x9c, 0x13, 0xa6, 0xaf, 0xa6, 0x4e, 0xfb, + 0xa4, 0x3e, 0x8a, 0xb0, 0x49, 0x0f, 0xe3, 0xcc, 0x8c, 0x11, 0x68, 0x22, 0x0c, 0xff, 0xa8, 0x01, + 0xc8, 0x03, 0xdf, 0x77, 0x48, 0x87, 0xb8, 0x02, 0x3b, 0xf2, 0x7e, 0xcf, 0xf5, 0x35, 0xe9, 0xef, + 0xc7, 0xf3, 0xe6, 0x93, 0x22, 0x25, 0x1d, 0x8f, 0x8f, 0xe9, 0x34, 0x14, 0x65, 0xf8, 0x0c, 0xd3, + 0x79, 0xcd, 0xe5, 0x6f, 0x7d, 0xfd, 0xce, 0x74, 0x66, 0xbf, 0x5f, 0x26, 0xe9, 0x54, 0x76, 0x14, + 0x49, 0xc2, 0xcf, 0xc1, 0x4e, 0xf4, 0xba, 0x43, 0x9e, 0x27, 0x4e, 0xa8, 0x43, 0x78, 0x9f, 0x0b, + 0xd2, 0xd1, 0x8b, 0x72, 0x99, 0x4b, 0x8a, 0xb9, 0x83, 0x32, 0x51, 0x68, 0x06, 0x1b, 0x76, 0x80, + 0x11, 0xb5, 0x87, 0x70, 0xef, 0x8c, 0xfb, 0xd3, 0x31, 0x6f, 0x62, 0x67, 0x74, 0x6b, 0x79, 0x28, + 0x1d, 0xbc, 0x3b, 0x1c, 0x18, 0x46, 0x75, 0x3e, 0x14, 0xdd, 0xa5, 0x05, 0x7f, 0x01, 0x74, 0x3c, + 0xcb, 0xcf, 0x86, 0xf4, 0xf3, 0xdd, 0xb0, 0xe7, 0xcc, 0x74, 0x30, 0x93, 0x0d, 0x7d, 0xb0, 0x81, + 0xe3, 0xef, 0x6c, 0xae, 0x6f, 0xca, 0x5d, 0xf8, 0xde, 0x9c, 0x75, 0x48, 0x3c, 0xcd, 0x2d, 0x5d, + 0xa5, 0x71, 0x23, 0x61, 0xe0, 0x28, 0xa5, 0x0e, 0x7b, 0x00, 0xe2, 0xe4, 0xdf, 0x02, 0x5c, 0x87, + 0x77, 0x1e, 0x31, 0xa9, 0xff, 0x12, 0x26, 0xa5, 0x96, 0x32, 0x71, 0x94, 0xe1, 0x03, 0x5e, 0x80, + 0x6d, 0x35, 0xfa, 0xdc, 0xe5, 0xf8, 0x9a, 0xd4, 0xfb, 0xbc, 0x29, 0x1c, 0xae, 0x6f, 0xc9, 0xfe, + 0xa6, 0x0f, 0x07, 0xc6, 0xf6, 0x61, 0x86, 0x1d, 0x65, 0xb2, 0xe0, 0xa7, 0x60, 0xe3, 0xda, 0x63, + 0x0d, 0x6a, 0xdb, 0xc4, 0x8d, 0x94, 0xb6, 0xa5, 0xd2, 0x76, 0x98, 0x89, 0x93, 0x84, 0x0d, 0xa5, + 0xd0, 0xe1, 0x8b, 0x5c, 0x9f, 0xb5, 0x81, 0xe1, 0xc7, 0xb1, 0x37, 0xf9, 0x3b, 0x89, 0x37, 0xf9, + 0x66, 0x8a, 0xf7, 0x1a, 0x5e, 0xe4, 0x7f, 0xd3, 0xc0, 0x4e, 0x76, 0x03, 0x83, 0x4f, 0x63, 0xd1, + 0x19, 0x89, 0xe8, 0x1e, 0x26, 0x58, 0x2a, 0xb6, 0xdf, 0x80, 0xa2, 0x6a, 0x73, 0xf1, 0x3f, 0x3c, + 0x62, 0x31, 0x86, 0xe7, 0x53, 0x78, 0x43, 0x51, 0x12, 0xd1, 0x16, 0x97, 0x6f, 0x8b, 0xf8, 0x18, + 0x4a, 0xa8, 0x95, 0xff, 0xae, 0x81, 0x77, 0xee, 0x6c, 0x50, 0xd0, 0x8a, 0x85, 0x6e, 0x26, 0x42, + 0x2f, 0xcd, 0x16, 0x78, 0x3d, 0xff, 0x7b, 0x58, 0x1f, 0xdc, 0xbe, 0x2c, 0x2d, 0x7c, 0xf5, 0xb2, + 0xb4, 0xf0, 0xf5, 0xcb, 0xd2, 0xc2, 0xef, 0x87, 0x25, 0xed, 0x76, 0x58, 0xd2, 0xbe, 0x1a, 0x96, + 0xb4, 0xaf, 0x87, 0x25, 0xed, 0x3f, 0xc3, 0x92, 0xf6, 0xe7, 0xff, 0x96, 0x16, 0x7e, 0x95, 0x57, + 0x72, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x91, 0xe5, 0x7f, 0xdc, 0x14, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/policy/v1beta1/generated.proto b/vendor/k8s.io/api/policy/v1beta1/generated.proto index 514868a9f..1a14d946f 100644 --- a/vendor/k8s.io/api/policy/v1beta1/generated.proto +++ b/vendor/k8s.io/api/policy/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,14 +32,14 @@ option go_package = "v1beta1"; // AllowedFlexVolume represents a single Flexvolume that is allowed to be used. message AllowedFlexVolume { - // Driver is the name of the Flexvolume driver. + // driver is the name of the Flexvolume driver. optional string driver = 1; } -// defines the host volume conditions that will be enabled by a policy +// AllowedHostPath defines the host volume conditions that will be enabled by a policy // for pods to use. It requires the path prefix to be defined. message AllowedHostPath { - // is the path prefix that the host volume must match. + // pathPrefix is the path prefix that the host volume must match. // It does not support `*`. // Trailing slashes are trimmed when validating the path prefix with a host path. // @@ -47,6 +47,10 @@ message AllowedHostPath { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` optional string pathPrefix = 1; + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + optional bool readOnly = 2; } // Eviction evicts a pod from its node subject to certain policies and safety constraints. @@ -62,17 +66,17 @@ message Eviction { // FSGroupStrategyOptions defines the strategy type and options used to create the strategy. message FSGroupStrategyOptions { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. // +optional optional string rule = 1; - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. + // ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } -// Host Port Range defines a range of host ports that will be enabled by a policy +// HostPortRange defines a range of host ports that will be enabled by a policy // for pods to use. It requires both the start and end to be defined. message HostPortRange { // min is the start of the range, inclusive. @@ -82,12 +86,12 @@ message HostPortRange { optional int32 max = 2; } -// ID Range provides a min/max of an allowed range of IDs. +// IDRange provides a min/max of an allowed range of IDs. message IDRange { - // Min is the start of the range, inclusive. + // min is the start of the range, inclusive. optional int64 min = 1; - // Max is the end of the range, inclusive. + // max is the end of the range, inclusive. optional int64 max = 2; } @@ -162,7 +166,7 @@ message PodDisruptionBudgetStatus { optional int32 expectedPods = 6; } -// Pod Security Policy governs the ability to make requests that affect the Security Context +// PodSecurityPolicy governs the ability to make requests that affect the Security Context // that will be applied to a pod and container. message PodSecurityPolicy { // Standard object's metadata. @@ -175,43 +179,43 @@ message PodSecurityPolicy { optional PodSecurityPolicySpec spec = 2; } -// Pod Security Policy List is a list of PodSecurityPolicy objects. +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. message PodSecurityPolicyList { // Standard list metadata. // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - // Items is a list of schema objects. + // items is a list of schema objects. repeated PodSecurityPolicy items = 2; } -// Pod Security Policy Spec defines the policy enforced. +// PodSecurityPolicySpec defines the policy enforced. message PodSecurityPolicySpec { // privileged determines if a pod can request to be run as privileged. // +optional optional bool privileged = 1; - // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // defaultAddCapabilities is the default set of capabilities that will be added to the container // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. + // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the allowedCapabilities list. // +optional repeated string defaultAddCapabilities = 2; - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // requiredDropCapabilities are the capabilities that will be dropped from the container. These // are required to be dropped and cannot be added. // +optional repeated string requiredDropCapabilities = 3; - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // allowedCapabilities is a list of capabilities that can be requested to add to the container. // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. // +optional repeated string allowedCapabilities = 4; - // volumes is a white list of allowed volume plugins. Empty indicates that all plugins - // may be used. + // volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. // +optional repeated string volumes = 5; @@ -237,13 +241,13 @@ message PodSecurityPolicySpec { // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. optional RunAsUserStrategyOptions runAsUser = 11; - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. optional SupplementalGroupsStrategyOptions supplementalGroups = 12; - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. optional FSGroupStrategyOptions fsGroup = 13; - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // readOnlyRootFilesystem when set to true will force containers to run with a read only root file // system. If the container specifically requests to run with a non-read only root file system // the PSP should deny the pod. // If set to false the container may run with a read only root file system if it wishes but it @@ -251,40 +255,63 @@ message PodSecurityPolicySpec { // +optional optional bool readOnlyRootFilesystem = 14; - // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // defaultAllowPrivilegeEscalation controls the default setting for whether a // process can gain more privileges than its parent process. // +optional optional bool defaultAllowPrivilegeEscalation = 15; - // AllowPrivilegeEscalation determines if a pod can request to allow + // allowPrivilegeEscalation determines if a pod can request to allow // privilege escalation. If unspecified, defaults to true. // +optional optional bool allowPrivilegeEscalation = 16; - // is a white list of allowed host paths. Empty indicates that all host paths may be used. + // allowedHostPaths is a white list of allowed host paths. Empty indicates + // that all host paths may be used. // +optional repeated AllowedHostPath allowedHostPaths = 17; - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. + // is allowed in the "volumes" field. // +optional repeated AllowedFlexVolume allowedFlexVolumes = 18; + + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + repeated string allowedUnsafeSysctls = 19; + + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + repeated string forbiddenSysctls = 20; } -// Run A sUser Strategy Options defines the strategy type and any options used to create the strategy. +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. message RunAsUserStrategyOptions { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + // rule is the strategy that will dictate the allowable RunAsUser values that may be set. optional string rule = 1; - // Ranges are the allowed ranges of uids that may be used. + // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } -// SELinux Strategy Options defines the strategy type and any options used to create the strategy. +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. message SELinuxStrategyOptions { - // type is the strategy that will dictate the allowable labels that may be set. + // rule is the strategy that will dictate the allowable labels that may be set. optional string rule = 1; // seLinuxOptions required to run as; required for MustRunAs @@ -295,12 +322,12 @@ message SELinuxStrategyOptions { // SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. message SupplementalGroupsStrategyOptions { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. // +optional optional string rule = 1; - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. + // ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } diff --git a/vendor/k8s.io/api/policy/v1beta1/types.go b/vendor/k8s.io/api/policy/v1beta1/types.go index 6cea9615f..ba1e4ff31 100644 --- a/vendor/k8s.io/api/policy/v1beta1/types.go +++ b/vendor/k8s.io/api/policy/v1beta1/types.go @@ -119,7 +119,7 @@ type Eviction struct { // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Pod Security Policy governs the ability to make requests that affect the Security Context +// PodSecurityPolicy governs the ability to make requests that affect the Security Context // that will be applied to a pod and container. type PodSecurityPolicy struct { metav1.TypeMeta `json:",inline"` @@ -133,28 +133,28 @@ type PodSecurityPolicy struct { Spec PodSecurityPolicySpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` } -// Pod Security Policy Spec defines the policy enforced. +// PodSecurityPolicySpec defines the policy enforced. type PodSecurityPolicySpec struct { // privileged determines if a pod can request to be run as privileged. // +optional Privileged bool `json:"privileged,omitempty" protobuf:"varint,1,opt,name=privileged"` - // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // defaultAddCapabilities is the default set of capabilities that will be added to the container // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. + // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the allowedCapabilities list. // +optional DefaultAddCapabilities []v1.Capability `json:"defaultAddCapabilities,omitempty" protobuf:"bytes,2,rep,name=defaultAddCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // requiredDropCapabilities are the capabilities that will be dropped from the container. These // are required to be dropped and cannot be added. // +optional RequiredDropCapabilities []v1.Capability `json:"requiredDropCapabilities,omitempty" protobuf:"bytes,3,rep,name=requiredDropCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // allowedCapabilities is a list of capabilities that can be requested to add to the container. // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. // +optional AllowedCapabilities []v1.Capability `json:"allowedCapabilities,omitempty" protobuf:"bytes,4,rep,name=allowedCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // volumes is a white list of allowed volume plugins. Empty indicates that all plugins - // may be used. + // volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. // +optional Volumes []FSType `json:"volumes,omitempty" protobuf:"bytes,5,rep,name=volumes,casttype=FSType"` // hostNetwork determines if the policy allows the use of HostNetwork in the pod spec. @@ -173,39 +173,59 @@ type PodSecurityPolicySpec struct { SELinux SELinuxStrategyOptions `json:"seLinux" protobuf:"bytes,10,opt,name=seLinux"` // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. RunAsUser RunAsUserStrategyOptions `json:"runAsUser" protobuf:"bytes,11,opt,name=runAsUser"` - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. SupplementalGroups SupplementalGroupsStrategyOptions `json:"supplementalGroups" protobuf:"bytes,12,opt,name=supplementalGroups"` - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. FSGroup FSGroupStrategyOptions `json:"fsGroup" protobuf:"bytes,13,opt,name=fsGroup"` - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // readOnlyRootFilesystem when set to true will force containers to run with a read only root file // system. If the container specifically requests to run with a non-read only root file system // the PSP should deny the pod. // If set to false the container may run with a read only root file system if it wishes but it // will not be forced to. // +optional ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem,omitempty" protobuf:"varint,14,opt,name=readOnlyRootFilesystem"` - // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // defaultAllowPrivilegeEscalation controls the default setting for whether a // process can gain more privileges than its parent process. // +optional DefaultAllowPrivilegeEscalation *bool `json:"defaultAllowPrivilegeEscalation,omitempty" protobuf:"varint,15,opt,name=defaultAllowPrivilegeEscalation"` - // AllowPrivilegeEscalation determines if a pod can request to allow + // allowPrivilegeEscalation determines if a pod can request to allow // privilege escalation. If unspecified, defaults to true. // +optional AllowPrivilegeEscalation *bool `json:"allowPrivilegeEscalation,omitempty" protobuf:"varint,16,opt,name=allowPrivilegeEscalation"` - // is a white list of allowed host paths. Empty indicates that all host paths may be used. + // allowedHostPaths is a white list of allowed host paths. Empty indicates + // that all host paths may be used. // +optional AllowedHostPaths []AllowedHostPath `json:"allowedHostPaths,omitempty" protobuf:"bytes,17,rep,name=allowedHostPaths"` - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. + // is allowed in the "volumes" field. // +optional AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"` + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + AllowedUnsafeSysctls []string `json:"allowedUnsafeSysctls,omitempty" protobuf:"bytes,19,rep,name=allowedUnsafeSysctls"` + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + ForbiddenSysctls []string `json:"forbiddenSysctls,omitempty" protobuf:"bytes,20,rep,name=forbiddenSysctls"` } -// defines the host volume conditions that will be enabled by a policy +// AllowedHostPath defines the host volume conditions that will be enabled by a policy // for pods to use. It requires the path prefix to be defined. type AllowedHostPath struct { - // is the path prefix that the host volume must match. + // pathPrefix is the path prefix that the host volume must match. // It does not support `*`. // Trailing slashes are trimmed when validating the path prefix with a host path. // @@ -213,9 +233,13 @@ type AllowedHostPath struct { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` PathPrefix string `json:"pathPrefix,omitempty" protobuf:"bytes,1,rep,name=pathPrefix"` + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,2,opt,name=readOnly"` } -// FS Type gives strong typing to different file systems that are used by volumes. +// FSType gives strong typing to different file systems that are used by volumes. type FSType string var ( @@ -245,11 +269,11 @@ var ( // AllowedFlexVolume represents a single Flexvolume that is allowed to be used. type AllowedFlexVolume struct { - // Driver is the name of the Flexvolume driver. + // driver is the name of the Flexvolume driver. Driver string `json:"driver" protobuf:"bytes,1,opt,name=driver"` } -// Host Port Range defines a range of host ports that will be enabled by a policy +// HostPortRange defines a range of host ports that will be enabled by a policy // for pods to use. It requires both the start and end to be defined. type HostPortRange struct { // min is the start of the range, inclusive. @@ -258,9 +282,9 @@ type HostPortRange struct { Max int32 `json:"max" protobuf:"varint,2,opt,name=max"` } -// SELinux Strategy Options defines the strategy type and any options used to create the strategy. +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. type SELinuxStrategyOptions struct { - // type is the strategy that will dictate the allowable labels that may be set. + // rule is the strategy that will dictate the allowable labels that may be set. Rule SELinuxStrategy `json:"rule" protobuf:"bytes,1,opt,name=rule,casttype=SELinuxStrategy"` // seLinuxOptions required to run as; required for MustRunAs // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ @@ -273,26 +297,27 @@ type SELinuxStrategyOptions struct { type SELinuxStrategy string const ( - // container must have SELinux labels of X applied. + // SELinuxStrategyMustRunAs means that container must have SELinux labels of X applied. SELinuxStrategyMustRunAs SELinuxStrategy = "MustRunAs" - // container may make requests for any SELinux context labels. + // SELinuxStrategyRunAsAny means that container may make requests for any SELinux context labels. SELinuxStrategyRunAsAny SELinuxStrategy = "RunAsAny" ) -// Run A sUser Strategy Options defines the strategy type and any options used to create the strategy. +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. type RunAsUserStrategyOptions struct { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + // rule is the strategy that will dictate the allowable RunAsUser values that may be set. Rule RunAsUserStrategy `json:"rule" protobuf:"bytes,1,opt,name=rule,casttype=RunAsUserStrategy"` - // Ranges are the allowed ranges of uids that may be used. + // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } -// ID Range provides a min/max of an allowed range of IDs. +// IDRange provides a min/max of an allowed range of IDs. type IDRange struct { - // Min is the start of the range, inclusive. + // min is the start of the range, inclusive. Min int64 `json:"min" protobuf:"varint,1,opt,name=min"` - // Max is the end of the range, inclusive. + // max is the end of the range, inclusive. Max int64 `json:"max" protobuf:"varint,2,opt,name=max"` } @@ -301,21 +326,21 @@ type IDRange struct { type RunAsUserStrategy string const ( - // container must run as a particular uid. + // RunAsUserStrategyMustRunAs means that container must run as a particular uid. RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs" - // container must run as a non-root uid + // RunAsUserStrategyMustRunAsNonRoot means that container must run as a non-root uid. RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot" - // container may make requests for any uid. + // RunAsUserStrategyRunAsAny means that container may make requests for any uid. RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny" ) // FSGroupStrategyOptions defines the strategy type and options used to create the strategy. type FSGroupStrategyOptions struct { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. // +optional Rule FSGroupStrategyType `json:"rule,omitempty" protobuf:"bytes,1,opt,name=rule,casttype=FSGroupStrategyType"` - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. + // ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } @@ -325,19 +350,19 @@ type FSGroupStrategyOptions struct { type FSGroupStrategyType string const ( - // container must have FSGroup of X applied. + // FSGroupStrategyMustRunAs meant that container must have FSGroup of X applied. FSGroupStrategyMustRunAs FSGroupStrategyType = "MustRunAs" - // container may make requests for any FSGroup labels. + // FSGroupStrategyRunAsAny means that container may make requests for any FSGroup labels. FSGroupStrategyRunAsAny FSGroupStrategyType = "RunAsAny" ) // SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. type SupplementalGroupsStrategyOptions struct { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. // +optional Rule SupplementalGroupsStrategyType `json:"rule,omitempty" protobuf:"bytes,1,opt,name=rule,casttype=SupplementalGroupsStrategyType"` - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. + // ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } @@ -347,15 +372,15 @@ type SupplementalGroupsStrategyOptions struct { type SupplementalGroupsStrategyType string const ( - // container must run as a particular gid. + // SupplementalGroupsStrategyMustRunAs means that container must run as a particular gid. SupplementalGroupsStrategyMustRunAs SupplementalGroupsStrategyType = "MustRunAs" - // container may make requests for any gid. + // SupplementalGroupsStrategyRunAsAny means that container may make requests for any gid. SupplementalGroupsStrategyRunAsAny SupplementalGroupsStrategyType = "RunAsAny" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Pod Security Policy List is a list of PodSecurityPolicy objects. +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. type PodSecurityPolicyList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata. @@ -363,6 +388,6 @@ type PodSecurityPolicyList struct { // +optional metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` - // Items is a list of schema objects. + // items is a list of schema objects. Items []PodSecurityPolicy `json:"items" protobuf:"bytes,2,rep,name=items"` } diff --git a/vendor/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go index 8c51518d4..122287645 100644 --- a/vendor/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,10 +26,10 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AllowedFlexVolume = map[string]string{ "": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used.", - "driver": "Driver is the name of the Flexvolume driver.", + "driver": "driver is the name of the Flexvolume driver.", } func (AllowedFlexVolume) SwaggerDoc() map[string]string { @@ -37,8 +37,9 @@ func (AllowedFlexVolume) SwaggerDoc() map[string]string { } var map_AllowedHostPath = map[string]string{ - "": "defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", - "pathPrefix": "is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", + "pathPrefix": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "readOnly": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", } func (AllowedHostPath) SwaggerDoc() map[string]string { @@ -57,8 +58,8 @@ func (Eviction) SwaggerDoc() map[string]string { var map_FSGroupStrategyOptions = map[string]string{ "": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy.", - "rule": "Rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", - "ranges": "Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end.", + "rule": "rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", + "ranges": "ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs.", } func (FSGroupStrategyOptions) SwaggerDoc() map[string]string { @@ -66,7 +67,7 @@ func (FSGroupStrategyOptions) SwaggerDoc() map[string]string { } var map_HostPortRange = map[string]string{ - "": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", + "": "HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", "min": "min is the start of the range, inclusive.", "max": "max is the end of the range, inclusive.", } @@ -76,9 +77,9 @@ func (HostPortRange) SwaggerDoc() map[string]string { } var map_IDRange = map[string]string{ - "": "ID Range provides a min/max of an allowed range of IDs.", - "min": "Min is the start of the range, inclusive.", - "max": "Max is the end of the range, inclusive.", + "": "IDRange provides a min/max of an allowed range of IDs.", + "min": "min is the start of the range, inclusive.", + "max": "max is the end of the range, inclusive.", } func (IDRange) SwaggerDoc() map[string]string { @@ -129,7 +130,7 @@ func (PodDisruptionBudgetStatus) SwaggerDoc() map[string]string { } var map_PodSecurityPolicy = map[string]string{ - "": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", + "": "PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "spec": "spec defines the policy enforced.", } @@ -139,9 +140,9 @@ func (PodSecurityPolicy) SwaggerDoc() map[string]string { } var map_PodSecurityPolicyList = map[string]string{ - "": "Pod Security Policy List is a list of PodSecurityPolicy objects.", + "": "PodSecurityPolicyList is a list of PodSecurityPolicy objects.", "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "items": "Items is a list of schema objects.", + "items": "items is a list of schema objects.", } func (PodSecurityPolicyList) SwaggerDoc() map[string]string { @@ -149,25 +150,27 @@ func (PodSecurityPolicyList) SwaggerDoc() map[string]string { } var map_PodSecurityPolicySpec = map[string]string{ - "": "Pod Security Policy Spec defines the policy enforced.", + "": "PodSecurityPolicySpec defines the policy enforced.", "privileged": "privileged determines if a pod can request to be run as privileged.", - "defaultAddCapabilities": "DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list.", - "requiredDropCapabilities": "RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", - "allowedCapabilities": "AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities.", - "volumes": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.", + "defaultAddCapabilities": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.", + "requiredDropCapabilities": "requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", + "allowedCapabilities": "allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities.", + "volumes": "volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use '*'.", "hostNetwork": "hostNetwork determines if the policy allows the use of HostNetwork in the pod spec.", "hostPorts": "hostPorts determines which host port ranges are allowed to be exposed.", "hostPID": "hostPID determines if the policy allows the use of HostPID in the pod spec.", "hostIPC": "hostIPC determines if the policy allows the use of HostIPC in the pod spec.", "seLinux": "seLinux is the strategy that will dictate the allowable labels that may be set.", "runAsUser": "runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set.", - "supplementalGroups": "SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", - "fsGroup": "FSGroup is the strategy that will dictate what fs group is used by the SecurityContext.", - "readOnlyRootFilesystem": "ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", - "defaultAllowPrivilegeEscalation": "DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", - "allowPrivilegeEscalation": "AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", - "allowedHostPaths": "is a white list of allowed host paths. Empty indicates that all host paths may be used.", - "allowedFlexVolumes": "AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"Volumes\" field.", + "supplementalGroups": "supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", + "fsGroup": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.", + "readOnlyRootFilesystem": "readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", + "defaultAllowPrivilegeEscalation": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", + "allowPrivilegeEscalation": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", + "allowedHostPaths": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.", + "allowedFlexVolumes": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field.", + "allowedUnsafeSysctls": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "forbiddenSysctls": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", } func (PodSecurityPolicySpec) SwaggerDoc() map[string]string { @@ -175,9 +178,9 @@ func (PodSecurityPolicySpec) SwaggerDoc() map[string]string { } var map_RunAsUserStrategyOptions = map[string]string{ - "": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.", - "rule": "Rule is the strategy that will dictate the allowable RunAsUser values that may be set.", - "ranges": "Ranges are the allowed ranges of uids that may be used.", + "": "RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy.", + "rule": "rule is the strategy that will dictate the allowable RunAsUser values that may be set.", + "ranges": "ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs.", } func (RunAsUserStrategyOptions) SwaggerDoc() map[string]string { @@ -185,8 +188,8 @@ func (RunAsUserStrategyOptions) SwaggerDoc() map[string]string { } var map_SELinuxStrategyOptions = map[string]string{ - "": "SELinux Strategy Options defines the strategy type and any options used to create the strategy.", - "rule": "type is the strategy that will dictate the allowable labels that may be set.", + "": "SELinuxStrategyOptions defines the strategy type and any options used to create the strategy.", + "rule": "rule is the strategy that will dictate the allowable labels that may be set.", "seLinuxOptions": "seLinuxOptions required to run as; required for MustRunAs More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/", } @@ -196,8 +199,8 @@ func (SELinuxStrategyOptions) SwaggerDoc() map[string]string { var map_SupplementalGroupsStrategyOptions = map[string]string{ "": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy.", - "rule": "Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", - "ranges": "Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end.", + "rule": "rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", + "ranges": "ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs.", } func (SupplementalGroupsStrategyOptions) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go index 8a770b2f0..1980bd161 100644 --- a/vendor/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -394,6 +394,16 @@ func (in *PodSecurityPolicySpec) DeepCopyInto(out *PodSecurityPolicySpec) { *out = make([]AllowedFlexVolume, len(*in)) copy(*out, *in) } + if in.AllowedUnsafeSysctls != nil { + in, out := &in.AllowedUnsafeSysctls, &out.AllowedUnsafeSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ForbiddenSysctls != nil { + in, out := &in.ForbiddenSysctls, &out.ForbiddenSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/k8s.io/api/rbac/v1/generated.pb.go b/vendor/k8s.io/api/rbac/v1/generated.pb.go index 5343731cc..21010fbee 100644 --- a/vendor/k8s.io/api/rbac/v1/generated.pb.go +++ b/vendor/k8s.io/api/rbac/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2693,57 +2693,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 827 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x55, 0xcf, 0x8b, 0x23, 0x45, - 0x18, 0x4d, 0x65, 0x12, 0x26, 0x5d, 0x31, 0xc4, 0x2d, 0x17, 0x69, 0xa2, 0x74, 0x86, 0x16, 0x24, - 0xa0, 0x76, 0x9b, 0x5d, 0x51, 0x41, 0xf6, 0xb0, 0xbd, 0xa2, 0x0c, 0x3b, 0x8e, 0x4b, 0x2d, 0x7a, - 0x10, 0x0f, 0x56, 0x77, 0x6a, 0x3b, 0x65, 0xfa, 0x17, 0x55, 0xd5, 0x81, 0xc5, 0x8b, 0x08, 0x1e, - 0xbc, 0x79, 0xd4, 0xbf, 0xc0, 0x8b, 0x1e, 0xfd, 0x0b, 0xbc, 0xcc, 0x71, 0x8f, 0x7b, 0x0a, 0x4e, - 0xfb, 0x87, 0x28, 0xfd, 0x2b, 0x9d, 0xa4, 0x3b, 0x4e, 0x4e, 0x01, 0xf1, 0x34, 0x53, 0xdf, 0xf7, - 0xde, 0xfb, 0x5e, 0xbf, 0xa9, 0xaf, 0x06, 0x7e, 0xb0, 0x78, 0x5f, 0x18, 0x2c, 0x34, 0x17, 0xb1, - 0x4d, 0x79, 0x40, 0x25, 0x15, 0xe6, 0x92, 0x06, 0xb3, 0x90, 0x9b, 0x45, 0x83, 0x44, 0xcc, 0xe4, - 0x36, 0x71, 0xcc, 0xe5, 0xd4, 0x74, 0x69, 0x40, 0x39, 0x91, 0x74, 0x66, 0x44, 0x3c, 0x94, 0x21, - 0x42, 0x39, 0xc6, 0x20, 0x11, 0x33, 0x52, 0x8c, 0xb1, 0x9c, 0x8e, 0xde, 0x72, 0x99, 0x9c, 0xc7, - 0xb6, 0xe1, 0x84, 0xbe, 0xe9, 0x86, 0x6e, 0x68, 0x66, 0x50, 0x3b, 0x7e, 0x92, 0x9d, 0xb2, 0x43, - 0xf6, 0x5b, 0x2e, 0x31, 0x9a, 0xd4, 0xc7, 0x10, 0x2f, 0x9a, 0x93, 0xda, 0xb0, 0xd1, 0x3b, 0x15, - 0xd2, 0x27, 0xce, 0x9c, 0x05, 0x94, 0x3f, 0x35, 0xa3, 0x85, 0x9b, 0x16, 0x84, 0xe9, 0x53, 0x49, - 0x1a, 0x2c, 0x8e, 0xcc, 0x7d, 0x2c, 0x1e, 0x07, 0x92, 0xf9, 0xb4, 0x46, 0x78, 0xf7, 0x26, 0x82, - 0x70, 0xe6, 0xd4, 0x27, 0x35, 0xde, 0xdd, 0x7d, 0xbc, 0x58, 0x32, 0xcf, 0x64, 0x81, 0x14, 0x92, - 0xef, 0x92, 0xf4, 0x9f, 0x01, 0x1c, 0xde, 0x77, 0x5d, 0x4e, 0x5d, 0x22, 0x59, 0x18, 0xe0, 0xd8, - 0xa3, 0xe8, 0x7b, 0x00, 0x6f, 0x3b, 0x5e, 0x2c, 0x24, 0xe5, 0x38, 0xf4, 0xe8, 0x63, 0xea, 0x51, - 0x47, 0x86, 0x5c, 0xa8, 0xe0, 0xec, 0x64, 0xd2, 0xbf, 0x73, 0xd7, 0xa8, 0x42, 0x5f, 0x0f, 0x32, - 0xa2, 0x85, 0x9b, 0x16, 0x84, 0x91, 0xe6, 0x60, 0x2c, 0xa7, 0xc6, 0x05, 0xb1, 0xa9, 0x57, 0x72, - 0xad, 0x57, 0xaf, 0x56, 0xe3, 0x56, 0xb2, 0x1a, 0xdf, 0x7e, 0xd0, 0x20, 0x8c, 0x1b, 0xc7, 0xe9, - 0x3f, 0xb5, 0x61, 0x7f, 0x03, 0x8e, 0xbe, 0x82, 0xbd, 0x54, 0x7c, 0x46, 0x24, 0x51, 0xc1, 0x19, - 0x98, 0xf4, 0xef, 0xbc, 0x7d, 0x98, 0x95, 0x4f, 0xed, 0xaf, 0xa9, 0x23, 0x3f, 0xa1, 0x92, 0x58, - 0xa8, 0xf0, 0x01, 0xab, 0x1a, 0x5e, 0xab, 0xa2, 0x07, 0xb0, 0xcb, 0x63, 0x8f, 0x0a, 0xb5, 0x9d, - 0x7d, 0xa9, 0x66, 0xd4, 0xaf, 0x97, 0xf1, 0x28, 0xf4, 0x98, 0xf3, 0x34, 0x0d, 0xca, 0x1a, 0x14, - 0x62, 0xdd, 0xf4, 0x24, 0x70, 0xce, 0x45, 0x36, 0x1c, 0x92, 0xed, 0x44, 0xd5, 0x93, 0xcc, 0xed, - 0x6b, 0x4d, 0x72, 0x3b, 0xe1, 0x5b, 0x2f, 0x25, 0xab, 0xf1, 0xee, 0x5f, 0x04, 0xef, 0x0a, 0xea, - 0x3f, 0xb4, 0x21, 0xda, 0x88, 0xc6, 0x62, 0xc1, 0x8c, 0x05, 0xee, 0x11, 0x12, 0x3a, 0x87, 0x3d, - 0x11, 0x67, 0x8d, 0x32, 0xa4, 0x57, 0x9a, 0xbe, 0xea, 0x71, 0x8e, 0xb1, 0x5e, 0x2c, 0xc4, 0x7a, - 0x45, 0x41, 0xe0, 0x35, 0x1d, 0x7d, 0x04, 0x4f, 0x79, 0xe8, 0x51, 0x4c, 0x9f, 0x14, 0xf9, 0x34, - 0x2a, 0xe1, 0x1c, 0x62, 0x0d, 0x0b, 0xa5, 0xd3, 0xa2, 0x80, 0x4b, 0xb2, 0xfe, 0x07, 0x80, 0x2f, - 0xd7, 0xb3, 0xb8, 0x60, 0x42, 0xa2, 0x2f, 0x6b, 0x79, 0x18, 0x07, 0x5e, 0x5e, 0x26, 0xf2, 0x34, - 0xd6, 0x1f, 0x50, 0x56, 0x36, 0xb2, 0x78, 0x08, 0xbb, 0x4c, 0x52, 0xbf, 0x0c, 0xe2, 0xf5, 0x26, - 0xfb, 0x75, 0x63, 0xd5, 0xad, 0x39, 0x4f, 0xc9, 0x38, 0xd7, 0xd0, 0x7f, 0x07, 0x70, 0xb8, 0x01, - 0x3e, 0x82, 0xfd, 0x0f, 0xb7, 0xed, 0x8f, 0x6f, 0xb2, 0xdf, 0xec, 0xfb, 0x6f, 0x00, 0x61, 0xb5, - 0x12, 0x68, 0x0c, 0xbb, 0x4b, 0xca, 0xed, 0xfc, 0xad, 0x50, 0x2c, 0x25, 0xc5, 0x7f, 0x9e, 0x16, - 0x70, 0x5e, 0x47, 0x6f, 0x40, 0x85, 0x44, 0xec, 0x63, 0x1e, 0xc6, 0x51, 0x3e, 0x59, 0xb1, 0x06, - 0xc9, 0x6a, 0xac, 0xdc, 0x7f, 0x74, 0x9e, 0x17, 0x71, 0xd5, 0x4f, 0xc1, 0x9c, 0x8a, 0x30, 0xe6, - 0x0e, 0x15, 0xea, 0x49, 0x05, 0xc6, 0x65, 0x11, 0x57, 0x7d, 0xf4, 0x1e, 0x1c, 0x94, 0x87, 0x4b, - 0xe2, 0x53, 0xa1, 0x76, 0x32, 0xc2, 0xad, 0x64, 0x35, 0x1e, 0xe0, 0xcd, 0x06, 0xde, 0xc6, 0xa1, - 0x7b, 0x70, 0x18, 0x84, 0x41, 0x09, 0xf9, 0x0c, 0x5f, 0x08, 0xb5, 0x9b, 0x51, 0xb3, 0x5d, 0xbc, - 0xdc, 0x6e, 0xe1, 0x5d, 0xac, 0xfe, 0x1b, 0x80, 0x9d, 0xff, 0xd0, 0xfb, 0xa4, 0x7f, 0xd7, 0x86, - 0xfd, 0xff, 0xfd, 0xa3, 0x91, 0xae, 0xdb, 0x71, 0x5f, 0x8b, 0x43, 0xd6, 0xed, 0xe6, 0x67, 0xe2, - 0x17, 0x00, 0x7b, 0x47, 0x7a, 0x1f, 0xee, 0x6d, 0x1b, 0x56, 0xf7, 0x1a, 0x6e, 0x76, 0xfa, 0x0d, - 0x2c, 0x53, 0x47, 0x6f, 0xc2, 0x5e, 0xb9, 0xd3, 0x99, 0x4f, 0xa5, 0x9a, 0x5b, 0xae, 0x3d, 0x5e, - 0x23, 0xd0, 0x19, 0xec, 0x2c, 0x58, 0x30, 0x53, 0xdb, 0x19, 0xf2, 0x85, 0x02, 0xd9, 0x79, 0xc8, - 0x82, 0x19, 0xce, 0x3a, 0x29, 0x22, 0x20, 0x7e, 0xfe, 0x6f, 0x75, 0x03, 0x91, 0x6e, 0x33, 0xce, - 0x3a, 0xfa, 0xaf, 0x00, 0x9e, 0x16, 0xb7, 0x67, 0xad, 0x07, 0xf6, 0xea, 0x6d, 0xfa, 0x6b, 0x1f, - 0xe2, 0xef, 0xdf, 0xa7, 0x23, 0x13, 0x2a, 0xe9, 0x4f, 0x11, 0x11, 0x87, 0xaa, 0x9d, 0x0c, 0x76, - 0xab, 0x80, 0x29, 0x97, 0x65, 0x03, 0x57, 0x18, 0x6b, 0x72, 0x75, 0xad, 0xb5, 0x9e, 0x5d, 0x6b, - 0xad, 0xe7, 0xd7, 0x5a, 0xeb, 0xdb, 0x44, 0x03, 0x57, 0x89, 0x06, 0x9e, 0x25, 0x1a, 0x78, 0x9e, - 0x68, 0xe0, 0xcf, 0x44, 0x03, 0x3f, 0xfe, 0xa5, 0xb5, 0xbe, 0x68, 0x2f, 0xa7, 0xff, 0x04, 0x00, - 0x00, 0xff, 0xff, 0x32, 0xe3, 0x23, 0xf8, 0x2e, 0x0b, 0x00, 0x00, + // 807 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x55, 0xcf, 0x6f, 0xe3, 0x44, + 0x14, 0xce, 0xa4, 0x89, 0x1a, 0x4f, 0x88, 0x42, 0x87, 0x0a, 0x59, 0x05, 0x39, 0x95, 0x91, 0x50, + 0x25, 0xc0, 0x26, 0x05, 0x01, 0x12, 0xea, 0xa1, 0x2e, 0x02, 0x55, 0x2d, 0xa5, 0x9a, 0x0a, 0x0e, + 0x88, 0x03, 0x63, 0x67, 0xea, 0x0e, 0xf1, 0x2f, 0xcd, 0xd8, 0x91, 0x2a, 0x2e, 0x08, 0x89, 0x03, + 0xb7, 0x3d, 0xee, 0xfe, 0x05, 0x7b, 0xd9, 0x3d, 0xee, 0x5f, 0xb0, 0x97, 0x1e, 0x7b, 0xec, 0x29, + 0xda, 0x7a, 0xff, 0x90, 0x5d, 0xf9, 0x57, 0x9c, 0x1f, 0xee, 0x36, 0xa7, 0x48, 0xab, 0x3d, 0xb5, + 0xf3, 0xde, 0xf7, 0xbe, 0xf7, 0xcd, 0xe7, 0x79, 0x2f, 0xf0, 0xfb, 0xe1, 0x77, 0x42, 0x63, 0xbe, + 0x3e, 0x8c, 0x4c, 0xca, 0x3d, 0x1a, 0x52, 0xa1, 0x8f, 0xa8, 0x37, 0xf0, 0xb9, 0x9e, 0x27, 0x48, + 0xc0, 0x74, 0x6e, 0x12, 0x4b, 0x1f, 0xf5, 0x75, 0x9b, 0x7a, 0x94, 0x93, 0x90, 0x0e, 0xb4, 0x80, + 0xfb, 0xa1, 0x8f, 0x50, 0x86, 0xd1, 0x48, 0xc0, 0xb4, 0x04, 0xa3, 0x8d, 0xfa, 0x5b, 0x5f, 0xd8, + 0x2c, 0xbc, 0x88, 0x4c, 0xcd, 0xf2, 0x5d, 0xdd, 0xf6, 0x6d, 0x5f, 0x4f, 0xa1, 0x66, 0x74, 0x9e, + 0x9e, 0xd2, 0x43, 0xfa, 0x5f, 0x46, 0xb1, 0xf5, 0x75, 0xd9, 0xc6, 0x25, 0xd6, 0x05, 0xf3, 0x28, + 0xbf, 0xd4, 0x83, 0xa1, 0x9d, 0x04, 0x84, 0xee, 0xd2, 0x90, 0x54, 0x34, 0xde, 0xd2, 0xef, 0xaa, + 0xe2, 0x91, 0x17, 0x32, 0x97, 0x2e, 0x14, 0x7c, 0x73, 0x5f, 0x81, 0xb0, 0x2e, 0xa8, 0x4b, 0xe6, + 0xeb, 0xd4, 0x47, 0x00, 0x76, 0xf7, 0x6d, 0x9b, 0x53, 0x9b, 0x84, 0xcc, 0xf7, 0x70, 0xe4, 0x50, + 0xf4, 0x1f, 0x80, 0x9b, 0x96, 0x13, 0x89, 0x90, 0x72, 0xec, 0x3b, 0xf4, 0x8c, 0x3a, 0xd4, 0x0a, + 0x7d, 0x2e, 0x64, 0xb0, 0xbd, 0xb6, 0xd3, 0xde, 0xfd, 0x4a, 0x2b, 0x5d, 0x99, 0xf4, 0xd2, 0x82, + 0xa1, 0x9d, 0x04, 0x84, 0x96, 0x5c, 0x49, 0x1b, 0xf5, 0xb5, 0x63, 0x62, 0x52, 0xa7, 0xa8, 0x35, + 0x3e, 0xbe, 0x1a, 0xf7, 0x6a, 0xf1, 0xb8, 0xb7, 0x79, 0x50, 0x41, 0x8c, 0x2b, 0xdb, 0xa9, 0x0f, + 0xeb, 0xb0, 0x3d, 0x05, 0x47, 0x7f, 0xc2, 0x56, 0x42, 0x3e, 0x20, 0x21, 0x91, 0xc1, 0x36, 0xd8, + 0x69, 0xef, 0x7e, 0xb9, 0x9c, 0x94, 0x5f, 0xcc, 0xbf, 0xa8, 0x15, 0xfe, 0x4c, 0x43, 0x62, 0xa0, + 0x5c, 0x07, 0x2c, 0x63, 0x78, 0xc2, 0x8a, 0x0e, 0x60, 0x93, 0x47, 0x0e, 0x15, 0x72, 0x3d, 0xbd, + 0xa9, 0xa2, 0x2d, 0x7e, 0x7f, 0xed, 0xd4, 0x77, 0x98, 0x75, 0x99, 0x18, 0x65, 0x74, 0x72, 0xb2, + 0x66, 0x72, 0x12, 0x38, 0xab, 0x45, 0x26, 0xec, 0x92, 0x59, 0x47, 0xe5, 0xb5, 0x54, 0xed, 0x27, + 0x55, 0x74, 0x73, 0xe6, 0x1b, 0x1f, 0xc4, 0xe3, 0xde, 0xfc, 0x17, 0xc1, 0xf3, 0x84, 0xea, 0xff, + 0x75, 0x88, 0xa6, 0xac, 0x31, 0x98, 0x37, 0x60, 0x9e, 0xbd, 0x02, 0x87, 0x0e, 0x61, 0x4b, 0x44, + 0x69, 0xa2, 0x30, 0xe9, 0xa3, 0xaa, 0x5b, 0x9d, 0x65, 0x18, 0xe3, 0xfd, 0x9c, 0xac, 0x95, 0x07, + 0x04, 0x9e, 0x94, 0xa3, 0x1f, 0xe1, 0x3a, 0xf7, 0x1d, 0x8a, 0xe9, 0x79, 0xee, 0x4f, 0x25, 0x13, + 0xce, 0x20, 0x46, 0x37, 0x67, 0x5a, 0xcf, 0x03, 0xb8, 0x28, 0x56, 0x9f, 0x03, 0xf8, 0xe1, 0xa2, + 0x17, 0xc7, 0x4c, 0x84, 0xe8, 0x8f, 0x05, 0x3f, 0xb4, 0x25, 0x1f, 0x2f, 0x13, 0x99, 0x1b, 0x93, + 0x0b, 0x14, 0x91, 0x29, 0x2f, 0x8e, 0x60, 0x93, 0x85, 0xd4, 0x2d, 0x8c, 0xf8, 0xb4, 0x4a, 0xfe, + 0xa2, 0xb0, 0xf2, 0xd5, 0x1c, 0x26, 0xc5, 0x38, 0xe3, 0x50, 0x9f, 0x01, 0xd8, 0x9d, 0x02, 0xaf, + 0x40, 0xfe, 0x0f, 0xb3, 0xf2, 0x7b, 0xf7, 0xc9, 0xaf, 0xd6, 0xfd, 0x0a, 0x40, 0x58, 0x8e, 0x04, + 0xea, 0xc1, 0xe6, 0x88, 0x72, 0x33, 0xdb, 0x15, 0x92, 0x21, 0x25, 0xf8, 0xdf, 0x92, 0x00, 0xce, + 0xe2, 0xe8, 0x33, 0x28, 0x91, 0x80, 0xfd, 0xc4, 0xfd, 0x28, 0xc8, 0x3a, 0x4b, 0x46, 0x27, 0x1e, + 0xf7, 0xa4, 0xfd, 0xd3, 0xc3, 0x2c, 0x88, 0xcb, 0x7c, 0x02, 0xe6, 0x54, 0xf8, 0x11, 0xb7, 0xa8, + 0x90, 0xd7, 0x4a, 0x30, 0x2e, 0x82, 0xb8, 0xcc, 0xa3, 0x6f, 0x61, 0xa7, 0x38, 0x9c, 0x10, 0x97, + 0x0a, 0xb9, 0x91, 0x16, 0x6c, 0xc4, 0xe3, 0x5e, 0x07, 0x4f, 0x27, 0xf0, 0x2c, 0x0e, 0xed, 0xc1, + 0xae, 0xe7, 0x7b, 0x05, 0xe4, 0x57, 0x7c, 0x2c, 0xe4, 0x66, 0x5a, 0x9a, 0xce, 0xe2, 0xc9, 0x6c, + 0x0a, 0xcf, 0x63, 0xd5, 0xa7, 0x00, 0x36, 0xde, 0xa2, 0xfd, 0xa4, 0xfe, 0x5b, 0x87, 0xed, 0x77, + 0x7e, 0x69, 0x24, 0xe3, 0xb6, 0xda, 0x6d, 0xb1, 0xcc, 0xb8, 0xdd, 0xbf, 0x26, 0x1e, 0x03, 0xd8, + 0x5a, 0xd1, 0x7e, 0xd8, 0x9b, 0x15, 0x2c, 0xdf, 0x29, 0xb8, 0x5a, 0xe9, 0xdf, 0xb0, 0x70, 0x1d, + 0x7d, 0x0e, 0x5b, 0xc5, 0x4c, 0xa7, 0x3a, 0xa5, 0xb2, 0x6f, 0x31, 0xf6, 0x78, 0x82, 0x40, 0xdb, + 0xb0, 0x31, 0x64, 0xde, 0x40, 0xae, 0xa7, 0xc8, 0xf7, 0x72, 0x64, 0xe3, 0x88, 0x79, 0x03, 0x9c, + 0x66, 0x12, 0x84, 0x47, 0xdc, 0xec, 0x67, 0x75, 0x0a, 0x91, 0x4c, 0x33, 0x4e, 0x33, 0xea, 0x13, + 0x00, 0xd7, 0xf3, 0xd7, 0x33, 0xe1, 0x03, 0x77, 0xf2, 0x4d, 0xeb, 0xab, 0x2f, 0xa3, 0xef, 0xcd, + 0xdd, 0x91, 0x0e, 0xa5, 0xe4, 0xaf, 0x08, 0x88, 0x45, 0xe5, 0x46, 0x0a, 0xdb, 0xc8, 0x61, 0xd2, + 0x49, 0x91, 0xc0, 0x25, 0xc6, 0xd8, 0xb9, 0xba, 0x55, 0x6a, 0xd7, 0xb7, 0x4a, 0xed, 0xe6, 0x56, + 0xa9, 0xfd, 0x13, 0x2b, 0xe0, 0x2a, 0x56, 0xc0, 0x75, 0xac, 0x80, 0x9b, 0x58, 0x01, 0x2f, 0x62, + 0x05, 0x3c, 0x78, 0xa9, 0xd4, 0x7e, 0xaf, 0x8f, 0xfa, 0xaf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x24, + 0xa1, 0x47, 0x98, 0xcf, 0x0a, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/rbac/v1/generated.proto b/vendor/k8s.io/api/rbac/v1/generated.proto index 2f8d863df..4b321a7c2 100644 --- a/vendor/k8s.io/api/rbac/v1/generated.proto +++ b/vendor/k8s.io/api/rbac/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,11 +21,9 @@ syntax = 'proto2'; package k8s.io.api.rbac.v1; -import "k8s.io/api/rbac/v1alpha1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; @@ -62,6 +60,7 @@ message ClusterRoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can only reference a ClusterRole in the global namespace. @@ -134,6 +133,7 @@ message RoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. diff --git a/vendor/k8s.io/api/rbac/v1/types.go b/vendor/k8s.io/api/rbac/v1/types.go index 91990548b..17163cbb2 100644 --- a/vendor/k8s.io/api/rbac/v1/types.go +++ b/vendor/k8s.io/api/rbac/v1/types.go @@ -124,7 +124,8 @@ type RoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. @@ -199,7 +200,8 @@ type ClusterRoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can only reference a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. diff --git a/vendor/k8s.io/api/rbac/v1/types_swagger_doc_generated.go b/vendor/k8s.io/api/rbac/v1/types_swagger_doc_generated.go index 280ae5a82..0ec20c88e 100644 --- a/vendor/k8s.io/api/rbac/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/rbac/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AggregationRule = map[string]string{ "": "AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole", "clusterRoleSelectors": "ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. If any of the selectors match, then the ClusterRole's permissions will be added", diff --git a/vendor/k8s.io/api/rbac/v1/zz_generated.deepcopy.go b/vendor/k8s.io/api/rbac/v1/zz_generated.deepcopy.go index 0a2a4d08e..be1592f77 100644 --- a/vendor/k8s.io/api/rbac/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/rbac/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/rbac/v1alpha1/generated.pb.go b/vendor/k8s.io/api/rbac/v1alpha1/generated.pb.go index c07cdc75d..71eced8d4 100644 --- a/vendor/k8s.io/api/rbac/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/api/rbac/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2693,58 +2693,57 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 844 bytes of a gzipped FileDescriptorProto + // 830 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x55, 0xbf, 0x8f, 0xe3, 0x44, - 0x14, 0xce, 0x64, 0x13, 0x36, 0x99, 0x65, 0x15, 0x6e, 0x38, 0x21, 0x6b, 0x85, 0x9c, 0xc5, 0x02, - 0xe9, 0x10, 0x87, 0xcd, 0xee, 0x21, 0xa0, 0xa1, 0x58, 0x5f, 0x81, 0x16, 0x96, 0xbd, 0x65, 0x4e, - 0x5c, 0x81, 0x28, 0x98, 0x38, 0x73, 0xce, 0x10, 0xdb, 0x63, 0xcd, 0x8c, 0x23, 0x9d, 0x68, 0x68, - 0x68, 0x11, 0x0d, 0x05, 0x3d, 0x2d, 0x0d, 0x94, 0xfc, 0x03, 0x4b, 0x77, 0xe5, 0x56, 0x11, 0x6b, - 0xfe, 0x10, 0x90, 0xc7, 0x76, 0xec, 0xfc, 0x22, 0xa9, 0x22, 0x21, 0x51, 0x25, 0xf3, 0xde, 0xf7, - 0xbe, 0xf7, 0xde, 0x37, 0xf3, 0x9e, 0xe1, 0xd9, 0xf8, 0x03, 0x69, 0x33, 0xee, 0x8c, 0x93, 0x01, - 0x15, 0x11, 0x55, 0x54, 0x3a, 0x13, 0x1a, 0x0d, 0xb9, 0x70, 0x0a, 0x07, 0x89, 0x99, 0x23, 0x06, - 0xc4, 0x73, 0x26, 0x27, 0x24, 0x88, 0x47, 0xe4, 0xc4, 0xf1, 0x69, 0x44, 0x05, 0x51, 0x74, 0x68, - 0xc7, 0x82, 0x2b, 0x8e, 0x8c, 0x1c, 0x69, 0x93, 0x98, 0xd9, 0x19, 0xd2, 0x2e, 0x91, 0x47, 0x6f, - 0xfb, 0x4c, 0x8d, 0x92, 0x81, 0xed, 0xf1, 0xd0, 0xf1, 0xb9, 0xcf, 0x1d, 0x1d, 0x30, 0x48, 0x9e, - 0xea, 0x93, 0x3e, 0xe8, 0x7f, 0x39, 0xd1, 0xd1, 0xbb, 0x55, 0xca, 0x90, 0x78, 0x23, 0x16, 0x51, - 0xf1, 0xcc, 0x89, 0xc7, 0x7e, 0x66, 0x90, 0x4e, 0x48, 0x15, 0x71, 0x26, 0x4b, 0xe9, 0x8f, 0x9c, - 0x75, 0x51, 0x22, 0x89, 0x14, 0x0b, 0xe9, 0x52, 0xc0, 0x7b, 0x9b, 0x02, 0xa4, 0x37, 0xa2, 0x21, - 0x59, 0x8a, 0x7b, 0xb0, 0x2e, 0x2e, 0x51, 0x2c, 0x70, 0x58, 0xa4, 0xa4, 0x12, 0x8b, 0x41, 0xd6, - 0x4f, 0x00, 0xf6, 0xce, 0x7c, 0x5f, 0x50, 0x9f, 0x28, 0xc6, 0x23, 0x9c, 0x04, 0x14, 0x7d, 0x07, - 0xe0, 0x5d, 0x2f, 0x48, 0xa4, 0xa2, 0x02, 0xf3, 0x80, 0x3e, 0xa6, 0x01, 0xf5, 0x14, 0x17, 0xd2, - 0x00, 0xc7, 0x7b, 0xf7, 0x0e, 0x4e, 0x1f, 0xd8, 0x95, 0xa0, 0xb3, 0x44, 0x76, 0x3c, 0xf6, 0x33, - 0x83, 0xb4, 0x33, 0x1d, 0xec, 0xc9, 0x89, 0x7d, 0x41, 0x06, 0x34, 0x28, 0x63, 0xdd, 0x57, 0xaf, - 0xa7, 0xfd, 0x46, 0x3a, 0xed, 0xdf, 0x7d, 0xb8, 0x82, 0x18, 0xaf, 0x4c, 0x67, 0xfd, 0xdc, 0x84, - 0x07, 0x35, 0x38, 0xfa, 0x0a, 0x76, 0x32, 0xf2, 0x21, 0x51, 0xc4, 0x00, 0xc7, 0xe0, 0xde, 0xc1, - 0xe9, 0x3b, 0xdb, 0x95, 0xf2, 0x68, 0xf0, 0x35, 0xf5, 0xd4, 0xa7, 0x54, 0x11, 0x17, 0x15, 0x75, - 0xc0, 0xca, 0x86, 0x67, 0xac, 0xe8, 0x1c, 0xb6, 0x45, 0x12, 0x50, 0x69, 0x34, 0x75, 0xa7, 0xaf, - 0xdb, 0xeb, 0x9e, 0x8e, 0x7d, 0xc5, 0x03, 0xe6, 0x3d, 0xcb, 0xe4, 0x72, 0x0f, 0x0b, 0xca, 0x76, - 0x76, 0x92, 0x38, 0x67, 0x40, 0x23, 0xd8, 0x23, 0xf3, 0xba, 0x1a, 0x7b, 0xba, 0xe6, 0x37, 0xd7, - 0x93, 0x2e, 0x5c, 0x84, 0xfb, 0x72, 0x3a, 0xed, 0x2f, 0xde, 0x0e, 0x5e, 0xa4, 0xb5, 0x7e, 0x6c, - 0x42, 0x54, 0x93, 0xc9, 0x65, 0xd1, 0x90, 0x45, 0xfe, 0x0e, 0xd4, 0x7a, 0x04, 0x3b, 0x32, 0xd1, - 0x8e, 0x52, 0xb0, 0xd7, 0xd6, 0xf7, 0xf6, 0x38, 0x47, 0xba, 0x2f, 0x15, 0x94, 0x9d, 0xc2, 0x20, - 0xf1, 0x8c, 0x04, 0x5d, 0xc0, 0x7d, 0xc1, 0x03, 0x8a, 0xe9, 0xd3, 0x42, 0xab, 0x7f, 0xe1, 0xc3, - 0x39, 0xd0, 0xed, 0x15, 0x7c, 0xfb, 0x85, 0x01, 0x97, 0x14, 0xd6, 0x1f, 0x00, 0xbe, 0xb2, 0xac, - 0xcb, 0x05, 0x93, 0x0a, 0x7d, 0xb9, 0xa4, 0x8d, 0xbd, 0xe5, 0xa3, 0x66, 0x32, 0x57, 0x66, 0xd6, - 0x46, 0x69, 0xa9, 0xe9, 0xf2, 0x19, 0x6c, 0x33, 0x45, 0xc3, 0x52, 0x94, 0xfb, 0xeb, 0x9b, 0x58, - 0x2e, 0xaf, 0x7a, 0x4d, 0xe7, 0x19, 0x05, 0xce, 0x99, 0xac, 0xdf, 0x01, 0xec, 0xd5, 0xc0, 0x3b, - 0x68, 0xe2, 0xe3, 0xf9, 0x26, 0xde, 0xd8, 0xae, 0x89, 0xd5, 0xd5, 0xff, 0x0d, 0x20, 0xac, 0x06, - 0x06, 0xf5, 0x61, 0x7b, 0x42, 0xc5, 0x20, 0xdf, 0x27, 0x5d, 0xb7, 0x9b, 0xe1, 0x9f, 0x64, 0x06, - 0x9c, 0xdb, 0xd1, 0x5b, 0xb0, 0x4b, 0x62, 0xf6, 0x91, 0xe0, 0x49, 0x2c, 0x8d, 0x3d, 0x0d, 0x3a, - 0x4c, 0xa7, 0xfd, 0xee, 0xd9, 0xd5, 0x79, 0x6e, 0xc4, 0x95, 0x3f, 0x03, 0x0b, 0x2a, 0x79, 0x22, - 0x3c, 0x2a, 0x8d, 0x56, 0x05, 0xc6, 0xa5, 0x11, 0x57, 0x7e, 0xf4, 0x3e, 0x3c, 0x2c, 0x0f, 0x97, - 0x24, 0xa4, 0xd2, 0x68, 0xeb, 0x80, 0x3b, 0xe9, 0xb4, 0x7f, 0x88, 0xeb, 0x0e, 0x3c, 0x8f, 0x43, - 0x1f, 0xc2, 0x5e, 0xc4, 0xa3, 0x12, 0xf2, 0x39, 0xbe, 0x90, 0xc6, 0x0b, 0x3a, 0x54, 0xcf, 0xe8, - 0xe5, 0xbc, 0x0b, 0x2f, 0x62, 0xad, 0xdf, 0x00, 0x6c, 0xfd, 0xe7, 0x76, 0x98, 0xf5, 0x7d, 0x13, - 0x1e, 0xfc, 0xbf, 0x52, 0x6a, 0x2b, 0x25, 0x1b, 0xc3, 0xdd, 0xee, 0x92, 0xed, 0xc7, 0x70, 0xf3, - 0x12, 0xf9, 0x05, 0xc0, 0xce, 0x8e, 0xb6, 0xc7, 0xc3, 0xf9, 0xb2, 0xcd, 0x0d, 0x65, 0xaf, 0xae, - 0xf7, 0x1b, 0x58, 0xde, 0x00, 0xba, 0x0f, 0x3b, 0xe5, 0xc4, 0xeb, 0x6a, 0xbb, 0x55, 0xf6, 0x72, - 0x29, 0xe0, 0x19, 0x02, 0x1d, 0xc3, 0xd6, 0x98, 0x45, 0x43, 0xa3, 0xa9, 0x91, 0x2f, 0x16, 0xc8, - 0xd6, 0x27, 0x2c, 0x1a, 0x62, 0xed, 0xc9, 0x10, 0x11, 0x09, 0xf3, 0x4f, 0x72, 0x0d, 0x91, 0xcd, - 0x3a, 0xd6, 0x1e, 0xeb, 0x57, 0x00, 0xf7, 0x8b, 0xf7, 0x34, 0xe3, 0x03, 0x6b, 0xf9, 0x4e, 0x21, - 0x24, 0x31, 0x7b, 0x42, 0x85, 0x64, 0x3c, 0x2a, 0xf2, 0xce, 0x5e, 0xfa, 0xd9, 0xd5, 0x79, 0xe1, - 0xc1, 0x35, 0xd4, 0xe6, 0x1a, 0x90, 0x03, 0xbb, 0xd9, 0xaf, 0x8c, 0x89, 0x47, 0x8d, 0x96, 0x86, - 0xdd, 0x29, 0x60, 0xdd, 0xcb, 0xd2, 0x81, 0x2b, 0x8c, 0x6b, 0x5f, 0xdf, 0x9a, 0x8d, 0xe7, 0xb7, - 0x66, 0xe3, 0xe6, 0xd6, 0x6c, 0x7c, 0x9b, 0x9a, 0xe0, 0x3a, 0x35, 0xc1, 0xf3, 0xd4, 0x04, 0x37, - 0xa9, 0x09, 0xfe, 0x4c, 0x4d, 0xf0, 0xc3, 0x5f, 0x66, 0xe3, 0x8b, 0x4e, 0x29, 0xfe, 0x3f, 0x01, - 0x00, 0x00, 0xff, 0xff, 0xeb, 0xcc, 0xe2, 0x61, 0x5e, 0x0b, 0x00, 0x00, + 0x14, 0xce, 0x64, 0x13, 0x36, 0x99, 0x25, 0x0a, 0x37, 0x9c, 0x90, 0xb5, 0x42, 0xce, 0x62, 0x81, + 0x74, 0x88, 0xc3, 0x66, 0x17, 0x04, 0x34, 0x14, 0xf1, 0x15, 0x28, 0x10, 0xf6, 0x96, 0x39, 0x71, + 0x05, 0xa2, 0x60, 0xe2, 0xcc, 0x39, 0x43, 0x6c, 0x8f, 0x35, 0x63, 0x47, 0x3a, 0xd1, 0xd0, 0xd0, + 0x22, 0x1a, 0x0a, 0x7a, 0x5a, 0x1a, 0x28, 0xf9, 0x07, 0x96, 0xee, 0xca, 0xad, 0x22, 0xd6, 0xfc, + 0x21, 0x20, 0x8f, 0xed, 0xd8, 0xf9, 0x45, 0x52, 0x45, 0x42, 0xba, 0x2a, 0x99, 0xf7, 0xbe, 0xf7, + 0xbd, 0xf7, 0xbe, 0x99, 0xf7, 0x0c, 0xfb, 0xd3, 0x0f, 0xa5, 0xc9, 0xb8, 0x35, 0x8d, 0x47, 0x54, + 0x04, 0x34, 0xa2, 0xd2, 0x9a, 0xd1, 0x60, 0xcc, 0x85, 0x95, 0x3b, 0x48, 0xc8, 0x2c, 0x31, 0x22, + 0x8e, 0x35, 0x3b, 0x27, 0x5e, 0x38, 0x21, 0xe7, 0x96, 0x4b, 0x03, 0x2a, 0x48, 0x44, 0xc7, 0x66, + 0x28, 0x78, 0xc4, 0x91, 0x96, 0x21, 0x4d, 0x12, 0x32, 0x33, 0x45, 0x9a, 0x05, 0xf2, 0xf4, 0x6d, + 0x97, 0x45, 0x93, 0x78, 0x64, 0x3a, 0xdc, 0xb7, 0x5c, 0xee, 0x72, 0x4b, 0x05, 0x8c, 0xe2, 0x27, + 0xea, 0xa4, 0x0e, 0xea, 0x5f, 0x46, 0x74, 0xfa, 0x5e, 0x99, 0xd2, 0x27, 0xce, 0x84, 0x05, 0x54, + 0x3c, 0xb5, 0xc2, 0xa9, 0x9b, 0x1a, 0xa4, 0xe5, 0xd3, 0x88, 0x58, 0xb3, 0xb5, 0xf4, 0xa7, 0xd6, + 0xb6, 0x28, 0x11, 0x07, 0x11, 0xf3, 0xe9, 0x5a, 0xc0, 0xfb, 0xbb, 0x02, 0xa4, 0x33, 0xa1, 0x3e, + 0x59, 0x8d, 0x33, 0x7e, 0x06, 0xb0, 0xdb, 0x77, 0x5d, 0x41, 0x5d, 0x12, 0x31, 0x1e, 0xe0, 0xd8, + 0xa3, 0xe8, 0x7b, 0x00, 0xef, 0x3a, 0x5e, 0x2c, 0x23, 0x2a, 0x30, 0xf7, 0xe8, 0x23, 0xea, 0x51, + 0x27, 0xe2, 0x42, 0x6a, 0xe0, 0xec, 0xe8, 0xde, 0xc9, 0xc5, 0xbb, 0x66, 0xa9, 0xcd, 0x22, 0x97, + 0x19, 0x4e, 0xdd, 0xd4, 0x20, 0xcd, 0xb4, 0x25, 0x73, 0x76, 0x6e, 0x0e, 0xc9, 0x88, 0x7a, 0x45, + 0xac, 0xfd, 0xea, 0xf5, 0xbc, 0x57, 0x4b, 0xe6, 0xbd, 0xbb, 0x0f, 0x36, 0x10, 0xe3, 0x8d, 0xe9, + 0x8c, 0x5f, 0xea, 0xf0, 0xa4, 0x02, 0x47, 0x5f, 0xc3, 0x56, 0x4a, 0x3e, 0x26, 0x11, 0xd1, 0xc0, + 0x19, 0xb8, 0x77, 0x72, 0xf1, 0xce, 0x7e, 0xa5, 0x3c, 0x1c, 0x7d, 0x43, 0x9d, 0xe8, 0x33, 0x1a, + 0x11, 0x1b, 0xe5, 0x75, 0xc0, 0xd2, 0x86, 0x17, 0xac, 0x68, 0x00, 0x9b, 0x22, 0xf6, 0xa8, 0xd4, + 0xea, 0xaa, 0xd3, 0xd7, 0xcd, 0x6d, 0xaf, 0xc0, 0xbc, 0xe2, 0x1e, 0x73, 0x9e, 0xa6, 0x72, 0xd9, + 0x9d, 0x9c, 0xb2, 0x99, 0x9e, 0x24, 0xce, 0x18, 0xd0, 0x04, 0x76, 0xc9, 0xb2, 0xae, 0xda, 0x91, + 0xaa, 0xf9, 0xcd, 0xed, 0xa4, 0x2b, 0x17, 0x61, 0xbf, 0x9c, 0xcc, 0x7b, 0xab, 0xb7, 0x83, 0x57, + 0x69, 0x8d, 0x9f, 0xea, 0x10, 0x55, 0x64, 0xb2, 0x59, 0x30, 0x66, 0x81, 0x7b, 0x00, 0xb5, 0x1e, + 0xc2, 0x96, 0x8c, 0x95, 0xa3, 0x10, 0xec, 0xb5, 0xed, 0xbd, 0x3d, 0xca, 0x90, 0xf6, 0x4b, 0x39, + 0x65, 0x2b, 0x37, 0x48, 0xbc, 0x20, 0x41, 0x43, 0x78, 0x2c, 0xb8, 0x47, 0x31, 0x7d, 0x92, 0x6b, + 0xf5, 0x1f, 0x7c, 0x38, 0x03, 0xda, 0xdd, 0x9c, 0xef, 0x38, 0x37, 0xe0, 0x82, 0xc2, 0xf8, 0x13, + 0xc0, 0x57, 0xd6, 0x75, 0x19, 0x32, 0x19, 0xa1, 0xaf, 0xd6, 0xb4, 0x31, 0xf7, 0x7c, 0xd4, 0x4c, + 0x66, 0xca, 0x2c, 0xda, 0x28, 0x2c, 0x15, 0x5d, 0x3e, 0x87, 0x4d, 0x16, 0x51, 0xbf, 0x10, 0xe5, + 0xfe, 0xf6, 0x26, 0xd6, 0xcb, 0x2b, 0x5f, 0xd3, 0x20, 0xa5, 0xc0, 0x19, 0x93, 0xf1, 0x07, 0x80, + 0xdd, 0x0a, 0xf8, 0x00, 0x4d, 0x7c, 0xb2, 0xdc, 0xc4, 0x1b, 0xfb, 0x35, 0xb1, 0xb9, 0xfa, 0x7f, + 0x00, 0x84, 0xe5, 0xc0, 0xa0, 0x1e, 0x6c, 0xce, 0xa8, 0x18, 0x65, 0xfb, 0xa4, 0x6d, 0xb7, 0x53, + 0xfc, 0xe3, 0xd4, 0x80, 0x33, 0x3b, 0x7a, 0x0b, 0xb6, 0x49, 0xc8, 0x3e, 0x16, 0x3c, 0x0e, 0xa5, + 0x76, 0xa4, 0x40, 0x9d, 0x64, 0xde, 0x6b, 0xf7, 0xaf, 0x06, 0x99, 0x11, 0x97, 0xfe, 0x14, 0x2c, + 0xa8, 0xe4, 0xb1, 0x70, 0xa8, 0xd4, 0x1a, 0x25, 0x18, 0x17, 0x46, 0x5c, 0xfa, 0xd1, 0x07, 0xb0, + 0x53, 0x1c, 0x2e, 0x89, 0x4f, 0xa5, 0xd6, 0x54, 0x01, 0x77, 0x92, 0x79, 0xaf, 0x83, 0xab, 0x0e, + 0xbc, 0x8c, 0x43, 0x1f, 0xc1, 0x6e, 0xc0, 0x83, 0x02, 0xf2, 0x05, 0x1e, 0x4a, 0xed, 0x05, 0x15, + 0xaa, 0x66, 0xf4, 0x72, 0xd9, 0x85, 0x57, 0xb1, 0xc6, 0xef, 0x00, 0x36, 0xfe, 0x77, 0x3b, 0xcc, + 0xf8, 0xa1, 0x0e, 0x4f, 0x9e, 0xaf, 0x94, 0xca, 0x4a, 0x49, 0xc7, 0xf0, 0xb0, 0xbb, 0x64, 0xff, + 0x31, 0xdc, 0xbd, 0x44, 0x7e, 0x05, 0xb0, 0x75, 0xa0, 0xed, 0xf1, 0x60, 0xb9, 0x6c, 0x7d, 0x47, + 0xd9, 0x9b, 0xeb, 0xfd, 0x16, 0x16, 0x37, 0x80, 0xee, 0xc3, 0x56, 0x31, 0xf1, 0xaa, 0xda, 0x76, + 0x99, 0xbd, 0x58, 0x0a, 0x78, 0x81, 0x40, 0x67, 0xb0, 0x31, 0x65, 0xc1, 0x58, 0xab, 0x2b, 0xe4, + 0x8b, 0x39, 0xb2, 0xf1, 0x29, 0x0b, 0xc6, 0x58, 0x79, 0x52, 0x44, 0x40, 0xfc, 0xec, 0x93, 0x5c, + 0x41, 0xa4, 0xb3, 0x8e, 0x95, 0xc7, 0xf8, 0x0d, 0xc0, 0xe3, 0xfc, 0x3d, 0x2d, 0xf8, 0xc0, 0x56, + 0xbe, 0x0b, 0x08, 0x49, 0xc8, 0x1e, 0x53, 0x21, 0x19, 0x0f, 0xf2, 0xbc, 0x8b, 0x97, 0xde, 0xbf, + 0x1a, 0xe4, 0x1e, 0x5c, 0x41, 0xed, 0xae, 0x01, 0x59, 0xb0, 0x9d, 0xfe, 0xca, 0x90, 0x38, 0x54, + 0x6b, 0x28, 0xd8, 0x9d, 0x1c, 0xd6, 0xbe, 0x2c, 0x1c, 0xb8, 0xc4, 0xd8, 0xe6, 0xf5, 0xad, 0x5e, + 0x7b, 0x76, 0xab, 0xd7, 0x6e, 0x6e, 0xf5, 0xda, 0x77, 0x89, 0x0e, 0xae, 0x13, 0x1d, 0x3c, 0x4b, + 0x74, 0x70, 0x93, 0xe8, 0xe0, 0xaf, 0x44, 0x07, 0x3f, 0xfe, 0xad, 0xd7, 0xbe, 0x6c, 0x15, 0xe2, + 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xb0, 0x73, 0x15, 0x10, 0x29, 0x0b, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/rbac/v1alpha1/generated.proto b/vendor/k8s.io/api/rbac/v1alpha1/generated.proto index 41a193f55..cde3aaac9 100644 --- a/vendor/k8s.io/api/rbac/v1alpha1/generated.proto +++ b/vendor/k8s.io/api/rbac/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.rbac.v1alpha1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; @@ -61,6 +60,7 @@ message ClusterRoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can only reference a ClusterRole in the global namespace. @@ -134,6 +134,7 @@ message RoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. diff --git a/vendor/k8s.io/api/rbac/v1alpha1/types.go b/vendor/k8s.io/api/rbac/v1alpha1/types.go index 843d998ec..398d6a169 100644 --- a/vendor/k8s.io/api/rbac/v1alpha1/types.go +++ b/vendor/k8s.io/api/rbac/v1alpha1/types.go @@ -126,7 +126,8 @@ type RoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. @@ -201,7 +202,8 @@ type ClusterRoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can only reference a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. diff --git a/vendor/k8s.io/api/rbac/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/api/rbac/v1alpha1/types_swagger_doc_generated.go index e56cd0f10..1d6ef30b0 100644 --- a/vendor/k8s.io/api/rbac/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/rbac/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AggregationRule = map[string]string{ "": "AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole", "clusterRoleSelectors": "ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. If any of the selectors match, then the ClusterRole's permissions will be added", diff --git a/vendor/k8s.io/api/rbac/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/api/rbac/v1alpha1/zz_generated.deepcopy.go index 562451cd6..1d29acff3 100644 --- a/vendor/k8s.io/api/rbac/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/rbac/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/rbac/v1beta1/generated.pb.go b/vendor/k8s.io/api/rbac/v1beta1/generated.pb.go index c2525e0df..71e5799e3 100644 --- a/vendor/k8s.io/api/rbac/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/rbac/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2693,58 +2693,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 833 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x55, 0xbf, 0x8f, 0xe3, 0x44, - 0x14, 0xce, 0x64, 0x13, 0x6d, 0x3c, 0xcb, 0x2a, 0xdc, 0x70, 0x02, 0x6b, 0x05, 0xce, 0x2a, 0x50, - 0x44, 0x3a, 0xce, 0x66, 0xef, 0x10, 0xd0, 0x20, 0x71, 0xa6, 0x80, 0xd5, 0x2d, 0x61, 0x35, 0x27, - 0x28, 0x10, 0x05, 0x63, 0x67, 0xce, 0x19, 0xe2, 0x5f, 0x9a, 0x19, 0x47, 0x3a, 0xd1, 0xd0, 0xd0, - 0x51, 0x20, 0x51, 0xd1, 0x52, 0x53, 0x51, 0xf2, 0x17, 0xa4, 0xbc, 0xf2, 0xaa, 0x88, 0x35, 0x7f, - 0x08, 0x68, 0xfc, 0x23, 0x4e, 0xe2, 0xf8, 0x2e, 0x55, 0x24, 0xa4, 0xab, 0x76, 0xe7, 0xbd, 0xef, - 0x7d, 0xef, 0x7b, 0x9f, 0x67, 0x5e, 0xe0, 0x27, 0xb3, 0x8f, 0x84, 0xc9, 0x22, 0x6b, 0x96, 0x38, - 0x94, 0x87, 0x54, 0x52, 0x61, 0xcd, 0x69, 0x38, 0x89, 0xb8, 0x55, 0x24, 0x48, 0xcc, 0x2c, 0xee, - 0x10, 0xd7, 0x9a, 0x5f, 0x38, 0x54, 0x92, 0x0b, 0xcb, 0xa3, 0x21, 0xe5, 0x44, 0xd2, 0x89, 0x19, - 0xf3, 0x48, 0x46, 0xe8, 0x8d, 0x1c, 0x68, 0x92, 0x98, 0x99, 0x0a, 0x68, 0x16, 0xc0, 0xb3, 0xbb, - 0x1e, 0x93, 0xd3, 0xc4, 0x31, 0xdd, 0x28, 0xb0, 0xbc, 0xc8, 0x8b, 0xac, 0x0c, 0xef, 0x24, 0x8f, - 0xb3, 0x53, 0x76, 0xc8, 0xfe, 0xcb, 0x79, 0xce, 0x46, 0xf5, 0x86, 0xc4, 0x8f, 0xa7, 0xf5, 0x8e, - 0x67, 0xef, 0x57, 0xc8, 0x80, 0xb8, 0x53, 0x16, 0x52, 0xfe, 0xc4, 0x8a, 0x67, 0x9e, 0x0a, 0x08, - 0x2b, 0xa0, 0x92, 0x58, 0xf3, 0x7a, 0x95, 0xd5, 0x54, 0xc5, 0x93, 0x50, 0xb2, 0x80, 0xd6, 0x0a, - 0x3e, 0x78, 0x51, 0x81, 0x70, 0xa7, 0x34, 0x20, 0xb5, 0xba, 0xfb, 0x4d, 0x75, 0x89, 0x64, 0xbe, - 0xc5, 0x42, 0x29, 0x24, 0xdf, 0x2e, 0x1a, 0xfe, 0x06, 0x60, 0xff, 0x81, 0xe7, 0x71, 0xea, 0x11, - 0xc9, 0xa2, 0x10, 0x27, 0x3e, 0x45, 0x3f, 0x01, 0x78, 0xdb, 0xf5, 0x13, 0x21, 0x29, 0xc7, 0x91, - 0x4f, 0x1f, 0x51, 0x9f, 0xba, 0x32, 0xe2, 0x42, 0x07, 0xe7, 0x47, 0xa3, 0x93, 0x7b, 0xf7, 0xcd, - 0xca, 0xf9, 0x55, 0x23, 0x33, 0x9e, 0x79, 0x2a, 0x20, 0x4c, 0xe5, 0x83, 0x39, 0xbf, 0x30, 0xaf, - 0x88, 0x43, 0xfd, 0xb2, 0xd6, 0x7e, 0x73, 0xb1, 0x1c, 0xb4, 0xd2, 0xe5, 0xe0, 0xf6, 0xa7, 0x3b, - 0x88, 0xf1, 0xce, 0x76, 0xc3, 0xdf, 0xdb, 0xf0, 0x64, 0x0d, 0x8e, 0xbe, 0x83, 0x3d, 0x45, 0x3e, - 0x21, 0x92, 0xe8, 0xe0, 0x1c, 0x8c, 0x4e, 0xee, 0xbd, 0xb7, 0x9f, 0x94, 0x2f, 0x9d, 0xef, 0xa9, - 0x2b, 0xbf, 0xa0, 0x92, 0xd8, 0xa8, 0xd0, 0x01, 0xab, 0x18, 0x5e, 0xb1, 0xa2, 0xcf, 0x61, 0x97, - 0x27, 0x3e, 0x15, 0x7a, 0x3b, 0x9b, 0xf4, 0x6d, 0xb3, 0xe1, 0x8e, 0x99, 0xd7, 0x91, 0xcf, 0xdc, - 0x27, 0xca, 0x2d, 0xfb, 0xb4, 0x60, 0xec, 0xaa, 0x93, 0xc0, 0x39, 0x01, 0xf2, 0x60, 0x9f, 0x6c, - 0xda, 0xaa, 0x1f, 0x65, 0x92, 0x47, 0x8d, 0x9c, 0x5b, 0x9f, 0xc1, 0x7e, 0x2d, 0x5d, 0x0e, 0xb6, - 0xbf, 0x0d, 0xde, 0x66, 0x1d, 0xfe, 0xda, 0x86, 0x68, 0xcd, 0x24, 0x9b, 0x85, 0x13, 0x16, 0x7a, - 0x07, 0xf0, 0x6a, 0x0c, 0x7b, 0x22, 0xc9, 0x12, 0xa5, 0x5d, 0xe7, 0x8d, 0xa3, 0x3d, 0xca, 0x81, - 0xf6, 0xab, 0x05, 0x63, 0xaf, 0x08, 0x08, 0xbc, 0xe2, 0x40, 0x0f, 0xe1, 0x31, 0x8f, 0x7c, 0x8a, - 0xe9, 0xe3, 0xc2, 0xa9, 0x66, 0x3a, 0x9c, 0xe3, 0xec, 0x7e, 0x41, 0x77, 0x5c, 0x04, 0x70, 0xc9, - 0x30, 0x5c, 0x00, 0xf8, 0x7a, 0xdd, 0x95, 0x2b, 0x26, 0x24, 0xfa, 0xb6, 0xe6, 0x8c, 0xb9, 0xe7, - 0x85, 0x66, 0x22, 0xf7, 0x65, 0x35, 0x45, 0x19, 0x59, 0x73, 0xe5, 0x1a, 0x76, 0x99, 0xa4, 0x41, - 0x69, 0xc9, 0x9d, 0xc6, 0x19, 0xea, 0xea, 0xaa, 0x9b, 0x74, 0xa9, 0x18, 0x70, 0x4e, 0x34, 0xfc, - 0x0b, 0xc0, 0xfe, 0x1a, 0xf8, 0x00, 0x33, 0x5c, 0x6e, 0xce, 0xf0, 0xce, 0x5e, 0x33, 0xec, 0x16, - 0xff, 0x2f, 0x80, 0xb0, 0x7a, 0x2b, 0x68, 0x00, 0xbb, 0x73, 0xca, 0x9d, 0x7c, 0x93, 0x68, 0xb6, - 0xa6, 0xf0, 0x5f, 0xab, 0x00, 0xce, 0xe3, 0xe8, 0x0e, 0xd4, 0x48, 0xcc, 0x3e, 0xe3, 0x51, 0x12, - 0xe7, 0xed, 0x35, 0xfb, 0x34, 0x5d, 0x0e, 0xb4, 0x07, 0xd7, 0x97, 0x79, 0x10, 0x57, 0x79, 0x05, - 0xe6, 0x54, 0x44, 0x09, 0x77, 0xa9, 0xd0, 0x8f, 0x2a, 0x30, 0x2e, 0x83, 0xb8, 0xca, 0xa3, 0x0f, - 0xe1, 0x69, 0x79, 0x18, 0x93, 0x80, 0x0a, 0xbd, 0x93, 0x15, 0xdc, 0x4a, 0x97, 0x83, 0x53, 0xbc, - 0x9e, 0xc0, 0x9b, 0x38, 0xf4, 0x31, 0xec, 0x87, 0x51, 0x58, 0x42, 0xbe, 0xc2, 0x57, 0x42, 0xef, - 0x66, 0xa5, 0xd9, 0xfb, 0x1c, 0x6f, 0xa6, 0xf0, 0x36, 0x76, 0xf8, 0x27, 0x80, 0x9d, 0xff, 0xdb, - 0xf6, 0x1a, 0xfe, 0xdc, 0x86, 0x27, 0x2f, 0xb7, 0xc9, 0x6a, 0x9b, 0xa8, 0x27, 0x78, 0xd8, 0x35, - 0xb2, 0xf7, 0x13, 0x7c, 0xf1, 0xfe, 0xf8, 0x03, 0xc0, 0xde, 0x81, 0x16, 0x87, 0xbd, 0xa9, 0xfa, - 0xad, 0xe7, 0xab, 0xde, 0x2d, 0xf7, 0x07, 0x58, 0xfa, 0x8f, 0xde, 0x85, 0xbd, 0xf2, 0xb1, 0x67, - 0x62, 0xb5, 0xaa, 0x79, 0xb9, 0x0f, 0xf0, 0x0a, 0x81, 0xce, 0x61, 0x67, 0xc6, 0xc2, 0x89, 0xde, - 0xce, 0x90, 0xaf, 0x14, 0xc8, 0xce, 0x43, 0x16, 0x4e, 0x70, 0x96, 0x51, 0x88, 0x90, 0x04, 0xf9, - 0x0f, 0xf1, 0x1a, 0x42, 0x3d, 0x73, 0x9c, 0x65, 0x94, 0x57, 0xc7, 0xc5, 0x65, 0x5a, 0xf1, 0x81, - 0x46, 0xbe, 0x75, 0x7d, 0xed, 0x7d, 0xf4, 0x3d, 0xbf, 0x3b, 0xb2, 0xa0, 0xa6, 0xfe, 0x8a, 0x98, - 0xb8, 0x54, 0xef, 0x64, 0xb0, 0x5b, 0x05, 0x4c, 0x1b, 0x97, 0x09, 0x5c, 0x61, 0xec, 0xbb, 0x8b, - 0x1b, 0xa3, 0xf5, 0xf4, 0xc6, 0x68, 0x3d, 0xbb, 0x31, 0x5a, 0x3f, 0xa6, 0x06, 0x58, 0xa4, 0x06, - 0x78, 0x9a, 0x1a, 0xe0, 0x59, 0x6a, 0x80, 0xbf, 0x53, 0x03, 0xfc, 0xf2, 0x8f, 0xd1, 0xfa, 0xe6, - 0xb8, 0x70, 0xfd, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd1, 0x99, 0xaf, 0xff, 0x74, 0x0b, 0x00, - 0x00, + // 808 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x55, 0xbd, 0x6f, 0xfb, 0x44, + 0x18, 0xce, 0xa5, 0x89, 0x12, 0x5f, 0x88, 0xc2, 0xef, 0xa8, 0xc0, 0xaa, 0xc0, 0x89, 0x02, 0x43, + 0xa5, 0x52, 0x9b, 0x16, 0x04, 0x2c, 0x48, 0xd4, 0x0c, 0x50, 0xb5, 0x84, 0xea, 0x2a, 0x18, 0x10, + 0x03, 0x67, 0xe7, 0xea, 0x1e, 0xf1, 0x97, 0xee, 0xec, 0x48, 0x15, 0x0b, 0x0b, 0x1b, 0x03, 0x12, + 0x13, 0x2b, 0x33, 0x13, 0x23, 0x7f, 0x41, 0xc6, 0x8e, 0x9d, 0x22, 0x6a, 0xfe, 0x10, 0xd0, 0xf9, + 0x23, 0xce, 0x67, 0x9b, 0x29, 0x12, 0x12, 0x53, 0x7b, 0xef, 0xfb, 0xbc, 0xcf, 0xfb, 0xbc, 0x8f, + 0xef, 0xde, 0xc0, 0x8f, 0x47, 0x1f, 0x0a, 0x9d, 0x05, 0xc6, 0x28, 0xb6, 0x28, 0xf7, 0x69, 0x44, + 0x85, 0x31, 0xa6, 0xfe, 0x30, 0xe0, 0x46, 0x9e, 0x20, 0x21, 0x33, 0xb8, 0x45, 0x6c, 0x63, 0x7c, + 0x62, 0xd1, 0x88, 0x9c, 0x18, 0x0e, 0xf5, 0x29, 0x27, 0x11, 0x1d, 0xea, 0x21, 0x0f, 0xa2, 0x00, + 0xbd, 0x96, 0x01, 0x75, 0x12, 0x32, 0x5d, 0x02, 0xf5, 0x1c, 0x78, 0x70, 0xec, 0xb0, 0xe8, 0x36, + 0xb6, 0x74, 0x3b, 0xf0, 0x0c, 0x27, 0x70, 0x02, 0x23, 0xc5, 0x5b, 0xf1, 0x4d, 0x7a, 0x4a, 0x0f, + 0xe9, 0x7f, 0x19, 0xcf, 0xc1, 0x7b, 0x65, 0x43, 0x8f, 0xd8, 0xb7, 0xcc, 0xa7, 0xfc, 0xce, 0x08, + 0x47, 0x8e, 0x0c, 0x08, 0xc3, 0xa3, 0x11, 0x31, 0xc6, 0x2b, 0xdd, 0x0f, 0x8c, 0x4d, 0x55, 0x3c, + 0xf6, 0x23, 0xe6, 0xd1, 0x95, 0x82, 0xf7, 0x9f, 0x2b, 0x10, 0xf6, 0x2d, 0xf5, 0xc8, 0x72, 0x5d, + 0xff, 0x57, 0x00, 0x3b, 0x67, 0x8e, 0xc3, 0xa9, 0x43, 0x22, 0x16, 0xf8, 0x38, 0x76, 0x29, 0xfa, + 0x11, 0xc0, 0x7d, 0xdb, 0x8d, 0x45, 0x44, 0x39, 0x0e, 0x5c, 0x7a, 0x4d, 0x5d, 0x6a, 0x47, 0x01, + 0x17, 0x2a, 0xe8, 0xed, 0x1d, 0xb6, 0x4e, 0xdf, 0xd5, 0x4b, 0x6b, 0x66, 0xbd, 0xf4, 0x70, 0xe4, + 0xc8, 0x80, 0xd0, 0xe5, 0x48, 0xfa, 0xf8, 0x44, 0xbf, 0x24, 0x16, 0x75, 0x8b, 0x5a, 0xf3, 0xf5, + 0xc9, 0xb4, 0x5b, 0x49, 0xa6, 0xdd, 0xfd, 0x4f, 0xd6, 0x10, 0xe3, 0xb5, 0xed, 0xfa, 0xbf, 0x55, + 0x61, 0x6b, 0x0e, 0x8e, 0xbe, 0x85, 0x4d, 0x49, 0x3e, 0x24, 0x11, 0x51, 0x41, 0x0f, 0x1c, 0xb6, + 0x4e, 0xdf, 0xd9, 0x4e, 0xca, 0x17, 0xd6, 0x77, 0xd4, 0x8e, 0x3e, 0xa7, 0x11, 0x31, 0x51, 0xae, + 0x03, 0x96, 0x31, 0x3c, 0x63, 0x45, 0x9f, 0xc1, 0x3a, 0x8f, 0x5d, 0x2a, 0xd4, 0x6a, 0x3a, 0xe9, + 0x9b, 0xfa, 0x86, 0x4b, 0xa0, 0x5f, 0x05, 0x2e, 0xb3, 0xef, 0xa4, 0x5b, 0x66, 0x3b, 0x67, 0xac, + 0xcb, 0x93, 0xc0, 0x19, 0x01, 0x72, 0x60, 0x87, 0x2c, 0xda, 0xaa, 0xee, 0xa5, 0x92, 0x0f, 0x37, + 0x72, 0x2e, 0x7d, 0x06, 0xf3, 0x95, 0x64, 0xda, 0x5d, 0xfe, 0x36, 0x78, 0x99, 0xb5, 0xff, 0x4b, + 0x15, 0xa2, 0x39, 0x93, 0x4c, 0xe6, 0x0f, 0x99, 0xef, 0xec, 0xc0, 0xab, 0x01, 0x6c, 0x8a, 0x38, + 0x4d, 0x14, 0x76, 0xf5, 0x36, 0x8e, 0x76, 0x9d, 0x01, 0xcd, 0x97, 0x73, 0xc6, 0x66, 0x1e, 0x10, + 0x78, 0xc6, 0x81, 0x2e, 0x60, 0x83, 0x07, 0x2e, 0xc5, 0xf4, 0x26, 0x77, 0x6a, 0x33, 0x1d, 0xce, + 0x70, 0x66, 0x27, 0xa7, 0x6b, 0xe4, 0x01, 0x5c, 0x30, 0xf4, 0x27, 0x00, 0xbe, 0xba, 0xea, 0xca, + 0x25, 0x13, 0x11, 0xfa, 0x66, 0xc5, 0x19, 0x7d, 0xcb, 0x0b, 0xcd, 0x44, 0xe6, 0xcb, 0x6c, 0x8a, + 0x22, 0x32, 0xe7, 0xca, 0x15, 0xac, 0xb3, 0x88, 0x7a, 0x85, 0x25, 0x47, 0x1b, 0x67, 0x58, 0x55, + 0x57, 0xde, 0xa4, 0x73, 0xc9, 0x80, 0x33, 0xa2, 0xfe, 0x9f, 0x00, 0x76, 0xe6, 0xc0, 0x3b, 0x98, + 0xe1, 0x7c, 0x71, 0x86, 0xb7, 0xb6, 0x9a, 0x61, 0xbd, 0xf8, 0x7f, 0x00, 0x84, 0xe5, 0x5b, 0x41, + 0x5d, 0x58, 0x1f, 0x53, 0x6e, 0x65, 0x9b, 0x44, 0x31, 0x15, 0x89, 0xff, 0x4a, 0x06, 0x70, 0x16, + 0x47, 0x47, 0x50, 0x21, 0x21, 0xfb, 0x94, 0x07, 0x71, 0x98, 0xb5, 0x57, 0xcc, 0x76, 0x32, 0xed, + 0x2a, 0x67, 0x57, 0xe7, 0x59, 0x10, 0x97, 0x79, 0x09, 0xe6, 0x54, 0x04, 0x31, 0xb7, 0xa9, 0x50, + 0xf7, 0x4a, 0x30, 0x2e, 0x82, 0xb8, 0xcc, 0xa3, 0x0f, 0x60, 0xbb, 0x38, 0x0c, 0x88, 0x47, 0x85, + 0x5a, 0x4b, 0x0b, 0x5e, 0x24, 0xd3, 0x6e, 0x1b, 0xcf, 0x27, 0xf0, 0x22, 0x0e, 0x7d, 0x04, 0x3b, + 0x7e, 0xe0, 0x17, 0x90, 0x2f, 0xf1, 0xa5, 0x50, 0xeb, 0x69, 0x69, 0xfa, 0x3e, 0x07, 0x8b, 0x29, + 0xbc, 0x8c, 0xed, 0xff, 0x01, 0x60, 0xed, 0xbf, 0xb6, 0xbd, 0xfa, 0x3f, 0x55, 0x61, 0xeb, 0xff, + 0x6d, 0x32, 0xdb, 0x26, 0xf2, 0x09, 0xee, 0x76, 0x8d, 0x6c, 0xfd, 0x04, 0x9f, 0xdf, 0x1f, 0xbf, + 0x03, 0xd8, 0xdc, 0xd1, 0xe2, 0x30, 0x17, 0x55, 0xbf, 0xf1, 0xb4, 0xea, 0xf5, 0x72, 0xbf, 0x87, + 0x85, 0xff, 0xe8, 0x6d, 0xd8, 0x2c, 0x1e, 0x7b, 0x2a, 0x56, 0x29, 0x9b, 0x17, 0xfb, 0x00, 0xcf, + 0x10, 0xa8, 0x07, 0x6b, 0x23, 0xe6, 0x0f, 0xd5, 0x6a, 0x8a, 0x7c, 0x29, 0x47, 0xd6, 0x2e, 0x98, + 0x3f, 0xc4, 0x69, 0x46, 0x22, 0x7c, 0xe2, 0x65, 0x3f, 0xc4, 0x73, 0x08, 0xf9, 0xcc, 0x71, 0x9a, + 0x91, 0x5e, 0x35, 0xf2, 0xcb, 0x34, 0xe3, 0x03, 0x1b, 0xf9, 0xe6, 0xf5, 0x55, 0xb7, 0xd1, 0xf7, + 0x74, 0x77, 0x64, 0x40, 0x45, 0xfe, 0x15, 0x21, 0xb1, 0xa9, 0x5a, 0x4b, 0x61, 0x2f, 0x72, 0x98, + 0x32, 0x28, 0x12, 0xb8, 0xc4, 0x98, 0xc7, 0x93, 0x47, 0xad, 0x72, 0xff, 0xa8, 0x55, 0x1e, 0x1e, + 0xb5, 0xca, 0x0f, 0x89, 0x06, 0x26, 0x89, 0x06, 0xee, 0x13, 0x0d, 0x3c, 0x24, 0x1a, 0xf8, 0x2b, + 0xd1, 0xc0, 0xcf, 0x7f, 0x6b, 0x95, 0xaf, 0x1b, 0xb9, 0xeb, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, + 0x37, 0x8f, 0x77, 0xcd, 0x15, 0x0b, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/rbac/v1beta1/generated.proto b/vendor/k8s.io/api/rbac/v1beta1/generated.proto index aa9960b8e..27bd30ce9 100644 --- a/vendor/k8s.io/api/rbac/v1beta1/generated.proto +++ b/vendor/k8s.io/api/rbac/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,11 +21,9 @@ syntax = 'proto2'; package k8s.io.api.rbac.v1beta1; -import "k8s.io/api/rbac/v1alpha1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; @@ -62,6 +60,7 @@ message ClusterRoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can only reference a ClusterRole in the global namespace. @@ -135,6 +134,7 @@ message RoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. diff --git a/vendor/k8s.io/api/rbac/v1beta1/types.go b/vendor/k8s.io/api/rbac/v1beta1/types.go index 091fc1dc9..857b67a6f 100644 --- a/vendor/k8s.io/api/rbac/v1beta1/types.go +++ b/vendor/k8s.io/api/rbac/v1beta1/types.go @@ -125,7 +125,8 @@ type RoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. @@ -199,7 +200,8 @@ type ClusterRoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can only reference a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. diff --git a/vendor/k8s.io/api/rbac/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/rbac/v1beta1/types_swagger_doc_generated.go index 6180d6d43..66dba6ca1 100644 --- a/vendor/k8s.io/api/rbac/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/rbac/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AggregationRule = map[string]string{ "": "AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole", "clusterRoleSelectors": "ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. If any of the selectors match, then the ClusterRole's permissions will be added", diff --git a/vendor/k8s.io/api/rbac/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/rbac/v1beta1/zz_generated.deepcopy.go index 0ef823a07..86fadd170 100644 --- a/vendor/k8s.io/api/rbac/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/rbac/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/roundtrip_test.go b/vendor/k8s.io/api/roundtrip_test.go new file mode 100644 index 000000000..5b82feb84 --- /dev/null +++ b/vendor/k8s.io/api/roundtrip_test.go @@ -0,0 +1,150 @@ +/* +Copyright 2018 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 testing + +import ( + "math/rand" + "testing" + + admissionv1beta1 "k8s.io/api/admission/v1beta1" + admissionregv1alpha1 "k8s.io/api/admissionregistration/v1alpha1" + admissionregv1beta1 "k8s.io/api/admissionregistration/v1beta1" + appsv1 "k8s.io/api/apps/v1" + appsv1beta1 "k8s.io/api/apps/v1beta1" + appsv1beta2 "k8s.io/api/apps/v1beta2" + authenticationv1 "k8s.io/api/authentication/v1" + authenticationv1beta1 "k8s.io/api/authentication/v1beta1" + authorizationv1 "k8s.io/api/authorization/v1" + authorizationv1beta1 "k8s.io/api/authorization/v1beta1" + autoscalingv1 "k8s.io/api/autoscaling/v1" + autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" + batchv2alpha1 "k8s.io/api/batch/v2alpha1" + certificatesv1beta1 "k8s.io/api/certificates/v1beta1" + corev1 "k8s.io/api/core/v1" + eventsv1beta1 "k8s.io/api/events/v1beta1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + imagepolicyv1alpha1 "k8s.io/api/imagepolicy/v1alpha1" + networkingv1 "k8s.io/api/networking/v1" + policyv1beta1 "k8s.io/api/policy/v1beta1" + rbacv1 "k8s.io/api/rbac/v1" + rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" + rbacv1beta1 "k8s.io/api/rbac/v1beta1" + schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" + settingsv1alpha1 "k8s.io/api/settings/v1alpha1" + storagev1 "k8s.io/api/storage/v1" + storagev1alpha1 "k8s.io/api/storage/v1alpha1" + storagev1beta1 "k8s.io/api/storage/v1beta1" + + "k8s.io/apimachinery/pkg/api/testing/fuzzer" + "k8s.io/apimachinery/pkg/api/testing/roundtrip" + genericfuzzer "k8s.io/apimachinery/pkg/apis/meta/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" +) + +var groups = []runtime.SchemeBuilder{ + admissionv1beta1.SchemeBuilder, + admissionregv1alpha1.SchemeBuilder, + admissionregv1beta1.SchemeBuilder, + appsv1beta1.SchemeBuilder, + appsv1beta2.SchemeBuilder, + appsv1.SchemeBuilder, + authenticationv1beta1.SchemeBuilder, + authenticationv1.SchemeBuilder, + authorizationv1beta1.SchemeBuilder, + authorizationv1.SchemeBuilder, + autoscalingv1.SchemeBuilder, + autoscalingv2beta1.SchemeBuilder, + batchv2alpha1.SchemeBuilder, + batchv1beta1.SchemeBuilder, + batchv1.SchemeBuilder, + certificatesv1beta1.SchemeBuilder, + corev1.SchemeBuilder, + eventsv1beta1.SchemeBuilder, + extensionsv1beta1.SchemeBuilder, + imagepolicyv1alpha1.SchemeBuilder, + networkingv1.SchemeBuilder, + policyv1beta1.SchemeBuilder, + rbacv1alpha1.SchemeBuilder, + rbacv1beta1.SchemeBuilder, + rbacv1.SchemeBuilder, + schedulingv1alpha1.SchemeBuilder, + schedulingv1beta1.SchemeBuilder, + settingsv1alpha1.SchemeBuilder, + storagev1alpha1.SchemeBuilder, + storagev1beta1.SchemeBuilder, + storagev1.SchemeBuilder, +} + +func TestRoundTripExternalTypes(t *testing.T) { + for _, builder := range groups { + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + + builder.AddToScheme(scheme) + seed := rand.Int63() + // I'm only using the generic fuzzer funcs, but at some point in time we might need to + // switch to specialized. For now we're happy with the current serialization test. + fuzzer := fuzzer.FuzzerFor(genericfuzzer.Funcs, rand.NewSource(seed), codecs) + + roundtrip.RoundTripExternalTypes(t, scheme, codecs, fuzzer, nil) + } +} + +func TestFailRoundTrip(t *testing.T) { + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + groupVersion := schema.GroupVersion{Group: "broken", Version: "v1"} + builder := runtime.NewSchemeBuilder(func(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(groupVersion, &BrokenType{}) + metav1.AddToGroupVersion(scheme, groupVersion) + return nil + }) + builder.AddToScheme(scheme) + seed := rand.Int63() + fuzzer := fuzzer.FuzzerFor(genericfuzzer.Funcs, rand.NewSource(seed), codecs) + tmpT := new(testing.T) + roundtrip.RoundTripExternalTypes(tmpT, scheme, codecs, fuzzer, nil) + // It's very hacky way of making sure the DeepCopy is actually invoked inside RoundTripExternalTypes + // used in the other test. If for some reason this tests starts passing we need to fail b/c we're not testing + // the DeepCopy in the other method which we care so much about. + if !tmpT.Failed() { + t.Log("RoundTrip should've failed on DeepCopy but it did not!") + t.FailNow() + } +} + +type BrokenType struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Field1 string `json:"field1,omitempty"` + Field2 string `json:"field2,omitempty"` +} + +func (in *BrokenType) DeepCopy() *BrokenType { + return new(BrokenType) +} + +func (in *BrokenType) DeepCopyObject() runtime.Object { + return in.DeepCopy() +} diff --git a/vendor/k8s.io/api/scheduling/v1alpha1/generated.pb.go b/vendor/k8s.io/api/scheduling/v1alpha1/generated.pb.go index 39c0b9e6a..97c07c984 100644 --- a/vendor/k8s.io/api/scheduling/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/api/scheduling/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -608,34 +608,33 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 460 bytes of a gzipped FileDescriptorProto + // 447 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x4f, 0x8b, 0xd3, 0x40, 0x18, 0xc6, 0x33, 0x5d, 0x0b, 0x75, 0x4a, 0x41, 0x23, 0x42, 0xe8, 0x61, 0x36, 0xac, 0x97, 0x5c, - 0x76, 0xc6, 0xae, 0x7f, 0x10, 0xbc, 0xc5, 0x85, 0x45, 0x50, 0x94, 0x1c, 0x3c, 0x88, 0x07, 0x27, - 0xc9, 0x6c, 0x3a, 0x36, 0xc9, 0x84, 0x99, 0x37, 0x81, 0xbd, 0x79, 0xf6, 0xe4, 0x97, 0x12, 0x7a, - 0xdc, 0xe3, 0x9e, 0x16, 0x1b, 0xbf, 0x88, 0x24, 0x4d, 0x37, 0xad, 0x65, 0xd5, 0x5b, 0xe6, 0x79, - 0x9f, 0xdf, 0x33, 0xf3, 0x3e, 0x04, 0x9f, 0x2d, 0x5e, 0x18, 0x2a, 0x15, 0x5b, 0x94, 0xa1, 0xd0, - 0xb9, 0x00, 0x61, 0x58, 0x25, 0xf2, 0x58, 0x69, 0xd6, 0x0d, 0x78, 0x21, 0x99, 0x89, 0xe6, 0x22, - 0x2e, 0x53, 0x99, 0x27, 0xac, 0x9a, 0xf1, 0xb4, 0x98, 0xf3, 0x19, 0x4b, 0x44, 0x2e, 0x34, 0x07, - 0x11, 0xd3, 0x42, 0x2b, 0x50, 0x36, 0x59, 0xfb, 0x29, 0x2f, 0x24, 0xed, 0xfd, 0x74, 0xe3, 0x9f, - 0x1e, 0x27, 0x12, 0xe6, 0x65, 0x48, 0x23, 0x95, 0xb1, 0x44, 0x25, 0x8a, 0xb5, 0x58, 0x58, 0x9e, - 0xb7, 0xa7, 0xf6, 0xd0, 0x7e, 0xad, 0xe3, 0xa6, 0x4f, 0xfb, 0xeb, 0x33, 0x1e, 0xcd, 0x65, 0x2e, - 0xf4, 0x05, 0x2b, 0x16, 0x49, 0x23, 0x18, 0x96, 0x09, 0xe0, 0xac, 0xda, 0x7b, 0xc4, 0x94, 0xdd, - 0x46, 0xe9, 0x32, 0x07, 0x99, 0x89, 0x3d, 0xe0, 0xf9, 0xbf, 0x80, 0x66, 0x95, 0x8c, 0xef, 0x71, - 0x4f, 0x6e, 0xe3, 0x4a, 0x90, 0x29, 0x93, 0x39, 0x18, 0xd0, 0x7f, 0x42, 0x47, 0xdf, 0x06, 0x78, - 0xf2, 0x5e, 0x4b, 0xa5, 0x25, 0x5c, 0xbc, 0x4a, 0xb9, 0x31, 0xf6, 0x67, 0x3c, 0x6a, 0x56, 0x89, - 0x39, 0x70, 0x07, 0xb9, 0xc8, 0x1b, 0x9f, 0x3c, 0xa6, 0x7d, 0x8f, 0x37, 0xc9, 0xb4, 0x58, 0x24, - 0x8d, 0x60, 0x68, 0xe3, 0xa6, 0xd5, 0x8c, 0xbe, 0x0b, 0xbf, 0x88, 0x08, 0xde, 0x0a, 0xe0, 0xbe, - 0xbd, 0xbc, 0x3e, 0xb4, 0xea, 0xeb, 0x43, 0xdc, 0x6b, 0xc1, 0x4d, 0xaa, 0xfd, 0x08, 0x0f, 0x2b, - 0x9e, 0x96, 0xc2, 0x19, 0xb8, 0xc8, 0x1b, 0xfa, 0x93, 0xce, 0x3c, 0xfc, 0xd0, 0x88, 0xc1, 0x7a, - 0x66, 0xbf, 0xc4, 0x93, 0x24, 0x55, 0x21, 0x4f, 0x4f, 0xc5, 0x39, 0x2f, 0x53, 0x70, 0x0e, 0x5c, - 0xe4, 0x8d, 0xfc, 0x87, 0x9d, 0x79, 0x72, 0xb6, 0x3d, 0x0c, 0x76, 0xbd, 0xf6, 0x33, 0x3c, 0x8e, - 0x85, 0x89, 0xb4, 0x2c, 0x40, 0xaa, 0xdc, 0xb9, 0xe3, 0x22, 0xef, 0xae, 0xff, 0xa0, 0x43, 0xc7, - 0xa7, 0xfd, 0x28, 0xd8, 0xf6, 0x1d, 0xfd, 0x40, 0xf8, 0xfe, 0x4e, 0x19, 0x6f, 0xa4, 0x01, 0xfb, - 0xd3, 0x5e, 0x21, 0xf4, 0xff, 0x0a, 0x69, 0xe8, 0xb6, 0x8e, 0x7b, 0xdd, 0xcd, 0xa3, 0x8d, 0xb2, - 0x55, 0x46, 0x80, 0x87, 0x12, 0x44, 0x66, 0x9c, 0x81, 0x7b, 0xe0, 0x8d, 0x4f, 0x8e, 0xe9, 0xdf, - 0xff, 0x59, 0xba, 0xf3, 0xbe, 0xbe, 0xbb, 0xd7, 0x4d, 0x46, 0xb0, 0x8e, 0xf2, 0xe9, 0x72, 0x45, - 0xac, 0xcb, 0x15, 0xb1, 0xae, 0x56, 0xc4, 0xfa, 0x5a, 0x13, 0xb4, 0xac, 0x09, 0xba, 0xac, 0x09, - 0xba, 0xaa, 0x09, 0xfa, 0x59, 0x13, 0xf4, 0xfd, 0x17, 0xb1, 0x3e, 0x8e, 0x36, 0x99, 0xbf, 0x03, - 0x00, 0x00, 0xff, 0xff, 0x44, 0x05, 0xba, 0x7b, 0x71, 0x03, 0x00, 0x00, + 0x76, 0xc6, 0x2e, 0x2a, 0x82, 0xb7, 0xb8, 0xb0, 0x08, 0x8a, 0x92, 0x83, 0x07, 0xf1, 0xe0, 0x24, + 0x79, 0x37, 0x1d, 0x9b, 0x64, 0xc2, 0xcc, 0x24, 0xb0, 0x37, 0xcf, 0x9e, 0xfc, 0x52, 0x42, 0x8f, + 0x7b, 0xdc, 0xd3, 0x62, 0xe3, 0x17, 0x91, 0xa4, 0x69, 0xd3, 0x5a, 0xfc, 0x73, 0xcb, 0x3c, 0xef, + 0xef, 0x79, 0xe6, 0xcd, 0xc3, 0xe0, 0x8b, 0xc5, 0x73, 0x4d, 0x85, 0x64, 0x8b, 0x32, 0x04, 0x95, + 0x83, 0x01, 0xcd, 0x2a, 0xc8, 0x63, 0xa9, 0x58, 0x37, 0xe0, 0x85, 0x60, 0x3a, 0x9a, 0x43, 0x5c, + 0xa6, 0x22, 0x4f, 0x58, 0x35, 0xe3, 0x69, 0x31, 0xe7, 0x33, 0x96, 0x40, 0x0e, 0x8a, 0x1b, 0x88, + 0x69, 0xa1, 0xa4, 0x91, 0x36, 0x59, 0xf3, 0x94, 0x17, 0x82, 0xf6, 0x3c, 0xdd, 0xf0, 0xd3, 0xd3, + 0x44, 0x98, 0x79, 0x19, 0xd2, 0x48, 0x66, 0x2c, 0x91, 0x89, 0x64, 0xad, 0x2d, 0x2c, 0x2f, 0xdb, + 0x53, 0x7b, 0x68, 0xbf, 0xd6, 0x71, 0xd3, 0x27, 0xfd, 0xf5, 0x19, 0x8f, 0xe6, 0x22, 0x07, 0x75, + 0xc5, 0x8a, 0x45, 0xd2, 0x08, 0x9a, 0x65, 0x60, 0x38, 0xab, 0x0e, 0x96, 0x98, 0xb2, 0x3f, 0xb9, + 0x54, 0x99, 0x1b, 0x91, 0xc1, 0x81, 0xe1, 0xd9, 0xbf, 0x0c, 0xcd, 0xaf, 0x64, 0xfc, 0x77, 0xdf, + 0xc9, 0xd7, 0x01, 0x9e, 0xbc, 0x53, 0x42, 0x2a, 0x61, 0xae, 0x5e, 0xa6, 0x5c, 0x6b, 0xfb, 0x13, + 0x1e, 0x35, 0x5b, 0xc5, 0xdc, 0x70, 0x07, 0xb9, 0xc8, 0x1b, 0x9f, 0x3d, 0xa6, 0x7d, 0x25, 0xdb, + 0x70, 0x5a, 0x2c, 0x92, 0x46, 0xd0, 0xb4, 0xa1, 0x69, 0x35, 0xa3, 0x6f, 0xc3, 0xcf, 0x10, 0x99, + 0x37, 0x60, 0xb8, 0x6f, 0x2f, 0x6f, 0x8f, 0xad, 0xfa, 0xf6, 0x18, 0xf7, 0x5a, 0xb0, 0x4d, 0xb5, + 0x1f, 0xe1, 0x61, 0xc5, 0xd3, 0x12, 0x9c, 0x81, 0x8b, 0xbc, 0xa1, 0x3f, 0xe9, 0xe0, 0xe1, 0xfb, + 0x46, 0x0c, 0xd6, 0x33, 0xfb, 0x05, 0x9e, 0x24, 0xa9, 0x0c, 0x79, 0x7a, 0x0e, 0x97, 0xbc, 0x4c, + 0x8d, 0x73, 0xe4, 0x22, 0x6f, 0xe4, 0x3f, 0xec, 0xe0, 0xc9, 0xc5, 0xee, 0x30, 0xd8, 0x67, 0xed, + 0xa7, 0x78, 0x1c, 0x83, 0x8e, 0x94, 0x28, 0x8c, 0x90, 0xb9, 0x73, 0xc7, 0x45, 0xde, 0x5d, 0xff, + 0x41, 0x67, 0x1d, 0x9f, 0xf7, 0xa3, 0x60, 0x97, 0x3b, 0xf9, 0x8e, 0xf0, 0xfd, 0xbd, 0x32, 0x5e, + 0x0b, 0x6d, 0xec, 0x8f, 0x07, 0x85, 0xd0, 0xff, 0x2b, 0xa4, 0x71, 0xb7, 0x75, 0xdc, 0xeb, 0x6e, + 0x1e, 0x6d, 0x94, 0x9d, 0x32, 0x02, 0x3c, 0x14, 0x06, 0x32, 0xed, 0x0c, 0xdc, 0x23, 0x6f, 0x7c, + 0x76, 0x4a, 0xff, 0xfe, 0xfc, 0xe8, 0xde, 0x7e, 0x7d, 0x77, 0xaf, 0x9a, 0x8c, 0x60, 0x1d, 0xe5, + 0xd3, 0xe5, 0x8a, 0x58, 0xd7, 0x2b, 0x62, 0xdd, 0xac, 0x88, 0xf5, 0xa5, 0x26, 0x68, 0x59, 0x13, + 0x74, 0x5d, 0x13, 0x74, 0x53, 0x13, 0xf4, 0xa3, 0x26, 0xe8, 0xdb, 0x4f, 0x62, 0x7d, 0x18, 0x6d, + 0x32, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0xab, 0x20, 0x12, 0x63, 0x3c, 0x03, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/scheduling/v1alpha1/generated.proto b/vendor/k8s.io/api/scheduling/v1alpha1/generated.proto index e964a76dd..5fb547211 100644 --- a/vendor/k8s.io/api/scheduling/v1alpha1/generated.proto +++ b/vendor/k8s.io/api/scheduling/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.scheduling.v1alpha1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go index 9080dd9d6..f406f4402 100644 --- a/vendor/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_PriorityClass = map[string]string{ "": "PriorityClass defines mapping from a priority class name to the priority integer value. The value can be any valid integer.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/api/scheduling/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/api/scheduling/v1alpha1/zz_generated.deepcopy.go index 51f8d0473..fe0c86040 100644 --- a/vendor/k8s.io/api/scheduling/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/scheduling/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/scheduling/v1beta1/doc.go b/vendor/k8s.io/api/scheduling/v1beta1/doc.go new file mode 100644 index 000000000..f2dd1cfac --- /dev/null +++ b/vendor/k8s.io/api/scheduling/v1beta1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2018 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. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:openapi-gen=true + +// +groupName=scheduling.k8s.io +package v1beta1 // import "k8s.io/api/scheduling/v1beta1" diff --git a/vendor/k8s.io/api/scheduling/v1beta1/generated.pb.go b/vendor/k8s.io/api/scheduling/v1beta1/generated.pb.go new file mode 100644 index 000000000..ea8f8d5e6 --- /dev/null +++ b/vendor/k8s.io/api/scheduling/v1beta1/generated.pb.go @@ -0,0 +1,640 @@ +/* +Copyright 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. +*/ + +// Code generated by protoc-gen-gogo. +// source: k8s.io/kubernetes/vendor/k8s.io/api/scheduling/v1beta1/generated.proto +// DO NOT EDIT! + +/* + Package v1beta1 is a generated protocol buffer package. + + It is generated from these files: + k8s.io/kubernetes/vendor/k8s.io/api/scheduling/v1beta1/generated.proto + + It has these top-level messages: + PriorityClass + PriorityClassList +*/ +package v1beta1 + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" + +import strings "strings" +import reflect "reflect" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +func (m *PriorityClass) Reset() { *m = PriorityClass{} } +func (*PriorityClass) ProtoMessage() {} +func (*PriorityClass) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} } + +func (m *PriorityClassList) Reset() { *m = PriorityClassList{} } +func (*PriorityClassList) ProtoMessage() {} +func (*PriorityClassList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} } + +func init() { + proto.RegisterType((*PriorityClass)(nil), "k8s.io.api.scheduling.v1beta1.PriorityClass") + proto.RegisterType((*PriorityClassList)(nil), "k8s.io.api.scheduling.v1beta1.PriorityClassList") +} +func (m *PriorityClass) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PriorityClass) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) + n1, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + dAtA[i] = 0x10 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Value)) + dAtA[i] = 0x18 + i++ + if m.GlobalDefault { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Description))) + i += copy(dAtA[i:], m.Description) + return i, nil +} + +func (m *PriorityClassList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PriorityClassList) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) + n2, err := m.ListMeta.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n2 + if len(m.Items) > 0 { + for _, msg := range m.Items { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *PriorityClass) Size() (n int) { + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + n += 1 + sovGenerated(uint64(m.Value)) + n += 2 + l = len(m.Description) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *PriorityClassList) Size() (n int) { + var l int + _ = l + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func sovGenerated(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozGenerated(x uint64) (n int) { + return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *PriorityClass) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PriorityClass{`, + `ObjectMeta:` + strings.Replace(strings.Replace(this.ObjectMeta.String(), "ObjectMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `GlobalDefault:` + fmt.Sprintf("%v", this.GlobalDefault) + `,`, + `Description:` + fmt.Sprintf("%v", this.Description) + `,`, + `}`, + }, "") + return s +} +func (this *PriorityClassList) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PriorityClassList{`, + `ListMeta:` + strings.Replace(strings.Replace(this.ListMeta.String(), "ListMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Items), "PriorityClass", "PriorityClass", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func valueToStringGenerated(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *PriorityClass) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PriorityClass: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PriorityClass: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + m.Value = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Value |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GlobalDefault", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.GlobalDefault = bool(v != 0) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PriorityClassList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PriorityClassList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PriorityClassList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, PriorityClass{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenerated(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthGenerated + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipGenerated(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow") +) + +func init() { + proto.RegisterFile("k8s.io/kubernetes/vendor/k8s.io/api/scheduling/v1beta1/generated.proto", fileDescriptorGenerated) +} + +var fileDescriptorGenerated = []byte{ + // 448 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x8b, 0xd3, 0x40, + 0x18, 0xc5, 0x33, 0x5d, 0x8b, 0x75, 0x4a, 0x41, 0x23, 0x42, 0x28, 0x38, 0x1b, 0xd6, 0x4b, 0x0e, + 0xee, 0x8c, 0x5d, 0x54, 0x04, 0x6f, 0x71, 0x51, 0x04, 0x45, 0xcd, 0xc1, 0x83, 0x78, 0x70, 0x92, + 0x7c, 0x9b, 0x8e, 0x4d, 0x32, 0x61, 0x66, 0x12, 0xd8, 0x9b, 0x67, 0x4f, 0xfe, 0x51, 0x1e, 0x7a, + 0xdc, 0xe3, 0x9e, 0x16, 0x1b, 0xff, 0x11, 0x49, 0x1a, 0x37, 0xad, 0x45, 0xdd, 0x5b, 0xe6, 0x7d, + 0xbf, 0xf7, 0xe6, 0xcb, 0x63, 0xf0, 0xf3, 0xc5, 0x13, 0x4d, 0x85, 0x64, 0x8b, 0x32, 0x04, 0x95, + 0x83, 0x01, 0xcd, 0x2a, 0xc8, 0x63, 0xa9, 0x58, 0x37, 0xe0, 0x85, 0x60, 0x3a, 0x9a, 0x43, 0x5c, + 0xa6, 0x22, 0x4f, 0x58, 0x35, 0x0b, 0xc1, 0xf0, 0x19, 0x4b, 0x20, 0x07, 0xc5, 0x0d, 0xc4, 0xb4, + 0x50, 0xd2, 0x48, 0xfb, 0xee, 0x1a, 0xa7, 0xbc, 0x10, 0xb4, 0xc7, 0x69, 0x87, 0x4f, 0x0f, 0x13, + 0x61, 0xe6, 0x65, 0x48, 0x23, 0x99, 0xb1, 0x44, 0x26, 0x92, 0xb5, 0xae, 0xb0, 0x3c, 0x69, 0x4f, + 0xed, 0xa1, 0xfd, 0x5a, 0xa7, 0x4d, 0x1f, 0xf6, 0x97, 0x67, 0x3c, 0x9a, 0x8b, 0x1c, 0xd4, 0x29, + 0x2b, 0x16, 0x49, 0x23, 0x68, 0x96, 0x81, 0xe1, 0xac, 0xda, 0xd9, 0x61, 0xca, 0xfe, 0xe6, 0x52, + 0x65, 0x6e, 0x44, 0x06, 0x3b, 0x86, 0xc7, 0xff, 0x33, 0x34, 0x7f, 0x92, 0xf1, 0x3f, 0x7d, 0x07, + 0x5f, 0x07, 0x78, 0xf2, 0x56, 0x09, 0xa9, 0x84, 0x39, 0x7d, 0x96, 0x72, 0xad, 0xed, 0x4f, 0x78, + 0xd4, 0x6c, 0x15, 0x73, 0xc3, 0x1d, 0xe4, 0x22, 0x6f, 0x7c, 0xf4, 0x80, 0xf6, 0x8d, 0x5c, 0x86, + 0xd3, 0x62, 0x91, 0x34, 0x82, 0xa6, 0x0d, 0x4d, 0xab, 0x19, 0x7d, 0x13, 0x7e, 0x86, 0xc8, 0xbc, + 0x06, 0xc3, 0x7d, 0x7b, 0x79, 0xb1, 0x6f, 0xd5, 0x17, 0xfb, 0xb8, 0xd7, 0x82, 0xcb, 0x54, 0xfb, + 0x1e, 0x1e, 0x56, 0x3c, 0x2d, 0xc1, 0x19, 0xb8, 0xc8, 0x1b, 0xfa, 0x93, 0x0e, 0x1e, 0xbe, 0x6f, + 0xc4, 0x60, 0x3d, 0xb3, 0x9f, 0xe2, 0x49, 0x92, 0xca, 0x90, 0xa7, 0xc7, 0x70, 0xc2, 0xcb, 0xd4, + 0x38, 0x7b, 0x2e, 0xf2, 0x46, 0xfe, 0x9d, 0x0e, 0x9e, 0xbc, 0xd8, 0x1c, 0x06, 0xdb, 0xac, 0xfd, + 0x08, 0x8f, 0x63, 0xd0, 0x91, 0x12, 0x85, 0x11, 0x32, 0x77, 0xae, 0xb9, 0xc8, 0xbb, 0xe1, 0xdf, + 0xee, 0xac, 0xe3, 0xe3, 0x7e, 0x14, 0x6c, 0x72, 0x07, 0xdf, 0x11, 0xbe, 0xb5, 0x55, 0xc6, 0x2b, + 0xa1, 0x8d, 0xfd, 0x71, 0xa7, 0x10, 0x7a, 0xb5, 0x42, 0x1a, 0x77, 0x5b, 0xc7, 0xcd, 0xee, 0xe6, + 0xd1, 0x6f, 0x65, 0xa3, 0x8c, 0x77, 0x78, 0x28, 0x0c, 0x64, 0xda, 0x19, 0xb8, 0x7b, 0xde, 0xf8, + 0xe8, 0x3e, 0xfd, 0xe7, 0xeb, 0xa3, 0x5b, 0xeb, 0xf5, 0xd5, 0xbd, 0x6c, 0x22, 0x82, 0x75, 0x92, + 0x7f, 0xb8, 0x5c, 0x11, 0xeb, 0x6c, 0x45, 0xac, 0xf3, 0x15, 0xb1, 0xbe, 0xd4, 0x04, 0x2d, 0x6b, + 0x82, 0xce, 0x6a, 0x82, 0xce, 0x6b, 0x82, 0x7e, 0xd4, 0x04, 0x7d, 0xfb, 0x49, 0xac, 0x0f, 0xd7, + 0xbb, 0xc8, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x41, 0x74, 0x8a, 0x60, 0x38, 0x03, 0x00, 0x00, +} diff --git a/vendor/k8s.io/api/scheduling/v1beta1/generated.proto b/vendor/k8s.io/api/scheduling/v1beta1/generated.proto new file mode 100644 index 000000000..0a9575503 --- /dev/null +++ b/vendor/k8s.io/api/scheduling/v1beta1/generated.proto @@ -0,0 +1,67 @@ +/* +Copyright 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. +*/ + + +// This file was autogenerated by go-to-protobuf. Do not edit it manually! + +syntax = 'proto2'; + +package k8s.io.api.scheduling.v1beta1; + +import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; + +// Package-wide variables from generator "generated". +option go_package = "v1beta1"; + +// PriorityClass defines mapping from a priority class name to the priority +// integer value. The value can be any valid integer. +message PriorityClass { + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // The value of this priority class. This is the actual priority that pods + // receive when they have the name of this class in their pod spec. + optional int32 value = 2; + + // globalDefault specifies whether this PriorityClass should be considered as + // the default priority for pods that do not have any priority class. + // Only one PriorityClass can be marked as `globalDefault`. However, if more than + // one PriorityClasses exists with their `globalDefault` field set to true, + // the smallest value of such global default PriorityClasses will be used as the default priority. + // +optional + optional bool globalDefault = 3; + + // description is an arbitrary string that usually provides guidelines on + // when this priority class should be used. + // +optional + optional string description = 4; +} + +// PriorityClassList is a collection of priority classes. +message PriorityClassList { + // Standard list metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + // items is the list of PriorityClasses + repeated PriorityClass items = 2; +} + diff --git a/vendor/k8s.io/api/scheduling/v1beta1/register.go b/vendor/k8s.io/api/scheduling/v1beta1/register.go new file mode 100644 index 000000000..fb26557bb --- /dev/null +++ b/vendor/k8s.io/api/scheduling/v1beta1/register.go @@ -0,0 +1,52 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "scheduling.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + localSchemeBuilder = &SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +// Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &PriorityClass{}, + &PriorityClassList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/k8s.io/api/scheduling/v1beta1/types.go b/vendor/k8s.io/api/scheduling/v1beta1/types.go new file mode 100644 index 000000000..a9aaa8665 --- /dev/null +++ b/vendor/k8s.io/api/scheduling/v1beta1/types.go @@ -0,0 +1,66 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PriorityClass defines mapping from a priority class name to the priority +// integer value. The value can be any valid integer. +type PriorityClass struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // The value of this priority class. This is the actual priority that pods + // receive when they have the name of this class in their pod spec. + Value int32 `json:"value" protobuf:"bytes,2,opt,name=value"` + + // globalDefault specifies whether this PriorityClass should be considered as + // the default priority for pods that do not have any priority class. + // Only one PriorityClass can be marked as `globalDefault`. However, if more than + // one PriorityClasses exists with their `globalDefault` field set to true, + // the smallest value of such global default PriorityClasses will be used as the default priority. + // +optional + GlobalDefault bool `json:"globalDefault,omitempty" protobuf:"bytes,3,opt,name=globalDefault"` + + // description is an arbitrary string that usually provides guidelines on + // when this priority class should be used. + // +optional + Description string `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PriorityClassList is a collection of priority classes. +type PriorityClassList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // items is the list of PriorityClasses + Items []PriorityClass `json:"items" protobuf:"bytes,2,rep,name=items"` +} diff --git a/vendor/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go new file mode 100644 index 000000000..c18f54a82 --- /dev/null +++ b/vendor/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go @@ -0,0 +1,52 @@ +/* +Copyright 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 v1beta1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-generated-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. +var map_PriorityClass = map[string]string{ + "": "PriorityClass defines mapping from a priority class name to the priority integer value. The value can be any valid integer.", + "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "value": "The value of this priority class. This is the actual priority that pods receive when they have the name of this class in their pod spec.", + "globalDefault": "globalDefault specifies whether this PriorityClass should be considered as the default priority for pods that do not have any priority class. Only one PriorityClass can be marked as `globalDefault`. However, if more than one PriorityClasses exists with their `globalDefault` field set to true, the smallest value of such global default PriorityClasses will be used as the default priority.", + "description": "description is an arbitrary string that usually provides guidelines on when this priority class should be used.", +} + +func (PriorityClass) SwaggerDoc() map[string]string { + return map_PriorityClass +} + +var map_PriorityClassList = map[string]string{ + "": "PriorityClassList is a collection of priority classes.", + "metadata": "Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "items": "items is the list of PriorityClasses", +} + +func (PriorityClassList) SwaggerDoc() map[string]string { + return map_PriorityClassList +} + +// AUTO-GENERATED FUNCTIONS END HERE diff --git a/vendor/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 000000000..6f68e4ac5 --- /dev/null +++ b/vendor/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,84 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PriorityClass) DeepCopyInto(out *PriorityClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PriorityClass. +func (in *PriorityClass) DeepCopy() *PriorityClass { + if in == nil { + return nil + } + out := new(PriorityClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PriorityClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PriorityClassList) DeepCopyInto(out *PriorityClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]PriorityClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PriorityClassList. +func (in *PriorityClassList) DeepCopy() *PriorityClassList { + if in == nil { + return nil + } + out := new(PriorityClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PriorityClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/vendor/k8s.io/api/settings/v1alpha1/generated.pb.go b/vendor/k8s.io/api/settings/v1alpha1/generated.pb.go index bfc6a5a11..15285bae5 100644 --- a/vendor/k8s.io/api/settings/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/api/settings/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -891,40 +891,39 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 556 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x8e, 0xd2, 0x4e, - 0x1c, 0xc7, 0xe9, 0xb2, 0x04, 0xfe, 0x03, 0x9b, 0xbf, 0x69, 0x3c, 0x34, 0xc4, 0x94, 0x95, 0x8b, - 0x9b, 0x18, 0x67, 0x64, 0xd7, 0x18, 0xbd, 0x36, 0xc1, 0xc4, 0x04, 0xe2, 0xa6, 0x24, 0x9b, 0x68, - 0x3c, 0x38, 0x94, 0x9f, 0xa5, 0x42, 0x67, 0x9a, 0x99, 0x69, 0x13, 0x6f, 0x3e, 0x82, 0x2f, 0xe0, - 0x93, 0xe8, 0x03, 0x70, 0xdc, 0xe3, 0x9e, 0x36, 0x52, 0x5f, 0xc4, 0x4c, 0x99, 0x02, 0x8a, 0x28, - 0xb7, 0xce, 0x8f, 0xef, 0xe7, 0x33, 0xbf, 0x2f, 0x2d, 0xea, 0xcf, 0x9e, 0x49, 0x1c, 0x71, 0x32, - 0x4b, 0xc7, 0x20, 0x18, 0x28, 0x90, 0x24, 0x03, 0x36, 0xe1, 0x82, 0x98, 0x1f, 0x68, 0x12, 0x11, - 0x09, 0x4a, 0x45, 0x2c, 0x94, 0x24, 0xeb, 0xd1, 0x79, 0x32, 0xa5, 0x3d, 0x12, 0x02, 0x03, 0x41, - 0x15, 0x4c, 0x70, 0x22, 0xb8, 0xe2, 0xf6, 0xbd, 0x55, 0x1a, 0xd3, 0x24, 0xc2, 0x65, 0x1a, 0x97, - 0xe9, 0xf6, 0xa3, 0x30, 0x52, 0xd3, 0x74, 0x8c, 0x03, 0x1e, 0x93, 0x90, 0x87, 0x9c, 0x14, 0xd0, - 0x38, 0x7d, 0x5f, 0x9c, 0x8a, 0x43, 0xf1, 0xb4, 0x92, 0xb5, 0xbb, 0x5b, 0x57, 0x07, 0x5c, 0x00, - 0xc9, 0x76, 0x2e, 0x6c, 0x3f, 0xd9, 0x64, 0x62, 0x1a, 0x4c, 0x23, 0x06, 0xe2, 0x23, 0x49, 0x66, - 0xa1, 0x1e, 0x48, 0x12, 0x83, 0xa2, 0x7f, 0xa2, 0xc8, 0x3e, 0x4a, 0xa4, 0x4c, 0x45, 0x31, 0xec, - 0x00, 0x4f, 0xff, 0x05, 0xc8, 0x60, 0x0a, 0x31, 0xdd, 0xe1, 0x2e, 0xf6, 0x71, 0xa9, 0x8a, 0xe6, - 0x24, 0x62, 0x4a, 0x2a, 0xf1, 0x3b, 0xd4, 0xfd, 0x66, 0xa1, 0xff, 0x2e, 0xf9, 0xe4, 0x52, 0x80, - 0x04, 0x65, 0xbf, 0x43, 0x0d, 0x5d, 0x63, 0x42, 0x15, 0x75, 0xac, 0x53, 0xeb, 0xac, 0x79, 0xfe, - 0x18, 0x6f, 0xfe, 0xe5, 0xb5, 0x15, 0x27, 0xb3, 0x50, 0x0f, 0x24, 0xd6, 0x69, 0x9c, 0xf5, 0xf0, - 0xab, 0xf1, 0x07, 0x08, 0xd4, 0x10, 0x14, 0xf5, 0xec, 0xc5, 0x6d, 0xa7, 0x92, 0xdf, 0x76, 0xd0, - 0x66, 0xe6, 0xaf, 0xad, 0xf6, 0x10, 0x1d, 0xcb, 0x04, 0x02, 0xe7, 0xa8, 0xb0, 0x3f, 0xc4, 0x7f, - 0x7b, 0x87, 0x78, 0xbd, 0xd8, 0x28, 0x81, 0xc0, 0x6b, 0x19, 0xf1, 0xb1, 0x3e, 0xf9, 0x85, 0xa6, - 0xfb, 0xd5, 0x42, 0x27, 0xeb, 0xd4, 0x20, 0x92, 0xca, 0x7e, 0xbb, 0x53, 0x01, 0x1f, 0x56, 0x41, - 0xd3, 0x45, 0x81, 0x3b, 0xe6, 0x9e, 0x46, 0x39, 0xd9, 0x5a, 0x7f, 0x80, 0x6a, 0x91, 0x82, 0x58, - 0x3a, 0x47, 0xa7, 0xd5, 0xb3, 0xe6, 0xf9, 0x83, 0x03, 0xf7, 0xf7, 0x4e, 0x8c, 0xb3, 0xf6, 0x52, - 0xd3, 0xfe, 0x4a, 0xd2, 0xfd, 0x52, 0xdd, 0xda, 0x5e, 0xb7, 0xb2, 0x29, 0x6a, 0x48, 0x98, 0x43, - 0xa0, 0xb8, 0x30, 0xdb, 0x5f, 0x1c, 0xb8, 0x3d, 0x1d, 0xc3, 0x7c, 0x64, 0xd0, 0x4d, 0x85, 0x72, - 0xe2, 0xaf, 0xb5, 0xf6, 0x73, 0x54, 0x05, 0x96, 0x99, 0x02, 0xed, 0xed, 0x02, 0xfa, 0xbb, 0xd7, - 0xae, 0x3e, 0xcb, 0xae, 0xa8, 0xf0, 0x9a, 0x46, 0x52, 0xed, 0xb3, 0xcc, 0xd7, 0x8c, 0x3d, 0x40, - 0x75, 0x60, 0xd9, 0x0b, 0xc1, 0x63, 0xa7, 0x5a, 0xe0, 0xf7, 0xf7, 0xe0, 0x3a, 0x32, 0xe2, 0xa9, - 0x08, 0xc0, 0xfb, 0xdf, 0x58, 0xea, 0x66, 0xec, 0x97, 0x0a, 0xbb, 0x8f, 0xea, 0x19, 0x9f, 0xa7, - 0x31, 0x48, 0xe7, 0x78, 0xff, 0x32, 0x57, 0x45, 0x64, 0xa3, 0x59, 0x9d, 0xa5, 0x5f, 0xb2, 0xf6, - 0x6b, 0xd4, 0x5a, 0x3d, 0x0e, 0x79, 0xca, 0x94, 0x74, 0x6a, 0x85, 0xab, 0xb3, 0xdf, 0x55, 0xe4, - 0xbc, 0xbb, 0x46, 0xd8, 0xda, 0x1a, 0x4a, 0xff, 0x17, 0x95, 0x87, 0x17, 0x4b, 0xb7, 0x72, 0xbd, - 0x74, 0x2b, 0x37, 0x4b, 0xb7, 0xf2, 0x29, 0x77, 0xad, 0x45, 0xee, 0x5a, 0xd7, 0xb9, 0x6b, 0xdd, - 0xe4, 0xae, 0xf5, 0x3d, 0x77, 0xad, 0xcf, 0x3f, 0xdc, 0xca, 0x9b, 0x46, 0xf9, 0xbe, 0x7f, 0x06, - 0x00, 0x00, 0xff, 0xff, 0x0e, 0x35, 0x98, 0xb5, 0xd9, 0x04, 0x00, 0x00, + // 542 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x8e, 0xd2, 0x40, + 0x1c, 0xc6, 0xe9, 0xb2, 0x04, 0x1c, 0xd8, 0x68, 0x1a, 0x0f, 0x0d, 0x31, 0x65, 0xe5, 0xe2, 0x26, + 0xc6, 0x19, 0x59, 0x8d, 0xd1, 0x6b, 0x13, 0x4c, 0x4c, 0x20, 0x6e, 0x4a, 0xb2, 0x89, 0xc6, 0x83, + 0x43, 0xf9, 0x5b, 0x2a, 0xb4, 0xd3, 0xcc, 0x4c, 0x9b, 0x78, 0xf3, 0x11, 0x7c, 0x01, 0x9f, 0x44, + 0x1f, 0x80, 0xe3, 0x1e, 0xf7, 0xb4, 0x91, 0xfa, 0x22, 0x66, 0x86, 0x29, 0xa0, 0x88, 0x72, 0x9b, + 0xff, 0x9f, 0xef, 0xfb, 0xcd, 0xf7, 0x31, 0x45, 0xfd, 0xd9, 0x73, 0x81, 0x23, 0x46, 0x66, 0xd9, + 0x18, 0x78, 0x02, 0x12, 0x04, 0xc9, 0x21, 0x99, 0x30, 0x4e, 0xcc, 0x0f, 0x34, 0x8d, 0x88, 0x00, + 0x29, 0xa3, 0x24, 0x14, 0x24, 0xef, 0xd1, 0x79, 0x3a, 0xa5, 0x3d, 0x12, 0x42, 0x02, 0x9c, 0x4a, + 0x98, 0xe0, 0x94, 0x33, 0xc9, 0xec, 0x7b, 0x2b, 0x35, 0xa6, 0x69, 0x84, 0x4b, 0x35, 0x2e, 0xd5, + 0xed, 0x47, 0x61, 0x24, 0xa7, 0xd9, 0x18, 0x07, 0x2c, 0x26, 0x21, 0x0b, 0x19, 0xd1, 0xa6, 0x71, + 0xf6, 0x41, 0x4f, 0x7a, 0xd0, 0xa7, 0x15, 0xac, 0xdd, 0xdd, 0xba, 0x3a, 0x60, 0x1c, 0x48, 0xbe, + 0x73, 0x61, 0xfb, 0xe9, 0x46, 0x13, 0xd3, 0x60, 0x1a, 0x25, 0xc0, 0x3f, 0x91, 0x74, 0x16, 0xaa, + 0x85, 0x20, 0x31, 0x48, 0xfa, 0x37, 0x17, 0xd9, 0xe7, 0xe2, 0x59, 0x22, 0xa3, 0x18, 0x76, 0x0c, + 0xcf, 0xfe, 0x67, 0x10, 0xc1, 0x14, 0x62, 0xfa, 0xa7, 0xaf, 0xfb, 0xdd, 0x42, 0xb7, 0x2e, 0xd8, + 0xe4, 0x82, 0x83, 0x00, 0x69, 0xbf, 0x47, 0x0d, 0x95, 0x68, 0x42, 0x25, 0x75, 0xac, 0x53, 0xeb, + 0xac, 0x79, 0xfe, 0x18, 0x6f, 0xfe, 0xb0, 0x35, 0x18, 0xa7, 0xb3, 0x50, 0x2d, 0x04, 0x56, 0x6a, + 0x9c, 0xf7, 0xf0, 0xeb, 0xf1, 0x47, 0x08, 0xe4, 0x10, 0x24, 0xf5, 0xec, 0xc5, 0x4d, 0xa7, 0x52, + 0xdc, 0x74, 0xd0, 0x66, 0xe7, 0xaf, 0xa9, 0xf6, 0x10, 0x1d, 0x8b, 0x14, 0x02, 0xe7, 0x48, 0xd3, + 0x1f, 0xe2, 0x7f, 0x3d, 0x07, 0x5e, 0x07, 0x1b, 0xa5, 0x10, 0x78, 0x2d, 0x03, 0x3e, 0x56, 0x93, + 0xaf, 0x31, 0xdd, 0x6f, 0x16, 0x3a, 0x59, 0xab, 0x06, 0x91, 0x90, 0xf6, 0xbb, 0x9d, 0x0a, 0xf8, + 0xb0, 0x0a, 0xca, 0xad, 0x0b, 0xdc, 0x31, 0xf7, 0x34, 0xca, 0xcd, 0x56, 0xfc, 0x01, 0xaa, 0x45, + 0x12, 0x62, 0xe1, 0x1c, 0x9d, 0x56, 0xcf, 0x9a, 0xe7, 0x0f, 0x0e, 0xcc, 0xef, 0x9d, 0x18, 0x66, + 0xed, 0x95, 0x72, 0xfb, 0x2b, 0x48, 0xf7, 0x6b, 0x75, 0x2b, 0xbd, 0x6a, 0x65, 0x53, 0xd4, 0x10, + 0x30, 0x87, 0x40, 0x32, 0x6e, 0xd2, 0x3f, 0x39, 0x30, 0x3d, 0x1d, 0xc3, 0x7c, 0x64, 0xac, 0x9b, + 0x0a, 0xe5, 0xc6, 0x5f, 0x63, 0xed, 0x17, 0xa8, 0x0a, 0x49, 0x6e, 0x0a, 0xb4, 0xb7, 0x0b, 0xa8, + 0x4f, 0x58, 0xb1, 0xfa, 0x49, 0x7e, 0x49, 0xb9, 0xd7, 0x34, 0x90, 0x6a, 0x3f, 0xc9, 0x7d, 0xe5, + 0xb1, 0x07, 0xa8, 0x0e, 0x49, 0xfe, 0x92, 0xb3, 0xd8, 0xa9, 0x6a, 0xfb, 0xfd, 0x3d, 0x76, 0x25, + 0x19, 0xb1, 0x8c, 0x07, 0xe0, 0xdd, 0x36, 0x94, 0xba, 0x59, 0xfb, 0x25, 0xc2, 0xee, 0xa3, 0x7a, + 0xce, 0xe6, 0x59, 0x0c, 0xc2, 0x39, 0xde, 0x1f, 0xe6, 0x52, 0x4b, 0x36, 0x98, 0xd5, 0x2c, 0xfc, + 0xd2, 0x6b, 0xbf, 0x41, 0xad, 0xd5, 0x71, 0xc8, 0xb2, 0x44, 0x0a, 0xa7, 0xa6, 0x59, 0x9d, 0xfd, + 0x2c, 0xad, 0xf3, 0xee, 0x1a, 0x60, 0x6b, 0x6b, 0x29, 0xfc, 0xdf, 0x50, 0x1e, 0x5e, 0x2c, 0xdd, + 0xca, 0xd5, 0xd2, 0xad, 0x5c, 0x2f, 0xdd, 0xca, 0xe7, 0xc2, 0xb5, 0x16, 0x85, 0x6b, 0x5d, 0x15, + 0xae, 0x75, 0x5d, 0xb8, 0xd6, 0x8f, 0xc2, 0xb5, 0xbe, 0xfc, 0x74, 0x2b, 0x6f, 0x1b, 0xe5, 0x7b, + 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x46, 0x15, 0xf2, 0x97, 0xa4, 0x04, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/settings/v1alpha1/generated.proto b/vendor/k8s.io/api/settings/v1alpha1/generated.proto index 098e8dd9b..d5534c4de 100644 --- a/vendor/k8s.io/api/settings/v1alpha1/generated.proto +++ b/vendor/k8s.io/api/settings/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/api/settings/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/api/settings/v1alpha1/types_swagger_doc_generated.go index 2a89e5566..508c452f1 100644 --- a/vendor/k8s.io/api/settings/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/settings/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_PodPreset = map[string]string{ "": "PodPreset is a policy resource that defines additional runtime requirements for a Pod.", } diff --git a/vendor/k8s.io/api/settings/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/api/settings/v1alpha1/zz_generated.deepcopy.go index 3fe7f6ca4..6397a88ab 100644 --- a/vendor/k8s.io/api/settings/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/settings/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/storage/v1/generated.pb.go b/vendor/k8s.io/api/storage/v1/generated.pb.go index 31988b70d..d43a98298 100644 --- a/vendor/k8s.io/api/storage/v1/generated.pb.go +++ b/vendor/k8s.io/api/storage/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -152,6 +152,18 @@ func (m *StorageClass) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(len(*m.VolumeBindingMode))) i += copy(dAtA[i:], *m.VolumeBindingMode) } + if len(m.AllowedTopologies) > 0 { + for _, msg := range m.AllowedTopologies { + dAtA[i] = 0x42 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -252,6 +264,12 @@ func (m *StorageClass) Size() (n int) { l = len(*m.VolumeBindingMode) n += 1 + l + sovGenerated(uint64(l)) } + if len(m.AllowedTopologies) > 0 { + for _, e := range m.AllowedTopologies { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -304,6 +322,7 @@ func (this *StorageClass) String() string { `MountOptions:` + fmt.Sprintf("%v", this.MountOptions) + `,`, `AllowVolumeExpansion:` + valueToStringGenerated(this.AllowVolumeExpansion) + `,`, `VolumeBindingMode:` + valueToStringGenerated(this.VolumeBindingMode) + `,`, + `AllowedTopologies:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedTopologies), "TopologySelectorTerm", "k8s_io_api_core_v1.TopologySelectorTerm", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -641,6 +660,37 @@ func (m *StorageClass) Unmarshal(dAtA []byte) error { s := VolumeBindingMode(dAtA[iNdEx:postIndex]) m.VolumeBindingMode = &s iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedTopologies", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedTopologies = append(m.AllowedTopologies, k8s_io_api_core_v1.TopologySelectorTerm{}) + if err := m.AllowedTopologies[len(m.AllowedTopologies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -883,44 +933,46 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 623 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x4f, 0x6f, 0xd3, 0x3c, - 0x18, 0x6f, 0xda, 0xb7, 0x2f, 0x9b, 0xbb, 0x89, 0x2e, 0x0c, 0x29, 0xea, 0x21, 0xa9, 0xc6, 0xa5, - 0x9a, 0x84, 0xb3, 0x6e, 0x03, 0x4d, 0x48, 0x20, 0x11, 0x34, 0x09, 0xa4, 0x4d, 0xab, 0x82, 0x34, - 0x21, 0xc4, 0x01, 0x37, 0x7d, 0xc8, 0x4c, 0x13, 0x3b, 0xb2, 0x9d, 0x40, 0x6f, 0x7c, 0x04, 0xce, - 0x7c, 0x14, 0x3e, 0xc1, 0x8e, 0x3b, 0xee, 0x14, 0xb1, 0xf0, 0x2d, 0x76, 0x42, 0x49, 0xca, 0x9a, - 0xad, 0x9d, 0xd8, 0x2d, 0xfe, 0xfd, 0xb3, 0x9f, 0x27, 0x3f, 0xf4, 0x62, 0xbc, 0x27, 0x31, 0xe5, - 0xf6, 0x38, 0x1e, 0x82, 0x60, 0xa0, 0x40, 0xda, 0x09, 0xb0, 0x11, 0x17, 0xf6, 0x94, 0x20, 0x11, - 0xb5, 0xa5, 0xe2, 0x82, 0xf8, 0x60, 0x27, 0x7d, 0xdb, 0x07, 0x06, 0x82, 0x28, 0x18, 0xe1, 0x48, - 0x70, 0xc5, 0xf5, 0x87, 0xa5, 0x0c, 0x93, 0x88, 0xe2, 0xa9, 0x0c, 0x27, 0xfd, 0xce, 0x63, 0x9f, - 0xaa, 0x93, 0x78, 0x88, 0x3d, 0x1e, 0xda, 0x3e, 0xf7, 0xb9, 0x5d, 0xa8, 0x87, 0xf1, 0xa7, 0xe2, - 0x54, 0x1c, 0x8a, 0xaf, 0x32, 0xa5, 0xb3, 0xb9, 0xf0, 0xb2, 0x21, 0x28, 0x32, 0x77, 0x63, 0x67, - 0x77, 0xa6, 0x0d, 0x89, 0x77, 0x42, 0x19, 0x88, 0x89, 0x1d, 0x8d, 0xfd, 0x1c, 0x90, 0x76, 0x08, - 0x8a, 0x2c, 0x78, 0x67, 0xc7, 0xbe, 0xcd, 0x25, 0x62, 0xa6, 0x68, 0x08, 0x73, 0x86, 0xa7, 0xff, - 0x32, 0x48, 0xef, 0x04, 0x42, 0x32, 0xe7, 0xdb, 0xb9, 0xcd, 0x17, 0x2b, 0x1a, 0xd8, 0x94, 0x29, - 0xa9, 0xc4, 0x4d, 0xd3, 0xc6, 0x8f, 0x26, 0x5a, 0x79, 0x5b, 0xce, 0xfd, 0x2a, 0x20, 0x52, 0xea, - 0x1f, 0xd1, 0x52, 0x3e, 0xc9, 0x88, 0x28, 0x62, 0x68, 0x5d, 0xad, 0xd7, 0xda, 0xde, 0xc2, 0xb3, - 0x4d, 0x5f, 0x05, 0xe3, 0x68, 0xec, 0xe7, 0x80, 0xc4, 0xb9, 0x1a, 0x27, 0x7d, 0x7c, 0x34, 0xfc, - 0x0c, 0x9e, 0x3a, 0x04, 0x45, 0x1c, 0xfd, 0x34, 0xb5, 0x6a, 0x59, 0x6a, 0xa1, 0x19, 0xe6, 0x5e, - 0xa5, 0xea, 0x4f, 0x50, 0x2b, 0x12, 0x3c, 0xa1, 0x92, 0x72, 0x06, 0xc2, 0xa8, 0x77, 0xb5, 0xde, - 0xb2, 0xf3, 0x60, 0x6a, 0x69, 0x0d, 0x66, 0x94, 0x5b, 0xd5, 0xe9, 0x3e, 0x42, 0x11, 0x11, 0x24, - 0x04, 0x05, 0x42, 0x1a, 0x8d, 0x6e, 0xa3, 0xd7, 0xda, 0xde, 0xc1, 0x0b, 0x4b, 0x80, 0xab, 0x13, - 0xe1, 0xc1, 0x95, 0x6b, 0x9f, 0x29, 0x31, 0x99, 0xbd, 0x6e, 0x46, 0xb8, 0x95, 0x68, 0x7d, 0x8c, - 0x56, 0x05, 0x78, 0x01, 0xa1, 0xe1, 0x80, 0x07, 0xd4, 0x9b, 0x18, 0xff, 0x15, 0x2f, 0xdc, 0xcf, - 0x52, 0x6b, 0xd5, 0xad, 0x12, 0x97, 0xa9, 0xb5, 0x55, 0xa9, 0x8f, 0xc7, 0x45, 0xde, 0x1d, 0x3c, - 0x00, 0x21, 0xa9, 0x54, 0xc0, 0xd4, 0x31, 0x0f, 0xe2, 0x10, 0xae, 0x79, 0xdc, 0xeb, 0xd9, 0xfa, - 0x2e, 0x5a, 0x09, 0x79, 0xcc, 0xd4, 0x51, 0xa4, 0x28, 0x67, 0xd2, 0x68, 0x76, 0x1b, 0xbd, 0x65, - 0xa7, 0x9d, 0xa5, 0xd6, 0xca, 0x61, 0x05, 0x77, 0xaf, 0xa9, 0xf4, 0x03, 0xb4, 0x4e, 0x82, 0x80, - 0x7f, 0x29, 0x2f, 0xd8, 0xff, 0x1a, 0x11, 0x96, 0x6f, 0xc9, 0xf8, 0xbf, 0xab, 0xf5, 0x96, 0x1c, - 0x23, 0x4b, 0xad, 0xf5, 0x97, 0x0b, 0x78, 0x77, 0xa1, 0x4b, 0x7f, 0x87, 0xd6, 0x92, 0x02, 0x72, - 0x28, 0x1b, 0x51, 0xe6, 0x1f, 0xf2, 0x11, 0x18, 0xf7, 0x8a, 0xa1, 0x37, 0xb3, 0xd4, 0x5a, 0x3b, - 0xbe, 0x49, 0x5e, 0x2e, 0x02, 0xdd, 0xf9, 0x90, 0xce, 0x73, 0x74, 0xff, 0xc6, 0xf6, 0xf5, 0x36, - 0x6a, 0x8c, 0x61, 0x52, 0x54, 0x6b, 0xd9, 0xcd, 0x3f, 0xf5, 0x75, 0xd4, 0x4c, 0x48, 0x10, 0x43, - 0xd9, 0x04, 0xb7, 0x3c, 0x3c, 0xab, 0xef, 0x69, 0x1b, 0x3f, 0x35, 0xd4, 0xae, 0xfe, 0xca, 0x03, - 0x2a, 0x95, 0xfe, 0x61, 0xae, 0xa0, 0xf8, 0x6e, 0x05, 0xcd, 0xdd, 0x45, 0x3d, 0xdb, 0xd3, 0x02, - 0x2c, 0xfd, 0x45, 0x2a, 0xe5, 0x7c, 0x8d, 0x9a, 0x54, 0x41, 0x28, 0x8d, 0x7a, 0x51, 0xb0, 0x47, - 0x77, 0x28, 0x98, 0xb3, 0x3a, 0xcd, 0x6b, 0xbe, 0xc9, 0x9d, 0x6e, 0x19, 0xe0, 0xf4, 0x4e, 0x2f, - 0xcc, 0xda, 0xd9, 0x85, 0x59, 0x3b, 0xbf, 0x30, 0x6b, 0xdf, 0x32, 0x53, 0x3b, 0xcd, 0x4c, 0xed, - 0x2c, 0x33, 0xb5, 0xf3, 0xcc, 0xd4, 0x7e, 0x65, 0xa6, 0xf6, 0xfd, 0xb7, 0x59, 0x7b, 0x5f, 0x4f, - 0xfa, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xee, 0x56, 0xcc, 0xfd, 0x0a, 0x05, 0x00, 0x00, + // 656 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xcd, 0x6e, 0xd3, 0x4a, + 0x14, 0x8e, 0x93, 0x9b, 0xde, 0x74, 0xd2, 0xea, 0x26, 0xbe, 0xbd, 0x92, 0x6f, 0x16, 0x4e, 0x54, + 0x36, 0x11, 0x12, 0xe3, 0xa6, 0x14, 0x54, 0x21, 0x81, 0x54, 0xa3, 0x4a, 0x20, 0xb5, 0x6a, 0xe4, + 0x56, 0x15, 0x42, 0x2c, 0x98, 0x38, 0x07, 0x77, 0x88, 0xed, 0x31, 0x33, 0x63, 0x43, 0x76, 0xbc, + 0x00, 0x12, 0xcf, 0xc3, 0x13, 0x74, 0xd9, 0x65, 0x57, 0x16, 0x35, 0x6f, 0xd1, 0x15, 0xf2, 0x0f, + 0x8d, 0x9b, 0x04, 0xd1, 0xdd, 0xcc, 0x77, 0xbe, 0xef, 0x3b, 0x33, 0xe7, 0x07, 0x3d, 0x9b, 0xec, + 0x0a, 0x4c, 0x99, 0x31, 0x09, 0x47, 0xc0, 0x7d, 0x90, 0x20, 0x8c, 0x08, 0xfc, 0x31, 0xe3, 0x46, + 0x11, 0x20, 0x01, 0x35, 0x84, 0x64, 0x9c, 0x38, 0x60, 0x44, 0x03, 0xc3, 0x01, 0x1f, 0x38, 0x91, + 0x30, 0xc6, 0x01, 0x67, 0x92, 0xa9, 0xff, 0xe5, 0x34, 0x4c, 0x02, 0x8a, 0x0b, 0x1a, 0x8e, 0x06, + 0x9d, 0x07, 0x0e, 0x95, 0x67, 0xe1, 0x08, 0xdb, 0xcc, 0x33, 0x1c, 0xe6, 0x30, 0x23, 0x63, 0x8f, + 0xc2, 0x77, 0xd9, 0x2d, 0xbb, 0x64, 0xa7, 0xdc, 0xa5, 0xb3, 0x59, 0x4a, 0x66, 0x33, 0xbe, 0x2c, + 0x53, 0x67, 0x67, 0xc6, 0xf1, 0x88, 0x7d, 0x46, 0x7d, 0xe0, 0x53, 0x23, 0x98, 0x38, 0x29, 0x20, + 0x0c, 0x0f, 0x24, 0x59, 0xa6, 0x32, 0x7e, 0xa7, 0xe2, 0xa1, 0x2f, 0xa9, 0x07, 0x0b, 0x82, 0xc7, + 0x7f, 0x12, 0x08, 0xfb, 0x0c, 0x3c, 0x32, 0xaf, 0xdb, 0xfc, 0xb2, 0x82, 0xd6, 0x8e, 0xf3, 0x02, + 0x3c, 0x77, 0x89, 0x10, 0xea, 0x5b, 0xd4, 0x48, 0x1f, 0x35, 0x26, 0x92, 0x68, 0x4a, 0x4f, 0xe9, + 0x37, 0xb7, 0xb7, 0xf0, 0xac, 0x58, 0x37, 0xde, 0x38, 0x98, 0x38, 0x29, 0x20, 0x70, 0xca, 0xc6, + 0xd1, 0x00, 0x1f, 0x8d, 0xde, 0x83, 0x2d, 0x0f, 0x41, 0x12, 0x53, 0x3d, 0x8f, 0xbb, 0x95, 0x24, + 0xee, 0xa2, 0x19, 0x66, 0xdd, 0xb8, 0xaa, 0x8f, 0x50, 0x33, 0xe0, 0x2c, 0xa2, 0x82, 0x32, 0x1f, + 0xb8, 0x56, 0xed, 0x29, 0xfd, 0x55, 0xf3, 0xdf, 0x42, 0xd2, 0x1c, 0xce, 0x42, 0x56, 0x99, 0xa7, + 0x3a, 0x08, 0x05, 0x84, 0x13, 0x0f, 0x24, 0x70, 0xa1, 0xd5, 0x7a, 0xb5, 0x7e, 0x73, 0xfb, 0x21, + 0x5e, 0xda, 0x47, 0x5c, 0xfe, 0x11, 0x1e, 0xde, 0xa8, 0xf6, 0x7d, 0xc9, 0xa7, 0xb3, 0xd7, 0xcd, + 0x02, 0x56, 0xc9, 0x5a, 0x9d, 0xa0, 0x75, 0x0e, 0xb6, 0x4b, 0xa8, 0x37, 0x64, 0x2e, 0xb5, 0xa7, + 0xda, 0x5f, 0xd9, 0x0b, 0xf7, 0x93, 0xb8, 0xbb, 0x6e, 0x95, 0x03, 0xd7, 0x71, 0x77, 0x6b, 0x71, + 0x02, 0xf0, 0x10, 0xb8, 0xa0, 0x42, 0x82, 0x2f, 0x4f, 0x99, 0x1b, 0x7a, 0x70, 0x4b, 0x63, 0xdd, + 0xf6, 0x56, 0x77, 0xd0, 0x9a, 0xc7, 0x42, 0x5f, 0x1e, 0x05, 0x92, 0x32, 0x5f, 0x68, 0xf5, 0x5e, + 0xad, 0xbf, 0x6a, 0xb6, 0x92, 0xb8, 0xbb, 0x76, 0x58, 0xc2, 0xad, 0x5b, 0x2c, 0xf5, 0x00, 0x6d, + 0x10, 0xd7, 0x65, 0x1f, 0xf3, 0x04, 0xfb, 0x9f, 0x02, 0xe2, 0xa7, 0x55, 0xd2, 0x56, 0x7a, 0x4a, + 0xbf, 0x61, 0x6a, 0x49, 0xdc, 0xdd, 0xd8, 0x5b, 0x12, 0xb7, 0x96, 0xaa, 0xd4, 0x57, 0xa8, 0x1d, + 0x65, 0x90, 0x49, 0xfd, 0x31, 0xf5, 0x9d, 0x43, 0x36, 0x06, 0xed, 0xef, 0xec, 0xd3, 0xf7, 0x93, + 0xb8, 0xdb, 0x3e, 0x9d, 0x0f, 0x5e, 0x2f, 0x03, 0xad, 0x45, 0x13, 0xf5, 0x03, 0x6a, 0x67, 0x19, + 0x61, 0x7c, 0xc2, 0x02, 0xe6, 0x32, 0x87, 0x82, 0xd0, 0x1a, 0x59, 0xeb, 0xfa, 0xe5, 0xd6, 0xa5, + 0xa5, 0x4b, 0xfb, 0x56, 0xb0, 0xa6, 0xc7, 0xe0, 0x82, 0x2d, 0x19, 0x3f, 0x01, 0xee, 0x99, 0xff, + 0x17, 0xfd, 0x6a, 0xef, 0xcd, 0x5b, 0x59, 0x8b, 0xee, 0x9d, 0xa7, 0xe8, 0x9f, 0xb9, 0x86, 0xab, + 0x2d, 0x54, 0x9b, 0xc0, 0x34, 0x9b, 0xe6, 0x55, 0x2b, 0x3d, 0xaa, 0x1b, 0xa8, 0x1e, 0x11, 0x37, + 0x84, 0x7c, 0xf8, 0xac, 0xfc, 0xf2, 0xa4, 0xba, 0xab, 0x6c, 0x7e, 0x53, 0x50, 0xab, 0x3c, 0x3d, + 0x07, 0x54, 0x48, 0xf5, 0xcd, 0xc2, 0x4e, 0xe0, 0xbb, 0xed, 0x44, 0xaa, 0xce, 0x36, 0xa2, 0x55, + 0xfc, 0xa1, 0xf1, 0x0b, 0x29, 0xed, 0xc3, 0x0b, 0x54, 0xa7, 0x12, 0x3c, 0xa1, 0x55, 0xb3, 0xc2, + 0xdc, 0xbb, 0xc3, 0x4c, 0x9b, 0xeb, 0x85, 0x5f, 0xfd, 0x65, 0xaa, 0xb4, 0x72, 0x03, 0xb3, 0x7f, + 0x7e, 0xa5, 0x57, 0x2e, 0xae, 0xf4, 0xca, 0xe5, 0x95, 0x5e, 0xf9, 0x9c, 0xe8, 0xca, 0x79, 0xa2, + 0x2b, 0x17, 0x89, 0xae, 0x5c, 0x26, 0xba, 0xf2, 0x3d, 0xd1, 0x95, 0xaf, 0x3f, 0xf4, 0xca, 0xeb, + 0x6a, 0x34, 0xf8, 0x19, 0x00, 0x00, 0xff, 0xff, 0x0d, 0x64, 0x41, 0x83, 0x40, 0x05, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/storage/v1/generated.proto b/vendor/k8s.io/api/storage/v1/generated.proto index 72b3ceb83..df9f1dc45 100644 --- a/vendor/k8s.io/api/storage/v1/generated.proto +++ b/vendor/k8s.io/api/storage/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,11 +21,10 @@ syntax = 'proto2'; package k8s.io.api.storage.v1; -import "k8s.io/api/storage/v1beta1/generated.proto"; +import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; @@ -70,6 +69,14 @@ message StorageClass { // the VolumeScheduling feature. // +optional optional string volumeBindingMode = 7; + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + repeated k8s.io.api.core.v1.TopologySelectorTerm allowedTopologies = 8; } // StorageClassList is a collection of storage classes. diff --git a/vendor/k8s.io/api/storage/v1/types.go b/vendor/k8s.io/api/storage/v1/types.go index 288d40abb..45bfa7681 100644 --- a/vendor/k8s.io/api/storage/v1/types.go +++ b/vendor/k8s.io/api/storage/v1/types.go @@ -66,6 +66,14 @@ type StorageClass struct { // the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode `json:"volumeBindingMode,omitempty" protobuf:"bytes,7,opt,name=volumeBindingMode"` + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + AllowedTopologies []v1.TopologySelectorTerm `json:"allowedTopologies,omitempty" protobuf:"bytes,8,rep,name=allowedTopologies"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/k8s.io/api/storage/v1/types_swagger_doc_generated.go b/vendor/k8s.io/api/storage/v1/types_swagger_doc_generated.go index 3eb9bdab7..1d6587047 100644 --- a/vendor/k8s.io/api/storage/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/storage/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_StorageClass = map[string]string{ "": "StorageClass describes the parameters for a class of storage for which PersistentVolumes can be dynamically provisioned.\n\nStorageClasses are non-namespaced; the name of the storage class according to etcd is in ObjectMeta.Name.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -36,6 +36,7 @@ var map_StorageClass = map[string]string{ "mountOptions": "Dynamically provisioned PersistentVolumes of this storage class are created with these mountOptions, e.g. [\"ro\", \"soft\"]. Not validated - mount of the PVs will simply fail if one is invalid.", "allowVolumeExpansion": "AllowVolumeExpansion shows whether the storage class allow volume expand", "volumeBindingMode": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature.", + "allowedTopologies": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", } func (StorageClass) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/api/storage/v1/zz_generated.deepcopy.go b/vendor/k8s.io/api/storage/v1/zz_generated.deepcopy.go index ccab05ccc..a1050134c 100644 --- a/vendor/k8s.io/api/storage/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/storage/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -69,6 +69,13 @@ func (in *StorageClass) DeepCopyInto(out *StorageClass) { **out = **in } } + if in.AllowedTopologies != nil { + in, out := &in.AllowedTopologies, &out.AllowedTopologies + *out = make([]core_v1.TopologySelectorTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/vendor/k8s.io/api/storage/v1alpha1/generated.pb.go b/vendor/k8s.io/api/storage/v1alpha1/generated.pb.go index 586a1b672..507b5c1d5 100644 --- a/vendor/k8s.io/api/storage/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/api/storage/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1472,52 +1472,49 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 745 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0x3d, 0x6f, 0xdb, 0x46, - 0x18, 0xc7, 0x45, 0x49, 0xb6, 0xe5, 0x53, 0x5f, 0x8c, 0x83, 0xd0, 0x0a, 0x2a, 0x40, 0x19, 0x9a, - 0xdc, 0xa2, 0x3e, 0x56, 0x76, 0x51, 0x18, 0xdd, 0x44, 0xd8, 0x43, 0x51, 0xcb, 0x2d, 0xe8, 0xa2, - 0x43, 0xdb, 0xa1, 0x27, 0xf2, 0x31, 0x45, 0x4b, 0x7c, 0xc1, 0xdd, 0x51, 0x88, 0xb7, 0x4c, 0x99, - 0xb3, 0xe5, 0x1b, 0xe4, 0xb3, 0x68, 0x8b, 0x47, 0x4f, 0x42, 0xcc, 0x7c, 0x8b, 0x2c, 0x09, 0x78, - 0x3c, 0x89, 0xb2, 0x29, 0x25, 0xb6, 0x37, 0x3e, 0xcf, 0x3d, 0xff, 0xdf, 0xf3, 0x76, 0x47, 0x74, - 0x3c, 0x3a, 0xe2, 0xc4, 0x0b, 0x8d, 0x51, 0x3c, 0x00, 0x16, 0x80, 0x00, 0x6e, 0x4c, 0x20, 0x70, - 0x42, 0x66, 0xa8, 0x03, 0x1a, 0x79, 0x06, 0x17, 0x21, 0xa3, 0x2e, 0x18, 0x93, 0x2e, 0x1d, 0x47, - 0x43, 0xda, 0x35, 0x5c, 0x08, 0x80, 0x51, 0x01, 0x0e, 0x89, 0x58, 0x28, 0x42, 0xfc, 0x5d, 0x16, - 0x4c, 0x68, 0xe4, 0x11, 0x15, 0x4c, 0xe6, 0xc1, 0xad, 0x7d, 0xd7, 0x13, 0xc3, 0x78, 0x40, 0xec, - 0xd0, 0x37, 0xdc, 0xd0, 0x0d, 0x0d, 0xa9, 0x19, 0xc4, 0x17, 0xd2, 0x92, 0x86, 0xfc, 0xca, 0x58, - 0xad, 0x7e, 0x9e, 0x18, 0x9e, 0x09, 0x08, 0xb8, 0x17, 0x06, 0x7c, 0x9f, 0x46, 0x1e, 0x07, 0x36, - 0x01, 0x66, 0x44, 0x23, 0x37, 0x3d, 0xe3, 0x77, 0x03, 0x8c, 0x49, 0x77, 0x00, 0xa2, 0x58, 0x5a, - 0xeb, 0xe7, 0x1c, 0xe7, 0x53, 0x7b, 0xe8, 0x05, 0xc0, 0xae, 0x72, 0x86, 0x0f, 0x82, 0x1a, 0x93, - 0xa2, 0xca, 0x58, 0xa7, 0x62, 0x71, 0x20, 0x3c, 0x1f, 0x0a, 0x82, 0x5f, 0x3e, 0x27, 0xe0, 0xf6, - 0x10, 0x7c, 0x5a, 0xd0, 0x1d, 0xae, 0xd3, 0xc5, 0xc2, 0x1b, 0x1b, 0x5e, 0x20, 0xb8, 0x60, 0xf7, - 0x45, 0x9d, 0xd7, 0x65, 0xb4, 0xf3, 0x77, 0x38, 0x8e, 0x7d, 0xe8, 0x09, 0x41, 0xed, 0xa1, 0x0f, - 0x81, 0xc0, 0xff, 0xa3, 0x5a, 0xda, 0x8d, 0x43, 0x05, 0x6d, 0x6a, 0xbb, 0xda, 0x5e, 0xfd, 0xe0, - 0x27, 0x92, 0xaf, 0x65, 0x01, 0x27, 0xd1, 0xc8, 0x4d, 0x1d, 0x9c, 0xa4, 0xd1, 0x64, 0xd2, 0x25, - 0x7f, 0x0c, 0x2e, 0xc1, 0x16, 0x7d, 0x10, 0xd4, 0xc4, 0xd3, 0x59, 0xbb, 0x94, 0xcc, 0xda, 0x28, - 0xf7, 0x59, 0x0b, 0x2a, 0x3e, 0x47, 0x55, 0x1e, 0x81, 0xdd, 0x2c, 0x4b, 0x7a, 0x97, 0x7c, 0x62, - 0xe9, 0xe4, 0x7e, 0x79, 0xe7, 0x11, 0xd8, 0xe6, 0x17, 0x0a, 0x5f, 0x4d, 0x2d, 0x4b, 0xc2, 0xf0, - 0xbf, 0x68, 0x93, 0x0b, 0x2a, 0x62, 0xde, 0xac, 0x48, 0xec, 0xe1, 0xe3, 0xb0, 0x52, 0x6a, 0x7e, - 0xa5, 0xc0, 0x9b, 0x99, 0x6d, 0x29, 0x64, 0x67, 0xaa, 0xa1, 0xc6, 0x7d, 0xc9, 0xa9, 0xc7, 0x05, - 0xfe, 0xaf, 0x30, 0x2c, 0xf2, 0xb0, 0x61, 0xa5, 0x6a, 0x39, 0xaa, 0x1d, 0x95, 0xb2, 0x36, 0xf7, - 0x2c, 0x0d, 0xca, 0x42, 0x1b, 0x9e, 0x00, 0x9f, 0x37, 0xcb, 0xbb, 0x95, 0xbd, 0xfa, 0xc1, 0xfe, - 0xa3, 0x5a, 0x32, 0xbf, 0x54, 0xe4, 0x8d, 0xdf, 0x52, 0x86, 0x95, 0xa1, 0x3a, 0x17, 0xe8, 0x9b, - 0x42, 0xf3, 0x61, 0xcc, 0x6c, 0xc0, 0xa7, 0xa8, 0x11, 0x01, 0xe3, 0x1e, 0x17, 0x10, 0x88, 0x2c, - 0xe6, 0x8c, 0xfa, 0x20, 0xfb, 0xda, 0x36, 0x9b, 0xc9, 0xac, 0xdd, 0xf8, 0x73, 0xc5, 0xb9, 0xb5, - 0x52, 0xd5, 0x79, 0xb3, 0x62, 0x64, 0xe9, 0xba, 0xf0, 0x8f, 0xa8, 0x46, 0xa5, 0x07, 0x98, 0x42, - 0x2f, 0x46, 0xd0, 0x53, 0x7e, 0x6b, 0x11, 0x21, 0xd7, 0x2a, 0xcb, 0x53, 0xb7, 0xe5, 0x91, 0x6b, - 0x95, 0xd2, 0xa5, 0xb5, 0x4a, 0xdb, 0x52, 0xc8, 0xb4, 0x94, 0x20, 0x74, 0xb2, 0x2e, 0x2b, 0x77, - 0x4b, 0x39, 0x53, 0x7e, 0x6b, 0x11, 0xd1, 0xf9, 0x50, 0x59, 0x31, 0x3a, 0x79, 0x3f, 0x96, 0x7a, - 0x72, 0x64, 0x4f, 0xb5, 0x42, 0x4f, 0xce, 0xa2, 0x27, 0x07, 0xbf, 0xd2, 0x10, 0xa6, 0x0b, 0x44, - 0x7f, 0x7e, 0x7f, 0xb2, 0x25, 0xff, 0xfe, 0x84, 0x7b, 0x4b, 0x7a, 0x05, 0xda, 0x49, 0x20, 0xd8, - 0x95, 0xd9, 0x52, 0x55, 0xe0, 0x62, 0x80, 0xb5, 0xa2, 0x04, 0x7c, 0x89, 0xea, 0x99, 0xf7, 0x84, - 0xb1, 0x90, 0xa9, 0x97, 0xb4, 0xf7, 0x80, 0x8a, 0x64, 0xbc, 0xa9, 0x27, 0xb3, 0x76, 0xbd, 0x97, - 0x03, 0xde, 0xcf, 0xda, 0xf5, 0xa5, 0x73, 0x6b, 0x19, 0x9e, 0xe6, 0x72, 0x20, 0xcf, 0x55, 0x7d, - 0x4a, 0xae, 0x63, 0x58, 0x9f, 0x6b, 0x09, 0xde, 0x3a, 0x41, 0xdf, 0xae, 0x19, 0x11, 0xde, 0x41, - 0x95, 0x11, 0x5c, 0x65, 0x37, 0xd1, 0x4a, 0x3f, 0x71, 0x03, 0x6d, 0x4c, 0xe8, 0x38, 0xce, 0x6e, - 0xdc, 0xb6, 0x95, 0x19, 0xbf, 0x96, 0x8f, 0xb4, 0xce, 0x0b, 0x0d, 0x2d, 0xe7, 0xc0, 0xa7, 0xa8, - 0x9a, 0xfe, 0x93, 0xd5, 0xcb, 0xff, 0xe1, 0x61, 0x2f, 0xff, 0x2f, 0xcf, 0x87, 0xfc, 0x0f, 0x96, - 0x5a, 0x96, 0xa4, 0xe0, 0xef, 0xd1, 0x96, 0x0f, 0x9c, 0x53, 0x57, 0x65, 0x36, 0xbf, 0x56, 0x41, - 0x5b, 0xfd, 0xcc, 0x6d, 0xcd, 0xcf, 0x4d, 0x32, 0xbd, 0xd5, 0x4b, 0xd7, 0xb7, 0x7a, 0xe9, 0xe6, - 0x56, 0x2f, 0x3d, 0x4f, 0x74, 0x6d, 0x9a, 0xe8, 0xda, 0x75, 0xa2, 0x6b, 0x37, 0x89, 0xae, 0xbd, - 0x4d, 0x74, 0xed, 0xe5, 0x3b, 0xbd, 0xf4, 0x4f, 0x6d, 0x3e, 0xb8, 0x8f, 0x01, 0x00, 0x00, 0xff, - 0xff, 0x68, 0x82, 0x7b, 0x73, 0x9e, 0x07, 0x00, 0x00, + // 704 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0x4d, 0x6f, 0xd3, 0x4c, + 0x10, 0xc7, 0xe3, 0x24, 0x6d, 0xd3, 0xcd, 0xf3, 0x52, 0xad, 0xa2, 0xe7, 0x89, 0x82, 0xe4, 0x54, + 0x39, 0x15, 0x44, 0xd7, 0xa4, 0x20, 0x54, 0x71, 0x8b, 0xd5, 0x1e, 0x10, 0x6d, 0x41, 0x5b, 0xc4, + 0x01, 0x38, 0xb0, 0xb1, 0xa7, 0x8e, 0x9b, 0xfa, 0x45, 0xbb, 0xeb, 0x48, 0xbd, 0x71, 0xe2, 0xcc, + 0x8d, 0x6f, 0xc0, 0x67, 0xc9, 0x8d, 0x1e, 0x7b, 0x8a, 0xa8, 0xf9, 0x16, 0x5c, 0x40, 0x5e, 0x6f, + 0x5e, 0x68, 0x52, 0x68, 0x7b, 0xf3, 0xcc, 0xce, 0xfc, 0x66, 0xe6, 0xbf, 0xb3, 0x46, 0x3b, 0xfd, + 0x6d, 0x41, 0xfc, 0xc8, 0xea, 0x27, 0x5d, 0xe0, 0x21, 0x48, 0x10, 0xd6, 0x00, 0x42, 0x37, 0xe2, + 0x96, 0x3e, 0x60, 0xb1, 0x6f, 0x09, 0x19, 0x71, 0xe6, 0x81, 0x35, 0x68, 0xb3, 0x93, 0xb8, 0xc7, + 0xda, 0x96, 0x07, 0x21, 0x70, 0x26, 0xc1, 0x25, 0x31, 0x8f, 0x64, 0x84, 0xef, 0xe4, 0xc1, 0x84, + 0xc5, 0x3e, 0xd1, 0xc1, 0x64, 0x1c, 0xdc, 0xd8, 0xf4, 0x7c, 0xd9, 0x4b, 0xba, 0xc4, 0x89, 0x02, + 0xcb, 0x8b, 0xbc, 0xc8, 0x52, 0x39, 0xdd, 0xe4, 0x48, 0x59, 0xca, 0x50, 0x5f, 0x39, 0xab, 0xf1, + 0x68, 0x5a, 0x38, 0x60, 0x4e, 0xcf, 0x0f, 0x81, 0x9f, 0x5a, 0x71, 0xdf, 0xcb, 0x1c, 0xc2, 0x0a, + 0x40, 0x32, 0x6b, 0x30, 0xd7, 0x41, 0xc3, 0xba, 0x2a, 0x8b, 0x27, 0xa1, 0xf4, 0x03, 0x98, 0x4b, + 0x78, 0xfc, 0xa7, 0x04, 0xe1, 0xf4, 0x20, 0x60, 0x97, 0xf3, 0x5a, 0x9f, 0x8b, 0x68, 0xed, 0x55, + 0x74, 0x92, 0x04, 0xd0, 0x91, 0x92, 0x39, 0xbd, 0x00, 0x42, 0x89, 0xdf, 0xa1, 0x4a, 0xd6, 0x98, + 0xcb, 0x24, 0xab, 0x1b, 0xeb, 0xc6, 0x46, 0x75, 0xeb, 0x01, 0x99, 0x4a, 0x32, 0xe1, 0x93, 0xb8, + 0xef, 0x65, 0x0e, 0x41, 0xb2, 0x68, 0x32, 0x68, 0x93, 0xe7, 0xdd, 0x63, 0x70, 0xe4, 0x3e, 0x48, + 0x66, 0xe3, 0xe1, 0xa8, 0x59, 0x48, 0x47, 0x4d, 0x34, 0xf5, 0xd1, 0x09, 0x15, 0x1f, 0xa2, 0xb2, + 0x88, 0xc1, 0xa9, 0x17, 0x15, 0xbd, 0x4d, 0x7e, 0x23, 0x38, 0xb9, 0xdc, 0xde, 0x61, 0x0c, 0x8e, + 0xfd, 0x97, 0xc6, 0x97, 0x33, 0x8b, 0x2a, 0x18, 0x7e, 0x83, 0x96, 0x85, 0x64, 0x32, 0x11, 0xf5, + 0x92, 0xc2, 0x3e, 0xbc, 0x19, 0x56, 0xa5, 0xda, 0xff, 0x68, 0xf0, 0x72, 0x6e, 0x53, 0x8d, 0x6c, + 0x0d, 0x0d, 0x54, 0xbb, 0x9c, 0xb2, 0xe7, 0x0b, 0x89, 0xdf, 0xce, 0x89, 0x45, 0xae, 0x27, 0x56, + 0x96, 0xad, 0xa4, 0x5a, 0xd3, 0x25, 0x2b, 0x63, 0xcf, 0x8c, 0x50, 0x14, 0x2d, 0xf9, 0x12, 0x02, + 0x51, 0x2f, 0xae, 0x97, 0x36, 0xaa, 0x5b, 0x9b, 0x37, 0x1a, 0xc9, 0xfe, 0x5b, 0x93, 0x97, 0x9e, + 0x66, 0x0c, 0x9a, 0xa3, 0x5a, 0x47, 0xe8, 0xbf, 0xb9, 0xe1, 0xa3, 0x84, 0x3b, 0x80, 0xf7, 0x50, + 0x2d, 0x06, 0x2e, 0x7c, 0x21, 0x21, 0x94, 0x79, 0xcc, 0x01, 0x0b, 0x40, 0xcd, 0xb5, 0x6a, 0xd7, + 0xd3, 0x51, 0xb3, 0xf6, 0x62, 0xc1, 0x39, 0x5d, 0x98, 0xd5, 0xfa, 0xb2, 0x40, 0xb2, 0xec, 0xba, + 0xf0, 0x7d, 0x54, 0x61, 0xca, 0x03, 0x5c, 0xa3, 0x27, 0x12, 0x74, 0xb4, 0x9f, 0x4e, 0x22, 0xd4, + 0xb5, 0xaa, 0xf6, 0xf4, 0xb6, 0xdc, 0xf0, 0x5a, 0x55, 0xea, 0xcc, 0xb5, 0x2a, 0x9b, 0x6a, 0x64, + 0xd6, 0x4a, 0x18, 0xb9, 0xf9, 0x94, 0xa5, 0x5f, 0x5b, 0x39, 0xd0, 0x7e, 0x3a, 0x89, 0x68, 0xfd, + 0x28, 0x2d, 0x90, 0x4e, 0xed, 0xc7, 0xcc, 0x4c, 0xae, 0x9a, 0xa9, 0x32, 0x37, 0x93, 0x3b, 0x99, + 0xc9, 0xc5, 0x9f, 0x0c, 0x84, 0xd9, 0x04, 0xb1, 0x3f, 0xde, 0x9f, 0xfc, 0x92, 0x9f, 0xdd, 0x62, + 0x6f, 0x49, 0x67, 0x8e, 0xb6, 0x1b, 0x4a, 0x7e, 0x6a, 0x37, 0x74, 0x17, 0x78, 0x3e, 0x80, 0x2e, + 0x68, 0x01, 0x1f, 0xa3, 0x6a, 0xee, 0xdd, 0xe5, 0x3c, 0xe2, 0xfa, 0x25, 0x6d, 0x5c, 0xa3, 0x23, + 0x15, 0x6f, 0x9b, 0xe9, 0xa8, 0x59, 0xed, 0x4c, 0x01, 0xdf, 0x47, 0xcd, 0xea, 0xcc, 0x39, 0x9d, + 0x85, 0x67, 0xb5, 0x5c, 0x98, 0xd6, 0x2a, 0xdf, 0xa6, 0xd6, 0x0e, 0x5c, 0x5d, 0x6b, 0x06, 0xde, + 0xd8, 0x45, 0xff, 0x5f, 0x21, 0x11, 0x5e, 0x43, 0xa5, 0x3e, 0x9c, 0xe6, 0x9b, 0x48, 0xb3, 0x4f, + 0x5c, 0x43, 0x4b, 0x03, 0x76, 0x92, 0xe4, 0x1b, 0xb7, 0x4a, 0x73, 0xe3, 0x49, 0x71, 0xdb, 0x68, + 0x7d, 0x30, 0xd0, 0x6c, 0x0d, 0xbc, 0x87, 0xca, 0xd9, 0xef, 0x55, 0xbf, 0xfc, 0x7b, 0xd7, 0x7b, + 0xf9, 0x2f, 0xfd, 0x00, 0xa6, 0x7f, 0xb0, 0xcc, 0xa2, 0x8a, 0x82, 0xef, 0xa2, 0x95, 0x00, 0x84, + 0x60, 0x9e, 0xae, 0x6c, 0xff, 0xab, 0x83, 0x56, 0xf6, 0x73, 0x37, 0x1d, 0x9f, 0xdb, 0x64, 0x78, + 0x61, 0x16, 0xce, 0x2e, 0xcc, 0xc2, 0xf9, 0x85, 0x59, 0x78, 0x9f, 0x9a, 0xc6, 0x30, 0x35, 0x8d, + 0xb3, 0xd4, 0x34, 0xce, 0x53, 0xd3, 0xf8, 0x9a, 0x9a, 0xc6, 0xc7, 0x6f, 0x66, 0xe1, 0x75, 0x65, + 0x2c, 0xdc, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x42, 0xba, 0xdb, 0x12, 0x1a, 0x07, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/storage/v1alpha1/generated.proto b/vendor/k8s.io/api/storage/v1alpha1/generated.proto index 289ef5f3e..ccb947540 100644 --- a/vendor/k8s.io/api/storage/v1alpha1/generated.proto +++ b/vendor/k8s.io/api/storage/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,11 +21,9 @@ syntax = 'proto2'; package k8s.io.api.storage.v1alpha1; -import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/api/storage/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/api/storage/v1alpha1/types_swagger_doc_generated.go index faca8e939..32d7dcc52 100644 --- a/vendor/k8s.io/api/storage/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/storage/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_VolumeAttachment = map[string]string{ "": "VolumeAttachment captures the intent to attach or detach the specified volume to/from the specified node.\n\nVolumeAttachment objects are non-namespaced.", "metadata": "Standard object metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/api/storage/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/api/storage/v1alpha1/zz_generated.deepcopy.go index 04221c67c..d1a53755b 100644 --- a/vendor/k8s.io/api/storage/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/storage/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/api/storage/v1beta1/generated.pb.go b/vendor/k8s.io/api/storage/v1beta1/generated.pb.go index 425d0e717..fed8c7a63 100644 --- a/vendor/k8s.io/api/storage/v1beta1/generated.pb.go +++ b/vendor/k8s.io/api/storage/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -188,6 +188,18 @@ func (m *StorageClass) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(len(*m.VolumeBindingMode))) i += copy(dAtA[i:], *m.VolumeBindingMode) } + if len(m.AllowedTopologies) > 0 { + for _, msg := range m.AllowedTopologies { + dAtA[i] = 0x42 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -524,6 +536,12 @@ func (m *StorageClass) Size() (n int) { l = len(*m.VolumeBindingMode) n += 1 + l + sovGenerated(uint64(l)) } + if len(m.AllowedTopologies) > 0 { + for _, e := range m.AllowedTopologies { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -657,6 +675,7 @@ func (this *StorageClass) String() string { `MountOptions:` + fmt.Sprintf("%v", this.MountOptions) + `,`, `AllowVolumeExpansion:` + valueToStringGenerated(this.AllowVolumeExpansion) + `,`, `VolumeBindingMode:` + valueToStringGenerated(this.VolumeBindingMode) + `,`, + `AllowedTopologies:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedTopologies), "TopologySelectorTerm", "k8s_io_api_core_v1.TopologySelectorTerm", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -1073,6 +1092,37 @@ func (m *StorageClass) Unmarshal(dAtA []byte) error { s := VolumeBindingMode(dAtA[iNdEx:postIndex]) m.VolumeBindingMode = &s iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedTopologies", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedTopologies = append(m.AllowedTopologies, k8s_io_api_core_v1.TopologySelectorTerm{}) + if err := m.AllowedTopologies[len(m.AllowedTopologies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -2145,67 +2195,67 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 977 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6f, 0x1b, 0x45, - 0x14, 0xcf, 0xc6, 0xf9, 0x1c, 0x27, 0x34, 0x1d, 0x22, 0xb0, 0x7c, 0x58, 0x47, 0xbe, 0x60, 0xaa, - 0x66, 0xb7, 0x09, 0x05, 0x45, 0x48, 0x1c, 0xb2, 0x25, 0x07, 0x50, 0xdc, 0x86, 0x29, 0xaa, 0x50, - 0xc5, 0x81, 0xc9, 0xee, 0xab, 0x33, 0xd8, 0xfb, 0xa1, 0x99, 0x59, 0xd3, 0xdc, 0x38, 0x71, 0xe6, - 0xc4, 0x95, 0x0b, 0xff, 0x07, 0x47, 0x72, 0x42, 0x3d, 0xf6, 0x64, 0x91, 0xe5, 0xbf, 0x88, 0x38, - 0xa0, 0x99, 0x9d, 0x78, 0xd7, 0x5e, 0x5b, 0x4d, 0x7a, 0xe8, 0x2d, 0xf3, 0xde, 0xfb, 0xfd, 0xde, - 0xd7, 0xef, 0xad, 0x83, 0x1e, 0xf5, 0x0f, 0x84, 0xc3, 0x62, 0xb7, 0x9f, 0x9e, 0x02, 0x8f, 0x40, - 0x82, 0x70, 0x87, 0x10, 0x05, 0x31, 0x77, 0x8d, 0x83, 0x26, 0xcc, 0x15, 0x32, 0xe6, 0xb4, 0x07, - 0xee, 0x70, 0xef, 0x14, 0x24, 0xdd, 0x73, 0x7b, 0x10, 0x01, 0xa7, 0x12, 0x02, 0x27, 0xe1, 0xb1, - 0x8c, 0x71, 0x33, 0x8f, 0x75, 0x68, 0xc2, 0x1c, 0x13, 0xeb, 0x98, 0xd8, 0xe6, 0x6e, 0x8f, 0xc9, - 0xb3, 0xf4, 0xd4, 0xf1, 0xe3, 0xd0, 0xed, 0xc5, 0xbd, 0xd8, 0xd5, 0x90, 0xd3, 0xf4, 0x85, 0x7e, - 0xe9, 0x87, 0xfe, 0x2b, 0xa7, 0x6a, 0xb6, 0x4b, 0x69, 0xfd, 0x98, 0xab, 0x9c, 0xd3, 0xe9, 0x9a, - 0xdd, 0x22, 0x06, 0x5e, 0x4a, 0x88, 0x04, 0x8b, 0x23, 0xb1, 0x4b, 0x13, 0x26, 0x80, 0x0f, 0x81, - 0xbb, 0x49, 0xbf, 0xa7, 0x7c, 0x62, 0x32, 0x60, 0x5e, 0xf5, 0xcd, 0x87, 0x05, 0x5d, 0x48, 0xfd, - 0x33, 0x16, 0x01, 0x3f, 0x2f, 0x38, 0x42, 0x90, 0x74, 0x56, 0x11, 0xee, 0x3c, 0x14, 0x4f, 0x23, - 0xc9, 0x42, 0xa8, 0x00, 0x3e, 0x7b, 0x13, 0x40, 0xf8, 0x67, 0x10, 0xd2, 0x0a, 0xee, 0x93, 0x79, - 0xb8, 0x54, 0xb2, 0x81, 0xcb, 0x22, 0x29, 0x24, 0x9f, 0x06, 0xb5, 0x7f, 0x5f, 0x46, 0x1b, 0x4f, - 0xf3, 0x4d, 0x3c, 0x1a, 0x50, 0x21, 0xf0, 0x0f, 0x68, 0x4d, 0x75, 0x12, 0x50, 0x49, 0x1b, 0xd6, - 0x8e, 0xd5, 0xa9, 0xef, 0x3f, 0x70, 0x8a, 0xad, 0x8d, 0x89, 0x9d, 0xa4, 0xdf, 0x53, 0x06, 0xe1, - 0xa8, 0x68, 0x67, 0xb8, 0xe7, 0x3c, 0x39, 0xfd, 0x11, 0x7c, 0xd9, 0x05, 0x49, 0x3d, 0x7c, 0x31, - 0x6a, 0x2d, 0x64, 0xa3, 0x16, 0x2a, 0x6c, 0x64, 0xcc, 0x8a, 0x3f, 0x45, 0xf5, 0x84, 0xc7, 0x43, - 0xa6, 0x86, 0x0d, 0xbc, 0xb1, 0xb8, 0x63, 0x75, 0xd6, 0xbd, 0xf7, 0x0d, 0xa4, 0x7e, 0x52, 0xb8, - 0x48, 0x39, 0x0e, 0x0f, 0x10, 0x4a, 0x28, 0xa7, 0x21, 0x48, 0xe0, 0xa2, 0x51, 0xdb, 0xa9, 0x75, - 0xea, 0xfb, 0x07, 0xce, 0x7c, 0x41, 0x39, 0xe5, 0xb6, 0x9c, 0x93, 0x31, 0xf4, 0x28, 0x92, 0xfc, - 0xbc, 0x28, 0xb1, 0x70, 0x90, 0x12, 0x3f, 0xee, 0xa3, 0x4d, 0x0e, 0xfe, 0x80, 0xb2, 0xf0, 0x24, - 0x1e, 0x30, 0xff, 0xbc, 0xb1, 0xa4, 0xcb, 0x3c, 0xca, 0x46, 0xad, 0x4d, 0x52, 0x76, 0x5c, 0x8d, - 0x5a, 0x0f, 0xaa, 0x52, 0x74, 0x4e, 0x80, 0x0b, 0x26, 0x24, 0x44, 0xf2, 0x59, 0x3c, 0x48, 0x43, - 0x98, 0xc0, 0x90, 0x49, 0x6e, 0xfc, 0x10, 0x6d, 0x84, 0x71, 0x1a, 0xc9, 0x27, 0x89, 0x54, 0x02, - 0x6c, 0x2c, 0xef, 0xd4, 0x3a, 0xeb, 0xde, 0x56, 0x36, 0x6a, 0x6d, 0x74, 0x4b, 0x76, 0x32, 0x11, - 0x85, 0x8f, 0xd1, 0x36, 0x1d, 0x0c, 0xe2, 0x9f, 0xf2, 0x04, 0x47, 0x2f, 0x13, 0xaa, 0xf5, 0xdb, - 0x58, 0xd9, 0xb1, 0x3a, 0x6b, 0x5e, 0x23, 0x1b, 0xb5, 0xb6, 0x0f, 0x67, 0xf8, 0xc9, 0x4c, 0x14, - 0xfe, 0x0e, 0xdd, 0x1d, 0x6a, 0x93, 0xc7, 0xa2, 0x80, 0x45, 0xbd, 0x6e, 0x1c, 0x40, 0x63, 0x55, - 0x37, 0x7d, 0x2f, 0x1b, 0xb5, 0xee, 0x3e, 0x9b, 0x76, 0x5e, 0xcd, 0x32, 0x92, 0x2a, 0x49, 0xf3, - 0x0b, 0x74, 0x67, 0x6a, 0xfa, 0x78, 0x0b, 0xd5, 0xfa, 0x70, 0xae, 0xf5, 0xb5, 0x4e, 0xd4, 0x9f, - 0x78, 0x1b, 0x2d, 0x0f, 0xe9, 0x20, 0x85, 0x5c, 0x0e, 0x24, 0x7f, 0x7c, 0xbe, 0x78, 0x60, 0xb5, - 0xff, 0xb4, 0xd0, 0x56, 0x79, 0x95, 0xc7, 0x4c, 0x48, 0xfc, 0x7d, 0x45, 0xa5, 0xce, 0xcd, 0x54, - 0xaa, 0xd0, 0x5a, 0xa3, 0x5b, 0x46, 0x00, 0x6b, 0xd7, 0x96, 0x92, 0x42, 0xbb, 0x68, 0x99, 0x49, - 0x08, 0x45, 0x63, 0x51, 0xab, 0xac, 0x73, 0x53, 0x95, 0x79, 0x9b, 0x86, 0x74, 0xf9, 0x2b, 0x05, - 0x27, 0x39, 0x4b, 0xfb, 0x8f, 0x45, 0xb4, 0x95, 0x4f, 0xea, 0x50, 0x4a, 0xea, 0x9f, 0x85, 0x10, - 0xc9, 0x77, 0x70, 0x67, 0x04, 0x2d, 0x89, 0x04, 0x7c, 0x3d, 0xd1, 0x49, 0xf6, 0x4a, 0x13, 0xd3, - 0xd5, 0x3d, 0x4d, 0xc0, 0xf7, 0x36, 0x0c, 0xfb, 0x92, 0x7a, 0x11, 0xcd, 0x85, 0x9f, 0xa3, 0x15, - 0x21, 0xa9, 0x4c, 0xd5, 0x01, 0x2a, 0xd6, 0xfd, 0x5b, 0xb1, 0x6a, 0xa4, 0xf7, 0x9e, 0xe1, 0x5d, - 0xc9, 0xdf, 0xc4, 0x30, 0xb6, 0xff, 0xb2, 0xd0, 0xf6, 0x34, 0xe4, 0x1d, 0x2c, 0xfb, 0x9b, 0xc9, - 0x65, 0xdf, 0xbf, 0x4d, 0x47, 0x73, 0x16, 0xfe, 0x02, 0x7d, 0x50, 0xe9, 0x3d, 0x4e, 0xb9, 0x0f, - 0xea, 0x66, 0x93, 0xa9, 0x2f, 0xc3, 0x63, 0x1a, 0x42, 0x7e, 0x09, 0xf9, 0xcd, 0x9e, 0xcc, 0xf0, - 0x93, 0x99, 0xa8, 0xf6, 0xdf, 0x33, 0x26, 0xa6, 0x96, 0x85, 0xef, 0xa3, 0x35, 0xaa, 0x2d, 0xc0, - 0x0d, 0xf5, 0x78, 0x02, 0x87, 0xc6, 0x4e, 0xc6, 0x11, 0x7a, 0xa9, 0xba, 0x3c, 0x23, 0x95, 0xdb, - 0x2d, 0x55, 0x23, 0x4b, 0x4b, 0xd5, 0x6f, 0x62, 0x18, 0x55, 0x25, 0x51, 0x1c, 0xe4, 0x4d, 0xd6, - 0x26, 0x2b, 0x79, 0x6c, 0xec, 0x64, 0x1c, 0xd1, 0xfe, 0xaf, 0x36, 0x63, 0x72, 0x5a, 0x1d, 0xa5, - 0x96, 0x02, 0xdd, 0xd2, 0x5a, 0xa5, 0xa5, 0x60, 0xdc, 0x52, 0x80, 0x7f, 0xb3, 0x10, 0xa6, 0x63, - 0x8a, 0xee, 0xb5, 0x7a, 0xf2, 0x15, 0x7f, 0x7d, 0x7b, 0xd1, 0x3a, 0x87, 0x15, 0xb2, 0xfc, 0x77, - 0xa4, 0x69, 0x8a, 0xc0, 0xd5, 0x00, 0x32, 0xa3, 0x02, 0xcc, 0x50, 0x3d, 0xb7, 0x1e, 0x71, 0x1e, - 0x73, 0x73, 0x45, 0x1f, 0xbd, 0xb9, 0x20, 0x1d, 0xee, 0xd9, 0xea, 0x17, 0xf2, 0xb0, 0xc0, 0x5f, - 0x8d, 0x5a, 0xf5, 0x92, 0x9f, 0x94, 0xb9, 0x55, 0xaa, 0x00, 0x8a, 0x54, 0x4b, 0x6f, 0x91, 0xea, - 0x4b, 0x98, 0x9f, 0xaa, 0xc4, 0xdd, 0x3c, 0x42, 0x1f, 0xce, 0x19, 0xd0, 0xad, 0x3e, 0xf5, 0xbf, - 0x58, 0xa8, 0x9c, 0x03, 0x1f, 0xa3, 0x25, 0xf5, 0x0f, 0x8f, 0x39, 0xfa, 0x7b, 0x37, 0x3b, 0xfa, - 0x6f, 0x59, 0x08, 0xc5, 0xb7, 0x4b, 0xbd, 0x88, 0x66, 0xc1, 0x1f, 0xa3, 0xd5, 0x10, 0x84, 0xa0, - 0x3d, 0x93, 0xd9, 0xbb, 0x63, 0x82, 0x56, 0xbb, 0xb9, 0x99, 0x5c, 0xfb, 0xbd, 0xdd, 0x8b, 0x4b, - 0x7b, 0xe1, 0xd5, 0xa5, 0xbd, 0xf0, 0xfa, 0xd2, 0x5e, 0xf8, 0x39, 0xb3, 0xad, 0x8b, 0xcc, 0xb6, - 0x5e, 0x65, 0xb6, 0xf5, 0x3a, 0xb3, 0xad, 0x7f, 0x32, 0xdb, 0xfa, 0xf5, 0x5f, 0x7b, 0xe1, 0xf9, - 0xaa, 0x99, 0xdb, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x4b, 0x7f, 0x8a, 0x3b, 0x1c, 0x0b, 0x00, - 0x00, + // 988 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4d, 0x6f, 0x1b, 0x45, + 0x18, 0xce, 0xc6, 0xf9, 0x70, 0xc6, 0x09, 0x4d, 0x86, 0x08, 0x8c, 0x0f, 0x76, 0xe4, 0x0b, 0xa6, + 0x6a, 0x77, 0x9b, 0xa8, 0xa0, 0x08, 0x89, 0x83, 0xb7, 0xe4, 0x00, 0x8a, 0xdb, 0x30, 0x89, 0x2a, + 0x54, 0x71, 0x60, 0xb2, 0xfb, 0x76, 0xb3, 0x78, 0x77, 0x67, 0x99, 0x19, 0x1b, 0x72, 0xe3, 0xc4, + 0x19, 0x71, 0xe0, 0x17, 0xf0, 0x3f, 0x38, 0x92, 0x13, 0xea, 0xb1, 0x27, 0x8b, 0x2c, 0xff, 0x22, + 0xe2, 0x80, 0x66, 0x76, 0x62, 0xaf, 0xbd, 0x0e, 0x6d, 0x7a, 0xe8, 0xcd, 0xef, 0xc7, 0xf3, 0xbc, + 0xdf, 0xb3, 0x46, 0x8f, 0xfa, 0xfb, 0xc2, 0x0e, 0x99, 0xd3, 0x1f, 0x9c, 0x02, 0x4f, 0x40, 0x82, + 0x70, 0x86, 0x90, 0xf8, 0x8c, 0x3b, 0xc6, 0x40, 0xd3, 0xd0, 0x11, 0x92, 0x71, 0x1a, 0x80, 0x33, + 0xdc, 0x3d, 0x05, 0x49, 0x77, 0x9d, 0x00, 0x12, 0xe0, 0x54, 0x82, 0x6f, 0xa7, 0x9c, 0x49, 0x86, + 0x1b, 0xb9, 0xaf, 0x4d, 0xd3, 0xd0, 0x36, 0xbe, 0xb6, 0xf1, 0x6d, 0xdc, 0x0f, 0x42, 0x79, 0x36, + 0x38, 0xb5, 0x3d, 0x16, 0x3b, 0x01, 0x0b, 0x98, 0xa3, 0x21, 0xa7, 0x83, 0xe7, 0x5a, 0xd2, 0x82, + 0xfe, 0x95, 0x53, 0x35, 0xda, 0x85, 0xb0, 0x1e, 0xe3, 0x2a, 0xe6, 0x6c, 0xb8, 0xc6, 0xc3, 0x89, + 0x4f, 0x4c, 0xbd, 0xb3, 0x30, 0x01, 0x7e, 0xee, 0xa4, 0xfd, 0x40, 0x29, 0x84, 0x13, 0x83, 0xa4, + 0xf3, 0x50, 0xce, 0x4d, 0x28, 0x3e, 0x48, 0x64, 0x18, 0x43, 0x09, 0xf0, 0xc9, 0xab, 0x00, 0xc2, + 0x3b, 0x83, 0x98, 0xce, 0xe2, 0xda, 0xbf, 0xae, 0xa0, 0xf5, 0xe3, 0xbc, 0x0b, 0x8f, 0x22, 0x2a, + 0x04, 0xfe, 0x16, 0x55, 0x55, 0x52, 0x3e, 0x95, 0xb4, 0x6e, 0xed, 0x58, 0x9d, 0xda, 0xde, 0x03, + 0x7b, 0xd2, 0xb1, 0x31, 0xb7, 0x9d, 0xf6, 0x03, 0xa5, 0x10, 0xb6, 0xf2, 0xb6, 0x87, 0xbb, 0xf6, + 0x93, 0xd3, 0xef, 0xc0, 0x93, 0x3d, 0x90, 0xd4, 0xc5, 0x17, 0xa3, 0xd6, 0x42, 0x36, 0x6a, 0xa1, + 0x89, 0x8e, 0x8c, 0x59, 0xf1, 0xc7, 0xa8, 0x96, 0x72, 0x36, 0x0c, 0x45, 0xc8, 0x12, 0xe0, 0xf5, + 0xc5, 0x1d, 0xab, 0xb3, 0xe6, 0xbe, 0x6b, 0x20, 0xb5, 0xa3, 0x89, 0x89, 0x14, 0xfd, 0x70, 0x84, + 0x50, 0x4a, 0x39, 0x8d, 0x41, 0x02, 0x17, 0xf5, 0xca, 0x4e, 0xa5, 0x53, 0xdb, 0xdb, 0xb7, 0x6f, + 0x1e, 0xa6, 0x5d, 0x2c, 0xcb, 0x3e, 0x1a, 0x43, 0x0f, 0x12, 0xc9, 0xcf, 0x27, 0x29, 0x4e, 0x0c, + 0xa4, 0xc0, 0x8f, 0xfb, 0x68, 0x83, 0x83, 0x17, 0xd1, 0x30, 0x3e, 0x62, 0x51, 0xe8, 0x9d, 0xd7, + 0x97, 0x74, 0x9a, 0x07, 0xd9, 0xa8, 0xb5, 0x41, 0x8a, 0x86, 0xab, 0x51, 0xeb, 0x41, 0x79, 0x0d, + 0xec, 0x23, 0xe0, 0x22, 0x14, 0x12, 0x12, 0xf9, 0x94, 0x45, 0x83, 0x18, 0xa6, 0x30, 0x64, 0x9a, + 0x1b, 0x3f, 0x44, 0xeb, 0x31, 0x1b, 0x24, 0xf2, 0x49, 0x2a, 0x43, 0x96, 0x88, 0xfa, 0xf2, 0x4e, + 0xa5, 0xb3, 0xe6, 0x6e, 0x66, 0xa3, 0xd6, 0x7a, 0xaf, 0xa0, 0x27, 0x53, 0x5e, 0xf8, 0x10, 0x6d, + 0xd3, 0x28, 0x62, 0x3f, 0xe4, 0x01, 0x0e, 0x7e, 0x4c, 0x69, 0xa2, 0x5a, 0x55, 0x5f, 0xd9, 0xb1, + 0x3a, 0x55, 0xb7, 0x9e, 0x8d, 0x5a, 0xdb, 0xdd, 0x39, 0x76, 0x32, 0x17, 0x85, 0xbf, 0x46, 0x5b, + 0x43, 0xad, 0x72, 0xc3, 0xc4, 0x0f, 0x93, 0xa0, 0xc7, 0x7c, 0xa8, 0xaf, 0xea, 0xa2, 0xef, 0x66, + 0xa3, 0xd6, 0xd6, 0xd3, 0x59, 0xe3, 0xd5, 0x3c, 0x25, 0x29, 0x93, 0xe0, 0xef, 0xd1, 0x96, 0x8e, + 0x08, 0xfe, 0x09, 0x4b, 0x59, 0xc4, 0x82, 0x10, 0x44, 0xbd, 0xaa, 0xe7, 0xd7, 0x29, 0xce, 0x4f, + 0xb5, 0x4e, 0x2d, 0x92, 0xf1, 0x3a, 0x3f, 0x86, 0x08, 0x3c, 0xc9, 0xf8, 0x09, 0xf0, 0xd8, 0xfd, + 0xc0, 0xcc, 0x6b, 0xab, 0x3b, 0x4b, 0x45, 0xca, 0xec, 0x8d, 0xcf, 0xd0, 0x9d, 0x99, 0x81, 0xe3, + 0x4d, 0x54, 0xe9, 0xc3, 0xb9, 0x5e, 0xe9, 0x35, 0xa2, 0x7e, 0xe2, 0x6d, 0xb4, 0x3c, 0xa4, 0xd1, + 0x00, 0xf2, 0x0d, 0x24, 0xb9, 0xf0, 0xe9, 0xe2, 0xbe, 0xd5, 0xfe, 0xc3, 0x42, 0x9b, 0xc5, 0xed, + 0x39, 0x0c, 0x85, 0xc4, 0xdf, 0x94, 0x0e, 0xc3, 0x7e, 0xbd, 0xc3, 0x50, 0x68, 0x7d, 0x16, 0x9b, + 0xa6, 0x86, 0xea, 0xb5, 0xa6, 0x70, 0x14, 0x3d, 0xb4, 0x1c, 0x4a, 0x88, 0x45, 0x7d, 0xb1, 0xdc, + 0x98, 0xff, 0x5b, 0x6c, 0x77, 0xc3, 0x90, 0x2e, 0x7f, 0xa1, 0xe0, 0x24, 0x67, 0x69, 0xff, 0xbe, + 0x88, 0x36, 0xf3, 0xe1, 0x74, 0xa5, 0xa4, 0xde, 0x59, 0x0c, 0x89, 0x7c, 0x0b, 0xa7, 0x4d, 0xd0, + 0x92, 0x48, 0xc1, 0xd3, 0x1d, 0x9d, 0x66, 0x2f, 0x15, 0x31, 0x9b, 0xdd, 0x71, 0x0a, 0x9e, 0xbb, + 0x6e, 0xd8, 0x97, 0x94, 0x44, 0x34, 0x17, 0x7e, 0x86, 0x56, 0x84, 0xa4, 0x72, 0xa0, 0x6e, 0x5e, + 0xb1, 0xee, 0xdd, 0x8a, 0x55, 0x23, 0xdd, 0x77, 0x0c, 0xef, 0x4a, 0x2e, 0x13, 0xc3, 0xd8, 0xfe, + 0xd3, 0x42, 0xdb, 0xb3, 0x90, 0xb7, 0x30, 0xec, 0xaf, 0xa6, 0x87, 0x7d, 0xef, 0x36, 0x15, 0xdd, + 0x30, 0xf0, 0xe7, 0xe8, 0xbd, 0x52, 0xed, 0x6c, 0xc0, 0x3d, 0x50, 0xcf, 0x44, 0x3a, 0xf3, 0x18, + 0x3d, 0xa6, 0x31, 0xe4, 0x97, 0x90, 0x3f, 0x13, 0x47, 0x73, 0xec, 0x64, 0x2e, 0xaa, 0xfd, 0xd7, + 0x9c, 0x8e, 0xa9, 0x61, 0xe1, 0x7b, 0xa8, 0x4a, 0xb5, 0x06, 0xb8, 0xa1, 0x1e, 0x77, 0xa0, 0x6b, + 0xf4, 0x64, 0xec, 0xa1, 0x87, 0xaa, 0xd3, 0x33, 0xab, 0x72, 0xbb, 0xa1, 0x6a, 0x64, 0x61, 0xa8, + 0x5a, 0x26, 0x86, 0x51, 0x65, 0x92, 0x30, 0x3f, 0x2f, 0xb2, 0x32, 0x9d, 0xc9, 0x63, 0xa3, 0x27, + 0x63, 0x8f, 0xf6, 0xbf, 0x95, 0x39, 0x9d, 0xd3, 0xdb, 0x51, 0x28, 0xc9, 0xd7, 0x25, 0x55, 0x4b, + 0x25, 0xf9, 0xe3, 0x92, 0x7c, 0xfc, 0x9b, 0x85, 0x30, 0x1d, 0x53, 0xf4, 0xae, 0xb7, 0x27, 0x1f, + 0xf1, 0x97, 0xb7, 0x5f, 0x5a, 0xbb, 0x5b, 0x22, 0xcb, 0x3f, 0x5d, 0x0d, 0x93, 0x04, 0x2e, 0x3b, + 0x90, 0x39, 0x19, 0xe0, 0x10, 0xd5, 0x72, 0xed, 0x01, 0xe7, 0x8c, 0x9b, 0x2b, 0xfa, 0xf0, 0xd5, + 0x09, 0x69, 0x77, 0xb7, 0xa9, 0x3e, 0xca, 0xdd, 0x09, 0xfe, 0x6a, 0xd4, 0xaa, 0x15, 0xec, 0xa4, + 0xc8, 0xad, 0x42, 0xf9, 0x30, 0x09, 0xb5, 0xf4, 0x06, 0xa1, 0x3e, 0x87, 0x9b, 0x43, 0x15, 0xb8, + 0x1b, 0x07, 0xe8, 0xfd, 0x1b, 0x1a, 0x74, 0xab, 0xa7, 0xfe, 0x67, 0x0b, 0x15, 0x63, 0xe0, 0x43, + 0xb4, 0xa4, 0xfe, 0x2e, 0x99, 0xa3, 0xbf, 0xfb, 0x7a, 0x47, 0x7f, 0x12, 0xc6, 0x30, 0x79, 0xbb, + 0x94, 0x44, 0x34, 0x0b, 0xfe, 0x08, 0xad, 0xc6, 0x20, 0x04, 0x0d, 0x4c, 0x64, 0xf7, 0x8e, 0x71, + 0x5a, 0xed, 0xe5, 0x6a, 0x72, 0x6d, 0x77, 0xef, 0x5f, 0x5c, 0x36, 0x17, 0x5e, 0x5c, 0x36, 0x17, + 0x5e, 0x5e, 0x36, 0x17, 0x7e, 0xca, 0x9a, 0xd6, 0x45, 0xd6, 0xb4, 0x5e, 0x64, 0x4d, 0xeb, 0x65, + 0xd6, 0xb4, 0xfe, 0xce, 0x9a, 0xd6, 0x2f, 0xff, 0x34, 0x17, 0x9e, 0xad, 0x9a, 0xbe, 0xfd, 0x17, + 0x00, 0x00, 0xff, 0xff, 0xb4, 0x63, 0x7e, 0xa7, 0x0b, 0x0b, 0x00, 0x00, } diff --git a/vendor/k8s.io/api/storage/v1beta1/generated.proto b/vendor/k8s.io/api/storage/v1beta1/generated.proto index 1c6db8d41..359b68634 100644 --- a/vendor/k8s.io/api/storage/v1beta1/generated.proto +++ b/vendor/k8s.io/api/storage/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,11 +22,9 @@ syntax = 'proto2'; package k8s.io.api.storage.v1beta1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; @@ -71,6 +69,14 @@ message StorageClass { // the VolumeScheduling feature. // +optional optional string volumeBindingMode = 7; + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + repeated k8s.io.api.core.v1.TopologySelectorTerm allowedTopologies = 8; } // StorageClassList is a collection of storage classes. diff --git a/vendor/k8s.io/api/storage/v1beta1/types.go b/vendor/k8s.io/api/storage/v1beta1/types.go index 99c9e4594..7ec1e908f 100644 --- a/vendor/k8s.io/api/storage/v1beta1/types.go +++ b/vendor/k8s.io/api/storage/v1beta1/types.go @@ -66,6 +66,14 @@ type StorageClass struct { // the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode `json:"volumeBindingMode,omitempty" protobuf:"bytes,7,opt,name=volumeBindingMode"` + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + AllowedTopologies []v1.TopologySelectorTerm `json:"allowedTopologies,omitempty" protobuf:"bytes,8,rep,name=allowedTopologies"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go index c9c20c453..423e7f271 100644 --- a/vendor/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_StorageClass = map[string]string{ "": "StorageClass describes the parameters for a class of storage for which PersistentVolumes can be dynamically provisioned.\n\nStorageClasses are non-namespaced; the name of the storage class according to etcd is in ObjectMeta.Name.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -36,6 +36,7 @@ var map_StorageClass = map[string]string{ "mountOptions": "Dynamically provisioned PersistentVolumes of this storage class are created with these mountOptions, e.g. [\"ro\", \"soft\"]. Not validated - mount of the PVs will simply fail if one is invalid.", "allowVolumeExpansion": "AllowVolumeExpansion shows whether the storage class allow volume expand", "volumeBindingMode": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature.", + "allowedTopologies": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", } func (StorageClass) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go index 9a6a7266d..7c7c8fde5 100644 --- a/vendor/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -69,6 +69,13 @@ func (in *StorageClass) DeepCopyInto(out *StorageClass) { **out = **in } } + if in.AllowedTopologies != nil { + in, out := &in.AllowedTopologies, &out.AllowedTopologies + *out = make([]v1.TopologySelectorTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/vendor/k8s.io/apiextensions-apiserver/Godeps/Godeps.json b/vendor/k8s.io/apiextensions-apiserver/Godeps/Godeps.json index 5f1736372..83bb43f6b 100644 --- a/vendor/k8s.io/apiextensions-apiserver/Godeps/Godeps.json +++ b/vendor/k8s.io/apiextensions-apiserver/Godeps/Godeps.json @@ -1,6 +1,6 @@ { "ImportPath": "k8s.io/apiextensions-apiserver", - "GoVersion": "go1.9", + "GoVersion": "go1.10", "GodepVersion": "v80", "Packages": [ "./..." @@ -372,7 +372,7 @@ }, { "ImportPath": "github.com/evanphx/json-patch", - "Rev": "944e07253867aacae43c04b2e6a239005443f33a" + "Rev": "94e38aa1586e8a6c8a75770bddf5ff84c48a106b" }, { "ImportPath": "github.com/ghodss/yaml", @@ -436,35 +436,35 @@ }, { "ImportPath": "github.com/golang/protobuf/jsonpb", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/struct", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -486,6 +486,14 @@ "ImportPath": "github.com/googleapis/gnostic/extensions", "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, { "ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus", "Rev": "2500245aa6110c562d17020fb31a2c133d737799" @@ -510,10 +518,6 @@ "ImportPath": "github.com/hashicorp/golang-lru/simplelru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" }, - { - "ImportPath": "github.com/howeyc/gopass", - "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" - }, { "ImportPath": "github.com/imdario/mergo", "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" @@ -528,7 +532,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/mailru/easyjson/buffer", @@ -546,10 +550,22 @@ "ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil", "Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a" }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, { "ImportPath": "github.com/pborman/uuid", "Rev": "ca53cad383cad2479bbba7f7a1a05797ec1386e4" }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" + }, { "ImportPath": "github.com/pmezard/go-difflib/difflib", "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d" @@ -584,7 +600,7 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Rev": "6644d46b81fa1831979c4cded0106e774e0ef0ab" + "Rev": "c439c4fa093711d42e1b01acb1235b52004753c1" }, { "ImportPath": "github.com/spf13/pflag", @@ -592,11 +608,11 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/stretchr/testify/require", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/ugorji/go/codec", @@ -608,15 +624,15 @@ }, { "ImportPath": "golang.org/x/crypto/bcrypt", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/blowfish", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/net/context", @@ -800,1271 +816,1287 @@ }, { "ImportPath": "k8s.io/api/admission/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/admissionregistration/v1alpha1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/admissionregistration/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/apps/v1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/apps/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/apps/v1beta2", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/authentication/v1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/authentication/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/authorization/v1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/authorization/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/autoscaling/v1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/autoscaling/v2beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/batch/v1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/batch/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/batch/v2alpha1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/certificates/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/core/v1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/events/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/extensions/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/networking/v1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/policy/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/rbac/v1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/rbac/v1alpha1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/rbac/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/scheduling/v1alpha1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" + }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/settings/v1alpha1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/storage/v1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/storage/v1alpha1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/api/storage/v1beta1", - "Rev": "8b7507fac302640dd5f1efbf9643199952cc58db" + "Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/equality", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/errors", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/meta", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/meta/table", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/resource", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/testing", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/validation", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/validation/path", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/validation", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/conversion", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/fields", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/labels", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/selection", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/types", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/cache", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/clock", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/diff", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/duration", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/errors", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/framer", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/intstr", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/json", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/net", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/rand", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/runtime", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/sets", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/uuid", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation/field", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/wait", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/waitgroup", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/yaml", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/version", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/pkg/watch", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", - "Rev": "17529ec7eadb8de8e7dc835201455f53571f655a" + "Rev": "def12e63c512da17043b4f0293f52d1006603d9f" }, { "ImportPath": "k8s.io/apiserver/pkg/admission", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/configuration", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/initializer", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/metrics", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/initialization", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" + }, + { + "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/generic", + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/namespace", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/request", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/rules", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/validating", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" - }, - { - "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/versioned", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/apis/apiserver", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/apis/apiserver/install", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/apis/audit", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/apis/audit/install", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/apis/audit/v1alpha1", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/apis/audit/v1beta1", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/apis/audit/validation", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/audit", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/audit/policy", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/authenticator", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/authenticatorfactory", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/group", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/request/anonymous", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/request/bearertoken", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/request/headerrequest", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/request/union", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/request/websocket", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/request/x509", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/serviceaccount", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/token/tokenfile", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authentication/user", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authorization/authorizer", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authorization/authorizerfactory", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/authorization/union", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/endpoints", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/endpoints/discovery", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/endpoints/filters", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/endpoints/handlers", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/endpoints/handlers/negotiation", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/endpoints/metrics", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/endpoints/openapi", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/endpoints/request", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/features", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/registry/generic", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/registry/generic/registry", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/registry/generic/testing", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/registry/rest", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/registry/rest/resttest", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server/filters", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server/healthz", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server/httplog", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server/mux", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server/options", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server/resourceconfig", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server/routes", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server/routes/data/swagger", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/server/storage", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/errors", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/etcd", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/etcd/etcdtest", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/etcd/metrics", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/etcd/testing", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/etcd/testing/testingcert", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/etcd/util", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/etcd3", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/etcd3/preflight", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/names", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/storagebackend", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/storagebackend/factory", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/testing", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/storage/value", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/util/feature", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" - }, - { - "ImportPath": "k8s.io/apiserver/pkg/util/feature/testing", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/util/flag", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/util/flushwriter", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/util/logs", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" + }, + { + "ImportPath": "k8s.io/apiserver/pkg/util/openapi", + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/util/trace", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/util/webhook", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/pkg/util/wsstream", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/plugin/pkg/audit/buffered", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/plugin/pkg/audit/log", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/plugin/pkg/audit/truncate", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/plugin/pkg/audit/webhook", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/plugin/pkg/authenticator/token/webhook", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/apiserver/plugin/pkg/authorizer/webhook", - "Rev": "8378ef881d4fa7d3ca5c5e7e5309592ec69b11e4" + "Rev": "386115dd78fde3efc2366cb381420a4dd0157348" }, { "ImportPath": "k8s.io/client-go/discovery", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/discovery/fake", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/dynamic", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/admissionregistration", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/admissionregistration/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/admissionregistration/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/apps", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/apps/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/apps/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/apps/v1beta2", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/autoscaling", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/autoscaling/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/autoscaling/v2beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/batch", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/batch/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/batch/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/batch/v2alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/certificates", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/certificates/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/core", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/core/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/events", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/events/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/extensions", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/extensions/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/internalinterfaces", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/networking", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/networking/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/policy", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/policy/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/rbac", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/rbac/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/rbac/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/rbac/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/scheduling", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/scheduling/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" + }, + { + "ImportPath": "k8s.io/client-go/informers/scheduling/v1beta1", + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/settings", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/settings/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/storage", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/storage/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/storage/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/informers/storage/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/scheme", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1beta2", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/authentication/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/authentication/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/authorization/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/authorization/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/autoscaling/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v2alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/core/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/events/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/extensions/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/networking/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/policy/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" + }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1", + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/settings/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/admissionregistration/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/admissionregistration/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/apps/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/apps/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/apps/v1beta2", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/autoscaling/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/autoscaling/v2beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/batch/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/batch/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/batch/v2alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/certificates/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/core/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/events/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/extensions/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/networking/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/policy/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/rbac/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/rbac/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/rbac/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/scheduling/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" + }, + { + "ImportPath": "k8s.io/client-go/listers/scheduling/v1beta1", + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/settings/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/storage/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/storage/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/listers/storage/v1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" + }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/pkg/version", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/plugin/pkg/client/auth/exec", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/rest", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/rest/watch", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" + }, + { + "ImportPath": "k8s.io/client-go/restmapper", + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/scale", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/scale/scheme", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/scale/scheme/appsint", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/scale/scheme/appsv1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/scale/scheme/appsv1beta2", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/scale/scheme/autoscalingv1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/scale/scheme/extensionsint", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/scale/scheme/extensionsv1beta1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/testing", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/third_party/forked/golang/template", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/tools/auth", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/tools/cache", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/tools/clientcmd", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/tools/clientcmd/api", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/tools/clientcmd/api/latest", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/tools/clientcmd/api/v1", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/tools/metrics", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/tools/pager", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/tools/reference", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/transport", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/util/buffer", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/util/cert", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" + }, + { + "ImportPath": "k8s.io/client-go/util/connrotation", + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/util/flowcontrol", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/util/homedir", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/util/integer", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/util/jsonpath", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/util/retry", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/client-go/util/workqueue", - "Rev": "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0" + "Rev": "2cefa64ff137e128daeddbd1775cd775708a05bf" }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/apiextensions-apiserver/OWNERS b/vendor/k8s.io/apiextensions-apiserver/OWNERS index e0cd3186f..d9cb557fc 100644 --- a/vendor/k8s.io/apiextensions-apiserver/OWNERS +++ b/vendor/k8s.io/apiextensions-apiserver/OWNERS @@ -2,6 +2,7 @@ reviewers: - deads2k - sttts - enisoc +- mbohlool approvers: - deads2k - lavalamp diff --git a/vendor/k8s.io/apiextensions-apiserver/SECURITY_CONTACTS b/vendor/k8s.io/apiextensions-apiserver/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/apiextensions-apiserver/artifacts/example/rc.yaml b/vendor/k8s.io/apiextensions-apiserver/artifacts/example/rc.yaml index 629abf870..86b5d3070 100644 --- a/vendor/k8s.io/apiextensions-apiserver/artifacts/example/rc.yaml +++ b/vendor/k8s.io/apiextensions-apiserver/artifacts/example/rc.yaml @@ -23,4 +23,4 @@ spec: - "--etcd-servers=http://localhost:2379" - "--audit-log-path=-" - name: etcd - image: quay.io/coreos/etcd:v3.1.12 + image: quay.io/coreos/etcd:v3.2.18 diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh index 3659ad330..ea26ad63c 100755 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/verify-codegen.sh b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/verify-codegen.sh index 9cc02a5a4..d02a6fa39 100755 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/verify-codegen.sh +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1/zz_generated.deepcopy.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1/zz_generated.deepcopy.go index a0399a5ca..50828809d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/clientset.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/clientset.go index 45745dd27..92ff15819 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/clientset.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,10 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package versioned import ( - glog "github.com/golang/glog" crv1 "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" @@ -72,7 +73,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/doc.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/doc.go index 7d2f4d80d..41721ca52 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // This package has the automatically generated clientset. package versioned diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/clientset_generated.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/clientset_generated.go index 2a03c770e..28089890d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package fake import ( @@ -39,11 +41,20 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil)) + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/doc.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/doc.go index 3fd8e1e2c..9b99e7167 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // This package has the automatically generated fake clientset. package fake diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/register.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/register.go index 4e6435d2a..fdcedd4c5 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/register.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package fake import ( @@ -49,5 +51,4 @@ func init() { // correctly. func AddToScheme(scheme *runtime.Scheme) { crv1.AddToScheme(scheme) - } diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/doc.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/doc.go index 3ec2200d0..7dc375616 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // This package contains the scheme of the automatically generated clientset. package scheme diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/register.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/register.go index 311152e38..74d8fa4d0 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/register.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package scheme import ( @@ -49,5 +51,4 @@ func init() { // correctly. func AddToScheme(scheme *runtime.Scheme) { crv1.AddToScheme(scheme) - } diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/cr_client.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/cr_client.go index 8c662905c..04e3930e1 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/cr_client.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/cr_client.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package v1 import ( @@ -28,7 +30,7 @@ type CrV1Interface interface { ExamplesGetter } -// CrV1Client is used to interact with features provided by the cr.client-go.k8s.io group. +// CrV1Client is used to interact with features provided by the cr.example.apiextensions.k8s.io group. type CrV1Client struct { restClient rest.Interface } diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/doc.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/doc.go index b6a2a4672..3af5d054f 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // This package has the automatically generated typed clients. package v1 diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/example.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/example.go index 66e0e1cff..a0cc33852 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/example.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/example.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package v1 import ( diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/doc.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/doc.go index c58fac35e..16f443990 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // Package fake has the automatically generated clients. package fake diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_cr_client.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_cr_client.go index b3f6247c4..5ce902313 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_cr_client.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_cr_client.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package fake import ( diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_example.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_example.go index 7a8dd94b9..2db7f5c1e 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_example.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_example.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package fake import ( @@ -32,9 +34,9 @@ type FakeExamples struct { ns string } -var examplesResource = schema.GroupVersionResource{Group: "cr.client-go.k8s.io", Version: "v1", Resource: "examples"} +var examplesResource = schema.GroupVersionResource{Group: "cr.example.apiextensions.k8s.io", Version: "v1", Resource: "examples"} -var examplesKind = schema.GroupVersionKind{Group: "cr.client-go.k8s.io", Version: "v1", Kind: "Example"} +var examplesKind = schema.GroupVersionKind{Group: "cr.example.apiextensions.k8s.io", Version: "v1", Kind: "Example"} // Get takes name of the example, and returns the corresponding example object, and an error if there is any. func (c *FakeExamples) Get(name string, options v1.GetOptions) (result *cr_v1.Example, err error) { @@ -60,7 +62,7 @@ func (c *FakeExamples) List(opts v1.ListOptions) (result *cr_v1.ExampleList, err if label == nil { label = labels.Everything() } - list := &cr_v1.ExampleList{} + list := &cr_v1.ExampleList{ListMeta: obj.(*cr_v1.ExampleList).ListMeta} for _, item := range obj.(*cr_v1.ExampleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/generated_expansion.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/generated_expansion.go index 70b162feb..755021ec4 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/generated_expansion.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package v1 type ExampleExpansion interface{} diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/interface.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/interface.go index 9366da3be..0c633e3ef 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/interface.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package cr @@ -30,15 +30,17 @@ type Interface interface { } type group struct { - internalinterfaces.SharedInformerFactory + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc } // New returns a new Interface. -func New(f internalinterfaces.SharedInformerFactory) Interface { - return &group{f} +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } // V1 returns a new v1.Interface. func (g *group) V1() v1.Interface { - return v1.New(g.SharedInformerFactory) + return v1.New(g.factory, g.namespace, g.tweakListOptions) } diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/example.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/example.go index 39918ff5a..50b563d39 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/example.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/example.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,11 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package v1 import ( + time "time" + cr_v1 "k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1" versioned "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned" internalinterfaces "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces" @@ -27,7 +29,6 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" - time "time" ) // ExampleInformer provides access to a shared informer and lister for @@ -38,19 +39,34 @@ type ExampleInformer interface { } type exampleInformer struct { - factory internalinterfaces.SharedInformerFactory + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string } // NewExampleInformer constructs a new informer for Example type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewExampleInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredExampleInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredExampleInformer constructs a new informer for Example type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredExampleInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } return client.CrV1().Examples(namespace).List(options) }, WatchFunc: func(options meta_v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } return client.CrV1().Examples(namespace).Watch(options) }, }, @@ -60,12 +76,12 @@ func NewExampleInformer(client versioned.Interface, namespace string, resyncPeri ) } -func defaultExampleInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewExampleInformer(client, meta_v1.NamespaceAll, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) +func (f *exampleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredExampleInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } func (f *exampleInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&cr_v1.Example{}, defaultExampleInformer) + return f.factory.InformerFor(&cr_v1.Example{}, f.defaultInformer) } func (f *exampleInformer) Lister() v1.ExampleLister { diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/interface.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/interface.go index 0612ce3bd..96ee1514c 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/interface.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package v1 @@ -29,15 +29,17 @@ type Interface interface { } type version struct { - internalinterfaces.SharedInformerFactory + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc } // New returns a new Interface. -func New(f internalinterfaces.SharedInformerFactory) Interface { - return &version{f} +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } // Examples returns a ExampleInformer. func (v *version) Examples() ExampleInformer { - return &exampleInformer{factory: v.SharedInformerFactory} + return &exampleInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go index f9ae8be12..67c55af39 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,26 +14,34 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package externalversions import ( + reflect "reflect" + sync "sync" + time "time" + versioned "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned" cr "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr" internalinterfaces "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" - reflect "reflect" - sync "sync" - time "time" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { - client versioned.Interface - lock sync.Mutex - defaultResync time.Duration + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -41,14 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -97,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer @@ -114,5 +176,5 @@ type SharedInformerFactory interface { } func (f *sharedInformerFactory) Cr() cr.Interface { - return cr.New(f) + return cr.New(f, f.namespace, f.tweakListOptions) } diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/generic.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/generic.go index 12390b7a9..2bf6c5a47 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/generic.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,12 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package externalversions import ( "fmt" + v1 "k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" @@ -51,7 +52,7 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=Cr, Version=V1 + // Group=cr.example.apiextensions.k8s.io, Version=v1 case v1.SchemeGroupVersion.WithResource("examples"): return &genericInformer{resource: resource.GroupResource(), informer: f.Cr().V1().Examples().Informer()}, nil diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index d8f00586b..5b81f037b 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,15 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package internalinterfaces import ( + time "time" + versioned "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" cache "k8s.io/client-go/tools/cache" - time "time" ) type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer @@ -32,3 +34,5 @@ type SharedInformerFactory interface { Start(stopCh <-chan struct{}) InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer } + +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/example.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/example.go index 554c9f2db..8a64d09cc 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/example.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/example.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by lister-gen +// Code generated by lister-gen. DO NOT EDIT. package v1 diff --git a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/expansion_generated.go b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/expansion_generated.go index 7397d6f6c..5291ebaec 100644 --- a/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/expansion_generated.go +++ b/vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by lister-gen +// Code generated by lister-gen. DO NOT EDIT. package v1 diff --git a/vendor/k8s.io/apiextensions-apiserver/hack/boilerplate.go.txt b/vendor/k8s.io/apiextensions-apiserver/hack/boilerplate.go.txt index 59e740c1e..b7c650da4 100644 --- a/vendor/k8s.io/apiextensions-apiserver/hack/boilerplate.go.txt +++ b/vendor/k8s.io/apiextensions-apiserver/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright YEAR The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/hack/build-image.sh b/vendor/k8s.io/apiextensions-apiserver/hack/build-image.sh index c9152a4de..d0d129078 100755 --- a/vendor/k8s.io/apiextensions-apiserver/hack/build-image.sh +++ b/vendor/k8s.io/apiextensions-apiserver/hack/build-image.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/apiextensions-apiserver/hack/update-codegen.sh b/vendor/k8s.io/apiextensions-apiserver/hack/update-codegen.sh index 9c98ebf4d..a586b48e0 100755 --- a/vendor/k8s.io/apiextensions-apiserver/hack/update-codegen.sh +++ b/vendor/k8s.io/apiextensions-apiserver/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh b/vendor/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh index f5835c425..ab43ba23d 100755 --- a/vendor/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh +++ b/vendor/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/apiextensions-apiserver/main.go b/vendor/k8s.io/apiextensions-apiserver/main.go index 7723e6513..09143ab6e 100644 --- a/vendor/k8s.io/apiextensions-apiserver/main.go +++ b/vendor/k8s.io/apiextensions-apiserver/main.go @@ -19,7 +19,6 @@ package main import ( "flag" "os" - "runtime" "github.com/golang/glog" @@ -32,10 +31,6 @@ func main() { logs.InitLogs() defer logs.FlushLogs() - if len(os.Getenv("GOMAXPROCS")) == 0 { - runtime.GOMAXPROCS(runtime.NumCPU()) - } - stopCh := genericapiserver.SetupSignalHandler() cmd := server.NewCommandStartCustomResourceDefinitionsServer(os.Stdout, os.Stderr, stopCh) cmd.Flags().AddGoFlagSet(flag.CommandLine) diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go index dd9680c36..37b4d1df9 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go @@ -16,6 +16,8 @@ limitations under the License. package apiextensions +import "k8s.io/apimachinery/pkg/runtime" + // TODO: Update this after a tag is created for interface fields in DeepCopy func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { if in == nil { @@ -26,14 +28,14 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { *out = *in if in.Default != nil { - defaultJSON := JSON(deepCopyJSON(*(in.Default))) + defaultJSON := JSON(runtime.DeepCopyJSONValue(*(in.Default))) out.Default = &(defaultJSON) } else { out.Default = nil } if in.Example != nil { - exampleJSON := JSON(deepCopyJSON(*(in.Example))) + exampleJSON := JSON(runtime.DeepCopyJSONValue(*(in.Example))) out.Example = &(exampleJSON) } else { out.Example = nil @@ -121,7 +123,7 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { if in.Enum != nil { out.Enum = make([]JSON, len(in.Enum)) for i := range in.Enum { - out.Enum[i] = deepCopyJSON(in.Enum[i]) + out.Enum[i] = runtime.DeepCopyJSONValue(in.Enum[i]) } } @@ -258,22 +260,3 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { return out } - -func deepCopyJSON(x interface{}) interface{} { - switch x := x.(type) { - case map[string]interface{}: - clone := make(map[string]interface{}, len(x)) - for k, v := range x { - clone[k] = deepCopyJSON(v) - } - return clone - case []interface{}: - clone := make([]interface{}, len(x)) - for i := range x { - clone[i] = deepCopyJSON(x[i]) - } - return clone - default: - return x - } -} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go index a7cfb0ae7..ff8cc0334 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go @@ -23,9 +23,12 @@ import ( "github.com/google/gofuzz" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" ) +var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() + // Funcs returns the fuzzer functions for the apiextensions apis. func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ @@ -42,6 +45,33 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 { obj.Names.ListKind = obj.Names.Kind + "List" } + if len(obj.Versions) == 0 && len(obj.Version) != 0 { + obj.Versions = []apiextensions.CustomResourceDefinitionVersion{ + { + Name: obj.Version, + Served: true, + Storage: true, + }, + } + } else if len(obj.Versions) != 0 { + obj.Version = obj.Versions[0].Name + } + if len(obj.AdditionalPrinterColumns) == 0 { + obj.AdditionalPrinterColumns = []apiextensions.CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"}, + } + } + }, + func(obj *apiextensions.CustomResourceDefinition, c fuzz.Continue) { + c.FuzzNoCustom(obj) + + if len(obj.Status.StoredVersions) == 0 { + for _, v := range obj.Spec.Versions { + if v.Storage && !apiextensions.IsStoredVersion(obj, v.Name) { + obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name) + } + } + } }, func(obj *apiextensions.JSONSchemaProps, c fuzz.Continue) { // we cannot use c.FuzzNoCustom because of the interface{} fields. So let's loop with reflection. @@ -81,6 +111,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { }, func(obj *apiextensions.JSONSchemaPropsOrBool, c fuzz.Continue) { if c.RandBool() { + obj.Allows = true obj.Schema = &apiextensions.JSONSchemaProps{} c.Fuzz(obj.Schema) } else { diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go index 8dc7f72d6..92cad7d9b 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go @@ -17,6 +17,7 @@ limitations under the License. package apiextensions import ( + "fmt" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -116,3 +117,33 @@ func CRDRemoveFinalizer(crd *CustomResourceDefinition, needle string) { } crd.Finalizers = newFinalizers } + +// HasServedCRDVersion returns true if `version` is in the list of CRD's versions and the Served flag is set. +func HasServedCRDVersion(crd *CustomResourceDefinition, version string) bool { + for _, v := range crd.Spec.Versions { + if v.Name == version { + return v.Served + } + } + return false +} + +// GetCRDStorageVersion returns the storage version for given CRD. +func GetCRDStorageVersion(crd *CustomResourceDefinition) (string, error) { + for _, v := range crd.Spec.Versions { + if v.Storage { + return v.Name, nil + } + } + // This should not happened if crd is valid + return "", fmt.Errorf("invalid CustomResourceDefinition, no storage version") +} + +func IsStoredVersion(crd *CustomResourceDefinition, version string) bool { + for _, v := range crd.Status.StoredVersions { + if version == v { + return true + } + } + return false +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go index 1abb49815..df58a7cbf 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go @@ -19,6 +19,7 @@ package apiextensions import ( "reflect" "testing" + "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -88,3 +89,333 @@ func TestCRDRemoveFinalizer(t *testing.T) { } } } + +func TestSetCRDCondition(t *testing.T) { + tests := []struct { + name string + crdCondition []CustomResourceDefinitionCondition + newCondition CustomResourceDefinitionCondition + expectedcrdCondition []CustomResourceDefinitionCondition + }{ + { + name: "test setCRDcondition when one condition", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + newCondition: CustomResourceDefinitionCondition{ + Type: Established, + Status: ConditionFalse, + Reason: "NotAccepted", + Message: "Not accepted", + LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC), + }, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionFalse, + Reason: "NotAccepted", + Message: "Not accepted", + LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC), + }, + }, + }, + { + name: "test setCRDcondition when two condition", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + newCondition: CustomResourceDefinitionCondition{ + Type: NamesAccepted, + Status: ConditionFalse, + Reason: "Conflicts", + Message: "conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC), + }, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionFalse, + Reason: "Conflicts", + Message: "conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC), + }, + }, + }, + { + name: "test setCRDcondition when condition needs to be appended", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + newCondition: CustomResourceDefinitionCondition{ + Type: Terminating, + Status: ConditionFalse, + Reason: "NeverEstablished", + Message: "resource was never established", + LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC), + }, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: Terminating, + Status: ConditionFalse, + Reason: "NeverEstablished", + Message: "resource was never established", + LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC), + }, + }, + }, + } + for _, tc := range tests { + crd := generateCRDwithCondition(tc.crdCondition) + SetCRDCondition(crd, tc.newCondition) + if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) { + t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions) + } + for i := range tc.expectedcrdCondition { + if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) { + t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions) + } + } + } +} + +func TestRemoveCRDCondition(t *testing.T) { + tests := []struct { + name string + crdCondition []CustomResourceDefinitionCondition + conditionType CustomResourceDefinitionConditionType + expectedcrdCondition []CustomResourceDefinitionCondition + }{ + { + name: "test remove CRDCondition when the conditionType meets", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: NamesAccepted, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2011, 1, 2, 0, 0, 0, 0, time.UTC), + }, + }, + }, + { + name: "test remove CRDCondition when the conditionType not meets", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: Terminating, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + }, + } + for _, tc := range tests { + crd := generateCRDwithCondition(tc.crdCondition) + RemoveCRDCondition(crd, tc.conditionType) + if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) { + t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions) + } + for i := range tc.expectedcrdCondition { + if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) { + t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions) + } + } + } +} + +func TestIsCRDConditionPresentAndEqual(t *testing.T) { + tests := []struct { + name string + crdCondition []CustomResourceDefinitionCondition + conditionType CustomResourceDefinitionConditionType + status ConditionStatus + expectresult bool + }{ + { + name: "test CRDCondition is not Present", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: Terminating, + status: ConditionTrue, + expectresult: false, + }, + { + name: "test CRDCondition is Present but not Equal", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: Established, + status: ConditionFalse, + expectresult: false, + }, + { + name: "test CRDCondition is Present and Equal", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: NamesAccepted, + status: ConditionTrue, + expectresult: true, + }, + } + for _, tc := range tests { + crd := generateCRDwithCondition(tc.crdCondition) + res := IsCRDConditionPresentAndEqual(crd, tc.conditionType, tc.status) + if res != tc.expectresult { + t.Errorf("%v expected %t, got %t", tc.name, tc.expectresult, res) + } + } +} + +func generateCRDwithCondition(conditions []CustomResourceDefinitionCondition) *CustomResourceDefinition { + testCRDObjectMeta := metav1.ObjectMeta{ + Name: "plural.group.com", + ResourceVersion: "12", + } + testCRDSpec := CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Scope: ResourceScope("Cluster"), + Names: CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + } + testCRDAcceptedNames := CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + } + return &CustomResourceDefinition{ + ObjectMeta: testCRDObjectMeta, + Spec: testCRDSpec, + Status: CustomResourceDefinitionStatus{ + AcceptedNames: testCRDAcceptedNames, + Conditions: conditions, + }, + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go index 25cee84d2..2fd04b77d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go @@ -19,25 +19,13 @@ package install import ( "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: apiextensions.GroupName, - RootScopedKinds: sets.NewString("CustomResourceDefinition"), - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: apiextensions.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(apiextensions.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go index 0deb7cbd0..6fc75154f 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go @@ -25,6 +25,9 @@ type CustomResourceDefinitionSpec struct { // Group is the group this resource belongs in Group string // Version is the version this resource belongs in + // Should be always first item in Versions field if provided. + // Optional, but at least one of Version or Versions must be set. + // Deprecated: Please use `Versions`. Version string // Names are the names used to describe this custom resource Names CustomResourceDefinitionNames @@ -34,6 +37,52 @@ type CustomResourceDefinitionSpec struct { Validation *CustomResourceValidation // Subresources describes the subresources for CustomResources Subresources *CustomResourceSubresources + // Versions is the list of all supported versions for this resource. + // If Version field is provided, this field is optional. + // Validation: All versions must use the same validation schema for now. i.e., top + // level Validation field is applied to all of these versions. + // Order: The version name will be used to compute the order. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing + // major version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. + Versions []CustomResourceDefinitionVersion + // AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column. + AdditionalPrinterColumns []CustomResourceColumnDefinition +} + +type CustomResourceDefinitionVersion struct { + // Name is the version name, e.g. “v1”, “v2beta1”, etc. + Name string + // Served is a flag enabling/disabling this version from being served via REST APIs + Served bool + // Storage flags the version as storage version. There must be exactly one flagged + // as storage version. + Storage bool +} + +// CustomResourceColumnDefinition specifies a column for server side printing. +type CustomResourceColumnDefinition struct { + // name is a human readable name for the column. + Name string + // type is an OpenAPI type definition for this column. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Type string + // format is an optional OpenAPI type definition for this column. The 'name' format is applied + // to the primary identifier column to assist in clients identifying column is the resource name. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Format string + // description is a human readable description of this column. + Description string + // priority is an integer defining the relative importance of this column compared to others. Lower + // numbers are considered higher priority. Columns that may be omitted in limited space scenarios + // should be given a higher priority. + Priority int32 + + // JSONPath is a simple JSON path, i.e. without array notation. + JSONPath string } // CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition @@ -115,6 +164,14 @@ type CustomResourceDefinitionStatus struct { // AcceptedNames are the names that are actually being used to serve discovery // They may be different than the names in spec. AcceptedNames CustomResourceDefinitionNames + + // StoredVersions are all versions of CustomResources that were ever persisted. Tracking these + // versions allows a migration path for stored versions in etcd. The field is mutable + // so the migration controller can first finish a migration to another version (i.e. + // that no old objects are left in the storage), and then remove the rest of the + // versions from this list. + // None of the versions in this list can be removed from the spec.Versions field. + StoredVersions []string } // CustomResourceCleanupFinalizer is the name of the finalizer which will delete instances of diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go index 903773ae2..f6a114e2b 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go @@ -236,22 +236,3 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { return out } - -func deepCopyJSON(x interface{}) interface{} { - switch x := x.(type) { - case map[string]interface{}: - clone := make(map[string]interface{}, len(x)) - for k, v := range x { - clone[k] = deepCopyJSON(v) - } - return clone - case []interface{}: - clone := make([]interface{}, len(x)) - for i := range x { - clone[i] = deepCopyJSON(x[i]) - } - return clone - default: - return x - } -} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go index edffaed55..e3235e870 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go @@ -19,9 +19,12 @@ package v1beta1 import ( "strings" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) +var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() + func addDefaultingFuncs(scheme *runtime.Scheme) error { scheme.AddTypeDefaultingFunc(&CustomResourceDefinition{}, func(obj interface{}) { SetDefaults_CustomResourceDefinition(obj.(*CustomResourceDefinition)) }) // TODO figure out why I can't seem to get my defaulter generated @@ -31,6 +34,14 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { func SetDefaults_CustomResourceDefinition(obj *CustomResourceDefinition) { SetDefaults_CustomResourceDefinitionSpec(&obj.Spec) + if len(obj.Status.StoredVersions) == 0 { + for _, v := range obj.Spec.Versions { + if v.Storage { + obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name) + break + } + } + } } func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) { @@ -43,4 +54,21 @@ func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 { obj.Names.ListKind = obj.Names.Kind + "List" } + // If there is no list of versions, create on using deprecated Version field. + if len(obj.Versions) == 0 && len(obj.Version) != 0 { + obj.Versions = []CustomResourceDefinitionVersion{{ + Name: obj.Version, + Storage: true, + Served: true, + }} + } + // For backward compatibility set the version field to the first item in versions list. + if len(obj.Version) == 0 && len(obj.Versions) != 0 { + obj.Version = obj.Versions[0].Name + } + if len(obj.AdditionalPrinterColumns) == 0 { + obj.AdditionalPrinterColumns = []CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"}, + } + } } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go index e7325da23..c771e61cb 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,12 +25,14 @@ limitations under the License. k8s.io/kubernetes/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto It has these top-level messages: + CustomResourceColumnDefinition CustomResourceDefinition CustomResourceDefinitionCondition CustomResourceDefinitionList CustomResourceDefinitionNames CustomResourceDefinitionSpec CustomResourceDefinitionStatus + CustomResourceDefinitionVersion CustomResourceSubresourceScale CustomResourceSubresourceStatus CustomResourceSubresources @@ -66,99 +68,113 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +func (m *CustomResourceColumnDefinition) Reset() { *m = CustomResourceColumnDefinition{} } +func (*CustomResourceColumnDefinition) ProtoMessage() {} +func (*CustomResourceColumnDefinition) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{0} +} + func (m *CustomResourceDefinition) Reset() { *m = CustomResourceDefinition{} } func (*CustomResourceDefinition) ProtoMessage() {} func (*CustomResourceDefinition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{0} + return fileDescriptorGenerated, []int{1} } func (m *CustomResourceDefinitionCondition) Reset() { *m = CustomResourceDefinitionCondition{} } func (*CustomResourceDefinitionCondition) ProtoMessage() {} func (*CustomResourceDefinitionCondition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{1} + return fileDescriptorGenerated, []int{2} } func (m *CustomResourceDefinitionList) Reset() { *m = CustomResourceDefinitionList{} } func (*CustomResourceDefinitionList) ProtoMessage() {} func (*CustomResourceDefinitionList) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{2} + return fileDescriptorGenerated, []int{3} } func (m *CustomResourceDefinitionNames) Reset() { *m = CustomResourceDefinitionNames{} } func (*CustomResourceDefinitionNames) ProtoMessage() {} func (*CustomResourceDefinitionNames) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{3} + return fileDescriptorGenerated, []int{4} } func (m *CustomResourceDefinitionSpec) Reset() { *m = CustomResourceDefinitionSpec{} } func (*CustomResourceDefinitionSpec) ProtoMessage() {} func (*CustomResourceDefinitionSpec) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{4} + return fileDescriptorGenerated, []int{5} } func (m *CustomResourceDefinitionStatus) Reset() { *m = CustomResourceDefinitionStatus{} } func (*CustomResourceDefinitionStatus) ProtoMessage() {} func (*CustomResourceDefinitionStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{5} + return fileDescriptorGenerated, []int{6} +} + +func (m *CustomResourceDefinitionVersion) Reset() { *m = CustomResourceDefinitionVersion{} } +func (*CustomResourceDefinitionVersion) ProtoMessage() {} +func (*CustomResourceDefinitionVersion) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{7} } func (m *CustomResourceSubresourceScale) Reset() { *m = CustomResourceSubresourceScale{} } func (*CustomResourceSubresourceScale) ProtoMessage() {} func (*CustomResourceSubresourceScale) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{6} + return fileDescriptorGenerated, []int{8} } func (m *CustomResourceSubresourceStatus) Reset() { *m = CustomResourceSubresourceStatus{} } func (*CustomResourceSubresourceStatus) ProtoMessage() {} func (*CustomResourceSubresourceStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{7} + return fileDescriptorGenerated, []int{9} } func (m *CustomResourceSubresources) Reset() { *m = CustomResourceSubresources{} } func (*CustomResourceSubresources) ProtoMessage() {} func (*CustomResourceSubresources) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{8} + return fileDescriptorGenerated, []int{10} } func (m *CustomResourceValidation) Reset() { *m = CustomResourceValidation{} } func (*CustomResourceValidation) ProtoMessage() {} func (*CustomResourceValidation) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{9} + return fileDescriptorGenerated, []int{11} } func (m *ExternalDocumentation) Reset() { *m = ExternalDocumentation{} } func (*ExternalDocumentation) ProtoMessage() {} -func (*ExternalDocumentation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} } +func (*ExternalDocumentation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } func (m *JSON) Reset() { *m = JSON{} } func (*JSON) ProtoMessage() {} -func (*JSON) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } +func (*JSON) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (m *JSONSchemaProps) Reset() { *m = JSONSchemaProps{} } func (*JSONSchemaProps) ProtoMessage() {} -func (*JSONSchemaProps) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } +func (*JSONSchemaProps) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } func (m *JSONSchemaPropsOrArray) Reset() { *m = JSONSchemaPropsOrArray{} } func (*JSONSchemaPropsOrArray) ProtoMessage() {} -func (*JSONSchemaPropsOrArray) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } +func (*JSONSchemaPropsOrArray) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } func (m *JSONSchemaPropsOrBool) Reset() { *m = JSONSchemaPropsOrBool{} } func (*JSONSchemaPropsOrBool) ProtoMessage() {} -func (*JSONSchemaPropsOrBool) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } +func (*JSONSchemaPropsOrBool) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } func (m *JSONSchemaPropsOrStringArray) Reset() { *m = JSONSchemaPropsOrStringArray{} } func (*JSONSchemaPropsOrStringArray) ProtoMessage() {} func (*JSONSchemaPropsOrStringArray) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{15} + return fileDescriptorGenerated, []int{17} } func init() { + proto.RegisterType((*CustomResourceColumnDefinition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition") proto.RegisterType((*CustomResourceDefinition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition") proto.RegisterType((*CustomResourceDefinitionCondition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition") proto.RegisterType((*CustomResourceDefinitionList)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionList") proto.RegisterType((*CustomResourceDefinitionNames)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames") proto.RegisterType((*CustomResourceDefinitionSpec)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionSpec") proto.RegisterType((*CustomResourceDefinitionStatus)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus") + proto.RegisterType((*CustomResourceDefinitionVersion)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion") proto.RegisterType((*CustomResourceSubresourceScale)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceScale") proto.RegisterType((*CustomResourceSubresourceStatus)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceStatus") proto.RegisterType((*CustomResourceSubresources)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresources") @@ -170,6 +186,47 @@ func init() { proto.RegisterType((*JSONSchemaPropsOrBool)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool") proto.RegisterType((*JSONSchemaPropsOrStringArray)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray") } +func (m *CustomResourceColumnDefinition) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CustomResourceColumnDefinition) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Type))) + i += copy(dAtA[i:], m.Type) + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Format))) + i += copy(dAtA[i:], m.Format) + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Description))) + i += copy(dAtA[i:], m.Description) + dAtA[i] = 0x28 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Priority)) + dAtA[i] = 0x32 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.JSONPath))) + i += copy(dAtA[i:], m.JSONPath) + return i, nil +} + func (m *CustomResourceDefinition) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -411,6 +468,30 @@ func (m *CustomResourceDefinitionSpec) MarshalTo(dAtA []byte) (int, error) { } i += n8 } + if len(m.Versions) > 0 { + for _, msg := range m.Versions { + dAtA[i] = 0x3a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.AdditionalPrinterColumns) > 0 { + for _, msg := range m.AdditionalPrinterColumns { + dAtA[i] = 0x42 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -449,6 +530,59 @@ func (m *CustomResourceDefinitionStatus) MarshalTo(dAtA []byte) (int, error) { return 0, err } i += n9 + if len(m.StoredVersions) > 0 { + for _, s := range m.StoredVersions { + dAtA[i] = 0x1a + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + +func (m *CustomResourceDefinitionVersion) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CustomResourceDefinitionVersion) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + dAtA[i] = 0x10 + i++ + if m.Served { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + dAtA[i] = 0x18 + i++ + if m.Storage { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -1184,6 +1318,23 @@ func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return offset + 1 } +func (m *CustomResourceColumnDefinition) Size() (n int) { + var l int + _ = l + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Type) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Format) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Description) + n += 1 + l + sovGenerated(uint64(l)) + n += 1 + sovGenerated(uint64(m.Priority)) + l = len(m.JSONPath) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *CustomResourceDefinition) Size() (n int) { var l int _ = l @@ -1271,6 +1422,18 @@ func (m *CustomResourceDefinitionSpec) Size() (n int) { l = m.Subresources.Size() n += 1 + l + sovGenerated(uint64(l)) } + if len(m.Versions) > 0 { + for _, e := range m.Versions { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + if len(m.AdditionalPrinterColumns) > 0 { + for _, e := range m.AdditionalPrinterColumns { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -1285,6 +1448,22 @@ func (m *CustomResourceDefinitionStatus) Size() (n int) { } l = m.AcceptedNames.Size() n += 1 + l + sovGenerated(uint64(l)) + if len(m.StoredVersions) > 0 { + for _, s := range m.StoredVersions { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *CustomResourceDefinitionVersion) Size() (n int) { + var l int + _ = l + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + n += 2 + n += 2 return n } @@ -1556,6 +1735,21 @@ func sovGenerated(x uint64) (n int) { func sozGenerated(x uint64) (n int) { return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (this *CustomResourceColumnDefinition) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CustomResourceColumnDefinition{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `Format:` + fmt.Sprintf("%v", this.Format) + `,`, + `Description:` + fmt.Sprintf("%v", this.Description) + `,`, + `Priority:` + fmt.Sprintf("%v", this.Priority) + `,`, + `JSONPath:` + fmt.Sprintf("%v", this.JSONPath) + `,`, + `}`, + }, "") + return s +} func (this *CustomResourceDefinition) String() string { if this == nil { return "nil" @@ -1619,6 +1813,8 @@ func (this *CustomResourceDefinitionSpec) String() string { `Scope:` + fmt.Sprintf("%v", this.Scope) + `,`, `Validation:` + strings.Replace(fmt.Sprintf("%v", this.Validation), "CustomResourceValidation", "CustomResourceValidation", 1) + `,`, `Subresources:` + strings.Replace(fmt.Sprintf("%v", this.Subresources), "CustomResourceSubresources", "CustomResourceSubresources", 1) + `,`, + `Versions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Versions), "CustomResourceDefinitionVersion", "CustomResourceDefinitionVersion", 1), `&`, ``, 1) + `,`, + `AdditionalPrinterColumns:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AdditionalPrinterColumns), "CustomResourceColumnDefinition", "CustomResourceColumnDefinition", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -1630,6 +1826,19 @@ func (this *CustomResourceDefinitionStatus) String() string { s := strings.Join([]string{`&CustomResourceDefinitionStatus{`, `Conditions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Conditions), "CustomResourceDefinitionCondition", "CustomResourceDefinitionCondition", 1), `&`, ``, 1) + `,`, `AcceptedNames:` + strings.Replace(strings.Replace(this.AcceptedNames.String(), "CustomResourceDefinitionNames", "CustomResourceDefinitionNames", 1), `&`, ``, 1) + `,`, + `StoredVersions:` + fmt.Sprintf("%v", this.StoredVersions) + `,`, + `}`, + }, "") + return s +} +func (this *CustomResourceDefinitionVersion) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CustomResourceDefinitionVersion{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Served:` + fmt.Sprintf("%v", this.Served) + `,`, + `Storage:` + fmt.Sprintf("%v", this.Storage) + `,`, `}`, }, "") return s @@ -1823,7 +2032,7 @@ func valueToStringGenerated(v interface{}) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("*%v", pv) } -func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { +func (m *CustomResourceColumnDefinition) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1846,17 +2055,17 @@ func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CustomResourceDefinition: wiretype end group for non-group") + return fmt.Errorf("proto: CustomResourceColumnDefinition: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CustomResourceDefinition: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CustomResourceColumnDefinition: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -1866,27 +2075,26 @@ func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Name = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -1896,27 +2104,26 @@ func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Type = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -1926,47 +2133,263 @@ func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Format = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) } - if skippy < 0 { + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - if (iNdEx + skippy) > l { + postIndex := iNdEx + intStringLen + if postIndex > l { return io.ErrUnexpectedEOF } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *CustomResourceDefinitionCondition) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) + } + m.Priority = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Priority |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field JSONPath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.JSONPath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CustomResourceDefinition: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CustomResourceDefinition: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CustomResourceDefinitionCondition) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { preIndex := iNdEx var wire uint64 for shift := uint(0); ; shift += 7 { @@ -2706,6 +3129,68 @@ func (m *CustomResourceDefinitionSpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Versions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Versions = append(m.Versions, CustomResourceDefinitionVersion{}) + if err := m.Versions[len(m.Versions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AdditionalPrinterColumns", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AdditionalPrinterColumns = append(m.AdditionalPrinterColumns, CustomResourceColumnDefinition{}) + if err := m.AdditionalPrinterColumns[len(m.AdditionalPrinterColumns)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -2817,6 +3302,154 @@ func (m *CustomResourceDefinitionStatus) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StoredVersions", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StoredVersions = append(m.StoredVersions, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CustomResourceDefinitionVersion) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CustomResourceDefinitionVersion: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CustomResourceDefinitionVersion: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Served", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Served = bool(v != 0) + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Storage", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Storage = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -5241,137 +5874,149 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2102 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0xcb, 0x6f, 0x63, 0x49, - 0xd5, 0x4f, 0xd9, 0x79, 0x56, 0x92, 0x49, 0x52, 0xdd, 0xe9, 0xef, 0x76, 0xbe, 0x6e, 0x3b, 0xf1, - 0x30, 0xa3, 0x00, 0xd3, 0x36, 0x3d, 0x0f, 0x66, 0x40, 0x62, 0x11, 0x27, 0x01, 0xf5, 0x90, 0x74, - 0xa2, 0x72, 0x77, 0x23, 0x98, 0x67, 0xe5, 0xba, 0xec, 0x54, 0xe7, 0xbe, 0xfa, 0x56, 0x5d, 0x77, - 0x22, 0x01, 0xe2, 0xa1, 0x11, 0x12, 0x12, 0x0f, 0x41, 0x6f, 0x90, 0xd8, 0x80, 0xc4, 0x06, 0x21, - 0x58, 0xc0, 0x92, 0x25, 0x8b, 0x5e, 0x8e, 0xc4, 0x66, 0x56, 0x16, 0x6d, 0xfe, 0x05, 0x24, 0xa4, - 0xac, 0x50, 0x3d, 0xee, 0xcb, 0x8e, 0x67, 0x5a, 0x1a, 0x7b, 0x7a, 0xe7, 0x7b, 0x5e, 0xbf, 0x5f, - 0x9d, 0x3a, 0x75, 0xea, 0x94, 0x61, 0xeb, 0xe4, 0x0d, 0x5e, 0x65, 0x7e, 0xed, 0x24, 0x3a, 0xa2, - 0xa1, 0x47, 0x05, 0xe5, 0xb5, 0x0e, 0xf5, 0x9a, 0x7e, 0x58, 0x33, 0x0a, 0x12, 0x30, 0x7a, 0x2a, - 0xa8, 0xc7, 0x99, 0xef, 0xf1, 0x1b, 0x24, 0x60, 0x9c, 0x86, 0x1d, 0x1a, 0xd6, 0x82, 0x93, 0xb6, - 0xd4, 0xf1, 0xbc, 0x41, 0xad, 0x73, 0xf3, 0x88, 0x0a, 0x72, 0xb3, 0xd6, 0xa6, 0x1e, 0x0d, 0x89, - 0xa0, 0xcd, 0x6a, 0x10, 0xfa, 0xc2, 0x47, 0x5f, 0xd3, 0xe1, 0xaa, 0x39, 0xeb, 0xf7, 0x92, 0x70, - 0xd5, 0xe0, 0xa4, 0x2d, 0x75, 0x3c, 0x6f, 0x50, 0x35, 0xe1, 0xd6, 0x6e, 0xb4, 0x99, 0x38, 0x8e, - 0x8e, 0xaa, 0xb6, 0xef, 0xd6, 0xda, 0x7e, 0xdb, 0xaf, 0xa9, 0xa8, 0x47, 0x51, 0x4b, 0x7d, 0xa9, - 0x0f, 0xf5, 0x4b, 0xa3, 0xad, 0xbd, 0x9a, 0x92, 0x77, 0x89, 0x7d, 0xcc, 0x3c, 0x1a, 0x9e, 0xa5, - 0x8c, 0x5d, 0x2a, 0x48, 0xad, 0x33, 0xc0, 0x71, 0xad, 0x36, 0xcc, 0x2b, 0x8c, 0x3c, 0xc1, 0x5c, - 0x3a, 0xe0, 0xf0, 0xe5, 0x4f, 0x72, 0xe0, 0xf6, 0x31, 0x75, 0xc9, 0x80, 0xdf, 0x2b, 0xc3, 0xfc, - 0x22, 0xc1, 0x9c, 0x1a, 0xf3, 0x04, 0x17, 0x61, 0xbf, 0x53, 0xe5, 0xc7, 0x45, 0x68, 0x6d, 0x47, - 0x5c, 0xf8, 0x2e, 0xa6, 0xdc, 0x8f, 0x42, 0x9b, 0xee, 0xd0, 0x16, 0xf3, 0x98, 0x60, 0xbe, 0x87, - 0xde, 0x87, 0xb3, 0x72, 0x55, 0x4d, 0x22, 0x88, 0x05, 0xd6, 0xc1, 0xe6, 0xfc, 0xcb, 0x5f, 0xaa, - 0xa6, 0x19, 0x4f, 0x40, 0xd2, 0x34, 0x4b, 0xeb, 0x6a, 0xe7, 0x66, 0xf5, 0xe0, 0xe8, 0x3e, 0xb5, - 0xc5, 0x3e, 0x15, 0xa4, 0x8e, 0x1e, 0x77, 0xcb, 0x13, 0xbd, 0x6e, 0x19, 0xa6, 0x32, 0x9c, 0x44, - 0x45, 0xdf, 0x83, 0x93, 0x3c, 0xa0, 0xb6, 0x55, 0x50, 0xd1, 0xdf, 0xaa, 0x7e, 0xaa, 0xfd, 0xac, - 0x0e, 0x5b, 0x48, 0x23, 0xa0, 0x76, 0x7d, 0xc1, 0x10, 0x99, 0x94, 0x5f, 0x58, 0xc1, 0xa2, 0x0f, - 0x00, 0x9c, 0xe6, 0x82, 0x88, 0x88, 0x5b, 0x45, 0xc5, 0xe0, 0x9d, 0x71, 0x31, 0x50, 0x20, 0xf5, - 0xe7, 0x0c, 0x87, 0x69, 0xfd, 0x8d, 0x0d, 0x78, 0xe5, 0x3f, 0x05, 0xb8, 0x31, 0xcc, 0x75, 0xdb, - 0xf7, 0x9a, 0x7a, 0x3b, 0x6e, 0xc1, 0x49, 0x71, 0x16, 0x50, 0xb5, 0x15, 0x73, 0xf5, 0xd7, 0xe2, - 0xf5, 0xdc, 0x39, 0x0b, 0xe8, 0x79, 0xb7, 0xfc, 0xc2, 0x27, 0x06, 0x90, 0x86, 0x58, 0x85, 0x40, - 0x5f, 0x49, 0xd6, 0x5d, 0x50, 0xc1, 0x36, 0xf2, 0xc4, 0xce, 0xbb, 0xe5, 0xa5, 0xc4, 0x2d, 0xcf, - 0x15, 0x75, 0x20, 0x72, 0x08, 0x17, 0x77, 0x42, 0xe2, 0x71, 0x1d, 0x96, 0xb9, 0xd4, 0xa4, 0xef, - 0x0b, 0x4f, 0x57, 0x1e, 0xd2, 0xa3, 0xbe, 0x66, 0x20, 0xd1, 0xde, 0x40, 0x34, 0x7c, 0x01, 0x02, - 0x7a, 0x11, 0x4e, 0x87, 0x94, 0x70, 0xdf, 0xb3, 0x26, 0x15, 0xe5, 0x24, 0x97, 0x58, 0x49, 0xb1, - 0xd1, 0xa2, 0xcf, 0xc3, 0x19, 0x97, 0x72, 0x4e, 0xda, 0xd4, 0x9a, 0x52, 0x86, 0x4b, 0xc6, 0x70, - 0x66, 0x5f, 0x8b, 0x71, 0xac, 0xaf, 0x9c, 0x03, 0x78, 0x6d, 0x58, 0xd6, 0xf6, 0x18, 0x17, 0xe8, - 0xed, 0x81, 0x03, 0x50, 0x7d, 0xba, 0x15, 0x4a, 0x6f, 0x55, 0xfe, 0xcb, 0x06, 0x7c, 0x36, 0x96, - 0x64, 0x8a, 0xff, 0xbb, 0x70, 0x8a, 0x09, 0xea, 0xca, 0x3d, 0x28, 0x6e, 0xce, 0xbf, 0xfc, 0xad, - 0x31, 0xd5, 0x5e, 0x7d, 0xd1, 0x70, 0x98, 0xba, 0x25, 0xd1, 0xb0, 0x06, 0xad, 0xfc, 0xa1, 0x00, - 0xaf, 0x0f, 0x73, 0xb9, 0x4d, 0x5c, 0xca, 0x65, 0xc6, 0x03, 0x27, 0x0a, 0x89, 0x63, 0x2a, 0x2e, - 0xc9, 0xf8, 0xa1, 0x92, 0x62, 0xa3, 0x45, 0x2f, 0xc1, 0x59, 0xce, 0xbc, 0x76, 0xe4, 0x90, 0xd0, - 0x94, 0x53, 0xb2, 0xea, 0x86, 0x91, 0xe3, 0xc4, 0x02, 0x55, 0x21, 0xe4, 0xc7, 0x7e, 0x28, 0x14, - 0x86, 0x55, 0x5c, 0x2f, 0xca, 0xc8, 0xb2, 0x41, 0x34, 0x12, 0x29, 0xce, 0x58, 0xa0, 0x75, 0x38, - 0x79, 0xc2, 0xbc, 0xa6, 0xd9, 0xf5, 0xe4, 0x14, 0x7f, 0x93, 0x79, 0x4d, 0xac, 0x34, 0x12, 0xdf, - 0x61, 0x5c, 0x48, 0x89, 0xd9, 0xf2, 0x5c, 0xd6, 0x95, 0x65, 0x62, 0x21, 0xf1, 0x6d, 0x22, 0x68, - 0xdb, 0x0f, 0x19, 0xe5, 0xd6, 0x74, 0x8a, 0xbf, 0x9d, 0x48, 0x71, 0xc6, 0xa2, 0xf2, 0x8f, 0xc9, - 0xe1, 0x45, 0x22, 0x5b, 0x09, 0x7a, 0x1e, 0x4e, 0xb5, 0x43, 0x3f, 0x0a, 0x4c, 0x96, 0x92, 0x6c, - 0x7f, 0x43, 0x0a, 0xb1, 0xd6, 0xc9, 0xaa, 0xec, 0xd0, 0x50, 0x6e, 0x98, 0x49, 0x51, 0x52, 0x95, - 0xf7, 0xb4, 0x18, 0xc7, 0x7a, 0xf4, 0x43, 0x00, 0xa7, 0x3c, 0x93, 0x1c, 0x59, 0x72, 0x6f, 0x8f, - 0xa9, 0x2e, 0x54, 0x7a, 0x53, 0xba, 0x3a, 0xf3, 0x1a, 0x19, 0xbd, 0x0a, 0xa7, 0xb8, 0xed, 0x07, - 0xd4, 0x64, 0xbd, 0x14, 0x1b, 0x35, 0xa4, 0xf0, 0xbc, 0x5b, 0x5e, 0x8c, 0xc3, 0x29, 0x01, 0xd6, - 0xc6, 0xe8, 0x27, 0x00, 0xc2, 0x0e, 0x71, 0x58, 0x93, 0xc8, 0xf8, 0x6a, 0x2f, 0x46, 0x5d, 0xd6, - 0xf7, 0x92, 0xf0, 0x7a, 0xd3, 0xd2, 0x6f, 0x9c, 0x81, 0x46, 0xbf, 0x00, 0x70, 0x81, 0x47, 0x47, - 0xa1, 0xf1, 0x92, 0xfb, 0x2c, 0xb9, 0x7c, 0x7b, 0xa4, 0x5c, 0x1a, 0x19, 0x80, 0xfa, 0x72, 0xaf, - 0x5b, 0x5e, 0xc8, 0x4a, 0x70, 0x8e, 0x40, 0xe5, 0x9f, 0x05, 0x58, 0xfa, 0xf8, 0xdb, 0x01, 0x3d, - 0x02, 0x10, 0xda, 0x71, 0xd7, 0xe5, 0x16, 0x50, 0x5d, 0xe1, 0xfd, 0x31, 0xed, 0x7e, 0xd2, 0xde, - 0xd3, 0x1b, 0x3a, 0x11, 0xc9, 0x03, 0x90, 0xfc, 0x46, 0xbf, 0x01, 0x70, 0x91, 0xd8, 0x36, 0x0d, - 0x04, 0x6d, 0xea, 0x43, 0x5b, 0xf8, 0x0c, 0xea, 0x72, 0xd5, 0xb0, 0x5a, 0xdc, 0xca, 0x42, 0xe3, - 0x3c, 0x93, 0xca, 0x7f, 0x41, 0x7f, 0x56, 0x33, 0x5b, 0xd0, 0xb0, 0x89, 0x43, 0xd1, 0x0e, 0x5c, - 0x96, 0x77, 0x3d, 0xa6, 0x81, 0xc3, 0x6c, 0xc2, 0x0f, 0x89, 0x38, 0x36, 0x27, 0xd5, 0x32, 0x10, - 0xcb, 0x8d, 0x3e, 0x3d, 0x1e, 0xf0, 0x40, 0x6f, 0x42, 0xa4, 0xef, 0xbf, 0x5c, 0x1c, 0x7d, 0x94, - 0x93, 0x9b, 0xac, 0x31, 0x60, 0x81, 0x2f, 0xf0, 0x42, 0xdb, 0x70, 0xc5, 0x21, 0x47, 0xd4, 0x69, - 0x50, 0x87, 0xda, 0xc2, 0x0f, 0x55, 0xa8, 0xa2, 0x0a, 0xb5, 0xda, 0xeb, 0x96, 0x57, 0xf6, 0xfa, - 0x95, 0x78, 0xd0, 0xbe, 0xb2, 0x01, 0xcb, 0xc3, 0x17, 0xae, 0xa7, 0x8a, 0xdf, 0x15, 0xe0, 0xda, - 0xf0, 0x8a, 0x45, 0x3f, 0x4a, 0x87, 0x1f, 0x7d, 0xb7, 0xbd, 0x3b, 0xae, 0xd3, 0x61, 0xa6, 0x1f, - 0x38, 0x38, 0xf9, 0xa0, 0xef, 0xcb, 0x46, 0x43, 0x1c, 0x6a, 0x6a, 0xea, 0x9d, 0xb1, 0x51, 0x90, - 0x20, 0xf5, 0x39, 0xdd, 0xc3, 0x88, 0xa3, 0x5a, 0x16, 0x71, 0x68, 0xe5, 0x8f, 0xa0, 0x7f, 0xfe, - 0x4d, 0x3b, 0x0a, 0xfa, 0x19, 0x80, 0x4b, 0x7e, 0x40, 0xbd, 0xad, 0xc3, 0x5b, 0xf7, 0x5e, 0x69, - 0xa8, 0xa9, 0xdb, 0xa4, 0xea, 0xf6, 0xa7, 0xe4, 0xf9, 0x66, 0xe3, 0xe0, 0xb6, 0x0e, 0x78, 0x18, - 0xfa, 0x01, 0xaf, 0x5f, 0xea, 0x75, 0xcb, 0x4b, 0x07, 0x79, 0x28, 0xdc, 0x8f, 0x5d, 0x71, 0xe1, - 0xea, 0xee, 0xa9, 0xa0, 0xa1, 0x47, 0x9c, 0x1d, 0xdf, 0x8e, 0x5c, 0xea, 0x09, 0x4d, 0xf4, 0x35, - 0x38, 0xdf, 0xa4, 0xdc, 0x0e, 0x59, 0xa0, 0x1a, 0xaf, 0x2e, 0xef, 0x4b, 0xa6, 0x2c, 0xe7, 0x77, - 0x52, 0x15, 0xce, 0xda, 0xa1, 0xeb, 0xb0, 0x18, 0x85, 0x8e, 0xa9, 0xe2, 0x79, 0x63, 0x5e, 0xbc, - 0x8b, 0xf7, 0xb0, 0x94, 0x57, 0x36, 0xe0, 0xa4, 0xe4, 0x89, 0xae, 0xc2, 0x62, 0x48, 0x1e, 0xaa, - 0xa8, 0x0b, 0xf5, 0x19, 0x69, 0x82, 0xc9, 0x43, 0x2c, 0x65, 0x95, 0x3f, 0x5d, 0x83, 0x4b, 0x7d, - 0x6b, 0x41, 0x6b, 0xb0, 0xc0, 0x9a, 0x86, 0x03, 0x34, 0x41, 0x0b, 0xb7, 0x76, 0x70, 0x81, 0x35, - 0xd1, 0xeb, 0x70, 0x5a, 0xbf, 0x5e, 0x0c, 0x68, 0x39, 0x99, 0x3b, 0x95, 0x54, 0xde, 0x2c, 0x69, - 0x38, 0x49, 0xc4, 0x98, 0x2b, 0x0e, 0xb4, 0x65, 0x4e, 0x89, 0xe6, 0x40, 0x5b, 0x58, 0xca, 0xfa, - 0x17, 0x3f, 0xf9, 0x94, 0x8b, 0x5f, 0x37, 0xd3, 0xf4, 0x54, 0x7e, 0xae, 0xc8, 0x0c, 0xc9, 0x2f, - 0xc2, 0xe9, 0x96, 0x1f, 0xba, 0x44, 0xa8, 0xdb, 0x23, 0x33, 0xff, 0x7c, 0x5d, 0x49, 0xb1, 0xd1, - 0xca, 0x01, 0x40, 0x30, 0xe1, 0x50, 0x6b, 0x26, 0x3f, 0x00, 0xdc, 0x91, 0x42, 0xac, 0x75, 0xe8, - 0x3e, 0x9c, 0x69, 0xd2, 0x16, 0x89, 0x1c, 0x61, 0xcd, 0xaa, 0x12, 0xda, 0x1e, 0x41, 0x09, 0xd5, - 0xe7, 0xe5, 0x04, 0xb1, 0xa3, 0xe3, 0xe2, 0x18, 0x00, 0xbd, 0x00, 0x67, 0x5c, 0x72, 0xca, 0xdc, - 0xc8, 0xb5, 0xe6, 0xd6, 0xc1, 0x26, 0xd0, 0x66, 0xfb, 0x5a, 0x84, 0x63, 0x9d, 0xec, 0x8c, 0xf4, - 0xd4, 0x76, 0x22, 0xce, 0x3a, 0xd4, 0x28, 0x2d, 0xb8, 0x0e, 0x36, 0x67, 0xd3, 0xce, 0xb8, 0xdb, - 0xa7, 0xc7, 0x03, 0x1e, 0x0a, 0x8c, 0x79, 0xca, 0x79, 0x3e, 0x03, 0xa6, 0x45, 0x38, 0xd6, 0xe5, - 0xc1, 0x8c, 0xfd, 0xc2, 0x30, 0x30, 0xe3, 0x3c, 0xe0, 0x81, 0xbe, 0x08, 0xe7, 0x5c, 0x72, 0xba, - 0x47, 0xbd, 0xb6, 0x38, 0xb6, 0x16, 0xd7, 0xc1, 0x66, 0xb1, 0xbe, 0xd8, 0xeb, 0x96, 0xe7, 0xf6, - 0x63, 0x21, 0x4e, 0xf5, 0xca, 0x98, 0x79, 0xc6, 0xf8, 0xb9, 0x8c, 0x71, 0x2c, 0xc4, 0xa9, 0x5e, - 0x0e, 0x68, 0x01, 0x11, 0xf2, 0x70, 0x59, 0x4b, 0xf9, 0x01, 0xed, 0x50, 0x8b, 0x71, 0xac, 0x47, - 0x9b, 0x70, 0xd6, 0x25, 0xa7, 0x6a, 0x98, 0xb6, 0x96, 0x55, 0xd8, 0x05, 0x39, 0x6b, 0xee, 0x1b, - 0x19, 0x4e, 0xb4, 0xca, 0x92, 0x79, 0xda, 0x72, 0x25, 0x63, 0x69, 0x64, 0x38, 0xd1, 0xca, 0x22, - 0x8e, 0x3c, 0xf6, 0x20, 0xa2, 0xda, 0x18, 0xa9, 0xcc, 0x24, 0x45, 0x7c, 0x37, 0x55, 0xe1, 0xac, - 0x9d, 0x1c, 0x66, 0xdd, 0xc8, 0x11, 0x2c, 0x70, 0xe8, 0x41, 0xcb, 0xba, 0xa4, 0xf2, 0xaf, 0xe6, - 0xa2, 0xfd, 0x44, 0x8a, 0x33, 0x16, 0x88, 0xc2, 0x49, 0xea, 0x45, 0xae, 0x75, 0x59, 0xcd, 0x16, - 0x23, 0x29, 0xc1, 0xe4, 0xe4, 0xec, 0x7a, 0x91, 0x8b, 0x55, 0x78, 0xf4, 0x3a, 0x5c, 0x74, 0xc9, - 0xa9, 0x6c, 0x07, 0x34, 0x14, 0x72, 0xcc, 0x5e, 0x55, 0x8b, 0x5f, 0x91, 0xf7, 0xf9, 0x7e, 0x56, - 0x81, 0xf3, 0x76, 0xca, 0x91, 0x79, 0x19, 0xc7, 0x2b, 0x19, 0xc7, 0xac, 0x02, 0xe7, 0xed, 0x64, - 0xa6, 0x43, 0xfa, 0x20, 0x62, 0x21, 0x6d, 0x5a, 0xff, 0xa7, 0x66, 0x7a, 0x95, 0x69, 0x6c, 0x64, - 0x38, 0xd1, 0xa2, 0x4e, 0xfc, 0xea, 0xb2, 0xd4, 0x31, 0xbc, 0x3b, 0xda, 0x4e, 0x7e, 0x10, 0x6e, - 0x85, 0x21, 0x39, 0xd3, 0x37, 0x4d, 0xf6, 0xbd, 0x85, 0x38, 0x9c, 0x22, 0x8e, 0x73, 0xd0, 0xb2, - 0xae, 0xaa, 0xdc, 0x8f, 0xfa, 0x06, 0x49, 0xba, 0xce, 0x96, 0x04, 0xc1, 0x1a, 0x4b, 0x82, 0xfa, - 0x9e, 0x2c, 0x8d, 0xb5, 0xf1, 0x82, 0x1e, 0x48, 0x10, 0xac, 0xb1, 0xd4, 0x4a, 0xbd, 0xb3, 0x83, - 0x96, 0xf5, 0xff, 0x63, 0x5e, 0xa9, 0x04, 0xc1, 0x1a, 0x0b, 0x31, 0x58, 0xf4, 0x7c, 0x61, 0x5d, - 0x1b, 0xcb, 0xf5, 0xac, 0x2e, 0x9c, 0xdb, 0xbe, 0xc0, 0x12, 0x03, 0xfd, 0x0a, 0x40, 0x18, 0xa4, - 0x25, 0x7a, 0x5d, 0xad, 0xf2, 0xdd, 0xd1, 0x42, 0x56, 0xd3, 0xda, 0xde, 0xf5, 0x44, 0x78, 0x96, - 0x4e, 0xe9, 0x99, 0x33, 0x90, 0x61, 0x81, 0x7e, 0x0f, 0xe0, 0x65, 0xd2, 0xd4, 0x33, 0x3b, 0x71, - 0x32, 0x27, 0xa8, 0xa4, 0x32, 0x72, 0x67, 0xd4, 0x65, 0x5e, 0xf7, 0x7d, 0xa7, 0x6e, 0xf5, 0xba, - 0xe5, 0xcb, 0x5b, 0x17, 0xa0, 0xe2, 0x0b, 0xb9, 0xa0, 0x3f, 0x03, 0xb8, 0x62, 0xba, 0x68, 0x86, - 0x61, 0x59, 0x25, 0x90, 0x8e, 0x3a, 0x81, 0xfd, 0x38, 0x3a, 0x8f, 0x57, 0x4d, 0x1e, 0x57, 0x06, - 0xf4, 0x78, 0x90, 0x1a, 0xfa, 0x1b, 0x80, 0x0b, 0x4d, 0x1a, 0x50, 0xaf, 0x49, 0x3d, 0x5b, 0x72, - 0x5d, 0x1f, 0xc9, 0xa3, 0xac, 0x9f, 0xeb, 0x4e, 0x06, 0x42, 0xd3, 0xac, 0x1a, 0x9a, 0x0b, 0x59, - 0xd5, 0x79, 0xb7, 0x7c, 0x25, 0x75, 0xcd, 0x6a, 0x70, 0x8e, 0x25, 0xfa, 0x35, 0x80, 0x4b, 0xe9, - 0x06, 0xe8, 0x2b, 0x65, 0x63, 0x8c, 0x75, 0xa0, 0xc6, 0xd7, 0xad, 0x3c, 0x20, 0xee, 0x67, 0x80, - 0xfe, 0x02, 0xe4, 0xa4, 0x16, 0x3f, 0xf3, 0xb8, 0x55, 0x51, 0xb9, 0x7c, 0x6f, 0xe4, 0xb9, 0x4c, - 0x10, 0x74, 0x2a, 0x5f, 0x4a, 0x47, 0xc1, 0x44, 0x73, 0xde, 0x2d, 0xaf, 0x66, 0x33, 0x99, 0x28, - 0x70, 0x96, 0x21, 0xfa, 0x29, 0x80, 0x0b, 0x34, 0x9d, 0xb8, 0xb9, 0xf5, 0xfc, 0x48, 0x92, 0x78, - 0xe1, 0x10, 0xaf, 0xff, 0x41, 0xc8, 0xa8, 0x38, 0xce, 0x61, 0xcb, 0x09, 0x92, 0x9e, 0x12, 0x37, - 0x70, 0xa8, 0xf5, 0xb9, 0x11, 0x4f, 0x90, 0xbb, 0x3a, 0x2e, 0x8e, 0x01, 0xd6, 0xe4, 0xcb, 0xa7, - 0xef, 0xe4, 0xa0, 0x65, 0x58, 0x3c, 0xa1, 0x67, 0x7a, 0xb0, 0xc7, 0xf2, 0x27, 0x6a, 0xc2, 0xa9, - 0x0e, 0x71, 0xa2, 0xf8, 0xf1, 0x36, 0xe2, 0xae, 0x8b, 0x75, 0xf0, 0xaf, 0x16, 0xde, 0x00, 0x6b, - 0x8f, 0x00, 0xbc, 0x72, 0xf1, 0x81, 0x7e, 0xa6, 0xb4, 0x7e, 0x0b, 0xe0, 0xca, 0xc0, 0xd9, 0xbd, - 0x80, 0xd1, 0x83, 0x3c, 0xa3, 0xb7, 0x46, 0x7d, 0x08, 0x1b, 0x22, 0x64, 0x5e, 0x5b, 0x4d, 0x1e, - 0x59, 0x7a, 0x3f, 0x07, 0x70, 0xb9, 0xff, 0x38, 0x3c, 0xcb, 0x7c, 0x55, 0x1e, 0x15, 0xe0, 0x95, - 0x8b, 0x07, 0x26, 0x14, 0x26, 0x2f, 0xc3, 0xf1, 0xbc, 0xb0, 0x61, 0xfa, 0xca, 0x4c, 0x1e, 0x95, - 0x1f, 0x00, 0x38, 0x7f, 0x3f, 0xb1, 0x8b, 0xff, 0x87, 0x1f, 0xf9, 0xdb, 0x3e, 0xee, 0x3f, 0xa9, - 0x82, 0xe3, 0x2c, 0x6e, 0xe5, 0xaf, 0x00, 0xae, 0x5e, 0xd8, 0x58, 0xe5, 0x13, 0x94, 0x38, 0x8e, - 0xff, 0x50, 0xff, 0x45, 0x33, 0x9b, 0x3e, 0x41, 0xb7, 0x94, 0x14, 0x1b, 0x6d, 0x26, 0x7b, 0x85, - 0xcf, 0x2a, 0x7b, 0x95, 0xbf, 0x03, 0x78, 0xed, 0xe3, 0x2a, 0xf1, 0x99, 0x6c, 0xe9, 0x26, 0x9c, - 0x35, 0x43, 0xd1, 0x99, 0xda, 0x4e, 0xf3, 0x0e, 0x30, 0x4d, 0xe3, 0x0c, 0x27, 0xda, 0xfa, 0x8d, - 0xc7, 0x4f, 0x4a, 0x13, 0x1f, 0x3e, 0x29, 0x4d, 0x7c, 0xf4, 0xa4, 0x34, 0xf1, 0x83, 0x5e, 0x09, - 0x3c, 0xee, 0x95, 0xc0, 0x87, 0xbd, 0x12, 0xf8, 0xa8, 0x57, 0x02, 0xff, 0xea, 0x95, 0xc0, 0x2f, - 0xff, 0x5d, 0x9a, 0xf8, 0xce, 0x8c, 0x01, 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x6f, - 0x04, 0x49, 0xd3, 0x1e, 0x00, 0x00, + // 2292 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6f, 0x5b, 0x49, + 0x15, 0xef, 0xd8, 0x71, 0xe2, 0x8c, 0x93, 0x26, 0x99, 0x6d, 0xca, 0x6d, 0x68, 0xed, 0xd4, 0x65, + 0x57, 0x01, 0xb6, 0x0e, 0x2d, 0xbb, 0xec, 0xb2, 0x12, 0x0f, 0x71, 0x52, 0x50, 0x97, 0xa6, 0x89, + 0xc6, 0x6d, 0x11, 0xec, 0xe7, 0xc4, 0x9e, 0x38, 0xb7, 0xb9, 0x5f, 0xbd, 0x33, 0xd7, 0x4d, 0x24, + 0x40, 0x7c, 0x68, 0x85, 0x84, 0x80, 0x05, 0xb6, 0x42, 0x42, 0xe2, 0x05, 0x24, 0x5e, 0x10, 0x82, + 0x07, 0x78, 0x83, 0x3f, 0xa0, 0x8f, 0xfb, 0xb8, 0x4f, 0x16, 0x35, 0xff, 0x02, 0x12, 0x52, 0x9e, + 0xd0, 0x7c, 0xdc, 0xb9, 0x1f, 0x4e, 0xb6, 0x11, 0x6b, 0x6f, 0xdf, 0x7c, 0xcf, 0x39, 0x73, 0x7e, + 0xbf, 0x39, 0x73, 0xe6, 0xcc, 0x39, 0x09, 0xdc, 0xdd, 0x7f, 0x95, 0x35, 0x6c, 0x7f, 0x75, 0x3f, + 0xda, 0xa1, 0xa1, 0x47, 0x39, 0x65, 0xab, 0x3d, 0xea, 0x75, 0xfc, 0x70, 0x55, 0x2b, 0x48, 0x60, + 0xd3, 0x03, 0x4e, 0x3d, 0x66, 0xfb, 0x1e, 0xbb, 0x4a, 0x02, 0x9b, 0xd1, 0xb0, 0x47, 0xc3, 0xd5, + 0x60, 0xbf, 0x2b, 0x74, 0x2c, 0x6b, 0xb0, 0xda, 0xbb, 0xb6, 0x43, 0x39, 0xb9, 0xb6, 0xda, 0xa5, + 0x1e, 0x0d, 0x09, 0xa7, 0x9d, 0x46, 0x10, 0xfa, 0xdc, 0x47, 0x5f, 0x53, 0xee, 0x1a, 0x19, 0xeb, + 0x77, 0x8c, 0xbb, 0x46, 0xb0, 0xdf, 0x15, 0x3a, 0x96, 0x35, 0x68, 0x68, 0x77, 0x4b, 0x57, 0xbb, + 0x36, 0xdf, 0x8b, 0x76, 0x1a, 0x6d, 0xdf, 0x5d, 0xed, 0xfa, 0x5d, 0x7f, 0x55, 0x7a, 0xdd, 0x89, + 0x76, 0xe5, 0x97, 0xfc, 0x90, 0xbf, 0x14, 0xda, 0xd2, 0x4b, 0x09, 0x79, 0x97, 0xb4, 0xf7, 0x6c, + 0x8f, 0x86, 0x87, 0x09, 0x63, 0x97, 0x72, 0xb2, 0xda, 0x1b, 0xe2, 0xb8, 0xb4, 0x7a, 0xd2, 0xaa, + 0x30, 0xf2, 0xb8, 0xed, 0xd2, 0xa1, 0x05, 0x5f, 0x79, 0xda, 0x02, 0xd6, 0xde, 0xa3, 0x2e, 0xc9, + 0xaf, 0xab, 0x7f, 0x50, 0x80, 0xd5, 0xf5, 0x88, 0x71, 0xdf, 0xc5, 0x94, 0xf9, 0x51, 0xd8, 0xa6, + 0xeb, 0xbe, 0x13, 0xb9, 0xde, 0x06, 0xdd, 0xb5, 0x3d, 0x9b, 0xdb, 0xbe, 0x87, 0x96, 0xe1, 0x84, + 0x47, 0x5c, 0x6a, 0x81, 0x65, 0xb0, 0x32, 0xdd, 0x9c, 0x79, 0xdc, 0xaf, 0x9d, 0x19, 0xf4, 0x6b, + 0x13, 0xb7, 0x89, 0x4b, 0xb1, 0xd4, 0x08, 0x0b, 0x7e, 0x18, 0x50, 0xab, 0x90, 0xb5, 0xb8, 0x73, + 0x18, 0x50, 0x2c, 0x35, 0xe8, 0x05, 0x38, 0xb9, 0xeb, 0x87, 0x2e, 0xe1, 0x56, 0x51, 0xda, 0x9c, + 0xd5, 0x36, 0x93, 0x5f, 0x97, 0x52, 0xac, 0xb5, 0xe8, 0x65, 0x58, 0xe9, 0x50, 0xd6, 0x0e, 0xed, + 0x40, 0x40, 0x5b, 0x13, 0xd2, 0xf8, 0x39, 0x6d, 0x5c, 0xd9, 0x48, 0x54, 0x38, 0x6d, 0x87, 0x5e, + 0x84, 0xe5, 0x20, 0xb4, 0xfd, 0xd0, 0xe6, 0x87, 0x56, 0x69, 0x19, 0xac, 0x94, 0x9a, 0xf3, 0x7a, + 0x4d, 0x79, 0x5b, 0xcb, 0xb1, 0xb1, 0x40, 0xcb, 0xb0, 0xfc, 0x7a, 0x6b, 0xeb, 0xf6, 0x36, 0xe1, + 0x7b, 0xd6, 0xa4, 0x44, 0x98, 0x10, 0xd6, 0xb8, 0x7c, 0x5f, 0x4b, 0xeb, 0x3f, 0x2e, 0x42, 0x2b, + 0x1b, 0x95, 0x54, 0x3c, 0xde, 0x85, 0x65, 0x71, 0x6c, 0x1d, 0xc2, 0x89, 0x8c, 0x49, 0xe5, 0xfa, + 0x97, 0x1a, 0x49, 0x4a, 0x99, 0xe8, 0x27, 0x79, 0x24, 0xac, 0x1b, 0xbd, 0x6b, 0x8d, 0xad, 0x9d, + 0xfb, 0xb4, 0xcd, 0x37, 0x29, 0x27, 0x4d, 0xa4, 0xe9, 0xc1, 0x44, 0x86, 0x8d, 0x57, 0xf4, 0x3d, + 0x38, 0xc1, 0x02, 0xda, 0x96, 0xf1, 0xac, 0x5c, 0x7f, 0xa3, 0xf1, 0x89, 0x12, 0xb6, 0x71, 0xd2, + 0x46, 0x5a, 0x01, 0x6d, 0x27, 0x87, 0x25, 0xbe, 0xb0, 0x84, 0x45, 0xef, 0x01, 0x38, 0xc9, 0x38, + 0xe1, 0x11, 0x93, 0xa7, 0x55, 0xb9, 0xfe, 0xd6, 0xb8, 0x18, 0x48, 0x90, 0x24, 0x19, 0xd4, 0x37, + 0xd6, 0xe0, 0xf5, 0xff, 0x14, 0xe0, 0xe5, 0x93, 0x96, 0xae, 0xfb, 0x5e, 0x47, 0x1d, 0xc7, 0x4d, + 0x9d, 0x7c, 0x2a, 0x3d, 0x5f, 0x4e, 0x27, 0xdf, 0x51, 0xbf, 0xf6, 0xfc, 0x53, 0x1d, 0xa4, 0xb2, + 0xf4, 0xab, 0x66, 0xdf, 0x2a, 0x93, 0x2f, 0x67, 0x89, 0x1d, 0xf5, 0x6b, 0x73, 0x66, 0x59, 0x96, + 0x2b, 0xea, 0x41, 0xe4, 0x10, 0xc6, 0xef, 0x84, 0xc4, 0x63, 0xca, 0xad, 0xed, 0x52, 0x1d, 0xbe, + 0x2f, 0x9c, 0x2e, 0x3d, 0xc4, 0x8a, 0xe6, 0x92, 0x86, 0x44, 0xb7, 0x86, 0xbc, 0xe1, 0x63, 0x10, + 0xc4, 0xc5, 0x0a, 0x29, 0x61, 0xe6, 0xae, 0x98, 0x58, 0x62, 0x29, 0xc5, 0x5a, 0x8b, 0x3e, 0x0f, + 0xa7, 0x5c, 0xca, 0x18, 0xe9, 0x52, 0x79, 0x41, 0xa6, 0x9b, 0x73, 0xda, 0x70, 0x6a, 0x53, 0x89, + 0x71, 0xac, 0xaf, 0x1f, 0x01, 0x78, 0xf1, 0xa4, 0xa8, 0xdd, 0xb2, 0x19, 0x47, 0x6f, 0x0e, 0x5d, + 0x80, 0xc6, 0xe9, 0x76, 0x28, 0x56, 0xcb, 0xf4, 0x37, 0xb7, 0x33, 0x96, 0xa4, 0x92, 0xff, 0xbb, + 0xb0, 0x64, 0x73, 0xea, 0x8a, 0x33, 0x28, 0xae, 0x54, 0xae, 0x7f, 0x6b, 0x4c, 0xb9, 0xd7, 0x9c, + 0xd5, 0x1c, 0x4a, 0x37, 0x05, 0x1a, 0x56, 0xa0, 0xf5, 0x3f, 0x16, 0xe0, 0xa5, 0x93, 0x96, 0x88, + 0x8a, 0xc7, 0x44, 0xc4, 0x03, 0x27, 0x0a, 0x89, 0xa3, 0x33, 0xce, 0x44, 0x7c, 0x5b, 0x4a, 0xb1, + 0xd6, 0x8a, 0x9a, 0xc4, 0x6c, 0xaf, 0x1b, 0x39, 0x24, 0xd4, 0xe9, 0x64, 0x76, 0xdd, 0xd2, 0x72, + 0x6c, 0x2c, 0x50, 0x03, 0x42, 0xb6, 0xe7, 0x87, 0x5c, 0x62, 0x58, 0xc5, 0xe5, 0xa2, 0xf0, 0x2c, + 0x0a, 0x44, 0xcb, 0x48, 0x71, 0xca, 0x42, 0x94, 0xdc, 0x7d, 0xdb, 0xeb, 0xe8, 0x53, 0x37, 0xb7, + 0xf8, 0x9b, 0xb6, 0xd7, 0xc1, 0x52, 0x23, 0xf0, 0x1d, 0x9b, 0x71, 0x21, 0xd1, 0x47, 0x9e, 0x89, + 0xba, 0xb4, 0x34, 0x16, 0x02, 0xbf, 0x4d, 0x38, 0xed, 0xfa, 0xa1, 0x4d, 0x99, 0x35, 0x99, 0xe0, + 0xaf, 0x1b, 0x29, 0x4e, 0x59, 0xd4, 0x7f, 0x35, 0x75, 0x72, 0x92, 0x88, 0x52, 0x82, 0xae, 0xc0, + 0x52, 0x37, 0xf4, 0xa3, 0x40, 0x47, 0xc9, 0x44, 0xfb, 0x1b, 0x42, 0x88, 0x95, 0x4e, 0x64, 0x65, + 0x8f, 0x86, 0xe2, 0xc0, 0x74, 0x88, 0x4c, 0x56, 0xde, 0x53, 0x62, 0x1c, 0xeb, 0xd1, 0x0f, 0x01, + 0x2c, 0x79, 0x3a, 0x38, 0x22, 0xe5, 0xde, 0x1c, 0x53, 0x5e, 0xc8, 0xf0, 0x26, 0x74, 0x55, 0xe4, + 0x15, 0x32, 0x7a, 0x09, 0x96, 0x58, 0xdb, 0x0f, 0xa8, 0x8e, 0x7a, 0x35, 0x36, 0x6a, 0x09, 0xe1, + 0x51, 0xbf, 0x36, 0x1b, 0xbb, 0x93, 0x02, 0xac, 0x8c, 0xd1, 0x4f, 0x00, 0x84, 0x3d, 0xe2, 0xd8, + 0x1d, 0x22, 0xdf, 0xb4, 0x92, 0xa4, 0x3f, 0xda, 0xb4, 0xbe, 0x67, 0xdc, 0xab, 0x43, 0x4b, 0xbe, + 0x71, 0x0a, 0x1a, 0xbd, 0x0f, 0xe0, 0x0c, 0x8b, 0x76, 0x42, 0xbd, 0x8a, 0xc9, 0xd7, 0xaf, 0x72, + 0xfd, 0xdb, 0x23, 0xe5, 0xd2, 0x4a, 0x01, 0x34, 0xe7, 0x07, 0xfd, 0xda, 0x4c, 0x5a, 0x82, 0x33, + 0x04, 0xd0, 0xcf, 0x00, 0x2c, 0xeb, 0x13, 0x66, 0xd6, 0x94, 0xbc, 0xf0, 0x6f, 0x8f, 0xe9, 0x60, + 0x75, 0x46, 0x25, 0xb7, 0x40, 0x0b, 0x18, 0x36, 0x0c, 0xd0, 0x3f, 0x00, 0xb4, 0x48, 0x47, 0x15, + 0x78, 0xe2, 0x6c, 0x87, 0xb6, 0xc7, 0x69, 0xa8, 0x1a, 0x22, 0x66, 0x95, 0x25, 0xbd, 0xd1, 0xbe, + 0x85, 0xf9, 0x66, 0xab, 0xb9, 0xac, 0xd9, 0x59, 0x6b, 0x27, 0xd0, 0xc0, 0x27, 0x12, 0xac, 0xbf, + 0x5f, 0xcc, 0xf7, 0x72, 0xf9, 0xa7, 0x16, 0x3d, 0x02, 0x10, 0xb6, 0xe3, 0x27, 0x8c, 0x59, 0x40, + 0x6e, 0xe9, 0xdd, 0x31, 0x45, 0xdc, 0xbc, 0x95, 0x49, 0xbb, 0x63, 0x44, 0xa2, 0x9a, 0x98, 0xdf, + 0xe8, 0xb7, 0x00, 0xce, 0x92, 0x76, 0x9b, 0x06, 0x9c, 0x76, 0x54, 0x05, 0x2c, 0x7c, 0x0a, 0x97, + 0x7c, 0x51, 0xb3, 0x9a, 0x5d, 0x4b, 0x43, 0xe3, 0x2c, 0x13, 0xf4, 0x1a, 0x3c, 0xcb, 0xb8, 0x1f, + 0xd2, 0x4e, 0x9c, 0x2f, 0xba, 0x3a, 0xa3, 0x41, 0xbf, 0x76, 0xb6, 0x95, 0xd1, 0xe0, 0x9c, 0x65, + 0xfd, 0x37, 0x00, 0xd6, 0x9e, 0x92, 0x8f, 0xa7, 0x68, 0xaf, 0x5f, 0x80, 0x93, 0x72, 0xbb, 0x1d, + 0x19, 0x95, 0x72, 0xaa, 0x5f, 0x92, 0x52, 0xac, 0xb5, 0xa2, 0x9a, 0x0a, 0x7c, 0xf1, 0xc6, 0x17, + 0xa5, 0xa1, 0xa9, 0xa6, 0x2d, 0x25, 0xc6, 0xb1, 0xbe, 0xfe, 0x5f, 0x90, 0x4f, 0x95, 0xd4, 0x25, + 0x6d, 0xb5, 0x89, 0x43, 0xd1, 0x06, 0x9c, 0x17, 0xdd, 0x20, 0xa6, 0x81, 0x63, 0xb7, 0x09, 0x93, + 0xdd, 0xb2, 0xe2, 0x68, 0x69, 0xb7, 0xf3, 0xad, 0x9c, 0x1e, 0x0f, 0xad, 0x40, 0xaf, 0x43, 0xa4, + 0x3a, 0xa4, 0x8c, 0x1f, 0x55, 0xec, 0x4d, 0xaf, 0xd3, 0x1a, 0xb2, 0xc0, 0xc7, 0xac, 0x42, 0xeb, + 0x70, 0xc1, 0x21, 0x3b, 0xd4, 0x69, 0x51, 0x87, 0xb6, 0xb9, 0x1f, 0x4a, 0x57, 0x6a, 0x9e, 0x58, + 0x1c, 0xf4, 0x6b, 0x0b, 0xb7, 0xf2, 0x4a, 0x3c, 0x6c, 0x5f, 0xbf, 0x9c, 0x3f, 0x91, 0xf4, 0xc6, + 0x55, 0xdf, 0xf9, 0xfb, 0x02, 0x5c, 0x3a, 0xb9, 0xa6, 0xa1, 0x1f, 0x25, 0xed, 0xb1, 0xea, 0x7e, + 0xde, 0x1e, 0x57, 0xfd, 0xd4, 0xfd, 0x31, 0x1c, 0xee, 0x8d, 0xd1, 0xf7, 0xc5, 0x53, 0x44, 0x1c, + 0xaa, 0x2f, 0xca, 0x5b, 0x63, 0xa3, 0x20, 0x40, 0x9a, 0xd3, 0xea, 0x95, 0x23, 0x8e, 0x7c, 0xd4, + 0x88, 0x43, 0xeb, 0x7f, 0x02, 0xf9, 0x09, 0x29, 0x79, 0x73, 0xd0, 0xcf, 0x01, 0x9c, 0xf3, 0x03, + 0xea, 0xad, 0x6d, 0xdf, 0xbc, 0xf7, 0xe5, 0x96, 0x1c, 0x3c, 0x75, 0xa8, 0x6e, 0x7f, 0x42, 0x9e, + 0x62, 0x6e, 0x53, 0x0e, 0xb7, 0x43, 0x3f, 0x60, 0xcd, 0xe7, 0x06, 0xfd, 0xda, 0xdc, 0x56, 0x16, + 0x0a, 0xe7, 0xb1, 0xeb, 0x2e, 0x5c, 0xbc, 0x71, 0xc0, 0x69, 0xe8, 0x11, 0x67, 0xc3, 0x6f, 0x47, + 0x2e, 0xf5, 0xb8, 0x22, 0x9a, 0x1b, 0x37, 0xc1, 0x29, 0xc7, 0xcd, 0x4b, 0xb0, 0x18, 0x85, 0x8e, + 0xce, 0xe2, 0x8a, 0x36, 0x2f, 0xde, 0xc5, 0xb7, 0xb0, 0x90, 0xd7, 0x2f, 0xc3, 0x09, 0xc1, 0x13, + 0x5d, 0x80, 0xc5, 0x90, 0x3c, 0x94, 0x5e, 0x67, 0x9a, 0x53, 0xc2, 0x04, 0x93, 0x87, 0x58, 0xc8, + 0xea, 0x7f, 0xbe, 0x08, 0xe7, 0x72, 0x7b, 0x41, 0x4b, 0xb0, 0x60, 0x77, 0x34, 0x07, 0xa8, 0x9d, + 0x16, 0x6e, 0x6e, 0xe0, 0x82, 0xdd, 0x41, 0xaf, 0xc0, 0x49, 0x35, 0xc0, 0x6b, 0xd0, 0x9a, 0x29, + 0x01, 0x52, 0x2a, 0x7a, 0x8f, 0xc4, 0x9d, 0x20, 0xa2, 0xcd, 0x25, 0x07, 0xba, 0xab, 0x6f, 0x89, + 0xe2, 0x40, 0x77, 0xb1, 0x90, 0xfd, 0xbf, 0xb3, 0x76, 0x3c, 0xec, 0x97, 0x4e, 0x31, 0xec, 0x4f, + 0x7e, 0xec, 0xb0, 0x7f, 0x05, 0x96, 0xb8, 0xcd, 0x1d, 0x6a, 0x4d, 0x65, 0x5b, 0xc4, 0x3b, 0x42, + 0x88, 0x95, 0x0e, 0xdd, 0x87, 0x53, 0x1d, 0xba, 0x4b, 0x22, 0x87, 0x5b, 0x65, 0x99, 0x42, 0xeb, + 0x23, 0x48, 0xa1, 0x66, 0x45, 0x54, 0xc5, 0x0d, 0xe5, 0x17, 0xc7, 0x00, 0xe8, 0x79, 0x38, 0xe5, + 0x92, 0x03, 0xdb, 0x8d, 0x5c, 0x6b, 0x7a, 0x19, 0xac, 0x00, 0x65, 0xb6, 0xa9, 0x44, 0x38, 0xd6, + 0x89, 0xca, 0x48, 0x0f, 0xda, 0x4e, 0xc4, 0xec, 0x1e, 0xd5, 0x4a, 0x0b, 0xca, 0x82, 0x6b, 0x2a, + 0xe3, 0x8d, 0x9c, 0x1e, 0x0f, 0xad, 0x90, 0x60, 0xb6, 0x27, 0x17, 0x57, 0x52, 0x60, 0x4a, 0x84, + 0x63, 0x5d, 0x16, 0x4c, 0xdb, 0xcf, 0x9c, 0x04, 0xa6, 0x17, 0x0f, 0xad, 0x40, 0x5f, 0x84, 0xd3, + 0x2e, 0x39, 0xb8, 0x45, 0xbd, 0x2e, 0xdf, 0xb3, 0x66, 0x97, 0xc1, 0x4a, 0xb1, 0x39, 0x3b, 0xe8, + 0xd7, 0xa6, 0x37, 0x63, 0x21, 0x4e, 0xf4, 0xd2, 0xd8, 0xf6, 0xb4, 0xf1, 0xd9, 0x94, 0x71, 0x2c, + 0xc4, 0x89, 0x5e, 0x3c, 0x3a, 0x01, 0xe1, 0xe2, 0x72, 0x59, 0x73, 0xd9, 0x16, 0x7e, 0x5b, 0x89, + 0x71, 0xac, 0x47, 0x2b, 0xb0, 0xec, 0x92, 0x03, 0x39, 0x6e, 0x59, 0xf3, 0xd2, 0xed, 0x8c, 0xe8, + 0xc3, 0x36, 0xb5, 0x0c, 0x1b, 0xad, 0xb4, 0xb4, 0x3d, 0x65, 0xb9, 0x90, 0xb2, 0xd4, 0x32, 0x6c, + 0xb4, 0x22, 0x89, 0x23, 0xcf, 0x7e, 0x10, 0x51, 0x65, 0x8c, 0x64, 0x64, 0x4c, 0x12, 0xdf, 0x4d, + 0x54, 0x38, 0x6d, 0x27, 0xc6, 0x1d, 0x37, 0x72, 0xb8, 0x1d, 0x38, 0x74, 0x6b, 0xd7, 0x7a, 0x4e, + 0xc6, 0x5f, 0x76, 0xce, 0x9b, 0x46, 0x8a, 0x53, 0x16, 0x88, 0xc2, 0x09, 0xea, 0x45, 0xae, 0x75, + 0x4e, 0x36, 0x4c, 0x23, 0x49, 0x41, 0x73, 0x73, 0x6e, 0x78, 0x91, 0x8b, 0xa5, 0x7b, 0xf4, 0x0a, + 0x9c, 0x75, 0xc9, 0x81, 0x28, 0x07, 0x34, 0xe4, 0x62, 0x10, 0x5b, 0x94, 0x9b, 0x5f, 0x10, 0x4d, + 0xca, 0x66, 0x5a, 0x81, 0xb3, 0x76, 0x72, 0xa1, 0xed, 0xa5, 0x16, 0x9e, 0x4f, 0x2d, 0x4c, 0x2b, + 0x70, 0xd6, 0x4e, 0x44, 0x3a, 0xa4, 0x0f, 0x22, 0x3b, 0xa4, 0x1d, 0xeb, 0x33, 0xb2, 0xaf, 0x91, + 0x91, 0xc6, 0x5a, 0x86, 0x8d, 0x16, 0xf5, 0xe2, 0xb9, 0xdc, 0x92, 0xd7, 0xf0, 0xee, 0x68, 0x2b, + 0xf9, 0x56, 0xb8, 0x16, 0x86, 0xe4, 0x50, 0xbd, 0x34, 0xe9, 0x89, 0x1c, 0x31, 0x58, 0x22, 0x8e, + 0xb3, 0xb5, 0x6b, 0x5d, 0x90, 0xb1, 0x1f, 0xf5, 0x0b, 0x62, 0xaa, 0xce, 0x9a, 0x00, 0xc1, 0x0a, + 0x4b, 0x80, 0xfa, 0x9e, 0x48, 0x8d, 0xa5, 0xf1, 0x82, 0x6e, 0x09, 0x10, 0xac, 0xb0, 0xe4, 0x4e, + 0xbd, 0xc3, 0xad, 0x5d, 0xeb, 0xb3, 0x63, 0xde, 0xa9, 0x00, 0xc1, 0x0a, 0x0b, 0xd9, 0xb0, 0xe8, + 0xf9, 0xdc, 0xba, 0x38, 0x96, 0xe7, 0x59, 0x3e, 0x38, 0xb7, 0x7d, 0x8e, 0x05, 0x06, 0xfa, 0x35, + 0x80, 0x30, 0x48, 0x52, 0xf4, 0xd2, 0x48, 0xc6, 0xbd, 0x1c, 0x64, 0x23, 0xc9, 0xed, 0x1b, 0x1e, + 0x0f, 0x0f, 0x93, 0xd1, 0x23, 0x75, 0x07, 0x52, 0x2c, 0xd0, 0x1f, 0x00, 0x3c, 0x97, 0x9e, 0xa8, + 0x0c, 0xbd, 0xaa, 0x8c, 0xc8, 0x9d, 0x51, 0xa7, 0x79, 0xd3, 0xf7, 0x9d, 0xa6, 0x35, 0xe8, 0xd7, + 0xce, 0xad, 0x1d, 0x83, 0x8a, 0x8f, 0xe5, 0x82, 0xfe, 0x02, 0xe0, 0x82, 0xae, 0xa2, 0x29, 0x86, + 0x35, 0x19, 0x40, 0x3a, 0xea, 0x00, 0xe6, 0x71, 0x54, 0x1c, 0x2f, 0xe8, 0x38, 0x2e, 0x0c, 0xe9, + 0xf1, 0x30, 0x35, 0xf4, 0x77, 0x00, 0x67, 0x3a, 0x34, 0xa0, 0x5e, 0x87, 0x7a, 0x6d, 0xc1, 0x75, + 0x79, 0x24, 0x93, 0x66, 0x9e, 0xeb, 0x46, 0x0a, 0x42, 0xd1, 0x6c, 0x68, 0x9a, 0x33, 0x69, 0xd5, + 0x51, 0xbf, 0x76, 0x3e, 0x59, 0x9a, 0xd6, 0xe0, 0x0c, 0x4b, 0xf4, 0x01, 0x80, 0x73, 0xc9, 0x01, + 0xa8, 0x27, 0xe5, 0xf2, 0x18, 0xf3, 0x40, 0xb6, 0xaf, 0x6b, 0x59, 0x40, 0x9c, 0x67, 0x80, 0xfe, + 0x0a, 0x44, 0xa7, 0x16, 0xcf, 0x8d, 0xcc, 0xaa, 0xcb, 0x58, 0xbe, 0x33, 0xf2, 0x58, 0x1a, 0x04, + 0x15, 0xca, 0x17, 0x93, 0x56, 0xd0, 0x68, 0x8e, 0xfa, 0xb5, 0xc5, 0x74, 0x24, 0x8d, 0x02, 0xa7, + 0x19, 0xa2, 0x9f, 0x02, 0x38, 0x43, 0x93, 0x8e, 0x9b, 0x59, 0x57, 0x46, 0x12, 0xc4, 0x63, 0x9b, + 0x78, 0xf5, 0x37, 0xa6, 0x94, 0x8a, 0xe1, 0x0c, 0xb6, 0xe8, 0x20, 0xe9, 0x01, 0x71, 0x03, 0x87, + 0x5a, 0x9f, 0x1b, 0x71, 0x07, 0x79, 0x43, 0xf9, 0xc5, 0x31, 0xc0, 0x92, 0x98, 0x7c, 0x72, 0x37, + 0x07, 0xcd, 0xc3, 0xe2, 0x3e, 0x3d, 0x54, 0x8d, 0x3d, 0x16, 0x3f, 0x51, 0x07, 0x96, 0x7a, 0xc4, + 0x89, 0xe2, 0xe1, 0x6d, 0xc4, 0x55, 0x17, 0x2b, 0xe7, 0xaf, 0x15, 0x5e, 0x05, 0x4b, 0x8f, 0x00, + 0x3c, 0x7f, 0xfc, 0x85, 0x7e, 0xa6, 0xb4, 0x7e, 0x07, 0xe0, 0xc2, 0xd0, 0xdd, 0x3d, 0x86, 0xd1, + 0x83, 0x2c, 0xa3, 0x37, 0x46, 0x7d, 0x09, 0x5b, 0x3c, 0xb4, 0xbd, 0xae, 0xec, 0x3c, 0xd2, 0xf4, + 0x7e, 0x01, 0xe0, 0x7c, 0xfe, 0x3a, 0x3c, 0xcb, 0x78, 0xd5, 0x1f, 0x15, 0xe0, 0xf9, 0xe3, 0x1b, + 0x26, 0x14, 0x9a, 0xc9, 0x70, 0x3c, 0x13, 0x36, 0x4c, 0xa6, 0x4c, 0x33, 0x54, 0xbe, 0x07, 0x60, + 0xe5, 0xbe, 0xb1, 0x8b, 0xff, 0x53, 0x33, 0xf2, 0xd9, 0x3e, 0xae, 0x3f, 0x89, 0x82, 0xe1, 0x34, + 0x6e, 0xfd, 0x6f, 0x00, 0x2e, 0x1e, 0x5b, 0x58, 0xc5, 0x08, 0x4a, 0x1c, 0xc7, 0x7f, 0xa8, 0xfe, + 0x44, 0x93, 0xfa, 0x93, 0xd9, 0x9a, 0x94, 0x62, 0xad, 0x4d, 0x45, 0xaf, 0xf0, 0x69, 0x45, 0xaf, + 0xfe, 0x4f, 0x00, 0x2f, 0x7e, 0x5c, 0x26, 0x3e, 0x93, 0x23, 0x5d, 0x81, 0x65, 0xdd, 0x14, 0x1d, + 0xca, 0xe3, 0xd4, 0x73, 0x80, 0x2e, 0x1a, 0xf2, 0xbf, 0xe7, 0xea, 0x57, 0xf3, 0xea, 0xe3, 0x27, + 0xd5, 0x33, 0x1f, 0x3e, 0xa9, 0x9e, 0xf9, 0xe8, 0x49, 0xf5, 0xcc, 0x0f, 0x06, 0x55, 0xf0, 0x78, + 0x50, 0x05, 0x1f, 0x0e, 0xaa, 0xe0, 0xa3, 0x41, 0x15, 0xfc, 0x6b, 0x50, 0x05, 0xbf, 0xfc, 0x77, + 0xf5, 0xcc, 0x77, 0xa6, 0x34, 0xf8, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x5b, 0x62, 0x04, + 0xd6, 0x21, 0x00, 0x00, } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto index 46cfd1ca7..4cdaf2289 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,11 +24,36 @@ package k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; +// CustomResourceColumnDefinition specifies a column for server side printing. +message CustomResourceColumnDefinition { + // name is a human readable name for the column. + optional string name = 1; + + // type is an OpenAPI type definition for this column. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + optional string type = 2; + + // format is an optional OpenAPI type definition for this column. The 'name' format is applied + // to the primary identifier column to assist in clients identifying column is the resource name. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + optional string format = 3; + + // description is a human readable description of this column. + optional string description = 4; + + // priority is an integer defining the relative importance of this column compared to others. Lower + // numbers are considered higher priority. Columns that may be omitted in limited space scenarios + // should be given a higher priority. + optional int32 priority = 5; + + // JSONPath is a simple JSON path, i.e. with array notation. + optional string JSONPath = 6; +} + // CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format // <.spec.name>.<.spec.group>. message CustomResourceDefinition { @@ -100,6 +125,10 @@ message CustomResourceDefinitionSpec { optional string group = 1; // Version is the version this resource belongs in + // Should be always first item in Versions field if provided. + // Optional, but at least one of Version or Versions must be set. + // Deprecated: Please use `Versions`. + // +optional optional string version = 2; // Names are the names used to describe this custom resource @@ -113,10 +142,24 @@ message CustomResourceDefinitionSpec { optional CustomResourceValidation validation = 5; // Subresources describes the subresources for CustomResources - // This field is alpha-level and should only be sent to servers that enable - // subresources via the CustomResourceSubresources feature gate. // +optional optional CustomResourceSubresources subresources = 6; + + // Versions is the list of all supported versions for this resource. + // If Version field is provided, this field is optional. + // Validation: All versions must use the same validation schema for now. i.e., top + // level Validation field is applied to all of these versions. + // Order: The version name will be used to compute the order. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing + // major version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. + repeated CustomResourceDefinitionVersion versions = 7; + + // AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column. + repeated CustomResourceColumnDefinition additionalPrinterColumns = 8; } // CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition @@ -127,6 +170,26 @@ message CustomResourceDefinitionStatus { // AcceptedNames are the names that are actually being used to serve discovery // They may be different than the names in spec. optional CustomResourceDefinitionNames acceptedNames = 2; + + // StoredVersions are all versions of CustomResources that were ever persisted. Tracking these + // versions allows a migration path for stored versions in etcd. The field is mutable + // so the migration controller can first finish a migration to another version (i.e. + // that no old objects are left in the storage), and then remove the rest of the + // versions from this list. + // None of the versions in this list can be removed from the spec.Versions field. + repeated string storedVersions = 3; +} + +message CustomResourceDefinitionVersion { + // Name is the version name, e.g. “v1”, “v2beta1”, etc. + optional string name = 1; + + // Served is a flag enabling/disabling this version from being served via REST APIs + optional bool served = 2; + + // Storage flags the version as storage version. There must be exactly one + // flagged as storage version. + optional bool storage = 3; } // CustomResourceSubresourceScale defines how to serve the scale subresource for CustomResources. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go index d8f9f164e..9a8fad3b7 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go @@ -45,6 +45,7 @@ func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &sch); err != nil { return err } + nw.Allows = true nw.Schema = &sch case len(data) == 4 && string(data) == "true": nw.Allows = true diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go index 0c6d4d4b5..99065ff95 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go @@ -34,13 +34,13 @@ func TestJSONSchemaPropsOrBoolUnmarshalJSON(t *testing.T) { }{ {`{}`, JSONSchemaPropsOrBoolHolder{}}, - {`{"val1": {}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{}}}}, - {`{"val1": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{Type: "string"}}}}, + {`{"val1": {}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{}}}}, + {`{"val1": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{Type: "string"}}}}, {`{"val1": false}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{}}}, {`{"val1": true}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true}}}, - {`{"val2": {}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{}}}}, - {`{"val2": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{Type: "string"}}}}, + {`{"val2": {}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{}}}}, + {`{"val2": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{Type: "string"}}}}, {`{"val2": false}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{}}}, {`{"val2": true}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true}}}, } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go index 3a4da9aea..2080cc821 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go @@ -25,7 +25,11 @@ type CustomResourceDefinitionSpec struct { // Group is the group this resource belongs in Group string `json:"group" protobuf:"bytes,1,opt,name=group"` // Version is the version this resource belongs in - Version string `json:"version" protobuf:"bytes,2,opt,name=version"` + // Should be always first item in Versions field if provided. + // Optional, but at least one of Version or Versions must be set. + // Deprecated: Please use `Versions`. + // +optional + Version string `json:"version,omitempty" protobuf:"bytes,2,opt,name=version"` // Names are the names used to describe this custom resource Names CustomResourceDefinitionNames `json:"names" protobuf:"bytes,3,opt,name=names"` // Scope indicates whether this resource is cluster or namespace scoped. Default is namespaced @@ -34,10 +38,54 @@ type CustomResourceDefinitionSpec struct { // +optional Validation *CustomResourceValidation `json:"validation,omitempty" protobuf:"bytes,5,opt,name=validation"` // Subresources describes the subresources for CustomResources - // This field is alpha-level and should only be sent to servers that enable - // subresources via the CustomResourceSubresources feature gate. // +optional Subresources *CustomResourceSubresources `json:"subresources,omitempty" protobuf:"bytes,6,opt,name=subresources"` + // Versions is the list of all supported versions for this resource. + // If Version field is provided, this field is optional. + // Validation: All versions must use the same validation schema for now. i.e., top + // level Validation field is applied to all of these versions. + // Order: The version name will be used to compute the order. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing + // major version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. + Versions []CustomResourceDefinitionVersion `json:"versions,omitempty" protobuf:"bytes,7,rep,name=versions"` + // AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column. + AdditionalPrinterColumns []CustomResourceColumnDefinition `json:"additionalPrinterColumns,omitempty" protobuf:"bytes,8,rep,name=additionalPrinterColumns"` +} + +type CustomResourceDefinitionVersion struct { + // Name is the version name, e.g. “v1”, “v2beta1”, etc. + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` + // Served is a flag enabling/disabling this version from being served via REST APIs + Served bool `json:"served" protobuf:"varint,2,opt,name=served"` + // Storage flags the version as storage version. There must be exactly one + // flagged as storage version. + Storage bool `json:"storage" protobuf:"varint,3,opt,name=storage"` +} + +// CustomResourceColumnDefinition specifies a column for server side printing. +type CustomResourceColumnDefinition struct { + // name is a human readable name for the column. + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` + // type is an OpenAPI type definition for this column. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Type string `json:"type" protobuf:"bytes,2,opt,name=type"` + // format is an optional OpenAPI type definition for this column. The 'name' format is applied + // to the primary identifier column to assist in clients identifying column is the resource name. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Format string `json:"format,omitempty" protobuf:"bytes,3,opt,name=format"` + // description is a human readable description of this column. + Description string `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"` + // priority is an integer defining the relative importance of this column compared to others. Lower + // numbers are considered higher priority. Columns that may be omitted in limited space scenarios + // should be given a higher priority. + Priority int32 `json:"priority,omitempty" protobuf:"bytes,5,opt,name=priority"` + + // JSONPath is a simple JSON path, i.e. with array notation. + JSONPath string `json:"JSONPath" protobuf:"bytes,6,opt,name=JSONPath"` } // CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition @@ -119,6 +167,14 @@ type CustomResourceDefinitionStatus struct { // AcceptedNames are the names that are actually being used to serve discovery // They may be different than the names in spec. AcceptedNames CustomResourceDefinitionNames `json:"acceptedNames" protobuf:"bytes,2,opt,name=acceptedNames"` + + // StoredVersions are all versions of CustomResources that were ever persisted. Tracking these + // versions allows a migration path for stored versions in etcd. The field is mutable + // so the migration controller can first finish a migration to another version (i.e. + // that no old objects are left in the storage), and then remove the rest of the + // versions from this list. + // None of the versions in this list can be removed from the spec.Versions field. + StoredVersions []string `json:"storedVersions" protobuf:"bytes,3,rep,name=storedVersions"` } // CustomResourceCleanupFinalizer is the name of the finalizer which will delete instances of diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go index 9edd276d8..9776731cf 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go @@ -62,6 +62,19 @@ type JSON struct { Raw []byte `protobuf:"bytes,1,opt,name=raw"` } +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ JSON) OpenAPISchemaType() []string { + // TODO: return actual types when anyOf is supported + return []string{} +} + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +func (_ JSON) OpenAPISchemaFormat() string { return "" } + // JSONSchemaURL represents a schema url. type JSONSchemaURL string @@ -72,6 +85,19 @@ type JSONSchemaPropsOrArray struct { JSONSchemas []JSONSchemaProps `protobuf:"bytes,2,rep,name=jSONSchemas"` } +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ JSONSchemaPropsOrArray) OpenAPISchemaType() []string { + // TODO: return actual types when anyOf is supported + return []string{} +} + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +func (_ JSONSchemaPropsOrArray) OpenAPISchemaFormat() string { return "" } + // JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value. // Defaults to true for the boolean property. type JSONSchemaPropsOrBool struct { @@ -79,6 +105,19 @@ type JSONSchemaPropsOrBool struct { Schema *JSONSchemaProps `protobuf:"bytes,2,opt,name=schema"` } +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ JSONSchemaPropsOrBool) OpenAPISchemaType() []string { + // TODO: return actual types when anyOf is supported + return []string{} +} + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +func (_ JSONSchemaPropsOrBool) OpenAPISchemaFormat() string { return "" } + // JSONSchemaDependencies represent a dependencies property. type JSONSchemaDependencies map[string]JSONSchemaPropsOrStringArray @@ -88,6 +127,19 @@ type JSONSchemaPropsOrStringArray struct { Property []string `protobuf:"bytes,2,rep,name=property"` } +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaType() []string { + // TODO: return actual types when anyOf is supported + return []string{} +} + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaFormat() string { return "" } + // JSONSchemaDefinitions contains the models explicitly defined in this spec. type JSONSchemaDefinitions map[string]JSONSchemaProps diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go index 6cd42fe5b..bcb2527c8 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -36,6 +36,8 @@ func init() { // Public to allow building arbitrary schemes. func RegisterConversions(scheme *runtime.Scheme) error { return scheme.AddGeneratedConversionFuncs( + Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition, + Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition, Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition, Convert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition, Convert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition, @@ -48,6 +50,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomResourceDefinitionSpec, Convert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomResourceDefinitionStatus, Convert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus, + Convert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion, + Convert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion, Convert_v1beta1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale, Convert_apiextensions_CustomResourceSubresourceScale_To_v1beta1_CustomResourceSubresourceScale, Convert_v1beta1_CustomResourceSubresourceStatus_To_apiextensions_CustomResourceSubresourceStatus, @@ -71,6 +75,36 @@ func RegisterConversions(scheme *runtime.Scheme) error { ) } +func autoConvert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in *CustomResourceColumnDefinition, out *apiextensions.CustomResourceColumnDefinition, s conversion.Scope) error { + out.Name = in.Name + out.Type = in.Type + out.Format = in.Format + out.Description = in.Description + out.Priority = in.Priority + out.JSONPath = in.JSONPath + return nil +} + +// Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition is an autogenerated conversion function. +func Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in *CustomResourceColumnDefinition, out *apiextensions.CustomResourceColumnDefinition, s conversion.Scope) error { + return autoConvert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in, out, s) +} + +func autoConvert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in *apiextensions.CustomResourceColumnDefinition, out *CustomResourceColumnDefinition, s conversion.Scope) error { + out.Name = in.Name + out.Type = in.Type + out.Format = in.Format + out.Description = in.Description + out.Priority = in.Priority + out.JSONPath = in.JSONPath + return nil +} + +// Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition is an autogenerated conversion function. +func Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in *apiextensions.CustomResourceColumnDefinition, out *CustomResourceColumnDefinition, s conversion.Scope) error { + return autoConvert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in, out, s) +} + func autoConvert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(in *CustomResourceDefinition, out *apiextensions.CustomResourceDefinition, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(&in.Spec, &out.Spec, s); err != nil { @@ -220,6 +254,8 @@ func autoConvert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomRes out.Validation = nil } out.Subresources = (*apiextensions.CustomResourceSubresources)(unsafe.Pointer(in.Subresources)) + out.Versions = *(*[]apiextensions.CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions)) + out.AdditionalPrinterColumns = *(*[]apiextensions.CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns)) return nil } @@ -245,6 +281,8 @@ func autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomRes out.Validation = nil } out.Subresources = (*CustomResourceSubresources)(unsafe.Pointer(in.Subresources)) + out.Versions = *(*[]CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions)) + out.AdditionalPrinterColumns = *(*[]CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns)) return nil } @@ -258,6 +296,7 @@ func autoConvert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomR if err := Convert_v1beta1_CustomResourceDefinitionNames_To_apiextensions_CustomResourceDefinitionNames(&in.AcceptedNames, &out.AcceptedNames, s); err != nil { return err } + out.StoredVersions = *(*[]string)(unsafe.Pointer(&in.StoredVersions)) return nil } @@ -271,6 +310,7 @@ func autoConvert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomR if err := Convert_apiextensions_CustomResourceDefinitionNames_To_v1beta1_CustomResourceDefinitionNames(&in.AcceptedNames, &out.AcceptedNames, s); err != nil { return err } + out.StoredVersions = *(*[]string)(unsafe.Pointer(&in.StoredVersions)) return nil } @@ -279,6 +319,30 @@ func Convert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResou return autoConvert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus(in, out, s) } +func autoConvert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion(in *CustomResourceDefinitionVersion, out *apiextensions.CustomResourceDefinitionVersion, s conversion.Scope) error { + out.Name = in.Name + out.Served = in.Served + out.Storage = in.Storage + return nil +} + +// Convert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion is an autogenerated conversion function. +func Convert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion(in *CustomResourceDefinitionVersion, out *apiextensions.CustomResourceDefinitionVersion, s conversion.Scope) error { + return autoConvert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion(in, out, s) +} + +func autoConvert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion(in *apiextensions.CustomResourceDefinitionVersion, out *CustomResourceDefinitionVersion, s conversion.Scope) error { + out.Name = in.Name + out.Served = in.Served + out.Storage = in.Storage + return nil +} + +// Convert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion is an autogenerated conversion function. +func Convert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion(in *apiextensions.CustomResourceDefinitionVersion, out *CustomResourceDefinitionVersion, s conversion.Scope) error { + return autoConvert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion(in, out, s) +} + func autoConvert_v1beta1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale(in *CustomResourceSubresourceScale, out *apiextensions.CustomResourceSubresourceScale, s conversion.Scope) error { out.SpecReplicasPath = in.SpecReplicasPath out.StatusReplicasPath = in.StatusReplicasPath diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go index 35c3a0b75..d2c1cebf2 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,22 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceColumnDefinition) DeepCopyInto(out *CustomResourceColumnDefinition) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceColumnDefinition. +func (in *CustomResourceColumnDefinition) DeepCopy() *CustomResourceColumnDefinition { + if in == nil { + return nil + } + out := new(CustomResourceColumnDefinition) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) { *out = *in @@ -150,6 +166,16 @@ func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefiniti (*in).DeepCopyInto(*out) } } + if in.Versions != nil { + in, out := &in.Versions, &out.Versions + *out = make([]CustomResourceDefinitionVersion, len(*in)) + copy(*out, *in) + } + if in.AdditionalPrinterColumns != nil { + in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns + *out = make([]CustomResourceColumnDefinition, len(*in)) + copy(*out, *in) + } return } @@ -174,6 +200,11 @@ func (in *CustomResourceDefinitionStatus) DeepCopyInto(out *CustomResourceDefini } } in.AcceptedNames.DeepCopyInto(&out.AcceptedNames) + if in.StoredVersions != nil { + in, out := &in.StoredVersions, &out.StoredVersions + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -187,6 +218,22 @@ func (in *CustomResourceDefinitionStatus) DeepCopy() *CustomResourceDefinitionSt return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceDefinitionVersion) DeepCopyInto(out *CustomResourceDefinitionVersion) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionVersion. +func (in *CustomResourceDefinitionVersion) DeepCopy() *CustomResourceDefinitionVersion { + if in == nil { + return nil + } + out := new(CustomResourceDefinitionVersion) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceSubresourceScale) DeepCopyInto(out *CustomResourceSubresourceScale) { *out = *in diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go index 546f33eda..f65f47a03 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go index 713fcfa90..1179226dd 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go @@ -22,6 +22,7 @@ import ( "strings" genericvalidation "k8s.io/apimachinery/pkg/api/validation" + "k8s.io/apimachinery/pkg/util/sets" validationutil "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -31,6 +32,11 @@ import ( apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" ) +var ( + printerColumnDatatypes = sets.NewString("integer", "number", "string", "boolean", "date") + customResourceColumnDefinitionFormats = sets.NewString("int32", "int64", "float", "double", "byte", "date", "date-time", "password") +) + // ValidateCustomResourceDefinition statically validates func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinition) field.ErrorList { nameValidationFn := func(name string, prefix bool) []string { @@ -45,6 +51,7 @@ func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinitio allErrs := genericvalidation.ValidateObjectMeta(&obj.ObjectMeta, false, nameValidationFn, field.NewPath("metadata")) allErrs = append(allErrs, ValidateCustomResourceDefinitionSpec(&obj.Spec, field.NewPath("spec"))...) allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...) + allErrs = append(allErrs, ValidateCustomResourceDefinitionStoredVersions(obj.Status.StoredVersions, obj.Spec.Versions, field.NewPath("status").Child("storedVersions"))...) return allErrs } @@ -53,6 +60,34 @@ func ValidateCustomResourceDefinitionUpdate(obj, oldObj *apiextensions.CustomRes allErrs := genericvalidation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &oldObj.ObjectMeta, field.NewPath("metadata")) allErrs = append(allErrs, ValidateCustomResourceDefinitionSpecUpdate(&obj.Spec, &oldObj.Spec, apiextensions.IsCRDConditionTrue(oldObj, apiextensions.Established), field.NewPath("spec"))...) allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...) + allErrs = append(allErrs, ValidateCustomResourceDefinitionStoredVersions(obj.Status.StoredVersions, obj.Spec.Versions, field.NewPath("status").Child("storedVersions"))...) + return allErrs +} + +// ValidateCustomResourceDefinitionStoredVersions statically validates +func ValidateCustomResourceDefinitionStoredVersions(storedVersions []string, versions []apiextensions.CustomResourceDefinitionVersion, fldPath *field.Path) field.ErrorList { + if len(storedVersions) == 0 { + return field.ErrorList{field.Invalid(fldPath, storedVersions, "must have at least one stored version")} + } + allErrs := field.ErrorList{} + storedVersionsMap := map[string]int{} + for i, v := range storedVersions { + storedVersionsMap[v] = i + } + for _, v := range versions { + _, ok := storedVersionsMap[v.Name] + if v.Storage && !ok { + allErrs = append(allErrs, field.Invalid(fldPath, v, "must have the storage version "+v.Name)) + } + if ok { + delete(storedVersionsMap, v.Name) + } + } + + for v, i := range storedVersionsMap { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i), v, "must appear in spec.versions")) + } + return allErrs } @@ -75,12 +110,6 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi allErrs = append(allErrs, field.Invalid(fldPath.Child("group"), spec.Group, "should be a domain with at least one dot")) } - if len(spec.Version) == 0 { - allErrs = append(allErrs, field.Required(fldPath.Child("version"), "")) - } else if errs := validationutil.IsDNS1035Label(spec.Version); len(errs) > 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, strings.Join(errs, ","))) - } - switch spec.Scope { case "": allErrs = append(allErrs, field.Required(fldPath.Child("scope"), "")) @@ -89,6 +118,37 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi allErrs = append(allErrs, field.NotSupported(fldPath.Child("scope"), spec.Scope, []string{string(apiextensions.ClusterScoped), string(apiextensions.NamespaceScoped)})) } + storageFlagCount := 0 + versionsMap := map[string]bool{} + uniqueNames := true + for i, version := range spec.Versions { + if version.Storage { + storageFlagCount++ + } + if versionsMap[version.Name] { + uniqueNames = false + } else { + versionsMap[version.Name] = true + } + if errs := validationutil.IsDNS1035Label(version.Name); len(errs) > 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("versions").Index(i).Child("name"), spec.Versions[i].Name, strings.Join(errs, ","))) + } + } + if !uniqueNames { + allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "must contain unique version names")) + } + if storageFlagCount != 1 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "must have exactly one version marked as storage version")) + } + if len(spec.Version) != 0 { + if errs := validationutil.IsDNS1035Label(spec.Version); len(errs) > 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, strings.Join(errs, ","))) + } + if len(spec.Versions) >= 1 && spec.Versions[0].Name != spec.Version { + allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, "must match the first version in spec.versions")) + } + } + // in addition to the basic name restrictions, some names are required for spec, but not for status if len(spec.Names.Plural) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("names", "plural"), "")) @@ -106,7 +166,11 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi allErrs = append(allErrs, ValidateCustomResourceDefinitionNames(&spec.Names, fldPath.Child("names"))...) if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) { - allErrs = append(allErrs, ValidateCustomResourceDefinitionValidation(spec.Validation, fldPath.Child("validation"))...) + statusEnabled := false + if spec.Subresources != nil && spec.Subresources.Status != nil { + statusEnabled = true + } + allErrs = append(allErrs, ValidateCustomResourceDefinitionValidation(spec.Validation, statusEnabled, fldPath.Child("validation"))...) } else if spec.Validation != nil { allErrs = append(allErrs, field.Forbidden(fldPath.Child("validation"), "disabled by feature-gate CustomResourceValidation")) } @@ -117,6 +181,12 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi allErrs = append(allErrs, field.Forbidden(fldPath.Child("subresources"), "disabled by feature-gate CustomResourceSubresources")) } + for i := range spec.AdditionalPrinterColumns { + if errs := ValidateCustomResourceColumnDefinition(&spec.AdditionalPrinterColumns[i], fldPath.Child("columns").Index(i)); len(errs) > 0 { + allErrs = append(allErrs, errs...) + } + } + return allErrs } @@ -126,7 +196,6 @@ func ValidateCustomResourceDefinitionSpecUpdate(spec, oldSpec *apiextensions.Cus if established { // these effect the storage and cannot be changed therefore - allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Version, oldSpec.Version, fldPath.Child("version"))...) allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Scope, oldSpec.Scope, fldPath.Child("scope"))...) allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Names.Kind, oldSpec.Names.Kind, fldPath.Child("names", "kind"))...) } @@ -181,13 +250,40 @@ func ValidateCustomResourceDefinitionNames(names *apiextensions.CustomResourceDe return allErrs } +// ValidateCustomResourceColumnDefinition statically validates a printer column. +func ValidateCustomResourceColumnDefinition(col *apiextensions.CustomResourceColumnDefinition, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if len(col.Name) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("header"), "")) + } + + if len(col.Type) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("type"), fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ",")))) + } else if !printerColumnDatatypes.Has(col.Type) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), col.Type, fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ",")))) + } + + if len(col.Format) > 0 && !customResourceColumnDefinitionFormats.Has(col.Format) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("format"), col.Format, fmt.Sprintf("must be one of %s", strings.Join(customResourceColumnDefinitionFormats.List(), ",")))) + } + + if len(col.JSONPath) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("path"), "")) + } else if errs := validateSimpleJSONPath(col.JSONPath, fldPath.Child("path")); len(errs) > 0 { + allErrs = append(allErrs, errs...) + } + + return allErrs +} + // specStandardValidator applies validations for different OpenAPI specification versions. type specStandardValidator interface { validate(spec *apiextensions.JSONSchemaProps, fldPath *field.Path) field.ErrorList } // ValidateCustomResourceDefinitionValidation statically validates -func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiextensions.CustomResourceValidation, fldPath *field.Path) field.ErrorList { +func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiextensions.CustomResourceValidation, statusSubresourceEnabled bool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if customResourceValidation == nil { @@ -195,21 +291,19 @@ func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiext } if schema := customResourceValidation.OpenAPIV3Schema; schema != nil { - // if subresources are enabled, only properties is allowed inside the root schema - if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) { + // if subresources are enabled, only "properties", "required" and "description" are allowed inside the root schema + if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && statusSubresourceEnabled { v := reflect.ValueOf(schema).Elem() - fieldsPresent := 0 - for i := 0; i < v.NumField(); i++ { - field := v.Field(i).Interface() - if !reflect.DeepEqual(field, reflect.Zero(reflect.TypeOf(field)).Interface()) { - fieldsPresent++ + // skip zero values + if value := v.Field(i).Interface(); reflect.DeepEqual(value, reflect.Zero(reflect.TypeOf(value)).Interface()) { + continue } - } - if fieldsPresent > 1 || (fieldsPresent == 1 && v.FieldByName("Properties").IsNil()) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), *schema, fmt.Sprintf("if subresources for custom resources are enabled, only properties can be used at the root of the schema"))) - return allErrs + if name := v.Type().Field(i).Name; name != "Properties" && name != "Required" && name != "Description" { + allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), *schema, fmt.Sprintf(`must only have "properties", "required" or "description" at the root if the status subresource is enabled`))) + break + } } } @@ -240,14 +334,36 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch allErrs = append(allErrs, field.Forbidden(fldPath.Child("uniqueItems"), "uniqueItems cannot be set to true since the runtime complexity becomes quadratic")) } - // additionalProperties contradicts Kubernetes API convention to ignore unknown fields + // additionalProperties and properties are mutual exclusive because otherwise they + // contradict Kubernetes' API convention to ignore unknown fields. + // + // In other words: + // - properties are for structs, + // - additionalProperties are for map[string]interface{} + // + // Note: when patternProperties is added to OpenAPI some day, this will have to be + // restricted like additionalProperties. if schema.AdditionalProperties != nil { - if schema.AdditionalProperties.Allows == false { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalProperties"), "additionalProperties cannot be set to false")) + if len(schema.Properties) != 0 { + if schema.AdditionalProperties.Allows == false || schema.AdditionalProperties.Schema != nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalProperties"), "additionalProperties and properties are mutual exclusive")) + } } allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.AdditionalProperties.Schema, fldPath.Child("additionalProperties"), ssv)...) } + if len(schema.Properties) != 0 { + for property, jsonSchema := range schema.Properties { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("properties").Key(property), ssv)...) + } + } + + if len(schema.PatternProperties) != 0 { + for property, jsonSchema := range schema.PatternProperties { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("patternProperties").Key(property), ssv)...) + } + } + if schema.AdditionalItems != nil { allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.AdditionalItems.Schema, fldPath.Child("additionalItems"), ssv)...) } @@ -255,32 +371,20 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.Not, fldPath.Child("not"), ssv)...) if len(schema.AllOf) != 0 { - for _, jsonSchema := range schema.AllOf { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("allOf"), ssv)...) + for i, jsonSchema := range schema.AllOf { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("allOf").Index(i), ssv)...) } } if len(schema.OneOf) != 0 { - for _, jsonSchema := range schema.OneOf { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("oneOf"), ssv)...) + for i, jsonSchema := range schema.OneOf { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("oneOf").Index(i), ssv)...) } } if len(schema.AnyOf) != 0 { - for _, jsonSchema := range schema.AnyOf { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("anyOf"), ssv)...) - } - } - - if len(schema.Properties) != 0 { - for property, jsonSchema := range schema.Properties { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("properties").Key(property), ssv)...) - } - } - - if len(schema.PatternProperties) != 0 { - for property, jsonSchema := range schema.PatternProperties { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("patternProperties").Key(property), ssv)...) + for i, jsonSchema := range schema.AnyOf { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("anyOf").Index(i), ssv)...) } } @@ -293,8 +397,8 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch if schema.Items != nil { allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.Items.Schema, fldPath.Child("items"), ssv)...) if len(schema.Items.JSONSchemas) != 0 { - for _, jsonSchema := range schema.Items.JSONSchemas { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("items"), ssv)...) + for i, jsonSchema := range schema.Items.JSONSchemas { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("items").Index(i), ssv)...) } } } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go index dd712c94f..68dc8aaed 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go @@ -41,17 +41,159 @@ func unsupported(path ...string) validationMatch { func immutable(path ...string) validationMatch { return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeInvalid} } +func forbidden(path ...string) validationMatch { + return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeForbidden} +} func (v validationMatch) matches(err *field.Error) bool { return err.Type == v.errorType && err.Field == v.path.String() } func TestValidateCustomResourceDefinition(t *testing.T) { + singleVersionList := []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + } tests := []struct { name string resource *apiextensions.CustomResourceDefinition errors []validationMatch }{ + { + name: "no_storage_version", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: false, + }, + { + Name: "version2", + Served: true, + Storage: false, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{ + invalid("spec", "versions"), + }, + }, + { + name: "multiple_storage_version", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + { + Name: "version2", + Served: true, + Storage: true, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{ + invalid("spec", "versions"), + invalid("status", "storedVersions"), + }, + }, + { + name: "missing_storage_version_in_stored_versions", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: false, + }, + { + Name: "version2", + Served: true, + Storage: true, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{ + invalid("status", "storedVersions"), + }, + }, + { + name: "empty_stored_version", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{}, + }, + }, + errors: []validationMatch{ + invalid("status", "storedVersions"), + }, + }, { name: "mismatched name", resource: &apiextensions.CustomResourceDefinition{ @@ -64,8 +206,9 @@ func TestValidateCustomResourceDefinition(t *testing.T) { }, }, errors: []validationMatch{ + invalid("status", "storedVersions"), invalid("metadata", "name"), - required("spec", "version"), + invalid("spec", "versions"), required("spec", "scope"), required("spec", "names", "singular"), required("spec", "names", "kind"), @@ -78,9 +221,10 @@ func TestValidateCustomResourceDefinition(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, }, errors: []validationMatch{ + invalid("status", "storedVersions"), invalid("metadata", "name"), + invalid("spec", "versions"), required("spec", "group"), - required("spec", "version"), required("spec", "scope"), required("spec", "names", "plural"), required("spec", "names", "singular"), @@ -113,9 +257,9 @@ func TestValidateCustomResourceDefinition(t *testing.T) { }, }, errors: []validationMatch{ + invalid("status", "storedVersions"), invalid("metadata", "name"), invalid("spec", "group"), - invalid("spec", "version"), unsupported("spec", "scope"), invalid("spec", "names", "plural"), invalid("spec", "names", "singular"), @@ -127,6 +271,8 @@ func TestValidateCustomResourceDefinition(t *testing.T) { invalid("status", "acceptedNames", "kind"), invalid("status", "acceptedNames", "listKind"), // invalid format invalid("status", "acceptedNames", "listKind"), // kind == listKind + invalid("spec", "versions"), + invalid("spec", "version"), }, }, { @@ -134,8 +280,9 @@ func TestValidateCustomResourceDefinition(t *testing.T) { resource: &apiextensions.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "plural.group"}, Spec: apiextensions.CustomResourceDefinitionSpec{ - Group: "group.c(*&om", - Version: "version", + Group: "group.c(*&om", + Version: "version", + Versions: singleVersionList, Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -150,6 +297,7 @@ func TestValidateCustomResourceDefinition(t *testing.T) { Kind: "matching", ListKind: "matching", }, + StoredVersions: []string{"version"}, }, }, errors: []validationMatch{ @@ -160,6 +308,70 @@ func TestValidateCustomResourceDefinition(t *testing.T) { invalid("status", "acceptedNames", "listKind"), }, }, + { + name: "additionalProperties and properties forbidden", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Versions: singleVersionList, + Scope: apiextensions.NamespaceScoped, + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Validation: &apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + Properties: map[string]apiextensions.JSONSchemaProps{ + "foo": {}, + }, + AdditionalProperties: &apiextensions.JSONSchemaPropsOrBool{Allows: false}, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{ + forbidden("spec", "validation", "openAPIV3Schema", "additionalProperties"), + }, + }, + { + name: "additionalProperties without properties allowed (map[string]string)", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Versions: singleVersionList, + Scope: apiextensions.NamespaceScoped, + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Validation: &apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + AdditionalProperties: &apiextensions.JSONSchemaPropsOrBool{ + Allows: true, + Schema: &apiextensions.JSONSchemaProps{ + Type: "string", + }, + }, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{}, + }, } for _, tc := range tests { @@ -206,7 +418,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -231,7 +450,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -246,6 +472,7 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Kind: "kind", ListKind: "listkind", }, + StoredVersions: []string{"version"}, }, }, errors: []validationMatch{}, @@ -260,7 +487,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -288,7 +522,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -303,10 +544,91 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Kind: "kind", ListKind: "listkind", }, + StoredVersions: []string{"version"}, }, }, errors: []validationMatch{}, }, + { + name: "version-deleted", + old: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "plural.group.com", + ResourceVersion: "42", + }, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + { + Name: "version2", + Served: true, + Storage: false, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + AcceptedNames: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + StoredVersions: []string{"version", "version2"}, + Conditions: []apiextensions.CustomResourceDefinitionCondition{ + {Type: apiextensions.Established, Status: apiextensions.ConditionTrue}, + }, + }, + }, + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "plural.group.com", + ResourceVersion: "42", + }, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + AcceptedNames: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + StoredVersions: []string{"version", "version2"}, + }, + }, + errors: []validationMatch{ + invalid("status", "storedVersions[1]"), + }, + }, { name: "changes", old: &apiextensions.CustomResourceDefinition{ @@ -317,7 +639,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -345,7 +674,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "abc.com", Version: "version2", - Scope: apiextensions.ResourceScope("Namespaced"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version2", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Namespaced"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural2", Singular: "singular2", @@ -360,6 +696,7 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Kind: "kind2", ListKind: "listkind2", }, + StoredVersions: []string{"version2"}, }, }, errors: []validationMatch{ @@ -377,7 +714,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -405,7 +749,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "abc.com", Version: "version2", - Scope: apiextensions.ResourceScope("Namespaced"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version2", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Namespaced"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural2", Singular: "singular2", @@ -420,11 +771,11 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Kind: "kind2", ListKind: "listkind2", }, + StoredVersions: []string{"version2"}, }, }, errors: []validationMatch{ immutable("spec", "group"), - immutable("spec", "version"), immutable("spec", "scope"), immutable("spec", "names", "kind"), immutable("spec", "names", "plural"), @@ -458,3 +809,69 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { } } } + +func TestValidateCustomResourceDefinitionValidation(t *testing.T) { + tests := []struct { + name string + input apiextensions.CustomResourceValidation + statusEnabled bool + wantError bool + }{ + { + name: "empty", + input: apiextensions.CustomResourceValidation{}, + wantError: false, + }, + { + name: "empty with status", + input: apiextensions.CustomResourceValidation{}, + statusEnabled: true, + wantError: false, + }, + { + name: "root type without status", + input: apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + Type: "object", + }, + }, + statusEnabled: false, + wantError: false, + }, + { + name: "root type with status", + input: apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + Type: "object", + }, + }, + statusEnabled: true, + wantError: true, + }, + { + name: "properties, required and description with status", + input: apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + Properties: map[string]apiextensions.JSONSchemaProps{ + "spec": {}, + "status": {}, + }, + Required: []string{"spec", "status"}, + Description: "This is a description", + }, + }, + statusEnabled: true, + wantError: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := ValidateCustomResourceDefinitionValidation(&tt.input, tt.statusEnabled, field.NewPath("spec", "validation")) + if !tt.wantError && len(got) > 0 { + t.Errorf("Expected no error, but got: %v", got) + } else if tt.wantError && len(got) == 0 { + t.Error("Expected error, but got none") + } + }) + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go index ea3af6976..145b3c5d7 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,22 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceColumnDefinition) DeepCopyInto(out *CustomResourceColumnDefinition) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceColumnDefinition. +func (in *CustomResourceColumnDefinition) DeepCopy() *CustomResourceColumnDefinition { + if in == nil { + return nil + } + out := new(CustomResourceColumnDefinition) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) { *out = *in @@ -150,6 +166,16 @@ func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefiniti (*in).DeepCopyInto(*out) } } + if in.Versions != nil { + in, out := &in.Versions, &out.Versions + *out = make([]CustomResourceDefinitionVersion, len(*in)) + copy(*out, *in) + } + if in.AdditionalPrinterColumns != nil { + in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns + *out = make([]CustomResourceColumnDefinition, len(*in)) + copy(*out, *in) + } return } @@ -174,6 +200,11 @@ func (in *CustomResourceDefinitionStatus) DeepCopyInto(out *CustomResourceDefini } } in.AcceptedNames.DeepCopyInto(&out.AcceptedNames) + if in.StoredVersions != nil { + in, out := &in.StoredVersions, &out.StoredVersions + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -187,6 +218,22 @@ func (in *CustomResourceDefinitionStatus) DeepCopy() *CustomResourceDefinitionSt return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceDefinitionVersion) DeepCopyInto(out *CustomResourceDefinitionVersion) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionVersion. +func (in *CustomResourceDefinitionVersion) DeepCopy() *CustomResourceDefinitionVersion { + if in == nil { + return nil + } + out := new(CustomResourceDefinitionVersion) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceSubresourceScale) DeepCopyInto(out *CustomResourceSubresourceScale) { *out = *in diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go index 1415ff8d9..f1fc89ba9 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go @@ -19,13 +19,8 @@ package apiserver import ( "fmt" "net/http" - "os" "time" - "github.com/golang/glog" - - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -42,21 +37,19 @@ import ( "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset" internalinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion" + "k8s.io/apiextensions-apiserver/pkg/controller/establish" "k8s.io/apiextensions-apiserver/pkg/controller/finalizer" "k8s.io/apiextensions-apiserver/pkg/controller/status" "k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition" - // make sure the generated client works _ "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" _ "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions" _ "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion" ) var ( - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - Registry = registered.NewOrDie("") - Scheme = runtime.NewScheme() - Codecs = serializer.NewCodecFactory(Scheme) + Scheme = runtime.NewScheme() + Codecs = serializer.NewCodecFactory(Scheme) // if you modify this, make sure you update the crEncoder unversionedVersion = schema.GroupVersion{Group: "", Version: "v1"} @@ -71,7 +64,7 @@ var ( ) func init() { - install.Install(groupFactoryRegistry, Registry, Scheme) + install.Install(Scheme) // we need to add the options to empty v1 metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Group: "", Version: "v1"}) @@ -81,6 +74,10 @@ func init() { type ExtraConfig struct { CRDRESTOptionsGetter genericregistry.RESTOptionsGetter + + // MasterCount is used to detect whether cluster is HA, and if it is + // the CRD Establishing will be hold by 5 seconds. + MasterCount int } type Config struct { @@ -133,9 +130,8 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) } apiResourceConfig := c.GenericConfig.MergedResourceConfig - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiextensions.GroupName, Registry, Scheme, metav1.ParameterCodec, Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiextensions.GroupName, Scheme, metav1.ParameterCodec, Codecs) if apiResourceConfig.VersionEnabled(v1beta1.SchemeGroupVersion) { - apiGroupInfo.GroupMeta.GroupVersion = v1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} // customresourcedefinitions customResourceDefintionStorage := customresourcedefinition.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter) @@ -153,16 +149,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) if err != nil { // it's really bad that this is leaking here, but until we can fix the test (which I'm pretty sure isn't even testing what it wants to test), // we need to be able to move forward - kubeAPIVersions := os.Getenv("KUBE_API_VERSIONS") - if len(kubeAPIVersions) == 0 { - return nil, fmt.Errorf("failed to create clientset: %v", err) - } - - // KUBE_API_VERSIONS is used in test-update-storage-objects.sh, disabling a number of API - // groups. This leads to a nil client above and undefined behaviour further down. - // - // TODO: get rid of KUBE_API_VERSIONS or define sane behaviour if set - glog.Errorf("Failed to create clientset with KUBE_API_VERSIONS=%q. KUBE_API_VERSIONS is only for testing. Things will break.", kubeAPIVersions) + return nil, fmt.Errorf("failed to create clientset: %v", err) } s.Informers = internalinformers.NewSharedInformerFactory(crdClient, 5*time.Minute) @@ -179,24 +166,21 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) discovery: map[string]*discovery.APIGroupHandler{}, delegate: delegateHandler, } + establishingController := establish.NewEstablishingController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), crdClient.Apiextensions()) crdHandler := NewCustomResourceDefinitionHandler( versionDiscoveryHandler, groupDiscoveryHandler, - s.GenericAPIServer.RequestContextMapper(), s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), delegateHandler, c.ExtraConfig.CRDRESTOptionsGetter, c.GenericConfig.AdmissionControl, + establishingController, + c.ExtraConfig.MasterCount, ) s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", crdHandler) s.GenericAPIServer.Handler.NonGoRestfulMux.HandlePrefix("/apis/", crdHandler) - // this only happens when KUBE_API_VERSIONS is set. We must return without adding controllers or poststarthooks which would affect healthz - if crdClient == nil { - return s, nil - } - - crdController := NewDiscoveryController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), versionDiscoveryHandler, groupDiscoveryHandler, c.GenericConfig.RequestContextMapper) + crdController := NewDiscoveryController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), versionDiscoveryHandler, groupDiscoveryHandler) namingController := status.NewNamingConditionController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), crdClient.Apiextensions()) finalizingController := finalizer.NewCRDFinalizer( s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), @@ -211,6 +195,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) s.GenericAPIServer.AddPostStartHook("start-apiextensions-controllers", func(context genericapiserver.PostStartHookContext) error { go crdController.Run(context.StopCh) go namingController.Run(context.StopCh) + go establishingController.Run(context.StopCh) go finalizingController.Run(5, context.StopCh) return nil }) diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/converter.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/converter.go new file mode 100644 index 000000000..69f5340a9 --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/converter.go @@ -0,0 +1,117 @@ +/* +Copyright 2018 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 conversion + +import ( + "fmt" + + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// NewCRDConverter returns a new CRD converter based on the conversion settings in crd object. +func NewCRDConverter(crd *apiextensions.CustomResourceDefinition) (safe, unsafe runtime.ObjectConvertor) { + validVersions := map[schema.GroupVersion]bool{} + for _, version := range crd.Spec.Versions { + validVersions[schema.GroupVersion{Group: crd.Spec.Group, Version: version.Name}] = true + } + + // The only converter right now is nopConverter. More converters will be returned based on the + // CRD object when they introduced. + unsafe = &crdConverter{ + clusterScoped: crd.Spec.Scope == apiextensions.ClusterScoped, + delegate: &nopConverter{ + validVersions: validVersions, + }, + } + return &safeConverterWrapper{unsafe}, unsafe +} + +var _ runtime.ObjectConvertor = &crdConverter{} + +// crdConverter extends the delegate with generic CRD conversion behaviour. The delegate will implement the +// user defined conversion strategy given in the CustomResourceDefinition. +type crdConverter struct { + delegate runtime.ObjectConvertor + clusterScoped bool +} + +func (c *crdConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + // We currently only support metadata.namespace and metadata.name. + switch { + case label == "metadata.name": + return label, value, nil + case !c.clusterScoped && label == "metadata.namespace": + return label, value, nil + default: + return "", "", fmt.Errorf("field label not supported: %s", label) + } +} + +func (c *crdConverter) Convert(in, out, context interface{}) error { + return c.delegate.Convert(in, out, context) +} + +// ConvertToVersion converts in object to the given gvk in place and returns the same `in` object. +func (c *crdConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { + // Run the converter on the list items instead of list itself + if list, ok := in.(*unstructured.UnstructuredList); ok { + for i := range list.Items { + obj, err := c.delegate.ConvertToVersion(&list.Items[i], target) + if err != nil { + return nil, err + } + + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return nil, fmt.Errorf("output type %T in not valid for unstructured conversion", obj) + } + list.Items[i] = *u + } + return list, nil + } + + return c.delegate.ConvertToVersion(in, target) +} + +// safeConverterWrapper is a wrapper over an unsafe object converter that makes copy of the input and then delegate to the unsafe converter. +type safeConverterWrapper struct { + unsafe runtime.ObjectConvertor +} + +var _ runtime.ObjectConvertor = &nopConverter{} + +// ConvertFieldLabel delegate the call to the unsafe converter. +func (c *safeConverterWrapper) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + return c.unsafe.ConvertFieldLabel(version, kind, label, value) +} + +// Convert makes a copy of in object and then delegate the call to the unsafe converter. +func (c *safeConverterWrapper) Convert(in, out, context interface{}) error { + inObject, ok := in.(runtime.Object) + if !ok { + return fmt.Errorf("input type %T in not valid for object conversion", in) + } + return c.unsafe.Convert(inObject.DeepCopyObject(), out, context) +} + +// ConvertToVersion makes a copy of in object and then delegate the call to the unsafe converter. +func (c *safeConverterWrapper) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { + return c.unsafe.ConvertToVersion(in.DeepCopyObject(), target) +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/nop_converter.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/nop_converter.go new file mode 100644 index 000000000..716930bfb --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/nop_converter.go @@ -0,0 +1,79 @@ +/* +Copyright 2018 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 conversion + +import ( + "errors" + "fmt" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// nopConverter is a converter that only sets the apiVersion fields, but does not real conversion. +type nopConverter struct { + validVersions map[schema.GroupVersion]bool +} + +var _ runtime.ObjectConvertor = &nopConverter{} + +func (nopConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + return "", "", errors.New("unstructured cannot convert field labels") +} + +func (c *nopConverter) Convert(in, out, context interface{}) error { + unstructIn, ok := in.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("input type %T in not valid for unstructured conversion", in) + } + + unstructOut, ok := out.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("output type %T in not valid for unstructured conversion", out) + } + + outGVK := unstructOut.GroupVersionKind() + if !c.validVersions[outGVK.GroupVersion()] { + return fmt.Errorf("request to convert CRD from an invalid group/version: %s", outGVK.String()) + } + inGVK := unstructIn.GroupVersionKind() + if !c.validVersions[inGVK.GroupVersion()] { + return fmt.Errorf("request to convert CRD to an invalid group/version: %s", inGVK.String()) + } + + unstructOut.SetUnstructuredContent(unstructIn.UnstructuredContent()) + _, err := c.ConvertToVersion(unstructOut, outGVK.GroupVersion()) + if err != nil { + return err + } + return nil +} + +func (c *nopConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { + kind := in.GetObjectKind().GroupVersionKind() + gvk, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{kind}) + if !ok { + // TODO: should this be a typed error? + return nil, fmt.Errorf("%v is unstructured and is not suitable for converting to %q", kind, target) + } + if !c.validVersions[gvk.GroupVersion()] { + return nil, fmt.Errorf("request to convert CRD to an invalid group/version: %s", gvk.String()) + } + in.GetObjectKind().SetGroupVersionKind(gvk) + return in, nil +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go index b180e105b..e3b3d0a44 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go @@ -18,6 +18,7 @@ package apiserver import ( "fmt" + "sort" "time" "github.com/golang/glog" @@ -28,8 +29,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/version" "k8s.io/apiserver/pkg/endpoints/discovery" - "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" @@ -41,7 +42,6 @@ import ( type DiscoveryController struct { versionHandler *versionDiscoveryHandler groupHandler *groupDiscoveryHandler - contextMapper request.RequestContextMapper crdLister listers.CustomResourceDefinitionLister crdsSynced cache.InformerSynced @@ -52,13 +52,12 @@ type DiscoveryController struct { queue workqueue.RateLimitingInterface } -func NewDiscoveryController(crdInformer informers.CustomResourceDefinitionInformer, versionHandler *versionDiscoveryHandler, groupHandler *groupDiscoveryHandler, contextMapper request.RequestContextMapper) *DiscoveryController { +func NewDiscoveryController(crdInformer informers.CustomResourceDefinitionInformer, versionHandler *versionDiscoveryHandler, groupHandler *groupDiscoveryHandler) *DiscoveryController { c := &DiscoveryController{ versionHandler: versionHandler, groupHandler: groupHandler, crdLister: crdInformer.Lister(), crdsSynced: crdInformer.Informer().HasSynced, - contextMapper: contextMapper, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "DiscoveryController"), } @@ -78,6 +77,7 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error { apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{} apiResourcesForDiscovery := []metav1.APIResource{} + versionsForDiscoveryMap := map[metav1.GroupVersion]bool{} crds, err := c.crdLister.List(labels.Everything()) if err != nil { @@ -93,13 +93,29 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error { if crd.Spec.Group != version.Group { continue } - foundGroup = true - apiVersionsForDiscovery = append(apiVersionsForDiscovery, metav1.GroupVersionForDiscovery{ - GroupVersion: crd.Spec.Group + "/" + crd.Spec.Version, - Version: crd.Spec.Version, - }) - if crd.Spec.Version != version.Version { + foundThisVersion := false + for _, v := range crd.Spec.Versions { + if !v.Served { + continue + } + // If there is any Served version, that means the group should show up in discovery + foundGroup = true + + gv := metav1.GroupVersion{Group: crd.Spec.Group, Version: v.Name} + if !versionsForDiscoveryMap[gv] { + versionsForDiscoveryMap[gv] = true + apiVersionsForDiscovery = append(apiVersionsForDiscovery, metav1.GroupVersionForDiscovery{ + GroupVersion: crd.Spec.Group + "/" + v.Name, + Version: v.Name, + }) + } + if v.Name == version.Version { + foundThisVersion = true + } + } + + if !foundThisVersion { continue } foundVersion = true @@ -147,13 +163,16 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error { return nil } + sortGroupDiscoveryByKubeAwareVersion(apiVersionsForDiscovery) + apiGroup := metav1.APIGroup{ Name: version.Group, Versions: apiVersionsForDiscovery, - // the preferred versions for a group is arbitrary since there cannot be duplicate resources + // the preferred versions for a group is the first item in + // apiVersionsForDiscovery after it put in the right ordered PreferredVersion: apiVersionsForDiscovery[0], } - c.groupHandler.setDiscovery(version.Group, discovery.NewAPIGroupHandler(Codecs, apiGroup, c.contextMapper)) + c.groupHandler.setDiscovery(version.Group, discovery.NewAPIGroupHandler(Codecs, apiGroup)) if !foundVersion { c.versionHandler.unsetDiscovery(version) @@ -161,11 +180,17 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error { } c.versionHandler.setDiscovery(version, discovery.NewAPIVersionHandler(Codecs, version, discovery.APIResourceListerFunc(func() []metav1.APIResource { return apiResourcesForDiscovery - }), c.contextMapper)) + }))) return nil } +func sortGroupDiscoveryByKubeAwareVersion(gd []metav1.GroupVersionForDiscovery) { + sort.Slice(gd, func(i, j int) bool { + return version.CompareKubeAwareVersionStrings(gd[i].Version, gd[j].Version) > 0 + }) +} + func (c *DiscoveryController) Run(stopCh <-chan struct{}) { defer utilruntime.HandleCrash() defer c.queue.ShutDown() @@ -210,7 +235,9 @@ func (c *DiscoveryController) processNextWorkItem() bool { } func (c *DiscoveryController) enqueue(obj *apiextensions.CustomResourceDefinition) { - c.queue.Add(schema.GroupVersion{Group: obj.Spec.Group, Version: obj.Spec.Version}) + for _, v := range obj.Spec.Versions { + c.queue.Add(schema.GroupVersion{Group: obj.Spec.Group, Version: v.Name}) + } } func (c *DiscoveryController) addCustomResourceDefinition(obj interface{}) { @@ -219,10 +246,14 @@ func (c *DiscoveryController) addCustomResourceDefinition(obj interface{}) { c.enqueue(castObj) } -func (c *DiscoveryController) updateCustomResourceDefinition(obj, _ interface{}) { - castObj := obj.(*apiextensions.CustomResourceDefinition) - glog.V(4).Infof("Updating customresourcedefinition %s", castObj.Name) - c.enqueue(castObj) +func (c *DiscoveryController) updateCustomResourceDefinition(oldObj, newObj interface{}) { + castNewObj := newObj.(*apiextensions.CustomResourceDefinition) + castOldObj := oldObj.(*apiextensions.CustomResourceDefinition) + glog.V(4).Infof("Updating customresourcedefinition %s", castOldObj.Name) + // Enqueue both old and new object to make sure we remove and add appropriate Versions. + // The working queue will resolve any duplicates and only changes will stay in the queue. + c.enqueue(castNewObj) + c.enqueue(castOldObj) } func (c *DiscoveryController) deleteCustomResourceDefinition(obj interface{}) { diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go index e427f4c11..7be3711dc 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go @@ -58,9 +58,11 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + "k8s.io/apiextensions-apiserver/pkg/apiserver/conversion" apiservervalidation "k8s.io/apiextensions-apiserver/pkg/apiserver/validation" informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion" listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion" + "k8s.io/apiextensions-apiserver/pkg/controller/establish" "k8s.io/apiextensions-apiserver/pkg/controller/finalizer" apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" "k8s.io/apiextensions-apiserver/pkg/registry/customresource" @@ -80,13 +82,17 @@ type crdHandler struct { // which is suited for most read and rarely write cases customStorage atomic.Value - requestContextMapper apirequest.RequestContextMapper - crdLister listers.CustomResourceDefinitionLister delegate http.Handler restOptionsGetter generic.RESTOptionsGetter admission admission.Interface + + establishingController *establish.EstablishingController + + // MasterCount is used to implement sleep to improve + // CRD establishing process for HA clusters. + masterCount int } // crdInfo stores enough information to serve the storage for the custom resource @@ -96,11 +102,20 @@ type crdInfo struct { spec *apiextensions.CustomResourceDefinitionSpec acceptedNames *apiextensions.CustomResourceDefinitionNames - storage customresource.CustomResourceStorage + // Storage per version + storages map[string]customresource.CustomResourceStorage + + // Request scope per version + requestScopes map[string]handlers.RequestScope + + // Scale scope per version + scaleRequestScopes map[string]handlers.RequestScope - requestScope handlers.RequestScope - scaleRequestScope handlers.RequestScope - statusRequestScope handlers.RequestScope + // Status scope per version + statusRequestScopes map[string]handlers.RequestScope + + // storageVersion is the CRD version used when storing the object in etcd. + storageVersion string } // crdStorageMap goes from customresourcedefinition to its storage @@ -109,22 +124,23 @@ type crdStorageMap map[types.UID]*crdInfo func NewCustomResourceDefinitionHandler( versionDiscoveryHandler *versionDiscoveryHandler, groupDiscoveryHandler *groupDiscoveryHandler, - requestContextMapper apirequest.RequestContextMapper, crdInformer informers.CustomResourceDefinitionInformer, delegate http.Handler, restOptionsGetter generic.RESTOptionsGetter, - admission admission.Interface) *crdHandler { + admission admission.Interface, + establishingController *establish.EstablishingController, + masterCount int) *crdHandler { ret := &crdHandler{ versionDiscoveryHandler: versionDiscoveryHandler, groupDiscoveryHandler: groupDiscoveryHandler, customStorage: atomic.Value{}, - requestContextMapper: requestContextMapper, crdLister: crdInformer.Lister(), delegate: delegate, restOptionsGetter: restOptionsGetter, admission: admission, + establishingController: establishingController, + masterCount: masterCount, } - crdInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: ret.updateCustomResourceDefinition, DeleteFunc: func(obj interface{}) { @@ -138,11 +154,7 @@ func NewCustomResourceDefinitionHandler( } func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - ctx, ok := r.requestContextMapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, fmt.Errorf("no context found for request")) - return - } + ctx := req.Context() requestInfo, ok := apirequest.RequestInfoFrom(ctx) if !ok { responsewriters.InternalError(w, req, fmt.Errorf("no RequestInfo found in the context")) @@ -176,11 +188,16 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - if crd.Spec.Version != requestInfo.APIVersion { + if !apiextensions.HasServedCRDVersion(crd, requestInfo.APIVersion) { r.delegate.ServeHTTP(w, req) return } - if !apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) { + // There is a small chance that a CRD is being served because NamesAccepted condition is true, + // but it becomes "unserved" because another names update leads to a conflict + // and EstablishingController wasn't fast enough to put the CRD into the Established condition. + // We accept this as the problem is small and self-healing. + if !apiextensions.IsCRDConditionTrue(crd, apiextensions.NamesAccepted) && + !apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) { r.delegate.ServeHTTP(w, req) return } @@ -222,8 +239,8 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { } func (r *crdHandler) serveResource(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc { - requestScope := crdInfo.requestScope - storage := crdInfo.storage.CustomResource + requestScope := crdInfo.requestScopes[requestInfo.APIVersion] + storage := crdInfo.storages[requestInfo.APIVersion].CustomResource minRequestTimeout := 1 * time.Minute switch requestInfo.Verb { @@ -240,11 +257,11 @@ func (r *crdHandler) serveResource(w http.ResponseWriter, req *http.Request, req http.Error(w, fmt.Sprintf("%v not allowed while CustomResourceDefinition is terminating", requestInfo.Verb), http.StatusMethodNotAllowed) return nil } - return handlers.CreateResource(storage, requestScope, discovery.NewUnstructuredObjectTyper(nil), r.admission) + return handlers.CreateResource(storage, requestScope, r.admission) case "update": - return handlers.UpdateResource(storage, requestScope, discovery.NewUnstructuredObjectTyper(nil), r.admission) + return handlers.UpdateResource(storage, requestScope, r.admission) case "patch": - return handlers.PatchResource(storage, requestScope, r.admission, unstructured.UnstructuredObjectConverter{}, supportedTypes) + return handlers.PatchResource(storage, requestScope, r.admission, supportedTypes) case "delete": allowsOptions := true return handlers.DeleteResource(storage, allowsOptions, requestScope, r.admission) @@ -258,16 +275,16 @@ func (r *crdHandler) serveResource(w http.ResponseWriter, req *http.Request, req } func (r *crdHandler) serveStatus(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc { - requestScope := crdInfo.statusRequestScope - storage := crdInfo.storage.Status + requestScope := crdInfo.statusRequestScopes[requestInfo.APIVersion] + storage := crdInfo.storages[requestInfo.APIVersion].Status switch requestInfo.Verb { case "get": return handlers.GetResource(storage, nil, requestScope) case "update": - return handlers.UpdateResource(storage, requestScope, discovery.NewUnstructuredObjectTyper(nil), r.admission) + return handlers.UpdateResource(storage, requestScope, r.admission) case "patch": - return handlers.PatchResource(storage, requestScope, r.admission, unstructured.UnstructuredObjectConverter{}, supportedTypes) + return handlers.PatchResource(storage, requestScope, r.admission, supportedTypes) default: http.Error(w, fmt.Sprintf("unhandled verb %q", requestInfo.Verb), http.StatusMethodNotAllowed) return nil @@ -275,16 +292,16 @@ func (r *crdHandler) serveStatus(w http.ResponseWriter, req *http.Request, reque } func (r *crdHandler) serveScale(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc { - requestScope := crdInfo.scaleRequestScope - storage := crdInfo.storage.Scale + requestScope := crdInfo.scaleRequestScopes[requestInfo.APIVersion] + storage := crdInfo.storages[requestInfo.APIVersion].Scale switch requestInfo.Verb { case "get": return handlers.GetResource(storage, nil, requestScope) case "update": - return handlers.UpdateResource(storage, requestScope, discovery.NewUnstructuredObjectTyper(nil), r.admission) + return handlers.UpdateResource(storage, requestScope, r.admission) case "patch": - return handlers.PatchResource(storage, requestScope, r.admission, unstructured.UnstructuredObjectConverter{}, supportedTypes) + return handlers.PatchResource(storage, requestScope, r.admission, supportedTypes) default: http.Error(w, fmt.Sprintf("unhandled verb %q", requestInfo.Verb), http.StatusMethodNotAllowed) return nil @@ -298,6 +315,19 @@ func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{}) r.customStorageLock.Lock() defer r.customStorageLock.Unlock() + // Add CRD to the establishing controller queue. + // For HA clusters, we want to prevent race conditions when changing status to Established, + // so we want to be sure that CRD is Installing at least for 5 seconds before Establishing it. + // TODO: find a real HA safe checkpointing mechanism instead of an arbitrary wait. + if !apiextensions.IsCRDConditionTrue(newCRD, apiextensions.Established) && + apiextensions.IsCRDConditionTrue(newCRD, apiextensions.NamesAccepted) { + if r.masterCount > 1 { + r.establishingController.QueueCRD(newCRD.Name, 5*time.Second) + } else { + r.establishingController.QueueCRD(newCRD.Name, 0) + } + } + storageMap := r.customStorage.Load().(crdStorageMap) oldInfo, found := storageMap[newCRD.UID] if !found { @@ -314,8 +344,10 @@ func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{}) // as it is used without locking elsewhere. storageMap2 := storageMap.clone() if oldInfo, ok := storageMap2[types.UID(oldCRD.UID)]; ok { - // destroy only the main storage. Those for the subresources share cacher and etcd clients. - oldInfo.storage.CustomResource.DestroyFunc() + for _, storage := range oldInfo.storages { + // destroy only the main storage. Those for the subresources share cacher and etcd clients. + storage.CustomResource.DestroyFunc() + } delete(storageMap2, types.UID(oldCRD.UID)) } @@ -346,9 +378,11 @@ func (r *crdHandler) removeDeadStorage() { } } if !found { - glog.V(4).Infof("Removing dead CRD storage for %v", s.requestScope.Resource) - // destroy only the main storage. Those for the subresources share cacher and etcd clients. - s.storage.CustomResource.DestroyFunc() + glog.V(4).Infof("Removing dead CRD storage for %s/%s", s.spec.Group, s.spec.Names.Kind) + for _, storage := range s.storages { + // destroy only the main storage. Those for the subresources share cacher and etcd clients. + storage.CustomResource.DestroyFunc() + } delete(storageMap2, uid) } } @@ -362,9 +396,11 @@ func (r *crdHandler) GetCustomResourceListerCollectionDeleter(crd *apiextensions if err != nil { return nil, err } - return info.storage.CustomResource, nil + return info.storages[info.storageVersion].CustomResource, nil } +var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() + func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResourceDefinition) (*crdInfo, error) { storageMap := r.customStorage.Load().(crdStorageMap) if ret, ok := storageMap[crd.UID]; ok { @@ -379,153 +415,157 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource return ret, nil } - // In addition to Unstructured objects (Custom Resources), we also may sometimes need to - // decode unversioned Options objects, so we delegate to parameterScheme for such types. - parameterScheme := runtime.NewScheme() - parameterScheme.AddUnversionedTypes(schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version}, - &metav1.ListOptions{}, - &metav1.ExportOptions{}, - &metav1.GetOptions{}, - &metav1.DeleteOptions{}, - ) - parameterCodec := runtime.NewParameterCodec(parameterScheme) - - kind := schema.GroupVersionKind{Group: crd.Spec.Group, Version: crd.Spec.Version, Kind: crd.Status.AcceptedNames.Kind} - typer := UnstructuredObjectTyper{ - Delegate: parameterScheme, - UnstructuredTyper: discovery.NewUnstructuredObjectTyper(nil), - } - creator := unstructuredCreator{} - - validator, _, err := apiservervalidation.NewSchemaValidator(crd.Spec.Validation) + storageVersion, err := apiextensions.GetCRDStorageVersion(crd) if err != nil { return nil, err } - var statusSpec *apiextensions.CustomResourceSubresourceStatus - var statusValidator *validate.SchemaValidator - if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Status != nil { - statusSpec = crd.Spec.Subresources.Status + // Scope/Storages per version. + requestScopes := map[string]handlers.RequestScope{} + storages := map[string]customresource.CustomResourceStorage{} + statusScopes := map[string]handlers.RequestScope{} + scaleScopes := map[string]handlers.RequestScope{} + + for _, v := range crd.Spec.Versions { + safeConverter, unsafeConverter := conversion.NewCRDConverter(crd) + // In addition to Unstructured objects (Custom Resources), we also may sometimes need to + // decode unversioned Options objects, so we delegate to parameterScheme for such types. + parameterScheme := runtime.NewScheme() + parameterScheme.AddUnversionedTypes(schema.GroupVersion{Group: crd.Spec.Group, Version: v.Name}, + &metav1.ListOptions{}, + &metav1.ExportOptions{}, + &metav1.GetOptions{}, + &metav1.DeleteOptions{}, + ) + parameterCodec := runtime.NewParameterCodec(parameterScheme) + + kind := schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.Kind} + typer := newUnstructuredObjectTyper(parameterScheme) + creator := unstructuredCreator{} + + validator, _, err := apiservervalidation.NewSchemaValidator(crd.Spec.Validation) + if err != nil { + return nil, err + } - // for the status subresource, validate only against the status schema - if crd.Spec.Validation != nil && crd.Spec.Validation.OpenAPIV3Schema != nil && crd.Spec.Validation.OpenAPIV3Schema.Properties != nil { - if statusSchema, ok := crd.Spec.Validation.OpenAPIV3Schema.Properties["status"]; ok { - openapiSchema := &spec.Schema{} - if err := apiservervalidation.ConvertJSONSchemaProps(&statusSchema, openapiSchema); err != nil { - return nil, err + var statusSpec *apiextensions.CustomResourceSubresourceStatus + var statusValidator *validate.SchemaValidator + if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Status != nil { + statusSpec = crd.Spec.Subresources.Status + + // for the status subresource, validate only against the status schema + if crd.Spec.Validation != nil && crd.Spec.Validation.OpenAPIV3Schema != nil && crd.Spec.Validation.OpenAPIV3Schema.Properties != nil { + if statusSchema, ok := crd.Spec.Validation.OpenAPIV3Schema.Properties["status"]; ok { + openapiSchema := &spec.Schema{} + if err := apiservervalidation.ConvertJSONSchemaProps(&statusSchema, openapiSchema); err != nil { + return nil, err + } + statusValidator = validate.NewSchemaValidator(openapiSchema, nil, "", strfmt.Default) } - statusValidator = validate.NewSchemaValidator(openapiSchema, nil, "", strfmt.Default) } } - } - var scaleSpec *apiextensions.CustomResourceSubresourceScale - if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil { - scaleSpec = crd.Spec.Subresources.Scale - } + var scaleSpec *apiextensions.CustomResourceSubresourceScale + if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil { + scaleSpec = crd.Spec.Subresources.Scale + } - // TODO: identify how to pass printer specification from the CRD - table, err := tableconvertor.New(nil) - if err != nil { - glog.V(2).Infof("The CRD for %v has an invalid printer specification, falling back to default printing: %v", kind, err) - } - - customResourceStorage := customresource.NewStorage( - schema.GroupResource{Group: crd.Spec.Group, Resource: crd.Status.AcceptedNames.Plural}, - schema.GroupVersionKind{Group: crd.Spec.Group, Version: crd.Spec.Version, Kind: crd.Status.AcceptedNames.ListKind}, - customresource.NewStrategy( - typer, - crd.Spec.Scope == apiextensions.NamespaceScoped, - kind, - validator, - statusValidator, - statusSpec, - scaleSpec, - ), - r.restOptionsGetter, - crd.Status.AcceptedNames.Categories, - table, - ) - - selfLinkPrefix := "" - switch crd.Spec.Scope { - case apiextensions.ClusterScoped: - selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, crd.Spec.Version) + "/" + crd.Status.AcceptedNames.Plural + "/" - case apiextensions.NamespaceScoped: - selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, crd.Spec.Version, "namespaces") + "/" - } - - clusterScoped := crd.Spec.Scope == apiextensions.ClusterScoped - - var ctxFn handlers.ContextFunc - ctxFn = func(req *http.Request) apirequest.Context { - ret, _ := r.requestContextMapper.Get(req) - return ret - } - - requestScope := handlers.RequestScope{ - Namer: handlers.ContextBasedNaming{ - GetContext: ctxFn, - SelfLinker: meta.NewAccessor(), - ClusterScoped: clusterScoped, - SelfLinkPathPrefix: selfLinkPrefix, - }, - ContextFunc: func(req *http.Request) apirequest.Context { - ret, _ := r.requestContextMapper.Get(req) - return ret - }, + table, err := tableconvertor.New(crd.Spec.AdditionalPrinterColumns) + if err != nil { + glog.V(2).Infof("The CRD for %v has an invalid printer specification, falling back to default printing: %v", kind, err) + } - Serializer: unstructuredNegotiatedSerializer{typer: typer, creator: creator}, - ParameterCodec: parameterCodec, + storages[v.Name] = customresource.NewStorage( + schema.GroupResource{Group: crd.Spec.Group, Resource: crd.Status.AcceptedNames.Plural}, + schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.ListKind}, + customresource.NewStrategy( + typer, + crd.Spec.Scope == apiextensions.NamespaceScoped, + kind, + validator, + statusValidator, + statusSpec, + scaleSpec, + ), + crdConversionRESTOptionsGetter{ + RESTOptionsGetter: r.restOptionsGetter, + converter: safeConverter, + decoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: v.Name}, + encoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: storageVersion}, + }, + crd.Status.AcceptedNames.Categories, + table, + ) + + selfLinkPrefix := "" + switch crd.Spec.Scope { + case apiextensions.ClusterScoped: + selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, v.Name) + "/" + crd.Status.AcceptedNames.Plural + "/" + case apiextensions.NamespaceScoped: + selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, v.Name, "namespaces") + "/" + } - Creater: creator, - Convertor: crdObjectConverter{ - UnstructuredObjectConverter: unstructured.UnstructuredObjectConverter{}, - clusterScoped: clusterScoped, - }, - Defaulter: unstructuredDefaulter{parameterScheme}, - Typer: typer, - UnsafeConvertor: unstructured.UnstructuredObjectConverter{}, + clusterScoped := crd.Spec.Scope == apiextensions.ClusterScoped + + requestScopes[v.Name] = handlers.RequestScope{ + Namer: handlers.ContextBasedNaming{ + SelfLinker: meta.NewAccessor(), + ClusterScoped: clusterScoped, + SelfLinkPathPrefix: selfLinkPrefix, + }, + Serializer: unstructuredNegotiatedSerializer{typer: typer, creator: creator, converter: safeConverter}, + ParameterCodec: parameterCodec, - Resource: schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Status.AcceptedNames.Plural}, - Kind: kind, + Creater: creator, + Convertor: safeConverter, + Defaulter: unstructuredDefaulter{parameterScheme}, + Typer: typer, + UnsafeConvertor: unsafeConverter, - MetaGroupVersion: metav1.SchemeGroupVersion, + Resource: schema.GroupVersionResource{Group: crd.Spec.Group, Version: v.Name, Resource: crd.Status.AcceptedNames.Plural}, + Kind: kind, - TableConvertor: customResourceStorage.CustomResource, + MetaGroupVersion: metav1.SchemeGroupVersion, + + TableConvertor: storages[v.Name].CustomResource, + } + + // override scaleSpec subresource values + // shallow copy + scaleScope := requestScopes[v.Name] + scaleConverter := scale.NewScaleConverter() + scaleScope.Subresource = "scale" + scaleScope.Serializer = serializer.NewCodecFactory(scaleConverter.Scheme()) + scaleScope.Kind = autoscalingv1.SchemeGroupVersion.WithKind("Scale") + scaleScope.Namer = handlers.ContextBasedNaming{ + SelfLinker: meta.NewAccessor(), + ClusterScoped: clusterScoped, + SelfLinkPathPrefix: selfLinkPrefix, + SelfLinkPathSuffix: "/scale", + } + scaleScopes[v.Name] = scaleScope + + // override status subresource values + // shallow copy + statusScope := requestScopes[v.Name] + statusScope.Subresource = "status" + statusScope.Namer = handlers.ContextBasedNaming{ + SelfLinker: meta.NewAccessor(), + ClusterScoped: clusterScoped, + SelfLinkPathPrefix: selfLinkPrefix, + SelfLinkPathSuffix: "/status", + } + statusScopes[v.Name] = statusScope } ret := &crdInfo{ - spec: &crd.Spec, - acceptedNames: &crd.Status.AcceptedNames, - - storage: customResourceStorage, - requestScope: requestScope, - scaleRequestScope: requestScope, // shallow copy - statusRequestScope: requestScope, // shallow copy - } - - // override scaleSpec subresource values - scaleConverter := scale.NewScaleConverter() - ret.scaleRequestScope.Subresource = "scale" - ret.scaleRequestScope.Serializer = serializer.NewCodecFactory(scaleConverter.Scheme()) - ret.scaleRequestScope.Kind = autoscalingv1.SchemeGroupVersion.WithKind("Scale") - ret.scaleRequestScope.Namer = handlers.ContextBasedNaming{ - GetContext: ctxFn, - SelfLinker: meta.NewAccessor(), - ClusterScoped: clusterScoped, - SelfLinkPathPrefix: selfLinkPrefix, - SelfLinkPathSuffix: "/scale", - } - - // override status subresource values - ret.statusRequestScope.Subresource = "status" - ret.statusRequestScope.Namer = handlers.ContextBasedNaming{ - GetContext: ctxFn, - SelfLinker: meta.NewAccessor(), - ClusterScoped: clusterScoped, - SelfLinkPathPrefix: selfLinkPrefix, - SelfLinkPathSuffix: "/status", + spec: &crd.Spec, + acceptedNames: &crd.Status.AcceptedNames, + storages: storages, + requestScopes: requestScopes, + scaleRequestScopes: scaleScopes, + statusRequestScopes: statusScopes, + storageVersion: storageVersion, } // Copy because we cannot write to storageMap without a race @@ -538,27 +578,10 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource return ret, nil } -// crdObjectConverter is a converter that supports field selectors for CRDs. -type crdObjectConverter struct { - unstructured.UnstructuredObjectConverter - clusterScoped bool -} - -func (c crdObjectConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { - // We currently only support metadata.namespace and metadata.name. - switch { - case label == "metadata.name": - return label, value, nil - case !c.clusterScoped && label == "metadata.namespace": - return label, value, nil - default: - return "", "", fmt.Errorf("field label not supported: %s", label) - } -} - type unstructuredNegotiatedSerializer struct { - typer runtime.ObjectTyper - creator runtime.ObjectCreater + typer runtime.ObjectTyper + creator runtime.ObjectCreater + converter runtime.ObjectConvertor } func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { @@ -583,11 +606,12 @@ func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.Serial } func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { - return versioning.NewDefaultingCodecForScheme(Scheme, encoder, nil, gv, nil) + return versioning.NewCodec(encoder, nil, s.converter, Scheme, Scheme, Scheme, gv, nil) } func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { - return versioning.NewDefaultingCodecForScheme(Scheme, nil, decoder, nil, gv) + d := schemaCoercingDecoder{delegate: decoder, validator: unstructuredSchemaCoercer{}} + return versioning.NewDefaultingCodecForScheme(Scheme, nil, d, nil, gv) } type UnstructuredObjectTyper struct { @@ -595,6 +619,13 @@ type UnstructuredObjectTyper struct { UnstructuredTyper runtime.ObjectTyper } +func newUnstructuredObjectTyper(Delegate runtime.ObjectTyper) UnstructuredObjectTyper { + return UnstructuredObjectTyper{ + Delegate: Delegate, + UnstructuredTyper: discovery.NewUnstructuredObjectTyper(), + } +} + func (t UnstructuredObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { // Delegate for things other than Unstructured. if _, ok := obj.(runtime.Unstructured); !ok { @@ -661,3 +692,192 @@ func (in crdStorageMap) clone() crdStorageMap { } return out } + +// crdConversionRESTOptionsGetter overrides the codec with one using the +// provided custom converter and custom encoder and decoder version. +type crdConversionRESTOptionsGetter struct { + generic.RESTOptionsGetter + converter runtime.ObjectConvertor + encoderVersion schema.GroupVersion + decoderVersion schema.GroupVersion +} + +func (t crdConversionRESTOptionsGetter) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) { + ret, err := t.RESTOptionsGetter.GetRESTOptions(resource) + if err == nil { + d := schemaCoercingDecoder{delegate: ret.StorageConfig.Codec, validator: unstructuredSchemaCoercer{ + // drop invalid fields while decoding old CRs (before we had any ObjectMeta validation) + dropInvalidMetadata: true, + }} + c := schemaCoercingConverter{delegate: t.converter, validator: unstructuredSchemaCoercer{}} + ret.StorageConfig.Codec = versioning.NewCodec(ret.StorageConfig.Codec, d, c, &unstructuredCreator{}, discovery.NewUnstructuredObjectTyper(), &unstructuredDefaulter{delegate: Scheme}, t.encoderVersion, t.decoderVersion) + } + return ret, err +} + +// schemaCoercingDecoder calls the delegate decoder, and then applies the Unstructured schema validator +// to coerce the schema. +type schemaCoercingDecoder struct { + delegate runtime.Decoder + validator unstructuredSchemaCoercer +} + +var _ runtime.Decoder = schemaCoercingDecoder{} + +func (d schemaCoercingDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { + obj, gvk, err := d.delegate.Decode(data, defaults, into) + if err != nil { + return nil, gvk, err + } + if u, ok := obj.(*unstructured.Unstructured); ok { + if err := d.validator.apply(u); err != nil { + return nil, gvk, err + } + } + + return obj, gvk, nil +} + +// schemaCoercingConverter calls the delegate converter and applies the Unstructured validator to +// coerce the schema. +type schemaCoercingConverter struct { + delegate runtime.ObjectConvertor + validator unstructuredSchemaCoercer +} + +var _ runtime.ObjectConvertor = schemaCoercingConverter{} + +func (v schemaCoercingConverter) Convert(in, out, context interface{}) error { + if err := v.delegate.Convert(in, out, context); err != nil { + return err + } + + if u, ok := out.(*unstructured.Unstructured); ok { + if err := v.validator.apply(u); err != nil { + return err + } + } + + return nil +} + +func (v schemaCoercingConverter) ConvertToVersion(in runtime.Object, gv runtime.GroupVersioner) (runtime.Object, error) { + out, err := v.delegate.ConvertToVersion(in, gv) + if err != nil { + return nil, err + } + + if u, ok := out.(*unstructured.Unstructured); ok { + if err := v.validator.apply(u); err != nil { + return nil, err + } + } + + return out, nil +} + +func (v schemaCoercingConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + return v.ConvertFieldLabel(version, kind, label, value) +} + +// unstructuredSchemaCoercer does the validation for Unstructured that json.Unmarshal +// does for native types. This includes: +// - validating and pruning ObjectMeta (here with optional error instead of pruning) +// - TODO: application of an OpenAPI validator (against the whole object or a top-level field of it). +// - TODO: optionally application of post-validation algorithms like defaulting and/or OpenAPI based pruning. +type unstructuredSchemaCoercer struct { + dropInvalidMetadata bool +} + +func (v *unstructuredSchemaCoercer) apply(u *unstructured.Unstructured) error { + // save implicit meta fields that don't have to be specified in the validation spec + kind, foundKind, err := unstructured.NestedString(u.UnstructuredContent(), "kind") + if err != nil { + return err + } + apiVersion, foundApiVersion, err := unstructured.NestedString(u.UnstructuredContent(), "apiVersion") + if err != nil { + return err + } + objectMeta, foundObjectMeta, err := getObjectMeta(u, v.dropInvalidMetadata) + if err != nil { + return err + } + + // restore meta fields, starting clean + if foundKind { + u.SetKind(kind) + } + if foundApiVersion { + u.SetAPIVersion(apiVersion) + } + if foundObjectMeta { + if err := setObjectMeta(u, objectMeta); err != nil { + return err + } + } + + return nil +} + +var encodingjson = json.CaseSensitiveJsonIterator() + +func getObjectMeta(u *unstructured.Unstructured, dropMalformedFields bool) (*metav1.ObjectMeta, bool, error) { + metadata, found := u.UnstructuredContent()["metadata"] + if !found { + return nil, false, nil + } + + // round-trip through JSON first, hoping that unmarshaling just works + objectMeta := &metav1.ObjectMeta{} + metadataBytes, err := encodingjson.Marshal(metadata) + if err != nil { + return nil, false, err + } + if err = encodingjson.Unmarshal(metadataBytes, objectMeta); err == nil { + // if successful, return + return objectMeta, true, nil + } + if !dropMalformedFields { + // if we're not trying to drop malformed fields, return the error + return nil, true, err + } + + metadataMap, ok := metadata.(map[string]interface{}) + if !ok { + return nil, false, fmt.Errorf("invalid metadata: expected object, got %T", metadata) + } + + // Go field by field accumulating into the metadata object. + // This takes advantage of the fact that you can repeatedly unmarshal individual fields into a single struct, + // each iteration preserving the old key-values. + accumulatedObjectMeta := &metav1.ObjectMeta{} + testObjectMeta := &metav1.ObjectMeta{} + for k, v := range metadataMap { + // serialize a single field + if singleFieldBytes, err := encodingjson.Marshal(map[string]interface{}{k: v}); err == nil { + // do a test unmarshal + if encodingjson.Unmarshal(singleFieldBytes, testObjectMeta) == nil { + // if that succeeds, unmarshal for real + encodingjson.Unmarshal(singleFieldBytes, accumulatedObjectMeta) + } + } + } + + return accumulatedObjectMeta, true, nil +} + +func setObjectMeta(u *unstructured.Unstructured, objectMeta *metav1.ObjectMeta) error { + if objectMeta == nil { + unstructured.RemoveNestedField(u.UnstructuredContent(), "metadata") + return nil + } + + metadata, err := runtime.DefaultUnstructuredConverter.ToUnstructured(objectMeta) + if err != nil { + return err + } + + u.UnstructuredContent()["metadata"] = metadata + return nil +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go index 81c3ac705..a6d6e23a1 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go @@ -17,9 +17,23 @@ limitations under the License. package apiserver import ( + "math/rand" + "reflect" "testing" + corev1 "k8s.io/api/core/v1" + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + "k8s.io/apiextensions-apiserver/pkg/apiserver/conversion" + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/testing/fuzzer" + metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/apimachinery/pkg/util/diff" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" ) func TestConvertFieldLabel(t *testing.T) { @@ -64,10 +78,14 @@ func TestConvertFieldLabel(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - c := crdObjectConverter{ - UnstructuredObjectConverter: unstructured.UnstructuredObjectConverter{}, - clusterScoped: test.clusterScoped, + crd := apiextensions.CustomResourceDefinition{} + + if test.clusterScoped { + crd.Spec.Scope = apiextensions.ClusterScoped + } else { + crd.Spec.Scope = apiextensions.NamespaceScoped } + _, c := conversion.NewCRDConverter(&crd) label, value, err := c.ConvertFieldLabel("", "", test.label, "value") if e, a := test.expectError, err != nil; e != a { @@ -89,3 +107,202 @@ func TestConvertFieldLabel(t *testing.T) { }) } } + +func TestRoundtripObjectMeta(t *testing.T) { + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + codec := json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false) + seed := rand.Int63() + fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(seed), codecs) + + N := 1000 + for i := 0; i < N; i++ { + u := &unstructured.Unstructured{Object: map[string]interface{}{}} + original := &metav1.ObjectMeta{} + fuzzer.Fuzz(original) + if err := setObjectMeta(u, original); err != nil { + t.Fatalf("unexpected error setting ObjectMeta: %v", err) + } + o, _, err := getObjectMeta(u, false) + if err != nil { + t.Fatalf("unexpected error getting the Objectmeta: %v", err) + } + + if !equality.Semantic.DeepEqual(original, o) { + t.Errorf("diff: %v\nCodec: %#v", diff.ObjectReflectDiff(original, o), codec) + } + } +} + +// TestMalformedObjectMetaFields sets a number of different random values and types for all +// metadata fields. If json.Unmarshal accepts them, compare that getObjectMeta +// gives the same result. Otherwise, drop malformed fields. +func TestMalformedObjectMetaFields(t *testing.T) { + fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(rand.Int63()), serializer.NewCodecFactory(runtime.NewScheme())) + spuriousValues := func() []interface{} { + return []interface{}{ + // primitives + nil, + int64(1), + float64(1.5), + true, + "a", + // well-formed complex values + []interface{}{"a", "b"}, + map[string]interface{}{"a": "1", "b": "2"}, + []interface{}{int64(1), int64(2)}, + []interface{}{float64(1.5), float64(2.5)}, + // known things json decoding tolerates + map[string]interface{}{"a": "1", "b": nil}, + // malformed things + map[string]interface{}{"a": "1", "b": []interface{}{"nested"}}, + []interface{}{"a", int64(1), float64(1.5), true, []interface{}{"nested"}}, + } + } + N := 100 + for i := 0; i < N; i++ { + fuzzedObjectMeta := &metav1.ObjectMeta{} + fuzzer.Fuzz(fuzzedObjectMeta) + goodMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy()) + if err != nil { + t.Fatal(err) + } + for _, pth := range jsonPaths(nil, goodMetaMap) { + for _, v := range spuriousValues() { + // skip values of same type, because they can only cause decoding errors further insides + orig, err := JsonPathValue(goodMetaMap, pth, 0) + if err != nil { + t.Fatalf("unexpected to not find something at %v: %v", pth, err) + } + if reflect.TypeOf(v) == reflect.TypeOf(orig) { + continue + } + + // make a spurious map + spuriousMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy()) + if err != nil { + t.Fatal(err) + } + if err := SetJsonPath(spuriousMetaMap, pth, 0, v); err != nil { + t.Fatal(err) + } + + // See if it can unmarshal to object meta + spuriousJSON, err := encodingjson.Marshal(spuriousMetaMap) + if err != nil { + t.Fatalf("error on %v=%#v: %v", pth, v, err) + } + expectedObjectMeta := &metav1.ObjectMeta{} + if err := encodingjson.Unmarshal(spuriousJSON, expectedObjectMeta); err != nil { + // if standard json unmarshal would fail decoding this field, drop the field entirely + truncatedMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy()) + if err != nil { + t.Fatal(err) + } + + // we expect this logic for the different fields: + switch { + default: + // delete complete top-level field by default + DeleteJsonPath(truncatedMetaMap, pth[:1], 0) + } + + truncatedJSON, err := encodingjson.Marshal(truncatedMetaMap) + if err != nil { + t.Fatalf("error on %v=%#v: %v", pth, v, err) + } + expectedObjectMeta = &metav1.ObjectMeta{} + if err := encodingjson.Unmarshal(truncatedJSON, expectedObjectMeta); err != nil { + t.Fatalf("error on %v=%#v: %v", pth, v, err) + } + } + + // make sure dropInvalidTypedFields+getObjectMeta matches what we expect + u := &unstructured.Unstructured{Object: map[string]interface{}{"metadata": spuriousMetaMap}} + actualObjectMeta, _, err := getObjectMeta(u, true) + if err != nil { + t.Errorf("got unexpected error after dropping invalid typed fields on %v=%#v: %v", pth, v, err) + continue + } + + if !equality.Semantic.DeepEqual(expectedObjectMeta, actualObjectMeta) { + t.Errorf("%v=%#v, diff: %v\n", pth, v, diff.ObjectReflectDiff(expectedObjectMeta, actualObjectMeta)) + t.Errorf("expectedObjectMeta %#v", expectedObjectMeta) + } + } + } + } +} + +func TestGetObjectMetaNils(t *testing.T) { + u := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "kind": "Pod", + "apiVersion": "v1", + "metadata": map[string]interface{}{ + "generateName": nil, + "labels": map[string]interface{}{ + "foo": nil, + }, + }, + }, + } + + o, _, err := getObjectMeta(u, true) + if err != nil { + t.Fatal(err) + } + if o.GenerateName != "" { + t.Errorf("expected null json value to be read as \"\" string, but got: %q", o.GenerateName) + } + if got, expected := o.Labels, map[string]string{"foo": ""}; !reflect.DeepEqual(got, expected) { + t.Errorf("unexpected labels, expected=%#v, got=%#v", expected, got) + } + + // double check this what the kube JSON decode is doing + bs, _ := encodingjson.Marshal(u.UnstructuredContent()) + kubeObj, _, err := clientgoscheme.Codecs.UniversalDecoder(corev1.SchemeGroupVersion).Decode(bs, nil, nil) + if err != nil { + t.Fatal(err) + } + pod, ok := kubeObj.(*corev1.Pod) + if !ok { + t.Fatalf("expected v1 Pod, got: %T", pod) + } + if got, expected := o.GenerateName, pod.ObjectMeta.GenerateName; got != expected { + t.Errorf("expected generatedName to be %q, got %q", expected, got) + } + if got, expected := o.Labels, pod.ObjectMeta.Labels; !reflect.DeepEqual(got, expected) { + t.Errorf("expected labels to be %v, got %v", expected, got) + } +} + +func TestGetObjectMeta(t *testing.T) { + for i := 0; i < 100; i++ { + u := &unstructured.Unstructured{Object: map[string]interface{}{ + "metadata": map[string]interface{}{ + "name": "good", + "Name": "bad1", + "nAme": "bad2", + "naMe": "bad3", + "namE": "bad4", + + "namespace": "good", + "Namespace": "bad1", + "nAmespace": "bad2", + "naMespace": "bad3", + "namEspace": "bad4", + + "creationTimestamp": "a", + }, + }} + + meta, _, err := getObjectMeta(u, true) + if err != nil { + t.Fatal(err) + } + if meta.Name != "good" || meta.Namespace != "good" { + t.Fatalf("got %#v", meta) + } + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go new file mode 100644 index 000000000..8d9bb24f8 --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go @@ -0,0 +1,235 @@ +/* +Copyright 2018 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 apiserver + +import ( + "bytes" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" +) + +type ( + jsonPathNode struct { + index *int + field string + } + JsonPath []jsonPathNode +) + +func (p JsonPath) String() string { + var buf bytes.Buffer + for _, n := range p { + if n.index == nil { + buf.WriteString("." + n.field) + } else { + buf.WriteString(fmt.Sprintf("[%d]", *n.index)) + } + } + return buf.String() +} + +func jsonPaths(base JsonPath, j map[string]interface{}) []JsonPath { + res := make([]JsonPath, 0, len(j)) + for k, old := range j { + kPth := append(append([]jsonPathNode(nil), base...), jsonPathNode{field: k}) + res = append(res, kPth) + + switch old := old.(type) { + case map[string]interface{}: + res = append(res, jsonPaths(kPth, old)...) + case []interface{}: + res = append(res, jsonIterSlice(kPth, old)...) + } + } + return res +} + +func jsonIterSlice(base JsonPath, j []interface{}) []JsonPath { + res := make([]JsonPath, 0, len(j)) + for i, old := range j { + index := i + iPth := append(append([]jsonPathNode(nil), base...), jsonPathNode{index: &index}) + res = append(res, iPth) + + switch old := old.(type) { + case map[string]interface{}: + res = append(res, jsonPaths(iPth, old)...) + case []interface{}: + res = append(res, jsonIterSlice(iPth, old)...) + } + } + return res +} + +func JsonPathValue(j map[string]interface{}, pth JsonPath, base int) (interface{}, error) { + if len(pth) == base { + return nil, fmt.Errorf("empty json path is invalid for object") + } + if pth[base].index != nil { + return nil, fmt.Errorf("index json path is invalid for object") + } + field, ok := j[pth[base].field] + if !ok || len(pth) == base+1 { + if len(pth) > base+1 { + return nil, fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth) + } + return j[pth[base].field], nil + } + switch field := field.(type) { + case map[string]interface{}: + return JsonPathValue(field, pth, base+1) + case []interface{}: + return jsonPathValueSlice(field, pth, base+1) + default: + return nil, fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1]) + } +} + +func jsonPathValueSlice(j []interface{}, pth JsonPath, base int) (interface{}, error) { + if len(pth) == base { + return nil, fmt.Errorf("empty json path %q is invalid for object", pth) + } + if pth[base].index == nil { + return nil, fmt.Errorf("field json path %q is invalid for object", pth[:base+1]) + } + if *pth[base].index >= len(j) { + return nil, fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j)) + } + if len(pth) == base+1 { + return j[*pth[base].index], nil + } + switch item := j[*pth[base].index].(type) { + case map[string]interface{}: + return JsonPathValue(item, pth, base+1) + case []interface{}: + return jsonPathValueSlice(item, pth, base+1) + default: + return nil, fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1]) + } +} + +func SetJsonPath(j map[string]interface{}, pth JsonPath, base int, value interface{}) error { + if len(pth) == base { + return fmt.Errorf("empty json path is invalid for object") + } + if pth[base].index != nil { + return fmt.Errorf("index json path is invalid for object") + } + field, ok := j[pth[base].field] + if !ok || len(pth) == base+1 { + if len(pth) > base+1 { + return fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth) + } + j[pth[base].field] = runtime.DeepCopyJSONValue(value) + return nil + } + switch field := field.(type) { + case map[string]interface{}: + return SetJsonPath(field, pth, base+1, value) + case []interface{}: + return setJsonPathSlice(field, pth, base+1, value) + default: + return fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1]) + } +} + +func setJsonPathSlice(j []interface{}, pth JsonPath, base int, value interface{}) error { + if len(pth) == base { + return fmt.Errorf("empty json path %q is invalid for object", pth) + } + if pth[base].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth[:base+1]) + } + if *pth[base].index >= len(j) { + return fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j)) + } + if len(pth) == base+1 { + j[*pth[base].index] = runtime.DeepCopyJSONValue(value) + return nil + } + switch item := j[*pth[base].index].(type) { + case map[string]interface{}: + return SetJsonPath(item, pth, base+1, value) + case []interface{}: + return setJsonPathSlice(item, pth, base+1, value) + default: + return fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1]) + } +} + +func DeleteJsonPath(j map[string]interface{}, pth JsonPath, base int) error { + if len(pth) == base { + return fmt.Errorf("empty json path is invalid for object") + } + if pth[base].index != nil { + return fmt.Errorf("index json path is invalid for object") + } + field, ok := j[pth[base].field] + if !ok || len(pth) == base+1 { + if len(pth) > base+1 { + return fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth) + } + delete(j, pth[base].field) + return nil + } + switch field := field.(type) { + case map[string]interface{}: + return DeleteJsonPath(field, pth, base+1) + case []interface{}: + if len(pth) == base+2 { + if pth[base+1].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth) + } + j[pth[base].field] = append(field[:*pth[base+1].index], field[*pth[base+1].index+1:]...) + return nil + } + return deleteJsonPathSlice(field, pth, base+1) + default: + return fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1]) + } +} + +func deleteJsonPathSlice(j []interface{}, pth JsonPath, base int) error { + if len(pth) == base { + return fmt.Errorf("empty json path %q is invalid for object", pth) + } + if pth[base].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth[:base+1]) + } + if *pth[base].index >= len(j) { + return fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j)) + } + if len(pth) == base+1 { + return fmt.Errorf("cannot delete item at index %q in-place", pth[:base]) + } + switch item := j[*pth[base].index].(type) { + case map[string]interface{}: + return DeleteJsonPath(item, pth, base+1) + case []interface{}: + if len(pth) == base+2 { + if pth[base+1].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth) + } + j[*pth[base].index] = append(item[:*pth[base+1].index], item[*pth[base+1].index+1:]) + return nil + } + return deleteJsonPathSlice(item, pth, base+1) + default: + return fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1]) + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go index 444418888..63fcb510a 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package clientset import ( - glog "github.com/golang/glog" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" @@ -74,7 +73,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go index 3421911a7..ee865e56d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go index 9988cd0b4..e65fe63ea 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -41,9 +41,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -53,7 +54,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go index 3113c1a6d..f37309186 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go index bc08c37e1..bd73f1179 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go index 7da7276b7..a1fd337f9 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go index 3a2513caf..f25a6ce34 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go index 39327a9c3..288683ef9 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go index 10fd3cc15..11aefe869 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeCustomResourceDefinitions) List(opts v1.ListOptions) (result *v1bet if label == nil { label = labels.Everything() } - list := &v1beta1.CustomResourceDefinitionList{} + list := &v1beta1.CustomResourceDefinitionList{ListMeta: obj.(*v1beta1.CustomResourceDefinitionList).ListMeta} for _, item := range obj.(*v1beta1.CustomResourceDefinitionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go index 07a7c1dce..2a989d4be 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go index 9519b78f1..152a9fea0 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package internalclientset import ( - glog "github.com/golang/glog" apiextensionsinternalversion "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" @@ -66,7 +65,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go index 22ccee919..01b3d5e0f 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go index 3c0f41dba..72ab169e9 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -41,9 +41,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -53,7 +54,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go index 5c17a1003..89093fd9f 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go index f9de21961..01df98a6b 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,11 +19,7 @@ limitations under the License. package scheme import ( - os "os" - apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install" - announced "k8s.io/apimachinery/pkg/apimachinery/announced" - registered "k8s.io/apimachinery/pkg/apimachinery/registered" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -34,15 +30,12 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) -var Registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) -var GroupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - func init() { v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - Install(GroupFactoryRegistry, Registry, Scheme) + Install(Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - apiextensions.Install(groupFactoryRegistry, registry, scheme) +func Install(scheme *runtime.Scheme) { + apiextensions.Install(scheme) } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go index 9e08a905a..31b34404c 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *ApiextensionsClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("apiextensions.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("apiextensions.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("apiextensions.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go index 322454cdf..f3ddc8044 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_apiextensions_client.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_apiextensions_client.go index 32bb913c0..1a601e5b0 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_apiextensions_client.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_apiextensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_customresourcedefinition.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_customresourcedefinition.go index c5cd1da48..74016362d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_customresourcedefinition.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeCustomResourceDefinitions) List(opts v1.ListOptions) (result *apiex if label == nil { label = labels.Everything() } - list := &apiextensions.CustomResourceDefinitionList{} + list := &apiextensions.CustomResourceDefinitionList{ListMeta: obj.(*apiextensions.CustomResourceDefinitionList).ListMeta} for _, item := range obj.(*apiextensions.CustomResourceDefinitionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go index 74c295f6c..a88821021 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go index e88c53087..7b48c57ca 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go index 9d9b12787..589b4b20c 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go index 331dad83e..f78edbb59 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go index 6e7141621..94d039c72 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,12 +32,16 @@ import ( cache "k8s.io/client-go/tools/cache" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client clientset.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -45,23 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client clientset.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client clientset.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client clientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -110,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go index a742bbd25..da8a2ab0c 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index 2048b744f..3b17f5a1a 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go index f096df135..8236e2acc 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go index 08587b732..2c54f3ce5 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go index 15c7e9f14..d9444144b 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go index b1d07527d..84b04523d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,12 +32,16 @@ import ( cache "k8s.io/client-go/tools/cache" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client internalclientset.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -45,23 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client internalclientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -110,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go index 77a9e1b0b..c12c44074 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go index d41da2418..5854db0ca 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go index c736b3db8..f64f01d9d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go index 05a413aee..5e3ae381d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go index 468f5a664..87633217b 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go index 65b786659..429782deb 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/start.go b/vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/start.go index df3cf3e60..c36071d8d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/start.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/start.go @@ -51,7 +51,7 @@ func NewCustomResourceDefinitionsServerOptions(out, errOut io.Writer) *CustomRes StdErr: errOut, } - // the shared informer is not needed for kube-aggregator. Disable the kubeconfig flag and the client creation. + // the shared informer is not needed for apiextentions apiserver. Disable the kubeconfig flag and the client creation. o.RecommendedOptions.CoreAPI = nil return o @@ -86,7 +86,7 @@ func NewCommandStartCustomResourceDefinitionsServer(out, errOut io.Writer, stopC func (o CustomResourceDefinitionsServerOptions) Validate(args []string) error { errors := []error{} errors = append(errors, o.RecommendedOptions.Validate()...) - errors = append(errors, o.APIEnablement.Validate(apiserver.Registry)...) + errors = append(errors, o.APIEnablement.Validate(apiserver.Scheme)...) return utilerrors.NewAggregate(errors) } @@ -104,7 +104,7 @@ func (o CustomResourceDefinitionsServerOptions) Config() (*apiserver.Config, err if err := o.RecommendedOptions.ApplyTo(serverConfig, apiserver.Scheme); err != nil { return nil, err } - if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Registry); err != nil { + if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Scheme); err != nil { return nil, err } @@ -137,7 +137,7 @@ func (o CustomResourceDefinitionsServerOptions) RunCustomResourceDefinitionsServ return err } - server, err := config.Complete().New(genericapiserver.EmptyDelegate) + server, err := config.Complete().New(genericapiserver.NewEmptyDelegate()) if err != nil { return err } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go b/vendor/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go new file mode 100644 index 000000000..5c2ebbcaa --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go @@ -0,0 +1,142 @@ +/* +Copyright 2018 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 establish + +import ( + "fmt" + "time" + + "github.com/golang/glog" + apierrors "k8s.io/apimachinery/pkg/api/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + client "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion" + informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion" + listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion" +) + +// EstablishingController controls how and when CRD is established. +type EstablishingController struct { + crdClient client.CustomResourceDefinitionsGetter + crdLister listers.CustomResourceDefinitionLister + crdSynced cache.InformerSynced + + // To allow injection for testing. + syncFn func(key string) error + + queue workqueue.RateLimitingInterface +} + +// NewEstablishingController creates new EstablishingController. +func NewEstablishingController(crdInformer informers.CustomResourceDefinitionInformer, + crdClient client.CustomResourceDefinitionsGetter) *EstablishingController { + ec := &EstablishingController{ + crdClient: crdClient, + crdLister: crdInformer.Lister(), + crdSynced: crdInformer.Informer().HasSynced, + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "crdEstablishing"), + } + + ec.syncFn = ec.sync + + return ec +} + +// QueueCRD adds CRD into the establishing queue. +func (ec *EstablishingController) QueueCRD(key string, timeout time.Duration) { + ec.queue.AddAfter(key, timeout) +} + +// Run starts the EstablishingController. +func (ec *EstablishingController) Run(stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer ec.queue.ShutDown() + + glog.Infof("Starting EstablishingController") + defer glog.Infof("Shutting down EstablishingController") + + if !cache.WaitForCacheSync(stopCh, ec.crdSynced) { + return + } + + // only start one worker thread since its a slow moving API + go wait.Until(ec.runWorker, time.Second, stopCh) + + <-stopCh +} + +func (ec *EstablishingController) runWorker() { + for ec.processNextWorkItem() { + } +} + +// processNextWorkItem deals with one key off the queue. +// It returns false when it's time to quit. +func (ec *EstablishingController) processNextWorkItem() bool { + key, quit := ec.queue.Get() + if quit { + return false + } + defer ec.queue.Done(key) + + err := ec.syncFn(key.(string)) + if err == nil { + return true + } + + utilruntime.HandleError(fmt.Errorf("%v failed with: %v", key, err)) + ec.queue.AddRateLimited(key) + + return true +} + +// sync is used to turn CRDs into the Established state. +func (ec *EstablishingController) sync(key string) error { + cachedCRD, err := ec.crdLister.Get(key) + if apierrors.IsNotFound(err) { + return nil + } + if err != nil { + return err + } + + if !apiextensions.IsCRDConditionTrue(cachedCRD, apiextensions.NamesAccepted) || + apiextensions.IsCRDConditionTrue(cachedCRD, apiextensions.Established) { + return nil + } + + crd := cachedCRD.DeepCopy() + establishedCondition := apiextensions.CustomResourceDefinitionCondition{ + Type: apiextensions.Established, + Status: apiextensions.ConditionTrue, + Reason: "InitialNamesAccepted", + Message: "the initial names have been accepted", + } + apiextensions.SetCRDCondition(crd, establishedCondition) + + // Update server with new CRD condition. + _, err = ec.crdClient.CustomResourceDefinitions().UpdateStatus(crd) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go b/vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go index 16016e493..f00def4b1 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go @@ -24,6 +24,7 @@ import ( "github.com/golang/glog" + "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -191,7 +192,10 @@ func (c *NamingConditionController) calculateNamesAndConditions(in *apiextension namesAcceptedCondition.Message = "no conflicts found" } - // set EstablishedCondition to true if all names are accepted. Never set it back to false. + // set EstablishedCondition initially to false, then set it to true in establishing controller. + // The Establishing Controller will see the NamesAccepted condition when it arrives through the shared informer. + // At that time the API endpoint handler will serve the endpoint, avoiding a race + // which we had if we set Established to true here. establishedCondition := apiextensions.CustomResourceDefinitionCondition{ Type: apiextensions.Established, Status: apiextensions.ConditionFalse, @@ -204,8 +208,8 @@ func (c *NamingConditionController) calculateNamesAndConditions(in *apiextension if establishedCondition.Status != apiextensions.ConditionTrue && namesAcceptedCondition.Status == apiextensions.ConditionTrue { establishedCondition = apiextensions.CustomResourceDefinitionCondition{ Type: apiextensions.Established, - Status: apiextensions.ConditionTrue, - Reason: "InitialNamesAccepted", + Status: apiextensions.ConditionFalse, + Reason: "Installing", Message: "the initial names have been accepted", } } @@ -238,12 +242,16 @@ func (c *NamingConditionController) sync(key string) error { return err } + // Skip checking names if Spec and Status names are same. + if equality.Semantic.DeepEqual(inCustomResourceDefinition.Spec.Names, inCustomResourceDefinition.Status.AcceptedNames) { + return nil + } + acceptedNames, namingCondition, establishedCondition := c.calculateNamesAndConditions(inCustomResourceDefinition) // nothing to do if accepted names and NamesAccepted condition didn't change if reflect.DeepEqual(inCustomResourceDefinition.Status.AcceptedNames, acceptedNames) && - apiextensions.IsCRDConditionEquivalent(&namingCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.NamesAccepted)) && - apiextensions.IsCRDConditionEquivalent(&establishedCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.Established)) { + apiextensions.IsCRDConditionEquivalent(&namingCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.NamesAccepted)) { return nil } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go b/vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go index 615c5dd85..717e52884 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go @@ -95,19 +95,17 @@ var acceptedCondition = apiextensions.CustomResourceDefinitionCondition{ Message: "no conflicts found", } -func nameConflictCondition(reason, message string) apiextensions.CustomResourceDefinitionCondition { - return apiextensions.CustomResourceDefinitionCondition{ - Type: apiextensions.NamesAccepted, - Status: apiextensions.ConditionFalse, - Reason: reason, - Message: message, - } +var notAcceptedCondition = apiextensions.CustomResourceDefinitionCondition{ + Type: apiextensions.NamesAccepted, + Status: apiextensions.ConditionFalse, + Reason: "NotAccepted", + Message: "not all names are accepted", } -var establishedCondition = apiextensions.CustomResourceDefinitionCondition{ +var installingCondition = apiextensions.CustomResourceDefinitionCondition{ Type: apiextensions.Established, - Status: apiextensions.ConditionTrue, - Reason: "InitialNamesAccepted", + Status: apiextensions.ConditionFalse, + Reason: "Installing", Message: "the initial names have been accepted", } @@ -118,6 +116,15 @@ var notEstablishedCondition = apiextensions.CustomResourceDefinitionCondition{ Message: "not all names are accepted", } +func nameConflictCondition(reason, message string) apiextensions.CustomResourceDefinitionCondition { + return apiextensions.CustomResourceDefinitionCondition{ + Type: apiextensions.NamesAccepted, + Status: apiextensions.ConditionFalse, + Reason: reason, + Message: message, + } +} + func TestSync(t *testing.T) { tests := []struct { name string @@ -136,7 +143,7 @@ func TestSync(t *testing.T) { Plural: "alfa", }, expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "different groups", @@ -146,7 +153,7 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "conflict plural to singular", @@ -206,7 +213,7 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "merge on conflicts", @@ -248,7 +255,7 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "no conflicts on self, remove shortname", @@ -264,44 +271,44 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { - name: "established before with true condition", - in: newCRD("alfa.bravo.com").Condition(establishedCondition).NewOrDie(), + name: "installing before with true condition", + in: newCRD("alfa.bravo.com").Condition(acceptedCondition).NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{}, expectedNames: apiextensions.CustomResourceDefinitionNames{ Plural: "alfa", }, expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { - name: "not established before with false condition", - in: newCRD("alfa.bravo.com").Condition(notEstablishedCondition).NewOrDie(), + name: "not installing before with false condition", + in: newCRD("alfa.bravo.com").Condition(notAcceptedCondition).NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{}, expectedNames: apiextensions.CustomResourceDefinitionNames{ Plural: "alfa", }, expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { - name: "conflicting, established before with true condition", + name: "conflicting, installing before with true condition", in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"). - Condition(establishedCondition). + Condition(acceptedCondition). NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{ newCRD("india.bravo.com").StatusNames("india", "alfa", "", "").NewOrDie(), }, expectedNames: names("", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: nameConflictCondition("PluralConflict", `"alfa" is already in use`), - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: notEstablishedCondition, }, { - name: "conflicting, not established before with false condition", + name: "conflicting, not installing before with false condition", in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"). - Condition(notEstablishedCondition). + Condition(notAcceptedCondition). NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{ newCRD("india.bravo.com").StatusNames("india", "alfa", "", "").NewOrDie(), @@ -322,7 +329,7 @@ func TestSync(t *testing.T) { crdLister: listers.NewCustomResourceDefinitionLister(crdIndexer), crdMutationCache: cache.NewIntegerResourceVersionMutationCache(crdIndexer, crdIndexer, 60*time.Second, false), } - actualNames, actualNameConflictCondition, actualEstablishedCondition := c.calculateNamesAndConditions(tc.in) + actualNames, actualNameConflictCondition, establishedCondition := c.calculateNamesAndConditions(tc.in) if e, a := tc.expectedNames, actualNames; !reflect.DeepEqual(e, a) { t.Errorf("%v expected %v, got %#v", tc.name, e, a) @@ -330,7 +337,7 @@ func TestSync(t *testing.T) { if e, a := tc.expectedNameConflictCondition, actualNameConflictCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) { t.Errorf("%v expected %v, got %v", tc.name, e, a) } - if e, a := tc.expectedEstablishedCondition, actualEstablishedCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) { + if e, a := tc.expectedEstablishedCondition, establishedCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) { t.Errorf("%v expected %v, got %v", tc.name, e, a) } } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/features/OWNERS b/vendor/k8s.io/apiextensions-apiserver/pkg/features/OWNERS new file mode 100644 index 000000000..fe7b0144e --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/features/OWNERS @@ -0,0 +1,2 @@ +approvers: +- feature-approvers diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go b/vendor/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go index b80e80ac3..24e72f91e 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go @@ -36,6 +36,7 @@ const ( // owner: @sttts, @nikhita // alpha: v1.10 + // beta: v1.11 // // CustomResourceSubresources defines the subresources for CustomResources CustomResourceSubresources utilfeature.Feature = "CustomResourceSubresources" @@ -50,5 +51,5 @@ func init() { // available throughout Kubernetes binaries. var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureSpec{ CustomResourceValidation: {Default: true, PreRelease: utilfeature.Beta}, - CustomResourceSubresources: {Default: false, PreRelease: utilfeature.Alpha}, + CustomResourceSubresources: {Default: true, PreRelease: utilfeature.Beta}, } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go index bf54fe33b..d9e8fd97c 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go @@ -17,16 +17,17 @@ limitations under the License. package customresource import ( + "context" "fmt" "strings" autoscalingv1 "k8s.io/api/autoscaling/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -106,6 +107,59 @@ func newREST(resource schema.GroupResource, listKind schema.GroupVersionKind, st // Implement CategoriesProvider var _ rest.CategoriesProvider = &REST{} +// List returns a list of items matching labels and field according to the store's PredicateFunc. +func (e *REST) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { + l, err := e.Store.List(ctx, options) + if err != nil { + return nil, err + } + + // Shallow copy ObjectMeta in returned list for each item. Native types have `Items []Item` fields and therefore + // implicitly shallow copy ObjectMeta. The generic store sets the self-link for each item. So this is necessary + // to avoid mutation of the objects from the cache. + if ul, ok := l.(*unstructured.UnstructuredList); ok { + for i := range ul.Items { + shallowCopyObjectMeta(&ul.Items[i]) + } + } + + return l, nil +} + +func (r *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + o, err := r.Store.Get(ctx, name, options) + if err != nil { + return nil, err + } + if u, ok := o.(*unstructured.Unstructured); ok { + shallowCopyObjectMeta(u) + } + return o, nil +} + +func shallowCopyObjectMeta(u runtime.Unstructured) { + obj := shallowMapDeepCopy(u.UnstructuredContent()) + if metadata, ok := obj["metadata"]; ok { + if metadata, ok := metadata.(map[string]interface{}); ok { + obj["metadata"] = shallowMapDeepCopy(metadata) + u.SetUnstructuredContent(obj) + } + } +} + +func shallowMapDeepCopy(in map[string]interface{}) map[string]interface{} { + if in == nil { + return nil + } + + out := make(map[string]interface{}, len(in)) + for k, v := range in { + out[k] = v + } + + return out +} + // Categories implements the CategoriesProvider interface. Returns a list of categories a resource is part of. func (r *REST) Categories() []string { return r.categories @@ -116,17 +170,19 @@ type StatusREST struct { store *genericregistry.Store } +var _ = rest.Patcher(&StatusREST{}) + func (r *StatusREST) New() runtime.Object { return &unstructured.Unstructured{} } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } @@ -150,7 +206,7 @@ func (r *ScaleREST) New() runtime.Object { return &autoscalingv1.Scale{} } -func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *ScaleREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { cr, err := r.registry.GetCustomResource(ctx, name, options) if err != nil { return nil, err @@ -166,7 +222,7 @@ func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *met return scaleObject, err } -func (r *ScaleREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { cr, err := r.registry.GetCustomResource(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, err diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go index 8bee3396c..15a242e44 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go @@ -21,12 +21,15 @@ import ( "reflect" "strings" "testing" + "time" autoscalingv1 "k8s.io/api/autoscaling/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" + metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" @@ -58,7 +61,7 @@ func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcdtestin typer := apiserver.UnstructuredObjectTyper{ Delegate: parameterScheme, - UnstructuredTyper: discovery.NewUnstructuredObjectTyper(nil), + UnstructuredTyper: discovery.NewUnstructuredObjectTyper(), } kind := schema.GroupVersionKind{Group: "mygroup.example.com", Version: "v1beta1", Kind: "Noxu"} @@ -72,8 +75,19 @@ func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcdtestin status := &apiextensions.CustomResourceSubresourceStatus{} - // TODO: identify how to pass printer specification from the CRD - table, _ := tableconvertor.New(nil) + headers := []apiextensions.CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"}, + {Name: "Replicas", Type: "integer", JSONPath: ".spec.replicas"}, + {Name: "Missing", Type: "string", JSONPath: ".spec.missing"}, + {Name: "Invalid", Type: "integer", JSONPath: ".spec.string"}, + {Name: "String", Type: "string", JSONPath: ".spec.string"}, + {Name: "StringFloat64", Type: "string", JSONPath: ".spec.float64"}, + {Name: "StringInt64", Type: "string", JSONPath: ".spec.replicas"}, + {Name: "StringBool", Type: "string", JSONPath: ".spec.bool"}, + {Name: "Float64", Type: "number", JSONPath: ".spec.float64"}, + {Name: "Bool", Type: "boolean", JSONPath: ".spec.bool"}, + } + table, _ := tableconvertor.New(headers) storage := customresource.NewStorage( schema.GroupResource{Group: "mygroup.example.com", Resource: "noxus"}, @@ -112,11 +126,18 @@ func validNewCustomResource() *unstructured.Unstructured { "apiVersion": "mygroup.example.com/v1beta1", "kind": "Noxu", "metadata": map[string]interface{}{ - "namespace": "default", - "name": "foo", + "namespace": "default", + "name": "foo", + "creationTimestamp": time.Now().Add(-time.Hour*12 - 30*time.Minute).UTC().Format(time.RFC3339), }, "spec": map[string]interface{}{ - "replicas": int64(7), + "replicas": int64(7), + "string": "string", + "float64": float64(3.1415926), + "bool": true, + "stringList": []interface{}{"foo", "bar"}, + "mixedList": []interface{}{"foo", int64(42)}, + "nonPrimitiveList": []interface{}{"foo", []interface{}{int64(1), int64(2)}}, }, }, } @@ -160,6 +181,58 @@ func TestDelete(t *testing.T) { test.TestDelete(validNewCustomResource()) } +func TestGenerationNumber(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.CustomResource.Store.DestroyFunc() + modifiedRno := *validNewCustomResource() + modifiedRno.SetGeneration(10) + ctx := genericapirequest.NewDefaultContext() + cr, err := createCustomResource(storage.CustomResource, modifiedRno, t) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + etcdCR, err := storage.CustomResource.Get(ctx, cr.GetName(), &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + storedCR, _ := etcdCR.(*unstructured.Unstructured) + + // Generation initialization + if storedCR.GetGeneration() != 1 { + t.Fatalf("Unexpected generation number %v", storedCR.GetGeneration()) + } + + // Updates to spec should increment the generation number + setSpecReplicas(storedCR, getSpecReplicas(storedCR)+1) + if _, _, err := storage.CustomResource.Update(ctx, storedCR.GetName(), rest.DefaultUpdatedObjectInfo(storedCR), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc); err != nil { + t.Errorf("unexpected error: %v", err) + } + etcdCR, err = storage.CustomResource.Get(ctx, cr.GetName(), &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + storedCR, _ = etcdCR.(*unstructured.Unstructured) + if storedCR.GetGeneration() != 2 { + t.Fatalf("Unexpected generation, spec: %v", storedCR.GetGeneration()) + } + + // Updates to status should not increment the generation number + setStatusReplicas(storedCR, getStatusReplicas(storedCR)+1) + if _, _, err := storage.CustomResource.Update(ctx, storedCR.GetName(), rest.DefaultUpdatedObjectInfo(storedCR), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc); err != nil { + t.Errorf("unexpected error: %v", err) + } + etcdCR, err = storage.CustomResource.Get(ctx, cr.GetName(), &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + storedCR, _ = etcdCR.(*unstructured.Unstructured) + if storedCR.GetGeneration() != 2 { + t.Fatalf("Unexpected generation, spec: %v", storedCR.GetGeneration()) + } + +} + func TestCategories(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) @@ -173,6 +246,77 @@ func TestCategories(t *testing.T) { } } +func TestColumns(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.CustomResource.Store.DestroyFunc() + + ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault) + key := "/noxus/" + metav1.NamespaceDefault + "/foo" + validCustomResource := validNewCustomResource() + if err := storage.CustomResource.Storage.Create(ctx, key, validCustomResource, nil, 0); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + gottenList, err := storage.CustomResource.List(ctx, &metainternal.ListOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + tbl, err := storage.CustomResource.ConvertToTable(ctx, gottenList, &metav1beta1.TableOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expectedColumns := []struct { + Name, Type string + }{ + {"Name", "string"}, + {"Age", "date"}, + {"Replicas", "integer"}, + {"Missing", "string"}, + {"Invalid", "integer"}, + {"String", "string"}, + {"StringFloat64", "string"}, + {"StringInt64", "string"}, + {"StringBool", "string"}, + {"Float64", "number"}, + {"Bool", "boolean"}, + } + if len(tbl.ColumnDefinitions) != len(expectedColumns) { + t.Fatalf("got %d columns, expected %d. Got: %+v", len(tbl.ColumnDefinitions), len(expectedColumns), tbl.ColumnDefinitions) + } + for i, d := range tbl.ColumnDefinitions { + if d.Name != expectedColumns[i].Name { + t.Errorf("got column %d name %q, expected %q", i, d.Name, expectedColumns[i].Name) + } + if d.Type != expectedColumns[i].Type { + t.Errorf("got column %d type %q, expected %q", i, d.Type, expectedColumns[i].Type) + } + } + + expectedRows := [][]interface{}{ + { + "foo", + "12h", + int64(7), + nil, + nil, + "string", + "3.1415926", + "7", + "true", + float64(3.1415926), + true, + }, + } + for i, r := range tbl.Rows { + if !reflect.DeepEqual(r.Cells, expectedRows[i]) { + t.Errorf("got row %d with cells %#v, expected %#v", i, r.Cells, expectedRows[i]) + } + } +} + func TestStatusUpdate(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) @@ -398,3 +542,34 @@ func (c unstructuredJsonCodec) Encode(obj runtime.Object, w io.Writer) error { w.Write(bs) return nil } + +func setSpecReplicas(u *unstructured.Unstructured, replicas int64) { + setNestedField(u, replicas, "spec", "replicas") +} + +func getSpecReplicas(u *unstructured.Unstructured) int64 { + val, found, err := unstructured.NestedInt64(u.Object, "spec", "replicas") + if !found || err != nil { + return 0 + } + return val +} + +func setStatusReplicas(u *unstructured.Unstructured, replicas int64) { + setNestedField(u, replicas, "status", "replicas") +} + +func getStatusReplicas(u *unstructured.Unstructured) int64 { + val, found, err := unstructured.NestedInt64(u.Object, "status", "replicas") + if !found || err != nil { + return 0 + } + return val +} + +func setNestedField(u *unstructured.Unstructured, value interface{}, fields ...string) { + if u.Object == nil { + u.Object = make(map[string]interface{}) + } + unstructured.SetNestedField(u.Object, value, fields...) +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go index a0fd086d0..e3d468036 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go @@ -17,6 +17,7 @@ limitations under the License. package customresource import ( + "context" "fmt" "strings" @@ -26,18 +27,17 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" ) // Registry is an interface for things that know how to store CustomResources. type Registry interface { - ListCustomResources(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error) - WatchCustomResources(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) - GetCustomResource(ctx genericapirequest.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error) - CreateCustomResource(ctx genericapirequest.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error) - UpdateCustomResource(ctx genericapirequest.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error) - DeleteCustomResource(ctx genericapirequest.Context, customResourceID string) error + ListCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error) + WatchCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetCustomResource(ctx context.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error) + CreateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error) + UpdateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error) + DeleteCustomResource(ctx context.Context, customResourceID string) error } // storage puts strong typing around storage calls @@ -51,7 +51,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListCustomResources(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error) { +func (s *storage) ListCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error) { if options != nil && options.FieldSelector != nil && !options.FieldSelector.Empty() { return nil, fmt.Errorf("field selector not supported yet") } @@ -62,11 +62,11 @@ func (s *storage) ListCustomResources(ctx genericapirequest.Context, options *me return obj.(*unstructured.UnstructuredList), err } -func (s *storage) WatchCustomResources(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetCustomResource(ctx genericapirequest.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error) { +func (s *storage) GetCustomResource(ctx context.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error) { obj, err := s.Get(ctx, customResourceID, options) customResource, ok := obj.(*unstructured.Unstructured) if !ok { @@ -82,7 +82,7 @@ func (s *storage) GetCustomResource(ctx genericapirequest.Context, customResourc return customResource, nil } -func (s *storage) CreateCustomResource(ctx genericapirequest.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error) { +func (s *storage) CreateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error) { obj, err := s.Create(ctx, customResource, rest.ValidateAllObjectFunc, false) if err != nil { return nil, err @@ -90,7 +90,7 @@ func (s *storage) CreateCustomResource(ctx genericapirequest.Context, customReso return obj.(*unstructured.Unstructured), nil } -func (s *storage) UpdateCustomResource(ctx genericapirequest.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error) { +func (s *storage) UpdateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error) { obj, _, err := s.Update(ctx, customResource.GetName(), rest.DefaultUpdatedObjectInfo(customResource), createValidation, updateValidation) if err != nil { return nil, err @@ -98,7 +98,7 @@ func (s *storage) UpdateCustomResource(ctx genericapirequest.Context, customReso return obj.(*unstructured.Unstructured), nil } -func (s *storage) DeleteCustomResource(ctx genericapirequest.Context, customResourceID string) error { +func (s *storage) DeleteCustomResource(ctx context.Context, customResourceID string) error { _, _, err := s.Delete(ctx, customResourceID, nil) return err } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go index 4aeaf5efe..1710eb2e1 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go @@ -17,10 +17,11 @@ limitations under the License. package customresource import ( + "context" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) type statusStrategy struct { @@ -31,7 +32,7 @@ func NewStatusStrategy(strategy customResourceStrategy) statusStrategy { return statusStrategy{strategy} } -func (a statusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (a statusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { // update is only allowed to set status newCustomResourceObject := obj.(*unstructured.Unstructured) newCustomResource := newCustomResourceObject.UnstructuredContent() @@ -53,6 +54,6 @@ func (a statusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old } // ValidateUpdate is the default update validation for an end user updating status. -func (a statusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return a.customResourceStrategy.validator.ValidateStatusUpdate(ctx, obj, old, a.scale) } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go index 79b0235f0..8a651d12b 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go @@ -17,11 +17,11 @@ limitations under the License. package customresource import ( + "context" "reflect" "testing" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) func TestPrepareForUpdate(t *testing.T) { @@ -130,7 +130,7 @@ func TestPrepareForUpdate(t *testing.T) { }, } for index, tc := range tcs { - strategy.PrepareForUpdate(genericapirequest.NewContext(), tc.obj, tc.old) + strategy.PrepareForUpdate(context.TODO(), tc.obj, tc.old) if !reflect.DeepEqual(tc.obj, tc.expected) { t.Errorf("test %d failed: expected: %v, got %v", index, tc.expected, tc.obj) } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go index 092bfc89c..4895e287a 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go @@ -17,6 +17,8 @@ limitations under the License. package customresource import ( + "context" + "github.com/go-openapi/validate" apiequality "k8s.io/apimachinery/pkg/api/equality" @@ -28,7 +30,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" apiserverstorage "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -69,7 +70,7 @@ func (a customResourceStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a CustomResource before creation. -func (a customResourceStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (a customResourceStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && a.status != nil { customResourceObject := obj.(*unstructured.Unstructured) customResource := customResourceObject.UnstructuredContent() @@ -85,7 +86,7 @@ func (a customResourceStrategy) PrepareForCreate(ctx genericapirequest.Context, } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (a customResourceStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (a customResourceStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) || a.status == nil { return } @@ -126,7 +127,7 @@ func (a customResourceStrategy) PrepareForUpdate(ctx genericapirequest.Context, } // Validate validates a new CustomResource. -func (a customResourceStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (a customResourceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return a.validator.Validate(ctx, obj, a.scale) } @@ -146,7 +147,7 @@ func (customResourceStrategy) AllowUnconditionalUpdate() bool { } // ValidateUpdate is the default update validation for an end user updating status. -func (a customResourceStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (a customResourceStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return a.validator.ValidateUpdate(ctx, obj, old, a.scale) } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go index 4eb62da6b..e1bed809d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go @@ -18,74 +18,64 @@ package tableconvertor import ( "bytes" + "context" + "encoding/json" "fmt" - "strings" - - "github.com/go-openapi/spec" + "reflect" + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apimachinery/pkg/api/meta" metatable "k8s.io/apimachinery/pkg/api/meta/table" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/client-go/util/jsonpath" ) -const printColumnsKey = "x-kubernetes-print-columns" - var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() -// New creates a new table convertor for the provided OpenAPI schema. If the printer definition cannot be parsed, +// New creates a new table convertor for the provided CRD column definition. If the printer definition cannot be parsed, // error will be returned along with a default table convertor. -func New(extensions spec.Extensions) (rest.TableConvertor, error) { +func New(crdColumns []apiextensions.CustomResourceColumnDefinition) (rest.TableConvertor, error) { headers := []metav1beta1.TableColumnDefinition{ {Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]}, - {Name: "Created At", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"]}, } c := &convertor{ headers: headers, } - format, ok := extensions.GetString(printColumnsKey) - if !ok { - return c, nil - } - // "x-kubernetes-print-columns": "custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion" - parts := strings.SplitN(format, "=", 2) - if len(parts) != 2 || parts[0] != "custom-columns" { - return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns', only support 'custom-columns=NAME=JSONPATH[,NAME=JSONPATH]'") - } - columnSpecs := strings.Split(parts[1], ",") - var columns []*jsonpath.JSONPath - for _, spec := range columnSpecs { - parts := strings.SplitN(spec, ":", 2) - if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 { - return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns', must specify NAME=JSONPATH: %s", spec) - } - path := jsonpath.New(parts[0]) - if err := path.Parse(parts[1]); err != nil { - return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns': %v", spec) + + for _, col := range crdColumns { + path := jsonpath.New(col.Name) + if err := path.Parse(fmt.Sprintf("{%s}", col.JSONPath)); err != nil { + return c, fmt.Errorf("unrecognized column definition %q", col.JSONPath) } path.AllowMissingKeys(true) - columns = append(columns, path) - headers = append(headers, metav1beta1.TableColumnDefinition{ - Name: parts[0], - Type: "string", - Description: fmt.Sprintf("Custom resource definition column from OpenAPI (in JSONPath format): %s", parts[1]), + + desc := fmt.Sprintf("Custom resource definition column (in JSONPath format): %s", col.JSONPath) + if len(col.Description) > 0 { + desc = col.Description + } + + c.additionalColumns = append(c.additionalColumns, path) + c.headers = append(c.headers, metav1beta1.TableColumnDefinition{ + Name: col.Name, + Type: col.Type, + Format: col.Format, + Description: desc, + Priority: col.Priority, }) } - c.columns = columns - c.headers = headers + return c, nil } type convertor struct { - headers []metav1beta1.TableColumnDefinition - columns []*jsonpath.JSONPath + headers []metav1beta1.TableColumnDefinition + additionalColumns []*jsonpath.JSONPath } -func (c *convertor) ConvertToTable(ctx genericapirequest.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { +func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { table := &metav1beta1.Table{ ColumnDefinitions: c.headers, } @@ -103,18 +93,80 @@ func (c *convertor) ConvertToTable(ctx genericapirequest.Context, obj runtime.Ob var err error buf := &bytes.Buffer{} table.Rows, err = metatable.MetaToTableRow(obj, func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) { - cells := make([]interface{}, 2, 2+len(c.columns)) + cells := make([]interface{}, 1, 1+len(c.additionalColumns)) cells[0] = name - cells[1] = age - for _, column := range c.columns { - if err := column.Execute(buf, obj); err != nil { + customHeaders := c.headers[1:] + for i, column := range c.additionalColumns { + results, err := column.FindResults(obj.(runtime.Unstructured).UnstructuredContent()) + if err != nil || len(results) == 0 || len(results[0]) == 0 { cells = append(cells, nil) continue } - cells = append(cells, buf.String()) - buf.Reset() + + // as we only support simple JSON path, we can assume to have only one result (or none, filtered out above) + value := results[0][0].Interface() + if customHeaders[i].Type == "string" { + if err := column.PrintResults(buf, []reflect.Value{reflect.ValueOf(value)}); err == nil { + cells = append(cells, buf.String()) + buf.Reset() + } else { + cells = append(cells, nil) + } + } else { + cells = append(cells, cellForJSONValue(customHeaders[i].Type, value)) + } } return cells, nil }) return table, err } + +func cellForJSONValue(headerType string, value interface{}) interface{} { + if value == nil { + return nil + } + + switch headerType { + case "integer": + switch typed := value.(type) { + case int64: + return typed + case float64: + return int64(typed) + case json.Number: + if i64, err := typed.Int64(); err == nil { + return i64 + } + } + case "number": + switch typed := value.(type) { + case int64: + return float64(typed) + case float64: + return typed + case json.Number: + if f, err := typed.Float64(); err == nil { + return f + } + } + case "boolean": + if b, ok := value.(bool); ok { + return b + } + case "string": + if s, ok := value.(string); ok { + return s + } + case "date": + if typed, ok := value.(string); ok { + var timestamp metav1.Time + err := timestamp.UnmarshalQueryParameter(typed) + if err != nil { + return "" + } + return metatable.ConvertToHumanReadableDateType(timestamp) + } + } + + return nil +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go new file mode 100644 index 000000000..179aabb8a --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2018 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 tableconvertor + +import ( + "fmt" + "reflect" + "testing" + "time" +) + +func Test_cellForJSONValue(t *testing.T) { + tests := []struct { + headerType string + value interface{} + want interface{} + }{ + {"integer", int64(42), int64(42)}, + {"integer", float64(3.14), int64(3)}, + {"integer", true, nil}, + {"integer", "foo", nil}, + + {"number", int64(42), float64(42)}, + {"number", float64(3.14), float64(3.14)}, + {"number", true, nil}, + {"number", "foo", nil}, + + {"boolean", int64(42), nil}, + {"boolean", float64(3.14), nil}, + {"boolean", true, true}, + {"boolean", "foo", nil}, + + {"string", int64(42), nil}, + {"string", float64(3.14), nil}, + {"string", true, nil}, + {"string", "foo", "foo"}, + + {"date", int64(42), nil}, + {"date", float64(3.14), nil}, + {"date", true, nil}, + {"date", time.Now().Add(-time.Hour*12 - 30*time.Minute).UTC().Format(time.RFC3339), "12h"}, + {"date", time.Now().Add(+time.Hour*12 + 30*time.Minute).UTC().Format(time.RFC3339), ""}, + {"date", "", ""}, + + {"unknown", "foo", nil}, + } + for _, tt := range tests { + t.Run(fmt.Sprintf("%#v of type %s", tt.value, tt.headerType), func(t *testing.T) { + if got := cellForJSONValue(tt.headerType, tt.value); !reflect.DeepEqual(got, tt.want) { + t.Errorf("cellForJSONValue() = %#v, want %#v", got, tt.want) + } + }) + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go index ef5023dc6..5206a17eb 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go @@ -17,6 +17,7 @@ limitations under the License. package customresource import ( + "context" "fmt" "math" "strings" @@ -29,7 +30,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" apiservervalidation "k8s.io/apiextensions-apiserver/pkg/apiserver/validation" @@ -42,74 +42,37 @@ type customResourceValidator struct { statusSchemaValidator *validate.SchemaValidator } -func (a customResourceValidator) Validate(ctx genericapirequest.Context, obj runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { +func (a customResourceValidator) Validate(ctx context.Context, obj runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} + } accessor, err := meta.Accessor(obj) if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} } - typeAccessor, err := meta.TypeAccessor(obj) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath("kind"), nil, err.Error())} - } - if typeAccessor.GetKind() != a.kind.Kind { - return field.ErrorList{field.Invalid(field.NewPath("kind"), typeAccessor.GetKind(), fmt.Sprintf("must be %v", a.kind.Kind))} - } - if typeAccessor.GetAPIVersion() != a.kind.Group+"/"+a.kind.Version { - return field.ErrorList{field.Invalid(field.NewPath("apiVersion"), typeAccessor.GetAPIVersion(), fmt.Sprintf("must be %v", a.kind.Group+"/"+a.kind.Version))} - } - customResourceObject, ok := obj.(*unstructured.Unstructured) - // this will never happen. - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), customResourceObject, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", customResourceObject))} + if errs := a.ValidateTypeMeta(ctx, u); len(errs) > 0 { + return errs } - customResource := customResourceObject.UnstructuredContent() - if err = apiservervalidation.ValidateCustomResource(customResource, a.schemaValidator); err != nil { - return field.ErrorList{field.Invalid(field.NewPath(""), customResource, err.Error())} - } + var allErrs field.ErrorList - if scale != nil { - // validate specReplicas - specReplicasPath := strings.TrimPrefix(scale.SpecReplicasPath, ".") // ignore leading period - specReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(specReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, err.Error())} - } - if specReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, "should be a non-negative integer")} - } - if specReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } - - // validate statusReplicas - statusReplicasPath := strings.TrimPrefix(scale.StatusReplicasPath, ".") // ignore leading period - statusReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(statusReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, err.Error())} - } - if statusReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, "should be a non-negative integer")} - } - if statusReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } - - // validate labelSelector - if scale.LabelSelectorPath != nil { - labelSelectorPath := strings.TrimPrefix(*scale.LabelSelectorPath, ".") // ignore leading period - labelSelector, _, err := unstructured.NestedString(customResource, strings.Split(labelSelectorPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(*scale.LabelSelectorPath), labelSelector, err.Error())} - } - } + allErrs = append(allErrs, validation.ValidateObjectMetaAccessor(accessor, a.namespaceScoped, validation.NameIsDNSSubdomain, field.NewPath("metadata"))...) + if err = apiservervalidation.ValidateCustomResource(u.UnstructuredContent(), a.schemaValidator); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(""), u.UnstructuredContent(), err.Error())) } + allErrs = append(allErrs, a.ValidateScaleSpec(ctx, u, scale)...) + allErrs = append(allErrs, a.ValidateScaleStatus(ctx, u, scale)...) - return validation.ValidateObjectMetaAccessor(accessor, a.namespaceScoped, validation.NameIsDNSSubdomain, field.NewPath("metadata")) + return allErrs } -func (a customResourceValidator) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { +func (a customResourceValidator) ValidateUpdate(ctx context.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} + } objAccessor, err := meta.Accessor(obj) if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} @@ -118,69 +81,28 @@ func (a customResourceValidator) ValidateUpdate(ctx genericapirequest.Context, o if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} } - typeAccessor, err := meta.TypeAccessor(obj) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath("kind"), nil, err.Error())} - } - if typeAccessor.GetKind() != a.kind.Kind { - return field.ErrorList{field.Invalid(field.NewPath("kind"), typeAccessor.GetKind(), fmt.Sprintf("must be %v", a.kind.Kind))} - } - if typeAccessor.GetAPIVersion() != a.kind.Group+"/"+a.kind.Version { - return field.ErrorList{field.Invalid(field.NewPath("apiVersion"), typeAccessor.GetAPIVersion(), fmt.Sprintf("must be %v", a.kind.Group+"/"+a.kind.Version))} - } - customResourceObject, ok := obj.(*unstructured.Unstructured) - // this will never happen. - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), customResourceObject, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", customResourceObject))} + if errs := a.ValidateTypeMeta(ctx, u); len(errs) > 0 { + return errs } - customResource := customResourceObject.UnstructuredContent() - if err = apiservervalidation.ValidateCustomResource(customResource, a.schemaValidator); err != nil { - return field.ErrorList{field.Invalid(field.NewPath(""), customResource, err.Error())} - } + var allErrs field.ErrorList - if scale != nil { - // validate specReplicas - specReplicasPath := strings.TrimPrefix(scale.SpecReplicasPath, ".") // ignore leading period - specReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(specReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, err.Error())} - } - if specReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, "should be a non-negative integer")} - } - if specReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } - - // validate statusReplicas - statusReplicasPath := strings.TrimPrefix(scale.StatusReplicasPath, ".") // ignore leading period - statusReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(statusReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, err.Error())} - } - if statusReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, "should be a non-negative integer")} - } - if statusReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } - - // validate labelSelector - if scale.LabelSelectorPath != nil { - labelSelectorPath := strings.TrimPrefix(*scale.LabelSelectorPath, ".") // ignore leading period - labelSelector, _, err := unstructured.NestedString(customResource, strings.Split(labelSelectorPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(*scale.LabelSelectorPath), labelSelector, err.Error())} - } - } + allErrs = append(allErrs, validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata"))...) + if err = apiservervalidation.ValidateCustomResource(u.UnstructuredContent(), a.schemaValidator); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(""), u.UnstructuredContent(), err.Error())) } + allErrs = append(allErrs, a.ValidateScaleSpec(ctx, u, scale)...) + allErrs = append(allErrs, a.ValidateScaleStatus(ctx, u, scale)...) - return validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata")) + return allErrs } -func (a customResourceValidator) ValidateStatusUpdate(ctx genericapirequest.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { +func (a customResourceValidator) ValidateStatusUpdate(ctx context.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} + } objAccessor, err := meta.Accessor(obj) if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} @@ -189,53 +111,85 @@ func (a customResourceValidator) ValidateStatusUpdate(ctx genericapirequest.Cont if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} } + + if errs := a.ValidateTypeMeta(ctx, u); len(errs) > 0 { + return errs + } + + var allErrs field.ErrorList + + allErrs = append(allErrs, validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata"))...) + if err = apiservervalidation.ValidateCustomResource(u.UnstructuredContent(), a.schemaValidator); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(""), u.UnstructuredContent(), err.Error())) + } + allErrs = append(allErrs, a.ValidateScaleStatus(ctx, u, scale)...) + + return allErrs +} + +func (a customResourceValidator) ValidateTypeMeta(ctx context.Context, obj *unstructured.Unstructured) field.ErrorList { typeAccessor, err := meta.TypeAccessor(obj) if err != nil { return field.ErrorList{field.Invalid(field.NewPath("kind"), nil, err.Error())} } + + var allErrs field.ErrorList if typeAccessor.GetKind() != a.kind.Kind { - return field.ErrorList{field.Invalid(field.NewPath("kind"), typeAccessor.GetKind(), fmt.Sprintf("must be %v", a.kind.Kind))} + allErrs = append(allErrs, field.Invalid(field.NewPath("kind"), typeAccessor.GetKind(), fmt.Sprintf("must be %v", a.kind.Kind))) } if typeAccessor.GetAPIVersion() != a.kind.Group+"/"+a.kind.Version { - return field.ErrorList{field.Invalid(field.NewPath("apiVersion"), typeAccessor.GetAPIVersion(), fmt.Sprintf("must be %v", a.kind.Group+"/"+a.kind.Version))} + allErrs = append(allErrs, field.Invalid(field.NewPath("apiVersion"), typeAccessor.GetAPIVersion(), fmt.Sprintf("must be %v", a.kind.Group+"/"+a.kind.Version))) } + return allErrs +} - customResourceObject, ok := obj.(*unstructured.Unstructured) - // this will never happen. - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), customResourceObject, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", customResourceObject))} +func (a customResourceValidator) ValidateScaleSpec(ctx context.Context, obj *unstructured.Unstructured, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + if scale == nil { + return nil } - customResource := customResourceObject.UnstructuredContent() - // validate only the status - customResourceStatus := customResource["status"] - if err = apiservervalidation.ValidateCustomResource(customResourceStatus, a.statusSchemaValidator); err != nil { - return field.ErrorList{field.Invalid(field.NewPath("status"), customResourceStatus, err.Error())} + var allErrs field.ErrorList + + // validate specReplicas + specReplicasPath := strings.TrimPrefix(scale.SpecReplicasPath, ".") // ignore leading period + specReplicas, _, err := unstructured.NestedInt64(obj.UnstructuredContent(), strings.Split(specReplicasPath, ".")...) + if err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, err.Error())) + } else if specReplicas < 0 { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, "should be a non-negative integer")) + } else if specReplicas > math.MaxInt32 { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))) } - if scale != nil { - // validate statusReplicas - statusReplicasPath := strings.TrimPrefix(scale.StatusReplicasPath, ".") // ignore leading period - statusReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(statusReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, err.Error())} - } - if statusReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, "should be a non-negative integer")} - } - if statusReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } + return allErrs +} + +func (a customResourceValidator) ValidateScaleStatus(ctx context.Context, obj *unstructured.Unstructured, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + if scale == nil { + return nil + } + + var allErrs field.ErrorList - // validate labelSelector - if scale.LabelSelectorPath != nil { - labelSelectorPath := strings.TrimPrefix(*scale.LabelSelectorPath, ".") // ignore leading period - labelSelector, _, err := unstructured.NestedString(customResource, strings.Split(labelSelectorPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(*scale.LabelSelectorPath), labelSelector, err.Error())} - } + // validate statusReplicas + statusReplicasPath := strings.TrimPrefix(scale.StatusReplicasPath, ".") // ignore leading period + statusReplicas, _, err := unstructured.NestedInt64(obj.UnstructuredContent(), strings.Split(statusReplicasPath, ".")...) + if err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, err.Error())) + } else if statusReplicas < 0 { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, "should be a non-negative integer")) + } else if statusReplicas > math.MaxInt32 { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))) + } + + // validate labelSelector + if scale.LabelSelectorPath != nil { + labelSelectorPath := strings.TrimPrefix(*scale.LabelSelectorPath, ".") // ignore leading period + labelSelector, _, err := unstructured.NestedString(obj.UnstructuredContent(), strings.Split(labelSelectorPath, ".")...) + if err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(*scale.LabelSelectorPath), labelSelector, err.Error())) } } - return validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata")) + return allErrs } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go index c501c6a08..8d272ad77 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go @@ -17,13 +17,13 @@ limitations under the License. package customresourcedefinition import ( + "context" "fmt" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -66,7 +66,7 @@ func (r *REST) ShortNames() []string { } // Delete adds the CRD finalizer to the list -func (r *REST) Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { +func (r *REST) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { obj, err := r.Get(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, err @@ -160,13 +160,18 @@ type StatusREST struct { store *genericregistry.Store } -var _ = rest.Updater(&StatusREST{}) +var _ = rest.Patcher(&StatusREST{}) func (r *StatusREST) New() runtime.Object { return &apiextensions.CustomResourceDefinition{} } +// Get retrieves the object from the storage. It is required to support Patch. +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + return r.store.Get(ctx, name, options) +} + // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go index 7e44fa4c2..a0bebb7a7 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go @@ -17,6 +17,7 @@ limitations under the License. package customresourcedefinition import ( + "context" "fmt" apiequality "k8s.io/apimachinery/pkg/api/equality" @@ -24,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" @@ -50,7 +50,7 @@ func (strategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a CustomResourceDefinition before creation. -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { crd := obj.(*apiextensions.CustomResourceDefinition) crd.Status = apiextensions.CustomResourceDefinitionStatus{} crd.Generation = 1 @@ -62,10 +62,19 @@ func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Obje if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) { crd.Spec.Subresources = nil } + + for _, v := range crd.Spec.Versions { + if v.Storage { + if !apiextensions.IsStoredVersion(crd, v.Name) { + crd.Status.StoredVersions = append(crd.Status.StoredVersions, v.Name) + } + break + } + } } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newCRD := obj.(*apiextensions.CustomResourceDefinition) oldCRD := old.(*apiextensions.CustomResourceDefinition) newCRD.Status = oldCRD.Status @@ -90,10 +99,19 @@ func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime newCRD.Spec.Subresources = nil oldCRD.Spec.Subresources = nil } + + for _, v := range newCRD.Spec.Versions { + if v.Storage { + if !apiextensions.IsStoredVersion(newCRD, v.Name) { + newCRD.Status.StoredVersions = append(newCRD.Status.StoredVersions, v.Name) + } + break + } + } } // Validate validates a new CustomResourceDefinition. -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return validation.ValidateCustomResourceDefinition(obj.(*apiextensions.CustomResourceDefinition)) } @@ -113,7 +131,7 @@ func (strategy) Canonicalize(obj runtime.Object) { } // ValidateUpdate is the default update validation for an end user updating status. -func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateCustomResourceDefinitionUpdate(obj.(*apiextensions.CustomResourceDefinition), old.(*apiextensions.CustomResourceDefinition)) } @@ -130,7 +148,7 @@ func (statusStrategy) NamespaceScoped() bool { return false } -func (statusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (statusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newObj := obj.(*apiextensions.CustomResourceDefinition) oldObj := old.(*apiextensions.CustomResourceDefinition) newObj.Spec = oldObj.Spec @@ -155,7 +173,7 @@ func (statusStrategy) AllowUnconditionalUpdate() bool { func (statusStrategy) Canonicalize(obj runtime.Object) { } -func (statusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateUpdateCustomResourceDefinitionStatus(obj.(*apiextensions.CustomResourceDefinition), old.(*apiextensions.CustomResourceDefinition)) } diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/basic_test.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/basic_test.go index e373a178a..888675438 100644 --- a/vendor/k8s.io/apiextensions-apiserver/test/integration/basic_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/basic_test.go @@ -17,8 +17,10 @@ limitations under the License. package integration import ( + "fmt" "reflect" "sort" + "strings" "testing" "time" @@ -43,177 +45,217 @@ func TestServerUp(t *testing.T) { } func TestNamespaceScopedCRUD(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - testSimpleCRUD(t, ns, noxuDefinition, noxuVersionClient) - testFieldSelector(t, ns, noxuDefinition, noxuVersionClient) + + testSimpleCRUD(t, ns, noxuDefinition, dynamicClient) + testFieldSelector(t, ns, noxuDefinition, dynamicClient) } func TestClusterScopedCRUD(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "" - testSimpleCRUD(t, ns, noxuDefinition, noxuVersionClient) - testFieldSelector(t, ns, noxuDefinition, noxuVersionClient) + testSimpleCRUD(t, ns, noxuDefinition, dynamicClient) + testFieldSelector(t, ns, noxuDefinition, dynamicClient) } -func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, noxuVersionClient dynamic.Interface) { - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - initialList, err := noxuResourceClient.List(metav1.ListOptions{}) - if err != nil { - t.Fatal(err) - } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { - t.Errorf("expected %v, got %v", e, a) - } - initialListTypeMeta, err := meta.TypeAccessor(initialList) - if err != nil { - t.Fatal(err) - } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, initialListTypeMeta.GetAPIVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := noxuDefinition.Spec.Names.ListKind, initialListTypeMeta.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - initialListListMeta, err := meta.ListAccessor(initialList) - if err != nil { - t.Fatal(err) +func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) { + noxuResourceClients := map[string]dynamic.ResourceInterface{} + noxuWatchs := map[string]watch.Interface{} + disabledVersions := map[string]bool{} + for _, v := range noxuDefinition.Spec.Versions { + disabledVersions[v.Name] = !v.Served } - noxuWatch, err := noxuResourceClient.Watch(metav1.ListOptions{ResourceVersion: initialListListMeta.GetResourceVersion()}) - if err != nil { - t.Fatal(err) - } - defer noxuWatch.Stop() + for _, v := range noxuDefinition.Spec.Versions { + noxuResourceClients[v.Name] = newNamespacedCustomResourceVersionedClient(ns, dynamicClient, noxuDefinition, v.Name) - createdNoxuInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, "foo"), noxuResourceClient, noxuDefinition) - if err != nil { - t.Fatalf("unable to create noxu Instance:%v", err) - } - - select { - case watchEvent := <-noxuWatch.ResultChan(): - if e, a := watch.Added, watchEvent.Type; e != a { - t.Errorf("expected %v, got %v", e, a) - break - } - createdObjectMeta, err := meta.Accessor(watchEvent.Object) - if err != nil { - t.Fatal(err) + noxuWatch, err := noxuResourceClients[v.Name].Watch(metav1.ListOptions{}) + if disabledVersions[v.Name] { + if err == nil { + t.Errorf("expected the watch creation fail for disabled version %s", v.Name) + } + } else { + if err != nil { + t.Fatal(err) + } + noxuWatchs[v.Name] = noxuWatch } - // it should have a UUID - if len(createdObjectMeta.GetUID()) == 0 { - t.Errorf("missing uuid: %#v", watchEvent.Object) + } + defer func() { + for _, w := range noxuWatchs { + w.Stop() } - if e, a := ns, createdObjectMeta.GetNamespace(); e != a { - t.Errorf("expected %v, got %v", e, a) + }() + + for version, noxuResourceClient := range noxuResourceClients { + createdNoxuInstance, err := instantiateVersionedCustomResource(t, testserver.NewVersionedNoxuInstance(ns, "foo", version), noxuResourceClient, noxuDefinition, version) + if disabledVersions[version] { + if err == nil { + t.Errorf("expected the CR creation fail for disabled version %s", version) + } + continue } - createdTypeMeta, err := meta.TypeAccessor(watchEvent.Object) if err != nil { - t.Fatal(err) + t.Fatalf("unable to create noxu Instance:%v", err) } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a { + if e, a := noxuDefinition.Spec.Group+"/"+version, createdNoxuInstance.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) + for watchVersion, noxuWatch := range noxuWatchs { + select { + case watchEvent := <-noxuWatch.ResultChan(): + if e, a := watch.Added, watchEvent.Type; e != a { + t.Errorf("expected %v, got %v", e, a) + break + } + createdObjectMeta, err := meta.Accessor(watchEvent.Object) + if err != nil { + t.Fatal(err) + } + // it should have a UUID + if len(createdObjectMeta.GetUID()) == 0 { + t.Errorf("missing uuid: %#v", watchEvent.Object) + } + if e, a := ns, createdObjectMeta.GetNamespace(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + createdTypeMeta, err := meta.TypeAccessor(watchEvent.Object) + if err != nil { + t.Fatal(err) + } + if e, a := noxuDefinition.Spec.Group+"/"+watchVersion, createdTypeMeta.GetAPIVersion(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + case <-time.After(5 * time.Second): + t.Errorf("missing watch event") + } } - case <-time.After(5 * time.Second): - t.Errorf("missing watch event") - } + // Check get for all versions + for version2, noxuResourceClient2 := range noxuResourceClients { + // Get test + gottenNoxuInstance, err := noxuResourceClient2.Get("foo", metav1.GetOptions{}) - gottenNoxuInstance, err := noxuResourceClient.Get("foo", metav1.GetOptions{}) - if err != nil { - t.Fatal(err) - } - if e, a := createdNoxuInstance, gottenNoxuInstance; !reflect.DeepEqual(e, a) { - t.Errorf("expected %v, got %v", e, a) - } + if disabledVersions[version2] { + if err == nil { + t.Errorf("expected the get operation fail for disabled version %s", version2) + } + } else { + if err != nil { + t.Fatal(err) + } - listWithItem, err := noxuResourceClient.List(metav1.ListOptions{}) - if err != nil { - t.Fatal(err) - } - if e, a := 1, len(listWithItem.(*unstructured.UnstructuredList).Items); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := *createdNoxuInstance, listWithItem.(*unstructured.UnstructuredList).Items[0]; !reflect.DeepEqual(e, a) { - t.Errorf("expected %v, got %v", e, a) - } - - if err := noxuResourceClient.Delete("foo", nil); err != nil { - t.Fatal(err) - } - - listWithoutItem, err := noxuResourceClient.List(metav1.ListOptions{}) - if err != nil { - t.Fatal(err) - } - if e, a := 0, len(listWithoutItem.(*unstructured.UnstructuredList).Items); e != a { - t.Errorf("expected %v, got %v", e, a) - } + if e, a := version2, gottenNoxuInstance.GroupVersionKind().Version; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + } - select { - case watchEvent := <-noxuWatch.ResultChan(): - if e, a := watch.Deleted, watchEvent.Type; e != a { - t.Errorf("expected %v, got %v", e, a) - break + // List test + listWithItem, err := noxuResourceClient2.List(metav1.ListOptions{}) + if disabledVersions[version2] { + if err == nil { + t.Errorf("expected the list operation fail for disabled version %s", version2) + } + } else { + if err != nil { + t.Fatal(err) + } + if e, a := 1, len(listWithItem.Items); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := version2, listWithItem.GroupVersionKind().Version; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := version2, listWithItem.Items[0].GroupVersionKind().Version; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + } } - deletedObjectMeta, err := meta.Accessor(watchEvent.Object) - if err != nil { + + // Delete test + if err := noxuResourceClient.Delete("foo", metav1.NewDeleteOptions(0)); err != nil { t.Fatal(err) } - // it should have a UUID - createdObjectMeta, err := meta.Accessor(createdNoxuInstance) + + listWithoutItem, err := noxuResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) } - if e, a := createdObjectMeta.GetUID(), deletedObjectMeta.GetUID(); e != a { + if e, a := 0, len(listWithoutItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } - case <-time.After(5 * time.Second): - t.Errorf("missing watch event") + for _, noxuWatch := range noxuWatchs { + select { + case watchEvent := <-noxuWatch.ResultChan(): + if e, a := watch.Deleted, watchEvent.Type; e != a { + t.Errorf("expected %v, got %v", e, a) + break + } + deletedObjectMeta, err := meta.Accessor(watchEvent.Object) + if err != nil { + t.Fatal(err) + } + // it should have a UUID + createdObjectMeta, err := meta.Accessor(createdNoxuInstance) + if err != nil { + t.Fatal(err) + } + if e, a := createdObjectMeta.GetUID(), deletedObjectMeta.GetUID(); e != a { + t.Errorf("expected equal UID for (expected) %v, and (actual) %v", createdNoxuInstance, watchEvent.Object) + } + + case <-time.After(5 * time.Second): + t.Errorf("missing watch event") + } + } + + // Delete test + if err := noxuResourceClient.DeleteCollection(metav1.NewDeleteOptions(0), metav1.ListOptions{}); err != nil { + t.Fatal(err) + } } } -func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, noxuVersionClient dynamic.Interface) { - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) +func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) { + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) initialList, err := noxuResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(initialList.Items); e != a { t.Errorf("expected %v, got %v", e, a) } initialListTypeMeta, err := meta.TypeAccessor(initialList) if err != nil { t.Fatal(err) } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, initialListTypeMeta.GetAPIVersion(); e != a { + if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Versions[0].Name, initialListTypeMeta.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := noxuDefinition.Spec.Names.ListKind, initialListTypeMeta.GetKind(); e != a { @@ -268,7 +310,7 @@ func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1b if err != nil { t.Fatal(err) } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a { + if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Versions[0].Name, createdTypeMeta.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { @@ -291,10 +333,10 @@ func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1b if err != nil { t.Fatal(err) } - if e, a := 1, len(listWithItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 1, len(listWithItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := *createdNoxuInstanceFoo, listWithItem.(*unstructured.UnstructuredList).Items[0]; !reflect.DeepEqual(e, a) { + if e, a := *createdNoxuInstanceFoo, listWithItem.Items[0]; !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } @@ -309,7 +351,7 @@ func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1b if err != nil { t.Fatal(err) } - if e, a := 0, len(listWithoutItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(listWithoutItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -347,7 +389,7 @@ func TestDiscovery(t *testing.T) { group := "mygroup.example.com" version := "v1beta1" - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -355,7 +397,7 @@ func TestDiscovery(t *testing.T) { scope := apiextensionsv1beta1.NamespaceScoped noxuDefinition := testserver.NewNoxuCustomResourceDefinition(scope) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -395,25 +437,25 @@ func TestDiscovery(t *testing.T) { } func TestNoNamespaceReject(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) initialList, err := noxuResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(initialList.Items); e != a { t.Errorf("expected %v, got %v", e, a) } initialListTypeMeta, err := meta.TypeAccessor(initialList) @@ -434,27 +476,27 @@ func TestNoNamespaceReject(t *testing.T) { } func TestSameNameDiffNamespace(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns1 := "namespace-1" - testSimpleCRUD(t, ns1, noxuDefinition, noxuVersionClient) + testSimpleCRUD(t, ns1, noxuDefinition, dynamicClient) ns2 := "namespace-2" - testSimpleCRUD(t, ns2, noxuDefinition, noxuVersionClient) + testSimpleCRUD(t, ns2, noxuDefinition, dynamicClient) } func TestSelfLink(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -462,16 +504,13 @@ func TestSelfLink(t *testing.T) { // namespace scoped noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuNamespacedResourceClient := noxuVersionClient.Resource(&metav1.APIResource{ - Name: noxuDefinition.Spec.Names.Plural, - Namespaced: noxuDefinition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuInstanceToCreate := testserver.NewNoxuInstance(ns, "foo") createdNoxuInstance, err := noxuNamespacedResourceClient.Create(noxuInstanceToCreate) @@ -485,15 +524,12 @@ func TestSelfLink(t *testing.T) { // cluster scoped curletDefinition := testserver.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - curletVersionClient, err := testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, clientPool) + curletDefinition, err = testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - curletResourceClient := curletVersionClient.Resource(&metav1.APIResource{ - Name: curletDefinition.Spec.Names.Plural, - Namespaced: curletDefinition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) + curletResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, curletDefinition) curletInstanceToCreate := testserver.NewCurletInstance(ns, "foo") createdCurletInstance, err := curletResourceClient.Create(curletInstanceToCreate) @@ -507,23 +543,20 @@ func TestSelfLink(t *testing.T) { } func TestPreserveInt(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuNamespacedResourceClient := noxuVersionClient.Resource(&metav1.APIResource{ - Name: noxuDefinition.Spec.Names.Plural, - Namespaced: true, - }, ns) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuInstanceToCreate := testserver.NewNoxuInstance(ns, "foo") createdNoxuInstance, err := noxuNamespacedResourceClient.Create(noxuInstanceToCreate) @@ -552,60 +585,64 @@ func TestPreserveInt(t *testing.T) { } func TestPatch(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuNamespacedResourceClient := noxuVersionClient.Resource(&metav1.APIResource{ - Name: noxuDefinition.Spec.Names.Plural, - Namespaced: true, - }, ns) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) + t.Logf("Creating foo") noxuInstanceToCreate := testserver.NewNoxuInstance(ns, "foo") - createdNoxuInstance, err := noxuNamespacedResourceClient.Create(noxuInstanceToCreate) + _, err = noxuNamespacedResourceClient.Create(noxuInstanceToCreate) if err != nil { t.Fatal(err) } + t.Logf("Patching .num.num2 to 999") patch := []byte(`{"num": {"num2":999}}`) - createdNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, patch) + patchedNoxuInstance, err := noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, patch) if err != nil { t.Fatalf("unexpected error: %v", err) } - - // this call waits for the resourceVersion to be reached in the cache before returning. - // We need to do this because the patch gets its initial object from the storage, and the cache serves that. - // If it is out of date, then our initial patch is applied to an old resource version, which conflicts - // and then the updated object shows a conflicting diff, which permanently fails the patch. - // This gives expected stability in the patch without retrying on an known number of conflicts below in the test. - // See https://issue.k8s.io/42644 - _, err = noxuNamespacedResourceClient.Get("foo", metav1.GetOptions{ResourceVersion: createdNoxuInstance.GetResourceVersion()}) + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "num", "num2") + rv, found, err := unstructured.NestedString(patchedNoxuInstance.UnstructuredContent(), "metadata", "resourceVersion") if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatal(err) + } + if !found { + t.Fatalf("metadata.resourceVersion not found") } // a patch with no change - createdNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, patch) + t.Logf("Patching .num.num2 again to 999") + patchedNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, patch) if err != nil { t.Fatalf("unexpected error: %v", err) } + // make sure no-op patch does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "num", "num2") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") // an empty patch - createdNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) + t.Logf("Applying empty patch") + patchedNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) if err != nil { t.Fatalf("unexpected error: %v", err) } + // an empty patch is a no-op patch. make sure it does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "num", "num2") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") - originalJSON, err := runtime.Encode(unstructured.UnstructuredJSONScheme, createdNoxuInstance) + originalJSON, err := runtime.Encode(unstructured.UnstructuredJSONScheme, patchedNoxuInstance) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -626,25 +663,25 @@ func TestPatch(t *testing.T) { } func TestCrossNamespaceListWatch(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) initialList, err := noxuResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(initialList.Items); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -661,13 +698,13 @@ func TestCrossNamespaceListWatch(t *testing.T) { instances := make(map[string]*unstructured.Unstructured) ns1 := "namespace-1" - noxuNamespacedResourceClient1 := NewNamespacedCustomResourceClient(ns1, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient1 := newNamespacedCustomResourceClient(ns1, dynamicClient, noxuDefinition) instances[ns1] = createInstanceWithNamespaceHelper(t, ns1, "foo1", noxuNamespacedResourceClient1, noxuDefinition) noxuNamespacesWatch1, err := noxuNamespacedResourceClient1.Watch(metav1.ListOptions{ResourceVersion: initialListListMeta.GetResourceVersion()}) defer noxuNamespacesWatch1.Stop() ns2 := "namespace-2" - noxuNamespacedResourceClient2 := NewNamespacedCustomResourceClient(ns2, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient2 := newNamespacedCustomResourceClient(ns2, dynamicClient, noxuDefinition) instances[ns2] = createInstanceWithNamespaceHelper(t, ns2, "foo2", noxuNamespacedResourceClient2, noxuDefinition) noxuNamespacesWatch2, err := noxuNamespacedResourceClient2.Watch(metav1.ListOptions{ResourceVersion: initialListListMeta.GetResourceVersion()}) defer noxuNamespacesWatch2.Stop() @@ -677,11 +714,11 @@ func TestCrossNamespaceListWatch(t *testing.T) { t.Fatal(err) } - if e, a := 2, len(createdList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 2, len(createdList.Items); e != a { t.Errorf("expected %v, got %v", e, a) } - for _, a := range createdList.(*unstructured.UnstructuredList).Items { + for _, a := range createdList.Items { if e := instances[a.GetNamespace()]; !reflect.DeepEqual(e, &a) { t.Errorf("expected %v, got %v", e, a) } @@ -762,27 +799,27 @@ func checkNamespacesWatchHelper(t *testing.T, ns string, namespacedwatch watch.I } func TestNameConflict(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } noxu2Definition := testserver.NewNoxu2CustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - _, err = apiExtensionClient.Apiextensions().CustomResourceDefinitions().Create(noxu2Definition) + _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(noxu2Definition) if err != nil { t.Fatal(err) } // A NameConflict occurs err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - crd, err := testserver.GetCustomResourceDefinition(noxu2Definition, apiExtensionClient) + crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxu2Definition.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -805,7 +842,7 @@ func TestNameConflict(t *testing.T) { // Names are now accepted err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - crd, err := testserver.GetCustomResourceDefinition(noxu2Definition, apiExtensionClient) + crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxu2Definition.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -821,3 +858,57 @@ func TestNameConflict(t *testing.T) { t.Fatal(err) } } + +func TestStatusGetAndPatch(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + // make sure we don't get 405 Method Not Allowed from Getting CRD/status subresource + result := &apiextensionsv1beta1.CustomResourceDefinition{} + err = apiExtensionClient.ApiextensionsV1beta1().RESTClient().Get(). + Resource("customresourcedefinitions"). + Name(noxuDefinition.Name). + SubResource("status"). + Do(). + Into(result) + if err != nil { + t.Fatal(err) + } + + // make sure we don't get 405 Method Not Allowed from Patching CRD/status subresource + _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions(). + Patch(noxuDefinition.Name, types.StrategicMergePatchType, + []byte(fmt.Sprintf(`{"labels":{"test-label":"dummy"}}`)), + "status") + if err != nil { + t.Fatal(err) + } +} + +func expectInt64(t *testing.T, obj map[string]interface{}, value int64, pth ...string) { + if v, found, err := unstructured.NestedInt64(obj, pth...); err != nil { + t.Fatalf("failed to access .%s: %v", strings.Join(pth, "."), err) + } else if !found { + t.Fatalf("failed to find .%s", strings.Join(pth, ".")) + } else if v != value { + t.Fatalf("wanted %d at .%s, got %d", value, strings.Join(pth, "."), v) + } +} +func expectString(t *testing.T, obj map[string]interface{}, value string, pth ...string) { + if v, found, err := unstructured.NestedString(obj, pth...); err != nil { + t.Fatalf("failed to access .%s: %v", strings.Join(pth, "."), err) + } else if !found { + t.Fatalf("failed to find .%s", strings.Join(pth, ".")) + } else if v != value { + t.Fatalf("wanted %q at .%s, got %q", value, strings.Join(pth, "."), v) + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go index 57b04884b..4dcf8d727 100644 --- a/vendor/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go @@ -18,27 +18,30 @@ package integration import ( "testing" + "time" "github.com/stretchr/testify/require" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/test/integration/testserver" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" ) func TestFinalization(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() require.NoError(t, err) defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) require.NoError(t, err) ns := "not-the-default" name := "foo123" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) instance := testserver.NewNoxuInstance(ns, name) instance.SetFinalizers([]string{"noxu.example.com/finalizer"}) @@ -89,3 +92,74 @@ func TestFinalization(t *testing.T) { require.Error(t, err) require.True(t, errors.IsNotFound(err), "%#v", err) } + +func TestFinalizationAndDeletion(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + require.NoError(t, err) + defer close(stopCh) + + // Create a CRD. + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + require.NoError(t, err) + + // Create a CR with a finalizer. + ns := "not-the-default" + name := "foo123" + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) + + instance := testserver.NewNoxuInstance(ns, name) + instance.SetFinalizers([]string{"noxu.example.com/finalizer"}) + createdNoxuInstance, err := instantiateCustomResource(t, instance, noxuResourceClient, noxuDefinition) + require.NoError(t, err) + + // Delete a CR. Because there's a finalizer, it will not get deleted now. + uid := createdNoxuInstance.GetUID() + err = noxuResourceClient.Delete(name, &metav1.DeleteOptions{ + Preconditions: &metav1.Preconditions{ + UID: &uid, + }, + }) + require.NoError(t, err) + + // Check is the CR scheduled for deletion. + gottenNoxuInstance, err := noxuResourceClient.Get(name, metav1.GetOptions{}) + require.NoError(t, err) + require.NotNil(t, gottenNoxuInstance.GetDeletionTimestamp()) + + // Delete the CRD. + testserver.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient) + + // Check is CR still there after the CRD deletion. + gottenNoxuInstance, err = noxuResourceClient.Get(name, metav1.GetOptions{}) + require.NoError(t, err) + + // Update the CR to remove the finalizer. + for { + gottenNoxuInstance.SetFinalizers(nil) + _, err = noxuResourceClient.Update(gottenNoxuInstance) + if err == nil { + break + } + if !errors.IsConflict(err) { + require.NoError(t, err) // Fail on unexpected error + } + gottenNoxuInstance, err = noxuResourceClient.Get(name, metav1.GetOptions{}) + require.NoError(t, err) + } + + // Verify the CR is gone. + // It should return the NonFound error. + _, err = noxuResourceClient.Get(name, metav1.GetOptions{}) + if !errors.IsNotFound(err) { + t.Fatalf("unable to delete cr: %v", err) + } + + err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { + _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}) + return errors.IsNotFound(err), err + }) + if !errors.IsNotFound(err) { + t.Fatalf("unable to delete crd: %v", err) + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/helpers.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/helpers.go new file mode 100644 index 000000000..5aa231d45 --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/helpers.go @@ -0,0 +1,94 @@ +/* +Copyright 2018 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 integration + +import ( + "fmt" + "testing" + + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" +) + +func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) { + return instantiateVersionedCustomResource(t, instanceToCreate, client, definition, definition.Spec.Versions[0].Name) +} + +func instantiateVersionedCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition, version string) (*unstructured.Unstructured, error) { + createdInstance, err := client.Create(instanceToCreate) + if err != nil { + t.Logf("%#v", createdInstance) + return nil, err + } + createdObjectMeta, err := meta.Accessor(createdInstance) + if err != nil { + t.Fatal(err) + } + // it should have a UUID + if len(createdObjectMeta.GetUID()) == 0 { + t.Errorf("missing uuid: %#v", createdInstance) + } + createdTypeMeta, err := meta.TypeAccessor(createdInstance) + if err != nil { + t.Fatal(err) + } + if e, a := definition.Spec.Group+"/"+version, createdTypeMeta.GetAPIVersion(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := definition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + return createdInstance, nil +} + +func newNamespacedCustomResourceVersionedClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition, version string) dynamic.ResourceInterface { + gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: version, Resource: crd.Spec.Names.Plural} + + if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { + return client.Resource(gvr).Namespace(ns) + } + return client.Resource(gvr) +} + +func newNamespacedCustomResourceClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { + return newNamespacedCustomResourceVersionedClient(ns, client, crd, crd.Spec.Versions[0].Name) +} + +// updateCustomResourceDefinitionWithRetry updates a CRD, retrying up to 5 times on version conflict errors. +func updateCustomResourceDefinitionWithRetry(client clientset.Interface, name string, update func(*apiextensionsv1beta1.CustomResourceDefinition)) (*apiextensionsv1beta1.CustomResourceDefinition, error) { + for i := 0; i < 5; i++ { + crd, err := client.ApiextensionsV1beta1().CustomResourceDefinitions().Get(name, metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to get CustomResourceDefinition %q: %v", name, err) + } + update(crd) + crd, err = client.ApiextensionsV1beta1().CustomResourceDefinitions().Update(crd) + if err == nil { + return crd, nil + } + if !errors.IsConflict(err) { + return nil, fmt.Errorf("failed to update CustomResourceDefinition %q: %v", name, err) + } + } + return nil, fmt.Errorf("too many retries after conflicts updating CustomResourceDefinition %q", name) +} diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go new file mode 100644 index 000000000..50f656bf1 --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go @@ -0,0 +1,166 @@ +/* +Copyright 2018 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 integration + +import ( + "path" + "reflect" + "strings" + "testing" + + "github.com/coreos/etcd/clientv3" + "github.com/coreos/etcd/pkg/transport" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apiextensions-apiserver/test/integration/testserver" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/json" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/client-go/dynamic" +) + +func TestPostInvalidObjectMeta(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + noxuResourceClient := newNamespacedCustomResourceClient("default", dynamicClient, noxuDefinition) + + obj := testserver.NewNoxuInstance("default", "foo") + unstructured.SetNestedField(obj.UnstructuredContent(), int64(42), "metadata", "unknown") + unstructured.SetNestedField(obj.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "labels") + _, err = instantiateCustomResource(t, obj, noxuResourceClient, noxuDefinition) + if err == nil { + t.Fatalf("unexpected non-error, expected invalid labels to be rejected: %v", err) + } + if status, ok := err.(errors.APIStatus); !ok { + t.Fatalf("expected APIStatus error, but got: %#v", err) + } else if !errors.IsBadRequest(err) { + t.Fatalf("expected BadRequst error, but got: %v", errors.ReasonForError(err)) + } else if !strings.Contains(status.Status().Message, "cannot be handled") { + t.Fatalf("expected 'cannot be handled' error message, got: %v", status.Status().Message) + } + + unstructured.SetNestedField(obj.UnstructuredContent(), map[string]interface{}{"bar": "abc"}, "metadata", "labels") + obj, err = instantiateCustomResource(t, obj, noxuResourceClient, noxuDefinition) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if unknown, found, err := unstructured.NestedInt64(obj.UnstructuredContent(), "metadata", "unknown"); err != nil { + t.Errorf("unexpected error getting metadata.unknown: %v", err) + } else if found { + t.Errorf("unexpected metadata.unknown=%#v: expected this to be pruned", unknown) + } +} + +func TestInvalidObjectMetaInStorage(t *testing.T) { + serverConfig, err := testserver.DefaultServerConfig() + if err != nil { + t.Fatal(err) + } + + stopCh, config, err := testserver.StartServer(serverConfig) + defer close(stopCh) + if err != nil { + t.Fatal(err) + } + + apiExtensionClient, err := clientset.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + restOptions, err := serverConfig.GenericConfig.RESTOptionsGetter.GetRESTOptions(schema.GroupResource{Group: noxuDefinition.Spec.Group, Resource: noxuDefinition.Spec.Names.Plural}) + if err != nil { + t.Fatal(err) + } + tlsInfo := transport.TLSInfo{ + CertFile: restOptions.StorageConfig.CertFile, + KeyFile: restOptions.StorageConfig.KeyFile, + CAFile: restOptions.StorageConfig.CAFile, + } + tlsConfig, err := tlsInfo.ClientConfig() + if err != nil { + t.Fatal(err) + } + etcdConfig := clientv3.Config{ + Endpoints: restOptions.StorageConfig.ServerList, + TLS: tlsConfig, + } + etcdclient, err := clientv3.New(etcdConfig) + if err != nil { + t.Fatal(err) + } + + t.Logf("Creating object with invalid labels manually in etcd") + + original := testserver.NewNoxuInstance("default", "foo") + unstructured.SetNestedField(original.UnstructuredContent(), int64(42), "metadata", "unknown") + unstructured.SetNestedField(original.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "labels") + + ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault) + key := path.Join("/", restOptions.StorageConfig.Prefix, noxuDefinition.Spec.Group, "noxus/default/foo") + val, _ := json.Marshal(original.UnstructuredContent()) + if _, err := etcdclient.Put(ctx, key, string(val)); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + t.Logf("Checking that ObjectMeta is pruned from unknown fields") + + noxuResourceClient := newNamespacedCustomResourceClient("default", dynamicClient, noxuDefinition) + obj, err := noxuResourceClient.Get("foo", metav1.GetOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if unknown, found, err := unstructured.NestedFieldNoCopy(obj.UnstructuredContent(), "metadata", "unknown"); err != nil { + t.Errorf("unexpected error: %v", err) + } else if found { + t.Errorf("unexpected to find metadata.unknown=%#v", unknown) + } + + t.Logf("Checking that ObjectMeta is pruned from invalid typed fields") + + if labels, found, err := unstructured.NestedStringMap(obj.UnstructuredContent(), "metadata", "labels"); err != nil { + t.Errorf("unexpected error: %v", err) + } else if found && !reflect.DeepEqual(labels, map[string]string{"bar": "abc"}) { + t.Errorf("unexpected to find metadata.lables=%#v", labels) + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/registration_test.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/registration_test.go index 7cdd2bc7c..9cb33ac70 100644 --- a/vendor/k8s.io/apiextensions-apiserver/test/integration/registration_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/registration_test.go @@ -40,56 +40,8 @@ import ( "k8s.io/client-go/dynamic" ) -func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) { - createdInstance, err := client.Create(instanceToCreate) - if err != nil { - t.Logf("%#v", createdInstance) - return nil, err - } - createdObjectMeta, err := meta.Accessor(createdInstance) - if err != nil { - t.Fatal(err) - } - // it should have a UUID - if len(createdObjectMeta.GetUID()) == 0 { - t.Errorf("missing uuid: %#v", createdInstance) - } - createdTypeMeta, err := meta.TypeAccessor(createdInstance) - if err != nil { - t.Fatal(err) - } - if e, a := definition.Spec.Group+"/"+definition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := definition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - return createdInstance, nil -} - -func NewNamespacedCustomResourceClient(ns string, client dynamic.Interface, definition *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { - return client.Resource(&metav1.APIResource{ - Name: definition.Spec.Names.Plural, - Namespaced: definition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) -} - -func NewNamespacedCustomResourceStatusClient(ns string, client dynamic.Interface, definition *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { - return client.Resource(&metav1.APIResource{ - Name: definition.Spec.Names.Plural + "/status", - Namespaced: definition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) -} - -func NewNamespacedCustomResourceScaleClient(ns string, client dynamic.Interface, definition *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { - return client.Resource(&metav1.APIResource{ - Name: definition.Spec.Names.Plural + "/scale", - Namespaced: definition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) -} - func TestMultipleResourceInstances(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -97,11 +49,11 @@ func TestMultipleResourceInstances(t *testing.T) { ns := "not-the-default" noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuList, err := noxuNamespacedResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) @@ -168,10 +120,10 @@ func TestMultipleResourceInstances(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := len(instances), len(listWithItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := len(instances), len(listWithItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } - for _, a := range listWithItem.(*unstructured.UnstructuredList).Items { + for _, a := range listWithItem.Items { if e := instances[a.GetName()].Instance; !reflect.DeepEqual(e, &a) { t.Errorf("expected %v, got %v", e, a) } @@ -185,7 +137,7 @@ func TestMultipleResourceInstances(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := 0, len(listWithoutItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(listWithoutItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -213,7 +165,7 @@ func TestMultipleResourceInstances(t *testing.T) { } func TestMultipleRegistration(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -222,11 +174,11 @@ func TestMultipleRegistration(t *testing.T) { ns := "not-the-default" sameInstanceName := "foo" noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) createdNoxuInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu Instance:%v", err) @@ -241,11 +193,11 @@ func TestMultipleRegistration(t *testing.T) { } curletDefinition := testserver.NewCurletCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - curletVersionClient, err := testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, clientPool) + curletDefinition, err = testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - curletNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, curletVersionClient, curletDefinition) + curletNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, curletDefinition) createdCurletInstance, err := instantiateCustomResource(t, testserver.NewCurletInstance(ns, sameInstanceName), curletNamespacedResourceClient, curletDefinition) if err != nil { t.Fatalf("unable to create noxu Instance:%v", err) @@ -269,7 +221,7 @@ func TestMultipleRegistration(t *testing.T) { } func TestDeRegistrationAndReRegistration(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -278,18 +230,18 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { ns := "not-the-default" sameInstanceName := "foo" func() { - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) if _, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition); err != nil { t.Fatal(err) } if err := testserver.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } - if _, err := testserver.GetCustomResourceDefinition(noxuDefinition, apiExtensionClient); err == nil || !errors.IsNotFound(err) { + if _, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { t.Fatalf("expected a NotFound error, got:%v", err) } if _, err = noxuNamespacedResourceClient.List(metav1.ListOptions{}); err == nil || !errors.IsNotFound(err) { @@ -301,14 +253,14 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { }() func() { - if _, err := testserver.GetCustomResourceDefinition(noxuDefinition, apiExtensionClient); err == nil || !errors.IsNotFound(err) { + if _, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { t.Fatalf("expected a NotFound error, got:%v", err) } - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) initialList, err := noxuNamespacedResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) @@ -316,7 +268,7 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { if _, err = noxuNamespacedResourceClient.Get(sameInstanceName, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { t.Fatalf("expected a NotFound error, got:%v", err) } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(initialList.Items); e != a { t.Fatalf("expected %v, got %v", e, a) } createdNoxuInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition) @@ -334,10 +286,10 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := 1, len(listWithItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 1, len(listWithItem.Items); e != a { t.Fatalf("expected %v, got %v", e, a) } - if e, a := *createdNoxuInstance, listWithItem.(*unstructured.UnstructuredList).Items[0]; !reflect.DeepEqual(e, a) { + if e, a := *createdNoxuInstance, listWithItem.Items[0]; !reflect.DeepEqual(e, a) { t.Fatalf("expected %v, got %v", e, a) } @@ -351,7 +303,7 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := 0, len(listWithoutItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(listWithoutItem.Items); e != a { t.Fatalf("expected %v, got %v", e, a) } }() @@ -372,28 +324,31 @@ func TestEtcdStorage(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(clientConfig) + dynamicClient, err := dynamic.NewForConfig(clientConfig) + if err != nil { + t.Fatal(err) + } etcdPrefix := getPrefixFromConfig(t, config) ns1 := "another-default-is-possible" curletDefinition := testserver.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - curletVersionClient, err := testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, clientPool) + curletDefinition, err = testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - curletNamespacedResourceClient := NewNamespacedCustomResourceClient(ns1, curletVersionClient, curletDefinition) + curletNamespacedResourceClient := newNamespacedCustomResourceClient(ns1, dynamicClient, curletDefinition) if _, err := instantiateCustomResource(t, testserver.NewCurletInstance(ns1, "bar"), curletNamespacedResourceClient, curletDefinition); err != nil { t.Fatalf("unable to create curlet cluster scoped Instance:%v", err) } ns2 := "the-cruel-default" noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns2, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns2, dynamicClient, noxuDefinition) if _, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns2, "foo"), noxuNamespacedResourceClient, noxuDefinition); err != nil { t.Fatalf("unable to create noxu namespace scoped Instance:%v", err) } diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go index 7f04c8215..4421d840d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go @@ -22,7 +22,6 @@ import ( "sort" "strings" "testing" - "time" autoscaling "k8s.io/api/autoscaling/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -30,14 +29,10 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/dynamic" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "k8s.io/apiextensions-apiserver/pkg/features" "k8s.io/apiextensions-apiserver/test/integration/testserver" ) @@ -90,24 +85,20 @@ func NewNoxuSubresourceInstance(namespace, name string) *unstructured.Unstructur } func TestStatusSubresource(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -137,7 +128,7 @@ func TestStatusSubresource(t *testing.T) { // UpdateStatus should not update spec. // Check that .spec.num = 10 and .status.num = 20 - updatedStatusInstance, err := noxuStatusResourceClient.Update(gottenNoxuInstance) + updatedStatusInstance, err := noxuResourceClient.UpdateStatus(gottenNoxuInstance) if err != nil { t.Fatalf("unable to update status: %v", err) } @@ -200,9 +191,6 @@ func TestStatusSubresource(t *testing.T) { } func TestScaleSubresource(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - groupResource := schema.GroupResource{ Group: "mygroup.example.com", Resource: "noxus", @@ -218,26 +206,28 @@ func TestScaleSubresource(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) // set invalid json path for specReplicasPath noxuDefinition.Spec.Subresources.Scale.SpecReplicasPath = "foo,bar" - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatalf("unexpected non-error: specReplicasPath should be a valid json path under .spec") } noxuDefinition.Spec.Subresources.Scale.SpecReplicasPath = ".spec.replicas" - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -257,7 +247,7 @@ func TestScaleSubresource(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - _, err = noxuStatusResourceClient.Update(gottenNoxuInstance) + _, err = noxuResourceClient.UpdateStatus(gottenNoxuInstance) if err != nil { t.Fatalf("unable to update status: %v", err) } @@ -332,9 +322,6 @@ func TestScaleSubresource(t *testing.T) { } func TestValidationSchema(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - stopCh, config, err := testserver.StartDefaultServer() if err != nil { t.Fatal(err) @@ -345,13 +332,19 @@ func TestValidationSchema(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } // fields other than properties in root schema are not allowed noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition.Spec.Subresources = &apiextensionsv1beta1.CustomResourceSubresources{ + Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, + } + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { - t.Fatalf("unexpected non-error: if subresources for custom resources are enabled, only properties can be used at the root of the schema") + t.Fatalf(`unexpected non-error, expected: must only have "properties" or "required" at the root if the status subresource is enabled`) } // make sure we are not restricting fields to properties even in subschemas @@ -366,18 +359,17 @@ func TestValidationSchema(t *testing.T) { }, }, }, + Required: []string{"spec"}, + Description: "This is a description at the root of the schema", } - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatalf("unable to created crd %v: %v", noxuDefinition.Name, err) } } func TestValidateOnlyStatus(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -386,9 +378,8 @@ func TestValidateOnlyStatus(t *testing.T) { // UpdateStatus should validate only status // 1. create a crd with max value of .spec.num = 10 and .status.num = 10 // 2. create a cr with .spec.num = 10 and .status.num = 10 (valid) - // 3. update the crd so that max value of .spec.num = 5 and .status.num = 10 - // 4. update the status of the cr with .status.num = 5 (spec is invalid) - // validation passes becauses spec is not validated + // 3. update the spec of the cr with .spec.num = 15 (spec is invalid), expect no error + // 4. update the spec of the cr with .spec.num = 15 (spec is invalid), expect error // max value of spec.num = 10 and status.num = 10 schema := &apiextensionsv1beta1.JSONSchemaProps{ @@ -417,13 +408,12 @@ func TestValidateOnlyStatus(t *testing.T) { OpenAPIV3Schema: schema, } - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) // set .spec.num = 10 and .status.num = 10 noxuInstance := NewNoxuSubresourceInstance(ns, "foo") @@ -437,65 +427,35 @@ func TestValidateOnlyStatus(t *testing.T) { t.Fatalf("unable to create noxu instance: %v", err) } - gottenCRD, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get("noxus.mygroup.example.com", metav1.GetOptions{}) + // update the spec with .spec.num = 15, expecting no error + err = unstructured.SetNestedField(createdNoxuInstance.Object, int64(15), "spec", "num") if err != nil { - t.Fatal(err) + t.Fatalf("unexpected error setting .spec.num: %v", err) } - - // update the crd so that max value of spec.num = 5 and status.num = 10 - gottenCRD.Spec.Validation.OpenAPIV3Schema = &apiextensionsv1beta1.JSONSchemaProps{ - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ - "spec": { - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ - "num": { - Type: "integer", - Maximum: float64Ptr(5), - }, - }, - }, - "status": { - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ - "num": { - Type: "integer", - Maximum: float64Ptr(10), - }, - }, - }, - }, - } - - if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(gottenCRD); err != nil { - t.Fatal(err) - } - - // update the status with .status.num = 5 - err = unstructured.SetNestedField(createdNoxuInstance.Object, int64(5), "status", "num") + createdNoxuInstance, err = noxuResourceClient.UpdateStatus(createdNoxuInstance) if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Errorf("unexpected error: %v", err) } - // cr is updated even though spec is invalid - err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - _, err := noxuStatusResourceClient.Update(createdNoxuInstance) - if statusError, isStatus := err.(*apierrors.StatusError); isStatus { - if strings.Contains(statusError.Error(), "is invalid") { - return false, nil - } - } - if err != nil { - return false, err - } - return true, nil - }) + // update with .status.num = 15, expecting an error + err = unstructured.SetNestedField(createdNoxuInstance.Object, int64(15), "status", "num") if err != nil { - t.Fatal(err) + t.Fatalf("unexpected error setting .status.num: %v", err) + } + createdNoxuInstance, err = noxuResourceClient.UpdateStatus(createdNoxuInstance) + if err == nil { + t.Fatal("expected error, but got none") + } + statusError, isStatus := err.(*apierrors.StatusError) + if !isStatus || statusError == nil { + t.Fatalf("expected status error, got %T: %v", err, err) + } + if !strings.Contains(statusError.Error(), "Invalid value") { + t.Fatalf("expected 'Invalid value' in error, got: %v", err) } } func TestSubresourcesDiscovery(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - stopCh, config, err := testserver.StartDefaultServer() if err != nil { t.Fatal(err) @@ -506,10 +466,13 @@ func TestSubresourcesDiscovery(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -577,24 +540,20 @@ func TestSubresourcesDiscovery(t *testing.T) { } func TestGeneration(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -616,7 +575,7 @@ func TestGeneration(t *testing.T) { } // UpdateStatus does not increment generation - updatedStatusInstance, err := noxuStatusResourceClient.Update(gottenNoxuInstance) + updatedStatusInstance, err := noxuResourceClient.UpdateStatus(gottenNoxuInstance) if err != nil { t.Fatalf("unable to update status: %v", err) } @@ -646,9 +605,6 @@ func TestGeneration(t *testing.T) { } func TestSubresourcePatch(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - groupResource := schema.GroupResource{ Group: "mygroup.example.com", Resource: "noxus", @@ -664,18 +620,21 @@ func TestSubresourcePatch(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) - noxuScaleResourceClient := NewNamespacedCustomResourceScaleClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) + + t.Logf("Creating foo") _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -686,28 +645,21 @@ func TestSubresourcePatch(t *testing.T) { t.Fatal(err) } + t.Logf("Patching .status.num to 999") patch := []byte(`{"spec": {"num":999}, "status": {"num":999}}`) - patchedNoxuInstance, err := noxuStatusResourceClient.Patch("foo", types.MergePatchType, patch) + patchedNoxuInstance, err := noxuResourceClient.Patch("foo", types.MergePatchType, patch, "status") if err != nil { t.Fatalf("unexpected error: %v", err) } - // .spec.num should remain 10 - specNum, found, err := unstructured.NestedInt64(patchedNoxuInstance.Object, "spec", "num") - if !found || err != nil { - t.Fatalf("unable to get .spec.num") - } - if specNum != 10 { - t.Fatalf(".spec.num: expected: %v, got: %v", 10, specNum) - } - - // .status.num should be 999 - statusNum, found, err := unstructured.NestedInt64(patchedNoxuInstance.Object, "status", "num") - if !found || err != nil { - t.Fatalf("unable to get .status.num") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "status", "num") // .status.num should be 999 + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 10, "spec", "num") // .spec.num should remain 10 + rv, found, err := unstructured.NestedString(patchedNoxuInstance.UnstructuredContent(), "metadata", "resourceVersion") + if err != nil { + t.Fatal(err) } - if statusNum != 999 { - t.Fatalf(".status.num: expected: %v, got: %v", 999, statusNum) + if !found { + t.Fatalf("metadata.resourceVersion not found") } // this call waits for the resourceVersion to be reached in the cache before returning. @@ -722,23 +674,44 @@ func TestSubresourcePatch(t *testing.T) { } // no-op patch - _, err = noxuStatusResourceClient.Patch("foo", types.MergePatchType, patch) + t.Logf("Patching .status.num again to 999") + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "status") if err != nil { t.Fatalf("unexpected error: %v", err) } + // make sure no-op patch does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "status", "num") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 10, "spec", "num") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") // empty patch - _, err = noxuStatusResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) + t.Logf("Applying empty patch") + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`), "status") if err != nil { t.Fatalf("unexpected error: %v", err) } + // an empty patch is a no-op patch. make sure it does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "status", "num") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 10, "spec", "num") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") + t.Logf("Patching .spec.replicas to 7") patch = []byte(`{"spec": {"replicas":7}, "status": {"replicas":7}}`) - patchedNoxuInstance, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, patch) + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "scale") if err != nil { t.Fatalf("unexpected error: %v", err) } + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 7, "spec", "replicas") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 0, "status", "replicas") // .status.replicas should remain 0 + rv, found, err = unstructured.NestedString(patchedNoxuInstance.UnstructuredContent(), "metadata", "resourceVersion") + if err != nil { + t.Fatal(err) + } + if !found { + t.Fatalf("metadata.resourceVersion not found") + } + // this call waits for the resourceVersion to be reached in the cache before returning. // We need to do this because the patch gets its initial object from the storage, and the cache serves that. // If it is out of date, then our initial patch is applied to an old resource version, which conflicts @@ -750,7 +723,7 @@ func TestSubresourcePatch(t *testing.T) { t.Fatalf("unexpected error: %v", err) } - // Scale.Spec.Replicas = 7 but Scale.Status.Replicas should remain 7 + // Scale.Spec.Replicas = 7 but Scale.Status.Replicas should remain 0 gottenScale, err := scaleClient.Scales("not-the-default").Get(groupResource, "foo") if err != nil { t.Fatal(err) @@ -763,24 +736,34 @@ func TestSubresourcePatch(t *testing.T) { } // no-op patch - _, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, patch) + t.Logf("Patching .spec.replicas again to 7") + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "scale") if err != nil { t.Fatalf("unexpected error: %v", err) } + // make sure no-op patch does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 7, "spec", "replicas") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 0, "status", "replicas") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") // empty patch - _, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) + t.Logf("Applying empty patch") + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`), "scale") if err != nil { t.Fatalf("unexpected error: %v", err) } + // an empty patch is a no-op patch. make sure it does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 7, "spec", "replicas") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 0, "status", "replicas") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") // make sure strategic merge patch is not supported for both status and scale - _, err = noxuStatusResourceClient.Patch("foo", types.StrategicMergePatchType, patch) + _, err = noxuResourceClient.Patch("foo", types.StrategicMergePatchType, patch, "status") if err == nil { t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources") } - _, err = noxuScaleResourceClient.Patch("foo", types.StrategicMergePatchType, patch) + _, err = noxuResourceClient.Patch("foo", types.StrategicMergePatchType, patch, "scale") if err == nil { t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources") } diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/table_test.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/table_test.go new file mode 100644 index 000000000..0c3ac609a --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/table_test.go @@ -0,0 +1,185 @@ +/* +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 integration + +import ( + "fmt" + "testing" + + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/test/integration/testserver" +) + +func newTableCRD() *apiextensionsv1beta1.CustomResourceDefinition { + return &apiextensionsv1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "tables.mygroup.example.com"}, + Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Version: "v1beta1", + Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Plural: "tables", + Singular: "table", + Kind: "Table", + ListKind: "TablemList", + }, + Scope: apiextensionsv1beta1.ClusterScoped, + AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"}, + {Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"}, + {Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"}, + {Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values", JSONPath: ".spec.gamma"}, + }, + }, + } +} + +func newTableInstance(name string) *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "mygroup.example.com/v1beta1", + "kind": "Table", + "metadata": map[string]interface{}{ + "name": name, + }, + "spec": map[string]interface{}{ + "alpha": "foo_123", + "beta": 10, + "gamma": "bar", + "delta": "hello", + }, + }, + } +} + +func TestTableGet(t *testing.T) { + stopCh, config, err := testserver.StartDefaultServer() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + apiExtensionClient, err := clientset.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + crd := newTableCRD() + crd, err = testserver.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crd.Name, metav1.GetOptions{}) + if err != nil { + t.Fatal(err) + } + t.Logf("table crd created: %#v", crd) + + crClient := newNamespacedCustomResourceClient("", dynamicClient, crd) + foo, err := crClient.Create(newTableInstance("foo")) + if err != nil { + t.Fatalf("unable to create noxu instance: %v", err) + } + t.Logf("foo created: %#v", foo.UnstructuredContent()) + + gv := schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version} + gvk := gv.WithKind(crd.Spec.Names.Kind) + + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + parameterCodec := runtime.NewParameterCodec(scheme) + metav1.AddToGroupVersion(scheme, gv) + scheme.AddKnownTypes(gv, &metav1beta1.Table{}, &metav1beta1.TableOptions{}) + scheme.AddKnownTypes(metav1beta1.SchemeGroupVersion, &metav1beta1.Table{}, &metav1beta1.TableOptions{}) + + crConfig := *config + crConfig.GroupVersion = &gv + crConfig.APIPath = "/apis" + crConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: codecs} + crRestClient, err := rest.RESTClientFor(&crConfig) + if err != nil { + t.Fatal(err) + } + + ret, err := crRestClient.Get(). + Resource(crd.Spec.Names.Plural). + SetHeader("Accept", fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName)). + VersionedParams(&metav1beta1.TableOptions{}, parameterCodec). + Do(). + Get() + if err != nil { + t.Fatalf("failed to list %v resources: %v", gvk, err) + } + + tbl, ok := ret.(*metav1beta1.Table) + if !ok { + t.Fatalf("expected metav1beta1.Table, got %T", ret) + } + t.Logf("%v table list: %#v", gvk, tbl) + + if got, expected := len(tbl.ColumnDefinitions), 5; got != expected { + t.Errorf("expected %d headers, got %d", expected, got) + } else { + alpha := metav1beta1.TableColumnDefinition{Name: "Alpha", Type: "string", Format: "", Description: "Custom resource definition column (in JSONPath format): .spec.alpha", Priority: 0} + if got, expected := tbl.ColumnDefinitions[2], alpha; got != expected { + t.Errorf("expected column definition %#v, got %#v", expected, got) + } + + beta := metav1beta1.TableColumnDefinition{Name: "Beta", Type: "integer", Format: "int64", Description: "the beta field", Priority: 42} + if got, expected := tbl.ColumnDefinitions[3], beta; got != expected { + t.Errorf("expected column definition %#v, got %#v", expected, got) + } + + gamma := metav1beta1.TableColumnDefinition{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values"} + if got, expected := tbl.ColumnDefinitions[4], gamma; got != expected { + t.Errorf("expected column definition %#v, got %#v", expected, got) + } + } + if got, expected := len(tbl.Rows), 1; got != expected { + t.Errorf("expected %d rows, got %d", expected, got) + } else if got, expected := len(tbl.Rows[0].Cells), 5; got != expected { + t.Errorf("expected %d cells, got %d", expected, got) + } else { + if got, expected := tbl.Rows[0].Cells[0], "foo"; got != expected { + t.Errorf("expected cell[0] to equal %q, got %q", expected, got) + } + if got, expected := tbl.Rows[0].Cells[2], "foo_123"; got != expected { + t.Errorf("expected cell[2] to equal %q, got %q", expected, got) + } + if got, expected := tbl.Rows[0].Cells[3], int64(10); got != expected { + t.Errorf("expected cell[3] to equal %#v, got %#v", expected, got) + } + if got, expected := tbl.Rows[0].Cells[4], interface{}(nil); got != expected { + t.Errorf("expected cell[3] to equal %#v although the type does not match the column, got %#v", expected, got) + } + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go index bf54e1490..f341b002f 100644 --- a/vendor/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go @@ -23,7 +23,6 @@ import ( apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" @@ -33,6 +32,7 @@ import ( "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" "k8s.io/client-go/scale" ) @@ -79,10 +79,10 @@ func NewNoxuCustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) * } } -func NewNoxuInstance(namespace, name string) *unstructured.Unstructured { +func NewVersionedNoxuInstance(namespace, name, version string) *unstructured.Unstructured { return &unstructured.Unstructured{ Object: map[string]interface{}{ - "apiVersion": "mygroup.example.com/v1beta1", + "apiVersion": "mygroup.example.com/" + version, "kind": "WishIHadChosenNoxu", "metadata": map[string]interface{}{ "namespace": namespace, @@ -99,6 +99,46 @@ func NewNoxuInstance(namespace, name string) *unstructured.Unstructured { } } +func NewNoxuInstance(namespace, name string) *unstructured.Unstructured { + return NewVersionedNoxuInstance(namespace, name, "v1beta1") +} + +func NewMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { + return &apiextensionsv1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, + Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Version: "v1beta1", + Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Plural: "noxus", + Singular: "nonenglishnoxu", + Kind: "WishIHadChosenNoxu", + ShortNames: []string{"foo", "bar", "abc", "def"}, + ListKind: "NoxuItemList", + Categories: []string{"all"}, + }, + Scope: scope, + Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: false, + }, + { + Name: "v1beta2", + Served: true, + Storage: true, + }, + { + Name: "v0", + Served: false, + Storage: false, + }, + }, + }, + } +} + func NewNoxu2CustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { return &apiextensionsv1beta1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "noxus2.mygroup.example.com"}, @@ -150,38 +190,60 @@ func NewCurletInstance(namespace, name string) *unstructured.Unstructured { } } +func servedVersions(crd *apiextensionsv1beta1.CustomResourceDefinition) []string { + if len(crd.Spec.Versions) == 0 { + return []string{crd.Spec.Version} + } + var versions []string + for _, v := range crd.Spec.Versions { + if v.Served { + versions = append(versions, v.Name) + } + } + return versions +} + +func existsInDiscovery(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, version string) (bool, error) { + groupResource, err := apiExtensionsClient.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + version) + if err != nil { + if errors.IsNotFound(err) { + return false, nil + } + return false, err + } + for _, g := range groupResource.APIResources { + if g.Name == crd.Spec.Names.Plural { + return true, nil + } + } + return false, nil +} + // CreateNewCustomResourceDefinitionWatchUnsafe creates the CRD and makes sure // the apiextension apiserver has installed the CRD. But it's not safe to watch // the created CR. Please call CreateNewCustomResourceDefinition if you need to // watch the CR. -func CreateNewCustomResourceDefinitionWatchUnsafe(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, clientPool dynamic.ClientPool) (dynamic.Interface, error) { - _, err := apiExtensionsClient.Apiextensions().CustomResourceDefinitions().Create(crd) +func CreateNewCustomResourceDefinitionWatchUnsafe(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) (*apiextensionsv1beta1.CustomResourceDefinition, error) { + crd, err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd) if err != nil { return nil, err } - // wait until the resource appears in discovery - err = wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - resourceList, err := apiExtensionsClient.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + crd.Spec.Version) + // wait until all resources appears in discovery + for _, version := range servedVersions(crd) { + err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { + return existsInDiscovery(crd, apiExtensionsClient, version) + }) if err != nil { - return false, nil - } - for _, resource := range resourceList.APIResources { - if resource.Name == crd.Spec.Names.Plural { - return true, nil - } + return nil, err } - return false, nil - }) - if err != nil { - return nil, err } - return clientPool.ClientForGroupVersionResource(schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}) + return crd, err } -func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, clientPool dynamic.ClientPool) (dynamic.Interface, error) { - dynamicClient, err := CreateNewCustomResourceDefinitionWatchUnsafe(crd, apiExtensionsClient, clientPool) +func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, dynamicClientSet dynamic.Interface) (*apiextensionsv1beta1.CustomResourceDefinition, error) { + crd, err := CreateNewCustomResourceDefinitionWatchUnsafe(crd, apiExtensionsClient) if err != nil { return nil, err } @@ -196,43 +258,35 @@ func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceD // For this test, we'll actually cycle, "list/watch/create/delete" until we get an RV from list that observes the create and not an error. // This way all the tests that are checking for watches don't have to worry about RV too old problems because crazy things *could* happen // before like the created RV could be too old to watch. - var primingErr error - wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - primingErr = checkForWatchCachePrimed(crd, dynamicClient) - if primingErr == nil { - return true, nil + for _, version := range servedVersions(crd) { + err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { + return isWatchCachePrimed(crd, dynamicClientSet, version) + }) + if err != nil { + return nil, err } - return false, nil - }) - if primingErr != nil { - return nil, primingErr } - - return dynamicClient, nil + return crd, nil } -func checkForWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) error { +// isWatchCachePrimed returns true if the watch is primed for an specified version of CRD watch +func isWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition, dynamicClientSet dynamic.Interface, version string) (bool, error) { ns := "" if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { ns = "aval" } - resourceClient := dynamicClient.Resource(&metav1.APIResource{ - Name: crd.Spec.Names.Plural, - Namespaced: crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped, - }, ns) - initialList, err := resourceClient.List(metav1.ListOptions{}) - if err != nil { - return err - } - initialListListMeta, err := meta.ListAccessor(initialList) - if err != nil { - return err - } + gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: version, Resource: crd.Spec.Names.Plural} + var resourceClient dynamic.ResourceInterface + if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { + resourceClient = dynamicClientSet.Resource(gvr).Namespace(ns) + } else { + resourceClient = dynamicClientSet.Resource(gvr) + } instanceName := "setup-instance" instance := &unstructured.Unstructured{ Object: map[string]interface{}{ - "apiVersion": crd.Spec.Group + "/" + crd.Spec.Version, + "apiVersion": crd.Spec.Group + "/" + version, "kind": crd.Spec.Names.Kind, "metadata": map[string]interface{}{ "namespace": ns, @@ -243,31 +297,35 @@ func checkForWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition "gamma": "bar", "delta": "hello", "epsilon": "foobar", + "spec": map[string]interface{}{}, }, } - if _, err := resourceClient.Create(instance); err != nil { - return err + createdInstance, err := resourceClient.Create(instance) + if err != nil { + return false, err + } + err = resourceClient.Delete(createdInstance.GetName(), nil) + if err != nil { + return false, err } - // we created something, clean it up - defer func() { - resourceClient.Delete(instanceName, nil) - }() - noxuWatch, err := resourceClient.Watch(metav1.ListOptions{ResourceVersion: initialListListMeta.GetResourceVersion()}) + noxuWatch, err := resourceClient.Watch(metav1.ListOptions{ResourceVersion: createdInstance.GetResourceVersion()}) if err != nil { - return err + return false, err } defer noxuWatch.Stop() select { case watchEvent := <-noxuWatch.ResultChan(): - if watch.Added == watchEvent.Type { - return nil + if watch.Error == watchEvent.Type { + return false, nil } - return fmt.Errorf("expected add, but got %#v", watchEvent) - + if watch.Deleted != watchEvent.Type { + return false, fmt.Errorf("expected DELETE, but got %#v", watchEvent) + } + return true, nil case <-time.After(5 * time.Second): - return fmt.Errorf("gave up waiting for watch event") + return false, fmt.Errorf("gave up waiting for watch event") } } @@ -275,27 +333,16 @@ func DeleteCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefi if err := apiExtensionsClient.Apiextensions().CustomResourceDefinitions().Delete(crd.Name, nil); err != nil { return err } - err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - groupResource, err := apiExtensionsClient.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + crd.Spec.Version) + for _, version := range servedVersions(crd) { + err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { + exists, err := existsInDiscovery(crd, apiExtensionsClient, version) + return !exists, err + }) if err != nil { - if errors.IsNotFound(err) { - return true, nil - - } - return false, err - } - for _, g := range groupResource.APIResources { - if g.Name == crd.Spec.Names.Plural { - return false, nil - } + return err } - return true, nil - }) - return err -} - -func GetCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) (*apiextensionsv1beta1.CustomResourceDefinition, error) { - return apiExtensionsClient.Apiextensions().CustomResourceDefinitions().Get(crd.Name, metav1.GetOptions{}) + } + return nil } func CreateNewScaleClient(crd *apiextensionsv1beta1.CustomResourceDefinition, config *rest.Config) (scale.ScalesGetter, error) { @@ -308,7 +355,7 @@ func CreateNewScaleClient(crd *apiextensionsv1beta1.CustomResourceDefinition, co return nil, err } - resources := []*discovery.APIGroupResources{ + resources := []*restmapper.APIGroupResources{ { Group: metav1.APIGroup{ Name: crd.Spec.Group, @@ -323,7 +370,7 @@ func CreateNewScaleClient(crd *apiextensionsv1beta1.CustomResourceDefinition, co }, } - restMapper := discovery.NewRESTMapper(resources, nil) + restMapper := restmapper.NewDiscoveryRESTMapper(resources) resolver := scale.NewDiscoveryScaleKindResolver(discoveryClient) return scale.NewForConfig(config, restMapper, dynamic.LegacyAPIPathResolverFunc, resolver) diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/testserver/start.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/testserver/start.go index c0a60bfc7..22b9fa286 100644 --- a/vendor/k8s.io/apiextensions-apiserver/test/integration/testserver/start.go +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/testserver/start.go @@ -64,7 +64,7 @@ func DefaultServerConfig() (*extensionsapiserver.Config, error) { if err := options.RecommendedOptions.ApplyTo(genericConfig, nil); err != nil { return nil, err } - if err := options.APIEnablement.ApplyTo(&genericConfig.Config, extensionsapiserver.DefaultAPIResourceConfigSource(), extensionsapiserver.Registry); err != nil { + if err := options.APIEnablement.ApplyTo(&genericConfig.Config, extensionsapiserver.DefaultAPIResourceConfigSource(), extensionsapiserver.Scheme); err != nil { return nil, err } @@ -90,7 +90,7 @@ func DefaultServerConfig() (*extensionsapiserver.Config, error) { func StartServer(config *extensionsapiserver.Config) (chan struct{}, *rest.Config, error) { stopCh := make(chan struct{}) - server, err := config.Complete().New(genericapiserver.EmptyDelegate) + server, err := config.Complete().New(genericapiserver.NewEmptyDelegate()) if err != nil { return nil, nil, err } @@ -139,7 +139,7 @@ func StartDefaultServer() (chan struct{}, *rest.Config, error) { return StartServer(config) } -func StartDefaultServerWithClients() (chan struct{}, clientset.Interface, dynamic.ClientPool, error) { +func StartDefaultServerWithClients() (chan struct{}, clientset.Interface, dynamic.Interface, error) { stopCh, config, err := StartDefaultServer() if err != nil { return nil, nil, nil, err @@ -151,5 +151,11 @@ func StartDefaultServerWithClients() (chan struct{}, clientset.Interface, dynami return nil, nil, nil, err } - return stopCh, apiExtensionsClient, dynamic.NewDynamicClientPool(config), nil + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + close(stopCh) + return nil, nil, nil, err + } + + return stopCh, apiExtensionsClient, dynamicClient, nil } diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/validation_test.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/validation_test.go index 3ef47b658..cb761330d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/test/integration/validation_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/validation_test.go @@ -31,20 +31,20 @@ import ( ) func TestForProperValidationErrors(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) tests := []struct { name string @@ -54,8 +54,7 @@ func TestForProperValidationErrors(t *testing.T) { { name: "bad version", instanceFn: func() *unstructured.Unstructured { - instance := testserver.NewNoxuInstance(ns, "foo") - instance.Object["apiVersion"] = "mygroup.example.com/v2" + instance := testserver.NewVersionedNoxuInstance(ns, "foo", "v2") return instance }, expectedError: "the API version in the data (mygroup.example.com/v2) does not match the expected API version (mygroup.example.com/v1beta1)", @@ -169,20 +168,20 @@ func newNoxuValidationInstance(namespace, name string) *unstructured.Unstructure } func TestCustomResourceValidation(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, newNoxuValidationInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -190,20 +189,20 @@ func TestCustomResourceValidation(t *testing.T) { } func TestCustomResourceUpdateValidation(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, newNoxuValidationInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -233,20 +232,20 @@ func TestCustomResourceUpdateValidation(t *testing.T) { } func TestCustomResourceValidationErrors(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) tests := []struct { name string @@ -324,7 +323,7 @@ func TestCustomResourceValidationErrors(t *testing.T) { } func TestCRValidationOnCRDUpdate(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -335,12 +334,12 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { // set stricter schema noxuDefinition.Spec.Validation.OpenAPIV3Schema.Required = []string{"alpha", "beta", "epsilon"} - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) // CR is rejected _, err = instantiateCustomResource(t, newNoxuValidationInstance(ns, "foo"), noxuResourceClient, noxuDefinition) @@ -348,14 +347,11 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { t.Fatalf("unexpected non-error: CR should be rejected") } - gottenCRD, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get("noxus.mygroup.example.com", metav1.GetOptions{}) - if err != nil { - t.Fatal(err) - } - // update the CRD to a less stricter schema - gottenCRD.Spec.Validation.OpenAPIV3Schema.Required = []string{"alpha", "beta"} - if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(gottenCRD); err != nil { + _, err = updateCustomResourceDefinitionWithRetry(apiExtensionClient, "noxus.mygroup.example.com", func(crd *apiextensionsv1beta1.CustomResourceDefinition) { + crd.Spec.Validation.OpenAPIV3Schema.Required = []string{"alpha", "beta"} + }) + if err != nil { t.Fatal(err) } @@ -378,7 +374,7 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { } func TestForbiddenFieldsInSchema(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -387,7 +383,7 @@ func TestForbiddenFieldsInSchema(t *testing.T) { noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) noxuDefinition.Spec.Validation.OpenAPIV3Schema.AdditionalProperties.Allows = false - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatalf("unexpected non-error: additionalProperties cannot be set to false") } @@ -398,7 +394,7 @@ func TestForbiddenFieldsInSchema(t *testing.T) { } noxuDefinition.Spec.Validation.OpenAPIV3Schema.AdditionalProperties.Allows = true - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatalf("unexpected non-error: uniqueItems cannot be set to true") } @@ -409,14 +405,14 @@ func TestForbiddenFieldsInSchema(t *testing.T) { UniqueItems: false, } - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatal("unexpected non-error: $ref cannot be non-empty string") } noxuDefinition.Spec.Validation.OpenAPIV3Schema.Ref = nil - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go new file mode 100644 index 000000000..55d0c17af --- /dev/null +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go @@ -0,0 +1,138 @@ +/* +Copyright 2018 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 integration + +import ( + "reflect" + "testing" + + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/test/integration/testserver" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestVersionedNamspacedScopedCRD(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + ns := "not-the-default" + testSimpleCRUD(t, ns, noxuDefinition, dynamicClient) +} + +func TestVersionedClusterScopedCRD(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + ns := "" + testSimpleCRUD(t, ns, noxuDefinition, dynamicClient) +} + +func TestStoragedVersionInNamespacedCRDStatus(t *testing.T) { + noxuDefinition := testserver.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped) + ns := "not-the-default" + testStoragedVersionInCRDStatus(t, ns, noxuDefinition) +} + +func TestStoragedVersionInClusterScopedCRDStatus(t *testing.T) { + noxuDefinition := testserver.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped) + ns := "" + testStoragedVersionInCRDStatus(t, ns, noxuDefinition) +} + +func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition) { + versionsV1Beta1Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: true, + }, + { + Name: "v1beta2", + Served: true, + Storage: false, + }, + } + versionsV1Beta2Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: false, + }, + { + Name: "v1beta2", + Served: true, + Storage: true, + }, + } + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition.Spec.Versions = versionsV1Beta1Storage + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + // The storage version list should be initilized to storage version + crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}) + if err != nil { + t.Fatal(err) + } + if e, a := []string{"v1beta1"}, crd.Status.StoredVersions; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + + // Changing CRD storage version should be reflected immediately + crd.Spec.Versions = versionsV1Beta2Storage + _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(crd) + if err != nil { + t.Fatal(err) + } + crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}) + if err != nil { + t.Fatal(err) + } + if e, a := []string{"v1beta1", "v1beta2"}, crd.Status.StoredVersions; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + + err = testserver.DeleteCustomResourceDefinition(crd, apiExtensionClient) + if err != nil { + t.Fatal(err) + } +} diff --git a/vendor/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go b/vendor/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go index 9f23427f0..2dc279559 100644 --- a/vendor/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go +++ b/vendor/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go @@ -27,13 +27,10 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/dynamic" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "k8s.io/apiextensions-apiserver/pkg/features" "k8s.io/apiextensions-apiserver/test/integration/testserver" ) @@ -48,10 +45,13 @@ func TestYAML(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -354,9 +354,6 @@ values: } func TestYAMLSubresource(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - stopCh, config, err := testserver.StartDefaultServer() if err != nil { t.Fatal(err) @@ -367,10 +364,13 @@ func TestYAMLSubresource(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.ClusterScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } diff --git a/vendor/k8s.io/apimachinery/Godeps/Godeps.json b/vendor/k8s.io/apimachinery/Godeps/Godeps.json index 9f81122a2..b580e4b31 100644 --- a/vendor/k8s.io/apimachinery/Godeps/Godeps.json +++ b/vendor/k8s.io/apimachinery/Godeps/Godeps.json @@ -1,6 +1,6 @@ { "ImportPath": "k8s.io/apimachinery", - "GoVersion": "go1.9", + "GoVersion": "go1.10", "GodepVersion": "v80", "Packages": [ "./..." @@ -24,7 +24,7 @@ }, { "ImportPath": "github.com/evanphx/json-patch", - "Rev": "944e07253867aacae43c04b2e6a239005443f33a" + "Rev": "94e38aa1586e8a6c8a75770bddf5ff84c48a106b" }, { "ImportPath": "github.com/ghodss/yaml", @@ -48,23 +48,23 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/gofuzz", @@ -92,7 +92,15 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" + }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" }, { "ImportPath": "github.com/mxk/go-flowrate/flowrate", @@ -112,11 +120,11 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/stretchr/testify/require", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "golang.org/x/net/html", @@ -172,7 +180,7 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/apimachinery/SECURITY_CONTACTS b/vendor/k8s.io/apimachinery/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/apimachinery/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/interfaces.go b/vendor/k8s.io/apimachinery/pkg/api/meta/interfaces.go index 5dc9d89e6..42eac3af0 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/interfaces.go +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/interfaces.go @@ -23,12 +23,6 @@ import ( "k8s.io/apimachinery/pkg/types" ) -// VersionInterfaces contains the interfaces one should use for dealing with types of a particular version. -type VersionInterfaces struct { - runtime.ObjectConvertor - MetadataAccessor -} - type ListMetaAccessor interface { GetListMeta() List } @@ -92,28 +86,19 @@ const ( type RESTScope interface { // Name of the scope Name() RESTScopeName - // ParamName is the optional name of the parameter that should be inserted in the resource url - // If empty, no param will be inserted - ParamName() string - // ArgumentName is the optional name that should be used for the variable holding the value. - ArgumentName() string - // ParamDescription is the optional description to use to document the parameter in api documentation - ParamDescription() string } // RESTMapping contains the information needed to deal with objects of a specific // resource and kind in a RESTful manner. type RESTMapping struct { - // Resource is a string representing the name of this resource as a REST client would see it - Resource string + // Resource is the GroupVersionResource (location) for this endpoint + Resource schema.GroupVersionResource + // GroupVersionKind is the GroupVersionKind (data format) to submit to this endpoint GroupVersionKind schema.GroupVersionKind // Scope contains the information needed to deal with REST Resources that are in a resource hierarchy Scope RESTScope - - runtime.ObjectConvertor - MetadataAccessor } // RESTMapper allows clients to map resources to kind, and map kind and version diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/lazy.go b/vendor/k8s.io/apimachinery/pkg/api/meta/lazy.go index 7f92f39a4..431a0a635 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/lazy.go +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/lazy.go @@ -19,27 +19,25 @@ package meta import ( "sync" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) // lazyObject defers loading the mapper and typer until necessary. type lazyObject struct { - loader func() (RESTMapper, runtime.ObjectTyper, error) + loader func() (RESTMapper, error) lock sync.Mutex loaded bool err error mapper RESTMapper - typer runtime.ObjectTyper } // NewLazyObjectLoader handles unrecoverable errors when creating a RESTMapper / ObjectTyper by // returning those initialization errors when the interface methods are invoked. This defers the // initialization and any server calls until a client actually needs to perform the action. -func NewLazyObjectLoader(fn func() (RESTMapper, runtime.ObjectTyper, error)) (RESTMapper, runtime.ObjectTyper) { +func NewLazyRESTMapperLoader(fn func() (RESTMapper, error)) RESTMapper { obj := &lazyObject{loader: fn} - return obj, obj + return obj } // init lazily loads the mapper and typer, returning an error if initialization has failed. @@ -49,13 +47,12 @@ func (o *lazyObject) init() error { if o.loaded { return o.err } - o.mapper, o.typer, o.err = o.loader() + o.mapper, o.err = o.loader() o.loaded = true return o.err } var _ RESTMapper = &lazyObject{} -var _ runtime.ObjectTyper = &lazyObject{} func (o *lazyObject) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { if err := o.init(); err != nil { @@ -105,17 +102,3 @@ func (o *lazyObject) ResourceSingularizer(resource string) (singular string, err } return o.mapper.ResourceSingularizer(resource) } - -func (o *lazyObject) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { - if err := o.init(); err != nil { - return nil, false, err - } - return o.typer.ObjectKinds(obj) -} - -func (o *lazyObject) Recognizes(gvk schema.GroupVersionKind) bool { - if err := o.init(); err != nil { - return false - } - return o.typer.Recognizes(gvk) -} diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/meta.go b/vendor/k8s.io/apimachinery/pkg/api/meta/meta.go index b9670071c..1c2a83cfa 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/meta.go +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/meta.go @@ -38,7 +38,6 @@ var errNotCommon = fmt.Errorf("object does not implement the common interface fo // CommonAccessor returns a Common interface for the provided object or an error if the object does // not provide List. -// TODO: return bool instead of error func CommonAccessor(obj interface{}) (metav1.Common, error) { switch t := obj.(type) { case List: @@ -71,7 +70,6 @@ func CommonAccessor(obj interface{}) (metav1.Common, error) { // not provide List. // IMPORTANT: Objects are NOT a superset of lists. Do not use this check to determine whether an // object *is* a List. -// TODO: return bool instead of error func ListAccessor(obj interface{}) (List, error) { switch t := obj.(type) { case List: @@ -101,7 +99,6 @@ var errNotObject = fmt.Errorf("object does not implement the Object interfaces") // obj must be a pointer to an API type. An error is returned if the minimum // required fields are missing. Fields that are not required return the default // value and are a no-op if set. -// TODO: return bool instead of error func Accessor(obj interface{}) (metav1.Object, error) { switch t := obj.(type) { case metav1.Object: diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/priority.go b/vendor/k8s.io/apimachinery/pkg/api/meta/priority.go index df28e64ff..fa11c580f 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/priority.go +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/priority.go @@ -54,12 +54,12 @@ func (m PriorityRESTMapper) String() string { // ResourceFor finds all resources, then passes them through the ResourcePriority patterns to find a single matching hit. func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupVersionResource) (schema.GroupVersionResource, error) { - originalGVRs, err := m.Delegate.ResourcesFor(partiallySpecifiedResource) - if err != nil { - return schema.GroupVersionResource{}, err + originalGVRs, originalErr := m.Delegate.ResourcesFor(partiallySpecifiedResource) + if originalErr != nil && len(originalGVRs) == 0 { + return schema.GroupVersionResource{}, originalErr } if len(originalGVRs) == 1 { - return originalGVRs[0], nil + return originalGVRs[0], originalErr } remainingGVRs := append([]schema.GroupVersionResource{}, originalGVRs...) @@ -77,7 +77,7 @@ func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupV continue case 1: // one match, return - return matchedGVRs[0], nil + return matchedGVRs[0], originalErr default: // more than one match, use the matched hits as the list moving to the next pattern. // this way you can have a series of selection criteria @@ -90,12 +90,12 @@ func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupV // KindFor finds all kinds, then passes them through the KindPriority patterns to find a single matching hit. func (m PriorityRESTMapper) KindFor(partiallySpecifiedResource schema.GroupVersionResource) (schema.GroupVersionKind, error) { - originalGVKs, err := m.Delegate.KindsFor(partiallySpecifiedResource) - if err != nil { - return schema.GroupVersionKind{}, err + originalGVKs, originalErr := m.Delegate.KindsFor(partiallySpecifiedResource) + if originalErr != nil && len(originalGVKs) == 0 { + return schema.GroupVersionKind{}, originalErr } if len(originalGVKs) == 1 { - return originalGVKs[0], nil + return originalGVKs[0], originalErr } remainingGVKs := append([]schema.GroupVersionKind{}, originalGVKs...) @@ -113,7 +113,7 @@ func (m PriorityRESTMapper) KindFor(partiallySpecifiedResource schema.GroupVersi continue case 1: // one match, return - return matchedGVKs[0], nil + return matchedGVKs[0], originalErr default: // more than one match, use the matched hits as the list moving to the next pattern. // this way you can have a series of selection criteria @@ -153,9 +153,9 @@ func kindMatches(pattern schema.GroupVersionKind, kind schema.GroupVersionKind) } func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (mapping *RESTMapping, err error) { - mappings, err := m.Delegate.RESTMappings(gk, versions...) - if err != nil { - return nil, err + mappings, originalErr := m.Delegate.RESTMappings(gk, versions...) + if originalErr != nil && len(mappings) == 0 { + return nil, originalErr } // any versions the user provides take priority @@ -187,7 +187,7 @@ func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) continue case 1: // one match, return - return matching[0], nil + return matching[0], originalErr default: // more than one match, use the matched hits as the list moving to the next pattern. // this way you can have a series of selection criteria @@ -195,7 +195,7 @@ func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) } } if len(remaining) == 1 { - return remaining[0], nil + return remaining[0], originalErr } var kinds []schema.GroupVersionKind diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/priority_test.go b/vendor/k8s.io/apimachinery/pkg/api/meta/priority_test.go index 098d53bd5..fff1afd17 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/priority_test.go +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/priority_test.go @@ -34,6 +34,30 @@ func TestPriorityRESTMapperResourceForErrorHandling(t *testing.T) { result schema.GroupVersionResource err string }{ + { + name: "error", + delegate: fixedRESTMapper{err: errors.New("delegateError")}, + err: "delegateError", + }, + { + name: "single hit + error", + delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "single-hit"}}, err: errors.New("delegateError")}, + result: schema.GroupVersionResource{Resource: "single-hit"}, + err: "delegateError", + }, + { + name: "group selection + error", + delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{ + {Group: "one", Version: "a", Resource: "first"}, + {Group: "two", Version: "b", Resource: "second"}, + }, err: errors.New("delegateError")}, + resourcePatterns: []schema.GroupVersionResource{ + {Group: "one", Version: AnyVersion, Resource: AnyResource}, + }, + result: schema.GroupVersionResource{Group: "one", Version: "a", Resource: "first"}, + err: "delegateError", + }, + { name: "single hit", delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "single-hit"}}}, @@ -106,6 +130,10 @@ func TestPriorityRESTMapperResourceForErrorHandling(t *testing.T) { if len(tc.err) == 0 && actualErr == nil { continue } + if len(tc.err) == 0 && actualErr != nil { + t.Errorf("%s: unexpected err: %v", tc.name, actualErr) + continue + } if len(tc.err) > 0 && actualErr == nil { t.Errorf("%s: missing expected err: %v", tc.name, tc.err) continue @@ -125,6 +153,30 @@ func TestPriorityRESTMapperKindForErrorHandling(t *testing.T) { result schema.GroupVersionKind err string }{ + { + name: "error", + delegate: fixedRESTMapper{err: errors.New("delegateErr")}, + err: "delegateErr", + }, + { + name: "single hit + error", + delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "single-hit"}}, err: errors.New("delegateErr")}, + result: schema.GroupVersionKind{Kind: "single-hit"}, + err: "delegateErr", + }, + { + name: "group selection + error", + delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{ + {Group: "one", Version: "a", Kind: "first"}, + {Group: "two", Version: "b", Kind: "second"}, + }, err: errors.New("delegateErr")}, + kindPatterns: []schema.GroupVersionKind{ + {Group: "one", Version: AnyVersion, Kind: AnyKind}, + }, + result: schema.GroupVersionKind{Group: "one", Version: "a", Kind: "first"}, + err: "delegateErr", + }, + { name: "single hit", delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "single-hit"}}}, @@ -197,6 +249,10 @@ func TestPriorityRESTMapperKindForErrorHandling(t *testing.T) { if len(tc.err) == 0 && actualErr == nil { continue } + if len(tc.err) == 0 && actualErr != nil { + t.Errorf("%s: unexpected err: %v", tc.name, actualErr) + continue + } if len(tc.err) > 0 && actualErr == nil { t.Errorf("%s: missing expected err: %v", tc.name, tc.err) continue @@ -248,6 +304,13 @@ func TestPriorityRESTMapperRESTMapping(t *testing.T) { input: schema.GroupKind{Kind: "Foo"}, err: errors.New("fail on this"), }, + { + name: "result + error", + mapper: PriorityRESTMapper{Delegate: fixedRESTMapper{mappings: []*RESTMapping{mapping1}, err: errors.New("fail on this")}}, + input: schema.GroupKind{Kind: "Foo"}, + result: mapping1, + err: errors.New("fail on this"), + }, { name: "return error for ambiguous", mapper: PriorityRESTMapper{ diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/restmapper.go b/vendor/k8s.io/apimachinery/pkg/api/meta/restmapper.go index ff945acd1..41b60d731 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/restmapper.go +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/restmapper.go @@ -28,30 +28,15 @@ import ( // Implements RESTScope interface type restScope struct { - name RESTScopeName - paramName string - argumentName string - paramDescription string + name RESTScopeName } func (r *restScope) Name() RESTScopeName { return r.name } -func (r *restScope) ParamName() string { - return r.paramName -} -func (r *restScope) ArgumentName() string { - return r.argumentName -} -func (r *restScope) ParamDescription() string { - return r.paramDescription -} var RESTScopeNamespace = &restScope{ - name: RESTScopeNameNamespace, - paramName: "namespaces", - argumentName: "namespace", - paramDescription: "object name and auth scope, such as for teams and projects", + name: RESTScopeNameNamespace, } var RESTScopeRoot = &restScope{ @@ -77,8 +62,6 @@ type DefaultRESTMapper struct { kindToScope map[schema.GroupVersionKind]RESTScope singularToPlural map[schema.GroupVersionResource]schema.GroupVersionResource pluralToSingular map[schema.GroupVersionResource]schema.GroupVersionResource - - interfacesFunc VersionInterfacesFunc } func (m *DefaultRESTMapper) String() string { @@ -87,16 +70,12 @@ func (m *DefaultRESTMapper) String() string { var _ RESTMapper = &DefaultRESTMapper{} -// VersionInterfacesFunc returns the appropriate typer, and metadata accessor for a -// given api version, or an error if no such api version exists. -type VersionInterfacesFunc func(version schema.GroupVersion) (*VersionInterfaces, error) - // NewDefaultRESTMapper initializes a mapping between Kind and APIVersion // to a resource name and back based on the objects in a runtime.Scheme // and the Kubernetes API conventions. Takes a group name, a priority list of the versions // to search when an object has no default version (set empty to return an error), // and a function that retrieves the correct metadata for a given version. -func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion, f VersionInterfacesFunc) *DefaultRESTMapper { +func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion) *DefaultRESTMapper { resourceToKind := make(map[schema.GroupVersionResource]schema.GroupVersionKind) kindToPluralResource := make(map[schema.GroupVersionKind]schema.GroupVersionResource) kindToScope := make(map[schema.GroupVersionKind]RESTScope) @@ -111,7 +90,6 @@ func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion, f VersionI defaultGroupVersions: defaultGroupVersions, singularToPlural: singularToPlural, pluralToSingular: pluralToSingular, - interfacesFunc: f, } } @@ -526,18 +504,10 @@ func (m *DefaultRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported scope", gvk.GroupVersion(), gvk.Kind) } - interfaces, err := m.interfacesFunc(gvk.GroupVersion()) - if err != nil { - return nil, fmt.Errorf("the provided version %q has no relevant versions: %v", gvk.GroupVersion().String(), err) - } - mappings = append(mappings, &RESTMapping{ - Resource: res.Resource, + Resource: res, GroupVersionKind: gvk, Scope: scope, - - ObjectConvertor: interfaces.ObjectConvertor, - MetadataAccessor: interfaces.MetadataAccessor, }) } diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/restmapper_test.go b/vendor/k8s.io/apimachinery/pkg/api/meta/restmapper_test.go index 1b1c70d65..853404ad6 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/restmapper_test.go +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/restmapper_test.go @@ -17,42 +17,13 @@ limitations under the License. package meta import ( - "errors" "reflect" "strings" "testing" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) -type fakeConvertor struct{} - -func (fakeConvertor) Convert(in, out, context interface{}) error { - return nil -} - -func (fakeConvertor) ConvertToVersion(in runtime.Object, _ runtime.GroupVersioner) (runtime.Object, error) { - return in, nil -} - -func (fakeConvertor) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { - return label, value, nil -} - -var validAccessor = resourceAccessor{} -var validConvertor = fakeConvertor{} - -func fakeInterfaces(version schema.GroupVersion) (*VersionInterfaces, error) { - return &VersionInterfaces{ObjectConvertor: validConvertor, MetadataAccessor: validAccessor}, nil -} - -var unmatchedErr = errors.New("no version") - -func unmatchedVersionInterfaces(version schema.GroupVersion) (*VersionInterfaces, error) { - return nil, unmatchedErr -} - func TestRESTMapperVersionAndKindForResource(t *testing.T) { testGroup := "test.group" testVersion := "test" @@ -71,7 +42,7 @@ func TestRESTMapperVersionAndKindForResource(t *testing.T) { {Resource: schema.GroupVersionResource{Resource: "internalobjects"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}, fakeInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}) if len(testCase.ExpectedGVK.Kind) != 0 { mapper.Add(testCase.ExpectedGVK, RESTScopeNamespace) } @@ -104,7 +75,7 @@ func TestRESTMapperGroupForResource(t *testing.T) { {Resource: schema.GroupVersionResource{Resource: "myobje"}, Err: true, GroupVersionKind: schema.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}}, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper([]schema.GroupVersion{testCase.GroupVersionKind.GroupVersion()}, fakeInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{testCase.GroupVersionKind.GroupVersion()}) mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace) actualGVK, err := mapper.KindFor(testCase.Resource) @@ -249,7 +220,7 @@ func TestRESTMapperKindsFor(t *testing.T) { } for _, testCase := range testCases { tcName := testCase.Name - mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces) + mapper := NewDefaultRESTMapper(testCase.PreferredOrder) for _, kind := range testCase.KindsToRegister { mapper.Add(kind, RESTScopeNamespace) } @@ -426,7 +397,7 @@ func TestRESTMapperResourcesFor(t *testing.T) { tcName := testCase.Name for _, partialResource := range []schema.GroupVersionResource{testCase.PluralPartialResourceToRequest, testCase.SingularPartialResourceToRequest} { - mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces) + mapper := NewDefaultRESTMapper(testCase.PreferredOrder) for _, kind := range testCase.KindsToRegister { mapper.Add(kind, RESTScopeNamespace) } @@ -511,7 +482,7 @@ func TestRESTMapperResourceSingularizer(t *testing.T) { {Kind: "lowercases", Plural: "lowercaseses", Singular: "lowercases"}, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}, fakeInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}) // create singular/plural mapping mapper.Add(testGroupVersion.WithKind(testCase.Kind), RESTScopeNamespace) @@ -535,7 +506,7 @@ func TestRESTMapperRESTMapping(t *testing.T) { APIGroupVersions []schema.GroupVersion DefaultVersions []schema.GroupVersion - Resource string + Resource schema.GroupVersionResource ExpectedGroupVersion *schema.GroupVersion Err bool }{ @@ -544,19 +515,19 @@ func TestRESTMapperRESTMapping(t *testing.T) { {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "Unknown", Err: true}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{}, Resource: "internalobjects", ExpectedGroupVersion: &schema.GroupVersion{Group: testGroup, Version: "test"}}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{}, Resource: internalGroupVersion.WithResource("internalobjects"), ExpectedGroupVersion: &schema.GroupVersion{Group: testGroup, Version: "test"}}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")}, // TODO: add test for a resource that exists in one version but not another } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces) + mapper := NewDefaultRESTMapper(testCase.DefaultVersions) mapper.Add(internalGroupVersion.WithKind("InternalObject"), RESTScopeNamespace) preferredVersions := []string{} @@ -577,10 +548,6 @@ func TestRESTMapperRESTMapping(t *testing.T) { t.Errorf("%d: unexpected resource: %#v", i, mapping) } - if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil { - t.Errorf("%d: missing codec and accessor: %#v", i, mapping) - } - groupVersion := testCase.ExpectedGroupVersion if groupVersion == nil { groupVersion = &testCase.APIGroupVersions[0] @@ -599,7 +566,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { internalObjectGK := schema.GroupKind{Group: "tgroup", Kind: "InternalObject"} otherObjectGK := schema.GroupKind{Group: "tgroup", Kind: "OtherObject"} - mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, fakeInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}) mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace) mapper.Add(expectedGroupVersion2.WithKind("OtherObject"), RESTScopeNamespace) @@ -608,7 +575,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { + if mapping.Resource != expectedGroupVersion2.WithResource("otherobjects") || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { t.Errorf("unexpected mapping: %#v", mapping) } @@ -616,7 +583,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.Resource != "internalobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion1 { + if mapping.Resource != expectedGroupVersion1.WithResource("internalobjects") || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion1 { t.Errorf("unexpected mapping: %#v", mapping) } @@ -646,7 +613,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { + if mapping.Resource != expectedGroupVersion2.WithResource("otherobjects") || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { t.Errorf("unexpected mapping: %#v", mapping) } } @@ -678,7 +645,7 @@ func TestRESTMapperRESTMappings(t *testing.T) { Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "v2"}}, AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")}, - ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, + ExpectedRESTMappings: []*RESTMapping{{Resource: schema.GroupVersionResource{Group: testGroup, Version: "v2", Resource: "internalobjects"}, GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, }, // ask for specific versions - only one available - check ExpectedRESTMappings @@ -687,20 +654,29 @@ func TestRESTMapperRESTMappings(t *testing.T) { Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "v3"}, {Group: testGroup, Version: "v2"}}, AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")}, - ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, + ExpectedRESTMappings: []*RESTMapping{{Resource: schema.GroupVersionResource{Group: testGroup, Version: "v2", Resource: "internalobjects"}, GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, }, // do not ask for specific version - search through default versions - check ExpectedRESTMappings { - DefaultVersions: []schema.GroupVersion{testGroupVersion, {Group: testGroup, Version: "v2"}}, - Kind: "InternalObject", - AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v1"}.WithKind("InternalObject"), schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")}, - ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v1", Kind: "InternalObject"}}, {Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, + DefaultVersions: []schema.GroupVersion{testGroupVersion, {Group: testGroup, Version: "v2"}}, + Kind: "InternalObject", + AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v1"}.WithKind("InternalObject"), schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")}, + ExpectedRESTMappings: []*RESTMapping{ + { + Resource: schema.GroupVersionResource{Group: testGroup, Version: "v1", Resource: "internalobjects"}, + GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v1", Kind: "InternalObject"}, + }, + { + Resource: schema.GroupVersionResource{Group: testGroup, Version: "v2", Resource: "internalobjects"}, + GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}, + }, + }, }, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces) + mapper := NewDefaultRESTMapper(testCase.DefaultVersions) for _, gvk := range testCase.AddGroupVersionKind { mapper.Add(gvk, RESTScopeNamespace) } @@ -727,9 +703,6 @@ func TestRESTMapperRESTMappings(t *testing.T) { if mapping.Resource != exp.Resource { t.Errorf("%d - %d: unexpected resource: %#v", i, j, mapping) } - if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil { - t.Errorf("%d - %d: missing codec and accessor: %#v", i, j, mapping) - } if mapping.GroupVersionKind != exp.GroupVersionKind { t.Errorf("%d - %d: unexpected GroupVersionKind: %#v", i, j, mapping) } @@ -742,9 +715,9 @@ func TestRESTMapperReportsErrorOnBadVersion(t *testing.T) { expectedGroupVersion2 := schema.GroupVersion{Group: "tgroup", Version: "test2"} internalObjectGK := schema.GroupKind{Group: "tgroup", Kind: "InternalObject"} - mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, unmatchedVersionInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}) mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace) - _, err := mapper.RESTMapping(internalObjectGK, expectedGroupVersion1.Version) + _, err := mapper.RESTMapping(internalObjectGK, "test3") if err == nil { t.Errorf("unexpected non-error") } diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/table/table.go b/vendor/k8s.io/apimachinery/pkg/api/meta/table/table.go index a0097a4e2..2144a77cb 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/table/table.go +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/table/table.go @@ -53,7 +53,7 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1. row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells, err = rowFn(obj, m, m.GetName(), translateTimestamp(m.GetCreationTimestamp())) + row.Cells, err = rowFn(obj, m, m.GetName(), ConvertToHumanReadableDateType(m.GetCreationTimestamp())) if err != nil { return nil, err } @@ -61,9 +61,9 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1. return rows, nil } -// translateTimestamp returns the elapsed time since timestamp in +// ConvertToHumanReadableDateType returns the elapsed time since timestamp in // human-readable approximation. -func translateTimestamp(timestamp metav1.Time) string { +func ConvertToHumanReadableDateType(timestamp metav1.Time) string { if timestamp.IsZero() { return "" } diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper/test_restmapper.go b/vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper/test_restmapper.go new file mode 100644 index 000000000..a08b42b82 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper/test_restmapper.go @@ -0,0 +1,171 @@ +/* +Copyright 2018 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 testrestmapper + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/sets" +) + +// TestOnlyStaticRESTMapper returns a union RESTMapper of all known types with priorities chosen in the following order: +// 1. legacy kube group preferred version, extensions preferred version, metrics perferred version, legacy +// kube any version, extensions any version, metrics any version, all other groups alphabetical preferred version, +// all other groups alphabetical. +// TODO callers of this method should be updated to build their own specific restmapper based on their scheme for their tests +// TODO the things being tested are related to whether various cases are handled, not tied to the particular types being checked. +func TestOnlyStaticRESTMapper(scheme *runtime.Scheme, versionPatterns ...schema.GroupVersion) meta.RESTMapper { + unionMapper := meta.MultiRESTMapper{} + unionedGroups := sets.NewString() + for _, enabledVersion := range scheme.PrioritizedVersionsAllGroups() { + if !unionedGroups.Has(enabledVersion.Group) { + unionedGroups.Insert(enabledVersion.Group) + unionMapper = append(unionMapper, newRESTMapper(enabledVersion.Group, scheme)) + } + } + + if len(versionPatterns) != 0 { + resourcePriority := []schema.GroupVersionResource{} + kindPriority := []schema.GroupVersionKind{} + for _, versionPriority := range versionPatterns { + resourcePriority = append(resourcePriority, versionPriority.WithResource(meta.AnyResource)) + kindPriority = append(kindPriority, versionPriority.WithKind(meta.AnyKind)) + } + + return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} + } + + prioritizedGroups := []string{"", "extensions", "metrics"} + resourcePriority, kindPriority := prioritiesForGroups(scheme, prioritizedGroups...) + + prioritizedGroupsSet := sets.NewString(prioritizedGroups...) + remainingGroups := sets.String{} + for _, enabledVersion := range scheme.PrioritizedVersionsAllGroups() { + if !prioritizedGroupsSet.Has(enabledVersion.Group) { + remainingGroups.Insert(enabledVersion.Group) + } + } + + remainingResourcePriority, remainingKindPriority := prioritiesForGroups(scheme, remainingGroups.List()...) + resourcePriority = append(resourcePriority, remainingResourcePriority...) + kindPriority = append(kindPriority, remainingKindPriority...) + + return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} +} + +// prioritiesForGroups returns the resource and kind priorities for a PriorityRESTMapper, preferring the preferred version of each group first, +// then any non-preferred version of the group second. +func prioritiesForGroups(scheme *runtime.Scheme, groups ...string) ([]schema.GroupVersionResource, []schema.GroupVersionKind) { + resourcePriority := []schema.GroupVersionResource{} + kindPriority := []schema.GroupVersionKind{} + + for _, group := range groups { + availableVersions := scheme.PrioritizedVersionsForGroup(group) + if len(availableVersions) > 0 { + resourcePriority = append(resourcePriority, availableVersions[0].WithResource(meta.AnyResource)) + kindPriority = append(kindPriority, availableVersions[0].WithKind(meta.AnyKind)) + } + } + for _, group := range groups { + resourcePriority = append(resourcePriority, schema.GroupVersionResource{Group: group, Version: meta.AnyVersion, Resource: meta.AnyResource}) + kindPriority = append(kindPriority, schema.GroupVersionKind{Group: group, Version: meta.AnyVersion, Kind: meta.AnyKind}) + } + + return resourcePriority, kindPriority +} + +func newRESTMapper(group string, scheme *runtime.Scheme) meta.RESTMapper { + mapper := meta.NewDefaultRESTMapper(scheme.PrioritizedVersionsForGroup(group)) + for _, gv := range scheme.PrioritizedVersionsForGroup(group) { + for kind := range scheme.KnownTypes(gv) { + if ignoredKinds.Has(kind) { + continue + } + scope := meta.RESTScopeNamespace + if rootScopedKinds[gv.WithKind(kind).GroupKind()] { + scope = meta.RESTScopeRoot + } + mapper.Add(gv.WithKind(kind), scope) + } + } + + return mapper +} + +// hardcoded is good enough for the test we're running +var rootScopedKinds = map[schema.GroupKind]bool{ + {Group: "admission.k8s.io", Kind: "AdmissionReview"}: true, + + {Group: "admissionregistration.k8s.io", Kind: "InitializerConfiguration"}: true, + {Group: "admissionregistration.k8s.io", Kind: "ValidatingWebhookConfiguration"}: true, + {Group: "admissionregistration.k8s.io", Kind: "MutatingWebhookConfiguration"}: true, + + {Group: "authentication.k8s.io", Kind: "TokenReview"}: true, + + {Group: "authorization.k8s.io", Kind: "SubjectAccessReview"}: true, + {Group: "authorization.k8s.io", Kind: "SelfSubjectAccessReview"}: true, + {Group: "authorization.k8s.io", Kind: "SelfSubjectRulesReview"}: true, + + {Group: "certificates.k8s.io", Kind: "CertificateSigningRequest"}: true, + + {Group: "", Kind: "Node"}: true, + {Group: "", Kind: "Namespace"}: true, + {Group: "", Kind: "PersistentVolume"}: true, + {Group: "", Kind: "ComponentStatus"}: true, + + {Group: "extensions", Kind: "PodSecurityPolicy"}: true, + + {Group: "policy", Kind: "PodSecurityPolicy"}: true, + + {Group: "extensions", Kind: "PodSecurityPolicy"}: true, + + {Group: "rbac.authorization.k8s.io", Kind: "ClusterRole"}: true, + {Group: "rbac.authorization.k8s.io", Kind: "ClusterRoleBinding"}: true, + + {Group: "scheduling.k8s.io", Kind: "PriorityClass"}: true, + + {Group: "storage.k8s.io", Kind: "StorageClass"}: true, + {Group: "storage.k8s.io", Kind: "VolumeAttachment"}: true, + + {Group: "apiextensions.k8s.io", Kind: "CustomResourceDefinition"}: true, + + {Group: "apiserver.k8s.io", Kind: "AdmissionConfiguration"}: true, + + {Group: "audit.k8s.io", Kind: "Event"}: true, + {Group: "audit.k8s.io", Kind: "Policy"}: true, + + {Group: "apiregistration.k8s.io", Kind: "APIService"}: true, + + {Group: "metrics.k8s.io", Kind: "NodeMetrics"}: true, + + {Group: "wardle.k8s.io", Kind: "Fischer"}: true, +} + +// hardcoded is good enough for the test we're running +var ignoredKinds = sets.NewString( + "ListOptions", + "DeleteOptions", + "Status", + "PodLogOptions", + "PodExecOptions", + "PodAttachOptions", + "PodPortForwardOptions", + "PodProxyOptions", + "NodeProxyOptions", + "ServiceProxyOptions", +) diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/unstructured.go b/vendor/k8s.io/apimachinery/pkg/api/meta/unstructured.go deleted file mode 100644 index 4e13efea3..000000000 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/unstructured.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -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 meta - -import ( - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// InterfacesForUnstructuredConversion returns VersionInterfaces suitable for -// dealing with unstructured.Unstructured objects and supports conversion -// from typed objects (provided by parent) to untyped objects. -func InterfacesForUnstructuredConversion(parent VersionInterfacesFunc) VersionInterfacesFunc { - return func(version schema.GroupVersion) (*VersionInterfaces, error) { - if i, err := parent(version); err == nil { - return &VersionInterfaces{ - ObjectConvertor: i.ObjectConvertor, - MetadataAccessor: NewAccessor(), - }, nil - } - return InterfacesForUnstructured(version) - } -} - -// InterfacesForUnstructured returns VersionInterfaces suitable for -// dealing with unstructured.Unstructured objects. It will return errors for -// other conversions. -func InterfacesForUnstructured(schema.GroupVersion) (*VersionInterfaces, error) { - return &VersionInterfaces{ - ObjectConvertor: &unstructured.UnstructuredObjectConverter{}, - MetadataAccessor: NewAccessor(), - }, nil -} diff --git a/vendor/k8s.io/apimachinery/pkg/api/resource/generated.pb.go b/vendor/k8s.io/apimachinery/pkg/api/resource/generated.pb.go index 6de71e508..802f22a63 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/resource/generated.pb.go +++ b/vendor/k8s.io/apimachinery/pkg/api/resource/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,13 +19,13 @@ limitations under the License. // DO NOT EDIT! /* - Package resource is a generated protocol buffer package. +Package resource is a generated protocol buffer package. - It is generated from these files: - k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto +It is generated from these files: + k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto - It has these top-level messages: - Quantity +It has these top-level messages: + Quantity */ package resource @@ -57,21 +57,20 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 255 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x8f, 0xa1, 0x4e, 0x03, 0x41, - 0x10, 0x86, 0x77, 0x0d, 0x29, 0x95, 0x0d, 0x21, 0xa4, 0x62, 0xaf, 0x21, 0x08, 0x0c, 0x3b, 0x02, - 0xd3, 0x20, 0xf1, 0x08, 0x90, 0xb8, 0xbb, 0xeb, 0xb0, 0xdd, 0x1c, 0xdd, 0xbd, 0xcc, 0xce, 0x92, - 0xd4, 0x55, 0x22, 0x2b, 0x91, 0xbd, 0xb7, 0xa9, 0xac, 0xac, 0x40, 0x70, 0xcb, 0x8b, 0x90, 0x5e, - 0xdb, 0x84, 0x90, 0xe0, 0xe6, 0xfb, 0x27, 0xdf, 0xe4, 0x9f, 0xfe, 0x43, 0x35, 0x0e, 0xda, 0x7a, - 0xa8, 0x62, 0x81, 0xe4, 0x90, 0x31, 0xc0, 0x1b, 0xba, 0x89, 0x27, 0x38, 0x2c, 0xf2, 0xda, 0xce, - 0xf2, 0x72, 0x6a, 0x1d, 0xd2, 0x1c, 0xea, 0xca, 0xec, 0x02, 0x20, 0x0c, 0x3e, 0x52, 0x89, 0x60, - 0xd0, 0x21, 0xe5, 0x8c, 0x13, 0x5d, 0x93, 0x67, 0x3f, 0xb8, 0xda, 0x5b, 0xfa, 0xb7, 0xa5, 0xeb, - 0xca, 0xec, 0x02, 0x7d, 0xb4, 0x86, 0x37, 0xc6, 0xf2, 0x34, 0x16, 0xba, 0xf4, 0x33, 0x30, 0xde, - 0x78, 0xe8, 0xe4, 0x22, 0xbe, 0x74, 0xd4, 0x41, 0x37, 0xed, 0x8f, 0x0e, 0x6f, 0xff, 0xab, 0x12, - 0xd9, 0xbe, 0x82, 0x75, 0x1c, 0x98, 0xfe, 0x36, 0xb9, 0x1c, 0xf7, 0x7b, 0x8f, 0x31, 0x77, 0x6c, - 0x79, 0x3e, 0x38, 0xef, 0x9f, 0x04, 0x26, 0xeb, 0xcc, 0x85, 0x1c, 0xc9, 0xeb, 0xd3, 0xa7, 0x03, - 0xdd, 0x9d, 0x7d, 0xac, 0x32, 0xf1, 0xde, 0x64, 0x62, 0xd9, 0x64, 0x62, 0xd5, 0x64, 0x62, 0xf1, - 0x39, 0x12, 0xf7, 0x7a, 0xdd, 0x2a, 0xb1, 0x69, 0x95, 0xd8, 0xb6, 0x4a, 0x2c, 0x92, 0x92, 0xeb, - 0xa4, 0xe4, 0x26, 0x29, 0xb9, 0x4d, 0x4a, 0x7e, 0x25, 0x25, 0x97, 0xdf, 0x4a, 0x3c, 0xf7, 0x8e, - 0xdf, 0xfc, 0x04, 0x00, 0x00, 0xff, 0xff, 0x5f, 0x5e, 0xda, 0xf9, 0x43, 0x01, 0x00, 0x00, + // 237 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x8e, 0xb1, 0x4e, 0xc3, 0x30, + 0x10, 0x40, 0xcf, 0x0b, 0x2a, 0x19, 0x2b, 0x84, 0x10, 0xc3, 0xa5, 0x42, 0x0c, 0x2c, 0xd8, 0x6b, + 0xc5, 0xc8, 0xce, 0x00, 0x23, 0x5b, 0x92, 0x1e, 0xae, 0x15, 0xd5, 0x8e, 0x2e, 0x36, 0x52, 0xb7, + 0x8e, 0x8c, 0x1d, 0x19, 0x9b, 0xbf, 0xe9, 0xd8, 0xb1, 0x03, 0x03, 0x31, 0x3f, 0x82, 0xea, 0x36, + 0x52, 0xb7, 0x7b, 0xef, 0xf4, 0x4e, 0x97, 0xbd, 0xd4, 0xd3, 0x56, 0x1a, 0xa7, 0xea, 0x50, 0x12, + 0x5b, 0xf2, 0xd4, 0xaa, 0x4f, 0xb2, 0x33, 0xc7, 0xea, 0xb4, 0x28, 0x1a, 0xb3, 0x28, 0xaa, 0xb9, + 0xb1, 0xc4, 0x4b, 0xd5, 0xd4, 0xfa, 0x20, 0x14, 0x53, 0xeb, 0x02, 0x57, 0xa4, 0x34, 0x59, 0xe2, + 0xc2, 0xd3, 0x4c, 0x36, 0xec, 0xbc, 0x1b, 0xdf, 0x1f, 0x2b, 0x79, 0x5e, 0xc9, 0xa6, 0xd6, 0x07, + 0x21, 0x87, 0xea, 0xf6, 0x51, 0x1b, 0x3f, 0x0f, 0xa5, 0xac, 0xdc, 0x42, 0x69, 0xa7, 0x9d, 0x4a, + 0x71, 0x19, 0x3e, 0x12, 0x25, 0x48, 0xd3, 0xf1, 0xe8, 0xdd, 0x34, 0x1b, 0xbd, 0x86, 0xc2, 0x7a, + 0xe3, 0x97, 0xe3, 0xeb, 0xec, 0xa2, 0xf5, 0x6c, 0xac, 0xbe, 0x11, 0x13, 0xf1, 0x70, 0xf9, 0x76, + 0xa2, 0xa7, 0xab, 0xef, 0x4d, 0x0e, 0x5f, 0x5d, 0x0e, 0xeb, 0x2e, 0x87, 0x4d, 0x97, 0xc3, 0xea, + 0x67, 0x02, 0xcf, 0x72, 0xdb, 0x23, 0xec, 0x7a, 0x84, 0x7d, 0x8f, 0xb0, 0x8a, 0x28, 0xb6, 0x11, + 0xc5, 0x2e, 0xa2, 0xd8, 0x47, 0x14, 0xbf, 0x11, 0xc5, 0xfa, 0x0f, 0xe1, 0x7d, 0x34, 0x3c, 0xf6, + 0x1f, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x08, 0x88, 0x49, 0x0e, 0x01, 0x00, 0x00, } diff --git a/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto b/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto index 40185777e..2c0aaa45b 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto +++ b/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,8 +21,6 @@ syntax = 'proto2'; package k8s.io.apimachinery.pkg.api.resource; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - // Package-wide variables from generator "generated". option go_package = "resource"; diff --git a/vendor/k8s.io/apimachinery/pkg/api/resource/quantity.go b/vendor/k8s.io/apimachinery/pkg/api/resource/quantity.go index 6a8bb9972..c3cd13960 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/resource/quantity.go +++ b/vendor/k8s.io/apimachinery/pkg/api/resource/quantity.go @@ -25,8 +25,6 @@ import ( "strconv" "strings" - flag "github.com/spf13/pflag" - inf "gopkg.in/inf.v0" ) @@ -747,43 +745,3 @@ func (q *Quantity) Copy() *Quantity { Format: q.Format, } } - -// qFlag is a helper type for the Flag function -type qFlag struct { - dest *Quantity -} - -// Sets the value of the internal Quantity. (used by flag & pflag) -func (qf qFlag) Set(val string) error { - q, err := ParseQuantity(val) - if err != nil { - return err - } - // This copy is OK because q will not be referenced again. - *qf.dest = q - return nil -} - -// Converts the value of the internal Quantity to a string. (used by flag & pflag) -func (qf qFlag) String() string { - return qf.dest.String() -} - -// States the type of flag this is (Quantity). (used by pflag) -func (qf qFlag) Type() string { - return "quantity" -} - -// QuantityFlag is a helper that makes a quantity flag (using standard flag package). -// Will panic if defaultValue is not a valid quantity. -func QuantityFlag(flagName, defaultValue, description string) *Quantity { - q := MustParse(defaultValue) - flag.Var(NewQuantityFlagValue(&q), flagName, description) - return &q -} - -// NewQuantityFlagValue returns an object that can be used to back a flag, -// pointing at the given Quantity variable. -func NewQuantityFlagValue(q *Quantity) flag.Value { - return qFlag{q} -} diff --git a/vendor/k8s.io/apimachinery/pkg/api/resource/quantity_test.go b/vendor/k8s.io/apimachinery/pkg/api/resource/quantity_test.go index 74f091a38..915b2444e 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/resource/quantity_test.go +++ b/vendor/k8s.io/apimachinery/pkg/api/resource/quantity_test.go @@ -24,7 +24,6 @@ import ( "unicode" fuzz "github.com/google/gofuzz" - "github.com/spf13/pflag" inf "gopkg.in/inf.v0" ) @@ -1059,21 +1058,6 @@ func TestCopy(t *testing.T) { } } -func TestQFlagSet(t *testing.T) { - qf := qFlag{&Quantity{}} - qf.Set("1Ki") - if e, a := "1Ki", qf.String(); e != a { - t.Errorf("Unexpected result %v != %v", e, a) - } -} - -func TestQFlagIsPFlag(t *testing.T) { - var pfv pflag.Value = qFlag{} - if e, a := "quantity", pfv.Type(); e != a { - t.Errorf("Unexpected result %v != %v", e, a) - } -} - func TestSub(t *testing.T) { tests := []struct { a Quantity diff --git a/vendor/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go index fc36d9811..ab4740790 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip/roundtrip.go b/vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip/roundtrip.go index 0c032b815..f8b12aa85 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip/roundtrip.go +++ b/vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip/roundtrip.go @@ -33,8 +33,6 @@ import ( apimeta "k8s.io/apimachinery/pkg/api/meta" apitesting "k8s.io/apimachinery/pkg/api/testing" "k8s.io/apimachinery/pkg/api/testing/fuzzer" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,15 +43,13 @@ import ( "k8s.io/apimachinery/pkg/util/sets" ) -type InstallFunc func(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) +type InstallFunc func(scheme *runtime.Scheme) // RoundTripTestForAPIGroup is convenient to call from your install package to make sure that a "bare" install of your group provides // enough information to round trip func RoundTripTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs fuzzer.FuzzerFuncs) { - groupFactoryRegistry := make(announced.APIGroupFactoryRegistry) - registry := registered.NewOrDie("") scheme := runtime.NewScheme() - installFn(groupFactoryRegistry, registry, scheme) + installFn(scheme) RoundTripTestForScheme(t, scheme, fuzzingFuncs) } @@ -72,10 +68,8 @@ func RoundTripTestForScheme(t *testing.T, scheme *runtime.Scheme, fuzzingFuncs f // RoundTripProtobufTestForAPIGroup is convenient to call from your install package to make sure that a "bare" install of your group provides // enough information to round trip func RoundTripProtobufTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs fuzzer.FuzzerFuncs) { - groupFactoryRegistry := make(announced.APIGroupFactoryRegistry) - registry := registered.NewOrDie("") scheme := runtime.NewScheme() - installFn(groupFactoryRegistry, registry, scheme) + installFn(scheme) RoundTripProtobufTestForScheme(t, scheme, fuzzingFuncs) } @@ -138,6 +132,24 @@ func roundTripTypes(t *testing.T, scheme *runtime.Scheme, codecFactory runtimese } } +// RoundTripExternalTypes applies the round-trip test to all external round-trippable Kinds +// in the scheme. It will skip all the GroupVersionKinds in the nonRoundTripExternalTypes list . +func RoundTripExternalTypes(t *testing.T, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) { + kinds := scheme.AllKnownTypes() + for gvk := range kinds { + if gvk.Version == runtime.APIVersionInternal || globalNonRoundTrippableTypes.Has(gvk.Kind) { + continue + } + + // FIXME: this is explicitly testing w/o protobuf which was failing if enabled + // the reason for that is that protobuf is not setting Kind and APIVersion fields + // during obj2 decode, the same then applies to DecodeInto obj3. My guess is we + // should be setting these two fields accordingly when protobuf is passed as codec + // to roundTrip method. + roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true) + } +} + func RoundTripSpecificKindWithoutProtobuf(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) { roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true) } diff --git a/vendor/k8s.io/apimachinery/pkg/api/validation/objectmeta.go b/vendor/k8s.io/apimachinery/pkg/api/validation/objectmeta.go index 3c32a937a..44b9b1600 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/validation/objectmeta.go +++ b/vendor/k8s.io/apimachinery/pkg/api/validation/objectmeta.go @@ -30,10 +30,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ) -// TODO: delete this global variable when we enable the validation of common -// fields by default. -var RepairMalformedUpdates bool = true - const FieldImmutableErrorMsg string = `field is immutable` const totalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB @@ -254,39 +250,6 @@ func ValidateObjectMetaUpdate(newMeta, oldMeta *metav1.ObjectMeta, fldPath *fiel func ValidateObjectMetaAccessorUpdate(newMeta, oldMeta metav1.Object, fldPath *field.Path) field.ErrorList { var allErrs field.ErrorList - if !RepairMalformedUpdates && newMeta.GetUID() != oldMeta.GetUID() { - allErrs = append(allErrs, field.Invalid(fldPath.Child("uid"), newMeta.GetUID(), "field is immutable")) - } - // in the event it is left empty, set it, to allow clients more flexibility - // TODO: remove the following code that repairs the update request when we retire the clients that modify the immutable fields. - // Please do not copy this pattern elsewhere; validation functions should not be modifying the objects they are passed! - if RepairMalformedUpdates { - if len(newMeta.GetUID()) == 0 { - newMeta.SetUID(oldMeta.GetUID()) - } - // ignore changes to timestamp - if oldCreationTime := oldMeta.GetCreationTimestamp(); oldCreationTime.IsZero() { - oldMeta.SetCreationTimestamp(newMeta.GetCreationTimestamp()) - } else { - newMeta.SetCreationTimestamp(oldMeta.GetCreationTimestamp()) - } - // an object can never remove a deletion timestamp or clear/change grace period seconds - if !oldMeta.GetDeletionTimestamp().IsZero() { - newMeta.SetDeletionTimestamp(oldMeta.GetDeletionTimestamp()) - } - if oldMeta.GetDeletionGracePeriodSeconds() != nil && newMeta.GetDeletionGracePeriodSeconds() == nil { - newMeta.SetDeletionGracePeriodSeconds(oldMeta.GetDeletionGracePeriodSeconds()) - } - } - - // TODO: needs to check if newMeta==nil && oldMeta !=nil after the repair logic is removed. - if newMeta.GetDeletionGracePeriodSeconds() != nil && (oldMeta.GetDeletionGracePeriodSeconds() == nil || *newMeta.GetDeletionGracePeriodSeconds() != *oldMeta.GetDeletionGracePeriodSeconds()) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("deletionGracePeriodSeconds"), newMeta.GetDeletionGracePeriodSeconds(), "field is immutable; may only be changed via deletion")) - } - if newMeta.GetDeletionTimestamp() != nil && (oldMeta.GetDeletionTimestamp() == nil || !newMeta.GetDeletionTimestamp().Equal(oldMeta.GetDeletionTimestamp())) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("deletionTimestamp"), newMeta.GetDeletionTimestamp(), "field is immutable; may only be changed via deletion")) - } - // Finalizers cannot be added if the object is already being deleted. if oldMeta.GetDeletionTimestamp() != nil { allErrs = append(allErrs, ValidateNoNewFinalizers(newMeta.GetFinalizers(), oldMeta.GetFinalizers(), fldPath.Child("finalizers"))...) @@ -308,6 +271,8 @@ func ValidateObjectMetaAccessorUpdate(newMeta, oldMeta metav1.Object, fldPath *f allErrs = append(allErrs, ValidateImmutableField(newMeta.GetNamespace(), oldMeta.GetNamespace(), fldPath.Child("namespace"))...) allErrs = append(allErrs, ValidateImmutableField(newMeta.GetUID(), oldMeta.GetUID(), fldPath.Child("uid"))...) allErrs = append(allErrs, ValidateImmutableField(newMeta.GetCreationTimestamp(), oldMeta.GetCreationTimestamp(), fldPath.Child("creationTimestamp"))...) + allErrs = append(allErrs, ValidateImmutableField(newMeta.GetDeletionTimestamp(), oldMeta.GetDeletionTimestamp(), fldPath.Child("deletionTimestamp"))...) + allErrs = append(allErrs, ValidateImmutableField(newMeta.GetDeletionGracePeriodSeconds(), oldMeta.GetDeletionGracePeriodSeconds(), fldPath.Child("deletionGracePeriodSeconds"))...) allErrs = append(allErrs, ValidateImmutableField(newMeta.GetClusterName(), oldMeta.GetClusterName(), fldPath.Child("clusterName"))...) allErrs = append(allErrs, v1validation.ValidateLabels(newMeta.GetLabels(), fldPath.Child("labels"))...) diff --git a/vendor/k8s.io/apimachinery/pkg/api/validation/objectmeta_test.go b/vendor/k8s.io/apimachinery/pkg/api/validation/objectmeta_test.go index 9ec73b040..ebd6c7e7c 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/validation/objectmeta_test.go +++ b/vendor/k8s.io/apimachinery/pkg/api/validation/objectmeta_test.go @@ -219,21 +219,21 @@ func TestValidateObjectMetaUpdateIgnoresCreationTimestamp(t *testing.T) { &metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, &metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))}, field.NewPath("field"), - ); len(errs) != 0 { + ); len(errs) != 1 { t.Fatalf("unexpected errors: %v", errs) } if errs := ValidateObjectMetaUpdate( &metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))}, &metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, field.NewPath("field"), - ); len(errs) != 0 { + ); len(errs) != 1 { t.Fatalf("unexpected errors: %v", errs) } if errs := ValidateObjectMetaUpdate( &metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))}, &metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(11, 0))}, field.NewPath("field"), - ); len(errs) != 0 { + ); len(errs) != 1 { t.Fatalf("unexpected errors: %v", errs) } } @@ -328,38 +328,38 @@ func TestValidateObjectMetaUpdatePreventsDeletionFieldMutation(t *testing.T) { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: 1970-01-01 00:16:40 +0000 UTC: field is immutable; may only be changed via deletion"}, + ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: 1970-01-01 00:16:40 +0000 UTC: field is immutable"}, }, "invalid clear deletionTimestamp": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, - ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedErrs: []string{}, // no errors, validation copies the old value + ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, + ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: \"null\": field is immutable"}, }, "invalid change deletionTimestamp": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &later}, - ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedErrs: []string{}, // no errors, validation copies the old value + ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &later}, + ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: 1970-01-01 00:33:20 +0000 UTC: field is immutable"}, }, "invalid set deletionGracePeriodSeconds": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, - ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 30: field is immutable; may only be changed via deletion"}, + ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 30: field is immutable"}, }, "invalid clear deletionGracePeriodSeconds": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, - ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, - ExpectedErrs: []string{}, // no errors, validation copies the old value + ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, + ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: \"null\": field is immutable"}, }, "invalid change deletionGracePeriodSeconds": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong}, ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong}, - ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 40: field is immutable; may only be changed via deletion"}, + ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 40: field is immutable"}, }, } diff --git a/vendor/k8s.io/apimachinery/pkg/apimachinery/announced/announced.go b/vendor/k8s.io/apimachinery/pkg/apimachinery/announced/announced.go deleted file mode 100644 index 4e38cc8c5..000000000 --- a/vendor/k8s.io/apimachinery/pkg/apimachinery/announced/announced.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -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 announced contains tools for announcing API group factories. This is -// distinct from registration (in the 'registered' package) in that it's safe -// to announce every possible group linked in, but only groups requested at -// runtime should be registered. This package contains both a registry, and -// factory code (which was formerly copy-pasta in every install package). -package announced - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/apimachinery/registered" - "k8s.io/apimachinery/pkg/runtime" -) - -// APIGroupFactoryRegistry allows for groups and versions to announce themselves, -// which simply makes them available and doesn't take other actions. Later, -// users of the registry can select which groups and versions they'd actually -// like to register with an APIRegistrationManager. -// -// (Right now APIRegistrationManager has separate 'registration' and 'enabled' -// concepts-- APIGroupFactory is going to take over the former function; -// they will overlap until the refactoring is finished.) -// -// The key is the group name. After initialization, this should be treated as -// read-only. It is implemented as a map from group name to group factory, and -// it is safe to use this knowledge to manually pick out groups to register -// (e.g., for testing). -type APIGroupFactoryRegistry map[string]*GroupMetaFactory - -func (gar APIGroupFactoryRegistry) group(groupName string) *GroupMetaFactory { - gmf, ok := gar[groupName] - if !ok { - gmf = &GroupMetaFactory{VersionArgs: map[string]*GroupVersionFactoryArgs{}} - gar[groupName] = gmf - } - return gmf -} - -// AnnounceGroupVersion adds the particular arguments for this group version to the group factory. -func (gar APIGroupFactoryRegistry) AnnounceGroupVersion(gvf *GroupVersionFactoryArgs) error { - gmf := gar.group(gvf.GroupName) - if _, ok := gmf.VersionArgs[gvf.VersionName]; ok { - return fmt.Errorf("version %q in group %q has already been announced", gvf.VersionName, gvf.GroupName) - } - gmf.VersionArgs[gvf.VersionName] = gvf - return nil -} - -// AnnounceGroup adds the group-wide arguments to the group factory. -func (gar APIGroupFactoryRegistry) AnnounceGroup(args *GroupMetaFactoryArgs) error { - gmf := gar.group(args.GroupName) - if gmf.GroupArgs != nil { - return fmt.Errorf("group %q has already been announced", args.GroupName) - } - gmf.GroupArgs = args - return nil -} - -// RegisterAndEnableAll throws every factory at the specified API registration -// manager, and lets it decide which to register. (If you want to do this a la -// cart, you may look through gar itself-- it's just a map.) -func (gar APIGroupFactoryRegistry) RegisterAndEnableAll(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error { - for groupName, gmf := range gar { - if err := gmf.Register(m); err != nil { - return fmt.Errorf("error registering %v: %v", groupName, err) - } - if err := gmf.Enable(m, scheme); err != nil { - return fmt.Errorf("error enabling %v: %v", groupName, err) - } - } - return nil -} - -// AnnouncePreconstructedFactory announces a factory which you've manually assembled. -// You may call this instead of calling AnnounceGroup and AnnounceGroupVersion. -func (gar APIGroupFactoryRegistry) AnnouncePreconstructedFactory(gmf *GroupMetaFactory) error { - name := gmf.GroupArgs.GroupName - if _, exists := gar[name]; exists { - return fmt.Errorf("the group %q has already been announced.", name) - } - gar[name] = gmf - return nil -} diff --git a/vendor/k8s.io/apimachinery/pkg/apimachinery/announced/announced_test.go b/vendor/k8s.io/apimachinery/pkg/apimachinery/announced/announced_test.go deleted file mode 100644 index 95882e5df..000000000 --- a/vendor/k8s.io/apimachinery/pkg/apimachinery/announced/announced_test.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -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 announced - -import ( - "reflect" - "testing" - - "k8s.io/apimachinery/pkg/util/sets" -) - -func TestFactoryRegistry(t *testing.T) { - regA := make(APIGroupFactoryRegistry) - regB := make(APIGroupFactoryRegistry) - - if err := regA.AnnounceGroup(&GroupMetaFactoryArgs{ - GroupName: "foo", - VersionPreferenceOrder: []string{"v2", "v1"}, - RootScopedKinds: sets.NewString("namespaces"), - }); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if err := regA.AnnounceGroupVersion(&GroupVersionFactoryArgs{ - GroupName: "foo", - VersionName: "v1", - }); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if err := regA.AnnounceGroupVersion(&GroupVersionFactoryArgs{ - GroupName: "foo", - VersionName: "v2", - }); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - if err := regB.AnnouncePreconstructedFactory(NewGroupMetaFactory( - &GroupMetaFactoryArgs{ - GroupName: "foo", - VersionPreferenceOrder: []string{"v2", "v1"}, - RootScopedKinds: sets.NewString("namespaces"), - }, - VersionToSchemeFunc{"v1": nil, "v2": nil}, - )); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - if !reflect.DeepEqual(regA, regB) { - t.Errorf("Expected both ways of registering to be equivalent, but they were not.\n\n%#v\n\n%#v\n", regA, regB) - } -} diff --git a/vendor/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go b/vendor/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go deleted file mode 100644 index 154ed08f5..000000000 --- a/vendor/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go +++ /dev/null @@ -1,255 +0,0 @@ -/* -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 announced - -import ( - "fmt" - - "github.com/golang/glog" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/apimachinery" - "k8s.io/apimachinery/pkg/apimachinery/registered" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/sets" -) - -type SchemeFunc func(*runtime.Scheme) error -type VersionToSchemeFunc map[string]SchemeFunc - -// GroupVersionFactoryArgs contains all the per-version parts of a GroupMetaFactory. -type GroupVersionFactoryArgs struct { - GroupName string - VersionName string - - AddToScheme SchemeFunc -} - -// GroupMetaFactoryArgs contains the group-level args of a GroupMetaFactory. -type GroupMetaFactoryArgs struct { - // GroupName is the name of the API-Group - // - // example: 'servicecatalog.k8s.io' - GroupName string - VersionPreferenceOrder []string - // RootScopedKinds are resources that are not namespaced. - RootScopedKinds sets.String // nil is allowed - IgnoredKinds sets.String // nil is allowed - - // May be nil if there are no internal objects. - AddInternalObjectsToScheme SchemeFunc -} - -// NewGroupMetaFactory builds the args for you. This is for if you're -// constructing a factory all at once and not using the registry. -func NewGroupMetaFactory(groupArgs *GroupMetaFactoryArgs, versions VersionToSchemeFunc) *GroupMetaFactory { - gmf := &GroupMetaFactory{ - GroupArgs: groupArgs, - VersionArgs: map[string]*GroupVersionFactoryArgs{}, - } - for v, f := range versions { - gmf.VersionArgs[v] = &GroupVersionFactoryArgs{ - GroupName: groupArgs.GroupName, - VersionName: v, - AddToScheme: f, - } - } - return gmf -} - -// Announce adds this Group factory to the global factory registry. It should -// only be called if you constructed the GroupMetaFactory yourself via -// NewGroupMetaFactory. -// Note that this will panic on an error, since it's expected that you'll be -// calling this at initialization time and any error is a result of a -// programmer importing the wrong set of packages. If this assumption doesn't -// work for you, just call DefaultGroupFactoryRegistry.AnnouncePreconstructedFactory -// yourself. -func (gmf *GroupMetaFactory) Announce(groupFactoryRegistry APIGroupFactoryRegistry) *GroupMetaFactory { - if err := groupFactoryRegistry.AnnouncePreconstructedFactory(gmf); err != nil { - panic(err) - } - return gmf -} - -// GroupMetaFactory has the logic for actually assembling and registering a group. -// -// There are two ways of obtaining one of these. -// 1. You can announce your group and versions separately, and then let the -// GroupFactoryRegistry assemble this object for you. (This allows group and -// versions to be imported separately, without referencing each other, to -// keep import trees small.) -// 2. You can call NewGroupMetaFactory(), which is mostly a drop-in replacement -// for the old, bad way of doing things. You can then call .Announce() to -// announce your constructed factory to any code that would like to do -// things the new, better way. -// -// Note that GroupMetaFactory actually does construct GroupMeta objects, but -// currently it does so in a way that's very entangled with an -// APIRegistrationManager. It's a TODO item to cleanly separate that interface. -type GroupMetaFactory struct { - GroupArgs *GroupMetaFactoryArgs - // map of version name to version factory - VersionArgs map[string]*GroupVersionFactoryArgs - - // assembled by Register() - prioritizedVersionList []schema.GroupVersion -} - -// Register constructs the finalized prioritized version list and sanity checks -// the announced group & versions. Then it calls register. -func (gmf *GroupMetaFactory) Register(m *registered.APIRegistrationManager) error { - if gmf.GroupArgs == nil { - return fmt.Errorf("partially announced groups are not allowed, only got versions: %#v", gmf.VersionArgs) - } - if len(gmf.VersionArgs) == 0 { - return fmt.Errorf("group %v announced but no versions announced", gmf.GroupArgs.GroupName) - } - - pvSet := sets.NewString(gmf.GroupArgs.VersionPreferenceOrder...) - if pvSet.Len() != len(gmf.GroupArgs.VersionPreferenceOrder) { - return fmt.Errorf("preference order for group %v has duplicates: %v", gmf.GroupArgs.GroupName, gmf.GroupArgs.VersionPreferenceOrder) - } - prioritizedVersions := []schema.GroupVersion{} - for _, v := range gmf.GroupArgs.VersionPreferenceOrder { - prioritizedVersions = append( - prioritizedVersions, - schema.GroupVersion{ - Group: gmf.GroupArgs.GroupName, - Version: v, - }, - ) - } - - // Go through versions that weren't explicitly prioritized. - unprioritizedVersions := []schema.GroupVersion{} - for _, v := range gmf.VersionArgs { - if v.GroupName != gmf.GroupArgs.GroupName { - return fmt.Errorf("found %v/%v in group %v?", v.GroupName, v.VersionName, gmf.GroupArgs.GroupName) - } - if pvSet.Has(v.VersionName) { - pvSet.Delete(v.VersionName) - continue - } - unprioritizedVersions = append(unprioritizedVersions, schema.GroupVersion{Group: v.GroupName, Version: v.VersionName}) - } - if len(unprioritizedVersions) > 1 { - glog.Warningf("group %v has multiple unprioritized versions: %#v. They will have an arbitrary preference order!", gmf.GroupArgs.GroupName, unprioritizedVersions) - } - if pvSet.Len() != 0 { - return fmt.Errorf("group %v has versions in the priority list that were never announced: %s", gmf.GroupArgs.GroupName, pvSet) - } - prioritizedVersions = append(prioritizedVersions, unprioritizedVersions...) - m.RegisterVersions(prioritizedVersions) - gmf.prioritizedVersionList = prioritizedVersions - return nil -} - -func (gmf *GroupMetaFactory) newRESTMapper(scheme *runtime.Scheme, externalVersions []schema.GroupVersion, groupMeta *apimachinery.GroupMeta) meta.RESTMapper { - // the list of kinds that are scoped at the root of the api hierarchy - // if a kind is not enumerated here, it is assumed to have a namespace scope - rootScoped := sets.NewString() - if gmf.GroupArgs.RootScopedKinds != nil { - rootScoped = gmf.GroupArgs.RootScopedKinds - } - ignoredKinds := sets.NewString() - if gmf.GroupArgs.IgnoredKinds != nil { - ignoredKinds = gmf.GroupArgs.IgnoredKinds - } - - mapper := meta.NewDefaultRESTMapper(externalVersions, groupMeta.InterfacesFor) - for _, gv := range externalVersions { - for kind := range scheme.KnownTypes(gv) { - if ignoredKinds.Has(kind) { - continue - } - scope := meta.RESTScopeNamespace - if rootScoped.Has(kind) { - scope = meta.RESTScopeRoot - } - mapper.Add(gv.WithKind(kind), scope) - } - } - - return mapper -} - -// Enable enables group versions that are allowed, adds methods to the scheme, etc. -func (gmf *GroupMetaFactory) Enable(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error { - externalVersions := []schema.GroupVersion{} - for _, v := range gmf.prioritizedVersionList { - if !m.IsAllowedVersion(v) { - continue - } - externalVersions = append(externalVersions, v) - if err := m.EnableVersions(v); err != nil { - return err - } - gmf.VersionArgs[v.Version].AddToScheme(scheme) - } - if len(externalVersions) == 0 { - glog.V(4).Infof("No version is registered for group %v", gmf.GroupArgs.GroupName) - return nil - } - - if gmf.GroupArgs.AddInternalObjectsToScheme != nil { - gmf.GroupArgs.AddInternalObjectsToScheme(scheme) - } - - preferredExternalVersion := externalVersions[0] - accessor := meta.NewAccessor() - - groupMeta := &apimachinery.GroupMeta{ - GroupVersion: preferredExternalVersion, - GroupVersions: externalVersions, - SelfLinker: runtime.SelfLinker(accessor), - } - for _, v := range externalVersions { - gvf := gmf.VersionArgs[v.Version] - if err := groupMeta.AddVersionInterfaces( - schema.GroupVersion{Group: gvf.GroupName, Version: gvf.VersionName}, - &meta.VersionInterfaces{ - ObjectConvertor: scheme, - MetadataAccessor: accessor, - }, - ); err != nil { - return err - } - } - groupMeta.InterfacesFor = groupMeta.DefaultInterfacesFor - groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta) - - if err := m.RegisterGroup(*groupMeta); err != nil { - return err - } - return nil -} - -// RegisterAndEnable is provided only to allow this code to get added in multiple steps. -// It's really bad that this is called in init() methods, but supporting this -// temporarily lets us do the change incrementally. -func (gmf *GroupMetaFactory) RegisterAndEnable(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) error { - if err := gmf.Register(registry); err != nil { - return err - } - if err := gmf.Enable(registry, scheme); err != nil { - return err - } - - return nil -} diff --git a/vendor/k8s.io/apimachinery/pkg/apimachinery/doc.go b/vendor/k8s.io/apimachinery/pkg/apimachinery/doc.go deleted file mode 100644 index b238454b2..000000000 --- a/vendor/k8s.io/apimachinery/pkg/apimachinery/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -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 apimachinery contains the generic API machinery code that -// is common to both server and clients. -// This package should never import specific API objects. -package apimachinery // import "k8s.io/apimachinery/pkg/apimachinery" diff --git a/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go b/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go deleted file mode 100644 index 0da94f50f..000000000 --- a/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go +++ /dev/null @@ -1,336 +0,0 @@ -/* -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 to keep track of API Versions that can be registered and are enabled in a Scheme. -package registered - -import ( - "fmt" - "sort" - "strings" - - "github.com/golang/glog" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/apimachinery" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/sets" -) - -// APIRegistrationManager provides the concept of what API groups are enabled. -// -// TODO: currently, it also provides a "registered" concept. But it's wrong to -// have both concepts in the same object. Therefore the "announced" package is -// going to take over the registered concept. After all the install packages -// are switched to using the announce package instead of this package, then we -// can combine the registered/enabled concepts in this object. Simplifying this -// isn't easy right now because there are so many callers of this package. -type APIRegistrationManager struct { - // registeredGroupVersions stores all API group versions for which RegisterGroup is called. - registeredVersions map[schema.GroupVersion]struct{} - - // enabledVersions represents all enabled API versions. It should be a - // subset of registeredVersions. Please call EnableVersions() to add - // enabled versions. - enabledVersions map[schema.GroupVersion]struct{} - - // map of group meta for all groups. - groupMetaMap map[string]*apimachinery.GroupMeta - - // envRequestedVersions represents the versions requested via the - // KUBE_API_VERSIONS environment variable. The install package of each group - // checks this list before add their versions to the latest package and - // Scheme. This list is small and order matters, so represent as a slice - envRequestedVersions []schema.GroupVersion -} - -// NewAPIRegistrationManager constructs a new manager. The argument ought to be -// the value of the KUBE_API_VERSIONS env var, or a value of this which you -// wish to test. -func NewAPIRegistrationManager(kubeAPIVersions string) (*APIRegistrationManager, error) { - m := &APIRegistrationManager{ - registeredVersions: map[schema.GroupVersion]struct{}{}, - enabledVersions: map[schema.GroupVersion]struct{}{}, - groupMetaMap: map[string]*apimachinery.GroupMeta{}, - envRequestedVersions: []schema.GroupVersion{}, - } - - if len(kubeAPIVersions) != 0 { - for _, version := range strings.Split(kubeAPIVersions, ",") { - gv, err := schema.ParseGroupVersion(version) - if err != nil { - return nil, fmt.Errorf("invalid api version: %s in KUBE_API_VERSIONS: %s.", - version, kubeAPIVersions) - } - m.envRequestedVersions = append(m.envRequestedVersions, gv) - } - } - return m, nil -} - -func NewOrDie(kubeAPIVersions string) *APIRegistrationManager { - m, err := NewAPIRegistrationManager(kubeAPIVersions) - if err != nil { - glog.Fatalf("Could not construct version manager: %v (KUBE_API_VERSIONS=%q)", err, kubeAPIVersions) - } - return m -} - -// RegisterVersions adds the given group versions to the list of registered group versions. -func (m *APIRegistrationManager) RegisterVersions(availableVersions []schema.GroupVersion) { - for _, v := range availableVersions { - m.registeredVersions[v] = struct{}{} - } -} - -// RegisterGroup adds the given group to the list of registered groups. -func (m *APIRegistrationManager) RegisterGroup(groupMeta apimachinery.GroupMeta) error { - groupName := groupMeta.GroupVersion.Group - if _, found := m.groupMetaMap[groupName]; found { - return fmt.Errorf("group %q is already registered in groupsMap: %v", groupName, m.groupMetaMap) - } - m.groupMetaMap[groupName] = &groupMeta - return nil -} - -// EnableVersions adds the versions for the given group to the list of enabled versions. -// Note that the caller should call RegisterGroup before calling this method. -// The caller of this function is responsible to add the versions to scheme and RESTMapper. -func (m *APIRegistrationManager) EnableVersions(versions ...schema.GroupVersion) error { - var unregisteredVersions []schema.GroupVersion - for _, v := range versions { - if _, found := m.registeredVersions[v]; !found { - unregisteredVersions = append(unregisteredVersions, v) - } - m.enabledVersions[v] = struct{}{} - } - if len(unregisteredVersions) != 0 { - return fmt.Errorf("Please register versions before enabling them: %v", unregisteredVersions) - } - return nil -} - -// IsAllowedVersion returns if the version is allowed by the KUBE_API_VERSIONS -// environment variable. If the environment variable is empty, then it always -// returns true. -func (m *APIRegistrationManager) IsAllowedVersion(v schema.GroupVersion) bool { - if len(m.envRequestedVersions) == 0 { - return true - } - for _, envGV := range m.envRequestedVersions { - if v == envGV { - return true - } - } - return false -} - -// IsEnabledVersion returns if a version is enabled. -func (m *APIRegistrationManager) IsEnabledVersion(v schema.GroupVersion) bool { - _, found := m.enabledVersions[v] - return found -} - -// EnabledVersions returns all enabled versions. Groups are randomly ordered, but versions within groups -// are priority order from best to worst -func (m *APIRegistrationManager) EnabledVersions() []schema.GroupVersion { - ret := []schema.GroupVersion{} - for _, groupMeta := range m.groupMetaMap { - for _, version := range groupMeta.GroupVersions { - if m.IsEnabledVersion(version) { - ret = append(ret, version) - } - } - } - return ret -} - -// EnabledVersionsForGroup returns all enabled versions for a group in order of best to worst -func (m *APIRegistrationManager) EnabledVersionsForGroup(group string) []schema.GroupVersion { - groupMeta, ok := m.groupMetaMap[group] - if !ok { - return []schema.GroupVersion{} - } - - ret := []schema.GroupVersion{} - for _, version := range groupMeta.GroupVersions { - if m.IsEnabledVersion(version) { - ret = append(ret, version) - } - } - return ret -} - -// Group returns the metadata of a group if the group is registered, otherwise -// an error is returned. -func (m *APIRegistrationManager) Group(group string) (*apimachinery.GroupMeta, error) { - groupMeta, found := m.groupMetaMap[group] - if !found { - return nil, fmt.Errorf("group %v has not been registered", group) - } - groupMetaCopy := *groupMeta - return &groupMetaCopy, nil -} - -// IsRegistered takes a string and determines if it's one of the registered groups -func (m *APIRegistrationManager) IsRegistered(group string) bool { - _, found := m.groupMetaMap[group] - return found -} - -// IsRegisteredVersion returns if a version is registered. -func (m *APIRegistrationManager) IsRegisteredVersion(v schema.GroupVersion) bool { - _, found := m.registeredVersions[v] - return found -} - -// RegisteredGroupVersions returns all registered group versions. -func (m *APIRegistrationManager) RegisteredGroupVersions() []schema.GroupVersion { - ret := []schema.GroupVersion{} - for groupVersion := range m.registeredVersions { - ret = append(ret, groupVersion) - } - return ret -} - -// InterfacesFor is a union meta.VersionInterfacesFunc func for all registered types -func (m *APIRegistrationManager) InterfacesFor(version schema.GroupVersion) (*meta.VersionInterfaces, error) { - groupMeta, err := m.Group(version.Group) - if err != nil { - return nil, err - } - return groupMeta.InterfacesFor(version) -} - -// TODO: This is an expedient function, because we don't check if a Group is -// supported throughout the code base. We will abandon this function and -// checking the error returned by the Group() function. -func (m *APIRegistrationManager) GroupOrDie(group string) *apimachinery.GroupMeta { - groupMeta, found := m.groupMetaMap[group] - if !found { - if group == "" { - panic("The legacy v1 API is not registered.") - } else { - panic(fmt.Sprintf("Group %s is not registered.", group)) - } - } - groupMetaCopy := *groupMeta - return &groupMetaCopy -} - -// RESTMapper returns a union RESTMapper of all known types with priorities chosen in the following order: -// 1. if KUBE_API_VERSIONS is specified, then KUBE_API_VERSIONS in order, OR -// 1. legacy kube group preferred version, extensions preferred version, metrics perferred version, legacy -// kube any version, extensions any version, metrics any version, all other groups alphabetical preferred version, -// all other groups alphabetical. -func (m *APIRegistrationManager) RESTMapper(versionPatterns ...schema.GroupVersion) meta.RESTMapper { - unionMapper := meta.MultiRESTMapper{} - unionedGroups := sets.NewString() - for enabledVersion := range m.enabledVersions { - if !unionedGroups.Has(enabledVersion.Group) { - unionedGroups.Insert(enabledVersion.Group) - groupMeta := m.groupMetaMap[enabledVersion.Group] - unionMapper = append(unionMapper, groupMeta.RESTMapper) - } - } - - if len(versionPatterns) != 0 { - resourcePriority := []schema.GroupVersionResource{} - kindPriority := []schema.GroupVersionKind{} - for _, versionPriority := range versionPatterns { - resourcePriority = append(resourcePriority, versionPriority.WithResource(meta.AnyResource)) - kindPriority = append(kindPriority, versionPriority.WithKind(meta.AnyKind)) - } - - return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} - } - - if len(m.envRequestedVersions) != 0 { - resourcePriority := []schema.GroupVersionResource{} - kindPriority := []schema.GroupVersionKind{} - - for _, versionPriority := range m.envRequestedVersions { - resourcePriority = append(resourcePriority, versionPriority.WithResource(meta.AnyResource)) - kindPriority = append(kindPriority, versionPriority.WithKind(meta.AnyKind)) - } - - return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} - } - - prioritizedGroups := []string{"", "extensions", "metrics"} - resourcePriority, kindPriority := m.prioritiesForGroups(prioritizedGroups...) - - prioritizedGroupsSet := sets.NewString(prioritizedGroups...) - remainingGroups := sets.String{} - for enabledVersion := range m.enabledVersions { - if !prioritizedGroupsSet.Has(enabledVersion.Group) { - remainingGroups.Insert(enabledVersion.Group) - } - } - - remainingResourcePriority, remainingKindPriority := m.prioritiesForGroups(remainingGroups.List()...) - resourcePriority = append(resourcePriority, remainingResourcePriority...) - kindPriority = append(kindPriority, remainingKindPriority...) - - return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} -} - -// prioritiesForGroups returns the resource and kind priorities for a PriorityRESTMapper, preferring the preferred version of each group first, -// then any non-preferred version of the group second. -func (m *APIRegistrationManager) prioritiesForGroups(groups ...string) ([]schema.GroupVersionResource, []schema.GroupVersionKind) { - resourcePriority := []schema.GroupVersionResource{} - kindPriority := []schema.GroupVersionKind{} - - for _, group := range groups { - availableVersions := m.EnabledVersionsForGroup(group) - if len(availableVersions) > 0 { - resourcePriority = append(resourcePriority, availableVersions[0].WithResource(meta.AnyResource)) - kindPriority = append(kindPriority, availableVersions[0].WithKind(meta.AnyKind)) - } - } - for _, group := range groups { - resourcePriority = append(resourcePriority, schema.GroupVersionResource{Group: group, Version: meta.AnyVersion, Resource: meta.AnyResource}) - kindPriority = append(kindPriority, schema.GroupVersionKind{Group: group, Version: meta.AnyVersion, Kind: meta.AnyKind}) - } - - return resourcePriority, kindPriority -} - -// AllPreferredGroupVersions returns the preferred versions of all registered -// groups in the form of "group1/version1,group2/version2,..." -func (m *APIRegistrationManager) AllPreferredGroupVersions() string { - if len(m.groupMetaMap) == 0 { - return "" - } - var defaults []string - for _, groupMeta := range m.groupMetaMap { - defaults = append(defaults, groupMeta.GroupVersion.String()) - } - sort.Strings(defaults) - return strings.Join(defaults, ",") -} - -// ValidateEnvRequestedVersions returns a list of versions that are requested in -// the KUBE_API_VERSIONS environment variable, but not enabled. -func (m *APIRegistrationManager) ValidateEnvRequestedVersions() []schema.GroupVersion { - var missingVersions []schema.GroupVersion - for _, v := range m.envRequestedVersions { - if _, found := m.enabledVersions[v]; !found { - missingVersions = append(missingVersions, v) - } - } - return missingVersions -} diff --git a/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered_test.go b/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered_test.go deleted file mode 100644 index 58fc0173e..000000000 --- a/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered_test.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -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 registered - -import ( - "testing" - - "k8s.io/apimachinery/pkg/apimachinery" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestAllPreferredGroupVersions(t *testing.T) { - testCases := []struct { - groupMetas []apimachinery.GroupMeta - expect string - }{ - { - groupMetas: []apimachinery.GroupMeta{ - { - GroupVersion: schema.GroupVersion{Group: "group1", Version: "v1"}, - }, - { - GroupVersion: schema.GroupVersion{Group: "group2", Version: "v2"}, - }, - { - GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, - }, - }, - expect: "group1/v1,group2/v2,v1", - }, - { - groupMetas: []apimachinery.GroupMeta{ - { - GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, - }, - }, - expect: "v1", - }, - { - groupMetas: []apimachinery.GroupMeta{}, - expect: "", - }, - } - for _, testCase := range testCases { - m, err := NewAPIRegistrationManager("") - if err != nil { - t.Fatalf("Unexpected failure to make a manager: %v", err) - } - for _, groupMeta := range testCase.groupMetas { - m.RegisterGroup(groupMeta) - } - output := m.AllPreferredGroupVersions() - if testCase.expect != output { - t.Errorf("Error. expect: %s, got: %s", testCase.expect, output) - } - } -} diff --git a/vendor/k8s.io/apimachinery/pkg/apimachinery/types.go b/vendor/k8s.io/apimachinery/pkg/apimachinery/types.go deleted file mode 100644 index baca784fa..000000000 --- a/vendor/k8s.io/apimachinery/pkg/apimachinery/types.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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 apimachinery - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// GroupMeta stores the metadata of a group. -type GroupMeta struct { - // GroupVersion represents the preferred version of the group. - GroupVersion schema.GroupVersion - - // GroupVersions is Group + all versions in that group. - GroupVersions []schema.GroupVersion - - // SelfLinker can set or get the SelfLink field of all API types. - // TODO: when versioning changes, make this part of each API definition. - // TODO(lavalamp): Combine SelfLinker & ResourceVersioner interfaces, force all uses - // to go through the InterfacesFor method below. - SelfLinker runtime.SelfLinker - - // RESTMapper provides the default mapping between REST paths and the objects declared in a Scheme and all known - // versions. - RESTMapper meta.RESTMapper - - // InterfacesFor returns the default Codec and ResourceVersioner for a given version - // string, or an error if the version is not known. - // TODO: make this stop being a func pointer and always use the default - // function provided below once every place that populates this field has been changed. - InterfacesFor func(version schema.GroupVersion) (*meta.VersionInterfaces, error) - - // InterfacesByVersion stores the per-version interfaces. - InterfacesByVersion map[schema.GroupVersion]*meta.VersionInterfaces -} - -// DefaultInterfacesFor returns the default Codec and ResourceVersioner for a given version -// string, or an error if the version is not known. -// TODO: Remove the "Default" prefix. -func (gm *GroupMeta) DefaultInterfacesFor(version schema.GroupVersion) (*meta.VersionInterfaces, error) { - if v, ok := gm.InterfacesByVersion[version]; ok { - return v, nil - } - return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, gm.GroupVersions) -} - -// AddVersionInterfaces adds the given version to the group. Only call during -// init, after that GroupMeta objects should be immutable. Not thread safe. -// (If you use this, be sure to set .InterfacesFor = .DefaultInterfacesFor) -// TODO: remove the "Interfaces" suffix and make this also maintain the -// .GroupVersions member. -func (gm *GroupMeta) AddVersionInterfaces(version schema.GroupVersion, interfaces *meta.VersionInterfaces) error { - if e, a := gm.GroupVersion.Group, version.Group; a != e { - return fmt.Errorf("got a version in group %v, but am in group %v", a, e) - } - if gm.InterfacesByVersion == nil { - gm.InterfacesByVersion = make(map[schema.GroupVersion]*meta.VersionInterfaces) - } - gm.InterfacesByVersion[version] = interfaces - - // TODO: refactor to make the below error not possible, this function - // should *set* GroupVersions rather than depend on it. - for _, v := range gm.GroupVersions { - if v == version { - return nil - } - } - return fmt.Errorf("added a version interface without the corresponding version %v being in the list %#v", version, gm.GroupVersions) -} diff --git a/vendor/k8s.io/apimachinery/pkg/apimachinery/types_test.go b/vendor/k8s.io/apimachinery/pkg/apimachinery/types_test.go deleted file mode 100644 index ca858788e..000000000 --- a/vendor/k8s.io/apimachinery/pkg/apimachinery/types_test.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -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 apimachinery - -import ( - "testing" - - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestAdd(t *testing.T) { - gm := GroupMeta{ - GroupVersion: schema.GroupVersion{ - Group: "test", - Version: "v1", - }, - GroupVersions: []schema.GroupVersion{{Group: "test", Version: "v1"}}, - } - - gm.AddVersionInterfaces(schema.GroupVersion{Group: "test", Version: "v1"}, nil) - if e, a := 1, len(gm.InterfacesByVersion); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - // GroupVersions is unchanged - if e, a := 1, len(gm.GroupVersions); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go index 54fab9c02..3a28f7431 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go @@ -181,16 +181,45 @@ func v1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} { j.Kind = "" }, func(j *metav1.ObjectMeta, c fuzz.Continue) { - j.Name = c.RandString() + c.FuzzNoCustom(j) + j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) - j.SelfLink = c.RandString() j.UID = types.UID(c.RandString()) - j.GenerateName = c.RandString() var sec, nsec int64 c.Fuzz(&sec) c.Fuzz(&nsec) j.CreationTimestamp = metav1.Unix(sec, nsec).Rfc3339Copy() + + if j.DeletionTimestamp != nil { + c.Fuzz(&sec) + c.Fuzz(&nsec) + t := metav1.Unix(sec, nsec).Rfc3339Copy() + j.DeletionTimestamp = &t + } + + if len(j.Labels) == 0 { + j.Labels = nil + } else { + delete(j.Labels, "") + } + if len(j.Annotations) == 0 { + j.Annotations = nil + } else { + delete(j.Annotations, "") + } + if len(j.OwnerReferences) == 0 { + j.OwnerReferences = nil + } + if len(j.Finalizers) == 0 { + j.Finalizers = nil + } + }, + func(j *metav1.Initializers, c fuzz.Continue) { + c.FuzzNoCustom(j) + if len(j.Pending) == 0 { + j.Pending = nil + } }, func(j *metav1.ListMeta, c fuzz.Continue) { j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) @@ -268,7 +297,7 @@ func v1alpha1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} { case 0: r.Cells[i] = c.RandString() case 1: - r.Cells[i] = c.Uint64() + r.Cells[i] = c.Int63() case 2: r.Cells[i] = c.RandBool() case 3: @@ -280,7 +309,7 @@ func v1alpha1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} { case 4: x := make([]interface{}, c.Intn(10)) for i := range x { - x[i] = c.Uint64() + x[i] = c.Int63() } r.Cells[i] = x default: diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.conversion.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.conversion.go index c3fd40a90..a63b3fc2c 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.conversion.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go index e4e5b017b..77bd9a6b4 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go index cd651bcd5..c36fc6556 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go @@ -75,6 +75,8 @@ func AddConversionFuncs(scheme *runtime.Scheme) error { Convert_unversioned_LabelSelector_to_map, Convert_Slice_string_To_Slice_int32, + + Convert_Slice_string_To_v1_DeletionPropagation, ) } @@ -304,3 +306,13 @@ func Convert_Slice_string_To_Slice_int32(in *[]string, out *[]int32, s conversio } return nil } + +// Convert_Slice_string_To_v1_DeletionPropagation allows converting a URL query parameter propagationPolicy +func Convert_Slice_string_To_v1_DeletionPropagation(input *[]string, out *DeletionPropagation, s conversion.Scope) error { + if len(*input) > 0 { + *out = DeletionPropagation((*input)[0]) + } else { + *out = "" + } + return nil +} diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/conversion_test.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/conversion_test.go index bc591584e..4ff57fd8d 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/conversion_test.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/conversion_test.go @@ -47,3 +47,38 @@ func TestMapToLabelSelectorRoundTrip(t *testing.T) { } } } + +func TestConvertSliceStringToDeletionPropagation(t *testing.T) { + tcs := []struct { + Input []string + Output v1.DeletionPropagation + }{ + { + Input: nil, + Output: "", + }, + { + Input: []string{}, + Output: "", + }, + { + Input: []string{"foo"}, + Output: "foo", + }, + { + Input: []string{"bar", "foo"}, + Output: "bar", + }, + } + + for _, tc := range tcs { + var dp v1.DeletionPropagation + if err := v1.Convert_Slice_string_To_v1_DeletionPropagation(&tc.Input, &dp, nil); err != nil { + t.Errorf("Convert_Slice_string_To_v1_DeletionPropagation(%#v): %v", tc.Input, err) + continue + } + if !apiequality.Semantic.DeepEqual(dp, tc.Output) { + t.Errorf("slice string to DeletionPropagation conversion failed: got %v; want %v", dp, tc.Output) + } + } +} diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go index fea458dfb..2eaabf079 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go @@ -31,7 +31,10 @@ type Duration struct { // UnmarshalJSON implements the json.Unmarshaller interface. func (d *Duration) UnmarshalJSON(b []byte) error { var str string - json.Unmarshal(b, &str) + err := json.Unmarshal(b, &str) + if err != nil { + return err + } pd, err := time.ParseDuration(str) if err != nil { diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go index 1fa478f5a..d987058ef 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -7804,158 +7804,157 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2435 bytes of a gzipped FileDescriptorProto + // 2422 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x59, 0x4d, 0x6c, 0x23, 0x49, 0x15, 0x4e, 0xdb, 0xb1, 0x63, 0x3f, 0xc7, 0xf9, 0xa9, 0xcd, 0x80, 0x37, 0x02, 0x3b, 0xdb, 0x8b, - 0x56, 0x59, 0x98, 0xb5, 0x49, 0x16, 0x56, 0xc3, 0x00, 0x03, 0xe9, 0x38, 0x33, 0x8a, 0x76, 0x32, - 0x63, 0x55, 0x76, 0x06, 0x31, 0x8c, 0x10, 0x9d, 0x76, 0xc5, 0x69, 0xd2, 0xee, 0xf6, 0x56, 0x95, - 0x33, 0x09, 0x1c, 0xd8, 0x03, 0x48, 0x1c, 0x10, 0x9a, 0x23, 0x27, 0xb4, 0x23, 0xb8, 0x70, 0xe5, - 0xc4, 0x05, 0x4e, 0x48, 0xcc, 0x71, 0x24, 0x2e, 0x7b, 0x40, 0xd6, 0x8e, 0xf7, 0xc0, 0x09, 0x71, - 0xcf, 0x09, 0x55, 0x75, 0xf5, 0x9f, 0x1d, 0x4f, 0xda, 0x3b, 0x0b, 0xe2, 0x14, 0xf7, 0xfb, 0xf9, - 0xde, 0xab, 0x57, 0xaf, 0x5e, 0xbd, 0x7a, 0x81, 0xbd, 0xe3, 0x6b, 0xac, 0x6e, 0x7b, 0x8d, 0xe3, - 0xfe, 0x01, 0xa1, 0x2e, 0xe1, 0x84, 0x35, 0x4e, 0x88, 0xdb, 0xf6, 0x68, 0x43, 0x31, 0xcc, 0x9e, - 0xdd, 0x35, 0xad, 0x23, 0xdb, 0x25, 0xf4, 0xac, 0xd1, 0x3b, 0xee, 0x08, 0x02, 0x6b, 0x74, 0x09, - 0x37, 0x1b, 0x27, 0x1b, 0x8d, 0x0e, 0x71, 0x09, 0x35, 0x39, 0x69, 0xd7, 0x7b, 0xd4, 0xe3, 0x1e, - 0xfa, 0x92, 0xaf, 0x55, 0x8f, 0x6b, 0xd5, 0x7b, 0xc7, 0x1d, 0x41, 0x60, 0x75, 0xa1, 0x55, 0x3f, - 0xd9, 0x58, 0x7d, 0xab, 0x63, 0xf3, 0xa3, 0xfe, 0x41, 0xdd, 0xf2, 0xba, 0x8d, 0x8e, 0xd7, 0xf1, - 0x1a, 0x52, 0xf9, 0xa0, 0x7f, 0x28, 0xbf, 0xe4, 0x87, 0xfc, 0xe5, 0x83, 0xae, 0x4e, 0x74, 0x85, - 0xf6, 0x5d, 0x6e, 0x77, 0xc9, 0xa8, 0x17, 0xab, 0xef, 0x5c, 0xa6, 0xc0, 0xac, 0x23, 0xd2, 0x35, - 0xc7, 0xf4, 0xde, 0x9e, 0xa4, 0xd7, 0xe7, 0xb6, 0xd3, 0xb0, 0x5d, 0xce, 0x38, 0x1d, 0x55, 0xd2, - 0xff, 0x96, 0x85, 0xc2, 0x56, 0x6b, 0xf7, 0x16, 0xf5, 0xfa, 0x3d, 0xb4, 0x06, 0xb3, 0xae, 0xd9, - 0x25, 0x15, 0x6d, 0x4d, 0x5b, 0x2f, 0x1a, 0xf3, 0x4f, 0x07, 0xb5, 0x99, 0xe1, 0xa0, 0x36, 0x7b, - 0xc7, 0xec, 0x12, 0x2c, 0x39, 0xc8, 0x81, 0xc2, 0x09, 0xa1, 0xcc, 0xf6, 0x5c, 0x56, 0xc9, 0xac, - 0x65, 0xd7, 0x4b, 0x9b, 0x37, 0xea, 0x69, 0x82, 0x56, 0x97, 0x06, 0xee, 0xfb, 0xaa, 0x37, 0x3d, - 0xda, 0xb4, 0x99, 0xe5, 0x9d, 0x10, 0x7a, 0x66, 0x2c, 0x29, 0x2b, 0x05, 0xc5, 0x64, 0x38, 0xb4, - 0x80, 0x7e, 0xae, 0xc1, 0x52, 0x8f, 0x92, 0x43, 0x42, 0x29, 0x69, 0x2b, 0x7e, 0x25, 0xbb, 0xa6, - 0x7d, 0x06, 0x66, 0x2b, 0xca, 0xec, 0x52, 0x6b, 0x04, 0x1f, 0x8f, 0x59, 0x44, 0xbf, 0xd3, 0x60, - 0x95, 0x11, 0x7a, 0x42, 0xe8, 0x56, 0xbb, 0x4d, 0x09, 0x63, 0xc6, 0xd9, 0xb6, 0x63, 0x13, 0x97, - 0x6f, 0xef, 0x36, 0x31, 0xab, 0xcc, 0xca, 0x38, 0x7c, 0x27, 0x9d, 0x43, 0xfb, 0x93, 0x70, 0x0c, - 0x5d, 0x79, 0xb4, 0x3a, 0x51, 0x84, 0xe1, 0x17, 0xb8, 0xa1, 0x1f, 0xc2, 0x7c, 0xb0, 0x91, 0xb7, - 0x6d, 0xc6, 0xd1, 0x7d, 0xc8, 0x77, 0xc4, 0x07, 0xab, 0x68, 0xd2, 0xc1, 0x7a, 0x3a, 0x07, 0x03, - 0x0c, 0x63, 0x41, 0xf9, 0x93, 0x97, 0x9f, 0x0c, 0x2b, 0x34, 0xfd, 0xcf, 0x59, 0x28, 0x6d, 0xb5, - 0x76, 0x31, 0x61, 0x5e, 0x9f, 0x5a, 0x24, 0x45, 0xd2, 0x6c, 0x02, 0x88, 0xbf, 0xac, 0x67, 0x5a, - 0xa4, 0x5d, 0xc9, 0xac, 0x69, 0xeb, 0x05, 0x03, 0x29, 0x39, 0xb8, 0x13, 0x72, 0x70, 0x4c, 0x4a, - 0xa0, 0x1e, 0xdb, 0x6e, 0x5b, 0xee, 0x76, 0x0c, 0xf5, 0x5d, 0xdb, 0x6d, 0x63, 0xc9, 0x41, 0xb7, - 0x21, 0x77, 0x42, 0xe8, 0x81, 0x88, 0xbf, 0x48, 0x88, 0xaf, 0xa4, 0x5b, 0xde, 0x7d, 0xa1, 0x62, - 0x14, 0x87, 0x83, 0x5a, 0x4e, 0xfe, 0xc4, 0x3e, 0x08, 0xaa, 0x03, 0xb0, 0x23, 0x8f, 0x72, 0xe9, - 0x4e, 0x25, 0xb7, 0x96, 0x5d, 0x2f, 0x1a, 0x0b, 0xc2, 0xbf, 0xfd, 0x90, 0x8a, 0x63, 0x12, 0xe8, - 0x1a, 0xcc, 0x33, 0xdb, 0xed, 0xf4, 0x1d, 0x93, 0x0a, 0x42, 0x25, 0x2f, 0xfd, 0x5c, 0x51, 0x7e, - 0xce, 0xef, 0xc7, 0x78, 0x38, 0x21, 0x29, 0x2c, 0x59, 0x26, 0x27, 0x1d, 0x8f, 0xda, 0x84, 0x55, - 0xe6, 0x22, 0x4b, 0xdb, 0x21, 0x15, 0xc7, 0x24, 0xd0, 0xeb, 0x90, 0x93, 0x91, 0xaf, 0x14, 0xa4, - 0x89, 0xb2, 0x32, 0x91, 0x93, 0xdb, 0x82, 0x7d, 0x1e, 0x7a, 0x13, 0xe6, 0xd4, 0xa9, 0xa9, 0x14, - 0xa5, 0xd8, 0xa2, 0x12, 0x9b, 0x0b, 0xd2, 0x3a, 0xe0, 0xeb, 0x7f, 0xd4, 0x60, 0x31, 0xb6, 0x7f, - 0x32, 0x57, 0xae, 0xc1, 0x7c, 0x27, 0x76, 0x52, 0xd4, 0x5e, 0x86, 0xab, 0x89, 0x9f, 0x22, 0x9c, - 0x90, 0x44, 0x04, 0x8a, 0x54, 0x21, 0x05, 0x15, 0x61, 0x23, 0x75, 0xa2, 0x05, 0x3e, 0x44, 0x96, - 0x62, 0x44, 0x86, 0x23, 0x64, 0xfd, 0x9f, 0x9a, 0x4c, 0xba, 0xa0, 0x46, 0xa0, 0xf5, 0x58, 0x1d, - 0xd2, 0x64, 0x08, 0xe7, 0x27, 0xd4, 0x90, 0x4b, 0x0e, 0x6f, 0xe6, 0xff, 0xe2, 0xf0, 0x5e, 0x2f, - 0xfc, 0xe6, 0xc3, 0xda, 0xcc, 0x07, 0xff, 0x58, 0x9b, 0xd1, 0x3f, 0xc9, 0x40, 0xb9, 0x49, 0x1c, - 0xc2, 0xc9, 0xdd, 0x1e, 0x97, 0x2b, 0xb8, 0x09, 0xa8, 0x43, 0x4d, 0x8b, 0xb4, 0x08, 0xb5, 0xbd, - 0xf6, 0x3e, 0xb1, 0x3c, 0xb7, 0xcd, 0xe4, 0x16, 0x65, 0x8d, 0xcf, 0x0d, 0x07, 0x35, 0x74, 0x6b, - 0x8c, 0x8b, 0x2f, 0xd0, 0x40, 0x0e, 0x94, 0x7b, 0x54, 0xfe, 0xb6, 0xb9, 0x2a, 0xe0, 0xe2, 0xe0, - 0xbc, 0x9d, 0x6e, 0xed, 0xad, 0xb8, 0xaa, 0xb1, 0x3c, 0x1c, 0xd4, 0xca, 0x09, 0x12, 0x4e, 0x82, - 0xa3, 0xef, 0xc2, 0x92, 0x47, 0x7b, 0x47, 0xa6, 0xdb, 0x24, 0x3d, 0xe2, 0xb6, 0x89, 0xcb, 0x99, - 0x3c, 0xcc, 0x05, 0x63, 0x45, 0x94, 0xdd, 0xbb, 0x23, 0x3c, 0x3c, 0x26, 0x8d, 0x1e, 0xc0, 0x72, - 0x8f, 0x7a, 0x3d, 0xb3, 0x63, 0x0a, 0xc4, 0x96, 0xe7, 0xd8, 0xd6, 0x99, 0x3c, 0xec, 0x45, 0xe3, - 0xea, 0x70, 0x50, 0x5b, 0x6e, 0x8d, 0x32, 0xcf, 0x07, 0xb5, 0x57, 0x64, 0xe8, 0x04, 0x25, 0x62, - 0xe2, 0x71, 0x18, 0x7d, 0x17, 0x0a, 0xcd, 0x3e, 0x95, 0x14, 0xf4, 0x6d, 0x28, 0xb4, 0xd5, 0x6f, - 0x15, 0xd5, 0xd7, 0x82, 0x3b, 0x29, 0x90, 0x39, 0x1f, 0xd4, 0xca, 0xe2, 0xea, 0xad, 0x07, 0x04, - 0x1c, 0xaa, 0xe8, 0x0f, 0xa1, 0xbc, 0x73, 0xda, 0xf3, 0x28, 0x0f, 0xf6, 0xeb, 0x0d, 0xc8, 0x13, - 0x49, 0x90, 0x68, 0x85, 0xa8, 0x90, 0xfa, 0x62, 0x58, 0x71, 0xc5, 0xc1, 0x26, 0xa7, 0xa6, 0xc5, - 0x55, 0x45, 0x0c, 0x0f, 0xf6, 0x8e, 0x20, 0x62, 0x9f, 0xa7, 0x3f, 0xd1, 0x00, 0x6e, 0x91, 0x10, - 0x7b, 0x0b, 0x16, 0x83, 0x43, 0x91, 0x3c, 0xab, 0x9f, 0x57, 0xda, 0x8b, 0x38, 0xc9, 0xc6, 0xa3, - 0xf2, 0xa8, 0x05, 0x2b, 0xb6, 0x6b, 0x39, 0xfd, 0x36, 0xb9, 0xe7, 0xda, 0xae, 0xcd, 0x6d, 0xd3, - 0xb1, 0x7f, 0x12, 0xd6, 0xe5, 0x2f, 0x28, 0x9c, 0x95, 0xdd, 0x0b, 0x64, 0xf0, 0x85, 0x9a, 0xfa, - 0x43, 0x28, 0xca, 0x0a, 0x21, 0x8a, 0x73, 0x54, 0xae, 0xb4, 0x17, 0x94, 0xab, 0xa0, 0xba, 0x67, - 0x26, 0x55, 0xf7, 0xd8, 0x81, 0x70, 0xa0, 0xec, 0xeb, 0x06, 0x17, 0x4e, 0x2a, 0x0b, 0x57, 0xa1, - 0x10, 0x2c, 0x5c, 0x59, 0x09, 0x1b, 0x8d, 0x00, 0x08, 0x87, 0x12, 0x31, 0x6b, 0x47, 0x90, 0xa8, - 0x76, 0xe9, 0x8c, 0xc5, 0xaa, 0x6f, 0xe6, 0xc5, 0xd5, 0x37, 0x66, 0xe9, 0x67, 0x50, 0x99, 0xd4, - 0x9d, 0xbc, 0x44, 0x3d, 0x4e, 0xef, 0x8a, 0xfe, 0x6b, 0x0d, 0x96, 0xe2, 0x48, 0xe9, 0xb7, 0x2f, - 0xbd, 0x91, 0xcb, 0xef, 0xf1, 0x58, 0x44, 0x7e, 0xab, 0xc1, 0x4a, 0x62, 0x69, 0x53, 0xed, 0xf8, - 0x14, 0x4e, 0xc5, 0x93, 0x23, 0x3b, 0x45, 0x72, 0x34, 0xa0, 0xb4, 0x1b, 0xe6, 0x3d, 0xbd, 0xbc, - 0xf3, 0xd1, 0xff, 0xa2, 0xc1, 0x7c, 0x4c, 0x83, 0xa1, 0x87, 0x30, 0x27, 0xea, 0x9b, 0xed, 0x76, - 0x54, 0x57, 0x96, 0xf2, 0xb2, 0x8c, 0x81, 0x44, 0xeb, 0x6a, 0xf9, 0x48, 0x38, 0x80, 0x44, 0x2d, - 0xc8, 0x53, 0xc2, 0xfa, 0x0e, 0x57, 0xa5, 0xfd, 0x6a, 0xca, 0x6b, 0x8d, 0x9b, 0xbc, 0xcf, 0x0c, - 0x10, 0x35, 0x0a, 0x4b, 0x7d, 0xac, 0x70, 0xf4, 0xbf, 0x67, 0xa0, 0x7c, 0xdb, 0x3c, 0x20, 0xce, - 0x3e, 0x71, 0x88, 0xc5, 0x3d, 0x8a, 0x7e, 0x0a, 0xa5, 0xae, 0xc9, 0xad, 0x23, 0x49, 0x0d, 0x7a, - 0xcb, 0x66, 0x3a, 0x43, 0x09, 0xa4, 0xfa, 0x5e, 0x04, 0xb3, 0xe3, 0x72, 0x7a, 0x66, 0xbc, 0xa2, - 0x16, 0x56, 0x8a, 0x71, 0x70, 0xdc, 0x9a, 0x7c, 0x10, 0xc8, 0xef, 0x9d, 0xd3, 0x9e, 0xb8, 0x44, - 0xa7, 0x7f, 0x87, 0x24, 0x5c, 0xc0, 0xe4, 0xfd, 0xbe, 0x4d, 0x49, 0x97, 0xb8, 0x3c, 0x7a, 0x10, - 0xec, 0x8d, 0xe0, 0xe3, 0x31, 0x8b, 0xab, 0x37, 0x60, 0x69, 0xd4, 0x79, 0xb4, 0x04, 0xd9, 0x63, - 0x72, 0xe6, 0xe7, 0x02, 0x16, 0x3f, 0xd1, 0x0a, 0xe4, 0x4e, 0x4c, 0xa7, 0xaf, 0xea, 0x0f, 0xf6, - 0x3f, 0xae, 0x67, 0xae, 0x69, 0xfa, 0xef, 0x35, 0xa8, 0x4c, 0x72, 0x04, 0x7d, 0x31, 0x06, 0x64, - 0x94, 0x94, 0x57, 0xd9, 0x77, 0xc9, 0x99, 0x8f, 0xba, 0x03, 0x05, 0xaf, 0x27, 0x9e, 0x70, 0x1e, - 0x55, 0x79, 0xfe, 0x66, 0x90, 0xbb, 0x77, 0x15, 0xfd, 0x7c, 0x50, 0xbb, 0x92, 0x80, 0x0f, 0x18, - 0x38, 0x54, 0x45, 0x3a, 0xe4, 0xa5, 0x3f, 0xe2, 0x52, 0x16, 0xed, 0x93, 0xdc, 0xfc, 0xfb, 0x92, - 0x82, 0x15, 0x47, 0xff, 0x93, 0x06, 0xb3, 0xb2, 0x3d, 0x7c, 0x08, 0x05, 0x11, 0xbf, 0xb6, 0xc9, - 0x4d, 0xe9, 0x57, 0xea, 0xc7, 0x84, 0xd0, 0xde, 0x23, 0xdc, 0x8c, 0xce, 0x57, 0x40, 0xc1, 0x21, - 0x22, 0xc2, 0x90, 0xb3, 0x39, 0xe9, 0x06, 0x1b, 0xf9, 0xd6, 0x44, 0x68, 0xf5, 0xfe, 0xad, 0x63, - 0xf3, 0xd1, 0xce, 0x29, 0x27, 0xae, 0xd8, 0x8c, 0xa8, 0x18, 0xec, 0x0a, 0x0c, 0xec, 0x43, 0xe9, - 0x7f, 0xd0, 0x20, 0x34, 0x25, 0x8e, 0x3b, 0x23, 0xce, 0xe1, 0x6d, 0xdb, 0x3d, 0x56, 0x61, 0x0d, - 0xdd, 0xd9, 0x57, 0x74, 0x1c, 0x4a, 0x5c, 0x74, 0xc5, 0x66, 0xa6, 0xbc, 0x62, 0xaf, 0x42, 0xc1, - 0xf2, 0x5c, 0x6e, 0xbb, 0xfd, 0xb1, 0xfa, 0xb2, 0xad, 0xe8, 0x38, 0x94, 0xd0, 0x9f, 0x65, 0xa1, - 0x24, 0x7c, 0x0d, 0xee, 0xf8, 0x6f, 0x42, 0xd9, 0x89, 0xef, 0x9e, 0xf2, 0xf9, 0x8a, 0x82, 0x48, - 0x9e, 0x47, 0x9c, 0x94, 0x15, 0xca, 0x87, 0x36, 0x71, 0xda, 0xa1, 0x72, 0x26, 0xa9, 0x7c, 0x33, - 0xce, 0xc4, 0x49, 0x59, 0x51, 0x67, 0x1f, 0x89, 0xbc, 0x56, 0x8d, 0x5a, 0x18, 0xda, 0xef, 0x09, - 0x22, 0xf6, 0x79, 0x17, 0xc5, 0x67, 0x76, 0xca, 0xf8, 0x5c, 0x87, 0x05, 0xb1, 0x91, 0x5e, 0x9f, - 0x07, 0xdd, 0x6c, 0x4e, 0xf6, 0x5d, 0x68, 0x38, 0xa8, 0x2d, 0xbc, 0x97, 0xe0, 0xe0, 0x11, 0xc9, - 0x89, 0xed, 0x4b, 0xfe, 0xd3, 0xb6, 0x2f, 0x62, 0xd5, 0x8e, 0xdd, 0xb5, 0x79, 0x65, 0x4e, 0x3a, - 0x11, 0xae, 0xfa, 0xb6, 0x20, 0x62, 0x9f, 0x97, 0xd8, 0xd2, 0xc2, 0xa5, 0x5b, 0xfa, 0x3e, 0x14, - 0xf7, 0x6c, 0x8b, 0x7a, 0x62, 0x2d, 0xe2, 0x62, 0x62, 0x89, 0xa6, 0x3d, 0x2c, 0xe0, 0xc1, 0x1a, - 0x03, 0xbe, 0x70, 0xc5, 0x35, 0x5d, 0xcf, 0x6f, 0xcd, 0x73, 0x91, 0x2b, 0x77, 0x04, 0x11, 0xfb, - 0xbc, 0xeb, 0x2b, 0xe2, 0x3e, 0xfa, 0xe5, 0x93, 0xda, 0xcc, 0xe3, 0x27, 0xb5, 0x99, 0x0f, 0x9f, - 0xa8, 0xbb, 0xe9, 0x5f, 0x00, 0x70, 0xf7, 0xe0, 0xc7, 0xc4, 0xf2, 0x73, 0xfe, 0xf2, 0x57, 0xb9, - 0xe8, 0x31, 0xd4, 0x30, 0x48, 0xbe, 0x60, 0x33, 0x23, 0x3d, 0x46, 0x8c, 0x87, 0x13, 0x92, 0xa8, - 0x01, 0xc5, 0xf0, 0xa5, 0xae, 0xf2, 0x7b, 0x59, 0xa9, 0x15, 0xc3, 0xe7, 0x3c, 0x8e, 0x64, 0x12, - 0x07, 0x70, 0xf6, 0xd2, 0x03, 0x68, 0x40, 0xb6, 0x6f, 0xb7, 0x65, 0x4a, 0x14, 0x8d, 0xaf, 0x06, - 0x05, 0xf0, 0xde, 0x6e, 0xf3, 0x7c, 0x50, 0x7b, 0x6d, 0xd2, 0x8c, 0x8b, 0x9f, 0xf5, 0x08, 0xab, - 0xdf, 0xdb, 0x6d, 0x62, 0xa1, 0x7c, 0x51, 0x92, 0xe6, 0xa7, 0x4c, 0xd2, 0x4d, 0x00, 0xb5, 0x6a, - 0xa1, 0xed, 0xe7, 0x46, 0x38, 0xb5, 0xb8, 0x15, 0x72, 0x70, 0x4c, 0x0a, 0x31, 0x58, 0xb6, 0x28, - 0x91, 0xbf, 0xc5, 0xd6, 0x33, 0x6e, 0x76, 0xfd, 0x77, 0x7b, 0x69, 0xf3, 0xcb, 0xe9, 0x2a, 0xa6, - 0x50, 0x33, 0x5e, 0x55, 0x66, 0x96, 0xb7, 0x47, 0xc1, 0xf0, 0x38, 0x3e, 0xf2, 0x60, 0xb9, 0xad, - 0x5e, 0x3d, 0x91, 0xd1, 0xe2, 0xd4, 0x46, 0xaf, 0x08, 0x83, 0xcd, 0x51, 0x20, 0x3c, 0x8e, 0x8d, - 0x7e, 0x08, 0xab, 0x01, 0x71, 0xfc, 0xe9, 0x59, 0x01, 0x19, 0xa9, 0xaa, 0x78, 0x0c, 0x37, 0x27, - 0x4a, 0xe1, 0x17, 0x20, 0xa0, 0x36, 0xe4, 0x1d, 0xbf, 0xbb, 0x28, 0xc9, 0x1b, 0xe1, 0x5b, 0xe9, - 0x56, 0x11, 0x65, 0x7f, 0x3d, 0xde, 0x55, 0x84, 0xcf, 0x2f, 0xd5, 0x50, 0x28, 0x6c, 0x74, 0x0a, - 0x25, 0xd3, 0x75, 0x3d, 0x6e, 0xfa, 0x8f, 0xe1, 0x79, 0x69, 0x6a, 0x6b, 0x6a, 0x53, 0x5b, 0x11, - 0xc6, 0x48, 0x17, 0x13, 0xe3, 0xe0, 0xb8, 0x29, 0xf4, 0x08, 0x16, 0xbd, 0x47, 0x2e, 0xa1, 0x98, - 0x1c, 0x12, 0x4a, 0x5c, 0x8b, 0xb0, 0x4a, 0x59, 0x5a, 0xff, 0x5a, 0x4a, 0xeb, 0x09, 0xe5, 0x28, - 0xa5, 0x93, 0x74, 0x86, 0x47, 0xad, 0xa0, 0x3a, 0xc0, 0xa1, 0xed, 0xaa, 0x5e, 0xb4, 0xb2, 0x10, - 0x8d, 0x9e, 0x6e, 0x86, 0x54, 0x1c, 0x93, 0x40, 0x5f, 0x87, 0x92, 0xe5, 0xf4, 0x19, 0x27, 0xfe, - 0x8c, 0x6b, 0x51, 0x9e, 0xa0, 0x70, 0x7d, 0xdb, 0x11, 0x0b, 0xc7, 0xe5, 0xd0, 0x11, 0xcc, 0xdb, - 0xb1, 0xa6, 0xb7, 0xb2, 0x24, 0x73, 0x71, 0x73, 0xea, 0x4e, 0x97, 0x19, 0x4b, 0xa2, 0x12, 0xc5, - 0x29, 0x38, 0x81, 0xbc, 0xfa, 0x0d, 0x28, 0x7d, 0xca, 0x1e, 0x4c, 0xf4, 0x70, 0xa3, 0x5b, 0x37, - 0x55, 0x0f, 0xf7, 0xd7, 0x0c, 0x2c, 0x24, 0x03, 0x1e, 0xbe, 0x75, 0xb4, 0x89, 0x33, 0xcb, 0xa0, - 0x2a, 0x67, 0x27, 0x56, 0x65, 0x55, 0xfc, 0x66, 0x5f, 0xa6, 0xf8, 0x6d, 0x02, 0x98, 0x3d, 0x3b, - 0xa8, 0x7b, 0x7e, 0x1d, 0x0d, 0x2b, 0x57, 0x34, 0x45, 0xc3, 0x31, 0x29, 0x39, 0x95, 0xf4, 0x5c, - 0x4e, 0x3d, 0xc7, 0x21, 0x54, 0x5d, 0xa6, 0xfe, 0x54, 0x32, 0xa4, 0xe2, 0x98, 0x04, 0xba, 0x09, - 0xe8, 0xc0, 0xf1, 0xac, 0x63, 0x19, 0x82, 0xe0, 0x9c, 0xcb, 0x2a, 0x59, 0xf0, 0x87, 0x52, 0xc6, - 0x18, 0x17, 0x5f, 0xa0, 0xa1, 0xcf, 0x41, 0xae, 0x25, 0xda, 0x0a, 0xfd, 0x2e, 0x24, 0xe7, 0x49, - 0xe8, 0x86, 0x1f, 0x09, 0x2d, 0x1c, 0xf8, 0x4c, 0x17, 0x05, 0xfd, 0x2a, 0x14, 0xb1, 0xe7, 0xf1, - 0x96, 0xc9, 0x8f, 0x18, 0xaa, 0x41, 0xae, 0x27, 0x7e, 0xa8, 0x61, 0xa1, 0x9c, 0xff, 0x4a, 0x0e, - 0xf6, 0xe9, 0xfa, 0xaf, 0x34, 0x78, 0x75, 0xe2, 0xec, 0x4e, 0x44, 0xd4, 0x0a, 0xbf, 0x94, 0x4b, - 0x61, 0x44, 0x23, 0x39, 0x1c, 0x93, 0x12, 0x9d, 0x58, 0x62, 0xe0, 0x37, 0xda, 0x89, 0x25, 0xac, - 0xe1, 0xa4, 0xac, 0xfe, 0xef, 0x0c, 0xe4, 0xfd, 0x67, 0xd9, 0x7f, 0xb9, 0xf9, 0x7e, 0x03, 0xf2, - 0x4c, 0xda, 0x51, 0xee, 0x85, 0xd5, 0xd2, 0xb7, 0x8e, 0x15, 0x57, 0x34, 0x31, 0x5d, 0xc2, 0x98, - 0xd9, 0x09, 0x92, 0x37, 0x6c, 0x62, 0xf6, 0x7c, 0x32, 0x0e, 0xf8, 0xe8, 0x1d, 0xf1, 0x0a, 0x35, - 0x59, 0xd8, 0x17, 0x56, 0x03, 0x48, 0x2c, 0xa9, 0xe7, 0x83, 0xda, 0xbc, 0x02, 0x97, 0xdf, 0x58, - 0x49, 0xa3, 0x07, 0x30, 0xd7, 0x26, 0xdc, 0xb4, 0x1d, 0xbf, 0x1d, 0x4c, 0x3d, 0x99, 0xf4, 0xc1, - 0x9a, 0xbe, 0xaa, 0x51, 0x12, 0x3e, 0xa9, 0x0f, 0x1c, 0x00, 0x8a, 0x83, 0x67, 0x79, 0x6d, 0x7f, - 0x4c, 0x9f, 0x8b, 0x0e, 0xde, 0xb6, 0xd7, 0x26, 0x58, 0x72, 0xf4, 0xc7, 0x1a, 0x94, 0x7c, 0xa4, - 0x6d, 0xb3, 0xcf, 0x08, 0xda, 0x08, 0x57, 0xe1, 0x6f, 0x77, 0x70, 0x27, 0xcf, 0xbe, 0x77, 0xd6, - 0x23, 0xe7, 0x83, 0x5a, 0x51, 0x8a, 0x89, 0x8f, 0x70, 0x01, 0xb1, 0x18, 0x65, 0x2e, 0x89, 0xd1, - 0xeb, 0x90, 0x93, 0xad, 0xb7, 0x0a, 0x66, 0xd8, 0xe8, 0xc9, 0xf6, 0x1c, 0xfb, 0x3c, 0xfd, 0xe3, - 0x0c, 0x94, 0x13, 0x8b, 0x4b, 0xd1, 0xd5, 0x85, 0xa3, 0x92, 0x4c, 0x8a, 0xf1, 0xdb, 0xe4, 0x7f, - 0xae, 0x7c, 0x1f, 0xf2, 0x96, 0x58, 0x5f, 0xf0, 0xdf, 0xad, 0x8d, 0x69, 0xb6, 0x42, 0x46, 0x26, - 0xca, 0x24, 0xf9, 0xc9, 0xb0, 0x02, 0x44, 0xb7, 0x60, 0x99, 0x12, 0x4e, 0xcf, 0xb6, 0x0e, 0x39, - 0xa1, 0xf1, 0xfe, 0x3f, 0x17, 0xf5, 0x3d, 0x78, 0x54, 0x00, 0x8f, 0xeb, 0x04, 0xa5, 0x32, 0xff, - 0x12, 0xa5, 0x52, 0x77, 0x60, 0xf6, 0x7f, 0xd8, 0xa3, 0xff, 0x00, 0x8a, 0x51, 0x17, 0xf5, 0x19, - 0x9b, 0xd4, 0x7f, 0x04, 0x05, 0x91, 0x8d, 0x41, 0xf7, 0x7f, 0xc9, 0x4d, 0x94, 0xbc, 0x23, 0x32, - 0x69, 0xee, 0x08, 0x7d, 0x13, 0xfc, 0xff, 0x99, 0x89, 0x6a, 0xea, 0xbf, 0xd8, 0x63, 0xd5, 0x34, - 0xfe, 0xfc, 0x8e, 0x8d, 0xcc, 0x7e, 0xa1, 0x01, 0xc8, 0xe7, 0xe3, 0xce, 0x09, 0x71, 0xb9, 0x70, - 0x4c, 0xec, 0xc0, 0xa8, 0x63, 0xf2, 0x18, 0x49, 0x0e, 0xba, 0x07, 0x79, 0x4f, 0x76, 0x57, 0x6a, - 0x86, 0x35, 0xe5, 0x38, 0x20, 0xcc, 0x3a, 0xbf, 0x45, 0xc3, 0x0a, 0xcc, 0x58, 0x7f, 0xfa, 0xbc, - 0x3a, 0xf3, 0xec, 0x79, 0x75, 0xe6, 0xa3, 0xe7, 0xd5, 0x99, 0x0f, 0x86, 0x55, 0xed, 0xe9, 0xb0, - 0xaa, 0x3d, 0x1b, 0x56, 0xb5, 0x8f, 0x86, 0x55, 0xed, 0xe3, 0x61, 0x55, 0x7b, 0xfc, 0x49, 0x75, - 0xe6, 0x41, 0xe6, 0x64, 0xe3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6c, 0xc5, 0x28, 0xb2, 0x54, - 0x20, 0x00, 0x00, + 0x56, 0x59, 0x98, 0xb5, 0x49, 0x80, 0xd5, 0x30, 0xc0, 0x40, 0x3a, 0xce, 0x8c, 0xa2, 0x9d, 0xcc, + 0x58, 0x95, 0x9d, 0x41, 0x0c, 0x23, 0x44, 0xa7, 0x5d, 0x71, 0x9a, 0xb4, 0xbb, 0xbd, 0x55, 0xed, + 0x4c, 0x02, 0x07, 0xf6, 0x00, 0x12, 0x07, 0x84, 0xe6, 0xc8, 0x09, 0xed, 0x08, 0x2e, 0x5c, 0x39, + 0x71, 0x81, 0x13, 0x12, 0x73, 0x1c, 0x89, 0xcb, 0x1e, 0x90, 0xb5, 0xe3, 0x3d, 0x70, 0x42, 0xdc, + 0x73, 0x42, 0x55, 0x5d, 0xdd, 0x5d, 0x6d, 0xc7, 0x93, 0xf6, 0xce, 0x82, 0xf6, 0x14, 0xf7, 0xfb, + 0xf9, 0xde, 0xab, 0xaa, 0xf7, 0x5e, 0xbd, 0x7a, 0x81, 0xbd, 0xe3, 0x6b, 0xac, 0x6e, 0x7b, 0x8d, + 0xe3, 0xfe, 0x01, 0xa1, 0x2e, 0xf1, 0x09, 0x6b, 0x9c, 0x10, 0xb7, 0xed, 0xd1, 0x86, 0x64, 0x98, + 0x3d, 0xbb, 0x6b, 0x5a, 0x47, 0xb6, 0x4b, 0xe8, 0x59, 0xa3, 0x77, 0xdc, 0xe1, 0x04, 0xd6, 0xe8, + 0x12, 0xdf, 0x6c, 0x9c, 0x6c, 0x34, 0x3a, 0xc4, 0x25, 0xd4, 0xf4, 0x49, 0xbb, 0xde, 0xa3, 0x9e, + 0xef, 0xa1, 0x2f, 0x05, 0x5a, 0x75, 0x55, 0xab, 0xde, 0x3b, 0xee, 0x70, 0x02, 0xab, 0x73, 0xad, + 0xfa, 0xc9, 0xc6, 0xea, 0x5b, 0x1d, 0xdb, 0x3f, 0xea, 0x1f, 0xd4, 0x2d, 0xaf, 0xdb, 0xe8, 0x78, + 0x1d, 0xaf, 0x21, 0x94, 0x0f, 0xfa, 0x87, 0xe2, 0x4b, 0x7c, 0x88, 0x5f, 0x01, 0xe8, 0xea, 0x44, + 0x57, 0x68, 0xdf, 0xf5, 0xed, 0x2e, 0x19, 0xf5, 0x62, 0xf5, 0xed, 0xcb, 0x14, 0x98, 0x75, 0x44, + 0xba, 0xe6, 0xa8, 0x9e, 0xfe, 0xf7, 0x2c, 0x14, 0xb6, 0x5a, 0xbb, 0xb7, 0xa8, 0xd7, 0xef, 0xa1, + 0x35, 0x98, 0x75, 0xcd, 0x2e, 0xa9, 0x68, 0x6b, 0xda, 0x7a, 0xd1, 0x98, 0x7f, 0x3a, 0xa8, 0xcd, + 0x0c, 0x07, 0xb5, 0xd9, 0x3b, 0x66, 0x97, 0x60, 0xc1, 0x41, 0x0e, 0x14, 0x4e, 0x08, 0x65, 0xb6, + 0xe7, 0xb2, 0x4a, 0x66, 0x2d, 0xbb, 0x5e, 0xda, 0xbc, 0x51, 0x4f, 0xb3, 0xfe, 0xba, 0x30, 0x70, + 0x3f, 0x50, 0xbd, 0xe9, 0xd1, 0xa6, 0xcd, 0x2c, 0xef, 0x84, 0xd0, 0x33, 0x63, 0x49, 0x5a, 0x29, + 0x48, 0x26, 0xc3, 0x91, 0x05, 0xf4, 0x0b, 0x0d, 0x96, 0x7a, 0x94, 0x1c, 0x12, 0x4a, 0x49, 0x5b, + 0xf2, 0x2b, 0xd9, 0x35, 0xed, 0x53, 0x30, 0x5b, 0x91, 0x66, 0x97, 0x5a, 0x23, 0xf8, 0x78, 0xcc, + 0x22, 0xfa, 0xbd, 0x06, 0xab, 0x8c, 0xd0, 0x13, 0x42, 0xb7, 0xda, 0x6d, 0x4a, 0x18, 0x33, 0xce, + 0xb6, 0x1d, 0x9b, 0xb8, 0xfe, 0xf6, 0x6e, 0x13, 0xb3, 0xca, 0xac, 0xd8, 0x87, 0xef, 0xa6, 0x73, + 0x68, 0x7f, 0x12, 0x8e, 0xa1, 0x4b, 0x8f, 0x56, 0x27, 0x8a, 0x30, 0xfc, 0x02, 0x37, 0xf4, 0x43, + 0x98, 0x0f, 0x0f, 0xf2, 0xb6, 0xcd, 0x7c, 0x74, 0x1f, 0xf2, 0x1d, 0xfe, 0xc1, 0x2a, 0x9a, 0x70, + 0xb0, 0x9e, 0xce, 0xc1, 0x10, 0xc3, 0x58, 0x90, 0xfe, 0xe4, 0xc5, 0x27, 0xc3, 0x12, 0x4d, 0xff, + 0x4b, 0x16, 0x4a, 0x5b, 0xad, 0x5d, 0x4c, 0x98, 0xd7, 0xa7, 0x16, 0x49, 0x11, 0x34, 0x9b, 0x00, + 0xfc, 0x2f, 0xeb, 0x99, 0x16, 0x69, 0x57, 0x32, 0x6b, 0xda, 0x7a, 0xc1, 0x40, 0x52, 0x0e, 0xee, + 0x44, 0x1c, 0xac, 0x48, 0x71, 0xd4, 0x63, 0xdb, 0x6d, 0x8b, 0xd3, 0x56, 0x50, 0xdf, 0xb1, 0xdd, + 0x36, 0x16, 0x1c, 0x74, 0x1b, 0x72, 0x27, 0x84, 0x1e, 0xf0, 0xfd, 0xe7, 0x01, 0xf1, 0x95, 0x74, + 0xcb, 0xbb, 0xcf, 0x55, 0x8c, 0xe2, 0x70, 0x50, 0xcb, 0x89, 0x9f, 0x38, 0x00, 0x41, 0x75, 0x00, + 0x76, 0xe4, 0x51, 0x5f, 0xb8, 0x53, 0xc9, 0xad, 0x65, 0xd7, 0x8b, 0xc6, 0x02, 0xf7, 0x6f, 0x3f, + 0xa2, 0x62, 0x45, 0x02, 0x5d, 0x83, 0x79, 0x66, 0xbb, 0x9d, 0xbe, 0x63, 0x52, 0x4e, 0xa8, 0xe4, + 0x85, 0x9f, 0x2b, 0xd2, 0xcf, 0xf9, 0x7d, 0x85, 0x87, 0x13, 0x92, 0xdc, 0x92, 0x65, 0xfa, 0xa4, + 0xe3, 0x51, 0x9b, 0xb0, 0xca, 0x5c, 0x6c, 0x69, 0x3b, 0xa2, 0x62, 0x45, 0x02, 0xbd, 0x0e, 0x39, + 0xb1, 0xf3, 0x95, 0x82, 0x30, 0x51, 0x96, 0x26, 0x72, 0xe2, 0x58, 0x70, 0xc0, 0x43, 0x6f, 0xc2, + 0x9c, 0xcc, 0x9a, 0x4a, 0x51, 0x88, 0x2d, 0x4a, 0xb1, 0xb9, 0x30, 0xac, 0x43, 0xbe, 0xfe, 0x27, + 0x0d, 0x16, 0x95, 0xf3, 0x13, 0xb1, 0x72, 0x0d, 0xe6, 0x3b, 0x4a, 0xa6, 0xc8, 0xb3, 0x8c, 0x56, + 0xa3, 0x66, 0x11, 0x4e, 0x48, 0x22, 0x02, 0x45, 0x2a, 0x91, 0xc2, 0x8a, 0xb0, 0x91, 0x3a, 0xd0, + 0x42, 0x1f, 0x62, 0x4b, 0x0a, 0x91, 0xe1, 0x18, 0x59, 0xff, 0x97, 0x26, 0x82, 0x2e, 0xac, 0x11, + 0x68, 0x5d, 0xa9, 0x43, 0x9a, 0xd8, 0xc2, 0xf9, 0x09, 0x35, 0xe4, 0x92, 0xe4, 0xcd, 0x7c, 0x26, + 0x92, 0xf7, 0x7a, 0xe1, 0xb7, 0x1f, 0xd4, 0x66, 0xde, 0xff, 0xe7, 0xda, 0x8c, 0xfe, 0x71, 0x06, + 0xca, 0x4d, 0xe2, 0x10, 0x9f, 0xdc, 0xed, 0xf9, 0x62, 0x05, 0x37, 0x01, 0x75, 0xa8, 0x69, 0x91, + 0x16, 0xa1, 0xb6, 0xd7, 0xde, 0x27, 0x96, 0xe7, 0xb6, 0x99, 0x38, 0xa2, 0xac, 0xf1, 0xb9, 0xe1, + 0xa0, 0x86, 0x6e, 0x8d, 0x71, 0xf1, 0x05, 0x1a, 0xc8, 0x81, 0x72, 0x8f, 0x8a, 0xdf, 0xb6, 0x2f, + 0x0b, 0x38, 0x4f, 0x9c, 0xaf, 0xa5, 0x5b, 0x7b, 0x4b, 0x55, 0x35, 0x96, 0x87, 0x83, 0x5a, 0x39, + 0x41, 0xc2, 0x49, 0x70, 0xf4, 0x3d, 0x58, 0xf2, 0x68, 0xef, 0xc8, 0x74, 0x9b, 0xa4, 0x47, 0xdc, + 0x36, 0x71, 0x7d, 0x26, 0x92, 0xb9, 0x60, 0xac, 0xf0, 0xb2, 0x7b, 0x77, 0x84, 0x87, 0xc7, 0xa4, + 0xd1, 0x03, 0x58, 0xee, 0x51, 0xaf, 0x67, 0x76, 0x4c, 0x8e, 0xd8, 0xf2, 0x1c, 0xdb, 0x3a, 0x13, + 0xc9, 0x5e, 0x34, 0xae, 0x0e, 0x07, 0xb5, 0xe5, 0xd6, 0x28, 0xf3, 0x7c, 0x50, 0x7b, 0x45, 0x6c, + 0x1d, 0xa7, 0xc4, 0x4c, 0x3c, 0x0e, 0xa3, 0xef, 0x42, 0xa1, 0xd9, 0xa7, 0x82, 0x82, 0xbe, 0x03, + 0x85, 0xb6, 0xfc, 0x2d, 0x77, 0xf5, 0xb5, 0xf0, 0x4e, 0x0a, 0x65, 0xce, 0x07, 0xb5, 0x32, 0xbf, + 0x45, 0xeb, 0x21, 0x01, 0x47, 0x2a, 0xfa, 0x43, 0x28, 0xef, 0x9c, 0xf6, 0x3c, 0xea, 0x87, 0xe7, + 0xf5, 0x06, 0xe4, 0x89, 0x20, 0x08, 0xb4, 0x42, 0x5c, 0x48, 0x03, 0x31, 0x2c, 0xb9, 0x3c, 0xb1, + 0xc9, 0xa9, 0x69, 0xf9, 0xb2, 0x22, 0x46, 0x89, 0xbd, 0xc3, 0x89, 0x38, 0xe0, 0xe9, 0x4f, 0x34, + 0x80, 0x5b, 0x24, 0xc2, 0xde, 0x82, 0xc5, 0x30, 0x29, 0x92, 0xb9, 0xfa, 0x79, 0xa9, 0xbd, 0x88, + 0x93, 0x6c, 0x3c, 0x2a, 0x8f, 0x5a, 0xb0, 0x62, 0xbb, 0x96, 0xd3, 0x6f, 0x93, 0x7b, 0xae, 0xed, + 0xda, 0xbe, 0x6d, 0x3a, 0xf6, 0x4f, 0xa3, 0xba, 0xfc, 0x05, 0x89, 0xb3, 0xb2, 0x7b, 0x81, 0x0c, + 0xbe, 0x50, 0x53, 0x7f, 0x08, 0x45, 0x51, 0x21, 0x78, 0x71, 0x8e, 0xcb, 0x95, 0xf6, 0x82, 0x72, + 0x15, 0x56, 0xf7, 0xcc, 0xa4, 0xea, 0xae, 0x24, 0x84, 0x03, 0xe5, 0x40, 0x37, 0xbc, 0x70, 0x52, + 0x59, 0xb8, 0x0a, 0x85, 0x70, 0xe1, 0xd2, 0x4a, 0xd4, 0x68, 0x84, 0x40, 0x38, 0x92, 0x50, 0xac, + 0x1d, 0x41, 0xa2, 0xda, 0xa5, 0x33, 0xa6, 0x54, 0xdf, 0xcc, 0x8b, 0xab, 0xaf, 0x62, 0xe9, 0xe7, + 0x50, 0x99, 0xd4, 0x9d, 0xbc, 0x44, 0x3d, 0x4e, 0xef, 0x8a, 0xfe, 0x1b, 0x0d, 0x96, 0x54, 0xa4, + 0xf4, 0xc7, 0x97, 0xde, 0xc8, 0xe5, 0xf7, 0xb8, 0xb2, 0x23, 0xbf, 0xd3, 0x60, 0x25, 0xb1, 0xb4, + 0xa9, 0x4e, 0x7c, 0x0a, 0xa7, 0xd4, 0xe0, 0xc8, 0x4e, 0x11, 0x1c, 0x0d, 0x28, 0xed, 0x46, 0x71, + 0x4f, 0x2f, 0xef, 0x7c, 0xf4, 0xbf, 0x6a, 0x30, 0xaf, 0x68, 0x30, 0xf4, 0x10, 0xe6, 0x78, 0x7d, + 0xb3, 0xdd, 0x8e, 0xec, 0xca, 0x52, 0x5e, 0x96, 0x0a, 0x48, 0xbc, 0xae, 0x56, 0x80, 0x84, 0x43, + 0x48, 0xd4, 0x82, 0x3c, 0x25, 0xac, 0xef, 0xf8, 0xb2, 0xb4, 0x5f, 0x4d, 0x79, 0xad, 0xf9, 0xa6, + 0xdf, 0x67, 0x06, 0xf0, 0x1a, 0x85, 0x85, 0x3e, 0x96, 0x38, 0xfa, 0x3f, 0x32, 0x50, 0xbe, 0x6d, + 0x1e, 0x10, 0x67, 0x9f, 0x38, 0xc4, 0xf2, 0x3d, 0x8a, 0x7e, 0x06, 0xa5, 0xae, 0xe9, 0x5b, 0x47, + 0x82, 0x1a, 0xf6, 0x96, 0xcd, 0x74, 0x86, 0x12, 0x48, 0xf5, 0xbd, 0x18, 0x66, 0xc7, 0xf5, 0xe9, + 0x99, 0xf1, 0x8a, 0x5c, 0x58, 0x49, 0xe1, 0x60, 0xd5, 0x9a, 0x78, 0x10, 0x88, 0xef, 0x9d, 0xd3, + 0x1e, 0xbf, 0x44, 0xa7, 0x7f, 0x87, 0x24, 0x5c, 0xc0, 0xe4, 0xbd, 0xbe, 0x4d, 0x49, 0x97, 0xb8, + 0x7e, 0xfc, 0x20, 0xd8, 0x1b, 0xc1, 0xc7, 0x63, 0x16, 0x57, 0x6f, 0xc0, 0xd2, 0xa8, 0xf3, 0x68, + 0x09, 0xb2, 0xc7, 0xe4, 0x2c, 0x88, 0x05, 0xcc, 0x7f, 0xa2, 0x15, 0xc8, 0x9d, 0x98, 0x4e, 0x5f, + 0xd6, 0x1f, 0x1c, 0x7c, 0x5c, 0xcf, 0x5c, 0xd3, 0xf4, 0x3f, 0x68, 0x50, 0x99, 0xe4, 0x08, 0xfa, + 0xa2, 0x02, 0x64, 0x94, 0xa4, 0x57, 0xd9, 0x77, 0xc8, 0x59, 0x80, 0xba, 0x03, 0x05, 0xaf, 0xc7, + 0x9f, 0x70, 0x1e, 0x95, 0x71, 0xfe, 0x66, 0x18, 0xbb, 0x77, 0x25, 0xfd, 0x7c, 0x50, 0xbb, 0x92, + 0x80, 0x0f, 0x19, 0x38, 0x52, 0x45, 0x3a, 0xe4, 0x85, 0x3f, 0xfc, 0x52, 0xe6, 0xed, 0x93, 0x38, + 0xfc, 0xfb, 0x82, 0x82, 0x25, 0x47, 0xff, 0xb3, 0x06, 0xb3, 0xa2, 0x3d, 0x7c, 0x08, 0x05, 0xbe, + 0x7f, 0x6d, 0xd3, 0x37, 0x85, 0x5f, 0xa9, 0x1f, 0x13, 0x5c, 0x7b, 0x8f, 0xf8, 0x66, 0x9c, 0x5f, + 0x21, 0x05, 0x47, 0x88, 0x08, 0x43, 0xce, 0xf6, 0x49, 0x37, 0x3c, 0xc8, 0xb7, 0x26, 0x42, 0xcb, + 0xa7, 0x6c, 0x1d, 0x9b, 0x8f, 0x76, 0x4e, 0x7d, 0xe2, 0xf2, 0xc3, 0x88, 0x8b, 0xc1, 0x2e, 0xc7, + 0xc0, 0x01, 0x94, 0xfe, 0x47, 0x0d, 0x22, 0x53, 0x3c, 0xdd, 0x19, 0x71, 0x0e, 0x6f, 0xdb, 0xee, + 0xb1, 0xdc, 0xd6, 0xc8, 0x9d, 0x7d, 0x49, 0xc7, 0x91, 0xc4, 0x45, 0x57, 0x6c, 0x66, 0xca, 0x2b, + 0xf6, 0x2a, 0x14, 0x2c, 0xcf, 0xf5, 0x6d, 0xb7, 0x3f, 0x56, 0x5f, 0xb6, 0x25, 0x1d, 0x47, 0x12, + 0xfa, 0xb3, 0x2c, 0x94, 0xb8, 0xaf, 0xe1, 0x1d, 0xff, 0x2d, 0x28, 0x3b, 0xea, 0xe9, 0x49, 0x9f, + 0xaf, 0x48, 0x88, 0x64, 0x3e, 0xe2, 0xa4, 0x2c, 0x57, 0x3e, 0xb4, 0x89, 0xd3, 0x8e, 0x94, 0x33, + 0x49, 0xe5, 0x9b, 0x2a, 0x13, 0x27, 0x65, 0x79, 0x9d, 0x7d, 0xc4, 0xe3, 0x5a, 0x36, 0x6a, 0xd1, + 0xd6, 0x7e, 0x9f, 0x13, 0x71, 0xc0, 0xbb, 0x68, 0x7f, 0x66, 0xa7, 0xdc, 0x9f, 0xeb, 0xb0, 0xc0, + 0x0f, 0xd2, 0xeb, 0xfb, 0x61, 0x37, 0x9b, 0x13, 0x7d, 0x17, 0x1a, 0x0e, 0x6a, 0x0b, 0xef, 0x26, + 0x38, 0x78, 0x44, 0x72, 0x62, 0xfb, 0x92, 0xff, 0xa4, 0xed, 0x0b, 0x5f, 0xb5, 0x63, 0x77, 0x6d, + 0xbf, 0x32, 0x27, 0x9c, 0x88, 0x56, 0x7d, 0x9b, 0x13, 0x71, 0xc0, 0x4b, 0x1c, 0x69, 0xe1, 0xd2, + 0x23, 0x7d, 0x0f, 0x8a, 0x7b, 0xb6, 0x45, 0x3d, 0xbe, 0x16, 0x7e, 0x31, 0xb1, 0x44, 0xd3, 0x1e, + 0x15, 0xf0, 0x70, 0x8d, 0x21, 0x9f, 0xbb, 0xe2, 0x9a, 0xae, 0x17, 0xb4, 0xe6, 0xb9, 0xd8, 0x95, + 0x3b, 0x9c, 0x88, 0x03, 0xde, 0xf5, 0x15, 0x7e, 0x1f, 0xfd, 0xea, 0x49, 0x6d, 0xe6, 0xf1, 0x93, + 0xda, 0xcc, 0x07, 0x4f, 0xe4, 0xdd, 0xf4, 0x6f, 0x00, 0xb8, 0x7b, 0xf0, 0x13, 0x62, 0x05, 0x31, + 0x7f, 0xf9, 0xab, 0x9c, 0xf7, 0x18, 0x72, 0x18, 0x24, 0x5e, 0xb0, 0x99, 0x91, 0x1e, 0x43, 0xe1, + 0xe1, 0x84, 0x24, 0x6a, 0x40, 0x31, 0x7a, 0xa9, 0xcb, 0xf8, 0x5e, 0x96, 0x6a, 0xc5, 0xe8, 0x39, + 0x8f, 0x63, 0x99, 0x44, 0x02, 0xce, 0x5e, 0x9a, 0x80, 0x06, 0x64, 0xfb, 0x76, 0x5b, 0x84, 0x44, + 0xd1, 0xf8, 0x6a, 0x58, 0x00, 0xef, 0xed, 0x36, 0xcf, 0x07, 0xb5, 0xd7, 0x26, 0x8d, 0xb9, 0xfc, + 0xb3, 0x1e, 0x61, 0xf5, 0x7b, 0xbb, 0x4d, 0xcc, 0x95, 0x2f, 0x0a, 0xd2, 0xfc, 0x94, 0x41, 0xba, + 0x09, 0x20, 0x57, 0xcd, 0xb5, 0x83, 0xd8, 0x88, 0xa6, 0x16, 0xb7, 0x22, 0x0e, 0x56, 0xa4, 0x10, + 0x83, 0x65, 0x8b, 0x12, 0xf1, 0x9b, 0x1f, 0x3d, 0xf3, 0xcd, 0x6e, 0xf0, 0x6e, 0x2f, 0x6d, 0x7e, + 0x39, 0x5d, 0xc5, 0xe4, 0x6a, 0xc6, 0xab, 0xd2, 0xcc, 0xf2, 0xf6, 0x28, 0x18, 0x1e, 0xc7, 0x47, + 0x1e, 0x2c, 0xb7, 0xe5, 0xab, 0x27, 0x36, 0x5a, 0x9c, 0xda, 0xe8, 0x15, 0x6e, 0xb0, 0x39, 0x0a, + 0x84, 0xc7, 0xb1, 0xd1, 0x8f, 0x60, 0x35, 0x24, 0x8e, 0x3f, 0x3d, 0x2b, 0x20, 0x76, 0xaa, 0xca, + 0x1f, 0xc3, 0xcd, 0x89, 0x52, 0xf8, 0x05, 0x08, 0xa8, 0x0d, 0x79, 0x27, 0xe8, 0x2e, 0x4a, 0xe2, + 0x46, 0xf8, 0x76, 0xba, 0x55, 0xc4, 0xd1, 0x5f, 0x57, 0xbb, 0x8a, 0xe8, 0xf9, 0x25, 0x1b, 0x0a, + 0x89, 0x8d, 0x4e, 0xa1, 0x64, 0xba, 0xae, 0xe7, 0x9b, 0xc1, 0x63, 0x78, 0x5e, 0x98, 0xda, 0x9a, + 0xda, 0xd4, 0x56, 0x8c, 0x31, 0xd2, 0xc5, 0x28, 0x1c, 0xac, 0x9a, 0x42, 0x8f, 0x60, 0xd1, 0x7b, + 0xe4, 0x12, 0x8a, 0xc9, 0x21, 0xa1, 0xc4, 0xb5, 0x08, 0xab, 0x94, 0x85, 0xf5, 0xaf, 0xa7, 0xb4, + 0x9e, 0x50, 0x8e, 0x43, 0x3a, 0x49, 0x67, 0x78, 0xd4, 0x0a, 0xaa, 0x03, 0x1c, 0xda, 0xae, 0xec, + 0x45, 0x2b, 0x0b, 0xf1, 0xe8, 0xe9, 0x66, 0x44, 0xc5, 0x8a, 0x04, 0xfa, 0x06, 0x94, 0x2c, 0xa7, + 0xcf, 0x7c, 0x12, 0xcc, 0xb8, 0x16, 0x45, 0x06, 0x45, 0xeb, 0xdb, 0x8e, 0x59, 0x58, 0x95, 0x43, + 0x47, 0x30, 0x6f, 0x2b, 0x4d, 0x6f, 0x65, 0x49, 0xc4, 0xe2, 0xe6, 0xd4, 0x9d, 0x2e, 0x33, 0x96, + 0x78, 0x25, 0x52, 0x29, 0x38, 0x81, 0xbc, 0xfa, 0x4d, 0x28, 0x7d, 0xc2, 0x1e, 0x8c, 0xf7, 0x70, + 0xa3, 0x47, 0x37, 0x55, 0x0f, 0xf7, 0xb7, 0x0c, 0x2c, 0x24, 0x37, 0x3c, 0x7a, 0xeb, 0x68, 0x13, + 0x67, 0x96, 0x61, 0x55, 0xce, 0x4e, 0xac, 0xca, 0xb2, 0xf8, 0xcd, 0xbe, 0x4c, 0xf1, 0xdb, 0x04, + 0x30, 0x7b, 0x76, 0x58, 0xf7, 0x82, 0x3a, 0x1a, 0x55, 0xae, 0x78, 0x8a, 0x86, 0x15, 0x29, 0x31, + 0x95, 0xf4, 0x5c, 0x9f, 0x7a, 0x8e, 0x43, 0xa8, 0xbc, 0x4c, 0x83, 0xa9, 0x64, 0x44, 0xc5, 0x8a, + 0x04, 0xba, 0x09, 0xe8, 0xc0, 0xf1, 0xac, 0x63, 0xb1, 0x05, 0x61, 0x9e, 0x8b, 0x2a, 0x59, 0x08, + 0x86, 0x52, 0xc6, 0x18, 0x17, 0x5f, 0xa0, 0xa1, 0xcf, 0x41, 0xae, 0xc5, 0xdb, 0x0a, 0xfd, 0x2e, + 0x24, 0xe7, 0x49, 0xe8, 0x46, 0xb0, 0x13, 0x5a, 0x34, 0xf0, 0x99, 0x6e, 0x17, 0xf4, 0xab, 0x50, + 0xc4, 0x9e, 0xe7, 0xb7, 0x4c, 0xff, 0x88, 0xa1, 0x1a, 0xe4, 0x7a, 0xfc, 0x87, 0x1c, 0x16, 0x8a, + 0xf9, 0xaf, 0xe0, 0xe0, 0x80, 0xae, 0xff, 0x5a, 0x83, 0x57, 0x27, 0xce, 0xee, 0xf8, 0x8e, 0x5a, + 0xd1, 0x97, 0x74, 0x29, 0xda, 0xd1, 0x58, 0x0e, 0x2b, 0x52, 0xbc, 0x13, 0x4b, 0x0c, 0xfc, 0x46, + 0x3b, 0xb1, 0x84, 0x35, 0x9c, 0x94, 0xd5, 0xff, 0x93, 0x81, 0x7c, 0xf0, 0x2c, 0xfb, 0x1f, 0x37, + 0xdf, 0x6f, 0x40, 0x9e, 0x09, 0x3b, 0xd2, 0xbd, 0xa8, 0x5a, 0x06, 0xd6, 0xb1, 0xe4, 0xf2, 0x26, + 0xa6, 0x4b, 0x18, 0x33, 0x3b, 0x61, 0xf0, 0x46, 0x4d, 0xcc, 0x5e, 0x40, 0xc6, 0x21, 0x1f, 0xbd, + 0xcd, 0x5f, 0xa1, 0x26, 0x8b, 0xfa, 0xc2, 0x6a, 0x08, 0x89, 0x05, 0xf5, 0x7c, 0x50, 0x9b, 0x97, + 0xe0, 0xe2, 0x1b, 0x4b, 0x69, 0xf4, 0x00, 0xe6, 0xda, 0xc4, 0x37, 0x6d, 0x27, 0x68, 0x07, 0x53, + 0x4f, 0x26, 0x03, 0xb0, 0x66, 0xa0, 0x6a, 0x94, 0xb8, 0x4f, 0xf2, 0x03, 0x87, 0x80, 0x3c, 0xf1, + 0x2c, 0xaf, 0x1d, 0x8c, 0xe9, 0x73, 0x71, 0xe2, 0x6d, 0x7b, 0x6d, 0x82, 0x05, 0x47, 0x7f, 0xac, + 0x41, 0x29, 0x40, 0xda, 0x36, 0xfb, 0x8c, 0xa0, 0x8d, 0x68, 0x15, 0xc1, 0x71, 0x87, 0x77, 0xf2, + 0xec, 0xbb, 0x67, 0x3d, 0x72, 0x3e, 0xa8, 0x15, 0x85, 0x18, 0xff, 0x88, 0x16, 0xa0, 0xec, 0x51, + 0xe6, 0x92, 0x3d, 0x7a, 0x1d, 0x72, 0xa2, 0xf5, 0x96, 0x9b, 0x19, 0x35, 0x7a, 0xa2, 0x3d, 0xc7, + 0x01, 0x4f, 0xff, 0x28, 0x03, 0xe5, 0xc4, 0xe2, 0x52, 0x74, 0x75, 0xd1, 0xa8, 0x24, 0x93, 0x62, + 0xfc, 0x36, 0xf9, 0x9f, 0x2b, 0x3f, 0x80, 0xbc, 0xc5, 0xd7, 0x17, 0xfe, 0x77, 0x6b, 0x63, 0x9a, + 0xa3, 0x10, 0x3b, 0x13, 0x47, 0x92, 0xf8, 0x64, 0x58, 0x02, 0xa2, 0x5b, 0xb0, 0x4c, 0x89, 0x4f, + 0xcf, 0xb6, 0x0e, 0x7d, 0x42, 0xd5, 0xfe, 0x3f, 0x17, 0xf7, 0x3d, 0x78, 0x54, 0x00, 0x8f, 0xeb, + 0x84, 0xa5, 0x32, 0xff, 0x12, 0xa5, 0x52, 0x77, 0x60, 0xf6, 0xff, 0xd8, 0xa3, 0xff, 0x10, 0x8a, + 0x71, 0x17, 0xf5, 0x29, 0x9b, 0xd4, 0x7f, 0x0c, 0x05, 0x1e, 0x8d, 0x61, 0xf7, 0x7f, 0xc9, 0x4d, + 0x94, 0xbc, 0x23, 0x32, 0x69, 0xee, 0x08, 0x7d, 0x13, 0x82, 0xff, 0x99, 0xf1, 0x6a, 0x1a, 0xbc, + 0xd8, 0x95, 0x6a, 0xaa, 0x3e, 0xbf, 0x95, 0x91, 0xd9, 0x2f, 0x35, 0x00, 0xf1, 0x7c, 0xdc, 0x39, + 0x21, 0xae, 0xcf, 0x1d, 0xe3, 0x27, 0x30, 0xea, 0x98, 0x48, 0x23, 0xc1, 0x41, 0xf7, 0x20, 0xef, + 0x89, 0xee, 0x4a, 0xce, 0xb0, 0xa6, 0x1c, 0x07, 0x44, 0x51, 0x17, 0xb4, 0x68, 0x58, 0x82, 0x19, + 0xeb, 0x4f, 0x9f, 0x57, 0x67, 0x9e, 0x3d, 0xaf, 0xce, 0x7c, 0xf8, 0xbc, 0x3a, 0xf3, 0xfe, 0xb0, + 0xaa, 0x3d, 0x1d, 0x56, 0xb5, 0x67, 0xc3, 0xaa, 0xf6, 0xe1, 0xb0, 0xaa, 0x7d, 0x34, 0xac, 0x6a, + 0x8f, 0x3f, 0xae, 0xce, 0x3c, 0xc8, 0x9c, 0x6c, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, 0x0e, 0xc8, + 0x1d, 0xca, 0x1f, 0x20, 0x00, 0x00, } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto index bd5abcb79..df386bc9a 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -23,7 +23,6 @@ package k8s.io.apimachinery.pkg.apis.meta.v1; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; @@ -49,6 +48,7 @@ message APIGroup { // The server returns only those CIDRs that it thinks that the client can match. // For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. // Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP. + // +optional repeated ServerAddressByClientCIDR serverAddressByClientCIDRs = 4; } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go index 1f7f07e81..ab62ff424 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go @@ -21,7 +21,7 @@ import ( "reflect" "testing" - jsoniter "github.com/json-iterator/go" + k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json" ) type GroupVersionHolder struct { @@ -47,7 +47,8 @@ func TestGroupVersionUnmarshalJSON(t *testing.T) { t.Errorf("JSON codec failed to unmarshal input '%s': expected %+v, got %+v", c.input, c.expect, result.GV) } // test the json-iterator codec - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(c.input, &result); err != nil { + iter := k8s_json.CaseSensitiveJsonIterator() + if err := iter.Unmarshal(c.input, &result); err != nil { t.Errorf("json-iterator codec failed to unmarshal input '%v': %v", c.input, err) } if !reflect.DeepEqual(result.GV, c.expect) { diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/helpers_test.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/helpers_test.go index fba6b158e..fa4249300 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/helpers_test.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/helpers_test.go @@ -17,6 +17,7 @@ limitations under the License. package v1 import ( + "fmt" "reflect" "strings" "testing" @@ -70,15 +71,21 @@ func TestLabelSelectorAsSelector(t *testing.T) { } for i, tc := range tc { + inCopy := tc.in.DeepCopy() out, err := LabelSelectorAsSelector(tc.in) + // after calling LabelSelectorAsSelector, tc.in shouldn't be modified + if !reflect.DeepEqual(inCopy, tc.in) { + t.Errorf("[%v]expected:\n\t%#v\nbut got:\n\t%#v", i, inCopy, tc.in) + } if err == nil && tc.expectErr { t.Errorf("[%v]expected error but got none.", i) } if err != nil && !tc.expectErr { t.Errorf("[%v]did not expect error but got: %v", i, err) } - if !reflect.DeepEqual(out, tc.out) { - t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out) + // fmt.Sprint() over String() as nil.String() will panic + if fmt.Sprint(out) != fmt.Sprint(tc.out) { + t.Errorf("[%v]expected:\n\t%s\nbut got:\n\t%s", i, fmt.Sprint(tc.out), fmt.Sprint(out)) } } } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go index 7e5bc2d4e..6f6c5111b 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go @@ -104,7 +104,10 @@ func (t *MicroTime) UnmarshalJSON(b []byte) error { } var str string - json.Unmarshal(b, &str) + err := json.Unmarshal(b, &str) + if err != nil { + return err + } pt, err := time.Parse(RFC3339Micro, str) if err != nil { diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/time.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/time.go index 5041954f7..efff656e1 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/time.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/time.go @@ -106,7 +106,10 @@ func (t *Time) UnmarshalJSON(b []byte) error { } var str string - json.Unmarshal(b, &str) + err := json.Unmarshal(b, &str) + if err != nil { + return err + } pt, err := time.Parse(time.RFC3339, str) if err != nil { diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types.go index 917efb37f..e93df1846 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types.go @@ -799,7 +799,8 @@ type APIGroup struct { // The server returns only those CIDRs that it thinks that the client can match. // For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. // Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP. - ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs" protobuf:"bytes,4,rep,name=serverAddressByClientCIDRs"` + // +optional + ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs,omitempty" protobuf:"bytes,4,rep,name=serverAddressByClientCIDRs"` } // ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go index caf929ee0..f91d8a81f 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_APIGroup = map[string]string{ "": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "name": "name is the name of the group.", diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go index 116f7505a..ed5f20c40 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go @@ -21,7 +21,7 @@ import ( "reflect" "testing" - jsoniter "github.com/json-iterator/go" + k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json" ) func TestVerbsUgorjiMarshalJSON(t *testing.T) { @@ -45,7 +45,7 @@ func TestVerbsUgorjiMarshalJSON(t *testing.T) { } } -func TestVerbsUgorjiUnmarshalJSON(t *testing.T) { +func TestVerbsUJsonIterUnmarshalJSON(t *testing.T) { cases := []struct { input string result APIResource @@ -56,9 +56,10 @@ func TestVerbsUgorjiUnmarshalJSON(t *testing.T) { {`{"verbs":["delete"]}`, APIResource{Verbs: Verbs([]string{"delete"})}}, } + iter := k8s_json.CaseSensitiveJsonIterator() for i, c := range cases { var result APIResource - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(c.input), &result); err != nil { + if err := iter.Unmarshal([]byte(c.input), &result); err != nil { t.Errorf("[%d] Failed to unmarshal input '%v': %v", i, c.input, err) } if !reflect.DeepEqual(result, c.result) { diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go index 08705ac84..fc138e75a 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go @@ -18,7 +18,6 @@ package unstructured import ( gojson "encoding/json" - "errors" "fmt" "io" "strings" @@ -34,14 +33,17 @@ import ( // Returns false if the value is missing. // No error is returned for a nil field. func NestedFieldCopy(obj map[string]interface{}, fields ...string) (interface{}, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return nil, found, err } return runtime.DeepCopyJSONValue(val), true, nil } -func nestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{}, bool, error) { +// NestedFieldNoCopy returns a reference to a nested field. +// Returns false if value is not found and an error if unable +// to traverse obj. +func NestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{}, bool, error) { var val interface{} = obj for i, field := range fields { @@ -60,7 +62,7 @@ func nestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{ // NestedString returns the string value of a nested field. // Returns false if value is not found and an error if not a string. func NestedString(obj map[string]interface{}, fields ...string) (string, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return "", found, err } @@ -74,7 +76,7 @@ func NestedString(obj map[string]interface{}, fields ...string) (string, bool, e // NestedBool returns the bool value of a nested field. // Returns false if value is not found and an error if not a bool. func NestedBool(obj map[string]interface{}, fields ...string) (bool, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return false, found, err } @@ -88,7 +90,7 @@ func NestedBool(obj map[string]interface{}, fields ...string) (bool, bool, error // NestedFloat64 returns the float64 value of a nested field. // Returns false if value is not found and an error if not a float64. func NestedFloat64(obj map[string]interface{}, fields ...string) (float64, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return 0, found, err } @@ -102,7 +104,7 @@ func NestedFloat64(obj map[string]interface{}, fields ...string) (float64, bool, // NestedInt64 returns the int64 value of a nested field. // Returns false if value is not found and an error if not an int64. func NestedInt64(obj map[string]interface{}, fields ...string) (int64, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return 0, found, err } @@ -116,7 +118,7 @@ func NestedInt64(obj map[string]interface{}, fields ...string) (int64, bool, err // NestedStringSlice returns a copy of []string value of a nested field. // Returns false if value is not found and an error if not a []interface{} or contains non-string items in the slice. func NestedStringSlice(obj map[string]interface{}, fields ...string) ([]string, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return nil, found, err } @@ -138,7 +140,7 @@ func NestedStringSlice(obj map[string]interface{}, fields ...string) ([]string, // NestedSlice returns a deep copy of []interface{} value of a nested field. // Returns false if value is not found and an error if not a []interface{}. func NestedSlice(obj map[string]interface{}, fields ...string) ([]interface{}, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return nil, found, err } @@ -180,7 +182,7 @@ func NestedMap(obj map[string]interface{}, fields ...string) (map[string]interfa // nestedMapNoCopy returns a map[string]interface{} value of a nested field. // Returns false if value is not found and an error if not a map[string]interface{}. func nestedMapNoCopy(obj map[string]interface{}, fields ...string) (map[string]interface{}, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return nil, found, err } @@ -433,43 +435,17 @@ func (s unstructuredJSONScheme) decodeToList(data []byte, list *UnstructuredList return nil } -// UnstructuredObjectConverter is an ObjectConverter for use with -// Unstructured objects. Since it has no schema or type information, -// it will only succeed for no-op conversions. This is provided as a -// sane implementation for APIs that require an object converter. -type UnstructuredObjectConverter struct{} - -func (UnstructuredObjectConverter) Convert(in, out, context interface{}) error { - unstructIn, ok := in.(*Unstructured) - if !ok { - return fmt.Errorf("input type %T in not valid for unstructured conversion", in) - } - - unstructOut, ok := out.(*Unstructured) - if !ok { - return fmt.Errorf("output type %T in not valid for unstructured conversion", out) - } - - // maybe deep copy the map? It is documented in the - // ObjectConverter interface that this function is not - // guaranteed to not mutate the input. Or maybe set the input - // object to nil. - unstructOut.Object = unstructIn.Object - return nil +type JSONFallbackEncoder struct { + runtime.Encoder } -func (UnstructuredObjectConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { - if kind := in.GetObjectKind().GroupVersionKind(); !kind.Empty() { - gvk, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{kind}) - if !ok { - // TODO: should this be a typed error? - return nil, fmt.Errorf("%v is unstructured and is not suitable for converting to %q", kind, target) +func (c JSONFallbackEncoder) Encode(obj runtime.Object, w io.Writer) error { + err := c.Encoder.Encode(obj, w) + if runtime.IsNotRegisteredError(err) { + switch obj.(type) { + case *Unstructured, *UnstructuredList: + return UnstructuredJSONScheme.Encode(obj, w) } - in.GetObjectKind().SetGroupVersionKind(gvk) } - return in, nil -} - -func (UnstructuredObjectConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { - return "", "", errors.New("unstructured cannot convert field labels") + return err } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers_test.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers_test.go index 9e774d1c1..d97996211 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers_test.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers_test.go @@ -58,3 +58,79 @@ func TestRemoveNestedField(t *testing.T) { RemoveNestedField(obj, "x") // Remove of a non-existent field assert.Empty(t, obj) } + +func TestNestedFieldNoCopy(t *testing.T) { + target := map[string]interface{}{"foo": "bar"} + + obj := map[string]interface{}{ + "a": map[string]interface{}{ + "b": target, + "c": nil, + "d": []interface{}{"foo"}, + }, + } + + // case 1: field exists and is non-nil + res, exists, err := NestedFieldNoCopy(obj, "a", "b") + assert.True(t, exists) + assert.Nil(t, err) + assert.Equal(t, target, res) + target["foo"] = "baz" + assert.Equal(t, target["foo"], res.(map[string]interface{})["foo"], "result should be a reference to the expected item") + + // case 2: field exists and is nil + res, exists, err = NestedFieldNoCopy(obj, "a", "c") + assert.True(t, exists) + assert.Nil(t, err) + assert.Nil(t, res) + + // case 3: error traversing obj + res, exists, err = NestedFieldNoCopy(obj, "a", "d", "foo") + assert.False(t, exists) + assert.NotNil(t, err) + assert.Nil(t, res) + + // case 4: field does not exist + res, exists, err = NestedFieldNoCopy(obj, "a", "e") + assert.False(t, exists) + assert.Nil(t, err) + assert.Nil(t, res) +} + +func TestNestedFieldCopy(t *testing.T) { + target := map[string]interface{}{"foo": "bar"} + + obj := map[string]interface{}{ + "a": map[string]interface{}{ + "b": target, + "c": nil, + "d": []interface{}{"foo"}, + }, + } + + // case 1: field exists and is non-nil + res, exists, err := NestedFieldCopy(obj, "a", "b") + assert.True(t, exists) + assert.Nil(t, err) + assert.Equal(t, target, res) + target["foo"] = "baz" + assert.NotEqual(t, target["foo"], res.(map[string]interface{})["foo"], "result should be a copy of the expected item") + + // case 2: field exists and is nil + res, exists, err = NestedFieldCopy(obj, "a", "c") + assert.True(t, exists) + assert.Nil(t, err) + assert.Nil(t, res) + + // case 3: error traversing obj + res, exists, err = NestedFieldCopy(obj, "a", "d", "foo") + assert.False(t, exists) + assert.NotNil(t, err) + assert.Nil(t, res) + + // case 4: field does not exist + res, exists, err = NestedFieldCopy(obj, "a", "e") + assert.False(t, exists) + assert.Nil(t, err) + assert.Nil(t, res) +} diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go index 2a1333049..548a01e59 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go @@ -58,6 +58,26 @@ func (obj *Unstructured) IsList() bool { _, ok = field.([]interface{}) return ok } +func (obj *Unstructured) ToList() (*UnstructuredList, error) { + if !obj.IsList() { + // return an empty list back + return &UnstructuredList{Object: obj.Object}, nil + } + + ret := &UnstructuredList{} + ret.Object = obj.Object + + err := obj.EachListItem(func(item runtime.Object) error { + castItem := item.(*Unstructured) + ret.Items = append(ret.Items, *castItem) + return nil + }) + if err != nil { + return nil, err + } + + return ret, nil +} func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { field, ok := obj.Object["items"] @@ -82,7 +102,7 @@ func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { func (obj *Unstructured) UnstructuredContent() map[string]interface{} { if obj.Object == nil { - obj.Object = make(map[string]interface{}) + return make(map[string]interface{}) } return obj.Object } @@ -138,7 +158,7 @@ func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) { } func (u *Unstructured) GetOwnerReferences() []metav1.OwnerReference { - field, found, err := nestedFieldNoCopy(u.Object, "metadata", "ownerReferences") + field, found, err := NestedFieldNoCopy(u.Object, "metadata", "ownerReferences") if !found || err != nil { return nil } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go index 57d78a09d..bf3fd023f 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go @@ -53,19 +53,18 @@ func (u *UnstructuredList) EachListItem(fn func(runtime.Object) error) error { } // UnstructuredContent returns a map contain an overlay of the Items field onto -// the Object field. Items always overwrites overlay. Changing "items" in the -// returned object will affect items in the underlying Items field, but changing -// the "items" slice itself will have no effect. -// TODO: expose SetUnstructuredContent on runtime.Unstructured that allows -// items to be changed. +// the Object field. Items always overwrites overlay. func (u *UnstructuredList) UnstructuredContent() map[string]interface{} { - out := u.Object - if out == nil { - out = make(map[string]interface{}) + out := make(map[string]interface{}, len(u.Object)+1) + + // shallow copy every property + for k, v := range u.Object { + out[k] = v } + items := make([]interface{}, len(u.Items)) for i, item := range u.Items { - items[i] = item.Object + items[i] = item.UnstructuredContent() } out["items"] = items return out diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_test.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_test.go new file mode 100644 index 000000000..cbcbbcef3 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_test.go @@ -0,0 +1,32 @@ +/* +Copyright 2018 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 unstructured + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNilUnstructuredContent(t *testing.T) { + var u Unstructured + uCopy := u.DeepCopy() + content := u.UnstructuredContent() + expContent := make(map[string]interface{}) + assert.EqualValues(t, expContent, content) + assert.Equal(t, uCopy, &u) +} diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go new file mode 100644 index 000000000..ab2574e82 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go @@ -0,0 +1,129 @@ +/* +Copyright 2018 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 unstructuredscheme + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/apimachinery/pkg/runtime/serializer/versioning" +) + +var ( + scheme = runtime.NewScheme() + codecs = serializer.NewCodecFactory(scheme) +) + +// NewUnstructuredNegotiatedSerializer returns a simple, negotiated serializer +func NewUnstructuredNegotiatedSerializer() runtime.NegotiatedSerializer { + return unstructuredNegotiatedSerializer{ + scheme: scheme, + typer: NewUnstructuredObjectTyper(), + creator: NewUnstructuredCreator(), + } +} + +type unstructuredNegotiatedSerializer struct { + scheme *runtime.Scheme + typer runtime.ObjectTyper + creator runtime.ObjectCreater +} + +func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { + return []runtime.SerializerInfo{ + { + MediaType: "application/json", + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false), + PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, true), + StreamSerializer: &runtime.StreamSerializerInfo{ + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false), + Framer: json.Framer, + }, + }, + { + MediaType: "application/yaml", + EncodesAsText: true, + Serializer: json.NewYAMLSerializer(json.DefaultMetaFactory, s.creator, s.typer), + }, + } +} + +func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { + return versioning.NewDefaultingCodecForScheme(s.scheme, encoder, nil, gv, nil) +} + +func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { + return versioning.NewDefaultingCodecForScheme(s.scheme, nil, decoder, nil, gv) +} + +type unstructuredObjectTyper struct { +} + +// NewUnstructuredObjectTyper returns an object typer that can deal with unstructured things +func NewUnstructuredObjectTyper() runtime.ObjectTyper { + return unstructuredObjectTyper{} +} + +func (t unstructuredObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { + // Delegate for things other than Unstructured. + if _, ok := obj.(runtime.Unstructured); !ok { + return nil, false, fmt.Errorf("cannot type %T", obj) + } + gvk := obj.GetObjectKind().GroupVersionKind() + if len(gvk.Kind) == 0 { + return nil, false, runtime.NewMissingKindErr("object has no kind field ") + } + if len(gvk.Version) == 0 { + return nil, false, runtime.NewMissingVersionErr("object has no apiVersion field") + } + + return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil +} + +func (t unstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool { + return true +} + +type unstructuredCreator struct{} + +// NewUnstructuredCreator returns a simple object creator that always returns an unstructured +func NewUnstructuredCreator() runtime.ObjectCreater { + return unstructuredCreator{} +} + +func (c unstructuredCreator) New(kind schema.GroupVersionKind) (runtime.Object, error) { + ret := &unstructured.Unstructured{} + ret.SetGroupVersionKind(kind) + return ret, nil +} + +type unstructuredDefaulter struct { +} + +// NewUnstructuredDefaulter returns defaulter suitable for unstructured types that doesn't default anything +func NewUnstructuredDefaulter() runtime.ObjectDefaulter { + return unstructuredDefaulter{} +} + +func (d unstructuredDefaulter) Default(in runtime.Object) { +} diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go index 1c185139f..9a9f25e8f 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go index 26c5a0cdc..96e5f42b7 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go @@ -17,8 +17,6 @@ limitations under the License. package validation import ( - "fmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" @@ -78,13 +76,13 @@ func ValidateLabels(labels map[string]string, fldPath *field.Path) field.ErrorLi func ValidateDeleteOptions(options *metav1.DeleteOptions) field.ErrorList { allErrs := field.ErrorList{} if options.OrphanDependents != nil && options.PropagationPolicy != nil { - allErrs = append(allErrs, field.Invalid(field.NewPath(""), options, "OrphanDependents and DeletionPropagation cannot be both set")) + allErrs = append(allErrs, field.Invalid(field.NewPath("propagationPolicy"), options.PropagationPolicy, "orphanDependents and deletionPropagation cannot be both set")) } if options.PropagationPolicy != nil && *options.PropagationPolicy != metav1.DeletePropagationForeground && *options.PropagationPolicy != metav1.DeletePropagationBackground && *options.PropagationPolicy != metav1.DeletePropagationOrphan { - allErrs = append(allErrs, field.Invalid(field.NewPath(""), options, fmt.Sprintf("DeletionPropagation need to be one of %q, %q, %q or nil", metav1.DeletePropagationForeground, metav1.DeletePropagationBackground, metav1.DeletePropagationOrphan))) + allErrs = append(allErrs, field.NotSupported(field.NewPath("propagationPolicy"), options.PropagationPolicy, []string{string(metav1.DeletePropagationForeground), string(metav1.DeletePropagationBackground), string(metav1.DeletePropagationOrphan), "nil"})) } return allErrs } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go index 73308d86e..98dfea095 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/deepcopy.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/deepcopy.go index 2dd440bb7..3b2bedd92 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/deepcopy.go @@ -16,6 +16,8 @@ limitations under the License. package v1beta1 +import "k8s.io/apimachinery/pkg/runtime" + func (in *TableRow) DeepCopy() *TableRow { if in == nil { return nil @@ -26,7 +28,7 @@ func (in *TableRow) DeepCopy() *TableRow { if in.Cells != nil { out.Cells = make([]interface{}, len(in.Cells)) for i := range in.Cells { - out.Cells[i] = deepCopyJSON(in.Cells[i]) + out.Cells[i] = runtime.DeepCopyJSONValue(in.Cells[i]) } } @@ -40,22 +42,3 @@ func (in *TableRow) DeepCopy() *TableRow { in.Object.DeepCopyInto(&out.Object) return out } - -func deepCopyJSON(x interface{}) interface{} { - switch x := x.(type) { - case map[string]interface{}: - clone := make(map[string]interface{}, len(x)) - for k, v := range x { - clone[k] = deepCopyJSON(v) - } - return clone - case []interface{}: - clone := make([]interface{}, len(x)) - for i := range x { - clone[i] = deepCopyJSON(x[i]) - } - return clone - default: - return x - } -} diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go index dda05bea4..fe3df6916 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -604,30 +604,29 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 391 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xbd, 0x6e, 0xd4, 0x40, - 0x10, 0xc7, 0xbd, 0x42, 0x11, 0x64, 0x43, 0x1a, 0x23, 0xa4, 0x70, 0xc5, 0x3a, 0xba, 0x2a, 0x48, - 0x64, 0x97, 0x04, 0x84, 0x28, 0x91, 0xbb, 0x48, 0xa0, 0x44, 0x16, 0x15, 0x15, 0x6b, 0x7b, 0xf0, - 0x2d, 0xb6, 0x77, 0xad, 0xdd, 0x71, 0xa4, 0x6b, 0x10, 0x8f, 0xc0, 0x63, 0x5d, 0x99, 0x32, 0x95, - 0xc5, 0x99, 0xb7, 0xa0, 0x42, 0xfe, 0x10, 0xf9, 0xb8, 0x3b, 0xe5, 0xba, 0x99, 0xff, 0xe8, 0xf7, - 0xf3, 0x8c, 0x97, 0x46, 0xf9, 0x7b, 0xc7, 0x95, 0x11, 0x79, 0x1d, 0x83, 0xd5, 0x80, 0xe0, 0xc4, - 0x25, 0xe8, 0xd4, 0x58, 0x31, 0x0e, 0x64, 0xa5, 0x4a, 0x99, 0xcc, 0x94, 0x06, 0x3b, 0x17, 0x55, - 0x9e, 0x75, 0x81, 0x13, 0x25, 0xa0, 0x14, 0x97, 0x27, 0x31, 0xa0, 0x3c, 0x11, 0x19, 0x68, 0xb0, - 0x12, 0x21, 0xe5, 0x95, 0x35, 0x68, 0xfc, 0x97, 0x03, 0xca, 0x6f, 0xa3, 0xbc, 0xca, 0xb3, 0x2e, - 0x70, 0xbc, 0x43, 0xf9, 0x88, 0x4e, 0x8e, 0x33, 0x85, 0xb3, 0x3a, 0xe6, 0x89, 0x29, 0x45, 0x66, - 0x32, 0x23, 0x7a, 0x43, 0x5c, 0x7f, 0xeb, 0xbb, 0xbe, 0xe9, 0xab, 0xc1, 0x3c, 0x79, 0xbb, 0xcd, - 0x52, 0xf7, 0xf7, 0x99, 0x6c, 0x3c, 0xc5, 0xd6, 0x1a, 0x55, 0x09, 0x2b, 0xc0, 0xbb, 0x87, 0x00, - 0x97, 0xcc, 0xa0, 0x94, 0x2b, 0xdc, 0x9b, 0x4d, 0x5c, 0x8d, 0xaa, 0x10, 0x4a, 0xa3, 0x43, 0x7b, - 0x1f, 0x9a, 0xce, 0xe9, 0xf3, 0x0b, 0x69, 0x51, 0xc9, 0xe2, 0x3c, 0xfe, 0x0e, 0x09, 0x7e, 0x02, - 0x94, 0xa9, 0x44, 0xe9, 0x7f, 0xa5, 0x4f, 0xca, 0xb1, 0x3e, 0x20, 0x87, 0xe4, 0x68, 0xef, 0xf4, - 0x35, 0xdf, 0xe6, 0xcf, 0xf2, 0x1b, 0x4f, 0xe8, 0x2f, 0x9a, 0xc0, 0x6b, 0x9b, 0x80, 0xde, 0x64, - 0xd1, 0x7f, 0xeb, 0xf4, 0x07, 0x7d, 0xb1, 0xf6, 0xd3, 0x1f, 0x95, 0x43, 0x5f, 0xd2, 0x1d, 0x85, - 0x50, 0xba, 0x03, 0x72, 0xf8, 0xe8, 0x68, 0xef, 0xf4, 0x03, 0xdf, 0xfa, 0x55, 0xf9, 0x5a, 0x69, - 0xb8, 0xdb, 0x36, 0xc1, 0xce, 0x59, 0xa7, 0x8c, 0x06, 0xf3, 0x34, 0xa6, 0x4f, 0x3f, 0xcb, 0xb8, - 0x80, 0xf3, 0x0a, 0x95, 0xd1, 0xce, 0x8f, 0xe8, 0xbe, 0xd2, 0x49, 0x51, 0xa7, 0x30, 0xa0, 0xfd, - 0xd9, 0xbb, 0xe1, 0xab, 0xf1, 0x88, 0xfd, 0xb3, 0xdb, 0xc3, 0xbf, 0x4d, 0xf0, 0xec, 0x4e, 0x70, - 0x61, 0x0a, 0x95, 0xcc, 0xa3, 0xbb, 0x8a, 0xf0, 0x78, 0xb1, 0x64, 0xde, 0xd5, 0x92, 0x79, 0xd7, - 0x4b, 0xe6, 0xfd, 0x6c, 0x19, 0x59, 0xb4, 0x8c, 0x5c, 0xb5, 0x8c, 0x5c, 0xb7, 0x8c, 0xfc, 0x6e, - 0x19, 0xf9, 0xf5, 0x87, 0x79, 0x5f, 0x1e, 0x8f, 0xab, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x73, - 0xdf, 0x3a, 0x0c, 0x10, 0x03, 0x00, 0x00, + // 375 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xcd, 0x0a, 0xd3, 0x40, + 0x10, 0xc7, 0xb3, 0x48, 0xd1, 0x6e, 0xed, 0x25, 0x22, 0xd4, 0x1e, 0x36, 0xa5, 0xa7, 0x0a, 0x76, + 0xd7, 0x16, 0x11, 0x8f, 0x92, 0x5b, 0x41, 0x69, 0x09, 0x9e, 0x3c, 0xb9, 0x49, 0xc6, 0x74, 0xcd, + 0xc7, 0x86, 0xec, 0xa6, 0xd0, 0x8b, 0xf8, 0x08, 0x3e, 0x56, 0x8f, 0x3d, 0xf6, 0x14, 0x6c, 0x7c, + 0x0b, 0x4f, 0x92, 0x0f, 0xec, 0x87, 0x15, 0x7b, 0x9b, 0xf9, 0x0f, 0xbf, 0x5f, 0x66, 0xb2, 0xd8, + 0x09, 0xdf, 0x28, 0x2a, 0x24, 0x0b, 0x73, 0x17, 0xb2, 0x04, 0x34, 0x28, 0xb6, 0x81, 0xc4, 0x97, + 0x19, 0x6b, 0x07, 0x3c, 0x15, 0x31, 0xf7, 0xd6, 0x22, 0x81, 0x6c, 0xcb, 0xd2, 0x30, 0xa8, 0x02, + 0xc5, 0x62, 0xd0, 0x9c, 0x6d, 0x66, 0x2e, 0x68, 0x3e, 0x63, 0x01, 0x24, 0x90, 0x71, 0x0d, 0x3e, + 0x4d, 0x33, 0xa9, 0xa5, 0xf9, 0xbc, 0x41, 0xe9, 0x39, 0x4a, 0xd3, 0x30, 0xa8, 0x02, 0x45, 0x2b, + 0x94, 0xb6, 0xe8, 0x70, 0x1a, 0x08, 0xbd, 0xce, 0x5d, 0xea, 0xc9, 0x98, 0x05, 0x32, 0x90, 0xac, + 0x36, 0xb8, 0xf9, 0xe7, 0xba, 0xab, 0x9b, 0xba, 0x6a, 0xcc, 0xc3, 0x57, 0xf7, 0x2c, 0x75, 0xbd, + 0xcf, 0xf0, 0x9f, 0xa7, 0x64, 0x79, 0xa2, 0x45, 0x0c, 0x7f, 0x01, 0xaf, 0xff, 0x07, 0x28, 0x6f, + 0x0d, 0x31, 0xbf, 0xe6, 0xc6, 0x5b, 0xfc, 0x74, 0xc5, 0x33, 0x2d, 0x78, 0xb4, 0x74, 0xbf, 0x80, + 0xa7, 0xdf, 0x83, 0xe6, 0x3e, 0xd7, 0xdc, 0xfc, 0x84, 0x1f, 0xc5, 0x6d, 0x3d, 0x40, 0x23, 0x34, + 0xe9, 0xcd, 0x5f, 0xd2, 0x7b, 0x7e, 0x12, 0x3d, 0x79, 0x6c, 0x73, 0x57, 0x58, 0x46, 0x59, 0x58, + 0xf8, 0x94, 0x39, 0x7f, 0xac, 0xe3, 0xaf, 0xf8, 0xd9, 0xcd, 0x4f, 0xbf, 0x13, 0x4a, 0x9b, 0x1c, + 0x77, 0x84, 0x86, 0x58, 0x0d, 0xd0, 0xe8, 0xc1, 0xa4, 0x37, 0x7f, 0x4b, 0xef, 0x7e, 0x20, 0x7a, + 0x53, 0x6a, 0x77, 0xcb, 0xc2, 0xea, 0x2c, 0x2a, 0xa5, 0xd3, 0x98, 0xc7, 0x2e, 0x7e, 0xfc, 0x81, + 0xbb, 0x11, 0x2c, 0x53, 0x2d, 0x64, 0xa2, 0x4c, 0x07, 0xf7, 0x45, 0xe2, 0x45, 0xb9, 0x0f, 0x0d, + 0x5a, 0x9f, 0xdd, 0xb5, 0x5f, 0xb4, 0x47, 0xf4, 0x17, 0xe7, 0xc3, 0x5f, 0x85, 0xf5, 0xe4, 0x22, + 0x58, 0xc9, 0x48, 0x78, 0x5b, 0xe7, 0x52, 0x61, 0x4f, 0x77, 0x47, 0x62, 0xec, 0x8f, 0xc4, 0x38, + 0x1c, 0x89, 0xf1, 0xad, 0x24, 0x68, 0x57, 0x12, 0xb4, 0x2f, 0x09, 0x3a, 0x94, 0x04, 0xfd, 0x28, + 0x09, 0xfa, 0xfe, 0x93, 0x18, 0x1f, 0x1f, 0xb6, 0xab, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xf3, + 0xe1, 0xde, 0x86, 0xdb, 0x02, 0x00, 0x00, } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto index a9060bf96..83be99790 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.apimachinery.pkg.apis.meta.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go index 7b7c47d82..344c533e1 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go @@ -66,8 +66,8 @@ type TableColumnDefinition struct { // TableRow is an individual row in a table. // +protobuf=false type TableRow struct { - // cells will be as wide as headers and may contain strings, numbers, booleans, simple maps, or lists, or - // null. See the type field of the column definition for a more detailed description. + // cells will be as wide as headers and may contain strings, numbers (float64 or int64), booleans, simple + // maps, or lists, or null. See the type field of the column definition for a more detailed description. Cells []interface{} `json:"cells"` // conditions describe additional status of a row that are relevant for a human user. // +optional diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go index 2680fbf7e..7394535d9 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_PartialObjectMetadata = map[string]string{ "": "PartialObjectMetadata is a generic representation of any object with ObjectMeta. It allows clients to get access to a particular ObjectMeta schema without knowing the details of the version.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -80,7 +80,7 @@ func (TableOptions) SwaggerDoc() map[string]string { var map_TableRow = map[string]string{ "": "TableRow is an individual row in a table.", - "cells": "cells will be as wide as headers and may contain strings, numbers, booleans, simple maps, or lists, or null. See the type field of the column definition for a more detailed description.", + "cells": "cells will be as wide as headers and may contain strings, numbers (float64 or int64), booleans, simple maps, or lists, or null. See the type field of the column definition for a more detailed description.", "conditions": "conditions describe additional status of a row that are relevant for a human user.", "object": "This field contains the requested additional information about each object based on the includeObject policy when requesting the Table. If \"None\", this field is empty, if \"Object\" this will be the default serialization of the object for the current API version, and if \"Metadata\" (the default) will contain the object metadata. Check the returned kind and apiVersion of the object before parsing.", } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.deepcopy.go index 226995a21..2e79a131f 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.defaults.go index 544e569dc..73e63fc11 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/install/install.go b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/install/install.go index c7ada70f9..6fc079f51 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/install/install.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/apis/testapigroup" "k8s.io/apimachinery/pkg/apis/testapigroup/v1" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: testapigroup.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: testapigroup.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(testapigroup.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.pb.go b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.pb.go index 4ad2352e5..5fd3c3f97 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.pb.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1938,72 +1938,71 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1062 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcf, 0x6e, 0xdb, 0xc6, - 0x13, 0x36, 0x2d, 0xc9, 0x96, 0xd6, 0x56, 0x62, 0x6f, 0x62, 0x80, 0x3f, 0x03, 0x91, 0x1c, 0x1f, - 0x0c, 0xff, 0x8a, 0x94, 0x8c, 0xdd, 0x26, 0x70, 0x9b, 0x43, 0x11, 0xda, 0x45, 0xed, 0xc2, 0x71, - 0x84, 0x95, 0x8b, 0x14, 0x45, 0x0f, 0x59, 0x51, 0x53, 0x99, 0x95, 0xc8, 0x25, 0x76, 0x97, 0x2a, - 0x74, 0x2b, 0xfa, 0x04, 0x7d, 0x88, 0xde, 0x7a, 0xee, 0x03, 0xf4, 0x50, 0xc0, 0xc7, 0x1c, 0x73, - 0x12, 0x6a, 0xf5, 0x2d, 0x7c, 0x2a, 0x76, 0xf9, 0x47, 0x94, 0xe5, 0xa8, 0x51, 0x6e, 0xdc, 0x99, - 0xef, 0xfb, 0x66, 0x76, 0x67, 0x38, 0x83, 0xbe, 0xe9, 0x1e, 0x08, 0xcb, 0x63, 0x76, 0x37, 0x6a, - 0x01, 0x0f, 0x40, 0x82, 0xb0, 0xfb, 0x10, 0xb4, 0x19, 0xb7, 0x13, 0x07, 0x0d, 0x3d, 0x9f, 0xba, - 0x17, 0x5e, 0x00, 0x7c, 0x60, 0x87, 0xdd, 0x8e, 0x32, 0x08, 0x5b, 0x82, 0x90, 0x34, 0xf4, 0x3a, - 0x9c, 0x45, 0xa1, 0xdd, 0xdf, 0xb3, 0x3b, 0x10, 0x00, 0xa7, 0x12, 0xda, 0x56, 0xc8, 0x99, 0x64, - 0xf8, 0x51, 0xcc, 0xb6, 0xf2, 0x6c, 0x2b, 0xec, 0x76, 0x94, 0x41, 0x58, 0x79, 0xb6, 0xd5, 0xdf, - 0xdb, 0xfc, 0xb8, 0xe3, 0xc9, 0x8b, 0xa8, 0x65, 0xb9, 0xcc, 0xb7, 0x3b, 0xac, 0xc3, 0x6c, 0x2d, - 0xd2, 0x8a, 0x7e, 0xd0, 0x27, 0x7d, 0xd0, 0x5f, 0xb1, 0xf8, 0xe6, 0xa7, 0x33, 0x53, 0xf3, 0x41, - 0xd2, 0x5b, 0x52, 0xda, 0x7c, 0xe7, 0x85, 0x78, 0x14, 0x48, 0xcf, 0x87, 0x29, 0xc2, 0xd3, 0xff, - 0x22, 0x08, 0xf7, 0x02, 0x7c, 0x3a, 0xc5, 0xfb, 0xe4, 0x5d, 0xbc, 0x48, 0x7a, 0x3d, 0xdb, 0x0b, - 0xa4, 0x90, 0xfc, 0x26, 0x69, 0xfb, 0xb7, 0x45, 0x54, 0x3c, 0xa4, 0x3c, 0xc4, 0xaf, 0x51, 0x59, - 0xdd, 0xa0, 0x4d, 0x25, 0x35, 0x8d, 0x2d, 0x63, 0x77, 0x65, 0xff, 0xb1, 0x35, 0xf3, 0x31, 0x15, - 0xda, 0xea, 0xef, 0x59, 0x2f, 0x5b, 0x3f, 0x82, 0x2b, 0x5f, 0x80, 0xa4, 0x0e, 0xbe, 0x1c, 0xd6, - 0x17, 0x46, 0xc3, 0x3a, 0x1a, 0xdb, 0x48, 0xa6, 0x8a, 0xbf, 0x45, 0x45, 0x11, 0x82, 0x6b, 0x2e, - 0x6a, 0xf5, 0xa7, 0xd6, 0x3c, 0xa5, 0xb2, 0x54, 0x8e, 0xcd, 0x10, 0x5c, 0x67, 0x35, 0x89, 0x51, - 0x54, 0x27, 0xa2, 0x15, 0xf1, 0x6b, 0xb4, 0x24, 0x24, 0x95, 0x91, 0x30, 0x0b, 0x5a, 0xfb, 0xe0, - 0x03, 0xb4, 0x35, 0xdf, 0xb9, 0x93, 0xa8, 0x2f, 0xc5, 0x67, 0x92, 0xe8, 0x6e, 0xff, 0x51, 0x40, - 0x55, 0x05, 0x3b, 0x64, 0x41, 0xdb, 0x93, 0x1e, 0x0b, 0xf0, 0x13, 0x54, 0x94, 0x83, 0x10, 0xf4, - 0x5b, 0x55, 0x9c, 0x87, 0x69, 0x56, 0xe7, 0x83, 0x10, 0xae, 0x87, 0xf5, 0xf5, 0x09, 0xb0, 0x32, - 0x12, 0x0d, 0xc7, 0x9f, 0x65, 0xa9, 0x2e, 0x4e, 0x10, 0x93, 0x80, 0xd7, 0xc3, 0xfa, 0xdd, 0x8c, - 0x36, 0x99, 0x03, 0xee, 0xa0, 0x6a, 0x8f, 0x0a, 0xd9, 0xe0, 0xac, 0x05, 0xe7, 0x9e, 0x0f, 0xc9, - 0x65, 0x3f, 0x7a, 0xbf, 0x32, 0x29, 0x86, 0xb3, 0x91, 0x44, 0xab, 0x9e, 0xe6, 0x85, 0xc8, 0xa4, - 0x2e, 0xee, 0x23, 0xac, 0x0c, 0xe7, 0x9c, 0x06, 0x22, 0xce, 0x5f, 0x45, 0x2b, 0xce, 0x1d, 0x6d, - 0x33, 0x89, 0x86, 0x4f, 0xa7, 0xd4, 0xc8, 0x2d, 0x11, 0xf0, 0x0e, 0x5a, 0xe2, 0x40, 0x05, 0x0b, - 0xcc, 0x92, 0x7e, 0x9b, 0xac, 0x18, 0x44, 0x5b, 0x49, 0xe2, 0xc5, 0xff, 0x47, 0xcb, 0x3e, 0x08, - 0x41, 0x3b, 0x60, 0x2e, 0x69, 0xe0, 0xdd, 0x04, 0xb8, 0xfc, 0x22, 0x36, 0x93, 0xd4, 0xbf, 0xfd, - 0xa7, 0x81, 0xca, 0xaa, 0x14, 0xa7, 0x9e, 0x90, 0xf8, 0xfb, 0xa9, 0x16, 0xb7, 0xde, 0xef, 0x36, - 0x8a, 0xad, 0x1b, 0x7c, 0x2d, 0x09, 0x54, 0x4e, 0x2d, 0xb9, 0xf6, 0x7e, 0x85, 0x4a, 0x9e, 0x04, - 0x5f, 0x15, 0xb6, 0xb0, 0xbb, 0xb2, 0xbf, 0x3f, 0x7f, 0x0f, 0x3a, 0xd5, 0x44, 0xbe, 0x74, 0xa2, - 0x84, 0x48, 0xac, 0xb7, 0xfd, 0xd7, 0x72, 0x7c, 0x07, 0xd5, 0xf0, 0xf8, 0x14, 0x55, 0xb9, 0xa2, - 0x72, 0xd9, 0x60, 0x3d, 0xcf, 0x1d, 0xe8, 0x26, 0xa8, 0x38, 0x3b, 0x69, 0x61, 0x49, 0xde, 0x79, - 0x7d, 0xd3, 0x40, 0x26, 0xc9, 0xb8, 0x83, 0x1e, 0x48, 0xe0, 0xbe, 0x17, 0x50, 0x55, 0x84, 0xaf, - 0x38, 0x75, 0xa1, 0x01, 0xdc, 0x63, 0xed, 0x26, 0xb8, 0x2c, 0x68, 0x0b, 0x5d, 0xf4, 0x82, 0xf3, - 0x70, 0x34, 0xac, 0x3f, 0x38, 0x9f, 0x05, 0x24, 0xb3, 0x75, 0xf0, 0x4b, 0xb4, 0x41, 0x5d, 0xe9, - 0xf5, 0xe1, 0x08, 0x68, 0xbb, 0xe7, 0x05, 0x90, 0x06, 0x28, 0xe9, 0x00, 0xff, 0x1b, 0x0d, 0xeb, - 0x1b, 0xcf, 0x6f, 0x03, 0x90, 0xdb, 0x79, 0xf8, 0x17, 0x03, 0xad, 0x06, 0xac, 0x0d, 0x4d, 0xe8, - 0x81, 0x2b, 0x19, 0x37, 0x97, 0xf5, 0xab, 0x1f, 0x7f, 0xd8, 0x54, 0xb1, 0xce, 0x72, 0x52, 0x5f, - 0x06, 0x92, 0x0f, 0x9c, 0xfb, 0xc9, 0x8b, 0xae, 0xe6, 0x5d, 0x64, 0x22, 0x26, 0xfe, 0x1a, 0x61, - 0x01, 0xbc, 0xef, 0xb9, 0xf0, 0xdc, 0x75, 0x59, 0x14, 0xc8, 0x33, 0xea, 0x83, 0x59, 0xd6, 0x15, - 0xc9, 0x9a, 0xbf, 0x39, 0x85, 0x20, 0xb7, 0xb0, 0xf0, 0x31, 0xba, 0x33, 0x69, 0x35, 0x2b, 0x5a, - 0x67, 0x2b, 0xd1, 0x31, 0x8f, 0x20, 0xe4, 0xe0, 0xaa, 0xd1, 0x3d, 0xa9, 0x48, 0x6e, 0xf0, 0xf0, - 0x23, 0x54, 0x56, 0x59, 0xea, 0x5c, 0x90, 0xd6, 0xc8, 0xda, 0xf6, 0x2c, 0xb1, 0x93, 0x0c, 0x81, - 0x9f, 0xa0, 0x95, 0x0b, 0x26, 0xe4, 0x19, 0xc8, 0x9f, 0x18, 0xef, 0x9a, 0x2b, 0x5b, 0xc6, 0x6e, - 0xd9, 0xb9, 0x97, 0x10, 0x56, 0x8e, 0xc7, 0x2e, 0x92, 0xc7, 0xa9, 0x7f, 0x50, 0x1d, 0x1b, 0x27, - 0x47, 0xe6, 0xaa, 0xa6, 0x64, 0xff, 0xe0, 0x71, 0x6c, 0x26, 0xa9, 0x3f, 0x85, 0x9e, 0x34, 0x0e, - 0xcd, 0xea, 0x34, 0xf4, 0xa4, 0x71, 0x48, 0x52, 0xbf, 0x4a, 0x5d, 0x7d, 0x06, 0x2a, 0xf5, 0xb5, - 0xc9, 0xd4, 0x8f, 0x13, 0x3b, 0xc9, 0x10, 0xd8, 0x46, 0x15, 0x11, 0xb5, 0xda, 0xcc, 0xa7, 0x5e, - 0x60, 0xae, 0x6b, 0xf8, 0x7a, 0x02, 0xaf, 0x34, 0x53, 0x07, 0x19, 0x63, 0xf0, 0x33, 0x54, 0x55, - 0xbb, 0xb3, 0x1d, 0xf5, 0x80, 0xeb, 0x18, 0xf7, 0x34, 0x29, 0x9b, 0x8a, 0xcd, 0xd4, 0xa9, 0xdf, - 0x68, 0x12, 0xbb, 0xf9, 0x05, 0x5a, 0x9f, 0xea, 0x12, 0xbc, 0x86, 0x0a, 0x5d, 0x18, 0xc4, 0x4b, - 0x80, 0xa8, 0x4f, 0x7c, 0x1f, 0x95, 0xfa, 0xb4, 0x17, 0x41, 0x3c, 0xdf, 0x49, 0x7c, 0xf8, 0x7c, - 0xf1, 0xc0, 0xd8, 0xfe, 0xbd, 0x80, 0xd0, 0x78, 0xd5, 0xe0, 0xc7, 0xa8, 0x14, 0x5e, 0x50, 0x91, - 0x6e, 0x90, 0xb4, 0x5f, 0x4a, 0x0d, 0x65, 0xbc, 0x1e, 0xd6, 0x2b, 0x0a, 0xab, 0x0f, 0x24, 0x06, - 0x62, 0x86, 0x90, 0x9b, 0xee, 0x86, 0x74, 0xcc, 0x3c, 0x9b, 0xbf, 0xe1, 0xb3, 0xfd, 0x32, 0xde, - 0xd7, 0x99, 0x49, 0x90, 0x5c, 0x88, 0xfc, 0xa0, 0x2d, 0xcc, 0x1e, 0xb4, 0xb9, 0xd9, 0x5d, 0x9c, - 0x39, 0xbb, 0x77, 0xd0, 0x52, 0x5c, 0xec, 0x9b, 0x33, 0x3e, 0xee, 0x05, 0x92, 0x78, 0x15, 0xce, - 0xa5, 0x3c, 0x3c, 0x69, 0x24, 0x23, 0x3e, 0xc3, 0x1d, 0x6a, 0x2b, 0x49, 0xbc, 0xf8, 0x15, 0xaa, - 0xe8, 0x81, 0xa6, 0x57, 0xd4, 0xf2, 0xdc, 0x2b, 0xaa, 0xaa, 0x7b, 0x25, 0x15, 0x20, 0x63, 0x2d, - 0x67, 0xf7, 0xf2, 0xaa, 0xb6, 0xf0, 0xe6, 0xaa, 0xb6, 0xf0, 0xf6, 0xaa, 0xb6, 0xf0, 0xf3, 0xa8, - 0x66, 0x5c, 0x8e, 0x6a, 0xc6, 0x9b, 0x51, 0xcd, 0x78, 0x3b, 0xaa, 0x19, 0x7f, 0x8f, 0x6a, 0xc6, - 0xaf, 0xff, 0xd4, 0x16, 0xbe, 0x5b, 0xec, 0xef, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xc2, 0xaa, - 0x9e, 0x7b, 0xcb, 0x0a, 0x00, 0x00, + // 1048 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xc1, 0x6e, 0xdb, 0x46, + 0x10, 0x35, 0x2d, 0xc9, 0x96, 0xd6, 0x56, 0x62, 0x6f, 0x62, 0x80, 0x35, 0x10, 0xc9, 0xf1, 0xc1, + 0x70, 0x8b, 0x94, 0x8a, 0x8d, 0x26, 0x70, 0x9b, 0x43, 0x11, 0xda, 0x45, 0xed, 0xc2, 0x71, 0x84, + 0x95, 0x8b, 0x14, 0x45, 0x0f, 0x59, 0x51, 0x53, 0x99, 0x95, 0xc8, 0x25, 0x76, 0x57, 0x2a, 0x74, + 0x2b, 0xfa, 0x05, 0xfd, 0x88, 0xde, 0x7a, 0xee, 0x07, 0xf4, 0x50, 0xc0, 0xc7, 0x1c, 0x73, 0x12, + 0x6a, 0xf5, 0x2f, 0x7c, 0x2a, 0x76, 0xb9, 0xa4, 0x28, 0xcb, 0x55, 0xa2, 0xdc, 0xb8, 0x33, 0xef, + 0xbd, 0x99, 0xdd, 0x19, 0xce, 0xa0, 0x6f, 0x3b, 0x07, 0xc2, 0xf1, 0x59, 0xad, 0xd3, 0x6b, 0x02, + 0x0f, 0x41, 0x82, 0xa8, 0xf5, 0x21, 0x6c, 0x31, 0x5e, 0x33, 0x0e, 0x1a, 0xf9, 0x01, 0xf5, 0x2e, + 0xfc, 0x10, 0xf8, 0xa0, 0x16, 0x75, 0xda, 0xca, 0x20, 0x6a, 0x12, 0x84, 0xa4, 0x91, 0xdf, 0xe6, + 0xac, 0x17, 0xd5, 0xfa, 0x7b, 0xb5, 0x36, 0x84, 0xc0, 0xa9, 0x84, 0x96, 0x13, 0x71, 0x26, 0x19, + 0x7e, 0x14, 0xb3, 0x9d, 0x2c, 0xdb, 0x89, 0x3a, 0x6d, 0x65, 0x10, 0x4e, 0x96, 0xed, 0xf4, 0xf7, + 0x36, 0x3f, 0x6d, 0xfb, 0xf2, 0xa2, 0xd7, 0x74, 0x3c, 0x16, 0xd4, 0xda, 0xac, 0xcd, 0x6a, 0x5a, + 0xa4, 0xd9, 0xfb, 0x51, 0x9f, 0xf4, 0x41, 0x7f, 0xc5, 0xe2, 0x9b, 0x9f, 0xcd, 0x4c, 0x2d, 0x00, + 0x49, 0x6f, 0x49, 0x69, 0xf3, 0x7f, 0x2f, 0xc4, 0x7b, 0xa1, 0xf4, 0x03, 0x98, 0x22, 0x3c, 0x7d, + 0x17, 0x41, 0x78, 0x17, 0x10, 0xd0, 0x9b, 0xbc, 0xed, 0xdf, 0x17, 0x51, 0xfe, 0x90, 0xf2, 0x08, + 0xbf, 0x46, 0x45, 0x95, 0x4c, 0x8b, 0x4a, 0x6a, 0x5b, 0x5b, 0xd6, 0xee, 0xca, 0xfe, 0x63, 0x67, + 0xe6, 0xbb, 0x28, 0xb4, 0xd3, 0xdf, 0x73, 0x5e, 0x36, 0x7f, 0x02, 0x4f, 0xbe, 0x00, 0x49, 0x5d, + 0x7c, 0x39, 0xac, 0x2e, 0x8c, 0x86, 0x55, 0x34, 0xb6, 0x91, 0x54, 0x15, 0x7f, 0x87, 0xf2, 0x22, + 0x02, 0xcf, 0x5e, 0xd4, 0xea, 0x4f, 0x9d, 0x79, 0x5e, 0xdd, 0x51, 0x39, 0x36, 0x22, 0xf0, 0xdc, + 0x55, 0x13, 0x23, 0xaf, 0x4e, 0x44, 0x2b, 0xe2, 0xd7, 0x68, 0x49, 0x48, 0x2a, 0x7b, 0xc2, 0xce, + 0x69, 0xed, 0x83, 0x0f, 0xd0, 0xd6, 0x7c, 0xf7, 0x8e, 0x51, 0x5f, 0x8a, 0xcf, 0xc4, 0xe8, 0x6e, + 0xff, 0x99, 0x43, 0x65, 0x05, 0x3b, 0x64, 0x61, 0xcb, 0x97, 0x3e, 0x0b, 0xf1, 0x13, 0x94, 0x97, + 0x83, 0x08, 0xf4, 0x5b, 0x95, 0xdc, 0x87, 0x49, 0x56, 0xe7, 0x83, 0x08, 0xae, 0x87, 0xd5, 0xf5, + 0x09, 0xb0, 0x32, 0x12, 0x0d, 0xc7, 0x9f, 0xa7, 0xa9, 0x2e, 0x4e, 0x10, 0x4d, 0xc0, 0xeb, 0x61, + 0xf5, 0x6e, 0x4a, 0x9b, 0xcc, 0x01, 0xb7, 0x51, 0xb9, 0x4b, 0x85, 0xac, 0x73, 0xd6, 0x84, 0x73, + 0x3f, 0x00, 0x73, 0xd9, 0x4f, 0xde, 0xaf, 0x4c, 0x8a, 0xe1, 0x6e, 0x98, 0x68, 0xe5, 0xd3, 0xac, + 0x10, 0x99, 0xd4, 0xc5, 0x7d, 0x84, 0x95, 0xe1, 0x9c, 0xd3, 0x50, 0xc4, 0xf9, 0xab, 0x68, 0xf9, + 0xb9, 0xa3, 0x6d, 0x9a, 0x68, 0xf8, 0x74, 0x4a, 0x8d, 0xdc, 0x12, 0x01, 0xef, 0xa0, 0x25, 0x0e, + 0x54, 0xb0, 0xd0, 0x2e, 0xe8, 0xb7, 0x49, 0x8b, 0x41, 0xb4, 0x95, 0x18, 0x2f, 0xfe, 0x18, 0x2d, + 0x07, 0x20, 0x04, 0x6d, 0x83, 0xbd, 0xa4, 0x81, 0x77, 0x0d, 0x70, 0xf9, 0x45, 0x6c, 0x26, 0x89, + 0x7f, 0xfb, 0x2f, 0x0b, 0x15, 0x55, 0x29, 0x4e, 0x7d, 0x21, 0xf1, 0x0f, 0x53, 0x2d, 0xee, 0xbc, + 0xdf, 0x6d, 0x14, 0x5b, 0x37, 0xf8, 0x9a, 0x09, 0x54, 0x4c, 0x2c, 0x99, 0xf6, 0x7e, 0x85, 0x0a, + 0xbe, 0x84, 0x40, 0x15, 0x36, 0xb7, 0xbb, 0xb2, 0xbf, 0x3f, 0x7f, 0x0f, 0xba, 0x65, 0x23, 0x5f, + 0x38, 0x51, 0x42, 0x24, 0xd6, 0xdb, 0xfe, 0x7b, 0x39, 0xbe, 0x83, 0x6a, 0x78, 0x7c, 0x8a, 0xca, + 0x5c, 0x51, 0xb9, 0xac, 0xb3, 0xae, 0xef, 0x0d, 0x74, 0x13, 0x94, 0xdc, 0x9d, 0xa4, 0xb0, 0x24, + 0xeb, 0xbc, 0xbe, 0x69, 0x20, 0x93, 0x64, 0xdc, 0x46, 0x0f, 0x24, 0xf0, 0xc0, 0x0f, 0xa9, 0x2a, + 0xc2, 0xd7, 0x9c, 0x7a, 0x50, 0x07, 0xee, 0xb3, 0x56, 0x03, 0x3c, 0x16, 0xb6, 0x84, 0x2e, 0x7a, + 0xce, 0x7d, 0x38, 0x1a, 0x56, 0x1f, 0x9c, 0xcf, 0x02, 0x92, 0xd9, 0x3a, 0xf8, 0x25, 0xda, 0xa0, + 0x9e, 0xf4, 0xfb, 0x70, 0x04, 0xb4, 0xd5, 0xf5, 0x43, 0x48, 0x02, 0x14, 0x74, 0x80, 0x8f, 0x46, + 0xc3, 0xea, 0xc6, 0xf3, 0xdb, 0x00, 0xe4, 0x76, 0x1e, 0xfe, 0xd5, 0x42, 0xab, 0x21, 0x6b, 0x41, + 0x03, 0xba, 0xe0, 0x49, 0xc6, 0xed, 0x65, 0xfd, 0xea, 0xc7, 0x1f, 0x36, 0x55, 0x9c, 0xb3, 0x8c, + 0xd4, 0x57, 0xa1, 0xe4, 0x03, 0xf7, 0xbe, 0x79, 0xd1, 0xd5, 0xac, 0x8b, 0x4c, 0xc4, 0xc4, 0xdf, + 0x20, 0x2c, 0x80, 0xf7, 0x7d, 0x0f, 0x9e, 0x7b, 0x1e, 0xeb, 0x85, 0xf2, 0x8c, 0x06, 0x60, 0x17, + 0x75, 0x45, 0xd2, 0xe6, 0x6f, 0x4c, 0x21, 0xc8, 0x2d, 0x2c, 0x7c, 0x8c, 0xee, 0x4c, 0x5a, 0xed, + 0x92, 0xd6, 0xd9, 0x32, 0x3a, 0xf6, 0x11, 0x44, 0x1c, 0x3c, 0x35, 0xba, 0x27, 0x15, 0xc9, 0x0d, + 0x1e, 0x7e, 0x84, 0x8a, 0x2a, 0x4b, 0x9d, 0x0b, 0xd2, 0x1a, 0x69, 0xdb, 0x9e, 0x19, 0x3b, 0x49, + 0x11, 0xf8, 0x09, 0x5a, 0xb9, 0x60, 0x42, 0x9e, 0x81, 0xfc, 0x99, 0xf1, 0x8e, 0xbd, 0xb2, 0x65, + 0xed, 0x16, 0xdd, 0x7b, 0x86, 0xb0, 0x72, 0x3c, 0x76, 0x91, 0x2c, 0x4e, 0xfd, 0x83, 0xea, 0x58, + 0x3f, 0x39, 0xb2, 0x57, 0x35, 0x25, 0xfd, 0x07, 0x8f, 0x63, 0x33, 0x49, 0xfc, 0x09, 0xf4, 0xa4, + 0x7e, 0x68, 0x97, 0xa7, 0xa1, 0x27, 0xf5, 0x43, 0x92, 0xf8, 0x55, 0xea, 0xea, 0x33, 0x54, 0xa9, + 0xaf, 0x4d, 0xa6, 0x7e, 0x6c, 0xec, 0x24, 0x45, 0xe0, 0x1a, 0x2a, 0x89, 0x5e, 0xb3, 0xc5, 0x02, + 0xea, 0x87, 0xf6, 0xba, 0x86, 0xaf, 0x1b, 0x78, 0xa9, 0x91, 0x38, 0xc8, 0x18, 0x83, 0x9f, 0xa1, + 0xb2, 0x5a, 0x83, 0xad, 0x5e, 0x17, 0xb8, 0x8e, 0x71, 0x4f, 0x93, 0xd2, 0xa9, 0xd8, 0x48, 0x9c, + 0xfa, 0x8d, 0x26, 0xb1, 0x9b, 0x5f, 0xa2, 0xf5, 0xa9, 0x2e, 0xc1, 0x6b, 0x28, 0xd7, 0x81, 0x41, + 0xbc, 0x04, 0x88, 0xfa, 0xc4, 0xf7, 0x51, 0xa1, 0x4f, 0xbb, 0x3d, 0x88, 0xe7, 0x3b, 0x89, 0x0f, + 0x5f, 0x2c, 0x1e, 0x58, 0xdb, 0x7f, 0xe4, 0x10, 0x1a, 0xaf, 0x1a, 0xfc, 0x18, 0x15, 0xa2, 0x0b, + 0x2a, 0x92, 0x0d, 0x92, 0xf4, 0x4b, 0xa1, 0xae, 0x8c, 0xd7, 0xc3, 0x6a, 0x49, 0x61, 0xf5, 0x81, + 0xc4, 0x40, 0xcc, 0x10, 0xf2, 0x92, 0xdd, 0x90, 0x8c, 0x99, 0x67, 0xf3, 0x37, 0x7c, 0xba, 0x5f, + 0xc6, 0xfb, 0x3a, 0x35, 0x09, 0x92, 0x09, 0x91, 0x1d, 0xb4, 0xb9, 0xd9, 0x83, 0x36, 0x33, 0xbb, + 0xf3, 0x33, 0x67, 0xf7, 0x0e, 0x5a, 0x8a, 0x8b, 0x7d, 0x73, 0xc6, 0xc7, 0xbd, 0x40, 0x8c, 0x57, + 0xe1, 0x3c, 0xca, 0xa3, 0x93, 0xba, 0x19, 0xf1, 0x29, 0xee, 0x50, 0x5b, 0x89, 0xf1, 0xe2, 0x57, + 0xa8, 0xa4, 0x07, 0x9a, 0x5e, 0x51, 0xcb, 0x73, 0xaf, 0xa8, 0xb2, 0xee, 0x95, 0x44, 0x80, 0x8c, + 0xb5, 0xdc, 0xdd, 0xcb, 0xab, 0xca, 0xc2, 0x9b, 0xab, 0xca, 0xc2, 0xdb, 0xab, 0xca, 0xc2, 0x2f, + 0xa3, 0x8a, 0x75, 0x39, 0xaa, 0x58, 0x6f, 0x46, 0x15, 0xeb, 0xed, 0xa8, 0x62, 0xfd, 0x33, 0xaa, + 0x58, 0xbf, 0xfd, 0x5b, 0x59, 0xf8, 0x7e, 0xb1, 0xbf, 0xf7, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xd7, 0x22, 0x1b, 0x36, 0x96, 0x0a, 0x00, 0x00, } diff --git a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.proto b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.proto index 70f3408d9..0b058c5f7 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.proto +++ b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.apimachinery.pkg.apis.testapigroup.v1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.conversion.go b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.conversion.go index 117a75f32..33d8012c2 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.deepcopy.go index 4b2a9b4f4..ec9acd61a 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.defaults.go b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/zz_generated.deepcopy.go index 341030abd..e107585e3 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/testapigroup/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go b/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go index 17b366617..b3804aa42 100644 --- a/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go +++ b/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go @@ -174,6 +174,9 @@ func convertStruct(result url.Values, st reflect.Type, sv reflect.Value) { kind = ft.Kind() if !field.IsNil() { field = reflect.Indirect(field) + // If the field is non-nil, it should be added to params + // and the omitempty should be overwite to false + omitempty = false } } diff --git a/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/convert_test.go b/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/convert_test.go index b075debf1..1eed5e1fe 100644 --- a/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/convert_test.go +++ b/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/convert_test.go @@ -70,6 +70,7 @@ type childStructs struct { Follow bool `json:"follow,omitempty"` Previous bool `json:"previous,omitempty"` SinceSeconds *int64 `json:"sinceSeconds,omitempty"` + TailLines *int64 `json:"tailLines,omitempty"` SinceTime *metav1.Time `json:"sinceTime,omitempty"` EmptyTime *metav1.Time `json:"emptyTime"` NonPointerTime metav1.Time `json:"nonPointerTime"` @@ -99,6 +100,7 @@ func validateResult(t *testing.T, input interface{}, actual, expected url.Values func TestConvert(t *testing.T) { sinceSeconds := int64(123) + tailLines := int64(0) sinceTime := metav1.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC) tests := []struct { @@ -182,6 +184,7 @@ func TestConvert(t *testing.T) { Follow: true, Previous: true, SinceSeconds: &sinceSeconds, + TailLines: nil, SinceTime: &sinceTime, // test a custom marshaller EmptyTime: nil, // test a nil custom marshaller without omitempty NonPointerTime: sinceTime, @@ -194,10 +197,11 @@ func TestConvert(t *testing.T) { Follow: true, Previous: true, SinceSeconds: &sinceSeconds, + TailLines: &tailLines, SinceTime: nil, // test a nil custom marshaller with omitempty NonPointerTime: sinceTime, }, - expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "emptyTime": {""}, "nonPointerTime": {"2000-01-01T12:34:56Z"}}, + expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "tailLines": {"0"}, "emptyTime": {""}, "nonPointerTime": {"2000-01-01T12:34:56Z"}}, }, } diff --git a/vendor/k8s.io/apimachinery/pkg/fields/selector.go b/vendor/k8s.io/apimachinery/pkg/fields/selector.go index 3785d8c2f..e3e4453b6 100644 --- a/vendor/k8s.io/apimachinery/pkg/fields/selector.go +++ b/vendor/k8s.io/apimachinery/pkg/fields/selector.go @@ -55,6 +55,21 @@ type Selector interface { DeepCopySelector() Selector } +type nothingSelector struct{} + +func (n nothingSelector) Matches(_ Fields) bool { return false } +func (n nothingSelector) Empty() bool { return false } +func (n nothingSelector) String() string { return "" } +func (n nothingSelector) Requirements() Requirements { return nil } +func (n nothingSelector) DeepCopySelector() Selector { return n } +func (n nothingSelector) RequiresExactMatch(field string) (value string, found bool) { return "", false } +func (n nothingSelector) Transform(fn TransformFunc) (Selector, error) { return n, nil } + +// Nothing returns a selector that matches no fields +func Nothing() Selector { + return nothingSelector{} +} + // Everything returns a selector that matches all fields. func Everything() Selector { return andTerm{} @@ -449,6 +464,12 @@ func OneTermEqualSelector(k, v string) Selector { return &hasTerm{field: k, value: v} } +// OneTermNotEqualSelector returns an object that matches objects where one field/field does not equal one value. +// Cannot return an error. +func OneTermNotEqualSelector(k, v string) Selector { + return ¬HasTerm{field: k, value: v} +} + // AndSelectors creates a selector that is the logical AND of all the given selectors func AndSelectors(selectors ...Selector) Selector { return andTerm(selectors) diff --git a/vendor/k8s.io/apimachinery/pkg/labels/selector.go b/vendor/k8s.io/apimachinery/pkg/labels/selector.go index b301b4284..374d2ef13 100644 --- a/vendor/k8s.io/apimachinery/pkg/labels/selector.go +++ b/vendor/k8s.io/apimachinery/pkg/labels/selector.go @@ -166,7 +166,6 @@ func NewRequirement(key string, op selection.Operator, vals []string) (*Requirem return nil, err } } - sort.Strings(vals) return &Requirement{key: key, operator: op, strValues: vals}, nil } @@ -299,7 +298,9 @@ func (r *Requirement) String() string { if len(r.strValues) == 1 { buffer.WriteString(r.strValues[0]) } else { // only > 1 since == 0 prohibited by NewRequirement - buffer.WriteString(strings.Join(r.strValues, ",")) + // normalizes value order on output, without mutating the in-memory selector representation + // also avoids normalization when it is not required, and ensures we do not mutate shared data + buffer.WriteString(strings.Join(safeSort(r.strValues), ",")) } switch r.operator { @@ -309,6 +310,17 @@ func (r *Requirement) String() string { return buffer.String() } +// safeSort sort input strings without modification +func safeSort(in []string) []string { + if sort.StringsAreSorted(in) { + return in + } + out := make([]string, len(in)) + copy(out, in) + sort.Strings(out) + return out +} + // Add adds requirements to the selector. It copies the current selector returning a new one func (lsel internalSelector) Add(reqs ...Requirement) Selector { var sel internalSelector diff --git a/vendor/k8s.io/apimachinery/pkg/labels/selector_test.go b/vendor/k8s.io/apimachinery/pkg/labels/selector_test.go index 995317bd1..a2702989b 100644 --- a/vendor/k8s.io/apimachinery/pkg/labels/selector_test.go +++ b/vendor/k8s.io/apimachinery/pkg/labels/selector_test.go @@ -573,3 +573,47 @@ func TestAdd(t *testing.T) { } } } + +func TestSafeSort(t *testing.T) { + tests := []struct { + name string + in []string + inCopy []string + want []string + }{ + { + name: "nil strings", + in: nil, + inCopy: nil, + want: nil, + }, + { + name: "ordered strings", + in: []string{"bar", "foo"}, + inCopy: []string{"bar", "foo"}, + want: []string{"bar", "foo"}, + }, + { + name: "unordered strings", + in: []string{"foo", "bar"}, + inCopy: []string{"foo", "bar"}, + want: []string{"bar", "foo"}, + }, + { + name: "duplicated strings", + in: []string{"foo", "bar", "foo", "bar"}, + inCopy: []string{"foo", "bar", "foo", "bar"}, + want: []string{"bar", "bar", "foo", "foo"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := safeSort(tt.in); !reflect.DeepEqual(got, tt.want) { + t.Errorf("safeSort() = %v, want %v", got, tt.want) + } + if !reflect.DeepEqual(tt.in, tt.inCopy) { + t.Errorf("after safeSort(), input = %v, want %v", tt.in, tt.inCopy) + } + }) + } +} diff --git a/vendor/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go index a536f9ec9..4d482947f 100644 --- a/vendor/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/converter.go b/vendor/k8s.io/apimachinery/pkg/runtime/converter.go index f6f7c10de..291d7a4e8 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/converter.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/converter.go @@ -73,7 +73,6 @@ var ( mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{}) stringType = reflect.TypeOf(string("")) int64Type = reflect.TypeOf(int64(0)) - uint64Type = reflect.TypeOf(uint64(0)) float64Type = reflect.TypeOf(float64(0)) boolType = reflect.TypeOf(bool(false)) fieldCache = newFieldsCache() @@ -411,8 +410,7 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte var u map[string]interface{} var err error if unstr, ok := obj.(Unstructured); ok { - // UnstructuredContent() mutates the object so we need to make a copy first - u = unstr.DeepCopyObject().(Unstructured).UnstructuredContent() + u = unstr.UnstructuredContent() } else { t := reflect.TypeOf(obj) value := reflect.ValueOf(obj) @@ -439,22 +437,32 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte } // DeepCopyJSON deep copies the passed value, assuming it is a valid JSON representation i.e. only contains -// types produced by json.Unmarshal(). +// types produced by json.Unmarshal() and also int64. +// bool, int64, float64, string, []interface{}, map[string]interface{}, json.Number and nil func DeepCopyJSON(x map[string]interface{}) map[string]interface{} { return DeepCopyJSONValue(x).(map[string]interface{}) } // DeepCopyJSONValue deep copies the passed value, assuming it is a valid JSON representation i.e. only contains -// types produced by json.Unmarshal(). +// types produced by json.Unmarshal() and also int64. +// bool, int64, float64, string, []interface{}, map[string]interface{}, json.Number and nil func DeepCopyJSONValue(x interface{}) interface{} { switch x := x.(type) { case map[string]interface{}: + if x == nil { + // Typed nil - an interface{} that contains a type map[string]interface{} with a value of nil + return x + } clone := make(map[string]interface{}, len(x)) for k, v := range x { clone[k] = DeepCopyJSONValue(v) } return clone case []interface{}: + if x == nil { + // Typed nil - an interface{} that contains a type []interface{} with a value of nil + return x + } clone := make([]interface{}, len(x)) for i, v := range x { clone[i] = DeepCopyJSONValue(v) @@ -584,10 +592,14 @@ func toUnstructured(sv, dv reflect.Value) error { dv.Set(reflect.ValueOf(sv.Int())) return nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + uVal := sv.Uint() + if uVal > math.MaxInt64 { + return fmt.Errorf("unsigned value %d does not fit into int64 (overflow)", uVal) + } if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 { - dv.Set(reflect.New(uint64Type)) + dv.Set(reflect.New(int64Type)) } - dv.Set(reflect.ValueOf(sv.Uint())) + dv.Set(reflect.ValueOf(int64(uVal))) return nil case reflect.Float32, reflect.Float64: if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 { diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/error.go b/vendor/k8s.io/apimachinery/pkg/runtime/error.go index 86b24840f..778796602 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/error.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/error.go @@ -41,10 +41,18 @@ func NewNotRegisteredErrForTarget(t reflect.Type, target GroupVersioner) error { return ¬RegisteredErr{t: t, target: target} } +func NewNotRegisteredGVKErrForTarget(gvk schema.GroupVersionKind, target GroupVersioner) error { + return ¬RegisteredErr{gvk: gvk, target: target} +} + func (k *notRegisteredErr) Error() string { if k.t != nil && k.target != nil { return fmt.Sprintf("%v is not suitable for converting to %q", k.t, k.target) } + nullGVK := schema.GroupVersionKind{} + if k.gvk != nullGVK && k.target != nil { + return fmt.Sprintf("%q is not suitable for converting to %q", k.gvk.GroupVersion(), k.target) + } if k.t != nil { return fmt.Sprintf("no kind is registered for the type %v", k.t) } diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/generated.pb.go b/vendor/k8s.io/apimachinery/pkg/runtime/generated.pb.go index f561fd476..967e0f530 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/generated.pb.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -744,30 +744,29 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 395 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0x4f, 0x6f, 0xd3, 0x30, - 0x18, 0xc6, 0xe3, 0xb5, 0x52, 0x87, 0x5b, 0x69, 0xc8, 0x1c, 0x08, 0x3b, 0x38, 0x53, 0x4f, 0xec, - 0x30, 0x5b, 0x1a, 0x42, 0xe2, 0xba, 0x4c, 0x93, 0x40, 0x08, 0x09, 0x59, 0xfc, 0x91, 0x38, 0xe1, - 0x26, 0x26, 0xb3, 0x42, 0x5f, 0x47, 0x8e, 0x43, 0xd8, 0x8d, 0x8f, 0xc0, 0xc7, 0xea, 0x71, 0xc7, - 0x9e, 0x2a, 0x1a, 0x3e, 0x04, 0x57, 0x54, 0xd7, 0x2d, 0xa5, 0x08, 0xed, 0x16, 0xbf, 0xcf, 0xf3, - 0x7b, 0xde, 0xe7, 0x0d, 0x7e, 0x5e, 0x3e, 0xab, 0x99, 0x36, 0xbc, 0x6c, 0x26, 0xca, 0x82, 0x72, - 0xaa, 0xe6, 0x5f, 0x14, 0xe4, 0xc6, 0xf2, 0x20, 0xc8, 0x4a, 0x4f, 0x65, 0x76, 0xad, 0x41, 0xd9, - 0x1b, 0x5e, 0x95, 0x05, 0xb7, 0x0d, 0x38, 0x3d, 0x55, 0xbc, 0x50, 0xa0, 0xac, 0x74, 0x2a, 0x67, - 0x95, 0x35, 0xce, 0x90, 0x64, 0x0d, 0xb0, 0x5d, 0x80, 0x55, 0x65, 0xc1, 0x02, 0x70, 0x7c, 0x56, - 0x68, 0x77, 0xdd, 0x4c, 0x58, 0x66, 0xa6, 0xbc, 0x30, 0x85, 0xe1, 0x9e, 0x9b, 0x34, 0x9f, 0xfc, - 0xcb, 0x3f, 0xfc, 0xd7, 0x3a, 0xef, 0xf8, 0xc9, 0xff, 0x0a, 0x34, 0x4e, 0x7f, 0xe6, 0x1a, 0x5c, - 0xed, 0xec, 0x7e, 0x89, 0xf1, 0x29, 0x1e, 0x09, 0xd9, 0x5e, 0x7d, 0x75, 0x0a, 0x6a, 0x6d, 0x80, - 0x3c, 0xc2, 0x3d, 0x2b, 0xdb, 0x18, 0x9d, 0xa0, 0xc7, 0xa3, 0x74, 0xd0, 0x2d, 0x92, 0x9e, 0x90, - 0xad, 0x58, 0xcd, 0xc6, 0x1f, 0xf1, 0xe1, 0x9b, 0x9b, 0x4a, 0xbd, 0x52, 0x4e, 0x92, 0x73, 0x8c, - 0x65, 0xa5, 0xdf, 0x29, 0xbb, 0x82, 0xbc, 0xfb, 0x5e, 0x4a, 0x66, 0x8b, 0x24, 0xea, 0x16, 0x09, - 0xbe, 0x78, 0xfd, 0x22, 0x28, 0x62, 0xc7, 0x45, 0x4e, 0x70, 0xbf, 0xd4, 0x90, 0xc7, 0x07, 0xde, - 0x3d, 0x0a, 0xee, 0xfe, 0x4b, 0x0d, 0xb9, 0xf0, 0xca, 0xf8, 0x17, 0xc2, 0x83, 0xb7, 0x50, 0x82, - 0x69, 0x81, 0xbc, 0xc7, 0x87, 0x2e, 0x6c, 0xf3, 0xf9, 0xc3, 0xf3, 0x53, 0x76, 0xc7, 0x0f, 0x63, - 0x9b, 0x7a, 0xe9, 0xfd, 0x10, 0xbe, 0x2d, 0x2c, 0xb6, 0x61, 0x9b, 0x0b, 0x0f, 0xfe, 0xbd, 0x90, - 0x5c, 0xe0, 0xa3, 0xcc, 0x80, 0x53, 0xe0, 0xae, 0x20, 0x33, 0xb9, 0x86, 0x22, 0xee, 0xf9, 0xb2, - 0x0f, 0x43, 0xde, 0xd1, 0xe5, 0xdf, 0xb2, 0xd8, 0xf7, 0x93, 0xa7, 0x78, 0x18, 0x46, 0xab, 0xd5, - 0x71, 0xdf, 0xe3, 0x0f, 0x02, 0x3e, 0xbc, 0xfc, 0x23, 0x89, 0x5d, 0x5f, 0x7a, 0x36, 0x5b, 0xd2, - 0xe8, 0x76, 0x49, 0xa3, 0xf9, 0x92, 0x46, 0xdf, 0x3a, 0x8a, 0x66, 0x1d, 0x45, 0xb7, 0x1d, 0x45, - 0xf3, 0x8e, 0xa2, 0x1f, 0x1d, 0x45, 0xdf, 0x7f, 0xd2, 0xe8, 0xc3, 0x20, 0x1c, 0xfa, 0x3b, 0x00, - 0x00, 0xff, 0xff, 0x3f, 0x1e, 0x24, 0x09, 0x85, 0x02, 0x00, 0x00, + // 378 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x8f, 0x4f, 0xab, 0x13, 0x31, + 0x14, 0xc5, 0x27, 0xaf, 0x85, 0x3e, 0xd3, 0xc2, 0x93, 0xb8, 0x70, 0x74, 0x91, 0x79, 0x74, 0xe5, + 0x5b, 0xbc, 0x04, 0x1e, 0x08, 0x6e, 0x3b, 0xa5, 0xa0, 0x88, 0x20, 0xc1, 0x3f, 0xe0, 0xca, 0x74, + 0x26, 0x4e, 0xc3, 0xd0, 0x9b, 0x21, 0xcd, 0x38, 0x76, 0xe7, 0x47, 0xf0, 0x63, 0x75, 0xd9, 0x65, + 0x57, 0xc5, 0x8e, 0x1f, 0xc2, 0xad, 0x34, 0x4d, 0x6b, 0xd5, 0x85, 0xbb, 0xe4, 0x9e, 0xf3, 0x3b, + 0xf7, 0x1e, 0xfc, 0xbc, 0x7c, 0xb6, 0x60, 0xda, 0xf0, 0xb2, 0x9e, 0x2a, 0x0b, 0xca, 0xa9, 0x05, + 0xff, 0xac, 0x20, 0x37, 0x96, 0x07, 0x41, 0x56, 0x7a, 0x2e, 0xb3, 0x99, 0x06, 0x65, 0x97, 0xbc, + 0x2a, 0x0b, 0x6e, 0x6b, 0x70, 0x7a, 0xae, 0x78, 0xa1, 0x40, 0x59, 0xe9, 0x54, 0xce, 0x2a, 0x6b, + 0x9c, 0x21, 0xc9, 0x01, 0x60, 0xe7, 0x00, 0xab, 0xca, 0x82, 0x05, 0xe0, 0xf1, 0x6d, 0xa1, 0xdd, + 0xac, 0x9e, 0xb2, 0xcc, 0xcc, 0x79, 0x61, 0x0a, 0xc3, 0x3d, 0x37, 0xad, 0x3f, 0xf9, 0x9f, 0xff, + 0xf8, 0xd7, 0x21, 0x6f, 0x78, 0x83, 0x07, 0x42, 0x36, 0x93, 0x2f, 0x4e, 0xc1, 0x42, 0x1b, 0x20, + 0x8f, 0x70, 0xc7, 0xca, 0x26, 0x46, 0xd7, 0xe8, 0xc9, 0x20, 0xed, 0xb5, 0xdb, 0xa4, 0x23, 0x64, + 0x23, 0xf6, 0xb3, 0xe1, 0x47, 0x7c, 0xf9, 0x66, 0x59, 0xa9, 0x57, 0xca, 0x49, 0x72, 0x87, 0xb1, + 0xac, 0xf4, 0x3b, 0x65, 0xf7, 0x90, 0x77, 0xdf, 0x4b, 0xc9, 0x6a, 0x9b, 0x44, 0xed, 0x36, 0xc1, + 0xa3, 0xd7, 0x2f, 0x82, 0x22, 0xce, 0x5c, 0xe4, 0x1a, 0x77, 0x4b, 0x0d, 0x79, 0x7c, 0xe1, 0xdd, + 0x83, 0xe0, 0xee, 0xbe, 0xd4, 0x90, 0x0b, 0xaf, 0x0c, 0x7f, 0x22, 0xdc, 0x7b, 0x0b, 0x25, 0x98, + 0x06, 0xc8, 0x7b, 0x7c, 0xe9, 0xc2, 0x36, 0x9f, 0xdf, 0xbf, 0xbb, 0x61, 0xff, 0xe9, 0xce, 0x8e, + 0xe7, 0xa5, 0xf7, 0x43, 0xf8, 0xe9, 0x60, 0x71, 0x0a, 0x3b, 0x36, 0xbc, 0xf8, 0xb7, 0x21, 0x19, + 0xe1, 0xab, 0xcc, 0x80, 0x53, 0xe0, 0x26, 0x90, 0x99, 0x5c, 0x43, 0x11, 0x77, 0xfc, 0xb1, 0x0f, + 0x43, 0xde, 0xd5, 0xf8, 0x4f, 0x59, 0xfc, 0xed, 0x27, 0x4f, 0x71, 0x3f, 0x8c, 0xf6, 0xab, 0xe3, + 0xae, 0xc7, 0x1f, 0x04, 0xbc, 0x3f, 0xfe, 0x2d, 0x89, 0x73, 0x5f, 0x7a, 0xbb, 0xda, 0xd1, 0x68, + 0xbd, 0xa3, 0xd1, 0x66, 0x47, 0xa3, 0xaf, 0x2d, 0x45, 0xab, 0x96, 0xa2, 0x75, 0x4b, 0xd1, 0xa6, + 0xa5, 0xe8, 0x7b, 0x4b, 0xd1, 0xb7, 0x1f, 0x34, 0xfa, 0xd0, 0x0b, 0x45, 0x7f, 0x05, 0x00, 0x00, + 0xff, 0xff, 0xe3, 0x33, 0x18, 0x0b, 0x50, 0x02, 0x00, 0x00, } diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/generated.proto b/vendor/k8s.io/apimachinery/pkg/runtime/generated.proto index 02e388e90..fb61ac96a 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/generated.proto +++ b/vendor/k8s.io/apimachinery/pkg/runtime/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,8 +21,6 @@ syntax = 'proto2'; package k8s.io.apimachinery.pkg.runtime; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - // Package-wide variables from generator "generated". option go_package = "runtime"; diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go b/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go index 9d00f1650..ba48e6146 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go @@ -174,13 +174,16 @@ type ObjectVersioner interface { // ObjectConvertor converts an object to a different version. type ObjectConvertor interface { - // Convert attempts to convert one object into another, or returns an error. This method does - // not guarantee the in object is not mutated. The context argument will be passed to - // all nested conversions. + // Convert attempts to convert one object into another, or returns an error. This + // method does not mutate the in object, but the in and out object might share data structures, + // i.e. the out object cannot be mutated without mutating the in object as well. + // The context argument will be passed to all nested conversions. Convert(in, out, context interface{}) error // ConvertToVersion takes the provided object and converts it the provided version. This - // method does not guarantee that the in object is not mutated. This method is similar to - // Convert() but handles specific details of choosing the correct output version. + // method does not mutate the in object, but the in and out object might share data structures, + // i.e. the out object cannot be mutated without mutating the in object as well. + // This method is similar to Convert() but handles specific details of choosing the correct + // output version. ConvertToVersion(in Object, gv GroupVersioner) (out Object, err error) ConvertFieldLabel(version, kind, label, value string) (string, string, error) } @@ -234,9 +237,9 @@ type Object interface { // to JSON allowed. type Unstructured interface { Object - // UnstructuredContent returns a non-nil, mutable map of the contents of this object. Values may be + // UnstructuredContent returns a non-nil map with this object's contents. Values may be // []interface{}, map[string]interface{}, or any primitive type. Contents are typically serialized to - // and from JSON. + // and from JSON. SetUnstructuredContent should be used to mutate the contents. UnstructuredContent() map[string]interface{} // SetUnstructuredContent updates the object content to match the provided map. SetUnstructuredContent(map[string]interface{}) diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/local_scheme_test.go b/vendor/k8s.io/apimachinery/pkg/runtime/local_scheme_test.go new file mode 100644 index 000000000..45a0dde5e --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/runtime/local_scheme_test.go @@ -0,0 +1,150 @@ +/* +Copyright 2018 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 runtime + +import ( + "testing" + + "reflect" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/diff" +) + +func TestPreferredVersionsAllGroups(t *testing.T) { + tests := []struct { + name string + versionPriority map[string][]string + observedVersions []schema.GroupVersion + expectedPrioritized map[string][]schema.GroupVersion + expectedPreferred map[schema.GroupVersion]bool + }{ + { + name: "observedOnly", + observedVersions: []schema.GroupVersion{ + {Group: "", Version: "v3"}, + {Group: "foo", Version: "v1"}, + {Group: "foo", Version: "v2"}, + {Group: "", Version: "v1"}, + }, + expectedPrioritized: map[string][]schema.GroupVersion{ + "": { + {Group: "", Version: "v3"}, + {Group: "", Version: "v1"}, + }, + "foo": { + {Group: "foo", Version: "v1"}, + {Group: "foo", Version: "v2"}, + }, + }, + expectedPreferred: map[schema.GroupVersion]bool{ + {Group: "", Version: "v3"}: true, + {Group: "foo", Version: "v1"}: true, + }, + }, + { + name: "specifiedOnly", + versionPriority: map[string][]string{ + "": {"v3", "v1"}, + "foo": {"v1", "v2"}, + }, + expectedPrioritized: map[string][]schema.GroupVersion{ + "": { + {Group: "", Version: "v3"}, + {Group: "", Version: "v1"}, + }, + "foo": { + {Group: "foo", Version: "v1"}, + {Group: "foo", Version: "v2"}, + }, + }, + expectedPreferred: map[schema.GroupVersion]bool{ + {Group: "", Version: "v3"}: true, + {Group: "foo", Version: "v1"}: true, + }, + }, + { + name: "both", + versionPriority: map[string][]string{ + "": {"v3", "v1"}, + "foo": {"v1", "v2"}, + }, + observedVersions: []schema.GroupVersion{ + {Group: "", Version: "v1"}, + {Group: "", Version: "v3"}, + {Group: "", Version: "v4"}, + {Group: "", Version: "v5"}, + {Group: "bar", Version: "v1"}, + {Group: "bar", Version: "v2"}, + }, + expectedPrioritized: map[string][]schema.GroupVersion{ + "": { + {Group: "", Version: "v3"}, + {Group: "", Version: "v1"}, + {Group: "", Version: "v4"}, + {Group: "", Version: "v5"}, + }, + "foo": { + {Group: "foo", Version: "v1"}, + {Group: "foo", Version: "v2"}, + }, + "bar": { + {Group: "bar", Version: "v1"}, + {Group: "bar", Version: "v2"}, + }, + }, + expectedPreferred: map[schema.GroupVersion]bool{ + {Group: "", Version: "v3"}: true, + {Group: "foo", Version: "v1"}: true, + {Group: "bar", Version: "v1"}: true, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + scheme := NewScheme() + scheme.versionPriority = test.versionPriority + scheme.observedVersions = test.observedVersions + + for group, expected := range test.expectedPrioritized { + actual := scheme.PrioritizedVersionsForGroup(group) + if !reflect.DeepEqual(expected, actual) { + t.Error(diff.ObjectDiff(expected, actual)) + } + } + + prioritizedAll := scheme.PrioritizedVersionsAllGroups() + actualPrioritizedAll := map[string][]schema.GroupVersion{} + for _, actual := range prioritizedAll { + actualPrioritizedAll[actual.Group] = append(actualPrioritizedAll[actual.Group], actual) + } + if !reflect.DeepEqual(test.expectedPrioritized, actualPrioritizedAll) { + t.Error(diff.ObjectDiff(test.expectedPrioritized, actualPrioritizedAll)) + } + + preferredAll := scheme.PreferredVersionAllGroups() + actualPreferredAll := map[schema.GroupVersion]bool{} + for _, actual := range preferredAll { + actualPreferredAll[actual] = true + } + if !reflect.DeepEqual(test.expectedPreferred, actualPreferredAll) { + t.Error(diff.ObjectDiff(test.expectedPreferred, actualPreferredAll)) + } + }) + } +} diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go b/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go index 5357628ad..5c9934c73 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,12 +19,12 @@ limitations under the License. // DO NOT EDIT! /* - Package schema is a generated protocol buffer package. +Package schema is a generated protocol buffer package. - It is generated from these files: - k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto +It is generated from these files: + k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto - It has these top-level messages: +It has these top-level messages: */ package schema @@ -48,18 +48,17 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 202 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0xce, 0xaf, 0x4e, 0x04, 0x31, - 0x10, 0xc7, 0xf1, 0xd6, 0x20, 0x90, 0xc8, 0x13, 0x23, 0x51, 0xd0, 0x11, 0x18, 0x34, 0x2f, 0x80, - 0xc7, 0x75, 0xf7, 0x86, 0x6e, 0x53, 0xfa, 0x27, 0xed, 0x94, 0x04, 0xc7, 0x23, 0xf0, 0x58, 0x27, - 0x4f, 0xae, 0x64, 0xcb, 0x8b, 0x90, 0xb4, 0x2b, 0x08, 0xc9, 0xb9, 0xfe, 0xd2, 0x7c, 0x26, 0xdf, - 0xeb, 0x67, 0xf7, 0x58, 0x94, 0x8d, 0xe8, 0xea, 0x44, 0x39, 0x10, 0x53, 0xc1, 0x77, 0x0a, 0xc7, - 0x98, 0x71, 0xff, 0xd0, 0xc9, 0x7a, 0x3d, 0x2f, 0x36, 0x50, 0xfe, 0xc0, 0xe4, 0x0c, 0xe6, 0x1a, - 0xd8, 0x7a, 0xc2, 0x32, 0x2f, 0xe4, 0x35, 0x1a, 0x0a, 0x94, 0x35, 0xd3, 0x51, 0xa5, 0x1c, 0x39, - 0xde, 0xdc, 0x0e, 0xa7, 0xfe, 0x3a, 0x95, 0x9c, 0x51, 0xbb, 0x53, 0xc3, 0x1d, 0xee, 0x8d, 0xe5, - 0xa5, 0x4e, 0x6a, 0x8e, 0x1e, 0x4d, 0x34, 0x11, 0x3b, 0x9f, 0xea, 0x6b, 0x5f, 0x7d, 0xf4, 0xd7, - 0x38, 0x7b, 0x78, 0xb8, 0x94, 0x53, 0xd9, 0xbe, 0xa1, 0x0d, 0x5c, 0x38, 0xff, 0x6f, 0x79, 0xba, - 0x3b, 0x6d, 0x20, 0xce, 0x1b, 0x88, 0x75, 0x03, 0xf1, 0xd9, 0x40, 0x9e, 0x1a, 0xc8, 0x73, 0x03, - 0xb9, 0x36, 0x90, 0xdf, 0x0d, 0xe4, 0xd7, 0x0f, 0x88, 0x97, 0xab, 0x51, 0xf4, 0x1b, 0x00, 0x00, - 0xff, 0xff, 0xfd, 0x59, 0x57, 0x93, 0x0b, 0x01, 0x00, 0x00, + // 185 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0xcc, 0xaf, 0x6e, 0xc3, 0x30, + 0x10, 0xc7, 0x71, 0x9b, 0x0c, 0x0c, 0x0e, 0x0e, 0x1c, 0x1c, 0xda, 0x7c, 0x74, 0xb8, 0x2f, 0x50, + 0x5e, 0xe6, 0x24, 0x57, 0xc7, 0xb2, 0xfc, 0x47, 0x8e, 0x5d, 0xa9, 0xac, 0x8f, 0xd0, 0xc7, 0x0a, + 0x0c, 0x0c, 0x6c, 0xdc, 0x17, 0xa9, 0x64, 0x07, 0x94, 0xdd, 0x4f, 0xa7, 0xcf, 0xf7, 0xf3, 0x68, + 0xfe, 0x27, 0xa1, 0x3d, 0x9a, 0xdc, 0x51, 0x74, 0x94, 0x68, 0xc2, 0x0b, 0xb9, 0xc1, 0x47, 0xdc, + 0x1f, 0x32, 0x68, 0x2b, 0xfb, 0x51, 0x3b, 0x8a, 0x57, 0x0c, 0x46, 0x61, 0xcc, 0x2e, 0x69, 0x4b, + 0x38, 0xf5, 0x23, 0x59, 0x89, 0x8a, 0x1c, 0x45, 0x99, 0x68, 0x10, 0x21, 0xfa, 0xe4, 0xbf, 0x7e, + 0x9a, 0x13, 0xef, 0x4e, 0x04, 0xa3, 0xc4, 0xee, 0x44, 0x73, 0xdf, 0x7f, 0x4a, 0xa7, 0x31, 0x77, + 0xa2, 0xf7, 0x16, 0x95, 0x57, 0x1e, 0x2b, 0xef, 0xf2, 0xb9, 0xae, 0x3a, 0xea, 0xd5, 0xb2, 0x87, + 0xdf, 0x79, 0x03, 0xb6, 0x6c, 0xc0, 0xd6, 0x0d, 0xd8, 0xad, 0x00, 0x9f, 0x0b, 0xf0, 0xa5, 0x00, + 0x5f, 0x0b, 0xf0, 0x47, 0x01, 0x7e, 0x7f, 0x02, 0x3b, 0x7d, 0xb4, 0xf8, 0x2b, 0x00, 0x00, 0xff, + 0xff, 0xba, 0x7e, 0x65, 0xf4, 0xd6, 0x00, 0x00, 0x00, } diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto b/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto index 50c2f2a63..5aeeaa100 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto +++ b/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,8 +21,6 @@ syntax = 'proto2'; package k8s.io.apimachinery.pkg.runtime.schema; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - // Package-wide variables from generator "generated". option go_package = "schema"; diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/schema/group_version_test.go b/vendor/k8s.io/apimachinery/pkg/runtime/schema/group_version_test.go index 51f26df7f..3934bc45a 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/schema/group_version_test.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/schema/group_version_test.go @@ -134,3 +134,47 @@ func TestKindForGroupVersionKinds(t *testing.T) { } } } + +func TestParseKindArg(t *testing.T) { + tests := []struct { + input string + gvk *GroupVersionKind + gk GroupKind + }{ + {input: "Pod", gk: GroupKind{Kind: "Pod"}}, + {input: ".apps", gk: GroupKind{Group: "apps"}}, + {input: "Pod.", gk: GroupKind{Kind: "Pod"}}, + {input: "StatefulSet.apps", gk: GroupKind{Group: "apps", Kind: "StatefulSet"}}, + {input: "StatefulSet.v1.apps", gvk: &GroupVersionKind{Group: "apps", Version: "v1", Kind: "StatefulSet"}, gk: GroupKind{Group: "v1.apps", Kind: "StatefulSet"}}, + } + for i, test := range tests { + t.Run(test.input, func(t *testing.T) { + gvk, gk := ParseKindArg(test.input) + if (gvk != nil && test.gvk == nil) || (gvk == nil && test.gvk != nil) || (test.gvk != nil && *gvk != *test.gvk) { + t.Errorf("%d: expected output: %#v, got: %#v", i, test.gvk, gvk) + } + if gk != test.gk { + t.Errorf("%d: expected output: %#v, got: %#v", i, test.gk, gk) + } + }) + } +} + +func TestParseGroupKind(t *testing.T) { + tests := []struct { + input string + out GroupKind + }{ + {input: "Pod", out: GroupKind{Kind: "Pod"}}, + {input: ".StatefulSet", out: GroupKind{Group: "StatefulSet"}}, + {input: "StatefulSet.apps", out: GroupKind{Group: "apps", Kind: "StatefulSet"}}, + } + for i, test := range tests { + t.Run(test.input, func(t *testing.T) { + out := ParseGroupKind(test.input) + if out != test.out { + t.Errorf("%d: expected output: %#v, got: %#v", i, test.out, out) + } + }) + } +} diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/scheme.go b/vendor/k8s.io/apimachinery/pkg/runtime/scheme.go index 3d94a3041..59163d777 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/scheme.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/scheme.go @@ -21,8 +21,11 @@ import ( "net/url" "reflect" + "strings" + "k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/sets" ) // Scheme defines methods for serializing and deserializing API objects, a type @@ -68,6 +71,13 @@ type Scheme struct { // converter stores all registered conversion functions. It also has // default coverting behavior. converter *conversion.Converter + + // versionPriority is a map of groups to ordered lists of versions for those groups indicating the + // default priorities of these versions as registered in the scheme + versionPriority map[string][]string + + // observedVersions keeps track of the order we've seen versions during type registration + observedVersions []schema.GroupVersion } // Function to convert a field selector to internal representation. @@ -82,6 +92,7 @@ func NewScheme() *Scheme { unversionedKinds: map[string]reflect.Type{}, fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{}, defaulterFuncs: map[reflect.Type]func(interface{}){}, + versionPriority: map[string][]string{}, } s.converter = conversion.NewConverter(s.nameFunc) @@ -111,7 +122,7 @@ func (s *Scheme) nameFunc(t reflect.Type) string { for _, gvk := range gvks { internalGV := gvk.GroupVersion() - internalGV.Version = "__internal" // this is hacky and maybe should be passed in + internalGV.Version = APIVersionInternal // this is hacky and maybe should be passed in internalGVK := internalGV.WithKind(gvk.Kind) if internalType, exists := s.gvkToType[internalGVK]; exists { @@ -141,6 +152,7 @@ func (s *Scheme) Converter() *conversion.Converter { // TODO: there is discussion about removing unversioned and replacing it with objects that are manifest into // every version with particular schemas. Resolve this method at that point. func (s *Scheme) AddUnversionedTypes(version schema.GroupVersion, types ...Object) { + s.addObservedVersion(version) s.AddKnownTypes(version, types...) for _, obj := range types { t := reflect.TypeOf(obj).Elem() @@ -158,6 +170,7 @@ func (s *Scheme) AddUnversionedTypes(version schema.GroupVersion, types ...Objec // the struct becomes the "kind" field when encoding. Version may not be empty - use the // APIVersionInternal constant if you have a type that does not have a formal version. func (s *Scheme) AddKnownTypes(gv schema.GroupVersion, types ...Object) { + s.addObservedVersion(gv) for _, obj := range types { t := reflect.TypeOf(obj) if t.Kind() != reflect.Ptr { @@ -173,6 +186,7 @@ func (s *Scheme) AddKnownTypes(gv schema.GroupVersion, types ...Object) { // your structs. Version may not be empty - use the APIVersionInternal constant if you have a // type that does not have a formal version. func (s *Scheme) AddKnownTypeWithName(gvk schema.GroupVersionKind, obj Object) { + s.addObservedVersion(gvk.GroupVersion()) t := reflect.TypeOf(obj) if len(gvk.Version) == 0 { panic(fmt.Sprintf("version is required on all types: %s %v", gvk, t)) @@ -620,3 +634,133 @@ func setTargetKind(obj Object, kind schema.GroupVersionKind) { } obj.GetObjectKind().SetGroupVersionKind(kind) } + +// SetVersionPriority allows specifying a precise order of priority. All specified versions must be in the same group, +// and the specified order overwrites any previously specified order for this group +func (s *Scheme) SetVersionPriority(versions ...schema.GroupVersion) error { + groups := sets.String{} + order := []string{} + for _, version := range versions { + if len(version.Version) == 0 || version.Version == APIVersionInternal { + return fmt.Errorf("internal versions cannot be prioritized: %v", version) + } + + groups.Insert(version.Group) + order = append(order, version.Version) + } + if len(groups) != 1 { + return fmt.Errorf("must register versions for exactly one group: %v", strings.Join(groups.List(), ", ")) + } + + s.versionPriority[groups.List()[0]] = order + return nil +} + +// PrioritizedVersionsForGroup returns versions for a single group in priority order +func (s *Scheme) PrioritizedVersionsForGroup(group string) []schema.GroupVersion { + ret := []schema.GroupVersion{} + for _, version := range s.versionPriority[group] { + ret = append(ret, schema.GroupVersion{Group: group, Version: version}) + } + for _, observedVersion := range s.observedVersions { + if observedVersion.Group != group { + continue + } + found := false + for _, existing := range ret { + if existing == observedVersion { + found = true + break + } + } + if !found { + ret = append(ret, observedVersion) + } + } + + return ret +} + +// PrioritizedVersionsAllGroups returns all known versions in their priority order. Groups are random, but +// versions for a single group are prioritized +func (s *Scheme) PrioritizedVersionsAllGroups() []schema.GroupVersion { + ret := []schema.GroupVersion{} + for group, versions := range s.versionPriority { + for _, version := range versions { + ret = append(ret, schema.GroupVersion{Group: group, Version: version}) + } + } + for _, observedVersion := range s.observedVersions { + found := false + for _, existing := range ret { + if existing == observedVersion { + found = true + break + } + } + if !found { + ret = append(ret, observedVersion) + } + } + return ret +} + +// PreferredVersionAllGroups returns the most preferred version for every group. +// group ordering is random. +func (s *Scheme) PreferredVersionAllGroups() []schema.GroupVersion { + ret := []schema.GroupVersion{} + for group, versions := range s.versionPriority { + for _, version := range versions { + ret = append(ret, schema.GroupVersion{Group: group, Version: version}) + break + } + } + for _, observedVersion := range s.observedVersions { + found := false + for _, existing := range ret { + if existing.Group == observedVersion.Group { + found = true + break + } + } + if !found { + ret = append(ret, observedVersion) + } + } + + return ret +} + +// IsGroupRegistered returns true if types for the group have been registered with the scheme +func (s *Scheme) IsGroupRegistered(group string) bool { + for _, observedVersion := range s.observedVersions { + if observedVersion.Group == group { + return true + } + } + return false +} + +// IsVersionRegistered returns true if types for the version have been registered with the scheme +func (s *Scheme) IsVersionRegistered(version schema.GroupVersion) bool { + for _, observedVersion := range s.observedVersions { + if observedVersion == version { + return true + } + } + + return false +} + +func (s *Scheme) addObservedVersion(version schema.GroupVersion) { + if len(version.Version) == 0 || version.Version == APIVersionInternal { + return + } + for _, observedVersion := range s.observedVersions { + if observedVersion == version { + return + } + } + + s.observedVersions = append(s.observedVersions, version) +} diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go index 2b795b5b8..068d3f708 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go @@ -75,11 +75,6 @@ func init() { case jsoniter.NumberValue: var number json.Number iter.ReadVal(&number) - u64, err := strconv.ParseUint(string(number), 10, 64) - if err == nil { - *(*interface{})(ptr) = u64 - return - } i64, err := strconv.ParseInt(string(number), 10, 64) if err == nil { *(*interface{})(ptr) = i64 @@ -98,6 +93,20 @@ func init() { jsoniter.RegisterTypeDecoderFunc("interface {}", decodeNumberAsInt64IfPossible) } +// CaseSensitiveJsonIterator returns a jsoniterator API that's configured to be +// case-sensitive when unmarshalling, and otherwise compatible with +// the encoding/json standard library. +func CaseSensitiveJsonIterator() jsoniter.API { + return jsoniter.Config{ + EscapeHTML: true, + SortMapKeys: true, + ValidateJsonRawMessage: true, + CaseSensitive: true, + }.Froze() +} + +var caseSensitiveJsonIterator = CaseSensitiveJsonIterator() + // gvkWithDefaults returns group kind and version defaulting from provided default func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind { if len(actual.Kind) == 0 { @@ -162,7 +171,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i types, _, err := s.typer.ObjectKinds(into) switch { case runtime.IsNotRegisteredError(err), isUnstructured: - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, into); err != nil { + if err := caseSensitiveJsonIterator.Unmarshal(data, into); err != nil { return nil, actual, err } return into, actual, nil @@ -186,7 +195,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i return nil, actual, err } - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, obj); err != nil { + if err := caseSensitiveJsonIterator.Unmarshal(data, obj); err != nil { return nil, actual, err } return obj, actual, nil @@ -195,7 +204,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i // Encode serializes the provided object to the given writer. func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error { if s.yaml { - json, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(obj) + json, err := caseSensitiveJsonIterator.Marshal(obj) if err != nil { return err } @@ -208,7 +217,7 @@ func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error { } if s.pretty { - data, err := jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent(obj, "", " ") + data, err := caseSensitiveJsonIterator.MarshalIndent(obj, "", " ") if err != nil { return err } diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go index c8ae5550c..b3d629a06 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go @@ -30,10 +30,31 @@ import ( type testDecodable struct { Other string - Value int `json:"value"` + Value int `json:"value"` + Spec DecodableSpec `json:"spec"` gvk schema.GroupVersionKind } +// DecodableSpec has 15 fields. json-iterator treats struct with more than 10 +// fields differently from struct that has less than 10 fields. +type DecodableSpec struct { + A int `json:"A"` + B int `json:"B"` + C int `json:"C"` + D int `json:"D"` + E int `json:"E"` + F int `json:"F"` + G int `json:"G"` + H int `json:"h"` + I int `json:"i"` + J int `json:"j"` + K int `json:"k"` + L int `json:"l"` + M int `json:"m"` + N int `json:"n"` + O int `json:"o"` +} + func (d *testDecodable) GetObjectKind() schema.ObjectKind { return d } func (d *testDecodable) SetGroupVersionKind(gvk schema.GroupVersionKind) { d.gvk = gvk } func (d *testDecodable) GroupVersionKind() schema.GroupVersionKind { return d.gvk } @@ -221,6 +242,28 @@ func TestDecode(t *testing.T) { }, }, }, + // Unmarshalling is case-sensitive + { + // "VaLue" should have been "value" + data: []byte(`{"kind":"Test","apiVersion":"other/blah","VaLue":1,"Other":"test"}`), + into: &testDecodable{}, + typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})}, + expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, + expectedObject: &testDecodable{ + Other: "test", + }, + }, + // Unmarshalling is case-sensitive for big struct. + { + // "b" should have been "B", "I" should have been "i" + data: []byte(`{"kind":"Test","apiVersion":"other/blah","spec": {"A": 1, "b": 2, "h": 3, "I": 4}}`), + into: &testDecodable{}, + typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})}, + expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, + expectedObject: &testDecodable{ + Spec: DecodableSpec{A: 1, H: 3}, + }, + }, } for i, test := range testCases { diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/sparse_test.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/sparse_test.go new file mode 100644 index 000000000..3bc9d13bb --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/sparse_test.go @@ -0,0 +1,91 @@ +/* +Copyright 2018 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 serializer + +import ( + "testing" + + "k8s.io/apimachinery/pkg/api/equality" + 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" +) + +type FakeV1Obj struct { + metav1.TypeMeta + metav1.ObjectMeta +} + +func (*FakeV1Obj) DeepCopyObject() runtime.Object { + panic("not supported") +} + +type FakeV2DifferentObj struct { + metav1.TypeMeta + metav1.ObjectMeta +} + +func (*FakeV2DifferentObj) DeepCopyObject() runtime.Object { + panic("not supported") +} +func TestSparse(t *testing.T) { + v1 := schema.GroupVersion{Group: "mygroup", Version: "v1"} + v2 := schema.GroupVersion{Group: "mygroup", Version: "v2"} + + scheme := runtime.NewScheme() + scheme.AddKnownTypes(v1, &FakeV1Obj{}) + scheme.AddKnownTypes(v2, &FakeV2DifferentObj{}) + codecs := NewCodecFactory(scheme) + + srcObj1 := &FakeV1Obj{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + srcObj2 := &FakeV2DifferentObj{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + + encoder := codecs.LegacyCodec(v2, v1) + decoder := codecs.UniversalDecoder(v2, v1) + + srcObj1Bytes, err := runtime.Encode(encoder, srcObj1) + if err != nil { + t.Fatal(err) + } + t.Log(string(srcObj1Bytes)) + srcObj2Bytes, err := runtime.Encode(encoder, srcObj2) + if err != nil { + t.Fatal(err) + } + t.Log(string(srcObj2Bytes)) + + uncastDstObj1, err := runtime.Decode(decoder, srcObj1Bytes) + if err != nil { + t.Fatal(err) + } + uncastDstObj2, err := runtime.Decode(decoder, srcObj2Bytes) + if err != nil { + t.Fatal(err) + } + + // clear typemeta + uncastDstObj1.(*FakeV1Obj).TypeMeta = metav1.TypeMeta{} + uncastDstObj2.(*FakeV2DifferentObj).TypeMeta = metav1.TypeMeta{} + + if !equality.Semantic.DeepEqual(srcObj1, uncastDstObj1) { + t.Fatal(diff.ObjectDiff(srcObj1, uncastDstObj1)) + } + if !equality.Semantic.DeepEqual(srcObj2, uncastDstObj2) { + t.Fatal(diff.ObjectDiff(srcObj2, uncastDstObj2)) + } +} diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/testing/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/testing/zz_generated.deepcopy.go index 200e92468..8796679dc 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/testing/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/testing/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go index b717fe8fe..7716cc421 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go @@ -19,6 +19,7 @@ package versioning import ( "io" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -166,9 +167,27 @@ func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into ru // Encode ensures the provided object is output in the appropriate group and version, invoking // conversion if necessary. Unversioned objects (according to the ObjectTyper) are output as is. func (c *codec) Encode(obj runtime.Object, w io.Writer) error { - switch obj.(type) { - case *runtime.Unknown, runtime.Unstructured: + switch obj := obj.(type) { + case *runtime.Unknown: return c.encoder.Encode(obj, w) + case runtime.Unstructured: + // An unstructured list can contain objects of multiple group version kinds. don't short-circuit just + // because the top-level type matches our desired destination type. actually send the object to the converter + // to give it a chance to convert the list items if needed. + if _, ok := obj.(*unstructured.UnstructuredList); !ok { + // avoid conversion roundtrip if GVK is the right one already or is empty (yes, this is a hack, but the old behaviour we rely on in kubectl) + objGVK := obj.GetObjectKind().GroupVersionKind() + if len(objGVK.Version) == 0 { + return c.encoder.Encode(obj, w) + } + targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK}) + if !ok { + return runtime.NewNotRegisteredGVKErrForTarget(objGVK, c.encodeVersion) + } + if targetGVK == objGVK { + return c.encoder.Encode(obj, w) + } + } } gvks, isUnversioned, err := c.typer.ObjectKinds(obj) diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go index 43c242657..f79b2a7cb 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go @@ -129,25 +129,25 @@ func TestDecode(t *testing.T) { }{ { serializer: &mockSerializer{actual: gvk1}, - convertor: &checkConvertor{groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}}, + convertor: &checkConvertor{groupVersion: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}}, expectedGVK: gvk1, - decodes: schema.GroupVersion{Group: "other", Version: "__internal"}, + decodes: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}, }, { serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}}, + convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}}, expectedGVK: gvk1, sameObject: decodable2, - decodes: schema.GroupVersion{Group: "other", Version: "__internal"}, + decodes: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}, }, // defaultGVK.Group is allowed to force a conversion to the destination group { serializer: &mockSerializer{actual: gvk1, obj: decodable1}, defaultGVK: &schema.GroupVersionKind{Group: "force"}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "force", Version: "__internal"}}, + convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "force", Version: runtime.APIVersionInternal}}, expectedGVK: gvk1, sameObject: decodable2, - decodes: schema.GroupVersion{Group: "force", Version: "__internal"}, + decodes: schema.GroupVersion{Group: "force", Version: runtime.APIVersionInternal}, }, // uses direct conversion for into when objects differ { @@ -184,10 +184,10 @@ func TestDecode(t *testing.T) { into: &runtime.VersionedObjects{Objects: []runtime.Object{}}, serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}}, + convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}}, expectedGVK: gvk1, expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1, decodable2}}, - decodes: schema.GroupVersion{Group: "other", Version: "__internal"}, + decodes: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}, }, // decode into the same version as the serialized object diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/testing/types.go b/vendor/k8s.io/apimachinery/pkg/runtime/testing/types.go index 0694e7011..b8d67061d 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/testing/types.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/testing/types.go @@ -263,7 +263,7 @@ func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { func (obj *Unstructured) UnstructuredContent() map[string]interface{} { if obj.Object == nil { - obj.Object = make(map[string]interface{}) + return make(map[string]interface{}) } return obj.Object } diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/testing/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/runtime/testing/zz_generated.deepcopy.go index 787bffe56..957cbf9ee 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/testing/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/testing/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go index ba89cd235..167de6104 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/test/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/test/zz_generated.deepcopy.go index 1a080acc7..6cdf98394 100644 --- a/vendor/k8s.io/apimachinery/pkg/test/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/test/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/types/namespacedname.go b/vendor/k8s.io/apimachinery/pkg/types/namespacedname.go index 1e2130da0..88f0de36d 100644 --- a/vendor/k8s.io/apimachinery/pkg/types/namespacedname.go +++ b/vendor/k8s.io/apimachinery/pkg/types/namespacedname.go @@ -18,7 +18,6 @@ package types import ( "fmt" - "strings" ) // NamespacedName comprises a resource name, with a mandatory namespace, @@ -42,19 +41,3 @@ const ( func (n NamespacedName) String() string { return fmt.Sprintf("%s%c%s", n.Namespace, Separator, n.Name) } - -// NewNamespacedNameFromString parses the provided string and returns a NamespacedName. -// The expected format is as per String() above. -// If the input string is invalid, the returned NamespacedName has all empty string field values. -// This allows a single-value return from this function, while still allowing error checks in the caller. -// Note that an input string which does not include exactly one Separator is not a valid input (as it could never -// have neem returned by String() ) -func NewNamespacedNameFromString(s string) NamespacedName { - nn := NamespacedName{} - result := strings.Split(s, string(Separator)) - if len(result) == 2 { - nn.Namespace = result[0] - nn.Name = result[1] - } - return nn -} diff --git a/vendor/k8s.io/apimachinery/pkg/util/clock/clock.go b/vendor/k8s.io/apimachinery/pkg/util/clock/clock.go index c303a212a..9567f9006 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/clock/clock.go +++ b/vendor/k8s.io/apimachinery/pkg/util/clock/clock.go @@ -26,18 +26,12 @@ import ( type Clock interface { Now() time.Time Since(time.Time) time.Duration - After(d time.Duration) <-chan time.Time - NewTimer(d time.Duration) Timer - Sleep(d time.Duration) - Tick(d time.Duration) <-chan time.Time + After(time.Duration) <-chan time.Time + NewTimer(time.Duration) Timer + Sleep(time.Duration) + NewTicker(time.Duration) Ticker } -var ( - _ = Clock(RealClock{}) - _ = Clock(&FakeClock{}) - _ = Clock(&IntervalClock{}) -) - // RealClock really calls time.Now() type RealClock struct{} @@ -62,8 +56,10 @@ func (RealClock) NewTimer(d time.Duration) Timer { } } -func (RealClock) Tick(d time.Duration) <-chan time.Time { - return time.Tick(d) +func (RealClock) NewTicker(d time.Duration) Ticker { + return &realTicker{ + ticker: time.NewTicker(d), + } } func (RealClock) Sleep(d time.Duration) { @@ -137,7 +133,7 @@ func (f *FakeClock) NewTimer(d time.Duration) Timer { return timer } -func (f *FakeClock) Tick(d time.Duration) <-chan time.Time { +func (f *FakeClock) NewTicker(d time.Duration) Ticker { f.lock.Lock() defer f.lock.Unlock() tickTime := f.time.Add(d) @@ -149,7 +145,9 @@ func (f *FakeClock) Tick(d time.Duration) <-chan time.Time { destChan: ch, }) - return ch + return &fakeTicker{ + c: ch, + } } // Move clock by Duration, notify anyone that's called After, Tick, or NewTimer @@ -242,8 +240,8 @@ func (*IntervalClock) NewTimer(d time.Duration) Timer { // Unimplemented, will panic. // TODO: make interval clock use FakeClock so this can be implemented. -func (*IntervalClock) Tick(d time.Duration) <-chan time.Time { - panic("IntervalClock doesn't implement Tick") +func (*IntervalClock) NewTicker(d time.Duration) Ticker { + panic("IntervalClock doesn't implement NewTicker") } func (*IntervalClock) Sleep(d time.Duration) { @@ -258,11 +256,6 @@ type Timer interface { Reset(d time.Duration) bool } -var ( - _ = Timer(&realTimer{}) - _ = Timer(&fakeTimer{}) -) - // realTimer is backed by an actual time.Timer. type realTimer struct { timer *time.Timer @@ -325,3 +318,31 @@ func (f *fakeTimer) Reset(d time.Duration) bool { return active } + +type Ticker interface { + C() <-chan time.Time + Stop() +} + +type realTicker struct { + ticker *time.Ticker +} + +func (t *realTicker) C() <-chan time.Time { + return t.ticker.C +} + +func (t *realTicker) Stop() { + t.ticker.Stop() +} + +type fakeTicker struct { + c <-chan time.Time +} + +func (t *fakeTicker) C() <-chan time.Time { + return t.c +} + +func (t *fakeTicker) Stop() { +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/clock/clock_test.go b/vendor/k8s.io/apimachinery/pkg/util/clock/clock_test.go index 27d34605f..c7b371fc6 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/clock/clock_test.go +++ b/vendor/k8s.io/apimachinery/pkg/util/clock/clock_test.go @@ -21,6 +21,18 @@ import ( "time" ) +var ( + _ = Clock(RealClock{}) + _ = Clock(&FakeClock{}) + _ = Clock(&IntervalClock{}) + + _ = Timer(&realTimer{}) + _ = Timer(&fakeTimer{}) + + _ = Ticker(&realTicker{}) + _ = Ticker(&fakeTicker{}) +) + func TestFakeClock(t *testing.T) { startTime := time.Now() tc := NewFakeClock(startTime) @@ -110,13 +122,13 @@ func TestFakeTick(t *testing.T) { if tc.HasWaiters() { t.Errorf("unexpected waiter?") } - oneSec := tc.Tick(time.Second) + oneSec := tc.NewTicker(time.Second).C() if !tc.HasWaiters() { t.Errorf("unexpected lack of waiter?") } - oneOhOneSec := tc.Tick(time.Second + time.Millisecond) - twoSec := tc.Tick(2 * time.Second) + oneOhOneSec := tc.NewTicker(time.Second + time.Millisecond).C() + twoSec := tc.NewTicker(2 * time.Second).C() select { case <-oneSec: t.Errorf("unexpected channel read") diff --git a/vendor/k8s.io/apimachinery/pkg/util/diff/diff.go b/vendor/k8s.io/apimachinery/pkg/util/diff/diff.go index 3d5ec14bf..bce95baf1 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/diff/diff.go +++ b/vendor/k8s.io/apimachinery/pkg/util/diff/diff.go @@ -89,20 +89,52 @@ func ObjectReflectDiff(a, b interface{}) string { } out := []string{""} for _, d := range diffs { + elidedA, elidedB := limit(d.a, d.b, 80) out = append(out, fmt.Sprintf("%s:", d.path), - limit(fmt.Sprintf(" a: %#v", d.a), 80), - limit(fmt.Sprintf(" b: %#v", d.b), 80), + fmt.Sprintf(" a: %s", elidedA), + fmt.Sprintf(" b: %s", elidedB), ) } return strings.Join(out, "\n") } -func limit(s string, max int) string { - if len(s) > max { - return s[:max] +// limit: +// 1. stringifies aObj and bObj +// 2. elides identical prefixes if either is too long +// 3. elides remaining content from the end if either is too long +func limit(aObj, bObj interface{}, max int) (string, string) { + elidedPrefix := "" + elidedASuffix := "" + elidedBSuffix := "" + a, b := fmt.Sprintf("%#v", aObj), fmt.Sprintf("%#v", bObj) + for { + switch { + case len(a) > max && len(a) > 4 && len(b) > 4 && a[:4] == b[:4]: + // a is too long, b has data, and the first several characters are the same + elidedPrefix = "..." + a = a[2:] + b = b[2:] + + case len(b) > max && len(b) > 4 && len(a) > 4 && a[:4] == b[:4]: + // b is too long, a has data, and the first several characters are the same + elidedPrefix = "..." + a = a[2:] + b = b[2:] + + case len(a) > max: + a = a[:max] + elidedASuffix = "..." + + case len(b) > max: + b = b[:max] + elidedBSuffix = "..." + + default: + // both are short enough + return elidedPrefix + a + elidedASuffix, elidedPrefix + b + elidedBSuffix + } } - return s } func public(s string) bool { diff --git a/vendor/k8s.io/apimachinery/pkg/util/diff/diff_test.go b/vendor/k8s.io/apimachinery/pkg/util/diff/diff_test.go index 2b72c2f53..d26dba818 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/diff/diff_test.go +++ b/vendor/k8s.io/apimachinery/pkg/util/diff/diff_test.go @@ -94,3 +94,50 @@ func TestStringDiff(t *testing.T) { t.Errorf("diff returned %v", diff) } } + +func TestLimit(t *testing.T) { + testcases := []struct { + a interface{} + b interface{} + expectA string + expectB string + }{ + { + a: `short a`, + b: `short b`, + expectA: `"short a"`, + expectB: `"short b"`, + }, + { + a: `short a`, + b: `long b needs truncating`, + expectA: `"short a"`, + expectB: `"long b ne...`, + }, + { + a: `long a needs truncating`, + b: `long b needs truncating`, + expectA: `...g a needs ...`, + expectB: `...g b needs ...`, + }, + { + a: `long common prefix with different stuff at the end of a`, + b: `long common prefix with different stuff at the end of b`, + expectA: `...end of a"`, + expectB: `...end of b"`, + }, + { + a: `long common prefix with different stuff at the end of a`, + b: `long common prefix with different stuff at the end of b which continues`, + expectA: `...of a"`, + expectB: `...of b which...`, + }, + } + + for _, tc := range testcases { + a, b := limit(tc.a, tc.b, 10) + if a != tc.expectA || b != tc.expectB { + t.Errorf("limit(%q, %q)\n\texpected: %s, %s\n\tgot: %s, %s", tc.a, tc.b, tc.expectA, tc.expectB, a, b) + } + } +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go index d2d3ad8cb..dd781cbc8 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go +++ b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go @@ -19,6 +19,7 @@ package spdy import ( "bufio" "bytes" + "context" "crypto/tls" "encoding/base64" "fmt" @@ -118,7 +119,7 @@ func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { } if proxyURL == nil { - return s.dialWithoutProxy(req.URL) + return s.dialWithoutProxy(req.Context(), req.URL) } // ensure we use a canonical host with proxyReq @@ -136,7 +137,7 @@ func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { proxyReq.Header.Set("Proxy-Authorization", pa) } - proxyDialConn, err := s.dialWithoutProxy(proxyURL) + proxyDialConn, err := s.dialWithoutProxy(req.Context(), proxyURL) if err != nil { return nil, err } @@ -187,14 +188,15 @@ func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { } // dialWithoutProxy dials the host specified by url, using TLS if appropriate. -func (s *SpdyRoundTripper) dialWithoutProxy(url *url.URL) (net.Conn, error) { +func (s *SpdyRoundTripper) dialWithoutProxy(ctx context.Context, url *url.URL) (net.Conn, error) { dialAddr := netutil.CanonicalAddr(url) if url.Scheme == "http" { if s.Dialer == nil { - return net.Dial("tcp", dialAddr) + var d net.Dialer + return d.DialContext(ctx, "tcp", dialAddr) } else { - return s.Dialer.Dial("tcp", dialAddr) + return s.Dialer.DialContext(ctx, "tcp", dialAddr) } } diff --git a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go index 887adbe8f..fb396bca5 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go +++ b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go @@ -399,7 +399,7 @@ func TestRoundTripRedirects(t *testing.T) { var redirects int32 = 0 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if redirects < test.redirects { - redirects = atomic.AddInt32(&redirects, 1) + atomic.AddInt32(&redirects, 1) http.Redirect(w, req, "redirect", http.StatusFound) return } diff --git a/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go b/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go index 161e9a6f8..5c2ac4f23 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go +++ b/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto b/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto index 6819d468d..1c3ec732e 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto +++ b/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch.go b/vendor/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch.go index e81e4f23a..82e4b4b57 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch.go +++ b/vendor/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch.go @@ -116,10 +116,26 @@ func keepOrDeleteNullInObj(m map[string]interface{}, keepNull bool) (map[string] case val != nil: switch typedVal := val.(type) { case map[string]interface{}: - filteredMap[key], err = keepOrDeleteNullInObj(typedVal, keepNull) + // Explicitly-set empty maps are treated as values instead of empty patches + if len(typedVal) == 0 { + if !keepNull { + filteredMap[key] = typedVal + } + continue + } + + var filteredSubMap map[string]interface{} + filteredSubMap, err = keepOrDeleteNullInObj(typedVal, keepNull) if err != nil { return nil, err } + + // If the returned filtered submap was empty, this is an empty patch for the entire subdict, so the key + // should not be set + if len(filteredSubMap) != 0 { + filteredMap[key] = filteredSubMap + } + case []interface{}, string, float64, bool, int, int64, nil: // Lists are always replaced in Json, no need to check each entry in the list. if !keepNull { diff --git a/vendor/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch_test.go b/vendor/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch_test.go index f462bf915..9672deaad 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch_test.go +++ b/vendor/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch_test.go @@ -62,12 +62,12 @@ testCases: expectedWithoutNull: {} - description: simple map with all non-nil values originalObj: - nonNilKey: foo - nonNilKey: bar + nonNilKey1: foo + nonNilKey2: bar expectedWithNull: {} expectedWithoutNull: - nonNilKey: foo - nonNilKey: bar + nonNilKey1: foo + nonNilKey2: bar - description: nested map originalObj: mapKey: @@ -88,19 +88,52 @@ testCases: mapKey: nilKey1: null nilKey2: null + expectedWithoutNull: {} + - description: nested map that all subkeys are non-nil + originalObj: + mapKey: + nonNilKey1: foo + nonNilKey2: bar + expectedWithNull: {} expectedWithoutNull: + mapKey: + nonNilKey1: foo + nonNilKey2: bar + - description: explicitly empty map as value + originalObj: mapKey: {} - - description: nested map that all subkeys are non-nil + expectedWithNull: {} + expectedWithoutNull: + mapKey: {} + - description: explicitly empty nested map originalObj: mapKey: - nonNilKey: foo - nonNilKey: bar + nonNilKey: {} + expectedWithNull: {} + expectedWithoutNull: + mapKey: + nonNilKey: {} + - description: multiple expliclty empty nested maps + originalObj: + mapKey: + nonNilKey1: {} + nonNilKey2: {} + expectedWithNull: {} + expectedWithoutNull: + mapKey: + nonNilKey1: {} + nonNilKey2: {} + - description: nested map with non-null value as empty map + originalObj: + mapKey: + nonNilKey: {} + nilKey: null expectedWithNull: - mapKey: {} + mapKey: + nilKey: null expectedWithoutNull: mapKey: - nonNilKey: foo - nonNilKey: bar + nonNilKey: {} - description: empty list originalObj: listKey: [] diff --git a/vendor/k8s.io/apimachinery/pkg/util/net/http.go b/vendor/k8s.io/apimachinery/pkg/util/net/http.go index 76eb8b4fa..7ea2df226 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/net/http.go +++ b/vendor/k8s.io/apimachinery/pkg/util/net/http.go @@ -19,6 +19,7 @@ package net import ( "bufio" "bytes" + "context" "crypto/tls" "fmt" "io" @@ -90,8 +91,8 @@ func SetOldTransportDefaults(t *http.Transport) *http.Transport { // ProxierWithNoProxyCIDR allows CIDR rules in NO_PROXY t.Proxy = NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment) } - if t.Dial == nil { - t.Dial = defaultTransport.Dial + if t.DialContext == nil { + t.DialContext = defaultTransport.DialContext } if t.TLSHandshakeTimeout == 0 { t.TLSHandshakeTimeout = defaultTransport.TLSHandshakeTimeout @@ -119,7 +120,7 @@ type RoundTripperWrapper interface { WrappedRoundTripper() http.RoundTripper } -type DialFunc func(net, addr string) (net.Conn, error) +type DialFunc func(ctx context.Context, net, addr string) (net.Conn, error) func DialerFor(transport http.RoundTripper) (DialFunc, error) { if transport == nil { @@ -128,7 +129,7 @@ func DialerFor(transport http.RoundTripper) (DialFunc, error) { switch transport := transport.(type) { case *http.Transport: - return transport.Dial, nil + return transport.DialContext, nil case RoundTripperWrapper: return DialerFor(transport.WrappedRoundTripper()) default: diff --git a/vendor/k8s.io/apimachinery/pkg/util/net/port_range.go b/vendor/k8s.io/apimachinery/pkg/util/net/port_range.go index 6a50e6186..7b6eca893 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/net/port_range.go +++ b/vendor/k8s.io/apimachinery/pkg/util/net/port_range.go @@ -43,14 +43,19 @@ func (pr PortRange) String() string { return fmt.Sprintf("%d-%d", pr.Base, pr.Base+pr.Size-1) } -// Set parses a string of the form "min-max", inclusive at both ends, and +// Set parses a string of the form "value", "min-max", or "min+offset", inclusive at both ends, and // sets the PortRange from it. This is part of the flag.Value and pflag.Value // interfaces. func (pr *PortRange) Set(value string) error { - value = strings.TrimSpace(value) + const ( + SinglePortNotation = 1 << iota + HyphenNotation + PlusNotation + ) - // TODO: Accept "80" syntax - // TODO: Accept "80+8" syntax + value = strings.TrimSpace(value) + hyphenIndex := strings.Index(value, "-") + plusIndex := strings.Index(value, "+") if value == "" { pr.Base = 0 @@ -58,20 +63,51 @@ func (pr *PortRange) Set(value string) error { return nil } - hyphenIndex := strings.Index(value, "-") - if hyphenIndex == -1 { - return fmt.Errorf("expected hyphen in port range") + var err error + var low, high int + var notation int + + if plusIndex == -1 && hyphenIndex == -1 { + notation |= SinglePortNotation + } + if hyphenIndex != -1 { + notation |= HyphenNotation + } + if plusIndex != -1 { + notation |= PlusNotation } - var err error - var low int - var high int - low, err = strconv.Atoi(value[:hyphenIndex]) - if err == nil { + switch notation { + case SinglePortNotation: + var port int + port, err = strconv.Atoi(value) + if err != nil { + return err + } + low = port + high = port + case HyphenNotation: + low, err = strconv.Atoi(value[:hyphenIndex]) + if err != nil { + return err + } high, err = strconv.Atoi(value[hyphenIndex+1:]) - } - if err != nil { - return fmt.Errorf("unable to parse port range: %s: %v", value, err) + if err != nil { + return err + } + case PlusNotation: + var offset int + low, err = strconv.Atoi(value[:plusIndex]) + if err != nil { + return err + } + offset, err = strconv.Atoi(value[plusIndex+1:]) + if err != nil { + return err + } + high = low + offset + default: + return fmt.Errorf("unable to parse port range: %s", value) } if low > 65535 || high > 65535 { diff --git a/vendor/k8s.io/apimachinery/pkg/util/net/port_range_test.go b/vendor/k8s.io/apimachinery/pkg/util/net/port_range_test.go index 897b8df61..b4cbe8245 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/net/port_range_test.go +++ b/vendor/k8s.io/apimachinery/pkg/util/net/port_range_test.go @@ -34,13 +34,21 @@ func TestPortRange(t *testing.T) { {" 100-200 ", true, "100-200", 200, 201}, {"0-0", true, "0-0", 0, 1}, {"", true, "", -1, 0}, - {"100", false, "", -1, -1}, + {"100", true, "100-100", 100, 101}, {"100 - 200", false, "", -1, -1}, {"-100", false, "", -1, -1}, {"100-", false, "", -1, -1}, {"200-100", false, "", -1, -1}, {"60000-70000", false, "", -1, -1}, {"70000-80000", false, "", -1, -1}, + {"70000+80000", false, "", -1, -1}, + {"1+0", true, "1-1", 1, 2}, + {"0+0", true, "0-0", 0, 1}, + {"1+-1", false, "", -1, -1}, + {"1-+1", false, "", -1, -1}, + {"100+200", true, "100-300", 300, 301}, + {"1+65535", false, "", -1, -1}, + {"0+65535", true, "0-65535", 65535, 65536}, } for i := range testCases { @@ -52,7 +60,7 @@ func TestPortRange(t *testing.T) { t.Errorf("expected success, got %q", err) continue } else if err == nil && tc.success == false { - t.Errorf("expected failure") + t.Errorf("expected failure %#v", testCases[i]) continue } else if tc.success { if f.String() != tc.expected { diff --git a/vendor/k8s.io/apimachinery/pkg/util/proxy/dial.go b/vendor/k8s.io/apimachinery/pkg/util/proxy/dial.go index 3da7e965f..37a5be487 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/proxy/dial.go +++ b/vendor/k8s.io/apimachinery/pkg/util/proxy/dial.go @@ -17,6 +17,7 @@ limitations under the License. package proxy import ( + "context" "crypto/tls" "fmt" "net" @@ -29,7 +30,7 @@ import ( "k8s.io/apimachinery/third_party/forked/golang/netutil" ) -func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { +func DialURL(ctx context.Context, url *url.URL, transport http.RoundTripper) (net.Conn, error) { dialAddr := netutil.CanonicalAddr(url) dialer, err := utilnet.DialerFor(transport) @@ -40,9 +41,10 @@ func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { switch url.Scheme { case "http": if dialer != nil { - return dialer("tcp", dialAddr) + return dialer(ctx, "tcp", dialAddr) } - return net.Dial("tcp", dialAddr) + var d net.Dialer + return d.DialContext(ctx, "tcp", dialAddr) case "https": // Get the tls config from the transport if we recognize it var tlsConfig *tls.Config @@ -56,7 +58,7 @@ func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { if dialer != nil { // We have a dialer; use it to open the connection, then // create a tls client using the connection. - netConn, err := dialer("tcp", dialAddr) + netConn, err := dialer(ctx, "tcp", dialAddr) if err != nil { return nil, err } @@ -86,7 +88,7 @@ func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { } } else { - // Dial + // Dial. This Dial method does not allow to pass a context unfortunately tlsConn, err = tls.Dial("tcp", dialAddr, tlsConfig) if err != nil { return nil, err diff --git a/vendor/k8s.io/apimachinery/pkg/util/proxy/dial_test.go b/vendor/k8s.io/apimachinery/pkg/util/proxy/dial_test.go index 8b9f78e4d..6ee594174 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/proxy/dial_test.go +++ b/vendor/k8s.io/apimachinery/pkg/util/proxy/dial_test.go @@ -17,6 +17,7 @@ limitations under the License. package proxy import ( + "context" "crypto/tls" "crypto/x509" "fmt" @@ -42,6 +43,7 @@ func TestDialURL(t *testing.T) { if err != nil { t.Fatal(err) } + var d net.Dialer testcases := map[string]struct { TLSConfig *tls.Config @@ -68,25 +70,25 @@ func TestDialURL(t *testing.T) { "insecure, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: true}, - Dial: net.Dial, + Dial: d.DialContext, }, "secure, no roots, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: false}, - Dial: net.Dial, + Dial: d.DialContext, ExpectError: "unknown authority", }, "secure with roots, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots}, - Dial: net.Dial, + Dial: d.DialContext, }, "secure with mismatched server, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots, ServerName: "bogus.com"}, - Dial: net.Dial, + Dial: d.DialContext, ExpectError: "not bogus.com", }, "secure with matched server, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots, ServerName: "example.com"}, - Dial: net.Dial, + Dial: d.DialContext, }, } @@ -102,7 +104,7 @@ func TestDialURL(t *testing.T) { // Clone() mutates the receiver (!), so also call it on the copy tlsConfigCopy.Clone() transport := &http.Transport{ - Dial: tc.Dial, + DialContext: tc.Dial, TLSClientConfig: tlsConfigCopy, } @@ -125,7 +127,7 @@ func TestDialURL(t *testing.T) { u, _ := url.Parse(ts.URL) _, p, _ := net.SplitHostPort(u.Host) u.Host = net.JoinHostPort("127.0.0.1", p) - conn, err := DialURL(u, transport) + conn, err := DialURL(context.Background(), u, transport) // Make sure dialing doesn't mutate the transport's TLSConfig if !reflect.DeepEqual(tc.TLSConfig, tlsConfigCopy) { diff --git a/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go index 2bc19655e..d725b228e 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go +++ b/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go @@ -347,7 +347,7 @@ func (h *UpgradeAwareHandler) DialForUpgrade(req *http.Request) (net.Conn, error // dial dials the backend at req.URL and writes req to it. func dial(req *http.Request, transport http.RoundTripper) (net.Conn, error) { - conn, err := DialURL(req.URL, transport) + conn, err := DialURL(req.Context(), req.URL, transport) if err != nil { return nil, fmt.Errorf("error dialing backend: %v", err) } diff --git a/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go index a33b10e58..c5dfde90d 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go +++ b/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go @@ -19,6 +19,7 @@ package proxy import ( "bytes" "compress/gzip" + "context" "crypto/tls" "crypto/x509" "errors" @@ -341,6 +342,7 @@ func TestProxyUpgrade(t *testing.T) { if !localhostPool.AppendCertsFromPEM(localhostCert) { t.Errorf("error setting up localhostCert pool") } + var d net.Dialer testcases := map[string]struct { ServerFunc func(http.Handler) *httptest.Server @@ -395,7 +397,7 @@ func TestProxyUpgrade(t *testing.T) { ts.StartTLS() return ts }, - ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), + ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{DialContext: d.DialContext, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), }, "https (valid hostname + RootCAs + custom dialer + bearer token)": { ServerFunc: func(h http.Handler) *httptest.Server { @@ -410,9 +412,9 @@ func TestProxyUpgrade(t *testing.T) { ts.StartTLS() return ts }, - ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), + ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{DialContext: d.DialContext, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), UpgradeTransport: NewUpgradeRequestRoundTripper( - utilnet.SetOldTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), + utilnet.SetOldTransportDefaults(&http.Transport{DialContext: d.DialContext, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), RoundTripperFunc(func(req *http.Request) (*http.Response, error) { req = utilnet.CloneRequest(req) req.Header.Set("Authorization", "Bearer 1234") @@ -496,9 +498,15 @@ func TestProxyUpgradeErrorResponse(t *testing.T) { expectedErr = errors.New("EXPECTED") ) proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - transport := http.DefaultTransport.(*http.Transport) - transport.Dial = func(network, addr string) (net.Conn, error) { - return &fakeConn{err: expectedErr}, nil + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return &fakeConn{err: expectedErr}, nil + }, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, } responder = &fakeResponder{t: t, w: w} proxyHandler := NewUpgradeAwareHandler( diff --git a/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go b/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go index d4cec0b88..da32fe12f 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go +++ b/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go @@ -128,9 +128,8 @@ func (r *rudimentaryErrorBackoff) OnError(error) { r.lastErrorTimeLock.Lock() defer r.lastErrorTimeLock.Unlock() d := time.Since(r.lastErrorTime) - if d < r.minPeriod && d >= 0 { + if d < r.minPeriod { // If the time moves backwards for any reason, do nothing - // TODO: remove check "d >= 0" after go 1.8 is no longer supported time.Sleep(r.minPeriod - d) } r.lastErrorTime = time.Now() @@ -161,3 +160,10 @@ func RecoverFromPanic(err *error) { callers) } } + +// Must panics on non-nil errors. Useful to handling programmer level errors. +func Must(err error) { + if err != nil { + panic(err) + } +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/sets/byte.go b/vendor/k8s.io/apimachinery/pkg/util/sets/byte.go index a460e4b1f..766f4501e 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/sets/byte.go +++ b/vendor/k8s.io/apimachinery/pkg/util/sets/byte.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets @@ -26,7 +26,7 @@ import ( // sets.Byte is a set of bytes, implemented via map[byte]struct{} for minimal memory consumption. type Byte map[byte]Empty -// New creates a Byte from a list of values. +// NewByte creates a Byte from a list of values. func NewByte(items ...byte) Byte { ss := Byte{} ss.Insert(items...) diff --git a/vendor/k8s.io/apimachinery/pkg/util/sets/doc.go b/vendor/k8s.io/apimachinery/pkg/util/sets/doc.go index 28a6a7d5c..b152a0bf0 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/sets/doc.go +++ b/vendor/k8s.io/apimachinery/pkg/util/sets/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. // Package sets has auto-generated set types. package sets diff --git a/vendor/k8s.io/apimachinery/pkg/util/sets/empty.go b/vendor/k8s.io/apimachinery/pkg/util/sets/empty.go index cd22b953a..e11e622c5 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/sets/empty.go +++ b/vendor/k8s.io/apimachinery/pkg/util/sets/empty.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets diff --git a/vendor/k8s.io/apimachinery/pkg/util/sets/int.go b/vendor/k8s.io/apimachinery/pkg/util/sets/int.go index 0614e9fb0..a0a513cd9 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/sets/int.go +++ b/vendor/k8s.io/apimachinery/pkg/util/sets/int.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets @@ -26,7 +26,7 @@ import ( // sets.Int is a set of ints, implemented via map[int]struct{} for minimal memory consumption. type Int map[int]Empty -// New creates a Int from a list of values. +// NewInt creates a Int from a list of values. func NewInt(items ...int) Int { ss := Int{} ss.Insert(items...) diff --git a/vendor/k8s.io/apimachinery/pkg/util/sets/int64.go b/vendor/k8s.io/apimachinery/pkg/util/sets/int64.go index 82e1ba782..9ca9af0c5 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/sets/int64.go +++ b/vendor/k8s.io/apimachinery/pkg/util/sets/int64.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets @@ -26,7 +26,7 @@ import ( // sets.Int64 is a set of int64s, implemented via map[int64]struct{} for minimal memory consumption. type Int64 map[int64]Empty -// New creates a Int64 from a list of values. +// NewInt64 creates a Int64 from a list of values. func NewInt64(items ...int64) Int64 { ss := Int64{} ss.Insert(items...) diff --git a/vendor/k8s.io/apimachinery/pkg/util/sets/string.go b/vendor/k8s.io/apimachinery/pkg/util/sets/string.go index baef7a6a2..ba00ad7df 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/sets/string.go +++ b/vendor/k8s.io/apimachinery/pkg/util/sets/string.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets @@ -26,7 +26,7 @@ import ( // sets.String is a set of strings, implemented via map[string]struct{} for minimal memory consumption. type String map[string]Empty -// New creates a String from a list of values. +// NewString creates a String from a list of values. func NewString(items ...string) String { ss := String{} ss.Insert(items...) diff --git a/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go index 2f6ade2be..6be328f74 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go +++ b/vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go @@ -880,6 +880,29 @@ func StrategicMergeMapPatchUsingLookupPatchMeta(original, patch JSONMap, schema return mergeMap(original, patch, schema, mergeOptions) } +// MergeStrategicMergeMapPatchUsingLookupPatchMeta merges strategic merge +// patches retaining `null` fields and parallel lists. If 2 patches change the +// same fields and the latter one will override the former one. If you don't +// want that happen, you need to run func MergingMapsHaveConflicts before +// merging these patches. Applying the resulting merged merge patch to a JSONMap +// yields the same as merging each strategic merge patch to the JSONMap in +// succession. +func MergeStrategicMergeMapPatchUsingLookupPatchMeta(schema LookupPatchMeta, patches ...JSONMap) (JSONMap, error) { + mergeOptions := MergeOptions{ + MergeParallelList: false, + IgnoreUnmatchedNulls: false, + } + merged := JSONMap{} + var err error + for _, patch := range patches { + merged, err = mergeMap(merged, patch, schema, mergeOptions) + if err != nil { + return nil, err + } + } + return merged, nil +} + // handleDirectiveInMergeMap handles the patch directive when merging 2 maps. func handleDirectiveInMergeMap(directive interface{}, patch map[string]interface{}) (map[string]interface{}, error) { if directive == replaceDirective { diff --git a/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go b/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go index 0997de806..a25e92465 100644 --- a/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go +++ b/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go @@ -284,12 +284,32 @@ func PollImmediateInfinite(interval time.Duration, condition ConditionFunc) erro // PollUntil tries a condition func until it returns true, an error or stopCh is // closed. // -// PolUntil always waits interval before the first run of 'condition'. +// PollUntil always waits interval before the first run of 'condition'. // 'condition' will always be invoked at least once. func PollUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error { return WaitFor(poller(interval, 0), condition, stopCh) } +// PollImmediateUntil tries a condition func until it returns true, an error or stopCh is closed. +// +// PollImmediateUntil runs the 'condition' before waiting for the interval. +// 'condition' will always be invoked at least once. +func PollImmediateUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error { + done, err := condition() + if err != nil { + return err + } + if done { + return nil + } + select { + case <-stopCh: + return ErrWaitTimeout + default: + return PollUntil(interval, condition, stopCh) + } +} + // WaitFunc creates a channel that receives an item every time a test // should be executed and is closed when the last test should be invoked. type WaitFunc func(done <-chan struct{}) <-chan struct{} diff --git a/vendor/k8s.io/apimachinery/pkg/version/helpers.go b/vendor/k8s.io/apimachinery/pkg/version/helpers.go new file mode 100644 index 000000000..5e041d6f3 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/version/helpers.go @@ -0,0 +1,88 @@ +/* +Copyright 2018 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 version + +import ( + "regexp" + "strconv" + "strings" +) + +type versionType int + +const ( + // Bigger the version type number, higher priority it is + versionTypeAlpha versionType = iota + versionTypeBeta + versionTypeGA +) + +var kubeVersionRegex = regexp.MustCompile("^v([\\d]+)(?:(alpha|beta)([\\d]+))?$") + +func parseKubeVersion(v string) (majorVersion int, vType versionType, minorVersion int, ok bool) { + var err error + submatches := kubeVersionRegex.FindStringSubmatch(v) + if len(submatches) != 4 { + return 0, 0, 0, false + } + switch submatches[2] { + case "alpha": + vType = versionTypeAlpha + case "beta": + vType = versionTypeBeta + case "": + vType = versionTypeGA + default: + return 0, 0, 0, false + } + if majorVersion, err = strconv.Atoi(submatches[1]); err != nil { + return 0, 0, 0, false + } + if vType != versionTypeGA { + if minorVersion, err = strconv.Atoi(submatches[3]); err != nil { + return 0, 0, 0, false + } + } + return majorVersion, vType, minorVersion, true +} + +// CompareKubeAwareVersionStrings compares two kube-like version strings. +// Kube-like version strings are starting with a v, followed by a major version, optional "alpha" or "beta" strings +// followed by a minor version (e.g. v1, v2beta1). Versions will be sorted based on GA/alpha/beta first and then major +// and minor versions. e.g. v2, v1, v1beta2, v1beta1, v1alpha1. +func CompareKubeAwareVersionStrings(v1, v2 string) int { + if v1 == v2 { + return 0 + } + v1major, v1type, v1minor, ok1 := parseKubeVersion(v1) + v2major, v2type, v2minor, ok2 := parseKubeVersion(v2) + switch { + case !ok1 && !ok2: + return strings.Compare(v2, v1) + case !ok1 && ok2: + return -1 + case ok1 && !ok2: + return 1 + } + if v1type != v2type { + return int(v1type) - int(v2type) + } + if v1major != v2major { + return v1major - v2major + } + return v1minor - v2minor +} diff --git a/vendor/k8s.io/apimachinery/pkg/version/helpers_test.go b/vendor/k8s.io/apimachinery/pkg/version/helpers_test.go new file mode 100644 index 000000000..863a53697 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/version/helpers_test.go @@ -0,0 +1,52 @@ +/* +Copyright 2018 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 version + +import ( + "testing" +) + +func TestCompareKubeAwareVersionStrings(t *testing.T) { + tests := []*struct { + v1, v2 string + expectedGreater bool + }{ + {"v1", "v2", false}, + {"v2", "v1", true}, + {"v10", "v2", true}, + {"v1", "v2alpha1", true}, + {"v1", "v2beta1", true}, + {"v1alpha2", "v1alpha1", true}, + {"v1beta1", "v2alpha3", true}, + {"v1alpha10", "v1alpha2", true}, + {"v1beta10", "v1beta2", true}, + {"foo", "v1beta2", false}, + {"bar", "foo", true}, + {"version1", "version2", true}, // Non kube-like versions are sorted alphabetically + {"version1", "version10", true}, // Non kube-like versions are sorted alphabetically + } + + for _, tc := range tests { + if e, a := tc.expectedGreater, CompareKubeAwareVersionStrings(tc.v1, tc.v2) > 0; e != a { + if e { + t.Errorf("expected %s to be greater than %s", tc.v1, tc.v2) + } else { + t.Errorf("expected %s to be less than than %s", tc.v1, tc.v2) + } + } + } +} diff --git a/vendor/k8s.io/apimachinery/pkg/watch/filter.go b/vendor/k8s.io/apimachinery/pkg/watch/filter.go index 3ca27f22c..22c9449f5 100644 --- a/vendor/k8s.io/apimachinery/pkg/watch/filter.go +++ b/vendor/k8s.io/apimachinery/pkg/watch/filter.go @@ -62,11 +62,7 @@ func (fw *filteredWatch) Stop() { // loop waits for new values, filters them, and resends them. func (fw *filteredWatch) loop() { defer close(fw.result) - for { - event, ok := <-fw.incoming.ResultChan() - if !ok { - break - } + for event := range fw.incoming.ResultChan() { filtered, keep := fw.f(event) if keep { fw.result <- filtered diff --git a/vendor/k8s.io/apimachinery/pkg/watch/mux.go b/vendor/k8s.io/apimachinery/pkg/watch/mux.go index a65088c1c..0ac8dc4ef 100644 --- a/vendor/k8s.io/apimachinery/pkg/watch/mux.go +++ b/vendor/k8s.io/apimachinery/pkg/watch/mux.go @@ -204,11 +204,7 @@ func (m *Broadcaster) Shutdown() { func (m *Broadcaster) loop() { // Deliberately not catching crashes here. Yes, bring down the process if there's a // bug in watch.Broadcaster. - for { - event, ok := <-m.incoming - if !ok { - break - } + for event := range m.incoming { if event.Type == internalRunFunctionMarker { event.Object.(functionFakeRuntimeObject)() continue diff --git a/vendor/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go index b1b19d118..0d266ffb6 100644 --- a/vendor/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go +++ b/vendor/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/apimachinery/third_party/forked/golang/reflect/deep_equal.go b/vendor/k8s.io/apimachinery/third_party/forked/golang/reflect/deep_equal.go index 9e45dbe1d..7ed1d1cff 100644 --- a/vendor/k8s.io/apimachinery/third_party/forked/golang/reflect/deep_equal.go +++ b/vendor/k8s.io/apimachinery/third_party/forked/golang/reflect/deep_equal.go @@ -44,7 +44,7 @@ func (e Equalities) AddFunc(eqFunc interface{}) error { return fmt.Errorf("expected func, got: %v", ft) } if ft.NumIn() != 2 { - return fmt.Errorf("expected three 'in' params, got: %v", ft) + return fmt.Errorf("expected two 'in' params, got: %v", ft) } if ft.NumOut() != 1 { return fmt.Errorf("expected one 'out' param, got: %v", ft) diff --git a/vendor/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md b/vendor/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md index e559c074b..6aed9889c 100644 --- a/vendor/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md +++ b/vendor/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md @@ -1,2 +1,3 @@ -Sorry, we do not accept changes directly against this repository. Please see -CONTRIBUTING.md for information on where and how to contribute instead. +Sorry, we do not accept changes directly against this repository, unless the +change is to the `README.md` itself. Please see +`CONTRIBUTING.md` for information on where and how to contribute instead. diff --git a/vendor/k8s.io/client-go/CHANGELOG.md b/vendor/k8s.io/client-go/CHANGELOG.md index bfa8a453d..030611620 100644 --- a/vendor/k8s.io/client-go/CHANGELOG.md +++ b/vendor/k8s.io/client-go/CHANGELOG.md @@ -5,6 +5,119 @@ https://github.com/kubernetes/client-go/issues/234. Changes in `k8s.io/api` and `k8s.io/apimachinery` are mentioned here because `k8s.io/client-go` depends on them. +# v7.0.0 + +**Breaking Changes:** + +* Google Cloud Service Account email addresses can now be used in RBAC Role bindings since the default scopes now include the `userinfo.email` scope. This is a breaking change if the numeric uniqueIDs of the Google service accounts were being used in RBAC role bindings. The behavior can be overridden by explicitly specifying the scope values as comma-separated string in the `users[*].config.scopes` field in the `KUBECONFIG` file. + + * [https://github.com/kubernetes/kubernetes/pull/58141](https://github.com/kubernetes/kubernetes/pull/58141) + +* [k8s.io/api] The `ConfigOK` node condition has been renamed to `KubeletConfigOk`. + + * [https://github.com/kubernetes/kubernetes/pull/59905](https://github.com/kubernetes/kubernetes/pull/59905) + +**New Features:** + +* Subresource support is added to the dynamic client. + + * [https://github.com/kubernetes/kubernetes/pull/56717](https://github.com/kubernetes/kubernetes/pull/56717) + +* A watch method is added to the Fake Client. + + * [https://github.com/kubernetes/kubernetes/pull/57504](https://github.com/kubernetes/kubernetes/pull/57504) + +* `ListOptions` can be modified when creating a `ListWatch`. + + * [https://github.com/kubernetes/kubernetes/pull/57508](https://github.com/kubernetes/kubernetes/pull/57508) + +* A `/token` subresource for ServiceAccount is added. + + * [https://github.com/kubernetes/kubernetes/pull/58111](https://github.com/kubernetes/kubernetes/pull/58111) + +* If an informer delivery fails, the particular notification is skipped and continued the next time. + + * [https://github.com/kubernetes/kubernetes/pull/58394](https://github.com/kubernetes/kubernetes/pull/58394) + +* Certificate manager will no longer wait until the initial rotation succeeds or fails before returning from `Start()`. + + * [https://github.com/kubernetes/kubernetes/pull/58930](https://github.com/kubernetes/kubernetes/pull/58930) + +* [k8s.io/api] `VolumeScheduling` and `LocalPersistentVolume` features are beta and enabled by default. The PersistentVolume NodeAffinity alpha annotation is deprecated and will be removed in a future release. + + * [https://github.com/kubernetes/kubernetes/pull/59391](https://github.com/kubernetes/kubernetes/pull/59391) + +* [k8s.io/api] The `PodSecurityPolicy` API has been moved to the `policy/v1beta1` API group. The `PodSecurityPolicy` API in the `extensions/v1beta1` API group is deprecated and will be removed in a future release. + + * [https://github.com/kubernetes/kubernetes/pull/54933](https://github.com/kubernetes/kubernetes/pull/54933) + +* [k8s.io/api] ConfigMap objects now support binary data via a new `binaryData` field. + + * [https://github.com/kubernetes/kubernetes/pull/57938](https://github.com/kubernetes/kubernetes/pull/57938) + +* [k8s.io/api] Service account TokenRequest API is added. + + * [https://github.com/kubernetes/kubernetes/pull/58027](https://github.com/kubernetes/kubernetes/pull/58027) + +* [k8s.io/api] FSType is added in CSI volume source to specify filesystems. + + * [https://github.com/kubernetes/kubernetes/pull/58209](https://github.com/kubernetes/kubernetes/pull/58209) + +* [k8s.io/api] v1beta1 VolumeAttachment API is added. + + * [https://github.com/kubernetes/kubernetes/pull/58462](https://github.com/kubernetes/kubernetes/pull/58462) + +* [k8s.io/api] `v1.Pod` now has a field `ShareProcessNamespace` to configure whether a single process namespace should be shared between all containers in a pod. This feature is in alpha preview. + + * [https://github.com/kubernetes/kubernetes/pull/58716](https://github.com/kubernetes/kubernetes/pull/58716) + +* [k8s.io/api] Add `NominatedNodeName` field to `PodStatus`. This field is set when a pod preempts other pods on the node. + + * [https://github.com/kubernetes/kubernetes/pull/58990](https://github.com/kubernetes/kubernetes/pull/58990) + +* [k8s.io/api] Promote `CSIPersistentVolumeSourc`e to beta. + + * [https://github.com/kubernetes/kubernetes/pull/59157](https://github.com/kubernetes/kubernetes/pull/59157) + +* [k8s.io/api] Promote `DNSPolicy` and `DNSConfig` in `PodSpec` to beta. + + * [https://github.com/kubernetes/kubernetes/pull/59771](https://github.com/kubernetes/kubernetes/pull/59771) + +* [k8s.io/api] External metric types are added to the HPA API. + + * [https://github.com/kubernetes/kubernetes/pull/60096](https://github.com/kubernetes/kubernetes/pull/60096) + +* [k8s.io/apimachinery] The `meta.k8s.io/v1alpha1` objects for retrieving tabular responses from the server (`Table`) or fetching just the `ObjectMeta` for an object (as `PartialObjectMetadata`) are now beta as part of `meta.k8s.io/v1beta1`. Clients may request alternate representations of normal Kubernetes objects by passing an `Accept` header like `application/json;as=Table;g=meta.k8s.io;v=v1beta1` or `application/json;as=PartialObjectMetadata;g=meta.k8s.io;v1=v1beta1`. Older servers will ignore this representation or return an error if it is not available. Clients may request fallback to the normal object by adding a non-qualified mime-type to their `Accept` header like `application/json` - the server will then respond with either the alternate representation if it is supported or the fallback mime-type which is the normal object response. + + * [https://github.com/kubernetes/kubernetes/pull/59059](https://github.com/kubernetes/kubernetes/pull/59059) + + +**Bug fixes and Improvements:** + +* Port-forwarding of TCP6 ports is fixed. + + * [https://github.com/kubernetes/kubernetes/pull/57457](https://github.com/kubernetes/kubernetes/pull/57457) + +* A race condition in SharedInformer that could violate the sequential delivery guarantee and cause panics on shutdown is fixed. + + * [https://github.com/kubernetes/kubernetes/pull/59828](https://github.com/kubernetes/kubernetes/pull/59828) + +* [k8s.io/api] PersistentVolume flexVolume sources can now reference secrets in a namespace other than the PersistentVolumeClaim's namespace. + + * [https://github.com/kubernetes/kubernetes/pull/56460](https://github.com/kubernetes/kubernetes/pull/56460) + +* [k8s.io/apimachinery] YAMLDecoder Read can now return the number of bytes read. + + * [https://github.com/kubernetes/kubernetes/pull/57000](https://github.com/kubernetes/kubernetes/pull/57000) + +* [k8s.io/apimachinery] YAMLDecoder Read now tracks rest of buffer on `io.ErrShortBuffer`. + + * [https://github.com/kubernetes/kubernetes/pull/58817](https://github.com/kubernetes/kubernetes/pull/58817) + +* [k8s.io/apimachinery] Prompt required merge key in the error message while applying a strategic merge patch. + + * [https://github.com/kubernetes/kubernetes/pull/57854](https://github.com/kubernetes/kubernetes/pull/57854) + # v6.0.0 **Breaking Changes:** diff --git a/vendor/k8s.io/client-go/Godeps/Godeps.json b/vendor/k8s.io/client-go/Godeps/Godeps.json index 3598fddc7..779a338f1 100644 --- a/vendor/k8s.io/client-go/Godeps/Godeps.json +++ b/vendor/k8s.io/client-go/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "k8s.io/client-go", "GoVersion": "go1.9", - "GodepVersion": "v79", + "GodepVersion": "v80", "Packages": [ "./..." ], @@ -16,19 +16,19 @@ }, { "ImportPath": "github.com/Azure/go-autorest/autorest", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/adal", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/azure", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/date", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/davecgh/go-spew/spew", @@ -68,23 +68,27 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/google/btree", + "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" }, { "ImportPath": "github.com/google/gofuzz", @@ -104,31 +108,39 @@ }, { "ImportPath": "github.com/gophercloud/gophercloud", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/utils", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/pagination", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" + }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" }, { "ImportPath": "github.com/hashicorp/golang-lru", @@ -138,17 +150,25 @@ "ImportPath": "github.com/hashicorp/golang-lru/simplelru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" }, - { - "ImportPath": "github.com/howeyc/gopass", - "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" - }, { "ImportPath": "github.com/imdario/mergo", "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" + }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" }, { "ImportPath": "github.com/pmezard/go-difflib/difflib", @@ -156,15 +176,15 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" + "Rev": "583c0c0531f06d5278b7d917446061adc344b5cd" }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/net/context", @@ -248,335 +268,327 @@ }, { "ImportPath": "k8s.io/api/admissionregistration/v1alpha1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/admissionregistration/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/apps/v1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/apps/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/apps/v1beta2", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/authentication/v1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/authentication/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/authorization/v1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/authorization/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/autoscaling/v1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/autoscaling/v2beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/batch/v1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/batch/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/batch/v2alpha1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/certificates/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/core/v1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/events/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/extensions/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/imagepolicy/v1alpha1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/networking/v1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/policy/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/rbac/v1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/rbac/v1alpha1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/rbac/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/scheduling/v1alpha1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" + }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/settings/v1alpha1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/storage/v1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/storage/v1alpha1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/api/storage/v1beta1", - "Rev": "73d903622b7391f3312dcbac6483fed484e185f8" + "Rev": "072894a440bdee3a891dea811fe42902311cd2a3" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/equality", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/errors", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/meta", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/resource", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/testing", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/conversion", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/fields", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/labels", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/selection", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/types", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/cache", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/clock", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/diff", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/errors", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/framer", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/intstr", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/json", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/net", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/runtime", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/sets", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation/field", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/wait", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/yaml", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/version", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/pkg/watch", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", - "Rev": "302974c03f7e50f16561ba237db776ab93594ef6" + "Rev": "103fd098999dc9c0c88536f5c9ad2e5da39373ae" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/client-go/OWNERS b/vendor/k8s.io/client-go/OWNERS index 44a4c9e1f..b39916829 100644 --- a/vendor/k8s.io/client-go/OWNERS +++ b/vendor/k8s.io/client-go/OWNERS @@ -1,44 +1,15 @@ approvers: - caesarxuchao - deads2k -- krousey - lavalamp +- liggitt - smarterclayton - sttts -- liggitt reviewers: -- thockin -- lavalamp -- smarterclayton -- wojtek-t -- deads2k -- yujuhong -- derekwaynecarr - caesarxuchao -- vishh -- mikedanese +- deads2k +- lavalamp - liggitt -- nikhiljindal -- gmarek -- erictune -- davidopp -- pmorie -- sttts -- dchen1107 -- saad-ali -- zmerlynn -- luxas -- janetkuo -- justinsb -- roberthbailey -- ncdc -- tallclair -- yifan-gu -- eparis -- mwielgus -- timothysc -- feiskyer -- jlowdermilk - soltysh -- piosz -- jsafrane +- sttts +- yliaog diff --git a/vendor/k8s.io/client-go/README.md b/vendor/k8s.io/client-go/README.md index 82f41d738..4e5e42207 100644 --- a/vendor/k8s.io/client-go/README.md +++ b/vendor/k8s.io/client-go/README.md @@ -2,7 +2,7 @@ Go clients for talking to a [kubernetes](http://kubernetes.io/) cluster. -We currently recommend using the v6.0.0 tag. See [INSTALL.md](/INSTALL.md) for +We currently recommend using the v7.0.0 tag. See [INSTALL.md](/INSTALL.md) for detailed installation instructions. `go get k8s.io/client-go/...` works, but will give you head and doesn't handle the dependencies well. @@ -91,16 +91,17 @@ We will backport bugfixes--but not new features--into older versions of #### Compatibility matrix -| | Kubernetes 1.4 | Kubernetes 1.5 | Kubernetes 1.6 | Kubernetes 1.7 | Kubernetes 1.8 | Kubernetes 1.9 | -|---------------------|----------------|----------------|----------------|----------------|----------------|----------------| -| client-go 1.4 | ✓ | - | - | - | - | - | -| client-go 1.5 | + | - | - | - | - | - | -| client-go 2.0 | +- | ✓ | +- | +- | +- | +- | -| client-go 3.0 | +- | +- | ✓ | - | +- | +- | -| client-go 4.0 | +- | +- | +- | ✓ | +- | +- | -| client-go 5.0 | +- | +- | +- | +- | ✓ | +- | -| client-go 6.0 | +- | +- | +- | +- | +- | ✓ | -| client-go HEAD | +- | +- | +- | +- | +- | + | +| | Kubernetes 1.4 | Kubernetes 1.5 | Kubernetes 1.6 | Kubernetes 1.7 | Kubernetes 1.8 | Kubernetes 1.9 | Kubernetes 1.10 | +|---------------------|----------------|----------------|----------------|----------------|----------------|----------------|-----------------| +| client-go 1.4 | ✓ | - | - | - | - | - | - | +| client-go 1.5 | + | - | - | - | - | - | - | +| client-go 2.0 | +- | ✓ | +- | +- | +- | +- | +- | +| client-go 3.0 | +- | +- | ✓ | - | +- | +- | +- | +| client-go 4.0 | +- | +- | +- | ✓ | +- | +- | +- | +| client-go 5.0 | +- | +- | +- | +- | ✓ | +- | +- | +| client-go 6.0 | +- | +- | +- | +- | +- | ✓ | +- | +| client-go 7.0 | +- | +- | +- | +- | +- | +- | ✓ | +| client-go HEAD | +- | +- | +- | +- | +- | + | + | Key: @@ -125,9 +126,10 @@ between client-go versions. | client-go 1.5 | Kubernetes main repo, 1.5 branch | = - | | client-go 2.0 | Kubernetes main repo, 1.5 branch | = - | | client-go 3.0 | Kubernetes main repo, 1.6 branch | = - | -| client-go 4.0 | Kubernetes main repo, 1.7 branch | ✓ | +| client-go 4.0 | Kubernetes main repo, 1.7 branch | = - | | client-go 5.0 | Kubernetes main repo, 1.8 branch | ✓ | | client-go 6.0 | Kubernetes main repo, 1.9 branch | ✓ | +| client-go 7.0 | Kubernetes main repo, 1.10 branch | ✓ | | client-go HEAD | Kubernetes main repo, master branch | ✓ | Key: @@ -152,7 +154,7 @@ existing users won't be broken. ### Kubernetes tags -As of October 2017, client-go is still a mirror of +As of April 2018, client-go is still a mirror of [k8s.io/kubernetes/staging/src/client-go](https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/client-go), the code development is still done in the staging area. Since Kubernetes 1.8 release, when syncing the code from the staging area, we also sync the Kubernetes diff --git a/vendor/k8s.io/client-go/SECURITY_CONTACTS b/vendor/k8s.io/client-go/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/client-go/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/client-go/deprecated-dynamic/bad_debt.go b/vendor/k8s.io/client-go/deprecated-dynamic/bad_debt.go new file mode 100644 index 000000000..51e4a5830 --- /dev/null +++ b/vendor/k8s.io/client-go/deprecated-dynamic/bad_debt.go @@ -0,0 +1,79 @@ +/* +Copyright 2018 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 deprecated_dynamic + +import ( + "encoding/json" + "io" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" +) + +// dynamicCodec is a codec that wraps the standard unstructured codec +// with special handling for Status objects. +// Deprecated only used by test code and its wrong +type dynamicCodec struct{} + +func (dynamicCodec) Decode(data []byte, gvk *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { + obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(data, gvk, obj) + if err != nil { + return nil, nil, err + } + + if _, ok := obj.(*metav1.Status); !ok && strings.ToLower(gvk.Kind) == "status" { + obj = &metav1.Status{} + err := json.Unmarshal(data, obj) + if err != nil { + return nil, nil, err + } + } + + return obj, gvk, nil +} + +func (dynamicCodec) Encode(obj runtime.Object, w io.Writer) error { + return unstructured.UnstructuredJSONScheme.Encode(obj, w) +} + +// ContentConfig returns a rest.ContentConfig for dynamic types. +// Deprecated only used by test code and its wrong +func ContentConfig() rest.ContentConfig { + var jsonInfo runtime.SerializerInfo + // TODO: scheme.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need + // to talk to a kubernetes server + for _, info := range scheme.Codecs.SupportedMediaTypes() { + if info.MediaType == runtime.ContentTypeJSON { + jsonInfo = info + break + } + } + + jsonInfo.Serializer = dynamicCodec{} + jsonInfo.PrettySerializer = nil + return rest.ContentConfig{ + AcceptContentTypes: runtime.ContentTypeJSON, + ContentType: runtime.ContentTypeJSON, + NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo), + } +} diff --git a/vendor/k8s.io/client-go/deprecated-dynamic/client.go b/vendor/k8s.io/client-go/deprecated-dynamic/client.go new file mode 100644 index 000000000..0974fe64d --- /dev/null +++ b/vendor/k8s.io/client-go/deprecated-dynamic/client.go @@ -0,0 +1,131 @@ +/* +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 dynamic provides a client interface to arbitrary Kubernetes +// APIs that exposes common high level operations and exposes common +// metadata. +package deprecated_dynamic + +import ( + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/dynamic" + restclient "k8s.io/client-go/rest" +) + +// Interface is a Kubernetes client that allows you to access metadata +// and manipulate metadata of a Kubernetes API group. +type Interface interface { + // Resource returns an API interface to the specified resource for this client's + // group and version. If resource is not a namespaced resource, then namespace + // is ignored. The ResourceInterface inherits the parameter codec of this client. + Resource(resource *metav1.APIResource, namespace string) ResourceInterface +} + +// ResourceInterface is an API interface to a specific resource under a +// dynamic client. +type ResourceInterface interface { + // List returns a list of objects for this resource. + List(opts metav1.ListOptions) (runtime.Object, error) + // Get gets the resource with the specified name. + Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) + // Delete deletes the resource with the specified name. + Delete(name string, opts *metav1.DeleteOptions) error + // DeleteCollection deletes a collection of objects. + DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error + // Create creates the provided resource. + Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) + // Update updates the provided resource. + Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) + // Watch returns a watch.Interface that watches the resource. + Watch(opts metav1.ListOptions) (watch.Interface, error) + // Patch patches the provided resource. + Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) +} + +// Client is a Kubernetes client that allows you to access metadata +// and manipulate metadata of a Kubernetes API group, and implements Interface. +type Client struct { + version schema.GroupVersion + delegate dynamic.Interface +} + +// NewClient returns a new client based on the passed in config. The +// codec is ignored, as the dynamic client uses it's own codec. +func NewClient(conf *restclient.Config, version schema.GroupVersion) (*Client, error) { + delegate, err := dynamic.NewForConfig(conf) + if err != nil { + return nil, err + } + + return &Client{version: version, delegate: delegate}, nil +} + +// Resource returns an API interface to the specified resource for this client's +// group and version. If resource is not a namespaced resource, then namespace +// is ignored. The ResourceInterface inherits the parameter codec of c. +func (c *Client) Resource(resource *metav1.APIResource, namespace string) ResourceInterface { + resourceTokens := strings.SplitN(resource.Name, "/", 2) + subresources := []string{} + if len(resourceTokens) > 1 { + subresources = strings.Split(resourceTokens[1], "/") + } + + if len(namespace) == 0 { + return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])), subresources) + } + return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])).Namespace(namespace), subresources) +} + +// the old interfaces used the wrong type for lists. this fixes that +func oldResourceShim(in dynamic.ResourceInterface, subresources []string) ResourceInterface { + return oldResourceShimType{ResourceInterface: in, subresources: subresources} +} + +type oldResourceShimType struct { + dynamic.ResourceInterface + subresources []string +} + +func (s oldResourceShimType) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + return s.ResourceInterface.Create(obj, s.subresources...) +} + +func (s oldResourceShimType) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + return s.ResourceInterface.Update(obj, s.subresources...) +} + +func (s oldResourceShimType) Delete(name string, opts *metav1.DeleteOptions) error { + return s.ResourceInterface.Delete(name, opts, s.subresources...) +} + +func (s oldResourceShimType) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) { + return s.ResourceInterface.Get(name, opts, s.subresources...) +} + +func (s oldResourceShimType) List(opts metav1.ListOptions) (runtime.Object, error) { + return s.ResourceInterface.List(opts) +} + +func (s oldResourceShimType) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) { + return s.ResourceInterface.Patch(name, pt, data, s.subresources...) +} diff --git a/vendor/k8s.io/client-go/deprecated-dynamic/client_pool.go b/vendor/k8s.io/client-go/deprecated-dynamic/client_pool.go new file mode 100644 index 000000000..36dc54ce4 --- /dev/null +++ b/vendor/k8s.io/client-go/deprecated-dynamic/client_pool.go @@ -0,0 +1,122 @@ +/* +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 deprecated_dynamic + +import ( + "sync" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" + restclient "k8s.io/client-go/rest" +) + +// ClientPool manages a pool of dynamic clients. +type ClientPool interface { + // ClientForGroupVersionResource returns a client configured for the specified groupVersionResource. + // Resource may be empty. + ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error) + // ClientForGroupVersionKind returns a client configured for the specified groupVersionKind. + // Kind may be empty. + ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error) +} + +// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is +// optional. +type APIPathResolverFunc func(kind schema.GroupVersionKind) string + +// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API. +func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string { + if len(kind.Group) == 0 { + return "/api" + } + return "/apis" +} + +// clientPoolImpl implements ClientPool and caches clients for the resource group versions +// is asked to retrieve. This type is thread safe. +type clientPoolImpl struct { + lock sync.RWMutex + config *restclient.Config + clients map[schema.GroupVersion]*Client + apiPathResolverFunc APIPathResolverFunc + mapper meta.RESTMapper +} + +// NewClientPool returns a ClientPool from the specified config. It reuses clients for the same +// group version. It is expected this type may be wrapped by specific logic that special cases certain +// resources or groups. +func NewClientPool(config *restclient.Config, mapper meta.RESTMapper, apiPathResolverFunc APIPathResolverFunc) ClientPool { + confCopy := *config + + return &clientPoolImpl{ + config: &confCopy, + clients: map[schema.GroupVersion]*Client{}, + apiPathResolverFunc: apiPathResolverFunc, + mapper: mapper, + } +} + +// Instantiates a new dynamic client pool with the given config. +func NewDynamicClientPool(cfg *restclient.Config) ClientPool { + // restMapper is not needed when using LegacyAPIPathResolverFunc + emptyMapper := meta.MultiRESTMapper{} + return NewClientPool(cfg, emptyMapper, LegacyAPIPathResolverFunc) +} + +// ClientForGroupVersionResource uses the provided RESTMapper to identify the appropriate resource. Resource may +// be empty. If no matching kind is found the underlying client for that group is still returned. +func (c *clientPoolImpl) ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error) { + kinds, err := c.mapper.KindsFor(resource) + if err != nil { + if meta.IsNoMatchError(err) { + return c.ClientForGroupVersionKind(schema.GroupVersionKind{Group: resource.Group, Version: resource.Version}) + } + return nil, err + } + return c.ClientForGroupVersionKind(kinds[0]) +} + +// ClientForGroupVersion returns a client for the specified groupVersion, creates one if none exists. Kind +// in the GroupVersionKind may be empty. +func (c *clientPoolImpl) ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error) { + c.lock.Lock() + defer c.lock.Unlock() + + gv := kind.GroupVersion() + + // do we have a client already configured? + if existingClient, found := c.clients[gv]; found { + return existingClient, nil + } + + // avoid changing the original config + confCopy := *c.config + conf := &confCopy + + // we need to set the api path based on group version, if no group, default to legacy path + conf.APIPath = c.apiPathResolverFunc(kind) + + // we need to make a client + conf.GroupVersion = &gv + + dynamicClient, err := NewClient(conf, gv) + if err != nil { + return nil, err + } + c.clients[gv] = dynamicClient + return dynamicClient, nil +} diff --git a/vendor/k8s.io/client-go/deprecated-dynamic/client_test.go b/vendor/k8s.io/client-go/deprecated-dynamic/client_test.go new file mode 100644 index 000000000..790474522 --- /dev/null +++ b/vendor/k8s.io/client-go/deprecated-dynamic/client_test.go @@ -0,0 +1,623 @@ +/* +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 deprecated_dynamic + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "reflect" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer/streaming" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + restclient "k8s.io/client-go/rest" + restclientwatch "k8s.io/client-go/rest/watch" +) + +func getJSON(version, kind, name string) []byte { + return []byte(fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "metadata": {"name": %q}}`, version, kind, name)) +} + +func getListJSON(version, kind string, items ...[]byte) []byte { + json := fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "items": [%s]}`, + version, kind, bytes.Join(items, []byte(","))) + return []byte(json) +} + +func getObject(version, kind, name string) *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": version, + "kind": kind, + "metadata": map[string]interface{}{ + "name": name, + }, + }, + } +} + +func getClientServer(gv *schema.GroupVersion, h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) { + srv := httptest.NewServer(http.HandlerFunc(h)) + cl, err := NewClient(&restclient.Config{ + Host: srv.URL, + ContentConfig: restclient.ContentConfig{GroupVersion: gv}, + }, *gv) + if err != nil { + srv.Close() + return nil, nil, err + } + return cl, srv, nil +} + +func TestList(t *testing.T) { + tcs := []struct { + name string + namespace string + path string + resp []byte + want *unstructured.UnstructuredList + }{ + { + name: "normal_list", + path: "/apis/gtest/vtest/rtest", + resp: getListJSON("vTest", "rTestList", + getJSON("vTest", "rTest", "item1"), + getJSON("vTest", "rTest", "item2")), + want: &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "apiVersion": "vTest", + "kind": "rTestList", + }, + Items: []unstructured.Unstructured{ + *getObject("vTest", "rTest", "item1"), + *getObject("vTest", "rTest", "item2"), + }, + }, + }, + { + name: "namespaced_list", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + resp: getListJSON("vTest", "rTestList", + getJSON("vTest", "rTest", "item1"), + getJSON("vTest", "rTest", "item2")), + want: &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "apiVersion": "vTest", + "kind": "rTestList", + }, + Items: []unstructured.Unstructured{ + *getObject("vTest", "rTest", "item1"), + *getObject("vTest", "rTest", "item2"), + }, + }, + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("List(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + w.Write(tc.resp) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).List(metav1.ListOptions{}) + if err != nil { + t.Errorf("unexpected error when listing %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("List(%q) want: %v\ngot: %v", tc.name, tc.want, got) + } + } +} + +func TestGet(t *testing.T) { + tcs := []struct { + resource string + namespace string + name string + path string + resp []byte + want *unstructured.Unstructured + }{ + { + resource: "rtest", + name: "normal_get", + path: "/apis/gtest/vtest/rtest/normal_get", + resp: getJSON("vTest", "rTest", "normal_get"), + want: getObject("vTest", "rTest", "normal_get"), + }, + { + resource: "rtest", + namespace: "nstest", + name: "namespaced_get", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_get", + resp: getJSON("vTest", "rTest", "namespaced_get"), + want: getObject("vTest", "rTest", "namespaced_get"), + }, + { + resource: "rtest/srtest", + name: "normal_subresource_get", + path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest", + resp: getJSON("vTest", "srTest", "normal_subresource_get"), + want: getObject("vTest", "srTest", "normal_subresource_get"), + }, + { + resource: "rtest/srtest", + namespace: "nstest", + name: "namespaced_subresource_get", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest", + resp: getJSON("vTest", "srTest", "namespaced_subresource_get"), + want: getObject("vTest", "srTest", "namespaced_subresource_get"), + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Get(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + w.Write(tc.resp) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).Get(tc.name, metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error when getting %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("Get(%q) want: %v\ngot: %v", tc.name, tc.want, got) + } + } +} + +func TestDelete(t *testing.T) { + background := metav1.DeletePropagationBackground + uid := types.UID("uid") + + statusOK := &metav1.Status{ + TypeMeta: metav1.TypeMeta{Kind: "Status"}, + Status: metav1.StatusSuccess, + } + tcs := []struct { + namespace string + name string + path string + deleteOptions *metav1.DeleteOptions + }{ + { + name: "normal_delete", + path: "/apis/gtest/vtest/rtest/normal_delete", + }, + { + namespace: "nstest", + name: "namespaced_delete", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete", + }, + { + namespace: "nstest", + name: "namespaced_delete_with_options", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete_with_options", + deleteOptions: &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}, PropagationPolicy: &background}, + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "DELETE" { + t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Delete(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + unstructured.UnstructuredJSONScheme.Encode(statusOK, w) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + err = cl.Resource(resource, tc.namespace).Delete(tc.name, tc.deleteOptions) + if err != nil { + t.Errorf("unexpected error when deleting %q: %v", tc.name, err) + continue + } + } +} + +func TestDeleteCollection(t *testing.T) { + statusOK := &metav1.Status{ + TypeMeta: metav1.TypeMeta{Kind: "Status"}, + Status: metav1.StatusSuccess, + } + tcs := []struct { + namespace string + name string + path string + }{ + { + name: "normal_delete_collection", + path: "/apis/gtest/vtest/rtest", + }, + { + namespace: "nstest", + name: "namespaced_delete_collection", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "DELETE" { + t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("DeleteCollection(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + unstructured.UnstructuredJSONScheme.Encode(statusOK, w) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + err = cl.Resource(resource, tc.namespace).DeleteCollection(nil, metav1.ListOptions{}) + if err != nil { + t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err) + continue + } + } +} + +func TestCreate(t *testing.T) { + tcs := []struct { + resource string + name string + namespace string + obj *unstructured.Unstructured + path string + }{ + { + resource: "rtest", + name: "normal_create", + path: "/apis/gtest/vtest/rtest", + obj: getObject("gtest/vTest", "rTest", "normal_create"), + }, + { + resource: "rtest", + name: "namespaced_create", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + obj: getObject("gtest/vTest", "rTest", "namespaced_create"), + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "POST" { + t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Create(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + data, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Errorf("Create(%q) unexpected error reading body: %v", tc.name, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.Write(data) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).Create(tc.obj) + if err != nil { + t.Errorf("unexpected error when creating %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.obj) { + t.Errorf("Create(%q) want: %v\ngot: %v", tc.name, tc.obj, got) + } + } +} + +func TestUpdate(t *testing.T) { + tcs := []struct { + resource string + name string + namespace string + obj *unstructured.Unstructured + path string + }{ + { + resource: "rtest", + name: "normal_update", + path: "/apis/gtest/vtest/rtest/normal_update", + obj: getObject("gtest/vTest", "rTest", "normal_update"), + }, + { + resource: "rtest", + name: "namespaced_update", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update", + obj: getObject("gtest/vTest", "rTest", "namespaced_update"), + }, + { + resource: "rtest/srtest", + name: "normal_subresource_update", + path: "/apis/gtest/vtest/rtest/normal_update/srtest", + obj: getObject("gtest/vTest", "srTest", "normal_update"), + }, + { + resource: "rtest/srtest", + name: "namespaced_subresource_update", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest", + obj: getObject("gtest/vTest", "srTest", "namespaced_update"), + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "PUT" { + t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Update(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + data, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Errorf("Update(%q) unexpected error reading body: %v", tc.name, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.Write(data) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).Update(tc.obj) + if err != nil { + t.Errorf("unexpected error when updating %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.obj) { + t.Errorf("Update(%q) want: %v\ngot: %v", tc.name, tc.obj, got) + } + } +} + +func TestWatch(t *testing.T) { + tcs := []struct { + name string + namespace string + events []watch.Event + path string + query string + }{ + { + name: "normal_watch", + path: "/apis/gtest/vtest/rtest", + query: "watch=true", + events: []watch.Event{ + {Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + {Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + {Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + }, + }, + { + name: "namespaced_watch", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + query: "watch=true", + events: []watch.Event{ + {Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + {Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + {Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + }, + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Watch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + if r.URL.RawQuery != tc.query { + t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query) + } + + enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{}) + for _, e := range tc.events { + enc.Encode(&e) + } + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + watcher, err := cl.Resource(resource, tc.namespace).Watch(metav1.ListOptions{}) + if err != nil { + t.Errorf("unexpected error when watching %q: %v", tc.name, err) + continue + } + + for _, want := range tc.events { + got := <-watcher.ResultChan() + if !reflect.DeepEqual(got, want) { + t.Errorf("Watch(%q) want: %v\ngot: %v", tc.name, want, got) + } + } + } +} + +func TestPatch(t *testing.T) { + tcs := []struct { + resource string + name string + namespace string + patch []byte + want *unstructured.Unstructured + path string + }{ + { + resource: "rtest", + name: "normal_patch", + path: "/apis/gtest/vtest/rtest/normal_patch", + patch: getJSON("gtest/vTest", "rTest", "normal_patch"), + want: getObject("gtest/vTest", "rTest", "normal_patch"), + }, + { + resource: "rtest", + name: "namespaced_patch", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_patch", + patch: getJSON("gtest/vTest", "rTest", "namespaced_patch"), + want: getObject("gtest/vTest", "rTest", "namespaced_patch"), + }, + { + resource: "rtest/srtest", + name: "normal_subresource_patch", + path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest", + patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"), + want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"), + }, + { + resource: "rtest/srtest", + name: "namespaced_subresource_patch", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest", + patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"), + want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"), + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "PATCH" { + t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Patch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + content := r.Header.Get("Content-Type") + if content != string(types.StrategicMergePatchType) { + t.Errorf("Patch(%q) got Content-Type %s. wanted %s", tc.name, content, types.StrategicMergePatchType) + } + + data, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Errorf("Patch(%q) unexpected error reading body: %v", tc.name, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.Write(data) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch) + if err != nil { + t.Errorf("unexpected error when patching %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("Patch(%q) want: %v\ngot: %v", tc.name, tc.want, got) + } + } +} diff --git a/vendor/k8s.io/client-go/discovery/BUILD b/vendor/k8s.io/client-go/discovery/BUILD deleted file mode 100644 index 19523ba53..000000000 --- a/vendor/k8s.io/client-go/discovery/BUILD +++ /dev/null @@ -1,75 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "discovery_client.go", - "helper.go", - "restmapper.go", - "unstructured.go", - ], - importpath = "k8s.io/client-go/discovery", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/golang/protobuf/proto:go_default_library", - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -go_test( - name = "go_default_xtest", - srcs = [ - "discovery_client_test.go", - "helper_blackbox_test.go", - "restmapper_test.go", - ], - deps = [ - "//vendor/github.com/gogo/protobuf/proto:go_default_library", - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", - "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/rest/fake:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/discovery/cached:all-srcs", - "//staging/src/k8s.io/client-go/discovery/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/discovery/cached/BUILD b/vendor/k8s.io/client-go/discovery/cached/BUILD deleted file mode 100644 index 279e0ff9a..000000000 --- a/vendor/k8s.io/client-go/discovery/cached/BUILD +++ /dev/null @@ -1,44 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["memcache_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/client-go/discovery/fake:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = ["memcache.go"], - importpath = "k8s.io/client-go/discovery/cached", - deps = [ - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/discovery/cached/memcache.go b/vendor/k8s.io/client-go/discovery/cached/memcache.go index 585b4c80d..d4313bcf3 100644 --- a/vendor/k8s.io/client-go/discovery/cached/memcache.go +++ b/vendor/k8s.io/client-go/discovery/cached/memcache.go @@ -96,18 +96,12 @@ func (d *memCacheClient) RESTClient() restclient.Interface { return d.delegate.RESTClient() } -// TODO: Should this also be cached? The results seem more likely to be -// inconsistent with ServerGroups and ServerResources given the requirement to -// actively Invalidate. func (d *memCacheClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - return d.delegate.ServerPreferredResources() + return discovery.ServerPreferredResources(d) } -// TODO: Should this also be cached? The results seem more likely to be -// inconsistent with ServerGroups and ServerResources given the requirement to -// actively Invalidate. func (d *memCacheClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { - return d.delegate.ServerPreferredNamespacedResources() + return discovery.ServerPreferredNamespacedResources(d) } func (d *memCacheClient) ServerVersion() (*version.Info, error) { diff --git a/vendor/k8s.io/client-go/discovery/cached_discovery.go b/vendor/k8s.io/client-go/discovery/cached_discovery.go new file mode 100644 index 000000000..aca46546e --- /dev/null +++ b/vendor/k8s.io/client-go/discovery/cached_discovery.go @@ -0,0 +1,282 @@ +/* +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 discovery + +import ( + "errors" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "sync" + "time" + + "github.com/golang/glog" + "github.com/googleapis/gnostic/OpenAPIv2" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/version" + "k8s.io/client-go/kubernetes/scheme" + restclient "k8s.io/client-go/rest" +) + +// CachedDiscoveryClient implements the functions that discovery server-supported API groups, +// versions and resources. +type CachedDiscoveryClient struct { + delegate DiscoveryInterface + + // cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well. + cacheDirectory string + + // ttl is how long the cache should be considered valid + ttl time.Duration + + // mutex protects the variables below + mutex sync.Mutex + + // ourFiles are all filenames of cache files created by this process + ourFiles map[string]struct{} + // invalidated is true if all cache files should be ignored that are not ours (e.g. after Invalidate() was called) + invalidated bool + // fresh is true if all used cache files were ours + fresh bool +} + +var _ CachedDiscoveryInterface = &CachedDiscoveryClient{} + +// ServerResourcesForGroupVersion returns the supported resources for a group and version. +func (d *CachedDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + filename := filepath.Join(d.cacheDirectory, groupVersion, "serverresources.json") + cachedBytes, err := d.getCachedFile(filename) + // don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback. + if err == nil { + cachedResources := &metav1.APIResourceList{} + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedResources); err == nil { + glog.V(10).Infof("returning cached discovery info from %v", filename) + return cachedResources, nil + } + } + + liveResources, err := d.delegate.ServerResourcesForGroupVersion(groupVersion) + if err != nil { + glog.V(3).Infof("skipped caching discovery info due to %v", err) + return liveResources, err + } + if liveResources == nil || len(liveResources.APIResources) == 0 { + glog.V(3).Infof("skipped caching discovery info, no resources found") + return liveResources, err + } + + if err := d.writeCachedFile(filename, liveResources); err != nil { + glog.V(3).Infof("failed to write cache to %v due to %v", filename, err) + } + + return liveResources, nil +} + +// ServerResources returns the supported resources for all groups and versions. +func (d *CachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { + return ServerResources(d) +} + +func (d *CachedDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { + filename := filepath.Join(d.cacheDirectory, "servergroups.json") + cachedBytes, err := d.getCachedFile(filename) + // don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback. + if err == nil { + cachedGroups := &metav1.APIGroupList{} + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedGroups); err == nil { + glog.V(10).Infof("returning cached discovery info from %v", filename) + return cachedGroups, nil + } + } + + liveGroups, err := d.delegate.ServerGroups() + if err != nil { + glog.V(3).Infof("skipped caching discovery info due to %v", err) + return liveGroups, err + } + if liveGroups == nil || len(liveGroups.Groups) == 0 { + glog.V(3).Infof("skipped caching discovery info, no groups found") + return liveGroups, err + } + + if err := d.writeCachedFile(filename, liveGroups); err != nil { + glog.V(3).Infof("failed to write cache to %v due to %v", filename, err) + } + + return liveGroups, nil +} + +func (d *CachedDiscoveryClient) getCachedFile(filename string) ([]byte, error) { + // after invalidation ignore cache files not created by this process + d.mutex.Lock() + _, ourFile := d.ourFiles[filename] + if d.invalidated && !ourFile { + d.mutex.Unlock() + return nil, errors.New("cache invalidated") + } + d.mutex.Unlock() + + file, err := os.Open(filename) + if err != nil { + return nil, err + } + defer file.Close() + + fileInfo, err := file.Stat() + if err != nil { + return nil, err + } + + if time.Now().After(fileInfo.ModTime().Add(d.ttl)) { + return nil, errors.New("cache expired") + } + + // the cache is present and its valid. Try to read and use it. + cachedBytes, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + + d.mutex.Lock() + defer d.mutex.Unlock() + d.fresh = d.fresh && ourFile + + return cachedBytes, nil +} + +func (d *CachedDiscoveryClient) writeCachedFile(filename string, obj runtime.Object) error { + if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil { + return err + } + + bytes, err := runtime.Encode(scheme.Codecs.LegacyCodec(), obj) + if err != nil { + return err + } + + f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)+".") + if err != nil { + return err + } + defer os.Remove(f.Name()) + _, err = f.Write(bytes) + if err != nil { + return err + } + + err = os.Chmod(f.Name(), 0755) + if err != nil { + return err + } + + name := f.Name() + err = f.Close() + if err != nil { + return err + } + + // atomic rename + d.mutex.Lock() + defer d.mutex.Unlock() + err = os.Rename(name, filename) + if err == nil { + d.ourFiles[filename] = struct{}{} + } + return err +} + +func (d *CachedDiscoveryClient) RESTClient() restclient.Interface { + return d.delegate.RESTClient() +} + +func (d *CachedDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + return ServerPreferredResources(d) +} + +func (d *CachedDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return ServerPreferredNamespacedResources(d) +} + +func (d *CachedDiscoveryClient) ServerVersion() (*version.Info, error) { + return d.delegate.ServerVersion() +} + +func (d *CachedDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { + return d.delegate.OpenAPISchema() +} + +func (d *CachedDiscoveryClient) Fresh() bool { + d.mutex.Lock() + defer d.mutex.Unlock() + + return d.fresh +} + +func (d *CachedDiscoveryClient) Invalidate() { + d.mutex.Lock() + defer d.mutex.Unlock() + + d.ourFiles = map[string]struct{}{} + d.fresh = true + d.invalidated = true +} + +// NewCachedDiscoveryClientForConfig creates a new DiscoveryClient for the given config, and wraps +// the created client in a CachedDiscoveryClient. The provided configuration is updated with a +// custom transport that understands cache responses. +// We receive two distinct cache directories for now, in order to preserve old behavior +// which makes use of the --cache-dir flag value for storing cache data from the CacheRoundTripper, +// and makes use of the hardcoded destination (~/.kube/cache/discovery/...) for storing +// CachedDiscoveryClient cache data. If httpCacheDir is empty, the restconfig's transport will not +// be updated with a roundtripper that understands cache responses. +// If discoveryCacheDir is empty, cached server resource data will be looked up in the current directory. +// TODO(juanvallejo): the value of "--cache-dir" should be honored. Consolidate discoveryCacheDir with httpCacheDir +// so that server resources and http-cache data are stored in the same location, provided via config flags. +func NewCachedDiscoveryClientForConfig(config *restclient.Config, discoveryCacheDir, httpCacheDir string, ttl time.Duration) (*CachedDiscoveryClient, error) { + if len(httpCacheDir) > 0 { + // update the given restconfig with a custom roundtripper that + // understands how to handle cache responses. + wt := config.WrapTransport + config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { + if wt != nil { + rt = wt(rt) + } + return newCacheRoundTripper(httpCacheDir, rt) + } + } + + discoveryClient, err := NewDiscoveryClientForConfig(config) + if err != nil { + return nil, err + } + + return newCachedDiscoveryClient(discoveryClient, discoveryCacheDir, ttl), nil +} + +// NewCachedDiscoveryClient creates a new DiscoveryClient. cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well. +func newCachedDiscoveryClient(delegate DiscoveryInterface, cacheDirectory string, ttl time.Duration) *CachedDiscoveryClient { + return &CachedDiscoveryClient{ + delegate: delegate, + cacheDirectory: cacheDirectory, + ttl: ttl, + ourFiles: map[string]struct{}{}, + fresh: true, + } +} diff --git a/vendor/k8s.io/client-go/discovery/cached_discovery_test.go b/vendor/k8s.io/client-go/discovery/cached_discovery_test.go new file mode 100644 index 000000000..278931c2d --- /dev/null +++ b/vendor/k8s.io/client-go/discovery/cached_discovery_test.go @@ -0,0 +1,169 @@ +/* +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 discovery + +import ( + "io/ioutil" + "os" + "testing" + "time" + + "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/stretchr/testify/assert" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/version" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" +) + +func TestCachedDiscoveryClient_Fresh(t *testing.T) { + assert := assert.New(t) + + d, err := ioutil.TempDir("", "") + assert.NoError(err) + defer os.RemoveAll(d) + + c := fakeDiscoveryClient{} + cdc := newCachedDiscoveryClient(&c, d, 60*time.Second) + assert.True(cdc.Fresh(), "should be fresh after creation") + + cdc.ServerGroups() + assert.True(cdc.Fresh(), "should be fresh after groups call without cache") + assert.Equal(c.groupCalls, 1) + + cdc.ServerGroups() + assert.True(cdc.Fresh(), "should be fresh after another groups call") + assert.Equal(c.groupCalls, 1) + + cdc.ServerResources() + assert.True(cdc.Fresh(), "should be fresh after resources call") + assert.Equal(c.resourceCalls, 1) + + cdc.ServerResources() + assert.True(cdc.Fresh(), "should be fresh after another resources call") + assert.Equal(c.resourceCalls, 1) + + cdc = newCachedDiscoveryClient(&c, d, 60*time.Second) + cdc.ServerGroups() + assert.False(cdc.Fresh(), "should NOT be fresh after recreation with existing groups cache") + assert.Equal(c.groupCalls, 1) + + cdc.ServerResources() + assert.False(cdc.Fresh(), "should NOT be fresh after recreation with existing resources cache") + assert.Equal(c.resourceCalls, 1) + + cdc.Invalidate() + assert.True(cdc.Fresh(), "should be fresh after cache invalidation") + + cdc.ServerResources() + assert.True(cdc.Fresh(), "should ignore existing resources cache after invalidation") + assert.Equal(c.resourceCalls, 2) +} + +func TestNewCachedDiscoveryClient_TTL(t *testing.T) { + assert := assert.New(t) + + d, err := ioutil.TempDir("", "") + assert.NoError(err) + defer os.RemoveAll(d) + + c := fakeDiscoveryClient{} + cdc := newCachedDiscoveryClient(&c, d, 1*time.Nanosecond) + cdc.ServerGroups() + assert.Equal(c.groupCalls, 1) + + time.Sleep(1 * time.Second) + + cdc.ServerGroups() + assert.Equal(c.groupCalls, 2) +} + +type fakeDiscoveryClient struct { + groupCalls int + resourceCalls int + versionCalls int + openAPICalls int + + serverResourcesHandler func() ([]*metav1.APIResourceList, error) +} + +var _ DiscoveryInterface = &fakeDiscoveryClient{} + +func (c *fakeDiscoveryClient) RESTClient() restclient.Interface { + return &fake.RESTClient{} +} + +func (c *fakeDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { + c.groupCalls = c.groupCalls + 1 + return &metav1.APIGroupList{ + Groups: []metav1.APIGroup{ + { + Name: "a", + Versions: []metav1.GroupVersionForDiscovery{ + { + GroupVersion: "a/v1", + Version: "v1", + }, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "a/v1", + Version: "v1", + }, + }, + }, + }, nil +} + +func (c *fakeDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + c.resourceCalls = c.resourceCalls + 1 + if groupVersion == "a/v1" { + return &metav1.APIResourceList{APIResources: []metav1.APIResource{{Name: "widgets", Kind: "Widget"}}}, nil + } + + return nil, errors.NewNotFound(schema.GroupResource{}, "") +} + +func (c *fakeDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { + c.resourceCalls = c.resourceCalls + 1 + if c.serverResourcesHandler != nil { + return c.serverResourcesHandler() + } + return []*metav1.APIResourceList{}, nil +} + +func (c *fakeDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + c.resourceCalls = c.resourceCalls + 1 + return nil, nil +} + +func (c *fakeDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + c.resourceCalls = c.resourceCalls + 1 + return nil, nil +} + +func (c *fakeDiscoveryClient) ServerVersion() (*version.Info, error) { + c.versionCalls = c.versionCalls + 1 + return &version.Info{}, nil +} + +func (c *fakeDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { + c.openAPICalls = c.openAPICalls + 1 + return &openapi_v2.Document{}, nil +} diff --git a/vendor/k8s.io/client-go/discovery/discovery_client.go b/vendor/k8s.io/client-go/discovery/discovery_client.go index 3c685a955..a96602974 100644 --- a/vendor/k8s.io/client-go/discovery/discovery_client.go +++ b/vendor/k8s.io/client-go/discovery/discovery_client.go @@ -22,6 +22,8 @@ import ( "net/url" "sort" "strings" + "sync" + "time" "github.com/golang/protobuf/proto" "github.com/googleapis/gnostic/OpenAPIv2" @@ -31,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/version" "k8s.io/client-go/kubernetes/scheme" restclient "k8s.io/client-go/rest" @@ -41,6 +44,9 @@ const ( defaultRetries = 2 // protobuf mime type mimePb = "application/com.github.proto-openapi.spec.v2@v1.0+protobuf" + // defaultTimeout is the maximum amount of time per request when no timeout has been set on a RESTClient. + // Defaults to 32s in order to have a distinguishable length of time, relative to other timeouts that exist. + defaultTimeout = 32 * time.Second ) // DiscoveryInterface holds the methods that discover server-supported API groups, @@ -183,33 +189,7 @@ func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (r // serverResources returns the supported resources for all groups and versions. func (d *DiscoveryClient) serverResources() ([]*metav1.APIResourceList, error) { - apiGroups, err := d.ServerGroups() - if err != nil { - return nil, err - } - - result := []*metav1.APIResourceList{} - failedGroups := make(map[schema.GroupVersion]error) - - for _, apiGroup := range apiGroups.Groups { - for _, version := range apiGroup.Versions { - gv := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version} - resources, err := d.ServerResourcesForGroupVersion(version.GroupVersion) - if err != nil { - // TODO: maybe restrict this to NotFound errors - failedGroups[gv] = err - continue - } - - result = append(result, resources) - } - } - - if len(failedGroups) == 0 { - return result, nil - } - - return result, &ErrGroupDiscoveryFailed{Groups: failedGroups} + return ServerResources(d) } // ServerResources returns the supported resources for all groups and versions. @@ -242,14 +222,46 @@ func IsGroupDiscoveryFailedError(err error) bool { // serverPreferredResources returns the supported resources with the version preferred by the server. func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList, error) { - serverGroupList, err := d.ServerGroups() + return ServerPreferredResources(d) +} + +// ServerResources uses the provided discovery interface to look up supported resources for all groups and versions. +func ServerResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) { + apiGroups, err := d.ServerGroups() if err != nil { return nil, err } + groupVersionResources, failedGroups := fetchGroupVersionResources(d, apiGroups) + + // order results by group/version discovery order result := []*metav1.APIResourceList{} - failedGroups := make(map[schema.GroupVersion]error) + for _, apiGroup := range apiGroups.Groups { + for _, version := range apiGroup.Versions { + gv := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version} + if resources, ok := groupVersionResources[gv]; ok { + result = append(result, resources) + } + } + } + + if len(failedGroups) == 0 { + return result, nil + } + + return result, &ErrGroupDiscoveryFailed{Groups: failedGroups} +} + +// ServerPreferredResources uses the provided discovery interface to look up preferred resources +func ServerPreferredResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) { + serverGroupList, err := d.ServerGroups() + if err != nil { + return nil, err + } + groupVersionResources, failedGroups := fetchGroupVersionResources(d, serverGroupList) + + result := []*metav1.APIResourceList{} grVersions := map[schema.GroupResource]string{} // selected version of a GroupResource grApiResources := map[schema.GroupResource]*metav1.APIResource{} // selected APIResource for a GroupResource gvApiResourceLists := map[schema.GroupVersion]*metav1.APIResourceList{} // blueprint for a APIResourceList for later grouping @@ -257,10 +269,9 @@ func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList, for _, apiGroup := range serverGroupList.Groups { for _, version := range apiGroup.Versions { groupVersion := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version} - apiResourceList, err := d.ServerResourcesForGroupVersion(version.GroupVersion) - if err != nil { - // TODO: maybe restrict this to NotFound errors - failedGroups[groupVersion] = err + + apiResourceList, ok := groupVersionResources[groupVersion] + if !ok { continue } @@ -302,6 +313,41 @@ func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList, return result, &ErrGroupDiscoveryFailed{Groups: failedGroups} } +// fetchServerResourcesForGroupVersions uses the discovery client to fetch the resources for the specified groups in parallel +func fetchGroupVersionResources(d DiscoveryInterface, apiGroups *metav1.APIGroupList) (map[schema.GroupVersion]*metav1.APIResourceList, map[schema.GroupVersion]error) { + groupVersionResources := make(map[schema.GroupVersion]*metav1.APIResourceList) + failedGroups := make(map[schema.GroupVersion]error) + + wg := &sync.WaitGroup{} + resultLock := &sync.Mutex{} + for _, apiGroup := range apiGroups.Groups { + for _, version := range apiGroup.Versions { + groupVersion := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version} + wg.Add(1) + go func() { + defer wg.Done() + defer utilruntime.HandleCrash() + + apiResourceList, err := d.ServerResourcesForGroupVersion(groupVersion.String()) + + // lock to record results + resultLock.Lock() + defer resultLock.Unlock() + + if err != nil { + // TODO: maybe restrict this to NotFound errors + failedGroups[groupVersion] = err + } else { + groupVersionResources[groupVersion] = apiResourceList + } + }() + } + } + wg.Wait() + + return groupVersionResources, failedGroups +} + // ServerPreferredResources returns the supported resources with the version preferred by the // server. func (d *DiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { @@ -311,7 +357,12 @@ func (d *DiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, // ServerPreferredNamespacedResources returns the supported namespaced resources with the // version preferred by the server. func (d *DiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { - all, err := d.ServerPreferredResources() + return ServerPreferredNamespacedResources(d) +} + +// ServerPreferredNamespacedResources uses the provided discovery interface to look up preferred namespaced resources +func ServerPreferredNamespacedResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) { + all, err := ServerPreferredResources(d) return FilteredBy(ResourcePredicateFunc(func(groupVersion string, r *metav1.APIResource) bool { return r.Namespaced }), all), err @@ -335,7 +386,7 @@ func (d *DiscoveryClient) ServerVersion() (*version.Info, error) { func (d *DiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { data, err := d.restClient.Get().AbsPath("/openapi/v2").SetHeader("Accept", mimePb).Do().Raw() if err != nil { - if errors.IsForbidden(err) || errors.IsNotFound(err) { + if errors.IsForbidden(err) || errors.IsNotFound(err) || errors.IsNotAcceptable(err) { // single endpoint not found/registered in old server, try to fetch old endpoint // TODO(roycaihw): remove this in 1.11 data, err = d.restClient.Get().AbsPath("/swagger-2.0.0.pb-v1").Do().Raw() @@ -373,6 +424,9 @@ func withRetries(maxRetries int, f func() ([]*metav1.APIResourceList, error)) ([ func setDiscoveryDefaults(config *restclient.Config) error { config.APIPath = "" config.GroupVersion = nil + if config.Timeout == 0 { + config.Timeout = defaultTimeout + } codec := runtime.NoopEncoder{Decoder: scheme.Codecs.UniversalDecoder()} config.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec}) if len(config.UserAgent) == 0 { diff --git a/vendor/k8s.io/client-go/discovery/discovery_client_test.go b/vendor/k8s.io/client-go/discovery/discovery_client_test.go index ad855139a..10e494322 100644 --- a/vendor/k8s.io/client-go/discovery/discovery_client_test.go +++ b/vendor/k8s.io/client-go/discovery/discovery_client_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package discovery_test +package discovery import ( "encoding/json" @@ -27,12 +27,13 @@ import ( "github.com/gogo/protobuf/proto" "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/version" - . "k8s.io/client-go/discovery" restclient "k8s.io/client-go/rest" ) @@ -130,6 +131,12 @@ func TestGetServerGroupsWithBrokenServer(t *testing.T) { } } +func TestTimeoutIsSet(t *testing.T) { + cfg := &restclient.Config{} + setDiscoveryDefaults(cfg) + assert.Equal(t, defaultTimeout, cfg.Timeout) +} + func TestGetServerResourcesWithV1Server(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { var obj interface{} @@ -183,6 +190,14 @@ func TestGetServerResources(t *testing.T) { {Name: "jobs", Namespaced: true, Kind: "Job"}, }, } + beta2 := metav1.APIResourceList{ + GroupVersion: "extensions/v1beta2", + APIResources: []metav1.APIResource{ + {Name: "deployments", Namespaced: true, Kind: "Deployment"}, + {Name: "ingresses", Namespaced: true, Kind: "Ingress"}, + {Name: "jobs", Namespaced: true, Kind: "Job"}, + }, + } tests := []struct { resourcesList *metav1.APIResourceList path string @@ -215,6 +230,8 @@ func TestGetServerResources(t *testing.T) { list = &stable case "/apis/extensions/v1beta1": list = &beta + case "/apis/extensions/v1beta2": + list = &beta2 case "/api": list = &metav1.APIVersions{ Versions: []string{ @@ -225,8 +242,10 @@ func TestGetServerResources(t *testing.T) { list = &metav1.APIGroupList{ Groups: []metav1.APIGroup{ { + Name: "extensions", Versions: []metav1.GroupVersionForDiscovery{ - {GroupVersion: "extensions/v1beta1"}, + {GroupVersion: "extensions/v1beta1", Version: "v1beta1"}, + {GroupVersion: "extensions/v1beta2", Version: "v1beta2"}, }, }, }, @@ -268,11 +287,10 @@ func TestGetServerResources(t *testing.T) { if err != nil { t.Errorf("unexpected error: %v", err) } - serverGroupVersions := sets.NewString(groupVersions(serverResources)...) - for _, api := range []string{"v1", "extensions/v1beta1"} { - if !serverGroupVersions.Has(api) { - t.Errorf("missing expected api %q in %v", api, serverResources) - } + serverGroupVersions := groupVersions(serverResources) + expectedGroupVersions := []string{"v1", "extensions/v1beta1", "extensions/v1beta2"} + if !reflect.DeepEqual(expectedGroupVersions, serverGroupVersions) { + t.Errorf("unexpected group versions: %v", diff.ObjectReflectDiff(expectedGroupVersions, serverGroupVersions)) } } @@ -326,12 +344,12 @@ var returnedOpenAPI = openapi_v2.Document{ }, } -func openapiSchemaDeprecatedFakeServer() (*httptest.Server, error) { +func openapiSchemaDeprecatedFakeServer(status int) (*httptest.Server, error) { var sErr error server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - // old server returns 403 on new endpoint request if req.URL.Path == "/openapi/v2" { - w.WriteHeader(http.StatusForbidden) + // write the error status for the new endpoint request + w.WriteHeader(status) return } if req.URL.Path != "/swagger-2.0.0.pb-v1" { @@ -398,8 +416,42 @@ func TestGetOpenAPISchema(t *testing.T) { } } -func TestGetOpenAPISchemaFallback(t *testing.T) { - server, err := openapiSchemaDeprecatedFakeServer() +func TestGetOpenAPISchemaForbiddenFallback(t *testing.T) { + server, err := openapiSchemaDeprecatedFakeServer(http.StatusForbidden) + if err != nil { + t.Errorf("unexpected error starting fake server: %v", err) + } + defer server.Close() + + client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL}) + got, err := client.OpenAPISchema() + if err != nil { + t.Fatalf("unexpected error getting openapi: %v", err) + } + if e, a := returnedOpenAPI, *got; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetOpenAPISchemaNotFoundFallback(t *testing.T) { + server, err := openapiSchemaDeprecatedFakeServer(http.StatusNotFound) + if err != nil { + t.Errorf("unexpected error starting fake server: %v", err) + } + defer server.Close() + + client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL}) + got, err := client.OpenAPISchema() + if err != nil { + t.Fatalf("unexpected error getting openapi: %v", err) + } + if e, a := returnedOpenAPI, *got; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetOpenAPISchemaNotAcceptableFallback(t *testing.T) { + server, err := openapiSchemaDeprecatedFakeServer(http.StatusNotAcceptable) if err != nil { t.Errorf("unexpected error starting fake server: %v", err) } @@ -584,7 +636,7 @@ func TestServerPreferredResourcesRetries(t *testing.T) { { Name: "extensions", Versions: []metav1.GroupVersionForDiscovery{ - {GroupVersion: "extensions/v1beta1"}, + {GroupVersion: "extensions/v1beta1", Version: "v1beta1"}, }, PreferredVersion: metav1.GroupVersionForDiscovery{ GroupVersion: "extensions/v1beta1", diff --git a/vendor/k8s.io/client-go/discovery/fake/BUILD b/vendor/k8s.io/client-go/discovery/fake/BUILD deleted file mode 100644 index 5b50832a8..000000000 --- a/vendor/k8s.io/client-go/discovery/fake/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["discovery.go"], - importpath = "k8s.io/client-go/discovery/fake", - deps = [ - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) - -go_test( - name = "go_default_xtest", - srcs = ["discovery_test.go"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/discovery/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", - ], -) diff --git a/vendor/k8s.io/client-go/discovery/restmapper.go b/vendor/k8s.io/client-go/discovery/restmapper.go deleted file mode 100644 index df5ab0358..000000000 --- a/vendor/k8s.io/client-go/discovery/restmapper.go +++ /dev/null @@ -1,333 +0,0 @@ -/* -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 discovery - -import ( - "fmt" - "strings" - "sync" - - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - - "github.com/golang/glog" -) - -// APIGroupResources is an API group with a mapping of versions to -// resources. -type APIGroupResources struct { - Group metav1.APIGroup - // A mapping of version string to a slice of APIResources for - // that version. - VersionedResources map[string][]metav1.APIResource -} - -// NewRESTMapper returns a PriorityRESTMapper based on the discovered -// groups and resources passed in. -func NewRESTMapper(groupResources []*APIGroupResources, versionInterfaces meta.VersionInterfacesFunc) meta.RESTMapper { - unionMapper := meta.MultiRESTMapper{} - - var groupPriority []string - // /v1 is special. It should always come first - resourcePriority := []schema.GroupVersionResource{{Group: "", Version: "v1", Resource: meta.AnyResource}} - kindPriority := []schema.GroupVersionKind{{Group: "", Version: "v1", Kind: meta.AnyKind}} - - for _, group := range groupResources { - groupPriority = append(groupPriority, group.Group.Name) - - // Make sure the preferred version comes first - if len(group.Group.PreferredVersion.Version) != 0 { - preferred := group.Group.PreferredVersion.Version - if _, ok := group.VersionedResources[preferred]; ok { - resourcePriority = append(resourcePriority, schema.GroupVersionResource{ - Group: group.Group.Name, - Version: group.Group.PreferredVersion.Version, - Resource: meta.AnyResource, - }) - - kindPriority = append(kindPriority, schema.GroupVersionKind{ - Group: group.Group.Name, - Version: group.Group.PreferredVersion.Version, - Kind: meta.AnyKind, - }) - } - } - - for _, discoveryVersion := range group.Group.Versions { - resources, ok := group.VersionedResources[discoveryVersion.Version] - if !ok { - continue - } - - // Add non-preferred versions after the preferred version, in case there are resources that only exist in those versions - if discoveryVersion.Version != group.Group.PreferredVersion.Version { - resourcePriority = append(resourcePriority, schema.GroupVersionResource{ - Group: group.Group.Name, - Version: discoveryVersion.Version, - Resource: meta.AnyResource, - }) - - kindPriority = append(kindPriority, schema.GroupVersionKind{ - Group: group.Group.Name, - Version: discoveryVersion.Version, - Kind: meta.AnyKind, - }) - } - - gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version} - versionMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{gv}, versionInterfaces) - - for _, resource := range resources { - scope := meta.RESTScopeNamespace - if !resource.Namespaced { - scope = meta.RESTScopeRoot - } - - // this is for legacy resources and servers which don't list singular forms. For those we must still guess. - if len(resource.SingularName) == 0 { - versionMapper.Add(gv.WithKind(resource.Kind), scope) - // TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior - versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope) - continue - } - - plural := gv.WithResource(resource.Name) - singular := gv.WithResource(resource.SingularName) - versionMapper.AddSpecific(gv.WithKind(resource.Kind), plural, singular, scope) - versionMapper.AddSpecific(gv.WithKind(strings.ToLower(resource.Kind)), plural, singular, scope) - // TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior - versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope) - } - // TODO why is this type not in discovery (at least for "v1") - versionMapper.Add(gv.WithKind("List"), meta.RESTScopeRoot) - unionMapper = append(unionMapper, versionMapper) - } - } - - for _, group := range groupPriority { - resourcePriority = append(resourcePriority, schema.GroupVersionResource{ - Group: group, - Version: meta.AnyVersion, - Resource: meta.AnyResource, - }) - kindPriority = append(kindPriority, schema.GroupVersionKind{ - Group: group, - Version: meta.AnyVersion, - Kind: meta.AnyKind, - }) - } - - return meta.PriorityRESTMapper{ - Delegate: unionMapper, - ResourcePriority: resourcePriority, - KindPriority: kindPriority, - } -} - -// GetAPIGroupResources uses the provided discovery client to gather -// discovery information and populate a slice of APIGroupResources. -func GetAPIGroupResources(cl DiscoveryInterface) ([]*APIGroupResources, error) { - apiGroups, err := cl.ServerGroups() - if err != nil { - return nil, err - } - var result []*APIGroupResources - for _, group := range apiGroups.Groups { - groupResources := &APIGroupResources{ - Group: group, - VersionedResources: make(map[string][]metav1.APIResource), - } - for _, version := range group.Versions { - resources, err := cl.ServerResourcesForGroupVersion(version.GroupVersion) - if err != nil { - // continue as best we can - // TODO track the errors and update callers to handle partial errors. - continue - } - groupResources.VersionedResources[version.Version] = resources.APIResources - } - result = append(result, groupResources) - } - return result, nil -} - -// DeferredDiscoveryRESTMapper is a RESTMapper that will defer -// initialization of the RESTMapper until the first mapping is -// requested. -type DeferredDiscoveryRESTMapper struct { - initMu sync.Mutex - delegate meta.RESTMapper - cl CachedDiscoveryInterface - versionInterface meta.VersionInterfacesFunc -} - -// NewDeferredDiscoveryRESTMapper returns a -// DeferredDiscoveryRESTMapper that will lazily query the provided -// client for discovery information to do REST mappings. -func NewDeferredDiscoveryRESTMapper(cl CachedDiscoveryInterface, versionInterface meta.VersionInterfacesFunc) *DeferredDiscoveryRESTMapper { - return &DeferredDiscoveryRESTMapper{ - cl: cl, - versionInterface: versionInterface, - } -} - -func (d *DeferredDiscoveryRESTMapper) getDelegate() (meta.RESTMapper, error) { - d.initMu.Lock() - defer d.initMu.Unlock() - - if d.delegate != nil { - return d.delegate, nil - } - - groupResources, err := GetAPIGroupResources(d.cl) - if err != nil { - return nil, err - } - - d.delegate = NewRESTMapper(groupResources, d.versionInterface) - return d.delegate, err -} - -// Reset resets the internally cached Discovery information and will -// cause the next mapping request to re-discover. -func (d *DeferredDiscoveryRESTMapper) Reset() { - glog.V(5).Info("Invalidating discovery information") - - d.initMu.Lock() - defer d.initMu.Unlock() - - d.cl.Invalidate() - d.delegate = nil -} - -// KindFor takes a partial resource and returns back the single match. -// It returns an error if there are multiple matches. -func (d *DeferredDiscoveryRESTMapper) KindFor(resource schema.GroupVersionResource) (gvk schema.GroupVersionKind, err error) { - del, err := d.getDelegate() - if err != nil { - return schema.GroupVersionKind{}, err - } - gvk, err = del.KindFor(resource) - if err != nil && !d.cl.Fresh() { - d.Reset() - gvk, err = d.KindFor(resource) - } - return -} - -// KindsFor takes a partial resource and returns back the list of -// potential kinds in priority order. -func (d *DeferredDiscoveryRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvks []schema.GroupVersionKind, err error) { - del, err := d.getDelegate() - if err != nil { - return nil, err - } - gvks, err = del.KindsFor(resource) - if len(gvks) == 0 && !d.cl.Fresh() { - d.Reset() - gvks, err = d.KindsFor(resource) - } - return -} - -// ResourceFor takes a partial resource and returns back the single -// match. It returns an error if there are multiple matches. -func (d *DeferredDiscoveryRESTMapper) ResourceFor(input schema.GroupVersionResource) (gvr schema.GroupVersionResource, err error) { - del, err := d.getDelegate() - if err != nil { - return schema.GroupVersionResource{}, err - } - gvr, err = del.ResourceFor(input) - if err != nil && !d.cl.Fresh() { - d.Reset() - gvr, err = d.ResourceFor(input) - } - return -} - -// ResourcesFor takes a partial resource and returns back the list of -// potential resource in priority order. -func (d *DeferredDiscoveryRESTMapper) ResourcesFor(input schema.GroupVersionResource) (gvrs []schema.GroupVersionResource, err error) { - del, err := d.getDelegate() - if err != nil { - return nil, err - } - gvrs, err = del.ResourcesFor(input) - if len(gvrs) == 0 && !d.cl.Fresh() { - d.Reset() - gvrs, err = d.ResourcesFor(input) - } - return -} - -// RESTMapping identifies a preferred resource mapping for the -// provided group kind. -func (d *DeferredDiscoveryRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (m *meta.RESTMapping, err error) { - del, err := d.getDelegate() - if err != nil { - return nil, err - } - m, err = del.RESTMapping(gk, versions...) - if err != nil && !d.cl.Fresh() { - d.Reset() - m, err = d.RESTMapping(gk, versions...) - } - return -} - -// RESTMappings returns the RESTMappings for the provided group kind -// in a rough internal preferred order. If no kind is found, it will -// return a NoResourceMatchError. -func (d *DeferredDiscoveryRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (ms []*meta.RESTMapping, err error) { - del, err := d.getDelegate() - if err != nil { - return nil, err - } - ms, err = del.RESTMappings(gk, versions...) - if len(ms) == 0 && !d.cl.Fresh() { - d.Reset() - ms, err = d.RESTMappings(gk, versions...) - } - return -} - -// ResourceSingularizer converts a resource name from plural to -// singular (e.g., from pods to pod). -func (d *DeferredDiscoveryRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { - del, err := d.getDelegate() - if err != nil { - return resource, err - } - singular, err = del.ResourceSingularizer(resource) - if err != nil && !d.cl.Fresh() { - d.Reset() - singular, err = d.ResourceSingularizer(resource) - } - return -} - -func (d *DeferredDiscoveryRESTMapper) String() string { - del, err := d.getDelegate() - if err != nil { - return fmt.Sprintf("DeferredDiscoveryRESTMapper{%v}", err) - } - return fmt.Sprintf("DeferredDiscoveryRESTMapper{\n\t%v\n}", del) -} - -// Make sure it satisfies the interface -var _ meta.RESTMapper = &DeferredDiscoveryRESTMapper{} diff --git a/vendor/k8s.io/client-go/discovery/restmapper_test.go b/vendor/k8s.io/client-go/discovery/restmapper_test.go deleted file mode 100644 index 69ee7e686..000000000 --- a/vendor/k8s.io/client-go/discovery/restmapper_test.go +++ /dev/null @@ -1,384 +0,0 @@ -/* -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 discovery_test - -import ( - "reflect" - "testing" - - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/version" - . "k8s.io/client-go/discovery" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" - - "github.com/googleapis/gnostic/OpenAPIv2" - "github.com/stretchr/testify/assert" -) - -func TestRESTMapper(t *testing.T) { - resources := []*APIGroupResources{ - { - Group: metav1.APIGroup{ - Name: "extensions", - Versions: []metav1.GroupVersionForDiscovery{ - {Version: "v1beta"}, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1beta"}, - }, - VersionedResources: map[string][]metav1.APIResource{ - "v1beta": { - {Name: "jobs", Namespaced: true, Kind: "Job"}, - {Name: "pods", Namespaced: true, Kind: "Pod"}, - }, - }, - }, - { - Group: metav1.APIGroup{ - Versions: []metav1.GroupVersionForDiscovery{ - {Version: "v1"}, - {Version: "v2"}, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1"}, - }, - VersionedResources: map[string][]metav1.APIResource{ - "v1": { - {Name: "pods", Namespaced: true, Kind: "Pod"}, - }, - "v2": { - {Name: "pods", Namespaced: true, Kind: "Pod"}, - }, - }, - }, - - // This group tests finding and prioritizing resources that only exist in non-preferred versions - { - Group: metav1.APIGroup{ - Name: "unpreferred", - Versions: []metav1.GroupVersionForDiscovery{ - {Version: "v1"}, - {Version: "v2beta1"}, - {Version: "v2alpha1"}, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1"}, - }, - VersionedResources: map[string][]metav1.APIResource{ - "v1": { - {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, - }, - "v2beta1": { - {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, - {Name: "peas", Namespaced: true, Kind: "Pea"}, - }, - "v2alpha1": { - {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, - {Name: "peas", Namespaced: true, Kind: "Pea"}, - }, - }, - }, - } - - restMapper := NewRESTMapper(resources, nil) - - kindTCs := []struct { - input schema.GroupVersionResource - want schema.GroupVersionKind - }{ - { - input: schema.GroupVersionResource{ - Resource: "pods", - }, - want: schema.GroupVersionKind{ - Version: "v1", - Kind: "Pod", - }, - }, - { - input: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - want: schema.GroupVersionKind{ - Version: "v1", - Kind: "Pod", - }, - }, - { - input: schema.GroupVersionResource{ - Version: "v2", - Resource: "pods", - }, - want: schema.GroupVersionKind{ - Version: "v2", - Kind: "Pod", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "pods", - }, - want: schema.GroupVersionKind{ - Version: "v1", - Kind: "Pod", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "jobs", - }, - want: schema.GroupVersionKind{ - Group: "extensions", - Version: "v1beta", - Kind: "Job", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "peas", - }, - want: schema.GroupVersionKind{ - Group: "unpreferred", - Version: "v2beta1", - Kind: "Pea", - }, - }, - } - - for _, tc := range kindTCs { - got, err := restMapper.KindFor(tc.input) - if err != nil { - t.Errorf("KindFor(%#v) unexpected error: %v", tc.input, err) - continue - } - - if !reflect.DeepEqual(got, tc.want) { - t.Errorf("KindFor(%#v) = %#v, want %#v", tc.input, got, tc.want) - } - } - - resourceTCs := []struct { - input schema.GroupVersionResource - want schema.GroupVersionResource - }{ - { - input: schema.GroupVersionResource{ - Resource: "pods", - }, - want: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - }, - { - input: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - want: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - }, - { - input: schema.GroupVersionResource{ - Version: "v2", - Resource: "pods", - }, - want: schema.GroupVersionResource{ - Version: "v2", - Resource: "pods", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "pods", - }, - want: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "jobs", - }, - want: schema.GroupVersionResource{ - Group: "extensions", - Version: "v1beta", - Resource: "jobs", - }, - }, - } - - for _, tc := range resourceTCs { - got, err := restMapper.ResourceFor(tc.input) - if err != nil { - t.Errorf("ResourceFor(%#v) unexpected error: %v", tc.input, err) - continue - } - - if !reflect.DeepEqual(got, tc.want) { - t.Errorf("ResourceFor(%#v) = %#v, want %#v", tc.input, got, tc.want) - } - } -} - -func TestDeferredDiscoveryRESTMapper_CacheMiss(t *testing.T) { - assert := assert.New(t) - - cdc := fakeCachedDiscoveryInterface{fresh: false} - m := NewDeferredDiscoveryRESTMapper(&cdc, nil) - assert.False(cdc.fresh, "should NOT be fresh after instantiation") - assert.Zero(cdc.invalidateCalls, "should not have called Invalidate()") - - gvk, err := m.KindFor(schema.GroupVersionResource{ - Group: "a", - Version: "v1", - Resource: "foo", - }) - assert.NoError(err) - assert.True(cdc.fresh, "should be fresh after a cache-miss") - assert.Equal(cdc.invalidateCalls, 1, "should have called Invalidate() once") - assert.Equal(gvk.Kind, "Foo") - - gvk, err = m.KindFor(schema.GroupVersionResource{ - Group: "a", - Version: "v1", - Resource: "foo", - }) - assert.NoError(err) - assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again") - - gvk, err = m.KindFor(schema.GroupVersionResource{ - Group: "a", - Version: "v1", - Resource: "bar", - }) - assert.Error(err) - assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again after another cache-miss, but with fresh==true") - - cdc.fresh = false - gvk, err = m.KindFor(schema.GroupVersionResource{ - Group: "a", - Version: "v1", - Resource: "bar", - }) - assert.Error(err) - assert.Equal(cdc.invalidateCalls, 2, "should HAVE called Invalidate() again after another cache-miss, but with fresh==false") -} - -type fakeCachedDiscoveryInterface struct { - invalidateCalls int - fresh bool - enabledA bool -} - -var _ CachedDiscoveryInterface = &fakeCachedDiscoveryInterface{} - -func (c *fakeCachedDiscoveryInterface) Fresh() bool { - return c.fresh -} - -func (c *fakeCachedDiscoveryInterface) Invalidate() { - c.invalidateCalls = c.invalidateCalls + 1 - c.fresh = true - c.enabledA = true -} - -func (c *fakeCachedDiscoveryInterface) RESTClient() restclient.Interface { - return &fake.RESTClient{} -} - -func (c *fakeCachedDiscoveryInterface) ServerGroups() (*metav1.APIGroupList, error) { - if c.enabledA { - return &metav1.APIGroupList{ - Groups: []metav1.APIGroup{ - { - Name: "a", - Versions: []metav1.GroupVersionForDiscovery{ - { - GroupVersion: "a/v1", - Version: "v1", - }, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{ - GroupVersion: "a/v1", - Version: "v1", - }, - }, - }, - }, nil - } - return &metav1.APIGroupList{}, nil -} - -func (c *fakeCachedDiscoveryInterface) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - if c.enabledA && groupVersion == "a/v1" { - return &metav1.APIResourceList{ - GroupVersion: "a/v1", - APIResources: []metav1.APIResource{ - { - Name: "foo", - Kind: "Foo", - Namespaced: false, - }, - }, - }, nil - } - - return nil, errors.NewNotFound(schema.GroupResource{}, "") -} - -func (c *fakeCachedDiscoveryInterface) ServerResources() ([]*metav1.APIResourceList, error) { - if c.enabledA { - av1, _ := c.ServerResourcesForGroupVersion("a/v1") - return []*metav1.APIResourceList{av1}, nil - } - return []*metav1.APIResourceList{}, nil -} - -func (c *fakeCachedDiscoveryInterface) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - if c.enabledA { - return []*metav1.APIResourceList{ - { - GroupVersion: "a/v1", - APIResources: []metav1.APIResource{ - { - Name: "foo", - Kind: "Foo", - Verbs: []string{}, - }, - }, - }, - }, nil - } - return nil, nil -} - -func (c *fakeCachedDiscoveryInterface) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { - return nil, nil -} - -func (c *fakeCachedDiscoveryInterface) ServerVersion() (*version.Info, error) { - return &version.Info{}, nil -} - -func (c *fakeCachedDiscoveryInterface) OpenAPISchema() (*openapi_v2.Document, error) { - return &openapi_v2.Document{}, nil -} diff --git a/vendor/k8s.io/client-go/discovery/round_tripper.go b/vendor/k8s.io/client-go/discovery/round_tripper.go new file mode 100644 index 000000000..2e352b888 --- /dev/null +++ b/vendor/k8s.io/client-go/discovery/round_tripper.go @@ -0,0 +1,51 @@ +/* +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 transport provides a round tripper capable of caching HTTP responses. +package discovery + +import ( + "net/http" + "path/filepath" + + "github.com/gregjones/httpcache" + "github.com/gregjones/httpcache/diskcache" + "github.com/peterbourgon/diskv" +) + +type cacheRoundTripper struct { + rt *httpcache.Transport +} + +// newCacheRoundTripper creates a roundtripper that reads the ETag on +// response headers and send the If-None-Match header on subsequent +// corresponding requests. +func newCacheRoundTripper(cacheDir string, rt http.RoundTripper) http.RoundTripper { + d := diskv.New(diskv.Options{ + BasePath: cacheDir, + TempDir: filepath.Join(cacheDir, ".diskv-temp"), + }) + t := httpcache.NewTransport(diskcache.NewWithDiskv(d)) + t.Transport = rt + + return &cacheRoundTripper{rt: t} +} + +func (rt *cacheRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + return rt.rt.RoundTrip(req) +} + +func (rt *cacheRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt.Transport } diff --git a/vendor/k8s.io/client-go/discovery/round_tripper_test.go b/vendor/k8s.io/client-go/discovery/round_tripper_test.go new file mode 100644 index 000000000..b15e2e771 --- /dev/null +++ b/vendor/k8s.io/client-go/discovery/round_tripper_test.go @@ -0,0 +1,95 @@ +/* +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 discovery + +import ( + "bytes" + "io/ioutil" + "net/http" + "net/url" + "os" + "testing" +) + +// copied from k8s.io/client-go/transport/round_trippers_test.go +type testRoundTripper struct { + Request *http.Request + Response *http.Response + Err error +} + +func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + rt.Request = req + return rt.Response, rt.Err +} + +func TestCacheRoundTripper(t *testing.T) { + rt := &testRoundTripper{} + cacheDir, err := ioutil.TempDir("", "cache-rt") + defer os.RemoveAll(cacheDir) + if err != nil { + t.Fatal(err) + } + cache := newCacheRoundTripper(cacheDir, rt) + + // First call, caches the response + req := &http.Request{ + Method: http.MethodGet, + URL: &url.URL{Host: "localhost"}, + } + rt.Response = &http.Response{ + Header: http.Header{"ETag": []string{`"123456"`}}, + Body: ioutil.NopCloser(bytes.NewReader([]byte("Content"))), + StatusCode: http.StatusOK, + } + resp, err := cache.RoundTrip(req) + if err != nil { + t.Fatal(err) + } + content, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + if string(content) != "Content" { + t.Errorf(`Expected Body to be "Content", got %q`, string(content)) + } + + // Second call, returns cached response + req = &http.Request{ + Method: http.MethodGet, + URL: &url.URL{Host: "localhost"}, + } + rt.Response = &http.Response{ + StatusCode: http.StatusNotModified, + Body: ioutil.NopCloser(bytes.NewReader([]byte("Other Content"))), + } + + resp, err = cache.RoundTrip(req) + if err != nil { + t.Fatal(err) + } + + // Read body and make sure we have the initial content + content, err = ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + t.Fatal(err) + } + if string(content) != "Content" { + t.Errorf("Invalid content read from cache %q", string(content)) + } +} diff --git a/vendor/k8s.io/client-go/discovery/unstructured.go b/vendor/k8s.io/client-go/discovery/unstructured.go index fa7f2ec06..81913a414 100644 --- a/vendor/k8s.io/client-go/discovery/unstructured.go +++ b/vendor/k8s.io/client-go/discovery/unstructured.go @@ -26,31 +26,17 @@ import ( // UnstructuredObjectTyper provides a runtime.ObjectTyper implementation for // runtime.Unstructured object based on discovery information. type UnstructuredObjectTyper struct { - registered map[schema.GroupVersionKind]bool - typers []runtime.ObjectTyper + typers []runtime.ObjectTyper } // NewUnstructuredObjectTyper returns a runtime.ObjectTyper for // unstructured objects based on discovery information. It accepts a list of fallback typers // for handling objects that are not runtime.Unstructured. It does not delegate the Recognizes // check, only ObjectKinds. -func NewUnstructuredObjectTyper(groupResources []*APIGroupResources, typers ...runtime.ObjectTyper) *UnstructuredObjectTyper { +// TODO this only works for the apiextensions server and doesn't recognize any types. Move to point of use. +func NewUnstructuredObjectTyper(typers ...runtime.ObjectTyper) *UnstructuredObjectTyper { dot := &UnstructuredObjectTyper{ - registered: make(map[schema.GroupVersionKind]bool), - typers: typers, - } - for _, group := range groupResources { - for _, discoveryVersion := range group.Group.Versions { - resources, ok := group.VersionedResources[discoveryVersion.Version] - if !ok { - continue - } - - gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version} - for _, resource := range resources { - dot.registered[gv.WithKind(resource.Kind)] = true - } - } + typers: typers, } return dot } @@ -89,7 +75,7 @@ func (d *UnstructuredObjectTyper) ObjectKinds(obj runtime.Object) (gvks []schema // Recognizes returns true if the provided group,version,kind was in the // discovery information. func (d *UnstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool { - return d.registered[gvk] + return false } var _ runtime.ObjectTyper = &UnstructuredObjectTyper{} diff --git a/vendor/k8s.io/client-go/dynamic/BUILD b/vendor/k8s.io/client-go/dynamic/BUILD deleted file mode 100644 index 3642f6a0f..000000000 --- a/vendor/k8s.io/client-go/dynamic/BUILD +++ /dev/null @@ -1,68 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "client_test.go", - "dynamic_util_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/streaming:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/rest/watch:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = [ - "client.go", - "client_pool.go", - "dynamic_util.go", - ], - importpath = "k8s.io/client-go/dynamic", - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/conversion/queryparams: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:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/dynamic/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/dynamic/client.go b/vendor/k8s.io/client-go/dynamic/client.go deleted file mode 100644 index 833e43537..000000000 --- a/vendor/k8s.io/client-go/dynamic/client.go +++ /dev/null @@ -1,379 +0,0 @@ -/* -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 dynamic provides a client interface to arbitrary Kubernetes -// APIs that exposes common high level operations and exposes common -// metadata. -package dynamic - -import ( - "encoding/json" - "errors" - "io" - "net/url" - "strings" - - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/conversion/queryparams" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/kubernetes/scheme" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/util/flowcontrol" -) - -// Interface is a Kubernetes client that allows you to access metadata -// and manipulate metadata of a Kubernetes API group. -type Interface interface { - // GetRateLimiter returns the rate limiter for this client. - GetRateLimiter() flowcontrol.RateLimiter - // Resource returns an API interface to the specified resource for this client's - // group and version. If resource is not a namespaced resource, then namespace - // is ignored. The ResourceInterface inherits the parameter codec of this client. - Resource(resource *metav1.APIResource, namespace string) ResourceInterface - // ParameterCodec returns a client with the provided parameter codec. - ParameterCodec(parameterCodec runtime.ParameterCodec) Interface -} - -// ResourceInterface is an API interface to a specific resource under a -// dynamic client. -type ResourceInterface interface { - // List returns a list of objects for this resource. - List(opts metav1.ListOptions) (runtime.Object, error) - // Get gets the resource with the specified name. - Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) - // Delete deletes the resource with the specified name. - Delete(name string, opts *metav1.DeleteOptions) error - // DeleteCollection deletes a collection of objects. - DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error - // Create creates the provided resource. - Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) - // Update updates the provided resource. - Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) - // Watch returns a watch.Interface that watches the resource. - Watch(opts metav1.ListOptions) (watch.Interface, error) - // Patch patches the provided resource. - Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) -} - -// Client is a Kubernetes client that allows you to access metadata -// and manipulate metadata of a Kubernetes API group, and implements Interface. -type Client struct { - cl *restclient.RESTClient - parameterCodec runtime.ParameterCodec -} - -// NewClient returns a new client based on the passed in config. The -// codec is ignored, as the dynamic client uses it's own codec. -func NewClient(conf *restclient.Config) (*Client, error) { - // avoid changing the original config - confCopy := *conf - conf = &confCopy - - contentConfig := ContentConfig() - contentConfig.GroupVersion = conf.GroupVersion - if conf.NegotiatedSerializer != nil { - contentConfig.NegotiatedSerializer = conf.NegotiatedSerializer - } - conf.ContentConfig = contentConfig - - if conf.APIPath == "" { - conf.APIPath = "/api" - } - - if len(conf.UserAgent) == 0 { - conf.UserAgent = restclient.DefaultKubernetesUserAgent() - } - - cl, err := restclient.RESTClientFor(conf) - if err != nil { - return nil, err - } - - return &Client{cl: cl}, nil -} - -// GetRateLimiter returns rate limier. -func (c *Client) GetRateLimiter() flowcontrol.RateLimiter { - return c.cl.GetRateLimiter() -} - -// Resource returns an API interface to the specified resource for this client's -// group and version. If resource is not a namespaced resource, then namespace -// is ignored. The ResourceInterface inherits the parameter codec of c. -func (c *Client) Resource(resource *metav1.APIResource, namespace string) ResourceInterface { - return &ResourceClient{ - cl: c.cl, - resource: resource, - ns: namespace, - parameterCodec: c.parameterCodec, - } -} - -// ParameterCodec returns a client with the provided parameter codec. -func (c *Client) ParameterCodec(parameterCodec runtime.ParameterCodec) Interface { - return &Client{ - cl: c.cl, - parameterCodec: parameterCodec, - } -} - -// ResourceClient is an API interface to a specific resource under a -// dynamic client, and implements ResourceInterface. -type ResourceClient struct { - cl *restclient.RESTClient - resource *metav1.APIResource - ns string - parameterCodec runtime.ParameterCodec -} - -func (rc *ResourceClient) parseResourceSubresourceName() (string, []string) { - var resourceName string - var subresourceName []string - if strings.Contains(rc.resource.Name, "/") { - resourceName = strings.Split(rc.resource.Name, "/")[0] - subresourceName = strings.Split(rc.resource.Name, "/")[1:] - } else { - resourceName = rc.resource.Name - } - - return resourceName, subresourceName -} - -// List returns a list of objects for this resource. -func (rc *ResourceClient) List(opts metav1.ListOptions) (runtime.Object, error) { - parameterEncoder := rc.parameterCodec - if parameterEncoder == nil { - parameterEncoder = defaultParameterEncoder - } - return rc.cl.Get(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(rc.resource.Name). - VersionedParams(&opts, parameterEncoder). - Do(). - Get() -} - -// Get gets the resource with the specified name. -func (rc *ResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) { - parameterEncoder := rc.parameterCodec - if parameterEncoder == nil { - parameterEncoder = defaultParameterEncoder - } - result := new(unstructured.Unstructured) - resourceName, subresourceName := rc.parseResourceSubresourceName() - err := rc.cl.Get(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(resourceName). - SubResource(subresourceName...). - VersionedParams(&opts, parameterEncoder). - Name(name). - Do(). - Into(result) - return result, err -} - -// Delete deletes the resource with the specified name. -func (rc *ResourceClient) Delete(name string, opts *metav1.DeleteOptions) error { - return rc.cl.Delete(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(rc.resource.Name). - Name(name). - Body(opts). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (rc *ResourceClient) DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error { - parameterEncoder := rc.parameterCodec - if parameterEncoder == nil { - parameterEncoder = defaultParameterEncoder - } - return rc.cl.Delete(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(rc.resource.Name). - VersionedParams(&listOptions, parameterEncoder). - Body(deleteOptions). - Do(). - Error() -} - -// Create creates the provided resource. -func (rc *ResourceClient) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - result := new(unstructured.Unstructured) - resourceName, subresourceName := rc.parseResourceSubresourceName() - req := rc.cl.Post(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(resourceName). - Body(obj) - if len(subresourceName) > 0 { - // If the provided resource is a subresource, the POST request should contain - // object name. Examples of subresources that support Create operation: - // core/v1/pods/{name}/binding - // core/v1/pods/{name}/eviction - // extensions/v1beta1/deployments/{name}/rollback - // apps/v1beta1/deployments/{name}/rollback - // NOTE: Currently our system assumes every subresource object has the same - // name as the parent resource object. E.g. a pods/binding object having - // metadada.name "foo" means pod "foo" is being bound. We may need to - // change this if we break the assumption in the future. - req = req.SubResource(subresourceName...). - Name(obj.GetName()) - } - err := req.Do(). - Into(result) - return result, err -} - -// Update updates the provided resource. -func (rc *ResourceClient) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - result := new(unstructured.Unstructured) - if len(obj.GetName()) == 0 { - return result, errors.New("object missing name") - } - resourceName, subresourceName := rc.parseResourceSubresourceName() - err := rc.cl.Put(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(resourceName). - SubResource(subresourceName...). - // NOTE: Currently our system assumes every subresource object has the same - // name as the parent resource object. E.g. a pods/binding object having - // metadada.name "foo" means pod "foo" is being bound. We may need to - // change this if we break the assumption in the future. - Name(obj.GetName()). - Body(obj). - Do(). - Into(result) - return result, err -} - -// Watch returns a watch.Interface that watches the resource. -func (rc *ResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - parameterEncoder := rc.parameterCodec - if parameterEncoder == nil { - parameterEncoder = defaultParameterEncoder - } - opts.Watch = true - return rc.cl.Get(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(rc.resource.Name). - VersionedParams(&opts, parameterEncoder). - Watch() -} - -// Patch applies the patch and returns the patched resource. -func (rc *ResourceClient) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) { - result := new(unstructured.Unstructured) - resourceName, subresourceName := rc.parseResourceSubresourceName() - err := rc.cl.Patch(pt). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(resourceName). - SubResource(subresourceName...). - Name(name). - Body(data). - Do(). - Into(result) - return result, err -} - -// dynamicCodec is a codec that wraps the standard unstructured codec -// with special handling for Status objects. -type dynamicCodec struct{} - -func (dynamicCodec) Decode(data []byte, gvk *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { - obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(data, gvk, obj) - if err != nil { - return nil, nil, err - } - - if _, ok := obj.(*metav1.Status); !ok && strings.ToLower(gvk.Kind) == "status" { - obj = &metav1.Status{} - err := json.Unmarshal(data, obj) - if err != nil { - return nil, nil, err - } - } - - return obj, gvk, nil -} - -func (dynamicCodec) Encode(obj runtime.Object, w io.Writer) error { - return unstructured.UnstructuredJSONScheme.Encode(obj, w) -} - -// ContentConfig returns a restclient.ContentConfig for dynamic types. -func ContentConfig() restclient.ContentConfig { - var jsonInfo runtime.SerializerInfo - // TODO: scheme.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need - // to talk to a kubernetes server - for _, info := range scheme.Codecs.SupportedMediaTypes() { - if info.MediaType == runtime.ContentTypeJSON { - jsonInfo = info - break - } - } - - jsonInfo.Serializer = dynamicCodec{} - jsonInfo.PrettySerializer = nil - return restclient.ContentConfig{ - AcceptContentTypes: runtime.ContentTypeJSON, - ContentType: runtime.ContentTypeJSON, - NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo), - } -} - -// paramaterCodec is a codec converts an API object to query -// parameters without trying to convert to the target version. -type parameterCodec struct{} - -func (parameterCodec) EncodeParameters(obj runtime.Object, to schema.GroupVersion) (url.Values, error) { - return queryparams.Convert(obj) -} - -func (parameterCodec) DecodeParameters(parameters url.Values, from schema.GroupVersion, into runtime.Object) error { - return errors.New("DecodeParameters not implemented on dynamic parameterCodec") -} - -var defaultParameterEncoder runtime.ParameterCodec = parameterCodec{} - -type versionedParameterEncoderWithV1Fallback struct{} - -func (versionedParameterEncoderWithV1Fallback) EncodeParameters(obj runtime.Object, to schema.GroupVersion) (url.Values, error) { - ret, err := scheme.ParameterCodec.EncodeParameters(obj, to) - if err != nil && runtime.IsNotRegisteredError(err) { - // fallback to v1 - return scheme.ParameterCodec.EncodeParameters(obj, v1.SchemeGroupVersion) - } - return ret, err -} - -func (versionedParameterEncoderWithV1Fallback) DecodeParameters(parameters url.Values, from schema.GroupVersion, into runtime.Object) error { - return errors.New("DecodeParameters not implemented on versionedParameterEncoderWithV1Fallback") -} - -// VersionedParameterEncoderWithV1Fallback is useful for encoding query -// parameters for custom resources. It tries to convert object to the -// specified version before converting it to query parameters, and falls back to -// converting to v1 if the object is not registered in the specified version. -// For the record, currently API server always treats query parameters sent to a -// custom resource endpoint as v1. -var VersionedParameterEncoderWithV1Fallback runtime.ParameterCodec = versionedParameterEncoderWithV1Fallback{} diff --git a/vendor/k8s.io/client-go/dynamic/client_pool.go b/vendor/k8s.io/client-go/dynamic/client_pool.go deleted file mode 100644 index a5e1b2978..000000000 --- a/vendor/k8s.io/client-go/dynamic/client_pool.go +++ /dev/null @@ -1,122 +0,0 @@ -/* -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 dynamic - -import ( - "sync" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime/schema" - restclient "k8s.io/client-go/rest" -) - -// ClientPool manages a pool of dynamic clients. -type ClientPool interface { - // ClientForGroupVersionResource returns a client configured for the specified groupVersionResource. - // Resource may be empty. - ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error) - // ClientForGroupVersionKind returns a client configured for the specified groupVersionKind. - // Kind may be empty. - ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error) -} - -// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is -// optional. -type APIPathResolverFunc func(kind schema.GroupVersionKind) string - -// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API. -func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string { - if len(kind.Group) == 0 { - return "/api" - } - return "/apis" -} - -// clientPoolImpl implements ClientPool and caches clients for the resource group versions -// is asked to retrieve. This type is thread safe. -type clientPoolImpl struct { - lock sync.RWMutex - config *restclient.Config - clients map[schema.GroupVersion]*Client - apiPathResolverFunc APIPathResolverFunc - mapper meta.RESTMapper -} - -// NewClientPool returns a ClientPool from the specified config. It reuses clients for the same -// group version. It is expected this type may be wrapped by specific logic that special cases certain -// resources or groups. -func NewClientPool(config *restclient.Config, mapper meta.RESTMapper, apiPathResolverFunc APIPathResolverFunc) ClientPool { - confCopy := *config - - return &clientPoolImpl{ - config: &confCopy, - clients: map[schema.GroupVersion]*Client{}, - apiPathResolverFunc: apiPathResolverFunc, - mapper: mapper, - } -} - -// Instantiates a new dynamic client pool with the given config. -func NewDynamicClientPool(cfg *restclient.Config) ClientPool { - // restMapper is not needed when using LegacyAPIPathResolverFunc - emptyMapper := meta.MultiRESTMapper{} - return NewClientPool(cfg, emptyMapper, LegacyAPIPathResolverFunc) -} - -// ClientForGroupVersionResource uses the provided RESTMapper to identify the appropriate resource. Resource may -// be empty. If no matching kind is found the underlying client for that group is still returned. -func (c *clientPoolImpl) ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error) { - kinds, err := c.mapper.KindsFor(resource) - if err != nil { - if meta.IsNoMatchError(err) { - return c.ClientForGroupVersionKind(schema.GroupVersionKind{Group: resource.Group, Version: resource.Version}) - } - return nil, err - } - return c.ClientForGroupVersionKind(kinds[0]) -} - -// ClientForGroupVersion returns a client for the specified groupVersion, creates one if none exists. Kind -// in the GroupVersionKind may be empty. -func (c *clientPoolImpl) ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error) { - c.lock.Lock() - defer c.lock.Unlock() - - gv := kind.GroupVersion() - - // do we have a client already configured? - if existingClient, found := c.clients[gv]; found { - return existingClient, nil - } - - // avoid changing the original config - confCopy := *c.config - conf := &confCopy - - // we need to set the api path based on group version, if no group, default to legacy path - conf.APIPath = c.apiPathResolverFunc(kind) - - // we need to make a client - conf.GroupVersion = &gv - - dynamicClient, err := NewClient(conf) - if err != nil { - return nil, err - } - c.clients[gv] = dynamicClient - return dynamicClient, nil -} diff --git a/vendor/k8s.io/client-go/dynamic/client_test.go b/vendor/k8s.io/client-go/dynamic/client_test.go index ffa550ed5..e8fe93867 100644 --- a/vendor/k8s.io/client-go/dynamic/client_test.go +++ b/vendor/k8s.io/client-go/dynamic/client_test.go @@ -58,11 +58,10 @@ func getObject(version, kind, name string) *unstructured.Unstructured { } } -func getClientServer(gv *schema.GroupVersion, h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) { +func getClientServer(h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) { srv := httptest.NewServer(http.HandlerFunc(h)) - cl, err := NewClient(&restclient.Config{ - Host: srv.URL, - ContentConfig: restclient.ContentConfig{GroupVersion: gv}, + cl, err := NewForConfig(&restclient.Config{ + Host: srv.URL, }) if err != nil { srv.Close() @@ -81,7 +80,7 @@ func TestList(t *testing.T) { }{ { name: "normal_list", - path: "/api/gtest/vtest/rtest", + path: "/apis/gtest/vtest/rtest", resp: getListJSON("vTest", "rTestList", getJSON("vTest", "rTest", "item1"), getJSON("vTest", "rTest", "item2")), @@ -99,7 +98,7 @@ func TestList(t *testing.T) { { name: "namespaced_list", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", resp: getListJSON("vTest", "rTestList", getJSON("vTest", "rTest", "item1"), getJSON("vTest", "rTest", "item2")), @@ -116,9 +115,8 @@ func TestList(t *testing.T) { }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method) } @@ -136,7 +134,7 @@ func TestList(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).List(metav1.ListOptions{}) + got, err := cl.Resource(resource).Namespace(tc.namespace).List(metav1.ListOptions{}) if err != nil { t.Errorf("unexpected error when listing %q: %v", tc.name, err) continue @@ -150,17 +148,18 @@ func TestList(t *testing.T) { func TestGet(t *testing.T) { tcs := []struct { - resource string - namespace string - name string - path string - resp []byte - want *unstructured.Unstructured + resource string + subresource []string + namespace string + name string + path string + resp []byte + want *unstructured.Unstructured }{ { resource: "rtest", name: "normal_get", - path: "/api/gtest/vtest/rtest/normal_get", + path: "/apis/gtest/vtest/rtest/normal_get", resp: getJSON("vTest", "rTest", "normal_get"), want: getObject("vTest", "rTest", "normal_get"), }, @@ -168,30 +167,31 @@ func TestGet(t *testing.T) { resource: "rtest", namespace: "nstest", name: "namespaced_get", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_get", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_get", resp: getJSON("vTest", "rTest", "namespaced_get"), want: getObject("vTest", "rTest", "namespaced_get"), }, { - resource: "rtest/srtest", - name: "normal_subresource_get", - path: "/api/gtest/vtest/rtest/normal_subresource_get/srtest", - resp: getJSON("vTest", "srTest", "normal_subresource_get"), - want: getObject("vTest", "srTest", "normal_subresource_get"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "normal_subresource_get", + path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest", + resp: getJSON("vTest", "srTest", "normal_subresource_get"), + want: getObject("vTest", "srTest", "normal_subresource_get"), }, { - resource: "rtest/srtest", - namespace: "nstest", - name: "namespaced_subresource_get", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest", - resp: getJSON("vTest", "srTest", "namespaced_subresource_get"), - want: getObject("vTest", "srTest", "namespaced_subresource_get"), + resource: "rtest", + subresource: []string{"srtest"}, + namespace: "nstest", + name: "namespaced_subresource_get", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest", + resp: getJSON("vTest", "srTest", "namespaced_subresource_get"), + want: getObject("vTest", "srTest", "namespaced_subresource_get"), }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method) } @@ -209,7 +209,7 @@ func TestGet(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).Get(tc.name, metav1.GetOptions{}) + got, err := cl.Resource(resource).Namespace(tc.namespace).Get(tc.name, metav1.GetOptions{}, tc.subresource...) if err != nil { t.Errorf("unexpected error when getting %q: %v", tc.name, err) continue @@ -222,29 +222,50 @@ func TestGet(t *testing.T) { } func TestDelete(t *testing.T) { + background := metav1.DeletePropagationBackground + uid := types.UID("uid") + statusOK := &metav1.Status{ TypeMeta: metav1.TypeMeta{Kind: "Status"}, Status: metav1.StatusSuccess, } tcs := []struct { - namespace string - name string - path string + subresource []string + namespace string + name string + path string + deleteOptions *metav1.DeleteOptions }{ { name: "normal_delete", - path: "/api/gtest/vtest/rtest/normal_delete", + path: "/apis/gtest/vtest/rtest/normal_delete", }, { namespace: "nstest", name: "namespaced_delete", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_delete", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete", + }, + { + subresource: []string{"srtest"}, + name: "normal_delete", + path: "/apis/gtest/vtest/rtest/normal_delete/srtest", + }, + { + subresource: []string{"srtest"}, + namespace: "nstest", + name: "namespaced_delete", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete/srtest", + }, + { + namespace: "nstest", + name: "namespaced_delete_with_options", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete_with_options", + deleteOptions: &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}, PropagationPolicy: &background}, }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "DELETE" { t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method) } @@ -262,7 +283,7 @@ func TestDelete(t *testing.T) { } defer srv.Close() - err = cl.Resource(resource, tc.namespace).Delete(tc.name, nil) + err = cl.Resource(resource).Namespace(tc.namespace).Delete(tc.name, tc.deleteOptions, tc.subresource...) if err != nil { t.Errorf("unexpected error when deleting %q: %v", tc.name, err) continue @@ -282,18 +303,17 @@ func TestDeleteCollection(t *testing.T) { }{ { name: "normal_delete_collection", - path: "/api/gtest/vtest/rtest", + path: "/apis/gtest/vtest/rtest", }, { namespace: "nstest", name: "namespaced_delete_collection", - path: "/api/gtest/vtest/namespaces/nstest/rtest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "DELETE" { t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method) } @@ -311,7 +331,7 @@ func TestDeleteCollection(t *testing.T) { } defer srv.Close() - err = cl.Resource(resource, tc.namespace).DeleteCollection(nil, metav1.ListOptions{}) + err = cl.Resource(resource).Namespace(tc.namespace).DeleteCollection(nil, metav1.ListOptions{}) if err != nil { t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err) continue @@ -321,43 +341,45 @@ func TestDeleteCollection(t *testing.T) { func TestCreate(t *testing.T) { tcs := []struct { - resource string - name string - namespace string - obj *unstructured.Unstructured - path string + resource string + subresource []string + name string + namespace string + obj *unstructured.Unstructured + path string }{ { resource: "rtest", name: "normal_create", - path: "/api/gtest/vtest/rtest", - obj: getObject("vTest", "rTest", "normal_create"), + path: "/apis/gtest/vtest/rtest", + obj: getObject("gtest/vTest", "rTest", "normal_create"), }, { resource: "rtest", name: "namespaced_create", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest", - obj: getObject("vTest", "rTest", "namespaced_create"), + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + obj: getObject("gtest/vTest", "rTest", "namespaced_create"), }, { - resource: "rtest/srtest", - name: "normal_subresource_create", - path: "/api/gtest/vtest/rtest/normal_subresource_create/srtest", - obj: getObject("vTest", "srTest", "normal_subresource_create"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "normal_subresource_create", + path: "/apis/gtest/vtest/rtest/normal_subresource_create/srtest", + obj: getObject("vTest", "srTest", "normal_subresource_create"), }, { - resource: "rtest/srtest", - name: "namespaced_subresource_create", - namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_create/srtest", - obj: getObject("vTest", "srTest", "namespaced_subresource_create"), + resource: "rtest/", + subresource: []string{"srtest"}, + name: "namespaced_subresource_create", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_create/srtest", + obj: getObject("vTest", "srTest", "namespaced_subresource_create"), }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method) } @@ -382,7 +404,7 @@ func TestCreate(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).Create(tc.obj) + got, err := cl.Resource(resource).Namespace(tc.namespace).Create(tc.obj, tc.subresource...) if err != nil { t.Errorf("unexpected error when creating %q: %v", tc.name, err) continue @@ -396,43 +418,45 @@ func TestCreate(t *testing.T) { func TestUpdate(t *testing.T) { tcs := []struct { - resource string - name string - namespace string - obj *unstructured.Unstructured - path string + resource string + subresource []string + name string + namespace string + obj *unstructured.Unstructured + path string }{ { resource: "rtest", name: "normal_update", - path: "/api/gtest/vtest/rtest/normal_update", - obj: getObject("vTest", "rTest", "normal_update"), + path: "/apis/gtest/vtest/rtest/normal_update", + obj: getObject("gtest/vTest", "rTest", "normal_update"), }, { resource: "rtest", name: "namespaced_update", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_update", - obj: getObject("vTest", "rTest", "namespaced_update"), + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update", + obj: getObject("gtest/vTest", "rTest", "namespaced_update"), }, { - resource: "rtest/srtest", - name: "normal_subresource_update", - path: "/api/gtest/vtest/rtest/normal_update/srtest", - obj: getObject("vTest", "srTest", "normal_update"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "normal_subresource_update", + path: "/apis/gtest/vtest/rtest/normal_update/srtest", + obj: getObject("gtest/vTest", "srTest", "normal_update"), }, { - resource: "rtest/srtest", - name: "namespaced_subresource_update", - namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest", - obj: getObject("vTest", "srTest", "namespaced_update"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "namespaced_subresource_update", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest", + obj: getObject("gtest/vTest", "srTest", "namespaced_update"), }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "PUT" { t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method) } @@ -457,7 +481,7 @@ func TestUpdate(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).Update(tc.obj) + got, err := cl.Resource(resource).Namespace(tc.namespace).Update(tc.obj, tc.subresource...) if err != nil { t.Errorf("unexpected error when updating %q: %v", tc.name, err) continue @@ -479,30 +503,29 @@ func TestWatch(t *testing.T) { }{ { name: "normal_watch", - path: "/api/gtest/vtest/rtest", + path: "/apis/gtest/vtest/rtest", query: "watch=true", events: []watch.Event{ - {Type: watch.Added, Object: getObject("vTest", "rTest", "normal_watch")}, - {Type: watch.Modified, Object: getObject("vTest", "rTest", "normal_watch")}, - {Type: watch.Deleted, Object: getObject("vTest", "rTest", "normal_watch")}, + {Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + {Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + {Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, }, }, { name: "namespaced_watch", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", query: "watch=true", events: []watch.Event{ - {Type: watch.Added, Object: getObject("vTest", "rTest", "namespaced_watch")}, - {Type: watch.Modified, Object: getObject("vTest", "rTest", "namespaced_watch")}, - {Type: watch.Deleted, Object: getObject("vTest", "rTest", "namespaced_watch")}, + {Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + {Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + {Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, }, }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method) } @@ -514,7 +537,7 @@ func TestWatch(t *testing.T) { t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query) } - enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{}) + enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, unstructured.UnstructuredJSONScheme), unstructured.UnstructuredJSONScheme) for _, e := range tc.events { enc.Encode(&e) } @@ -525,7 +548,7 @@ func TestWatch(t *testing.T) { } defer srv.Close() - watcher, err := cl.Resource(resource, tc.namespace).Watch(metav1.ListOptions{}) + watcher, err := cl.Resource(resource).Namespace(tc.namespace).Watch(metav1.ListOptions{}) if err != nil { t.Errorf("unexpected error when watching %q: %v", tc.name, err) continue @@ -542,48 +565,50 @@ func TestWatch(t *testing.T) { func TestPatch(t *testing.T) { tcs := []struct { - resource string - name string - namespace string - patch []byte - want *unstructured.Unstructured - path string + resource string + subresource []string + name string + namespace string + patch []byte + want *unstructured.Unstructured + path string }{ { resource: "rtest", name: "normal_patch", - path: "/api/gtest/vtest/rtest/normal_patch", - patch: getJSON("vTest", "rTest", "normal_patch"), - want: getObject("vTest", "rTest", "normal_patch"), + path: "/apis/gtest/vtest/rtest/normal_patch", + patch: getJSON("gtest/vTest", "rTest", "normal_patch"), + want: getObject("gtest/vTest", "rTest", "normal_patch"), }, { resource: "rtest", name: "namespaced_patch", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_patch", - patch: getJSON("vTest", "rTest", "namespaced_patch"), - want: getObject("vTest", "rTest", "namespaced_patch"), + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_patch", + patch: getJSON("gtest/vTest", "rTest", "namespaced_patch"), + want: getObject("gtest/vTest", "rTest", "namespaced_patch"), }, { - resource: "rtest/srtest", - name: "normal_subresource_patch", - path: "/api/gtest/vtest/rtest/normal_subresource_patch/srtest", - patch: getJSON("vTest", "srTest", "normal_subresource_patch"), - want: getObject("vTest", "srTest", "normal_subresource_patch"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "normal_subresource_patch", + path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest", + patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"), + want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"), }, { - resource: "rtest/srtest", - name: "namespaced_subresource_patch", - namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest", - patch: getJSON("vTest", "srTest", "namespaced_subresource_patch"), - want: getObject("vTest", "srTest", "namespaced_subresource_patch"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "namespaced_subresource_patch", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest", + patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"), + want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"), }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "PATCH" { t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method) } @@ -613,7 +638,7 @@ func TestPatch(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch) + got, err := cl.Resource(resource).Namespace(tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch, tc.subresource...) if err != nil { t.Errorf("unexpected error when patching %q: %v", tc.name, err) continue @@ -624,11 +649,3 @@ func TestPatch(t *testing.T) { } } } - -func TestVersionedParameterEncoderWithV1Fallback(t *testing.T) { - enc := VersionedParameterEncoderWithV1Fallback - _, err := enc.EncodeParameters(&metav1.ListOptions{}, schema.GroupVersion{Group: "foo.bar.com", Version: "v4"}) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } -} diff --git a/vendor/k8s.io/client-go/dynamic/dynamic_util.go b/vendor/k8s.io/client-go/dynamic/dynamic_util.go deleted file mode 100644 index c2cf0daea..000000000 --- a/vendor/k8s.io/client-go/dynamic/dynamic_util.go +++ /dev/null @@ -1,96 +0,0 @@ -/* -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 dynamic - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// VersionInterfaces provides an object converter and metadata -// accessor appropriate for use with unstructured objects. -func VersionInterfaces(schema.GroupVersion) (*meta.VersionInterfaces, error) { - return &meta.VersionInterfaces{ - ObjectConvertor: &unstructured.UnstructuredObjectConverter{}, - MetadataAccessor: meta.NewAccessor(), - }, nil -} - -// NewDiscoveryRESTMapper returns a RESTMapper based on discovery information. -func NewDiscoveryRESTMapper(resources []*metav1.APIResourceList, versionFunc meta.VersionInterfacesFunc) (*meta.DefaultRESTMapper, error) { - rm := meta.NewDefaultRESTMapper(nil, versionFunc) - for _, resourceList := range resources { - gv, err := schema.ParseGroupVersion(resourceList.GroupVersion) - if err != nil { - return nil, err - } - - for _, resource := range resourceList.APIResources { - gvk := gv.WithKind(resource.Kind) - scope := meta.RESTScopeRoot - if resource.Namespaced { - scope = meta.RESTScopeNamespace - } - rm.Add(gvk, scope) - } - } - return rm, nil -} - -// ObjectTyper provides an ObjectTyper implementation for -// unstructured.Unstructured object based on discovery information. -type ObjectTyper struct { - registered map[schema.GroupVersionKind]bool -} - -// NewObjectTyper constructs an ObjectTyper from discovery information. -func NewObjectTyper(resources []*metav1.APIResourceList) (runtime.ObjectTyper, error) { - ot := &ObjectTyper{registered: make(map[schema.GroupVersionKind]bool)} - for _, resourceList := range resources { - gv, err := schema.ParseGroupVersion(resourceList.GroupVersion) - if err != nil { - return nil, err - } - - for _, resource := range resourceList.APIResources { - ot.registered[gv.WithKind(resource.Kind)] = true - } - } - return ot, nil -} - -// ObjectKinds returns a slice of one element with the -// group,version,kind of the provided object, or an error if the -// object is not *unstructured.Unstructured or has no group,version,kind -// information. -func (ot *ObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { - if _, ok := obj.(*unstructured.Unstructured); !ok { - return nil, false, fmt.Errorf("type %T is invalid for determining dynamic object types", obj) - } - return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil -} - -// Recognizes returns true if the provided group,version,kind was in -// the discovery information. -func (ot *ObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool { - return ot.registered[gvk] -} diff --git a/vendor/k8s.io/client-go/dynamic/dynamic_util_test.go b/vendor/k8s.io/client-go/dynamic/dynamic_util_test.go deleted file mode 100644 index cdc68e018..000000000 --- a/vendor/k8s.io/client-go/dynamic/dynamic_util_test.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -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 dynamic - -import ( - "testing" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestDiscoveryRESTMapper(t *testing.T) { - resources := []*metav1.APIResourceList{ - { - GroupVersion: "test/beta1", - APIResources: []metav1.APIResource{ - { - Name: "test_kinds", - Namespaced: true, - Kind: "test_kind", - }, - }, - }, - } - - gvk := schema.GroupVersionKind{ - Group: "test", - Version: "beta1", - Kind: "test_kind", - } - - mapper, err := NewDiscoveryRESTMapper(resources, VersionInterfaces) - if err != nil { - t.Fatalf("unexpected error creating mapper: %s", err) - } - - for _, res := range []schema.GroupVersionResource{ - { - Group: "test", - Version: "beta1", - Resource: "test_kinds", - }, - { - Version: "beta1", - Resource: "test_kinds", - }, - { - Group: "test", - Resource: "test_kinds", - }, - { - Resource: "test_kinds", - }, - } { - got, err := mapper.KindFor(res) - if err != nil { - t.Errorf("KindFor(%#v) unexpected error: %s", res, err) - continue - } - - if got != gvk { - t.Errorf("KindFor(%#v) = %#v; want %#v", res, got, gvk) - } - } -} diff --git a/vendor/k8s.io/client-go/dynamic/fake/BUILD b/vendor/k8s.io/client-go/dynamic/fake/BUILD deleted file mode 100644 index d006188f8..000000000 --- a/vendor/k8s.io/client-go/dynamic/fake/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "client.go", - "client_pool.go", - ], - importpath = "k8s.io/client-go/dynamic/fake", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels: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/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/dynamic:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/dynamic/fake/client.go b/vendor/k8s.io/client-go/dynamic/fake/client.go deleted file mode 100644 index 8399076c2..000000000 --- a/vendor/k8s.io/client-go/dynamic/fake/client.go +++ /dev/null @@ -1,163 +0,0 @@ -/* -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 fake provides a fake client interface to arbitrary Kubernetes -// APIs that exposes common high level operations and exposes common -// metadata. -package fake - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/testing" - "k8s.io/client-go/util/flowcontrol" -) - -// FakeClient is a fake implementation of dynamic.Interface. -type FakeClient struct { - GroupVersion schema.GroupVersion - - *testing.Fake -} - -// GetRateLimiter returns the rate limiter for this client. -func (c *FakeClient) GetRateLimiter() flowcontrol.RateLimiter { - return nil -} - -// Resource returns an API interface to the specified resource for this client's -// group and version. If resource is not a namespaced resource, then namespace -// is ignored. The ResourceClient inherits the parameter codec of this client -func (c *FakeClient) Resource(resource *metav1.APIResource, namespace string) dynamic.ResourceInterface { - return &FakeResourceClient{ - Resource: c.GroupVersion.WithResource(resource.Name), - Kind: c.GroupVersion.WithKind(resource.Kind), - Namespace: namespace, - - Fake: c.Fake, - } -} - -// ParameterCodec returns a client with the provided parameter codec. -func (c *FakeClient) ParameterCodec(parameterCodec runtime.ParameterCodec) dynamic.Interface { - return &FakeClient{ - Fake: c.Fake, - } -} - -// FakeResourceClient is a fake implementation of dynamic.ResourceInterface -type FakeResourceClient struct { - Resource schema.GroupVersionResource - Kind schema.GroupVersionKind - Namespace string - - *testing.Fake -} - -// List returns a list of objects for this resource. -func (c *FakeResourceClient) List(opts metav1.ListOptions) (runtime.Object, error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(c.Resource, c.Kind, c.Namespace, opts), &unstructured.UnstructuredList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &unstructured.UnstructuredList{} - for _, item := range obj.(*unstructured.UnstructuredList).Items { - if label.Matches(labels.Set(item.GetLabels())) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Get gets the resource with the specified name. -func (c *FakeResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(c.Resource, c.Namespace, name), &unstructured.Unstructured{}) - - if obj == nil { - return nil, err - } - - return obj.(*unstructured.Unstructured), err -} - -// Delete deletes the resource with the specified name. -func (c *FakeResourceClient) Delete(name string, opts *metav1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteAction(c.Resource, c.Namespace, name), &unstructured.Unstructured{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeResourceClient) DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteCollectionAction(c.Resource, c.Namespace, listOptions), &unstructured.Unstructured{}) - - return err -} - -// Create creates the provided resource. -func (c *FakeResourceClient) Create(inObj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(c.Resource, c.Namespace, inObj), &unstructured.Unstructured{}) - - if obj == nil { - return nil, err - } - return obj.(*unstructured.Unstructured), err -} - -// Update updates the provided resource. -func (c *FakeResourceClient) Update(inObj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(c.Resource, c.Namespace, inObj), &unstructured.Unstructured{}) - - if obj == nil { - return nil, err - } - return obj.(*unstructured.Unstructured), err -} - -// Watch returns a watch.Interface that watches the resource. -func (c *FakeResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(c.Resource, c.Namespace, opts)) -} - -// Patch patches the provided resource. -func (c *FakeResourceClient) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) { - obj, err := c.Fake. - Invokes(testing.NewPatchAction(c.Resource, c.Namespace, name, data), &unstructured.Unstructured{}) - - if obj == nil { - return nil, err - } - return obj.(*unstructured.Unstructured), err -} diff --git a/vendor/k8s.io/client-go/dynamic/fake/client_pool.go b/vendor/k8s.io/client-go/dynamic/fake/client_pool.go deleted file mode 100644 index 7ec114892..000000000 --- a/vendor/k8s.io/client-go/dynamic/fake/client_pool.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -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 fake provides a fake client interface to arbitrary Kubernetes -// APIs that exposes common high level operations and exposes common -// metadata. -package fake - -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/testing" -) - -// FakeClientPool provides a fake implementation of dynamic.ClientPool. -// It assumes resource GroupVersions are the same as their corresponding kind GroupVersions. -type FakeClientPool struct { - testing.Fake -} - -// ClientForGroupVersionKind returns a client configured for the specified groupVersionResource. -// Resource may be empty. -func (p *FakeClientPool) ClientForGroupVersionResource(resource schema.GroupVersionResource) (dynamic.Interface, error) { - return p.ClientForGroupVersionKind(resource.GroupVersion().WithKind("")) -} - -// ClientForGroupVersionKind returns a client configured for the specified groupVersionKind. -// Kind may be empty. -func (p *FakeClientPool) ClientForGroupVersionKind(kind schema.GroupVersionKind) (dynamic.Interface, error) { - // we can just create a new client every time for testing purposes - return &FakeClient{ - GroupVersion: kind.GroupVersion(), - Fake: &p.Fake, - }, nil -} diff --git a/vendor/k8s.io/client-go/dynamic/fake/simple.go b/vendor/k8s.io/client-go/dynamic/fake/simple.go new file mode 100644 index 000000000..a71cec50e --- /dev/null +++ b/vendor/k8s.io/client-go/dynamic/fake/simple.go @@ -0,0 +1,363 @@ +/* +Copyright 2018 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 fake + +import ( + "strings" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/testing" +) + +func NewSimpleDynamicClient(scheme *runtime.Scheme, objects ...runtime.Object) *FakeDynamicClient { + codecs := serializer.NewCodecFactory(scheme) + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &FakeDynamicClient{} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type FakeDynamicClient struct { + testing.Fake + scheme *runtime.Scheme +} + +type dynamicResourceClient struct { + client *FakeDynamicClient + namespace string + resource schema.GroupVersionResource +} + +var _ dynamic.Interface = &FakeDynamicClient{} + +func (c *FakeDynamicClient) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableResourceInterface { + return &dynamicResourceClient{client: c, resource: resource} +} + +func (c *dynamicResourceClient) Namespace(ns string) dynamic.ResourceInterface { + ret := *c + ret.namespace = ns + return &ret +} + +func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootCreateAction(c.resource, obj), obj) + + case len(c.namespace) == 0 && len(subresources) > 0: + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + name := accessor.GetName() + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), obj), obj) + + case len(c.namespace) > 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewCreateAction(c.resource, c.namespace, obj), obj) + + case len(c.namespace) > 0 && len(subresources) > 0: + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + name := accessor.GetName() + uncastRet, err = c.client.Fake. + Invokes(testing.NewCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), c.namespace, obj), obj) + + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} + +func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootUpdateAction(c.resource, obj), obj) + + case len(c.namespace) == 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), obj), obj) + + case len(c.namespace) > 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewUpdateAction(c.resource, c.namespace, obj), obj) + + case len(c.namespace) > 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, obj), obj) + + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} + +func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(c.resource, "status", obj), obj) + + case len(c.namespace) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewUpdateSubresourceAction(c.resource, "status", c.namespace, obj), obj) + + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} + +func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error { + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + _, err = c.client.Fake. + Invokes(testing.NewRootDeleteAction(c.resource, name), &metav1.Status{Status: "dynamic delete fail"}) + + case len(c.namespace) == 0 && len(subresources) > 0: + _, err = c.client.Fake. + Invokes(testing.NewRootDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic delete fail"}) + + case len(c.namespace) > 0 && len(subresources) == 0: + _, err = c.client.Fake. + Invokes(testing.NewDeleteAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic delete fail"}) + + case len(c.namespace) > 0 && len(subresources) > 0: + _, err = c.client.Fake. + Invokes(testing.NewDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, name), &metav1.Status{Status: "dynamic delete fail"}) + } + + return err +} + +func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error { + var err error + switch { + case len(c.namespace) == 0: + action := testing.NewRootDeleteCollectionAction(c.resource, listOptions) + _, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"}) + + case len(c.namespace) > 0: + action := testing.NewDeleteCollectionAction(c.resource, c.namespace, listOptions) + _, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"}) + + } + + return err +} + +func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootGetAction(c.resource, name), &metav1.Status{Status: "dynamic get fail"}) + + case len(c.namespace) == 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootGetSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"}) + + case len(c.namespace) > 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewGetAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic get fail"}) + + case len(c.namespace) > 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewGetSubresourceAction(c.resource, c.namespace, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"}) + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} + +func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) { + var obj runtime.Object + var err error + switch { + case len(c.namespace) == 0: + obj, err = c.client.Fake. + Invokes(testing.NewRootListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, opts), &metav1.Status{Status: "dynamic list fail"}) + + case len(c.namespace) > 0: + obj, err = c.client.Fake. + Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"}) + + } + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + + retUnstructured := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(obj, retUnstructured, nil); err != nil { + return nil, err + } + entireList, err := retUnstructured.ToList() + if err != nil { + return nil, err + } + + list := &unstructured.UnstructuredList{} + for _, item := range entireList.Items { + metadata, err := meta.Accessor(item) + if err != nil { + return nil, err + } + if label.Matches(labels.Set(metadata.GetLabels())) { + list.Items = append(list.Items, item) + } + } + return list, nil +} + +func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { + switch { + case len(c.namespace) == 0: + return c.client.Fake. + InvokesWatch(testing.NewRootWatchAction(c.resource, opts)) + + case len(c.namespace) > 0: + return c.client.Fake. + InvokesWatch(testing.NewWatchAction(c.resource, c.namespace, opts)) + + } + + panic("math broke") +} + +func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootPatchAction(c.resource, name, data), &metav1.Status{Status: "dynamic patch fail"}) + + case len(c.namespace) == 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"}) + + case len(c.namespace) > 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewPatchAction(c.resource, c.namespace, name, data), &metav1.Status{Status: "dynamic patch fail"}) + + case len(c.namespace) > 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"}) + + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} diff --git a/vendor/k8s.io/client-go/dynamic/interface.go b/vendor/k8s.io/client-go/dynamic/interface.go new file mode 100644 index 000000000..3f364f872 --- /dev/null +++ b/vendor/k8s.io/client-go/dynamic/interface.go @@ -0,0 +1,59 @@ +/* +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 dynamic + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" +) + +type Interface interface { + Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface +} + +type ResourceInterface interface { + Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) + Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) + UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) + Delete(name string, options *metav1.DeleteOptions, subresources ...string) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) + List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) +} + +type NamespaceableResourceInterface interface { + Namespace(string) ResourceInterface + ResourceInterface +} + +// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is optional. +// TODO find a better place to move this for existing callers +type APIPathResolverFunc func(kind schema.GroupVersionKind) string + +// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API. +// TODO find a better place to move this for existing callers +func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string { + if len(kind.Group) == 0 { + return "/api" + } + return "/apis" +} diff --git a/vendor/k8s.io/client-go/dynamic/scheme.go b/vendor/k8s.io/client-go/dynamic/scheme.go new file mode 100644 index 000000000..c4aa081f9 --- /dev/null +++ b/vendor/k8s.io/client-go/dynamic/scheme.go @@ -0,0 +1,98 @@ +/* +Copyright 2018 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 dynamic + +import ( + 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" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/apimachinery/pkg/runtime/serializer/versioning" +) + +var watchScheme = runtime.NewScheme() +var basicScheme = runtime.NewScheme() +var deleteScheme = runtime.NewScheme() +var parameterScheme = runtime.NewScheme() +var deleteOptionsCodec = serializer.NewCodecFactory(deleteScheme) +var dynamicParameterCodec = runtime.NewParameterCodec(parameterScheme) + +var versionV1 = schema.GroupVersion{Version: "v1"} + +func init() { + metav1.AddToGroupVersion(watchScheme, versionV1) + metav1.AddToGroupVersion(basicScheme, versionV1) + metav1.AddToGroupVersion(parameterScheme, versionV1) + metav1.AddToGroupVersion(deleteScheme, versionV1) +} + +var watchJsonSerializerInfo = runtime.SerializerInfo{ + MediaType: "application/json", + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, false), + PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, true), + StreamSerializer: &runtime.StreamSerializerInfo{ + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, false), + Framer: json.Framer, + }, +} + +// watchNegotiatedSerializer is used to read the wrapper of the watch stream +type watchNegotiatedSerializer struct{} + +var watchNegotiatedSerializerInstance = watchNegotiatedSerializer{} + +func (s watchNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { + return []runtime.SerializerInfo{watchJsonSerializerInfo} +} + +func (s watchNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { + return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, nil, gv, nil) +} + +func (s watchNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { + return versioning.NewDefaultingCodecForScheme(watchScheme, nil, decoder, nil, gv) +} + +// basicNegotiatedSerializer is used to handle discovery and error handling serialization +type basicNegotiatedSerializer struct{} + +func (s basicNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { + return []runtime.SerializerInfo{ + { + MediaType: "application/json", + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false), + PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, true), + StreamSerializer: &runtime.StreamSerializerInfo{ + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false), + Framer: json.Framer, + }, + }, + } +} + +func (s basicNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { + return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, nil, gv, nil) +} + +func (s basicNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { + return versioning.NewDefaultingCodecForScheme(watchScheme, nil, decoder, nil, gv) +} diff --git a/vendor/k8s.io/client-go/dynamic/simple.go b/vendor/k8s.io/client-go/dynamic/simple.go new file mode 100644 index 000000000..88e9cc2b0 --- /dev/null +++ b/vendor/k8s.io/client-go/dynamic/simple.go @@ -0,0 +1,287 @@ +/* +Copyright 2018 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 dynamic + +import ( + "io" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer/streaming" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/rest" +) + +type dynamicClient struct { + client *rest.RESTClient +} + +var _ Interface = &dynamicClient{} + +func NewForConfig(inConfig *rest.Config) (Interface, error) { + config := rest.CopyConfig(inConfig) + // for serializing the options + config.GroupVersion = &schema.GroupVersion{} + config.APIPath = "/if-you-see-this-search-for-the-break" + config.AcceptContentTypes = "application/json" + config.ContentType = "application/json" + config.NegotiatedSerializer = basicNegotiatedSerializer{} // this gets used for discovery and error handling types + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + restClient, err := rest.RESTClientFor(config) + if err != nil { + return nil, err + } + + return &dynamicClient{client: restClient}, nil +} + +type dynamicResourceClient struct { + client *dynamicClient + namespace string + resource schema.GroupVersionResource +} + +func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface { + return &dynamicResourceClient{client: c, resource: resource} +} + +func (c *dynamicResourceClient) Namespace(ns string) ResourceInterface { + ret := *c + ret.namespace = ns + return &ret +} + +func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) { + outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) + if err != nil { + return nil, err + } + name := "" + if len(subresources) > 0 { + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + name = accessor.GetName() + } + + result := c.client.client.Post().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(outBytes).Do() + if err := result.Error(); err != nil { + return nil, err + } + + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) { + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) + if err != nil { + return nil, err + } + + result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), subresources...)...).Body(outBytes).Do() + if err := result.Error(); err != nil { + return nil, err + } + + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + + outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) + if err != nil { + return nil, err + } + + result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), "status")...).Body(outBytes).Do() + if err := result.Error(); err != nil { + return nil, err + } + + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error { + if opts == nil { + opts = &metav1.DeleteOptions{} + } + deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts) + if err != nil { + return err + } + + result := c.client.client.Delete().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(deleteOptionsByte).Do() + return result.Error() +} + +func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error { + if opts == nil { + opts = &metav1.DeleteOptions{} + } + deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts) + if err != nil { + return err + } + + result := c.client.client.Delete().AbsPath(c.makeURLSegments("")...).Body(deleteOptionsByte).SpecificallyVersionedParams(&listOptions, dynamicParameterCodec, versionV1).Do() + return result.Error() +} + +func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) { + result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do() + if err := result.Error(); err != nil { + return nil, err + } + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) { + result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do() + if err := result.Error(); err != nil { + return nil, err + } + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + if list, ok := uncastObj.(*unstructured.UnstructuredList); ok { + return list, nil + } + + list, err := uncastObj.(*unstructured.Unstructured).ToList() + if err != nil { + return nil, err + } + return list, nil +} + +func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { + internalGV := schema.GroupVersions{ + {Group: c.resource.Group, Version: runtime.APIVersionInternal}, + // always include the legacy group as a decoding target to handle non-error `Status` return types + {Group: "", Version: runtime.APIVersionInternal}, + } + s := &rest.Serializers{ + Encoder: watchNegotiatedSerializerInstance.EncoderForVersion(watchJsonSerializerInfo.Serializer, c.resource.GroupVersion()), + Decoder: watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV), + + RenegotiatedDecoder: func(contentType string, params map[string]string) (runtime.Decoder, error) { + return watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV), nil + }, + StreamingSerializer: watchJsonSerializerInfo.StreamSerializer.Serializer, + Framer: watchJsonSerializerInfo.StreamSerializer.Framer, + } + + wrappedDecoderFn := func(body io.ReadCloser) streaming.Decoder { + framer := s.Framer.NewFrameReader(body) + return streaming.NewDecoder(framer, s.StreamingSerializer) + } + + opts.Watch = true + return c.client.client.Get().AbsPath(c.makeURLSegments("")...). + SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1). + WatchWithSpecificDecoders(wrappedDecoderFn, unstructured.UnstructuredJSONScheme) +} + +func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) { + result := c.client.client.Patch(pt).AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(data).Do() + if err := result.Error(); err != nil { + return nil, err + } + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) makeURLSegments(name string) []string { + url := []string{} + if len(c.resource.Group) == 0 { + url = append(url, "api") + } else { + url = append(url, "apis", c.resource.Group) + } + url = append(url, c.resource.Version) + + if len(c.namespace) > 0 { + url = append(url, "namespaces", c.namespace) + } + url = append(url, c.resource.Resource) + + if len(name) > 0 { + url = append(url, name) + } + + return url +} diff --git a/vendor/k8s.io/client-go/examples/create-update-delete-deployment/BUILD b/vendor/k8s.io/client-go/examples/create-update-delete-deployment/BUILD deleted file mode 100644 index 2da72ec9f..000000000 --- a/vendor/k8s.io/client-go/examples/create-update-delete-deployment/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "create-update-delete-deployment", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["main.go"], - importpath = "k8s.io/client-go/examples/create-update-delete-deployment", - deps = [ - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - "//vendor/k8s.io/client-go/util/homedir:go_default_library", - "//vendor/k8s.io/client-go/util/retry:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/examples/create-update-delete-deployment/main.go b/vendor/k8s.io/client-go/examples/create-update-delete-deployment/main.go index f6d622745..333ada018 100644 --- a/vendor/k8s.io/client-go/examples/create-update-delete-deployment/main.go +++ b/vendor/k8s.io/client-go/examples/create-update-delete-deployment/main.go @@ -24,7 +24,7 @@ import ( "os" "path/filepath" - appsv1beta1 "k8s.io/api/apps/v1beta1" + appsv1 "k8s.io/api/apps/v1" apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -53,14 +53,19 @@ func main() { panic(err) } - deploymentsClient := clientset.AppsV1beta1().Deployments(apiv1.NamespaceDefault) + deploymentsClient := clientset.AppsV1().Deployments(apiv1.NamespaceDefault) - deployment := &appsv1beta1.Deployment{ + deployment := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "demo-deployment", }, - Spec: appsv1beta1.DeploymentSpec{ + Spec: appsv1.DeploymentSpec{ Replicas: int32Ptr(2), + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "demo", + }, + }, Template: apiv1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ @@ -128,27 +133,6 @@ func main() { } fmt.Println("Updated deployment...") - // Rollback Deployment - prompt() - fmt.Println("Rolling back deployment...") - // Once again use RetryOnConflict to avoid update conflicts - retryErr = retry.RetryOnConflict(retry.DefaultRetry, func() error { - result, getErr := deploymentsClient.Get("demo-deployment", metav1.GetOptions{}) - if getErr != nil { - panic(fmt.Errorf("Failed to get latest version of Deployment: %v", getErr)) - } - - result.Spec.RollbackTo = &appsv1beta1.RollbackConfig{ - Revision: 0, // can be specific revision number, or 0 for last revision - } - _, updateErr := deploymentsClient.Update(result) - return updateErr - }) - if retryErr != nil { - panic(fmt.Errorf("Rollback failed: %v", retryErr)) - } - fmt.Println("Rolled back deployment...") - // List Deployments prompt() fmt.Printf("Listing deployments in namespace %q:\n", apiv1.NamespaceDefault) diff --git a/vendor/k8s.io/client-go/examples/in-cluster-client-configuration/BUILD b/vendor/k8s.io/client-go/examples/in-cluster-client-configuration/BUILD deleted file mode 100644 index f4146ae37..000000000 --- a/vendor/k8s.io/client-go/examples/in-cluster-client-configuration/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "in-cluster-client-configuration", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["main.go"], - importpath = "k8s.io/client-go/examples/in-cluster-client-configuration", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/examples/out-of-cluster-client-configuration/BUILD b/vendor/k8s.io/client-go/examples/out-of-cluster-client-configuration/BUILD deleted file mode 100644 index 2fda9686f..000000000 --- a/vendor/k8s.io/client-go/examples/out-of-cluster-client-configuration/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "out-of-cluster-client-configuration", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["main.go"], - importpath = "k8s.io/client-go/examples/out-of-cluster-client-configuration", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/examples/workqueue/BUILD b/vendor/k8s.io/client-go/examples/workqueue/BUILD deleted file mode 100644 index 8c3c7cb51..000000000 --- a/vendor/k8s.io/client-go/examples/workqueue/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "workqueue", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["main.go"], - importpath = "k8s.io/client-go/examples/workqueue", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - "//vendor/k8s.io/client-go/util/workqueue:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/BUILD b/vendor/k8s.io/client-go/informers/BUILD deleted file mode 100644 index 99486a1c8..000000000 --- a/vendor/k8s.io/client-go/informers/BUILD +++ /dev/null @@ -1,91 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "factory.go", - "generic.go", - ], - importpath = "k8s.io/client-go/informers", - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/api/apps/v1:go_default_library", - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/events/v1beta1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/api/networking/v1:go_default_library", - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/api/storage/v1:go_default_library", - "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/api/storage/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/client-go/informers/admissionregistration:go_default_library", - "//vendor/k8s.io/client-go/informers/apps:go_default_library", - "//vendor/k8s.io/client-go/informers/autoscaling:go_default_library", - "//vendor/k8s.io/client-go/informers/batch:go_default_library", - "//vendor/k8s.io/client-go/informers/certificates:go_default_library", - "//vendor/k8s.io/client-go/informers/core:go_default_library", - "//vendor/k8s.io/client-go/informers/events:go_default_library", - "//vendor/k8s.io/client-go/informers/extensions:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/informers/networking:go_default_library", - "//vendor/k8s.io/client-go/informers/policy:go_default_library", - "//vendor/k8s.io/client-go/informers/rbac:go_default_library", - "//vendor/k8s.io/client-go/informers/scheduling:go_default_library", - "//vendor/k8s.io/client-go/informers/settings:go_default_library", - "//vendor/k8s.io/client-go/informers/storage:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/admissionregistration:all-srcs", - "//staging/src/k8s.io/client-go/informers/apps:all-srcs", - "//staging/src/k8s.io/client-go/informers/autoscaling:all-srcs", - "//staging/src/k8s.io/client-go/informers/batch:all-srcs", - "//staging/src/k8s.io/client-go/informers/certificates:all-srcs", - "//staging/src/k8s.io/client-go/informers/core:all-srcs", - "//staging/src/k8s.io/client-go/informers/events:all-srcs", - "//staging/src/k8s.io/client-go/informers/extensions:all-srcs", - "//staging/src/k8s.io/client-go/informers/internalinterfaces:all-srcs", - "//staging/src/k8s.io/client-go/informers/networking:all-srcs", - "//staging/src/k8s.io/client-go/informers/policy:all-srcs", - "//staging/src/k8s.io/client-go/informers/rbac:all-srcs", - "//staging/src/k8s.io/client-go/informers/scheduling:all-srcs", - "//staging/src/k8s.io/client-go/informers/settings:all-srcs", - "//staging/src/k8s.io/client-go/informers/storage:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/admissionregistration/BUILD b/vendor/k8s.io/client-go/informers/admissionregistration/BUILD deleted file mode 100644 index 6f93c10a2..000000000 --- a/vendor/k8s.io/client-go/informers/admissionregistration/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/admissionregistration", - deps = [ - "//vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/informers/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1:all-srcs", - "//staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/admissionregistration/interface.go b/vendor/k8s.io/client-go/informers/admissionregistration/interface.go index 138dccc26..7a0783cc3 100644 --- a/vendor/k8s.io/client-go/informers/admissionregistration/interface.go +++ b/vendor/k8s.io/client-go/informers/admissionregistration/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/BUILD b/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/BUILD deleted file mode 100644 index 7292f8ca2..000000000 --- a/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "initializerconfiguration.go", - "interface.go", - ], - importpath = "k8s.io/client-go/informers/admissionregistration/v1alpha1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/initializerconfiguration.go b/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/initializerconfiguration.go index 659a04caf..463ca00e7 100644 --- a/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/initializerconfiguration.go +++ b/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/interface.go b/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/interface.go index 54df1caf3..0f47d65d8 100644 --- a/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/interface.go +++ b/vendor/k8s.io/client-go/informers/admissionregistration/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/BUILD b/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/BUILD deleted file mode 100644 index e66e6eb44..000000000 --- a/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "interface.go", - "mutatingwebhookconfiguration.go", - "validatingwebhookconfiguration.go", - ], - importpath = "k8s.io/client-go/informers/admissionregistration/v1beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/interface.go index 5364c1ae1..d1e2b61be 100644 --- a/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go b/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go index 6e65a86c3..58f065de2 100644 --- a/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/validatingwebhookconfiguration.go b/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/validatingwebhookconfiguration.go index 42d16177c..bfa89cef5 100644 --- a/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/validatingwebhookconfiguration.go +++ b/vendor/k8s.io/client-go/informers/admissionregistration/v1beta1/validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/BUILD b/vendor/k8s.io/client-go/informers/apps/BUILD deleted file mode 100644 index 80615b108..000000000 --- a/vendor/k8s.io/client-go/informers/apps/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/apps", - deps = [ - "//vendor/k8s.io/client-go/informers/apps/v1:go_default_library", - "//vendor/k8s.io/client-go/informers/apps/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/informers/apps/v1beta2:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/apps/v1:all-srcs", - "//staging/src/k8s.io/client-go/informers/apps/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/informers/apps/v1beta2:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/apps/interface.go b/vendor/k8s.io/client-go/informers/apps/interface.go index 7013d4d6f..02eefe584 100644 --- a/vendor/k8s.io/client-go/informers/apps/interface.go +++ b/vendor/k8s.io/client-go/informers/apps/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1/BUILD b/vendor/k8s.io/client-go/informers/apps/v1/BUILD deleted file mode 100644 index 233e26101..000000000 --- a/vendor/k8s.io/client-go/informers/apps/v1/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "controllerrevision.go", - "daemonset.go", - "deployment.go", - "interface.go", - "replicaset.go", - "statefulset.go", - ], - importpath = "k8s.io/client-go/informers/apps/v1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/apps/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/apps/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/informers/apps/v1/controllerrevision.go b/vendor/k8s.io/client-go/informers/apps/v1/controllerrevision.go index 3fe6630ff..58bf42146 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1/controllerrevision.go +++ b/vendor/k8s.io/client-go/informers/apps/v1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1/daemonset.go b/vendor/k8s.io/client-go/informers/apps/v1/daemonset.go index 4e10d6f6f..14d890ba3 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1/daemonset.go +++ b/vendor/k8s.io/client-go/informers/apps/v1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1/deployment.go b/vendor/k8s.io/client-go/informers/apps/v1/deployment.go index e08f42ddb..dd8587508 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1/deployment.go +++ b/vendor/k8s.io/client-go/informers/apps/v1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1/interface.go b/vendor/k8s.io/client-go/informers/apps/v1/interface.go index f3abfa9aa..fab1e76bd 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1/interface.go +++ b/vendor/k8s.io/client-go/informers/apps/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1/replicaset.go b/vendor/k8s.io/client-go/informers/apps/v1/replicaset.go index 2a17836cb..b1ab1ebe7 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1/replicaset.go +++ b/vendor/k8s.io/client-go/informers/apps/v1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1/statefulset.go b/vendor/k8s.io/client-go/informers/apps/v1/statefulset.go index e7084af58..f488e3b98 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1/statefulset.go +++ b/vendor/k8s.io/client-go/informers/apps/v1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta1/BUILD b/vendor/k8s.io/client-go/informers/apps/v1beta1/BUILD deleted file mode 100644 index 80ca939e1..000000000 --- a/vendor/k8s.io/client-go/informers/apps/v1beta1/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "controllerrevision.go", - "deployment.go", - "interface.go", - "statefulset.go", - ], - importpath = "k8s.io/client-go/informers/apps/v1beta1", - deps = [ - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/apps/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta1/controllerrevision.go b/vendor/k8s.io/client-go/informers/apps/v1beta1/controllerrevision.go index b4878e724..4283d3822 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta1/controllerrevision.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta1/deployment.go b/vendor/k8s.io/client-go/informers/apps/v1beta1/deployment.go index 589ec39a5..1e7620beb 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta1/deployment.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/apps/v1beta1/interface.go index c0a487ca2..326939cd1 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta1/statefulset.go b/vendor/k8s.io/client-go/informers/apps/v1beta1/statefulset.go index f12364c51..94fd0f93c 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta1/statefulset.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta2/BUILD b/vendor/k8s.io/client-go/informers/apps/v1beta2/BUILD deleted file mode 100644 index 5b0137bb2..000000000 --- a/vendor/k8s.io/client-go/informers/apps/v1beta2/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "controllerrevision.go", - "daemonset.go", - "deployment.go", - "interface.go", - "replicaset.go", - "statefulset.go", - ], - importpath = "k8s.io/client-go/informers/apps/v1beta2", - deps = [ - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/apps/v1beta2:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta2/controllerrevision.go b/vendor/k8s.io/client-go/informers/apps/v1beta2/controllerrevision.go index a2f3ceaac..28e241b18 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta2/controllerrevision.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta2/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta2/daemonset.go b/vendor/k8s.io/client-go/informers/apps/v1beta2/daemonset.go index 700895e61..bb25a1945 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta2/daemonset.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta2/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta2/deployment.go b/vendor/k8s.io/client-go/informers/apps/v1beta2/deployment.go index ba1a3cf9b..457ca30a1 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta2/deployment.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta2/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta2/interface.go b/vendor/k8s.io/client-go/informers/apps/v1beta2/interface.go index 93a1940d9..ded89bd5b 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta2/interface.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta2/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta2/replicaset.go b/vendor/k8s.io/client-go/informers/apps/v1beta2/replicaset.go index 6a46b810b..1558c1416 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta2/replicaset.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta2/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/apps/v1beta2/statefulset.go b/vendor/k8s.io/client-go/informers/apps/v1beta2/statefulset.go index 841cbd8ab..ae929d656 100644 --- a/vendor/k8s.io/client-go/informers/apps/v1beta2/statefulset.go +++ b/vendor/k8s.io/client-go/informers/apps/v1beta2/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/autoscaling/BUILD b/vendor/k8s.io/client-go/informers/autoscaling/BUILD deleted file mode 100644 index 7ad9e975e..000000000 --- a/vendor/k8s.io/client-go/informers/autoscaling/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/autoscaling", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/client-go/informers/autoscaling/v1:go_default_library", - "//vendor/k8s.io/client-go/informers/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/autoscaling/v1:all-srcs", - "//staging/src/k8s.io/client-go/informers/autoscaling/v2beta1:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/informers/autoscaling/interface.go b/vendor/k8s.io/client-go/informers/autoscaling/interface.go index 347d6f628..1494d19d6 100644 --- a/vendor/k8s.io/client-go/informers/autoscaling/interface.go +++ b/vendor/k8s.io/client-go/informers/autoscaling/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/autoscaling/v1/BUILD b/vendor/k8s.io/client-go/informers/autoscaling/v1/BUILD deleted file mode 100644 index 5c3ba46bc..000000000 --- a/vendor/k8s.io/client-go/informers/autoscaling/v1/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "horizontalpodautoscaler.go", - "interface.go", - ], - importpath = "k8s.io/client-go/informers/autoscaling/v1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/autoscaling/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/informers/autoscaling/v1/horizontalpodautoscaler.go b/vendor/k8s.io/client-go/informers/autoscaling/v1/horizontalpodautoscaler.go index 1215c7f3b..71991b7f5 100644 --- a/vendor/k8s.io/client-go/informers/autoscaling/v1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/client-go/informers/autoscaling/v1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/autoscaling/v1/interface.go b/vendor/k8s.io/client-go/informers/autoscaling/v1/interface.go index ffa7a168e..601d0f77f 100644 --- a/vendor/k8s.io/client-go/informers/autoscaling/v1/interface.go +++ b/vendor/k8s.io/client-go/informers/autoscaling/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/BUILD b/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/BUILD deleted file mode 100644 index 3439a4ed2..000000000 --- a/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "horizontalpodautoscaler.go", - "interface.go", - ], - importpath = "k8s.io/client-go/informers/autoscaling/v2beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/horizontalpodautoscaler.go b/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/horizontalpodautoscaler.go index 208757de3..1546eb9b5 100644 --- a/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/interface.go b/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/interface.go index 37ce2bc5f..ff5d44b09 100644 --- a/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/autoscaling/v2beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/batch/BUILD b/vendor/k8s.io/client-go/informers/batch/BUILD deleted file mode 100644 index 9199107c7..000000000 --- a/vendor/k8s.io/client-go/informers/batch/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/batch", - deps = [ - "//vendor/k8s.io/client-go/informers/batch/v1:go_default_library", - "//vendor/k8s.io/client-go/informers/batch/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/informers/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/batch/v1:all-srcs", - "//staging/src/k8s.io/client-go/informers/batch/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/informers/batch/v2alpha1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/batch/interface.go b/vendor/k8s.io/client-go/informers/batch/interface.go index f08227ba4..fa428869d 100644 --- a/vendor/k8s.io/client-go/informers/batch/interface.go +++ b/vendor/k8s.io/client-go/informers/batch/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/batch/v1/BUILD b/vendor/k8s.io/client-go/informers/batch/v1/BUILD deleted file mode 100644 index ed4825488..000000000 --- a/vendor/k8s.io/client-go/informers/batch/v1/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "interface.go", - "job.go", - ], - importpath = "k8s.io/client-go/informers/batch/v1", - deps = [ - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/batch/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/batch/v1/interface.go b/vendor/k8s.io/client-go/informers/batch/v1/interface.go index 5a09dc7ce..67d71adc2 100644 --- a/vendor/k8s.io/client-go/informers/batch/v1/interface.go +++ b/vendor/k8s.io/client-go/informers/batch/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/batch/v1/job.go b/vendor/k8s.io/client-go/informers/batch/v1/job.go index 36d3cef42..6be8a025e 100644 --- a/vendor/k8s.io/client-go/informers/batch/v1/job.go +++ b/vendor/k8s.io/client-go/informers/batch/v1/job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/batch/v1beta1/BUILD b/vendor/k8s.io/client-go/informers/batch/v1beta1/BUILD deleted file mode 100644 index 20f4ac3c4..000000000 --- a/vendor/k8s.io/client-go/informers/batch/v1beta1/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "cronjob.go", - "interface.go", - ], - importpath = "k8s.io/client-go/informers/batch/v1beta1", - deps = [ - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/batch/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/batch/v1beta1/cronjob.go b/vendor/k8s.io/client-go/informers/batch/v1beta1/cronjob.go index 9dfaed490..3ace60109 100644 --- a/vendor/k8s.io/client-go/informers/batch/v1beta1/cronjob.go +++ b/vendor/k8s.io/client-go/informers/batch/v1beta1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/batch/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/batch/v1beta1/interface.go index 3ba8401ac..76cae22d6 100644 --- a/vendor/k8s.io/client-go/informers/batch/v1beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/batch/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/batch/v2alpha1/BUILD b/vendor/k8s.io/client-go/informers/batch/v2alpha1/BUILD deleted file mode 100644 index 4684ca4b4..000000000 --- a/vendor/k8s.io/client-go/informers/batch/v2alpha1/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "cronjob.go", - "interface.go", - ], - importpath = "k8s.io/client-go/informers/batch/v2alpha1", - deps = [ - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/batch/v2alpha1/cronjob.go b/vendor/k8s.io/client-go/informers/batch/v2alpha1/cronjob.go index 82bc9422f..6608e4614 100644 --- a/vendor/k8s.io/client-go/informers/batch/v2alpha1/cronjob.go +++ b/vendor/k8s.io/client-go/informers/batch/v2alpha1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/batch/v2alpha1/interface.go b/vendor/k8s.io/client-go/informers/batch/v2alpha1/interface.go index 3c2780fd2..6c5bf236f 100644 --- a/vendor/k8s.io/client-go/informers/batch/v2alpha1/interface.go +++ b/vendor/k8s.io/client-go/informers/batch/v2alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/certificates/BUILD b/vendor/k8s.io/client-go/informers/certificates/BUILD deleted file mode 100644 index bbe39da8b..000000000 --- a/vendor/k8s.io/client-go/informers/certificates/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/certificates", - deps = [ - "//vendor/k8s.io/client-go/informers/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/certificates/v1beta1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/certificates/interface.go b/vendor/k8s.io/client-go/informers/certificates/interface.go index 9b3121186..cff455403 100644 --- a/vendor/k8s.io/client-go/informers/certificates/interface.go +++ b/vendor/k8s.io/client-go/informers/certificates/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/certificates/v1beta1/BUILD b/vendor/k8s.io/client-go/informers/certificates/v1beta1/BUILD deleted file mode 100644 index d8ada3891..000000000 --- a/vendor/k8s.io/client-go/informers/certificates/v1beta1/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "certificatesigningrequest.go", - "interface.go", - ], - importpath = "k8s.io/client-go/informers/certificates/v1beta1", - deps = [ - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/certificates/v1beta1/certificatesigningrequest.go b/vendor/k8s.io/client-go/informers/certificates/v1beta1/certificatesigningrequest.go index a3d6c2d6a..b442ff788 100644 --- a/vendor/k8s.io/client-go/informers/certificates/v1beta1/certificatesigningrequest.go +++ b/vendor/k8s.io/client-go/informers/certificates/v1beta1/certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/certificates/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/certificates/v1beta1/interface.go index 718f370ee..258dd1d0e 100644 --- a/vendor/k8s.io/client-go/informers/certificates/v1beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/certificates/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/BUILD b/vendor/k8s.io/client-go/informers/core/BUILD deleted file mode 100644 index 694589909..000000000 --- a/vendor/k8s.io/client-go/informers/core/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/core", - deps = [ - "//vendor/k8s.io/client-go/informers/core/v1:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/core/v1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/core/interface.go b/vendor/k8s.io/client-go/informers/core/interface.go index aba68f349..de8396b51 100644 --- a/vendor/k8s.io/client-go/informers/core/interface.go +++ b/vendor/k8s.io/client-go/informers/core/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/BUILD b/vendor/k8s.io/client-go/informers/core/v1/BUILD deleted file mode 100644 index 1d459c5db..000000000 --- a/vendor/k8s.io/client-go/informers/core/v1/BUILD +++ /dev/null @@ -1,53 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "componentstatus.go", - "configmap.go", - "endpoints.go", - "event.go", - "interface.go", - "limitrange.go", - "namespace.go", - "node.go", - "persistentvolume.go", - "persistentvolumeclaim.go", - "pod.go", - "podtemplate.go", - "replicationcontroller.go", - "resourcequota.go", - "secret.go", - "service.go", - "serviceaccount.go", - ], - importpath = "k8s.io/client-go/informers/core/v1", - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/core/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/core/v1/componentstatus.go b/vendor/k8s.io/client-go/informers/core/v1/componentstatus.go index 33fc65a52..cc60d480f 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/componentstatus.go +++ b/vendor/k8s.io/client-go/informers/core/v1/componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/configmap.go b/vendor/k8s.io/client-go/informers/core/v1/configmap.go index 618e74994..ebd86c2d8 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/configmap.go +++ b/vendor/k8s.io/client-go/informers/core/v1/configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/endpoints.go b/vendor/k8s.io/client-go/informers/core/v1/endpoints.go index fa56fbc25..b7362d080 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/endpoints.go +++ b/vendor/k8s.io/client-go/informers/core/v1/endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/event.go b/vendor/k8s.io/client-go/informers/core/v1/event.go index 515784175..905db2dba 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/event.go +++ b/vendor/k8s.io/client-go/informers/core/v1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/interface.go b/vendor/k8s.io/client-go/informers/core/v1/interface.go index 9580dd9e0..b2216a05c 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/interface.go +++ b/vendor/k8s.io/client-go/informers/core/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/limitrange.go b/vendor/k8s.io/client-go/informers/core/v1/limitrange.go index 8edffdfb7..39d0340df 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/limitrange.go +++ b/vendor/k8s.io/client-go/informers/core/v1/limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/namespace.go b/vendor/k8s.io/client-go/informers/core/v1/namespace.go index e1925fed1..5830c88f5 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/namespace.go +++ b/vendor/k8s.io/client-go/informers/core/v1/namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/node.go b/vendor/k8s.io/client-go/informers/core/v1/node.go index dc829bcd6..202cb3b7b 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/node.go +++ b/vendor/k8s.io/client-go/informers/core/v1/node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/persistentvolume.go b/vendor/k8s.io/client-go/informers/core/v1/persistentvolume.go index b3ed3c0d0..3f9af92a3 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/persistentvolume.go +++ b/vendor/k8s.io/client-go/informers/core/v1/persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/persistentvolumeclaim.go b/vendor/k8s.io/client-go/informers/core/v1/persistentvolumeclaim.go index 9b4fde573..b4946e849 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/persistentvolumeclaim.go +++ b/vendor/k8s.io/client-go/informers/core/v1/persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/pod.go b/vendor/k8s.io/client-go/informers/core/v1/pod.go index 18e61b225..e964d5812 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/pod.go +++ b/vendor/k8s.io/client-go/informers/core/v1/pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/podtemplate.go b/vendor/k8s.io/client-go/informers/core/v1/podtemplate.go index a7de79b18..542fd032e 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/podtemplate.go +++ b/vendor/k8s.io/client-go/informers/core/v1/podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/replicationcontroller.go b/vendor/k8s.io/client-go/informers/core/v1/replicationcontroller.go index df0a1d604..c5c009b07 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/replicationcontroller.go +++ b/vendor/k8s.io/client-go/informers/core/v1/replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/resourcequota.go b/vendor/k8s.io/client-go/informers/core/v1/resourcequota.go index 89a56acb8..85ea9098b 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/resourcequota.go +++ b/vendor/k8s.io/client-go/informers/core/v1/resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/secret.go b/vendor/k8s.io/client-go/informers/core/v1/secret.go index 05939c861..6c0c5a847 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/secret.go +++ b/vendor/k8s.io/client-go/informers/core/v1/secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/service.go b/vendor/k8s.io/client-go/informers/core/v1/service.go index 0e8aa0f7a..c2bb80250 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/service.go +++ b/vendor/k8s.io/client-go/informers/core/v1/service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/core/v1/serviceaccount.go b/vendor/k8s.io/client-go/informers/core/v1/serviceaccount.go index bf3b5a7bb..2d0b94a63 100644 --- a/vendor/k8s.io/client-go/informers/core/v1/serviceaccount.go +++ b/vendor/k8s.io/client-go/informers/core/v1/serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/events/BUILD b/vendor/k8s.io/client-go/informers/events/BUILD deleted file mode 100644 index cf87d7c56..000000000 --- a/vendor/k8s.io/client-go/informers/events/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/events", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/client-go/informers/events/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/events/v1beta1:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/informers/events/interface.go b/vendor/k8s.io/client-go/informers/events/interface.go index e8ad97c3c..af30a3913 100644 --- a/vendor/k8s.io/client-go/informers/events/interface.go +++ b/vendor/k8s.io/client-go/informers/events/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/events/v1beta1/BUILD b/vendor/k8s.io/client-go/informers/events/v1beta1/BUILD deleted file mode 100644 index 7f398d3ef..000000000 --- a/vendor/k8s.io/client-go/informers/events/v1beta1/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "event.go", - "interface.go", - ], - importpath = "k8s.io/client-go/informers/events/v1beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/events/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/events/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/informers/events/v1beta1/event.go b/vendor/k8s.io/client-go/informers/events/v1beta1/event.go index 8f2b27cf5..cb757c5bc 100644 --- a/vendor/k8s.io/client-go/informers/events/v1beta1/event.go +++ b/vendor/k8s.io/client-go/informers/events/v1beta1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/events/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/events/v1beta1/interface.go index 0c67badb2..c71888c9a 100644 --- a/vendor/k8s.io/client-go/informers/events/v1beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/events/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/extensions/BUILD b/vendor/k8s.io/client-go/informers/extensions/BUILD deleted file mode 100644 index 070358e20..000000000 --- a/vendor/k8s.io/client-go/informers/extensions/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/extensions", - deps = [ - "//vendor/k8s.io/client-go/informers/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/extensions/v1beta1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/extensions/interface.go b/vendor/k8s.io/client-go/informers/extensions/interface.go index 93d912ca5..94a66d385 100644 --- a/vendor/k8s.io/client-go/informers/extensions/interface.go +++ b/vendor/k8s.io/client-go/informers/extensions/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/extensions/v1beta1/BUILD b/vendor/k8s.io/client-go/informers/extensions/v1beta1/BUILD deleted file mode 100644 index 7f11d7bdf..000000000 --- a/vendor/k8s.io/client-go/informers/extensions/v1beta1/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "daemonset.go", - "deployment.go", - "ingress.go", - "interface.go", - "podsecuritypolicy.go", - "replicaset.go", - ], - importpath = "k8s.io/client-go/informers/extensions/v1beta1", - deps = [ - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/extensions/v1beta1/daemonset.go b/vendor/k8s.io/client-go/informers/extensions/v1beta1/daemonset.go index 0f24af5ca..3064384b2 100644 --- a/vendor/k8s.io/client-go/informers/extensions/v1beta1/daemonset.go +++ b/vendor/k8s.io/client-go/informers/extensions/v1beta1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/extensions/v1beta1/deployment.go b/vendor/k8s.io/client-go/informers/extensions/v1beta1/deployment.go index 980eecb0f..a6b8b68e6 100644 --- a/vendor/k8s.io/client-go/informers/extensions/v1beta1/deployment.go +++ b/vendor/k8s.io/client-go/informers/extensions/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/extensions/v1beta1/ingress.go b/vendor/k8s.io/client-go/informers/extensions/v1beta1/ingress.go index b250d22a3..ec8147c19 100644 --- a/vendor/k8s.io/client-go/informers/extensions/v1beta1/ingress.go +++ b/vendor/k8s.io/client-go/informers/extensions/v1beta1/ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/extensions/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/extensions/v1beta1/interface.go index 10aa1b704..a259d27ae 100644 --- a/vendor/k8s.io/client-go/informers/extensions/v1beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/extensions/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/extensions/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/client-go/informers/extensions/v1beta1/podsecuritypolicy.go index 76b83b823..15414d8ed 100644 --- a/vendor/k8s.io/client-go/informers/extensions/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/client-go/informers/extensions/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/extensions/v1beta1/replicaset.go b/vendor/k8s.io/client-go/informers/extensions/v1beta1/replicaset.go index 31c6a1b86..a63d769e5 100644 --- a/vendor/k8s.io/client-go/informers/extensions/v1beta1/replicaset.go +++ b/vendor/k8s.io/client-go/informers/extensions/v1beta1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/factory.go b/vendor/k8s.io/client-go/informers/factory.go index 455afc2b9..902195d6c 100644 --- a/vendor/k8s.io/client-go/informers/factory.go +++ b/vendor/k8s.io/client-go/informers/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -45,12 +45,16 @@ import ( cache "k8s.io/client-go/tools/cache" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client kubernetes.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -58,23 +62,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client kubernetes.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client kubernetes.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client kubernetes.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -123,7 +166,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/client-go/informers/generic.go b/vendor/k8s.io/client-go/informers/generic.go index 801267edf..08c43906f 100644 --- a/vendor/k8s.io/client-go/informers/generic.go +++ b/vendor/k8s.io/client-go/informers/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -41,6 +41,7 @@ import ( rbac_v1alpha1 "k8s.io/api/rbac/v1alpha1" rbac_v1beta1 "k8s.io/api/rbac/v1beta1" scheduling_v1alpha1 "k8s.io/api/scheduling/v1alpha1" + scheduling_v1beta1 "k8s.io/api/scheduling/v1beta1" settings_v1alpha1 "k8s.io/api/settings/v1alpha1" storage_v1 "k8s.io/api/storage/v1" storage_v1alpha1 "k8s.io/api/storage/v1alpha1" @@ -235,6 +236,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case scheduling_v1alpha1.SchemeGroupVersion.WithResource("priorityclasses"): return &genericInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1alpha1().PriorityClasses().Informer()}, nil + // Group=scheduling.k8s.io, Version=v1beta1 + case scheduling_v1beta1.SchemeGroupVersion.WithResource("priorityclasses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1beta1().PriorityClasses().Informer()}, nil + // Group=settings.k8s.io, Version=v1alpha1 case settings_v1alpha1.SchemeGroupVersion.WithResource("podpresets"): return &genericInformer{resource: resource.GroupResource(), informer: f.Settings().V1alpha1().PodPresets().Informer()}, nil diff --git a/vendor/k8s.io/client-go/informers/internalinterfaces/BUILD b/vendor/k8s.io/client-go/informers/internalinterfaces/BUILD deleted file mode 100644 index 5b20c78f7..000000000 --- a/vendor/k8s.io/client-go/informers/internalinterfaces/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["factory_interfaces.go"], - importpath = "k8s.io/client-go/informers/internalinterfaces", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/client-go/informers/internalinterfaces/factory_interfaces.go index 4e2a28fc7..5e05516b1 100644 --- a/vendor/k8s.io/client-go/informers/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/client-go/informers/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/networking/BUILD b/vendor/k8s.io/client-go/informers/networking/BUILD deleted file mode 100644 index 3219e7d02..000000000 --- a/vendor/k8s.io/client-go/informers/networking/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/networking", - deps = [ - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/informers/networking/v1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/networking/v1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/networking/interface.go b/vendor/k8s.io/client-go/informers/networking/interface.go index 0f6c45649..989e8fa0f 100644 --- a/vendor/k8s.io/client-go/informers/networking/interface.go +++ b/vendor/k8s.io/client-go/informers/networking/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/networking/v1/BUILD b/vendor/k8s.io/client-go/informers/networking/v1/BUILD deleted file mode 100644 index dc6f32696..000000000 --- a/vendor/k8s.io/client-go/informers/networking/v1/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "interface.go", - "networkpolicy.go", - ], - importpath = "k8s.io/client-go/informers/networking/v1", - deps = [ - "//vendor/k8s.io/api/networking/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/networking/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/networking/v1/interface.go b/vendor/k8s.io/client-go/informers/networking/v1/interface.go index 819a86146..84dc6476a 100644 --- a/vendor/k8s.io/client-go/informers/networking/v1/interface.go +++ b/vendor/k8s.io/client-go/informers/networking/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/networking/v1/networkpolicy.go b/vendor/k8s.io/client-go/informers/networking/v1/networkpolicy.go index 20ac9909d..51e0bdf19 100644 --- a/vendor/k8s.io/client-go/informers/networking/v1/networkpolicy.go +++ b/vendor/k8s.io/client-go/informers/networking/v1/networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/policy/BUILD b/vendor/k8s.io/client-go/informers/policy/BUILD deleted file mode 100644 index 882d54d5e..000000000 --- a/vendor/k8s.io/client-go/informers/policy/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/policy", - deps = [ - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/informers/policy/v1beta1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/policy/v1beta1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/policy/interface.go b/vendor/k8s.io/client-go/informers/policy/interface.go index e77ab2b24..1859fca82 100644 --- a/vendor/k8s.io/client-go/informers/policy/interface.go +++ b/vendor/k8s.io/client-go/informers/policy/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/policy/v1beta1/BUILD b/vendor/k8s.io/client-go/informers/policy/v1beta1/BUILD deleted file mode 100644 index 547a0a397..000000000 --- a/vendor/k8s.io/client-go/informers/policy/v1beta1/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "interface.go", - "poddisruptionbudget.go", - "podsecuritypolicy.go", - ], - importpath = "k8s.io/client-go/informers/policy/v1beta1", - deps = [ - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/policy/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/policy/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/policy/v1beta1/interface.go index b368f068f..a6c1825d2 100644 --- a/vendor/k8s.io/client-go/informers/policy/v1beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/policy/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/policy/v1beta1/poddisruptionbudget.go b/vendor/k8s.io/client-go/informers/policy/v1beta1/poddisruptionbudget.go index d5178652a..d305e617b 100644 --- a/vendor/k8s.io/client-go/informers/policy/v1beta1/poddisruptionbudget.go +++ b/vendor/k8s.io/client-go/informers/policy/v1beta1/poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/policy/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/client-go/informers/policy/v1beta1/podsecuritypolicy.go index c9bcc8bab..12a16acde 100644 --- a/vendor/k8s.io/client-go/informers/policy/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/client-go/informers/policy/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/BUILD b/vendor/k8s.io/client-go/informers/rbac/BUILD deleted file mode 100644 index e2afef934..000000000 --- a/vendor/k8s.io/client-go/informers/rbac/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/rbac", - deps = [ - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/informers/rbac/v1:go_default_library", - "//vendor/k8s.io/client-go/informers/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/informers/rbac/v1beta1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/rbac/v1:all-srcs", - "//staging/src/k8s.io/client-go/informers/rbac/v1alpha1:all-srcs", - "//staging/src/k8s.io/client-go/informers/rbac/v1beta1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/rbac/interface.go b/vendor/k8s.io/client-go/informers/rbac/interface.go index ac491ee42..228811f8a 100644 --- a/vendor/k8s.io/client-go/informers/rbac/interface.go +++ b/vendor/k8s.io/client-go/informers/rbac/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1/BUILD b/vendor/k8s.io/client-go/informers/rbac/v1/BUILD deleted file mode 100644 index 4278890e8..000000000 --- a/vendor/k8s.io/client-go/informers/rbac/v1/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clusterrole.go", - "clusterrolebinding.go", - "interface.go", - "role.go", - "rolebinding.go", - ], - importpath = "k8s.io/client-go/informers/rbac/v1", - deps = [ - "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/rbac/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/rbac/v1/clusterrole.go b/vendor/k8s.io/client-go/informers/rbac/v1/clusterrole.go index f541957a2..d5e10cadd 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1/clusterrole.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1/clusterrolebinding.go b/vendor/k8s.io/client-go/informers/rbac/v1/clusterrolebinding.go index bf1d7bdc1..027d11b60 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1/clusterrolebinding.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1/interface.go b/vendor/k8s.io/client-go/informers/rbac/v1/interface.go index fca0e807b..7f99c9454 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1/interface.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1/role.go b/vendor/k8s.io/client-go/informers/rbac/v1/role.go index f08e1fde3..9c9f4f84b 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1/role.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1/rolebinding.go b/vendor/k8s.io/client-go/informers/rbac/v1/rolebinding.go index f91c2ef03..73cd3056d 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1/rolebinding.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/BUILD b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/BUILD deleted file mode 100644 index 345e10c6f..000000000 --- a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clusterrole.go", - "clusterrolebinding.go", - "interface.go", - "role.go", - "rolebinding.go", - ], - importpath = "k8s.io/client-go/informers/rbac/v1alpha1", - deps = [ - "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/clusterrole.go b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/clusterrole.go index 9293439f4..76aa466cd 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/clusterrole.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/clusterrolebinding.go b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/clusterrolebinding.go index d13561274..851eb39dc 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/clusterrolebinding.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/interface.go b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/interface.go index 1c972ec82..d27c79987 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/interface.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/role.go b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/role.go index 5b4148fa9..be847445e 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/role.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/rolebinding.go b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/rolebinding.go index 54bae16e7..20e7159e3 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1alpha1/rolebinding.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1alpha1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1beta1/BUILD b/vendor/k8s.io/client-go/informers/rbac/v1beta1/BUILD deleted file mode 100644 index 0ed73f4ec..000000000 --- a/vendor/k8s.io/client-go/informers/rbac/v1beta1/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clusterrole.go", - "clusterrolebinding.go", - "interface.go", - "role.go", - "rolebinding.go", - ], - importpath = "k8s.io/client-go/informers/rbac/v1beta1", - deps = [ - "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/rbac/v1beta1/clusterrole.go b/vendor/k8s.io/client-go/informers/rbac/v1beta1/clusterrole.go index f429eeca1..d79c75c9b 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1beta1/clusterrole.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1beta1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1beta1/clusterrolebinding.go b/vendor/k8s.io/client-go/informers/rbac/v1beta1/clusterrolebinding.go index 5900eae9a..f6b64816b 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1beta1/clusterrolebinding.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1beta1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/rbac/v1beta1/interface.go index c36d644e1..04add43af 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1beta1/role.go b/vendor/k8s.io/client-go/informers/rbac/v1beta1/role.go index 479044b42..fc1c56879 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1beta1/role.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1beta1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/rbac/v1beta1/rolebinding.go b/vendor/k8s.io/client-go/informers/rbac/v1beta1/rolebinding.go index 34feed183..9bbf70200 100644 --- a/vendor/k8s.io/client-go/informers/rbac/v1beta1/rolebinding.go +++ b/vendor/k8s.io/client-go/informers/rbac/v1beta1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/scheduling/BUILD b/vendor/k8s.io/client-go/informers/scheduling/BUILD deleted file mode 100644 index 14c2a70b9..000000000 --- a/vendor/k8s.io/client-go/informers/scheduling/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/scheduling", - deps = [ - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/informers/scheduling/v1alpha1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/scheduling/v1alpha1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/scheduling/interface.go b/vendor/k8s.io/client-go/informers/scheduling/interface.go index 89aaac195..16d030c30 100644 --- a/vendor/k8s.io/client-go/informers/scheduling/interface.go +++ b/vendor/k8s.io/client-go/informers/scheduling/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,12 +21,15 @@ package scheduling import ( internalinterfaces "k8s.io/client-go/informers/internalinterfaces" v1alpha1 "k8s.io/client-go/informers/scheduling/v1alpha1" + v1beta1 "k8s.io/client-go/informers/scheduling/v1beta1" ) // Interface provides access to each of this group's versions. type Interface interface { // V1alpha1 provides access to shared informers for resources in V1alpha1. V1alpha1() v1alpha1.Interface + // V1beta1 provides access to shared informers for resources in V1beta1. + V1beta1() v1beta1.Interface } type group struct { @@ -44,3 +47,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList func (g *group) V1alpha1() v1alpha1.Interface { return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) } + +// V1beta1 returns a new v1beta1.Interface. +func (g *group) V1beta1() v1beta1.Interface { + return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/BUILD b/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/BUILD deleted file mode 100644 index b168cda49..000000000 --- a/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "interface.go", - "priorityclass.go", - ], - importpath = "k8s.io/client-go/informers/scheduling/v1alpha1", - deps = [ - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/interface.go b/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/interface.go index 091dd90b6..cd908d14e 100644 --- a/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/interface.go +++ b/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/priorityclass.go b/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/priorityclass.go index 8a27631be..481df0499 100644 --- a/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/priorityclass.go +++ b/vendor/k8s.io/client-go/informers/scheduling/v1alpha1/priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/scheduling/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/scheduling/v1beta1/interface.go new file mode 100644 index 000000000..52840a9ce --- /dev/null +++ b/vendor/k8s.io/client-go/informers/scheduling/v1beta1/interface.go @@ -0,0 +1,45 @@ +/* +Copyright 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1beta1 + +import ( + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // PriorityClasses returns a PriorityClassInformer. + PriorityClasses() PriorityClassInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// PriorityClasses returns a PriorityClassInformer. +func (v *version) PriorityClasses() PriorityClassInformer { + return &priorityClassInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/k8s.io/client-go/informers/scheduling/v1beta1/priorityclass.go b/vendor/k8s.io/client-go/informers/scheduling/v1beta1/priorityclass.go new file mode 100644 index 000000000..ff61e58de --- /dev/null +++ b/vendor/k8s.io/client-go/informers/scheduling/v1beta1/priorityclass.go @@ -0,0 +1,88 @@ +/* +Copyright 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1beta1 + +import ( + time "time" + + scheduling_v1beta1 "k8s.io/api/scheduling/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" + kubernetes "k8s.io/client-go/kubernetes" + v1beta1 "k8s.io/client-go/listers/scheduling/v1beta1" + cache "k8s.io/client-go/tools/cache" +) + +// PriorityClassInformer provides access to a shared informer and lister for +// PriorityClasses. +type PriorityClassInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1beta1.PriorityClassLister +} + +type priorityClassInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewPriorityClassInformer constructs a new informer for PriorityClass type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewPriorityClassInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredPriorityClassInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredPriorityClassInformer constructs a new informer for PriorityClass type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredPriorityClassInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SchedulingV1beta1().PriorityClasses().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SchedulingV1beta1().PriorityClasses().Watch(options) + }, + }, + &scheduling_v1beta1.PriorityClass{}, + resyncPeriod, + indexers, + ) +} + +func (f *priorityClassInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredPriorityClassInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *priorityClassInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&scheduling_v1beta1.PriorityClass{}, f.defaultInformer) +} + +func (f *priorityClassInformer) Lister() v1beta1.PriorityClassLister { + return v1beta1.NewPriorityClassLister(f.Informer().GetIndexer()) +} diff --git a/vendor/k8s.io/client-go/informers/settings/BUILD b/vendor/k8s.io/client-go/informers/settings/BUILD deleted file mode 100644 index 5dc3cfd14..000000000 --- a/vendor/k8s.io/client-go/informers/settings/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/settings", - deps = [ - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/informers/settings/v1alpha1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/settings/v1alpha1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/settings/interface.go b/vendor/k8s.io/client-go/informers/settings/interface.go index cc134f706..d91e49867 100644 --- a/vendor/k8s.io/client-go/informers/settings/interface.go +++ b/vendor/k8s.io/client-go/informers/settings/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/settings/v1alpha1/BUILD b/vendor/k8s.io/client-go/informers/settings/v1alpha1/BUILD deleted file mode 100644 index fd24549e8..000000000 --- a/vendor/k8s.io/client-go/informers/settings/v1alpha1/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "interface.go", - "podpreset.go", - ], - importpath = "k8s.io/client-go/informers/settings/v1alpha1", - deps = [ - "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/settings/v1alpha1/interface.go b/vendor/k8s.io/client-go/informers/settings/v1alpha1/interface.go index d2964352a..250220469 100644 --- a/vendor/k8s.io/client-go/informers/settings/v1alpha1/interface.go +++ b/vendor/k8s.io/client-go/informers/settings/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/settings/v1alpha1/podpreset.go b/vendor/k8s.io/client-go/informers/settings/v1alpha1/podpreset.go index 7e241b2be..c4596c828 100644 --- a/vendor/k8s.io/client-go/informers/settings/v1alpha1/podpreset.go +++ b/vendor/k8s.io/client-go/informers/settings/v1alpha1/podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/storage/BUILD b/vendor/k8s.io/client-go/informers/storage/BUILD deleted file mode 100644 index 56e9e1850..000000000 --- a/vendor/k8s.io/client-go/informers/storage/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importpath = "k8s.io/client-go/informers/storage", - deps = [ - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/informers/storage/v1:go_default_library", - "//vendor/k8s.io/client-go/informers/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/informers/storage/v1beta1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/informers/storage/v1:all-srcs", - "//staging/src/k8s.io/client-go/informers/storage/v1alpha1:all-srcs", - "//staging/src/k8s.io/client-go/informers/storage/v1beta1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/storage/interface.go b/vendor/k8s.io/client-go/informers/storage/interface.go index 6581a2a8d..8245aa60c 100644 --- a/vendor/k8s.io/client-go/informers/storage/interface.go +++ b/vendor/k8s.io/client-go/informers/storage/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/storage/v1/BUILD b/vendor/k8s.io/client-go/informers/storage/v1/BUILD deleted file mode 100644 index 29c0b883d..000000000 --- a/vendor/k8s.io/client-go/informers/storage/v1/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "interface.go", - "storageclass.go", - ], - importpath = "k8s.io/client-go/informers/storage/v1", - deps = [ - "//vendor/k8s.io/api/storage/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/storage/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/storage/v1/interface.go b/vendor/k8s.io/client-go/informers/storage/v1/interface.go index ebdb1d98a..d7e4b5c49 100644 --- a/vendor/k8s.io/client-go/informers/storage/v1/interface.go +++ b/vendor/k8s.io/client-go/informers/storage/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/storage/v1/storageclass.go b/vendor/k8s.io/client-go/informers/storage/v1/storageclass.go index 5ef571eb4..ae90b53b4 100644 --- a/vendor/k8s.io/client-go/informers/storage/v1/storageclass.go +++ b/vendor/k8s.io/client-go/informers/storage/v1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/storage/v1alpha1/BUILD b/vendor/k8s.io/client-go/informers/storage/v1alpha1/BUILD deleted file mode 100644 index 1871ff496..000000000 --- a/vendor/k8s.io/client-go/informers/storage/v1alpha1/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "interface.go", - "volumeattachment.go", - ], - importpath = "k8s.io/client-go/informers/storage/v1alpha1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/informers/storage/v1alpha1/interface.go b/vendor/k8s.io/client-go/informers/storage/v1alpha1/interface.go index f1b1a9bbd..d389b73fa 100644 --- a/vendor/k8s.io/client-go/informers/storage/v1alpha1/interface.go +++ b/vendor/k8s.io/client-go/informers/storage/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/storage/v1alpha1/volumeattachment.go b/vendor/k8s.io/client-go/informers/storage/v1alpha1/volumeattachment.go index 506517acd..01c468582 100644 --- a/vendor/k8s.io/client-go/informers/storage/v1alpha1/volumeattachment.go +++ b/vendor/k8s.io/client-go/informers/storage/v1alpha1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/storage/v1beta1/BUILD b/vendor/k8s.io/client-go/informers/storage/v1beta1/BUILD deleted file mode 100644 index 64aae5165..000000000 --- a/vendor/k8s.io/client-go/informers/storage/v1beta1/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "interface.go", - "storageclass.go", - "volumeattachment.go", - ], - importpath = "k8s.io/client-go/informers/storage/v1beta1", - deps = [ - "//vendor/k8s.io/api/storage/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/listers/storage/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/informers/storage/v1beta1/interface.go b/vendor/k8s.io/client-go/informers/storage/v1beta1/interface.go index 5a63728f1..aa11c2bb6 100644 --- a/vendor/k8s.io/client-go/informers/storage/v1beta1/interface.go +++ b/vendor/k8s.io/client-go/informers/storage/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/storage/v1beta1/storageclass.go b/vendor/k8s.io/client-go/informers/storage/v1beta1/storageclass.go index 0b4edbf52..1c2f3490c 100644 --- a/vendor/k8s.io/client-go/informers/storage/v1beta1/storageclass.go +++ b/vendor/k8s.io/client-go/informers/storage/v1beta1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/informers/storage/v1beta1/volumeattachment.go b/vendor/k8s.io/client-go/informers/storage/v1beta1/volumeattachment.go index ae3c2fd71..63fa12f0e 100644 --- a/vendor/k8s.io/client-go/informers/storage/v1beta1/volumeattachment.go +++ b/vendor/k8s.io/client-go/informers/storage/v1beta1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/BUILD b/vendor/k8s.io/client-go/kubernetes/BUILD deleted file mode 100644 index 0ef4f8671..000000000 --- a/vendor/k8s.io/client-go/kubernetes/BUILD +++ /dev/null @@ -1,95 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clientset.go", - "doc.go", - "import.go", - ], - importpath = "k8s.io/client-go/kubernetes", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authentication/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authorization/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/networking/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/fake:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/scheme:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/networking/v1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1:all-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/clientset.go b/vendor/k8s.io/client-go/kubernetes/clientset.go index d867a58b2..9d0eace46 100644 --- a/vendor/k8s.io/client-go/kubernetes/clientset.go +++ b/vendor/k8s.io/client-go/kubernetes/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package kubernetes import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" admissionregistrationv1alpha1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1" admissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1" @@ -45,6 +44,7 @@ import ( rbacv1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1" rbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1" schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1" + schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1" settingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1" storagev1 "k8s.io/client-go/kubernetes/typed/storage/v1" storagev1alpha1 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1" @@ -105,8 +105,9 @@ type Interface interface { RbacV1beta1() rbacv1beta1.RbacV1beta1Interface RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface + SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface // Deprecated: please explicitly pick a version if possible. - Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface + Scheduling() schedulingv1beta1.SchedulingV1beta1Interface SettingsV1alpha1() settingsv1alpha1.SettingsV1alpha1Interface // Deprecated: please explicitly pick a version if possible. Settings() settingsv1alpha1.SettingsV1alpha1Interface @@ -145,6 +146,7 @@ type Clientset struct { rbacV1beta1 *rbacv1beta1.RbacV1beta1Client rbacV1alpha1 *rbacv1alpha1.RbacV1alpha1Client schedulingV1alpha1 *schedulingv1alpha1.SchedulingV1alpha1Client + schedulingV1beta1 *schedulingv1beta1.SchedulingV1beta1Client settingsV1alpha1 *settingsv1alpha1.SettingsV1alpha1Client storageV1beta1 *storagev1beta1.StorageV1beta1Client storageV1 *storagev1.StorageV1Client @@ -349,10 +351,15 @@ func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1In return c.schedulingV1alpha1 } +// SchedulingV1beta1 retrieves the SchedulingV1beta1Client +func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface { + return c.schedulingV1beta1 +} + // Deprecated: Scheduling retrieves the default version of SchedulingClient. // Please explicitly pick a version. -func (c *Clientset) Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface { - return c.schedulingV1alpha1 +func (c *Clientset) Scheduling() schedulingv1beta1.SchedulingV1beta1Interface { + return c.schedulingV1beta1 } // SettingsV1alpha1 retrieves the SettingsV1alpha1Client @@ -499,6 +506,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { if err != nil { return nil, err } + cs.schedulingV1beta1, err = schedulingv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.settingsV1alpha1, err = settingsv1alpha1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -518,7 +529,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil @@ -552,6 +562,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { cs.rbacV1beta1 = rbacv1beta1.NewForConfigOrDie(c) cs.rbacV1alpha1 = rbacv1alpha1.NewForConfigOrDie(c) cs.schedulingV1alpha1 = schedulingv1alpha1.NewForConfigOrDie(c) + cs.schedulingV1beta1 = schedulingv1beta1.NewForConfigOrDie(c) cs.settingsV1alpha1 = settingsv1alpha1.NewForConfigOrDie(c) cs.storageV1beta1 = storagev1beta1.NewForConfigOrDie(c) cs.storageV1 = storagev1.NewForConfigOrDie(c) @@ -588,6 +599,7 @@ func New(c rest.Interface) *Clientset { cs.rbacV1beta1 = rbacv1beta1.New(c) cs.rbacV1alpha1 = rbacv1alpha1.New(c) cs.schedulingV1alpha1 = schedulingv1alpha1.New(c) + cs.schedulingV1beta1 = schedulingv1beta1.New(c) cs.settingsV1alpha1 = settingsv1alpha1.New(c) cs.storageV1beta1 = storagev1beta1.New(c) cs.storageV1 = storagev1.New(c) diff --git a/vendor/k8s.io/client-go/kubernetes/doc.go b/vendor/k8s.io/client-go/kubernetes/doc.go index c5870c01a..b272334ad 100644 --- a/vendor/k8s.io/client-go/kubernetes/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/fake/BUILD deleted file mode 100644 index c30d43ffb..000000000 --- a/vendor/k8s.io/client-go/kubernetes/fake/BUILD +++ /dev/null @@ -1,124 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clientset_generated.go", - "doc.go", - "register.go", - ], - importpath = "k8s.io/client-go/kubernetes/fake", - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/api/apps/v1:go_default_library", - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", - "//vendor/k8s.io/api/authentication/v1:go_default_library", - "//vendor/k8s.io/api/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/api/authorization/v1:go_default_library", - "//vendor/k8s.io/api/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/events/v1beta1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/api/networking/v1:go_default_library", - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/api/storage/v1:go_default_library", - "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/api/storage/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - "//vendor/k8s.io/client-go/discovery/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authentication/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authorization/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/networking/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/fake/clientset_generated.go b/vendor/k8s.io/client-go/kubernetes/fake/clientset_generated.go index 0eb5ac9e5..b764b21b6 100644 --- a/vendor/k8s.io/client-go/kubernetes/fake/clientset_generated.go +++ b/vendor/k8s.io/client-go/kubernetes/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -72,6 +72,8 @@ import ( fakerbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake" schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1" fakeschedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake" + schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1" + fakeschedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake" settingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1" fakesettingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake" storagev1 "k8s.io/client-go/kubernetes/typed/storage/v1" @@ -95,9 +97,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -107,7 +110,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a @@ -309,9 +312,14 @@ func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1In return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake} } -// Scheduling retrieves the SchedulingV1alpha1Client -func (c *Clientset) Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface { - return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake} +// SchedulingV1beta1 retrieves the SchedulingV1beta1Client +func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface { + return &fakeschedulingv1beta1.FakeSchedulingV1beta1{Fake: &c.Fake} +} + +// Scheduling retrieves the SchedulingV1beta1Client +func (c *Clientset) Scheduling() schedulingv1beta1.SchedulingV1beta1Interface { + return &fakeschedulingv1beta1.FakeSchedulingV1beta1{Fake: &c.Fake} } // SettingsV1alpha1 retrieves the SettingsV1alpha1Client diff --git a/vendor/k8s.io/client-go/kubernetes/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/client-go/kubernetes/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/fake/register.go b/vendor/k8s.io/client-go/kubernetes/fake/register.go index 45fdf124c..88e168fa6 100644 --- a/vendor/k8s.io/client-go/kubernetes/fake/register.go +++ b/vendor/k8s.io/client-go/kubernetes/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,6 +43,7 @@ import ( rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" settingsv1alpha1 "k8s.io/api/settings/v1alpha1" storagev1 "k8s.io/api/storage/v1" storagev1alpha1 "k8s.io/api/storage/v1alpha1" @@ -101,6 +102,7 @@ func AddToScheme(scheme *runtime.Scheme) { rbacv1beta1.AddToScheme(scheme) rbacv1alpha1.AddToScheme(scheme) schedulingv1alpha1.AddToScheme(scheme) + schedulingv1beta1.AddToScheme(scheme) settingsv1alpha1.AddToScheme(scheme) storagev1beta1.AddToScheme(scheme) storagev1.AddToScheme(scheme) diff --git a/vendor/k8s.io/client-go/kubernetes/scheme/BUILD b/vendor/k8s.io/client-go/kubernetes/scheme/BUILD deleted file mode 100644 index 1bb118aa0..000000000 --- a/vendor/k8s.io/client-go/kubernetes/scheme/BUILD +++ /dev/null @@ -1,62 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "register.go", - ], - importpath = "k8s.io/client-go/kubernetes/scheme", - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/api/apps/v1:go_default_library", - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", - "//vendor/k8s.io/api/authentication/v1:go_default_library", - "//vendor/k8s.io/api/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/api/authorization/v1:go_default_library", - "//vendor/k8s.io/api/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/events/v1beta1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/api/networking/v1:go_default_library", - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/api/storage/v1:go_default_library", - "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/api/storage/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/scheme/doc.go b/vendor/k8s.io/client-go/kubernetes/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/client-go/kubernetes/scheme/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/scheme/register.go b/vendor/k8s.io/client-go/kubernetes/scheme/register.go index 66e2dcd18..86584cf83 100644 --- a/vendor/k8s.io/client-go/kubernetes/scheme/register.go +++ b/vendor/k8s.io/client-go/kubernetes/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,6 +43,7 @@ import ( rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" settingsv1alpha1 "k8s.io/api/settings/v1alpha1" storagev1 "k8s.io/api/storage/v1" storagev1alpha1 "k8s.io/api/storage/v1alpha1" @@ -101,6 +102,7 @@ func AddToScheme(scheme *runtime.Scheme) { rbacv1beta1.AddToScheme(scheme) rbacv1alpha1.AddToScheme(scheme) schedulingv1alpha1.AddToScheme(scheme) + schedulingv1beta1.AddToScheme(scheme) settingsv1alpha1.AddToScheme(scheme) storagev1beta1.AddToScheme(scheme) storagev1.AddToScheme(scheme) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/BUILD deleted file mode 100644 index 6ad245311..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "admissionregistration_client.go", - "doc.go", - "generated_expansion.go", - "initializerconfiguration.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/admissionregistration_client.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/admissionregistration_client.go index 8137129fc..5e02f7227 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/admissionregistration_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/BUILD deleted file mode 100644 index a70c2bef0..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_admissionregistration_client.go", - "fake_initializerconfiguration.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go index 2917c0ae4..8457aec27 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go index 699261cd4..b927dae2c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeInitializerConfigurations) List(opts v1.ListOptions) (result *v1alp if label == nil { label = labels.Everything() } - list := &v1alpha1.InitializerConfigurationList{} + list := &v1alpha1.InitializerConfigurationList{ListMeta: obj.(*v1alpha1.InitializerConfigurationList).ListMeta} for _, item := range obj.(*v1alpha1.InitializerConfigurationList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/generated_expansion.go index 710bc4ea4..1e29b96f4 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/initializerconfiguration.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/initializerconfiguration.go index 77c6b8fcc..e014ea72b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/initializerconfiguration.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/BUILD deleted file mode 100644 index 197f738eb..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "admissionregistration_client.go", - "doc.go", - "generated_expansion.go", - "mutatingwebhookconfiguration.go", - "validatingwebhookconfiguration.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/admissionregistration_client.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/admissionregistration_client.go index 44b20b577..b13ea7953 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/admissionregistration_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/BUILD deleted file mode 100644 index 4e615188d..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_admissionregistration_client.go", - "fake_mutatingwebhookconfiguration.go", - "fake_validatingwebhookconfiguration.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go index 3255acb47..1a988ddba 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go index 044636ead..e06888cc1 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeMutatingWebhookConfigurations) List(opts v1.ListOptions) (result *v if label == nil { label = labels.Everything() } - list := &v1beta1.MutatingWebhookConfigurationList{} + list := &v1beta1.MutatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.MutatingWebhookConfigurationList).ListMeta} for _, item := range obj.(*v1beta1.MutatingWebhookConfigurationList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go index f06582d4e..1069634e2 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeValidatingWebhookConfigurations) List(opts v1.ListOptions) (result if label == nil { label = labels.Everything() } - list := &v1beta1.ValidatingWebhookConfigurationList{} + list := &v1beta1.ValidatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.ValidatingWebhookConfigurationList).ListMeta} for _, item := range obj.(*v1beta1.ValidatingWebhookConfigurationList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/generated_expansion.go index 293697555..2aeb9c98a 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/mutatingwebhookconfiguration.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/mutatingwebhookconfiguration.go index d37f68448..cb0157102 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/validatingwebhookconfiguration.go b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/validatingwebhookconfiguration.go index 30dcfddbc..3a9339f6c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/validatingwebhookconfiguration.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/BUILD deleted file mode 100644 index 5d77a94df..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "apps_client.go", - "controllerrevision.go", - "daemonset.go", - "deployment.go", - "doc.go", - "generated_expansion.go", - "replicaset.go", - "statefulset.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/apps/v1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/apps/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go index b0af79806..da19c7596 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/controllerrevision.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/controllerrevision.go index 26d020747..ac9d62790 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/controllerrevision.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/daemonset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/daemonset.go index 73fd1e9bd..b50ac2557 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/daemonset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go index 1a3e8f730..e2b1b1886 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/BUILD deleted file mode 100644 index 912b2755d..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_apps_client.go", - "fake_controllerrevision.go", - "fake_daemonset.go", - "fake_deployment.go", - "fake_replicaset.go", - "fake_statefulset.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/apps/v1/fake", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/apps/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go index 11accc235..458df0fa3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go index fb43bea4c..0655803d8 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *apps_v1.Con if label == nil { label = labels.Everything() } - list := &apps_v1.ControllerRevisionList{} + list := &apps_v1.ControllerRevisionList{ListMeta: obj.(*apps_v1.ControllerRevisionList).ListMeta} for _, item := range obj.(*apps_v1.ControllerRevisionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go index 0ee4cd33d..47cdca788 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *apps_v1.DaemonSetLis if label == nil { label = labels.Everything() } - list := &apps_v1.DaemonSetList{} + list := &apps_v1.DaemonSetList{ListMeta: obj.(*apps_v1.DaemonSetList).ListMeta} for _, item := range obj.(*apps_v1.DaemonSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go index 852b628ad..dab4f40c3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *apps_v1.DeploymentL if label == nil { label = labels.Everything() } - list := &apps_v1.DeploymentList{} + list := &apps_v1.DeploymentList{ListMeta: obj.(*apps_v1.DeploymentList).ListMeta} for _, item := range obj.(*apps_v1.DeploymentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go index 03f7558d4..948091bed 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *apps_v1.ReplicaSetL if label == nil { label = labels.Everything() } - list := &apps_v1.ReplicaSetList{} + list := &apps_v1.ReplicaSetList{ListMeta: obj.(*apps_v1.ReplicaSetList).ListMeta} for _, item := range obj.(*apps_v1.ReplicaSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go index af0a90720..19cb2fad5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *apps_v1.StatefulSe if label == nil { label = labels.Everything() } - list := &apps_v1.StatefulSetList{} + list := &apps_v1.StatefulSetList{ListMeta: obj.(*apps_v1.StatefulSetList).ListMeta} for _, item := range obj.(*apps_v1.StatefulSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/generated_expansion.go index 0f603bb8c..88cfe4ecb 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/replicaset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/replicaset.go index f2f9c7256..21614cbe1 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/replicaset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/statefulset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/statefulset.go index 78fe23f84..3ef5b8880 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/statefulset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/BUILD deleted file mode 100644 index 18dca7163..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "apps_client.go", - "controllerrevision.go", - "deployment.go", - "doc.go", - "generated_expansion.go", - "scale.go", - "statefulset.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/apps/v1beta1", - deps = [ - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/apps_client.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/apps_client.go index 1aebc2176..4d882e26e 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/apps_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/controllerrevision.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/controllerrevision.go index 312ba3c47..ec8fa9242 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/controllerrevision.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/deployment.go index 2ff58aeac..365e06f3f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/deployment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/BUILD deleted file mode 100644 index ef39b5d3d..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_apps_client.go", - "fake_controllerrevision.go", - "fake_deployment.go", - "fake_scale.go", - "fake_statefulset.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake", - deps = [ - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go index 5cc316882..2ff602be9 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go index 2360bb07a..924194891 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *v1beta1.Con if label == nil { label = labels.Everything() } - list := &v1beta1.ControllerRevisionList{} + list := &v1beta1.ControllerRevisionList{ListMeta: obj.(*v1beta1.ControllerRevisionList).ListMeta} for _, item := range obj.(*v1beta1.ControllerRevisionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go index 5282d8cd9..c4749c52b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta1.DeploymentL if label == nil { label = labels.Everything() } - list := &v1beta1.DeploymentList{} + list := &v1beta1.DeploymentList{ListMeta: obj.(*v1beta1.DeploymentList).ListMeta} for _, item := range obj.(*v1beta1.DeploymentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go index 72615c803..de71947e5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go index 6e1d7a560..b0f194a7d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1beta1.StatefulSe if label == nil { label = labels.Everything() } - list := &v1beta1.StatefulSetList{} + list := &v1beta1.StatefulSetList{ListMeta: obj.(*v1beta1.StatefulSetList).ListMeta} for _, item := range obj.(*v1beta1.StatefulSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/generated_expansion.go index a44a94b63..b2bfd73a7 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/scale.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/scale.go index e8c507326..cef27bd14 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/scale.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/statefulset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/statefulset.go index 6f89ca73a..651745451 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/statefulset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/BUILD deleted file mode 100644 index 0af42bcf8..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/BUILD +++ /dev/null @@ -1,47 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "apps_client.go", - "controllerrevision.go", - "daemonset.go", - "deployment.go", - "doc.go", - "generated_expansion.go", - "replicaset.go", - "scale.go", - "statefulset.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/apps/v1beta2", - deps = [ - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/apps_client.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/apps_client.go index 8d5a78c44..27549499f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/apps_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/controllerrevision.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/controllerrevision.go index 28b30e8be..1271cc623 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/controllerrevision.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/daemonset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/daemonset.go index c21fc50a8..683c06812 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/daemonset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/deployment.go index 270be527e..9a04513f1 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/deployment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/doc.go index 01d0ed2c2..56518ef7f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/BUILD deleted file mode 100644 index d965ed1b2..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_apps_client.go", - "fake_controllerrevision.go", - "fake_daemonset.go", - "fake_deployment.go", - "fake_replicaset.go", - "fake_scale.go", - "fake_statefulset.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake", - deps = [ - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go index 7223cd24e..f7d79d352 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go index 720972e7d..954ac35df 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *v1beta2.Con if label == nil { label = labels.Everything() } - list := &v1beta2.ControllerRevisionList{} + list := &v1beta2.ControllerRevisionList{ListMeta: obj.(*v1beta2.ControllerRevisionList).ListMeta} for _, item := range obj.(*v1beta2.ControllerRevisionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go index 3576b8427..38a147550 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *v1beta2.DaemonSetLis if label == nil { label = labels.Everything() } - list := &v1beta2.DaemonSetList{} + list := &v1beta2.DaemonSetList{ListMeta: obj.(*v1beta2.DaemonSetList).ListMeta} for _, item := range obj.(*v1beta2.DaemonSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go index 1f654a3cc..cae232242 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta2.DeploymentL if label == nil { label = labels.Everything() } - list := &v1beta2.DeploymentList{} + list := &v1beta2.DeploymentList{ListMeta: obj.(*v1beta2.DeploymentList).ListMeta} for _, item := range obj.(*v1beta2.DeploymentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go index f8e69a3a3..05fa78931 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *v1beta2.ReplicaSetL if label == nil { label = labels.Everything() } - list := &v1beta2.ReplicaSetList{} + list := &v1beta2.ReplicaSetList{ListMeta: obj.(*v1beta2.ReplicaSetList).ListMeta} for _, item := range obj.(*v1beta2.ReplicaSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_scale.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_scale.go index fb5eb5c59..b06b7e8e3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_scale.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go index 0413428eb..fe7851286 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1beta2.StatefulSe if label == nil { label = labels.Everything() } - list := &v1beta2.StatefulSetList{} + list := &v1beta2.StatefulSetList{ListMeta: obj.(*v1beta2.StatefulSetList).ListMeta} for _, item := range obj.(*v1beta2.StatefulSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/generated_expansion.go index a88e1721f..bceae5986 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/replicaset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/replicaset.go index 298ec26a2..9fd9de930 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/replicaset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/scale.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/scale.go index 84f27a797..f8d6a7fb0 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/scale.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/statefulset.go b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/statefulset.go index 64b7c8c8f..095601e15 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/statefulset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/BUILD deleted file mode 100644 index b89498dea..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "authentication_client.go", - "doc.go", - "generated_expansion.go", - "tokenreview.go", - "tokenreview_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/authentication/v1", - deps = [ - "//vendor/k8s.io/api/authentication/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/authentication_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/authentication_client.go index 25b86152d..3bdcee598 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/authentication_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/BUILD deleted file mode 100644 index b2c995baf..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_authentication_client.go", - "fake_tokenreview.go", - "fake_tokenreview_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/authentication/v1/fake", - deps = [ - "//vendor/k8s.io/api/authentication/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authentication/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go index 93a0633e8..ee06a6cdd 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go index d98aa03d8..e2a7f72b6 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/generated_expansion.go index 7c92b9147..177209ec6 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/tokenreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/tokenreview.go index 88f759f2b..25a8d6a17 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/tokenreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/BUILD deleted file mode 100644 index ddbe7e984..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "authentication_client.go", - "doc.go", - "generated_expansion.go", - "tokenreview.go", - "tokenreview_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/authentication/v1beta1", - deps = [ - "//vendor/k8s.io/api/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/authentication_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/authentication_client.go index 744c26c9e..7f3334a0c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/authentication_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/BUILD deleted file mode 100644 index b9800aac7..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_authentication_client.go", - "fake_tokenreview.go", - "fake_tokenreview_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake", - deps = [ - "//vendor/k8s.io/api/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go index abc1fedd1..7299653ca 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go index c7c3e5631..63b6b6a85 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/generated_expansion.go index 7fd68c803..f6df76963 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/tokenreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/tokenreview.go index fa611825e..0ac3561e1 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/tokenreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/BUILD deleted file mode 100644 index f6255f38c..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/BUILD +++ /dev/null @@ -1,46 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "authorization_client.go", - "doc.go", - "generated_expansion.go", - "localsubjectaccessreview.go", - "localsubjectaccessreview_expansion.go", - "selfsubjectaccessreview.go", - "selfsubjectaccessreview_expansion.go", - "selfsubjectrulesreview.go", - "selfsubjectrulesreview_expansion.go", - "subjectaccessreview.go", - "subjectaccessreview_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/authorization/v1", - deps = [ - "//vendor/k8s.io/api/authorization/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/authorization_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/authorization_client.go index 852720f34..e84b90084 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/authorization_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/BUILD deleted file mode 100644 index cfea68c78..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_authorization_client.go", - "fake_localsubjectaccessreview.go", - "fake_localsubjectaccessreview_expansion.go", - "fake_selfsubjectaccessreview.go", - "fake_selfsubjectaccessreview_expansion.go", - "fake_selfsubjectrulesreview.go", - "fake_selfsubjectrulesreview_expansion.go", - "fake_subjectaccessreview.go", - "fake_subjectaccessreview_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/authorization/v1/fake", - deps = [ - "//vendor/k8s.io/api/authorization/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authorization/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go index 5db9b9f34..f7e823450 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go index 5f1aab8a4..778ba9cea 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go index 7e466e1ec..a43a980ba 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go index 82c1ac9cf..243f2e89e 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go index cbc440e71..d07e56254 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/generated_expansion.go index 7c92b9147..177209ec6 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/localsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/localsubjectaccessreview.go index 20461f132..0292c7861 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/localsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectaccessreview.go index 202e7c90d..1e3a45817 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectrulesreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectrulesreview.go index 5fb1cab5c..50a0233eb 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectrulesreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/subjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/subjectaccessreview.go index 881641494..9c09008c3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/subjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/BUILD deleted file mode 100644 index 793ec39b5..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/BUILD +++ /dev/null @@ -1,46 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "authorization_client.go", - "doc.go", - "generated_expansion.go", - "localsubjectaccessreview.go", - "localsubjectaccessreview_expansion.go", - "selfsubjectaccessreview.go", - "selfsubjectaccessreview_expansion.go", - "selfsubjectrulesreview.go", - "selfsubjectrulesreview_expansion.go", - "subjectaccessreview.go", - "subjectaccessreview_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/authorization/v1beta1", - deps = [ - "//vendor/k8s.io/api/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/authorization_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/authorization_client.go index cbe5bdcee..7f236f6e3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/authorization_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/BUILD deleted file mode 100644 index d3fd9e81b..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_authorization_client.go", - "fake_generated_expansion.go", - "fake_localsubjectaccessreview.go", - "fake_localsubjectaccessreview_expansion.go", - "fake_selfsubjectaccessreview.go", - "fake_selfsubjectaccessreview_expansion.go", - "fake_selfsubjectrulesreview.go", - "fake_selfsubjectrulesreview_expansion.go", - "fake_subjectaccessreview.go", - "fake_subjectaccessreview_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake", - deps = [ - "//vendor/k8s.io/api/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go index 7c3fc1746..8e328a57b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go index c7949a7df..d02d05e5d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go index 20904d179..8f98ce7a3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go index 2acd5f279..d8466b4c8 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go index 218ed3d8f..0d0abdb72 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/generated_expansion.go index 7fd68c803..f6df76963 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/localsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/localsubjectaccessreview.go index 8029837f9..f5e86a76a 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/localsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectaccessreview.go index 36feb1530..906712cc3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectrulesreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectrulesreview.go index 57079c8d9..56c0f99d4 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectrulesreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/subjectaccessreview.go b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/subjectaccessreview.go index d91fa87ec..79f1ec535 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/subjectaccessreview.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/BUILD deleted file mode 100644 index 30e434a68..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "autoscaling_client.go", - "doc.go", - "generated_expansion.go", - "horizontalpodautoscaler.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/autoscaling/v1", - deps = [ - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/autoscaling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/autoscaling_client.go index b336bbd39..2bd49e2db 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/autoscaling_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/BUILD deleted file mode 100644 index 3cabf19c5..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_autoscaling_client.go", - "fake_horizontalpodautoscaler.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake", - deps = [ - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go index 540eb5f5c..99e26fcf3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go index 532e6f51c..f774fc5dc 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *autosc if label == nil { label = labels.Everything() } - list := &autoscaling_v1.HorizontalPodAutoscalerList{} + list := &autoscaling_v1.HorizontalPodAutoscalerList{ListMeta: obj.(*autoscaling_v1.HorizontalPodAutoscalerList).ListMeta} for _, item := range obj.(*autoscaling_v1.HorizontalPodAutoscalerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/generated_expansion.go index a5c694ffb..c60028b05 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/horizontalpodautoscaler.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/horizontalpodautoscaler.go index 9245e41a2..2da25e96b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/BUILD deleted file mode 100644 index 1bb145072..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "autoscaling_client.go", - "doc.go", - "generated_expansion.go", - "horizontalpodautoscaler.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/autoscaling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/autoscaling_client.go index 25446452f..3a49b26b3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/autoscaling_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/doc.go index 1f70aedf8..06fd344c0 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/BUILD deleted file mode 100644 index 6d7d87326..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_autoscaling_client.go", - "fake_horizontalpodautoscaler.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go index 6d3437a23..be8e0f48e 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go index 549196c5e..2d860341a 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *v2beta if label == nil { label = labels.Everything() } - list := &v2beta1.HorizontalPodAutoscalerList{} + list := &v2beta1.HorizontalPodAutoscalerList{ListMeta: obj.(*v2beta1.HorizontalPodAutoscalerList).ListMeta} for _, item := range obj.(*v2beta1.HorizontalPodAutoscalerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/generated_expansion.go index 561fbb0e6..6f1704f1e 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/horizontalpodautoscaler.go b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/horizontalpodautoscaler.go index 1be9b80ca..4ac8cce71 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/BUILD deleted file mode 100644 index 2af6de364..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "batch_client.go", - "doc.go", - "generated_expansion.go", - "job.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/batch/v1", - deps = [ - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/batch_client.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/batch_client.go index c092a3ca1..d5e35e6b2 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/batch_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/BUILD deleted file mode 100644 index 384e15eee..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_batch_client.go", - "fake_job.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/batch/v1/fake", - deps = [ - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go index 27d54c4c4..c90dd7561 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go index 4d9ba490f..6a83115ba 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeJobs) List(opts v1.ListOptions) (result *batch_v1.JobList, err erro if label == nil { label = labels.Everything() } - list := &batch_v1.JobList{} + list := &batch_v1.JobList{ListMeta: obj.(*batch_v1.JobList).ListMeta} for _, item := range obj.(*batch_v1.JobList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/generated_expansion.go index 04a37a49d..dc4142934 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/job.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/job.go index dc0c79997..f714d3de5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/job.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1/job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/BUILD deleted file mode 100644 index 58e0a6afa..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "batch_client.go", - "cronjob.go", - "doc.go", - "generated_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/batch/v1beta1", - deps = [ - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/batch_client.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/batch_client.go index 5ee39b5be..aa71ca833 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/batch_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/cronjob.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/cronjob.go index 32ac52fac..04637c36a 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/cronjob.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/BUILD deleted file mode 100644 index 8fd1c81ec..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_batch_client.go", - "fake_cronjob.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake", - deps = [ - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go index 9de70f8fe..6f350aed9 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go index 756585d7d..d80ef5e67 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeCronJobs) List(opts v1.ListOptions) (result *v1beta1.CronJobList, e if label == nil { label = labels.Everything() } - list := &v1beta1.CronJobList{} + list := &v1beta1.CronJobList{ListMeta: obj.(*v1beta1.CronJobList).ListMeta} for _, item := range obj.(*v1beta1.CronJobList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/generated_expansion.go index a093bbad4..145e14a99 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/BUILD deleted file mode 100644 index c698053ad..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "batch_client.go", - "cronjob.go", - "doc.go", - "generated_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/batch/v2alpha1", - deps = [ - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/batch_client.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/batch_client.go index ff26a76d5..e6c6306b8 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/batch_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/cronjob.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/cronjob.go index e5b135314..4d922f9ae 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/cronjob.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/doc.go index ba60ac54b..3efe0d284 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/BUILD deleted file mode 100644 index 659470373..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_batch_client.go", - "fake_cronjob.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake", - deps = [ - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go index 52ad499cc..3e478cde9 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go index f80e94cae..75c0b1733 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeCronJobs) List(opts v1.ListOptions) (result *v2alpha1.CronJobList, if label == nil { label = labels.Everything() } - list := &v2alpha1.CronJobList{} + list := &v2alpha1.CronJobList{ListMeta: obj.(*v2alpha1.CronJobList).ListMeta} for _, item := range obj.(*v2alpha1.CronJobList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/generated_expansion.go index ed2c942b0..34dafc464 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/BUILD deleted file mode 100644 index 1caeb018f..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "certificates_client.go", - "certificatesigningrequest.go", - "certificatesigningrequest_expansion.go", - "doc.go", - "generated_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", - deps = [ - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificates_client.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificates_client.go index 7d69ce9f6..baac42ee2 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificates_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificates_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificatesigningrequest.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificatesigningrequest.go index ecca7aedc..b39169a8f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificatesigningrequest.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/BUILD deleted file mode 100644 index 6fa63d82a..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_certificates_client.go", - "fake_certificatesigningrequest.go", - "fake_certificatesigningrequest_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake", - deps = [ - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go index 455ac56b5..29d8b088e 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go index f3ea4c464..dfd517195 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeCertificateSigningRequests) List(opts v1.ListOptions) (result *v1be if label == nil { label = labels.Everything() } - list := &v1beta1.CertificateSigningRequestList{} + list := &v1beta1.CertificateSigningRequestList{ListMeta: obj.(*v1beta1.CertificateSigningRequestList).ListMeta} for _, item := range obj.(*v1beta1.CertificateSigningRequestList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/generated_expansion.go index 7fd68c803..f6df76963 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/BUILD deleted file mode 100644 index 4c9f03aa4..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/BUILD +++ /dev/null @@ -1,70 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "componentstatus.go", - "configmap.go", - "core_client.go", - "doc.go", - "endpoints.go", - "event.go", - "event_expansion.go", - "generated_expansion.go", - "limitrange.go", - "namespace.go", - "namespace_expansion.go", - "node.go", - "node_expansion.go", - "persistentvolume.go", - "persistentvolumeclaim.go", - "pod.go", - "pod_expansion.go", - "podtemplate.go", - "replicationcontroller.go", - "resourcequota.go", - "secret.go", - "service.go", - "service_expansion.go", - "serviceaccount.go", - "serviceaccount_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/core/v1", - deps = [ - "//vendor/k8s.io/api/authentication/v1:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/reference:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/componentstatus.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/componentstatus.go index 1717e7c19..6ae5a6681 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/componentstatus.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go index 6e7a12e5d..3ae229f42 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/core_client.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/core_client.go index 1c86c47d4..044a28ebd 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/core_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/core_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/endpoints.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/endpoints.go index 03b2a6919..2868baaa1 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/endpoints.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/event.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/event.go index b9570e689..565062345 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/event.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/BUILD deleted file mode 100644 index 7403a4997..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/BUILD +++ /dev/null @@ -1,66 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_componentstatus.go", - "fake_configmap.go", - "fake_core_client.go", - "fake_endpoints.go", - "fake_event.go", - "fake_event_expansion.go", - "fake_limitrange.go", - "fake_namespace.go", - "fake_namespace_expansion.go", - "fake_node.go", - "fake_node_expansion.go", - "fake_persistentvolume.go", - "fake_persistentvolumeclaim.go", - "fake_pod.go", - "fake_pod_expansion.go", - "fake_podtemplate.go", - "fake_replicationcontroller.go", - "fake_resourcequota.go", - "fake_secret.go", - "fake_service.go", - "fake_service_expansion.go", - "fake_serviceaccount.go", - "fake_serviceaccount_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/core/v1/fake", - deps = [ - "//vendor/k8s.io/api/authentication/v1:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/runtime:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go index 42039aea9..2f2420730 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeComponentStatuses) List(opts v1.ListOptions) (result *core_v1.Compo if label == nil { label = labels.Everything() } - list := &core_v1.ComponentStatusList{} + list := &core_v1.ComponentStatusList{ListMeta: obj.(*core_v1.ComponentStatusList).ListMeta} for _, item := range obj.(*core_v1.ComponentStatusList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go index 8de1cde17..1bc7757fb 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeConfigMaps) List(opts v1.ListOptions) (result *core_v1.ConfigMapLis if label == nil { label = labels.Everything() } - list := &core_v1.ConfigMapList{} + list := &core_v1.ConfigMapList{ListMeta: obj.(*core_v1.ConfigMapList).ListMeta} for _, item := range obj.(*core_v1.ConfigMapList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go index b30c02de1..5ad90943c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go index 7b54929f6..eb5eac981 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeEndpoints) List(opts v1.ListOptions) (result *core_v1.EndpointsList if label == nil { label = labels.Everything() } - list := &core_v1.EndpointsList{} + list := &core_v1.EndpointsList{ListMeta: obj.(*core_v1.EndpointsList).ListMeta} for _, item := range obj.(*core_v1.EndpointsList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go index 5ba47f419..458b8c153 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeEvents) List(opts v1.ListOptions) (result *core_v1.EventList, err e if label == nil { label = labels.Everything() } - list := &core_v1.EventList{} + list := &core_v1.EventList{ListMeta: obj.(*core_v1.EventList).ListMeta} for _, item := range obj.(*core_v1.EventList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go index bd736980e..c5156c7c0 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeLimitRanges) List(opts v1.ListOptions) (result *core_v1.LimitRangeL if label == nil { label = labels.Everything() } - list := &core_v1.LimitRangeList{} + list := &core_v1.LimitRangeList{ListMeta: obj.(*core_v1.LimitRangeList).ListMeta} for _, item := range obj.(*core_v1.LimitRangeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go index 84743469a..32aae1389 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeNamespaces) List(opts v1.ListOptions) (result *core_v1.NamespaceLis if label == nil { label = labels.Everything() } - list := &core_v1.NamespaceList{} + list := &core_v1.NamespaceList{ListMeta: obj.(*core_v1.NamespaceList).ListMeta} for _, item := range obj.(*core_v1.NamespaceList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) @@ -112,14 +112,6 @@ func (c *FakeNamespaces) Delete(name string, options *v1.DeleteOptions) error { return err } -// DeleteCollection deletes a collection of objects. -func (c *FakeNamespaces) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewRootDeleteCollectionAction(namespacesResource, listOptions) - - _, err := c.Fake.Invokes(action, &core_v1.NamespaceList{}) - return err -} - // Patch applies the patch and returns the patched namespace. func (c *FakeNamespaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *core_v1.Namespace, err error) { obj, err := c.Fake. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go index c7e042fc8..8b99bb8e4 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeNodes) List(opts v1.ListOptions) (result *core_v1.NodeList, err err if label == nil { label = labels.Everything() } - list := &core_v1.NodeList{} + list := &core_v1.NodeList{ListMeta: obj.(*core_v1.NodeList).ListMeta} for _, item := range obj.(*core_v1.NodeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go index 1be38a89e..5742936d2 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePersistentVolumes) List(opts v1.ListOptions) (result *core_v1.Persi if label == nil { label = labels.Everything() } - list := &core_v1.PersistentVolumeList{} + list := &core_v1.PersistentVolumeList{ListMeta: obj.(*core_v1.PersistentVolumeList).ListMeta} for _, item := range obj.(*core_v1.PersistentVolumeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go index ea189bb9c..d2d17984c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePersistentVolumeClaims) List(opts v1.ListOptions) (result *core_v1. if label == nil { label = labels.Everything() } - list := &core_v1.PersistentVolumeClaimList{} + list := &core_v1.PersistentVolumeClaimList{ListMeta: obj.(*core_v1.PersistentVolumeClaimList).ListMeta} for _, item := range obj.(*core_v1.PersistentVolumeClaimList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go index 6f5faef99..2960b12ae 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePods) List(opts v1.ListOptions) (result *core_v1.PodList, err error if label == nil { label = labels.Everything() } - list := &core_v1.PodList{} + list := &core_v1.PodList{ListMeta: obj.(*core_v1.PodList).ListMeta} for _, item := range obj.(*core_v1.PodList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go index 1dd272e78..3ae6ca551 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePodTemplates) List(opts v1.ListOptions) (result *core_v1.PodTemplat if label == nil { label = labels.Everything() } - list := &core_v1.PodTemplateList{} + list := &core_v1.PodTemplateList{ListMeta: obj.(*core_v1.PodTemplateList).ListMeta} for _, item := range obj.(*core_v1.PodTemplateList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go index 047831a31..f25235ff2 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -63,7 +63,7 @@ func (c *FakeReplicationControllers) List(opts v1.ListOptions) (result *core_v1. if label == nil { label = labels.Everything() } - list := &core_v1.ReplicationControllerList{} + list := &core_v1.ReplicationControllerList{ListMeta: obj.(*core_v1.ReplicationControllerList).ListMeta} for _, item := range obj.(*core_v1.ReplicationControllerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go index afdc8c88a..9c6ae20a2 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeResourceQuotas) List(opts v1.ListOptions) (result *core_v1.Resource if label == nil { label = labels.Everything() } - list := &core_v1.ResourceQuotaList{} + list := &core_v1.ResourceQuotaList{ListMeta: obj.(*core_v1.ResourceQuotaList).ListMeta} for _, item := range obj.(*core_v1.ResourceQuotaList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go index abf7db090..e1eeea5f8 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeSecrets) List(opts v1.ListOptions) (result *core_v1.SecretList, err if label == nil { label = labels.Everything() } - list := &core_v1.SecretList{} + list := &core_v1.SecretList{ListMeta: obj.(*core_v1.SecretList).ListMeta} for _, item := range obj.(*core_v1.SecretList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go index 7ce885ae8..aa23e0efa 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeServices) List(opts v1.ListOptions) (result *core_v1.ServiceList, e if label == nil { label = labels.Everything() } - list := &core_v1.ServiceList{} + list := &core_v1.ServiceList{ListMeta: obj.(*core_v1.ServiceList).ListMeta} for _, item := range obj.(*core_v1.ServiceList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) @@ -120,14 +120,6 @@ func (c *FakeServices) Delete(name string, options *v1.DeleteOptions) error { return err } -// DeleteCollection deletes a collection of objects. -func (c *FakeServices) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(servicesResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &core_v1.ServiceList{}) - return err -} - // Patch applies the patch and returns the patched service. func (c *FakeServices) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *core_v1.Service, err error) { obj, err := c.Fake. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go index 635b2c32b..1d5837f8b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeServiceAccounts) List(opts v1.ListOptions) (result *core_v1.Service if label == nil { label = labels.Everything() } - list := &core_v1.ServiceAccountList{} + list := &core_v1.ServiceAccountList{ListMeta: obj.(*core_v1.ServiceAccountList).ListMeta} for _, item := range obj.(*core_v1.ServiceAccountList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/generated_expansion.go index 430bd6c5a..6e8591b12 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/limitrange.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/limitrange.go index b67997d70..396e5ca4b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/limitrange.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/namespace.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/namespace.go index a298d7c02..707b3e971 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/namespace.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -39,7 +39,6 @@ type NamespaceInterface interface { Update(*v1.Namespace) (*v1.Namespace, error) UpdateStatus(*v1.Namespace) (*v1.Namespace, error) Delete(name string, options *meta_v1.DeleteOptions) error - DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error Get(name string, options meta_v1.GetOptions) (*v1.Namespace, error) List(opts meta_v1.ListOptions) (*v1.NamespaceList, error) Watch(opts meta_v1.ListOptions) (watch.Interface, error) @@ -139,16 +138,6 @@ func (c *namespaces) Delete(name string, options *meta_v1.DeleteOptions) error { Error() } -// DeleteCollection deletes a collection of objects. -func (c *namespaces) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error { - return c.client.Delete(). - Resource("namespaces"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Body(options). - Do(). - Error() -} - // Patch applies the patch and returns the patched namespace. func (c *namespaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Namespace, err error) { result = &v1.Namespace{} diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/node.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/node.go index b16f92f00..1462d2549 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/node.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolume.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolume.go index f23b95f30..f9010119b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolume.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolumeclaim.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolumeclaim.go index f168a985a..59253d5ef 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolumeclaim.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/pod.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/pod.go index 423d81ad8..8eb7ba8bd 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/pod.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/podtemplate.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/podtemplate.go index 730b54330..d99d8c3b5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/podtemplate.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/replicationcontroller.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/replicationcontroller.go index a0f36a1fa..7741f970a 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/replicationcontroller.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/resourcequota.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/resourcequota.go index 011e72a91..7662a0280 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/resourcequota.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/secret.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/secret.go index 931afb5db..5d149f8cc 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/secret.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/service.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/service.go index 156bcc235..ec8646a27 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/service.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -39,7 +39,6 @@ type ServiceInterface interface { Update(*v1.Service) (*v1.Service, error) UpdateStatus(*v1.Service) (*v1.Service, error) Delete(name string, options *meta_v1.DeleteOptions) error - DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error Get(name string, options meta_v1.GetOptions) (*v1.Service, error) List(opts meta_v1.ListOptions) (*v1.ServiceList, error) Watch(opts meta_v1.ListOptions) (watch.Interface, error) @@ -148,17 +147,6 @@ func (c *services) Delete(name string, options *meta_v1.DeleteOptions) error { Error() } -// DeleteCollection deletes a collection of objects. -func (c *services) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("services"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Body(options). - Do(). - Error() -} - // Patch applies the patch and returns the patched service. func (c *services) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Service, err error) { result = &v1.Service{} diff --git a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/serviceaccount.go b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/serviceaccount.go index 0a87feb5b..ba2a27948 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/core/v1/serviceaccount.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/core/v1/serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/BUILD deleted file mode 100644 index 307884cc4..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "event.go", - "events_client.go", - "generated_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/events/v1beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/events/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/event.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/event.go index e8737cf9e..af7d060d5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/event.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/events_client.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/events_client.go index 7225d90d8..fb59635bb 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/events_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/events_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/BUILD deleted file mode 100644 index b9a692e5c..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_event.go", - "fake_events_client.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/events/v1beta1/fake", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/events/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go index 02fa70fbd..b210e40a0 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeEvents) List(opts v1.ListOptions) (result *v1beta1.EventList, err e if label == nil { label = labels.Everything() } - list := &v1beta1.EventList{} + list := &v1beta1.EventList{ListMeta: obj.(*v1beta1.EventList).ListMeta} for _, item := range obj.(*v1beta1.EventList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go index c6eb06623..875c774e3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/generated_expansion.go index 871411abb..e27f693f8 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/events/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/BUILD deleted file mode 100644 index 5ad976867..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/BUILD +++ /dev/null @@ -1,51 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "daemonset.go", - "deployment.go", - "deployment_expansion.go", - "doc.go", - "extensions_client.go", - "generated_expansion.go", - "ingress.go", - "podsecuritypolicy.go", - "replicaset.go", - "scale.go", - "scale_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/extensions/v1beta1", - deps = [ - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/daemonset.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/daemonset.go index 20cd58728..85294be4b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/daemonset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/deployment.go index 91ada9e54..89183d285 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/deployment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go index c359a58f2..1961ffc7c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/BUILD deleted file mode 100644 index e62ff5bc8..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/BUILD +++ /dev/null @@ -1,47 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_daemonset.go", - "fake_deployment.go", - "fake_deployment_expansion.go", - "fake_extensions_client.go", - "fake_ingress.go", - "fake_podsecuritypolicy.go", - "fake_replicaset.go", - "fake_scale.go", - "fake_scale_expansion.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake", - deps = [ - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go index 083bed820..3a760b317 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *v1beta1.DaemonSetLis if label == nil { label = labels.Everything() } - list := &v1beta1.DaemonSetList{} + list := &v1beta1.DaemonSetList{ListMeta: obj.(*v1beta1.DaemonSetList).ListMeta} for _, item := range obj.(*v1beta1.DaemonSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go index 1ce8fb34b..f032a5563 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta1.DeploymentL if label == nil { label = labels.Everything() } - list := &v1beta1.DeploymentList{} + list := &v1beta1.DeploymentList{ListMeta: obj.(*v1beta1.DeploymentList).ListMeta} for _, item := range obj.(*v1beta1.DeploymentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go index d8b6741e6..1aba34f9d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go index 60efe17c8..55257a88a 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeIngresses) List(opts v1.ListOptions) (result *v1beta1.IngressList, if label == nil { label = labels.Everything() } - list := &v1beta1.IngressList{} + list := &v1beta1.IngressList{ListMeta: obj.(*v1beta1.IngressList).ListMeta} for _, item := range obj.(*v1beta1.IngressList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go index c381e62f1..70b5dac28 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *v1beta1.Pod if label == nil { label = labels.Everything() } - list := &v1beta1.PodSecurityPolicyList{} + list := &v1beta1.PodSecurityPolicyList{ListMeta: obj.(*v1beta1.PodSecurityPolicyList).ListMeta} for _, item := range obj.(*v1beta1.PodSecurityPolicyList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go index 20e8f76f6..2ab8f244f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *v1beta1.ReplicaSetL if label == nil { label = labels.Everything() } - list := &v1beta1.ReplicaSetList{} + list := &v1beta1.ReplicaSetList{ListMeta: obj.(*v1beta1.ReplicaSetList).ListMeta} for _, item := range obj.(*v1beta1.ReplicaSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_scale.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_scale.go index 0bbcbd15f..02c4d0bab 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_scale.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/generated_expansion.go index eef05e765..cfaeebd05 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/ingress.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/ingress.go index 26b21baa5..f8b664cbd 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/ingress.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/podsecuritypolicy.go index 19475a5c0..8099d7730 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/replicaset.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/replicaset.go index b307ac70e..7e61fa2d1 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/replicaset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/scale.go b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/scale.go index e654d9537..6ee677acd 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/scale.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/BUILD deleted file mode 100644 index 7a2e3e2b1..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "generated_expansion.go", - "networking_client.go", - "networkpolicy.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/networking/v1", - deps = [ - "//vendor/k8s.io/api/networking/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/BUILD deleted file mode 100644 index bc84632da..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_networking_client.go", - "fake_networkpolicy.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/networking/v1/fake", - deps = [ - "//vendor/k8s.io/api/networking/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/networking/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go index 8bce64250..6b135c636 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go index fbab3ca16..4bf7ef7ca 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeNetworkPolicies) List(opts v1.ListOptions) (result *networking_v1.N if label == nil { label = labels.Everything() } - list := &networking_v1.NetworkPolicyList{} + list := &networking_v1.NetworkPolicyList{ListMeta: obj.(*networking_v1.NetworkPolicyList).ListMeta} for _, item := range obj.(*networking_v1.NetworkPolicyList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/generated_expansion.go index c6dd5c323..7d77495fa 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/networking_client.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/networking_client.go index ac8200f82..8684db456 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/networking_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/networking_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/networkpolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/networkpolicy.go index b0a85c5c5..c2eb2e792 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/networkpolicy.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/networking/v1/networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/BUILD deleted file mode 100644 index 92606b3c4..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "eviction.go", - "eviction_expansion.go", - "generated_expansion.go", - "poddisruptionbudget.go", - "podsecuritypolicy.go", - "policy_client.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/policy/v1beta1", - deps = [ - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/eviction.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/eviction.go index b0abf6563..12e8e76ed 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/eviction.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/eviction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/BUILD deleted file mode 100644 index 9b6941ce9..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_eviction.go", - "fake_eviction_expansion.go", - "fake_poddisruptionbudget.go", - "fake_podsecuritypolicy.go", - "fake_policy_client.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake", - deps = [ - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go index 06aba37b4..b8f6f3eae 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go index d85a67e4f..3f2e78b31 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePodDisruptionBudgets) List(opts v1.ListOptions) (result *v1beta1.Po if label == nil { label = labels.Everything() } - list := &v1beta1.PodDisruptionBudgetList{} + list := &v1beta1.PodDisruptionBudgetList{ListMeta: obj.(*v1beta1.PodDisruptionBudgetList).ListMeta} for _, item := range obj.(*v1beta1.PodDisruptionBudgetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go index 068515a36..0df9aa15f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *v1beta1.Pod if label == nil { label = labels.Everything() } - list := &v1beta1.PodSecurityPolicyList{} + list := &v1beta1.PodSecurityPolicyList{ListMeta: obj.(*v1beta1.PodSecurityPolicyList).ListMeta} for _, item := range obj.(*v1beta1.PodSecurityPolicyList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go index 3b7e5415e..9c780bf1f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/generated_expansion.go index d39f527be..078c16d5c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/poddisruptionbudget.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/poddisruptionbudget.go index d154dfcf8..a11f27eb2 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/poddisruptionbudget.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/podsecuritypolicy.go index de6760b14..355be1e9c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/policy_client.go b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/policy_client.go index f45cfdf37..020e185e6 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/policy_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/policy/v1beta1/policy_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/BUILD deleted file mode 100644 index 76e85d4fc..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clusterrole.go", - "clusterrolebinding.go", - "doc.go", - "generated_expansion.go", - "rbac_client.go", - "role.go", - "rolebinding.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/rbac/v1", - deps = [ - "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrole.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrole.go index e1af3a99b..f3db3beb5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrole.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrolebinding.go index c49ac6dd2..21dda4980 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/BUILD deleted file mode 100644 index 4e92a39ba..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_clusterrole.go", - "fake_clusterrolebinding.go", - "fake_rbac_client.go", - "fake_role.go", - "fake_rolebinding.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/rbac/v1/fake", - deps = [ - "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go index b07323c50..01e62aeb5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *rbac_v1.ClusterRol if label == nil { label = labels.Everything() } - list := &rbac_v1.ClusterRoleList{} + list := &rbac_v1.ClusterRoleList{ListMeta: obj.(*rbac_v1.ClusterRoleList).ListMeta} for _, item := range obj.(*rbac_v1.ClusterRoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go index 5e960c8ca..e5c054c9c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *rbac_v1.Clu if label == nil { label = labels.Everything() } - list := &rbac_v1.ClusterRoleBindingList{} + list := &rbac_v1.ClusterRoleBindingList{ListMeta: obj.(*rbac_v1.ClusterRoleBindingList).ListMeta} for _, item := range obj.(*rbac_v1.ClusterRoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go index 5311f0618..426fd70d6 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go index 733760de2..413c70c09 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *rbac_v1.RoleList, err err if label == nil { label = labels.Everything() } - list := &rbac_v1.RoleList{} + list := &rbac_v1.RoleList{ListMeta: obj.(*rbac_v1.RoleList).ListMeta} for _, item := range obj.(*rbac_v1.RoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go index 11a75f939..536377b30 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *rbac_v1.RoleBindin if label == nil { label = labels.Everything() } - list := &rbac_v1.RoleBindingList{} + list := &rbac_v1.RoleBindingList{ListMeta: obj.(*rbac_v1.RoleBindingList).ListMeta} for _, item := range obj.(*rbac_v1.RoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/generated_expansion.go index 0977cc00c..e3f1b02e3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/rbac_client.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/rbac_client.go index e5b7b561d..e3855bb9b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/rbac_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/role.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/role.go index 678e284b7..cb7c5c4e8 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/role.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/rolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/rolebinding.go index 7fd9e29fa..a19010fa8 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/rolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/BUILD deleted file mode 100644 index 11065cf6a..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clusterrole.go", - "clusterrolebinding.go", - "doc.go", - "generated_expansion.go", - "rbac_client.go", - "role.go", - "rolebinding.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1", - deps = [ - "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrole.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrole.go index 901ef7f46..37a545762 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrole.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrolebinding.go index c5c5360b9..605078906 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/BUILD deleted file mode 100644 index 461fd09a0..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_clusterrole.go", - "fake_clusterrolebinding.go", - "fake_rbac_client.go", - "fake_role.go", - "fake_rolebinding.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake", - deps = [ - "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go index 1b3eec014..13fbce4e7 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *v1alpha1.ClusterRo if label == nil { label = labels.Everything() } - list := &v1alpha1.ClusterRoleList{} + list := &v1alpha1.ClusterRoleList{ListMeta: obj.(*v1alpha1.ClusterRoleList).ListMeta} for _, item := range obj.(*v1alpha1.ClusterRoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go index d54eb6f25..5076543d9 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *v1alpha1.Cl if label == nil { label = labels.Everything() } - list := &v1alpha1.ClusterRoleBindingList{} + list := &v1alpha1.ClusterRoleBindingList{ListMeta: obj.(*v1alpha1.ClusterRoleBindingList).ListMeta} for _, item := range obj.(*v1alpha1.ClusterRoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go index 12a96c5b6..3447e9be8 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go index 8c365efcb..24d8efee3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *v1alpha1.RoleList, err er if label == nil { label = labels.Everything() } - list := &v1alpha1.RoleList{} + list := &v1alpha1.RoleList{ListMeta: obj.(*v1alpha1.RoleList).ListMeta} for _, item := range obj.(*v1alpha1.RoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go index 4346589a8..cb01ef99d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *v1alpha1.RoleBindi if label == nil { label = labels.Everything() } - list := &v1alpha1.RoleBindingList{} + list := &v1alpha1.RoleBindingList{ListMeta: obj.(*v1alpha1.RoleBindingList).ListMeta} for _, item := range obj.(*v1alpha1.RoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/generated_expansion.go index aebf50655..b8b5c7869 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rbac_client.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rbac_client.go index 06b5f5cab..de83531ed 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rbac_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/role.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/role.go index 8af1d7784..aa6954bb5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/role.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rolebinding.go index 43888d066..0941b8e86 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/BUILD deleted file mode 100644 index e750f1e17..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clusterrole.go", - "clusterrolebinding.go", - "doc.go", - "generated_expansion.go", - "rbac_client.go", - "role.go", - "rolebinding.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/rbac/v1beta1", - deps = [ - "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrole.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrole.go index fd6effd46..bac951c87 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrole.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrolebinding.go index 469307000..96c91de6e 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/BUILD deleted file mode 100644 index 0ab08b3e3..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_clusterrole.go", - "fake_clusterrolebinding.go", - "fake_rbac_client.go", - "fake_role.go", - "fake_rolebinding.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake", - deps = [ - "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go index 738ca1ea9..62a832197 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *v1beta1.ClusterRol if label == nil { label = labels.Everything() } - list := &v1beta1.ClusterRoleList{} + list := &v1beta1.ClusterRoleList{ListMeta: obj.(*v1beta1.ClusterRoleList).ListMeta} for _, item := range obj.(*v1beta1.ClusterRoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go index 144bf70d3..c9ab47269 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *v1beta1.Clu if label == nil { label = labels.Everything() } - list := &v1beta1.ClusterRoleBindingList{} + list := &v1beta1.ClusterRoleBindingList{ListMeta: obj.(*v1beta1.ClusterRoleBindingList).ListMeta} for _, item := range obj.(*v1beta1.ClusterRoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go index 0856ee084..bdbc246b7 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go index 2e9d46b51..45b07a001 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *v1beta1.RoleList, err err if label == nil { label = labels.Everything() } - list := &v1beta1.RoleList{} + list := &v1beta1.RoleList{ListMeta: obj.(*v1beta1.RoleList).ListMeta} for _, item := range obj.(*v1beta1.RoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go index bb363d874..1efd40005 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *v1beta1.RoleBindin if label == nil { label = labels.Everything() } - list := &v1beta1.RoleBindingList{} + list := &v1beta1.RoleBindingList{ListMeta: obj.(*v1beta1.RoleBindingList).ListMeta} for _, item := range obj.(*v1beta1.RoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/generated_expansion.go index 538b09833..e7be79f8d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rbac_client.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rbac_client.go index eecdd45a8..46718d731 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rbac_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/role.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/role.go index 363b2c6cd..66f382c07 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/role.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rolebinding.go b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rolebinding.go index 8d9f1f617..67d3d331b 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rolebinding.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/BUILD deleted file mode 100644 index db9b36f32..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "generated_expansion.go", - "priorityclass.go", - "scheduling_client.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1", - deps = [ - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/BUILD deleted file mode 100644 index f5c9c6436..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_priorityclass.go", - "fake_scheduling_client.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake", - deps = [ - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go index 9946411e2..8ab4421a9 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *v1alpha1.Priori if label == nil { label = labels.Everything() } - list := &v1alpha1.PriorityClassList{} + list := &v1alpha1.PriorityClassList{ListMeta: obj.(*v1alpha1.PriorityClassList).ListMeta} for _, item := range obj.(*v1alpha1.PriorityClassList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go index 6e0a9659e..974ba193f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/generated_expansion.go index 682f0f3bf..52f81d881 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/priorityclass.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/priorityclass.go index 055a0e3f3..6845d25c3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/priorityclass.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/scheduling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/scheduling_client.go index f030b319e..375f41b8d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/scheduling_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/scheduling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/doc.go new file mode 100644 index 000000000..771101956 --- /dev/null +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1beta1 diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/doc.go new file mode 100644 index 000000000..16f443990 --- /dev/null +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go new file mode 100644 index 000000000..e234fec66 --- /dev/null +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go @@ -0,0 +1,120 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1beta1 "k8s.io/api/scheduling/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakePriorityClasses implements PriorityClassInterface +type FakePriorityClasses struct { + Fake *FakeSchedulingV1beta1 +} + +var priorityclassesResource = schema.GroupVersionResource{Group: "scheduling.k8s.io", Version: "v1beta1", Resource: "priorityclasses"} + +var priorityclassesKind = schema.GroupVersionKind{Group: "scheduling.k8s.io", Version: "v1beta1", Kind: "PriorityClass"} + +// Get takes name of the priorityClass, and returns the corresponding priorityClass object, and an error if there is any. +func (c *FakePriorityClasses) Get(name string, options v1.GetOptions) (result *v1beta1.PriorityClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(priorityclassesResource, name), &v1beta1.PriorityClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.PriorityClass), err +} + +// List takes label and field selectors, and returns the list of PriorityClasses that match those selectors. +func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *v1beta1.PriorityClassList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(priorityclassesResource, priorityclassesKind, opts), &v1beta1.PriorityClassList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta1.PriorityClassList{ListMeta: obj.(*v1beta1.PriorityClassList).ListMeta} + for _, item := range obj.(*v1beta1.PriorityClassList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested priorityClasses. +func (c *FakePriorityClasses) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(priorityclassesResource, opts)) +} + +// Create takes the representation of a priorityClass and creates it. Returns the server's representation of the priorityClass, and an error, if there is any. +func (c *FakePriorityClasses) Create(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(priorityclassesResource, priorityClass), &v1beta1.PriorityClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.PriorityClass), err +} + +// Update takes the representation of a priorityClass and updates it. Returns the server's representation of the priorityClass, and an error, if there is any. +func (c *FakePriorityClasses) Update(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(priorityclassesResource, priorityClass), &v1beta1.PriorityClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.PriorityClass), err +} + +// Delete takes name of the priorityClass and deletes it. Returns an error if one occurs. +func (c *FakePriorityClasses) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(priorityclassesResource, name), &v1beta1.PriorityClass{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakePriorityClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(priorityclassesResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1beta1.PriorityClassList{}) + return err +} + +// Patch applies the patch and returns the patched priorityClass. +func (c *FakePriorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, data, subresources...), &v1beta1.PriorityClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.PriorityClass), err +} diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_scheduling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_scheduling_client.go new file mode 100644 index 000000000..4a6878a45 --- /dev/null +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_scheduling_client.go @@ -0,0 +1,40 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeSchedulingV1beta1 struct { + *testing.Fake +} + +func (c *FakeSchedulingV1beta1) PriorityClasses() v1beta1.PriorityClassInterface { + return &FakePriorityClasses{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeSchedulingV1beta1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/generated_expansion.go new file mode 100644 index 000000000..3bab873e6 --- /dev/null +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +type PriorityClassExpansion interface{} diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/priorityclass.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/priorityclass.go new file mode 100644 index 000000000..57b9766e4 --- /dev/null +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/priorityclass.go @@ -0,0 +1,147 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1beta1 "k8s.io/api/scheduling/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + scheme "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +// PriorityClassesGetter has a method to return a PriorityClassInterface. +// A group's client should implement this interface. +type PriorityClassesGetter interface { + PriorityClasses() PriorityClassInterface +} + +// PriorityClassInterface has methods to work with PriorityClass resources. +type PriorityClassInterface interface { + Create(*v1beta1.PriorityClass) (*v1beta1.PriorityClass, error) + Update(*v1beta1.PriorityClass) (*v1beta1.PriorityClass, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1beta1.PriorityClass, error) + List(opts v1.ListOptions) (*v1beta1.PriorityClassList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) + PriorityClassExpansion +} + +// priorityClasses implements PriorityClassInterface +type priorityClasses struct { + client rest.Interface +} + +// newPriorityClasses returns a PriorityClasses +func newPriorityClasses(c *SchedulingV1beta1Client) *priorityClasses { + return &priorityClasses{ + client: c.RESTClient(), + } +} + +// Get takes name of the priorityClass, and returns the corresponding priorityClass object, and an error if there is any. +func (c *priorityClasses) Get(name string, options v1.GetOptions) (result *v1beta1.PriorityClass, err error) { + result = &v1beta1.PriorityClass{} + err = c.client.Get(). + Resource("priorityclasses"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of PriorityClasses that match those selectors. +func (c *priorityClasses) List(opts v1.ListOptions) (result *v1beta1.PriorityClassList, err error) { + result = &v1beta1.PriorityClassList{} + err = c.client.Get(). + Resource("priorityclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested priorityClasses. +func (c *priorityClasses) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Resource("priorityclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a priorityClass and creates it. Returns the server's representation of the priorityClass, and an error, if there is any. +func (c *priorityClasses) Create(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) { + result = &v1beta1.PriorityClass{} + err = c.client.Post(). + Resource("priorityclasses"). + Body(priorityClass). + Do(). + Into(result) + return +} + +// Update takes the representation of a priorityClass and updates it. Returns the server's representation of the priorityClass, and an error, if there is any. +func (c *priorityClasses) Update(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) { + result = &v1beta1.PriorityClass{} + err = c.client.Put(). + Resource("priorityclasses"). + Name(priorityClass.Name). + Body(priorityClass). + Do(). + Into(result) + return +} + +// Delete takes name of the priorityClass and deletes it. Returns an error if one occurs. +func (c *priorityClasses) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("priorityclasses"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *priorityClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Resource("priorityclasses"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched priorityClass. +func (c *priorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) { + result = &v1beta1.PriorityClass{} + err = c.client.Patch(pt). + Resource("priorityclasses"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/scheduling_client.go b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/scheduling_client.go new file mode 100644 index 000000000..6feec4aec --- /dev/null +++ b/vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/scheduling_client.go @@ -0,0 +1,90 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1beta1 "k8s.io/api/scheduling/v1beta1" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +type SchedulingV1beta1Interface interface { + RESTClient() rest.Interface + PriorityClassesGetter +} + +// SchedulingV1beta1Client is used to interact with features provided by the scheduling.k8s.io group. +type SchedulingV1beta1Client struct { + restClient rest.Interface +} + +func (c *SchedulingV1beta1Client) PriorityClasses() PriorityClassInterface { + return newPriorityClasses(c) +} + +// NewForConfig creates a new SchedulingV1beta1Client for the given config. +func NewForConfig(c *rest.Config) (*SchedulingV1beta1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &SchedulingV1beta1Client{client}, nil +} + +// NewForConfigOrDie creates a new SchedulingV1beta1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *SchedulingV1beta1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new SchedulingV1beta1Client for the given RESTClient. +func New(c rest.Interface) *SchedulingV1beta1Client { + return &SchedulingV1beta1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1beta1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *SchedulingV1beta1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/BUILD deleted file mode 100644 index a1abc87e3..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "generated_expansion.go", - "podpreset.go", - "settings_client.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/settings/v1alpha1", - deps = [ - "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/BUILD deleted file mode 100644 index f8823f465..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_podpreset.go", - "fake_settings_client.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake", - deps = [ - "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go index 512b38f54..90eaccec5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePodPresets) List(opts v1.ListOptions) (result *v1alpha1.PodPresetLi if label == nil { label = labels.Everything() } - list := &v1alpha1.PodPresetList{} + list := &v1alpha1.PodPresetList{ListMeta: obj.(*v1alpha1.PodPresetList).ListMeta} for _, item := range obj.(*v1alpha1.PodPresetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go index fb07a8248..a142edfed 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/generated_expansion.go index f0dbcc607..23d9f94d5 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/podpreset.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/podpreset.go index 25ed8f543..f000ae486 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/podpreset.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/settings_client.go b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/settings_client.go index 77fa64040..c2a03b960 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/settings_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/settings_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/BUILD deleted file mode 100644 index 0c5507141..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "generated_expansion.go", - "storage_client.go", - "storageclass.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/storage/v1", - deps = [ - "//vendor/k8s.io/api/storage/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/BUILD deleted file mode 100644 index be83e85f8..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_storage_client.go", - "fake_storageclass.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/storage/v1/fake", - deps = [ - "//vendor/k8s.io/api/storage/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go index 9ba1f5104..fc6f98cf6 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go index 147ad8028..2b0e279bb 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeStorageClasses) List(opts v1.ListOptions) (result *storage_v1.Stora if label == nil { label = labels.Everything() } - list := &storage_v1.StorageClassList{} + list := &storage_v1.StorageClassList{ListMeta: obj.(*storage_v1.StorageClassList).ListMeta} for _, item := range obj.(*storage_v1.StorageClassList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/generated_expansion.go index 08fedd7ed..2bea7ec7f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/storage_client.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/storage_client.go index 36a189c46..ac48f4916 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/storage_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/storageclass.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/storageclass.go index 24133cd62..74410b245 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/storageclass.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/BUILD deleted file mode 100644 index 155421963..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "generated_expansion.go", - "storage_client.go", - "volumeattachment.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/storage/v1alpha1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/BUILD deleted file mode 100644 index a509ba7fc..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_storage_client.go", - "fake_volumeattachment.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go index 5a9ed0964..1a4d9f56f 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go index c5db88531..af04b681c 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeVolumeAttachments) List(opts v1.ListOptions) (result *v1alpha1.Volu if label == nil { label = labels.Everything() } - list := &v1alpha1.VolumeAttachmentList{} + list := &v1alpha1.VolumeAttachmentList{ListMeta: obj.(*v1alpha1.VolumeAttachmentList).ListMeta} for _, item := range obj.(*v1alpha1.VolumeAttachmentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/generated_expansion.go index e3fc3f399..cdb7ab2f8 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/storage_client.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/storage_client.go index 63834e462..c52f630ac 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/storage_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/volumeattachment.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/volumeattachment.go index 7bf79a6c1..e6af00185 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/volumeattachment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/BUILD deleted file mode 100644 index 79d13929c..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "generated_expansion.go", - "storage_client.go", - "storageclass.go", - "volumeattachment.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/storage/v1beta1", - deps = [ - "//vendor/k8s.io/api/storage/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/BUILD b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/BUILD deleted file mode 100644 index 743008884..000000000 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "fake_storage_client.go", - "fake_storageclass.go", - "fake_volumeattachment.go", - ], - importpath = "k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake", - deps = [ - "//vendor/k8s.io/api/storage/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go index a81d90542..e0e3f1d78 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go index ce1e72d53..cbfbab1a3 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeStorageClasses) List(opts v1.ListOptions) (result *v1beta1.StorageC if label == nil { label = labels.Everything() } - list := &v1beta1.StorageClassList{} + list := &v1beta1.StorageClassList{ListMeta: obj.(*v1beta1.StorageClassList).ListMeta} for _, item := range obj.(*v1beta1.StorageClassList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go index 8bbf197dd..04c0c463a 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeVolumeAttachments) List(opts v1.ListOptions) (result *v1beta1.Volum if label == nil { label = labels.Everything() } - list := &v1beta1.VolumeAttachmentList{} + list := &v1beta1.VolumeAttachmentList{ListMeta: obj.(*v1beta1.VolumeAttachmentList).ListMeta} for _, item := range obj.(*v1beta1.VolumeAttachmentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/generated_expansion.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/generated_expansion.go index 5bb931f05..559f88f67 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storage_client.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storage_client.go index 4ca05be6f..4bdebb878 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storage_client.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storageclass.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storageclass.go index 63047a7fb..fbe1fd4c2 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storageclass.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/volumeattachment.go b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/volumeattachment.go index fab0801b0..5cd2d3919 100644 --- a/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/volumeattachment.go +++ b/vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/BUILD b/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/BUILD deleted file mode 100644 index df0364232..000000000 --- a/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "initializerconfiguration.go", - ], - importpath = "k8s.io/client-go/listers/admissionregistration/v1alpha1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/expansion_generated.go b/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/expansion_generated.go index 868ee66cf..2c9f9f6a6 100644 --- a/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/initializerconfiguration.go b/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/initializerconfiguration.go index a2cc796dc..dbd7301fc 100644 --- a/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/initializerconfiguration.go +++ b/vendor/k8s.io/client-go/listers/admissionregistration/v1alpha1/initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/BUILD deleted file mode 100644 index d5128618f..000000000 --- a/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "mutatingwebhookconfiguration.go", - "validatingwebhookconfiguration.go", - ], - importpath = "k8s.io/client-go/listers/admissionregistration/v1beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/expansion_generated.go index 93dddb5ff..8960abc4f 100644 --- a/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go b/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go index 015587e80..b38732c36 100644 --- a/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/validatingwebhookconfiguration.go b/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/validatingwebhookconfiguration.go index 243589b2f..b89c9bbe2 100644 --- a/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/validatingwebhookconfiguration.go +++ b/vendor/k8s.io/client-go/listers/admissionregistration/v1beta1/validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1/BUILD b/vendor/k8s.io/client-go/listers/apps/v1/BUILD deleted file mode 100644 index fb3cfbbb6..000000000 --- a/vendor/k8s.io/client-go/listers/apps/v1/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "controllerrevision.go", - "daemonset.go", - "daemonset_expansion.go", - "deployment.go", - "deployment_expansion.go", - "expansion_generated.go", - "replicaset.go", - "replicaset_expansion.go", - "statefulset.go", - "statefulset_expansion.go", - ], - importpath = "k8s.io/client-go/listers/apps/v1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/apps/v1:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/listers/apps/v1/controllerrevision.go b/vendor/k8s.io/client-go/listers/apps/v1/controllerrevision.go index 19f567e82..9029805a3 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1/controllerrevision.go +++ b/vendor/k8s.io/client-go/listers/apps/v1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1/daemonset.go b/vendor/k8s.io/client-go/listers/apps/v1/daemonset.go index 7fcd1e063..b022ecc4a 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1/daemonset.go +++ b/vendor/k8s.io/client-go/listers/apps/v1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1/deployment.go b/vendor/k8s.io/client-go/listers/apps/v1/deployment.go index 2d2ecf0cf..d1be7156e 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1/deployment.go +++ b/vendor/k8s.io/client-go/listers/apps/v1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1/expansion_generated.go b/vendor/k8s.io/client-go/listers/apps/v1/expansion_generated.go index 1e8bf6fec..7f5815f79 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/apps/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1/replicaset.go b/vendor/k8s.io/client-go/listers/apps/v1/replicaset.go index 99fb92ff4..d487ef656 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1/replicaset.go +++ b/vendor/k8s.io/client-go/listers/apps/v1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1/statefulset.go b/vendor/k8s.io/client-go/listers/apps/v1/statefulset.go index 6ad54b71f..cc0031858 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1/statefulset.go +++ b/vendor/k8s.io/client-go/listers/apps/v1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/apps/v1beta1/BUILD deleted file mode 100644 index f6ddce530..000000000 --- a/vendor/k8s.io/client-go/listers/apps/v1beta1/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "controllerrevision.go", - "deployment.go", - "expansion_generated.go", - "scale.go", - "statefulset.go", - "statefulset_expansion.go", - ], - importpath = "k8s.io/client-go/listers/apps/v1beta1", - deps = [ - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta1/controllerrevision.go b/vendor/k8s.io/client-go/listers/apps/v1beta1/controllerrevision.go index 95aeb0236..d84a865b3 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta1/controllerrevision.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta1/deployment.go b/vendor/k8s.io/client-go/listers/apps/v1beta1/deployment.go index 4f6e883ba..048558f2a 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta1/deployment.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/apps/v1beta1/expansion_generated.go index 4f3813a94..8f8d08434 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta1/scale.go b/vendor/k8s.io/client-go/listers/apps/v1beta1/scale.go index 85bf3a6f4..ef8a2630e 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta1/scale.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta1/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta1/statefulset.go b/vendor/k8s.io/client-go/listers/apps/v1beta1/statefulset.go index a967e8492..277beb3e4 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta1/statefulset.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta2/BUILD b/vendor/k8s.io/client-go/listers/apps/v1beta2/BUILD deleted file mode 100644 index 50aefcab1..000000000 --- a/vendor/k8s.io/client-go/listers/apps/v1beta2/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "controllerrevision.go", - "daemonset.go", - "daemonset_expansion.go", - "deployment.go", - "deployment_expansion.go", - "expansion_generated.go", - "replicaset.go", - "replicaset_expansion.go", - "scale.go", - "statefulset.go", - "statefulset_expansion.go", - ], - importpath = "k8s.io/client-go/listers/apps/v1beta2", - deps = [ - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta2/controllerrevision.go b/vendor/k8s.io/client-go/listers/apps/v1beta2/controllerrevision.go index 3d5274dc3..904b59b24 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta2/controllerrevision.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta2/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta2/daemonset.go b/vendor/k8s.io/client-go/listers/apps/v1beta2/daemonset.go index 0ea4dc83f..8a40d2c86 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta2/daemonset.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta2/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta2/deployment.go b/vendor/k8s.io/client-go/listers/apps/v1beta2/deployment.go index 8855bb20c..32beaf25c 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta2/deployment.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta2/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta2/expansion_generated.go b/vendor/k8s.io/client-go/listers/apps/v1beta2/expansion_generated.go index 48cbedb8f..d468f38e7 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta2/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta2/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta2/replicaset.go b/vendor/k8s.io/client-go/listers/apps/v1beta2/replicaset.go index 0fd8dbaa4..18c2136a2 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta2/replicaset.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta2/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta2/scale.go b/vendor/k8s.io/client-go/listers/apps/v1beta2/scale.go index f53e42ce8..d89329864 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta2/scale.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta2/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/apps/v1beta2/statefulset.go b/vendor/k8s.io/client-go/listers/apps/v1beta2/statefulset.go index 2e095ace4..544bff458 100644 --- a/vendor/k8s.io/client-go/listers/apps/v1beta2/statefulset.go +++ b/vendor/k8s.io/client-go/listers/apps/v1beta2/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authentication/v1/BUILD b/vendor/k8s.io/client-go/listers/authentication/v1/BUILD deleted file mode 100644 index 18c90f1d3..000000000 --- a/vendor/k8s.io/client-go/listers/authentication/v1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "tokenreview.go", - ], - importpath = "k8s.io/client-go/listers/authentication/v1", - deps = [ - "//vendor/k8s.io/api/authentication/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/authentication/v1/expansion_generated.go b/vendor/k8s.io/client-go/listers/authentication/v1/expansion_generated.go index 77b284d8d..a8d097f40 100644 --- a/vendor/k8s.io/client-go/listers/authentication/v1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/authentication/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authentication/v1/tokenreview.go b/vendor/k8s.io/client-go/listers/authentication/v1/tokenreview.go index 5f2c6c3e6..5bb907c0c 100644 --- a/vendor/k8s.io/client-go/listers/authentication/v1/tokenreview.go +++ b/vendor/k8s.io/client-go/listers/authentication/v1/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authentication/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/authentication/v1beta1/BUILD deleted file mode 100644 index 45a7b02eb..000000000 --- a/vendor/k8s.io/client-go/listers/authentication/v1beta1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "tokenreview.go", - ], - importpath = "k8s.io/client-go/listers/authentication/v1beta1", - deps = [ - "//vendor/k8s.io/api/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/authentication/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/authentication/v1beta1/expansion_generated.go index 3b2b18860..82192059d 100644 --- a/vendor/k8s.io/client-go/listers/authentication/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/authentication/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authentication/v1beta1/tokenreview.go b/vendor/k8s.io/client-go/listers/authentication/v1beta1/tokenreview.go index 9db014e9b..148bcae78 100644 --- a/vendor/k8s.io/client-go/listers/authentication/v1beta1/tokenreview.go +++ b/vendor/k8s.io/client-go/listers/authentication/v1beta1/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1/BUILD b/vendor/k8s.io/client-go/listers/authorization/v1/BUILD deleted file mode 100644 index dbea6dcc2..000000000 --- a/vendor/k8s.io/client-go/listers/authorization/v1/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "localsubjectaccessreview.go", - "selfsubjectaccessreview.go", - "selfsubjectrulesreview.go", - "subjectaccessreview.go", - ], - importpath = "k8s.io/client-go/listers/authorization/v1", - deps = [ - "//vendor/k8s.io/api/authorization/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/authorization/v1/expansion_generated.go b/vendor/k8s.io/client-go/listers/authorization/v1/expansion_generated.go index 9a0f2e212..af91939fb 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1/localsubjectaccessreview.go b/vendor/k8s.io/client-go/listers/authorization/v1/localsubjectaccessreview.go index 99055b348..e064c94c1 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1/localsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1/selfsubjectaccessreview.go b/vendor/k8s.io/client-go/listers/authorization/v1/selfsubjectaccessreview.go index 627e4dd74..f89bc1dde 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1/selfsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1/selfsubjectrulesreview.go b/vendor/k8s.io/client-go/listers/authorization/v1/selfsubjectrulesreview.go index 6b2f06352..c65b5f84d 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1/selfsubjectrulesreview.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1/subjectaccessreview.go b/vendor/k8s.io/client-go/listers/authorization/v1/subjectaccessreview.go index ca7b47b46..0d6c29b39 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1/subjectaccessreview.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/authorization/v1beta1/BUILD deleted file mode 100644 index 665642706..000000000 --- a/vendor/k8s.io/client-go/listers/authorization/v1beta1/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "localsubjectaccessreview.go", - "selfsubjectaccessreview.go", - "selfsubjectrulesreview.go", - "subjectaccessreview.go", - ], - importpath = "k8s.io/client-go/listers/authorization/v1beta1", - deps = [ - "//vendor/k8s.io/api/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/authorization/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/authorization/v1beta1/expansion_generated.go index d140d6563..24b06185e 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1beta1/localsubjectaccessreview.go b/vendor/k8s.io/client-go/listers/authorization/v1beta1/localsubjectaccessreview.go index 534e39aa9..4eb8158a3 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1beta1/localsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1beta1/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectaccessreview.go b/vendor/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectaccessreview.go index c2e82dbb9..4736ccdd5 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectaccessreview.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectrulesreview.go b/vendor/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectrulesreview.go index 5ce83f217..4e47abc3a 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectrulesreview.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/authorization/v1beta1/subjectaccessreview.go b/vendor/k8s.io/client-go/listers/authorization/v1beta1/subjectaccessreview.go index b1853fc3c..5782b4f23 100644 --- a/vendor/k8s.io/client-go/listers/authorization/v1beta1/subjectaccessreview.go +++ b/vendor/k8s.io/client-go/listers/authorization/v1beta1/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/autoscaling/v1/BUILD b/vendor/k8s.io/client-go/listers/autoscaling/v1/BUILD deleted file mode 100644 index 8c5bfd95d..000000000 --- a/vendor/k8s.io/client-go/listers/autoscaling/v1/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "horizontalpodautoscaler.go", - ], - importpath = "k8s.io/client-go/listers/autoscaling/v1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/listers/autoscaling/v1/expansion_generated.go b/vendor/k8s.io/client-go/listers/autoscaling/v1/expansion_generated.go index a20ab75da..05253c770 100644 --- a/vendor/k8s.io/client-go/listers/autoscaling/v1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/autoscaling/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/autoscaling/v1/horizontalpodautoscaler.go b/vendor/k8s.io/client-go/listers/autoscaling/v1/horizontalpodautoscaler.go index 27ade7ddb..6d563ca98 100644 --- a/vendor/k8s.io/client-go/listers/autoscaling/v1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/client-go/listers/autoscaling/v1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/BUILD b/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/BUILD deleted file mode 100644 index 78aca5847..000000000 --- a/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "horizontalpodautoscaler.go", - ], - importpath = "k8s.io/client-go/listers/autoscaling/v2beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/expansion_generated.go index c026b65d5..8d46a4b6e 100644 --- a/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/horizontalpodautoscaler.go b/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/horizontalpodautoscaler.go index 4c29df910..08d13803b 100644 --- a/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/client-go/listers/autoscaling/v2beta1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/batch/v1/BUILD b/vendor/k8s.io/client-go/listers/batch/v1/BUILD deleted file mode 100644 index c695b9856..000000000 --- a/vendor/k8s.io/client-go/listers/batch/v1/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "job.go", - "job_expansion.go", - ], - importpath = "k8s.io/client-go/listers/batch/v1", - deps = [ - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/batch/v1/expansion_generated.go b/vendor/k8s.io/client-go/listers/batch/v1/expansion_generated.go index 63091e84a..c43caf240 100644 --- a/vendor/k8s.io/client-go/listers/batch/v1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/batch/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/batch/v1/job.go b/vendor/k8s.io/client-go/listers/batch/v1/job.go index e29e0271c..909b6f88f 100644 --- a/vendor/k8s.io/client-go/listers/batch/v1/job.go +++ b/vendor/k8s.io/client-go/listers/batch/v1/job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/batch/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/batch/v1beta1/BUILD deleted file mode 100644 index 0ae1a2eda..000000000 --- a/vendor/k8s.io/client-go/listers/batch/v1beta1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "cronjob.go", - "expansion_generated.go", - ], - importpath = "k8s.io/client-go/listers/batch/v1beta1", - deps = [ - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/batch/v1beta1/cronjob.go b/vendor/k8s.io/client-go/listers/batch/v1beta1/cronjob.go index 93f197986..521378ebf 100644 --- a/vendor/k8s.io/client-go/listers/batch/v1beta1/cronjob.go +++ b/vendor/k8s.io/client-go/listers/batch/v1beta1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/batch/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/batch/v1beta1/expansion_generated.go index 1d6cc198a..be2742ef6 100644 --- a/vendor/k8s.io/client-go/listers/batch/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/batch/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/batch/v2alpha1/BUILD b/vendor/k8s.io/client-go/listers/batch/v2alpha1/BUILD deleted file mode 100644 index 92220512e..000000000 --- a/vendor/k8s.io/client-go/listers/batch/v2alpha1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "cronjob.go", - "expansion_generated.go", - ], - importpath = "k8s.io/client-go/listers/batch/v2alpha1", - deps = [ - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/batch/v2alpha1/cronjob.go b/vendor/k8s.io/client-go/listers/batch/v2alpha1/cronjob.go index 6af5f1457..2623f1959 100644 --- a/vendor/k8s.io/client-go/listers/batch/v2alpha1/cronjob.go +++ b/vendor/k8s.io/client-go/listers/batch/v2alpha1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/batch/v2alpha1/expansion_generated.go b/vendor/k8s.io/client-go/listers/batch/v2alpha1/expansion_generated.go index 11f6c3471..a30c7a619 100644 --- a/vendor/k8s.io/client-go/listers/batch/v2alpha1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/batch/v2alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/certificates/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/certificates/v1beta1/BUILD deleted file mode 100644 index b7ca4270c..000000000 --- a/vendor/k8s.io/client-go/listers/certificates/v1beta1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "certificatesigningrequest.go", - "expansion_generated.go", - ], - importpath = "k8s.io/client-go/listers/certificates/v1beta1", - deps = [ - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/certificates/v1beta1/certificatesigningrequest.go b/vendor/k8s.io/client-go/listers/certificates/v1beta1/certificatesigningrequest.go index a122c3660..47c282984 100644 --- a/vendor/k8s.io/client-go/listers/certificates/v1beta1/certificatesigningrequest.go +++ b/vendor/k8s.io/client-go/listers/certificates/v1beta1/certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/certificates/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/certificates/v1beta1/expansion_generated.go index 6815de7ad..68f993cd6 100644 --- a/vendor/k8s.io/client-go/listers/certificates/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/certificates/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/BUILD b/vendor/k8s.io/client-go/listers/core/v1/BUILD deleted file mode 100644 index 313cdc299..000000000 --- a/vendor/k8s.io/client-go/listers/core/v1/BUILD +++ /dev/null @@ -1,52 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "componentstatus.go", - "configmap.go", - "endpoints.go", - "event.go", - "expansion_generated.go", - "limitrange.go", - "namespace.go", - "node.go", - "node_expansion.go", - "persistentvolume.go", - "persistentvolumeclaim.go", - "pod.go", - "podtemplate.go", - "replicationcontroller.go", - "replicationcontroller_expansion.go", - "resourcequota.go", - "secret.go", - "service.go", - "service_expansion.go", - "serviceaccount.go", - ], - importpath = "k8s.io/client-go/listers/core/v1", - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/core/v1/componentstatus.go b/vendor/k8s.io/client-go/listers/core/v1/componentstatus.go index 82fbedac2..23d070810 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/componentstatus.go +++ b/vendor/k8s.io/client-go/listers/core/v1/componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/configmap.go b/vendor/k8s.io/client-go/listers/core/v1/configmap.go index fc927ab2c..55d7cd4d3 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/configmap.go +++ b/vendor/k8s.io/client-go/listers/core/v1/configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/endpoints.go b/vendor/k8s.io/client-go/listers/core/v1/endpoints.go index 7799562d7..ac2fdfc57 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/endpoints.go +++ b/vendor/k8s.io/client-go/listers/core/v1/endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/event.go b/vendor/k8s.io/client-go/listers/core/v1/event.go index 738e333db..a9d2db01a 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/event.go +++ b/vendor/k8s.io/client-go/listers/core/v1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/expansion_generated.go b/vendor/k8s.io/client-go/listers/core/v1/expansion_generated.go index b8b985ce0..fac0221b8 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/core/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/limitrange.go b/vendor/k8s.io/client-go/listers/core/v1/limitrange.go index 4ee02634d..c773c433e 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/limitrange.go +++ b/vendor/k8s.io/client-go/listers/core/v1/limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/namespace.go b/vendor/k8s.io/client-go/listers/core/v1/namespace.go index b819d741e..6a17d0457 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/namespace.go +++ b/vendor/k8s.io/client-go/listers/core/v1/namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/node.go b/vendor/k8s.io/client-go/listers/core/v1/node.go index 21a8a0675..b568ebe47 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/node.go +++ b/vendor/k8s.io/client-go/listers/core/v1/node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/persistentvolume.go b/vendor/k8s.io/client-go/listers/core/v1/persistentvolume.go index a88dbd0c0..1d7c6ca76 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/persistentvolume.go +++ b/vendor/k8s.io/client-go/listers/core/v1/persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/persistentvolumeclaim.go b/vendor/k8s.io/client-go/listers/core/v1/persistentvolumeclaim.go index 8c3d5f566..501a38c43 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/persistentvolumeclaim.go +++ b/vendor/k8s.io/client-go/listers/core/v1/persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/pod.go b/vendor/k8s.io/client-go/listers/core/v1/pod.go index d3ce8ab32..442f8c55f 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/pod.go +++ b/vendor/k8s.io/client-go/listers/core/v1/pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/podtemplate.go b/vendor/k8s.io/client-go/listers/core/v1/podtemplate.go index 91c2a4661..9a17f820c 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/podtemplate.go +++ b/vendor/k8s.io/client-go/listers/core/v1/podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/replicationcontroller.go b/vendor/k8s.io/client-go/listers/core/v1/replicationcontroller.go index ee00a465c..8b17aa2c4 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/replicationcontroller.go +++ b/vendor/k8s.io/client-go/listers/core/v1/replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/resourcequota.go b/vendor/k8s.io/client-go/listers/core/v1/resourcequota.go index fd3119d45..f5b7030cc 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/resourcequota.go +++ b/vendor/k8s.io/client-go/listers/core/v1/resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/secret.go b/vendor/k8s.io/client-go/listers/core/v1/secret.go index f8c2b11e1..e9ef24934 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/secret.go +++ b/vendor/k8s.io/client-go/listers/core/v1/secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/service.go b/vendor/k8s.io/client-go/listers/core/v1/service.go index d872540b3..3b5941acb 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/service.go +++ b/vendor/k8s.io/client-go/listers/core/v1/service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/core/v1/serviceaccount.go b/vendor/k8s.io/client-go/listers/core/v1/serviceaccount.go index 9973af66b..8b94cf594 100644 --- a/vendor/k8s.io/client-go/listers/core/v1/serviceaccount.go +++ b/vendor/k8s.io/client-go/listers/core/v1/serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/events/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/events/v1beta1/BUILD deleted file mode 100644 index f4ea35d4a..000000000 --- a/vendor/k8s.io/client-go/listers/events/v1beta1/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "event.go", - "expansion_generated.go", - ], - importpath = "k8s.io/client-go/listers/events/v1beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/events/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/listers/events/v1beta1/event.go b/vendor/k8s.io/client-go/listers/events/v1beta1/event.go index c52afd091..4a5bc3997 100644 --- a/vendor/k8s.io/client-go/listers/events/v1beta1/event.go +++ b/vendor/k8s.io/client-go/listers/events/v1beta1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/events/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/events/v1beta1/expansion_generated.go index 9971dd5dd..d311691d9 100644 --- a/vendor/k8s.io/client-go/listers/events/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/events/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/extensions/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/extensions/v1beta1/BUILD deleted file mode 100644 index 49b895c3e..000000000 --- a/vendor/k8s.io/client-go/listers/extensions/v1beta1/BUILD +++ /dev/null @@ -1,60 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "daemonset.go", - "daemonset_expansion.go", - "deployment.go", - "deployment_expansion.go", - "expansion_generated.go", - "ingress.go", - "podsecuritypolicy.go", - "replicaset.go", - "replicaset_expansion.go", - "scale.go", - ], - importpath = "k8s.io/client-go/listers/extensions/v1beta1", - deps = [ - "//vendor/k8s.io/api/apps/v1beta1: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/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["daemonset_expansion_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/extensions/v1beta1/daemonset.go b/vendor/k8s.io/client-go/listers/extensions/v1beta1/daemonset.go index b63c32b97..a7bb6657a 100644 --- a/vendor/k8s.io/client-go/listers/extensions/v1beta1/daemonset.go +++ b/vendor/k8s.io/client-go/listers/extensions/v1beta1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/extensions/v1beta1/deployment.go b/vendor/k8s.io/client-go/listers/extensions/v1beta1/deployment.go index ea5168fef..13e307189 100644 --- a/vendor/k8s.io/client-go/listers/extensions/v1beta1/deployment.go +++ b/vendor/k8s.io/client-go/listers/extensions/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/extensions/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/extensions/v1beta1/expansion_generated.go index 87c3cbe3b..b5ee8a492 100644 --- a/vendor/k8s.io/client-go/listers/extensions/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/extensions/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/extensions/v1beta1/ingress.go b/vendor/k8s.io/client-go/listers/extensions/v1beta1/ingress.go index 1f9e34d17..1bc33ede2 100644 --- a/vendor/k8s.io/client-go/listers/extensions/v1beta1/ingress.go +++ b/vendor/k8s.io/client-go/listers/extensions/v1beta1/ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/extensions/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/client-go/listers/extensions/v1beta1/podsecuritypolicy.go index fadd212f1..1298e87ba 100644 --- a/vendor/k8s.io/client-go/listers/extensions/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/client-go/listers/extensions/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/extensions/v1beta1/replicaset.go b/vendor/k8s.io/client-go/listers/extensions/v1beta1/replicaset.go index 930db4480..d3e741a86 100644 --- a/vendor/k8s.io/client-go/listers/extensions/v1beta1/replicaset.go +++ b/vendor/k8s.io/client-go/listers/extensions/v1beta1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/extensions/v1beta1/scale.go b/vendor/k8s.io/client-go/listers/extensions/v1beta1/scale.go index 67d45e328..527d4be42 100644 --- a/vendor/k8s.io/client-go/listers/extensions/v1beta1/scale.go +++ b/vendor/k8s.io/client-go/listers/extensions/v1beta1/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/BUILD b/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/BUILD deleted file mode 100644 index da825e6a5..000000000 --- a/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "imagereview.go", - ], - importpath = "k8s.io/client-go/listers/imagepolicy/v1alpha1", - deps = [ - "//vendor/k8s.io/api/imagepolicy/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/expansion_generated.go b/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/expansion_generated.go index 1529fcf3f..9cb13f792 100644 --- a/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/imagereview.go b/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/imagereview.go index cdb046cf9..722e456e7 100644 --- a/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/imagereview.go +++ b/vendor/k8s.io/client-go/listers/imagepolicy/v1alpha1/imagereview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/networking/v1/BUILD b/vendor/k8s.io/client-go/listers/networking/v1/BUILD deleted file mode 100644 index 64dc638ba..000000000 --- a/vendor/k8s.io/client-go/listers/networking/v1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "networkpolicy.go", - ], - importpath = "k8s.io/client-go/listers/networking/v1", - deps = [ - "//vendor/k8s.io/api/networking/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/networking/v1/expansion_generated.go b/vendor/k8s.io/client-go/listers/networking/v1/expansion_generated.go index 458a1d249..e03a52385 100644 --- a/vendor/k8s.io/client-go/listers/networking/v1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/networking/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/networking/v1/networkpolicy.go b/vendor/k8s.io/client-go/listers/networking/v1/networkpolicy.go index b70adedf1..e5d997747 100644 --- a/vendor/k8s.io/client-go/listers/networking/v1/networkpolicy.go +++ b/vendor/k8s.io/client-go/listers/networking/v1/networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/policy/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/policy/v1beta1/BUILD deleted file mode 100644 index 2c5f33df4..000000000 --- a/vendor/k8s.io/client-go/listers/policy/v1beta1/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "eviction.go", - "expansion_generated.go", - "poddisruptionbudget.go", - "poddisruptionbudget_expansion.go", - "podsecuritypolicy.go", - ], - importpath = "k8s.io/client-go/listers/policy/v1beta1", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/policy/v1beta1/eviction.go b/vendor/k8s.io/client-go/listers/policy/v1beta1/eviction.go index 29c454e2a..6e27f5fdc 100644 --- a/vendor/k8s.io/client-go/listers/policy/v1beta1/eviction.go +++ b/vendor/k8s.io/client-go/listers/policy/v1beta1/eviction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/policy/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/policy/v1beta1/expansion_generated.go index 3e63c2c9c..9a005f20b 100644 --- a/vendor/k8s.io/client-go/listers/policy/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/policy/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/policy/v1beta1/poddisruptionbudget.go b/vendor/k8s.io/client-go/listers/policy/v1beta1/poddisruptionbudget.go index 7304f36b2..b1f83ee16 100644 --- a/vendor/k8s.io/client-go/listers/policy/v1beta1/poddisruptionbudget.go +++ b/vendor/k8s.io/client-go/listers/policy/v1beta1/poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/policy/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/client-go/listers/policy/v1beta1/podsecuritypolicy.go index d80f5c56e..e943d3a05 100644 --- a/vendor/k8s.io/client-go/listers/policy/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/client-go/listers/policy/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1/BUILD b/vendor/k8s.io/client-go/listers/rbac/v1/BUILD deleted file mode 100644 index 9facdc04d..000000000 --- a/vendor/k8s.io/client-go/listers/rbac/v1/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clusterrole.go", - "clusterrolebinding.go", - "expansion_generated.go", - "role.go", - "rolebinding.go", - ], - importpath = "k8s.io/client-go/listers/rbac/v1", - deps = [ - "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/rbac/v1/clusterrole.go b/vendor/k8s.io/client-go/listers/rbac/v1/clusterrole.go index eb1d87006..a612dbeab 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1/clusterrole.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1/clusterrolebinding.go b/vendor/k8s.io/client-go/listers/rbac/v1/clusterrolebinding.go index a22d6025e..2c5958ff9 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1/clusterrolebinding.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1/expansion_generated.go b/vendor/k8s.io/client-go/listers/rbac/v1/expansion_generated.go index 967ebdd84..0eb2a6d11 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1/role.go b/vendor/k8s.io/client-go/listers/rbac/v1/role.go index b4649c2c3..9a9d98773 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1/role.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1/rolebinding.go b/vendor/k8s.io/client-go/listers/rbac/v1/rolebinding.go index 8dc0968bb..85a69315a 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1/rolebinding.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/BUILD b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/BUILD deleted file mode 100644 index 917c535fc..000000000 --- a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clusterrole.go", - "clusterrolebinding.go", - "expansion_generated.go", - "role.go", - "rolebinding.go", - ], - importpath = "k8s.io/client-go/listers/rbac/v1alpha1", - deps = [ - "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/clusterrole.go b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/clusterrole.go index 302ca29d8..f8c50f65b 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/clusterrole.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/clusterrolebinding.go b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/clusterrolebinding.go index 91ba54c23..5769ed0e6 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/clusterrolebinding.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/expansion_generated.go b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/expansion_generated.go index 737ba6637..2d4ad1756 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/role.go b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/role.go index cf874f56c..c337b589b 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/role.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/rolebinding.go b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/rolebinding.go index 5e76ab42f..4e517f4d6 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1alpha1/rolebinding.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1alpha1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/rbac/v1beta1/BUILD deleted file mode 100644 index bde3d52e8..000000000 --- a/vendor/k8s.io/client-go/listers/rbac/v1beta1/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "clusterrole.go", - "clusterrolebinding.go", - "expansion_generated.go", - "role.go", - "rolebinding.go", - ], - importpath = "k8s.io/client-go/listers/rbac/v1beta1", - deps = [ - "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/rbac/v1beta1/clusterrole.go b/vendor/k8s.io/client-go/listers/rbac/v1beta1/clusterrole.go index be7f2df6a..01356f4b2 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1beta1/clusterrole.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1beta1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1beta1/clusterrolebinding.go b/vendor/k8s.io/client-go/listers/rbac/v1beta1/clusterrolebinding.go index 09d65be76..6d3f14338 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1beta1/clusterrolebinding.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1beta1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/rbac/v1beta1/expansion_generated.go index 8da573661..51f674bd0 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1beta1/role.go b/vendor/k8s.io/client-go/listers/rbac/v1beta1/role.go index e12039dbf..c946c43a7 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1beta1/role.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1beta1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/rbac/v1beta1/rolebinding.go b/vendor/k8s.io/client-go/listers/rbac/v1beta1/rolebinding.go index 10cb23cd3..0eec45bde 100644 --- a/vendor/k8s.io/client-go/listers/rbac/v1beta1/rolebinding.go +++ b/vendor/k8s.io/client-go/listers/rbac/v1beta1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/BUILD b/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/BUILD deleted file mode 100644 index cf60e8132..000000000 --- a/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "priorityclass.go", - ], - importpath = "k8s.io/client-go/listers/scheduling/v1alpha1", - deps = [ - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/expansion_generated.go b/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/expansion_generated.go index 00b662888..bde8b6206 100644 --- a/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/priorityclass.go b/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/priorityclass.go index fb7f6007c..a3059c94d 100644 --- a/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/priorityclass.go +++ b/vendor/k8s.io/client-go/listers/scheduling/v1alpha1/priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/scheduling/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/scheduling/v1beta1/expansion_generated.go new file mode 100644 index 000000000..b806e8cf8 --- /dev/null +++ b/vendor/k8s.io/client-go/listers/scheduling/v1beta1/expansion_generated.go @@ -0,0 +1,23 @@ +/* +Copyright 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1beta1 + +// PriorityClassListerExpansion allows custom methods to be added to +// PriorityClassLister. +type PriorityClassListerExpansion interface{} diff --git a/vendor/k8s.io/client-go/listers/scheduling/v1beta1/priorityclass.go b/vendor/k8s.io/client-go/listers/scheduling/v1beta1/priorityclass.go new file mode 100644 index 000000000..9d0606392 --- /dev/null +++ b/vendor/k8s.io/client-go/listers/scheduling/v1beta1/priorityclass.go @@ -0,0 +1,65 @@ +/* +Copyright 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1beta1 "k8s.io/api/scheduling/v1beta1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// PriorityClassLister helps list PriorityClasses. +type PriorityClassLister interface { + // List lists all PriorityClasses in the indexer. + List(selector labels.Selector) (ret []*v1beta1.PriorityClass, err error) + // Get retrieves the PriorityClass from the index for a given name. + Get(name string) (*v1beta1.PriorityClass, error) + PriorityClassListerExpansion +} + +// priorityClassLister implements the PriorityClassLister interface. +type priorityClassLister struct { + indexer cache.Indexer +} + +// NewPriorityClassLister returns a new PriorityClassLister. +func NewPriorityClassLister(indexer cache.Indexer) PriorityClassLister { + return &priorityClassLister{indexer: indexer} +} + +// List lists all PriorityClasses in the indexer. +func (s *priorityClassLister) List(selector labels.Selector) (ret []*v1beta1.PriorityClass, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta1.PriorityClass)) + }) + return ret, err +} + +// Get retrieves the PriorityClass from the index for a given name. +func (s *priorityClassLister) Get(name string) (*v1beta1.PriorityClass, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1beta1.Resource("priorityclass"), name) + } + return obj.(*v1beta1.PriorityClass), nil +} diff --git a/vendor/k8s.io/client-go/listers/settings/v1alpha1/BUILD b/vendor/k8s.io/client-go/listers/settings/v1alpha1/BUILD deleted file mode 100644 index 9979b5e3c..000000000 --- a/vendor/k8s.io/client-go/listers/settings/v1alpha1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "podpreset.go", - ], - importpath = "k8s.io/client-go/listers/settings/v1alpha1", - deps = [ - "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/settings/v1alpha1/expansion_generated.go b/vendor/k8s.io/client-go/listers/settings/v1alpha1/expansion_generated.go index 72558897b..fba210343 100644 --- a/vendor/k8s.io/client-go/listers/settings/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/settings/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/settings/v1alpha1/podpreset.go b/vendor/k8s.io/client-go/listers/settings/v1alpha1/podpreset.go index d30036962..c862e7d7d 100644 --- a/vendor/k8s.io/client-go/listers/settings/v1alpha1/podpreset.go +++ b/vendor/k8s.io/client-go/listers/settings/v1alpha1/podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/storage/v1/BUILD b/vendor/k8s.io/client-go/listers/storage/v1/BUILD deleted file mode 100644 index b90f06bb7..000000000 --- a/vendor/k8s.io/client-go/listers/storage/v1/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "storageclass.go", - ], - importpath = "k8s.io/client-go/listers/storage/v1", - deps = [ - "//vendor/k8s.io/api/storage/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/storage/v1/expansion_generated.go b/vendor/k8s.io/client-go/listers/storage/v1/expansion_generated.go index 49e290f4c..d93247064 100644 --- a/vendor/k8s.io/client-go/listers/storage/v1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/storage/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/storage/v1/storageclass.go b/vendor/k8s.io/client-go/listers/storage/v1/storageclass.go index 5b20f6ab5..13e8536b4 100644 --- a/vendor/k8s.io/client-go/listers/storage/v1/storageclass.go +++ b/vendor/k8s.io/client-go/listers/storage/v1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/storage/v1alpha1/BUILD b/vendor/k8s.io/client-go/listers/storage/v1alpha1/BUILD deleted file mode 100644 index 50592d670..000000000 --- a/vendor/k8s.io/client-go/listers/storage/v1alpha1/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "volumeattachment.go", - ], - importpath = "k8s.io/client-go/listers/storage/v1alpha1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/listers/storage/v1alpha1/expansion_generated.go b/vendor/k8s.io/client-go/listers/storage/v1alpha1/expansion_generated.go index 2fc6add1d..7ca765622 100644 --- a/vendor/k8s.io/client-go/listers/storage/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/storage/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/storage/v1alpha1/volumeattachment.go b/vendor/k8s.io/client-go/listers/storage/v1alpha1/volumeattachment.go index f8d1bdb2d..7871f55e4 100644 --- a/vendor/k8s.io/client-go/listers/storage/v1alpha1/volumeattachment.go +++ b/vendor/k8s.io/client-go/listers/storage/v1alpha1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/storage/v1beta1/BUILD b/vendor/k8s.io/client-go/listers/storage/v1beta1/BUILD deleted file mode 100644 index 49d992e47..000000000 --- a/vendor/k8s.io/client-go/listers/storage/v1beta1/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "expansion_generated.go", - "storageclass.go", - "volumeattachment.go", - ], - importpath = "k8s.io/client-go/listers/storage/v1beta1", - deps = [ - "//vendor/k8s.io/api/storage/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/listers/storage/v1beta1/expansion_generated.go b/vendor/k8s.io/client-go/listers/storage/v1beta1/expansion_generated.go index 8c2dc9055..21d95620c 100644 --- a/vendor/k8s.io/client-go/listers/storage/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/client-go/listers/storage/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/storage/v1beta1/storageclass.go b/vendor/k8s.io/client-go/listers/storage/v1beta1/storageclass.go index 45afe0e77..07bc97b32 100644 --- a/vendor/k8s.io/client-go/listers/storage/v1beta1/storageclass.go +++ b/vendor/k8s.io/client-go/listers/storage/v1beta1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/listers/storage/v1beta1/volumeattachment.go b/vendor/k8s.io/client-go/listers/storage/v1beta1/volumeattachment.go index c9cc3984e..7193441b0 100644 --- a/vendor/k8s.io/client-go/listers/storage/v1beta1/volumeattachment.go +++ b/vendor/k8s.io/client-go/listers/storage/v1beta1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/BUILD b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/BUILD deleted file mode 100644 index 64cdd678d..000000000 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "register.go", - "types.go", - "zz_generated.deepcopy.go", - ], - importpath = "k8s.io/client-go/pkg/apis/clientauthentication", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install:all-srcs", - "//staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/install/BUILD b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/install/BUILD deleted file mode 100644 index de371ab22..000000000 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/install/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["install.go"], - importpath = "k8s.io/client-go/pkg/apis/clientauthentication/install", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/install/install.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/install/install.go index 40093e97f..1b7b5f949 100644 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/install/install.go +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/pkg/apis/clientauthentication" "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: clientauthentication.GroupName, - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: clientauthentication.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(clientauthentication.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/types.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/types.go index 5c05825f6..6fb53cecf 100644 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/types.go +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/types.go @@ -57,7 +57,14 @@ type ExecCredentialStatus struct { // +optional ExpirationTimestamp *metav1.Time // Token is a bearer token used by the client for request authentication. + // +optional Token string + // PEM-encoded client TLS certificate. + // +optional + ClientCertificateData string + // PEM-encoded client TLS private key. + // +optional + ClientKeyData string } // Response defines metadata about a failed request, including HTTP status code and diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/BUILD b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/BUILD deleted file mode 100644 index 1a3bc15f6..000000000 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "register.go", - "types.go", - "zz_generated.conversion.go", - "zz_generated.deepcopy.go", - "zz_generated.defaults.go", - ], - importpath = "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", - deps = [ - "//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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go index 8920d3187..921f3a2b9 100644 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go @@ -52,12 +52,20 @@ type ExecCredentialSpec struct { } // ExecCredentialStatus holds credentials for the transport to use. +// +// Token and ClientKeyData are sensitive fields. This data should only be +// transmitted in-memory between client and exec plugin process. Exec plugin +// itself should at least be protected via file permissions. type ExecCredentialStatus struct { // ExpirationTimestamp indicates a time when the provided credentials expire. // +optional ExpirationTimestamp *metav1.Time `json:"expirationTimestamp,omitempty"` // Token is a bearer token used by the client for request authentication. Token string `json:"token,omitempty"` + // PEM-encoded client TLS certificates (including intermediates, if any). + ClientCertificateData string `json:"clientCertificateData,omitempty"` + // PEM-encoded private key for the above certificate. + ClientKeyData string `json:"clientKeyData,omitempty"` } // Response defines metadata about a failed request, including HTTP status code and diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go index bf28baef2..9921c7ee5 100644 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -99,6 +99,8 @@ func Convert_clientauthentication_ExecCredentialSpec_To_v1alpha1_ExecCredentialS func autoConvert_v1alpha1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error { out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData return nil } @@ -110,6 +112,8 @@ func Convert_v1alpha1_ExecCredentialStatus_To_clientauthentication_ExecCredentia func autoConvert_clientauthentication_ExecCredentialStatus_To_v1alpha1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error { out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData return nil } diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.deepcopy.go index c6dbbce4d..f062b8f06 100644 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/conversion.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/conversion.go new file mode 100644 index 000000000..f543806ac --- /dev/null +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/conversion.go @@ -0,0 +1,26 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + clientauthentication "k8s.io/client-go/pkg/apis/clientauthentication" +) + +func Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error { + return nil +} diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/doc.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/doc.go new file mode 100644 index 000000000..fbcd9b7fe --- /dev/null +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2018 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. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/client-go/pkg/apis/clientauthentication +// +k8s:openapi-gen=true +// +k8s:defaulter-gen=TypeMeta + +// +groupName=client.authentication.k8s.io +package v1beta1 // import "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1" diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/register.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/register.go new file mode 100644 index 000000000..0bb92f16a --- /dev/null +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/register.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "client.authentication.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ExecCredential{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.go new file mode 100644 index 000000000..d6e267452 --- /dev/null +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.go @@ -0,0 +1,59 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExecCredentials is used by exec-based plugins to communicate credentials to +// HTTP transports. +type ExecCredential struct { + metav1.TypeMeta `json:",inline"` + + // Spec holds information passed to the plugin by the transport. This contains + // request and runtime specific information, such as if the session is interactive. + Spec ExecCredentialSpec `json:"spec,omitempty"` + + // Status is filled in by the plugin and holds the credentials that the transport + // should use to contact the API. + // +optional + Status *ExecCredentialStatus `json:"status,omitempty"` +} + +// ExecCredenitalSpec holds request and runtime specific information provided by +// the transport. +type ExecCredentialSpec struct{} + +// ExecCredentialStatus holds credentials for the transport to use. +// +// Token and ClientKeyData are sensitive fields. This data should only be +// transmitted in-memory between client and exec plugin process. Exec plugin +// itself should at least be protected via file permissions. +type ExecCredentialStatus struct { + // ExpirationTimestamp indicates a time when the provided credentials expire. + // +optional + ExpirationTimestamp *metav1.Time `json:"expirationTimestamp,omitempty"` + // Token is a bearer token used by the client for request authentication. + Token string `json:"token,omitempty"` + // PEM-encoded client TLS certificates (including intermediates, if any). + ClientCertificateData string `json:"clientCertificateData,omitempty"` + // PEM-encoded private key for the above certificate. + ClientKeyData string `json:"clientKeyData,omitempty"` +} diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go new file mode 100644 index 000000000..80e9b3159 --- /dev/null +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go @@ -0,0 +1,114 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1beta1 + +import ( + unsafe "unsafe" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + clientauthentication "k8s.io/client-go/pkg/apis/clientauthentication" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(scheme *runtime.Scheme) error { + return scheme.AddGeneratedConversionFuncs( + Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential, + Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential, + Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec, + Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec, + Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus, + Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus, + ) +} + +func autoConvert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in *ExecCredential, out *clientauthentication.ExecCredential, s conversion.Scope) error { + if err := Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + out.Status = (*clientauthentication.ExecCredentialStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential is an autogenerated conversion function. +func Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in *ExecCredential, out *clientauthentication.ExecCredential, s conversion.Scope) error { + return autoConvert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in, out, s) +} + +func autoConvert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in *clientauthentication.ExecCredential, out *ExecCredential, s conversion.Scope) error { + if err := Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + out.Status = (*ExecCredentialStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential is an autogenerated conversion function. +func Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in *clientauthentication.ExecCredential, out *ExecCredential, s conversion.Scope) error { + return autoConvert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in, out, s) +} + +func autoConvert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in *ExecCredentialSpec, out *clientauthentication.ExecCredentialSpec, s conversion.Scope) error { + return nil +} + +// Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec is an autogenerated conversion function. +func Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in *ExecCredentialSpec, out *clientauthentication.ExecCredentialSpec, s conversion.Scope) error { + return autoConvert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in, out, s) +} + +func autoConvert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error { + // WARNING: in.Response requires manual conversion: does not exist in peer-type + // WARNING: in.Interactive requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error { + out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) + out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData + return nil +} + +// Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus is an autogenerated conversion function. +func Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error { + return autoConvert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in, out, s) +} + +func autoConvert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error { + out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) + out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData + return nil +} + +// Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus is an autogenerated conversion function. +func Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error { + return autoConvert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in, out, s) +} diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 000000000..656fea4d8 --- /dev/null +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,100 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecCredential) DeepCopyInto(out *ExecCredential) { + *out = *in + out.TypeMeta = in.TypeMeta + out.Spec = in.Spec + if in.Status != nil { + in, out := &in.Status, &out.Status + if *in == nil { + *out = nil + } else { + *out = new(ExecCredentialStatus) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredential. +func (in *ExecCredential) DeepCopy() *ExecCredential { + if in == nil { + return nil + } + out := new(ExecCredential) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExecCredential) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecCredentialSpec) DeepCopyInto(out *ExecCredentialSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredentialSpec. +func (in *ExecCredentialSpec) DeepCopy() *ExecCredentialSpec { + if in == nil { + return nil + } + out := new(ExecCredentialSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecCredentialStatus) DeepCopyInto(out *ExecCredentialStatus) { + *out = *in + if in.ExpirationTimestamp != nil { + in, out := &in.ExpirationTimestamp, &out.ExpirationTimestamp + if *in == nil { + *out = nil + } else { + *out = (*in).DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredentialStatus. +func (in *ExecCredentialStatus) DeepCopy() *ExecCredentialStatus { + if in == nil { + return nil + } + out := new(ExecCredentialStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.defaults.go new file mode 100644 index 000000000..73e63fc11 --- /dev/null +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.defaults.go @@ -0,0 +1,32 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/zz_generated.deepcopy.go b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/zz_generated.deepcopy.go index f8b15d848..008c3c7df 100644 --- a/vendor/k8s.io/client-go/pkg/apis/clientauthentication/zz_generated.deepcopy.go +++ b/vendor/k8s.io/client-go/pkg/apis/clientauthentication/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/pkg/version/BUILD b/vendor/k8s.io/client-go/pkg/version/BUILD deleted file mode 100644 index ee19d8cde..000000000 --- a/vendor/k8s.io/client-go/pkg/version/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "base.go", - "doc.go", - "version.go", - ], - importpath = "k8s.io/client-go/pkg/version", - deps = ["//vendor/k8s.io/apimachinery/pkg/version:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/pkg/version/base.go b/vendor/k8s.io/client-go/pkg/version/base.go index 7ab0ed3a7..9b4c79f89 100644 --- a/vendor/k8s.io/client-go/pkg/version/base.go +++ b/vendor/k8s.io/client-go/pkg/version/base.go @@ -43,7 +43,7 @@ var ( gitMinor string = "" // minor version, numeric possibly followed by "+" // semantic version, derived by build scripts (see - // https://github.com/kubernetes/kubernetes/blob/master/docs/design/versioning.md + // https://git.k8s.io/community/contributors/design-proposals/release/versioning.md // for a detailed discussion of this field) // // TODO: This field is still called "gitVersion" for legacy diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/BUILD b/vendor/k8s.io/client-go/plugin/pkg/client/auth/BUILD deleted file mode 100644 index 367e897fd..000000000 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["plugins.go"], - importpath = "k8s.io/client-go/plugin/pkg/client/auth", - deps = [ - "//vendor/k8s.io/client-go/plugin/pkg/client/auth/azure:go_default_library", - "//vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp:go_default_library", - "//vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc:go_default_library", - "//vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure:all-srcs", - "//staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec:all-srcs", - "//staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp:all-srcs", - "//staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc:all-srcs", - "//staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/BUILD b/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/BUILD deleted file mode 100644 index 682776db5..000000000 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["azure_test.go"], - embed = [":go_default_library"], - deps = ["//vendor/github.com/Azure/go-autorest/autorest/adal:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["azure.go"], - importpath = "k8s.io/client-go/plugin/pkg/client/auth/azure", - deps = [ - "//vendor/github.com/Azure/go-autorest/autorest:go_default_library", - "//vendor/github.com/Azure/go-autorest/autorest/adal:go_default_library", - "//vendor/github.com/Azure/go-autorest/autorest/azure:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/README.md b/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/README.md index 0b5e62bd4..e4ba791ea 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/README.md +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/README.md @@ -1,15 +1,14 @@ # Azure Active Directory plugin for client authentication -This plugin provides an integration with Azure Active Directory device flow. If no tokens are present in the kubectl configuration, it will prompt a device code which can be used to login in a browser. After login it will automatically fetch the tokens and stored them in the kubectl configuration. In addition it will refresh and update the tokens in configuration when expired. - +This plugin provides an integration with Azure Active Directory device flow. If no tokens are present in the kubectl configuration, it will prompt a device code which can be used to login in a browser. After login it will automatically fetch the tokens and store them in the kubectl configuration. In addition it will refresh and update the tokens in the configuration when expired. ## Usage -1. Create an Azure Active Directory *Web App / API* application for `apiserver` following these [instructions](https://docs.microsoft.com/en-us/azure/active-directory/active-directory-app-registration) +1. Create an Azure Active Directory *Web App / API* application for `apiserver` following these [instructions](https://docs.microsoft.com/en-us/azure/active-directory/active-directory-app-registration). The callback URL does not matter (just cannot be empty). -2. Create a second Azure Active Directory native application for `kubectl` +2. Create a second Azure Active Directory native application for `kubectl`. The callback URL does not matter (just cannot be empty). -3. On `kubectl` application's configuration page in Azure portal grant permissions to `apiserver` application by clicking on *Required Permissions*, click the *Add* button and search for the apiserver application created in step 1. Select "Access apiserver" under the *DELEGATED PERMISSIONS*. Once added click the *Grant Permissions* button to apply the changes +3. On `kubectl` application's configuration page in Azure portal grant permissions to `apiserver` application by clicking on *Required Permissions*, click the *Add* button and search for the apiserver application created in step 1. Select "Access apiserver" under the *DELEGATED PERMISSIONS*. Once added click the *Grant Permissions* button to apply the changes. 4. Configure the `apiserver` to use the Azure Active Directory as an OIDC provider with following options @@ -21,8 +20,9 @@ This plugin provides an integration with Azure Active Directory device flow. If * Replace the `APISERVER_APPLICATION_ID` with the application ID of `apiserver` application * Replace `TENANT_ID` with your tenant ID. +   * For a list of alternative username claims that are supported by the OIDC issuer check the JSON response at `https://sts.windows.net/TENANT_ID/.well-known/openid-configuration`. -5. Configure the `kubectl` to use the `azure` authentication provider +5. Configure `kubectl` to use the `azure` authentication provider ``` kubectl config set-credentials "USER_NAME" --auth-provider=azure \ @@ -35,7 +35,8 @@ This plugin provides an integration with Azure Active Directory device flow. If * Supported environments: `AzurePublicCloud`, `AzureUSGovernmentCloud`, `AzureChinaCloud`, `AzureGermanCloud` * Replace `USER_NAME` and `TENANT_ID` with your user name and tenant ID * Replace `APPLICATION_ID` with the application ID of your`kubectl` application ID - * Replace `APISERVER_APPLICATION_ID` with the application ID of your `apiserver` application ID + * Replace `APISERVER_APPLICATION_ID` with the application ID of your `apiserver` application ID + * Be sure to also (create and) select a context that uses above user 6. The access token is acquired when first `kubectl` command is executed @@ -45,4 +46,5 @@ This plugin provides an integration with Azure Active Directory device flow. If To sign in, use a web browser to open the page https://aka.ms/devicelogin and enter the code DEC7D48GA to authenticate. ``` - * After signing in a web browser, the token is stored in the configuration, and it will be reused when executing next commands. + * After signing in a web browser, the token is stored in the configuration, and it will be reused when executing further commands. + * The resulting username in Kubernetes depends on your [configuration of the `--oidc-username-claim` and `--oidc-username-prefix` flags on the API server](https://kubernetes.io/docs/admin/authentication/#configuring-the-api-server). If you are using any authorization method you need to give permissions to that user, e.g. by binding the user to a role in the case of RBAC. diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go b/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go index e14dc8d9d..60304b0f3 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go @@ -297,7 +297,7 @@ func (ts *azureTokenSource) refreshToken(token *azureToken) (*azureToken, error) } return &azureToken{ - token: spt.Token, + token: spt.Token(), clientID: token.clientID, tenantID: token.tenantID, apiserverID: token.apiserverID, diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD b/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD deleted file mode 100644 index 38cf9bdc2..000000000 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD +++ /dev/null @@ -1,44 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["exec.go"], - importpath = "k8s.io/client-go/plugin/pkg/client/auth/exec", - visibility = ["//visibility:public"], - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/crypto/ssh/terminal:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["exec_test.go"], - data = glob(["testdata/**"]), - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go b/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go index dfd434d0c..2d05ac622 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go @@ -18,11 +18,15 @@ package exec import ( "bytes" + "context" + "crypto/tls" "fmt" "io" + "net" "net/http" "os" "os/exec" + "reflect" "sync" "time" @@ -34,7 +38,10 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/client-go/pkg/apis/clientauthentication" "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1" + "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1" "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/client-go/transport" + "k8s.io/client-go/util/connrotation" ) const execInfoEnv = "KUBERNETES_EXEC_INFO" @@ -45,6 +52,7 @@ var codecs = serializer.NewCodecFactory(scheme) func init() { v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) v1alpha1.AddToScheme(scheme) + v1beta1.AddToScheme(scheme) clientauthentication.AddToScheme(scheme) } @@ -55,6 +63,7 @@ var ( // The list of API versions we accept. apiVersions = map[string]schema.GroupVersion{ v1alpha1.SchemeGroupVersion.String(): v1alpha1.SchemeGroupVersion, + v1beta1.SchemeGroupVersion.String(): v1beta1.SchemeGroupVersion, } ) @@ -147,14 +156,55 @@ type Authenticator struct { // The mutex also guards calling the plugin. Since the plugin could be // interactive we want to make sure it's only called once. mu sync.Mutex - cachedToken string + cachedCreds *credentials exp time.Time + + onRotate func() +} + +type credentials struct { + token string + cert *tls.Certificate } -// WrapTransport instruments an existing http.RoundTripper with credentials returned -// by the plugin. -func (a *Authenticator) WrapTransport(rt http.RoundTripper) http.RoundTripper { - return &roundTripper{a, rt} +// UpdateTransportConfig updates the transport.Config to use credentials +// returned by the plugin. +func (a *Authenticator) UpdateTransportConfig(c *transport.Config) error { + wt := c.WrapTransport + c.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { + if wt != nil { + rt = wt(rt) + } + return &roundTripper{a, rt} + } + + getCert := c.TLS.GetCert + c.TLS.GetCert = func() (*tls.Certificate, error) { + // If previous GetCert is present and returns a valid non-nil + // certificate, use that. Otherwise use cert from exec plugin. + if getCert != nil { + cert, err := getCert() + if err != nil { + return nil, err + } + if cert != nil { + return cert, nil + } + } + return a.cert() + } + + var dial func(ctx context.Context, network, addr string) (net.Conn, error) + if c.Dial != nil { + dial = c.Dial + } else { + dial = (&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext + } + d := connrotation.NewDialer(dial) + a.onRotate = d.CloseAll + c.Dial = d.DialContext + + return nil } type roundTripper struct { @@ -169,11 +219,13 @@ func (r *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { return r.base.RoundTrip(req) } - token, err := r.a.token() + creds, err := r.a.getCreds() if err != nil { - return nil, fmt.Errorf("getting token: %v", err) + return nil, fmt.Errorf("getting credentials: %v", err) + } + if creds.token != "" { + req.Header.Set("Authorization", "Bearer "+creds.token) } - req.Header.Set("Authorization", "Bearer "+token) res, err := r.base.RoundTrip(req) if err != nil { @@ -184,47 +236,60 @@ func (r *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { Header: res.Header, Code: int32(res.StatusCode), } - if err := r.a.refresh(token, resp); err != nil { - glog.Errorf("refreshing token: %v", err) + if err := r.a.maybeRefreshCreds(creds, resp); err != nil { + glog.Errorf("refreshing credentials: %v", err) } } return res, nil } -func (a *Authenticator) tokenExpired() bool { +func (a *Authenticator) credsExpired() bool { if a.exp.IsZero() { return false } return a.now().After(a.exp) } -func (a *Authenticator) token() (string, error) { +func (a *Authenticator) cert() (*tls.Certificate, error) { + creds, err := a.getCreds() + if err != nil { + return nil, err + } + return creds.cert, nil +} + +func (a *Authenticator) getCreds() (*credentials, error) { a.mu.Lock() defer a.mu.Unlock() - if a.cachedToken != "" && !a.tokenExpired() { - return a.cachedToken, nil + if a.cachedCreds != nil && !a.credsExpired() { + return a.cachedCreds, nil } - return a.getToken(nil) + if err := a.refreshCredsLocked(nil); err != nil { + return nil, err + } + return a.cachedCreds, nil } -// refresh executes the plugin to force a rotation of the token. -func (a *Authenticator) refresh(token string, r *clientauthentication.Response) error { +// maybeRefreshCreds executes the plugin to force a rotation of the +// credentials, unless they were rotated already. +func (a *Authenticator) maybeRefreshCreds(creds *credentials, r *clientauthentication.Response) error { a.mu.Lock() defer a.mu.Unlock() - if token != a.cachedToken { - // Token already rotated. + // Since we're not making a new pointer to a.cachedCreds in getCreds, no + // need to do deep comparison. + if creds != a.cachedCreds { + // Credentials already rotated. return nil } - _, err := a.getToken(r) - return err + return a.refreshCredsLocked(r) } -// getToken executes the plugin and reads the credentials from stdout. It must be -// called while holding the Authenticator's mutex. -func (a *Authenticator) getToken(r *clientauthentication.Response) (string, error) { +// refreshCredsLocked executes the plugin and reads the credentials from +// stdout. It must be called while holding the Authenticator's mutex. +func (a *Authenticator) refreshCredsLocked(r *clientauthentication.Response) error { cred := &clientauthentication.ExecCredential{ Spec: clientauthentication.ExecCredentialSpec{ Response: r, @@ -232,13 +297,18 @@ func (a *Authenticator) getToken(r *clientauthentication.Response) (string, erro }, } - data, err := runtime.Encode(codecs.LegacyCodec(a.group), cred) - if err != nil { - return "", fmt.Errorf("encode ExecCredentials: %v", err) - } - env := append(a.environ(), a.env...) - env = append(env, fmt.Sprintf("%s=%s", execInfoEnv, data)) + if a.group == v1alpha1.SchemeGroupVersion { + // Input spec disabled for beta due to lack of use. Possibly re-enable this later if + // someone wants it back. + // + // See: https://github.com/kubernetes/kubernetes/issues/61796 + data, err := runtime.Encode(codecs.LegacyCodec(a.group), cred) + if err != nil { + return fmt.Errorf("encode ExecCredentials: %v", err) + } + env = append(env, fmt.Sprintf("%s=%s", execInfoEnv, data)) + } stdout := &bytes.Buffer{} cmd := exec.Command(a.cmd, a.args...) @@ -250,23 +320,26 @@ func (a *Authenticator) getToken(r *clientauthentication.Response) (string, erro } if err := cmd.Run(); err != nil { - return "", fmt.Errorf("exec: %v", err) + return fmt.Errorf("exec: %v", err) } _, gvk, err := codecs.UniversalDecoder(a.group).Decode(stdout.Bytes(), nil, cred) if err != nil { - return "", fmt.Errorf("decode stdout: %v", err) + return fmt.Errorf("decoding stdout: %v", err) } if gvk.Group != a.group.Group || gvk.Version != a.group.Version { - return "", fmt.Errorf("exec plugin is configured to use API version %s, plugin returned version %s", + return fmt.Errorf("exec plugin is configured to use API version %s, plugin returned version %s", a.group, schema.GroupVersion{Group: gvk.Group, Version: gvk.Version}) } if cred.Status == nil { - return "", fmt.Errorf("exec plugin didn't return a status field") + return fmt.Errorf("exec plugin didn't return a status field") + } + if cred.Status.Token == "" && cred.Status.ClientCertificateData == "" && cred.Status.ClientKeyData == "" { + return fmt.Errorf("exec plugin didn't return a token or cert/key pair") } - if cred.Status.Token == "" { - return "", fmt.Errorf("exec plugin didn't return a token") + if (cred.Status.ClientCertificateData == "") != (cred.Status.ClientKeyData == "") { + return fmt.Errorf("exec plugin returned only certificate or key, not both") } if cred.Status.ExpirationTimestamp != nil { @@ -274,7 +347,24 @@ func (a *Authenticator) getToken(r *clientauthentication.Response) (string, erro } else { a.exp = time.Time{} } - a.cachedToken = cred.Status.Token - return a.cachedToken, nil + newCreds := &credentials{ + token: cred.Status.Token, + } + if cred.Status.ClientKeyData != "" && cred.Status.ClientCertificateData != "" { + cert, err := tls.X509KeyPair([]byte(cred.Status.ClientCertificateData), []byte(cred.Status.ClientKeyData)) + if err != nil { + return fmt.Errorf("failed parsing client key/certificate: %v", err) + } + newCreds.cert = &cert + } + + oldCreds := a.cachedCreds + a.cachedCreds = newCreds + // Only close all connections when TLS cert rotates. Token rotation doesn't + // need the extra noise. + if a.onRotate != nil && oldCreds != nil && !reflect.DeepEqual(oldCreds.cert, a.cachedCreds.cert) { + a.onRotate() + } + return nil } diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go b/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go index 28137eb84..e3398e821 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go @@ -18,19 +18,88 @@ package exec import ( "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" "encoding/json" + "encoding/pem" "fmt" "io/ioutil" + "math/big" "net/http" "net/http/httptest" + "reflect" "strings" "testing" "time" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/pkg/apis/clientauthentication" "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/client-go/transport" ) +var ( + certData = []byte(`-----BEGIN CERTIFICATE----- +MIIC6jCCAdSgAwIBAgIBCzALBgkqhkiG9w0BAQswIzEhMB8GA1UEAwwYMTAuMTMu +MTI5LjEwNkAxNDIxMzU5MDU4MB4XDTE1MDExNTIyMDEzMVoXDTE2MDExNTIyMDEz +MlowGzEZMBcGA1UEAxMQb3BlbnNoaWZ0LWNsaWVudDCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKtdhz0+uCLXw5cSYns9rU/XifFSpb/x24WDdrm72S/v +b9BPYsAStiP148buylr1SOuNi8sTAZmlVDDIpIVwMLff+o2rKYDicn9fjbrTxTOj +lI4pHJBH+JU3AJ0tbajupioh70jwFS0oYpwtneg2zcnE2Z4l6mhrj2okrc5Q1/X2 +I2HChtIU4JYTisObtin10QKJX01CLfYXJLa8upWzKZ4/GOcHG+eAV3jXWoXidtjb +1Usw70amoTZ6mIVCkiu1QwCoa8+ycojGfZhvqMsAp1536ZcCul+Na+AbCv4zKS7F +kQQaImVrXdUiFansIoofGlw/JNuoKK6ssVpS5Ic3pgcCAwEAAaM1MDMwDgYDVR0P +AQH/BAQDAgCgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJ +KoZIhvcNAQELA4IBAQCKLREH7bXtXtZ+8vI6cjD7W3QikiArGqbl36bAhhWsJLp/ +p/ndKz39iFNaiZ3GlwIURWOOKx3y3GA0x9m8FR+Llthf0EQ8sUjnwaknWs0Y6DQ3 +jjPFZOpV3KPCFrdMJ3++E3MgwFC/Ih/N2ebFX9EcV9Vcc6oVWMdwT0fsrhu683rq +6GSR/3iVX1G/pmOiuaR0fNUaCyCfYrnI4zHBDgSfnlm3vIvN2lrsR/DQBakNL8DJ +HBgKxMGeUPoneBv+c8DMXIL0EhaFXRlBv9QW45/GiAIOuyFJ0i6hCtGZpJjq4OpQ +BRjCI+izPzFTjsxD4aORE+WOkyWFCGPWKfNejfw0 +-----END CERTIFICATE-----`) + keyData = []byte(`-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAq12HPT64ItfDlxJiez2tT9eJ8VKlv/HbhYN2ubvZL+9v0E9i +wBK2I/Xjxu7KWvVI642LyxMBmaVUMMikhXAwt9/6jaspgOJyf1+NutPFM6OUjikc +kEf4lTcAnS1tqO6mKiHvSPAVLShinC2d6DbNycTZniXqaGuPaiStzlDX9fYjYcKG +0hTglhOKw5u2KfXRAolfTUIt9hcktry6lbMpnj8Y5wcb54BXeNdaheJ22NvVSzDv +RqahNnqYhUKSK7VDAKhrz7JyiMZ9mG+oywCnXnfplwK6X41r4BsK/jMpLsWRBBoi +ZWtd1SIVqewiih8aXD8k26gorqyxWlLkhzemBwIDAQABAoIBAD2XYRs3JrGHQUpU +FkdbVKZkvrSY0vAZOqBTLuH0zUv4UATb8487anGkWBjRDLQCgxH+jucPTrztekQK +aW94clo0S3aNtV4YhbSYIHWs1a0It0UdK6ID7CmdWkAj6s0T8W8lQT7C46mWYVLm +5mFnCTHi6aB42jZrqmEpC7sivWwuU0xqj3Ml8kkxQCGmyc9JjmCB4OrFFC8NNt6M +ObvQkUI6Z3nO4phTbpxkE1/9dT0MmPIF7GhHVzJMS+EyyRYUDllZ0wvVSOM3qZT0 +JMUaBerkNwm9foKJ1+dv2nMKZZbJajv7suUDCfU44mVeaEO+4kmTKSGCGjjTBGkr +7L1ySDECgYEA5ElIMhpdBzIivCuBIH8LlUeuzd93pqssO1G2Xg0jHtfM4tz7fyeI +cr90dc8gpli24dkSxzLeg3Tn3wIj/Bu64m2TpZPZEIlukYvgdgArmRIPQVxerYey +OkrfTNkxU1HXsYjLCdGcGXs5lmb+K/kuTcFxaMOs7jZi7La+jEONwf8CgYEAwCs/ +rUOOA0klDsWWisbivOiNPII79c9McZCNBqncCBfMUoiGe8uWDEO4TFHN60vFuVk9 +8PkwpCfvaBUX+ajvbafIfHxsnfk1M04WLGCeqQ/ym5Q4sQoQOcC1b1y9qc/xEWfg +nIUuia0ukYRpl7qQa3tNg+BNFyjypW8zukUAC/kCgYB1/Kojuxx5q5/oQVPrx73k +2bevD+B3c+DYh9MJqSCNwFtUpYIWpggPxoQan4LwdsmO0PKzocb/ilyNFj4i/vII +NToqSc/WjDFpaDIKyuu9oWfhECye45NqLWhb/6VOuu4QA/Nsj7luMhIBehnEAHW+ +GkzTKM8oD1PxpEG3nPKXYQKBgQC6AuMPRt3XBl1NkCrpSBy/uObFlFaP2Enpf39S +3OZ0Gv0XQrnSaL1kP8TMcz68rMrGX8DaWYsgytstR4W+jyy7WvZwsUu+GjTJ5aMG +77uEcEBpIi9CBzivfn7hPccE8ZgqPf+n4i6q66yxBJflW5xhvafJqDtW2LcPNbW/ +bvzdmQKBgExALRUXpq+5dbmkdXBHtvXdRDZ6rVmrnjy4nI5bPw+1GqQqk6uAR6B/ +F6NmLCQOO4PDG/cuatNHIr2FrwTmGdEL6ObLUGWn9Oer9gJhHVqqsY5I4sEPo4XX +stR0Yiw0buV6DL/moUO0HIM9Bjh96HJp+LxiIS6UCdIhMPp5HoQa +-----END RSA PRIVATE KEY-----`) + validCert *tls.Certificate +) + +func init() { + cert, err := tls.X509KeyPair(certData, keyData) + if err != nil { + panic(err) + } + validCert = &cert +} + func TestCacheKey(t *testing.T) { c1 := &api.ExecConfig{ Command: "foo-bar", @@ -93,7 +162,7 @@ func compJSON(t *testing.T, got, want []byte) { } } -func TestGetToken(t *testing.T) { +func TestRefreshCreds(t *testing.T) { tests := []struct { name string config api.ExecConfig @@ -101,7 +170,7 @@ func TestGetToken(t *testing.T) { interactive bool response *clientauthentication.Response wantInput string - wantToken string + wantCreds credentials wantExpiry time.Time wantErr bool }{ @@ -122,7 +191,7 @@ func TestGetToken(t *testing.T) { "token": "foo-bar" } }`, - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "interactive", @@ -144,7 +213,7 @@ func TestGetToken(t *testing.T) { "token": "foo-bar" } }`, - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "response", @@ -178,7 +247,7 @@ func TestGetToken(t *testing.T) { "token": "foo-bar" } }`, - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "expiry", @@ -199,7 +268,7 @@ func TestGetToken(t *testing.T) { } }`, wantExpiry: time.Date(2006, 01, 02, 15, 04, 05, 0, time.UTC), - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "no-group-version", @@ -236,7 +305,44 @@ func TestGetToken(t *testing.T) { wantErr: true, }, { - name: "no-token", + name: "no-creds", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1alpha1", + }, + wantInput: `{ + "kind":"ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1alpha1", + "spec": {} + }`, + output: `{ + "kind": "ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1alpha1", + "status": {} + }`, + wantErr: true, + }, + { + name: "TLS credentials", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1alpha1", + }, + wantInput: `{ + "kind":"ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1alpha1", + "spec": {} + }`, + output: fmt.Sprintf(`{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1alpha1", + "status": { + "clientKeyData": %q, + "clientCertificateData": %q + } + }`, keyData, certData), + wantCreds: credentials{cert: validCert}, + }, + { + name: "bad TLS credentials", config: api.ExecConfig{ APIVersion: "client.authentication.k8s.io/v1alpha1", }, @@ -247,7 +353,95 @@ func TestGetToken(t *testing.T) { }`, output: `{ "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1alpha1", + "status": { + "clientKeyData": "foo", + "clientCertificateData": "bar" + } + }`, + wantErr: true, + }, + { + name: "cert but no key", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1alpha1", + }, + wantInput: `{ + "kind":"ExecCredential", "apiVersion":"client.authentication.k8s.io/v1alpha1", + "spec": {} + }`, + output: fmt.Sprintf(`{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1alpha1", + "status": { + "clientCertificateData": %q + } + }`, certData), + wantErr: true, + }, + { + name: "beta-basic-request", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1beta1", + "status": { + "token": "foo-bar" + } + }`, + wantCreds: credentials{token: "foo-bar"}, + }, + { + name: "beta-expiry", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1beta1", + "status": { + "token": "foo-bar", + "expirationTimestamp": "2006-01-02T15:04:05Z" + } + }`, + wantExpiry: time.Date(2006, 01, 02, 15, 04, 05, 0, time.UTC), + wantCreds: credentials{token: "foo-bar"}, + }, + { + name: "beta-no-group-version", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "status": { + "token": "foo-bar" + } + }`, + wantErr: true, + }, + { + name: "beta-no-status", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1beta1" + }`, + wantErr: true, + }, + { + name: "beta-no-token", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1beta1", "status": {} }`, wantErr: true, @@ -274,8 +468,7 @@ func TestGetToken(t *testing.T) { a.interactive = test.interactive a.environ = func() []string { return nil } - token, err := a.getToken(test.response) - if err != nil { + if err := a.refreshCredsLocked(test.response); err != nil { if !test.wantErr { t.Errorf("get token %v", err) } @@ -285,14 +478,21 @@ func TestGetToken(t *testing.T) { t.Fatal("expected error getting token") } - if token != test.wantToken { - t.Errorf("expected token %q got %q", test.wantToken, token) + if !reflect.DeepEqual(a.cachedCreds, &test.wantCreds) { + t.Errorf("expected credentials %+v got %+v", &test.wantCreds, a.cachedCreds) } if !a.exp.Equal(test.wantExpiry) { t.Errorf("expected expiry %v got %v", test.wantExpiry, a.exp) } + if test.wantInput == "" { + if got := strings.TrimSpace(stderr.String()); got != "" { + t.Errorf("expected no input parameters, got %q", got) + } + return + } + compJSON(t, stderr.Bytes(), []byte(test.wantInput)) }) } @@ -342,8 +542,12 @@ func TestRoundTripper(t *testing.T) { a.now = now a.stderr = ioutil.Discard + tc := &transport.Config{} + if err := a.UpdateTransportConfig(tc); err != nil { + t.Fatal(err) + } client := http.Client{ - Transport: a.WrapTransport(http.DefaultTransport), + Transport: tc.WrapTransport(http.DefaultTransport), } get := func(t *testing.T, statusCode int) { @@ -411,3 +615,134 @@ func TestRoundTripper(t *testing.T) { // Old token is expired, should refresh automatically without hitting a 401. get(t, http.StatusOK) } + +func TestTLSCredentials(t *testing.T) { + now := time.Now() + + certPool := x509.NewCertPool() + cert, key := genClientCert(t) + if !certPool.AppendCertsFromPEM(cert) { + t.Fatal("failed to add client cert to CertPool") + } + + server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "ok") + })) + server.TLS = &tls.Config{ + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: certPool, + } + server.StartTLS() + defer server.Close() + + a, err := newAuthenticator(newCache(), &api.ExecConfig{ + Command: "./testdata/test-plugin.sh", + APIVersion: "client.authentication.k8s.io/v1alpha1", + }) + if err != nil { + t.Fatal(err) + } + var output *clientauthentication.ExecCredential + a.environ = func() []string { + data, err := runtime.Encode(codecs.LegacyCodec(a.group), output) + if err != nil { + t.Fatal(err) + } + return []string{"TEST_OUTPUT=" + string(data)} + } + a.now = func() time.Time { return now } + a.stderr = ioutil.Discard + + // We're not interested in server's cert, this test is about client cert. + tc := &transport.Config{TLS: transport.TLSConfig{Insecure: true}} + if err := a.UpdateTransportConfig(tc); err != nil { + t.Fatal(err) + } + + get := func(t *testing.T, desc string, wantErr bool) { + t.Run(desc, func(t *testing.T) { + tlsCfg, err := transport.TLSConfigFor(tc) + if err != nil { + t.Fatal("TLSConfigFor:", err) + } + client := http.Client{ + Transport: &http.Transport{TLSClientConfig: tlsCfg}, + } + resp, err := client.Get(server.URL) + switch { + case err != nil && !wantErr: + t.Errorf("got client.Get error: %q, want nil", err) + case err == nil && wantErr: + t.Error("got nil client.Get error, want non-nil") + } + if err == nil { + resp.Body.Close() + } + }) + } + + output = &clientauthentication.ExecCredential{ + Status: &clientauthentication.ExecCredentialStatus{ + ClientCertificateData: string(cert), + ClientKeyData: string(key), + ExpirationTimestamp: &v1.Time{now.Add(time.Hour)}, + }, + } + get(t, "valid TLS cert", false) + + // Advance time to force re-exec. + nCert, nKey := genClientCert(t) + now = now.Add(time.Hour * 2) + output = &clientauthentication.ExecCredential{ + Status: &clientauthentication.ExecCredentialStatus{ + ClientCertificateData: string(nCert), + ClientKeyData: string(nKey), + ExpirationTimestamp: &v1.Time{now.Add(time.Hour)}, + }, + } + get(t, "untrusted TLS cert", true) + + now = now.Add(time.Hour * 2) + output = &clientauthentication.ExecCredential{ + Status: &clientauthentication.ExecCredentialStatus{ + ClientCertificateData: string(cert), + ClientKeyData: string(key), + ExpirationTimestamp: &v1.Time{now.Add(time.Hour)}, + }, + } + get(t, "valid TLS cert again", false) +} + +// genClientCert generates an x509 certificate for testing. Certificate and key +// are returned in PEM encoding. +func genClientCert(t *testing.T) ([]byte, []byte) { + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + keyRaw, err := x509.MarshalECPrivateKey(key) + if err != nil { + t.Fatal(err) + } + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + t.Fatal(err) + } + cert := &x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{Organization: []string{"Acme Co"}}, + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + } + certRaw, err := x509.CreateCertificate(rand.Reader, cert, cert, key.Public(), key) + if err != nil { + t.Fatal(err) + } + return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certRaw}), + pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyRaw}) +} diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh b/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh index 6b9bb100c..aa7daad5f 100755 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/bash -e # Copyright 2018 The Kubernetes Authors. # diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp/BUILD b/vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp/BUILD deleted file mode 100644 index e57e896ae..000000000 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["gcp_test.go"], - embed = [":go_default_library"], - deps = ["//vendor/golang.org/x/oauth2:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["gcp.go"], - importpath = "k8s.io/client-go/plugin/pkg/client/auth/gcp", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/oauth2:go_default_library", - "//vendor/golang.org/x/oauth2/google:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/util/jsonpath:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp/gcp.go b/vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp/gcp.go index 3a4f86777..193d0c727 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp/gcp.go +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp/gcp.go @@ -18,6 +18,7 @@ package gcp import ( "bytes" + "context" "encoding/json" "fmt" "net/http" @@ -27,7 +28,6 @@ import ( "time" "github.com/golang/glog" - "golang.org/x/net/context" "golang.org/x/oauth2" "golang.org/x/oauth2/google" "k8s.io/apimachinery/pkg/util/net" diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/BUILD b/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/BUILD deleted file mode 100644 index ee76fac0d..000000000 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["oidc_test.go"], - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["oidc.go"], - importpath = "k8s.io/client-go/plugin/pkg/client/auth/oidc", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/oauth2:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/OWNERS b/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/OWNERS index d2210cb89..e0f3c6ca9 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/OWNERS +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/OWNERS @@ -2,3 +2,4 @@ approvers: - ericchiang reviewers: - ericchiang +- rithujohn191 diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go b/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go index 1fe52c524..9c3ea0ab8 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go @@ -279,7 +279,7 @@ func (p *oidcAuthProvider) idToken() (string, error) { // Persist new config and if successful, update the in memory config. if err = p.persister.Persist(newCfg); err != nil { - return "", fmt.Errorf("could not perist new tokens: %v", err) + return "", fmt.Errorf("could not persist new tokens: %v", err) } p.cfg = newCfg diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/BUILD b/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/BUILD deleted file mode 100644 index 750ffd6f5..000000000 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["openstack_test.go"], - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["openstack.go"], - importpath = "k8s.io/client-go/plugin/pkg/client/auth/openstack", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/gophercloud/gophercloud/openstack:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go b/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go index 490eff128..e6d7f0493 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go @@ -23,6 +23,7 @@ import ( "time" "github.com/golang/glog" + "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack" "k8s.io/apimachinery/pkg/util/net" @@ -42,8 +43,7 @@ const DefaultTTLDuration = 10 * time.Minute // the environment variables to determine the client identity, and generates a // token which will be inserted into the request header later. type openstackAuthProvider struct { - ttl time.Duration - + ttl time.Duration tokenGetter TokenGetter } @@ -52,13 +52,23 @@ type TokenGetter interface { Token() (string, error) } -type tokenGetter struct{} +type tokenGetter struct { + authOpt *gophercloud.AuthOptions +} // Token creates a token by authenticate with keystone. -func (*tokenGetter) Token() (string, error) { - options, err := openstack.AuthOptionsFromEnv() - if err != nil { - return "", fmt.Errorf("failed to read openstack env vars: %s", err) +func (t *tokenGetter) Token() (string, error) { + var options gophercloud.AuthOptions + var err error + if t.authOpt == nil { + // reads the config from the environment + glog.V(4).Info("reading openstack config from the environment variables") + options, err = openstack.AuthOptionsFromEnv() + if err != nil { + return "", fmt.Errorf("failed to read openstack env vars: %s", err) + } + } else { + options = *t.authOpt } client, err := openstack.AuthenticatedClient(options) if err != nil { @@ -85,7 +95,7 @@ func (c *cachedGetter) Token() (string, error) { var err error // no token or exceeds the TTL - if c.token == "" || time.Now().Sub(c.born) > c.ttl { + if c.token == "" || time.Since(c.born) > c.ttl { c.token, err = c.tokenGetter.Token() if err != nil { return "", fmt.Errorf("failed to get token: %s", err) @@ -126,10 +136,11 @@ func (t *tokenRoundTripper) WrappedRoundTripper() http.RoundTripper { return t.R // newOpenstackAuthProvider creates an auth provider which works with openstack // environment. -func newOpenstackAuthProvider(clusterAddress string, config map[string]string, persister restclient.AuthProviderConfigPersister) (restclient.AuthProvider, error) { +func newOpenstackAuthProvider(_ string, config map[string]string, persister restclient.AuthProviderConfigPersister) (restclient.AuthProvider, error) { var ttlDuration time.Duration var err error + glog.Warningf("WARNING: in-tree openstack auth plugin is now deprecated. please use the \"client-keystone-auth\" kubectl/client-go credential plugin instead") ttl, found := config["ttl"] if !found { ttlDuration = DefaultTTLDuration @@ -145,11 +156,27 @@ func newOpenstackAuthProvider(clusterAddress string, config map[string]string, p } } - // TODO: read/persist client configuration(OS_XXX env vars) in config + authOpt := gophercloud.AuthOptions{ + IdentityEndpoint: config["identityEndpoint"], + Username: config["username"], + Password: config["password"], + DomainName: config["name"], + TenantID: config["tenantId"], + TenantName: config["tenantName"], + } + + getter := tokenGetter{} + // not empty + if (authOpt != gophercloud.AuthOptions{}) { + if len(authOpt.IdentityEndpoint) == 0 { + return nil, fmt.Errorf("empty %q in the config for openstack auth provider", "identityEndpoint") + } + getter.authOpt = &authOpt + } return &openstackAuthProvider{ ttl: ttlDuration, - tokenGetter: &tokenGetter{}, + tokenGetter: &getter, }, nil } diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack_test.go b/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack_test.go index 411bec70f..24d55b9fc 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack_test.go +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack_test.go @@ -114,3 +114,60 @@ func TestOpenstackAuthProvider(t *testing.T) { } } + +type fakePersister struct{} + +func (i *fakePersister) Persist(map[string]string) error { + return nil +} + +func TestNewOpenstackAuthProvider(t *testing.T) { + tests := []struct { + name string + config map[string]string + expectError bool + }{ + { + name: "normal config without openstack configurations", + config: map[string]string{ + "ttl": "1s", + "foo": "bar", + }, + }, + { + name: "openstack auth provider: missing identityEndpoint", + config: map[string]string{ + "ttl": "1s", + "foo": "bar", + "username": "xyz", + "password": "123", + "tenantName": "admin", + }, + expectError: true, + }, + { + name: "openstack auth provider", + config: map[string]string{ + "ttl": "1s", + "foo": "bar", + "identityEndpoint": "http://controller:35357/v3", + "username": "xyz", + "password": "123", + "tenantName": "admin", + }, + }, + } + + for _, test := range tests { + _, err := newOpenstackAuthProvider("test", test.config, &fakePersister{}) + if err != nil { + if !test.expectError { + t.Errorf("unexpected error: %v", err) + } + } else { + if test.expectError { + t.Error("expect error, but nil") + } + } + } +} diff --git a/vendor/k8s.io/client-go/rest/BUILD b/vendor/k8s.io/client-go/rest/BUILD deleted file mode 100644 index 0cb24bcff..000000000 --- a/vendor/k8s.io/client-go/rest/BUILD +++ /dev/null @@ -1,99 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "client_test.go", - "config_test.go", - "plugin_test.go", - "request_test.go", - "url_utils_test.go", - "urlbackoff_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/google/gofuzz: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", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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: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/clock:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest/watch:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", - "//vendor/k8s.io/client-go/util/testing:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = [ - "client.go", - "config.go", - "plugin.go", - "request.go", - "transport.go", - "url_utils.go", - "urlbackoff.go", - "zz_generated.deepcopy.go", - ], - importpath = "k8s.io/client-go/rest", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/http2:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/streaming:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/plugin/pkg/client/auth/exec:go_default_library", - "//vendor/k8s.io/client-go/rest/watch:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", - "//vendor/k8s.io/client-go/tools/metrics:go_default_library", - "//vendor/k8s.io/client-go/transport:go_default_library", - "//vendor/k8s.io/client-go/util/cert:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/rest/fake:all-srcs", - "//staging/src/k8s.io/client-go/rest/watch:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/rest/config.go b/vendor/k8s.io/client-go/rest/config.go index 72a78bc0a..7934a0196 100644 --- a/vendor/k8s.io/client-go/rest/config.go +++ b/vendor/k8s.io/client-go/rest/config.go @@ -17,6 +17,7 @@ limitations under the License. package rest import ( + "context" "fmt" "io/ioutil" "net" @@ -29,7 +30,6 @@ import ( "github.com/golang/glog" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -111,7 +111,7 @@ type Config struct { Timeout time.Duration // Dial specifies the dial function for creating unencrypted TCP connections. - Dial func(network, addr string) (net.Conn, error) + Dial func(ctx context.Context, network, address string) (net.Conn, error) // Version forces a specific version to be used (if registered) // Do we need this? @@ -316,12 +316,12 @@ func InClusterConfig() (*Config, error) { return nil, fmt.Errorf("unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined") } - token, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/" + v1.ServiceAccountTokenKey) + token, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token") if err != nil { return nil, err } tlsClientConfig := TLSClientConfig{} - rootCAFile := "/var/run/secrets/kubernetes.io/serviceaccount/" + v1.ServiceAccountRootCAKey + rootCAFile := "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" if _, err := certutil.NewPool(rootCAFile); err != nil { glog.Errorf("Expected to load root CA config from %s, but got err: %v", rootCAFile, err) } else { diff --git a/vendor/k8s.io/client-go/rest/config_test.go b/vendor/k8s.io/client-go/rest/config_test.go index a9495d792..347864285 100644 --- a/vendor/k8s.io/client-go/rest/config_test.go +++ b/vendor/k8s.io/client-go/rest/config_test.go @@ -17,6 +17,8 @@ limitations under the License. package rest import ( + "context" + "errors" "io" "net" "net/http" @@ -25,8 +27,6 @@ import ( "strings" "testing" - fuzz "github.com/google/gofuzz" - "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -35,8 +35,7 @@ import ( clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/util/flowcontrol" - "errors" - + fuzz "github.com/google/gofuzz" "github.com/stretchr/testify/assert" ) @@ -208,7 +207,7 @@ func (n *fakeNegotiatedSerializer) DecoderToVersion(serializer runtime.Decoder, return &fakeCodec{} } -var fakeDialFunc = func(network, addr string) (net.Conn, error) { +var fakeDialFunc = func(ctx context.Context, network, addr string) (net.Conn, error) { return nil, fakeDialerError } var fakeDialerError = errors.New("fakedialer") @@ -253,7 +252,7 @@ func TestAnonymousConfig(t *testing.T) { r.Config = map[string]string{} }, // Dial does not require fuzzer - func(r *func(network, addr string) (net.Conn, error), f fuzz.Continue) {}, + func(r *func(ctx context.Context, network, addr string) (net.Conn, error), f fuzz.Continue) {}, ) for i := 0; i < 20; i++ { original := &Config{} @@ -284,10 +283,10 @@ func TestAnonymousConfig(t *testing.T) { expected.WrapTransport = nil } if actual.Dial != nil { - _, actualError := actual.Dial("", "") - _, expectedError := actual.Dial("", "") + _, actualError := actual.Dial(context.Background(), "", "") + _, expectedError := expected.Dial(context.Background(), "", "") if !reflect.DeepEqual(expectedError, actualError) { - t.Fatalf("CopyConfig dropped the Dial field") + t.Fatalf("CopyConfig dropped the Dial field") } } else { actual.Dial = nil @@ -329,7 +328,7 @@ func TestCopyConfig(t *testing.T) { func(r *AuthProviderConfigPersister, f fuzz.Continue) { *r = fakeAuthProviderConfigPersister{} }, - func(r *func(network, addr string) (net.Conn, error), f fuzz.Continue) { + func(r *func(ctx context.Context, network, addr string) (net.Conn, error), f fuzz.Continue) { *r = fakeDialFunc }, ) @@ -351,8 +350,8 @@ func TestCopyConfig(t *testing.T) { expected.WrapTransport = nil } if actual.Dial != nil { - _, actualError := actual.Dial("", "") - _, expectedError := actual.Dial("", "") + _, actualError := actual.Dial(context.Background(), "", "") + _, expectedError := expected.Dial(context.Background(), "", "") if !reflect.DeepEqual(expectedError, actualError) { t.Fatalf("CopyConfig dropped the Dial field") } @@ -361,7 +360,7 @@ func TestCopyConfig(t *testing.T) { expected.Dial = nil if actual.AuthConfigPersister != nil { actualError := actual.AuthConfigPersister.Persist(nil) - expectedError := actual.AuthConfigPersister.Persist(nil) + expectedError := expected.AuthConfigPersister.Persist(nil) if !reflect.DeepEqual(expectedError, actualError) { t.Fatalf("CopyConfig dropped the Dial field") } diff --git a/vendor/k8s.io/client-go/rest/fake/BUILD b/vendor/k8s.io/client-go/rest/fake/BUILD deleted file mode 100644 index e511b207a..000000000 --- a/vendor/k8s.io/client-go/rest/fake/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["fake.go"], - importpath = "k8s.io/client-go/rest/fake", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/rest/request.go b/vendor/k8s.io/client-go/rest/request.go index 6ca9e0197..09ffd76dd 100644 --- a/vendor/k8s.io/client-go/rest/request.go +++ b/vendor/k8s.io/client-go/rest/request.go @@ -317,10 +317,14 @@ func (r *Request) Param(paramName, s string) *Request { // VersionedParams will not write query parameters that have omitempty set and are empty. If a // parameter has already been set it is appended to (Params and VersionedParams are additive). func (r *Request) VersionedParams(obj runtime.Object, codec runtime.ParameterCodec) *Request { + return r.SpecificallyVersionedParams(obj, codec, *r.content.GroupVersion) +} + +func (r *Request) SpecificallyVersionedParams(obj runtime.Object, codec runtime.ParameterCodec, version schema.GroupVersion) *Request { if r.err != nil { return r } - params, err := codec.EncodeParameters(obj, *r.content.GroupVersion) + params, err := codec.EncodeParameters(obj, version) if err != nil { r.err = err return r @@ -353,8 +357,8 @@ func (r *Request) SetHeader(key string, values ...string) *Request { return r } -// Timeout makes the request use the given duration as a timeout. Sets the "timeout" -// parameter. +// Timeout makes the request use the given duration as an overall timeout for the +// request. Additionally, if set passes the value as "timeout" parameter in URL. func (r *Request) Timeout(d time.Duration) *Request { if r.err != nil { return r @@ -485,6 +489,19 @@ func (r *Request) tryThrottle() { // Watch attempts to begin watching the requested location. // Returns a watch.Interface, or an error. func (r *Request) Watch() (watch.Interface, error) { + return r.WatchWithSpecificDecoders( + func(body io.ReadCloser) streaming.Decoder { + framer := r.serializers.Framer.NewFrameReader(body) + return streaming.NewDecoder(framer, r.serializers.StreamingSerializer) + }, + r.serializers.Decoder, + ) +} + +// WatchWithSpecificDecoders attempts to begin watching the requested location with a *different* decoder. +// Turns out that you want one "standard" decoder for the watch event and one "personal" decoder for the content +// Returns a watch.Interface, or an error. +func (r *Request) WatchWithSpecificDecoders(wrapperDecoderFn func(io.ReadCloser) streaming.Decoder, embeddedDecoder runtime.Decoder) (watch.Interface, error) { // We specifically don't want to rate limit watches, so we // don't use r.throttle here. if r.err != nil { @@ -532,9 +549,8 @@ func (r *Request) Watch() (watch.Interface, error) { } return nil, fmt.Errorf("for request '%+v', got status: %v", url, resp.StatusCode) } - framer := r.serializers.Framer.NewFrameReader(resp.Body) - decoder := streaming.NewDecoder(framer, r.serializers.StreamingSerializer) - return watch.NewStreamWatcher(restclientwatch.NewDecoder(decoder, r.serializers.Decoder)), nil + wrapperDecoder := wrapperDecoderFn(resp.Body) + return watch.NewStreamWatcher(restclientwatch.NewDecoder(wrapperDecoder, embeddedDecoder)), nil } // updateURLMetrics is a convenience function for pushing metrics. @@ -640,7 +656,6 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error { } // Right now we make about ten retry attempts if we get a Retry-After response. - // TODO: Change to a timeout based approach. maxRetries := 10 retries := 0 for { @@ -649,6 +664,14 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error { if err != nil { return err } + if r.timeout > 0 { + if r.ctx == nil { + r.ctx = context.Background() + } + var cancelFn context.CancelFunc + r.ctx, cancelFn = context.WithTimeout(r.ctx, r.timeout) + defer cancelFn() + } if r.ctx != nil { req = req.WithContext(r.ctx) } diff --git a/vendor/k8s.io/client-go/rest/request_test.go b/vendor/k8s.io/client-go/rest/request_test.go index fac690255..f75ee86cb 100755 --- a/vendor/k8s.io/client-go/rest/request_test.go +++ b/vendor/k8s.io/client-go/rest/request_test.go @@ -1522,7 +1522,7 @@ func TestBody(t *testing.T) { f.Close() defer os.Remove(f.Name()) - var nilObject *v1.DeleteOptions + var nilObject *metav1.DeleteOptions typedObject := interface{}(nilObject) c := testRESTClient(t, nil) tests := []struct { diff --git a/vendor/k8s.io/client-go/rest/transport.go b/vendor/k8s.io/client-go/rest/transport.go index b6a067632..25c1801b6 100644 --- a/vendor/k8s.io/client-go/rest/transport.go +++ b/vendor/k8s.io/client-go/rest/transport.go @@ -18,6 +18,7 @@ package rest import ( "crypto/tls" + "errors" "net/http" "k8s.io/client-go/plugin/pkg/client/auth/exec" @@ -59,39 +60,10 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip // TransportConfig converts a client config to an appropriate transport config. func (c *Config) TransportConfig() (*transport.Config, error) { - wt := c.WrapTransport - if c.ExecProvider != nil { - provider, err := exec.GetAuthenticator(c.ExecProvider) - if err != nil { - return nil, err - } - if wt != nil { - previousWT := wt - wt = func(rt http.RoundTripper) http.RoundTripper { - return provider.WrapTransport(previousWT(rt)) - } - } else { - wt = provider.WrapTransport - } - } - if c.AuthProvider != nil { - provider, err := GetAuthProvider(c.Host, c.AuthProvider, c.AuthConfigPersister) - if err != nil { - return nil, err - } - if wt != nil { - previousWT := wt - wt = func(rt http.RoundTripper) http.RoundTripper { - return provider.WrapTransport(previousWT(rt)) - } - } else { - wt = provider.WrapTransport - } - } - return &transport.Config{ + conf := &transport.Config{ UserAgent: c.UserAgent, Transport: c.Transport, - WrapTransport: wt, + WrapTransport: c.WrapTransport, TLS: transport.TLSConfig{ Insecure: c.Insecure, ServerName: c.ServerName, @@ -111,5 +83,34 @@ func (c *Config) TransportConfig() (*transport.Config, error) { Extra: c.Impersonate.Extra, }, Dial: c.Dial, - }, nil + } + + if c.ExecProvider != nil && c.AuthProvider != nil { + return nil, errors.New("execProvider and authProvider cannot be used in combination") + } + + if c.ExecProvider != nil { + provider, err := exec.GetAuthenticator(c.ExecProvider) + if err != nil { + return nil, err + } + if err := provider.UpdateTransportConfig(conf); err != nil { + return nil, err + } + } + if c.AuthProvider != nil { + provider, err := GetAuthProvider(c.Host, c.AuthProvider, c.AuthConfigPersister) + if err != nil { + return nil, err + } + wt := conf.WrapTransport + if wt != nil { + conf.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { + return provider.WrapTransport(wt(rt)) + } + } else { + conf.WrapTransport = provider.WrapTransport + } + } + return conf, nil } diff --git a/vendor/k8s.io/client-go/rest/watch/BUILD b/vendor/k8s.io/client-go/rest/watch/BUILD deleted file mode 100644 index 30dfadd1f..000000000 --- a/vendor/k8s.io/client-go/rest/watch/BUILD +++ /dev/null @@ -1,56 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "decoder.go", - "encoder.go", - ], - importpath = "k8s.io/client-go/rest/watch", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - ], -) - -go_test( - name = "go_default_xtest", - srcs = [ - "decoder_test.go", - "encoder_test.go", - ], - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest/watch:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/rest/zz_generated.deepcopy.go b/vendor/k8s.io/client-go/rest/zz_generated.deepcopy.go index 67568bf0b..c1ab45f33 100644 --- a/vendor/k8s.io/client-go/rest/zz_generated.deepcopy.go +++ b/vendor/k8s.io/client-go/rest/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/restmapper/category_expansion.go b/vendor/k8s.io/client-go/restmapper/category_expansion.go new file mode 100644 index 000000000..1620bbcf8 --- /dev/null +++ b/vendor/k8s.io/client-go/restmapper/category_expansion.go @@ -0,0 +1,119 @@ +/* +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 restmapper + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" +) + +// CategoryExpander maps category strings to GroupResouces. +// Categories are classification or 'tag' of a group of resources. +type CategoryExpander interface { + Expand(category string) ([]schema.GroupResource, bool) +} + +// SimpleCategoryExpander implements CategoryExpander interface +// using a static mapping of categories to GroupResource mapping. +type SimpleCategoryExpander struct { + Expansions map[string][]schema.GroupResource +} + +// Expand fulfills CategoryExpander +func (e SimpleCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) { + ret, ok := e.Expansions[category] + return ret, ok +} + +// discoveryCategoryExpander struct lets a REST Client wrapper (discoveryClient) to retrieve list of APIResourceList, +// and then convert to fallbackExpander +type discoveryCategoryExpander struct { + discoveryClient discovery.DiscoveryInterface +} + +// NewDiscoveryCategoryExpander returns a category expander that makes use of the "categories" fields from +// the API, found through the discovery client. In case of any error or no category found (which likely +// means we're at a cluster prior to categories support, fallback to the expander provided. +func NewDiscoveryCategoryExpander(client discovery.DiscoveryInterface) CategoryExpander { + if client == nil { + panic("Please provide discovery client to shortcut expander") + } + return discoveryCategoryExpander{discoveryClient: client} +} + +// Expand fulfills CategoryExpander +func (e discoveryCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) { + // Get all supported resources for groups and versions from server, if no resource found, fallback anyway. + apiResourceLists, _ := e.discoveryClient.ServerResources() + if len(apiResourceLists) == 0 { + return nil, false + } + + discoveredExpansions := map[string][]schema.GroupResource{} + for _, apiResourceList := range apiResourceLists { + gv, err := schema.ParseGroupVersion(apiResourceList.GroupVersion) + if err != nil { + continue + } + // Collect GroupVersions by categories + for _, apiResource := range apiResourceList.APIResources { + if categories := apiResource.Categories; len(categories) > 0 { + for _, category := range categories { + groupResource := schema.GroupResource{ + Group: gv.Group, + Resource: apiResource.Name, + } + discoveredExpansions[category] = append(discoveredExpansions[category], groupResource) + } + } + } + } + + ret, ok := discoveredExpansions[category] + return ret, ok +} + +// UnionCategoryExpander implements CategoryExpander interface. +// It maps given category string to union of expansions returned by all the CategoryExpanders in the list. +type UnionCategoryExpander []CategoryExpander + +// Expand fulfills CategoryExpander +func (u UnionCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) { + ret := []schema.GroupResource{} + ok := false + + // Expand the category for each CategoryExpander in the list and merge/combine the results. + for _, expansion := range u { + curr, currOk := expansion.Expand(category) + + for _, currGR := range curr { + found := false + for _, existing := range ret { + if existing == currGR { + found = true + break + } + } + if !found { + ret = append(ret, currGR) + } + } + ok = ok || currOk + } + + return ret, ok +} diff --git a/vendor/k8s.io/client-go/restmapper/category_expansion_test.go b/vendor/k8s.io/client-go/restmapper/category_expansion_test.go new file mode 100644 index 000000000..8537a6b49 --- /dev/null +++ b/vendor/k8s.io/client-go/restmapper/category_expansion_test.go @@ -0,0 +1,145 @@ +/* +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 restmapper + +import ( + "reflect" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func TestCategoryExpansion(t *testing.T) { + tests := []struct { + name string + arg string + + expected []schema.GroupResource + expectedOk bool + }{ + { + name: "no-replacement", + arg: "service", + expected: nil, + }, + { + name: "all-replacement", + arg: "all", + expected: []schema.GroupResource{ + {Resource: "one"}, + {Resource: "two"}, + {Resource: "three", Group: "alpha"}, + {Resource: "four", Group: "bravo"}, + }, + expectedOk: true, + }, + } + + for _, test := range tests { + simpleCategoryExpander := SimpleCategoryExpander{ + Expansions: map[string][]schema.GroupResource{ + "all": { + {Group: "", Resource: "one"}, + {Group: "", Resource: "two"}, + {Group: "alpha", Resource: "three"}, + {Group: "bravo", Resource: "four"}, + }, + }, + } + + actual, actualOk := simpleCategoryExpander.Expand(test.arg) + if e, a := test.expected, actual; !reflect.DeepEqual(e, a) { + t.Errorf("%s: expected %s, got %s", test.name, e, a) + } + if e, a := test.expectedOk, actualOk; e != a { + t.Errorf("%s: expected %v, got %v", test.name, e, a) + } + } +} + +func TestDiscoveryCategoryExpander(t *testing.T) { + tests := []struct { + category string + serverResponse []*metav1.APIResourceList + expected []schema.GroupResource + }{ + { + category: "all", + serverResponse: []*metav1.APIResourceList{ + { + GroupVersion: "batch/v1", + APIResources: []metav1.APIResource{ + { + Name: "jobs", + ShortNames: []string{"jz"}, + Categories: []string{"all"}, + }, + }, + }, + }, + expected: []schema.GroupResource{ + { + Group: "batch", + Resource: "jobs", + }, + }, + }, + { + category: "all", + serverResponse: []*metav1.APIResourceList{ + { + GroupVersion: "batch/v1", + APIResources: []metav1.APIResource{ + { + Name: "jobs", + ShortNames: []string{"jz"}, + }, + }, + }, + }, + }, + { + category: "targaryens", + serverResponse: []*metav1.APIResourceList{ + { + GroupVersion: "batch/v1", + APIResources: []metav1.APIResource{ + { + Name: "jobs", + ShortNames: []string{"jz"}, + Categories: []string{"all"}, + }, + }, + }, + }, + }, + } + + dc := &fakeDiscoveryClient{} + for _, test := range tests { + dc.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { + return test.serverResponse, nil + } + expander := NewDiscoveryCategoryExpander(dc) + expanded, _ := expander.Expand(test.category) + if !reflect.DeepEqual(expanded, test.expected) { + t.Errorf("expected %v, got %v", test.expected, expanded) + } + } + +} diff --git a/vendor/k8s.io/client-go/restmapper/discovery.go b/vendor/k8s.io/client-go/restmapper/discovery.go new file mode 100644 index 000000000..58887cd89 --- /dev/null +++ b/vendor/k8s.io/client-go/restmapper/discovery.go @@ -0,0 +1,337 @@ +/* +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 restmapper + +import ( + "fmt" + "strings" + "sync" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" + + "github.com/golang/glog" +) + +// APIGroupResources is an API group with a mapping of versions to +// resources. +type APIGroupResources struct { + Group metav1.APIGroup + // A mapping of version string to a slice of APIResources for + // that version. + VersionedResources map[string][]metav1.APIResource +} + +// NewDiscoveryRESTMapper returns a PriorityRESTMapper based on the discovered +// groups and resources passed in. +func NewDiscoveryRESTMapper(groupResources []*APIGroupResources) meta.RESTMapper { + unionMapper := meta.MultiRESTMapper{} + + var groupPriority []string + // /v1 is special. It should always come first + resourcePriority := []schema.GroupVersionResource{{Group: "", Version: "v1", Resource: meta.AnyResource}} + kindPriority := []schema.GroupVersionKind{{Group: "", Version: "v1", Kind: meta.AnyKind}} + + for _, group := range groupResources { + groupPriority = append(groupPriority, group.Group.Name) + + // Make sure the preferred version comes first + if len(group.Group.PreferredVersion.Version) != 0 { + preferred := group.Group.PreferredVersion.Version + if _, ok := group.VersionedResources[preferred]; ok { + resourcePriority = append(resourcePriority, schema.GroupVersionResource{ + Group: group.Group.Name, + Version: group.Group.PreferredVersion.Version, + Resource: meta.AnyResource, + }) + + kindPriority = append(kindPriority, schema.GroupVersionKind{ + Group: group.Group.Name, + Version: group.Group.PreferredVersion.Version, + Kind: meta.AnyKind, + }) + } + } + + for _, discoveryVersion := range group.Group.Versions { + resources, ok := group.VersionedResources[discoveryVersion.Version] + if !ok { + continue + } + + // Add non-preferred versions after the preferred version, in case there are resources that only exist in those versions + if discoveryVersion.Version != group.Group.PreferredVersion.Version { + resourcePriority = append(resourcePriority, schema.GroupVersionResource{ + Group: group.Group.Name, + Version: discoveryVersion.Version, + Resource: meta.AnyResource, + }) + + kindPriority = append(kindPriority, schema.GroupVersionKind{ + Group: group.Group.Name, + Version: discoveryVersion.Version, + Kind: meta.AnyKind, + }) + } + + gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version} + versionMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{gv}) + + for _, resource := range resources { + scope := meta.RESTScopeNamespace + if !resource.Namespaced { + scope = meta.RESTScopeRoot + } + + // this is for legacy resources and servers which don't list singular forms. For those we must still guess. + if len(resource.SingularName) == 0 { + versionMapper.Add(gv.WithKind(resource.Kind), scope) + // TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior + versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope) + continue + } + + plural := gv.WithResource(resource.Name) + singular := gv.WithResource(resource.SingularName) + versionMapper.AddSpecific(gv.WithKind(resource.Kind), plural, singular, scope) + versionMapper.AddSpecific(gv.WithKind(strings.ToLower(resource.Kind)), plural, singular, scope) + // TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior + versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope) + } + // TODO why is this type not in discovery (at least for "v1") + versionMapper.Add(gv.WithKind("List"), meta.RESTScopeRoot) + unionMapper = append(unionMapper, versionMapper) + } + } + + for _, group := range groupPriority { + resourcePriority = append(resourcePriority, schema.GroupVersionResource{ + Group: group, + Version: meta.AnyVersion, + Resource: meta.AnyResource, + }) + kindPriority = append(kindPriority, schema.GroupVersionKind{ + Group: group, + Version: meta.AnyVersion, + Kind: meta.AnyKind, + }) + } + + return meta.PriorityRESTMapper{ + Delegate: unionMapper, + ResourcePriority: resourcePriority, + KindPriority: kindPriority, + } +} + +// GetAPIGroupResources uses the provided discovery client to gather +// discovery information and populate a slice of APIGroupResources. +func GetAPIGroupResources(cl discovery.DiscoveryInterface) ([]*APIGroupResources, error) { + apiGroups, err := cl.ServerGroups() + if err != nil { + if apiGroups == nil || len(apiGroups.Groups) == 0 { + return nil, err + } + // TODO track the errors and update callers to handle partial errors. + } + var result []*APIGroupResources + for _, group := range apiGroups.Groups { + groupResources := &APIGroupResources{ + Group: group, + VersionedResources: make(map[string][]metav1.APIResource), + } + for _, version := range group.Versions { + resources, err := cl.ServerResourcesForGroupVersion(version.GroupVersion) + if err != nil { + // continue as best we can + // TODO track the errors and update callers to handle partial errors. + if resources == nil || len(resources.APIResources) == 0 { + continue + } + } + groupResources.VersionedResources[version.Version] = resources.APIResources + } + result = append(result, groupResources) + } + return result, nil +} + +// DeferredDiscoveryRESTMapper is a RESTMapper that will defer +// initialization of the RESTMapper until the first mapping is +// requested. +type DeferredDiscoveryRESTMapper struct { + initMu sync.Mutex + delegate meta.RESTMapper + cl discovery.CachedDiscoveryInterface +} + +// NewDeferredDiscoveryRESTMapper returns a +// DeferredDiscoveryRESTMapper that will lazily query the provided +// client for discovery information to do REST mappings. +func NewDeferredDiscoveryRESTMapper(cl discovery.CachedDiscoveryInterface) *DeferredDiscoveryRESTMapper { + return &DeferredDiscoveryRESTMapper{ + cl: cl, + } +} + +func (d *DeferredDiscoveryRESTMapper) getDelegate() (meta.RESTMapper, error) { + d.initMu.Lock() + defer d.initMu.Unlock() + + if d.delegate != nil { + return d.delegate, nil + } + + groupResources, err := GetAPIGroupResources(d.cl) + if err != nil { + return nil, err + } + + d.delegate = NewDiscoveryRESTMapper(groupResources) + return d.delegate, err +} + +// Reset resets the internally cached Discovery information and will +// cause the next mapping request to re-discover. +func (d *DeferredDiscoveryRESTMapper) Reset() { + glog.V(5).Info("Invalidating discovery information") + + d.initMu.Lock() + defer d.initMu.Unlock() + + d.cl.Invalidate() + d.delegate = nil +} + +// KindFor takes a partial resource and returns back the single match. +// It returns an error if there are multiple matches. +func (d *DeferredDiscoveryRESTMapper) KindFor(resource schema.GroupVersionResource) (gvk schema.GroupVersionKind, err error) { + del, err := d.getDelegate() + if err != nil { + return schema.GroupVersionKind{}, err + } + gvk, err = del.KindFor(resource) + if err != nil && !d.cl.Fresh() { + d.Reset() + gvk, err = d.KindFor(resource) + } + return +} + +// KindsFor takes a partial resource and returns back the list of +// potential kinds in priority order. +func (d *DeferredDiscoveryRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvks []schema.GroupVersionKind, err error) { + del, err := d.getDelegate() + if err != nil { + return nil, err + } + gvks, err = del.KindsFor(resource) + if len(gvks) == 0 && !d.cl.Fresh() { + d.Reset() + gvks, err = d.KindsFor(resource) + } + return +} + +// ResourceFor takes a partial resource and returns back the single +// match. It returns an error if there are multiple matches. +func (d *DeferredDiscoveryRESTMapper) ResourceFor(input schema.GroupVersionResource) (gvr schema.GroupVersionResource, err error) { + del, err := d.getDelegate() + if err != nil { + return schema.GroupVersionResource{}, err + } + gvr, err = del.ResourceFor(input) + if err != nil && !d.cl.Fresh() { + d.Reset() + gvr, err = d.ResourceFor(input) + } + return +} + +// ResourcesFor takes a partial resource and returns back the list of +// potential resource in priority order. +func (d *DeferredDiscoveryRESTMapper) ResourcesFor(input schema.GroupVersionResource) (gvrs []schema.GroupVersionResource, err error) { + del, err := d.getDelegate() + if err != nil { + return nil, err + } + gvrs, err = del.ResourcesFor(input) + if len(gvrs) == 0 && !d.cl.Fresh() { + d.Reset() + gvrs, err = d.ResourcesFor(input) + } + return +} + +// RESTMapping identifies a preferred resource mapping for the +// provided group kind. +func (d *DeferredDiscoveryRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (m *meta.RESTMapping, err error) { + del, err := d.getDelegate() + if err != nil { + return nil, err + } + m, err = del.RESTMapping(gk, versions...) + if err != nil && !d.cl.Fresh() { + d.Reset() + m, err = d.RESTMapping(gk, versions...) + } + return +} + +// RESTMappings returns the RESTMappings for the provided group kind +// in a rough internal preferred order. If no kind is found, it will +// return a NoResourceMatchError. +func (d *DeferredDiscoveryRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (ms []*meta.RESTMapping, err error) { + del, err := d.getDelegate() + if err != nil { + return nil, err + } + ms, err = del.RESTMappings(gk, versions...) + if len(ms) == 0 && !d.cl.Fresh() { + d.Reset() + ms, err = d.RESTMappings(gk, versions...) + } + return +} + +// ResourceSingularizer converts a resource name from plural to +// singular (e.g., from pods to pod). +func (d *DeferredDiscoveryRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { + del, err := d.getDelegate() + if err != nil { + return resource, err + } + singular, err = del.ResourceSingularizer(resource) + if err != nil && !d.cl.Fresh() { + d.Reset() + singular, err = d.ResourceSingularizer(resource) + } + return +} + +func (d *DeferredDiscoveryRESTMapper) String() string { + del, err := d.getDelegate() + if err != nil { + return fmt.Sprintf("DeferredDiscoveryRESTMapper{%v}", err) + } + return fmt.Sprintf("DeferredDiscoveryRESTMapper{\n\t%v\n}", del) +} + +// Make sure it satisfies the interface +var _ meta.RESTMapper = &DeferredDiscoveryRESTMapper{} diff --git a/vendor/k8s.io/client-go/restmapper/discovery_test.go b/vendor/k8s.io/client-go/restmapper/discovery_test.go new file mode 100644 index 000000000..1b8e7c4f0 --- /dev/null +++ b/vendor/k8s.io/client-go/restmapper/discovery_test.go @@ -0,0 +1,384 @@ +/* +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 restmapper + +import ( + "reflect" + "testing" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/version" + . "k8s.io/client-go/discovery" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" + + "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/stretchr/testify/assert" +) + +func TestRESTMapper(t *testing.T) { + resources := []*APIGroupResources{ + { + Group: metav1.APIGroup{ + Name: "extensions", + Versions: []metav1.GroupVersionForDiscovery{ + {Version: "v1beta"}, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1beta"}, + }, + VersionedResources: map[string][]metav1.APIResource{ + "v1beta": { + {Name: "jobs", Namespaced: true, Kind: "Job"}, + {Name: "pods", Namespaced: true, Kind: "Pod"}, + }, + }, + }, + { + Group: metav1.APIGroup{ + Versions: []metav1.GroupVersionForDiscovery{ + {Version: "v1"}, + {Version: "v2"}, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1"}, + }, + VersionedResources: map[string][]metav1.APIResource{ + "v1": { + {Name: "pods", Namespaced: true, Kind: "Pod"}, + }, + "v2": { + {Name: "pods", Namespaced: true, Kind: "Pod"}, + }, + }, + }, + + // This group tests finding and prioritizing resources that only exist in non-preferred versions + { + Group: metav1.APIGroup{ + Name: "unpreferred", + Versions: []metav1.GroupVersionForDiscovery{ + {Version: "v1"}, + {Version: "v2beta1"}, + {Version: "v2alpha1"}, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1"}, + }, + VersionedResources: map[string][]metav1.APIResource{ + "v1": { + {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, + }, + "v2beta1": { + {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, + {Name: "peas", Namespaced: true, Kind: "Pea"}, + }, + "v2alpha1": { + {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, + {Name: "peas", Namespaced: true, Kind: "Pea"}, + }, + }, + }, + } + + restMapper := NewDiscoveryRESTMapper(resources) + + kindTCs := []struct { + input schema.GroupVersionResource + want schema.GroupVersionKind + }{ + { + input: schema.GroupVersionResource{ + Resource: "pods", + }, + want: schema.GroupVersionKind{ + Version: "v1", + Kind: "Pod", + }, + }, + { + input: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + want: schema.GroupVersionKind{ + Version: "v1", + Kind: "Pod", + }, + }, + { + input: schema.GroupVersionResource{ + Version: "v2", + Resource: "pods", + }, + want: schema.GroupVersionKind{ + Version: "v2", + Kind: "Pod", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "pods", + }, + want: schema.GroupVersionKind{ + Version: "v1", + Kind: "Pod", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "jobs", + }, + want: schema.GroupVersionKind{ + Group: "extensions", + Version: "v1beta", + Kind: "Job", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "peas", + }, + want: schema.GroupVersionKind{ + Group: "unpreferred", + Version: "v2beta1", + Kind: "Pea", + }, + }, + } + + for _, tc := range kindTCs { + got, err := restMapper.KindFor(tc.input) + if err != nil { + t.Errorf("KindFor(%#v) unexpected error: %v", tc.input, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("KindFor(%#v) = %#v, want %#v", tc.input, got, tc.want) + } + } + + resourceTCs := []struct { + input schema.GroupVersionResource + want schema.GroupVersionResource + }{ + { + input: schema.GroupVersionResource{ + Resource: "pods", + }, + want: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + { + input: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + want: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + { + input: schema.GroupVersionResource{ + Version: "v2", + Resource: "pods", + }, + want: schema.GroupVersionResource{ + Version: "v2", + Resource: "pods", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "pods", + }, + want: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "jobs", + }, + want: schema.GroupVersionResource{ + Group: "extensions", + Version: "v1beta", + Resource: "jobs", + }, + }, + } + + for _, tc := range resourceTCs { + got, err := restMapper.ResourceFor(tc.input) + if err != nil { + t.Errorf("ResourceFor(%#v) unexpected error: %v", tc.input, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("ResourceFor(%#v) = %#v, want %#v", tc.input, got, tc.want) + } + } +} + +func TestDeferredDiscoveryRESTMapper_CacheMiss(t *testing.T) { + assert := assert.New(t) + + cdc := fakeCachedDiscoveryInterface{fresh: false} + m := NewDeferredDiscoveryRESTMapper(&cdc) + assert.False(cdc.fresh, "should NOT be fresh after instantiation") + assert.Zero(cdc.invalidateCalls, "should not have called Invalidate()") + + gvk, err := m.KindFor(schema.GroupVersionResource{ + Group: "a", + Version: "v1", + Resource: "foo", + }) + assert.NoError(err) + assert.True(cdc.fresh, "should be fresh after a cache-miss") + assert.Equal(cdc.invalidateCalls, 1, "should have called Invalidate() once") + assert.Equal(gvk.Kind, "Foo") + + gvk, err = m.KindFor(schema.GroupVersionResource{ + Group: "a", + Version: "v1", + Resource: "foo", + }) + assert.NoError(err) + assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again") + + gvk, err = m.KindFor(schema.GroupVersionResource{ + Group: "a", + Version: "v1", + Resource: "bar", + }) + assert.Error(err) + assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again after another cache-miss, but with fresh==true") + + cdc.fresh = false + gvk, err = m.KindFor(schema.GroupVersionResource{ + Group: "a", + Version: "v1", + Resource: "bar", + }) + assert.Error(err) + assert.Equal(cdc.invalidateCalls, 2, "should HAVE called Invalidate() again after another cache-miss, but with fresh==false") +} + +type fakeCachedDiscoveryInterface struct { + invalidateCalls int + fresh bool + enabledA bool +} + +var _ CachedDiscoveryInterface = &fakeCachedDiscoveryInterface{} + +func (c *fakeCachedDiscoveryInterface) Fresh() bool { + return c.fresh +} + +func (c *fakeCachedDiscoveryInterface) Invalidate() { + c.invalidateCalls = c.invalidateCalls + 1 + c.fresh = true + c.enabledA = true +} + +func (c *fakeCachedDiscoveryInterface) RESTClient() restclient.Interface { + return &fake.RESTClient{} +} + +func (c *fakeCachedDiscoveryInterface) ServerGroups() (*metav1.APIGroupList, error) { + if c.enabledA { + return &metav1.APIGroupList{ + Groups: []metav1.APIGroup{ + { + Name: "a", + Versions: []metav1.GroupVersionForDiscovery{ + { + GroupVersion: "a/v1", + Version: "v1", + }, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "a/v1", + Version: "v1", + }, + }, + }, + }, nil + } + return &metav1.APIGroupList{}, nil +} + +func (c *fakeCachedDiscoveryInterface) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + if c.enabledA && groupVersion == "a/v1" { + return &metav1.APIResourceList{ + GroupVersion: "a/v1", + APIResources: []metav1.APIResource{ + { + Name: "foo", + Kind: "Foo", + Namespaced: false, + }, + }, + }, nil + } + + return nil, errors.NewNotFound(schema.GroupResource{}, "") +} + +func (c *fakeCachedDiscoveryInterface) ServerResources() ([]*metav1.APIResourceList, error) { + if c.enabledA { + av1, _ := c.ServerResourcesForGroupVersion("a/v1") + return []*metav1.APIResourceList{av1}, nil + } + return []*metav1.APIResourceList{}, nil +} + +func (c *fakeCachedDiscoveryInterface) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + if c.enabledA { + return []*metav1.APIResourceList{ + { + GroupVersion: "a/v1", + APIResources: []metav1.APIResource{ + { + Name: "foo", + Kind: "Foo", + Verbs: []string{}, + }, + }, + }, + }, nil + } + return nil, nil +} + +func (c *fakeCachedDiscoveryInterface) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return nil, nil +} + +func (c *fakeCachedDiscoveryInterface) ServerVersion() (*version.Info, error) { + return &version.Info{}, nil +} + +func (c *fakeCachedDiscoveryInterface) OpenAPISchema() (*openapi_v2.Document, error) { + return &openapi_v2.Document{}, nil +} diff --git a/vendor/k8s.io/client-go/restmapper/shortcut.go b/vendor/k8s.io/client-go/restmapper/shortcut.go new file mode 100644 index 000000000..d9f4be0b6 --- /dev/null +++ b/vendor/k8s.io/client-go/restmapper/shortcut.go @@ -0,0 +1,172 @@ +/* +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 restmapper + +import ( + "strings" + + "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" +) + +// shortcutExpander is a RESTMapper that can be used for Kubernetes resources. It expands the resource first, then invokes the wrapped +type shortcutExpander struct { + RESTMapper meta.RESTMapper + + discoveryClient discovery.DiscoveryInterface +} + +var _ meta.RESTMapper = &shortcutExpander{} + +// NewShortcutExpander wraps a restmapper in a layer that expands shortcuts found via discovery +func NewShortcutExpander(delegate meta.RESTMapper, client discovery.DiscoveryInterface) meta.RESTMapper { + return shortcutExpander{RESTMapper: delegate, discoveryClient: client} +} + +// KindFor fulfills meta.RESTMapper +func (e shortcutExpander) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { + return e.RESTMapper.KindFor(e.expandResourceShortcut(resource)) +} + +// KindsFor fulfills meta.RESTMapper +func (e shortcutExpander) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { + return e.RESTMapper.KindsFor(e.expandResourceShortcut(resource)) +} + +// ResourcesFor fulfills meta.RESTMapper +func (e shortcutExpander) ResourcesFor(resource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { + return e.RESTMapper.ResourcesFor(e.expandResourceShortcut(resource)) +} + +// ResourceFor fulfills meta.RESTMapper +func (e shortcutExpander) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) { + return e.RESTMapper.ResourceFor(e.expandResourceShortcut(resource)) +} + +// ResourceSingularizer fulfills meta.RESTMapper +func (e shortcutExpander) ResourceSingularizer(resource string) (string, error) { + return e.RESTMapper.ResourceSingularizer(e.expandResourceShortcut(schema.GroupVersionResource{Resource: resource}).Resource) +} + +// RESTMapping fulfills meta.RESTMapper +func (e shortcutExpander) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { + return e.RESTMapper.RESTMapping(gk, versions...) +} + +// RESTMappings fulfills meta.RESTMapper +func (e shortcutExpander) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) { + return e.RESTMapper.RESTMappings(gk, versions...) +} + +// getShortcutMappings returns a set of tuples which holds short names for resources. +// First the list of potential resources will be taken from the API server. +// Next we will append the hardcoded list of resources - to be backward compatible with old servers. +// NOTE that the list is ordered by group priority. +func (e shortcutExpander) getShortcutMappings() ([]*metav1.APIResourceList, []resourceShortcuts, error) { + res := []resourceShortcuts{} + // get server resources + // This can return an error *and* the results it was able to find. We don't need to fail on the error. + apiResList, err := e.discoveryClient.ServerResources() + if err != nil { + glog.V(1).Infof("Error loading discovery information: %v", err) + } + for _, apiResources := range apiResList { + gv, err := schema.ParseGroupVersion(apiResources.GroupVersion) + if err != nil { + glog.V(1).Infof("Unable to parse groupversion = %s due to = %s", apiResources.GroupVersion, err.Error()) + continue + } + for _, apiRes := range apiResources.APIResources { + for _, shortName := range apiRes.ShortNames { + rs := resourceShortcuts{ + ShortForm: schema.GroupResource{Group: gv.Group, Resource: shortName}, + LongForm: schema.GroupResource{Group: gv.Group, Resource: apiRes.Name}, + } + res = append(res, rs) + } + } + } + + return apiResList, res, nil +} + +// expandResourceShortcut will return the expanded version of resource +// (something that a pkg/api/meta.RESTMapper can understand), if it is +// indeed a shortcut. If no match has been found, we will match on group prefixing. +// Lastly we will return resource unmodified. +func (e shortcutExpander) expandResourceShortcut(resource schema.GroupVersionResource) schema.GroupVersionResource { + // get the shortcut mappings and return on first match. + if allResources, shortcutResources, err := e.getShortcutMappings(); err == nil { + // avoid expanding if there's an exact match to a full resource name + for _, apiResources := range allResources { + gv, err := schema.ParseGroupVersion(apiResources.GroupVersion) + if err != nil { + continue + } + if len(resource.Group) != 0 && resource.Group != gv.Group { + continue + } + for _, apiRes := range apiResources.APIResources { + if resource.Resource == apiRes.Name { + return resource + } + if resource.Resource == apiRes.SingularName { + return resource + } + } + } + + for _, item := range shortcutResources { + if len(resource.Group) != 0 && resource.Group != item.ShortForm.Group { + continue + } + if resource.Resource == item.ShortForm.Resource { + resource.Resource = item.LongForm.Resource + resource.Group = item.LongForm.Group + return resource + } + } + + // we didn't find exact match so match on group prefixing. This allows autoscal to match autoscaling + if len(resource.Group) == 0 { + return resource + } + for _, item := range shortcutResources { + if !strings.HasPrefix(item.ShortForm.Group, resource.Group) { + continue + } + if resource.Resource == item.ShortForm.Resource { + resource.Resource = item.LongForm.Resource + resource.Group = item.LongForm.Group + return resource + } + } + } + + return resource +} + +// ResourceShortcuts represents a structure that holds the information how to +// transition from resource's shortcut to its full name. +type resourceShortcuts struct { + ShortForm schema.GroupResource + LongForm schema.GroupResource +} diff --git a/vendor/k8s.io/client-go/restmapper/shortcut_test.go b/vendor/k8s.io/client-go/restmapper/shortcut_test.go new file mode 100644 index 000000000..dbc288fad --- /dev/null +++ b/vendor/k8s.io/client-go/restmapper/shortcut_test.go @@ -0,0 +1,289 @@ +/* +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 restmapper + +import ( + "testing" + + "github.com/googleapis/gnostic/OpenAPIv2" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/version" + "k8s.io/client-go/discovery" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" +) + +func TestReplaceAliases(t *testing.T) { + tests := []struct { + name string + arg string + expected schema.GroupVersionResource + srvRes []*metav1.APIResourceList + }{ + { + name: "storageclasses-no-replacement", + arg: "storageclasses", + expected: schema.GroupVersionResource{Resource: "storageclasses"}, + srvRes: []*metav1.APIResourceList{}, + }, + { + name: "hpa-priority", + arg: "hpa", + expected: schema.GroupVersionResource{Resource: "superhorizontalpodautoscalers", Group: "autoscaling"}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "autoscaling/v1", + APIResources: []metav1.APIResource{ + { + Name: "superhorizontalpodautoscalers", + ShortNames: []string{"hpa"}, + }, + }, + }, + { + GroupVersion: "autoscaling/v1", + APIResources: []metav1.APIResource{ + { + Name: "horizontalpodautoscalers", + ShortNames: []string{"hpa"}, + }, + }, + }, + }, + }, + { + name: "resource-override", + arg: "dpl", + expected: schema.GroupVersionResource{Resource: "deployments", Group: "foo"}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "foo/v1", + APIResources: []metav1.APIResource{ + { + Name: "deployments", + ShortNames: []string{"dpl"}, + }, + }, + }, + { + GroupVersion: "extension/v1beta1", + APIResources: []metav1.APIResource{ + { + Name: "deployments", + ShortNames: []string{"deploy"}, + }, + }, + }, + }, + }, + { + name: "resource-match-preferred", + arg: "pods", + expected: schema.GroupVersionResource{Resource: "pods", Group: ""}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "v1", + APIResources: []metav1.APIResource{{Name: "pods", SingularName: "pod"}}, + }, + { + GroupVersion: "acme.com/v1", + APIResources: []metav1.APIResource{{Name: "poddlers", ShortNames: []string{"pods", "pod"}}}, + }, + }, + }, + { + name: "resource-match-singular-preferred", + arg: "pod", + expected: schema.GroupVersionResource{Resource: "pod", Group: ""}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "v1", + APIResources: []metav1.APIResource{{Name: "pods", SingularName: "pod"}}, + }, + { + GroupVersion: "acme.com/v1", + APIResources: []metav1.APIResource{{Name: "poddlers", ShortNames: []string{"pods", "pod"}}}, + }, + }, + }, + } + + for _, test := range tests { + ds := &fakeDiscoveryClient{} + ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { + return test.srvRes, nil + } + mapper := NewShortcutExpander(&fakeRESTMapper{}, ds).(shortcutExpander) + + actual := mapper.expandResourceShortcut(schema.GroupVersionResource{Resource: test.arg}) + if actual != test.expected { + t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, actual) + } + } +} + +func TestKindFor(t *testing.T) { + tests := []struct { + in schema.GroupVersionResource + expected schema.GroupVersionResource + srvRes []*metav1.APIResourceList + }{ + { + in: schema.GroupVersionResource{Group: "storage.k8s.io", Version: "", Resource: "sc"}, + expected: schema.GroupVersionResource{Group: "storage.k8s.io", Version: "", Resource: "storageclasses"}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "storage.k8s.io/v1", + APIResources: []metav1.APIResource{ + { + Name: "storageclasses", + ShortNames: []string{"sc"}, + }, + }, + }, + }, + }, + { + in: schema.GroupVersionResource{Group: "", Version: "", Resource: "sc"}, + expected: schema.GroupVersionResource{Group: "storage.k8s.io", Version: "", Resource: "storageclasses"}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "storage.k8s.io/v1", + APIResources: []metav1.APIResource{ + { + Name: "storageclasses", + ShortNames: []string{"sc"}, + }, + }, + }, + }, + }, + } + + for i, test := range tests { + ds := &fakeDiscoveryClient{} + ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { + return test.srvRes, nil + } + + delegate := &fakeRESTMapper{} + mapper := NewShortcutExpander(delegate, ds) + + mapper.KindFor(test.in) + if delegate.kindForInput != test.expected { + t.Errorf("%d: unexpected data returned %#v, expected %#v", i, delegate.kindForInput, test.expected) + } + } +} + +type fakeRESTMapper struct { + kindForInput schema.GroupVersionResource +} + +func (f *fakeRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { + f.kindForInput = resource + return schema.GroupVersionKind{}, nil +} + +func (f *fakeRESTMapper) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { + return nil, nil +} + +func (f *fakeRESTMapper) ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) { + return schema.GroupVersionResource{}, nil +} + +func (f *fakeRESTMapper) ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { + return nil, nil +} + +func (f *fakeRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { + return nil, nil +} + +func (f *fakeRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) { + return nil, nil +} + +func (f *fakeRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { + return "", nil +} + +type fakeDiscoveryClient struct { + serverResourcesHandler func() ([]*metav1.APIResourceList, error) +} + +var _ discovery.DiscoveryInterface = &fakeDiscoveryClient{} + +func (c *fakeDiscoveryClient) RESTClient() restclient.Interface { + return &fake.RESTClient{} +} + +func (c *fakeDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { + return &metav1.APIGroupList{ + Groups: []metav1.APIGroup{ + { + Name: "a", + Versions: []metav1.GroupVersionForDiscovery{ + { + GroupVersion: "a/v1", + Version: "v1", + }, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "a/v1", + Version: "v1", + }, + }, + }, + }, nil +} + +func (c *fakeDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + if groupVersion == "a/v1" { + return &metav1.APIResourceList{APIResources: []metav1.APIResource{{Name: "widgets", Kind: "Widget"}}}, nil + } + + return nil, errors.NewNotFound(schema.GroupResource{}, "") +} + +func (c *fakeDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { + if c.serverResourcesHandler != nil { + return c.serverResourcesHandler() + } + return []*metav1.APIResourceList{}, nil +} + +func (c *fakeDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + return nil, nil +} + +func (c *fakeDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return nil, nil +} + +func (c *fakeDiscoveryClient) ServerVersion() (*version.Info, error) { + return &version.Info{}, nil +} + +func (c *fakeDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { + return &openapi_v2.Document{}, nil +} diff --git a/vendor/k8s.io/client-go/scale/BUILD b/vendor/k8s.io/client-go/scale/BUILD deleted file mode 100644 index b82984243..000000000 --- a/vendor/k8s.io/client-go/scale/BUILD +++ /dev/null @@ -1,76 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "client.go", - "doc.go", - "interfaces.go", - "util.go", - ], - importpath = "k8s.io/client-go/scale", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta: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:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - "//vendor/k8s.io/client-go/dynamic:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme/appsint:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme/appsv1beta1:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme/appsv1beta2:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme/autoscalingv1:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme/extensionsint:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "client_test.go", - "roundtrip_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", - "//vendor/k8s.io/api/autoscaling/v1: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/meta: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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - "//vendor/k8s.io/client-go/discovery/fake:go_default_library", - "//vendor/k8s.io/client-go/dynamic:go_default_library", - "//vendor/k8s.io/client-go/rest/fake:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/scale/fake:all-srcs", - "//staging/src/k8s.io/client-go/scale/scheme:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/scale/client.go b/vendor/k8s.io/client-go/scale/client.go index 782aca394..3a3e8fc9e 100644 --- a/vendor/k8s.io/client-go/scale/client.go +++ b/vendor/k8s.io/client-go/scale/client.go @@ -20,7 +20,6 @@ import ( "fmt" autoscaling "k8s.io/api/autoscaling/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" @@ -41,7 +40,7 @@ type restInterfaceProvider func(*restclient.Config) (restclient.Interface, error // It behaves somewhat similarly to the dynamic ClientPool, // but is more specifically scoped to Scale. type scaleClient struct { - mapper meta.RESTMapper + mapper PreferredResourceMapper apiPathResolverFunc dynamic.APIPathResolverFunc scaleKindResolver ScaleKindResolver @@ -51,7 +50,7 @@ type scaleClient struct { // NewForConfig creates a new ScalesGetter which resolves kinds // to resources using the given RESTMapper, and API paths using // the given dynamic.APIPathResolverFunc. -func NewForConfig(cfg *restclient.Config, mapper meta.RESTMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) (ScalesGetter, error) { +func NewForConfig(cfg *restclient.Config, mapper PreferredResourceMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) (ScalesGetter, error) { // so that the RESTClientFor doesn't complain cfg.GroupVersion = &schema.GroupVersion{} @@ -72,7 +71,7 @@ func NewForConfig(cfg *restclient.Config, mapper meta.RESTMapper, resolver dynam // New creates a new ScalesGetter using the given client to make requests. // The GroupVersion on the client is ignored. -func New(baseClient restclient.Interface, mapper meta.RESTMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) ScalesGetter { +func New(baseClient restclient.Interface, mapper PreferredResourceMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) ScalesGetter { return &scaleClient{ mapper: mapper, @@ -138,7 +137,7 @@ func (c *namespacedScaleClient) Get(resource schema.GroupResource, name string) SubResource("scale"). Do() if err := result.Error(); err != nil { - return nil, fmt.Errorf("could not fetch the scale for %s %s: %v", resource.String(), name, err) + return nil, err } scaleBytes, err := result.Raw() @@ -196,7 +195,10 @@ func (c *namespacedScaleClient) Update(resource schema.GroupResource, scale *aut Body(scaleUpdateBytes). Do() if err := result.Error(); err != nil { - return nil, fmt.Errorf("could not update the scale for %s %s: %v", resource.String(), scale.Name, err) + // propagate "raw" error from the API + // this allows callers to interpret underlying Reason field + // for example: errors.IsConflict(err) + return nil, err } scaleBytes, err := result.Raw() diff --git a/vendor/k8s.io/client-go/scale/client_test.go b/vendor/k8s.io/client-go/scale/client_test.go index 6301320f3..a3a8c037d 100644 --- a/vendor/k8s.io/client-go/scale/client_test.go +++ b/vendor/k8s.io/client-go/scale/client_test.go @@ -29,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/client-go/discovery" fakedisco "k8s.io/client-go/discovery/fake" "k8s.io/client-go/dynamic" fakerest "k8s.io/client-go/rest/fake" @@ -40,7 +39,7 @@ import ( autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" extv1beta1 "k8s.io/api/extensions/v1beta1" - apimeta "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/restmapper" coretesting "k8s.io/client-go/testing" ) @@ -97,11 +96,11 @@ func fakeScaleClient(t *testing.T) (ScalesGetter, []schema.GroupResource) { }, } - restMapperRes, err := discovery.GetAPIGroupResources(fakeDiscoveryClient) + restMapperRes, err := restmapper.GetAPIGroupResources(fakeDiscoveryClient) if err != nil { t.Fatalf("unexpected error while constructing resource list from fake discovery client: %v", err) } - restMapper := discovery.NewRESTMapper(restMapperRes, apimeta.InterfacesForUnstructured) + restMapper := restmapper.NewDiscoveryRESTMapper(restMapperRes) autoscalingScale := &autoscalingv1.Scale{ TypeMeta: metav1.TypeMeta{ diff --git a/vendor/k8s.io/client-go/scale/fake/BUILD b/vendor/k8s.io/client-go/scale/fake/BUILD deleted file mode 100644 index 8c9374305..000000000 --- a/vendor/k8s.io/client-go/scale/fake/BUILD +++ /dev/null @@ -1,28 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["client.go"], - importpath = "k8s.io/client-go/scale/fake", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/client-go/scale:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/scale/scheme/BUILD b/vendor/k8s.io/client-go/scale/scheme/BUILD deleted file mode 100644 index 74bd976a1..000000000 --- a/vendor/k8s.io/client-go/scale/scheme/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "register.go", - "types.go", - "zz_generated.deepcopy.go", - ], - importpath = "k8s.io/client-go/scale/scheme", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/scale/scheme/appsint:all-srcs", - "//staging/src/k8s.io/client-go/scale/scheme/appsv1beta1:all-srcs", - "//staging/src/k8s.io/client-go/scale/scheme/appsv1beta2:all-srcs", - "//staging/src/k8s.io/client-go/scale/scheme/autoscalingv1:all-srcs", - "//staging/src/k8s.io/client-go/scale/scheme/extensionsint:all-srcs", - "//staging/src/k8s.io/client-go/scale/scheme/extensionsv1beta1:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/scale/scheme/appsint/BUILD b/vendor/k8s.io/client-go/scale/scheme/appsint/BUILD deleted file mode 100644 index 2fef63f0e..000000000 --- a/vendor/k8s.io/client-go/scale/scheme/appsint/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "register.go", - ], - importpath = "k8s.io/client-go/scale/scheme/appsint", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/apps/v1beta2: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/client-go/scale/scheme:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/BUILD b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/BUILD deleted file mode 100644 index 05530e300..000000000 --- a/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "conversion.go", - "doc.go", - "register.go", - "zz_generated.conversion.go", - ], - importpath = "k8s.io/client-go/scale/scheme/appsv1beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/apps/v1beta1: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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go index bd42e7add..00734d437 100644 --- a/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/BUILD b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/BUILD deleted file mode 100644 index 7e52bc060..000000000 --- a/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "conversion.go", - "doc.go", - "register.go", - "zz_generated.conversion.go", - ], - importpath = "k8s.io/client-go/scale/scheme/appsv1beta2", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/apps/v1beta2: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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go index d6afedb0d..44f28aa1a 100644 --- a/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/BUILD b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/BUILD deleted file mode 100644 index 646a6fdf8..000000000 --- a/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "conversion.go", - "doc.go", - "register.go", - "zz_generated.conversion.go", - ], - importpath = "k8s.io/client-go/scale/scheme/autoscalingv1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/autoscaling/v1: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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go index 2a7a45a47..474c80350 100644 --- a/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go +++ b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/scale/scheme/extensionsint/BUILD b/vendor/k8s.io/client-go/scale/scheme/extensionsint/BUILD deleted file mode 100644 index 6174a88b1..000000000 --- a/vendor/k8s.io/client-go/scale/scheme/extensionsint/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "register.go", - ], - importpath = "k8s.io/client-go/scale/scheme/extensionsint", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/extensions/v1beta1: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/client-go/scale/scheme:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/BUILD b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/BUILD deleted file mode 100644 index 4c992c7d1..000000000 --- a/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "conversion.go", - "doc.go", - "register.go", - "zz_generated.conversion.go", - ], - importpath = "k8s.io/client-go/scale/scheme/extensionsv1beta1", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/extensions/v1beta1: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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/client-go/scale/scheme:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go index 6d0ed7a29..26ed5754e 100644 --- a/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go b/vendor/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go index d34399667..7fe882f03 100644 --- a/vendor/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go +++ b/vendor/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/scale/util.go b/vendor/k8s.io/client-go/scale/util.go index 46b5c4d1e..1c04b4551 100644 --- a/vendor/k8s.io/client-go/scale/util.go +++ b/vendor/k8s.io/client-go/scale/util.go @@ -21,6 +21,7 @@ import ( "strings" "sync" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" @@ -34,6 +35,15 @@ import ( scaleext "k8s.io/client-go/scale/scheme/extensionsv1beta1" ) +// PreferredResourceMapper determines the preferred version of a resource to scale +type PreferredResourceMapper interface { + // ResourceFor takes a partial resource and returns the preferred resource. + ResourceFor(resource schema.GroupVersionResource) (preferredResource schema.GroupVersionResource, err error) +} + +// Ensure a RESTMapper satisfies the PreferredResourceMapper interface +var _ PreferredResourceMapper = meta.RESTMapper(nil) + // ScaleKindResolver knows about the relationship between // resources and the GroupVersionKind of their scale subresources. type ScaleKindResolver interface { diff --git a/vendor/k8s.io/client-go/testing/BUILD b/vendor/k8s.io/client-go/testing/BUILD deleted file mode 100644 index dd8d13397..000000000 --- a/vendor/k8s.io/client-go/testing/BUILD +++ /dev/null @@ -1,60 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "actions.go", - "fake.go", - "fixture.go", - ], - importpath = "k8s.io/client-go/testing", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "fixture_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/testing/actions.go b/vendor/k8s.io/client-go/testing/actions.go index 6f1c3a896..b99f231c8 100644 --- a/vendor/k8s.io/client-go/testing/actions.go +++ b/vendor/k8s.io/client-go/testing/actions.go @@ -58,37 +58,33 @@ func NewGetSubresourceAction(resource schema.GroupVersionResource, namespace, su return action } -func NewRootListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, opts interface{}) ListActionImpl { - action := ListActionImpl{} - action.Verb = "list" +func NewRootGetSubresourceAction(resource schema.GroupVersionResource, subresource, name string) GetActionImpl { + action := GetActionImpl{} + action.Verb = "get" action.Resource = resource - action.Kind = kind - labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) - action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} + action.Subresource = subresource + action.Name = name return action } -func NewListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, namespace string, opts interface{}) ListActionImpl { +func NewRootListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, opts interface{}) ListActionImpl { action := ListActionImpl{} action.Verb = "list" action.Resource = resource action.Kind = kind - action.Namespace = namespace labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} return action } -func NewListSubresourceAction(resource schema.GroupVersionResource, name, subresource string, kind schema.GroupVersionKind, namespace string, opts interface{}) ListActionImpl { +func NewListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, namespace string, opts interface{}) ListActionImpl { action := ListActionImpl{} action.Verb = "list" action.Resource = resource - action.Subresource = subresource action.Kind = kind action.Namespace = namespace - action.Name = name labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} @@ -114,12 +110,23 @@ func NewCreateAction(resource schema.GroupVersionResource, namespace string, obj return action } -func NewCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource string, namespace string, object runtime.Object) CreateActionImpl { +func NewRootCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource string, object runtime.Object) CreateActionImpl { action := CreateActionImpl{} action.Verb = "create" action.Resource = resource action.Subresource = subresource + action.Name = name + action.Object = object + + return action +} + +func NewCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource, namespace string, object runtime.Object) CreateActionImpl { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = resource action.Namespace = namespace + action.Subresource = subresource action.Name = name action.Object = object @@ -218,6 +225,16 @@ func NewRootDeleteAction(resource schema.GroupVersionResource, name string) Dele return action } +func NewRootDeleteSubresourceAction(resource schema.GroupVersionResource, subresource string, name string) DeleteActionImpl { + action := DeleteActionImpl{} + action.Verb = "delete" + action.Resource = resource + action.Subresource = subresource + action.Name = name + + return action +} + func NewDeleteAction(resource schema.GroupVersionResource, namespace, name string) DeleteActionImpl { action := DeleteActionImpl{} action.Verb = "delete" @@ -228,6 +245,17 @@ func NewDeleteAction(resource schema.GroupVersionResource, namespace, name strin return action } +func NewDeleteSubresourceAction(resource schema.GroupVersionResource, subresource, namespace, name string) DeleteActionImpl { + action := DeleteActionImpl{} + action.Verb = "delete" + action.Resource = resource + action.Subresource = subresource + action.Namespace = namespace + action.Name = name + + return action +} + func NewRootDeleteCollectionAction(resource schema.GroupVersionResource, opts interface{}) DeleteCollectionActionImpl { action := DeleteCollectionActionImpl{} action.Verb = "delete-collection" @@ -324,6 +352,10 @@ type Action interface { GetResource() schema.GroupVersionResource GetSubresource() string Matches(verb, resource string) bool + + // DeepCopy is used to copy an action to avoid any risk of accidental mutation. Most people never need to call this + // because the invocation logic deep copies before calls to storage and reactors. + DeepCopy() Action } type GenericAction interface { @@ -404,6 +436,10 @@ func (a ActionImpl) Matches(verb, resource string) bool { return strings.ToLower(verb) == strings.ToLower(a.Verb) && strings.ToLower(resource) == strings.ToLower(a.Resource.Resource) } +func (a ActionImpl) DeepCopy() Action { + ret := a + return ret +} type GenericActionImpl struct { ActionImpl @@ -414,6 +450,14 @@ func (a GenericActionImpl) GetValue() interface{} { return a.Value } +func (a GenericActionImpl) DeepCopy() Action { + return GenericActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + // TODO this is wrong, but no worse than before + Value: a.Value, + } +} + type GetActionImpl struct { ActionImpl Name string @@ -423,6 +467,13 @@ func (a GetActionImpl) GetName() string { return a.Name } +func (a GetActionImpl) DeepCopy() Action { + return GetActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Name: a.Name, + } +} + type ListActionImpl struct { ActionImpl Kind schema.GroupVersionKind @@ -438,6 +489,18 @@ func (a ListActionImpl) GetListRestrictions() ListRestrictions { return a.ListRestrictions } +func (a ListActionImpl) DeepCopy() Action { + return ListActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Kind: a.Kind, + Name: a.Name, + ListRestrictions: ListRestrictions{ + Labels: a.ListRestrictions.Labels.DeepCopySelector(), + Fields: a.ListRestrictions.Fields.DeepCopySelector(), + }, + } +} + type CreateActionImpl struct { ActionImpl Name string @@ -448,6 +511,14 @@ func (a CreateActionImpl) GetObject() runtime.Object { return a.Object } +func (a CreateActionImpl) DeepCopy() Action { + return CreateActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Name: a.Name, + Object: a.Object.DeepCopyObject(), + } +} + type UpdateActionImpl struct { ActionImpl Object runtime.Object @@ -457,6 +528,13 @@ func (a UpdateActionImpl) GetObject() runtime.Object { return a.Object } +func (a UpdateActionImpl) DeepCopy() Action { + return UpdateActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Object: a.Object.DeepCopyObject(), + } +} + type PatchActionImpl struct { ActionImpl Name string @@ -471,6 +549,16 @@ func (a PatchActionImpl) GetPatch() []byte { return a.Patch } +func (a PatchActionImpl) DeepCopy() Action { + patch := make([]byte, len(a.Patch)) + copy(patch, a.Patch) + return PatchActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Name: a.Name, + Patch: patch, + } +} + type DeleteActionImpl struct { ActionImpl Name string @@ -480,6 +568,13 @@ func (a DeleteActionImpl) GetName() string { return a.Name } +func (a DeleteActionImpl) DeepCopy() Action { + return DeleteActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Name: a.Name, + } +} + type DeleteCollectionActionImpl struct { ActionImpl ListRestrictions ListRestrictions @@ -489,6 +584,16 @@ func (a DeleteCollectionActionImpl) GetListRestrictions() ListRestrictions { return a.ListRestrictions } +func (a DeleteCollectionActionImpl) DeepCopy() Action { + return DeleteCollectionActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + ListRestrictions: ListRestrictions{ + Labels: a.ListRestrictions.Labels.DeepCopySelector(), + Fields: a.ListRestrictions.Fields.DeepCopySelector(), + }, + } +} + type WatchActionImpl struct { ActionImpl WatchRestrictions WatchRestrictions @@ -498,6 +603,17 @@ func (a WatchActionImpl) GetWatchRestrictions() WatchRestrictions { return a.WatchRestrictions } +func (a WatchActionImpl) DeepCopy() Action { + return WatchActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + WatchRestrictions: WatchRestrictions{ + Labels: a.WatchRestrictions.Labels.DeepCopySelector(), + Fields: a.WatchRestrictions.Fields.DeepCopySelector(), + ResourceVersion: a.WatchRestrictions.ResourceVersion, + }, + } +} + type ProxyGetActionImpl struct { ActionImpl Scheme string @@ -526,3 +642,18 @@ func (a ProxyGetActionImpl) GetPath() string { func (a ProxyGetActionImpl) GetParams() map[string]string { return a.Params } + +func (a ProxyGetActionImpl) DeepCopy() Action { + params := map[string]string{} + for k, v := range a.Params { + params[k] = v + } + return ProxyGetActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Scheme: a.Scheme, + Name: a.Name, + Port: a.Port, + Path: a.Path, + Params: params, + } +} diff --git a/vendor/k8s.io/client-go/testing/fake.go b/vendor/k8s.io/client-go/testing/fake.go index da47b23b9..8b3f31eaf 100644 --- a/vendor/k8s.io/client-go/testing/fake.go +++ b/vendor/k8s.io/client-go/testing/fake.go @@ -22,10 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/version" "k8s.io/apimachinery/pkg/watch" - kubeversion "k8s.io/client-go/pkg/version" restclient "k8s.io/client-go/rest" ) @@ -134,13 +131,13 @@ func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime. c.Lock() defer c.Unlock() - c.actions = append(c.actions, action) + c.actions = append(c.actions, action.DeepCopy()) for _, reactor := range c.ReactionChain { if !reactor.Handles(action) { continue } - handled, ret, err := reactor.React(action) + handled, ret, err := reactor.React(action.DeepCopy()) if !handled { continue } @@ -157,13 +154,13 @@ func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) { c.Lock() defer c.Unlock() - c.actions = append(c.actions, action) + c.actions = append(c.actions, action.DeepCopy()) for _, reactor := range c.WatchReactionChain { if !reactor.Handles(action) { continue } - handled, ret, err := reactor.React(action) + handled, ret, err := reactor.React(action.DeepCopy()) if !handled { continue } @@ -180,13 +177,13 @@ func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper { c.Lock() defer c.Unlock() - c.actions = append(c.actions, action) + c.actions = append(c.actions, action.DeepCopy()) for _, reactor := range c.ProxyReactionChain { if !reactor.Handles(action) { continue } - handled, ret, err := reactor.React(action) + handled, ret, err := reactor.React(action.DeepCopy()) if !handled || err != nil { continue } @@ -214,46 +211,3 @@ func (c *Fake) Actions() []Action { copy(fa, c.actions) return fa } - -// TODO: this probably should be moved to somewhere else. -type FakeDiscovery struct { - *Fake -} - -func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - action := ActionImpl{ - Verb: "get", - Resource: schema.GroupVersionResource{Resource: "resource"}, - } - c.Invokes(action, nil) - for _, rl := range c.Resources { - if rl.GroupVersion == groupVersion { - return rl, nil - } - } - - return nil, fmt.Errorf("GroupVersion %q not found", groupVersion) -} - -func (c *FakeDiscovery) ServerResources() ([]*metav1.APIResourceList, error) { - action := ActionImpl{ - Verb: "get", - Resource: schema.GroupVersionResource{Resource: "resource"}, - } - c.Invokes(action, nil) - return c.Resources, nil -} - -func (c *FakeDiscovery) ServerGroups() (*metav1.APIGroupList, error) { - return nil, nil -} - -func (c *FakeDiscovery) ServerVersion() (*version.Info, error) { - action := ActionImpl{} - action.Verb = "get" - action.Resource = schema.GroupVersionResource{Resource: "version"} - - c.Invokes(action, nil) - versionInfo := kubeversion.Get() - return &versionInfo, nil -} diff --git a/vendor/k8s.io/client-go/testing/fixture.go b/vendor/k8s.io/client-go/testing/fixture.go index ba8ee508f..00c4c49fc 100644 --- a/vendor/k8s.io/client-go/testing/fixture.go +++ b/vendor/k8s.io/client-go/testing/fixture.go @@ -25,15 +25,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/json" + "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/watch" restclient "k8s.io/client-go/rest" ) -// FakeWatchBufferSize is the max num of watch event can be buffered in the -// watch channel. Note that when watch event overflows or exceed this buffer -// size, manipulations via fake client may be blocked. -const FakeWatchBufferSize = 128 - // ObjectTracker keeps track of objects. It is intended to be used to // fake calls to a server by returning objects based on their kind, // namespace and name. @@ -77,7 +74,6 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc { return func(action Action) (bool, runtime.Object, error) { ns := action.GetNamespace() gvr := action.GetResource() - // Here and below we need to switch on implementation types, // not on interfaces, as some interfaces are identical // (e.g. UpdateAction and CreateAction), so if we use them, @@ -130,6 +126,34 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc { } return true, nil, nil + case PatchActionImpl: + obj, err := tracker.Get(gvr, ns, action.GetName()) + if err != nil { + // object is not registered + return false, nil, err + } + + old, err := json.Marshal(obj) + if err != nil { + return true, nil, err + } + // Only supports strategic merge patch + // TODO: Add support for other Patch types + mergedByte, err := strategicpatch.StrategicMergePatch(old, action.GetPatch(), obj) + if err != nil { + return true, nil, err + } + + if err = json.Unmarshal(mergedByte, obj); err != nil { + return true, nil, err + } + + if err = tracker.Update(gvr, obj, ns); err != nil { + return true, nil, err + } + + return true, obj, nil + default: return false, nil, fmt.Errorf("no reaction implemented for %s", action) } @@ -142,12 +166,11 @@ type tracker struct { lock sync.RWMutex objects map[schema.GroupVersionResource][]runtime.Object // The value type of watchers is a map of which the key is either a namespace or - // all/non namespace aka "" and its value is list of fake watchers. Each of - // fake watcher holds a buffered channel of size "FakeWatchBufferSize" which - // is default to 128. Manipulations on resources will broadcast the notification - // events into the watchers' channel and note that too many unhandled event may - // potentially block the tracker. - watchers map[schema.GroupVersionResource]map[string][]*watch.FakeWatcher + // all/non namespace aka "" and its value is list of fake watchers. + // Manipulations on resources will broadcast the notification events into the + // watchers' channel. Note that too many unhandled events (currently 100, + // see apimachinery/pkg/watch.DefaultChanSize) will cause a panic. + watchers map[schema.GroupVersionResource]map[string][]*watch.RaceFreeFakeWatcher } var _ ObjectTracker = &tracker{} @@ -159,7 +182,7 @@ func NewObjectTracker(scheme ObjectScheme, decoder runtime.Decoder) ObjectTracke scheme: scheme, decoder: decoder, objects: make(map[schema.GroupVersionResource][]runtime.Object), - watchers: make(map[schema.GroupVersionResource]map[string][]*watch.FakeWatcher), + watchers: make(map[schema.GroupVersionResource]map[string][]*watch.RaceFreeFakeWatcher), } } @@ -206,10 +229,10 @@ func (t *tracker) Watch(gvr schema.GroupVersionResource, ns string) (watch.Inter t.lock.Lock() defer t.lock.Unlock() - fakewatcher := watch.NewFakeWithChanSize(FakeWatchBufferSize, true) + fakewatcher := watch.NewRaceFreeFake() if _, exists := t.watchers[gvr]; !exists { - t.watchers[gvr] = make(map[string][]*watch.FakeWatcher) + t.watchers[gvr] = make(map[string][]*watch.RaceFreeFakeWatcher) } t.watchers[gvr][ns] = append(t.watchers[gvr][ns], fakewatcher) return fakewatcher, nil @@ -293,8 +316,8 @@ func (t *tracker) Update(gvr schema.GroupVersionResource, obj runtime.Object, ns return t.add(gvr, obj, ns, true) } -func (t *tracker) getWatches(gvr schema.GroupVersionResource, ns string) []*watch.FakeWatcher { - watches := []*watch.FakeWatcher{} +func (t *tracker) getWatches(gvr schema.GroupVersionResource, ns string) []*watch.RaceFreeFakeWatcher { + watches := []*watch.RaceFreeFakeWatcher{} if t.watchers[gvr] != nil { if w := t.watchers[gvr][ns]; w != nil { watches = append(watches, w...) diff --git a/vendor/k8s.io/client-go/testing/fixture_test.go b/vendor/k8s.io/client-go/testing/fixture_test.go index 967e0aefa..405fe1a7e 100644 --- a/vendor/k8s.io/client-go/testing/fixture_test.go +++ b/vendor/k8s.io/client-go/testing/fixture_test.go @@ -63,6 +63,9 @@ func TestWatchCallNonNamespace(t *testing.T) { codecs := serializer.NewCodecFactory(scheme) o := NewObjectTracker(scheme, codecs.UniversalDecoder()) watch, err := o.Watch(testResource, ns) + if err != nil { + t.Fatalf("test resource watch failed in %s: %v ", ns, err) + } go func() { err := o.Create(testResource, testObj, ns) if err != nil { @@ -85,7 +88,13 @@ func TestWatchCallAllNamespace(t *testing.T) { codecs := serializer.NewCodecFactory(scheme) o := NewObjectTracker(scheme, codecs.UniversalDecoder()) w, err := o.Watch(testResource, "test_namespace") + if err != nil { + t.Fatalf("test resource watch failed in test_namespace: %v", err) + } wAll, err := o.Watch(testResource, "") + if err != nil { + t.Fatalf("test resource watch failed in all namespaces: %v", err) + } go func() { err := o.Create(testResource, testObj, ns) assert.NoError(t, err, "test resource creation failed") @@ -161,6 +170,9 @@ func TestWatchCallMultipleInvocation(t *testing.T) { for idx, watchNamespace := range watchNamespaces { i := idx w, err := o.Watch(testResource, watchNamespace) + if err != nil { + t.Fatalf("test resource watch failed in %s: %v", watchNamespace, err) + } go func() { assert.NoError(t, err, "watch invocation failed") for _, c := range cases { @@ -190,3 +202,34 @@ func TestWatchCallMultipleInvocation(t *testing.T) { } wg.Wait() } + +func TestWatchAddAfterStop(t *testing.T) { + testResource := schema.GroupVersionResource{Group: "", Version: "test_version", Resource: "test_kind"} + testObj := getArbitraryResource(testResource, "test_name", "test_namespace") + accessor, err := meta.Accessor(testObj) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + ns := accessor.GetNamespace() + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + o := NewObjectTracker(scheme, codecs.UniversalDecoder()) + watch, err := o.Watch(testResource, ns) + if err != nil { + t.Errorf("watch creation failed: %v", err) + } + + // When the watch is stopped it should ignore later events without panicking. + defer func() { + if r := recover(); r != nil { + t.Errorf("Watch panicked when it should have ignored create after stop: %v", r) + } + }() + + watch.Stop() + err = o.Create(testResource, testObj, ns) + if err != nil { + t.Errorf("test resource creation failed: %v", err) + } +} diff --git a/vendor/k8s.io/client-go/third_party/forked/golang/template/BUILD b/vendor/k8s.io/client-go/third_party/forked/golang/template/BUILD deleted file mode 100644 index cebdf7b63..000000000 --- a/vendor/k8s.io/client-go/third_party/forked/golang/template/BUILD +++ /dev/null @@ -1,28 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "exec.go", - "funcs.go", - ], - importpath = "k8s.io/client-go/third_party/forked/golang/template", -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/auth/BUILD b/vendor/k8s.io/client-go/tools/auth/BUILD deleted file mode 100644 index 5c7718a77..000000000 --- a/vendor/k8s.io/client-go/tools/auth/BUILD +++ /dev/null @@ -1,33 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["clientauth.go"], - importpath = "k8s.io/client-go/tools/auth", - deps = ["//vendor/k8s.io/client-go/rest:go_default_library"], -) - -go_test( - name = "go_default_xtest", - srcs = ["clientauth_test.go"], - deps = ["//vendor/k8s.io/client-go/tools/auth:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/bootstrap/token/api/OWNERS b/vendor/k8s.io/client-go/tools/bootstrap/token/OWNERS similarity index 100% rename from vendor/k8s.io/client-go/tools/bootstrap/token/api/OWNERS rename to vendor/k8s.io/client-go/tools/bootstrap/token/OWNERS diff --git a/vendor/k8s.io/client-go/tools/bootstrap/token/api/BUILD b/vendor/k8s.io/client-go/tools/bootstrap/token/api/BUILD deleted file mode 100644 index 7416adc01..000000000 --- a/vendor/k8s.io/client-go/tools/bootstrap/token/api/BUILD +++ /dev/null @@ -1,26 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "types.go", - ], - importpath = "k8s.io/client-go/tools/bootstrap/token/api", - visibility = ["//visibility:public"], - deps = ["//vendor/k8s.io/api/core/v1:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/tools/bootstrap/token/api/doc.go b/vendor/k8s.io/client-go/tools/bootstrap/token/api/doc.go index b9910c35a..249e0a059 100644 --- a/vendor/k8s.io/client-go/tools/bootstrap/token/api/doc.go +++ b/vendor/k8s.io/client-go/tools/bootstrap/token/api/doc.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package api (pkg/bootstrap/token/api) contains constants and types needed for +// Package api (k8s.io/client-go/tools/bootstrap/token/api) contains constants and types needed for // bootstrap tokens as maintained by the BootstrapSigner and TokenCleaner -// controllers (in pkg/controller/bootstrap) +// controllers (in k8s.io/kubernetes/pkg/controller/bootstrap) package api // import "k8s.io/client-go/tools/bootstrap/token/api" diff --git a/vendor/k8s.io/client-go/tools/bootstrap/token/api/types.go b/vendor/k8s.io/client-go/tools/bootstrap/token/api/types.go index c30814c0e..3bea78b17 100644 --- a/vendor/k8s.io/client-go/tools/bootstrap/token/api/types.go +++ b/vendor/k8s.io/client-go/tools/bootstrap/token/api/types.go @@ -86,14 +86,26 @@ const ( // authenticate as. The full username given is "system:bootstrap:". BootstrapUserPrefix = "system:bootstrap:" - // BootstrapGroupPattern is the valid regex pattern that all groups - // assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match. - // See also ValidateBootstrapGroupName(). - BootstrapGroupPattern = "system:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]" - // BootstrapDefaultGroup is the default group for bootstrapping bearer // tokens (in addition to any groups from BootstrapTokenExtraGroupsKey). BootstrapDefaultGroup = "system:bootstrappers" + + // BootstrapGroupPattern is the valid regex pattern that all groups + // assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match. + // See also util.ValidateBootstrapGroupName() + BootstrapGroupPattern = `\Asystem:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]\z` + + // BootstrapTokenPattern defines the {id}.{secret} regular expression pattern + BootstrapTokenPattern = `\A([a-z0-9]{6})\.([a-z0-9]{16})\z` + + // BootstrapTokenIDPattern defines token's id regular expression pattern + BootstrapTokenIDPattern = `\A([a-z0-9]{6})\z` + + // BootstrapTokenIDBytes defines the number of bytes used for the Bootstrap Token's ID field + BootstrapTokenIDBytes = 6 + + // BootstrapTokenSecretBytes defines the number of bytes used the Bootstrap Token's Secret field + BootstrapTokenSecretBytes = 16 ) // KnownTokenUsages specifies the known functions a token will get. diff --git a/vendor/k8s.io/client-go/tools/bootstrap/token/util/BUILD b/vendor/k8s.io/client-go/tools/bootstrap/token/util/BUILD deleted file mode 100644 index 1d4d10e99..000000000 --- a/vendor/k8s.io/client-go/tools/bootstrap/token/util/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["helpers.go"], - importpath = "k8s.io/client-go/tools/bootstrap/token/util", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["helpers_test.go"], - embed = [":go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/tools/bootstrap/token/util/helpers.go b/vendor/k8s.io/client-go/tools/bootstrap/token/util/helpers.go index d28fd28f2..bb1fbeb65 100644 --- a/vendor/k8s.io/client-go/tools/bootstrap/token/util/helpers.go +++ b/vendor/k8s.io/client-go/tools/bootstrap/token/util/helpers.go @@ -17,20 +17,101 @@ limitations under the License. package util import ( + "bufio" + "crypto/rand" "fmt" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/client-go/tools/bootstrap/token/api" "regexp" "strings" + + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/tools/bootstrap/token/api" +) + +// validBootstrapTokenChars defines the characters a bootstrap token can consist of +const validBootstrapTokenChars = "0123456789abcdefghijklmnopqrstuvwxyz" + +var ( + // BootstrapTokenRegexp is a compiled regular expression of TokenRegexpString + BootstrapTokenRegexp = regexp.MustCompile(api.BootstrapTokenPattern) + // BootstrapTokenIDRegexp is a compiled regular expression of TokenIDRegexpString + BootstrapTokenIDRegexp = regexp.MustCompile(api.BootstrapTokenIDPattern) + // BootstrapGroupRegexp is a compiled regular expression of BootstrapGroupPattern + BootstrapGroupRegexp = regexp.MustCompile(api.BootstrapGroupPattern) ) -var bootstrapGroupRegexp = regexp.MustCompile(`\A` + api.BootstrapGroupPattern + `\z`) +// GenerateBootstrapToken generates a new, random Bootstrap Token. +func GenerateBootstrapToken() (string, error) { + tokenID, err := randBytes(api.BootstrapTokenIDBytes) + if err != nil { + return "", err + } + + tokenSecret, err := randBytes(api.BootstrapTokenSecretBytes) + if err != nil { + return "", err + } + + return TokenFromIDAndSecret(tokenID, tokenSecret), nil +} + +// randBytes returns a random string consisting of the characters in +// validBootstrapTokenChars, with the length customized by the parameter +func randBytes(length int) (string, error) { + // len("0123456789abcdefghijklmnopqrstuvwxyz") = 36 which doesn't evenly divide + // the possible values of a byte: 256 mod 36 = 4. Discard any random bytes we + // read that are >= 252 so the bytes we evenly divide the character set. + const maxByteValue = 252 + + var ( + b byte + err error + token = make([]byte, length) + ) + + reader := bufio.NewReaderSize(rand.Reader, length*2) + for i := range token { + for { + if b, err = reader.ReadByte(); err != nil { + return "", err + } + if b < maxByteValue { + break + } + } + + token[i] = validBootstrapTokenChars[int(b)%len(validBootstrapTokenChars)] + } + + return string(token), nil +} + +// TokenFromIDAndSecret returns the full token which is of the form "{id}.{secret}" +func TokenFromIDAndSecret(id, secret string) string { + return fmt.Sprintf("%s.%s", id, secret) +} + +// IsValidBootstrapToken returns whether the given string is valid as a Bootstrap Token and +// in other words satisfies the BootstrapTokenRegexp +func IsValidBootstrapToken(token string) bool { + return BootstrapTokenRegexp.MatchString(token) +} + +// IsValidBootstrapTokenID returns whether the given string is valid as a Bootstrap Token ID and +// in other words satisfies the BootstrapTokenIDRegexp +func IsValidBootstrapTokenID(tokenID string) bool { + return BootstrapTokenIDRegexp.MatchString(tokenID) +} + +// BootstrapTokenSecretName returns the expected name for the Secret storing the +// Bootstrap Token in the Kubernetes API. +func BootstrapTokenSecretName(tokenID string) string { + return fmt.Sprintf("%s%s", api.BootstrapTokenSecretPrefix, tokenID) +} // ValidateBootstrapGroupName checks if the provided group name is a valid // bootstrap group name. Returns nil if valid or a validation error if invalid. -// TODO(mattmoyer): this validation should migrate out to client-go (see https://github.com/kubernetes/client-go/issues/114) func ValidateBootstrapGroupName(name string) error { - if bootstrapGroupRegexp.Match([]byte(name)) { + if BootstrapGroupRegexp.Match([]byte(name)) { return nil } return fmt.Errorf("bootstrap group %q is invalid (must match %s)", name, api.BootstrapGroupPattern) @@ -46,7 +127,7 @@ func ValidateUsages(usages []string) error { } } if len(invalidUsages) > 0 { - return fmt.Errorf("invalide bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ",")) + return fmt.Errorf("invalid bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ",")) } return nil } diff --git a/vendor/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go b/vendor/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go index 915bf7540..a1fe6092f 100644 --- a/vendor/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go +++ b/vendor/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go @@ -21,6 +21,143 @@ import ( "testing" ) +func TestGenerateBootstrapToken(t *testing.T) { + token, err := GenerateBootstrapToken() + if err != nil { + t.Fatalf("GenerateBootstrapToken returned an unexpected error: %+v", err) + } + if !IsValidBootstrapToken(token) { + t.Errorf("GenerateBootstrapToken didn't generate a valid token: %q", token) + } +} + +func TestRandBytes(t *testing.T) { + var randTest = []int{ + 0, + 1, + 2, + 3, + 100, + } + + for _, rt := range randTest { + actual, err := randBytes(rt) + if err != nil { + t.Errorf("failed randBytes: %v", err) + } + if len(actual) != rt { + t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt, len(actual)) + } + } +} + +func TestTokenFromIDAndSecret(t *testing.T) { + var tests = []struct { + id string + secret string + expected string + }{ + {"foo", "bar", "foo.bar"}, // should use default + {"abcdef", "abcdef0123456789", "abcdef.abcdef0123456789"}, + {"h", "b", "h.b"}, + } + for _, rt := range tests { + actual := TokenFromIDAndSecret(rt.id, rt.secret) + if actual != rt.expected { + t.Errorf( + "failed TokenFromIDAndSecret:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + +func TestIsValidBootstrapToken(t *testing.T) { + var tests = []struct { + token string + expected bool + }{ + {token: "", expected: false}, + {token: ".", expected: false}, + {token: "1234567890123456789012", expected: false}, // invalid parcel size + {token: "12345.1234567890123456", expected: false}, // invalid parcel size + {token: ".1234567890123456", expected: false}, // invalid parcel size + {token: "123456.", expected: false}, // invalid parcel size + {token: "123456:1234567890.123456", expected: false}, // invalid separation + {token: "abcdef:1234567890123456", expected: false}, // invalid separation + {token: "Abcdef.1234567890123456", expected: false}, // invalid token id + {token: "123456.AABBCCDDEEFFGGHH", expected: false}, // invalid token secret + {token: "123456.AABBCCD-EEFFGGHH", expected: false}, // invalid character + {token: "abc*ef.1234567890123456", expected: false}, // invalid character + {token: "abcdef.1234567890123456", expected: true}, + {token: "123456.aabbccddeeffgghh", expected: true}, + {token: "ABCDEF.abcdef0123456789", expected: false}, + {token: "abcdef.abcdef0123456789", expected: true}, + {token: "123456.1234560123456789", expected: true}, + } + for _, rt := range tests { + actual := IsValidBootstrapToken(rt.token) + if actual != rt.expected { + t.Errorf( + "failed IsValidBootstrapToken for the token %q\n\texpected: %t\n\t actual: %t", + rt.token, + rt.expected, + actual, + ) + } + } +} + +func TestIsValidBootstrapTokenID(t *testing.T) { + var tests = []struct { + tokenID string + expected bool + }{ + {tokenID: "", expected: false}, + {tokenID: "1234567890123456789012", expected: false}, + {tokenID: "12345", expected: false}, + {tokenID: "Abcdef", expected: false}, + {tokenID: "ABCDEF", expected: false}, + {tokenID: "abcdef.", expected: false}, + {tokenID: "abcdef", expected: true}, + {tokenID: "123456", expected: true}, + } + for _, rt := range tests { + actual := IsValidBootstrapTokenID(rt.tokenID) + if actual != rt.expected { + t.Errorf( + "failed IsValidBootstrapTokenID for the token %q\n\texpected: %t\n\t actual: %t", + rt.tokenID, + rt.expected, + actual, + ) + } + } +} + +func TestBootstrapTokenSecretName(t *testing.T) { + var tests = []struct { + tokenID string + expected string + }{ + {"foo", "bootstrap-token-foo"}, + {"bar", "bootstrap-token-bar"}, + {"", "bootstrap-token-"}, + {"abcdef", "bootstrap-token-abcdef"}, + } + for _, rt := range tests { + actual := BootstrapTokenSecretName(rt.tokenID) + if actual != rt.expected { + t.Errorf( + "failed BootstrapTokenSecretName:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + func TestValidateBootstrapGroupName(t *testing.T) { tests := []struct { name string diff --git a/vendor/k8s.io/client-go/tools/cache/BUILD b/vendor/k8s.io/client-go/tools/cache/BUILD deleted file mode 100644 index 524354e87..000000000 --- a/vendor/k8s.io/client-go/tools/cache/BUILD +++ /dev/null @@ -1,103 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "controller_test.go", - "delta_fifo_test.go", - "expiration_cache_test.go", - "fifo_test.go", - "heap_test.go", - "index_test.go", - "mutation_detector_test.go", - "processor_listener_test.go", - "reflector_test.go", - "shared_informer_test.go", - "store_test.go", - "undelta_store_test.go", - ], - embed = [":go_default_library"], - race = "off", - deps = [ - "//vendor/github.com/google/gofuzz:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/tools/cache/testing:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = [ - "controller.go", - "delta_fifo.go", - "doc.go", - "expiration_cache.go", - "expiration_cache_fakes.go", - "fake_custom_store.go", - "fifo.go", - "heap.go", - "index.go", - "listers.go", - "listwatch.go", - "mutation_cache.go", - "mutation_detector.go", - "reflector.go", - "reflector_metrics.go", - "shared_informer.go", - "store.go", - "thread_safe_store.go", - "undelta_store.go", - ], - importpath = "k8s.io/client-go/tools/cache", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/cache:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/pager:go_default_library", - "//vendor/k8s.io/client-go/util/buffer:go_default_library", - "//vendor/k8s.io/client-go/util/retry:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/tools/cache/testing:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/cache/listwatch.go b/vendor/k8s.io/client-go/tools/cache/listwatch.go index 06657a3b0..8bf41f517 100644 --- a/vendor/k8s.io/client-go/tools/cache/listwatch.go +++ b/vendor/k8s.io/client-go/tools/cache/listwatch.go @@ -17,10 +17,9 @@ limitations under the License. package cache import ( + "context" "time" - "golang.org/x/net/context" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" diff --git a/vendor/k8s.io/client-go/tools/cache/mutation_detector.go b/vendor/k8s.io/client-go/tools/cache/mutation_detector.go index 8e6338a1b..e2aa44848 100644 --- a/vendor/k8s.io/client-go/tools/cache/mutation_detector.go +++ b/vendor/k8s.io/client-go/tools/cache/mutation_detector.go @@ -24,6 +24,8 @@ import ( "sync" "time" + "github.com/golang/glog" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/diff" ) @@ -43,6 +45,7 @@ func NewCacheMutationDetector(name string) CacheMutationDetector { if !mutationDetectionEnabled { return dummyMutationDetector{} } + glog.Warningln("Mutation detector is enabled, this will result in memory leakage.") return &defaultCacheMutationDetector{name: name, period: 1 * time.Second} } diff --git a/vendor/k8s.io/client-go/tools/cache/testing/BUILD b/vendor/k8s.io/client-go/tools/cache/testing/BUILD deleted file mode 100644 index d1658af4d..000000000 --- a/vendor/k8s.io/client-go/tools/cache/testing/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["fake_controller_source_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = ["fake_controller_source.go"], - importpath = "k8s.io/client-go/tools/cache/testing", - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/clientcmd/BUILD b/vendor/k8s.io/client-go/tools/clientcmd/BUILD deleted file mode 100644 index c46c76d5d..000000000 --- a/vendor/k8s.io/client-go/tools/clientcmd/BUILD +++ /dev/null @@ -1,78 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "client_config_test.go", - "loader_test.go", - "merged_client_builder_test.go", - "overrides_test.go", - "validation_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/github.com/ghodss/yaml:go_default_library", - "//vendor/github.com/imdario/mergo:go_default_library", - "//vendor/github.com/spf13/pflag:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api/latest:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = [ - "auth_loaders.go", - "client_config.go", - "config.go", - "doc.go", - "flag.go", - "helpers.go", - "loader.go", - "merged_client_builder.go", - "overrides.go", - "validation.go", - ], - importpath = "k8s.io/client-go/tools/clientcmd", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/howeyc/gopass:go_default_library", - "//vendor/github.com/imdario/mergo:go_default_library", - "//vendor/github.com/spf13/pflag:go_default_library", - "//vendor/k8s.io/api/core/v1: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/util/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/auth:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api/latest:go_default_library", - "//vendor/k8s.io/client-go/util/homedir:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/tools/clientcmd/api:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/clientcmd/api/BUILD b/vendor/k8s.io/client-go/tools/clientcmd/api/BUILD deleted file mode 100644 index b2fd13824..000000000 --- a/vendor/k8s.io/client-go/tools/clientcmd/api/BUILD +++ /dev/null @@ -1,50 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "helpers_test.go", - "types_test.go", - ], - embed = [":go_default_library"], - deps = ["//vendor/github.com/ghodss/yaml:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "helpers.go", - "register.go", - "types.go", - "zz_generated.deepcopy.go", - ], - importpath = "k8s.io/client-go/tools/clientcmd/api", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/tools/clientcmd/api/latest:all-srcs", - "//staging/src/k8s.io/client-go/tools/clientcmd/api/v1:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/clientcmd/api/latest/BUILD b/vendor/k8s.io/client-go/tools/clientcmd/api/latest/BUILD deleted file mode 100644 index 308319e22..000000000 --- a/vendor/k8s.io/client-go/tools/clientcmd/api/latest/BUILD +++ /dev/null @@ -1,33 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["latest.go"], - importpath = "k8s.io/client-go/tools/clientcmd/api/latest", - deps = [ - "//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/json:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api/v1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/clientcmd/api/v1/BUILD b/vendor/k8s.io/client-go/tools/clientcmd/api/v1/BUILD deleted file mode 100644 index 2b9daaf08..000000000 --- a/vendor/k8s.io/client-go/tools/clientcmd/api/v1/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "conversion.go", - "doc.go", - "register.go", - "types.go", - "zz_generated.deepcopy.go", - ], - importpath = "k8s.io/client-go/tools/clientcmd/api/v1", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/conversion: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/client-go/tools/clientcmd/api:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/clientcmd/api/v1/conversion.go b/vendor/k8s.io/client-go/tools/clientcmd/api/v1/conversion.go index b47bfbca2..2d7142e6e 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/api/v1/conversion.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/api/v1/conversion.go @@ -17,6 +17,7 @@ limitations under the License. package v1 import ( + "fmt" "sort" "k8s.io/apimachinery/pkg/conversion" @@ -105,7 +106,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error { if err := s.Convert(&curr.Cluster, newCluster, 0); err != nil { return err } - (*out)[curr.Name] = newCluster + if (*out)[curr.Name] == nil { + (*out)[curr.Name] = newCluster + } else { + return fmt.Errorf("error converting *[]NamedCluster into *map[string]*api.Cluster: duplicate name \"%v\" in list: %v", curr.Name, *in) + } } return nil @@ -136,7 +141,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error { if err := s.Convert(&curr.AuthInfo, newAuthInfo, 0); err != nil { return err } - (*out)[curr.Name] = newAuthInfo + if (*out)[curr.Name] == nil { + (*out)[curr.Name] = newAuthInfo + } else { + return fmt.Errorf("error converting *[]NamedAuthInfo into *map[string]*api.AuthInfo: duplicate name \"%v\" in list: %v", curr.Name, *in) + } } return nil @@ -167,7 +176,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error { if err := s.Convert(&curr.Context, newContext, 0); err != nil { return err } - (*out)[curr.Name] = newContext + if (*out)[curr.Name] == nil { + (*out)[curr.Name] = newContext + } else { + return fmt.Errorf("error converting *[]NamedContext into *map[string]*api.Context: duplicate name \"%v\" in list: %v", curr.Name, *in) + } } return nil @@ -198,7 +211,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error { if err := s.Convert(&curr.Extension, &newExtension, 0); err != nil { return err } - (*out)[curr.Name] = newExtension + if (*out)[curr.Name] == nil { + (*out)[curr.Name] = newExtension + } else { + return fmt.Errorf("error converting *[]NamedExtension into *map[string]runtime.Object: duplicate name \"%v\" in list: %v", curr.Name, *in) + } } return nil diff --git a/vendor/k8s.io/client-go/tools/clientcmd/api/v1/zz_generated.deepcopy.go b/vendor/k8s.io/client-go/tools/clientcmd/api/v1/zz_generated.deepcopy.go index 83d05b7c6..bb0f3523f 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/api/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/api/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/tools/clientcmd/api/zz_generated.deepcopy.go b/vendor/k8s.io/client-go/tools/clientcmd/api/zz_generated.deepcopy.go index 085c088ee..b90aa8d74 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/api/zz_generated.deepcopy.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/api/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/client-go/tools/clientcmd/auth_loaders.go b/vendor/k8s.io/client-go/tools/clientcmd/auth_loaders.go index 12331f6e6..1d3c11d8f 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/auth_loaders.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/auth_loaders.go @@ -23,7 +23,8 @@ import ( "io/ioutil" "os" - "github.com/howeyc/gopass" + "golang.org/x/crypto/ssh/terminal" + clientauth "k8s.io/client-go/tools/auth" ) @@ -89,8 +90,12 @@ func promptForString(field string, r io.Reader, show bool) (result string, err e _, err = fmt.Fscan(r, &result) } else { var data []byte - data, err = gopass.GetPasswdMasked() - result = string(data) + if terminal.IsTerminal(int(os.Stdin.Fd())) { + data, err = terminal.ReadPassword(int(os.Stdin.Fd())) + result = string(data) + } else { + return "", fmt.Errorf("error reading input for %s", field) + } } return result, err } diff --git a/vendor/k8s.io/client-go/tools/clientcmd/client_config.go b/vendor/k8s.io/client-go/tools/clientcmd/client_config.go index c202e6b25..66331a7ad 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/client_config.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/client_config.go @@ -27,7 +27,6 @@ import ( "github.com/golang/glog" "github.com/imdario/mergo" - "k8s.io/api/core/v1" restclient "k8s.io/client-go/rest" clientauth "k8s.io/client-go/tools/auth" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" @@ -100,6 +99,26 @@ func NewInteractiveClientConfig(config clientcmdapi.Config, contextName string, return &DirectClientConfig{config, contextName, overrides, fallbackReader, configAccess, promptedCredentials{}} } +// NewClientConfigFromBytes takes your kubeconfig and gives you back a ClientConfig +func NewClientConfigFromBytes(configBytes []byte) (ClientConfig, error) { + config, err := Load(configBytes) + if err != nil { + return nil, err + } + + return &DirectClientConfig{*config, "", &ConfigOverrides{}, nil, nil, promptedCredentials{}}, nil +} + +// RESTConfigFromKubeConfig is a convenience method to give back a restconfig from your kubeconfig bytes. +// For programmatic access, this is what you want 80% of the time +func RESTConfigFromKubeConfig(configBytes []byte) (*restclient.Config, error) { + clientConfig, err := NewClientConfigFromBytes(configBytes) + if err != nil { + return nil, err + } + return clientConfig.ClientConfig() +} + func (config *DirectClientConfig) RawConfig() (clientcmdapi.Config, error) { return config.config, nil } @@ -318,7 +337,7 @@ func (config *DirectClientConfig) Namespace() (string, bool, error) { } if len(configContext.Namespace) == 0 { - return v1.NamespaceDefault, false, nil + return "default", false, nil } return configContext.Namespace, false, nil diff --git a/vendor/k8s.io/client-go/tools/clientcmd/config.go b/vendor/k8s.io/client-go/tools/clientcmd/config.go index 16ccdaf20..7092c5b10 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/config.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/config.go @@ -68,7 +68,9 @@ func (o *PathOptions) GetEnvVarFiles() []string { return []string{} } - return filepath.SplitList(envVarValue) + fileList := filepath.SplitList(envVarValue) + // prevent the same path load multiple times + return deduplicate(fileList) } func (o *PathOptions) GetLoadingPrecedence() []string { diff --git a/vendor/k8s.io/client-go/tools/clientcmd/loader.go b/vendor/k8s.io/client-go/tools/clientcmd/loader.go index 95e7b1540..3442475e2 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/loader.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/loader.go @@ -139,7 +139,9 @@ func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules { envVarFiles := os.Getenv(RecommendedConfigPathEnvVar) if len(envVarFiles) != 0 { - chain = append(chain, filepath.SplitList(envVarFiles)...) + fileList := filepath.SplitList(envVarFiles) + // prevent the same path load multiple times + chain = append(chain, deduplicate(fileList)...) } else { chain = append(chain, RecommendedHomeFile) @@ -615,3 +617,17 @@ func MakeRelative(path, base string) (string, error) { } return path, nil } + +// deduplicate removes any duplicated values and returns a new slice, keeping the order unchanged +func deduplicate(s []string) []string { + encountered := map[string]bool{} + ret := make([]string, 0) + for i := range s { + if encountered[s[i]] { + continue + } + encountered[s[i]] = true + ret = append(ret, s[i]) + } + return ret +} diff --git a/vendor/k8s.io/client-go/tools/clientcmd/loader_test.go b/vendor/k8s.io/client-go/tools/clientcmd/loader_test.go index c2dbd019d..86eccac45 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/loader_test.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/loader_test.go @@ -201,6 +201,174 @@ func TestLoadingEmptyMaps(t *testing.T) { } } +func TestDuplicateClusterName(t *testing.T) { + configFile, _ := ioutil.TempFile("", "") + defer os.Remove(configFile.Name()) + + err := ioutil.WriteFile(configFile.Name(), []byte(` +kind: Config +apiVersion: v1 +clusters: +- cluster: + api-version: v1 + server: https://kubernetes.default.svc:443 + certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + name: kubeconfig-cluster +- cluster: + api-version: v2 + server: https://test.example.server:443 + certificate-authority: /var/run/secrets/test.example.io/serviceaccount/ca.crt + name: kubeconfig-cluster +contexts: +- context: + cluster: kubeconfig-cluster + namespace: default + user: kubeconfig-user + name: kubeconfig-context +current-context: kubeconfig-context +users: +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +`), os.FileMode(0755)) + + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + _, err = LoadFromFile(configFile.Name()) + if err == nil || !strings.Contains(err.Error(), + "error converting *[]NamedCluster into *map[string]*api.Cluster: duplicate name \"kubeconfig-cluster\" in list") { + t.Error("Expected error in loading duplicate cluster name, got none") + } +} + +func TestDuplicateContextName(t *testing.T) { + configFile, _ := ioutil.TempFile("", "") + defer os.Remove(configFile.Name()) + + err := ioutil.WriteFile(configFile.Name(), []byte(` +kind: Config +apiVersion: v1 +clusters: +- cluster: + api-version: v1 + server: https://kubernetes.default.svc:443 + certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + name: kubeconfig-cluster +contexts: +- context: + cluster: kubeconfig-cluster + namespace: default + user: kubeconfig-user + name: kubeconfig-context +- context: + cluster: test-example-cluster + namespace: test-example + user: test-example-user + name: kubeconfig-context +current-context: kubeconfig-context +users: +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +`), os.FileMode(0755)) + + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + _, err = LoadFromFile(configFile.Name()) + if err == nil || !strings.Contains(err.Error(), + "error converting *[]NamedContext into *map[string]*api.Context: duplicate name \"kubeconfig-context\" in list") { + t.Error("Expected error in loading duplicate context name, got none") + } +} + +func TestDuplicateUserName(t *testing.T) { + configFile, _ := ioutil.TempFile("", "") + defer os.Remove(configFile.Name()) + + err := ioutil.WriteFile(configFile.Name(), []byte(` +kind: Config +apiVersion: v1 +clusters: +- cluster: + api-version: v1 + server: https://kubernetes.default.svc:443 + certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + name: kubeconfig-cluster +contexts: +- context: + cluster: kubeconfig-cluster + namespace: default + user: kubeconfig-user + name: kubeconfig-context +current-context: kubeconfig-context +users: +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/test.example.com/serviceaccount/token +`), os.FileMode(0755)) + + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + _, err = LoadFromFile(configFile.Name()) + if err == nil || !strings.Contains(err.Error(), + "error converting *[]NamedAuthInfo into *map[string]*api.AuthInfo: duplicate name \"kubeconfig-user\" in list") { + t.Error("Expected error in loading duplicate user name, got none") + } +} + +func TestDuplicateExtensionName(t *testing.T) { + configFile, _ := ioutil.TempFile("", "") + defer os.Remove(configFile.Name()) + + err := ioutil.WriteFile(configFile.Name(), []byte(` +kind: Config +apiVersion: v1 +clusters: +- cluster: + api-version: v1 + server: https://kubernetes.default.svc:443 + certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + name: kubeconfig-cluster +contexts: +- context: + cluster: kubeconfig-cluster + namespace: default + user: kubeconfig-user + name: kubeconfig-context +current-context: kubeconfig-context +users: +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +extensions: +- extension: + bytes: test + name: test-extension +- extension: + bytes: some-example + name: test-extension +`), os.FileMode(0755)) + + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + _, err = LoadFromFile(configFile.Name()) + if err == nil || !strings.Contains(err.Error(), + "error converting *[]NamedExtension into *map[string]runtime.Object: duplicate name \"test-extension\" in list") { + t.Error("Expected error in loading duplicate extension name, got none") + } +} + func TestResolveRelativePaths(t *testing.T) { pathResolutionConfig1 := clientcmdapi.Config{ AuthInfos: map[string]*clientcmdapi.AuthInfo{ @@ -592,3 +760,30 @@ func Example_mergingEverythingNoConflicts() { // user: // token: red-token } + +func TestDeduplicate(t *testing.T) { + testCases := []struct { + src []string + expect []string + }{ + { + src: []string{"a", "b", "c", "d", "e", "f"}, + expect: []string{"a", "b", "c", "d", "e", "f"}, + }, + { + src: []string{"a", "b", "c", "b", "e", "f"}, + expect: []string{"a", "b", "c", "e", "f"}, + }, + { + src: []string{"a", "a", "b", "b", "c", "b"}, + expect: []string{"a", "b", "c"}, + }, + } + + for _, testCase := range testCases { + get := deduplicate(testCase.src) + if !reflect.DeepEqual(get, testCase.expect) { + t.Errorf("expect: %v, get: %v", testCase.expect, get) + } + } +} diff --git a/vendor/k8s.io/client-go/tools/clientcmd/merged_client_builder.go b/vendor/k8s.io/client-go/tools/clientcmd/merged_client_builder.go index 3f02111bd..05038133b 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/merged_client_builder.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/merged_client_builder.go @@ -22,7 +22,6 @@ import ( "github.com/golang/glog" - "k8s.io/api/core/v1" restclient "k8s.io/client-go/rest" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) @@ -145,7 +144,7 @@ func (config *DeferredLoadingClientConfig) Namespace() (string, bool, error) { if len(ns) > 0 { // if we got a non-default namespace from the kubeconfig, use it - if ns != v1.NamespaceDefault { + if ns != "default" { return ns, false, nil } diff --git a/vendor/k8s.io/client-go/tools/leaderelection/BUILD b/vendor/k8s.io/client-go/tools/leaderelection/BUILD deleted file mode 100644 index 22e020d8c..000000000 --- a/vendor/k8s.io/client-go/tools/leaderelection/BUILD +++ /dev/null @@ -1,53 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["leaderelection.go"], - importpath = "k8s.io/client-go/tools/leaderelection", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["leaderelection_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1/fake:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - "//vendor/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library", - "//vendor/k8s.io/client-go/tools/record:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/tools/leaderelection/resourcelock:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/leaderelection/leaderelection.go b/vendor/k8s.io/client-go/tools/leaderelection/leaderelection.go index e41b420c9..aed55574a 100644 --- a/vendor/k8s.io/client-go/tools/leaderelection/leaderelection.go +++ b/vendor/k8s.io/client-go/tools/leaderelection/leaderelection.go @@ -74,6 +74,16 @@ func NewLeaderElector(lec LeaderElectionConfig) (*LeaderElector, error) { if lec.RenewDeadline <= time.Duration(JitterFactor*float64(lec.RetryPeriod)) { return nil, fmt.Errorf("renewDeadline must be greater than retryPeriod*JitterFactor") } + if lec.LeaseDuration < 1 { + return nil, fmt.Errorf("leaseDuration must be greater than zero") + } + if lec.RenewDeadline < 1 { + return nil, fmt.Errorf("renewDeadline must be greater than zero") + } + if lec.RetryPeriod < 1 { + return nil, fmt.Errorf("retryPeriod must be greater than zero") + } + if lec.Lock == nil { return nil, fmt.Errorf("Lock must not be nil.") } diff --git a/vendor/k8s.io/client-go/tools/leaderelection/resourcelock/BUILD b/vendor/k8s.io/client-go/tools/leaderelection/resourcelock/BUILD deleted file mode 100644 index 8a9f8104f..000000000 --- a/vendor/k8s.io/client-go/tools/leaderelection/resourcelock/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "configmaplock.go", - "endpointslock.go", - "interface.go", - ], - importpath = "k8s.io/client-go/tools/leaderelection/resourcelock", - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/record:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/metrics/BUILD b/vendor/k8s.io/client-go/tools/metrics/BUILD deleted file mode 100644 index 7b06e0f96..000000000 --- a/vendor/k8s.io/client-go/tools/metrics/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["metrics.go"], - importpath = "k8s.io/client-go/tools/metrics", -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/pager/BUILD b/vendor/k8s.io/client-go/tools/pager/BUILD deleted file mode 100644 index 4d07429af..000000000 --- a/vendor/k8s.io/client-go/tools/pager/BUILD +++ /dev/null @@ -1,49 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["pager.go"], - importpath = "k8s.io/client-go/tools/pager", - deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) - -go_test( - name = "go_default_test", - srcs = ["pager_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - ], -) diff --git a/vendor/k8s.io/client-go/tools/pager/pager.go b/vendor/k8s.io/client-go/tools/pager/pager.go index 2e0874e0e..74ea3586a 100644 --- a/vendor/k8s.io/client-go/tools/pager/pager.go +++ b/vendor/k8s.io/client-go/tools/pager/pager.go @@ -17,10 +17,9 @@ limitations under the License. package pager import ( + "context" "fmt" - "golang.org/x/net/context" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" diff --git a/vendor/k8s.io/client-go/tools/pager/pager_test.go b/vendor/k8s.io/client-go/tools/pager/pager_test.go index b905fc1fb..ae517cab2 100644 --- a/vendor/k8s.io/client-go/tools/pager/pager_test.go +++ b/vendor/k8s.io/client-go/tools/pager/pager_test.go @@ -17,11 +17,11 @@ limitations under the License. package pager import ( + "context" "fmt" "reflect" "testing" - "golang.org/x/net/context" "k8s.io/apimachinery/pkg/api/errors" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/vendor/k8s.io/client-go/tools/portforward/BUILD b/vendor/k8s.io/client-go/tools/portforward/BUILD deleted file mode 100644 index e2fb01e73..000000000 --- a/vendor/k8s.io/client-go/tools/portforward/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["portforward_test.go"], - embed = [":go_default_library"], - deps = ["//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "portforward.go", - ], - importpath = "k8s.io/client-go/tools/portforward", - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/record/BUILD b/vendor/k8s.io/client-go/tools/record/BUILD deleted file mode 100644 index 0799afe7e..000000000 --- a/vendor/k8s.io/client-go/tools/record/BUILD +++ /dev/null @@ -1,68 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "event_test.go", - "events_cache_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/reference:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "event.go", - "events_cache.go", - "fake.go", - ], - importpath = "k8s.io/client-go/tools/record", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/golang/groupcache/lru:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/reference:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/record/event.go b/vendor/k8s.io/client-go/tools/record/event.go index b5ec44650..168dfa80c 100644 --- a/vendor/k8s.io/client-go/tools/record/event.go +++ b/vendor/k8s.io/client-go/tools/record/event.go @@ -72,6 +72,9 @@ type EventRecorder interface { // PastEventf is just like Eventf, but with an option to specify the event's 'timestamp' field. PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) + + // AnnotatedEventf is just like eventf, but with annotations attached + AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) } // EventBroadcaster knows how to receive events and send them to any EventSink, watcher, or log. @@ -225,11 +228,7 @@ func (eventBroadcaster *eventBroadcasterImpl) StartEventWatcher(eventHandler fun watcher := eventBroadcaster.Watch() go func() { defer utilruntime.HandleCrash() - for { - watchEvent, open := <-watcher.ResultChan() - if !open { - return - } + for watchEvent := range watcher.ResultChan() { event, ok := watchEvent.Object.(*v1.Event) if !ok { // This is all local, so there's no reason this should @@ -254,7 +253,7 @@ type recorderImpl struct { clock clock.Clock } -func (recorder *recorderImpl) generateEvent(object runtime.Object, timestamp metav1.Time, eventtype, reason, message string) { +func (recorder *recorderImpl) generateEvent(object runtime.Object, annotations map[string]string, timestamp metav1.Time, eventtype, reason, message string) { ref, err := ref.GetReference(recorder.scheme, object) if err != nil { glog.Errorf("Could not construct reference to: '%#v' due to: '%v'. Will not report event: '%v' '%v' '%v'", object, err, eventtype, reason, message) @@ -266,7 +265,7 @@ func (recorder *recorderImpl) generateEvent(object runtime.Object, timestamp met return } - event := recorder.makeEvent(ref, eventtype, reason, message) + event := recorder.makeEvent(ref, annotations, eventtype, reason, message) event.Source = recorder.source go func() { @@ -285,7 +284,7 @@ func validateEventType(eventtype string) bool { } func (recorder *recorderImpl) Event(object runtime.Object, eventtype, reason, message string) { - recorder.generateEvent(object, metav1.Now(), eventtype, reason, message) + recorder.generateEvent(object, nil, metav1.Now(), eventtype, reason, message) } func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) { @@ -293,10 +292,14 @@ func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, m } func (recorder *recorderImpl) PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) { - recorder.generateEvent(object, timestamp, eventtype, reason, fmt.Sprintf(messageFmt, args...)) + recorder.generateEvent(object, nil, timestamp, eventtype, reason, fmt.Sprintf(messageFmt, args...)) +} + +func (recorder *recorderImpl) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + recorder.generateEvent(object, annotations, metav1.Now(), eventtype, reason, fmt.Sprintf(messageFmt, args...)) } -func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, eventtype, reason, message string) *v1.Event { +func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, annotations map[string]string, eventtype, reason, message string) *v1.Event { t := metav1.Time{Time: recorder.clock.Now()} namespace := ref.Namespace if namespace == "" { @@ -304,8 +307,9 @@ func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, eventtype, reas } return &v1.Event{ ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%v.%x", ref.Name, t.UnixNano()), - Namespace: namespace, + Name: fmt.Sprintf("%v.%x", ref.Name, t.UnixNano()), + Namespace: namespace, + Annotations: annotations, }, InvolvedObject: *ref, Reason: reason, diff --git a/vendor/k8s.io/client-go/tools/record/fake.go b/vendor/k8s.io/client-go/tools/record/fake.go index c0e8eedbb..6e031daaf 100644 --- a/vendor/k8s.io/client-go/tools/record/fake.go +++ b/vendor/k8s.io/client-go/tools/record/fake.go @@ -45,6 +45,10 @@ func (f *FakeRecorder) Eventf(object runtime.Object, eventtype, reason, messageF func (f *FakeRecorder) PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) { } +func (f *FakeRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + f.Eventf(object, eventtype, reason, messageFmt, args) +} + // NewFakeRecorder creates new fake event recorder with event channel with // buffer of given size. func NewFakeRecorder(bufferSize int) *FakeRecorder { diff --git a/vendor/k8s.io/client-go/tools/reference/BUILD b/vendor/k8s.io/client-go/tools/reference/BUILD deleted file mode 100644 index 47da958ab..000000000 --- a/vendor/k8s.io/client-go/tools/reference/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["ref.go"], - importpath = "k8s.io/client-go/tools/reference", - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/tools/reference/ref.go b/vendor/k8s.io/client-go/tools/reference/ref.go index 58b60fd5d..573d948a9 100644 --- a/vendor/k8s.io/client-go/tools/reference/ref.go +++ b/vendor/k8s.io/client-go/tools/reference/ref.go @@ -86,10 +86,14 @@ func GetReference(scheme *runtime.Scheme, obj runtime.Object) (*v1.ObjectReferen } // example paths: ///* parts := strings.Split(selfLinkUrl.Path, "/") - if len(parts) < 3 { + if len(parts) < 4 { return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version) } - version = parts[2] + if parts[1] == "api" { + version = parts[2] + } else { + version = parts[2] + "/" + parts[3] + } } // only has list metadata diff --git a/vendor/k8s.io/client-go/tools/reference/ref_test.go b/vendor/k8s.io/client-go/tools/reference/ref_test.go new file mode 100644 index 000000000..b0cf06a97 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/reference/ref_test.go @@ -0,0 +1,72 @@ +/* +Copyright 2018 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 reference + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +type TestRuntimeObj struct { + metav1.TypeMeta + metav1.ObjectMeta +} + +func (o *TestRuntimeObj) DeepCopyObject() runtime.Object { + panic("die") +} + +func TestGetReferenceRefVersion(t *testing.T) { + tests := []struct { + name string + input *TestRuntimeObj + expectedRefVersion string + }{ + { + name: "api from selflink", + input: &TestRuntimeObj{ + ObjectMeta: metav1.ObjectMeta{SelfLink: "/api/v1/namespaces"}, + }, + expectedRefVersion: "v1", + }, + { + name: "foo.group/v3 from selflink", + input: &TestRuntimeObj{ + ObjectMeta: metav1.ObjectMeta{SelfLink: "/apis/foo.group/v3/namespaces"}, + }, + expectedRefVersion: "foo.group/v3", + }, + } + + scheme := runtime.NewScheme() + scheme.AddKnownTypes(schema.GroupVersion{Group: "this", Version: "is ignored"}, &TestRuntimeObj{}) + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ref, err := GetReference(scheme, test.input) + if err != nil { + t.Fatal(err) + } + if test.expectedRefVersion != ref.APIVersion { + t.Errorf("expected %q, got %q", test.expectedRefVersion, ref.APIVersion) + } + }) + } +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/BUILD b/vendor/k8s.io/client-go/tools/remotecommand/BUILD deleted file mode 100644 index b30c122c3..000000000 --- a/vendor/k8s.io/client-go/tools/remotecommand/BUILD +++ /dev/null @@ -1,60 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "v2_test.go", - "v4_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "errorstream.go", - "remotecommand.go", - "resize.go", - "v1.go", - "v2.go", - "v3.go", - "v4.go", - ], - importpath = "k8s.io/client-go/tools/remotecommand", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/remotecommand:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/transport/spdy:go_default_library", - "//vendor/k8s.io/client-go/util/exec:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/transport/BUILD b/vendor/k8s.io/client-go/transport/BUILD deleted file mode 100644 index 71494544a..000000000 --- a/vendor/k8s.io/client-go/transport/BUILD +++ /dev/null @@ -1,48 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "cache_test.go", - "round_trippers_test.go", - "transport_test.go", - ], - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = [ - "cache.go", - "config.go", - "round_trippers.go", - "transport.go", - ], - importpath = "k8s.io/client-go/transport", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/transport/spdy:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/transport/cache.go b/vendor/k8s.io/client-go/transport/cache.go index 7c40848c7..7cffe2a5f 100644 --- a/vendor/k8s.io/client-go/transport/cache.go +++ b/vendor/k8s.io/client-go/transport/cache.go @@ -43,7 +43,9 @@ type tlsCacheKey struct { caData string certData string keyData string + getCert string serverName string + dial string } func (t tlsCacheKey) String() string { @@ -51,7 +53,7 @@ func (t tlsCacheKey) String() string { if len(t.keyData) > 0 { keyText = "" } - return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, serverName:%s", t.insecure, t.caData, t.certData, keyText, t.serverName) + return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, getCert: %s, serverName:%s, dial:%s", t.insecure, t.caData, t.certData, keyText, t.getCert, t.serverName, t.dial) } func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { @@ -75,7 +77,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { return nil, err } // The options didn't require a custom TLS config - if tlsConfig == nil { + if tlsConfig == nil && config.Dial == nil { return http.DefaultTransport, nil } @@ -84,7 +86,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { dial = (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, - }).Dial + }).DialContext } // Cache a single transport for these options c.transports[key] = utilnet.SetTransportDefaults(&http.Transport{ @@ -92,7 +94,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { TLSHandshakeTimeout: 10 * time.Second, TLSClientConfig: tlsConfig, MaxIdleConnsPerHost: idleConnsPerHost, - Dial: dial, + DialContext: dial, }) return c.transports[key], nil } @@ -108,6 +110,8 @@ func tlsConfigKey(c *Config) (tlsCacheKey, error) { caData: string(c.TLS.CAData), certData: string(c.TLS.CertData), keyData: string(c.TLS.KeyData), + getCert: fmt.Sprintf("%p", c.TLS.GetCert), serverName: c.TLS.ServerName, + dial: fmt.Sprintf("%p", c.Dial), }, nil } diff --git a/vendor/k8s.io/client-go/transport/cache_test.go b/vendor/k8s.io/client-go/transport/cache_test.go index 81f428de0..9b740cdec 100644 --- a/vendor/k8s.io/client-go/transport/cache_test.go +++ b/vendor/k8s.io/client-go/transport/cache_test.go @@ -17,6 +17,9 @@ limitations under the License. package transport import ( + "context" + "crypto/tls" + "net" "net/http" "testing" ) @@ -51,8 +54,12 @@ func TestTLSConfigKey(t *testing.T) { } // Make sure config fields that affect the tls config affect the cache key + dialer := net.Dialer{} + getCert := func() (*tls.Certificate, error) { return nil, nil } uniqueConfigurations := map[string]*Config{ "no tls": {}, + "dialer": {Dial: dialer.DialContext}, + "dialer2": {Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil }}, "insecure": {TLS: TLSConfig{Insecure: true}}, "cadata 1": {TLS: TLSConfig{CAData: []byte{1}}}, "cadata 2": {TLS: TLSConfig{CAData: []byte{2}}}, @@ -101,14 +108,27 @@ func TestTLSConfigKey(t *testing.T) { KeyData: []byte{1}, }, }, + "getCert1": { + TLS: TLSConfig{ + KeyData: []byte{1}, + GetCert: getCert, + }, + }, + "getCert2": { + TLS: TLSConfig{ + KeyData: []byte{1}, + GetCert: func() (*tls.Certificate, error) { return nil, nil }, + }, + }, + "getCert1, key 2": { + TLS: TLSConfig{ + KeyData: []byte{2}, + GetCert: getCert, + }, + }, } for nameA, valueA := range uniqueConfigurations { for nameB, valueB := range uniqueConfigurations { - // Don't compare to ourselves - if nameA == nameB { - continue - } - keyA, err := tlsConfigKey(valueA) if err != nil { t.Errorf("Unexpected error for %q: %v", nameA, err) @@ -119,6 +139,15 @@ func TestTLSConfigKey(t *testing.T) { t.Errorf("Unexpected error for %q: %v", nameB, err) continue } + + // Make sure we get the same key on the same config + if nameA == nameB { + if keyA != keyB { + t.Errorf("Expected identical cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB) + } + continue + } + if keyA == keyB { t.Errorf("Expected unique cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB) continue diff --git a/vendor/k8s.io/client-go/transport/config.go b/vendor/k8s.io/client-go/transport/config.go index af347dafe..4081c23e7 100644 --- a/vendor/k8s.io/client-go/transport/config.go +++ b/vendor/k8s.io/client-go/transport/config.go @@ -17,6 +17,8 @@ limitations under the License. package transport import ( + "context" + "crypto/tls" "net" "net/http" ) @@ -53,7 +55,7 @@ type Config struct { WrapTransport func(rt http.RoundTripper) http.RoundTripper // Dial specifies the dial function for creating unencrypted TCP connections. - Dial func(network, addr string) (net.Conn, error) + Dial func(ctx context.Context, network, address string) (net.Conn, error) } // ImpersonationConfig has all the available impersonation options @@ -83,7 +85,12 @@ func (c *Config) HasTokenAuth() bool { // HasCertAuth returns whether the configuration has certificate authentication or not. func (c *Config) HasCertAuth() bool { - return len(c.TLS.CertData) != 0 || len(c.TLS.CertFile) != 0 + return (len(c.TLS.CertData) != 0 || len(c.TLS.CertFile) != 0) && (len(c.TLS.KeyData) != 0 || len(c.TLS.KeyFile) != 0) +} + +// HasCertCallbacks returns whether the configuration has certificate callback or not. +func (c *Config) HasCertCallback() bool { + return c.TLS.GetCert != nil } // TLSConfig holds the information needed to set up a TLS transport. @@ -98,4 +105,6 @@ type TLSConfig struct { CAData []byte // Bytes of the PEM-encoded server trusted root certificates. Supercedes CAFile. CertData []byte // Bytes of the PEM-encoded client certificate. Supercedes CertFile. KeyData []byte // Bytes of the PEM-encoded client key. Supercedes KeyFile. + + GetCert func() (*tls.Certificate, error) // Callback that returns a TLS client certificate. CertData, CertFile, KeyData and KeyFile supercede this field. } diff --git a/vendor/k8s.io/client-go/transport/round_trippers.go b/vendor/k8s.io/client-go/transport/round_trippers.go index c728b1877..459a93760 100644 --- a/vendor/k8s.io/client-go/transport/round_trippers.go +++ b/vendor/k8s.io/client-go/transport/round_trippers.go @@ -335,7 +335,7 @@ func (r *requestInfo) toCurl() string { } } - return fmt.Sprintf("curl -k -v -X%s %s %s", r.RequestVerb, headers, r.RequestURL) + return fmt.Sprintf("curl -k -v -X%s %s '%s'", r.RequestVerb, headers, r.RequestURL) } // debuggingRoundTripper will display information about the requests passing diff --git a/vendor/k8s.io/client-go/transport/spdy/BUILD b/vendor/k8s.io/client-go/transport/spdy/BUILD deleted file mode 100644 index bf90084b6..000000000 --- a/vendor/k8s.io/client-go/transport/spdy/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["spdy.go"], - importpath = "k8s.io/client-go/transport/spdy", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/transport/transport.go b/vendor/k8s.io/client-go/transport/transport.go index 15be0a3e6..c19739fdf 100644 --- a/vendor/k8s.io/client-go/transport/transport.go +++ b/vendor/k8s.io/client-go/transport/transport.go @@ -28,7 +28,7 @@ import ( // or transport level security defined by the provided Config. func New(config *Config) (http.RoundTripper, error) { // Set transport level security - if config.Transport != nil && (config.HasCA() || config.HasCertAuth() || config.TLS.Insecure) { + if config.Transport != nil && (config.HasCA() || config.HasCertAuth() || config.HasCertCallback() || config.TLS.Insecure) { return nil, fmt.Errorf("using a custom transport with TLS certificate options or the insecure flag is not allowed") } @@ -52,7 +52,7 @@ func New(config *Config) (http.RoundTripper, error) { // TLSConfigFor returns a tls.Config that will provide the transport level security defined // by the provided Config. Will return nil if no transport level security is requested. func TLSConfigFor(c *Config) (*tls.Config, error) { - if !(c.HasCA() || c.HasCertAuth() || c.TLS.Insecure) { + if !(c.HasCA() || c.HasCertAuth() || c.HasCertCallback() || c.TLS.Insecure || len(c.TLS.ServerName) > 0) { return nil, nil } if c.HasCA() && c.TLS.Insecure { @@ -75,12 +75,40 @@ func TLSConfigFor(c *Config) (*tls.Config, error) { tlsConfig.RootCAs = rootCertPool(c.TLS.CAData) } + var staticCert *tls.Certificate if c.HasCertAuth() { + // If key/cert were provided, verify them before setting up + // tlsConfig.GetClientCertificate. cert, err := tls.X509KeyPair(c.TLS.CertData, c.TLS.KeyData) if err != nil { return nil, err } - tlsConfig.Certificates = []tls.Certificate{cert} + staticCert = &cert + } + + if c.HasCertAuth() || c.HasCertCallback() { + tlsConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { + // Note: static key/cert data always take precedence over cert + // callback. + if staticCert != nil { + return staticCert, nil + } + if c.HasCertCallback() { + cert, err := c.TLS.GetCert() + if err != nil { + return nil, err + } + // GetCert may return empty value, meaning no cert. + if cert != nil { + return cert, nil + } + } + + // Both c.TLS.CertData/KeyData were unset and GetCert didn't return + // anything. Return an empty tls.Certificate, no client cert will + // be sent to the server. + return &tls.Certificate{}, nil + } } return tlsConfig, nil diff --git a/vendor/k8s.io/client-go/transport/transport_test.go b/vendor/k8s.io/client-go/transport/transport_test.go index 4d2d78f86..2e9896a08 100644 --- a/vendor/k8s.io/client-go/transport/transport_test.go +++ b/vendor/k8s.io/client-go/transport/transport_test.go @@ -17,6 +17,8 @@ limitations under the License. package transport import ( + "crypto/tls" + "errors" "net/http" "testing" ) @@ -94,6 +96,8 @@ func TestNew(t *testing.T) { Config *Config Err bool TLS bool + TLSCert bool + TLSErr bool Default bool }{ "default transport": { @@ -101,6 +105,13 @@ func TestNew(t *testing.T) { Config: &Config{}, }, + "server name": { + TLS: true, + Config: &Config{TLS: TLSConfig{ + ServerName: "foo", + }}, + }, + "ca transport": { TLS: true, Config: &Config{ @@ -128,7 +139,8 @@ func TestNew(t *testing.T) { }, "cert transport": { - TLS: true, + TLS: true, + TLSCert: true, Config: &Config{ TLS: TLSConfig{ CAData: []byte(rootCACert), @@ -158,7 +170,8 @@ func TestNew(t *testing.T) { }, }, "key data overriding bad file cert transport": { - TLS: true, + TLS: true, + TLSCert: true, Config: &Config{ TLS: TLSConfig{ CAData: []byte(rootCACert), @@ -168,37 +181,108 @@ func TestNew(t *testing.T) { }, }, }, + "callback cert and key": { + TLS: true, + TLSCert: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + crt, err := tls.X509KeyPair([]byte(certData), []byte(keyData)) + return &crt, err + }, + }, + }, + }, + "cert callback error": { + TLS: true, + TLSCert: true, + TLSErr: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + return nil, errors.New("GetCert failure") + }, + }, + }, + }, + "cert data overrides empty callback result": { + TLS: true, + TLSCert: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + return nil, nil + }, + CertData: []byte(certData), + KeyData: []byte(keyData), + }, + }, + }, + "callback returns nothing": { + TLS: true, + TLSCert: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + return nil, nil + }, + }, + }, + }, } for k, testCase := range testCases { - transport, err := New(testCase.Config) - switch { - case testCase.Err && err == nil: - t.Errorf("%s: unexpected non-error", k) - continue - case !testCase.Err && err != nil: - t.Errorf("%s: unexpected error: %v", k, err) - continue - } - - switch { - case testCase.Default && transport != http.DefaultTransport: - t.Errorf("%s: expected the default transport, got %#v", k, transport) - continue - case !testCase.Default && transport == http.DefaultTransport: - t.Errorf("%s: expected non-default transport, got %#v", k, transport) - continue - } - - // We only know how to check TLSConfig on http.Transports - if transport, ok := transport.(*http.Transport); ok { + t.Run(k, func(t *testing.T) { + rt, err := New(testCase.Config) + switch { + case testCase.Err && err == nil: + t.Fatal("unexpected non-error") + case !testCase.Err && err != nil: + t.Fatalf("unexpected error: %v", err) + } + if testCase.Err { + return + } + + switch { + case testCase.Default && rt != http.DefaultTransport: + t.Fatalf("got %#v, expected the default transport", rt) + case !testCase.Default && rt == http.DefaultTransport: + t.Fatalf("got %#v, expected non-default transport", rt) + } + + // We only know how to check TLSConfig on http.Transports + transport := rt.(*http.Transport) switch { case testCase.TLS && transport.TLSClientConfig == nil: - t.Errorf("%s: expected TLSClientConfig, got %#v", k, transport) - continue + t.Fatalf("got %#v, expected TLSClientConfig", transport) case !testCase.TLS && transport.TLSClientConfig != nil: - t.Errorf("%s: expected no TLSClientConfig, got %#v", k, transport) - continue + t.Fatalf("got %#v, expected no TLSClientConfig", transport) + } + if !testCase.TLS { + return + } + + switch { + case testCase.TLSCert && transport.TLSClientConfig.GetClientCertificate == nil: + t.Fatalf("got %#v, expected TLSClientConfig.GetClientCertificate", transport.TLSClientConfig) + case !testCase.TLSCert && transport.TLSClientConfig.GetClientCertificate != nil: + t.Fatalf("got %#v, expected no TLSClientConfig.GetClientCertificate", transport.TLSClientConfig) + } + if !testCase.TLSCert { + return + } + + _, err = transport.TLSClientConfig.GetClientCertificate(nil) + switch { + case testCase.TLSErr && err == nil: + t.Error("got nil error from GetClientCertificate, expected non-nil") + case !testCase.TLSErr && err != nil: + t.Errorf("got error from GetClientCertificate: %q, expected nil", err) } - } + }) } } diff --git a/vendor/k8s.io/client-go/util/buffer/BUILD b/vendor/k8s.io/client-go/util/buffer/BUILD deleted file mode 100644 index d3b2652ce..000000000 --- a/vendor/k8s.io/client-go/util/buffer/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["ring_growing.go"], - importpath = "k8s.io/client-go/util/buffer", - visibility = ["//visibility:public"], -) - -go_test( - name = "go_default_test", - srcs = ["ring_growing_test.go"], - embed = [":go_default_library"], - deps = ["//vendor/github.com/stretchr/testify/assert:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/util/buffer/ring_growing_test.go b/vendor/k8s.io/client-go/util/buffer/ring_growing_test.go index 231b836c0..31a4c079d 100644 --- a/vendor/k8s.io/client-go/util/buffer/ring_growing_test.go +++ b/vendor/k8s.io/client-go/util/buffer/ring_growing_test.go @@ -39,7 +39,7 @@ func TestGrowth(t *testing.T) { } assert.Equalf(t, x, read, "expected to have read %d items: %d", x, read) assert.Zerof(t, g.readable, "expected readable to be zero: %d", g.readable) - assert.Equalf(t, g.n, 16, "expected N to be 16: %d", g.n) + assert.Equalf(t, 16, g.n, "expected N to be 16: %d", g.n) } func TestEmpty(t *testing.T) { diff --git a/vendor/k8s.io/client-go/util/cert/BUILD b/vendor/k8s.io/client-go/util/cert/BUILD deleted file mode 100644 index 799979d46..000000000 --- a/vendor/k8s.io/client-go/util/cert/BUILD +++ /dev/null @@ -1,47 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "csr_test.go", - "pem_test.go", - ], - data = glob(["testdata/**"]), - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = [ - "cert.go", - "csr.go", - "io.go", - "pem.go", - ], - data = [ - "testdata/dontUseThisKey.pem", - ], - importpath = "k8s.io/client-go/util/cert", -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/util/cert/triple:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/cert/io.go b/vendor/k8s.io/client-go/util/cert/io.go index a41f8054a..a57bf09d5 100644 --- a/vendor/k8s.io/client-go/util/cert/io.go +++ b/vendor/k8s.io/client-go/util/cert/io.go @@ -17,7 +17,11 @@ limitations under the License. package cert import ( + "crypto" + "crypto/ecdsa" + "crypto/rsa" "crypto/x509" + "encoding/pem" "fmt" "io/ioutil" "os" @@ -84,7 +88,8 @@ func WriteKey(keyPath string, data []byte) error { // can't find one, it will generate a new key and store it there. func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) { loadedData, err := ioutil.ReadFile(keyPath) - if err == nil { + // Call verifyKeyData to ensure the file wasn't empty/corrupt. + if err == nil && verifyKeyData(loadedData) { return loadedData, false, err } if !os.IsNotExist(err) { @@ -101,6 +106,27 @@ func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err return generatedData, true, nil } +// MarshalPrivateKeyToPEM converts a known private key type of RSA or ECDSA to +// a PEM encoded block or returns an error. +func MarshalPrivateKeyToPEM(privateKey crypto.PrivateKey) ([]byte, error) { + switch t := privateKey.(type) { + case *ecdsa.PrivateKey: + derBytes, err := x509.MarshalECPrivateKey(t) + if err != nil { + return nil, err + } + privateKeyPemBlock := &pem.Block{ + Type: ECPrivateKeyBlockType, + Bytes: derBytes, + } + return pem.EncodeToMemory(privateKeyPemBlock), nil + case *rsa.PrivateKey: + return EncodePrivateKeyPEM(t), nil + default: + return nil, fmt.Errorf("private key is not a recognized type: %T", privateKey) + } +} + // NewPool returns an x509.CertPool containing the certificates in the given PEM-encoded file. // Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates func NewPool(filename string) (*x509.CertPool, error) { @@ -156,3 +182,12 @@ func PublicKeysFromFile(file string) ([]interface{}, error) { } return keys, nil } + +// verifyKeyData returns true if the provided data appears to be a valid private key. +func verifyKeyData(data []byte) bool { + if len(data) == 0 { + return false + } + _, err := ParsePrivateKeyPEM(data) + return err == nil +} diff --git a/vendor/k8s.io/client-go/util/cert/triple/BUILD b/vendor/k8s.io/client-go/util/cert/triple/BUILD deleted file mode 100644 index 6399d0e95..000000000 --- a/vendor/k8s.io/client-go/util/cert/triple/BUILD +++ /dev/null @@ -1,26 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["triple.go"], - importpath = "k8s.io/client-go/util/cert/triple", - deps = ["//vendor/k8s.io/client-go/util/cert:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/certificate/BUILD b/vendor/k8s.io/client-go/util/certificate/BUILD deleted file mode 100644 index dfc5c3933..000000000 --- a/vendor/k8s.io/client-go/util/certificate/BUILD +++ /dev/null @@ -1,66 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "certificate_manager_test.go", - "certificate_store_test.go", - ], - embed = [":go_default_library"], - tags = ["automanaged"], - deps = [ - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/util/cert:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = [ - "certificate_manager.go", - "certificate_store.go", - ], - importpath = "k8s.io/client-go/util/certificate", - tags = ["automanaged"], - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/util/cert:go_default_library", - "//vendor/k8s.io/client-go/util/certificate/csr:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/client-go/util/certificate/csr:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/client-go/util/certificate/certificate_store.go b/vendor/k8s.io/client-go/util/certificate/certificate_store.go index 42a40dcdf..f54bd6586 100644 --- a/vendor/k8s.io/client-go/util/certificate/certificate_store.go +++ b/vendor/k8s.io/client-go/util/certificate/certificate_store.go @@ -46,6 +46,15 @@ type fileStore struct { keyFile string } +// FileStore is a store that provides certificate retrieval as well as +// the path on disk of the current PEM. +type FileStore interface { + Store + // CurrentPath returns the path on disk of the current certificate/key + // pair encoded as PEM files. + CurrentPath() string +} + // NewFileStore returns a concrete implementation of a Store that is based on // storing the cert/key pairs in a single file per pair on disk in the // designated directory. When starting up it will look for the currently @@ -64,7 +73,7 @@ func NewFileStore( certDirectory string, keyDirectory string, certFile string, - keyFile string) (Store, error) { + keyFile string) (FileStore, error) { s := fileStore{ pairNamePrefix: pairNamePrefix, @@ -79,6 +88,11 @@ func NewFileStore( return &s, nil } +// CurrentPath returns the path to the current version of these certificates. +func (s *fileStore) CurrentPath() string { + return filepath.Join(s.certDirectory, s.filename(currentPair)) +} + // recover checks if there is a certificate rotation that was interrupted while // progress, and if so, attempts to recover to a good state. func (s *fileStore) recover() error { diff --git a/vendor/k8s.io/client-go/util/certificate/csr/BUILD b/vendor/k8s.io/client-go/util/certificate/csr/BUILD deleted file mode 100644 index c1bcd9578..000000000 --- a/vendor/k8s.io/client-go/util/certificate/csr/BUILD +++ /dev/null @@ -1,53 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["csr.go"], - importpath = "k8s.io/client-go/util/certificate/csr", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", - "//vendor/k8s.io/client-go/util/cert:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) - -go_test( - name = "go_default_test", - srcs = ["csr_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/util/cert:go_default_library", - ], -) diff --git a/vendor/k8s.io/client-go/util/connrotation/connrotation.go b/vendor/k8s.io/client-go/util/connrotation/connrotation.go new file mode 100644 index 000000000..235a9e019 --- /dev/null +++ b/vendor/k8s.io/client-go/util/connrotation/connrotation.go @@ -0,0 +1,105 @@ +/* +Copyright 2018 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 connrotation implements a connection dialer that tracks and can close +// all created connections. +// +// This is used for credential rotation of long-lived connections, when there's +// no way to re-authenticate on a live connection. +package connrotation + +import ( + "context" + "net" + "sync" +) + +// DialFunc is a shorthand for signature of net.DialContext. +type DialFunc func(ctx context.Context, network, address string) (net.Conn, error) + +// Dialer opens connections through Dial and tracks them. +type Dialer struct { + dial DialFunc + + mu sync.Mutex + conns map[*closableConn]struct{} +} + +// NewDialer creates a new Dialer instance. +// +// If dial is not nil, it will be used to create new underlying connections. +// Otherwise net.DialContext is used. +func NewDialer(dial DialFunc) *Dialer { + return &Dialer{ + dial: dial, + conns: make(map[*closableConn]struct{}), + } +} + +// CloseAll forcibly closes all tracked connections. +// +// Note: new connections may get created before CloseAll returns. +func (d *Dialer) CloseAll() { + d.mu.Lock() + conns := d.conns + d.conns = make(map[*closableConn]struct{}) + d.mu.Unlock() + + for conn := range conns { + conn.Close() + } +} + +// Dial creates a new tracked connection. +func (d *Dialer) Dial(network, address string) (net.Conn, error) { + return d.DialContext(context.Background(), network, address) +} + +// DialContext creates a new tracked connection. +func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { + conn, err := d.dial(ctx, network, address) + if err != nil { + return nil, err + } + + closable := &closableConn{Conn: conn} + + // Start tracking the connection + d.mu.Lock() + d.conns[closable] = struct{}{} + d.mu.Unlock() + + // When the connection is closed, remove it from the map. This will + // be no-op if the connection isn't in the map, e.g. if CloseAll() + // is called. + closable.onClose = func() { + d.mu.Lock() + delete(d.conns, closable) + d.mu.Unlock() + } + + return closable, nil +} + +type closableConn struct { + onClose func() + net.Conn +} + +func (c *closableConn) Close() error { + go c.onClose() + return c.Conn.Close() +} diff --git a/vendor/k8s.io/client-go/util/connrotation/connrotation_test.go b/vendor/k8s.io/client-go/util/connrotation/connrotation_test.go new file mode 100644 index 000000000..a618f2961 --- /dev/null +++ b/vendor/k8s.io/client-go/util/connrotation/connrotation_test.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 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 connrotation + +import ( + "context" + "net" + "testing" + "time" +) + +func TestCloseAll(t *testing.T) { + closed := make(chan struct{}) + dialFn := func(ctx context.Context, network, address string) (net.Conn, error) { + return closeOnlyConn{onClose: func() { closed <- struct{}{} }}, nil + } + dialer := NewDialer(dialFn) + + const numConns = 10 + + // Outer loop to ensure Dialer is re-usable after CloseAll. + for i := 0; i < 5; i++ { + for j := 0; j < numConns; j++ { + if _, err := dialer.Dial("", ""); err != nil { + t.Fatal(err) + } + } + dialer.CloseAll() + for j := 0; j < numConns; j++ { + select { + case <-closed: + case <-time.After(time.Second): + t.Fatalf("iteration %d: 1s after CloseAll only %d/%d connections closed", i, j, numConns) + } + } + } +} + +type closeOnlyConn struct { + net.Conn + onClose func() +} + +func (c closeOnlyConn) Close() error { + go c.onClose() + return nil +} diff --git a/vendor/k8s.io/client-go/util/exec/BUILD b/vendor/k8s.io/client-go/util/exec/BUILD deleted file mode 100644 index 57b58e5cc..000000000 --- a/vendor/k8s.io/client-go/util/exec/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["exec.go"], - importpath = "k8s.io/client-go/util/exec", -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/flowcontrol/BUILD b/vendor/k8s.io/client-go/util/flowcontrol/BUILD deleted file mode 100644 index 819bb7ef3..000000000 --- a/vendor/k8s.io/client-go/util/flowcontrol/BUILD +++ /dev/null @@ -1,44 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "backoff_test.go", - "throttle_test.go", - ], - embed = [":go_default_library"], - deps = ["//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = [ - "backoff.go", - "throttle.go", - ], - importpath = "k8s.io/client-go/util/flowcontrol", - deps = [ - "//vendor/golang.org/x/time/rate:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", - "//vendor/k8s.io/client-go/util/integer:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/homedir/BUILD b/vendor/k8s.io/client-go/util/homedir/BUILD deleted file mode 100644 index 21a1952cf..000000000 --- a/vendor/k8s.io/client-go/util/homedir/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["homedir.go"], - importpath = "k8s.io/client-go/util/homedir", -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/integer/BUILD b/vendor/k8s.io/client-go/util/integer/BUILD deleted file mode 100644 index 8a2105e46..000000000 --- a/vendor/k8s.io/client-go/util/integer/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["integer_test.go"], - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["integer.go"], - importpath = "k8s.io/client-go/util/integer", -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/jsonpath/BUILD b/vendor/k8s.io/client-go/util/jsonpath/BUILD deleted file mode 100644 index ab43accd6..000000000 --- a/vendor/k8s.io/client-go/util/jsonpath/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "jsonpath_test.go", - "parser_test.go", - ], - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "jsonpath.go", - "node.go", - "parser.go", - ], - importpath = "k8s.io/client-go/util/jsonpath", - deps = ["//vendor/k8s.io/client-go/third_party/forked/golang/template:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/retry/BUILD b/vendor/k8s.io/client-go/util/retry/BUILD deleted file mode 100644 index d74581310..000000000 --- a/vendor/k8s.io/client-go/util/retry/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["util.go"], - importpath = "k8s.io/client-go/util/retry", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["util_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/testing/BUILD b/vendor/k8s.io/client-go/util/testing/BUILD deleted file mode 100644 index 726a30f92..000000000 --- a/vendor/k8s.io/client-go/util/testing/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["fake_handler_test.go"], - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = [ - "fake_handler.go", - "tmpdir.go", - ], - importpath = "k8s.io/client-go/util/testing", -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/workqueue/BUILD b/vendor/k8s.io/client-go/util/workqueue/BUILD deleted file mode 100644 index 7fb9fba48..000000000 --- a/vendor/k8s.io/client-go/util/workqueue/BUILD +++ /dev/null @@ -1,59 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "default_rate_limiters_test.go", - "delaying_queue_test.go", - "rate_limitting_queue_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = [ - "default_rate_limiters.go", - "delaying_queue.go", - "doc.go", - "metrics.go", - "parallelizer.go", - "queue.go", - "rate_limitting_queue.go", - ], - importpath = "k8s.io/client-go/util/workqueue", - deps = [ - "//vendor/golang.org/x/time/rate:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - ], -) - -go_test( - name = "go_default_xtest", - srcs = ["queue_test.go"], - deps = ["//vendor/k8s.io/client-go/util/workqueue:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/client-go/util/workqueue/delaying_queue.go b/vendor/k8s.io/client-go/util/workqueue/delaying_queue.go index c62ed32ef..a37177425 100644 --- a/vendor/k8s.io/client-go/util/workqueue/delaying_queue.go +++ b/vendor/k8s.io/client-go/util/workqueue/delaying_queue.go @@ -45,7 +45,7 @@ func newDelayingQueue(clock clock.Clock, name string) DelayingInterface { ret := &delayingType{ Interface: NewNamed(name), clock: clock, - heartbeat: clock.Tick(maxWait), + heartbeat: clock.NewTicker(maxWait), stopCh: make(chan struct{}), waitingForAddCh: make(chan *waitFor, 1000), metrics: newRetryMetrics(name), @@ -67,10 +67,7 @@ type delayingType struct { stopCh chan struct{} // heartbeat ensures we wait no more than maxWait before firing - // - // TODO: replace with Ticker (and add to clock) so this can be cleaned up. - // clock.Tick will leak. - heartbeat <-chan time.Time + heartbeat clock.Ticker // waitingForAddCh is a buffered channel that feeds waitingForAdd waitingForAddCh chan *waitFor @@ -138,6 +135,7 @@ func (pq waitForPriorityQueue) Peek() interface{} { func (q *delayingType) ShutDown() { q.Interface.ShutDown() close(q.stopCh) + q.heartbeat.Stop() } // AddAfter adds the given item to the work queue after the given delay @@ -209,7 +207,7 @@ func (q *delayingType) waitingLoop() { case <-q.stopCh: return - case <-q.heartbeat: + case <-q.heartbeat.C(): // continue the loop, which will add ready items case <-nextReadyAt: diff --git a/vendor/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go b/vendor/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go index 32d7fc906..3fbe07d0d 100644 --- a/vendor/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go +++ b/vendor/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go @@ -30,7 +30,7 @@ func TestRateLimitingQueue(t *testing.T) { delayingQueue := &delayingType{ Interface: New(), clock: fakeClock, - heartbeat: fakeClock.Tick(maxWait), + heartbeat: fakeClock.NewTicker(maxWait), stopCh: make(chan struct{}), waitingForAddCh: make(chan *waitFor, 1000), metrics: newRetryMetrics(""), diff --git a/vendor/k8s.io/code-generator/Godeps/Godeps.json b/vendor/k8s.io/code-generator/Godeps/Godeps.json index 30ee4a3bf..021cf1458 100644 --- a/vendor/k8s.io/code-generator/Godeps/Godeps.json +++ b/vendor/k8s.io/code-generator/Godeps/Godeps.json @@ -1,6 +1,6 @@ { "ImportPath": "k8s.io/code-generator", - "GoVersion": "go1.9", + "GoVersion": "go1.10", "GodepVersion": "v80", "Packages": [ "./..." @@ -260,11 +260,11 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/generators", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/code-generator/SECURITY_CONTACTS b/vendor/k8s.io/code-generator/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/code-generator/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/install/install.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/install/install.go index b5182d690..d056c5b78 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/install/install.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/code-generator/_examples/apiserver/apis/example" "k8s.io/code-generator/_examples/apiserver/apis/example/v1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: example.SchemeGroupVersion.Group, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: example.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(example.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/doc.go index 242d3904d..5b6bd5b30 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/doc.go @@ -15,6 +15,7 @@ limitations under the License. */ // +k8s:deepcopy-gen=package +// +k8s:defaulter-gen=TypeMeta // +k8s:conversion-gen=k8s.io/code-generator/_examples/apiserver/apis/example // +groupName=example.apiserver.code-generator.k8s.io package v1 diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.conversion.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.conversion.go index 66667f1b8..811031685 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.deepcopy.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.deepcopy.go index 1e4402a82..dae52ff12 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.defaults.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/zz_generated.deepcopy.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/zz_generated.deepcopy.go index 291de95fc..980112fa8 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/zz_generated.deepcopy.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/install/install.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/install/install.go index ef241a33f..1e786f5c5 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/install/install.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/code-generator/_examples/apiserver/apis/example2" "k8s.io/code-generator/_examples/apiserver/apis/example2/v1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: example2.SchemeGroupVersion.Group, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: example2.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(example2.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/doc.go index 41e271d22..36bd4549c 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/doc.go @@ -15,6 +15,7 @@ limitations under the License. */ // +k8s:deepcopy-gen=package +// +k8s:defaulter-gen=TypeMeta // +groupName=example.test.apiserver.code-generator.k8s.io // +k8s:conversion-gen=k8s.io/code-generator/_examples/apiserver/apis/example2 // +groupGoName=SecondExample diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.conversion.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.conversion.go index e73a0f630..88bf603d0 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.deepcopy.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.deepcopy.go index 1e4402a82..dae52ff12 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.defaults.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/zz_generated.deepcopy.go b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/zz_generated.deepcopy.go index 284ecd2da..f9b317e57 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/zz_generated.deepcopy.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/apis/example2/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/clientset.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/clientset.go index 0cb86bf5c..ff88d121c 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/clientset.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package internalversion import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -78,7 +77,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/doc.go index 50398f9ef..6c970b092 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/clientset_generated.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/clientset_generated.go index efc0095b8..37f1b724d 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/clientset_generated.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,9 +43,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -55,7 +56,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/register.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/register.go index ef0ba8fc2..58b47c9fa 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/register.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/register.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/register.go index e3b2cf663..97b03068e 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/register.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,10 +19,6 @@ limitations under the License. package scheme import ( - os "os" - - announced "k8s.io/apimachinery/pkg/apimachinery/announced" - registered "k8s.io/apimachinery/pkg/apimachinery/registered" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -35,16 +31,13 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) -var Registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) -var GroupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - func init() { v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - Install(GroupFactoryRegistry, Registry, Scheme) + Install(Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - example.Install(groupFactoryRegistry, registry, scheme) - secondexample.Install(groupFactoryRegistry, registry, scheme) +func Install(scheme *runtime.Scheme) { + example.Install(scheme) + secondexample.Install(scheme) } diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/example_client.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/example_client.go index e99d41f98..61d99cad0 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/example_client.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *ExampleClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("example.apiserver.code-generator.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("example.apiserver.code-generator.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("example.apiserver.code-generator.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_example_client.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_example_client.go index 71e9e11cb..90564e449 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_example_client.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_testtype.go index 4f268fb81..7b247ca95 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example.TestTypeList, if label == nil { label = labels.Everything() } - list := &example.TestTypeList{} + list := &example.TestTypeList{ListMeta: obj.(*example.TestTypeList).ListMeta} for _, item := range obj.(*example.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/generated_expansion.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/generated_expansion.go index 0cdfc3128..50bdbd254 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/generated_expansion.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/testtype.go index 6cfbcb36d..d19392e85 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/example2_client.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/example2_client.go index b0e673a83..0fcc7baa4 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/example2_client.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *SecondExampleClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("example.test.apiserver.code-generator.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("example.test.apiserver.code-generator.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("example.test.apiserver.code-generator.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_example2_client.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_example2_client.go index 91751c249..235305e9d 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_example2_client.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_testtype.go index 3e9e6c7a8..2890ff19d 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example2.TestTypeList if label == nil { label = labels.Everything() } - list := &example2.TestTypeList{} + list := &example2.TestTypeList{ListMeta: obj.(*example2.TestTypeList).ListMeta} for _, item := range obj.(*example2.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/generated_expansion.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/generated_expansion.go index 0cdfc3128..50bdbd254 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/generated_expansion.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/testtype.go index 77ab9a342..1a2ca7891 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/clientset.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/clientset.go index c0d337d2e..8ba9799f5 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/clientset.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package versioned import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -94,7 +93,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/doc.go index 006b79214..41721ca52 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/clientset_generated.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/clientset_generated.go index fe657f08e..6dce4fed4 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/clientset_generated.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,9 +43,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -55,7 +56,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/register.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/register.go index 37c3ae6f8..79e200500 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/register.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/register.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/register.go index 7c7daa6a2..16f0196a8 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/register.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/example_client.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/example_client.go index 4cead71e4..743c8ded2 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/example_client.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_example_client.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_example_client.go index c8bbfe7c4..509a5b427 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_example_client.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_testtype.go index a0779aaef..100de1809 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example_v1.TestTypeLi if label == nil { label = labels.Everything() } - list := &example_v1.TestTypeList{} + list := &example_v1.TestTypeList{ListMeta: obj.(*example_v1.TestTypeList).ListMeta} for _, item := range obj.(*example_v1.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/generated_expansion.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/generated_expansion.go index 3f19f4e33..d513810d0 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/generated_expansion.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/testtype.go index 0e51af495..d9aa3c5d6 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/example2_client.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/example2_client.go index c245b0716..1271c0f19 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/example2_client.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/doc.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/doc.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go index 2c52a1445..1820e182c 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_testtype.go index 9b005136f..296975e4d 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example2_v1.TestTypeL if label == nil { label = labels.Everything() } - list := &example2_v1.TestTypeList{} + list := &example2_v1.TestTypeList{ListMeta: obj.(*example2_v1.TestTypeList).ListMeta} for _, item := range obj.(*example2_v1.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/generated_expansion.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/generated_expansion.go index 3f19f4e33..d513810d0 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/generated_expansion.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/testtype.go index 21e7e0805..f199ee092 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/interface.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/interface.go index e014cde14..9cc5d1b0a 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/interface.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/interface.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/interface.go index ae5abf354..1ccc8f3ca 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/interface.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/testtype.go index d8cdead8b..84fc62975 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/interface.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/interface.go index 7aef7a4e2..3a791dd0f 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/interface.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/interface.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/interface.go index ae5abf354..1ccc8f3ca 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/interface.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/testtype.go index 48d098232..1d366be5a 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/factory.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/factory.go index 767191e1b..fc4aa0d39 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/factory.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -33,12 +33,16 @@ import ( internalinterfaces "k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client versioned.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -46,23 +50,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -111,7 +154,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/generic.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/generic.go index e1273ab31..aee8fad34 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/generic.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces/factory_interfaces.go index 988e57b54..6318f5284 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/interface.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/interface.go index 4f0aae2fd..d2a36b3c8 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/interface.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/interface.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/interface.go index 1ac865c7a..0fd5f8c3b 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/interface.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/testtype.go index f6991dfdd..3745a315d 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/interface.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/interface.go index 843463ddd..9a5b411a1 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/interface.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/interface.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/interface.go index 1ac865c7a..0fd5f8c3b 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/interface.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/testtype.go index 613fd6933..51518210d 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/factory.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/factory.go index 737d5227f..ca6d4defe 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/factory.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -33,12 +33,16 @@ import ( internalinterfaces "k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client internalversion.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -46,23 +50,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client internalversion.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -111,7 +154,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/generic.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/generic.go index d0822bbb1..046ccac95 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/generic.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces/factory_interfaces.go index 80e3603a0..03c679244 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/expansion_generated.go b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/expansion_generated.go index 6d32d9754..4bb87150c 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/expansion_generated.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/testtype.go index 184c1649a..9daa91bbc 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/v1/expansion_generated.go b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/v1/expansion_generated.go index c5f4333d5..0192e05f0 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/v1/expansion_generated.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/v1/testtype.go index 9eee6a69e..a9b3d87c0 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/expansion_generated.go b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/expansion_generated.go index 6d32d9754..4bb87150c 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/expansion_generated.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/testtype.go index 24659a2d6..724e63871 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/expansion_generated.go b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/expansion_generated.go index c5f4333d5..0192e05f0 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/expansion_generated.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/testtype.go index 64c5bb884..8aa178af8 100644 --- a/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/doc.go b/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/doc.go index 08f1279fb..e6614c0da 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/doc.go +++ b/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/doc.go @@ -15,5 +15,6 @@ limitations under the License. */ // +k8s:deepcopy-gen=package +// +k8s:defaulter-gen=TypeMeta // +groupName=example.crd.code-generator.k8s.io package v1 diff --git a/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/types.go b/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/types.go index 5c2ebc4d6..d79ea38b7 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/types.go +++ b/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/types.go @@ -45,3 +45,30 @@ type TestTypeList struct { type TestTypeStatus struct { Blah string } + +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type ClusterTestTypeList struct { + metav1.TypeMeta + metav1.ListMeta + Items []ClusterTestType +} + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/kubernetes/pkg/apis/autoscaling.Scale +// +genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/kubernetes/pkg/apis/autoscaling.Scale,result=k8s.io/kubernetes/pkg/apis/autoscaling.Scale + +type ClusterTestType struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + // +optional + Status ClusterTestTypeStatus `json:"status,omitempty"` +} + +type ClusterTestTypeStatus struct { + Blah string +} diff --git a/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.deepcopy.go b/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.deepcopy.go index 1e4402a82..a3b4bfa9c 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,82 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterTestType) DeepCopyInto(out *ClusterTestType) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterTestType. +func (in *ClusterTestType) DeepCopy() *ClusterTestType { + if in == nil { + return nil + } + out := new(ClusterTestType) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterTestType) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterTestTypeList) DeepCopyInto(out *ClusterTestTypeList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterTestType, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterTestTypeList. +func (in *ClusterTestTypeList) DeepCopy() *ClusterTestTypeList { + if in == nil { + return nil + } + out := new(ClusterTestTypeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterTestTypeList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterTestTypeStatus) DeepCopyInto(out *ClusterTestTypeStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterTestTypeStatus. +func (in *ClusterTestTypeStatus) DeepCopy() *ClusterTestTypeStatus { + if in == nil { + return nil + } + out := new(ClusterTestTypeStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestType) DeepCopyInto(out *TestType) { *out = *in diff --git a/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.defaults.go b/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.defaults.go new file mode 100644 index 000000000..cce2e603a --- /dev/null +++ b/vendor/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.defaults.go @@ -0,0 +1,32 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/doc.go b/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/doc.go index 702b71634..6521d83ff 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/doc.go +++ b/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/doc.go @@ -15,6 +15,7 @@ limitations under the License. */ // +k8s:deepcopy-gen=package +// +k8s:defaulter-gen=TypeMeta // +groupName=example.test.crd.code-generator.k8s.io // +groupGoName=SecondExample package v1 diff --git a/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.deepcopy.go b/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.deepcopy.go index 1e4402a82..dae52ff12 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.defaults.go b/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.defaults.go new file mode 100644 index 000000000..cce2e603a --- /dev/null +++ b/vendor/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.defaults.go @@ -0,0 +1,32 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/clientset.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/clientset.go index fe1447d50..034e06ad0 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/clientset.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package versioned import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -94,7 +93,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/doc.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/doc.go index 006b79214..41721ca52 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/doc.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/clientset_generated.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/clientset_generated.go index ab158f772..4ad8bba75 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/clientset_generated.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,9 +43,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -55,7 +56,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/doc.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/doc.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/register.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/register.go index 08ebf3b3c..d91e79dac 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/register.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/doc.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/doc.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/register.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/register.go index 1a2abe6a0..7a5ad4f86 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/register.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/clustertesttype.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/clustertesttype.go new file mode 100644 index 000000000..a55b859e1 --- /dev/null +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/clustertesttype.go @@ -0,0 +1,193 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1 "k8s.io/code-generator/_examples/crd/apis/example/v1" + scheme "k8s.io/code-generator/_examples/crd/clientset/versioned/scheme" + autoscaling "k8s.io/kubernetes/pkg/apis/autoscaling" +) + +// ClusterTestTypesGetter has a method to return a ClusterTestTypeInterface. +// A group's client should implement this interface. +type ClusterTestTypesGetter interface { + ClusterTestTypes() ClusterTestTypeInterface +} + +// ClusterTestTypeInterface has methods to work with ClusterTestType resources. +type ClusterTestTypeInterface interface { + Create(*v1.ClusterTestType) (*v1.ClusterTestType, error) + Update(*v1.ClusterTestType) (*v1.ClusterTestType, error) + UpdateStatus(*v1.ClusterTestType) (*v1.ClusterTestType, error) + Delete(name string, options *meta_v1.DeleteOptions) error + DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error + Get(name string, options meta_v1.GetOptions) (*v1.ClusterTestType, error) + List(opts meta_v1.ListOptions) (*v1.ClusterTestTypeList, error) + Watch(opts meta_v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ClusterTestType, err error) + GetScale(clusterTestTypeName string, options meta_v1.GetOptions) (*autoscaling.Scale, error) + UpdateScale(clusterTestTypeName string, scale *autoscaling.Scale) (*autoscaling.Scale, error) + + ClusterTestTypeExpansion +} + +// clusterTestTypes implements ClusterTestTypeInterface +type clusterTestTypes struct { + client rest.Interface +} + +// newClusterTestTypes returns a ClusterTestTypes +func newClusterTestTypes(c *ExampleV1Client) *clusterTestTypes { + return &clusterTestTypes{ + client: c.RESTClient(), + } +} + +// Get takes name of the clusterTestType, and returns the corresponding clusterTestType object, and an error if there is any. +func (c *clusterTestTypes) Get(name string, options meta_v1.GetOptions) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Get(). + Resource("clustertesttypes"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ClusterTestTypes that match those selectors. +func (c *clusterTestTypes) List(opts meta_v1.ListOptions) (result *v1.ClusterTestTypeList, err error) { + result = &v1.ClusterTestTypeList{} + err = c.client.Get(). + Resource("clustertesttypes"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested clusterTestTypes. +func (c *clusterTestTypes) Watch(opts meta_v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Resource("clustertesttypes"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a clusterTestType and creates it. Returns the server's representation of the clusterTestType, and an error, if there is any. +func (c *clusterTestTypes) Create(clusterTestType *v1.ClusterTestType) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Post(). + Resource("clustertesttypes"). + Body(clusterTestType). + Do(). + Into(result) + return +} + +// Update takes the representation of a clusterTestType and updates it. Returns the server's representation of the clusterTestType, and an error, if there is any. +func (c *clusterTestTypes) Update(clusterTestType *v1.ClusterTestType) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Put(). + Resource("clustertesttypes"). + Name(clusterTestType.Name). + Body(clusterTestType). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *clusterTestTypes) UpdateStatus(clusterTestType *v1.ClusterTestType) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Put(). + Resource("clustertesttypes"). + Name(clusterTestType.Name). + SubResource("status"). + Body(clusterTestType). + Do(). + Into(result) + return +} + +// Delete takes name of the clusterTestType and deletes it. Returns an error if one occurs. +func (c *clusterTestTypes) Delete(name string, options *meta_v1.DeleteOptions) error { + return c.client.Delete(). + Resource("clustertesttypes"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *clusterTestTypes) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error { + return c.client.Delete(). + Resource("clustertesttypes"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched clusterTestType. +func (c *clusterTestTypes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Patch(pt). + Resource("clustertesttypes"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} + +// GetScale takes name of the clusterTestType, and returns the corresponding autoscaling.Scale object, and an error if there is any. +func (c *clusterTestTypes) GetScale(clusterTestTypeName string, options meta_v1.GetOptions) (result *autoscaling.Scale, err error) { + result = &autoscaling.Scale{} + err = c.client.Get(). + Resource("clustertesttypes"). + Name(clusterTestTypeName). + SubResource("scale"). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// UpdateScale takes the top resource name and the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any. +func (c *clusterTestTypes) UpdateScale(clusterTestTypeName string, scale *autoscaling.Scale) (result *autoscaling.Scale, err error) { + result = &autoscaling.Scale{} + err = c.client.Put(). + Resource("clustertesttypes"). + Name(clusterTestTypeName). + SubResource("scale"). + Body(scale). + Do(). + Into(result) + return +} diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/doc.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/doc.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/example_client.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/example_client.go index 7dcb34bbd..25d80728c 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/example_client.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -27,6 +27,7 @@ import ( type ExampleV1Interface interface { RESTClient() rest.Interface + ClusterTestTypesGetter TestTypesGetter } @@ -35,6 +36,10 @@ type ExampleV1Client struct { restClient rest.Interface } +func (c *ExampleV1Client) ClusterTestTypes() ClusterTestTypeInterface { + return newClusterTestTypes(c) +} + func (c *ExampleV1Client) TestTypes(namespace string) TestTypeInterface { return newTestTypes(c, namespace) } diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/doc.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/doc.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_clustertesttype.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_clustertesttype.go new file mode 100644 index 000000000..66eda8bc2 --- /dev/null +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_clustertesttype.go @@ -0,0 +1,152 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + example_v1 "k8s.io/code-generator/_examples/crd/apis/example/v1" + autoscaling "k8s.io/kubernetes/pkg/apis/autoscaling" +) + +// FakeClusterTestTypes implements ClusterTestTypeInterface +type FakeClusterTestTypes struct { + Fake *FakeExampleV1 +} + +var clustertesttypesResource = schema.GroupVersionResource{Group: "example.crd.code-generator.k8s.io", Version: "v1", Resource: "clustertesttypes"} + +var clustertesttypesKind = schema.GroupVersionKind{Group: "example.crd.code-generator.k8s.io", Version: "v1", Kind: "ClusterTestType"} + +// Get takes name of the clusterTestType, and returns the corresponding clusterTestType object, and an error if there is any. +func (c *FakeClusterTestTypes) Get(name string, options v1.GetOptions) (result *example_v1.ClusterTestType, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(clustertesttypesResource, name), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// List takes label and field selectors, and returns the list of ClusterTestTypes that match those selectors. +func (c *FakeClusterTestTypes) List(opts v1.ListOptions) (result *example_v1.ClusterTestTypeList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(clustertesttypesResource, clustertesttypesKind, opts), &example_v1.ClusterTestTypeList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &example_v1.ClusterTestTypeList{ListMeta: obj.(*example_v1.ClusterTestTypeList).ListMeta} + for _, item := range obj.(*example_v1.ClusterTestTypeList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested clusterTestTypes. +func (c *FakeClusterTestTypes) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(clustertesttypesResource, opts)) +} + +// Create takes the representation of a clusterTestType and creates it. Returns the server's representation of the clusterTestType, and an error, if there is any. +func (c *FakeClusterTestTypes) Create(clusterTestType *example_v1.ClusterTestType) (result *example_v1.ClusterTestType, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(clustertesttypesResource, clusterTestType), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// Update takes the representation of a clusterTestType and updates it. Returns the server's representation of the clusterTestType, and an error, if there is any. +func (c *FakeClusterTestTypes) Update(clusterTestType *example_v1.ClusterTestType) (result *example_v1.ClusterTestType, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(clustertesttypesResource, clusterTestType), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeClusterTestTypes) UpdateStatus(clusterTestType *example_v1.ClusterTestType) (*example_v1.ClusterTestType, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(clustertesttypesResource, "status", clusterTestType), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// Delete takes name of the clusterTestType and deletes it. Returns an error if one occurs. +func (c *FakeClusterTestTypes) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(clustertesttypesResource, name), &example_v1.ClusterTestType{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeClusterTestTypes) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(clustertesttypesResource, listOptions) + + _, err := c.Fake.Invokes(action, &example_v1.ClusterTestTypeList{}) + return err +} + +// Patch applies the patch and returns the patched clusterTestType. +func (c *FakeClusterTestTypes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *example_v1.ClusterTestType, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(clustertesttypesResource, name, data, subresources...), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// GetScale takes name of the clusterTestType, and returns the corresponding scale object, and an error if there is any. +func (c *FakeClusterTestTypes) GetScale(clusterTestTypeName string, options v1.GetOptions) (result *autoscaling.Scale, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetSubresourceAction(clustertesttypesResource, clusterTestTypeName), &autoscaling.Scale{}) + if obj == nil { + return nil, err + } + return obj.(*autoscaling.Scale), err +} + +// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any. +func (c *FakeClusterTestTypes) UpdateScale(clusterTestTypeName string, scale *autoscaling.Scale) (result *autoscaling.Scale, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(clustertesttypesResource, "scale", scale), &autoscaling.Scale{}) + if obj == nil { + return nil, err + } + return obj.(*autoscaling.Scale), err +} diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_example_client.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_example_client.go index 4e99c7cba..e6aa99993 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_example_client.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -28,6 +28,10 @@ type FakeExampleV1 struct { *testing.Fake } +func (c *FakeExampleV1) ClusterTestTypes() v1.ClusterTestTypeInterface { + return &FakeClusterTestTypes{c} +} + func (c *FakeExampleV1) TestTypes(namespace string) v1.TestTypeInterface { return &FakeTestTypes{c, namespace} } diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_testtype.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_testtype.go index 848b529a3..d925d9b39 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_testtype.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example_v1.TestTypeLi if label == nil { label = labels.Everything() } - list := &example_v1.TestTypeList{} + list := &example_v1.TestTypeList{ListMeta: obj.(*example_v1.TestTypeList).ListMeta} for _, item := range obj.(*example_v1.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/generated_expansion.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/generated_expansion.go index 3f19f4e33..3059734a9 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/generated_expansion.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -18,4 +18,6 @@ limitations under the License. package v1 +type ClusterTestTypeExpansion interface{} + type TestTypeExpansion interface{} diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/testtype.go index d1175fe7c..b5b510ff0 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/doc.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/doc.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/example2_client.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/example2_client.go index 71e7cd31a..210b6509f 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/example2_client.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/doc.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/doc.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go index d63405ffe..0d55a6b8e 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_testtype.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_testtype.go index 07d26a277..8a51cbf8a 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_testtype.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example2_v1.TestTypeL if label == nil { label = labels.Everything() } - list := &example2_v1.TestTypeList{} + list := &example2_v1.TestTypeList{ListMeta: obj.(*example2_v1.TestTypeList).ListMeta} for _, item := range obj.(*example2_v1.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/generated_expansion.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/generated_expansion.go index 3f19f4e33..d513810d0 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/generated_expansion.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/testtype.go index 056415cbe..9691956ea 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/interface.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/interface.go index 51440cbc9..10c18944c 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/interface.go +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/clustertesttype.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/clustertesttype.go new file mode 100644 index 000000000..cef599f48 --- /dev/null +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/clustertesttype.go @@ -0,0 +1,88 @@ +/* +Copyright 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + time "time" + + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + example_v1 "k8s.io/code-generator/_examples/crd/apis/example/v1" + versioned "k8s.io/code-generator/_examples/crd/clientset/versioned" + internalinterfaces "k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces" + v1 "k8s.io/code-generator/_examples/crd/listers/example/v1" +) + +// ClusterTestTypeInformer provides access to a shared informer and lister for +// ClusterTestTypes. +type ClusterTestTypeInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ClusterTestTypeLister +} + +type clusterTestTypeInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewClusterTestTypeInformer constructs a new informer for ClusterTestType type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewClusterTestTypeInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredClusterTestTypeInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredClusterTestTypeInformer constructs a new informer for ClusterTestType type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredClusterTestTypeInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExampleV1().ClusterTestTypes().List(options) + }, + WatchFunc: func(options meta_v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExampleV1().ClusterTestTypes().Watch(options) + }, + }, + &example_v1.ClusterTestType{}, + resyncPeriod, + indexers, + ) +} + +func (f *clusterTestTypeInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredClusterTestTypeInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *clusterTestTypeInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&example_v1.ClusterTestType{}, f.defaultInformer) +} + +func (f *clusterTestTypeInformer) Lister() v1.ClusterTestTypeLister { + return v1.NewClusterTestTypeLister(f.Informer().GetIndexer()) +} diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/interface.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/interface.go index 9378a06ba..1e17b1325 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/interface.go +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // ClusterTestTypes returns a ClusterTestTypeInformer. + ClusterTestTypes() ClusterTestTypeInformer // TestTypes returns a TestTypeInformer. TestTypes() TestTypeInformer } @@ -39,6 +41,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// ClusterTestTypes returns a ClusterTestTypeInformer. +func (v *version) ClusterTestTypes() ClusterTestTypeInformer { + return &clusterTestTypeInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + // TestTypes returns a TestTypeInformer. func (v *version) TestTypes() TestTypeInformer { return &testTypeInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/testtype.go index d1e600c9a..04aa78337 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/interface.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/interface.go index cf0d52cc8..9e00c7b80 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/interface.go +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/interface.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/interface.go index 9378a06ba..024352284 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/interface.go +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/testtype.go index 855dd1d75..095237c45 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/factory.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/factory.go index a843ddb9d..7d6d1f934 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/factory.go +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -33,12 +33,16 @@ import ( internalinterfaces "k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client versioned.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -46,23 +50,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -111,7 +154,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/generic.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/generic.go index 2e88773e8..d89bd2a76 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/generic.go +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -54,6 +54,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=example.crd.code-generator.k8s.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("clustertesttypes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Example().V1().ClusterTestTypes().Informer()}, nil case v1.SchemeGroupVersion.WithResource("testtypes"): return &genericInformer{resource: resource.GroupResource(), informer: f.Example().V1().TestTypes().Informer()}, nil diff --git a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces/factory_interfaces.go index e87f58032..02e0d6ac3 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/clustertesttype.go b/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/clustertesttype.go new file mode 100644 index 000000000..584b3b273 --- /dev/null +++ b/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/clustertesttype.go @@ -0,0 +1,65 @@ +/* +Copyright 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "k8s.io/code-generator/_examples/crd/apis/example/v1" +) + +// ClusterTestTypeLister helps list ClusterTestTypes. +type ClusterTestTypeLister interface { + // List lists all ClusterTestTypes in the indexer. + List(selector labels.Selector) (ret []*v1.ClusterTestType, err error) + // Get retrieves the ClusterTestType from the index for a given name. + Get(name string) (*v1.ClusterTestType, error) + ClusterTestTypeListerExpansion +} + +// clusterTestTypeLister implements the ClusterTestTypeLister interface. +type clusterTestTypeLister struct { + indexer cache.Indexer +} + +// NewClusterTestTypeLister returns a new ClusterTestTypeLister. +func NewClusterTestTypeLister(indexer cache.Indexer) ClusterTestTypeLister { + return &clusterTestTypeLister{indexer: indexer} +} + +// List lists all ClusterTestTypes in the indexer. +func (s *clusterTestTypeLister) List(selector labels.Selector) (ret []*v1.ClusterTestType, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ClusterTestType)) + }) + return ret, err +} + +// Get retrieves the ClusterTestType from the index for a given name. +func (s *clusterTestTypeLister) Get(name string) (*v1.ClusterTestType, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("clustertesttype"), name) + } + return obj.(*v1.ClusterTestType), nil +} diff --git a/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/expansion_generated.go b/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/expansion_generated.go index c5f4333d5..2681a29f4 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/expansion_generated.go +++ b/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -18,6 +18,10 @@ limitations under the License. package v1 +// ClusterTestTypeListerExpansion allows custom methods to be added to +// ClusterTestTypeLister. +type ClusterTestTypeListerExpansion interface{} + // TestTypeListerExpansion allows custom methods to be added to // TestTypeLister. type TestTypeListerExpansion interface{} diff --git a/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/testtype.go index c39f5a395..7055b6cc4 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/crd/listers/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/listers/example2/v1/expansion_generated.go b/vendor/k8s.io/code-generator/_examples/crd/listers/example2/v1/expansion_generated.go index c5f4333d5..0192e05f0 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/listers/example2/v1/expansion_generated.go +++ b/vendor/k8s.io/code-generator/_examples/crd/listers/example2/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/_examples/crd/listers/example2/v1/testtype.go b/vendor/k8s.io/code-generator/_examples/crd/listers/example2/v1/testtype.go index cd239c2f9..d3b15c0b9 100644 --- a/vendor/k8s.io/code-generator/_examples/crd/listers/example2/v1/testtype.go +++ b/vendor/k8s.io/code-generator/_examples/crd/listers/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages_test.go b/vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages_test.go index 8154c2eec..f8891bec8 100644 --- a/vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages_test.go +++ b/vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages_test.go @@ -45,12 +45,12 @@ func TestGVPackageFlag(t *testing.T) { args: []string{"foo/bar/v1", "foo/bar/v2", "foo/bar/", "foo/v1"}, expectedGroups: []types.GroupVersions{ {PackageName: "bar", Group: types.Group("bar"), Versions: []types.PackageVersion{ - {"v1", "foo/bar/v1"}, - {"v2", "foo/bar/v2"}, - {"", "foo/bar"}, + {Version: "v1", Package: "foo/bar/v1"}, + {Version: "v2", Package: "foo/bar/v2"}, + {Version: "", Package: "foo/bar"}, }}, {PackageName: "foo", Group: types.Group("foo"), Versions: []types.PackageVersion{ - {"v1", "foo/v1"}, + {Version: "v1", Package: "foo/v1"}, }}, }, }, @@ -59,12 +59,12 @@ func TestGVPackageFlag(t *testing.T) { def: []string{"foo/bar/v1alpha1", "foo/v1"}, expectedGroups: []types.GroupVersions{ {PackageName: "bar", Group: types.Group("bar"), Versions: []types.PackageVersion{ - {"v1", "foo/bar/v1"}, - {"v2", "foo/bar/v2"}, - {"", "foo/bar"}, + {Version: "v1", Package: "foo/bar/v1"}, + {Version: "v2", Package: "foo/bar/v2"}, + {Version: "", Package: "foo/bar"}, }}, {PackageName: "foo", Group: types.Group("foo"), Versions: []types.PackageVersion{ - {"v1", "foo/v1"}, + {Version: "v1", Package: "foo/v1"}, }}, }, }, @@ -72,8 +72,8 @@ func TestGVPackageFlag(t *testing.T) { args: []string{"api/v1", "api"}, expectedGroups: []types.GroupVersions{ {PackageName: "core", Group: types.Group("api"), Versions: []types.PackageVersion{ - {"v1", "core/v1"}, - {"", "core"}, + {Version: "v1", Package: "core/v1"}, + {Version: "", Package: "core"}, }}, }, }, @@ -82,7 +82,7 @@ func TestGVPackageFlag(t *testing.T) { importBasePath: "k8s.io/api", expectedGroups: []types.GroupVersions{ {PackageName: "foo", Group: types.Group("foo"), Versions: []types.PackageVersion{ - {"v1", "k8s.io/api/foo/v1"}, + {Version: "v1", Package: "k8s.io/api/foo/v1"}, }}, }, }, diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go index 74af0b31d..335e995c0 100644 --- a/vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go @@ -44,10 +44,10 @@ func NameSystems() namer.NameSystems { publicNamer := &ExceptionNamer{ Exceptions: map[string]string{ - // these exceptions are used to deconflict the generated code - // you can put your fully qualified package like - // to generate a name that doesn't conflict with your group. - // "k8s.io/apis/events/v1beta1.Event": "EventResource" + // these exceptions are used to deconflict the generated code + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "EventResource" }, KeyFunc: func(t *types.Type) string { return t.Name.Package + "." + t.Name.Name @@ -56,10 +56,10 @@ func NameSystems() namer.NameSystems { } privateNamer := &ExceptionNamer{ Exceptions: map[string]string{ - // these exceptions are used to deconflict the generated code - // you can put your fully qualified package like - // to generate a name that doesn't conflict with your group. - // "k8s.io/apis/events/v1beta1.Event": "eventResource" + // these exceptions are used to deconflict the generated code + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "eventResource" }, KeyFunc: func(t *types.Type) string { return t.Name.Package + "." + t.Name.Name @@ -68,10 +68,10 @@ func NameSystems() namer.NameSystems { } publicPluralNamer := &ExceptionNamer{ Exceptions: map[string]string{ - // these exceptions are used to deconflict the generated code - // you can put your fully qualified package like - // to generate a name that doesn't conflict with your group. - // "k8s.io/apis/events/v1beta1.Event": "EventResource" + // these exceptions are used to deconflict the generated code + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "EventResource" }, KeyFunc: func(t *types.Type) string { return t.Name.Package + "." + t.Name.Name diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go index f77ab0570..f1225acb3 100644 --- a/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go @@ -63,7 +63,7 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) { groupClientPackage := filepath.Join(g.fakeClientsetPackage, "typed", group.PackageName, version.NonEmpty()) fakeGroupClientPackage := filepath.Join(groupClientPackage, "fake") - groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{group.Group, version.Version}]) + groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]) imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", groupAlias, version.NonEmpty(), groupClientPackage))) imports = append(imports, strings.ToLower(fmt.Sprintf("fake%s%s \"%s\"", groupAlias, version.NonEmpty(), fakeGroupClientPackage))) } @@ -125,9 +125,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -137,7 +138,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go index c129a5f4b..bf18c14c6 100644 --- a/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go @@ -146,9 +146,10 @@ func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io. "NewRootWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootWatchAction"}), "NewWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewWatchAction"}), "NewCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateSubresourceAction"}), + "NewRootCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateSubresourceAction"}), "NewUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateSubresourceAction"}), "NewGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetSubresourceAction"}), - "NewListSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewListSubresourceAction"}), + "NewRootGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetSubresourceAction"}), "NewRootUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateSubresourceAction"}), "NewRootPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchAction"}), "NewPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchAction"}), @@ -235,11 +236,8 @@ func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io. } if e.HasVerb("list") { - if e.IsSubresource() { - sw.Do(adjustTemplate(e.VerbName, e.VerbType, listSubresourceTemplate), m) - } else { - sw.Do(adjustTemplate(e.VerbName, e.VerbType, listTemplate), m) - } + + sw.Do(adjustTemplate(e.VerbName, e.VerbType, listTemplate), m) } // TODO: Figure out schemantic for watching a sub-resource. @@ -322,19 +320,6 @@ func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type } ` -var listSubresourceTemplate = ` -// List takes label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors. -func (c *Fake$.type|publicPlural$) List($.type|private$Name string, opts $.ListOptions|raw$) (result *$.resultType|raw$List, err error) { - obj, err := c.Fake. - $if .namespaced$Invokes($.NewListSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", $.type|allLowercasePlural$Kind, c.ns, opts), &$.resultType|raw$List{}) - $else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), &$.resultType|raw$List{})$end$ - if obj == nil { - return nil, err - } - return obj.(*$.resultType|raw$List), err -} -` - var listUsingOptionsTemplate = ` // List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors. func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type|raw$List, err error) { @@ -349,7 +334,7 @@ func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type if label == nil { label = $.Everything|raw$() } - list := &$.type|raw$List{} + list := &$.type|raw$List{ListMeta: obj.(*$.type|raw$List).ListMeta} for _, item := range obj.(*$.type|raw$List).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) @@ -377,7 +362,7 @@ var getSubresourceTemplate = ` func (c *Fake$.type|publicPlural$) Get($.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) { obj, err := c.Fake. $if .namespaced$Invokes($.NewGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, "$.subresourcePath$", $.type|private$Name), &$.resultType|raw${}) - $else$Invokes($.NewRootGetAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name), &$.resultType|raw${})$end$ + $else$Invokes($.NewRootGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name), &$.resultType|raw${})$end$ if obj == nil { return nil, err } @@ -423,7 +408,7 @@ var createSubresourceTemplate = ` func (c *Fake$.type|publicPlural$) Create($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { obj, err := c.Fake. $if .namespaced$Invokes($.NewCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", c.ns, $.inputType|private$), &$.resultType|raw${}) - $else$Invokes($.NewRootCreateAction|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$), &$.resultType|raw${})$end$ + $else$Invokes($.NewRootCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$ if obj == nil { return nil, err } @@ -449,7 +434,7 @@ var updateSubresourceTemplate = ` func (c *Fake$.type|publicPlural$) Update($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { obj, err := c.Fake. $if .namespaced$Invokes($.NewUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", c.ns, $.inputType|private$), &$.inputType|raw${}) - $else$Invokes($.NewRootUpdateAction|raw$($.type|allLowercasePlural$Resource, $.type|private$), &$.type|raw${})$end$ + $else$Invokes($.NewRootUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$ if obj == nil { return nil, err } diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go index de5264660..18ec09ac6 100644 --- a/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go @@ -59,7 +59,7 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) { for _, group := range g.groups { for _, version := range group.Versions { typedClientPath := filepath.Join(g.clientsetPackage, "typed", group.PackageName, version.NonEmpty()) - groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{group.Group, version.Version}]) + groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]) imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", groupAlias, version.NonEmpty(), typedClientPath))) } } @@ -83,7 +83,6 @@ func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Wr "NewDiscoveryClientForConfigOrDie": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClientForConfigOrDie"}), "NewDiscoveryClient": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClient"}), "flowcontrolNewTokenBucketRateLimiter": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/flowcontrol", Name: "NewTokenBucketRateLimiter"}), - "glogErrorf": c.Universe.Function(types.Name{Package: "github.com/golang/glog", Name: "Errorf"}), } sw.Do(clientsetInterface, m) sw.Do(clientsetTemplate, m) @@ -163,7 +162,6 @@ $range .allGroups$ cs.$.LowerCaseGroupGoName$$.Version$, err =$.PackageAlias$ $end$ cs.DiscoveryClient, err = $.NewDiscoveryClientForConfig|raw$(&configShallowCopy) if err!=nil { - $.glogErrorf|raw$("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go index 8e569a84f..fd59715c4 100644 --- a/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go @@ -210,17 +210,12 @@ func New(c $.restRESTClientInterface|raw$) *$.GroupGoName$$.Version$Client { var setInternalVersionClientDefaultsTemplate = ` func setConfigDefaults(config *$.restConfig|raw$) error { - g, err := scheme.Registry.Group("$.groupName$") - if err != nil { - return err - } - config.APIPath = $.apiPath$ if config.UserAgent == "" { config.UserAgent = $.restDefaultKubernetesUserAgent|raw$() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("$.groupName$")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("$.groupName$")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go index 6000e40da..dd9afadbf 100644 --- a/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go @@ -62,7 +62,7 @@ func (g *GenScheme) Imports(c *generator.Context) (imports []string) { for _, group := range g.Groups { for _, version := range group.Versions { packagePath := g.InputPackages[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}] - groupAlias := strings.ToLower(g.GroupGoNames[clientgentypes.GroupVersion{group.Group, version.Version}]) + groupAlias := strings.ToLower(g.GroupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]) if g.CreateRegistry { // import the install package for internal clientsets instead of the type package with register.go if version.Version != "" { @@ -86,26 +86,21 @@ func (g *GenScheme) GenerateType(c *generator.Context, t *types.Type, w io.Write allInstallGroups := clientgentypes.ToGroupInstallPackages(g.Groups, g.GroupGoNames) m := map[string]interface{}{ - "allGroupVersions": allGroupVersions, - "allInstallGroups": allInstallGroups, - "customRegister": false, - "osGetenv": c.Universe.Function(types.Name{Package: "os", Name: "Getenv"}), - "runtimeNewParameterCodec": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewParameterCodec"}), - "runtimeNewScheme": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewScheme"}), - "serializerNewCodecFactory": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/serializer", Name: "NewCodecFactory"}), - "runtimeScheme": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "Scheme"}), - "schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}), - "metav1AddToGroupVersion": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "AddToGroupVersion"}), - "announcedAPIGroupFactoryRegistry": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/announced", Name: "APIGroupFactoryRegistry"}), - "registeredNewOrDie": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/registered", Name: "NewOrDie"}), - "registeredAPIRegistrationManager": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/registered", Name: "APIRegistrationManager"}), + "allGroupVersions": allGroupVersions, + "allInstallGroups": allInstallGroups, + "customRegister": false, + "runtimeNewParameterCodec": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewParameterCodec"}), + "runtimeNewScheme": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewScheme"}), + "serializerNewCodecFactory": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/serializer", Name: "NewCodecFactory"}), + "runtimeScheme": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "Scheme"}), + "schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}), + "metav1AddToGroupVersion": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "AddToGroupVersion"}), } globals := map[string]string{ - "Scheme": "Scheme", - "Codecs": "Codecs", - "ParameterCodec": "ParameterCodec", - "Registry": "Registry", - "GroupFactoryRegistry": "GroupFactoryRegistry", + "Scheme": "Scheme", + "Codecs": "Codecs", + "ParameterCodec": "ParameterCodec", + "Registry": "Registry", } for k, v := range globals { if g.PrivateScheme { @@ -139,21 +134,18 @@ var $.ParameterCodec$ = $.runtimeNewParameterCodec|raw$($.Scheme$) ` var registryRegistration = ` -var $.Registry$ = $.registeredNewOrDie|raw$($.osGetenv|raw$("KUBE_API_VERSIONS")) -var $.GroupFactoryRegistry$ = make($.announcedAPIGroupFactoryRegistry|raw$) - func init() { $.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"}) - Install($.GroupFactoryRegistry$, $.Registry$, $.Scheme$) + Install($.Scheme$) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry $.announcedAPIGroupFactoryRegistry|raw$, registry *$.registeredAPIRegistrationManager|raw$, scheme *$.runtimeScheme|raw$) { +func Install(scheme *$.runtimeScheme|raw$) { $- range .allInstallGroups$ - $.InstallPackageAlias$.Install(groupFactoryRegistry, registry, scheme) + $.InstallPackageAlias$.Install(scheme) $- end$ $if .customRegister$ - ExtraInstall(groupFactoryRegistry, registry, scheme) + ExtraInstall(scheme) $end -$ } ` diff --git a/vendor/k8s.io/code-generator/cmd/conversion-gen/args/args.go b/vendor/k8s.io/code-generator/cmd/conversion-gen/args/args.go index 3b7b0123d..07ce6e72b 100644 --- a/vendor/k8s.io/code-generator/cmd/conversion-gen/args/args.go +++ b/vendor/k8s.io/code-generator/cmd/conversion-gen/args/args.go @@ -42,7 +42,7 @@ type CustomArgs struct { // generator pick up manually written conversion funcs from external packages. ExtraPeerDirs []string - // Skipunsafe indicates whether to generate unsafe conversions to improve the efficiency + // SkipUnsafe indicates whether to generate unsafe conversions to improve the efficiency // of these operations. The unsafe operation is a direct pointer assignment via unsafe // (within the allowed uses of unsafe) and is equivalent to a proposed Golang change to // allow structs that are identical to be assigned to each other. diff --git a/vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go b/vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go index 423577a12..e3b21c670 100644 --- a/vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go +++ b/vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go @@ -116,7 +116,10 @@ func assignGoTypeToProtoPackage(p *protobufPackage, t *types.Type, local, global } return } - global[t.Name] = p + if t.Name.Package == p.PackagePath { + // Associate types only to their own package + global[t.Name] = p + } if _, ok := local[t.Name]; ok { return } diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go index 2a91aaa9e..5c557db73 100644 --- a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go @@ -89,6 +89,7 @@ func (g *factoryGenerator) GenerateType(c *generator.Context, t *types.Type, w i "syncMutex": c.Universe.Type(syncMutex), "timeDuration": c.Universe.Type(timeDuration), "namespaceAll": c.Universe.Type(metav1NamespaceAll), + "object": c.Universe.Type(metav1Object), } sw.Do(sharedInformerFactoryStruct, m) @@ -98,12 +99,16 @@ func (g *factoryGenerator) GenerateType(c *generator.Context, t *types.Type, w i } var sharedInformerFactoryStruct = ` +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client {{.clientSetInterface|raw}} namespace string tweakListOptions {{.interfacesTweakListOptionsFunc|raw}} lock {{.syncMutex|raw}} defaultResync {{.timeDuration|raw}} + customResync map[{{.reflectType|raw}}]{{.timeDuration|raw}} informers map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}} // startedInformers is used for tracking which informers have been started. @@ -111,23 +116,62 @@ type sharedInformerFactory struct { startedInformers map[{{.reflectType|raw}}]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[{{.object|raw}}]{{.timeDuration|raw}}) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, {{.namespaceAll|raw}}, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}, namespace string, tweakListOptions {{.interfacesTweakListOptionsFunc|raw}}) SharedInformerFactory { - return &sharedInformerFactory{ - client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, - defaultResync: defaultResync, - informers: make(map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}}), - startedInformers: make(map[{{.reflectType|raw}}]bool), - } + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}}), + startedInformers: make(map[{{.reflectType|raw}}]bool), + customResync: make(map[{{.reflectType|raw}}]{{.timeDuration|raw}}), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory } // Start initializes all requested informers. @@ -176,7 +220,13 @@ func (f *sharedInformerFactory) InformerFor(obj {{.runtimeObject|raw}}, newFunc if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go index ecefb078c..27d4bd51a 100644 --- a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go @@ -37,5 +37,6 @@ var ( timeDuration = types.Name{Package: "time", Name: "Duration"} v1ListOptions = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"} metav1NamespaceAll = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "NamespaceAll"} + metav1Object = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "Object"} watchInterface = types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"} ) diff --git a/vendor/k8s.io/code-generator/generate-groups.sh b/vendor/k8s.io/code-generator/generate-groups.sh index b92296d96..6707221e4 100755 --- a/vendor/k8s.io/code-generator/generate-groups.sh +++ b/vendor/k8s.io/code-generator/generate-groups.sh @@ -46,7 +46,13 @@ APIS_PKG="$3" GROUPS_WITH_VERSIONS="$4" shift 4 -go install ./$(dirname "${0}")/cmd/{defaulter-gen,client-gen,lister-gen,informer-gen,deepcopy-gen} +( + # To support running this script from anywhere, we have to first cd into this directory + # so we can install the tools. + cd $(dirname "${0}") + go install ./cmd/{defaulter-gen,client-gen,lister-gen,informer-gen,deepcopy-gen} +) + function codegen::join() { local IFS="$1"; shift; echo "$*"; } # enumerate group versions diff --git a/vendor/k8s.io/code-generator/hack/boilerplate.go.txt b/vendor/k8s.io/code-generator/hack/boilerplate.go.txt index 59e740c1e..b7c650da4 100644 --- a/vendor/k8s.io/code-generator/hack/boilerplate.go.txt +++ b/vendor/k8s.io/code-generator/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright YEAR The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/code-generator/hack/update-codegen.sh b/vendor/k8s.io/code-generator/hack/update-codegen.sh index e38a0d92c..767c2ab36 100755 --- a/vendor/k8s.io/code-generator/hack/update-codegen.sh +++ b/vendor/k8s.io/code-generator/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/code-generator/hack/verify-codegen.sh b/vendor/k8s.io/code-generator/hack/verify-codegen.sh index 601a76962..25302228d 100755 --- a/vendor/k8s.io/code-generator/hack/verify-codegen.sh +++ b/vendor/k8s.io/code-generator/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kube-openapi/.gitignore b/vendor/k8s.io/kube-openapi/.gitignore new file mode 100644 index 000000000..e36047774 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/.gitignore @@ -0,0 +1,20 @@ +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 +.glide/ + +# Intellij IDEA files +.idea/ +*.iml +.vscode + diff --git a/vendor/k8s.io/kube-openapi/.travis.yml b/vendor/k8s.io/kube-openapi/.travis.yml new file mode 100644 index 000000000..6c770ec12 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/.travis.yml @@ -0,0 +1,4 @@ +language: go +go_import_path: k8s.io/kube-openapi +script: go test ./pkg/... ./test/... + diff --git a/vendor/k8s.io/kube-openapi/CONTRIBUTING.md b/vendor/k8s.io/kube-openapi/CONTRIBUTING.md new file mode 100644 index 000000000..ef37eb0b6 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/CONTRIBUTING.md @@ -0,0 +1,9 @@ +# Contributing + +Thanks for taking the time to join our community and start contributing! + +The [Contributor Guide](https://github.com/kubernetes/community/blob/master/contributors/guide/README.md) +provides detailed instructions on how to get your ideas and bug fixes seen and accepted. + +Please remember to sign the [CNCF CLA](https://github.com/kubernetes/community/blob/master/CLA.md) and +read and observe the [Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). diff --git a/vendor/k8s.io/kube-openapi/Godeps/Godeps.json b/vendor/k8s.io/kube-openapi/Godeps/Godeps.json new file mode 100644 index 000000000..38032f652 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/Godeps/Godeps.json @@ -0,0 +1,401 @@ +{ + "ImportPath": "k8s.io/kube-openapi", + "GoVersion": "go1.8", + "GodepVersion": "v79", + "Packages": [ + "./..." + ], + "Deps": [ + { + "ImportPath": "bitbucket.org/ww/goautoneg", + "Comment": "null-5", + "Rev": "75cd24fc2f2c2a2088577d12123ddee5f54e0675" + }, + { + "ImportPath": "github.com/NYTimes/gziphandler", + "Rev": "56545f4a5d46df9a6648819d1664c3a03a13ffdb" + }, + { + "ImportPath": "github.com/PuerkitoBio/purell", + "Comment": "v1.0.0", + "Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4" + }, + { + "ImportPath": "github.com/PuerkitoBio/urlesc", + "Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e" + }, + { + "ImportPath": "github.com/davecgh/go-spew/spew", + "Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d" + }, + { + "ImportPath": "github.com/emicklei/go-restful", + "Comment": "2.2.0-4-gff4f55a", + "Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46" + }, + { + "ImportPath": "github.com/emicklei/go-restful/log", + "Comment": "2.2.0-4-gff4f55a", + "Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46" + }, + { + "ImportPath": "github.com/ghodss/yaml", + "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" + }, + { + "ImportPath": "github.com/go-openapi/jsonpointer", + "Rev": "46af16f9f7b149af66e5d1bd010e3574dc06de98" + }, + { + "ImportPath": "github.com/go-openapi/jsonreference", + "Rev": "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272" + }, + { + "ImportPath": "github.com/go-openapi/spec", + "Rev": "6aced65f8501fe1217321abf0749d354824ba2ff" + }, + { + "ImportPath": "github.com/go-openapi/swag", + "Rev": "1d0bd113de87027671077d3c71eb3ac5d7dbba72" + }, + { + "ImportPath": "github.com/golang/glog", + "Rev": "44145f04b68cf362d9c4df2182967c2275eaefed" + }, + { + "ImportPath": "github.com/golang/protobuf/proto", + "Rev": "4bd1920723d7b7c925de087aa32e2187708897f7" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes", + "Rev": "4bd1920723d7b7c925de087aa32e2187708897f7" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes/any", + "Rev": "4bd1920723d7b7c925de087aa32e2187708897f7" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes/duration", + "Rev": "4bd1920723d7b7c925de087aa32e2187708897f7" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", + "Rev": "4bd1920723d7b7c925de087aa32e2187708897f7" + }, + { + "ImportPath": "github.com/googleapis/gnostic/OpenAPIv2", + "Rev": "68f4ded48ba9414dab2ae69b3f0d69971da73aa5" + }, + { + "ImportPath": "github.com/googleapis/gnostic/compiler", + "Rev": "68f4ded48ba9414dab2ae69b3f0d69971da73aa5" + }, + { + "ImportPath": "github.com/googleapis/gnostic/extensions", + "Rev": "68f4ded48ba9414dab2ae69b3f0d69971da73aa5" + }, + { + "ImportPath": "github.com/mailru/easyjson/buffer", + "Rev": "d5b7844b561a7bc640052f1b935f7b800330d7e0" + }, + { + "ImportPath": "github.com/mailru/easyjson/jlexer", + "Rev": "d5b7844b561a7bc640052f1b935f7b800330d7e0" + }, + { + "ImportPath": "github.com/mailru/easyjson/jwriter", + "Rev": "d5b7844b561a7bc640052f1b935f7b800330d7e0" + }, + { + "ImportPath": "github.com/onsi/ginkgo", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/config", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/codelocation", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/containernode", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/failer", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/leafnodes", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/remote", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/spec", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/spec_iterator", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/specrunner", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/suite", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/testingtproxy", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/internal/writer", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/reporters", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/reporters/stenographer", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/ginkgo/types", + "Comment": "v1.4.0-4-g11459a8", + "Rev": "11459a886d9cd66b319dac7ef1e917ee221372c9" + }, + { + "ImportPath": "github.com/onsi/gomega", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/format", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/internal/assertion", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/internal/asyncassertion", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/internal/oraclematcher", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/internal/testingtsupport", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/matchers", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/matchers/support/goraph/bipartitegraph", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/matchers/support/goraph/edge", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/matchers/support/goraph/node", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/matchers/support/goraph/util", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/onsi/gomega/types", + "Comment": "v1.2.0-2-gdcabb60", + "Rev": "dcabb60a477c2b6f456df65037cb6708210fbb02" + }, + { + "ImportPath": "github.com/pmezard/go-difflib/difflib", + "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d" + }, + { + "ImportPath": "github.com/spf13/pflag", + "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + }, + { + "ImportPath": "github.com/stretchr/testify/assert", + "Comment": "v1.0-88-ge3a8ff8", + "Rev": "e3a8ff8ce36581f87a15341206f205b1da467059" + }, + { + "ImportPath": "golang.org/x/net/html", + "Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" + }, + { + "ImportPath": "golang.org/x/net/html/atom", + "Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" + }, + { + "ImportPath": "golang.org/x/net/html/charset", + "Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" + }, + { + "ImportPath": "golang.org/x/net/idna", + "Rev": "f2499483f923065a842d38eb4c7f1927e6fc6e6d" + }, + { + "ImportPath": "golang.org/x/sys/unix", + "Rev": "bb24a47a89eac6c1227fbcb2ae37a8b9ed323366" + }, + { + "ImportPath": "golang.org/x/text/cases", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding/charmap", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding/htmlindex", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding/internal", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding/internal/identifier", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding/japanese", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding/korean", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding/simplifiedchinese", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding/traditionalchinese", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/encoding/unicode", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/internal/tag", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/internal/utf8internal", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/language", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/runes", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/secure/bidirule", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/secure/precis", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/transform", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/unicode/bidi", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/unicode/norm", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "golang.org/x/text/width", + "Rev": "2910a502d2bf9e43193af9d68ca516529614eed3" + }, + { + "ImportPath": "gopkg.in/yaml.v2", + "Rev": "53feefa2559fb8dfa8d81baad31be332c97d6c77" + }, + { + "ImportPath": "k8s.io/gengo/args", + "Rev": "75356185a9af8f0464efa792e2e9508d5b4be83c" + }, + { + "ImportPath": "k8s.io/gengo/generator", + "Rev": "75356185a9af8f0464efa792e2e9508d5b4be83c" + }, + { + "ImportPath": "k8s.io/gengo/namer", + "Rev": "75356185a9af8f0464efa792e2e9508d5b4be83c" + }, + { + "ImportPath": "k8s.io/gengo/parser", + "Rev": "75356185a9af8f0464efa792e2e9508d5b4be83c" + }, + { + "ImportPath": "k8s.io/gengo/types", + "Rev": "75356185a9af8f0464efa792e2e9508d5b4be83c" + } + ] +} diff --git a/vendor/k8s.io/kube-openapi/Godeps/Readme b/vendor/k8s.io/kube-openapi/Godeps/Readme new file mode 100644 index 000000000..4cdaa53d5 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/Godeps/Readme @@ -0,0 +1,5 @@ +This directory tree is generated automatically by godep. + +Please do not edit. + +See https://github.com/tools/godep for more information. diff --git a/vendor/k8s.io/kube-openapi/LICENSE b/vendor/k8s.io/kube-openapi/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/k8s.io/kube-openapi/OWNERS b/vendor/k8s.io/kube-openapi/OWNERS new file mode 100755 index 000000000..e8c62bfa2 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/OWNERS @@ -0,0 +1,11 @@ +reviewers: +- yujuhong +- gmarek +- mbohlool +- philips +- seans3 +- apelisse +approvers: +- mbohlool +- lavalamp +- seans3 diff --git a/vendor/k8s.io/kube-openapi/README.md b/vendor/k8s.io/kube-openapi/README.md new file mode 100644 index 000000000..fd448585b --- /dev/null +++ b/vendor/k8s.io/kube-openapi/README.md @@ -0,0 +1,18 @@ +# Kube OpenAPI + +This repo is the home for Kubernetes OpenAPI discovery spec generation. The goal +is to support a subset of OpenAPI features to satisfy kubernetes use-cases but +implement that subset with little to no assumption about the structure of the +code or routes. Thus, there should be no kubernetes specific code in this repo. + + +There are two main parts: + - A model generator that goes through .go files, find and generate model +definitions. + - The spec generator that is responsible for dynamically generate +the final OpenAPI spec using web service routes or combining other +OpenAPI/Json specs. + +## Contributing + +Please see [CONTRIBUTING.md](CONTRIBUTING.md) for instructions on how to contribute. diff --git a/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go b/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go new file mode 100644 index 000000000..f555bddaf --- /dev/null +++ b/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go @@ -0,0 +1,73 @@ +/* +Copyright 2018 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 args + +import ( + "fmt" + + "github.com/spf13/pflag" + "k8s.io/gengo/args" +) + +// CustomArgs is used by the gengo framework to pass args specific to this generator. +type CustomArgs struct { + // ReportFilename is added to CustomArgs for specifying name of report file used + // by API linter. If specified, API rule violations will be printed to report file. + // Otherwise default value "-" will be used which indicates stdout. + ReportFilename string +} + +// NewDefaults returns default arguments for the generator. Returning the arguments instead +// of using default flag parsing allows registering custom arguments afterwards +func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { + // Default() sets a couple of flag default values for example the boilerplate. + // WithoutDefaultFlagParsing() disables implicit addition of command line flags and parsing, + // which allows registering custom arguments afterwards + genericArgs := args.Default().WithoutDefaultFlagParsing() + customArgs := &CustomArgs{} + genericArgs.CustomArgs = customArgs + + // Default value for report filename is "-", which stands for stdout + customArgs.ReportFilename = "-" + // Default value for output file base name + genericArgs.OutputFileBaseName = "openapi_generated" + + return genericArgs, customArgs +} + +// AddFlags add the generator flags to the flag set. +func (c *CustomArgs) AddFlags(fs *pflag.FlagSet) { + fs.StringVarP(&c.ReportFilename, "report-filename", "r", c.ReportFilename, "Name of report file used by API linter to print API violations. Default \"-\" stands for standard output. NOTE that if valid filename other than \"-\" is specified, API linter won't return error on detected API violations. This allows further check of existing API violations without stopping the OpenAPI generation toolchain.") +} + +// Validate checks the given arguments. +func Validate(genericArgs *args.GeneratorArgs) error { + c, ok := genericArgs.CustomArgs.(*CustomArgs) + if !ok { + return fmt.Errorf("input arguments don't contain valid custom arguments") + } + if len(c.ReportFilename) == 0 { + return fmt.Errorf("report filename cannot be empty. specify a valid filename or use \"-\" for stdout") + } + if len(genericArgs.OutputFileBaseName) == 0 { + return fmt.Errorf("output file base name cannot be empty") + } + if len(genericArgs.OutputPackagePath) == 0 { + return fmt.Errorf("output package cannot be empty") + } + return nil +} diff --git a/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go b/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go new file mode 100644 index 000000000..0f7563b10 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 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. +*/ + +// This package generates openAPI definition file to be used in open API spec generation on API servers. To generate +// definition for a specific type or package add "+k8s:openapi-gen=true" tag to the type/package comment lines. To +// exclude a type from a tagged package, add "+k8s:openapi-gen=false" tag to the type comment lines. + +package main + +import ( + "flag" + "log" + + generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args" + "k8s.io/kube-openapi/pkg/generators" + + "github.com/spf13/pflag" +) + +func main() { + genericArgs, customArgs := generatorargs.NewDefaults() + + genericArgs.AddFlags(pflag.CommandLine) + customArgs.AddFlags(pflag.CommandLine) + flag.Set("logtostderr", "true") + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) + pflag.Parse() + + if err := generatorargs.Validate(genericArgs); err != nil { + log.Fatalf("Arguments validation error: %v", err) + } + + // Generates the code for the OpenAPIDefinitions. + if err := genericArgs.Execute( + generators.NameSystems(), + generators.DefaultNameSystem(), + generators.Packages, + ); err != nil { + log.Fatalf("OpenAPI code generation error: %v", err) + } + log.Println("Code for OpenAPI definitions generated") +} diff --git a/vendor/k8s.io/kube-openapi/code-of-conduct.md b/vendor/k8s.io/kube-openapi/code-of-conduct.md new file mode 100644 index 000000000..0d15c00cf --- /dev/null +++ b/vendor/k8s.io/kube-openapi/code-of-conduct.md @@ -0,0 +1,3 @@ +# Kubernetes Community Code of Conduct + +Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) diff --git a/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator.go b/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator.go new file mode 100644 index 000000000..cbeb3ef8a --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator.go @@ -0,0 +1,391 @@ +/* +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 aggregator + +import ( + "encoding/json" + "fmt" + "reflect" + "strings" + + "github.com/go-openapi/spec" + + "k8s.io/kube-openapi/pkg/util" +) + +const ( + definitionPrefix = "#/definitions/" +) + +// Run a walkRefCallback method on all references of an OpenAPI spec +type referenceWalker struct { + // walkRefCallback will be called on each reference and the return value + // will replace that reference. This will allow the callers to change + // all/some references of an spec (e.g. useful in renaming definitions). + walkRefCallback func(ref spec.Ref) spec.Ref + + // The spec to walk through. + root *spec.Swagger + + // Keep track of visited references + alreadyVisited map[string]bool +} + +func walkOnAllReferences(walkRef func(ref spec.Ref) spec.Ref, sp *spec.Swagger) { + walker := &referenceWalker{walkRefCallback: walkRef, root: sp, alreadyVisited: map[string]bool{}} + walker.Start() +} + +func (s *referenceWalker) walkRef(ref spec.Ref) spec.Ref { + refStr := ref.String() + // References that start with #/definitions/ has a definition + // inside the same spec file. If that is the case, walk through + // those definitions too. + // We do not support external references yet. + if !s.alreadyVisited[refStr] && strings.HasPrefix(refStr, definitionPrefix) { + s.alreadyVisited[refStr] = true + k := refStr[len(definitionPrefix):] + def := s.root.Definitions[k] + s.walkSchema(&def) + // Make sure we don't assign to nil map + if s.root.Definitions == nil { + s.root.Definitions = spec.Definitions{} + } + s.root.Definitions[k] = def + } + return s.walkRefCallback(ref) +} + +func (s *referenceWalker) walkSchema(schema *spec.Schema) { + if schema == nil { + return + } + schema.Ref = s.walkRef(schema.Ref) + for k, v := range schema.Definitions { + s.walkSchema(&v) + schema.Definitions[k] = v + } + for k, v := range schema.Properties { + s.walkSchema(&v) + schema.Properties[k] = v + } + for k, v := range schema.PatternProperties { + s.walkSchema(&v) + schema.PatternProperties[k] = v + } + for i := range schema.AllOf { + s.walkSchema(&schema.AllOf[i]) + } + for i := range schema.AnyOf { + s.walkSchema(&schema.AnyOf[i]) + } + for i := range schema.OneOf { + s.walkSchema(&schema.OneOf[i]) + } + if schema.Not != nil { + s.walkSchema(schema.Not) + } + if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil { + s.walkSchema(schema.AdditionalProperties.Schema) + } + if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil { + s.walkSchema(schema.AdditionalItems.Schema) + } + if schema.Items != nil { + if schema.Items.Schema != nil { + s.walkSchema(schema.Items.Schema) + } + for i := range schema.Items.Schemas { + s.walkSchema(&schema.Items.Schemas[i]) + } + } +} + +func (s *referenceWalker) walkParams(params []spec.Parameter) { + if params == nil { + return + } + for _, param := range params { + param.Ref = s.walkRef(param.Ref) + s.walkSchema(param.Schema) + if param.Items != nil { + param.Items.Ref = s.walkRef(param.Items.Ref) + } + } +} + +func (s *referenceWalker) walkResponse(resp *spec.Response) { + if resp == nil { + return + } + resp.Ref = s.walkRef(resp.Ref) + s.walkSchema(resp.Schema) +} + +func (s *referenceWalker) walkOperation(op *spec.Operation) { + if op == nil { + return + } + s.walkParams(op.Parameters) + if op.Responses == nil { + return + } + s.walkResponse(op.Responses.Default) + for _, r := range op.Responses.StatusCodeResponses { + s.walkResponse(&r) + } +} + +func (s *referenceWalker) Start() { + if s.root.Paths == nil { + return + } + for _, pathItem := range s.root.Paths.Paths { + s.walkParams(pathItem.Parameters) + s.walkOperation(pathItem.Delete) + s.walkOperation(pathItem.Get) + s.walkOperation(pathItem.Head) + s.walkOperation(pathItem.Options) + s.walkOperation(pathItem.Patch) + s.walkOperation(pathItem.Post) + s.walkOperation(pathItem.Put) + } +} + +// usedDefinitionForSpec returns a map with all used definitions in the provided spec as keys and true as values. +func usedDefinitionForSpec(sp *spec.Swagger) map[string]bool { + usedDefinitions := map[string]bool{} + walkOnAllReferences(func(ref spec.Ref) spec.Ref { + if refStr := ref.String(); refStr != "" && strings.HasPrefix(refStr, definitionPrefix) { + usedDefinitions[refStr[len(definitionPrefix):]] = true + } + return ref + }, sp) + return usedDefinitions +} + +// FilterSpecByPaths removes unnecessary paths and definitions used by those paths. +// i.e. if a Path removed by this function, all definitions used by it and not used +// anywhere else will also be removed. +func FilterSpecByPaths(sp *spec.Swagger, keepPathPrefixes []string) { + // Walk all references to find all used definitions. This function + // want to only deal with unused definitions resulted from filtering paths. + // Thus a definition will be removed only if it has been used before but + // it is unused because of a path prune. + initialUsedDefinitions := usedDefinitionForSpec(sp) + + // First remove unwanted paths + prefixes := util.NewTrie(keepPathPrefixes) + orgPaths := sp.Paths + if orgPaths == nil { + return + } + sp.Paths = &spec.Paths{ + VendorExtensible: orgPaths.VendorExtensible, + Paths: map[string]spec.PathItem{}, + } + for path, pathItem := range orgPaths.Paths { + if !prefixes.HasPrefix(path) { + continue + } + sp.Paths.Paths[path] = pathItem + } + + // Walk all references to find all definition references. + usedDefinitions := usedDefinitionForSpec(sp) + + // Remove unused definitions + orgDefinitions := sp.Definitions + sp.Definitions = spec.Definitions{} + for k, v := range orgDefinitions { + if usedDefinitions[k] || !initialUsedDefinitions[k] { + sp.Definitions[k] = v + } + } +} + +func renameDefinition(s *spec.Swagger, old, new string) { + oldRef := definitionPrefix + old + newRef := definitionPrefix + new + walkOnAllReferences(func(ref spec.Ref) spec.Ref { + if ref.String() == oldRef { + return spec.MustCreateRef(newRef) + } + return ref + }, s) + // Make sure we don't assign to nil map + if s.Definitions == nil { + s.Definitions = spec.Definitions{} + } + s.Definitions[new] = s.Definitions[old] + delete(s.Definitions, old) +} + +// MergeSpecsIgnorePathConflict is the same as MergeSpecs except it will ignore any path +// conflicts by keeping the paths of destination. It will rename definition conflicts. +func MergeSpecsIgnorePathConflict(dest, source *spec.Swagger) error { + return mergeSpecs(dest, source, true, true) +} + +// MergeSpecsFailOnDefinitionConflict is differ from MergeSpecs as it fails if there is +// a definition conflict. +func MergeSpecsFailOnDefinitionConflict(dest, source *spec.Swagger) error { + return mergeSpecs(dest, source, false, false) +} + +// MergeSpecs copies paths and definitions from source to dest, rename definitions if needed. +// dest will be mutated, and source will not be changed. It will fail on path conflicts. +func MergeSpecs(dest, source *spec.Swagger) error { + return mergeSpecs(dest, source, true, false) +} + +func mergeSpecs(dest, source *spec.Swagger, renameModelConflicts, ignorePathConflicts bool) (err error) { + specCloned := false + // Paths may be empty, due to [ACL constraints](http://goo.gl/8us55a#securityFiltering). + if source.Paths == nil { + // When a source spec does not have any path, that means none of the definitions + // are used thus we should not do anything + return nil + } + if dest.Paths == nil { + dest.Paths = &spec.Paths{} + } + if ignorePathConflicts { + keepPaths := []string{} + hasConflictingPath := false + for k := range source.Paths.Paths { + if _, found := dest.Paths.Paths[k]; !found { + keepPaths = append(keepPaths, k) + } else { + hasConflictingPath = true + } + } + if len(keepPaths) == 0 { + // There is nothing to merge. All paths are conflicting. + return nil + } + if hasConflictingPath { + source, err = CloneSpec(source) + if err != nil { + return err + } + specCloned = true + FilterSpecByPaths(source, keepPaths) + } + } + // Check for model conflicts + conflicts := false + for k, v := range source.Definitions { + v2, found := dest.Definitions[k] + if found && !reflect.DeepEqual(v, v2) { + if !renameModelConflicts { + return fmt.Errorf("model name conflict in merging OpenAPI spec: %s", k) + } + conflicts = true + break + } + } + + if conflicts { + if !specCloned { + source, err = CloneSpec(source) + if err != nil { + return err + } + } + specCloned = true + usedNames := map[string]bool{} + for k := range dest.Definitions { + usedNames[k] = true + } + type Rename struct { + from, to string + } + renames := []Rename{} + + OUTERLOOP: + for k, v := range source.Definitions { + if usedNames[k] { + v2, found := dest.Definitions[k] + // Reuse model if they are exactly the same. + if found && reflect.DeepEqual(v, v2) { + continue + } + + // Reuse previously renamed model if one exists + var newName string + i := 1 + for found { + i++ + newName = fmt.Sprintf("%s_v%d", k, i) + v2, found = dest.Definitions[newName] + if found && reflect.DeepEqual(v, v2) { + renames = append(renames, Rename{from: k, to: newName}) + continue OUTERLOOP + } + } + + _, foundInSource := source.Definitions[newName] + for usedNames[newName] || foundInSource { + i++ + newName = fmt.Sprintf("%s_v%d", k, i) + _, foundInSource = source.Definitions[newName] + } + renames = append(renames, Rename{from: k, to: newName}) + usedNames[newName] = true + } + } + for _, r := range renames { + renameDefinition(source, r.from, r.to) + } + } + for k, v := range source.Definitions { + if _, found := dest.Definitions[k]; !found { + if dest.Definitions == nil { + dest.Definitions = spec.Definitions{} + } + dest.Definitions[k] = v + } + } + // Check for path conflicts + for k, v := range source.Paths.Paths { + if _, found := dest.Paths.Paths[k]; found { + return fmt.Errorf("unable to merge: duplicated path %s", k) + } + // PathItem may be empty, due to [ACL constraints](http://goo.gl/8us55a#securityFiltering). + if dest.Paths.Paths == nil { + dest.Paths.Paths = map[string]spec.PathItem{} + } + dest.Paths.Paths[k] = v + } + return nil +} + +// CloneSpec clones OpenAPI spec +func CloneSpec(source *spec.Swagger) (*spec.Swagger, error) { + // TODO(mehdy): Find a faster way to clone an spec + bytes, err := json.Marshal(source) + if err != nil { + return nil, err + } + var ret spec.Swagger + err = json.Unmarshal(bytes, &ret) + if err != nil { + return nil, err + } + return &ret, nil +} diff --git a/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator_test.go b/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator_test.go new file mode 100644 index 000000000..779ac01d4 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator_test.go @@ -0,0 +1,1858 @@ +/* +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 aggregator + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/ghodss/yaml" + "github.com/go-openapi/spec" + "github.com/stretchr/testify/assert" +) + +type DebugSpec struct { + *spec.Swagger +} + +func (d DebugSpec) String() string { + bytes, err := json.MarshalIndent(d.Swagger, "", " ") + if err != nil { + return fmt.Sprintf("DebugSpec.String failed: %s", err) + } + return string(bytes) +} +func TestFilterSpecs(t *testing.T) { + var spec1, spec1_filtered *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test2" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" + Test2: + type: "object" + properties: + other: + $ref: "#/definitions/Other" + Other: + type: "string" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" +`), &spec1_filtered) + + ast := assert.New(t) + FilterSpecByPaths(spec1, []string{"/test"}) + ast.Equal(DebugSpec{spec1_filtered}, DebugSpec{spec1}) +} + +func TestFilterSpecsWithUnusedDefinitions(t *testing.T) { + var spec1, spec1Filtered *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test2" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" + Test2: + type: "object" + properties: + other: + $ref: "#/definitions/Other" + Other: + type: "string" + Unused: + type: "object" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" + Unused: + type: "object" +`), &spec1Filtered) + + ast := assert.New(t) + FilterSpecByPaths(spec1, []string{"/test"}) + ast.Equal(DebugSpec{spec1Filtered}, DebugSpec{spec1}) +} + +func TestMergeSpecsSimple(t *testing.T) { + var spec1, spec2, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test2" +definitions: + Test2: + type: "object" + properties: + other: + $ref: "#/definitions/Other" + Other: + type: "string" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test2" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" + Test2: + type: "object" + properties: + other: + $ref: "#/definitions/Other" + Other: + type: "string" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} + +func TestMergeSpecsEmptyDefinitions(t *testing.T) { + var spec1, spec2, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + responses: + 405: + description: "Invalid input" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test2" +definitions: + Test2: + type: "object" + properties: + other: + $ref: "#/definitions/Other" + Other: + type: "string" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + responses: + 405: + description: "Invalid input" + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test2" +definitions: + Test2: + type: "object" + properties: + other: + $ref: "#/definitions/Other" + Other: + type: "string" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} + +func TestMergeSpecsEmptyPaths(t *testing.T) { + var spec1, spec2, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test2" +definitions: + Test2: + type: "object" + properties: + other: + $ref: "#/definitions/Other" + Other: + type: "string" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test2" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" + Test2: + type: "object" + properties: + other: + $ref: "#/definitions/Other" + Other: + type: "string" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} + +func TestMergeSpecsReuseModel(t *testing.T) { + var spec1, spec2, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} + +func TestMergeSpecsRenameModel(t *testing.T) { + var spec1, spec2, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + InvalidInput: + type: "string" + format: "string" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test" +definitions: + Test: + description: "This Test has a description" + type: "object" + properties: + id: + type: "integer" + format: "int64" + InvalidInput: + type: "string" + format: "string" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + tags: + - "test" + summary: "Test API" + operationId: "addTest" + parameters: + - in: "body" + name: "body" + description: "test object" + required: true + schema: + $ref: "#/definitions/Test" + responses: + 405: + description: "Invalid input" + $ref: "#/definitions/InvalidInput" + /othertest: + post: + tags: + - "test2" + summary: "Test2 API" + operationId: "addTest2" + consumes: + - "application/json" + produces: + - "application/xml" + parameters: + - in: "body" + name: "body" + description: "test2 object" + required: true + schema: + $ref: "#/definitions/Test_v2" +definitions: + Test: + type: "object" + properties: + id: + type: "integer" + format: "int64" + status: + type: "string" + description: "Status" + Test_v2: + description: "This Test has a description" + type: "object" + properties: + id: + type: "integer" + format: "int64" + InvalidInput: + type: "string" + format: "string" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} + +func TestMergeSpecsRenameModelWithExistingV2InDestination(t *testing.T) { + var spec1, spec2, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" + /testv2: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test_v2" +definitions: + Test: + type: "object" + Test_v2: + description: "This is an existing Test_v2 in destination schema" + type: "object" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" +definitions: + Test: + description: "This Test has a description" + type: "object" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" + /testv2: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test_v2" + /othertest: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test_v3" +definitions: + Test: + type: "object" + Test_v2: + description: "This is an existing Test_v2 in destination schema" + type: "object" + Test_v3: + description: "This Test has a description" + type: "object" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} + +func TestMergeSpecsRenameModelWithExistingV2InSource(t *testing.T) { + var spec1, spec2, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" +definitions: + Test: + type: "object" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" + /testv2: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test_v2" +definitions: + Test: + description: "This Test has a description" + type: "object" + Test_v2: + description: "This is an existing Test_v2 in source schema" + type: "object" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" + /testv2: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test_v2" + /othertest: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test_v3" +definitions: + Test: + type: "object" + Test_v2: + description: "This is an existing Test_v2 in source schema" + type: "object" + Test_v3: + description: "This Test has a description" + type: "object" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} + +// This tests if there are three specs, where the first two use the same object definition, +// while the third one uses its own. +// We expect the merged schema to contain two versions of the object, not three +func TestTwoMergeSpecsFirstTwoSchemasHaveSameDefinition(t *testing.T) { + var spec1, spec2, spec3, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" +definitions: + Test: + description: "spec1 and spec2 use the same object definition, while spec3 doesn't" + type: "object" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test2: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" +definitions: + Test: + description: "spec1 and spec2 use the same object definition, while spec3 doesn't" + type: "object" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test3: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" +definitions: + Test: + description: "spec3 has its own definition (the description doesn't match)" + type: "object" +`), &spec3) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" + /test2: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" + /test3: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test_v2" +definitions: + Test: + description: "spec1 and spec2 use the same object definition, while spec3 doesn't" + type: "object" + Test_v2: + description: "spec3 has its own definition (the description doesn't match)" + type: "object" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + if !ast.NoError(MergeSpecs(spec1, spec3)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} + +// This tests if there are three specs, where the last two use the same object definition, +// while the first one uses its own. +// We expect the merged schema to contain two versions of the object, not three +func TestTwoMergeSpecsLastTwoSchemasHaveSameDefinition(t *testing.T) { + var spec1, spec2, spec3, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" +definitions: + Test: + type: "object" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" +definitions: + Test: + description: "spec2 and spec3 use the same object definition, while spec1 doesn't" + type: "object" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /othertest2: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" +definitions: + Test: + description: "spec2 and spec3 use the same object definition, while spec1 doesn't" + type: "object" +`), &spec3) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" + /othertest: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test_v2" + /othertest2: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test_v2" +definitions: + Test: + type: "object" + Test_v2: + description: "spec2 and spec3 use the same object definition, while spec1 doesn't" + type: "object" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + if !ast.NoError(MergeSpecs(spec1, spec3)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} + +func TestSafeMergeSpecsSimple(t *testing.T) { + var fooSpec, barSpec, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Foo API" + operationId: "fooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" +`), &fooSpec) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /bar: + post: + summary: "Bar API" + operationId: "barTest" + parameters: + - in: "body" + name: "body" + description: "bar object" + required: true + schema: + $ref: "#/definitions/Bar" + responses: + 200: + description: "OK" +definitions: + Bar: + type: "object" + properties: + id: + type: "integer" + format: "int64" +`), &barSpec) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Foo API" + operationId: "fooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" + /bar: + post: + summary: "Bar API" + operationId: "barTest" + parameters: + - in: "body" + name: "body" + description: "bar object" + required: true + schema: + $ref: "#/definitions/Bar" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" + Bar: + type: "object" + properties: + id: + type: "integer" + format: "int64" + `), &expected) + + ast := assert.New(t) + actual, err := CloneSpec(fooSpec) + if !ast.NoError(err) { + return + } + if !ast.NoError(MergeSpecsFailOnDefinitionConflict(actual, barSpec)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{actual}) +} + +func TestSafeMergeSpecsReuseModel(t *testing.T) { + var fooSpec, barSpec, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Foo API" + operationId: "fooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" +`), &fooSpec) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /refoo: + post: + summary: "Refoo API" + operationId: "refooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" +`), &barSpec) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Foo API" + operationId: "fooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" + /refoo: + post: + summary: "Refoo API" + operationId: "refooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" + `), &expected) + + ast := assert.New(t) + actual, err := CloneSpec(fooSpec) + if !ast.NoError(err) { + return + } + if !ast.NoError(MergeSpecsFailOnDefinitionConflict(actual, barSpec)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{actual}) +} + +func TestSafeMergeSpecsReuseModelFails(t *testing.T) { + var fooSpec, barSpec, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Foo API" + operationId: "fooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" +`), &fooSpec) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /refoo: + post: + summary: "Refoo API" + operationId: "refooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" + new_field: + type: "string" +`), &barSpec) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Foo API" + operationId: "fooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" + /refoo: + post: + summary: "Refoo API" + operationId: "refooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" + `), &expected) + + ast := assert.New(t) + actual, err := CloneSpec(fooSpec) + if !ast.NoError(err) { + return + } + ast.Error(MergeSpecsFailOnDefinitionConflict(actual, barSpec)) +} + +func TestMergeSpecsIgnorePathConflicts(t *testing.T) { + var fooSpec, barSpec, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Foo API" + operationId: "fooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" +`), &fooSpec) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Should be ignored" + /bar: + post: + summary: "Bar API" + operationId: "barTest" + parameters: + - in: "body" + name: "body" + description: "bar object" + required: true + schema: + $ref: "#/definitions/Bar" + responses: + 200: + description: "OK" +definitions: + Bar: + type: "object" + properties: + id: + type: "integer" + format: "int64" +`), &barSpec) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Foo API" + operationId: "fooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" + /bar: + post: + summary: "Bar API" + operationId: "barTest" + parameters: + - in: "body" + name: "body" + description: "bar object" + required: true + schema: + $ref: "#/definitions/Bar" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" + Bar: + type: "object" + properties: + id: + type: "integer" + format: "int64" + `), &expected) + + ast := assert.New(t) + actual, err := CloneSpec(fooSpec) + if !ast.NoError(err) { + return + } + if !ast.Error(MergeSpecs(actual, barSpec)) { + return + } + actual, err = CloneSpec(fooSpec) + if !ast.NoError(err) { + return + } + if !ast.NoError(MergeSpecsIgnorePathConflict(actual, barSpec)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{actual}) +} + +func TestMergeSpecsIgnorePathConflictsAllConflicting(t *testing.T) { + var fooSpec *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /foo: + post: + summary: "Foo API" + operationId: "fooTest" + parameters: + - in: "body" + name: "body" + description: "foo object" + required: true + schema: + $ref: "#/definitions/Foo" + responses: + 200: + description: "OK" +definitions: + Foo: + type: "object" + properties: + id: + type: "integer" + format: "int64" +`), &fooSpec) + + ast := assert.New(t) + foo2Spec, err := CloneSpec(fooSpec) + actual, err := CloneSpec(fooSpec) + if !ast.NoError(err) { + return + } + if !ast.NoError(MergeSpecsIgnorePathConflict(actual, foo2Spec)) { + return + } + ast.Equal(DebugSpec{fooSpec}, DebugSpec{actual}) +} + +func TestMergeSpecReplacesAllPossibleRefs(t *testing.T) { + var spec1, spec2, expected *spec.Swagger + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" +definitions: + Test: + type: "object" + properties: + foo: + $ref: "#/definitions/TestProperty" + TestProperty: + type: "object" +`), &spec1) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test2: + post: + parameters: + - name: "test2" + schema: + $ref: "#/definitions/Test2" + - name: "test3" + schema: + $ref: "#/definitions/Test3" + - name: "test4" + schema: + $ref: "#/definitions/Test4" + - name: "test5" + schema: + $ref: "#/definitions/Test5" +definitions: + Test2: + $ref: "#/definitions/TestProperty" + Test3: + type: "object" + properties: + withRef: + $ref: "#/definitions/TestProperty" + withAllOf: + type: "object" + allOf: + - $ref: "#/definitions/TestProperty" + - type: object + properties: + test: + $ref: "#/definitions/TestProperty" + withAnyOf: + type: "object" + anyOf: + - $ref: "#/definitions/TestProperty" + - type: object + properties: + test: + $ref: "#/definitions/TestProperty" + withOneOf: + type: "object" + oneOf: + - $ref: "#/definitions/TestProperty" + - type: object + properties: + test: + $ref: "#/definitions/TestProperty" + withNot: + type: "object" + not: + $ref: "#/definitions/TestProperty" + patternProperties: + "prefix.*": + $ref: "#/definitions/TestProperty" + additionalProperties: + $ref: "#/definitions/TestProperty" + definitions: + SomeDefinition: + $ref: "#/definitions/TestProperty" + Test4: + type: "array" + items: + $ref: "#/definitions/TestProperty" + additionalItems: + $ref: "#/definitions/TestProperty" + Test5: + type: "array" + items: + - $ref: "#/definitions/TestProperty" + - $ref: "#/definitions/TestProperty" + TestProperty: + description: "This TestProperty is different from the one in spec1" + type: "object" +`), &spec2) + + yaml.Unmarshal([]byte(` +swagger: "2.0" +paths: + /test: + post: + parameters: + - name: "body" + schema: + $ref: "#/definitions/Test" + /test2: + post: + parameters: + - name: "test2" + schema: + $ref: "#/definitions/Test2" + - name: "test3" + schema: + $ref: "#/definitions/Test3" + - name: "test4" + schema: + $ref: "#/definitions/Test4" + - name: "test5" + schema: + $ref: "#/definitions/Test5" +definitions: + Test: + type: "object" + properties: + foo: + $ref: "#/definitions/TestProperty" + TestProperty: + type: "object" + Test2: + $ref: "#/definitions/TestProperty_v2" + Test3: + type: "object" + properties: + withRef: + $ref: "#/definitions/TestProperty_v2" + withAllOf: + type: "object" + allOf: + - $ref: "#/definitions/TestProperty_v2" + - type: object + properties: + test: + $ref: "#/definitions/TestProperty_v2" + withAnyOf: + type: "object" + anyOf: + - $ref: "#/definitions/TestProperty_v2" + - type: object + properties: + test: + $ref: "#/definitions/TestProperty_v2" + withOneOf: + type: "object" + oneOf: + - $ref: "#/definitions/TestProperty_v2" + - type: object + properties: + test: + $ref: "#/definitions/TestProperty_v2" + withNot: + type: "object" + not: + $ref: "#/definitions/TestProperty_v2" + patternProperties: + "prefix.*": + $ref: "#/definitions/TestProperty_v2" + additionalProperties: + $ref: "#/definitions/TestProperty_v2" + definitions: + SomeDefinition: + $ref: "#/definitions/TestProperty_v2" + Test4: + type: "array" + items: + $ref: "#/definitions/TestProperty_v2" + additionalItems: + $ref: "#/definitions/TestProperty_v2" + Test5: + type: "array" + items: + - $ref: "#/definitions/TestProperty_v2" + - $ref: "#/definitions/TestProperty_v2" + TestProperty_v2: + description: "This TestProperty is different from the one in spec1" + type: "object" +`), &expected) + + ast := assert.New(t) + if !ast.NoError(MergeSpecs(spec1, spec2)) { + return + } + ast.Equal(DebugSpec{expected}, DebugSpec{spec1}) +} diff --git a/vendor/k8s.io/kube-openapi/pkg/builder/doc.go b/vendor/k8s.io/kube-openapi/pkg/builder/doc.go new file mode 100644 index 000000000..c3109067f --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/builder/doc.go @@ -0,0 +1,20 @@ +/* +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 builder contains code to generate OpenAPI discovery spec (which +// initial version of it also known as Swagger 2.0). +// For more details: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md +package builder diff --git a/vendor/k8s.io/kube-openapi/pkg/builder/openapi.go b/vendor/k8s.io/kube-openapi/pkg/builder/openapi.go new file mode 100644 index 000000000..8846d8206 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/builder/openapi.go @@ -0,0 +1,441 @@ +/* +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 builder + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + + restful "github.com/emicklei/go-restful" + "github.com/go-openapi/spec" + + "k8s.io/kube-openapi/pkg/common" + "k8s.io/kube-openapi/pkg/util" +) + +const ( + OpenAPIVersion = "2.0" + // TODO: Make this configurable. + extensionPrefix = "x-kubernetes-" +) + +type openAPI struct { + config *common.Config + swagger *spec.Swagger + protocolList []string + definitions map[string]common.OpenAPIDefinition +} + +// BuildOpenAPISpec builds OpenAPI spec given a list of webservices (containing routes) and common.Config to customize it. +func BuildOpenAPISpec(webServices []*restful.WebService, config *common.Config) (*spec.Swagger, error) { + o := newOpenAPI(config) + err := o.buildPaths(webServices) + if err != nil { + return nil, err + } + return o.finalizeSwagger() +} + +// BuildOpenAPIDefinitionsForResource builds a partial OpenAPI spec given a sample object and common.Config to customize it. +func BuildOpenAPIDefinitionsForResource(model interface{}, config *common.Config) (*spec.Definitions, error) { + o := newOpenAPI(config) + // We can discard the return value of toSchema because all we care about is the side effect of calling it. + // All the models created for this resource get added to o.swagger.Definitions + _, err := o.toSchema(util.GetCanonicalTypeName(model)) + if err != nil { + return nil, err + } + swagger, err := o.finalizeSwagger() + if err != nil { + return nil, err + } + return &swagger.Definitions, nil +} + +// BuildOpenAPIDefinitionsForResources returns the OpenAPI spec which includes the definitions for the +// passed type names. +func BuildOpenAPIDefinitionsForResources(config *common.Config, names ...string) (*spec.Swagger, error) { + o := newOpenAPI(config) + // We can discard the return value of toSchema because all we care about is the side effect of calling it. + // All the models created for this resource get added to o.swagger.Definitions + for _, name := range names { + _, err := o.toSchema(name) + if err != nil { + return nil, err + } + } + return o.finalizeSwagger() +} + +// newOpenAPI sets up the openAPI object so we can build the spec. +func newOpenAPI(config *common.Config) openAPI { + o := openAPI{ + config: config, + swagger: &spec.Swagger{ + SwaggerProps: spec.SwaggerProps{ + Swagger: OpenAPIVersion, + Definitions: spec.Definitions{}, + Paths: &spec.Paths{Paths: map[string]spec.PathItem{}}, + Info: config.Info, + }, + }, + } + if o.config.GetOperationIDAndTags == nil { + o.config.GetOperationIDAndTags = func(r *restful.Route) (string, []string, error) { + return r.Operation, nil, nil + } + } + if o.config.GetDefinitionName == nil { + o.config.GetDefinitionName = func(name string) (string, spec.Extensions) { + return name[strings.LastIndex(name, "/")+1:], nil + } + } + o.definitions = o.config.GetDefinitions(func(name string) spec.Ref { + defName, _ := o.config.GetDefinitionName(name) + return spec.MustCreateRef("#/definitions/" + common.EscapeJsonPointer(defName)) + }) + if o.config.CommonResponses == nil { + o.config.CommonResponses = map[int]spec.Response{} + } + return o +} + +// finalizeSwagger is called after the spec is built and returns the final spec. +// NOTE: finalizeSwagger also make changes to the final spec, as specified in the config. +func (o *openAPI) finalizeSwagger() (*spec.Swagger, error) { + if o.config.SecurityDefinitions != nil { + o.swagger.SecurityDefinitions = *o.config.SecurityDefinitions + o.swagger.Security = o.config.DefaultSecurity + } + if o.config.PostProcessSpec != nil { + var err error + o.swagger, err = o.config.PostProcessSpec(o.swagger) + if err != nil { + return nil, err + } + } + + return o.swagger, nil +} + +func (o *openAPI) buildDefinitionRecursively(name string) error { + uniqueName, extensions := o.config.GetDefinitionName(name) + if _, ok := o.swagger.Definitions[uniqueName]; ok { + return nil + } + if item, ok := o.definitions[name]; ok { + schema := spec.Schema{ + VendorExtensible: item.Schema.VendorExtensible, + SchemaProps: item.Schema.SchemaProps, + SwaggerSchemaProps: item.Schema.SwaggerSchemaProps, + } + if extensions != nil { + if schema.Extensions == nil { + schema.Extensions = spec.Extensions{} + } + for k, v := range extensions { + schema.Extensions[k] = v + } + } + o.swagger.Definitions[uniqueName] = schema + for _, v := range item.Dependencies { + if err := o.buildDefinitionRecursively(v); err != nil { + return err + } + } + } else { + return fmt.Errorf("cannot find model definition for %v. If you added a new type, you may need to add +k8s:openapi-gen=true to the package or type and run code-gen again", name) + } + return nil +} + +// buildDefinitionForType build a definition for a given type and return a referable name to its definition. +// This is the main function that keep track of definitions used in this spec and is depend on code generated +// by k8s.io/kubernetes/cmd/libs/go2idl/openapi-gen. +func (o *openAPI) buildDefinitionForType(name string) (string, error) { + if err := o.buildDefinitionRecursively(name); err != nil { + return "", err + } + defName, _ := o.config.GetDefinitionName(name) + return "#/definitions/" + common.EscapeJsonPointer(defName), nil +} + +// buildPaths builds OpenAPI paths using go-restful's web services. +func (o *openAPI) buildPaths(webServices []*restful.WebService) error { + pathsToIgnore := util.NewTrie(o.config.IgnorePrefixes) + duplicateOpId := make(map[string]string) + for _, w := range webServices { + rootPath := w.RootPath() + if pathsToIgnore.HasPrefix(rootPath) { + continue + } + commonParams, err := o.buildParameters(w.PathParameters()) + if err != nil { + return err + } + for path, routes := range groupRoutesByPath(w.Routes()) { + // go-swagger has special variable definition {$NAME:*} that can only be + // used at the end of the path and it is not recognized by OpenAPI. + if strings.HasSuffix(path, ":*}") { + path = path[:len(path)-3] + "}" + } + if pathsToIgnore.HasPrefix(path) { + continue + } + // Aggregating common parameters make API spec (and generated clients) simpler + inPathCommonParamsMap, err := o.findCommonParameters(routes) + if err != nil { + return err + } + pathItem, exists := o.swagger.Paths.Paths[path] + if exists { + return fmt.Errorf("duplicate webservice route has been found for path: %v", path) + } + pathItem = spec.PathItem{ + PathItemProps: spec.PathItemProps{ + Parameters: make([]spec.Parameter, 0), + }, + } + // add web services's parameters as well as any parameters appears in all ops, as common parameters + pathItem.Parameters = append(pathItem.Parameters, commonParams...) + for _, p := range inPathCommonParamsMap { + pathItem.Parameters = append(pathItem.Parameters, p) + } + sortParameters(pathItem.Parameters) + for _, route := range routes { + op, err := o.buildOperations(route, inPathCommonParamsMap) + sortParameters(op.Parameters) + if err != nil { + return err + } + dpath, exists := duplicateOpId[op.ID] + if exists { + return fmt.Errorf("duplicate Operation ID %v for path %v and %v", op.ID, dpath, path) + } else { + duplicateOpId[op.ID] = path + } + switch strings.ToUpper(route.Method) { + case "GET": + pathItem.Get = op + case "POST": + pathItem.Post = op + case "HEAD": + pathItem.Head = op + case "PUT": + pathItem.Put = op + case "DELETE": + pathItem.Delete = op + case "OPTIONS": + pathItem.Options = op + case "PATCH": + pathItem.Patch = op + } + } + o.swagger.Paths.Paths[path] = pathItem + } + } + return nil +} + +// buildOperations builds operations for each webservice path +func (o *openAPI) buildOperations(route restful.Route, inPathCommonParamsMap map[interface{}]spec.Parameter) (ret *spec.Operation, err error) { + ret = &spec.Operation{ + OperationProps: spec.OperationProps{ + Description: route.Doc, + Consumes: route.Consumes, + Produces: route.Produces, + Schemes: o.config.ProtocolList, + Responses: &spec.Responses{ + ResponsesProps: spec.ResponsesProps{ + StatusCodeResponses: make(map[int]spec.Response), + }, + }, + }, + } + for k, v := range route.Metadata { + if strings.HasPrefix(k, extensionPrefix) { + if ret.Extensions == nil { + ret.Extensions = spec.Extensions{} + } + ret.Extensions.Add(k, v) + } + } + if ret.ID, ret.Tags, err = o.config.GetOperationIDAndTags(&route); err != nil { + return ret, err + } + + // Build responses + for _, resp := range route.ResponseErrors { + ret.Responses.StatusCodeResponses[resp.Code], err = o.buildResponse(resp.Model, resp.Message) + if err != nil { + return ret, err + } + } + // If there is no response but a write sample, assume that write sample is an http.StatusOK response. + if len(ret.Responses.StatusCodeResponses) == 0 && route.WriteSample != nil { + ret.Responses.StatusCodeResponses[http.StatusOK], err = o.buildResponse(route.WriteSample, "OK") + if err != nil { + return ret, err + } + } + for code, resp := range o.config.CommonResponses { + if _, exists := ret.Responses.StatusCodeResponses[code]; !exists { + ret.Responses.StatusCodeResponses[code] = resp + } + } + // If there is still no response, use default response provided. + if len(ret.Responses.StatusCodeResponses) == 0 { + ret.Responses.Default = o.config.DefaultResponse + } + + // Build non-common Parameters + ret.Parameters = make([]spec.Parameter, 0) + for _, param := range route.ParameterDocs { + if _, isCommon := inPathCommonParamsMap[mapKeyFromParam(param)]; !isCommon { + openAPIParam, err := o.buildParameter(param.Data(), route.ReadSample) + if err != nil { + return ret, err + } + ret.Parameters = append(ret.Parameters, openAPIParam) + } + } + return ret, nil +} + +func (o *openAPI) buildResponse(model interface{}, description string) (spec.Response, error) { + schema, err := o.toSchema(util.GetCanonicalTypeName(model)) + if err != nil { + return spec.Response{}, err + } + return spec.Response{ + ResponseProps: spec.ResponseProps{ + Description: description, + Schema: schema, + }, + }, nil +} + +func (o *openAPI) findCommonParameters(routes []restful.Route) (map[interface{}]spec.Parameter, error) { + commonParamsMap := make(map[interface{}]spec.Parameter, 0) + paramOpsCountByName := make(map[interface{}]int, 0) + paramNameKindToDataMap := make(map[interface{}]restful.ParameterData, 0) + for _, route := range routes { + routeParamDuplicateMap := make(map[interface{}]bool) + s := "" + for _, param := range route.ParameterDocs { + m, _ := json.Marshal(param.Data()) + s += string(m) + "\n" + key := mapKeyFromParam(param) + if routeParamDuplicateMap[key] { + msg, _ := json.Marshal(route.ParameterDocs) + return commonParamsMap, fmt.Errorf("duplicate parameter %v for route %v, %v", param.Data().Name, string(msg), s) + } + routeParamDuplicateMap[key] = true + paramOpsCountByName[key]++ + paramNameKindToDataMap[key] = param.Data() + } + } + for key, count := range paramOpsCountByName { + paramData := paramNameKindToDataMap[key] + if count == len(routes) && paramData.Kind != restful.BodyParameterKind { + openAPIParam, err := o.buildParameter(paramData, nil) + if err != nil { + return commonParamsMap, err + } + commonParamsMap[key] = openAPIParam + } + } + return commonParamsMap, nil +} + +func (o *openAPI) toSchema(name string) (_ *spec.Schema, err error) { + if openAPIType, openAPIFormat := common.GetOpenAPITypeFormat(name); openAPIType != "" { + return &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{openAPIType}, + Format: openAPIFormat, + }, + }, nil + } else { + ref, err := o.buildDefinitionForType(name) + if err != nil { + return nil, err + } + return &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: spec.MustCreateRef(ref), + }, + }, nil + } +} + +func (o *openAPI) buildParameter(restParam restful.ParameterData, bodySample interface{}) (ret spec.Parameter, err error) { + ret = spec.Parameter{ + ParamProps: spec.ParamProps{ + Name: restParam.Name, + Description: restParam.Description, + Required: restParam.Required, + }, + } + switch restParam.Kind { + case restful.BodyParameterKind: + if bodySample != nil { + ret.In = "body" + ret.Schema, err = o.toSchema(util.GetCanonicalTypeName(bodySample)) + return ret, err + } else { + // There is not enough information in the body parameter to build the definition. + // Body parameter has a data type that is a short name but we need full package name + // of the type to create a definition. + return ret, fmt.Errorf("restful body parameters are not supported: %v", restParam.DataType) + } + case restful.PathParameterKind: + ret.In = "path" + if !restParam.Required { + return ret, fmt.Errorf("path parameters should be marked at required for parameter %v", restParam) + } + case restful.QueryParameterKind: + ret.In = "query" + case restful.HeaderParameterKind: + ret.In = "header" + case restful.FormParameterKind: + ret.In = "formData" + default: + return ret, fmt.Errorf("unknown restful operation kind : %v", restParam.Kind) + } + openAPIType, openAPIFormat := common.GetOpenAPITypeFormat(restParam.DataType) + if openAPIType == "" { + return ret, fmt.Errorf("non-body Restful parameter type should be a simple type, but got : %v", restParam.DataType) + } + ret.Type = openAPIType + ret.Format = openAPIFormat + ret.UniqueItems = !restParam.AllowMultiple + return ret, nil +} + +func (o *openAPI) buildParameters(restParam []*restful.Parameter) (ret []spec.Parameter, err error) { + ret = make([]spec.Parameter, len(restParam)) + for i, v := range restParam { + ret[i], err = o.buildParameter(v.Data(), nil) + if err != nil { + return ret, err + } + } + return ret, nil +} diff --git a/vendor/k8s.io/kube-openapi/pkg/builder/openapi_test.go b/vendor/k8s.io/kube-openapi/pkg/builder/openapi_test.go new file mode 100644 index 000000000..eb67c1bc8 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/builder/openapi_test.go @@ -0,0 +1,475 @@ +/* +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 builder + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "testing" + + "github.com/emicklei/go-restful" + "github.com/go-openapi/spec" + "github.com/stretchr/testify/assert" + openapi "k8s.io/kube-openapi/pkg/common" +) + +// setUp is a convenience function for setting up for (most) tests. +func setUp(t *testing.T, fullMethods bool) (*openapi.Config, *restful.Container, *assert.Assertions) { + assert := assert.New(t) + config, container := getConfig(fullMethods) + return config, container, assert +} + +func noOp(request *restful.Request, response *restful.Response) {} + +// Test input +type TestInput struct { + // Name of the input + Name string `json:"name,omitempty"` + // ID of the input + ID int `json:"id,omitempty"` + Tags []string `json:"tags,omitempty"` +} + +// Test output +type TestOutput struct { + // Name of the output + Name string `json:"name,omitempty"` + // Number of outputs + Count int `json:"count,omitempty"` +} + +func (_ TestInput) OpenAPIDefinition() *openapi.OpenAPIDefinition { + schema := spec.Schema{} + schema.Description = "Test input" + schema.Properties = map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name of the input", + Type: []string{"string"}, + Format: "", + }, + }, + "id": { + SchemaProps: spec.SchemaProps{ + Description: "ID of the input", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "tags": { + SchemaProps: spec.SchemaProps{ + Description: "", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } + schema.Extensions = spec.Extensions{"x-test": "test"} + return &openapi.OpenAPIDefinition{ + Schema: schema, + Dependencies: []string{}, + } +} + +func (_ TestOutput) OpenAPIDefinition() *openapi.OpenAPIDefinition { + schema := spec.Schema{} + schema.Description = "Test output" + schema.Properties = map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name of the output", + Type: []string{"string"}, + Format: "", + }, + }, + "count": { + SchemaProps: spec.SchemaProps{ + Description: "Number of outputs", + Type: []string{"integer"}, + Format: "int32", + }, + }, + } + return &openapi.OpenAPIDefinition{ + Schema: schema, + Dependencies: []string{}, + } +} + +var _ openapi.OpenAPIDefinitionGetter = TestInput{} +var _ openapi.OpenAPIDefinitionGetter = TestOutput{} + +func getTestRoute(ws *restful.WebService, method string, additionalParams bool, opPrefix string) *restful.RouteBuilder { + ret := ws.Method(method). + Path("/test/{path:*}"). + Doc(fmt.Sprintf("%s test input", method)). + Operation(fmt.Sprintf("%s%sTestInput", method, opPrefix)). + Produces(restful.MIME_JSON). + Consumes(restful.MIME_JSON). + Param(ws.PathParameter("path", "path to the resource").DataType("string")). + Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). + Reads(TestInput{}). + Returns(200, "OK", TestOutput{}). + Writes(TestOutput{}). + To(noOp) + if additionalParams { + ret.Param(ws.HeaderParameter("hparam", "a test head parameter").DataType("integer")) + ret.Param(ws.FormParameter("fparam", "a test form parameter").DataType("number")) + } + return ret +} + +func getConfig(fullMethods bool) (*openapi.Config, *restful.Container) { + mux := http.NewServeMux() + container := restful.NewContainer() + container.ServeMux = mux + ws := new(restful.WebService) + ws.Path("/foo") + ws.Route(getTestRoute(ws, "get", true, "foo")) + if fullMethods { + ws.Route(getTestRoute(ws, "post", false, "foo")). + Route(getTestRoute(ws, "put", false, "foo")). + Route(getTestRoute(ws, "head", false, "foo")). + Route(getTestRoute(ws, "patch", false, "foo")). + Route(getTestRoute(ws, "options", false, "foo")). + Route(getTestRoute(ws, "delete", false, "foo")) + + } + ws.Path("/bar") + ws.Route(getTestRoute(ws, "get", true, "bar")) + if fullMethods { + ws.Route(getTestRoute(ws, "post", false, "bar")). + Route(getTestRoute(ws, "put", false, "bar")). + Route(getTestRoute(ws, "head", false, "bar")). + Route(getTestRoute(ws, "patch", false, "bar")). + Route(getTestRoute(ws, "options", false, "bar")). + Route(getTestRoute(ws, "delete", false, "bar")) + + } + container.Add(ws) + return &openapi.Config{ + ProtocolList: []string{"https"}, + Info: &spec.Info{ + InfoProps: spec.InfoProps{ + Title: "TestAPI", + Description: "Test API", + Version: "unversioned", + }, + }, + GetDefinitions: func(_ openapi.ReferenceCallback) map[string]openapi.OpenAPIDefinition { + return map[string]openapi.OpenAPIDefinition{ + "k8s.io/kube-openapi/pkg/builder.TestInput": *TestInput{}.OpenAPIDefinition(), + "k8s.io/kube-openapi/pkg/builder.TestOutput": *TestOutput{}.OpenAPIDefinition(), + // Bazel changes the package name, this is ok for testing, but we need to fix it if it happened + // in the main code. + "k8s.io/kube-openapi/pkg/builder/go_default_test.TestInput": *TestInput{}.OpenAPIDefinition(), + "k8s.io/kube-openapi/pkg/builder/go_default_test.TestOutput": *TestOutput{}.OpenAPIDefinition(), + } + }, + GetDefinitionName: func(name string) (string, spec.Extensions) { + friendlyName := name[strings.LastIndex(name, "/")+1:] + if strings.HasPrefix(friendlyName, "go_default_test") { + friendlyName = "builder" + friendlyName[len("go_default_test"):] + } + return friendlyName, spec.Extensions{"x-test2": "test2"} + }, + }, container +} + +func getTestOperation(method string, opPrefix string) *spec.Operation { + return &spec.Operation{ + OperationProps: spec.OperationProps{ + Description: fmt.Sprintf("%s test input", method), + Consumes: []string{"application/json"}, + Produces: []string{"application/json"}, + Schemes: []string{"https"}, + Parameters: []spec.Parameter{}, + Responses: getTestResponses(), + ID: fmt.Sprintf("%s%sTestInput", method, opPrefix), + }, + } +} + +func getTestPathItem(allMethods bool, opPrefix string) spec.PathItem { + ret := spec.PathItem{ + PathItemProps: spec.PathItemProps{ + Get: getTestOperation("get", opPrefix), + Parameters: getTestCommonParameters(), + }, + } + ret.Get.Parameters = getAdditionalTestParameters() + if allMethods { + ret.Put = getTestOperation("put", opPrefix) + ret.Put.Parameters = getTestParameters() + ret.Post = getTestOperation("post", opPrefix) + ret.Post.Parameters = getTestParameters() + ret.Head = getTestOperation("head", opPrefix) + ret.Head.Parameters = getTestParameters() + ret.Patch = getTestOperation("patch", opPrefix) + ret.Patch.Parameters = getTestParameters() + ret.Delete = getTestOperation("delete", opPrefix) + ret.Delete.Parameters = getTestParameters() + ret.Options = getTestOperation("options", opPrefix) + ret.Options.Parameters = getTestParameters() + } + return ret +} + +func getRefSchema(ref string) *spec.Schema { + return &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: spec.MustCreateRef(ref), + }, + } +} + +func getTestResponses() *spec.Responses { + ret := spec.Responses{ + ResponsesProps: spec.ResponsesProps{ + StatusCodeResponses: map[int]spec.Response{}, + }, + } + ret.StatusCodeResponses[200] = spec.Response{ + ResponseProps: spec.ResponseProps{ + Description: "OK", + Schema: getRefSchema("#/definitions/builder.TestOutput"), + }, + } + return &ret +} + +func getTestCommonParameters() []spec.Parameter { + ret := make([]spec.Parameter, 2) + ret[0] = spec.Parameter{ + SimpleSchema: spec.SimpleSchema{ + Type: "string", + }, + ParamProps: spec.ParamProps{ + Description: "path to the resource", + Name: "path", + In: "path", + Required: true, + }, + CommonValidations: spec.CommonValidations{ + UniqueItems: true, + }, + } + ret[1] = spec.Parameter{ + SimpleSchema: spec.SimpleSchema{ + Type: "string", + }, + ParamProps: spec.ParamProps{ + Description: "If 'true', then the output is pretty printed.", + Name: "pretty", + In: "query", + }, + CommonValidations: spec.CommonValidations{ + UniqueItems: true, + }, + } + return ret +} + +func getTestParameters() []spec.Parameter { + ret := make([]spec.Parameter, 1) + ret[0] = spec.Parameter{ + ParamProps: spec.ParamProps{ + Name: "body", + In: "body", + Required: true, + Schema: getRefSchema("#/definitions/builder.TestInput"), + }, + } + return ret +} + +func getAdditionalTestParameters() []spec.Parameter { + ret := make([]spec.Parameter, 3) + ret[0] = spec.Parameter{ + ParamProps: spec.ParamProps{ + Name: "body", + In: "body", + Required: true, + Schema: getRefSchema("#/definitions/builder.TestInput"), + }, + } + ret[1] = spec.Parameter{ + ParamProps: spec.ParamProps{ + Name: "fparam", + Description: "a test form parameter", + In: "formData", + }, + SimpleSchema: spec.SimpleSchema{ + Type: "number", + }, + CommonValidations: spec.CommonValidations{ + UniqueItems: true, + }, + } + ret[2] = spec.Parameter{ + SimpleSchema: spec.SimpleSchema{ + Type: "integer", + }, + ParamProps: spec.ParamProps{ + Description: "a test head parameter", + Name: "hparam", + In: "header", + }, + CommonValidations: spec.CommonValidations{ + UniqueItems: true, + }, + } + return ret +} + +func getTestInputDefinition() spec.Schema { + return spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Test input", + Properties: map[string]spec.Schema{ + "id": { + SchemaProps: spec.SchemaProps{ + Description: "ID of the input", + Type: spec.StringOrArray{"integer"}, + Format: "int32", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name of the input", + Type: spec.StringOrArray{"string"}, + }, + }, + "tags": { + SchemaProps: spec.SchemaProps{ + Type: spec.StringOrArray{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: spec.StringOrArray{"string"}, + }, + }, + }, + }, + }, + }, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-test": "test", + "x-test2": "test2", + }, + }, + } +} + +func getTestOutputDefinition() spec.Schema { + return spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Test output", + Properties: map[string]spec.Schema{ + "count": { + SchemaProps: spec.SchemaProps{ + Description: "Number of outputs", + Type: spec.StringOrArray{"integer"}, + Format: "int32", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name of the output", + Type: spec.StringOrArray{"string"}, + }, + }, + }, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-test2": "test2", + }, + }, + } +} + +func TestBuildOpenAPISpec(t *testing.T) { + config, container, assert := setUp(t, true) + expected := &spec.Swagger{ + SwaggerProps: spec.SwaggerProps{ + Info: &spec.Info{ + InfoProps: spec.InfoProps{ + Title: "TestAPI", + Description: "Test API", + Version: "unversioned", + }, + }, + Swagger: "2.0", + Paths: &spec.Paths{ + Paths: map[string]spec.PathItem{ + "/foo/test/{path}": getTestPathItem(true, "foo"), + "/bar/test/{path}": getTestPathItem(true, "bar"), + }, + }, + Definitions: spec.Definitions{ + "builder.TestInput": getTestInputDefinition(), + "builder.TestOutput": getTestOutputDefinition(), + }, + }, + } + swagger, err := BuildOpenAPISpec(container.RegisteredWebServices(), config) + if !assert.NoError(err) { + return + } + expected_json, err := json.Marshal(expected) + if !assert.NoError(err) { + return + } + actual_json, err := json.Marshal(swagger) + if !assert.NoError(err) { + return + } + assert.Equal(string(expected_json), string(actual_json)) +} + +func TestBuildOpenAPIDefinitionsForResource(t *testing.T) { + config, _, assert := setUp(t, true) + expected := &spec.Definitions{ + "builder.TestInput": getTestInputDefinition(), + } + swagger, err := BuildOpenAPIDefinitionsForResource(TestInput{}, config) + if !assert.NoError(err) { + return + } + expected_json, err := json.Marshal(expected) + if !assert.NoError(err) { + return + } + actual_json, err := json.Marshal(swagger) + if !assert.NoError(err) { + return + } + assert.Equal(string(expected_json), string(actual_json)) +} diff --git a/vendor/k8s.io/kube-openapi/pkg/builder/util.go b/vendor/k8s.io/kube-openapi/pkg/builder/util.go new file mode 100644 index 000000000..5e9a56a6b --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/builder/util.go @@ -0,0 +1,61 @@ +/* +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 builder + +import ( + "sort" + + "github.com/emicklei/go-restful" + "github.com/go-openapi/spec" +) + +type parameters []spec.Parameter + +func (s parameters) Len() int { return len(s) } +func (s parameters) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// byNameIn used in sorting parameters by Name and In fields. +type byNameIn struct { + parameters +} + +func (s byNameIn) Less(i, j int) bool { + return s.parameters[i].Name < s.parameters[j].Name || (s.parameters[i].Name == s.parameters[j].Name && s.parameters[i].In < s.parameters[j].In) +} + +// SortParameters sorts parameters by Name and In fields. +func sortParameters(p []spec.Parameter) { + sort.Sort(byNameIn{p}) +} + +func groupRoutesByPath(routes []restful.Route) map[string][]restful.Route { + pathToRoutes := make(map[string][]restful.Route) + for _, r := range routes { + pathToRoutes[r.Path] = append(pathToRoutes[r.Path], r) + } + return pathToRoutes +} + +func mapKeyFromParam(param *restful.Parameter) interface{} { + return struct { + Name string + Kind int + }{ + Name: param.Data().Name, + Kind: param.Data().Kind, + } +} diff --git a/vendor/k8s.io/kube-openapi/pkg/common/common.go b/vendor/k8s.io/kube-openapi/pkg/common/common.go new file mode 100644 index 000000000..0d235876d --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/common/common.go @@ -0,0 +1,168 @@ +/* +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 common + +import ( + "net/http" + "strings" + + "github.com/emicklei/go-restful" + "github.com/go-openapi/spec" +) + +// OpenAPIDefinition describes single type. Normally these definitions are auto-generated using gen-openapi. +type OpenAPIDefinition struct { + Schema spec.Schema + Dependencies []string +} + +type ReferenceCallback func(path string) spec.Ref + +// GetOpenAPIDefinitions is collection of all definitions. +type GetOpenAPIDefinitions func(ReferenceCallback) map[string]OpenAPIDefinition + +// OpenAPIDefinitionGetter gets openAPI definitions for a given type. If a type implements this interface, +// the definition returned by it will be used, otherwise the auto-generated definitions will be used. See +// GetOpenAPITypeFormat for more information about trade-offs of using this interface or GetOpenAPITypeFormat method when +// possible. +type OpenAPIDefinitionGetter interface { + OpenAPIDefinition() *OpenAPIDefinition +} + +type PathHandler interface { + Handle(path string, handler http.Handler) +} + +// Config is set of configuration for openAPI spec generation. +type Config struct { + // List of supported protocols such as https, http, etc. + ProtocolList []string + + // Info is general information about the API. + Info *spec.Info + + // DefaultResponse will be used if an operation does not have any responses listed. It + // will show up as ... "responses" : {"default" : $DefaultResponse} in the spec. + DefaultResponse *spec.Response + + // CommonResponses will be added as a response to all operation specs. This is a good place to add common + // responses such as authorization failed. + CommonResponses map[int]spec.Response + + // List of webservice's path prefixes to ignore + IgnorePrefixes []string + + // OpenAPIDefinitions should provide definition for all models used by routes. Failure to provide this map + // or any of the models will result in spec generation failure. + GetDefinitions GetOpenAPIDefinitions + + // GetOperationIDAndTags returns operation id and tags for a restful route. It is an optional function to customize operation IDs. + GetOperationIDAndTags func(r *restful.Route) (string, []string, error) + + // GetDefinitionName returns a friendly name for a definition base on the serving path. parameter `name` is the full name of the definition. + // It is an optional function to customize model names. + GetDefinitionName func(name string) (string, spec.Extensions) + + // PostProcessSpec runs after the spec is ready to serve. It allows a final modification to the spec before serving. + PostProcessSpec func(*spec.Swagger) (*spec.Swagger, error) + + // SecurityDefinitions is list of all security definitions for OpenAPI service. If this is not nil, the user of config + // is responsible to provide DefaultSecurity and (maybe) add unauthorized response to CommonResponses. + SecurityDefinitions *spec.SecurityDefinitions + + // DefaultSecurity for all operations. This will pass as spec.SwaggerProps.Security to OpenAPI. + // For most cases, this will be list of acceptable definitions in SecurityDefinitions. + DefaultSecurity []map[string][]string +} + +var schemaTypeFormatMap = map[string][]string{ + "uint": {"integer", "int32"}, + "uint8": {"integer", "byte"}, + "uint16": {"integer", "int32"}, + "uint32": {"integer", "int64"}, + "uint64": {"integer", "int64"}, + "int": {"integer", "int32"}, + "int8": {"integer", "byte"}, + "int16": {"integer", "int32"}, + "int32": {"integer", "int32"}, + "int64": {"integer", "int64"}, + "byte": {"integer", "byte"}, + "float64": {"number", "double"}, + "float32": {"number", "float"}, + "bool": {"boolean", ""}, + "time.Time": {"string", "date-time"}, + "string": {"string", ""}, + "integer": {"integer", ""}, + "number": {"number", ""}, + "boolean": {"boolean", ""}, + "[]byte": {"string", "byte"}, // base64 encoded characters + "interface{}": {"object", ""}, +} + +// This function is a reference for converting go (or any custom type) to a simple open API type,format pair. There are +// two ways to customize spec for a type. If you add it here, a type will be converted to a simple type and the type +// comment (the comment that is added before type definition) will be lost. The spec will still have the property +// comment. The second way is to implement OpenAPIDefinitionGetter interface. That function can customize the spec (so +// the spec does not need to be simple type,format) or can even return a simple type,format (e.g. IntOrString). For simple +// type formats, the benefit of adding OpenAPIDefinitionGetter interface is to keep both type and property documentation. +// Example: +// type Sample struct { +// ... +// // port of the server +// port IntOrString +// ... +// } +// // IntOrString documentation... +// type IntOrString { ... } +// +// Adding IntOrString to this function: +// "port" : { +// format: "string", +// type: "int-or-string", +// Description: "port of the server" +// } +// +// Implement OpenAPIDefinitionGetter for IntOrString: +// +// "port" : { +// $Ref: "#/definitions/IntOrString" +// Description: "port of the server" +// } +// ... +// definitions: +// { +// "IntOrString": { +// format: "string", +// type: "int-or-string", +// Description: "IntOrString documentation..." // new +// } +// } +// +func GetOpenAPITypeFormat(typeName string) (string, string) { + mapped, ok := schemaTypeFormatMap[typeName] + if !ok { + return "", "" + } + return mapped[0], mapped[1] +} + +func EscapeJsonPointer(p string) string { + // Escaping reference name using rfc6901 + p = strings.Replace(p, "~", "~0", -1) + p = strings.Replace(p, "/", "~1", -1) + return p +} diff --git a/vendor/k8s.io/kube-openapi/pkg/common/doc.go b/vendor/k8s.io/kube-openapi/pkg/common/doc.go new file mode 100644 index 000000000..2ba6d247b --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/common/doc.go @@ -0,0 +1,19 @@ +/* +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 common holds shared code and types between open API code +// generator and spec generator. +package common diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/README.md b/vendor/k8s.io/kube-openapi/pkg/generators/README.md new file mode 100644 index 000000000..72b4e5fb4 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/README.md @@ -0,0 +1,49 @@ +# Generate OpenAPI definitions + +- To generate definition for a specific type or package add "+k8s:openapi-gen=true" tag to the type/package comment lines. +- To exclude a type or a member from a tagged package/type, add "+k8s:openapi-gen=false" tag to the comment lines. + +# OpenAPI Extensions + +OpenAPI spec can have extensions on types. To define one or more extensions on a type or its member +add `+k8s:openapi-gen=x-kubernetes-$NAME:$VALUE` to the comment lines before type/member. A type/member can +have multiple extensions. The rest of the line in the comment will be used as $VALUE so there is no need to +escape or quote the value string. Extensions can be used to pass more information to client generators or +documentation generators. For example a type might have a friendly name to be displayed in documentation or +being used in a client's fluent interface. + +# Custom OpenAPI type definitions + +Custom types which otherwise don't map directly to OpenAPI can override their +OpenAPI definition by implementing a function named "OpenAPIDefinition" with +the following signature: + +```go + import openapi "k8s.io/kube-openapi/pkg/common" + + // ... + + type Time struct { + time.Time + } + + func (_ Time) OpenAPIDefinition() openapi.OpenAPIDefinition { + return openapi.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "date-time", + }, + }, + } + } +``` + +Alternatively, the type can avoid the "openapi" import by defining the following +methods. The following example produces the same OpenAPI definition as the +example above: + +```go + func (_ Time) OpenAPISchemaType() []string { return []string{"string"} } + func (_ Time) OpenAPISchemaFormat() string { return "date-time" } +``` diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go b/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go new file mode 100644 index 000000000..fa8e93b4f --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go @@ -0,0 +1,121 @@ +/* +Copyright 2018 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 generators + +import ( + "fmt" + "io" + "sort" + + "k8s.io/kube-openapi/pkg/generators/rules" + + "github.com/golang/glog" + "k8s.io/gengo/types" +) + +// apiLinter is the framework hosting multiple API rules and recording API rule +// violations +type apiLinter struct { + // API rules that implement APIRule interface and output API rule violations + rules []APIRule + violations []apiViolation +} + +// newAPILinter creates an apiLinter object with API rules in package rules. Please +// add APIRule here when new API rule is implemented. +func newAPILinter() *apiLinter { + return &apiLinter{ + rules: []APIRule{ + &rules.NamesMatch{}, + }, + } +} + +// apiViolation uniquely identifies single API rule violation +type apiViolation struct { + // Name of rule from APIRule.Name() + rule string + + packageName string + typeName string + + // Optional: name of field that violates API rule. Empty fieldName implies that + // the entire type violates the rule. + field string +} + +// apiViolations implements sort.Interface for []apiViolation based on the fields: rule, +// packageName, typeName and field. +type apiViolations []apiViolation + +func (a apiViolations) Len() int { return len(a) } +func (a apiViolations) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a apiViolations) Less(i, j int) bool { + if a[i].rule != a[j].rule { + return a[i].rule < a[j].rule + } + if a[i].packageName != a[j].packageName { + return a[i].packageName < a[j].packageName + } + if a[i].typeName != a[j].typeName { + return a[i].typeName < a[j].typeName + } + return a[i].field < a[j].field +} + +// APIRule is the interface for validating API rule on Go types +type APIRule interface { + // Validate evaluates API rule on type t and returns a list of field names in + // the type that violate the rule. Empty field name [""] implies the entire + // type violates the rule. + Validate(t *types.Type) ([]string, error) + + // Name returns the name of APIRule + Name() string +} + +// validate runs all API rules on type t and records any API rule violation +func (l *apiLinter) validate(t *types.Type) error { + for _, r := range l.rules { + glog.V(5).Infof("validating API rule %v for type %v", r.Name(), t) + fields, err := r.Validate(t) + if err != nil { + return err + } + for _, field := range fields { + l.violations = append(l.violations, apiViolation{ + rule: r.Name(), + packageName: t.Name.Package, + typeName: t.Name.Name, + field: field, + }) + } + } + return nil +} + +// report prints any API rule violation to writer w and returns error if violation exists +func (l *apiLinter) report(w io.Writer) error { + sort.Sort(apiViolations(l.violations)) + for _, v := range l.violations { + fmt.Fprintf(w, "API rule violation: %s,%s,%s,%s\n", v.rule, v.packageName, v.typeName, v.field) + } + if len(l.violations) > 0 { + return fmt.Errorf("API rule violations exist") + } + return nil +} diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/extension.go b/vendor/k8s.io/kube-openapi/pkg/generators/extension.go new file mode 100644 index 000000000..14eab18f6 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/extension.go @@ -0,0 +1,182 @@ +/* +Copyright 2018 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 generators + +import ( + "fmt" + "sort" + "strings" + + "k8s.io/gengo/examples/set-gen/sets" + "k8s.io/gengo/types" +) + +const extensionPrefix = "x-kubernetes-" + +// extensionAttributes encapsulates common traits for particular extensions. +type extensionAttributes struct { + xName string + kind types.Kind + allowedValues sets.String +} + +// Extension tag to openapi extension attributes +var tagToExtension = map[string]extensionAttributes{ + "patchMergeKey": { + xName: "x-kubernetes-patch-merge-key", + kind: types.Slice, + }, + "patchStrategy": { + xName: "x-kubernetes-patch-strategy", + kind: types.Slice, + allowedValues: sets.NewString("merge", "retainKeys"), + }, + "listMapKey": { + xName: "x-kubernetes-list-map-keys", + kind: types.Slice, + }, + "listType": { + xName: "x-kubernetes-list-type", + kind: types.Slice, + allowedValues: sets.NewString("atomic", "set", "map"), + }, +} + +// Extension encapsulates information necessary to generate an OpenAPI extension. +type extension struct { + idlTag string // Example: listType + xName string // Example: x-kubernetes-list-type + values []string // Example: [atomic] +} + +func (e extension) hasAllowedValues() bool { + return tagToExtension[e.idlTag].allowedValues.Len() > 0 +} + +func (e extension) allowedValues() sets.String { + return tagToExtension[e.idlTag].allowedValues +} + +func (e extension) hasKind() bool { + return len(tagToExtension[e.idlTag].kind) > 0 +} + +func (e extension) kind() types.Kind { + return tagToExtension[e.idlTag].kind +} + +func (e extension) validateAllowedValues() error { + // allowedValues not set means no restrictions on values. + if !e.hasAllowedValues() { + return nil + } + // Check for missing value. + if len(e.values) == 0 { + return fmt.Errorf("%s needs a value, none given.", e.idlTag) + } + // For each extension value, validate that it is allowed. + allowedValues := e.allowedValues() + if !allowedValues.HasAll(e.values...) { + return fmt.Errorf("%v not allowed for %s. Allowed values: %v", + e.values, e.idlTag, allowedValues.List()) + } + return nil +} + +func (e extension) validateType(kind types.Kind) error { + // If this extension class has no kind, then don't validate the type. + if !e.hasKind() { + return nil + } + if kind != e.kind() { + return fmt.Errorf("tag %s on type %v; only allowed on type %v", + e.idlTag, kind, e.kind()) + } + return nil +} + +func (e extension) hasMultipleValues() bool { + return len(e.values) > 1 +} + +// Returns sorted list of map keys. Needed for deterministic testing. +func sortedMapKeys(m map[string][]string) []string { + keys := make([]string, len(m)) + i := 0 + for k := range m { + keys[i] = k + i++ + } + sort.Strings(keys) + return keys +} + +// Parses comments to return openapi extensions. Returns a list of +// extensions which parsed correctly, as well as a list of the +// parse errors. Validating extensions is performed separately. +// NOTE: Non-empty errors does not mean extensions is empty. +func parseExtensions(comments []string) ([]extension, []error) { + extensions := []extension{} + errors := []error{} + // First, generate extensions from "+k8s:openapi-gen=x-kubernetes-*" annotations. + values := getOpenAPITagValue(comments) + for _, val := range values { + // Example: x-kubernetes-member-tag:member_test + if strings.HasPrefix(val, extensionPrefix) { + parts := strings.SplitN(val, ":", 2) + if len(parts) != 2 { + errors = append(errors, fmt.Errorf("invalid extension value: %v", val)) + continue + } + e := extension{ + idlTag: tagName, // Example: k8s:openapi-gen + xName: parts[0], // Example: x-kubernetes-member-tag + values: []string{parts[1]}, // Example: member_test + } + extensions = append(extensions, e) + } + } + // Next, generate extensions from "idlTags" (e.g. +listType) + tagValues := types.ExtractCommentTags("+", comments) + for _, idlTag := range sortedMapKeys(tagValues) { + xAttrs, exists := tagToExtension[idlTag] + if !exists { + continue + } + values := tagValues[idlTag] + e := extension{ + idlTag: idlTag, // listType + xName: xAttrs.xName, // x-kubernetes-list-type + values: values, // [atomic] + } + extensions = append(extensions, e) + } + return extensions, errors +} + +func validateMemberExtensions(extensions []extension, m *types.Member) []error { + errors := []error{} + for _, e := range extensions { + if err := e.validateAllowedValues(); err != nil { + errors = append(errors, err) + } + if err := e.validateType(m.Type.Kind); err != nil { + errors = append(errors, err) + } + } + return errors +} diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/extension_test.go b/vendor/k8s.io/kube-openapi/pkg/generators/extension_test.go new file mode 100644 index 000000000..d1214bd9a --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/extension_test.go @@ -0,0 +1,454 @@ +/* +Copyright 2018 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 generators + +import ( + "reflect" + "strings" + "testing" + + "k8s.io/gengo/examples/set-gen/sets" + "k8s.io/gengo/types" +) + +func TestSingleTagExtension(t *testing.T) { + + // Comments only contain one tag extension and one value. + var tests = []struct { + comments []string + extensionTag string + extensionName string + extensionValues []string + }{ + { + comments: []string{"+patchMergeKey=name"}, + extensionTag: "patchMergeKey", + extensionName: "x-kubernetes-patch-merge-key", + extensionValues: []string{"name"}, + }, + { + comments: []string{"+patchStrategy=merge"}, + extensionTag: "patchStrategy", + extensionName: "x-kubernetes-patch-strategy", + extensionValues: []string{"merge"}, + }, + { + comments: []string{"+listType=atomic"}, + extensionTag: "listType", + extensionName: "x-kubernetes-list-type", + extensionValues: []string{"atomic"}, + }, + { + comments: []string{"+listMapKey=port"}, + extensionTag: "listMapKey", + extensionName: "x-kubernetes-list-map-keys", + extensionValues: []string{"port"}, + }, + { + comments: []string{"+k8s:openapi-gen=x-kubernetes-member-tag:member_test"}, + extensionTag: "k8s:openapi-gen", + extensionName: "x-kubernetes-member-tag", + extensionValues: []string{"member_test"}, + }, + { + comments: []string{"+k8s:openapi-gen=x-kubernetes-member-tag:member_test:member_test2"}, + extensionTag: "k8s:openapi-gen", + extensionName: "x-kubernetes-member-tag", + extensionValues: []string{"member_test:member_test2"}, + }, + { + // Test that poorly formatted extensions aren't added. + comments: []string{ + "+k8s:openapi-gen=x-kubernetes-no-value", + "+k8s:openapi-gen=x-kubernetes-member-success:success", + "+k8s:openapi-gen=x-kubernetes-wrong-separator;error", + }, + extensionTag: "k8s:openapi-gen", + extensionName: "x-kubernetes-member-success", + extensionValues: []string{"success"}, + }, + } + for _, test := range tests { + extensions, _ := parseExtensions(test.comments) + actual := extensions[0] + if actual.idlTag != test.extensionTag { + t.Errorf("Extension Tag: expected (%s), actual (%s)\n", test.extensionTag, actual.idlTag) + } + if actual.xName != test.extensionName { + t.Errorf("Extension Name: expected (%s), actual (%s)\n", test.extensionName, actual.xName) + } + if !reflect.DeepEqual(actual.values, test.extensionValues) { + t.Errorf("Extension Values: expected (%s), actual (%s)\n", test.extensionValues, actual.values) + } + if actual.hasMultipleValues() { + t.Errorf("%s: hasMultipleValues() should be false\n", actual.xName) + } + } + +} + +func TestMultipleTagExtensions(t *testing.T) { + + var tests = []struct { + comments []string + extensionTag string + extensionName string + extensionValues []string + }{ + { + comments: []string{ + "+listMapKey=port", + "+listMapKey=protocol", + }, + extensionTag: "listMapKey", + extensionName: "x-kubernetes-list-map-keys", + extensionValues: []string{"port", "protocol"}, + }, + } + for _, test := range tests { + extensions, errors := parseExtensions(test.comments) + if len(errors) > 0 { + t.Errorf("Unexpected errors: %v\n", errors) + } + actual := extensions[0] + if actual.idlTag != test.extensionTag { + t.Errorf("Extension Tag: expected (%s), actual (%s)\n", test.extensionTag, actual.idlTag) + } + if actual.xName != test.extensionName { + t.Errorf("Extension Name: expected (%s), actual (%s)\n", test.extensionName, actual.xName) + } + if !reflect.DeepEqual(actual.values, test.extensionValues) { + t.Errorf("Extension Values: expected (%s), actual (%s)\n", test.extensionValues, actual.values) + } + if !actual.hasMultipleValues() { + t.Errorf("%s: hasMultipleValues() should be true\n", actual.xName) + } + } + +} + +func TestExtensionParseErrors(t *testing.T) { + + var tests = []struct { + comments []string + errorMessage string + }{ + { + // Missing extension value should be an error. + comments: []string{ + "+k8s:openapi-gen=x-kubernetes-no-value", + }, + errorMessage: "x-kubernetes-no-value", + }, + { + // Wrong separator should be an error. + comments: []string{ + "+k8s:openapi-gen=x-kubernetes-wrong-separator;error", + }, + errorMessage: "x-kubernetes-wrong-separator;error", + }, + } + + for _, test := range tests { + _, errors := parseExtensions(test.comments) + if len(errors) == 0 { + t.Errorf("Expected errors while parsing: %v\n", test.comments) + } + error := errors[0] + if !strings.Contains(error.Error(), test.errorMessage) { + t.Errorf("Error (%v) should contain substring (%s)\n", error, test.errorMessage) + } + } +} + +func TestExtensionAllowedValues(t *testing.T) { + + var methodTests = []struct { + e extension + allowedValues sets.String + }{ + { + e: extension{ + idlTag: "patchStrategy", + }, + allowedValues: sets.NewString("merge", "retainKeys"), + }, + { + e: extension{ + idlTag: "patchMergeKey", + }, + allowedValues: nil, + }, + { + e: extension{ + idlTag: "listType", + }, + allowedValues: sets.NewString("atomic", "set", "map"), + }, + { + e: extension{ + idlTag: "listMapKey", + }, + allowedValues: nil, + }, + { + e: extension{ + idlTag: "k8s:openapi-gen", + }, + allowedValues: nil, + }, + } + for _, test := range methodTests { + if test.allowedValues != nil { + if !test.e.hasAllowedValues() { + t.Errorf("hasAllowedValues() expected (true), but received: false") + } + if !reflect.DeepEqual(test.allowedValues, test.e.allowedValues()) { + t.Errorf("allowedValues() expected (%v), but received: %v", + test.allowedValues, test.e.allowedValues()) + } + } + if test.allowedValues == nil && test.e.hasAllowedValues() { + t.Errorf("hasAllowedValues() expected (false), but received: true") + } + } + + var successTests = []struct { + e extension + }{ + { + e: extension{ + idlTag: "patchStrategy", + xName: "x-kubernetes-patch-strategy", + values: []string{"merge"}, + }, + }, + { + // Validate multiple values. + e: extension{ + idlTag: "patchStrategy", + xName: "x-kubernetes-patch-strategy", + values: []string{"merge", "retainKeys"}, + }, + }, + { + e: extension{ + idlTag: "patchMergeKey", + xName: "x-kubernetes-patch-merge-key", + values: []string{"key1"}, + }, + }, + { + e: extension{ + idlTag: "listType", + xName: "x-kubernetes-list-type", + values: []string{"atomic"}, + }, + }, + } + for _, test := range successTests { + actualErr := test.e.validateAllowedValues() + if actualErr != nil { + t.Errorf("Expected no error for (%v), but received: %v\n", test.e, actualErr) + } + } + + var failureTests = []struct { + e extension + }{ + { + // Every value must be allowed. + e: extension{ + idlTag: "patchStrategy", + xName: "x-kubernetes-patch-strategy", + values: []string{"disallowed", "merge"}, + }, + }, + { + e: extension{ + idlTag: "patchStrategy", + xName: "x-kubernetes-patch-strategy", + values: []string{"foo"}, + }, + }, + { + e: extension{ + idlTag: "listType", + xName: "x-kubernetes-list-type", + values: []string{"not-allowed"}, + }, + }, + } + for _, test := range failureTests { + actualErr := test.e.validateAllowedValues() + if actualErr == nil { + t.Errorf("Expected error, but received none: %v\n", test.e) + } + } + +} + +func TestExtensionKind(t *testing.T) { + + var methodTests = []struct { + e extension + kind types.Kind + }{ + { + e: extension{ + idlTag: "patchStrategy", + }, + kind: types.Slice, + }, + { + e: extension{ + idlTag: "patchMergeKey", + }, + kind: types.Slice, + }, + { + e: extension{ + idlTag: "listType", + }, + kind: types.Slice, + }, + { + e: extension{ + idlTag: "listMapKey", + }, + kind: types.Slice, + }, + { + e: extension{ + idlTag: "k8s:openapi-gen", + }, + kind: "", + }, + } + for _, test := range methodTests { + if len(test.kind) > 0 { + if !test.e.hasKind() { + t.Errorf("%v: hasKind() expected (true), but received: false", test.e) + } + if test.kind != test.e.kind() { + t.Errorf("%v: kind() expected (%v), but received: %v", test.e, test.kind, test.e.kind()) + } + } else { + if test.e.hasKind() { + t.Errorf("%v: hasKind() expected (false), but received: true", test.e) + } + } + } +} + +func TestValidateMemberExtensions(t *testing.T) { + + patchStrategyExtension := extension{ + idlTag: "patchStrategy", + xName: "x-kubernetes-patch-strategy", + values: []string{"merge"}, + } + patchMergeKeyExtension := extension{ + idlTag: "patchMergeKey", + xName: "x-kubernetes-patch-merge-key", + values: []string{"key1", "key2"}, + } + listTypeExtension := extension{ + idlTag: "listType", + xName: "x-kubernetes-list-type", + values: []string{"atomic"}, + } + listMapKeysExtension := extension{ + idlTag: "listMapKey", + xName: "x-kubernetes-map-keys", + values: []string{"key1"}, + } + genExtension := extension{ + idlTag: "k8s:openapi-gen", + xName: "x-kubernetes-member-type", + values: []string{"value1"}, + } + + sliceField := types.Member{ + Name: "Containers", + Type: &types.Type{ + Kind: types.Slice, + }, + } + mapField := types.Member{ + Name: "Containers", + Type: &types.Type{ + Kind: types.Map, + }, + } + + var successTests = []struct { + extensions []extension + member types.Member + }{ + // Test single member extension + { + extensions: []extension{patchStrategyExtension}, + member: sliceField, + }, + // Test multiple member extensions + { + extensions: []extension{ + patchMergeKeyExtension, + listTypeExtension, + listMapKeysExtension, + genExtension, // Should not generate errors during type validation + }, + member: sliceField, + }, + } + for _, test := range successTests { + errors := validateMemberExtensions(test.extensions, &test.member) + if len(errors) > 0 { + t.Errorf("validateMemberExtensions: %v should have produced no errors. Errors: %v", + test.extensions, errors) + } + } + + var failureTests = []struct { + extensions []extension + member types.Member + }{ + // Test single member extension + { + extensions: []extension{patchStrategyExtension}, + member: mapField, + }, + // Test multiple member extensions + { + extensions: []extension{ + patchMergeKeyExtension, + listTypeExtension, + listMapKeysExtension, + }, + member: mapField, + }, + } + for _, test := range failureTests { + errors := validateMemberExtensions(test.extensions, &test.member) + if len(errors) != len(test.extensions) { + t.Errorf("validateMemberExtensions: %v should have produced all errors. Errors: %v", + test.extensions, errors) + } + } + +} diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go b/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go new file mode 100644 index 000000000..d6c6275a7 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go @@ -0,0 +1,704 @@ +/* +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 generators + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "reflect" + "sort" + "strings" + + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args" + openapi "k8s.io/kube-openapi/pkg/common" + + "github.com/golang/glog" +) + +// This is the comment tag that carries parameters for open API generation. +const tagName = "k8s:openapi-gen" +const tagOptional = "optional" + +// Known values for the tag. +const ( + tagValueTrue = "true" + tagValueFalse = "false" +) + +// Used for temporary validation of patch struct tags. +// TODO: Remove patch struct tag validation because they we are now consuming OpenAPI on server. +var tempPatchTags = [...]string{ + "patchMergeKey", + "patchStrategy", +} + +func getOpenAPITagValue(comments []string) []string { + return types.ExtractCommentTags("+", comments)[tagName] +} + +func getSingleTagsValue(comments []string, tag string) (string, error) { + tags, ok := types.ExtractCommentTags("+", comments)[tag] + if !ok || len(tags) == 0 { + return "", nil + } + if len(tags) > 1 { + return "", fmt.Errorf("multiple values are not allowed for tag %s", tag) + } + return tags[0], nil +} + +func hasOpenAPITagValue(comments []string, value string) bool { + tagValues := getOpenAPITagValue(comments) + for _, val := range tagValues { + if val == value { + return true + } + } + return false +} + +// hasOptionalTag returns true if the member has +optional in its comments or +// omitempty in its json tags. +func hasOptionalTag(m *types.Member) bool { + hasOptionalCommentTag := types.ExtractCommentTags( + "+", m.CommentLines)[tagOptional] != nil + hasOptionalJsonTag := strings.Contains( + reflect.StructTag(m.Tags).Get("json"), "omitempty") + return hasOptionalCommentTag || hasOptionalJsonTag +} + +type identityNamer struct{} + +func (_ identityNamer) Name(t *types.Type) string { + return t.Name.String() +} + +var _ namer.Namer = identityNamer{} + +// NameSystems returns the name system used by the generators in this package. +func NameSystems() namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer("", nil), + "sorting_namer": identityNamer{}, + } +} + +// DefaultNameSystem returns the default name system for ordering the types to be +// processed by the generators in this package. +func DefaultNameSystem() string { + return "sorting_namer" +} + +func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { + boilerplate, err := arguments.LoadGoBoilerplate() + if err != nil { + glog.Fatalf("Failed loading boilerplate: %v", err) + } + header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) + header = append(header, []byte( + ` +// This file was autogenerated by openapi-gen. Do not edit it manually! + +`)...) + + reportFilename := "-" + if customArgs, ok := arguments.CustomArgs.(*generatorargs.CustomArgs); ok { + reportFilename = customArgs.ReportFilename + } + + return generator.Packages{ + &generator.DefaultPackage{ + PackageName: filepath.Base(arguments.OutputPackagePath), + PackagePath: arguments.OutputPackagePath, + HeaderText: header, + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + return []generator.Generator{NewOpenAPIGen(arguments.OutputFileBaseName, arguments.OutputPackagePath, context, newAPILinter(), reportFilename)} + }, + FilterFunc: func(c *generator.Context, t *types.Type) bool { + // There is a conflict between this codegen and codecgen, we should avoid types generated for codecgen + if strings.HasPrefix(t.Name.Name, "codecSelfer") { + return false + } + pkg := context.Universe.Package(t.Name.Package) + if hasOpenAPITagValue(pkg.Comments, tagValueTrue) { + return !hasOpenAPITagValue(t.CommentLines, tagValueFalse) + } + if hasOpenAPITagValue(t.CommentLines, tagValueTrue) { + return true + } + return false + }, + }, + } +} + +const ( + specPackagePath = "github.com/go-openapi/spec" + openAPICommonPackagePath = "k8s.io/kube-openapi/pkg/common" +) + +// openApiGen produces a file with auto-generated OpenAPI functions. +type openAPIGen struct { + generator.DefaultGen + // TargetPackage is the package that will get GetOpenAPIDefinitions function returns all open API definitions. + targetPackage string + imports namer.ImportTracker + types []*types.Type + context *generator.Context + linter *apiLinter + reportFilename string +} + +func NewOpenAPIGen(sanitizedName string, targetPackage string, context *generator.Context, linter *apiLinter, reportFilename string) generator.Generator { + return &openAPIGen{ + DefaultGen: generator.DefaultGen{ + OptionalName: sanitizedName, + }, + imports: generator.NewImportTracker(), + targetPackage: targetPackage, + context: context, + linter: linter, + reportFilename: reportFilename, + } +} + +const nameTmpl = "schema_$.type|private$" + +func (g *openAPIGen) Namers(c *generator.Context) namer.NameSystems { + // Have the raw namer for this file track what it imports. + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.targetPackage, g.imports), + "private": &namer.NameStrategy{ + Join: func(pre string, in []string, post string) string { + return strings.Join(in, "_") + }, + PrependPackageNames: 4, // enough to fully qualify from k8s.io/api/... + }, + } +} + +func (g *openAPIGen) Filter(c *generator.Context, t *types.Type) bool { + // There is a conflict between this codegen and codecgen, we should avoid types generated for codecgen + if strings.HasPrefix(t.Name.Name, "codecSelfer") { + return false + } + g.types = append(g.types, t) + return true +} + +func (g *openAPIGen) isOtherPackage(pkg string) bool { + if pkg == g.targetPackage { + return false + } + if strings.HasSuffix(pkg, "\""+g.targetPackage+"\"") { + return false + } + return true +} + +func (g *openAPIGen) Imports(c *generator.Context) []string { + importLines := []string{} + for _, singleImport := range g.imports.ImportLines() { + importLines = append(importLines, singleImport) + } + return importLines +} + +func argsFromType(t *types.Type) generator.Args { + return generator.Args{ + "type": t, + "ReferenceCallback": types.Ref(openAPICommonPackagePath, "ReferenceCallback"), + "OpenAPIDefinition": types.Ref(openAPICommonPackagePath, "OpenAPIDefinition"), + "SpecSchemaType": types.Ref(specPackagePath, "Schema"), + } +} + +func (g *openAPIGen) Init(c *generator.Context, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + sw.Do("func GetOpenAPIDefinitions(ref $.ReferenceCallback|raw$) map[string]$.OpenAPIDefinition|raw$ {\n", argsFromType(nil)) + sw.Do("return map[string]$.OpenAPIDefinition|raw${\n", argsFromType(nil)) + + for _, t := range g.types { + err := newOpenAPITypeWriter(sw).generateCall(t) + if err != nil { + return err + } + } + + sw.Do("}\n", nil) + sw.Do("}\n\n", nil) + + return sw.Error() +} + +func (g *openAPIGen) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + glog.V(5).Infof("validating API rules for type %v", t) + if err := g.linter.validate(t); err != nil { + return err + } + glog.V(5).Infof("generating for type %v", t) + sw := generator.NewSnippetWriter(w, c, "$", "$") + err := newOpenAPITypeWriter(sw).generate(t) + if err != nil { + return err + } + return sw.Error() +} + +func getJsonTags(m *types.Member) []string { + jsonTag := reflect.StructTag(m.Tags).Get("json") + if jsonTag == "" { + return []string{} + } + return strings.Split(jsonTag, ",") +} + +func getReferableName(m *types.Member) string { + jsonTags := getJsonTags(m) + if len(jsonTags) > 0 { + if jsonTags[0] == "-" { + return "" + } else { + return jsonTags[0] + } + } else { + return m.Name + } +} + +func shouldInlineMembers(m *types.Member) bool { + jsonTags := getJsonTags(m) + return len(jsonTags) > 1 && jsonTags[1] == "inline" +} + +type openAPITypeWriter struct { + *generator.SnippetWriter + refTypes map[string]*types.Type + GetDefinitionInterface *types.Type +} + +func newOpenAPITypeWriter(sw *generator.SnippetWriter) openAPITypeWriter { + return openAPITypeWriter{ + SnippetWriter: sw, + refTypes: map[string]*types.Type{}, + } +} + +func methodReturnsValue(mt *types.Type, pkg, name string) bool { + if len(mt.Signature.Parameters) != 0 || len(mt.Signature.Results) != 1 { + return false + } + r := mt.Signature.Results[0] + return r.Name.Name == name && r.Name.Package == pkg +} + +func hasOpenAPIDefinitionMethod(t *types.Type) bool { + for mn, mt := range t.Methods { + if mn != "OpenAPIDefinition" { + continue + } + return methodReturnsValue(mt, openAPICommonPackagePath, "OpenAPIDefinition") + } + return false +} + +func hasOpenAPIDefinitionMethods(t *types.Type) bool { + var hasSchemaTypeMethod, hasOpenAPISchemaFormat bool + for mn, mt := range t.Methods { + switch mn { + case "OpenAPISchemaType": + hasSchemaTypeMethod = methodReturnsValue(mt, "", "[]string") + case "OpenAPISchemaFormat": + hasOpenAPISchemaFormat = methodReturnsValue(mt, "", "string") + } + } + return hasSchemaTypeMethod && hasOpenAPISchemaFormat +} + +// typeShortName returns short package name (e.g. the name x appears in package x definition) dot type name. +func typeShortName(t *types.Type) string { + return filepath.Base(t.Name.Package) + "." + t.Name.Name +} + +func (g openAPITypeWriter) generateMembers(t *types.Type, required []string) ([]string, error) { + var err error + for _, m := range t.Members { + if hasOpenAPITagValue(m.CommentLines, tagValueFalse) { + continue + } + if shouldInlineMembers(&m) { + required, err = g.generateMembers(m.Type, required) + if err != nil { + return required, err + } + continue + } + name := getReferableName(&m) + if name == "" { + continue + } + if !hasOptionalTag(&m) { + required = append(required, name) + } + if err = g.generateProperty(&m, t); err != nil { + glog.Errorf("Error when generating: %v, %v\n", name, m) + return required, err + } + } + return required, nil +} + +func (g openAPITypeWriter) generateCall(t *types.Type) error { + // Only generate for struct type and ignore the rest + switch t.Kind { + case types.Struct: + args := argsFromType(t) + g.Do("\"$.$\": ", t.Name) + if hasOpenAPIDefinitionMethod(t) { + g.Do("$.type|raw${}.OpenAPIDefinition(),\n", args) + } else { + g.Do(nameTmpl+"(ref),\n", args) + } + } + return g.Error() +} + +func (g openAPITypeWriter) generate(t *types.Type) error { + // Only generate for struct type and ignore the rest + switch t.Kind { + case types.Struct: + if hasOpenAPIDefinitionMethod(t) { + // already invoked directly + return nil + } + + args := argsFromType(t) + g.Do("func "+nameTmpl+"(ref $.ReferenceCallback|raw$) $.OpenAPIDefinition|raw$ {\n", args) + if hasOpenAPIDefinitionMethods(t) { + g.Do("return $.OpenAPIDefinition|raw${\n"+ + "Schema: spec.Schema{\n"+ + "SchemaProps: spec.SchemaProps{\n", args) + g.generateDescription(t.CommentLines) + g.Do("Type:$.type|raw${}.OpenAPISchemaType(),\n"+ + "Format:$.type|raw${}.OpenAPISchemaFormat(),\n"+ + "},\n"+ + "},\n"+ + "}\n}\n\n", args) + return nil + } + g.Do("return $.OpenAPIDefinition|raw${\nSchema: spec.Schema{\nSchemaProps: spec.SchemaProps{\n", args) + g.generateDescription(t.CommentLines) + g.Do("Properties: map[string]$.SpecSchemaType|raw${\n", args) + required, err := g.generateMembers(t, []string{}) + if err != nil { + return err + } + g.Do("},\n", nil) + if len(required) > 0 { + g.Do("Required: []string{\"$.$\"},\n", strings.Join(required, "\",\"")) + } + g.Do("},\n", nil) + if err := g.generateStructExtensions(t); err != nil { + return err + } + g.Do("},\n", nil) + g.Do("Dependencies: []string{\n", args) + // Map order is undefined, sort them or we may get a different file generated each time. + keys := []string{} + for k := range g.refTypes { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + v := g.refTypes[k] + if t, _ := openapi.GetOpenAPITypeFormat(v.String()); t != "" { + // This is a known type, we do not need a reference to it + // Will eliminate special case of time.Time + continue + } + g.Do("\"$.$\",", k) + } + g.Do("},\n}\n}\n\n", nil) + } + return nil +} + +func (g openAPITypeWriter) generateStructExtensions(t *types.Type) error { + extensions, errors := parseExtensions(t.CommentLines) + // Initially, we will only log struct extension errors. + if len(errors) > 0 { + for _, e := range errors { + glog.V(2).Infof("[%s]: %s\n", t.String(), e) + } + } + // TODO(seans3): Validate struct extensions here. + g.emitExtensions(extensions) + return nil +} + +func (g openAPITypeWriter) generateMemberExtensions(m *types.Member, parent *types.Type) error { + extensions, parseErrors := parseExtensions(m.CommentLines) + validationErrors := validateMemberExtensions(extensions, m) + errors := append(parseErrors, validationErrors...) + // Initially, we will only log member extension errors. + if len(errors) > 0 { + errorPrefix := fmt.Sprintf("[%s] %s:", parent.String(), m.String()) + for _, e := range errors { + glog.V(2).Infof("%s %s\n", errorPrefix, e) + } + } + g.emitExtensions(extensions) + return nil +} + +func (g openAPITypeWriter) emitExtensions(extensions []extension) { + // If any extensions exist, then emit code to create them. + if len(extensions) == 0 { + return + } + g.Do("VendorExtensible: spec.VendorExtensible{\nExtensions: spec.Extensions{\n", nil) + for _, extension := range extensions { + g.Do("\"$.$\": ", extension.xName) + if extension.hasMultipleValues() { + g.Do("[]string{\n", nil) + } + for _, value := range extension.values { + g.Do("\"$.$\",\n", value) + } + if extension.hasMultipleValues() { + g.Do("},\n", nil) + } + } + g.Do("},\n},\n", nil) +} + +// TODO(#44005): Move this validation outside of this generator (probably to policy verifier) +func (g openAPITypeWriter) validatePatchTags(m *types.Member, parent *types.Type) error { + // TODO: Remove patch struct tag validation because they we are now consuming OpenAPI on server. + for _, tagKey := range tempPatchTags { + structTagValue := reflect.StructTag(m.Tags).Get(tagKey) + commentTagValue, err := getSingleTagsValue(m.CommentLines, tagKey) + if err != nil { + return err + } + if structTagValue != commentTagValue { + return fmt.Errorf("Tags in comment and struct should match for member (%s) of (%s)", + m.Name, parent.Name.String()) + } + } + return nil +} + +func (g openAPITypeWriter) generateDescription(CommentLines []string) { + var buffer bytes.Buffer + delPrevChar := func() { + if buffer.Len() > 0 { + buffer.Truncate(buffer.Len() - 1) // Delete the last " " or "\n" + } + } + + for _, line := range CommentLines { + // Ignore all lines after --- + if line == "---" { + break + } + line = strings.TrimRight(line, " ") + leading := strings.TrimLeft(line, " ") + switch { + case len(line) == 0: // Keep paragraphs + delPrevChar() + buffer.WriteString("\n\n") + case strings.HasPrefix(leading, "TODO"): // Ignore one line TODOs + case strings.HasPrefix(leading, "+"): // Ignore instructions to go2idl + default: + if strings.HasPrefix(line, " ") || strings.HasPrefix(line, "\t") { + delPrevChar() + line = "\n" + line + "\n" // Replace it with newline. This is useful when we have a line with: "Example:\n\tJSON-someting..." + } else { + line += " " + } + buffer.WriteString(line) + } + } + + postDoc := strings.TrimRight(buffer.String(), "\n") + postDoc = strings.Replace(postDoc, "\\\"", "\"", -1) // replace user's \" to " + postDoc = strings.Replace(postDoc, "\"", "\\\"", -1) // Escape " + postDoc = strings.Replace(postDoc, "\n", "\\n", -1) + postDoc = strings.Replace(postDoc, "\t", "\\t", -1) + postDoc = strings.Trim(postDoc, " ") + if postDoc != "" { + g.Do("Description: \"$.$\",\n", postDoc) + } +} + +func (g openAPITypeWriter) generateProperty(m *types.Member, parent *types.Type) error { + name := getReferableName(m) + if name == "" { + return nil + } + if err := g.validatePatchTags(m, parent); err != nil { + return err + } + g.Do("\"$.$\": {\n", name) + if err := g.generateMemberExtensions(m, parent); err != nil { + return err + } + g.Do("SchemaProps: spec.SchemaProps{\n", nil) + g.generateDescription(m.CommentLines) + jsonTags := getJsonTags(m) + if len(jsonTags) > 1 && jsonTags[1] == "string" { + g.generateSimpleProperty("string", "") + g.Do("},\n},\n", nil) + return nil + } + t := resolveAliasAndPtrType(m.Type) + // If we can get a openAPI type and format for this type, we consider it to be simple property + typeString, format := openapi.GetOpenAPITypeFormat(t.String()) + if typeString != "" { + g.generateSimpleProperty(typeString, format) + g.Do("},\n},\n", nil) + return nil + } + switch t.Kind { + case types.Builtin: + return fmt.Errorf("please add type %v to getOpenAPITypeFormat function", t) + case types.Map: + if err := g.generateMapProperty(t); err != nil { + return err + } + case types.Slice, types.Array: + if err := g.generateSliceProperty(t); err != nil { + return err + } + case types.Struct, types.Interface: + g.generateReferenceProperty(t) + default: + return fmt.Errorf("cannot generate spec for type %v", t) + } + g.Do("},\n},\n", nil) + return g.Error() +} + +func (g openAPITypeWriter) generateSimpleProperty(typeString, format string) { + g.Do("Type: []string{\"$.$\"},\n", typeString) + g.Do("Format: \"$.$\",\n", format) +} + +func (g openAPITypeWriter) generateReferenceProperty(t *types.Type) { + g.refTypes[t.Name.String()] = t + g.Do("Ref: ref(\"$.$\"),\n", t.Name.String()) +} + +func resolveAliasAndPtrType(t *types.Type) *types.Type { + var prev *types.Type + for prev != t { + prev = t + if t.Kind == types.Alias { + t = t.Underlying + } + if t.Kind == types.Pointer { + t = t.Elem + } + } + return t +} + +func (g openAPITypeWriter) generateMapProperty(t *types.Type) error { + keyType := resolveAliasAndPtrType(t.Key) + elemType := resolveAliasAndPtrType(t.Elem) + + // According to OpenAPI examples, only map from string is supported + if keyType.Name.Name != "string" { + return fmt.Errorf("map with non-string keys are not supported by OpenAPI in %v", t) + } + g.Do("Type: []string{\"object\"},\n", nil) + g.Do("AdditionalProperties: &spec.SchemaOrBool{\nSchema: &spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil) + typeString, format := openapi.GetOpenAPITypeFormat(elemType.String()) + if typeString != "" { + g.generateSimpleProperty(typeString, format) + g.Do("},\n},\n},\n", nil) + return nil + } + switch elemType.Kind { + case types.Builtin: + return fmt.Errorf("please add type %v to getOpenAPITypeFormat function", elemType) + case types.Struct: + g.generateReferenceProperty(elemType) + case types.Slice, types.Array: + g.generateSliceProperty(elemType) + default: + return fmt.Errorf("map Element kind %v is not supported in %v", elemType.Kind, t.Name) + } + g.Do("},\n},\n},\n", nil) + return nil +} + +func (g openAPITypeWriter) generateSliceProperty(t *types.Type) error { + elemType := resolveAliasAndPtrType(t.Elem) + g.Do("Type: []string{\"array\"},\n", nil) + g.Do("Items: &spec.SchemaOrArray{\nSchema: &spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil) + typeString, format := openapi.GetOpenAPITypeFormat(elemType.String()) + if typeString != "" { + g.generateSimpleProperty(typeString, format) + g.Do("},\n},\n},\n", nil) + return nil + } + switch elemType.Kind { + case types.Builtin: + return fmt.Errorf("please add type %v to getOpenAPITypeFormat function", elemType) + case types.Struct: + g.generateReferenceProperty(elemType) + case types.Slice, types.Array: + g.generateSliceProperty(elemType) + default: + return fmt.Errorf("slice Element kind %v is not supported in %v", elemType.Kind, t) + } + g.Do("},\n},\n},\n", nil) + return nil +} + +// Finalize prints the API rule violations to report file (if specified from arguments) or stdout (default) +func (g *openAPIGen) Finalize(c *generator.Context, w io.Writer) error { + // If report file isn't specified, return error to force user to choose either stdout ("-") or a file name + if len(g.reportFilename) == 0 { + return fmt.Errorf("empty report file name: please provide a valid file name or use the default \"-\" (stdout)") + } + // If stdout is specified, print violations and return error + if g.reportFilename == "-" { + return g.linter.report(os.Stdout) + } + // Otherwise, print violations to report file and return nil + f, err := os.Create(g.reportFilename) + if err != nil { + return err + } + defer f.Close() + g.linter.report(f) + // NOTE: we don't return error here because we assume that the report file will + // get evaluated afterwards to determine if error should be raised. For example, + // you can have make rules that compare the report file with existing known + // violations (whitelist) and determine no error if no change is detected. + return nil +} diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/openapi_test.go b/vendor/k8s.io/kube-openapi/pkg/generators/openapi_test.go new file mode 100644 index 000000000..6713b8324 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/openapi_test.go @@ -0,0 +1,625 @@ +/* +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 generators + +import ( + "bytes" + "fmt" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/parser" + "k8s.io/gengo/types" +) + +func construct(t *testing.T, files map[string]string, testNamer namer.Namer) (*parser.Builder, types.Universe, []*types.Type) { + b := parser.New() + for name, src := range files { + if err := b.AddFileForTest(filepath.Dir(name), name, []byte(src)); err != nil { + t.Fatal(err) + } + } + u, err := b.FindTypes() + if err != nil { + t.Fatal(err) + } + orderer := namer.Orderer{Namer: testNamer} + o := orderer.OrderUniverse(u) + return b, u, o +} + +func testOpenAPITypeWriter(t *testing.T, code string) (error, error, *assert.Assertions, *bytes.Buffer, *bytes.Buffer) { + assert := assert.New(t) + var testFiles = map[string]string{ + "base/foo/bar.go": code, + } + rawNamer := namer.NewRawNamer("o", nil) + namers := namer.NameSystems{ + "raw": namer.NewRawNamer("", nil), + "private": &namer.NameStrategy{ + Join: func(pre string, in []string, post string) string { + return strings.Join(in, "_") + }, + PrependPackageNames: 4, // enough to fully qualify from k8s.io/api/... + }, + } + builder, universe, _ := construct(t, testFiles, rawNamer) + context, err := generator.NewContext(builder, namers, "raw") + if err != nil { + t.Fatal(err) + } + blahT := universe.Type(types.Name{Package: "base/foo", Name: "Blah"}) + + callBuffer := &bytes.Buffer{} + callSW := generator.NewSnippetWriter(callBuffer, context, "$", "$") + callError := newOpenAPITypeWriter(callSW).generateCall(blahT) + + funcBuffer := &bytes.Buffer{} + funcSW := generator.NewSnippetWriter(funcBuffer, context, "$", "$") + funcError := newOpenAPITypeWriter(funcSW).generate(blahT) + + return callError, funcError, assert, callBuffer, funcBuffer +} + +func TestSimple(t *testing.T) { + callErr, funcErr, assert, callBuffer, funcBuffer := testOpenAPITypeWriter(t, ` +package foo + +// Blah is a test. +// +k8s:openapi-gen=true +// +k8s:openapi-gen=x-kubernetes-type-tag:type_test +type Blah struct { + // A simple string + String string + // A simple int + Int int `+"`"+`json:",omitempty"`+"`"+` + // An int considered string simple int + IntString int `+"`"+`json:",string"`+"`"+` + // A simple int64 + Int64 int64 + // A simple int32 + Int32 int32 + // A simple int16 + Int16 int16 + // A simple int8 + Int8 int8 + // A simple int + Uint uint + // A simple int64 + Uint64 uint64 + // A simple int32 + Uint32 uint32 + // A simple int16 + Uint16 uint16 + // A simple int8 + Uint8 uint8 + // A simple byte + Byte byte + // A simple boolean + Bool bool + // A simple float64 + Float64 float64 + // A simple float32 + Float32 float32 + // a base64 encoded characters + ByteArray []byte + // a member with an extension + // +k8s:openapi-gen=x-kubernetes-member-tag:member_test + WithExtension string + // a member with struct tag as extension + // +patchStrategy=merge + // +patchMergeKey=pmk + WithStructTagExtension string `+"`"+`patchStrategy:"merge" patchMergeKey:"pmk"`+"`"+` + // a member with a list type + // +listType=atomic + WithListType []string +} + `) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), +`, callBuffer.String()) + assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { +return common.OpenAPIDefinition{ +Schema: spec.Schema{ +SchemaProps: spec.SchemaProps{ +Description: "Blah is a test.", +Properties: map[string]spec.Schema{ +"String": { +SchemaProps: spec.SchemaProps{ +Description: "A simple string", +Type: []string{"string"}, +Format: "", +}, +}, +"Int64": { +SchemaProps: spec.SchemaProps{ +Description: "A simple int64", +Type: []string{"integer"}, +Format: "int64", +}, +}, +"Int32": { +SchemaProps: spec.SchemaProps{ +Description: "A simple int32", +Type: []string{"integer"}, +Format: "int32", +}, +}, +"Int16": { +SchemaProps: spec.SchemaProps{ +Description: "A simple int16", +Type: []string{"integer"}, +Format: "int32", +}, +}, +"Int8": { +SchemaProps: spec.SchemaProps{ +Description: "A simple int8", +Type: []string{"integer"}, +Format: "byte", +}, +}, +"Uint": { +SchemaProps: spec.SchemaProps{ +Description: "A simple int", +Type: []string{"integer"}, +Format: "int32", +}, +}, +"Uint64": { +SchemaProps: spec.SchemaProps{ +Description: "A simple int64", +Type: []string{"integer"}, +Format: "int64", +}, +}, +"Uint32": { +SchemaProps: spec.SchemaProps{ +Description: "A simple int32", +Type: []string{"integer"}, +Format: "int64", +}, +}, +"Uint16": { +SchemaProps: spec.SchemaProps{ +Description: "A simple int16", +Type: []string{"integer"}, +Format: "int32", +}, +}, +"Uint8": { +SchemaProps: spec.SchemaProps{ +Description: "A simple int8", +Type: []string{"integer"}, +Format: "byte", +}, +}, +"Byte": { +SchemaProps: spec.SchemaProps{ +Description: "A simple byte", +Type: []string{"integer"}, +Format: "byte", +}, +}, +"Bool": { +SchemaProps: spec.SchemaProps{ +Description: "A simple boolean", +Type: []string{"boolean"}, +Format: "", +}, +}, +"Float64": { +SchemaProps: spec.SchemaProps{ +Description: "A simple float64", +Type: []string{"number"}, +Format: "double", +}, +}, +"Float32": { +SchemaProps: spec.SchemaProps{ +Description: "A simple float32", +Type: []string{"number"}, +Format: "float", +}, +}, +"ByteArray": { +SchemaProps: spec.SchemaProps{ +Description: "a base64 encoded characters", +Type: []string{"string"}, +Format: "byte", +}, +}, +"WithExtension": { +VendorExtensible: spec.VendorExtensible{ +Extensions: spec.Extensions{ +"x-kubernetes-member-tag": "member_test", +}, +}, +SchemaProps: spec.SchemaProps{ +Description: "a member with an extension", +Type: []string{"string"}, +Format: "", +}, +}, +"WithStructTagExtension": { +VendorExtensible: spec.VendorExtensible{ +Extensions: spec.Extensions{ +"x-kubernetes-patch-merge-key": "pmk", +"x-kubernetes-patch-strategy": "merge", +}, +}, +SchemaProps: spec.SchemaProps{ +Description: "a member with struct tag as extension", +Type: []string{"string"}, +Format: "", +}, +}, +"WithListType": { +VendorExtensible: spec.VendorExtensible{ +Extensions: spec.Extensions{ +"x-kubernetes-list-type": "atomic", +}, +}, +SchemaProps: spec.SchemaProps{ +Description: "a member with a list type", +Type: []string{"array"}, +Items: &spec.SchemaOrArray{ +Schema: &spec.Schema{ +SchemaProps: spec.SchemaProps{ +Type: []string{"string"}, +Format: "", +}, +}, +}, +}, +}, +}, +Required: []string{"String","Int64","Int32","Int16","Int8","Uint","Uint64","Uint32","Uint16","Uint8","Byte","Bool","Float64","Float32","ByteArray","WithExtension","WithStructTagExtension","WithListType"}, +}, +VendorExtensible: spec.VendorExtensible{ +Extensions: spec.Extensions{ +"x-kubernetes-type-tag": "type_test", +}, +}, +}, +Dependencies: []string{ +}, +} +} + +`, funcBuffer.String()) +} + +func TestFailingSample1(t *testing.T) { + _, funcErr, assert, _, _ := testOpenAPITypeWriter(t, ` +package foo + +// Map sample tests openAPIGen.generateMapProperty method. +type Blah struct { + // A sample String to String map + StringToArray map[string]map[string]string +} + `) + if assert.Error(funcErr, "An error was expected") { + assert.Equal(funcErr, fmt.Errorf("map Element kind Map is not supported in map[string]map[string]string")) + } +} + +func TestFailingSample2(t *testing.T) { + _, funcErr, assert, _, _ := testOpenAPITypeWriter(t, ` +package foo + +// Map sample tests openAPIGen.generateMapProperty method. +type Blah struct { + // A sample String to String map + StringToArray map[int]string +} `) + if assert.Error(funcErr, "An error was expected") { + assert.Equal(funcErr, fmt.Errorf("map with non-string keys are not supported by OpenAPI in map[int]string")) + } +} + +func TestCustomDef(t *testing.T) { + callErr, funcErr, assert, callBuffer, funcBuffer := testOpenAPITypeWriter(t, ` +package foo + +import openapi "k8s.io/kube-openapi/pkg/common" + +type Blah struct { +} + +func (_ Blah) OpenAPIDefinition() openapi.OpenAPIDefinition { + return openapi.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "date-time", + }, + }, + } +} +`) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assert.Equal(`"base/foo.Blah": foo.Blah{}.OpenAPIDefinition(), +`, callBuffer.String()) + assert.Equal(``, funcBuffer.String()) +} + +func TestCustomDefs(t *testing.T) { + callErr, funcErr, assert, callBuffer, funcBuffer := testOpenAPITypeWriter(t, ` +package foo + +// Blah is a custom type +type Blah struct { +} + +func (_ Blah) OpenAPISchemaType() []string { return []string{"string"} } +func (_ Blah) OpenAPISchemaFormat() string { return "date-time" } +`) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), +`, callBuffer.String()) + assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { +return common.OpenAPIDefinition{ +Schema: spec.Schema{ +SchemaProps: spec.SchemaProps{ +Description: "Blah is a custom type", +Type:foo.Blah{}.OpenAPISchemaType(), +Format:foo.Blah{}.OpenAPISchemaFormat(), +}, +}, +} +} + +`, funcBuffer.String()) +} + +func TestPointer(t *testing.T) { + callErr, funcErr, assert, callBuffer, funcBuffer := testOpenAPITypeWriter(t, ` +package foo + +// PointerSample demonstrate pointer's properties +type Blah struct { + // A string pointer + StringPointer *string + // A struct pointer + StructPointer *Blah + // A slice pointer + SlicePointer *[]string + // A map pointer + MapPointer *map[string]string +} + `) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), +`, callBuffer.String()) + assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { +return common.OpenAPIDefinition{ +Schema: spec.Schema{ +SchemaProps: spec.SchemaProps{ +Description: "PointerSample demonstrate pointer's properties", +Properties: map[string]spec.Schema{ +"StringPointer": { +SchemaProps: spec.SchemaProps{ +Description: "A string pointer", +Type: []string{"string"}, +Format: "", +}, +}, +"StructPointer": { +SchemaProps: spec.SchemaProps{ +Description: "A struct pointer", +Ref: ref("base/foo.Blah"), +}, +}, +"SlicePointer": { +SchemaProps: spec.SchemaProps{ +Description: "A slice pointer", +Type: []string{"array"}, +Items: &spec.SchemaOrArray{ +Schema: &spec.Schema{ +SchemaProps: spec.SchemaProps{ +Type: []string{"string"}, +Format: "", +}, +}, +}, +}, +}, +"MapPointer": { +SchemaProps: spec.SchemaProps{ +Description: "A map pointer", +Type: []string{"object"}, +AdditionalProperties: &spec.SchemaOrBool{ +Schema: &spec.Schema{ +SchemaProps: spec.SchemaProps{ +Type: []string{"string"}, +Format: "", +}, +}, +}, +}, +}, +}, +Required: []string{"StringPointer","StructPointer","SlicePointer","MapPointer"}, +}, +}, +Dependencies: []string{ +"base/foo.Blah",}, +} +} + +`, funcBuffer.String()) +} + +func TestNestedLists(t *testing.T) { + callErr, funcErr, assert, callBuffer, funcBuffer := testOpenAPITypeWriter(t, ` +package foo + +// Blah is a test. +// +k8s:openapi-gen=true +// +k8s:openapi-gen=x-kubernetes-type-tag:type_test +type Blah struct { + // Nested list + NestedList [][]int64 +} +`) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), +`, callBuffer.String()) + assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { +return common.OpenAPIDefinition{ +Schema: spec.Schema{ +SchemaProps: spec.SchemaProps{ +Description: "Blah is a test.", +Properties: map[string]spec.Schema{ +"NestedList": { +SchemaProps: spec.SchemaProps{ +Description: "Nested list", +Type: []string{"array"}, +Items: &spec.SchemaOrArray{ +Schema: &spec.Schema{ +SchemaProps: spec.SchemaProps{ +Type: []string{"array"}, +Items: &spec.SchemaOrArray{ +Schema: &spec.Schema{ +SchemaProps: spec.SchemaProps{ +Type: []string{"integer"}, +Format: "int64", +}, +}, +}, +}, +}, +}, +}, +}, +}, +Required: []string{"NestedList"}, +}, +VendorExtensible: spec.VendorExtensible{ +Extensions: spec.Extensions{ +"x-kubernetes-type-tag": "type_test", +}, +}, +}, +Dependencies: []string{ +}, +} +} + +`, funcBuffer.String()) +} + +func TestExtensions(t *testing.T) { + callErr, funcErr, assert, callBuffer, funcBuffer := testOpenAPITypeWriter(t, ` +package foo + +// Blah is a test. +// +k8s:openapi-gen=true +// +k8s:openapi-gen=x-kubernetes-type-tag:type_test +type Blah struct { + // a member with a list type + // +listType=map + // +listMapKey=port + // +listMapKey=protocol + WithListField []string +} + `) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), +`, callBuffer.String()) + assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { +return common.OpenAPIDefinition{ +Schema: spec.Schema{ +SchemaProps: spec.SchemaProps{ +Description: "Blah is a test.", +Properties: map[string]spec.Schema{ +"WithListField": { +VendorExtensible: spec.VendorExtensible{ +Extensions: spec.Extensions{ +"x-kubernetes-list-map-keys": []string{ +"port", +"protocol", +}, +"x-kubernetes-list-type": "map", +}, +}, +SchemaProps: spec.SchemaProps{ +Description: "a member with a list type", +Type: []string{"array"}, +Items: &spec.SchemaOrArray{ +Schema: &spec.Schema{ +SchemaProps: spec.SchemaProps{ +Type: []string{"string"}, +Format: "", +}, +}, +}, +}, +}, +}, +Required: []string{"WithListField"}, +}, +VendorExtensible: spec.VendorExtensible{ +Extensions: spec.Extensions{ +"x-kubernetes-type-tag": "type_test", +}, +}, +}, +Dependencies: []string{ +}, +} +} + +`, funcBuffer.String()) +} diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/rules/doc.go b/vendor/k8s.io/kube-openapi/pkg/generators/rules/doc.go new file mode 100644 index 000000000..384a44dca --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/rules/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2018 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 rules contains API rules that are enforced in OpenAPI spec generation +// as part of the machinery. Files under this package implement APIRule interface +// which evaluates Go type and produces list of API rule violations. +// +// Implementations of APIRule should be added to API linter under openAPIGen code- +// generator to get integrated in the generation process. +package rules diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/rules/names_match.go b/vendor/k8s.io/kube-openapi/pkg/generators/rules/names_match.go new file mode 100644 index 000000000..3a71ff178 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/rules/names_match.go @@ -0,0 +1,172 @@ +/* +Copyright 2018 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 rules + +import ( + "reflect" + "strings" + + "k8s.io/kube-openapi/pkg/util/sets" + + "k8s.io/gengo/types" +) + +var ( + // Blacklist of JSON tags that should skip match evaluation + jsonTagBlacklist = sets.NewString( + // Omitted field is ignored by the package + "-", + ) + + // Blacklist of JSON names that should skip match evaluation + jsonNameBlacklist = sets.NewString( + // Empty name is used for inline struct field (e.g. metav1.TypeMeta) + "", + // Special case for object and list meta + "metadata", + ) + + // List of substrings that aren't allowed in Go name and JSON name + disallowedNameSubstrings = sets.NewString( + // Underscore is not allowed in either name + "_", + // Dash is not allowed in either name. Note that since dash is a valid JSON tag, this should be checked + // after JSON tag blacklist check. + "-", + ) +) + +/* +NamesMatch implements APIRule interface. +Go field names must be CamelCase. JSON field names must be camelCase. Other than capitalization of the +initial letter, the two should almost always match. No underscores nor dashes in either. +This rule verifies the convention "Other than capitalization of the initial letter, the two should almost always match." +Examples (also in unit test): + Go name | JSON name | match + podSpec false + PodSpec podSpec true + PodSpec PodSpec false + podSpec podSpec false + PodSpec spec false + Spec podSpec false + JSONSpec jsonSpec true + JSONSpec jsonspec false + HTTPJSONSpec httpJSONSpec true +NOTE: this validator cannot tell two sequential all-capital words from one word, therefore the case below +is also considered matched. + HTTPJSONSpec httpjsonSpec true +NOTE: JSON names in jsonNameBlacklist should skip evaluation + true + podSpec true + podSpec - true + podSpec metadata true +*/ +type NamesMatch struct{} + +// Name returns the name of APIRule +func (n *NamesMatch) Name() string { + return "names_match" +} + +// Validate evaluates API rule on type t and returns a list of field names in +// the type that violate the rule. Empty field name [""] implies the entire +// type violates the rule. +func (n *NamesMatch) Validate(t *types.Type) ([]string, error) { + fields := make([]string, 0) + + // Only validate struct type and ignore the rest + switch t.Kind { + case types.Struct: + for _, m := range t.Members { + goName := m.Name + jsonTag, ok := reflect.StructTag(m.Tags).Lookup("json") + // Distinguish empty JSON tag and missing JSON tag. Empty JSON tag / name is + // allowed (in JSON name blacklist) but missing JSON tag is invalid. + if !ok { + fields = append(fields, goName) + continue + } + if jsonTagBlacklist.Has(jsonTag) { + continue + } + jsonName := strings.Split(jsonTag, ",")[0] + if !namesMatch(goName, jsonName) { + fields = append(fields, goName) + } + } + } + return fields, nil +} + +// namesMatch evaluates if goName and jsonName match the API rule +// TODO: Use an off-the-shelf CamelCase solution instead of implementing this logic. The following existing +// packages have been tried out: +// github.com/markbates/inflect +// github.com/segmentio/go-camelcase +// github.com/iancoleman/strcase +// github.com/fatih/camelcase +// Please see https://github.com/kubernetes/kube-openapi/pull/83#issuecomment-400842314 for more details +// about why they don't satisfy our need. What we need can be a function that detects an acronym at the +// beginning of a string. +func namesMatch(goName, jsonName string) bool { + if jsonNameBlacklist.Has(jsonName) { + return true + } + if !isAllowedName(goName) || !isAllowedName(jsonName) { + return false + } + if strings.ToLower(goName) != strings.ToLower(jsonName) { + return false + } + // Go field names must be CamelCase. JSON field names must be camelCase. + if !isCapital(goName[0]) || isCapital(jsonName[0]) { + return false + } + for i := 0; i < len(goName); i++ { + if goName[i] == jsonName[i] { + // goName[0:i-1] is uppercase and jsonName[0:i-1] is lowercase, goName[i:] + // and jsonName[i:] should match; + // goName[i] should be lowercase if i is equal to 1, e.g.: + // goName | jsonName + // PodSpec podSpec + // or uppercase if i is greater than 1, e.g.: + // goname | jsonName + // JSONSpec jsonSpec + // This is to rule out cases like: + // goname | jsonName + // JSONSpec jsonspec + return goName[i:] == jsonName[i:] && (i == 1 || isCapital(goName[i])) + } + } + return true +} + +// isCaptical returns true if one character is capital +func isCapital(b byte) bool { + return b >= 'A' && b <= 'Z' +} + +// isAllowedName checks the list of disallowedNameSubstrings and returns true if name doesn't contain +// any disallowed substring. +func isAllowedName(name string) bool { + for _, substr := range disallowedNameSubstrings.UnsortedList() { + if strings.Contains(name, substr) { + return false + } + } + return true +} diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/rules/names_match_test.go b/vendor/k8s.io/kube-openapi/pkg/generators/rules/names_match_test.go new file mode 100644 index 000000000..faae2cba8 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/rules/names_match_test.go @@ -0,0 +1,359 @@ +/* +Copyright 2018 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 rules + +import ( + "reflect" + "testing" + + "k8s.io/gengo/types" +) + +func TestNamesMatch(t *testing.T) { + tcs := []struct { + // name of test case + name string + t *types.Type + + // expected list of violation fields + expected []string + }{ + // The comments are in format of {goName, jsonName, match}, + // {"PodSpec", "podSpec", true}, + { + name: "simple", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "PodSpec", + Tags: `json:"podSpec"`, + }, + }, + }, + expected: []string{}, + }, + // {"PodSpec", "podSpec", true}, + { + name: "multiple_json_tags", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "PodSpec", + Tags: `json:"podSpec,omitempty"`, + }, + }, + }, + expected: []string{}, + }, + // {"PodSpec", "podSpec", true}, + { + name: "protobuf_tag", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "PodSpec", + Tags: `json:"podSpec,omitempty" protobuf:"bytes,1,opt,name=podSpec"`, + }, + }, + }, + expected: []string{}, + }, + // {"", "podSpec", false}, + { + name: "empty", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "", + Tags: `json:"podSpec"`, + }, + }, + }, + expected: []string{""}, + }, + // {"PodSpec", "PodSpec", false}, + { + name: "CamelCase_CamelCase", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "PodSpec", + Tags: `json:"PodSpec"`, + }, + }, + }, + expected: []string{"PodSpec"}, + }, + // {"podSpec", "podSpec", false}, + { + name: "camelCase_camelCase", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "podSpec", + Tags: `json:"podSpec"`, + }, + }, + }, + expected: []string{"podSpec"}, + }, + // {"PodSpec", "spec", false}, + { + name: "short_json_name", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "PodSpec", + Tags: `json:"spec"`, + }, + }, + }, + expected: []string{"PodSpec"}, + }, + // {"Spec", "podSpec", false}, + { + name: "long_json_name", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "Spec", + Tags: `json:"podSpec"`, + }, + }, + }, + expected: []string{"Spec"}, + }, + // {"JSONSpec", "jsonSpec", true}, + { + name: "acronym", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "JSONSpec", + Tags: `json:"jsonSpec"`, + }, + }, + }, + expected: []string{}, + }, + // {"JSONSpec", "jsonspec", false}, + { + name: "acronym_invalid", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "JSONSpec", + Tags: `json:"jsonspec"`, + }, + }, + }, + expected: []string{"JSONSpec"}, + }, + // {"HTTPJSONSpec", "httpJSONSpec", true}, + { + name: "multiple_acronym", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "HTTPJSONSpec", + Tags: `json:"httpJSONSpec"`, + }, + }, + }, + expected: []string{}, + }, + // // NOTE: this validator cannot tell two sequential all-capital words from one word, + // // therefore the case below is also considered matched. + // {"HTTPJSONSpec", "httpjsonSpec", true}, + { + name: "multiple_acronym_as_one", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "HTTPJSONSpec", + Tags: `json:"httpjsonSpec"`, + }, + }, + }, + expected: []string{}, + }, + // NOTE: JSON tags in jsonTagBlacklist should skip evaluation + { + name: "blacklist_tag_dash", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "podSpec", + Tags: `json:"-"`, + }, + }, + }, + expected: []string{}, + }, + // {"PodSpec", "-", false}, + { + name: "invalid_json_name_dash", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "PodSpec", + Tags: `json:"-,"`, + }, + }, + }, + expected: []string{"PodSpec"}, + }, + // NOTE: JSON names in jsonNameBlacklist should skip evaluation + // {"", "", true}, + { + name: "unspecified", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "", + Tags: `json:""`, + }, + }, + }, + expected: []string{}, + }, + // {"podSpec", "", true}, + { + name: "blacklist_empty", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "podSpec", + Tags: `json:""`, + }, + }, + }, + expected: []string{}, + }, + // {"podSpec", "metadata", true}, + { + name: "blacklist_metadata", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "podSpec", + Tags: `json:"metadata"`, + }, + }, + }, + expected: []string{}, + }, + { + name: "non_struct", + t: &types.Type{ + Kind: types.Map, + }, + expected: []string{}, + }, + { + name: "no_json_tag", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "PodSpec", + Tags: `podSpec`, + }, + }, + }, + expected: []string{"PodSpec"}, + }, + // NOTE: this is to expand test coverage + // {"S", "s", true}, + { + name: "single_character", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "S", + Tags: `json:"s"`, + }, + }, + }, + expected: []string{}, + }, + // NOTE: names with disallowed substrings should fail evaluation + // {"Pod-Spec", "pod-Spec", false}, + { + name: "disallowed_substring_dash", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "Pod-Spec", + Tags: `json:"pod-Spec"`, + }, + }, + }, + expected: []string{"Pod-Spec"}, + }, + // {"Pod_Spec", "pod_Spec", false}, + { + name: "disallowed_substring_underscore", + t: &types.Type{ + Kind: types.Struct, + Members: []types.Member{ + types.Member{ + Name: "Pod_Spec", + Tags: `json:"pod_Spec"`, + }, + }, + }, + expected: []string{"Pod_Spec"}, + }, + } + + n := &NamesMatch{} + for _, tc := range tcs { + if violations, _ := n.Validate(tc.t); !reflect.DeepEqual(violations, tc.expected) { + t.Errorf("unexpected validation result: test name %v, want: %v, got: %v", + tc.name, tc.expected, violations) + } + } +} + +// TestRuleName tests the Name of API rule. This is to expand test coverage +func TestRuleName(t *testing.T) { + ruleName := "names_match" + n := &NamesMatch{} + if n.Name() != ruleName { + t.Errorf("unexpected API rule name: want: %v, got: %v", ruleName, n.Name()) + } +} diff --git a/vendor/k8s.io/kube-openapi/pkg/handler/handler.go b/vendor/k8s.io/kube-openapi/pkg/handler/handler.go new file mode 100644 index 000000000..c4bbc0bff --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/handler/handler.go @@ -0,0 +1,272 @@ +/* +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 handler + +import ( + "bytes" + "compress/gzip" + "crypto/sha512" + "encoding/json" + "fmt" + "mime" + "net/http" + "strings" + "sync" + "time" + + "bitbucket.org/ww/goautoneg" + + yaml "gopkg.in/yaml.v2" + + "github.com/NYTimes/gziphandler" + restful "github.com/emicklei/go-restful" + "github.com/go-openapi/spec" + "github.com/golang/protobuf/proto" + openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/googleapis/gnostic/compiler" + + "k8s.io/kube-openapi/pkg/builder" + "k8s.io/kube-openapi/pkg/common" +) + +const ( + jsonExt = ".json" + + mimeJson = "application/json" + // TODO(mehdy): change @68f4ded to a version tag when gnostic add version tags. + mimePb = "application/com.github.googleapis.gnostic.OpenAPIv2@68f4ded+protobuf" + mimePbGz = "application/x-gzip" +) + +// OpenAPIService is the service responsible for serving OpenAPI spec. It has +// the ability to safely change the spec while serving it. +type OpenAPIService struct { + // rwMutex protects All members of this service. + rwMutex sync.RWMutex + + lastModified time.Time + + specBytes []byte + specPb []byte + specPbGz []byte + + specBytesETag string + specPbETag string + specPbGzETag string +} + +func init() { + mime.AddExtensionType(".json", mimeJson) + mime.AddExtensionType(".pb-v1", mimePb) + mime.AddExtensionType(".gz", mimePbGz) +} + +func computeETag(data []byte) string { + return fmt.Sprintf("\"%X\"", sha512.Sum512(data)) +} + +// NOTE: [DEPRECATION] We will announce deprecation for format-separated endpoints for OpenAPI spec, +// and switch to a single /openapi/v2 endpoint in Kubernetes 1.10. The design doc and deprecation process +// are tracked at: https://docs.google.com/document/d/19lEqE9lc4yHJ3WJAJxS_G7TcORIJXGHyq3wpwcH28nU. +// +// BuildAndRegisterOpenAPIService builds the spec and registers a handler to provide access to it. +// Use this method if your OpenAPI spec is static. If you want to update the spec, use BuildOpenAPISpec then RegisterOpenAPIService. +func BuildAndRegisterOpenAPIService(servePath string, webServices []*restful.WebService, config *common.Config, handler common.PathHandler) (*OpenAPIService, error) { + spec, err := builder.BuildOpenAPISpec(webServices, config) + if err != nil { + return nil, err + } + return RegisterOpenAPIService(spec, servePath, handler) +} + +// NOTE: [DEPRECATION] We will announce deprecation for format-separated endpoints for OpenAPI spec, +// and switch to a single /openapi/v2 endpoint in Kubernetes 1.10. The design doc and deprecation process +// are tracked at: https://docs.google.com/document/d/19lEqE9lc4yHJ3WJAJxS_G7TcORIJXGHyq3wpwcH28nU. +// +// RegisterOpenAPIService registers a handler to provide access to provided swagger spec. +// Note: servePath should end with ".json" as the RegisterOpenAPIService assume it is serving a +// json file and will also serve .pb and .gz files. +func RegisterOpenAPIService(openapiSpec *spec.Swagger, servePath string, handler common.PathHandler) (*OpenAPIService, error) { + if !strings.HasSuffix(servePath, jsonExt) { + return nil, fmt.Errorf("serving path must end with \"%s\"", jsonExt) + } + + servePathBase := strings.TrimSuffix(servePath, jsonExt) + + o := OpenAPIService{} + if err := o.UpdateSpec(openapiSpec); err != nil { + return nil, err + } + + type fileInfo struct { + ext string + getDataAndETag func() ([]byte, string, time.Time) + } + + files := []fileInfo{ + {".json", o.getSwaggerBytes}, + {"-2.0.0.json", o.getSwaggerBytes}, + {"-2.0.0.pb-v1", o.getSwaggerPbBytes}, + {"-2.0.0.pb-v1.gz", o.getSwaggerPbGzBytes}, + } + + for _, file := range files { + path := servePathBase + file.ext + getDataAndETag := file.getDataAndETag + handler.Handle(path, gziphandler.GzipHandler(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + data, etag, lastModified := getDataAndETag() + w.Header().Set("Etag", etag) + + // ServeContent will take care of caching using eTag. + http.ServeContent(w, r, path, lastModified, bytes.NewReader(data)) + }), + )) + } + + return &o, nil +} + +func (o *OpenAPIService) getSwaggerBytes() ([]byte, string, time.Time) { + o.rwMutex.RLock() + defer o.rwMutex.RUnlock() + return o.specBytes, o.specBytesETag, o.lastModified +} + +func (o *OpenAPIService) getSwaggerPbBytes() ([]byte, string, time.Time) { + o.rwMutex.RLock() + defer o.rwMutex.RUnlock() + return o.specPb, o.specPbETag, o.lastModified +} + +func (o *OpenAPIService) getSwaggerPbGzBytes() ([]byte, string, time.Time) { + o.rwMutex.RLock() + defer o.rwMutex.RUnlock() + return o.specPbGz, o.specPbGzETag, o.lastModified +} + +func (o *OpenAPIService) UpdateSpec(openapiSpec *spec.Swagger) (err error) { + specBytes, err := json.MarshalIndent(openapiSpec, " ", " ") + if err != nil { + return err + } + specPb, err := toProtoBinary(specBytes) + if err != nil { + return err + } + specPbGz := toGzip(specPb) + + specBytesETag := computeETag(specBytes) + specPbETag := computeETag(specPb) + specPbGzETag := computeETag(specPbGz) + + lastModified := time.Now() + + o.rwMutex.Lock() + defer o.rwMutex.Unlock() + + o.specBytes = specBytes + o.specPb = specPb + o.specPbGz = specPbGz + o.specBytesETag = specBytesETag + o.specPbETag = specPbETag + o.specPbGzETag = specPbGzETag + o.lastModified = lastModified + + return nil +} + +func toProtoBinary(spec []byte) ([]byte, error) { + var info yaml.MapSlice + err := yaml.Unmarshal(spec, &info) + if err != nil { + return nil, err + } + document, err := openapi_v2.NewDocument(info, compiler.NewContext("$root", nil)) + if err != nil { + return nil, err + } + return proto.Marshal(document) +} + +func toGzip(data []byte) []byte { + var buf bytes.Buffer + zw := gzip.NewWriter(&buf) + zw.Write(data) + zw.Close() + return buf.Bytes() +} + +// RegisterOpenAPIVersionedService registers a handler to provide access to provided swagger spec. +func RegisterOpenAPIVersionedService(openapiSpec *spec.Swagger, servePath string, handler common.PathHandler) (*OpenAPIService, error) { + o := OpenAPIService{} + if err := o.UpdateSpec(openapiSpec); err != nil { + return nil, err + } + + accepted := []struct { + Type string + SubType string + GetDataAndETag func() ([]byte, string, time.Time) + }{ + {"application", "json", o.getSwaggerBytes}, + {"application", "com.github.proto-openapi.spec.v2@v1.0+protobuf", o.getSwaggerPbBytes}, + } + + handler.Handle(servePath, gziphandler.GzipHandler(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + decipherableFormats := r.Header.Get("Accept") + if decipherableFormats == "" { + decipherableFormats = "*/*" + } + clauses := goautoneg.ParseAccept(decipherableFormats) + w.Header().Add("Vary", "Accept") + for _, clause := range clauses { + for _, accepts := range accepted { + if clause.Type != accepts.Type && clause.Type != "*" { + continue + } + if clause.SubType != accepts.SubType && clause.SubType != "*" { + continue + } + + // serve the first matching media type in the sorted clause list + data, etag, lastModified := accepts.GetDataAndETag() + w.Header().Set("Etag", etag) + // ServeContent will take care of caching using eTag. + http.ServeContent(w, r, servePath, lastModified, bytes.NewReader(data)) + return + } + } + // Return 406 for not acceptable format + w.WriteHeader(406) + return + }), + )) + + return &o, nil +} + +// BuildAndRegisterOpenAPIVersionedService builds the spec and registers a handler to provide access to it. +// Use this method if your OpenAPI spec is static. If you want to update the spec, use BuildOpenAPISpec then RegisterOpenAPIVersionedService. +func BuildAndRegisterOpenAPIVersionedService(servePath string, webServices []*restful.WebService, config *common.Config, handler common.PathHandler) (*OpenAPIService, error) { + spec, err := builder.BuildOpenAPISpec(webServices, config) + if err != nil { + return nil, err + } + return RegisterOpenAPIVersionedService(spec, servePath, handler) +} diff --git a/vendor/k8s.io/kube-openapi/pkg/handler/handler_test.go b/vendor/k8s.io/kube-openapi/pkg/handler/handler_test.go new file mode 100644 index 000000000..8d7146c10 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/handler/handler_test.go @@ -0,0 +1,89 @@ +package handler + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "net/http/httptest" + "reflect" + "testing" + + "github.com/go-openapi/spec" +) + +var returnedSwagger = []byte(`{ + "swagger": "2.0", + "info": { + "title": "Kubernetes", + "version": "v1.11.0" + }}`) + +func TestRegisterOpenAPIVersionedService(t *testing.T) { + var s spec.Swagger + err := s.UnmarshalJSON(returnedSwagger) + if err != nil { + t.Errorf("Unexpected error in unmarshalling SwaggerJSON: %v", err) + } + + returnedJSON, err := json.MarshalIndent(s, " ", " ") + if err != nil { + t.Errorf("Unexpected error in preparing returnedJSON: %v", err) + } + returnedPb, err := toProtoBinary(returnedJSON) + if err != nil { + t.Errorf("Unexpected error in preparing returnedPb: %v", err) + } + + mux := http.NewServeMux() + _, err = RegisterOpenAPIVersionedService(&s, "/openapi/v2", mux) + if err != nil { + t.Errorf("Unexpected error in register OpenAPI versioned service: %v", err) + } + server := httptest.NewServer(mux) + defer server.Close() + client := server.Client() + + tcs := []struct { + acceptHeader string + respStatus int + respBody []byte + }{ + {"", 200, returnedJSON}, + {"*/*", 200, returnedJSON}, + {"application/*", 200, returnedJSON}, + {"application/json", 200, returnedJSON}, + {"test/test", 406, []byte{}}, + {"application/test", 406, []byte{}}, + {"application/test, */*", 200, returnedJSON}, + {"application/test, application/json", 200, returnedJSON}, + {"application/com.github.proto-openapi.spec.v2@v1.0+protobuf", 200, returnedPb}, + {"application/json, application/com.github.proto-openapi.spec.v2@v1.0+protobuf", 200, returnedJSON}, + {"application/com.github.proto-openapi.spec.v2@v1.0+protobuf, application/json", 200, returnedPb}, + {"application/com.github.proto-openapi.spec.v2@v1.0+protobuf; q=0.5, application/json", 200, returnedJSON}, + } + + for _, tc := range tcs { + req, err := http.NewRequest("GET", server.URL+"/openapi/v2", nil) + if err != nil { + t.Errorf("Accept: %v: Unexpected error in creating new request: %v", tc.acceptHeader, err) + } + + req.Header.Add("Accept", tc.acceptHeader) + resp, err := client.Do(req) + if err != nil { + t.Errorf("Accept: %v: Unexpected error in serving HTTP request: %v", tc.acceptHeader, err) + } + + if resp.StatusCode != tc.respStatus { + t.Errorf("Accept: %v: Unexpected response status code, want: %v, got: %v", tc.acceptHeader, tc.respStatus, resp.StatusCode) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Errorf("Accept: %v: Unexpected error in reading response body: %v", tc.acceptHeader, err) + } + if !reflect.DeepEqual(body, tc.respBody) { + t.Errorf("Accept: %v: Response body mismatches, want: %v, got: %v", tc.acceptHeader, tc.respBody, body) + } + } +} diff --git a/vendor/k8s.io/kube-openapi/pkg/idl/doc.go b/vendor/k8s.io/kube-openapi/pkg/idl/doc.go new file mode 100644 index 000000000..9d59aaf0e --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/idl/doc.go @@ -0,0 +1,140 @@ +/* +Copyright 2018 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. +*/ + +// The IDL package describes comment directives that may be applied to +// API types and fields. +package idl + +// ListType annotates a list to further describe its topology. It may +// have 3 possible values: "atomic", "map", or "set". Note that there is +// no default, and the generation step will fail if a list is found that +// is missing the tag. +// +// This tag MUST only be used on lists, or the generation step will +// fail. +// +// Atomic +// +// Example: +// +listType=atomic +// +// Atomic lists will be entirely replaced when updated. This tag may be +// used on any type of list (struct, scalar, ...). +// +// Using this tag will generate the following OpenAPI extension: +// "x-kubernetes-list-type": "atomic" +// +// Map +// +// Example: +// +listType=map +// +// These lists are like maps in that their elements have a non-index key +// used to identify them. Order is preserved upon merge. Using the map +// tag on a list with non-struct elements will result in an error during +// the generation step. +// +// Using this tag will generate the following OpenAPI extension: +// "x-kubernetes-list-type": "map" +// +// Set +// +// Example: +// +listType=set +// +// Sets are lists that must not have multiple times the same value. Each +// value must be a scalar (or another atomic type). +// +// Using this tag will generate the following OpenAPI extension: +// "x-kubernetes-list-type": "set" +type ListType string + +// ListMapKey annotates map lists by specifying the key used as the index of the map. +// +// This tag MUST only be used on lists that have the listType=map +// attribute, or the generation step will fail. Also, the value +// specified for this attribute must be a scalar typed field of the +// child structure (no nesting is supported). +// +// An example of how this can be used is shown in the ListType (map) example. +// +// Example: +// +listMapKey=name +// +// Using this tag will generate the following OpenAPI extension: +// "x-kubernetes-list-map-key": "name" +type ListMapKey string + +// MapType annotates a map to further describe its topology. It may +// have only one value: "atomic". Atomic means that the entire map is +// considered as a whole, rather than as distinct values. +// +// By default, a map will be considered as a set of distinct values that +// can be updated individually. This default WILL NOT generate any +// openapi extension, as this will also be interpreted as the default +// behavior in the openapi definition. +// +// This tag MUST only be used on maps, or the generation step will fail. +// +// Atomic +// +// Example: +// +mapType=atomic +// +// Atomic maps will be entirely replaced when updated. This tag may be +// used on any map. +// +// Using this tag will generate the following OpenAPI extension: +// "x-kubernetes-map-type": "atomic" +type MapType string + +// OpenAPIGen needs to be described. +type OpenAPIGen string + +// Optional needs to be described. +type Optional string + +// PatchMergeKey needs to be described. +type PatchMergeKey string + +// PatchStrategy needs to be described. +type PatchStrategy string + +// StructType annotates a struct to further describe its topology. It may +// have only one value: "atomic". Atomic means that the entire struct is +// considered as a whole, rather than as distinct values. +// +// By default, a struct will be considered as a set of distinct values that +// can be updated individually. This default WILL NOT generate any +// openapi extension, as this will also be interpreted as the default +// behavior in the openapi definition. +// +// This tag MUST only be used on structs, or the generation step will fail. +// +// Atomic +// +// Example: +// +structType=atomic +// +// Atomic structs will be entirely replaced when updated. This tag may be +// used on any struct. +// +// Using this tag will generate the following OpenAPI extension: +// "x-kubernetes-struct-type": "atomic" +type StructType string + +// Union is TBD. +type Union string diff --git a/vendor/k8s.io/kube-openapi/pkg/idl/listtype_test.go b/vendor/k8s.io/kube-openapi/pkg/idl/listtype_test.go new file mode 100644 index 000000000..2fcc148e2 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/idl/listtype_test.go @@ -0,0 +1,56 @@ +/* +Copyright 2018 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 idl_test + +// This example shows how to use the listType map attribute and how to +// specify a key to identify elements of the list. The listMapKey +// attribute is used to specify that Name is the key of the map. +func ExampleListType_map() { + type SomeStruct struct { + Name string + Value string + } + type SomeAPI struct { + // +listType=map + // +listMapKey=name + elements []SomeStruct + } +} + +// This example shows how to use the listType set attribute to specify +// that this list should be treated as a set: items in the list can't be +// duplicated. +func ExampleListType_set() { + type SomeAPI struct { + // +listType=set + keys []string + } +} + +// This example shows how to use the listType atomic attribute to +// specify that this list should be treated as a whole. +func ExampleListType_atomic() { + type SomeStruct struct { + Name string + Value string + } + + type SomeAPI struct { + // +listType=atomic + elements []SomeStruct + } +} diff --git a/vendor/k8s.io/kube-openapi/pkg/idl/maptype_test.go b/vendor/k8s.io/kube-openapi/pkg/idl/maptype_test.go new file mode 100644 index 000000000..c791b1a54 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/idl/maptype_test.go @@ -0,0 +1,26 @@ +/* +Copyright 2018 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 idl_test + +// This example shows how to use the mapType atomic attribute to +// specify that this map should be treated as a whole. +func ExampleMapType_atomic() { + type SomeAPI struct { + // +mapType=atomic + elements map[string]string + } +} diff --git a/vendor/k8s.io/kube-openapi/pkg/idl/structtype_test.go b/vendor/k8s.io/kube-openapi/pkg/idl/structtype_test.go new file mode 100644 index 000000000..a7d8f933d --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/idl/structtype_test.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 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 idl_test + +// This example shows how to use the structType atomic attribute to +// specify that this struct should be treated as a whole. +func ExampleStructType_atomic() { + type SomeStruct struct { + Name string + Value string + } + type SomeAPI struct { + // +structType=atomic + elements SomeStruct + } +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/doc.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/doc.go new file mode 100644 index 000000000..11ed8a6b7 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/doc.go @@ -0,0 +1,19 @@ +/* +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 proto is a collection of libraries for parsing and indexing the type definitions. +// The openapi spec contains the object model definitions and extensions metadata. +package proto diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go new file mode 100644 index 000000000..a57dcd363 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go @@ -0,0 +1,299 @@ +/* +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 proto + +import ( + "fmt" + "sort" + "strings" + + "github.com/googleapis/gnostic/OpenAPIv2" + "gopkg.in/yaml.v2" +) + +func newSchemaError(path *Path, format string, a ...interface{}) error { + err := fmt.Sprintf(format, a...) + if path.Len() == 0 { + return fmt.Errorf("SchemaError: %v", err) + } + return fmt.Errorf("SchemaError(%v): %v", path, err) +} + +// VendorExtensionToMap converts openapi VendorExtension to a map. +func VendorExtensionToMap(e []*openapi_v2.NamedAny) map[string]interface{} { + values := map[string]interface{}{} + + for _, na := range e { + if na.GetName() == "" || na.GetValue() == nil { + continue + } + if na.GetValue().GetYaml() == "" { + continue + } + var value interface{} + err := yaml.Unmarshal([]byte(na.GetValue().GetYaml()), &value) + if err != nil { + continue + } + + values[na.GetName()] = value + } + + return values +} + +// Definitions is an implementation of `Models`. It looks for +// models in an openapi Schema. +type Definitions struct { + models map[string]Schema +} + +var _ Models = &Definitions{} + +// NewOpenAPIData creates a new `Models` out of the openapi document. +func NewOpenAPIData(doc *openapi_v2.Document) (Models, error) { + definitions := Definitions{ + models: map[string]Schema{}, + } + + // Save the list of all models first. This will allow us to + // validate that we don't have any dangling reference. + for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() { + definitions.models[namedSchema.GetName()] = nil + } + + // Now, parse each model. We can validate that references exists. + for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() { + path := NewPath(namedSchema.GetName()) + schema, err := definitions.ParseSchema(namedSchema.GetValue(), &path) + if err != nil { + return nil, err + } + definitions.models[namedSchema.GetName()] = schema + } + + return &definitions, nil +} + +// We believe the schema is a reference, verify that and returns a new +// Schema +func (d *Definitions) parseReference(s *openapi_v2.Schema, path *Path) (Schema, error) { + if len(s.GetProperties().GetAdditionalProperties()) > 0 { + return nil, newSchemaError(path, "unallowed embedded type definition") + } + if len(s.GetType().GetValue()) > 0 { + return nil, newSchemaError(path, "definition reference can't have a type") + } + + if !strings.HasPrefix(s.GetXRef(), "#/definitions/") { + return nil, newSchemaError(path, "unallowed reference to non-definition %q", s.GetXRef()) + } + reference := strings.TrimPrefix(s.GetXRef(), "#/definitions/") + if _, ok := d.models[reference]; !ok { + return nil, newSchemaError(path, "unknown model in reference: %q", reference) + } + return &Ref{ + BaseSchema: d.parseBaseSchema(s, path), + reference: reference, + definitions: d, + }, nil +} + +func (d *Definitions) parseBaseSchema(s *openapi_v2.Schema, path *Path) BaseSchema { + return BaseSchema{ + Description: s.GetDescription(), + Extensions: VendorExtensionToMap(s.GetVendorExtension()), + Path: *path, + } +} + +// We believe the schema is a map, verify and return a new schema +func (d *Definitions) parseMap(s *openapi_v2.Schema, path *Path) (Schema, error) { + if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object { + return nil, newSchemaError(path, "invalid object type") + } + var sub Schema + if s.GetAdditionalProperties().GetSchema() == nil { + sub = &Arbitrary{ + BaseSchema: d.parseBaseSchema(s, path), + } + } else { + var err error + sub, err = d.ParseSchema(s.GetAdditionalProperties().GetSchema(), path) + if err != nil { + return nil, err + } + } + return &Map{ + BaseSchema: d.parseBaseSchema(s, path), + SubType: sub, + }, nil +} + +func (d *Definitions) parsePrimitive(s *openapi_v2.Schema, path *Path) (Schema, error) { + var t string + if len(s.GetType().GetValue()) > 1 { + return nil, newSchemaError(path, "primitive can't have more than 1 type") + } + if len(s.GetType().GetValue()) == 1 { + t = s.GetType().GetValue()[0] + } + switch t { + case String: // do nothing + case Number: // do nothing + case Integer: // do nothing + case Boolean: // do nothing + default: + return nil, newSchemaError(path, "Unknown primitive type: %q", t) + } + return &Primitive{ + BaseSchema: d.parseBaseSchema(s, path), + Type: t, + Format: s.GetFormat(), + }, nil +} + +func (d *Definitions) parseArray(s *openapi_v2.Schema, path *Path) (Schema, error) { + if len(s.GetType().GetValue()) != 1 { + return nil, newSchemaError(path, "array should have exactly one type") + } + if s.GetType().GetValue()[0] != array { + return nil, newSchemaError(path, `array should have type "array"`) + } + if len(s.GetItems().GetSchema()) != 1 { + return nil, newSchemaError(path, "array should have exactly one sub-item") + } + sub, err := d.ParseSchema(s.GetItems().GetSchema()[0], path) + if err != nil { + return nil, err + } + return &Array{ + BaseSchema: d.parseBaseSchema(s, path), + SubType: sub, + }, nil +} + +func (d *Definitions) parseKind(s *openapi_v2.Schema, path *Path) (Schema, error) { + if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object { + return nil, newSchemaError(path, "invalid object type") + } + if s.GetProperties() == nil { + return nil, newSchemaError(path, "object doesn't have properties") + } + + fields := map[string]Schema{} + + for _, namedSchema := range s.GetProperties().GetAdditionalProperties() { + var err error + path := path.FieldPath(namedSchema.GetName()) + fields[namedSchema.GetName()], err = d.ParseSchema(namedSchema.GetValue(), &path) + if err != nil { + return nil, err + } + } + + return &Kind{ + BaseSchema: d.parseBaseSchema(s, path), + RequiredFields: s.GetRequired(), + Fields: fields, + }, nil +} + +func (d *Definitions) parseArbitrary(s *openapi_v2.Schema, path *Path) (Schema, error) { + return &Arbitrary{ + BaseSchema: d.parseBaseSchema(s, path), + }, nil +} + +// ParseSchema creates a walkable Schema from an openapi schema. While +// this function is public, it doesn't leak through the interface. +func (d *Definitions) ParseSchema(s *openapi_v2.Schema, path *Path) (Schema, error) { + if s.GetXRef() != "" { + return d.parseReference(s, path) + } + objectTypes := s.GetType().GetValue() + switch len(objectTypes) { + case 0: + // in the OpenAPI schema served by older k8s versions, object definitions created from structs did not include + // the type:object property (they only included the "properties" property), so we need to handle this case + if s.GetProperties() != nil { + return d.parseKind(s, path) + } else { + // Definition has no type and no properties. Treat it as an arbitrary value + // TODO: what if it has additionalProperties or patternProperties? + return d.parseArbitrary(s, path) + } + case 1: + t := objectTypes[0] + switch t { + case object: + if s.GetProperties() != nil { + return d.parseKind(s, path) + } else { + return d.parseMap(s, path) + } + case array: + return d.parseArray(s, path) + } + return d.parsePrimitive(s, path) + default: + // the OpenAPI generator never generates (nor it ever did in the past) OpenAPI type definitions with multiple types + return nil, newSchemaError(path, "definitions with multiple types aren't supported") + } +} + +// LookupModel is public through the interface of Models. It +// returns a visitable schema from the given model name. +func (d *Definitions) LookupModel(model string) Schema { + return d.models[model] +} + +func (d *Definitions) ListModels() []string { + models := []string{} + + for model := range d.models { + models = append(models, model) + } + + sort.Strings(models) + return models +} + +type Ref struct { + BaseSchema + + reference string + definitions *Definitions +} + +var _ Reference = &Ref{} + +func (r *Ref) Reference() string { + return r.reference +} + +func (r *Ref) SubSchema() Schema { + return r.definitions.models[r.reference] +} + +func (r *Ref) Accept(v SchemaVisitor) { + v.VisitReference(r) +} + +func (r *Ref) GetName() string { + return fmt.Sprintf("Reference to %q", r.reference) +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go new file mode 100644 index 000000000..f26b5ef88 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go @@ -0,0 +1,276 @@ +/* +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 proto + +import ( + "fmt" + "sort" + "strings" +) + +// Defines openapi types. +const ( + Integer = "integer" + Number = "number" + String = "string" + Boolean = "boolean" + + // These types are private as they should never leak, and are + // represented by actual structs. + array = "array" + object = "object" +) + +// Models interface describe a model provider. They can give you the +// schema for a specific model. +type Models interface { + LookupModel(string) Schema + ListModels() []string +} + +// SchemaVisitor is an interface that you need to implement if you want +// to "visit" an openapi schema. A dispatch on the Schema type will call +// the appropriate function based on its actual type: +// - Array is a list of one and only one given subtype +// - Map is a map of string to one and only one given subtype +// - Primitive can be string, integer, number and boolean. +// - Kind is an object with specific fields mapping to specific types. +// - Reference is a link to another definition. +type SchemaVisitor interface { + VisitArray(*Array) + VisitMap(*Map) + VisitPrimitive(*Primitive) + VisitKind(*Kind) + VisitReference(Reference) +} + +// SchemaVisitorArbitrary is an additional visitor interface which handles +// arbitrary types. For backwards compatibility, it's a separate interface +// which is checked for at runtime. +type SchemaVisitorArbitrary interface { + SchemaVisitor + VisitArbitrary(*Arbitrary) +} + +// Schema is the base definition of an openapi type. +type Schema interface { + // Giving a visitor here will let you visit the actual type. + Accept(SchemaVisitor) + + // Pretty print the name of the type. + GetName() string + // Describes how to access this field. + GetPath() *Path + // Describes the field. + GetDescription() string + // Returns type extensions. + GetExtensions() map[string]interface{} +} + +// Path helps us keep track of type paths +type Path struct { + parent *Path + key string +} + +func NewPath(key string) Path { + return Path{key: key} +} + +func (p *Path) Get() []string { + if p == nil { + return []string{} + } + if p.key == "" { + return p.parent.Get() + } + return append(p.parent.Get(), p.key) +} + +func (p *Path) Len() int { + return len(p.Get()) +} + +func (p *Path) String() string { + return strings.Join(p.Get(), "") +} + +// ArrayPath appends an array index and creates a new path +func (p *Path) ArrayPath(i int) Path { + return Path{ + parent: p, + key: fmt.Sprintf("[%d]", i), + } +} + +// FieldPath appends a field name and creates a new path +func (p *Path) FieldPath(field string) Path { + return Path{ + parent: p, + key: fmt.Sprintf(".%s", field), + } +} + +// BaseSchema holds data used by each types of schema. +type BaseSchema struct { + Description string + Extensions map[string]interface{} + + Path Path +} + +func (b *BaseSchema) GetDescription() string { + return b.Description +} + +func (b *BaseSchema) GetExtensions() map[string]interface{} { + return b.Extensions +} + +func (b *BaseSchema) GetPath() *Path { + return &b.Path +} + +// Array must have all its element of the same `SubType`. +type Array struct { + BaseSchema + + SubType Schema +} + +var _ Schema = &Array{} + +func (a *Array) Accept(v SchemaVisitor) { + v.VisitArray(a) +} + +func (a *Array) GetName() string { + return fmt.Sprintf("Array of %s", a.SubType.GetName()) +} + +// Kind is a complex object. It can have multiple different +// subtypes for each field, as defined in the `Fields` field. Mandatory +// fields are listed in `RequiredFields`. The key of the object is +// always of type `string`. +type Kind struct { + BaseSchema + + // Lists names of required fields. + RequiredFields []string + // Maps field names to types. + Fields map[string]Schema +} + +var _ Schema = &Kind{} + +func (k *Kind) Accept(v SchemaVisitor) { + v.VisitKind(k) +} + +func (k *Kind) GetName() string { + properties := []string{} + for key := range k.Fields { + properties = append(properties, key) + } + return fmt.Sprintf("Kind(%v)", properties) +} + +// IsRequired returns true if `field` is a required field for this type. +func (k *Kind) IsRequired(field string) bool { + for _, f := range k.RequiredFields { + if f == field { + return true + } + } + return false +} + +// Keys returns a alphabetically sorted list of keys. +func (k *Kind) Keys() []string { + keys := make([]string, 0) + for key := range k.Fields { + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} + +// Map is an object who values must all be of the same `SubType`. +// The key of the object is always of type `string`. +type Map struct { + BaseSchema + + SubType Schema +} + +var _ Schema = &Map{} + +func (m *Map) Accept(v SchemaVisitor) { + v.VisitMap(m) +} + +func (m *Map) GetName() string { + return fmt.Sprintf("Map of %s", m.SubType.GetName()) +} + +// Primitive is a literal. There can be multiple types of primitives, +// and this subtype can be visited through the `subType` field. +type Primitive struct { + BaseSchema + + // Type of a primitive must be one of: integer, number, string, boolean. + Type string + Format string +} + +var _ Schema = &Primitive{} + +func (p *Primitive) Accept(v SchemaVisitor) { + v.VisitPrimitive(p) +} + +func (p *Primitive) GetName() string { + if p.Format == "" { + return p.Type + } + return fmt.Sprintf("%s (%s)", p.Type, p.Format) +} + +// Arbitrary is a value of any type (primitive, object or array) +type Arbitrary struct { + BaseSchema +} + +var _ Schema = &Arbitrary{} + +func (a *Arbitrary) Accept(v SchemaVisitor) { + if visitor, ok := v.(SchemaVisitorArbitrary); ok { + visitor.VisitArbitrary(a) + } +} + +func (a *Arbitrary) GetName() string { + return "Arbitrary value (primitive, object or array)" +} + +// Reference implementation depends on the type of document. +type Reference interface { + Schema + + Reference() string + SubSchema() Schema +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi_suite_test.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi_suite_test.go new file mode 100644 index 000000000..24b5168e4 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi_suite_test.go @@ -0,0 +1,49 @@ +/* +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 proto_test + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/config" + . "github.com/onsi/ginkgo/types" + . "github.com/onsi/gomega" + + "fmt" + "testing" +) + +func TestOpenapi(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecsWithDefaultAndCustomReporters(t, "Openapi Suite", []Reporter{newlineReporter{}}) +} + +// Print a newline after the default newlineReporter due to issue +// https://github.com/jstemmer/go-junit-report/issues/31 +type newlineReporter struct{} + +func (newlineReporter) SpecSuiteWillBegin(config GinkgoConfigType, summary *SuiteSummary) {} + +func (newlineReporter) BeforeSuiteDidRun(setupSummary *SetupSummary) {} + +func (newlineReporter) AfterSuiteDidRun(setupSummary *SetupSummary) {} + +func (newlineReporter) SpecWillRun(specSummary *SpecSummary) {} + +func (newlineReporter) SpecDidComplete(specSummary *SpecSummary) {} + +// SpecSuiteDidEnd Prints a newline between "35 Passed | 0 Failed | 0 Pending | 0 Skipped" and "--- PASS:" +func (newlineReporter) SpecSuiteDidEnd(summary *SuiteSummary) { fmt.Printf("\n") } diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi_test.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi_test.go new file mode 100644 index 000000000..b6e237256 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi_test.go @@ -0,0 +1,265 @@ +/* +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 proto_test + +import ( + "path/filepath" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "k8s.io/kube-openapi/pkg/util/proto" + "k8s.io/kube-openapi/pkg/util/proto/testing" +) + +var fakeSchema = testing.Fake{Path: filepath.Join("testdata", "swagger.json")} +var fakeSchemaNext = testing.Fake{Path: filepath.Join("testdata", "swagger_next.json")} + +var _ = Describe("Reading apps/v1beta1/Deployment from v1.8 openAPIData", func() { + var models proto.Models + BeforeEach(func() { + s, err := fakeSchema.OpenAPISchema() + Expect(err).To(BeNil()) + models, err = proto.NewOpenAPIData(s) + Expect(err).To(BeNil()) + }) + + model := "io.k8s.api.apps.v1beta1.Deployment" + var schema proto.Schema + It("should lookup the Schema by its model name", func() { + schema = models.LookupModel(model) + Expect(schema).ToNot(BeNil()) + }) + + var deployment *proto.Kind + It("should be a Kind", func() { + deployment = schema.(*proto.Kind) + Expect(deployment).ToNot(BeNil()) + }) + + It("should have a path", func() { + Expect(deployment.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.Deployment"})) + }) + + It("should have a kind key of type string", func() { + Expect(deployment.Fields).To(HaveKey("kind")) + key := deployment.Fields["kind"].(*proto.Primitive) + Expect(key).ToNot(BeNil()) + Expect(key.Type).To(Equal("string")) + Expect(key.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.Deployment", ".kind"})) + }) + + It("should have a apiVersion key of type string", func() { + Expect(deployment.Fields).To(HaveKey("apiVersion")) + key := deployment.Fields["apiVersion"].(*proto.Primitive) + Expect(key).ToNot(BeNil()) + Expect(key.Type).To(Equal("string")) + Expect(key.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.Deployment", ".apiVersion"})) + }) + + It("should have a metadata key of type Reference", func() { + Expect(deployment.Fields).To(HaveKey("metadata")) + key := deployment.Fields["metadata"].(proto.Reference) + Expect(key).ToNot(BeNil()) + Expect(key.Reference()).To(Equal("io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta")) + subSchema := key.SubSchema().(*proto.Kind) + Expect(subSchema).ToNot(BeNil()) + }) + + var status *proto.Kind + It("should have a status key of type Reference", func() { + Expect(deployment.Fields).To(HaveKey("status")) + key := deployment.Fields["status"].(proto.Reference) + Expect(key).ToNot(BeNil()) + Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentStatus")) + status = key.SubSchema().(*proto.Kind) + Expect(status).ToNot(BeNil()) + }) + + It("should have a valid DeploymentStatus", func() { + By("having availableReplicas key") + Expect(status.Fields).To(HaveKey("availableReplicas")) + replicas := status.Fields["availableReplicas"].(*proto.Primitive) + Expect(replicas).ToNot(BeNil()) + Expect(replicas.Type).To(Equal("integer")) + + By("having conditions key") + Expect(status.Fields).To(HaveKey("conditions")) + conditions := status.Fields["conditions"].(*proto.Array) + Expect(conditions).ToNot(BeNil()) + Expect(conditions.GetName()).To(Equal(`Array of Reference to "io.k8s.api.apps.v1beta1.DeploymentCondition"`)) + Expect(conditions.GetExtensions()).To(Equal(map[string]interface{}{ + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge", + })) + condition := conditions.SubType.(proto.Reference) + Expect(condition.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentCondition")) + }) + + var spec *proto.Kind + It("should have a spec key of type Reference", func() { + Expect(deployment.Fields).To(HaveKey("spec")) + key := deployment.Fields["spec"].(proto.Reference) + Expect(key).ToNot(BeNil()) + Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentSpec")) + spec = key.SubSchema().(*proto.Kind) + Expect(spec).ToNot(BeNil()) + }) + + It("should have a spec with no gvk", func() { + _, found := spec.GetExtensions()["x-kubernetes-group-version-kind"] + Expect(found).To(BeFalse()) + }) + + It("should have a spec with a PodTemplateSpec sub-field", func() { + Expect(spec.Fields).To(HaveKey("template")) + key := spec.Fields["template"].(proto.Reference) + Expect(key).ToNot(BeNil()) + Expect(key.Reference()).To(Equal("io.k8s.api.core.v1.PodTemplateSpec")) + }) +}) + +var _ = Describe("Reading apps/v1beta1/Deployment from v1.11 openAPIData", func() { + var models proto.Models + BeforeEach(func() { + s, err := fakeSchemaNext.OpenAPISchema() + Expect(err).To(BeNil()) + models, err = proto.NewOpenAPIData(s) + Expect(err).To(BeNil()) + }) + + model := "io.k8s.api.apps.v1beta1.Deployment" + var schema proto.Schema + It("should lookup the Schema by its model name", func() { + schema = models.LookupModel(model) + Expect(schema).ToNot(BeNil()) + }) + + var deployment *proto.Kind + It("should be a Kind", func() { + deployment = schema.(*proto.Kind) + Expect(deployment).ToNot(BeNil()) + }) +}) + +var _ = Describe("Reading apps/v1beta1/ControllerRevision from v1.11 openAPIData", func() { + var models proto.Models + BeforeEach(func() { + s, err := fakeSchemaNext.OpenAPISchema() + Expect(err).To(BeNil()) + models, err = proto.NewOpenAPIData(s) + Expect(err).To(BeNil()) + }) + + model := "io.k8s.api.apps.v1beta1.ControllerRevision" + var schema proto.Schema + It("should lookup the Schema by its model name", func() { + schema = models.LookupModel(model) + Expect(schema).ToNot(BeNil()) + }) + + var cr *proto.Kind + It("data property should be map[string]Arbitrary", func() { + cr = schema.(*proto.Kind) + Expect(cr).ToNot(BeNil()) + Expect(cr.Fields).To(HaveKey("data")) + + data := cr.Fields["data"].(*proto.Map) + Expect(data).ToNot(BeNil()) + Expect(data.GetName()).To(Equal("Map of Arbitrary value (primitive, object or array)")) + Expect(data.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.ControllerRevision", ".data"})) + + arbitrary := data.SubType.(*proto.Arbitrary) + Expect(arbitrary).ToNot(BeNil()) + Expect(arbitrary.GetName()).To(Equal("Arbitrary value (primitive, object or array)")) + Expect(arbitrary.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.ControllerRevision", ".data"})) + }) +}) + +var _ = Describe("Reading authorization.k8s.io/v1/SubjectAccessReview from openAPIData", func() { + var models proto.Models + BeforeEach(func() { + s, err := fakeSchema.OpenAPISchema() + Expect(err).To(BeNil()) + models, err = proto.NewOpenAPIData(s) + Expect(err).To(BeNil()) + }) + + model := "io.k8s.api.authorization.v1.LocalSubjectAccessReview" + var schema proto.Schema + It("should lookup the Schema by its model", func() { + schema = models.LookupModel(model) + Expect(schema).ToNot(BeNil()) + }) + + var sarspec *proto.Kind + It("should be a Kind and have a spec", func() { + sar := schema.(*proto.Kind) + Expect(sar).ToNot(BeNil()) + Expect(sar.Fields).To(HaveKey("spec")) + specRef := sar.Fields["spec"].(proto.Reference) + Expect(specRef).ToNot(BeNil()) + Expect(specRef.Reference()).To(Equal("io.k8s.api.authorization.v1.SubjectAccessReviewSpec")) + sarspec = specRef.SubSchema().(*proto.Kind) + Expect(sarspec).ToNot(BeNil()) + }) + + It("should have a valid SubjectAccessReviewSpec", func() { + Expect(sarspec.Fields).To(HaveKey("extra")) + extra := sarspec.Fields["extra"].(*proto.Map) + Expect(extra).ToNot(BeNil()) + Expect(extra.GetName()).To(Equal("Map of Array of string")) + Expect(extra.GetPath().Get()).To(Equal([]string{"io.k8s.api.authorization.v1.SubjectAccessReviewSpec", ".extra"})) + array := extra.SubType.(*proto.Array) + Expect(array).ToNot(BeNil()) + Expect(array.GetName()).To(Equal("Array of string")) + Expect(array.GetPath().Get()).To(Equal([]string{"io.k8s.api.authorization.v1.SubjectAccessReviewSpec", ".extra"})) + str := array.SubType.(*proto.Primitive) + Expect(str).ToNot(BeNil()) + Expect(str.Type).To(Equal("string")) + Expect(str.GetName()).To(Equal("string")) + Expect(str.GetPath().Get()).To(Equal([]string{"io.k8s.api.authorization.v1.SubjectAccessReviewSpec", ".extra"})) + }) +}) + +var _ = Describe("Path", func() { + It("can be created by NewPath", func() { + path := proto.NewPath("key") + Expect(path.String()).To(Equal("key")) + }) + It("can create and print complex paths", func() { + key := proto.NewPath("key") + array := key.ArrayPath(12) + field := array.FieldPath("subKey") + + Expect(field.String()).To(Equal("key[12].subKey")) + }) + It("has a length", func() { + key := proto.NewPath("key") + array := key.ArrayPath(12) + field := array.FieldPath("subKey") + + Expect(field.Len()).To(Equal(3)) + }) + It("can look like an array", func() { + key := proto.NewPath("key") + array := key.ArrayPath(12) + field := array.FieldPath("subKey") + + Expect(field.Get()).To(Equal([]string{"key", "[12]", ".subKey"})) + }) +}) diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/testdata/swagger.json b/vendor/k8s.io/kube-openapi/pkg/util/proto/testdata/swagger.json new file mode 100644 index 000000000..0e15f86b8 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/testdata/swagger.json @@ -0,0 +1,6375 @@ +{ + "swagger": "2.0", + "info": { + "title": "Kubernetes", + "version": "v1.8.0" + }, + "paths": {}, + "definitions": { + "io.k8s.api.apps.v1beta1.ControllerRevision": { + "description": "ControllerRevision implements an immutable snapshot of state data. Clients are responsible for serializing and deserializing the objects that contain their internal state. Once a ControllerRevision has been successfully created, it can not be updated. The API Server will fail validation of all requests that attempt to mutate the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, it may be subject to name and representation changes in future releases, and clients should not depend on its stability. It is primarily for internal use by controllers.", + "required": [ + "revision" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "data": { + "description": "Data is the serialized representation of the state.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.runtime.RawExtension" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "revision": { + "description": "Revision indicates the revision of the state represented by Data.", + "type": "integer", + "format": "int64" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "ControllerRevision", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.ControllerRevisionList": { + "description": "ControllerRevisionList is a resource containing a list of ControllerRevision objects.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is the list of ControllerRevisions", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.ControllerRevision" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "ControllerRevisionList", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.Deployment": { + "description": "Deployment enables declarative updates for Pods and ReplicaSets.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object metadata.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Specification of the desired behavior of the Deployment.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentSpec" + }, + "status": { + "description": "Most recently observed status of the Deployment.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "Deployment", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.DeploymentCondition": { + "description": "DeploymentCondition describes the state of a deployment at a certain point.", + "required": [ + "type", + "status" + ], + "properties": { + "lastTransitionTime": { + "description": "Last time the condition transitioned from one status to another.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "lastUpdateTime": { + "description": "The last time this condition was updated.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "A human readable message indicating details about the transition.", + "type": "string" + }, + "reason": { + "description": "The reason for the condition's last transition.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of deployment condition.", + "type": "string" + } + } + }, + "io.k8s.api.apps.v1beta1.DeploymentList": { + "description": "DeploymentList is a list of Deployments.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is the list of Deployments.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.Deployment" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "DeploymentList", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.DeploymentRollback": { + "description": "DEPRECATED. DeploymentRollback stores the information required to rollback a deployment.", + "required": [ + "name", + "rollbackTo" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "Required: This must match the Name of a deployment.", + "type": "string" + }, + "rollbackTo": { + "description": "The config of this deployment rollback.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.RollbackConfig" + }, + "updatedAnnotations": { + "description": "The annotations to be updated to a deployment", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "DeploymentRollback", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.DeploymentSpec": { + "description": "DeploymentSpec is the specification of the desired behavior of the Deployment.", + "required": [ + "template" + ], + "properties": { + "minReadySeconds": { + "description": "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)", + "type": "integer", + "format": "int32" + }, + "paused": { + "description": "Indicates that the deployment is paused.", + "type": "boolean" + }, + "progressDeadlineSeconds": { + "description": "The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Once autoRollback is implemented, the deployment controller will automatically rollback failed deployments. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s.", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1.", + "type": "integer", + "format": "int32" + }, + "revisionHistoryLimit": { + "description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 2.", + "type": "integer", + "format": "int32" + }, + "rollbackTo": { + "description": "DEPRECATED. The config this deployment is rolling back to. Will be cleared after rollback is done.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.RollbackConfig" + }, + "selector": { + "description": "Label selector for pods. Existing ReplicaSets whose pods are selected by this will be the ones affected by this deployment.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, + "strategy": { + "description": "The deployment strategy to use to replace existing pods with new ones.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentStrategy" + }, + "template": { + "description": "Template describes the pods that will be created.", + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" + } + } + }, + "io.k8s.api.apps.v1beta1.DeploymentStatus": { + "description": "DeploymentStatus is the most recently observed status of the Deployment.", + "properties": { + "availableReplicas": { + "description": "Total number of available pods (ready for at least minReadySeconds) targeted by this deployment.", + "type": "integer", + "format": "int32" + }, + "collisionCount": { + "description": "Count of hash collisions for the Deployment. The Deployment controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ReplicaSet.", + "type": "integer", + "format": "int32" + }, + "conditions": { + "description": "Represents the latest available observations of a deployment's current state.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "observedGeneration": { + "description": "The generation observed by the deployment controller.", + "type": "integer", + "format": "int64" + }, + "readyReplicas": { + "description": "Total number of ready pods targeted by this deployment.", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "Total number of non-terminated pods targeted by this deployment (their labels match the selector).", + "type": "integer", + "format": "int32" + }, + "unavailableReplicas": { + "description": "Total number of unavailable pods targeted by this deployment.", + "type": "integer", + "format": "int32" + }, + "updatedReplicas": { + "description": "Total number of non-terminated pods targeted by this deployment that have the desired template spec.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.apps.v1beta1.DeploymentStrategy": { + "description": "DeploymentStrategy describes how to replace existing pods with new ones.", + "properties": { + "rollingUpdate": { + "description": "Rolling update config params. Present only if DeploymentStrategyType = RollingUpdate.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.RollingUpdateDeployment" + }, + "type": { + "description": "Type of deployment. Can be \"Recreate\" or \"RollingUpdate\". Default is RollingUpdate.", + "type": "string" + } + } + }, + "io.k8s.api.apps.v1beta1.RollbackConfig": { + "description": "DEPRECATED.", + "properties": { + "revision": { + "description": "The revision to rollback to. If set to 0, rollback to the last revision.", + "type": "integer", + "format": "int64" + } + } + }, + "io.k8s.api.apps.v1beta1.RollingUpdateDeployment": { + "description": "Spec to control the desired behavior of rolling update.", + "properties": { + "maxSurge": { + "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + }, + "maxUnavailable": { + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, + "io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy": { + "description": "RollingUpdateStatefulSetStrategy is used to communicate parameter for RollingUpdateStatefulSetStrategyType.", + "properties": { + "partition": { + "description": "Partition indicates the ordinal at which the StatefulSet should be partitioned.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.apps.v1beta1.Scale": { + "description": "Scale represents a scaling request for a resource.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "defines the behavior of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.ScaleSpec" + }, + "status": { + "description": "current status of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. Read-only.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.ScaleStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "Scale", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.ScaleSpec": { + "description": "ScaleSpec describes the attributes of a scale subresource", + "properties": { + "replicas": { + "description": "desired number of instances for the scaled object.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.apps.v1beta1.ScaleStatus": { + "description": "ScaleStatus represents the current status of a scale subresource.", + "required": [ + "replicas" + ], + "properties": { + "replicas": { + "description": "actual number of observed instances of the scaled object.", + "type": "integer", + "format": "int32" + }, + "selector": { + "description": "label query over pods that should match the replicas count. More info: http://kubernetes.io/docs/user-guide/labels#label-selectors", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "targetSelector": { + "description": "label selector for pods that should match the replicas count. This is a serializated version of both map-based and more expressive set-based selectors. This is done to avoid introspection in the clients. The string will be in the same format as the query-param syntax. If the target type only supports map-based selectors, both this field and map-based selector field are populated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", + "type": "string" + } + } + }, + "io.k8s.api.apps.v1beta1.StatefulSet": { + "description": "StatefulSet represents a set of pods with consistent identities. Identities are defined as:\n - Network: A single stable DNS and hostname.\n - Storage: As many VolumeClaims as requested.\nThe StatefulSet guarantees that a given network identity will always map to the same storage identity.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the desired identities of pods in this set.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.StatefulSetSpec" + }, + "status": { + "description": "Status is the current status of Pods in this StatefulSet. This data may be out of date by some window of time.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.StatefulSetStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "StatefulSet", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.StatefulSetList": { + "description": "StatefulSetList is a collection of StatefulSets.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.StatefulSet" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "StatefulSetList", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.StatefulSetSpec": { + "description": "A StatefulSetSpec is the specification of a StatefulSet.", + "required": [ + "template", + "serviceName" + ], + "properties": { + "podManagementPolicy": { + "description": "podManagementPolicy controls how pods are created during initial scale up, when replacing pods on nodes, or when scaling down. The default policy is `OrderedReady`, where pods are created in increasing order (pod-0, then pod-1, etc) and the controller will wait until each pod is ready before continuing. When scaling down, the pods are removed in the opposite order. The alternative policy is `Parallel` which will create pods in parallel to match the desired scale without waiting, and on scale down will delete all pods at once.", + "type": "string" + }, + "replicas": { + "description": "replicas is the desired number of replicas of the given Template. These are replicas in the sense that they are instantiations of the same Template, but individual replicas also have a consistent identity. If unspecified, defaults to 1.", + "type": "integer", + "format": "int32" + }, + "revisionHistoryLimit": { + "description": "revisionHistoryLimit is the maximum number of revisions that will be maintained in the StatefulSet's revision history. The revision history consists of all revisions not represented by a currently applied StatefulSetSpec version. The default value is 10.", + "type": "integer", + "format": "int32" + }, + "selector": { + "description": "selector is a label query over pods that should match the replica count. If empty, defaulted to labels on the pod template. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, + "serviceName": { + "description": "serviceName is the name of the service that governs this StatefulSet. This service must exist before the StatefulSet, and is responsible for the network identity of the set. Pods get DNS/hostnames that follow the pattern: pod-specific-string.serviceName.default.svc.cluster.local where \"pod-specific-string\" is managed by the StatefulSet controller.", + "type": "string" + }, + "template": { + "description": "template is the object that describes the pod that will be created if insufficient replicas are detected. Each pod stamped out by the StatefulSet will fulfill this Template, but have a unique identity from the rest of the StatefulSet.", + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" + }, + "updateStrategy": { + "description": "updateStrategy indicates the StatefulSetUpdateStrategy that will be employed to update Pods in the StatefulSet when a revision is made to Template.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy" + }, + "volumeClaimTemplates": { + "description": "volumeClaimTemplates is a list of claims that pods are allowed to reference. The StatefulSet controller is responsible for mapping network identities to claims in a way that maintains the identity of a pod. Every claim in this list must have at least one matching (by name) volumeMount in one container in the template. A claim in this list takes precedence over any volumes in the template, with the same name.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaim" + } + } + } + }, + "io.k8s.api.apps.v1beta1.StatefulSetStatus": { + "description": "StatefulSetStatus represents the current state of a StatefulSet.", + "required": [ + "replicas" + ], + "properties": { + "collisionCount": { + "description": "collisionCount is the count of hash collisions for the StatefulSet. The StatefulSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision.", + "type": "integer", + "format": "int32" + }, + "currentReplicas": { + "description": "currentReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version indicated by currentRevision.", + "type": "integer", + "format": "int32" + }, + "currentRevision": { + "description": "currentRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the sequence [0,currentReplicas).", + "type": "string" + }, + "observedGeneration": { + "description": "observedGeneration is the most recent generation observed for this StatefulSet. It corresponds to the StatefulSet's generation, which is updated on mutation by the API Server.", + "type": "integer", + "format": "int64" + }, + "readyReplicas": { + "description": "readyReplicas is the number of Pods created by the StatefulSet controller that have a Ready Condition.", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "replicas is the number of Pods created by the StatefulSet controller.", + "type": "integer", + "format": "int32" + }, + "updateRevision": { + "description": "updateRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the sequence [replicas-updatedReplicas,replicas)", + "type": "string" + }, + "updatedReplicas": { + "description": "updatedReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version indicated by updateRevision.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy": { + "description": "StatefulSetUpdateStrategy indicates the strategy that the StatefulSet controller will use to perform updates. It includes any additional parameters necessary to perform the update for the indicated strategy.", + "properties": { + "rollingUpdate": { + "description": "RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy" + }, + "type": { + "description": "Type indicates the type of the StatefulSetUpdateStrategy.", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1.LocalSubjectAccessReview": { + "description": "LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions checking.", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace you made the request against. If empty, it is defaulted.", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "LocalSubjectAccessReview", + "version": "v1" + } + ] + }, + "io.k8s.api.authorization.v1.NonResourceAttributes": { + "description": "NonResourceAttributes includes the authorization attributes available for non-resource requests to the Authorizer interface", + "properties": { + "path": { + "description": "Path is the URL path of the request", + "type": "string" + }, + "verb": { + "description": "Verb is the standard HTTP verb", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1.ResourceAttributes": { + "description": "ResourceAttributes includes the authorization attributes available for resource requests to the Authorizer interface", + "properties": { + "group": { + "description": "Group is the API Group of the Resource. \"*\" means all.", + "type": "string" + }, + "name": { + "description": "Name is the name of the resource being requested for a \"get\" or deleted for a \"delete\". \"\" (empty) means all.", + "type": "string" + }, + "namespace": { + "description": "Namespace is the namespace of the action being requested. Currently, there is no distinction between no namespace and all namespaces \"\" (empty) is defaulted for LocalSubjectAccessReviews \"\" (empty) is empty for cluster-scoped resources \"\" (empty) means \"all\" for namespace scoped resources from a SubjectAccessReview or SelfSubjectAccessReview", + "type": "string" + }, + "resource": { + "description": "Resource is one of the existing resource types. \"*\" means all.", + "type": "string" + }, + "subresource": { + "description": "Subresource is one of the existing resource types. \"\" means none.", + "type": "string" + }, + "verb": { + "description": "Verb is a kubernetes resource API verb, like: get, list, watch, create, update, delete, proxy. \"*\" means all.", + "type": "string" + }, + "version": { + "description": "Version is the API Version of the Resource. \"*\" means all.", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1.SelfSubjectAccessReview": { + "description": "SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a spec.namespace means \"in all namespaces\". Self is a special case, because users should always be able to check whether they can perform an action", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated. user and groups must be empty", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "SelfSubjectAccessReview", + "version": "v1" + } + ] + }, + "io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec": { + "description": "SelfSubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set", + "properties": { + "nonResourceAttributes": { + "description": "NonResourceAttributes describes information for a non-resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1.NonResourceAttributes" + }, + "resourceAttributes": { + "description": "ResourceAuthorizationAttributes describes information for a resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1.ResourceAttributes" + } + } + }, + "io.k8s.api.authorization.v1.SubjectAccessReview": { + "description": "SubjectAccessReview checks whether or not a user or group can perform an action.", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "SubjectAccessReview", + "version": "v1" + } + ] + }, + "io.k8s.api.authorization.v1.SubjectAccessReviewSpec": { + "description": "SubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set", + "properties": { + "extra": { + "description": "Extra corresponds to the user.Info.GetExtra() method from the authenticator. Since that is input to the authorizer it needs a reflection here.", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "groups": { + "description": "Groups is the groups you're testing for.", + "type": "array", + "items": { + "type": "string" + } + }, + "nonResourceAttributes": { + "description": "NonResourceAttributes describes information for a non-resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1.NonResourceAttributes" + }, + "resourceAttributes": { + "description": "ResourceAuthorizationAttributes describes information for a resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1.ResourceAttributes" + }, + "uid": { + "description": "UID information about the requesting user.", + "type": "string" + }, + "user": { + "description": "User is the user you're testing for. If you specify \"User\" but not \"Groups\", then is it interpreted as \"What if User were not a member of any groups", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1.SubjectAccessReviewStatus": { + "description": "SubjectAccessReviewStatus", + "required": [ + "allowed" + ], + "properties": { + "allowed": { + "description": "Allowed is required. True if the action would be allowed, false otherwise.", + "type": "boolean" + }, + "evaluationError": { + "description": "EvaluationError is an indication that some error occurred during the authorization check. It is entirely possible to get an error and be able to continue determine authorization status in spite of it. For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request.", + "type": "string" + }, + "reason": { + "description": "Reason is optional. It indicates why a request was allowed or denied.", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1beta1.LocalSubjectAccessReview": { + "description": "LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions checking.", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace you made the request against. If empty, it is defaulted.", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "LocalSubjectAccessReview", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.authorization.v1beta1.NonResourceAttributes": { + "description": "NonResourceAttributes includes the authorization attributes available for non-resource requests to the Authorizer interface", + "properties": { + "path": { + "description": "Path is the URL path of the request", + "type": "string" + }, + "verb": { + "description": "Verb is the standard HTTP verb", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1beta1.ResourceAttributes": { + "description": "ResourceAttributes includes the authorization attributes available for resource requests to the Authorizer interface", + "properties": { + "group": { + "description": "Group is the API Group of the Resource. \"*\" means all.", + "type": "string" + }, + "name": { + "description": "Name is the name of the resource being requested for a \"get\" or deleted for a \"delete\". \"\" (empty) means all.", + "type": "string" + }, + "namespace": { + "description": "Namespace is the namespace of the action being requested. Currently, there is no distinction between no namespace and all namespaces \"\" (empty) is defaulted for LocalSubjectAccessReviews \"\" (empty) is empty for cluster-scoped resources \"\" (empty) means \"all\" for namespace scoped resources from a SubjectAccessReview or SelfSubjectAccessReview", + "type": "string" + }, + "resource": { + "description": "Resource is one of the existing resource types. \"*\" means all.", + "type": "string" + }, + "subresource": { + "description": "Subresource is one of the existing resource types. \"\" means none.", + "type": "string" + }, + "verb": { + "description": "Verb is a kubernetes resource API verb, like: get, list, watch, create, update, delete, proxy. \"*\" means all.", + "type": "string" + }, + "version": { + "description": "Version is the API Version of the Resource. \"*\" means all.", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1beta1.SelfSubjectAccessReview": { + "description": "SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a spec.namespace means \"in all namespaces\". Self is a special case, because users should always be able to check whether they can perform an action", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated. user and groups must be empty", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "SelfSubjectAccessReview", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec": { + "description": "SelfSubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set", + "properties": { + "nonResourceAttributes": { + "description": "NonResourceAttributes describes information for a non-resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.NonResourceAttributes" + }, + "resourceAttributes": { + "description": "ResourceAuthorizationAttributes describes information for a resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.ResourceAttributes" + } + } + }, + "io.k8s.api.authorization.v1beta1.SubjectAccessReview": { + "description": "SubjectAccessReview checks whether or not a user or group can perform an action.", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "SubjectAccessReview", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec": { + "description": "SubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set", + "properties": { + "extra": { + "description": "Extra corresponds to the user.Info.GetExtra() method from the authenticator. Since that is input to the authorizer it needs a reflection here.", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "group": { + "description": "Groups is the groups you're testing for.", + "type": "array", + "items": { + "type": "string" + } + }, + "nonResourceAttributes": { + "description": "NonResourceAttributes describes information for a non-resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.NonResourceAttributes" + }, + "resourceAttributes": { + "description": "ResourceAuthorizationAttributes describes information for a resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.ResourceAttributes" + }, + "uid": { + "description": "UID information about the requesting user.", + "type": "string" + }, + "user": { + "description": "User is the user you're testing for. If you specify \"User\" but not \"Group\", then is it interpreted as \"What if User were not a member of any groups", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus": { + "description": "SubjectAccessReviewStatus", + "required": [ + "allowed" + ], + "properties": { + "allowed": { + "description": "Allowed is required. True if the action would be allowed, false otherwise.", + "type": "boolean" + }, + "evaluationError": { + "description": "EvaluationError is an indication that some error occurred during the authorization check. It is entirely possible to get an error and be able to continue determine authorization status in spite of it. For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request.", + "type": "string" + }, + "reason": { + "description": "Reason is optional. It indicates why a request was allowed or denied.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource": { + "description": "Represents a Persistent Disk resource in AWS.\n\nAn AWS EBS disk must exist before mounting to a container. The disk must also be in the same AWS zone as the kubelet. An AWS EBS disk can only be mounted as read/write once. AWS EBS volumes support ownership management and SELinux relabeling.", + "required": [ + "volumeID" + ], + "properties": { + "fsType": { + "description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "type": "string" + }, + "partition": { + "description": "The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as \"1\". Similarly, the volume partition for /dev/sda is \"0\" (or you can leave the property empty).", + "type": "integer", + "format": "int32" + }, + "readOnly": { + "description": "Specify \"true\" to force and set the ReadOnly property in VolumeMounts to \"true\". If omitted, the default is \"false\". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "type": "boolean" + }, + "volumeID": { + "description": "Unique ID of the persistent disk resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Affinity": { + "description": "Affinity is a group of affinity scheduling rules.", + "properties": { + "nodeAffinity": { + "description": "Describes node affinity scheduling rules for the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeAffinity" + }, + "podAffinity": { + "description": "Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)).", + "$ref": "#/definitions/io.k8s.api.core.v1.PodAffinity" + }, + "podAntiAffinity": { + "description": "Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)).", + "$ref": "#/definitions/io.k8s.api.core.v1.PodAntiAffinity" + } + } + }, + "io.k8s.api.core.v1.AttachedVolume": { + "description": "AttachedVolume describes a volume attached to a node", + "required": [ + "name", + "devicePath" + ], + "properties": { + "devicePath": { + "description": "DevicePath represents the device path where the volume should be available", + "type": "string" + }, + "name": { + "description": "Name of the attached volume", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.AzureDiskVolumeSource": { + "description": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.", + "required": [ + "diskName", + "diskURI" + ], + "properties": { + "cachingMode": { + "description": "Host Caching mode: None, Read Only, Read Write.", + "type": "string" + }, + "diskName": { + "description": "The Name of the data disk in the blob storage", + "type": "string" + }, + "diskURI": { + "description": "The URI the data disk in the blob storage", + "type": "string" + }, + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "kind": { + "description": "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", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.AzureFilePersistentVolumeSource": { + "description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.", + "required": [ + "secretName", + "shareName" + ], + "properties": { + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretName": { + "description": "the name of secret that contains Azure Storage Account Name and Key", + "type": "string" + }, + "secretNamespace": { + "description": "the namespace of the secret that contains Azure Storage Account Name and Key default is the same as the Pod", + "type": "string" + }, + "shareName": { + "description": "Share Name", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.AzureFileVolumeSource": { + "description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.", + "required": [ + "secretName", + "shareName" + ], + "properties": { + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretName": { + "description": "the name of secret that contains Azure Storage Account Name and Key", + "type": "string" + }, + "shareName": { + "description": "Share Name", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Binding": { + "description": "Binding ties one object to another; for example, a pod is bound to a node by a scheduler. Deprecated in 1.7, please use the bindings subresource of pods instead.", + "required": [ + "target" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "target": { + "description": "The target object that you want to bind to the standard object.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Binding", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.Capabilities": { + "description": "Adds and removes POSIX capabilities from running containers.", + "properties": { + "add": { + "description": "Added capabilities", + "type": "array", + "items": { + "type": "string" + } + }, + "drop": { + "description": "Removed capabilities", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.CephFSPersistentVolumeSource": { + "description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", + "required": [ + "monitors" + ], + "properties": { + "monitors": { + "description": "Required: Monitors is a collection of Ceph monitors More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "array", + "items": { + "type": "string" + } + }, + "path": { + "description": "Optional: Used as the mounted root, rather than the full Ceph tree, default is /", + "type": "string" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "boolean" + }, + "secretFile": { + "description": "Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "string" + }, + "secretRef": { + "description": "Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretReference" + }, + "user": { + "description": "Optional: User is the rados user name, default is admin More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.CephFSVolumeSource": { + "description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", + "required": [ + "monitors" + ], + "properties": { + "monitors": { + "description": "Required: Monitors is a collection of Ceph monitors More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "array", + "items": { + "type": "string" + } + }, + "path": { + "description": "Optional: Used as the mounted root, rather than the full Ceph tree, default is /", + "type": "string" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "boolean" + }, + "secretFile": { + "description": "Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "string" + }, + "secretRef": { + "description": "Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "user": { + "description": "Optional: User is the rados user name, default is admin More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.CinderVolumeSource": { + "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "required": [ + "volumeID" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "string" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "boolean" + }, + "volumeID": { + "description": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ClientIPConfig": { + "description": "ClientIPConfig represents the configurations of Client IP based session affinity.", + "properties": { + "timeoutSeconds": { + "description": "timeoutSeconds specifies the seconds of ClientIP type session sticky time. The value must be \u003e0 \u0026\u0026 \u003c=86400(for 1 day) if ServiceAffinity == \"ClientIP\". Default value is 10800(for 3 hours).", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.ComponentCondition": { + "description": "Information about the condition of a component.", + "required": [ + "type", + "status" + ], + "properties": { + "error": { + "description": "Condition error code for a component. For example, a health check error code.", + "type": "string" + }, + "message": { + "description": "Message about the condition for a component. For example, information about a health check.", + "type": "string" + }, + "status": { + "description": "Status of the condition for a component. Valid values for \"Healthy\": \"True\", \"False\", or \"Unknown\".", + "type": "string" + }, + "type": { + "description": "Type of condition for a component. Valid value: \"Healthy\"", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ComponentStatus": { + "description": "ComponentStatus (and ComponentStatusList) holds the cluster validation info.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "conditions": { + "description": "List of component conditions observed", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ComponentCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ComponentStatus", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ComponentStatusList": { + "description": "Status of all the conditions for the component as a list of ComponentStatus objects.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of ComponentStatus objects.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ComponentStatus" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ComponentStatusList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ConfigMap": { + "description": "ConfigMap holds configuration data for pods to consume.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "data": { + "description": "Data contains the configuration data. Each key must consist of alphanumeric characters, '-', '_' or '.'.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ConfigMap", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ConfigMapEnvSource": { + "description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.", + "properties": { + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.ConfigMapKeySelector": { + "description": "Selects a key from a ConfigMap.", + "required": [ + "key" + ], + "properties": { + "key": { + "description": "The key to select.", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or it's key must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.ConfigMapList": { + "description": "ConfigMapList is a resource containing a list of ConfigMap objects.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is the list of ConfigMaps.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMap" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ConfigMapList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ConfigMapProjection": { + "description": "Adapts a ConfigMap into a projected volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a projected volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. Note that this is identical to a configmap volume source without the default mode.", + "properties": { + "items": { + "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.KeyToPath" + } + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or it's keys must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.ConfigMapVolumeSource": { + "description": "Adapts a ConfigMap into a volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. ConfigMap volumes support ownership management and SELinux relabeling.", + "properties": { + "defaultMode": { + "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "items": { + "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.KeyToPath" + } + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or it's keys must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.Container": { + "description": "A single application container that you want to run within a pod.", + "required": [ + "name", + "image" + ], + "properties": { + "args": { + "description": "Arguments to the entrypoint. The docker image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell", + "type": "array", + "items": { + "type": "string" + } + }, + "command": { + "description": "Entrypoint array. Not executed within a shell. The docker image's ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell", + "type": "array", + "items": { + "type": "string" + } + }, + "env": { + "description": "List of environment variables to set in the container. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EnvVar" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "envFrom": { + "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EnvFromSource" + } + }, + "image": { + "description": "Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images", + "type": "string" + }, + "imagePullPolicy": { + "description": "Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images", + "type": "string" + }, + "lifecycle": { + "description": "Actions that the management system should take in response to container lifecycle events. Cannot be updated.", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle" + }, + "livenessProbe": { + "description": "Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", + "$ref": "#/definitions/io.k8s.api.core.v1.Probe" + }, + "name": { + "description": "Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated.", + "type": "string" + }, + "ports": { + "description": "List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerPort" + }, + "x-kubernetes-patch-merge-key": "containerPort", + "x-kubernetes-patch-strategy": "merge" + }, + "readinessProbe": { + "description": "Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", + "$ref": "#/definitions/io.k8s.api.core.v1.Probe" + }, + "resources": { + "description": "Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" + }, + "securityContext": { + "description": "Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://git.k8s.io/community/contributors/design-proposals/security_context.md", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext" + }, + "stdin": { + "description": "Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false.", + "type": "boolean" + }, + "stdinOnce": { + "description": "Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false", + "type": "boolean" + }, + "terminationMessagePath": { + "description": "Optional: Path at which the file to which the container's termination message will be written is mounted into the container's filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.", + "type": "string" + }, + "terminationMessagePolicy": { + "description": "Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated.", + "type": "string" + }, + "tty": { + "description": "Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false.", + "type": "boolean" + }, + "volumeMounts": { + "description": "Pod volumes to mount into the container's filesystem. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.VolumeMount" + }, + "x-kubernetes-patch-merge-key": "mountPath", + "x-kubernetes-patch-strategy": "merge" + }, + "workingDir": { + "description": "Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ContainerImage": { + "description": "Describe a container image", + "required": [ + "names" + ], + "properties": { + "names": { + "description": "Names by which this image is known. e.g. [\"k8s.gcr.io/hyperkube:v1.0.7\", \"dockerhub.io/google_containers/hyperkube:v1.0.7\"]", + "type": "array", + "items": { + "type": "string" + } + }, + "sizeBytes": { + "description": "The size of the image in bytes.", + "type": "integer", + "format": "int64" + } + } + }, + "io.k8s.api.core.v1.ContainerPort": { + "description": "ContainerPort represents a network port in a single container.", + "required": [ + "containerPort" + ], + "properties": { + "containerPort": { + "description": "Number of port to expose on the pod's IP address. This must be a valid port number, 0 \u003c x \u003c 65536.", + "type": "integer", + "format": "int32" + }, + "hostIP": { + "description": "What host IP to bind the external port to.", + "type": "string" + }, + "hostPort": { + "description": "Number of port to expose on the host. If specified, this must be a valid port number, 0 \u003c x \u003c 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this.", + "type": "integer", + "format": "int32" + }, + "name": { + "description": "If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services.", + "type": "string" + }, + "protocol": { + "description": "Protocol for port. Must be UDP or TCP. Defaults to \"TCP\".", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ContainerState": { + "description": "ContainerState holds a possible state of container. Only one of its members may be specified. If none of them is specified, the default one is ContainerStateWaiting.", + "properties": { + "running": { + "description": "Details about a running container", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStateRunning" + }, + "terminated": { + "description": "Details about a terminated container", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStateTerminated" + }, + "waiting": { + "description": "Details about a waiting container", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStateWaiting" + } + } + }, + "io.k8s.api.core.v1.ContainerStateRunning": { + "description": "ContainerStateRunning is a running state of a container.", + "properties": { + "startedAt": { + "description": "Time at which the container was last (re-)started", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + } + }, + "io.k8s.api.core.v1.ContainerStateTerminated": { + "description": "ContainerStateTerminated is a terminated state of a container.", + "required": [ + "exitCode" + ], + "properties": { + "containerID": { + "description": "Container's ID in the format 'docker://\u003ccontainer_id\u003e'", + "type": "string" + }, + "exitCode": { + "description": "Exit status from the last termination of the container", + "type": "integer", + "format": "int32" + }, + "finishedAt": { + "description": "Time at which the container last terminated", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "Message regarding the last termination of the container", + "type": "string" + }, + "reason": { + "description": "(brief) reason from the last termination of the container", + "type": "string" + }, + "signal": { + "description": "Signal from the last termination of the container", + "type": "integer", + "format": "int32" + }, + "startedAt": { + "description": "Time at which previous execution of the container started", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + } + }, + "io.k8s.api.core.v1.ContainerStateWaiting": { + "description": "ContainerStateWaiting is a waiting state of a container.", + "properties": { + "message": { + "description": "Message regarding why the container is not yet running.", + "type": "string" + }, + "reason": { + "description": "(brief) reason the container is not yet running.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ContainerStatus": { + "description": "ContainerStatus contains details for the current status of this container.", + "required": [ + "name", + "ready", + "restartCount", + "image", + "imageID" + ], + "properties": { + "containerID": { + "description": "Container's ID in the format 'docker://\u003ccontainer_id\u003e'.", + "type": "string" + }, + "image": { + "description": "The image the container is running. More info: https://kubernetes.io/docs/concepts/containers/images", + "type": "string" + }, + "imageID": { + "description": "ImageID of the container's image.", + "type": "string" + }, + "lastState": { + "description": "Details about the container's last termination condition.", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerState" + }, + "name": { + "description": "This must be a DNS_LABEL. Each container in a pod must have a unique name. Cannot be updated.", + "type": "string" + }, + "ready": { + "description": "Specifies whether the container has passed its readiness probe.", + "type": "boolean" + }, + "restartCount": { + "description": "The number of times the container has been restarted, currently based on the number of dead containers that have not yet been removed. Note that this is calculated from dead containers. But those containers are subject to garbage collection. This value will get capped at 5 by GC.", + "type": "integer", + "format": "int32" + }, + "state": { + "description": "Details about the container's current condition.", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerState" + } + } + }, + "io.k8s.api.core.v1.DaemonEndpoint": { + "description": "DaemonEndpoint contains information about a single Daemon endpoint.", + "required": [ + "Port" + ], + "properties": { + "Port": { + "description": "Port number of the given endpoint.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.DownwardAPIProjection": { + "description": "Represents downward API info for projecting into a projected volume. Note that this is identical to a downwardAPI volume source without the default mode.", + "properties": { + "items": { + "description": "Items is a list of DownwardAPIVolume file", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.DownwardAPIVolumeFile" + } + } + } + }, + "io.k8s.api.core.v1.DownwardAPIVolumeFile": { + "description": "DownwardAPIVolumeFile represents information to create the file containing the pod field", + "required": [ + "path" + ], + "properties": { + "fieldRef": { + "description": "Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectFieldSelector" + }, + "mode": { + "description": "Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "path": { + "description": "Required: Path is the relative path name of the file to be created. Must not be absolute or contain the '..' path. Must be utf-8 encoded. The first item of the relative path must not start with '..'", + "type": "string" + }, + "resourceFieldRef": { + "description": "Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceFieldSelector" + } + } + }, + "io.k8s.api.core.v1.DownwardAPIVolumeSource": { + "description": "DownwardAPIVolumeSource represents a volume containing downward API info. Downward API volumes support ownership management and SELinux relabeling.", + "properties": { + "defaultMode": { + "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "items": { + "description": "Items is a list of downward API volume file", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.DownwardAPIVolumeFile" + } + } + } + }, + "io.k8s.api.core.v1.EmptyDirVolumeSource": { + "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", + "properties": { + "medium": { + "description": "What type of storage medium should back this directory. The default is \"\" which means to use the node's default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir", + "type": "string" + }, + "sizeLimit": { + "description": "Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + } + }, + "io.k8s.api.core.v1.EndpointAddress": { + "description": "EndpointAddress is a tuple that describes single IP address.", + "required": [ + "ip" + ], + "properties": { + "hostname": { + "description": "The Hostname of this endpoint", + "type": "string" + }, + "ip": { + "description": "The IP of this endpoint. May not be loopback (127.0.0.0/8), link-local (169.254.0.0/16), or link-local multicast ((224.0.0.0/24). IPv6 is also accepted but not fully supported on all platforms. Also, certain kubernetes components, like kube-proxy, are not IPv6 ready.", + "type": "string" + }, + "nodeName": { + "description": "Optional: Node hosting this endpoint. This can be used to determine endpoints local to a node.", + "type": "string" + }, + "targetRef": { + "description": "Reference to object providing the endpoint.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + } + } + }, + "io.k8s.api.core.v1.EndpointPort": { + "description": "EndpointPort is a tuple that describes a single port.", + "required": [ + "port" + ], + "properties": { + "name": { + "description": "The name of this port (corresponds to ServicePort.Name). Must be a DNS_LABEL. Optional only if one port is defined.", + "type": "string" + }, + "port": { + "description": "The port number of the endpoint.", + "type": "integer", + "format": "int32" + }, + "protocol": { + "description": "The IP protocol for this port. Must be UDP or TCP. Default is TCP.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.EndpointSubset": { + "description": "EndpointSubset is a group of addresses with a common set of ports. The expanded set of endpoints is the Cartesian product of Addresses x Ports. For example, given:\n {\n Addresses: [{\"ip\": \"10.10.1.1\"}, {\"ip\": \"10.10.2.2\"}],\n Ports: [{\"name\": \"a\", \"port\": 8675}, {\"name\": \"b\", \"port\": 309}]\n }\nThe resulting set of endpoints can be viewed as:\n a: [ 10.10.1.1:8675, 10.10.2.2:8675 ],\n b: [ 10.10.1.1:309, 10.10.2.2:309 ]", + "properties": { + "addresses": { + "description": "IP addresses which offer the related ports that are marked as ready. These endpoints should be considered safe for load balancers and clients to utilize.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EndpointAddress" + } + }, + "notReadyAddresses": { + "description": "IP addresses which offer the related ports but are not currently marked as ready because they have not yet finished starting, have recently failed a readiness check, or have recently failed a liveness check.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EndpointAddress" + } + }, + "ports": { + "description": "Port numbers available on the related IP addresses.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EndpointPort" + } + } + } + }, + "io.k8s.api.core.v1.Endpoints": { + "description": "Endpoints is a collection of endpoints that implement the actual service. Example:\n Name: \"mysvc\",\n Subsets: [\n {\n Addresses: [{\"ip\": \"10.10.1.1\"}, {\"ip\": \"10.10.2.2\"}],\n Ports: [{\"name\": \"a\", \"port\": 8675}, {\"name\": \"b\", \"port\": 309}]\n },\n {\n Addresses: [{\"ip\": \"10.10.3.3\"}],\n Ports: [{\"name\": \"a\", \"port\": 93}, {\"name\": \"b\", \"port\": 76}]\n },\n ]", + "required": [ + "subsets" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "subsets": { + "description": "The set of all endpoints is the union of all subsets. Addresses are placed into subsets according to the IPs they share. A single address with multiple ports, some of which are ready and some of which are not (because they come from different containers) will result in the address being displayed in different subsets for the different ports. No address will appear in both Addresses and NotReadyAddresses in the same subset. Sets of addresses and ports that comprise a service.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EndpointSubset" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Endpoints", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.EndpointsList": { + "description": "EndpointsList is a list of endpoints.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of endpoints.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Endpoints" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "EndpointsList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.EnvFromSource": { + "description": "EnvFromSource represents the source of a set of ConfigMaps", + "properties": { + "configMapRef": { + "description": "The ConfigMap to select from", + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapEnvSource" + }, + "prefix": { + "description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.", + "type": "string" + }, + "secretRef": { + "description": "The Secret to select from", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretEnvSource" + } + } + }, + "io.k8s.api.core.v1.EnvVar": { + "description": "EnvVar represents an environment variable present in a Container.", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "Name of the environment variable. Must be a C_IDENTIFIER.", + "type": "string" + }, + "value": { + "description": "Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to \"\".", + "type": "string" + }, + "valueFrom": { + "description": "Source for the environment variable's value. Cannot be used if value is not empty.", + "$ref": "#/definitions/io.k8s.api.core.v1.EnvVarSource" + } + } + }, + "io.k8s.api.core.v1.EnvVarSource": { + "description": "EnvVarSource represents a source for the value of an EnvVar.", + "properties": { + "configMapKeyRef": { + "description": "Selects a key of a ConfigMap.", + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapKeySelector" + }, + "fieldRef": { + "description": "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectFieldSelector" + }, + "resourceFieldRef": { + "description": "Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceFieldSelector" + }, + "secretKeyRef": { + "description": "Selects a key of a secret in the pod's namespace", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretKeySelector" + } + } + }, + "io.k8s.api.core.v1.Event": { + "description": "Event is a report of an event somewhere in the cluster.", + "required": [ + "metadata", + "involvedObject" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "count": { + "description": "The number of times this event has occurred.", + "type": "integer", + "format": "int32" + }, + "firstTimestamp": { + "description": "The time at which the event was first recorded. (Time of server receipt is in TypeMeta.)", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "involvedObject": { + "description": "The object that this event is about.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "lastTimestamp": { + "description": "The time at which the most recent occurrence of this event was recorded.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "A human-readable description of the status of this operation.", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "reason": { + "description": "This should be a short, machine understandable string that gives the reason for the transition into the object's current status.", + "type": "string" + }, + "source": { + "description": "The component reporting this event. Should be a short machine understandable string.", + "$ref": "#/definitions/io.k8s.api.core.v1.EventSource" + }, + "type": { + "description": "Type of this event (Normal, Warning), new types could be added in the future", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Event", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.EventList": { + "description": "EventList is a list of events.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of events", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Event" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "EventList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.EventSource": { + "description": "EventSource contains information for an event.", + "properties": { + "component": { + "description": "Component from which the event is generated.", + "type": "string" + }, + "host": { + "description": "Node name on which the event is generated.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ExecAction": { + "description": "ExecAction describes a \"run in container\" action.", + "properties": { + "command": { + "description": "Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.FCVolumeSource": { + "description": "Represents a Fibre Channel volume. Fibre Channel volumes can only be mounted as read/write once. Fibre Channel volumes support ownership management and SELinux relabeling.", + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "lun": { + "description": "Optional: FC target lun number", + "type": "integer", + "format": "int32" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "targetWWNs": { + "description": "Optional: FC target worldwide names (WWNs)", + "type": "array", + "items": { + "type": "string" + } + }, + "wwids": { + "description": "Optional: FC volume world wide identifiers (wwids) Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.FlexVolumeSource": { + "description": "FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. This is an alpha feature and may change in future.", + "required": [ + "driver" + ], + "properties": { + "driver": { + "description": "Driver is the name of the driver to use for this volume.", + "type": "string" + }, + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". The default filesystem depends on FlexVolume script.", + "type": "string" + }, + "options": { + "description": "Optional: Extra command options if any.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretRef": { + "description": "Optional: SecretRef is reference to the secret object containing sensitive information to pass to the plugin scripts. This may be empty if no secret object is specified. If the secret object contains more than one secret, all secrets are passed to the plugin scripts.", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + } + } + }, + "io.k8s.api.core.v1.FlockerVolumeSource": { + "description": "Represents a Flocker volume mounted by the Flocker agent. One and only one of datasetName and datasetUUID should be set. Flocker volumes do not support ownership management or SELinux relabeling.", + "properties": { + "datasetName": { + "description": "Name of the dataset stored as metadata -\u003e name on the dataset for Flocker should be considered as deprecated", + "type": "string" + }, + "datasetUUID": { + "description": "UUID of the dataset. This is unique identifier of a Flocker dataset", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.GCEPersistentDiskVolumeSource": { + "description": "Represents a Persistent Disk resource in Google Compute Engine.\n\nA GCE PD must exist before mounting to a container. The disk must also be in the same GCE project and zone as the kubelet. A GCE PD can only be mounted as read/write once or read-only many times. GCE PDs support ownership management and SELinux relabeling.", + "required": [ + "pdName" + ], + "properties": { + "fsType": { + "description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "type": "string" + }, + "partition": { + "description": "The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as \"1\". Similarly, the volume partition for /dev/sda is \"0\" (or you can leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "type": "integer", + "format": "int32" + }, + "pdName": { + "description": "Unique name of the PD resource in GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.GitRepoVolumeSource": { + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "required": [ + "repository" + ], + "properties": { + "directory": { + "description": "Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name.", + "type": "string" + }, + "repository": { + "description": "Repository URL", + "type": "string" + }, + "revision": { + "description": "Commit hash for the specified revision.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.GlusterfsVolumeSource": { + "description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.", + "required": [ + "endpoints", + "path" + ], + "properties": { + "endpoints": { + "description": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", + "type": "string" + }, + "path": { + "description": "Path is the Glusterfs volume path. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.HTTPGetAction": { + "description": "HTTPGetAction describes an action based on HTTP Get requests.", + "required": [ + "port" + ], + "properties": { + "host": { + "description": "Host name to connect to, defaults to the pod IP. You probably want to set \"Host\" in httpHeaders instead.", + "type": "string" + }, + "httpHeaders": { + "description": "Custom headers to set in the request. HTTP allows repeated headers.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.HTTPHeader" + } + }, + "path": { + "description": "Path to access on the HTTP server.", + "type": "string" + }, + "port": { + "description": "Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + }, + "scheme": { + "description": "Scheme to use for connecting to the host. Defaults to HTTP.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.HTTPHeader": { + "description": "HTTPHeader describes a custom header to be used in HTTP probes", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "description": "The header field name", + "type": "string" + }, + "value": { + "description": "The header field value", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Handler": { + "description": "Handler defines a specific action that should be taken", + "properties": { + "exec": { + "description": "One and only one of the following should be specified. Exec specifies the action to take.", + "$ref": "#/definitions/io.k8s.api.core.v1.ExecAction" + }, + "httpGet": { + "description": "HTTPGet specifies the http request to perform.", + "$ref": "#/definitions/io.k8s.api.core.v1.HTTPGetAction" + }, + "tcpSocket": { + "description": "TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported", + "$ref": "#/definitions/io.k8s.api.core.v1.TCPSocketAction" + } + } + }, + "io.k8s.api.core.v1.HostAlias": { + "description": "HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file.", + "properties": { + "hostnames": { + "description": "Hostnames for the above IP address.", + "type": "array", + "items": { + "type": "string" + } + }, + "ip": { + "description": "IP address of the host file entry.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.HostPathVolumeSource": { + "description": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.", + "required": [ + "path" + ], + "properties": { + "path": { + "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", + "type": "string" + }, + "type": { + "description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ISCSIVolumeSource": { + "description": "Represents an ISCSI disk. ISCSI volumes can only be mounted as read/write once. ISCSI volumes support ownership management and SELinux relabeling.", + "required": [ + "targetPortal", + "iqn", + "lun" + ], + "properties": { + "chapAuthDiscovery": { + "description": "whether support iSCSI Discovery CHAP authentication", + "type": "boolean" + }, + "chapAuthSession": { + "description": "whether support iSCSI Session CHAP authentication", + "type": "boolean" + }, + "fsType": { + "description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi", + "type": "string" + }, + "initiatorName": { + "description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection.", + "type": "string" + }, + "iqn": { + "description": "Target iSCSI Qualified Name.", + "type": "string" + }, + "iscsiInterface": { + "description": "Optional: Defaults to 'default' (tcp). iSCSI interface name that uses an iSCSI transport.", + "type": "string" + }, + "lun": { + "description": "iSCSI target lun number.", + "type": "integer", + "format": "int32" + }, + "portals": { + "description": "iSCSI target portal List. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260).", + "type": "array", + "items": { + "type": "string" + } + }, + "readOnly": { + "description": "ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false.", + "type": "boolean" + }, + "secretRef": { + "description": "CHAP secret for iSCSI target and initiator authentication", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "targetPortal": { + "description": "iSCSI target portal. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260).", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.KeyToPath": { + "description": "Maps a string key to a path within a volume.", + "required": [ + "key", + "path" + ], + "properties": { + "key": { + "description": "The key to project.", + "type": "string" + }, + "mode": { + "description": "Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "path": { + "description": "The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Lifecycle": { + "description": "Lifecycle describes actions that the management system should take in response to container lifecycle events. For the PostStart and PreStop lifecycle handlers, management of the container blocks until the action is complete, unless the container process fails, in which case the handler is aborted.", + "properties": { + "postStart": { + "description": "PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks", + "$ref": "#/definitions/io.k8s.api.core.v1.Handler" + }, + "preStop": { + "description": "PreStop is called immediately before a container is terminated. The container is terminated after the handler completes. The reason for termination is passed to the handler. Regardless of the outcome of the handler, the container is eventually terminated. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks", + "$ref": "#/definitions/io.k8s.api.core.v1.Handler" + } + } + }, + "io.k8s.api.core.v1.LimitRange": { + "description": "LimitRange sets resource usage limits for each kind of resource in a Namespace.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the limits enforced. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.LimitRangeSpec" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "LimitRange", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.LimitRangeItem": { + "description": "LimitRangeItem defines a min/max usage limit for any resource that matches on kind.", + "properties": { + "default": { + "description": "Default resource requirement limit value by resource name if resource limit is omitted.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "defaultRequest": { + "description": "DefaultRequest is the default resource requirement request value by resource name if resource request is omitted.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "max": { + "description": "Max usage constraints on this kind by resource name.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "maxLimitRequestRatio": { + "description": "MaxLimitRequestRatio if specified, the named resource must have a request and limit that are both non-zero where limit divided by request is less than or equal to the enumerated value; this represents the max burst for the named resource.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "min": { + "description": "Min usage constraints on this kind by resource name.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "type": { + "description": "Type of resource that this limit applies to.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.LimitRangeList": { + "description": "LimitRangeList is a list of LimitRange items.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is a list of LimitRange objects. More info: https://git.k8s.io/community/contributors/design-proposals/admission_control_limit_range.md", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LimitRange" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "LimitRangeList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.LimitRangeSpec": { + "description": "LimitRangeSpec defines a min/max usage limit for resources that match on kind.", + "required": [ + "limits" + ], + "properties": { + "limits": { + "description": "Limits is the list of LimitRangeItem objects that are enforced.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LimitRangeItem" + } + } + } + }, + "io.k8s.api.core.v1.LoadBalancerIngress": { + "description": "LoadBalancerIngress represents the status of a load-balancer ingress point: traffic intended for the service should be sent to an ingress point.", + "properties": { + "hostname": { + "description": "Hostname is set for load-balancer ingress points that are DNS based (typically AWS load-balancers)", + "type": "string" + }, + "ip": { + "description": "IP is set for load-balancer ingress points that are IP based (typically GCE or OpenStack load-balancers)", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.LoadBalancerStatus": { + "description": "LoadBalancerStatus represents the status of a load-balancer.", + "properties": { + "ingress": { + "description": "Ingress is a list containing ingress points for the load-balancer. Traffic intended for the service should be sent to these ingress points.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LoadBalancerIngress" + } + } + } + }, + "io.k8s.api.core.v1.LocalObjectReference": { + "description": "LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace.", + "properties": { + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.LocalVolumeSource": { + "description": "Local represents directly-attached storage with node affinity", + "required": [ + "path" + ], + "properties": { + "path": { + "description": "The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.NFSVolumeSource": { + "description": "Represents an NFS mount that lasts the lifetime of a pod. NFS volumes do not support ownership management or SELinux relabeling.", + "required": [ + "server", + "path" + ], + "properties": { + "path": { + "description": "Path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "type": "boolean" + }, + "server": { + "description": "Server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Namespace": { + "description": "Namespace provides a scope for Names. Use of multiple namespaces is optional.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the behavior of the Namespace. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.NamespaceSpec" + }, + "status": { + "description": "Status describes the current status of a Namespace. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.NamespaceStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Namespace", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NamespaceList": { + "description": "NamespaceList is a list of Namespaces.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is the list of Namespace objects in the list. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Namespace" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "NamespaceList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NamespaceSpec": { + "description": "NamespaceSpec describes the attributes on a Namespace.", + "properties": { + "finalizers": { + "description": "Finalizers is an opaque list of values that must be empty to permanently remove object from storage. More info: https://git.k8s.io/community/contributors/design-proposals/namespaces.md#finalizers", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.NamespaceStatus": { + "description": "NamespaceStatus is information about the current status of a Namespace.", + "properties": { + "phase": { + "description": "Phase is the current lifecycle phase of the namespace. More info: https://git.k8s.io/community/contributors/design-proposals/namespaces.md#phases", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Node": { + "description": "Node is a worker node in Kubernetes. Each node will have a unique identifier in the cache (i.e. in etcd).", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the behavior of a node. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSpec" + }, + "status": { + "description": "Most recently observed status of the node. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Node", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NodeAddress": { + "description": "NodeAddress contains information for the node's address.", + "required": [ + "type", + "address" + ], + "properties": { + "address": { + "description": "The node address.", + "type": "string" + }, + "type": { + "description": "Node address type, one of Hostname, ExternalIP or InternalIP.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.NodeAffinity": { + "description": "Node affinity is a group of node affinity scheduling rules.", + "properties": { + "preferredDuringSchedulingIgnoredDuringExecution": { + "description": "The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding \"weight\" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PreferredSchedulingTerm" + } + }, + "requiredDuringSchedulingIgnoredDuringExecution": { + "description": "If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelector" + } + } + }, + "io.k8s.api.core.v1.NodeCondition": { + "description": "NodeCondition contains condition information for a node.", + "required": [ + "type", + "status" + ], + "properties": { + "lastHeartbeatTime": { + "description": "Last time we got an update on a given condition.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "lastTransitionTime": { + "description": "Last time the condition transit from one status to another.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "Human readable message indicating details about last transition.", + "type": "string" + }, + "reason": { + "description": "(brief) reason for the condition's last transition.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of node condition.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.NodeConfigSource": { + "description": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "configMapRef": { + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "NodeConfigSource", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NodeDaemonEndpoints": { + "description": "NodeDaemonEndpoints lists ports opened by daemons running on the Node.", + "properties": { + "kubeletEndpoint": { + "description": "Endpoint on which Kubelet is listening.", + "$ref": "#/definitions/io.k8s.api.core.v1.DaemonEndpoint" + } + } + }, + "io.k8s.api.core.v1.NodeList": { + "description": "NodeList is the whole list of all Nodes which have been registered with master.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of nodes", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Node" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "NodeList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NodeSelector": { + "description": "A node selector represents the union of the results of one or more label queries over a set of nodes; that is, it represents the OR of the selectors represented by the node selector terms.", + "required": [ + "nodeSelectorTerms" + ], + "properties": { + "nodeSelectorTerms": { + "description": "Required. A list of node selector terms. The terms are ORed.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelectorTerm" + } + } + } + }, + "io.k8s.api.core.v1.NodeSelectorRequirement": { + "description": "A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values.", + "required": [ + "key", + "operator" + ], + "properties": { + "key": { + "description": "The label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.", + "type": "string" + }, + "values": { + "description": "An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.NodeSelectorTerm": { + "description": "A null or empty node selector term matches no objects.", + "required": [ + "matchExpressions" + ], + "properties": { + "matchExpressions": { + "description": "Required. A list of node selector requirements. The requirements are ANDed.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelectorRequirement" + } + } + } + }, + "io.k8s.api.core.v1.NodeSpec": { + "description": "NodeSpec describes the attributes that a node is created with.", + "properties": { + "configSource": { + "description": "If specified, the source to get node configuration from The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource" + }, + "externalID": { + "description": "External ID of the node assigned by some machine database (e.g. a cloud provider). Deprecated.", + "type": "string" + }, + "podCIDR": { + "description": "PodCIDR represents the pod IP range assigned to the node.", + "type": "string" + }, + "providerID": { + "description": "ID of the node assigned by the cloud provider in the format: \u003cProviderName\u003e://\u003cProviderSpecificNodeID\u003e", + "type": "string" + }, + "taints": { + "description": "If specified, the node's taints.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Taint" + } + }, + "unschedulable": { + "description": "Unschedulable controls node schedulability of new pods. By default, node is schedulable. More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.NodeStatus": { + "description": "NodeStatus is information about the current status of a node.", + "properties": { + "addresses": { + "description": "List of addresses reachable to the node. Queried from cloud provider, if available. More info: https://kubernetes.io/docs/concepts/nodes/node/#addresses", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeAddress" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "allocatable": { + "description": "Allocatable represents the resources of a node that are available for scheduling. Defaults to Capacity.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "capacity": { + "description": "Capacity represents the total resources of a node. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "conditions": { + "description": "Conditions is an array of current observed node conditions. More info: https://kubernetes.io/docs/concepts/nodes/node/#condition", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "daemonEndpoints": { + "description": "Endpoints of daemons running on the Node.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeDaemonEndpoints" + }, + "images": { + "description": "List of container images on this node", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerImage" + } + }, + "nodeInfo": { + "description": "Set of ids/uuids to uniquely identify the node. More info: https://kubernetes.io/docs/concepts/nodes/node/#info", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSystemInfo" + }, + "phase": { + "description": "NodePhase is the recently observed lifecycle phase of the node. More info: https://kubernetes.io/docs/concepts/nodes/node/#phase The field is never populated, and now is deprecated.", + "type": "string" + }, + "volumesAttached": { + "description": "List of volumes that are attached to the node.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.AttachedVolume" + } + }, + "volumesInUse": { + "description": "List of attachable volumes in use (mounted) by the node.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.NodeSystemInfo": { + "description": "NodeSystemInfo is a set of ids/uuids to uniquely identify the node.", + "required": [ + "machineID", + "systemUUID", + "bootID", + "kernelVersion", + "osImage", + "containerRuntimeVersion", + "kubeletVersion", + "kubeProxyVersion", + "operatingSystem", + "architecture" + ], + "properties": { + "architecture": { + "description": "The Architecture reported by the node", + "type": "string" + }, + "bootID": { + "description": "Boot ID reported by the node.", + "type": "string" + }, + "containerRuntimeVersion": { + "description": "ContainerRuntime Version reported by the node through runtime remote API (e.g. docker://1.5.0).", + "type": "string" + }, + "kernelVersion": { + "description": "Kernel Version reported by the node from 'uname -r' (e.g. 3.16.0-0.bpo.4-amd64).", + "type": "string" + }, + "kubeProxyVersion": { + "description": "KubeProxy Version reported by the node.", + "type": "string" + }, + "kubeletVersion": { + "description": "Kubelet Version reported by the node.", + "type": "string" + }, + "machineID": { + "description": "MachineID reported by the node. For unique machine identification in the cluster this field is preferred. Learn more from man(5) machine-id: http://man7.org/linux/man-pages/man5/machine-id.5.html", + "type": "string" + }, + "operatingSystem": { + "description": "The Operating System reported by the node", + "type": "string" + }, + "osImage": { + "description": "OS Image reported by the node from /etc/os-release (e.g. Debian GNU/Linux 7 (wheezy)).", + "type": "string" + }, + "systemUUID": { + "description": "SystemUUID reported by the node. For unique machine identification MachineID is preferred. This field is specific to Red Hat hosts https://access.redhat.com/documentation/en-US/Red_Hat_Subscription_Management/1/html/RHSM/getting-system-uuid.html", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ObjectFieldSelector": { + "description": "ObjectFieldSelector selects an APIVersioned field of an object.", + "required": [ + "fieldPath" + ], + "properties": { + "apiVersion": { + "description": "Version of the schema the FieldPath is written in terms of, defaults to \"v1\".", + "type": "string" + }, + "fieldPath": { + "description": "Path of the field to select in the specified API version.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ObjectReference": { + "description": "ObjectReference contains enough information to let you inspect or modify the referred object.", + "properties": { + "apiVersion": { + "description": "API version of the referent.", + "type": "string" + }, + "fieldPath": { + "description": "If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: \"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered the event) or if no container name is specified \"spec.containers[2]\" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object.", + "type": "string" + }, + "kind": { + "description": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "namespace": { + "description": "Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", + "type": "string" + }, + "resourceVersion": { + "description": "Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency", + "type": "string" + }, + "uid": { + "description": "UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PersistentVolume": { + "description": "PersistentVolume (PV) is a storage resource provisioned by an administrator. It is analogous to a node. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines a specification of a persistent volume owned by the cluster. Provisioned by an administrator. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeSpec" + }, + "status": { + "description": "Status represents the current information/status for the persistent volume. Populated by the system. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PersistentVolume", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PersistentVolumeClaim": { + "description": "PersistentVolumeClaim is a user's request for and claim to a persistent volume", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaimSpec" + }, + "status": { + "description": "Status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaimStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PersistentVolumeClaim", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PersistentVolumeClaimList": { + "description": "PersistentVolumeClaimList is a list of PersistentVolumeClaim items.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "A list of persistent volume claims. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaim" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PersistentVolumeClaimList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PersistentVolumeClaimSpec": { + "description": "PersistentVolumeClaimSpec describes the common attributes of storage devices and allows a Source for provider-specific attributes", + "properties": { + "accessModes": { + "description": "AccessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1", + "type": "array", + "items": { + "type": "string" + } + }, + "resources": { + "description": "Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" + }, + "selector": { + "description": "A label query over volumes to consider for binding.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, + "storageClassName": { + "description": "Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1", + "type": "string" + }, + "volumeName": { + "description": "VolumeName is the binding reference to the PersistentVolume backing this claim.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PersistentVolumeClaimStatus": { + "description": "PersistentVolumeClaimStatus is the current status of a persistent volume claim.", + "properties": { + "accessModes": { + "description": "AccessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1", + "type": "array", + "items": { + "type": "string" + } + }, + "capacity": { + "description": "Represents the actual resources of the underlying volume.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "phase": { + "description": "Phase represents the current phase of PersistentVolumeClaim.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource": { + "description": "PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace. This volume finds the bound PV and mounts that volume for the pod. A PersistentVolumeClaimVolumeSource is, essentially, a wrapper around another type of volume that is owned by someone else (the system).", + "required": [ + "claimName" + ], + "properties": { + "claimName": { + "description": "ClaimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "type": "string" + }, + "readOnly": { + "description": "Will force the ReadOnly setting in VolumeMounts. Default false.", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.PersistentVolumeList": { + "description": "PersistentVolumeList is a list of PersistentVolume items.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of persistent volumes. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolume" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PersistentVolumeList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PersistentVolumeSpec": { + "description": "PersistentVolumeSpec is the specification of a persistent volume.", + "properties": { + "accessModes": { + "description": "AccessModes contains all ways the volume can be mounted. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes", + "type": "array", + "items": { + "type": "string" + } + }, + "awsElasticBlockStore": { + "description": "AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "$ref": "#/definitions/io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource" + }, + "azureDisk": { + "description": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.AzureDiskVolumeSource" + }, + "azureFile": { + "description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.AzureFilePersistentVolumeSource" + }, + "capacity": { + "description": "A description of the persistent volume's resources and capacity. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "cephfs": { + "description": "CephFS represents a Ceph FS mount on the host that shares a pod's lifetime", + "$ref": "#/definitions/io.k8s.api.core.v1.CephFSPersistentVolumeSource" + }, + "cinder": { + "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.CinderVolumeSource" + }, + "claimRef": { + "description": "ClaimRef is part of a bi-directional binding between PersistentVolume and PersistentVolumeClaim. Expected to be non-nil when bound. claim.VolumeName is the authoritative bind between PV and PVC. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#binding", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "fc": { + "description": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.FCVolumeSource" + }, + "flexVolume": { + "description": "FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. This is an alpha feature and may change in future.", + "$ref": "#/definitions/io.k8s.api.core.v1.FlexVolumeSource" + }, + "flocker": { + "description": "Flocker represents a Flocker volume attached to a kubelet's host machine and exposed to the pod for its usage. This depends on the Flocker control service being running", + "$ref": "#/definitions/io.k8s.api.core.v1.FlockerVolumeSource" + }, + "gcePersistentDisk": { + "description": "GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "$ref": "#/definitions/io.k8s.api.core.v1.GCEPersistentDiskVolumeSource" + }, + "glusterfs": { + "description": "Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.GlusterfsVolumeSource" + }, + "hostPath": { + "description": "HostPath represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", + "$ref": "#/definitions/io.k8s.api.core.v1.HostPathVolumeSource" + }, + "iscsi": { + "description": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin.", + "$ref": "#/definitions/io.k8s.api.core.v1.ISCSIVolumeSource" + }, + "local": { + "description": "Local represents directly-attached storage with node affinity", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalVolumeSource" + }, + "mountOptions": { + "description": "A list of mount options, e.g. [\"ro\", \"soft\"]. Not validated - mount will simply fail if one is invalid. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options", + "type": "array", + "items": { + "type": "string" + } + }, + "nfs": { + "description": "NFS represents an NFS mount on the host. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "$ref": "#/definitions/io.k8s.api.core.v1.NFSVolumeSource" + }, + "persistentVolumeReclaimPolicy": { + "description": "What happens to a persistent volume when released from its claim. Valid options are Retain (default) and Recycle. Recycling must be supported by the volume plugin underlying this persistent volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming", + "type": "string" + }, + "photonPersistentDisk": { + "description": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource" + }, + "portworxVolume": { + "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.PortworxVolumeSource" + }, + "quobyte": { + "description": "Quobyte represents a Quobyte mount on the host that shares a pod's lifetime", + "$ref": "#/definitions/io.k8s.api.core.v1.QuobyteVolumeSource" + }, + "rbd": { + "description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.RBDVolumeSource" + }, + "scaleIO": { + "description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.", + "$ref": "#/definitions/io.k8s.api.core.v1.ScaleIOVolumeSource" + }, + "storageClassName": { + "description": "Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.", + "type": "string" + }, + "storageos": { + "description": "StorageOS represents a StorageOS volume that is attached to the kubelet's host machine and mounted into the pod More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.StorageOSPersistentVolumeSource" + }, + "vsphereVolume": { + "description": "VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource" + } + } + }, + "io.k8s.api.core.v1.PersistentVolumeStatus": { + "description": "PersistentVolumeStatus is the current status of a persistent volume.", + "properties": { + "message": { + "description": "A human-readable message indicating details about why the volume is in this state.", + "type": "string" + }, + "phase": { + "description": "Phase indicates if a volume is available, bound to a claim, or released by a claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#phase", + "type": "string" + }, + "reason": { + "description": "Reason is a brief CamelCase string that describes any failure and is meant for machine parsing and tidy display in the CLI.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource": { + "description": "Represents a Photon Controller persistent disk resource.", + "required": [ + "pdID" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "pdID": { + "description": "ID that identifies Photon Controller persistent disk", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Pod": { + "description": "Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSpec" + }, + "status": { + "description": "Most recently observed status of the pod. This data may not be up to date. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.PodStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Pod", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PodAffinity": { + "description": "Pod affinity is a group of inter pod affinity scheduling rules.", + "properties": { + "preferredDuringSchedulingIgnoredDuringExecution": { + "description": "The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding \"weight\" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.WeightedPodAffinityTerm" + } + }, + "requiredDuringSchedulingIgnoredDuringExecution": { + "description": "If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodAffinityTerm" + } + } + } + }, + "io.k8s.api.core.v1.PodAffinityTerm": { + "description": "Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key \u003ctopologyKey\u003e tches that of any node on which a pod of the set of pods is running", + "properties": { + "labelSelector": { + "description": "A label query over a set of resources, in this case pods.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, + "namespaces": { + "description": "namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means \"this pod's namespace\"", + "type": "array", + "items": { + "type": "string" + } + }, + "topologyKey": { + "description": "This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. For PreferredDuringScheduling pod anti-affinity, empty topologyKey is interpreted as \"all topologies\" (\"all topologies\" here means all the topologyKeys indicated by scheduler command-line argument --failure-domains); for affinity and for RequiredDuringScheduling pod anti-affinity, empty topologyKey is not allowed.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PodAntiAffinity": { + "description": "Pod anti affinity is a group of inter pod anti affinity scheduling rules.", + "properties": { + "preferredDuringSchedulingIgnoredDuringExecution": { + "description": "The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding \"weight\" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.WeightedPodAffinityTerm" + } + }, + "requiredDuringSchedulingIgnoredDuringExecution": { + "description": "If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodAffinityTerm" + } + } + } + }, + "io.k8s.api.core.v1.PodCondition": { + "description": "PodCondition contains details for the current condition of this pod.", + "required": [ + "type", + "status" + ], + "properties": { + "lastProbeTime": { + "description": "Last time we probed the condition.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "lastTransitionTime": { + "description": "Last time the condition transitioned from one status to another.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "Human-readable message indicating details about last transition.", + "type": "string" + }, + "reason": { + "description": "Unique, one-word, CamelCase reason for the condition's last transition.", + "type": "string" + }, + "status": { + "description": "Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "type": "string" + }, + "type": { + "description": "Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PodList": { + "description": "PodList is a list of Pods.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of pods. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Pod" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PodList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PodSecurityContext": { + "description": "PodSecurityContext holds pod-level security attributes and common container settings. Some fields are also present in container.securityContext. Field values of container.securityContext take precedence over field values of PodSecurityContext.", + "properties": { + "fsGroup": { + "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw----\n\nIf unset, the Kubelet will not modify the ownership and permissions of any volume.", + "type": "integer", + "format": "int64" + }, + "runAsNonRoot": { + "description": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", + "type": "boolean" + }, + "runAsUser": { + "description": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.", + "type": "integer", + "format": "int64" + }, + "seLinuxOptions": { + "description": "The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.", + "$ref": "#/definitions/io.k8s.api.core.v1.SELinuxOptions" + }, + "supplementalGroups": { + "description": "A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container.", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + } + } + }, + "io.k8s.api.core.v1.PodSpec": { + "description": "PodSpec is a description of a pod.", + "required": [ + "containers" + ], + "properties": { + "activeDeadlineSeconds": { + "description": "Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.", + "type": "integer", + "format": "int64" + }, + "affinity": { + "description": "If specified, the pod's scheduling constraints", + "$ref": "#/definitions/io.k8s.api.core.v1.Affinity" + }, + "automountServiceAccountToken": { + "description": "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.", + "type": "boolean" + }, + "containers": { + "description": "List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Container" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "dnsPolicy": { + "description": "Set DNS policy for containers within the pod. One of 'ClusterFirstWithHostNet', 'ClusterFirst' or 'Default'. Defaults to \"ClusterFirst\". To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'.", + "type": "string" + }, + "hostAliases": { + "description": "HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts file if specified. This is only valid for non-hostNetwork pods.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.HostAlias" + }, + "x-kubernetes-patch-merge-key": "ip", + "x-kubernetes-patch-strategy": "merge" + }, + "hostIPC": { + "description": "Use the host's ipc namespace. Optional: Default to false.", + "type": "boolean" + }, + "hostNetwork": { + "description": "Host networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false.", + "type": "boolean" + }, + "hostPID": { + "description": "Use the host's pid namespace. Optional: Default to false.", + "type": "boolean" + }, + "hostname": { + "description": "Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value.", + "type": "string" + }, + "imagePullSecrets": { + "description": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "initContainers": { + "description": "List of initialization containers belonging to the pod. Init containers are executed in order prior to containers being started. If any init container fails, the pod is considered to have failed and is handled according to its restartPolicy. The name for an init container or normal container must be unique among all containers. Init containers may not have Lifecycle actions, Readiness probes, or Liveness probes. The resourceRequirements of an init container are taken into account during scheduling by finding the highest request/limit for each resource type, and then using the max of of that value or the sum of the normal containers. Limits are applied to init containers in a similar fashion. Init containers cannot currently be added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Container" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "nodeName": { + "description": "NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.", + "type": "string" + }, + "nodeSelector": { + "description": "NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "priority": { + "description": "The priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.", + "type": "integer", + "format": "int32" + }, + "priorityClassName": { + "description": "If specified, indicates the pod's priority. \"SYSTEM\" is a special keyword which indicates the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.", + "type": "string" + }, + "restartPolicy": { + "description": "Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy", + "type": "string" + }, + "schedulerName": { + "description": "If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler.", + "type": "string" + }, + "securityContext": { + "description": "SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext" + }, + "serviceAccount": { + "description": "DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead.", + "type": "string" + }, + "serviceAccountName": { + "description": "ServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/", + "type": "string" + }, + "subdomain": { + "description": "If specified, the fully qualified Pod hostname will be \"\u003chostname\u003e.\u003csubdomain\u003e.\u003cpod namespace\u003e.svc.\u003ccluster domain\u003e\". If not specified, the pod will not have a domainname at all.", + "type": "string" + }, + "terminationGracePeriodSeconds": { + "description": "Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds.", + "type": "integer", + "format": "int64" + }, + "tolerations": { + "description": "If specified, the pod's tolerations.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Toleration" + } + }, + "volumes": { + "description": "List of volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Volume" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge,retainKeys" + } + } + }, + "io.k8s.api.core.v1.PodStatus": { + "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system.", + "properties": { + "conditions": { + "description": "Current service state of pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "containerStatuses": { + "description": "The list has one entry per container in the manifest. Each entry is currently the output of `docker inspect`. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStatus" + } + }, + "hostIP": { + "description": "IP address of the host to which the pod is assigned. Empty if not yet scheduled.", + "type": "string" + }, + "initContainerStatuses": { + "description": "The list has one entry per init container in the manifest. The most recent successful init container will have ready = true, the most recently started container will have startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStatus" + } + }, + "message": { + "description": "A human readable message indicating details about why the pod is in this condition.", + "type": "string" + }, + "phase": { + "description": "Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", + "type": "string" + }, + "podIP": { + "description": "IP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.", + "type": "string" + }, + "qosClass": { + "description": "The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://github.com/kubernetes/kubernetes/blob/master/docs/design/resource-qos.md", + "type": "string" + }, + "reason": { + "description": "A brief CamelCase message indicating details about why the pod is in this state. e.g. 'Evicted'", + "type": "string" + }, + "startTime": { + "description": "RFC 3339 date and time at which the object was acknowledged by the Kubelet. This is before the Kubelet pulled the container image(s) for the pod.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + } + }, + "io.k8s.api.core.v1.PodTemplate": { + "description": "PodTemplate describes a template for creating copies of a predefined pod.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "template": { + "description": "Template defines the pods that will be created from this pod template. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PodTemplate", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PodTemplateList": { + "description": "PodTemplateList is a list of PodTemplates.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of pod templates", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplate" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PodTemplateList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PodTemplateSpec": { + "description": "PodTemplateSpec describes the data a pod should have when created from a template", + "properties": { + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSpec" + } + } + }, + "io.k8s.api.core.v1.PortworxVolumeSource": { + "description": "PortworxVolumeSource represents a Portworx volume resource.", + "required": [ + "volumeID" + ], + "properties": { + "fsType": { + "description": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "volumeID": { + "description": "VolumeID uniquely identifies a Portworx volume", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PreferredSchedulingTerm": { + "description": "An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op).", + "required": [ + "weight", + "preference" + ], + "properties": { + "preference": { + "description": "A node selector term, associated with the corresponding weight.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelectorTerm" + }, + "weight": { + "description": "Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.Probe": { + "description": "Probe describes a health check to be performed against a container to determine whether it is alive or ready to receive traffic.", + "properties": { + "exec": { + "description": "One and only one of the following should be specified. Exec specifies the action to take.", + "$ref": "#/definitions/io.k8s.api.core.v1.ExecAction" + }, + "failureThreshold": { + "description": "Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1.", + "type": "integer", + "format": "int32" + }, + "httpGet": { + "description": "HTTPGet specifies the http request to perform.", + "$ref": "#/definitions/io.k8s.api.core.v1.HTTPGetAction" + }, + "initialDelaySeconds": { + "description": "Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", + "type": "integer", + "format": "int32" + }, + "periodSeconds": { + "description": "How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1.", + "type": "integer", + "format": "int32" + }, + "successThreshold": { + "description": "Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1.", + "type": "integer", + "format": "int32" + }, + "tcpSocket": { + "description": "TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported", + "$ref": "#/definitions/io.k8s.api.core.v1.TCPSocketAction" + }, + "timeoutSeconds": { + "description": "Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.ProjectedVolumeSource": { + "description": "Represents a projected volume source", + "required": [ + "sources" + ], + "properties": { + "defaultMode": { + "description": "Mode bits to use on created files by default. Must be a value between 0 and 0777. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "sources": { + "description": "list of volume projections", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.VolumeProjection" + } + } + } + }, + "io.k8s.api.core.v1.QuobyteVolumeSource": { + "description": "Represents a Quobyte mount that lasts the lifetime of a pod. Quobyte volumes do not support ownership management or SELinux relabeling.", + "required": [ + "registry", + "volume" + ], + "properties": { + "group": { + "description": "Group to map volume access to Default is no group", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false.", + "type": "boolean" + }, + "registry": { + "description": "Registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes", + "type": "string" + }, + "user": { + "description": "User to map volume access to Defaults to serivceaccount user", + "type": "string" + }, + "volume": { + "description": "Volume is a string that references an already created Quobyte volume by name.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.RBDVolumeSource": { + "description": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.", + "required": [ + "monitors", + "image" + ], + "properties": { + "fsType": { + "description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd", + "type": "string" + }, + "image": { + "description": "The rados image name. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "string" + }, + "keyring": { + "description": "Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "string" + }, + "monitors": { + "description": "A collection of Ceph monitors. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "array", + "items": { + "type": "string" + } + }, + "pool": { + "description": "The rados pool name. Default is rbd. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "boolean" + }, + "secretRef": { + "description": "SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "user": { + "description": "The rados user name. Default is admin. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ReplicationController": { + "description": "ReplicationController represents the configuration of a replication controller.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "If the Labels of a ReplicationController are empty, they are defaulted to be the same as the Pod(s) that the replication controller manages. Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the specification of the desired behavior of the replication controller. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ReplicationControllerSpec" + }, + "status": { + "description": "Status is the most recently observed status of the replication controller. This data may be out of date by some window of time. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ReplicationControllerStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ReplicationController", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ReplicationControllerCondition": { + "description": "ReplicationControllerCondition describes the state of a replication controller at a certain point.", + "required": [ + "type", + "status" + ], + "properties": { + "lastTransitionTime": { + "description": "The last time the condition transitioned from one status to another.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "A human readable message indicating details about the transition.", + "type": "string" + }, + "reason": { + "description": "The reason for the condition's last transition.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of replication controller condition.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ReplicationControllerList": { + "description": "ReplicationControllerList is a collection of replication controllers.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of replication controllers. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ReplicationController" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ReplicationControllerList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ReplicationControllerSpec": { + "description": "ReplicationControllerSpec is the specification of a replication controller.", + "properties": { + "minReadySeconds": { + "description": "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "Replicas is the number of desired replicas. This is a pointer to distinguish between explicit zero and unspecified. Defaults to 1. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller", + "type": "integer", + "format": "int32" + }, + "selector": { + "description": "Selector is a label query over pods that should match the Replicas count. If Selector is empty, it is defaulted to the labels present on the Pod template. Label keys and values that must match in order to be controlled by this replication controller, if empty defaulted to labels on Pod template. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "description": "Template is the object that describes the pod that will be created if insufficient replicas are detected. This takes precedence over a TemplateRef. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template", + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" + } + } + }, + "io.k8s.api.core.v1.ReplicationControllerStatus": { + "description": "ReplicationControllerStatus represents the current status of a replication controller.", + "required": [ + "replicas" + ], + "properties": { + "availableReplicas": { + "description": "The number of available replicas (ready for at least minReadySeconds) for this replication controller.", + "type": "integer", + "format": "int32" + }, + "conditions": { + "description": "Represents the latest available observations of a replication controller's current state.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ReplicationControllerCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "fullyLabeledReplicas": { + "description": "The number of pods that have labels matching the labels of the pod template of the replication controller.", + "type": "integer", + "format": "int32" + }, + "observedGeneration": { + "description": "ObservedGeneration reflects the generation of the most recently observed replication controller.", + "type": "integer", + "format": "int64" + }, + "readyReplicas": { + "description": "The number of ready replicas for this replication controller.", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "Replicas is the most recently oberved number of replicas. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.ResourceFieldSelector": { + "description": "ResourceFieldSelector represents container resources (cpu, memory) and their output format", + "required": [ + "resource" + ], + "properties": { + "containerName": { + "description": "Container name: required for volumes, optional for env vars", + "type": "string" + }, + "divisor": { + "description": "Specifies the output format of the exposed resources, defaults to \"1\"", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + }, + "resource": { + "description": "Required: resource to select", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ResourceQuota": { + "description": "ResourceQuota sets aggregate quota restrictions enforced per namespace", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the desired quota. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceQuotaSpec" + }, + "status": { + "description": "Status defines the actual enforced quota and its current usage. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceQuotaStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ResourceQuota", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ResourceQuotaList": { + "description": "ResourceQuotaList is a list of ResourceQuota items.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is a list of ResourceQuota objects. More info: https://git.k8s.io/community/contributors/design-proposals/admission_control_resource_quota.md", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceQuota" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ResourceQuotaList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ResourceQuotaSpec": { + "description": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", + "properties": { + "hard": { + "description": "Hard is the set of desired hard limits for each named resource. More info: https://git.k8s.io/community/contributors/design-proposals/admission_control_resource_quota.md", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "scopes": { + "description": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.ResourceQuotaStatus": { + "description": "ResourceQuotaStatus defines the enforced hard limits and observed use.", + "properties": { + "hard": { + "description": "Hard is the set of enforced hard limits for each named resource. More info: https://git.k8s.io/community/contributors/design-proposals/admission_control_resource_quota.md", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "used": { + "description": "Used is the current observed total usage of the resource in the namespace.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + } + } + }, + "io.k8s.api.core.v1.ResourceRequirements": { + "description": "ResourceRequirements describes the compute resource requirements.", + "properties": { + "limits": { + "description": "Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "requests": { + "description": "Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + } + } + }, + "io.k8s.api.core.v1.SELinuxOptions": { + "description": "SELinuxOptions are the labels to be applied to the container", + "properties": { + "level": { + "description": "Level is SELinux level label that applies to the container.", + "type": "string" + }, + "role": { + "description": "Role is a SELinux role label that applies to the container.", + "type": "string" + }, + "type": { + "description": "Type is a SELinux type label that applies to the container.", + "type": "string" + }, + "user": { + "description": "User is a SELinux user label that applies to the container.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ScaleIOVolumeSource": { + "description": "ScaleIOVolumeSource represents a persistent ScaleIO volume", + "required": [ + "gateway", + "system", + "secretRef" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "gateway": { + "description": "The host address of the ScaleIO API Gateway.", + "type": "string" + }, + "protectionDomain": { + "description": "The name of the Protection Domain for the configured storage (defaults to \"default\").", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretRef": { + "description": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail.", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "sslEnabled": { + "description": "Flag to enable/disable SSL communication with Gateway, default false", + "type": "boolean" + }, + "storageMode": { + "description": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\").", + "type": "string" + }, + "storagePool": { + "description": "The Storage Pool associated with the protection domain (defaults to \"default\").", + "type": "string" + }, + "system": { + "description": "The name of the storage system as configured in ScaleIO.", + "type": "string" + }, + "volumeName": { + "description": "The name of a volume already created in the ScaleIO system that is associated with this volume source.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Secret": { + "description": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "data": { + "description": "Data contains the secret data. Each key must consist of alphanumeric characters, '-', '_' or '.'. The serialized form of the secret data is a base64 encoded string, representing the arbitrary (possibly non-string) data value here. Described in https://tools.ietf.org/html/rfc4648#section-4", + "type": "object", + "additionalProperties": { + "type": "string", + "format": "byte" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "stringData": { + "description": "stringData allows specifying non-binary secret data in string form. It is provided as a write-only convenience method. All keys and values are merged into the data field on write, overwriting any existing values. It is never output when reading from the API.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "type": { + "description": "Used to facilitate programmatic handling of secret data.", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Secret", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.SecretEnvSource": { + "description": "SecretEnvSource selects a Secret to populate the environment variables with.\n\nThe contents of the target Secret's Data field will represent the key-value pairs as environment variables.", + "properties": { + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the Secret must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.SecretKeySelector": { + "description": "SecretKeySelector selects a key of a Secret.", + "required": [ + "key" + ], + "properties": { + "key": { + "description": "The key of the secret to select from. Must be a valid secret key.", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the Secret or it's key must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.SecretList": { + "description": "SecretList is a list of Secret.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is a list of secret objects. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Secret" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "SecretList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.SecretProjection": { + "description": "Adapts a secret into a projected volume.\n\nThe contents of the target Secret's Data field will be presented in a projected volume as files using the keys in the Data field as the file names. Note that this is identical to a secret volume source without the default mode.", + "properties": { + "items": { + "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.KeyToPath" + } + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the Secret or its key must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.SecretReference": { + "description": "SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace", + "properties": { + "name": { + "description": "Name is unique within a namespace to reference a secret resource.", + "type": "string" + }, + "namespace": { + "description": "Namespace defines the space within which the secret name must be unique.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.SecretVolumeSource": { + "description": "Adapts a Secret into a volume.\n\nThe contents of the target Secret's Data field will be presented in a volume as files using the keys in the Data field as the file names. Secret volumes support ownership management and SELinux relabeling.", + "properties": { + "defaultMode": { + "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "items": { + "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.KeyToPath" + } + }, + "optional": { + "description": "Specify whether the Secret or it's keys must be defined", + "type": "boolean" + }, + "secretName": { + "description": "Name of the secret in the pod's namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.SecurityContext": { + "description": "SecurityContext holds security configuration that will be applied to a container. Some fields are present in both SecurityContext and PodSecurityContext. When both are set, the values in SecurityContext take precedence.", + "properties": { + "allowPrivilegeEscalation": { + "description": "AllowPrivilegeEscalation controls whether a process can gain more privileges than it's parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN", + "type": "boolean" + }, + "capabilities": { + "description": "The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime.", + "$ref": "#/definitions/io.k8s.api.core.v1.Capabilities" + }, + "privileged": { + "description": "Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false.", + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "description": "Whether this container has a read-only root filesystem. Default is false.", + "type": "boolean" + }, + "runAsNonRoot": { + "description": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", + "type": "boolean" + }, + "runAsUser": { + "description": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", + "type": "integer", + "format": "int64" + }, + "seLinuxOptions": { + "description": "The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", + "$ref": "#/definitions/io.k8s.api.core.v1.SELinuxOptions" + } + } + }, + "io.k8s.api.core.v1.Service": { + "description": "Service is a named abstraction of software service (for example, mysql) consisting of local port (for example 3306) that the proxy listens on, and the selector that determines which pods will answer requests sent through the proxy.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the behavior of a service. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ServiceSpec" + }, + "status": { + "description": "Most recently observed status of the service. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ServiceStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Service", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ServiceAccount": { + "description": "ServiceAccount binds together: * a name, understood by users, and perhaps by peripheral systems, for an identity * a principal that can be authenticated and authorized * a set of secrets", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "automountServiceAccountToken": { + "description": "AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted. Can be overridden at the pod level.", + "type": "boolean" + }, + "imagePullSecrets": { + "description": "ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet. More info: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "secrets": { + "description": "Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ServiceAccount", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ServiceAccountList": { + "description": "ServiceAccountList is a list of ServiceAccount objects", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of ServiceAccounts. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ServiceAccount" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ServiceAccountList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ServiceList": { + "description": "ServiceList holds a list of services.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of services", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Service" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ServiceList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ServicePort": { + "description": "ServicePort contains information on service's port.", + "required": [ + "port" + ], + "properties": { + "name": { + "description": "The name of this port within the service. This must be a DNS_LABEL. All ports within a ServiceSpec must have unique names. This maps to the 'Name' field in EndpointPort objects. Optional if only one ServicePort is defined on this service.", + "type": "string" + }, + "nodePort": { + "description": "The port on each node on which this service is exposed when type=NodePort or LoadBalancer. Usually assigned by the system. If specified, it will be allocated to the service if unused or else creation of the service will fail. Default is to auto-allocate a port if the ServiceType of this Service requires one. More info: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport", + "type": "integer", + "format": "int32" + }, + "port": { + "description": "The port that will be exposed by this service.", + "type": "integer", + "format": "int32" + }, + "protocol": { + "description": "The IP protocol for this port. Supports \"TCP\" and \"UDP\". Default is TCP.", + "type": "string" + }, + "targetPort": { + "description": "Number or name of the port to access on the pods targeted by the service. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. If this is a string, it will be looked up as a named port in the target Pod's container ports. If this is not specified, the value of the 'port' field is used (an identity map). This field is ignored for services with clusterIP=None, and should be omitted or set equal to the 'port' field. More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, + "io.k8s.api.core.v1.ServiceSpec": { + "description": "ServiceSpec describes the attributes that a user creates on a service.", + "properties": { + "clusterIP": { + "description": "clusterIP is the IP address of the service and is usually assigned randomly by the master. If an address is specified manually and is not in use by others, it will be allocated to the service; otherwise, creation of the service will fail. This field can not be changed through updates. Valid values are \"None\", empty string (\"\"), or a valid IP address. \"None\" can be specified for headless services when proxying is not required. Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if type is ExternalName. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies", + "type": "string" + }, + "externalIPs": { + "description": "externalIPs is a list of IP addresses for which nodes in the cluster will also accept traffic for this service. These IPs are not managed by Kubernetes. The user is responsible for ensuring that traffic arrives at a node with this IP. A common example is external load-balancers that are not part of the Kubernetes system.", + "type": "array", + "items": { + "type": "string" + } + }, + "externalName": { + "description": "externalName is the external reference that kubedns or equivalent will return as a CNAME record for this service. No proxying will be involved. Must be a valid DNS name and requires Type to be ExternalName.", + "type": "string" + }, + "externalTrafficPolicy": { + "description": "externalTrafficPolicy denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints. \"Local\" preserves the client source IP and avoids a second hop for LoadBalancer and Nodeport type services, but risks potentially imbalanced traffic spreading. \"Cluster\" obscures the client source IP and may cause a second hop to another node, but should have good overall load-spreading.", + "type": "string" + }, + "healthCheckNodePort": { + "description": "healthCheckNodePort specifies the healthcheck nodePort for the service. If not specified, HealthCheckNodePort is created by the service api backend with the allocated nodePort. Will use user-specified nodePort value if specified by the client. Only effects when Type is set to LoadBalancer and ExternalTrafficPolicy is set to Local.", + "type": "integer", + "format": "int32" + }, + "loadBalancerIP": { + "description": "Only applies to Service Type: LoadBalancer LoadBalancer will get created with the IP specified in this field. This feature depends on whether the underlying cloud-provider supports specifying the loadBalancerIP when a load balancer is created. This field will be ignored if the cloud-provider does not support the feature.", + "type": "string" + }, + "loadBalancerSourceRanges": { + "description": "If specified and supported by the platform, this will restrict traffic through the cloud-provider load-balancer will be restricted to the specified client IPs. This field will be ignored if the cloud-provider does not support the feature.\" More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/", + "type": "array", + "items": { + "type": "string" + } + }, + "ports": { + "description": "The list of ports that are exposed by this service. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ServicePort" + }, + "x-kubernetes-patch-merge-key": "port", + "x-kubernetes-patch-strategy": "merge" + }, + "publishNotReadyAddresses": { + "description": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery. This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints when that annotation is deprecated and all clients have been converted to use this field.", + "type": "boolean" + }, + "selector": { + "description": "Route service traffic to pods with label keys and values matching this selector. If empty or not present, the service is assumed to have an external process managing its endpoints, which Kubernetes will not modify. Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if type is ExternalName. More info: https://kubernetes.io/docs/concepts/services-networking/service/", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "sessionAffinity": { + "description": "Supports \"ClientIP\" and \"None\". Used to maintain session affinity. Enable client IP based session affinity. Must be ClientIP or None. Defaults to None. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies", + "type": "string" + }, + "sessionAffinityConfig": { + "description": "sessionAffinityConfig contains the configurations of session affinity.", + "$ref": "#/definitions/io.k8s.api.core.v1.SessionAffinityConfig" + }, + "type": { + "description": "type determines how the Service is exposed. Defaults to ClusterIP. Valid options are ExternalName, ClusterIP, NodePort, and LoadBalancer. \"ExternalName\" maps to the specified externalName. \"ClusterIP\" allocates a cluster-internal IP address for load-balancing to endpoints. Endpoints are determined by the selector or if that is not specified, by manual construction of an Endpoints object. If clusterIP is \"None\", no virtual IP is allocated and the endpoints are published as a set of endpoints rather than a stable IP. \"NodePort\" builds on ClusterIP and allocates a port on every node which routes to the clusterIP. \"LoadBalancer\" builds on NodePort and creates an external load-balancer (if supported in the current cloud) which routes to the clusterIP. More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ServiceStatus": { + "description": "ServiceStatus represents the current status of a service.", + "properties": { + "loadBalancer": { + "description": "LoadBalancer contains the current status of the load-balancer, if one is present.", + "$ref": "#/definitions/io.k8s.api.core.v1.LoadBalancerStatus" + } + } + }, + "io.k8s.api.core.v1.SessionAffinityConfig": { + "description": "SessionAffinityConfig represents the configurations of session affinity.", + "properties": { + "clientIP": { + "description": "clientIP contains the configurations of Client IP based session affinity.", + "$ref": "#/definitions/io.k8s.api.core.v1.ClientIPConfig" + } + } + }, + "io.k8s.api.core.v1.StorageOSPersistentVolumeSource": { + "description": "Represents a StorageOS persistent volume resource.", + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretRef": { + "description": "SecretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "volumeName": { + "description": "VolumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace.", + "type": "string" + }, + "volumeNamespace": { + "description": "VolumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping to be mirrored within StorageOS for tighter integration. Set VolumeName to any name to override the default behaviour. Set to \"default\" if you are not using namespaces within StorageOS. Namespaces that do not pre-exist within StorageOS will be created.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.StorageOSVolumeSource": { + "description": "Represents a StorageOS persistent volume resource.", + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretRef": { + "description": "SecretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted.", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "volumeName": { + "description": "VolumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace.", + "type": "string" + }, + "volumeNamespace": { + "description": "VolumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping to be mirrored within StorageOS for tighter integration. Set VolumeName to any name to override the default behaviour. Set to \"default\" if you are not using namespaces within StorageOS. Namespaces that do not pre-exist within StorageOS will be created.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.TCPSocketAction": { + "description": "TCPSocketAction describes an action based on opening a socket", + "required": [ + "port" + ], + "properties": { + "host": { + "description": "Optional: Host name to connect to, defaults to the pod IP.", + "type": "string" + }, + "port": { + "description": "Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, + "io.k8s.api.core.v1.Taint": { + "description": "The node this Taint is attached to has the \"effect\" on any pod that does not tolerate the Taint.", + "required": [ + "key", + "effect" + ], + "properties": { + "effect": { + "description": "Required. The effect of the taint on pods that do not tolerate the taint. Valid effects are NoSchedule, PreferNoSchedule and NoExecute.", + "type": "string" + }, + "key": { + "description": "Required. The taint key to be applied to a node.", + "type": "string" + }, + "timeAdded": { + "description": "TimeAdded represents the time at which the taint was added. It is only written for NoExecute taints.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "value": { + "description": "Required. The taint value corresponding to the taint key.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Toleration": { + "description": "The pod this Toleration is attached to tolerates any taint that matches the triple \u003ckey,value,effect\u003e using the matching operator \u003coperator\u003e.", + "properties": { + "effect": { + "description": "Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.", + "type": "string" + }, + "key": { + "description": "Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys.", + "type": "string" + }, + "operator": { + "description": "Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category.", + "type": "string" + }, + "tolerationSeconds": { + "description": "TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.", + "type": "integer", + "format": "int64" + }, + "value": { + "description": "Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Volume": { + "description": "Volume represents a named volume in a pod that may be accessed by any container in the pod.", + "required": [ + "name" + ], + "properties": { + "awsElasticBlockStore": { + "description": "AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "$ref": "#/definitions/io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource" + }, + "azureDisk": { + "description": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.AzureDiskVolumeSource" + }, + "azureFile": { + "description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.AzureFileVolumeSource" + }, + "cephfs": { + "description": "CephFS represents a Ceph FS mount on the host that shares a pod's lifetime", + "$ref": "#/definitions/io.k8s.api.core.v1.CephFSVolumeSource" + }, + "cinder": { + "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.CinderVolumeSource" + }, + "configMap": { + "description": "ConfigMap represents a configMap that should populate this volume", + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapVolumeSource" + }, + "downwardAPI": { + "description": "DownwardAPI represents downward API about the pod that should populate this volume", + "$ref": "#/definitions/io.k8s.api.core.v1.DownwardAPIVolumeSource" + }, + "emptyDir": { + "description": "EmptyDir represents a temporary directory that shares a pod's lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir", + "$ref": "#/definitions/io.k8s.api.core.v1.EmptyDirVolumeSource" + }, + "fc": { + "description": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.FCVolumeSource" + }, + "flexVolume": { + "description": "FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. This is an alpha feature and may change in future.", + "$ref": "#/definitions/io.k8s.api.core.v1.FlexVolumeSource" + }, + "flocker": { + "description": "Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running", + "$ref": "#/definitions/io.k8s.api.core.v1.FlockerVolumeSource" + }, + "gcePersistentDisk": { + "description": "GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "$ref": "#/definitions/io.k8s.api.core.v1.GCEPersistentDiskVolumeSource" + }, + "gitRepo": { + "description": "GitRepo represents a git repository at a particular revision.", + "$ref": "#/definitions/io.k8s.api.core.v1.GitRepoVolumeSource" + }, + "glusterfs": { + "description": "Glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.GlusterfsVolumeSource" + }, + "hostPath": { + "description": "HostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", + "$ref": "#/definitions/io.k8s.api.core.v1.HostPathVolumeSource" + }, + "iscsi": { + "description": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://releases.k8s.io/HEAD/examples/volumes/iscsi/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.ISCSIVolumeSource" + }, + "name": { + "description": "Volume's name. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "nfs": { + "description": "NFS represents an NFS mount on the host that shares a pod's lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "$ref": "#/definitions/io.k8s.api.core.v1.NFSVolumeSource" + }, + "persistentVolumeClaim": { + "description": "PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource" + }, + "photonPersistentDisk": { + "description": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource" + }, + "portworxVolume": { + "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.PortworxVolumeSource" + }, + "projected": { + "description": "Items for all in one resources secrets, configmaps, and downward API", + "$ref": "#/definitions/io.k8s.api.core.v1.ProjectedVolumeSource" + }, + "quobyte": { + "description": "Quobyte represents a Quobyte mount on the host that shares a pod's lifetime", + "$ref": "#/definitions/io.k8s.api.core.v1.QuobyteVolumeSource" + }, + "rbd": { + "description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.RBDVolumeSource" + }, + "scaleIO": { + "description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.", + "$ref": "#/definitions/io.k8s.api.core.v1.ScaleIOVolumeSource" + }, + "secret": { + "description": "Secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretVolumeSource" + }, + "storageos": { + "description": "StorageOS represents a StorageOS volume attached and mounted on Kubernetes nodes.", + "$ref": "#/definitions/io.k8s.api.core.v1.StorageOSVolumeSource" + }, + "vsphereVolume": { + "description": "VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource" + } + } + }, + "io.k8s.api.core.v1.VolumeMount": { + "description": "VolumeMount describes a mounting of a Volume within a container.", + "required": [ + "name", + "mountPath" + ], + "properties": { + "mountPath": { + "description": "Path within the container at which the volume should be mounted. Must not contain ':'.", + "type": "string" + }, + "name": { + "description": "This must match the Name of a Volume.", + "type": "string" + }, + "readOnly": { + "description": "Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false.", + "type": "boolean" + }, + "subPath": { + "description": "Path within the volume from which the container's volume should be mounted. Defaults to \"\" (volume's root).", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.VolumeProjection": { + "description": "Projection that may be projected along with other supported volume types", + "properties": { + "configMap": { + "description": "information about the configMap data to project", + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapProjection" + }, + "downwardAPI": { + "description": "information about the downwardAPI data to project", + "$ref": "#/definitions/io.k8s.api.core.v1.DownwardAPIProjection" + }, + "secret": { + "description": "information about the secret data to project", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretProjection" + } + } + }, + "io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource": { + "description": "Represents a vSphere volume resource.", + "required": [ + "volumePath" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "storagePolicyID": { + "description": "Storage Policy Based Management (SPBM) profile ID associated with the StoragePolicyName.", + "type": "string" + }, + "storagePolicyName": { + "description": "Storage Policy Based Management (SPBM) profile name.", + "type": "string" + }, + "volumePath": { + "description": "Path that identifies vSphere volume vmdk", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.WeightedPodAffinityTerm": { + "description": "The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s)", + "required": [ + "weight", + "podAffinityTerm" + ], + "properties": { + "podAffinityTerm": { + "description": "Required. A pod affinity term, associated with the corresponding weight.", + "$ref": "#/definitions/io.k8s.api.core.v1.PodAffinityTerm" + }, + "weight": { + "description": "weight associated with matching the corresponding podAffinityTerm, in the range 1-100.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.apimachinery.pkg.api.resource.Quantity": { + "type": "string" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup": { + "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", + "required": [ + "name", + "versions", + "serverAddressByClientCIDRs" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "name is the name of the group.", + "type": "string" + }, + "preferredVersion": { + "description": "preferredVersion is the version preferred by the API server, which probably is the storage version.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery" + }, + "serverAddressByClientCIDRs": { + "description": "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR" + } + }, + "versions": { + "description": "versions are the versions supported in this group.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIGroup", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIGroupList": { + "description": "APIGroupList is a list of APIGroup, to allow clients to discover the API at /apis.", + "required": [ + "groups" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "groups": { + "description": "groups is a list of APIGroup.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIGroupList", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIResource": { + "description": "APIResource specifies the name of a resource and whether it is namespaced.", + "required": [ + "name", + "singularName", + "namespaced", + "kind", + "verbs" + ], + "properties": { + "categories": { + "description": "categories is a list of the grouped resources this resource belongs to (e.g. 'all')", + "type": "array", + "items": { + "type": "string" + } + }, + "kind": { + "description": "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')", + "type": "string" + }, + "name": { + "description": "name is the plural name of the resource.", + "type": "string" + }, + "namespaced": { + "description": "namespaced indicates if a resource is namespaced or not.", + "type": "boolean" + }, + "shortNames": { + "description": "shortNames is a list of suggested short names of the resource.", + "type": "array", + "items": { + "type": "string" + } + }, + "singularName": { + "description": "singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface.", + "type": "string" + }, + "verbs": { + "description": "verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList": { + "description": "APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.", + "required": [ + "groupVersion", + "resources" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "groupVersion": { + "description": "groupVersion is the group and version this APIResourceList is for.", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "resources": { + "description": "resources contains the name of the resources and if they are namespaced.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIResource" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIResourceList", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIVersions": { + "description": "APIVersions lists the versions that are available, to allow clients to discover the API at /api, which is the root path of the legacy v1 API.", + "required": [ + "versions", + "serverAddressByClientCIDRs" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "serverAddressByClientCIDRs": { + "description": "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR" + } + }, + "versions": { + "description": "versions are the api versions that are available.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIVersions", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions": { + "description": "DeleteOptions may be provided when deleting an API object.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "gracePeriodSeconds": { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "type": "integer", + "format": "int64" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "orphanDependents": { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "type": "boolean" + }, + "preconditions": { + "description": "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions" + }, + "propagationPolicy": { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy.", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "admission.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "apps", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "apps", + "kind": "DeleteOptions", + "version": "v1beta2" + }, + { + "group": "authentication.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "authentication.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "autoscaling", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "autoscaling", + "kind": "DeleteOptions", + "version": "v2alpha1" + }, + { + "group": "batch", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "batch", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "batch", + "kind": "DeleteOptions", + "version": "v2alpha1" + }, + { + "group": "certificates.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "extensions", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "federation", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "imagepolicy.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "networking.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "policy", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "scheduling.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "settings.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "storage.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "storage.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery": { + "description": "GroupVersion contains the \"group/version\" and \"version\" string of a version. It is made a struct to keep extensibility.", + "required": [ + "groupVersion", + "version" + ], + "properties": { + "groupVersion": { + "description": "groupVersion specifies the API group and version in the form \"group/version\"", + "type": "string" + }, + "version": { + "description": "version specifies the version in the form of \"version\". This is to save the clients the trouble of splitting the GroupVersion.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Initializer": { + "description": "Initializer is information about an initializer that has not yet completed.", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "name of the process that is responsible for initializing this object.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Initializers": { + "description": "Initializers tracks the progress of initialization.", + "required": [ + "pending" + ], + "properties": { + "pending": { + "description": "Pending is a list of initializers that must execute in order before this object is visible. When the last pending initializer is removed, and no failing result is set, the initializers struct will be set to nil and the object is considered as initialized and visible to all clients.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Initializer" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "result": { + "description": "If result is set with the Failure field, the object will be persisted to storage and then deleted, ensuring that other clients can observe the deletion.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector": { + "description": "A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement" + } + }, + "matchLabels": { + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.", + "required": [ + "key", + "operator" + ], + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string", + "x-kubernetes-patch-merge-key": "key", + "x-kubernetes-patch-strategy": "merge" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values. Valid operators ard In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta": { + "description": "ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.", + "properties": { + "resourceVersion": { + "description": "String that identifies the server's internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency", + "type": "string" + }, + "selfLink": { + "description": "SelfLink is a URL representing this object. Populated by the system. Read-only.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": { + "description": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.", + "properties": { + "annotations": { + "description": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "clusterName": { + "description": "The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.", + "type": "string" + }, + "creationTimestamp": { + "description": "CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "deletionGracePeriodSeconds": { + "description": "Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.", + "type": "integer", + "format": "int64" + }, + "deletionTimestamp": { + "description": "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field. Once set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "finalizers": { + "description": "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed.", + "type": "array", + "items": { + "type": "string" + }, + "x-kubernetes-patch-strategy": "merge" + }, + "generateName": { + "description": "GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.\n\nIf this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).\n\nApplied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency", + "type": "string" + }, + "generation": { + "description": "A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.", + "type": "integer", + "format": "int64" + }, + "initializers": { + "description": "An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to observe uninitialized objects.\n\nWhen an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Initializers" + }, + "labels": { + "description": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "description": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names", + "type": "string" + }, + "namespace": { + "description": "Namespace defines the space within each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces", + "type": "string" + }, + "ownerReferences": { + "description": "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference" + }, + "x-kubernetes-patch-merge-key": "uid", + "x-kubernetes-patch-strategy": "merge" + }, + "resourceVersion": { + "description": "An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.\n\nPopulated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency", + "type": "string" + }, + "selfLink": { + "description": "SelfLink is a URL representing this object. Populated by the system. Read-only.", + "type": "string" + }, + "uid": { + "description": "UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.\n\nPopulated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference": { + "description": "OwnerReference contains enough information to let you identify an owning object. Currently, an owning object must be in the same namespace, so there is no namespace field.", + "required": [ + "apiVersion", + "kind", + "name", + "uid" + ], + "properties": { + "apiVersion": { + "description": "API version of the referent.", + "type": "string" + }, + "blockOwnerDeletion": { + "description": "If true, AND if the owner has the \"foregroundDeletion\" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. Defaults to false. To set this field, a user needs \"delete\" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned.", + "type": "boolean" + }, + "controller": { + "description": "If true, this reference points to the managing controller.", + "type": "boolean" + }, + "kind": { + "description": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", + "type": "string" + }, + "uid": { + "description": "UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Patch": { + "description": "Patch is provided to give a concrete name and type to the Kubernetes PATCH request body." + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions": { + "description": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.", + "properties": { + "uid": { + "description": "Specifies the target UID.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR": { + "description": "ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.", + "required": [ + "clientCIDR", + "serverAddress" + ], + "properties": { + "clientCIDR": { + "description": "The CIDR with which clients can match their IP to figure out the server address that they should use.", + "type": "string" + }, + "serverAddress": { + "description": "Address of this server, suitable for a client that matches the above CIDR. This can be a hostname, hostname:port, IP or IP:port.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Status": { + "description": "Status is a return value for calls that don't return other objects.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "code": { + "description": "Suggested HTTP return code for this status, 0 if not set.", + "type": "integer", + "format": "int32" + }, + "details": { + "description": "Extended data associated with the reason. Each reason may define its own extended details. This field is optional and the data returned is not guaranteed to conform to any schema except that defined by the reason type.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "message": { + "description": "A human-readable description of the status of this operation.", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + }, + "reason": { + "description": "A machine-readable description of why this operation is in the \"Failure\" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it.", + "type": "string" + }, + "status": { + "description": "Status of the operation. One of: \"Success\" or \"Failure\". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Status", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause": { + "description": "StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered.", + "properties": { + "field": { + "description": "The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.\n\nExamples:\n \"name\" - the field \"name\" on the current resource\n \"items[0].name\" - the field \"name\" on the first array entry in \"items\"", + "type": "string" + }, + "message": { + "description": "A human-readable description of the cause of the error. This field may be presented as-is to a reader.", + "type": "string" + }, + "reason": { + "description": "A machine-readable description of the cause of the error. If this value is empty there is no information available.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails": { + "description": "StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.", + "properties": { + "causes": { + "description": "The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause" + } + }, + "group": { + "description": "The group attribute of the resource associated with the status StatusReason.", + "type": "string" + }, + "kind": { + "description": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described).", + "type": "string" + }, + "retryAfterSeconds": { + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.", + "type": "integer", + "format": "int32" + }, + "uid": { + "description": "UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Time": { + "type": "string", + "format": "date-time" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent": { + "description": "Event represents a single event to a watched resource.", + "required": [ + "type", + "object" + ], + "properties": { + "object": { + "description": "Object is:\n * If Type is Added or Modified: the new state of the object.\n * If Type is Deleted: the state of the object immediately before deletion.\n * If Type is Error: *Status is recommended; other types may make sense\n depending on context.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.runtime.RawExtension" + }, + "type": { + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "admission.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "apps", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "apps", + "kind": "WatchEvent", + "version": "v1beta2" + }, + { + "group": "authentication.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "authentication.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "autoscaling", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "autoscaling", + "kind": "WatchEvent", + "version": "v2alpha1" + }, + { + "group": "batch", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "batch", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "batch", + "kind": "WatchEvent", + "version": "v2alpha1" + }, + { + "group": "certificates.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "extensions", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "federation", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "imagepolicy.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "networking.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "policy", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "scheduling.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "settings.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "storage.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "storage.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + } + ] + }, + "io.k8s.apimachinery.pkg.runtime.RawExtension": { + "description": "RawExtension is used to hold extensions in external versions.\n\nTo use this, make a field which has RawExtension as its type in your external, versioned struct, and Object in your internal struct. You also need to register your various plugin types.\n\n// Internal package: type MyAPIObject struct {\n\truntime.TypeMeta `json:\",inline\"`\n\tMyPlugin runtime.Object `json:\"myPlugin\"`\n} type PluginA struct {\n\tAOption string `json:\"aOption\"`\n}\n\n// External package: type MyAPIObject struct {\n\truntime.TypeMeta `json:\",inline\"`\n\tMyPlugin runtime.RawExtension `json:\"myPlugin\"`\n} type PluginA struct {\n\tAOption string `json:\"aOption\"`\n}\n\n// On the wire, the JSON will look something like this: {\n\t\"kind\":\"MyAPIObject\",\n\t\"apiVersion\":\"v1\",\n\t\"myPlugin\": {\n\t\t\"kind\":\"PluginA\",\n\t\t\"aOption\":\"foo\",\n\t},\n}\n\nSo what happens? Decode first uses json or yaml to unmarshal the serialized data into your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked. The next step is to copy (using pkg/conversion) into the internal struct. The runtime package's DefaultScheme has conversion functions installed which will unpack the JSON stored in RawExtension, turning it into the correct object type, and storing it in the Object. (TODO: In the case where the object is of an unknown type, a runtime.Unknown object will be created and stored.)", + "required": [ + "Raw" + ], + "properties": { + "Raw": { + "description": "Raw is the underlying serialization of this object.", + "type": "string", + "format": "byte" + } + } + }, + "io.k8s.apimachinery.pkg.util.intstr.IntOrString": { + "type": "string", + "format": "int-or-string" + }, + "io.k8s.apimachinery.pkg.version.Info": { + "description": "Info contains versioning information. how we'll want to distribute that information.", + "required": [ + "major", + "minor", + "gitVersion", + "gitCommit", + "gitTreeState", + "buildDate", + "goVersion", + "compiler", + "platform" + ], + "properties": { + "buildDate": { + "type": "string" + }, + "compiler": { + "type": "string" + }, + "gitCommit": { + "type": "string" + }, + "gitTreeState": { + "type": "string" + }, + "gitVersion": { + "type": "string" + }, + "goVersion": { + "type": "string" + }, + "major": { + "type": "string" + }, + "minor": { + "type": "string" + }, + "platform": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "BearerToken": { + "description": "Bearer Token authentication", + "type": "apiKey", + "name": "authorization", + "in": "header" + } + }, + "security": [ + { + "BearerToken": [] + } + ] + } diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/testdata/swagger_next.json b/vendor/k8s.io/kube-openapi/pkg/util/proto/testdata/swagger_next.json new file mode 100644 index 000000000..f2dc451f9 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/testdata/swagger_next.json @@ -0,0 +1,6574 @@ +{ + "swagger": "2.0", + "info": { + "title": "Kubernetes", + "version": "v1.8.0" + }, + "paths": {}, + "definitions": { + "io.k8s.api.apps.v1beta1.ControllerRevision": { + "description": "ControllerRevision implements an immutable snapshot of state data. Clients are responsible for serializing and deserializing the objects that contain their internal state. Once a ControllerRevision has been successfully created, it can not be updated. The API Server will fail validation of all requests that attempt to mutate the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, it may be subject to name and representation changes in future releases, and clients should not depend on its stability. It is primarily for internal use by controllers.", + "type": "object", + "required": [ + "revision" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "data": { + "description": "Data is the serialized representation of the state.", + "type": "object" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "revision": { + "description": "Revision indicates the revision of the state represented by Data.", + "type": "integer", + "format": "int64" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "ControllerRevision", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.ControllerRevisionList": { + "description": "ControllerRevisionList is a resource containing a list of ControllerRevision objects.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is the list of ControllerRevisions", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.ControllerRevision" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "ControllerRevisionList", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.Deployment": { + "description": "Deployment enables declarative updates for Pods and ReplicaSets.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object metadata.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Specification of the desired behavior of the Deployment.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentSpec" + }, + "status": { + "description": "Most recently observed status of the Deployment.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "Deployment", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.DeploymentCondition": { + "description": "DeploymentCondition describes the state of a deployment at a certain point.", + "type": "object", + "required": [ + "type", + "status" + ], + "properties": { + "lastTransitionTime": { + "description": "Last time the condition transitioned from one status to another.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "lastUpdateTime": { + "description": "The last time this condition was updated.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "A human readable message indicating details about the transition.", + "type": "string" + }, + "reason": { + "description": "The reason for the condition's last transition.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of deployment condition.", + "type": "string" + } + } + }, + "io.k8s.api.apps.v1beta1.DeploymentList": { + "description": "DeploymentList is a list of Deployments.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is the list of Deployments.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.Deployment" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "DeploymentList", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.DeploymentRollback": { + "description": "DEPRECATED. DeploymentRollback stores the information required to rollback a deployment.", + "type": "object", + "required": [ + "name", + "rollbackTo" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "Required: This must match the Name of a deployment.", + "type": "string" + }, + "rollbackTo": { + "description": "The config of this deployment rollback.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.RollbackConfig" + }, + "updatedAnnotations": { + "description": "The annotations to be updated to a deployment", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "DeploymentRollback", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.DeploymentSpec": { + "description": "DeploymentSpec is the specification of the desired behavior of the Deployment.", + "type": "object", + "required": [ + "template" + ], + "properties": { + "minReadySeconds": { + "description": "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)", + "type": "integer", + "format": "int32" + }, + "paused": { + "description": "Indicates that the deployment is paused.", + "type": "boolean" + }, + "progressDeadlineSeconds": { + "description": "The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Once autoRollback is implemented, the deployment controller will automatically rollback failed deployments. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s.", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1.", + "type": "integer", + "format": "int32" + }, + "revisionHistoryLimit": { + "description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 2.", + "type": "integer", + "format": "int32" + }, + "rollbackTo": { + "description": "DEPRECATED. The config this deployment is rolling back to. Will be cleared after rollback is done.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.RollbackConfig" + }, + "selector": { + "description": "Label selector for pods. Existing ReplicaSets whose pods are selected by this will be the ones affected by this deployment.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, + "strategy": { + "description": "The deployment strategy to use to replace existing pods with new ones.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentStrategy" + }, + "template": { + "description": "Template describes the pods that will be created.", + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" + } + } + }, + "io.k8s.api.apps.v1beta1.DeploymentStatus": { + "description": "DeploymentStatus is the most recently observed status of the Deployment.", + "type": "object", + "properties": { + "availableReplicas": { + "description": "Total number of available pods (ready for at least minReadySeconds) targeted by this deployment.", + "type": "integer", + "format": "int32" + }, + "collisionCount": { + "description": "Count of hash collisions for the Deployment. The Deployment controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ReplicaSet.", + "type": "integer", + "format": "int32" + }, + "conditions": { + "description": "Represents the latest available observations of a deployment's current state.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "observedGeneration": { + "description": "The generation observed by the deployment controller.", + "type": "integer", + "format": "int64" + }, + "readyReplicas": { + "description": "Total number of ready pods targeted by this deployment.", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "Total number of non-terminated pods targeted by this deployment (their labels match the selector).", + "type": "integer", + "format": "int32" + }, + "unavailableReplicas": { + "description": "Total number of unavailable pods targeted by this deployment.", + "type": "integer", + "format": "int32" + }, + "updatedReplicas": { + "description": "Total number of non-terminated pods targeted by this deployment that have the desired template spec.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.apps.v1beta1.DeploymentStrategy": { + "description": "DeploymentStrategy describes how to replace existing pods with new ones.", + "type": "object", + "properties": { + "rollingUpdate": { + "description": "Rolling update config params. Present only if DeploymentStrategyType = RollingUpdate.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.RollingUpdateDeployment" + }, + "type": { + "description": "Type of deployment. Can be \"Recreate\" or \"RollingUpdate\". Default is RollingUpdate.", + "type": "string" + } + } + }, + "io.k8s.api.apps.v1beta1.RollbackConfig": { + "description": "DEPRECATED.", + "type": "object", + "properties": { + "revision": { + "description": "The revision to rollback to. If set to 0, rollback to the last revision.", + "type": "integer", + "format": "int64" + } + } + }, + "io.k8s.api.apps.v1beta1.RollingUpdateDeployment": { + "description": "Spec to control the desired behavior of rolling update.", + "type": "object", + "properties": { + "maxSurge": { + "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + }, + "maxUnavailable": { + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, + "io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy": { + "description": "RollingUpdateStatefulSetStrategy is used to communicate parameter for RollingUpdateStatefulSetStrategyType.", + "type": "object", + "properties": { + "partition": { + "description": "Partition indicates the ordinal at which the StatefulSet should be partitioned.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.apps.v1beta1.Scale": { + "description": "Scale represents a scaling request for a resource.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "defines the behavior of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.ScaleSpec" + }, + "status": { + "description": "current status of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. Read-only.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.ScaleStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "Scale", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.ScaleSpec": { + "description": "ScaleSpec describes the attributes of a scale subresource", + "type": "object", + "properties": { + "replicas": { + "description": "desired number of instances for the scaled object.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.apps.v1beta1.ScaleStatus": { + "description": "ScaleStatus represents the current status of a scale subresource.", + "type": "object", + "required": [ + "replicas" + ], + "properties": { + "replicas": { + "description": "actual number of observed instances of the scaled object.", + "type": "integer", + "format": "int32" + }, + "selector": { + "description": "label query over pods that should match the replicas count. More info: http://kubernetes.io/docs/user-guide/labels#label-selectors", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "targetSelector": { + "description": "label selector for pods that should match the replicas count. This is a serializated version of both map-based and more expressive set-based selectors. This is done to avoid introspection in the clients. The string will be in the same format as the query-param syntax. If the target type only supports map-based selectors, both this field and map-based selector field are populated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", + "type": "string" + } + } + }, + "io.k8s.api.apps.v1beta1.StatefulSet": { + "description": "StatefulSet represents a set of pods with consistent identities. Identities are defined as:\n - Network: A single stable DNS and hostname.\n - Storage: As many VolumeClaims as requested.\nThe StatefulSet guarantees that a given network identity will always map to the same storage identity.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the desired identities of pods in this set.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.StatefulSetSpec" + }, + "status": { + "description": "Status is the current status of Pods in this StatefulSet. This data may be out of date by some window of time.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.StatefulSetStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "StatefulSet", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.StatefulSetList": { + "description": "StatefulSetList is a collection of StatefulSets.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.StatefulSet" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps", + "kind": "StatefulSetList", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.apps.v1beta1.StatefulSetSpec": { + "description": "A StatefulSetSpec is the specification of a StatefulSet.", + "type": "object", + "required": [ + "template", + "serviceName" + ], + "properties": { + "podManagementPolicy": { + "description": "podManagementPolicy controls how pods are created during initial scale up, when replacing pods on nodes, or when scaling down. The default policy is `OrderedReady`, where pods are created in increasing order (pod-0, then pod-1, etc) and the controller will wait until each pod is ready before continuing. When scaling down, the pods are removed in the opposite order. The alternative policy is `Parallel` which will create pods in parallel to match the desired scale without waiting, and on scale down will delete all pods at once.", + "type": "string" + }, + "replicas": { + "description": "replicas is the desired number of replicas of the given Template. These are replicas in the sense that they are instantiations of the same Template, but individual replicas also have a consistent identity. If unspecified, defaults to 1.", + "type": "integer", + "format": "int32" + }, + "revisionHistoryLimit": { + "description": "revisionHistoryLimit is the maximum number of revisions that will be maintained in the StatefulSet's revision history. The revision history consists of all revisions not represented by a currently applied StatefulSetSpec version. The default value is 10.", + "type": "integer", + "format": "int32" + }, + "selector": { + "description": "selector is a label query over pods that should match the replica count. If empty, defaulted to labels on the pod template. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, + "serviceName": { + "description": "serviceName is the name of the service that governs this StatefulSet. This service must exist before the StatefulSet, and is responsible for the network identity of the set. Pods get DNS/hostnames that follow the pattern: pod-specific-string.serviceName.default.svc.cluster.local where \"pod-specific-string\" is managed by the StatefulSet controller.", + "type": "string" + }, + "template": { + "description": "template is the object that describes the pod that will be created if insufficient replicas are detected. Each pod stamped out by the StatefulSet will fulfill this Template, but have a unique identity from the rest of the StatefulSet.", + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" + }, + "updateStrategy": { + "description": "updateStrategy indicates the StatefulSetUpdateStrategy that will be employed to update Pods in the StatefulSet when a revision is made to Template.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy" + }, + "volumeClaimTemplates": { + "description": "volumeClaimTemplates is a list of claims that pods are allowed to reference. The StatefulSet controller is responsible for mapping network identities to claims in a way that maintains the identity of a pod. Every claim in this list must have at least one matching (by name) volumeMount in one container in the template. A claim in this list takes precedence over any volumes in the template, with the same name.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaim" + } + } + } + }, + "io.k8s.api.apps.v1beta1.StatefulSetStatus": { + "description": "StatefulSetStatus represents the current state of a StatefulSet.", + "type": "object", + "required": [ + "replicas" + ], + "properties": { + "collisionCount": { + "description": "collisionCount is the count of hash collisions for the StatefulSet. The StatefulSet controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ControllerRevision.", + "type": "integer", + "format": "int32" + }, + "currentReplicas": { + "description": "currentReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version indicated by currentRevision.", + "type": "integer", + "format": "int32" + }, + "currentRevision": { + "description": "currentRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the sequence [0,currentReplicas).", + "type": "string" + }, + "observedGeneration": { + "description": "observedGeneration is the most recent generation observed for this StatefulSet. It corresponds to the StatefulSet's generation, which is updated on mutation by the API Server.", + "type": "integer", + "format": "int64" + }, + "readyReplicas": { + "description": "readyReplicas is the number of Pods created by the StatefulSet controller that have a Ready Condition.", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "replicas is the number of Pods created by the StatefulSet controller.", + "type": "integer", + "format": "int32" + }, + "updateRevision": { + "description": "updateRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the sequence [replicas-updatedReplicas,replicas)", + "type": "string" + }, + "updatedReplicas": { + "description": "updatedReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version indicated by updateRevision.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.apps.v1beta1.StatefulSetUpdateStrategy": { + "description": "StatefulSetUpdateStrategy indicates the strategy that the StatefulSet controller will use to perform updates. It includes any additional parameters necessary to perform the update for the indicated strategy.", + "type": "object", + "properties": { + "rollingUpdate": { + "description": "RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType.", + "$ref": "#/definitions/io.k8s.api.apps.v1beta1.RollingUpdateStatefulSetStrategy" + }, + "type": { + "description": "Type indicates the type of the StatefulSetUpdateStrategy.", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1.LocalSubjectAccessReview": { + "description": "LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions checking.", + "type": "object", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace you made the request against. If empty, it is defaulted.", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "LocalSubjectAccessReview", + "version": "v1" + } + ] + }, + "io.k8s.api.authorization.v1.NonResourceAttributes": { + "description": "NonResourceAttributes includes the authorization attributes available for non-resource requests to the Authorizer interface", + "type": "object", + "properties": { + "path": { + "description": "Path is the URL path of the request", + "type": "string" + }, + "verb": { + "description": "Verb is the standard HTTP verb", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1.ResourceAttributes": { + "description": "ResourceAttributes includes the authorization attributes available for resource requests to the Authorizer interface", + "type": "object", + "properties": { + "group": { + "description": "Group is the API Group of the Resource. \"*\" means all.", + "type": "string" + }, + "name": { + "description": "Name is the name of the resource being requested for a \"get\" or deleted for a \"delete\". \"\" (empty) means all.", + "type": "string" + }, + "namespace": { + "description": "Namespace is the namespace of the action being requested. Currently, there is no distinction between no namespace and all namespaces \"\" (empty) is defaulted for LocalSubjectAccessReviews \"\" (empty) is empty for cluster-scoped resources \"\" (empty) means \"all\" for namespace scoped resources from a SubjectAccessReview or SelfSubjectAccessReview", + "type": "string" + }, + "resource": { + "description": "Resource is one of the existing resource types. \"*\" means all.", + "type": "string" + }, + "subresource": { + "description": "Subresource is one of the existing resource types. \"\" means none.", + "type": "string" + }, + "verb": { + "description": "Verb is a kubernetes resource API verb, like: get, list, watch, create, update, delete, proxy. \"*\" means all.", + "type": "string" + }, + "version": { + "description": "Version is the API Version of the Resource. \"*\" means all.", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1.SelfSubjectAccessReview": { + "description": "SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a spec.namespace means \"in all namespaces\". Self is a special case, because users should always be able to check whether they can perform an action", + "type": "object", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated. user and groups must be empty", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "SelfSubjectAccessReview", + "version": "v1" + } + ] + }, + "io.k8s.api.authorization.v1.SelfSubjectAccessReviewSpec": { + "description": "SelfSubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set", + "type": "object", + "properties": { + "nonResourceAttributes": { + "description": "NonResourceAttributes describes information for a non-resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1.NonResourceAttributes" + }, + "resourceAttributes": { + "description": "ResourceAuthorizationAttributes describes information for a resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1.ResourceAttributes" + } + } + }, + "io.k8s.api.authorization.v1.SubjectAccessReview": { + "description": "SubjectAccessReview checks whether or not a user or group can perform an action.", + "type": "object", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "SubjectAccessReview", + "version": "v1" + } + ] + }, + "io.k8s.api.authorization.v1.SubjectAccessReviewSpec": { + "description": "SubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set", + "type": "object", + "properties": { + "extra": { + "description": "Extra corresponds to the user.Info.GetExtra() method from the authenticator. Since that is input to the authorizer it needs a reflection here.", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "groups": { + "description": "Groups is the groups you're testing for.", + "type": "array", + "items": { + "type": "string" + } + }, + "nonResourceAttributes": { + "description": "NonResourceAttributes describes information for a non-resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1.NonResourceAttributes" + }, + "resourceAttributes": { + "description": "ResourceAuthorizationAttributes describes information for a resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1.ResourceAttributes" + }, + "uid": { + "description": "UID information about the requesting user.", + "type": "string" + }, + "user": { + "description": "User is the user you're testing for. If you specify \"User\" but not \"Groups\", then is it interpreted as \"What if User were not a member of any groups", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1.SubjectAccessReviewStatus": { + "description": "SubjectAccessReviewStatus", + "type": "object", + "required": [ + "allowed" + ], + "properties": { + "allowed": { + "description": "Allowed is required. True if the action would be allowed, false otherwise.", + "type": "boolean" + }, + "evaluationError": { + "description": "EvaluationError is an indication that some error occurred during the authorization check. It is entirely possible to get an error and be able to continue determine authorization status in spite of it. For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request.", + "type": "string" + }, + "reason": { + "description": "Reason is optional. It indicates why a request was allowed or denied.", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1beta1.LocalSubjectAccessReview": { + "description": "LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions checking.", + "type": "object", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace you made the request against. If empty, it is defaulted.", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "LocalSubjectAccessReview", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.authorization.v1beta1.NonResourceAttributes": { + "description": "NonResourceAttributes includes the authorization attributes available for non-resource requests to the Authorizer interface", + "type": "object", + "properties": { + "path": { + "description": "Path is the URL path of the request", + "type": "string" + }, + "verb": { + "description": "Verb is the standard HTTP verb", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1beta1.ResourceAttributes": { + "description": "ResourceAttributes includes the authorization attributes available for resource requests to the Authorizer interface", + "type": "object", + "properties": { + "group": { + "description": "Group is the API Group of the Resource. \"*\" means all.", + "type": "string" + }, + "name": { + "description": "Name is the name of the resource being requested for a \"get\" or deleted for a \"delete\". \"\" (empty) means all.", + "type": "string" + }, + "namespace": { + "description": "Namespace is the namespace of the action being requested. Currently, there is no distinction between no namespace and all namespaces \"\" (empty) is defaulted for LocalSubjectAccessReviews \"\" (empty) is empty for cluster-scoped resources \"\" (empty) means \"all\" for namespace scoped resources from a SubjectAccessReview or SelfSubjectAccessReview", + "type": "string" + }, + "resource": { + "description": "Resource is one of the existing resource types. \"*\" means all.", + "type": "string" + }, + "subresource": { + "description": "Subresource is one of the existing resource types. \"\" means none.", + "type": "string" + }, + "verb": { + "description": "Verb is a kubernetes resource API verb, like: get, list, watch, create, update, delete, proxy. \"*\" means all.", + "type": "string" + }, + "version": { + "description": "Version is the API Version of the Resource. \"*\" means all.", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1beta1.SelfSubjectAccessReview": { + "description": "SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a spec.namespace means \"in all namespaces\". Self is a special case, because users should always be able to check whether they can perform an action", + "type": "object", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated. user and groups must be empty", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "SelfSubjectAccessReview", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.authorization.v1beta1.SelfSubjectAccessReviewSpec": { + "description": "SelfSubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set", + "type": "object", + "properties": { + "nonResourceAttributes": { + "description": "NonResourceAttributes describes information for a non-resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.NonResourceAttributes" + }, + "resourceAttributes": { + "description": "ResourceAuthorizationAttributes describes information for a resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.ResourceAttributes" + } + } + }, + "io.k8s.api.authorization.v1beta1.SubjectAccessReview": { + "description": "SubjectAccessReview checks whether or not a user or group can perform an action.", + "type": "object", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec holds information about the request being evaluated", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec" + }, + "status": { + "description": "Status is filled in by the server and indicates whether the request is allowed or not", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "authorization.k8s.io", + "kind": "SubjectAccessReview", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.authorization.v1beta1.SubjectAccessReviewSpec": { + "description": "SubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set", + "type": "object", + "properties": { + "extra": { + "description": "Extra corresponds to the user.Info.GetExtra() method from the authenticator. Since that is input to the authorizer it needs a reflection here.", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "group": { + "description": "Groups is the groups you're testing for.", + "type": "array", + "items": { + "type": "string" + } + }, + "nonResourceAttributes": { + "description": "NonResourceAttributes describes information for a non-resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.NonResourceAttributes" + }, + "resourceAttributes": { + "description": "ResourceAuthorizationAttributes describes information for a resource access request", + "$ref": "#/definitions/io.k8s.api.authorization.v1beta1.ResourceAttributes" + }, + "uid": { + "description": "UID information about the requesting user.", + "type": "string" + }, + "user": { + "description": "User is the user you're testing for. If you specify \"User\" but not \"Group\", then is it interpreted as \"What if User were not a member of any groups", + "type": "string" + } + } + }, + "io.k8s.api.authorization.v1beta1.SubjectAccessReviewStatus": { + "description": "SubjectAccessReviewStatus", + "type": "object", + "required": [ + "allowed" + ], + "properties": { + "allowed": { + "description": "Allowed is required. True if the action would be allowed, false otherwise.", + "type": "boolean" + }, + "evaluationError": { + "description": "EvaluationError is an indication that some error occurred during the authorization check. It is entirely possible to get an error and be able to continue determine authorization status in spite of it. For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request.", + "type": "string" + }, + "reason": { + "description": "Reason is optional. It indicates why a request was allowed or denied.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource": { + "description": "Represents a Persistent Disk resource in AWS.\n\nAn AWS EBS disk must exist before mounting to a container. The disk must also be in the same AWS zone as the kubelet. An AWS EBS disk can only be mounted as read/write once. AWS EBS volumes support ownership management and SELinux relabeling.", + "type": "object", + "required": [ + "volumeID" + ], + "properties": { + "fsType": { + "description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "type": "string" + }, + "partition": { + "description": "The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as \"1\". Similarly, the volume partition for /dev/sda is \"0\" (or you can leave the property empty).", + "type": "integer", + "format": "int32" + }, + "readOnly": { + "description": "Specify \"true\" to force and set the ReadOnly property in VolumeMounts to \"true\". If omitted, the default is \"false\". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "type": "boolean" + }, + "volumeID": { + "description": "Unique ID of the persistent disk resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Affinity": { + "description": "Affinity is a group of affinity scheduling rules.", + "type": "object", + "properties": { + "nodeAffinity": { + "description": "Describes node affinity scheduling rules for the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeAffinity" + }, + "podAffinity": { + "description": "Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)).", + "$ref": "#/definitions/io.k8s.api.core.v1.PodAffinity" + }, + "podAntiAffinity": { + "description": "Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)).", + "$ref": "#/definitions/io.k8s.api.core.v1.PodAntiAffinity" + } + } + }, + "io.k8s.api.core.v1.AttachedVolume": { + "description": "AttachedVolume describes a volume attached to a node", + "type": "object", + "required": [ + "name", + "devicePath" + ], + "properties": { + "devicePath": { + "description": "DevicePath represents the device path where the volume should be available", + "type": "string" + }, + "name": { + "description": "Name of the attached volume", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.AzureDiskVolumeSource": { + "description": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.", + "type": "object", + "required": [ + "diskName", + "diskURI" + ], + "properties": { + "cachingMode": { + "description": "Host Caching mode: None, Read Only, Read Write.", + "type": "string" + }, + "diskName": { + "description": "The Name of the data disk in the blob storage", + "type": "string" + }, + "diskURI": { + "description": "The URI the data disk in the blob storage", + "type": "string" + }, + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "kind": { + "description": "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", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.AzureFilePersistentVolumeSource": { + "description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.", + "type": "object", + "required": [ + "secretName", + "shareName" + ], + "properties": { + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretName": { + "description": "the name of secret that contains Azure Storage Account Name and Key", + "type": "string" + }, + "secretNamespace": { + "description": "the namespace of the secret that contains Azure Storage Account Name and Key default is the same as the Pod", + "type": "string" + }, + "shareName": { + "description": "Share Name", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.AzureFileVolumeSource": { + "description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.", + "type": "object", + "required": [ + "secretName", + "shareName" + ], + "properties": { + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretName": { + "description": "the name of secret that contains Azure Storage Account Name and Key", + "type": "string" + }, + "shareName": { + "description": "Share Name", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Binding": { + "description": "Binding ties one object to another; for example, a pod is bound to a node by a scheduler. Deprecated in 1.7, please use the bindings subresource of pods instead.", + "type": "object", + "required": [ + "target" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "target": { + "description": "The target object that you want to bind to the standard object.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Binding", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.Capabilities": { + "description": "Adds and removes POSIX capabilities from running containers.", + "type": "object", + "properties": { + "add": { + "description": "Added capabilities", + "type": "array", + "items": { + "type": "string" + } + }, + "drop": { + "description": "Removed capabilities", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.CephFSPersistentVolumeSource": { + "description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", + "type": "object", + "required": [ + "monitors" + ], + "properties": { + "monitors": { + "description": "Required: Monitors is a collection of Ceph monitors More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "array", + "items": { + "type": "string" + } + }, + "path": { + "description": "Optional: Used as the mounted root, rather than the full Ceph tree, default is /", + "type": "string" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "boolean" + }, + "secretFile": { + "description": "Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "string" + }, + "secretRef": { + "description": "Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretReference" + }, + "user": { + "description": "Optional: User is the rados user name, default is admin More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.CephFSVolumeSource": { + "description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", + "type": "object", + "required": [ + "monitors" + ], + "properties": { + "monitors": { + "description": "Required: Monitors is a collection of Ceph monitors More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "array", + "items": { + "type": "string" + } + }, + "path": { + "description": "Optional: Used as the mounted root, rather than the full Ceph tree, default is /", + "type": "string" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "boolean" + }, + "secretFile": { + "description": "Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "string" + }, + "secretRef": { + "description": "Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "user": { + "description": "Optional: User is the rados user name, default is admin More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.CinderVolumeSource": { + "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "type": "object", + "required": [ + "volumeID" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "string" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "boolean" + }, + "volumeID": { + "description": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ClientIPConfig": { + "description": "ClientIPConfig represents the configurations of Client IP based session affinity.", + "type": "object", + "properties": { + "timeoutSeconds": { + "description": "timeoutSeconds specifies the seconds of ClientIP type session sticky time. The value must be \u003e0 \u0026\u0026 \u003c=86400(for 1 day) if ServiceAffinity == \"ClientIP\". Default value is 10800(for 3 hours).", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.ComponentCondition": { + "description": "Information about the condition of a component.", + "type": "object", + "required": [ + "type", + "status" + ], + "properties": { + "error": { + "description": "Condition error code for a component. For example, a health check error code.", + "type": "string" + }, + "message": { + "description": "Message about the condition for a component. For example, information about a health check.", + "type": "string" + }, + "status": { + "description": "Status of the condition for a component. Valid values for \"Healthy\": \"True\", \"False\", or \"Unknown\".", + "type": "string" + }, + "type": { + "description": "Type of condition for a component. Valid value: \"Healthy\"", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ComponentStatus": { + "description": "ComponentStatus (and ComponentStatusList) holds the cluster validation info.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "conditions": { + "description": "List of component conditions observed", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ComponentCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ComponentStatus", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ComponentStatusList": { + "description": "Status of all the conditions for the component as a list of ComponentStatus objects.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of ComponentStatus objects.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ComponentStatus" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ComponentStatusList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ConfigMap": { + "description": "ConfigMap holds configuration data for pods to consume.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "data": { + "description": "Data contains the configuration data. Each key must consist of alphanumeric characters, '-', '_' or '.'.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ConfigMap", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ConfigMapEnvSource": { + "description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.", + "type": "object", + "properties": { + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.ConfigMapKeySelector": { + "description": "Selects a key from a ConfigMap.", + "type": "object", + "required": [ + "key" + ], + "properties": { + "key": { + "description": "The key to select.", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or it's key must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.ConfigMapList": { + "description": "ConfigMapList is a resource containing a list of ConfigMap objects.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is the list of ConfigMaps.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMap" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ConfigMapList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ConfigMapProjection": { + "description": "Adapts a ConfigMap into a projected volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a projected volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. Note that this is identical to a configmap volume source without the default mode.", + "type": "object", + "properties": { + "items": { + "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.KeyToPath" + } + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or it's keys must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.ConfigMapVolumeSource": { + "description": "Adapts a ConfigMap into a volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. ConfigMap volumes support ownership management and SELinux relabeling.", + "type": "object", + "properties": { + "defaultMode": { + "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "items": { + "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.KeyToPath" + } + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or it's keys must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.Container": { + "description": "A single application container that you want to run within a pod.", + "type": "object", + "required": [ + "name", + "image" + ], + "properties": { + "args": { + "description": "Arguments to the entrypoint. The docker image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell", + "type": "array", + "items": { + "type": "string" + } + }, + "command": { + "description": "Entrypoint array. Not executed within a shell. The docker image's ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell", + "type": "array", + "items": { + "type": "string" + } + }, + "env": { + "description": "List of environment variables to set in the container. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EnvVar" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "envFrom": { + "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EnvFromSource" + } + }, + "image": { + "description": "Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images", + "type": "string" + }, + "imagePullPolicy": { + "description": "Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images", + "type": "string" + }, + "lifecycle": { + "description": "Actions that the management system should take in response to container lifecycle events. Cannot be updated.", + "$ref": "#/definitions/io.k8s.api.core.v1.Lifecycle" + }, + "livenessProbe": { + "description": "Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", + "$ref": "#/definitions/io.k8s.api.core.v1.Probe" + }, + "name": { + "description": "Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated.", + "type": "string" + }, + "ports": { + "description": "List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerPort" + }, + "x-kubernetes-patch-merge-key": "containerPort", + "x-kubernetes-patch-strategy": "merge" + }, + "readinessProbe": { + "description": "Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", + "$ref": "#/definitions/io.k8s.api.core.v1.Probe" + }, + "resources": { + "description": "Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" + }, + "securityContext": { + "description": "Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://git.k8s.io/community/contributors/design-proposals/security_context.md", + "$ref": "#/definitions/io.k8s.api.core.v1.SecurityContext" + }, + "stdin": { + "description": "Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false.", + "type": "boolean" + }, + "stdinOnce": { + "description": "Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false", + "type": "boolean" + }, + "terminationMessagePath": { + "description": "Optional: Path at which the file to which the container's termination message will be written is mounted into the container's filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.", + "type": "string" + }, + "terminationMessagePolicy": { + "description": "Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated.", + "type": "string" + }, + "tty": { + "description": "Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false.", + "type": "boolean" + }, + "volumeMounts": { + "description": "Pod volumes to mount into the container's filesystem. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.VolumeMount" + }, + "x-kubernetes-patch-merge-key": "mountPath", + "x-kubernetes-patch-strategy": "merge" + }, + "workingDir": { + "description": "Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ContainerImage": { + "description": "Describe a container image", + "type": "object", + "required": [ + "names" + ], + "properties": { + "names": { + "description": "Names by which this image is known. e.g. [\"gcr.io/google_containers/hyperkube:v1.0.7\", \"dockerhub.io/google_containers/hyperkube:v1.0.7\"]", + "type": "array", + "items": { + "type": "string" + } + }, + "sizeBytes": { + "description": "The size of the image in bytes.", + "type": "integer", + "format": "int64" + } + } + }, + "io.k8s.api.core.v1.ContainerPort": { + "description": "ContainerPort represents a network port in a single container.", + "type": "object", + "required": [ + "containerPort" + ], + "properties": { + "containerPort": { + "description": "Number of port to expose on the pod's IP address. This must be a valid port number, 0 \u003c x \u003c 65536.", + "type": "integer", + "format": "int32" + }, + "hostIP": { + "description": "What host IP to bind the external port to.", + "type": "string" + }, + "hostPort": { + "description": "Number of port to expose on the host. If specified, this must be a valid port number, 0 \u003c x \u003c 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this.", + "type": "integer", + "format": "int32" + }, + "name": { + "description": "If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services.", + "type": "string" + }, + "protocol": { + "description": "Protocol for port. Must be UDP or TCP. Defaults to \"TCP\".", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ContainerState": { + "description": "ContainerState holds a possible state of container. Only one of its members may be specified. If none of them is specified, the default one is ContainerStateWaiting.", + "type": "object", + "properties": { + "running": { + "description": "Details about a running container", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStateRunning" + }, + "terminated": { + "description": "Details about a terminated container", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStateTerminated" + }, + "waiting": { + "description": "Details about a waiting container", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStateWaiting" + } + } + }, + "io.k8s.api.core.v1.ContainerStateRunning": { + "description": "ContainerStateRunning is a running state of a container.", + "type": "object", + "properties": { + "startedAt": { + "description": "Time at which the container was last (re-)started", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + } + }, + "io.k8s.api.core.v1.ContainerStateTerminated": { + "description": "ContainerStateTerminated is a terminated state of a container.", + "type": "object", + "required": [ + "exitCode" + ], + "properties": { + "containerID": { + "description": "Container's ID in the format 'docker://\u003ccontainer_id\u003e'", + "type": "string" + }, + "exitCode": { + "description": "Exit status from the last termination of the container", + "type": "integer", + "format": "int32" + }, + "finishedAt": { + "description": "Time at which the container last terminated", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "Message regarding the last termination of the container", + "type": "string" + }, + "reason": { + "description": "(brief) reason from the last termination of the container", + "type": "string" + }, + "signal": { + "description": "Signal from the last termination of the container", + "type": "integer", + "format": "int32" + }, + "startedAt": { + "description": "Time at which previous execution of the container started", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + } + }, + "io.k8s.api.core.v1.ContainerStateWaiting": { + "description": "ContainerStateWaiting is a waiting state of a container.", + "type": "object", + "properties": { + "message": { + "description": "Message regarding why the container is not yet running.", + "type": "string" + }, + "reason": { + "description": "(brief) reason the container is not yet running.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ContainerStatus": { + "description": "ContainerStatus contains details for the current status of this container.", + "type": "object", + "required": [ + "name", + "ready", + "restartCount", + "image", + "imageID" + ], + "properties": { + "containerID": { + "description": "Container's ID in the format 'docker://\u003ccontainer_id\u003e'.", + "type": "string" + }, + "image": { + "description": "The image the container is running. More info: https://kubernetes.io/docs/concepts/containers/images", + "type": "string" + }, + "imageID": { + "description": "ImageID of the container's image.", + "type": "string" + }, + "lastState": { + "description": "Details about the container's last termination condition.", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerState" + }, + "name": { + "description": "This must be a DNS_LABEL. Each container in a pod must have a unique name. Cannot be updated.", + "type": "string" + }, + "ready": { + "description": "Specifies whether the container has passed its readiness probe.", + "type": "boolean" + }, + "restartCount": { + "description": "The number of times the container has been restarted, currently based on the number of dead containers that have not yet been removed. Note that this is calculated from dead containers. But those containers are subject to garbage collection. This value will get capped at 5 by GC.", + "type": "integer", + "format": "int32" + }, + "state": { + "description": "Details about the container's current condition.", + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerState" + } + } + }, + "io.k8s.api.core.v1.DaemonEndpoint": { + "description": "DaemonEndpoint contains information about a single Daemon endpoint.", + "type": "object", + "required": [ + "Port" + ], + "properties": { + "Port": { + "description": "Port number of the given endpoint.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.DownwardAPIProjection": { + "description": "Represents downward API info for projecting into a projected volume. Note that this is identical to a downwardAPI volume source without the default mode.", + "type": "object", + "properties": { + "items": { + "description": "Items is a list of DownwardAPIVolume file", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.DownwardAPIVolumeFile" + } + } + } + }, + "io.k8s.api.core.v1.DownwardAPIVolumeFile": { + "description": "DownwardAPIVolumeFile represents information to create the file containing the pod field", + "type": "object", + "required": [ + "path" + ], + "properties": { + "fieldRef": { + "description": "Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectFieldSelector" + }, + "mode": { + "description": "Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "path": { + "description": "Required: Path is the relative path name of the file to be created. Must not be absolute or contain the '..' path. Must be utf-8 encoded. The first item of the relative path must not start with '..'", + "type": "string" + }, + "resourceFieldRef": { + "description": "Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceFieldSelector" + } + } + }, + "io.k8s.api.core.v1.DownwardAPIVolumeSource": { + "description": "DownwardAPIVolumeSource represents a volume containing downward API info. Downward API volumes support ownership management and SELinux relabeling.", + "type": "object", + "properties": { + "defaultMode": { + "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "items": { + "description": "Items is a list of downward API volume file", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.DownwardAPIVolumeFile" + } + } + } + }, + "io.k8s.api.core.v1.EmptyDirVolumeSource": { + "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", + "type": "object", + "properties": { + "medium": { + "description": "What type of storage medium should back this directory. The default is \"\" which means to use the node's default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir", + "type": "string" + }, + "sizeLimit": { + "description": "Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + } + }, + "io.k8s.api.core.v1.EndpointAddress": { + "description": "EndpointAddress is a tuple that describes single IP address.", + "type": "object", + "required": [ + "ip" + ], + "properties": { + "hostname": { + "description": "The Hostname of this endpoint", + "type": "string" + }, + "ip": { + "description": "The IP of this endpoint. May not be loopback (127.0.0.0/8), link-local (169.254.0.0/16), or link-local multicast ((224.0.0.0/24). IPv6 is also accepted but not fully supported on all platforms. Also, certain kubernetes components, like kube-proxy, are not IPv6 ready.", + "type": "string" + }, + "nodeName": { + "description": "Optional: Node hosting this endpoint. This can be used to determine endpoints local to a node.", + "type": "string" + }, + "targetRef": { + "description": "Reference to object providing the endpoint.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + } + } + }, + "io.k8s.api.core.v1.EndpointPort": { + "description": "EndpointPort is a tuple that describes a single port.", + "type": "object", + "required": [ + "port" + ], + "properties": { + "name": { + "description": "The name of this port (corresponds to ServicePort.Name). Must be a DNS_LABEL. Optional only if one port is defined.", + "type": "string" + }, + "port": { + "description": "The port number of the endpoint.", + "type": "integer", + "format": "int32" + }, + "protocol": { + "description": "The IP protocol for this port. Must be UDP or TCP. Default is TCP.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.EndpointSubset": { + "description": "EndpointSubset is a group of addresses with a common set of ports. The expanded set of endpoints is the Cartesian product of Addresses x Ports. For example, given:\n {\n Addresses: [{\"ip\": \"10.10.1.1\"}, {\"ip\": \"10.10.2.2\"}],\n Ports: [{\"name\": \"a\", \"port\": 8675}, {\"name\": \"b\", \"port\": 309}]\n }\nThe resulting set of endpoints can be viewed as:\n a: [ 10.10.1.1:8675, 10.10.2.2:8675 ],\n b: [ 10.10.1.1:309, 10.10.2.2:309 ]", + "type": "object", + "properties": { + "addresses": { + "description": "IP addresses which offer the related ports that are marked as ready. These endpoints should be considered safe for load balancers and clients to utilize.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EndpointAddress" + } + }, + "notReadyAddresses": { + "description": "IP addresses which offer the related ports but are not currently marked as ready because they have not yet finished starting, have recently failed a readiness check, or have recently failed a liveness check.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EndpointAddress" + } + }, + "ports": { + "description": "Port numbers available on the related IP addresses.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EndpointPort" + } + } + } + }, + "io.k8s.api.core.v1.Endpoints": { + "description": "Endpoints is a collection of endpoints that implement the actual service. Example:\n Name: \"mysvc\",\n Subsets: [\n {\n Addresses: [{\"ip\": \"10.10.1.1\"}, {\"ip\": \"10.10.2.2\"}],\n Ports: [{\"name\": \"a\", \"port\": 8675}, {\"name\": \"b\", \"port\": 309}]\n },\n {\n Addresses: [{\"ip\": \"10.10.3.3\"}],\n Ports: [{\"name\": \"a\", \"port\": 93}, {\"name\": \"b\", \"port\": 76}]\n },\n ]", + "type": "object", + "required": [ + "subsets" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "subsets": { + "description": "The set of all endpoints is the union of all subsets. Addresses are placed into subsets according to the IPs they share. A single address with multiple ports, some of which are ready and some of which are not (because they come from different containers) will result in the address being displayed in different subsets for the different ports. No address will appear in both Addresses and NotReadyAddresses in the same subset. Sets of addresses and ports that comprise a service.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.EndpointSubset" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Endpoints", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.EndpointsList": { + "description": "EndpointsList is a list of endpoints.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of endpoints.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Endpoints" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "EndpointsList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.EnvFromSource": { + "description": "EnvFromSource represents the source of a set of ConfigMaps", + "type": "object", + "properties": { + "configMapRef": { + "description": "The ConfigMap to select from", + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapEnvSource" + }, + "prefix": { + "description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.", + "type": "string" + }, + "secretRef": { + "description": "The Secret to select from", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretEnvSource" + } + } + }, + "io.k8s.api.core.v1.EnvVar": { + "description": "EnvVar represents an environment variable present in a Container.", + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "Name of the environment variable. Must be a C_IDENTIFIER.", + "type": "string" + }, + "value": { + "description": "Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to \"\".", + "type": "string" + }, + "valueFrom": { + "description": "Source for the environment variable's value. Cannot be used if value is not empty.", + "$ref": "#/definitions/io.k8s.api.core.v1.EnvVarSource" + } + } + }, + "io.k8s.api.core.v1.EnvVarSource": { + "description": "EnvVarSource represents a source for the value of an EnvVar.", + "type": "object", + "properties": { + "configMapKeyRef": { + "description": "Selects a key of a ConfigMap.", + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapKeySelector" + }, + "fieldRef": { + "description": "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectFieldSelector" + }, + "resourceFieldRef": { + "description": "Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceFieldSelector" + }, + "secretKeyRef": { + "description": "Selects a key of a secret in the pod's namespace", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretKeySelector" + } + } + }, + "io.k8s.api.core.v1.Event": { + "description": "Event is a report of an event somewhere in the cluster.", + "type": "object", + "required": [ + "metadata", + "involvedObject" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "count": { + "description": "The number of times this event has occurred.", + "type": "integer", + "format": "int32" + }, + "firstTimestamp": { + "description": "The time at which the event was first recorded. (Time of server receipt is in TypeMeta.)", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "involvedObject": { + "description": "The object that this event is about.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "lastTimestamp": { + "description": "The time at which the most recent occurrence of this event was recorded.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "A human-readable description of the status of this operation.", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "reason": { + "description": "This should be a short, machine understandable string that gives the reason for the transition into the object's current status.", + "type": "string" + }, + "source": { + "description": "The component reporting this event. Should be a short machine understandable string.", + "$ref": "#/definitions/io.k8s.api.core.v1.EventSource" + }, + "type": { + "description": "Type of this event (Normal, Warning), new types could be added in the future", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Event", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.EventList": { + "description": "EventList is a list of events.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of events", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Event" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "EventList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.EventSource": { + "description": "EventSource contains information for an event.", + "type": "object", + "properties": { + "component": { + "description": "Component from which the event is generated.", + "type": "string" + }, + "host": { + "description": "Node name on which the event is generated.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ExecAction": { + "description": "ExecAction describes a \"run in container\" action.", + "type": "object", + "properties": { + "command": { + "description": "Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.FCVolumeSource": { + "description": "Represents a Fibre Channel volume. Fibre Channel volumes can only be mounted as read/write once. Fibre Channel volumes support ownership management and SELinux relabeling.", + "type": "object", + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "lun": { + "description": "Optional: FC target lun number", + "type": "integer", + "format": "int32" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "targetWWNs": { + "description": "Optional: FC target worldwide names (WWNs)", + "type": "array", + "items": { + "type": "string" + } + }, + "wwids": { + "description": "Optional: FC volume world wide identifiers (wwids) Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.FlexVolumeSource": { + "description": "FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. This is an alpha feature and may change in future.", + "type": "object", + "required": [ + "driver" + ], + "properties": { + "driver": { + "description": "Driver is the name of the driver to use for this volume.", + "type": "string" + }, + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". The default filesystem depends on FlexVolume script.", + "type": "string" + }, + "options": { + "description": "Optional: Extra command options if any.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretRef": { + "description": "Optional: SecretRef is reference to the secret object containing sensitive information to pass to the plugin scripts. This may be empty if no secret object is specified. If the secret object contains more than one secret, all secrets are passed to the plugin scripts.", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + } + } + }, + "io.k8s.api.core.v1.FlockerVolumeSource": { + "description": "Represents a Flocker volume mounted by the Flocker agent. One and only one of datasetName and datasetUUID should be set. Flocker volumes do not support ownership management or SELinux relabeling.", + "type": "object", + "properties": { + "datasetName": { + "description": "Name of the dataset stored as metadata -\u003e name on the dataset for Flocker should be considered as deprecated", + "type": "string" + }, + "datasetUUID": { + "description": "UUID of the dataset. This is unique identifier of a Flocker dataset", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.GCEPersistentDiskVolumeSource": { + "description": "Represents a Persistent Disk resource in Google Compute Engine.\n\nA GCE PD must exist before mounting to a container. The disk must also be in the same GCE project and zone as the kubelet. A GCE PD can only be mounted as read/write once or read-only many times. GCE PDs support ownership management and SELinux relabeling.", + "type": "object", + "required": [ + "pdName" + ], + "properties": { + "fsType": { + "description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "type": "string" + }, + "partition": { + "description": "The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as \"1\". Similarly, the volume partition for /dev/sda is \"0\" (or you can leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "type": "integer", + "format": "int32" + }, + "pdName": { + "description": "Unique name of the PD resource in GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.GitRepoVolumeSource": { + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "type": "object", + "required": [ + "repository" + ], + "properties": { + "directory": { + "description": "Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name.", + "type": "string" + }, + "repository": { + "description": "Repository URL", + "type": "string" + }, + "revision": { + "description": "Commit hash for the specified revision.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.GlusterfsVolumeSource": { + "description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.", + "type": "object", + "required": [ + "endpoints", + "path" + ], + "properties": { + "endpoints": { + "description": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", + "type": "string" + }, + "path": { + "description": "Path is the Glusterfs volume path. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.HTTPGetAction": { + "description": "HTTPGetAction describes an action based on HTTP Get requests.", + "type": "object", + "required": [ + "port" + ], + "properties": { + "host": { + "description": "Host name to connect to, defaults to the pod IP. You probably want to set \"Host\" in httpHeaders instead.", + "type": "string" + }, + "httpHeaders": { + "description": "Custom headers to set in the request. HTTP allows repeated headers.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.HTTPHeader" + } + }, + "path": { + "description": "Path to access on the HTTP server.", + "type": "string" + }, + "port": { + "description": "Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + }, + "scheme": { + "description": "Scheme to use for connecting to the host. Defaults to HTTP.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.HTTPHeader": { + "description": "HTTPHeader describes a custom header to be used in HTTP probes", + "type": "object", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "description": "The header field name", + "type": "string" + }, + "value": { + "description": "The header field value", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Handler": { + "description": "Handler defines a specific action that should be taken", + "type": "object", + "properties": { + "exec": { + "description": "One and only one of the following should be specified. Exec specifies the action to take.", + "$ref": "#/definitions/io.k8s.api.core.v1.ExecAction" + }, + "httpGet": { + "description": "HTTPGet specifies the http request to perform.", + "$ref": "#/definitions/io.k8s.api.core.v1.HTTPGetAction" + }, + "tcpSocket": { + "description": "TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported", + "$ref": "#/definitions/io.k8s.api.core.v1.TCPSocketAction" + } + } + }, + "io.k8s.api.core.v1.HostAlias": { + "description": "HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file.", + "type": "object", + "properties": { + "hostnames": { + "description": "Hostnames for the above IP address.", + "type": "array", + "items": { + "type": "string" + } + }, + "ip": { + "description": "IP address of the host file entry.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.HostPathVolumeSource": { + "description": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.", + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", + "type": "string" + }, + "type": { + "description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ISCSIVolumeSource": { + "description": "Represents an ISCSI disk. ISCSI volumes can only be mounted as read/write once. ISCSI volumes support ownership management and SELinux relabeling.", + "type": "object", + "required": [ + "targetPortal", + "iqn", + "lun" + ], + "properties": { + "chapAuthDiscovery": { + "description": "whether support iSCSI Discovery CHAP authentication", + "type": "boolean" + }, + "chapAuthSession": { + "description": "whether support iSCSI Session CHAP authentication", + "type": "boolean" + }, + "fsType": { + "description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi", + "type": "string" + }, + "initiatorName": { + "description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection.", + "type": "string" + }, + "iqn": { + "description": "Target iSCSI Qualified Name.", + "type": "string" + }, + "iscsiInterface": { + "description": "Optional: Defaults to 'default' (tcp). iSCSI interface name that uses an iSCSI transport.", + "type": "string" + }, + "lun": { + "description": "iSCSI target lun number.", + "type": "integer", + "format": "int32" + }, + "portals": { + "description": "iSCSI target portal List. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260).", + "type": "array", + "items": { + "type": "string" + } + }, + "readOnly": { + "description": "ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false.", + "type": "boolean" + }, + "secretRef": { + "description": "CHAP secret for iSCSI target and initiator authentication", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "targetPortal": { + "description": "iSCSI target portal. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260).", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.KeyToPath": { + "description": "Maps a string key to a path within a volume.", + "type": "object", + "required": [ + "key", + "path" + ], + "properties": { + "key": { + "description": "The key to project.", + "type": "string" + }, + "mode": { + "description": "Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "path": { + "description": "The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Lifecycle": { + "description": "Lifecycle describes actions that the management system should take in response to container lifecycle events. For the PostStart and PreStop lifecycle handlers, management of the container blocks until the action is complete, unless the container process fails, in which case the handler is aborted.", + "type": "object", + "properties": { + "postStart": { + "description": "PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks", + "$ref": "#/definitions/io.k8s.api.core.v1.Handler" + }, + "preStop": { + "description": "PreStop is called immediately before a container is terminated. The container is terminated after the handler completes. The reason for termination is passed to the handler. Regardless of the outcome of the handler, the container is eventually terminated. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks", + "$ref": "#/definitions/io.k8s.api.core.v1.Handler" + } + } + }, + "io.k8s.api.core.v1.LimitRange": { + "description": "LimitRange sets resource usage limits for each kind of resource in a Namespace.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the limits enforced. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.LimitRangeSpec" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "LimitRange", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.LimitRangeItem": { + "description": "LimitRangeItem defines a min/max usage limit for any resource that matches on kind.", + "type": "object", + "properties": { + "default": { + "description": "Default resource requirement limit value by resource name if resource limit is omitted.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "defaultRequest": { + "description": "DefaultRequest is the default resource requirement request value by resource name if resource request is omitted.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "max": { + "description": "Max usage constraints on this kind by resource name.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "maxLimitRequestRatio": { + "description": "MaxLimitRequestRatio if specified, the named resource must have a request and limit that are both non-zero where limit divided by request is less than or equal to the enumerated value; this represents the max burst for the named resource.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "min": { + "description": "Min usage constraints on this kind by resource name.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "type": { + "description": "Type of resource that this limit applies to.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.LimitRangeList": { + "description": "LimitRangeList is a list of LimitRange items.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is a list of LimitRange objects. More info: https://git.k8s.io/community/contributors/design-proposals/admission_control_limit_range.md", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LimitRange" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "LimitRangeList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.LimitRangeSpec": { + "description": "LimitRangeSpec defines a min/max usage limit for resources that match on kind.", + "type": "object", + "required": [ + "limits" + ], + "properties": { + "limits": { + "description": "Limits is the list of LimitRangeItem objects that are enforced.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LimitRangeItem" + } + } + } + }, + "io.k8s.api.core.v1.LoadBalancerIngress": { + "description": "LoadBalancerIngress represents the status of a load-balancer ingress point: traffic intended for the service should be sent to an ingress point.", + "type": "object", + "properties": { + "hostname": { + "description": "Hostname is set for load-balancer ingress points that are DNS based (typically AWS load-balancers)", + "type": "string" + }, + "ip": { + "description": "IP is set for load-balancer ingress points that are IP based (typically GCE or OpenStack load-balancers)", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.LoadBalancerStatus": { + "description": "LoadBalancerStatus represents the status of a load-balancer.", + "type": "object", + "properties": { + "ingress": { + "description": "Ingress is a list containing ingress points for the load-balancer. Traffic intended for the service should be sent to these ingress points.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LoadBalancerIngress" + } + } + } + }, + "io.k8s.api.core.v1.LocalObjectReference": { + "description": "LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace.", + "type": "object", + "properties": { + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.LocalVolumeSource": { + "description": "Local represents directly-attached storage with node affinity", + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "description": "The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.NFSVolumeSource": { + "description": "Represents an NFS mount that lasts the lifetime of a pod. NFS volumes do not support ownership management or SELinux relabeling.", + "type": "object", + "required": [ + "server", + "path" + ], + "properties": { + "path": { + "description": "Path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "type": "boolean" + }, + "server": { + "description": "Server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Namespace": { + "description": "Namespace provides a scope for Names. Use of multiple namespaces is optional.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the behavior of the Namespace. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.NamespaceSpec" + }, + "status": { + "description": "Status describes the current status of a Namespace. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.NamespaceStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Namespace", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NamespaceList": { + "description": "NamespaceList is a list of Namespaces.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is the list of Namespace objects in the list. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Namespace" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "NamespaceList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NamespaceSpec": { + "description": "NamespaceSpec describes the attributes on a Namespace.", + "type": "object", + "properties": { + "finalizers": { + "description": "Finalizers is an opaque list of values that must be empty to permanently remove object from storage. More info: https://git.k8s.io/community/contributors/design-proposals/namespaces.md#finalizers", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.NamespaceStatus": { + "description": "NamespaceStatus is information about the current status of a Namespace.", + "type": "object", + "properties": { + "phase": { + "description": "Phase is the current lifecycle phase of the namespace. More info: https://git.k8s.io/community/contributors/design-proposals/namespaces.md#phases", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Node": { + "description": "Node is a worker node in Kubernetes. Each node will have a unique identifier in the cache (i.e. in etcd).", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the behavior of a node. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSpec" + }, + "status": { + "description": "Most recently observed status of the node. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Node", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NodeAddress": { + "description": "NodeAddress contains information for the node's address.", + "type": "object", + "required": [ + "type", + "address" + ], + "properties": { + "address": { + "description": "The node address.", + "type": "string" + }, + "type": { + "description": "Node address type, one of Hostname, ExternalIP or InternalIP.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.NodeAffinity": { + "description": "Node affinity is a group of node affinity scheduling rules.", + "type": "object", + "properties": { + "preferredDuringSchedulingIgnoredDuringExecution": { + "description": "The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding \"weight\" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PreferredSchedulingTerm" + } + }, + "requiredDuringSchedulingIgnoredDuringExecution": { + "description": "If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelector" + } + } + }, + "io.k8s.api.core.v1.NodeCondition": { + "description": "NodeCondition contains condition information for a node.", + "type": "object", + "required": [ + "type", + "status" + ], + "properties": { + "lastHeartbeatTime": { + "description": "Last time we got an update on a given condition.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "lastTransitionTime": { + "description": "Last time the condition transit from one status to another.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "Human readable message indicating details about last transition.", + "type": "string" + }, + "reason": { + "description": "(brief) reason for the condition's last transition.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of node condition.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.NodeConfigSource": { + "description": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "configMapRef": { + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "NodeConfigSource", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NodeDaemonEndpoints": { + "description": "NodeDaemonEndpoints lists ports opened by daemons running on the Node.", + "type": "object", + "properties": { + "kubeletEndpoint": { + "description": "Endpoint on which Kubelet is listening.", + "$ref": "#/definitions/io.k8s.api.core.v1.DaemonEndpoint" + } + } + }, + "io.k8s.api.core.v1.NodeList": { + "description": "NodeList is the whole list of all Nodes which have been registered with master.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of nodes", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Node" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "NodeList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.NodeSelector": { + "description": "A node selector represents the union of the results of one or more label queries over a set of nodes; that is, it represents the OR of the selectors represented by the node selector terms.", + "type": "object", + "required": [ + "nodeSelectorTerms" + ], + "properties": { + "nodeSelectorTerms": { + "description": "Required. A list of node selector terms. The terms are ORed.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelectorTerm" + } + } + } + }, + "io.k8s.api.core.v1.NodeSelectorRequirement": { + "description": "A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values.", + "type": "object", + "required": [ + "key", + "operator" + ], + "properties": { + "key": { + "description": "The label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.", + "type": "string" + }, + "values": { + "description": "An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.NodeSelectorTerm": { + "description": "A null or empty node selector term matches no objects.", + "type": "object", + "required": [ + "matchExpressions" + ], + "properties": { + "matchExpressions": { + "description": "Required. A list of node selector requirements. The requirements are ANDed.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelectorRequirement" + } + } + } + }, + "io.k8s.api.core.v1.NodeSpec": { + "description": "NodeSpec describes the attributes that a node is created with.", + "type": "object", + "properties": { + "configSource": { + "description": "If specified, the source to get node configuration from The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource" + }, + "externalID": { + "description": "External ID of the node assigned by some machine database (e.g. a cloud provider). Deprecated.", + "type": "string" + }, + "podCIDR": { + "description": "PodCIDR represents the pod IP range assigned to the node.", + "type": "string" + }, + "providerID": { + "description": "ID of the node assigned by the cloud provider in the format: \u003cProviderName\u003e://\u003cProviderSpecificNodeID\u003e", + "type": "string" + }, + "taints": { + "description": "If specified, the node's taints.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Taint" + } + }, + "unschedulable": { + "description": "Unschedulable controls node schedulability of new pods. By default, node is schedulable. More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.NodeStatus": { + "description": "NodeStatus is information about the current status of a node.", + "type": "object", + "properties": { + "addresses": { + "description": "List of addresses reachable to the node. Queried from cloud provider, if available. More info: https://kubernetes.io/docs/concepts/nodes/node/#addresses", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeAddress" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "allocatable": { + "description": "Allocatable represents the resources of a node that are available for scheduling. Defaults to Capacity.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "capacity": { + "description": "Capacity represents the total resources of a node. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "conditions": { + "description": "Conditions is an array of current observed node conditions. More info: https://kubernetes.io/docs/concepts/nodes/node/#condition", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "daemonEndpoints": { + "description": "Endpoints of daemons running on the Node.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeDaemonEndpoints" + }, + "images": { + "description": "List of container images on this node", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerImage" + } + }, + "nodeInfo": { + "description": "Set of ids/uuids to uniquely identify the node. More info: https://kubernetes.io/docs/concepts/nodes/node/#info", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSystemInfo" + }, + "phase": { + "description": "NodePhase is the recently observed lifecycle phase of the node. More info: https://kubernetes.io/docs/concepts/nodes/node/#phase The field is never populated, and now is deprecated.", + "type": "string" + }, + "volumesAttached": { + "description": "List of volumes that are attached to the node.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.AttachedVolume" + } + }, + "volumesInUse": { + "description": "List of attachable volumes in use (mounted) by the node.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.NodeSystemInfo": { + "description": "NodeSystemInfo is a set of ids/uuids to uniquely identify the node.", + "type": "object", + "required": [ + "machineID", + "systemUUID", + "bootID", + "kernelVersion", + "osImage", + "containerRuntimeVersion", + "kubeletVersion", + "kubeProxyVersion", + "operatingSystem", + "architecture" + ], + "properties": { + "architecture": { + "description": "The Architecture reported by the node", + "type": "string" + }, + "bootID": { + "description": "Boot ID reported by the node.", + "type": "string" + }, + "containerRuntimeVersion": { + "description": "ContainerRuntime Version reported by the node through runtime remote API (e.g. docker://1.5.0).", + "type": "string" + }, + "kernelVersion": { + "description": "Kernel Version reported by the node from 'uname -r' (e.g. 3.16.0-0.bpo.4-amd64).", + "type": "string" + }, + "kubeProxyVersion": { + "description": "KubeProxy Version reported by the node.", + "type": "string" + }, + "kubeletVersion": { + "description": "Kubelet Version reported by the node.", + "type": "string" + }, + "machineID": { + "description": "MachineID reported by the node. For unique machine identification in the cluster this field is preferred. Learn more from man(5) machine-id: http://man7.org/linux/man-pages/man5/machine-id.5.html", + "type": "string" + }, + "operatingSystem": { + "description": "The Operating System reported by the node", + "type": "string" + }, + "osImage": { + "description": "OS Image reported by the node from /etc/os-release (e.g. Debian GNU/Linux 7 (wheezy)).", + "type": "string" + }, + "systemUUID": { + "description": "SystemUUID reported by the node. For unique machine identification MachineID is preferred. This field is specific to Red Hat hosts https://access.redhat.com/documentation/en-US/Red_Hat_Subscription_Management/1/html/RHSM/getting-system-uuid.html", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ObjectFieldSelector": { + "description": "ObjectFieldSelector selects an APIVersioned field of an object.", + "type": "object", + "required": [ + "fieldPath" + ], + "properties": { + "apiVersion": { + "description": "Version of the schema the FieldPath is written in terms of, defaults to \"v1\".", + "type": "string" + }, + "fieldPath": { + "description": "Path of the field to select in the specified API version.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ObjectReference": { + "description": "ObjectReference contains enough information to let you inspect or modify the referred object.", + "type": "object", + "properties": { + "apiVersion": { + "description": "API version of the referent.", + "type": "string" + }, + "fieldPath": { + "description": "If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: \"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered the event) or if no container name is specified \"spec.containers[2]\" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object.", + "type": "string" + }, + "kind": { + "description": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "namespace": { + "description": "Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", + "type": "string" + }, + "resourceVersion": { + "description": "Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency", + "type": "string" + }, + "uid": { + "description": "UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PersistentVolume": { + "description": "PersistentVolume (PV) is a storage resource provisioned by an administrator. It is analogous to a node. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines a specification of a persistent volume owned by the cluster. Provisioned by an administrator. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeSpec" + }, + "status": { + "description": "Status represents the current information/status for the persistent volume. Populated by the system. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PersistentVolume", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PersistentVolumeClaim": { + "description": "PersistentVolumeClaim is a user's request for and claim to a persistent volume", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaimSpec" + }, + "status": { + "description": "Status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaimStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PersistentVolumeClaim", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PersistentVolumeClaimList": { + "description": "PersistentVolumeClaimList is a list of PersistentVolumeClaim items.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "A list of persistent volume claims. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaim" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PersistentVolumeClaimList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PersistentVolumeClaimSpec": { + "description": "PersistentVolumeClaimSpec describes the common attributes of storage devices and allows a Source for provider-specific attributes", + "type": "object", + "properties": { + "accessModes": { + "description": "AccessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1", + "type": "array", + "items": { + "type": "string" + } + }, + "resources": { + "description": "Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" + }, + "selector": { + "description": "A label query over volumes to consider for binding.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, + "storageClassName": { + "description": "Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1", + "type": "string" + }, + "volumeName": { + "description": "VolumeName is the binding reference to the PersistentVolume backing this claim.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PersistentVolumeClaimStatus": { + "description": "PersistentVolumeClaimStatus is the current status of a persistent volume claim.", + "type": "object", + "properties": { + "accessModes": { + "description": "AccessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1", + "type": "array", + "items": { + "type": "string" + } + }, + "capacity": { + "description": "Represents the actual resources of the underlying volume.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "phase": { + "description": "Phase represents the current phase of PersistentVolumeClaim.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource": { + "description": "PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace. This volume finds the bound PV and mounts that volume for the pod. A PersistentVolumeClaimVolumeSource is, essentially, a wrapper around another type of volume that is owned by someone else (the system).", + "type": "object", + "required": [ + "claimName" + ], + "properties": { + "claimName": { + "description": "ClaimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "type": "string" + }, + "readOnly": { + "description": "Will force the ReadOnly setting in VolumeMounts. Default false.", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.PersistentVolumeList": { + "description": "PersistentVolumeList is a list of PersistentVolume items.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of persistent volumes. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolume" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PersistentVolumeList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PersistentVolumeSpec": { + "description": "PersistentVolumeSpec is the specification of a persistent volume.", + "type": "object", + "properties": { + "accessModes": { + "description": "AccessModes contains all ways the volume can be mounted. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes", + "type": "array", + "items": { + "type": "string" + } + }, + "awsElasticBlockStore": { + "description": "AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "$ref": "#/definitions/io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource" + }, + "azureDisk": { + "description": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.AzureDiskVolumeSource" + }, + "azureFile": { + "description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.AzureFilePersistentVolumeSource" + }, + "capacity": { + "description": "A description of the persistent volume's resources and capacity. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "cephfs": { + "description": "CephFS represents a Ceph FS mount on the host that shares a pod's lifetime", + "$ref": "#/definitions/io.k8s.api.core.v1.CephFSPersistentVolumeSource" + }, + "cinder": { + "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.CinderVolumeSource" + }, + "claimRef": { + "description": "ClaimRef is part of a bi-directional binding between PersistentVolume and PersistentVolumeClaim. Expected to be non-nil when bound. claim.VolumeName is the authoritative bind between PV and PVC. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#binding", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "fc": { + "description": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.FCVolumeSource" + }, + "flexVolume": { + "description": "FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. This is an alpha feature and may change in future.", + "$ref": "#/definitions/io.k8s.api.core.v1.FlexVolumeSource" + }, + "flocker": { + "description": "Flocker represents a Flocker volume attached to a kubelet's host machine and exposed to the pod for its usage. This depends on the Flocker control service being running", + "$ref": "#/definitions/io.k8s.api.core.v1.FlockerVolumeSource" + }, + "gcePersistentDisk": { + "description": "GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "$ref": "#/definitions/io.k8s.api.core.v1.GCEPersistentDiskVolumeSource" + }, + "glusterfs": { + "description": "Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.GlusterfsVolumeSource" + }, + "hostPath": { + "description": "HostPath represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", + "$ref": "#/definitions/io.k8s.api.core.v1.HostPathVolumeSource" + }, + "iscsi": { + "description": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin.", + "$ref": "#/definitions/io.k8s.api.core.v1.ISCSIVolumeSource" + }, + "local": { + "description": "Local represents directly-attached storage with node affinity", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalVolumeSource" + }, + "mountOptions": { + "description": "A list of mount options, e.g. [\"ro\", \"soft\"]. Not validated - mount will simply fail if one is invalid. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options", + "type": "array", + "items": { + "type": "string" + } + }, + "nfs": { + "description": "NFS represents an NFS mount on the host. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "$ref": "#/definitions/io.k8s.api.core.v1.NFSVolumeSource" + }, + "persistentVolumeReclaimPolicy": { + "description": "What happens to a persistent volume when released from its claim. Valid options are Retain (default) and Recycle. Recycling must be supported by the volume plugin underlying this persistent volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming", + "type": "string" + }, + "photonPersistentDisk": { + "description": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource" + }, + "portworxVolume": { + "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.PortworxVolumeSource" + }, + "quobyte": { + "description": "Quobyte represents a Quobyte mount on the host that shares a pod's lifetime", + "$ref": "#/definitions/io.k8s.api.core.v1.QuobyteVolumeSource" + }, + "rbd": { + "description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.RBDVolumeSource" + }, + "scaleIO": { + "description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.", + "$ref": "#/definitions/io.k8s.api.core.v1.ScaleIOVolumeSource" + }, + "storageClassName": { + "description": "Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.", + "type": "string" + }, + "storageos": { + "description": "StorageOS represents a StorageOS volume that is attached to the kubelet's host machine and mounted into the pod More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.StorageOSPersistentVolumeSource" + }, + "vsphereVolume": { + "description": "VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource" + } + } + }, + "io.k8s.api.core.v1.PersistentVolumeStatus": { + "description": "PersistentVolumeStatus is the current status of a persistent volume.", + "type": "object", + "properties": { + "message": { + "description": "A human-readable message indicating details about why the volume is in this state.", + "type": "string" + }, + "phase": { + "description": "Phase indicates if a volume is available, bound to a claim, or released by a claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#phase", + "type": "string" + }, + "reason": { + "description": "Reason is a brief CamelCase string that describes any failure and is meant for machine parsing and tidy display in the CLI.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource": { + "description": "Represents a Photon Controller persistent disk resource.", + "type": "object", + "required": [ + "pdID" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "pdID": { + "description": "ID that identifies Photon Controller persistent disk", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Pod": { + "description": "Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSpec" + }, + "status": { + "description": "Most recently observed status of the pod. This data may not be up to date. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.PodStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Pod", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PodAffinity": { + "description": "Pod affinity is a group of inter pod affinity scheduling rules.", + "type": "object", + "properties": { + "preferredDuringSchedulingIgnoredDuringExecution": { + "description": "The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding \"weight\" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.WeightedPodAffinityTerm" + } + }, + "requiredDuringSchedulingIgnoredDuringExecution": { + "description": "If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodAffinityTerm" + } + } + } + }, + "io.k8s.api.core.v1.PodAffinityTerm": { + "description": "Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key \u003ctopologyKey\u003e tches that of any node on which a pod of the set of pods is running", + "type": "object", + "properties": { + "labelSelector": { + "description": "A label query over a set of resources, in this case pods.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, + "namespaces": { + "description": "namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means \"this pod's namespace\"", + "type": "array", + "items": { + "type": "string" + } + }, + "topologyKey": { + "description": "This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. For PreferredDuringScheduling pod anti-affinity, empty topologyKey is interpreted as \"all topologies\" (\"all topologies\" here means all the topologyKeys indicated by scheduler command-line argument --failure-domains); for affinity and for RequiredDuringScheduling pod anti-affinity, empty topologyKey is not allowed.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PodAntiAffinity": { + "description": "Pod anti affinity is a group of inter pod anti affinity scheduling rules.", + "type": "object", + "properties": { + "preferredDuringSchedulingIgnoredDuringExecution": { + "description": "The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding \"weight\" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.WeightedPodAffinityTerm" + } + }, + "requiredDuringSchedulingIgnoredDuringExecution": { + "description": "If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodAffinityTerm" + } + } + } + }, + "io.k8s.api.core.v1.PodCondition": { + "description": "PodCondition contains details for the current condition of this pod.", + "type": "object", + "required": [ + "type", + "status" + ], + "properties": { + "lastProbeTime": { + "description": "Last time we probed the condition.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "lastTransitionTime": { + "description": "Last time the condition transitioned from one status to another.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "Human-readable message indicating details about last transition.", + "type": "string" + }, + "reason": { + "description": "Unique, one-word, CamelCase reason for the condition's last transition.", + "type": "string" + }, + "status": { + "description": "Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "type": "string" + }, + "type": { + "description": "Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PodList": { + "description": "PodList is a list of Pods.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of pods. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Pod" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PodList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PodSecurityContext": { + "description": "PodSecurityContext holds pod-level security attributes and common container settings. Some fields are also present in container.securityContext. Field values of container.securityContext take precedence over field values of PodSecurityContext.", + "type": "object", + "properties": { + "fsGroup": { + "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw----\n\nIf unset, the Kubelet will not modify the ownership and permissions of any volume.", + "type": "integer", + "format": "int64" + }, + "runAsNonRoot": { + "description": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", + "type": "boolean" + }, + "runAsUser": { + "description": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.", + "type": "integer", + "format": "int64" + }, + "seLinuxOptions": { + "description": "The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.", + "$ref": "#/definitions/io.k8s.api.core.v1.SELinuxOptions" + }, + "supplementalGroups": { + "description": "A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container.", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + } + } + }, + "io.k8s.api.core.v1.PodSpec": { + "description": "PodSpec is a description of a pod.", + "type": "object", + "required": [ + "containers" + ], + "properties": { + "activeDeadlineSeconds": { + "description": "Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.", + "type": "integer", + "format": "int64" + }, + "affinity": { + "description": "If specified, the pod's scheduling constraints", + "$ref": "#/definitions/io.k8s.api.core.v1.Affinity" + }, + "automountServiceAccountToken": { + "description": "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.", + "type": "boolean" + }, + "containers": { + "description": "List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Container" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "dnsPolicy": { + "description": "Set DNS policy for containers within the pod. One of 'ClusterFirstWithHostNet', 'ClusterFirst' or 'Default'. Defaults to \"ClusterFirst\". To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'.", + "type": "string" + }, + "hostAliases": { + "description": "HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts file if specified. This is only valid for non-hostNetwork pods.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.HostAlias" + }, + "x-kubernetes-patch-merge-key": "ip", + "x-kubernetes-patch-strategy": "merge" + }, + "hostIPC": { + "description": "Use the host's ipc namespace. Optional: Default to false.", + "type": "boolean" + }, + "hostNetwork": { + "description": "Host networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false.", + "type": "boolean" + }, + "hostPID": { + "description": "Use the host's pid namespace. Optional: Default to false.", + "type": "boolean" + }, + "hostname": { + "description": "Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value.", + "type": "string" + }, + "imagePullSecrets": { + "description": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "initContainers": { + "description": "List of initialization containers belonging to the pod. Init containers are executed in order prior to containers being started. If any init container fails, the pod is considered to have failed and is handled according to its restartPolicy. The name for an init container or normal container must be unique among all containers. Init containers may not have Lifecycle actions, Readiness probes, or Liveness probes. The resourceRequirements of an init container are taken into account during scheduling by finding the highest request/limit for each resource type, and then using the max of of that value or the sum of the normal containers. Limits are applied to init containers in a similar fashion. Init containers cannot currently be added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Container" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "nodeName": { + "description": "NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.", + "type": "string" + }, + "nodeSelector": { + "description": "NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "priority": { + "description": "The priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.", + "type": "integer", + "format": "int32" + }, + "priorityClassName": { + "description": "If specified, indicates the pod's priority. \"SYSTEM\" is a special keyword which indicates the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.", + "type": "string" + }, + "restartPolicy": { + "description": "Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy", + "type": "string" + }, + "schedulerName": { + "description": "If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler.", + "type": "string" + }, + "securityContext": { + "description": "SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSecurityContext" + }, + "serviceAccount": { + "description": "DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead.", + "type": "string" + }, + "serviceAccountName": { + "description": "ServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/", + "type": "string" + }, + "subdomain": { + "description": "If specified, the fully qualified Pod hostname will be \"\u003chostname\u003e.\u003csubdomain\u003e.\u003cpod namespace\u003e.svc.\u003ccluster domain\u003e\". If not specified, the pod will not have a domainname at all.", + "type": "string" + }, + "terminationGracePeriodSeconds": { + "description": "Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds.", + "type": "integer", + "format": "int64" + }, + "tolerations": { + "description": "If specified, the pod's tolerations.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Toleration" + } + }, + "volumes": { + "description": "List of volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Volume" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge,retainKeys" + } + } + }, + "io.k8s.api.core.v1.PodStatus": { + "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system.", + "type": "object", + "properties": { + "conditions": { + "description": "Current service state of pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "containerStatuses": { + "description": "The list has one entry per container in the manifest. Each entry is currently the output of `docker inspect`. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStatus" + } + }, + "hostIP": { + "description": "IP address of the host to which the pod is assigned. Empty if not yet scheduled.", + "type": "string" + }, + "initContainerStatuses": { + "description": "The list has one entry per init container in the manifest. The most recent successful init container will have ready = true, the most recently started container will have startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ContainerStatus" + } + }, + "message": { + "description": "A human readable message indicating details about why the pod is in this condition.", + "type": "string" + }, + "phase": { + "description": "Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", + "type": "string" + }, + "podIP": { + "description": "IP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.", + "type": "string" + }, + "qosClass": { + "description": "The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://github.com/kubernetes/kubernetes/blob/master/docs/design/resource-qos.md", + "type": "string" + }, + "reason": { + "description": "A brief CamelCase message indicating details about why the pod is in this state. e.g. 'Evicted'", + "type": "string" + }, + "startTime": { + "description": "RFC 3339 date and time at which the object was acknowledged by the Kubelet. This is before the Kubelet pulled the container image(s) for the pod.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + } + }, + "io.k8s.api.core.v1.PodTemplate": { + "description": "PodTemplate describes a template for creating copies of a predefined pod.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "template": { + "description": "Template defines the pods that will be created from this pod template. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PodTemplate", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PodTemplateList": { + "description": "PodTemplateList is a list of PodTemplates.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of pod templates", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplate" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "PodTemplateList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.PodTemplateSpec": { + "description": "PodTemplateSpec describes the data a pod should have when created from a template", + "type": "object", + "properties": { + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.PodSpec" + } + } + }, + "io.k8s.api.core.v1.PortworxVolumeSource": { + "description": "PortworxVolumeSource represents a Portworx volume resource.", + "type": "object", + "required": [ + "volumeID" + ], + "properties": { + "fsType": { + "description": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "volumeID": { + "description": "VolumeID uniquely identifies a Portworx volume", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.PreferredSchedulingTerm": { + "description": "An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op).", + "type": "object", + "required": [ + "weight", + "preference" + ], + "properties": { + "preference": { + "description": "A node selector term, associated with the corresponding weight.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelectorTerm" + }, + "weight": { + "description": "Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.Probe": { + "description": "Probe describes a health check to be performed against a container to determine whether it is alive or ready to receive traffic.", + "type": "object", + "properties": { + "exec": { + "description": "One and only one of the following should be specified. Exec specifies the action to take.", + "$ref": "#/definitions/io.k8s.api.core.v1.ExecAction" + }, + "failureThreshold": { + "description": "Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1.", + "type": "integer", + "format": "int32" + }, + "httpGet": { + "description": "HTTPGet specifies the http request to perform.", + "$ref": "#/definitions/io.k8s.api.core.v1.HTTPGetAction" + }, + "initialDelaySeconds": { + "description": "Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", + "type": "integer", + "format": "int32" + }, + "periodSeconds": { + "description": "How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1.", + "type": "integer", + "format": "int32" + }, + "successThreshold": { + "description": "Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1.", + "type": "integer", + "format": "int32" + }, + "tcpSocket": { + "description": "TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported", + "$ref": "#/definitions/io.k8s.api.core.v1.TCPSocketAction" + }, + "timeoutSeconds": { + "description": "Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.ProjectedVolumeSource": { + "description": "Represents a projected volume source", + "type": "object", + "required": [ + "sources" + ], + "properties": { + "defaultMode": { + "description": "Mode bits to use on created files by default. Must be a value between 0 and 0777. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "sources": { + "description": "list of volume projections", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.VolumeProjection" + } + } + } + }, + "io.k8s.api.core.v1.QuobyteVolumeSource": { + "description": "Represents a Quobyte mount that lasts the lifetime of a pod. Quobyte volumes do not support ownership management or SELinux relabeling.", + "type": "object", + "required": [ + "registry", + "volume" + ], + "properties": { + "group": { + "description": "Group to map volume access to Default is no group", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false.", + "type": "boolean" + }, + "registry": { + "description": "Registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes", + "type": "string" + }, + "user": { + "description": "User to map volume access to Defaults to serivceaccount user", + "type": "string" + }, + "volume": { + "description": "Volume is a string that references an already created Quobyte volume by name.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.RBDVolumeSource": { + "description": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.", + "type": "object", + "required": [ + "monitors", + "image" + ], + "properties": { + "fsType": { + "description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd", + "type": "string" + }, + "image": { + "description": "The rados image name. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "string" + }, + "keyring": { + "description": "Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "string" + }, + "monitors": { + "description": "A collection of Ceph monitors. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "array", + "items": { + "type": "string" + } + }, + "pool": { + "description": "The rados pool name. Default is rbd. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "string" + }, + "readOnly": { + "description": "ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "boolean" + }, + "secretRef": { + "description": "SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "user": { + "description": "The rados user name. Default is admin. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ReplicationController": { + "description": "ReplicationController represents the configuration of a replication controller.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "If the Labels of a ReplicationController are empty, they are defaulted to be the same as the Pod(s) that the replication controller manages. Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the specification of the desired behavior of the replication controller. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ReplicationControllerSpec" + }, + "status": { + "description": "Status is the most recently observed status of the replication controller. This data may be out of date by some window of time. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ReplicationControllerStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ReplicationController", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ReplicationControllerCondition": { + "description": "ReplicationControllerCondition describes the state of a replication controller at a certain point.", + "type": "object", + "required": [ + "type", + "status" + ], + "properties": { + "lastTransitionTime": { + "description": "The last time the condition transitioned from one status to another.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "message": { + "description": "A human readable message indicating details about the transition.", + "type": "string" + }, + "reason": { + "description": "The reason for the condition's last transition.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of replication controller condition.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ReplicationControllerList": { + "description": "ReplicationControllerList is a collection of replication controllers.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of replication controllers. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ReplicationController" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ReplicationControllerList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ReplicationControllerSpec": { + "description": "ReplicationControllerSpec is the specification of a replication controller.", + "type": "object", + "properties": { + "minReadySeconds": { + "description": "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "Replicas is the number of desired replicas. This is a pointer to distinguish between explicit zero and unspecified. Defaults to 1. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller", + "type": "integer", + "format": "int32" + }, + "selector": { + "description": "Selector is a label query over pods that should match the Replicas count. If Selector is empty, it is defaulted to the labels present on the Pod template. Label keys and values that must match in order to be controlled by this replication controller, if empty defaulted to labels on Pod template. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "template": { + "description": "Template is the object that describes the pod that will be created if insufficient replicas are detected. This takes precedence over a TemplateRef. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template", + "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" + } + } + }, + "io.k8s.api.core.v1.ReplicationControllerStatus": { + "description": "ReplicationControllerStatus represents the current status of a replication controller.", + "type": "object", + "required": [ + "replicas" + ], + "properties": { + "availableReplicas": { + "description": "The number of available replicas (ready for at least minReadySeconds) for this replication controller.", + "type": "integer", + "format": "int32" + }, + "conditions": { + "description": "Represents the latest available observations of a replication controller's current state.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ReplicationControllerCondition" + }, + "x-kubernetes-patch-merge-key": "type", + "x-kubernetes-patch-strategy": "merge" + }, + "fullyLabeledReplicas": { + "description": "The number of pods that have labels matching the labels of the pod template of the replication controller.", + "type": "integer", + "format": "int32" + }, + "observedGeneration": { + "description": "ObservedGeneration reflects the generation of the most recently observed replication controller.", + "type": "integer", + "format": "int64" + }, + "readyReplicas": { + "description": "The number of ready replicas for this replication controller.", + "type": "integer", + "format": "int32" + }, + "replicas": { + "description": "Replicas is the most recently oberved number of replicas. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.api.core.v1.ResourceFieldSelector": { + "description": "ResourceFieldSelector represents container resources (cpu, memory) and their output format", + "type": "object", + "required": [ + "resource" + ], + "properties": { + "containerName": { + "description": "Container name: required for volumes, optional for env vars", + "type": "string" + }, + "divisor": { + "description": "Specifies the output format of the exposed resources, defaults to \"1\"", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + }, + "resource": { + "description": "Required: resource to select", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ResourceQuota": { + "description": "ResourceQuota sets aggregate quota restrictions enforced per namespace", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the desired quota. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceQuotaSpec" + }, + "status": { + "description": "Status defines the actual enforced quota and its current usage. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceQuotaStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ResourceQuota", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ResourceQuotaList": { + "description": "ResourceQuotaList is a list of ResourceQuota items.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is a list of ResourceQuota objects. More info: https://git.k8s.io/community/contributors/design-proposals/admission_control_resource_quota.md", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceQuota" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ResourceQuotaList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ResourceQuotaSpec": { + "description": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", + "type": "object", + "properties": { + "hard": { + "description": "Hard is the set of desired hard limits for each named resource. More info: https://git.k8s.io/community/contributors/design-proposals/admission_control_resource_quota.md", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "scopes": { + "description": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.ResourceQuotaStatus": { + "description": "ResourceQuotaStatus defines the enforced hard limits and observed use.", + "type": "object", + "properties": { + "hard": { + "description": "Hard is the set of enforced hard limits for each named resource. More info: https://git.k8s.io/community/contributors/design-proposals/admission_control_resource_quota.md", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "used": { + "description": "Used is the current observed total usage of the resource in the namespace.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + } + } + }, + "io.k8s.api.core.v1.ResourceRequirements": { + "description": "ResourceRequirements describes the compute resource requirements.", + "type": "object", + "properties": { + "limits": { + "description": "Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + }, + "requests": { + "description": "Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + } + } + }, + "io.k8s.api.core.v1.SELinuxOptions": { + "description": "SELinuxOptions are the labels to be applied to the container", + "type": "object", + "properties": { + "level": { + "description": "Level is SELinux level label that applies to the container.", + "type": "string" + }, + "role": { + "description": "Role is a SELinux role label that applies to the container.", + "type": "string" + }, + "type": { + "description": "Type is a SELinux type label that applies to the container.", + "type": "string" + }, + "user": { + "description": "User is a SELinux user label that applies to the container.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ScaleIOVolumeSource": { + "description": "ScaleIOVolumeSource represents a persistent ScaleIO volume", + "type": "object", + "required": [ + "gateway", + "system", + "secretRef" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "gateway": { + "description": "The host address of the ScaleIO API Gateway.", + "type": "string" + }, + "protectionDomain": { + "description": "The name of the Protection Domain for the configured storage (defaults to \"default\").", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretRef": { + "description": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail.", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "sslEnabled": { + "description": "Flag to enable/disable SSL communication with Gateway, default false", + "type": "boolean" + }, + "storageMode": { + "description": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\").", + "type": "string" + }, + "storagePool": { + "description": "The Storage Pool associated with the protection domain (defaults to \"default\").", + "type": "string" + }, + "system": { + "description": "The name of the storage system as configured in ScaleIO.", + "type": "string" + }, + "volumeName": { + "description": "The name of a volume already created in the ScaleIO system that is associated with this volume source.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Secret": { + "description": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "data": { + "description": "Data contains the secret data. Each key must consist of alphanumeric characters, '-', '_' or '.'. The serialized form of the secret data is a base64 encoded string, representing the arbitrary (possibly non-string) data value here. Described in https://tools.ietf.org/html/rfc4648#section-4", + "type": "object", + "additionalProperties": { + "type": "string", + "format": "byte" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "stringData": { + "description": "stringData allows specifying non-binary secret data in string form. It is provided as a write-only convenience method. All keys and values are merged into the data field on write, overwriting any existing values. It is never output when reading from the API.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "type": { + "description": "Used to facilitate programmatic handling of secret data.", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Secret", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.SecretEnvSource": { + "description": "SecretEnvSource selects a Secret to populate the environment variables with.\n\nThe contents of the target Secret's Data field will represent the key-value pairs as environment variables.", + "type": "object", + "properties": { + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the Secret must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.SecretKeySelector": { + "description": "SecretKeySelector selects a key of a Secret.", + "type": "object", + "required": [ + "key" + ], + "properties": { + "key": { + "description": "The key of the secret to select from. Must be a valid secret key.", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the Secret or it's key must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.SecretList": { + "description": "SecretList is a list of Secret.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is a list of secret objects. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Secret" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "SecretList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.SecretProjection": { + "description": "Adapts a secret into a projected volume.\n\nThe contents of the target Secret's Data field will be presented in a projected volume as files using the keys in the Data field as the file names. Note that this is identical to a secret volume source without the default mode.", + "type": "object", + "properties": { + "items": { + "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.KeyToPath" + } + }, + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the Secret or its key must be defined", + "type": "boolean" + } + } + }, + "io.k8s.api.core.v1.SecretReference": { + "description": "SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace", + "type": "object", + "properties": { + "name": { + "description": "Name is unique within a namespace to reference a secret resource.", + "type": "string" + }, + "namespace": { + "description": "Namespace defines the space within which the secret name must be unique.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.SecretVolumeSource": { + "description": "Adapts a Secret into a volume.\n\nThe contents of the target Secret's Data field will be presented in a volume as files using the keys in the Data field as the file names. Secret volumes support ownership management and SELinux relabeling.", + "type": "object", + "properties": { + "defaultMode": { + "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", + "type": "integer", + "format": "int32" + }, + "items": { + "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.KeyToPath" + } + }, + "optional": { + "description": "Specify whether the Secret or it's keys must be defined", + "type": "boolean" + }, + "secretName": { + "description": "Name of the secret in the pod's namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.SecurityContext": { + "description": "SecurityContext holds security configuration that will be applied to a container. Some fields are present in both SecurityContext and PodSecurityContext. When both are set, the values in SecurityContext take precedence.", + "type": "object", + "properties": { + "allowPrivilegeEscalation": { + "description": "AllowPrivilegeEscalation controls whether a process can gain more privileges than it's parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN", + "type": "boolean" + }, + "capabilities": { + "description": "The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime.", + "$ref": "#/definitions/io.k8s.api.core.v1.Capabilities" + }, + "privileged": { + "description": "Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false.", + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "description": "Whether this container has a read-only root filesystem. Default is false.", + "type": "boolean" + }, + "runAsNonRoot": { + "description": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", + "type": "boolean" + }, + "runAsUser": { + "description": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", + "type": "integer", + "format": "int64" + }, + "seLinuxOptions": { + "description": "The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", + "$ref": "#/definitions/io.k8s.api.core.v1.SELinuxOptions" + } + } + }, + "io.k8s.api.core.v1.Service": { + "description": "Service is a named abstraction of software service (for example, mysql) consisting of local port (for example 3306) that the proxy listens on, and the selector that determines which pods will answer requests sent through the proxy.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec defines the behavior of a service. https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ServiceSpec" + }, + "status": { + "description": "Most recently observed status of the service. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.core.v1.ServiceStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Service", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ServiceAccount": { + "description": "ServiceAccount binds together: * a name, understood by users, and perhaps by peripheral systems, for an identity * a principal that can be authenticated and authorized * a set of secrets", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "automountServiceAccountToken": { + "description": "AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted. Can be overridden at the pod level.", + "type": "boolean" + }, + "imagePullSecrets": { + "description": "ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet. More info: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "secrets": { + "description": "Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ServiceAccount", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ServiceAccountList": { + "description": "ServiceAccountList is a list of ServiceAccount objects", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of ServiceAccounts. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ServiceAccount" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ServiceAccountList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ServiceList": { + "description": "ServiceList holds a list of services.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "List of services", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Service" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "ServiceList", + "version": "v1" + } + ] + }, + "io.k8s.api.core.v1.ServicePort": { + "description": "ServicePort contains information on service's port.", + "type": "object", + "required": [ + "port" + ], + "properties": { + "name": { + "description": "The name of this port within the service. This must be a DNS_LABEL. All ports within a ServiceSpec must have unique names. This maps to the 'Name' field in EndpointPort objects. Optional if only one ServicePort is defined on this service.", + "type": "string" + }, + "nodePort": { + "description": "The port on each node on which this service is exposed when type=NodePort or LoadBalancer. Usually assigned by the system. If specified, it will be allocated to the service if unused or else creation of the service will fail. Default is to auto-allocate a port if the ServiceType of this Service requires one. More info: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport", + "type": "integer", + "format": "int32" + }, + "port": { + "description": "The port that will be exposed by this service.", + "type": "integer", + "format": "int32" + }, + "protocol": { + "description": "The IP protocol for this port. Supports \"TCP\" and \"UDP\". Default is TCP.", + "type": "string" + }, + "targetPort": { + "description": "Number or name of the port to access on the pods targeted by the service. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. If this is a string, it will be looked up as a named port in the target Pod's container ports. If this is not specified, the value of the 'port' field is used (an identity map). This field is ignored for services with clusterIP=None, and should be omitted or set equal to the 'port' field. More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, + "io.k8s.api.core.v1.ServiceSpec": { + "description": "ServiceSpec describes the attributes that a user creates on a service.", + "type": "object", + "properties": { + "clusterIP": { + "description": "clusterIP is the IP address of the service and is usually assigned randomly by the master. If an address is specified manually and is not in use by others, it will be allocated to the service; otherwise, creation of the service will fail. This field can not be changed through updates. Valid values are \"None\", empty string (\"\"), or a valid IP address. \"None\" can be specified for headless services when proxying is not required. Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if type is ExternalName. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies", + "type": "string" + }, + "externalIPs": { + "description": "externalIPs is a list of IP addresses for which nodes in the cluster will also accept traffic for this service. These IPs are not managed by Kubernetes. The user is responsible for ensuring that traffic arrives at a node with this IP. A common example is external load-balancers that are not part of the Kubernetes system.", + "type": "array", + "items": { + "type": "string" + } + }, + "externalName": { + "description": "externalName is the external reference that kubedns or equivalent will return as a CNAME record for this service. No proxying will be involved. Must be a valid DNS name and requires Type to be ExternalName.", + "type": "string" + }, + "externalTrafficPolicy": { + "description": "externalTrafficPolicy denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints. \"Local\" preserves the client source IP and avoids a second hop for LoadBalancer and Nodeport type services, but risks potentially imbalanced traffic spreading. \"Cluster\" obscures the client source IP and may cause a second hop to another node, but should have good overall load-spreading.", + "type": "string" + }, + "healthCheckNodePort": { + "description": "healthCheckNodePort specifies the healthcheck nodePort for the service. If not specified, HealthCheckNodePort is created by the service api backend with the allocated nodePort. Will use user-specified nodePort value if specified by the client. Only effects when Type is set to LoadBalancer and ExternalTrafficPolicy is set to Local.", + "type": "integer", + "format": "int32" + }, + "loadBalancerIP": { + "description": "Only applies to Service Type: LoadBalancer LoadBalancer will get created with the IP specified in this field. This feature depends on whether the underlying cloud-provider supports specifying the loadBalancerIP when a load balancer is created. This field will be ignored if the cloud-provider does not support the feature.", + "type": "string" + }, + "loadBalancerSourceRanges": { + "description": "If specified and supported by the platform, this will restrict traffic through the cloud-provider load-balancer will be restricted to the specified client IPs. This field will be ignored if the cloud-provider does not support the feature.\" More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/", + "type": "array", + "items": { + "type": "string" + } + }, + "ports": { + "description": "The list of ports that are exposed by this service. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ServicePort" + }, + "x-kubernetes-patch-merge-key": "port", + "x-kubernetes-patch-strategy": "merge" + }, + "publishNotReadyAddresses": { + "description": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery. This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints when that annotation is deprecated and all clients have been converted to use this field.", + "type": "boolean" + }, + "selector": { + "description": "Route service traffic to pods with label keys and values matching this selector. If empty or not present, the service is assumed to have an external process managing its endpoints, which Kubernetes will not modify. Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if type is ExternalName. More info: https://kubernetes.io/docs/concepts/services-networking/service/", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "sessionAffinity": { + "description": "Supports \"ClientIP\" and \"None\". Used to maintain session affinity. Enable client IP based session affinity. Must be ClientIP or None. Defaults to None. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies", + "type": "string" + }, + "sessionAffinityConfig": { + "description": "sessionAffinityConfig contains the configurations of session affinity.", + "$ref": "#/definitions/io.k8s.api.core.v1.SessionAffinityConfig" + }, + "type": { + "description": "type determines how the Service is exposed. Defaults to ClusterIP. Valid options are ExternalName, ClusterIP, NodePort, and LoadBalancer. \"ExternalName\" maps to the specified externalName. \"ClusterIP\" allocates a cluster-internal IP address for load-balancing to endpoints. Endpoints are determined by the selector or if that is not specified, by manual construction of an Endpoints object. If clusterIP is \"None\", no virtual IP is allocated and the endpoints are published as a set of endpoints rather than a stable IP. \"NodePort\" builds on ClusterIP and allocates a port on every node which routes to the clusterIP. \"LoadBalancer\" builds on NodePort and creates an external load-balancer (if supported in the current cloud) which routes to the clusterIP. More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.ServiceStatus": { + "description": "ServiceStatus represents the current status of a service.", + "type": "object", + "properties": { + "loadBalancer": { + "description": "LoadBalancer contains the current status of the load-balancer, if one is present.", + "$ref": "#/definitions/io.k8s.api.core.v1.LoadBalancerStatus" + } + } + }, + "io.k8s.api.core.v1.SessionAffinityConfig": { + "description": "SessionAffinityConfig represents the configurations of session affinity.", + "type": "object", + "properties": { + "clientIP": { + "description": "clientIP contains the configurations of Client IP based session affinity.", + "$ref": "#/definitions/io.k8s.api.core.v1.ClientIPConfig" + } + } + }, + "io.k8s.api.core.v1.StorageOSPersistentVolumeSource": { + "description": "Represents a StorageOS persistent volume resource.", + "type": "object", + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretRef": { + "description": "SecretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted.", + "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + }, + "volumeName": { + "description": "VolumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace.", + "type": "string" + }, + "volumeNamespace": { + "description": "VolumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping to be mirrored within StorageOS for tighter integration. Set VolumeName to any name to override the default behaviour. Set to \"default\" if you are not using namespaces within StorageOS. Namespaces that do not pre-exist within StorageOS will be created.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.StorageOSVolumeSource": { + "description": "Represents a StorageOS persistent volume resource.", + "type": "object", + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "readOnly": { + "description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.", + "type": "boolean" + }, + "secretRef": { + "description": "SecretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted.", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "volumeName": { + "description": "VolumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace.", + "type": "string" + }, + "volumeNamespace": { + "description": "VolumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping to be mirrored within StorageOS for tighter integration. Set VolumeName to any name to override the default behaviour. Set to \"default\" if you are not using namespaces within StorageOS. Namespaces that do not pre-exist within StorageOS will be created.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.TCPSocketAction": { + "description": "TCPSocketAction describes an action based on opening a socket", + "type": "object", + "required": [ + "port" + ], + "properties": { + "host": { + "description": "Optional: Host name to connect to, defaults to the pod IP.", + "type": "string" + }, + "port": { + "description": "Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, + "io.k8s.api.core.v1.Taint": { + "description": "The node this Taint is attached to has the \"effect\" on any pod that does not tolerate the Taint.", + "type": "object", + "required": [ + "key", + "effect" + ], + "properties": { + "effect": { + "description": "Required. The effect of the taint on pods that do not tolerate the taint. Valid effects are NoSchedule, PreferNoSchedule and NoExecute.", + "type": "string" + }, + "key": { + "description": "Required. The taint key to be applied to a node.", + "type": "string" + }, + "timeAdded": { + "description": "TimeAdded represents the time at which the taint was added. It is only written for NoExecute taints.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "value": { + "description": "Required. The taint value corresponding to the taint key.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Toleration": { + "description": "The pod this Toleration is attached to tolerates any taint that matches the triple \u003ckey,value,effect\u003e using the matching operator \u003coperator\u003e.", + "type": "object", + "properties": { + "effect": { + "description": "Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.", + "type": "string" + }, + "key": { + "description": "Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys.", + "type": "string" + }, + "operator": { + "description": "Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category.", + "type": "string" + }, + "tolerationSeconds": { + "description": "TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.", + "type": "integer", + "format": "int64" + }, + "value": { + "description": "Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string.", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.Volume": { + "description": "Volume represents a named volume in a pod that may be accessed by any container in the pod.", + "type": "object", + "required": [ + "name" + ], + "properties": { + "awsElasticBlockStore": { + "description": "AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", + "$ref": "#/definitions/io.k8s.api.core.v1.AWSElasticBlockStoreVolumeSource" + }, + "azureDisk": { + "description": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.AzureDiskVolumeSource" + }, + "azureFile": { + "description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.AzureFileVolumeSource" + }, + "cephfs": { + "description": "CephFS represents a Ceph FS mount on the host that shares a pod's lifetime", + "$ref": "#/definitions/io.k8s.api.core.v1.CephFSVolumeSource" + }, + "cinder": { + "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.CinderVolumeSource" + }, + "configMap": { + "description": "ConfigMap represents a configMap that should populate this volume", + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapVolumeSource" + }, + "downwardAPI": { + "description": "DownwardAPI represents downward API about the pod that should populate this volume", + "$ref": "#/definitions/io.k8s.api.core.v1.DownwardAPIVolumeSource" + }, + "emptyDir": { + "description": "EmptyDir represents a temporary directory that shares a pod's lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir", + "$ref": "#/definitions/io.k8s.api.core.v1.EmptyDirVolumeSource" + }, + "fc": { + "description": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.", + "$ref": "#/definitions/io.k8s.api.core.v1.FCVolumeSource" + }, + "flexVolume": { + "description": "FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. This is an alpha feature and may change in future.", + "$ref": "#/definitions/io.k8s.api.core.v1.FlexVolumeSource" + }, + "flocker": { + "description": "Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running", + "$ref": "#/definitions/io.k8s.api.core.v1.FlockerVolumeSource" + }, + "gcePersistentDisk": { + "description": "GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", + "$ref": "#/definitions/io.k8s.api.core.v1.GCEPersistentDiskVolumeSource" + }, + "gitRepo": { + "description": "GitRepo represents a git repository at a particular revision.", + "$ref": "#/definitions/io.k8s.api.core.v1.GitRepoVolumeSource" + }, + "glusterfs": { + "description": "Glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.GlusterfsVolumeSource" + }, + "hostPath": { + "description": "HostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", + "$ref": "#/definitions/io.k8s.api.core.v1.HostPathVolumeSource" + }, + "iscsi": { + "description": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://releases.k8s.io/HEAD/examples/volumes/iscsi/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.ISCSIVolumeSource" + }, + "name": { + "description": "Volume's name. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "nfs": { + "description": "NFS represents an NFS mount on the host that shares a pod's lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", + "$ref": "#/definitions/io.k8s.api.core.v1.NFSVolumeSource" + }, + "persistentVolumeClaim": { + "description": "PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", + "$ref": "#/definitions/io.k8s.api.core.v1.PersistentVolumeClaimVolumeSource" + }, + "photonPersistentDisk": { + "description": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.PhotonPersistentDiskVolumeSource" + }, + "portworxVolume": { + "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.PortworxVolumeSource" + }, + "projected": { + "description": "Items for all in one resources secrets, configmaps, and downward API", + "$ref": "#/definitions/io.k8s.api.core.v1.ProjectedVolumeSource" + }, + "quobyte": { + "description": "Quobyte represents a Quobyte mount on the host that shares a pod's lifetime", + "$ref": "#/definitions/io.k8s.api.core.v1.QuobyteVolumeSource" + }, + "rbd": { + "description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md", + "$ref": "#/definitions/io.k8s.api.core.v1.RBDVolumeSource" + }, + "scaleIO": { + "description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.", + "$ref": "#/definitions/io.k8s.api.core.v1.ScaleIOVolumeSource" + }, + "secret": { + "description": "Secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretVolumeSource" + }, + "storageos": { + "description": "StorageOS represents a StorageOS volume attached and mounted on Kubernetes nodes.", + "$ref": "#/definitions/io.k8s.api.core.v1.StorageOSVolumeSource" + }, + "vsphereVolume": { + "description": "VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine", + "$ref": "#/definitions/io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource" + } + } + }, + "io.k8s.api.core.v1.VolumeMount": { + "description": "VolumeMount describes a mounting of a Volume within a container.", + "required": [ + "name", + "mountPath" + ], + "properties": { + "mountPath": { + "description": "Path within the container at which the volume should be mounted. Must not contain ':'.", + "type": "string" + }, + "name": { + "description": "This must match the Name of a Volume.", + "type": "string" + }, + "readOnly": { + "description": "Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false.", + "type": "boolean" + }, + "subPath": { + "description": "Path within the volume from which the container's volume should be mounted. Defaults to \"\" (volume's root).", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.VolumeProjection": { + "description": "Projection that may be projected along with other supported volume types", + "type": "object", + "properties": { + "configMap": { + "description": "information about the configMap data to project", + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapProjection" + }, + "downwardAPI": { + "description": "information about the downwardAPI data to project", + "$ref": "#/definitions/io.k8s.api.core.v1.DownwardAPIProjection" + }, + "secret": { + "description": "information about the secret data to project", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretProjection" + } + } + }, + "io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource": { + "description": "Represents a vSphere volume resource.", + "type": "object", + "required": [ + "volumePath" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, + "storagePolicyID": { + "description": "Storage Policy Based Management (SPBM) profile ID associated with the StoragePolicyName.", + "type": "string" + }, + "storagePolicyName": { + "description": "Storage Policy Based Management (SPBM) profile name.", + "type": "string" + }, + "volumePath": { + "description": "Path that identifies vSphere volume vmdk", + "type": "string" + } + } + }, + "io.k8s.api.core.v1.WeightedPodAffinityTerm": { + "description": "The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s)", + "type": "object", + "required": [ + "weight", + "podAffinityTerm" + ], + "properties": { + "podAffinityTerm": { + "description": "Required. A pod affinity term, associated with the corresponding weight.", + "$ref": "#/definitions/io.k8s.api.core.v1.PodAffinityTerm" + }, + "weight": { + "description": "weight associated with matching the corresponding podAffinityTerm, in the range 1-100.", + "type": "integer", + "format": "int32" + } + } + }, + "io.k8s.apimachinery.pkg.api.resource.Quantity": { + "type": "string" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup": { + "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", + "type": "object", + "required": [ + "name", + "versions", + "serverAddressByClientCIDRs" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "name is the name of the group.", + "type": "string" + }, + "preferredVersion": { + "description": "preferredVersion is the version preferred by the API server, which probably is the storage version.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery" + }, + "serverAddressByClientCIDRs": { + "description": "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR" + } + }, + "versions": { + "description": "versions are the versions supported in this group.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIGroup", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIGroupList": { + "description": "APIGroupList is a list of APIGroup, to allow clients to discover the API at /apis.", + "type": "object", + "required": [ + "groups" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "groups": { + "description": "groups is a list of APIGroup.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIGroupList", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIResource": { + "description": "APIResource specifies the name of a resource and whether it is namespaced.", + "type": "object", + "required": [ + "name", + "singularName", + "namespaced", + "kind", + "verbs" + ], + "properties": { + "categories": { + "description": "categories is a list of the grouped resources this resource belongs to (e.g. 'all')", + "type": "array", + "items": { + "type": "string" + } + }, + "kind": { + "description": "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')", + "type": "string" + }, + "name": { + "description": "name is the plural name of the resource.", + "type": "string" + }, + "namespaced": { + "description": "namespaced indicates if a resource is namespaced or not.", + "type": "boolean" + }, + "shortNames": { + "description": "shortNames is a list of suggested short names of the resource.", + "type": "array", + "items": { + "type": "string" + } + }, + "singularName": { + "description": "singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface.", + "type": "string" + }, + "verbs": { + "description": "verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList": { + "description": "APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.", + "type": "object", + "required": [ + "groupVersion", + "resources" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "groupVersion": { + "description": "groupVersion is the group and version this APIResourceList is for.", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "resources": { + "description": "resources contains the name of the resources and if they are namespaced.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIResource" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIResourceList", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIVersions": { + "description": "APIVersions lists the versions that are available, to allow clients to discover the API at /api, which is the root path of the legacy v1 API.", + "type": "object", + "required": [ + "versions", + "serverAddressByClientCIDRs" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "serverAddressByClientCIDRs": { + "description": "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR" + } + }, + "versions": { + "description": "versions are the api versions that are available.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIVersions", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions": { + "description": "DeleteOptions may be provided when deleting an API object.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "gracePeriodSeconds": { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "type": "integer", + "format": "int64" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "orphanDependents": { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "type": "boolean" + }, + "preconditions": { + "description": "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions" + }, + "propagationPolicy": { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy.", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "admission.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "apps", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "apps", + "kind": "DeleteOptions", + "version": "v1beta2" + }, + { + "group": "authentication.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "authentication.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "autoscaling", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "autoscaling", + "kind": "DeleteOptions", + "version": "v2alpha1" + }, + { + "group": "batch", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "batch", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "batch", + "kind": "DeleteOptions", + "version": "v2alpha1" + }, + { + "group": "certificates.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "extensions", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "federation", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "imagepolicy.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "networking.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "policy", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "scheduling.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "settings.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "storage.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "storage.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery": { + "description": "GroupVersion contains the \"group/version\" and \"version\" string of a version. It is made a struct to keep extensibility.", + "type": "object", + "required": [ + "groupVersion", + "version" + ], + "properties": { + "groupVersion": { + "description": "groupVersion specifies the API group and version in the form \"group/version\"", + "type": "string" + }, + "version": { + "description": "version specifies the version in the form of \"version\". This is to save the clients the trouble of splitting the GroupVersion.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Initializer": { + "description": "Initializer is information about an initializer that has not yet completed.", + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "name of the process that is responsible for initializing this object.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Initializers": { + "description": "Initializers tracks the progress of initialization.", + "type": "object", + "required": [ + "pending" + ], + "properties": { + "pending": { + "description": "Pending is a list of initializers that must execute in order before this object is visible. When the last pending initializer is removed, and no failing result is set, the initializers struct will be set to nil and the object is considered as initialized and visible to all clients.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Initializer" + }, + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge" + }, + "result": { + "description": "If result is set with the Failure field, the object will be persisted to storage and then deleted, ensuring that other clients can observe the deletion.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector": { + "description": "A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects.", + "type": "object", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement" + } + }, + "matchLabels": { + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.", + "type": "object", + "required": [ + "key", + "operator" + ], + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string", + "x-kubernetes-patch-merge-key": "key", + "x-kubernetes-patch-strategy": "merge" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values. Valid operators ard In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta": { + "description": "ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.", + "type": "object", + "properties": { + "resourceVersion": { + "description": "String that identifies the server's internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency", + "type": "string" + }, + "selfLink": { + "description": "SelfLink is a URL representing this object. Populated by the system. Read-only.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": { + "description": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.", + "type": "object", + "properties": { + "annotations": { + "description": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "clusterName": { + "description": "The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.", + "type": "string" + }, + "creationTimestamp": { + "description": "CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "deletionGracePeriodSeconds": { + "description": "Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.", + "type": "integer", + "format": "int64" + }, + "deletionTimestamp": { + "description": "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field. Once set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, + "finalizers": { + "description": "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed.", + "type": "array", + "items": { + "type": "string" + }, + "x-kubernetes-patch-strategy": "merge" + }, + "generateName": { + "description": "GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.\n\nIf this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).\n\nApplied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency", + "type": "string" + }, + "generation": { + "description": "A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.", + "type": "integer", + "format": "int64" + }, + "initializers": { + "description": "An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to observe uninitialized objects.\n\nWhen an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Initializers" + }, + "labels": { + "description": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "description": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names", + "type": "string" + }, + "namespace": { + "description": "Namespace defines the space within each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces", + "type": "string" + }, + "ownerReferences": { + "description": "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference" + }, + "x-kubernetes-patch-merge-key": "uid", + "x-kubernetes-patch-strategy": "merge" + }, + "resourceVersion": { + "description": "An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.\n\nPopulated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency", + "type": "string" + }, + "selfLink": { + "description": "SelfLink is a URL representing this object. Populated by the system. Read-only.", + "type": "string" + }, + "uid": { + "description": "UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.\n\nPopulated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference": { + "description": "OwnerReference contains enough information to let you identify an owning object. Currently, an owning object must be in the same namespace, so there is no namespace field.", + "type": "object", + "required": [ + "apiVersion", + "kind", + "name", + "uid" + ], + "properties": { + "apiVersion": { + "description": "API version of the referent.", + "type": "string" + }, + "blockOwnerDeletion": { + "description": "If true, AND if the owner has the \"foregroundDeletion\" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. Defaults to false. To set this field, a user needs \"delete\" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned.", + "type": "boolean" + }, + "controller": { + "description": "If true, this reference points to the managing controller.", + "type": "boolean" + }, + "kind": { + "description": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", + "type": "string" + }, + "uid": { + "description": "UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Patch": { + "description": "Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.", + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions": { + "description": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.", + "type": "object", + "properties": { + "uid": { + "description": "Specifies the target UID.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR": { + "description": "ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.", + "type": "object", + "required": [ + "clientCIDR", + "serverAddress" + ], + "properties": { + "clientCIDR": { + "description": "The CIDR with which clients can match their IP to figure out the server address that they should use.", + "type": "string" + }, + "serverAddress": { + "description": "Address of this server, suitable for a client that matches the above CIDR. This can be a hostname, hostname:port, IP or IP:port.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Status": { + "description": "Status is a return value for calls that don't return other objects.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "code": { + "description": "Suggested HTTP return code for this status, 0 if not set.", + "type": "integer", + "format": "int32" + }, + "details": { + "description": "Extended data associated with the reason. Each reason may define its own extended details. This field is optional and the data returned is not guaranteed to conform to any schema except that defined by the reason type.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "message": { + "description": "A human-readable description of the status of this operation.", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + }, + "reason": { + "description": "A machine-readable description of why this operation is in the \"Failure\" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it.", + "type": "string" + }, + "status": { + "description": "Status of the operation. One of: \"Success\" or \"Failure\". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Status", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause": { + "description": "StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered.", + "type": "object", + "properties": { + "field": { + "description": "The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.\n\nExamples:\n \"name\" - the field \"name\" on the current resource\n \"items[0].name\" - the field \"name\" on the first array entry in \"items\"", + "type": "string" + }, + "message": { + "description": "A human-readable description of the cause of the error. This field may be presented as-is to a reader.", + "type": "string" + }, + "reason": { + "description": "A machine-readable description of the cause of the error. If this value is empty there is no information available.", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails": { + "description": "StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.", + "type": "object", + "properties": { + "causes": { + "description": "The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause" + } + }, + "group": { + "description": "The group attribute of the resource associated with the status StatusReason.", + "type": "string" + }, + "kind": { + "description": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described).", + "type": "string" + }, + "retryAfterSeconds": { + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.", + "type": "integer", + "format": "int32" + }, + "uid": { + "description": "UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids", + "type": "string" + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Time": { + "type": "string", + "format": "date-time" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent": { + "description": "Event represents a single event to a watched resource.", + "type": "object", + "required": [ + "type", + "object" + ], + "properties": { + "object": { + "description": "Object is:\n * If Type is Added or Modified: the new state of the object.\n * If Type is Deleted: the state of the object immediately before deletion.\n * If Type is Error: *Status is recommended; other types may make sense\n depending on context.", + "type": "object" + }, + "type": { + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "admission.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "apps", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "apps", + "kind": "WatchEvent", + "version": "v1beta2" + }, + { + "group": "authentication.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "authentication.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "autoscaling", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "autoscaling", + "kind": "WatchEvent", + "version": "v2alpha1" + }, + { + "group": "batch", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "batch", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "batch", + "kind": "WatchEvent", + "version": "v2alpha1" + }, + { + "group": "certificates.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "extensions", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "federation", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "imagepolicy.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "networking.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "policy", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "scheduling.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "settings.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "storage.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "storage.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + } + ] + }, + "io.k8s.apimachinery.pkg.util.intstr.IntOrString": { + "type": "string", + "format": "int-or-string" + }, + "io.k8s.apimachinery.pkg.version.Info": { + "description": "Info contains versioning information. how we'll want to distribute that information.", + "type": "object", + "required": [ + "major", + "minor", + "gitVersion", + "gitCommit", + "gitTreeState", + "buildDate", + "goVersion", + "compiler", + "platform" + ], + "properties": { + "buildDate": { + "type": "string" + }, + "compiler": { + "type": "string" + }, + "gitCommit": { + "type": "string" + }, + "gitTreeState": { + "type": "string" + }, + "gitVersion": { + "type": "string" + }, + "goVersion": { + "type": "string" + }, + "major": { + "type": "string" + }, + "minor": { + "type": "string" + }, + "platform": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "BearerToken": { + "description": "Bearer Token authentication", + "type": "apiKey", + "name": "authorization", + "in": "header" + } + }, + "security": [ + { + "BearerToken": [] + } + ] +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/testing/openapi.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/testing/openapi.go new file mode 100644 index 000000000..bc280a198 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/testing/openapi.go @@ -0,0 +1,68 @@ +/* +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 testing + +import ( + "io/ioutil" + "os" + "sync" + + yaml "gopkg.in/yaml.v2" + + "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/googleapis/gnostic/compiler" +) + +// Fake opens and returns a openapi swagger from a file Path. It will +// parse only once and then return the same copy everytime. +type Fake struct { + Path string + + once sync.Once + document *openapi_v2.Document + err error +} + +// OpenAPISchema returns the openapi document and a potential error. +func (f *Fake) OpenAPISchema() (*openapi_v2.Document, error) { + f.once.Do(func() { + _, err := os.Stat(f.Path) + if err != nil { + f.err = err + return + } + spec, err := ioutil.ReadFile(f.Path) + if err != nil { + f.err = err + return + } + var info yaml.MapSlice + err = yaml.Unmarshal(spec, &info) + if err != nil { + f.err = err + return + } + f.document, f.err = openapi_v2.NewDocument(info, compiler.NewContext("$root", nil)) + }) + return f.document, f.err +} + +type Empty struct{} + +func (Empty) OpenAPISchema() (*openapi_v2.Document, error) { + return nil, nil +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/errors.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/errors.go new file mode 100644 index 000000000..b1aa8c008 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/errors.go @@ -0,0 +1,79 @@ +/* +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 validation + +import ( + "fmt" +) + +type errors struct { + errors []error +} + +func (e *errors) Errors() []error { + return e.errors +} + +func (e *errors) AppendErrors(err ...error) { + e.errors = append(e.errors, err...) +} + +type ValidationError struct { + Path string + Err error +} + +func (e ValidationError) Error() string { + return fmt.Sprintf("ValidationError(%s): %v", e.Path, e.Err) +} + +type InvalidTypeError struct { + Path string + Expected string + Actual string +} + +func (e InvalidTypeError) Error() string { + return fmt.Sprintf("invalid type for %s: got %q, expected %q", e.Path, e.Actual, e.Expected) +} + +type MissingRequiredFieldError struct { + Path string + Field string +} + +func (e MissingRequiredFieldError) Error() string { + return fmt.Sprintf("missing required field %q in %s", e.Field, e.Path) +} + +type UnknownFieldError struct { + Path string + Field string +} + +func (e UnknownFieldError) Error() string { + return fmt.Sprintf("unknown field %q in %s", e.Field, e.Path) +} + +type InvalidObjectTypeError struct { + Path string + Type string +} + +func (e InvalidObjectTypeError) Error() string { + return fmt.Sprintf("unknown object type %q in %s", e.Type, e.Path) +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/types.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/types.go new file mode 100644 index 000000000..bbbdd4f61 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/types.go @@ -0,0 +1,298 @@ +/* +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 validation + +import ( + "reflect" + "sort" + + "k8s.io/kube-openapi/pkg/util/proto" +) + +type validationItem interface { + proto.SchemaVisitor + + Errors() []error + Path() *proto.Path +} + +type baseItem struct { + errors errors + path proto.Path +} + +// Errors returns the list of errors found for this item. +func (item *baseItem) Errors() []error { + return item.errors.Errors() +} + +// AddValidationError wraps the given error into a ValidationError and +// attaches it to this item. +func (item *baseItem) AddValidationError(err error) { + item.errors.AppendErrors(ValidationError{Path: item.path.String(), Err: err}) +} + +// AddError adds a regular (non-validation related) error to the list. +func (item *baseItem) AddError(err error) { + item.errors.AppendErrors(err) +} + +// CopyErrors adds a list of errors to this item. This is useful to copy +// errors from subitems. +func (item *baseItem) CopyErrors(errs []error) { + item.errors.AppendErrors(errs...) +} + +// Path returns the path of this item, helps print useful errors. +func (item *baseItem) Path() *proto.Path { + return &item.path +} + +// mapItem represents a map entry in the yaml. +type mapItem struct { + baseItem + + Map map[string]interface{} +} + +func (item *mapItem) sortedKeys() []string { + sortedKeys := []string{} + for key := range item.Map { + sortedKeys = append(sortedKeys, key) + } + sort.Strings(sortedKeys) + return sortedKeys +} + +var _ validationItem = &mapItem{} + +func (item *mapItem) VisitPrimitive(schema *proto.Primitive) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: schema.Type, Actual: "map"}) +} + +func (item *mapItem) VisitArray(schema *proto.Array) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "array", Actual: "map"}) +} + +func (item *mapItem) VisitMap(schema *proto.Map) { + for _, key := range item.sortedKeys() { + subItem, err := itemFactory(item.Path().FieldPath(key), item.Map[key]) + if err != nil { + item.AddError(err) + continue + } + schema.SubType.Accept(subItem) + item.CopyErrors(subItem.Errors()) + } +} + +func (item *mapItem) VisitKind(schema *proto.Kind) { + // Verify each sub-field. + for _, key := range item.sortedKeys() { + if item.Map[key] == nil { + continue + } + subItem, err := itemFactory(item.Path().FieldPath(key), item.Map[key]) + if err != nil { + item.AddError(err) + continue + } + if _, ok := schema.Fields[key]; !ok { + item.AddValidationError(UnknownFieldError{Path: schema.GetPath().String(), Field: key}) + continue + } + schema.Fields[key].Accept(subItem) + item.CopyErrors(subItem.Errors()) + } + + // Verify that all required fields are present. + for _, required := range schema.RequiredFields { + if v, ok := item.Map[required]; !ok || v == nil { + item.AddValidationError(MissingRequiredFieldError{Path: schema.GetPath().String(), Field: required}) + } + } +} + +func (item *mapItem) VisitArbitrary(schema *proto.Arbitrary) { +} + +func (item *mapItem) VisitReference(schema proto.Reference) { + // passthrough + schema.SubSchema().Accept(item) +} + +// arrayItem represents a yaml array. +type arrayItem struct { + baseItem + + Array []interface{} +} + +var _ validationItem = &arrayItem{} + +func (item *arrayItem) VisitPrimitive(schema *proto.Primitive) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: schema.Type, Actual: "array"}) +} + +func (item *arrayItem) VisitArray(schema *proto.Array) { + for i, v := range item.Array { + path := item.Path().ArrayPath(i) + if v == nil { + item.AddValidationError(InvalidObjectTypeError{Type: "nil", Path: path.String()}) + continue + } + subItem, err := itemFactory(path, v) + if err != nil { + item.AddError(err) + continue + } + schema.SubType.Accept(subItem) + item.CopyErrors(subItem.Errors()) + } +} + +func (item *arrayItem) VisitMap(schema *proto.Map) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: "array"}) +} + +func (item *arrayItem) VisitKind(schema *proto.Kind) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: "array"}) +} + +func (item *arrayItem) VisitArbitrary(schema *proto.Arbitrary) { +} + +func (item *arrayItem) VisitReference(schema proto.Reference) { + // passthrough + schema.SubSchema().Accept(item) +} + +// primitiveItem represents a yaml value. +type primitiveItem struct { + baseItem + + Value interface{} + Kind string +} + +var _ validationItem = &primitiveItem{} + +func (item *primitiveItem) VisitPrimitive(schema *proto.Primitive) { + // Some types of primitives can match more than one (a number + // can be a string, but not the other way around). Return from + // the switch if we have a valid possible type conversion + // NOTE(apelisse): This logic is blindly copied from the + // existing swagger logic, and I'm not sure I agree with it. + switch schema.Type { + case proto.Boolean: + switch item.Kind { + case proto.Boolean: + return + } + case proto.Integer: + switch item.Kind { + case proto.Integer, proto.Number: + return + } + case proto.Number: + switch item.Kind { + case proto.Number: + return + } + case proto.String: + return + } + + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: schema.Type, Actual: item.Kind}) +} + +func (item *primitiveItem) VisitArray(schema *proto.Array) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "array", Actual: item.Kind}) +} + +func (item *primitiveItem) VisitMap(schema *proto.Map) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: item.Kind}) +} + +func (item *primitiveItem) VisitKind(schema *proto.Kind) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: item.Kind}) +} + +func (item *primitiveItem) VisitArbitrary(schema *proto.Arbitrary) { +} + +func (item *primitiveItem) VisitReference(schema proto.Reference) { + // passthrough + schema.SubSchema().Accept(item) +} + +// itemFactory creates the relevant item type/visitor based on the current yaml type. +func itemFactory(path proto.Path, v interface{}) (validationItem, error) { + // We need to special case for no-type fields in yaml (e.g. empty item in list) + if v == nil { + return nil, InvalidObjectTypeError{Type: "nil", Path: path.String()} + } + kind := reflect.TypeOf(v).Kind() + switch kind { + case reflect.Bool: + return &primitiveItem{ + baseItem: baseItem{path: path}, + Value: v, + Kind: proto.Boolean, + }, nil + case reflect.Int, + reflect.Int8, + reflect.Int16, + reflect.Int32, + reflect.Int64, + reflect.Uint, + reflect.Uint8, + reflect.Uint16, + reflect.Uint32, + reflect.Uint64: + return &primitiveItem{ + baseItem: baseItem{path: path}, + Value: v, + Kind: proto.Integer, + }, nil + case reflect.Float32, + reflect.Float64: + return &primitiveItem{ + baseItem: baseItem{path: path}, + Value: v, + Kind: proto.Number, + }, nil + case reflect.String: + return &primitiveItem{ + baseItem: baseItem{path: path}, + Value: v, + Kind: proto.String, + }, nil + case reflect.Array, + reflect.Slice: + return &arrayItem{ + baseItem: baseItem{path: path}, + Array: v.([]interface{}), + }, nil + case reflect.Map: + return &mapItem{ + baseItem: baseItem{path: path}, + Map: v.(map[string]interface{}), + }, nil + } + return nil, InvalidObjectTypeError{Type: kind.String(), Path: path.String()} +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation.go new file mode 100644 index 000000000..35310f637 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation.go @@ -0,0 +1,30 @@ +/* +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 validation + +import ( + "k8s.io/kube-openapi/pkg/util/proto" +) + +func ValidateModel(obj interface{}, schema proto.Schema, name string) []error { + rootValidation, err := itemFactory(proto.NewPath(name), obj) + if err != nil { + return []error{err} + } + schema.Accept(rootValidation) + return rootValidation.Errors() +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation_suite_test.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation_suite_test.go new file mode 100644 index 000000000..30e4381f9 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation_suite_test.go @@ -0,0 +1,49 @@ +/* +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 validation + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/config" + . "github.com/onsi/ginkgo/types" + . "github.com/onsi/gomega" + + "fmt" + "testing" +) + +func TestOpenapi(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecsWithDefaultAndCustomReporters(t, "Openapi Suite", []Reporter{newlineReporter{}}) +} + +// Print a newline after the default newlineReporter due to issue +// https://github.com/jstemmer/go-junit-report/issues/31 +type newlineReporter struct{} + +func (newlineReporter) SpecSuiteWillBegin(config GinkgoConfigType, summary *SuiteSummary) {} + +func (newlineReporter) BeforeSuiteDidRun(setupSummary *SetupSummary) {} + +func (newlineReporter) AfterSuiteDidRun(setupSummary *SetupSummary) {} + +func (newlineReporter) SpecWillRun(specSummary *SpecSummary) {} + +func (newlineReporter) SpecDidComplete(specSummary *SpecSummary) {} + +// SpecSuiteDidEnd Prints a newline between "35 Passed | 0 Failed | 0 Pending | 0 Skipped" and "--- PASS:" +func (newlineReporter) SpecSuiteDidEnd(summary *SuiteSummary) { fmt.Printf("\n") } diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation_test.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation_test.go new file mode 100644 index 000000000..dee2eb701 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation_test.go @@ -0,0 +1,369 @@ +/* +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 validation_test + +import ( + "fmt" + "path/filepath" + + "github.com/ghodss/yaml" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "k8s.io/kube-openapi/pkg/util/proto" + "k8s.io/kube-openapi/pkg/util/proto/testing" + "k8s.io/kube-openapi/pkg/util/proto/validation" +) + +var fakeSchema = testing.Fake{Path: filepath.Join("..", "testdata", "swagger.json")} + +func Validate(models proto.Models, model string, data string) []error { + var obj interface{} + if err := yaml.Unmarshal([]byte(data), &obj); err != nil { + return []error{fmt.Errorf("pre-validation: failed to parse yaml: %v", err)} + } + schema := models.LookupModel(model) + if schema == nil { + return []error{fmt.Errorf("pre-validation: couldn't find model %s", model)} + } + + return validation.ValidateModel(obj, schema, model) +} + +var _ = Describe("resource validation using OpenAPI Schema", func() { + var models proto.Models + BeforeEach(func() { + s, err := fakeSchema.OpenAPISchema() + Expect(err).To(BeNil()) + models, err = proto.NewOpenAPIData(s) + Expect(err).To(BeNil()) + }) + + It("finds Deployment in Schema and validates it", func() { + err := Validate(models, "io.k8s.api.apps.v1beta1.Deployment", ` +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + name: redis-master + name: name +spec: + replicas: 1 + template: + metadata: + labels: + app: redis + spec: + containers: + - image: redis + name: redis +`) + Expect(err).To(BeNil()) + }) + + It("validates a valid pod", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +apiVersion: v1 +kind: Pod +metadata: + labels: + name: redis-master + name: name +spec: + containers: + - args: + - this + - is + - an + - ok + - command + image: gcr.io/fake_project/fake_image:fake_tag + name: master +`) + Expect(err).To(BeNil()) + }) + + It("finds invalid command (string instead of []string) in Json Pod", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +{ + "kind": "Pod", + "apiVersion": "v1", + "metadata": { + "name": "name", + "labels": { + "name": "redis-master" + } + }, + "spec": { + "containers": [ + { + "name": "master", + "image": "gcr.io/fake_project/fake_image:fake_tag", + "args": "this is a bad command" + } + ] + } +} +`) + Expect(err).To(Equal([]error{ + validation.ValidationError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0].args", + Err: validation.InvalidTypeError{ + Path: "io.k8s.api.core.v1.Container.args", + Expected: "array", + Actual: "string", + }, + }, + })) + }) + + It("fails because hostPort is string instead of int", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +{ + "kind": "Pod", + "apiVersion": "v1", + "metadata": { + "name": "apache-php", + "labels": { + "name": "apache-php" + } + }, + "spec": { + "volumes": [{ + "name": "shared-disk" + }], + "containers": [ + { + "name": "apache-php", + "image": "gcr.io/fake_project/fake_image:fake_tag", + "ports": [ + { + "name": "apache", + "hostPort": "13380", + "containerPort": 80, + "protocol": "TCP" + } + ], + "volumeMounts": [ + { + "name": "shared-disk", + "mountPath": "/var/www/html" + } + ] + } + ] + } +} +`) + + Expect(err).To(Equal([]error{ + validation.ValidationError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0].ports[0].hostPort", + Err: validation.InvalidTypeError{ + Path: "io.k8s.api.core.v1.ContainerPort.hostPort", + Expected: "integer", + Actual: "string", + }, + }, + })) + + }) + + It("fails because volume is not an array of object", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +{ + "kind": "Pod", + "apiVersion": "v1", + "metadata": { + "name": "apache-php", + "labels": { + "name": "apache-php" + } + }, + "spec": { + "volumes": [ + "name": "shared-disk" + ], + "containers": [ + { + "name": "apache-php", + "image": "gcr.io/fake_project/fake_image:fake_tag", + "ports": [ + { + "name": "apache", + "hostPort": 13380, + "containerPort": 80, + "protocol": "TCP" + } + ], + "volumeMounts": [ + { + "name": "shared-disk", + "mountPath": "/var/www/html" + } + ] + } + ] + } +} +`) + Expect(err).To(BeNil()) + }) + + It("fails because some string lists have empty strings", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +apiVersion: v1 +kind: Pod +metadata: + labels: + name: redis-master + name: name +spec: + containers: + - image: gcr.io/fake_project/fake_image:fake_tag + name: master + args: + - + command: + - +`) + + Expect(err).To(Equal([]error{ + validation.ValidationError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0].args", + Err: validation.InvalidObjectTypeError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0].args[0]", + Type: "nil", + }, + }, + validation.ValidationError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0].command", + Err: validation.InvalidObjectTypeError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0].command[0]", + Type: "nil", + }, + }, + })) + }) + + It("fails if required fields are missing", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +apiVersion: v1 +kind: Pod +metadata: + labels: + name: redis-master + name: name +spec: + containers: + - command: ["my", "command"] +`) + + Expect(err).To(Equal([]error{ + validation.ValidationError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0]", + Err: validation.MissingRequiredFieldError{ + Path: "io.k8s.api.core.v1.Container", + Field: "name", + }, + }, + validation.ValidationError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0]", + Err: validation.MissingRequiredFieldError{ + Path: "io.k8s.api.core.v1.Container", + Field: "image", + }, + }, + })) + }) + + It("fails if required fields are empty", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +apiVersion: v1 +kind: Pod +metadata: + labels: + name: redis-master + name: name +spec: + containers: + - image: + name: +`) + + Expect(err).To(Equal([]error{ + validation.ValidationError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0]", + Err: validation.MissingRequiredFieldError{ + Path: "io.k8s.api.core.v1.Container", + Field: "name", + }, + }, + validation.ValidationError{ + Path: "io.k8s.api.core.v1.Pod.spec.containers[0]", + Err: validation.MissingRequiredFieldError{ + Path: "io.k8s.api.core.v1.Container", + Field: "image", + }, + }, + })) + }) + + It("is fine with empty non-mandatory fields", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +apiVersion: v1 +kind: Pod +metadata: + labels: + name: redis-master + name: name +spec: + containers: + - image: image + name: name + command: +`) + + Expect(err).To(BeNil()) + }) + + It("fails because apiVersion is not provided", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +kind: Pod +metadata: + name: name +spec: + containers: + - name: name + image: image +`) + Expect(err).To(BeNil()) + }) + + It("fails because apiVersion type is not string and kind is not provided", func() { + err := Validate(models, "io.k8s.api.core.v1.Pod", ` +apiVersion: 1 +metadata: + name: name +spec: + containers: + - name: name + image: image +`) + Expect(err).To(BeNil()) + }) +}) diff --git a/vendor/k8s.io/kube-openapi/pkg/util/sets/empty.go b/vendor/k8s.io/kube-openapi/pkg/util/sets/empty.go new file mode 100644 index 000000000..13303ea89 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/sets/empty.go @@ -0,0 +1,27 @@ +/* +Copyright 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. +*/ + +// Code generated by set-gen. DO NOT EDIT. + +// NOTE: This file is copied from k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/sets/empty.go +// because in Kubernetes we don't allowed vendor code to import staging code. See +// https://github.com/kubernetes/kube-openapi/pull/90 for more details. + +package sets + +// Empty is public since it is used by some internal API objects for conversions between external +// string arrays and internal sets, and conversion logic requires public types today. +type Empty struct{} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/sets/string.go b/vendor/k8s.io/kube-openapi/pkg/util/sets/string.go new file mode 100644 index 000000000..53f2bc12a --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/sets/string.go @@ -0,0 +1,207 @@ +/* +Copyright 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. +*/ + +// Code generated by set-gen. DO NOT EDIT. + +// NOTE: This file is copied from k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/sets/string.go +// because in Kubernetes we don't allowed vendor code to import staging code. See +// https://github.com/kubernetes/kube-openapi/pull/90 for more details. + +package sets + +import ( + "reflect" + "sort" +) + +// sets.String is a set of strings, implemented via map[string]struct{} for minimal memory consumption. +type String map[string]Empty + +// NewString creates a String from a list of values. +func NewString(items ...string) String { + ss := String{} + ss.Insert(items...) + return ss +} + +// StringKeySet creates a String from a keys of a map[string](? extends interface{}). +// If the value passed in is not actually a map, this will panic. +func StringKeySet(theMap interface{}) String { + v := reflect.ValueOf(theMap) + ret := String{} + + for _, keyValue := range v.MapKeys() { + ret.Insert(keyValue.Interface().(string)) + } + return ret +} + +// Insert adds items to the set. +func (s String) Insert(items ...string) { + for _, item := range items { + s[item] = Empty{} + } +} + +// Delete removes all items from the set. +func (s String) Delete(items ...string) { + for _, item := range items { + delete(s, item) + } +} + +// Has returns true if and only if item is contained in the set. +func (s String) Has(item string) bool { + _, contained := s[item] + return contained +} + +// HasAll returns true if and only if all items are contained in the set. +func (s String) HasAll(items ...string) bool { + for _, item := range items { + if !s.Has(item) { + return false + } + } + return true +} + +// HasAny returns true if any items are contained in the set. +func (s String) HasAny(items ...string) bool { + for _, item := range items { + if s.Has(item) { + return true + } + } + return false +} + +// Difference returns a set of objects that are not in s2 +// For example: +// s1 = {a1, a2, a3} +// s2 = {a1, a2, a4, a5} +// s1.Difference(s2) = {a3} +// s2.Difference(s1) = {a4, a5} +func (s String) Difference(s2 String) String { + result := NewString() + for key := range s { + if !s2.Has(key) { + result.Insert(key) + } + } + return result +} + +// Union returns a new set which includes items in either s1 or s2. +// For example: +// s1 = {a1, a2} +// s2 = {a3, a4} +// s1.Union(s2) = {a1, a2, a3, a4} +// s2.Union(s1) = {a1, a2, a3, a4} +func (s1 String) Union(s2 String) String { + result := NewString() + for key := range s1 { + result.Insert(key) + } + for key := range s2 { + result.Insert(key) + } + return result +} + +// Intersection returns a new set which includes the item in BOTH s1 and s2 +// For example: +// s1 = {a1, a2} +// s2 = {a2, a3} +// s1.Intersection(s2) = {a2} +func (s1 String) Intersection(s2 String) String { + var walk, other String + result := NewString() + if s1.Len() < s2.Len() { + walk = s1 + other = s2 + } else { + walk = s2 + other = s1 + } + for key := range walk { + if other.Has(key) { + result.Insert(key) + } + } + return result +} + +// IsSuperset returns true if and only if s1 is a superset of s2. +func (s1 String) IsSuperset(s2 String) bool { + for item := range s2 { + if !s1.Has(item) { + return false + } + } + return true +} + +// Equal returns true if and only if s1 is equal (as a set) to s2. +// Two sets are equal if their membership is identical. +// (In practice, this means same elements, order doesn't matter) +func (s1 String) Equal(s2 String) bool { + return len(s1) == len(s2) && s1.IsSuperset(s2) +} + +type sortableSliceOfString []string + +func (s sortableSliceOfString) Len() int { return len(s) } +func (s sortableSliceOfString) Less(i, j int) bool { return lessString(s[i], s[j]) } +func (s sortableSliceOfString) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// List returns the contents as a sorted string slice. +func (s String) List() []string { + res := make(sortableSliceOfString, 0, len(s)) + for key := range s { + res = append(res, key) + } + sort.Sort(res) + return []string(res) +} + +// UnsortedList returns the slice with contents in random order. +func (s String) UnsortedList() []string { + res := make([]string, 0, len(s)) + for key := range s { + res = append(res, key) + } + return res +} + +// Returns a single element from the set. +func (s String) PopAny() (string, bool) { + for key := range s { + s.Delete(key) + return key, true + } + var zeroValue string + return zeroValue, false +} + +// Len returns the size of the set. +func (s String) Len() int { + return len(s) +} + +func lessString(lhs, rhs string) bool { + return lhs < rhs +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/trie.go b/vendor/k8s.io/kube-openapi/pkg/util/trie.go new file mode 100644 index 000000000..a9a76c179 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/trie.go @@ -0,0 +1,79 @@ +/* +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 util + +// A simple trie implementation with Add and HasPrefix methods only. +type Trie struct { + children map[byte]*Trie + wordTail bool + word string +} + +// NewTrie creates a Trie and add all strings in the provided list to it. +func NewTrie(list []string) Trie { + ret := Trie{ + children: make(map[byte]*Trie), + wordTail: false, + } + for _, v := range list { + ret.Add(v) + } + return ret +} + +// Add adds a word to this trie +func (t *Trie) Add(v string) { + root := t + for _, b := range []byte(v) { + child, exists := root.children[b] + if !exists { + child = &Trie{ + children: make(map[byte]*Trie), + wordTail: false, + } + root.children[b] = child + } + root = child + } + root.wordTail = true + root.word = v +} + +// HasPrefix returns true of v has any of the prefixes stored in this trie. +func (t *Trie) HasPrefix(v string) bool { + _, has := t.GetPrefix(v) + return has +} + +// GetPrefix is like HasPrefix but return the prefix in case of match or empty string otherwise. +func (t *Trie) GetPrefix(v string) (string, bool) { + root := t + if root.wordTail { + return root.word, true + } + for _, b := range []byte(v) { + child, exists := root.children[b] + if !exists { + return "", false + } + if child.wordTail { + return child.word, true + } + root = child + } + return "", false +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/util.go b/vendor/k8s.io/kube-openapi/pkg/util/util.go new file mode 100644 index 000000000..c5c42cd44 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/util.go @@ -0,0 +1,59 @@ +/* +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 util + +import ( + "reflect" + "strings" +) + +// ToCanonicalName converts Golang package/type name into canonical OpenAPI name. +// Examples: +// Input: k8s.io/api/core/v1.Pod +// Output: io.k8s.api.core.v1.Pod +// +// Input: k8s.io/api/core/v1 +// Output: io.k8s.api.core.v1 +func ToCanonicalName(name string) string { + nameParts := strings.Split(name, "/") + // Reverse first part. e.g., io.k8s... instead of k8s.io... + if len(nameParts) > 0 && strings.Contains(nameParts[0], ".") { + parts := strings.Split(nameParts[0], ".") + for i, j := 0, len(parts)-1; i < j; i, j = i+1, j-1 { + parts[i], parts[j] = parts[j], parts[i] + } + nameParts[0] = strings.Join(parts, ".") + } + return strings.Join(nameParts, ".") +} + +// GetCanonicalTypeName will find the canonical type name of a sample object, removing +// the "vendor" part of the path +func GetCanonicalTypeName(model interface{}) string { + t := reflect.TypeOf(model) + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + if t.PkgPath() == "" { + return t.Name() + } + path := t.PkgPath() + if strings.Contains(path, "/vendor/") { + path = path[strings.Index(path, "/vendor/")+len("/vendor/"):] + } + return path + "." + t.Name() +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/util_test.go b/vendor/k8s.io/kube-openapi/pkg/util/util_test.go new file mode 100644 index 000000000..43b9b4048 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/util_test.go @@ -0,0 +1,58 @@ +/* +Copyright 2018 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 ( + "reflect" + "testing" +) + +func TestCanonicalName(t *testing.T) { + + var tests = []struct { + input string + expected string + }{ + {"k8s.io/api/core/v1.Pod", "io.k8s.api.core.v1.Pod"}, + {"k8s.io/api/networking/v1/NetworkPolicy", "io.k8s.api.networking.v1.NetworkPolicy"}, + {"k8s.io/api/apps/v1beta2.Scale", "io.k8s.api.apps.v1beta2.Scale"}, + {"servicecatalog.k8s.io/foo/bar/v1alpha1.Baz", "io.k8s.servicecatalog.foo.bar.v1alpha1.Baz"}, + } + for _, test := range tests { + if got := ToCanonicalName(test.input); got != test.expected { + t.Errorf("ToCanonicalName(%q) = %v", test.input, got) + } + } +} + +type TestType struct{} + +func TestGetCanonicalTypeName(t *testing.T) { + + var tests = []struct { + input interface{} + expected string + }{ + {TestType{}, "k8s.io/kube-openapi/pkg/util.TestType"}, + {&TestType{}, "k8s.io/kube-openapi/pkg/util.TestType"}, + } + for _, test := range tests { + if got := GetCanonicalTypeName(test.input); got != test.expected { + t.Errorf("GetCanonicalTypeName(%q) = %v", reflect.TypeOf(test.input), got) + } + } +} diff --git a/vendor/k8s.io/kube-openapi/test/integration/README.md b/vendor/k8s.io/kube-openapi/test/integration/README.md new file mode 100644 index 000000000..5a5de24f2 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/README.md @@ -0,0 +1,31 @@ +# Kube OpenAPI Integration Tests + +## Running the integration tests + +Within the current directory: + +```bash +$ go test -v . +``` + +## Generating the golden Swagger definition file and API rule violation report + +First, run the generator to create `openapi_generated.go` file which specifies +the `OpenAPIDefinition` for each type, and generate the golden API rule +violation report file . Note that if you do not pass a report +filename (`./testdata/golden.report` in the command below) to let the generator +to print API rule violations to the file, the generator will return error to stderr +on API rule violations. + +```bash +$ go run ../../cmd/openapi-gen/openapi-gen.go -i "./testdata/listtype,./testdata/dummytype" -o pkg -p generated -O openapi_generated -r ./testdata/golden.report +``` +The generated file `pkg/generated/openapi_generated.go` should have been created. + +Next, run the OpenAPI builder to create the Swagger file which includes +the definitions. The output file named `golden.json` will be output in +the current directory. + +```bash +$ go run builder/main.go testdata/golden.json +``` diff --git a/vendor/k8s.io/kube-openapi/test/integration/builder/main.go b/vendor/k8s.io/kube-openapi/test/integration/builder/main.go new file mode 100644 index 000000000..7008c574c --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/builder/main.go @@ -0,0 +1,85 @@ +/* +Copyright 2018 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 main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "os" + + "github.com/go-openapi/spec" + "k8s.io/kube-openapi/pkg/builder" + "k8s.io/kube-openapi/pkg/common" + "k8s.io/kube-openapi/test/integration/pkg/generated" +) + +// TODO: Change this to output the generated swagger to stdout. +const defaultSwaggerFile = "generated.json" + +func main() { + // Get the name of the generated swagger file from the args + // if it exists; otherwise use the default file name. + swaggerFilename := defaultSwaggerFile + if len(os.Args) > 1 { + swaggerFilename = os.Args[1] + } + + // Generate the definition names from the map keys returned + // from GetOpenAPIDefinitions. Anonymous function returning empty + // Ref is not used. + var defNames []string + for name, _ := range generated.GetOpenAPIDefinitions(func(name string) spec.Ref { + return spec.Ref{} + }) { + defNames = append(defNames, name) + } + + // Create a minimal builder config, then call the builder with the definition names. + config := createOpenAPIBuilderConfig() + config.GetDefinitions = generated.GetOpenAPIDefinitions + swagger, serr := builder.BuildOpenAPIDefinitionsForResources(config, defNames...) + if serr != nil { + log.Fatalf("ERROR: %s", serr.Error()) + } + + // Marshal the swagger spec into JSON, then write it out. + specBytes, err := json.MarshalIndent(swagger, " ", " ") + if err != nil { + panic(fmt.Sprintf("json marshal error: %s", err.Error())) + } + err = ioutil.WriteFile(swaggerFilename, specBytes, 0644) + if err != nil { + log.Fatalf("stdout write error: %s", err.Error()) + } +} + +// CreateOpenAPIBuilderConfig hard-codes some values in the API builder +// config for testing. +func createOpenAPIBuilderConfig() *common.Config { + return &common.Config{ + ProtocolList: []string{"https"}, + IgnorePrefixes: []string{"/swaggerapi"}, + Info: &spec.Info{ + InfoProps: spec.InfoProps{ + Title: "Integration Test", + Version: "1.0", + }, + }, + } +} diff --git a/vendor/k8s.io/kube-openapi/test/integration/integration_suite_test.go b/vendor/k8s.io/kube-openapi/test/integration/integration_suite_test.go new file mode 100644 index 000000000..93d86d555 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/integration_suite_test.go @@ -0,0 +1,111 @@ +/* +Copyright 2018 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 integration + +import ( + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/onsi/gomega/gexec" +) + +const ( + testdataDir = "./testdata" + inputDir = testdataDir + "/listtype" + "," + testdataDir + "/dummytype" + outputBase = "pkg" + outputPackage = "generated" + outputBaseFilename = "openapi_generated" + generatedSwaggerFile = "generated.json" + generatedReportFile = "generated.report" + goldenSwaggerFile = "golden.json" + goldenReportFile = "golden.report" + timeoutSeconds = 5.0 +) + +func TestGenerators(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Integration Test Suite") +} + +var _ = Describe("Open API Definitions Generation", func() { + + var ( + tempDir string + terr error + generatedSwaggerDef string + generatedReportDef string + ) + + BeforeSuite(func() { + // Create a temporary directory for generated swagger files. + tempDir, terr = ioutil.TempDir("", "openapi") + Expect(terr).ShouldNot(HaveOccurred()) + // Build the OpenAPI code generator. + binary_path, berr := gexec.Build("../../cmd/openapi-gen/openapi-gen.go") + Expect(berr).ShouldNot(HaveOccurred()) + generatedReportDef = filepath.Join(tempDir, generatedReportFile) + // Run the OpenAPI code generator, creating OpenAPIDefinition code + // to be compiled into builder. + command := exec.Command(binary_path, "-i", inputDir, "-o", outputBase, "-p", outputPackage, "-O", outputBaseFilename, "-r", generatedReportDef) + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(session, timeoutSeconds).Should(gexec.Exit(0)) + + // Create the OpenAPI swagger builder. + binary_path, berr = gexec.Build("./builder/main.go") + Expect(berr).ShouldNot(HaveOccurred()) + // Execute the builder, generating an OpenAPI swagger file with definitions. + generatedSwaggerDef = filepath.Join(tempDir, generatedSwaggerFile) + command = exec.Command(binary_path, generatedSwaggerDef) + command.Dir = testdataDir + session, err = gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(session, timeoutSeconds).Should(gexec.Exit(0)) + }) + + AfterSuite(func() { + os.RemoveAll(tempDir) + gexec.CleanupBuildArtifacts() + }) + + Describe("Validating OpenAPI Definition Generation", func() { + It("Generated OpenAPI swagger definitions should match golden files", func() { + // Diff the generated swagger against the golden swagger. Exit code should be zero. + command := exec.Command("diff", goldenSwaggerFile, generatedSwaggerDef) + command.Dir = testdataDir + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(session, timeoutSeconds).Should(gexec.Exit(0)) + }) + }) + + Describe("Validating API Rule Violation Reporting", func() { + It("Generated API rule violations should match golden report files", func() { + // Diff the generated report against the golden report. Exit code should be zero. + command := exec.Command("diff", goldenReportFile, generatedReportDef) + command.Dir = testdataDir + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(session, timeoutSeconds).Should(gexec.Exit(0)) + }) + }) +}) diff --git a/vendor/k8s.io/kube-openapi/test/integration/pkg/generated/openapi_generated.go b/vendor/k8s.io/kube-openapi/test/integration/pkg/generated/openapi_generated.go new file mode 100644 index 000000000..43705ccec --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/pkg/generated/openapi_generated.go @@ -0,0 +1,25 @@ +/* +Copyright 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 generated + +import ( + common "k8s.io/kube-openapi/pkg/common" +) + +func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { + return map[string]common.OpenAPIDefinition{} +} diff --git a/vendor/k8s.io/kube-openapi/test/integration/testdata/dummytype/alpha.go b/vendor/k8s.io/kube-openapi/test/integration/testdata/dummytype/alpha.go new file mode 100644 index 000000000..f3e50b4a5 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/testdata/dummytype/alpha.go @@ -0,0 +1,36 @@ +// The package is intended for testing the openapi-gen API rule +// checker. The API rule violations are in format of: +// +// `{rule-name},{package},{type},{(optional) field}` +// +// The checker should sort the violations before +// reporting to a file or stderr. +// +// We have the dummytype package separately from the listtype +// package to test the sorting behavior on package level, e.g. +// +// -i "./testdata/listtype,./testdata/dummytype" +// -i "./testdata/dummytype,./testdata/listtype" +// +// The violations from dummytype should always come first in +// report. + +package dummytype + +// +k8s:openapi-gen=true +type Foo struct { + Second string + First int +} + +// +k8s:openapi-gen=true +type Bar struct { + ViolationBehind bool + Violation bool +} + +// +k8s:openapi-gen=true +type Baz struct { + Violation bool + ViolationBehind bool +} diff --git a/vendor/k8s.io/kube-openapi/test/integration/testdata/dummytype/beta.go b/vendor/k8s.io/kube-openapi/test/integration/testdata/dummytype/beta.go new file mode 100644 index 000000000..c029f40e1 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/testdata/dummytype/beta.go @@ -0,0 +1,24 @@ +// The package is intended for testing the openapi-gen API rule +// checker. The API rule violations are in format of: +// +// `{rule-name},{package},{type},{(optional) field}` +// +// The checker should sort the violations before +// reporting to a file or stderr. +// +// We have the dummytype package separately from the listtype +// package to test the sorting behavior on package level, e.g. +// +// -i "./testdata/listtype,./testdata/dummytype" +// -i "./testdata/dummytype,./testdata/listtype" +// +// The violations from dummytype should always come first in +// report. + +package dummytype + +// +k8s:openapi-gen=true +type Waldo struct { + First int + Second string +} diff --git a/vendor/k8s.io/kube-openapi/test/integration/testdata/golden.json b/vendor/k8s.io/kube-openapi/test/integration/testdata/golden.json new file mode 100644 index 000000000..a8980c144 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/testdata/golden.json @@ -0,0 +1,126 @@ +{ + "swagger": "2.0", + "info": { + "title": "Integration Test", + "version": "1.0" + }, + "paths": {}, + "definitions": { + "dummytype.Bar": { + "required": [ + "ViolationBehind", + "Violation" + ], + "properties": { + "Violation": { + "type": "boolean" + }, + "ViolationBehind": { + "type": "boolean" + } + } + }, + "dummytype.Baz": { + "required": [ + "Violation", + "ViolationBehind" + ], + "properties": { + "Violation": { + "type": "boolean" + }, + "ViolationBehind": { + "type": "boolean" + } + } + }, + "dummytype.Foo": { + "required": [ + "Second", + "First" + ], + "properties": { + "First": { + "type": "integer", + "format": "int32" + }, + "Second": { + "type": "string" + } + } + }, + "dummytype.Waldo": { + "required": [ + "First", + "Second" + ], + "properties": { + "First": { + "type": "integer", + "format": "int32" + }, + "Second": { + "type": "string" + } + } + }, + "listtype.AtomicList": { + "required": [ + "Field" + ], + "properties": { + "Field": { + "type": "array", + "items": { + "type": "string" + }, + "x-kubernetes-list-type": "atomic" + } + } + }, + "listtype.Item": { + "required": [ + "Protocol", + "Port" + ], + "properties": { + "Port": { + "type": "integer", + "format": "int32" + }, + "Protocol": { + "type": "string" + } + } + }, + "listtype.MapList": { + "required": [ + "Field" + ], + "properties": { + "Field": { + "type": "array", + "items": { + "$ref": "#/definitions/listtype.Item" + }, + "x-kubernetes-list-map-keys": "port", + "x-kubernetes-list-type": "map" + } + } + }, + "listtype.SetList": { + "required": [ + "Field" + ], + "properties": { + "Field": { + "type": "array", + "items": { + "type": "string" + }, + "x-kubernetes-list-type": "set" + } + } + } + } + } \ No newline at end of file diff --git a/vendor/k8s.io/kube-openapi/test/integration/testdata/golden.report b/vendor/k8s.io/kube-openapi/test/integration/testdata/golden.report new file mode 100644 index 000000000..d827030c9 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/testdata/golden.report @@ -0,0 +1,13 @@ +API rule violation: names_match,./testdata/dummytype,Bar,Violation +API rule violation: names_match,./testdata/dummytype,Bar,ViolationBehind +API rule violation: names_match,./testdata/dummytype,Baz,Violation +API rule violation: names_match,./testdata/dummytype,Baz,ViolationBehind +API rule violation: names_match,./testdata/dummytype,Foo,First +API rule violation: names_match,./testdata/dummytype,Foo,Second +API rule violation: names_match,./testdata/dummytype,Waldo,First +API rule violation: names_match,./testdata/dummytype,Waldo,Second +API rule violation: names_match,./testdata/listtype,AtomicList,Field +API rule violation: names_match,./testdata/listtype,Item,Port +API rule violation: names_match,./testdata/listtype,Item,Protocol +API rule violation: names_match,./testdata/listtype,MapList,Field +API rule violation: names_match,./testdata/listtype,SetList,Field diff --git a/vendor/k8s.io/kube-openapi/test/integration/testdata/listtype/atomic-list.go b/vendor/k8s.io/kube-openapi/test/integration/testdata/listtype/atomic-list.go new file mode 100644 index 000000000..9029ece01 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/testdata/listtype/atomic-list.go @@ -0,0 +1,7 @@ +package listtype + +// +k8s:openapi-gen=true +type AtomicList struct { + // +listType=atomic + Field []string +} diff --git a/vendor/k8s.io/kube-openapi/test/integration/testdata/listtype/map-list.go b/vendor/k8s.io/kube-openapi/test/integration/testdata/listtype/map-list.go new file mode 100644 index 000000000..65e4ebd92 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/testdata/listtype/map-list.go @@ -0,0 +1,14 @@ +package listtype + +// +k8s:openapi-gen=true +type MapList struct { + // +listType=map + // +listMapKey=port + Field []Item +} + +// +k8s:openapi-gen=true +type Item struct { + Protocol string + Port int +} diff --git a/vendor/k8s.io/kube-openapi/test/integration/testdata/listtype/set-list.go b/vendor/k8s.io/kube-openapi/test/integration/testdata/listtype/set-list.go new file mode 100644 index 000000000..bf7b27c53 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/test/integration/testdata/listtype/set-list.go @@ -0,0 +1,7 @@ +package listtype + +// +k8s:openapi-gen=true +type SetList struct { + // +listType=set + Field []string +} diff --git a/vendor/k8s.io/kubernetes/.github/ISSUE_TEMPLATE.md b/vendor/k8s.io/kubernetes/.github/ISSUE_TEMPLATE.md index d397f16b1..f6bf1e478 100644 --- a/vendor/k8s.io/kubernetes/.github/ISSUE_TEMPLATE.md +++ b/vendor/k8s.io/kubernetes/.github/ISSUE_TEMPLATE.md @@ -1,11 +1,13 @@ - **Is this a BUG REPORT or FEATURE REQUEST?**: -> Uncomment only one, leave it on its own line: +> Uncomment only one, leave it on its own line: > > /kind bug > /kind feature diff --git a/vendor/k8s.io/kubernetes/.github/OWNERS b/vendor/k8s.io/kubernetes/.github/OWNERS new file mode 100644 index 000000000..fb52e4625 --- /dev/null +++ b/vendor/k8s.io/kubernetes/.github/OWNERS @@ -0,0 +1,12 @@ +reviewers: + - castrojo + - cblecker + - grodrigues3 + - parispittman + - Phillels +approvers: + - castrojo + - cblecker + - grodrigues3 + - parispittman + - Phillels diff --git a/vendor/k8s.io/kubernetes/.github/PULL_REQUEST_TEMPLATE.md b/vendor/k8s.io/kubernetes/.github/PULL_REQUEST_TEMPLATE.md index 2ac1d28d9..58451ec71 100644 --- a/vendor/k8s.io/kubernetes/.github/PULL_REQUEST_TEMPLATE.md +++ b/vendor/k8s.io/kubernetes/.github/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,8 @@ **What this PR does / why we need it**: diff --git a/vendor/k8s.io/kubernetes/.gitignore b/vendor/k8s.io/kubernetes/.gitignore index 269a9d0ab..9aa7a78aa 100644 --- a/vendor/k8s.io/kubernetes/.gitignore +++ b/vendor/k8s.io/kubernetes/.gitignore @@ -114,6 +114,7 @@ zz_generated.openapi.go # make-related metadata /.make/ + # Just in time generated data in the source, should never be committed /test/e2e/generated/bindata.go diff --git a/vendor/k8s.io/kubernetes/CHANGELOG-1.10.md b/vendor/k8s.io/kubernetes/CHANGELOG-1.10.md deleted file mode 100644 index 6b9869512..000000000 --- a/vendor/k8s.io/kubernetes/CHANGELOG-1.10.md +++ /dev/null @@ -1,2338 +0,0 @@ - -- [v1.10.3](#v1103) - - [Downloads for v1.10.3](#downloads-for-v1103) - - [Client Binaries](#client-binaries) - - [Server Binaries](#server-binaries) - - [Node Binaries](#node-binaries) - - [Changelog since v1.10.2](#changelog-since-v1102) - - [Other notable changes](#other-notable-changes) -- [v1.10.2](#v1102) - - [Downloads for v1.10.2](#downloads-for-v1102) - - [Client Binaries](#client-binaries-1) - - [Server Binaries](#server-binaries-1) - - [Node Binaries](#node-binaries-1) - - [Changelog since v1.10.1](#changelog-since-v1101) - - [Other notable changes](#other-notable-changes-1) -- [v1.10.1](#v1101) - - [Downloads for v1.10.1](#downloads-for-v1101) - - [Client Binaries](#client-binaries-2) - - [Server Binaries](#server-binaries-2) - - [Node Binaries](#node-binaries-2) - - [Changelog since v1.10.0](#changelog-since-v1100) - - [Other notable changes](#other-notable-changes-2) -- [v1.10.0](#v1100) - - [Downloads for v1.10.0](#downloads-for-v1100) - - [Client Binaries](#client-binaries-3) - - [Server Binaries](#server-binaries-3) - - [Node Binaries](#node-binaries-3) - - [Major Themes](#major-themes) - - [Node](#node) - - [Storage](#storage) - - [Windows](#windows) - - [OpenStack](#openstack) - - [API-machinery](#api-machinery) - - [Auth](#auth) - - [Azure](#azure) - - [CLI](#cli) - - [Network](#network) - - [Before Upgrading](#before-upgrading) - - [Known Issues](#known-issues) - - [Deprecations](#deprecations) - - [Other Notable Changes](#other-notable-changes-3) - - [Apps](#apps) - - [AWS](#aws) - - [Auth](#auth-1) - - [CLI](#cli-1) - - [Cluster Lifecycle](#cluster-lifecycle) - - [GCP](#gcp) - - [Instrumentation](#instrumentation) - - [Node](#node-1) - - [OpenStack](#openstack-1) - - [Scalability](#scalability) - - [Storage](#storage-1) - - [Windows](#windows-1) - - [Autoscaling](#autoscaling) - - [API-Machinery](#api-machinery-1) - - [Network](#network-1) - - [Azure](#azure-1) - - [Scheduling](#scheduling) - - [Other changes](#other-changes) - - [Non-user-facing Changes](#non-user-facing-changes) - - [External Dependencies](#external-dependencies) -- [v1.10.0-rc.1](#v1100-rc1) - - [Downloads for v1.10.0-rc.1](#downloads-for-v1100-rc1) - - [Client Binaries](#client-binaries-4) - - [Server Binaries](#server-binaries-4) - - [Node Binaries](#node-binaries-4) - - [Changelog since v1.10.0-beta.4](#changelog-since-v1100-beta4) - - [Other notable changes](#other-notable-changes-4) -- [v1.10.0-beta.4](#v1100-beta4) - - [Downloads for v1.10.0-beta.4](#downloads-for-v1100-beta4) - - [Client Binaries](#client-binaries-5) - - [Server Binaries](#server-binaries-5) - - [Node Binaries](#node-binaries-5) - - [Changelog since v1.10.0-beta.3](#changelog-since-v1100-beta3) - - [Other notable changes](#other-notable-changes-5) -- [v1.10.0-beta.3](#v1100-beta3) - - [Downloads for v1.10.0-beta.3](#downloads-for-v1100-beta3) - - [Client Binaries](#client-binaries-6) - - [Server Binaries](#server-binaries-6) - - [Node Binaries](#node-binaries-6) - - [Changelog since v1.10.0-beta.2](#changelog-since-v1100-beta2) - - [Other notable changes](#other-notable-changes-6) -- [v1.10.0-beta.2](#v1100-beta2) - - [Downloads for v1.10.0-beta.2](#downloads-for-v1100-beta2) - - [Client Binaries](#client-binaries-7) - - [Server Binaries](#server-binaries-7) - - [Node Binaries](#node-binaries-7) - - [Changelog since v1.10.0-beta.1](#changelog-since-v1100-beta1) - - [Action Required](#action-required) - - [Other notable changes](#other-notable-changes-7) -- [v1.10.0-beta.1](#v1100-beta1) - - [Downloads for v1.10.0-beta.1](#downloads-for-v1100-beta1) - - [Client Binaries](#client-binaries-8) - - [Server Binaries](#server-binaries-8) - - [Node Binaries](#node-binaries-8) - - [Changelog since v1.10.0-alpha.3](#changelog-since-v1100-alpha3) - - [Action Required](#action-required-1) - - [Other notable changes](#other-notable-changes-8) -- [v1.10.0-alpha.3](#v1100-alpha3) - - [Downloads for v1.10.0-alpha.3](#downloads-for-v1100-alpha3) - - [Client Binaries](#client-binaries-9) - - [Server Binaries](#server-binaries-9) - - [Node Binaries](#node-binaries-9) - - [Changelog since v1.10.0-alpha.2](#changelog-since-v1100-alpha2) - - [Other notable changes](#other-notable-changes-9) -- [v1.10.0-alpha.2](#v1100-alpha2) - - [Downloads for v1.10.0-alpha.2](#downloads-for-v1100-alpha2) - - [Client Binaries](#client-binaries-10) - - [Server Binaries](#server-binaries-10) - - [Node Binaries](#node-binaries-10) - - [Changelog since v1.10.0-alpha.1](#changelog-since-v1100-alpha1) - - [Action Required](#action-required-2) - - [Other notable changes](#other-notable-changes-10) -- [v1.10.0-alpha.1](#v1100-alpha1) - - [Downloads for v1.10.0-alpha.1](#downloads-for-v1100-alpha1) - - [Client Binaries](#client-binaries-11) - - [Server Binaries](#server-binaries-11) - - [Node Binaries](#node-binaries-11) - - [Changelog since v1.9.0](#changelog-since-v190) - - [Action Required](#action-required-3) - - [Other notable changes](#other-notable-changes-11) - - - - - -# v1.10.3 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) - -## Downloads for v1.10.3 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes.tar.gz) | `c39d9c5a1cd3507c9464a1df12436ec005975a13980b47c451434c4e6de43a76` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-src.tar.gz) | `9106ebb70d016b2417cf239b62bdd6a85e927f2d010627aa64cfcf912fb0059b` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-darwin-386.tar.gz) | `0a98adaedf4734dd6a757fee062a10da389e5a7dd456ab335ad5189f9fbf5cf5` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-darwin-amd64.tar.gz) | `ef3a831e8778be0633e992a0acc876eea694a2149d7142e0e619c33d897ec0aa` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-linux-386.tar.gz) | `fd270522896cbbd61538deb64d21031983f9965084376cc3dd53c3e2aa72afec` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-linux-amd64.tar.gz) | `687a75e695dd9f5f38d727f27df9ecdbb04594a4082acdde2c852b289ccaaefa` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-linux-arm.tar.gz) | `449ea23eacb31f90cb8ad98ba18a0bc3cd3403281c0c06764cd7bab85aa6c09d` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-linux-arm64.tar.gz) | `74a4fe81159243393e47af19955aadefed3269476a18d90b1f1a394f69cc7f62` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-linux-ppc64le.tar.gz) | `239e685f8793a0f87612d19edadb9465aefe3814da13ebf6d1853b707c5626b8` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-linux-s390x.tar.gz) | `ca3b5f3a8c9c8e861baf309e5a68eda1946124b7ce75cddd78de45713729ee32` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-windows-386.tar.gz) | `5a3ea415339d57b669457601c957bc80cb3119c10d7d750355cdae8f1fe05763` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-client-windows-amd64.tar.gz) | `11b8d65c4ee813ce99f2d4df702d23fb90ab6a0d823ae70de5cc7d8468a06285` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-server-linux-amd64.tar.gz) | `c87f0b80a60e8d451cb0cc33819efe9e12fe971be8de200d8ca577f05d9bac82` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-server-linux-arm.tar.gz) | `1368ccd9ef57260ed60f7b91f6783af0efe0827910d409aa699a461fde89ce10` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-server-linux-arm64.tar.gz) | `1eb81d4d486add74281733fd3eae5f5a835aa2049f55d481a5f076863523229a` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-server-linux-ppc64le.tar.gz) | `7aa07397df4d786bda38cf1ae11f5c240477d784ba76524dd106c2d267ee6fe3` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-server-linux-s390x.tar.gz) | `c3725f1dc33a994beb0d99f01fd3d1d0b5120d3ff23c6db42ac36e76dfe3812d` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-node-linux-amd64.tar.gz) | `e0ab6d4759e72cba8f3676cb4789108ab4aaeb978939f1b80a1c0c5be9c4f6bf` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-node-linux-arm.tar.gz) | `a7f09a209e8689309dd3126349006206f3e851a1515fbbf811bc9809c7aefcd2` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-node-linux-arm64.tar.gz) | `c56e9e71284c94b4d2d272781937426330aff18dde8339573feb12ab1e106ebb` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-node-linux-ppc64le.tar.gz) | `42711c69cafa6fc15fb7b0c19429248a04ae043f9045999d868cc35b30148e41` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-node-linux-s390x.tar.gz) | `5ab986d2de922744b9fa87fdd5e557888615eb9ec24dec1f820d05e0ab51e249` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.3/kubernetes-node-windows-amd64.tar.gz) | `d69524ad0dc671a32b221e76b73968c316b58e16a2f0e762925350ddd9de393a` - -## Changelog since v1.10.2 - -### Other notable changes - -* Use inline func to ensure unlock is executed ([#61644](https://github.com/kubernetes/kubernetes/pull/61644), [@resouer](https://github.com/resouer)) -* Introduce truncating audit backend that can be enabled by passing --audit-log-truncate-enabled or --audit-webhook-truncate-enabled flag to the apiserver to limit the size of individual audit events and batches of events. ([#64024](https://github.com/kubernetes/kubernetes/pull/64024), [@loburm](https://github.com/loburm)) -* Fix memory cgroup notifications, and reduce associated log spam. ([#63220](https://github.com/kubernetes/kubernetes/pull/63220), [@dashpole](https://github.com/dashpole)) -* Cluster Autoscaler 1.2.2 (release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.2.2) ([#63974](https://github.com/kubernetes/kubernetes/pull/63974), [@aleksandra-malinowska](https://github.com/aleksandra-malinowska)) -* kubeadm - fix upgrades with external etcd ([#63925](https://github.com/kubernetes/kubernetes/pull/63925), [@detiber](https://github.com/detiber)) -* Restores the pre-1.10 behavior of the openstack cloud provider which uses the instance name as the Kubernetes Node name. This requires instances be named with RFC-1123 compatible names. ([#63903](https://github.com/kubernetes/kubernetes/pull/63903), [@liggitt](https://github.com/liggitt)) -* Re-enable nodeipam controller for external clouds. ([#63049](https://github.com/kubernetes/kubernetes/pull/63049), [@andrewsykim](https://github.com/andrewsykim)) -* kubelet: fix hangs in updating Node status after network interruptions/changes between the kubelet and API server ([#63492](https://github.com/kubernetes/kubernetes/pull/63492), [@liggitt](https://github.com/liggitt)) -* [fluentd-gcp addon] Use the logging agent's node name as the metadata agent URL. ([#63353](https://github.com/kubernetes/kubernetes/pull/63353), [@bmoyles0117](https://github.com/bmoyles0117)) -* Fixes bugs that make apiserver panic when aggregating valid but not well formed OpenAPI spec ([#63627](https://github.com/kubernetes/kubernetes/pull/63627), [@roycaihw](https://github.com/roycaihw)) -* fix local volume absolute path issue on Windows ([#62018](https://github.com/kubernetes/kubernetes/pull/62018), [@andyzhangx](https://github.com/andyzhangx)) -* Fixes issue where subpath readOnly mounts failed ([#63045](https://github.com/kubernetes/kubernetes/pull/63045), [@msau42](https://github.com/msau42)) -* Add MAX_PODS_PER_NODE env so that GCE/GKE user can use it to specify the default max pods per node for the cluster. IP_ALIAS_SIZE will be changed accordingly. Must have ip alias enabled. ([#63621](https://github.com/kubernetes/kubernetes/pull/63621), [@grayluck](https://github.com/grayluck)) -* corrects a race condition in bootstrapping aggregated cluster roles in new HA clusters ([#63761](https://github.com/kubernetes/kubernetes/pull/63761), [@liggitt](https://github.com/liggitt)) -* Fix stackdriver metrics for node memory using wrong metric type ([#63535](https://github.com/kubernetes/kubernetes/pull/63535), [@serathius](https://github.com/serathius)) -* Fix dockershim CreateContainer error handling ([#61965](https://github.com/kubernetes/kubernetes/pull/61965), [@Random-Liu](https://github.com/Random-Liu)) -* When updating /status subresource of a custom resource, only the value at the `.status` subpath for the update is considered. ([#63385](https://github.com/kubernetes/kubernetes/pull/63385), [@CaoShuFeng](https://github.com/CaoShuFeng)) -* Kubernetes version command line parameter in kubeadm has been updated to drop an unnecessary redirection from ci/latest.txt to ci-cross/latest.txt. Users should know exactly where the builds are stored on Google Cloud storage buckets from now on. For example for 1.9 and 1.10, users can specify ci/latest-1.9 and ci/latest-1.10 as the CI build jobs what build images correctly updates those. The CI jobs for master update the ci-cross/latest location, so if you are looking for latest master builds, then the correct parameter to use would be ci-cross/latest. ([#63504](https://github.com/kubernetes/kubernetes/pull/63504), [@dims](https://github.com/dims)) -* Azure VMSS: support VM names to contain the `_` character ([#63526](https://github.com/kubernetes/kubernetes/pull/63526), [@djsly](https://github.com/djsly)) -* Default mount propagation has changed from "HostToContainer" ("rslave" in Linux terminology) to "None" ("private") to match the behavior in 1.9 and earlier releases. "HostToContainer" as a default caused regressions in some pods. ([#62462](https://github.com/kubernetes/kubernetes/pull/62462), [@jsafrane](https://github.com/jsafrane)) -* Make volume usage metrics available for Cinder ([#62668](https://github.com/kubernetes/kubernetes/pull/62668), [@zetaab](https://github.com/zetaab)) -* Fix issue where on re-registration of device plugin, `allocatable` was not getting updated. This issue makes devices invisible to the Kubelet if device plugin restarts. Only work-around, if this fix is not there, is to restart the kubelet and then start device plugin. ([#63118](https://github.com/kubernetes/kubernetes/pull/63118), [@vikaschoudhary16](https://github.com/vikaschoudhary16)) - - - -# v1.10.2 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) - -## Downloads for v1.10.2 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes.tar.gz) | `1ff377ad005a5548f872f7534328dcc332c683e527f432708eddcc549a6ab880` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-src.tar.gz) | `175a33ad6dec11e86e022b57e5e3f11280c70a04a309b1b915f030697e789d89` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-darwin-386.tar.gz) | `95722e24ce02e4844563686f91773b053cf01ed66a46284a85f127a73528ae4c` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-darwin-amd64.tar.gz) | `3b5829a446b9eadae573c4d4e51dc69c1fe0af9453a88d0371095dd6560622bf` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-linux-386.tar.gz) | `8a5d3d031e09b511be77efd8701841a46265204c99549ef99f7849f162022e32` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-linux-amd64.tar.gz) | `84ca93bf6c427ad0cbef4f053c25deb3b267fea05aaa996b14f6b34db670e764` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-linux-arm.tar.gz) | `aa3775972d7f8e5ee833ad8f19c09fd42c908e51b5f80ea843983ce5741b4e3b` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-linux-arm64.tar.gz) | `e7b272d498c5b914fa6918be6851979c79f7adc14c5778120e42f4cba1e9fbde` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-linux-ppc64le.tar.gz) | `7913ba72de496e8a1cc38a2e7efa156f9b5fe8c3cad37a2056a406d852f4b0e2` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-linux-s390x.tar.gz) | `87a4c565d1d782351f320b38a9a76c4a9141efd4fa4559f7abe98769ba9ccbba` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-windows-386.tar.gz) | `1dfe9684bfaed00a185bdb791e292d078a6be23c7acc2941492fc11ad9a4f68d` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-client-windows-amd64.tar.gz) | `3d6396737ca6f9e272348cd31f150a636d5cd90fae341712cdb9d809c2eab3e7` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-server-linux-amd64.tar.gz) | `350e48201e97c79639764e2380f3943aac944d602ad472f506be3f48923679d2` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-server-linux-arm.tar.gz) | `75425973f22d846896f293a2d416ea697d44511d35aa6c7dd777c8f6227e6655` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-server-linux-arm64.tar.gz) | `85cdbfbeb12ad35d814e3e29c962daeb6d4995d694df4ff5fbc7aeddd96366d5` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-server-linux-ppc64le.tar.gz) | `c75f906ec1397c7fc2d5a0a0edde25b789c122088dfb39d1a28adeec40e1ca49` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-server-linux-s390x.tar.gz) | `af23a78f51906b84836e44300336348d7df99807e3b25cf46e8c406001433299` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-node-linux-amd64.tar.gz) | `9a8e88688de9ee5e32aab445d00e119d6d918bb28b238e75670055a37efac777` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-node-linux-arm.tar.gz) | `9ab0bec58796e9b48aded1deb8bdb64e9a030b0e5b38a22421d5f9d54326bcf5` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-node-linux-arm64.tar.gz) | `aaf5e103e1cdcc2e8c4cb3485091dac6eaf2381bafaf8cb0c23fc77e4611adce` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-node-linux-ppc64le.tar.gz) | `868d754868686db1d3900e48f12e3a79f94d7fed73d2827be8a1105f75787c6d` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-node-linux-s390x.tar.gz) | `e4d0e3a647edf1c145171716f038f4eff652565f4fa12e57fca106d244579cd6` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.2/kubernetes-node-windows-amd64.tar.gz) | `a25add831d97f2f4edc9e3ee02334e1831fe2ca165d901b9319546452bf01eca` - -## Changelog since v1.10.1 - -### Other notable changes - -* kubeadm upgrade no longer races leading to unexpected upgrade behavior on pod restarts ([#62655](https://github.com/kubernetes/kubernetes/pull/62655), [@stealthybox](https://github.com/stealthybox)) - * kubeadm upgrade now successfully upgrades etcd and the controlplane to use TLS - * kubeadm upgrade now supports external etcd setups - * kubeadm upgrade can now rollback and restore etcd after an upgrade failure -* Update version of Istio addon from 0.5.1 to 0.6.0. ([#61911](https://github.com/kubernetes/kubernetes/pull/61911), [@ostromart](https://github.com/ostromart)) - * See https://istio.io/about/notes/0.6.html for full Isto release notes. -* removed unsafe double RLock in cpumanager ([#62464](https://github.com/kubernetes/kubernetes/pull/62464), [@choury](https://github.com/choury)) -* Fix in vSphere Cloud Provider to handle upgrades from kubernetes version less than v1.9.4 to v1.9.4 and above. ([#62919](https://github.com/kubernetes/kubernetes/pull/62919), [@abrarshivani](https://github.com/abrarshivani)) -* Remove METADATA_AGENT_VERSION configuration option. ([#63000](https://github.com/kubernetes/kubernetes/pull/63000), [@kawych](https://github.com/kawych)) -* Fix in vSphere Cloud Provider to report disk is detach when VM is not found. ([#62220](https://github.com/kubernetes/kubernetes/pull/62220), [@abrarshivani](https://github.com/abrarshivani)) -* Restores ability to enable/disable resource within an API GroupVersion individually. ([#62116](https://github.com/kubernetes/kubernetes/pull/62116), [@deads2k](https://github.com/deads2k)) -* Fixes the kubernetes.default.svc loopback service resolution to use a loopback configuration. ([#62649](https://github.com/kubernetes/kubernetes/pull/62649), [@liggitt](https://github.com/liggitt)) -* Fix the liveness probe to use `/bin/bash -c` instead of `/bin/bash c`. ([#63033](https://github.com/kubernetes/kubernetes/pull/63033), [@bmoyles0117](https://github.com/bmoyles0117)) -* Fix error where config map for Metadata Agent was not created by addon manager. ([#62909](https://github.com/kubernetes/kubernetes/pull/62909), [@kawych](https://github.com/kawych)) -* GCE: Fix for internal load balancer management resulting in backend services with outdated instance group links. ([#62887](https://github.com/kubernetes/kubernetes/pull/62887), [@nicksardo](https://github.com/nicksardo)) -* respect fstype in Windows for azure disk ([#61267](https://github.com/kubernetes/kubernetes/pull/61267), [@andyzhangx](https://github.com/andyzhangx)) -* Update kube-dns to Version 1.14.10. Major changes: ([#62676](https://github.com/kubernetes/kubernetes/pull/62676), [@MrHohn](https://github.com/MrHohn)) - * - Fix a bug in DNS resolution for externalName services - * and PTR records that need to query from upstream nameserver. -* Fix machineID getting for vmss nodes when using instance metadata ([#62611](https://github.com/kubernetes/kubernetes/pull/62611), [@feiskyer](https://github.com/feiskyer)) -* GCE: Bump GLBC version to 1.1.1 - fixing an issue of handling multiple certs with identical certificates ([#62751](https://github.com/kubernetes/kubernetes/pull/62751), [@nicksardo](https://github.com/nicksardo)) -* fix nsenter GetFileType issue in containerized kubelet ([#62467](https://github.com/kubernetes/kubernetes/pull/62467), [@andyzhangx](https://github.com/andyzhangx)) -* fix WaitForAttach failure issue for azure disk ([#62612](https://github.com/kubernetes/kubernetes/pull/62612), [@andyzhangx](https://github.com/andyzhangx)) -* Pod affinity `nodeSelectorTerm.matchExpressions` may now be empty, and works as previously documented: nil or empty `matchExpressions` matches no objects in scheduler. ([#62448](https://github.com/kubernetes/kubernetes/pull/62448), [@k82cn](https://github.com/k82cn)) -* Fix user visible files creation for windows ([#62375](https://github.com/kubernetes/kubernetes/pull/62375), [@feiskyer](https://github.com/feiskyer)) -* Resolves forbidden error when the `daemon-set-controller` cluster role access `controllerrevisions` resources. ([#62146](https://github.com/kubernetes/kubernetes/pull/62146), [@frodenas](https://github.com/frodenas)) -* fixes configuration error when upgrading kubeadm from 1.9 to 1.10+ ([#62568](https://github.com/kubernetes/kubernetes/pull/62568), [@liztio](https://github.com/liztio)) - * enforces kubeadm upgrading kubernetes from the same major and minor versions as the kubeadm binary. -* Bugfix allowing use of IP-aliases with custom-mode network in GCE setup scripts. ([#62172](https://github.com/kubernetes/kubernetes/pull/62172), [@shyamjvs](https://github.com/shyamjvs)) -* Ensure expected load balancer is selected for Azure ([#62450](https://github.com/kubernetes/kubernetes/pull/62450), [@feiskyer](https://github.com/feiskyer)) -* fix the issue that default azure disk fsypte(ext4) does not work on Windows ([#62250](https://github.com/kubernetes/kubernetes/pull/62250), [@andyzhangx](https://github.com/andyzhangx)) -* gitRepo volumes in pods no longer require git 1.8.5 or newer, older git versions are supported too now. ([#62394](https://github.com/kubernetes/kubernetes/pull/62394), [@jsafrane](https://github.com/jsafrane)) -* Fixes issue where PersistentVolume.NodeAffinity.NodeSelectorTerms were ANDed instead of ORed. ([#62556](https://github.com/kubernetes/kubernetes/pull/62556), [@msau42](https://github.com/msau42)) -* Cluster Autoscaler 1.2.1 (release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.2.1) ([#62457](https://github.com/kubernetes/kubernetes/pull/62457), [@mwielgus](https://github.com/mwielgus)) -* Return error if get NodeStageSecret and NodePublishSecret failed in CSI volume plugin ([#61096](https://github.com/kubernetes/kubernetes/pull/61096), [@mlmhl](https://github.com/mlmhl)) -* fix incompatible file type checking on Windows ([#62154](https://github.com/kubernetes/kubernetes/pull/62154), [@dixudx](https://github.com/dixudx)) - - - -# v1.10.1 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) - -## Downloads for v1.10.1 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes.tar.gz) | `877f83d7475eade8104388799a842d1002f5ef8f284154bed229a25862ed2bde` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-src.tar.gz) | `7c0f5b80e89e1a7bd5cd859d505bfafbcf873ad99be9ac22b422d9ef732a5d4c` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-darwin-386.tar.gz) | `e7eca1569c705752ab8aef07623d2a9a3b8d798c71b702b4d5c18892d455349d` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-darwin-amd64.tar.gz) | `68c5080b85c2ab5340268e21585e309eacef64fcd175b869194b4d6b0bec2467` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-linux-386.tar.gz) | `bd08ce097e25e970eea3f13d02e322770a036eed8a63ac6fb1364f6ad1283e5c` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-linux-amd64.tar.gz) | `f638cf6121e25762e2f6f36bca9818206778942465f0ea6e3ba59cfcc9c2738a` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-linux-arm.tar.gz) | `7d395f3c0f27a14c9980f930a2b8c4b56528a09c477a5121b71ff54c17b61f73` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-linux-arm64.tar.gz) | `75fd5b1eeb082df201abc91e7a98b280817692c52f723ed2ff8234097eaff841` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-linux-ppc64le.tar.gz) | `56b4102881c3945765bbc94efa035628a522911a4ddb2a80e63255bbe989db2d` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-linux-s390x.tar.gz) | `f4e6f10f265a2cf9b71fad9ce2ddb28d577cc79643321e31318261f140d612e1` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-windows-386.tar.gz) | `86c591895cfee141b147d58d13af2c75cfb03a0ae615a70300a63a3a45132243` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-client-windows-amd64.tar.gz) | `b2caa7e6a192c1333614b3aae412cdbbc764431c1e59ace53ca6792aa7ec6496` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-server-linux-amd64.tar.gz) | `c66ad48fb37c6bd31e86f7633742eab7ccb136cd7268f1f642ca52fdb814f1a5` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-server-linux-arm.tar.gz) | `8ef4a278639f3335c033d385e57a286043b7172dc7613403f841f05486dc731a` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-server-linux-arm64.tar.gz) | `5987762c352155a5d378760e91af55c6180bdb25be1bf3799e9317d9435ab05a` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-server-linux-ppc64le.tar.gz) | `014409580ccc492caaee30e1136e88b4580608b1eedf2c9da96488a05b586110` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-server-linux-s390x.tar.gz) | `dc2fb6e1f53e11fc161b617ceef09f4117e54e18ade24401813c934283e8ee6f` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-node-linux-amd64.tar.gz) | `6398c87906dbd37ccd881ca4169713c512a7bd04e336f4c81d2497c460be855f` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-node-linux-arm.tar.gz) | `54e24107ac1f98fa75ce3c603c4f8c3edcf7277046deaff2cef55521147ac956` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-node-linux-arm64.tar.gz) | `7d9c8aa2ee5f2d6207a6bac9e32639ea14fe830e6bb57f2ab4fc4ad47b6772c4` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-node-linux-ppc64le.tar.gz) | `339ce8cb3e703fd2252e6978bfbdd2c26d46516ed8ef4f548e2e1fd2b7d4b49e` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-node-linux-s390x.tar.gz) | `896396437d74a8a1c8c310de1666cc95d4d5bbee67c201c400c383e9fb6818f2` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.1/kubernetes-node-windows-amd64.tar.gz) | `9932e75059ffb8c9a7400ffd5620fb114fcd53961651f97b943298bb8a7dd24a` - -## Changelog since v1.10.0 - -### Other notable changes - -* Fix panic create/update CRD when mutating/validating webhook configured. ([#61404](https://github.com/kubernetes/kubernetes/pull/61404), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) -* Add support to ingest log entries to Stackdriver against new "k8s_container" and "k8s_node" resources. ([#62076](https://github.com/kubernetes/kubernetes/pull/62076), [@qingling128](https://github.com/qingling128)) -* new dhcp-domain parameter to be used for figuring out the hostname of a node ([#61890](https://github.com/kubernetes/kubernetes/pull/61890), [@dims](https://github.com/dims)) -* Extend the Stackdriver Metadata Agent by adding a new Deployment for ingesting unscheduled pods, and services. ([#62043](https://github.com/kubernetes/kubernetes/pull/62043), [@supriyagarg](https://github.com/supriyagarg)) -* Fixed a panic in `kubectl run --attach ...` when the api server failed to create the runtime object (due to name conflict, PSP restriction, etc.) ([#61713](https://github.com/kubernetes/kubernetes/pull/61713), [@mountkin](https://github.com/mountkin)) -* Fix a bug that fluentd doesn't inject container logs for CRI container runtimes (containerd, cri-o etc.) into elasticsearch on GCE. ([#61818](https://github.com/kubernetes/kubernetes/pull/61818), [@Random-Liu](https://github.com/Random-Liu)) -* fix local volume issue on Windows ([#62012](https://github.com/kubernetes/kubernetes/pull/62012), [@andyzhangx](https://github.com/andyzhangx)) -* Fixed bug in rbd-nbd utility when nbd is used. ([#62168](https://github.com/kubernetes/kubernetes/pull/62168), [@piontec](https://github.com/piontec)) -* GCE: Updates GLBC version to 1.0.1 which includes a fix which prevents multi-cluster ingress objects from creating full load balancers. ([#62075](https://github.com/kubernetes/kubernetes/pull/62075), [@nicksardo](https://github.com/nicksardo)) -* Fix GCE etcd scripts to pass in all required parameters for the etcd migration utility to correctly perform HA upgrades and downgrades ([#61960](https://github.com/kubernetes/kubernetes/pull/61960), [@jpbetz](https://github.com/jpbetz)) -* Update kube-dns to Version 1.14.9. Major changes: ([#61908](https://github.com/kubernetes/kubernetes/pull/61908), [@MrHohn](https://github.com/MrHohn)) - * - Fix for kube-dns returns NXDOMAIN when not yet synced with apiserver. - * - Don't generate empty record for externalName service. - * - Add validation for upstreamNameserver port. - * - Update go version to 1.9.3. -* kubectl: improves compatibility with older servers when creating/updating API objects ([#61949](https://github.com/kubernetes/kubernetes/pull/61949), [@liggitt](https://github.com/liggitt)) -* Bound cloud allocator to 10 retries with 100 ms delay between retries. ([#61375](https://github.com/kubernetes/kubernetes/pull/61375), [@satyasm](https://github.com/satyasm)) -* Fixed [#61123](https://github.com/kubernetes/kubernetes/pull/61123) by triggering syncer.Update on all cases including when a syncer is created ([#61124](https://github.com/kubernetes/kubernetes/pull/61124), [@satyasm](https://github.com/satyasm)) - * on a new add event. -* Add ipset and udevadm to the hyperkube base image. ([#61357](https://github.com/kubernetes/kubernetes/pull/61357), [@rphillips](https://github.com/rphillips)) -* kubectl: restore the ability to show resource kinds when displaying multiple objects ([#61985](https://github.com/kubernetes/kubernetes/pull/61985), [@liggitt](https://github.com/liggitt)) -* Remove 'system' prefix from Metadata Agent rbac configuration ([#61394](https://github.com/kubernetes/kubernetes/pull/61394), [@kawych](https://github.com/kawych)) -* Ensure cloudprovider.InstanceNotFound is reported when the VM is not found on Azure ([#61531](https://github.com/kubernetes/kubernetes/pull/61531), [@feiskyer](https://github.com/feiskyer)) -* kubectl: fixes issue with `-o yaml` and `-o json` omitting kind and apiVersion when used with `--dry-run` ([#61808](https://github.com/kubernetes/kubernetes/pull/61808), [@liggitt](https://github.com/liggitt)) -* Bump Heapster to v1.5.2 ([#61396](https://github.com/kubernetes/kubernetes/pull/61396), [@kawych](https://github.com/kawych)) -* Support new NODE_OS_DISTRIBUTION 'custom' on GCE ([#61235](https://github.com/kubernetes/kubernetes/pull/61235), [@yguo0905](https://github.com/yguo0905)) -* Fix mounting of UNIX sockets(and other special files) in subpaths ([#61480](https://github.com/kubernetes/kubernetes/pull/61480), [@gnufied](https://github.com/gnufied)) -* [fluentd-gcp addon] Update event-exporter image to have the latest base image. ([#61727](https://github.com/kubernetes/kubernetes/pull/61727), [@crassirostris](https://github.com/crassirostris)) - - - -# v1.10.0 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) - -## Downloads for v1.10.0 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes.tar.gz) | `a48d4f6eb4bf329a87915d2264250f2045aab1e8c6cc3e574a887ec42b5c6edc` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-src.tar.gz) | `3b51bf50370fc022f5e4578b071db6b63963cd64b35c41954d4a2a8f6738c0a7` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-darwin-386.tar.gz) | `8f35d820d21bfdb3186074eb2ed5212b983e119215356a7a76a9f773f2a1e6a3` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-darwin-amd64.tar.gz) | `ae06d0cd8f6fa8d145a9dbdb77e6cba99ad9cfce98b01c766df1394c17443e42` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-linux-386.tar.gz) | `8147723a68763b9791def5b41d75745e835ddd82f23465a2ba7797b84ad73554` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-linux-amd64.tar.gz) | `845668fe2f854b05aa6f0b133314df83bb41a486a6ba613dbb1374bf3fbe8720` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-linux-arm.tar.gz) | `5d2552a6781ef0ecaf308fe6a02637faef217c98841196d4bd7c52a0f1a4bfa0` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-linux-arm64.tar.gz) | `9d5e4ba43ad7250429015f33f728c366daa81e894e8bfe8063d73ce990e82944` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-linux-ppc64le.tar.gz) | `acabf3a26870303641ce60a59b5bb9702c8a7445b16f4293abc7868e91d252c8` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-linux-s390x.tar.gz) | `8d836df10b50d11434b5ee797aecc21714723f02fc47fe3dd600426eb83b9e38` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-windows-386.tar.gz) | `ca183b66f910ff11fa468e47251c68d256ef145fcfc2d23d4347d066e7787971` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-client-windows-amd64.tar.gz) | `817aea754a059c635f4d690aa0232a8e77eb74e76357cafd8f10556972022e9e` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-server-linux-amd64.tar.gz) | `f2e0505bee7d9217332b96be11d1b88c06f51049f7a44666b0ede80bfb92fdf6` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-server-linux-arm.tar.gz) | `a7be68c32a299c98353633f3161f910c4b970c8364ccee5f98e1991364b3ce69` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-server-linux-arm64.tar.gz) | `4df4add2891d02101818653ac68b57e6ce4760fd298f47467ce767ac029f4508` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-server-linux-ppc64le.tar.gz) | `199b52461930c0218f984884069770fb7e6ceaf66342d5855b209ff1889025b8` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-server-linux-s390x.tar.gz) | `578f93fc22d2a5bec7dc36633946eb5b7359d96233a2ce74f8b3c5a231494584` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-node-linux-amd64.tar.gz) | `8c03412881eaab5f3ea828bbb81e8ebcfc092d311b2685585817531fa7c2a289` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-node-linux-arm.tar.gz) | `d6a413fcadb1b933a761ac9b0c864f596498a8ac3cc4922c1569306cd0047b1d` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-node-linux-arm64.tar.gz) | `46d6b74759fbc3b2aad42357f019dae0e882cd4639e499e31b5b029340dabd42` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-node-linux-ppc64le.tar.gz) | `bdecc12feab2464ad917623ade0cbf58675e0566db38284b79445841d246fc08` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-node-linux-s390x.tar.gz) | `afe35c2854f35939be75ccfb0ec81399acf4043ae7cf19dd6fbe6386288972c2` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0/kubernetes-node-windows-amd64.tar.gz) | `eac14e3420ca9769e067cbf929b5383cd77d56e460880a30c0df1bbfbb5a43db` - -## Major Themes - -### Node - -Many of the changes within SIG-Node revolve around control. With the beta release of the `kubelet.config.k8s.io` API group, a significant subset of Kubelet configuration can now be [configured via a versioned config file](https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/). Kubernetes v1.10 adds alpha support for the ability to [configure whether containers in a pod should share a single process namespace](https://github.com/kubernetes/features/issues/495), and the CRI has been upgraded to v1alpha2, which adds [support for Windows Container Configuration](https://github.com/kubernetes/features/issues/547). Kubernetes v1.10 also ships with the beta release of the [CRI validation test suite](https://github.com/kubernetes/features/issues/292). - -The Resource Management Working Group graduated three features to beta in the 1.10 release. First, [CPU Manager](https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/), which allows users to request exclusive CPU cores. This helps performance in a variety of use-cases, including network latency sensitive applications, as well as applications that benefit from CPU cache residency. Next, [Huge Pages](https://kubernetes.io/docs/tasks/manage-hugepages/scheduling-hugepages/), which allows pods to consume either 2Mi or 1Gi Huge Pages. This benefits applications that consume large amounts of memory. Use of Huge Pages is a common tuning recommendation for databases and JVMs. Finally, the [Device Plugin](https://kubernetes.io/docs/concepts/cluster-administration/device-plugins/) feature, which provides a framework for vendors to advertise their resources to the Kubelet without changing Kubernetes core code. Targeted devices include GPUs, High-performance NICs, FPGAs, InfiniBand, and other similar computing resources that may require vendor specific initialization and setup. - -### Storage - -This release brings additional power to both local storage and Persistent Volumes. [Mount namespace propagation](https://github.com/kubernetes/features/issues/432) allows a container to mount a volume as rslave so that host mounts can be seen inside the container, or as rshared so that mounts made inside a container can be seen by the host. (Note that this is [not supported on Windows](https://github.com/kubernetes/kubernetes/pull/60275).) [Local Ephemeral Storage Capacity Isolation](https://github.com/kubernetes/features/issues/361) makes it possible to set requests and limits on ephemeral local storage resources. In addition, you can now create [Local Persistent Storage](https://github.com/kubernetes/features/issues/121), which enables PersistentVolumes to be created with locally attached disks, and not just network volumes. - -On the Persistent Volumes side, this release [Prevents deletion of Persistent Volume Claims that are used by a pod](https://github.com/kubernetes/features/issues/498) and [Persistent Volumes that are bound to a Persistent Volume Claim](https://github.com/kubernetes/features/issues/499), making it impossible to delete storage that is in use by a pod. - -This release also includes [Topology Aware Volume Scheduling](https://github.com/kubernetes/features/issues/490) for local persistent volumes, the stable release of [Detailed storage metrics of internal state](https://github.com/kubernetes/features/issues/496), and beta support for [Out-of-tree CSI Volume Plugins](https://github.com/kubernetes/features/issues/178). - -### Windows - -This release continues to enable more existing features on Windows, including container CPU resources, image filesystem stats, and flexvolumes. It also adds Windows service control manager support and experimental support for Hyper-V isolation of single-container pods. - -### OpenStack - -SIG-OpenStack updated the OpenStack provider to use newer APIs, consolidated community code into one repository, engaged with the Cloud Provider Working Group to have a consistent plan for moving provider code into individual repositories, improved testing of provider code, and strengthened ties with the OpenStack developer community. - -### API-machinery - -[API Aggregation](https://github.com/kubernetes/features/issues/263) has been upgraded to "stable" in Kubernetes 1.10, so you can use it in production. Webhooks have seen numerous improvements, including alpha [Support for self-hosting authorizer webhooks](https://github.com/kubernetes/features/issues/516). - -### Auth - -This release lays the groundwork for new authentication methods, including the alpha release of [External client-go credential providers](https://github.com/kubernetes/features/issues/541) and the [TokenRequest API](https://github.com/kubernetes/features/issues/542). In addition, [Pod Security Policy](https://github.com/kubernetes/features/issues/5) now lets administrators decide what contexts pods can run in, and gives administrators the ability to [limit node access to the API](https://github.com/kubernetes/features/issues/279). - -### Azure - -Kubernetes 1.10 includes alpha [Azure support for cluster-autoscaler](https://github.com/kubernetes/features/issues/514), as well as [support for Azure Virtual Machine Scale Sets](https://github.com/kubernetes/features/issues/513). - -### CLI - -This release includes a change to [kubectl get and describe to work better with extensions](https://github.com/kubernetes/features/issues/515), as the server, rather than the client, returns this information for a smoother user experience. - -### Network - -In terms of networking, Kubernetes 1.10 is about control. Users now have beta support for the ability to [configure a pod's resolv.conf](https://github.com/kubernetes/features/issues/504), rather than relying on the cluster DNS, as well as [configuring the NodePort IP address](https://github.com/kubernetes/features/issues/539). You can also [switch the default DNS plugin to CoreDNS](https://github.com/kubernetes/features/issues/427) (beta). - -## Before Upgrading - -* If you need to downgrade from 1.10 to 1.9.x, downgrade to v1.9.6 to ensure PV and PVC objects can be deleted properly. - -* In-place node upgrades to this release from versions 1.7.14, 1.8.9, and 1.9.4 are not supported if using subpath volumes with PVCs. Such pods should be drained from the node first. - -* The minimum supported version of Docker is now 1.11; if you are using Docker 1.10 or below, be sure to upgrade Docker before upgrading Kubernetes. ([#57845](https://github.com/kubernetes/kubernetes/pull/57845), [@yujuhong](https://github.com/yujuhong)) - -* The Container Runtime Interface (CRI) version has increased from v1alpha1 to v1alpha2. Runtimes implementing the CRI will need to update to the new version, which configures container namespaces using an enumeration rather than booleans. This change to the alpha API is not backwards compatible; implementations of the CRI such as containerd, will need to update to the new API version. ([#58973](https://github.com/kubernetes/kubernetes/pull/58973), [@verb](https://github.com/verb)) - -* The default Flexvolume plugin directory for COS images on GCE has changed to `/home/kubernetes/flexvolume`, rather than `/etc/srv/kubernetes/kubelet-plugins/volume/exec`. Existing Flexvolume installations in clusters using COS images must be moved to the new directory, and installation processes must be updated with the new path. ([#58171](https://github.com/kubernetes/kubernetes/pull/58171), [@verult](https://github.com/verult)) - -* Default values differ between the Kubelet's componentconfig (config file) API and the Kubelet's command line. Be sure to review the default values when migrating to using a config file. For example, the authz mode is set to "AlwaysAllow" if you rely on the command line, but defaults to the more secure "Webhook" mode if you load config from a file. ([#59666](https://github.com/kubernetes/kubernetes/pull/59666), [@mtaufen](https://github.com/mtaufen)) - -* [GCP kube-up.sh] Variables that were part of kube-env that were only used for kubelet flags are no longer being set, and are being replaced by the more portable mechanism of the kubelet configuration file. The individual variables in the kube-env metadata entry were never meant to be a stable interface and this release note only applies if you are depending on them. ([#60020](https://github.com/kubernetes/kubernetes/pull/60020), [@roberthbailey](https://github.com/roberthbailey)) - -* kube-proxy: feature gates are now specified as a map when provided via a JSON or YAML KubeProxyConfiguration, rather than as a string of key-value pairs. For example: - -KubeProxyConfiguration Before: - -``` -apiVersion: kubeproxy.config.k8s.io/v1alpha1 -kind: KubeProxyConfiguration -**featureGates: "SupportIPVSProxyMode=true"** -``` - -KubeProxyConfiguration After: - -``` -apiVersion: kubeproxy.config.k8s.io/v1alpha1 -kind: KubeProxyConfiguration -**featureGates:** -** SupportIPVSProxyMode: true** -``` - -If your cluster was installed by kubeadm, you should edit the `featureGates` field in the `kubeadm-config` ConfigMap. You can do this using `kubectl -n kube-system edit cm kubeadm-config` before upgrading. For example: - -kubeadm-config Before: - -``` -apiVersion: v1 -kind: ConfigMap -metadata: - name: kubeadm-config -data: - MasterConfiguration: | - kubeProxy: - config: - featureGates: "SupportIPVSProxyMode=true" -``` - -kubeadm-config After: - -``` -apiVersion: v1 -kind: ConfigMap -metadata: - name: kubeadm-config -data: - MasterConfiguration: | - kubeProxy: - config: - featureGates: - SupportIPVSProxyMode: true -``` - -If no featureGates was specified in `kubeadm-config`, just change `featureGates: ""` to `featureGates: {}`. - -([#57962](https://github.com/kubernetes/kubernetes/pull/57962), [@xiangpengzhao](https://github.com/xiangpengzhao)) - -* The `kubeletconfig` API group has graduated from alpha to beta, and the name has changed to `kubelet.config.k8s.io`. Please use `kubelet.config.k8s.io/v1beta1`, as `kubeletconfig/v1alpha1` is no longer available. ([#53833](https://github.com/kubernetes/kubernetes/pull/53833), [@mtaufen](https://github.com/mtaufen)) - -* kube-apiserver: the experimental in-tree Keystone password authenticator has been removed in favor of extensions that enable use of Keystone tokens. ([#59492](https://github.com/kubernetes/kubernetes/pull/59492), [@dims](https://github.com/dims)) - -* The udpTimeoutMilliseconds field in the kube-proxy configuration file has been renamed to udpIdleTimeout. Administrators must update their files accordingly. ([#57754](https://github.com/kubernetes/kubernetes/pull/57754), [@ncdc](https://github.com/ncdc)) - -* The kubelet's `--cloud-provider=auto-detect` feature has been removed; make certain to specify the cloud provider. ([#56287](https://github.com/kubernetes/kubernetes/pull/56287), [@stewart-yu](https://github.com/stewart-yu)) - -* kube-apiserver: the OpenID Connect authenticator no longer accepts tokens from the Google v3 token APIs; users must switch to the "https://www.googleapis.com/oauth2/v4/token" endpoint. - -* kube-apiserver: the root /proxy paths have been removed (deprecated since v1.2). Use the /proxy subresources on objects that support HTTP proxying. ([#59884](https://github.com/kubernetes/kubernetes/pull/59884), [@mikedanese](https://github.com/mikedanese)) - -* Eviction thresholds set to 0% or 100% will turn off eviction. ([#59681](https://github.com/kubernetes/kubernetes/pull/59681), [@mtaufen](https://github.com/mtaufen)) - -* CustomResourceDefinitions: OpenAPI v3 validation schemas containing `$ref`references are no longer permitted. Before upgrading, ensure CRD definitions do not include those `$ref` fields. ([#58438](https://github.com/kubernetes/kubernetes/pull/58438), [@carlory](https://github.com/carlory)) - -* Webhooks now do not skip cluster-scoped resources. Before upgrading your Kubernetes clusters, double check whether you have configured webhooks for cluster-scoped objects (e.g., nodes, persistentVolume), as these webhooks will start to take effect. Delete/modify the configs if that's not desirable. ([#58185](https://github.com/kubernetes/kubernetes/pull/58185), [@caesarxuchao](https://github.com/caesarxuchao)) - -* Using kubectl gcp auth plugin with a Google Service Account to authenticate to a cluster now additionally requests a token with the "userinfo.email" scope. This way, users can write ClusterRoleBindings/RoleBindings with the email address of the service account directly. (This is a breaking change if the numeric uniqueIDs of the Google service accounts were being used in RBAC role bindings. The behavior can be overridden by explicitly specifying the scope values as comma-separated string in the "users[*].config.scopes" field in the KUBECONFIG file.) This way, users can now set a Google Service Account JSON key in the GOOGLE_APPLICATION_CREDENTIALS environment variable, craft a kubeconfig file with GKE master IP+CA cert, and authenticate to GKE in headless mode without requiring gcloud CLI. ([#58141](https://github.com/kubernetes/kubernetes/pull/58141), [@ahmetb](https://github.com/ahmetb)) - -* kubectl port-forward no longer supports the deprecated -p flag; the flag itself is unnecessary and should be replaced by just the ``. ([#59705](https://github.com/kubernetes/kubernetes/pull/59705), [@phsiao](https://github.com/phsiao)) - -* Removed deprecated --require-kubeconfig flag, removed default --kubeconfig value (([#58367](https://github.com/kubernetes/kubernetes/pull/58367), [@zhangxiaoyu-zidif](https://github.com/zhangxiaoyu-zidif)) - -* The public-address-override, address, and port flags have been removed and replaced by bind-address, insecure-bind-address, and insecure-port, respectively. They are marked as deprecated in [#36604](https://github.com/kubernetes/kubernetes/pull/36604), which is more than a year ago. ([#59018](https://github.com/kubernetes/kubernetes/pull/59018), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) - -* The alpha `--init-config-dir` flag has been removed. Instead, use the `--config` flag to reference a kubelet configuration file directly. ([#57624](https://github.com/kubernetes/kubernetes/pull/57624), [@mtaufen](https://github.com/mtaufen)) - -* Removed deprecated and unmaintained salt support. kubernetes-salt.tar.gz will no longer be published in the release tarball. ([#58248](https://github.com/kubernetes/kubernetes/pull/58248), [@mikedanese](https://github.com/mikedanese)) - -* The deprecated –mode switch for GCE has been removed.([#61203](https://github.com/kubernetes/kubernetes/pull/61203)) - -* The word “manifest” has been expunged from the Kubelet API. ([#60314](https://github.com/kubernetes/kubernetes/pull/60314)) - -* [https://github.com/kubernetes/kubernetes/issues/49213](https://github.com/kubernetes/kubernetes/issues/49213) sig-cluster-lifecycle has decided to phase out the cluster/ directory over the next couple of releases in favor of deployment automations maintained outside of the core repo and outside of kubernetes orgs. ([@kubernetes/sig-cluster-lifecycle-misc](https://github.com/orgs/kubernetes/teams/sig-cluster-lifecycle-misc)) - - * Remove deprecated ContainerVM support from GCE kube-up. ([#58247](https://github.com/kubernetes/kubernetes/pull/58247), [@mikedanese](https://github.com/mikedanese)) - - * Remove deprecated kube-push.sh functionality. ([#58246](https://github.com/kubernetes/kubernetes/pull/58246), [@mikedanese](https://github.com/mikedanese)) - - * Remove deprecated container-linux support in gce kube-up.sh. ([#58098](https://github.com/kubernetes/kubernetes/pull/58098), [@mikedanese](https://github.com/mikedanese)) - - * Remove deprecated and unmaintained photon-controller kube-up.sh. ([#58096](https://github.com/kubernetes/kubernetes/pull/58096), [@mikedanese](https://github.com/mikedanese)) - - * Remove deprecated and unmaintained libvirt-coreos kube-up.sh. ([#58023](https://github.com/kubernetes/kubernetes/pull/58023), [@mikedanese](https://github.com/mikedanese)) - - * Remove deprecated and unmaintained windows installer. ([#58020](https://github.com/kubernetes/kubernetes/pull/58020), [@mikedanese](https://github.com/mikedanese)) - - * Remove deprecated and unmaintained openstack-heat kube-up.sh. ([#58021](https://github.com/kubernetes/kubernetes/pull/58021), [@mikedanese](https://github.com/mikedanese)) - - * Remove deprecated vagrant kube-up.sh. ([#58118](https://github.com/kubernetes/kubernetes/pull/58118),[@roberthbailey](https://github.com/roberthbailey)) - -* The DaemonSet controller, its integration tests, and its e2e tests, have been updated to use the apps/v1 API. Users should, but are not yet required to, update their scripts accordingly. ([#59883](https://github.com/kubernetes/kubernetes/pull/59883), [@kow3ns](https://github.com/kow3ns)) - -* MountPropagation feature is now beta. As a consequence, all volume mounts in containers are now `rslave` on Linux by default. To make this default work in all Linux environments the entire mount tree should be marked as shareable, e.g. via `mount --make-rshared /`. All Linux distributions that use systemd already have the root directory mounted as rshared and hence they need not do anything. In Linux environments without systemd we recommend running `mount --make-rshared /` during boot before docker is started, ([@jsafrane](https://github.com/jsafrane)) - -## Known Issues - -* If you need to downgrade from 1.10 to 1.9.x, downgrade to v1.9.6 to ensure PV and PVC objects can be deleted properly. - -* Use of subPath module with hostPath volumes can cause issues during reconstruction ([#61446](https://github.com/kubernetes/kubernetes/issues/61446)) and with containerized kubelets ([#61456](https://github.com/kubernetes/kubernetes/issues/61456)). The workaround for this issue is to specify the complete path in the hostPath volume. Use of subPathmounts nested within atomic writer volumes (configmap, secret, downwardAPI, projected) does not work ([#61545](https://github.com/kubernetes/kubernetes/issues/61545)), and socket files cannot be loaded from a subPath ([#62377](https://github.com/kubernetes/kubernetes/issues/61377)). Work on these issues is ongoing. - -* Kubeadm is currently omitting etcd certificates in a self-hosted deployment; this will be fixed in a point relelase. ([#61322](https://github.com/kubernetes/kubernetes/issues/61322)) - -* Some users, especially those with very large clusters, may see higher memory usage by the kube-controller-manager in 1.10. ([#61041](https://github.com/kubernetes/kubernetes/issues/61041)) - -* Due to an issue in ingress-gce controller in 1.10.0, creating multi-cluster ingresses with [kubemci CLI](https://github.com/GoogleCloudPlatform/k8s-multicluster-ingress) fails. This will be fixed in 1.10.1 release. ([GoogleCloudPlatform/k8s-multicluster-ingress#175](https://github.com/GoogleCloudPlatform/k8s-multicluster-ingress/issues/175)) - -## Deprecations - -* etcd2 as a backend is deprecated and support will be removed in Kubernetes 1.13. - -* VolumeScheduling and LocalPersistentVolume features are beta and enabled by default. The PersistentVolume NodeAffinity alpha annotation is deprecated and will be removed in a future release. ([#59391](https://github.com/kubernetes/kubernetes/pull/59391), [@msau42](https://github.com/msau42)) - -* The alpha Accelerators feature gate is deprecated and will be removed in v1.11. Please use device plugins ([https://github.com/kubernetes/features/issues/368](https://github.com/kubernetes/features/issues/368)) instead. They can be enabled using the DevicePlugins feature gate. ([#57384](https://github.com/kubernetes/kubernetes/pull/57384), [@mindprince](https://github.com/mindprince)) - -* The ability to use kubectl scale jobs is deprecated. All other scale operations remain in place, but the ability to scale jobs will be removed in a future release. ([#60139](https://github.com/kubernetes/kubernetes/pull/60139), [@soltysh](https://github.com/soltysh)) - -* Flags that can be set via the [Kubelet's --config file](https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/) are now deprecated in favor of the file. ([#60148](https://github.com/kubernetes/kubernetes/pull/60148), [@mtaufen](https://github.com/mtaufen)) - -* `--show-all` (which only affected pods and only for human readable/non-API printers) is now defaulted to true and deprecated. The flag determines whether pods in a terminal state are displayed. It will be inert in 1.11 and removed in a future release. ([#60210](https://github.com/kubernetes/kubernetes/pull/60210), [@deads2k](https://github.com/deads2k)) - -* The ability to use the insecure HTTP port of kube-controller-manager and cloud-controller-manager has been deprecated, and will be removed in a future release. Use `--secure-port` and `--bind-address` instead. ([#59582](https://github.com/kubernetes/kubernetes/pull/59582), [@sttts](https://github.com/sttts)) - -* The ability to use the insecure flags `--insecure-bind-address`, `--insecure-port` in the apiserver has been deprecated and will be removed in a future release. Use `--secure-port` and `--bind-address` instead. ([#59018](https://github.com/kubernetes/kubernetes/pull/59018), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) - -* The recycling reclaim policy has been deprecated. Users should use dynamic provisioning instead. ([#59063](https://github.com/kubernetes/kubernetes/pull/59063), [@ayushpateria](https://github.com/ayushpateria)) - -* kube-apiserver flag --tls-ca-file has had no effect for some time. It is now deprecated and slated for removal in 1.11. If you are specifying this flag, you must remove it from your launch config before upgrading to 1.11. ([#58968](https://github.com/kubernetes/kubernetes/pull/58968), [@deads2k](https://github.com/deads2k)) - -* The `PodSecurityPolicy` API has been moved to the `policy/v1beta1` API group. The `PodSecurityPolicy` API in the `extensions/v1beta1` API group is deprecated and will be removed in a future release. Authorizations for using pod security policy resources should change to reference the `policy` API group after upgrading to 1.11. ([#54933](https://github.com/kubernetes/kubernetes/pull/54933), [@php-coder](https://github.com/php-coder)) - -* Add `--enable-admission-plugins` `--disable-admission-plugins` flags and deprecate `--admission-control`. When using the separate flag, the order in which they're specified doesn't matter. ([#58123](https://github.com/kubernetes/kubernetes/pull/58123), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) - -* The kubelet --docker-disable-shared-pid flag, which runs docker containers with a process namespace that is shared between all containers in a pod, is now deprecated and will be removed in a future release. It is replaced by `v1.Pod.Spec.ShareProcessNamespace`, which configures this behavior. This field is alpha and can be enabled with --feature-gates=PodShareProcessNamespace=true. ([#58093](https://github.com/kubernetes/kubernetes/pull/58093), [@verb](https://github.com/verb)) - -* The kubelet's cadvisor port has been deprecated. The default will change to 0 (disabled) in 1.12, and the cadvisor port will be removed entirely in 1.13. ([#59827](https://github.com/kubernetes/kubernetes/pull/59827), [@dashpole](https://github.com/dashpole)) - -* rktnetes has been deprecated in favor of rktlet. Please see [https://github.com/kubernetes-incubator/rktlet](https://github.com/kubernetes-incubator/rktlet) for more information. ([#58418](https://github.com/kubernetes/kubernetes/pull/58418), [@yujuhong](https://github.com/yujuhong)) - -* The Kubelet now explicitly registers all of its command-line flags with an internal flagset, which prevents flags from third party libraries from unintentionally leaking into the Kubelet's command-line API. Many unintentionally leaked flags are now marked deprecated, so that users have a chance to migrate away from them before they are removed. In addition, one previously leaked flag, --cloud-provider-gce-lb-src-cidrs, has been entirely removed from the Kubelet's command-line API, because it is irrelevant to Kubelet operation. The deprecated flags are: - - * --application_metrics_count_limit - * --boot_id_file - * --container_hints - * --containerd - * --docker - * --docker_env_metadata_whitelist - * --docker_only - * --docker-tls - * --docker-tls-ca - * --docker-tls-cert - * --docker-tls-key - * --enable_load_reader - * --event_storage_age_limit - * --event_storage_event_limit - * --global_housekeeping_interval - * --google-json-key - * --log_cadvisor_usage - * --machine_id_file - * --storage_driver_user - * --storage_driver_password - * --storage_driver_host - * --storage_driver_db - * --storage_driver_table - * --storage_driver_secure - * --storage_driver_buffer_duration - -([#57613](https://github.com/kubernetes/kubernetes/pull/57613), [@mtaufen](https://github.com/mtaufen)) - -* The boostrapped RBAC role and rolebinding for the `cloud-provider` service account is now deprecated. If you're currently using this service account, you must create and apply your own [RBAC policy](https://kubernetes.io/docs/admin/authorization/rbac/) for new clusters. ([#59949](https://github.com/kubernetes/kubernetes/pull/59949), [@nicksardo](https://github.com/nicksardo)) - -* Format-separated endpoints for the OpenAPI spec, such as /swagger.json, /swagger-2.0.0.0.json, and so on, have been deprecated. The old endpoints will remain in 1.10, 1.11, 1.12 and 1.13, and get removed in 1.14. Please use single `/openapi/v2` endpoint with the appropriate Accept: header instead. For example: - - - - - - - - - - - - - - - - - - -
previousnow
GET /swagger.jsonGET /openapi/v2 -Accept: application/json
GET /swagger-2.0.0.pb-v1GET /openapi/v2 -Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf
GET /swagger-2.0.0.pb-v1.gzGET /openapi/v2 -Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf Accept-Encoding: gzip
- - ([#59293](https://github.com/kubernetes/kubernetes/pull/59293), [@roycaihw](https://github.com/roycaihw)) - -## Other Notable Changes - -### Apps - -* Updated defaultbackend image to 1.4 and deployment apiVersion to apps/v1. Users should concentrate on updating scripts to the new version. ([#57866](https://github.com/kubernetes/kubernetes/pull/57866), [@zouyee](https://github.com/zouyee)) - -* Fix StatefulSet to work correctly with set-based selectors. ([#59365](https://github.com/kubernetes/kubernetes/pull/59365), [@ayushpateria](https://github.com/ayushpateria)) - -* Fixes a case when Deployment with recreate strategy could get stuck on old failed Pod. ([#60301](https://github.com/kubernetes/kubernetes/pull/60301), [@tnozicka](https://github.com/tnozicka)) - -* ConfigMap objects now support binary data via a new `binaryData` field. When using `kubectl create configmap --from-file`, files containing non-UTF8 data will be placed in this new field in order to preserve the non-UTF8 data. Note that kubectl's `--append-hash` feature doesn't take `binaryData` into account. Use of this feature requires 1.10+ apiserver and kubelets. ([#57938](https://github.com/kubernetes/kubernetes/pull/57938), [@dims](https://github.com/dims)) - -### AWS - -* Add AWS cloud provider option to use an assumed IAM role. For example, this allows running Controller Manager in a account separate from the worker nodes, but still allows all resources created to interact with the workers. ELBs created would be in the same account as the worker nodes for instance.([#59668](https://github.com/kubernetes/kubernetes/pull/59668), [@brycecarman](https://github.com/brycecarman)) - -* AWS EBS volume plugin now includes block and volumeMode support. ([#58625](https://github.com/kubernetes/kubernetes/pull/58625), [@screeley44](https://github.com/screeley44)) - -* On AWS kubelet returns an error when started under conditions that do not allow it to work (AWS has not yet tagged the instance), rather than failing silently. ([#60125](https://github.com/kubernetes/kubernetes/pull/60125), [@vainu-arto](https://github.com/vainu-arto)) - -* AWS Security Groups created for ELBs will now be tagged with the same additional tags as the ELB; that is, the tags specified by the "service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags" annotation. This is useful for identifying orphaned resources. ([#58767](https://github.com/kubernetes/kubernetes/pull/58767), [@2rs2ts](https://github.com/2rs2ts)) - -* AWS Network Load Balancers will now be deleted properly, including security group rules. Fixes [#57568](https://github.com/kubernetes/kubernetes/pull/57568) ([#57569](https://github.com/kubernetes/kubernetes/pull/57569), [@micahhausler](https://github.com/micahhausler)) - -* Time for attach/detach retry operations has been decreased from 10-12s to 2-6s ([#56974](https://github.com/kubernetes/kubernetes/pull/56974), [@gnufied](https://github.com/gnufied)) - -### Auth - -* Contexts must be named in kubeconfigs. ([#56769](https://github.com/kubernetes/kubernetes/pull/56769), [@dixudx](https://github.com/dixudx)) - -* vSphere operations will no longer fail due to authentication errors. ([#57978](https://github.com/kubernetes/kubernetes/pull/57978), [@prashima](https://github.com/prashima)) - -* This removes the cloud-provider role and role binding from the rbac boostrapper and replaces it with a policy applied via addon mgr. This also creates a new clusterrole allowing the service account to create events for any namespace. - -* client-go: alpha support for out-of-tree exec-based credential providers. For example, a cloud provider could create their own authentication system rather than using the standard authentication provided with Kubernetes. ([#59495](https://github.com/kubernetes/kubernetes/pull/59495), [@ericchiang](https://github.com/ericchiang)) - -* The node authorizer now allows nodes to request service account tokens for the service accounts of pods running on them. This allows agents using the node identity to take actions on behalf of local pods. ([#55019](https://github.com/kubernetes/kubernetes/pull/55019), [@mikedanese](https://github.com/mikedanese)) - -* kube-apiserver: the OpenID Connect authenticator can now verify ID Tokens signed with JOSE algorithms other than RS256 through the --oidc-signing-algs flag. ([#58544](https://github.com/kubernetes/kubernetes/pull/58544), [@ericchiang](https://github.com/ericchiang)) - -* Requests with invalid credentials no longer match audit policy rules where users or groups are set, correcting a problem where authorized requests were getting through. ([#59398](https://github.com/kubernetes/kubernetes/pull/59398), [@CaoShuFeng](https://github.com/CaoShuFeng)) - -* The Stackdriver Metadata Agent addon now includes RBAC manifests, enabling it to watch nodes and pods. ([#57455](https://github.com/kubernetes/kubernetes/pull/57455), [@kawych](https://github.com/kawych)) - -* Fix RBAC role for certificate controller to allow cleaning up of Certificate Signing Requests that are Approved and issued or Denied. ([#59375](https://github.com/kubernetes/kubernetes/pull/59375), [@mikedanese](https://github.com/mikedanese)) - -* kube-apiserver: Use of the `--admission-control-config-file` with a file containing an AdmissionConfiguration apiserver.k8s.io/v1alpha1 config object no longer leads to an error when launching kube-apiserver. ([#58439]([https://github.com/kubernetes/kubernetes/pull/58439](https://github.com/kubernetes/kubernetes/pull/58439)) [@liggitt](https://github.com/liggitt)) - -* Default enabled admission plugins are now `NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota`. Please note that if you previously had not set the `--admission-control` flag, your cluster behavior may change (to be more standard). ([#58684](https://github.com/kubernetes/kubernetes/pull/58684), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) - -* Encryption key and encryption provider rotation now works properly. ([#58375](https://github.com/kubernetes/kubernetes/pull/58375), [@liggitt](https://github.com/liggitt)) - -* RBAC: The system:kubelet-api-admin cluster role can be used to grant full access to the kubelet API so integrators can grant this role to the --kubelet-client-certificate credential given to the apiserver. ([#57128](https://github.com/kubernetes/kubernetes/pull/57128), [@liggitt](https://github.com/liggitt)) - -* DenyEscalatingExec admission controller now checks psp HostNetwork as well as hostIPC and hostPID. hostNetwork is also checked to deny exec /attach. ([#56839](https://github.com/kubernetes/kubernetes/pull/56839), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) - -* When using Role-Based Access Control, the "admin", "edit", and "view" roles now have the expected permissions on NetworkPolicy resources, rather than reserving those permissions to only cluster-admin. ([#56650](https://github.com/kubernetes/kubernetes/pull/56650), [@danwinship](https://github.com/danwinship)) - -* Added docker-logins config to kubernetes-worker charm. ([#56217](https://github.com/kubernetes/kubernetes/pull/56217), [@Cynerva](https://github.com/Cynerva)) - -* Add ability to control primary GID of containers through Pod Spec at Pod level and Per Container SecurityContext level. ([#52077](https://github.com/kubernetes/kubernetes/pull/52077), [@krmayankk](https://github.com/krmayankk)) - -### CLI - -* Use structured generator for kubectl autoscale. ([#55913](https://github.com/kubernetes/kubernetes/pull/55913), [@wackxu](https://github.com/wackxu)) - -* Allow kubectl to set image|env on a cronjob ([#57742](https://github.com/kubernetes/kubernetes/pull/57742), [@soltysh](https://github.com/soltysh)) - -* Fixed crash in kubectl cp when path has multiple leading slashes. ([#58144](https://github.com/kubernetes/kubernetes/pull/58144), [@tomerf](https://github.com/tomerf)) - -* kubectl port-forward now allows using resource name (e.g., deployment/www) to select a matching pod, as well as the use of --pod-running-timeout to wait until at least one pod is running. ([#59705](https://github.com/kubernetes/kubernetes/pull/59705), [@phsiao](https://github.com/phsiao)) - -* 'cj' has been added as a shortname for CronJobs, as in `kubectl get cj` ([#59499](https://github.com/kubernetes/kubernetes/pull/59499), [@soltysh](https://github.com/soltysh)) - -* `crds` has been added as a shortname for CustomResourceDefinition, as in `kubectl get crds` ([#59061](https://github.com/kubernetes/kubernetes/pull/59061), [@nikhita](https://github.com/nikhita)) - -* Fix kubectl explain for resources not existing in default version of API group, such as `batch/v1, Kind=CronJob`. ([#58753](https://github.com/kubernetes/kubernetes/pull/58753), [@soltysh](https://github.com/soltysh)) - -* Added the ability to select pods in a chosen node to be drained based on given pod label-selector. ([#56864](https://github.com/kubernetes/kubernetes/pull/56864), [@juanvallejo](https://github.com/juanvallejo)) - -* Kubectl explain now prints out the Kind and API version of the resource being explained. ([#55689](https://github.com/kubernetes/kubernetes/pull/55689), [@luksa](https://github.com/luksa)) - -### Cluster Lifecycle - -* The default Kubernetes version for kubeadm is now 1.10. ([#61127](https://github.com/kubernetes/kubernetes/pull/61127), [@timothysc](https://github.com/timothysc)) - -* The minimum Kubernetes version in kubeadm is now v1.9.0. ([#57233](https://github.com/kubernetes/kubernetes/pull/57233), [@xiangpengzhao](https://github.com/xiangpengzhao)) - -* Fixes a bug in Heapster deployment for google sink. ([#57902](https://github.com/kubernetes/kubernetes/pull/57902), [@kawych](https://github.com/kawych)) - -* On cluster provision or upgrade, kubeadm now generates certs and secures all connections to the etcd static-pod with mTLS. This includes the etcd serving cert, the etcd peer cert, and the apiserver etcd client cert. Flags and hostMounts are added to the etcd and apiserver static-pods to load these certs. For connections to etcd, https is now used in favor of http. ([#57415](https://github.com/kubernetes/kubernetes/pull/57415), [@stealthybox](https://github.com/stealthybox)) These certs are also generated on upgrade. ([#60385](https://github.com/kubernetes/kubernetes/pull/60385), [@stealthybox](https://github.com/stealthybox)) - -* Demoted controlplane passthrough flags apiserver-extra-args, controller-manager-extra-args, scheduler-extra-args to alpha flags ([#59882](https://github.com/kubernetes/kubernetes/pull/59882), [@kris-nova](https://github.com/kris-nova)) - -* The new flag `--apiserver-advertise-dns-address` is used in the node's kubelet.confg to point to the API server, allowing users to define a DNS entry instead of an IP address. ([#59288](https://github.com/kubernetes/kubernetes/pull/59288), [@stevesloka](https://github.com/stevesloka)) - -* MasterConfiguration manifiest The criSocket flag is now usable within the `MasterConfiguration` and `NodeConfiguration` manifest files that exist for configuring kubeadm. Before it only existed as a command line flag and was not able to be configured when using the `--config` flag and the manifest files. ([#59057](https://github.com/kubernetes/kubernetes/pull/59057))([#59292](https://github.com/kubernetes/kubernetes/pull/59292), [@JordanFaust](https://github.com/JordanFaust)) - -* `kubeadm init` can now omit the tainting of the master node if configured to do so in `kubeadm.yaml` using `noTaintMaster: true`. For example, uses can create a file with the content: - -``` -apiVersion: [kubeadm.k8s.io/v1alpha1](http://kubeadm.k8s.io/v1alpha1) -kind: MasterConfiguration -kubernetesVersion: v1.9.1 -noTaintMaster: true -``` - -And point to the file using the --config flag, as in - -`kubeadm init --config /etc/kubeadm/kubeadm.yaml` - -([#55479](https://github.com/kubernetes/kubernetes/pull/55479), [@ijc](https://github.com/ijc)) - -* kubeadm: New "imagePullPolicy" option in the init configuration file, that gets forwarded to kubelet static pods to control pull policy for etcd and control plane images. This option allows for precise image pull policy specification for master nodes and thus for more tight control over images. It is useful in CI environments and in environments, where the user has total control over master VM templates (thus, the master VM templates can be preloaded with the required Docker images for the control plane services). ([#58960](https://github.com/kubernetes/kubernetes/pull/58960), [@rosti](https://github.com/rosti)) - -* Fixed issue with charm upgrades resulting in an error state. ([#59064](https://github.com/kubernetes/kubernetes/pull/59064), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* kube-apiserver --advertise-address is now set using downward API for self-hosted Kubernetes with kubeadm. ([#56084](https://github.com/kubernetes/kubernetes/pull/56084), [@andrewsykim](https://github.com/andrewsykim)) - -* When using client or server certificate rotation, the Kubelet will no longer wait until the initial rotation succeeds or fails before starting static pods. This makes running self-hosted masters with rotation more predictable. ([#58930](https://github.com/kubernetes/kubernetes/pull/58930), [@smarterclayton](https://github.com/smarterclayton)) - -* Kubeadm no longer throws an error for the --cloud-provider=external flag. ([#58259](https://github.com/kubernetes/kubernetes/pull/58259), [@dims](https://github.com/dims)) - -* Added support for network spaces in the kubeapi-load-balancer charm. ([#58708](https://github.com/kubernetes/kubernetes/pull/58708), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* Added support for network spaces in the kubernetes-master charm. ([#58704](https://github.com/kubernetes/kubernetes/pull/58704), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* Added support for network spaces in the kubernetes-worker charm. ([#58523](https://github.com/kubernetes/kubernetes/pull/58523), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* Added support for changing nginx and default backend images to kubernetes-worker config. ([#58542](https://github.com/kubernetes/kubernetes/pull/58542), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* kubeadm now accepts `--apiserver-extra-args`, `--controller-manager-extra-args` and `--scheduler-extra-args`, making it possible to override / specify additional flags for control plane components. One good example is to deploy Kubernetes with a different admission-control flag on API server. ([#58080](https://github.com/kubernetes/kubernetes/pull/58080), [@simonferquel](https://github.com/simonferquel)) - -* Alpha Initializers have been removed from kubadm admission control. Kubeadm users who still want to use Initializers can use apiServerExtraArgs through the kubeadm config file to enable it when booting up the cluster. ([#58428](https://github.com/kubernetes/kubernetes/pull/58428), [@dixudx](https://github.com/dixudx)) - -* ValidatingAdmissionWebhook and MutatingAdmissionWebhook are beta, and are enabled in kubeadm by default. ([#58255](https://github.com/kubernetes/kubernetes/pull/58255), [@dixudx](https://github.com/dixudx)) - -* Add proxy_read_timeout flag to kubeapi_load_balancer charm. ([#57926](https://github.com/kubernetes/kubernetes/pull/57926), [@wwwtyro](https://github.com/wwwtyro)) - -* Check for known manifests during preflight instead of only checking for non-empty manifests directory. This makes the preflight checks less heavy-handed by specifically checking for well-known files (kube-apiserver.yaml, kube-controller-manager.yaml, kube-scheduler.yaml, etcd.yaml) in /etc/kubernetes/manifests instead of simply checking for a non-empty directory. ([#57287](https://github.com/kubernetes/kubernetes/pull/57287), [@mattkelly](https://github.com/mattkelly)) - -* PVC Protection alpha feature was renamed to Storage Protection. The Storage Protection feature is beta. ([#59052](https://github.com/kubernetes/kubernetes/pull/59052), [@pospispa](https://github.com/pospispa)) - -* iSCSI sessions managed by kubernetes will now explicitly set startup.mode to 'manual' to prevent automatic login after node failure recovery. This is the default open-iscsi mode, so this change will only impact users who have changed their startup.mode to be 'automatic' in /etc/iscsi/iscsid.conf. ([#57475](https://github.com/kubernetes/kubernetes/pull/57475), [@stmcginnis](https://github.com/stmcginnis)) - -* The IPVS feature gateway is now enabled by default in kubeadm, which makes the --feature-gates=SupportIPVSProxyMode=true obsolete, and it is no longer supported. ([#60540](https://github.com/kubernetes/kubernetes/pull/60540), [@m1093782566](https://github.com/m1093782566)) - -### GCP - -* ingress-gce image in glbc.manifest updated to 1.0.0 ([#61302](https://github.com/kubernetes/kubernetes/pull/61302), [@rramkumar1](https://github.com/rramkumar1)) - -### Instrumentation - -* For advanced auditing, audit policy supports subresources wildcard matching, such as "resource/", "/subresource","*". ([#55306](https://github.com/kubernetes/kubernetes/pull/55306), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) - -* [Auditing](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/) is now enabled behind a featureGate in kubeadm. A user can supply their own audit policy with configuration option as well as a place for the audit logs to live. If no policy is supplied a default policy will be provided. The default policy will log all Metadata level policy logs. It is the example provided in the documentation. ([#59067](https://github.com/kubernetes/kubernetes/pull/59067), [@chuckha](https://github.com/chuckha)) - -* Reduce Metrics Server memory requirement from 140Mi + 4Mi per node to 40Mi + 4Mi per node. ([#58391](https://github.com/kubernetes/kubernetes/pull/58391), [@kawych](https://github.com/kawych)) - -* Annotations is added to advanced audit api. ([#58806](https://github.com/kubernetes/kubernetes/pull/58806), [@CaoShuFeng](https://github.com/CaoShuFeng)) - -* Reorganized iptables rules to fix a performance regression on clusters with thousands of services. ([#56164](https://github.com/kubernetes/kubernetes/pull/56164), [@danwinship](https://github.com/danwinship)) - -* Container runtime daemon (e.g. dockerd) logs in GCE cluster will be uploaded to stackdriver and elasticsearch with tag `container-runtime`. ([#59103](https://github.com/kubernetes/kubernetes/pull/59103), [@Random-Liu](https://github.com/Random-Liu)) - -* Enable prometheus apiserver metrics for custom resources. ([#57682](https://github.com/kubernetes/kubernetes/pull/57682), [@nikhita](https://github.com/nikhita)) - -* Add apiserver metric for number of requests dropped because of inflight limit, making it easier to figure out on which dimension the master is overloaded. ([#58340](https://github.com/kubernetes/kubernetes/pull/58340), [@gmarek](https://github.com/gmarek)) - -* The Metrics Server now exposes metrics via the /metric endpoint. These metrics are in the prometheus format. ([#57456](https://github.com/kubernetes/kubernetes/pull/57456), [@kawych](https://github.com/kawych)) - -* Reduced the CPU and memory requests for the Metrics Server Nanny sidecar container to free up unused resources. ([#57252](https://github.com/kubernetes/kubernetes/pull/57252), [@kawych](https://github.com/kawych)) - -* Enabled log rotation for load balancer's api logs to prevent running out of disk space. ([#56979](https://github.com/kubernetes/kubernetes/pull/56979), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* Fixed `etcd-version-monitor` to backward compatibly support etcd 3.1 [go-grpc-prometheus](https://github.com/grpc-ecosystem/go-grpc-prometheus) metrics format. ([#56871](https://github.com/kubernetes/kubernetes/pull/56871), [@jpbetz](https://github.com/jpbetz)) - -### Node - -* Summary of Container Runtime changes: - * [beta] [cri-tools](https://github.com/kubernetes-incubator/cri-tools): CLI and validation tools for CRI is now v1.0.0-beta.0. This release mainly focused on UX improvements. [@feiskyer] - * [stable] [containerd](https://github.com/containerd/containerd): containerd v1.1 natively supports CRI v1alpha2 now, so users can use Kubernetes v1.10 with containerd v1.1 directly, without having to use the intermediate cri-containerd daemon. [All Kubernetes 1.10 tests passed](https://k8s-testgrid.appspot.com/sig-node-containerd). [@Random-Liu] - * [stable] [cri-o](https://github.com/kubernetes-incubator/cri-o): cri-o v1.10 updated CRI version to v1alpha2 and made several bug and stability fixes. [@mrunalp] - * [stable] [frakti](https://github.com/kubernetes/frakti): frakti v1.10 implemented GCE Persistent Disk as a high performance volume, fixed several bugs, added ARM64 support, and passed all CRI validation conformance tests and node e2e conformance tests. [@resouer] - * [alpha] CRI now supports specifying the GID of the container at both LinuxSandboxSecurityContext and LinuxContainerSecurityContext in addition to specifying the UID. Support is implemented for dockershim. [@krmayankk] - -* Fixed race conditions around devicemanager Allocate() and endpoint deletion. ([#60856](https://github.com/kubernetes/kubernetes/pull/60856), [@jiayingz](https://github.com/jiayingz)) - -* kubelet initial flag parse now normalizes flags instead of exiting. ([#61053](https://github.com/kubernetes/kubernetes/pull/61053), [@andrewsykim](https://github.com/andrewsykim)) - -* Fixed regression where kubelet --cpu-cfs-quota flag did not work when --cgroups-per-qos was enabled ([#61294](https://github.com/kubernetes/kubernetes/pull/61294), [@derekwaynecarr](https://github.com/derekwaynecarr)) - -* Kubelet now supports container log rotation for container runtimes implementing CRI (container runtime interface). The feature can be enabled with feature gate `CRIContainerLogRotation`. The flags `--container-log-max-size` and `--container-log-max-files` can be used to configure the rotation behavior. ([#59898](https://github.com/kubernetes/kubernetes/pull/59898), [@Random-Liu](https://github.com/Random-Liu)) - -* Fixed a bug where if an error was returned that was not an `autorest.DetailedError` we would return `"not found", nil` which caused nodes to go to `NotReady` state. ([#57484](https://github.com/kubernetes/kubernetes/pull/57484), [@brendandburns](https://github.com/brendandburns)) - -* [HugePages](https://kubernetes.io/docs/tasks/manage-hugepages/scheduling-hugepages/) feature is beta, and thus enabled by default. ([#56939](https://github.com/kubernetes/kubernetes/pull/56939), [@derekwaynecarr](https://github.com/derekwaynecarr)) - -* Avoid panic when failing to allocate a Cloud CIDR (aka GCE Alias IP Range). ([#58186](https://github.com/kubernetes/kubernetes/pull/58186), [@negz](https://github.com/negz)) - -* 'none' can now be specified in KubeletConfiguration.EnforceNodeAllocatable (--enforce-node-allocatable) to explicitly disable enforcement. ([#59515](https://github.com/kubernetes/kubernetes/pull/59515), [@mtaufen](https://github.com/mtaufen)) - -* The alpha KubeletConfiguration.ConfigTrialDuration field is no longer available. It can still be set using the dynamic configuration alpha feature. ([#59628](https://github.com/kubernetes/kubernetes/pull/59628), [@mtaufen](https://github.com/mtaufen)) - -* Summary API will include pod CPU and Memory stats for CRI container runtime. ([#60328](https://github.com/kubernetes/kubernetes/pull/60328), [@Random-Liu](https://github.com/Random-Liu)) - -* Some field names in the Kubelet's now v1beta1 config API differ from the v1alpha1 API: for example, PodManifestPath is renamed to StaticPodPath, ManifestURL is renamed to StaticPodURL, and ManifestURLHeader is renamed to StaticPodURLHeader. Users should focus on switching to the v1beta1 API. ([#60314](https://github.com/kubernetes/kubernetes/pull/60314), [@mtaufen](https://github.com/mtaufen)) - -* The DevicePlugins feature has graduated to beta, and is now enabled by default; users should focus on moving to the v1beta API if possible. ([#60170](https://github.com/kubernetes/kubernetes/pull/60170), [@jiayingz](https://github.com/jiayingz)) - -* Per-cpu metrics have been disabled by default for to improve scalability. ([#60106](https://github.com/kubernetes/kubernetes/pull/60106), [@dashpole](https://github.com/dashpole)) - -* When the `PodShareProcessNamespace` alpha feature is enabled, setting `pod.Spec.ShareProcessNamespace` to `true` will cause a single process namespace to be shared between all containers in a pod. ([#58716](https://github.com/kubernetes/kubernetes/pull/58716), [@verb](https://github.com/verb)) - -* Resource quotas on extended resources such as GPUs are now supported. ([#57302](https://github.com/kubernetes/kubernetes/pull/57302), [@lichuqiang](https://github.com/lichuqiang)) - -* If the TaintNodesByCondition is enabled, a node will be tainted when it is under PID pressure. ([#60008](https://github.com/kubernetes/kubernetes/pull/60008), [@k82cn](https://github.com/k82cn)) - -* The Kubelet Summary API will now include total usage of pods through the "pods" SystemContainer. ([#57802](https://github.com/kubernetes/kubernetes/pull/57802), [@dashpole](https://github.com/dashpole)) - -* vSphere Cloud Provider supports VMs provisioned on vSphere v6.5. ([#59519](https://github.com/kubernetes/kubernetes/pull/59519), [@abrarshivani](https://github.com/abrarshivani)) - -* Created k8s.gcr.io image repo alias to pull images from the closest regional repo. Replaces gcr.io/google_containers. ([#57824](https://github.com/kubernetes/kubernetes/pull/57824), [@thockin](https://github.com/thockin)) - -* Fix the bug where kubelet in the standalone mode would wait for the update from the apiserver source, even if there wasn't one. ([#59276](https://github.com/kubernetes/kubernetes/pull/59276), [@roboll](https://github.com/roboll)) - -* Changes secret, configMap, downwardAPI and projected volumes to mount read-only, instead of allowing applications to write data and then reverting it automatically. Until version 1.11, setting the feature gate ReadOnlyAPIDataVolumes=false will preserve the old behavior. ([#58720](https://github.com/kubernetes/kubernetes/pull/58720), [@joelsmith](https://github.com/joelsmith)) - -* Fixes a bug where kubelet crashes trying to free memory under memory pressure. ([#58574](https://github.com/kubernetes/kubernetes/pull/58574), [@yastij](https://github.com/yastij)) - -* New alpha feature limits the number of processes running in a pod. Cluster administrators will be able to place limits by using the new kubelet command line parameter --pod-max-pids. Note that since this is a alpha feature they will need to enable the "SupportPodPidsLimit" feature. By default, we do not set any maximum limit, If an administrator wants to enable this, they should enable SupportPodPidsLimit=true in the --feature-gates= parameter to kubelet and specify the limit using the --pod-max-pids parameter. The limit set is the total count of all processes running in all containers in the pod. ([#57973](https://github.com/kubernetes/kubernetes/pull/57973),[@dims](https://github.com/dims)) - -* Fixes bug finding master replicas in GCE when running multiple Kubernetes clusters. ([#58561](https://github.com/kubernetes/kubernetes/pull/58561), [@jesseshieh](https://github.com/jesseshieh)) - -* --tls-min-version on kubelet and kube-apiserver allow for configuring minimum TLS versions ([#58528](https://github.com/kubernetes/kubernetes/pull/58528), [@deads2k](https://github.com/deads2k)) - -* Fix a bug affecting nested data volumes such as secret, configmap, etc. ([#57422](https://github.com/kubernetes/kubernetes/pull/57422), [@joelsmith](https://github.com/joelsmith)) - -* kubelet will no longer attempt to remove images being used by running containers when garbage collecting. ([#57020](https://github.com/kubernetes/kubernetes/pull/57020), [@dixudx](https://github.com/dixudx)) - -* Allow kubernetes components to react to SIGTERM signal and shutdown gracefully. ([#57756](https://github.com/kubernetes/kubernetes/pull/57756), [@mborsz](https://github.com/mborsz)) - -* Fixed garbage collection and resource quota issue when the controller-manager uses --leader-elect=false ([#57340](https://github.com/kubernetes/kubernetes/pull/57340), [@jmcmeek](https://github.com/jmcmeek)) - -* Fixed issue creating docker secrets with kubectl 1.9 for accessing docker private registries. ([#57463](https://github.com/kubernetes/kubernetes/pull/57463), [@dims](https://github.com/dims)) - -* The CPU Manager feature is now beta, and is enabled by default, but the default policy is no-op so no action is required. ([#55977](https://github.com/kubernetes/kubernetes/pull/55977), [@ConnorDoyle](https://github.com/ConnorDoyle)) - -### OpenStack - -* Fixed a bug in the OpenStack cloud provider where dual stack deployments (IPv4 and IPv6) did not work well when using kubenet as the network plugin. ([#59749](https://github.com/kubernetes/kubernetes/pull/59749), [@zioproto](https://github.com/zioproto)) - -* Fixed a bug that tries to use the octavia client to query flip. ([#59075](https://github.com/kubernetes/kubernetes/pull/59075), [@jrperritt](https://github.com/jrperritt)) - -* Kubernetes now registers metadata.hostname as node name for OpenStack nodes, eliminating a problem with invalid node names. ([#58502](https://github.com/kubernetes/kubernetes/pull/58502), [@dixudx](https://github.com/dixudx)) - -* Authentication information for OpenStack cloud provider can now be specified as environment variables. When we convert the OpenStack cloud provider to run in an external process, we can now use the kubernetes Secrets capability to inject the OS_* variables. This way we can specify the cloud configuration as a configmap, and specify secrets for the userid/password information. The configmap is mounted as a file, and the secrets are made available as environment variables. The external controller itself runs as a pod/daemonset. For backward compatibility, we preload all the OS_* variables, and if anything is in the config file, then that overrides the environment variables. ([#58300](https://github.com/kubernetes/kubernetes/pull/58300), [@dims](https://github.com/dims)) - -* Fixed issue when using OpenStack config drive for node metadata. Since we need to run commands such as blkid, we need to ensure that api server and kube controller are running in the privileged mode. ([#57561](https://github.com/kubernetes/kubernetes/pull/57561), [@dims](https://github.com/dims)) - -* Orphaned routes are properly removed from terminated instances. ([#56258](https://github.com/kubernetes/kubernetes/pull/56258), [@databus23](https://github.com/databus23)) - -* OpenStack Cinder will now detach properly when Nova is shut down. ([#56846](https://github.com/kubernetes/kubernetes/pull/56846), [@zetaab](https://github.com/zetaab)) -### Scalability - -* Added the ability to limit the increase in apiserver memory usage when audit logging with buffering is enabled. ([#61118](https://github.com/kubernetes/kubernetes/pull/61118), [@shyamjvs](https://github.com/shyamjvs)) - -* Upgrade to etcd client 3.2.13 and grpc 1.7.5 to improve HA etcd cluster stability. ([#57480](https://github.com/kubernetes/kubernetes/pull/57480), [@jpbetz](https://github.com/jpbetz)) - -### Storage - -* Fixes CVE-2017-1002101 - See [https://issue.k8s.io/60813](https://issue.k8s.io/60813) for details on this **major security fix**. ([#61044](https://github.com/kubernetes/kubernetes/pull/61044), [@liggitt](https://github.com/liggitt)) - -* Fixed missing error checking that could cause kubelet to crash in a race condition. ([#60962](https://github.com/kubernetes/kubernetes/pull/60962), [@technicianted](https://github.com/technicianted)) - -* Fixed a regression that prevented using `subPath` volume mounts with secret, configMap, projected, and downwardAPI volumes. ([#61080](https://github.com/kubernetes/kubernetes/pull/61080), [@liggitt](https://github.com/liggitt)) - -* K8s supports cephfs fuse mount. ([#55866](https://github.com/kubernetes/kubernetes/pull/55866), [@zhangxiaoyu-zidif](https://github.com/zhangxiaoyu-zidif)) - -* Use GiB unit for creating and resizing volumes for Glusterfs. ([#56581](https://github.com/kubernetes/kubernetes/pull/56581), [@gnufied](https://github.com/gnufied)) - -* Adding support for Block Volume type to rbd plugin. ([#56651](https://github.com/kubernetes/kubernetes/pull/56651), [@sbezverk](https://github.com/sbezverk)) - -* Add FSType for CSI volume source to specify filesystems (alpha defaults to ext4) ([#58209](https://github.com/kubernetes/kubernetes/pull/58209), [@NickrenREN](https://github.com/NickrenREN)) - -* Enabled File system resize of mounted volumes. ([#58794](https://github.com/kubernetes/kubernetes/pull/58794), [@gnufied](https://github.com/gnufied)) - -* The Local Volume Plugin has been updated to support Block volumeMode PVs. With this change, it is now possible to create local volume PVs for raw block devices. ([#59303](https://github.com/kubernetes/kubernetes/pull/59303), [@dhirajh](https://github.com/dhirajh)) - -* Fixed an issue where Portworx volume driver wasn't passing namespace and annotations to the Portworx Create API. ([#59607](https://github.com/kubernetes/kubernetes/pull/59607), [@harsh-px](https://github.com/harsh-px)) - -* Addressed breaking changes introduced by new 0.2.0 release of CSI spec. Specifically, csi.Version was removed from all API calls and CcontrollerProbe and NodeProbe were consolidated into a single Probe API call. ([#59209](https://github.com/kubernetes/kubernetes/pull/59209), [@sbezverk](https://github.com/sbezverk)) - -* GCE PD volume plugin now supports block volumes. ([#58710](https://github.com/kubernetes/kubernetes/pull/58710), [@screeley44](https://github.com/screeley44)) - -* Implements MountDevice and UnmountDevice for the CSI Plugin, the functions will call through to NodeStageVolume/NodeUnstageVolume for CSI plugins. ([#60115](https://github.com/kubernetes/kubernetes/pull/60115), [@davidz627](https://github.com/davidz627)) - -* The LocalStorageCapacityIsolation feature is beta and enabled by default. The LocalStorageCapacityIsolation feature added a new resource type ResourceEphemeralStorage "ephemeral-storage" so that this resource can be allocated, limited, and consumed as the same way as CPU/memory. All the features related to resource management (resource request/limit, quota, limitrange) are available for local ephemeral storage. This local ephemeral storage represents the storage for root file system, which will be consumed by containers' writable layer and logs. Some volumes such as emptyDir might also consume this storage. ([#60159](https://github.com/kubernetes/kubernetes/pull/60159), [@jingxu97](https://github.com/jingxu97)) - -* VolumeScheduling and LocalPersistentVolume features are beta and enabled by default. The PersistentVolume NodeAffinity alpha annotation is deprecated and will be removed in a future release. ([#59391](https://github.com/kubernetes/kubernetes/pull/59391), [@msau42](https://github.com/msau42)) - -* K8s now supports rbd-nbd for Ceph rbd volume mounts. ([#58916](https://github.com/kubernetes/kubernetes/pull/58916), [@ianchakeres](https://github.com/ianchakeres)) - -* CSI now allows credentials to be specified on CreateVolume/DeleteVolume, ControllerPublishVolume/ControllerUnpublishVolume, and NodePublishVolume/NodeUnpublishVolume operations. Before this change all API calls had to fetch key/value stored in secret and use it to authenticate/authorize these operations. With this change API calls receive key/value as a input parameter so they not need to know where and how credentials were stored and fetched. Main goal was to make these API calls CO (Container Orchestrator) agnostic. ([#60118](https://github.com/kubernetes/kubernetes/pull/60118), [@sbezverk](https://github.com/sbezverk)) - -* StorageOS volume plugin has been updated to support mount options and environments where the kubelet runs in a container and the device location should be specified. ([#58816](https://github.com/kubernetes/kubernetes/pull/58816), [@croomes](https://github.com/croomes)) - -* Get parent dir via canonical absolute path when trying to judge mount-point, fixing a problem that caused an NFS volume with improper permissions to get stuck in `TERMINATING` status. ([#58433](https://github.com/kubernetes/kubernetes/pull/58433), [@yue9944882](https://github.com/yue9944882)) - -* Clusters with GCE feature 'DiskAlphaAPI' enabled can now dynamically provision GCE PD volumes. ([#59447](https://github.com/kubernetes/kubernetes/pull/59447), [@verult](https://github.com/verult)) - -* Added `keyring` parameter for Ceph RBD provisioner. ([#58287](https://github.com/kubernetes/kubernetes/pull/58287), [@madddi](https://github.com/madddi)) - -* Added xfsprogs to hyperkube container image. ([#56937](https://github.com/kubernetes/kubernetes/pull/56937), [@redbaron](https://github.com/redbaron)) - -* Improved messages user gets during and after volume resizing is done, providing a clear message to the user explaining what to do when resizing is finished. ([#58415](https://github.com/kubernetes/kubernetes/pull/58415), [@gnufied](https://github.com/gnufied)) - -* MountPropagation feature is now beta. As consequence, all volume mounts in containers are now "rslave" on Linux by default. To make this default work in all Linux environments you should have entire mount tree marked as shareable via "mount --make-rshared /". All Linux distributions that use systemd already have root directory mounted as rshared and hence they need not do anything. In Linux environments without systemd we recommend running "mount --make-rshared /" during boot, before docker is started. ([#59252](https://github.com/kubernetes/kubernetes/pull/59252), [@jsafrane](https://github.com/jsafrane)) - -* Volume metrics support for vSphere Cloud Provider has been added. You can now monitor available space, capacity, and used space on volumes created using vSphere. ([#59328](https://github.com/kubernetes/kubernetes/pull/59328), [@divyenpatel](https://github.com/divyenpatel)) - -* Emit number of bound and unbound persistent volumes as Metrics. This PR adds four kinds of Volume Metrics for kube-controller-manager: bound PVC numbers, unbound PVC numbers, bound PV numbers and unbound PV numbers. The PVC metrics use namespace as dimension and the PV metrics use StorageClassName as its dimension. With these metrics we can better monitor the use of volumes in the cluster. ([#57872](https://github.com/kubernetes/kubernetes/pull/57872), [@mlmhl](https://github.com/mlmhl)) - -* Add windows config to Kubelet CRI so that WindowsContainerResources can be managed. ([#57076](https://github.com/kubernetes/kubernetes/pull/57076), [@feiskyer](https://github.com/feiskyer)) - -* PersistentVolumes that are bound to a PersistentVolumeClaim will not be deleted. ([#58743](https://github.com/kubernetes/kubernetes/pull/58743), [@NickrenREN](https://github.com/NickrenREN)) - -* The VolumeAttachment API is now available as V1beta1, and is enabled by default. The Alpha API is deprecated and will be removed in a future release. ([#58462](https://github.com/kubernetes/kubernetes/pull/58462), [@NickrenREN](https://github.com/NickrenREN)) - -* Add storage-backend configuration option to kubernetes-master charm. ([#58830](https://github.com/kubernetes/kubernetes/pull/58830), [@wwwtyro](https://github.com/wwwtyro)) - -* Fixed dynamic provisioning of GCE PDs to round to the next GB (base 1000) instead of GiB (base 1024). ([#56600](https://github.com/kubernetes/kubernetes/pull/56600), [@edisonxiang](https://github.com/edisonxiang)) - -* PersistentVolume flexVolume sources can now reference secrets in a namespace other than the PersistentVolumeClaim's namespace. ([#56460](https://github.com/kubernetes/kubernetes/pull/56460), [@liggitt](https://github.com/liggitt)) - -### Windows - -* kubelet and kube-proxy can now be run as native Windows services. ([#60144](https://github.com/kubernetes/kubernetes/pull/60144), [@alinbalutoiu](https://github.com/alinbalutoiu)) - -* WindowsContainerResources is set now for windows containers. ([#59333](https://github.com/kubernetes/kubernetes/pull/59333), [@feiskyer](https://github.com/feiskyer)) - -* Disable mount propagation for windows containers (because it is not supported by the OS). ([#60275](https://github.com/kubernetes/kubernetes/pull/60275), [@feiskyer](https://github.com/feiskyer)) - -* Fix image file system stats for windows nodes. ([#59743](https://github.com/kubernetes/kubernetes/pull/59743), [@feiskyer](https://github.com/feiskyer)) - -* Kubernetes will now return an error if New-SmbGlobalMapping failed when mounting an azure file on Windows. ([#59540](https://github.com/kubernetes/kubernetes/pull/59540), [@andyzhangx](https://github.com/andyzhangx)) - -* Kubernetes now uses the more reliable GlobalMemoryStatusEx to get total physical memory on windows nodes. ([#57124](https://github.com/kubernetes/kubernetes/pull/57124), [@JiangtianLi](https://github.com/JiangtianLi)) - -* Windows containers now support experimental Hyper-V isolation by setting annotation `experimental.windows.kubernetes.io/isolation-type=hyperv` and feature gates HyperVContainer. At the moment this function only supports one container per pod. ([#58751]([https://github.com/kubernetes/kubernetes/pull/58751](https://github.com/kubernetes/kubernetes/pull/58751)), [@feiskyer](https://github.com/feiskyer)) - -* Get windows kernel version directly from registry rather than windows.getVersion(). ([#58498](https://github.com/kubernetes/kubernetes/pull/58498), [@feiskyer](https://github.com/feiskyer)) - -* Fixed controller manager crash when using mixed case names in a vSphere cloud provider environment. ([#57286](https://github.com/kubernetes/kubernetes/pull/57286), [@rohitjogvmw](https://github.com/rohitjogvmw)) - -* Flexvolume is now [enabled on Windows nodes](https://github.com/andyzhangx/Demo/tree/master/windows/flexvolume). ([#56921](https://github.com/kubernetes/kubernetes/pull/56921), [@andyzhangx](https://github.com/andyzhangx)) - -### Autoscaling - -* The getSubnetIDForLB() returns subnet id rather than net id. ([#58208](https://github.com/kubernetes/kubernetes/pull/58208), [@FengyunPan](https://github.com/FengyunPan)) - -* `kubectl scale` can now scale any resource (kube, CRD, aggregate) conforming to the standard scale endpoint ([#58298](https://github.com/kubernetes/kubernetes/pull/58298), [@p0lyn0mial](https://github.com/p0lyn0mial)) - -* Cluster Autoscaler has been updated to Version 1.2.0, which includes fixes around GPUs and base image change. See [https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-](https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.1.2)1.2.0for details. ([#60842](https://github.com/kubernetes/kubernetes/pull/60842), [@mwielgus](https://github.com/mwielgus)) - -* Allows HorizontalPodAutoscaler to use global metrics not associated with any Kubernetes object (for example metrics from a hosting service running outside of the Kubernetes cluster). ([#60096](https://github.com/kubernetes/kubernetes/pull/60096), [@MaciekPytel](https://github.com/MaciekPytel)) - -* fluentd-gcp resources can be modified via a ScalingPolicy. ([#59657](https://github.com/kubernetes/kubernetes/pull/59657), [@x13n](https://github.com/x13n)) - -* Added anti-affinity to kube-dns pods. Otherwise the "no single point of failure" setting doesn't actually work (a single node failure can still take down the entire cluster). ([#57683](https://github.com/kubernetes/kubernetes/pull/57683), [@vainu-arto](https://github.com/vainu-arto)) - -### API-Machinery - -* Fixed webhooks to use the scheme provided in clientConfig, instead of defaulting to http. ([#60943](https://github.com/kubernetes/kubernetes/pull/60943), [@jennybuckley](https://github.com/jennybuckley)) - -* The webhook admission controller in a custom apiserver now works off-the-shelf. ([#60995](https://github.com/kubernetes/kubernetes/pull/60995), [@caesarxuchao](https://github.com/caesarxuchao)) - -* Upgrade the default etcd server version to 3.1.12 to pick up critical etcd "mvcc "unsynced" watcher restore operation" fix. ([#60998](https://github.com/kubernetes/kubernetes/pull/60998), [@jpbetz](https://github.com/jpbetz)) - -* Fixed bug allowing garbage collector to enter a broken state that could only be fixed by restarting the controller-manager. ([#61201](https://github.com/kubernetes/kubernetes/pull/61201), [@jennybuckley](https://github.com/jennybuckley)) - -* kube-apiserver: The external hostname no longer longer use the cloud provider API to select a default. It can be set explicitly using --external-hostname, if needed. If there is no default, AdvertiseAddress or os.Hostname() will be used, in that order. ([#56812](https://github.com/kubernetes/kubernetes/pull/56812), [@dims](https://github.com/dims)) - -* Custom resources can be listed with a set of grouped resources (category) by specifying the categories in the [CustomResourceDefinition spec](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/#categories). Example: They can be used with `kubectl get important`, where `important` is a category. ([#59561](https://github.com/kubernetes/kubernetes/pull/59561), [@nikhita](https://github.com/nikhita)) - -* Fixed an issue making it possible to create a situation in which two webhooks make it impossible to delete each other. ValidatingWebhooks and MutatingWebhooks will not be called on admission requests for ValidatingWebhookConfiguration and MutatingWebhookConfiguration objects in the admissionregistration.k8s.io group ([#59840](https://github.com/kubernetes/kubernetes/pull/59840), [@jennybuckley](https://github.com/jennybuckley)) - -* Fixed potential deadlock when deleting CustomResourceDefinition for custom resources with finalizers. ([#60542](https://github.com/kubernetes/kubernetes/pull/60542), [@liggitt](https://github.com/liggitt)) - -* A buffered audit backend can be used with other audit backends. ([#60076](https://github.com/kubernetes/kubernetes/pull/60076), [@crassirostris](https://github.com/crassirostris)) - -* Introduced `--http2-max-streams-per-connection` command line flag on api-servers and set default to 1000 for aggregated API servers. ([#60054](https://github.com/kubernetes/kubernetes/pull/60054), [@MikeSpreitzer](https://github.com/MikeSpreitzer)) - -* APIserver backed by etcdv3 exports metric shows number of resources per kind. ([#59757](https://github.com/kubernetes/kubernetes/pull/59757), [@gmarek](https://github.com/gmarek)) - -* Add `kubectl create job --from-cronjob` command. ([#60084](https://github.com/kubernetes/kubernetes/pull/60084), [@soltysh](https://github.com/soltysh)) - -* `/status` and `/scale` subresources have been added for custom resources. See [https://github.com/kubernetes/kubernetes/pull/55168](https://github.com/kubernetes/kubernetes/pull/55168) for more details. ([#55168](https://github.com/kubernetes/kubernetes/pull/55168), [@nikhita](https://github.com/nikhita)) - -* Restores the ability of older clients to delete and scale jobs with initContainers. ([#59880](https://github.com/kubernetes/kubernetes/pull/59880), [@liggitt](https://github.com/liggitt)) - -* Fixed a race condition causing apiserver crashes during etcd healthchecking. ([#60069](https://github.com/kubernetes/kubernetes/pull/60069), [@wojtek-t](https://github.com/wojtek-t)) - -* Fixed a race condition in k8s.io/client-go/tools/cache.SharedInformer that could violate the sequential delivery guarantee and cause panics on shutdown in Kubernetes 1.8.* and 1.9.*. ([#59828](https://github.com/kubernetes/kubernetes/pull/59828), [@krousey](https://github.com/krousey)) - -* Add automatic etcd 3.2->3.1 and 3.1->3.0 minor version rollback support to gcr.io/google_container/etcd images. For HA clusters, all members must be stopped before performing a rollback. ([#59298](https://github.com/kubernetes/kubernetes/pull/59298), [@jpbetz](https://github.com/jpbetz)) - -* The `meta.k8s.io/v1alpha1` objects for retrieving tabular responses from the server (`Table`) or fetching just the `ObjectMeta` for an object (as `PartialObjectMetadata`) are now beta as part of `meta.k8s.io/v1beta1` and configurations must be changed to use the new API. Clients may request alternate representations of normal Kubernetes objects by passing an `Accept` header like `application/json;as=Table;g=meta.k8s.io;v=v1beta1` or `application/json;as=PartialObjectMetadata;g=meta.k8s.io;v1=v1beta1`. Older servers will ignore this representation or return an error if it is not available. Clients may request fallback to the normal object by adding a non-qualified mime-type to their `Accept` header like `application/json` - the server will then respond with either the alternate representation if it is supported or the fallback mime-type which is the normal object response. ([#59059](https://github.com/kubernetes/kubernetes/pull/59059), [@smarterclayton](https://github.com/smarterclayton)) - -* kube-apiserver now uses SSH tunnels for webhooks if the webhook is not directly routable from apiserver's network environment. ([#58644](https://github.com/kubernetes/kubernetes/pull/58644), [@yguo0905](https://github.com/yguo0905)) - -* Access to externally managed IP addresses via the kube-apiserver service proxy subresource is no longer allowed by default. This can be re-enabled via the `ServiceProxyAllowExternalIPs` feature gate, but will be disallowed completely in 1.11 ([#57265](https://github.com/kubernetes/kubernetes/pull/57265), [@brendandburns](https://github.com/brendandburns)) - -* The apiregistration.k8s.io (aggregation) is now generally available. Users should transition from the v1beta1 API to the v1 API. ([#58393](https://github.com/kubernetes/kubernetes/pull/58393), [@deads2k](https://github.com/deads2k)) - -* Fixes an issue where the resourceVersion of an object in a DELETE watch event was not the resourceVersion of the delete itself, but of the last update to the object. This could disrupt the ability of clients clients to re-establish watches properly. ([#58547](https://github.com/kubernetes/kubernetes/pull/58547), [@liggitt](https://github.com/liggitt)) - -* kube-apiserver: requests to endpoints handled by unavailable extension API servers (as indicated by an `Available` condition of `false` in the registered APIService) now return `503` errors instead of `404` errors. ([#58070](https://github.com/kubernetes/kubernetes/pull/58070), [@weekface](https://github.com/weekface)) - -* Custom resources can now be submitted to and received from the API server in application/yaml format, consistent with other API resources. ([#58260](https://github.com/kubernetes/kubernetes/pull/58260), [@liggitt](https://github.com/liggitt)) - -### Network - -* Fixed kube-proxy to work correctly with iptables 1.6.2 and later. ([#60978](https://github.com/kubernetes/kubernetes/pull/60978), [@danwinship](https://github.com/danwinship)) - -* Makes the kube-dns addon optional so that users can deploy their own DNS solution. ([#57113](https://github.com/kubernetes/kubernetes/pull/57113), [@wwwtyro](https://github.com/wwwtyro)) - -* `kubectl port-forward` now supports specifying a service to port forward to, as in `kubectl port-forward svc/myservice 8443:443`. Additional support has also been added for looking up targetPort for a service, as well as enabling using svc/name to select a pod. ([#59809](https://github.com/kubernetes/kubernetes/pull/59809), [@phsiao](https://github.com/phsiao)) -* [Make NodePort IP addres](https://github.com/kubernetes/website/pull/7631/files)[ses configurabl](https://github.com/kubernetes/website/pull/7631/files)[e](https://github.com/kubernetes/website/pull/7631/files). ([#58052](https://github.com/kubernetes/kubernetes/pull/58052), [@m1093782566](https://github.com/m1093782566)) - -* Fixed the issue in kube-proxy iptables/ipvs mode to properly handle incorrect IP version. ([#56880](https://github.com/kubernetes/kubernetes/pull/56880), [@MrHohn](https://github.com/MrHohn)) -* Kubeadm: CoreDNS supports migration of the kube-dns configuration to CoreDNS configuration when upgrading the service discovery from kube-dns to CoreDNS as part of Beta. ([#58828](https://github.com/kubernetes/kubernetes/pull/58828), [@rajansandeep](https://github.com/rajansandeep)) - -* Adds BETA support for `DNSConfig` field in PodSpec and `DNSPolicy=None`, so configurable pod resolve.conf is now enabled by default. ([#59771](https://github.com/kubernetes/kubernetes/pull/59771), [@MrHohn](https://github.com/MrHohn)) -* Removed some redundant rules created by the iptables proxier to improve performance on systems with very many services. ([#57461](https://github.com/kubernetes/kubernetes/pull/57461), [@danwinship](https://github.com/danwinship)) - -* Fix an issue where port forwarding doesn't forward local TCP6 ports to the pod ([#57457](https://github.com/kubernetes/kubernetes/pull/57457), [@vfreex](https://github.com/vfreex)) -* Correctly handle transient connection reset errors on GET requests from client library. ([#58520](https://github.com/kubernetes/kubernetes/pull/58520), [@porridge](https://github.com/porridge)) - -* GCE: Allows existing internal load balancers to continue using a subnetwork that may have been wrongfully chosen due to a bug choosing subnetworks on automatic networks. ([#57861](https://github.com/kubernetes/kubernetes/pull/57861), [@nicksardo](https://github.com/nicksardo)) -### Azure - -* Set node external IP for azure node when disabling UseInstanceMetadata. ([#60959](https://github.com/kubernetes/kubernetes/pull/60959), [@feiskyer](https://github.com/feiskyer)) - -* Changed default azure file/dir mode to 0755. ([#56551](https://github.com/kubernetes/kubernetes/pull/56551), [@andyzhangx](https://github.com/andyzhangx)) - -* Fixed azure file plugin failure issue on Windows after node restart. ([#60625](https://github.com/kubernetes/kubernetes/pull/60625), [@andyzhangx](https://github.com/andyzhangx))([#60623](https://github.com/kubernetes/kubernetes/pull/60623), [@feiskyer](https://github.com/feiskyer)) - -* Fixed race condition issue when detaching azure disk, preventing `Multi-Attach error`s when scheduling one pod from one node to another. ([#60183](https://github.com/kubernetes/kubernetes/pull/60183), [@andyzhangx](https://github.com/andyzhangx)) - -* Add AzureDisk support for vmss nodes. ([#59716]([https://github.com/kubernetes/kubernetes/pull/59716](https://github.com/kubernetes/kubernetes/pull/59716)), [@feiskyer](https://github.com/feiskyer)) - -* Map correct vmset name for Azure internal load balancers. ([#59747](https://github.com/kubernetes/kubernetes/pull/59747), [@feiskyer](https://github.com/feiskyer)) - -* Node's providerID will now follow the Azure resource ID format (`azure:///subscriptions//resourceGroups//providers/Microsoft.Compute/virtualMachines/` rather than `azure://d84a1c30-0c9f-11e8-8a34-000d3a919531`) when useInstanceMetadata is enabled ([#59539](https://github.com/kubernetes/kubernetes/pull/59539), [@feiskyer](https://github.com/feiskyer)) - -* Azure public IP is now correctly removed after a service is deleted. ([#59340](https://github.com/kubernetes/kubernetes/pull/59340), [@feiskyer](https://github.com/feiskyer)) - -* Added PV size grow feature for azure filesystems. ([#57017](https://github.com/kubernetes/kubernetes/pull/57017), [@andyzhangx](https://github.com/andyzhangx)) - -* Ensured IP is set for Azure internal load balancer. ([#59083](https://github.com/kubernetes/kubernetes/pull/59083), [@feiskyer](https://github.com/feiskyer)) - -* Set fsGroup by securityContext.fsGroup in azure file. However,f user both sets gid=xxx in mountOptions in azure storage class and securityContext.fsGroup, gid=xxx setting in mountOptions takes precedence. ([#58316](https://github.com/kubernetes/kubernetes/pull/58316), [@andyzhangx](https://github.com/andyzhangx)) - -* If an Azure disk is not found, K8s will immediately detach it. ([#58345](https://github.com/kubernetes/kubernetes/pull/58345), [@rootfs](https://github.com/rootfs)) -* Instrumented the Azure cloud provider for Prometheus monitoring. ([#58204](https://github.com/kubernetes/kubernetes/pull/58204), [@cosmincojocar](https://github.com/cosmincojocar)) - -* Fixed device name change issues for azure disk. ([#57953](https://github.com/kubernetes/kubernetes/pull/57953), [@andyzhangx](https://github.com/andyzhangx)) ([#57549](https://github.com/kubernetes/kubernetes/pull/57549), [@andyzhangx](https://github.com/andyzhangx)) - -* Support multiple scale sets in Azure cloud provider. ([#57543](https://github.com/kubernetes/kubernetes/pull/57543), [@feiskyer](https://github.com/feiskyer)) - -* Support LoadBalancer for Azure Virtual Machine Scale Sets ([#57131](https://github.com/kubernetes/kubernetes/pull/57131), [@feiskyer](https://github.com/feiskyer)) - -* Fixed incorrect error info when creating an azure file PVC failed. ([#56550](https://github.com/kubernetes/kubernetes/pull/56550), [@andyzhangx](https://github.com/andyzhangx)) - -* Added mount options support for azure disk. For example: - -``` -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: hdd -provisioner: kubernetes.io/azure-disk -mountOptions: - - barrier=1 - - acl -parameters: - skuname: Standard_LRS - kind: Managed - fstype: ext3 -``` - -([#56147](https://github.com/kubernetes/kubernetes/pull/56147), [@andyzhangx](https://github.com/andyzhangx)) - -### Scheduling - -* Fixed a bug the in scheduler cache by using Pod UID as the cache key instead of namespace/name ([#61069](https://github.com/kubernetes/kubernetes/pull/61069), [@anfernee](https://github.com/anfernee)) - -* When `TaintNodesByCondition` is enabled, added `node.kubernetes.io/unschedulable:NoSchedule` ([#61161](https://github.com/kubernetes/kubernetes/pull/61161), [@k82cn](https://github.com/k82cn)) - -* kube-scheduler: Support extender managed extended resources in kube-scheduler ([#60332](https://github.com/kubernetes/kubernetes/pull/60332), [@yguo0905](https://github.com/yguo0905)) - -* Updated priority of mirror pod according to PriorityClassName. ([#58485](https://github.com/kubernetes/kubernetes/pull/58485), [@k82cn](https://github.com/k82cn)) - -* kube-scheduler: restores default leader election behavior. Setting the `--leader-elect` command line parameter to `true` ([#60524](https://github.com/kubernetes/kubernetes/pull/60524), [@dims](https://github.com/dims)) - -* All pods with priorityClassName system-node-critical and system-cluster-critical will be critical pods while preserving backwards compatibility. ([#58835](https://github.com/kubernetes/kubernetes/pull/58835), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) -* Priority admission controller picks a global default with the lowest priority value if more than one such default PriorityClass exists. ([#59991](https://github.com/kubernetes/kubernetes/pull/59991), [@bsalamat](https://github.com/bsalamat)) -* Disallow PriorityClass names with 'system-' prefix for user defined priority classes. ([#59382](https://github.com/kubernetes/kubernetes/pull/59382), [@bsalamat](https://github.com/bsalamat)) -* kube-scheduler: Use default predicates/prioritizers if they are unspecified in the policy config. ([#59363](https://github.com/kubernetes/kubernetes/pull/59363), [@yguo0905](https://github.com/yguo0905)) - -* Scheduler should be able to read from config file if configmap is not present. ([#59386](https://github.com/kubernetes/kubernetes/pull/59386), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) -* Add apiserver metric for current inflight-request usage. ([#58342](https://github.com/kubernetes/kubernetes/pull/58342), [@gmarek](https://github.com/gmarek)) - -* Stability: Make Pod delete event handling of scheduler more robust. ([#58712](https://github.com/kubernetes/kubernetes/pull/58712), [@bsalamat](https://github.com/bsalamat))* Allow scheduler set AlwaysCheckAllPredicates, short circuit all predicates if one predicate fails can greatly improve the scheduling performance. ([#56926](https://github.com/kubernetes/kubernetes/pull/56926), [@wgliang](https://github.com/wgliang)) - -* GCE: support passing kube-scheduler policy config via SCHEDULER_POLICY_CONFIG. This allows us to specify a customized scheduler policy configuration. ([#57425](https://github.com/kubernetes/kubernetes/pull/57425), [@yguo0905](https://github.com/yguo0905)) - -* Returns an error for non overcommitable resources if they don't have limit field set in container spec to prevent users from creating invalid configurations. ([#57170](https://github.com/kubernetes/kubernetes/pull/57170), [@jiayingz](https://github.com/jiayingz)) - -* GCE: Fixed ILB creation on automatic networks with manually created subnetworks. ([#57351](https://github.com/kubernetes/kubernetes/pull/57351), [@nicksardo](https://github.com/nicksardo)) - -* Multiple Performance Improvements to the MatchInterPodAffinity predicate ([#57476](https://github.com/kubernetes/kubernetes/pull/57476), [@misterikkit](https://github.com/misterikkit))([#57477](https://github.com/kubernetes/kubernetes/pull/57477), [@misterikkit](https://github.com/misterikkit)) - -* The calico-node addon tolerates all NoExecute and NoSchedule taints by default. So Calico components can even be scheduled on tainted nodes. ([#57122](https://github.com/kubernetes/kubernetes/pull/57122), [@caseydavenport](https://github.com/caseydavenport)) -* The scheduler skips pods that use a PVC that either does not exist or is being deleted. ([#55957](https://github.com/kubernetes/kubernetes/pull/55957), [@jsafrane](https://github.com/jsafrane)) - -### Other changes - -* Updated dashboard version to v1.8.3, which keeps auto-generated certs in memory. ([#57326](https://github.com/kubernetes/kubernetes/pull/57326), [@floreks](https://github.com/floreks)) - -* fluentd-gcp addon: Fixed bug with reporting metrics in event-exporter. ([#60126](https://github.com/kubernetes/kubernetes/pull/60126), [@serathius](https://github.com/serathius)) - -* Avoid hook errors when effecting label changes on kubernetes-worker charm. ([#59803](https://github.com/kubernetes/kubernetes/pull/59803), [@wwwtyro](https://github.com/wwwtyro)) - -* Fixed charm issue where docker login would run prior to daemon options being set. ([#59396](https://github.com/kubernetes/kubernetes/pull/59396), [@kwmonroe](https://github.com/kwmonroe)) - -* Implementers of the cloud provider interface will note the addition of a context to this interface. Trivial code modification will be necessary for a cloud provider to continue to compile. ([#59287](https://github.com/kubernetes/kubernetes/pull/59287), [@cheftako](https://github.com/cheftako)) - -* Added configurable etcd quota backend bytes in GCE. ([#59259](https://github.com/kubernetes/kubernetes/pull/59259), [@wojtek-t](https://github.com/wojtek-t)) - -* GCP: allow a master to not include a metadata concealment firewall rule (if it's not running the metadata proxy). ([#58104](https://github.com/kubernetes/kubernetes/pull/58104), [@ihmccreery](https://github.com/ihmccreery)) - -* Fixed issue with kubernetes-worker option allow-privileged not properly handling the value True with a capital T. ([#59116](https://github.com/kubernetes/kubernetes/pull/59116), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* Controller-manager --service-sync-period flag has been removed. (It was never used in the code and should have no user impact.) ([#59359](https://github.com/kubernetes/kubernetes/pull/59359), [@khenidak](https://github.com/khenidak)) - -* [fluentd-gcp addon] Switch to the image provided by Stackdriver. The Stackdriver Logging Agent container image uses fluentd v0.14.25. ([#59128](https://github.com/kubernetes/kubernetes/pull/59128), [@bmoyles0117](https://github.com/bmoyles0117)) - -## Non-user-facing Changes - -* CRI now uses moutpoint as image filesystem identifier instead of UUID. ([#59475](https://github.com/kubernetes/kubernetes/pull/59475), [@Random-Liu](https://github.com/Random-Liu)) - -* GCE: support Cloud TPU API in cloud provider ([#58029](https://github.com/kubernetes/kubernetes/pull/58029), [@yguo0905](https://github.com/yguo0905)) - -* kubelet now notifies systemd that it has finished starting, if systemd is available and running. ([#60654](https://github.com/kubernetes/kubernetes/pull/60654), [@dcbw](https://github.com/dcbw)) - -* Do not count failed pods as unready in HPA controller ([#60648](https://github.com/kubernetes/kubernetes/pull/60648), [@bskiba](https://github.com/bskiba)) - -* fixed foreground deletion of podtemplates ([#60683](https://github.com/kubernetes/kubernetes/pull/60683), [@nilebox](https://github.com/nilebox)) - -* Conformance tests are added for the DaemonSet kinds in the apps/v1 group version. Deprecated versions of DaemonSet will not be tested for conformance, and conformance is only applicable to release 1.10 and later. ([#60456](https://github.com/kubernetes/kubernetes/pull/60456), [@kow3ns](https://github.com/kow3ns)) - -* Log audit backend can now be configured to perform batching before writing events to disk. ([#60237](https://github.com/kubernetes/kubernetes/pull/60237), [@crassirostris](https://github.com/crassirostris)) - -* New conformance tests added for the Garbage Collector ([#60116](https://github.com/kubernetes/kubernetes/pull/60116), [@jennybuckley](https://github.com/jennybuckley)) - -* Fixes a bug where character devices are not recongized by the kubelet ([#60440](https://github.com/kubernetes/kubernetes/pull/60440), [@andrewsykim](https://github.com/andrewsykim)) - -* StatefulSet in apps/v1 is now included in Conformance Tests. ([#60336](https://github.com/kubernetes/kubernetes/pull/60336), [@enisoc](https://github.com/enisoc)) - -* dockertools: disable memory swap on Linux. ([#59404](https://github.com/kubernetes/kubernetes/pull/59404), [@ohmystack](https://github.com/ohmystack)) - -* Increase timeout of integration tests ([#60458](https://github.com/kubernetes/kubernetes/pull/60458), [@jennybuckley](https://github.com/jennybuckley)) - -* force node name lowercase on static pod name generating ([#59849](https://github.com/kubernetes/kubernetes/pull/59849), [@yue9944882]([https://github.com/yue9944882](https://github.com/yue9944882)) - -* fix device name change issue for azure disk ([#60346](https://github.com/kubernetes/kubernetes/pull/60346), [@andyzhangx](https://github.com/andyzhangx)) - -* Additional changes to iptables kube-proxy backend to improve performance on clusters with very large numbers of services. ([#60306](https://github.com/kubernetes/kubernetes/pull/60306), [@danwinship](https://github.com/danwinship)) - -* add spelling checking script ([#59463](https://github.com/kubernetes/kubernetes/pull/59463), [@dixudx](https://github.com/dixudx)) - -* Use consts as predicate name in handlers ([#59952](https://github.com/kubernetes/kubernetes/pull/59952), [@resouer](https://github.com/resouer)) - -* Fix instanceID for vmss nodes. ([#59857](https://github.com/kubernetes/kubernetes/pull/59857), [@feiskyer](https://github.com/feiskyer)) - -* Increase allowed lag for ssh key sync loop in tunneler to allow for one failure ([#60068](https://github.com/kubernetes/kubernetes/pull/60068), [@wojtek-t](https://github.com/wojtek-t)) - -* Set an upper bound (5 minutes) on how long the Kubelet will wait before exiting when the client cert from disk is missing or invalid. This prevents the Kubelet from waiting forever without attempting to bootstrap a new client credentials. ([#59316](https://github.com/kubernetes/kubernetes/pull/59316), [@smarterclayton](https://github.com/smarterclayton)) - -* Add ipset binary for IPVS to hyperkube docker image ([#57648](https://github.com/kubernetes/kubernetes/pull/57648), [@Fsero](https://github.com/Fsero)) - -* Making sure CSI E2E test runs on a local cluster ([#60017](https://github.com/kubernetes/kubernetes/pull/60017), [@sbezverk](https://github.com/sbezverk)) - -* Fix kubelet PVC stale metrics ([#59170](https://github.com/kubernetes/kubernetes/pull/59170), [@cofyc](https://github.com/cofyc)) - -* Separate current ARM rate limiter into read/write ([#59830](https://github.com/kubernetes/kubernetes/pull/59830), [@khenidak](https://github.com/khenidak)) - -* Improve control over how ARM rate limiter is used within Azure cloud provider, add generic cache for Azure VM/LB/NSG/RouteTable ([#59520](https://github.com/kubernetes/kubernetes/pull/59520), [@feiskyer](https://github.com/feiskyer)) - -* fix typo ([#59619](https://github.com/kubernetes/kubernetes/pull/59619), [@jianliao82](https://github.com/jianliao82)) - -* DaemonSet, Deployment, ReplicaSet, and StatefulSet objects are now persisted in etcd in apps/v1 format ([#58854](https://github.com/kubernetes/kubernetes/pull/58854), [@liggitt](https://github.com/liggitt)) - -* YAMLDecoder Read now tracks rest of buffer on io.ErrShortBuffer ([#58817](https://github.com/kubernetes/kubernetes/pull/58817), [@karlhungus](https://github.com/karlhungus)) - -* Prevent kubelet from getting wedged if initialization of modules returns an error. ([#59020](https://github.com/kubernetes/kubernetes/pull/59020), [@brendandburns](https://github.com/brendandburns)) - -* Fixed a race condition inside kubernetes-worker that would result in a temporary error situation. ([#59005](https://github.com/kubernetes/kubernetes/pull/59005), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* Fix regression in the CRI: do not add a default hostname on short image names ([#58955](https://github.com/kubernetes/kubernetes/pull/58955), [@runcom](https://github.com/runcom)) - -* use containing API group when resolving shortname from discovery ([#58741](https://github.com/kubernetes/kubernetes/pull/58741), [@dixudx](https://github.com/dixudx)) - -* remove spaces from kubectl describe hpa ([#56331](https://github.com/kubernetes/kubernetes/pull/56331), [@shiywang](https://github.com/shiywang)) - -* fluentd-es addon: multiline stacktraces are now grouped into one entry automatically ([#58063](https://github.com/kubernetes/kubernetes/pull/58063), [@monotek](https://github.com/monotek)) - -* Default scheduler code is moved out of the plugin directory. ([#57852](https://github.com/kubernetes/kubernetes/pull/57852), [@misterikkit](https://github.com/misterikkit)) - -* CDK nginx ingress is now handled via a daemon set. ([#57530](https://github.com/kubernetes/kubernetes/pull/57530), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* Move local PV negative scheduling tests to integration ([#57570](https://github.com/kubernetes/kubernetes/pull/57570), [@sbezverk](https://github.com/sbezverk)) - -* Only create Privileged PSP binding during e2e tests if RBAC is enabled. ([#56382](https://github.com/kubernetes/kubernetes/pull/56382), [@mikkeloscar](https://github.com/mikkeloscar)) - -* ignore nonexistent ns net file error when deleting container network in case a retry ([#57697](https://github.com/kubernetes/kubernetes/pull/57697), [@dixudx](https://github.com/dixudx)) - -* Use old dns-ip mechanism with older cdk-addons. ([#57403](https://github.com/kubernetes/kubernetes/pull/57403), [@wwwtyro](https://github.com/wwwtyro)) - -* Retry 'connection refused' errors when setting up clusters on GCE. ([#57394](https://github.com/kubernetes/kubernetes/pull/57394), [@mborsz](https://github.com/mborsz)) - -* YAMLDecoder Read now returns the number of bytes read ([#57000](https://github.com/kubernetes/kubernetes/pull/57000), [@sel](https://github.com/sel)) - -* Drop hacks used for Mesos integration that was already removed from main kubernetes repository ([#56754](https://github.com/kubernetes/kubernetes/pull/56754), [@dims](https://github.com/dims)) - -* Compare correct file names for volume detach operation ([#57053](https://github.com/kubernetes/kubernetes/pull/57053), [@prashima](https://github.com/prashima)) - -* Fixed documentation typo in IPVS README. ([#56578](https://github.com/kubernetes/kubernetes/pull/56578), [@shift](https://github.com/shift)) - -* The ConfigOK node condition has been renamed to KubeletConfigOk. ([#59905](https://github.com/kubernetes/kubernetes/pull/59905), [@mtaufen](https://github.com/mtaufen)) - -* Adding pkg/kubelet/apis/deviceplugin/v1beta1 API. ([#59588](https://github.com/kubernetes/kubernetes/pull/59588), [@jiayingz](https://github.com/jiayingz)) - -* Fixes volume predicate handler for equiv class ([#59335](https://github.com/kubernetes/kubernetes/pull/59335), [@resouer](https://github.com/resouer)) - -* Bugfix: vSphere Cloud Provider (VCP) does not need any special service account anymore. ([#59440](https://github.com/kubernetes/kubernetes/pull/59440), [@rohitjogvmw](https://github.com/rohitjogvmw)) - -* fix the error prone account creation method of blob disk ([#59739](https://github.com/kubernetes/kubernetes/pull/59739), [@andyzhangx](https://github.com/andyzhangx)) - -* Updated kubernetes-worker to request new security tokens when the aws cloud provider changes the registered node name. ([#59730](https://github.com/kubernetes/kubernetes/pull/59730), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* Pod priority can be specified ins PodSpec even when the feature is disabled, but it will be effective only when the feature is enabled. ([#59291](https://github.com/kubernetes/kubernetes/pull/59291), [@bsalamat](https://github.com/bsalamat))* Add generic cache for Azure VMSS ([#59652](https://github.com/kubernetes/kubernetes/pull/59652), [@feiskyer](https://github.com/feiskyer)) - -* fix the create azure file pvc failure if there is no storage account in current resource group ([#56557](https://github.com/kubernetes/kubernetes/pull/56557), [@andyzhangx](https://github.com/andyzhangx)) - -* Implement envelope service with gRPC, so that KMS providers can be pulled out from API server. ([#55684](https://github.com/kubernetes/kubernetes/pull/55684), [@wu-qiang](https://github.com/wu-qiang)) - -* Enable golint for `pkg/scheduler` and fix the golint errors in it. ([#58437](https://github.com/kubernetes/kubernetes/pull/58437), [@tossmilestone](https://github.com/tossmilestone)) - -* Ensure euqiv hash calculation is per schedule ([#59245](https://github.com/kubernetes/kubernetes/pull/59245), [@resouer](https://github.com/resouer)) - -* Upped the timeout for apiserver communication in the juju kubernetes-worker charm. ([#59219](https://github.com/kubernetes/kubernetes/pull/59219), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* kubeadm init: skip checking cri socket in preflight checks ([#58802](https://github.com/kubernetes/kubernetes/pull/58802), [@dixudx](https://github.com/dixudx)) - -* Configurable etcd compaction frequency in GCE ([#59106](https://github.com/kubernetes/kubernetes/pull/59106), [@wojtek-t](https://github.com/wojtek-t)) - -* Fixed a bug which caused the apiserver reboot failure in the presence of malfunctioning webhooks. ([#59073](https://github.com/kubernetes/kubernetes/pull/59073), [@caesarxuchao](https://github.com/caesarxuchao)) - -* GCE: Apiserver uses `InternalIP` as the most preferred kubelet address type by default. ([#59019](https://github.com/kubernetes/kubernetes/pull/59019), [@MrHohn](https://github.com/MrHohn)) - -* CRI: Add a call to reopen log file for a container. ([#58899](https://github.com/kubernetes/kubernetes/pull/58899), [@yujuhong](https://github.com/yujuhong)) - -* The alpha KubeletConfigFile feature gate has been removed, because it was redundant with the Kubelet's --config flag. It is no longer necessary to set this gate to use the flag. The --config flag is still considered alpha. ([#58978](https://github.com/kubernetes/kubernetes/pull/58978), [@mtaufen](https://github.com/mtaufen)) - -* Fixing extra_sans option on master and load balancer. ([#58843](https://github.com/kubernetes/kubernetes/pull/58843), [@hyperbolic2346](https://github.com/hyperbolic2346)) - -* Ensure config has been created before attempting to launch ingress. ([#58756](https://github.com/kubernetes/kubernetes/pull/58756), [@wwwtyro](https://github.com/wwwtyro)) - -* Support metrics API in `kubectl top` commands. ([#56206](https://github.com/kubernetes/kubernetes/pull/56206), [@brancz](https://github.com/brancz)) - -* Bump GCE metadata proxy to v0.1.9 to pick up security fixes. ([#58221](https://github.com/kubernetes/kubernetes/pull/58221), [@ihmccreery](https://github.com/ihmccreery)) - -* "ExternalTrafficLocalOnly" has been removed from feature gate. It has been a GA feature since v1.7. ([#56948](https://github.com/kubernetes/kubernetes/pull/56948), [@MrHohn](https://github.com/MrHohn)) -* feat(fakeclient): push event on watched channel on add/update/delete ([#57504](https://github.com/kubernetes/kubernetes/pull/57504), [@yue9944882](https://github.com/yue9944882)) - -* Fixes a possible deadlock preventing quota from being recalculated ([#58107](https://github.com/kubernetes/kubernetes/pull/58107), [@ironcladlou](https://github.com/ironcladlou)) - -* Bump metadata proxy version to v0.1.7 to pick up security fix. ([#57762](https://github.com/kubernetes/kubernetes/pull/57762), [@ihmccreery](https://github.com/ihmccreery)) - -* The kubelet uses a new release 3.1 of the pause container with the Docker runtime. This version will clean up orphaned zombie processes that it inherits. ([#57517](https://github.com/kubernetes/kubernetes/pull/57517), [@verb](https://github.com/verb)) - -* Add cache for VM get operation in azure cloud provider ([#57432](https://github.com/kubernetes/kubernetes/pull/57432), [@karataliu](https://github.com/karataliu)) - -* Configurable liveness probe initial delays for etcd and kube-apiserver in GCE ([#57749](https://github.com/kubernetes/kubernetes/pull/57749), [@wojtek-t](https://github.com/wojtek-t)) - -* Fixed garbage collection hang ([#57503](https://github.com/kubernetes/kubernetes/pull/57503), [@liggitt](https://github.com/liggitt) - -* Improve scheduler performance of MatchInterPodAffinity predicate. ([#57478](https://github.com/kubernetes/kubernetes/pull/57478), [@misterikkit](https://github.com/misterikkit)) - -* Add the path '/version/' to the `system:discovery` cluster role. ([#57368](https://github.com/kubernetes/kubernetes/pull/57368), [@brendandburns](https://github.com/brendandburns)) - -* adding predicates ordering for the kubernetes scheduler. ([#57168](https://github.com/kubernetes/kubernetes/pull/57168), [@yastij](https://github.com/yastij)) - -* Fix ipvs proxier nodeport ethassumption ([#56685](https://github.com/kubernetes/kubernetes/pull/56685), [@m1093782566](https://github.com/m1093782566)) - -* Fix Heapster configuration and Metrics Server configuration to enable overriding default resource requirements. ([#56965](https://github.com/kubernetes/kubernetes/pull/56965), [@kawych](https://github.com/kawych)) - -* Improved event generation in volume mount, attach, and extend operations ([#56872](https://github.com/kubernetes/kubernetes/pull/56872), [@davidz627](https://github.com/davidz627)) - -* Remove ScrubDNS interface from cloudprovider. ([#56955](https://github.com/kubernetes/kubernetes/pull/56955), [@feiskyer](https://github.com/feiskyer)) - -* Fixed a garbage collection race condition where objects with ownerRefs pointing to cluster-scoped objects could be deleted incorrectly. ([#57211](https://github.com/kubernetes/kubernetes/pull/57211), [@liggitt](https://github.com/liggitt)) - -* api-server provides specific events when unable to repair a service cluster ip or node port ([#54304](https://github.com/kubernetes/kubernetes/pull/54304), [@frodenas](https://github.com/frodenas)) - -* delete useless params containerized ([#56146](https://github.com/kubernetes/kubernetes/pull/56146), [@jiulongzaitian](https://github.com/jiulongzaitian)) - -* dockershim now makes an Image's Labels available in the Info field of ImageStatusResponse ([#58036](https://github.com/kubernetes/kubernetes/pull/58036), [@shlevy](https://github.com/shlevy)) - -* Support GetLabelsForVolume in OpenStack Provider ([#58871](https://github.com/kubernetes/kubernetes/pull/58871), [@edisonxiang](https://github.com/edisonxiang)) - -* Add "nominatedNodeName" field to PodStatus. This field is set when a pod preempts other pods on the node. ([#58990](https://github.com/kubernetes/kubernetes/pull/58990), [@bsalamat](https://github.com/bsalamat))* Fix the PersistentVolumeLabel controller from initializing the PV labels when it's not the next pending initializer. ([#56831](https://github.com/kubernetes/kubernetes/pull/56831), [@jhorwit2](https://github.com/jhorwit2)) - -* Rename StorageProtection to StorageObjectInUseProtection ([#59901](https://github.com/kubernetes/kubernetes/pull/59901), [@NickrenREN](https://github.com/NickrenREN)) - -* Add support for cloud-controller-manager in local-up-cluster.sh ([#57757](https://github.com/kubernetes/kubernetes/pull/57757), [@dims](https://github.com/dims)) - -* GCE: A role and clusterrole will now be provided with GCE/GKE for allowing the cloud-provider to post warning events on all services and watching configmaps in the kube-system namespace. No user action is required. ([#59686](https://github.com/kubernetes/kubernetes/pull/59686), [@nicksardo](https://github.com/nicksardo)) - -* Wait for kubedns to be ready when collecting the cluster IP. ([#57337](https://github.com/kubernetes/kubernetes/pull/57337), [@wwwtyro](https://github.com/wwwtyro)) - -## External Dependencies -* The supported etcd server version is 3.1.12, as compared to 3.1.10 in v1.9 ([#60998](https://github.com/kubernetes/kubernetes/pull/60998)) -* The validated docker versions are the same as for v1.9: 1.11.2 to 1.13.1 and 17.03.x ([ref](https://github.com/kubernetes/kubernetes/blob/master/test/e2e_node/system/docker_validator_test.go)) -* The Go version is go1.9.3, as compared to go1.9.2 in v1.9. ([#59012](https://github.com/kubernetes/kubernetes/pull/59012)) -* The minimum supported go is the same as for v1.9: go1.9.1. ([#55301](https://github.com/kubernetes/kubernetes/pull/55301)) -* CNI is the same as v1.9: v0.6.0 ([#51250](https://github.com/kubernetes/kubernetes/pull/51250)) -* CSI is updated to 0.2.0 as compared to 0.1.0 in v1.9. ([#60736](https://github.com/kubernetes/kubernetes/pull/60736)) -* The dashboard add-on has been updated to v1.8.3, as compared to 1.8.0 in v1.9. ([#57326](https://github.com/kubernetes/kubernetes/pull/57326)) -* Heapster has is the same as v1.9: v1.5.0. It will be upgraded in v1.11. ([ref](https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/cluster-monitoring/google/heapster-controller.yaml)) -* Cluster Autoscaler has been updated to v1.2.0. ([#60842](https://github.com/kubernetes/kubernetes/pull/60842), [@mwielgus](https://github.com/mwielgus)) -* Updates kube-dns to v1.14.8 ([#57918](https://github.com/kubernetes/kubernetes/pull/57918), [@rramkumar1](https://github.com/rramkumar1)) -* Influxdb is unchanged from v1.9: v1.3.3 ([#53319](https://github.com/kubernetes/kubernetes/pull/53319)) -* Grafana is unchanged from v1.9: v4.4.3 ([#53319](https://github.com/kubernetes/kubernetes/pull/53319)) -* CAdvisor is v0.29.1 ([#60867](https://github.com/kubernetes/kubernetes/pull/60867)) -* fluentd-gcp-scaler is v0.3.0 ([#61269](https://github.com/kubernetes/kubernetes/pull/61269)) -* Updated fluentd in fluentd-es-image to fluentd v1.1.0 ([#58525](https://github.com/kubernetes/kubernetes/pull/58525), [@monotek](https://github.com/monotek)) -* fluentd-elasticsearch is v2.0.4 ([#58525](https://github.com/kubernetes/kubernetes/pull/58525)) -* Updated fluentd-gcp to v3.0.0. ([#60722](https://github.com/kubernetes/kubernetes/pull/60722)) -* Ingress glbc is v1.0.0 ([#61302](https://github.com/kubernetes/kubernetes/pull/61302)) -* OIDC authentication is coreos/go-oidc v2 ([#58544](https://github.com/kubernetes/kubernetes/pull/58544)) -* Updated fluentd-gcp updated to v2.0.11. ([#56927](https://github.com/kubernetes/kubernetes/pull/56927), [@x13n](https://github.com/x13n)) -* Calico has been updated to v2.6.7 ([#59130](https://github.com/kubernetes/kubernetes/pull/59130), [@caseydavenport](https://github.com/caseydavenport)) - -# v1.10.0-rc.1 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) - -## Downloads for v1.10.0-rc.1 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes.tar.gz) | `d7409a0bf36558b8328eefc01959920641f1fb2630fe3ac19b266fcea05a1646` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-src.tar.gz) | `4384bfe4151850e5d169b125c0cba51b7c2f00aa9972a6b4c22c44af74e8e3f8` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-darwin-386.tar.gz) | `1eb98b5d527ee9ed375f06df96c1158b9879880eb12d68a81e823d7a92e3866d` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-darwin-amd64.tar.gz) | `be7e35e9698b84ace37e0ed54640c3958c0d9eea8bd413eb8b604ec02922321a` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-linux-386.tar.gz) | `825a80abdb1171e72c1660fb7854ed6e8290cb7cb54ebb88c3570b3f95e77a02` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-linux-amd64.tar.gz) | `97e22907c3f0780818b7124c50451ae78e930cd99ec8f96f188cdd080547e21b` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-linux-arm64.tar.gz) | `d27674c7daec425f0fa72ca14695e7f13c81cfd08517ceb1f5ce1bb052b5b9b2` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-linux-arm.tar.gz) | `e54f1fc7cf95981f54d68108ad0113396357ff0c7baaf6a76a635f0de21fb944` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-linux-ppc64le.tar.gz) | `7535a6668e6ca6888b22615439fae8c68d37d62f572b284755db87600050a6c6` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-linux-s390x.tar.gz) | `6a9f90e2ea5cb50b2691c45d327cca444ae9bfc41cba43ca22016679da940a71` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-windows-386.tar.gz) | `cc5fef5e054588ad41870a379662d8429bd0f09500bcf4a67648bf6593d18aaf` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-client-windows-amd64.tar.gz) | `a06033004c5cecc43494d95dd5d5e75f698cf8e4d358c229c5fef222c131b077` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-server-linux-amd64.tar.gz) | `e844897e9a39ca14a449e077cb4e4f2dc6c7d5326b95a1e47bef3b6f9c6057f7` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-server-linux-arm64.tar.gz) | `c15476626cd750a8f59c30c3389ada482995aea66b510c43732035d33e87e774` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-server-linux-arm.tar.gz) | `74a1ff7478d7ca5c4ccb2fb772ef13745a20cfb512e3e66f238abb98122cc4eb` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-server-linux-ppc64le.tar.gz) | `3b004717fe811352c15fe71f3122d2eaac7e0d1c4ff07d8810894c877b409c0f` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-server-linux-s390x.tar.gz) | `b6ff40f13355b47e2c02c6c016ac334a3f5008769ed7b4377c617c2fc9e30b7a` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-node-linux-amd64.tar.gz) | `a3a3e27c2b77fa46b7c9ff3b8bfdc672c2657e47fc4b1ca3d76cdc102ca27630` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-node-linux-arm64.tar.gz) | `af172c9d71ba2d15e14354159ac34ca7fe112b7d2d2ba38325c467950aa04755` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-node-linux-arm.tar.gz) | `fb904aa009c3309e92505ceff15863f83d9317af15cbf729bcbd198f5be3379f` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-node-linux-ppc64le.tar.gz) | `659f0091578e42b111417d45f708be2ac60447512e485dab7d2f4abaeee36f49` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-node-linux-s390x.tar.gz) | `ce40dcc55ca299401ddf146b2622dd7f19532e95620bae63aea58a45a8020875` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-rc.1/kubernetes-node-windows-amd64.tar.gz) | `0f8b5c551f58cdf298d41258483311cef66fe1b41093152a43120514a493b23d` - -## Changelog since v1.10.0-beta.4 - -### Other notable changes - -* Updates kubeadm default to use 1.10 ([#61127](https://github.com/kubernetes/kubernetes/pull/61127), [@timothysc](https://github.com/timothysc)) -* Bump ingress-gce image in glbc.manifest to 1.0.0 ([#61302](https://github.com/kubernetes/kubernetes/pull/61302), [@rramkumar1](https://github.com/rramkumar1)) -* Fix regression where kubelet --cpu-cfs-quota flag did not work when --cgroups-per-qos was enabled ([#61294](https://github.com/kubernetes/kubernetes/pull/61294), [@derekwaynecarr](https://github.com/derekwaynecarr)) -* Fix bug allowing garbage collector to enter a broken state that could only be fixed by restarting the controller-manager. ([#61201](https://github.com/kubernetes/kubernetes/pull/61201), [@jennybuckley](https://github.com/jennybuckley)) -* When `TaintNodesByCondition` enabled, added `node.kubernetes.io/unschedulable:NoSchedule` ([#61161](https://github.com/kubernetes/kubernetes/pull/61161), [@k82cn](https://github.com/k82cn)) - * taint to the node if `spec.Unschedulable` is true. - * When `ScheduleDaemonSetPods` enabled, `node.kubernetes.io/unschedulable:NoSchedule` - * toleration is added automatically to DaemonSet Pods; so the `unschedulable` field of - * a node is not respected by the DaemonSet controller. -* Fixed kube-proxy to work correctly with iptables 1.6.2 and later. ([#60978](https://github.com/kubernetes/kubernetes/pull/60978), [@danwinship](https://github.com/danwinship)) -* Audit logging with buffering enabled can increase apiserver memory usage (e.g. up to 200MB in 100-node cluster). The increase is bounded by the buffer size (configurable). Ref: issue [#60500](https://github.com/kubernetes/kubernetes/pull/60500) ([#61118](https://github.com/kubernetes/kubernetes/pull/61118), [@shyamjvs](https://github.com/shyamjvs)) -* Fix a bug in scheduler cache by using Pod UID as the cache key instead of namespace/name ([#61069](https://github.com/kubernetes/kubernetes/pull/61069), [@anfernee](https://github.com/anfernee)) - - - -# v1.10.0-beta.4 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) - -## Downloads for v1.10.0-beta.4 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes.tar.gz) | `69132f3edcf549c686055903e8ef007f0c92ec05a8ec1e3fea4d5b4dc4685580` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-src.tar.gz) | `60ba32e493c0a1449cdbd615d709e9d46780c91c88255e8e9f468c5e4e124576` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-darwin-386.tar.gz) | `80ef567c51aa705511ca20fbfcad2e85f1dc4fb750c0f58e0d82f4166359273f` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-darwin-amd64.tar.gz) | `925830f3c6c135adec206012ae94807b58b9438008ae87881e7a9d648ab993ec` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-linux-386.tar.gz) | `9e4f40325a27b79f16eb3254c6283d67e2fecd313535b300f9931800e4c495a4` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-linux-amd64.tar.gz) | `85ee9bfa519e49283ab711c73f52809f8fc43616cc2076dc060987e6f262ff95` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-linux-arm.tar.gz) | `f0123581243a278052413e862208a797e78e7689c6dba0da08ab3200feedd66c` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-linux-arm64.tar.gz) | `dd19b034e1798f5bb0b1c6230ef294ca8f3ef7944837c5d49dce4659bb284b8e` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-linux-ppc64le.tar.gz) | `84a46003fe0140f8ecec03befceed7a4d955f9f88abdced99ecee24bc675b113` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-linux-s390x.tar.gz) | `c4ee2bf9f7ea66ab41b350220920644bee3eeceb13cfd19873843a9ab43b372d` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-windows-386.tar.gz) | `917e768179e82a33232281b9b6e555cee75cf6315bd3c60a1fce4717fbd0e538` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-client-windows-amd64.tar.gz) | `915f3cc888332b360701a4b20d1af384ec5388636f2c3e3868e36124ce8a96a8` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-server-linux-amd64.tar.gz) | `01b50da6bae8abe4e2c813381c3848ff615fc1d8164d11b163ac0819554ad7b4` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-server-linux-arm.tar.gz) | `0a1ebd399759a68972e6248b09ce46a76deef931e51c807e032fefc4210e3dde` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-server-linux-arm64.tar.gz) | `b8298a06aed6cd1c624855fb4e2d7258e8f9201fbc5bfebc8190c24273e95d9b` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-server-linux-ppc64le.tar.gz) | `b3b03dc71476f70c8a62cf5ac72fe0bfa433005778d39bfbc43fe225675f9986` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-server-linux-s390x.tar.gz) | `940bc9b4f73f32896f3c55d1b5824f931517689ec62b70600c8699e84bc725ee` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-node-linux-amd64.tar.gz) | `bcc29195864e4e486a7e8194be06f3cf575203e012790ea6d70003349b108701` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-node-linux-arm.tar.gz) | `35ab99a6cd30c2ea6a1f2347d244fb8583bfd7ef1d54f89fbf9a3a3be14fb9e7` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-node-linux-arm64.tar.gz) | `fcb611d964c7e1c546fbbb38c8b30b3e3bb54226540caa0b80930f53e321dd2e` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-node-linux-ppc64le.tar.gz) | `4de7b25cf712df27b6eec5232dc2891e07dbeb8c3699a145f777cc0629f1fe9c` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-node-linux-s390x.tar.gz) | `2f0b6a01c7c86209f031f47e1901bf3da82efef4db5b73b4e7d83be04b03c814` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.4/kubernetes-node-windows-amd64.tar.gz) | `619013157435d8da7f58bb339aa21d5a080c341aebe226934d1139d29cff72be` - -## Changelog since v1.10.0-beta.3 - -### Other notable changes - -* Fix a regression that prevented using `subPath` volume mounts with secret, configMap, projected, and downwardAPI volumes ([#61080](https://github.com/kubernetes/kubernetes/pull/61080), [@liggitt](https://github.com/liggitt)) -* Upgrade the default etcd server version to 3.1.12 to pick up critical etcd "mvcc "unsynced" watcher restore operation" fix. ([#60998](https://github.com/kubernetes/kubernetes/pull/60998), [@jpbetz](https://github.com/jpbetz)) -* Fixed missing error checking that could cause kubelet to crash in a race condition. ([#60962](https://github.com/kubernetes/kubernetes/pull/60962), [@technicianted](https://github.com/technicianted)) - - - -# v1.10.0-beta.3 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) - -## Downloads for v1.10.0-beta.3 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes.tar.gz) | `65880d0bb77eeb83554bb0a6c78b6d3a25cd38ef7d714bbe2c73b203386618d6` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-src.tar.gz) | `e9fbf8198fd80c92dd7e2ecf0cf6cefda06f9b89e7986ae141412f8732dae47c` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-darwin-386.tar.gz) | `50b1a41e70804f74b3e76d7603752d45dfd47011fd986d055462e1330330aa45` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-darwin-amd64.tar.gz) | `3658e70ae9761464df50c6cae8d57349648c80d16658892e42ea898ddab362bc` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-linux-386.tar.gz) | `00b8c048b201931ab1fb059df030e0bfc866f3c3ff464213aa6071ff261a3d33` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-linux-amd64.tar.gz) | `364d6439185399e72f96bea1bf2863deb2080f4bf6df721932ef14ec45b2d5fc` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-linux-arm.tar.gz) | `98670b2e965e118fb02901aa949cd1eb12d34ffd0bba7ff22014e9ad587556bc` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-linux-arm64.tar.gz) | `5f4febc543aa2f10c0c8aee9c9a8cb169b19b04486bda4cf1f72c80fa7a3a483` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-linux-ppc64le.tar.gz) | `ff3d020e97e2ff4c1824db910f13945d70320fc3988cc24385708cab58d4065f` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-linux-s390x.tar.gz) | `508695afe6d3466488bc20cad31c184723cb238d1c311d2d1c4f9f1c9e981bd6` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-windows-386.tar.gz) | `9f6372cfb973d04a150e1388d96cb60e7fe6ccb9ba63a146ff2dee491c2e3f4e` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-client-windows-amd64.tar.gz) | `2c85f2f13dc535d3c777f186b7e6d9403d64ac18ae01d1e460a8979e62845e04` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-server-linux-amd64.tar.gz) | `4797ada6fd43e223d67840e815c1edb244a3b40a3a1b6ecfde7789119f2add3d` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-server-linux-arm.tar.gz) | `fb2fdb4b2feb41adbbd33fe4b7abbe9780d91a288a64ff7acf85d5ef942d3960` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-server-linux-arm64.tar.gz) | `bc1f35e1999beaac91b65050f70c8e539918b927937e88bfcfa34a0c26b96701` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-server-linux-ppc64le.tar.gz) | `cce312f5af7dd182c8cc4ef35a768fef788a849a93a6f2f36e9d2991e721b362` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-server-linux-s390x.tar.gz) | `42edec36fa34a4cc4959af20a587fb05924ccc87c94b0f845953ba1ceec56bb7` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-node-linux-amd64.tar.gz) | `e517986261e3789cada07d9063ae96ed9b17ffd80c1b220b6ae9c41238c07c08` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-node-linux-arm.tar.gz) | `9eb213248982816a855a7ff18c9421d5e987d5f1c472880a16bc6c477ce8da2a` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-node-linux-arm64.tar.gz) | `e938dce3ec05cedcd6ab8e2b63224170db00e2c47e67685eb3cb4bad247ac8c0` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-node-linux-ppc64le.tar.gz) | `bc9bf3d55f85d3b30f0a28fd79b7610ecdf019b8bc8d7f978da62ee0006c72eb` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-node-linux-s390x.tar.gz) | `c5a1b18b8030ec86748e23d45f1de63783c2e95d67b0d6c2fcbcd545d205db8d` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.3/kubernetes-node-windows-amd64.tar.gz) | `df4f4e8df8665ed08a9a3d9816e61c6c9f0ce50e4185b6c7a7f34135ad1f91d0` - -## Changelog since v1.10.0-beta.2 - -### Other notable changes - -* kubelet initial flag parse should normalize flags instead of exiting. ([#61053](https://github.com/kubernetes/kubernetes/pull/61053), [@andrewsykim](https://github.com/andrewsykim)) -* Fixes CVE-2017-1002101 - See https://issue.k8s.io/60813 for details ([#61044](https://github.com/kubernetes/kubernetes/pull/61044), [@liggitt](https://github.com/liggitt)) -* Fixes the races around devicemanager Allocate() and endpoint deletion. ([#60856](https://github.com/kubernetes/kubernetes/pull/60856), [@jiayingz](https://github.com/jiayingz)) -* When ScheduleDaemonSetPods is enabled, the DaemonSet controller will delegate Pods scheduling to default scheduler. ([#59862](https://github.com/kubernetes/kubernetes/pull/59862), [@k82cn](https://github.com/k82cn)) -* Set node external IP for azure node when disabling UseInstanceMetadata ([#60959](https://github.com/kubernetes/kubernetes/pull/60959), [@feiskyer](https://github.com/feiskyer)) -* Bug fix, allow webhooks to use the scheme provided in clientConfig, instead of defaulting to http. ([#60943](https://github.com/kubernetes/kubernetes/pull/60943), [@jennybuckley](https://github.com/jennybuckley)) -* Downgrade default etcd server version to 3.1.11 due to [#60589](https://github.com/kubernetes/kubernetes/pull/60589) ([#60891](https://github.com/kubernetes/kubernetes/pull/60891), [@shyamjvs](https://github.com/shyamjvs)) -* kubelet and kube-proxy can now be ran as Windows services ([#60144](https://github.com/kubernetes/kubernetes/pull/60144), [@alinbalutoiu](https://github.com/alinbalutoiu)) - - - -# v1.10.0-beta.2 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) - -## Downloads for v1.10.0-beta.2 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes.tar.gz) | `d07d77f16664cdb5ce86c87de36727577f48113efdb00f83283714ac1373d521` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-src.tar.gz) | `c27b06e748e4c10f42472f51ddfef7e9546e4ec9d2ce9f7a9a3c5768de8d97bf` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-darwin-386.tar.gz) | `d63168f9155f04e4b47fe96381f9aa06c3d498b6e6b71d1fb8c3ffeb0f3c6e4c` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-darwin-amd64.tar.gz) | `f473cbe830c1bfb738b0a66f07b3cd858ba185232eba26fe776f90d8a27bd7c1` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-linux-386.tar.gz) | `2a0f74d30cdaf19ed7c3fde3528e98a8cd98fdb9dc6e6a501525e69895674d56` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-linux-amd64.tar.gz) | `69c18569717a97cb5e6bc22bebcf2f64969ba68b11685faaf2949c4ffbcd0b73` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-linux-arm.tar.gz) | `10e1d76a1ee6c0df9f9cce40d18c350a1e3e3665e6fe64d22e4433b6283d3fe2` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-linux-arm64.tar.gz) | `12f081b99770548c8ddd688ae6b417c196f8308bd5901abbed6f203e133411ae` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-linux-ppc64le.tar.gz) | `6e1a035b4857539c90324e00b150ae65aaf4f4524250c9ca7d77ad5936f0628e` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-linux-s390x.tar.gz) | `5a8e2b0d14e18a39f821b09a7d73fa5c085cf6c197aeb540a3fe289e04fcc0d9` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-windows-386.tar.gz) | `03fac6befb94b85fb90e0bb47596868b4da507d803806fad2a5fb4b85c98d87d` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-client-windows-amd64.tar.gz) | `3bf8dd42eb70735ebdbda4ec4ec54e9507410e2f97ab2f364b88c2f24fdf471c` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-server-linux-amd64.tar.gz) | `1278703060865281aa48b1366e3c4b0720d4eca623ba08cf852a4719a6680ec3` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-server-linux-arm.tar.gz) | `b1e2b399bec8c25b7b6037203485d2d09b091afc51ffebf861d5bddb8bb076ac` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-server-linux-arm64.tar.gz) | `4c3d0ed44d6a19ae178034117891678ec373894b02f8d33627b37a36c2ea815b` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-server-linux-ppc64le.tar.gz) | `88a7b52030104a4c6fb1f8c5f79444ed853f381e1463fec7e4939a9998d92dff` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-server-linux-s390x.tar.gz) | `35981580c00bff0e3d92238f961e37dd505c08bcd4cafb11e274daa1eb8ced5f` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-node-linux-amd64.tar.gz) | `ceedb0a322167bae33042407da5369e0b7889fbaa3568281500c921afcdbe310` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-node-linux-arm.tar.gz) | `b84ab4c486bc8f00841fccce2aafe4dcef25606c8f3184bce2551ab6486c8f71` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-node-linux-arm64.tar.gz) | `b79a41145c28358a64d7a689cd282cf8361fe87c410fbae1cdc8db76cfcf6e5b` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-node-linux-ppc64le.tar.gz) | `afc00f67b9f6d4fc149d4426fc8bbf6083077e11a1d2330d70be7e765b6cb923` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-node-linux-s390x.tar.gz) | `f6128bbccddfe8ce39762bacb5c13c6c68d76a4bf8d35e773560332eb05a2c86` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.2/kubernetes-node-windows-amd64.tar.gz) | `b1dde1ed2582cd511236fec69ebd6ca30281b30cc37e0841c493f06924a466cf` - -## Changelog since v1.10.0-beta.1 - -### Action Required - -* ACTION REQUIRED: LocalStorageCapacityIsolation feature is beta and enabled by default. ([#60159](https://github.com/kubernetes/kubernetes/pull/60159), [@jingxu97](https://github.com/jingxu97)) - -### Other notable changes - -* Upgrade the default etcd server version to 3.2.16 ([#59836](https://github.com/kubernetes/kubernetes/pull/59836), [@jpbetz](https://github.com/jpbetz)) -* Cluster Autoscaler 1.1.2 ([#60842](https://github.com/kubernetes/kubernetes/pull/60842), [@mwielgus](https://github.com/mwielgus)) -* ValidatingWebhooks and MutatingWebhooks will not be called on admission requests for ValidatingWebhookConfiguration and MutatingWebhookConfiguration objects in the admissionregistration.k8s.io group ([#59840](https://github.com/kubernetes/kubernetes/pull/59840), [@jennybuckley](https://github.com/jennybuckley)) -* Kubeadm: CoreDNS supports migration of the kube-dns configuration to CoreDNS configuration when upgrading the service discovery from kube-dns to CoreDNS as part of Beta. ([#58828](https://github.com/kubernetes/kubernetes/pull/58828), [@rajansandeep](https://github.com/rajansandeep)) -* Fix broken useManagedIdentityExtension for azure cloud provider ([#60775](https://github.com/kubernetes/kubernetes/pull/60775), [@feiskyer](https://github.com/feiskyer)) -* kubelet now notifies systemd that it has finished starting, if systemd is available and running. ([#60654](https://github.com/kubernetes/kubernetes/pull/60654), [@dcbw](https://github.com/dcbw)) -* Do not count failed pods as unready in HPA controller ([#60648](https://github.com/kubernetes/kubernetes/pull/60648), [@bskiba](https://github.com/bskiba)) -* fixed foreground deletion of podtemplates ([#60683](https://github.com/kubernetes/kubernetes/pull/60683), [@nilebox](https://github.com/nilebox)) -* Conformance tests are added for the DaemonSet kinds in the apps/v1 group version. Deprecated versions of DaemonSet will not be tested for conformance, and conformance is only applicable to release 1.10 and later. ([#60456](https://github.com/kubernetes/kubernetes/pull/60456), [@kow3ns](https://github.com/kow3ns)) -* Log audit backend can now be configured to perform batching before writing events to disk. ([#60237](https://github.com/kubernetes/kubernetes/pull/60237), [@crassirostris](https://github.com/crassirostris)) -* Fixes potential deadlock when deleting CustomResourceDefinition for custom resources with finalizers ([#60542](https://github.com/kubernetes/kubernetes/pull/60542), [@liggitt](https://github.com/liggitt)) -* fix azure file plugin failure issue on Windows after node restart ([#60625](https://github.com/kubernetes/kubernetes/pull/60625), [@andyzhangx](https://github.com/andyzhangx)) -* Set Azure vmType to standard if it is not set in azure cloud config. ([#60623](https://github.com/kubernetes/kubernetes/pull/60623), [@feiskyer](https://github.com/feiskyer)) -* On cluster provision or upgrade, kubeadm generates an etcd specific CA for all etcd related certificates. ([#60385](https://github.com/kubernetes/kubernetes/pull/60385), [@stealthybox](https://github.com/stealthybox)) -* kube-scheduler: restores default leader election behavior. leader-elect command line parameter should "true" ([#60524](https://github.com/kubernetes/kubernetes/pull/60524), [@dims](https://github.com/dims)) -* client-go: alpha support for exec-based credential providers ([#59495](https://github.com/kubernetes/kubernetes/pull/59495), [@ericchiang](https://github.com/ericchiang)) - - - -# v1.10.0-beta.1 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.10/examples) - -## Downloads for v1.10.0-beta.1 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes.tar.gz) | `428139d9877f5f94acc806cc4053b0a5f8eac2acc219f06efd0817807473dbc5` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-src.tar.gz) | `5bfdecdbb43d946ea965f22ec6b8a0fc7195197a523aefebc2b7b926d4252edf` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-darwin-386.tar.gz) | `8cc086e901fe699df5e0711438195e675e099848a72ba272b290d22abc107a93` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-darwin-amd64.tar.gz) | `b2782b8f6dbfe3fa962b08606cbf3366b071b78c47794d2ef67f9d484b4af4e4` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-linux-386.tar.gz) | `a4001ad2387ccb4557b15c560b0ea8ea4d7c7ed494375346e3f83c10eb9426ac` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-linux-amd64.tar.gz) | `b95d354e80d9f00a883e5eeb8c2e0ceaacc0f3cc8c904cb2eca1e1b6d91462b2` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-linux-arm64.tar.gz) | `647d234c59bc1d6f8eea88624d85b09bbe1272d9e27e1f7963e03cc025530ed0` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-linux-arm.tar.gz) | `187da9ad060ac7d426811772f6c3d891a354945af6a7d8832ac7097e19d4b46d` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-linux-ppc64le.tar.gz) | `6112396b8f0e7b1401b374aa2ae6195849da7718572036b6f060a722a89dc319` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-linux-s390x.tar.gz) | `09789cf33d8eed610ad2eef7d3ae25a4b4a63ee5525e452f9094097a172a1ce9` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-windows-386.tar.gz) | `1e71bc9979c8915587cdea980dad36b0cafd502f972c051c2aa63c3bbfeceb14` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-client-windows-amd64.tar.gz) | `3c2978479c6f65f1cb5043ba182a0571480090298b7d62090d9bf11b043dd27d` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-server-linux-amd64.tar.gz) | `d887411450bbc06e2f4a24ce3c478fe6844856a8707b3236c045d44ab93b27d2` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-server-linux-arm64.tar.gz) | `907f037eea90bf893520d3adeccdf29eda69eea32c564b08cecbedfd06471acd` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-server-linux-arm.tar.gz) | `f2ac4ad4f831a970cb35c1d7194788850dff722e859a08a879c918db1233aaa7` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-server-linux-ppc64le.tar.gz) | `0bebb59217b491c5aa4b4b9dc740c0c8c5518872f6f86853cbe30493ea8539a5` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-server-linux-s390x.tar.gz) | `5f343764e04e3a8639dffe225cc6f8bc6f17e1584b2c68923708546f48d38f89` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-node-linux-amd64.tar.gz) | `c4475c315d4ae27c30f80bc01d6ea8b0b8549ec6a60a5dc745cf11a0c4398c23` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-node-linux-arm64.tar.gz) | `4512a4c3e62cd26fb0d3f78bfc8de9a860e7d88e7c913c5df4c239536f89da42` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-node-linux-arm.tar.gz) | `1da407ad152b185f520f04215775a8fe176550a31a2bb79e3e82968734bdfb5c` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-node-linux-ppc64le.tar.gz) | `f23f6f819e6d894f8ca7457f80ee4ede729fd35ac59e9c65ab031b56aa06d4a1` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-node-linux-s390x.tar.gz) | `205c789f52a4c666a63ac7944ffa8ee325cb97e788b748c262eae59b838a94ba` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-beta.1/kubernetes-node-windows-amd64.tar.gz) | `aa7675fd22d9ca671585f429f6981aa79798f1894025c3abe3a7154f3c94aae6` - -## Changelog since v1.10.0-alpha.3 - -### Action Required - -* [action required] Default Flexvolume plugin directory for COS images on GCE is changed to `/home/kubernetes/flexvolume`. ([#58171](https://github.com/kubernetes/kubernetes/pull/58171), [@verult](https://github.com/verult)) -* action required: [GCP kube-up.sh] Some variables that were part of kube-env are no longer being set (ones only used for kubelet flags) and are being replaced by a more portable mechanism (kubelet configuration file). The individual variables in the kube-env metadata entry were never meant to be a stable interface and this release note only applies if you are depending on them. ([#60020](https://github.com/kubernetes/kubernetes/pull/60020), [@roberthbailey](https://github.com/roberthbailey)) -* action required: Deprecate format-separated endpoints for OpenAPI spec. Please use single `/openapi/v2` endpoint instead. ([#59293](https://github.com/kubernetes/kubernetes/pull/59293), [@roycaihw](https://github.com/roycaihw)) -* action required: kube-proxy: feature gates are now specified as a map when provided via a JSON or YAML KubeProxyConfiguration, rather than as a string of key-value pairs. ([#57962](https://github.com/kubernetes/kubernetes/pull/57962), [@xiangpengzhao](https://github.com/xiangpengzhao)) -* Action Required: The boostrapped RBAC role and rolebinding for the `cloud-provider` service account is now deprecated. If you're currently using this service account, you must create and apply your own RBAC policy for new clusters. ([#59949](https://github.com/kubernetes/kubernetes/pull/59949), [@nicksardo](https://github.com/nicksardo)) -* ACTION REQUIRED: VolumeScheduling and LocalPersistentVolume features are beta and enabled by default. The PersistentVolume NodeAffinity alpha annotation is deprecated and will be removed in a future release. ([#59391](https://github.com/kubernetes/kubernetes/pull/59391), [@msau42](https://github.com/msau42)) -* action required: Deprecate the kubelet's cadvisor port. The default will change to 0 (disabled) in 1.12, and the cadvisor port will be removed entirely in 1.13. ([#59827](https://github.com/kubernetes/kubernetes/pull/59827), [@dashpole](https://github.com/dashpole)) -* action required: The `kubeletconfig` API group has graduated from alpha to beta, and the name has changed to `kubelet.config.k8s.io`. Please use `kubelet.config.k8s.io/v1beta1`, as `kubeletconfig/v1alpha1` is no longer available. ([#53833](https://github.com/kubernetes/kubernetes/pull/53833), [@mtaufen](https://github.com/mtaufen)) -* Action required: Default values differ between the Kubelet's componentconfig (config file) API and the Kubelet's command line. Be sure to review the default values when migrating to using a config file. ([#59666](https://github.com/kubernetes/kubernetes/pull/59666), [@mtaufen](https://github.com/mtaufen)) -* kube-apiserver: the experimental in-tree Keystone password authenticator has been removed in favor of extensions that enable use of Keystone tokens. ([#59492](https://github.com/kubernetes/kubernetes/pull/59492), [@dims](https://github.com/dims)) -* The udpTimeoutMilliseconds field in the kube-proxy configuration file has been renamed to udpIdleTimeout. Action required: administrators need to update their files accordingly. ([#57754](https://github.com/kubernetes/kubernetes/pull/57754), [@ncdc](https://github.com/ncdc)) - -### Other notable changes - -* Enable IPVS feature gateway by default ([#60540](https://github.com/kubernetes/kubernetes/pull/60540), [@m1093782566](https://github.com/m1093782566)) -* dockershim now makes an Image's Labels available in the Info field of ImageStatusResponse ([#58036](https://github.com/kubernetes/kubernetes/pull/58036), [@shlevy](https://github.com/shlevy)) -* kube-scheduler: Support extender managed extended resources in kube-scheduler ([#60332](https://github.com/kubernetes/kubernetes/pull/60332), [@yguo0905](https://github.com/yguo0905)) -* Fix the issue in kube-proxy iptables/ipvs mode to properly handle incorrect IP version. ([#56880](https://github.com/kubernetes/kubernetes/pull/56880), [@MrHohn](https://github.com/MrHohn)) -* WindowsContainerResources is set now for windows containers ([#59333](https://github.com/kubernetes/kubernetes/pull/59333), [@feiskyer](https://github.com/feiskyer)) -* GCE: support Cloud TPU API in cloud provider ([#58029](https://github.com/kubernetes/kubernetes/pull/58029), [@yguo0905](https://github.com/yguo0905)) -* The node authorizer now allows nodes to request service account tokens for the service accounts of pods running on them. ([#55019](https://github.com/kubernetes/kubernetes/pull/55019), [@mikedanese](https://github.com/mikedanese)) -* Fix StatefulSet to work with set-based selectors. ([#59365](https://github.com/kubernetes/kubernetes/pull/59365), [@ayushpateria](https://github.com/ayushpateria)) -* New conformance tests added for the Garbage Collector ([#60116](https://github.com/kubernetes/kubernetes/pull/60116), [@jennybuckley](https://github.com/jennybuckley)) -* Make NodePort IP addresses configurable ([#58052](https://github.com/kubernetes/kubernetes/pull/58052), [@m1093782566](https://github.com/m1093782566)) -* Implements MountDevice and UnmountDevice for the CSI Plugin, the functions will call through to NodeStageVolume/NodeUnstageVolume for CSI plugins. ([#60115](https://github.com/kubernetes/kubernetes/pull/60115), [@davidz627](https://github.com/davidz627)) -* Fixes a bug where character devices are not recongized by the kubelet ([#60440](https://github.com/kubernetes/kubernetes/pull/60440), [@andrewsykim](https://github.com/andrewsykim)) -* [fluentd-gcp addon] Switch to the image, provided by Stackdriver. ([#59128](https://github.com/kubernetes/kubernetes/pull/59128), [@bmoyles0117](https://github.com/bmoyles0117)) -* StatefulSet in apps/v1 is now included in Conformance Tests. ([#60336](https://github.com/kubernetes/kubernetes/pull/60336), [@enisoc](https://github.com/enisoc)) -* K8s supports rbd-nbd for Ceph rbd volume mounts. ([#58916](https://github.com/kubernetes/kubernetes/pull/58916), [@ianchakeres](https://github.com/ianchakeres)) -* AWS EBS volume plugin got block volume support ([#58625](https://github.com/kubernetes/kubernetes/pull/58625), [@screeley44](https://github.com/screeley44)) -* Summary API will include pod CPU and Memory stats for CRI container runtime. ([#60328](https://github.com/kubernetes/kubernetes/pull/60328), [@Random-Liu](https://github.com/Random-Liu)) -* dockertools: disable memory swap on Linux. ([#59404](https://github.com/kubernetes/kubernetes/pull/59404), [@ohmystack](https://github.com/ohmystack)) -* On AWS kubelet returns an error when started under conditions that do not allow it to work (AWS has not yet tagged the instance). ([#60125](https://github.com/kubernetes/kubernetes/pull/60125), [@vainu-arto](https://github.com/vainu-arto)) -* Increase timeout of integration tests ([#60458](https://github.com/kubernetes/kubernetes/pull/60458), [@jennybuckley](https://github.com/jennybuckley)) -* Fixes a case when Deployment with recreate strategy could get stuck on old failed Pod. ([#60301](https://github.com/kubernetes/kubernetes/pull/60301), [@tnozicka](https://github.com/tnozicka)) -* Buffered audit backend is introduced, to be used with other audit backends. ([#60076](https://github.com/kubernetes/kubernetes/pull/60076), [@crassirostris](https://github.com/crassirostris)) -* Update dashboard version to v1.8.3 ([#57326](https://github.com/kubernetes/kubernetes/pull/57326), [@floreks](https://github.com/floreks)) -* GCE PD volume plugin got block volume support ([#58710](https://github.com/kubernetes/kubernetes/pull/58710), [@screeley44](https://github.com/screeley44)) -* force node name lowercase on static pod name generating ([#59849](https://github.com/kubernetes/kubernetes/pull/59849), [@yue9944882](https://github.com/yue9944882)) -* AWS Security Groups created for ELBs will now be tagged with the same additional tags as the ELB (i.e. the tags specified by the "service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags" annotation.) ([#58767](https://github.com/kubernetes/kubernetes/pull/58767), [@2rs2ts](https://github.com/2rs2ts)) -* Fixes an error when deleting an NLB in AWS - Fixes [#57568](https://github.com/kubernetes/kubernetes/pull/57568) ([#57569](https://github.com/kubernetes/kubernetes/pull/57569), [@micahhausler](https://github.com/micahhausler)) -* fix device name change issue for azure disk ([#60346](https://github.com/kubernetes/kubernetes/pull/60346), [@andyzhangx](https://github.com/andyzhangx)) -* On cluster provision or upgrade, kubeadm now generates certs and secures all connections to the etcd static-pod with mTLS. ([#57415](https://github.com/kubernetes/kubernetes/pull/57415), [@stealthybox](https://github.com/stealthybox)) -* Some field names in the Kubelet's now v1beta1 config API differ from the v1alpha1 API: PodManifestPath is renamed to StaticPodPath, ManifestURL is renamed to StaticPodURL, ManifestURLHeader is renamed to StaticPodURLHeader. ([#60314](https://github.com/kubernetes/kubernetes/pull/60314), [@mtaufen](https://github.com/mtaufen)) -* Adds BETA support for `DNSConfig` field in PodSpec and `DNSPolicy=None`. ([#59771](https://github.com/kubernetes/kubernetes/pull/59771), [@MrHohn](https://github.com/MrHohn)) -* kubeadm: Demote controlplane passthrough flags to alpha flags ([#59882](https://github.com/kubernetes/kubernetes/pull/59882), [@kris-nova](https://github.com/kris-nova)) -* DevicePlugins feature graduates to beta. ([#60170](https://github.com/kubernetes/kubernetes/pull/60170), [@jiayingz](https://github.com/jiayingz)) -* Additional changes to iptables kube-proxy backend to improve performance on clusters with very large numbers of services. ([#60306](https://github.com/kubernetes/kubernetes/pull/60306), [@danwinship](https://github.com/danwinship)) -* CSI now allows credentials to be specified on CreateVolume/DeleteVolume, ControllerPublishVolume/ControllerUnpublishVolume, and NodePublishVolume/NodeUnpublishVolume operations ([#60118](https://github.com/kubernetes/kubernetes/pull/60118), [@sbezverk](https://github.com/sbezverk)) -* Disable mount propagation for windows containers. ([#60275](https://github.com/kubernetes/kubernetes/pull/60275), [@feiskyer](https://github.com/feiskyer)) -* Introduced `--http2-max-streams-per-connection` command line flag on api-servers and set default to 1000 for aggregated API servers. ([#60054](https://github.com/kubernetes/kubernetes/pull/60054), [@MikeSpreitzer](https://github.com/MikeSpreitzer)) -* APIserver backed by etcdv3 exports metric showing number of resources per kind ([#59757](https://github.com/kubernetes/kubernetes/pull/59757), [@gmarek](https://github.com/gmarek)) -* The DaemonSet controller, its integration tests, and its e2e tests, have been updated to use the apps/v1 API. ([#59883](https://github.com/kubernetes/kubernetes/pull/59883), [@kow3ns](https://github.com/kow3ns)) -* Fix image file system stats for windows nodes ([#59743](https://github.com/kubernetes/kubernetes/pull/59743), [@feiskyer](https://github.com/feiskyer)) -* Custom resources can be listed with a set of grouped resources (category) by specifying the categories in the CustomResourceDefinition spec. Example: They can be used with `kubectl get all`, where `all` is a category. ([#59561](https://github.com/kubernetes/kubernetes/pull/59561), [@nikhita](https://github.com/nikhita)) -* [fluentd-gcp addon] Fixed bug with reporting metrics in event-exporter ([#60126](https://github.com/kubernetes/kubernetes/pull/60126), [@serathius](https://github.com/serathius)) -* Critical pods to use priorityClasses. ([#58835](https://github.com/kubernetes/kubernetes/pull/58835), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) -* `--show-all` (which only affected pods and only for human readable/non-API printers) is now defaulted to true and deprecated. It will be inert in 1.11 and removed in a future release. ([#60210](https://github.com/kubernetes/kubernetes/pull/60210), [@deads2k](https://github.com/deads2k)) -* Removed some redundant rules created by the iptables proxier, to improve performance on systems with very many services. ([#57461](https://github.com/kubernetes/kubernetes/pull/57461), [@danwinship](https://github.com/danwinship)) -* Disable per-cpu metrics by default for scalability. ([#60106](https://github.com/kubernetes/kubernetes/pull/60106), [@dashpole](https://github.com/dashpole)) - * Fix inaccurate disk usage monitoring of overlayFs. - * Retry docker connection on startup timeout to avoid permanent loss of metrics. -* When the `PodShareProcessNamespace` alpha feature is enabled, setting `pod.Spec.ShareProcessNamespace` to `true` will cause a single process namespace to be shared between all containers in a pod. ([#60181](https://github.com/kubernetes/kubernetes/pull/60181), [@verb](https://github.com/verb)) -* add spelling checking script ([#59463](https://github.com/kubernetes/kubernetes/pull/59463), [@dixudx](https://github.com/dixudx)) -* Allows HorizontalPodAutoscaler to use global metrics not associated with any Kubernetes object (for example metrics from a hoster service running outside of Kubernetes cluster). ([#60096](https://github.com/kubernetes/kubernetes/pull/60096), [@MaciekPytel](https://github.com/MaciekPytel)) -* fix race condition issue when detaching azure disk ([#60183](https://github.com/kubernetes/kubernetes/pull/60183), [@andyzhangx](https://github.com/andyzhangx)) -* Add kubectl create job command ([#60084](https://github.com/kubernetes/kubernetes/pull/60084), [@soltysh](https://github.com/soltysh)) -* [Alpha] Kubelet now supports container log rotation for container runtime which implements CRI(container runtime interface). ([#59898](https://github.com/kubernetes/kubernetes/pull/59898), [@Random-Liu](https://github.com/Random-Liu)) - * The feature can be enabled with feature gate `CRIContainerLogRotation`. - * The flags `--container-log-max-size` and `--container-log-max-files` can be used to configure the rotation behavior. -* Reorganized iptables rules to fix a performance regression on clusters with thousands of services. ([#56164](https://github.com/kubernetes/kubernetes/pull/56164), [@danwinship](https://github.com/danwinship)) -* StorageOS volume plugin updated to support mount options and environments where the kubelet runs in a container and the device location should be specified. ([#58816](https://github.com/kubernetes/kubernetes/pull/58816), [@croomes](https://github.com/croomes)) -* Use consts as predicate name in handlers ([#59952](https://github.com/kubernetes/kubernetes/pull/59952), [@resouer](https://github.com/resouer)) -* `/status` and `/scale` subresources are added for custom resources. ([#55168](https://github.com/kubernetes/kubernetes/pull/55168), [@nikhita](https://github.com/nikhita)) -* Allow kubectl env to specify which keys to import from a config map ([#60040](https://github.com/kubernetes/kubernetes/pull/60040), [@PhilipGough](https://github.com/PhilipGough)) -* Set default enabled admission plugins `NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota` ([#58684](https://github.com/kubernetes/kubernetes/pull/58684), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) -* Fix instanceID for vmss nodes. ([#59857](https://github.com/kubernetes/kubernetes/pull/59857), [@feiskyer](https://github.com/feiskyer)) -* Deprecate kubectl scale jobs (only jobs). ([#60139](https://github.com/kubernetes/kubernetes/pull/60139), [@soltysh](https://github.com/soltysh)) -* Adds new flag `--apiserver-advertise-dns-address` which is used in node kubelet.confg to point to API server ([#59288](https://github.com/kubernetes/kubernetes/pull/59288), [@stevesloka](https://github.com/stevesloka)) -* Fix kube-proxy flags validation for --healthz-bind-address and --metrics-bind-address to allow specifying ip:port. ([#54191](https://github.com/kubernetes/kubernetes/pull/54191), [@MrHohn](https://github.com/MrHohn)) -* Increase allowed lag for ssh key sync loop in tunneler to allow for one failure ([#60068](https://github.com/kubernetes/kubernetes/pull/60068), [@wojtek-t](https://github.com/wojtek-t)) -* Flags that can be set via the Kubelet's --config file are now deprecated in favor of the file. ([#60148](https://github.com/kubernetes/kubernetes/pull/60148), [@mtaufen](https://github.com/mtaufen)) -* PVC Protection alpha feature was renamed to Storage Protection. Storage Protection feature is beta. ([#59052](https://github.com/kubernetes/kubernetes/pull/59052), [@pospispa](https://github.com/pospispa)) -* kube-apiserver: the root /proxy paths have been removed (deprecated since v1.2). Use the /proxy subresources on objects that support HTTP proxying. ([#59884](https://github.com/kubernetes/kubernetes/pull/59884), [@mikedanese](https://github.com/mikedanese)) -* Set an upper bound (5 minutes) on how long the Kubelet will wait before exiting when the client cert from disk is missing or invalid. This prevents the Kubelet from waiting forever without attempting to bootstrap a new client credentials. ([#59316](https://github.com/kubernetes/kubernetes/pull/59316), [@smarterclayton](https://github.com/smarterclayton)) -* v1.Pod now has a field to configure whether a single process namespace should be shared between all containers in a pod. This feature is in alpha preview. ([#58716](https://github.com/kubernetes/kubernetes/pull/58716), [@verb](https://github.com/verb)) -* Priority admission controller picks a global default with the lowest priority value if more than one such default PriorityClass exists. ([#59991](https://github.com/kubernetes/kubernetes/pull/59991), [@bsalamat](https://github.com/bsalamat)) -* Add ipset binary for IPVS to hyperkube docker image ([#57648](https://github.com/kubernetes/kubernetes/pull/57648), [@Fsero](https://github.com/Fsero)) -* kube-apiserver: the OpenID Connect authenticator can now verify ID Tokens signed with JOSE algorithms other than RS256 through the --oidc-signing-algs flag. ([#58544](https://github.com/kubernetes/kubernetes/pull/58544), [@ericchiang](https://github.com/ericchiang)) - * kube-apiserver: the OpenID Connect authenticator no longer accepts tokens from the Google v3 token APIs, users must switch to the "https://www.googleapis.com/oauth2/v4/token" endpoint. -* Rename StorageProtection to StorageObjectInUseProtection ([#59901](https://github.com/kubernetes/kubernetes/pull/59901), [@NickrenREN](https://github.com/NickrenREN)) -* kubeadm: add criSocket field to MasterConfiguration manifiest ([#59057](https://github.com/kubernetes/kubernetes/pull/59057), [@JordanFaust](https://github.com/JordanFaust)) -* kubeadm: add criSocket field to NodeConfiguration manifiest ([#59292](https://github.com/kubernetes/kubernetes/pull/59292), [@JordanFaust](https://github.com/JordanFaust)) -* The `PodSecurityPolicy` API has been moved to the `policy/v1beta1` API group. The `PodSecurityPolicy` API in the `extensions/v1beta1` API group is deprecated and will be removed in a future release. Authorizations for using pod security policy resources should change to reference the `policy` API group after upgrading to 1.11. ([#54933](https://github.com/kubernetes/kubernetes/pull/54933), [@php-coder](https://github.com/php-coder)) -* Restores the ability of older clients to delete and scale jobs with initContainers ([#59880](https://github.com/kubernetes/kubernetes/pull/59880), [@liggitt](https://github.com/liggitt)) -* Support for resource quota on extended resources ([#57302](https://github.com/kubernetes/kubernetes/pull/57302), [@lichuqiang](https://github.com/lichuqiang)) -* Fix race causing apiserver crashes during etcd healthchecking ([#60069](https://github.com/kubernetes/kubernetes/pull/60069), [@wojtek-t](https://github.com/wojtek-t)) -* If TaintNodesByCondition enabled, taint node when it under PID pressure ([#60008](https://github.com/kubernetes/kubernetes/pull/60008), [@k82cn](https://github.com/k82cn)) -* Expose total usage of pods through the "pods" SystemContainer in the Kubelet Summary API ([#57802](https://github.com/kubernetes/kubernetes/pull/57802), [@dashpole](https://github.com/dashpole)) -* Unauthorized requests will not match audit policy rules where users or groups are set. ([#59398](https://github.com/kubernetes/kubernetes/pull/59398), [@CaoShuFeng](https://github.com/CaoShuFeng)) -* Making sure CSI E2E test runs on a local cluster ([#60017](https://github.com/kubernetes/kubernetes/pull/60017), [@sbezverk](https://github.com/sbezverk)) -* Addressing breaking changes introduced by new 0.2.0 release of CSI spec ([#59209](https://github.com/kubernetes/kubernetes/pull/59209), [@sbezverk](https://github.com/sbezverk)) -* GCE: A role and clusterrole will now be provided with GCE/GKE for allowing the cloud-provider to post warning events on all services and watching configmaps in the kube-system namespace. ([#59686](https://github.com/kubernetes/kubernetes/pull/59686), [@nicksardo](https://github.com/nicksardo)) -* Updated PID pressure node condition ([#57136](https://github.com/kubernetes/kubernetes/pull/57136), [@k82cn](https://github.com/k82cn)) -* Add AWS cloud provider option to use an assumed IAM role ([#59668](https://github.com/kubernetes/kubernetes/pull/59668), [@brycecarman](https://github.com/brycecarman)) -* `kubectl port-forward` now supports specifying a service to port forward to: `kubectl port-forward svc/myservice 8443:443` ([#59809](https://github.com/kubernetes/kubernetes/pull/59809), [@phsiao](https://github.com/phsiao)) -* Fix kubelet PVC stale metrics ([#59170](https://github.com/kubernetes/kubernetes/pull/59170), [@cofyc](https://github.com/cofyc)) -* Separate current ARM rate limiter into read/write ([#59830](https://github.com/kubernetes/kubernetes/pull/59830), [@khenidak](https://github.com/khenidak)) - * Improve control over how ARM rate limiter is used within Azure cloud provider -* The ConfigOK node condition has been renamed to KubeletConfigOk. ([#59905](https://github.com/kubernetes/kubernetes/pull/59905), [@mtaufen](https://github.com/mtaufen)) -* fluentd-gcp resources can be modified via a ScalingPolicy ([#59657](https://github.com/kubernetes/kubernetes/pull/59657), [@x13n](https://github.com/x13n)) -* Adding pkg/kubelet/apis/deviceplugin/v1beta1 API. ([#59588](https://github.com/kubernetes/kubernetes/pull/59588), [@jiayingz](https://github.com/jiayingz)) -* Fixes volume predicate handler for equiv class ([#59335](https://github.com/kubernetes/kubernetes/pull/59335), [@resouer](https://github.com/resouer)) -* Bugfix: vSphere Cloud Provider (VCP) does not need any special service account anymore. ([#59440](https://github.com/kubernetes/kubernetes/pull/59440), [@rohitjogvmw](https://github.com/rohitjogvmw)) -* Fixing a bug in OpenStack cloud provider, where dual stack deployments (IPv4 and IPv6) did not work well when using kubenet as the network plugin. ([#59749](https://github.com/kubernetes/kubernetes/pull/59749), [@zioproto](https://github.com/zioproto)) -* Get parent dir via canonical absolute path when trying to judge mount-point ([#58433](https://github.com/kubernetes/kubernetes/pull/58433), [@yue9944882](https://github.com/yue9944882)) -* Container runtime daemon (e.g. dockerd) logs in GCE cluster will be uploaded to stackdriver and elasticsearch with tag `container-runtime` ([#59103](https://github.com/kubernetes/kubernetes/pull/59103), [@Random-Liu](https://github.com/Random-Liu)) -* Add AzureDisk support for vmss nodes ([#59716](https://github.com/kubernetes/kubernetes/pull/59716), [@feiskyer](https://github.com/feiskyer)) -* Fixed a race condition in k8s.io/client-go/tools/cache.SharedInformer that could violate the sequential delivery guarantee and cause panics on shutdown. ([#59828](https://github.com/kubernetes/kubernetes/pull/59828), [@krousey](https://github.com/krousey)) -* Avoid hook errors when effecting label changes on kubernetes-worker charm. ([#59803](https://github.com/kubernetes/kubernetes/pull/59803), [@wwwtyro](https://github.com/wwwtyro)) -* kubectl port-forward now allows using resource name (e.g., deployment/www) to select a matching pod, as well as allows the use of --pod-running-timeout to wait till at least one pod is running. ([#59705](https://github.com/kubernetes/kubernetes/pull/59705), [@phsiao](https://github.com/phsiao)) - * kubectl port-forward no longer support deprecated -p flag -* Deprecate insecure HTTP port of kube-controller-manager and cloud-controller-manager. Use `--secure-port` and `--bind-address` instead. ([#59582](https://github.com/kubernetes/kubernetes/pull/59582), [@sttts](https://github.com/sttts)) -* Eviction thresholds set to 0% or 100% are now ignored. ([#59681](https://github.com/kubernetes/kubernetes/pull/59681), [@mtaufen](https://github.com/mtaufen)) -* [advanced audit] support subresources wildcard matching. ([#55306](https://github.com/kubernetes/kubernetes/pull/55306), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) -* CronJobs can be accessed through cj alias ([#59499](https://github.com/kubernetes/kubernetes/pull/59499), [@soltysh](https://github.com/soltysh)) -* fix typo in resource_allocation.go ([#58275](https://github.com/kubernetes/kubernetes/pull/58275), [@carmark](https://github.com/carmark)) -* fix the error prone account creation method of blob disk ([#59739](https://github.com/kubernetes/kubernetes/pull/59739), [@andyzhangx](https://github.com/andyzhangx)) -* Add automatic etcd 3.2->3.1 and 3.1->3.0 minor version rollback support to gcr.io/google_container/etcd images. For HA clusters, all members must be stopped before performing a rollback. ([#59298](https://github.com/kubernetes/kubernetes/pull/59298), [@jpbetz](https://github.com/jpbetz)) -* `kubeadm init` can now omit the tainting of the master node if configured to do so in `kubeadm.yaml`. ([#55479](https://github.com/kubernetes/kubernetes/pull/55479), [@ijc](https://github.com/ijc)) -* Updated kubernetes-worker to request new security tokens when the aws cloud provider changes the registered node name. ([#59730](https://github.com/kubernetes/kubernetes/pull/59730), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* Controller-manager --service-sync-period flag is removed (was never used in the code). ([#59359](https://github.com/kubernetes/kubernetes/pull/59359), [@khenidak](https://github.com/khenidak)) -* Pod priority can be specified ins PodSpec even when the feature is disabled, but it will be effective only when the feature is enabled. ([#59291](https://github.com/kubernetes/kubernetes/pull/59291), [@bsalamat](https://github.com/bsalamat)) -* kubeadm: Enable auditing behind a feature gate. ([#59067](https://github.com/kubernetes/kubernetes/pull/59067), [@chuckha](https://github.com/chuckha)) -* Map correct vmset name for Azure internal load balancers ([#59747](https://github.com/kubernetes/kubernetes/pull/59747), [@feiskyer](https://github.com/feiskyer)) -* Add generic cache for Azure VMSS ([#59652](https://github.com/kubernetes/kubernetes/pull/59652), [@feiskyer](https://github.com/feiskyer)) -* kubeadm: New "imagePullPolicy" option in the init configuration file, that gets forwarded to kubelet static pods to control pull policy for etcd and control plane images. ([#58960](https://github.com/kubernetes/kubernetes/pull/58960), [@rosti](https://github.com/rosti)) -* fix the create azure file pvc failure if there is no storage account in current resource group ([#56557](https://github.com/kubernetes/kubernetes/pull/56557), [@andyzhangx](https://github.com/andyzhangx)) -* Add generic cache for Azure VM/LB/NSG/RouteTable ([#59520](https://github.com/kubernetes/kubernetes/pull/59520), [@feiskyer](https://github.com/feiskyer)) -* The alpha KubeletConfiguration.ConfigTrialDuration field is no longer available. ([#59628](https://github.com/kubernetes/kubernetes/pull/59628), [@mtaufen](https://github.com/mtaufen)) -* Updates Calico version to v2.6.7 (Fixed a bug where Felix would crash when parsing a NetworkPolicy with a named port. See https://github.com/projectcalico/calico/releases/tag/v2.6.7) ([#59130](https://github.com/kubernetes/kubernetes/pull/59130), [@caseydavenport](https://github.com/caseydavenport)) -* return error if New-SmbGlobalMapping failed when mounting azure file on Windows ([#59540](https://github.com/kubernetes/kubernetes/pull/59540), [@andyzhangx](https://github.com/andyzhangx)) -* Disallow PriorityClass names with 'system-' prefix for user defined priority classes. ([#59382](https://github.com/kubernetes/kubernetes/pull/59382), [@bsalamat](https://github.com/bsalamat)) -* Fixed an issue where Portworx volume driver wasn't passing namespace and annotations to the Portworx Create API. ([#59607](https://github.com/kubernetes/kubernetes/pull/59607), [@harsh-px](https://github.com/harsh-px)) -* Enable apiserver metrics for custom resources. ([#57682](https://github.com/kubernetes/kubernetes/pull/57682), [@nikhita](https://github.com/nikhita)) -* fix typo ([#59619](https://github.com/kubernetes/kubernetes/pull/59619), [@jianliao82](https://github.com/jianliao82)) - * incase -> in case - * selction -> selection -* Implement envelope service with gRPC, so that KMS providers can be pulled out from API server. ([#55684](https://github.com/kubernetes/kubernetes/pull/55684), [@wu-qiang](https://github.com/wu-qiang)) -* Enable golint for `pkg/scheduler` and fix the golint errors in it. ([#58437](https://github.com/kubernetes/kubernetes/pull/58437), [@tossmilestone](https://github.com/tossmilestone)) -* AWS: Make attach/detach operations faster. from 10-12s to 2-6s ([#56974](https://github.com/kubernetes/kubernetes/pull/56974), [@gnufied](https://github.com/gnufied)) -* CRI starts using moutpoint as image filesystem identifier instead of UUID. ([#59475](https://github.com/kubernetes/kubernetes/pull/59475), [@Random-Liu](https://github.com/Random-Liu)) -* DaemonSet, Deployment, ReplicaSet, and StatefulSet objects are now persisted in etcd in apps/v1 format ([#58854](https://github.com/kubernetes/kubernetes/pull/58854), [@liggitt](https://github.com/liggitt)) -* 'none' can now be specified in KubeletConfiguration.EnforceNodeAllocatable (--enforce-node-allocatable) to explicitly disable enforcement. ([#59515](https://github.com/kubernetes/kubernetes/pull/59515), [@mtaufen](https://github.com/mtaufen)) -* vSphere Cloud Provider supports VMs provisioned on vSphere v1.6.5 ([#59519](https://github.com/kubernetes/kubernetes/pull/59519), [@abrarshivani](https://github.com/abrarshivani)) -* Annotations is added to advanced audit api ([#58806](https://github.com/kubernetes/kubernetes/pull/58806), [@CaoShuFeng](https://github.com/CaoShuFeng)) -* 2nd try at using a vanity GCR name ([#57824](https://github.com/kubernetes/kubernetes/pull/57824), [@thockin](https://github.com/thockin)) -* Node's providerID is following Azure resource ID format now when useInstanceMetadata is enabled ([#59539](https://github.com/kubernetes/kubernetes/pull/59539), [@feiskyer](https://github.com/feiskyer)) -* Block Volume Support: Local Volume Plugin update ([#59303](https://github.com/kubernetes/kubernetes/pull/59303), [@dhirajh](https://github.com/dhirajh)) -* [action-required] The Container Runtime Interface (CRI) version has increased from v1alpha1 to v1alpha2. Runtimes implementing the CRI will need to update to the new version, which configures container namespaces using an enumeration rather than booleans. ([#58973](https://github.com/kubernetes/kubernetes/pull/58973), [@verb](https://github.com/verb)) -* Fix the bug where kubelet in the standalone mode would wait for the update from the apiserver source. ([#59276](https://github.com/kubernetes/kubernetes/pull/59276), [@roboll](https://github.com/roboll)) -* Add "keyring" parameter for Ceph RBD provisioner ([#58287](https://github.com/kubernetes/kubernetes/pull/58287), [@madddi](https://github.com/madddi)) -* Ensure euqiv hash calculation is per schedule ([#59245](https://github.com/kubernetes/kubernetes/pull/59245), [@resouer](https://github.com/resouer)) -* kube-scheduler: Use default predicates/prioritizers if they are unspecified in the policy config ([#59363](https://github.com/kubernetes/kubernetes/pull/59363), [@yguo0905](https://github.com/yguo0905)) -* Fixed charm issue where docker login would run prior to daemon options being set. ([#59396](https://github.com/kubernetes/kubernetes/pull/59396), [@kwmonroe](https://github.com/kwmonroe)) -* Implementers of the cloud provider interface will note the addition of a context to this interface. Trivial code modification will be necessary for a cloud provider to continue to compile. ([#59287](https://github.com/kubernetes/kubernetes/pull/59287), [@cheftako](https://github.com/cheftako)) -* /release-note-none ([#58264](https://github.com/kubernetes/kubernetes/pull/58264), [@WanLinghao](https://github.com/WanLinghao)) -* Use a more reliable way to get total physical memory on windows nodes ([#57124](https://github.com/kubernetes/kubernetes/pull/57124), [@JiangtianLi](https://github.com/JiangtianLi)) -* Add xfsprogs to hyperkube container image. ([#56937](https://github.com/kubernetes/kubernetes/pull/56937), [@redbaron](https://github.com/redbaron)) -* Ensure Azure public IP removed after service deleted ([#59340](https://github.com/kubernetes/kubernetes/pull/59340), [@feiskyer](https://github.com/feiskyer)) -* Improve messages user gets during and after volume resizing is done. ([#58415](https://github.com/kubernetes/kubernetes/pull/58415), [@gnufied](https://github.com/gnufied)) -* Fix RBAC permissions for Stackdriver Metadata Agent. ([#57455](https://github.com/kubernetes/kubernetes/pull/57455), [@kawych](https://github.com/kawych)) -* Scheduler should be able to read from config file if configmap is not present. ([#59386](https://github.com/kubernetes/kubernetes/pull/59386), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) -* MountPropagation feature is now beta. As consequence, all volume mounts in containers are now "rslave" on Linux by default. ([#59252](https://github.com/kubernetes/kubernetes/pull/59252), [@jsafrane](https://github.com/jsafrane)) -* Fix RBAC role for certificate controller to allow cleaning. ([#59375](https://github.com/kubernetes/kubernetes/pull/59375), [@mikedanese](https://github.com/mikedanese)) -* Volume metrics support for vSphere Cloud Provider ([#59328](https://github.com/kubernetes/kubernetes/pull/59328), [@divyenpatel](https://github.com/divyenpatel)) -* Announcing the deprecation of the recycling reclaim policy. ([#59063](https://github.com/kubernetes/kubernetes/pull/59063), [@ayushpateria](https://github.com/ayushpateria)) -* Intended for post-1.9 ([#57872](https://github.com/kubernetes/kubernetes/pull/57872), [@mlmhl](https://github.com/mlmhl)) -* The `meta.k8s.io/v1alpha1` objects for retrieving tabular responses from the server (`Table`) or fetching just the `ObjectMeta` for an object (as `PartialObjectMetadata`) are now beta as part of `meta.k8s.io/v1beta1`. Clients may request alternate representations of normal Kubernetes objects by passing an `Accept` header like `application/json;as=Table;g=meta.k8s.io;v=v1beta1` or `application/json;as=PartialObjectMetadata;g=meta.k8s.io;v1=v1beta1`. Older servers will ignore this representation or return an error if it is not available. Clients may request fallback to the normal object by adding a non-qualified mime-type to their `Accept` header like `application/json` - the server will then respond with either the alternate representation if it is supported or the fallback mime-type which is the normal object response. ([#59059](https://github.com/kubernetes/kubernetes/pull/59059), [@smarterclayton](https://github.com/smarterclayton)) -* add PV size grow feature for azure file ([#57017](https://github.com/kubernetes/kubernetes/pull/57017), [@andyzhangx](https://github.com/andyzhangx)) -* Upgrade default etcd server version to 3.2.14 ([#58645](https://github.com/kubernetes/kubernetes/pull/58645), [@jpbetz](https://github.com/jpbetz)) -* Add windows config to Kubelet CRI ([#57076](https://github.com/kubernetes/kubernetes/pull/57076), [@feiskyer](https://github.com/feiskyer)) -* Configurable etcd quota backend bytes in GCE ([#59259](https://github.com/kubernetes/kubernetes/pull/59259), [@wojtek-t](https://github.com/wojtek-t)) -* Remove unmaintained kube-registry-proxy support from gce kube-up. ([#58564](https://github.com/kubernetes/kubernetes/pull/58564), [@mikedanese](https://github.com/mikedanese)) -* Allow expanding mounted volumes ([#58794](https://github.com/kubernetes/kubernetes/pull/58794), [@gnufied](https://github.com/gnufied)) -* Upped the timeout for apiserver communication in the juju kubernetes-worker charm. ([#59219](https://github.com/kubernetes/kubernetes/pull/59219), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* kubeadm init: skip checking cri socket in preflight checks ([#58802](https://github.com/kubernetes/kubernetes/pull/58802), [@dixudx](https://github.com/dixudx)) -* Add "nominatedNodeName" field to PodStatus. This field is set when a pod preempts other pods on the node. ([#58990](https://github.com/kubernetes/kubernetes/pull/58990), [@bsalamat](https://github.com/bsalamat)) -* Changes secret, configMap, downwardAPI and projected volumes to mount read-only, instead of allowing applications to write data and then reverting it automatically. Until version 1.11, setting the feature gate ReadOnlyAPIDataVolumes=false will preserve the old behavior. ([#58720](https://github.com/kubernetes/kubernetes/pull/58720), [@joelsmith](https://github.com/joelsmith)) -* Fixed issue with charm upgrades resulting in an error state. ([#59064](https://github.com/kubernetes/kubernetes/pull/59064), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* Ensure IP is set for Azure internal load balancer. ([#59083](https://github.com/kubernetes/kubernetes/pull/59083), [@feiskyer](https://github.com/feiskyer)) -* Postpone PV deletion when it is being bound to a PVC ([#58743](https://github.com/kubernetes/kubernetes/pull/58743), [@NickrenREN](https://github.com/NickrenREN)) -* Add V1beta1 VolumeAttachment API, co-existing with Alpha API object ([#58462](https://github.com/kubernetes/kubernetes/pull/58462), [@NickrenREN](https://github.com/NickrenREN)) -* When using client or server certificate rotation, the Kubelet will no longer wait until the initial rotation succeeds or fails before starting static pods. This makes running self-hosted masters with rotation more predictable. ([#58930](https://github.com/kubernetes/kubernetes/pull/58930), [@smarterclayton](https://github.com/smarterclayton)) - - - -# v1.10.0-alpha.3 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/master/examples) - -## Downloads for v1.10.0-alpha.3 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes.tar.gz) | `246f0373ccb25a243a387527b32354b69fc2211c422e71479d22bfb3a829c8fb` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-src.tar.gz) | `f9c60bb37fb7b363c9f66d8efd8aa5a36ea2093c61317c950719b3ddc86c5e10` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-darwin-386.tar.gz) | `ca8dfd7fbd34478e7ba9bba3779fcca08f7efd4f218b0c8a7f52bbeea0f42cd7` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-darwin-amd64.tar.gz) | `713c35d99f44bd19d225d2c9f2d7c4f3976b5dd76e9a817b2aaf68ee0cb5a939` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-linux-386.tar.gz) | `7601e55e3bb0f0fc11611c68c4bc000c3cbbb7a09652c386e482a1671be7e2d6` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-linux-amd64.tar.gz) | `8a6c498531c1832176e22d622008a98bac6043f05dec96747649651531ed3fd7` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-linux-arm64.tar.gz) | `81561820fb5a000152e9d8d94882e0ed6228025ea7973ee98173b5fc89d62a42` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-linux-arm.tar.gz) | `6ce8c3ed253a10d78e62e000419653a29c411cd64910325b21ff3370cb0a89eb` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-linux-ppc64le.tar.gz) | `a46b42c94040767f6bbf2ce10aef36d8dbe94c0069f866a848d69b2274f8f0bc` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-linux-s390x.tar.gz) | `fa3e656b612277fc4c303aef95c60b58ed887e36431db23d26b536f226a23cf6` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-windows-386.tar.gz) | `832e12266495ac55cb54a999bc5ae41d42d160387b487d8b4ead577d96686b62` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-client-windows-amd64.tar.gz) | `7056a3eb5a8f9e8fa0326aa6e0bf97fc5b260447315f8ec7340be5747a16f5fd` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-server-linux-amd64.tar.gz) | `dc8e2be2fcb6477249621fb5c813c853371a3bf8732c5cb3a6d6cab667cfa324` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-server-linux-arm64.tar.gz) | `399071ad9042a72bccd6e1aa322405c02b4a807c0b4f987d608c4c9c369979d6` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-server-linux-arm.tar.gz) | `7457ad16665e331fa9224a3d61690206723721197ad9760c3b488de9602293f5` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-server-linux-ppc64le.tar.gz) | `ffcb728d879c0347bd751c9bccac3520bb057d203ba1acd55f8c727295282049` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-server-linux-s390x.tar.gz) | `f942f6e15886a1fb0d91d04adf47677068c56070dff060f38c371c3ee3e99648` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-node-linux-amd64.tar.gz) | `81b22beb30be9d270016c7b35b86ea585f29c0c5f09128da9341f9f67c8865f9` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-node-linux-arm64.tar.gz) | `d9020b99c145f44c519b1a95b55ed24e69d9c679a02352c7e05e86042daca9d1` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-node-linux-arm.tar.gz) | `1d10bee4ed62d70b318f5703b2cd8295a08e199f810d6b361f367907e3f01fb6` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-node-linux-ppc64le.tar.gz) | `67cd4dde212abda37e6f9e6dee1bb59db96e0727100ef0aa561c15562df0f3e1` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-node-linux-s390x.tar.gz) | `362b030e011ea6222b1f2dec62311d3971bcce4dba94997963e2a091efbf967b` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.3/kubernetes-node-windows-amd64.tar.gz) | `e609a2b0410acbb64d3ee6d7f134d98723d82d05bdbead1eaafd3584d3e45c39` - -## Changelog since v1.10.0-alpha.2 - -### Other notable changes - -* Fixed issue with kubernetes-worker option allow-privileged not properly handling the value True with a capital T. ([#59116](https://github.com/kubernetes/kubernetes/pull/59116), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* Added anti-affinity to kube-dns pods ([#57683](https://github.com/kubernetes/kubernetes/pull/57683), [@vainu-arto](https://github.com/vainu-arto)) -* cloudprovider/openstack: fix bug the tries to use octavia client to query flip ([#59075](https://github.com/kubernetes/kubernetes/pull/59075), [@jrperritt](https://github.com/jrperritt)) -* Windows containers now support experimental Hyper-V isolation by setting annotation `experimental.windows.kubernetes.io/isolation-type=hyperv` and feature gates HyperVContainer. Only one container per pod is supported yet. ([#58751](https://github.com/kubernetes/kubernetes/pull/58751), [@feiskyer](https://github.com/feiskyer)) -* `crds` is added as a shortname for CustomResourceDefinition i.e. `kubectl get crds` can now be used. ([#59061](https://github.com/kubernetes/kubernetes/pull/59061), [@nikhita](https://github.com/nikhita)) -* Fix an issue where port forwarding doesn't forward local TCP6 ports to the pod ([#57457](https://github.com/kubernetes/kubernetes/pull/57457), [@vfreex](https://github.com/vfreex)) -* YAMLDecoder Read now tracks rest of buffer on io.ErrShortBuffer ([#58817](https://github.com/kubernetes/kubernetes/pull/58817), [@karlhungus](https://github.com/karlhungus)) -* Prevent kubelet from getting wedged if initialization of modules returns an error. ([#59020](https://github.com/kubernetes/kubernetes/pull/59020), [@brendandburns](https://github.com/brendandburns)) -* Fixed a race condition inside kubernetes-worker that would result in a temporary error situation. ([#59005](https://github.com/kubernetes/kubernetes/pull/59005), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* [GCE] Apiserver uses `InternalIP` as the most preferred kubelet address type by default. ([#59019](https://github.com/kubernetes/kubernetes/pull/59019), [@MrHohn](https://github.com/MrHohn)) -* Deprecate insecure flags `--insecure-bind-address`, `--insecure-port` and remove `--public-address-override`. ([#59018](https://github.com/kubernetes/kubernetes/pull/59018), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) -* Support GetLabelsForVolume in OpenStack Provider ([#58871](https://github.com/kubernetes/kubernetes/pull/58871), [@edisonxiang](https://github.com/edisonxiang)) -* Build using go1.9.3. ([#59012](https://github.com/kubernetes/kubernetes/pull/59012), [@ixdy](https://github.com/ixdy)) -* CRI: Add a call to reopen log file for a container. ([#58899](https://github.com/kubernetes/kubernetes/pull/58899), [@yujuhong](https://github.com/yujuhong)) -* The alpha KubeletConfigFile feature gate has been removed, because it was redundant with the Kubelet's --config flag. It is no longer necessary to set this gate to use the flag. The --config flag is still considered alpha. ([#58978](https://github.com/kubernetes/kubernetes/pull/58978), [@mtaufen](https://github.com/mtaufen)) -* `kubectl scale` can now scale any resource (kube, CRD, aggregate) conforming to the standard scale endpoint ([#58298](https://github.com/kubernetes/kubernetes/pull/58298), [@p0lyn0mial](https://github.com/p0lyn0mial)) -* kube-apiserver flag --tls-ca-file has had no effect for some time. It is now deprecated and slated for removal in 1.11. If you are specifying this flag, you must remove it from your launch config before upgrading to 1.11. ([#58968](https://github.com/kubernetes/kubernetes/pull/58968), [@deads2k](https://github.com/deads2k)) -* Fix regression in the CRI: do not add a default hostname on short image names ([#58955](https://github.com/kubernetes/kubernetes/pull/58955), [@runcom](https://github.com/runcom)) -* Get windows kernel version directly from registry ([#58498](https://github.com/kubernetes/kubernetes/pull/58498), [@feiskyer](https://github.com/feiskyer)) -* Remove deprecated --require-kubeconfig flag, remove default --kubeconfig value ([#58367](https://github.com/kubernetes/kubernetes/pull/58367), [@zhangxiaoyu-zidif](https://github.com/zhangxiaoyu-zidif)) -* Google Cloud Service Account email addresses can now be used in RBAC ([#58141](https://github.com/kubernetes/kubernetes/pull/58141), [@ahmetb](https://github.com/ahmetb)) - * Role bindings since the default scopes now include the "userinfo.email" - * scope. This is a breaking change if the numeric uniqueIDs of the Google - * service accounts were being used in RBAC role bindings. The behavior - * can be overridden by explicitly specifying the scope values as - * comma-separated string in the "users[*].config.scopes" field in the - * KUBECONFIG file. -* kube-apiserver is changed to use SSH tunnels for webhook iff the webhook is not directly routable from apiserver's network environment. ([#58644](https://github.com/kubernetes/kubernetes/pull/58644), [@yguo0905](https://github.com/yguo0905)) -* Updated priority of mirror pod according to PriorityClassName. ([#58485](https://github.com/kubernetes/kubernetes/pull/58485), [@k82cn](https://github.com/k82cn)) -* Fixes a bug where kubelet crashes trying to free memory under memory pressure ([#58574](https://github.com/kubernetes/kubernetes/pull/58574), [@yastij](https://github.com/yastij)) - - - -# v1.10.0-alpha.2 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/master/examples) - -## Downloads for v1.10.0-alpha.2 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes.tar.gz) | `89efeb8b16c40e5074f092f51399995f0fe4a0312367a8f54bd227c3c6fcb629` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-src.tar.gz) | `eefbbf435f1b7a0e416f4e6b2c936c49ce5d692994da8d235c5e25bc408eec57` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-darwin-386.tar.gz) | `878366200ddfb9128a133d7d377057c6f878b24357062cf5243c0f0aac26b292` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-darwin-amd64.tar.gz) | `dc065b9ecfa513607eac6e7dd125b2c25c9a9e7c13d0b2b6e56586e17bbd6ae5` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-linux-386.tar.gz) | `93c2462051935d8f6bca6c72d09948963d47cd64426660f63e0cea7d37e24812` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-linux-amd64.tar.gz) | `0eef61285fad1f9ff8392c59986d3a41887abc642bcb5cb451c5a5300927e2c4` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-linux-arm64.tar.gz) | `6cf7913730a57b503beaf37f5c4d0f97789358983ed03654036f8b986b60cc62` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-linux-arm.tar.gz) | `f03c3ecbf4c08d263f2daa8cbe838e20452d6650b80e9a74762c155c26a579b7` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-linux-ppc64le.tar.gz) | `25a2f93ebb721901d262adae4c0bdaa4cf1293793e9dff4507e031b85f46aff8` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-linux-s390x.tar.gz) | `3e0b9ef771f36edb61bd61ccb67996ed41793c01f8686509bf93e585ee882c94` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-windows-386.tar.gz) | `387e5e6b0535f4f5996c0732f1b591d80691acaec86e35482c7b90e00a1856f7` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-client-windows-amd64.tar.gz) | `c10a72d40252707b732d33d03beec3c6380802d0a6e3214cbbf4af258fddf28c` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-server-linux-amd64.tar.gz) | `42c1e016e8b0c5cc36c7bf574abca18c63e16d719d35e19ddbcbcd5aaeabc46c` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-server-linux-arm64.tar.gz) | `b7774c54344c75bf5c703d4ca271f0af6c230e86cbe40eafd9cbf98a4f4be6e9` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-server-linux-arm.tar.gz) | `c11c8554506b64d6fd1a6e79bfc4e1e19f4f826b9ba98de81bc757901e8cdc43` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-server-linux-ppc64le.tar.gz) | `196bd957804b2a9049189d225e49bf78e52e9adef12c072128e4e85d35da438e` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-server-linux-s390x.tar.gz) | `be12fbea28a6cb089734782fe11e6f90a30785b9ad1ec02bc08a59afeb95c173` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-node-linux-amd64.tar.gz) | `a1feb239dfc473b49adf95d7d94e4a9c6c7d07416d4e935e3fc10175ffaa7163` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-node-linux-arm64.tar.gz) | `26583c0bd08313bdc0bdfba6745f3ccd0f117431d3a5e2623bb5015675d506b8` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-node-linux-arm.tar.gz) | `79c6299a5482467e3e85ee881f21edf5d491bc28c94e547d9297d1e1ad1b7458` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-node-linux-ppc64le.tar.gz) | `2732fd288f1eac44c599423ce28cbdb85b54a646970a3714be5ff86d1b14b5e2` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-node-linux-s390x.tar.gz) | `8d49432f0ff3baf55e71c29fb6ffc1673b2a45b9eae2e1906138b1409da53940` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.2/kubernetes-node-windows-amd64.tar.gz) | `15ff74edfa98cd1afadcc4e53dd592b1e2935fbab76ad731309d355ae23bdd09` - -## Changelog since v1.10.0-alpha.1 - -### Action Required - -* Bug fix: webhooks now do not skip cluster-scoped resources ([#58185](https://github.com/kubernetes/kubernetes/pull/58185), [@caesarxuchao](https://github.com/caesarxuchao)) - * Action required: Before upgrading your Kubernetes clusters, double check if you had configured webhooks for cluster-scoped objects (e.g., nodes, persistentVolume), these webhooks will start to take effect. Delete/modify the configs if that's not desirable. - -### Other notable changes - -* Fixing extra_sans option on master and load balancer. ([#58843](https://github.com/kubernetes/kubernetes/pull/58843), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* ConfigMap objects now support binary data via a new `binaryData` field. When using `kubectl create configmap --from-file`, files containing non-UTF8 data will be placed in this new field in order to preserve the non-UTF8 data. Use of this feature requires 1.10+ apiserver and kubelets. ([#57938](https://github.com/kubernetes/kubernetes/pull/57938), [@dims](https://github.com/dims)) -* New alpha feature to limit the number of processes running in a pod. Cluster administrators will be able to place limits by using the new kubelet command line parameter --pod-max-pids. Note that since this is a alpha feature they will need to enable the "SupportPodPidsLimit" feature. ([#57973](https://github.com/kubernetes/kubernetes/pull/57973), [@dims](https://github.com/dims)) -* Add storage-backend configuration option to kubernetes-master charm. ([#58830](https://github.com/kubernetes/kubernetes/pull/58830), [@wwwtyro](https://github.com/wwwtyro)) -* use containing API group when resolving shortname from discovery ([#58741](https://github.com/kubernetes/kubernetes/pull/58741), [@dixudx](https://github.com/dixudx)) -* Fix kubectl explain for resources not existing in default version of API group ([#58753](https://github.com/kubernetes/kubernetes/pull/58753), [@soltysh](https://github.com/soltysh)) -* Ensure config has been created before attempting to launch ingress. ([#58756](https://github.com/kubernetes/kubernetes/pull/58756), [@wwwtyro](https://github.com/wwwtyro)) -* Access to externally managed IP addresses via the kube-apiserver service proxy subresource is no longer allowed by default. This can be re-enabled via the `ServiceProxyAllowExternalIPs` feature gate, but will be disallowed completely in 1.11 ([#57265](https://github.com/kubernetes/kubernetes/pull/57265), [@brendandburns](https://github.com/brendandburns)) -* Added support for external cloud providers in kubeadm ([#58259](https://github.com/kubernetes/kubernetes/pull/58259), [@dims](https://github.com/dims)) -* rktnetes has been deprecated in favor of rktlet. Please see https://github.com/kubernetes-incubator/rktlet for more information. ([#58418](https://github.com/kubernetes/kubernetes/pull/58418), [@yujuhong](https://github.com/yujuhong)) -* Fixes bug finding master replicas in GCE when running multiple Kubernetes clusters ([#58561](https://github.com/kubernetes/kubernetes/pull/58561), [@jesseshieh](https://github.com/jesseshieh)) -* Update Calico version to v2.6.6 ([#58482](https://github.com/kubernetes/kubernetes/pull/58482), [@tmjd](https://github.com/tmjd)) -* Promoting the apiregistration.k8s.io (aggregation) to GA ([#58393](https://github.com/kubernetes/kubernetes/pull/58393), [@deads2k](https://github.com/deads2k)) -* Stability: Make Pod delete event handling of scheduler more robust. ([#58712](https://github.com/kubernetes/kubernetes/pull/58712), [@bsalamat](https://github.com/bsalamat)) -* Added support for network spaces in the kubeapi-load-balancer charm ([#58708](https://github.com/kubernetes/kubernetes/pull/58708), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* Added support for network spaces in the kubernetes-master charm ([#58704](https://github.com/kubernetes/kubernetes/pull/58704), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* update etcd unified version to 3.1.10 ([#54242](https://github.com/kubernetes/kubernetes/pull/54242), [@zouyee](https://github.com/zouyee)) -* updates fluentd in fluentd-es-image to fluentd 1.1.0 ([#58525](https://github.com/kubernetes/kubernetes/pull/58525), [@monotek](https://github.com/monotek)) -* Support metrics API in `kubectl top` commands. ([#56206](https://github.com/kubernetes/kubernetes/pull/56206), [@brancz](https://github.com/brancz)) -* Added support for network spaces in the kubernetes-worker charm ([#58523](https://github.com/kubernetes/kubernetes/pull/58523), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* CustomResourceDefinitions: OpenAPI v3 validation schemas containing `$ref`references are no longer permitted (valid references could not be constructed previously because property ids were not permitted either). Before upgrading, ensure CRD definitions do not include those `$ref` fields. ([#58438](https://github.com/kubernetes/kubernetes/pull/58438), [@carlory](https://github.com/carlory)) -* Openstack: register metadata.hostname as node name ([#58502](https://github.com/kubernetes/kubernetes/pull/58502), [@dixudx](https://github.com/dixudx)) -* Added nginx and default backend images to kubernetes-worker config. ([#58542](https://github.com/kubernetes/kubernetes/pull/58542), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* --tls-min-version on kubelet and kube-apiserver allow for configuring minimum TLS versions ([#58528](https://github.com/kubernetes/kubernetes/pull/58528), [@deads2k](https://github.com/deads2k)) -* Fixes an issue where the resourceVersion of an object in a DELETE watch event was not the resourceVersion of the delete itself, but of the last update to the object. This could disrupt the ability of clients clients to re-establish watches properly. ([#58547](https://github.com/kubernetes/kubernetes/pull/58547), [@liggitt](https://github.com/liggitt)) -* Fixed crash in kubectl cp when path has multiple leading slashes ([#58144](https://github.com/kubernetes/kubernetes/pull/58144), [@tomerf](https://github.com/tomerf)) -* kube-apiserver: requests to endpoints handled by unavailable extension API servers (as indicated by an `Available` condition of `false` in the registered APIService) now return `503` errors instead of `404` errors. ([#58070](https://github.com/kubernetes/kubernetes/pull/58070), [@weekface](https://github.com/weekface)) -* Correctly handle transient connection reset errors on GET requests from client library. ([#58520](https://github.com/kubernetes/kubernetes/pull/58520), [@porridge](https://github.com/porridge)) -* Authentication information for OpenStack cloud provider can now be specified as environment variables ([#58300](https://github.com/kubernetes/kubernetes/pull/58300), [@dims](https://github.com/dims)) -* Bump GCE metadata proxy to v0.1.9 to pick up security fixes. ([#58221](https://github.com/kubernetes/kubernetes/pull/58221), [@ihmccreery](https://github.com/ihmccreery)) -* kubeadm now supports CIDR notations in NO_PROXY environment variable ([#53895](https://github.com/kubernetes/kubernetes/pull/53895), [@kad](https://github.com/kad)) -* kubeadm now accept `--apiserver-extra-args`, `--controller-manager-extra-args` and `--scheduler-extra-args` to override / specify additional flags for control plane components ([#58080](https://github.com/kubernetes/kubernetes/pull/58080), [@simonferquel](https://github.com/simonferquel)) -* Add `--enable-admission-plugins` `--disable-admission-plugins` flags and deprecate `--admission-control`. ([#58123](https://github.com/kubernetes/kubernetes/pull/58123), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) - * Afterwards, don't care about the orders specified in the flags. -* "ExternalTrafficLocalOnly" has been removed from feature gate. It has been a GA feature since v1.7. ([#56948](https://github.com/kubernetes/kubernetes/pull/56948), [@MrHohn](https://github.com/MrHohn)) -* GCP: allow a master to not include a metadata concealment firewall rule (if it's not running the metadata proxy). ([#58104](https://github.com/kubernetes/kubernetes/pull/58104), [@ihmccreery](https://github.com/ihmccreery)) -* kube-apiserver: fixes loading of `--admission-control-config-file` containing AdmissionConfiguration apiserver.k8s.io/v1alpha1 config object ([#58439](https://github.com/kubernetes/kubernetes/pull/58439), [@liggitt](https://github.com/liggitt)) -* Fix issue when using OpenStack config drive for node metadata ([#57561](https://github.com/kubernetes/kubernetes/pull/57561), [@dims](https://github.com/dims)) -* Add FSType for CSI volume source to specify filesystems ([#58209](https://github.com/kubernetes/kubernetes/pull/58209), [@NickrenREN](https://github.com/NickrenREN)) -* OpenStack cloudprovider: Ensure orphaned routes are removed. ([#56258](https://github.com/kubernetes/kubernetes/pull/56258), [@databus23](https://github.com/databus23)) -* Reduce Metrics Server memory requirement ([#58391](https://github.com/kubernetes/kubernetes/pull/58391), [@kawych](https://github.com/kawych)) -* Fix a bug affecting nested data volumes such as secret, configmap, etc. ([#57422](https://github.com/kubernetes/kubernetes/pull/57422), [@joelsmith](https://github.com/joelsmith)) -* kubectl now enforces required flags at a more fundamental level ([#53631](https://github.com/kubernetes/kubernetes/pull/53631), [@dixudx](https://github.com/dixudx)) -* Remove alpha Initializers from kubadm admission control ([#58428](https://github.com/kubernetes/kubernetes/pull/58428), [@dixudx](https://github.com/dixudx)) -* Enable ValidatingAdmissionWebhook and MutatingAdmissionWebhook in kubeadm from v1.9 ([#58255](https://github.com/kubernetes/kubernetes/pull/58255), [@dixudx](https://github.com/dixudx)) -* Fixed encryption key and encryption provider rotation ([#58375](https://github.com/kubernetes/kubernetes/pull/58375), [@liggitt](https://github.com/liggitt)) -* set fsGroup by securityContext.fsGroup in azure file ([#58316](https://github.com/kubernetes/kubernetes/pull/58316), [@andyzhangx](https://github.com/andyzhangx)) -* Remove deprecated and unmaintained salt support. kubernetes-salt.tar.gz will no longer be published in the release tarball. ([#58248](https://github.com/kubernetes/kubernetes/pull/58248), [@mikedanese](https://github.com/mikedanese)) -* Detach and clear bad disk URI ([#58345](https://github.com/kubernetes/kubernetes/pull/58345), [@rootfs](https://github.com/rootfs)) -* Allow version arg in kubeadm upgrade apply to be optional if config file already have version info ([#53220](https://github.com/kubernetes/kubernetes/pull/53220), [@medinatiger](https://github.com/medinatiger)) -* feat(fakeclient): push event on watched channel on add/update/delete ([#57504](https://github.com/kubernetes/kubernetes/pull/57504), [@yue9944882](https://github.com/yue9944882)) -* Custom resources can now be submitted to and received from the API server in application/yaml format, consistent with other API resources. ([#58260](https://github.com/kubernetes/kubernetes/pull/58260), [@liggitt](https://github.com/liggitt)) -* remove spaces from kubectl describe hpa ([#56331](https://github.com/kubernetes/kubernetes/pull/56331), [@shiywang](https://github.com/shiywang)) -* fluentd-gcp updated to version 2.0.14. ([#58224](https://github.com/kubernetes/kubernetes/pull/58224), [@zombiezen](https://github.com/zombiezen)) -* Instrument the Azure cloud provider for Prometheus monitoring. ([#58204](https://github.com/kubernetes/kubernetes/pull/58204), [@cosmincojocar](https://github.com/cosmincojocar)) -* -Add scheduler optimization options, short circuit all predicates if … ([#56926](https://github.com/kubernetes/kubernetes/pull/56926), [@wgliang](https://github.com/wgliang)) -* Remove deprecated ContainerVM support from GCE kube-up. ([#58247](https://github.com/kubernetes/kubernetes/pull/58247), [@mikedanese](https://github.com/mikedanese)) -* Remove deprecated kube-push.sh functionality. ([#58246](https://github.com/kubernetes/kubernetes/pull/58246), [@mikedanese](https://github.com/mikedanese)) -* The getSubnetIDForLB() should return subnet id rather than net id. ([#58208](https://github.com/kubernetes/kubernetes/pull/58208), [@FengyunPan](https://github.com/FengyunPan)) -* Avoid panic when failing to allocate a Cloud CIDR (aka GCE Alias IP Range). ([#58186](https://github.com/kubernetes/kubernetes/pull/58186), [@negz](https://github.com/negz)) -* Handle Unhealthy devices ([#57266](https://github.com/kubernetes/kubernetes/pull/57266), [@vikaschoudhary16](https://github.com/vikaschoudhary16)) -* Expose Metrics Server metrics via /metric endpoint. ([#57456](https://github.com/kubernetes/kubernetes/pull/57456), [@kawych](https://github.com/kawych)) -* Remove deprecated container-linux support in gce kube-up.sh. ([#58098](https://github.com/kubernetes/kubernetes/pull/58098), [@mikedanese](https://github.com/mikedanese)) -* openstack cinder detach problem is fixed if nova is shutdowned ([#56846](https://github.com/kubernetes/kubernetes/pull/56846), [@zetaab](https://github.com/zetaab)) -* Fixes a possible deadlock preventing quota from being recalculated ([#58107](https://github.com/kubernetes/kubernetes/pull/58107), [@ironcladlou](https://github.com/ironcladlou)) -* fluentd-es addon: multiline stacktraces are now grouped into one entry automatically ([#58063](https://github.com/kubernetes/kubernetes/pull/58063), [@monotek](https://github.com/monotek)) -* GCE: Allows existing internal load balancers to continue using an outdated subnetwork ([#57861](https://github.com/kubernetes/kubernetes/pull/57861), [@nicksardo](https://github.com/nicksardo)) -* ignore images in used by running containers when GC ([#57020](https://github.com/kubernetes/kubernetes/pull/57020), [@dixudx](https://github.com/dixudx)) -* Remove deprecated and unmaintained photon-controller kube-up.sh. ([#58096](https://github.com/kubernetes/kubernetes/pull/58096), [@mikedanese](https://github.com/mikedanese)) -* The kubelet flag to run docker containers with a process namespace that is shared between all containers in a pod is now deprecated and will be replaced by a new field in `v1.Pod` that configures this behavior. ([#58093](https://github.com/kubernetes/kubernetes/pull/58093), [@verb](https://github.com/verb)) -* fix device name change issue for azure disk: add remount logic ([#57953](https://github.com/kubernetes/kubernetes/pull/57953), [@andyzhangx](https://github.com/andyzhangx)) -* The Kubelet now explicitly registers all of its command-line flags with an internal flagset, which prevents flags from third party libraries from unintentionally leaking into the Kubelet's command-line API. Many unintentionally leaked flags are now marked deprecated, so that users have a chance to migrate away from them before they are removed. One previously leaked flag, --cloud-provider-gce-lb-src-cidrs, was entirely removed from the Kubelet's command-line API, because it is irrelevant to Kubelet operation. ([#57613](https://github.com/kubernetes/kubernetes/pull/57613), [@mtaufen](https://github.com/mtaufen)) -* Remove deprecated and unmaintained libvirt-coreos kube-up.sh. ([#58023](https://github.com/kubernetes/kubernetes/pull/58023), [@mikedanese](https://github.com/mikedanese)) -* Remove deprecated and unmaintained windows installer. ([#58020](https://github.com/kubernetes/kubernetes/pull/58020), [@mikedanese](https://github.com/mikedanese)) -* Remove deprecated and unmaintained openstack-heat kube-up.sh. ([#58021](https://github.com/kubernetes/kubernetes/pull/58021), [@mikedanese](https://github.com/mikedanese)) -* Fixes authentication problem faced during various vSphere operations. ([#57978](https://github.com/kubernetes/kubernetes/pull/57978), [@prashima](https://github.com/prashima)) -* fluentd-gcp updated to version 2.0.13. ([#57789](https://github.com/kubernetes/kubernetes/pull/57789), [@x13n](https://github.com/x13n)) -* Add support for cloud-controller-manager in local-up-cluster.sh ([#57757](https://github.com/kubernetes/kubernetes/pull/57757), [@dims](https://github.com/dims)) -* Update CSI spec dependency to point to v0.1.0 tag ([#57989](https://github.com/kubernetes/kubernetes/pull/57989), [@NickrenREN](https://github.com/NickrenREN)) -* Update kube-dns to Version 1.14.8 that includes only small changes to how Prometheus metrics are collected. ([#57918](https://github.com/kubernetes/kubernetes/pull/57918), [@rramkumar1](https://github.com/rramkumar1)) -* Add proxy_read_timeout flag to kubeapi_load_balancer charm. ([#57926](https://github.com/kubernetes/kubernetes/pull/57926), [@wwwtyro](https://github.com/wwwtyro)) -* Adding support for Block Volume type to rbd plugin. ([#56651](https://github.com/kubernetes/kubernetes/pull/56651), [@sbezverk](https://github.com/sbezverk)) -* Fixes a bug in Heapster deployment for google sink. ([#57902](https://github.com/kubernetes/kubernetes/pull/57902), [@kawych](https://github.com/kawych)) -* Forbid unnamed contexts in kubeconfigs. ([#56769](https://github.com/kubernetes/kubernetes/pull/56769), [@dixudx](https://github.com/dixudx)) -* Upgrade to etcd client 3.2.13 and grpc 1.7.5 to improve HA etcd cluster stability. ([#57480](https://github.com/kubernetes/kubernetes/pull/57480), [@jpbetz](https://github.com/jpbetz)) -* Default scheduler code is moved out of the plugin directory. ([#57852](https://github.com/kubernetes/kubernetes/pull/57852), [@misterikkit](https://github.com/misterikkit)) - * plugin/pkg/scheduler -> pkg/scheduler - * plugin/cmd/kube-scheduler -> cmd/kube-scheduler -* Bump metadata proxy version to v0.1.7 to pick up security fix. ([#57762](https://github.com/kubernetes/kubernetes/pull/57762), [@ihmccreery](https://github.com/ihmccreery)) -* HugePages feature is beta ([#56939](https://github.com/kubernetes/kubernetes/pull/56939), [@derekwaynecarr](https://github.com/derekwaynecarr)) -* GCE: support passing kube-scheduler policy config via SCHEDULER_POLICY_CONFIG ([#57425](https://github.com/kubernetes/kubernetes/pull/57425), [@yguo0905](https://github.com/yguo0905)) -* Returns an error for non overcommitable resources if they don't have limit field set in container spec. ([#57170](https://github.com/kubernetes/kubernetes/pull/57170), [@jiayingz](https://github.com/jiayingz)) -* Update defaultbackend image to 1.4 and deployment apiVersion to apps/v1 ([#57866](https://github.com/kubernetes/kubernetes/pull/57866), [@zouyee](https://github.com/zouyee)) -* kubeadm: set kube-apiserver advertise address using downward API ([#56084](https://github.com/kubernetes/kubernetes/pull/56084), [@andrewsykim](https://github.com/andrewsykim)) -* CDK nginx ingress is now handled via a daemon set. ([#57530](https://github.com/kubernetes/kubernetes/pull/57530), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* The kubelet uses a new release 3.1 of the pause container with the Docker runtime. This version will clean up orphaned zombie processes that it inherits. ([#57517](https://github.com/kubernetes/kubernetes/pull/57517), [@verb](https://github.com/verb)) -* Allow kubectl set image|env on a cronjob ([#57742](https://github.com/kubernetes/kubernetes/pull/57742), [@soltysh](https://github.com/soltysh)) -* Move local PV negative scheduling tests to integration ([#57570](https://github.com/kubernetes/kubernetes/pull/57570), [@sbezverk](https://github.com/sbezverk)) -* fix azure disk not available issue when device name changed ([#57549](https://github.com/kubernetes/kubernetes/pull/57549), [@andyzhangx](https://github.com/andyzhangx)) -* Only create Privileged PSP binding during e2e tests if RBAC is enabled. ([#56382](https://github.com/kubernetes/kubernetes/pull/56382), [@mikkeloscar](https://github.com/mikkeloscar)) -* RBAC: The system:kubelet-api-admin cluster role can be used to grant full access to the kubelet API ([#57128](https://github.com/kubernetes/kubernetes/pull/57128), [@liggitt](https://github.com/liggitt)) -* Allow kubernetes components to react to SIGTERM signal and shutdown gracefully. ([#57756](https://github.com/kubernetes/kubernetes/pull/57756), [@mborsz](https://github.com/mborsz)) -* ignore nonexistent ns net file error when deleting container network in case a retry ([#57697](https://github.com/kubernetes/kubernetes/pull/57697), [@dixudx](https://github.com/dixudx)) -* check psp HostNetwork in DenyEscalatingExec admission controller. ([#56839](https://github.com/kubernetes/kubernetes/pull/56839), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) -* The alpha `--init-config-dir` flag has been removed. Instead, use the `--config` flag to reference a kubelet configuration file directly. ([#57624](https://github.com/kubernetes/kubernetes/pull/57624), [@mtaufen](https://github.com/mtaufen)) -* Add cache for VM get operation in azure cloud provider ([#57432](https://github.com/kubernetes/kubernetes/pull/57432), [@karataliu](https://github.com/karataliu)) -* Fix garbage collection when the controller-manager uses --leader-elect=false ([#57340](https://github.com/kubernetes/kubernetes/pull/57340), [@jmcmeek](https://github.com/jmcmeek)) -* iSCSI sessions managed by kubernetes will now explicitly set startup.mode to 'manual' to ([#57475](https://github.com/kubernetes/kubernetes/pull/57475), [@stmcginnis](https://github.com/stmcginnis)) - * prevent automatic login after node failure recovery. This is the default open-iscsi mode, so - * this change will only impact users who have changed their startup.mode to be 'automatic' - * in /etc/iscsi/iscsid.conf. -* Configurable liveness probe initial delays for etcd and kube-apiserver in GCE ([#57749](https://github.com/kubernetes/kubernetes/pull/57749), [@wojtek-t](https://github.com/wojtek-t)) -* Fixed garbage collection hang ([#57503](https://github.com/kubernetes/kubernetes/pull/57503), [@liggitt](https://github.com/liggitt)) -* Fixes controller manager crash in certain vSphere cloud provider environment. ([#57286](https://github.com/kubernetes/kubernetes/pull/57286), [@rohitjogvmw](https://github.com/rohitjogvmw)) -* Remove useInstanceMetadata parameter from Azure cloud provider. ([#57647](https://github.com/kubernetes/kubernetes/pull/57647), [@feiskyer](https://github.com/feiskyer)) -* Support multiple scale sets in Azure cloud provider. ([#57543](https://github.com/kubernetes/kubernetes/pull/57543), [@feiskyer](https://github.com/feiskyer)) -* GCE: Fixes ILB creation on automatic networks with manually created subnetworks. ([#57351](https://github.com/kubernetes/kubernetes/pull/57351), [@nicksardo](https://github.com/nicksardo)) -* Improve scheduler performance of MatchInterPodAffinity predicate. ([#57476](https://github.com/kubernetes/kubernetes/pull/57476), [@misterikkit](https://github.com/misterikkit)) -* Improve scheduler performance of MatchInterPodAffinity predicate. ([#57477](https://github.com/kubernetes/kubernetes/pull/57477), [@misterikkit](https://github.com/misterikkit)) -* Improve scheduler performance of MatchInterPodAffinity predicate. ([#57478](https://github.com/kubernetes/kubernetes/pull/57478), [@misterikkit](https://github.com/misterikkit)) -* Allow use resource ID to specify public IP address in azure_loadbalancer ([#53557](https://github.com/kubernetes/kubernetes/pull/53557), [@yolo3301](https://github.com/yolo3301)) -* Fixes a bug where if an error was returned that was not an `autorest.DetailedError` we would return `"not found", nil` which caused nodes to go to `NotReady` state. ([#57484](https://github.com/kubernetes/kubernetes/pull/57484), [@brendandburns](https://github.com/brendandburns)) -* Add the path '/version/' to the `system:discovery` cluster role. ([#57368](https://github.com/kubernetes/kubernetes/pull/57368), [@brendandburns](https://github.com/brendandburns)) -* Fixes issue creating docker secrets with kubectl 1.9 for accessing docker private registries. ([#57463](https://github.com/kubernetes/kubernetes/pull/57463), [@dims](https://github.com/dims)) -* adding predicates ordering for the kubernetes scheduler. ([#57168](https://github.com/kubernetes/kubernetes/pull/57168), [@yastij](https://github.com/yastij)) -* Free up CPU and memory requested but unused by Metrics Server Pod Nanny. ([#57252](https://github.com/kubernetes/kubernetes/pull/57252), [@kawych](https://github.com/kawych)) -* The alpha Accelerators feature gate is deprecated and will be removed in v1.11. Please use device plugins instead. They can be enabled using the DevicePlugins feature gate. ([#57384](https://github.com/kubernetes/kubernetes/pull/57384), [@mindprince](https://github.com/mindprince)) -* Fixed dynamic provisioning of GCE PDs to round to the next GB instead of GiB ([#56600](https://github.com/kubernetes/kubernetes/pull/56600), [@edisonxiang](https://github.com/edisonxiang)) -* Separate loop and plugin control ([#52371](https://github.com/kubernetes/kubernetes/pull/52371), [@cheftako](https://github.com/cheftako)) -* Use old dns-ip mechanism with older cdk-addons. ([#57403](https://github.com/kubernetes/kubernetes/pull/57403), [@wwwtyro](https://github.com/wwwtyro)) -* Retry 'connection refused' errors when setting up clusters on GCE. ([#57394](https://github.com/kubernetes/kubernetes/pull/57394), [@mborsz](https://github.com/mborsz)) -* Upgrade to etcd client 3.2.11 and grpc 1.7.5 to improve HA etcd cluster stability. ([#57160](https://github.com/kubernetes/kubernetes/pull/57160), [@jpbetz](https://github.com/jpbetz)) -* Added the ability to select pods in a chosen node to be drained, based on given pod label-selector ([#56864](https://github.com/kubernetes/kubernetes/pull/56864), [@juanvallejo](https://github.com/juanvallejo)) -* Wait for kubedns to be ready when collecting the cluster IP. ([#57337](https://github.com/kubernetes/kubernetes/pull/57337), [@wwwtyro](https://github.com/wwwtyro)) -* Use "k8s.gcr.io" for container images rather than "gcr.io/google_containers". This is just a redirect, for now, so should not impact anyone materially. ([#54174](https://github.com/kubernetes/kubernetes/pull/54174), [@thockin](https://github.com/thockin)) - * Documentation and tools should all convert to the new name. Users should take note of this in case they see this new name in the system. -* Fix ipvs proxier nodeport eth* assumption ([#56685](https://github.com/kubernetes/kubernetes/pull/56685), [@m1093782566](https://github.com/m1093782566)) - - - -# v1.10.0-alpha.1 - -[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/master/examples) - -## Downloads for v1.10.0-alpha.1 - - -filename | sha256 hash --------- | ----------- -[kubernetes.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes.tar.gz) | `403b90bfa32f7669b326045a629bd15941c533addcaf0c49d3c3c561da0542f2` -[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-src.tar.gz) | `266da065e9eddf19d36df5ad325f2f854101a0e712766148e87d998e789b80cf` - -### Client Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-darwin-386.tar.gz) | `5aaa8e294ae4060d34828239e37f37b45fa5a69508374be668965102848626be` -[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-darwin-amd64.tar.gz) | `40a8e3bab11b88a2bb8e748f0b29da806d89b55775508039abe9c38c5f4ab97d` -[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-linux-386.tar.gz) | `e08dde0b561529f0b2bb39c141f4d7b1c943749ef7c1f9779facf5fb5b385d6a` -[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-linux-amd64.tar.gz) | `76a05d31acaab932ef45c67e1d6c9273933b8bc06dd5ce9bad3c7345d5267702` -[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-linux-arm64.tar.gz) | `4b833c9e80f3e4ac4958ea0ffb5ae564b31d2a524f6a14e58802937b2b936d73` -[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-linux-arm.tar.gz) | `f1484ab75010a2258ed7717b1284d0c139d17e194ac9e391b8f1c0999eec3c2d` -[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-linux-ppc64le.tar.gz) | `da884f09ec753925b2c1f27ea0a1f6c3da2056855fc88f47929bb3d6c2a09312` -[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-linux-s390x.tar.gz) | `c486f760c6707fc92d1659d3cbe33d68c03190760b73ac215957ee52f9c19195` -[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-windows-386.tar.gz) | `514c550b7ff85ac33e6ed333bcc06461651fe4004d8b7c12ca67f5dc1d2198bf` -[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-client-windows-amd64.tar.gz) | `ddad59222f6a8cb4e88c4330c2a967c4126cb22ac5e0d7126f9f65cca0fb9f45` - -### Server Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-server-linux-amd64.tar.gz) | `514efd798ce1d7fe4233127f3334a3238faad6c26372a2d457eff02cbe72d756` -[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-server-linux-arm64.tar.gz) | `f71f75fb96221f65891fc3e04fd52ae4e5628da8b7b4fbedece3fab4cb650afa` -[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-server-linux-arm.tar.gz) | `a9d8c2386813fd690e60623a6ee1968fe8f0a1a8e13bc5cc12b2caf8e8a862e1` -[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-server-linux-ppc64le.tar.gz) | `21336a5e40aead4e2ec7e744a99d72bf8cb552341f3141abf8f235beb250cd93` -[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-server-linux-s390x.tar.gz) | `257e44d38fef83f08990b6b9b5e985118e867c0c33f0e869f0900397b9d30498` - -### Node Binaries - -filename | sha256 hash --------- | ----------- -[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-node-linux-amd64.tar.gz) | `97bf1210f0595ebf496ca7b000c4367f8a459d97ef72459efc6d0e07a072398f` -[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-node-linux-arm64.tar.gz) | `eebcd3c14fb4faeb82ab047a2152db528adc2d9f7b20eef6f5dc58202ebe3124` -[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-node-linux-arm.tar.gz) | `3d4428416c775a0a6463f623286bd2ecdf9240ce901e1fbae180dfb564c53ea1` -[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-node-linux-ppc64le.tar.gz) | `5cc96b24fad0ac1779a66f9b136d90e975b07bf619fea905e6c26ac5a4c41168` -[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-node-linux-s390x.tar.gz) | `134c13338edf4efcd511f4161742fbaa6dc232965d3d926c3de435e8a080fcbb` -[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.0-alpha.1/kubernetes-node-windows-amd64.tar.gz) | `ae54bf2bbcb99cdcde959140460d0f83c0ecb187d060b594ae9c5349960ab055` - -## Changelog since v1.9.0 - -### Action Required - -* [action required] Remove the kubelet's `--cloud-provider=auto-detect` feature ([#56287](https://github.com/kubernetes/kubernetes/pull/56287), [@stewart-yu](https://github.com/stewart-yu)) - -### Other notable changes - -* Fix Heapster configuration and Metrics Server configuration to enable overriding default resource requirements. ([#56965](https://github.com/kubernetes/kubernetes/pull/56965), [@kawych](https://github.com/kawych)) -* YAMLDecoder Read now returns the number of bytes read ([#57000](https://github.com/kubernetes/kubernetes/pull/57000), [@sel](https://github.com/sel)) -* Retry 'connection refused' errors when setting up clusters on GCE. ([#57324](https://github.com/kubernetes/kubernetes/pull/57324), [@mborsz](https://github.com/mborsz)) -* Update kubeadm's minimum supported Kubernetes version in v1.10.x to v1.9.0 ([#57233](https://github.com/kubernetes/kubernetes/pull/57233), [@xiangpengzhao](https://github.com/xiangpengzhao)) -* Graduate CPU Manager feature from alpha to beta. ([#55977](https://github.com/kubernetes/kubernetes/pull/55977), [@ConnorDoyle](https://github.com/ConnorDoyle)) -* Drop hacks used for Mesos integration that was already removed from main kubernetes repository ([#56754](https://github.com/kubernetes/kubernetes/pull/56754), [@dims](https://github.com/dims)) -* Compare correct file names for volume detach operation ([#57053](https://github.com/kubernetes/kubernetes/pull/57053), [@prashima](https://github.com/prashima)) -* Improved event generation in volume mount, attach, and extend operations ([#56872](https://github.com/kubernetes/kubernetes/pull/56872), [@davidz627](https://github.com/davidz627)) -* GCE: bump COS image version to cos-stable-63-10032-71-0 ([#57204](https://github.com/kubernetes/kubernetes/pull/57204), [@yujuhong](https://github.com/yujuhong)) -* fluentd-gcp updated to version 2.0.11. ([#56927](https://github.com/kubernetes/kubernetes/pull/56927), [@x13n](https://github.com/x13n)) -* calico-node addon tolerates all NoExecute and NoSchedule taints by default. ([#57122](https://github.com/kubernetes/kubernetes/pull/57122), [@caseydavenport](https://github.com/caseydavenport)) -* Support LoadBalancer for Azure Virtual Machine Scale Sets ([#57131](https://github.com/kubernetes/kubernetes/pull/57131), [@feiskyer](https://github.com/feiskyer)) -* Makes the kube-dns addon optional so that users can deploy their own DNS solution. ([#57113](https://github.com/kubernetes/kubernetes/pull/57113), [@wwwtyro](https://github.com/wwwtyro)) -* Enabled log rotation for load balancer's api logs to prevent running out of disk space. ([#56979](https://github.com/kubernetes/kubernetes/pull/56979), [@hyperbolic2346](https://github.com/hyperbolic2346)) -* Remove ScrubDNS interface from cloudprovider. ([#56955](https://github.com/kubernetes/kubernetes/pull/56955), [@feiskyer](https://github.com/feiskyer)) -* Fix `etcd-version-monitor` to backward compatibly support etcd 3.1 [go-grpc-prometheus](https://github.com/grpc-ecosystem/go-grpc-prometheus) metrics format. ([#56871](https://github.com/kubernetes/kubernetes/pull/56871), [@jpbetz](https://github.com/jpbetz)) -* enable flexvolume on Windows node ([#56921](https://github.com/kubernetes/kubernetes/pull/56921), [@andyzhangx](https://github.com/andyzhangx)) -* When using Role-Based Access Control, the "admin", "edit", and "view" roles now have the expected permissions on NetworkPolicy resources. ([#56650](https://github.com/kubernetes/kubernetes/pull/56650), [@danwinship](https://github.com/danwinship)) -* Fix the PersistentVolumeLabel controller from initializing the PV labels when it's not the next pending initializer. ([#56831](https://github.com/kubernetes/kubernetes/pull/56831), [@jhorwit2](https://github.com/jhorwit2)) -* kube-apiserver: The external hostname no longer use the cloud provider API to select a default. It can be set explicitly using --external-hostname, if needed. ([#56812](https://github.com/kubernetes/kubernetes/pull/56812), [@dims](https://github.com/dims)) -* Use GiB unit for creating and resizing volumes for Glusterfs ([#56581](https://github.com/kubernetes/kubernetes/pull/56581), [@gnufied](https://github.com/gnufied)) -* PersistentVolume flexVolume sources can now reference secrets in a namespace other than the PersistentVolumeClaim's namespace. ([#56460](https://github.com/kubernetes/kubernetes/pull/56460), [@liggitt](https://github.com/liggitt)) -* Scheduler skips pods that use a PVC that either does not exist or is being deleted. ([#55957](https://github.com/kubernetes/kubernetes/pull/55957), [@jsafrane](https://github.com/jsafrane)) -* Fixed a garbage collection race condition where objects with ownerRefs pointing to cluster-scoped objects could be deleted incorrectly. ([#57211](https://github.com/kubernetes/kubernetes/pull/57211), [@liggitt](https://github.com/liggitt)) -* Kubectl explain now prints out the Kind and API version of the resource being explained ([#55689](https://github.com/kubernetes/kubernetes/pull/55689), [@luksa](https://github.com/luksa)) -* api-server provides specific events when unable to repair a service cluster ip or node port ([#54304](https://github.com/kubernetes/kubernetes/pull/54304), [@frodenas](https://github.com/frodenas)) -* Added docker-logins config to kubernetes-worker charm ([#56217](https://github.com/kubernetes/kubernetes/pull/56217), [@Cynerva](https://github.com/Cynerva)) -* delete useless params containerized ([#56146](https://github.com/kubernetes/kubernetes/pull/56146), [@jiulongzaitian](https://github.com/jiulongzaitian)) -* add mount options support for azure disk ([#56147](https://github.com/kubernetes/kubernetes/pull/56147), [@andyzhangx](https://github.com/andyzhangx)) -* Use structured generator for kubectl autoscale ([#55913](https://github.com/kubernetes/kubernetes/pull/55913), [@wackxu](https://github.com/wackxu)) -* K8s supports cephfs fuse mount. ([#55866](https://github.com/kubernetes/kubernetes/pull/55866), [@zhangxiaoyu-zidif](https://github.com/zhangxiaoyu-zidif)) -* COS: Keep the docker network checkpoint ([#54805](https://github.com/kubernetes/kubernetes/pull/54805), [@yujuhong](https://github.com/yujuhong)) -* Fixed documentation typo in IPVS README. ([#56578](https://github.com/kubernetes/kubernetes/pull/56578), [@shift](https://github.com/shift)) - diff --git a/vendor/k8s.io/kubernetes/CHANGELOG-1.11.md b/vendor/k8s.io/kubernetes/CHANGELOG-1.11.md new file mode 100644 index 000000000..d28b0fb61 --- /dev/null +++ b/vendor/k8s.io/kubernetes/CHANGELOG-1.11.md @@ -0,0 +1,1925 @@ + +- [v1.11.2](#v1112) + - [Downloads for v1.11.2](#downloads-for-v1112) + - [Client Binaries](#client-binaries) + - [Server Binaries](#server-binaries) + - [Node Binaries](#node-binaries) + - [Changelog since v1.11.1](#changelog-since-v1111) + - [Action Required](#action-required) + - [Other notable changes](#other-notable-changes) +- [v1.11.1](#v1111) + - [Downloads for v1.11.1](#downloads-for-v1111) + - [Client Binaries](#client-binaries-1) + - [Server Binaries](#server-binaries-1) + - [Node Binaries](#node-binaries-1) + - [Changelog since v1.11.0](#changelog-since-v1110) + - [Action Required](#action-required-1) + - [Other notable changes](#other-notable-changes-1) +- [v1.11.0](#v1110) + - [Downloads for v1.11.0](#downloads-for-v1110) + - [Client Binaries](#client-binaries-2) + - [Server Binaries](#server-binaries-2) + - [Node Binaries](#node-binaries-2) +- [Kubernetes 1.11 Release Notes](#kubernetes-111-release-notes) + - [Urgent Upgrade Notes](#urgent-upgrade-notes) + - [(No, really, you MUST do this before you upgrade)](#no-really-you-must-do-this-before-you-upgrade) + - [Major Themes](#major-themes) + - [SIG API Machinery](#sig-api-machinery) + - [SIG Auth](#sig-auth) + - [SIG CLI](#sig-cli) + - [SIG Cluster Lifecycle](#sig-cluster-lifecycle) + - [SIG Instrumentation](#sig-instrumentation) + - [SIG Network](#sig-network) + - [SIG Node](#sig-node) + - [SIG OpenStack](#sig-openstack) + - [SIG Scheduling](#sig-scheduling) + - [SIG Storage](#sig-storage) + - [SIG Windows](#sig-windows) + - [Known Issues](#known-issues) + - [Before Upgrading](#before-upgrading) + - [New Deprecations](#new-deprecations) + - [Removed Deprecations](#removed-deprecations) + - [Graduated to Stable/GA](#graduated-to-stablega) + - [Graduated to Beta](#graduated-to-beta) + - [New alpha features](#new-alpha-features) + - [Other Notable Changes](#other-notable-changes-2) + - [SIG API Machinery](#sig-api-machinery-1) + - [SIG Apps](#sig-apps) + - [SIG Auth](#sig-auth-1) + - [SIG Autoscaling](#sig-autoscaling) + - [SIG Azure](#sig-azure) + - [SIG CLI](#sig-cli-1) + - [SIG Cluster Lifecycle](#sig-cluster-lifecycle-1) + - [SIG GCP](#sig-gcp) + - [SIG Instrumentation](#sig-instrumentation-1) + - [SIG Network](#sig-network-1) + - [SIG Node](#sig-node-1) + - [SIG OpenStack](#sig-openstack-1) + - [SIG Scheduling](#sig-scheduling-1) + - [SIG Storage](#sig-storage-1) + - [SIG vSphere](#sig-vsphere) + - [SIG Windows](#sig-windows-1) + - [Additional changes](#additional-changes) + - [External Dependencies](#external-dependencies) + - [Bug Fixes](#bug-fixes) + - [General Fixes and Reliability](#general-fixes-and-reliability) + - [Non-user-facing changes](#non-user-facing-changes) +- [v1.11.0-rc.3](#v1110-rc3) + - [Downloads for v1.11.0-rc.3](#downloads-for-v1110-rc3) + - [Client Binaries](#client-binaries-3) + - [Server Binaries](#server-binaries-3) + - [Node Binaries](#node-binaries-3) + - [Changelog since v1.11.0-rc.2](#changelog-since-v1110-rc2) + - [Other notable changes](#other-notable-changes-3) +- [v1.11.0-rc.2](#v1110-rc2) + - [Downloads for v1.11.0-rc.2](#downloads-for-v1110-rc2) + - [Client Binaries](#client-binaries-4) + - [Server Binaries](#server-binaries-4) + - [Node Binaries](#node-binaries-4) + - [Changelog since v1.11.0-rc.1](#changelog-since-v1110-rc1) + - [Other notable changes](#other-notable-changes-4) +- [v1.11.0-rc.1](#v1110-rc1) + - [Downloads for v1.11.0-rc.1](#downloads-for-v1110-rc1) + - [Client Binaries](#client-binaries-5) + - [Server Binaries](#server-binaries-5) + - [Node Binaries](#node-binaries-5) + - [Changelog since v1.11.0-beta.2](#changelog-since-v1110-beta2) + - [Action Required](#action-required-2) + - [Other notable changes](#other-notable-changes-5) +- [v1.11.0-beta.2](#v1110-beta2) + - [Downloads for v1.11.0-beta.2](#downloads-for-v1110-beta2) + - [Client Binaries](#client-binaries-6) + - [Server Binaries](#server-binaries-6) + - [Node Binaries](#node-binaries-6) + - [Changelog since v1.11.0-beta.1](#changelog-since-v1110-beta1) + - [Action Required](#action-required-3) + - [Other notable changes](#other-notable-changes-6) +- [v1.11.0-beta.1](#v1110-beta1) + - [Downloads for v1.11.0-beta.1](#downloads-for-v1110-beta1) + - [Client Binaries](#client-binaries-7) + - [Server Binaries](#server-binaries-7) + - [Node Binaries](#node-binaries-7) + - [Changelog since v1.11.0-alpha.2](#changelog-since-v1110-alpha2) + - [Action Required](#action-required-4) + - [Other notable changes](#other-notable-changes-7) +- [v1.11.0-alpha.2](#v1110-alpha2) + - [Downloads for v1.11.0-alpha.2](#downloads-for-v1110-alpha2) + - [Client Binaries](#client-binaries-8) + - [Server Binaries](#server-binaries-8) + - [Node Binaries](#node-binaries-8) + - [Changelog since v1.11.0-alpha.1](#changelog-since-v1110-alpha1) + - [Other notable changes](#other-notable-changes-8) +- [v1.11.0-alpha.1](#v1110-alpha1) + - [Downloads for v1.11.0-alpha.1](#downloads-for-v1110-alpha1) + - [Client Binaries](#client-binaries-9) + - [Server Binaries](#server-binaries-9) + - [Node Binaries](#node-binaries-9) + - [Changelog since v1.10.0](#changelog-since-v1100) + - [Action Required](#action-required-5) + - [Other notable changes](#other-notable-changes-9) + + + + + +# v1.11.2 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.2 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes.tar.gz) | `deaabdab00003ef97309cde188a61db8c2737721efeb75f7b19c6240863d9cbe` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-src.tar.gz) | `7d98defe2eb909bc5ebcbddd8d55ffaa902d5d3c76d9e42fe0a092c341016a6e` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-darwin-386.tar.gz) | `bee271bf7b251428fe5cf21fd586cc43dfd2c842932f4d9e0b1b549546dc7a2a` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-darwin-amd64.tar.gz) | `fc1d506c63b48997100aa6099b5d1b019dcd41bb962805f34273ada9a6b2252c` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-linux-386.tar.gz) | `bc7d637eff280bacf2059a487ca374169e63cf311808eb8e8b7504fc8a28a07d` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-linux-amd64.tar.gz) | `f7444a2200092ca6b4cd92408810ae88506fb7a27f762298fafb009b031250e3` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-linux-arm.tar.gz) | `d976e2ca975d5142364df996e4e9597817b65ab6bd0212bde807ec82f7345879` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-linux-arm64.tar.gz) | `7641599ee2d8743f861ff723cf54d3f01732f354729f4c8c101cad5ceeeb0e62` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-linux-ppc64le.tar.gz) | `ceea9bb4f218b3cd7346b44c56ffc7113540ceb1eb59e34df503b281722516a9` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-linux-s390x.tar.gz) | `e1b3ae15e84c8f911537c5e8af0d79d5187ded344fc3330e9d43f22dff3073bb` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-windows-386.tar.gz) | `5ea3c0aba710df3c95bb59621c8b220989ac45698b5268a75b17144d361d338c` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-client-windows-amd64.tar.gz) | `0499fe3b55fa6252c6c3611c3b22e8f65bf3d2aebcde7b847f7572a539ac9d70` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-server-linux-amd64.tar.gz) | `1323f4d58522e4480641948299f4804e09c20357682bc12d547f78a60c920836` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-server-linux-arm.tar.gz) | `a0d145a1794da4ae1018ad2b14c74e564be3c0c13514a3ed32c6177723d2e41f` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-server-linux-arm64.tar.gz) | `8f4419ec15470e450094b24299ecae21eb59fc8308009b5b726b98730f7e13a2` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-server-linux-ppc64le.tar.gz) | `e40aebbaa17976699125913fd6a7d8b66ab343e02c7da674bd4256d1de029950` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-server-linux-s390x.tar.gz) | `924d2b177e3646be59f6411b574d99e32ca74e5b7419e12e8642bc085d735560` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-node-linux-amd64.tar.gz) | `d254aa910a0dc47e587bec5a5fa8544c743835ba6d9ca5627d9d11a2df90c561` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-node-linux-arm.tar.gz) | `d1104c040efbdca831d5af584ad1482a2ade883af198aefef99ad1884794cefd` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-node-linux-arm64.tar.gz) | `c983f7e35aaee922865ab5d4d7893f168e026c3216dbc87658ce1bf6d8e67e06` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-node-linux-ppc64le.tar.gz) | `b8f784a4b142450bb990ab80a76950c8816e96e4b6e15134d0af5bd48f62c9f3` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-node-linux-s390x.tar.gz) | `b541c476b797f346b5ea68437904995c02d55e089433bdca6fd40531034fc838` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.2/kubernetes-node-windows-amd64.tar.gz) | `c3e91f4b30b801cc942bd0f160dc1afd01bebc3d2f11e69f373b1116409ffb44` + +## Changelog since v1.11.1 + +### Action Required + +* Cluster Autoscaler version updated to 1.3.1. Release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.3.1 ([#66123](https://github.com/kubernetes/kubernetes/pull/66123), [@aleksandra-malinowska](https://github.com/aleksandra-malinowska)) + * Default value for expendable pod priority cutoff in GCP deployment of Cluster Autoscaler changed from 0 to -10. + * action required: users deploying workloads with priority lower than 0 may want to use priority lower than -10 to avoid triggering scale-up. + +### Other notable changes + +* Metadata Agent Improvements ([#66485](https://github.com/kubernetes/kubernetes/pull/66485), [@bmoyles0117](https://github.com/bmoyles0117)) + * Bump metadata agent version to 0.2-0.0.21-1. + * Expand the metadata agent's access to all API groups. + * Remove metadata agent config maps in favor of command line flags. + * Update the metadata agent's liveness probe to a new /healthz handler. + * Logging Agent Improvements + * Bump logging agent version to 0.2-1.5.33-1-k8s-1. + * Appropriately set log severity for k8s_container. + * Fix detect exceptions plugin to analyze message field instead of log field. + * Fix detect exceptions plugin to analyze streams based on local resource id. + * Disable the metadata agent for monitored resource construction in logging. + * Disable timestamp adjustment in logs to optimize performance. + * Reduce logging agent buffer chunk limit to 512k to optimize performance. +* Fix a bug on GCE that /etc/crictl.yaml is not generated when crictl is preloaded. ([#66877](https://github.com/kubernetes/kubernetes/pull/66877), [@Random-Liu](https://github.com/Random-Liu)) +* Fix validation for HealthzBindAddress in kube-proxy when --healthz-port is set to 0 ([#66138](https://github.com/kubernetes/kubernetes/pull/66138), [@wsong](https://github.com/wsong)) +* fix acr could not be listed in sp issue ([#66429](https://github.com/kubernetes/kubernetes/pull/66429), [@andyzhangx](https://github.com/andyzhangx)) +* Fixed an issue which prevented `gcloud` from working on GCE when metadata concealment was enabled. ([#66630](https://github.com/kubernetes/kubernetes/pull/66630), [@dekkagaijin](https://github.com/dekkagaijin)) +* Fix for resourcepool-path configuration in the vsphere.conf file. ([#66261](https://github.com/kubernetes/kubernetes/pull/66261), [@divyenpatel](https://github.com/divyenpatel)) +* This fix prevents a GCE PD volume from being mounted if the udev device link is stale and tries to correct the link. ([#66832](https://github.com/kubernetes/kubernetes/pull/66832), [@msau42](https://github.com/msau42)) +* Fix kubelet startup failure when using ExecPlugin in kubeconfig ([#66395](https://github.com/kubernetes/kubernetes/pull/66395), [@awly](https://github.com/awly)) +* GCE: Fixes loadbalancer creation and deletion issues appearing in 1.10.5. ([#66400](https://github.com/kubernetes/kubernetes/pull/66400), [@nicksardo](https://github.com/nicksardo)) +* kubeadm: Pull sidecar and dnsmasq-nanny images when using kube-dns ([#66499](https://github.com/kubernetes/kubernetes/pull/66499), [@rosti](https://github.com/rosti)) +* fix smb mount issue ([#65751](https://github.com/kubernetes/kubernetes/pull/65751), [@andyzhangx](https://github.com/andyzhangx)) +* Extend TLS timeouts to work around slow arm64 math/big ([#66264](https://github.com/kubernetes/kubernetes/pull/66264), [@joejulian](https://github.com/joejulian)) +* Allow ScaleIO volumes to be provisioned without having to first manually create /dev/disk/by-id path on each kubernetes node (if not already present) ([#66174](https://github.com/kubernetes/kubernetes/pull/66174), [@ddebroy](https://github.com/ddebroy)) +* kubeadm: stop setting UID in the kubelet ConfigMap ([#66341](https://github.com/kubernetes/kubernetes/pull/66341), [@runiq](https://github.com/runiq)) +* fixes a panic when using a mutating webhook admission plugin with a DELETE operation ([#66425](https://github.com/kubernetes/kubernetes/pull/66425), [@liggitt](https://github.com/liggitt)) +* Update crictl to v1.11.1. ([#66152](https://github.com/kubernetes/kubernetes/pull/66152), [@Random-Liu](https://github.com/Random-Liu)) +* kubectl: fixes a panic displaying pods with nominatedNodeName set ([#66406](https://github.com/kubernetes/kubernetes/pull/66406), [@liggitt](https://github.com/liggitt)) +* fixes a validation error that could prevent updates to StatefulSet objects containing non-normalized resource requests ([#66165](https://github.com/kubernetes/kubernetes/pull/66165), [@liggitt](https://github.com/liggitt)) +* Tolerate missing watch permission when deleting a resource ([#65370](https://github.com/kubernetes/kubernetes/pull/65370), [@deads2k](https://github.com/deads2k)) +* prevents infinite CLI wait on delete when item is recreated ([#66136](https://github.com/kubernetes/kubernetes/pull/66136), [@deads2k](https://github.com/deads2k)) +* Preserve vmUUID when renewing nodeinfo in vSphere cloud provider ([#66007](https://github.com/kubernetes/kubernetes/pull/66007), [@w-leads](https://github.com/w-leads)) + + + +# v1.11.1 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.1 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes.tar.gz) | `77d93c4ab10b1c4421835ebf3c81dc9c6d2a798949ee9132418e24d500c22d6e` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-src.tar.gz) | `e597a3a73f4c4933e9fb145d398adfc4e245e4465bbea50b0e55c78d2b0e70ef` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-darwin-386.tar.gz) | `d668a91a52ad9c0a95a94172f89b42b42ca8f9eafe4ac479a97fe2e11f5dbd8e` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-darwin-amd64.tar.gz) | `5d6ce0f956b789840baf207b6d2bb252a4f8f0eaf6981207eb7df25e39871452` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-linux-386.tar.gz) | `1e47c66db3b7a194327f1d3082b657140d4cfee09eb03162a658d0604c31028e` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-linux-amd64.tar.gz) | `a6c7537434fedde75fb77c593b2d2978be1aed00896a354120c5b7164e54aa99` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-linux-arm.tar.gz) | `6eed4c3f11eb844947344e283482eeeb38a4b59eb8e24174fb706e997945ce12` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-linux-arm64.tar.gz) | `c260ee179420ce396ab972ab1252a26431c50b5412de2466ede1fb506d5587af` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-linux-ppc64le.tar.gz) | `01ec89ebbeb2b673504bb629e6a20793c31e29fc9b96100796533c391f3b13f2` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-linux-s390x.tar.gz) | `28b171b63d5c49d0d64006d331daba0ef6e9e841d69c3588bb3502eb122ef76a` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-windows-386.tar.gz) | `9ee394cadd909a937aef5c82c3499ae12da226ccbaa21f6d82c4878b7cb31d6c` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-client-windows-amd64.tar.gz) | `ab2c21e627a2fab52193ad7af0aabc001520975aac35660dc5f857320176e6c4` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-server-linux-amd64.tar.gz) | `f120baa4b37323a8d7cd6e8027f7b19a544f528d2cae4028366ffbb28dc68d8a` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-server-linux-arm.tar.gz) | `eac27b81cf2819619fdda54a83f06aecf77aefef1f2f2accd7adcc725cb607ff` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-server-linux-arm64.tar.gz) | `25d87248f0da9ba71a4e6c5d1b7af2259ffd43435715d52db6044ebe85466fad` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-server-linux-ppc64le.tar.gz) | `7eba9021f93b6f99167cd088933aabbf11d5a6f990d796fc1b884ed97e066a3b` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-server-linux-s390x.tar.gz) | `144fa932ab4bea9e810958dd859fdf9b11a9f90918c22b2c9322b6c21b5c82ed` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-node-linux-amd64.tar.gz) | `45fae35f7c3b23ff8557dcf638eb631dabbcc46a804534ca9d1043d846ec4408` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-node-linux-arm.tar.gz) | `19c29a635807979a87dcac610f79373df8ee90de823cf095362dcca086844831` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-node-linux-arm64.tar.gz) | `35b9a5fa8671c46b9c175a4920dce269fccf84b1defdbccb24e76c4eab9fb255` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-node-linux-ppc64le.tar.gz) | `b4a111ee652b42c9d92288d4d86f4897af524537b9409b1f5cedefb4122bb2d6` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-node-linux-s390x.tar.gz) | `4730b9d81cdde078c17c0831b1b20eeda65f4df37e0f595accc63bd2c1635bae` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.1/kubernetes-node-windows-amd64.tar.gz) | `d7fdf0341efe3d6a80a295aae19874a4099644c7ddba5fa34bee3a6924e0840b` + +## Changelog since v1.11.0 + +### Action Required + +* ACTION REQUIRED: Removes defaulting of CSI file system type to ext4. All the production drivers listed under https://kubernetes-csi.github.io/docs/Drivers.html were inspected and should not be impacted after this change. If you are using a driver not in that list, please test the drivers on an updated test cluster first. ``` ([#65499](https://github.com/kubernetes/kubernetes/pull/65499), [@krunaljain](https://github.com/krunaljain)) +* kube-apiserver: the `Priority` admission plugin is now enabled by default when using `--enable-admission-plugins`. If using `--admission-control` to fully specify the set of admission plugins, the `Priority` admission plugin should be added if using the `PodPriority` feature, which is enabled by default in 1.11. ([#65739](https://github.com/kubernetes/kubernetes/pull/65739), [@liggitt](https://github.com/liggitt)) +* The `system-node-critical` and `system-cluster-critical` priority classes are now limited to the `kube-system` namespace by the `PodPriority` admission plugin. ([#65593](https://github.com/kubernetes/kubernetes/pull/65593), [@bsalamat](https://github.com/bsalamat)) + +### Other notable changes + +* kubeadm: run kube-proxy on non-master tainted nodes ([#65931](https://github.com/kubernetes/kubernetes/pull/65931), [@neolit123](https://github.com/neolit123)) +* Fix an issue with dropped audit logs, when truncating and batch backends enabled at the same time. ([#65823](https://github.com/kubernetes/kubernetes/pull/65823), [@loburm](https://github.com/loburm)) +* set EnableHTTPSTrafficOnly in azure storage account creation ([#64957](https://github.com/kubernetes/kubernetes/pull/64957), [@andyzhangx](https://github.com/andyzhangx)) +* Re-adds `pkg/generated/bindata.go` to the repository to allow some parts of k8s.io/kubernetes to be go-vendorable. ([#65985](https://github.com/kubernetes/kubernetes/pull/65985), [@ixdy](https://github.com/ixdy)) +* Fix a scalability issue where high rates of event writes degraded etcd performance. ([#64539](https://github.com/kubernetes/kubernetes/pull/64539), [@ccding](https://github.com/ccding)) +* "kubectl delete" no longer waits for dependent objects to be deleted when removing parent resources ([#65908](https://github.com/kubernetes/kubernetes/pull/65908), [@juanvallejo](https://github.com/juanvallejo)) +* Update to use go1.10.3 ([#65726](https://github.com/kubernetes/kubernetes/pull/65726), [@ixdy](https://github.com/ixdy)) +* Fix the bug where image garbage collection is disabled by mistake. ([#66051](https://github.com/kubernetes/kubernetes/pull/66051), [@jiaxuanzhou](https://github.com/jiaxuanzhou)) +* Fix `RunAsGroup` which doesn't work since 1.10. ([#65926](https://github.com/kubernetes/kubernetes/pull/65926), [@Random-Liu](https://github.com/Random-Liu)) +* Fixed cleanup of CSI metadata files. ([#65323](https://github.com/kubernetes/kubernetes/pull/65323), [@jsafrane](https://github.com/jsafrane)) +* Reload systemd config files before starting kubelet. ([#65702](https://github.com/kubernetes/kubernetes/pull/65702), [@mborsz](https://github.com/mborsz)) +* Fix a bug that preempting a pod may block forever. ([#65987](https://github.com/kubernetes/kubernetes/pull/65987), [@Random-Liu](https://github.com/Random-Liu)) +* fixes a regression in kubectl printing behavior when using go-template or jsonpath output that resulted in a "unable to match a printer" error message ([#65979](https://github.com/kubernetes/kubernetes/pull/65979), [@juanvallejo](https://github.com/juanvallejo)) +* add external resource group support for azure disk ([#64427](https://github.com/kubernetes/kubernetes/pull/64427), [@andyzhangx](https://github.com/andyzhangx)) +* Properly manage security groups for loadbalancer services on OpenStack. ([#65373](https://github.com/kubernetes/kubernetes/pull/65373), [@multi-io](https://github.com/multi-io)) +* Allow access to ClusterIP from the host network namespace when kube-proxy is started in IPVS mode without either masqueradeAll or clusterCIDR flags ([#65388](https://github.com/kubernetes/kubernetes/pull/65388), [@lbernail](https://github.com/lbernail)) +* kubeadm: Fix pause image to not use architecture, as it is a manifest list ([#65920](https://github.com/kubernetes/kubernetes/pull/65920), [@dims](https://github.com/dims)) +* bazel deb package bugfix: The kubeadm deb package now reloads the kubelet after installation ([#65554](https://github.com/kubernetes/kubernetes/pull/65554), [@rdodev](https://github.com/rdodev)) +* The garbage collector now supports CustomResourceDefinitions and APIServices. ([#65915](https://github.com/kubernetes/kubernetes/pull/65915), [@nikhita](https://github.com/nikhita)) +* fix azure storage account creation failure ([#65846](https://github.com/kubernetes/kubernetes/pull/65846), [@andyzhangx](https://github.com/andyzhangx)) +* skip nodes that have a primary NIC in a 'Failed' provisioningState ([#65412](https://github.com/kubernetes/kubernetes/pull/65412), [@yastij](https://github.com/yastij)) +* Fix 'kubectl cp' with no arguments causes a panic ([#65482](https://github.com/kubernetes/kubernetes/pull/65482), [@wgliang](https://github.com/wgliang)) +* On COS, NPD creates a node condition for frequent occurrences of unregister_netdevice ([#65342](https://github.com/kubernetes/kubernetes/pull/65342), [@dashpole](https://github.com/dashpole)) +* bugfix: Do not print feature gates in the generic apiserver code for glog level 0 ([#65584](https://github.com/kubernetes/kubernetes/pull/65584), [@neolit123](https://github.com/neolit123)) +* Add prometheus scrape port to CoreDNS service ([#65589](https://github.com/kubernetes/kubernetes/pull/65589), [@rajansandeep](https://github.com/rajansandeep)) +* kubectl: fixes a regression with --use-openapi-print-columns that would not print object contents ([#65600](https://github.com/kubernetes/kubernetes/pull/65600), [@liggitt](https://github.com/liggitt)) +* fixes an out of range panic in the NoExecuteTaintManager controller when running a non-64-bit build ([#65596](https://github.com/kubernetes/kubernetes/pull/65596), [@liggitt](https://github.com/liggitt)) +* Fixed issue 63608, which is that under rare circumstances the ResourceQuota admission controller could lose track of an request in progress and time out after waiting 10 seconds for a decision to be made. ([#64598](https://github.com/kubernetes/kubernetes/pull/64598), [@MikeSpreitzer](https://github.com/MikeSpreitzer)) + + + +# v1.11.0 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.0 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes.tar.gz) | `3c779492574a5d8ce702d89915184f5dd52280da909abf134232e5ab00b4a885` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-src.tar.gz) | `f0b2d8e61860acaf50a9bae0dc36b8bfdb4bb41b8d0a1bb5a9bc3d87aad3b794` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-darwin-386.tar.gz) | `196738ef058510438b3129f0a72544544b7d52a8732948b4f9358781f87dab59` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-darwin-amd64.tar.gz) | `9ec8357b10b79f8fd87f3a836879d0a4bb46fb70adbb82f1e34dc7e91d74999f` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-linux-386.tar.gz) | `e8ee8a965d3ea241d9768b9ac868ecbbee112ef45038ff219e4006fa7f4ab4e2` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-linux-amd64.tar.gz) | `d31377c92b4cc9b3da086bc1974cbf57b0d2c2b22ae789ba84cf1b7554ea7067` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-linux-arm.tar.gz) | `9e9da909293a4682a5d6270a39894b056b3e901532b15eb8fdc0814a8d628d65` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-linux-arm64.tar.gz) | `149df9daac3e596042f5759977f9f9299a397130d9dddc2d4a2b513dd64f1092` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-linux-ppc64le.tar.gz) | `ff3d3e4714406d92e9a2b7ef2887519800b89f6592a756524f7a37dc48057f44` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-linux-s390x.tar.gz) | `e5a39bdc1e474d9d00974a81101e043aaff37c30c1418fb85a0c2561465e14c7` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-windows-386.tar.gz) | `4ba1102a33c6d4df650c4864a118f99a9882021fea6f250a35f4b4f4a2d68eaa` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-client-windows-amd64.tar.gz) | `0bb74af7358f9a2f4139ed1c10716a2f5f0c1c13ab3af71a0621a1983233c8d7` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-server-linux-amd64.tar.gz) | `b8a8a88afd8a40871749b2362dbb21295c6a9c0a85b6fc87e7febea1688eb99e` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-server-linux-arm.tar.gz) | `88b9168013bb07a7e17ddc0638e7d36bcd2984d049a50a96f54cb4218647d8da` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-server-linux-arm64.tar.gz) | `12fab9e9f0e032f278c0e114c72ea01899a0430fc772401f23e26de306e0f59f` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-server-linux-ppc64le.tar.gz) | `6616d726a651e733cfd4cccd78bfdc1d421c4a446edf4b617b8fd8f5e21f073e` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-server-linux-s390x.tar.gz) | `291838980929c8073ac592219d9576c84a9bdf233585966c81a380c3d753316e` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-node-linux-amd64.tar.gz) | `b23e905efb828fdffc4efc208f7343236b22c964e408fe889f529502aed4a335` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-node-linux-arm.tar.gz) | `44bf8973581887a2edd33eb637407e76dc0dc3a5abcc2ff04aec8338b533156d` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-node-linux-arm64.tar.gz) | `51e481c782233b46ee21e9635c7d8c2a84450cbe30d7b1cbe5c5982b33f40b13` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-node-linux-ppc64le.tar.gz) | `d1a3feda31a954d3a83193a51a117873b6ef9f8acc3e10b3f1504fece91f2eb8` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-node-linux-s390x.tar.gz) | `0ad76c6e6aef670c215256803b3b0d19f4730a0843429951c6421564c73d4932` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0/kubernetes-node-windows-amd64.tar.gz) | `8ad26200ed40d40a1b78d7a5dbe56220f0813d31194f40f267b476499fe2c5c3` + +# Kubernetes 1.11 Release Notes + +## Urgent Upgrade Notes +### (No, really, you MUST do this before you upgrade) + +Before upgrading to Kubernetes 1.11, you must keep the following in mind: + +* **JSON configuration files that contain fields with incorrect case will no longer be valid. You must correct these files before upgrading.** When specifying keys in JSON resource definitions during direct API server communication, the keys are case-sensitive. A bug introduced in Kubernetes 1.8 caused the API server to accept a request with incorrect case and coerce it to correct case, but this behaviour has been fixed in 1.11 and the API server will once again be enforcing the correct case. It’s worth noting that during this time, the `kubectl` tool continued to enforce case-sensitive keys, so users that strictly manage resources with `kubectl` will be unaffected by this change. ([#65034](https://github.com/kubernetes/kubernetes/pull/65034), [@caesarxuchao](https://github.com/caesarxuchao)) +* **[Pod priority and preemption](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/) is now enabled by default.** Note that this means that pods from *any* namespace can now request priority classes that compete with and/or cause preemption of critical system pods that are already running. If that is not desired, disable the PodPriority feature by setting `--feature-gates=PodPriority=false` on the kube-apiserver, kube-scheduler, and kubelet components before upgrading to 1.11. Disabling the PodPriority feature limits [critical pods](https://kubernetes.io/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/#marking-pod-as-critical-when-priorites-are-enabled) to the `kube-system` namespace. + +## Major Themes + +### SIG API Machinery + +This release SIG API Machinery focused mainly on CustomResources. For example, subresources for CustomResources are now beta and enabled by default. With this, updates to the `/status` subresource will disallow updates to all fields other than `.status` (not just `.spec` and `.metadata` as before). Also, `required` and `description` can be used at the root of the CRD OpenAPI validation schema when the `/status` subresource is enabled. + +In addition, users can now create multiple versions of CustomResourceDefinitions, but without any kind of automatic conversion, and CustomResourceDefinitions now allow specification of additional columns for `kubectl get` output via the `spec.additionalPrinterColumns` field. + +### SIG Auth + +Work this cycle focused on graduating existing functions, and on making security functions more understandable for users. + +RBAC [cluster role aggregation](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles), introduced in 1.9, graduated to stable status with no changes in 1.11, and [client-go credential plugins](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins) graduated to beta status, while also adding support for obtaining TLS credentials from an external plugin. + +Kubernetes 1.11 also makes it easier to see what's happening, as audit events can now be annotated with information about how an API request was handled: + * Authorization sets `authorization.k8s.io/decision` and `authorization.k8s.io/reason` annotations with the authorization decision ("allow" or "forbid") and a human-readable description of why the decision was made (for example, RBAC includes the name of the role/binding/subject which allowed a request). + * PodSecurityPolicy admission sets `podsecuritypolicy.admission.k8s.io/admit-policy` and `podsecuritypolicy.admission.k8s.io/validate-policy` annotations containing the name of the policy that allowed a pod to be admitted. (PodSecurityPolicy also gained the ability to [limit hostPath volume mounts to be read-only](https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems).) + +In addition, the NodeRestriction admission plugin now prevents kubelets from modifying taints on their Node API objects, making it easier to keep track of which nodes should be in use. + +### SIG CLI + +SIG CLI's main focus this release was on refactoring `kubectl` internals to improve composability, readability and testability of `kubectl` commands. Those refactors will allow the team to extract a mechanism for extensibility of kubectl -- that is, plugins -- in the next releases. + +### SIG Cluster Lifecycle + +SIG Cluster Lifecycle focused on improving kubeadm’s user experience by including a set of new commands related to maintaining the kubeadm configuration file, the API version of which has now has been incremented to `v1alpha2`. These commands can handle the migration of the configuration to a newer version, printing the default configuration, and listing and pulling the required container images for bootstrapping a cluster. + +Other notable changes include: +* CoreDNS replaces kube-dns as the default DNS provider +* Improved user experience for environments without a public internet connection and users using other CRI runtimes than Docker +* Support for structured configuration for the kubelet, which avoids the need to modify the systemd drop-in file +* Many improvements to the upgrade process and other bug fixes + +### SIG Instrumentation + +As far as Sig Instrumentation, the major change in Kubernetes 1.11 is the deprecation of Heapster as part of ongoing efforts to move to the new Kubernetes monitoring model. Clusters still using Heapster for autoscaling should be migrated over to metrics-server and the custom metrics API. See the deprecation section for more information. + +### SIG Network + +The main milestones for SIG Network this release are the graduation of IPVS-based load balancing and CoreDNS to general availability. + +IPVS is an alternative approach to in-cluster load balancing that uses in-kernel hash tables rather than the previous iptables approach, while CoreDNS is a replacement for kube-dns for service discovery. + +### SIG Node + +SIG-Node advanced several features and made incremental improvements in a few key topic areas this release. + +The dynamic kubelet config feature graduated to beta, so it is enabled by default, simplifying management of the node object itself. Kubelets that are configured to work with the CRI may take advantage of the log rotation feature, which is graduating to beta this release. + +The cri-tools project, which aims to provide consistent tooling for operators to debug and introspect their nodes in production independent of their chosen container runtime, graduated to GA. + +As far as platforms, working with SIG-Windows, enhancements were made to the kubelet to improve platform support on Windows operating systems, and improvements to resource management were also made. In particular, support for sysctls on Linux graduated to beta. + +### SIG OpenStack + +SIG-OpenStack continued to build out testing, with eleven acceptance tests covering a wide-range of scenarios and use-cases. During the 1.11 cycle our reporting back to test-grid has qualified the OpenStack cloud provider as a gating job for the Kubernetes release. + +New features include improved integration between the Keystone service and Kubernetes RBAC, and a number of stability and compatibility improvements across the entire provider code-base. + +### SIG Scheduling +[Pod Priority and Preemption](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/) has graduated to Beta, so it is enabled by default. Note that this involves [significant and important changes for operators](https://github.com/kubernetes/sig-release/pull/201/files). The team also worked on improved performance and reliability of the scheduler. + +### SIG Storage + +Sig Storage graduated two features that had been introduced in previous versions and introduced three new features in an alpha state. + +The StorageProtection feature, which prevents deletion of PVCs while Pods are still using them and of PVs while still bound to a PVC, is now generally available, and volume resizing, which lets you increase size of a volume after a Pod restarts is now beta, which means it is on by default. + +New alpha features include: +* Online volume resizing will increase the filesystem size of a resized volume without requiring a Pod restart. +* AWS EBS and GCE PD volumes support increased limits on the maximum number of attached volumes per node. +* Subpath volume directories can be created using DownwardAPI environment variables. + +### SIG Windows + +This release supports more of Kubernetes API for pods and containers on Windows, including: + +* Metrics for Pod, Container, Log filesystem +* The run_as_user security contexts +* Local persistent volumes and fstype for Azure disk + +Improvements in Windows Server version 1803 also bring new storage functionality to Kubernetes v1.11, including: + +* Volume mounts for ConfigMap and Secret +* Flexvolume plugins for SMB and iSCSI storage are also available out-of-tree at [Microsoft/K8s-Storage-Plugins](https://github.com/Microsoft/K8s-Storage-Plugins) + +## Known Issues + +* IPVS based kube-proxy doesn't support graceful close connections for terminating pod. This issue will be fixed in a future release. ([#57841](https://github.com/kubernetes/kubernetes/pull/57841), [@jsravn](https://github.com/jsravn)) +* kube-proxy needs to be configured to override hostname in some environments. ([#857](https://github.com/kubernetes/kubeadm/issues/857), [@detiber](https://github.com/detiber)) +* There's a known issue where the Vertical Pod Autoscaler will radically change implementation in 1.12, so users of VPA (alpha) in 1.11 are warned that they will not be able to automatically migrate their VPA configs from 1.11 to 1.12. + + +## Before Upgrading + +* When Response is a `metav1.Status`, it is no longer copied into the audit.Event status. Only the "status", "reason" and "code" fields are set. For example, when we run `kubectl get pods abc`, the API Server returns a status object: +```{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"pods \"abc\" not found","reason":"NotFound","details":{"name":"abc","kind":"pods"},"code":404}``` +In previous versions, the whole object was logged in audit events. Starting in 1.11, only `status`, `reason`, and `code` are logged. Code that relies on the older version must be updated to avoid errors. +([#62695](https://github.com/kubernetes/kubernetes/pull/62695), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* HTTP transport now uses `context.Context` to cancel dial operations. k8s.io/client-go/transport/Config struct has been updated to accept a function with a `context.Context` parameter. This is a breaking change if you use this field in your code. ([#60012](https://github.com/kubernetes/kubernetes/pull/60012), [@ash2k](https://github.com/ash2k)) +* kubectl: This client version requires the `apps/v1` APIs, so it will not work against a cluster version older than v1.9.0. Note that kubectl only guarantees compatibility with clusters that are +/-1 minor version away. ([#61419](https://github.com/kubernetes/kubernetes/pull/61419), [@enisoc](https://github.com/enisoc)) +* Pod priority and preemption is now enabled by default. Even if you don't plan to use this feature, you might need to take some action immediately after upgrading. In multi-tenant clusters where not all users are trusted, you are advised to create appropriate quotas for two default priority classes, system-cluster-critical and system-node-critical, which are added to clusters by default. `ResourceQuota` should be created to limit users from creating Pods at these priorities if not all users of your cluster are trusted. We do not advise disabling this feature because critical system Pods rely on the scheduler preemption to be scheduled when cluster is under resource pressure. +* Default mount propagation has changed from `HostToContainer` ("rslave" in Linux terminology), as it was in 1.10, to `None` ("private") to match the behavior in 1.9 and earlier releases; `HostToContainer` as a default caused regressions in some pods. If you are relying on this behavior you will need to set it explicitly. ([#62462](https://github.com/kubernetes/kubernetes/pull/62462), [@jsafrane](https://github.com/jsafrane)) +* The kube-apiserver `--storage-version` flag has been removed; you must use `--storage-versions` instead. ([#61453](https://github.com/kubernetes/kubernetes/pull/61453), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* Authors of aggregated API servers must not rely on authorization being done by the kube-apiserver, and must do delegated authorization in addition. ([#61349](https://github.com/kubernetes/kubernetes/pull/61349), [@sttts](https://github.com/sttts)) +* GC is now bound by QPS so if you need more QPS to avoid ratelimiting GC, you'll have to set it explicitly. ([#63657](https://github.com/kubernetes/kubernetes/pull/63657), [@shyamjvs](https://github.com/shyamjvs)) +* `kubeadm join` is now blocking on the kubelet performing the TLS Bootstrap properly. Earlier, `kubeadm join` only did the discovery part and exited successfully without checking that the kubelet actually started properly and performed the TLS bootstrap correctly. Now, as kubeadm runs some post-join steps (for example, annotating the Node API object with the CRISocket), `kubeadm join` is now waiting for the kubelet to perform the TLS Bootstrap, and then uses that credential to perform further actions. This also improves the UX, as `kubeadm` will exit with a non-zero code if the kubelet isn't in a functional state, instead of pretending everything's fine. + ([#64792](https://github.com/kubernetes/kubernetes/pull/64792), [@luxas](https://github.com/luxas)) +* The structure of the kubelet dropin in the kubeadm deb package has changed significantly. Instead of hard-coding the parameters for the kubelet in the dropin, a structured configuration file for the kubelet is used, and is expected to be present in `/var/lib/kubelet/config.yaml`. For runtime-detected, instance-specific configuration values, a environment file with dynamically-generated flags at `kubeadm init` or `kubeadm join` run time is used. Finally, if you want to override something specific for the kubelet that can't be done via the kubeadm Configuration file (which is preferred), you might add flags to the `KUBELET_EXTRA_ARGS` environment variable in either `/etc/default/kubelet` +or `/etc/sysconfig/kubelet`, depending on the system you're running on. +([#64780](https://github.com/kubernetes/kubernetes/pull/64780), [@luxas](https://github.com/luxas)) +* The `--node-name` flag for kubeadm now dictates the Node API object name the kubelet uses for registration, in all cases but where you might use an in-tree cloud provider. If you're not using an in-tree cloud provider, `--node-name` will set the Node API object name. If you're using an in-tree cloud provider, you MUST make `--node-name` match the name the in-tree cloud provider decides to use. +([#64706](https://github.com/kubernetes/kubernetes/pull/64706), [@liztio](https://github.com/liztio)) +* The `PersistentVolumeLabel` admission controller is now disabled by default. If you depend on this feature (AWS/GCE) then ensure it is added to the `--enable-admission-plugins` flag on the kube-apiserver. ([#64326](https://github.com/kubernetes/kubernetes/pull/64326), [@andrewsykim](https://github.com/andrewsykim)) +* kubeadm: kubelets in kubeadm clusters now disable the readonly port (10255). If you're relying on unauthenticated access to the readonly port, please switch to using the secure port (10250). Instead, you can now use ServiceAccount tokens when talking to the secure port, which will make it easier to get access to, for example, the `/metrics` endpoint of the kubelet, securely. ([#64187](https://github.com/kubernetes/kubernetes/pull/64187), [@luxas](https://github.com/luxas)) +* The formerly publicly-available cAdvisor web UI that the kubelet ran on port 4194 by default is now turned off by default. The flag configuring what port to run this UI on `--cadvisor-port` was deprecated in v1.10. Now the default is `--cadvisor-port=0`, in other words, to not run the web server. If you still need to run cAdvisor, the recommended way to run it is via a DaemonSet. Note that the `--cadvisor-port` will be removed in v1.12 ([#63881](https://github.com/kubernetes/kubernetes/pull/63881), [@luxas](https://github.com/luxas)) + +#### New Deprecations + +* As a reminder, etcd2 as a backend is deprecated and support will be removed in Kubernetes 1.13. Please ensure that your clusters are upgraded to etcd3 as soon as possible. +* InfluxDB cluster monitoring has been deprecated as part of the deprecation of Heapster. Instead, you may use the [metrics server](https://github.com/kubernetes-incubator/metrics-server). It's a simplified heapster that is able to gather and serve current metrics values. It provides the Metrics API that is used by `kubectl top`, and horizontal pod autoscaler. Note that it doesn't include some features of Heapster, such as short term metrics for graphs in kube-dashboard and dedicated push sinks, which proved hard to maintain and scale. Clusters using Heapster for transfering metrics into long-term storage should consider using their metric solution's native Kubernetes support, if present, or should consider alternative solutions. ([#62328](https://github.com/kubernetes/kubernetes/pull/62328), [@serathius](https://github.com/serathius)) +* The kubelet `--rotate-certificates` flag is now deprecated, and will be removed in a future release. The kubelet certificate rotation feature can now be enabled via the `.RotateCertificates` field in the kubelet's config file. ([#63912](https://github.com/kubernetes/kubernetes/pull/63912), [@luxas](https://github.com/luxas)) +* The kubeadm configuration file version has been upgraded from `v1alpha2` from `v1alpha1`. `v1alpha1` read support exists in v1.11, but will be removed in v1.12. ([#63788](https://github.com/kubernetes/kubernetes/pull/63788), [@luxas](https://github.com/luxas)) +The following PRs changed the API spec: + * In the new v1alpha2 kubeadm Configuration API, the `.CloudProvider` and `.PrivilegedPods` fields don't exist anymore. Instead, you should use the out-of-tree cloud provider implementations, which are beta in v1.11. + * If you have to use the legacy in-tree cloud providers, you can rearrange your config like the example below. If you need the `cloud-config` file (located in `{cloud-config-path}`), you can mount it into the API Server and controller-manager containers using ExtraVolumes, as in: +``` +kind: MasterConfiguration +apiVersion: kubeadm.k8s.io/v1alpha2 +apiServerExtraArgs: + cloud-provider: "{cloud}" + cloud-config: "{cloud-config-path}" +apiServerExtraVolumes: +- name: cloud + hostPath: "{cloud-config-path}" + mountPath: "{cloud-config-path}" +controllerManagerExtraArgs: + cloud-provider: "{cloud}" + cloud-config: "{cloud-config-path}" +controllerManagerExtraVolumes: +- name: cloud + hostPath: "{cloud-config-path}" + mountPath: "{cloud-config-path}" +``` +* If you need to use the `.PrivilegedPods` functionality, you can still edit the manifests in `/etc/kubernetes/manifests/`, and set `.SecurityContext.Privileged=true` for the apiserver and controller manager. + ([#63866](https://github.com/kubernetes/kubernetes/pull/63866), [@luxas](https://github.com/luxas)) + * kubeadm: The Token-related fields in the `MasterConfiguration` object have now been refactored. Instead of the top-level `.Token`, `.TokenTTL`, `.TokenUsages`, `.TokenGroups` fields, there is now a `BootstrapTokens` slice of `BootstrapToken` objects that support the same features under the `.Token`, `.TTL`, `.Usages`, `.Groups` fields. ([#64408](https://github.com/kubernetes/kubernetes/pull/64408), [@luxas](https://github.com/luxas)) + * `.NodeName` and `.CRISocket` in the `MasterConfiguration` and `NodeConfiguration` v1alpha1 API objects are now `.NodeRegistration.Name` and `.NodeRegistration.CRISocket` respectively in the v1alpha2 API. The `.NoTaintMaster` field has been removed in the v1alpha2 API. ([#64210](https://github.com/kubernetes/kubernetes/pull/64210), [@luxas](https://github.com/luxas)) + * kubeadm: Support for `.AuthorizationModes` in the kubeadm v1alpha2 API has been removed. Instead, you can use the `.APIServerExtraArgs` and `.APIServerExtraVolumes` fields to achieve the same effect. Files using the v1alpha1 API and setting this field will be automatically upgraded to this v1alpha2 API and the information will be preserved. ([#64068](https://github.com/kubernetes/kubernetes/pull/64068), [@luxas](https://github.com/luxas)) +* The annotation `service.alpha.kubernetes.io/tolerate-unready-endpoints` is deprecated. Users should use Service.spec.publishNotReadyAddresses instead. ([#63742](https://github.com/kubernetes/kubernetes/pull/63742), [@thockin](https://github.com/thockin)) +* `--show-all`, which only affected pods, and even then only for human readable/non-API printers, is inert in v1.11, and will be removed in a future release. ([#60793](https://github.com/kubernetes/kubernetes/pull/60793), [@charrywanganthony](https://github.com/charrywanganthony)) +* The `kubectl rolling-update` is now deprecated. Use `kubectl rollout` instead. ([#61285](https://github.com/kubernetes/kubernetes/pull/61285), [@soltysh](https://github.com/soltysh)) +* kube-apiserver: the default `--endpoint-reconciler-type` is now `lease`. The `master-count` endpoint reconciler type is deprecated and will be removed in 1.13. ([#63383](https://github.com/kubernetes/kubernetes/pull/63383), [@liggitt](https://github.com/liggitt)) +* OpenStack built-in cloud provider is now deprecated. Please use the external cloud provider for OpenStack. ([#63524](https://github.com/kubernetes/kubernetes/pull/63524), [@dims](https://github.com/dims)) +* The Kubelet's deprecated `--allow-privileged` flag now defaults to true. This enables users to stop setting `--allow-privileged` in order to transition to `PodSecurityPolicy`. Previously, users had to continue setting `--allow-privileged`, because the default was false. ([#63442](https://github.com/kubernetes/kubernetes/pull/63442), [@mtaufen](https://github.com/mtaufen)) +* The old dynamic client has been replaced by a new one. The previous dynamic client will exist for one release in `client-go/deprecated-dynamic`. Switch as soon as possible. ([#63446](https://github.com/kubernetes/kubernetes/pull/63446), [@deads2k](https://github.com/deads2k)) +* In-tree support for openstack credentials is now deprecated. please use the "client-keystone-auth" from the cloud-provider-openstack repository. details on how to use this new capability is documented [here](https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/using-client-keystone-auth.md) ([#64346](https://github.com/kubernetes/kubernetes/pull/64346), [@dims](https://github.com/dims)) +* The GitRepo volume type is deprecated. To provision a container with a git repo, mount an `EmptyDir` into an `InitContainer` that clones the repo using git, then moEmptyDir` into the Pod's container. +([#63445](https://github.com/kubernetes/kubernetes/pull/63445), [@ericchiang](https://github.com/ericchiang)) +* Alpha annotation for PersistentVolume node affinity has been removed. Update your PersistentVolumes to use the beta PersistentVolume.nodeAffinity field before upgrading to this release. ([#61816](https://github.com/kubernetes/kubernetes/pull/61816), [@wackxu +](https://github.com/wackxu)) + +#### Removed Deprecations + +* kubeadm has removed the `.ImagePullPolicy` field in the v1alpha2 API version. Instead it's set statically to `IfNotPresent` for all required images. If you want to always pull the latest images before cluster init (as `Always` would do), run `kubeadm config images pull` before each `kubeadm init`. If you don't want the kubelet to pull any images at `kubeadm init` time, for example if you don't have an internet connection, you can also run `kubeadm config images pull` before `kubeadm init` or side-load the images some other way (such as `docker load -i image.tar`). Having the images locally cached will result in no pull at runtime, which makes it possible to run without any internet connection. ([#64096](https://github.com/kubernetes/kubernetes/pull/64096), [@luxas](https://github.com/luxas)) +* kubeadm has removed `.Etcd.SelfHosting` from its configuration API. It was never used in practice ([#63871](https://github.com/kubernetes/kubernetes/pull/63871), [@luxas](https://github.com/luxas)) +* The deprecated and inactive option '--enable-custom-metrics' has been removed in 1.11. ([#60699](https://github.com/kubernetes/kubernetes/pull/60699), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* --include-extended-apis, which was deprecated back in [#32894](https://github.com/kubernetes/kubernetes/pull/32894), has been removed. ([#62803](https://github.com/kubernetes/kubernetes/pull/62803), [@deads2k](https://github.com/deads2k)) +* Kubelets will no longer set `externalID` in their node spec. This feature has been deprecated since v1.1. ([#61877](https://github.com/kubernetes/kubernetes/pull/61877), [@mikedanese](https://github.com/mikedanese)) +* The `initresource` admission plugin has been removed. ([#58784](https://github.com/kubernetes/kubernetes/pull/58784), [@wackxu](https://github.com/wackxu)) +* `ObjectMeta `, `ListOptions`, and `DeleteOptions` have been removed from the core api group. Please reference them in `meta/v1` instead. ([#61809](https://github.com/kubernetes/kubernetes/pull/61809), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* The deprecated `--mode` flag in `check-network-mode` has been removed. ([#60102](https://github.com/kubernetes/kubernetes/pull/60102), [@satyasm](https://github.com/satyasm)) +* Support for the `alpha.kubernetes.io/nvidia-gpu` resource, which was deprecated in 1.10, has been removed. Please use the resource exposed by DevicePlugins instead (`nvidia.com/gpu`). ([#61498](https://github.com/kubernetes/kubernetes/pull/61498), [@mindprince](https://github.com/mindprince)) +* The `kube-cloud-controller-manager` flag `--service-account-private-key-file` has been removed. Use `--use-service-account-credentials` instead. ([#60875](https://github.com/kubernetes/kubernetes/pull/60875), [@charrywanganthony](https://github.com/charrywanganthony)) +* The rknetes code, which was deprecated in 1.10, has been removed. Use rktlet and CRI instead. ([#61432](https://github.com/kubernetes/kubernetes/pull/61432), [@filbranden](https://github.com/filbranden)) +* DaemonSet scheduling associated with the alpha ScheduleDaemonSetPods feature flag has been emoved. See https://github.com/kubernetes/features/issues/548 for feature status. ([#61411](https://github.com/kubernetes/kubernetes/pull/61411), [@liggitt](https://github.com/liggitt)) +* The `METADATA_AGENT_VERSION` configuration option has been removed to keep metadata agent version consistent across Kubernetes deployments. ([#63000](https://github.com/kubernetes/kubernetes/pull/63000), [@kawych](https://github.com/kawych)) +* The deprecated `--service-account-private-key-file` flag has been removed from the cloud-controller-manager. The flag is still present and supported in the kube-controller-manager. ([#65182](https://github.com/kubernetes/kubernetes/pull/65182), [@liggitt](https://github.com/liggitt)) +* Removed alpha functionality that allowed the controller manager to approve kubelet server certificates. This functionality should be replaced by automating validation and approval of node server certificate signing requests. ([#62471](https://github.com/kubernetes/kubernetes/pull/62471), [@mikedanese](https://github.com/mikedanese)) + +#### Graduated to Stable/GA +* IPVS-based in-cluster load balancing is now GA ([ref](https://github.com/kubernetes/features/issues/265)) +* Enable CoreDNS as a DNS plugin for Kubernetes ([ref](https://github.com/kubernetes/features/issues/427)) +* Azure Go SDK is now GA ([#63063](https://github.com/kubernetes/kubernetes/pull/63063), [@feiskyer](https://github.com/feiskyer)) +* ClusterRole aggregation is now GA ([ref](https://github.com/kubernetes/features/issues/502)) +* CRI validation test suite is now GA ([ref](https://github.com/kubernetes/features/issues/292)) +* StorageObjectInUseProtection is now GA ([ref](https://github.com/kubernetes/features/issues/498)) and ([ref](https://github.com/kubernetes/features/issues/499)) + +#### Graduated to Beta + +* Supporting out-of-tree/external cloud providers is now considered beta ([ref](https://github.com/kubernetes/features/issues/88)) +* Resizing PersistentVolumes after pod restart is now considered beta. ([ref](https://github.com/kubernetes/features/issues/284)) +* sysctl support is now considered beta ([ref](https://github.com/kubernetes/features/issues/34)) +* Support for Azure Virtual Machine Scale Sets is now considered beta. ([ref](https://github.com/kubernetes/features/issues/513)) +* Azure support for Cluster Autoscaler is now considered beta. ([ref](https://github.com/kubernetes/features/issues/514)) +* The ability to limit a node's access to the API is now considered beta. ([ref](https://github.com/kubernetes/features/issues/279)) +* CustomResource versioning is now considered beta. ([ref](https://github.com/kubernetes/features/issues/544)) +* Windows container configuration in CRI is now considered beta ([ref](https://github.com/kubernetes/features/issues/547)) +* CRI logging and stats are now considered beta ([ref](https://github.com/kubernetes/features/issues/552)) +* The dynamic Kubelet config feature is now beta, and the DynamicKubeletConfig feature gate is on by default. In order to use dynamic Kubelet config, ensure that the Kubelet's --dynamic-config-dir option is set. ([#64275](https://github.com/kubernetes/kubernetes/pull/64275), [@mtaufen](https://github.com/mtaufen)) +* The Sysctls experimental feature has been promoted to beta (enabled by default via the `Sysctls` feature flag). PodSecurityPolicy and Pod objects now have fields for specifying and controlling sysctls. Alpha sysctl annotations will be ignored by 1.11+ kubelets. All alpha sysctl annotations in existing deployments must be converted to API fields to be effective. ([#6371](https://github.com/kubernetes/kubernetes/pull/63717), [@ingvagabund](https://github.com/ingvagabund)) +* Volume expansion is now considered Beta. ([#64288](https://github.com/kubernetes/kubernetes/pull/64288), [@gnufied](https://github.com/gnufied)) +* CRI container log rotation is now considered beta, and is enabled by default. ([#64046](https://github.com/kubernetes/kubernetes/pull/64046), [@yujuhong](https://github.com/yujuhong)) +* The `PriorityClass` API has been promoted to `scheduling.k8s.io/v1beta1` ([#63100](https://github.com/kubernetes/kubernetes/pull/63100), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* The priorityClass feature is now considered beta. ([#63724](https://github.com/kubernetes/kubernetes/pull/63724), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* client-go: credential exec plugins is now considered beta. ([#64482](https://github.com/kubernetes/kubernetes/pull/64482), [@ericchiang](https://github.com/ericchiang)) +* Subresources for custom resources is now considered beta and enabled by default. With this, updates to the `/status` subresource will disallow updates to all fields other than `.status` (not just `.spec` and `.metadata` as before). Also, `required` can be used at the root of the CRD OpenAPI validation schema when the `/status` subresource is enabled. ([#63598](https://github.com/kubernetes/kubernetes/pull/63598), [@nikhita](https://github.com/nikhita)) + +### New alpha features + +* kube-scheduler can now schedule DaemonSet pods ([ref](https://github.com/kubernetes/features/issues/548)) +* You can now resize PersistentVolumes without taking them offline ([ref](https://github.com/kubernetes/features/issues/531)) +* You can now set a maximum volume count ([ref](https://github.com/kubernetes/features/issues/554)) +* You can now do environment variable expansion in a subpath mount. ([ref](https://github.com/kubernetes/features/issues/559)) +* You can now run containers in a pod as a particular group. ([ref](https://github.com/kubernetes/features/issues/213)) +You can now bind tokens to service requests. ([ref](https://github.com/kubernetes/features/issues/542)) +* The --experimental-qos-reserve kubelet flags has been replaced by the alpha level --qos-reserved flag or the QOSReserved field in the kubeletconfig, and requires the QOSReserved feature gate to be enabled. ([#62509](https://github.com/kubernetes/kubernetes/pull/62509), [@sjenning](https://github.com/sjenning)) + +## Other Notable Changes + +### SIG API Machinery + +* Orphan delete is now supported for custom resources. ([#63386](https://github.com/kubernetes/kubernetes/pull/63386), [@roycaihw](https://github.com/roycaihw)) +* Metadata of CustomResources is now pruned and schema-checked during deserialization of requests and when read from etcd. In the former case, invalid meta data is rejected, in the later it is dropped from the CustomResource objects. ([#64267](https://github.com/kubernetes/kubernetes/pull/64267), [@sttts](https://github.com/sttts)) +* The kube-apiserver openapi doc now includes extensions identifying `APIService` and `CustomResourceDefinition` `kind`s ([#64174](https://github.com/kubernetes/kubernetes/pull/64174), [@liggitt](https://github.com/liggitt)) +* CustomResourceDefinitions Status subresource now supports GET and PATCH ([#63619](https://github.com/kubernetes/kubernetes/pull/63619), [@roycaihw](https://github.com/roycaihw)) +* When updating `/status` subresource of a custom resource, only the value at the `.status` subpath for the update is considered. ([#63385](https://github.cm/kubernetes/kubernetes/pull/63385), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* Added a way to pass extra arguments to etcd. The these extra arguments can be used to adjust runtime configuration like heartbeat interval etc. ([#63961](https://github.com/kubernetes/kubernetes/pull/63961), [@mborsz](https://github.com/mborsz)) +* Added Establishing Controller on CRDs to avoid race between Established condition and CRs actually served. In HA setups, the Established condition is delayed by 5 seconds. ([#63068](https://github.com/kubernetes/kubernetes/pull/63068), [@xmudrii](https://github.com/xmudrii)) +* Added `spec.additionalPrinterColumns` to CRDs to define server side printing columns. ([#60991](https://github.com/kubernetes/kubernetes/pull/60991), [@sttts](https://github.com/sttts)) +* Added CRD Versioning with NOP converter ([#63830](https://github.com/kubernetes/kubernetes/pull/63830), [@mbohlool](https://github.com/mbohlool)) +* Allow "required" and "description" to be used at the CRD OpenAPI validation schema root when the `/status` subresource is enabled. ([#63533](https://github.com/kubernetes/kubernetes/pull/63533), [@sttts](https://github.com/sttts)) +* Etcd health checks by the apiserver now ensure the apiserver can connect to and exercise the etcd API. ([#65027](https://github.com/kubernetes/kubernetes/pull/65027), [@liggitt](https://github.com/liggitt)) api- machinery +* The deprecated `--service-account-private-key-file` flag has been removed from the `cloud-controller-manager`. The flag is still present and supported in the `kube-controller-manager`. ([#65182](https://github.com/kubernetes/kubernetes/pull/65182), [@liggitt](https://github.com/liggitt)) +* Webhooks for the mutating admission controller now support the "remove" operation. ([#64255](https://github.com/kubernetes/kubernetes/pull/64255), [@rojkov](https://github.com/rojkov)) sig-API machinery +* The CRD OpenAPI v3 specification for validation now allows `additionalProperties`, which are mutually exclusive to properties. ([#62333](https://github.com/kubernetes/kubernetes/pull/62333), [@sttts](https://github.com/sttts)) +* Added the apiserver configuration option to choose the audit output version. ([#60056](https://github.com/kubernetes/kubernetes/pull/60056), [@crassirostris](https://github.com/crassirostris)) +* Created a new `dryRun` query parameter for mutating endpoints. If the parameter is set, then the query will be rejected, as the feature is not implemented yet. This will allow forward compatibility with future clients; otherwise, future clients talking with older apiservers might end up modifying a resource even if they include the `dryRun` query parameter. ([#63557](https://github.com/kubernetes/kubernetes/pull/63557), [@apelisse](https://github.com/apelisse)) +* `list`/`watch` API requests with a `fieldSelector` that specifies `metadata.name` can now be authorized as requests for an individual named resource ([#63469](https://github.com/kubernetes/kubernetes/pull/63469), [@wojtek-t](https://github.com/wojtek-t)) +* Exposed `/debug/flags/v` to allow dynamically set glog logging level. For example, to change glog level to 3, send a PUT request such as `curl -X PUT http://127.0.0.1:8080/debug/flags/v -d "3"`. ([#63777](https://github.com/kubernetes/kubernetes/pull/63777), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* Exec authenticator plugin supports TLS client certificates. ([#61803](https://github.com/kubernetes/kubernetes/pull/61803), [@awly](https://github.com/awly)) +* The `serverAddressByClientCIDRs` property in `metav1.APIGroup`(discovery API) is now optional instead of required. ([#61963](https://github.com/kubernetes/kubernetes/pull/61963), [@roycaihw](https://github.com/roycaihw)) +* `apiservices/status` and `certificatesigningrequests/status` now support `GET` and `PATCH` ([#64063](https://github.com/kubernetes/kubernetes/pull/64063), [@roycaihw](https://github.com/roycaihw)) +* APIServices with kube-like versions (e.g. `v1`, `v2beta1`, etc.) will be sorted appropriately within each group. ([#64004](https://github.com/kubernetes/kubernetes/pull/64004), [@mbohlool](https://github.com/mbohlool)) +* Event object references with apiversion will now that value. ([#63913](https://github.com/kubernetes/kubernetes/pull/63913), [@deads2k](https://github.com/deads2k)) +* Fixes the `kubernetes.default.svc` loopback service resolution to use a loopback configuration. ([#62649](https://github.com/kubernetes/kubernetes/pull/62649), [@liggitt](https://github.com/liggitt)) + +### SIG Apps + +* Added generators for `apps/v1` deployments. ([#61288](https://github.com/kubernetes/kubernetes/pull/61288), [@ayushpateria](https://github.com/ayushpateria)) + +### SIG Auth + +* RBAC information is now included in audit logs via audit.Event annotations: + * authorization.k8s.io/decision = {allow, forbid} + * authorization.k8s.io/reason = human-readable reason for the decision ([#58807](https://github.com/kubernetes/kubernetes/pull/58807), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* `kubectl certificate approve|deny` will not modify an already approved or denied CSR unless the `--force` flag is provided. ([#61971](https://github.com/kubernetes/kubernetes/pull/61971), [@smarterclayton](https://github.com/smarterclayton)) +* The `--bootstrap-kubeconfig` argument to Kubelet previously created the first bootstrap client credentials in the certificates directory as `kubelet-client.key` and `kubelet-client.crt`. Subsequent certificates created by cert rotation were created in a combined PEM file that was atomically rotated as `kubelet-client-DATE.pem` in that directory, which meant clients relying on the `node.kubeconfig` generated by bootstrapping would never use a rotated cert. The initial bootstrap certificate is now generated into the cert directory as a PEM file and symlinked to `kubelet-client-current.pem` so that the generated kubeconfig remains valid after rotation. ([#62152](https://github.com/kubernetes/kubernetes/pull/62152), [@smarterclayton](https://github.com/smarterclayton)) +* Owner references can now be set during creation, even if the user doesn't have deletion power ([#63403](https://github.com/kubernetes/kubernetes/pull/63403), [@deads2k](https://github.com/deads2k)) +* Laid the groundwork for OIDC distributed claims handling in the apiserver authentication token checker. A distributed claim allows the OIDC provider to delegate a claim to a separate URL. ([ref](http://openid.net/specs/openid-connect-core-1_0.html#AggregatedDistributedClaims)). ([#63213](https://github.com/kubernetes/kubernetes/pull/63213), [@filmil](https://github.com/filmil)) +* RBAC: all configured authorizers are now checked to determine if an RBAC role or clusterrole escalation (setting permissions the user does not currently have via RBAC) is allowed. ([#56358](https://github.com/kubernetes/kubernetes/pull/56358), [@liggitt](https://github.com/liggitt)) +* kube-apiserver: OIDC authentication now supports requiring specific claims with `--oidc-required-claim==` Previously, there was no mechanism for a user to specify claims in the OIDC authentication process that were requid to be present in the ID Token with an expected value. This version now makes it possible to require claims support for the OIDC authentication. It allows users to pass in a `--oidc-required-claims` flag, and `key=value` pairs in the API config, which will ensure that the specified required claims are checked against the ID Token claims. ([#62136](https://github.com/kubernetes/kubernetes/pull/62136), [@rithujohn191](https://github.com/rithujohn191)) +* Included the list of security groups when failing with the errors that more than one is tagged. ([#58874](https://github.com/kubernetes/kubernetes/pull/58874), [@sorenmat](https://github.com/sorenmat)) +* Added proxy for container streaming in kubelet for streaming auth. ([#64006](https://github.com/kubernetes/kubernetes/pull/64006), [@Random-Liu](https://github.com/Random-Liu)) +* PodSecurityPolicy admission information has been added to audit logs. ([#58143](https://github.com/kubernetes/kubernetes/pull/58143), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* TokenRequests now are required to have an expiration duration between 10 minutes and 2^32 seconds. ([#63999](https://github.com/kubernetes/kubernetes/pull/63999), [@mikedanese](https://github.com/mikedanese)) +* The `NodeRestriction` admission plugin now prevents kubelets from modifying/removing taints applied to their Node API object. ([#63167](https://github.com/kubernetes/kubernetes/pull/63167), [@liggitt](https://github.com/liggitt)) +* authz: nodes should not be able to delete themselves ([#62818](https://github.com/kubernetes/kubernetes/pull/62818), [@mikedanese](https://github.com/mikedanese)) + +### SIG Autoscaling + +* A cluster-autoscaler ClusterRole is added to cover only the functionality required by Cluster Autoscaler and avoid abusing system:cluster-admin role. Cloud providers other than GCE might want to update their deployments or sample yaml files to reuse the role created via add-on. ([#64503](https://github.com/kubernetes/kubernetes/pull/64503), [@kgolab](https://github.com/kgolab)) + +### SIG Azure + +* The Azure cloud provider now supports standard SKU load balancer and public IP. +`excludeMasterFromStandardLB` defaults to true, which means master nodes are excluded from the standard load balancer. Also note that because all nodes (except master) are added as loadbalancer backends, the standard load balancer doesn't work with the `service.beta.kubernetes.io/azure-load-balancer-mode` annotation. +([#61884](https://github.com/kubernetes/kubernetes/pull/61884), [#62707](https://github.com/kubernetes/kubernetes/pull/62707), [@feiskyer](https://github.com/feiskyer)) +* The Azure cloud provider now supports specifying allowed service tags by the `service.beta.kubernetes.io/azure-allowed-service-tags` annotation. ([#61467](https://github.com/kubernetes/kubernetes/pull/61467), [@feiskyer](https://github.com/feiskyer)) +* You can now change the size of an azuredisk PVC using `kubectl edit pvc pvc-azuredisk`. Note that this operation will fail if the volume is already attached to a running VM. ([#64386](https://github.com/kubernetes/kubernetes/pull/64386), [@andyzhangx](https://github.com/andyzhangx)) +* Block device support has been added for azure disk. ([#63841](https://github.com/kubernetes/kubernetes/pull/63841), [@andyzhangx](https://github.com/andyzhangx)) +* Azure VM names can now contain the underscore (`_`) character ([#63526](https://github.com/kubernetes/kubernetes/pull/63526), [@djsly](https://github.com/djsly)) +* Azure disks now support external resource groups. +([#64427](https://github.com/kubernetes/kuernetes/pull/64427), [@andyzhangx](https://github.com/andyzhangx)) +* Added reason message logs for non-existant Azure resources. +([#64248](https://github.com/kubernetes/kubernetes/pull/64248), [@feiskyer](https://github.com/feiskyer)) + +### SIG CLI + +* You can now use the `base64decode` function in kubectl go templates to decode base64-encoded data, such as `kubectl get secret SECRET -o go-template='{{ .data.KEY | base64decode }}'`. ([#60755](https://github.com/kubernetes/kubernetes/pull/60755), [@glb](https://github.com/glb)) +* `kubectl patch` now supports `--dry-run`. ([#60675](https://github.com/kubernetes/kubernetes/pull/60675), [@timoreimann](https://github.com/timoreimann)) +* The global flag `--match-server-version` is now global. `kubectl version` will respect it. ([#63613](https://github.com/kubernetes/kubernetes/pull/63613), [@deads2k](https://github.com/deads2k)) +* kubectl will list all allowed print formats when an invalid format is passed. ([#64371](https://github.com/kubernetes/kubernetes/pull/64371), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* The global flag "context" now gets applied to `kubectl config view --minify`. In previous versions, this command was only available for `current-context`. Now it will be easier for users to view other non current contexts when minifying. ([#64608](https://github.com/kubernetes/kubernetes/pull/64608), [@dixudx](https://github.com/dixudx)) +* `kubectl apply --prune` supports CronJob resources. ([#62991](https://github.com/kubernetes/kubernetes/pull/62991), [@tomoe](https://github.com/tomoe)) +* The `--dry-run` flag has been enabled for `kubectl auth reconcile` ([#64458](https://github.com/kubernetes/kubernetes/pull/64458), [@mrogers950](https://github.com/mrogers950)) +* `kubectl wait` is a new command that allows waiting for one or more resources to be deleted or to reach a specific condition. It adds a `kubectl wait --for=[delete|condition=condition-name] resource/string` command. ([#64034](https://github.com/kubernetes/kubernetes/pull/64034), [@deads2k](https://github.com/deads2k)) +* `kubectl auth reconcile` only works with rbac.v1; all the core helpers have been switched over to use the external types. ([#63967](https://github.com/kubernetes/kubernetes/pull/63967), [@deads2k](https://github.com/deads2k)) +* kubectl and client-go now detect duplicated names for user, cluster and context when loading kubeconfig and report this condition as an error. ([#60464](https://github.com/kubernetes/kubernetes/pull/60464), [@roycaihw](https://github.com/roycaihw)) +* Added 'UpdateStrategyType' and 'RollingUpdateStrategy' to 'kubectl describe sts' command output. ([#63844](https://github.com/kubernetes/kubernetes/pull/63844), [@tossmilestone](https://github.com/tossmilestone)) +* Initial Korean translation for kubectl has been added. ([#62040](https://github.com/kubernetes/kubernetes/pull/62040), [@ianychoi](https://github.com/ianychoi)) +* `kubectl cp` now supports completion. +([#60371](https://github.com/kubernetes/kubernetes/pull/60371), [@superbrothers](https://github.com/superbrothers)) +* The shortcuts that were moved server-side in at least 1.9 have been removed from being hardcoded in kubectl. This means that the client-based restmappers have been moved to client-go, where everyone who needs them can have access. ([#63507](https://github.com/kubernetes/kubernetes/pull/63507), [@deads2k](https://github.com/deads2k)) +* When using `kubectl delete` with selection criteria, the defaults to is now to ignore "not found" errors. Note that this does not apply when deleting a speciic resource. ([#63490](https://github.com/kubernetes/kubernetes/pull/63490), [@deads2k](https://github.com/deads2k)) +* `kubectl create [secret | configmap] --from-file` now works on Windows with fully-qualified paths ([#63439](https://github.com/kubernetes/kubernetes/pull/63439), [@liggitt](https://github.com/liggitt)) +* Portability across systems has been increased by the use of `/usr/bin/env` in all script shebangs. ([#62657](https://github.com/kubernetes/kubernetes/pull/62657), [@matthyx](https://github.com/matthyx)) +* You can now use `kubectl api-resources` to discover resources. + ([#42873](https://github.com/kubernetes/kubernetes/pull/42873), [@xilabao](https://github.com/xilabao)) +* You can now display requests/limits of extended resources in node allocated resources. ([#46079](https://github.com/kubernetes/kubernetes/pull/46079), [@xiangpengzhao](https://github.com/xiangpengzhao)) +* The `--remove-extra-subjects` and `--remove-extra-permissions` flags have been enabled for `kubectl auth reconcile` ([#64541](https://github.com/kubernetes/kubernetes/pull/64541), [@mrogers950](https://github.com/mrogers950)) +* kubectl now has improved compatibility with older servers when creating/updating API objects ([#61949](https://github.com/kubernetes/kubernetes/pull/61949), [@liggitt](https://github.com/liggitt)) +* `kubectl apply` view/edit-last-applied now supports completion. ([#60499](https://github.com/kubernetes/kubernetes/pull/60499), [@superbrothers](https://github.com/superbrothers)) + +### SIG Cluster Lifecycle + + * kubeadm: The `:Etcd` struct has been refactored in the v1alpha2 API. All the options now reside under either `.Etcd.Local` or `.Etcd.External`. Automatic conversions from the v1alpha1 API are supported. ([#64066](https://github.com/kubernetes/kubernetes/pull/64066), [@luxas](https://github.com/luxas)) +* kubeadm now uses an upgraded API version for the configuration file, `kubeadm.k8s.io/v1alpha2`. kubeadm in v1.11 will still be able to read `v1alpha1` configuration, and will automatically convert the configuration to `v1alpha2`, both internally and when storing the configuration in the ConfigMap in the cluster. ([#63788](https://github.com/kubernetes/kubernetes/pull/63788), [@luxas](https://github.com/luxas)) +* Phase `kubeadm alpha phase kubelet` has been added to support dynamic kubelet configuration in kubeadm. ([#57224](https://github.com/kubernetes/kubernetes/pull/57224), [@xiangpengzhao](https://github.com/xiangpengzhao)) +* The kubeadm config option `API.ControlPlaneEndpoint` has been extended to take an optional port, which may differ from the apiserver's bind port. ([#62314](https://github.com/kubernetes/kubernetes/pull/62314), [@rjosephwright](https://github.com/rjosephwright)) +* The `--cluster-name` parameter has been added to kubeadm init, enabling users to specify the cluster name in kubeconfig. ([#60852](https://github.com/kubernetes/kubernetes/pull/60852), [@karan](https://github.com/karan)) +* The logging feature for kubeadm commands now supports a verbosity setting. ([#57661](https://github.com/kubernetes/kubernetes/pull/57661), [@vbmade2000](https://github.com/vbmade2000)) +* kubeadm now has a join timeout that can be controlled via the `discoveryTimeout` config option. This option is set to 5 minutes by default. ([#60983](https://github.com/kubernetes/kubernetes/pull/60983), [@rosti](https://github.com/rosti)) +* Added the `writable` boolean option to kubeadm config. This option works on a per-volume basis for `ExtraVolumes` config keys. ([#60428](https://github.com/kubernetes/kubernetes/pul60428), [@rosti](https://github.com/rosti)) +* Added a new `kubeadm upgrade node config` command. ([#64624](https://github.com/kubernetes/kubernetes/pull/64624), [@luxas](https://github.com/luxas)) +* kubeadm now makes the CoreDNS container more secure by dropping (root) capabilities and improves the integrity of the container by running the whole container in read-only. ([#64473](https://github.com/kubernetes/kubernetes/pull/64473), [@nberlee](https://github.com/nberlee)) +* kubeadm now detects the Docker cgroup driver and starts the kubelet with the matching driver. This eliminates a common error experienced by new users in when the Docker cgroup driver is not the same as the one set for the kubelet due to different Linux distributions setting different cgroup drivers for Docker, making it hard to start the kubelet properly. +([#64347](https://github.com/kubernetes/kubernetes/pull/64347), [@neolit123](https://github.com/neolit123)) +* Added a 'kubeadm config migrate' command to convert old API types to their newer counterparts in the new, supported API types. This is just a client-side tool; it just executes locally without requiring a cluster to be running, operating in much the same way as a Unix pipe that upgrades config files. ([#64232](https://github.com/kubernetes/kubernetes/pull/64232), [@luxas](https://github.com/luxas)) +* kubeadm will now pull required images during preflight checks if it cannot find them on the system. ([#64105](https://github.com/kubernetes/kubernetes/pull/64105), [@chuckha](https://github.com/chuckha)) +* "kubeadm init" now writes a structured and versioned kubelet ComponentConfiguration file to `/var/lib/kubelet/config.yaml` and an environment file with runtime flags that you can source in the systemd kubelet dropin to `/var/lib/kubelet/kubeadm-flags.env`. ([#63887](https://github.com/kubernetes/kubernetes/pull/63887), [@luxas](https://github.com/luxas)) +* A `kubeadm config print-default` command has now been added. You can use this command to output a starting point when writing your own kubeadm configuration files. ([#63969](https://github.com/kubernetes/kubernetes/pull/63969), [@luxas](https://github.com/luxas)) +* Updated kubeadm's minimum supported kubernetes in v1.11.x to 1.10 ([#63920](https://github.com/kubernetes/kubernetes/pull/63920), [@dixudx](https://github.com/dixudx)) +* Added the `kubeadm upgrade diff` command to show how static pod manifests will be changed by an upgrade. This command shows the changes that will be made to the static pod manifests before applying them. This is a narrower case than kubeadm upgrade apply --dry-run, which specifically focuses on the static pod manifests. ([#63930](https://github.com/kubernetes/kubernetes/pull/63930), [@liztio](https://github.com/liztio)) +* The `kubeadm config images pull` command can now be used to pull container images used by kubeadm. ([#63833](https://github.com/kubernetes/kubernetes/pull/63833), [@chuckha](https://github.com/chuckha)) +* kubeadm will now deploy CoreDNS by default instead of KubeDNS ([#63509](https://github.com/kubernetes/kubernetes/pull/63509), [@detiber](https://github.com/detiber)) +* Preflight checks for kubeadm no longer validate custom kube-apiserver, kube-controller-manager and kube-scheduler arguments. ([#63673](https://github.com/kubernetes/kubernetes/pull/63673), [@chuckha](https://github.com/chuckha)) +* Added a `kubeadm config images list` command that lists required container images for a kubeadm install. ([#63450](https://github.com/kubernetes/kubernetes/pull/63450), [@chuckha](https://github.com/chukha)) +* You can now use `kubeadm token` specifying `--kubeconfig`. In this case, kubeadm searches the current user home path and the environment variable KUBECONFIG for existing files. If provided, the `--kubeconfig` flag will be honored instead. ([#62850](https://github.com/kubernetes/kubernetes/pull/62850), [@neolit123](https://github.com/neolit123)) +([#64988](https://github.com/kubernetes/kubernetes/pull/64988), [@detiber](https://github.com/detiber)) +* kubeadm now sets peer URLs for the default etcd instance. Previously we left the defaults, which meant the peer URL was unsecured. +* Kubernetes now packages crictl in a cri-tools deb and rpm package. ([#64836](https://github.com/kubernetes/kubernetes/pull/64836), [@chuckha](https://github.com/chuckha)) +* kubeadm now prompts the user for confirmation when resetting a master node. ([#59115](https://github.com/kubernetes/kubernetes/pull/59115), [@alexbrand](https://github.com/alexbrand)) +* kubead now creates kube-proxy with a toleration to run on all nodes, no matter the taint. ([#62390](https://github.com/kubernetes/kubernetes/pull/62390), [@discordianfish](https://github.com/discordianfish)) +* kubeadm now sets the kubelet `--resolv-conf` flag conditionally on init. ([#64665](https://github.com/kubernetes/kubernetes/pull/64665), [@stealthybox](https://github.com/stealthybox)) +* Added ipset and udevadm to the hyperkube base image. ([#61357](https://github.com/kubernetes/kubernetes/pull/61357), [@rphillips](https://github.com/rphillips)) + +### SIG GCP + +* Kubernetes clusters on GCE now have crictl installed. Users can use it to help debug their nodes. See the [crictl documentation](https://github.com/kubernetes-incubator/cri-tools/blob/master/docs/crictl.md) for details. ([#63357](https://github.com/kubernetes/kubernetes/pull/63357), [@Random-Liu](https://github.com/Random-Liu)) +* `cluster/kube-up.sh` now provisions a Kubelet config file for GCE via the metadata server. This file is installed by the corresponding GCE init scripts. ([#62183](https://github.com/kubernetes/kubernetes/pull/62183), [@mtaufen](https://github.com/mtaufen)) +* GCE: Update cloud provider to use TPU v1 API ([#64727](https://github.com/kubernetes/kubernetes/pull/64727), [@yguo0905](https://github.com/yguo0905)) +* GCE: Bump GLBC version to 1.1.1 - fixing an issue of handling multiple certs with identical certificates. ([#62751](https://github.com/kubernetes/kubernetes/pull/62751), [@nicksardo](https://github.com/nicksardo)) + +### SIG Instrumentation + +* Added prometheus cluster monitoring addon to kube-up. ([#62195](https://github.com/kubernetes/kubernetes/pull/62195), [@serathius](https://github.com/serathius)) +* Kubelet now exposes a new endpoint, `/metrics/probes`, which exposes a Prometheus metric containing the liveness and/or readiness probe results for a container. ([#61369](https://github.com/kubernetes/kubernetes/pull/61369), [@rramkumar1](https://github.com/rramkumar1)) + +### SIG Network + +* The internal IP address of the node is now added as additional information for kubectl. ([#57623](https://github.com/kubernetes/kubernetes/pull/57623), [@dixudx](https://github.com/dixudx)) +* NetworkPolicies can now target specific pods in other namespaces by including both a namespaceSelector and a podSelector in the same peer element. ([#60452](https://github.com/kubernetes/kubernetes/pull/60452), [@danwinship](https://github.com/danwinship)) +* CoreDNS deployment configuration now uses the k8s.gcr.io imageRepository. ([#64775](https://github.com/kubernetes/kubernetes/pull/64775), [@rajansandeep](https://giub.com/rajansandeep)) +* kubelet's `--cni-bin-dir` option now accepts multiple comma-separated CNI binary directory paths, which are searched for CNI plugins in the given order. ([#58714](https://github.com/kubernetes/kubernetes/pull/58714), [@dcbw](https://github.com/dcbw)) +* You can now use `--ipvs-exclude-cidrs` to specify a list of CIDR's which the IPVS proxier should not touch when cleaning up IPVS rules. ([#62083](https://github.com/kubernetes/kubernetes/pull/62083), [@rramkumar1](https://github.com/rramkumar1)) +* You can now receive node DNS info with the `--node-ip` flag, which adds `ExternalDNS`, `InternalDNS`, and `ExternalIP` to kubelet's output. ([#63170](https://github.com/kubernetes/kubernetes/pull/63170), [@micahhausler](https://github.com/micahhausler)) +* You can now have services that listen on the same host ports on different interfaces by specifying `--nodeport-addresses`. ([#62003](https://github.com/kubernetes/kubernetes/pull/62003), [@m1093782566](https://github.com/m1093782566)) +* Added port-forward examples for service + +### SIG Node + +* CRI: The container log path has been changed from containername_attempt#.log to containername/attempt#.log ([#62015](https://github.com/kubernetes/kubernetes/pull/62015), [@feiskyer](https://github.com/feiskyer)) +* Introduced the `ContainersReady` condition in Pod status. ([#64646](https://github.com/kubernetes/kubernetes/pull/64646), [@freehan](https://github.com/freehan)) +* Kubelet will now set extended resource capacity to zero after it restarts. If the extended resource is exported by a device plugin, its capacity will change to a valid value after the device plugin re-connects with the Kubelet. If the extended resource is exported by an external component through direct node status capacity patching, the component should repatch the field after kubelet becomes ready again. During the time gap, pods previously assigned with such resources may fail kubelet admission but their controller should create new pods in response to such failures. ([#64784](https://github.com/kubernetes/kubernetes/pull/64784), [@jiayingz](https://github.com/jiayingz)) node +* You can now use a security context with Windows containers +([#64009](https://github.com/kubernetes/kubernetes/pull/64009), [@feiskyer](https://github.com/feiskyer)) +* Added e2e regression tests for kubelet security. ([#64140](https://github.com/kubernetes/kubernetes/pull/64140), [@dixudx](https://github.com/dixudx)) +* The maximum number of images the Kubelet will report in the Node status can now be controlled via the Kubelet's `--node-status-max-images` flag. The default (50) remains the same. ([#64170](https://github.com/kubernetes/kubernetes/pull/64170), [@mtaufen](https://github.com/mtaufen)) +* The Kubelet now exports metrics that report the assigned (`node_config_assigned`), last-known-good (`node_config_last_known_good`), and active (`node_config_active`) config sources, and a metric indicating whether the node is experiencing a config-related error (`node_config_error`). The config source metrics always report the value `1`, and carry the `node_config_name`, `node_config_uid`, `node_config_resource_version`, and `node_config_kubelet_key labels`, which identify the config version. The error metric reports `1` if there is an error, `0` otherwise. ([#57527](https://github.com/kubernetes/kubernetes/pull/57527), [@mtaufen](https://github.com/mtaufen)) +* You now have the ability to quota resources by priority. ([#57963](https://github.com/kubernetes/kubernetes/pull/57963), [@vikaschoudhary16](https://github.com/ikaschoudhary16)) +* The gRPC max message size in the remote container runtime has been increased to 16MB. ([#64672](https://github.com/kubernetes/kubernetes/pull/64672), [@mcluseau](https://github.com/mcluseau)) +* Added a feature gate for the plugin watcher. ([#64605](https://github.com/kubernetes/kubernetes/pull/64605), [@vikaschoudhary16](https://github.com/vikaschoudhary16)) +* The status of dynamic Kubelet config is now reported via Node.Status.Config, rather than the KubeletConfigOk node condition. ([#63314](https://github.com/kubernetes/kubernetes/pull/63314), [@mtaufen](https://github.com/mtaufen)) +* You must now specify `Node.Spec.ConfigSource.ConfigMap.KubeletConfigKey` when using dynamic Kubelet config to tell the Kubelet which key of the `ConfigMap` identifies its config file. ([#59847](https://github.com/kubernetes/kubernetes/pull/59847), [@mtaufen](https://github.com/mtaufen)) +* The dynamic Kubelet config feature will now update the config in the event of a ConfigMap mutation, which reduces the chance for silent config skew. Only name, namespace, and kubeletConfigKey may now be set in `Node.Spec.ConfigSource.ConfigMap`. The least disruptive pattern for config management is still to create a new ConfigMap and incrementally roll out a new `Node.Spec.ConfigSource`. ([#63221](https://github.com/kubernetes/kubernetes/pull/63221), [@mtaufen](https://github.com/mtaufen)) +* Change seccomp annotation from "docker/default" to "runtime/default" ([#62662](https://github.com/kubernetes/kubernetes/pull/62662), [@wangzhen127](https://github.com/wangzhen127)) +* The node authorizer now automatically sets up rules for `Node.Spec.ConfigSource` when the DynamicKubeletConfig feature gate is enabled. ([#60100](https://github.com/kubernetes/kubernetes/pull/60100), [@mtaufen](https://github.com/mtaufen)) +* CRI now defines mounting behavior. If the host path doesn't exist, the runtime should return an error. If the host path is a symlink, the runtime should follow the symlink and mount the real destination to the container. ([#61460](https://github.com/kubernetes/kubernetes/pull/61460), [@feiskyer](https://github.com/feiskyer)) + +### SIG OpenStack + +* Provide a meaningful error message in the openstack cloud provider when no valid IP address can be found for a node, rather than just the first address of the node, which leads to a load balancer error if that address is a hostname or DNS name instead of an IP address. ([#64318](https://github.com/kubernetes/kubernetes/pull/64318), [@gonzolino](https://github.com/gonzolino)) +* Restored the pre-1.10 behavior of the openstack cloud provider, which uses the instance name as the Kubernetes Node name. This requires instances be named with RFC-1123 compatible names. ([#63903](https://github.com/kubernetes/kubernetes/pull/63903), [@liggitt](https://github.com/liggitt)) +* Kubernetes will try to read the openstack auth config from the client config and fall back to read from the environment variables if the auth config is not available. ([#60200](https://github.com/kubernetes/kubernetes/pull/60200), [@dixudx](https://github.com/dixudx)) + +### SIG Scheduling + +* Schedule DaemonSet Pods in scheduler, rather than the Daemonset controller. +([#63223](https://github.com/kubernetes/kubernetes/pull/63223), [@k82cn](https://github.com/k82cn)) +* Added `MatchFields` to `NodeSelectorTerm`; in 1.11, it only supports `metadata.name`. ([#62002](https://github.com/kubernetes/kubernetes/pull/62002), [@k82cn](https://github.com/k82cn)) +* kube-scheduler now has the `--write-config-to` flag so that Scheduler canwritets default configuration to a file. +([#62515](https://github.com/kubernetes/kubernetes/pull/62515), [@resouer](https://github.com/resouer)) +* Performance of the affinity/anti-affinity predicate for the default scheduler has been significantly improved. ([#62211](https://github.com/kubernetes/kubernetes/pull/62211), [@bsalamat](https://github.com/bsalamat)) +* The 'scheduling_latency_seconds' metric into has been split into finer steps (predicate, priority, preemption). ([#65306](https://github.com/kubernetes/kubernetes/pull/65306), [@shyamjvs](https://github.com/shyamjvs)) +* Scheduler now has a summary-type metric, 'scheduling_latency_seconds'. ([#64838](https://github.com/kubernetes/kubernetes/pull/64838), [@krzysied](https://github.com/krzysied)) +* `nodeSelector.matchFields` (node's `metadata.node`) is now supported in scheduler. ([#62453](https://github.com/kubernetes/kubernetes/pull/62453), [@k82cn](https://github.com/k82cn)) +* Added a parametrizable priority function mapping requested/capacity ratio to priority. This function is disabled by default and can be enabled via the scheduler policy config file. +([#63929](https://github.com/kubernetes/kubernetes/pull/63929), [@losipiuk](https://github.com/losipiuk)) +* System critical priority classes are now automatically added at cluster boostrapping. ([#60519](https://github.com/kubernetes/kubernetes/pull/60519), [@bsalamat](https://github.com/bsalamat)) + +### SIG Storage + +* AWS EBS, Azure Disk, GCE PD and Ceph RBD volume plugins now support dynamic provisioning of raw block volumes. ([#64447](https://github.com/kubernetes/kubernetes/pull/64447), [@jsafrane](https://github.com/jsafrane)) +* gitRepo volumes in pods no longer require git 1.8.5 or newer; older git versions are now supported. ([#62394](https://github.com/kubernetes/kubernetes/pull/62394), [@jsafrane](https://github.com/jsafrane)) +* Added support for resizing Portworx volumes. ([#62308](https://github.com/kubernetes/kubernetes/pull/62308), [@harsh-px](https://github.com/harsh-px)) +* Added block volume support to Cinder volume plugin. ([#64879](https://github.com/kubernetes/kubernetes/pull/64879), [@bertinatto](https://github.com/bertinatto)) +* Provided API support for external CSI storage drivers to support block volumes. ([#64723](https://github.com/kubernetes/kubernetes/pull/64723), [@vladimirvivien](https://github.com/vladimirvivien)) +* Volume topology aware dynamic provisioning for external provisioners is now supported. ([#63193](https://github.com/kubernetes/kubernetes/pull/63193), [@lichuqiang](https://github.com/lichuqiang)) +* Added a volume projection that is able to project service account tokens. ([#62005](https://github.com/kubernetes/kubernetes/pull/62005), [@mikedanese](https://github.com/mikedanese)) +* PodSecurityPolicy now supports restricting hostPath volume mounts to be readOnly and under specific path prefixes ([#58647](https://github.com/kubernetes/kubernetes/pull/58647), [@jhorwit2](https://github.com/jhorwit2)) +* Added StorageClass API to restrict topologies of dynamically provisioned volumes. ([#63233](https://github.com/kubernetes/kubernetes/pull/63233), [@lichuqiang](https://github.com/lichuqiang)) +* Added Alpha support for dynamic volume limits based on node type ([#64154](https://github.com/kubernetes/kubernetes/pull/64154), [@gnufied](https://github.com/gnufied)) +* AWS EBS volumes can be now used as ReadOnly in pods. ([#64403](https://github.com/kubernetes/kubernetes/pull/64403), [@jsafrane](https://github.com/jsafrane)) +* Basic plumbing for volume topology aware dynamic provisionin has been implemented. ([#63232](https://github.com/kubernetes/kubernetes/pull/63232), [@lichuqiang](https://github.com/lichuqiang)) +* Changed ext3/ext4 volume creation to not reserve any portion of the volume for the root user. When creating ext3/ext4 volume, mkfs defaults to reserving 5% of the volume for the super-user (root). This patch changes the mkfs to pass -m0 to disable this setting. +([#64102](https://github.com/kubernetes/kubernetes/pull/64102), [@atombender](https://github.com/atombender)) +* Added support for NFS relations on kubernetes-worker charm. ([#63817](https://github.com/kubernetes/kubernetes/pull/63817), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Implemented kubelet side online file system resizing ([#62460](https://github.com/kubernetes/kubernetes/pull/62460), [@mlmhl](https://github.com/mlmhl)) +* Generated subpath name from Downward API env ([#49388](https://github.com/kubernetes/kubernetes/pull/49388), [@kevtaylor](https://github.com/kevtaylor)) + +### SIG vSphere + +* Added a mechanism in vSphere Cloud Provider to get credentials from Kubernetes secrets, rather than the plain text `vsphere.conf` file.([#63902](https://github.com/kubernetes/kubernetes/pull/63902), [@abrarshivani](https://github.com/abrarshivani)) +* vSphere Cloud Provider: added SAML token authentication support ([#63824](https://github.com/kubernetes/kubernetes/pull/63824), [@dougm](https://github.com/dougm)) + +### SIG Windows + +* Added log and fs stats for Windows containers. ([#62266](https://github.com/kubernetes/kubernetes/pull/62266), [@feiskyer](https://github.com/feiskyer)) +* Added security contexts for Windows containers. [#64009](https://github.com/kubernetes/kubernetes/pull/64009), ([@feiskyer](https://github.com/feiskyer)) +* Added local persistent volumes for Windows containers. ([#62012](https://github.com/kubernetes/kubernetes/pull/62012), [@andyzhangx](https://github.com/andyzhangx)) and fstype for Azure disk ([#61267](https://github.com/kubernetes/kubernetes/pull/61267), [@andyzhangx](https://github.com/andyzhangx)) +* Improvements in Windows Server version 1803 also bring new storage functionality to Kubernetes v1.11, including: + * Volume mounts for ConfigMap and Secret + * Flexvolume plugins for SMB and iSCSI storage are also available out-of-tree at [Microsoft/K8s-Storage-Plugins](https://github.com/Microsoft/K8s-Storage-Plugins) +* Setup dns servers and search domains for Windows Pods in dockershim. Docker EE version >= 17.10.0 is required for propagating DNS to containers. ([#63905](https://github.com/kubernetes/kubernetes/pull/63905), [@feiskyer](https://github.com/feiskyer)) + +### Additional changes + +* Extended the Stackdriver Metadata Agent by adding a new Deployment for ingesting unscheduled pods and services. ([#62043](https://github.com/kubernetes/kubernetes/pull/62043), [@supriyagarg](https://github.com/supriyagarg)) +* Added all kinds of resource objects' statuses in HPA description. ([#59609](https://github.com/kubernetes/kubernetes/pull/59609), [@zhangxiaoyu-zidif](https://github.com/zhangxiaoyu-zidif)) +* Implemented preemption for extender with a verb and new interface ([#58717](https://github.com/kubernetes/kubernetes/pull/58717), [@resouer](https://github.com/resouer)) +* Updated nvidia-gpu-device-plugin DaemonSet config to use RollingUpdate updateStrategy instead of OnDelete. ([#64296](https://github.com/kubernetes/kubernetes/pull/64296), [@mindprince](https://github.com/mindprince)) +* increased grpc client default response size. ([#63977](https://github.com/kubernetes/kubernetes/pull/677), [@runcom](https://github.com/runcom)) +* Applied pod name and namespace labels to pod cgroup in cAdvisor metrics ([#63406](https://github.com/kubernetes/kubernetes/pull/63406), [@derekwaynecarr](https://github.com/derekwaynecarr)) +* [fluentd-gcp addon] Use the logging agent's node name as the metadata agent URL. ([#63353](https://github.com/kubernetes/kubernetes/pull/63353), [@bmoyles0117](https://github.com/bmoyles0117)) +* The new default value for the --allow-privileged parameter of the Kubernetes-worker charm has been set to true based on changes which went into the Kubernetes 1.10 release. Before this change the default value was set to false. If you're installing Canonical Kubernetes you should expect this value to now be true by default and you should now look to use PSP (pod security policies). ([#64104](https://github.com/kubernetes/kubernetes/pull/64104), [@CalvinHartwell](https://github.com/CalvinHartwell)) + +## External Dependencies + +* Default etcd server version is v3.2.18 compared with v3.1.12 in v1.10 ([#61198](https://github.com/kubernetes/kubernetes/pull/61198)) +* Rescheduler is v0.4.0, compared with v0.3.1 in v1.10 ([#65454](https://github.com/kubernetes/kubernetes/pull/65454)) +* The validated docker versions are the same as for v1.10: 1.11.2 to 1.13.1 and 17.03.x (ref) +* The Go version is go1.10.2, as compared to go1.9.3 in v1.10. ([#63412](https://github.com/kubernetes/kubernetes/pull/63412)) +* The minimum supported go is the same as for v1.10: go1.9.1. ([#55301](https://github.com/kubernetes/kubernetes/pull/55301)) +* CNI is the same as v1.10: v0.6.0 ([#51250](https://github.com/kubernetes/kubernetes/pull/51250)) +* CSI is updated to 0.3.0 as compared to 0.2.0 in v1.10. ([#64719](https://github.com/kubernetes/kubernetes/pull/64719)) +* The dashboard add-on is the same as v1.10: v1.8.3. ([#517326](https://github.com/kubernetes/kubernetes/pull/57326)) +* Bump Heapster to v1.5.2 as compared to v1.5.0 in v1.10 ([#61396](https://github.com/kubernetes/kubernetes/pull/61396)) +* Updates Cluster Autoscaler version to v1.3.0 from v1.2.0 in v1.10. See [release notes](https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.3.0) for details. ([#65219](https://github.com/kubernetes/kubernetes/pull/65219)) +* Kube-dns has been updated to v1.14.10, as compared to v1.14.8 in v1.10 ([#62676](https://github.com/kubernetes/kubernetes/pull/62676)) +* Influxdb is unchanged from v1.10: v1.3.3 ([#53319](https://github.com/kubernetes/kubernetes/pull/53319)) +* Grafana is unchanged from v1.10: v4.4.3 ([#53319](https://github.com/kubernetes/kubernetes/pull/53319)) +* CAdvisor is v0.30.1, as opposed to v0.29.1 in v1.10 ([#64987](https://github.com/kubernetes/kubernetes/pull/64987)) +* fluentd-gcp-scaler is unchanged from v1.10: v0.3.0 ([#61269](https://github.com/kubernetes/kubernetes/pull/61269)) +* fluentd in fluentd-es-image is unchanged from 1.10: v1.1.0 ([#58525](https://github.com/kubernetes/kubernetes/pull/58525)) +* fluentd-elasticsearch is unchanged from 1.10: v2.0.4 ([#58525](https://github.com/kubernetes/kubernetes/pull/58525)) +* fluentd-gcp is unchanged from 1.10: v3.0.0. ([#60722](https://github.com/kubernetes/kubernetes/pull/60722)) +* Ingress glbc is unchanged from 1.10: v1.0.0 ([#61302](https://github.com/kubernetes/kubernetes/pull/61302)) +* OIDC authentication is unchanged from 1.10: coreos/go-oidc v2 ([#58544](https://github.com/kubernetes/kubernetes/pull/58544)) +* Calico is unchanged from 1.10: v2.6.7 ([#59130](https://github.com/kubernetes/kubernetes/pull/59130)) +* hcsshim has been updated to v0..11 ([#64272](https://github.com/kubernetes/kubernetes/pull/64272)) +* gitRepo volumes in pods no longer require git 1.8.5 or newer; older git versions are now supported. ([#62394](https://github.com/kubernetes/kubernetes/pull/62394)) +* Update crictl on GCE to v1.11.0. ([#65254](https://github.com/kubernetes/kubernetes/pull/65254)) +* CoreDNS is now v1.1.3 ([#64258](https://github.com/kubernetes/kubernetes/pull/64258)) +* Setup dns servers and search domains for Windows Pods in dockershim. Docker EE version >= 17.10.0 is required for propagating DNS to containers. ([#63905](https://github.com/kubernetes/kubernetes/pull/63905)) +* Update version of Istio addon from 0.5.1 to 0.8.0. See [full Istio release notes](https://istio.io/about/notes/0.6.html).([#64537](https://github.com/kubernetes/kubernetes/pull/64537)) +* Update cadvisor godeps to v0.30.0 ([#64800](https://github.com/kubernetes/kubernetes/pull/64800)) +* Update event-exporter to version v0.2.0 that supports old (gke_container/gce_instance) and new (k8s_container/k8s_node/k8s_pod) stackdriver resources. ([#63918](https://github.com/kubernetes/kubernetes/pull/63918)) +* Rev the Azure SDK for networking to 2017-06-01 ([#61955](https://github.com/kubernetes/kubernetes/pull/61955)) + +## Bug Fixes + +* Fixed spurious "unable to find api field" errors patching custom resources ([#63146](https://github.com/kubernetes/kubernetes/pull/63146), [@liggitt](https://github.com/liggitt)) +* Nodes are not deleted from kubernetes anymore if node is shutdown in Openstack. ([#59931](https://github.com/kubernetes/kubernetes/pull/59931), [@zetaab](https://github.com/zetaab)) +* Re-enabled nodeipam controller for external clouds. Re-enables nodeipam controller for external clouds. Also does a small refactor so that we don't need to pass in allocateNodeCidr into the controller. + ([#63049](https://github.com/kubernetes/kubernetes/pull/63049), [@andrewsykim](https://github.com/andrewsykim)) +* Fixed a configuration error when upgrading kubeadm from 1.9 to 1.10+; Kubernetes must have the same major and minor versions as the kubeadm library. ([#62568](https://github.com/kubernetes/kubernetes/pull/62568), [@liztio](https://github.com/liztio)) +* kubectl no longer renders a List as suffix kind name for CRD resources ([#62512](https://github.com/kubernetes/kubernetes/pull/62512), [@dixudx](https://github.com/dixudx)) +* Restored old behavior to the `--template` flag in `get.go`. In old releases, providing a `--template` flag value and no `--output` value implicitly assigned a default value ("go-template") to `--output`, printing using the provided template argument. +([#65377](https://github.com/kubernetes/kubernetes/pull/65377),[@juanvallejo](https://github.com/juanvallejo)) +* Ensured cloudprovider.InstanceNotFound is reported when the VM is not found on Azure ([#61531](https://github.com/kubernetes/kubernetes/pull/61531), [@feiskyer](https://github.com/feiskyer)) +* Kubernetes version command line parameter in kubeadm has been updated to drop an unnecessary redirection from ci/latest.txt to ci-cross/latest.txt. Users should know exactly where the builds are stored on Google Cloud storage buckets from now on. For example for 1.9 and 1.10, users can specify ci/latest-1.9 and ci/latest-1.10 as the CI build jobs what build images correctly updates those. The CI jobs for master update the ci-cross/latest location, so if you are looking for latest master builds, then the correct parameter to use would be ci-cross/latest. ([#63504](https://github.com/kubernetes/kubernetes/pull/63504), [@dims](https://github.cm/dims)) +* Fixes incompatibility with custom scheduler extender configurations specifying `bindVerb` ([#65424](https://github.com/kubernetes/kubernetes/pull/65424), [@liggitt](https://github.com/liggitt)) +* kubectl built for darwin from darwin now enables cgo to use the system-native C libraries for DNS resolution. Cross-compiled kubectl (e.g. from an official kubernetes release) still uses the go-native netgo DNS implementation. ([#64219](https://github.com/kubernetes/kubernetes/pull/64219), [@ixdy](https://github.com/ixdy)) +* API server properly parses propagationPolicy as a query parameter sent with a delete request ([#63414](https://github.com/kubernetes/kubernetes/pull/63414), [@roycaihw](https://github.com/roycaihw)) +* Corrected a race condition in bootstrapping aggregated cluster roles in new HA clusters ([#63761](https://github.com/kubernetes/kubernetes/pull/63761), [@liggitt](https://github.com/liggitt)) +* kubelet: fix hangs in updating Node status after network interruptions/changes between the kubelet and API server ([#63492](https://github.com/kubernetes/kubernetes/pull/63492), [@liggitt](https://github.com/liggitt)) +* Added log and fs stats for Windows containers ([#62266](https://github.com/kubernetes/kubernetes/pull/62266), [@feiskyer](https://github.com/feiskyer)) +* Fail fast if cgroups-per-qos is set on Windows ([#62984](https://github.com/kubernetes/kubernetes/pull/62984), [@feiskyer](https://github.com/feiskyer)) +* Minor fix for VolumeZoneChecker predicate, storageclass can be in annotation and spec. ([#63749](https://github.com/kubernetes/kubernetes/pull/63749), [@wenlxie](https://github.com/wenlxie)) +* Fixes issue for readOnly subpath mounts for SELinux systems and when the volume mountPath already existed in the container image. ([#64351](https://github.com/kubernetes/kubernetes/pull/64351), [@msau42](https://github.com/msau42)) +* Fixed CSI gRPC connection leak during volume operations. ([#64519](https://github.com/kubernetes/kubernetes/pull/64519), [@vladimirvivien](https://github.com/vladimirvivien)) +* Fixed error reporting of CSI volumes attachment. ([#63303](https://github.com/kubernetes/kubernetes/pull/63303), [@jsafrane](https://github.com/jsafrane)) +* Fixed SELinux relabeling of CSI volumes. ([#64026](https://github.com/kubernetes/kubernetes/pull/64026), [@jsafrane](https://github.com/jsafrane)) +* Fixed detach of already detached CSI volumes. ([#63295](https://github.com/kubernetes/kubernetes/pull/63295), [@jsafrane](https://github.com/jsafrane)) +* fix rbd device works at block mode not get mapped to container ([#64555](https://github.com/kubernetes/kubernetes/pull/64555), [@wenlxie](https://github.com/wenlxie)) +* Fixed an issue where Portworx PVCs remain in pending state when created using a StorageClass with empty parameters ([#64895](https://github.com/kubernetes/kubernetes/pull/64895), [@harsh-px](https://github.com/harsh-px)) storage +* FIX: The OpenStack cloud providers DeleteRoute method fails to delete routes when it can’t find the corresponding instance in OpenStack. (#62729, databus23) +* [fluentd-gcp addon] Increase CPU limit for fluentd to 1 core to achieve 100kb/s throughput. ([#62430](https://github.com/kubernetes/kubernetes/pull/62430), [@bmoyles0117](https://github.com/bmoyles0117)) +* GCE: Fixed operation polling to adhere to the specified interval. Furthermore, operation errors are now returned instead of ignored. ([#64630](https://github.com/kubernetes/kubernetes/pull/64630), [@nicksardo](https://github.com/nicksardo)) +* Included kms-plugin-container.manifest to master nifests tarball. ([#65035](https://github.com/kubernetes/kubernetes/pull/65035), [@immutableT](https://github.com/immutableT)) +* Fixed missing nodes lines when kubectl top nodes ([#64389](https://github.com/kubernetes/kubernetes/pull/64389), [@yue9944882](https://github.com/yue9944882)) sig-cli +* Fixed kubectl drain --timeout option when eviction is used. ([#64378](https://github.com/kubernetes/kubernetes/pull/64378), [@wrdls](https://github.com/wrdls)) sig-cli +* Fixed kubectl auth can-i exit code. It will return 1 if the user is not allowed and 0 if it's allowed. ([#59579](https://github.com/kubernetes/kubernetes/pull/59579), [@fbac](https://github.com/fbac)) +* Fixed data loss issue if using existing azure disk with partitions in disk mount ([#63270](https://github.com/kubernetes/kubernetes/pull/63270), [@andyzhangx](https://github.com/andyzhangx)) +* Fixed azure file size grow issue ([#64383](https://github.com/kubernetes/kubernetes/pull/64383), [@andyzhangx](https://github.com/andyzhangx)) +* Fixed SessionAffinity not updated issue for Azure load balancer ([#64180](https://github.com/kubernetes/kubernetes/pull/64180), [@feiskyer](https://github.com/feiskyer)) +* Fixed kube-controller-manager panic while provisioning Azure security group rules ([#64739](https://github.com/kubernetes/kubernetes/pull/64739), [@feiskyer](https://github.com/feiskyer)) +* Fixed API server panic during concurrent GET or LIST requests with non-empty `resourceVersion`. ([#65092](https://github.com/kubernetes/kubernetes/pull/65092), [@sttts](https://github.com/sttts)) +* Fixed incorrect OpenAPI schema for CustomResourceDefinition objects ([#65256](https://github.com/kubernetes/kubernetes/pull/65256), [@liggitt](https://github.com/liggitt)) +* Fixed issue where PersistentVolume.NodeAffinity.NodeSelectorTerms were ANDed instead of ORed. ([#62556](https://github.com/kubernetes/kubernetes/pull/62556), [@msau42](https://github.com/msau42)) +* Fixed potential infinite loop that can occur when NFS PVs are recycled. ([#62572](https://github.com/kubernetes/kubernetes/pull/62572), [@joelsmith](https://github.com/joelsmith)) +* Fixed column alignment when kubectl get is used with custom columns from OpenAPI schema ([#56629](https://github.com/kubernetes/kubernetes/pull/56629), [@luksa](https://github.com/luksa)) +* kubectl: restore the ability to show resource kinds when displaying multiple objects ([#61985](https://github.com/kubernetes/kubernetes/pull/61985), [@liggitt](https://github.com/liggitt)) +* Fixed a panic in `kubectl run --attach ...` when the api server failed to create the runtime object (due to name conflict, PSP restriction, etc.) ([#61713](https://github.com/kubernetes/kubernetes/pull/61713), [@mountkin](https://github.com/mountkin)) +* kube-scheduler has been fixed to use `--leader-elect` option back to true (as it was in previous versions) ([#59732](https://github.com/kubernetes/kubernetes/pull/59732), [@dims](https://github.com/dims)) +* kubectl: fixes issue with `-o yaml` and `-o json` omitting kind and apiVersion when used with `--dry-run` ([#61808](https://github.com/kubernetes/kubernetes/pull/61808), [@liggitt](https://github.com/liggitt)) +* Ensure reasons end up as comments in `kubectl edit`. ([#60990](https://github.com/kubernetes/kubernetes/pull/60990), [@bmcstdio](https://github.com/bmcstdio)) +* Fixes issue where subpath readOnly mounts failed ([#63045](https://github.com/kubernetes/kubernetes/pull/63045), [@msau42](https://github.com/msau42)) +* Fix stackdriver metrics for node memory using wrong metric type ([#63535](https://github.co/kubernetes/kubernetes/pull/63535), [@serathius](https://github.com/serathius)) +* fix mount unmount failure for a Windows pod ([#63272](https://github.com/kubernetes/kubernetes/pull/63272), [@andyzhangx](https://github.com/andyzhangx)) + +#### General Fixes and Reliability + +* Fixed a regression in kube-scheduler to properly load client connection information from a `--config` file that references a kubeconfig file. ([#65507](https://github.com/kubernetes/kubernetes/pull/65507), [@liggitt](https://github.com/liggitt)) +* Fix regression in `v1.JobSpec.backoffLimit` that caused failed Jobs to be restarted indefinitely. ([#63650](https://github.com/kubernetes/kubernetes/pull/63650), [@soltysh](https://github.com/soltysh)) +* fixes a potential deadlock in the garbage collection controller ([#64235](https://github.com/kubernetes/kubernetes/pull/64235), [@liggitt](https://github.com/liggitt)) +* fix formatAndMount func issue on Windows ([#63248](https://github.com/kubernetes/kubernetes/pull/63248), [@andyzhangx](https://github.com/andyzhangx)) +* Fix issue of colliding nodePorts when the cluster has services with externalTrafficPolicy=Local ([#64349](https://github.com/kubernetes/kubernetes/pull/64349), [@nicksardo](https://github.com/nicksardo)) +* fixes a panic applying json patches containing out of bounds operations ([#64355](https://github.com/kubernetes/kubernetes/pull/64355), [@liggitt](https://github.com/liggitt)) +* Fix incorrectly propagated ResourceVersion in ListRequests returning 0 items. ([#64150](https://github.com/kubernetes/kubernetes/pull/64150), [@wojtek-t](https://github.com/wojtek-t)) +* GCE: Fix to make the built-in `kubernetes` service properly point to the master's load balancer address in clusters that use multiple master VMs. ([#63696](https://github.com/kubernetes/kubernetes/pull/63696), [@grosskur](https://github.com/grosskur)) +* Fixes fake client generation for non-namespaced subresources ([#60445](https://github.com/kubernetes/kubernetes/pull/60445), [@jhorwit2](https://github.com/jhorwit2)) +* Schedule even if extender is not available when using extender ([#61445](https://github.com/kubernetes/kubernetes/pull/61445), [@resouer](https://github.com/resouer)) +* Fix panic create/update CRD when mutating/validating webhook configured. ([#61404](https://github.com/kubernetes/kubernetes/pull/61404), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* Pods requesting resources prefixed with `*kubernetes.io` will remain unscheduled if there are no nodes exposing that resource. ([#61860](https://github.com/kubernetes/kubernetes/pull/61860), [@mindprince](https://github.com/mindprince)) +* fix scheduling policy on ConfigMap breaks without the --policy-configmap-namespace flag set ([#61388](https://github.com/kubernetes/kubernetes/pull/61388), [@zjj2wry](https://github.com/zjj2wry)) +* Bugfix for erroneous upgrade needed messaging in kubernetes worker charm. ([#60873](https://github.com/kubernetes/kubernetes/pull/60873), [@wwwtyro](https://github.com/wwwtyro)) +* Fix inter-pod anti-affinity check to consider a pod a match when all the anti-affinity terms match. ([#62715](https://github.com/kubernetes/kubernetes/pull/62715), [@bsalamat](https://github.com/bsalamat)) +* Pod affinity `nodeSelectorTerm.matchExpressions` may now be empty, and works as previously documented: nil or empty `matchExpressions` matches no objects in scheduler. ([#62448](https://github.com/kubernetes/kubernetes/pull/62448), [@k82cn](https://github.com/k82cn)) +* Fix an issue in inter-pod affinity predicate that cause affinity to self being processed correctly ([#62591](https://github.com/kubernetes/kubernetes/pull/62591), [@bsalamat](https://github.com/bsalamat)) +* fix WaitForAttach failure issue for azure disk ([#62612](https://github.com/kubernetes/kubernetes/pull/62612), [@andyzhangx](https://github.com/andyzhangx)) +* Fix user visible files creation for windows ([#62375](https://github.com/kubernetes/kubernetes/pull/62375), [@feiskyer](https://github.com/feiskyer)) +* Fix machineID getting for vmss nodes when using instance metadata ([#62611](https://github.com/kubernetes/kubernetes/pull/62611), [@feiskyer](https://github.com/feiskyer)) +* Fix Forward chain default reject policy for IPVS proxier ([#62007](https://github.com/kubernetes/kubernetes/pull/62007), [@m1093782566](https://github.com/m1093782566)) +* fix nsenter GetFileType issue in containerized kubelet ([#62467](https://github.com/kubernetes/kubernetes/pull/62467), [@andyzhangx](https://github.com/andyzhangx)) +* Ensure expected load balancer is selected for Azure ([#62450](https://github.com/kubernetes/kubernetes/pull/62450), [@feiskyer](https://github.com/feiskyer)) +* Resolves forbidden error when the `daemon-set-controller` cluster role access `controllerrevisions` resources. ([#62146](https://github.com/kubernetes/kubernetes/pull/62146), [@frodenas](https://github.com/frodenas)) +* fix incompatible file type checking on Windows ([#62154](https://github.com/kubernetes/kubernetes/pull/62154), [@dixudx](https://github.com/dixudx)) +* fix local volume absolute path issue on Windows ([#620s18](https://github.com/kubernetes/kubernetes/pull/62018), [@andyzhangx](https://github.com/andyzhangx)) +* fix the issue that default azure disk fsypte(ext4) does not work on Windows ([#62250](https://github.com/kubernetes/kubernetes/pull/62250), [@andyzhangx](https://github.com/andyzhangx)) +* Fixed bug in rbd-nbd utility when nbd is used. ([#62168](https://github.com/kubernetes/kubernetes/pull/62168), [@piontec](https://github.com/piontec)) +* fix local volume issue on Windows ([#62012](https://github.com/kubernetes/kubernetes/pull/62012), [@andyzhangx](https://github.com/andyzhangx)) +* Fix a bug that fluentd doesn't inject container logs for CRI container runtimes (containerd, cri-o etc.) into elasticsearch on GCE. ([#61818](https://github.com/kubernetes/kubernetes/pull/61818), [@Random-Liu](https://github.com/Random-Liu)) +* flexvolume: trigger plugin init only for the relevant plugin while probe ([#58519](https://github.com/kubernetes/kubernetes/pull/58519), [@linyouchong](https://github.com/linyouchong)) +* Fixed ingress issue with CDK and pre-1.9 versions of kubernetes. ([#61859](https://github.com/kubernetes/kubernetes/pull/61859), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Fixed racy panics when using fake watches with ObjectTracker ([#61195](https://github.com/kubernetes/kubernetes/pull/61195), [@grantr](https://github.com/grantr)) +* Fixed mounting of UNIX sockets(and other special files) in subpaths ([#61480](https://github.com/kubernetes/kubernetes/pull/61480), [@gnufscied](https://github.com/gnufied)) +* Fixed [#61123](https://github.com/kubernetes/kubernetes/pull/61123) by triggering syncer.Update on all cases including when a syncer is created ([#61124](https://github.com/kubernetes/kubernetes/pull/61124), [@satyasm](https://github.com/satyasm)) +* Fixed data race in node lifecycle controller ([#60831](https://github.com/kubernetes/kubernetes/pull/60831), [@resouer](https://github.com/resouer)) +* Fixed resultRun by resetting it to 0 on pod restart ([#62853](https://github.com/kubernetes/kubernetes/pull62853), [@tony612](https://github.com/tony612)) +* Fixed the liveness probe to use `/bin/bash -c` instead of `/bin/bash c`. ([#63033](https://github.com/kubernetes/kubernetes/pull/63033), [@bmoyles0117](https://github.com/bmoyles0117)) +* Fixed scheduler informers to receive events for all the pods in the cluster. ([#63003](https://github.com/kubernetes/kubernetes/pull/63003), [@bsalamat](https://github.com/bsalamat)) +* Fixed in vSphere Cloud Provider to handle upgrades from kubernetes version less than v1.9.4 to v1.9.4 and above. ([#62919](https://github.com/kubernetes/kubernetes/pull/62919), [@abrarshivani](https://github.com/abrarshivani)) +* Fixed error where config map for Metadata Agent was not created by addon manager. ([#62909](https://github.com/kubernetes/kubernetes/pull/62909), [@kawych](https://github.com/kawych)) +* Fixed permissions to allow statefulset scaling for admins, editors, and viewers ([#62336](https://github.com/kubernetes/kubernetes/pull/62336), [@deads2k](https://github.com/deads2k)) +* GCE: Fixed for internal load balancer management resulting in backend services with outdated instance group links. ([#62885](https://github.com/kubernetes/kubernetes/pull/62885), [@nicksardo](https://github.com/nicksardo)) +* Deployment will stop adding pod-template-hash labels/selector to ReplicaSets and Pods it adopts. Resources created by Deployments are not affected (will still have pod-template-hash labels/selector). ([#61615](https://github.com/kubernetes/kubernetes/pull/61615), [@janetkuo](https://github.com/janetkuo)) +* Used inline func to ensure unlock is executed ([#61644](https://github.com/kubernetes/kubernetes/pull/61644), [@resouer](https://github.com/resouer)) +* kubernetes-master charm now properly clears the client-ca-file setting on the apiserver snap ([#61479](https://github.com/kubernetes/kubernetes/pull/61479), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Bound cloud allocator to 10 retries with 100 ms delay between retries. ([#61375](https://github.com/kubernetes/kubernetes/pull/61375), [@satyasm](https://github.com/satyasm)) +* Respect fstype in Windows for azure disk ([#61267](https://github.com/kubernetes/kubernetes/pull/61267), [@andyzhangx](https://github.com/andyzhangx)) +* Unready pods will no longer impact the number of desired replicas when using horizontal auto-scaling with external metrics or object metrics. ([#60886](https://github.com/kubernetes/kubernetes/pull/60886), [@mattjmcnaughton](https://github.com/mattjmcnaughton)) +* Removed unsafe double RLock in cpumanager ([#62464](https://github.com/kubernetes/kubernetes/pull/62464), [@choury](https://github.com/choury)) + +## Non-user-facing changes + +* Remove UID mutation from request.context. ([#63957](https://github.com/kubernetes/kubernetes/pull/63957), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* Use Patch instead of Put to sync pod status. ([#62306](https://github.com/kubernetes/kubernetes/pull/62306), [@freehan](https://github.com/freehan)) +* Allow env from resource with keys & updated tests ([#60636](https://github.com/kubernetes/kubernetes/pull/60636), [@PhilipGough](https://github.com/PhilipGough)) +* set EnableHTTPSTrafficOnly in azure storage account creation ([#64957](https://github.com/kubernetes/kubernetes/pull/64957), [@andyzhangx](https://github.com/andyzhangx)) +* New conformance test added for Watch. ([#61424](https://github.com/kubernetes/kubernetes/pull/61424), [@jennybuckley](https://github.com/jennybuckley)) +* Use DeleteOptions.PropagationPolicy instead of OrphanDependents in kubectl ([#59851](https://thub.com/kubernetes/kubernetes/pull/59851), [@nilebox](https://github.com/nilebox)) +* Add probe based mechanism for kubelet plugin discovery ([#63328](https://github.com/kubernetes/kubernetes/pull/63328), [@vikaschoudhary16](https://github.com/vikaschoudhary16)) +* keep pod state consistent when scheduler cache UpdatePod ([#64692](https://github.com/kubernetes/kubernetes/pull/64692), [@adohe](https://github.com/adohe)) +* kubectl delete does not use reapers for removing objects anymore, but relies on server-side GC entirely ([#63979](https://github.com/kubernetes/kubernetes/pull/63979), [@soltysh](https://github.com/soltysh)) +* Updated default image for nginx ingress in CDK to match current Kubernetes docs. ([#64285](https://github.com/kubernetes/kubernetes/pull/64285), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Increase scheduler cache generation number monotonically in order to avoid collision and use of stale information in scheduler. ([#63264](https://github.com/kubernetes/kubernetes/pull/63264), [@bsalamat](https://github.com/bsalamat)) +* Adding CSI driver registration code. ([#64560](https://github.com/kubernetes/kubernetes/pull/64560), [@sbezverk](https://github.com/sbezverk)) +* Do not check vmSetName when getting Azure node's IP ([#63541](https://github.com/kubernetes/kubernetes/pull/63541), [@feiskyer](https://github.com/feiskyer)) +* [fluentd-gcp addon] Update event-exporter image to have the latest base image. ([#61727](https://github.com/kubernetes/kubernetes/pull/61727), [@crassirostris](https://github.com/crassirostris)) +* Make volume usage metrics available for Cinder ([#62668](https://github.com/kubernetes/kubernetes/pull/62668), [@zetaab](https://github.com/zetaab)) +* cinder volume plugin : When the cinder volume status is `error`, controller will not do `attach ` and `detach ` operation ([#61082](https://github.com/kubernetes/kubernetes/pull/61082), [@wenlxie](https://github.com/wenlxie)) +* Allow user to scale l7 default backend deployment ([#62685](https://github.com/kubernetes/kubernetes/pull/62685), [@freehan](https://github.com/freehan)) +* Add support to ingest log entries to Stackdriver against new "k8s_container" and "k8s_node" resources. ([#62076](https://github.com/kubernetes/kubernetes/pull/62076), [@qingling128](https://github.com/qingling128)) +* Disabled CheckNodeMemoryPressure and CheckNodeDiskPressure predicates if TaintNodesByCondition enabled ([#60398](https://github.com/kubernetes/kubernetes/pull/60398), [@k82cn](https://github.com/k82cn)) +* Support custom test configuration for IPAM performance integration tests ([#61959](https://github.com/kubernetes/kubernetes/pull/61959), [@satyasm](https://github.com/satyasm)) +* OIDC authentication now allows tokens without an "email_verified" claim when using the "email" claim. If an "email_verified" claim is present when using the "email" claim, it must be `true`. ([#61508](https://github.com/kubernetes/kubernetes/pull/61508), [@rithujohn191](https://github.com/rithujohn191)) +* Add e2e test for CRD Watch ([#61025](https://github.com/kubernetes/kubernetes/pull/61025), [@ayushpateria](https://github.com/ayushpateria)) +* Return error if get NodeStageSecret and NodePublishSecret failed in CSI volume plugin ([#61096](https://github.com/kubernetes/kubernetes/pull/61096), [@mlmhl](https://github.com/mlmhl)) +* kubernetes-master charm now supports metrics server for horizontal pod autoscaler. ([#60174](https://github.com/kubernetes/kubernetes/pull/60174), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* In a GCE cluster, the default `HIRPIN_MODE` is now "hairpin-veth". ([#60166](https://github.com/kubernetes/kubernetes/pull/60166), [@rramkumar1](https://github.com/rramkumar1)) +* Balanced resource allocation priority in scheduler to include volume count on node ([#60525](https://github.com/kubernetes/kubernetes/pull/60525), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* new dhcp-domain parameter to be used for figuring out the hostname of a node ([#61890](https://github.com/kubernetes/kubernetes/pull/61890), [@dims](https://github.com/dims)) +* Disable ipamperf integration tests as part of every PR verification. ([#61863](https://github.com/kubernetes/kubernetes/pull/61863), [@satyasm](https://github.com/satyasm)) +* Enable server-side print in kubectl by default, with the ability to turn it off with --server-print=false ([#61477](https://github.com/kubernetes/kubernetes/pull/61477), [@soltysh](https://github.com/soltysh)) +* Updated admission controller settings for Juju deployed Kubernetes clusters ([#61427](https://github.com/kubernetes/kubernetes/pull/61427), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Performance test framework and basic tests for the IPAM controller, to simulate behavior of the four supported modes under lightly loaded and loaded conditions, where load is defined as the number of operations to perform as against the configured kubernetes. ([#61143](https://github.com/kubernetes/kubernetes/pull/61143), [@satyasm](https://github.com/satyasm)) +* Removed always pull policy from the template for ingress on CDK. ([#61598](https://github.com/kubernetes/kubernetes/pull/61598), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* `make test-cmd` now works on OSX. ([#61393](https://github.com/kubernetes/kubernetes/pull/61393), [@totherme](https://github.com/totherme)) +* Conformance: ReplicaSet must be supported in the `apps/v1` version. ([#61367](https://github.com/kubernetes/kubernetes/pull/61367), [@enisoc](https://github.com/enisoc)) +* Remove 'system' prefix from Metadata Agent rbac configuration ([#61394](https://github.com/kubernetes/kubernetes/pull/61394), [@kawych](https://github.com/kawych)) +* Support new NODE_OS_DISTRIBUTION 'custom' on GCE on a new add event. ([#61235](https://github.com/kubernetes/kubernetes/pull/61235), [@yguo0905](https://github.com/yguo0905)) +* include file name in the error when visiting files ([#60919](https://github.com/kubernetes/kubernetes/pull/60919), [@dixudx](https://github.com/dixudx)) +* Split PodPriority and PodPreemption feature gate ([#62243](https://github.com/kubernetes/kubernetes/pull/62243), [@resouer](https://github.com/resouer)) +* Code generated for CRDs now passes `go vet`. ([#62412](https://github.com/kubernetes/kubernetes/pull/62412), [@bhcleek](https://github.com/bhcleek)) +* "beginPort+offset" format support for port range which affects kube-proxy only ([#58731](https://github.com/kubernetes/kubernetes/pull/58731), [@yue9944882](https://github.com/yue9944882)) +* Added e2e test for watch ([#60331](https://github.com/kubernetes/kubernetes/pull/60331), [@jennybuckley](https://github.com/jennybuckley)) +* add warnings on using pod-infra-container-image for remote container runtime ([#62982](https://github.com/kubernetes/kubernetes/pull/62982), [@dixudx](https://github.com/dixudx)) +* Mount additional paths required for a working CA root, for setups where /etc/ssl/certs doesn't contains certificates but just symlink. ([#59122](https://github.com/kubernetes/kubernetes/pull/59122), [@klausenbusk](https://github.com/klausenbusk)) +* Introduce truncating audit bacnd that can be enabled for existing backend to limit the size of individual audit events and batches of events. ([#61711](https://github.com/kubernetes/kubernetes/pull/61711), [@crassirostris](https://github.com/crassirostris)) +* stop kubelet to cloud provider integration potentially wedging kubelet sync loop ([#62543](https://github.com/kubernetes/kubernetes/pull/62543), [@ingvagabund](https://github.com/ingvagabund)) +* Set pod status to "Running" if there is at least one container still reporting as "Running" status and others are "Completed". ([#62642](https://github.com/kubernetes/kubernetes/pull/62642), [@ceshihao](https://github.com/ceshihao)) +* Fix memory cgroup notifications, and reduce associated log spam. ([#63220](https://github.com/kubernetes/kubernetes/pull/63220), [@dashpole](https://github.com/dashpole)) +* Remove never used NewCronJobControllerFromClient method (#59471, dmathieu) + + +- [v1.11.0-rc.3](#v1110-rc3) +- [v1.11.0-rc.2](#v1110-rc2) +- [v1.11.0-rc.1](#v1110-rc1) +- [v1.11.0-beta.2](#v1110-beta2) +- [v1.11.0-beta.1](#v1110-beta1) +- [v1.11.0-alpha.2](#v1110-alpha2) +- [v1.11.0-alpha.1](#v1110-alpha1) + + + +# v1.11.0-rc.3 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.0-rc.3 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes.tar.gz) | `25879ba96d7baf1eb9002956cef3ee40597ed7507784262881a09c00d35ab4c6` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-src.tar.gz) | `748786c0847e278530c790f82af52797de8b5a9e494e727d0049d4b35e370327` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-darwin-386.tar.gz) | `7a3c1b89d6787e275b4b6b855237da6964145e0234b82243c7c6803f1cbd3b46` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-darwin-amd64.tar.gz) | `0265652c3d7f98e36d1d591e3e6ec5018825b6c0cd37bf65c4d043dc313279e3` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-linux-386.tar.gz) | `600d9c83ba4d2126da1cfcd0c079d97c8ede75fad61bead1135dc9e4f7e325ce` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-linux-amd64.tar.gz) | `143fdaf82480dab68b1c783ae9f21916783335f3e4eaa132d72a2c1f7b4b393f` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-linux-arm.tar.gz) | `1bf4a0823c9c8128b19a2f0a8fbaf81226a313bc35132412a9fa1d251c2af07c` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-linux-arm64.tar.gz) | `643b84a227838dd6f1dc6c874f6966e9f098b64fd7947ff940776613fa2addf0` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-linux-ppc64le.tar.gz) | `f46e1952046e977defd1a308ebe6de3ba6a710d562d17de987966a630ea2f7a3` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-linux-s390x.tar.gz) | `7ba61a3d8e6b50b238814eb086c6f9a9354342be9ac1882d0751d6cd2ce9f295` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-windows-386.tar.gz) | `587ca7b09cd45864b8093a8aa10284d473db1f528a6173cd2e58f336673aade0` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-client-windows-amd64.tar.gz) | `a8b1aac95def9f2bf54a5bbd2d83a1dd7778d0a08f1986187063a9a288a9079b` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-server-linux-amd64.tar.gz) | `d19cc5604370eb2fa826420c99dcbdbbb9bf096ea2916549a46ace990c09e20e` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-server-linux-arm.tar.gz) | `47b4ac984a855df2c78443a527705e45909da27405bb7cd8f257a5cde0314518` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-server-linux-arm64.tar.gz) | `09f8c2692f8de291c522fc96a5cbefcd60fe7a1ba9235251be11e6dda8663360` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-server-linux-ppc64le.tar.gz) | `594ff5991206887a70ec0c13624fa940f7ef4ce9cb17f9d8906f7a124a7ae4d1` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-server-linux-s390x.tar.gz) | `43a635f34ce473dcf52870e1d8fad324776d4d958b9829a3dce49eb07f8c4412` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-node-linux-amd64.tar.gz) | `b3259ed3bf2063aca9e6061cc27752adc4d787dfada4498bc4495cbc962826a2` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-node-linux-arm.tar.gz) | `9c71370709c345e4495708d8a2c03c1698f59cc9ca60678f498e895170530f9f` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-node-linux-arm64.tar.gz) | `d3d1cb767da267ebe8c03c7c6176490d5d047e33596704d099597ff50e5ae3b6` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-node-linux-ppc64le.tar.gz) | `d7c623d9ccce9cbb4c8a5d1432ac00222b54f420699d565416e09555e2cc7ff3` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-node-linux-s390x.tar.gz) | `288cd27f2e428a3e805c7fcc2c3945c0c6ee2db4812ad293e2bfd9f85bccf428` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.3/kubernetes-node-windows-amd64.tar.gz) | `991765513e0f778ec5416de456dfd709ed90a2fa97741f50dfdb0d30ee4ccbc0` + +## Changelog since v1.11.0-rc.2 + +### Other notable changes + +* Pass cluster_location argument to Heapster ([#65176](https://github.com/kubernetes/kubernetes/pull/65176), [@kawych](https://github.com/kawych)) +* Fix concurrent map access panic ([#65331](https://github.com/kubernetes/kubernetes/pull/65331), [@dashpole](https://github.com/dashpole)) + * Don't watch .mount cgroups to reduce number of inotify watches + * Fix NVML initialization race condition + * Fix brtfs disk metrics when using a subdirectory of a subvolume +* User can now use `sudo crictl` on GCE cluster. ([#65389](https://github.com/kubernetes/kubernetes/pull/65389), [@Random-Liu](https://github.com/Random-Liu)) + + + +# v1.11.0-rc.2 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.0-rc.2 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes.tar.gz) | `30742ea1e24ade88e148db872eeef58597813bc67d485c0ff6e4b7284d59500a` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-src.tar.gz) | `77e1f018820542088f1e9af453a139ae8ad0691cbde98ab01695a8f499dbe4cf` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-darwin-386.tar.gz) | `2f8777fcb938bbc310fb481a56dca62e14c27f6a85e61ab4650aeb28e5f9f05a` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-darwin-amd64.tar.gz) | `30a5ed844d2b6b6b75e19e1f68f5c18ff8ec4f268c149737a6e715bc0a6e297f` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-linux-386.tar.gz) | `e4c60f463366fdf62e9c10c45c6f6b75d63aa3bd6665a0b56c9c2e2104ea9da6` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-linux-amd64.tar.gz) | `1d62f9ac92f23897d4545ebaf15d78b13b04157d83a839e347f4bd02cc484af4` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-linux-arm.tar.gz) | `8f52c6da9f95c7e127a6945a164e66d5266ebf2f4d02261653c5dd6936ec6b00` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-linux-arm64.tar.gz) | `e6b677601f0d78cf9463a86d6cc33b4861a88d2fbf3728b9c449a216fb84578e` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-linux-ppc64le.tar.gz) | `2cd49eb1d5f6d97f1342ee7f4803e9713a9cf4bfa419c86f4e1f82182d27f535` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-linux-s390x.tar.gz) | `e8134efaea3146336b24e76ae2f6f5cdc63f6aeecc65b52cd0aae92edb8432ac` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-windows-386.tar.gz) | `226b8c687251c877d5876f95f086b131ff3f831fca01dd07caf168269ee2c51d` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-client-windows-amd64.tar.gz) | `c590a3a7f2e08f8046752b5bbc0d0b11f174f750fdd7912a68dd5335fcedc03d` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-server-linux-amd64.tar.gz) | `13c518091348c1b4355bf6b1a72514e71f68ad68a51df7d0706666c488e51158` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-server-linux-arm.tar.gz) | `d4b4fa98ece74d2cc240cf43b59629fe0115d3750d5938ae5ece972251a96018` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-server-linux-arm64.tar.gz) | `6b9e9de414619fb28dbbee05537697c2fdce130abe65372b477d3858571bfabd` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-server-linux-ppc64le.tar.gz) | `537f27284ad47d37d9ab8c4f4113b90f55948f88cd5dbab203349a34a9ddeccb` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-server-linux-s390x.tar.gz) | `71299a59bd4b7b38242631b3f441885ca9dcd99934427c8399b4f4598cc47fbb` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-node-linux-amd64.tar.gz) | `792da4aa3c06dee14b10f219591af8e967e466c5d5646d8973abfb1071cb5202` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-node-linux-arm.tar.gz) | `40a276dd0efdd6e87206d9b2a994ba49c336a455bad7076ddb22a4a6aa0a885f` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-node-linux-arm64.tar.gz) | `867504f25a864130c28f18aa5e99be0b2a8e0223ea86d46a4033e76cbe865533` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-node-linux-ppc64le.tar.gz) | `b1ff4471acf84a0d4f43854c778d6e18f8d0358da1323d1812f1d1a922b56662` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-node-linux-s390x.tar.gz) | `b527ab6ad8f7a3220e743780412c2d6c7fdaccc4eaa71ccfe90ad3e4e98d1d80` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.2/kubernetes-node-windows-amd64.tar.gz) | `1643e19c7dd5b139a6ab81768249d62392fcad5f6f2aec7edab279009368898b` + +## Changelog since v1.11.0-rc.1 + +### Other notable changes + +* Prevents a `kubectl delete` hang when deleting controller managed lists ([#65367](https://github.com/kubernetes/kubernetes/pull/65367), [@deads2k](https://github.com/deads2k)) +* fixes a memory leak in the kube-controller-manager observed when large numbers of pods with tolerations are created/deleted ([#65339](https://github.com/kubernetes/kubernetes/pull/65339), [@liggitt](https://github.com/liggitt)) +* The "kubectl cp" command now supports path shortcuts (../) in remote paths. ([#65189](https://github.com/kubernetes/kubernetes/pull/65189), [@juanvallejo](https://github.com/juanvallejo)) +* Split 'scheduling_latency_seconds' metric into finer steps (predicate, priority, premption) ([#65306](https://github.com/kubernetes/kubernetes/pull/65306), [@shyamjvs](https://github.com/shyamjvs)) +* fixed incorrect OpenAPI schema for CustomResourceDefinition objects ([#65256](https://github.com/kubernetes/kubernetes/pull/65256), [@liggitt](https://github.com/liggitt)) + + + +# v1.11.0-rc.1 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.0-rc.1 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes.tar.gz) | `f4d6126030d76f4340bf36ba02562388ea6984aa3d3f3ece39359c2a0f605b73` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-src.tar.gz) | `6383966a2bc5b252f1938fdfe4a7c35fafaa7642da22f86a017e2b718dedda92` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-darwin-386.tar.gz) | `1582a21d8e7c9ec8719a003cd79a7c51e984f2b7b703f0816af50efa4b838c6f` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-darwin-amd64.tar.gz) | `77ae2765fcac147095d2791f42b212a6c150764a311dfb6e7740a70d0c155574` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-linux-386.tar.gz) | `87f6e22ef05bcd468424b02da2a58c0d695bd875e2130cb94adb842988aa532c` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-linux-amd64.tar.gz) | `978147f7989b5669a74be5af7c6fe9b3039956c958d17dc53f65ae2364f8485c` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-linux-arm.tar.gz) | `e7e13c6f500f86641f62fcaa34715fd8aa40913fe97ac507a73a726fb6d2f3f4` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-linux-arm64.tar.gz) | `5e35f3c80f0811b252c725c938dc4803034b4925d6fa1c2f0042132fd19d6db2` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-linux-ppc64le.tar.gz) | `0cec908e2f85763e9f066661c2f12122b13901004f552729ced66673f12669da` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-linux-s390x.tar.gz) | `ae6e0d7eb75647531b224d8a873528bb951858bfddc9595771def8a26dd2a709` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-windows-386.tar.gz) | `9eaba9edce7e06c15088612b90c8adc714509cab8ba612019c960dc3fe306b9d` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-client-windows-amd64.tar.gz) | `dae41cc0be99bec6b28c8bd96eccd6c41b2d51602bc6a374dff922c34708354f` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-server-linux-amd64.tar.gz) | `73510e5be3650bdeb219e93f78b042b4c9b616cbe672c68cab2e713c13f040ca` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-server-linux-arm.tar.gz) | `00475cb20dbabbc7f1a048f0907ef1b2cf34cfacab3ad82d2d86e2afae466eca` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-server-linux-arm64.tar.gz) | `00b1a2fa9e7c6b9929e09d7e0ec9aadc3e697d7527dcda9cd7d57e89daf618f5` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-server-linux-ppc64le.tar.gz) | `6c2d303a243ca4452c19b613bc71c92222c33c9322983f9a485231a7d2471681` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-server-linux-s390x.tar.gz) | `c93d9021bd00bd1adda521e6952c72e08beebe8d994ad92cc14c741555e429a9` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-node-linux-amd64.tar.gz) | `7d84cd7f60186d59e84e4b48bc5cd25ddd0fbcef4ebb2a2a3bd06831433c0135` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-node-linux-arm.tar.gz) | `4fa046b5c0b3d860e741b33f4da722a16d4b7de9674ab6a60da2d5749b3175ef` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-node-linux-arm64.tar.gz) | `db80b1916da3262b1e3aeb658b9a9c829a76e85f97e30c5fc1b07a3ef331003a` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-node-linux-ppc64le.tar.gz) | `c693a8b7827f9098e8f407182febc24041dd396fdd66c61f8b666252fbbb342a` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-node-linux-s390x.tar.gz) | `ee5becf3f2034157e4c50488278095c3685a01b7f715693a1053fa986d983dcf` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-rc.1/kubernetes-node-windows-amd64.tar.gz) | `65f4f7a96f89c8dcba6c21e79aeac677790c8338c3f8f0e9e27fb16154d7e06f` + +## Changelog since v1.11.0-beta.2 + +### Action Required + +* A cluster-autoscaler ClusterRole is added to cover only the functionality required by Cluster Autoscaler and avoid abusing system:cluster-admin role. ([#64503](https://github.com/kubernetes/kubernetes/pull/64503), [@kgolab](https://github.com/kgolab)) + * action required: Cloud providers other than GCE might want to update their deployments or sample yaml files to reuse the role created via add-on. + +### Other notable changes + +* The "kubectl cp" command now supports path shortcuts (../) in remote paths. ([#65189](https://github.com/kubernetes/kubernetes/pull/65189), [@juanvallejo](https://github.com/juanvallejo)) +* Update crictl on GCE to v1.11.0. ([#65254](https://github.com/kubernetes/kubernetes/pull/65254), [@Random-Liu](https://github.com/Random-Liu)) +* kubeadm: Use the release-1.11 branch by default ([#65229](https://github.com/kubernetes/kubernetes/pull/65229), [@luxas](https://github.com/luxas)) +* Updates Cluster Autoscaler version to 1.3.0. Release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.3.0 ([#65219](https://github.com/kubernetes/kubernetes/pull/65219), [@aleksandra-malinowska](https://github.com/aleksandra-malinowska)) +* The deprecated `--service-account-private-key-file` flag has been removed from the cloud-controller-manager. The flag is still present and supported in the kube-controller-manager. ([#65182](https://github.com/kubernetes/kubernetes/pull/65182), [@liggitt](https://github.com/liggitt)) +* Update Cluster Autoscaler to v1.3.0-beta.2. Release notes for this version: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.3.0-beta.2 ([#65148](https://github.com/kubernetes/kubernetes/pull/65148), [@aleksandra-malinowska](https://github.com/aleksandra-malinowska)) +* Fixed API server panic during concurrent GET or LIST requests with non-empty `resourceVersion`. ([#65092](https://github.com/kubernetes/kubernetes/pull/65092), [@sttts](https://github.com/sttts)) +* Kubernetes json deserializer is now case-sensitive to restore compatibility with pre-1.8 servers. ([#65034](https://github.com/kubernetes/kubernetes/pull/65034), [@caesarxuchao](https://github.com/caesarxuchao)) + * If your config files contains fields with wrong case, the config files will be now invalid. +* GCE: Fixes operation polling to adhere to the specified interval. Furthermore, operation errors are now returned instead of ignored. ([#64630](https://github.com/kubernetes/kubernetes/pull/64630), [@nicksardo](https://github.com/nicksardo)) +* Updated hcsshim dependency to v0.6.11 ([#64272](https://github.com/kubernetes/kubernetes/pull/64272), [@jessfraz](https://github.com/jessfraz)) +* Include kms-plugin-container.manifest to master manifests tarball. ([#65035](https://github.com/kubernetes/kubernetes/pull/65035), [@immutableT](https://github.com/immutableT)) +* kubeadm - Ensure the peer port is secured by explicitly setting the peer URLs for the default etcd instance. ([#64988](https://github.com/kubernetes/kubernetes/pull/64988), [@detiber](https://github.com/detiber)) + * kubeadm - Ensure that the etcd certificates are generated using a proper CN + * kubeadm - Update generated etcd peer certificate to include localhost addresses for the default configuration. + * kubeadm - Increase the manifest update timeout to make upgrades a bit more reliable. +* Kubernetes depends on v0.30.1 of cAdvisor ([#64987](https://github.com/kubernetes/kubernetes/pull/64987), [@dashpole](https://github.com/dashpole)) +* Update Cluster Autoscaler version to 1.3.0-beta.1. Release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.3.0-beta.1 ([#64977](https://github.com/kubernetes/kubernetes/pull/64977), [@aleksandra-malinowska](https://github.com/aleksandra-malinowska)) +* Webhooks for the mutating admission controller now support "remove" operation. ([#64255](https://github.com/kubernetes/kubernetes/pull/64255), [@rojkov](https://github.com/rojkov)) +* deprecated and inactive option '--enable-custom-metrics' is removed in 1.11 ([#60699](https://github.com/kubernetes/kubernetes/pull/60699), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* kubernetes now packages cri-tools (crictl) in addition to all the other kubeadm tools in a deb and rpm. ([#64836](https://github.com/kubernetes/kubernetes/pull/64836), [@chuckha](https://github.com/chuckha)) +* Fix setup of configmap/secret/projected/downwardapi volumes ([#64855](https://github.com/kubernetes/kubernetes/pull/64855), [@gnufied](https://github.com/gnufied)) +* Setup dns servers and search domains for Windows Pods in dockershim. Docker EE version >= 17.10.0 is required for propagating DNS to containers. ([#63905](https://github.com/kubernetes/kubernetes/pull/63905), [@feiskyer](https://github.com/feiskyer)) + + + +# v1.11.0-beta.2 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.0-beta.2 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes.tar.gz) | `0addbff3fc61047460da0fca7413f4cc679fac7482c3f09aa4f4a60d8ec8dd5c` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-src.tar.gz) | `943629abc5b046cc5db280417e5cf3a8342c5f67c8deb3d7283b02de67b3a3c3` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-darwin-386.tar.gz) | `9b714bb99e9d8c51c718d9ec719412b2006c921e6a5566acf387797b57014386` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-darwin-amd64.tar.gz) | `11fc9f94c82b2adc860964be8e84ed1e17ae711329cac3c7aff58067caeeffe2` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-386.tar.gz) | `016abd161dc394ab6e1e8f57066ff413b523c71ac2af458bfc8dfa2107530910` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-amd64.tar.gz) | `f98c223c24680aae583ff63fa8e1ef49421ddd660bd748fea493841c24ad6417` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-arm.tar.gz) | `78cf5dca303314023d6f82c7570e92b814304029fb7d3941d7c04855679e120d` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-arm64.tar.gz) | `c35e03687d491d9ca955121912c56d00741c86381370ed5890b0ee8b629a3e01` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-ppc64le.tar.gz) | `4e848a58f822f971dbda607d26128d1b718fc07665d2f65b87936eec40b037b2` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-linux-s390x.tar.gz) | `ead83a70e4782efdaea3645ca2a59e51209041ce41f9d805d5c1d10f029b1cb0` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-windows-386.tar.gz) | `c357b28c83e769517d7b19e357260d62485e861005d98f84c752d109fa48bd20` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-client-windows-amd64.tar.gz) | `2ae78921a35a8a582b226521f904f0840c17e3e097364d6a3fcd10d196bec0dc` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-amd64.tar.gz) | `26bd6e05a4bf942534f0578b1cdbd11b8c868aa3331e2681734ecc93d75f6b85` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-arm.tar.gz) | `df706ccad0a235613e644eda363c49bfb858860a2ae5219b17b996f36669a7fc` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-arm64.tar.gz) | `73f3e7a82d7c78a9f03ce0c84ae4904942f0bf88b3bf045fc9b1707b686cb04e` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-ppc64le.tar.gz) | `ebeb67e45e630469d55b442d2c6092065f1c1403d1965c4340d0b6c1fa7f6676` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-server-linux-s390x.tar.gz) | `c82e6a41b8e451600fb5bfdad3addf3c35b5edb518a7bf9ebd03af0574d57975` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-amd64.tar.gz) | `e6dbd56c10fee83f400e76ae02325eda0a583347f6b965eeb610c90d664d7990` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-arm.tar.gz) | `df9d18c3af4d6ee237a238b3029823f6e90b2ae3f0d25b741d4b3fedb7ea14f8` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-arm64.tar.gz) | `d84e98702651615336256d3453516df9ad39f39400f6091d9e2b4c95b4111ede` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-ppc64le.tar.gz) | `a62037f00ab29302f72aa23116c304b676cc41a6f47f79a2faf4e4ea18059178` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-linux-s390x.tar.gz) | `bef66f2080f7ebf442234d841ec9c994089fa02b400d98e1b01021f1f66c4cd0` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.2/kubernetes-node-windows-amd64.tar.gz) | `2b029715b98c3355a172ed5a6e08e73ad4ef264c74a26ed5a3da67f90764b7dc` + +## Changelog since v1.11.0-beta.1 + +### Action Required + +* [action required] `kubeadm join` is now blocking on the kubelet performing the TLS Bootstrap properly. ([#64792](https://github.com/kubernetes/kubernetes/pull/64792), [@luxas](https://github.com/luxas)) + * Earlier, `kubeadm join` only did the discovery part and exited successfully without checking that the + * kubelet actually started properly and performed the TLS bootstrap correctly. Now, as kubeadm runs + * some post-join steps (e.g. annotating the Node API object with the CRISocket as in this PR, as a + * stop-gap until this is discoverable automatically), `kubeadm join` is now waiting for the kubelet to + * perform the TLS Bootstrap, and then uses that credential to perform further actions. This also + * improves the UX, as `kubeadm` will exit with a non-zero code if the kubelet isn't in a functional + * state, instead of pretending like everything's fine. +* [action required] The structure of the kubelet dropin in the kubeadm deb package has changed significantly. ([#64780](https://github.com/kubernetes/kubernetes/pull/64780), [@luxas](https://github.com/luxas)) + * Instead of hard-coding the parameters for the kubelet in the dropin, a structured configuration file + * for the kubelet is used, and is expected to be present in `/var/lib/kubelet/config.yaml`. + * For runtime-detected, instance-specific configuration values, a environment file with + * dynamically-generated flags at `kubeadm init` or `kubeadm join` run time is used. + * Finally, if the user wants to override something specific for the kubelet that can't be done via + * the kubeadm Configuration file (which is preferred), they might add flags to the + * `KUBELET_EXTRA_ARGS` environment variable in either `/etc/default/kubelet` + * or `/etc/sysconfig/kubelet`, depending on the system you're running on. +* [action required] The `--node-name` flag for kubeadm now dictates the Node API object name the ([#64706](https://github.com/kubernetes/kubernetes/pull/64706), [@liztio](https://github.com/liztio)) + * kubelet uses for registration, in all cases but where you might use an in-tree cloud provider. + * If you're not using an in-tree cloud provider, `--node-name` will set the Node API object name. + * If you're using an in-tree cloud provider, you MUST make `--node-name` match the name the + * in-tree cloud provider decides to use. +* [action required] kubeadm: The Token-related fields in the `MasterConfiguration` object have now been refactored. Instead of the top-level `.Token`, `.TokenTTL`, `.TokenUsages`, `.TokenGroups` fields, there is now a `BootstrapTokens` slice of `BootstrapToken` objects that support the same features under the `.Token`, `.TTL`, `.Usages`, `.Groups` fields. ([#64408](https://github.com/kubernetes/kubernetes/pull/64408), [@luxas](https://github.com/luxas)) + +### Other notable changes + +* Add Vertical Pod Autoscaler to autoscaling/v2beta1 ([#63797](https://github.com/kubernetes/kubernetes/pull/63797), [@kgrygiel](https://github.com/kgrygiel)) +* kubeadm: only run kube-proxy on architecture consistent nodes ([#64696](https://github.com/kubernetes/kubernetes/pull/64696), [@dixudx](https://github.com/dixudx)) +* kubeadm: Add a new `kubeadm upgrade node config` command ([#64624](https://github.com/kubernetes/kubernetes/pull/64624), [@luxas](https://github.com/luxas)) +* Orphan delete is now supported for custom resources ([#63386](https://github.com/kubernetes/kubernetes/pull/63386), [@roycaihw](https://github.com/roycaihw)) +* Update version of Istio addon from 0.6.0 to 0.8.0. ([#64537](https://github.com/kubernetes/kubernetes/pull/64537), [@ostromart](https://github.com/ostromart)) + * See https://istio.io/about/notes/0.8.html for full Isto release notes. +* Provides API support for external CSI storage drivers to support block volumes. ([#64723](https://github.com/kubernetes/kubernetes/pull/64723), [@vladimirvivien](https://github.com/vladimirvivien)) +* kubectl will list all allowed print formats when an invalid format is passed. ([#64371](https://github.com/kubernetes/kubernetes/pull/64371), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* Use IONice to reduce IO priority of du and find ([#64800](https://github.com/kubernetes/kubernetes/pull/64800), [@dashpole](https://github.com/dashpole)) + * cAdvisor ContainerReference no longer contains Labels. Use ContainerSpec instead. + * Fix a bug where cadvisor failed to discover a sub-cgroup that was created soon after the parent cgroup. +* Kubelet will set extended resource capacity to zero after it restarts. If the extended resource is exported by a device plugin, its capacity will change to a valid value after the device plugin re-connects with the Kubelet. If the extended resource is exported by an external component through direct node status capacity patching, the component should repatch the field after kubelet becomes ready again. During the time gap, pods previously assigned with such resources may fail kubelet admission but their controller should create new pods in response to such failures. ([#64784](https://github.com/kubernetes/kubernetes/pull/64784), [@jiayingz](https://github.com/jiayingz)) +* Introduce ContainersReady condition in Pod Status ([#64646](https://github.com/kubernetes/kubernetes/pull/64646), [@freehan](https://github.com/freehan)) +* The Sysctls experimental feature has been promoted to beta (enabled by default via the `Sysctls` feature flag). PodSecurityPolicy and Pod objects now have fields for specifying and controlling sysctls. Alpha sysctl annotations will be ignored by 1.11+ kubelets. All alpha sysctl annotations in existing deployments must be converted to API fields to be effective. ([#63717](https://github.com/kubernetes/kubernetes/pull/63717), [@ingvagabund](https://github.com/ingvagabund)) +* kubeadm now configures the etcd liveness probe correctly when etcd is listening on all interfaces ([#64670](https://github.com/kubernetes/kubernetes/pull/64670), [@stealthybox](https://github.com/stealthybox)) +* Fix regression in `v1.JobSpec.backoffLimit` that caused failed Jobs to be restarted indefinitely. ([#63650](https://github.com/kubernetes/kubernetes/pull/63650), [@soltysh](https://github.com/soltysh)) +* GCE: Update cloud provider to use TPU v1 API ([#64727](https://github.com/kubernetes/kubernetes/pull/64727), [@yguo0905](https://github.com/yguo0905)) +* Kubelet: Add security context for Windows containers ([#64009](https://github.com/kubernetes/kubernetes/pull/64009), [@feiskyer](https://github.com/feiskyer)) +* Volume topology aware dynamic provisioning ([#63193](https://github.com/kubernetes/kubernetes/pull/63193), [@lichuqiang](https://github.com/lichuqiang)) +* CoreDNS deployment configuration now uses k8s.gcr.io imageRepository ([#64775](https://github.com/kubernetes/kubernetes/pull/64775), [@rajansandeep](https://github.com/rajansandeep)) +* Updated Container Storage Interface specification version to v0.3.0 ([#64719](https://github.com/kubernetes/kubernetes/pull/64719), [@davidz627](https://github.com/davidz627)) +* Kubeadm: Make CoreDNS run in read-only mode and drop all unneeded privileges ([#64473](https://github.com/kubernetes/kubernetes/pull/64473), [@nberlee](https://github.com/nberlee)) +* Add a volume projection that is able to project service account tokens. ([#62005](https://github.com/kubernetes/kubernetes/pull/62005), [@mikedanese](https://github.com/mikedanese)) +* Fix kubectl auth can-i exit code. It will return 1 if the user is not allowed and 0 if it's allowed. ([#59579](https://github.com/kubernetes/kubernetes/pull/59579), [@fbac](https://github.com/fbac)) +* apply global flag "context" for kubectl config view --minify ([#64608](https://github.com/kubernetes/kubernetes/pull/64608), [@dixudx](https://github.com/dixudx)) +* Fix kube-controller-manager panic while provisioning Azure security group rules ([#64739](https://github.com/kubernetes/kubernetes/pull/64739), [@feiskyer](https://github.com/feiskyer)) +* API change for volume topology aware dynamic provisioning ([#63233](https://github.com/kubernetes/kubernetes/pull/63233), [@lichuqiang](https://github.com/lichuqiang)) +* Add azuredisk PV size grow feature ([#64386](https://github.com/kubernetes/kubernetes/pull/64386), [@andyzhangx](https://github.com/andyzhangx)) +* Modify e2e tests to use priorityClass beta version & switch priorityClass feature to beta ([#63724](https://github.com/kubernetes/kubernetes/pull/63724), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* Adding CSI driver registration code. ([#64560](https://github.com/kubernetes/kubernetes/pull/64560), [@sbezverk](https://github.com/sbezverk)) +* fixes a potential deadlock in the garbage collection controller ([#64235](https://github.com/kubernetes/kubernetes/pull/64235), [@liggitt](https://github.com/liggitt)) +* Fixes issue for readOnly subpath mounts for SELinux systems and when the volume mountPath already existed in the container image. ([#64351](https://github.com/kubernetes/kubernetes/pull/64351), [@msau42](https://github.com/msau42)) +* Add log and fs stats for Windows containers ([#62266](https://github.com/kubernetes/kubernetes/pull/62266), [@feiskyer](https://github.com/feiskyer)) +* client-go: credential exec plugins have been promoted to beta ([#64482](https://github.com/kubernetes/kubernetes/pull/64482), [@ericchiang](https://github.com/ericchiang)) +* Revert [#64364](https://github.com/kubernetes/kubernetes/pull/64364) to resurrect rescheduler. For More info see[#64725] https://github.com/kubernetes/kubernetes/issues/64725 and ([#64592](https://github.com/kubernetes/kubernetes/pull/64592), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* Add RequestedToCapacityRatioPriority priority function. Function is parametrized with set of points mapping node utilization (0-100) to score (0-10). ([#63929](https://github.com/kubernetes/kubernetes/pull/63929), [@losipiuk](https://github.com/losipiuk)) + * Function is linear between points. Resource utilization is defined as one minus ratio of total amount of resource requested by pods on node and node's capacity (scaled to 100). + * Final utilization used for computation is arithmetic mean of cpu utilization and memory utilization. + * Function is disabled by default and can be enabled via scheduler policy config file. + * If no parametrization is specified in config file it defaults to one which gives score 10 to utilization 0 and score 0 to utilization 100. +* `kubeadm init` detects if systemd-resolved is running and configures the kubelet to use a working resolv.conf. ([#64665](https://github.com/kubernetes/kubernetes/pull/64665), [@stealthybox](https://github.com/stealthybox)) +* fix data loss issue if using existing azure disk with partitions in disk mount ([#63270](https://github.com/kubernetes/kubernetes/pull/63270), [@andyzhangx](https://github.com/andyzhangx)) +* Meta data of CustomResources is now pruned and schema checked during deserialization of requests and when read from etcd. In the former case, invalid meta data is rejected, in the later it is dropped from the CustomResource objects. ([#64267](https://github.com/kubernetes/kubernetes/pull/64267), [@sttts](https://github.com/sttts)) +* Add Alpha support for dynamic volume limits based on node type ([#64154](https://github.com/kubernetes/kubernetes/pull/64154), [@gnufied](https://github.com/gnufied)) +* Fixed CSI gRPC connection leak during volume operations. ([#64519](https://github.com/kubernetes/kubernetes/pull/64519), [@vladimirvivien](https://github.com/vladimirvivien)) +* in-tree support for openstack credentials is now deprecated. please use the "client-keystone-auth" from the cloud-provider-openstack repository. details on how to use this new capability is documented here - https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/using-client-keystone-auth.md ([#64346](https://github.com/kubernetes/kubernetes/pull/64346), [@dims](https://github.com/dims)) +* `ScheduleDaemonSetPods` is an alpha feature (since v1.11) that causes DaemonSet Pods ([#63223](https://github.com/kubernetes/kubernetes/pull/63223), [@k82cn](https://github.com/k82cn)) + * to be scheduler by default scheduler, instead of Daemonset controller. When it is enabled, + * the `NodeAffinity` term (instead of `.spec.nodeName`) is added to the DaemonSet Pods; + * this enables the default scheduler to bind the Pod to the target host. If node affinity + * of DaemonSet Pod already exists, it will be replaced. + * DaemonSet controller will only perform these operations when creating DaemonSet Pods; + * and those operations will only modify the Pods of DaemonSet, no changes are made to the + * `.spec.template` of DaemonSet. +* fix formatAndMount func issue on Windows ([#63248](https://github.com/kubernetes/kubernetes/pull/63248), [@andyzhangx](https://github.com/andyzhangx)) +* AWS EBS, Azure Disk, GCE PD and Ceph RBD volume plugins support dynamic provisioning of raw block volumes. ([#64447](https://github.com/kubernetes/kubernetes/pull/64447), [@jsafrane](https://github.com/jsafrane)) +* kubeadm upgrade apply can now ignore version errors with --force ([#64570](https://github.com/kubernetes/kubernetes/pull/64570), [@liztio](https://github.com/liztio)) +* Adds feature gate for plugin watcher ([#64605](https://github.com/kubernetes/kubernetes/pull/64605), [@vikaschoudhary16](https://github.com/vikaschoudhary16)) +* Kubelet now proxies container streaming between apiserver and container runtime. The connection between kubelet and apiserver is authenticated. Container runtime should change streaming server to serve on localhost, to make the connection between kubelet and container runtime local. ([#64006](https://github.com/kubernetes/kubernetes/pull/64006), [@Random-Liu](https://github.com/Random-Liu)) + * In this way, the whole container streaming connection is secure. To switch back to the old behavior, set `--redirect-container-streaming=true` flag. +* TokenRequests now are required to have an expiration duration between 10 minutes and 2^32 seconds. ([#63999](https://github.com/kubernetes/kubernetes/pull/63999), [@mikedanese](https://github.com/mikedanese)) +* Expose `/debug/flags/v` to allow dynamically set glog logging level, if want to change glog level to 3, you only have to send a PUT request with like `curl -X PUT http://127.0.0.1:8080/debug/flags/v -d "3"`. ([#63777](https://github.com/kubernetes/kubernetes/pull/63777), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* New conformance test added for Watch. ([#61424](https://github.com/kubernetes/kubernetes/pull/61424), [@jennybuckley](https://github.com/jennybuckley)) +* The GitRepo volume type is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container. ([#63445](https://github.com/kubernetes/kubernetes/pull/63445), [@ericchiang](https://github.com/ericchiang)) +* kubeadm now preserves previous manifests after upgrades ([#64337](https://github.com/kubernetes/kubernetes/pull/64337), [@liztio](https://github.com/liztio)) +* Implement kubelet side online file system resizing ([#62460](https://github.com/kubernetes/kubernetes/pull/62460), [@mlmhl](https://github.com/mlmhl)) + + + +# v1.11.0-beta.1 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.11/examples) + +## Downloads for v1.11.0-beta.1 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes.tar.gz) | `3209303a10ca8dd311c500ee858b9151b43c1bb5c2b3a9fb9281722e021d6871` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-src.tar.gz) | `c2e4d3b1beb4cd0b2a775394a30da2c2949d380e57f729dc48c541069c103326` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-darwin-386.tar.gz) | `cbded4d58b3d2cbeb2e43c48c9dd359834c9c9aa376751a7f8960be45601fb40` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-darwin-amd64.tar.gz) | `ceccd21fda90b96865801053f1784d4062d69b11e2e911483223860dfe6c3a17` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-386.tar.gz) | `75c9794a7f43f891aa839b2571fa44ffced25197578adc31b4c3cb28d7fbf158` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-amd64.tar.gz) | `184905f6b8b856306483d811d015cf0b28c0703ceb372594622732da2a07989f` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-arm.tar.gz) | `2d985829499588d32483d7c6a36b3b0f2b6d4031eda31c65b066b77bc51bae66` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-arm64.tar.gz) | `268556ede751058162a42d0156f27e42e37b23d60b2485e350cffe6e1b376fa4` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-ppc64le.tar.gz) | `8859bd7a37bf5a659eb17e47d2c54d228950b2ef48243c93f11799c455789983` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-linux-s390x.tar.gz) | `90bbe2fc45ae722a05270820336b9178baaab198401bb6888e817afe6a1a304e` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-windows-386.tar.gz) | `948b01f555abfc30990345004d5ce679d4b9d0a32d699a50b6d8309040b2b2f2` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-client-windows-amd64.tar.gz) | `091e9d4e7fa611cf06d2907d159e0cc36ae8602403ad0819d62df4ddbaba6095` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-amd64.tar.gz) | `727a5e8241035d631d90f3d119a27384abe93cde14c242c4d2d1cf948f84a650` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-arm.tar.gz) | `6eb7479348e9480d9d1ee31dc991297b93e076dd21b567c595f82d45b66ef949` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-arm64.tar.gz) | `9eab5ccdfba2803a743ed12b4323ad0e8e0215779edf5752224103b6667a35c1` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-ppc64le.tar.gz) | `d86b07ee28ed3d2c0668a2737fff4b3d025d4cd7b6f1aadc85f8f13b4c12e578` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-server-linux-s390x.tar.gz) | `c2d19acb88684a52a74f469ab26874ab224023f29290865e08c86338d30dd598` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-amd64.tar.gz) | `2957bf3e9dc9cd9570597434909e5ef03e996f8443c02f9d95fa6de2cd17126f` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-arm.tar.gz) | `5995b8b9628fca9eaa92c283cfb4199ab353efa8953b980eec994f49ac3a0ebd` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-arm64.tar.gz) | `996691b3b894ec9769be1ee45c5053ff1560e3ef161de8f8b9ac067c0d3559d3` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-ppc64le.tar.gz) | `8bb7fe72ec704afa5ad96356787972144b0f7923fc68678894424f1f62da7041` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-linux-s390x.tar.gz) | `4c1f0314ad60537c8a7866b0cabdece21284ee91ae692d1999b3d5273ee7cbaf` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-beta.1/kubernetes-node-windows-amd64.tar.gz) | `158832f41cd452f93482cc8a8f1dd69cc243eb63ce3581e7f2eab2de323f6202` + +## Changelog since v1.11.0-alpha.2 + +### Action Required + +* [action required] `.NodeName` and `.CRISocket` in the `MasterConfiguration` and `NodeConfiguration` v1alpha1 API objects are now `.NodeRegistration.Name` and `.NodeRegistration.CRISocket` respectively in the v1alpha2 API. The `.NoTaintMaster` field has been removed in the v1alpha2 API. ([#64210](https://github.com/kubernetes/kubernetes/pull/64210), [@luxas](https://github.com/luxas)) +* (ACTION REQUIRED) PersisntVolumeLabel admission controller is now disabled by default. If you depend on this feature (AWS/GCE) then ensure it is added to the `--enable-admission-plugins` flag on the kube-apiserver. ([#64326](https://github.com/kubernetes/kubernetes/pull/64326), [@andrewsykim](https://github.com/andrewsykim)) +* [action required] kubeadm: The `:Etcd` struct has been refactored in the v1alpha2 API. All the options now reside under either `.Etcd.Local` or `.Etcd.External`. Automatic conversions from the v1alpha1 API are supported. ([#64066](https://github.com/kubernetes/kubernetes/pull/64066), [@luxas](https://github.com/luxas)) +* [action required] kubeadm: kubelets in kubeadm clusters now disable the readonly port (10255). If you're relying on unauthenticated access to the readonly port, please switch to using the secure port (10250). Instead, you can now use ServiceAccount tokens when talking to the secure port, which will make it easier to get access to e.g. the `/metrics` endpoint of the kubelet securely. ([#64187](https://github.com/kubernetes/kubernetes/pull/64187), [@luxas](https://github.com/luxas)) +* [action required] kubeadm: Support for `.AuthorizationModes` in the kubeadm v1alpha2 API has been removed. Instead, you can use the `.APIServerExtraArgs` and `.APIServerExtraVolumes` fields to achieve the same effect. Files using the v1alpha1 API and setting this field will be automatically upgraded to this v1alpha2 API and the information will be preserved. ([#64068](https://github.com/kubernetes/kubernetes/pull/64068), [@luxas](https://github.com/luxas)) +* [action required] The formerly publicly-available cAdvisor web UI that the kubelet ran on port 4194 by default is now turned off by default. The flag configuring what port to run this UI on `--cadvisor-port` was deprecated in v1.10. Now the default is `--cadvisor-port=0`, in other words, to not run the web server. The recommended way to run cAdvisor if you still need it, is via a DaemonSet. The `--cadvisor-port` will be removed in v1.12 ([#63881](https://github.com/kubernetes/kubernetes/pull/63881), [@luxas](https://github.com/luxas)) +* [action required] kubeadm: The `.ImagePullPolicy` field has been removed in the v1alpha2 API version. Instead it's set statically to `IfNotPresent` for all required images. If you want to always pull the latest images before cluster init (like what `Always` would do), run `kubeadm config images pull` before each `kubeadm init`. If you don't want the kubelet to pull any images at `kubeadm init` time, as you for instance don't have an internet connection, you can also run `kubeadm config images pull` before `kubeadm init` or side-load the images some other way (e.g. `docker load -i image.tar`). Having the images locally cached will result in no pull at runtime, which makes it possible to run without any internet connection. ([#64096](https://github.com/kubernetes/kubernetes/pull/64096), [@luxas](https://github.com/luxas)) +* [action required] In the new v1alpha2 kubeadm Configuration API, the `.CloudProvider` and `.PrivilegedPods` fields don't exist anymore. ([#63866](https://github.com/kubernetes/kubernetes/pull/63866), [@luxas](https://github.com/luxas)) + * Instead, you should use the out-of-tree cloud provider implementations which are beta in v1.11. + * If you have to use the legacy in-tree cloud providers, you can rearrange your config like the example below. In case you need the `cloud-config` file (located in `{cloud-config-path}`), you can mount it into the API Server and controller-manager containers using ExtraVolumes like the example below. + * If you need to use the `.PrivilegedPods` functionality, you can still edit the manifests in `/etc/kubernetes/manifests/`, and set `.SecurityContext.Privileged=true` for the apiserver and controller manager. +``` +kind: MasterConfiguration +apiVersion: kubeadm.k8s.io/v1alpha2 +apiServerExtraArgs: + cloud-provider: "{cloud}" + cloud-config: "{cloud-config-path}" +apiServerExtraVolumes: +- name: cloud + hostPath: "{cloud-config-path}" + mountPath: "{cloud-config-path}" +controllerManagerExtraArgs: + cloud-provider: "{cloud}" + cloud-config: "{cloud-config-path}" +controllerManagerExtraVolumes: +- name: cloud + hostPath: "{cloud-config-path}" + mountPath: "{cloud-config-path}" +``` +* [action required] kubeadm now uses an upgraded API version for the configuration file, `kubeadm.k8s.io/v1alpha2`. kubeadm in v1.11 will still be able to read `v1alpha1` configuration, and will automatically convert the configuration to `v1alpha2` internally and when storing the configuration in the ConfigMap in the cluster. ([#63788](https://github.com/kubernetes/kubernetes/pull/63788), [@luxas](https://github.com/luxas)) +* The annotation `service.alpha.kubernetes.io/tolerate-unready-endpoints` is deprecated. Users should use Service.spec.publishNotReadyAddresses instead. ([#63742](https://github.com/kubernetes/kubernetes/pull/63742), [@thockin](https://github.com/thockin)) +* avoid duplicate status in audit events ([#62695](https://github.com/kubernetes/kubernetes/pull/62695), [@CaoShuFeng](https://github.com/CaoShuFeng)) + +### Other notable changes + +* Remove rescheduler from master. ([#64364](https://github.com/kubernetes/kubernetes/pull/64364), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* Declare IPVS-based kube-proxy GA ([#58442](https://github.com/kubernetes/kubernetes/pull/58442), [@m1093782566](https://github.com/m1093782566)) +* kubeadm: conditionally set the kubelet cgroup driver for Docker ([#64347](https://github.com/kubernetes/kubernetes/pull/64347), [@neolit123](https://github.com/neolit123)) +* kubectl built for darwin from darwin now enables cgo to use the system-native C libraries for DNS resolution. Cross-compiled kubectl (e.g. from an official kubernetes release) still uses the go-native netgo DNS implementation. ([#64219](https://github.com/kubernetes/kubernetes/pull/64219), [@ixdy](https://github.com/ixdy)) +* AWS EBS volumes can be now used as ReadOnly in pods. ([#64403](https://github.com/kubernetes/kubernetes/pull/64403), [@jsafrane](https://github.com/jsafrane)) +* Exec authenticator plugin supports TLS client certificates. ([#61803](https://github.com/kubernetes/kubernetes/pull/61803), [@awly](https://github.com/awly)) +* Use Patch instead of Put to sync pod status ([#62306](https://github.com/kubernetes/kubernetes/pull/62306), [@freehan](https://github.com/freehan)) +* kubectl apply --prune supports CronJob resource. ([#62991](https://github.com/kubernetes/kubernetes/pull/62991), [@tomoe](https://github.com/tomoe)) +* Label ExternalEtcdClientCertificates can be used for ignoring all preflight check issues related to client certificate files for external etcd. ([#64269](https://github.com/kubernetes/kubernetes/pull/64269), [@kad](https://github.com/kad)) +* Provide a meaningful error message in openstack cloud provider when no valid IP address can be found for a node ([#64318](https://github.com/kubernetes/kubernetes/pull/64318), [@gonzolino](https://github.com/gonzolino)) +* kubeadm: Add a 'kubeadm config migrate' command to convert old API types to their newer counterparts in the new, supported API types. This is just a client-side tool, it just executes locally without requiring a cluster to be running. You can think about this as an Unix pipe that upgrades config files. ([#64232](https://github.com/kubernetes/kubernetes/pull/64232), [@luxas](https://github.com/luxas)) +* The --dry-run flag has been enabled for kubectl auth reconcile ([#64458](https://github.com/kubernetes/kubernetes/pull/64458), [@mrogers950](https://github.com/mrogers950)) +* Add probe based mechanism for kubelet plugin discovery ([#63328](https://github.com/kubernetes/kubernetes/pull/63328), [@vikaschoudhary16](https://github.com/vikaschoudhary16)) +* Add Establishing Controller on CRDs to avoid race between Established condition and CRs actually served. In HA setups, the Established condition is delayed by 5 seconds. ([#63068](https://github.com/kubernetes/kubernetes/pull/63068), [@xmudrii](https://github.com/xmudrii)) +* CoreDNS is now v1.1.3 ([#64258](https://github.com/kubernetes/kubernetes/pull/64258), [@rajansandeep](https://github.com/rajansandeep)) +* kubeadm will pull required images during preflight checks if it cannot find them on the system ([#64105](https://github.com/kubernetes/kubernetes/pull/64105), [@chuckha](https://github.com/chuckha)) +* kubeadm: rename the addon parameter `kube-dns` to `coredns` for `kubeadm alpha phases addons` as CoreDNS is now the default DNS server in 1.11. ([#64274](https://github.com/kubernetes/kubernetes/pull/64274), [@neolit123](https://github.com/neolit123)) +* kubeadm: when starting the API server use the arguments --enable-admission-plugins and --disable-admission-plugins instead of the deprecated --admission-control. ([#64165](https://github.com/kubernetes/kubernetes/pull/64165), [@neolit123](https://github.com/neolit123)) +* Add spec.additionalPrinterColumns to CRDs to define server side printing columns. ([#60991](https://github.com/kubernetes/kubernetes/pull/60991), [@sttts](https://github.com/sttts)) +* fix azure file size grow issue ([#64383](https://github.com/kubernetes/kubernetes/pull/64383), [@andyzhangx](https://github.com/andyzhangx)) +* Fix issue of colliding nodePorts when the cluster has services with externalTrafficPolicy=Local ([#64349](https://github.com/kubernetes/kubernetes/pull/64349), [@nicksardo](https://github.com/nicksardo)) +* fixes a panic applying json patches containing out of bounds operations ([#64355](https://github.com/kubernetes/kubernetes/pull/64355), [@liggitt](https://github.com/liggitt)) +* Fail fast if cgroups-per-qos is set on Windows ([#62984](https://github.com/kubernetes/kubernetes/pull/62984), [@feiskyer](https://github.com/feiskyer)) +* Move Volume expansion to Beta ([#64288](https://github.com/kubernetes/kubernetes/pull/64288), [@gnufied](https://github.com/gnufied)) +* kubectl delete does not use reapers for removing objects anymore, but relies on server-side GC entirely ([#63979](https://github.com/kubernetes/kubernetes/pull/63979), [@soltysh](https://github.com/soltysh)) +* Basic plumbing for volume topology aware dynamic provisioning ([#63232](https://github.com/kubernetes/kubernetes/pull/63232), [@lichuqiang](https://github.com/lichuqiang)) +* API server properly parses propagationPolicy as a query parameter sent with a delete request ([#63414](https://github.com/kubernetes/kubernetes/pull/63414), [@roycaihw](https://github.com/roycaihw)) +* Property `serverAddressByClientCIDRs` in `metav1.APIGroup` (discovery API) now become optional instead of required ([#61963](https://github.com/kubernetes/kubernetes/pull/61963), [@roycaihw](https://github.com/roycaihw)) +* The dynamic Kubelet config feature is now beta, and the DynamicKubeletConfig feature gate is on by default. In order to use dynamic Kubelet config, ensure that the Kubelet's --dynamic-config-dir option is set. ([#64275](https://github.com/kubernetes/kubernetes/pull/64275), [@mtaufen](https://github.com/mtaufen)) +* Add reason message logs for non-exist Azure resources ([#64248](https://github.com/kubernetes/kubernetes/pull/64248), [@feiskyer](https://github.com/feiskyer)) +* Fix SessionAffinity not updated issue for Azure load balancer ([#64180](https://github.com/kubernetes/kubernetes/pull/64180), [@feiskyer](https://github.com/feiskyer)) +* The kube-apiserver openapi doc now includes extensions identifying APIService and CustomResourceDefinition kinds ([#64174](https://github.com/kubernetes/kubernetes/pull/64174), [@liggitt](https://github.com/liggitt)) +* apiservices/status and certificatesigningrequests/status now support GET and PATCH ([#64063](https://github.com/kubernetes/kubernetes/pull/64063), [@roycaihw](https://github.com/roycaihw)) +* kubectl: This client version requires the `apps/v1` APIs, so it will not work against a cluster version older than v1.9.0. Note that kubectl only guarantees compatibility with clusters that are +/-1 minor version away. ([#61419](https://github.com/kubernetes/kubernetes/pull/61419), [@enisoc](https://github.com/enisoc)) +* Correct the way we reset containers and pods in kubeadm via crictl ([#63862](https://github.com/kubernetes/kubernetes/pull/63862), [@runcom](https://github.com/runcom)) +* Allow env from resource with keys & updated tests ([#60636](https://github.com/kubernetes/kubernetes/pull/60636), [@PhilipGough](https://github.com/PhilipGough)) +* The kubelet certificate rotation feature can now be enabled via the `.RotateCertificates` field in the kubelet's config file. The `--rotate-certificates` flag is now deprecated, and will be removed in a future release. ([#63912](https://github.com/kubernetes/kubernetes/pull/63912), [@luxas](https://github.com/luxas)) +* Use DeleteOptions.PropagationPolicy instead of OrphanDependents in kubectl ([#59851](https://github.com/kubernetes/kubernetes/pull/59851), [@nilebox](https://github.com/nilebox)) +* add block device support for azure disk ([#63841](https://github.com/kubernetes/kubernetes/pull/63841), [@andyzhangx](https://github.com/andyzhangx)) +* Fix incorrectly propagated ResourceVersion in ListRequests returning 0 items. ([#64150](https://github.com/kubernetes/kubernetes/pull/64150), [@wojtek-t](https://github.com/wojtek-t)) +* Changes ext3/ext4 volume creation to not reserve any portion of the volume for the root user. ([#64102](https://github.com/kubernetes/kubernetes/pull/64102), [@atombender](https://github.com/atombender)) +* Add CRD Versioning with NOP converter ([#63830](https://github.com/kubernetes/kubernetes/pull/63830), [@mbohlool](https://github.com/mbohlool)) +* adds a kubectl wait command ([#64034](https://github.com/kubernetes/kubernetes/pull/64034), [@deads2k](https://github.com/deads2k)) +* "kubeadm init" now writes a structured and versioned kubelet ComponentConfiguration file to `/var/lib/kubelet/config.yaml` and an environment file with runtime flags (you can source this file in the systemd kubelet dropin) to `/var/lib/kubelet/kubeadm-flags.env`. ([#63887](https://github.com/kubernetes/kubernetes/pull/63887), [@luxas](https://github.com/luxas)) +* `kubectl auth reconcile` only works with rbac.v1 ([#63967](https://github.com/kubernetes/kubernetes/pull/63967), [@deads2k](https://github.com/deads2k)) +* The dynamic Kubelet config feature will now update config in the event of a ConfigMap mutation, which reduces the chance for silent config skew. Only name, namespace, and kubeletConfigKey may now be set in Node.Spec.ConfigSource.ConfigMap. The least disruptive pattern for config management is still to create a new ConfigMap and incrementally roll out a new Node.Spec.ConfigSource. ([#63221](https://github.com/kubernetes/kubernetes/pull/63221), [@mtaufen](https://github.com/mtaufen)) +* Graduate CRI container log rotation to beta, and enable it by default. ([#64046](https://github.com/kubernetes/kubernetes/pull/64046), [@yujuhong](https://github.com/yujuhong)) +* APIServices with kube-like versions (e.g. v1, v2beta1, etc.) will be sorted appropriately within each group. ([#64004](https://github.com/kubernetes/kubernetes/pull/64004), [@mbohlool](https://github.com/mbohlool)) +* kubectl and client-go now detects duplicated name for user, cluster and context when loading kubeconfig and reports error ([#60464](https://github.com/kubernetes/kubernetes/pull/60464), [@roycaihw](https://github.com/roycaihw)) +* event object references with apiversion will now report an apiversion. ([#63913](https://github.com/kubernetes/kubernetes/pull/63913), [@deads2k](https://github.com/deads2k)) +* Subresources for custom resources is now beta and enabled by default. With this, updates to the `/status` subresource will disallow updates to all fields other than `.status` (not just `.spec` and `.metadata` as before). Also, `required` can be used at the root of the CRD OpenAPI validation schema when the `/status` subresource is enabled. ([#63598](https://github.com/kubernetes/kubernetes/pull/63598), [@nikhita](https://github.com/nikhita)) +* increase grpc client default response size ([#63977](https://github.com/kubernetes/kubernetes/pull/63977), [@runcom](https://github.com/runcom)) +* HTTP transport now uses `context.Context` to cancel dial operations. k8s.io/client-go/transport/Config struct has been updated to accept a function with a `context.Context` parameter. This is a breaking change if you use this field in your code. ([#60012](https://github.com/kubernetes/kubernetes/pull/60012), [@ash2k](https://github.com/ash2k)) +* Adds a mechanism in vSphere Cloud Provider to get credentials from Kubernetes secrets ([#63902](https://github.com/kubernetes/kubernetes/pull/63902), [@abrarshivani](https://github.com/abrarshivani)) +* kubeadm: A `kubeadm config print-default` command has now been added that you can use as a starting point when writing your own kubeadm configuration files ([#63969](https://github.com/kubernetes/kubernetes/pull/63969), [@luxas](https://github.com/luxas)) +* Update event-exporter to version v0.2.0 that supports old (gke_container/gce_instance) and new (k8s_container/k8s_node/k8s_pod) stackdriver resources. ([#63918](https://github.com/kubernetes/kubernetes/pull/63918), [@cezarygerard](https://github.com/cezarygerard)) +* Cluster Autoscaler 1.2.2 (release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.2.2) ([#63974](https://github.com/kubernetes/kubernetes/pull/63974), [@aleksandra-malinowska](https://github.com/aleksandra-malinowska)) +* Update kubeadm's minimum supported kubernetes in v1.11.x to 1.10 ([#63920](https://github.com/kubernetes/kubernetes/pull/63920), [@dixudx](https://github.com/dixudx)) +* Add 'UpdateStrategyType' and 'RollingUpdateStrategy' to 'kubectl describe sts' command output. ([#63844](https://github.com/kubernetes/kubernetes/pull/63844), [@tossmilestone](https://github.com/tossmilestone)) +* Remove UID mutation from request.context. ([#63957](https://github.com/kubernetes/kubernetes/pull/63957), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* kubeadm has removed `.Etcd.SelfHosting` from its configuration API. It was never used in practice. ([#63871](https://github.com/kubernetes/kubernetes/pull/63871), [@luxas](https://github.com/luxas)) +* list/watch API requests with a fieldSelector that specifies `metadata.name` can now be authorized as requests for an individual named resource ([#63469](https://github.com/kubernetes/kubernetes/pull/63469), [@wojtek-t](https://github.com/wojtek-t)) +* Add a way to pass extra arguments to etcd. ([#63961](https://github.com/kubernetes/kubernetes/pull/63961), [@mborsz](https://github.com/mborsz)) +* minor fix for VolumeZoneChecker predicate, storageclass can be in annotation and spec. ([#63749](https://github.com/kubernetes/kubernetes/pull/63749), [@wenlxie](https://github.com/wenlxie)) +* vSphere Cloud Provider: add SAML token authentication support ([#63824](https://github.com/kubernetes/kubernetes/pull/63824), [@dougm](https://github.com/dougm)) +* adds the `kubeadm upgrade diff` command to show how static pod manifests will be changed by an upgrade. ([#63930](https://github.com/kubernetes/kubernetes/pull/63930), [@liztio](https://github.com/liztio)) +* Fix memory cgroup notifications, and reduce associated log spam. ([#63220](https://github.com/kubernetes/kubernetes/pull/63220), [@dashpole](https://github.com/dashpole)) +* Adds a `kubeadm config images pull` command to pull container images used by kubeadm. ([#63833](https://github.com/kubernetes/kubernetes/pull/63833), [@chuckha](https://github.com/chuckha)) +* Restores the pre-1.10 behavior of the openstack cloud provider which uses the instance name as the Kubernetes Node name. This requires instances be named with RFC-1123 compatible names. ([#63903](https://github.com/kubernetes/kubernetes/pull/63903), [@liggitt](https://github.com/liggitt)) +* Added support for NFS relations on kubernetes-worker charm. ([#63817](https://github.com/kubernetes/kubernetes/pull/63817), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Stop using InfluxDB as default cluster monitoring ([#62328](https://github.com/kubernetes/kubernetes/pull/62328), [@serathius](https://github.com/serathius)) + * InfluxDB cluster monitoring is deprecated and will be removed in v1.12 +* GCE: Fix to make the built-in `kubernetes` service properly point to the master's load balancer address in clusters that use multiple master VMs. ([#63696](https://github.com/kubernetes/kubernetes/pull/63696), [@grosskur](https://github.com/grosskur)) +* Kubernetes cluster on GCE have crictl installed now. Users can use it to help debug their node. The documentation of crictl can be found https://github.com/kubernetes-incubator/cri-tools/blob/master/docs/crictl.md. ([#63357](https://github.com/kubernetes/kubernetes/pull/63357), [@Random-Liu](https://github.com/Random-Liu)) +* The NodeRestriction admission plugin now prevents kubelets from modifying/removing taints applied to their Node API object. ([#63167](https://github.com/kubernetes/kubernetes/pull/63167), [@liggitt](https://github.com/liggitt)) +* The status of dynamic Kubelet config is now reported via Node.Status.Config, rather than the KubeletConfigOk node condition. ([#63314](https://github.com/kubernetes/kubernetes/pull/63314), [@mtaufen](https://github.com/mtaufen)) +* kubeadm now checks that IPv4/IPv6 forwarding is enabled ([#63872](https://github.com/kubernetes/kubernetes/pull/63872), [@kad](https://github.com/kad)) +* kubeadm will now deploy CoreDNS by default instead of KubeDNS ([#63509](https://github.com/kubernetes/kubernetes/pull/63509), [@detiber](https://github.com/detiber)) +* This PR will leverage subtests on the existing table tests for the scheduler units. ([#63658](https://github.com/kubernetes/kubernetes/pull/63658), [@xchapter7x](https://github.com/xchapter7x)) + * Some refactoring of error/status messages and functions to align with new approach. +* kubeadm upgrade now supports external etcd setups again ([#63495](https://github.com/kubernetes/kubernetes/pull/63495), [@detiber](https://github.com/detiber)) +* fix mount unmount failure for a Windows pod ([#63272](https://github.com/kubernetes/kubernetes/pull/63272), [@andyzhangx](https://github.com/andyzhangx)) +* CRI: update documents for container logpath. The container log path has been changed from containername_attempt#.log to containername/attempt#.log ([#62015](https://github.com/kubernetes/kubernetes/pull/62015), [@feiskyer](https://github.com/feiskyer)) +* Create a new `dryRun` query parameter for mutating endpoints. If the parameter is set, then the query will be rejected, as the feature is not implemented yet. This will allow forward compatibility with future clients; otherwise, future clients talking with older apiservers might end up modifying a resource even if they include the `dryRun` query parameter. ([#63557](https://github.com/kubernetes/kubernetes/pull/63557), [@apelisse](https://github.com/apelisse)) +* kubelet: fix hangs in updating Node status after network interruptions/changes between the kubelet and API server ([#63492](https://github.com/kubernetes/kubernetes/pull/63492), [@liggitt](https://github.com/liggitt)) +* The `PriorityClass` API is promoted to `scheduling.k8s.io/v1beta1` ([#63100](https://github.com/kubernetes/kubernetes/pull/63100), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* Services can listen on same host ports on different interfaces with --nodeport-addresses specified ([#62003](https://github.com/kubernetes/kubernetes/pull/62003), [@m1093782566](https://github.com/m1093782566)) +* kubeadm will no longer generate an unused etcd CA and certificates when configured to use an external etcd cluster. ([#63806](https://github.com/kubernetes/kubernetes/pull/63806), [@detiber](https://github.com/detiber)) +* corrects a race condition in bootstrapping aggregated cluster roles in new HA clusters ([#63761](https://github.com/kubernetes/kubernetes/pull/63761), [@liggitt](https://github.com/liggitt)) +* Adding initial Korean translation for kubectl ([#62040](https://github.com/kubernetes/kubernetes/pull/62040), [@ianychoi](https://github.com/ianychoi)) +* Report node DNS info with --node-ip flag ([#63170](https://github.com/kubernetes/kubernetes/pull/63170), [@micahhausler](https://github.com/micahhausler)) +* The old dynamic client has been replaced by a new one. The previous dynamic client will exist for one release in `client-go/deprecated-dynamic`. Switch as soon as possible. ([#63446](https://github.com/kubernetes/kubernetes/pull/63446), [@deads2k](https://github.com/deads2k)) +* CustomResourceDefinitions Status subresource now supports GET and PATCH ([#63619](https://github.com/kubernetes/kubernetes/pull/63619), [@roycaihw](https://github.com/roycaihw)) +* Re-enable nodeipam controller for external clouds. ([#63049](https://github.com/kubernetes/kubernetes/pull/63049), [@andrewsykim](https://github.com/andrewsykim)) +* Removes a preflight check for kubeadm that validated custom kube-apiserver, kube-controller-manager and kube-scheduler arguments. ([#63673](https://github.com/kubernetes/kubernetes/pull/63673), [@chuckha](https://github.com/chuckha)) +* Adds a list-images subcommand to kubeadm that lists required images for a kubeadm install. ([#63450](https://github.com/kubernetes/kubernetes/pull/63450), [@chuckha](https://github.com/chuckha)) +* Apply pod name and namespace labels to pod cgroup in cAdvisor metrics ([#63406](https://github.com/kubernetes/kubernetes/pull/63406), [@derekwaynecarr](https://github.com/derekwaynecarr)) +* try to read openstack auth config from client config and fall back to read from the environment variables if not available ([#60200](https://github.com/kubernetes/kubernetes/pull/60200), [@dixudx](https://github.com/dixudx)) +* GC is now bound by QPS (it wasn't before) and so if you need more QPS to avoid ratelimiting GC, you'll have to set it. ([#63657](https://github.com/kubernetes/kubernetes/pull/63657), [@shyamjvs](https://github.com/shyamjvs)) +* The Kubelet's deprecated --allow-privileged flag now defaults to true. This enables users to stop setting --allow-privileged in order to transition to PodSecurityPolicy. Previously, users had to continue setting --allow-privileged, because the default was false. ([#63442](https://github.com/kubernetes/kubernetes/pull/63442), [@mtaufen](https://github.com/mtaufen)) +* You must now specify Node.Spec.ConfigSource.ConfigMap.KubeletConfigKey when using dynamic Kubelet config to tell the Kubelet which key of the ConfigMap identifies its config file. ([#59847](https://github.com/kubernetes/kubernetes/pull/59847), [@mtaufen](https://github.com/mtaufen)) +* Kubernetes version command line parameter in kubeadm has been updated to drop an unnecessary redirection from ci/latest.txt to ci-cross/latest.txt. Users should know exactly where the builds are stored on Google Cloud storage buckets from now on. For example for 1.9 and 1.10, users can specify ci/latest-1.9 and ci/latest-1.10 as the CI build jobs what build images correctly updates those. The CI jobs for master update the ci-cross/latest location, so if you are looking for latest master builds, then the correct parameter to use would be ci-cross/latest. ([#63504](https://github.com/kubernetes/kubernetes/pull/63504), [@dims](https://github.com/dims)) +* Search standard KubeConfig file locations when using `kubeadm token` without `--kubeconfig`. ([#62850](https://github.com/kubernetes/kubernetes/pull/62850), [@neolit123](https://github.com/neolit123)) +* Include the list of security groups when failing with the errors that more then one is tagged ([#58874](https://github.com/kubernetes/kubernetes/pull/58874), [@sorenmat](https://github.com/sorenmat)) +* Allow "required" to be used at the CRD OpenAPI validation schema when the /status subresource is enabled. ([#63533](https://github.com/kubernetes/kubernetes/pull/63533), [@sttts](https://github.com/sttts)) +* When updating /status subresource of a custom resource, only the value at the `.status` subpath for the update is considered. ([#63385](https://github.com/kubernetes/kubernetes/pull/63385), [@CaoShuFeng](https://github.com/CaoShuFeng)) +* Supported nodeSelector.matchFields (node's `metadata.node`) in scheduler. ([#62453](https://github.com/kubernetes/kubernetes/pull/62453), [@k82cn](https://github.com/k82cn)) +* Do not check vmSetName when getting Azure node's IP ([#63541](https://github.com/kubernetes/kubernetes/pull/63541), [@feiskyer](https://github.com/feiskyer)) +* Fix stackdriver metrics for node memory using wrong metric type ([#63535](https://github.com/kubernetes/kubernetes/pull/63535), [@serathius](https://github.com/serathius)) +* [fluentd-gcp addon] Use the logging agent's node name as the metadata agent URL. ([#63353](https://github.com/kubernetes/kubernetes/pull/63353), [@bmoyles0117](https://github.com/bmoyles0117)) +* `kubectl cp` supports completion. ([#60371](https://github.com/kubernetes/kubernetes/pull/60371), [@superbrothers](https://github.com/superbrothers)) +* Azure VMSS: support VM names to contain the `_` character ([#63526](https://github.com/kubernetes/kubernetes/pull/63526), [@djsly](https://github.com/djsly)) +* OpenStack built-in cloud provider is now deprecated. Please use the external cloud provider for OpenStack. ([#63524](https://github.com/kubernetes/kubernetes/pull/63524), [@dims](https://github.com/dims)) +* the shortcuts which were moved server-side in at least 1.9 have been removed from being hardcoded in kubectl ([#63507](https://github.com/kubernetes/kubernetes/pull/63507), [@deads2k](https://github.com/deads2k)) +* Fixes fake client generation for non-namespaced subresources ([#60445](https://github.com/kubernetes/kubernetes/pull/60445), [@jhorwit2](https://github.com/jhorwit2)) +* `kubectl delete` with selection criteria defaults to ignoring not found errors ([#63490](https://github.com/kubernetes/kubernetes/pull/63490), [@deads2k](https://github.com/deads2k)) +* Increase scheduler cache generation number monotonically in order to avoid collision and use of stale information in scheduler. ([#63264](https://github.com/kubernetes/kubernetes/pull/63264), [@bsalamat](https://github.com/bsalamat)) +* Fixes issue where subpath readOnly mounts failed ([#63045](https://github.com/kubernetes/kubernetes/pull/63045), [@msau42](https://github.com/msau42)) +* Update to use go1.10.2 ([#63412](https://github.com/kubernetes/kubernetes/pull/63412), [@praseodym](https://github.com/praseodym)) +* `kubectl create [secret | configmap] --from-file` now works on Windows with fully-qualified paths ([#63439](https://github.com/kubernetes/kubernetes/pull/63439), [@liggitt](https://github.com/liggitt)) +* kube-apiserver: the default `--endpoint-reconciler-type` is now `lease`. The `master-count` endpoint reconciler type is deprecated and will be removed in 1.13. ([#63383](https://github.com/kubernetes/kubernetes/pull/63383), [@liggitt](https://github.com/liggitt)) +* owner references can be set during creation without deletion power ([#63403](https://github.com/kubernetes/kubernetes/pull/63403), [@deads2k](https://github.com/deads2k)) +* Lays groundwork for OIDC distributed claims handling in the apiserver authentication token checker. ([#63213](https://github.com/kubernetes/kubernetes/pull/63213), [@filmil](https://github.com/filmil)) + * A distributed claim allows the OIDC provider to delegate a claim to a + * separate URL. Distributed claims are of the form as seen below, and are + * defined in the OIDC Connect Core 1.0, section 5.6.2. + * For details, see: + * http://openid.net/specs/openid-connect-core-1_0.html#AggregatedDistributedClaims +* Use /usr/bin/env in all script shebangs to increase portability. ([#62657](https://github.com/kubernetes/kubernetes/pull/62657), [@matthyx](https://github.com/matthyx)) + + + +# v1.11.0-alpha.2 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/master/examples) + +## Downloads for v1.11.0-alpha.2 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes.tar.gz) | `8f352d4f44b0c539cfb4fb72a64098c155771916cff31642b131f1eb7879da20` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-src.tar.gz) | `d2de8df039fd3bd997c992abedb0353e37691053bd927627c6438ad654055f80` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-darwin-386.tar.gz) | `ca70a374de0c3be4897d913f6ad22e426c6336837be6debff3cbf5f3fcf4b3ae` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-darwin-amd64.tar.gz) | `d6e0e6f286ef20a54047038b337b8a47f6cbd105b69917137c5c30c8fbee006f` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-linux-386.tar.gz) | `6e73e49fa99391e1474d63a102f3cf758ef84b781bc0c0de42f1e5d1cc89132b` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-linux-amd64.tar.gz) | `1c0c7a7aefabcda0d0407dfadd2ee7e379b395ae4ad1671535d99305e72eb2ae` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-linux-arm.tar.gz) | `e6310653c31114efe32db29aa06c2c1530c285cda4cccc30edf4926d0417a3a6` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-linux-arm64.tar.gz) | `188312f25a53cf30f8375ab5727e64067ede4fba53823c3a4e2e4b768938244e` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-linux-ppc64le.tar.gz) | `875f77e17c3236dde0d6e5f302c52a5193f1bf1d79d72115ae1c6de5f494b0a3` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-linux-s390x.tar.gz) | `18502d6bd9fb483c3a858d73e2d55e32b946cbb351e09788671aca6010e39ba8` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-windows-386.tar.gz) | `f0e83868dd731365b8e3f95fe33622a59d0b67d97907089c2a1c56a8eca8ebf7` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-client-windows-amd64.tar.gz) | `571898fd6f612d75c9cfb248875cefbe9761155f3e8c7df48fce389606414028` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-server-linux-amd64.tar.gz) | `1f36c8bb40050d4371f0d8362e8fad9d60c39c5f7f9e5569ec70d0731c9dd438` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-server-linux-arm.tar.gz) | `f503c149c1aaef2df9fea146524c4f2cb505a1946062959d1acf8bc399333437` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-server-linux-arm64.tar.gz) | `660d282c18e2988744d902cb2c9f3b962b3418cbfae3644e3ea854835ca19d32` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-server-linux-ppc64le.tar.gz) | `0682060c38c704c710cc42a887b40e26726fad9cb23368ef44236527c2a7858f` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-server-linux-s390x.tar.gz) | `319337deee4e12e30da57ca484ef435f280a36792c2e2e3cd3515079b911281a` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-node-linux-amd64.tar.gz) | `8d111b862d4cb3490d5ee2b97acd439e10408cba0c7f04c98a9f0470a4869e20` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-node-linux-arm.tar.gz) | `e04a30445bdabc0b895e036497fdebd102c39a53660108e45c870ae7ebc6dced` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-node-linux-arm64.tar.gz) | `5fea9ce404e76e7d32c06aa2e1fbf2520531901c16a2e5f0047712d0a9422e42` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-node-linux-ppc64le.tar.gz) | `fc6e0568f5f72790d14260ff70fe0802490a3772ed9aef2723952d706ef0fa3d` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-node-linux-s390x.tar.gz) | `54f97b09c5adb4657e48fda59a9f4657386b0aa4be787c188eef1ece41bd4eb8` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.2/kubernetes-node-windows-amd64.tar.gz) | `72dbc9c474b15cc70e7d806cd0f78f10af1f9a7b4a11f014167f1d47277154cf` + +## Changelog since v1.11.0-alpha.1 + +### Other notable changes + +* `kubeadm upgrade plan` now accepts a version which improves the UX nicer in air-gapped environments. ([#63201](https://github.com/kubernetes/kubernetes/pull/63201), [@chuckha](https://github.com/chuckha)) +* kubectl now supports --field-selector for `delete`, `label`, and `annotate` ([#60717](https://github.com/kubernetes/kubernetes/pull/60717), [@liggitt](https://github.com/liggitt)) +* kube-apiserver: `--endpoint-reconciler-type` now defaults to `lease`. The `master-count` reconciler is deprecated and will be removed in 1.13. ([#58474](https://github.com/kubernetes/kubernetes/pull/58474), [@rphillips](https://github.com/rphillips)) +* OpenStack cloudprovider: Fix deletion of orphaned routes ([#62729](https://github.com/kubernetes/kubernetes/pull/62729), [@databus23](https://github.com/databus23)) +* Fix a bug that headless service without ports fails to have endpoint created. ([#62497](https://github.com/kubernetes/kubernetes/pull/62497), [@MrHohn](https://github.com/MrHohn)) +* Fix panic for attaching AzureDisk to vmss nodes ([#63275](https://github.com/kubernetes/kubernetes/pull/63275), [@feiskyer](https://github.com/feiskyer)) +* `kubectl api-resources` now supports filtering to resources supporting specific verbs, and can output fully qualified resource names suitable for combining with commands like `kubectl get` ([#63254](https://github.com/kubernetes/kubernetes/pull/63254), [@liggitt](https://github.com/liggitt)) +* fix cephfs fuse mount bug when user is not admin ([#61804](https://github.com/kubernetes/kubernetes/pull/61804), [@zhangxiaoyu-zidif](https://github.com/zhangxiaoyu-zidif)) +* StorageObjectInUseProtection feature is GA. ([#62870](https://github.com/kubernetes/kubernetes/pull/62870), [@pospispa](https://github.com/pospispa)) +* fixed spurious "unable to find api field" errors patching custom resources ([#63146](https://github.com/kubernetes/kubernetes/pull/63146), [@liggitt](https://github.com/liggitt)) +* KUBE_API_VERSIONS is no longer respected. It was used for testing, but runtime-config is the proper flag to set. ([#63165](https://github.com/kubernetes/kubernetes/pull/63165), [@deads2k](https://github.com/deads2k)) +* Added CheckNodePIDPressurePredicate to checks if a pod can be scheduled on ([#60007](https://github.com/kubernetes/kubernetes/pull/60007), [@k82cn](https://github.com/k82cn)) + * a node reporting pid pressure condition. +* Upgrade Azure Go SDK to stable version (v14.6.0) ([#63063](https://github.com/kubernetes/kubernetes/pull/63063), [@feiskyer](https://github.com/feiskyer)) +* kubeadm: prompt the user for confirmation when resetting a master node ([#59115](https://github.com/kubernetes/kubernetes/pull/59115), [@alexbrand](https://github.com/alexbrand)) +* add warnings on using pod-infra-container-image for remote container runtime ([#62982](https://github.com/kubernetes/kubernetes/pull/62982), [@dixudx](https://github.com/dixudx)) +* Deprecate kubectl rolling-update ([#61285](https://github.com/kubernetes/kubernetes/pull/61285), [@soltysh](https://github.com/soltysh)) +* client-go developers: the new dynamic client is easier to use and the old is deprecated, you must switch. ([#62913](https://github.com/kubernetes/kubernetes/pull/62913), [@deads2k](https://github.com/deads2k)) +* Fix issue where on re-registration of device plugin, `allocatable` was not getting updated. This issue makes devices invisible to the Kubelet if device plugin restarts. Only work-around, if this fix is not there, is to restart the kubelet and then start device plugin. ([#63118](https://github.com/kubernetes/kubernetes/pull/63118), [@vikaschoudhary16](https://github.com/vikaschoudhary16)) +* Remove METADATA_AGENT_VERSION configuration option. ([#63000](https://github.com/kubernetes/kubernetes/pull/63000), [@kawych](https://github.com/kawych)) +* kubelets are no longer allowed to delete their own Node API object. Prior to 1.11, in rare circumstances related to cloudprovider node ID changes, kubelets would attempt to delete/recreate their Node object at startup. If a legacy kubelet encounters this situation, a cluster admin can remove the Node object: ([#62818](https://github.com/kubernetes/kubernetes/pull/62818), [@mikedanese](https://github.com/mikedanese)) + * `kubectl delete node/` + * or grant self-deletion permission explicitly: + * `kubectl create clusterrole self-deleting-nodes --verb=delete --resource=nodes` + * `kubectl create clusterrolebinding self-deleting-nodes --clusterrole=self-deleting-nodes --group=system:nodes` +* kubeadm creates kube-proxy with a toleration to run on all nodes, no matter the taint. ([#62390](https://github.com/kubernetes/kubernetes/pull/62390), [@discordianfish](https://github.com/discordianfish)) +* fix resultRun by resetting it to 0 on pod restart ([#62853](https://github.com/kubernetes/kubernetes/pull/62853), [@tony612](https://github.com/tony612)) +* Mount additional paths required for a working CA root, for setups where /etc/ssl/certs doesn't contains certificates but just symlink. ([#59122](https://github.com/kubernetes/kubernetes/pull/59122), [@klausenbusk](https://github.com/klausenbusk)) +* Introduce truncating audit backend that can be enabled for existing backend to limit the size of individual audit events and batches of events. ([#61711](https://github.com/kubernetes/kubernetes/pull/61711), [@crassirostris](https://github.com/crassirostris)) +* kubeadm upgrade no longer races leading to unexpected upgrade behavior on pod restarts ([#62655](https://github.com/kubernetes/kubernetes/pull/62655), [@stealthybox](https://github.com/stealthybox)) + * kubeadm upgrade now successfully upgrades etcd and the controlplane to use TLS + * kubeadm upgrade now supports external etcd setups + * kubeadm upgrade can now rollback and restore etcd after an upgrade failure +* Add --ipvs-exclude-cidrs flag to kube-proxy. ([#62083](https://github.com/kubernetes/kubernetes/pull/62083), [@rramkumar1](https://github.com/rramkumar1)) +* Fix the liveness probe to use `/bin/bash -c` instead of `/bin/bash c`. ([#63033](https://github.com/kubernetes/kubernetes/pull/63033), [@bmoyles0117](https://github.com/bmoyles0117)) +* Added `MatchFields` to `NodeSelectorTerm`; in 1.11, it only support `metadata.name`. ([#62002](https://github.com/kubernetes/kubernetes/pull/62002), [@k82cn](https://github.com/k82cn)) +* Fix scheduler informers to receive events for all the pods in the cluster. ([#63003](https://github.com/kubernetes/kubernetes/pull/63003), [@bsalamat](https://github.com/bsalamat)) +* removed unsafe double RLock in cpumanager ([#62464](https://github.com/kubernetes/kubernetes/pull/62464), [@choury](https://github.com/choury)) +* Fix in vSphere Cloud Provider to handle upgrades from kubernetes version less than v1.9.4 to v1.9.4 and above. ([#62919](https://github.com/kubernetes/kubernetes/pull/62919), [@abrarshivani](https://github.com/abrarshivani)) +* The `--bootstrap-kubeconfig` argument to Kubelet previously created the first bootstrap client credentials in the certificates directory as `kubelet-client.key` and `kubelet-client.crt`. Subsequent certificates created by cert rotation were created in a combined PEM file that was atomically rotated as `kubelet-client-DATE.pem` in that directory, which meant clients relying on the `node.kubeconfig` generated by bootstrapping would never use a rotated cert. The initial bootstrap certificate is now generated into the cert directory as a PEM file and symlinked to `kubelet-client-current.pem` so that the generated kubeconfig remains valid after rotation. ([#62152](https://github.com/kubernetes/kubernetes/pull/62152), [@smarterclayton](https://github.com/smarterclayton)) +* stop kubelet to cloud provider integration potentially wedging kubelet sync loop ([#62543](https://github.com/kubernetes/kubernetes/pull/62543), [@ingvagabund](https://github.com/ingvagabund)) +* Fix error where config map for Metadata Agent was not created by addon manager. ([#62909](https://github.com/kubernetes/kubernetes/pull/62909), [@kawych](https://github.com/kawych)) +* Fixes the kubernetes.default.svc loopback service resolution to use a loopback configuration. ([#62649](https://github.com/kubernetes/kubernetes/pull/62649), [@liggitt](https://github.com/liggitt)) +* Code generated for CRDs now passes `go vet`. ([#62412](https://github.com/kubernetes/kubernetes/pull/62412), [@bhcleek](https://github.com/bhcleek)) +* fix permissions to allow statefulset scaling for admins, editors, and viewers ([#62336](https://github.com/kubernetes/kubernetes/pull/62336), [@deads2k](https://github.com/deads2k)) +* Add support of standard LB to Azure vmss ([#62707](https://github.com/kubernetes/kubernetes/pull/62707), [@feiskyer](https://github.com/feiskyer)) +* GCE: Fix for internal load balancer management resulting in backend services with outdated instance group links. ([#62885](https://github.com/kubernetes/kubernetes/pull/62885), [@nicksardo](https://github.com/nicksardo)) +* The --experimental-qos-reserve kubelet flags is replaced by the alpha level --qos-reserved flag or QOSReserved field in the kubeletconfig and requires the QOSReserved feature gate to be enabled. ([#62509](https://github.com/kubernetes/kubernetes/pull/62509), [@sjenning](https://github.com/sjenning)) +* Set pod status to "Running" if there is at least one container still reporting as "Running" status and others are "Completed". ([#62642](https://github.com/kubernetes/kubernetes/pull/62642), [@ceshihao](https://github.com/ceshihao)) +* Split PodPriority and PodPreemption feature gate ([#62243](https://github.com/kubernetes/kubernetes/pull/62243), [@resouer](https://github.com/resouer)) +* Add support to resize Portworx volumes. ([#62308](https://github.com/kubernetes/kubernetes/pull/62308), [@harsh-px](https://github.com/harsh-px)) + + + +# v1.11.0-alpha.1 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/master/examples) + +## Downloads for v1.11.0-alpha.1 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes.tar.gz) | `8e7f2b4c8f8fb948b4f7882038fd1bb3f2b967ee240d30d58347f40083ed199b` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-src.tar.gz) | `62ab39d8fd02309c74c2a978402ef809c0fe4bb576f1366d6bb0cff26d62e2ff` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-darwin-386.tar.gz) | `332fd9e243c9c37e31fd26d8fa1a7ccffba770a48a9b0ffe57403f028c6ad6f4` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-darwin-amd64.tar.gz) | `1703462ad564d2d52257fd59b0c8acab595fd08b41ea73fed9f6ccb4bfa074c7` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-linux-386.tar.gz) | `61073b7c5266624e0f7be323481b3111ee01511b6b96cf16468044d8a68068e3` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-linux-amd64.tar.gz) | `9a29117fa44ffc14a7004d55f4de97ad88d94076826cfc0bf9ec73c998c78f64` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-linux-arm.tar.gz) | `55114364aacd4eb6d080b818c859877dd5ce46b8f1e58e1469dfa9a50ade1cf9` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-linux-arm64.tar.gz) | `276fb16cf4aef7d1444ca754ec83365ff36184e1bc30104853f791a57934ee37` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-linux-ppc64le.tar.gz) | `8a9096dd1908b8f4004249daff7ae408e390dbc728cd237bc558192744f52116` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-linux-s390x.tar.gz) | `9297755244647b90c2d41ce9e04ee31fb158a69f011c0f4f1ec2310fa57234e7` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-windows-386.tar.gz) | `449562a4d6d82b5eb60151e6ff0b301f92b92f957e3a38b741a4c0d8b3c0611f` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-client-windows-amd64.tar.gz) | `ab97f150723614bcbacdf27c4ced8b45166425522a44e7de693d0e987c425f07` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-server-linux-amd64.tar.gz) | `4c2db4089271366933d0b63ea7fe8f0d9eb4af06fe91d6aac1b8240e2fbd62e1` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-server-linux-arm.tar.gz) | `d5abdfe5aa28b23cf4f4f6be27db031f885f87e2defef680f2d5b92098b2d783` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-server-linux-arm64.tar.gz) | `bd8a8d7c45108f4b0c2af81411c00e338e410b680abe4463f6b6d88e8adcc817` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-server-linux-ppc64le.tar.gz) | `cb5341af600c82d391fc5ca726ff96c48e741f597360a56cc2ada0a0f9e7ec95` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-server-linux-s390x.tar.gz) | `91009df3801430afde03e888f1f13a83bcb9d00b7cd4194b085684cc11657549` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-node-linux-amd64.tar.gz) | `22bf846c692545e7c2655e2ebe06ffc61313d7c76e4f75716be4cec457b548ed` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-node-linux-arm.tar.gz) | `351095bb0ec177ce1ba950d366516ed6154f6ce920eac39e2a26c48203a94e11` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-node-linux-arm64.tar.gz) | `947e6e9e362652db435903e9b40f14750a7ab3cc60622e78257797f6ed63b1ab` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-node-linux-ppc64le.tar.gz) | `1a0a1d0b96c3e01bc0737245eed76ed3db970c8d80c42450072193f23a0e186b` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-node-linux-s390x.tar.gz) | `6891b2e8f1f93b4f590981dccc6fd976a50a0aa5c425938fc5ca3a9c0742d16a` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.0-alpha.1/kubernetes-node-windows-amd64.tar.gz) | `70daea86c14fcafbd46f3d1bb252db50148fb9aab3371dffc4a039791caebac5` + +## Changelog since v1.10.0 + +### Action Required + +* NONE ([#62643](https://github.com/kubernetes/kubernetes/pull/62643), [@xiangpengzhao](https://github.com/xiangpengzhao)) +* ACTION REQUIRED: Alpha annotation for PersistentVolume node affinity has been removed. Update your PersistentVolumes to use the beta PersistentVolume.nodeAffinity field before upgrading to this release ([#61816](https://github.com/kubernetes/kubernetes/pull/61816), [@wackxu](https://github.com/wackxu)) +* ACTION REQUIRED: In-place node upgrades to this release from versions 1.7.14, 1.8.9, and 1.9.4 are not supported if using subpath volumes with PVCs. Such pods should be drained from the node first. ([#61373](https://github.com/kubernetes/kubernetes/pull/61373), [@msau42](https://github.com/msau42)) + +### Other notable changes + +* Make volume usage metrics available for Cinder ([#62668](https://github.com/kubernetes/kubernetes/pull/62668), [@zetaab](https://github.com/zetaab)) +* kubectl stops rendering List as suffix kind name for CRD resources ([#62512](https://github.com/kubernetes/kubernetes/pull/62512), [@dixudx](https://github.com/dixudx)) +* Removes --include-extended-apis which was deprecated back in https://github.com/kubernetes/kubernetes/pull/32894 ([#62803](https://github.com/kubernetes/kubernetes/pull/62803), [@deads2k](https://github.com/deads2k)) +* Add write-config-to to scheduler ([#62515](https://github.com/kubernetes/kubernetes/pull/62515), [@resouer](https://github.com/resouer)) +* Kubelets will no longer set `externalID` in their node spec. ([#61877](https://github.com/kubernetes/kubernetes/pull/61877), [@mikedanese](https://github.com/mikedanese)) +* kubeadm preflight: check CRI socket path if defined, otherwise check for Docker ([#62481](https://github.com/kubernetes/kubernetes/pull/62481), [@taharah](https://github.com/taharah)) +* fix network setup in hack/local-up-cluster.sh (https://github.com/kubernetes/kubernetes/pull/60431) ([#60633](https://github.com/kubernetes/kubernetes/pull/60633), [@pohly](https://github.com/pohly)) + * better error diagnostics in hack/local-up-cluster.sh output +* Add prometheus cluster monitoring addon to kube-up ([#62195](https://github.com/kubernetes/kubernetes/pull/62195), [@serathius](https://github.com/serathius)) +* Fix inter-pod anti-affinity check to consider a pod a match when all the anti-affinity terms match. ([#62715](https://github.com/kubernetes/kubernetes/pull/62715), [@bsalamat](https://github.com/bsalamat)) +* GCE: Bump GLBC version to 1.1.1 - fixing an issue of handling multiple certs with identical certificates ([#62751](https://github.com/kubernetes/kubernetes/pull/62751), [@nicksardo](https://github.com/nicksardo)) +* fixes configuration error when upgrading kubeadm from 1.9 to 1.10+ ([#62568](https://github.com/kubernetes/kubernetes/pull/62568), [@liztio](https://github.com/liztio)) + * enforces kubeadm upgrading kubernetes from the same major and minor versions as the kubeadm binary. +* Allow user to scale l7 default backend deployment ([#62685](https://github.com/kubernetes/kubernetes/pull/62685), [@freehan](https://github.com/freehan)) +* Pod affinity `nodeSelectorTerm.matchExpressions` may now be empty, and works as previously documented: nil or empty `matchExpressions` matches no objects in scheduler. ([#62448](https://github.com/kubernetes/kubernetes/pull/62448), [@k82cn](https://github.com/k82cn)) +* Add [@andrewsykim](https://github.com/andrewsykim) as an approver for CCM related code. ([#62749](https://github.com/kubernetes/kubernetes/pull/62749), [@andrewsykim](https://github.com/andrewsykim)) +* Fix an issue in inter-pod affinity predicate that cause affinity to self being processed incorrectly ([#62591](https://github.com/kubernetes/kubernetes/pull/62591), [@bsalamat](https://github.com/bsalamat)) +* fix WaitForAttach failure issue for azure disk ([#62612](https://github.com/kubernetes/kubernetes/pull/62612), [@andyzhangx](https://github.com/andyzhangx)) +* Update kube-dns to Version 1.14.10. Major changes: ([#62676](https://github.com/kubernetes/kubernetes/pull/62676), [@MrHohn](https://github.com/MrHohn)) + * Fix a bug in DNS resolution for externalName services + * and PTR records that need to query from upstream nameserver. +* Update version of Istio addon from 0.5.1 to 0.6.0. ([#61911](https://github.com/kubernetes/kubernetes/pull/61911), [@ostromart](https://github.com/ostromart)) + * See https://istio.io/about/notes/0.6.html for full Isto release notes. +* Phase `kubeadm alpha phase kubelet` is added to support dynamic kubelet configuration in kubeadm. ([#57224](https://github.com/kubernetes/kubernetes/pull/57224), [@xiangpengzhao](https://github.com/xiangpengzhao)) +* `kubeadm alpha phase kubeconfig user` supports groups (organizations) to be specified in client cert. ([#62627](https://github.com/kubernetes/kubernetes/pull/62627), [@xiangpengzhao](https://github.com/xiangpengzhao)) +* Fix user visible files creation for windows ([#62375](https://github.com/kubernetes/kubernetes/pull/62375), [@feiskyer](https://github.com/feiskyer)) +* remove deprecated initresource admission plugin ([#58784](https://github.com/kubernetes/kubernetes/pull/58784), [@wackxu](https://github.com/wackxu)) +* Fix machineID getting for vmss nodes when using instance metadata ([#62611](https://github.com/kubernetes/kubernetes/pull/62611), [@feiskyer](https://github.com/feiskyer)) +* Fixes issue where PersistentVolume.NodeAffinity.NodeSelectorTerms were ANDed instead of ORed. ([#62556](https://github.com/kubernetes/kubernetes/pull/62556), [@msau42](https://github.com/msau42)) +* Fix potential infinite loop that can occur when NFS PVs are recycled. ([#62572](https://github.com/kubernetes/kubernetes/pull/62572), [@joelsmith](https://github.com/joelsmith)) +* Fix Forward chain default reject policy for IPVS proxier ([#62007](https://github.com/kubernetes/kubernetes/pull/62007), [@m1093782566](https://github.com/m1093782566)) +* The kubeadm config option `API.ControlPlaneEndpoint` has been extended to take an optional port which may differ from the apiserver's bind port. ([#62314](https://github.com/kubernetes/kubernetes/pull/62314), [@rjosephwright](https://github.com/rjosephwright)) +* cluster/kube-up.sh now provisions a Kubelet config file for GCE via the metadata server. This file is installed by the corresponding GCE init scripts. ([#62183](https://github.com/kubernetes/kubernetes/pull/62183), [@mtaufen](https://github.com/mtaufen)) +* Remove alpha functionality that allowed the controller manager to approve kubelet server certificates. ([#62471](https://github.com/kubernetes/kubernetes/pull/62471), [@mikedanese](https://github.com/mikedanese)) +* gitRepo volumes in pods no longer require git 1.8.5 or newer, older git versions are supported too now. ([#62394](https://github.com/kubernetes/kubernetes/pull/62394), [@jsafrane](https://github.com/jsafrane)) +* Default mount propagation has changed from "HostToContainer" ("rslave" in Linux terminology) to "None" ("private") to match the behavior in 1.9 and earlier releases. "HostToContainer" as a default caused regressions in some pods. ([#62462](https://github.com/kubernetes/kubernetes/pull/62462), [@jsafrane](https://github.com/jsafrane)) +* improve performance of affinity/anti-affinity predicate of default scheduler significantly. ([#62211](https://github.com/kubernetes/kubernetes/pull/62211), [@bsalamat](https://github.com/bsalamat)) +* fix nsenter GetFileType issue in containerized kubelet ([#62467](https://github.com/kubernetes/kubernetes/pull/62467), [@andyzhangx](https://github.com/andyzhangx)) +* Ensure expected load balancer is selected for Azure ([#62450](https://github.com/kubernetes/kubernetes/pull/62450), [@feiskyer](https://github.com/feiskyer)) +* Resolves forbidden error when the `daemon-set-controller` cluster role access `controllerrevisions` resources. ([#62146](https://github.com/kubernetes/kubernetes/pull/62146), [@frodenas](https://github.com/frodenas)) +* Adds --cluster-name to kubeadm init for specifying the cluster name in kubeconfig. ([#60852](https://github.com/kubernetes/kubernetes/pull/60852), [@karan](https://github.com/karan)) +* Upgrade the default etcd server version to 3.2.18 ([#61198](https://github.com/kubernetes/kubernetes/pull/61198), [@jpbetz](https://github.com/jpbetz)) +* [fluentd-gcp addon] Increase CPU limit for fluentd to 1 core to achieve 100kb/s throughput. ([#62430](https://github.com/kubernetes/kubernetes/pull/62430), [@bmoyles0117](https://github.com/bmoyles0117)) +* GCE: Bump GLBC version to 1.1.0 - supporting multiple certificates and HTTP2 ([#62427](https://github.com/kubernetes/kubernetes/pull/62427), [@nicksardo](https://github.com/nicksardo)) +* Fixed #731 kubeadm upgrade ignores HighAvailability feature gate ([#62455](https://github.com/kubernetes/kubernetes/pull/62455), [@fabriziopandini](https://github.com/fabriziopandini)) +* Cluster Autoscaler 1.2.1 (release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.2.1) ([#62457](https://github.com/kubernetes/kubernetes/pull/62457), [@mwielgus](https://github.com/mwielgus)) +* Add generators for `apps/v1` deployments. ([#61288](https://github.com/kubernetes/kubernetes/pull/61288), [@ayushpateria](https://github.com/ayushpateria)) +* kubeadm: surface external etcd preflight validation errors ([#60585](https://github.com/kubernetes/kubernetes/pull/60585), [@alexbrand](https://github.com/alexbrand)) +* kube-apiserver: oidc authentication now supports requiring specific claims with `--oidc-required-claim==` ([#62136](https://github.com/kubernetes/kubernetes/pull/62136), [@rithujohn191](https://github.com/rithujohn191)) +* Implements verbosity logging feature for kubeadm commands ([#57661](https://github.com/kubernetes/kubernetes/pull/57661), [@vbmade2000](https://github.com/vbmade2000)) +* Allow additionalProperties in CRD OpenAPI v3 specification for validation, mutually exclusive to properties. ([#62333](https://github.com/kubernetes/kubernetes/pull/62333), [@sttts](https://github.com/sttts)) +* cinder volume plugin : ([#61082](https://github.com/kubernetes/kubernetes/pull/61082), [@wenlxie](https://github.com/wenlxie)) + * When the cinder volume status is `error`, controller will not do `attach ` and `detach ` operation +* fix incompatible file type checking on Windows ([#62154](https://github.com/kubernetes/kubernetes/pull/62154), [@dixudx](https://github.com/dixudx)) +* fix local volume absolute path issue on Windows ([#62018](https://github.com/kubernetes/kubernetes/pull/62018), [@andyzhangx](https://github.com/andyzhangx)) +* Remove `ObjectMeta ` `ListOptions` `DeleteOptions` from core api group. Please use that in meta/v1 ([#61809](https://github.com/kubernetes/kubernetes/pull/61809), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* fix the issue that default azure disk fsypte(ext4) does not work on Windows ([#62250](https://github.com/kubernetes/kubernetes/pull/62250), [@andyzhangx](https://github.com/andyzhangx)) +* RBAC information is included in audit logs via audit.Event annotations: ([#58807](https://github.com/kubernetes/kubernetes/pull/58807), [@CaoShuFeng](https://github.com/CaoShuFeng)) + * authorization.k8s.io/decision = {allow, forbid} + * authorization.k8s.io/reason = human-readable reason for the decision +* Update kube-dns to Version 1.14.9 in kubeadm. ([#61918](https://github.com/kubernetes/kubernetes/pull/61918), [@MrHohn](https://github.com/MrHohn)) +* Add support to ingest log entries to Stackdriver against new "k8s_container" and "k8s_node" resources. ([#62076](https://github.com/kubernetes/kubernetes/pull/62076), [@qingling128](https://github.com/qingling128)) +* remove deprecated --mode flag in check-network-mode ([#60102](https://github.com/kubernetes/kubernetes/pull/60102), [@satyasm](https://github.com/satyasm)) +* Schedule even if extender is not available when using extender ([#61445](https://github.com/kubernetes/kubernetes/pull/61445), [@resouer](https://github.com/resouer)) +* Fixed column alignment when kubectl get is used with custom columns from OpenAPI schema ([#56629](https://github.com/kubernetes/kubernetes/pull/56629), [@luksa](https://github.com/luksa)) +* Fixed bug in rbd-nbd utility when nbd is used. ([#62168](https://github.com/kubernetes/kubernetes/pull/62168), [@piontec](https://github.com/piontec)) +* Extend the Stackdriver Metadata Agent by adding a new Deployment for ingesting unscheduled pods, and services. ([#62043](https://github.com/kubernetes/kubernetes/pull/62043), [@supriyagarg](https://github.com/supriyagarg)) +* Disabled CheckNodeMemoryPressure and CheckNodeDiskPressure predicates if TaintNodesByCondition enabled ([#60398](https://github.com/kubernetes/kubernetes/pull/60398), [@k82cn](https://github.com/k82cn)) +* kubeadm config can now override the Node CIDR Mask Size passed to kube-controller-manager. ([#61705](https://github.com/kubernetes/kubernetes/pull/61705), [@jstangroome](https://github.com/jstangroome)) +* Add warnings that authors of aggregated API servers must not rely on authorization being done by the kube-apiserver. ([#61349](https://github.com/kubernetes/kubernetes/pull/61349), [@sttts](https://github.com/sttts)) +* Support custom test configuration for IPAM performance integration tests ([#61959](https://github.com/kubernetes/kubernetes/pull/61959), [@satyasm](https://github.com/satyasm)) +* GCE: Updates GLBC version to 1.0.1 which includes a fix which prevents multi-cluster ingress objects from creating full load balancers. ([#62075](https://github.com/kubernetes/kubernetes/pull/62075), [@nicksardo](https://github.com/nicksardo)) +* OIDC authentication now allows tokens without an "email_verified" claim when using the "email" claim. If an "email_verified" claim is present when using the "email" claim, it must be `true`. ([#61508](https://github.com/kubernetes/kubernetes/pull/61508), [@rithujohn191](https://github.com/rithujohn191)) +* fix local volume issue on Windows ([#62012](https://github.com/kubernetes/kubernetes/pull/62012), [@andyzhangx](https://github.com/andyzhangx)) +* kubeadm: Introduce join timeout that can be controlled via the discoveryTimeout config option (set to 5 minutes by default). ([#60983](https://github.com/kubernetes/kubernetes/pull/60983), [@rosti](https://github.com/rosti)) +* Add e2e test for CRD Watch ([#61025](https://github.com/kubernetes/kubernetes/pull/61025), [@ayushpateria](https://github.com/ayushpateria)) +* Fix panic create/update CRD when mutating/validating webhook configured. ([#61404](https://github.com/kubernetes/kubernetes/pull/61404), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* Fix a bug that fluentd doesn't inject container logs for CRI container runtimes (containerd, cri-o etc.) into elasticsearch on GCE. ([#61818](https://github.com/kubernetes/kubernetes/pull/61818), [@Random-Liu](https://github.com/Random-Liu)) +* Support for "alpha.kubernetes.io/nvidia-gpu" resource which was deprecated in 1.10 is removed. Please use the resource exposed by DevicePlugins instead ("nvidia.com/gpu"). ([#61498](https://github.com/kubernetes/kubernetes/pull/61498), [@mindprince](https://github.com/mindprince)) +* Pods requesting resources prefixed with `*kubernetes.io` will remain unscheduled if there are no nodes exposing that resource. ([#61860](https://github.com/kubernetes/kubernetes/pull/61860), [@mindprince](https://github.com/mindprince)) +* flexvolume: trigger plugin init only for the relevant plugin while probe ([#58519](https://github.com/kubernetes/kubernetes/pull/58519), [@linyouchong](https://github.com/linyouchong)) +* Update to use go1.10.1 ([#60597](https://github.com/kubernetes/kubernetes/pull/60597), [@cblecker](https://github.com/cblecker)) +* Rev the Azure SDK for networking to 2017-06-01 ([#61955](https://github.com/kubernetes/kubernetes/pull/61955), [@brendandburns](https://github.com/brendandburns)) +* Return error if get NodeStageSecret and NodePublishSecret failed in CSI volume plugin ([#61096](https://github.com/kubernetes/kubernetes/pull/61096), [@mlmhl](https://github.com/mlmhl)) +* kubectl: improves compatibility with older servers when creating/updating API objects ([#61949](https://github.com/kubernetes/kubernetes/pull/61949), [@liggitt](https://github.com/liggitt)) +* kubernetes-master charm now supports metrics server for horizontal pod autoscaler. ([#60174](https://github.com/kubernetes/kubernetes/pull/60174), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* fix scheduling policy on ConfigMap breaks without the --policy-configmap-namespace flag set ([#61388](https://github.com/kubernetes/kubernetes/pull/61388), [@zjj2wry](https://github.com/zjj2wry)) +* kubectl: restore the ability to show resource kinds when displaying multiple objects ([#61985](https://github.com/kubernetes/kubernetes/pull/61985), [@liggitt](https://github.com/liggitt)) +* `kubectl certificate approve|deny` will not modify an already approved or denied CSR unless the `--force` flag is provided. ([#61971](https://github.com/kubernetes/kubernetes/pull/61971), [@smarterclayton](https://github.com/smarterclayton)) +* Kubelet now exposes a new endpoint /metrics/probes which exposes a Prometheus metric containing the liveness and/or readiness probe results for a container. ([#61369](https://github.com/kubernetes/kubernetes/pull/61369), [@rramkumar1](https://github.com/rramkumar1)) +* Balanced resource allocation priority in scheduler to include volume count on node ([#60525](https://github.com/kubernetes/kubernetes/pull/60525), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) +* new dhcp-domain parameter to be used for figuring out the hostname of a node ([#61890](https://github.com/kubernetes/kubernetes/pull/61890), [@dims](https://github.com/dims)) +* Fixed a panic in `kubectl run --attach ...` when the api server failed to create the runtime object (due to name conflict, PSP restriction, etc.) ([#61713](https://github.com/kubernetes/kubernetes/pull/61713), [@mountkin](https://github.com/mountkin)) +* Ensure reasons end up as comments in `kubectl edit`. ([#60990](https://github.com/kubernetes/kubernetes/pull/60990), [@bmcstdio](https://github.com/bmcstdio)) +* kube-scheduler has been fixed to use `--leader-elect` option back to true (as it was in previous versions) ([#59732](https://github.com/kubernetes/kubernetes/pull/59732), [@dims](https://github.com/dims)) +* Azure cloud provider now supports standard SKU load balancer and public IP. To use it, set cloud provider config with ([#61884](https://github.com/kubernetes/kubernetes/pull/61884), [@feiskyer](https://github.com/feiskyer)) + * { + * "loadBalancerSku": "standard", + * "excludeMasterFromStandardLB": true, + * } + * If excludeMasterFromStandardLB is not set, it will be default to true, which means master nodes are excluded to the backend of standard LB. + * Also note standard load balancer doesn't work with annotation `service.beta.kubernetes.io/azure-load-balancer-mode`. This is because all nodes (except master) are added as the LB backends. +* The node authorizer now automatically sets up rules for Node.Spec.ConfigSource when the DynamicKubeletConfig feature gate is enabled. ([#60100](https://github.com/kubernetes/kubernetes/pull/60100), [@mtaufen](https://github.com/mtaufen)) +* Update kube-dns to Version 1.14.9. Major changes: ([#61908](https://github.com/kubernetes/kubernetes/pull/61908), [@MrHohn](https://github.com/MrHohn)) + * Fix for kube-dns returns NXDOMAIN when not yet synced with apiserver. + * Don't generate empty record for externalName service. + * Add validation for upstreamNameserver port. + * Update go version to 1.9.3. +* CRI: define the mount behavior when host path does not exist: runtime should report error if the host path doesn't exist ([#61460](https://github.com/kubernetes/kubernetes/pull/61460), [@feiskyer](https://github.com/feiskyer)) +* Fixed ingress issue with CDK and pre-1.9 versions of kubernetes. ([#61859](https://github.com/kubernetes/kubernetes/pull/61859), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Removed rknetes code, which was deprecated in 1.10. ([#61432](https://github.com/kubernetes/kubernetes/pull/61432), [@filbranden](https://github.com/filbranden)) +* Disable ipamperf integration tests as part of every PR verification. ([#61863](https://github.com/kubernetes/kubernetes/pull/61863), [@satyasm](https://github.com/satyasm)) +* Enable server-side print in kubectl by default, with the ability to turn it off with --server-print=false ([#61477](https://github.com/kubernetes/kubernetes/pull/61477), [@soltysh](https://github.com/soltysh)) +* Add ipset and udevadm to the hyperkube base image. ([#61357](https://github.com/kubernetes/kubernetes/pull/61357), [@rphillips](https://github.com/rphillips)) +* In a GCE cluster, the default HAIRPIN_MODE is now "hairpin-veth". ([#60166](https://github.com/kubernetes/kubernetes/pull/60166), [@rramkumar1](https://github.com/rramkumar1)) +* Deployment will stop adding pod-template-hash labels/selector to ReplicaSets and Pods it adopts. Resources created by Deployments are not affected (will still have pod-template-hash labels/selector). ([#61615](https://github.com/kubernetes/kubernetes/pull/61615), [@janetkuo](https://github.com/janetkuo)) +* kubectl: fixes issue with `-o yaml` and `-o json` omitting kind and apiVersion when used with `--dry-run` ([#61808](https://github.com/kubernetes/kubernetes/pull/61808), [@liggitt](https://github.com/liggitt)) +* Updated admission controller settings for Juju deployed Kubernetes clusters ([#61427](https://github.com/kubernetes/kubernetes/pull/61427), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Performance test framework and basic tests for the IPAM controller, to simulate behavior ([#61143](https://github.com/kubernetes/kubernetes/pull/61143), [@satyasm](https://github.com/satyasm)) + * of the four supported modes under lightly loaded and loaded conditions, where load is + * defined as the number of operations to perform as against the configured kubernetes + * API server QPS. +* kubernetes-master charm now properly clears the client-ca-file setting on the apiserver snap ([#61479](https://github.com/kubernetes/kubernetes/pull/61479), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* Fix racy panics when using fake watches with ObjectTracker ([#61195](https://github.com/kubernetes/kubernetes/pull/61195), [@grantr](https://github.com/grantr)) +* [fluentd-gcp addon] Update event-exporter image to have the latest base image. ([#61727](https://github.com/kubernetes/kubernetes/pull/61727), [@crassirostris](https://github.com/crassirostris)) +* Use inline func to ensure unlock is executed ([#61644](https://github.com/kubernetes/kubernetes/pull/61644), [@resouer](https://github.com/resouer)) +* `kubectl apply view/edit-last-applied support completion. ([#60499](https://github.com/kubernetes/kubernetes/pull/60499), [@superbrothers](https://github.com/superbrothers)) +* Automatically add system critical priority classes at cluster boostrapping. ([#60519](https://github.com/kubernetes/kubernetes/pull/60519), [@bsalamat](https://github.com/bsalamat)) +* Ensure cloudprovider.InstanceNotFound is reported when the VM is not found on Azure ([#61531](https://github.com/kubernetes/kubernetes/pull/61531), [@feiskyer](https://github.com/feiskyer)) +* Azure cloud provider now supports specifying allowed service tags by annotation `service.beta.kubernetes.io/azure-allowed-service-tags` ([#61467](https://github.com/kubernetes/kubernetes/pull/61467), [@feiskyer](https://github.com/feiskyer)) +* Add all kinds of resource objects' statuses in HPA description. ([#59609](https://github.com/kubernetes/kubernetes/pull/59609), [@zhangxiaoyu-zidif](https://github.com/zhangxiaoyu-zidif)) +* Bound cloud allocator to 10 retries with 100 ms delay between retries. ([#61375](https://github.com/kubernetes/kubernetes/pull/61375), [@satyasm](https://github.com/satyasm)) +* Removed always pull policy from the template for ingress on CDK. ([#61598](https://github.com/kubernetes/kubernetes/pull/61598), [@hyperbolic2346](https://github.com/hyperbolic2346)) +* escape literal percent sign when formatting ([#61523](https://github.com/kubernetes/kubernetes/pull/61523), [@dixudx](https://github.com/dixudx)) +* Cluster Autoscaler 1.2.0 - release notes available here: https://github.com/kubernetes/autoscaler/releases ([#61561](https://github.com/kubernetes/kubernetes/pull/61561), [@mwielgus](https://github.com/mwielgus)) +* Fix mounting of UNIX sockets(and other special files) in subpaths ([#61480](https://github.com/kubernetes/kubernetes/pull/61480), [@gnufied](https://github.com/gnufied)) +* `kubectl patch` now supports `--dry-run`. ([#60675](https://github.com/kubernetes/kubernetes/pull/60675), [@timoreimann](https://github.com/timoreimann)) +* fix sorting taints in case the sorting keys are equal ([#61255](https://github.com/kubernetes/kubernetes/pull/61255), [@dixudx](https://github.com/dixudx)) +* NetworkPolicies can now target specific pods in other namespaces by including both a namespaceSelector and a podSelector in the same peer element. ([#60452](https://github.com/kubernetes/kubernetes/pull/60452), [@danwinship](https://github.com/danwinship)) +* include node internal ip as additional information for kubectl ([#57623](https://github.com/kubernetes/kubernetes/pull/57623), [@dixudx](https://github.com/dixudx)) +* Add apiserver configuration option to choose audit output version. ([#60056](https://github.com/kubernetes/kubernetes/pull/60056), [@crassirostris](https://github.com/crassirostris)) +* `make test-cmd` now works on OSX. ([#61393](https://github.com/kubernetes/kubernetes/pull/61393), [@totherme](https://github.com/totherme)) +* Remove kube-apiserver `--storage-version` flag, use `--storage-versions` instead. ([#61453](https://github.com/kubernetes/kubernetes/pull/61453), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* Bump Heapster to v1.5.2 ([#61396](https://github.com/kubernetes/kubernetes/pull/61396), [@kawych](https://github.com/kawych)) +* Conformance: ReplicaSet must be supported in the `apps/v1` version. ([#61367](https://github.com/kubernetes/kubernetes/pull/61367), [@enisoc](https://github.com/enisoc)) +* You can now use the `base64decode` function in kubectl go templates to decode base64-encoded data, for example `kubectl get secret SECRET -o go-template='{{ .data.KEY | base64decode }}'`. ([#60755](https://github.com/kubernetes/kubernetes/pull/60755), [@glb](https://github.com/glb)) +* Remove 'system' prefix from Metadata Agent rbac configuration ([#61394](https://github.com/kubernetes/kubernetes/pull/61394), [@kawych](https://github.com/kawych)) +* Remove `--tls-ca-file` flag. ([#61386](https://github.com/kubernetes/kubernetes/pull/61386), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) +* fix sorting tolerations in case the keys are equal ([#61252](https://github.com/kubernetes/kubernetes/pull/61252), [@dixudx](https://github.com/dixudx)) +* respect fstype in Windows for azure disk ([#61267](https://github.com/kubernetes/kubernetes/pull/61267), [@andyzhangx](https://github.com/andyzhangx)) +* `--show-all` (which only affected pods and only for human readable/non-API printers) is inert in v1.11, and will be removed in a future release. ([#60793](https://github.com/kubernetes/kubernetes/pull/60793), [@charrywanganthony](https://github.com/charrywanganthony)) +* Remove never used NewCronJobControllerFromClient method ([#59471](https://github.com/kubernetes/kubernetes/pull/59471), [@dmathieu](https://github.com/dmathieu)) +* Support new NODE_OS_DISTRIBUTION 'custom' on GCE ([#61235](https://github.com/kubernetes/kubernetes/pull/61235), [@yguo0905](https://github.com/yguo0905)) +* Fixed [#61123](https://github.com/kubernetes/kubernetes/pull/61123) by triggering syncer.Update on all cases including when a syncer is created ([#61124](https://github.com/kubernetes/kubernetes/pull/61124), [@satyasm](https://github.com/satyasm)) + * on a new add event. +* Unready pods will no longer impact the number of desired replicas when using horizontal auto-scaling with external metrics or object metrics. ([#60886](https://github.com/kubernetes/kubernetes/pull/60886), [@mattjmcnaughton](https://github.com/mattjmcnaughton)) +* include file name in the error when visiting files ([#60919](https://github.com/kubernetes/kubernetes/pull/60919), [@dixudx](https://github.com/dixudx)) +* Implement preemption for extender with a verb and new interface ([#58717](https://github.com/kubernetes/kubernetes/pull/58717), [@resouer](https://github.com/resouer)) +* `kube-cloud-controller-manager` flag `--service-account-private-key-file` is removed in v1.11 ([#60875](https://github.com/kubernetes/kubernetes/pull/60875), [@charrywanganthony](https://github.com/charrywanganthony)) +* kubeadm: Add the writable boolean option to kubeadm config. The option works on a per-volume basis for *ExtraVolumes config keys. ([#60428](https://github.com/kubernetes/kubernetes/pull/60428), [@rosti](https://github.com/rosti)) +* DaemonSet scheduling associated with the alpha ScheduleDaemonSetPods feature flag has been removed from the 1.10 release. See https://github.com/kubernetes/features/issues/548 for feature status. ([#61411](https://github.com/kubernetes/kubernetes/pull/61411), [@liggitt](https://github.com/liggitt)) +* Bugfix for erroneous upgrade needed messaging in kubernetes worker charm. ([#60873](https://github.com/kubernetes/kubernetes/pull/60873), [@wwwtyro](https://github.com/wwwtyro)) +* Fix data race in node lifecycle controller ([#60831](https://github.com/kubernetes/kubernetes/pull/60831), [@resouer](https://github.com/resouer)) +* Nodes are not deleted from kubernetes anymore if node is shutdown in Openstack. ([#59931](https://github.com/kubernetes/kubernetes/pull/59931), [@zetaab](https://github.com/zetaab)) +* "beginPort+offset" format support for port range which affects kube-proxy only ([#58731](https://github.com/kubernetes/kubernetes/pull/58731), [@yue9944882](https://github.com/yue9944882)) +* Added e2e test for watch ([#60331](https://github.com/kubernetes/kubernetes/pull/60331), [@jennybuckley](https://github.com/jennybuckley)) +* kubelet's --cni-bin-dir option now accepts multiple comma-separated CNI binary directory paths, which are search for CNI plugins in the given order. ([#58714](https://github.com/kubernetes/kubernetes/pull/58714), [@dcbw](https://github.com/dcbw)) + diff --git a/vendor/k8s.io/kubernetes/CHANGELOG.md b/vendor/k8s.io/kubernetes/CHANGELOG.md index 06992d1f2..361eb783e 100644 --- a/vendor/k8s.io/kubernetes/CHANGELOG.md +++ b/vendor/k8s.io/kubernetes/CHANGELOG.md @@ -1,13 +1,14 @@ ## Development release: -- [CHANGELOG-1.10.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.10.md) ## Current release: -- [CHANGELOG-1.9.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.9.md) +- [CHANGELOG-1.11.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.11.md) ## Older releases: +- [CHANGELOG-1.10.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.10.md) +- [CHANGELOG-1.9.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.9.md) - [CHANGELOG-1.8.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.8.md) - [CHANGELOG-1.7.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.7.md) - [CHANGELOG-1.6.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.6.md) diff --git a/vendor/k8s.io/kubernetes/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/Godeps/Godeps.json index 2e1405149..1e3f61864 100644 --- a/vendor/k8s.io/kubernetes/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/Godeps/Godeps.json @@ -1,12 +1,14 @@ { "ImportPath": "k8s.io/kubernetes", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "github.com/onsi/ginkgo/ginkgo", "github.com/jteeuwen/go-bindata/go-bindata", "github.com/tools/godep", "github.com/client9/misspell/cmd/misspell", + "github.com/bazelbuild/bazel-gazelle/cmd/gazelle", + "github.com/kubernetes/repo-infra/kazel", "./..." ], "Deps": [ @@ -30,39 +32,34 @@ "Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821" }, { - "ImportPath": "github.com/Azure/azure-sdk-for-go/arm/compute", - "Comment": "v12.4.0-beta", - "Rev": "f111fc2fa3861c5fdced76cae4c9c71821969577" + "ImportPath": "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute", + "Comment": "v14.6.0", + "Rev": "56a0b1d2af3b65d5f1f7a330e02faaf48b473c5a" }, { - "ImportPath": "github.com/Azure/azure-sdk-for-go/arm/containerregistry", - "Comment": "v12.4.0-beta", - "Rev": "f111fc2fa3861c5fdced76cae4c9c71821969577" + "ImportPath": "github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry", + "Comment": "v14.6.0", + "Rev": "56a0b1d2af3b65d5f1f7a330e02faaf48b473c5a" }, { - "ImportPath": "github.com/Azure/azure-sdk-for-go/arm/disk", - "Comment": "v12.4.0-beta", - "Rev": "f111fc2fa3861c5fdced76cae4c9c71821969577" + "ImportPath": "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network", + "Comment": "v14.6.0", + "Rev": "56a0b1d2af3b65d5f1f7a330e02faaf48b473c5a" }, { - "ImportPath": "github.com/Azure/azure-sdk-for-go/arm/network", - "Comment": "v12.4.0-beta", - "Rev": "f111fc2fa3861c5fdced76cae4c9c71821969577" + "ImportPath": "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage", + "Comment": "v14.6.0", + "Rev": "56a0b1d2af3b65d5f1f7a330e02faaf48b473c5a" }, { - "ImportPath": "github.com/Azure/azure-sdk-for-go/arm/storage", - "Comment": "v12.4.0-beta", - "Rev": "f111fc2fa3861c5fdced76cae4c9c71821969577" + "ImportPath": "github.com/Azure/azure-sdk-for-go/storage", + "Comment": "v14.6.0", + "Rev": "56a0b1d2af3b65d5f1f7a330e02faaf48b473c5a" }, { - "ImportPath": "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute", - "Comment": "v12.4.0-beta", - "Rev": "f111fc2fa3861c5fdced76cae4c9c71821969577" - }, - { - "ImportPath": "github.com/Azure/azure-sdk-for-go/storage", - "Comment": "v12.4.0-beta", - "Rev": "f111fc2fa3861c5fdced76cae4c9c71821969577" + "ImportPath": "github.com/Azure/azure-sdk-for-go/version", + "Comment": "v14.6.0", + "Rev": "56a0b1d2af3b65d5f1f7a330e02faaf48b473c5a" }, { "ImportPath": "github.com/Azure/go-ansiterm", @@ -74,33 +71,33 @@ }, { "ImportPath": "github.com/Azure/go-autorest/autorest", - "Comment": "v9.9.0", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Comment": "v10.6.2", + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/adal", - "Comment": "v9.9.0", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Comment": "v10.6.2", + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/azure", - "Comment": "v9.9.0", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Comment": "v10.6.2", + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/date", - "Comment": "v9.9.0", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Comment": "v10.6.2", + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/to", - "Comment": "v9.9.0", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Comment": "v10.6.2", + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/validation", - "Comment": "v9.9.0", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Comment": "v10.6.2", + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/JeffAshton/win_pdh", @@ -117,8 +114,8 @@ }, { "ImportPath": "github.com/Microsoft/hcsshim", - "Comment": "V0.6.3", - "Rev": "6ea7fe54f719d95721e7d9b26ac0add224c9b923" + "Comment": "v0.6.11", + "Rev": "800683ae704ac360b2f3f47fa88f3a6c8c9091b5" }, { "ImportPath": "github.com/NYTimes/gziphandler", @@ -141,26 +138,6 @@ "ImportPath": "github.com/abbot/go-http-auth", "Rev": "c0ef4539dfab4d21c8ef20ba2924f9fc6f186d35" }, - { - "ImportPath": "github.com/appc/spec/schema", - "Comment": "v0.8.9-17-gfc380db", - "Rev": "fc380db5fc13c6dd71a5b0bf2af0d182865d1b1d" - }, - { - "ImportPath": "github.com/appc/spec/schema/common", - "Comment": "v0.8.9-17-gfc380db", - "Rev": "fc380db5fc13c6dd71a5b0bf2af0d182865d1b1d" - }, - { - "ImportPath": "github.com/appc/spec/schema/types", - "Comment": "v0.8.9-17-gfc380db", - "Rev": "fc380db5fc13c6dd71a5b0bf2af0d182865d1b1d" - }, - { - "ImportPath": "github.com/appc/spec/schema/types/resource", - "Comment": "v0.8.9-17-gfc380db", - "Rev": "fc380db5fc13c6dd71a5b0bf2af0d182865d1b1d" - }, { "ImportPath": "github.com/armon/circbuf", "Rev": "bbbad097214e2918d8543d5201d12bfd7bca254d" @@ -330,6 +307,71 @@ "Comment": "v1.12.7", "Rev": "760741802ad40f49ae9fc4a69ef6706d2527d62e" }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/cmd/gazelle", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/config", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/label", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/merger", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/packages", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/pathtools", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/repos", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/resolve", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/rules", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/version", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/bazel-gazelle/internal/wspace", + "Comment": "0.10.1", + "Rev": "ff4d67f395b3f4d1dc9810eeceb61585fea252cb" + }, + { + "ImportPath": "github.com/bazelbuild/buildtools/build", + "Comment": "0.6.0-60-g1a9c38e", + "Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f" + }, + { + "ImportPath": "github.com/bazelbuild/buildtools/tables", + "Comment": "0.6.0-60-g1a9c38e", + "Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f" + }, { "ImportPath": "github.com/beorn7/perks/quantile", "Rev": "3ac7bf7a47d159a033b107610db8a1b6575507a4" @@ -367,68 +409,68 @@ }, { "ImportPath": "github.com/cloudflare/cfssl/auth", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/certdb", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/config", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/csr", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/errors", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/helpers", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/helpers/derhelpers", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/info", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/log", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/ocsp/config", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/signer", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/cloudflare/cfssl/signer/local", - "Comment": "1.2.0", - "Rev": "db0d0650b6496bfe8061ec56a92edd32d8e75c30" + "Comment": "1.3.1", + "Rev": "4e2dcbde500472449917533851bf4bae9bdff562" }, { "ImportPath": "github.com/clusterhq/flocker-go", @@ -446,15 +488,10 @@ "ImportPath": "github.com/codedellemc/goscaleio/types/v1", "Rev": "20e2ce2cf8852dc78bd42b76698dcd8dcd77b7b1" }, - { - "ImportPath": "github.com/codegangsta/negroni", - "Comment": "v0.1.0-62-g8d75e11", - "Rev": "8d75e11374a1928608c906fe745b538483e7aeb2" - }, { "ImportPath": "github.com/container-storage-interface/spec/lib/go/csi/v0", - "Comment": "v0.2.0", - "Rev": "35d9f9d77954980e449e52c3f3e43c21bd8171f5" + "Comment": "v0.3.0", + "Rev": "2178fdeea87f1150a17a63252eee28d4d8141f72" }, { "ImportPath": "github.com/containerd/console", @@ -462,48 +499,48 @@ }, { "ImportPath": "github.com/containerd/containerd/api/services/containers/v1", - "Comment": "v1.0.0-beta.2-159-g27d450a0", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/api/services/tasks/v1", - "Comment": "v1.0.0-beta.2-159-g27d450a0", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/api/services/version/v1", - "Comment": "v1.0.0-beta.2-159-g27d450a0", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/api/types", - "Comment": "v1.0.0-beta.2-159-g27d450a0", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/api/types/task", - "Comment": "v1.0.0-beta.2-159-g27d450a0", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/containers", - "Comment": "v1.0.0-beta.2-159-g27d450a0", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/dialer", - "Comment": "v1.0.0-beta.2-159-g27d450a0", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/errdefs", - "Comment": "v1.0.0-beta.2-159-g27d450a0", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containerd/containerd/namespaces", - "Comment": "v1.0.0-beta.2-159-g27d450a0", - "Rev": "27d450a01bb533d7ebc5701eb52792565396b084" + "Comment": "v1.0.2", + "Rev": "cfd04396dc68220d1cecbe686a6cc3aa5ce3667c" }, { "ImportPath": "github.com/containernetworking/cni/libcni", @@ -928,11 +965,6 @@ "Comment": "v14", "Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6" }, - { - "ImportPath": "github.com/coreos/go-systemd/unit", - "Comment": "v14", - "Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6" - }, { "ImportPath": "github.com/coreos/go-systemd/util", "Comment": "v14", @@ -980,10 +1012,6 @@ "ImportPath": "github.com/daviddengcn/go-colortext", "Rev": "511bcaf42ccd42c38aba7427b6673277bf19e2a1" }, - { - "ImportPath": "github.com/dchest/safefile", - "Rev": "855e8d98f1852d48dde521e0522408d1fe7e836a" - }, { "ImportPath": "github.com/dgrijalva/jwt-go", "Comment": "v3.0.0-4-g01aeca5", @@ -1114,6 +1142,11 @@ "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, + { + "ImportPath": "github.com/docker/docker/pkg/parsers/operatingsystem", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" + }, { "ImportPath": "github.com/docker/docker/pkg/stdcopy", "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", @@ -1212,7 +1245,8 @@ }, { "ImportPath": "github.com/evanphx/json-patch", - "Rev": "944e07253867aacae43c04b2e6a239005443f33a" + "Comment": "v3.0.0-23-g94e38aa", + "Rev": "94e38aa1586e8a6c8a75770bddf5ff84c48a106b" }, { "ImportPath": "github.com/exponent-io/jsonpath", @@ -1227,16 +1261,6 @@ "Comment": "v1.3.1-1-gf12c623", "Rev": "f12c6236fe7b5cf6bcf30e5935d08cb079d78334" }, - { - "ImportPath": "github.com/garyburd/redigo/internal", - "Comment": "v1.0.0-1-gb8dc900", - "Rev": "b8dc90050f24c1a73a52f107f3f575be67b21b7c" - }, - { - "ImportPath": "github.com/garyburd/redigo/redis", - "Comment": "v1.0.0-1-gb8dc900", - "Rev": "b8dc90050f24c1a73a52f107f3f575be67b21b7c" - }, { "ImportPath": "github.com/ghodss/yaml", "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" @@ -1435,39 +1459,48 @@ }, { "ImportPath": "github.com/golang/protobuf/jsonpb", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" - }, - { - "ImportPath": "github.com/golang/protobuf/ptypes/empty", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/struct", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes/wrappers", + "Comment": "v1.1.0", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -1475,238 +1508,258 @@ }, { "ImportPath": "github.com/google/cadvisor/accelerators", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/api", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/cache/memory", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/client/v2", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/collector", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/container", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/container/common", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/container/containerd", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/container/crio", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/container/docker", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/container/libcontainer", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/container/raw", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/container/rkt", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/container/systemd", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/devicemapper", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/events", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/fs", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/healthz", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/http", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/http/mux", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/info/v1", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/info/v2", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/machine", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/manager", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/manager/watcher", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/manager/watcher/raw", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/manager/watcher/rkt", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/metrics", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/pages", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/pages/static", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/storage", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/summary", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/utils", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/utils/cloudinfo", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/utils/cpuload", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/utils/docker", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/utils/oomparser", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/utils/sysfs", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/utils/sysinfo", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/validate", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/version", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" }, { "ImportPath": "github.com/google/cadvisor/zfs", - "Comment": "v0.29.1", - "Rev": "2e02d28350c5fbbad9cfb7e5a1733468b75ab3f9" + "Comment": "v0.30.2", + "Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" + }, + { + "ImportPath": "github.com/google/certificate-transparency-go", + "Comment": "v1.0.10", + "Rev": "1bec4527572c443752ad4f2830bef88be0533236" + }, + { + "ImportPath": "github.com/google/certificate-transparency-go/asn1", + "Comment": "v1.0.10", + "Rev": "1bec4527572c443752ad4f2830bef88be0533236" + }, + { + "ImportPath": "github.com/google/certificate-transparency-go/client", + "Comment": "v1.0.10", + "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { - "ImportPath": "github.com/google/certificate-transparency/go", - "Rev": "af98904302724c29aa6659ca372d41c9687de2b7" + "ImportPath": "github.com/google/certificate-transparency-go/client/configpb", + "Comment": "v1.0.10", + "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { - "ImportPath": "github.com/google/certificate-transparency/go/asn1", - "Rev": "af98904302724c29aa6659ca372d41c9687de2b7" + "ImportPath": "github.com/google/certificate-transparency-go/jsonclient", + "Comment": "v1.0.10", + "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { - "ImportPath": "github.com/google/certificate-transparency/go/client", - "Rev": "af98904302724c29aa6659ca372d41c9687de2b7" + "ImportPath": "github.com/google/certificate-transparency-go/tls", + "Comment": "v1.0.10", + "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { - "ImportPath": "github.com/google/certificate-transparency/go/x509", - "Rev": "af98904302724c29aa6659ca372d41c9687de2b7" + "ImportPath": "github.com/google/certificate-transparency-go/x509", + "Comment": "v1.0.10", + "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { - "ImportPath": "github.com/google/certificate-transparency/go/x509/pkix", - "Rev": "af98904302724c29aa6659ca372d41c9687de2b7" + "ImportPath": "github.com/google/certificate-transparency-go/x509/pkix", + "Comment": "v1.0.10", + "Rev": "1bec4527572c443752ad4f2830bef88be0533236" }, { "ImportPath": "github.com/google/gofuzz", @@ -1731,131 +1784,123 @@ }, { "ImportPath": "github.com/gophercloud/gophercloud", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/common/extensions", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/images", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/networks", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/ports", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/utils", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/pagination", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" - }, - { - "ImportPath": "github.com/gorilla/context", - "Rev": "215affda49addc4c8ef7e2534915df2c8c35c6cd" - }, - { - "ImportPath": "github.com/gorilla/mux", - "Rev": "8096f47503459bcc74d1f4c487b7e6e42e5746b5" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gorilla/websocket", @@ -1933,11 +1978,6 @@ "ImportPath": "github.com/hashicorp/hcl/json/token", "Rev": "d8c773c4cba11b11539e3d45f93daeaa5dcf1fa1" }, - { - "ImportPath": "github.com/hawkular/hawkular-client-go/metrics", - "Comment": "v0.5.1-1-g1d46ce7", - "Rev": "1d46ce7e1eca635f372357a8ccbf1fa7cc28b7d2" - }, { "ImportPath": "github.com/heketi/heketi/client/api/go-client", "Comment": "v4.0.0-95-gaaf4061", @@ -1953,10 +1993,6 @@ "Comment": "v4.0.0-95-gaaf4061", "Rev": "aaf40619d85fda757e7a1c1ea1b5118cea65594b" }, - { - "ImportPath": "github.com/howeyc/gopass", - "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" - }, { "ImportPath": "github.com/imdario/mergo", "Comment": "0.1.3-8-g6633656", @@ -1967,11 +2003,6 @@ "Comment": "v1.0", "Rev": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" }, - { - "ImportPath": "github.com/influxdata/influxdb/client", - "Comment": "v1.1.1", - "Rev": "e47cf1f2e83a02443d7115c54f838be8ee959644" - }, { "ImportPath": "github.com/influxdata/influxdb/client/v2", "Comment": "v1.1.1", @@ -1998,8 +2029,8 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Comment": "1.0.4-7-g13f8643", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Comment": "1.1.3-22-gf2b4162", + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/jteeuwen/go-bindata", @@ -2024,15 +2055,14 @@ "Comment": "go.weekly.2011-12-22-24-gf31442d", "Rev": "f31442d60e51465c69811e2107ae978868dbea5c" }, - { - "ImportPath": "github.com/kr/pty", - "Comment": "release.r56-29-gf7ee69f", - "Rev": "f7ee69f31298ecbe5d2b349c711e2547a617d398" - }, { "ImportPath": "github.com/kr/text", "Rev": "6807e777504f54ad073ecef66747de158294b639" }, + { + "ImportPath": "github.com/kubernetes/repo-infra/kazel", + "Rev": "d9bb9fdc907665c61c228baa64fed9b91c7dc1b0" + }, { "ImportPath": "github.com/libopenstorage/openstorage/api", "Rev": "093a0c3888753c2056e7373183693d670c6bba01" @@ -2088,6 +2118,11 @@ "Comment": "v1.1.0-2-g8bdf7d1", "Rev": "8bdf7d1a087ccc975cf37dd6507da50698fd19ca" }, + { + "ImportPath": "github.com/mattn/go-shellwords", + "Comment": "v1.0.3-20-gf8471b0", + "Rev": "f8471b0a71ded0ab910825ee2cf230f25de000f1" + }, { "ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil", "Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a" @@ -2119,12 +2154,18 @@ "Rev": "53818660ed4955e899c0bcafa97299a388bd7c8e" }, { - "ImportPath": "github.com/mohae/deepcopy", - "Rev": "491d3605edfb866af34a48075bd4355ac1bf46ca" + "ImportPath": "github.com/modern-go/concurrent", + "Comment": "1.0.3", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" }, { - "ImportPath": "github.com/mreiferson/go-httpclient", - "Rev": "31f0106b4474f14bc441575c19d3a5fa21aa1f6c" + "ImportPath": "github.com/modern-go/reflect2", + "Comment": "1.0.0-9-g05fbef0", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, + { + "ImportPath": "github.com/mohae/deepcopy", + "Rev": "491d3605edfb866af34a48075bd4355ac1bf46ca" }, { "ImportPath": "github.com/mrunalp/fileutils", @@ -2447,15 +2488,10 @@ "ImportPath": "github.com/pborman/uuid", "Rev": "ca53cad383cad2479bbba7f7a1a05797ec1386e4" }, - { - "ImportPath": "github.com/pelletier/go-buffruneio", - "Comment": "v0.1.0", - "Rev": "df1e16fde7fc330a0ca68167c23bf7ed6ac31d6d" - }, { "ImportPath": "github.com/pelletier/go-toml", - "Comment": "v0.3.5-10-g0049ab3", - "Rev": "0049ab3dc4c4c70a9eee23087437b69c0dde2130" + "Comment": "v1.0.1", + "Rev": "16398bac157da96aa88f98a2df640c7f32af1da2" }, { "ImportPath": "github.com/peterbourgon/diskv", @@ -2582,13 +2618,13 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Comment": "v0.0.1-32-g6644d46", - "Rev": "6644d46b81fa1831979c4cded0106e774e0ef0ab" + "Comment": "v0.0.1-34-gc439c4f", + "Rev": "c439c4fa093711d42e1b01acb1235b52004753c1" }, { "ImportPath": "github.com/spf13/cobra/doc", - "Comment": "v0.0.1-32-g6644d46", - "Rev": "6644d46b81fa1831979c4cded0106e774e0ef0ab" + "Comment": "v0.0.1-34-gc439c4f", + "Rev": "c439c4fa093711d42e1b01acb1235b52004753c1" }, { "ImportPath": "github.com/spf13/jwalterweatherman", @@ -2629,18 +2665,18 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Comment": "v1.1.4-66-gf6abca5", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Comment": "v1.2.1-14-gc679ae2", + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/stretchr/testify/mock", - "Comment": "v1.1.4-66-gf6abca5", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Comment": "v1.2.1-14-gc679ae2", + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/stretchr/testify/require", - "Comment": "v1.1.4-66-gf6abca5", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Comment": "v1.2.1-14-gc679ae2", + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/syndtr/gocapability/capability", @@ -2648,8 +2684,8 @@ }, { "ImportPath": "github.com/tools/godep", - "Comment": "v79", - "Rev": "f15f6db5da33a4ac48be83e20b9dd838e14f117b" + "Comment": "v80", + "Rev": "ce0bfadeb516ab23c845a85c4b0eae421ec9614b" }, { "ImportPath": "github.com/ugorji/go/codec", @@ -2669,113 +2705,148 @@ }, { "ImportPath": "github.com/vmware/govmomi", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/find", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/list", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" + }, + { + "ImportPath": "github.com/vmware/govmomi/lookup", + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" + }, + { + "ImportPath": "github.com/vmware/govmomi/lookup/methods", + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" + }, + { + "ImportPath": "github.com/vmware/govmomi/lookup/simulator", + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" + }, + { + "ImportPath": "github.com/vmware/govmomi/lookup/types", + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/nfc", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/object", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/pbm", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/pbm/methods", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/pbm/types", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/property", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/session", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/simulator", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/simulator/esx", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/simulator/vpx", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" + }, + { + "ImportPath": "github.com/vmware/govmomi/sts", + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" + }, + { + "ImportPath": "github.com/vmware/govmomi/sts/internal", + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" + }, + { + "ImportPath": "github.com/vmware/govmomi/sts/simulator", + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/task", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/vim25", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/vim25/debug", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/vim25/methods", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/vim25/mo", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/vim25/progress", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/vim25/soap", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/vim25/types", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/govmomi/vim25/xml", - "Comment": "v0.16.0-97-g0f82f03", - "Rev": "0f82f03a2bbf14037d2331cf02f1d4157bbef6cc" + "Comment": "v0.17.1-46-ge70dd44", + "Rev": "e70dd44f80baf671099254d675eb278529038234" }, { "ImportPath": "github.com/vmware/photon-controller-go-sdk/SSPI", @@ -2803,61 +2874,68 @@ "Rev": "07dd2e8dfe18522e9c447ba95f2fe95262f63bb2" }, { - "ImportPath": "github.com/xyproto/simpleredis", - "Comment": "v1.0-13-g5292687", - "Rev": "5292687f5379e01054407da44d7c4590a61fd3de" + "ImportPath": "golang.org/x/crypto/bcrypt", + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { - "ImportPath": "go4.org/errorutil", - "Rev": "03efcb870d84809319ea509714dd6d19a1498483" + "ImportPath": "golang.org/x/crypto/blowfish", + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { - "ImportPath": "golang.org/x/crypto/bcrypt", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "ImportPath": "golang.org/x/crypto/cryptobyte", + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { - "ImportPath": "golang.org/x/crypto/blowfish", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "ImportPath": "golang.org/x/crypto/cryptobyte/asn1", + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/curve25519", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/ed25519", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/ed25519/internal/edwards25519", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" + }, + { + "ImportPath": "golang.org/x/crypto/internal/chacha20", + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/nacl/secretbox", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" + }, + { + "ImportPath": "golang.org/x/crypto/ocsp", + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/pkcs12", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/pkcs12/internal/rc2", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/poly1305", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/salsa20/salsa", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/ssh", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/exp/inotify", @@ -3031,53 +3109,49 @@ "ImportPath": "golang.org/x/tools/imports", "Rev": "2382e3994d48b1d22acc2c86bcad0a2aff028e32" }, - { - "ImportPath": "google.golang.org/api/cloudmonitoring/v2beta2", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" - }, { "ImportPath": "google.golang.org/api/compute/v0.alpha", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/compute/v0.beta", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/compute/v1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/container/v1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/gensupport", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/googleapi", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/googleapi/internal/uritemplates", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/logging/v2beta1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/monitoring/v3", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/api/pubsub/v1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { - "ImportPath": "google.golang.org/api/tpu/v1alpha1", - "Rev": "7f657476956314fee258816aaf81c0ff65cf8bee" + "ImportPath": "google.golang.org/api/tpu/v1", + "Rev": "8e296ef260056b6323d10727db40512dac6d92d5" }, { "ImportPath": "google.golang.org/genproto/googleapis/api/annotations", @@ -3112,11 +3186,6 @@ "Comment": "v1.7.5", "Rev": "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e" }, - { - "ImportPath": "google.golang.org/grpc/grpclb/grpc_lb_v1", - "Comment": "v1.7.5", - "Rev": "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e" - }, { "ImportPath": "google.golang.org/grpc/grpclb/grpc_lb_v1/messages", "Comment": "v1.7.5", @@ -3288,47 +3357,51 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/aggregator", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/generators", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" + }, + { + "ImportPath": "k8s.io/kube-openapi/pkg/util/proto/testing", + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto/validation", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/utils/clock", - "Rev": "aedf551cdb8b0119df3a19c65fde413a13b34997" + "Rev": "258e2a2fa64568210fbd6267cf1d8fd87c3cb86e" }, { "ImportPath": "k8s.io/utils/exec", - "Rev": "aedf551cdb8b0119df3a19c65fde413a13b34997" + "Rev": "258e2a2fa64568210fbd6267cf1d8fd87c3cb86e" }, { "ImportPath": "k8s.io/utils/exec/testing", - "Rev": "aedf551cdb8b0119df3a19c65fde413a13b34997" + "Rev": "258e2a2fa64568210fbd6267cf1d8fd87c3cb86e" }, { "ImportPath": "vbom.ml/util/sortorder", diff --git a/vendor/k8s.io/kubernetes/Godeps/LICENSES b/vendor/k8s.io/kubernetes/Godeps/LICENSES index a41c79856..99dccec64 100644 --- a/vendor/k8s.io/kubernetes/Godeps/LICENSES +++ b/vendor/k8s.io/kubernetes/Godeps/LICENSES @@ -917,9 +917,66 @@ SUBDIRECTORIES ================================================================================ -= vendor/github.com/appc/spec/schema licensed under: = += vendor/github.com/armon/circbuf licensed under: = -Apache License +The MIT License (MIT) + +Copyright (c) 2013 Armon Dadgar + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/armon/circbuf/LICENSE d2d77030c0183e3d1e66d26dc1f243be +================================================================================ + + +================================================================================ += vendor/github.com/asaskevich/govalidator licensed under: = + +The MIT License (MIT) + +Copyright (c) 2014 Alex Saskevich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. += vendor/github.com/asaskevich/govalidator/LICENSE 9548240229052f3a5f5bdf14ac19bbe3 +================================================================================ + + +================================================================================ += vendor/github.com/aws/aws-sdk-go/aws licensed under: = + + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1099,7 +1156,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -1107,7 +1164,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1121,15 +1178,15 @@ Apache License See the License for the specific language governing permissions and limitations under the License. - -= vendor/github.com/appc/spec/LICENSE d2794c0df5b907fdace235a619d80314 += vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/appc/spec/schema/common licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/awserr licensed under: = -Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1309,7 +1366,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -1317,7 +1374,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1331,15 +1388,225 @@ Apache License See the License for the specific language governing permissions and limitations under the License. += vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/aws/aws-sdk-go/aws/awsutil licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. -= vendor/github.com/appc/spec/LICENSE d2794c0df5b907fdace235a619d80314 += vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/appc/spec/schema/types licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/client licensed under: = -Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1519,7 +1786,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -1527,7 +1794,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1541,15 +1808,15 @@ Apache License See the License for the specific language governing permissions and limitations under the License. - -= vendor/github.com/appc/spec/LICENSE d2794c0df5b907fdace235a619d80314 += vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/appc/spec/schema/types/resource licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/client/metadata licensed under: = -Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1729,7 +1996,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -1737,7 +2004,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1751,69 +2018,222 @@ Apache License See the License for the specific language governing permissions and limitations under the License. - -= vendor/github.com/appc/spec/LICENSE d2794c0df5b907fdace235a619d80314 += vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/armon/circbuf licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/corehandlers licensed under: = -The MIT License (MIT) -Copyright (c) 2013 Armon Dadgar + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + 1. Definitions. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -= vendor/github.com/armon/circbuf/LICENSE d2d77030c0183e3d1e66d26dc1f243be -================================================================================ + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -================================================================================ -= vendor/github.com/asaskevich/govalidator licensed under: = + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -The MIT License (MIT) + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -Copyright (c) 2014 Alex Saskevich + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -= vendor/github.com/asaskevich/govalidator/LICENSE 9548240229052f3a5f5bdf14ac19bbe3 + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + += vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/credentials licensed under: = Apache License @@ -2023,7 +2443,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/awserr licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds licensed under: = Apache License @@ -2233,7 +2653,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/awsutil licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds licensed under: = Apache License @@ -2443,7 +2863,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/client licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds licensed under: = Apache License @@ -2653,7 +3073,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/client/metadata licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/defaults licensed under: = Apache License @@ -2863,7 +3283,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/corehandlers licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/ec2metadata licensed under: = Apache License @@ -3073,7 +3493,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/credentials licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/endpoints licensed under: = Apache License @@ -3283,7 +3703,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/request licensed under: = Apache License @@ -3493,7 +3913,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/session licensed under: = Apache License @@ -3703,7 +4123,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds licensed under: = += vendor/github.com/aws/aws-sdk-go/aws/signer/v4 licensed under: = Apache License @@ -3913,7 +4333,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/defaults licensed under: = += vendor/github.com/aws/aws-sdk-go/internal/shareddefaults licensed under: = Apache License @@ -4123,7 +4543,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/ec2metadata licensed under: = += vendor/github.com/aws/aws-sdk-go/private/protocol licensed under: = Apache License @@ -4333,7 +4753,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/endpoints licensed under: = += vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query licensed under: = Apache License @@ -4543,7 +4963,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/request licensed under: = += vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil licensed under: = Apache License @@ -4753,7 +5173,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/session licensed under: = += vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc licensed under: = Apache License @@ -4963,7 +5383,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/aws/signer/v4 licensed under: = += vendor/github.com/aws/aws-sdk-go/private/protocol/query licensed under: = Apache License @@ -5173,7 +5593,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/internal/shareddefaults licensed under: = += vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil licensed under: = Apache License @@ -5383,7 +5803,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/private/protocol licensed under: = += vendor/github.com/aws/aws-sdk-go/private/protocol/rest licensed under: = Apache License @@ -5593,7 +6013,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/private/protocol/ec2query licensed under: = += vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil licensed under: = Apache License @@ -5803,7 +6223,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil licensed under: = += vendor/github.com/aws/aws-sdk-go/service/autoscaling licensed under: = Apache License @@ -6013,7 +6433,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc licensed under: = += vendor/github.com/aws/aws-sdk-go/service/ec2 licensed under: = Apache License @@ -6223,7 +6643,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/private/protocol/query licensed under: = += vendor/github.com/aws/aws-sdk-go/service/ecr licensed under: = Apache License @@ -6433,7 +6853,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil licensed under: = += vendor/github.com/aws/aws-sdk-go/service/elb licensed under: = Apache License @@ -6643,7 +7063,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/private/protocol/rest licensed under: = += vendor/github.com/aws/aws-sdk-go/service/elbv2 licensed under: = Apache License @@ -6853,7 +7273,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil licensed under: = += vendor/github.com/aws/aws-sdk-go/service/kms licensed under: = Apache License @@ -7063,7 +7483,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/service/autoscaling licensed under: = += vendor/github.com/aws/aws-sdk-go/service/sts licensed under: = Apache License @@ -7273,7 +7693,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/aws/aws-sdk-go/service/ec2 licensed under: = += vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute licensed under: = Apache License @@ -7464,7 +7884,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2016 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -7478,12 +7898,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 ================================================================================ ================================================================================ -= vendor/github.com/aws/aws-sdk-go/service/ecr licensed under: = += vendor/github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry licensed under: = Apache License @@ -7674,7 +8094,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2016 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -7688,12 +8108,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 ================================================================================ ================================================================================ -= vendor/github.com/aws/aws-sdk-go/service/elb licensed under: = += vendor/github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network licensed under: = Apache License @@ -7884,7 +8304,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2016 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -7898,12 +8318,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 ================================================================================ ================================================================================ -= vendor/github.com/aws/aws-sdk-go/service/elbv2 licensed under: = += vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage licensed under: = Apache License @@ -8094,7 +8514,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2016 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -8108,12 +8528,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 ================================================================================ ================================================================================ -= vendor/github.com/aws/aws-sdk-go/service/kms licensed under: = += vendor/github.com/Azure/azure-sdk-for-go/storage licensed under: = Apache License @@ -8304,7 +8724,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2016 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -8318,12 +8738,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 ================================================================================ ================================================================================ -= vendor/github.com/aws/aws-sdk-go/service/sts licensed under: = += vendor/github.com/Azure/azure-sdk-for-go/version licensed under: = Apache License @@ -8514,7 +8934,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2016 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -8528,12 +8948,70 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/aws/aws-sdk-go/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 ================================================================================ ================================================================================ -= vendor/github.com/Azure/azure-sdk-for-go/arm/compute licensed under: = += vendor/github.com/Azure/go-ansiterm licensed under: = + +The MIT License (MIT) + +Copyright (c) 2015 Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + += vendor/github.com/Azure/go-ansiterm/LICENSE 6000442264015a23894024af9930539b +================================================================================ + + +================================================================================ += vendor/github.com/Azure/go-ansiterm/winterm licensed under: = + +The MIT License (MIT) + +Copyright (c) 2015 Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + += vendor/github.com/Azure/go-ansiterm/LICENSE 6000442264015a23894024af9930539b +================================================================================ + + +================================================================================ += vendor/github.com/Azure/go-autorest/autorest licensed under: = Apache License @@ -8713,18 +9191,7 @@ SOFTWARE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 Microsoft Corporation + Copyright 2015 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -8738,12 +9205,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 += vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b ================================================================================ ================================================================================ -= vendor/github.com/Azure/azure-sdk-for-go/arm/containerregistry licensed under: = += vendor/github.com/Azure/go-autorest/autorest/adal licensed under: = Apache License @@ -8923,18 +9390,7 @@ SOFTWARE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 Microsoft Corporation + Copyright 2015 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -8948,12 +9404,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 += vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b ================================================================================ ================================================================================ -= vendor/github.com/Azure/azure-sdk-for-go/arm/disk licensed under: = += vendor/github.com/Azure/go-autorest/autorest/azure licensed under: = Apache License @@ -9133,18 +9589,7 @@ SOFTWARE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 Microsoft Corporation + Copyright 2015 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -9158,12 +9603,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 += vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b ================================================================================ ================================================================================ -= vendor/github.com/Azure/azure-sdk-for-go/arm/network licensed under: = += vendor/github.com/Azure/go-autorest/autorest/date licensed under: = Apache License @@ -9343,18 +9788,7 @@ SOFTWARE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 Microsoft Corporation + Copyright 2015 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -9368,12 +9802,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 += vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b ================================================================================ ================================================================================ -= vendor/github.com/Azure/azure-sdk-for-go/arm/storage licensed under: = += vendor/github.com/Azure/go-autorest/autorest/to licensed under: = Apache License @@ -9553,18 +9987,7 @@ SOFTWARE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 Microsoft Corporation + Copyright 2015 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -9578,12 +10001,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 += vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b ================================================================================ ================================================================================ -= vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute licensed under: = += vendor/github.com/Azure/go-autorest/autorest/validation licensed under: = Apache License @@ -9763,18 +10186,7 @@ SOFTWARE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 Microsoft Corporation + Copyright 2015 Microsoft Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -9788,12 +10200,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 += vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b ================================================================================ ================================================================================ -= vendor/github.com/Azure/azure-sdk-for-go/storage licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/cmd/gazelle licensed under: = Apache License @@ -9984,7 +10396,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2016 Microsoft Corporation + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -9998,70 +10410,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/azure-sdk-for-go/LICENSE cce6fd055830ca30ff78fdf077e870d6 += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/Azure/go-ansiterm licensed under: = - -The MIT License (MIT) - -Copyright (c) 2015 Microsoft Corporation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -= vendor/github.com/Azure/go-ansiterm/LICENSE 6000442264015a23894024af9930539b -================================================================================ - - -================================================================================ -= vendor/github.com/Azure/go-ansiterm/winterm licensed under: = - -The MIT License (MIT) - -Copyright (c) 2015 Microsoft Corporation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -= vendor/github.com/Azure/go-ansiterm/LICENSE 6000442264015a23894024af9930539b -================================================================================ - - -================================================================================ -= vendor/github.com/Azure/go-autorest/autorest licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/internal/config licensed under: = Apache License @@ -10241,7 +10595,18 @@ THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2015 Microsoft Corporation + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -10255,12 +10620,12 @@ THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/Azure/go-autorest/autorest/adal licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/internal/label licensed under: = Apache License @@ -10440,7 +10805,18 @@ THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2015 Microsoft Corporation + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -10454,12 +10830,12 @@ THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/Azure/go-autorest/autorest/azure licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/internal/merger licensed under: = Apache License @@ -10639,7 +11015,18 @@ THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2015 Microsoft Corporation + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -10653,12 +11040,12 @@ THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/Azure/go-autorest/autorest/date licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/internal/packages licensed under: = Apache License @@ -10838,7 +11225,18 @@ THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2015 Microsoft Corporation + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -10852,12 +11250,12 @@ THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/Azure/go-autorest/autorest/to licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/internal/pathtools licensed under: = Apache License @@ -11037,7 +11435,18 @@ THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2015 Microsoft Corporation + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -11051,12 +11460,12 @@ THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/Azure/go-autorest/autorest/validation licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/internal/repos licensed under: = Apache License @@ -11236,7 +11645,18 @@ THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2015 Microsoft Corporation + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -11250,725 +11670,682 @@ THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/Azure/go-autorest/LICENSE a250e5ac3848f2acadb5adcb9555c18b += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/beorn7/perks/quantile licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/internal/resolve licensed under: = -Copyright (C) 2013 Blake Mizerany -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 1. Definitions. -= vendor/github.com/beorn7/perks/LICENSE 0d0738f37ee8dc0b5f88a32e83c60198 -================================================================================ + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -================================================================================ -= vendor/github.com/blang/semver licensed under: = + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -The MIT License + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Copyright (c) 2014 Benedikt Lang + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -= vendor/github.com/blang/semver/LICENSE 5a3ade42a900439691ebc22013660cae -================================================================================ + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -================================================================================ -= vendor/github.com/chai2010/gettext-go/gettext licensed under: = + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -Copyright 2013 ChaiShushan . All rights reserved. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -= vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 -================================================================================ + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -================================================================================ -= vendor/github.com/chai2010/gettext-go/gettext/mo licensed under: = + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -Copyright 2013 ChaiShushan . All rights reserved. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -= vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 -================================================================================ + END OF TERMS AND CONDITIONS + APPENDIX: How to apply the Apache License to your work. -================================================================================ -= vendor/github.com/chai2010/gettext-go/gettext/plural licensed under: = + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -Copyright 2013 ChaiShushan . All rights reserved. + Copyright [yyyy] [name of copyright owner] -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: + 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 - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. + http://www.apache.org/licenses/LICENSE-2.0 -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 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. -= vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/chai2010/gettext-go/gettext/po licensed under: = - -Copyright 2013 ChaiShushan . All rights reserved. += vendor/github.com/bazelbuild/bazel-gazelle/internal/rules licensed under: = -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -= vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 -================================================================================ + 1. Definitions. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -================================================================================ -= vendor/github.com/client9/misspell licensed under: = + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -The MIT License (MIT) + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -Copyright (c) 2015-2017 Nick Galbreath + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -= vendor/github.com/client9/misspell/LICENSE 387f6b7d6741c8a7f4f7e3c2bbdf97e4 -================================================================================ + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -================================================================================ -= vendor/github.com/client9/misspell/cmd/misspell licensed under: = + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -The MIT License (MIT) + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -Copyright (c) 2015-2017 Nick Galbreath - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -= vendor/github.com/client9/misspell/LICENSE 387f6b7d6741c8a7f4f7e3c2bbdf97e4 -================================================================================ + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -================================================================================ -= vendor/github.com/cloudflare/cfssl/auth licensed under: = + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -Copyright (c) 2014 CloudFlare Inc. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + END OF TERMS AND CONDITIONS -================================================================================ -= vendor/github.com/cloudflare/cfssl/certdb licensed under: = + APPENDIX: How to apply the Apache License to your work. -Copyright (c) 2014 CloudFlare Inc. + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: + Copyright [yyyy] [name of copyright owner] -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. + 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 -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. + http://www.apache.org/licenses/LICENSE-2.0 -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 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. -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/cloudflare/cfssl/config licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/internal/version licensed under: = -Copyright (c) 2014 CloudFlare Inc. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + 1. Definitions. -================================================================================ -= vendor/github.com/cloudflare/cfssl/crypto/pkcs7 licensed under: = + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -Copyright (c) 2014 CloudFlare Inc. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -================================================================================ -= vendor/github.com/cloudflare/cfssl/csr licensed under: = + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -Copyright (c) 2014 CloudFlare Inc. + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -================================================================================ -= vendor/github.com/cloudflare/cfssl/errors licensed under: = + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -Copyright (c) 2014 CloudFlare Inc. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + END OF TERMS AND CONDITIONS -================================================================================ -= vendor/github.com/cloudflare/cfssl/helpers licensed under: = + APPENDIX: How to apply the Apache License to your work. -Copyright (c) 2014 CloudFlare Inc. + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: + Copyright [yyyy] [name of copyright owner] -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. + 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 -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. + http://www.apache.org/licenses/LICENSE-2.0 -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 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. -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/cloudflare/cfssl/helpers/derhelpers licensed under: = += vendor/github.com/bazelbuild/bazel-gazelle/internal/wspace licensed under: = -Copyright (c) 2014 CloudFlare Inc. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. + 1. Definitions. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -================================================================================ -= vendor/github.com/cloudflare/cfssl/info licensed under: = + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Copyright (c) 2014 CloudFlare Inc. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ - - -================================================================================ -= vendor/github.com/cloudflare/cfssl/log licensed under: = - -Copyright (c) 2014 CloudFlare Inc. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ - - -================================================================================ -= vendor/github.com/cloudflare/cfssl/ocsp/config licensed under: = - -Copyright (c) 2014 CloudFlare Inc. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ - - -================================================================================ -= vendor/github.com/cloudflare/cfssl/signer licensed under: = - -Copyright (c) 2014 CloudFlare Inc. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ - - -================================================================================ -= vendor/github.com/cloudflare/cfssl/signer/local licensed under: = - -Copyright (c) 2014 CloudFlare Inc. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 -================================================================================ - - -================================================================================ -= vendor/github.com/clusterhq/flocker-go licensed under: = - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the @@ -12108,7 +12485,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. END OF TERMS AND CONDITIONS - Copyright 2014-2016 ClusterHQ + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -12122,250 +12510,756 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/clusterhq/flocker-go/LICENSE d8103d9796cd0e951379d0834edad066 += vendor/github.com/bazelbuild/bazel-gazelle/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/cockroachdb/cmux licensed under: = += vendor/github.com/bazelbuild/buildtools/build licensed under: = +Copyright 2016 Google Inc. All Rights Reserved. - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +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 - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + http://www.apache.org/licenses/LICENSE-2.0 - 1. Definitions. +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. - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. += vendor/github.com/bazelbuild/buildtools/LICENSE adb52eb384caedba181cd51fbcdf4b99 +================================================================================ - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. +================================================================================ += vendor/github.com/bazelbuild/buildtools/tables licensed under: = - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. +Copyright 2016 Google Inc. All Rights Reserved. - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. +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 - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. + http://www.apache.org/licenses/LICENSE-2.0 - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). +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. - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. += vendor/github.com/bazelbuild/buildtools/LICENSE adb52eb384caedba181cd51fbcdf4b99 +================================================================================ - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. +================================================================================ += vendor/github.com/beorn7/perks/quantile licensed under: = - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. +Copyright (C) 2013 Blake Mizerany - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and += vendor/github.com/beorn7/perks/LICENSE 0d0738f37ee8dc0b5f88a32e83c60198 +================================================================================ - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. +================================================================================ += vendor/github.com/blang/semver licensed under: = - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. +The MIT License - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. +Copyright (c) 2014 Benedikt Lang - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - END OF TERMS AND CONDITIONS += vendor/github.com/blang/semver/LICENSE 5a3ade42a900439691ebc22013660cae +================================================================================ - APPENDIX: How to apply the Apache License to your work. - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. +================================================================================ += vendor/github.com/chai2010/gettext-go/gettext licensed under: = - Copyright [yyyy] [name of copyright owner] +Copyright 2013 ChaiShushan . All rights reserved. - 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 +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: - http://www.apache.org/licenses/LICENSE-2.0 + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. - 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. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -= vendor/github.com/cockroachdb/cmux/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 ================================================================================ ================================================================================ -= vendor/github.com/codedellemc/goscaleio licensed under: = += vendor/github.com/chai2010/gettext-go/gettext/mo licensed under: = -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +Copyright 2013 ChaiShushan . All rights reserved. - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: - 1. Definitions. + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. += vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 +================================================================================ - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. +================================================================================ += vendor/github.com/chai2010/gettext-go/gettext/plural licensed under: = - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation +Copyright 2013 ChaiShushan . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 +================================================================================ + + +================================================================================ += vendor/github.com/chai2010/gettext-go/gettext/po licensed under: = + +Copyright 2013 ChaiShushan . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 +================================================================================ + + +================================================================================ += vendor/github.com/client9/misspell licensed under: = + +The MIT License (MIT) + +Copyright (c) 2015-2017 Nick Galbreath + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + += vendor/github.com/client9/misspell/LICENSE 387f6b7d6741c8a7f4f7e3c2bbdf97e4 +================================================================================ + + +================================================================================ += vendor/github.com/client9/misspell/cmd/misspell licensed under: = + +The MIT License (MIT) + +Copyright (c) 2015-2017 Nick Galbreath + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + += vendor/github.com/client9/misspell/LICENSE 387f6b7d6741c8a7f4f7e3c2bbdf97e4 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/auth licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/certdb licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/config licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/crypto/pkcs7 licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/csr licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/errors licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/helpers licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/helpers/derhelpers licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/info licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/log licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/ocsp/config licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/signer licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/cloudflare/cfssl/signer/local licensed under: = + +Copyright (c) 2014 CloudFlare Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/cloudflare/cfssl/LICENSE 9bd1e7022303d9bbc29fda142f3e4fd0 +================================================================================ + + +================================================================================ += vendor/github.com/clusterhq/flocker-go licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical @@ -12516,18 +13410,7 @@ Apache License END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright 2014-2016 ClusterHQ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -12541,15 +13424,15 @@ Apache License See the License for the specific language governing permissions and limitations under the License. - -= vendor/github.com/codedellemc/goscaleio/LICENSE d2794c0df5b907fdace235a619d80314 += vendor/github.com/clusterhq/flocker-go/LICENSE d8103d9796cd0e951379d0834edad066 ================================================================================ ================================================================================ -= vendor/github.com/codedellemc/goscaleio/types/v1 licensed under: = += vendor/github.com/cockroachdb/cmux licensed under: = -Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -12729,7 +13612,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -12737,7 +13620,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -12751,44 +13634,14 @@ Apache License See the License for the specific language governing permissions and limitations under the License. - -= vendor/github.com/codedellemc/goscaleio/LICENSE d2794c0df5b907fdace235a619d80314 -================================================================================ - - -================================================================================ -= vendor/github.com/codegangsta/negroni licensed under: = - -The MIT License (MIT) - -Copyright (c) 2014 Jeremy Saenz - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -= vendor/github.com/codegangsta/negroni/LICENSE ad35fc390e5be785ef854a14a761a6a0 += vendor/github.com/cockroachdb/cmux/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/container-storage-interface/spec/lib/go/csi/v0 licensed under: = += vendor/github.com/codedellemc/goscaleio licensed under: = - Apache License +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -12990,14 +13843,15 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/container-storage-interface/spec/LICENSE e3fc50a88d0a364313df4b21ef20c29e + += vendor/github.com/codedellemc/goscaleio/LICENSE d2794c0df5b907fdace235a619d80314 ================================================================================ ================================================================================ -= vendor/github.com/containerd/console licensed under: = += vendor/github.com/codedellemc/goscaleio/types/v1 licensed under: = - Apache License +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -13177,7 +14031,7 @@ SOFTWARE. APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -13185,7 +14039,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -13199,17 +14053,17 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/containerd/console/LICENSE 86d3f3a95c324c9479bd8986968f4327 + += vendor/github.com/codedellemc/goscaleio/LICENSE d2794c0df5b907fdace235a619d80314 ================================================================================ ================================================================================ -= vendor/github.com/containerd/containerd/api/services/containers/v1 licensed under: = - += vendor/github.com/container-storage-interface/spec/lib/go/csi/v0 licensed under: = Apache License Version 2.0, January 2004 - https://www.apache.org/licenses/ + http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -13384,13 +14238,24 @@ SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2013-2016 Docker, Inc. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} 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 - https://www.apache.org/licenses/LICENSE-2.0 + 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, @@ -13398,17 +14263,16 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/containerd/containerd/LICENSE.code aadc30f9c14d876ded7bedc0afd2d3d7 += vendor/github.com/container-storage-interface/spec/LICENSE e3fc50a88d0a364313df4b21ef20c29e ================================================================================ ================================================================================ -= vendor/github.com/containerd/containerd/api/services/tasks/v1 licensed under: = - += vendor/github.com/containerd/console licensed under: = Apache License Version 2.0, January 2004 - https://www.apache.org/licenses/ + http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -13583,13 +14447,24 @@ SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2013-2016 Docker, Inc. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] 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 - https://www.apache.org/licenses/LICENSE-2.0 + 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, @@ -13597,12 +14472,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/containerd/containerd/LICENSE.code aadc30f9c14d876ded7bedc0afd2d3d7 += vendor/github.com/containerd/console/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/containerd/containerd/api/services/version/v1 licensed under: = += vendor/github.com/containerd/containerd/api/services/containers/v1 licensed under: = Apache License @@ -13801,7 +14676,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containerd/containerd/api/types licensed under: = += vendor/github.com/containerd/containerd/api/services/tasks/v1 licensed under: = Apache License @@ -14000,7 +14875,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containerd/containerd/api/types/task licensed under: = += vendor/github.com/containerd/containerd/api/services/version/v1 licensed under: = Apache License @@ -14199,7 +15074,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containerd/containerd/containers licensed under: = += vendor/github.com/containerd/containerd/api/types licensed under: = Apache License @@ -14398,7 +15273,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containerd/containerd/dialer licensed under: = += vendor/github.com/containerd/containerd/api/types/task licensed under: = Apache License @@ -14597,7 +15472,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containerd/containerd/errdefs licensed under: = += vendor/github.com/containerd/containerd/containers licensed under: = Apache License @@ -14796,7 +15671,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containerd/containerd/namespaces licensed under: = += vendor/github.com/containerd/containerd/dialer licensed under: = Apache License @@ -14995,11 +15870,12 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containernetworking/cni/libcni licensed under: = += vendor/github.com/containerd/containerd/errdefs licensed under: = + Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -15174,24 +16050,13 @@ SOFTWARE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright 2013-2016 Docker, Inc. 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 + https://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, @@ -15199,17 +16064,17 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. - -= vendor/github.com/containernetworking/cni/LICENSE fa818a259cbed7ce8bc2a22d35a464fc += vendor/github.com/containerd/containerd/LICENSE.code aadc30f9c14d876ded7bedc0afd2d3d7 ================================================================================ ================================================================================ -= vendor/github.com/containernetworking/cni/pkg/invoke licensed under: = += vendor/github.com/containerd/containerd/namespaces licensed under: = + Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -15384,24 +16249,13 @@ SOFTWARE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright 2013-2016 Docker, Inc. 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 + https://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, @@ -15409,13 +16263,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. - -= vendor/github.com/containernetworking/cni/LICENSE fa818a259cbed7ce8bc2a22d35a464fc += vendor/github.com/containerd/containerd/LICENSE.code aadc30f9c14d876ded7bedc0afd2d3d7 ================================================================================ ================================================================================ -= vendor/github.com/containernetworking/cni/pkg/types licensed under: = += vendor/github.com/containernetworking/cni/libcni licensed under: = Apache License Version 2.0, January 2004 @@ -15625,7 +16478,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containernetworking/cni/pkg/types/020 licensed under: = += vendor/github.com/containernetworking/cni/pkg/invoke licensed under: = Apache License Version 2.0, January 2004 @@ -15835,7 +16688,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containernetworking/cni/pkg/types/current licensed under: = += vendor/github.com/containernetworking/cni/pkg/types licensed under: = Apache License Version 2.0, January 2004 @@ -16045,7 +16898,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/containernetworking/cni/pkg/version licensed under: = += vendor/github.com/containernetworking/cni/pkg/types/020 licensed under: = Apache License Version 2.0, January 2004 @@ -16255,36 +17108,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/coreos/bbolt licensed under: = - -The MIT License (MIT) - -Copyright (c) 2013 Ben Johnson - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= vendor/github.com/coreos/bbolt/LICENSE 13b2a308eefa10d841e3bf2467dbe07a -================================================================================ - - -================================================================================ -= vendor/github.com/coreos/etcd/alarm licensed under: = - += vendor/github.com/containernetworking/cni/pkg/types/current licensed under: = Apache License Version 2.0, January 2004 @@ -16466,7 +17290,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -16474,7 +17298,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16488,13 +17312,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/coreos/etcd/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 + += vendor/github.com/containernetworking/cni/LICENSE fa818a259cbed7ce8bc2a22d35a464fc ================================================================================ ================================================================================ -= vendor/github.com/coreos/etcd/auth licensed under: = - += vendor/github.com/containernetworking/cni/pkg/version licensed under: = Apache License Version 2.0, January 2004 @@ -16676,7 +17500,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -16684,7 +17508,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16698,12 +17522,41 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/coreos/etcd/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 + += vendor/github.com/containernetworking/cni/LICENSE fa818a259cbed7ce8bc2a22d35a464fc ================================================================================ ================================================================================ -= vendor/github.com/coreos/etcd/auth/authpb licensed under: = += vendor/github.com/coreos/bbolt licensed under: = + +The MIT License (MIT) + +Copyright (c) 2013 Ben Johnson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/coreos/bbolt/LICENSE 13b2a308eefa10d841e3bf2467dbe07a +================================================================================ + + +================================================================================ += vendor/github.com/coreos/etcd/alarm licensed under: = Apache License @@ -16913,7 +17766,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/client licensed under: = += vendor/github.com/coreos/etcd/auth licensed under: = Apache License @@ -17123,7 +17976,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/clientv3 licensed under: = += vendor/github.com/coreos/etcd/auth/authpb licensed under: = Apache License @@ -17333,7 +18186,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/clientv3/concurrency licensed under: = += vendor/github.com/coreos/etcd/client licensed under: = Apache License @@ -17543,7 +18396,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/clientv3/namespace licensed under: = += vendor/github.com/coreos/etcd/clientv3 licensed under: = Apache License @@ -17753,7 +18606,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/clientv3/naming licensed under: = += vendor/github.com/coreos/etcd/clientv3/concurrency licensed under: = Apache License @@ -17963,7 +18816,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/compactor licensed under: = += vendor/github.com/coreos/etcd/clientv3/namespace licensed under: = Apache License @@ -18173,7 +19026,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/discovery licensed under: = += vendor/github.com/coreos/etcd/clientv3/naming licensed under: = Apache License @@ -18383,7 +19236,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/embed licensed under: = += vendor/github.com/coreos/etcd/compactor licensed under: = Apache License @@ -18593,7 +19446,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/error licensed under: = += vendor/github.com/coreos/etcd/discovery licensed under: = Apache License @@ -18803,7 +19656,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver licensed under: = += vendor/github.com/coreos/etcd/embed licensed under: = Apache License @@ -19013,7 +19866,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api licensed under: = += vendor/github.com/coreos/etcd/error licensed under: = Apache License @@ -19223,7 +20076,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/etcdhttp licensed under: = += vendor/github.com/coreos/etcd/etcdserver licensed under: = Apache License @@ -19433,7 +20286,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v2http licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api licensed under: = Apache License @@ -19643,7 +20496,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v2http/httptypes licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/etcdhttp licensed under: = Apache License @@ -19853,7 +20706,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v3client licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v2http licensed under: = Apache License @@ -20063,7 +20916,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v3election licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v2http/httptypes licensed under: = Apache License @@ -20273,7 +21126,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v3client licensed under: = Apache License @@ -20483,7 +21336,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v3election licensed under: = Apache License @@ -20693,7 +21546,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v3lock licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb licensed under: = Apache License @@ -20903,7 +21756,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw licensed under: = Apache License @@ -21113,7 +21966,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v3lock licensed under: = Apache License @@ -21323,7 +22176,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v3rpc licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb licensed under: = Apache License @@ -21533,7 +22386,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw licensed under: = Apache License @@ -21743,7 +22596,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/auth licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v3rpc licensed under: = Apache License @@ -21953,7 +22806,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/etcdserverpb licensed under: = += vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes licensed under: = Apache License @@ -22163,7 +23016,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/gw licensed under: = += vendor/github.com/coreos/etcd/etcdserver/auth licensed under: = Apache License @@ -22373,7 +23226,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/membership licensed under: = += vendor/github.com/coreos/etcd/etcdserver/etcdserverpb licensed under: = Apache License @@ -22583,7 +23436,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/etcdserver/stats licensed under: = += vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/gw licensed under: = Apache License @@ -22793,7 +23646,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/integration licensed under: = += vendor/github.com/coreos/etcd/etcdserver/membership licensed under: = Apache License @@ -23003,7 +23856,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/lease licensed under: = += vendor/github.com/coreos/etcd/etcdserver/stats licensed under: = Apache License @@ -23213,7 +24066,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/lease/leasehttp licensed under: = += vendor/github.com/coreos/etcd/integration licensed under: = Apache License @@ -23423,7 +24276,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/lease/leasepb licensed under: = += vendor/github.com/coreos/etcd/lease licensed under: = Apache License @@ -23633,7 +24486,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/mvcc licensed under: = += vendor/github.com/coreos/etcd/lease/leasehttp licensed under: = Apache License @@ -23843,7 +24696,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/mvcc/backend licensed under: = += vendor/github.com/coreos/etcd/lease/leasepb licensed under: = Apache License @@ -24053,7 +24906,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/mvcc/mvccpb licensed under: = += vendor/github.com/coreos/etcd/mvcc licensed under: = Apache License @@ -24263,7 +25116,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/adt licensed under: = += vendor/github.com/coreos/etcd/mvcc/backend licensed under: = Apache License @@ -24473,7 +25326,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/contention licensed under: = += vendor/github.com/coreos/etcd/mvcc/mvccpb licensed under: = Apache License @@ -24683,7 +25536,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/cors licensed under: = += vendor/github.com/coreos/etcd/pkg/adt licensed under: = Apache License @@ -24893,7 +25746,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/cpuutil licensed under: = += vendor/github.com/coreos/etcd/pkg/contention licensed under: = Apache License @@ -25103,7 +25956,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/crc licensed under: = += vendor/github.com/coreos/etcd/pkg/cors licensed under: = Apache License @@ -25313,7 +26166,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/debugutil licensed under: = += vendor/github.com/coreos/etcd/pkg/cpuutil licensed under: = Apache License @@ -25523,7 +26376,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/fileutil licensed under: = += vendor/github.com/coreos/etcd/pkg/crc licensed under: = Apache License @@ -25733,7 +26586,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/httputil licensed under: = += vendor/github.com/coreos/etcd/pkg/debugutil licensed under: = Apache License @@ -25943,7 +26796,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/idutil licensed under: = += vendor/github.com/coreos/etcd/pkg/fileutil licensed under: = Apache License @@ -26153,7 +27006,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/ioutil licensed under: = += vendor/github.com/coreos/etcd/pkg/httputil licensed under: = Apache License @@ -26363,7 +27216,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/logutil licensed under: = += vendor/github.com/coreos/etcd/pkg/idutil licensed under: = Apache License @@ -26573,7 +27426,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/monotime licensed under: = += vendor/github.com/coreos/etcd/pkg/ioutil licensed under: = Apache License @@ -26783,7 +27636,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/netutil licensed under: = += vendor/github.com/coreos/etcd/pkg/logutil licensed under: = Apache License @@ -26993,7 +27846,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/pathutil licensed under: = += vendor/github.com/coreos/etcd/pkg/monotime licensed under: = Apache License @@ -27203,7 +28056,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/pbutil licensed under: = += vendor/github.com/coreos/etcd/pkg/netutil licensed under: = Apache License @@ -27413,7 +28266,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/runtime licensed under: = += vendor/github.com/coreos/etcd/pkg/pathutil licensed under: = Apache License @@ -27623,7 +28476,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/schedule licensed under: = += vendor/github.com/coreos/etcd/pkg/pbutil licensed under: = Apache License @@ -27833,7 +28686,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/srv licensed under: = += vendor/github.com/coreos/etcd/pkg/runtime licensed under: = Apache License @@ -28043,7 +28896,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/testutil licensed under: = += vendor/github.com/coreos/etcd/pkg/schedule licensed under: = Apache License @@ -28253,7 +29106,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/tlsutil licensed under: = += vendor/github.com/coreos/etcd/pkg/srv licensed under: = Apache License @@ -28463,7 +29316,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/transport licensed under: = += vendor/github.com/coreos/etcd/pkg/testutil licensed under: = Apache License @@ -28673,7 +29526,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/types licensed under: = += vendor/github.com/coreos/etcd/pkg/tlsutil licensed under: = Apache License @@ -28883,7 +29736,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/pkg/wait licensed under: = += vendor/github.com/coreos/etcd/pkg/transport licensed under: = Apache License @@ -29093,7 +29946,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/proxy/grpcproxy licensed under: = += vendor/github.com/coreos/etcd/pkg/types licensed under: = Apache License @@ -29303,7 +30156,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/proxy/grpcproxy/adapter licensed under: = += vendor/github.com/coreos/etcd/pkg/wait licensed under: = Apache License @@ -29513,7 +30366,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/proxy/grpcproxy/cache licensed under: = += vendor/github.com/coreos/etcd/proxy/grpcproxy licensed under: = Apache License @@ -29723,7 +30576,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/raft licensed under: = += vendor/github.com/coreos/etcd/proxy/grpcproxy/adapter licensed under: = Apache License @@ -29933,7 +30786,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/raft/raftpb licensed under: = += vendor/github.com/coreos/etcd/proxy/grpcproxy/cache licensed under: = Apache License @@ -30143,7 +30996,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/rafthttp licensed under: = += vendor/github.com/coreos/etcd/raft licensed under: = Apache License @@ -30353,7 +31206,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/snap licensed under: = += vendor/github.com/coreos/etcd/raft/raftpb licensed under: = Apache License @@ -30563,7 +31416,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/snap/snappb licensed under: = += vendor/github.com/coreos/etcd/rafthttp licensed under: = Apache License @@ -30773,7 +31626,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/store licensed under: = += vendor/github.com/coreos/etcd/snap licensed under: = Apache License @@ -30983,7 +31836,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/version licensed under: = += vendor/github.com/coreos/etcd/snap/snappb licensed under: = Apache License @@ -31193,7 +32046,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/wal licensed under: = += vendor/github.com/coreos/etcd/store licensed under: = Apache License @@ -31403,7 +32256,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/etcd/wal/walpb licensed under: = += vendor/github.com/coreos/etcd/version licensed under: = Apache License @@ -31613,9 +32466,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/coreos/go-oidc licensed under: = += vendor/github.com/coreos/etcd/wal licensed under: = -Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -31795,7 +32649,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -31803,7 +32657,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -31817,13 +32671,12 @@ Apache License See the License for the specific language governing permissions and limitations under the License. - -= vendor/github.com/coreos/go-oidc/LICENSE d2794c0df5b907fdace235a619d80314 += vendor/github.com/coreos/etcd/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/coreos/go-semver/semver licensed under: = += vendor/github.com/coreos/etcd/wal/walpb licensed under: = Apache License @@ -32006,7 +32859,216 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + += vendor/github.com/coreos/etcd/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/coreos/go-oidc licensed under: = + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -32014,7 +33076,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -32028,190 +33090,202 @@ Apache License See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/coreos/go-semver/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 -================================================================================ - += vendor/github.com/coreos/go-oidc/LICENSE d2794c0df5b907fdace235a619d80314 ================================================================================ -= vendor/github.com/coreos/go-systemd/daemon licensed under: = -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -1. Definitions. +================================================================================ += vendor/github.com/coreos/go-semver/semver licensed under: = -"License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -"Legal Entity" shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, "control" means (i) the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -"You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License. + 1. Definitions. -"Source" form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -"Object" form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -"Work" shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -"Derivative Works" shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -"Contribution" shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -"submitted" means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as "Not a Contribution." + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -2. Grant of Copyright License. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -3. Grant of Patent License. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -4. Redistribution. + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -If the Work includes a "NOTICE" text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -5. Submission of Contributions. + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -6. Trademarks. + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -7. Disclaimer of Warranty. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -8. Limitation of Liability. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -9. Accepting Warranty or Additional Liability. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS -APPENDIX: How to apply the Apache License to your work + APPENDIX: How to apply the Apache License to your work. -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets "[]" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same "printed page" as the copyright notice for easier identification within -third-party archives. + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. Copyright [yyyy] [name of copyright owner] @@ -32219,7 +33293,7 @@ third-party archives. 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 + 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, @@ -32227,12 +33301,12 @@ third-party archives. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/coreos/go-systemd/LICENSE 19cbd64715b51267a47bf3750cc6a8a5 += vendor/github.com/coreos/go-semver/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/coreos/go-systemd/dbus licensed under: = += vendor/github.com/coreos/go-systemd/daemon licensed under: = Apache License Version 2.0, January 2004 @@ -32431,7 +33505,7 @@ third-party archives. ================================================================================ -= vendor/github.com/coreos/go-systemd/journal licensed under: = += vendor/github.com/coreos/go-systemd/dbus licensed under: = Apache License Version 2.0, January 2004 @@ -32630,7 +33704,7 @@ third-party archives. ================================================================================ -= vendor/github.com/coreos/go-systemd/unit licensed under: = += vendor/github.com/coreos/go-systemd/journal licensed under: = Apache License Version 2.0, January 2004 @@ -34202,40 +35276,6 @@ SOFTWARE. ================================================================================ -================================================================================ -= vendor/github.com/dchest/safefile licensed under: = - -Copyright (c) 2013 Dmitry Chestnykh -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/dchest/safefile/LICENSE 499ffd499356286ac590c21f7b8bd677 -================================================================================ - - ================================================================================ = vendor/github.com/dgrijalva/jwt-go licensed under: = @@ -39250,7 +40290,7 @@ Apache License ================================================================================ -= vendor/github.com/docker/docker/pkg/stdcopy licensed under: = += vendor/github.com/docker/docker/pkg/parsers/operatingsystem licensed under: = Apache License @@ -39449,7 +40489,7 @@ Apache License ================================================================================ -= vendor/github.com/docker/docker/pkg/sysinfo licensed under: = += vendor/github.com/docker/docker/pkg/stdcopy licensed under: = Apache License @@ -39648,7 +40688,7 @@ Apache License ================================================================================ -= vendor/github.com/docker/docker/pkg/system licensed under: = += vendor/github.com/docker/docker/pkg/sysinfo licensed under: = Apache License @@ -39847,7 +40887,7 @@ Apache License ================================================================================ -= vendor/github.com/docker/docker/pkg/term licensed under: = += vendor/github.com/docker/docker/pkg/system licensed under: = Apache License @@ -40046,7 +41086,7 @@ Apache License ================================================================================ -= vendor/github.com/docker/docker/pkg/term/windows licensed under: = += vendor/github.com/docker/docker/pkg/term licensed under: = Apache License @@ -40245,7 +41285,7 @@ Apache License ================================================================================ -= vendor/github.com/docker/docker/pkg/tlsconfig licensed under: = += vendor/github.com/docker/docker/pkg/term/windows licensed under: = Apache License @@ -40444,7 +41484,7 @@ Apache License ================================================================================ -= vendor/github.com/docker/go-connections/nat licensed under: = += vendor/github.com/docker/docker/pkg/tlsconfig licensed under: = Apache License @@ -40624,7 +41664,7 @@ Apache License END OF TERMS AND CONDITIONS - Copyright 2015 Docker, Inc. + Copyright 2013-2017 Docker, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -40638,12 +41678,12 @@ Apache License See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/docker/go-connections/LICENSE 04424bc6f5a5be60691b9824d65c2ad8 += vendor/github.com/docker/docker/LICENSE 9740d093a080530b5c5c6573df9af45a ================================================================================ ================================================================================ -= vendor/github.com/docker/go-connections/sockets licensed under: = += vendor/github.com/docker/go-connections/nat licensed under: = Apache License @@ -40842,7 +41882,7 @@ Apache License ================================================================================ -= vendor/github.com/docker/go-connections/tlsconfig licensed under: = += vendor/github.com/docker/go-connections/sockets licensed under: = Apache License @@ -41041,7 +42081,7 @@ Apache License ================================================================================ -= vendor/github.com/docker/go-units licensed under: = += vendor/github.com/docker/go-connections/tlsconfig licensed under: = Apache License @@ -41235,227 +42275,17 @@ Apache License See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/docker/go-units/LICENSE 04424bc6f5a5be60691b9824d65c2ad8 -================================================================================ - - -================================================================================ -= vendor/github.com/docker/libnetwork/ipvs licensed under: = - -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - 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. - - -= vendor/github.com/docker/libnetwork/LICENSE d2794c0df5b907fdace235a619d80314 += vendor/github.com/docker/go-connections/LICENSE 04424bc6f5a5be60691b9824d65c2ad8 ================================================================================ ================================================================================ -= vendor/github.com/docker/libtrust licensed under: = += vendor/github.com/docker/go-units licensed under: = Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -41630,13 +42460,13 @@ Apache License END OF TERMS AND CONDITIONS - Copyright 2014 Docker, Inc. + Copyright 2015 Docker, Inc. 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 + https://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, @@ -41644,15 +42474,14 @@ Apache License See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/docker/libtrust/LICENSE 435b266b3899aa8a959f17d41c56def8 += vendor/github.com/docker/go-units/LICENSE 04424bc6f5a5be60691b9824d65c2ad8 ================================================================================ ================================================================================ -= vendor/github.com/docker/spdystream licensed under: = - += vendor/github.com/docker/libnetwork/ipvs licensed under: = - Apache License +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -41829,7 +42658,18 @@ Apache License END OF TERMS AND CONDITIONS - Copyright 2014-2015 Docker, Inc. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -41843,12 +42683,13 @@ Apache License See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/docker/spdystream/LICENSE 246dc1c1661293602d98ff9113c3be48 + += vendor/github.com/docker/libnetwork/LICENSE d2794c0df5b907fdace235a619d80314 ================================================================================ ================================================================================ -= vendor/github.com/docker/spdystream/spdy licensed under: = += vendor/github.com/docker/libtrust licensed under: = Apache License @@ -42028,7 +42869,7 @@ Apache License END OF TERMS AND CONDITIONS - Copyright 2014-2015 Docker, Inc. + Copyright 2014 Docker, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -42042,166 +42883,14 @@ Apache License See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/docker/spdystream/LICENSE 246dc1c1661293602d98ff9113c3be48 -================================================================================ - - -================================================================================ -= vendor/github.com/elazarl/go-bindata-assetfs licensed under: = - -Copyright (c) 2014, Elazar Leibovich -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/elazarl/go-bindata-assetfs/LICENSE 722abb44e97dc8f098516e09e5564a6a -================================================================================ - - -================================================================================ -= vendor/github.com/elazarl/goproxy licensed under: = - -Copyright (c) 2012 Elazar Leibovich. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Elazar Leibovich. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/elazarl/goproxy/LICENSE e2e14e5f5bd856768da39707ed93cd41 -================================================================================ - - -================================================================================ -= vendor/github.com/emicklei/go-restful licensed under: = - -Copyright (c) 2012,2013 Ernest Micklei - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/emicklei/go-restful/LICENSE 2ebc1c12a0f4eae5394522e31961e1de -================================================================================ - - -================================================================================ -= vendor/github.com/emicklei/go-restful-swagger12 licensed under: = - -Copyright (c) 2017 Ernest Micklei - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/emicklei/go-restful-swagger12/LICENSE b1ce415d97e837c8677d332b274d4f0b -================================================================================ - - += vendor/github.com/docker/libtrust/LICENSE 435b266b3899aa8a959f17d41c56def8 ================================================================================ -= vendor/github.com/emicklei/go-restful/log licensed under: = - -Copyright (c) 2012,2013 Ernest Micklei - -MIT License -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/emicklei/go-restful/LICENSE 2ebc1c12a0f4eae5394522e31961e1de ================================================================================ += vendor/github.com/docker/spdystream licensed under: = -================================================================================ -= vendor/github.com/euank/go-kmsg-parser/kmsgparser licensed under: = - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -42379,18 +43068,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright 2014-2015 Docker, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -42404,138 +43082,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/euank/go-kmsg-parser/LICENSE e3fc50a88d0a364313df4b21ef20c29e -================================================================================ - - -================================================================================ -= vendor/github.com/evanphx/json-patch licensed under: = - -Copyright (c) 2014, Evan Phoenix -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the Evan Phoenix nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/evanphx/json-patch/LICENSE 72c842ec53c3334a81b6d65b6f9025a3 -================================================================================ - - -================================================================================ -= vendor/github.com/exponent-io/jsonpath licensed under: = - -The MIT License (MIT) - -Copyright (c) 2015 Exponent Labs LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -= vendor/github.com/exponent-io/jsonpath/LICENSE 42f582355f11b1d4bc8615214b7f0c38 -================================================================================ - - -================================================================================ -= vendor/github.com/fatih/camelcase licensed under: = - -The MIT License (MIT) - -Copyright (c) 2015 Fatih Arslan - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= vendor/github.com/fatih/camelcase/LICENSE.md 4c59b216ce25dc182cdb837e07ba07c0 -================================================================================ - - -================================================================================ -= vendor/github.com/fsnotify/fsnotify licensed under: = - -Copyright (c) 2012 The Go Authors. All rights reserved. -Copyright (c) 2012 fsnotify Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/fsnotify/fsnotify/LICENSE c38914c9a7ab03bb2b96d4baaee10769 += vendor/github.com/docker/spdystream/LICENSE 246dc1c1661293602d98ff9113c3be48 ================================================================================ ================================================================================ -= vendor/github.com/garyburd/redigo/internal licensed under: = += vendor/github.com/docker/spdystream/spdy licensed under: = Apache License @@ -42713,13 +43265,181 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. -= vendor/github.com/garyburd/redigo/LICENSE 34400b68072d710fecd0a2940a0d1658 + END OF TERMS AND CONDITIONS + + Copyright 2014-2015 Docker, Inc. + + 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. + += vendor/github.com/docker/spdystream/LICENSE 246dc1c1661293602d98ff9113c3be48 ================================================================================ ================================================================================ -= vendor/github.com/garyburd/redigo/redis licensed under: = += vendor/github.com/elazarl/go-bindata-assetfs licensed under: = + +Copyright (c) 2014, Elazar Leibovich +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/elazarl/go-bindata-assetfs/LICENSE 722abb44e97dc8f098516e09e5564a6a +================================================================================ + +================================================================================ += vendor/github.com/elazarl/goproxy licensed under: = + +Copyright (c) 2012 Elazar Leibovich. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Elazar Leibovich. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/elazarl/goproxy/LICENSE e2e14e5f5bd856768da39707ed93cd41 +================================================================================ + + +================================================================================ += vendor/github.com/emicklei/go-restful licensed under: = + +Copyright (c) 2012,2013 Ernest Micklei + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. += vendor/github.com/emicklei/go-restful/LICENSE 2ebc1c12a0f4eae5394522e31961e1de +================================================================================ + + +================================================================================ += vendor/github.com/emicklei/go-restful-swagger12 licensed under: = + +Copyright (c) 2017 Ernest Micklei + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. += vendor/github.com/emicklei/go-restful-swagger12/LICENSE b1ce415d97e837c8677d332b274d4f0b +================================================================================ + + +================================================================================ += vendor/github.com/emicklei/go-restful/log licensed under: = + +Copyright (c) 2012,2013 Ernest Micklei + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. += vendor/github.com/emicklei/go-restful/LICENSE 2ebc1c12a0f4eae5394522e31961e1de +================================================================================ + + +================================================================================ += vendor/github.com/euank/go-kmsg-parser/kmsgparser licensed under: = Apache License Version 2.0, January 2004 @@ -42896,7 +43616,160 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. -= vendor/github.com/garyburd/redigo/LICENSE 34400b68072d710fecd0a2940a0d1658 + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + += vendor/github.com/euank/go-kmsg-parser/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/github.com/evanphx/json-patch licensed under: = + +Copyright (c) 2014, Evan Phoenix +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of the Evan Phoenix nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/evanphx/json-patch/LICENSE 72c842ec53c3334a81b6d65b6f9025a3 +================================================================================ + + +================================================================================ += vendor/github.com/exponent-io/jsonpath licensed under: = + +The MIT License (MIT) + +Copyright (c) 2015 Exponent Labs LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + += vendor/github.com/exponent-io/jsonpath/LICENSE 42f582355f11b1d4bc8615214b7f0c38 +================================================================================ + + +================================================================================ += vendor/github.com/fatih/camelcase licensed under: = + +The MIT License (MIT) + +Copyright (c) 2015 Fatih Arslan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/fatih/camelcase/LICENSE.md 4c59b216ce25dc182cdb837e07ba07c0 +================================================================================ + + +================================================================================ += vendor/github.com/fsnotify/fsnotify licensed under: = + +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2012 fsnotify Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/fsnotify/fsnotify/LICENSE c38914c9a7ab03bb2b96d4baaee10769 ================================================================================ @@ -47277,7 +48150,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/golang/protobuf/ptypes/empty licensed under: = += vendor/github.com/golang/protobuf/ptypes/struct licensed under: = Go support for Protocol Buffers - Google's data interchange format @@ -47316,7 +48189,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/golang/protobuf/ptypes/struct licensed under: = += vendor/github.com/golang/protobuf/ptypes/timestamp licensed under: = Go support for Protocol Buffers - Google's data interchange format @@ -47355,7 +48228,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/golang/protobuf/ptypes/timestamp licensed under: = += vendor/github.com/golang/protobuf/ptypes/wrappers licensed under: = Go support for Protocol Buffers - Google's data interchange format @@ -47574,18 +48447,237 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + += vendor/github.com/google/btree/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/google/cadvisor/accelerators licensed under: = + + Copyright 2014 The cAdvisor 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. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + += vendor/github.com/google/cadvisor/LICENSE e7790b946bfacb700e8a8f2baedb3205 +================================================================================ - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - Copyright [yyyy] [name of copyright owner] +================================================================================ += vendor/github.com/google/cadvisor/api licensed under: = + + Copyright 2014 The cAdvisor Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -47599,12 +48691,189 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/google/btree/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + += vendor/github.com/google/cadvisor/LICENSE e7790b946bfacb700e8a8f2baedb3205 ================================================================================ ================================================================================ -= vendor/github.com/google/cadvisor/accelerators licensed under: = += vendor/github.com/google/cadvisor/cache/memory licensed under: = Copyright 2014 The cAdvisor Authors @@ -47802,7 +49071,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/api licensed under: = += vendor/github.com/google/cadvisor/client/v2 licensed under: = Copyright 2014 The cAdvisor Authors @@ -48000,7 +49269,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/cache/memory licensed under: = += vendor/github.com/google/cadvisor/collector licensed under: = Copyright 2014 The cAdvisor Authors @@ -48198,7 +49467,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/client/v2 licensed under: = += vendor/github.com/google/cadvisor/container licensed under: = Copyright 2014 The cAdvisor Authors @@ -48396,7 +49665,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/collector licensed under: = += vendor/github.com/google/cadvisor/container/common licensed under: = Copyright 2014 The cAdvisor Authors @@ -48594,7 +49863,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/container licensed under: = += vendor/github.com/google/cadvisor/container/containerd licensed under: = Copyright 2014 The cAdvisor Authors @@ -48792,7 +50061,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/container/common licensed under: = += vendor/github.com/google/cadvisor/container/crio licensed under: = Copyright 2014 The cAdvisor Authors @@ -48990,7 +50259,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/container/containerd licensed under: = += vendor/github.com/google/cadvisor/container/docker licensed under: = Copyright 2014 The cAdvisor Authors @@ -49188,7 +50457,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/container/crio licensed under: = += vendor/github.com/google/cadvisor/container/libcontainer licensed under: = Copyright 2014 The cAdvisor Authors @@ -49386,7 +50655,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/container/docker licensed under: = += vendor/github.com/google/cadvisor/container/raw licensed under: = Copyright 2014 The cAdvisor Authors @@ -49584,7 +50853,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/container/libcontainer licensed under: = += vendor/github.com/google/cadvisor/container/rkt licensed under: = Copyright 2014 The cAdvisor Authors @@ -49782,7 +51051,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/container/raw licensed under: = += vendor/github.com/google/cadvisor/container/systemd licensed under: = Copyright 2014 The cAdvisor Authors @@ -49980,7 +51249,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/container/rkt licensed under: = += vendor/github.com/google/cadvisor/devicemapper licensed under: = Copyright 2014 The cAdvisor Authors @@ -50178,7 +51447,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/container/systemd licensed under: = += vendor/github.com/google/cadvisor/events licensed under: = Copyright 2014 The cAdvisor Authors @@ -50376,7 +51645,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/devicemapper licensed under: = += vendor/github.com/google/cadvisor/fs licensed under: = Copyright 2014 The cAdvisor Authors @@ -50574,7 +51843,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/events licensed under: = += vendor/github.com/google/cadvisor/healthz licensed under: = Copyright 2014 The cAdvisor Authors @@ -50772,7 +52041,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/fs licensed under: = += vendor/github.com/google/cadvisor/http licensed under: = Copyright 2014 The cAdvisor Authors @@ -50970,7 +52239,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/healthz licensed under: = += vendor/github.com/google/cadvisor/http/mux licensed under: = Copyright 2014 The cAdvisor Authors @@ -51168,7 +52437,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/http licensed under: = += vendor/github.com/google/cadvisor/info/v1 licensed under: = Copyright 2014 The cAdvisor Authors @@ -51366,7 +52635,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/http/mux licensed under: = += vendor/github.com/google/cadvisor/info/v2 licensed under: = Copyright 2014 The cAdvisor Authors @@ -51564,7 +52833,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/info/v1 licensed under: = += vendor/github.com/google/cadvisor/machine licensed under: = Copyright 2014 The cAdvisor Authors @@ -51762,7 +53031,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/info/v2 licensed under: = += vendor/github.com/google/cadvisor/manager licensed under: = Copyright 2014 The cAdvisor Authors @@ -51960,7 +53229,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/machine licensed under: = += vendor/github.com/google/cadvisor/manager/watcher licensed under: = Copyright 2014 The cAdvisor Authors @@ -52158,7 +53427,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/manager licensed under: = += vendor/github.com/google/cadvisor/manager/watcher/raw licensed under: = Copyright 2014 The cAdvisor Authors @@ -52356,7 +53625,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/manager/watcher licensed under: = += vendor/github.com/google/cadvisor/manager/watcher/rkt licensed under: = Copyright 2014 The cAdvisor Authors @@ -52554,7 +53823,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/manager/watcher/raw licensed under: = += vendor/github.com/google/cadvisor/metrics licensed under: = Copyright 2014 The cAdvisor Authors @@ -52752,7 +54021,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/manager/watcher/rkt licensed under: = += vendor/github.com/google/cadvisor/pages licensed under: = Copyright 2014 The cAdvisor Authors @@ -52950,7 +54219,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/metrics licensed under: = += vendor/github.com/google/cadvisor/pages/static licensed under: = Copyright 2014 The cAdvisor Authors @@ -53148,7 +54417,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/pages licensed under: = += vendor/github.com/google/cadvisor/storage licensed under: = Copyright 2014 The cAdvisor Authors @@ -53346,7 +54615,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/pages/static licensed under: = += vendor/github.com/google/cadvisor/summary licensed under: = Copyright 2014 The cAdvisor Authors @@ -53544,7 +54813,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/storage licensed under: = += vendor/github.com/google/cadvisor/utils licensed under: = Copyright 2014 The cAdvisor Authors @@ -53742,7 +55011,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/summary licensed under: = += vendor/github.com/google/cadvisor/utils/cloudinfo licensed under: = Copyright 2014 The cAdvisor Authors @@ -53940,7 +55209,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/utils licensed under: = += vendor/github.com/google/cadvisor/utils/cpuload licensed under: = Copyright 2014 The cAdvisor Authors @@ -54138,7 +55407,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/utils/cloudinfo licensed under: = += vendor/github.com/google/cadvisor/utils/cpuload/netlink licensed under: = Copyright 2014 The cAdvisor Authors @@ -54336,7 +55605,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/utils/cpuload licensed under: = += vendor/github.com/google/cadvisor/utils/docker licensed under: = Copyright 2014 The cAdvisor Authors @@ -54534,7 +55803,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/utils/cpuload/netlink licensed under: = += vendor/github.com/google/cadvisor/utils/oomparser licensed under: = Copyright 2014 The cAdvisor Authors @@ -54732,7 +56001,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/utils/docker licensed under: = += vendor/github.com/google/cadvisor/utils/sysfs licensed under: = Copyright 2014 The cAdvisor Authors @@ -54930,7 +56199,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/utils/oomparser licensed under: = += vendor/github.com/google/cadvisor/utils/sysinfo licensed under: = Copyright 2014 The cAdvisor Authors @@ -55128,7 +56397,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/utils/sysfs licensed under: = += vendor/github.com/google/cadvisor/validate licensed under: = Copyright 2014 The cAdvisor Authors @@ -55326,7 +56595,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/utils/sysinfo licensed under: = += vendor/github.com/google/cadvisor/version licensed under: = Copyright 2014 The cAdvisor Authors @@ -55524,7 +56793,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/validate licensed under: = += vendor/github.com/google/cadvisor/zfs licensed under: = Copyright 2014 The cAdvisor Authors @@ -55722,9 +56991,198 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/github.com/google/cadvisor/version licensed under: = += vendor/github.com/google/certificate-transparency-go licensed under: = - Copyright 2014 The cAdvisor Authors + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -55738,6 +57196,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. += vendor/github.com/google/certificate-transparency-go/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/google/certificate-transparency-go/asn1 licensed under: = + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -55915,14 +57381,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. END OF TERMS AND CONDITIONS -= vendor/github.com/google/cadvisor/LICENSE e7790b946bfacb700e8a8f2baedb3205 -================================================================================ - + APPENDIX: How to apply the Apache License to your work. -================================================================================ -= vendor/github.com/google/cadvisor/zfs licensed under: = + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. - Copyright 2014 The cAdvisor Authors + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -55936,6 +57406,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. += vendor/github.com/google/certificate-transparency-go/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/google/certificate-transparency-go/client licensed under: = + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -56113,12 +57591,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. END OF TERMS AND CONDITIONS -= vendor/github.com/google/cadvisor/LICENSE e7790b946bfacb700e8a8f2baedb3205 + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + += vendor/github.com/google/certificate-transparency-go/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/google/certificate-transparency/go licensed under: = += vendor/github.com/google/certificate-transparency-go/client/configpb licensed under: = Apache License @@ -56323,12 +57826,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/google/certificate-transparency/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/google/certificate-transparency-go/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/google/certificate-transparency/go/asn1 licensed under: = += vendor/github.com/google/certificate-transparency-go/jsonclient licensed under: = Apache License @@ -56533,12 +58036,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/google/certificate-transparency/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/google/certificate-transparency-go/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/google/certificate-transparency/go/client licensed under: = += vendor/github.com/google/certificate-transparency-go/tls licensed under: = Apache License @@ -56743,12 +58246,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/google/certificate-transparency/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/google/certificate-transparency-go/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/google/certificate-transparency/go/x509 licensed under: = += vendor/github.com/google/certificate-transparency-go/x509 licensed under: = Apache License @@ -56953,12 +58456,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/google/certificate-transparency/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/google/certificate-transparency-go/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/google/certificate-transparency/go/x509/pkix licensed under: = += vendor/github.com/google/certificate-transparency-go/x509/pkix licensed under: = Apache License @@ -57163,7 +58666,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/google/certificate-transparency/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/google/certificate-transparency-go/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ @@ -64015,76 +65518,6 @@ specific language governing permissions and limitations under the License. ================================================================================ -================================================================================ -= vendor/github.com/gorilla/context licensed under: = - -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/gorilla/context/LICENSE c50f6bd9c1e15ed0bad3bea18e3c1b7f -================================================================================ - - -================================================================================ -= vendor/github.com/gorilla/mux licensed under: = - -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/gorilla/mux/LICENSE c50f6bd9c1e15ed0bad3bea18e3c1b7f -================================================================================ - - ================================================================================ = vendor/github.com/gorilla/websocket licensed under: = @@ -64363,101 +65796,471 @@ are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Gengo, Inc. nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt c510a2a01572b82d27f28fd4d02ca318 +================================================================================ + + +================================================================================ += vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/internal licensed under: = + +Copyright (c) 2015, Gengo, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Gengo, Inc. nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt c510a2a01572b82d27f28fd4d02ca318 +================================================================================ + + +================================================================================ += vendor/github.com/grpc-ecosystem/grpc-gateway/utilities licensed under: = + +Copyright (c) 2015, Gengo, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Gengo, Inc. nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt c510a2a01572b82d27f28fd4d02ca318 +================================================================================ + + +================================================================================ += vendor/github.com/hashicorp/golang-lru licensed under: = + +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability - * Neither the name of Gengo, Inc. nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +8. Litigation -= vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt c510a2a01572b82d27f28fd4d02ca318 -================================================================================ + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. +9. Miscellaneous -================================================================================ -= vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/internal licensed under: = + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. -Copyright (c) 2015, Gengo, Inc. -All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +10. Versions of the License - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. +10.1. New Versions - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. - * Neither the name of Gengo, Inc. nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. +10.2. Effect of New Versions -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. -= vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt c510a2a01572b82d27f28fd4d02ca318 -================================================================================ +10.3. Modified Versions + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). -================================================================================ -= vendor/github.com/grpc-ecosystem/grpc-gateway/utilities licensed under: = +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. -Copyright (c) 2015, Gengo, Inc. -All rights reserved. +Exhibit A - Source Code Form License Notice -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +You may add additional accurate notices of copyright ownership. - * Neither the name of Gengo, Inc. nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. +Exhibit B - "Incompatible With Secondary Licenses" Notice -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. -= vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt c510a2a01572b82d27f28fd4d02ca318 += vendor/github.com/hashicorp/golang-lru/LICENSE f27a50d2e878867827842f2c60e30bfc ================================================================================ ================================================================================ -= vendor/github.com/hashicorp/golang-lru licensed under: = += vendor/github.com/hashicorp/golang-lru/simplelru licensed under: = Mozilla Public License, version 2.0 @@ -64611,9 +66414,377 @@ Mozilla Public License, version 2.0 2.6. Fair Use - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. + += vendor/github.com/hashicorp/golang-lru/LICENSE f27a50d2e878867827842f2c60e30bfc +================================================================================ + + +================================================================================ += vendor/github.com/hashicorp/hcl licensed under: = + +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions @@ -64626,12 +66797,11 @@ Mozilla Public License, version 2.0 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. 3.2. Distribution of Executable Form @@ -64643,40 +66813,39 @@ Mozilla Public License, version 2.0 reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). 3.4. Notices - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any @@ -64685,14 +66854,14 @@ Mozilla Public License, version 2.0 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. 5. Termination @@ -64700,22 +66869,21 @@ Mozilla Public License, version 2.0 fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been @@ -64724,16 +66892,16 @@ Mozilla Public License, version 2.0 6. Disclaimer of Warranty - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. 7. Limitation of Liability @@ -64745,29 +66913,27 @@ Mozilla Public License, version 2.0 goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. 8. Litigation - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. 9. Miscellaneous - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. 10. Versions of the License @@ -64781,24 +66947,23 @@ Mozilla Public License, version 2.0 10.2. Effect of New Versions - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice @@ -64809,113 +66974,113 @@ Exhibit A - Source Code Form License Notice obtain one at http://mozilla.org/MPL/2.0/. -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. -Exhibit B - "Incompatible With Secondary Licenses" Notice +Exhibit B - “Incompatible With Secondary Licenses” Notice - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0. -= vendor/github.com/hashicorp/golang-lru/LICENSE f27a50d2e878867827842f2c60e30bfc + += vendor/github.com/hashicorp/hcl/LICENSE b278a92d2c1509760384428817710378 ================================================================================ ================================================================================ -= vendor/github.com/hashicorp/golang-lru/simplelru licensed under: = += vendor/github.com/hashicorp/hcl/hcl/ast licensed under: = Mozilla Public License, version 2.0 1. Definitions -1.1. "Contributor" +1.1. “Contributor” means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. -1.2. "Contributor Version" +1.2. “Contributor Version” means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. + Contributor and that particular Contributor’s Contribution. -1.3. "Contribution" +1.3. “Contribution” means Covered Software of a particular Contributor. -1.4. "Covered Software" +1.4. “Covered Software” means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. -1.5. "Incompatible With Secondary Licenses" +1.5. “Incompatible With Secondary Licenses” means a. that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. -1.6. "Executable Form" +1.6. “Executable Form” means any form of the work other than Source Code Form. -1.7. "Larger Work" +1.7. “Larger Work” - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. -1.8. "License" +1.8. “License” means this document. -1.9. "Licensable" +1.9. “Licensable” - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. -1.10. "Modifications" +1.10. “Modifications” means any of the following: - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or b. any new file in Source Code Form that contains any Covered Software. -1.11. "Patent Claims" of a Contributor +1.11. “Patent Claims” of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. -1.12. "Secondary License" +1.12. “Secondary License” means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. -1.13. "Source Code Form" +1.13. “Source Code Form” means the form of the work preferred for making modifications. -1.14. "You" (or "Your") +1.14. “You” (or “Your”) means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is + License. For legal entities, “You” includes any entity that controls, is controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause + definition, “control” means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. @@ -64931,59 +67096,57 @@ Mozilla Public License, version 2.0 a. under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. 2.2. Effective Date - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. 2.3. Limitations on Grant Scope - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: a. for any code that a Contributor has removed from Covered Software; or - b. for infringements caused by: (i) Your and any other third party's + b. for infringements caused by: (i) Your and any other third party’s modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). 2.5. Representation - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. 2.6. Fair Use - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions @@ -64996,12 +67159,11 @@ Mozilla Public License, version 2.0 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. 3.2. Distribution of Executable Form @@ -65013,40 +67175,39 @@ Mozilla Public License, version 2.0 reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). 3.4. Notices - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any @@ -65055,14 +67216,14 @@ Mozilla Public License, version 2.0 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. 5. Termination @@ -65070,22 +67231,21 @@ Mozilla Public License, version 2.0 fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been @@ -65094,16 +67254,16 @@ Mozilla Public License, version 2.0 6. Disclaimer of Warranty - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. 7. Limitation of Liability @@ -65115,29 +67275,27 @@ Mozilla Public License, version 2.0 goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. 8. Litigation - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. 9. Miscellaneous - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. 10. Versions of the License @@ -65151,24 +67309,23 @@ Mozilla Public License, version 2.0 10.2. Effect of New Versions - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice @@ -65179,25 +67336,25 @@ Exhibit A - Source Code Form License Notice obtain one at http://mozilla.org/MPL/2.0/. -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. -Exhibit B - "Incompatible With Secondary Licenses" Notice +Exhibit B - “Incompatible With Secondary Licenses” Notice - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0. -= vendor/github.com/hashicorp/golang-lru/LICENSE f27a50d2e878867827842f2c60e30bfc + += vendor/github.com/hashicorp/hcl/LICENSE b278a92d2c1509760384428817710378 ================================================================================ ================================================================================ -= vendor/github.com/hashicorp/hcl licensed under: = += vendor/github.com/hashicorp/hcl/hcl/parser licensed under: = Mozilla Public License, version 2.0 @@ -65559,7 +67716,7 @@ Exhibit B - “Incompatible With Secondary Licenses” Notice ================================================================================ -= vendor/github.com/hashicorp/hcl/hcl/ast licensed under: = += vendor/github.com/hashicorp/hcl/hcl/scanner licensed under: = Mozilla Public License, version 2.0 @@ -65921,7 +68078,7 @@ Exhibit B - “Incompatible With Secondary Licenses” Notice ================================================================================ -= vendor/github.com/hashicorp/hcl/hcl/parser licensed under: = += vendor/github.com/hashicorp/hcl/hcl/strconv licensed under: = Mozilla Public License, version 2.0 @@ -66283,7 +68440,7 @@ Exhibit B - “Incompatible With Secondary Licenses” Notice ================================================================================ -= vendor/github.com/hashicorp/hcl/hcl/scanner licensed under: = += vendor/github.com/hashicorp/hcl/hcl/token licensed under: = Mozilla Public License, version 2.0 @@ -66645,7 +68802,7 @@ Exhibit B - “Incompatible With Secondary Licenses” Notice ================================================================================ -= vendor/github.com/hashicorp/hcl/hcl/strconv licensed under: = += vendor/github.com/hashicorp/hcl/json/parser licensed under: = Mozilla Public License, version 2.0 @@ -67007,7 +69164,7 @@ Exhibit B - “Incompatible With Secondary Licenses” Notice ================================================================================ -= vendor/github.com/hashicorp/hcl/hcl/token licensed under: = += vendor/github.com/hashicorp/hcl/json/scanner licensed under: = Mozilla Public License, version 2.0 @@ -67369,7 +69526,7 @@ Exhibit B - “Incompatible With Secondary Licenses” Notice ================================================================================ -= vendor/github.com/hashicorp/hcl/json/parser licensed under: = += vendor/github.com/hashicorp/hcl/json/token licensed under: = Mozilla Public License, version 2.0 @@ -67731,731 +69888,631 @@ Exhibit B - “Incompatible With Secondary Licenses” Notice ================================================================================ -= vendor/github.com/hashicorp/hcl/json/scanner licensed under: = - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. “Contributor” - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. “Contributor Version” - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. - -1.3. “Contribution” - - means Covered Software of a particular Contributor. - -1.4. “Covered Software” - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. “Incompatible With Secondary Licenses” - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. - -1.6. “Executable Form” - - means any form of the work other than Source Code Form. - -1.7. “Larger Work” - - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. - -1.8. “License” - - means this document. - -1.9. “Licensable” - - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. - -1.10. “Modifications” - - means any of the following: - - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. “Patent Claims” of a Contributor - - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. - -1.12. “Secondary License” - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. “Source Code Form” - - means the form of the work preferred for making modifications. - -1.14. “You” (or “Your”) - - means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. - - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. - -2.7. Conditions += vendor/github.com/heketi/heketi/client/api/go-client licensed under: = - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. +Heketi code is released under various licenses: +The REST API client code (in go and python) is released +under a dual license of Apache 2.0 or LGPLv3+. -3. Responsibilities +The other parts of heketi (server, cli, tests, ...) are released +under a dual license of LGPLv3+ or GPLv2. -3.1. Distribution of Source Form += vendor/github.com/heketi/heketi/LICENSE a58e72c3bda574189508cb90d56fa19f +================================================================================ - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. -3.2. Distribution of Executable Form +================================================================================ += vendor/github.com/heketi/heketi/pkg/glusterfs/api licensed under: = - If You distribute Covered Software in Executable Form then: +Heketi code is released under various licenses: - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and +The REST API client code (in go and python) is released +under a dual license of Apache 2.0 or LGPLv3+. - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. +The other parts of heketi (server, cli, tests, ...) are released +under a dual license of LGPLv3+ or GPLv2. -3.3. Distribution of a Larger Work += vendor/github.com/heketi/heketi/LICENSE a58e72c3bda574189508cb90d56fa19f +================================================================================ - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). -3.4. Notices +================================================================================ += vendor/github.com/heketi/heketi/pkg/utils licensed under: = - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. +Heketi code is released under various licenses: -3.5. Application of Additional Terms +The REST API client code (in go and python) is released +under a dual license of Apache 2.0 or LGPLv3+. - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. +The other parts of heketi (server, cli, tests, ...) are released +under a dual license of LGPLv3+ or GPLv2. -4. Inability to Comply Due to Statute or Regulation += vendor/github.com/heketi/heketi/LICENSE a58e72c3bda574189508cb90d56fa19f +================================================================================ - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. -5. Termination +================================================================================ += vendor/github.com/imdario/mergo licensed under: = -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. +Copyright (c) 2013 Dario Castañé. All rights reserved. +Copyright (c) 2012 The Go Authors. All rights reserved. -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. -6. Disclaimer of Warranty +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. += vendor/github.com/imdario/mergo/LICENSE ff13e03bb57bf9c52645f2f942afa28b +================================================================================ -7. Limitation of Liability - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. +================================================================================ += vendor/github.com/inconshreveable/mousetrap licensed under: = -8. Litigation +Copyright 2014 Alan Shreve - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. +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 -9. Miscellaneous + http://www.apache.org/licenses/LICENSE-2.0 - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. +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. += vendor/github.com/inconshreveable/mousetrap/LICENSE b23cff9db13f093a4e6ff77105cbd8eb +================================================================================ -10. Versions of the License -10.1. New Versions +================================================================================ += vendor/github.com/influxdata/influxdb/client/v2 licensed under: = - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. +The MIT License (MIT) -10.2. Effect of New Versions +Copyright (c) 2013-2016 Errplane Inc. - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -10.3. Modified Versions +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. += vendor/github.com/influxdata/influxdb/LICENSE ba8146ad9cc2a128209983265136e06a +================================================================================ -Exhibit A - Source Code Form License Notice - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. +================================================================================ += vendor/github.com/influxdata/influxdb/models licensed under: = -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. +The MIT License (MIT) -You may add additional accurate notices of copyright ownership. +Copyright (c) 2013-2016 Errplane Inc. -Exhibit B - “Incompatible With Secondary Licenses” Notice +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by - the Mozilla Public License, v. 2.0. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/hashicorp/hcl/LICENSE b278a92d2c1509760384428817710378 += vendor/github.com/influxdata/influxdb/LICENSE ba8146ad9cc2a128209983265136e06a ================================================================================ ================================================================================ -= vendor/github.com/hashicorp/hcl/json/token licensed under: = += vendor/github.com/influxdata/influxdb/pkg/escape licensed under: = -Mozilla Public License, version 2.0 +The MIT License (MIT) -1. Definitions +Copyright (c) 2013-2016 Errplane Inc. -1.1. “Contributor” +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -1.2. “Contributor Version” +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. += vendor/github.com/influxdata/influxdb/LICENSE ba8146ad9cc2a128209983265136e06a +================================================================================ -1.3. “Contribution” - means Covered Software of a particular Contributor. +================================================================================ += vendor/github.com/JeffAshton/win_pdh licensed under: = -1.4. “Covered Software” +Copyright (c) 2010 The win_pdh Authors. All rights reserved. - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. -1.5. “Incompatible With Secondary Licenses” - means +THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or += vendor/github.com/JeffAshton/win_pdh/LICENSE fadcabe0503181faf8d4a9579bed3b7f +================================================================================ - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. -1.6. “Executable Form” +================================================================================ += vendor/github.com/jmespath/go-jmespath licensed under: = - means any form of the work other than Source Code Form. +Copyright 2015 James Saryerwinnie -1.7. “Larger Work” +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 - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. + http://www.apache.org/licenses/LICENSE-2.0 -1.8. “License” +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. - means this document. += vendor/github.com/jmespath/go-jmespath/LICENSE 9abfa8353fce3f2cb28364e1e9016852 +================================================================================ -1.9. “Licensable” - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. +================================================================================ += vendor/github.com/jonboulle/clockwork licensed under: = -1.10. “Modifications” +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ - means any of the following: + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or + 1. Definitions. - b. any new file in Source Code Form that contains any Covered Software. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -1.11. “Patent Claims” of a Contributor + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -1.12. “Secondary License” + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -1.13. “Source Code Form” + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. - means the form of the work preferred for making modifications. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -1.14. “You” (or “Your”) + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. - means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -2. License Grants and Conditions + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -2.1. Grants + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -2.2. Effective Date + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -2.3. Limitations on Grant Scope + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. - a. for any code that a Contributor has removed from Covered Software; or + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -2.4. Subsequent Licenses + END OF TERMS AND CONDITIONS - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). + APPENDIX: How to apply the Apache License to your work. -2.5. Representation + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. + Copyright {yyyy} {name of copyright owner} -2.6. Fair Use + 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 - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. + http://www.apache.org/licenses/LICENSE-2.0 -2.7. Conditions + 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. - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. += vendor/github.com/jonboulle/clockwork/LICENSE 136e4f49dbf29942c572a3a8f6e88a77 +================================================================================ -3. Responsibilities +================================================================================ += vendor/github.com/json-iterator/go licensed under: = -3.1. Distribution of Source Form +MIT License - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. +Copyright (c) 2016 json-iterator -3.2. Distribution of Executable Form +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - If You distribute Covered Software in Executable Form then: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. += vendor/github.com/json-iterator/go/LICENSE 0b69744b481d72d30dbf69f84a451cfd +================================================================================ -3.3. Distribution of a Larger Work - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). +================================================================================ += vendor/github.com/jteeuwen/go-bindata licensed under: = -3.4. Notices +This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +license. Its contents can be found at: +http://creativecommons.org/publicdomain/zero/1.0 - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. += vendor/github.com/jteeuwen/go-bindata/LICENSE 8dcedca69f7a474372829521f37954b1 +================================================================================ -3.5. Application of Additional Terms - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. +================================================================================ += vendor/github.com/jteeuwen/go-bindata/go-bindata licensed under: = -4. Inability to Comply Due to Statute or Regulation +This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +license. Its contents can be found at: +http://creativecommons.org/publicdomain/zero/1.0 - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. += vendor/github.com/jteeuwen/go-bindata/LICENSE 8dcedca69f7a474372829521f37954b1 +================================================================================ -5. Termination -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. +================================================================================ += vendor/github.com/kardianos/osext licensed under: = -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. +Copyright (c) 2012 The Go Authors. All rights reserved. -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: -6. Disclaimer of Warranty + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -7. Limitation of Liability += vendor/github.com/kardianos/osext/LICENSE 591778525c869cdde0ab5a1bf283cd81 +================================================================================ - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. -8. Litigation +================================================================================ += vendor/github.com/kr/fs licensed under: = - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. +Copyright (c) 2012 The Go Authors. All rights reserved. -9. Miscellaneous +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -10. Versions of the License += vendor/github.com/kr/fs/LICENSE 591778525c869cdde0ab5a1bf283cd81 +================================================================================ -10.1. New Versions - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. +================================================================================ += vendor/github.com/kr/pretty licensed under: = -10.2. Effect of New Versions +The MIT License (MIT) - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. +Copyright 2012 Keith Rarick -10.3. Modified Versions +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -Exhibit A - Source Code Form License Notice += vendor/github.com/kr/pretty/License 9d305c2010c6891ee4f3cd42a562f78f +================================================================================ - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. +================================================================================ += vendor/github.com/kr/text licensed under: = -You may add additional accurate notices of copyright ownership. +Copyright 2012 Keith Rarick -Exhibit B - “Incompatible With Secondary Licenses” Notice +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by - the Mozilla Public License, v. 2.0. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -= vendor/github.com/hashicorp/hcl/LICENSE b278a92d2c1509760384428817710378 += vendor/github.com/kr/text/License 449bfedd81a372635934cf9ce004c0cf ================================================================================ ================================================================================ -= vendor/github.com/hawkular/hawkular-client-go/metrics licensed under: = += vendor/github.com/kubernetes/repo-infra/kazel licensed under: = Apache License Version 2.0, January 2004 @@ -68659,304 +70716,214 @@ Exhibit B - “Incompatible With Secondary Licenses” Notice See the License for the specific language governing permissions and limitations under the License. - -= vendor/github.com/hawkular/hawkular-client-go/LICENSE fa818a259cbed7ce8bc2a22d35a464fc -================================================================================ - - -================================================================================ -= vendor/github.com/heketi/heketi/client/api/go-client licensed under: = - -Heketi code is released under various licenses: - -The REST API client code (in go and python) is released -under a dual license of Apache 2.0 or LGPLv3+. - -The other parts of heketi (server, cli, tests, ...) are released -under a dual license of LGPLv3+ or GPLv2. - -= vendor/github.com/heketi/heketi/LICENSE a58e72c3bda574189508cb90d56fa19f -================================================================================ - - -================================================================================ -= vendor/github.com/heketi/heketi/pkg/glusterfs/api licensed under: = - -Heketi code is released under various licenses: - -The REST API client code (in go and python) is released -under a dual license of Apache 2.0 or LGPLv3+. - -The other parts of heketi (server, cli, tests, ...) are released -under a dual license of LGPLv3+ or GPLv2. - -= vendor/github.com/heketi/heketi/LICENSE a58e72c3bda574189508cb90d56fa19f -================================================================================ - - -================================================================================ -= vendor/github.com/heketi/heketi/pkg/utils licensed under: = - -Heketi code is released under various licenses: - -The REST API client code (in go and python) is released -under a dual license of Apache 2.0 or LGPLv3+. - -The other parts of heketi (server, cli, tests, ...) are released -under a dual license of LGPLv3+ or GPLv2. - -= vendor/github.com/heketi/heketi/LICENSE a58e72c3bda574189508cb90d56fa19f -================================================================================ - - -================================================================================ -= vendor/github.com/howeyc/gopass licensed under: = - -ISC License - -Copyright (c) 2012 Chris Howey - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -= vendor/github.com/howeyc/gopass/LICENSE.txt b24abd09a925eaf2b6de5a9b4c9bea07 -================================================================================ - - -================================================================================ -= vendor/github.com/imdario/mergo licensed under: = - -Copyright (c) 2013 Dario Castañé. All rights reserved. -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/imdario/mergo/LICENSE ff13e03bb57bf9c52645f2f942afa28b -================================================================================ - - -================================================================================ -= vendor/github.com/inconshreveable/mousetrap licensed under: = - -Copyright 2014 Alan Shreve - -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. - -= vendor/github.com/inconshreveable/mousetrap/LICENSE b23cff9db13f093a4e6ff77105cbd8eb += vendor/github.com/kubernetes/repo-infra/LICENSE e3fc50a88d0a364313df4b21ef20c29e ================================================================================ ================================================================================ -= vendor/github.com/influxdata/influxdb/client licensed under: = - -The MIT License (MIT) - -Copyright (c) 2013-2016 Errplane Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. += vendor/github.com/libopenstorage/openstorage/api licensed under: = -= vendor/github.com/influxdata/influxdb/LICENSE ba8146ad9cc2a128209983265136e06a -================================================================================ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -================================================================================ -= vendor/github.com/influxdata/influxdb/client/v2 licensed under: = + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -The MIT License (MIT) + 1. Definitions. -Copyright (c) 2013-2016 Errplane Inc. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -= vendor/github.com/influxdata/influxdb/LICENSE ba8146ad9cc2a128209983265136e06a -================================================================================ + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -================================================================================ -= vendor/github.com/influxdata/influxdb/models licensed under: = + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -The MIT License (MIT) + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -Copyright (c) 2013-2016 Errplane Inc. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -= vendor/github.com/influxdata/influxdb/LICENSE ba8146ad9cc2a128209983265136e06a -================================================================================ + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -================================================================================ -= vendor/github.com/influxdata/influxdb/pkg/escape licensed under: = + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -The MIT License (MIT) + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -Copyright (c) 2013-2016 Errplane Inc. + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -= vendor/github.com/influxdata/influxdb/LICENSE ba8146ad9cc2a128209983265136e06a -================================================================================ + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -================================================================================ -= vendor/github.com/JeffAshton/win_pdh licensed under: = + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -Copyright (c) 2010 The win_pdh Authors. All rights reserved. + END OF TERMS AND CONDITIONS -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. + Copyright 2015 Openstorage.org. -THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 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 -= vendor/github.com/JeffAshton/win_pdh/LICENSE fadcabe0503181faf8d4a9579bed3b7f -================================================================================ + 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. += vendor/github.com/libopenstorage/openstorage/LICENSE 40c3e1c9eacda859a17048003909a2f8 ================================================================================ -= vendor/github.com/jmespath/go-jmespath licensed under: = - -Copyright 2015 James Saryerwinnie - -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. -= vendor/github.com/jmespath/go-jmespath/LICENSE 9abfa8353fce3f2cb28364e1e9016852 ================================================================================ += vendor/github.com/libopenstorage/openstorage/api/client licensed under: = -================================================================================ -= vendor/github.com/jonboulle/clockwork licensed under: = - -Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -69133,18 +71100,7 @@ Apache License END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright 2015 Openstorage.org. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -69158,220 +71114,211 @@ Apache License See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/jonboulle/clockwork/LICENSE 136e4f49dbf29942c572a3a8f6e88a77 -================================================================================ - - -================================================================================ -= vendor/github.com/json-iterator/go licensed under: = - -MIT License - -Copyright (c) 2016 json-iterator - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -= vendor/github.com/json-iterator/go/LICENSE 0b69744b481d72d30dbf69f84a451cfd -================================================================================ - - -================================================================================ -= vendor/github.com/jteeuwen/go-bindata licensed under: = - -This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication -license. Its contents can be found at: -http://creativecommons.org/publicdomain/zero/1.0 - -= vendor/github.com/jteeuwen/go-bindata/LICENSE 8dcedca69f7a474372829521f37954b1 -================================================================================ - - -================================================================================ -= vendor/github.com/jteeuwen/go-bindata/go-bindata licensed under: = - -This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication -license. Its contents can be found at: -http://creativecommons.org/publicdomain/zero/1.0 - -= vendor/github.com/jteeuwen/go-bindata/LICENSE 8dcedca69f7a474372829521f37954b1 += vendor/github.com/libopenstorage/openstorage/LICENSE 40c3e1c9eacda859a17048003909a2f8 ================================================================================ ================================================================================ -= vendor/github.com/kardianos/osext licensed under: = - -Copyright (c) 2012 The Go Authors. All rights reserved. += vendor/github.com/libopenstorage/openstorage/api/client/volume licensed under: = -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -= vendor/github.com/kardianos/osext/LICENSE 591778525c869cdde0ab5a1bf283cd81 -================================================================================ + 1. Definitions. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -================================================================================ -= vendor/github.com/kr/fs licensed under: = + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -Copyright (c) 2012 The Go Authors. All rights reserved. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -= vendor/github.com/kr/fs/LICENSE 591778525c869cdde0ab5a1bf283cd81 -================================================================================ + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -================================================================================ -= vendor/github.com/kr/pretty licensed under: = + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -The MIT License (MIT) + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -Copyright 2012 Keith Rarick + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -= vendor/github.com/kr/pretty/License 9d305c2010c6891ee4f3cd42a562f78f -================================================================================ + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -================================================================================ -= vendor/github.com/kr/pty licensed under: = + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -Copyright (c) 2011 Keith Rarick + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, -subject to the following conditions: + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -The above copyright notice and this permission notice shall -be included in all copies or substantial portions of the -Software. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -= vendor/github.com/kr/pty/License 93958070863d769117fa33b129020050 -================================================================================ + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -================================================================================ -= vendor/github.com/kr/text licensed under: = + END OF TERMS AND CONDITIONS -Copyright 2012 Keith Rarick + Copyright 2015 Openstorage.org. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 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 -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + http://www.apache.org/licenses/LICENSE-2.0 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + 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. -= vendor/github.com/kr/text/License 449bfedd81a372635934cf9ce004c0cf += vendor/github.com/libopenstorage/openstorage/LICENSE 40c3e1c9eacda859a17048003909a2f8 ================================================================================ ================================================================================ -= vendor/github.com/libopenstorage/openstorage/api licensed under: = += vendor/github.com/libopenstorage/openstorage/api/spec licensed under: = Apache License @@ -69570,7 +71517,7 @@ THE SOFTWARE. ================================================================================ -= vendor/github.com/libopenstorage/openstorage/api/client licensed under: = += vendor/github.com/libopenstorage/openstorage/pkg/parser licensed under: = Apache License @@ -69769,7 +71716,7 @@ THE SOFTWARE. ================================================================================ -= vendor/github.com/libopenstorage/openstorage/api/client/volume licensed under: = += vendor/github.com/libopenstorage/openstorage/pkg/units licensed under: = Apache License @@ -69968,7 +71915,7 @@ THE SOFTWARE. ================================================================================ -= vendor/github.com/libopenstorage/openstorage/api/spec licensed under: = += vendor/github.com/libopenstorage/openstorage/volume licensed under: = Apache License @@ -70167,10 +72114,9 @@ THE SOFTWARE. ================================================================================ -= vendor/github.com/libopenstorage/openstorage/pkg/parser licensed under: = - += vendor/github.com/lpabon/godbc licensed under: = - Apache License +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -70347,7 +72293,18 @@ THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2015 Openstorage.org. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -70360,213 +72317,176 @@ THE SOFTWARE. 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. += vendor/github.com/lpabon/godbc/LICENSE 6c4db32a2fa8717faffa1d4f10136f47 +================================================================================ + -= vendor/github.com/libopenstorage/openstorage/LICENSE 40c3e1c9eacda859a17048003909a2f8 ================================================================================ += vendor/github.com/magiconair/properties licensed under: = + +goproperties - properties file decoder for Go + +Copyright (c) 2013-2014 - Frank Schroeder + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. += vendor/github.com/magiconair/properties/LICENSE c383a608fb9a0d227953e928803b9631 ================================================================================ -= vendor/github.com/libopenstorage/openstorage/pkg/units licensed under: = - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +================================================================================ += vendor/github.com/mailru/easyjson/buffer licensed under: = - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Copyright (c) 2016 Mail.Ru Group - 1. Definitions. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. += vendor/github.com/mailru/easyjson/LICENSE 819e81c2ec13e1bbc47dc5e90bb4d88b +================================================================================ - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. +================================================================================ += vendor/github.com/mailru/easyjson/jlexer licensed under: = - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. +Copyright (c) 2016 Mail.Ru Group - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. += vendor/github.com/mailru/easyjson/LICENSE 819e81c2ec13e1bbc47dc5e90bb4d88b +================================================================================ - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. +================================================================================ += vendor/github.com/mailru/easyjson/jwriter licensed under: = - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: +Copyright (c) 2016 Mail.Ru Group - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. += vendor/github.com/mailru/easyjson/LICENSE 819e81c2ec13e1bbc47dc5e90bb4d88b +================================================================================ - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. +================================================================================ += vendor/github.com/MakeNowJust/heredoc licensed under: = - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. +The MIT License (MIT) - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. +Copyright (c) 2014-2017 TSUYUSATO Kitsune - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - END OF TERMS AND CONDITIONS +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. - Copyright 2015 Openstorage.org. += vendor/github.com/MakeNowJust/heredoc/LICENSE 59c4411f6d7dfdaa85623e672d3d4438 +================================================================================ - 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 +================================================================================ += vendor/github.com/marstr/guid licensed under: = - 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. +MIT License -= vendor/github.com/libopenstorage/openstorage/LICENSE 40c3e1c9eacda859a17048003909a2f8 +Copyright (c) 2016 Martin Strobel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. += vendor/github.com/marstr/guid/LICENSE.txt 356484d12e6ad8a7c2d360b236e9a9c8 ================================================================================ ================================================================================ -= vendor/github.com/libopenstorage/openstorage/volume licensed under: = += vendor/github.com/mattn/go-shellwords licensed under: = +The MIT License (MIT) + +Copyright (c) 2017 Yasuhiro Matsumoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + += vendor/github.com/mattn/go-shellwords/LICENSE e5116fc268f5118168ff06a271b50ef9 +================================================================================ + + +================================================================================ += vendor/github.com/matttproud/golang_protobuf_extensions/pbutil licensed under: = Apache License Version 2.0, January 2004 @@ -70745,7 +72665,18 @@ THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2015 Openstorage.org. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2013 Matt T. Proud Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -70759,14 +72690,14 @@ THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/libopenstorage/openstorage/LICENSE 40c3e1c9eacda859a17048003909a2f8 += vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE a45ffb9ad39d4b4c1053bb27f6bb4272 ================================================================================ ================================================================================ -= vendor/github.com/lpabon/godbc licensed under: = += vendor/github.com/mholt/caddy/caddyfile licensed under: = -Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -70967,94 +72898,17 @@ Apache License 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. -= vendor/github.com/lpabon/godbc/LICENSE 6c4db32a2fa8717faffa1d4f10136f47 -================================================================================ - - -================================================================================ -= vendor/github.com/magiconair/properties licensed under: = - -goproperties - properties file decoder for Go - -Copyright (c) 2013-2014 - Frank Schroeder - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/magiconair/properties/LICENSE c383a608fb9a0d227953e928803b9631 -================================================================================ - - -================================================================================ -= vendor/github.com/mailru/easyjson/buffer licensed under: = - -Copyright (c) 2016 Mail.Ru Group - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= vendor/github.com/mailru/easyjson/LICENSE 819e81c2ec13e1bbc47dc5e90bb4d88b -================================================================================ - - -================================================================================ -= vendor/github.com/mailru/easyjson/jlexer licensed under: = - -Copyright (c) 2016 Mail.Ru Group -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= vendor/github.com/mailru/easyjson/LICENSE 819e81c2ec13e1bbc47dc5e90bb4d88b -================================================================================ - - -================================================================================ -= vendor/github.com/mailru/easyjson/jwriter licensed under: = - -Copyright (c) 2016 Mail.Ru Group - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= vendor/github.com/mailru/easyjson/LICENSE 819e81c2ec13e1bbc47dc5e90bb4d88b += vendor/github.com/mholt/caddy/LICENSE.txt e3fc50a88d0a364313df4b21ef20c29e ================================================================================ ================================================================================ -= vendor/github.com/MakeNowJust/heredoc licensed under: = += vendor/github.com/Microsoft/go-winio licensed under: = The MIT License (MIT) -Copyright (c) 2014-2017 TSUYUSATO Kitsune +Copyright (c) 2015 Microsoft Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -71063,27 +72917,28 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -= vendor/github.com/MakeNowJust/heredoc/LICENSE 59c4411f6d7dfdaa85623e672d3d4438 + += vendor/github.com/Microsoft/go-winio/LICENSE 69205ff73858f2c22b2ca135b557e8ef ================================================================================ ================================================================================ -= vendor/github.com/marstr/guid licensed under: = += vendor/github.com/Microsoft/hcsshim licensed under: = -MIT License +The MIT License (MIT) -Copyright (c) 2016 Martin Strobel +Copyright (c) 2015 Microsoft Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -71102,12 +72957,53 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/marstr/guid/LICENSE.txt 356484d12e6ad8a7c2d360b236e9a9c8 += vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e ================================================================================ ================================================================================ -= vendor/github.com/matttproud/golang_protobuf_extensions/pbutil licensed under: = += vendor/github.com/miekg/dns licensed under: = + +Extensions of the original work are copyright (c) 2011 Miek Gieben + +As this is fork of the official Go code the same license applies: + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + += vendor/github.com/miekg/dns/LICENSE 147353de6868a20caa562d26eab7b3c5 +================================================================================ + + +================================================================================ += vendor/github.com/mindprince/gonvml licensed under: = + Apache License Version 2.0, January 2004 @@ -71297,7 +73193,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2013 Matt T. Proud + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -71311,14 +73207,14 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE a45ffb9ad39d4b4c1053bb27f6bb4272 += vendor/github.com/mindprince/gonvml/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/mholt/caddy/caddyfile licensed under: = += vendor/github.com/mistifyio/go-zfs licensed under: = - Apache License +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -71506,7 +73402,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright (c) 2014, OmniTI Computer Consulting, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -71519,17 +73415,16 @@ SOFTWARE. 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. - -= vendor/github.com/mholt/caddy/LICENSE.txt e3fc50a88d0a364313df4b21ef20c29e += vendor/github.com/mistifyio/go-zfs/LICENSE cce9462224bfb44c1866ef7bd5eddf54 ================================================================================ ================================================================================ -= vendor/github.com/Microsoft/go-winio licensed under: = += vendor/github.com/mitchellh/go-wordwrap licensed under: = The MIT License (MIT) -Copyright (c) 2015 Microsoft +Copyright (c) 2014 Mitchell Hashimoto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -71538,28 +73433,27 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -= vendor/github.com/Microsoft/go-winio/LICENSE 69205ff73858f2c22b2ca135b557e8ef += vendor/github.com/mitchellh/go-wordwrap/LICENSE.md 56da355a12d4821cda57b8f23ec34bc4 ================================================================================ ================================================================================ -= vendor/github.com/Microsoft/hcsshim licensed under: = += vendor/github.com/mitchellh/mapstructure licensed under: = The MIT License (MIT) -Copyright (c) 2015 Microsoft +Copyright (c) 2013 Mitchell Hashimoto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -71568,63 +73462,23 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -= vendor/github.com/Microsoft/hcsshim/LICENSE d4c2cbbea5ee1e7c86dff68a7073718e -================================================================================ - - -================================================================================ -= vendor/github.com/miekg/dns licensed under: = - -Extensions of the original work are copyright (c) 2011 Miek Gieben - -As this is fork of the official Go code the same license applies: - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -= vendor/github.com/miekg/dns/LICENSE 147353de6868a20caa562d26eab7b3c5 += vendor/github.com/mitchellh/mapstructure/LICENSE 3f7765c3d4f58e1f84c4313cecf0f5bd ================================================================================ ================================================================================ -= vendor/github.com/mindprince/gonvml licensed under: = - += vendor/github.com/modern-go/concurrent licensed under: = Apache License Version 2.0, January 2004 @@ -71828,14 +73682,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/mindprince/gonvml/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/modern-go/concurrent/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/mistifyio/go-zfs licensed under: = += vendor/github.com/modern-go/reflect2 licensed under: = -Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -72015,7 +73869,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -72023,7 +73877,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright (c) 2014, OmniTI Computer Consulting, Inc. + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -72036,65 +73890,8 @@ Apache License 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. -= vendor/github.com/mistifyio/go-zfs/LICENSE cce9462224bfb44c1866ef7bd5eddf54 -================================================================================ - -================================================================================ -= vendor/github.com/mitchellh/go-wordwrap licensed under: = - -The MIT License (MIT) - -Copyright (c) 2014 Mitchell Hashimoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -= vendor/github.com/mitchellh/go-wordwrap/LICENSE.md 56da355a12d4821cda57b8f23ec34bc4 -================================================================================ - - -================================================================================ -= vendor/github.com/mitchellh/mapstructure licensed under: = - -The MIT License (MIT) - -Copyright (c) 2013 Mitchell Hashimoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -= vendor/github.com/mitchellh/mapstructure/LICENSE 3f7765c3d4f58e1f84c4313cecf0f5bd += vendor/github.com/modern-go/reflect2/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ @@ -72127,35 +73924,6 @@ SOFTWARE. ================================================================================ -================================================================================ -= vendor/github.com/mreiferson/go-httpclient licensed under: = - -The MIT License (MIT) - -Copyright (c) 2012 Matt Reiferson - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -= vendor/github.com/mreiferson/go-httpclient/LICENSE 443af26efefd8192911d22fb48b35824 -================================================================================ - - ================================================================================ = vendor/github.com/mrunalp/fileutils licensed under: = @@ -72791,7 +74559,259 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/ginkgo/internal/failer licensed under: = += vendor/github.com/onsi/ginkgo/internal/failer licensed under: = + +Copyright (c) 2013-2014 Onsi Fakhouri + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/onsi/ginkgo/internal/leafnodes licensed under: = + +Copyright (c) 2013-2014 Onsi Fakhouri + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/onsi/ginkgo/internal/remote licensed under: = + +Copyright (c) 2013-2014 Onsi Fakhouri + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/onsi/ginkgo/internal/spec licensed under: = + +Copyright (c) 2013-2014 Onsi Fakhouri + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/onsi/ginkgo/internal/specrunner licensed under: = + +Copyright (c) 2013-2014 Onsi Fakhouri + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/onsi/ginkgo/internal/spec_iterator licensed under: = + +Copyright (c) 2013-2014 Onsi Fakhouri + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/onsi/ginkgo/internal/suite licensed under: = + +Copyright (c) 2013-2014 Onsi Fakhouri + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/onsi/ginkgo/internal/testingtproxy licensed under: = + +Copyright (c) 2013-2014 Onsi Fakhouri + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/onsi/ginkgo/internal/writer licensed under: = + +Copyright (c) 2013-2014 Onsi Fakhouri + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/onsi/ginkgo/reporters licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -72819,7 +74839,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/ginkgo/internal/leafnodes licensed under: = += vendor/github.com/onsi/ginkgo/reporters/stenographer licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -72847,7 +74867,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/ginkgo/internal/remote licensed under: = += vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -72875,7 +74895,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/ginkgo/internal/spec licensed under: = += vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -72903,7 +74923,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/ginkgo/internal/specrunner licensed under: = += vendor/github.com/onsi/ginkgo/types licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -72931,7 +74951,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/ginkgo/internal/spec_iterator licensed under: = += vendor/github.com/onsi/gomega licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -72954,12 +74974,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 ================================================================================ ================================================================================ -= vendor/github.com/onsi/ginkgo/internal/suite licensed under: = += vendor/github.com/onsi/gomega/format licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -72982,12 +75002,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 ================================================================================ ================================================================================ -= vendor/github.com/onsi/ginkgo/internal/testingtproxy licensed under: = += vendor/github.com/onsi/gomega/gstruct licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73010,12 +75030,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 ================================================================================ ================================================================================ -= vendor/github.com/onsi/ginkgo/internal/writer licensed under: = += vendor/github.com/onsi/gomega/gstruct/errors licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73038,12 +75058,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 ================================================================================ ================================================================================ -= vendor/github.com/onsi/ginkgo/reporters licensed under: = += vendor/github.com/onsi/gomega/internal/assertion licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73066,12 +75086,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 ================================================================================ ================================================================================ -= vendor/github.com/onsi/ginkgo/reporters/stenographer licensed under: = += vendor/github.com/onsi/gomega/internal/asyncassertion licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73094,12 +75114,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 ================================================================================ ================================================================================ -= vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable licensed under: = += vendor/github.com/onsi/gomega/internal/oraclematcher licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73122,12 +75142,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 ================================================================================ ================================================================================ -= vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty licensed under: = += vendor/github.com/onsi/gomega/internal/testingtsupport licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73150,12 +75170,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 ================================================================================ ================================================================================ -= vendor/github.com/onsi/ginkgo/types licensed under: = += vendor/github.com/onsi/gomega/matchers licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73178,12 +75198,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/ginkgo/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 ================================================================================ ================================================================================ -= vendor/github.com/onsi/gomega licensed under: = += vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73211,7 +75231,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/gomega/format licensed under: = += vendor/github.com/onsi/gomega/matchers/support/goraph/edge licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73239,7 +75259,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/gomega/gstruct licensed under: = += vendor/github.com/onsi/gomega/matchers/support/goraph/node licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73267,7 +75287,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/gomega/gstruct/errors licensed under: = += vendor/github.com/onsi/gomega/matchers/support/goraph/util licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73295,7 +75315,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/onsi/gomega/internal/assertion licensed under: = += vendor/github.com/onsi/gomega/types licensed under: = Copyright (c) 2013-2014 Onsi Fakhouri @@ -73318,269 +75338,614 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 -================================================================================ += vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 +================================================================================ + + +================================================================================ += vendor/github.com/opencontainers/go-digest licensed under: = + + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2016 Docker, Inc. + + 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 + + https://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. + += vendor/github.com/opencontainers/go-digest/LICENSE.code 9cd86830b557232ce55e2a6b47387471 +================================================================================ + + +================================================================================ += vendor/github.com/opencontainers/image-spec/specs-go licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -================================================================================ -= vendor/github.com/onsi/gomega/internal/asyncassertion licensed under: = + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -Copyright (c) 2013-2014 Onsi Fakhouri + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 -================================================================================ + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -================================================================================ -= vendor/github.com/onsi/gomega/internal/oraclematcher licensed under: = + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -Copyright (c) 2013-2014 Onsi Fakhouri + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 -================================================================================ + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -================================================================================ -= vendor/github.com/onsi/gomega/internal/testingtsupport licensed under: = + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -Copyright (c) 2013-2014 Onsi Fakhouri + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 -================================================================================ + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -================================================================================ -= vendor/github.com/onsi/gomega/matchers licensed under: = + END OF TERMS AND CONDITIONS -Copyright (c) 2013-2014 Onsi Fakhouri + Copyright 2016 The Linux Foundation. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + 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 -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + http://www.apache.org/licenses/LICENSE-2.0 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 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. -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/opencontainers/image-spec/LICENSE 27ef03aa2da6e424307f102e8b42621d ================================================================================ ================================================================================ -= vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph licensed under: = += vendor/github.com/opencontainers/image-spec/specs-go/v1 licensed under: = -Copyright (c) 2013-2014 Onsi Fakhouri -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 1. Definitions. -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 -================================================================================ + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -================================================================================ -= vendor/github.com/onsi/gomega/matchers/support/goraph/edge licensed under: = + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -Copyright (c) 2013-2014 Onsi Fakhouri + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 -================================================================================ + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -================================================================================ -= vendor/github.com/onsi/gomega/matchers/support/goraph/node licensed under: = + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -Copyright (c) 2013-2014 Onsi Fakhouri + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 -================================================================================ + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -================================================================================ -= vendor/github.com/onsi/gomega/matchers/support/goraph/util licensed under: = + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -Copyright (c) 2013-2014 Onsi Fakhouri + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 -================================================================================ + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -================================================================================ -= vendor/github.com/onsi/gomega/types licensed under: = + END OF TERMS AND CONDITIONS -Copyright (c) 2013-2014 Onsi Fakhouri + Copyright 2016 The Linux Foundation. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + 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 -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + http://www.apache.org/licenses/LICENSE-2.0 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 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. -= vendor/github.com/onsi/gomega/LICENSE 570603114d52313cb86c0206401c9af7 += vendor/github.com/opencontainers/image-spec/LICENSE 27ef03aa2da6e424307f102e8b42621d ================================================================================ ================================================================================ -= vendor/github.com/opencontainers/go-digest licensed under: = += vendor/github.com/opencontainers/runc/libcontainer licensed under: = Apache License Version 2.0, January 2004 - https://www.apache.org/licenses/ + http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -73755,13 +76120,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2016 Docker, Inc. + Copyright 2014 Docker, Inc. 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 - https://www.apache.org/licenses/LICENSE-2.0 + 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, @@ -73769,12 +76134,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/opencontainers/go-digest/LICENSE.code 9cd86830b557232ce55e2a6b47387471 += vendor/github.com/opencontainers/runc/LICENSE 435b266b3899aa8a959f17d41c56def8 ================================================================================ ================================================================================ -= vendor/github.com/opencontainers/image-spec/specs-go licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/apparmor licensed under: = Apache License @@ -73954,7 +76319,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2016 The Linux Foundation. + Copyright 2014 Docker, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -73968,12 +76333,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/opencontainers/image-spec/LICENSE 27ef03aa2da6e424307f102e8b42621d += vendor/github.com/opencontainers/runc/LICENSE 435b266b3899aa8a959f17d41c56def8 ================================================================================ ================================================================================ -= vendor/github.com/opencontainers/image-spec/specs-go/v1 licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/cgroups licensed under: = Apache License @@ -74153,7 +76518,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2016 The Linux Foundation. + Copyright 2014 Docker, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -74167,12 +76532,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/opencontainers/image-spec/LICENSE 27ef03aa2da6e424307f102e8b42621d += vendor/github.com/opencontainers/runc/LICENSE 435b266b3899aa8a959f17d41c56def8 ================================================================================ ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs licensed under: = Apache License @@ -74371,7 +76736,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/apparmor licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd licensed under: = Apache License @@ -74570,7 +76935,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/cgroups licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/configs licensed under: = Apache License @@ -74769,7 +77134,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/configs/validate licensed under: = Apache License @@ -74968,7 +77333,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/criurpc licensed under: = Apache License @@ -75167,7 +77532,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/configs licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/intelrdt licensed under: = Apache License @@ -75366,7 +77731,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/configs/validate licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/keys licensed under: = Apache License @@ -75565,7 +77930,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/criurpc licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/mount licensed under: = Apache License @@ -75764,7 +78129,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/intelrdt licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/seccomp licensed under: = Apache License @@ -75963,7 +78328,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/keys licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/stacktrace licensed under: = Apache License @@ -76162,7 +78527,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/mount licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/system licensed under: = Apache License @@ -76361,7 +78726,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/seccomp licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/user licensed under: = Apache License @@ -76560,7 +78925,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/stacktrace licensed under: = += vendor/github.com/opencontainers/runc/libcontainer/utils licensed under: = Apache License @@ -76759,7 +79124,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/system licensed under: = += vendor/github.com/opencontainers/runtime-spec/specs-go licensed under: = Apache License @@ -76939,7 +79304,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2014 Docker, Inc. + Copyright 2015 The Linux Foundation. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -76953,13 +79318,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/opencontainers/runc/LICENSE 435b266b3899aa8a959f17d41c56def8 += vendor/github.com/opencontainers/runtime-spec/LICENSE b355a61a394a504dacde901c958f662c ================================================================================ ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/user licensed under: = - += vendor/github.com/opencontainers/selinux/go-selinux licensed under: = Apache License Version 2.0, January 2004 @@ -77138,7 +79502,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2014 Docker, Inc. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -77152,13 +79527,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/opencontainers/runc/LICENSE 435b266b3899aa8a959f17d41c56def8 += vendor/github.com/opencontainers/selinux/LICENSE e3fc50a88d0a364313df4b21ef20c29e ================================================================================ ================================================================================ -= vendor/github.com/opencontainers/runc/libcontainer/utils licensed under: = - += vendor/github.com/opencontainers/selinux/go-selinux/label licensed under: = Apache License Version 2.0, January 2004 @@ -77337,7 +79711,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2014 Docker, Inc. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -77351,12 +79736,186 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/opencontainers/runc/LICENSE 435b266b3899aa8a959f17d41c56def8 += vendor/github.com/opencontainers/selinux/LICENSE e3fc50a88d0a364313df4b21ef20c29e ================================================================================ ================================================================================ -= vendor/github.com/opencontainers/runtime-spec/specs-go licensed under: = += vendor/github.com/pborman/uuid licensed under: = + +Copyright (c) 2009,2014 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/pborman/uuid/LICENSE 88073b6dd8ec00fe09da59e0b6dfded1 +================================================================================ + + +================================================================================ += vendor/github.com/pelletier/go-toml licensed under: = + +The MIT License (MIT) + +Copyright (c) 2013 - 2017 Thomas Pelletier, Eric Anderton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + += vendor/github.com/pelletier/go-toml/LICENSE dc9ea87a81f62b8871b2a4158edbfde6 +================================================================================ + + +================================================================================ += vendor/github.com/peterbourgon/diskv licensed under: = + +Copyright (c) 2011-2012 Peter Bourgon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + += vendor/github.com/peterbourgon/diskv/LICENSE f9f3e815fc84aa04c4f4db33c553eef9 +================================================================================ + + +================================================================================ += vendor/github.com/pkg/errors licensed under: = + +Copyright (c) 2015, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/pkg/errors/LICENSE 6fe682a02df52c6653f33bd0f7126b5a +================================================================================ + + +================================================================================ += vendor/github.com/pkg/sftp licensed under: = + +Copyright (c) 2013, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/pkg/sftp/LICENSE 452fc5cc5a9127a0e828d73423d45035 +================================================================================ + + +================================================================================ += vendor/github.com/pmezard/go-difflib/difflib licensed under: = + +Copyright (c) 2013, Patrick Mezard +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + The names of its contributors may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/pmezard/go-difflib/LICENSE e9a2ebb8de779a07500ddecca806145e +================================================================================ + + +================================================================================ += vendor/github.com/pquerna/cachecontrol licensed under: = Apache License @@ -77536,7 +80095,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2015 The Linux Foundation. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -77550,12 +80120,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/opencontainers/runtime-spec/LICENSE b355a61a394a504dacde901c958f662c += vendor/github.com/pquerna/cachecontrol/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/opencontainers/selinux/go-selinux licensed under: = += vendor/github.com/pquerna/cachecontrol/cacheobject licensed under: = + Apache License Version 2.0, January 2004 @@ -77737,7 +80308,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -77745,7 +80316,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -77759,12 +80330,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/opencontainers/selinux/LICENSE e3fc50a88d0a364313df4b21ef20c29e += vendor/github.com/pquerna/cachecontrol/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/opencontainers/selinux/go-selinux/label licensed under: = += vendor/github.com/prometheus/client_golang/prometheus licensed under: = Apache License Version 2.0, January 2004 @@ -77946,7 +80517,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -77954,7 +80525,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -77968,258 +80539,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/opencontainers/selinux/LICENSE e3fc50a88d0a364313df4b21ef20c29e -================================================================================ - - -================================================================================ -= vendor/github.com/pborman/uuid licensed under: = - -Copyright (c) 2009,2014 Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/pborman/uuid/LICENSE 88073b6dd8ec00fe09da59e0b6dfded1 -================================================================================ - - -================================================================================ -= vendor/github.com/pelletier/go-buffruneio licensed under: = - -# buffruneio - -[![Tests Status](https://travis-ci.org/pelletier/go-buffruneio.svg?branch=master)](https://travis-ci.org/pelletier/go-buffruneio) -[![GoDoc](https://godoc.org/github.com/pelletier/go-buffruneio?status.svg)](https://godoc.org/github.com/pelletier/go-buffruneio) - -Buffruneio is a wrapper around bufio to provide buffered runes access with -unlimited unreads. - -```go -import "github.com/pelletier/go-buffruneio" -``` - -## Examples - -```go -import ( - "fmt" - "github.com/pelletier/go-buffruneio" - "strings" -) - -reader := buffruneio.NewReader(strings.NewReader("abcd")) -fmt.Println(reader.ReadRune()) // 'a' -fmt.Println(reader.ReadRune()) // 'b' -fmt.Println(reader.ReadRune()) // 'c' -reader.UnreadRune() -reader.UnreadRune() -fmt.Println(reader.ReadRune()) // 'b' -fmt.Println(reader.ReadRune()) // 'c' -``` - -## Documentation - -The documentation and additional examples are available at -[godoc.org](http://godoc.org/github.com/pelletier/go-buffruneio). - -## Contribute - -Feel free to report bugs and patches using GitHub's pull requests system on -[pelletier/go-toml](https://github.com/pelletier/go-buffruneio). Any feedback is -much appreciated! - -## LICENSE - -Copyright (c) 2016 Thomas Pelletier - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= vendor/github.com/pelletier/go-buffruneio/README.md 842f126317ddc8826665a8f44bae9607 -================================================================================ - - -================================================================================ -= vendor/github.com/pelletier/go-toml licensed under: = - -The MIT License (MIT) - -Copyright (c) 2013 - 2016 Thomas Pelletier, Eric Anderton - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -= vendor/github.com/pelletier/go-toml/LICENSE fe394639a0a3170b77ebe8d45430aacd -================================================================================ - - -================================================================================ -= vendor/github.com/peterbourgon/diskv licensed under: = - -Copyright (c) 2011-2012 Peter Bourgon - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -= vendor/github.com/peterbourgon/diskv/LICENSE f9f3e815fc84aa04c4f4db33c553eef9 -================================================================================ - - -================================================================================ -= vendor/github.com/pkg/errors licensed under: = - -Copyright (c) 2015, Dave Cheney -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/pkg/errors/LICENSE 6fe682a02df52c6653f33bd0f7126b5a -================================================================================ - - -================================================================================ -= vendor/github.com/pkg/sftp licensed under: = - -Copyright (c) 2013, Dave Cheney -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/pkg/sftp/LICENSE 452fc5cc5a9127a0e828d73423d45035 -================================================================================ - - -================================================================================ -= vendor/github.com/pmezard/go-difflib/difflib licensed under: = - -Copyright (c) 2013, Patrick Mezard -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - The names of its contributors may not be used to endorse or promote -products derived from this software without specific prior written -permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/pmezard/go-difflib/LICENSE e9a2ebb8de779a07500ddecca806145e += vendor/github.com/prometheus/client_golang/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/pquerna/cachecontrol licensed under: = - += vendor/github.com/prometheus/client_golang/prometheus/promhttp licensed under: = Apache License Version 2.0, January 2004 @@ -78423,13 +80748,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/pquerna/cachecontrol/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/prometheus/client_golang/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/pquerna/cachecontrol/cacheobject licensed under: = - += vendor/github.com/prometheus/client_model/go licensed under: = Apache License Version 2.0, January 2004 @@ -78633,12 +80957,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/pquerna/cachecontrol/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 += vendor/github.com/prometheus/client_model/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/prometheus/client_golang/prometheus licensed under: = += vendor/github.com/prometheus/common/expfmt licensed under: = Apache License Version 2.0, January 2004 @@ -78842,12 +81166,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/prometheus/client_golang/LICENSE 86d3f3a95c324c9479bd8986968f4327 += vendor/github.com/prometheus/common/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/prometheus/client_golang/prometheus/promhttp licensed under: = += vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg licensed under: = Apache License Version 2.0, January 2004 @@ -79051,12 +81375,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/prometheus/client_golang/LICENSE 86d3f3a95c324c9479bd8986968f4327 += vendor/github.com/prometheus/common/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/prometheus/client_model/go licensed under: = += vendor/github.com/prometheus/common/model licensed under: = Apache License Version 2.0, January 2004 @@ -79260,12 +81584,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/prometheus/client_model/LICENSE 86d3f3a95c324c9479bd8986968f4327 += vendor/github.com/prometheus/common/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/prometheus/common/expfmt licensed under: = += vendor/github.com/prometheus/procfs licensed under: = Apache License Version 2.0, January 2004 @@ -79469,12 +81793,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/prometheus/common/LICENSE 86d3f3a95c324c9479bd8986968f4327 += vendor/github.com/prometheus/procfs/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg licensed under: = += vendor/github.com/prometheus/procfs/xfs licensed under: = Apache License Version 2.0, January 2004 @@ -79678,12 +82002,104 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/prometheus/common/LICENSE 86d3f3a95c324c9479bd8986968f4327 += vendor/github.com/prometheus/procfs/LICENSE 86d3f3a95c324c9479bd8986968f4327 ================================================================================ ================================================================================ -= vendor/github.com/prometheus/common/model licensed under: = += vendor/github.com/PuerkitoBio/purell licensed under: = + +Copyright (c) 2012, Martin Angers +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/PuerkitoBio/purell/LICENSE fb8b39492731abb9a3d68575f3eedbfa +================================================================================ + + +================================================================================ += vendor/github.com/PuerkitoBio/urlesc licensed under: = + +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/PuerkitoBio/urlesc/LICENSE 591778525c869cdde0ab5a1bf283cd81 +================================================================================ + + +================================================================================ += vendor/github.com/quobyte/api licensed under: = + + +Copyright (c) 2016, Quobyte Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of quobyte-automation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/quobyte/api/LICENSE beacc5ea3bcda24bdcec545022dbb0b4 +================================================================================ + + +================================================================================ += vendor/github.com/rancher/go-rancher/client licensed under: = + Apache License Version 2.0, January 2004 @@ -79814,87 +82230,301 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + += vendor/github.com/rancher/go-rancher/LICENSE 2ee41112a44fe7014dce33e26468ba93 +================================================================================ + + +================================================================================ += vendor/github.com/renstrom/dedent licensed under: = + +The MIT License (MIT) + +Copyright (c) 2015 Peter Renström + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + += vendor/github.com/renstrom/dedent/LICENSE 285693e07a6e1fd790cb3f3b8b5127db +================================================================================ + + +================================================================================ += vendor/github.com/robfig/cron licensed under: = + +Copyright (C) 2012 Rob Figueiredo +All Rights Reserved. + +MIT LICENSE + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/robfig/cron/LICENSE d924a63cb54a2a6c4bd28c50b2b0af59 +================================================================================ + + +================================================================================ += vendor/github.com/rubiojr/go-vhd/vhd licensed under: = + +The MIT License (MIT) + +Copyright (c) 2015 Sergio Rubio + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + += vendor/github.com/rubiojr/go-vhd/LICENSE 9ce5db55ba47444787183e59733e1977 +================================================================================ + + +================================================================================ += vendor/github.com/russross/blackfriday licensed under: = + +Blackfriday is distributed under the Simplified BSD License: + +> Copyright © 2011 Russ Ross +> All rights reserved. +> +> Redistribution and use in source and binary forms, with or without +> modification, are permitted provided that the following conditions +> are met: +> +> 1. Redistributions of source code must retain the above copyright +> notice, this list of conditions and the following disclaimer. +> +> 2. Redistributions in binary form must reproduce the above +> copyright notice, this list of conditions and the following +> disclaimer in the documentation and/or other materials provided with +> the distribution. +> +> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +> COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +> INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +> BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +> LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +> ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +> POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/russross/blackfriday/LICENSE.txt ecf8a8a60560c35a862a4a545f2db1b3 +================================================================================ + + +================================================================================ += vendor/github.com/satori/go.uuid licensed under: = + +Copyright (C) 2013-2016 by Maxim Bublis + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/satori/go.uuid/LICENSE 02d5d17de0c82a23a09863acccc026f6 +================================================================================ + + +================================================================================ += vendor/github.com/seccomp/libseccomp-golang licensed under: = + +Copyright (c) 2015 Matthew Heon +Copyright (c) 2015 Paul Moore +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/seccomp/libseccomp-golang/LICENSE 343b433e752e8b44a543cdf61f14b628 +================================================================================ + + +================================================================================ += vendor/github.com/shurcooL/sanitized_anchor_name licensed under: = + +Copyright (c) 2015 Dmitri Shuralyov - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. += vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE bee2c3aa5bd0f265ffbd193eb18ca30d +================================================================================ - END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. +================================================================================ += vendor/github.com/sirupsen/logrus licensed under: = - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. +The MIT License (MIT) - Copyright [yyyy] [name of copyright owner] +Copyright (c) 2014 Simon Eskildsen - 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 +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - http://www.apache.org/licenses/LICENSE-2.0 +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - 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. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -= vendor/github.com/prometheus/common/LICENSE 86d3f3a95c324c9479bd8986968f4327 += vendor/github.com/sirupsen/logrus/LICENSE 8dadfef729c08ec4e631c4f6fc5d43a0 ================================================================================ ================================================================================ -= vendor/github.com/prometheus/procfs licensed under: = += vendor/github.com/spf13/afero licensed under: = - Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -80069,41 +82699,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - -= vendor/github.com/prometheus/procfs/LICENSE 86d3f3a95c324c9479bd8986968f4327 += vendor/github.com/spf13/afero/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be ================================================================================ ================================================================================ -= vendor/github.com/prometheus/procfs/xfs licensed under: = += vendor/github.com/spf13/afero/mem licensed under: = - Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -80278,133 +82881,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - -= vendor/github.com/prometheus/procfs/LICENSE 86d3f3a95c324c9479bd8986968f4327 -================================================================================ - - -================================================================================ -= vendor/github.com/PuerkitoBio/purell licensed under: = - -Copyright (c) 2012, Martin Angers -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/PuerkitoBio/purell/LICENSE fb8b39492731abb9a3d68575f3eedbfa -================================================================================ - - -================================================================================ -= vendor/github.com/PuerkitoBio/urlesc licensed under: = - -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/PuerkitoBio/urlesc/LICENSE 591778525c869cdde0ab5a1bf283cd81 -================================================================================ - - -================================================================================ -= vendor/github.com/quobyte/api licensed under: = - - -Copyright (c) 2016, Quobyte Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of quobyte-automation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/quobyte/api/LICENSE beacc5ea3bcda24bdcec545022dbb0b4 += vendor/github.com/spf13/afero/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be ================================================================================ ================================================================================ -= vendor/github.com/rancher/go-rancher/client licensed under: = - += vendor/github.com/spf13/afero/sftp licensed under: = - Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -80517,290 +83001,78 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - -= vendor/github.com/rancher/go-rancher/LICENSE 2ee41112a44fe7014dce33e26468ba93 -================================================================================ - - -================================================================================ -= vendor/github.com/renstrom/dedent licensed under: = - -The MIT License (MIT) - -Copyright (c) 2015 Peter Renström - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -= vendor/github.com/renstrom/dedent/LICENSE 285693e07a6e1fd790cb3f3b8b5127db -================================================================================ - - -================================================================================ -= vendor/github.com/robfig/cron licensed under: = - -Copyright (C) 2012 Rob Figueiredo -All Rights Reserved. - -MIT LICENSE - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= vendor/github.com/robfig/cron/LICENSE d924a63cb54a2a6c4bd28c50b2b0af59 -================================================================================ - - -================================================================================ -= vendor/github.com/rubiojr/go-vhd/vhd licensed under: = - -The MIT License (MIT) - -Copyright (c) 2015 Sergio Rubio - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -= vendor/github.com/rubiojr/go-vhd/LICENSE 9ce5db55ba47444787183e59733e1977 -================================================================================ - - -================================================================================ -= vendor/github.com/russross/blackfriday licensed under: = - -Blackfriday is distributed under the Simplified BSD License: - -> Copyright © 2011 Russ Ross -> All rights reserved. -> -> Redistribution and use in source and binary forms, with or without -> modification, are permitted provided that the following conditions -> are met: -> -> 1. Redistributions of source code must retain the above copyright -> notice, this list of conditions and the following disclaimer. -> -> 2. Redistributions in binary form must reproduce the above -> copyright notice, this list of conditions and the following -> disclaimer in the documentation and/or other materials provided with -> the distribution. -> -> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -> COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -> INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -> BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -> LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -> ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -> POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/russross/blackfriday/LICENSE.txt ecf8a8a60560c35a862a4a545f2db1b3 -================================================================================ - - -================================================================================ -= vendor/github.com/satori/go.uuid licensed under: = - -Copyright (C) 2013-2016 by Maxim Bublis - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= vendor/github.com/satori/go.uuid/LICENSE 02d5d17de0c82a23a09863acccc026f6 -================================================================================ - - -================================================================================ -= vendor/github.com/seccomp/libseccomp-golang licensed under: = - -Copyright (c) 2015 Matthew Heon -Copyright (c) 2015 Paul Moore -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -- Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/seccomp/libseccomp-golang/LICENSE 343b433e752e8b44a543cdf61f14b628 -================================================================================ + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -================================================================================ -= vendor/github.com/shurcooL/sanitized_anchor_name licensed under: = + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -Copyright (c) 2015 Dmitri Shuralyov + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -= vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE bee2c3aa5bd0f265ffbd193eb18ca30d += vendor/github.com/spf13/afero/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be ================================================================================ ================================================================================ -= vendor/github.com/sirupsen/logrus licensed under: = += vendor/github.com/spf13/cast licensed under: = The MIT License (MIT) -Copyright (c) 2014 Simon Eskildsen +Copyright (c) 2014 Steve Francia Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -80809,23 +83081,22 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -= vendor/github.com/sirupsen/logrus/LICENSE 8dadfef729c08ec4e631c4f6fc5d43a0 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. += vendor/github.com/spf13/cast/LICENSE 67fac7567cbf6ba946e5576d590b1ed4 ================================================================================ ================================================================================ -= vendor/github.com/spf13/afero licensed under: = += vendor/github.com/spf13/cobra licensed under: = Apache License Version 2.0, January 2004 @@ -81002,12 +83273,12 @@ THE SOFTWARE. incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. -= vendor/github.com/spf13/afero/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be += vendor/github.com/spf13/cobra/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be ================================================================================ ================================================================================ -= vendor/github.com/spf13/afero/mem licensed under: = += vendor/github.com/spf13/cobra/doc licensed under: = Apache License Version 2.0, January 2004 @@ -81184,198 +83455,510 @@ THE SOFTWARE. incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. -= vendor/github.com/spf13/afero/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be += vendor/github.com/spf13/cobra/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be ================================================================================ ================================================================================ -= vendor/github.com/spf13/afero/sftp licensed under: = += vendor/github.com/spf13/jwalterweatherman licensed under: = - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +The MIT License (MIT) - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Copyright (c) 2014 Steve Francia - 1. Definitions. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. += vendor/github.com/spf13/jwalterweatherman/LICENSE 67fac7567cbf6ba946e5576d590b1ed4 +================================================================================ - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. +================================================================================ += vendor/github.com/spf13/pflag licensed under: = - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. +Copyright (c) 2012 Alex Ogier. All rights reserved. +Copyright (c) 2012 The Go Authors. All rights reserved. - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/spf13/pflag/LICENSE 1e8b7dc8b906737639131047a590f21d +================================================================================ + + +================================================================================ += vendor/github.com/spf13/viper licensed under: = + +The MIT License (MIT) + +Copyright (c) 2014 Steve Francia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. += vendor/github.com/spf13/viper/LICENSE 67fac7567cbf6ba946e5576d590b1ed4 +================================================================================ + + +================================================================================ += vendor/github.com/storageos/go-api licensed under: = + +MIT License + +Copyright (c) 2015-2017 StorageOS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Copyright (c) 2013-2017, go-dockerclient authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/storageos/go-api/LICENCE d8f852a0f38554263e64363f57b07fc4 +================================================================================ + + +================================================================================ += vendor/github.com/storageos/go-api/netutil licensed under: = + +MIT License + +Copyright (c) 2015-2017 StorageOS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Copyright (c) 2013-2017, go-dockerclient authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/storageos/go-api/LICENCE d8f852a0f38554263e64363f57b07fc4 +================================================================================ + + +================================================================================ += vendor/github.com/storageos/go-api/serror licensed under: = + +MIT License + +Copyright (c) 2015-2017 StorageOS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Copyright (c) 2013-2017, go-dockerclient authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/storageos/go-api/LICENCE d8f852a0f38554263e64363f57b07fc4 +================================================================================ + + +================================================================================ += vendor/github.com/storageos/go-api/types licensed under: = + +MIT License + +Copyright (c) 2015-2017 StorageOS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Copyright (c) 2013-2017, go-dockerclient authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/storageos/go-api/LICENCE d8f852a0f38554263e64363f57b07fc4 +================================================================================ + + +================================================================================ += vendor/github.com/stretchr/objx licensed under: = + +objx - by Mat Ryer and Tyler Bunnell + +The MIT License (MIT) + +Copyright (c) 2014 Stretchr, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + += vendor/github.com/stretchr/objx/LICENSE.md 21e79cfe7201b9b64535bfae0895795b +================================================================================ + + +================================================================================ += vendor/github.com/stretchr/testify/assert licensed under: = + +Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell + +Please consider promoting this project if you find it useful. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/stretchr/testify/LICENSE 39cd1d751bc25944831de86496e3cf68 +================================================================================ + + +================================================================================ += vendor/github.com/stretchr/testify/mock licensed under: = + +Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell + +Please consider promoting this project if you find it useful. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += vendor/github.com/stretchr/testify/LICENSE 39cd1d751bc25944831de86496e3cf68 +================================================================================ + + +================================================================================ += vendor/github.com/stretchr/testify/require licensed under: = + +Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell + +Please consider promoting this project if you find it useful. - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. += vendor/github.com/stretchr/testify/LICENSE 39cd1d751bc25944831de86496e3cf68 +================================================================================ - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. +================================================================================ += vendor/github.com/syndtr/gocapability/capability licensed under: = - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: +Copyright 2013 Suryandaru Triandana +All rights reserved. - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. += vendor/github.com/syndtr/gocapability/LICENSE a7304f5073e7be4ba7bffabbf9f2bbca +================================================================================ - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. +================================================================================ += vendor/github.com/tools/godep licensed under: = - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. +Copyright © 2013 Keith Rarick. +Portions Copyright (c) 2012 The Go Authors. All rights reserved. - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -= vendor/github.com/spf13/afero/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be += vendor/github.com/tools/godep/License 71eb66e9b353dd06ca5a81ce0f469e1a ================================================================================ ================================================================================ -= vendor/github.com/spf13/cast licensed under: = += vendor/github.com/ugorji/go/codec licensed under: = The MIT License (MIT) -Copyright (c) 2014 Steve Francia +Copyright (c) 2012-2015 Ugorji Nwoke. +All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -81394,14 +83977,16 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -= vendor/github.com/spf13/cast/LICENSE 67fac7567cbf6ba946e5576d590b1ed4 + += vendor/github.com/ugorji/go/LICENSE a03c0693c900925da5789db4e72da142 ================================================================================ ================================================================================ -= vendor/github.com/spf13/cobra licensed under: = += vendor/github.com/vishvananda/netlink licensed under: = - Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -81576,14 +84161,32 @@ SOFTWARE. incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. -= vendor/github.com/spf13/cobra/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be + END OF TERMS AND CONDITIONS + + Copyright 2014 Vishvananda Ishaya. + Copyright 2014 Docker, Inc. + + 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. + += vendor/github.com/vishvananda/netlink/LICENSE 2ade771c7d7211af507864e8dd520529 ================================================================================ ================================================================================ -= vendor/github.com/spf13/cobra/doc licensed under: = += vendor/github.com/vishvananda/netlink/nl licensed under: = - Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -81758,535 +84361,439 @@ SOFTWARE. incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. -= vendor/github.com/spf13/cobra/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be -================================================================================ - - -================================================================================ -= vendor/github.com/spf13/jwalterweatherman licensed under: = - -The MIT License (MIT) - -Copyright (c) 2014 Steve Francia - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -= vendor/github.com/spf13/jwalterweatherman/LICENSE 67fac7567cbf6ba946e5576d590b1ed4 -================================================================================ - - -================================================================================ -= vendor/github.com/spf13/pflag licensed under: = - -Copyright (c) 2012 Alex Ogier. All rights reserved. -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/spf13/pflag/LICENSE 1e8b7dc8b906737639131047a590f21d -================================================================================ - - -================================================================================ -= vendor/github.com/spf13/viper licensed under: = - -The MIT License (MIT) - -Copyright (c) 2014 Steve Francia - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -= vendor/github.com/spf13/viper/LICENSE 67fac7567cbf6ba946e5576d590b1ed4 -================================================================================ - - -================================================================================ -= vendor/github.com/storageos/go-api licensed under: = - -MIT License - -Copyright (c) 2015-2017 StorageOS - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -Copyright (c) 2013-2017, go-dockerclient authors -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/github.com/storageos/go-api/LICENCE d8f852a0f38554263e64363f57b07fc4 -================================================================================ - - -================================================================================ -= vendor/github.com/storageos/go-api/netutil licensed under: = - -MIT License - -Copyright (c) 2015-2017 StorageOS - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - + END OF TERMS AND CONDITIONS -Copyright (c) 2013-2017, go-dockerclient authors -All rights reserved. + Copyright 2014 Vishvananda Ishaya. + Copyright 2014 Docker, Inc. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + 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 - * Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. + http://www.apache.org/licenses/LICENSE-2.0 -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 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. -= vendor/github.com/storageos/go-api/LICENCE d8f852a0f38554263e64363f57b07fc4 += vendor/github.com/vishvananda/netlink/LICENSE 2ade771c7d7211af507864e8dd520529 ================================================================================ ================================================================================ -= vendor/github.com/storageos/go-api/serror licensed under: = - -MIT License - -Copyright (c) 2015-2017 StorageOS - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -Copyright (c) 2013-2017, go-dockerclient authors -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. += vendor/github.com/vishvananda/netns licensed under: = -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -= vendor/github.com/storageos/go-api/LICENCE d8f852a0f38554263e64363f57b07fc4 -================================================================================ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -================================================================================ -= vendor/github.com/storageos/go-api/types licensed under: = + 1. Definitions. -MIT License + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -Copyright (c) 2015-2017 StorageOS + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -Copyright (c) 2013-2017, go-dockerclient authors -All rights reserved. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. - * Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -= vendor/github.com/storageos/go-api/LICENCE d8f852a0f38554263e64363f57b07fc4 -================================================================================ + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -================================================================================ -= vendor/github.com/stretchr/objx licensed under: = + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -objx - by Mat Ryer and Tyler Bunnell + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -The MIT License (MIT) + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -Copyright (c) 2014 Stretchr, Inc. + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -= vendor/github.com/stretchr/objx/LICENSE.md 21e79cfe7201b9b64535bfae0895795b -================================================================================ + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -================================================================================ -= vendor/github.com/stretchr/testify/assert licensed under: = + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -Please consider promoting this project if you find it useful. + END OF TERMS AND CONDITIONS -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: + Copyright 2014 Vishvananda Ishaya. + Copyright 2014 Docker, Inc. -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. + 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 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 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. -= vendor/github.com/stretchr/testify/LICENCE.txt 39cd1d751bc25944831de86496e3cf68 += vendor/github.com/vishvananda/netns/LICENSE 2ade771c7d7211af507864e8dd520529 ================================================================================ ================================================================================ -= vendor/github.com/stretchr/testify/mock licensed under: = - -Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell += vendor/github.com/vmware/govmomi licensed under: = -Please consider promoting this project if you find it useful. -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 1. Definitions. -= vendor/github.com/stretchr/testify/LICENCE.txt 39cd1d751bc25944831de86496e3cf68 -================================================================================ + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -================================================================================ -= vendor/github.com/stretchr/testify/require licensed under: = + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Please consider promoting this project if you find it useful. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -= vendor/github.com/stretchr/testify/LICENCE.txt 39cd1d751bc25944831de86496e3cf68 -================================================================================ + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -================================================================================ -= vendor/github.com/syndtr/gocapability/capability licensed under: = + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -Copyright 2013 Suryandaru Triandana -All rights reserved. + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -= vendor/github.com/syndtr/gocapability/LICENSE a7304f5073e7be4ba7bffabbf9f2bbca -================================================================================ + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -================================================================================ -= vendor/github.com/tools/godep licensed under: = + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Copyright © 2013 Keith Rarick. -Portions Copyright (c) 2012 The Go Authors. All rights reserved. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -= vendor/github.com/tools/godep/License 71eb66e9b353dd06ca5a81ce0f469e1a -================================================================================ + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + END OF TERMS AND CONDITIONS -================================================================================ -= vendor/github.com/ugorji/go/codec licensed under: = + APPENDIX: How to apply the Apache License to your work. -The MIT License (MIT) + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -Copyright (c) 2012-2015 Ugorji Nwoke. -All rights reserved. + Copyright [yyyy] [name of copyright owner] -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 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 -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + http://www.apache.org/licenses/LICENSE-2.0 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + 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. -= vendor/github.com/ugorji/go/LICENSE a03c0693c900925da5789db4e72da142 += vendor/github.com/vmware/govmomi/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/vishvananda/netlink licensed under: = += vendor/github.com/vmware/govmomi/find licensed under: = Apache License @@ -82466,8 +84973,18 @@ SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2014 Vishvananda Ishaya. - Copyright 2014 Docker, Inc. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -82481,12 +84998,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/vishvananda/netlink/LICENSE 2ade771c7d7211af507864e8dd520529 += vendor/github.com/vmware/govmomi/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/vishvananda/netlink/nl licensed under: = += vendor/github.com/vmware/govmomi/list licensed under: = Apache License @@ -82666,8 +85183,18 @@ SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2014 Vishvananda Ishaya. - Copyright 2014 Docker, Inc. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -82681,12 +85208,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/vishvananda/netlink/LICENSE 2ade771c7d7211af507864e8dd520529 += vendor/github.com/vmware/govmomi/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/vishvananda/netns licensed under: = += vendor/github.com/vmware/govmomi/lookup licensed under: = Apache License @@ -82866,8 +85393,18 @@ SOFTWARE. END OF TERMS AND CONDITIONS - Copyright 2014 Vishvananda Ishaya. - Copyright 2014 Docker, Inc. + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -82881,12 +85418,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/github.com/vishvananda/netns/LICENSE 2ade771c7d7211af507864e8dd520529 += vendor/github.com/vmware/govmomi/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/github.com/vmware/govmomi licensed under: = += vendor/github.com/vmware/govmomi/lookup/methods licensed under: = Apache License @@ -83096,7 +85633,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/find licensed under: = += vendor/github.com/vmware/govmomi/lookup/simulator licensed under: = Apache License @@ -83306,7 +85843,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/list licensed under: = += vendor/github.com/vmware/govmomi/lookup/types licensed under: = Apache License @@ -83726,7 +86263,217 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/object licensed under: = += vendor/github.com/vmware/govmomi/object licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + += vendor/github.com/vmware/govmomi/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/vmware/govmomi/pbm licensed under: = Apache License @@ -83936,7 +86683,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/pbm licensed under: = += vendor/github.com/vmware/govmomi/pbm/methods licensed under: = Apache License @@ -84146,7 +86893,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/pbm/methods licensed under: = += vendor/github.com/vmware/govmomi/pbm/types licensed under: = Apache License @@ -84356,7 +87103,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/pbm/types licensed under: = += vendor/github.com/vmware/govmomi/property licensed under: = Apache License @@ -84566,7 +87313,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/property licensed under: = += vendor/github.com/vmware/govmomi/session licensed under: = Apache License @@ -84776,7 +87523,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/session licensed under: = += vendor/github.com/vmware/govmomi/simulator licensed under: = Apache License @@ -84986,7 +87733,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/simulator licensed under: = += vendor/github.com/vmware/govmomi/simulator/esx licensed under: = Apache License @@ -85196,7 +87943,7 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/simulator/esx licensed under: = += vendor/github.com/vmware/govmomi/simulator/vpx licensed under: = Apache License @@ -85406,7 +88153,427 @@ SOFTWARE. ================================================================================ -= vendor/github.com/vmware/govmomi/simulator/vpx licensed under: = += vendor/github.com/vmware/govmomi/sts licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + += vendor/github.com/vmware/govmomi/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/vmware/govmomi/sts/internal licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + += vendor/github.com/vmware/govmomi/LICENSE.txt 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/vmware/govmomi/sts/simulator licensed under: = Apache License @@ -87991,246 +91158,147 @@ SOFTWARE. ================================================================================ -= vendor/github.com/xyproto/simpleredis licensed under: = - -The MIT License (MIT) += vendor/golang.org/x/crypto/bcrypt licensed under: = -Copyright (c) 2015 Alexander F Rødseth +Copyright (c) 2009 The Go Authors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -= vendor/github.com/xyproto/simpleredis/LICENSE d112c56a544c4ddeb3d863f7bdb3add6 += vendor/golang.org/x/crypto/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 ================================================================================ ================================================================================ -= vendor/go4.org/errorutil licensed under: = - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: += vendor/golang.org/x/crypto/blowfish licensed under: = - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and +Copyright (c) 2009 The Go Authors. All rights reserved. - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. += vendor/golang.org/x/crypto/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 +================================================================================ - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. +================================================================================ += vendor/golang.org/x/crypto/cryptobyte licensed under: = - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. +Copyright (c) 2009 The Go Authors. All rights reserved. - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. - END OF TERMS AND CONDITIONS +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - APPENDIX: How to apply the Apache License to your work. += vendor/golang.org/x/crypto/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 +================================================================================ - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - Copyright {yyyy} {name of copyright owner} +================================================================================ += vendor/golang.org/x/crypto/cryptobyte/asn1 licensed under: = - 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 +Copyright (c) 2009 The Go Authors. All rights reserved. - http://www.apache.org/licenses/LICENSE-2.0 +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: - 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. + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -= vendor/go4.org/LICENSE fa818a259cbed7ce8bc2a22d35a464fc += vendor/golang.org/x/crypto/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 ================================================================================ ================================================================================ -= vendor/golang.org/x/crypto/bcrypt licensed under: = += vendor/golang.org/x/crypto/curve25519 licensed under: = Copyright (c) 2009 The Go Authors. All rights reserved. @@ -88265,7 +91333,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/golang.org/x/crypto/blowfish licensed under: = += vendor/golang.org/x/crypto/ed25519 licensed under: = Copyright (c) 2009 The Go Authors. All rights reserved. @@ -88300,7 +91368,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/golang.org/x/crypto/curve25519 licensed under: = += vendor/golang.org/x/crypto/ed25519/internal/edwards25519 licensed under: = Copyright (c) 2009 The Go Authors. All rights reserved. @@ -88335,7 +91403,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/golang.org/x/crypto/ed25519 licensed under: = += vendor/golang.org/x/crypto/internal/chacha20 licensed under: = Copyright (c) 2009 The Go Authors. All rights reserved. @@ -88370,7 +91438,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/golang.org/x/crypto/ed25519/internal/edwards25519 licensed under: = += vendor/golang.org/x/crypto/nacl/secretbox licensed under: = Copyright (c) 2009 The Go Authors. All rights reserved. @@ -88405,7 +91473,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/golang.org/x/crypto/nacl/secretbox licensed under: = += vendor/golang.org/x/crypto/ocsp licensed under: = Copyright (c) 2009 The Go Authors. All rights reserved. @@ -90154,41 +93222,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -================================================================================ -= vendor/google.golang.org/api/cloudmonitoring/v2beta2 licensed under: = - -Copyright (c) 2011 Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/google.golang.org/api/LICENSE a651bb3d8b1c412632e28823bb432b40 -================================================================================ - - ================================================================================ = vendor/google.golang.org/api/compute/v0.alpha licensed under: = @@ -90540,7 +93573,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -= vendor/google.golang.org/api/tpu/v1alpha1 licensed under: = += vendor/google.golang.org/api/tpu/v1 licensed under: = Copyright (c) 2011 Google Inc. All rights reserved. @@ -92044,216 +95077,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ -================================================================================ -= vendor/google.golang.org/grpc/grpclb/grpc_lb_v1 licensed under: = - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - -= vendor/google.golang.org/grpc/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 -================================================================================ - - ================================================================================ = vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/messages licensed under: = @@ -95403,7 +98226,217 @@ SOFTWARE. ================================================================================ -= vendor/gopkg.in/square/go-jose.v2/cipher licensed under: = += vendor/gopkg.in/square/go-jose.v2/cipher licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + += vendor/gopkg.in/square/go-jose.v2/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/gopkg.in/square/go-jose.v2/json licensed under: = Apache License @@ -95613,7 +98646,7 @@ SOFTWARE. ================================================================================ -= vendor/gopkg.in/square/go-jose.v2/json licensed under: = += vendor/gopkg.in/square/go-jose.v2/jwt licensed under: = Apache License @@ -95823,7 +98856,270 @@ SOFTWARE. ================================================================================ -= vendor/gopkg.in/square/go-jose.v2/jwt licensed under: = += vendor/gopkg.in/warnings.v0 licensed under: = + +Copyright (c) 2016 Péter Surányi. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/gopkg.in/warnings.v0/LICENSE c6775875c9d604beb22447dfae3d7049 +================================================================================ + + +================================================================================ += vendor/gopkg.in/yaml.v2 licensed under: = + +Copyright 2011-2016 Canonical Ltd. + +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. + += vendor/gopkg.in/yaml.v2/LICENSE 6964839e54f4fefcdae13f22b92d0fbb +================================================================================ + + +================================================================================ += vendor/k8s.io/gengo/args licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + 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. + += vendor/k8s.io/gengo/LICENSE ad09685d909e7a9f763d2bb62d4bd6fb +================================================================================ + + +================================================================================ += vendor/k8s.io/gengo/examples/deepcopy-gen/generators licensed under: = Apache License @@ -96014,7 +99310,7 @@ SOFTWARE. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + 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. @@ -96028,65 +99324,12 @@ SOFTWARE. See the License for the specific language governing permissions and limitations under the License. -= vendor/gopkg.in/square/go-jose.v2/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 -================================================================================ - - -================================================================================ -= vendor/gopkg.in/warnings.v0 licensed under: = - -Copyright (c) 2016 Péter Surányi. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -= vendor/gopkg.in/warnings.v0/LICENSE c6775875c9d604beb22447dfae3d7049 -================================================================================ - - -================================================================================ -= vendor/gopkg.in/yaml.v2 licensed under: = - -Copyright 2011-2016 Canonical Ltd. - -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. - -= vendor/gopkg.in/yaml.v2/LICENSE 6964839e54f4fefcdae13f22b92d0fbb += vendor/k8s.io/gengo/LICENSE ad09685d909e7a9f763d2bb62d4bd6fb ================================================================================ ================================================================================ -= vendor/k8s.io/gengo/args licensed under: = += vendor/k8s.io/gengo/examples/defaulter-gen/generators licensed under: = Apache License @@ -96296,7 +99539,7 @@ limitations under the License. ================================================================================ -= vendor/k8s.io/gengo/examples/deepcopy-gen/generators licensed under: = += vendor/k8s.io/gengo/examples/import-boss/generators licensed under: = Apache License @@ -96506,7 +99749,7 @@ limitations under the License. ================================================================================ -= vendor/k8s.io/gengo/examples/defaulter-gen/generators licensed under: = += vendor/k8s.io/gengo/examples/set-gen/generators licensed under: = Apache License @@ -96716,7 +99959,7 @@ limitations under the License. ================================================================================ -= vendor/k8s.io/gengo/examples/import-boss/generators licensed under: = += vendor/k8s.io/gengo/examples/set-gen/sets licensed under: = Apache License @@ -96926,7 +100169,7 @@ limitations under the License. ================================================================================ -= vendor/k8s.io/gengo/examples/set-gen/generators licensed under: = += vendor/k8s.io/gengo/generator licensed under: = Apache License @@ -97136,7 +100379,7 @@ limitations under the License. ================================================================================ -= vendor/k8s.io/gengo/examples/set-gen/sets licensed under: = += vendor/k8s.io/gengo/namer licensed under: = Apache License @@ -97346,7 +100589,7 @@ limitations under the License. ================================================================================ -= vendor/k8s.io/gengo/generator licensed under: = += vendor/k8s.io/gengo/parser licensed under: = Apache License @@ -97556,7 +100799,7 @@ limitations under the License. ================================================================================ -= vendor/k8s.io/gengo/namer licensed under: = += vendor/k8s.io/gengo/types licensed under: = Apache License @@ -97766,10 +101009,9 @@ limitations under the License. ================================================================================ -= vendor/k8s.io/gengo/parser licensed under: = - += vendor/k8s.io/heapster/metrics/api/v1/types licensed under: = - Apache License +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -97949,7 +101191,7 @@ limitations under the License. APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -97957,7 +101199,7 @@ limitations under the License. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2014 The Kubernetes Authors. + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -97971,12 +101213,12 @@ limitations under the License. See the License for the specific language governing permissions and limitations under the License. -= vendor/k8s.io/gengo/LICENSE ad09685d909e7a9f763d2bb62d4bd6fb += vendor/k8s.io/heapster/LICENSE 136e4f49dbf29942c572a3a8f6e88a77 ================================================================================ ================================================================================ -= vendor/k8s.io/gengo/types licensed under: = += vendor/k8s.io/kube-openapi/pkg/aggregator licensed under: = Apache License @@ -98167,216 +101409,7 @@ limitations under the License. same "printed page" as the copyright notice for easier identification within third-party archives. - 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. - -= vendor/k8s.io/gengo/LICENSE ad09685d909e7a9f763d2bb62d4bd6fb -================================================================================ - - -================================================================================ -= vendor/k8s.io/heapster/metrics/api/v1/types licensed under: = - -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -98390,12 +101423,12 @@ Apache License See the License for the specific language governing permissions and limitations under the License. -= vendor/k8s.io/heapster/LICENSE 136e4f49dbf29942c572a3a8f6e88a77 += vendor/k8s.io/kube-openapi/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 ================================================================================ ================================================================================ -= vendor/k8s.io/kube-openapi/pkg/aggregator licensed under: = += vendor/k8s.io/kube-openapi/pkg/builder licensed under: = Apache License @@ -98605,7 +101638,7 @@ Apache License ================================================================================ -= vendor/k8s.io/kube-openapi/pkg/builder licensed under: = += vendor/k8s.io/kube-openapi/pkg/common licensed under: = Apache License @@ -98815,7 +101848,7 @@ Apache License ================================================================================ -= vendor/k8s.io/kube-openapi/pkg/common licensed under: = += vendor/k8s.io/kube-openapi/pkg/generators licensed under: = Apache License @@ -99025,7 +102058,7 @@ Apache License ================================================================================ -= vendor/k8s.io/kube-openapi/pkg/generators licensed under: = += vendor/k8s.io/kube-openapi/pkg/handler licensed under: = Apache License @@ -99235,7 +102268,7 @@ Apache License ================================================================================ -= vendor/k8s.io/kube-openapi/pkg/handler licensed under: = += vendor/k8s.io/kube-openapi/pkg/util licensed under: = Apache License @@ -99445,7 +102478,7 @@ Apache License ================================================================================ -= vendor/k8s.io/kube-openapi/pkg/util licensed under: = += vendor/k8s.io/kube-openapi/pkg/util/proto licensed under: = Apache License @@ -99655,7 +102688,7 @@ Apache License ================================================================================ -= vendor/k8s.io/kube-openapi/pkg/util/proto licensed under: = += vendor/k8s.io/kube-openapi/pkg/util/proto/testing licensed under: = Apache License diff --git a/vendor/k8s.io/kubernetes/OWNERS b/vendor/k8s.io/kubernetes/OWNERS index ec80d280a..822c0893e 100644 --- a/vendor/k8s.io/kubernetes/OWNERS +++ b/vendor/k8s.io/kubernetes/OWNERS @@ -1,17 +1,29 @@ -reviewers: - - brendandburns - - dchen1107 - - jbeda - - lavalamp - - smarterclayton - - thockin -approvers: - - bgrant0607 - - brendandburns - - dchen1107 - - jbeda - - monopole # To move code per kubernetes/community#598 - - lavalamp - - smarterclayton - - thockin - - wojtek-t +filters: + ".*": + reviewers: + - brendandburns + - dchen1107 + - jbeda + - lavalamp + - smarterclayton + - thockin + approvers: + - bgrant0607 + - brendandburns + - dchen1107 + - jbeda + - monopole # To move code per kubernetes/community#598 + - lavalamp + - smarterclayton + - thockin + - wojtek-t + + # Bazel build infrastructure changes often touch files throughout the tree + "\\.bzl$": + reviewers: + - ixdy + approvers: + - ixdy + "BUILD(\\.bazel)?$": + approvers: + - ixdy diff --git a/vendor/k8s.io/kubernetes/OWNERS_ALIASES b/vendor/k8s.io/kubernetes/OWNERS_ALIASES index 961a838d9..2a3074fef 100644 --- a/vendor/k8s.io/kubernetes/OWNERS_ALIASES +++ b/vendor/k8s.io/kubernetes/OWNERS_ALIASES @@ -5,6 +5,7 @@ aliases: - k82cn - timothysc - wojtek-t + - aveshagarwal sig-scheduling: - bsalamat - davidopp @@ -21,23 +22,29 @@ aliases: - deads2k - janetkuo - liggitt - - pwittrock + - seans3 + - monopole + - droot + - apelisse + - mengqiy - smarterclayton + - soltysh sig-cli: - adohe - deads2k - derekwaynecarr + - dixudx - dims - dshulyak - eparis - ericchiang - ghodss + - juanvallejo - mengqiy - rootfs - shiywang - smarterclayton - soltysh - - sttts sig-testing-reviewers: - fejta - ixdy @@ -85,6 +92,7 @@ aliases: - mrhohn - nicksardo - thockin + - rramkumar1 sig-apps-reviewers: - enisoc - erictune @@ -125,7 +133,6 @@ aliases: - slack - colemickens - foxish - - pwittrock - AdoHe - lukemarsden - jbeda @@ -153,7 +160,6 @@ aliases: - apsinha - idvoretskyi - calebamiles - - pwittrock - calebamiles - wojtek-t - countspongebob @@ -180,6 +186,7 @@ aliases: - cmluciano - bsalamat - m1093782566 + - tallclair api-approvers: - erictune - lavalamp @@ -228,3 +235,42 @@ aliases: - cblecker - thockin - sttts + feature-approvers: + - AdoHe # CLI + - bgrant0607 # Architecture + - brancz # Instrumentation + - bsalamat # Scheduling + - calebamiles # Release + - caseydavenport # Network + - childsb # Storage + - countspongebob # Scalability + - csbell # Multicluster + - dcbw # Network + - dchen1107 # Node + - deads2k # API Machinery + - derekwaynecarr # Node + - dghubble # On Premise + - directxman12 # Autoscaling + - ericchiang # Auth + - jdumars # Architecture, Cluster Ops, Release + - kow3ns # Apps + - lavalamp # API Machinery + - liggitt # Auth + - lukemarsden # Cluster Lifecycle + - luxas # Cluster Lifecycle + - marcoceppi # On Premise + - mattfarina # Apps + - michmike # Windows + - mwielgus # Autoscaling + - piosz # Instrumentation + - prydonius # Apps + - pwittrock # CLI + - quinton-hoole # Multicluster + - roberthbailey # Cluster Lifecycle + - saad-ali # Storage + - soltysh # CLI + - tallclair # Auth + - thockin # Network + - timothysc # Cluster Lifecycle, Scheduling + - wojtek-t # Scalability + - zehicle # Cluster Ops diff --git a/vendor/k8s.io/kubernetes/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/api/BUILD b/vendor/k8s.io/kubernetes/api/BUILD deleted file mode 100644 index fe152d74d..000000000 --- a/vendor/k8s.io/kubernetes/api/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//api/openapi-spec:all-srcs", - "//api/swagger-spec:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/api/openapi-spec/swagger.json b/vendor/k8s.io/kubernetes/api/openapi-spec/swagger.json index de49c3669..139ce817a 100644 --- a/vendor/k8s.io/kubernetes/api/openapi-spec/swagger.json +++ b/vendor/k8s.io/kubernetes/api/openapi-spec/swagger.json @@ -2,7 +2,7 @@ "swagger": "2.0", "info": { "title": "Kubernetes", - "version": "v1.10.4" + "version": "v1.11.3" }, "paths": { "/api/": { @@ -20060,6 +20060,41 @@ ] }, "/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/{name}/status": { + "get": { + "description": "read status of the specified CustomResourceDefinition", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "apiextensions_v1beta1" + ], + "operationId": "readApiextensionsV1beta1CustomResourceDefinitionStatus", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "apiextensions.k8s.io", + "kind": "CustomResourceDefinition", + "version": "v1beta1" + } + }, "put": { "description": "replace status of the specified CustomResourceDefinition", "consumes": [ @@ -20111,6 +20146,53 @@ "version": "v1beta1" } }, + "patch": { + "description": "partially update status of the specified CustomResourceDefinition", + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "apiextensions_v1beta1" + ], + "operationId": "patchApiextensionsV1beta1CustomResourceDefinitionStatus", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "apiextensions.k8s.io", + "kind": "CustomResourceDefinition", + "version": "v1beta1" + } + }, "parameters": [ { "uniqueItems": true, @@ -20902,6 +20984,41 @@ ] }, "/apis/apiregistration.k8s.io/v1/apiservices/{name}/status": { + "get": { + "description": "read status of the specified APIService", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "apiregistration_v1" + ], + "operationId": "readApiregistrationV1APIServiceStatus", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "apiregistration.k8s.io", + "kind": "APIService", + "version": "v1" + } + }, "put": { "description": "replace status of the specified APIService", "consumes": [ @@ -20953,6 +21070,53 @@ "version": "v1" } }, + "patch": { + "description": "partially update status of the specified APIService", + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "apiregistration_v1" + ], + "operationId": "patchApiregistrationV1APIServiceStatus", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIService" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "apiregistration.k8s.io", + "kind": "APIService", + "version": "v1" + } + }, "parameters": [ { "uniqueItems": true, @@ -21711,6 +21875,41 @@ ] }, "/apis/apiregistration.k8s.io/v1beta1/apiservices/{name}/status": { + "get": { + "description": "read status of the specified APIService", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "apiregistration_v1beta1" + ], + "operationId": "readApiregistrationV1beta1APIServiceStatus", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIService" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "apiregistration.k8s.io", + "kind": "APIService", + "version": "v1beta1" + } + }, "put": { "description": "replace status of the specified APIService", "consumes": [ @@ -21762,6 +21961,53 @@ "version": "v1beta1" } }, + "patch": { + "description": "partially update status of the specified APIService", + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "apiregistration_v1beta1" + ], + "operationId": "patchApiregistrationV1beta1APIServiceStatus", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIService" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "apiregistration.k8s.io", + "kind": "APIService", + "version": "v1beta1" + } + }, "parameters": [ { "uniqueItems": true, @@ -44672,6 +44918,41 @@ ] }, "/apis/certificates.k8s.io/v1beta1/certificatesigningrequests/{name}/status": { + "get": { + "description": "read status of the specified CertificateSigningRequest", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "certificates_v1beta1" + ], + "operationId": "readCertificatesV1beta1CertificateSigningRequestStatus", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.certificates.v1beta1.CertificateSigningRequest" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "certificates.k8s.io", + "kind": "CertificateSigningRequest", + "version": "v1beta1" + } + }, "put": { "description": "replace status of the specified CertificateSigningRequest", "consumes": [ @@ -44723,6 +45004,53 @@ "version": "v1beta1" } }, + "patch": { + "description": "partially update status of the specified CertificateSigningRequest", + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "certificates_v1beta1" + ], + "operationId": "patchCertificatesV1beta1CertificateSigningRequestStatus", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.certificates.v1beta1.CertificateSigningRequest" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "certificates.k8s.io", + "kind": "CertificateSigningRequest", + "version": "v1beta1" + } + }, "parameters": [ { "uniqueItems": true, @@ -66189,40 +66517,7 @@ } ] }, - "/apis/settings.k8s.io/": { - "get": { - "description": "get information of a group", - "consumes": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "schemes": [ - "https" - ], - "tags": [ - "settings" - ], - "operationId": "getSettingsAPIGroup", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup" - } - }, - "401": { - "description": "Unauthorized" - } - } - } - }, - "/apis/settings.k8s.io/v1alpha1/": { + "/apis/scheduling.k8s.io/v1beta1/": { "get": { "description": "get available resources", "consumes": [ @@ -66239,9 +66534,9 @@ "https" ], "tags": [ - "settings_v1alpha1" + "scheduling_v1beta1" ], - "operationId": "getSettingsV1alpha1APIResources", + "operationId": "getSchedulingV1beta1APIResources", "responses": { "200": { "description": "OK", @@ -66255,9 +66550,9 @@ } } }, - "/apis/settings.k8s.io/v1alpha1/namespaces/{namespace}/podpresets": { + "/apis/scheduling.k8s.io/v1beta1/priorityclasses": { "get": { - "description": "list or watch objects of kind PodPreset", + "description": "list or watch objects of kind PriorityClass", "consumes": [ "*/*" ], @@ -66272,9 +66567,9 @@ "https" ], "tags": [ - "settings_v1alpha1" + "scheduling_v1beta1" ], - "operationId": "listSettingsV1alpha1NamespacedPodPreset", + "operationId": "listSchedulingV1beta1PriorityClass", "parameters": [ { "uniqueItems": true, @@ -66337,7 +66632,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPresetList" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClassList" } }, "401": { @@ -66346,13 +66641,13 @@ }, "x-kubernetes-action": "list", "x-kubernetes-group-version-kind": { - "group": "settings.k8s.io", - "kind": "PodPreset", - "version": "v1alpha1" + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" } }, "post": { - "description": "create a PodPreset", + "description": "create a PriorityClass", "consumes": [ "*/*" ], @@ -66365,16 +66660,16 @@ "https" ], "tags": [ - "settings_v1alpha1" + "scheduling_v1beta1" ], - "operationId": "createSettingsV1alpha1NamespacedPodPreset", + "operationId": "createSchedulingV1beta1PriorityClass", "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" } } ], @@ -66382,19 +66677,19 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" } }, "201": { "description": "Created", "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" } }, "202": { "description": "Accepted", "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" } }, "401": { @@ -66403,13 +66698,13 @@ }, "x-kubernetes-action": "post", "x-kubernetes-group-version-kind": { - "group": "settings.k8s.io", - "kind": "PodPreset", - "version": "v1alpha1" + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" } }, "delete": { - "description": "delete collection of PodPreset", + "description": "delete collection of PriorityClass", "consumes": [ "*/*" ], @@ -66422,9 +66717,9 @@ "https" ], "tags": [ - "settings_v1alpha1" + "scheduling_v1beta1" ], - "operationId": "deleteSettingsV1alpha1CollectionNamespacedPodPreset", + "operationId": "deleteSchedulingV1beta1CollectionPriorityClass", "parameters": [ { "uniqueItems": true, @@ -66496,20 +66791,12 @@ }, "x-kubernetes-action": "deletecollection", "x-kubernetes-group-version-kind": { - "group": "settings.k8s.io", - "kind": "PodPreset", - "version": "v1alpha1" + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" } }, "parameters": [ - { - "uniqueItems": true, - "type": "string", - "description": "object name and auth scope, such as for teams and projects", - "name": "namespace", - "in": "path", - "required": true - }, { "uniqueItems": true, "type": "string", @@ -66519,9 +66806,9 @@ } ] }, - "/apis/settings.k8s.io/v1alpha1/namespaces/{namespace}/podpresets/{name}": { + "/apis/scheduling.k8s.io/v1beta1/priorityclasses/{name}": { "get": { - "description": "read the specified PodPreset", + "description": "read the specified PriorityClass", "consumes": [ "*/*" ], @@ -66534,9 +66821,9 @@ "https" ], "tags": [ - "settings_v1alpha1" + "scheduling_v1beta1" ], - "operationId": "readSettingsV1alpha1NamespacedPodPreset", + "operationId": "readSchedulingV1beta1PriorityClass", "parameters": [ { "uniqueItems": true, @@ -66557,7 +66844,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" } }, "401": { @@ -66566,13 +66853,13 @@ }, "x-kubernetes-action": "get", "x-kubernetes-group-version-kind": { - "group": "settings.k8s.io", - "kind": "PodPreset", - "version": "v1alpha1" + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" } }, "put": { - "description": "replace the specified PodPreset", + "description": "replace the specified PriorityClass", "consumes": [ "*/*" ], @@ -66585,16 +66872,16 @@ "https" ], "tags": [ - "settings_v1alpha1" + "scheduling_v1beta1" ], - "operationId": "replaceSettingsV1alpha1NamespacedPodPreset", + "operationId": "replaceSchedulingV1beta1PriorityClass", "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" } } ], @@ -66602,13 +66889,13 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" } }, "201": { "description": "Created", "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" } }, "401": { @@ -66617,13 +66904,13 @@ }, "x-kubernetes-action": "put", "x-kubernetes-group-version-kind": { - "group": "settings.k8s.io", - "kind": "PodPreset", - "version": "v1alpha1" + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" } }, "delete": { - "description": "delete a PodPreset", + "description": "delete a PriorityClass", "consumes": [ "*/*" ], @@ -66636,9 +66923,9 @@ "https" ], "tags": [ - "settings_v1alpha1" + "scheduling_v1beta1" ], - "operationId": "deleteSettingsV1alpha1NamespacedPodPreset", + "operationId": "deleteSchedulingV1beta1PriorityClass", "parameters": [ { "name": "body", @@ -66683,13 +66970,13 @@ }, "x-kubernetes-action": "delete", "x-kubernetes-group-version-kind": { - "group": "settings.k8s.io", - "kind": "PodPreset", - "version": "v1alpha1" + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" } }, "patch": { - "description": "partially update the specified PodPreset", + "description": "partially update the specified PriorityClass", "consumes": [ "application/json-patch+json", "application/merge-patch+json", @@ -66704,9 +66991,9 @@ "https" ], "tags": [ - "settings_v1alpha1" + "scheduling_v1beta1" ], - "operationId": "patchSettingsV1alpha1NamespacedPodPreset", + "operationId": "patchSchedulingV1beta1PriorityClass", "parameters": [ { "name": "body", @@ -66721,7 +67008,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" } }, "401": { @@ -66730,16 +67017,16 @@ }, "x-kubernetes-action": "patch", "x-kubernetes-group-version-kind": { - "group": "settings.k8s.io", - "kind": "PodPreset", - "version": "v1alpha1" + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" } }, "parameters": [ { "uniqueItems": true, "type": "string", - "description": "name of the PodPreset", + "description": "name of the PriorityClass", "name": "name", "in": "path", "required": true @@ -66747,10 +67034,85 @@ { "uniqueItems": true, "type": "string", - "description": "object name and auth scope, such as for teams and projects", - "name": "namespace", - "in": "path", - "required": true + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + } + ] + }, + "/apis/scheduling.k8s.io/v1beta1/watch/priorityclasses": { + "get": { + "description": "watch individual changes to a list of PriorityClass", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "scheduling_v1beta1" + ], + "operationId": "watchSchedulingV1beta1PriorityClassList", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "If true, partially initialized resources are included in the response.", + "name": "includeUninitialized", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" }, { "uniqueItems": true, @@ -66758,12 +67120,33 @@ "description": "If 'true', then the output is pretty printed.", "name": "pretty", "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" } ] }, - "/apis/settings.k8s.io/v1alpha1/podpresets": { + "/apis/scheduling.k8s.io/v1beta1/watch/priorityclasses/{name}": { "get": { - "description": "list or watch objects of kind PodPreset", + "description": "watch changes to an object of kind PriorityClass", "consumes": [ "*/*" ], @@ -66778,25 +67161,709 @@ "https" ], "tags": [ - "settings_v1alpha1" + "scheduling_v1beta1" ], - "operationId": "listSettingsV1alpha1PodPresetForAllNamespaces", + "operationId": "watchSchedulingV1beta1PriorityClass", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPresetList" + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" } }, "401": { "description": "Unauthorized" } }, - "x-kubernetes-action": "list", + "x-kubernetes-action": "watch", "x-kubernetes-group-version-kind": { - "group": "settings.k8s.io", - "kind": "PodPreset", - "version": "v1alpha1" + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "If true, partially initialized resources are included in the response.", + "name": "includeUninitialized", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "name of the PriorityClass", + "name": "name", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" + } + ] + }, + "/apis/settings.k8s.io/": { + "get": { + "description": "get information of a group", + "consumes": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings" + ], + "operationId": "getSettingsAPIGroup", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup" + } + }, + "401": { + "description": "Unauthorized" + } + } + } + }, + "/apis/settings.k8s.io/v1alpha1/": { + "get": { + "description": "get available resources", + "consumes": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings_v1alpha1" + ], + "operationId": "getSettingsV1alpha1APIResources", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList" + } + }, + "401": { + "description": "Unauthorized" + } + } + } + }, + "/apis/settings.k8s.io/v1alpha1/namespaces/{namespace}/podpresets": { + "get": { + "description": "list or watch objects of kind PodPreset", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings_v1alpha1" + ], + "operationId": "listSettingsV1alpha1NamespacedPodPreset", + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "If true, partially initialized resources are included in the response.", + "name": "includeUninitialized", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPresetList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "settings.k8s.io", + "kind": "PodPreset", + "version": "v1alpha1" + } + }, + "post": { + "description": "create a PodPreset", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings_v1alpha1" + ], + "operationId": "createSettingsV1alpha1NamespacedPodPreset", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "settings.k8s.io", + "kind": "PodPreset", + "version": "v1alpha1" + } + }, + "delete": { + "description": "delete collection of PodPreset", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings_v1alpha1" + ], + "operationId": "deleteSettingsV1alpha1CollectionNamespacedPodPreset", + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "If true, partially initialized resources are included in the response.", + "name": "includeUninitialized", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "settings.k8s.io", + "kind": "PodPreset", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "object name and auth scope, such as for teams and projects", + "name": "namespace", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + } + ] + }, + "/apis/settings.k8s.io/v1alpha1/namespaces/{namespace}/podpresets/{name}": { + "get": { + "description": "read the specified PodPreset", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings_v1alpha1" + ], + "operationId": "readSettingsV1alpha1NamespacedPodPreset", + "parameters": [ + { + "uniqueItems": true, + "type": "boolean", + "description": "Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'.", + "name": "exact", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Should this value be exported. Export strips fields that a user can not specify.", + "name": "export", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "settings.k8s.io", + "kind": "PodPreset", + "version": "v1alpha1" + } + }, + "put": { + "description": "replace the specified PodPreset", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings_v1alpha1" + ], + "operationId": "replaceSettingsV1alpha1NamespacedPodPreset", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "settings.k8s.io", + "kind": "PodPreset", + "version": "v1alpha1" + } + }, + "delete": { + "description": "delete a PodPreset", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings_v1alpha1" + ], + "operationId": "deleteSettingsV1alpha1NamespacedPodPreset", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "uniqueItems": true, + "type": "integer", + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "name": "gracePeriodSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "name": "orphanDependents", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "name": "propagationPolicy", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "settings.k8s.io", + "kind": "PodPreset", + "version": "v1alpha1" + } + }, + "patch": { + "description": "partially update the specified PodPreset", + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings_v1alpha1" + ], + "operationId": "patchSettingsV1alpha1NamespacedPodPreset", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPreset" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "settings.k8s.io", + "kind": "PodPreset", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "name of the PodPreset", + "name": "name", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "object name and auth scope, such as for teams and projects", + "name": "namespace", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + } + ] + }, + "/apis/settings.k8s.io/v1alpha1/podpresets": { + "get": { + "description": "list or watch objects of kind PodPreset", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "settings_v1alpha1" + ], + "operationId": "listSettingsV1alpha1PodPresetForAllNamespaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.settings.v1alpha1.PodPresetList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "settings.k8s.io", + "kind": "PodPreset", + "version": "v1alpha1" } }, "parameters": [ @@ -70574,7 +71641,7 @@ "format": "byte" }, "service": { - "description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nIf there is only one port open for the service, that port will be used. If there are multiple ports open, port 443 will be used if it is open, otherwise it is an error.", + "description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nPort 443 will be used if it is open, otherwise it is an error.", "$ref": "#/definitions/io.k8s.api.admissionregistration.v1beta1.ServiceReference" }, "url": { @@ -71239,11 +72306,11 @@ "description": "Spec to control the desired behavior of rolling update.", "properties": { "maxSurge": { - "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.", + "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" }, "maxUnavailable": { - "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" } } @@ -71797,11 +72864,11 @@ "description": "Spec to control the desired behavior of rolling update.", "properties": { "maxSurge": { - "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", + "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" }, "maxUnavailable": { - "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" } } @@ -72744,11 +73811,11 @@ "description": "Spec to control the desired behavior of rolling update.", "properties": { "maxSurge": { - "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", + "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" }, "maxUnavailable": { - "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" } } @@ -75326,7 +76393,7 @@ "type": "string" }, "fsType": { - "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\".", "type": "string" }, "nodePublishSecretRef": { @@ -75443,6 +76510,30 @@ } } }, + "io.k8s.api.core.v1.CinderPersistentVolumeSource": { + "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "required": [ + "volumeID" + ], + "properties": { + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "string" + }, + "readOnly": { + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "boolean" + }, + "secretRef": { + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack.", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretReference" + }, + "volumeID": { + "description": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "type": "string" + } + } + }, "io.k8s.api.core.v1.CinderVolumeSource": { "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", "required": [ @@ -75457,6 +76548,10 @@ "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", "type": "boolean" }, + "secretRef": { + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack.", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, "volumeID": { "description": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", "type": "string" @@ -75671,6 +76766,36 @@ } ] }, + "io.k8s.api.core.v1.ConfigMapNodeConfigSource": { + "description": "ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.", + "required": [ + "namespace", + "name", + "kubeletConfigKey" + ], + "properties": { + "kubeletConfigKey": { + "description": "KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure This field is required in all cases.", + "type": "string" + }, + "name": { + "description": "Name is the metadata.name of the referenced ConfigMap. This field is required in all cases.", + "type": "string" + }, + "namespace": { + "description": "Namespace is the metadata.namespace of the referenced ConfigMap. This field is required in all cases.", + "type": "string" + }, + "resourceVersion": { + "description": "ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status.", + "type": "string" + }, + "uid": { + "description": "UID is the metadata.UID of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status.", + "type": "string" + } + } + }, "io.k8s.api.core.v1.ConfigMapProjection": { "description": "Adapts a ConfigMap into a projected volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a projected volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. Note that this is identical to a configmap volume source without the default mode.", "properties": { @@ -76578,7 +77703,7 @@ } }, "io.k8s.api.core.v1.GitRepoVolumeSource": { - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -77022,13 +78147,13 @@ } }, "io.k8s.api.core.v1.LocalVolumeSource": { - "description": "Local represents directly-attached storage with node affinity", + "description": "Local represents directly-attached storage with node affinity (Beta feature)", "required": [ "path" ], "properties": { "path": { - "description": "The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device", + "description": "The full path to the volume on the node. It can be either a directory or block device (disk, partition, ...). Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. Block devices can be represented only by VolumeMode=Block, which also requires the BlockVolume alpha feature gate to be enabled.", "type": "string" } } @@ -77242,25 +78367,32 @@ "io.k8s.api.core.v1.NodeConfigSource": { "description": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.", "properties": { - "apiVersion": { - "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", - "type": "string" + "configMap": { + "description": "ConfigMap is a reference to a Node's ConfigMap", + "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapNodeConfigSource" + } + } + }, + "io.k8s.api.core.v1.NodeConfigStatus": { + "description": "NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource.", + "properties": { + "active": { + "description": "Active reports the checkpointed config the node is actively using. Active will represent either the current version of the Assigned config, or the current LastKnownGood config, depending on whether attempting to use the Assigned config results in an error.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource" }, - "configMapRef": { - "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" + "assigned": { + "description": "Assigned reports the checkpointed config the node will try to use. When Node.Spec.ConfigSource is updated, the node checkpoints the associated config payload to local disk, along with a record indicating intended config. The node refers to this record to choose its config checkpoint, and reports this record in Assigned. Assigned only updates in the status after the record has been checkpointed to disk. When the Kubelet is restarted, it tries to make the Assigned config the Active config by loading and validating the checkpointed payload identified by Assigned.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource" }, - "kind": { - "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "error": { + "description": "Error describes any problems reconciling the Spec.ConfigSource to the Active config. Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting to load or validate the Assigned config, etc. Errors may occur at different points while syncing config. Earlier errors (e.g. download or checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error by fixing the config assigned in Spec.ConfigSource. You can find additional information for debugging by searching the error message in the Kubelet log. Error is a human-readable description of the error state; machines can check whether or not Error is empty, but should not rely on the stability of the Error text across Kubelet versions.", "type": "string" + }, + "lastKnownGood": { + "description": "LastKnownGood reports the checkpointed config the node will fall back to when it encounters an error attempting to use the Assigned config. The Assigned config becomes the LastKnownGood config when the node determines that the Assigned config is stable and correct. This is currently implemented as a 10-minute soak period starting when the local record of Assigned config is updated. If the Assigned config is Active at the end of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, because the local default config is always assumed good. You should not make assumptions about the node's method of determining config stability and correctness, as this may change or become configurable in the future.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource" } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "", - "kind": "NodeConfigSource", - "version": "v1" - } - ] + } }, "io.k8s.api.core.v1.NodeDaemonEndpoints": { "description": "NodeDaemonEndpoints lists ports opened by daemons running on the Node.", @@ -77345,13 +78477,17 @@ } }, "io.k8s.api.core.v1.NodeSelectorTerm": { - "description": "A null or empty node selector term matches no objects.", - "required": [ - "matchExpressions" - ], + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { - "description": "Required. A list of node selector requirements. The requirements are ANDed.", + "description": "A list of node selector requirements by node's labels.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelectorRequirement" + } + }, + "matchFields": { + "description": "A list of node selector requirements by node's fields.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelectorRequirement" @@ -77367,7 +78503,7 @@ "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource" }, "externalID": { - "description": "External ID of the node assigned by some machine database (e.g. a cloud provider). Deprecated.", + "description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966", "type": "string" }, "podCIDR": { @@ -77426,6 +78562,10 @@ "x-kubernetes-patch-merge-key": "type", "x-kubernetes-patch-strategy": "merge" }, + "config": { + "description": "Status of the config assigned to the node via the dynamic Kubelet config feature.", + "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigStatus" + }, "daemonEndpoints": { "description": "Endpoints of daemons running on the Node.", "$ref": "#/definitions/io.k8s.api.core.v1.NodeDaemonEndpoints" @@ -77845,7 +78985,7 @@ }, "cinder": { "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - "$ref": "#/definitions/io.k8s.api.core.v1.CinderVolumeSource" + "$ref": "#/definitions/io.k8s.api.core.v1.CinderPersistentVolumeSource" }, "claimRef": { "description": "ClaimRef is part of a bi-directional binding between PersistentVolume and PersistentVolumeClaim. Expected to be non-nil when bound. claim.VolumeName is the authoritative bind between PV and PVC. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#binding", @@ -78098,7 +79238,7 @@ "type": "string" }, "type": { - "description": "Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "description": "Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "type": "string" } } @@ -78175,6 +79315,18 @@ } ] }, + "io.k8s.api.core.v1.PodReadinessGate": { + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "description": "ConditionType refers to a condition in the pod's condition list with matching type.", + "type": "string" + } + } + }, "io.k8s.api.core.v1.PodSecurityContext": { "description": "PodSecurityContext holds pod-level security attributes and common container settings. Some fields are also present in container.securityContext. Field values of container.securityContext take precedence over field values of PodSecurityContext.", "properties": { @@ -78208,6 +79360,13 @@ "type": "integer", "format": "int64" } + }, + "sysctls": { + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.Sysctl" + } } } }, @@ -78310,6 +79469,13 @@ "description": "If specified, indicates the pod's priority. \"system-node-critical\" and \"system-cluster-critical\" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.", "type": "string" }, + "readinessGates": { + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodReadinessGate" + } + }, "restartPolicy": { "description": "Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy", "type": "string" @@ -78362,7 +79528,7 @@ } }, "io.k8s.api.core.v1.PodStatus": { - "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system.", + "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system, especially if the node that hosts the pod cannot contact the control plane.", "properties": { "conditions": { "description": "Current service state of pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", @@ -78400,7 +79566,7 @@ "type": "string" }, "phase": { - "description": "Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", + "description": "The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod's status. There are five possible phase values:\n\nPending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.\n\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", "type": "string" }, "podIP": { @@ -78966,12 +80132,16 @@ "description": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", "properties": { "hard": { - "description": "Hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", + "description": "hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", "type": "object", "additionalProperties": { "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" } }, + "scopeSelector": { + "description": "scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota but expressed using ScopeSelectorOperator in combination with possible values. For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched.", + "$ref": "#/definitions/io.k8s.api.core.v1.ScopeSelector" + }, "scopes": { "description": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", "type": "array", @@ -79140,6 +80310,42 @@ } } }, + "io.k8s.api.core.v1.ScopeSelector": { + "description": "A scope selector represents the AND of the selectors represented by the scoped-resource selector requirements.", + "properties": { + "matchExpressions": { + "description": "A list of scope selector requirements by scope of the resources.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ScopedResourceSelectorRequirement" + } + } + } + }, + "io.k8s.api.core.v1.ScopedResourceSelectorRequirement": { + "description": "A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.", + "required": [ + "scopeName", + "operator" + ], + "properties": { + "operator": { + "description": "Represents a scope's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist.", + "type": "string" + }, + "scopeName": { + "description": "The name of the scope that the selector applies to.", + "type": "string" + }, + "values": { + "description": "An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, "io.k8s.api.core.v1.Secret": { "description": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", "properties": { @@ -79457,6 +80663,27 @@ } ] }, + "io.k8s.api.core.v1.ServiceAccountTokenProjection": { + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.", + "type": "string" + }, + "expirationSeconds": { + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.", + "type": "integer", + "format": "int64" + }, + "path": { + "description": "Path is the path relative to the mount point of the file to project the token into.", + "type": "string" + } + } + }, "io.k8s.api.core.v1.ServiceList": { "description": "ServiceList holds a list of services.", "required": [ @@ -79569,7 +80796,7 @@ "x-kubernetes-patch-strategy": "merge" }, "publishNotReadyAddresses": { - "description": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery. This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints when that annotation is deprecated and all clients have been converted to use this field.", + "description": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery.", "type": "boolean" }, "selector": { @@ -79661,6 +80888,23 @@ } } }, + "io.k8s.api.core.v1.Sysctl": { + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "description": "Name of a property to set", + "type": "string" + }, + "value": { + "description": "Value of a property to set", + "type": "string" + } + } + }, "io.k8s.api.core.v1.TCPSocketAction": { "description": "TCPSocketAction describes an action based on opening a socket", "required": [ @@ -79728,6 +80972,38 @@ } } }, + "io.k8s.api.core.v1.TopologySelectorLabelRequirement": { + "description": "A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.", + "required": [ + "key", + "values" + ], + "properties": { + "key": { + "description": "The label key that the selector applies to.", + "type": "string" + }, + "values": { + "description": "An array of string values. One value must match the label to be selected. Each entry in Values is ORed.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.api.core.v1.TopologySelectorTerm": { + "description": "A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.", + "properties": { + "matchLabelExpressions": { + "description": "A list of topology selector requirements by labels.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.TopologySelectorLabelRequirement" + } + } + } + }, "io.k8s.api.core.v1.Volume": { "description": "Volume represents a named volume in a pod that may be accessed by any container in the pod.", "required": [ @@ -79783,7 +81059,7 @@ "$ref": "#/definitions/io.k8s.api.core.v1.GCEPersistentDiskVolumeSource" }, "gitRepo": { - "description": "GitRepo represents a git repository at a particular revision.", + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "$ref": "#/definitions/io.k8s.api.core.v1.GitRepoVolumeSource" }, "glusterfs": { @@ -79877,7 +81153,7 @@ "type": "string" }, "mountPropagation": { - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.", + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.", "type": "string" }, "name": { @@ -79917,6 +81193,10 @@ "secret": { "description": "information about the secret data to project", "$ref": "#/definitions/io.k8s.api.core.v1.SecretProjection" + }, + "serviceAccountToken": { + "description": "information about the serviceAccountToken data to project", + "$ref": "#/definitions/io.k8s.api.core.v1.ServiceAccountTokenProjection" } } }, @@ -80103,23 +81383,27 @@ } }, "io.k8s.api.extensions.v1beta1.AllowedFlexVolume": { - "description": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used.", + "description": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used. Deprecated: use AllowedFlexVolume from policy API Group instead.", "required": [ "driver" ], "properties": { "driver": { - "description": "Driver is the name of the Flexvolume driver.", + "description": "driver is the name of the Flexvolume driver.", "type": "string" } } }, "io.k8s.api.extensions.v1beta1.AllowedHostPath": { - "description": "defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", + "description": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined. Deprecated: use AllowedHostPath from policy API Group instead.", "properties": { "pathPrefix": { - "description": "is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "description": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", "type": "string" + }, + "readOnly": { + "description": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", + "type": "boolean" } } }, @@ -80580,17 +81864,17 @@ } }, "io.k8s.api.extensions.v1beta1.FSGroupStrategyOptions": { - "description": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy.", + "description": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use FSGroupStrategyOptions from policy API Group instead.", "properties": { "ranges": { - "description": "Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end.", + "description": "ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.IDRange" } }, "rule": { - "description": "Rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", + "description": "rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", "type": "string" } } @@ -80627,7 +81911,7 @@ } }, "io.k8s.api.extensions.v1beta1.HostPortRange": { - "description": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", + "description": "HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined. Deprecated: use HostPortRange from policy API Group instead.", "required": [ "min", "max" @@ -80646,19 +81930,19 @@ } }, "io.k8s.api.extensions.v1beta1.IDRange": { - "description": "ID Range provides a min/max of an allowed range of IDs.", + "description": "IDRange provides a min/max of an allowed range of IDs. Deprecated: use IDRange from policy API Group instead.", "required": [ "min", "max" ], "properties": { "max": { - "description": "Max is the end of the range, inclusive.", + "description": "max is the end of the range, inclusive.", "type": "integer", "format": "int64" }, "min": { - "description": "Min is the start of the range, inclusive.", + "description": "min is the start of the range, inclusive.", "type": "integer", "format": "int64" } @@ -80930,15 +82214,15 @@ "description": "DEPRECATED 1.9 - This group version of NetworkPolicyPeer is deprecated by networking/v1/NetworkPolicyPeer.", "properties": { "ipBlock": { - "description": "IPBlock defines policy on a particular IPBlock", + "description": "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.", "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.IPBlock" }, "namespaceSelector": { - "description": "Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces.", + "description": "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" }, "podSelector": { - "description": "This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace.", + "description": "This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.\n\nIf NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy's own Namespace.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" } } @@ -80990,7 +82274,7 @@ } }, "io.k8s.api.extensions.v1beta1.PodSecurityPolicy": { - "description": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", + "description": "PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container. Deprecated: use PodSecurityPolicy from policy API Group instead.", "properties": { "apiVersion": { "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", @@ -81018,7 +82302,7 @@ ] }, "io.k8s.api.extensions.v1beta1.PodSecurityPolicyList": { - "description": "Pod Security Policy List is a list of PodSecurityPolicy objects.", + "description": "PodSecurityPolicyList is a list of PodSecurityPolicy objects. Deprecated: use PodSecurityPolicyList from policy API Group instead.", "required": [ "items" ], @@ -81028,7 +82312,7 @@ "type": "string" }, "items": { - "description": "Items is a list of schema objects.", + "description": "items is a list of schema objects.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.PodSecurityPolicy" @@ -81052,7 +82336,7 @@ ] }, "io.k8s.api.extensions.v1beta1.PodSecurityPolicySpec": { - "description": "Pod Security Policy Spec defines the policy enforced.", + "description": "PodSecurityPolicySpec defines the policy enforced. Deprecated: use PodSecurityPolicySpec from policy API Group instead.", "required": [ "seLinux", "runAsUser", @@ -81061,43 +82345,57 @@ ], "properties": { "allowPrivilegeEscalation": { - "description": "AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", + "description": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", "type": "boolean" }, "allowedCapabilities": { - "description": "AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities.", + "description": "allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities.", "type": "array", "items": { "type": "string" } }, "allowedFlexVolumes": { - "description": "AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"Volumes\" field.", + "description": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.AllowedFlexVolume" } }, "allowedHostPaths": { - "description": "is a white list of allowed host paths. Empty indicates that all host paths may be used.", + "description": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.AllowedHostPath" } }, + "allowedUnsafeSysctls": { + "description": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "type": "array", + "items": { + "type": "string" + } + }, "defaultAddCapabilities": { - "description": "DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list.", + "description": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.", "type": "array", "items": { "type": "string" } }, "defaultAllowPrivilegeEscalation": { - "description": "DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", + "description": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", "type": "boolean" }, + "forbiddenSysctls": { + "description": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", + "type": "array", + "items": { + "type": "string" + } + }, "fsGroup": { - "description": "FSGroup is the strategy that will dictate what fs group is used by the SecurityContext.", + "description": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.", "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.FSGroupStrategyOptions" }, "hostIPC": { @@ -81124,11 +82422,11 @@ "type": "boolean" }, "readOnlyRootFilesystem": { - "description": "ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", + "description": "readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", "type": "boolean" }, "requiredDropCapabilities": { - "description": "RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", + "description": "requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", "type": "array", "items": { "type": "string" @@ -81143,11 +82441,11 @@ "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.SELinuxStrategyOptions" }, "supplementalGroups": { - "description": "SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", + "description": "supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.SupplementalGroupsStrategyOptions" }, "volumes": { - "description": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.", + "description": "volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use '*'.", "type": "array", "items": { "type": "string" @@ -81348,32 +82646,32 @@ } }, "io.k8s.api.extensions.v1beta1.RunAsUserStrategyOptions": { - "description": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.", + "description": "RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use RunAsUserStrategyOptions from policy API Group instead.", "required": [ "rule" ], "properties": { "ranges": { - "description": "Ranges are the allowed ranges of uids that may be used.", + "description": "ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.IDRange" } }, "rule": { - "description": "Rule is the strategy that will dictate the allowable RunAsUser values that may be set.", + "description": "rule is the strategy that will dictate the allowable RunAsUser values that may be set.", "type": "string" } } }, "io.k8s.api.extensions.v1beta1.SELinuxStrategyOptions": { - "description": "SELinux Strategy Options defines the strategy type and any options used to create the strategy.", + "description": "SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use SELinuxStrategyOptions from policy API Group instead.", "required": [ "rule" ], "properties": { "rule": { - "description": "type is the strategy that will dictate the allowable labels that may be set.", + "description": "rule is the strategy that will dictate the allowable labels that may be set.", "type": "string" }, "seLinuxOptions": { @@ -81449,17 +82747,17 @@ } }, "io.k8s.api.extensions.v1beta1.SupplementalGroupsStrategyOptions": { - "description": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy.", + "description": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead.", "properties": { "ranges": { - "description": "Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end.", + "description": "ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.IDRange" } }, "rule": { - "description": "Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", + "description": "rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", "type": "string" } } @@ -81584,18 +82882,18 @@ ] }, "io.k8s.api.networking.v1.NetworkPolicyPeer": { - "description": "NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields must be specified.", + "description": "NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of fields are allowed", "properties": { "ipBlock": { - "description": "IPBlock defines policy on a particular IPBlock", + "description": "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.", "$ref": "#/definitions/io.k8s.api.networking.v1.IPBlock" }, "namespaceSelector": { - "description": "Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces.", + "description": "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" }, "podSelector": { - "description": "This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace.", + "description": "This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.\n\nIf NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy's own Namespace.", "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" } } @@ -81653,17 +82951,21 @@ ], "properties": { "driver": { - "description": "Driver is the name of the Flexvolume driver.", + "description": "driver is the name of the Flexvolume driver.", "type": "string" } } }, "io.k8s.api.policy.v1beta1.AllowedHostPath": { - "description": "defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", + "description": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", "properties": { "pathPrefix": { - "description": "is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "description": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", "type": "string" + }, + "readOnly": { + "description": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", + "type": "boolean" } } }, @@ -81699,20 +83001,20 @@ "description": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy.", "properties": { "ranges": { - "description": "Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end.", + "description": "ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.policy.v1beta1.IDRange" } }, "rule": { - "description": "Rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", + "description": "rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", "type": "string" } } }, "io.k8s.api.policy.v1beta1.HostPortRange": { - "description": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", + "description": "HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", "required": [ "min", "max" @@ -81731,19 +83033,19 @@ } }, "io.k8s.api.policy.v1beta1.IDRange": { - "description": "ID Range provides a min/max of an allowed range of IDs.", + "description": "IDRange provides a min/max of an allowed range of IDs.", "required": [ "min", "max" ], "properties": { "max": { - "description": "Max is the end of the range, inclusive.", + "description": "max is the end of the range, inclusive.", "type": "integer", "format": "int64" }, "min": { - "description": "Min is the start of the range, inclusive.", + "description": "min is the start of the range, inclusive.", "type": "integer", "format": "int64" } @@ -81874,7 +83176,7 @@ } }, "io.k8s.api.policy.v1beta1.PodSecurityPolicy": { - "description": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", + "description": "PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", "properties": { "apiVersion": { "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", @@ -81902,7 +83204,7 @@ ] }, "io.k8s.api.policy.v1beta1.PodSecurityPolicyList": { - "description": "Pod Security Policy List is a list of PodSecurityPolicy objects.", + "description": "PodSecurityPolicyList is a list of PodSecurityPolicy objects.", "required": [ "items" ], @@ -81912,7 +83214,7 @@ "type": "string" }, "items": { - "description": "Items is a list of schema objects.", + "description": "items is a list of schema objects.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.policy.v1beta1.PodSecurityPolicy" @@ -81936,7 +83238,7 @@ ] }, "io.k8s.api.policy.v1beta1.PodSecurityPolicySpec": { - "description": "Pod Security Policy Spec defines the policy enforced.", + "description": "PodSecurityPolicySpec defines the policy enforced.", "required": [ "seLinux", "runAsUser", @@ -81945,43 +83247,57 @@ ], "properties": { "allowPrivilegeEscalation": { - "description": "AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", + "description": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", "type": "boolean" }, "allowedCapabilities": { - "description": "AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities.", + "description": "allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities.", "type": "array", "items": { "type": "string" } }, "allowedFlexVolumes": { - "description": "AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"Volumes\" field.", + "description": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.policy.v1beta1.AllowedFlexVolume" } }, "allowedHostPaths": { - "description": "is a white list of allowed host paths. Empty indicates that all host paths may be used.", + "description": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.policy.v1beta1.AllowedHostPath" } }, + "allowedUnsafeSysctls": { + "description": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "type": "array", + "items": { + "type": "string" + } + }, "defaultAddCapabilities": { - "description": "DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list.", + "description": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.", "type": "array", "items": { "type": "string" } }, "defaultAllowPrivilegeEscalation": { - "description": "DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", + "description": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", "type": "boolean" }, + "forbiddenSysctls": { + "description": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", + "type": "array", + "items": { + "type": "string" + } + }, "fsGroup": { - "description": "FSGroup is the strategy that will dictate what fs group is used by the SecurityContext.", + "description": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.", "$ref": "#/definitions/io.k8s.api.policy.v1beta1.FSGroupStrategyOptions" }, "hostIPC": { @@ -82008,11 +83324,11 @@ "type": "boolean" }, "readOnlyRootFilesystem": { - "description": "ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", + "description": "readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", "type": "boolean" }, "requiredDropCapabilities": { - "description": "RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", + "description": "requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", "type": "array", "items": { "type": "string" @@ -82027,11 +83343,11 @@ "$ref": "#/definitions/io.k8s.api.policy.v1beta1.SELinuxStrategyOptions" }, "supplementalGroups": { - "description": "SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", + "description": "supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", "$ref": "#/definitions/io.k8s.api.policy.v1beta1.SupplementalGroupsStrategyOptions" }, "volumes": { - "description": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.", + "description": "volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use '*'.", "type": "array", "items": { "type": "string" @@ -82040,32 +83356,32 @@ } }, "io.k8s.api.policy.v1beta1.RunAsUserStrategyOptions": { - "description": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.", + "description": "RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy.", "required": [ "rule" ], "properties": { "ranges": { - "description": "Ranges are the allowed ranges of uids that may be used.", + "description": "ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.policy.v1beta1.IDRange" } }, "rule": { - "description": "Rule is the strategy that will dictate the allowable RunAsUser values that may be set.", + "description": "rule is the strategy that will dictate the allowable RunAsUser values that may be set.", "type": "string" } } }, "io.k8s.api.policy.v1beta1.SELinuxStrategyOptions": { - "description": "SELinux Strategy Options defines the strategy type and any options used to create the strategy.", + "description": "SELinuxStrategyOptions defines the strategy type and any options used to create the strategy.", "required": [ "rule" ], "properties": { "rule": { - "description": "type is the strategy that will dictate the allowable labels that may be set.", + "description": "rule is the strategy that will dictate the allowable labels that may be set.", "type": "string" }, "seLinuxOptions": { @@ -82078,14 +83394,14 @@ "description": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy.", "properties": { "ranges": { - "description": "Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end.", + "description": "ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs.", "type": "array", "items": { "$ref": "#/definitions/io.k8s.api.policy.v1beta1.IDRange" } }, "rule": { - "description": "Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", + "description": "rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", "type": "string" } } @@ -82143,7 +83459,6 @@ "io.k8s.api.rbac.v1.ClusterRoleBinding": { "description": "ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, and adds who information via Subject.", "required": [ - "subjects", "roleRef" ], "properties": { @@ -82327,7 +83642,6 @@ "io.k8s.api.rbac.v1.RoleBinding": { "description": "RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given namespace only have effect in that namespace.", "required": [ - "subjects", "roleRef" ], "properties": { @@ -82531,7 +83845,6 @@ "io.k8s.api.rbac.v1alpha1.ClusterRoleBinding": { "description": "ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, and adds who information via Subject.", "required": [ - "subjects", "roleRef" ], "properties": { @@ -82715,7 +84028,6 @@ "io.k8s.api.rbac.v1alpha1.RoleBinding": { "description": "RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given namespace only have effect in that namespace.", "required": [ - "subjects", "roleRef" ], "properties": { @@ -82919,7 +84231,6 @@ "io.k8s.api.rbac.v1beta1.ClusterRoleBinding": { "description": "ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, and adds who information via Subject.", "required": [ - "subjects", "roleRef" ], "properties": { @@ -83103,7 +84414,6 @@ "io.k8s.api.rbac.v1beta1.RoleBinding": { "description": "RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given namespace only have effect in that namespace.", "required": [ - "subjects", "roleRef" ], "properties": { @@ -83328,6 +84638,80 @@ } ] }, + "io.k8s.api.scheduling.v1beta1.PriorityClass": { + "description": "PriorityClass defines mapping from a priority class name to the priority integer value. The value can be any valid integer.", + "required": [ + "value" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "description": { + "description": "description is an arbitrary string that usually provides guidelines on when this priority class should be used.", + "type": "string" + }, + "globalDefault": { + "description": "globalDefault specifies whether this PriorityClass should be considered as the default priority for pods that do not have any priority class. Only one PriorityClass can be marked as `globalDefault`. However, if more than one PriorityClasses exists with their `globalDefault` field set to true, the smallest value of such global default PriorityClasses will be used as the default priority.", + "type": "boolean" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "value": { + "description": "The value of this priority class. This is the actual priority that pods receive when they have the name of this class in their pod spec.", + "type": "integer", + "format": "int32" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "scheduling.k8s.io", + "kind": "PriorityClass", + "version": "v1beta1" + } + ] + }, + "io.k8s.api.scheduling.v1beta1.PriorityClassList": { + "description": "PriorityClassList is a collection of priority classes.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "items is the list of PriorityClasses", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.PriorityClass" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "scheduling.k8s.io", + "kind": "PriorityClassList", + "version": "v1beta1" + } + ] + }, "io.k8s.api.settings.v1alpha1.PodPreset": { "description": "PodPreset is a policy resource that defines additional runtime requirements for a Pod.", "properties": { @@ -83435,6 +84819,13 @@ "description": "AllowVolumeExpansion shows whether the storage class allow volume expand", "type": "boolean" }, + "allowedTopologies": { + "description": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.TopologySelectorTerm" + } + }, "apiVersion": { "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", "type": "string" @@ -83666,6 +85057,13 @@ "description": "AllowVolumeExpansion shows whether the storage class allow volume expand", "type": "boolean" }, + "allowedTopologies": { + "description": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.TopologySelectorTerm" + } + }, "apiVersion": { "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", "type": "string" @@ -83887,6 +85285,41 @@ } } }, + "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition": { + "description": "CustomResourceColumnDefinition specifies a column for server side printing.", + "required": [ + "name", + "type", + "JSONPath" + ], + "properties": { + "JSONPath": { + "description": "JSONPath is a simple JSON path, i.e. with array notation.", + "type": "string" + }, + "description": { + "description": "description is a human readable description of this column.", + "type": "string" + }, + "format": { + "description": "format is an optional OpenAPI type definition for this column. The 'name' format is applied to the primary identifier column to assist in clients identifying column is the resource name. See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.", + "type": "string" + }, + "name": { + "description": "name is a human readable name for the column.", + "type": "string" + }, + "priority": { + "description": "priority is an integer defining the relative importance of this column compared to others. Lower numbers are considered higher priority. Columns that may be omitted in limited space scenarios should be given a higher priority.", + "type": "integer", + "format": "int32" + }, + "type": { + "description": "type is an OpenAPI type definition for this column. See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.", + "type": "string" + } + } + }, "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition": { "description": "CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format \u003c.spec.name\u003e.\u003c.spec.group\u003e.", "properties": { @@ -83909,7 +85342,14 @@ "description": "Status indicates the actual state of the CustomResourceDefinition", "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus" } - } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apiextensions.k8s.io", + "kind": "CustomResourceDefinition", + "version": "v1beta1" + } + ] }, "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition": { "description": "CustomResourceDefinitionCondition contains details for the current condition of this pod.", @@ -83964,7 +85404,14 @@ "metadata": { "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" } - } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apiextensions.k8s.io", + "kind": "CustomResourceDefinitionList", + "version": "v1beta1" + } + ] }, "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames": { "description": "CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition", @@ -84009,11 +85456,17 @@ "description": "CustomResourceDefinitionSpec describes how a user wants their resource to appear", "required": [ "group", - "version", "names", "scope" ], "properties": { + "additionalPrinterColumns": { + "description": "AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition" + } + }, "group": { "description": "Group is the group this resource belongs in", "type": "string" @@ -84027,7 +85480,7 @@ "type": "string" }, "subresources": { - "description": "Subresources describes the subresources for CustomResources This field is alpha-level and should only be sent to servers that enable subresources via the CustomResourceSubresources feature gate.", + "description": "Subresources describes the subresources for CustomResources", "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresources" }, "validation": { @@ -84035,8 +85488,15 @@ "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceValidation" }, "version": { - "description": "Version is the version this resource belongs in", + "description": "Version is the version this resource belongs in Should be always first item in Versions field if provided. Optional, but at least one of Version or Versions must be set. Deprecated: Please use `Versions`.", "type": "string" + }, + "versions": { + "description": "Versions is the list of all supported versions for this resource. If Version field is provided, this field is optional. Validation: All versions must use the same validation schema for now. i.e., top level Validation field is applied to all of these versions. Order: The version name will be used to compute the order. If the version string is \"kube-like\", it will sort above non \"kube-like\" version strings, which are ordered lexicographically. \"Kube-like\" versions start with a \"v\", then are followed by a number (the major version), then optionally the string \"alpha\" or \"beta\" and another number (the minor version). These are sorted first by GA \u003e beta \u003e alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing major version, then minor version. An example sorted list of versions: v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion" + } } } }, @@ -84044,7 +85504,8 @@ "description": "CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition", "required": [ "conditions", - "acceptedNames" + "acceptedNames", + "storedVersions" ], "properties": { "acceptedNames": { @@ -84057,6 +85518,34 @@ "items": { "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition" } + }, + "storedVersions": { + "description": "StoredVersions are all versions of CustomResources that were ever persisted. Tracking these versions allows a migration path for stored versions in etcd. The field is mutable so the migration controller can first finish a migration to another version (i.e. that no old objects are left in the storage), and then remove the rest of the versions from this list. None of the versions in this list can be removed from the spec.Versions field.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion": { + "required": [ + "name", + "served", + "storage" + ], + "properties": { + "name": { + "description": "Name is the version name, e.g. “v1”, “v2beta1”, etc.", + "type": "string" + }, + "served": { + "description": "Served is a flag enabling/disabling this version from being served via REST APIs", + "type": "boolean" + }, + "storage": { + "description": "Storage flags the version as storage version. There must be exactly one flagged as storage version.", + "type": "boolean" } } }, @@ -84118,16 +85607,7 @@ } }, "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSON": { - "description": "JSON represents any valid JSON value. These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil.", - "required": [ - "Raw" - ], - "properties": { - "Raw": { - "type": "string", - "format": "byte" - } - } + "description": "JSON represents any valid JSON value. These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil." }, "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps": { "description": "JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).", @@ -84279,65 +85759,23 @@ } }, "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrArray": { - "description": "JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps or an array of JSONSchemaProps. Mainly here for serialization purposes.", - "required": [ - "Schema", - "JSONSchemas" - ], - "properties": { - "JSONSchemas": { - "type": "array", - "items": { - "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps" - } - }, - "Schema": { - "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps" - } - } + "description": "JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps or an array of JSONSchemaProps. Mainly here for serialization purposes." }, "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool": { - "description": "JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value. Defaults to true for the boolean property.", - "required": [ - "Allows", - "Schema" - ], - "properties": { - "Allows": { - "type": "boolean" - }, - "Schema": { - "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps" - } - } + "description": "JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value. Defaults to true for the boolean property." }, "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray": { - "description": "JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array.", - "required": [ - "Schema", - "Property" - ], - "properties": { - "Property": { - "type": "array", - "items": { - "type": "string" - } - }, - "Schema": { - "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaProps" - } - } + "description": "JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array." }, "io.k8s.apimachinery.pkg.api.resource.Quantity": { + "description": "Quantity is a fixed-point representation of a number. It provides convenient marshaling/unmarshaling in JSON and YAML, in addition to String() and Int64() accessors.\n\nThe serialization format is:\n\n\u003cquantity\u003e ::= \u003csignedNumber\u003e\u003csuffix\u003e\n (Note that \u003csuffix\u003e may be empty, from the \"\" case in \u003cdecimalSI\u003e.)\n\u003cdigit\u003e ::= 0 | 1 | ... | 9 \u003cdigits\u003e ::= \u003cdigit\u003e | \u003cdigit\u003e\u003cdigits\u003e \u003cnumber\u003e ::= \u003cdigits\u003e | \u003cdigits\u003e.\u003cdigits\u003e | \u003cdigits\u003e. | .\u003cdigits\u003e \u003csign\u003e ::= \"+\" | \"-\" \u003csignedNumber\u003e ::= \u003cnumber\u003e | \u003csign\u003e\u003cnumber\u003e \u003csuffix\u003e ::= \u003cbinarySI\u003e | \u003cdecimalExponent\u003e | \u003cdecimalSI\u003e \u003cbinarySI\u003e ::= Ki | Mi | Gi | Ti | Pi | Ei\n (International System of units; See: http://physics.nist.gov/cuu/Units/binary.html)\n\u003cdecimalSI\u003e ::= m | \"\" | k | M | G | T | P | E\n (Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.)\n\u003cdecimalExponent\u003e ::= \"e\" \u003csignedNumber\u003e | \"E\" \u003csignedNumber\u003e\n\nNo matter which of the three exponent forms is used, no quantity may represent a number greater than 2^63-1 in magnitude, nor may it have more than 3 decimal places. Numbers larger or more precise will be capped or rounded up. (E.g.: 0.1m will rounded up to 1m.) This may be extended in the future if we require larger or smaller quantities.\n\nWhen a Quantity is parsed from a string, it will remember the type of suffix it had, and will use the same type again when it is serialized.\n\nBefore serializing, Quantity will be put in \"canonical form\". This means that Exponent/suffix will be adjusted up or down (with a corresponding increase or decrease in Mantissa) such that:\n a. No precision is lost\n b. No fractional digits will be emitted\n c. The exponent (or suffix) is as large as possible.\nThe sign will be omitted unless the number is negative.\n\nExamples:\n 1.5 will be serialized as \"1500m\"\n 1.5Gi will be serialized as \"1536Mi\"\n\nNOTE: We reserve the right to amend this canonical format, perhaps to\n allow 1.5 to be canonical.\n or after March 2015.\n\nNote that the quantity will NEVER be internally represented by a floating point number. That is the whole point of this exercise.\n\nNon-canonical values will still parse as long as they are well formed, but will be re-emitted in their canonical form. (So always use canonical form, or don't diff.)\n\nThis format is intended to make it difficult to use these numbers without writing some sort of special handling code in the hopes that that will cause implementors to also use a fixed point implementation.", "type": "string" }, "io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup": { "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "apiVersion": { @@ -84589,6 +86027,21 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "apiextensions.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "apiregistration.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "apiregistration.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, { "group": "apps", "kind": "DeleteOptions", @@ -84699,6 +86152,11 @@ "kind": "DeleteOptions", "version": "v1alpha1" }, + { + "group": "scheduling.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, { "group": "settings.k8s.io", "kind": "DeleteOptions", @@ -84834,6 +86292,7 @@ } }, "io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime": { + "description": "MicroTime is version of Time with microsecond level precision.", "type": "string", "format": "date-time" }, @@ -85083,6 +86542,7 @@ } }, "io.k8s.apimachinery.pkg.apis.meta.v1.Time": { + "description": "Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers.", "type": "string", "format": "date-time" }, @@ -85122,6 +86582,21 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "apiextensions.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "apiregistration.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "apiregistration.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, { "group": "apps", "kind": "WatchEvent", @@ -85232,6 +86707,11 @@ "kind": "WatchEvent", "version": "v1alpha1" }, + { + "group": "scheduling.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, { "group": "settings.k8s.io", "kind": "WatchEvent", @@ -85268,6 +86748,7 @@ } }, "io.k8s.apimachinery.pkg.util.intstr.IntOrString": { + "description": "IntOrString is a type that can hold an int32 or a string. When used in JSON or YAML marshalling and unmarshalling, it produces or consumes the inner type. This allows you to have, for example, a JSON field that can accept a name or number.", "type": "string", "format": "int-or-string" }, @@ -85336,7 +86817,14 @@ "description": "Status contains derived information about an API server", "$ref": "#/definitions/io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceStatus" } - } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apiregistration.k8s.io", + "kind": "APIService", + "version": "v1" + } + ] }, "io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceCondition": { "required": [ @@ -85389,13 +86877,19 @@ "metadata": { "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" } - } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apiregistration.k8s.io", + "kind": "APIServiceList", + "version": "v1" + } + ] }, "io.k8s.kube-aggregator.pkg.apis.apiregistration.v1.APIServiceSpec": { "description": "APIServiceSpec contains information for locating and communicating with a server. Only https is supported, though you are able to disable certificate verification.", "required": [ "service", - "caBundle", "groupPriorityMinimum", "versionPriority" ], @@ -85427,7 +86921,7 @@ "type": "string" }, "versionPriority": { - "description": "VersionPriority controls the ordering of this API version inside of its group. Must be greater than zero. The primary sort is based on VersionPriority, ordered highest to lowest (20 before 10). The secondary sort is based on the alphabetical comparison of the name of the object. (v1.bar before v1.foo) Since it's inside of a group, the number can be small, probably in the 10s.", + "description": "VersionPriority controls the ordering of this API version inside of its group. Must be greater than zero. The primary sort is based on VersionPriority, ordered highest to lowest (20 before 10). Since it's inside of a group, the number can be small, probably in the 10s. In case of equal version priorities, the version string will be used to compute the order inside a group. If the version string is \"kube-like\", it will sort above non \"kube-like\" version strings, which are ordered lexicographically. \"Kube-like\" versions start with a \"v\", then are followed by a number (the major version), then optionally the string \"alpha\" or \"beta\" and another number (the minor version). These are sorted first by GA \u003e beta \u003e alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing major version, then minor version. An example sorted list of versions: v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.", "type": "integer", "format": "int32" } @@ -85482,7 +86976,14 @@ "description": "Status contains derived information about an API server", "$ref": "#/definitions/io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceStatus" } - } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apiregistration.k8s.io", + "kind": "APIService", + "version": "v1beta1" + } + ] }, "io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceCondition": { "required": [ @@ -85535,13 +87036,19 @@ "metadata": { "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" } - } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apiregistration.k8s.io", + "kind": "APIServiceList", + "version": "v1beta1" + } + ] }, "io.k8s.kube-aggregator.pkg.apis.apiregistration.v1beta1.APIServiceSpec": { "description": "APIServiceSpec contains information for locating and communicating with a server. Only https is supported, though you are able to disable certificate verification.", "required": [ "service", - "caBundle", "groupPriorityMinimum", "versionPriority" ], @@ -85573,7 +87080,7 @@ "type": "string" }, "versionPriority": { - "description": "VersionPriority controls the ordering of this API version inside of its group. Must be greater than zero. The primary sort is based on VersionPriority, ordered highest to lowest (20 before 10). The secondary sort is based on the alphabetical comparison of the name of the object. (v1.bar before v1.foo) Since it's inside of a group, the number can be small, probably in the 10s.", + "description": "VersionPriority controls the ordering of this API version inside of its group. Must be greater than zero. The primary sort is based on VersionPriority, ordered highest to lowest (20 before 10). Since it's inside of a group, the number can be small, probably in the 10s. In case of equal version priorities, the version string will be used to compute the order inside a group. If the version string is \"kube-like\", it will sort above non \"kube-like\" version strings, which are ordered lexicographically. \"Kube-like\" versions start with a \"v\", then are followed by a number (the major version), then optionally the string \"alpha\" or \"beta\" and another number (the minor version). These are sorted first by GA \u003e beta \u003e alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing major version, then minor version. An example sorted list of versions: v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.", "type": "integer", "format": "int32" } diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/admissionregistration.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/admissionregistration.k8s.io.json index 8a93d2b97..4b5bba0b6 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/admissionregistration.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/admissionregistration.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/admissionregistration.k8s.io_v1beta1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/admissionregistration.k8s.io_v1beta1.json index a691aa36e..2f22143dc 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/admissionregistration.k8s.io_v1beta1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/admissionregistration.k8s.io_v1beta1.json @@ -1777,7 +1777,7 @@ }, "service": { "$ref": "v1beta1.ServiceReference", - "description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nIf there is only one port open for the service, that port will be used. If there are multiple ports open, port 443 will be used if it is open, otherwise it is an error." + "description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nPort 443 will be used if it is open, otherwise it is an error." }, "caBundle": { "type": "string", diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/apis.json b/vendor/k8s.io/kubernetes/api/swagger-spec/apis.json index 18d960ca5..9070fc909 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/apis.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/apis.json @@ -62,8 +62,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/apps.json b/vendor/k8s.io/kubernetes/api/swagger-spec/apps.json index ecfaa626a..603237ab4 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/apps.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/apps.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1.json index 757c99f1f..e8448fc8f 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1.json @@ -6743,6 +6743,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -6775,7 +6782,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -6956,7 +6963,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -7246,6 +7253,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -7612,6 +7623,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -7670,6 +7685,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -8084,7 +8121,7 @@ }, "mountPropagation": { "$ref": "v1.MountPropagationMode", - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10." + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10." } } }, @@ -8384,6 +8421,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -8440,17 +8502,21 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects.", - "required": [ - "matchExpressions" - ], + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", "items": { "$ref": "v1.NodeSelectorRequirement" }, - "description": "Required. A list of node selector requirements. The requirements are ANDed." + "description": "A list of node selector requirements by node's labels." + }, + "matchFields": { + "type": "array", + "items": { + "$ref": "v1.NodeSelectorRequirement" + }, + "description": "A list of node selector requirements by node's fields." } } }, @@ -8665,6 +8731,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1.DaemonSetUpdateStrategy": { "id": "v1.DaemonSetUpdateStrategy", "description": "DaemonSetUpdateStrategy is a struct used to control the update strategy for a DaemonSet.", @@ -8903,11 +8982,11 @@ "properties": { "maxUnavailable": { "type": "string", - "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods." + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods." }, "maxSurge": { "type": "string", - "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods." + "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods." } } }, diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1beta1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1beta1.json index a4b090a89..eaacb4510 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1beta1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1beta1.json @@ -4377,6 +4377,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -4409,7 +4416,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -4590,7 +4597,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -4880,6 +4887,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -5246,6 +5257,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -5304,6 +5319,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -5718,7 +5755,7 @@ }, "mountPropagation": { "$ref": "v1.MountPropagationMode", - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10." + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10." } } }, @@ -6018,6 +6055,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -6074,17 +6136,21 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects.", - "required": [ - "matchExpressions" - ], + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", "items": { "$ref": "v1.NodeSelectorRequirement" }, - "description": "Required. A list of node selector requirements. The requirements are ANDed." + "description": "A list of node selector requirements by node's labels." + }, + "matchFields": { + "type": "array", + "items": { + "$ref": "v1.NodeSelectorRequirement" + }, + "description": "A list of node selector requirements by node's fields." } } }, @@ -6299,6 +6365,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1beta1.DeploymentStrategy": { "id": "v1beta1.DeploymentStrategy", "description": "DeploymentStrategy describes how to replace existing pods with new ones.", @@ -6319,11 +6398,11 @@ "properties": { "maxUnavailable": { "type": "string", - "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods." + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods." }, "maxSurge": { "type": "string", - "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods." + "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods." } } }, diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1beta2.json b/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1beta2.json index b1fcb4898..d6bc46eae 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1beta2.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/apps_v1beta2.json @@ -6743,6 +6743,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -6775,7 +6782,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -6956,7 +6963,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -7246,6 +7253,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -7612,6 +7623,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -7670,6 +7685,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -8084,7 +8121,7 @@ }, "mountPropagation": { "$ref": "v1.MountPropagationMode", - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10." + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10." } } }, @@ -8384,6 +8421,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -8440,17 +8502,21 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects.", - "required": [ - "matchExpressions" - ], + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", "items": { "$ref": "v1.NodeSelectorRequirement" }, - "description": "Required. A list of node selector requirements. The requirements are ANDed." + "description": "A list of node selector requirements by node's labels." + }, + "matchFields": { + "type": "array", + "items": { + "$ref": "v1.NodeSelectorRequirement" + }, + "description": "A list of node selector requirements by node's fields." } } }, @@ -8665,6 +8731,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1beta2.DaemonSetUpdateStrategy": { "id": "v1beta2.DaemonSetUpdateStrategy", "description": "DaemonSetUpdateStrategy is a struct used to control the update strategy for a DaemonSet.", @@ -8903,11 +8982,11 @@ "properties": { "maxUnavailable": { "type": "string", - "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods." + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods." }, "maxSurge": { "type": "string", - "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods." + "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods." } } }, diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/authentication.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/authentication.k8s.io.json index d0ef25599..175735dba 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/authentication.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/authentication.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/authorization.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/authorization.k8s.io.json index 9bd028308..98200f758 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/authorization.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/authorization.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/autoscaling.json b/vendor/k8s.io/kubernetes/api/swagger-spec/autoscaling.json index fbb9329e3..39bdb8664 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/autoscaling.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/autoscaling.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/batch.json b/vendor/k8s.io/kubernetes/api/swagger-spec/batch.json index c8604aed9..ad5fcc2c2 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/batch.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/batch.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v1.json index b6d6cea6e..3f4abc921 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v1.json @@ -1717,6 +1717,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -1749,7 +1756,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -1930,7 +1937,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -2220,6 +2227,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -2586,6 +2597,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -2644,6 +2659,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -3058,7 +3095,7 @@ }, "mountPropagation": { "$ref": "v1.MountPropagationMode", - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10." + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10." } } }, @@ -3358,6 +3395,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -3414,17 +3476,21 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects.", - "required": [ - "matchExpressions" - ], + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", "items": { "$ref": "v1.NodeSelectorRequirement" }, - "description": "Required. A list of node selector requirements. The requirements are ANDed." + "description": "A list of node selector requirements by node's labels." + }, + "matchFields": { + "type": "array", + "items": { + "$ref": "v1.NodeSelectorRequirement" + }, + "description": "A list of node selector requirements by node's fields." } } }, @@ -3639,6 +3705,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1.JobStatus": { "id": "v1.JobStatus", "description": "JobStatus represents the current state of a Job.", diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v1beta1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v1beta1.json index 32cdfc0ce..58fa7522e 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v1beta1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v1beta1.json @@ -1772,6 +1772,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -1804,7 +1811,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -1985,7 +1992,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -2275,6 +2282,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -2641,6 +2652,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -2699,6 +2714,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -3113,7 +3150,7 @@ }, "mountPropagation": { "$ref": "v1.MountPropagationMode", - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10." + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10." } } }, @@ -3413,6 +3450,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -3469,17 +3531,21 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects.", - "required": [ - "matchExpressions" - ], + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", "items": { "$ref": "v1.NodeSelectorRequirement" }, - "description": "Required. A list of node selector requirements. The requirements are ANDed." + "description": "A list of node selector requirements by node's labels." + }, + "matchFields": { + "type": "array", + "items": { + "$ref": "v1.NodeSelectorRequirement" + }, + "description": "A list of node selector requirements by node's fields." } } }, @@ -3694,6 +3760,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1beta1.CronJobStatus": { "id": "v1beta1.CronJobStatus", "description": "CronJobStatus represents the current state of a cron job.", diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v2alpha1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v2alpha1.json index 57acdbb9a..050235b53 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v2alpha1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/batch_v2alpha1.json @@ -1772,6 +1772,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -1804,7 +1811,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -1985,7 +1992,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -2275,6 +2282,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -2641,6 +2652,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -2699,6 +2714,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -3113,7 +3150,7 @@ }, "mountPropagation": { "$ref": "v1.MountPropagationMode", - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10." + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10." } } }, @@ -3413,6 +3450,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -3469,17 +3531,21 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects.", - "required": [ - "matchExpressions" - ], + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", "items": { "$ref": "v1.NodeSelectorRequirement" }, - "description": "Required. A list of node selector requirements. The requirements are ANDed." + "description": "A list of node selector requirements by node's labels." + }, + "matchFields": { + "type": "array", + "items": { + "$ref": "v1.NodeSelectorRequirement" + }, + "description": "A list of node selector requirements by node's fields." } } }, @@ -3694,6 +3760,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v2alpha1.CronJobStatus": { "id": "v2alpha1.CronJobStatus", "description": "CronJobStatus represents the current state of a cron job.", diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/certificates.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/certificates.k8s.io.json index bdd12bab6..647997053 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/certificates.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/certificates.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/certificates.k8s.io_v1beta1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/certificates.k8s.io_v1beta1.json index 01c34cfc0..45bfd3144 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/certificates.k8s.io_v1beta1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/certificates.k8s.io_v1beta1.json @@ -764,6 +764,45 @@ "path": "/apis/certificates.k8s.io/v1beta1/certificatesigningrequests/{name}/status", "description": "API at /apis/certificates.k8s.io/v1beta1", "operations": [ + { + "type": "v1beta1.CertificateSigningRequest", + "method": "GET", + "summary": "read status of the specified CertificateSigningRequest", + "nickname": "readCertificateSigningRequestStatus", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the CertificateSigningRequest", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1beta1.CertificateSigningRequest" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + }, { "type": "v1beta1.CertificateSigningRequest", "method": "PUT", @@ -815,6 +854,55 @@ "consumes": [ "*/*" ] + }, + { + "type": "v1beta1.CertificateSigningRequest", + "method": "PATCH", + "summary": "partially update status of the specified CertificateSigningRequest", + "nickname": "patchCertificateSigningRequestStatus", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "v1.Patch", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the CertificateSigningRequest", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1beta1.CertificateSigningRequest" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json" + ] } ] }, diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/events.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/events.k8s.io.json index 423933664..b65138283 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/events.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/events.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/extensions.json b/vendor/k8s.io/kubernetes/api/swagger-spec/extensions.json index 2e2fc1afd..bc161e4ef 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/extensions.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/extensions.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/extensions_v1beta1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/extensions_v1beta1.json index 6d2e049ae..07c832d78 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/extensions_v1beta1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/extensions_v1beta1.json @@ -7385,6 +7385,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -7417,7 +7424,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -7598,7 +7605,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -7888,6 +7895,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -8254,6 +8265,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -8312,6 +8327,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -8726,7 +8763,7 @@ }, "mountPropagation": { "$ref": "v1.MountPropagationMode", - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10." + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10." } } }, @@ -9026,6 +9063,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -9082,17 +9144,21 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects.", - "required": [ - "matchExpressions" - ], + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", "items": { "$ref": "v1.NodeSelectorRequirement" }, - "description": "Required. A list of node selector requirements. The requirements are ANDed." + "description": "A list of node selector requirements by node's labels." + }, + "matchFields": { + "type": "array", + "items": { + "$ref": "v1.NodeSelectorRequirement" + }, + "description": "A list of node selector requirements by node's fields." } } }, @@ -9307,6 +9373,19 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1beta1.DaemonSetUpdateStrategy": { "id": "v1beta1.DaemonSetUpdateStrategy", "properties": { @@ -10130,15 +10209,15 @@ "properties": { "podSelector": { "$ref": "v1.LabelSelector", - "description": "This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace." + "description": "This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.\n\nIf NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy's own Namespace." }, "namespaceSelector": { "$ref": "v1.LabelSelector", - "description": "Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces." + "description": "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector." }, "ipBlock": { "$ref": "v1beta1.IPBlock", - "description": "IPBlock defines policy on a particular IPBlock" + "description": "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be." } } }, @@ -10188,7 +10267,7 @@ }, "v1beta1.PodSecurityPolicyList": { "id": "v1beta1.PodSecurityPolicyList", - "description": "Pod Security Policy List is a list of PodSecurityPolicy objects.", + "description": "PodSecurityPolicyList is a list of PodSecurityPolicy objects. Deprecated: use PodSecurityPolicyList from policy API Group instead.", "required": [ "items" ], @@ -10210,13 +10289,13 @@ "items": { "$ref": "v1beta1.PodSecurityPolicy" }, - "description": "Items is a list of schema objects." + "description": "items is a list of schema objects." } } }, "v1beta1.PodSecurityPolicy": { "id": "v1beta1.PodSecurityPolicy", - "description": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", + "description": "PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container. Deprecated: use PodSecurityPolicy from policy API Group instead.", "properties": { "kind": { "type": "string", @@ -10238,7 +10317,7 @@ }, "v1beta1.PodSecurityPolicySpec": { "id": "v1beta1.PodSecurityPolicySpec", - "description": "Pod Security Policy Spec defines the policy enforced.", + "description": "PodSecurityPolicySpec defines the policy enforced. Deprecated: use PodSecurityPolicySpec from policy API Group instead.", "required": [ "seLinux", "runAsUser", @@ -10255,28 +10334,28 @@ "items": { "$ref": "v1.Capability" }, - "description": "DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list." + "description": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list." }, "requiredDropCapabilities": { "type": "array", "items": { "$ref": "v1.Capability" }, - "description": "RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added." + "description": "requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added." }, "allowedCapabilities": { "type": "array", "items": { "$ref": "v1.Capability" }, - "description": "AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities." + "description": "allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities." }, "volumes": { "type": "array", "items": { "$ref": "v1beta1.FSType" }, - "description": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used." + "description": "volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use '*'." }, "hostNetwork": { "type": "boolean", @@ -10307,37 +10386,51 @@ }, "supplementalGroups": { "$ref": "v1beta1.SupplementalGroupsStrategyOptions", - "description": "SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext." + "description": "supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext." }, "fsGroup": { "$ref": "v1beta1.FSGroupStrategyOptions", - "description": "FSGroup is the strategy that will dictate what fs group is used by the SecurityContext." + "description": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext." }, "readOnlyRootFilesystem": { "type": "boolean", - "description": "ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to." + "description": "readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to." }, "defaultAllowPrivilegeEscalation": { "type": "boolean", - "description": "DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process." + "description": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process." }, "allowPrivilegeEscalation": { "type": "boolean", - "description": "AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true." + "description": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true." }, "allowedHostPaths": { "type": "array", "items": { "$ref": "v1beta1.AllowedHostPath" }, - "description": "is a white list of allowed host paths. Empty indicates that all host paths may be used." + "description": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used." }, "allowedFlexVolumes": { "type": "array", "items": { "$ref": "v1beta1.AllowedFlexVolume" }, - "description": "AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"Volumes\" field." + "description": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field." + }, + "allowedUnsafeSysctls": { + "type": "array", + "items": { + "type": "string" + }, + "description": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc." + }, + "forbiddenSysctls": { + "type": "array", + "items": { + "type": "string" + }, + "description": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc." } } }, @@ -10347,7 +10440,7 @@ }, "v1beta1.HostPortRange": { "id": "v1beta1.HostPortRange", - "description": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", + "description": "HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined. Deprecated: use HostPortRange from policy API Group instead.", "required": [ "min", "max" @@ -10367,14 +10460,14 @@ }, "v1beta1.SELinuxStrategyOptions": { "id": "v1beta1.SELinuxStrategyOptions", - "description": "SELinux Strategy Options defines the strategy type and any options used to create the strategy.", + "description": "SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use SELinuxStrategyOptions from policy API Group instead.", "required": [ "rule" ], "properties": { "rule": { "type": "string", - "description": "type is the strategy that will dictate the allowable labels that may be set." + "description": "rule is the strategy that will dictate the allowable labels that may be set." }, "seLinuxOptions": { "$ref": "v1.SELinuxOptions", @@ -10384,27 +10477,27 @@ }, "v1beta1.RunAsUserStrategyOptions": { "id": "v1beta1.RunAsUserStrategyOptions", - "description": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.", + "description": "RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use RunAsUserStrategyOptions from policy API Group instead.", "required": [ "rule" ], "properties": { "rule": { "type": "string", - "description": "Rule is the strategy that will dictate the allowable RunAsUser values that may be set." + "description": "rule is the strategy that will dictate the allowable RunAsUser values that may be set." }, "ranges": { "type": "array", "items": { "$ref": "v1beta1.IDRange" }, - "description": "Ranges are the allowed ranges of uids that may be used." + "description": "ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs." } } }, "v1beta1.IDRange": { "id": "v1beta1.IDRange", - "description": "ID Range provides a min/max of an allowed range of IDs.", + "description": "IDRange provides a min/max of an allowed range of IDs. Deprecated: use IDRange from policy API Group instead.", "required": [ "min", "max" @@ -10413,69 +10506,73 @@ "min": { "type": "integer", "format": "int64", - "description": "Min is the start of the range, inclusive." + "description": "min is the start of the range, inclusive." }, "max": { "type": "integer", "format": "int64", - "description": "Max is the end of the range, inclusive." + "description": "max is the end of the range, inclusive." } } }, "v1beta1.SupplementalGroupsStrategyOptions": { "id": "v1beta1.SupplementalGroupsStrategyOptions", - "description": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy.", + "description": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead.", "properties": { "rule": { "type": "string", - "description": "Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext." + "description": "rule is the strategy that will dictate what supplemental groups is used in the SecurityContext." }, "ranges": { "type": "array", "items": { "$ref": "v1beta1.IDRange" }, - "description": "Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end." + "description": "ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs." } } }, "v1beta1.FSGroupStrategyOptions": { "id": "v1beta1.FSGroupStrategyOptions", - "description": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy.", + "description": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use FSGroupStrategyOptions from policy API Group instead.", "properties": { "rule": { "type": "string", - "description": "Rule is the strategy that will dictate what FSGroup is used in the SecurityContext." + "description": "rule is the strategy that will dictate what FSGroup is used in the SecurityContext." }, "ranges": { "type": "array", "items": { "$ref": "v1beta1.IDRange" }, - "description": "Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end." + "description": "ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs." } } }, "v1beta1.AllowedHostPath": { "id": "v1beta1.AllowedHostPath", - "description": "defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", + "description": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined. Deprecated: use AllowedHostPath from policy API Group instead.", "properties": { "pathPrefix": { "type": "string", - "description": "is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`" + "description": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`" + }, + "readOnly": { + "type": "boolean", + "description": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly." } } }, "v1beta1.AllowedFlexVolume": { "id": "v1beta1.AllowedFlexVolume", - "description": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used.", + "description": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used. Deprecated: use AllowedFlexVolume from policy API Group instead.", "required": [ "driver" ], "properties": { "driver": { "type": "string", - "description": "Driver is the name of the Flexvolume driver." + "description": "driver is the name of the Flexvolume driver." } } }, diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/networking.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/networking.k8s.io.json index debc58cd7..9a67396dd 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/networking.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/networking.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/networking.k8s.io_v1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/networking.k8s.io_v1.json index ea6c57887..43ac7d0b9 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/networking.k8s.io_v1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/networking.k8s.io_v1.json @@ -1427,19 +1427,19 @@ }, "v1.NetworkPolicyPeer": { "id": "v1.NetworkPolicyPeer", - "description": "NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields must be specified.", + "description": "NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of fields are allowed", "properties": { "podSelector": { "$ref": "v1.LabelSelector", - "description": "This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace." + "description": "This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.\n\nIf NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy's own Namespace." }, "namespaceSelector": { "$ref": "v1.LabelSelector", - "description": "Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces." + "description": "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector." }, "ipBlock": { "$ref": "v1.IPBlock", - "description": "IPBlock defines policy on a particular IPBlock" + "description": "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be." } } }, diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/policy.json b/vendor/k8s.io/kubernetes/api/swagger-spec/policy.json index 51c62c221..12ee477cc 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/policy.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/policy.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/policy_v1beta1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/policy_v1beta1.json index 4693bef40..e62fd2425 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/policy_v1beta1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/policy_v1beta1.json @@ -2349,7 +2349,7 @@ }, "v1beta1.PodSecurityPolicyList": { "id": "v1beta1.PodSecurityPolicyList", - "description": "Pod Security Policy List is a list of PodSecurityPolicy objects.", + "description": "PodSecurityPolicyList is a list of PodSecurityPolicy objects.", "required": [ "items" ], @@ -2371,13 +2371,13 @@ "items": { "$ref": "v1beta1.PodSecurityPolicy" }, - "description": "Items is a list of schema objects." + "description": "items is a list of schema objects." } } }, "v1beta1.PodSecurityPolicy": { "id": "v1beta1.PodSecurityPolicy", - "description": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", + "description": "PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", "properties": { "kind": { "type": "string", @@ -2399,7 +2399,7 @@ }, "v1beta1.PodSecurityPolicySpec": { "id": "v1beta1.PodSecurityPolicySpec", - "description": "Pod Security Policy Spec defines the policy enforced.", + "description": "PodSecurityPolicySpec defines the policy enforced.", "required": [ "seLinux", "runAsUser", @@ -2416,28 +2416,28 @@ "items": { "$ref": "v1.Capability" }, - "description": "DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list." + "description": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list." }, "requiredDropCapabilities": { "type": "array", "items": { "$ref": "v1.Capability" }, - "description": "RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added." + "description": "requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added." }, "allowedCapabilities": { "type": "array", "items": { "$ref": "v1.Capability" }, - "description": "AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities." + "description": "allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities." }, "volumes": { "type": "array", "items": { "$ref": "v1beta1.FSType" }, - "description": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used." + "description": "volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use '*'." }, "hostNetwork": { "type": "boolean", @@ -2468,37 +2468,51 @@ }, "supplementalGroups": { "$ref": "v1beta1.SupplementalGroupsStrategyOptions", - "description": "SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext." + "description": "supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext." }, "fsGroup": { "$ref": "v1beta1.FSGroupStrategyOptions", - "description": "FSGroup is the strategy that will dictate what fs group is used by the SecurityContext." + "description": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext." }, "readOnlyRootFilesystem": { "type": "boolean", - "description": "ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to." + "description": "readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to." }, "defaultAllowPrivilegeEscalation": { "type": "boolean", - "description": "DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process." + "description": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process." }, "allowPrivilegeEscalation": { "type": "boolean", - "description": "AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true." + "description": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true." }, "allowedHostPaths": { "type": "array", "items": { "$ref": "v1beta1.AllowedHostPath" }, - "description": "is a white list of allowed host paths. Empty indicates that all host paths may be used." + "description": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used." }, "allowedFlexVolumes": { "type": "array", "items": { "$ref": "v1beta1.AllowedFlexVolume" }, - "description": "AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"Volumes\" field." + "description": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field." + }, + "allowedUnsafeSysctls": { + "type": "array", + "items": { + "type": "string" + }, + "description": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc." + }, + "forbiddenSysctls": { + "type": "array", + "items": { + "type": "string" + }, + "description": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc." } } }, @@ -2512,7 +2526,7 @@ }, "v1beta1.HostPortRange": { "id": "v1beta1.HostPortRange", - "description": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", + "description": "HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", "required": [ "min", "max" @@ -2532,14 +2546,14 @@ }, "v1beta1.SELinuxStrategyOptions": { "id": "v1beta1.SELinuxStrategyOptions", - "description": "SELinux Strategy Options defines the strategy type and any options used to create the strategy.", + "description": "SELinuxStrategyOptions defines the strategy type and any options used to create the strategy.", "required": [ "rule" ], "properties": { "rule": { "type": "string", - "description": "type is the strategy that will dictate the allowable labels that may be set." + "description": "rule is the strategy that will dictate the allowable labels that may be set." }, "seLinuxOptions": { "$ref": "v1.SELinuxOptions", @@ -2571,27 +2585,27 @@ }, "v1beta1.RunAsUserStrategyOptions": { "id": "v1beta1.RunAsUserStrategyOptions", - "description": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.", + "description": "RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy.", "required": [ "rule" ], "properties": { "rule": { "type": "string", - "description": "Rule is the strategy that will dictate the allowable RunAsUser values that may be set." + "description": "rule is the strategy that will dictate the allowable RunAsUser values that may be set." }, "ranges": { "type": "array", "items": { "$ref": "v1beta1.IDRange" }, - "description": "Ranges are the allowed ranges of uids that may be used." + "description": "ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs." } } }, "v1beta1.IDRange": { "id": "v1beta1.IDRange", - "description": "ID Range provides a min/max of an allowed range of IDs.", + "description": "IDRange provides a min/max of an allowed range of IDs.", "required": [ "min", "max" @@ -2600,12 +2614,12 @@ "min": { "type": "integer", "format": "int64", - "description": "Min is the start of the range, inclusive." + "description": "min is the start of the range, inclusive." }, "max": { "type": "integer", "format": "int64", - "description": "Max is the end of the range, inclusive." + "description": "max is the end of the range, inclusive." } } }, @@ -2615,14 +2629,14 @@ "properties": { "rule": { "type": "string", - "description": "Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext." + "description": "rule is the strategy that will dictate what supplemental groups is used in the SecurityContext." }, "ranges": { "type": "array", "items": { "$ref": "v1beta1.IDRange" }, - "description": "Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end." + "description": "ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs." } } }, @@ -2632,24 +2646,28 @@ "properties": { "rule": { "type": "string", - "description": "Rule is the strategy that will dictate what FSGroup is used in the SecurityContext." + "description": "rule is the strategy that will dictate what FSGroup is used in the SecurityContext." }, "ranges": { "type": "array", "items": { "$ref": "v1beta1.IDRange" }, - "description": "Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end." + "description": "ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs." } } }, "v1beta1.AllowedHostPath": { "id": "v1beta1.AllowedHostPath", - "description": "defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", + "description": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", "properties": { "pathPrefix": { "type": "string", - "description": "is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`" + "description": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`" + }, + "readOnly": { + "type": "boolean", + "description": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly." } } }, @@ -2662,7 +2680,7 @@ "properties": { "driver": { "type": "string", - "description": "Driver is the name of the Flexvolume driver." + "description": "driver is the name of the Flexvolume driver." } } }, diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io.json index d162e47b9..7752ae8a6 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1.json index b5fdb605d..e1f93d1e8 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1.json @@ -3351,7 +3351,6 @@ "id": "v1.ClusterRoleBinding", "description": "ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, and adds who information via Subject.", "required": [ - "subjects", "roleRef" ], "properties": { @@ -3927,7 +3926,6 @@ "id": "v1.RoleBinding", "description": "RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given namespace only have effect in that namespace.", "required": [ - "subjects", "roleRef" ], "properties": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1alpha1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1alpha1.json index bae9fa9fa..73a4ab4f5 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1alpha1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1alpha1.json @@ -3351,7 +3351,6 @@ "id": "v1alpha1.ClusterRoleBinding", "description": "ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, and adds who information via Subject.", "required": [ - "subjects", "roleRef" ], "properties": { @@ -3927,7 +3926,6 @@ "id": "v1alpha1.RoleBinding", "description": "RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given namespace only have effect in that namespace.", "required": [ - "subjects", "roleRef" ], "properties": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1beta1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1beta1.json index c51d9e77c..eb3bd1d1d 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1beta1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/rbac.authorization.k8s.io_v1beta1.json @@ -3351,7 +3351,6 @@ "id": "v1beta1.ClusterRoleBinding", "description": "ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, and adds who information via Subject.", "required": [ - "subjects", "roleRef" ], "properties": { @@ -3927,7 +3926,6 @@ "id": "v1beta1.RoleBinding", "description": "RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given namespace only have effect in that namespace.", "required": [ - "subjects", "roleRef" ], "properties": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/resourceListing.json b/vendor/k8s.io/kubernetes/api/swagger-spec/resourceListing.json index 1c9928dfa..d8ba11d01 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/resourceListing.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/resourceListing.json @@ -121,6 +121,10 @@ "path": "/apis/rbac.authorization.k8s.io", "description": "get information of a group" }, + { + "path": "/apis/scheduling.k8s.io/v1beta1", + "description": "API at /apis/scheduling.k8s.io/v1beta1" + }, { "path": "/apis/scheduling.k8s.io/v1alpha1", "description": "API at /apis/scheduling.k8s.io/v1alpha1" diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/scheduling.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/scheduling.k8s.io.json index ca8030cbd..639e581b0 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/scheduling.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/scheduling.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/scheduling.k8s.io_v1beta1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/scheduling.k8s.io_v1beta1.json new file mode 100644 index 000000000..742bcf631 --- /dev/null +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/scheduling.k8s.io_v1beta1.json @@ -0,0 +1,1205 @@ +{ + "swaggerVersion": "1.2", + "apiVersion": "scheduling.k8s.io/v1beta1", + "basePath": "https://10.10.10.10:6443", + "resourcePath": "/apis/scheduling.k8s.io/v1beta1", + "info": { + "title": "", + "description": "" + }, + "apis": [ + { + "path": "/apis/scheduling.k8s.io/v1beta1/priorityclasses", + "description": "API at /apis/scheduling.k8s.io/v1beta1", + "operations": [ + { + "type": "v1beta1.PriorityClassList", + "method": "GET", + "summary": "list or watch objects of kind PriorityClass", + "nickname": "listPriorityClass", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1beta1.PriorityClassList" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "v1beta1.PriorityClass", + "method": "POST", + "summary": "create a PriorityClass", + "nickname": "createPriorityClass", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.PriorityClass", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1beta1.PriorityClass" + }, + { + "code": 201, + "message": "Created", + "responseModel": "v1beta1.PriorityClass" + }, + { + "code": 202, + "message": "Accepted", + "responseModel": "v1beta1.PriorityClass" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "v1.Status", + "method": "DELETE", + "summary": "delete collection of PriorityClass", + "nickname": "deletecollectionPriorityClass", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.Status" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/scheduling.k8s.io/v1beta1/watch/priorityclasses", + "description": "API at /apis/scheduling.k8s.io/v1beta1", + "operations": [ + { + "type": "v1.WatchEvent", + "method": "GET", + "summary": "watch individual changes to a list of PriorityClass", + "nickname": "watchPriorityClassList", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.WatchEvent" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/scheduling.k8s.io/v1beta1/priorityclasses/{name}", + "description": "API at /apis/scheduling.k8s.io/v1beta1", + "operations": [ + { + "type": "v1beta1.PriorityClass", + "method": "GET", + "summary": "read the specified PriorityClass", + "nickname": "readPriorityClass", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "export", + "description": "Should this value be exported. Export strips fields that a user can not specify.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "exact", + "description": "Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the PriorityClass", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1beta1.PriorityClass" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "v1beta1.PriorityClass", + "method": "PUT", + "summary": "replace the specified PriorityClass", + "nickname": "replacePriorityClass", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.PriorityClass", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the PriorityClass", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1beta1.PriorityClass" + }, + { + "code": 201, + "message": "Created", + "responseModel": "v1beta1.PriorityClass" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "v1beta1.PriorityClass", + "method": "PATCH", + "summary": "partially update the specified PriorityClass", + "nickname": "patchPriorityClass", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "v1.Patch", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the PriorityClass", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1beta1.PriorityClass" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json" + ] + }, + { + "type": "v1.Status", + "method": "DELETE", + "summary": "delete a PriorityClass", + "nickname": "deletePriorityClass", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "v1.DeleteOptions", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "gracePeriodSeconds", + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "orphanDependents", + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "propagationPolicy", + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the PriorityClass", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.Status" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/scheduling.k8s.io/v1beta1/watch/priorityclasses/{name}", + "description": "API at /apis/scheduling.k8s.io/v1beta1", + "operations": [ + { + "type": "v1.WatchEvent", + "method": "GET", + "summary": "watch changes to an object of kind PriorityClass", + "nickname": "watchPriorityClass", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the PriorityClass", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.WatchEvent" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/scheduling.k8s.io/v1beta1", + "description": "API at /apis/scheduling.k8s.io/v1beta1", + "operations": [ + { + "type": "v1.APIResourceList", + "method": "GET", + "summary": "get available resources", + "nickname": "getAPIResources", + "parameters": [], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ] + } + ] + } + ], + "models": { + "v1beta1.PriorityClassList": { + "id": "v1beta1.PriorityClassList", + "description": "PriorityClassList is a collection of priority classes.", + "required": [ + "items" + ], + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "metadata": { + "$ref": "v1.ListMeta", + "description": "Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + }, + "items": { + "type": "array", + "items": { + "$ref": "v1beta1.PriorityClass" + }, + "description": "items is the list of PriorityClasses" + } + } + }, + "v1.ListMeta": { + "id": "v1.ListMeta", + "description": "ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.", + "properties": { + "selfLink": { + "type": "string", + "description": "selfLink is a URL representing this object. Populated by the system. Read-only." + }, + "resourceVersion": { + "type": "string", + "description": "String that identifies the server's internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency" + }, + "continue": { + "type": "string", + "description": "continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response." + } + } + }, + "v1beta1.PriorityClass": { + "id": "v1beta1.PriorityClass", + "description": "PriorityClass defines mapping from a priority class name to the priority integer value. The value can be any valid integer.", + "required": [ + "value" + ], + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "metadata": { + "$ref": "v1.ObjectMeta", + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + }, + "value": { + "type": "integer", + "format": "int32", + "description": "The value of this priority class. This is the actual priority that pods receive when they have the name of this class in their pod spec." + }, + "globalDefault": { + "type": "boolean", + "description": "globalDefault specifies whether this PriorityClass should be considered as the default priority for pods that do not have any priority class. Only one PriorityClass can be marked as `globalDefault`. However, if more than one PriorityClasses exists with their `globalDefault` field set to true, the smallest value of such global default PriorityClasses will be used as the default priority." + }, + "description": { + "type": "string", + "description": "description is an arbitrary string that usually provides guidelines on when this priority class should be used." + } + } + }, + "v1.ObjectMeta": { + "id": "v1.ObjectMeta", + "description": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.", + "properties": { + "name": { + "type": "string", + "description": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names" + }, + "generateName": { + "type": "string", + "description": "GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.\n\nIf this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).\n\nApplied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency" + }, + "namespace": { + "type": "string", + "description": "Namespace defines the space within each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces" + }, + "selfLink": { + "type": "string", + "description": "SelfLink is a URL representing this object. Populated by the system. Read-only." + }, + "uid": { + "type": "string", + "description": "UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.\n\nPopulated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + }, + "resourceVersion": { + "type": "string", + "description": "An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.\n\nPopulated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency" + }, + "generation": { + "type": "integer", + "format": "int64", + "description": "A sequence number representing a specific generation of the desired state. Populated by the system. Read-only." + }, + "creationTimestamp": { + "type": "string", + "description": "CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + }, + "deletionTimestamp": { + "type": "string", + "description": "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + }, + "deletionGracePeriodSeconds": { + "type": "integer", + "format": "int64", + "description": "Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only." + }, + "labels": { + "type": "object", + "description": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels" + }, + "annotations": { + "type": "object", + "description": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations" + }, + "ownerReferences": { + "type": "array", + "items": { + "$ref": "v1.OwnerReference" + }, + "description": "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller." + }, + "initializers": { + "$ref": "v1.Initializers", + "description": "An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to observe uninitialized objects.\n\nWhen an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user." + }, + "finalizers": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed." + }, + "clusterName": { + "type": "string", + "description": "The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request." + } + } + }, + "v1.OwnerReference": { + "id": "v1.OwnerReference", + "description": "OwnerReference contains enough information to let you identify an owning object. Currently, an owning object must be in the same namespace, so there is no namespace field.", + "required": [ + "apiVersion", + "kind", + "name", + "uid" + ], + "properties": { + "apiVersion": { + "type": "string", + "description": "API version of the referent." + }, + "kind": { + "type": "string", + "description": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "name": { + "type": "string", + "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" + }, + "uid": { + "type": "string", + "description": "UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + }, + "controller": { + "type": "boolean", + "description": "If true, this reference points to the managing controller." + }, + "blockOwnerDeletion": { + "type": "boolean", + "description": "If true, AND if the owner has the \"foregroundDeletion\" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. Defaults to false. To set this field, a user needs \"delete\" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned." + } + } + }, + "v1.Initializers": { + "id": "v1.Initializers", + "description": "Initializers tracks the progress of initialization.", + "required": [ + "pending" + ], + "properties": { + "pending": { + "type": "array", + "items": { + "$ref": "v1.Initializer" + }, + "description": "Pending is a list of initializers that must execute in order before this object is visible. When the last pending initializer is removed, and no failing result is set, the initializers struct will be set to nil and the object is considered as initialized and visible to all clients." + }, + "result": { + "$ref": "v1.Status", + "description": "If result is set with the Failure field, the object will be persisted to storage and then deleted, ensuring that other clients can observe the deletion." + } + } + }, + "v1.Initializer": { + "id": "v1.Initializer", + "description": "Initializer is information about an initializer that has not yet completed.", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "name of the process that is responsible for initializing this object." + } + } + }, + "v1.Status": { + "id": "v1.Status", + "description": "Status is a return value for calls that don't return other objects.", + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "metadata": { + "$ref": "v1.ListMeta", + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "status": { + "type": "string", + "description": "Status of the operation. One of: \"Success\" or \"Failure\". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status" + }, + "message": { + "type": "string", + "description": "A human-readable description of the status of this operation." + }, + "reason": { + "type": "string", + "description": "A machine-readable description of why this operation is in the \"Failure\" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it." + }, + "details": { + "$ref": "v1.StatusDetails", + "description": "Extended data associated with the reason. Each reason may define its own extended details. This field is optional and the data returned is not guaranteed to conform to any schema except that defined by the reason type." + }, + "code": { + "type": "integer", + "format": "int32", + "description": "Suggested HTTP return code for this status, 0 if not set." + } + } + }, + "v1.StatusDetails": { + "id": "v1.StatusDetails", + "description": "StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.", + "properties": { + "name": { + "type": "string", + "description": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described)." + }, + "group": { + "type": "string", + "description": "The group attribute of the resource associated with the status StatusReason." + }, + "kind": { + "type": "string", + "description": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "uid": { + "type": "string", + "description": "UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + }, + "causes": { + "type": "array", + "items": { + "$ref": "v1.StatusCause" + }, + "description": "The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes." + }, + "retryAfterSeconds": { + "type": "integer", + "format": "int32", + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." + } + } + }, + "v1.StatusCause": { + "id": "v1.StatusCause", + "description": "StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered.", + "properties": { + "reason": { + "type": "string", + "description": "A machine-readable description of the cause of the error. If this value is empty there is no information available." + }, + "message": { + "type": "string", + "description": "A human-readable description of the cause of the error. This field may be presented as-is to a reader." + }, + "field": { + "type": "string", + "description": "The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.\n\nExamples:\n \"name\" - the field \"name\" on the current resource\n \"items[0].name\" - the field \"name\" on the first array entry in \"items\"" + } + } + }, + "v1.WatchEvent": { + "id": "v1.WatchEvent", + "required": [ + "type", + "object" + ], + "properties": { + "type": { + "type": "string" + }, + "object": { + "type": "string" + } + } + }, + "v1.Patch": { + "id": "v1.Patch", + "description": "Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.", + "properties": {} + }, + "v1.DeleteOptions": { + "id": "v1.DeleteOptions", + "description": "DeleteOptions may be provided when deleting an API object.", + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "gracePeriodSeconds": { + "type": "integer", + "format": "int64", + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately." + }, + "preconditions": { + "$ref": "v1.Preconditions", + "description": "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned." + }, + "orphanDependents": { + "type": "boolean", + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both." + }, + "propagationPolicy": { + "$ref": "v1.DeletionPropagation", + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground." + } + } + }, + "v1.Preconditions": { + "id": "v1.Preconditions", + "description": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.", + "properties": { + "uid": { + "$ref": "types.UID", + "description": "Specifies the target UID." + } + } + }, + "types.UID": { + "id": "types.UID", + "properties": {} + }, + "v1.DeletionPropagation": { + "id": "v1.DeletionPropagation", + "properties": {} + }, + "v1.APIResourceList": { + "id": "v1.APIResourceList", + "description": "APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.", + "required": [ + "groupVersion", + "resources" + ], + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "groupVersion": { + "type": "string", + "description": "groupVersion is the group and version this APIResourceList is for." + }, + "resources": { + "type": "array", + "items": { + "$ref": "v1.APIResource" + }, + "description": "resources contains the name of the resources and if they are namespaced." + } + } + }, + "v1.APIResource": { + "id": "v1.APIResource", + "description": "APIResource specifies the name of a resource and whether it is namespaced.", + "required": [ + "name", + "singularName", + "namespaced", + "kind", + "verbs" + ], + "properties": { + "name": { + "type": "string", + "description": "name is the plural name of the resource." + }, + "singularName": { + "type": "string", + "description": "singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface." + }, + "namespaced": { + "type": "boolean", + "description": "namespaced indicates if a resource is namespaced or not." + }, + "group": { + "type": "string", + "description": "group is the preferred group of the resource. Empty implies the group of the containing resource list. For subresources, this may have a different value, for example: Scale\"." + }, + "version": { + "type": "string", + "description": "version is the preferred version of the resource. Empty implies the version of the containing resource list For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource's group)\"." + }, + "kind": { + "type": "string", + "description": "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')" + }, + "verbs": { + "type": "array", + "items": { + "type": "string" + }, + "description": "verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)" + }, + "shortNames": { + "type": "array", + "items": { + "type": "string" + }, + "description": "shortNames is a list of suggested short names of the resource." + }, + "categories": { + "type": "array", + "items": { + "type": "string" + }, + "description": "categories is a list of the grouped resources this resource belongs to (e.g. 'all')" + } + } + } + } + } diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/settings.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/settings.k8s.io.json index b82334cab..f14622907 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/settings.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/settings.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/settings.k8s.io_v1alpha1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/settings.k8s.io_v1alpha1.json index d4427baab..8c9e275eb 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/settings.k8s.io_v1alpha1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/settings.k8s.io_v1alpha1.json @@ -1587,7 +1587,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -1768,7 +1768,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -2058,6 +2058,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -2386,6 +2390,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -2444,6 +2452,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.PortworxVolumeSource": { "id": "v1.PortworxVolumeSource", "description": "PortworxVolumeSource represents a Portworx volume resource.", @@ -2568,7 +2598,7 @@ }, "mountPropagation": { "$ref": "v1.MountPropagationMode", - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10." + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10." } } }, diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io.json b/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io.json index 733f4ecef..956159c8c 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io.json @@ -38,8 +38,7 @@ "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "required": [ "name", - "versions", - "serverAddressByClientCIDRs" + "versions" ], "properties": { "kind": { diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io_v1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io_v1.json index 19adf296d..2ffcfd9c7 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io_v1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io_v1.json @@ -818,6 +818,13 @@ "volumeBindingMode": { "$ref": "v1.VolumeBindingMode", "description": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature." + }, + "allowedTopologies": { + "type": "array", + "items": { + "$ref": "v1.TopologySelectorTerm" + }, + "description": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature." } } }, @@ -1067,6 +1074,40 @@ "id": "v1.VolumeBindingMode", "properties": {} }, + "v1.TopologySelectorTerm": { + "id": "v1.TopologySelectorTerm", + "description": "A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.", + "properties": { + "matchLabelExpressions": { + "type": "array", + "items": { + "$ref": "v1.TopologySelectorLabelRequirement" + }, + "description": "A list of topology selector requirements by labels." + } + } + }, + "v1.TopologySelectorLabelRequirement": { + "id": "v1.TopologySelectorLabelRequirement", + "description": "A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.", + "required": [ + "key", + "values" + ], + "properties": { + "key": { + "type": "string", + "description": "The label key that the selector applies to." + }, + "values": { + "type": "array", + "items": { + "type": "string" + }, + "description": "An array of string values. One value must match the label to be selected. Each entry in Values is ORed." + } + } + }, "v1.WatchEvent": { "id": "v1.WatchEvent", "required": [ diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io_v1beta1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io_v1beta1.json index 3f987d8a8..3859a2203 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io_v1beta1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/storage.k8s.io_v1beta1.json @@ -1512,6 +1512,13 @@ "volumeBindingMode": { "$ref": "v1beta1.VolumeBindingMode", "description": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature." + }, + "allowedTopologies": { + "type": "array", + "items": { + "$ref": "v1.TopologySelectorTerm" + }, + "description": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature." } } }, @@ -1761,6 +1768,40 @@ "id": "v1beta1.VolumeBindingMode", "properties": {} }, + "v1.TopologySelectorTerm": { + "id": "v1.TopologySelectorTerm", + "description": "A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.", + "properties": { + "matchLabelExpressions": { + "type": "array", + "items": { + "$ref": "v1.TopologySelectorLabelRequirement" + }, + "description": "A list of topology selector requirements by labels." + } + } + }, + "v1.TopologySelectorLabelRequirement": { + "id": "v1.TopologySelectorLabelRequirement", + "description": "A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.", + "required": [ + "key", + "values" + ], + "properties": { + "key": { + "type": "string", + "description": "The label key that the selector applies to." + }, + "values": { + "type": "array", + "items": { + "type": "string" + }, + "description": "An array of string values. One value must match the label to be selected. Each entry in Values is ORed." + } + } + }, "v1.WatchEvent": { "id": "v1.WatchEvent", "required": [ diff --git a/vendor/k8s.io/kubernetes/api/swagger-spec/v1.json b/vendor/k8s.io/kubernetes/api/swagger-spec/v1.json index 3f1198efd..7cfc2e91a 100644 --- a/vendor/k8s.io/kubernetes/api/swagger-spec/v1.json +++ b/vendor/k8s.io/kubernetes/api/swagger-spec/v1.json @@ -18663,10 +18663,6 @@ "type": "string", "description": "PodCIDR represents the pod IP range assigned to the node." }, - "externalID": { - "type": "string", - "description": "External ID of the node assigned by some machine database (e.g. a cloud provider). Deprecated." - }, "providerID": { "type": "string", "description": "ID of the node assigned by the cloud provider in the format: \u003cProviderName\u003e://\u003cProviderSpecificNodeID\u003e" @@ -18685,6 +18681,10 @@ "configSource": { "$ref": "v1.NodeConfigSource", "description": "If specified, the source to get node configuration from The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field" + }, + "externalID": { + "type": "string", + "description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966" } } }, @@ -18718,16 +18718,40 @@ "id": "v1.NodeConfigSource", "description": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.", "properties": { - "kind": { + "configMap": { + "$ref": "v1.ConfigMapNodeConfigSource", + "description": "ConfigMap is a reference to a Node's ConfigMap" + } + } + }, + "v1.ConfigMapNodeConfigSource": { + "id": "v1.ConfigMapNodeConfigSource", + "description": "ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.", + "required": [ + "namespace", + "name", + "kubeletConfigKey" + ], + "properties": { + "namespace": { "type": "string", - "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + "description": "Namespace is the metadata.namespace of the referenced ConfigMap. This field is required in all cases." }, - "apiVersion": { + "name": { "type": "string", - "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + "description": "Name is the metadata.name of the referenced ConfigMap. This field is required in all cases." }, - "configMapRef": { - "$ref": "v1.ObjectReference" + "uid": { + "type": "string", + "description": "UID is the metadata.UID of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status." + }, + "resourceVersion": { + "type": "string", + "description": "ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status." + }, + "kubeletConfigKey": { + "type": "string", + "description": "KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure This field is required in all cases." } } }, @@ -18789,6 +18813,10 @@ "$ref": "v1.AttachedVolume" }, "description": "List of volumes that are attached to the node." + }, + "config": { + "$ref": "v1.NodeConfigStatus", + "description": "Status of the config assigned to the node via the dynamic Kubelet config feature." } } }, @@ -18969,6 +18997,28 @@ } } }, + "v1.NodeConfigStatus": { + "id": "v1.NodeConfigStatus", + "description": "NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource.", + "properties": { + "assigned": { + "$ref": "v1.NodeConfigSource", + "description": "Assigned reports the checkpointed config the node will try to use. When Node.Spec.ConfigSource is updated, the node checkpoints the associated config payload to local disk, along with a record indicating intended config. The node refers to this record to choose its config checkpoint, and reports this record in Assigned. Assigned only updates in the status after the record has been checkpointed to disk. When the Kubelet is restarted, it tries to make the Assigned config the Active config by loading and validating the checkpointed payload identified by Assigned." + }, + "active": { + "$ref": "v1.NodeConfigSource", + "description": "Active reports the checkpointed config the node is actively using. Active will represent either the current version of the Assigned config, or the current LastKnownGood config, depending on whether attempting to use the Assigned config results in an error." + }, + "lastKnownGood": { + "$ref": "v1.NodeConfigSource", + "description": "LastKnownGood reports the checkpointed config the node will fall back to when it encounters an error attempting to use the Assigned config. The Assigned config becomes the LastKnownGood config when the node determines that the Assigned config is stable and correct. This is currently implemented as a 10-minute soak period starting when the local record of Assigned config is updated. If the Assigned config is Active at the end of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, because the local default config is always assumed good. You should not make assumptions about the node's method of determining config stability and correctness, as this may change or become configurable in the future." + }, + "error": { + "type": "string", + "description": "Error describes any problems reconciling the Spec.ConfigSource to the Active config. Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting to load or validate the Assigned config, etc. Errors may occur at different points while syncing config. Earlier errors (e.g. download or checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error by fixing the config assigned in Spec.ConfigSource. You can find additional information for debugging by searching the error message in the Kubelet log. Error is a human-readable description of the error state; machines can check whether or not Error is empty, but should not rely on the stability of the Error text across Kubelet versions." + } + } + }, "v1.PersistentVolumeClaimList": { "id": "v1.PersistentVolumeClaimList", "description": "PersistentVolumeClaimList is a list of PersistentVolumeClaim items.", @@ -19271,7 +19321,7 @@ "description": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin." }, "cinder": { - "$ref": "v1.CinderVolumeSource", + "$ref": "v1.CinderPersistentVolumeSource", "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" }, "cephfs": { @@ -19601,8 +19651,8 @@ } } }, - "v1.CinderVolumeSource": { - "id": "v1.CinderVolumeSource", + "v1.CinderPersistentVolumeSource": { + "id": "v1.CinderPersistentVolumeSource", "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", "required": [ "volumeID" @@ -19619,6 +19669,10 @@ "readOnly": { "type": "boolean", "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.SecretReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." } } }, @@ -19949,14 +20003,14 @@ }, "v1.LocalVolumeSource": { "id": "v1.LocalVolumeSource", - "description": "Local represents directly-attached storage with node affinity", + "description": "Local represents directly-attached storage with node affinity (Beta feature)", "required": [ "path" ], "properties": { "path": { "type": "string", - "description": "The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device" + "description": "The full path to the volume on the node. It can be either a directory or block device (disk, partition, ...). Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. Block devices can be represented only by VolumeMode=Block, which also requires the BlockVolume alpha feature gate to be enabled." } } }, @@ -20008,7 +20062,7 @@ }, "fsType": { "type": "string", - "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified." + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\"." }, "volumeAttributes": { "type": "object", @@ -20056,17 +20110,21 @@ }, "v1.NodeSelectorTerm": { "id": "v1.NodeSelectorTerm", - "description": "A null or empty node selector term matches no objects.", - "required": [ - "matchExpressions" - ], + "description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", "properties": { "matchExpressions": { "type": "array", "items": { "$ref": "v1.NodeSelectorRequirement" }, - "description": "Required. A list of node selector requirements. The requirements are ANDed." + "description": "A list of node selector requirements by node's labels." + }, + "matchFields": { + "type": "array", + "items": { + "$ref": "v1.NodeSelectorRequirement" + }, + "description": "A list of node selector requirements by node's fields." } } }, @@ -20302,6 +20360,13 @@ "dnsConfig": { "$ref": "v1.PodDNSConfig", "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." + }, + "readinessGates": { + "type": "array", + "items": { + "$ref": "v1.PodReadinessGate" + }, + "description": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md" } } }, @@ -20334,7 +20399,7 @@ }, "gitRepo": { "$ref": "v1.GitRepoVolumeSource", - "description": "GitRepo represents a git repository at a particular revision." + "description": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container." }, "secret": { "$ref": "v1.SecretVolumeSource", @@ -20442,7 +20507,7 @@ }, "v1.GitRepoVolumeSource": { "id": "v1.GitRepoVolumeSource", - "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "description": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "required": [ "repository" ], @@ -20670,6 +20735,31 @@ } } }, + "v1.CinderVolumeSource": { + "id": "v1.CinderVolumeSource", + "description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "required": [ + "volumeID" + ], + "properties": { + "volumeID": { + "type": "string", + "description": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "fsType": { + "type": "string", + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "readOnly": { + "type": "boolean", + "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" + }, + "secretRef": { + "$ref": "v1.LocalObjectReference", + "description": "Optional: points to a secret object containing parameters used to connect to OpenStack." + } + } + }, "v1.CephFSVolumeSource": { "id": "v1.CephFSVolumeSource", "description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", @@ -20872,6 +20962,10 @@ "configMap": { "$ref": "v1.ConfigMapProjection", "description": "information about the configMap data to project" + }, + "serviceAccountToken": { + "$ref": "v1.ServiceAccountTokenProjection", + "description": "information about the serviceAccountToken data to project" } } }, @@ -20930,6 +21024,28 @@ } } }, + "v1.ServiceAccountTokenProjection": { + "id": "v1.ServiceAccountTokenProjection", + "description": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "required": [ + "path" + ], + "properties": { + "audience": { + "type": "string", + "description": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver." + }, + "expirationSeconds": { + "type": "integer", + "format": "int64", + "description": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes." + }, + "path": { + "type": "string", + "description": "Path is the path relative to the mount point of the file to project the token into." + } + } + }, "v1.ScaleIOVolumeSource": { "id": "v1.ScaleIOVolumeSource", "description": "ScaleIOVolumeSource represents a persistent ScaleIO volume", @@ -21309,7 +21425,7 @@ }, "mountPropagation": { "$ref": "v1.MountPropagationMode", - "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10." + "description": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10." } } }, @@ -21609,6 +21725,31 @@ "type": "integer", "format": "int64", "description": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw " + }, + "sysctls": { + "type": "array", + "items": { + "$ref": "v1.Sysctl" + }, + "description": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch." + } + } + }, + "v1.Sysctl": { + "id": "v1.Sysctl", + "description": "Sysctl defines a kernel parameter to be set", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set" + }, + "value": { + "type": "string", + "description": "Value of a property to set" } } }, @@ -21833,13 +21974,26 @@ } } }, + "v1.PodReadinessGate": { + "id": "v1.PodReadinessGate", + "description": "PodReadinessGate contains the reference to a pod condition", + "required": [ + "conditionType" + ], + "properties": { + "conditionType": { + "type": "string", + "description": "ConditionType refers to a condition in the pod's condition list with matching type." + } + } + }, "v1.PodStatus": { "id": "v1.PodStatus", - "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system.", + "description": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system, especially if the node that hosts the pod cannot contact the control plane.", "properties": { "phase": { "type": "string", - "description": "Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase" + "description": "The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod's status. There are five possible phase values:\n\nPending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.\n\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase" }, "conditions": { "type": "array", @@ -21902,7 +22056,7 @@ "properties": { "type": { "type": "string", - "description": "Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions" + "description": "Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions" }, "status": { "type": "string", @@ -22403,7 +22557,7 @@ "properties": { "hard": { "type": "object", - "description": "Hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/" + "description": "hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/" }, "scopes": { "type": "array", @@ -22411,6 +22565,10 @@ "$ref": "v1.ResourceQuotaScope" }, "description": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects." + }, + "scopeSelector": { + "$ref": "v1.ScopeSelector", + "description": "scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota but expressed using ScopeSelectorOperator in combination with possible values. For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched." } } }, @@ -22418,6 +22576,44 @@ "id": "v1.ResourceQuotaScope", "properties": {} }, + "v1.ScopeSelector": { + "id": "v1.ScopeSelector", + "description": "A scope selector represents the AND of the selectors represented by the scoped-resource selector requirements.", + "properties": { + "matchExpressions": { + "type": "array", + "items": { + "$ref": "v1.ScopedResourceSelectorRequirement" + }, + "description": "A list of scope selector requirements by scope of the resources." + } + } + }, + "v1.ScopedResourceSelectorRequirement": { + "id": "v1.ScopedResourceSelectorRequirement", + "description": "A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.", + "required": [ + "scopeName", + "operator" + ], + "properties": { + "scopeName": { + "type": "string", + "description": "The name of the scope that the selector applies to." + }, + "operator": { + "type": "string", + "description": "Represents a scope's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist." + }, + "values": { + "type": "array", + "items": { + "type": "string" + }, + "description": "An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch." + } + } + }, "v1.ResourceQuotaStatus": { "id": "v1.ResourceQuotaStatus", "description": "ResourceQuotaStatus defines the enforced hard limits and observed use.", @@ -22668,7 +22864,7 @@ }, "publishNotReadyAddresses": { "type": "boolean", - "description": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery. This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints when that annotation is deprecated and all clients have been converted to use this field." + "description": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery." }, "sessionAffinityConfig": { "$ref": "v1.SessionAffinityConfig", diff --git a/vendor/k8s.io/kubernetes/build/BUILD b/vendor/k8s.io/kubernetes/build/BUILD index 8d3cdbba4..d325d7333 100644 --- a/vendor/k8s.io/kubernetes/build/BUILD +++ b/vendor/k8s.io/kubernetes/build/BUILD @@ -62,7 +62,7 @@ DOCKERIZED_BINARIES = { [docker_bundle( name = binary, - # TODO(thockin): remove the google_containers name after release 1.10. + # TODO(thockin): remove the google_containers name after release 1.11. images = { "k8s.gcr.io/%s:{STABLE_DOCKER_TAG}" % binary: binary + "-internal", "gcr.io/google_containers/%s:{STABLE_DOCKER_TAG}" % binary: binary + "-internal", diff --git a/vendor/k8s.io/kubernetes/build/README.md b/vendor/k8s.io/kubernetes/build/README.md index cd453e3cc..7983f19fc 100644 --- a/vendor/k8s.io/kubernetes/build/README.md +++ b/vendor/k8s.io/kubernetes/build/README.md @@ -5,8 +5,8 @@ Building Kubernetes is easy if you take advantage of the containerized build env ## Requirements 1. Docker, using one of the following configurations: - * **Mac OS X** You can either use Docker for Mac or docker-machine. See installation instructions [here](https://docs.docker.com/docker-for-mac/). - **Note**: You will want to set the Docker VM to have at least 3GB of initial memory or building will likely fail. (See: [#11852]( http://issue.k8s.io/11852)). + * **macOS** You can either use Docker for Mac or docker-machine. See installation instructions [here](https://docs.docker.com/docker-for-mac/). + **Note**: You will want to set the Docker VM to have at least 4.5GB of initial memory or building will likely fail. (See: [#11852]( http://issue.k8s.io/11852)). * **Linux with local Docker** Install Docker according to the [instructions](https://docs.docker.com/installation/#installation) for your OS. * **Remote Docker engine** Use a big machine in the cloud to build faster. This is a little trickier so look at the section later on. 2. **Optional** [Google Cloud SDK](https://developers.google.com/cloud/sdk/) @@ -107,4 +107,23 @@ In addition, there are some other tar files that are created: When building final release tars, they are first staged into `_output/release-stage` before being tar'd up and put into `_output/release-tars`. +## Reproducibility +`make release`, its variant `make quick-release`, and Bazel all provide a +hermetic build environment which should provide some level of reproducibility +for builds. `make` itself is **not** hermetic. + +The Kubernetes build environment supports the [`SOURCE_DATE_EPOCH` environment +variable](https://reproducible-builds.org/specs/source-date-epoch/) specified by +the Reproducible Builds project, which can be set to a UNIX epoch timestamp. +This will be used for the build timestamps embedded in compiled Go binaries, +and maybe someday also Docker images. + +One reasonable setting for this variable is to use the commit timestamp from the +tip of the tree being built; this is what the Kubernetes CI system uses. For +example, you could use the following one-liner: + +```bash +SOURCE_DATE_EPOCH=$(git show -s --format=format:%ct HEAD) +``` + [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/build/README.md?pixel)]() diff --git a/vendor/k8s.io/kubernetes/build/bindata.bzl b/vendor/k8s.io/kubernetes/build/bindata.bzl new file mode 100644 index 000000000..f21f42e57 --- /dev/null +++ b/vendor/k8s.io/kubernetes/build/bindata.bzl @@ -0,0 +1,45 @@ +# Copyright 2018 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. + +# Genrule wrapper around the go-bindata utility. +# IMPORTANT: Any changes to this rule may also require changes to hack/generate-bindata.sh. +def go_bindata( + name, srcs, outs, + compress=True, + include_metadata=True, + pkg="generated", + ignores=["\.jpg", "\.png", "\.md", "BUILD(\.bazel)?"], + **kw): + + args = [] + for ignore in ignores: + args.extend(["-ignore", "'%s'" % ignore]) + if not include_metadata: + args.append("-nometadata") + if not compress: + args.append("-nocompress") + + native.genrule( + name = name, + srcs = srcs, + outs = outs, + cmd = """ + $(location //vendor/github.com/jteeuwen/go-bindata/go-bindata:go-bindata) \ + -o "$@" -pkg %s -prefix $$(pwd) %s $(SRCS) + """ % (pkg, " ".join(args)), + tools = [ + "//vendor/github.com/jteeuwen/go-bindata/go-bindata", + ], + **kw + ) diff --git a/vendor/k8s.io/kubernetes/build/build-image/cross/Dockerfile b/vendor/k8s.io/kubernetes/build/build-image/cross/Dockerfile index 423e1d634..ac38a5432 100644 --- a/vendor/k8s.io/kubernetes/build/build-image/cross/Dockerfile +++ b/vendor/k8s.io/kubernetes/build/build-image/cross/Dockerfile @@ -15,7 +15,7 @@ # This file creates a standard build environment for building cross # platform go binary for the architecture kubernetes cares about. -FROM golang:1.9.3 +FROM golang:1.10.3 ENV GOARM 7 ENV KUBE_DYNAMIC_CROSSPLATFORMS \ @@ -71,7 +71,7 @@ RUN go get golang.org/x/tools/cmd/cover \ golang.org/x/tools/cmd/goimports # Download and symlink etcd. We need this for our integration tests. -RUN export ETCD_VERSION=v3.1.12; \ +RUN export ETCD_VERSION=v3.2.18; \ mkdir -p /usr/local/src/etcd \ && cd /usr/local/src/etcd \ && curl -fsSL https://github.com/coreos/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz | tar -xz \ diff --git a/vendor/k8s.io/kubernetes/build/build-image/cross/VERSION b/vendor/k8s.io/kubernetes/build/build-image/cross/VERSION index 034db155c..e5b424370 100644 --- a/vendor/k8s.io/kubernetes/build/build-image/cross/VERSION +++ b/vendor/k8s.io/kubernetes/build/build-image/cross/VERSION @@ -1 +1 @@ -v1.9.3-2 +v1.10.3-1 diff --git a/vendor/k8s.io/kubernetes/build/build-image/rsyncd.sh b/vendor/k8s.io/kubernetes/build/build-image/rsyncd.sh index ff155ded3..21546e59d 100755 --- a/vendor/k8s.io/kubernetes/build/build-image/rsyncd.sh +++ b/vendor/k8s.io/kubernetes/build/build-image/rsyncd.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/build/common.sh b/vendor/k8s.io/kubernetes/build/common.sh index fa5917570..383765cae 100755 --- a/vendor/k8s.io/kubernetes/build/common.sh +++ b/vendor/k8s.io/kubernetes/build/common.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -29,13 +29,13 @@ DOCKER_MACHINE_NAME=${DOCKER_MACHINE_NAME:-"kube-dev"} readonly DOCKER_MACHINE_DRIVER=${DOCKER_MACHINE_DRIVER:-"virtualbox --virtualbox-cpu-count -1"} # This will canonicalize the path -KUBE_ROOT=$(cd $(dirname "${BASH_SOURCE}")/.. && pwd -P) +KUBE_ROOT=$(cd "$(dirname "${BASH_SOURCE}")"/.. && pwd -P) source "${KUBE_ROOT}/hack/lib/init.sh" # Constants readonly KUBE_BUILD_IMAGE_REPO=kube-build -readonly KUBE_BUILD_IMAGE_CROSS_TAG="$(cat ${KUBE_ROOT}/build/build-image/cross/VERSION)" +readonly KUBE_BUILD_IMAGE_CROSS_TAG="$(cat "${KUBE_ROOT}/build/build-image/cross/VERSION")" # This version number is used to cause everyone to rebuild their data containers # and build image. This is especially useful for automated build systems like @@ -43,7 +43,7 @@ readonly KUBE_BUILD_IMAGE_CROSS_TAG="$(cat ${KUBE_ROOT}/build/build-image/cross/ # # Increment/change this number if you change the build image (anything under # build/build-image) or change the set of volumes in the data container. -readonly KUBE_BUILD_IMAGE_VERSION_BASE="$(cat ${KUBE_ROOT}/build/build-image/VERSION)" +readonly KUBE_BUILD_IMAGE_VERSION_BASE="$(cat "${KUBE_ROOT}/build/build-image/VERSION")" readonly KUBE_BUILD_IMAGE_VERSION="${KUBE_BUILD_IMAGE_VERSION_BASE}-${KUBE_BUILD_IMAGE_CROSS_TAG}" # Here we map the output directories across both the local and remote _output @@ -232,7 +232,7 @@ function kube::build::prepare_docker_machine() { docker-machine inspect "${DOCKER_MACHINE_NAME}" &> /dev/null || { kube::log::status "Creating a machine to build Kubernetes" - docker-machine create --driver ${DOCKER_MACHINE_DRIVER} \ + docker-machine create --driver "${DOCKER_MACHINE_DRIVER}" \ --virtualbox-memory "${virtualbox_memory_mb}" \ --engine-env HTTP_PROXY="${KUBERNETES_HTTP_PROXY:-}" \ --engine-env HTTPS_PROXY="${KUBERNETES_HTTPS_PROXY:-}" \ @@ -249,13 +249,13 @@ function kube::build::prepare_docker_machine() { local docker_machine_out while ! docker_machine_out=$(docker-machine env "${DOCKER_MACHINE_NAME}" 2>&1); do if [[ ${docker_machine_out} =~ "Error checking TLS connection" ]]; then - echo ${docker_machine_out} + echo "${docker_machine_out}" docker-machine regenerate-certs ${DOCKER_MACHINE_NAME} else sleep 1 fi done - eval $(docker-machine env "${DOCKER_MACHINE_NAME}") + eval "$(docker-machine env "${DOCKER_MACHINE_NAME}")" kube::log::status "A Docker host using docker-machine named '${DOCKER_MACHINE_NAME}' is ready to go!" return 0 } @@ -354,7 +354,7 @@ function kube::build::docker_image_exists() { function kube::build::docker_delete_old_images() { # In Docker 1.12, we can replace this with # docker images "$1" --format "{{.Tag}}" - for tag in $("${DOCKER[@]}" images ${1} | tail -n +2 | awk '{print $2}') ; do + for tag in $("${DOCKER[@]}" images "${1}" | tail -n +2 | awk '{print $2}') ; do if [[ "${tag}" != "${2}"* ]] ; then V=3 kube::log::status "Keeping image ${1}:${tag}" continue @@ -434,7 +434,7 @@ function kube::build::clean() { kube::build::docker_delete_old_images "${KUBE_BUILD_IMAGE_REPO}" "${KUBE_BUILD_IMAGE_TAG_BASE}" V=2 kube::log::status "Cleaning all untagged docker images" - "${DOCKER[@]}" rmi $("${DOCKER[@]}" images -q --filter 'dangling=true') 2> /dev/null || true + "${DOCKER[@]}" rmi "$("${DOCKER[@]}" images -q --filter 'dangling=true')" 2> /dev/null || true fi if [[ -d "${LOCAL_OUTPUT_ROOT}" ]]; then @@ -451,8 +451,8 @@ function kube::build::build_image() { cp /etc/localtime "${LOCAL_OUTPUT_BUILD_CONTEXT}/" - cp ${KUBE_ROOT}/build/build-image/Dockerfile "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile" - cp ${KUBE_ROOT}/build/build-image/rsyncd.sh "${LOCAL_OUTPUT_BUILD_CONTEXT}/" + cp "${KUBE_ROOT}/build/build-image/Dockerfile" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile" + cp "${KUBE_ROOT}/build/build-image/rsyncd.sh" "${LOCAL_OUTPUT_BUILD_CONTEXT}/" dd if=/dev/urandom bs=512 count=1 2>/dev/null | LC_ALL=C tr -dc 'A-Za-z0-9' | dd bs=32 count=1 2>/dev/null > "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password" chmod go= "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password" diff --git a/vendor/k8s.io/kubernetes/build/copy-output.sh b/vendor/k8s.io/kubernetes/build/copy-output.sh index 842cf0a5f..8b1892243 100755 --- a/vendor/k8s.io/kubernetes/build/copy-output.sh +++ b/vendor/k8s.io/kubernetes/build/copy-output.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/build/debs/10-kubeadm.conf b/vendor/k8s.io/kubernetes/build/debs/10-kubeadm.conf index f2974f904..bd1b077f3 100644 --- a/vendor/k8s.io/kubernetes/build/debs/10-kubeadm.conf +++ b/vendor/k8s.io/kubernetes/build/debs/10-kubeadm.conf @@ -1,13 +1,11 @@ +# Note: This dropin only works with kubeadm and kubelet v1.11+ [Service] Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" -Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true" -Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin" -Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local" -Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt" -# Value should match Docker daemon settings. -# Defaults are "cgroupfs" for Debian/Ubuntu/OpenSUSE and "systemd" for Fedora/CentOS/RHEL -Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs" -Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0" -Environment="KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true" +Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" +# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically +EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env +# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use +# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file. +EnvironmentFile=-/etc/default/kubelet ExecStart= -ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS +ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS diff --git a/vendor/k8s.io/kubernetes/build/debs/BUILD b/vendor/k8s.io/kubernetes/build/debs/BUILD index 31700d045..1280e46d7 100644 --- a/vendor/k8s.io/kubernetes/build/debs/BUILD +++ b/vendor/k8s.io/kubernetes/build/debs/BUILD @@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"]) load("@io_kubernetes_build//defs:deb.bzl", "k8s_deb", "deb_data") load("@io_kubernetes_build//defs:build.bzl", "release_filegroup") load("@io_kubernetes_build//defs:pkg.bzl", "pkg_tar") +load("//build:workspace.bzl", "CRI_TOOLS_VERSION") # We do not include kube-scheduler, kube-controller-manager, # kube-apiserver, and kube-proxy in this list even though we @@ -13,6 +14,7 @@ release_filegroup( name = "debs", srcs = [ ":cloud-controller-manager.deb", + ":cri-tools.deb", ":kubeadm.deb", ":kubectl.deb", ":kubelet.deb", @@ -86,6 +88,12 @@ pkg_tar( deps = ["@kubernetes_cni//file"], ) +pkg_tar( + name = "cri-tools-data", + package_dir = "/usr/bin", + deps = ["@cri_tools//file"], +) + k8s_deb( name = "cloud-controller-manager", description = "Kubernetes Cloud Controller Manager", @@ -156,6 +164,7 @@ k8s_deb( description = """Kubernetes Cluster Bootstrapping Tool The Kubernetes command line tool for bootstrapping a Kubernetes cluster. """, + postinst = "postinst", version_file = "//build:os_package_version", ) @@ -167,6 +176,12 @@ The Container Networking Interface tools for provisioning container networks. version_file = "//build:cni_package_version", ) +k8s_deb( + name = "cri-tools", + description = """Container Runtime Interface tools (crictl)""", + version = CRI_TOOLS_VERSION, +) + filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/vendor/k8s.io/kubernetes/build/debs/postinst b/vendor/k8s.io/kubernetes/build/debs/postinst new file mode 100644 index 000000000..30a396bb1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/build/debs/postinst @@ -0,0 +1,30 @@ +#!/bin/sh +# see: dh_installdeb(1) + +set -o errexit +set -o nounset + +case "$1" in + configure) + # because kubeadm package adds kubelet drop-ins, we must daemon-reload + # and restart kubelet now. restarting kubelet is ok because kubelet + # postinst configure step auto-starts it. + systemctl daemon-reload 2>/dev/null || true + systemctl restart kubelet 2>/dev/null || true + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/build/lib/release.sh b/vendor/k8s.io/kubernetes/build/lib/release.sh index f3e1c9b31..004cab5b0 100644 --- a/vendor/k8s.io/kubernetes/build/lib/release.sh +++ b/vendor/k8s.io/kubernetes/build/lib/release.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -67,9 +67,9 @@ function kube::release::parse_and_validate_ci_version() { # Build final release artifacts function kube::release::clean_cruft() { # Clean out cruft - find ${RELEASE_STAGE} -name '*~' -exec rm {} \; - find ${RELEASE_STAGE} -name '#*#' -exec rm {} \; - find ${RELEASE_STAGE} -name '.DS*' -exec rm {} \; + find "${RELEASE_STAGE}" -name '*~' -exec rm {} \; + find "${RELEASE_STAGE}" -name '#*#' -exec rm {} \; + find "${RELEASE_STAGE}" -name '.DS*' -exec rm {} \; } function kube::release::package_tarballs() { @@ -154,7 +154,7 @@ function kube::release::package_node_tarballs() { local platform for platform in "${KUBE_NODE_PLATFORMS[@]}"; do local platform_tag=${platform/\//-} # Replace a "/" for a "-" - local arch=$(basename ${platform}) + local arch=$(basename "${platform}") kube::log::status "Building tarball: node $platform_tag" local release_stage="${RELEASE_STAGE}/node/${platform_tag}/kubernetes" @@ -198,7 +198,7 @@ function kube::release::package_server_tarballs() { local platform for platform in "${KUBE_SERVER_PLATFORMS[@]}"; do local platform_tag=${platform/\//-} # Replace a "/" for a "-" - local arch=$(basename ${platform}) + local arch=$(basename "${platform}") kube::log::status "Building tarball: server $platform_tag" local release_stage="${RELEASE_STAGE}/server/${platform_tag}/kubernetes" @@ -280,12 +280,12 @@ function kube::release::create_docker_images_for_server() { local binary_dir="$1" local arch="$2" local binary_name - local binaries=($(kube::build::get_docker_wrapped_binaries ${arch})) + local binaries=($(kube::build::get_docker_wrapped_binaries "${arch}")) local images_dir="${RELEASE_IMAGES}/${arch}" mkdir -p "${images_dir}" local -r docker_registry="k8s.gcr.io" - # TODO(thockin): Remove all traces of this after 1.10 release. + # TODO(thockin): Remove all traces of this after 1.11 release. # The following is the old non-indirected registry name. To ease the # transition to the new name (above), we are double-tagging saved images. local -r deprecated_registry="gcr.io/google_containers" @@ -325,16 +325,16 @@ function kube::release::create_docker_images_for_server() { kube::log::status "Starting docker build for image: ${binary_name}-${arch}" ( - rm -rf ${docker_build_path} - mkdir -p ${docker_build_path} - ln ${binary_dir}/${binary_name} ${docker_build_path}/${binary_name} - printf " FROM ${base_image} \n ADD ${binary_name} /usr/local/bin/${binary_name}\n" > ${docker_file_path} - - "${DOCKER[@]}" build --pull -q -t "${docker_image_tag}" ${docker_build_path} >/dev/null - "${DOCKER[@]}" tag "${docker_image_tag}" ${deprecated_image_tag} >/dev/null - "${DOCKER[@]}" save "${docker_image_tag}" ${deprecated_image_tag} > "${binary_dir}/${binary_name}.tar" - echo "${docker_tag}" > ${binary_dir}/${binary_name}.docker_tag - rm -rf ${docker_build_path} + rm -rf "${docker_build_path}" + mkdir -p "${docker_build_path}" + ln "${binary_dir}/${binary_name}" "${docker_build_path}/${binary_name}" + printf " FROM ${base_image} \n ADD ${binary_name} /usr/local/bin/${binary_name}\n" > "${docker_file_path}" + + "${DOCKER[@]}" build --pull -q -t "${docker_image_tag}" "${docker_build_path}" >/dev/null + "${DOCKER[@]}" tag "${docker_image_tag}" "${deprecated_image_tag}" >/dev/null + "${DOCKER[@]}" save "${docker_image_tag}" "${deprecated_image_tag}" > "${binary_dir}/${binary_name}.tar" + echo "${docker_tag}" > "${binary_dir}/${binary_name}.docker_tag" + rm -rf "${docker_build_path}" ln "${binary_dir}/${binary_name}.tar" "${images_dir}/" # If we are building an official/alpha/beta release we want to keep @@ -350,8 +350,8 @@ function kube::release::create_docker_images_for_server() { else # not a release kube::log::status "Deleting docker image ${docker_image_tag}" - "${DOCKER[@]}" rmi ${docker_image_tag} &>/dev/null || true - "${DOCKER[@]}" rmi ${deprecated_image_tag} &>/dev/null || true + "${DOCKER[@]}" rmi "${docker_image_tag}" &>/dev/null || true + "${DOCKER[@]}" rmi "${deprecated_image_tag}" &>/dev/null || true fi ) & done @@ -382,6 +382,7 @@ function kube::release::package_kube_manifests_tarball() { cp "${src_dir}/cluster-autoscaler.manifest" "${dst_dir}/" cp "${src_dir}/etcd.manifest" "${dst_dir}" cp "${src_dir}/kube-scheduler.manifest" "${dst_dir}" + cp "${src_dir}/kms-plugin-container.manifest" "${dst_dir}" cp "${src_dir}/kube-apiserver.manifest" "${dst_dir}" cp "${src_dir}/abac-authz-policy.jsonl" "${dst_dir}" cp "${src_dir}/kube-controller-manager.manifest" "${dst_dir}" @@ -389,7 +390,15 @@ function kube::release::package_kube_manifests_tarball() { cp "${src_dir}/glbc.manifest" "${dst_dir}" cp "${src_dir}/rescheduler.manifest" "${dst_dir}/" cp "${src_dir}/e2e-image-puller.manifest" "${dst_dir}/" + cp "${src_dir}/etcd-empty-dir-cleanup.yaml" "${dst_dir}/" + local internal_manifest + for internal_manifest in $(ls "${src_dir}" | grep "^internal-*"); do + cp "${src_dir}/${internal_manifest}" "${dst_dir}" + done cp "${KUBE_ROOT}/cluster/gce/gci/configure-helper.sh" "${dst_dir}/gci-configure-helper.sh" + if [[ -e "${KUBE_ROOT}/cluster/gce/gci/gke-internal-configure-helper.sh" ]]; then + cp "${KUBE_ROOT}/cluster/gce/gci/gke-internal-configure-helper.sh" "${dst_dir}/" + fi cp "${KUBE_ROOT}/cluster/gce/gci/health-monitor.sh" "${dst_dir}/health-monitor.sh" local objects objects=$(cd "${KUBE_ROOT}/cluster/addons" && find . \( -name \*.yaml -or -name \*.yaml.in -or -name \*.json \) | grep -v demo) @@ -434,7 +443,7 @@ function kube::release::package_test_tarball() { # Add the test image files mkdir -p "${release_stage}/test/images" cp -fR "${KUBE_ROOT}/test/images" "${release_stage}/test/" - tar c ${KUBE_TEST_PORTABLE[@]} | tar x -C ${release_stage} + tar c "${KUBE_TEST_PORTABLE[@]}" | tar x -C "${release_stage}" kube::release::clean_cruft @@ -477,14 +486,10 @@ Server binary tarballs are no longer included in the Kubernetes final tarball. Run cluster/get-kube-binaries.sh to download client and server binaries. EOF - mkdir -p "${release_stage}/third_party" - cp -R "${KUBE_ROOT}/third_party/htpasswd" "${release_stage}/third_party/htpasswd" - # Include hack/lib as a dependency for the cluster/ scripts mkdir -p "${release_stage}/hack" cp -R "${KUBE_ROOT}/hack/lib" "${release_stage}/hack/" - cp -R "${KUBE_ROOT}/examples" "${release_stage}/" cp -R "${KUBE_ROOT}/docs" "${release_stage}/" cp "${KUBE_ROOT}/README.md" "${release_stage}/" cp "${KUBE_ROOT}/Godeps/LICENSES" "${release_stage}/" diff --git a/vendor/k8s.io/kubernetes/build/make-build-image.sh b/vendor/k8s.io/kubernetes/build/make-build-image.sh index d4b69605c..8ad0e3bbd 100755 --- a/vendor/k8s.io/kubernetes/build/make-build-image.sh +++ b/vendor/k8s.io/kubernetes/build/make-build-image.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/build/make-clean.sh b/vendor/k8s.io/kubernetes/build/make-clean.sh index 8d82dfaaf..af59f33d1 100755 --- a/vendor/k8s.io/kubernetes/build/make-clean.sh +++ b/vendor/k8s.io/kubernetes/build/make-clean.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/build/package-tarballs.sh b/vendor/k8s.io/kubernetes/build/package-tarballs.sh index 3fa5cad2d..9432015b8 100755 --- a/vendor/k8s.io/kubernetes/build/package-tarballs.sh +++ b/vendor/k8s.io/kubernetes/build/package-tarballs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/vendor/k8s.io/kubernetes/build/release-in-a-container.sh b/vendor/k8s.io/kubernetes/build/release-in-a-container.sh index 46dab711f..a160fe927 100755 --- a/vendor/k8s.io/kubernetes/build/release-in-a-container.sh +++ b/vendor/k8s.io/kubernetes/build/release-in-a-container.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/vendor/k8s.io/kubernetes/build/release-tars/BUILD b/vendor/k8s.io/kubernetes/build/release-tars/BUILD index 42d7beeb6..e9f379a7d 100644 --- a/vendor/k8s.io/kubernetes/build/release-tars/BUILD +++ b/vendor/k8s.io/kubernetes/build/release-tars/BUILD @@ -193,9 +193,7 @@ pkg_tar( "//:version", "//cluster:all-srcs", "//docs:all-srcs", - "//examples:all-srcs", "//hack/lib:all-srcs", - "//third_party/htpasswd:all-srcs", ], extension = "tar.gz", package_dir = "kubernetes", diff --git a/vendor/k8s.io/kubernetes/build/release.sh b/vendor/k8s.io/kubernetes/build/release.sh index 63d201c47..9e7876b46 100755 --- a/vendor/k8s.io/kubernetes/build/release.sh +++ b/vendor/k8s.io/kubernetes/build/release.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/build/root/.bazelrc b/vendor/k8s.io/kubernetes/build/root/.bazelrc index 6c22f3572..4a7dcbb57 100644 --- a/vendor/k8s.io/kubernetes/build/root/.bazelrc +++ b/vendor/k8s.io/kubernetes/build/root/.bazelrc @@ -15,6 +15,7 @@ build --sandbox_tmpfs_path=/tmp build --sandbox_fake_username # Enable go race detection. +build:unit --features=race test:unit --features=race test:unit --test_tag_filters=-e2e,-integration test:unit --flaky_test_attempts=3 diff --git a/vendor/k8s.io/kubernetes/build/root/.kazelcfg.json b/vendor/k8s.io/kubernetes/build/root/.kazelcfg.json index 3d5d1a1ed..fae9ddd5f 100644 --- a/vendor/k8s.io/kubernetes/build/root/.kazelcfg.json +++ b/vendor/k8s.io/kubernetes/build/root/.kazelcfg.json @@ -1,7 +1,9 @@ { "GoPrefix": "k8s.io/kubernetes", "SkippedPaths": [ - "^_.*" + "^_.*", + "/_", + "^third_party/etcd.*" ], "AddSourcesRules": true, "K8sOpenAPIGen": true diff --git a/vendor/k8s.io/kubernetes/build/root/BUILD.root b/vendor/k8s.io/kubernetes/build/root/BUILD.root index 69ec9e685..2de430729 100644 --- a/vendor/k8s.io/kubernetes/build/root/BUILD.root +++ b/vendor/k8s.io/kubernetes/build/root/BUILD.root @@ -58,18 +58,19 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//api:all-srcs", + "//api/openapi-spec:all-srcs", + "//api/swagger-spec:all-srcs", "//build:all-srcs", "//cluster:all-srcs", "//cmd:all-srcs", "//docs:all-srcs", - "//examples:all-srcs", "//hack:all-srcs", "//pkg:all-srcs", "//plugin:all-srcs", "//staging:all-srcs", "//test:all-srcs", "//third_party:all-srcs", + "//translations:all-srcs", "//vendor:all-srcs", ], tags = ["automanaged"], diff --git a/vendor/k8s.io/kubernetes/build/root/Makefile b/vendor/k8s.io/kubernetes/build/root/Makefile index 143140d83..c7e16e90e 100644 --- a/vendor/k8s.io/kubernetes/build/root/Makefile +++ b/vendor/k8s.io/kubernetes/build/root/Makefile @@ -251,7 +251,7 @@ define TEST_E2E_NODE_HELP_INFO # GUBERNATOR: For REMOTE=true only. Produce link to Gubernator to view logs. # Defaults to false. # PARALLELISM: The number of gingko nodes to run. Defaults to 8. -# RUNTIME: Container runtime to use (eg. docker, rkt, remote). +# RUNTIME: Container runtime to use (eg. docker, remote). # Defaults to "docker". # CONTAINER_RUNTIME_ENDPOINT: remote container endpoint to connect to. # Used when RUNTIME is set to "remote". diff --git a/vendor/k8s.io/kubernetes/build/root/Makefile.generated_files b/vendor/k8s.io/kubernetes/build/root/Makefile.generated_files index 066da2daa..59372a0c3 100644 --- a/vendor/k8s.io/kubernetes/build/root/Makefile.generated_files +++ b/vendor/k8s.io/kubernetes/build/root/Makefile.generated_files @@ -35,7 +35,7 @@ SHELL := /bin/bash # This rule collects all the generated file sets into a single rule. Other # rules should depend on this to ensure generated files are rebuilt. .PHONY: generated_files -generated_files: gen_deepcopy gen_defaulter gen_conversion gen_openapi +generated_files: gen_deepcopy gen_defaulter gen_conversion gen_openapi gen_bindata .PHONY: verify_generated_files verify_generated_files: verify_gen_deepcopy \ @@ -486,110 +486,6 @@ $(DEFAULTER_GEN): hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/defaulter-gen touch $@ -# -# Open-api generation -# -# Any package that wants open-api functions generated must include a -# comment-tag in column 0 of one file of the form: -# // +k8s:openapi-gen=true -# -# The result file, in each pkg, of open-api generation. -OPENAPI_BASENAME := $(GENERATED_FILE_PREFIX)openapi -OPENAPI_FILENAME := $(OPENAPI_BASENAME).go -OPENAPI_OUTPUT_PKG := pkg/generated/openapi - -# The tool used to generate open apis. -OPENAPI_GEN := $(BIN_DIR)/openapi-gen - -# Find all the directories that request open-api generation. -ifeq ($(DBG_MAKEFILE),1) - $(warning ***** finding all +k8s:openapi-gen tags) -endif -OPENAPI_DIRS := $(shell \ - grep --color=never -l '+k8s:openapi-gen=' $(ALL_K8S_TAG_FILES) \ - | xargs -n1 dirname \ - | LC_ALL=C sort -u \ -) - -OPENAPI_OUTFILE := $(OPENAPI_OUTPUT_PKG)/$(OPENAPI_FILENAME) - -# This rule is the user-friendly entrypoint for openapi generation. -.PHONY: gen_openapi -gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN) - -# For each dir in OPENAPI_DIRS, this establishes a dependency between the -# output file and the input files that should trigger a rebuild. -# -# Note that this is a deps-only statement, not a full rule (see below). This -# has to be done in a distinct step because wildcards don't work in static -# pattern rules. -# -# The '$(eval)' is needed because this has a different RHS for each LHS, and -# would otherwise produce results that make can't parse. -# -# We depend on the $(GOFILES_META).stamp to detect when the set of input files -# has changed. This allows us to detect deleted input files. -$(foreach dir, $(OPENAPI_DIRS), $(eval \ - $(OPENAPI_OUTFILE): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \ - $(gofiles__$(dir)) \ -)) - -# How to regenerate open-api code. This emits a single file for all results. -$(OPENAPI_OUTFILE): $(OPENAPI_GEN) $(OPENAPI_GEN) - function run_gen_openapi() { \ - ./hack/run-in-gopath.sh $(OPENAPI_GEN) \ - --v $(KUBE_VERBOSE) \ - --logtostderr \ - -i $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(OPENAPI_DIRS)) | sed 's/ /,/g') \ - -p $(PRJ_SRC_PATH)/$(OPENAPI_OUTPUT_PKG) \ - -O $(OPENAPI_BASENAME) \ - "$$@"; \ - }; \ - run_gen_openapi - -# This calculates the dependencies for the generator tool, so we only rebuild -# it when needed. It is PHONY so that it always runs, but it only updates the -# file if the contents have actually changed. We 'sinclude' this later. -.PHONY: $(META_DIR)/$(OPENAPI_GEN).mk -$(META_DIR)/$(OPENAPI_GEN).mk: - mkdir -p $(@D); \ - (echo -n "$(OPENAPI_GEN): "; \ - ./hack/run-in-gopath.sh go list \ - -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \ - ./vendor/k8s.io/code-generator/cmd/openapi-gen \ - | grep --color=never "^$(PRJ_SRC_PATH)/" \ - | xargs ./hack/run-in-gopath.sh go list \ - -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \ - | paste -sd' ' - \ - | sed 's/ / \\=,/g' \ - | tr '=,' '\n\t' \ - | sed "s|$$(pwd -P)/||"; \ - ) > $@.tmp; \ - if ! cmp -s $@.tmp $@; then \ - if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ - echo "DBG: $(OPENAPI_GEN).mk changed"; \ - fi; \ - cat $@.tmp > $@; \ - rm -f $@.tmp; \ - fi - -# Include dependency info for the generator tool. This will cause the rule of -# the same name to be considered and if it is updated, make will restart. -sinclude $(META_DIR)/$(OPENAPI_GEN).mk - -# How to build the generator tool. The deps for this are defined in -# the $(OPENAPI_GEN).mk, above. -# -# A word on the need to touch: This rule might trigger if, for example, a -# non-Go file was added or deleted from a directory on which this depends. -# This target needs to be reconsidered, but Go realizes it doesn't actually -# have to be rebuilt. In that case, make will forever see the dependency as -# newer than the binary, and try to rebuild it over and over. So we touch it, -# and make is happy. -$(OPENAPI_GEN): - hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/openapi-gen - touch $@ - # # Conversion generation # @@ -805,3 +701,168 @@ sinclude $(META_DIR)/$(CONVERSION_GEN).mk $(CONVERSION_GEN): hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/conversion-gen touch $@ + +# +# Open-api generation +# +# Any package that wants open-api functions generated must include a +# comment-tag in column 0 of one file of the form: +# // +k8s:openapi-gen=true +# +# The result file, in each pkg, of open-api generation. +OPENAPI_BASENAME := $(GENERATED_FILE_PREFIX)openapi +OPENAPI_FILENAME := $(OPENAPI_BASENAME).go +OPENAPI_OUTPUT_PKG := pkg/generated/openapi + +# The tool used to generate open apis. +OPENAPI_GEN := $(BIN_DIR)/openapi-gen + +# Find all the directories that request open-api generation. +ifeq ($(DBG_MAKEFILE),1) + $(warning ***** finding all +k8s:openapi-gen tags) +endif +OPENAPI_DIRS := $(shell \ + grep --color=never -l '+k8s:openapi-gen=' $(ALL_K8S_TAG_FILES) \ + | xargs -n1 dirname \ + | LC_ALL=C sort -u \ +) + +OPENAPI_OUTFILE := $(OPENAPI_OUTPUT_PKG)/$(OPENAPI_FILENAME) + +# This rule is the user-friendly entrypoint for openapi generation. +.PHONY: gen_openapi +gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN) + +# For each dir in OPENAPI_DIRS, this establishes a dependency between the +# output file and the input files that should trigger a rebuild. +# +# Note that this is a deps-only statement, not a full rule (see below). This +# has to be done in a distinct step because wildcards don't work in static +# pattern rules. +# +# The '$(eval)' is needed because this has a different RHS for each LHS, and +# would otherwise produce results that make can't parse. +# +# We depend on the $(GOFILES_META).stamp to detect when the set of input files +# has changed. This allows us to detect deleted input files. +$(foreach dir, $(OPENAPI_DIRS), $(eval \ + $(OPENAPI_OUTFILE): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \ + $(gofiles__$(dir)) \ +)) + +# How to regenerate open-api code. This emits a single file for all results. +$(OPENAPI_OUTFILE): $(OPENAPI_GEN) $(OPENAPI_GEN) + function run_gen_openapi() { \ + ./hack/run-in-gopath.sh $(OPENAPI_GEN) \ + --v $(KUBE_VERBOSE) \ + --logtostderr \ + -i $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(OPENAPI_DIRS)) | sed 's/ /,/g') \ + -p $(PRJ_SRC_PATH)/$(OPENAPI_OUTPUT_PKG) \ + -O $(OPENAPI_BASENAME) \ + "$$@"; \ + }; \ + run_gen_openapi + +# This calculates the dependencies for the generator tool, so we only rebuild +# it when needed. It is PHONY so that it always runs, but it only updates the +# file if the contents have actually changed. We 'sinclude' this later. +.PHONY: $(META_DIR)/$(OPENAPI_GEN).mk +$(META_DIR)/$(OPENAPI_GEN).mk: + mkdir -p $(@D); \ + (echo -n "$(OPENAPI_GEN): "; \ + ./hack/run-in-gopath.sh go list \ + -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \ + ./vendor/k8s.io/code-generator/cmd/openapi-gen \ + | grep --color=never "^$(PRJ_SRC_PATH)/" \ + | xargs ./hack/run-in-gopath.sh go list \ + -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \ + | paste -sd' ' - \ + | sed 's/ / \\=,/g' \ + | tr '=,' '\n\t' \ + | sed "s|$$(pwd -P)/||"; \ + ) > $@.tmp; \ + if ! cmp -s $@.tmp $@; then \ + if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ + echo "DBG: $(OPENAPI_GEN).mk changed"; \ + fi; \ + cat $@.tmp > $@; \ + rm -f $@.tmp; \ + fi + +# Include dependency info for the generator tool. This will cause the rule of +# the same name to be considered and if it is updated, make will restart. +sinclude $(META_DIR)/$(OPENAPI_GEN).mk + +# How to build the generator tool. The deps for this are defined in +# the $(OPENAPI_GEN).mk, above. +# +# A word on the need to touch: This rule might trigger if, for example, a +# non-Go file was added or deleted from a directory on which this depends. +# This target needs to be reconsidered, but Go realizes it doesn't actually +# have to be rebuilt. In that case, make will forever see the dependency as +# newer than the binary, and try to rebuild it over and over. So we touch it, +# and make is happy. +$(OPENAPI_GEN): + hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/openapi-gen + touch $@ + +# +# bindata generation +# + +# The tool used to generate bindata files. +BINDATA_GEN := $(BIN_DIR)/go-bindata + +# A wrapper script that generates all bindata files. It is fast enough that we +# don't care. +BINDATA_SCRIPT := hack/generate-bindata.sh + +# This rule is the user-friendly entrypoint for bindata generation. +.PHONY: gen_bindata +gen_bindata: $(BINDATA_GEN) FORCE + ./hack/run-in-gopath.sh $(BINDATA_SCRIPT) + +FORCE: + +# This calculates the dependencies for the generator tool, so we only rebuild +# it when needed. It is PHONY so that it always runs, but it only updates the +# file if the contents have actually changed. We 'sinclude' this later. +.PHONY: $(META_DIR)/$(BINDATA_GEN).mk +$(META_DIR)/$(BINDATA_GEN).mk: + mkdir -p $(@D); \ + (echo -n "$(BINDATA_GEN): "; \ + ./hack/run-in-gopath.sh go list \ + -f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \ + ./vendor/github.com/jteeuwen/go-bindata/go-bindata \ + | grep --color=never "^$(PRJ_SRC_PATH)/" \ + | xargs ./hack/run-in-gopath.sh go list \ + -f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \ + | paste -sd' ' - \ + | sed 's/ / \\=,/g' \ + | tr '=,' '\n\t' \ + | sed "s|$$(pwd -P)/||"; \ + ) > $@.tmp; \ + if ! cmp -s $@.tmp $@; then \ + if [[ "$(DBG_CODEGEN)" == 1 ]]; then \ + echo "DBG: $(BINDATA_GEN).mk changed"; \ + fi; \ + cat $@.tmp > $@; \ + rm -f $@.tmp; \ + fi + +# Include dependency info for the generator tool. This will cause the rule of +# the same name to be considered and if it is updated, make will restart. +sinclude $(META_DIR)/$(BINDATA_GEN).mk + +# How to build the generator tool. The deps for this are defined in +# the $(BINDATA_GEN).mk, above. +# +# A word on the need to touch: This rule might trigger if, for example, a +# non-Go file was added or deleted from a directory on which this depends. +# This target needs to be reconsidered, but Go realizes it doesn't actually +# have to be rebuilt. In that case, make will forever see the dependency as +# newer than the binary, and try to rebuild it over and over. So we touch it, +# and make is happy. +$(BINDATA_GEN): + hack/make-rules/build.sh ./vendor/github.com/jteeuwen/go-bindata/go-bindata + touch $@ diff --git a/vendor/k8s.io/kubernetes/build/root/WORKSPACE b/vendor/k8s.io/kubernetes/build/root/WORKSPACE index 3d9a87c6c..f2d8cd915 100644 --- a/vendor/k8s.io/kubernetes/build/root/WORKSPACE +++ b/vendor/k8s.io/kubernetes/build/root/WORKSPACE @@ -1,52 +1,54 @@ +load("//build:workspace_mirror.bzl", "mirror") +load("//build:workspace.bzl", "CRI_TOOLS_VERSION") + http_archive( name = "io_bazel_rules_go", - sha256 = "66282d078c1847c2d876c02c5dabd4fd57cc75eb41a9668a2374352fa73b4587", - strip_prefix = "rules_go-ff7e3364d9383cf14155f8c2efc87218d07eb03b", - urls = ["https://github.com/bazelbuild/rules_go/archive/ff7e3364d9383cf14155f8c2efc87218d07eb03b.tar.gz"], + sha256 = "242602c9818a83cbe97d1446b48263dcd48949a74d713c172d1b03da841b168a", + urls = mirror("https://github.com/bazelbuild/rules_go/releases/download/0.10.5/rules_go-0.10.5.tar.gz"), ) http_archive( name = "io_kubernetes_build", sha256 = "007774f06536059f3f782d1a092bddc625d88c17f20bbe731cea844a52485b11", strip_prefix = "repo-infra-97099dccc8807e9159dc28f374a8f0602cab07e1", - urls = ["https://github.com/kubernetes/repo-infra/archive/97099dccc8807e9159dc28f374a8f0602cab07e1.tar.gz"], + urls = mirror("https://github.com/kubernetes/repo-infra/archive/97099dccc8807e9159dc28f374a8f0602cab07e1.tar.gz"), ) http_archive( name = "bazel_skylib", sha256 = "bbccf674aa441c266df9894182d80de104cabd19be98be002f6d478aaa31574d", strip_prefix = "bazel-skylib-2169ae1c374aab4a09aa90e65efe1a3aad4e279b", - urls = ["https://github.com/bazelbuild/bazel-skylib/archive/2169ae1c374aab4a09aa90e65efe1a3aad4e279b.tar.gz"], + urls = mirror("https://github.com/bazelbuild/bazel-skylib/archive/2169ae1c374aab4a09aa90e65efe1a3aad4e279b.tar.gz"), ) -ETCD_VERSION = "3.1.12" +ETCD_VERSION = "3.2.18" new_http_archive( name = "com_coreos_etcd", build_file = "third_party/etcd.BUILD", - sha256 = "4b22184bef1bba8b4908b14bae6af4a6d33ec2b91e4f7a240780e07fa43f2111", + sha256 = "b729db0732448064271ea6fdcb901773c4fe917763ca07776f22d0e5e0bd4097", strip_prefix = "etcd-v%s-linux-amd64" % ETCD_VERSION, - urls = ["https://github.com/coreos/etcd/releases/download/v%s/etcd-v%s-linux-amd64.tar.gz" % (ETCD_VERSION, ETCD_VERSION)], + urls = mirror("https://github.com/coreos/etcd/releases/download/v%s/etcd-v%s-linux-amd64.tar.gz" % (ETCD_VERSION, ETCD_VERSION)), ) http_archive( name = "io_bazel_rules_docker", sha256 = "c440717ee9b1b2f4a1e9bf5622539feb5aef9db83fc1fa1517818f13c041b0be", strip_prefix = "rules_docker-8bbe2a8abd382641e65ff7127a3700a8530f02ce", - urls = ["https://github.com/bazelbuild/rules_docker/archive/8bbe2a8abd382641e65ff7127a3700a8530f02ce.tar.gz"], + urls = mirror("https://github.com/bazelbuild/rules_docker/archive/8bbe2a8abd382641e65ff7127a3700a8530f02ce.tar.gz"), ) load("@bazel_skylib//:lib.bzl", "versions") -versions.check(minimum_bazel_version = "0.10.0") +versions.check(minimum_bazel_version = "0.13.0") -load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains", "go_download_sdk") -load("@io_bazel_rules_docker//docker:docker.bzl", "docker_repositories", "docker_pull") +load("@io_bazel_rules_go//go:def.bzl", "go_download_sdk", "go_register_toolchains", "go_rules_dependencies") +load("@io_bazel_rules_docker//docker:docker.bzl", "docker_pull", "docker_repositories") go_rules_dependencies() go_register_toolchains( - go_version = "1.9.3", + go_version = "1.10.3", ) docker_repositories() @@ -54,7 +56,13 @@ docker_repositories() http_file( name = "kubernetes_cni", sha256 = "f04339a21b8edf76d415e7f17b620e63b8f37a76b2f706671587ab6464411f2d", - url = "https://storage.googleapis.com/kubernetes-release/network-plugins/cni-plugins-amd64-v0.6.0.tgz", + urls = mirror("https://storage.googleapis.com/kubernetes-release/network-plugins/cni-plugins-amd64-v0.6.0.tgz"), +) + +http_file( + name = "cri_tools", + sha256 = "ccf83574556793ceb01717dc91c66b70f183c60c2bbec70283939aae8fdef768", + urls = mirror("https://github.com/kubernetes-incubator/cri-tools/releases/download/v%s/crictl-v%s-linux-amd64.tar.gz" % (CRI_TOOLS_VERSION, CRI_TOOLS_VERSION)), ) docker_pull( @@ -80,3 +88,7 @@ docker_pull( repository = "library/busybox", tag = "latest", # ignored, but kept here for documentation ) + +load("//build:workspace_mirror.bzl", "export_urls") + +export_urls("workspace_urls") diff --git a/vendor/k8s.io/kubernetes/build/rpms/10-kubeadm.conf b/vendor/k8s.io/kubernetes/build/rpms/10-kubeadm.conf index a989fe7e5..19475e59a 100644 --- a/vendor/k8s.io/kubernetes/build/rpms/10-kubeadm.conf +++ b/vendor/k8s.io/kubernetes/build/rpms/10-kubeadm.conf @@ -1,13 +1,11 @@ +# Note: This dropin only works with kubeadm and kubelet v1.11+ [Service] Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" -Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true" -Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin" -Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local" -Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt" -# Value should match Docker daemon settings. -# Defaults are "cgroupfs" for Debian/Ubuntu/OpenSUSE and "systemd" for Fedora/CentOS/RHEL -Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd" -Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0" -Environment="KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true" +Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" +# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically +EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env +# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use +# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file. +EnvironmentFile=-/etc/sysconfig/kubelet ExecStart= -ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS +ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS diff --git a/vendor/k8s.io/kubernetes/build/rpms/BUILD b/vendor/k8s.io/kubernetes/build/rpms/BUILD index 5db49c0a1..b9a6a9e26 100644 --- a/vendor/k8s.io/kubernetes/build/rpms/BUILD +++ b/vendor/k8s.io/kubernetes/build/rpms/BUILD @@ -1,6 +1,20 @@ package(default_visibility = ["//visibility:public"]) load("@bazel_tools//tools/build_defs/pkg:rpm.bzl", "pkg_rpm") +load("//build:workspace.bzl", "CRI_TOOLS_VERSION") + +filegroup( + name = "rpms", + srcs = [ + ":cri-tools", + ":kubeadm", + ":kubectl", + ":kubelet", + ":kubernetes-cni", + ], + tags = ["manual"], + visibility = ["//visibility:public"], +) pkg_rpm( name = "kubectl", @@ -10,6 +24,7 @@ pkg_rpm( "//cmd/kubectl", ], spec_file = "kubectl.spec", + tags = ["manual"], version_file = "//build:os_package_version", ) @@ -22,6 +37,7 @@ pkg_rpm( "//cmd/kubelet", ], spec_file = "kubelet.spec", + tags = ["manual"], version_file = "//build:os_package_version", ) @@ -31,9 +47,11 @@ pkg_rpm( changelog = "//:CHANGELOG.md", data = [ "10-kubeadm.conf", + "kubelet.env", "//cmd/kubeadm", ], spec_file = "kubeadm.spec", + tags = ["manual"], version_file = "//build:os_package_version", ) @@ -45,9 +63,22 @@ pkg_rpm( "@kubernetes_cni//file", ], spec_file = "kubernetes-cni.spec", + tags = ["manual"], version_file = "//build:cni_package_version", ) +pkg_rpm( + name = "cri-tools", + architecture = "x86_64", + data = [ + "@cri_tools//file", + ], + spec_file = "cri-tools.spec", + tags = ["manual"], + # dashes are not allowed in rpm versions + version = CRI_TOOLS_VERSION.replace("-", "_"), +) + filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/vendor/k8s.io/kubernetes/build/rpms/cri-tools.spec b/vendor/k8s.io/kubernetes/build/rpms/cri-tools.spec new file mode 100644 index 000000000..bf58fa8bd --- /dev/null +++ b/vendor/k8s.io/kubernetes/build/rpms/cri-tools.spec @@ -0,0 +1,21 @@ +Name: cri-tools +Version: OVERRIDE_THIS +Release: 00 +License: ASL 2.0 +Summary: Container Runtime Interface tools + +URL: https://kubernetes.io + +%description +Binaries to interface with the container runtime. + +%prep +# This has to be hard coded because bazel does a path substitution before rpm's %{version} is substituted. +tar -xzf {crictl-v1.11.1-linux-amd64.tar.gz} + +%install +install -m 755 -d %{buildroot}%{_bindir} +install -p -m 755 -t %{buildroot}%{_bindir} crictl + +%files +%{_bindir}/crictl diff --git a/vendor/k8s.io/kubernetes/build/rpms/kubeadm.spec b/vendor/k8s.io/kubernetes/build/rpms/kubeadm.spec index 08e8ad44f..53a992eb3 100644 --- a/vendor/k8s.io/kubernetes/build/rpms/kubeadm.spec +++ b/vendor/k8s.io/kubernetes/build/rpms/kubeadm.spec @@ -16,9 +16,12 @@ Command-line utility for deploying a Kubernetes cluster. install -m 755 -d %{buildroot}%{_bindir} install -m 755 -d %{buildroot}%{_sysconfdir}/systemd/system/ install -m 755 -d %{buildroot}%{_sysconfdir}/systemd/system/kubelet.service.d/ -install -p -m 755 -t %{buildroot}%{_bindir} kubeadm -install -p -m 755 -t %{buildroot}%{_sysconfdir}/systemd/system/kubelet.service.d/ 10-kubeadm.conf +install -m 755 -d %{buildroot}%{_sysconfdir}/sysconfig/ +install -p -m 755 -t %{buildroot}%{_bindir} {kubeadm} +install -p -m 755 -t %{buildroot}%{_sysconfdir}/systemd/system/kubelet.service.d/ {10-kubeadm.conf} +install -p -m 755 -T {kubelet.env} %{buildroot}%{_sysconfdir}/sysconfig/kubelet %files %{_bindir}/kubeadm %{_sysconfdir}/systemd/system/kubelet.service.d/10-kubeadm.conf +%{_sysconfdir}/sysconfig/kubelet diff --git a/vendor/k8s.io/kubernetes/build/rpms/kubectl.spec b/vendor/k8s.io/kubernetes/build/rpms/kubectl.spec index 247dc3fa0..adcc32b93 100644 --- a/vendor/k8s.io/kubernetes/build/rpms/kubectl.spec +++ b/vendor/k8s.io/kubernetes/build/rpms/kubectl.spec @@ -12,7 +12,7 @@ Command-line utility for interacting with a Kubernetes cluster. %install install -m 755 -d %{buildroot}%{_bindir} -install -p -m 755 -t %{buildroot}%{_bindir} kubectl +install -p -m 755 -t %{buildroot}%{_bindir} {kubectl} %files %{_bindir}/kubectl diff --git a/vendor/k8s.io/kubernetes/build/rpms/kubelet.env b/vendor/k8s.io/kubernetes/build/rpms/kubelet.env new file mode 100644 index 000000000..b6c7084e3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/build/rpms/kubelet.env @@ -0,0 +1 @@ +KUBELET_EXTRA_ARGS= diff --git a/vendor/k8s.io/kubernetes/build/rpms/kubelet.spec b/vendor/k8s.io/kubernetes/build/rpms/kubelet.spec index cde8afa58..d5e85bf90 100644 --- a/vendor/k8s.io/kubernetes/build/rpms/kubelet.spec +++ b/vendor/k8s.io/kubernetes/build/rpms/kubelet.spec @@ -22,8 +22,8 @@ The node agent of Kubernetes, the container cluster manager. install -m 755 -d %{buildroot}%{_bindir} install -m 755 -d %{buildroot}%{_sysconfdir}/systemd/system/ install -m 755 -d %{buildroot}%{_sysconfdir}/kubernetes/manifests/ -install -p -m 755 -t %{buildroot}%{_bindir} kubelet -install -p -m 755 -t %{buildroot}%{_sysconfdir}/systemd/system/ kubelet.service +install -p -m 755 -t %{buildroot}%{_bindir} {kubelet} +install -p -m 755 -t %{buildroot}%{_sysconfdir}/systemd/system/ {kubelet.service} %files %{_bindir}/kubelet diff --git a/vendor/k8s.io/kubernetes/build/rpms/kubernetes-cni.spec b/vendor/k8s.io/kubernetes/build/rpms/kubernetes-cni.spec index 70627fe4d..4b4751d11 100644 --- a/vendor/k8s.io/kubernetes/build/rpms/kubernetes-cni.spec +++ b/vendor/k8s.io/kubernetes/build/rpms/kubernetes-cni.spec @@ -11,7 +11,7 @@ Binaries required to provision container networking. %prep mkdir -p ./bin -tar -C ./bin -xz -f cni-plugins-amd64-v0.6.0.tgz +tar -C ./bin -xz -f {cni-plugins-amd64-v0.6.0.tgz} %install diff --git a/vendor/k8s.io/kubernetes/build/run.sh b/vendor/k8s.io/kubernetes/build/run.sh index 5304f9280..b0465fb6b 100755 --- a/vendor/k8s.io/kubernetes/build/run.sh +++ b/vendor/k8s.io/kubernetes/build/run.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/build/shell.sh b/vendor/k8s.io/kubernetes/build/shell.sh index dac2e4949..7572cedbc 100755 --- a/vendor/k8s.io/kubernetes/build/shell.sh +++ b/vendor/k8s.io/kubernetes/build/shell.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/build/util.sh b/vendor/k8s.io/kubernetes/build/util.sh index db9a7040b..32152ff92 100644 --- a/vendor/k8s.io/kubernetes/build/util.sh +++ b/vendor/k8s.io/kubernetes/build/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/build/visible_to/BUILD b/vendor/k8s.io/kubernetes/build/visible_to/BUILD index 094e9260f..9ba4b3ce5 100644 --- a/vendor/k8s.io/kubernetes/build/visible_to/BUILD +++ b/vendor/k8s.io/kubernetes/build/visible_to/BUILD @@ -73,23 +73,10 @@ package_group( ], ) -package_group( - name = "pkg_kubectl_CONSUMERS_BAD", - includes = [ - ":KUBEADM_BAD", - ], - packages = [ - "//cmd/clicheck", - "//cmd/hyperkube", - "//pkg", - ], -) - package_group( name = "pkg_kubectl_CONSUMERS", includes = [ ":COMMON_generators", - ":pkg_kubectl_CONSUMERS_BAD", ], packages = [ "//cmd/kubectl", @@ -142,6 +129,20 @@ package_group( ], ) +package_group( + name = "pkg_kubectl_cmd_create_CONSUMERS", + packages = [ + "//pkg/kubectl/cmd", + ], +) + +package_group( + name = "pkg_kubectl_cmd_get_CONSUMERS", + packages = [ + "//pkg/kubectl/cmd", + ], +) + package_group( name = "pkg_kubectl_cmd_rollout_CONSUMERS", packages = [ @@ -169,12 +170,14 @@ package_group( "//pkg/kubectl/cmd", "//pkg/kubectl/cmd/auth", "//pkg/kubectl/cmd/config", - "//pkg/kubectl/cmd/resource", + "//pkg/kubectl/cmd/create", + "//pkg/kubectl/cmd/get", "//pkg/kubectl/cmd/rollout", "//pkg/kubectl/cmd/set", "//pkg/kubectl/cmd/templates", "//pkg/kubectl/cmd/util", "//pkg/kubectl/cmd/util/sanity", + "//pkg/kubectl/cmd/wait", ], ) @@ -190,31 +193,21 @@ package_group( packages = [ "//pkg/kubectl/cmd", "//pkg/kubectl/cmd/auth", - "//pkg/kubectl/cmd/resource", + "//pkg/kubectl/cmd/create", + "//pkg/kubectl/cmd/get", + "//pkg/kubectl/cmd/rollout", "//pkg/kubectl/cmd/set", + "//pkg/kubectl/cmd/wait", "//pkg/kubectl/explain", ], ) -package_group( - name = "pkg_kubectl_cmd_util_CONSUMERS_BAD", - includes = [ - ":KUBEADM_BAD", - ], - packages = [ - "//cmd/clicheck", - "//cmd/hyperkube", - "//cmd/kube-proxy/app", - "//cmd/kube-scheduler/app", - ], -) - package_group( name = "pkg_kubectl_cmd_util_CONSUMERS", includes = [ ":COMMON_generators", ":COMMON_testing", - ":pkg_kubectl_cmd_util_CONSUMERS_BAD", + ":KUBEADM_BAD", ], packages = [ "//cmd/kubectl", @@ -222,12 +215,14 @@ package_group( "//pkg/kubectl/cmd", "//pkg/kubectl/cmd/auth", "//pkg/kubectl/cmd/config", - "//pkg/kubectl/cmd/resource", + "//pkg/kubectl/cmd/create", + "//pkg/kubectl/cmd/get", "//pkg/kubectl/cmd/rollout", "//pkg/kubectl/cmd/set", "//pkg/kubectl/cmd/testing", "//pkg/kubectl/cmd/util", "//pkg/kubectl/cmd/util/editor", + "//pkg/kubectl/cmd/wait", ], ) @@ -235,6 +230,7 @@ package_group( name = "pkg_kubectl_cmd_util_editor_CONSUMERS", packages = [ "//pkg/kubectl/cmd", + "//pkg/kubectl/cmd/create", "//pkg/kubectl/cmd/util", ], ) @@ -255,19 +251,10 @@ package_group( ], ) -package_group( - name = "pkg_kubectl_metricsutil_CONSUMERS_BAD", - packages = [ - "//cmd/clicheck", - "//cmd/hyperkube", - ], -) - package_group( name = "pkg_kubectl_metricsutil_CONSUMERS", includes = [ ":COMMON_generators", - ":pkg_kubectl_metricsutil_CONSUMERS_BAD", ], packages = [ "//cmd/kubectl", @@ -290,7 +277,8 @@ package_group( "//pkg/kubectl/cmd", "//pkg/kubectl/cmd/auth", "//pkg/kubectl/cmd/config", - "//pkg/kubectl/cmd/resource", + "//pkg/kubectl/cmd/create", + "//pkg/kubectl/cmd/get", "//pkg/kubectl/cmd/rollout", "//pkg/kubectl/cmd/set", "//pkg/kubectl/cmd/testing", @@ -320,6 +308,7 @@ package_group( name = "pkg_kubectl_validation_CONSUMERS", packages = [ "//pkg/kubectl", + "//pkg/kubectl/cmd", "//pkg/kubectl/cmd/testing", "//pkg/kubectl/cmd/util", "//pkg/kubectl/resource", diff --git a/vendor/k8s.io/kubernetes/build/visible_to/README.md b/vendor/k8s.io/kubernetes/build/visible_to/README.md index 9daa99a0f..3caf0a14b 100644 --- a/vendor/k8s.io/kubernetes/build/visible_to/README.md +++ b/vendor/k8s.io/kubernetes/build/visible_to/README.md @@ -115,7 +115,7 @@ visibility = ["//visible_to:client_foo,//visible_to:server_foo"], ``` bazel build --check_visibility --nobuild \ //cmd/... //pkg/... //plugin/... \ - //third_party/... //examples/... //test/... //vendor/k8s.io/... + //third_party/... //test/... //vendor/k8s.io/... ``` #### Who depends on target _q_? diff --git a/vendor/k8s.io/kubernetes/build/workspace.bzl b/vendor/k8s.io/kubernetes/build/workspace.bzl new file mode 100644 index 000000000..56a08f2e3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/build/workspace.bzl @@ -0,0 +1,15 @@ +# Copyright 2018 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. + +CRI_TOOLS_VERSION = "1.11.1" diff --git a/vendor/k8s.io/kubernetes/build/workspace_mirror.bzl b/vendor/k8s.io/kubernetes/build/workspace_mirror.bzl new file mode 100644 index 000000000..492249130 --- /dev/null +++ b/vendor/k8s.io/kubernetes/build/workspace_mirror.bzl @@ -0,0 +1,57 @@ +# Copyright 2018 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. + +prefix = "https://storage.googleapis.com/k8s-bazel-cache/" + +def mirror(url): + """Try downloading a URL from a GCS mirror first, then from the original. + + Update the GCS bucket using bazel run //hack:update-mirror""" + return [prefix + url, url] + +def mirror_urls(): + # This function only gives proper results when executed from WORKSPACE, + # but the data is needed in sh_binary, which can only be in a BUILD file. + # Thus, it is be exported by a repository_rule (which executes in WORKSPACE) + # to be used by the sh_binary. + urls = [] + for k, v in native.existing_rules().items(): + us = list(v.get("urls", [])) + if "url" in v: + us.append(v["url"]) + for u in us: + if u and not u.startswith(prefix): + urls.append(u) + return sorted(urls) + +def export_urls_impl(repo_ctx): + repo_ctx.file(repo_ctx.path("BUILD.bazel"), """ +exports_files(glob(["**"]), visibility=["//visibility:public"]) +""") + repo_ctx.file( + repo_ctx.path("urls.txt"), + # Add a trailing newline, since the "while read" loop needs it + content = ("\n".join(repo_ctx.attr.urls) + "\n"), + ) + +_export_urls = repository_rule( + attrs = { + "urls": attr.string_list(mandatory = True), + }, + local = True, + implementation = export_urls_impl, +) + +def export_urls(name): + return _export_urls(name = name, urls = mirror_urls()) diff --git a/vendor/k8s.io/kubernetes/cluster/BUILD b/vendor/k8s.io/kubernetes/cluster/BUILD index a4df9bb3d..0654bb05e 100644 --- a/vendor/k8s.io/kubernetes/cluster/BUILD +++ b/vendor/k8s.io/kubernetes/cluster/BUILD @@ -16,8 +16,7 @@ filegroup( "//cluster/addons:all-srcs", "//cluster/gce:all-srcs", "//cluster/images/etcd-version-monitor:all-srcs", - "//cluster/images/etcd/attachlease:all-srcs", - "//cluster/images/etcd/rollback:all-srcs", + "//cluster/images/etcd/migrate:all-srcs", "//cluster/images/hyperkube:all-srcs", "//cluster/images/kubemark:all-srcs", ], diff --git a/vendor/k8s.io/kubernetes/cluster/addons/addon-manager/kube-addons.sh b/vendor/k8s.io/kubernetes/cluster/addons/addon-manager/kube-addons.sh index f2002c3fb..eb118444d 100755 --- a/vendor/k8s.io/kubernetes/cluster/addons/addon-manager/kube-addons.sh +++ b/vendor/k8s.io/kubernetes/cluster/addons/addon-manager/kube-addons.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/calico-clusterrole.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/calico-clusterrole.yaml index 35508b2a6..0e3f40609 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/calico-clusterrole.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/calico-clusterrole.yaml @@ -36,6 +36,7 @@ rules: - get - list - watch + - patch - apiGroups: [""] resources: - nodes @@ -51,17 +52,28 @@ rules: - get - list - watch + - apiGroups: ["networking.k8s.io"] + resources: + - networkpolicies + verbs: + - watch + - list - apiGroups: ["crd.projectcalico.org"] resources: - globalfelixconfigs + - felixconfigurations + - bgppeers - globalbgpconfigs + - bgpconfigurations - ippools - globalnetworkpolicies + - globalnetworksets + - networkpolicies + - clusterinformations + - hostendpoints verbs: - create - get - list - update - - patch - - delete - watch diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/calico-node-daemonset.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/calico-node-daemonset.yaml index 27a2ece72..96440e74d 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/calico-node-daemonset.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/calico-node-daemonset.yaml @@ -41,18 +41,22 @@ spec: value: "none" - name: DATASTORE_TYPE value: "kubernetes" - - name: FELIX_TYPHAK8SSERVICENAME - value: "calico-typha" - name: FELIX_DEFAULTENDPOINTTOHOSTACTION value: "ACCEPT" + - name: FELIX_HEALTHENABLED + value: "true" - name: FELIX_IPV6SUPPORT value: "false" - name: FELIX_LOGSEVERITYSYS value: "none" + - name: FELIX_LOGSEVERITYSCREEN + value: "info" - name: FELIX_PROMETHEUSMETRICSENABLED value: "true" - - name: FELIX_HEALTHENABLED - value: "true" + - name: FELIX_REPORTINGINTERVALSECS + value: "0" + - name: FELIX_TYPHAK8SSERVICENAME + value: "calico-typha" - name: IP value: "" - name: NO_DEFAULT_POOLS @@ -84,6 +88,12 @@ spec: - mountPath: /etc/calico name: etc-calico readOnly: true + - mountPath: /var/run/calico + name: var-run-calico + readOnly: false + - mountPath: /var/lib/calico + name: var-lib-calico + readOnly: false # This container installs the Calico CNI binaries # and CNI network config file on each node. - name: install-cni @@ -149,6 +159,12 @@ spec: - name: cni-net-dir hostPath: path: /etc/cni/net.d + - name: var-run-calico + hostPath: + path: /var/run/calico + - name: var-lib-calico + hostPath: + path: /var/lib/calico tolerations: # Make sure calico/node gets scheduled on all nodes. - effect: NoSchedule diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/clusterinformations-crd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/clusterinformations-crd.yaml new file mode 100644 index 000000000..6809b8db2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/clusterinformations-crd.yaml @@ -0,0 +1,15 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: clusterinformations.crd.projectcalico.org + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +spec: + scope: Cluster + group: crd.projectcalico.org + version: v1 + names: + kind: ClusterInformation + plural: clusterinformations + singular: clusterinformation diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/felixconfigurations-crd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/felixconfigurations-crd.yaml new file mode 100644 index 000000000..e76badcf3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/felixconfigurations-crd.yaml @@ -0,0 +1,15 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: felixconfigurations.crd.projectcalico.org + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +spec: + scope: Cluster + group: crd.projectcalico.org + version: v1 + names: + kind: FelixConfiguration + plural: felixconfigurations + singular: felixconfiguration diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalbgpconfig-crd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalbgpconfig-crd.yaml index 2d3e6bd28..a0a98b8cc 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalbgpconfig-crd.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalbgpconfig-crd.yaml @@ -1,5 +1,4 @@ apiVersion: apiextensions.k8s.io/v1beta1 -description: Calico Global BGP Configuration kind: CustomResourceDefinition metadata: name: globalbgpconfigs.crd.projectcalico.org diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalfelixconfig-crd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalfelixconfig-crd.yaml index 7e5c7b196..619bdb91e 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalfelixconfig-crd.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalfelixconfig-crd.yaml @@ -1,5 +1,4 @@ apiVersion: apiextensions.k8s.io/v1beta1 -description: Calico Global Felix Configuration kind: CustomResourceDefinition metadata: name: globalfelixconfigs.crd.projectcalico.org diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalnetworkpolicy-crd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalnetworkpolicy-crd.yaml index 398c05949..1a9ede8e6 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalnetworkpolicy-crd.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalnetworkpolicy-crd.yaml @@ -1,5 +1,4 @@ apiVersion: apiextensions.k8s.io/v1beta1 -description: Calico Global Network Policies kind: CustomResourceDefinition metadata: name: globalnetworkpolicies.crd.projectcalico.org diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalnetworksets-crd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalnetworksets-crd.yaml new file mode 100644 index 000000000..534653973 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/globalnetworksets-crd.yaml @@ -0,0 +1,15 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: globalnetworksets.crd.projectcalico.org + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +spec: + scope: Cluster + group: crd.projectcalico.org + version: v1 + names: + kind: GlobalNetworkSet + plural: globalnetworksets + singular: globalnetworkset diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/hostendpoints-crd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/hostendpoints-crd.yaml new file mode 100644 index 000000000..6da4d9789 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/hostendpoints-crd.yaml @@ -0,0 +1,15 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: hostendpoints.crd.projectcalico.org + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +spec: + scope: Cluster + group: crd.projectcalico.org + version: v1 + names: + kind: HostEndpoint + plural: hostendpoints + singular: hostendpoint diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/ippool-crd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/ippool-crd.yaml index c09f73c18..c0ffcea34 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/ippool-crd.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/ippool-crd.yaml @@ -1,5 +1,4 @@ apiVersion: apiextensions.k8s.io/v1beta1 -description: Calico IP Pools kind: CustomResourceDefinition metadata: name: ippools.crd.projectcalico.org diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/networkpolicies-crd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/networkpolicies-crd.yaml new file mode 100644 index 000000000..a22556907 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/networkpolicies-crd.yaml @@ -0,0 +1,15 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: networkpolicies.crd.projectcalico.org + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +spec: + scope: Namespaced + group: crd.projectcalico.org + version: v1 + names: + kind: NetworkPolicy + plural: networkpolicies + singular: networkpolicy diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-deployment.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-deployment.yaml index f4c9ba82f..ebc6d6dba 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-deployment.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-deployment.yaml @@ -44,6 +44,8 @@ spec: value: "9093" - name: TYPHA_DATASTORETYPE value: "kubernetes" + - name: TYPHA_REPORTINGINTERVALSECS + value: "0" - name: TYPHA_MAXCONNECTIONSLOWERLIMIT value: "1" - name: TYPHA_HEALTHENABLED diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-clusterrole.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-clusterrole.yaml new file mode 100644 index 000000000..51751613b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-clusterrole.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: typha-cpva + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +rules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["list"] + - apiGroups: ["apps", "extensions"] + resources: ["deployments"] + verbs: ["patch"] diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-clusterrolebinding.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-clusterrolebinding.yaml new file mode 100644 index 000000000..327965cdc --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-clusterrolebinding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: typha-cpva + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: typha-cpva +subjects: + - kind: ServiceAccount + name: typha-cpva + namespace: kube-system diff --git a/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-serviceaccount.yaml b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-serviceaccount.yaml new file mode 100644 index 000000000..bf9a72359 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-serviceaccount.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: typha-cpva + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile diff --git a/vendor/k8s.io/kubernetes/cluster/addons/cluster-loadbalancing/glbc/default-svc-controller.yaml b/vendor/k8s.io/kubernetes/cluster/addons/cluster-loadbalancing/glbc/default-svc-controller.yaml index 3fa0e6f78..0fbadc5e1 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/cluster-loadbalancing/glbc/default-svc-controller.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/cluster-loadbalancing/glbc/default-svc-controller.yaml @@ -9,7 +9,6 @@ metadata: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: - replicas: 1 selector: matchLabels: k8s-app: glbc @@ -18,6 +17,8 @@ spec: labels: k8s-app: glbc name: glbc + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: containers: - name: default-http-backend diff --git a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/README.md b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/README.md index ea0442046..6642d9108 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/README.md +++ b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/README.md @@ -5,4 +5,17 @@ Heapster collects signals from kubelets and the api server, processes them, and More details can be found in [Monitoring user guide](http://kubernetes.io/docs/user-guide/monitoring/). +## Troubleshooting + +Heapster supports up to 30 pods per cluster node. In clusters where there are more running pods, Heapster may be throttled or fail with OOM error. Starting with Kubernetes 1.9.2, Heapster resource requirements may be overwritten manually. [Learn more about Addon Resizer configuration](https://github.com/kubernetes/autoscaler/tree/master/addon-resizer#addon-resizer-configuration) + +### Important notices + +Decreasing resource requirements for cluster addons may cause system instability. The effects may include (but are not limited to): + - Metrics not being exported + - Horizontal Pod Autoscaler not working + - `kubectl top` not working + +Overwritten configuration persists through cluster updates, therefore may cause all effects above after a cluster update. + [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/cluster/addons/cluster-monitoring/README.md?pixel)]() diff --git a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/google/heapster-controller.yaml b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/google/heapster-controller.yaml index 6bb8230dc..75075dc02 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/google/heapster-controller.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/google/heapster-controller.yaml @@ -36,30 +36,31 @@ data: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.5.3 + name: heapster-v1.6.0-beta.1 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.5.3 + version: v1.6.0-beta.1 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 template: metadata: labels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical containers: - - image: k8s.gcr.io/heapster-amd64:v1.5.3 + - image: k8s.gcr.io/heapster-amd64:v1.6.0-beta.1 name: heapster livenessProbe: httpGet: @@ -72,7 +73,7 @@ spec: - /heapster - --source=kubernetes.summary_api:'' - --sink=gcm - - image: k8s.gcr.io/heapster-amd64:v1.5.3 + - image: k8s.gcr.io/heapster-amd64:v1.6.0-beta.1 name: eventer command: - /eventer @@ -107,7 +108,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{metrics_memory_per_node}}Mi - --threshold=5 - - --deployment=heapster-v1.5.3 + - --deployment=heapster-v1.6.0-beta.1 - --container=heapster - --poll-period=300000 - --estimator=exponential @@ -140,7 +141,7 @@ spec: - --memory={{base_eventer_memory}} - --extra-memory={{eventer_memory_per_node}}Ki - --threshold=5 - - --deployment=heapster-v1.5.3 + - --deployment=heapster-v1.6.0-beta.1 - --container=eventer - --poll-period=300000 - --estimator=exponential diff --git a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml index 634861a53..9353b13f6 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml @@ -36,30 +36,31 @@ data: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.5.3 + name: heapster-v1.6.0-beta.1 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.5.3 + version: v1.6.0-beta.1 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 template: metadata: labels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical containers: - - image: k8s.gcr.io/heapster-amd64:v1.5.3 + - image: k8s.gcr.io/heapster-amd64:v1.6.0-beta.1 name: heapster livenessProbe: httpGet: @@ -73,7 +74,7 @@ spec: - --source=kubernetes.summary_api:'' - --sink=influxdb:http://monitoring-influxdb:8086 - --sink=gcm:?metrics=autoscaling - - image: k8s.gcr.io/heapster-amd64:v1.5.3 + - image: k8s.gcr.io/heapster-amd64:v1.6.0-beta.1 name: eventer command: - /eventer @@ -108,7 +109,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - --threshold=5 - - --deployment=heapster-v1.5.3 + - --deployment=heapster-v1.6.0-beta.1 - --container=heapster - --poll-period=300000 - --estimator=exponential @@ -141,7 +142,7 @@ spec: - --memory={{ base_eventer_memory }} - --extra-memory={{ eventer_memory_per_node }}Ki - --threshold=5 - - --deployment=heapster-v1.5.3 + - --deployment=heapster-v1.6.0-beta.1 - --container=eventer - --poll-period=300000 - --estimator=exponential diff --git a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml index 92c306c1a..3d2d8a94a 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml @@ -36,30 +36,31 @@ data: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.5.3 + name: heapster-v1.6.0-beta.1 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.5.3 + version: v1.6.0-beta.1 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 template: metadata: labels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical containers: - - image: k8s.gcr.io/heapster-amd64:v1.5.3 + - image: k8s.gcr.io/heapster-amd64:v1.6.0-beta.1 name: heapster livenessProbe: httpGet: @@ -72,7 +73,7 @@ spec: - /heapster - --source=kubernetes.summary_api:'' - --sink=influxdb:http://monitoring-influxdb:8086 - - image: k8s.gcr.io/heapster-amd64:v1.5.3 + - image: k8s.gcr.io/heapster-amd64:v1.6.0-beta.1 name: eventer command: - /eventer @@ -107,7 +108,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - --threshold=5 - - --deployment=heapster-v1.5.3 + - --deployment=heapster-v1.6.0-beta.1 - --container=heapster - --poll-period=300000 - --estimator=exponential @@ -140,7 +141,7 @@ spec: - --memory={{ base_eventer_memory }} - --extra-memory={{ eventer_memory_per_node }}Ki - --threshold=5 - - --deployment=heapster-v1.5.3 + - --deployment=heapster-v1.6.0-beta.1 - --container=eventer - --poll-period=300000 - --estimator=exponential diff --git a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/influxdb/influxdb-grafana-controller.yaml b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/influxdb/influxdb-grafana-controller.yaml index d494f3378..dd0ebe652 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/influxdb/influxdb-grafana-controller.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/influxdb/influxdb-grafana-controller.yaml @@ -21,6 +21,7 @@ spec: version: v4 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical tolerations: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml index fb5864929..33bf27756 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml @@ -23,30 +23,31 @@ data: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.5.3 + name: heapster-v1.6.0-beta.1 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.5.3 + version: v1.6.0-beta.1 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 template: metadata: labels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical containers: - - image: k8s.gcr.io/heapster-amd64:v1.5.3 + - image: k8s.gcr.io/heapster-amd64:v1.6.0-beta.1 name: heapster livenessProbe: httpGet: @@ -56,9 +57,10 @@ spec: initialDelaySeconds: 180 timeoutSeconds: 5 command: + # On GCP, container.googleapis.com/instance_id node annotation is used to provide instance_id label for Stackdriver - /heapster - - --source=kubernetes.summary_api:'' - - --sink=stackdriver:?cluster_name={{ cluster_name }}&use_old_resources={{ use_old_resources }}&use_new_resources={{ use_new_resources }}&min_interval_sec=100&batch_export_timeout_sec=110 + - --source=kubernetes.summary_api:?host_id_annotation=container.googleapis.com/instance_id + - --sink=stackdriver:?cluster_name={{ cluster_name }}&use_old_resources={{ use_old_resources }}&use_new_resources={{ use_new_resources }}&min_interval_sec=100&batch_export_timeout_sec=110&cluster_location={{ cluster_location }} # BEGIN_PROMETHEUS_TO_SD - name: prom-to-sd image: k8s.gcr.io/prometheus-to-sd:v0.2.4 @@ -108,7 +110,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{metrics_memory_per_node}}Mi - --threshold=5 - - --deployment=heapster-v1.5.3 + - --deployment=heapster-v1.6.0-beta.1 - --container=heapster - --poll-period=300000 - --estimator=exponential diff --git a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml index fa794c54a..86c6c3649 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml @@ -23,30 +23,31 @@ data: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.5.3 + name: heapster-v1.6.0-beta.1 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.5.3 + version: v1.6.0-beta.1 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 template: metadata: labels: k8s-app: heapster - version: v1.5.3 + version: v1.6.0-beta.1 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical containers: - - image: k8s.gcr.io/heapster-amd64:v1.5.3 + - image: k8s.gcr.io/heapster-amd64:v1.6.0-beta.1 name: heapster livenessProbe: httpGet: @@ -87,7 +88,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - --threshold=5 - - --deployment=heapster-v1.5.3 + - --deployment=heapster-v1.6.0-beta.1 - --container=heapster - --poll-period=300000 - --estimator=exponential diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dashboard/dashboard-controller.yaml b/vendor/k8s.io/kubernetes/cluster/addons/dashboard/dashboard-controller.yaml index 4988f5906..32f2b27dc 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/dashboard/dashboard-controller.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/dashboard/dashboard-controller.yaml @@ -26,6 +26,7 @@ spec: k8s-app: kubernetes-dashboard annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical containers: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/device-plugins/nvidia-gpu/daemonset.yaml b/vendor/k8s.io/kubernetes/cluster/addons/device-plugins/nvidia-gpu/daemonset.yaml index 776dfe6d0..7616b8e25 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/device-plugins/nvidia-gpu/daemonset.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/device-plugins/nvidia-gpu/daemonset.yaml @@ -30,8 +30,6 @@ spec: effect: "NoExecute" - operator: "Exists" effect: "NoSchedule" - hostNetwork: true - hostPID: true volumes: - name: device-plugin hostPath: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml b/vendor/k8s.io/kubernetes/cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml index 3dc0f7959..5cc3e05c6 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml @@ -77,6 +77,7 @@ spec: k8s-app: kube-dns-autoscaler annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical containers: @@ -91,7 +92,7 @@ spec: - --namespace=kube-system - --configmap=kube-dns-autoscaler # Should keep target in sync with cluster/addons/dns/kube-dns.yaml.base - - --target=Deployment/kube-dns + - --target={{.Target}} # When cluster is using large nodes(with more cores), "coresPerReplica" should dominate. # If using small nodes, "nodesPerReplica" should dominate. - --default-params={"linear":{"coresPerReplica":256,"nodesPerReplica":16,"preventSinglePointFailure":true}} diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/Makefile b/vendor/k8s.io/kubernetes/cluster/addons/dns/Makefile deleted file mode 100644 index 01f45e4ba..000000000 --- a/vendor/k8s.io/kubernetes/cluster/addons/dns/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# 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. - -# Makefile for the kubedns underscore templates to Salt/Pillar and other formats. - -# If you update the *.base templates, please run this Makefile before pushing. -# -# Usage: -# make - -all: transform - -# .base -> .in pattern rule -%.in: %.base - sed -f transforms2salt.sed $< | sed s/__SOURCE_FILENAME__/$ $@ - -# .base -> .sed pattern rule -%.sed: %.base - sed -f transforms2sed.sed $< | sed s/__SOURCE_FILENAME__/$ $@ - -transform: kube-dns.yaml.in kube-dns.yaml.sed coredns.yaml.in coredns.yaml.sed - -.PHONY: transform diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/Makefile b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/Makefile new file mode 100644 index 000000000..d3455dd85 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/Makefile @@ -0,0 +1,34 @@ +# 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. + +# Makefile for the kubedns underscore templates to Salt/Pillar and other formats. + +# If you update the *.base templates, please run this Makefile before pushing. +# +# Usage: +# make + +all: transform + +# .base -> .in pattern rule +%.in: %.base + sed -f transforms2salt.sed $< | sed s/__SOURCE_FILENAME__/$ $@ + +# .base -> .sed pattern rule +%.sed: %.base + sed -f transforms2sed.sed $< | sed s/__SOURCE_FILENAME__/$ $@ + +transform: coredns.yaml.in coredns.yaml.sed + +.PHONY: transform diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns.yaml.base b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/coredns.yaml.base similarity index 79% rename from vendor/k8s.io/kubernetes/cluster/addons/dns/coredns.yaml.base rename to vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/coredns.yaml.base index c6c9f7c82..0d969b261 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns.yaml.base +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/coredns.yaml.base @@ -66,6 +66,7 @@ data: prometheus :9153 proxy . /etc/resolv.conf cache 30 + reload } --- apiVersion: extensions/v1beta1 @@ -74,23 +75,28 @@ metadata: name: coredns namespace: kube-system labels: - k8s-app: coredns + k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: - replicas: 2 + # replicas: not specified here: + # 1. In order to make Addon Manager do not reconcile this replicas parameter. + # 2. Default is 1. + # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on. strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 selector: matchLabels: - k8s-app: coredns + k8s-app: kube-dns template: metadata: labels: - k8s-app: coredns + k8s-app: kube-dns + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: serviceAccountName: coredns tolerations: @@ -100,7 +106,7 @@ spec: operator: "Exists" containers: - name: coredns - image: coredns/coredns:1.0.6 + image: k8s.gcr.io/coredns:1.1.3 imagePullPolicy: IfNotPresent resources: limits: @@ -112,6 +118,7 @@ spec: volumeMounts: - name: config-volume mountPath: /etc/coredns + readOnly: true ports: - containerPort: 53 name: dns @@ -119,6 +126,9 @@ spec: - containerPort: 53 name: dns-tcp protocol: TCP + - containerPort: 9153 + name: metrics + protocol: TCP livenessProbe: httpGet: path: /health @@ -128,6 +138,14 @@ spec: timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - all + readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume @@ -140,16 +158,19 @@ spec: apiVersion: v1 kind: Service metadata: - name: coredns + name: kube-dns namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" labels: - k8s-app: coredns + k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: selector: - k8s-app: coredns + k8s-app: kube-dns clusterIP: __PILLAR__DNS__SERVER__ ports: - name: dns diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns.yaml.in b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/coredns.yaml.in similarity index 79% rename from vendor/k8s.io/kubernetes/cluster/addons/dns/coredns.yaml.in rename to vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/coredns.yaml.in index 7e79a6905..4013807f6 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns.yaml.in +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/coredns.yaml.in @@ -66,6 +66,7 @@ data: prometheus :9153 proxy . /etc/resolv.conf cache 30 + reload } --- apiVersion: extensions/v1beta1 @@ -74,23 +75,28 @@ metadata: name: coredns namespace: kube-system labels: - k8s-app: coredns + k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: - replicas: 2 + # replicas: not specified here: + # 1. In order to make Addon Manager do not reconcile this replicas parameter. + # 2. Default is 1. + # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on. strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 selector: matchLabels: - k8s-app: coredns + k8s-app: kube-dns template: metadata: labels: - k8s-app: coredns + k8s-app: kube-dns + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: serviceAccountName: coredns tolerations: @@ -100,7 +106,7 @@ spec: operator: "Exists" containers: - name: coredns - image: coredns/coredns:1.0.6 + image: k8s.gcr.io/coredns:1.1.3 imagePullPolicy: IfNotPresent resources: limits: @@ -112,6 +118,7 @@ spec: volumeMounts: - name: config-volume mountPath: /etc/coredns + readOnly: true ports: - containerPort: 53 name: dns @@ -119,6 +126,9 @@ spec: - containerPort: 53 name: dns-tcp protocol: TCP + - containerPort: 9153 + name: metrics + protocol: TCP livenessProbe: httpGet: path: /health @@ -128,6 +138,14 @@ spec: timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - all + readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume @@ -140,16 +158,19 @@ spec: apiVersion: v1 kind: Service metadata: - name: coredns + name: kube-dns namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" labels: - k8s-app: coredns + k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: selector: - k8s-app: coredns + k8s-app: kube-dns clusterIP: {{ pillar['dns_server'] }} ports: - name: dns diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns.yaml.sed b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/coredns.yaml.sed similarity index 79% rename from vendor/k8s.io/kubernetes/cluster/addons/dns/coredns.yaml.sed rename to vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/coredns.yaml.sed index db14e8417..f29d6e68c 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns.yaml.sed +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/coredns.yaml.sed @@ -66,6 +66,7 @@ data: prometheus :9153 proxy . /etc/resolv.conf cache 30 + reload } --- apiVersion: extensions/v1beta1 @@ -74,23 +75,28 @@ metadata: name: coredns namespace: kube-system labels: - k8s-app: coredns + k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: - replicas: 2 + # replicas: not specified here: + # 1. In order to make Addon Manager do not reconcile this replicas parameter. + # 2. Default is 1. + # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on. strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 selector: matchLabels: - k8s-app: coredns + k8s-app: kube-dns template: metadata: labels: - k8s-app: coredns + k8s-app: kube-dns + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: serviceAccountName: coredns tolerations: @@ -100,7 +106,7 @@ spec: operator: "Exists" containers: - name: coredns - image: coredns/coredns:1.0.6 + image: k8s.gcr.io/coredns:1.1.3 imagePullPolicy: IfNotPresent resources: limits: @@ -112,6 +118,7 @@ spec: volumeMounts: - name: config-volume mountPath: /etc/coredns + readOnly: true ports: - containerPort: 53 name: dns @@ -119,6 +126,9 @@ spec: - containerPort: 53 name: dns-tcp protocol: TCP + - containerPort: 9153 + name: metrics + protocol: TCP livenessProbe: httpGet: path: /health @@ -128,6 +138,14 @@ spec: timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - all + readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume @@ -140,16 +158,19 @@ spec: apiVersion: v1 kind: Service metadata: - name: coredns + name: kube-dns namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" labels: - k8s-app: coredns + k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: selector: - k8s-app: coredns + k8s-app: kube-dns clusterIP: $DNS_SERVER_IP ports: - name: dns diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/transforms2salt.sed b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/transforms2salt.sed similarity index 100% rename from vendor/k8s.io/kubernetes/cluster/addons/dns/transforms2salt.sed rename to vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/transforms2salt.sed diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/transforms2sed.sed b/vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/transforms2sed.sed similarity index 100% rename from vendor/k8s.io/kubernetes/cluster/addons/dns/transforms2sed.sed rename to vendor/k8s.io/kubernetes/cluster/addons/dns/coredns/transforms2sed.sed diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/Makefile b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/Makefile new file mode 100644 index 000000000..50419ff32 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/Makefile @@ -0,0 +1,34 @@ +# 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. + +# Makefile for the kubedns underscore templates to Salt/Pillar and other formats. + +# If you update the *.base templates, please run this Makefile before pushing. +# +# Usage: +# make + +all: transform + +# .base -> .in pattern rule +%.in: %.base + sed -f transforms2salt.sed $< | sed s/__SOURCE_FILENAME__/$ $@ + +# .base -> .sed pattern rule +%.sed: %.base + sed -f transforms2sed.sed $< | sed s/__SOURCE_FILENAME__/$ $@ + +transform: kube-dns.yaml.in kube-dns.yaml.sed + +.PHONY: transform diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/README.md b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/README.md similarity index 100% rename from vendor/k8s.io/kubernetes/cluster/addons/dns/README.md rename to vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/README.md diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns.yaml.base b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/kube-dns.yaml.base similarity index 98% rename from vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns.yaml.base rename to vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/kube-dns.yaml.base index aa19b8822..fbd232f51 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns.yaml.base +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/kube-dns.yaml.base @@ -83,6 +83,7 @@ spec: k8s-app: kube-dns annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical tolerations: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns.yaml.in b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/kube-dns.yaml.in similarity index 98% rename from vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns.yaml.in rename to vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/kube-dns.yaml.in index 392663108..74b73b550 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns.yaml.in +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/kube-dns.yaml.in @@ -83,6 +83,7 @@ spec: k8s-app: kube-dns annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical tolerations: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns.yaml.sed b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/kube-dns.yaml.sed similarity index 98% rename from vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns.yaml.sed rename to vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/kube-dns.yaml.sed index cc9bf8de6..e692d5ac8 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns.yaml.sed +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/kube-dns.yaml.sed @@ -83,6 +83,7 @@ spec: k8s-app: kube-dns annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical tolerations: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/transforms2salt.sed b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/transforms2salt.sed new file mode 100644 index 000000000..0a0778b92 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/transforms2salt.sed @@ -0,0 +1,4 @@ +s/__PILLAR__DNS__SERVER__/{{ pillar['dns_server'] }}/g +s/__PILLAR__DNS__DOMAIN__/{{ pillar['dns_domain'] }}/g +s/__PILLAR__CLUSTER_CIDR__/{{ pillar['service_cluster_ip_range'] }}/g +s/__MACHINE_GENERATED_WARNING__/Warning: This is a file generated from the base underscore template file: __SOURCE_FILENAME__/g diff --git a/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/transforms2sed.sed b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/transforms2sed.sed new file mode 100644 index 000000000..7d64f8e0b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/dns/kube-dns/transforms2sed.sed @@ -0,0 +1,4 @@ +s/__PILLAR__DNS__SERVER__/$DNS_SERVER_IP/g +s/__PILLAR__DNS__DOMAIN__/$DNS_DOMAIN/g +s/__PILLAR__CLUSTER_CIDR__/$SERVICE_CLUSTER_IP_RANGE/g +s/__MACHINE_GENERATED_WARNING__/Warning: This is a file generated from the base underscore template file: __SOURCE_FILENAME__/g diff --git a/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/etcd-empty-dir-cleanup.yaml b/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/etcd-empty-dir-cleanup.yaml deleted file mode 100644 index 8928310c7..000000000 --- a/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/etcd-empty-dir-cleanup.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: etcd-empty-dir-cleanup - namespace: kube-system - labels: - k8s-app: etcd-empty-dir-cleanup - kubernetes.io/cluster-service: "true" - addonmanager.kubernetes.io/mode: Reconcile ---- -apiVersion: v1 -kind: Pod -metadata: - name: etcd-empty-dir-cleanup - namespace: kube-system - annotations: - scheduler.alpha.kubernetes.io/critical-pod: '' - labels: - k8s-app: etcd-empty-dir-cleanup -spec: - priorityClassName: system-node-critical - serviceAccountName: etcd-empty-dir-cleanup - hostNetwork: true - dnsPolicy: Default - containers: - - name: etcd-empty-dir-cleanup - image: k8s.gcr.io/etcd-empty-dir-cleanup:3.1.12.0 diff --git a/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/podsecuritypolicies/etcd-empty-dir-cleanup-psp-binding.yaml b/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/podsecuritypolicies/etcd-empty-dir-cleanup-psp-binding.yaml deleted file mode 100644 index 77003f69c..000000000 --- a/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/podsecuritypolicies/etcd-empty-dir-cleanup-psp-binding.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: gce:podsecuritypolicy:etcd-empty-dir-cleanup - namespace: kube-system - labels: - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: gce:podsecuritypolicy:etcd-empty-dir-cleanup -subjects: -- kind: ServiceAccount - name: etcd-empty-dir-cleanup - namespace: kube-system diff --git a/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/podsecuritypolicies/etcd-empty-dir-cleanup-psp-role.yaml b/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/podsecuritypolicies/etcd-empty-dir-cleanup-psp-role.yaml deleted file mode 100644 index 6b577479d..000000000 --- a/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/podsecuritypolicies/etcd-empty-dir-cleanup-psp-role.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: gce:podsecuritypolicy:etcd-empty-dir-cleanup - namespace: kube-system - labels: - kubernetes.io/cluster-service: "true" - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: - - extensions - resourceNames: - - gce.etcd-empty-dir-cleanup - resources: - - podsecuritypolicies - verbs: - - use diff --git a/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/podsecuritypolicies/etcd-empty-dir-cleanup-psp.yaml b/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/podsecuritypolicies/etcd-empty-dir-cleanup-psp.yaml deleted file mode 100644 index d51c47811..000000000 --- a/vendor/k8s.io/kubernetes/cluster/addons/etcd-empty-dir-cleanup/podsecuritypolicies/etcd-empty-dir-cleanup-psp.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: PodSecurityPolicy -metadata: - name: gce.etcd-empty-dir-cleanup - annotations: - kubernetes.io/description: 'Policy used by the etcd-empty-dir-cleanup addon.' - # TODO: etcd-empty-dir-cleanup should run with the default seccomp profile - seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' - # 'runtime/default' is already the default, but must be filled in on the - # pod to pass admission. - apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' - labels: - kubernetes.io/cluster-service: 'true' - addonmanager.kubernetes.io/mode: Reconcile -spec: - privileged: false - volumes: - - 'secret' - hostNetwork: true - hostIPC: false - hostPID: false - runAsUser: - rule: 'RunAsAny' - seLinux: - rule: 'RunAsAny' - supplementalGroups: - rule: 'RunAsAny' - fsGroup: - rule: 'RunAsAny' - readOnlyRootFilesystem: false diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/OWNERS b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/OWNERS index 06843b466..0c5c18918 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/OWNERS +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/OWNERS @@ -1,8 +1,6 @@ approvers: - coffeepac -- crassirostris - piosz reviewers: - coffeepac -- crassirostris - piosz diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml index 84cf79f33..5b861084d 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml @@ -367,6 +367,22 @@ data: read_from_head true tag node-problem-detector + + + @id kernel + @type systemd + filters [{ "_TRANSPORT": "kernel" }] + + @type local + persistent true + + + fields_strip_underscores true + fields_lowercase true + + read_from_head true + tag kernel + forward.input.conf: |- # Takes the messages sent over TCP diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml index eecd6b480..6d8f959b7 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml @@ -71,6 +71,7 @@ spec: # Note that this does not guarantee admission on the nodes (#40573). annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-node-critical serviceAccountName: fluentd-es diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-image/run.sh b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-image/run.sh index 355701315..be0011b61 100755 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-image/run.sh +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/fluentd-es-image/run.sh @@ -20,4 +20,4 @@ # For systems without journald mkdir -p /var/log/journal -/usr/local/bin/fluentd $@ +exec /usr/local/bin/fluentd $@ diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml index 8cd00fe52..d6653dd15 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-elasticsearch/kibana-deployment.yaml @@ -16,6 +16,8 @@ spec: metadata: labels: k8s-app: kibana-logging + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: containers: - name: kibana-logging diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/OWNERS b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/OWNERS index 14bb6e15e..d70b164f0 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/OWNERS +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/OWNERS @@ -1,6 +1,6 @@ approvers: -- crassirostris - piosz +- x13n reviewers: -- crassirostris - piosz +- x13n diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/event-exporter.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/event-exporter.yaml index 1add52295..74df2e313 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/event-exporter.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/event-exporter.yaml @@ -29,11 +29,11 @@ subjects: apiVersion: apps/v1beta1 kind: Deployment metadata: - name: event-exporter-v0.2.1 + name: event-exporter-v0.2.2 namespace: kube-system labels: k8s-app: event-exporter - version: v0.2.1 + version: v0.2.2 kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: @@ -42,12 +42,12 @@ spec: metadata: labels: k8s-app: event-exporter - version: v0.2.1 + version: v0.2.2 spec: serviceAccountName: event-exporter-sa containers: - name: event-exporter - image: k8s.gcr.io/event-exporter:v0.2.1 + image: k8s.gcr.io/event-exporter:v0.2.2 command: - /event-exporter - -sink-opts=-stackdriver-resource-model={{ exporter_sd_resource_model }} diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/fluentd-gcp-configmap.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/fluentd-gcp-configmap.yaml index 03ef97e68..e345d593f 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/fluentd-gcp-configmap.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/fluentd-gcp-configmap.yaml @@ -98,6 +98,8 @@ data: # instead of jsonPayload after extracting 'time', 'severity' and # 'stream' from the record. message ${record['log']} + # If 'severity' is not set, assume stderr is ERROR and stdout is INFO. + severity ${record['severity'] || if record['stream'] == 'stderr' then 'ERROR' else 'INFO' end} tag ${if record['stream'] == 'stderr' then 'raw.stderr' else 'raw.stdout' end} remove_keys stream,log @@ -108,8 +110,8 @@ data: @type detect_exceptions remove_tag_prefix raw - message log - stream stream + message message + stream "logging.googleapis.com/local_resource_id" multiline_flush_interval 5 max_bytes 500000 max_lines 1000 @@ -299,6 +301,25 @@ data: read_from_head true tag node-problem-detector + + # BEGIN_NODE_JOURNAL + # Whether to include node-journal or not is determined when starting the + # cluster. It is not changed when the cluster is already running. + + @type systemd + pos_file /var/log/gcp-journald.pos + read_from_head true + tag node-journal + + + + @type grep + + key _SYSTEMD_UNIT + pattern ^(docker|{{ container_runtime }}|kubelet|node-problem-detector)\.service$ + + + # END_NODE_JOURNAL monitoring.conf: |- # This source is used to acquire approximate process start timestamp, # which purpose is explained before the corresponding output plugin. @@ -389,9 +410,9 @@ data: buffer_queue_full_action block # Set the chunk limit conservatively to avoid exceeding the recommended # chunk size of 5MB per write request. - buffer_chunk_limit 1M + buffer_chunk_limit 512k # Cap the combined memory usage of this buffer and the one below to - # 1MiB/chunk * (6 + 2) chunks = 8 MiB + # 512KiB/chunk * (6 + 2) chunks = 4 MiB buffer_queue_limit 6 # Never wait more than 5 seconds before flushing logs in the non-error case. flush_interval 5s @@ -402,8 +423,9 @@ data: # Use multiple threads for processing. num_threads 2 use_grpc true - # Use Metadata Agent to get monitored resource. - enable_metadata_agent true + # Skip timestamp adjustment as this is in a controlled environment with + # known timestamp format. This helps with CPU usage. + adjust_invalid_timestamps false # Attach local_resource_id for 'k8s_node' monitored resource. @@ -431,15 +453,16 @@ data: buffer_type file buffer_path /var/log/fluentd-buffers/kubernetes.system.buffer buffer_queue_full_action block - buffer_chunk_limit 1M + buffer_chunk_limit 512k buffer_queue_limit 2 flush_interval 5s max_retry_wait 30 disable_retry_limit num_threads 2 use_grpc true - # Use Metadata Agent to get monitored resource. - enable_metadata_agent true + # Skip timestamp adjustment as this is in a controlled environment with + # known timestamp format. This helps with CPU usage. + adjust_invalid_timestamps false metadata: name: fluentd-gcp-config-v1.2.5 diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml index 1b28506cb..963521abd 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml @@ -1,13 +1,13 @@ apiVersion: extensions/v1beta1 kind: DaemonSet metadata: - name: fluentd-gcp-v3.0.0 + name: fluentd-gcp-{{ fluentd_gcp_yaml_version }} namespace: kube-system labels: k8s-app: fluentd-gcp kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v3.0.0 + version: {{ fluentd_gcp_yaml_version }} spec: updateStrategy: type: RollingUpdate @@ -16,7 +16,7 @@ spec: labels: k8s-app: fluentd-gcp kubernetes.io/cluster-service: "true" - version: v3.0.0 + version: {{ fluentd_gcp_yaml_version }} # This annotation ensures that fluentd does not get evicted if the node # supports critical pod annotation based priority scheme. # Note that this does not guarantee admission on the nodes (#40573). diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/event-exporter-psp-role.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/event-exporter-psp-role.yaml index f360a87f4..1b0e02b2a 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/event-exporter-psp-role.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/event-exporter-psp-role.yaml @@ -8,7 +8,7 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - - extensions + - policy resourceNames: - gce.event-exporter resources: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/event-exporter-psp.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/event-exporter-psp.yaml index 48e57f7f0..319f3f5a0 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/event-exporter-psp.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/event-exporter-psp.yaml @@ -1,11 +1,11 @@ -apiVersion: extensions/v1beta1 +apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: gce.event-exporter annotations: kubernetes.io/description: 'Policy used by the event-exporter addon.' - # TODO: event-exporter should run with the default seccomp profile - seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'runtime/default,docker/default' # 'runtime/default' is already the default, but must be filled in on the # pod to pass admission. apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/fluentd-gcp-psp-role.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/fluentd-gcp-psp-role.yaml index 478257bf2..529d41b7a 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/fluentd-gcp-psp-role.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/fluentd-gcp-psp-role.yaml @@ -8,7 +8,7 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - - extensions + - policy resourceNames: - gce.fluentd-gcp resources: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/fluentd-gcp-psp.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/fluentd-gcp-psp.yaml index 36b3168f8..495ea5a33 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/fluentd-gcp-psp.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/podsecuritypolicies/fluentd-gcp-psp.yaml @@ -1,11 +1,11 @@ -apiVersion: extensions/v1beta1 +apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: gce.fluentd-gcp annotations: kubernetes.io/description: 'Policy used by the fluentd-gcp addon.' - # TODO: fluentd-gcp should run with the default seccomp profile - seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'runtime/default,docker/default' # 'runtime/default' is already the default, but must be filled in on the # pod to pass admission. apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' diff --git a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/scaler-deployment.yaml b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/scaler-deployment.yaml index 0dab0dcd3..64fb62779 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/scaler-deployment.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/fluentd-gcp/scaler-deployment.yaml @@ -19,10 +19,10 @@ spec: serviceAccountName: fluentd-gcp-scaler containers: - name: fluentd-gcp-scaler - image: gcr.io/google-containers/fluentd-gcp-scaler:0.3 + image: k8s.gcr.io/fluentd-gcp-scaler:0.3 command: - /scaler.sh - - --ds-name=fluentd-gcp-v3.0.0 + - --ds-name=fluentd-gcp-{{ fluentd_gcp_yaml_version }} - --scaling-policy=fluentd-gcp-scaling-policy env: # Defaults, used if no overrides are found in fluentd-gcp-scaling-policy @@ -30,5 +30,7 @@ spec: value: 100m - name: MEMORY_REQUEST value: 200Mi + - name: CPU_LIMIT + value: 1000m - name: MEMORY_LIMIT - value: 300Mi + value: 500Mi diff --git a/vendor/k8s.io/kubernetes/cluster/addons/ip-masq-agent/ip-masq-agent.yaml b/vendor/k8s.io/kubernetes/cluster/addons/ip-masq-agent/ip-masq-agent.yaml index 19a68b6b3..31520a411 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/ip-masq-agent/ip-masq-agent.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/ip-masq-agent/ip-masq-agent.yaml @@ -52,5 +52,9 @@ spec: - key: config path: ip-masq-agent tolerations: + - effect: NoSchedule + operator: Exists + - effect: NoExecute + operator: Exists - key: "CriticalAddonsOnly" operator: "Exists" diff --git a/vendor/k8s.io/kubernetes/cluster/addons/istio/auth/istio-auth.yaml b/vendor/k8s.io/kubernetes/cluster/addons/istio/auth/istio-auth.yaml index f87d4f2b2..6ecd26d59 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/istio/auth/istio-auth.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/istio/auth/istio-auth.yaml @@ -1,277 +1,1173 @@ -# GENERATED FILE. Use with Kubernetes 1.7+ -# TO UPDATE, modify files in install/kubernetes/templates and run install/updateVersion.sh -# -# Required for Istio as k8s addon. apiVersion: v1 kind: Namespace metadata: - name: default + name: kube-public labels: - istio-injection: enabled - addonmanager.kubernetes.io/mode: Reconcile --- -################################ -# Istio system namespace -################################ + istio-injection: disabled +--- apiVersion: v1 kind: Namespace metadata: - name: istio-system + name: kube-system labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile + istio-injection: disabled --- ################################ -# Istio RBAC +# Istio system namespace ################################ -# Permissions and roles for istio -# To debug: start the cluster with -vmodule=rbac,3 to enable verbose logging on RBAC DENY -# Also helps to enable logging on apiserver 'wrap' to see the URLs. -# Each RBAC deny needs to be mapped into a rule for the role. -# If using minikube, start with '--extra-config=apiserver.Authorization.Mode=RBAC' -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-pilot-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["config.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["*"] -- apiGroups: ["extensions"] - resources: ["thirdpartyresources", "thirdpartyresources.extensions", "ingresses", "ingresses/status"] - verbs: ["*"] -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "list", "watch", "update"] -- apiGroups: [""] - resources: ["endpoints", "pods", "services"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["namespaces", "nodes", "secrets"] - verbs: ["get", "list", "watch"] -- apiGroups: ["admissionregistration.k8s.io"] - resources: ["externaladmissionhookconfigurations"] - verbs: ["create", "update", "delete"] ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-injector-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["*"] - resources: ["configmaps"] - verbs: ["get", "list", "watch"] ---- -# Mixer CRD needs to watch and list CRDs -# It also uses discovery API to discover Kinds of config.istio.io -# K8s adapter needs to list pods, services etc. -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-mixer-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["config.istio.io"] # Istio CRD watcher - resources: ["*"] - verbs: ["get", "list", "watch"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] - verbs: ["get", "list", "watch"] ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ca-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create", "get", "watch", "list", "update"] -- apiGroups: [""] - resources: ["serviceaccounts"] - verbs: ["get", "watch", "list"] -- apiGroups: [""] - resources: ["services"] - verbs: ["get", "watch", "list"] ---- -# Permissions for the sidecar proxy. -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["extensions"] - resources: ["thirdpartyresources", "ingresses"] - verbs: ["get", "watch", "list", "update"] -- apiGroups: [""] - resources: ["configmaps", "pods", "endpoints", "services"] - verbs: ["get", "watch", "list"] ---- -# Grant permissions to the Pilot/discovery. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-pilot-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-pilot-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-pilot-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the Sidecar sidecar-injector -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-injector-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-sidecar-injector-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-sidecar-injector-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the CA. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ca-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-ca-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-ca-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the Ingress controller. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: v1 +kind: Namespace metadata: - name: istio-ingress-admin-role-binding-istio-system + name: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-ingress-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-pilot-istio-system - apiGroup: rbac.authorization.k8s.io + istio-injection: disabled --- -# Grant permissions to the sidecar. -# TEMPORARY: the istioctl should generate a separate service account for the proxy, and permission -# granted only to that account ! -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 +# Source: istio/charts/mixer/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap metadata: - name: istio-sidecar-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: default + name: istio-statsd-prom-bridge namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-sidecar-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to Mixer. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-mixer-admin-role-binding-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-mixer-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-mixer-istio-system - apiGroup: rbac.authorization.k8s.io + app: istio-statsd-prom-bridge + chart: mixer-0.8.0 + release: istio + heritage: Tiller + istio: mixer +data: + mapping.conf: |- --- -# Mixer apiVersion: v1 kind: ConfigMap metadata: - name: istio-mixer + name: istio-mixer-custom-resources namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-mixer + chart: mixer-0.8.0 + release: istio + heritage: Tiller + istio: mixer data: - mapping.conf: |- + custom-resources.yaml: |- + apiVersion: "config.istio.io/v1alpha2" + kind: attributemanifest + metadata: + name: istioproxy + namespace: istio-system + spec: + attributes: + origin.ip: + valueType: IP_ADDRESS + origin.uid: + valueType: STRING + origin.user: + valueType: STRING + request.headers: + valueType: STRING_MAP + request.id: + valueType: STRING + request.host: + valueType: STRING + request.method: + valueType: STRING + request.path: + valueType: STRING + request.reason: + valueType: STRING + request.referer: + valueType: STRING + request.scheme: + valueType: STRING + request.total_size: + valueType: INT64 + request.size: + valueType: INT64 + request.time: + valueType: TIMESTAMP + request.useragent: + valueType: STRING + response.code: + valueType: INT64 + response.duration: + valueType: DURATION + response.headers: + valueType: STRING_MAP + response.total_size: + valueType: INT64 + response.size: + valueType: INT64 + response.time: + valueType: TIMESTAMP + source.uid: + valueType: STRING + source.user: + valueType: STRING + destination.uid: + valueType: STRING + connection.id: + valueType: STRING + connection.received.bytes: + valueType: INT64 + connection.received.bytes_total: + valueType: INT64 + connection.sent.bytes: + valueType: INT64 + connection.sent.bytes_total: + valueType: INT64 + connection.duration: + valueType: DURATION + connection.mtls: + valueType: BOOL + context.protocol: + valueType: STRING + context.timestamp: + valueType: TIMESTAMP + context.time: + valueType: TIMESTAMP + api.service: + valueType: STRING + api.version: + valueType: STRING + api.operation: + valueType: STRING + api.protocol: + valueType: STRING + request.auth.principal: + valueType: STRING + request.auth.audiences: + valueType: STRING + request.auth.presenter: + valueType: STRING + request.auth.claims: + valueType: STRING_MAP + request.auth.raw_claims: + valueType: STRING + request.api_key: + valueType: STRING + + --- + apiVersion: "config.istio.io/v1alpha2" + kind: attributemanifest + metadata: + name: kubernetes + namespace: istio-system + spec: + attributes: + source.ip: + valueType: IP_ADDRESS + source.labels: + valueType: STRING_MAP + source.name: + valueType: STRING + source.namespace: + valueType: STRING + source.service: + valueType: STRING + source.serviceAccount: + valueType: STRING + destination.ip: + valueType: IP_ADDRESS + destination.labels: + valueType: STRING_MAP + destination.name: + valueType: STRING + destination.namespace: + valueType: STRING + destination.service: + valueType: STRING + destination.serviceAccount: + valueType: STRING + --- + apiVersion: "config.istio.io/v1alpha2" + kind: stdio + metadata: + name: handler + namespace: istio-system + spec: + outputAsJson: true + --- + apiVersion: "config.istio.io/v1alpha2" + kind: logentry + metadata: + name: accesslog + namespace: istio-system + spec: + severity: '"Info"' + timestamp: request.time + variables: + originIp: origin.ip | ip("0.0.0.0") + sourceIp: source.ip | ip("0.0.0.0") + sourceService: source.service | "" + sourceUser: source.user | source.uid | "" + sourceNamespace: source.namespace | "" + destinationIp: destination.ip | ip("0.0.0.0") + destinationService: destination.service | "" + destinationNamespace: destination.namespace | "" + apiName: api.service | "" + apiVersion: api.version | "" + apiClaims: request.headers["sec-istio-auth-userinfo"]| "" + apiKey: request.api_key | request.headers["x-api-key"] | "" + requestOperation: api.operation | "" + protocol: request.scheme | "http" + method: request.method | "" + url: request.path | "" + responseCode: response.code | 0 + responseSize: response.size | 0 + requestSize: request.size | 0 + latency: response.duration | "0ms" + connectionMtls: connection.mtls | false + userAgent: request.useragent | "" + responseTimestamp: response.time + receivedBytes: request.total_size | connection.received.bytes | 0 + sentBytes: response.total_size | connection.sent.bytes | 0 + referer: request.referer | "" + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: stdio + namespace: istio-system + spec: + match: "true" # If omitted match is true. + actions: + - handler: handler.stdio + instances: + - accesslog.logentry + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestcount + namespace: istio-system + spec: + value: "1" + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestduration + namespace: istio-system + spec: + value: response.duration | "0ms" + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestsize + namespace: istio-system + spec: + value: request.size | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: responsesize + namespace: istio-system + spec: + value: response.size | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: tcpbytesent + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp + spec: + value: connection.sent.bytes | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: tcpbytereceived + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp + spec: + value: connection.received.bytes | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: prometheus + metadata: + name: handler + namespace: istio-system + spec: + metrics: + - name: request_count + instance_name: requestcount.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + - name: request_duration + instance_name: requestduration.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + explicit_buckets: + bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] + - name: request_size + instance_name: requestsize.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + exponentialBuckets: + numFiniteBuckets: 8 + scale: 1 + growthFactor: 10 + - name: response_size + instance_name: responsesize.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + exponentialBuckets: + numFiniteBuckets: 8 + scale: 1 + growthFactor: 10 + - name: tcp_bytes_sent + instance_name: tcpbytesent.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - connection_mtls + - name: tcp_bytes_received + instance_name: tcpbytereceived.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - connection_mtls + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: promhttp + namespace: istio-system + labels: + istio-protocol: http + spec: + actions: + - handler: handler.prometheus + instances: + - requestcount.metric + - requestduration.metric + - requestsize.metric + - responsesize.metric + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: promtcp + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only execute when context.protocol == TCP + spec: + actions: + - handler: handler.prometheus + instances: + - tcpbytesent.metric + - tcpbytereceived.metric + --- + + apiVersion: "config.istio.io/v1alpha2" + kind: kubernetesenv + metadata: + name: handler + namespace: istio-system + spec: + # when running from mixer root, use the following config after adding a + # symbolic link to a kubernetes config file via: + # + # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig + # + # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" + + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: kubeattrgenrulerule + namespace: istio-system + spec: + actions: + - handler: handler.kubernetesenv + instances: + - attributes.kubernetes + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: tcpkubeattrgenrulerule + namespace: istio-system + spec: + match: context.protocol == "tcp" + actions: + - handler: handler.kubernetesenv + instances: + - attributes.kubernetes + --- + apiVersion: "config.istio.io/v1alpha2" + kind: kubernetes + metadata: + name: attributes + namespace: istio-system + spec: + # Pass the required attribute data to the adapter + source_uid: source.uid | "" + source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr + destination_uid: destination.uid | "" + origin_uid: '""' + origin_ip: ip("0.0.0.0") # default to unspecified ip addr + attribute_bindings: + # Fill the new attributes from the adapter produced output. + # $out refers to an instance of OutputTemplate message + source.ip: $out.source_pod_ip | ip("0.0.0.0") + source.labels: $out.source_labels | emptyStringMap() + source.namespace: $out.source_namespace | "default" + source.service: $out.source_service | "unknown" + source.serviceAccount: $out.source_service_account_name | "unknown" + destination.ip: $out.destination_pod_ip | ip("0.0.0.0") + destination.labels: $out.destination_labels | emptyStringMap() + destination.namespace: $out.destination_namespace | "default" + destination.service: $out.destination_service | "unknown" + destination.serviceAccount: $out.destination_service_account_name | "unknown" + --- + # Configuration needed by Mixer. + # Mixer cluster is delivered via CDS + # Specify mixer cluster settings + apiVersion: networking.istio.io/v1alpha3 + kind: DestinationRule + metadata: + name: istio-policy + namespace: istio-system + spec: + host: istio-policy.istio-system.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + name: grpc-mixer-mtls + tls: + mode: ISTIO_MUTUAL + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 + --- + apiVersion: networking.istio.io/v1alpha3 + kind: DestinationRule + metadata: + name: istio-telemetry + namespace: istio-system + spec: + host: istio-telemetry.istio-system.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + name: grpc-mixer-mtls + tls: + mode: ISTIO_MUTUAL + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 + --- + + --- +# Source: istio/charts/prometheus/templates/configmap.yaml apiVersion: v1 -kind: Service +kind: ConfigMap metadata: - name: istio-mixer + name: prometheus namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - istio: mixer -spec: - ports: - - name: tcp-plain - port: 9091 - - name: tcp-mtls - port: 15004 - - name: http-monitoring - port: 9093 - - name: configapi - port: 9094 - - name: statsd-prom - port: 9102 - - name: statsd-udp - port: 9125 - protocol: UDP - - name: prometheus - port: 42422 - selector: - istio: mixer + app: prometheus + chart: prometheus-0.1.0 + release: istio + heritage: Tiller +data: + prometheus.yml: |- + global: + scrape_interval: 15s + scrape_configs: + + - job_name: 'istio-mesh' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-telemetry;prometheus + + - job_name: 'envoy' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-statsd-prom-bridge;statsd-prom + + - job_name: 'istio-policy' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-policy;http-monitoring + + - job_name: 'istio-telemetry' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-telemetry;http-monitoring + + - job_name: 'pilot' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-pilot;http-monitoring + + # scrape config for API servers + - job_name: 'kubernetes-apiservers' + kubernetes_sd_configs: + - role: endpoints + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: default;kubernetes;https + + # scrape config for nodes (kubelet) + - job_name: 'kubernetes-nodes' + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/${1}/proxy/metrics + + # Scrape config for Kubelet cAdvisor. + # + # This is required for Kubernetes 1.7.3 and later, where cAdvisor metrics + # (those whose names begin with 'container_') have been removed from the + # Kubelet metrics endpoint. This job scrapes the cAdvisor endpoint to + # retrieve those metrics. + # + # In Kubernetes 1.7.0-1.7.2, these metrics are only exposed on the cAdvisor + # HTTP endpoint; use "replacement: /api/v1/nodes/${1}:4194/proxy/metrics" + # in that case (and ensure cAdvisor's HTTP server hasn't been disabled with + # the --cadvisor-port=0 Kubelet flag). + # + # This job is not necessary and should be removed in Kubernetes 1.6 and + # earlier versions, or it will cause the metrics to be scraped twice. + - job_name: 'kubernetes-cadvisor' + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor + + # scrape config for service endpoints. + - job_name: 'kubernetes-service-endpoints' + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: kubernetes_name + + # Example scrape config for pods + - job_name: 'kubernetes-pods' + kubernetes_sd_configs: + - role: pod + + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod_name + --- +# Source: istio/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio + chart: istio-0.8.0 + release: istio + heritage: Tiller +data: + mesh: |- + # Mutual TLS between proxies + authPolicy: MUTUAL_TLS + mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] + # + # Edit this list to avoid using mTLS to connect to these services. + # Typically, these are control services (e.g kubernetes API server) that don't have istio sidecar + # to transparently terminate mTLS authentication. + # mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] + + # Set the following variable to true to disable policy checks by the Mixer. + # Note that metrics will still be reported to the Mixer. + disablePolicyChecks: false + # Set enableTracing to false to disable request tracing. + enableTracing: true + # + # To disable the mixer completely (including metrics), comment out + # the following lines + mixerCheckServer: istio-policy.istio-system.svc.cluster.local:15004 + mixerReportServer: istio-telemetry.istio-system.svc.cluster.local:15004 + # This is the ingress service name, update if you used a different name + ingressService: istio-ingress + # + # Along with discoveryRefreshDelay, this setting determines how + # frequently should Envoy fetch and update its internal configuration + # from istio Pilot. Lower refresh delay results in higher CPU + # utilization and potential performance loss in exchange for faster + # convergence. Tweak this value according to your setup. + rdsRefreshDelay: 10s + # + defaultConfig: + # NOTE: If you change any values in this section, make sure to make + # the same changes in start up args in istio-ingress pods. + # See rdsRefreshDelay for explanation about this setting. + discoveryRefreshDelay: 10s + # + # TCP connection timeout between Envoy & the application, and between Envoys. + connectTimeout: 10s + # + ### ADVANCED SETTINGS ############# + # Where should envoy's configuration be stored in the istio-proxy container + configPath: "/etc/istio/proxy" + binaryPath: "/usr/local/bin/envoy" + # The pseudo service name used for Envoy. + serviceCluster: istio-proxy + # These settings that determine how long an old Envoy + # process should be kept alive after an occasional reload. + drainDuration: 45s + parentShutdownDuration: 1m0s + # + # The mode used to redirect inbound connections to Envoy. This setting + # has no effect on outbound traffic: iptables REDIRECT is always used for + # outbound connections. + # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. + # The "REDIRECT" mode loses source addresses during redirection. + # If "TPROXY", use iptables TPROXY to redirect to Envoy. + # The "TPROXY" mode preserves both the source and destination IP + # addresses and ports, so that they can be used for advanced filtering + # and manipulation. + # The "TPROXY" mode also configures the sidecar to run with the + # CAP_NET_ADMIN capability, which is required to use TPROXY. + #interceptionMode: REDIRECT + # + # Port where Envoy listens (on local host) for admin commands + # You can exec into the istio-proxy container in a pod and + # curl the admin port (curl http://localhost:15000/) to obtain + # diagnostic information from Envoy. See + # https://lyft.github.io/envoy/docs/operations/admin.html + # for more details + proxyAdminPort: 15000 + # + # Zipkin trace collector + zipkinAddress: zipkin.istio-system:9411 + # + # Statsd metrics collector converts statsd metrics into Prometheus metrics. + statsdUdpAddress: istio-statsd-prom-bridge.istio-system:9125 + # + # Mutual TLS authentication between sidecars and istio control plane. + controlPlaneAuthPolicy: MUTUAL_TLS + # + # Address where istio Pilot service is running + discoveryAddress: istio-pilot.istio-system:15005 + +--- +# Source: istio/templates/sidecar-injector-configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio + chart: istio-0.8.0 + release: istio + heritage: Tiller + istio: sidecar-injector +data: + config: |- + policy: enabled + template: |- + metadata: + annotations: + container.seccomp.security.alpha.kubernetes.io/istio-proxy: 'docker/default' + initContainers: + - name: istio-init + image: gcr.io/istio-release/proxy_init:0.8.0 + args: + - "-p" + - [[ .MeshConfig.ProxyListenPort ]] + - "-u" + - 1337 + - "-m" + - [[ or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String ]] + - "-i" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges" ]]" + [[ else -]] + - "*" + [[ end -]] + - "-x" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeOutboundIPRanges") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeOutboundIPRanges" ]]" + [[ else -]] + - "" + [[ end -]] + - "-b" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeInboundPorts") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeInboundPorts" ]]" + [[ else -]] + - [[ range .Spec.Containers -]][[ range .Ports -]][[ .ContainerPort -]], [[ end -]][[ end -]][[ end]] + - "-d" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeInboundPorts") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeInboundPorts" ]]" + [[ else -]] + - "" + [[ end -]] + imagePullPolicy: IfNotPresent + securityContext: + capabilities: + add: + - NET_ADMIN + privileged: true + restartPolicy: Always + + containers: + - name: istio-proxy + image: [[ if (isset .ObjectMeta.Annotations "sidecar.istio.io/proxyImage") -]] + "[[ index .ObjectMeta.Annotations "sidecar.istio.io/proxyImage" ]]" + [[ else -]] + gcr.io/istio-release/proxyv2:0.8.0 + [[ end -]] + args: + - proxy + - sidecar + - --configPath + - [[ .ProxyConfig.ConfigPath ]] + - --binaryPath + - [[ .ProxyConfig.BinaryPath ]] + - --serviceCluster + [[ if ne "" (index .ObjectMeta.Labels "app") -]] + - [[ index .ObjectMeta.Labels "app" ]] + [[ else -]] + - "istio-proxy" + [[ end -]] + - --drainDuration + - [[ formatDuration .ProxyConfig.DrainDuration ]] + - --parentShutdownDuration + - [[ formatDuration .ProxyConfig.ParentShutdownDuration ]] + - --discoveryAddress + - [[ .ProxyConfig.DiscoveryAddress ]] + - --discoveryRefreshDelay + - [[ formatDuration .ProxyConfig.DiscoveryRefreshDelay ]] + - --zipkinAddress + - [[ .ProxyConfig.ZipkinAddress ]] + - --connectTimeout + - [[ formatDuration .ProxyConfig.ConnectTimeout ]] + - --statsdUdpAddress + - [[ .ProxyConfig.StatsdUdpAddress ]] + - --proxyAdminPort + - [[ .ProxyConfig.ProxyAdminPort ]] + - --controlPlaneAuthPolicy + - [[ .ProxyConfig.ControlPlaneAuthPolicy ]] + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ISTIO_META_INTERCEPTION_MODE + value: [[ or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String ]] + imagePullPolicy: IfNotPresent + securityContext: + privileged: false + readOnlyRootFilesystem: true + [[ if eq (or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String) "TPROXY" -]] + capabilities: + add: + - NET_ADMIN + [[ else -]] + runAsUser: 1337 + [[ end -]] + restartPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - mountPath: /etc/istio/proxy + name: istio-envoy + - mountPath: /etc/certs/ + name: istio-certs + readOnly: true + volumes: + - emptyDir: + medium: Memory + name: istio-envoy + - name: istio-certs + secret: + optional: true + [[ if eq .Spec.ServiceAccountName "" -]] + secretName: istio.default + [[ else -]] + secretName: [[ printf "istio.%s" .Spec.ServiceAccountName ]] + [[ end -]] + + +--- +# Source: istio/charts/egressgateway/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-egressgateway-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: egressgateway + chart: egressgateway-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/ingress/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingress-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/ingressgateway/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingressgateway-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingressgateway + chart: ingressgateway-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/mixer/templates/create-custom-resources-job.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-mixer-post-install-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-mixer-post-install-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] # istio CRD watcher + resources: ["*"] + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: ["networking.istio.io"] # needed to create mixer destination rules + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-mixer-post-install-role-binding-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-mixer-post-install-istio-system +subjects: + - kind: ServiceAccount + name: istio-mixer-post-install-account + namespace: istio-system +--- + +apiVersion: batch/v1 +kind: Job +metadata: + name: istio-mixer-post-install + namespace: istio-system + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-delete-policy": before-hook-creation + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + release: istio + heritage: Tiller +spec: + template: + metadata: + name: istio-mixer-post-install + labels: + app: mixer + release: istio + spec: + serviceAccountName: istio-mixer-post-install-account + containers: + - name: hyperkube + image: "gcr.io/istio-release/coreos/hyperkube:v1.7.6_coreos.0" + command: + - ./kubectl + - apply + - -f + - /tmp/mixer/custom-resources.yaml + volumeMounts: + - mountPath: "/tmp/mixer" + name: tmp-configmap-mixer + volumes: + - name: tmp-configmap-mixer + configMap: + name: istio-mixer-custom-resources + restartPolicy: Never # CRD might take some time till they are available to consume + +--- +# Source: istio/charts/mixer/templates/serviceaccount.yaml + apiVersion: v1 kind: ServiceAccount metadata: @@ -280,82 +1176,85 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/charts/pilot/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-pilot-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/prometheus/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount metadata: - name: istio-mixer + name: prometheus + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +--- +# Source: istio/charts/security/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-citadel-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-cleanup-old-ca-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-sidecar-injector-service-account namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - istio: mixer - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-mixer-service-account - containers: - - name: statsd-to-prometheus - image: gcr.io/istio-release/statsd-exporter:v0.5.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9102 - - containerPort: 9125 - protocol: UDP - args: - - '-statsd.mapping-config=/etc/statsd/mapping.conf' - volumeMounts: - - name: config-volume - mountPath: /etc/statsd - - name: mixer - image: gcr.io/istio-release/mixer:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9091 - - containerPort: 9093 - - containerPort: 9094 - - containerPort: 42422 - args: - - --configStoreURL=k8s:// - - --configDefaultNamespace=istio-system - - --zipkinURL=http://zipkin:9411/api/v1/spans - - --logtostderr - - -v - - "2" - - name: istio-proxy - image: gcr.io/istio-release/proxy:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15004 - args: - - proxy - - mixer - - -v - - "2" - - --controlPlaneAuthPolicy - - MUTUAL_TLS - - --customConfigFile - - /etc/istio/proxy/envoy_mixer_auth.json - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.istio-mixer-service-account - optional: true - - name: config-volume - configMap: - name: istio-mixer ---- -# Mixer CRD definitions are generated using -# mixs crd all + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio +--- +# Source: istio/charts/mixer/templates/crds.yaml +# Mixer CRDs kind: CustomResourceDefinition apiVersion: apiextensions.k8s.io/v1beta1 metadata: @@ -363,6 +1262,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: istio.io.mixer istio: core spec: @@ -382,6 +1282,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: istio.io.mixer istio: core spec: @@ -401,6 +1302,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: circonus istio: mixer-adapter spec: @@ -420,6 +1322,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: denier istio: mixer-adapter spec: @@ -439,6 +1342,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: fluentd istio: mixer-adapter spec: @@ -458,6 +1362,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: kubernetesenv istio: mixer-adapter spec: @@ -477,6 +1382,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: listchecker istio: mixer-adapter spec: @@ -496,6 +1402,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: memquota istio: mixer-adapter spec: @@ -515,6 +1422,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: noop istio: mixer-adapter spec: @@ -534,6 +1442,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: opa istio: mixer-adapter spec: @@ -553,6 +1462,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: prometheus istio: mixer-adapter spec: @@ -572,6 +1482,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: rbac istio: mixer-adapter spec: @@ -591,6 +1502,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: servicecontrol istio: mixer-adapter spec: @@ -610,6 +1522,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: solarwinds istio: mixer-adapter spec: @@ -629,6 +1542,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: stackdriver istio: mixer-adapter spec: @@ -648,6 +1562,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: statsd istio: mixer-adapter spec: @@ -667,6 +1582,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: stdio istio: mixer-adapter spec: @@ -686,6 +1602,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: apikey istio: mixer-instance spec: @@ -705,6 +1622,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: authorization istio: mixer-instance spec: @@ -724,6 +1642,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: checknothing istio: mixer-instance spec: @@ -743,6 +1662,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: adapter.template.kubernetes istio: mixer-instance spec: @@ -762,6 +1682,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: listentry istio: mixer-instance spec: @@ -781,6 +1702,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: logentry istio: mixer-instance spec: @@ -800,6 +1722,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: metric istio: mixer-instance spec: @@ -819,6 +1742,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: quota istio: mixer-instance spec: @@ -838,6 +1762,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: reportnothing istio: mixer-instance spec: @@ -857,6 +1782,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: servicecontrolreport istio: mixer-instance spec: @@ -876,6 +1802,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: tracespan istio: mixer-instance spec: @@ -895,6 +1822,8 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer istio: rbac spec: group: config.istio.io @@ -913,6 +1842,8 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer istio: rbac spec: group: config.istio.io @@ -922,1180 +1853,1602 @@ spec: singular: servicerolebinding scope: Namespaced version: v1alpha2 ---- -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest +--- +# Source: istio/charts/pilot/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: - name: istioproxy - namespace: istio-system + name: destinationpolicies.config.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - attributes: - origin.ip: - valueType: IP_ADDRESS - origin.uid: - valueType: STRING - origin.user: - valueType: STRING - request.headers: - valueType: STRING_MAP - request.id: - valueType: STRING - request.host: - valueType: STRING - request.method: - valueType: STRING - request.path: - valueType: STRING - request.reason: - valueType: STRING - request.referer: - valueType: STRING - request.scheme: - valueType: STRING - request.size: - valueType: INT64 - request.time: - valueType: TIMESTAMP - request.useragent: - valueType: STRING - response.code: - valueType: INT64 - response.duration: - valueType: DURATION - response.headers: - valueType: STRING_MAP - response.size: - valueType: INT64 - response.time: - valueType: TIMESTAMP - source.uid: - valueType: STRING - source.user: - valueType: STRING - destination.uid: - valueType: STRING - connection.id: - valueType: STRING - connection.received.bytes: - valueType: INT64 - connection.received.bytes_total: - valueType: INT64 - connection.sent.bytes: - valueType: INT64 - connection.sent.bytes_total: - valueType: INT64 - connection.duration: - valueType: DURATION - context.protocol: - valueType: STRING - context.timestamp: - valueType: TIMESTAMP - context.time: - valueType: TIMESTAMP - api.service: - valueType: STRING - api.version: - valueType: STRING - api.operation: - valueType: STRING - api.protocol: - valueType: STRING - request.auth.principal: - valueType: STRING - request.auth.audiences: - valueType: STRING - request.auth.presenter: - valueType: STRING - request.api_key: - valueType: STRING - ---- -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest -metadata: - name: kubernetes - namespace: istio-system + group: config.istio.io + names: + kind: DestinationPolicy + listKind: DestinationPolicyList + plural: destinationpolicies + singular: destinationpolicy + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: egressrules.config.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - attributes: - source.ip: - valueType: IP_ADDRESS - source.labels: - valueType: STRING_MAP - source.name: - valueType: STRING - source.namespace: - valueType: STRING - source.service: - valueType: STRING - source.serviceAccount: - valueType: STRING - destination.ip: - valueType: IP_ADDRESS - destination.labels: - valueType: STRING_MAP - destination.name: - valueType: STRING - destination.namespace: - valueType: STRING - destination.service: - valueType: STRING - destination.serviceAccount: - valueType: STRING ---- -apiVersion: "config.istio.io/v1alpha2" -kind: stdio -metadata: - name: handler - namespace: istio-system + group: config.istio.io + names: + kind: EgressRule + listKind: EgressRuleList + plural: egressrules + singular: egressrule + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: routerules.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: config.istio.io + names: + kind: RouteRule + listKind: RouteRuleList + plural: routerules + singular: routerule + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: virtualservices.networking.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - outputAsJson: true + group: networking.istio.io + names: + kind: VirtualService + listKind: VirtualServiceList + plural: virtualservices + singular: virtualservice + scope: Namespaced + version: v1alpha3 --- -apiVersion: "config.istio.io/v1alpha2" -kind: logentry +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: - name: accesslog - namespace: istio-system + name: destinationrules.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: DestinationRule + listKind: DestinationRuleList + plural: destinationrules + singular: destinationrule + scope: Namespaced + version: v1alpha3 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: serviceentries.networking.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - severity: '"Default"' - timestamp: request.time - variables: - sourceIp: source.ip | ip("0.0.0.0") - destinationIp: destination.ip | ip("0.0.0.0") - sourceUser: source.user | "" - method: request.method | "" - url: request.path | "" - protocol: request.scheme | "http" - responseCode: response.code | 0 - responseSize: response.size | 0 - requestSize: request.size | 0 - latency: response.duration | "0ms" - monitored_resource_type: '"UNSPECIFIED"' + group: networking.istio.io + names: + kind: ServiceEntry + listKind: ServiceEntryList + plural: serviceentries + singular: serviceentry + scope: Namespaced + version: v1alpha3 --- -apiVersion: "config.istio.io/v1alpha2" -kind: rule +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: - name: stdio - namespace: istio-system + name: gateways.networking.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - match: "true" # If omitted match is true. - actions: - - handler: handler.stdio - instances: - - accesslog.logentry + group: networking.istio.io + names: + kind: Gateway + plural: gateways + singular: gateway + scope: Namespaced + version: v1alpha3 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: policies.authentication.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: authentication.istio.io + names: + kind: Policy + plural: policies + singular: policy + scope: Namespaced + version: v1alpha1 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: httpapispecbindings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: HTTPAPISpecBinding + plural: httpapispecbindings + singular: httpapispecbinding + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: httpapispecs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: HTTPAPISpec + plural: httpapispecs + singular: httpapispec + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotaspecbindings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: QuotaSpecBinding + plural: quotaspecbindings + singular: quotaspecbinding + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotaspecs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: QuotaSpec + plural: quotaspecs + singular: quotaspec + scope: Namespaced + version: v1alpha2 + + +--- +# Source: istio/charts/ingress/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + heritage: Tiller + release: istio + name: istio-ingress-istio-system +rules: +- apiGroups: ["extensions"] + resources: ["thirdpartyresources", "ingresses"] + verbs: ["get", "watch", "list", "update"] +- apiGroups: [""] + resources: ["configmaps", "pods", "endpoints", "services"] + verbs: ["get", "watch", "list"] + +--- +# Source: istio/charts/mixer/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-mixer-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] # istio CRD watcher + resources: ["*"] + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] + verbs: ["get", "list", "watch"] + +--- +# Source: istio/charts/pilot/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-pilot-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["networking.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["authentication.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["*"] +- apiGroups: ["extensions"] + resources: ["thirdpartyresources", "thirdpartyresources.extensions", "ingresses", "ingresses/status"] + verbs: ["*"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["endpoints", "pods", "services"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["namespaces", "nodes", "secrets"] + verbs: ["get", "list", "watch"] + --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: requestcount - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: "1" - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' +# Source: istio/charts/prometheus/templates/clusterrole.yaml + --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole metadata: - name: requestduration + name: prometheus-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - value: response.duration | "0ms" - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' +rules: +- apiGroups: [""] + resources: + - nodes + - services + - endpoints + - pods + - nodes/proxy + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: + - configmaps + verbs: ["get"] +- nonResourceURLs: ["/metrics"] + verbs: ["get"] --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: requestsize + name: prometheus-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - value: request.size | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' ---- -apiVersion: "config.istio.io/v1alpha2" -kind: metric -metadata: - name: responsesize +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: prometheus-istio-system +subjects: +- kind: ServiceAccount + name: prometheus namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - value: response.size | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric + + +--- +# Source: istio/charts/security/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole metadata: - name: tcpbytesent + name: istio-citadel-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp -spec: - value: connection.sent.bytes | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - monitored_resource_type: '"UNSPECIFIED"' + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "update", "delete"] +- apiGroups: [""] + resources: ["serviceaccounts"] + verbs: ["get", "watch", "list"] +- apiGroups: [""] + resources: ["services"] + verbs: ["get", "watch", "list"] --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: Role metadata: - name: tcpbytereceived + name: istio-cleanup-old-ca-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp -spec: - value: connection.received.bytes | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - monitored_resource_type: '"UNSPECIFIED"' + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: [""] + resources: ["deployments", "serviceaccounts", "services"] + verbs: ["get", "delete"] +- apiGroups: ["extensions"] + resources: ["deployments", "replicasets"] + verbs: ["get", "list", "update", "delete"] + --- -apiVersion: "config.istio.io/v1alpha2" -kind: prometheus +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole metadata: - name: handler - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - metrics: - - name: request_count - instance_name: requestcount.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - - name: request_duration - instance_name: requestduration.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - explicit_buckets: - bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] - - name: request_size - instance_name: requestsize.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - exponentialBuckets: - numFiniteBuckets: 8 - scale: 1 - growthFactor: 10 - - name: response_size - instance_name: responsesize.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - exponentialBuckets: - numFiniteBuckets: 8 - scale: 1 - growthFactor: 10 - - name: tcp_bytes_sent - instance_name: tcpbytesent.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version - - name: tcp_bytes_received - instance_name: tcpbytereceived.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: promhttp - namespace: istio-system + name: istio-sidecar-injector-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: http -spec: - actions: - - handler: handler.prometheus - instances: - - requestcount.metric - - requestduration.metric - - requestsize.metric - - responsesize.metric + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["*"] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "patch"] + --- -apiVersion: "config.istio.io/v1alpha2" -kind: rule +# Source: istio/charts/ingress/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: promtcp - namespace: istio-system + name: istio-ingress-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only execute when context.protocol == TCP -spec: - actions: - - handler: handler.prometheus - instances: - - tcpbytesent.metric - - tcpbytereceived.metric +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-ingress-service-account + namespace: istio-system + --- +# Source: istio/charts/mixer/templates/clusterrolebinding.yaml -apiVersion: "config.istio.io/v1alpha2" -kind: kubernetesenv +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: handler - namespace: istio-system + name: istio-mixer-admin-role-binding-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - # when running from mixer root, use the following config after adding a - # symbolic link to a kubernetes config file via: - # - # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig - # - # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-mixer-istio-system +subjects: + - kind: ServiceAccount + name: istio-mixer-service-account + namespace: istio-system --- -apiVersion: "config.istio.io/v1alpha2" -kind: rule +# Source: istio/charts/pilot/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: kubeattrgenrulerule - namespace: istio-system + name: istio-pilot-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - actions: - - handler: handler.kubernetesenv - instances: - - attributes.kubernetes + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-pilot-service-account + namespace: istio-system + --- -apiVersion: "config.istio.io/v1alpha2" -kind: kubernetes +# Source: istio/charts/security/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: attributes - namespace: istio-system + name: istio-citadel-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - # Pass the required attribute data to the adapter - source_uid: source.uid | "" - source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr - destination_uid: destination.uid | "" - destination_ip: destination.ip | ip("0.0.0.0") # default to unspecified ip addr - origin_uid: '""' - origin_ip: ip("0.0.0.0") # default to unspecified ip addr - attribute_bindings: - # Fill the new attributes from the adapter produced output. - # $out refers to an instance of OutputTemplate message - source.ip: $out.source_pod_ip | ip("0.0.0.0") - source.labels: $out.source_labels | emptyStringMap() - source.namespace: $out.source_namespace | "default" - source.service: $out.source_service | "unknown" - source.serviceAccount: $out.source_service_account_name | "unknown" - destination.ip: $out.destination_pod_ip | ip("0.0.0.0") - destination.labels: $out.destination_labels | emptyStringMap() - destination.namespace: $out.destination_namespace | "default" - destination.service: $out.destination_service | "unknown" - destination.serviceAccount: $out.destination_service_account_name | "unknown" + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-citadel-istio-system +subjects: + - kind: ServiceAccount + name: istio-citadel-service-account + namespace: istio-system --- -################################ -# Istio configMap cluster-wide -################################ -apiVersion: v1 -kind: ConfigMap +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding metadata: - name: istio + name: istio-cleanup-old-ca-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -data: - mesh: |- - # Uncomment the following line to enable mutual TLS between proxies - authPolicy: MUTUAL_TLS - # - # Edit this list to avoid using mTLS to connect to these services. - # Typically, these are control services (e.g kubernetes API server) that don't have Istio sidecar - # to transparently terminate mTLS authentication. - mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: istio-cleanup-old-ca-istio-system +subjects: + - kind: ServiceAccount + name: istio-cleanup-old-ca-service-account + namespace: istio-system - # Set the following variable to true to disable policy checks by the Mixer. - # Note that metrics will still be reported to the Mixer. - disablePolicyChecks: false - # Set enableTracing to false to disable request tracing. - enableTracing: true - # - # To disable the mixer completely (including metrics), comment out - # the following lines - mixerCheckServer: istio-mixer.istio-system:15004 - mixerReportServer: istio-mixer.istio-system:15004 - # This is the ingress service name, update if you used a different name - ingressService: istio-ingress - # - # Along with discoveryRefreshDelay, this setting determines how - # frequently should Envoy fetch and update its internal configuration - # from Istio Pilot. Lower refresh delay results in higher CPU - # utilization and potential performance loss in exchange for faster - # convergence. Tweak this value according to your setup. - rdsRefreshDelay: 1s - # - defaultConfig: - # NOTE: If you change any values in this section, make sure to make - # the same changes in start up args in istio-ingress pods. - # See rdsRefreshDelay for explanation about this setting. - discoveryRefreshDelay: 1s - # - # TCP connection timeout between Envoy & the application, and between Envoys. - connectTimeout: 10s - # - ### ADVANCED SETTINGS ############# - # Where should envoy's configuration be stored in the istio-proxy container - configPath: "/etc/istio/proxy" - binaryPath: "/usr/local/bin/envoy" - # The pseudo service name used for Envoy. - serviceCluster: istio-proxy - # These settings that determine how long an old Envoy - # process should be kept alive after an occasional reload. - drainDuration: 45s - parentShutdownDuration: 1m0s - # - # Port where Envoy listens (on local host) for admin commands - # You can exec into the istio-proxy container in a pod and - # curl the admin port (curl http://localhost:15000/) to obtain - # diagnostic information from Envoy. See - # https://lyft.github.io/envoy/docs/operations/admin.html - # for more details - proxyAdminPort: 15000 - # - # Address where Istio Pilot service is running - discoveryAddress: istio-pilot.istio-system:15003 - # - # Zipkin trace collector - zipkinAddress: zipkin.istio-system:9411 - # - # Statsd metrics collector. Istio mixer exposes a UDP endpoint - # to collect and convert statsd metrics into Prometheus metrics. - statsdUdpAddress: istio-mixer.istio-system:9125 - # Uncomment the following line to enable mutual TLS authentication between - # sidecars and istio control plane. - controlPlaneAuthPolicy: MUTUAL_TLS ---- -################################ -# Pilot -################################ -# Pilot CRDs -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: destinationpolicies.config.istio.io - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: DestinationPolicy - listKind: DestinationPolicyList - plural: destinationpolicies - singular: destinationpolicy - scope: Namespaced - version: v1alpha2 --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: egressrules.config.istio.io + name: istio-sidecar-injector-admin-role-binding-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: EgressRule - listKind: EgressRuleList - plural: egressrules - singular: egressrule - scope: Namespaced - version: v1alpha2 + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-sidecar-injector-istio-system +subjects: + - kind: ServiceAccount + name: istio-sidecar-injector-service-account + namespace: istio-system --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition +# Source: istio/charts/egressgateway/templates/service.yaml +apiVersion: v1 +kind: Service metadata: - name: routerules.config.istio.io + name: istio-egressgateway + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: egressgateway-0.8.0 + release: istio + heritage: Tiller + istio: egressgateway spec: - group: config.istio.io - names: - kind: RouteRule - listKind: RouteRuleList - plural: routerules - singular: routerule - scope: Namespaced - version: v1alpha2 + type: ClusterIP + selector: + istio: egressgateway + ports: + - + name: http + port: 80 + - + name: https + port: 443 + --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition +# Source: istio/charts/ingress/templates/service.yaml +apiVersion: v1 +kind: Service metadata: - name: v1alpha2routerules.config.istio.io + name: istio-ingress + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: V1alpha2RouteRule - listKind: V1alpha2RouteRuleList - plural: v1alpha2routerules - singular: v1alpha2routerule - scope: Namespaced - version: v1alpha2 + kubernetes.io/cluster-service: "true" + chart: ingress-0.8.0 + release: istio + heritage: Tiller + istio: ingress +spec: + type: LoadBalancer + selector: + istio: ingress + ports: + - + name: http + nodePort: 32000 + port: 80 + - + name: https + port: 443 --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition + +--- +# Source: istio/charts/ingressgateway/templates/service.yaml +apiVersion: v1 +kind: Service metadata: - name: destinationrules.config.istio.io + name: istio-ingressgateway + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: ingressgateway-0.8.0 + release: istio + heritage: Tiller + istio: ingressgateway spec: - group: config.istio.io - names: - kind: DestinationRule - listKind: DestinationRuleList - plural: destinationrules - singular: destinationrule - scope: Namespaced - version: v1alpha2 + type: LoadBalancer + selector: + istio: ingressgateway + ports: + - + name: http + nodePort: 31380 + port: 80 + - + name: https + nodePort: 31390 + port: 443 + - + name: tcp + nodePort: 31400 + port: 31400 + --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition +# Source: istio/charts/mixer/templates/service.yaml + +apiVersion: v1 +kind: Service metadata: - name: externalservices.config.istio.io + name: istio-policy + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: mixer spec: - group: config.istio.io - names: - kind: ExternalService - listKind: ExternalServiceList - plural: externalservices - singular: externalservice - scope: Namespaced - version: v1alpha2 + ports: + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 9093 + selector: + istio: mixer + istio-mixer-type: policy --- -# Pilot service for discovery apiVersion: v1 kind: Service metadata: - name: istio-pilot + name: istio-telemetry namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" - istio: pilot + chart: mixer-0.8.0 + release: istio + istio: mixer spec: ports: - - port: 15003 - name: http-discovery - - port: 8080 - name: http-legacy-discovery - - port: 9093 - name: http-monitoring - - port: 443 - name: admission-webhook + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 9093 + - name: prometheus + port: 42422 selector: - istio: pilot + istio: mixer + istio-mixer-type: telemetry +--- + +--- +# Source: istio/charts/mixer/templates/statsdtoprom.yaml + --- apiVersion: v1 -kind: ServiceAccount +kind: Service metadata: - name: istio-pilot-service-account + name: istio-statsd-prom-bridge namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: statsd-prom-bridge +spec: + ports: + - name: statsd-prom + port: 9102 + - name: statsd-udp + port: 9125 + protocol: UDP + selector: + istio: statsd-prom-bridge + --- + apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: istio-pilot + name: istio-statsd-prom-bridge namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer spec: template: metadata: labels: - istio: pilot + istio: statsd-prom-bridge annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: - serviceAccountName: istio-pilot-service-account + serviceAccountName: istio-mixer-service-account + volumes: + - name: config-volume + configMap: + name: istio-statsd-prom-bridge containers: - - name: discovery - image: gcr.io/istio-release/pilot:0.6.0 - imagePullPolicy: IfNotPresent - args: ["discovery", "-v", "2", "--admission-service", "istio-pilot"] - ports: - - containerPort: 8080 - - containerPort: 443 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: PILOT_THROTTLE - value: "200" - volumeMounts: - - name: config-volume - mountPath: /etc/istio/config - - name: istio-proxy - image: gcr.io/istio-release/proxy:0.6.0 + - name: statsd-prom-bridge + image: "gcr.io/istio-release/prom/statsd-exporter:v0.6.0" imagePullPolicy: IfNotPresent ports: - - containerPort: 15003 + - containerPort: 9102 + - containerPort: 9125 + protocol: UDP args: - - proxy - - pilot - - -v - - "2" - - --discoveryAddress - - istio-pilot:15003 - - --controlPlaneAuthPolicy - - MUTUAL_TLS - - --customConfigFile - - /etc/istio/proxy/envoy_pilot_auth.json + - '-statsd.mapping-config=/etc/statsd/mapping.conf' + resources: + {} + volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: config-volume - configMap: - name: istio - - name: istio-certs - secret: - secretName: istio.istio-pilot-service-account - optional: true + - name: config-volume + mountPath: /etc/statsd + --- -################################ -# Istio ingress -################################ +# Source: istio/charts/pilot/templates/service.yaml apiVersion: v1 kind: Service metadata: - name: istio-ingress + name: istio-pilot namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" - istio: ingress + app: istio-pilot + chart: pilot-0.8.0 + release: istio + heritage: Tiller spec: - type: LoadBalancer ports: - - port: 80 -# nodePort: 32000 - name: http - - port: 443 - name: https + - port: 15003 + name: http-old-discovery # mTLS or non-mTLS depending on auth setting + - port: 15005 + name: https-discovery # always mTLS + - port: 15007 + name: http-discovery # always plain-text + - port: 15010 + name: grpc-xds # direct + - port: 15011 + name: https-xds # mTLS + - port: 8080 + name: http-legacy-discovery # direct + - port: 9093 + name: http-monitoring selector: - istio: ingress + istio: pilot + --- +# Source: istio/charts/prometheus/templates/service.yaml apiVersion: v1 -kind: ServiceAccount +kind: Service metadata: - name: istio-ingress-service-account + name: prometheus + namespace: istio-system + annotations: + prometheus.io/scrape: 'true' + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + name: prometheus +spec: + selector: + app: prometheus + ports: + - name: http-prometheus + protocol: TCP + port: 9090 + +--- +# Source: istio/charts/security/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + # we use the normal name here (e.g. 'prometheus') + # as grafana is configured to use this as a data source + name: istio-citadel + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + app: istio-citadel +spec: + ports: + - name: grpc-citadel + port: 8060 + targetPort: 8060 + protocol: TCP + - name: http-monitoring + port: 9093 + selector: + istio: citadel + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-sidecar-injector namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + istio: sidecar-injector +spec: + ports: + - port: 443 + selector: + istio: sidecar-injector + --- +# Source: istio/charts/egressgateway/templates/deployment.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: istio-ingress + name: istio-egressgateway namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: egressgateway + chart: egressgateway-0.8.0 + release: istio + heritage: Tiller + istio: egressgateway spec: template: metadata: labels: - istio: ingress + istio: egressgateway annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: - serviceAccountName: istio-ingress-service-account + serviceAccountName: istio-egressgateway-service-account containers: - - name: istio-ingress - image: gcr.io/istio-release/proxy:0.6.0 - args: - - proxy - - ingress - - -v - - "2" - - --discoveryAddress - - istio-pilot:15003 - - --discoveryRefreshDelay - - '1s' #discoveryRefreshDelay - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - istio-ingress - - --zipkinAddress - - zipkin:9411 - - --statsdUdpAddress - - istio-mixer:9125 - - --proxyAdminPort - - "15000" - - --controlPlaneAuthPolicy - - MUTUAL_TLS - imagePullPolicy: IfNotPresent - ports: - - containerPort: 80 - - containerPort: 443 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: ingress-certs - mountPath: /etc/istio/ingress-certs - readOnly: true + - name: egressgateway + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + args: + - proxy + - router + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-egressgateway + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - MUTUAL_TLS + - --discoveryAddress + - istio-pilot:15005 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true volumes: - name: istio-certs secret: - secretName: istio.default - optional: true - - name: ingress-certs - secret: - secretName: istio-ingress-certs + secretName: "istio.default" optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- -################################ -# Istio-CA cluster-wide -################################ -# Service account CA -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-ca-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -# Istio CA watching all namespaces -apiVersion: v1 -kind: Deployment +# Source: istio/charts/ingress/templates/deployment.yaml apiVersion: extensions/v1beta1 +kind: Deployment metadata: - name: istio-ca + name: istio-ingress namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + release: istio + heritage: Tiller + istio: ingress spec: template: metadata: labels: - istio: istio-ca + istio: ingress annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: - serviceAccountName: istio-ca-service-account + serviceAccountName: istio-ingress-service-account containers: - - name: istio-ca - image: gcr.io/istio-release/istio-ca:0.6.0 - imagePullPolicy: IfNotPresent - command: ["/usr/local/bin/istio_ca"] - args: - - --istio-ca-storage-namespace=istio-system - - --grpc-port=8060 - - --grpc-hostname=istio-ca - - --self-signed-ca=true - - --logtostderr - - --stderrthreshold - - INFO ---- -apiVersion: v1 -kind: Service + - name: ingress + image: "gcr.io/istio-release/proxy:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + args: + - proxy + - ingress + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingress + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - MUTUAL_TLS + - --discoveryAddress + - istio-pilot:15005 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingress-certs + mountPath: /etc/istio/ingress-certs + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + - name: ingress-certs + secret: + secretName: istio-ingress-certs + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + +--- +# Source: istio/charts/ingressgateway/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment metadata: - name: grafana + name: istio-ingressgateway namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" + app: ingressgateway + chart: ingressgateway-0.8.0 + release: istio + heritage: Tiller + istio: ingressgateway spec: - ports: - - port: 3000 - protocol: TCP - name: http - selector: - app: grafana + template: + metadata: + labels: + istio: ingressgateway + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-ingressgateway-service-account + containers: + - name: ingressgateway + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + - containerPort: 31400 + args: + - proxy + - router + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingressgateway + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - MUTUAL_TLS + - --discoveryAddress + - istio-pilot:15005 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingressgateway-certs + mountPath: "/etc/istio/ingressgateway-certs" + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + - name: ingressgateway-certs + secret: + secretName: "istio-ingressgateway-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- +# Source: istio/charts/mixer/templates/deployment.yaml + apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: grafana + name: istio-policy namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer spec: template: metadata: labels: - app: grafana + istio: mixer + istio-mixer-type: policy annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: - serviceAccountName: grafana + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x containers: - - name: grafana - image: gcr.io/istio-release/grafana:0.6.0 + - name: mixer + image: "gcr.io/istio-release/mixer:0.8.0" imagePullPolicy: IfNotPresent ports: - - containerPort: 3000 - env: - # Only put environment related config here. Generic Istio config - # should go in addons/grafana/grafana.ini. - - name: GF_PATHS_DATA - value: /data/grafana - volumeMounts: - - mountPath: /data/grafana - name: grafana-data - volumes: - - name: grafana-data - emptyDir: {} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: grafana - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: prometheus - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -data: - prometheus.yml: |- - global: - scrape_interval: 15s - scrape_configs: - - - job_name: 'istio-mesh' - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - - kubernetes_sd_configs: - - role: endpoints - - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: istio-system;istio-mixer;prometheus - - - job_name: 'envoy' - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - # metrics_path defaults to '/metrics' - # scheme defaults to 'http'. - - kubernetes_sd_configs: - - role: endpoints - - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: istio-system;istio-mixer;statsd-prom - - - job_name: 'mixer' - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - # metrics_path defaults to '/metrics' - # scheme defaults to 'http'. - - kubernetes_sd_configs: - - role: endpoints - - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: istio-system;istio-mixer;http-monitoring - - - job_name: 'pilot' - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - # metrics_path defaults to '/metrics' - # scheme defaults to 'http'. - - kubernetes_sd_configs: - - role: endpoints - - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: istio-system;istio-pilot;http-monitoring - - # scrape config for API servers - - job_name: 'kubernetes-apiservers' - kubernetes_sd_configs: - - role: endpoints - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: default;kubernetes;https - - # scrape config for nodes (kubelet) - - job_name: 'kubernetes-nodes' - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - kubernetes_sd_configs: - - role: node - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/${1}/proxy/metrics - - # Scrape config for Kubelet cAdvisor. - # - # This is required for Kubernetes 1.7.3 and later, where cAdvisor metrics - # (those whose names begin with 'container_') have been removed from the - # Kubelet metrics endpoint. This job scrapes the cAdvisor endpoint to - # retrieve those metrics. - # - # In Kubernetes 1.7.0-1.7.2, these metrics are only exposed on the cAdvisor - # HTTP endpoint; use "replacement: /api/v1/nodes/${1}:4194/proxy/metrics" - # in that case (and ensure cAdvisor's HTTP server hasn't been disabled with - # the --cadvisor-port=0 Kubelet flag). - # - # This job is not necessary and should be removed in Kubernetes 1.6 and - # earlier versions, or it will cause the metrics to be scraped twice. - - job_name: 'kubernetes-cadvisor' - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - kubernetes_sd_configs: - - role: node - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor - - # scrape config for service endpoints. - - job_name: 'kubernetes-service-endpoints' - kubernetes_sd_configs: - - role: endpoints - relabel_configs: - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] - action: keep - regex: true - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] - action: replace - target_label: __scheme__ - regex: (https?) - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] - action: replace - target_label: __address__ - regex: ([^:]+)(?::\d+)?;(\d+) - replacement: $1:$2 - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_service_name] - action: replace - target_label: kubernetes_name - - # Example scrape config for pods - - job_name: 'kubernetes-pods' - kubernetes_sd_configs: - - role: pod - - relabel_configs: - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] - action: keep - regex: true - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] - action: replace - regex: ([^:]+)(?::\d+)?;(\d+) - replacement: $1:$2 - target_label: __address__ - - action: labelmap - regex: __meta_kubernetes_pod_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: namespace - - source_labels: [__meta_kubernetes_pod_name] - action: replace - target_label: pod_name + - containerPort: 9092 + - containerPort: 9093 + - containerPort: 42422 + args: + - --address + - tcp://127.0.0.1:9092 + - --configStoreURL=k8s:// + - --configDefaultNamespace=istio-system + - --trace_zipkin_url=http://zipkin:9411/api/v1/spans + resources: + {} + + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + args: + - proxy + - --serviceCluster + - istio-policy + - --templateFile + - /etc/istio/proxy/envoy_policy.yaml.tmpl + - --controlPlaneAuthPolicy + - MUTUAL_TLS + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true --- -apiVersion: v1 -kind: Service +apiVersion: extensions/v1beta1 +kind: Deployment metadata: - annotations: - prometheus.io/scrape: 'true' + name: istio-telemetry + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - name: prometheus - name: prometheus + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + template: + metadata: + labels: + istio: mixer + istio-mixer-type: telemetry + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + containers: + - name: mixer + image: "gcr.io/istio-release/mixer:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9092 + - containerPort: 9093 + - containerPort: 42422 + args: + - --address + - tcp://127.0.0.1:9092 + - --configStoreURL=k8s:// + - --configDefaultNamespace=istio-system + - --trace_zipkin_url=http://zipkin:9411/api/v1/spans + resources: + {} + + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + args: + - proxy + - --serviceCluster + - istio-telemetry + - --templateFile + - /etc/istio/proxy/envoy_telemetry.yaml.tmpl + - --controlPlaneAuthPolicy + - MUTUAL_TLS + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + +--- + +--- +# Source: istio/charts/pilot/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-pilot namespace: istio-system + # TODO: default tempate doesn't have this, which one is right ? + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + release: istio + heritage: Tiller + istio: pilot + annotations: + checksum/config-volume: f8da08b6b8c170dde721efd680270b2901e750d4aa186ebb6c22bef5b78a43f9 spec: - selector: - app: prometheus - ports: - - name: prometheus - protocol: TCP - port: 9090 + template: + metadata: + labels: + istio: pilot + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-pilot-service-account + containers: + - name: discovery + image: "gcr.io/istio-release/pilot:0.8.0" + imagePullPolicy: IfNotPresent + args: + - "discovery" +# TODO(sdake) remove when secrets are automagically registered + ports: + - containerPort: 8080 + - containerPort: 15010 + readinessProbe: + httpGet: + path: /v1/registration + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 5 + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: PILOT_THROTTLE + value: "500" + - name: PILOT_CACHE_SQUASH + value: "5" + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15003 + - containerPort: 15005 + - containerPort: 15007 + - containerPort: 15011 + args: + - proxy + - --serviceCluster + - istio-pilot + - --templateFile + - /etc/istio/proxy/envoy_pilot.yaml.tmpl + - --controlPlaneAuthPolicy + - MUTUAL_TLS + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: config-volume + configMap: + name: istio + - name: istio-certs + secret: + secretName: "istio.istio-pilot-service-account" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- +# Source: istio/charts/prometheus/templates/deployment.yaml +# TODO: the original template has service account, roles, etc apiVersion: extensions/v1beta1 kind: Deployment metadata: @@ -2104,132 +3457,451 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: prometheus + chart: prometheus-0.1.0 + release: istio + heritage: Tiller spec: selector: matchLabels: app: prometheus template: metadata: - name: prometheus labels: app: prometheus annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: serviceAccountName: prometheus + containers: - - name: prometheus - image: gcr.io/istio-release/prom/prometheus:v2.0.0 - imagePullPolicy: IfNotPresent - args: - - '--storage.tsdb.retention=6h' - - '--config.file=/etc/prometheus/prometheus.yml' - ports: - - name: web - containerPort: 9090 - volumeMounts: - - name: config-volume - mountPath: /etc/prometheus + - name: prometheus + image: "gcr.io/istio-release/prom/prometheus:v2.3.1" + imagePullPolicy: IfNotPresent + args: + - '--storage.tsdb.retention=6h' + - '--config.file=/etc/prometheus/prometheus.yml' + ports: + - containerPort: 9090 + name: http + livenessProbe: + httpGet: + path: /-/healthy + port: 9090 + readinessProbe: + httpGet: + path: /-/ready + port: 9090 + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/prometheus volumes: - name: config-volume configMap: name: prometheus + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- -apiVersion: v1 -kind: ServiceAccount +# Source: istio/charts/security/templates/deployment.yaml +# istio CA watching all namespaces +apiVersion: extensions/v1beta1 +kind: Deployment metadata: - name: prometheus + name: istio-citadel namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + release: istio + heritage: Tiller + istio: citadel +spec: + template: + metadata: + labels: + istio: citadel + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-citadel-service-account + containers: + - name: citadel + image: "gcr.io/istio-release/citadel:0.8.0" + imagePullPolicy: IfNotPresent + args: + - --append-dns-names=true + - --grpc-port=8060 + - --grpc-hostname=citadel + - --self-signed-ca=true + - --citadel-storage-namespace=istio-system + resources: + {} + + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRole -metadata: - name: prometheus - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: [""] - resources: - - nodes - - services - - endpoints - - pods - - nodes/proxy - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: - - configmaps - verbs: ["get"] -- nonResourceURLs: ["/metrics"] - verbs: ["get"] ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRoleBinding +# Source: istio/charts/sidecarInjectorWebhook/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment metadata: - name: prometheus + name: istio-sidecar-injector + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: prometheus -subjects: -- kind: ServiceAccount - name: prometheus - namespace: istio-system ---- + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook-0.8.0 + release: istio + heritage: Tiller + istio: sidecar-injector +spec: + template: + metadata: + labels: + istio: sidecar-injector + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-sidecar-injector-service-account + containers: + - name: sidecar-injector-webhook + image: "gcr.io/istio-release/sidecar_injector:0.8.0" + imagePullPolicy: IfNotPresent + args: + - --caCertFile=/etc/istio/certs/root-cert.pem + - --tlsCertFile=/etc/istio/certs/cert-chain.pem + - --tlsKeyFile=/etc/istio/certs/key.pem + - --injectConfig=/etc/istio/inject/config + - --meshConfig=/etc/istio/config/mesh + - --healthCheckInterval=2s + - --healthCheckFile=/health + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + readOnly: true + - name: certs + mountPath: /etc/istio/certs + readOnly: true + - name: inject-config + mountPath: /etc/istio/inject + readOnly: true + livenessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=2s + initialDelaySeconds: 4 + periodSeconds: 4 + readinessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=2s + initialDelaySeconds: 4 + periodSeconds: 4 + volumes: + - name: config-volume + configMap: + name: istio + - name: certs + secret: + secretName: istio.istio-sidecar-injector-service-account + - name: inject-config + configMap: + name: istio-sidecar-injector + items: + - key: config + path: config + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/charts/security/templates/cleanup-old-ca.yaml + +apiVersion: batch/v1 +kind: Job metadata: - name: servicegraph + name: istio-cleanup-old-ca namespace: istio-system + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-delete-policy": hook-succeeded labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + release: istio + heritage: Tiller spec: template: metadata: + name: istio-cleanup-old-ca labels: - app: servicegraph - annotations: - sidecar.istio.io/inject: "false" + app: security + release: istio spec: + serviceAccountName: istio-cleanup-old-ca-service-account containers: - - name: servicegraph - image: gcr.io/istio-release/servicegraph:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8088 - args: - - --prometheusAddr=http://prometheus:9090 + - name: hyperkube + image: "gcr.io/istio-release/coreos/hyperkube:v1.7.6_coreos.0" + command: + - /bin/bash + - -c + - > + NS="-n istio-system"; + ./kubectl get deploy istio-ca $NS; + if [[ $? = 0 ]]; then ./kubectl delete deploy istio-ca $NS; fi; + ./kubectl get serviceaccount istio-ca-service-account $NS; + if [[ $? = 0 ]]; then ./kubectl delete serviceaccount istio-ca-service-account $NS; fi; + ./kubectl get service istio-ca-ilb $NS; + if [[ $? = 0 ]]; then ./kubectl delete service istio-ca-ilb $NS; fi + restartPolicy: Never +--- +# Source: istio/charts/egressgateway/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-egressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-egressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/ingress/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingress + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-ingress + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/ingressgateway/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-ingressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/mutatingwebhook.yaml +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + release: istio + heritage: Tiller +webhooks: + - name: sidecar-injector.istio.io + clientConfig: + service: + name: istio-sidecar-injector + namespace: istio-system + path: "/inject" + caBundle: "" + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + failurePolicy: Fail + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: NotIn + values: + - disabled +--- +# Source: istio/charts/mixer/templates/config.yaml + + +--- +# Source: istio/charts/prometheus/templates/ingress.yaml --- apiVersion: v1 kind: Service metadata: - name: servicegraph + name: grafana namespace: istio-system + annotations: + auth.istio.io/3000: NONE labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" spec: ports: - - name: http - port: 8088 + - port: 3000 + protocol: TCP + name: http selector: - app: servicegraph ---- + app: grafana --- apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: zipkin + name: grafana namespace: istio-system labels: k8s-app: istio @@ -2238,36 +3910,36 @@ spec: template: metadata: labels: - app: zipkin + app: grafana annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: + serviceAccountName: grafana containers: - - name: zipkin - image: gcr.io/istio-release/zipkin:2.5.3 + - name: grafana + image: gcr.io/istio-release/grafana:0.8.0 imagePullPolicy: IfNotPresent ports: - - containerPort: 9411 + - containerPort: 3000 env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace + # Only put environment related config here. Generic Istio config + # should go in addons/grafana/grafana.ini. + - name: GF_PATHS_DATA + value: /data/grafana + volumeMounts: + - mountPath: /data/grafana + name: grafana-data + volumes: + - name: grafana-data + emptyDir: {} --- apiVersion: v1 -kind: Service +kind: ServiceAccount metadata: - name: zipkin + name: grafana namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" -spec: - ports: - - name: http - port: 9411 - selector: - app: zipkin --- diff --git a/vendor/k8s.io/kubernetes/cluster/addons/istio/noauth/istio.yaml b/vendor/k8s.io/kubernetes/cluster/addons/istio/noauth/istio.yaml index ba798b9df..cd44cbef4 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/istio/noauth/istio.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/istio/noauth/istio.yaml @@ -1,361 +1,1247 @@ -# GENERATED FILE. Use with Kubernetes 1.7+ -# TO UPDATE, modify files in install/kubernetes/templates and run install/updateVersion.sh -# -# Required for Istio as k8s addon. apiVersion: v1 kind: Namespace metadata: - name: default + name: kube-public labels: - istio-injection: enabled - addonmanager.kubernetes.io/mode: Reconcile + istio-injection: disabled --- -################################ -# Istio system namespace -################################ apiVersion: v1 kind: Namespace metadata: - name: istio-system + name: kube-system labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile + istio-injection: disabled --- ################################ -# Istio RBAC +# Istio system namespace ################################ -# Permissions and roles for istio -# To debug: start the cluster with -vmodule=rbac,3 to enable verbose logging on RBAC DENY -# Also helps to enable logging on apiserver 'wrap' to see the URLs. -# Each RBAC deny needs to be mapped into a rule for the role. -# If using minikube, start with '--extra-config=apiserver.Authorization.Mode=RBAC' -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-pilot-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["config.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["*"] -- apiGroups: ["extensions"] - resources: ["thirdpartyresources", "thirdpartyresources.extensions", "ingresses", "ingresses/status"] - verbs: ["*"] -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "list", "watch", "update"] -- apiGroups: [""] - resources: ["endpoints", "pods", "services"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["namespaces", "nodes", "secrets"] - verbs: ["get", "list", "watch"] -- apiGroups: ["admissionregistration.k8s.io"] - resources: ["externaladmissionhookconfigurations"] - verbs: ["create", "update", "delete"] ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-injector-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["*"] - resources: ["configmaps"] - verbs: ["get", "list", "watch"] ---- -# Mixer CRD needs to watch and list CRDs -# It also uses discovery API to discover Kinds of config.istio.io -# K8s adapter needs to list pods, services etc. -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-mixer-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["config.istio.io"] # Istio CRD watcher - resources: ["*"] - verbs: ["get", "list", "watch"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] - verbs: ["get", "list", "watch"] ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ca-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create", "get", "watch", "list", "update"] -- apiGroups: [""] - resources: ["serviceaccounts"] - verbs: ["get", "watch", "list"] -- apiGroups: [""] - resources: ["services"] - verbs: ["get", "watch", "list"] ---- -# Permissions for the sidecar proxy. -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: ["extensions"] - resources: ["thirdpartyresources", "ingresses"] - verbs: ["get", "watch", "list", "update"] -- apiGroups: [""] - resources: ["configmaps", "pods", "endpoints", "services"] - verbs: ["get", "watch", "list"] ---- -# Grant permissions to the Pilot/discovery. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-pilot-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-pilot-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-pilot-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the Sidecar sidecar-injector -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-sidecar-injector-admin-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-sidecar-injector-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-sidecar-injector-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the CA. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-ca-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-ca-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-ca-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to the Ingress controller. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: v1 +kind: Namespace metadata: - name: istio-ingress-admin-role-binding-istio-system + name: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-ingress-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-pilot-istio-system - apiGroup: rbac.authorization.k8s.io + istio-injection: disabled --- -# Grant permissions to the sidecar. -# TEMPORARY: the istioctl should generate a separate service account for the proxy, and permission -# granted only to that account ! -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 +# Source: istio/charts/mixer/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap metadata: - name: istio-sidecar-role-binding-istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: default + name: istio-statsd-prom-bridge namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-sidecar-istio-system - apiGroup: rbac.authorization.k8s.io ---- -# Grant permissions to Mixer. -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: istio-mixer-admin-role-binding-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -subjects: -- kind: ServiceAccount - name: istio-mixer-service-account - namespace: istio-system -roleRef: - kind: ClusterRole - name: istio-mixer-istio-system - apiGroup: rbac.authorization.k8s.io + app: istio-statsd-prom-bridge + chart: mixer-0.8.0 + release: istio + heritage: Tiller + istio: mixer +data: + mapping.conf: |- --- -# Mixer apiVersion: v1 kind: ConfigMap metadata: - name: istio-mixer + name: istio-mixer-custom-resources namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-mixer + chart: mixer-0.8.0 + release: istio + heritage: Tiller + istio: mixer data: - mapping.conf: |- + custom-resources.yaml: |- + apiVersion: "config.istio.io/v1alpha2" + kind: attributemanifest + metadata: + name: istioproxy + namespace: istio-system + spec: + attributes: + origin.ip: + valueType: IP_ADDRESS + origin.uid: + valueType: STRING + origin.user: + valueType: STRING + request.headers: + valueType: STRING_MAP + request.id: + valueType: STRING + request.host: + valueType: STRING + request.method: + valueType: STRING + request.path: + valueType: STRING + request.reason: + valueType: STRING + request.referer: + valueType: STRING + request.scheme: + valueType: STRING + request.total_size: + valueType: INT64 + request.size: + valueType: INT64 + request.time: + valueType: TIMESTAMP + request.useragent: + valueType: STRING + response.code: + valueType: INT64 + response.duration: + valueType: DURATION + response.headers: + valueType: STRING_MAP + response.total_size: + valueType: INT64 + response.size: + valueType: INT64 + response.time: + valueType: TIMESTAMP + source.uid: + valueType: STRING + source.user: + valueType: STRING + destination.uid: + valueType: STRING + connection.id: + valueType: STRING + connection.received.bytes: + valueType: INT64 + connection.received.bytes_total: + valueType: INT64 + connection.sent.bytes: + valueType: INT64 + connection.sent.bytes_total: + valueType: INT64 + connection.duration: + valueType: DURATION + connection.mtls: + valueType: BOOL + context.protocol: + valueType: STRING + context.timestamp: + valueType: TIMESTAMP + context.time: + valueType: TIMESTAMP + api.service: + valueType: STRING + api.version: + valueType: STRING + api.operation: + valueType: STRING + api.protocol: + valueType: STRING + request.auth.principal: + valueType: STRING + request.auth.audiences: + valueType: STRING + request.auth.presenter: + valueType: STRING + request.auth.claims: + valueType: STRING_MAP + request.auth.raw_claims: + valueType: STRING + request.api_key: + valueType: STRING + + --- + apiVersion: "config.istio.io/v1alpha2" + kind: attributemanifest + metadata: + name: kubernetes + namespace: istio-system + spec: + attributes: + source.ip: + valueType: IP_ADDRESS + source.labels: + valueType: STRING_MAP + source.name: + valueType: STRING + source.namespace: + valueType: STRING + source.service: + valueType: STRING + source.serviceAccount: + valueType: STRING + destination.ip: + valueType: IP_ADDRESS + destination.labels: + valueType: STRING_MAP + destination.name: + valueType: STRING + destination.namespace: + valueType: STRING + destination.service: + valueType: STRING + destination.serviceAccount: + valueType: STRING + --- + apiVersion: "config.istio.io/v1alpha2" + kind: stdio + metadata: + name: handler + namespace: istio-system + spec: + outputAsJson: true + --- + apiVersion: "config.istio.io/v1alpha2" + kind: logentry + metadata: + name: accesslog + namespace: istio-system + spec: + severity: '"Info"' + timestamp: request.time + variables: + originIp: origin.ip | ip("0.0.0.0") + sourceIp: source.ip | ip("0.0.0.0") + sourceService: source.service | "" + sourceUser: source.user | source.uid | "" + sourceNamespace: source.namespace | "" + destinationIp: destination.ip | ip("0.0.0.0") + destinationService: destination.service | "" + destinationNamespace: destination.namespace | "" + apiName: api.service | "" + apiVersion: api.version | "" + apiClaims: request.headers["sec-istio-auth-userinfo"]| "" + apiKey: request.api_key | request.headers["x-api-key"] | "" + requestOperation: api.operation | "" + protocol: request.scheme | "http" + method: request.method | "" + url: request.path | "" + responseCode: response.code | 0 + responseSize: response.size | 0 + requestSize: request.size | 0 + latency: response.duration | "0ms" + connectionMtls: connection.mtls | false + userAgent: request.useragent | "" + responseTimestamp: response.time + receivedBytes: request.total_size | connection.received.bytes | 0 + sentBytes: response.total_size | connection.sent.bytes | 0 + referer: request.referer | "" + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: stdio + namespace: istio-system + spec: + match: "true" # If omitted match is true. + actions: + - handler: handler.stdio + instances: + - accesslog.logentry + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestcount + namespace: istio-system + spec: + value: "1" + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestduration + namespace: istio-system + spec: + value: response.duration | "0ms" + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: requestsize + namespace: istio-system + spec: + value: request.size | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: responsesize + namespace: istio-system + spec: + value: response.size | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + response_code: response.code | 200 + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: tcpbytesent + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp + spec: + value: connection.sent.bytes | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: metric + metadata: + name: tcpbytereceived + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp + spec: + value: connection.received.bytes | 0 + dimensions: + source_service: source.service | "unknown" + source_version: source.labels["version"] | "unknown" + destination_service: destination.service | "unknown" + destination_version: destination.labels["version"] | "unknown" + connection_mtls: connection.mtls | false + monitored_resource_type: '"UNSPECIFIED"' + --- + apiVersion: "config.istio.io/v1alpha2" + kind: prometheus + metadata: + name: handler + namespace: istio-system + spec: + metrics: + - name: request_count + instance_name: requestcount.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + - name: request_duration + instance_name: requestduration.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + explicit_buckets: + bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] + - name: request_size + instance_name: requestsize.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + exponentialBuckets: + numFiniteBuckets: 8 + scale: 1 + growthFactor: 10 + - name: response_size + instance_name: responsesize.metric.istio-system + kind: DISTRIBUTION + label_names: + - source_service + - source_version + - destination_service + - destination_version + - response_code + - connection_mtls + buckets: + exponentialBuckets: + numFiniteBuckets: 8 + scale: 1 + growthFactor: 10 + - name: tcp_bytes_sent + instance_name: tcpbytesent.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - connection_mtls + - name: tcp_bytes_received + instance_name: tcpbytereceived.metric.istio-system + kind: COUNTER + label_names: + - source_service + - source_version + - destination_service + - destination_version + - connection_mtls + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: promhttp + namespace: istio-system + labels: + istio-protocol: http + spec: + actions: + - handler: handler.prometheus + instances: + - requestcount.metric + - requestduration.metric + - requestsize.metric + - responsesize.metric + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: promtcp + namespace: istio-system + labels: + istio-protocol: tcp # needed so that mixer will only execute when context.protocol == TCP + spec: + actions: + - handler: handler.prometheus + instances: + - tcpbytesent.metric + - tcpbytereceived.metric + --- + + apiVersion: "config.istio.io/v1alpha2" + kind: kubernetesenv + metadata: + name: handler + namespace: istio-system + spec: + # when running from mixer root, use the following config after adding a + # symbolic link to a kubernetes config file via: + # + # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig + # + # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" + + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: kubeattrgenrulerule + namespace: istio-system + spec: + actions: + - handler: handler.kubernetesenv + instances: + - attributes.kubernetes + --- + apiVersion: "config.istio.io/v1alpha2" + kind: rule + metadata: + name: tcpkubeattrgenrulerule + namespace: istio-system + spec: + match: context.protocol == "tcp" + actions: + - handler: handler.kubernetesenv + instances: + - attributes.kubernetes + --- + apiVersion: "config.istio.io/v1alpha2" + kind: kubernetes + metadata: + name: attributes + namespace: istio-system + spec: + # Pass the required attribute data to the adapter + source_uid: source.uid | "" + source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr + destination_uid: destination.uid | "" + origin_uid: '""' + origin_ip: ip("0.0.0.0") # default to unspecified ip addr + attribute_bindings: + # Fill the new attributes from the adapter produced output. + # $out refers to an instance of OutputTemplate message + source.ip: $out.source_pod_ip | ip("0.0.0.0") + source.labels: $out.source_labels | emptyStringMap() + source.namespace: $out.source_namespace | "default" + source.service: $out.source_service | "unknown" + source.serviceAccount: $out.source_service_account_name | "unknown" + destination.ip: $out.destination_pod_ip | ip("0.0.0.0") + destination.labels: $out.destination_labels | emptyStringMap() + destination.namespace: $out.destination_namespace | "default" + destination.service: $out.destination_service | "unknown" + destination.serviceAccount: $out.destination_service_account_name | "unknown" + --- + # Configuration needed by Mixer. + # Mixer cluster is delivered via CDS + # Specify mixer cluster settings + apiVersion: networking.istio.io/v1alpha3 + kind: DestinationRule + metadata: + name: istio-policy + namespace: istio-system + spec: + host: istio-policy.istio-system.svc.cluster.local + trafficPolicy: + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 + --- + apiVersion: networking.istio.io/v1alpha3 + kind: DestinationRule + metadata: + name: istio-telemetry + namespace: istio-system + spec: + host: istio-telemetry.istio-system.svc.cluster.local + trafficPolicy: + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 + --- + + --- +# Source: istio/charts/prometheus/templates/configmap.yaml apiVersion: v1 -kind: Service +kind: ConfigMap metadata: - name: istio-mixer + name: prometheus namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - istio: mixer -spec: - ports: - - name: tcp-plain - port: 9091 - - name: tcp-mtls - port: 15004 - - name: http-monitoring - port: 9093 - - name: configapi - port: 9094 - - name: statsd-prom - port: 9102 - - name: statsd-udp - port: 9125 - protocol: UDP - - name: prometheus - port: 42422 - selector: - istio: mixer + app: prometheus + chart: prometheus-0.1.0 + release: istio + heritage: Tiller +data: + prometheus.yml: |- + global: + scrape_interval: 15s + scrape_configs: + + - job_name: 'istio-mesh' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-telemetry;prometheus + + - job_name: 'envoy' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-statsd-prom-bridge;statsd-prom + + - job_name: 'istio-policy' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-policy;http-monitoring + + - job_name: 'istio-telemetry' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-telemetry;http-monitoring + + - job_name: 'pilot' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-system;istio-pilot;http-monitoring + + # scrape config for API servers + - job_name: 'kubernetes-apiservers' + kubernetes_sd_configs: + - role: endpoints + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: default;kubernetes;https + + # scrape config for nodes (kubelet) + - job_name: 'kubernetes-nodes' + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/${1}/proxy/metrics + + # Scrape config for Kubelet cAdvisor. + # + # This is required for Kubernetes 1.7.3 and later, where cAdvisor metrics + # (those whose names begin with 'container_') have been removed from the + # Kubelet metrics endpoint. This job scrapes the cAdvisor endpoint to + # retrieve those metrics. + # + # In Kubernetes 1.7.0-1.7.2, these metrics are only exposed on the cAdvisor + # HTTP endpoint; use "replacement: /api/v1/nodes/${1}:4194/proxy/metrics" + # in that case (and ensure cAdvisor's HTTP server hasn't been disabled with + # the --cadvisor-port=0 Kubelet flag). + # + # This job is not necessary and should be removed in Kubernetes 1.6 and + # earlier versions, or it will cause the metrics to be scraped twice. + - job_name: 'kubernetes-cadvisor' + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor + + # scrape config for service endpoints. + - job_name: 'kubernetes-service-endpoints' + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: kubernetes_name + + # Example scrape config for pods + - job_name: 'kubernetes-pods' + kubernetes_sd_configs: + - role: pod + + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod_name + +--- +# Source: istio/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio + chart: istio-0.8.0 + release: istio + heritage: Tiller +data: + mesh: |- + # + # Edit this list to avoid using mTLS to connect to these services. + # Typically, these are control services (e.g kubernetes API server) that don't have istio sidecar + # to transparently terminate mTLS authentication. + # mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] + + # Set the following variable to true to disable policy checks by the Mixer. + # Note that metrics will still be reported to the Mixer. + disablePolicyChecks: false + # Set enableTracing to false to disable request tracing. + enableTracing: true + # + # To disable the mixer completely (including metrics), comment out + # the following lines + mixerCheckServer: istio-policy.istio-system.svc.cluster.local:15004 + mixerReportServer: istio-telemetry.istio-system.svc.cluster.local:15004 + # This is the ingress service name, update if you used a different name + ingressService: istio-ingress + # + # Along with discoveryRefreshDelay, this setting determines how + # frequently should Envoy fetch and update its internal configuration + # from istio Pilot. Lower refresh delay results in higher CPU + # utilization and potential performance loss in exchange for faster + # convergence. Tweak this value according to your setup. + rdsRefreshDelay: 10s + # + defaultConfig: + # NOTE: If you change any values in this section, make sure to make + # the same changes in start up args in istio-ingress pods. + # See rdsRefreshDelay for explanation about this setting. + discoveryRefreshDelay: 10s + # + # TCP connection timeout between Envoy & the application, and between Envoys. + connectTimeout: 10s + # + ### ADVANCED SETTINGS ############# + # Where should envoy's configuration be stored in the istio-proxy container + configPath: "/etc/istio/proxy" + binaryPath: "/usr/local/bin/envoy" + # The pseudo service name used for Envoy. + serviceCluster: istio-proxy + # These settings that determine how long an old Envoy + # process should be kept alive after an occasional reload. + drainDuration: 45s + parentShutdownDuration: 1m0s + # + # The mode used to redirect inbound connections to Envoy. This setting + # has no effect on outbound traffic: iptables REDIRECT is always used for + # outbound connections. + # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. + # The "REDIRECT" mode loses source addresses during redirection. + # If "TPROXY", use iptables TPROXY to redirect to Envoy. + # The "TPROXY" mode preserves both the source and destination IP + # addresses and ports, so that they can be used for advanced filtering + # and manipulation. + # The "TPROXY" mode also configures the sidecar to run with the + # CAP_NET_ADMIN capability, which is required to use TPROXY. + #interceptionMode: REDIRECT + # + # Port where Envoy listens (on local host) for admin commands + # You can exec into the istio-proxy container in a pod and + # curl the admin port (curl http://localhost:15000/) to obtain + # diagnostic information from Envoy. See + # https://lyft.github.io/envoy/docs/operations/admin.html + # for more details + proxyAdminPort: 15000 + # + # Zipkin trace collector + zipkinAddress: zipkin.istio-system:9411 + # + # Statsd metrics collector converts statsd metrics into Prometheus metrics. + statsdUdpAddress: istio-statsd-prom-bridge.istio-system:9125 + # + # Mutual TLS authentication between sidecars and istio control plane. + controlPlaneAuthPolicy: NONE + # + # Address where istio Pilot service is running + discoveryAddress: istio-pilot.istio-system:15007 + +--- +# Source: istio/templates/sidecar-injector-configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio + chart: istio-0.8.0 + release: istio + heritage: Tiller + istio: sidecar-injector +data: + config: |- + policy: enabled + template: |- + metadata: + annotations: + container.seccomp.security.alpha.kubernetes.io/istio-proxy: 'docker/default' + initContainers: + - name: istio-init + image: gcr.io/istio-release/proxy_init:0.8.0 + args: + - "-p" + - [[ .MeshConfig.ProxyListenPort ]] + - "-u" + - 1337 + - "-m" + - [[ or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String ]] + - "-i" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges" ]]" + [[ else -]] + - "*" + [[ end -]] + - "-x" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeOutboundIPRanges") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeOutboundIPRanges" ]]" + [[ else -]] + - "" + [[ end -]] + - "-b" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeInboundPorts") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeInboundPorts" ]]" + [[ else -]] + - [[ range .Spec.Containers -]][[ range .Ports -]][[ .ContainerPort -]], [[ end -]][[ end -]][[ end]] + - "-d" + [[ if (isset .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeInboundPorts") -]] + - "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/excludeInboundPorts" ]]" + [[ else -]] + - "" + [[ end -]] + imagePullPolicy: IfNotPresent + securityContext: + capabilities: + add: + - NET_ADMIN + privileged: true + restartPolicy: Always + + containers: + - name: istio-proxy + image: [[ if (isset .ObjectMeta.Annotations "sidecar.istio.io/proxyImage") -]] + "[[ index .ObjectMeta.Annotations "sidecar.istio.io/proxyImage" ]]" + [[ else -]] + gcr.io/istio-release/proxyv2:0.8.0 + [[ end -]] + args: + - proxy + - sidecar + - --configPath + - [[ .ProxyConfig.ConfigPath ]] + - --binaryPath + - [[ .ProxyConfig.BinaryPath ]] + - --serviceCluster + [[ if ne "" (index .ObjectMeta.Labels "app") -]] + - [[ index .ObjectMeta.Labels "app" ]] + [[ else -]] + - "istio-proxy" + [[ end -]] + - --drainDuration + - [[ formatDuration .ProxyConfig.DrainDuration ]] + - --parentShutdownDuration + - [[ formatDuration .ProxyConfig.ParentShutdownDuration ]] + - --discoveryAddress + - [[ .ProxyConfig.DiscoveryAddress ]] + - --discoveryRefreshDelay + - [[ formatDuration .ProxyConfig.DiscoveryRefreshDelay ]] + - --zipkinAddress + - [[ .ProxyConfig.ZipkinAddress ]] + - --connectTimeout + - [[ formatDuration .ProxyConfig.ConnectTimeout ]] + - --statsdUdpAddress + - [[ .ProxyConfig.StatsdUdpAddress ]] + - --proxyAdminPort + - [[ .ProxyConfig.ProxyAdminPort ]] + - --controlPlaneAuthPolicy + - [[ .ProxyConfig.ControlPlaneAuthPolicy ]] + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ISTIO_META_INTERCEPTION_MODE + value: [[ or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String ]] + imagePullPolicy: IfNotPresent + securityContext: + privileged: false + readOnlyRootFilesystem: true + [[ if eq (or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String) "TPROXY" -]] + capabilities: + add: + - NET_ADMIN + [[ else -]] + runAsUser: 1337 + [[ end -]] + restartPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - mountPath: /etc/istio/proxy + name: istio-envoy + - mountPath: /etc/certs/ + name: istio-certs + readOnly: true + volumes: + - emptyDir: + medium: Memory + name: istio-envoy + - name: istio-certs + secret: + optional: true + [[ if eq .Spec.ServiceAccountName "" -]] + secretName: istio.default + [[ else -]] + secretName: [[ printf "istio.%s" .Spec.ServiceAccountName ]] + [[ end -]] + + +--- +# Source: istio/charts/egressgateway/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-egressgateway-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: egressgateway + chart: egressgateway-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/ingress/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingress-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/ingressgateway/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingressgateway-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingressgateway + chart: ingressgateway-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/mixer/templates/create-custom-resources-job.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-mixer-post-install-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-mixer-post-install-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] # istio CRD watcher + resources: ["*"] + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: ["networking.istio.io"] # needed to create mixer destination rules + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: istio-mixer-post-install-role-binding-istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-mixer-post-install-istio-system +subjects: + - kind: ServiceAccount + name: istio-mixer-post-install-account + namespace: istio-system +--- + +apiVersion: batch/v1 +kind: Job +metadata: + name: istio-mixer-post-install + namespace: istio-system + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-delete-policy": before-hook-creation + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + release: istio + heritage: Tiller +spec: + template: + metadata: + name: istio-mixer-post-install + labels: + app: mixer + release: istio + spec: + serviceAccountName: istio-mixer-post-install-account + containers: + - name: hyperkube + image: "gcr.io/istio-release/coreos/hyperkube:v1.7.6_coreos.0" + command: + - ./kubectl + - apply + - -f + - /tmp/mixer/custom-resources.yaml + volumeMounts: + - mountPath: "/tmp/mixer" + name: tmp-configmap-mixer + volumes: + - name: tmp-configmap-mixer + configMap: + name: istio-mixer-custom-resources + restartPolicy: Never # CRD might take some time till they are available to consume + +--- +# Source: istio/charts/mixer/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-mixer-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio + --- +# Source: istio/charts/pilot/templates/serviceaccount.yaml + apiVersion: v1 kind: ServiceAccount metadata: - name: istio-mixer-service-account + name: istio-pilot-service-account namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/charts/prometheus/templates/serviceaccount.yaml + +apiVersion: v1 +kind: ServiceAccount metadata: - name: istio-mixer + name: prometheus namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - template: - metadata: - labels: - istio: mixer - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-mixer-service-account - containers: - - name: statsd-to-prometheus - image: gcr.io/istio-release/statsd-exporter:v0.5.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9102 - - containerPort: 9125 - protocol: UDP - args: - - '-statsd.mapping-config=/etc/statsd/mapping.conf' - volumeMounts: - - name: config-volume - mountPath: /etc/statsd - - name: mixer - image: gcr.io/istio-release/mixer:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9091 - - containerPort: 9093 - - containerPort: 9094 - - containerPort: 42422 - args: - - --configStoreURL=k8s:// - - --configDefaultNamespace=istio-system - - --zipkinURL=http://zipkin:9411/api/v1/spans - - --logtostderr - - -v - - "2" - - name: istio-proxy - image: gcr.io/istio-release/proxy:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15004 - args: - - proxy - - mixer - - -v - - "2" - - --controlPlaneAuthPolicy - - NONE #--controlPlaneAuthPolicy - - --customConfigFile - - /etc/istio/proxy/envoy_mixer.json - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.istio-mixer-service-account - optional: true - - name: config-volume - configMap: - name: istio-mixer --- -# Mixer CRD definitions are generated using -# mixs crd all +# Source: istio/charts/security/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-citadel-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-cleanup-old-ca-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-sidecar-injector-service-account + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio + +--- +# Source: istio/charts/mixer/templates/crds.yaml +# Mixer CRDs kind: CustomResourceDefinition apiVersion: apiextensions.k8s.io/v1beta1 metadata: @@ -363,6 +1249,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: istio.io.mixer istio: core spec: @@ -382,6 +1269,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: istio.io.mixer istio: core spec: @@ -401,6 +1289,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: circonus istio: mixer-adapter spec: @@ -420,6 +1309,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: denier istio: mixer-adapter spec: @@ -439,6 +1329,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: fluentd istio: mixer-adapter spec: @@ -458,6 +1349,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: kubernetesenv istio: mixer-adapter spec: @@ -477,6 +1369,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: listchecker istio: mixer-adapter spec: @@ -496,6 +1389,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: memquota istio: mixer-adapter spec: @@ -515,6 +1409,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: noop istio: mixer-adapter spec: @@ -534,6 +1429,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: opa istio: mixer-adapter spec: @@ -553,6 +1449,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: prometheus istio: mixer-adapter spec: @@ -572,6 +1469,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: rbac istio: mixer-adapter spec: @@ -591,6 +1489,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: servicecontrol istio: mixer-adapter spec: @@ -610,6 +1509,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: solarwinds istio: mixer-adapter spec: @@ -629,6 +1529,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: stackdriver istio: mixer-adapter spec: @@ -648,6 +1549,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: statsd istio: mixer-adapter spec: @@ -667,6 +1569,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: stdio istio: mixer-adapter spec: @@ -686,6 +1589,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: apikey istio: mixer-instance spec: @@ -705,6 +1609,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: authorization istio: mixer-instance spec: @@ -724,6 +1629,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: checknothing istio: mixer-instance spec: @@ -743,6 +1649,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: adapter.template.kubernetes istio: mixer-instance spec: @@ -762,6 +1669,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: listentry istio: mixer-instance spec: @@ -781,6 +1689,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: logentry istio: mixer-instance spec: @@ -800,6 +1709,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: metric istio: mixer-instance spec: @@ -819,6 +1729,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: quota istio: mixer-instance spec: @@ -838,6 +1749,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: reportnothing istio: mixer-instance spec: @@ -857,6 +1769,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: servicecontrolreport istio: mixer-instance spec: @@ -876,6 +1789,7 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer package: tracespan istio: mixer-instance spec: @@ -895,6 +1809,8 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer istio: rbac spec: group: config.istio.io @@ -913,6 +1829,8 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: mixer + package: istio.io.mixer istio: rbac spec: group: config.istio.io @@ -922,787 +1840,986 @@ spec: singular: servicerolebinding scope: Namespaced version: v1alpha2 ---- -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest +--- +# Source: istio/charts/pilot/templates/crds.yaml +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: - name: istioproxy - namespace: istio-system + name: destinationpolicies.config.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - attributes: - origin.ip: - valueType: IP_ADDRESS - origin.uid: - valueType: STRING - origin.user: - valueType: STRING - request.headers: - valueType: STRING_MAP - request.id: - valueType: STRING - request.host: - valueType: STRING - request.method: - valueType: STRING - request.path: - valueType: STRING - request.reason: - valueType: STRING - request.referer: - valueType: STRING - request.scheme: - valueType: STRING - request.size: - valueType: INT64 - request.time: - valueType: TIMESTAMP - request.useragent: - valueType: STRING - response.code: - valueType: INT64 - response.duration: - valueType: DURATION - response.headers: - valueType: STRING_MAP - response.size: - valueType: INT64 - response.time: - valueType: TIMESTAMP - source.uid: - valueType: STRING - source.user: - valueType: STRING - destination.uid: - valueType: STRING - connection.id: - valueType: STRING - connection.received.bytes: - valueType: INT64 - connection.received.bytes_total: - valueType: INT64 - connection.sent.bytes: - valueType: INT64 - connection.sent.bytes_total: - valueType: INT64 - connection.duration: - valueType: DURATION - context.protocol: - valueType: STRING - context.timestamp: - valueType: TIMESTAMP - context.time: - valueType: TIMESTAMP - api.service: - valueType: STRING - api.version: - valueType: STRING - api.operation: - valueType: STRING - api.protocol: - valueType: STRING - request.auth.principal: - valueType: STRING - request.auth.audiences: - valueType: STRING - request.auth.presenter: - valueType: STRING - request.api_key: - valueType: STRING - ---- -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest -metadata: - name: kubernetes - namespace: istio-system + group: config.istio.io + names: + kind: DestinationPolicy + listKind: DestinationPolicyList + plural: destinationpolicies + singular: destinationpolicy + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: egressrules.config.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - attributes: - source.ip: - valueType: IP_ADDRESS - source.labels: - valueType: STRING_MAP - source.name: - valueType: STRING - source.namespace: - valueType: STRING - source.service: - valueType: STRING - source.serviceAccount: - valueType: STRING - destination.ip: - valueType: IP_ADDRESS - destination.labels: - valueType: STRING_MAP - destination.name: - valueType: STRING - destination.namespace: - valueType: STRING - destination.service: - valueType: STRING - destination.serviceAccount: - valueType: STRING ---- -apiVersion: "config.istio.io/v1alpha2" -kind: stdio -metadata: - name: handler - namespace: istio-system + group: config.istio.io + names: + kind: EgressRule + listKind: EgressRuleList + plural: egressrules + singular: egressrule + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: routerules.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: config.istio.io + names: + kind: RouteRule + listKind: RouteRuleList + plural: routerules + singular: routerule + scope: Namespaced + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: virtualservices.networking.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - outputAsJson: true + group: networking.istio.io + names: + kind: VirtualService + listKind: VirtualServiceList + plural: virtualservices + singular: virtualservice + scope: Namespaced + version: v1alpha3 --- -apiVersion: "config.istio.io/v1alpha2" -kind: logentry +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: - name: accesslog - namespace: istio-system + name: destinationrules.networking.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - severity: '"Default"' - timestamp: request.time - variables: - sourceIp: source.ip | ip("0.0.0.0") - destinationIp: destination.ip | ip("0.0.0.0") - sourceUser: source.user | "" - method: request.method | "" - url: request.path | "" - protocol: request.scheme | "http" - responseCode: response.code | 0 - responseSize: response.size | 0 - requestSize: request.size | 0 - latency: response.duration | "0ms" - monitored_resource_type: '"UNSPECIFIED"' + group: networking.istio.io + names: + kind: DestinationRule + listKind: DestinationRuleList + plural: destinationrules + singular: destinationrule + scope: Namespaced + version: v1alpha3 --- -apiVersion: "config.istio.io/v1alpha2" -kind: rule +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: - name: stdio - namespace: istio-system + name: serviceentries.networking.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot +spec: + group: networking.istio.io + names: + kind: ServiceEntry + listKind: ServiceEntryList + plural: serviceentries + singular: serviceentry + scope: Namespaced + version: v1alpha3 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: gateways.networking.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot spec: - match: "true" # If omitted match is true. - actions: - - handler: handler.stdio - instances: - - accesslog.logentry + group: networking.istio.io + names: + kind: Gateway + plural: gateways + singular: gateway + scope: Namespaced + version: v1alpha3 --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 metadata: - name: requestcount - namespace: istio-system + name: policies.authentication.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: authentication.istio.io + names: + kind: Policy + plural: policies + singular: policy + scope: Namespaced + version: v1alpha1 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: httpapispecbindings.config.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile spec: - value: "1" - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' + group: config.istio.io + names: + kind: HTTPAPISpecBinding + plural: httpapispecbindings + singular: httpapispecbinding + scope: Namespaced + version: v1alpha2 --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 metadata: - name: requestduration - namespace: istio-system + name: httpapispecs.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: HTTPAPISpec + plural: httpapispecs + singular: httpapispec + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotaspecbindings.config.istio.io + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + group: config.istio.io + names: + kind: QuotaSpecBinding + plural: quotaspecbindings + singular: quotaspecbinding + scope: Namespaced + version: v1alpha2 +--- +kind: CustomResourceDefinition +apiVersion: apiextensions.k8s.io/v1beta1 +metadata: + name: quotaspecs.config.istio.io labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile spec: - value: response.duration | "0ms" - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' + group: config.istio.io + names: + kind: QuotaSpec + plural: quotaspecs + singular: quotaspec + scope: Namespaced + version: v1alpha2 + + +--- +# Source: istio/charts/ingress/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + heritage: Tiller + release: istio + name: istio-ingress-istio-system +rules: +- apiGroups: ["extensions"] + resources: ["thirdpartyresources", "ingresses"] + verbs: ["get", "watch", "list", "update"] +- apiGroups: [""] + resources: ["configmaps", "pods", "endpoints", "services"] + verbs: ["get", "watch", "list"] + +--- +# Source: istio/charts/mixer/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: istio-mixer-istio-system + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] # istio CRD watcher + resources: ["*"] + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets"] + verbs: ["get", "list", "watch"] + --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric +# Source: istio/charts/pilot/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole metadata: - name: requestsize + name: istio-pilot-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - value: request.size | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["config.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["networking.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["authentication.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["*"] +- apiGroups: ["extensions"] + resources: ["thirdpartyresources", "thirdpartyresources.extensions", "ingresses", "ingresses/status"] + verbs: ["*"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["endpoints", "pods", "services"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["namespaces", "nodes", "secrets"] + verbs: ["get", "list", "watch"] + +--- +# Source: istio/charts/prometheus/templates/clusterrole.yaml + --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole metadata: - name: responsesize + name: prometheus-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - value: response.size | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - response_code: response.code | 200 - monitored_resource_type: '"UNSPECIFIED"' +rules: +- apiGroups: [""] + resources: + - nodes + - services + - endpoints + - pods + - nodes/proxy + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: + - configmaps + verbs: ["get"] +- nonResourceURLs: ["/metrics"] + verbs: ["get"] --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: tcpbytesent + name: prometheus-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp -spec: - value: connection.sent.bytes | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - monitored_resource_type: '"UNSPECIFIED"' +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: prometheus-istio-system +subjects: +- kind: ServiceAccount + name: prometheus + namespace: istio-system +--- + + --- -apiVersion: "config.istio.io/v1alpha2" -kind: metric +# Source: istio/charts/security/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole metadata: - name: tcpbytereceived + name: istio-citadel-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp -spec: - value: connection.received.bytes | 0 - dimensions: - source_service: source.service | "unknown" - source_version: source.labels["version"] | "unknown" - destination_service: destination.service | "unknown" - destination_version: destination.labels["version"] | "unknown" - monitored_resource_type: '"UNSPECIFIED"' + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "update", "delete"] +- apiGroups: [""] + resources: ["serviceaccounts"] + verbs: ["get", "watch", "list"] +- apiGroups: [""] + resources: ["services"] + verbs: ["get", "watch", "list"] --- -apiVersion: "config.istio.io/v1alpha2" -kind: prometheus +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: Role metadata: - name: handler - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -spec: - metrics: - - name: request_count - instance_name: requestcount.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - - name: request_duration - instance_name: requestduration.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - explicit_buckets: - bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] - - name: request_size - instance_name: requestsize.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - exponentialBuckets: - numFiniteBuckets: 8 - scale: 1 - growthFactor: 10 - - name: response_size - instance_name: responsesize.metric.istio-system - kind: DISTRIBUTION - label_names: - - source_service - - source_version - - destination_service - - destination_version - - response_code - buckets: - exponentialBuckets: - numFiniteBuckets: 8 - scale: 1 - growthFactor: 10 - - name: tcp_bytes_sent - instance_name: tcpbytesent.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version - - name: tcp_bytes_received - instance_name: tcpbytereceived.metric.istio-system - kind: COUNTER - label_names: - - source_service - - source_version - - destination_service - - destination_version ---- -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: promhttp + name: istio-cleanup-old-ca-istio-system namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: http -spec: - actions: - - handler: handler.prometheus - instances: - - requestcount.metric - - requestduration.metric - - requestsize.metric - - responsesize.metric + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: [""] + resources: ["deployments", "serviceaccounts", "services"] + verbs: ["get", "delete"] +- apiGroups: ["extensions"] + resources: ["deployments", "replicasets"] + verbs: ["get", "list", "update", "delete"] + --- -apiVersion: "config.istio.io/v1alpha2" -kind: rule +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrole.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole metadata: - name: promtcp - namespace: istio-system + name: istio-sidecar-injector-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - istio-protocol: tcp # needed so that mixer will only execute when context.protocol == TCP -spec: - actions: - - handler: handler.prometheus - instances: - - tcpbytesent.metric - - tcpbytereceived.metric + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio +rules: +- apiGroups: ["*"] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "patch"] + --- +# Source: istio/charts/ingress/templates/clusterrolebinding.yaml -apiVersion: "config.istio.io/v1alpha2" -kind: kubernetesenv +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: handler - namespace: istio-system + name: istio-ingress-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - # when running from mixer root, use the following config after adding a - # symbolic link to a kubernetes config file via: - # - # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig - # - # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-ingress-service-account + namespace: istio-system --- -apiVersion: "config.istio.io/v1alpha2" -kind: rule +# Source: istio/charts/mixer/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: kubeattrgenrulerule - namespace: istio-system + name: istio-mixer-admin-role-binding-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - actions: - - handler: handler.kubernetesenv - instances: - - attributes.kubernetes + app: mixer + chart: mixer-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-mixer-istio-system +subjects: + - kind: ServiceAccount + name: istio-mixer-service-account + namespace: istio-system + --- -apiVersion: "config.istio.io/v1alpha2" -kind: kubernetes +# Source: istio/charts/pilot/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: attributes - namespace: istio-system + name: istio-pilot-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - # Pass the required attribute data to the adapter - source_uid: source.uid | "" - source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr - destination_uid: destination.uid | "" - destination_ip: destination.ip | ip("0.0.0.0") # default to unspecified ip addr - origin_uid: '""' - origin_ip: ip("0.0.0.0") # default to unspecified ip addr - attribute_bindings: - # Fill the new attributes from the adapter produced output. - # $out refers to an instance of OutputTemplate message - source.ip: $out.source_pod_ip | ip("0.0.0.0") - source.labels: $out.source_labels | emptyStringMap() - source.namespace: $out.source_namespace | "default" - source.service: $out.source_service | "unknown" - source.serviceAccount: $out.source_service_account_name | "unknown" - destination.ip: $out.destination_pod_ip | ip("0.0.0.0") - destination.labels: $out.destination_labels | emptyStringMap() - destination.namespace: $out.destination_namespace | "default" - destination.service: $out.destination_service | "unknown" - destination.serviceAccount: $out.destination_service_account_name | "unknown" + app: istio-pilot + chart: pilot-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-pilot-service-account + namespace: istio-system + --- -################################ -# Istio configMap cluster-wide -################################ -apiVersion: v1 -kind: ConfigMap +# Source: istio/charts/security/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: istio - namespace: istio-system + name: istio-citadel-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -data: - mesh: |- - # Uncomment the following line to enable mutual TLS between proxies - # authPolicy: MUTUAL_TLS - # - # Edit this list to avoid using mTLS to connect to these services. - # Typically, these are control services (e.g kubernetes API server) that don't have Istio sidecar - # to transparently terminate mTLS authentication. - mtlsExcludedServices: ["kubernetes.default.svc.cluster.local"] - - # Set the following variable to true to disable policy checks by the Mixer. - # Note that metrics will still be reported to the Mixer. - disablePolicyChecks: false - # Set enableTracing to false to disable request tracing. - enableTracing: true - # - # To disable the mixer completely (including metrics), comment out - # the following lines - mixerCheckServer: istio-mixer.istio-system:15004 - mixerReportServer: istio-mixer.istio-system:15004 - # This is the ingress service name, update if you used a different name - ingressService: istio-ingress - # - # Along with discoveryRefreshDelay, this setting determines how - # frequently should Envoy fetch and update its internal configuration - # from Istio Pilot. Lower refresh delay results in higher CPU - # utilization and potential performance loss in exchange for faster - # convergence. Tweak this value according to your setup. - rdsRefreshDelay: 1s - # - defaultConfig: - # NOTE: If you change any values in this section, make sure to make - # the same changes in start up args in istio-ingress pods. - # See rdsRefreshDelay for explanation about this setting. - discoveryRefreshDelay: 1s - # - # TCP connection timeout between Envoy & the application, and between Envoys. - connectTimeout: 10s - # - ### ADVANCED SETTINGS ############# - # Where should envoy's configuration be stored in the istio-proxy container - configPath: "/etc/istio/proxy" - binaryPath: "/usr/local/bin/envoy" - # The pseudo service name used for Envoy. - serviceCluster: istio-proxy - # These settings that determine how long an old Envoy - # process should be kept alive after an occasional reload. - drainDuration: 45s - parentShutdownDuration: 1m0s - # - # Port where Envoy listens (on local host) for admin commands - # You can exec into the istio-proxy container in a pod and - # curl the admin port (curl http://localhost:15000/) to obtain - # diagnostic information from Envoy. See - # https://lyft.github.io/envoy/docs/operations/admin.html - # for more details - proxyAdminPort: 15000 - # - # Address where Istio Pilot service is running - discoveryAddress: istio-pilot.istio-system:15003 - # - # Zipkin trace collector - zipkinAddress: zipkin.istio-system:9411 - # - # Statsd metrics collector. Istio mixer exposes a UDP endpoint - # to collect and convert statsd metrics into Prometheus metrics. - statsdUdpAddress: istio-mixer.istio-system:9125 - # Uncomment the following line to enable mutual TLS authentication between - # sidecars and istio control plane. - # controlPlaneAuthPolicy: MUTUAL_TLS + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-citadel-istio-system +subjects: + - kind: ServiceAccount + name: istio-citadel-service-account + namespace: istio-system --- -################################ -# Pilot -################################ -# Pilot CRDs -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding metadata: - name: destinationpolicies.config.istio.io + name: istio-cleanup-old-ca-istio-system + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: DestinationPolicy - listKind: DestinationPolicyList - plural: destinationpolicies - singular: destinationpolicy - scope: Namespaced - version: v1alpha2 + app: security + chart: security-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: istio-cleanup-old-ca-istio-system +subjects: + - kind: ServiceAccount + name: istio-cleanup-old-ca-service-account + namespace: istio-system + --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrolebinding.yaml + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding metadata: - name: egressrules.config.istio.io + name: istio-sidecar-injector-admin-role-binding-istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -spec: - group: config.istio.io - names: - kind: EgressRule - listKind: EgressRuleList - plural: egressrules - singular: egressrule - scope: Namespaced - version: v1alpha2 + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + heritage: Tiller + release: istio +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-sidecar-injector-istio-system +subjects: + - kind: ServiceAccount + name: istio-sidecar-injector-service-account + namespace: istio-system --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition +# Source: istio/charts/egressgateway/templates/service.yaml +apiVersion: v1 +kind: Service metadata: - name: routerules.config.istio.io + name: istio-egressgateway + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: egressgateway-0.8.0 + release: istio + heritage: Tiller + istio: egressgateway spec: - group: config.istio.io - names: - kind: RouteRule - listKind: RouteRuleList - plural: routerules - singular: routerule - scope: Namespaced - version: v1alpha2 + type: ClusterIP + selector: + istio: egressgateway + ports: + - + name: http + port: 80 + - + name: https + port: 443 + --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition +# Source: istio/charts/ingress/templates/service.yaml +apiVersion: v1 +kind: Service metadata: - name: v1alpha2routerules.config.istio.io + name: istio-ingress + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: ingress-0.8.0 + release: istio + heritage: Tiller + istio: ingress spec: - group: config.istio.io - names: - kind: V1alpha2RouteRule - listKind: V1alpha2RouteRuleList - plural: v1alpha2routerules - singular: v1alpha2routerule - scope: Namespaced - version: v1alpha2 + type: LoadBalancer + selector: + istio: ingress + ports: + - + name: http + nodePort: 32000 + port: 80 + - + name: https + port: 443 --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition + +--- +# Source: istio/charts/ingressgateway/templates/service.yaml +apiVersion: v1 +kind: Service metadata: - name: destinationrules.config.istio.io + name: istio-ingressgateway + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: ingressgateway-0.8.0 + release: istio + heritage: Tiller + istio: ingressgateway spec: - group: config.istio.io - names: - kind: DestinationRule - listKind: DestinationRuleList - plural: destinationrules - singular: destinationrule - scope: Namespaced - version: v1alpha2 + type: LoadBalancer + selector: + istio: ingressgateway + ports: + - + name: http + nodePort: 31380 + port: 80 + - + name: https + nodePort: 31390 + port: 443 + - + name: tcp + nodePort: 31400 + port: 31400 + --- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition +# Source: istio/charts/mixer/templates/service.yaml + +apiVersion: v1 +kind: Service metadata: - name: externalservices.config.istio.io + name: istio-policy + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: mixer spec: - group: config.istio.io - names: - kind: ExternalService - listKind: ExternalServiceList - plural: externalservices - singular: externalservice - scope: Namespaced - version: v1alpha2 + ports: + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 9093 + selector: + istio: mixer + istio-mixer-type: policy --- -# Pilot service for discovery apiVersion: v1 kind: Service metadata: - name: istio-pilot + name: istio-telemetry namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" - istio: pilot + chart: mixer-0.8.0 + release: istio + istio: mixer spec: ports: - - port: 15003 - name: http-discovery - - port: 8080 - name: http-legacy-discovery - - port: 9093 - name: http-monitoring - - port: 443 - name: admission-webhook + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 9093 + - name: prometheus + port: 42422 selector: - istio: pilot + istio: mixer + istio-mixer-type: telemetry +--- + +--- +# Source: istio/charts/mixer/templates/statsdtoprom.yaml + --- apiVersion: v1 -kind: ServiceAccount +kind: Service metadata: - name: istio-pilot-service-account + name: istio-statsd-prom-bridge namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + chart: mixer-0.8.0 + release: istio + istio: statsd-prom-bridge +spec: + ports: + - name: statsd-prom + port: 9102 + - name: statsd-udp + port: 9125 + protocol: UDP + selector: + istio: statsd-prom-bridge + --- + apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: istio-pilot + name: istio-statsd-prom-bridge namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer spec: template: metadata: labels: - istio: pilot + istio: statsd-prom-bridge annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: - serviceAccountName: istio-pilot-service-account + serviceAccountName: istio-mixer-service-account + volumes: + - name: config-volume + configMap: + name: istio-statsd-prom-bridge containers: - - name: discovery - image: gcr.io/istio-release/pilot:0.6.0 - imagePullPolicy: IfNotPresent - args: ["discovery", "-v", "2", "--admission-service", "istio-pilot"] - ports: - - containerPort: 8080 - - containerPort: 443 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: PILOT_THROTTLE - value: "200" - volumeMounts: - - name: config-volume - mountPath: /etc/istio/config - - name: istio-proxy - image: gcr.io/istio-release/proxy:0.6.0 + - name: statsd-prom-bridge + image: "gcr.io/istio-release/prom/statsd-exporter:v0.6.0" imagePullPolicy: IfNotPresent ports: - - containerPort: 15003 + - containerPort: 9102 + - containerPort: 9125 + protocol: UDP args: - - proxy - - pilot - - -v - - "2" - - --discoveryAddress - - istio-pilot:15003 - - --controlPlaneAuthPolicy - - NONE #--controlPlaneAuthPolicy - - --customConfigFile - - /etc/istio/proxy/envoy_pilot.json + - '-statsd.mapping-config=/etc/statsd/mapping.conf' + resources: + {} + volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: config-volume - configMap: - name: istio - - name: istio-certs - secret: - secretName: istio.istio-pilot-service-account - optional: true + - name: config-volume + mountPath: /etc/statsd + --- -################################ -# Istio ingress -################################ +# Source: istio/charts/pilot/templates/service.yaml apiVersion: v1 kind: Service metadata: - name: istio-ingress + name: istio-pilot namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" - istio: ingress + app: istio-pilot + chart: pilot-0.8.0 + release: istio + heritage: Tiller spec: - type: LoadBalancer ports: - - port: 80 -# nodePort: 32000 - name: http - - port: 443 - name: https + - port: 15003 + name: http-old-discovery # mTLS or non-mTLS depending on auth setting + - port: 15005 + name: https-discovery # always mTLS + - port: 15007 + name: http-discovery # always plain-text + - port: 15010 + name: grpc-xds # direct + - port: 15011 + name: https-xds # mTLS + - port: 8080 + name: http-legacy-discovery # direct + - port: 9093 + name: http-monitoring selector: - istio: ingress + istio: pilot + --- +# Source: istio/charts/prometheus/templates/service.yaml apiVersion: v1 -kind: ServiceAccount +kind: Service metadata: - name: istio-ingress-service-account + name: prometheus + namespace: istio-system + annotations: + prometheus.io/scrape: 'true' + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + name: prometheus +spec: + selector: + app: prometheus + ports: + - name: http-prometheus + protocol: TCP + port: 9090 + +--- +# Source: istio/charts/security/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + # we use the normal name here (e.g. 'prometheus') + # as grafana is configured to use this as a data source + name: istio-citadel + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + app: istio-citadel +spec: + ports: + - name: grpc-citadel + port: 8060 + targetPort: 8060 + protocol: TCP + - name: http-monitoring + port: 9093 + selector: + istio: citadel + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/cluster-service: "true" + istio: sidecar-injector +spec: + ports: + - port: 443 + selector: + istio: sidecar-injector + +--- +# Source: istio/charts/egressgateway/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-egressgateway namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: egressgateway + chart: egressgateway-0.8.0 + release: istio + heritage: Tiller + istio: egressgateway +spec: + template: + metadata: + labels: + istio: egressgateway + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-egressgateway-service-account + containers: + - name: egressgateway + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + args: + - proxy + - router + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-egressgateway + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:8080 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- +# Source: istio/charts/ingress/templates/deployment.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: @@ -1711,6 +2828,11 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: ingress + chart: ingress-0.8.0 + release: istio + heritage: Tiller + istio: ingress spec: template: metadata: @@ -1718,384 +2840,602 @@ spec: istio: ingress annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: serviceAccountName: istio-ingress-service-account containers: - - name: istio-ingress - image: gcr.io/istio-release/proxy:0.6.0 - args: - - proxy - - ingress - - -v - - "2" - - --discoveryAddress - - istio-pilot:15003 - - --discoveryRefreshDelay - - '1s' #discoveryRefreshDelay - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - istio-ingress - - --zipkinAddress - - zipkin:9411 - - --statsdUdpAddress - - istio-mixer:9125 - - --proxyAdminPort - - "15000" - - --controlPlaneAuthPolicy - - NONE #--controlPlaneAuthPolicy - imagePullPolicy: IfNotPresent - ports: - - containerPort: 80 - - containerPort: 443 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: ingress-certs - mountPath: /etc/istio/ingress-certs - readOnly: true + - name: ingress + image: "gcr.io/istio-release/proxy:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + args: + - proxy + - ingress + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingress + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:8080 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingress-certs + mountPath: /etc/istio/ingress-certs + readOnly: true volumes: - name: istio-certs secret: - secretName: istio.default + secretName: "istio.default" optional: true - name: ingress-certs secret: secretName: istio-ingress-certs optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- -################################ -# Istio-CA cluster-wide -################################ -# Service account CA -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-ca-service-account - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- -# Istio CA watching all namespaces -apiVersion: v1 -kind: Deployment +# Source: istio/charts/ingressgateway/templates/deployment.yaml apiVersion: extensions/v1beta1 +kind: Deployment metadata: - name: istio-ca + name: istio-ingressgateway namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: ingressgateway + chart: ingressgateway-0.8.0 + release: istio + heritage: Tiller + istio: ingressgateway spec: template: metadata: labels: - istio: istio-ca + istio: ingressgateway annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: - serviceAccountName: istio-ca-service-account + serviceAccountName: istio-ingressgateway-service-account containers: - - name: istio-ca - image: gcr.io/istio-release/istio-ca:0.6.0 - imagePullPolicy: IfNotPresent - command: ["/usr/local/bin/istio_ca"] - args: - - --istio-ca-storage-namespace=istio-system - - --grpc-port=8060 - - --grpc-hostname=istio-ca - - --self-signed-ca=true - - --logtostderr - - --stderrthreshold - - INFO ---- -apiVersion: v1 -kind: Service -metadata: - name: grafana - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" -spec: - ports: - - port: 3000 - protocol: TCP - name: http - selector: - app: grafana + - name: ingressgateway + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 443 + - containerPort: 31400 + args: + - proxy + - router + - -v + - "2" + - --discoveryRefreshDelay + - '1s' #discoveryRefreshDelay + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingressgateway + - --zipkinAddress + - zipkin:9411 + - --statsdUdpAddress + - istio-statsd-prom-bridge:9125 + - --proxyAdminPort + - "15000" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:8080 + resources: + {} + + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingressgateway-certs + mountPath: "/etc/istio/ingressgateway-certs" + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: "istio.default" + optional: true + - name: ingressgateway-certs + secret: + secretName: "istio-ingressgateway-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- +# Source: istio/charts/mixer/templates/deployment.yaml + apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: grafana + name: istio-policy namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + chart: mixer-0.8.0 + release: istio + istio: mixer spec: template: metadata: labels: - app: grafana + istio: mixer + istio-mixer-type: policy annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: - serviceAccountName: grafana + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x containers: - - name: grafana - image: gcr.io/istio-release/grafana:0.6.0 + - name: mixer + image: "gcr.io/istio-release/mixer:0.8.0" imagePullPolicy: IfNotPresent ports: - - containerPort: 3000 - env: - # Only put environment related config here. Generic Istio config - # should go in addons/grafana/grafana.ini. - - name: GF_PATHS_DATA - value: /data/grafana - volumeMounts: - - mountPath: /data/grafana - name: grafana-data - volumes: - - name: grafana-data - emptyDir: {} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: grafana - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile ---- ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: prometheus - namespace: istio-system - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -data: - prometheus.yml: |- - global: - scrape_interval: 15s - scrape_configs: - - - job_name: 'istio-mesh' - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - - kubernetes_sd_configs: - - role: endpoints - - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: istio-system;istio-mixer;prometheus - - - job_name: 'envoy' - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - # metrics_path defaults to '/metrics' - # scheme defaults to 'http'. - - kubernetes_sd_configs: - - role: endpoints - - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: istio-system;istio-mixer;statsd-prom - - - job_name: 'mixer' - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - # metrics_path defaults to '/metrics' - # scheme defaults to 'http'. - - kubernetes_sd_configs: - - role: endpoints - - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: istio-system;istio-mixer;http-monitoring - - - job_name: 'pilot' - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - # metrics_path defaults to '/metrics' - # scheme defaults to 'http'. - - kubernetes_sd_configs: - - role: endpoints - - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: istio-system;istio-pilot;http-monitoring - - # scrape config for API servers - - job_name: 'kubernetes-apiservers' - kubernetes_sd_configs: - - role: endpoints - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: default;kubernetes;https - - # scrape config for nodes (kubelet) - - job_name: 'kubernetes-nodes' - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - kubernetes_sd_configs: - - role: node - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/${1}/proxy/metrics - - # Scrape config for Kubelet cAdvisor. - # - # This is required for Kubernetes 1.7.3 and later, where cAdvisor metrics - # (those whose names begin with 'container_') have been removed from the - # Kubelet metrics endpoint. This job scrapes the cAdvisor endpoint to - # retrieve those metrics. - # - # In Kubernetes 1.7.0-1.7.2, these metrics are only exposed on the cAdvisor - # HTTP endpoint; use "replacement: /api/v1/nodes/${1}:4194/proxy/metrics" - # in that case (and ensure cAdvisor's HTTP server hasn't been disabled with - # the --cadvisor-port=0 Kubelet flag). - # - # This job is not necessary and should be removed in Kubernetes 1.6 and - # earlier versions, or it will cause the metrics to be scraped twice. - - job_name: 'kubernetes-cadvisor' - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - kubernetes_sd_configs: - - role: node - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor - - # scrape config for service endpoints. - - job_name: 'kubernetes-service-endpoints' - kubernetes_sd_configs: - - role: endpoints - relabel_configs: - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] - action: keep - regex: true - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] - action: replace - target_label: __scheme__ - regex: (https?) - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] - action: replace - target_label: __address__ - regex: ([^:]+)(?::\d+)?;(\d+) - replacement: $1:$2 - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_service_name] - action: replace - target_label: kubernetes_name - - # Example scrape config for pods - - job_name: 'kubernetes-pods' - kubernetes_sd_configs: - - role: pod - - relabel_configs: - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] - action: keep - regex: true - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] - action: replace - regex: ([^:]+)(?::\d+)?;(\d+) - replacement: $1:$2 - target_label: __address__ - - action: labelmap - regex: __meta_kubernetes_pod_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: namespace - - source_labels: [__meta_kubernetes_pod_name] - action: replace - target_label: pod_name + - containerPort: 9092 + - containerPort: 9093 + - containerPort: 42422 + args: + - --address + - tcp://127.0.0.1:9092 + - --configStoreURL=k8s:// + - --configDefaultNamespace=istio-system + - --trace_zipkin_url=http://zipkin:9411/api/v1/spans + resources: + {} + + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + args: + - proxy + - --serviceCluster + - istio-policy + - --templateFile + - /etc/istio/proxy/envoy_policy.yaml.tmpl + - --controlPlaneAuthPolicy + - NONE + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true --- -apiVersion: v1 -kind: Service +apiVersion: extensions/v1beta1 +kind: Deployment metadata: - annotations: - prometheus.io/scrape: 'true' + name: istio-telemetry + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" - name: prometheus - name: prometheus + chart: mixer-0.8.0 + release: istio + istio: mixer +spec: + template: + metadata: + labels: + istio: mixer + istio-mixer-type: telemetry + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + containers: + - name: mixer + image: "gcr.io/istio-release/mixer:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9092 + - containerPort: 9093 + - containerPort: 42422 + args: + - --address + - tcp://127.0.0.1:9092 + - --configStoreURL=k8s:// + - --configDefaultNamespace=istio-system + - --trace_zipkin_url=http://zipkin:9411/api/v1/spans + resources: + {} + + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + args: + - proxy + - --serviceCluster + - istio-telemetry + - --templateFile + - /etc/istio/proxy/envoy_telemetry.yaml.tmpl + - --controlPlaneAuthPolicy + - NONE + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + +--- + +--- +# Source: istio/charts/pilot/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: istio-pilot namespace: istio-system + # TODO: default tempate doesn't have this, which one is right ? + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-pilot + chart: pilot-0.8.0 + release: istio + heritage: Tiller + istio: pilot + annotations: + checksum/config-volume: f8da08b6b8c170dde721efd680270b2901e750d4aa186ebb6c22bef5b78a43f9 spec: - selector: - app: prometheus - ports: - - name: prometheus - protocol: TCP - port: 9090 + template: + metadata: + labels: + istio: pilot + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-pilot-service-account + containers: + - name: discovery + image: "gcr.io/istio-release/pilot:0.8.0" + imagePullPolicy: IfNotPresent + args: + - "discovery" +# TODO(sdake) remove when secrets are automagically registered + ports: + - containerPort: 8080 + - containerPort: 15010 + readinessProbe: + httpGet: + path: /v1/registration + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 5 + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: PILOT_THROTTLE + value: "500" + - name: PILOT_CACHE_SQUASH + value: "5" + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: istio-proxy + image: "gcr.io/istio-release/proxyv2:0.8.0" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15003 + - containerPort: 15005 + - containerPort: 15007 + - containerPort: 15011 + args: + - proxy + - --serviceCluster + - istio-pilot + - --templateFile + - /etc/istio/proxy/envoy_pilot.yaml.tmpl + - --controlPlaneAuthPolicy + - NONE + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + resources: + requests: + cpu: 100m + memory: 128Mi + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: config-volume + configMap: + name: istio + - name: istio-certs + secret: + secretName: "istio.istio-pilot-service-account" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- +# Source: istio/charts/prometheus/templates/deployment.yaml +# TODO: the original template has service account, roles, etc apiVersion: extensions/v1beta1 kind: Deployment metadata: @@ -2104,132 +3444,451 @@ metadata: labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: prometheus + chart: prometheus-0.1.0 + release: istio + heritage: Tiller spec: selector: matchLabels: app: prometheus template: metadata: - name: prometheus labels: app: prometheus annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: serviceAccountName: prometheus + containers: - - name: prometheus - image: gcr.io/istio-release/prom/prometheus:v2.0.0 - imagePullPolicy: IfNotPresent - args: - - '--storage.tsdb.retention=6h' - - '--config.file=/etc/prometheus/prometheus.yml' - ports: - - name: web - containerPort: 9090 - volumeMounts: - - name: config-volume - mountPath: /etc/prometheus + - name: prometheus + image: "gcr.io/istio-release/prom/prometheus:v2.3.1" + imagePullPolicy: IfNotPresent + args: + - '--storage.tsdb.retention=6h' + - '--config.file=/etc/prometheus/prometheus.yml' + ports: + - containerPort: 9090 + name: http + livenessProbe: + httpGet: + path: /-/healthy + port: 9090 + readinessProbe: + httpGet: + path: /-/ready + port: 9090 + resources: + {} + + volumeMounts: + - name: config-volume + mountPath: /etc/prometheus volumes: - name: config-volume configMap: name: prometheus + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- -apiVersion: v1 -kind: ServiceAccount +# Source: istio/charts/security/templates/deployment.yaml +# istio CA watching all namespaces +apiVersion: extensions/v1beta1 +kind: Deployment metadata: - name: prometheus + name: istio-citadel namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + release: istio + heritage: Tiller + istio: citadel +spec: + template: + metadata: + labels: + istio: citadel + annotations: + sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-citadel-service-account + containers: + - name: citadel + image: "gcr.io/istio-release/citadel:0.8.0" + imagePullPolicy: IfNotPresent + args: + - --append-dns-names=true + - --grpc-port=8060 + - --grpc-hostname=citadel + - --self-signed-ca=true + - --citadel-storage-namespace=istio-system + resources: + {} + + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRole -metadata: - name: prometheus - labels: - k8s-app: istio - addonmanager.kubernetes.io/mode: Reconcile -rules: -- apiGroups: [""] - resources: - - nodes - - services - - endpoints - - pods - - nodes/proxy - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: - - configmaps - verbs: ["get"] -- nonResourceURLs: ["/metrics"] - verbs: ["get"] ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRoleBinding +# Source: istio/charts/sidecarInjectorWebhook/templates/deployment.yaml +apiVersion: extensions/v1beta1 +kind: Deployment metadata: - name: prometheus + name: istio-sidecar-injector + namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: prometheus -subjects: -- kind: ServiceAccount - name: prometheus - namespace: istio-system ---- + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook-0.8.0 + release: istio + heritage: Tiller + istio: sidecar-injector +spec: + template: + metadata: + labels: + istio: sidecar-injector + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + spec: + serviceAccountName: istio-sidecar-injector-service-account + containers: + - name: sidecar-injector-webhook + image: "gcr.io/istio-release/sidecar_injector:0.8.0" + imagePullPolicy: IfNotPresent + args: + - --caCertFile=/etc/istio/certs/root-cert.pem + - --tlsCertFile=/etc/istio/certs/cert-chain.pem + - --tlsKeyFile=/etc/istio/certs/key.pem + - --injectConfig=/etc/istio/inject/config + - --meshConfig=/etc/istio/config/mesh + - --healthCheckInterval=2s + - --healthCheckFile=/health + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + readOnly: true + - name: certs + mountPath: /etc/istio/certs + readOnly: true + - name: inject-config + mountPath: /etc/istio/inject + readOnly: true + livenessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=2s + initialDelaySeconds: 4 + periodSeconds: 4 + readinessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=2s + initialDelaySeconds: 4 + periodSeconds: 4 + volumes: + - name: config-volume + configMap: + name: istio + - name: certs + secret: + secretName: istio.istio-sidecar-injector-service-account + - name: inject-config + configMap: + name: istio-sidecar-injector + items: + - key: config + path: config + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - ppc64le + - s390x + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - ppc64le + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - s390x + --- -apiVersion: extensions/v1beta1 -kind: Deployment +# Source: istio/charts/security/templates/cleanup-old-ca.yaml + +apiVersion: batch/v1 +kind: Job metadata: - name: servicegraph + name: istio-cleanup-old-ca namespace: istio-system + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-delete-policy": hook-succeeded labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile + app: security + chart: security-0.8.0 + release: istio + heritage: Tiller spec: template: metadata: + name: istio-cleanup-old-ca labels: - app: servicegraph - annotations: - sidecar.istio.io/inject: "false" + app: security + release: istio spec: + serviceAccountName: istio-cleanup-old-ca-service-account containers: - - name: servicegraph - image: gcr.io/istio-release/servicegraph:0.6.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8088 - args: - - --prometheusAddr=http://prometheus:9090 + - name: hyperkube + image: "gcr.io/istio-release/coreos/hyperkube:v1.7.6_coreos.0" + command: + - /bin/bash + - -c + - > + NS="-n istio-system"; + ./kubectl get deploy istio-ca $NS; + if [[ $? = 0 ]]; then ./kubectl delete deploy istio-ca $NS; fi; + ./kubectl get serviceaccount istio-ca-service-account $NS; + if [[ $? = 0 ]]; then ./kubectl delete serviceaccount istio-ca-service-account $NS; fi; + ./kubectl get service istio-ca-ilb $NS; + if [[ $? = 0 ]]; then ./kubectl delete service istio-ca-ilb $NS; fi + restartPolicy: Never +--- +# Source: istio/charts/egressgateway/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-egressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-egressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/ingress/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingress + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-ingress + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/ingressgateway/templates/autoscale.yaml + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile +spec: + maxReplicas: 1 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: istio-ingressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 + + +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/mutatingwebhook.yaml +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + k8s-app: istio + addonmanager.kubernetes.io/mode: Reconcile + app: istio-sidecar-injector + chart: sidecarInjectorWebhook-0.8.0 + release: istio + heritage: Tiller +webhooks: + - name: sidecar-injector.istio.io + clientConfig: + service: + name: istio-sidecar-injector + namespace: istio-system + path: "/inject" + caBundle: "" + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + failurePolicy: Fail + namespaceSelector: + matchExpressions: + - key: istio-injection + operator: NotIn + values: + - disabled +--- +# Source: istio/charts/mixer/templates/config.yaml + + +--- +# Source: istio/charts/prometheus/templates/ingress.yaml --- apiVersion: v1 kind: Service metadata: - name: servicegraph + name: grafana namespace: istio-system + annotations: + auth.istio.io/3000: NONE labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" spec: ports: - - name: http - port: 8088 + - port: 3000 + protocol: TCP + name: http selector: - app: servicegraph ---- + app: grafana --- apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: zipkin + name: grafana namespace: istio-system labels: k8s-app: istio @@ -2238,36 +3897,36 @@ spec: template: metadata: labels: - app: zipkin + app: grafana annotations: sidecar.istio.io/inject: "false" + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: + serviceAccountName: grafana containers: - - name: zipkin - image: gcr.io/istio-release/zipkin:2.5.3 + - name: grafana + image: gcr.io/istio-release/grafana:0.8.0 imagePullPolicy: IfNotPresent ports: - - containerPort: 9411 + - containerPort: 3000 env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace + # Only put environment related config here. Generic Istio config + # should go in addons/grafana/grafana.ini. + - name: GF_PATHS_DATA + value: /data/grafana + volumeMounts: + - mountPath: /data/grafana + name: grafana-data + volumes: + - name: grafana-data + emptyDir: {} --- apiVersion: v1 -kind: Service +kind: ServiceAccount metadata: - name: zipkin + name: grafana namespace: istio-system labels: k8s-app: istio addonmanager.kubernetes.io/mode: Reconcile - kubernetes.io/cluster-service: "true" -spec: - ports: - - name: http - port: 9411 - selector: - app: zipkin --- diff --git a/vendor/k8s.io/kubernetes/cluster/addons/kube-proxy/kube-proxy-ds.yaml b/vendor/k8s.io/kubernetes/cluster/addons/kube-proxy/kube-proxy-ds.yaml index 2134e875f..d11765bb0 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/kube-proxy/kube-proxy-ds.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/kube-proxy/kube-proxy-ds.yaml @@ -24,7 +24,7 @@ spec: annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: - {{pod_priority}} + priorityClassName: system-node-critical hostNetwork: true nodeSelector: beta.kubernetes.io/kube-proxy-ds-ready: "true" diff --git a/vendor/k8s.io/kubernetes/cluster/addons/metadata-agent/stackdriver/metadata-agent-rbac.yaml b/vendor/k8s.io/kubernetes/cluster/addons/metadata-agent/stackdriver/metadata-agent-rbac.yaml index dfcada4d5..532b4b821 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/metadata-agent/stackdriver/metadata-agent-rbac.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/metadata-agent/stackdriver/metadata-agent-rbac.yaml @@ -7,9 +7,7 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - - "" - - "apps" - - "extensions" + - "*" resources: - "*" verbs: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/metadata-agent/stackdriver/metadata-agent.yaml b/vendor/k8s.io/kubernetes/cluster/addons/metadata-agent/stackdriver/metadata-agent.yaml index 025ecb556..d02362cb0 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/metadata-agent/stackdriver/metadata-agent.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/metadata-agent/stackdriver/metadata-agent.yaml @@ -7,22 +7,6 @@ metadata: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile --- -apiVersion: v1 -kind: ConfigMap -metadata: - name: metadata-agent-config - namespace: kube-system - labels: - kubernetes.io/cluster-service: "true" - addonmanager.kubernetes.io/mode: Reconcile -data: - node_level.conf: |- - KubernetesUseWatch: true - KubernetesClusterLevelMetadata: false - cluster_level.conf: |- - KubernetesUseWatch: true - KubernetesClusterLevelMetadata: true ---- kind: DaemonSet apiVersion: extensions/v1beta1 metadata: @@ -40,30 +24,27 @@ spec: metadata: labels: app: metadata-agent + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: serviceAccountName: metadata-agent containers: - - image: gcr.io/stackdriver-agents/stackdriver-metadata-agent:0.2-0.0.19-1 + - image: gcr.io/stackdriver-agents/stackdriver-metadata-agent:0.2-0.0.21-1 imagePullPolicy: IfNotPresent name: metadata-agent livenessProbe: - exec: - command: - - /bin/bash - - -c - - | - if [[ -f /var/run/metadata-agent/health/unhealthy ]]; then - exit 1; - fi - periodSeconds: 10 + httpGet: + path: /healthz + port: 8000 + initialDelaySeconds: 30 + periodSeconds: 60 + timeoutSeconds: 5 failureThreshold: 1 successThreshold: 1 - volumeMounts: - - name: metadata-agent-config-volume - mountPath: /etc/config - command: - - /opt/stackdriver/metadata/sbin/metadatad - - --config-file=/etc/config/node_level.conf + args: + - -o KubernetesUseWatch=true + - -o KubernetesClusterLevelMetadata=false + - -o MetadataReporterPurgeDeleted=true ports: - containerPort: 8000 hostPort: 8799 @@ -76,10 +57,6 @@ spec: restartPolicy: Always schedulerName: default-scheduler terminationGracePeriodSeconds: 30 - volumes: - - name: metadata-agent-config-volume - configMap: - name: metadata-agent-config updateStrategy: rollingUpdate: maxUnavailable: 1 @@ -103,30 +80,27 @@ spec: metadata: labels: app: metadata-agent-cluster-level + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: serviceAccountName: metadata-agent containers: - - image: gcr.io/stackdriver-agents/stackdriver-metadata-agent:0.2-0.0.19-1 + - image: gcr.io/stackdriver-agents/stackdriver-metadata-agent:0.2-0.0.21-1 imagePullPolicy: IfNotPresent name: metadata-agent livenessProbe: - exec: - command: - - /bin/bash - - -c - - | - if [[ -f /var/run/metadata-agent/health/unhealthy ]]; then - exit 1; - fi - periodSeconds: 10 + httpGet: + path: /healthz + port: 8000 + initialDelaySeconds: 30 + periodSeconds: 60 + timeoutSeconds: 5 failureThreshold: 1 successThreshold: 1 - volumeMounts: - - name: metadata-agent-config-volume - mountPath: /etc/config - command: - - /opt/stackdriver/metadata/sbin/metadatad - - --config-file=/etc/config/cluster_level.conf + args: + - -o KubernetesUseWatch=true + - -o KubernetesClusterLevelMetadata=true + - -o MetadataReporterPurgeDeleted=true ports: - containerPort: 8000 protocol: TCP @@ -138,10 +112,6 @@ spec: restartPolicy: Always schedulerName: default-scheduler terminationGracePeriodSeconds: 30 - volumes: - - name: metadata-agent-config-volume - configMap: - name: metadata-agent-config strategy: rollingUpdate: maxUnavailable: 1 diff --git a/vendor/k8s.io/kubernetes/cluster/addons/metadata-proxy/gce/metadata-proxy.yaml b/vendor/k8s.io/kubernetes/cluster/addons/metadata-proxy/gce/metadata-proxy.yaml index 963edd37f..7cb949afb 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/metadata-proxy/gce/metadata-proxy.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/metadata-proxy/gce/metadata-proxy.yaml @@ -44,7 +44,7 @@ spec: effect: "NoSchedule" containers: - name: metadata-proxy - image: k8s.gcr.io/metadata-proxy:v0.1.9 + image: k8s.gcr.io/metadata-proxy:v0.1.10 securityContext: privileged: true # Request and limit resources to get guaranteed QoS. diff --git a/vendor/k8s.io/kubernetes/cluster/addons/metrics-server/README.md b/vendor/k8s.io/kubernetes/cluster/addons/metrics-server/README.md new file mode 100644 index 000000000..f5f063bb7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/metrics-server/README.md @@ -0,0 +1,20 @@ +# Metrics Server + +[Metrics Server](https://github.com/kubernetes-incubator/metrics-server) exposes +core Kubernetes metrics via metrics API. + +More details can be found in [Core metrics pipeline documentation](https://kubernetes.io/docs/tasks/debug-application-cluster/core-metrics-pipeline/). + +## Troubleshooting + +Metrics Server supports up to 30 pods per cluster node. In clusters where there are more running pods, Metrics Server may be throttled or fail with OOM error. Starting with Kubernetes 1.9.2, Metrics Server resource requirements may be overwritten manually. [Learn more about Addon Resizer configuration](https://github.com/kubernetes/autoscaler/tree/master/addon-resizer#addon-resizer-configuration) + +### Important notices + +Decreasing resource requirements for cluster addons may cause system instability. The effects may include (but are not limited to): + - Horizontal Pod Autoscaler not working + - `kubectl top` not working (starting with Kubernetes 1.10) + +Overwritten configuration persists through cluster updates, therefore may cause all effects above after a cluster update. + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/cluster/addons/cluster-monitoring/README.md?pixel)]() diff --git a/vendor/k8s.io/kubernetes/cluster/addons/metrics-server/metrics-server-deployment.yaml b/vendor/k8s.io/kubernetes/cluster/addons/metrics-server/metrics-server-deployment.yaml index 3b6e5e66f..9190425f5 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/metrics-server/metrics-server-deployment.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/metrics-server/metrics-server-deployment.yaml @@ -43,6 +43,7 @@ spec: version: v0.2.1 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical serviceAccountName: metrics-server diff --git a/vendor/k8s.io/kubernetes/cluster/addons/node-problem-detector/npd.yaml b/vendor/k8s.io/kubernetes/cluster/addons/node-problem-detector/npd.yaml index 714125ea5..b25d2066d 100644 --- a/vendor/k8s.io/kubernetes/cluster/addons/node-problem-detector/npd.yaml +++ b/vendor/k8s.io/kubernetes/cluster/addons/node-problem-detector/npd.yaml @@ -48,7 +48,7 @@ spec: - "/bin/sh" - "-c" # Pass both config to support both journald and syslog. - - "/node-problem-detector --logtostderr --system-log-monitors=/config/kernel-monitor.json,/config/kernel-monitor-filelog.json,/config/docker-monitor.json,/config/docker-monitor-filelog.json >>/var/log/node-problem-detector.log 2>&1" + - "exec /node-problem-detector --logtostderr --system-log-monitors=/config/kernel-monitor.json,/config/kernel-monitor-filelog.json,/config/docker-monitor.json,/config/docker-monitor-filelog.json >>/var/log/node-problem-detector.log 2>&1" securityContext: privileged: true resources: diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/OWNERS b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/OWNERS new file mode 100644 index 000000000..ac100efc9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/OWNERS @@ -0,0 +1,11 @@ +approvers: +- kawych +- piosz +- serathius +- brancz +reviewers: +- kawych +- piosz +- serathius +- brancz + diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/README.md b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/README.md new file mode 100644 index 000000000..ef7288f17 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/README.md @@ -0,0 +1,5 @@ +# Prometheus Add-on + +This add-on is an experimental configuration of k8s monitoring using Prometheus used for e2e tests. + +For production use check out more mature setups like [Prometheus Operator](https://github.com/coreos/prometheus-operator) and [kube-prometheus](https://github.com/coreos/prometheus-operator/tree/master/contrib/kube-prometheus). \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-configmap.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-configmap.yaml new file mode 100644 index 000000000..0890a8b14 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-configmap.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: alertmanager-config + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: EnsureExists +data: + alertmanager.yml: | + global: null + receivers: + - name: default-receiver + route: + group_interval: 5m + group_wait: 10s + receiver: default-receiver + repeat_interval: 3h diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-deployment.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-deployment.yaml new file mode 100644 index 000000000..440f3d8d3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-deployment.yaml @@ -0,0 +1,78 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: alertmanager + namespace: kube-system + labels: + k8s-app: alertmanager + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile + version: v0.14.0 +spec: + replicas: 1 + selector: + matchLabels: + k8s-app: alertmanager + version: v0.14.0 + template: + metadata: + labels: + k8s-app: alertmanager + version: v0.14.0 + annotations: + scheduler.alpha.kubernetes.io/critical-pod: '' + spec: + priorityClassName: system-cluster-critical + containers: + - name: prometheus-alertmanager + image: "prom/alertmanager:v0.14.0" + imagePullPolicy: "IfNotPresent" + args: + - --config.file=/etc/config/alertmanager.yml + - --storage.path=/data + - --web.external-url=/ + ports: + - containerPort: 9093 + readinessProbe: + httpGet: + path: /#/status + port: 9093 + initialDelaySeconds: 30 + timeoutSeconds: 30 + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: storage-volume + mountPath: "/data" + subPath: "" + resources: + limits: + cpu: 10m + memory: 50Mi + requests: + cpu: 10m + memory: 50Mi + - name: prometheus-alertmanager-configmap-reload + image: "jimmidyson/configmap-reload:v0.1" + imagePullPolicy: "IfNotPresent" + args: + - --volume-dir=/etc/config + - --webhook-url=http://localhost:9093/-/reload + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + resources: + limits: + cpu: 10m + memory: 10Mi + requests: + cpu: 10m + memory: 10Mi + volumes: + - name: config-volume + configMap: + name: alertmanager-config + - name: storage-volume + persistentVolumeClaim: + claimName: alertmanager diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-pvc.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-pvc.yaml new file mode 100644 index 000000000..bc83c5f47 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-pvc.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: alertmanager + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: EnsureExists +spec: + storageClassName: standard + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "2Gi" diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-service.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-service.yaml new file mode 100644 index 000000000..62c7b5936 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/alertmanager-service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: alertmanager + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/name: "Alertmanager" +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 9093 + selector: + k8s-app: alertmanager + type: "ClusterIP" diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/kube-state-metrics-deployment.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/kube-state-metrics-deployment.yaml new file mode 100644 index 000000000..6b9877414 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/kube-state-metrics-deployment.yaml @@ -0,0 +1,67 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: kube-state-metrics + namespace: kube-system + labels: + k8s-app: kube-state-metrics + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile + version: v1.3.0 +spec: + selector: + matchLabels: + k8s-app: kube-state-metrics + version: v1.3.0 + replicas: 1 + template: + metadata: + labels: + k8s-app: kube-state-metrics + version: v1.3.0 + annotations: + scheduler.alpha.kubernetes.io/critical-pod: '' + spec: + priorityClassName: system-cluster-critical + serviceAccountName: kube-state-metrics + containers: + - name: kube-state-metrics + image: quay.io/coreos/kube-state-metrics:v1.3.0 + ports: + - name: http-metrics + containerPort: 8080 + - name: telemetry + containerPort: 8081 + readinessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 5 + timeoutSeconds: 5 + - name: addon-resizer + image: k8s.gcr.io/addon-resizer:1.7 + resources: + limits: + cpu: 100m + memory: 30Mi + requests: + cpu: 100m + memory: 30Mi + env: + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + command: + - /pod_nanny + - --container=kube-state-metrics + - --cpu=100m + - --extra-cpu=1m + - --memory=100Mi + - --extra-memory=2Mi + - --threshold=5 + - --deployment=kube-state-metrics diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/kube-state-metrics-rbac.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/kube-state-metrics-rbac.yaml new file mode 100644 index 000000000..2a27ce46e --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/kube-state-metrics-rbac.yaml @@ -0,0 +1,103 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kube-state-metrics + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kube-state-metrics + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +rules: +- apiGroups: [""] + resources: + - configmaps + - secrets + - nodes + - pods + - services + - resourcequotas + - replicationcontrollers + - limitranges + - persistentvolumeclaims + - persistentvolumes + - namespaces + - endpoints + verbs: ["list", "watch"] +- apiGroups: ["extensions"] + resources: + - daemonsets + - deployments + - replicasets + verbs: ["list", "watch"] +- apiGroups: ["apps"] + resources: + - statefulsets + verbs: ["list", "watch"] +- apiGroups: ["batch"] + resources: + - cronjobs + - jobs + verbs: ["list", "watch"] +- apiGroups: ["autoscaling"] + resources: + - horizontalpodautoscalers + verbs: ["list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kube-state-metrics-resizer + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +rules: +- apiGroups: [""] + resources: + - pods + verbs: ["get"] +- apiGroups: ["extensions"] + resources: + - deployments + resourceNames: ["kube-state-metrics"] + verbs: ["get", "update"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kube-state-metrics + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kube-state-metrics +subjects: +- kind: ServiceAccount + name: kube-state-metrics + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: kube-state-metrics + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kube-state-metrics-resizer +subjects: +- kind: ServiceAccount + name: kube-state-metrics + namespace: kube-system diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/kube-state-metrics-service.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/kube-state-metrics-service.yaml new file mode 100644 index 000000000..bad3ffd46 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/kube-state-metrics-service.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Service +metadata: + name: kube-state-metrics + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/name: "kube-state-metrics" + annotations: + prometheus.io/scrape: 'true' +spec: + ports: + - name: http-metrics + port: 8080 + targetPort: http-metrics + protocol: TCP + - name: telemetry + port: 8081 + targetPort: telemetry + protocol: TCP + selector: + k8s-app: kube-state-metrics diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/node-exporter-ds.yml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/node-exporter-ds.yml new file mode 100644 index 000000000..0c5881c21 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/node-exporter-ds.yml @@ -0,0 +1,56 @@ +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: node-exporter + namespace: kube-system + labels: + k8s-app: node-exporter + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile + version: v0.15.2 +spec: + updateStrategy: + type: OnDelete + template: + metadata: + labels: + k8s-app: node-exporter + version: v0.15.2 + annotations: + scheduler.alpha.kubernetes.io/critical-pod: '' + spec: + priorityClassName: system-node-critical + containers: + - name: prometheus-node-exporter + image: "prom/node-exporter:v0.15.2" + imagePullPolicy: "IfNotPresent" + args: + - --path.procfs=/host/proc + - --path.sysfs=/host/sys + ports: + - name: metrics + containerPort: 9100 + hostPort: 9100 + volumeMounts: + - name: proc + mountPath: /host/proc + readOnly: true + - name: sys + mountPath: /host/sys + readOnly: true + resources: + limits: + cpu: 10m + memory: 50Mi + requests: + cpu: 10m + memory: 50Mi + hostNetwork: true + hostPID: true + volumes: + - name: proc + hostPath: + path: /proc + - name: sys + hostPath: + path: /sys diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/node-exporter-service.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/node-exporter-service.yaml new file mode 100644 index 000000000..80a374ae2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/node-exporter-service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: node-exporter + namespace: kube-system + annotations: + prometheus.io/scrape: "true" + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/name: "NodeExporter" +spec: + clusterIP: None + ports: + - name: metrics + port: 9100 + protocol: TCP + targetPort: 9100 + selector: + k8s-app: node-exporter diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-configmap.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-configmap.yaml new file mode 100644 index 000000000..8a984b987 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-configmap.yaml @@ -0,0 +1,171 @@ +# Prometheus configuration format https://prometheus.io/docs/prometheus/latest/configuration/configuration/ +apiVersion: v1 +kind: ConfigMap +metadata: + name: prometheus-config + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: EnsureExists +data: + prometheus.yml: | + scrape_configs: + - job_name: prometheus + static_configs: + - targets: + - localhost:9090 + + - job_name: kubernetes-apiservers + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - action: keep + regex: default;kubernetes;https + source_labels: + - __meta_kubernetes_namespace + - __meta_kubernetes_service_name + - __meta_kubernetes_endpoint_port_name + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + - job_name: kubernetes-nodes-kubelet + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + - job_name: kubernetes-nodes-cadvisor + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __metrics_path__ + replacement: /metrics/cadvisor + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + - job_name: kubernetes-service-endpoints + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - action: keep + regex: true + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_scrape + - action: replace + regex: (https?) + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_scheme + target_label: __scheme__ + - action: replace + regex: (.+) + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_path + target_label: __metrics_path__ + - action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + source_labels: + - __address__ + - __meta_kubernetes_service_annotation_prometheus_io_port + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: kubernetes_namespace + - action: replace + source_labels: + - __meta_kubernetes_service_name + target_label: kubernetes_name + + - job_name: kubernetes-services + kubernetes_sd_configs: + - role: service + metrics_path: /probe + params: + module: + - http_2xx + relabel_configs: + - action: keep + regex: true + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_probe + - source_labels: + - __address__ + target_label: __param_target + - replacement: blackbox + target_label: __address__ + - source_labels: + - __param_target + target_label: instance + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: + - __meta_kubernetes_namespace + target_label: kubernetes_namespace + - source_labels: + - __meta_kubernetes_service_name + target_label: kubernetes_name + + - job_name: kubernetes-pods + kubernetes_sd_configs: + - role: pod + relabel_configs: + - action: keep + regex: true + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_scrape + - action: replace + regex: (.+) + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_path + target_label: __metrics_path__ + - action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + source_labels: + - __address__ + - __meta_kubernetes_pod_annotation_prometheus_io_port + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: kubernetes_namespace + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: kubernetes_pod_name + alerting: + alertmanagers: + - kubernetes_sd_configs: + - role: pod + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + relabel_configs: + - source_labels: [__meta_kubernetes_namespace] + regex: kube-system + action: keep + - source_labels: [__meta_kubernetes_pod_label_k8s_app] + regex: alertmanager + action: keep + - source_labels: [__meta_kubernetes_pod_container_port_number] + regex: + action: drop diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-rbac.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-rbac.yaml new file mode 100644 index 000000000..be1435b59 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-rbac.yaml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: prometheus + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: prometheus + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +rules: + - apiGroups: + - "" + resources: + - nodes + - nodes/metrics + - services + - endpoints + - pods + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - nonResourceURLs: + - "/metrics" + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: prometheus + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: prometheus +subjects: +- kind: ServiceAccount + name: prometheus + namespace: kube-system diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-service.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-service.yaml new file mode 100644 index 000000000..d97394b05 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-service.yaml @@ -0,0 +1,17 @@ +kind: Service +apiVersion: v1 +metadata: + name: prometheus + namespace: kube-system + labels: + kubernetes.io/name: "Prometheus" + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +spec: + ports: + - name: http + port: 9090 + protocol: TCP + targetPort: 9090 + selector: + k8s-app: prometheus diff --git a/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-statefulset.yaml b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-statefulset.yaml new file mode 100644 index 000000000..2b1e8ff82 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/prometheus/prometheus-statefulset.yaml @@ -0,0 +1,109 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: prometheus + namespace: kube-system + labels: + k8s-app: prometheus + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile + version: v2.2.1 +spec: + serviceName: "prometheus" + replicas: 1 + podManagementPolicy: "Parallel" + updateStrategy: + type: "RollingUpdate" + selector: + matchLabels: + k8s-app: prometheus + template: + metadata: + labels: + k8s-app: prometheus + annotations: + scheduler.alpha.kubernetes.io/critical-pod: '' + spec: + priorityClassName: system-cluster-critical + serviceAccountName: prometheus + initContainers: + - name: "init-chown-data" + image: "busybox:latest" + imagePullPolicy: "IfNotPresent" + command: ["chown", "-R", "65534:65534", "/data"] + volumeMounts: + - name: prometheus-data + mountPath: /data + subPath: "" + containers: + - name: prometheus-server-configmap-reload + image: "jimmidyson/configmap-reload:v0.1" + imagePullPolicy: "IfNotPresent" + args: + - --volume-dir=/etc/config + - --webhook-url=http://localhost:9090/-/reload + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + resources: + limits: + cpu: 10m + memory: 10Mi + requests: + cpu: 10m + memory: 10Mi + + - name: prometheus-server + image: "prom/prometheus:v2.2.1" + imagePullPolicy: "IfNotPresent" + args: + - --config.file=/etc/config/prometheus.yml + - --storage.tsdb.path=/data + - --web.console.libraries=/etc/prometheus/console_libraries + - --web.console.templates=/etc/prometheus/consoles + - --web.enable-lifecycle + ports: + - containerPort: 9090 + readinessProbe: + httpGet: + path: /-/ready + port: 9090 + initialDelaySeconds: 30 + timeoutSeconds: 30 + livenessProbe: + httpGet: + path: /-/healthy + port: 9090 + initialDelaySeconds: 30 + timeoutSeconds: 30 + # based on 10 running nodes with 30 pods each + resources: + limits: + cpu: 200m + memory: 1000Mi + requests: + cpu: 200m + memory: 1000Mi + + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: prometheus-data + mountPath: /data + subPath: "" + terminationGracePeriodSeconds: 300 + volumes: + - name: config-volume + configMap: + name: prometheus-config + volumeClaimTemplates: + - metadata: + name: prometheus-data + spec: + storageClassName: standard + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "16Gi" diff --git a/vendor/k8s.io/kubernetes/cluster/addons/rbac/cluster-autoscaler/cluster-autoscaler-rbac.yaml b/vendor/k8s.io/kubernetes/cluster/addons/rbac/cluster-autoscaler/cluster-autoscaler-rbac.yaml new file mode 100644 index 000000000..822f3c7b4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/addons/rbac/cluster-autoscaler/cluster-autoscaler-rbac.yaml @@ -0,0 +1,68 @@ +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: cluster-autoscaler + labels: + addonmanager.kubernetes.io/mode: Reconcile +rules: + # leader election + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["create"] + - apiGroups: [""] + resources: ["endpoints"] + resourceNames: ["cluster-autoscaler"] + verbs: ["get", "update", "patch", "delete"] + # accessing & modifying cluster state (nodes & pods) + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["pods/eviction"] + verbs: ["create"] + # read-only access to cluster state + - apiGroups: [""] + resources: ["services", "replicationcontrollers", "persistentvolumes", "persistentvolumeclaims"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps", "extensions"] + resources: ["daemonsets", "replicasets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps"] + resources: ["statefulsets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["policy"] + resources: ["poddisruptionbudgets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list", "watch"] + # misc access + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "update", "patch"] + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["create"] + - apiGroups: [""] + resources: ["configmaps"] + resourceNames: ["cluster-autoscaler-status"] + verbs: ["get", "update", "patch", "delete"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: cluster-autoscaler + labels: + addonmanager.kubernetes.io/mode: Reconcile +subjects: + - kind: User + name: cluster-autoscaler + namespace: kube-system +roleRef: + kind: ClusterRole + name: cluster-autoscaler + apiGroup: rbac.authorization.k8s.io + diff --git a/vendor/k8s.io/kubernetes/cluster/centos/build.sh b/vendor/k8s.io/kubernetes/cluster/centos/build.sh index 5d314371a..b7bc78328 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/build.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/config-build.sh b/vendor/k8s.io/kubernetes/cluster/centos/config-build.sh index 4854f7e10..852c3673f 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/config-build.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/config-build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/config-default.sh b/vendor/k8s.io/kubernetes/cluster/centos/config-default.sh index d24f59a90..0da86f28f 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/config-default.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/config-default.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/config-test.sh b/vendor/k8s.io/kubernetes/cluster/centos/config-test.sh index 5a0b917c5..c3a5c476f 100644 --- a/vendor/k8s.io/kubernetes/cluster/centos/config-test.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/config-test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/deployAddons.sh b/vendor/k8s.io/kubernetes/cluster/centos/deployAddons.sh index cefbc7c25..b19d1cd1e 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/deployAddons.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/deployAddons.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -26,7 +26,7 @@ export KUBE_CONFIG_FILE=${KUBE_CONFIG_FILE:-${KUBE_ROOT}/cluster/centos/config-d function deploy_dns { echo "Deploying DNS on Kubernetes" - cp "${KUBE_ROOT}/cluster/addons/dns/kube-dns.yaml.sed" kube-dns.yaml + cp "${KUBE_ROOT}/cluster/addons/dns/kube-dns/kube-dns.yaml.sed" kube-dns.yaml sed -i -e "s/\\\$DNS_DOMAIN/${DNS_DOMAIN}/g" kube-dns.yaml sed -i -e "s/\\\$DNS_SERVER_IP/${DNS_SERVER_IP}/g" kube-dns.yaml diff --git a/vendor/k8s.io/kubernetes/cluster/centos/make-ca-cert.sh b/vendor/k8s.io/kubernetes/cluster/centos/make-ca-cert.sh index c86f27bba..37202e3cc 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/make-ca-cert.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/make-ca-cert.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/apiserver.sh b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/apiserver.sh index 686e95d68..89e834f90 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/apiserver.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/apiserver.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/controller-manager.sh b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/controller-manager.sh index 3025d06fd..6fcbe6f9a 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/controller-manager.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/controller-manager.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/flannel.sh b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/flannel.sh index 092fcd8ff..745a29f08 100644 --- a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/flannel.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/flannel.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/post-etcd.sh b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/post-etcd.sh index be1859075..6bdfd5309 100644 --- a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/post-etcd.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/post-etcd.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/scheduler.sh b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/scheduler.sh index 202fb1b8d..2d9de3a21 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/scheduler.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/master/scripts/scheduler.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/node/bin/mk-docker-opts.sh b/vendor/k8s.io/kubernetes/cluster/centos/node/bin/mk-docker-opts.sh index 041d97758..e45dbc71b 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/node/bin/mk-docker-opts.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/node/bin/mk-docker-opts.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/node/bin/remove-docker0.sh b/vendor/k8s.io/kubernetes/cluster/centos/node/bin/remove-docker0.sh index 04b8d824c..8c862fbce 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/node/bin/remove-docker0.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/node/bin/remove-docker0.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/docker.sh b/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/docker.sh index 320446a5b..8b878b24c 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/docker.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/docker.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/flannel.sh b/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/flannel.sh index 58783c5e3..fe9b8e90c 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/flannel.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/flannel.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/kubelet.sh b/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/kubelet.sh index f11a56e9d..a6c0e216d 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/kubelet.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/kubelet.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/proxy.sh b/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/proxy.sh index 584987bf7..455084866 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/proxy.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/node/scripts/proxy.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/centos/util.sh b/vendor/k8s.io/kubernetes/cluster/centos/util.sh index 10378428b..efb1c878b 100755 --- a/vendor/k8s.io/kubernetes/cluster/centos/util.sh +++ b/vendor/k8s.io/kubernetes/cluster/centos/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/clientbin.sh b/vendor/k8s.io/kubernetes/cluster/clientbin.sh index a03a2ca3e..94d6894ef 100755 --- a/vendor/k8s.io/kubernetes/cluster/clientbin.sh +++ b/vendor/k8s.io/kubernetes/cluster/clientbin.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/common.sh b/vendor/k8s.io/kubernetes/cluster/common.sh index e20cece0e..6379219cb 100755 --- a/vendor/k8s.io/kubernetes/cluster/common.sh +++ b/vendor/k8s.io/kubernetes/cluster/common.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -453,32 +453,37 @@ EOF popd } -# Check whether required client and server binaries exist, prompting to download +# Check whether required binaries exist, prompting to download # if missing. # If KUBERNETES_SKIP_CONFIRM is set to y, we'll automatically download binaries # without prompting. function verify-kube-binaries() { - local missing_binaries=false if ! "${KUBE_ROOT}/cluster/kubectl.sh" version --client >&/dev/null; then echo "!!! kubectl appears to be broken or missing" - missing_binaries=true - fi - if ! $(find-release-tars); then - missing_binaries=true + download-release-binaries fi +} - if ! "${missing_binaries}"; then - return +# Check whether required release artifacts exist, prompting to download +# if missing. +# If KUBERNETES_SKIP_CONFIRM is set to y, we'll automatically download binaries +# without prompting. +function verify-release-tars() { + if ! $(find-release-tars); then + download-release-binaries fi +} +# Download release artifacts. +function download-release-binaries() { get_binaries_script="${KUBE_ROOT}/cluster/get-kube-binaries.sh" local resp="y" if [[ ! "${KUBERNETES_SKIP_CONFIRM:-n}" =~ ^[yY]$ ]]; then - echo "Required binaries appear to be missing. Do you wish to download them? [Y/n]" + echo "Required release artifacts appear to be missing. Do you wish to download them? [Y/n]" read resp fi if [[ "${resp}" =~ ^[nN]$ ]]; then - echo "You must download binaries to continue. You can use " + echo "You must download release artifacts to continue. You can use " echo " ${get_binaries_script}" echo "to do this for your automatically." exit 1 diff --git a/vendor/k8s.io/kubernetes/cluster/gce/OWNERS b/vendor/k8s.io/kubernetes/cluster/gce/OWNERS index aa00c0cc7..16cb0f077 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/OWNERS +++ b/vendor/k8s.io/kubernetes/cluster/gce/OWNERS @@ -5,6 +5,7 @@ reviewers: - vishh - mwielgus - MaciekPytel + - jingax10 approvers: - bowei - gmarek @@ -12,3 +13,4 @@ approvers: - vishh - mwielgus - MaciekPytel + - jingax10 diff --git a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/persistent-volume-binder-role.yaml b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/persistent-volume-binder-role.yaml index 277707019..5103b54dd 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/persistent-volume-binder-role.yaml +++ b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/persistent-volume-binder-role.yaml @@ -11,7 +11,7 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - - extensions + - policy resourceNames: - gce.persistent-volume-binder resources: diff --git a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/persistent-volume-binder.yaml b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/persistent-volume-binder.yaml index f15462037..bcb51caa9 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/persistent-volume-binder.yaml +++ b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/persistent-volume-binder.yaml @@ -1,12 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: gce.persistent-volume-binder annotations: kubernetes.io/description: 'Policy used by the persistent-volume-binder (a.k.a. persistentvolume-controller) to run recycler pods.' - # TODO: This should use the default seccomp profile. - seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'runtime/default,docker/default' labels: kubernetes.io/cluster-service: 'true' addonmanager.kubernetes.io/mode: Reconcile diff --git a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/privileged-role.yaml b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/privileged-role.yaml index 84bc91898..d89f67f25 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/privileged-role.yaml +++ b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/privileged-role.yaml @@ -7,7 +7,7 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - - extensions + - policy resourceNames: - gce.privileged resources: diff --git a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/privileged.yaml b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/privileged.yaml index 0fb96e164..ba85ef987 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/privileged.yaml +++ b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/privileged.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: gce.privileged diff --git a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/unprivileged-addon-role.yaml b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/unprivileged-addon-role.yaml index 580d67dec..2edfd62e0 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/unprivileged-addon-role.yaml +++ b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/unprivileged-addon-role.yaml @@ -8,7 +8,7 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - - extensions + - policy resourceNames: - gce.unprivileged-addon resources: diff --git a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/unprivileged-addon.yaml b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/unprivileged-addon.yaml index c3af5e2a3..a35258a34 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/unprivileged-addon.yaml +++ b/vendor/k8s.io/kubernetes/cluster/gce/addons/podsecuritypolicies/unprivileged-addon.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: gce.unprivileged-addon @@ -7,8 +7,8 @@ metadata: privilege necessary to run non-privileged kube-system pods. This policy is not intended for use outside of kube-system, and may include further restrictions in the future.' - # TODO: Addons should use the default seccomp profile. - seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'runtime/default,docker/default' # 'runtime/default' is already the default, but must be filled in on the # pod to pass admission. apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' diff --git a/vendor/k8s.io/kubernetes/cluster/gce/config-common.sh b/vendor/k8s.io/kubernetes/cluster/gce/config-common.sh index 08fb5039b..5ced3e1be 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/config-common.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/config-common.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -99,21 +99,18 @@ function get-cluster-ip-range { } # Calculate ip alias range based on max number of pods. -# Let pow be the smallest integer which is bigger than log2($1 * 2). +# Let pow be the smallest integer which is bigger or equal to log2($1 * 2). # (32 - pow) will be returned. # # $1: The number of max pods limitation. function get-alias-range-size() { for pow in {0..31}; do - if (( 1 << $pow > $1 * 2 )); then + if (( 1 << $pow >= $1 * 2 )); then echo $((32 - pow)) return 0 fi done - echo -e "${color_red}Error finding an alias range for $1 IPs." >&2 - exit 1 } - # NOTE: Avoid giving nodes empty scopes, because kubelet needs a service account # in order to initialize properly. NODE_SCOPES="${NODE_SCOPES:-monitoring,logging-write,storage-ro}" diff --git a/vendor/k8s.io/kubernetes/cluster/gce/config-default.sh b/vendor/k8s.io/kubernetes/cluster/gce/config-default.sh index c7615a453..8f0034597 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/config-default.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/config-default.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -74,7 +74,7 @@ fi # Also please update corresponding image for node e2e at: # https://github.com/kubernetes/kubernetes/blob/master/test/e2e_node/jenkins/image-config.yaml CVM_VERSION=${CVM_VERSION:-container-vm-v20170627} -GCI_VERSION=${KUBE_GCI_VERSION:-cos-stable-63-10032-71-0} +GCI_VERSION=${KUBE_GCI_VERSION:-cos-stable-65-10323-64-0} MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-} MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-cos-cloud} NODE_IMAGE=${KUBE_GCE_NODE_IMAGE:-${GCI_VERSION}} @@ -84,8 +84,6 @@ CONTAINER_RUNTIME=${KUBE_CONTAINER_RUNTIME:-docker} CONTAINER_RUNTIME_ENDPOINT=${KUBE_CONTAINER_RUNTIME_ENDPOINT:-} CONTAINER_RUNTIME_NAME=${KUBE_CONTAINER_RUNTIME_NAME:-} LOAD_IMAGE_COMMAND=${KUBE_LOAD_IMAGE_COMMAND:-} -RKT_VERSION=${KUBE_RKT_VERSION:-1.23.0} -RKT_STAGE1_IMAGE=${KUBE_RKT_STAGE1_IMAGE:-coreos.com/rkt/stage1-coreos} # MASTER_EXTRA_METADATA is the extra instance metadata on master instance separated by commas. MASTER_EXTRA_METADATA=${KUBE_MASTER_EXTRA_METADATA:-${KUBE_EXTRA_METADATA:-}} # MASTER_EXTRA_METADATA is the extra instance metadata on node instance separated by commas. @@ -144,7 +142,10 @@ ENABLE_L7_LOADBALANCING="${KUBE_ENABLE_L7_LOADBALANCING:-glbc}" # stackdriver - Heapster, Google Cloud Monitoring (schema container), and Google Cloud Logging # googleinfluxdb - Enable influxdb and google (except GCM) # standalone - Heapster only. Metrics available via Heapster REST API. -ENABLE_CLUSTER_MONITORING="${KUBE_ENABLE_CLUSTER_MONITORING:-influxdb}" +ENABLE_CLUSTER_MONITORING="${KUBE_ENABLE_CLUSTER_MONITORING:-standalone}" + +# Optional: Enable deploying separate prometheus stack for monitoring kubernetes cluster +ENABLE_PROMETHEUS_MONITORING="${KUBE_ENABLE_PROMETHEUS_MONITORING:-false}" # Optional: Enable Metrics Server. Metrics Server should be enable everywhere, # since it's a critical component, but in the first release we need a way to disable @@ -179,6 +180,16 @@ if [[ ${NETWORK_POLICY_PROVIDER:-} == "calico" ]]; then NON_MASTER_NODE_LABELS="${NON_MASTER_NODE_LABELS:+${NON_MASTER_NODE_LABELS},}projectcalico.org/ds-ready=true" fi +# Optional: Enable netd. +ENABLE_NETD="${KUBE_ENABLE_NETD:-false}" +CUSTOM_NETD_YAML="${KUBE_CUSTOM_NETD_YAML:-}" + +# To avoid running netd on a node that is not configured appropriately, +# label each Node so that the DaemonSet can run the Pods only on ready Nodes. +if [[ ${ENABLE_NETD:-} == "true" ]]; then + NON_MASTER_NODE_LABELS="${NON_MASTER_NODE_LABELS:+${NON_MASTER_NODE_LABELS},}beta.kubernetes.io/kube-netd-ready=true" +fi + # Enable metadata concealment by firewalling pod traffic to the metadata server # and run a proxy daemonset on nodes. # @@ -191,6 +202,25 @@ if [[ ${ENABLE_METADATA_CONCEALMENT:-} == "true" ]]; then PROVIDER_VARS="${PROVIDER_VARS:-} ENABLE_METADATA_CONCEALMENT METADATA_CONCEALMENT_NO_FIREWALL" fi + +# Enable AESGCM encryption of secrets by default. +ENCRYPTION_PROVIDER_CONFIG="${ENCRYPTION_PROVIDER_CONFIG:-}" +if [[ -z "${ENCRYPTION_PROVIDER_CONFIG}" ]]; then + ENCRYPTION_PROVIDER_CONFIG=$(cat << EOM | base64 | tr -d '\r\n' +kind: EncryptionConfig +apiVersion: v1 +resources: + - resources: + - secrets + providers: + - aesgcm: + keys: + - name: key1 + secret: $(dd if=/dev/random bs=32 count=1 status=none | base64 | tr -d '\r\n') +EOM +) +fi + # Optional: Enable node logging. ENABLE_NODE_LOGGING="${KUBE_ENABLE_NODE_LOGGING:-true}" LOGGING_DESTINATION="${KUBE_LOGGING_DESTINATION:-gcp}" # options: elasticsearch, gcp @@ -207,6 +237,10 @@ fi # Optional: customize runtime config RUNTIME_CONFIG="${KUBE_RUNTIME_CONFIG:-}" +if [[ "${KUBE_FEATURE_GATES:-}" == "AllAlpha=true" ]]; then + RUNTIME_CONFIG="${KUBE_RUNTIME_CONFIG:-api/all=true}" +fi + # Optional: set feature gates FEATURE_GATES="${KUBE_FEATURE_GATES:-ExperimentalCriticalPodAnnotation=true}" @@ -273,7 +307,7 @@ if [ ${ENABLE_IP_ALIASES} = true ]; then # If we're using custom network, use the subnet we already create for it as the one for ip-alias. # Note that this means SUBNETWORK would override KUBE_GCE_IP_ALIAS_SUBNETWORK in case of custom network. if [[ "${CREATE_CUSTOM_NETWORK}" == true ]]; then - IP_ALIAS_SUBNETWORK="${SUBNETWORK:-IP_ALIAS_SUBNETWORK}" + IP_ALIAS_SUBNETWORK="${SUBNETWORK}" fi # Reserve the services IP space to avoid being allocated for other GCP resources. SERVICE_CLUSTER_IP_SUBNETWORK=${KUBE_GCE_SERVICE_CLUSTER_IP_SUBNETWORK:-${INSTANCE_PREFIX}-subnet-services} @@ -334,7 +368,7 @@ NETWORK_POLICY_PROVIDER="${NETWORK_POLICY_PROVIDER:-none}" # calico NON_MASQUERADE_CIDR="0.0.0.0/0" # How should the kubelet configure hairpin mode? -HAIRPIN_MODE="${HAIRPIN_MODE:-promiscuous-bridge}" # promiscuous-bridge, hairpin-veth, none +HAIRPIN_MODE="${HAIRPIN_MODE:-hairpin-veth}" # promiscuous-bridge, hairpin-veth, none # Optional: if set to true, kube-up will configure the cluster to run e2e tests. E2E_STORAGE_TEST_ENVIRONMENT="${KUBE_E2E_STORAGE_TEST_ENVIRONMENT:-false}" @@ -369,6 +403,8 @@ if [[ -n "${LOGROTATE_MAX_SIZE:-}" ]]; then fi # Fluentd requirements +# YAML exists to trigger a configuration refresh when changes are made. +FLUENTD_GCP_YAML_VERSION="v3.1.0" FLUENTD_GCP_VERSION="${FLUENTD_GCP_VERSION:-0.2-1.5.30-1-k8s}" FLUENTD_GCP_MEMORY_LIMIT="${FLUENTD_GCP_MEMORY_LIMIT:-}" FLUENTD_GCP_CPU_REQUEST="${FLUENTD_GCP_CPU_REQUEST:-}" @@ -384,7 +420,10 @@ HEAPSTER_GCP_CPU_PER_NODE="${HEAPSTER_GCP_CPU_PER_NODE:-0.5}" LOGGING_STACKDRIVER_RESOURCE_TYPES="${LOGGING_STACKDRIVER_RESOURCE_TYPES:-old}" # Adding to PROVIDER_VARS, since this is GCP-specific. -PROVIDER_VARS="${PROVIDER_VARS:-} FLUENTD_GCP_VERSION FLUENTD_GCP_MEMORY_LIMIT FLUENTD_GCP_CPU_REQUEST FLUENTD_GCP_MEMORY_REQUEST HEAPSTER_GCP_BASE_MEMORY HEAPSTER_GCP_MEMORY_PER_NODE HEAPSTER_GCP_BASE_CPU HEAPSTER_GCP_CPU_PER_NODE CUSTOM_KUBE_DASHBOARD_BANNER LOGGING_STACKDRIVER_RESOURCE_TYPES" +PROVIDER_VARS="${PROVIDER_VARS:-} FLUENTD_GCP_YAML_VERSION FLUENTD_GCP_VERSION FLUENTD_GCP_MEMORY_LIMIT FLUENTD_GCP_CPU_REQUEST FLUENTD_GCP_MEMORY_REQUEST HEAPSTER_GCP_BASE_MEMORY HEAPSTER_GCP_MEMORY_PER_NODE HEAPSTER_GCP_BASE_CPU HEAPSTER_GCP_CPU_PER_NODE CUSTOM_KUBE_DASHBOARD_BANNER LOGGING_STACKDRIVER_RESOURCE_TYPES" + +# Fluentd configuration for node-journal +ENABLE_NODE_JOURNAL="${ENABLE_NODE_JOURNAL:-false}" # prometheus-to-sd configuration PROMETHEUS_TO_SD_ENDPOINT="${PROMETHEUS_TO_SD_ENDPOINT:-https://monitoring.googleapis.com/}" diff --git a/vendor/k8s.io/kubernetes/cluster/gce/config-test.sh b/vendor/k8s.io/kubernetes/cluster/gce/config-test.sh index 46fc0c709..fe4fd6e06 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/config-test.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/config-test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -66,13 +66,17 @@ if [[ "${NODE_OS_DISTRIBUTION}" == "debian" ]]; then NODE_ACCELERATORS="" fi +# To avoid failing large tests due to some flakes in starting nodes, allow +# for a small percentage of nodes to not start during cluster startup. +ALLOWED_NOTREADY_NODES="${ALLOWED_NOTREADY_NODES:-$((NUM_NODES / 100))}" + # By default a cluster will be started with the master and nodes # on Container-optimized OS (cos, previously known as gci). If # you are updating the os image versions, update this variable. # Also please update corresponding image for node e2e at: # https://github.com/kubernetes/kubernetes/blob/master/test/e2e_node/jenkins/image-config.yaml CVM_VERSION=${CVM_VERSION:-container-vm-v20170627} -GCI_VERSION=${KUBE_GCI_VERSION:-cos-stable-63-10032-71-0} +GCI_VERSION=${KUBE_GCI_VERSION:-cos-stable-65-10323-64-0} MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-} MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-cos-cloud} NODE_IMAGE=${KUBE_GCE_NODE_IMAGE:-${GCI_VERSION}} @@ -83,8 +87,6 @@ CONTAINER_RUNTIME_ENDPOINT=${KUBE_CONTAINER_RUNTIME_ENDPOINT:-} CONTAINER_RUNTIME_NAME=${KUBE_CONTAINER_RUNTIME_NAME:-} LOAD_IMAGE_COMMAND=${KUBE_LOAD_IMAGE_COMMAND:-} GCI_DOCKER_VERSION=${KUBE_GCI_DOCKER_VERSION:-} -RKT_VERSION=${KUBE_RKT_VERSION:-1.23.0} -RKT_STAGE1_IMAGE=${KUBE_RKT_STAGE1_IMAGE:-coreos.com/rkt/stage1-coreos} # MASTER_EXTRA_METADATA is the extra instance metadata on master instance separated by commas. MASTER_EXTRA_METADATA=${KUBE_MASTER_EXTRA_METADATA:-${KUBE_EXTRA_METADATA:-}} # MASTER_EXTRA_METADATA is the extra instance metadata on node instance separated by commas. @@ -111,6 +113,10 @@ NODE_IP_RANGE="$(get-node-ip-range)" RUNTIME_CONFIG="${KUBE_RUNTIME_CONFIG:-}" +if [[ "${KUBE_FEATURE_GATES:-}" == "AllAlpha=true" ]]; then + RUNTIME_CONFIG="${KUBE_RUNTIME_CONFIG:-api/all=true}" +fi + # Optional: set feature gates FEATURE_GATES="${KUBE_FEATURE_GATES:-ExperimentalCriticalPodAnnotation=true}" @@ -138,7 +144,10 @@ ENABLE_L7_LOADBALANCING="${KUBE_ENABLE_L7_LOADBALANCING:-glbc}" # stackdriver - Heapster, Google Cloud Monitoring (schema container), and Google Cloud Logging # googleinfluxdb - Enable influxdb and google (except GCM) # standalone - Heapster only. Metrics available via Heapster REST API. -ENABLE_CLUSTER_MONITORING="${KUBE_ENABLE_CLUSTER_MONITORING:-influxdb}" +ENABLE_CLUSTER_MONITORING="${KUBE_ENABLE_CLUSTER_MONITORING:-standalone}" + +# Optional: Enable deploying separate prometheus stack for monitoring kubernetes cluster +ENABLE_PROMETHEUS_MONITORING="${KUBE_ENABLE_PROMETHEUS_MONITORING:-false}" # Optional: Enable Metrics Server. Metrics Server should be enable everywhere, # since it's a critical component, but in the first release we need a way to disable @@ -157,7 +166,7 @@ ENABLE_METADATA_AGENT="${KUBE_ENABLE_METADATA_AGENT:-none}" # Useful for scheduling heapster in large clusters with nodes of small size. HEAPSTER_MACHINE_TYPE="${HEAPSTER_MACHINE_TYPE:-}" -# Set etcd image (e.g. k8s.gcr.io/etcd) and version (e.g. 3.1.12) if you need +# Set etcd image (e.g. k8s.gcr.io/etcd) and version (e.g. 3.2.18-0) if you need # non-default version. ETCD_IMAGE="${TEST_ETCD_IMAGE:-}" ETCD_DOCKER_REPOSITORY="${TEST_ETCD_DOCKER_REPOSITORY:-}" @@ -181,14 +190,14 @@ TEST_CLUSTER_RESYNC_PERIOD="${TEST_CLUSTER_RESYNC_PERIOD:---min-resync-period=3m # ContentType used by all components to communicate with apiserver. TEST_CLUSTER_API_CONTENT_TYPE="${TEST_CLUSTER_API_CONTENT_TYPE:-}" -KUBELET_TEST_ARGS="${KUBELET_TEST_ARGS:-} --max-pods=110 --serialize-image-pulls=false ${TEST_CLUSTER_API_CONTENT_TYPE}" -if [[ "${NODE_OS_DISTRIBUTION}" == "gci" ]] || [[ "${NODE_OS_DISTRIBUTION}" == "ubuntu" ]] || [[ "${NODE_OS_DISTRIBUTION}" == "custom" ]]; then - NODE_KUBELET_TEST_ARGS=" --experimental-kernel-memcg-notification=true" -fi -if [[ "${MASTER_OS_DISTRIBUTION}" == "gci" ]] || [[ "${MASTER_OS_DISTRIBUTION}" == "ubuntu" ]]; then - MASTER_KUBELET_TEST_ARGS=" --experimental-kernel-memcg-notification=true" +KUBELET_TEST_ARGS="${KUBELET_TEST_ARGS:-} --serialize-image-pulls=false ${TEST_CLUSTER_API_CONTENT_TYPE}" +if [[ "${NODE_OS_DISTRIBUTION}" == "gci" ]] || [[ "${NODE_OS_DISTRIBUTION}" == "ubuntu" ]] || [[ "${NODE_OS_DISTRIBUTION}" == "custom" ]]; then + NODE_KUBELET_TEST_ARGS="${NODE_KUBELET_TEST_ARGS:-} --experimental-kernel-memcg-notification=true" +fi +if [[ "${MASTER_OS_DISTRIBUTION}" == "gci" ]] || [[ "${MASTER_OS_DISTRIBUTION}" == "ubuntu" ]]; then + MASTER_KUBELET_TEST_ARGS="${MASTER_KUBELET_TEST_ARGS:-} --experimental-kernel-memcg-notification=true" fi -APISERVER_TEST_ARGS="${APISERVER_TEST_ARGS:-} --runtime-config=extensions/v1beta1 ${TEST_CLUSTER_DELETE_COLLECTION_WORKERS} ${TEST_CLUSTER_MAX_REQUESTS_INFLIGHT}" +APISERVER_TEST_ARGS="${APISERVER_TEST_ARGS:-} --vmodule=httplog=3 --runtime-config=extensions/v1beta1,scheduling.k8s.io/v1alpha1,settings.k8s.io/v1alpha1 ${TEST_CLUSTER_DELETE_COLLECTION_WORKERS} ${TEST_CLUSTER_MAX_REQUESTS_INFLIGHT}" CONTROLLER_MANAGER_TEST_ARGS="${CONTROLLER_MANAGER_TEST_ARGS:-} ${TEST_CLUSTER_RESYNC_PERIOD} ${TEST_CLUSTER_API_CONTENT_TYPE}" SCHEDULER_TEST_ARGS="${SCHEDULER_TEST_ARGS:-} ${TEST_CLUSTER_API_CONTENT_TYPE}" KUBEPROXY_TEST_ARGS="${KUBEPROXY_TEST_ARGS:-} ${TEST_CLUSTER_API_CONTENT_TYPE}" @@ -203,6 +212,16 @@ NODE_LABELS="${KUBE_NODE_LABELS:-beta.kubernetes.io/fluentd-ds-ready=true}" # NON_MASTER_NODE_LABELS are labels will only be applied on non-master nodes. NON_MASTER_NODE_LABELS="${KUBE_NON_MASTER_NODE_LABELS:-}" +# Optional: Enable netd. +ENABLE_NETD="${KUBE_ENABLE_NETD:-false}" +CUSTOM_NETD_YAML="${KUBE_CUSTOM_NETD_YAML:-}" + +# To avoid running netd on a node that is not configured appropriately, +# label each Node so that the DaemonSet can run the Pods only on ready Nodes. +if [[ ${ENABLE_NETD:-} == "true" ]]; then + NON_MASTER_NODE_LABELS="${NON_MASTER_NODE_LABELS:+${NON_MASTER_NODE_LABELS},}beta.kubernetes.io/kube-netd-ready=true" +fi + # To avoid running Calico on a node that is not configured appropriately, # label each Node so that the DaemonSet can run the Pods only on ready Nodes. if [[ ${NETWORK_POLICY_PROVIDER:-} == "calico" ]]; then @@ -295,7 +314,7 @@ if [ ${ENABLE_IP_ALIASES} = true ]; then # If we're using custom network, use the subnet we already create for it as the one for ip-alias. # Note that this means SUBNETWORK would override KUBE_GCE_IP_ALIAS_SUBNETWORK in case of custom network. if [[ "${CREATE_CUSTOM_NETWORK}" == true ]]; then - IP_ALIAS_SUBNETWORK="${SUBNETWORK:-IP_ALIAS_SUBNETWORK}" + IP_ALIAS_SUBNETWORK="${SUBNETWORK}" fi # Reserve the services IP space to avoid being allocated for other GCP resources. SERVICE_CLUSTER_IP_SUBNETWORK=${KUBE_GCE_SERVICE_CLUSTER_IP_SUBNETWORK:-${INSTANCE_PREFIX}-subnet-services} @@ -359,7 +378,7 @@ NETWORK_POLICY_PROVIDER="${NETWORK_POLICY_PROVIDER:-none}" # calico NON_MASQUERADE_CIDR="0.0.0.0/0" # How should the kubelet configure hairpin mode? -HAIRPIN_MODE="${HAIRPIN_MODE:-promiscuous-bridge}" # promiscuous-bridge, hairpin-veth, none +HAIRPIN_MODE="${HAIRPIN_MODE:-hairpin-veth}" # promiscuous-bridge, hairpin-veth, none # Optional: if set to true, kube-up will configure the cluster to run e2e tests. E2E_STORAGE_TEST_ENVIRONMENT=${KUBE_E2E_STORAGE_TEST_ENVIRONMENT:-false} @@ -400,6 +419,8 @@ if [[ -n "${LOGROTATE_MAX_SIZE:-}" ]]; then fi # Fluentd requirements +# YAML exists to trigger a configuration refresh when changes are made. +FLUENTD_GCP_YAML_VERSION="v3.1.0" FLUENTD_GCP_VERSION="${FLUENTD_GCP_VERSION:-0.2-1.5.30-1-k8s}" FLUENTD_GCP_MEMORY_LIMIT="${FLUENTD_GCP_MEMORY_LIMIT:-}" FLUENTD_GCP_CPU_REQUEST="${FLUENTD_GCP_CPU_REQUEST:-}" @@ -415,7 +436,10 @@ HEAPSTER_GCP_CPU_PER_NODE="${HEAPSTER_GCP_CPU_PER_NODE:-0.5}" LOGGING_STACKDRIVER_RESOURCE_TYPES="${LOGGING_STACKDRIVER_RESOURCE_TYPES:-old}" # Adding to PROVIDER_VARS, since this is GCP-specific. -PROVIDER_VARS="${PROVIDER_VARS:-} FLUENTD_GCP_VERSION FLUENTD_GCP_MEMORY_LIMIT FLUENTD_GCP_CPU_REQUEST FLUENTD_GCP_MEMORY_REQUEST HEAPSTER_GCP_BASE_MEMORY HEAPSTER_GCP_MEMORY_PER_NODE HEAPSTER_GCP_BASE_CPU HEAPSTER_GCP_CPU_PER_NODE CUSTOM_KUBE_DASHBOARD_BANNER LOGGING_STACKDRIVER_RESOURCE_TYPES" +PROVIDER_VARS="${PROVIDER_VARS:-} FLUENTD_GCP_YAML_VERSION FLUENTD_GCP_VERSION FLUENTD_GCP_MEMORY_LIMIT FLUENTD_GCP_CPU_REQUEST FLUENTD_GCP_MEMORY_REQUEST HEAPSTER_GCP_BASE_MEMORY HEAPSTER_GCP_MEMORY_PER_NODE HEAPSTER_GCP_BASE_CPU HEAPSTER_GCP_CPU_PER_NODE CUSTOM_KUBE_DASHBOARD_BANNER LOGGING_STACKDRIVER_RESOURCE_TYPES" + +# Fluentd configuration for node-journal +ENABLE_NODE_JOURNAL="${ENABLE_NODE_JOURNAL:-false}" # prometheus-to-sd configuration PROMETHEUS_TO_SD_ENDPOINT="${PROMETHEUS_TO_SD_ENDPOINT:-https://monitoring.googleapis.com/}" diff --git a/vendor/k8s.io/kubernetes/cluster/gce/delete-stranded-load-balancers.sh b/vendor/k8s.io/kubernetes/cluster/gce/delete-stranded-load-balancers.sh index be28ef52a..b03a7bba0 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/delete-stranded-load-balancers.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/delete-stranded-load-balancers.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/BUILD b/vendor/k8s.io/kubernetes/cluster/gce/gci/BUILD index 0a16226b9..692937a8e 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/gci/BUILD +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/BUILD @@ -28,12 +28,14 @@ release_filegroup( "configure.sh", "master.yaml", "node.yaml", + "shutdown.sh", ], visibility = ["//visibility:public"], ) pkg_tar( name = "gci-trusty-manifests", + srcs = glob(["gke-internal-configure-helper.sh"]), files = { "//cluster/gce/gci/mounter": "gci-mounter", "configure-helper.sh": "gci-configure-helper.sh", diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/configure-helper.sh b/vendor/k8s.io/kubernetes/cluster/gce/gci/configure-helper.sh index 76beee68f..5dfb81818 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/gci/configure-helper.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/configure-helper.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -27,6 +27,8 @@ set -o pipefail readonly UUID_MNT_PREFIX="/mnt/disks/by-uuid/google-local-ssds" readonly UUID_BLOCK_PREFIX="/dev/disk/by-uuid/google-local-ssds" +readonly COREDNS_AUTOSCALER="Deployment/coredns" +readonly KUBEDNS_AUTOSCALER="Deployment/kube-dns" # Use --retry-connrefused opt only if it's supported by curl. CURL_RETRY_CONNREFUSED="" @@ -543,6 +545,9 @@ function create-master-auth { if [[ -n "${KUBE_SCHEDULER_TOKEN:-}" ]]; then append_or_replace_prefixed_line "${known_tokens_csv}" "${KUBE_SCHEDULER_TOKEN}," "system:kube-scheduler,uid:system:kube-scheduler" fi + if [[ -n "${KUBE_CLUSTER_AUTOSCALER_TOKEN:-}" ]]; then + append_or_replace_prefixed_line "${known_tokens_csv}" "${KUBE_CLUSTER_AUTOSCALER_TOKEN}," "cluster-autoscaler,uid:cluster-autoscaler" + fi if [[ -n "${KUBE_PROXY_TOKEN:-}" ]]; then append_or_replace_prefixed_line "${known_tokens_csv}" "${KUBE_PROXY_TOKEN}," "system:kube-proxy,uid:kube_proxy" fi @@ -890,8 +895,9 @@ function create-kubelet-kubeconfig() { echo "Must provide API server address to create Kubelet kubeconfig file!" exit 1 fi - echo "Creating kubelet kubeconfig file" - cat </var/lib/kubelet/bootstrap-kubeconfig + if [[ "${CREATE_BOOTSTRAP_KUBECONFIG:-true}" == "true" ]]; then + echo "Creating kubelet bootstrap-kubeconfig file" + cat </var/lib/kubelet/bootstrap-kubeconfig apiVersion: v1 kind: Config users: @@ -911,6 +917,13 @@ contexts: name: service-account-context current-context: service-account-context EOF + elif [[ "${FETCH_BOOTSTRAP_KUBECONFIG:-false}" == "true" ]]; then + echo "Fetching kubelet bootstrap-kubeconfig file from metadata" + get-metadata-value "instance/attributes/bootstrap-kubeconfig" >/var/lib/kubelet/bootstrap-kubeconfig + else + echo "Fetching kubelet kubeconfig file from metadata" + get-metadata-value "instance/attributes/kubeconfig" >/var/lib/kubelet/kubeconfig + fi } # Uses KUBELET_CA_CERT (falling back to CA_CERT), KUBELET_CERT, and KUBELET_KEY @@ -996,6 +1009,30 @@ current-context: kube-scheduler EOF } +function create-clusterautoscaler-kubeconfig { + echo "Creating cluster-autoscaler kubeconfig file" + mkdir -p /etc/srv/kubernetes/cluster-autoscaler + cat </etc/srv/kubernetes/cluster-autoscaler/kubeconfig +apiVersion: v1 +kind: Config +users: +- name: cluster-autoscaler + user: + token: ${KUBE_CLUSTER_AUTOSCALER_TOKEN} +clusters: +- name: local + cluster: + insecure-skip-tls-verify: true + server: https://localhost:443 +contexts: +- context: + cluster: local + user: cluster-autoscaler + name: cluster-autoscaler +current-context: cluster-autoscaler +EOF +} + function create-kubescheduler-policy-config { echo "Creating kube-scheduler policy config file" mkdir -p /etc/srv/kubernetes/kube-scheduler @@ -1133,6 +1170,7 @@ ExecStart=${kubelet_bin} \$KUBELET_OPTS WantedBy=multi-user.target EOF + systemctl daemon-reload systemctl start kubelet.service } @@ -1144,13 +1182,18 @@ function start-node-problem-detector { local -r km_config="${KUBE_HOME}/node-problem-detector/config/kernel-monitor.json" # TODO(random-liu): Handle this for alternative container runtime. local -r dm_config="${KUBE_HOME}/node-problem-detector/config/docker-monitor.json" + local -r custom_km_config="${KUBE_HOME}/node-problem-detector/config/kernel-monitor-counter.json" echo "Using node problem detector binary at ${npd_bin}" local flags="${NPD_TEST_LOG_LEVEL:-"--v=2"} ${NPD_TEST_ARGS:-}" flags+=" --logtostderr" flags+=" --system-log-monitors=${km_config},${dm_config}" + flags+=" --custom-plugin-monitors=${custom_km_config}" flags+=" --apiserver-override=https://${KUBERNETES_MASTER_NAME}?inClusterConfig=false&auth=/var/lib/node-problem-detector/kubeconfig" local -r npd_port=${NODE_PROBLEM_DETECTOR_PORT:-20256} flags+=" --port=${npd_port}" + if [[ -n "${EXTRA_NPD_ARGS:-}" ]]; then + flags+=" ${EXTRA_NPD_ARGS}" + fi # Write the systemd service file for node problem detector. cat </etc/systemd/system/node-problem-detector.service @@ -1197,7 +1240,15 @@ function prepare-kube-proxy-manifest-variables { params+=" --feature-gates=${FEATURE_GATES}" fi if [[ "${KUBE_PROXY_MODE:-}" == "ipvs" ]];then - params+=" --proxy-mode=ipvs --feature-gates=SupportIPVSProxyMode=true" + sudo modprobe -a ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack_ipv4 + if [[ $? -eq 0 ]]; + then + params+=" --proxy-mode=ipvs" + else + # If IPVS modules are not present, make sure the node does not come up as + # healthy. + exit 1 + fi fi params+=" --iptables-sync-period=1m --iptables-min-sync-period=10s --ipvs-sync-period=1m --ipvs-min-sync-period=10s" if [[ -n "${KUBEPROXY_TEST_ARGS:-}" ]]; then @@ -1211,10 +1262,6 @@ function prepare-kube-proxy-manifest-variables { kube_cache_mutation_detector_env_name="- name: KUBE_CACHE_MUTATION_DETECTOR" kube_cache_mutation_detector_env_value="value: \"${ENABLE_CACHE_MUTATION_DETECTOR}\"" fi - local pod_priority="" - if [[ "${ENABLE_POD_PRIORITY:-}" == "true" ]]; then - pod_priority="priorityClassName: system-node-critical" - fi sed -i -e "s@{{kubeconfig}}@${kubeconfig}@g" ${src_file} sed -i -e "s@{{pillar\['kube_docker_registry'\]}}@${kube_docker_registry}@g" ${src_file} sed -i -e "s@{{pillar\['kube-proxy_docker_tag'\]}}@${kube_proxy_docker_tag}@g" ${src_file} @@ -1222,7 +1269,6 @@ function prepare-kube-proxy-manifest-variables { sed -i -e "s@{{container_env}}@${container_env}@g" ${src_file} sed -i -e "s@{{kube_cache_mutation_detector_env_name}}@${kube_cache_mutation_detector_env_name}@g" ${src_file} sed -i -e "s@{{kube_cache_mutation_detector_env_value}}@${kube_cache_mutation_detector_env_value}@g" ${src_file} - sed -i -e "s@{{pod_priority}}@${pod_priority}@g" ${src_file} sed -i -e "s@{{ cpurequest }}@100m@g" ${src_file} sed -i -e "s@{{api_servers_with_port}}@${api_servers}@g" ${src_file} sed -i -e "s@{{kubernetes_service_host_env_value}}@${KUBERNETES_MASTER_NAME}@g" ${src_file} @@ -1323,7 +1369,8 @@ function prepare-etcd-manifest { } function start-etcd-empty-dir-cleanup-pod { - cp "${KUBE_HOME}/kube-manifests/kubernetes/gci-trusty/etcd-empty-dir-cleanup/etcd-empty-dir-cleanup.yaml" "/etc/kubernetes/manifests" + local -r src_file="${KUBE_HOME}/kube-manifests/kubernetes/gci-trusty/etcd-empty-dir-cleanup.yaml" + cp "${src_file}" "/etc/kubernetes/manifests" } # Starts etcd server pod (and etcd-events pod if needed). @@ -1550,8 +1597,6 @@ function start-kube-apiserver { fi fi if [[ "${ADVANCED_AUDIT_BACKEND:-}" == *"webhook"* ]]; then - params+=" --audit-webhook-mode=batch" - # Create the audit webhook config file, and mount it into the apiserver pod. local -r audit_webhook_config_file="/etc/audit_webhook.config" params+=" --audit-webhook-config-file=${audit_webhook_config_file}" @@ -1562,6 +1607,8 @@ function start-kube-apiserver { # Batching parameters if [[ -n "${ADVANCED_AUDIT_WEBHOOK_MODE:-}" ]]; then params+=" --audit-webhook-mode=${ADVANCED_AUDIT_WEBHOOK_MODE}" + else + params+=" --audit-webhook-mode=batch" fi if [[ -n "${ADVANCED_AUDIT_WEBHOOK_BUFFER_SIZE:-}" ]]; then params+=" --audit-webhook-batch-buffer-size=${ADVANCED_AUDIT_WEBHOOK_BUFFER_SIZE}" @@ -1591,6 +1638,9 @@ function start-kube-apiserver { if [[ "${ENABLE_APISERVER_LOGS_HANDLER:-}" == "false" ]]; then params+=" --enable-logs-handler=false" fi + if [[ "${APISERVER_SET_KUBELET_CA:-false}" == "true" ]]; then + params+=" --kubelet-certificate-authority=${CA_CERT_BUNDLE_PATH}" + fi local admission_controller_config_mount="" local admission_controller_config_volume="" @@ -1625,7 +1675,7 @@ function start-kube-apiserver { params+=" --ssh-keyfile=/etc/srv/sshproxy/.sshkeyfile" fi elif [[ -n "${PROJECT_ID:-}" && -n "${TOKEN_URL:-}" && -n "${TOKEN_BODY:-}" && -n "${NODE_NETWORK:-}" ]]; then - local -r vm_external_ip=$(curl --retry 5 --retry-delay 3 ${CURL_RETRY_CONNREFUSED} --fail --silent -H 'Metadata-Flavor: Google' "http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip") + local -r vm_external_ip=$(get-metadata-value "instance/network-interfaces/0/access-configs/0/external-ip") if [[ -n "${PROXY_SSH_USER:-}" ]]; then params+=" --advertise-address=${vm_external_ip}" params+=" --ssh-user=${PROXY_SSH_USER}" @@ -1669,7 +1719,7 @@ function start-kube-apiserver { local webhook_config_mount="" local webhook_config_volume="" if [[ -n "${GCP_AUTHZ_URL:-}" ]]; then - authorization_mode="Webhook,${authorization_mode}" + authorization_mode="${authorization_mode},Webhook" params+=" --authorization-webhook-config-file=/etc/gcp_authz.config" webhook_config_mount="{\"name\": \"webhookconfigmount\",\"mountPath\": \"/etc/gcp_authz.config\", \"readOnly\": false}," webhook_config_volume="{\"name\": \"webhookconfigmount\",\"hostPath\": {\"path\": \"/etc/gcp_authz.config\", \"type\": \"FileOrCreate\"}}," @@ -1882,6 +1932,9 @@ function start-kube-controller-manager { params+=" --pv-recycler-pod-template-filepath-nfs=$PV_RECYCLER_OVERRIDE_TEMPLATE" params+=" --pv-recycler-pod-template-filepath-hostpath=$PV_RECYCLER_OVERRIDE_TEMPLATE" fi + if [[ -n "${RUN_CONTROLLERS:-}" ]]; then + params+=" --controllers=${RUN_CONTROLLERS}" + fi local -r kube_rc_docker_tag=$(cat /home/kubernetes/kube-docker-files/kube-controller-manager.docker_tag) local container_env="" @@ -1953,12 +2006,15 @@ function start-kube-scheduler { function start-cluster-autoscaler { if [[ "${ENABLE_CLUSTER_AUTOSCALER:-}" == "true" ]]; then echo "Start kubernetes cluster autoscaler" + setup-addon-manifests "addons" "rbac/cluster-autoscaler" + create-clusterautoscaler-kubeconfig prepare-log-file /var/log/cluster-autoscaler.log # Remove salt comments and replace variables with values local -r src_file="${KUBE_HOME}/kube-manifests/kubernetes/gci-trusty/cluster-autoscaler.manifest" local params="${AUTOSCALER_MIG_CONFIG} ${CLOUD_CONFIG_OPT} ${AUTOSCALER_EXPANDER_CONFIG:---expander=price}" + params+=" --kubeconfig=/etc/srv/kubernetes/cluster-autoscaler/kubeconfig" sed -i -e "s@{{params}}@${params}@g" "${src_file}" sed -i -e "s@{{cloud_config_mount}}@${CLOUD_CONFIG_MOUNT}@g" "${src_file}" sed -i -e "s@{{cloud_config_volume}}@${CLOUD_CONFIG_VOLUME}@g" "${src_file}" @@ -2016,6 +2072,20 @@ function download-extra-addons { "${curl_cmd[@]}" } +# A function that fetches a GCE metadata value and echoes it out. +# +# $1: URL path after /computeMetadata/v1/ (without heading slash). +function get-metadata-value { + curl \ + --retry 5 \ + --retry-delay 3 \ + ${CURL_RETRY_CONNREFUSED} \ + --fail \ + --silent \ + -H 'Metadata-Flavor: Google' \ + "http://metadata/computeMetadata/v1/${1}" +} + # A helper function for copying manifests and setting dir/files # permissions. # @@ -2097,10 +2167,16 @@ function start-fluentd-resource-update { wait-for-apiserver-and-update-fluentd & } -# Update {{ container-runtime }} with actual container runtime name. +# Update {{ container-runtime }} with actual container runtime name, +# and {{ container-runtime-endpoint }} with actual container runtime +# endpoint. function update-container-runtime { - local -r configmap_yaml="$1" - sed -i -e "s@{{ *container_runtime *}}@${CONTAINER_RUNTIME_NAME:-docker}@g" "${configmap_yaml}" + local -r file="$1" + local -r container_runtime_endpoint="${CONTAINER_RUNTIME_ENDPOINT:-unix:///var/run/dockershim.sock}" + sed -i \ + -e "s@{{ *container_runtime *}}@${CONTAINER_RUNTIME_NAME:-docker}@g" \ + -e "s@{{ *container_runtime_endpoint *}}@${container_runtime_endpoint#unix://}@g" \ + "${file}" } # Remove configuration in yaml file if node journal is not enabled. @@ -2138,18 +2214,25 @@ function update-dashboard-controller { # Sets up the manifests of coreDNS for k8s addons. function setup-coredns-manifest { - local -r coredns_file="${dst_dir}/dns/coredns.yaml" - mv "${dst_dir}/dns/coredns.yaml.in" "${coredns_file}" + local -r coredns_file="${dst_dir}/dns/coredns/coredns.yaml" + mv "${dst_dir}/dns/coredns/coredns.yaml.in" "${coredns_file}" # Replace the salt configurations with variable values. sed -i -e "s@{{ *pillar\['dns_domain'\] *}}@${DNS_DOMAIN}@g" "${coredns_file}" sed -i -e "s@{{ *pillar\['dns_server'\] *}}@${DNS_SERVER_IP}@g" "${coredns_file}" sed -i -e "s@{{ *pillar\['service_cluster_ip_range'\] *}}@${SERVICE_CLUSTER_IP_RANGE}@g" "${coredns_file}" + + if [[ "${ENABLE_DNS_HORIZONTAL_AUTOSCALER:-}" == "true" ]]; then + setup-addon-manifests "addons" "dns-horizontal-autoscaler" "gce" + local -r dns_autoscaler_file="${dst_dir}/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml" + sed -i'' -e "s@{{.Target}}@${COREDNS_AUTOSCALER}@g" "${dns_autoscaler_file}" + fi } # Sets up the manifests of Fluentd configmap and yamls for k8s addons. function setup-fluentd { local -r dst_dir="$1" local -r fluentd_gcp_yaml="${dst_dir}/fluentd-gcp/fluentd-gcp-ds.yaml" + local -r fluentd_gcp_scaler_yaml="${dst_dir}/fluentd-gcp/scaler-deployment.yaml" # Ingest logs against new resources like "k8s_container" and "k8s_node" if # LOGGING_STACKDRIVER_RESOURCE_TYPES is "new". # Ingest logs against old resources like "gke_container" and "gce_instance" if @@ -2162,7 +2245,10 @@ function setup-fluentd { fluentd_gcp_configmap_name="fluentd-gcp-config-old" fi sed -i -e "s@{{ fluentd_gcp_configmap_name }}@${fluentd_gcp_configmap_name}@g" "${fluentd_gcp_yaml}" - fluentd_gcp_version="${FLUENTD_GCP_VERSION:-0.2-1.5.30-1-k8s}" + fluentd_gcp_yaml_version="${FLUENTD_GCP_YAML_VERSION:-v3.1.0}" + sed -i -e "s@{{ fluentd_gcp_yaml_version }}@${fluentd_gcp_yaml_version}@g" "${fluentd_gcp_yaml}" + sed -i -e "s@{{ fluentd_gcp_yaml_version }}@${fluentd_gcp_yaml_version}@g" "${fluentd_gcp_scaler_yaml}" + fluentd_gcp_version="${FLUENTD_GCP_VERSION:-0.3-1.5.34-1-k8s-1}" sed -i -e "s@{{ fluentd_gcp_version }}@${fluentd_gcp_version}@g" "${fluentd_gcp_yaml}" update-prometheus-to-sd-parameters ${fluentd_gcp_yaml} start-fluentd-resource-update ${fluentd_gcp_yaml} @@ -2172,8 +2258,8 @@ function setup-fluentd { # Sets up the manifests of kube-dns for k8s addons. function setup-kube-dns-manifest { - local -r kubedns_file="${dst_dir}/dns/kube-dns.yaml" - mv "${dst_dir}/dns/kube-dns.yaml.in" "${kubedns_file}" + local -r kubedns_file="${dst_dir}/dns/kube-dns/kube-dns.yaml" + mv "${dst_dir}/dns/kube-dns/kube-dns.yaml.in" "${kubedns_file}" if [ -n "${CUSTOM_KUBE_DNS_YAML:-}" ]; then # Replace with custom GKE kube-dns deployment. cat > "${kubedns_file}" < "${netd_file}" < "${manifest_path}" < /etc/profile.d/kube_env.sh + # Add ${KUBE_HOME}/bin into sudoer secure path. + local sudo_path + sudo_path=$(sudo env | grep "^PATH=") + if [[ -n "${sudo_path}" ]]; then + sudo_path=${sudo_path#PATH=} + ( + umask 027 + echo "Defaults secure_path=\"${KUBE_HOME}/bin:${sudo_path}\"" > /etc/sudoers.d/kube_secure_path + ) + fi } function override-pv-recycler { @@ -2502,6 +2653,12 @@ function main() { source "${KUBE_HOME}/kube-env" + + if [[ -f "${KUBE_HOME}/kubelet-config.yaml" ]]; then + echo "Found Kubelet config file at ${KUBE_HOME}/kubelet-config.yaml" + KUBELET_CONFIG_FILE_ARG="--config ${KUBE_HOME}/kubelet-config.yaml" + fi + if [[ -e "${KUBE_HOME}/kube-master-certs" ]]; then source "${KUBE_HOME}/kube-master-certs" fi @@ -2513,9 +2670,10 @@ function main() { fi fi - # generate the controller manager and scheduler tokens here since they are only used on the master. + # generate the controller manager, scheduler and cluster autoscaler tokens here since they are only used on the master. KUBE_CONTROLLER_MANAGER_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) KUBE_SCHEDULER_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) + KUBE_CLUSTER_AUTOSCALER_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) setup-os-params config-ip-firewall @@ -2531,6 +2689,7 @@ function main() { create-master-kubelet-auth create-master-etcd-auth override-pv-recycler + gke-master-start else create-node-pki create-kubelet-kubeconfig ${KUBERNETES_MASTER_NAME} @@ -2552,6 +2711,7 @@ function main() { if [[ "${KUBERNETES_MASTER:-}" == "true" ]]; then compute-master-manifest-variables start-etcd-servers + start-etcd-empty-dir-cleanup-pod start-kube-apiserver start-kube-controller-manager start-kube-scheduler @@ -2581,4 +2741,4 @@ if [[ "$#" -eq 1 && "${1}" == "--source-only" ]]; then : else main "${@}" -fi \ No newline at end of file +fi diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/configure.sh b/vendor/k8s.io/kubernetes/cluster/gce/gci/configure.sh index 58a19815b..c2fd67500 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/gci/configure.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/configure.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -25,9 +25,11 @@ set -o pipefail ### Hardcoded constants DEFAULT_CNI_VERSION="v0.6.0" -DEFAULT_CNI_SHA1="d595d3ded6499a64e8dac02466e2f5f2ce257c9f" -DEFAULT_NPD_VERSION="v0.4.1" -DEFAULT_NPD_SHA1="a57a3fe64cab8a18ec654f5cef0aec59dae62568" +DEFAULT_CNI_SHA1="d595d3ded6499a64e8dac02466e2f5f2ce257c9f" +DEFAULT_NPD_VERSION="v0.5.0" +DEFAULT_NPD_SHA1="650ecfb2ae495175ee43706d0bd862a1ea7f1395" +DEFAULT_CRICTL_VERSION="v1.11.1" +DEFAULT_CRICTL_SHA1="527fca5a0ecef6a8e6433e2af9cf83f63aff5694" DEFAULT_MOUNTER_TAR_SHA="8003b798cf33c7f91320cd6ee5cec4fa22244571" ### @@ -54,37 +56,59 @@ EOF function download-kube-env { # Fetch kube-env from GCE metadata server. - (umask 077; - local -r tmp_kube_env="/tmp/kube-env.yaml" - curl --fail --retry 5 --retry-delay 3 ${CURL_RETRY_CONNREFUSED} --silent --show-error \ - -H "X-Google-Metadata-Request: True" \ - -o "${tmp_kube_env}" \ - http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env - # Convert the yaml format file into a shell-style file. - eval $(python -c ''' + ( + umask 077 + local -r tmp_kube_env="/tmp/kube-env.yaml" + curl --fail --retry 5 --retry-delay 3 ${CURL_RETRY_CONNREFUSED} --silent --show-error \ + -H "X-Google-Metadata-Request: True" \ + -o "${tmp_kube_env}" \ + http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env + # Convert the yaml format file into a shell-style file. + eval $(python -c ''' import pipes,sys,yaml for k,v in yaml.load(sys.stdin).iteritems(): print("readonly {var}={value}".format(var = k, value = pipes.quote(str(v)))) ''' < "${tmp_kube_env}" > "${KUBE_HOME}/kube-env") - rm -f "${tmp_kube_env}" + rm -f "${tmp_kube_env}" + ) +} + +function download-kubelet-config { + local -r dest="$1" + echo "Downloading Kubelet config file, if it exists" + # Fetch kubelet config file from GCE metadata server. + ( + umask 077 + local -r tmp_kubelet_config="/tmp/kubelet-config.yaml" + if curl --fail --retry 5 --retry-delay 3 ${CURL_RETRY_CONNREFUSED} --silent --show-error \ + -H "X-Google-Metadata-Request: True" \ + -o "${tmp_kubelet_config}" \ + http://metadata.google.internal/computeMetadata/v1/instance/attributes/kubelet-config; then + # only write to the final location if curl succeeds + mv "${tmp_kubelet_config}" "${dest}" + elif [[ "${REQUIRE_METADATA_KUBELET_CONFIG_FILE:-false}" == "true" ]]; then + echo "== Failed to download required Kubelet config file from metadata server ==" + exit 1 + fi ) } function download-kube-master-certs { # Fetch kube-env from GCE metadata server. - (umask 077; - local -r tmp_kube_master_certs="/tmp/kube-master-certs.yaml" - curl --fail --retry 5 --retry-delay 3 ${CURL_RETRY_CONNREFUSED} --silent --show-error \ - -H "X-Google-Metadata-Request: True" \ - -o "${tmp_kube_master_certs}" \ - http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-master-certs - # Convert the yaml format file into a shell-style file. - eval $(python -c ''' + ( + umask 077 + local -r tmp_kube_master_certs="/tmp/kube-master-certs.yaml" + curl --fail --retry 5 --retry-delay 3 ${CURL_RETRY_CONNREFUSED} --silent --show-error \ + -H "X-Google-Metadata-Request: True" \ + -o "${tmp_kube_master_certs}" \ + http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-master-certs + # Convert the yaml format file into a shell-style file. + eval $(python -c ''' import pipes,sys,yaml for k,v in yaml.load(sys.stdin).iteritems(): print("readonly {var}={value}".format(var = k, value = pipes.quote(str(v)))) ''' < "${tmp_kube_master_certs}" > "${KUBE_HOME}/kube-master-certs") - rm -f "${tmp_kube_master_certs}" + rm -f "${tmp_kube_master_certs}" ) } @@ -175,15 +199,15 @@ function install-node-problem-detector { local -r npd_version="${DEFAULT_NPD_VERSION}" local -r npd_sha1="${DEFAULT_NPD_SHA1}" fi + local -r npd_tar="node-problem-detector-${npd_version}.tar.gz" - if is-preloaded "node-problem-detector" "${npd_sha1}"; then + if is-preloaded "${npd_tar}" "${npd_sha1}"; then echo "node-problem-detector is preloaded." return fi echo "Downloading node problem detector." local -r npd_release_path="https://storage.googleapis.com/kubernetes-release" - local -r npd_tar="node-problem-detector-${npd_version}.tar.gz" download-or-bust "${npd_sha1}" "${npd_release_path}/node-problem-detector/${npd_tar}" local -r npd_dir="${KUBE_HOME}/node-problem-detector" mkdir -p "${npd_dir}" @@ -212,6 +236,47 @@ function install-cni-binaries { rm -f "${KUBE_HOME}/${cni_tar}" } +# Install crictl binary. +function install-crictl { + if [[ -n "${CRICTL_VERSION:-}" ]]; then + local -r crictl_version="${CRICTL_VERSION}" + local -r crictl_sha1="${CRICTL_TAR_HASH}" + else + local -r crictl_version="${DEFAULT_CRICTL_VERSION}" + local -r crictl_sha1="${DEFAULT_CRICTL_SHA1}" + fi + local -r crictl="crictl-${crictl_version}-linux-amd64" + + # Create crictl config file. + cat > /etc/crictl.yaml < /dev/null || /bin/true fi - if [ -n ${MOUNTER_DEFAULT_NAME:-} ]; then + if [[ -n ${MOUNTER_DEFAULT_NAME:-} ]]; then docker rm -f ${MOUNTER_DEFAULT_NAME} &> /dev/null || /bin/true fi } @@ -119,7 +119,7 @@ generate_chroot_wrapper() { mkdir -p $wrapper_dir cat >$wrapper_path < /dev/null; then - echo "Docker daemon failed!" - pkill docker +function container_runtime_monitoring { + local -r max_attempts=5 + local attempt=1 + local -r crictl="${KUBE_HOME}/bin/crictl" + local -r container_runtime_name="${CONTAINER_RUNTIME_NAME:-docker}" + # We still need to use `docker ps` when container runtime is "docker". This is because + # dockershim is still part of kubelet today. When kubelet is down, crictl pods + # will also fail, and docker will be killed. This is undesirable especially when + # docker live restore is disabled. + local healthcheck_command="docker ps" + if [[ "${CONTAINER_RUNTIME:-docker}" != "docker" ]]; then + healthcheck_command="${crictl} pods" + fi + # Container runtime startup takes time. Make initial attempts before starting + # killing the container runtime. + until timeout 60 ${healthcheck_command} > /dev/null; do + if (( attempt == max_attempts )); then + echo "Max attempt ${max_attempts} reached! Proceeding to monitor container runtime healthiness." + break + fi + echo "$attempt initial attempt \"${healthcheck_command}\"! Trying again in $attempt seconds..." + sleep "$(( 2 ** attempt++ ))" + done + while true; do + if ! timeout 60 ${healthcheck_command} > /dev/null; then + echo "Container runtime ${container_runtime_name} failed!" + if [[ "$container_runtime_name" == "docker" ]]; then + # Dump stack of docker daemon for investigation. + # Log fle name looks like goroutine-stacks-TIMESTAMP and will be saved to + # the exec root directory, which is /var/run/docker/ on Ubuntu and COS. + pkill -SIGUSR1 dockerd + fi + systemctl kill --kill-who=main "${container_runtime_name}" # Wait for a while, as we don't want to kill it again before it is really up. sleep 120 else @@ -48,7 +76,7 @@ function kubelet_monitoring { # Print the response and/or errors. echo $output echo "Kubelet is unhealthy!" - pkill kubelet + systemctl kill kubelet # Wait for a while, as we don't want to kill it again before it is really up. sleep 60 else @@ -60,11 +88,12 @@ function kubelet_monitoring { ############## Main Function ################ if [[ "$#" -ne 1 ]]; then - echo "Usage: health-monitor.sh " + echo "Usage: health-monitor.sh " exit 1 fi -KUBE_ENV="/home/kubernetes/kube-env" +KUBE_HOME="/home/kubernetes" +KUBE_ENV="${KUBE_HOME}/kube-env" if [[ ! -e "${KUBE_ENV}" ]]; then echo "The ${KUBE_ENV} file does not exist!! Terminate health monitoring" exit 1 @@ -74,8 +103,8 @@ SLEEP_SECONDS=10 component=$1 echo "Start kubernetes health monitoring for ${component}" source "${KUBE_ENV}" -if [[ "${component}" == "docker" ]]; then - docker_monitoring +if [[ "${component}" == "container-runtime" ]]; then + container_runtime_monitoring elif [[ "${component}" == "kubelet" ]]; then kubelet_monitoring else diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/helper.sh b/vendor/k8s.io/kubernetes/cluster/gce/gci/helper.sh index e0486c80c..11dfd7b85 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/gci/helper.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/helper.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/master-helper.sh b/vendor/k8s.io/kubernetes/cluster/gce/gci/master-helper.sh index 593652c9e..e86692696 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/gci/master-helper.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/master-helper.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -68,6 +68,7 @@ function replicate-master-instance() { get-metadata "${existing_master_zone}" "${existing_master_name}" gci-ensure-gke-docker > "${KUBE_TEMP}/gci-ensure-gke-docker.txt" get-metadata "${existing_master_zone}" "${existing_master_name}" gci-docker-version > "${KUBE_TEMP}/gci-docker-version.txt" get-metadata "${existing_master_zone}" "${existing_master_name}" kube-master-certs > "${KUBE_TEMP}/kube-master-certs.yaml" + get-metadata "${existing_master_zone}" "${existing_master_name}" cluster-location > "${KUBE_TEMP}/cluster-location.txt" create-master-instance-internal "${REPLICA_NAME}" } @@ -106,6 +107,7 @@ function create-master-instance-internal() { "${address:-}" "${enable_ip_aliases:-}" "${IP_ALIAS_SIZE:-}") local metadata="kube-env=${KUBE_TEMP}/master-kube-env.yaml" + metadata="${metadata},kubelet-config=${KUBE_TEMP}/master-kubelet-config.yaml" metadata="${metadata},user-data=${KUBE_ROOT}/cluster/gce/gci/master.yaml" metadata="${metadata},configure-sh=${KUBE_ROOT}/cluster/gce/gci/configure.sh" metadata="${metadata},cluster-location=${KUBE_TEMP}/cluster-location.txt" @@ -114,6 +116,7 @@ function create-master-instance-internal() { metadata="${metadata},gci-ensure-gke-docker=${KUBE_TEMP}/gci-ensure-gke-docker.txt" metadata="${metadata},gci-docker-version=${KUBE_TEMP}/gci-docker-version.txt" metadata="${metadata},kube-master-certs=${KUBE_TEMP}/kube-master-certs.yaml" + metadata="${metadata},cluster-location=${KUBE_TEMP}/cluster-location.txt" metadata="${metadata},${MASTER_EXTRA_METADATA}" local disk="name=${master_name}-pd" diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/master.yaml b/vendor/k8s.io/kubernetes/cluster/gce/gci/master.yaml index 6d7d8e8e1..7a74113af 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/gci/master.yaml +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/master.yaml @@ -40,12 +40,12 @@ write_files: [Install] WantedBy=kubernetes.target - - path: /etc/systemd/system/kube-docker-monitor.service + - path: /etc/systemd/system/kube-container-runtime-monitor.service permissions: 0644 owner: root content: | [Unit] - Description=Kubernetes health monitoring for docker + Description=Kubernetes health monitoring for container runtime After=kube-master-configuration.service [Service] @@ -54,7 +54,7 @@ write_files: RemainAfterExit=yes RemainAfterExit=yes ExecStartPre=/bin/chmod 544 /home/kubernetes/bin/health-monitor.sh - ExecStart=/home/kubernetes/bin/health-monitor.sh docker + ExecStart=/home/kubernetes/bin/health-monitor.sh container-runtime [Install] WantedBy=kubernetes.target @@ -120,7 +120,7 @@ runcmd: - systemctl daemon-reload - systemctl enable kube-master-installation.service - systemctl enable kube-master-configuration.service - - systemctl enable kube-docker-monitor.service + - systemctl enable kube-container-runtime-monitor.service - systemctl enable kubelet-monitor.service - systemctl enable kube-logrotate.timer - systemctl enable kube-logrotate.service diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/mounter/stage-upload.sh b/vendor/k8s.io/kubernetes/cluster/gce/gci/mounter/stage-upload.sh index 66780da38..f3359447c 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/gci/mounter/stage-upload.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/mounter/stage-upload.sh @@ -23,12 +23,10 @@ set -o errexit set -o pipefail set -o nounset -RKT_VERSION="v1.18.0" DOCKER2ACI_VERSION="v0.13.0" MOUNTER_VERSION=$1 DOCKER_IMAGE=docker://$2 MOUNTER_ACI_IMAGE=gci-mounter-${MOUNTER_VERSION}.aci -RKT_GCS_DIR=gs://kubernetes-release/rkt/ MOUNTER_GCS_DIR=gs://kubernetes-release/gci-mounter/ TMPDIR=/tmp @@ -37,7 +35,6 @@ DOWNLOAD_DIR=$(mktemp --tmpdir=${TMPDIR} -d gci-mounter-build.XXXXXXXXXX) # Setup a staging directory STAGING_DIR=$(mktemp --tmpdir=${TMPDIR} -d gci-mounter-staging.XXXXXXXXXX) -RKT_DIR=${STAGING_DIR}/${RKT_VERSION} ACI_DIR=${STAGING_DIR}/gci-mounter CWD=${PWD} @@ -51,20 +48,8 @@ function cleanup { # Delete temporary directories on exit trap cleanup EXIT -mkdir ${RKT_DIR} mkdir ${ACI_DIR} -# Download rkt -cd ${DOWNLOAD_DIR} -echo "Downloading rkt ${RKT_VERSION}" -wget "https://github.com/coreos/rkt/releases/download/${RKT_VERSION}/rkt-${RKT_VERSION}.tar.gz" &> /dev/null -echo "Extracting rkt ${RKT_VERSION}" -tar xzf rkt-${RKT_VERSION}.tar.gz - -# Stage rkt into working directory -cp rkt-${RKT_VERSION}/rkt ${RKT_DIR}/rkt -cp rkt-${RKT_VERSION}/stage1-fly.aci ${RKT_DIR}/ - # Convert docker image to aci and stage it echo "Downloading docker2aci ${DOCKER2ACI_VERSION}" wget "https://github.com/appc/docker2aci/releases/download/${DOCKER2ACI_VERSION}/docker2aci-${DOCKER2ACI_VERSION}.tar.gz" &> /dev/null @@ -74,13 +59,9 @@ ACI_IMAGE=$(${DOWNLOAD_DIR}/docker2aci-${DOCKER2ACI_VERSION}/docker2aci ${DOCKER cp ${ACI_IMAGE} ${ACI_DIR}/${MOUNTER_ACI_IMAGE} # Upload the contents to gcs -echo "Uploading rkt artifacts in ${RKT_DIR} to ${RKT_GCS_DIR}" -gsutil cp -R ${RKT_DIR} ${RKT_GCS_DIR} echo "Uploading gci mounter ACI in ${ACI_DIR} to ${MOUNTER_GCS_DIR}" gsutil cp ${ACI_DIR}/${MOUNTER_ACI_IMAGE} ${MOUNTER_GCS_DIR} echo "Upload completed" -echo "Update rkt, stag1-fly.aci & gci-mounter ACI versions and SHA1 in cluster/gce/gci/configure.sh" -echo "${RKT_VERSION}/rkt sha1: $(sha1sum ${RKT_DIR}/rkt)" -echo "${RKT_VERSION}/stage1-fly.aci sha1: $(sha1sum ${RKT_DIR}/stage1-fly.aci)" +echo "Updated gci-mounter ACI version and SHA1 in cluster/gce/gci/configure.sh" echo "${MOUNTER_ACI_IMAGE} hash: $(sha1sum ${ACI_DIR}/${MOUNTER_ACI_IMAGE})" diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/node-helper.sh b/vendor/k8s.io/kubernetes/cluster/gce/gci/node-helper.sh index 33030d3f6..fd4ca7378 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/gci/node-helper.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/node-helper.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -20,6 +20,7 @@ source "${KUBE_ROOT}/cluster/gce/gci/helper.sh" function get-node-instance-metadata { local metadata="" metadata+="kube-env=${KUBE_TEMP}/node-kube-env.yaml," + metadata+="kubelet-config=${KUBE_TEMP}/node-kubelet-config.yaml," metadata+="user-data=${KUBE_ROOT}/cluster/gce/gci/node.yaml," metadata+="configure-sh=${KUBE_ROOT}/cluster/gce/gci/configure.sh," metadata+="cluster-location=${KUBE_TEMP}/cluster-location.txt," @@ -27,6 +28,7 @@ function get-node-instance-metadata { metadata+="gci-update-strategy=${KUBE_TEMP}/gci-update.txt," metadata+="gci-ensure-gke-docker=${KUBE_TEMP}/gci-ensure-gke-docker.txt," metadata+="gci-docker-version=${KUBE_TEMP}/gci-docker-version.txt," + metadata+="shutdown-script=${KUBE_ROOT}/cluster/gce/gci/shutdown.sh," metadata+="${NODE_EXTRA_METADATA}" echo "${metadata}" } diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/node.yaml b/vendor/k8s.io/kubernetes/cluster/gce/gci/node.yaml index e04018e34..fe73c05bd 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/gci/node.yaml +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/node.yaml @@ -40,12 +40,12 @@ write_files: [Install] WantedBy=kubernetes.target - - path: /etc/systemd/system/kube-docker-monitor.service + - path: /etc/systemd/system/kube-container-runtime-monitor.service permissions: 0644 owner: root content: | [Unit] - Description=Kubernetes health monitoring for docker + Description=Kubernetes health monitoring for container runtime After=kube-node-configuration.service [Service] @@ -54,7 +54,7 @@ write_files: RemainAfterExit=yes RemainAfterExit=yes ExecStartPre=/bin/chmod 544 /home/kubernetes/bin/health-monitor.sh - ExecStart=/home/kubernetes/bin/health-monitor.sh docker + ExecStart=/home/kubernetes/bin/health-monitor.sh container-runtime [Install] WantedBy=kubernetes.target @@ -120,7 +120,7 @@ runcmd: - systemctl daemon-reload - systemctl enable kube-node-installation.service - systemctl enable kube-node-configuration.service - - systemctl enable kube-docker-monitor.service + - systemctl enable kube-container-runtime-monitor.service - systemctl enable kubelet-monitor.service - systemctl enable kube-logrotate.timer - systemctl enable kube-logrotate.service diff --git a/vendor/k8s.io/kubernetes/cluster/gce/gci/shutdown.sh b/vendor/k8s.io/kubernetes/cluster/gce/gci/shutdown.sh new file mode 100755 index 000000000..dab0d34c6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/gce/gci/shutdown.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# 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. + +# A script that let's gci preemptible nodes gracefully terminate in the event of a VM shutdown. +preemptible=$(curl "http://metadata.google.internal/computeMetadata/v1/instance/scheduling/preemptible" -H "Metadata-Flavor: Google") +if [ ${preemptible} == "TRUE" ]; then + echo "Shutting down! Sleeping for a minute to let the node gracefully terminate" + # https://cloud.google.com/compute/docs/instances/stopping-or-deleting-an-instance#delete_timeout + sleep 30 +fi diff --git a/vendor/k8s.io/kubernetes/cluster/gce/list-resources.sh b/vendor/k8s.io/kubernetes/cluster/gce/list-resources.sh index a63be2c24..3e33075db 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/list-resources.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/list-resources.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -38,17 +38,18 @@ if [[ "${KUBERNETES_PROVIDER:-}" == "gke" ]]; then INSTANCE_PREFIX="${INSTANCE_PREFIX:0:26}" fi -# Usage: gcloud-compute-list +# Usage: gcloud-list # GREP_REGEX is applied to the output of gcloud if set GREP_REGEX="" -function gcloud-compute-list() { - local -r resource=$1 - local -r filter=${2:-} - echo -e "\n\n[ ${resource} ]" +function gcloud-list() { + local -r group=$1 + local -r resource=$2 + local -r filter=${3:-} + echo -e "\n\n[ ${group} ${resource} ]" local attempt=1 local result="" while true; do - if result=$(gcloud compute ${resource} list --project=${PROJECT} ${filter:+--filter="$filter"} ${@:3}); then + if result=$(gcloud ${group} ${resource} list --project=${PROJECT} ${filter:+--filter="$filter"} ${@:4}); then if [[ ! -z "${GREP_REGEX}" ]]; then result=$(echo "${result}" | grep "${GREP_REGEX}" || true) fi @@ -57,7 +58,7 @@ function gcloud-compute-list() { fi echo -e "Attempt ${attempt} failed to list ${resource}. Retrying." >&2 attempt=$(($attempt+1)) - if [[ ${attempt} > 5 ]]; then + if [[ ${attempt} -gt 5 ]]; then echo -e "List ${resource} failed!" >&2 exit 2 fi @@ -74,21 +75,23 @@ echo "Provider: ${KUBERNETES_PROVIDER:-}" # List resources related to instances, filtering by the instance prefix if # provided. -gcloud-compute-list instance-templates "name ~ '${INSTANCE_PREFIX}.*'" -gcloud-compute-list instance-groups "${ZONE:+"zone:(${ZONE}) AND "}name ~ '${INSTANCE_PREFIX}.*'" -gcloud-compute-list instances "${ZONE:+"zone:(${ZONE}) AND "}name ~ '${INSTANCE_PREFIX}.*'" +gcloud-list compute instance-templates "name ~ '${INSTANCE_PREFIX}.*'" +gcloud-list compute instance-groups "${ZONE:+"zone:(${ZONE}) AND "}name ~ '${INSTANCE_PREFIX}.*'" +gcloud-list compute instances "${ZONE:+"zone:(${ZONE}) AND "}name ~ '${INSTANCE_PREFIX}.*'" # List disk resources, filtering by instance prefix if provided. -gcloud-compute-list disks "${ZONE:+"zone:(${ZONE}) AND "}name ~ '${INSTANCE_PREFIX}.*'" +gcloud-list compute disks "${ZONE:+"zone:(${ZONE}) AND "}name ~ '${INSTANCE_PREFIX}.*'" # List network resources. We include names starting with "a", corresponding to # those that Kubernetes creates. -gcloud-compute-list addresses "${REGION:+"region=(${REGION}) AND "}name ~ 'a.*|${INSTANCE_PREFIX}.*'" +gcloud-list compute addresses "${REGION:+"region=(${REGION}) AND "}name ~ 'a.*|${INSTANCE_PREFIX}.*'" # Match either the header or a line with the specified e2e network. # This assumes that the network name is the second field in the output. GREP_REGEX="^NAME\|^[^ ]\+[ ]\+\(default\|${NETWORK}\) " -gcloud-compute-list routes "name ~ 'default.*|${INSTANCE_PREFIX}.*'" -gcloud-compute-list firewall-rules "name ~ 'default.*|k8s-fw.*|${INSTANCE_PREFIX}.*'" +gcloud-list compute routes "name ~ 'default.*|${INSTANCE_PREFIX}.*'" +gcloud-list compute firewall-rules "name ~ 'default.*|k8s-fw.*|${INSTANCE_PREFIX}.*'" GREP_REGEX="" -gcloud-compute-list forwarding-rules ${REGION:+"region=(${REGION})"} -gcloud-compute-list target-pools ${REGION:+"region=(${REGION})"} +gcloud-list compute forwarding-rules ${REGION:+"region=(${REGION})"} +gcloud-list compute target-pools ${REGION:+"region=(${REGION})"} + +gcloud-list logging sinks diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/BUILD b/vendor/k8s.io/kubernetes/cluster/gce/manifests/BUILD index 851e44bfc..7ae23d79a 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/BUILD +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/BUILD @@ -9,6 +9,7 @@ pkg_tar( mode = "0644", ) +# if you update this, also update function kube::release::package_kube_manifests_tarball() in build/lib/release.sh filegroup( name = "manifests", srcs = [ @@ -16,6 +17,7 @@ filegroup( "cluster-autoscaler.manifest", "e2e-image-puller.manifest", "etcd.manifest", + "etcd-empty-dir-cleanup.yaml", "glbc.manifest", "kms-plugin-container.manifest", "kube-addon-manager.yaml", @@ -24,7 +26,7 @@ filegroup( "kube-proxy.manifest", "kube-scheduler.manifest", "rescheduler.manifest", - ], + ] + glob(["internal-*"]), ) filegroup( diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/cluster-autoscaler.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/cluster-autoscaler.manifest index fc1b406ea..d6a514475 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/cluster-autoscaler.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/cluster-autoscaler.manifest @@ -7,6 +7,9 @@ "labels": { "tier": "cluster-management", "component": "cluster-autoscaler" + }, + "annotations": { + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" } }, "spec": { @@ -14,7 +17,7 @@ "containers": [ { "name": "cluster-autoscaler", - "image": "k8s.gcr.io/cluster-autoscaler:v1.2.2", + "image": "k8s.gcr.io/cluster-autoscaler:v1.3.1", "livenessProbe": { "httpGet": { "path": "/health-check", @@ -25,11 +28,12 @@ }, "command": [ "./run.sh", - "--kubernetes=http://127.0.0.1:8080?inClusterConfig=f", + "--kubernetes=https://127.0.0.1:443", "--v=4", "--logtostderr=true", "--write-status-configmap=true", "--balance-similar-node-groups=true", + "--expendable-pods-priority-cutoff=-10", "{{params}}" ], "env": [ @@ -56,6 +60,11 @@ "readOnly": true, "mountPath": "/usr/share/ca-certificates" }, + { + "name": "srvkube", + "readOnly": true, + "mountPath": "/etc/srv/kubernetes/cluster-autoscaler" + }, { "name": "logfile", "mountPath": "/var/log/cluster-autoscaler.log", @@ -80,6 +89,12 @@ "path": "/usr/share/ca-certificates" } }, + { + "name": "srvkube", + "hostPath": { + "path": "/etc/srv/kubernetes/cluster-autoscaler" + } + }, { "name": "logfile", "hostPath": { diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/e2e-image-puller.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/e2e-image-puller.manifest index 035155825..6d3ba6fb8 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/e2e-image-puller.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/e2e-image-puller.manifest @@ -34,7 +34,7 @@ spec: k8s.gcr.io/busybox:1.24 k8s.gcr.io/dnsutils:e2e k8s.gcr.io/e2e-net-amd64:1.0 - k8s.gcr.io/echoserver:1.6 + k8s.gcr.io/echoserver:1.10 k8s.gcr.io/eptest:0.1 k8s.gcr.io/fakegitserver:0.1 k8s.gcr.io/galera-install:0.1 @@ -69,21 +69,23 @@ spec: k8s.gcr.io/test-webserver:e2e k8s.gcr.io/update-demo:kitten k8s.gcr.io/update-demo:nautilus - k8s.gcr.io/volume-ceph:0.1 - k8s.gcr.io/volume-gluster:0.2 - k8s.gcr.io/volume-iscsi:0.1 - k8s.gcr.io/volume-nfs:0.8 - k8s.gcr.io/volume-rbd:0.1 + gcr.io/kubernetes-e2e-test-images/volume-ceph:0.1 + gcr.io/kubernetes-e2e-test-images/volume-gluster:0.2 + gcr.io/kubernetes-e2e-test-images/volume-iscsi:0.1 + gcr.io/kubernetes-e2e-test-images/volume-nfs:0.8 + gcr.io/kubernetes-e2e-test-images/volume-rbd:0.1 k8s.gcr.io/zookeeper-install-3.5.0-alpha:e2e gcr.io/google_samples/gb-redisslave:nonexistent - ; do echo $(date '+%X') pulling $i; docker pull $i 1>/dev/null; done; exit 0; + ; do echo $(date '+%X') pulling $i; crictl pull $i 1>/dev/null; done; exit 0; securityContext: privileged: true volumeMounts: - - mountPath: /var/run/docker.sock + - mountPath: {{ container_runtime_endpoint }} name: socket - - mountPath: /usr/bin/docker - name: docker + - mountPath: /usr/bin/crictl + name: crictl + - mountPath: /etc/crictl.yaml + name: config # Add a container that runs a health-check - name: nethealth-check resources: @@ -98,13 +100,17 @@ spec: - "/usr/bin/nethealth || true" volumes: - hostPath: - path: /var/run/docker.sock + path: {{ container_runtime_endpoint }} type: Socket name: socket - hostPath: - path: /usr/bin/docker + path: /home/kubernetes/bin/crictl type: File - name: docker + name: crictl + - hostPath: + path: /etc/crictl.yaml + type: File + name: config # This pod is really fire-and-forget. restartPolicy: OnFailure # This pod needs hostNetworking for true VM perf measurement as well as avoiding cbr0 issues diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/etcd-empty-dir-cleanup.yaml b/vendor/k8s.io/kubernetes/cluster/gce/manifests/etcd-empty-dir-cleanup.yaml new file mode 100644 index 000000000..9b92d6f40 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/etcd-empty-dir-cleanup.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: etcd-empty-dir-cleanup + namespace: kube-system + annotations: + scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' + labels: + k8s-app: etcd-empty-dir-cleanup +spec: + priorityClassName: system-node-critical + hostNetwork: true + dnsPolicy: Default + containers: + - name: etcd-empty-dir-cleanup + image: k8s.gcr.io/etcd-empty-dir-cleanup:3.2.18.0 diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/etcd.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/etcd.manifest index 3abe65689..7413603f7 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/etcd.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/etcd.manifest @@ -5,7 +5,8 @@ "name":"etcd-server{{ suffix }}", "namespace": "kube-system", "annotations": { - "scheduler.alpha.kubernetes.io/critical-pod": "" + "scheduler.alpha.kubernetes.io/critical-pod": "", + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" } }, "spec":{ @@ -13,7 +14,7 @@ "containers":[ { "name": "etcd-container", - "image": "{{ pillar.get('etcd_docker_repository', 'k8s.gcr.io/etcd') }}:{{ pillar.get('etcd_docker_tag', '3.1.12') }}", + "image": "{{ pillar.get('etcd_docker_repository', 'k8s.gcr.io/etcd') }}:{{ pillar.get('etcd_docker_tag', '3.2.18-0') }}", "resources": { "requests": { "cpu": {{ cpulimit }} @@ -29,7 +30,7 @@ "value": "{{ pillar.get('storage_backend', 'etcd3') }}" }, { "name": "TARGET_VERSION", - "value": "{{ pillar.get('etcd_version', '3.1.12') }}" + "value": "{{ pillar.get('etcd_version', '3.2.18') }}" }, { "name": "DATA_DIRECTORY", "value": "/var/etcd/data{{ suffix }}" @@ -45,6 +46,9 @@ }, { "name": "ETCD_CREDS", "value": "{{ etcd_creds }}" + }, + { "name": "ETCD_SNAPSHOT_COUNT", + "value": "10000" } ], "livenessProbe": { @@ -59,7 +63,7 @@ "ports": [ { "name": "serverport", "containerPort": {{ server_port }}, - "hostPort": {{ server_port }} + "hostPort": {{ server_port }} }, { "name": "clientport", "containerPort": {{ port }}, diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/glbc.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/glbc.manifest index 2c80aa0ca..4401ab0d1 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/glbc.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/glbc.manifest @@ -5,6 +5,7 @@ metadata: namespace: kube-system annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' labels: k8s-app: gcp-lb-controller version: v1.1.1 diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kms-plugin-container.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kms-plugin-container.manifest index 6cae73b05..cb90c9fef 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kms-plugin-container.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kms-plugin-container.manifest @@ -5,4 +5,4 @@ "livenessProbe": { "httpGet": {"host": "127.0.0.1", "port": 8081, "path": "/healthz"}, "initialDelaySeconds": 3, "timeoutSeconds": 3}, "ports":[{ "name": "healthz", "containerPort": 8081, "hostPort": 8081}, { "name": "metrics", "containerPort": 8082, "hostPort": 8082}], "volumeMounts": [{{cloud_config_mount}}, {{kms_socket_mount}}] -} +} \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-addon-manager.yaml b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-addon-manager.yaml index c77e914e6..48a3b1519 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-addon-manager.yaml +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-addon-manager.yaml @@ -5,6 +5,7 @@ metadata: namespace: kube-system annotations: scheduler.alpha.kubernetes.io/critical-pod: '' + seccomp.security.alpha.kubernetes.io/pod: 'docker/default' labels: component: kube-addon-manager spec: diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-apiserver.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-apiserver.manifest index 4db9f470c..6b9f6bb58 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-apiserver.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-apiserver.manifest @@ -5,7 +5,8 @@ "name":"kube-apiserver", "namespace": "kube-system", "annotations": { - "scheduler.alpha.kubernetes.io/critical-pod": "" + "scheduler.alpha.kubernetes.io/critical-pod": "", + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" }, "labels": { "tier": "control-plane", @@ -138,4 +139,4 @@ "path": "{{srv_sshproxy_path}}"} } ] -}} \ No newline at end of file +}} diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-controller-manager.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-controller-manager.manifest index 353958642..1bd5d2d4a 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-controller-manager.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-controller-manager.manifest @@ -5,7 +5,8 @@ "name":"kube-controller-manager", "namespace": "kube-system", "annotations": { - "scheduler.alpha.kubernetes.io/critical-pod": "" + "scheduler.alpha.kubernetes.io/critical-pod": "", + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" }, "labels": { "tier": "control-plane", diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-proxy.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-proxy.manifest index fe4dd6c61..334150f68 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-proxy.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-proxy.manifest @@ -14,7 +14,7 @@ metadata: tier: node component: kube-proxy spec: - {{pod_priority}} + priorityClassName: system-node-critical hostNetwork: true tolerations: - operator: "Exists" diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-scheduler.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-scheduler.manifest index a7d496fdd..af71c049f 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-scheduler.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/kube-scheduler.manifest @@ -5,7 +5,8 @@ "name":"kube-scheduler", "namespace": "kube-system", "annotations": { - "scheduler.alpha.kubernetes.io/critical-pod": "" + "scheduler.alpha.kubernetes.io/critical-pod": "", + "seccomp.security.alpha.kubernetes.io/pod": "docker/default" }, "labels": { "tier": "control-plane", diff --git a/vendor/k8s.io/kubernetes/cluster/gce/manifests/rescheduler.manifest b/vendor/k8s.io/kubernetes/cluster/gce/manifests/rescheduler.manifest index b496449a7..6bbd4fa88 100644 --- a/vendor/k8s.io/kubernetes/cluster/gce/manifests/rescheduler.manifest +++ b/vendor/k8s.io/kubernetes/cluster/gce/manifests/rescheduler.manifest @@ -1,19 +1,19 @@ apiVersion: v1 kind: Pod metadata: - name: rescheduler-v0.3.1 + name: rescheduler-v0.4.0 namespace: kube-system annotations: scheduler.alpha.kubernetes.io/critical-pod: '' labels: k8s-app: rescheduler - version: v0.3.1 + version: v0.4.0 kubernetes.io/cluster-service: "true" kubernetes.io/name: "Rescheduler" spec: hostNetwork: true containers: - - image: k8s.gcr.io/rescheduler:v0.3.1 + - image: k8s.gcr.io/rescheduler:v0.4.0 name: rescheduler volumeMounts: - mountPath: /var/log/rescheduler.log diff --git a/vendor/k8s.io/kubernetes/cluster/gce/upgrade-aliases.sh b/vendor/k8s.io/kubernetes/cluster/gce/upgrade-aliases.sh index 29dbf0232..cc6fcb0ae 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/upgrade-aliases.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/upgrade-aliases.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Kubernetes Authors. # @@ -53,7 +53,7 @@ function detect-k8s-subnetwork() { local subnetwork_url=$(gcloud compute instances describe \ ${KUBE_MASTER} --project=${PROJECT} --zone=${ZONE} \ --format='value(networkInterfaces[0].subnetwork)') - if [ -n ${subnetwork_url} ]; then + if [[ -n ${subnetwork_url} ]]; then IP_ALIAS_SUBNETWORK=$(echo ${subnetwork_url##*/}) fi } @@ -161,8 +161,8 @@ export KUBE_GCE_ENABLE_IP_ALIASES=true export SECONDARY_RANGE_NAME="pods-default" export STORAGE_BACKEND="etcd3" export STORAGE_MEDIA_TYPE="application/vnd.kubernetes.protobuf" -export ETCD_IMAGE=3.1.12 -export ETCD_VERSION=3.1.12 +export ETCD_IMAGE=3.2.18-0 +export ETCD_VERSION=3.2.18 # Upgrade master with updated kube envs ${KUBE_ROOT}/cluster/gce/upgrade.sh -M -l diff --git a/vendor/k8s.io/kubernetes/cluster/gce/upgrade.sh b/vendor/k8s.io/kubernetes/cluster/gce/upgrade.sh index d928fe2be..ad311e455 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/upgrade.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/upgrade.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -291,18 +291,17 @@ function upgrade-node-env() { # Note: This is called multiple times from do-node-upgrade() in parallel, so should be thread-safe. function do-single-node-upgrade() { local -r instance="$1" - instance_id=$(gcloud compute instances describe "${instance}" \ - --format='get(id)' \ - --project="${PROJECT}" \ - --zone="${ZONE}" 2>&1) && describe_rc=$? || describe_rc=$? - if [[ "${describe_rc}" != 0 ]]; then - echo "== FAILED to describe ${instance} ==" - echo "${instance_id}" - return ${describe_rc} + local kubectl_rc + local boot_id=$("${KUBE_ROOT}/cluster/kubectl.sh" get node "${instance}" --output=jsonpath='{.status.nodeInfo.bootID}' 2>&1) && kubectl_rc=$? || kubectl_rc=$? + if [[ "${kubectl_rc}" != 0 ]]; then + echo "== FAILED to get bootID ${instance} ==" + echo "${boot_id}" + return ${kubectl_rc} fi # Drain node echo "== Draining ${instance}. == " >&2 + local drain_rc "${KUBE_ROOT}/cluster/kubectl.sh" drain --delete-local-data --force --ignore-daemonsets "${instance}" \ && drain_rc=$? || drain_rc=$? if [[ "${drain_rc}" != 0 ]]; then @@ -312,7 +311,8 @@ function do-single-node-upgrade() { # Recreate instance echo "== Recreating instance ${instance}. ==" >&2 - recreate=$(gcloud compute instance-groups managed recreate-instances "${group}" \ + local recreate_rc + local recreate=$(gcloud compute instance-groups managed recreate-instances "${group}" \ --project="${PROJECT}" \ --zone="${ZONE}" \ --instances="${instance}" 2>&1) && recreate_rc=$? || recreate_rc=$? @@ -322,55 +322,31 @@ function do-single-node-upgrade() { return ${recreate_rc} fi - # Wait for instance to be recreated - echo "== Waiting for instance ${instance} to be recreated. ==" >&2 - while true; do - new_instance_id=$(gcloud compute instances describe "${instance}" \ - --format='get(id)' \ - --project="${PROJECT}" \ - --zone="${ZONE}" 2>&1) && describe_rc=$? || describe_rc=$? - if [[ "${describe_rc}" != 0 ]]; then - echo "== FAILED to describe ${instance} ==" - echo "${new_instance_id}" - echo " (Will retry.)" - elif [[ "${new_instance_id}" == "${instance_id}" ]]; then - echo -n . - else - echo "Instance ${instance} recreated." - break - fi - sleep 1 - done - - # Wait for k8s node object to reflect new instance id + # Wait for node status to reflect a new boot ID. This guarantees us + # that the node status in the API is from a different boot. This + # does not guarantee that the status is from the upgraded node, but + # it is a best effort approximation. echo "== Waiting for new node to be added to k8s. ==" >&2 while true; do - external_id=$("${KUBE_ROOT}/cluster/kubectl.sh" get node "${instance}" --output=jsonpath='{.spec.externalID}' 2>&1) && kubectl_rc=$? || kubectl_rc=$? + local new_boot_id=$("${KUBE_ROOT}/cluster/kubectl.sh" get node "${instance}" --output=jsonpath='{.status.nodeInfo.bootID}' 2>&1) && kubectl_rc=$? || kubectl_rc=$? if [[ "${kubectl_rc}" != 0 ]]; then echo "== FAILED to get node ${instance} ==" - echo "${external_id}" + echo "${boot_id}" echo " (Will retry.)" - elif [[ "${external_id}" == "${new_instance_id}" ]]; then + elif [[ "${boot_id}" != "${new_boot_id}" ]]; then echo "Node ${instance} recreated." break - elif [[ "${external_id}" == "${instance_id}" ]]; then - echo -n . else - echo "Unexpected external_id '${external_id}' matches neither old ('${instance_id}') nor new ('${new_instance_id}')." - echo " (Will retry.)" + echo -n . fi sleep 1 done - # Wait for the node to not have SchedulingDisabled=True and also to have - # Ready=True. + # Wait for the node to have Ready=True. echo "== Waiting for ${instance} to become ready. ==" >&2 while true; do - cordoned=$("${KUBE_ROOT}/cluster/kubectl.sh" get node "${instance}" --output='jsonpath={.status.conditions[?(@.type == "SchedulingDisabled")].status}') - ready=$("${KUBE_ROOT}/cluster/kubectl.sh" get node "${instance}" --output='jsonpath={.status.conditions[?(@.type == "Ready")].status}') - if [[ "${cordoned}" == 'True' ]]; then - echo "Node ${instance} is still not ready: SchedulingDisabled=${ready}" - elif [[ "${ready}" != 'True' ]]; then + local ready=$("${KUBE_ROOT}/cluster/kubectl.sh" get node "${instance}" --output='jsonpath={.status.conditions[?(@.type == "Ready")].status}') + if [[ "${ready}" != 'True' ]]; then echo "Node ${instance} is still not ready: Ready=${ready}" else echo "Node ${instance} Ready=${ready}" @@ -378,6 +354,16 @@ function do-single-node-upgrade() { fi sleep 1 done + + # Uncordon the node. + echo "== Uncordon ${instance}. == " >&2 + local uncordon_rc + "${KUBE_ROOT}/cluster/kubectl.sh" uncordon "${instance}" \ + && uncordon_rc=$? || uncordon_rc=$? + if [[ "${uncordon_rc}" != 0 ]]; then + echo "== FAILED to uncordon ${instance} ==" + return ${uncordon_rc} + fi } # Prereqs: diff --git a/vendor/k8s.io/kubernetes/cluster/gce/util.sh b/vendor/k8s.io/kubernetes/cluster/gce/util.sh index 937c4e830..fd446852b 100755 --- a/vendor/k8s.io/kubernetes/cluster/gce/util.sh +++ b/vendor/k8s.io/kubernetes/cluster/gce/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -502,6 +502,7 @@ function write-master-env { construct-kubelet-flags true build-kube-env true "${KUBE_TEMP}/master-kube-env.yaml" + build-kubelet-config true "${KUBE_TEMP}/master-kubelet-config.yaml" build-kube-master-certs "${KUBE_TEMP}/kube-master-certs.yaml" } @@ -512,6 +513,7 @@ function write-node-env { construct-kubelet-flags false build-kube-env false "${KUBE_TEMP}/node-kube-env.yaml" + build-kubelet-config false "${KUBE_TEMP}/node-kubelet-config.yaml" } function build-node-labels { @@ -531,53 +533,116 @@ function build-node-labels { echo $node_labels } +# yaml-map-string-stringarray converts the encoded structure to yaml format, and echoes the result +# under the provided name. If the encoded structure is empty, echoes nothing. +# 1: name to be output in yaml +# 2: encoded map-string-string (which may contain duplicate keys - resulting in map-string-stringarray) +# 3: key-value separator (defaults to ':') +# 4: item separator (defaults to ',') +function yaml-map-string-stringarray { + declare -r name="${1}" + declare -r encoded="${2}" + declare -r kv_sep="${3:-:}" + declare -r item_sep="${4:-,}" + + declare -a pairs # indexed array + declare -A map # associative array + IFS="${item_sep}" read -ra pairs <<<"${encoded}" # split on item_sep + for pair in "${pairs[@]}"; do + declare key + declare value + IFS="${kv_sep}" read -r key value <<<"${pair}" # split on kv_sep + map[$key]="${map[$key]+${map[$key]}${item_sep}}${value}" # append values from duplicate keys + done + # only output if there is a non-empty map + if [[ ${#map[@]} -gt 0 ]]; then + echo "${name}:" + for k in "${!map[@]}"; do + echo " ${k}:" + declare -a values + IFS="${item_sep}" read -ra values <<<"${map[$k]}" + for val in "${values[@]}"; do + # declare across two lines so errexit can catch failures + declare v + v=$(yaml-quote "${val}") + echo " - ${v}" + done + done + fi +} + +# yaml-map-string-string converts the encoded structure to yaml format, and echoes the result +# under the provided name. If the encoded structure is empty, echoes nothing. +# 1: name to be output in yaml +# 2: encoded map-string-string (no duplicate keys) +# 3: bool, whether to yaml-quote the value string in the output (defaults to true) +# 4: key-value separator (defaults to ':') +# 5: item separator (defaults to ',') +function yaml-map-string-string { + declare -r name="${1}" + declare -r encoded="${2}" + declare -r quote_val_string="${3:-true}" + declare -r kv_sep="${4:-:}" + declare -r item_sep="${5:-,}" + + declare -a pairs # indexed array + declare -A map # associative array + IFS="${item_sep}" read -ra pairs <<<"${encoded}" # split on item_sep # TODO(mtaufen): try quoting this too + for pair in "${pairs[@]}"; do + declare key + declare value + IFS="${kv_sep}" read -r key value <<<"${pair}" # split on kv_sep + map[$key]="${value}" # add to associative array + done + # only output if there is a non-empty map + if [[ ${#map[@]} -gt 0 ]]; then + echo "${name}:" + for k in "${!map[@]}"; do + if [[ "${quote_val_string}" == "true" ]]; then + # declare across two lines so errexit can catch failures + declare v + v=$(yaml-quote "${map[$k]}") + echo " ${k}: ${v}" + else + echo " ${k}: ${map[$k]}" + fi + done + fi +} + # $1: if 'true', we're rendering flags for a master, else a node function construct-kubelet-flags { local master=$1 local flags="${KUBELET_TEST_LOG_LEVEL:-"--v=2"} ${KUBELET_TEST_ARGS:-}" flags+=" --allow-privileged=true" - flags+=" --cgroup-root=/" flags+=" --cloud-provider=gce" - flags+=" --cluster-dns=${DNS_SERVER_IP}" - flags+=" --cluster-domain=${DNS_DOMAIN}" - flags+=" --pod-manifest-path=/etc/kubernetes/manifests" # Keep in sync with CONTAINERIZED_MOUNTER_HOME in configure-helper.sh flags+=" --experimental-mounter-path=/home/kubernetes/containerized_mounter/mounter" flags+=" --experimental-check-node-capabilities-before-mount=true" # Keep in sync with the mkdir command in configure-helper.sh (until the TODO is resolved) flags+=" --cert-dir=/var/lib/kubelet/pki/" + # Configure the directory that the Kubelet should use to store dynamic config checkpoints + flags+=" --dynamic-config-dir=/var/lib/kubelet/dynamic-config" + if [[ "${master}" == "true" ]]; then flags+=" ${MASTER_KUBELET_TEST_ARGS:-}" - flags+=" --enable-debugging-handlers=false" - flags+=" --hairpin-mode=none" if [[ "${REGISTER_MASTER_KUBELET:-false}" == "true" ]]; then #TODO(mikedanese): allow static pods to start before creating a client #flags+=" --bootstrap-kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig" #flags+=" --kubeconfig=/var/lib/kubelet/kubeconfig" flags+=" --kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig" flags+=" --register-schedulable=false" - else - # Note: Standalone mode is used by GKE - flags+=" --pod-cidr=${MASTER_IP_RANGE}" fi else # For nodes flags+=" ${NODE_KUBELET_TEST_ARGS:-}" - flags+=" --enable-debugging-handlers=true" flags+=" --bootstrap-kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig" flags+=" --kubeconfig=/var/lib/kubelet/kubeconfig" - if [[ "${HAIRPIN_MODE:-}" == "promiscuous-bridge" ]] || \ - [[ "${HAIRPIN_MODE:-}" == "hairpin-veth" ]] || \ - [[ "${HAIRPIN_MODE:-}" == "none" ]]; then - flags+=" --hairpin-mode=${HAIRPIN_MODE}" - fi - # Keep client-ca-file in sync with CA_CERT_BUNDLE_PATH in configure-helper.sh - flags+=" --anonymous-auth=false --authorization-mode=Webhook --client-ca-file=/etc/srv/kubernetes/pki/ca-certificates.crt" fi # Network plugin if [[ -n "${NETWORK_PROVIDER:-}" || -n "${NETWORK_POLICY_PROVIDER:-}" ]]; then flags+=" --cni-bin-dir=/home/kubernetes/bin" - if [[ "${NETWORK_POLICY_PROVIDER:-}" == "calico" ]]; then + if [[ "${NETWORK_POLICY_PROVIDER:-}" == "calico" || "${ENABLE_NETD:-}" == "true" ]]; then # Calico uses CNI always. # Note that network policy won't work for master node. if [[ "${master}" == "true" ]]; then @@ -588,20 +653,13 @@ function construct-kubelet-flags { else # Otherwise use the configured value. flags+=" --network-plugin=${NETWORK_PROVIDER}" + fi fi if [[ -n "${NON_MASQUERADE_CIDR:-}" ]]; then flags+=" --non-masquerade-cidr=${NON_MASQUERADE_CIDR}" fi flags+=" --volume-plugin-dir=${VOLUME_PLUGIN_DIR}" - # Note: ENABLE_MANIFEST_URL is used by GKE - if [[ "${ENABLE_MANIFEST_URL:-}" == "true" ]]; then - flags+=" --manifest-url=${MANIFEST_URL}" - flags+=" --manifest-url-header=${MANIFEST_URL_HEADER}" - fi - if [[ -n "${ENABLE_CUSTOM_METRICS:-}" ]]; then - flags+=" --enable-custom-metrics=${ENABLE_CUSTOM_METRICS}" - fi local node_labels=$(build-node-labels ${master}) if [[ -n "${node_labels:-}" ]]; then flags+=" --node-labels=${node_labels}" @@ -609,12 +667,6 @@ function construct-kubelet-flags { if [[ -n "${NODE_TAINTS:-}" ]]; then flags+=" --register-with-taints=${NODE_TAINTS}" fi - if [[ -n "${EVICTION_HARD:-}" ]]; then - flags+=" --eviction-hard=${EVICTION_HARD}" - fi - if [[ -n "${FEATURE_GATES:-}" ]]; then - flags+=" --feature-gates=${FEATURE_GATES}" - fi # TODO(mtaufen): ROTATE_CERTIFICATES seems unused; delete it? if [[ -n "${ROTATE_CERTIFICATES:-}" ]]; then flags+=" --rotate-certificates=true" @@ -622,7 +674,6 @@ function construct-kubelet-flags { if [[ -n "${CONTAINER_RUNTIME:-}" ]]; then flags+=" --container-runtime=${CONTAINER_RUNTIME}" fi - # TODO(mtaufen): CONTAINER_RUNTIME_ENDPOINT seems unused; delete it? if [[ -n "${CONTAINER_RUNTIME_ENDPOINT:-}" ]]; then flags+=" --container-runtime-endpoint=${CONTAINER_RUNTIME_ENDPOINT}" fi @@ -633,6 +684,91 @@ function construct-kubelet-flags { KUBELET_ARGS="${flags}" } +# $1: if 'true', we're rendering config for a master, else a node +function build-kubelet-config { + local master=$1 + local file=$2 + + rm -f "${file}" + { + declare quoted_dns_server_ip + declare quoted_dns_domain + quoted_dns_server_ip=$(yaml-quote "${DNS_SERVER_IP}") + quoted_dns_domain=$(yaml-quote "${DNS_DOMAIN}") + cat <>$file <-". +IMAGE_TAG=$(LATEST_ETCD_VERSION)-$(REVISION) + ARCH?=amd64 # Image should be pulled from k8s.gcr.io, which will auto-detect # region (us, eu, asia, ...) and pull from the closest. REGISTRY?=k8s.gcr.io # Images should be pushed to staging-k8s.gcr.io. PUSH_REGISTRY?=staging-k8s.gcr.io -# golang version should match the golang version from https://github.com/coreos/etcd/releases for REGISTRY_TAG version of etcd. -GOLANG_VERSION?=1.8.5 +# golang version should match the golang version from https://github.com/coreos/etcd/releases for the current ETCD_VERSION. +GOLANG_VERSION?=1.8.7 GOARM=7 TEMP_DIR:=$(shell mktemp -d) @@ -62,40 +71,37 @@ build: # without copying the subdirectories. find ./ -maxdepth 1 -type f | xargs -I {} cp {} $(TEMP_DIR) - # Compile attachlease - docker run --interactive -v $(shell pwd)/../../../:/go/src/k8s.io/kubernetes -v $(TEMP_DIR):/build -e GOARCH=$(ARCH) golang:$(GOLANG_VERSION) \ - /bin/bash -c "CGO_ENABLED=0 go build -o /build/attachlease k8s.io/kubernetes/cluster/images/etcd/attachlease" - # Compile rollback + # Compile migrate docker run --interactive -v $(shell pwd)/../../../:/go/src/k8s.io/kubernetes -v $(TEMP_DIR):/build -e GOARCH=$(ARCH) golang:$(GOLANG_VERSION) \ - /bin/bash -c "CGO_ENABLED=0 go build -o /build/rollback k8s.io/kubernetes/cluster/images/etcd/rollback" + /bin/bash -c "CGO_ENABLED=0 go build -o /build/migrate k8s.io/kubernetes/cluster/images/etcd/migrate" ifeq ($(ARCH),amd64) # Do not compile if we should make an image for amd64, use the official etcd binaries instead # For each release create a tmp dir 'etcd_release_tmp_dir' and unpack the release tar there. - for tag in $(TAGS); do \ + for version in $(BUNDLED_ETCD_VERSIONS); do \ etcd_release_tmp_dir=$(shell mktemp -d); \ - curl -sSL --retry 5 https://github.com/coreos/etcd/releases/download/v$$tag/etcd-v$$tag-linux-amd64.tar.gz | tar -xz -C $$etcd_release_tmp_dir --strip-components=1; \ + curl -sSL --retry 5 https://github.com/coreos/etcd/releases/download/v$$version/etcd-v$$version-linux-amd64.tar.gz | tar -xz -C $$etcd_release_tmp_dir --strip-components=1; \ cp $$etcd_release_tmp_dir/etcd $$etcd_release_tmp_dir/etcdctl $(TEMP_DIR)/; \ - cp $(TEMP_DIR)/etcd $(TEMP_DIR)/etcd-$$tag; \ - cp $(TEMP_DIR)/etcdctl $(TEMP_DIR)/etcdctl-$$tag; \ + cp $(TEMP_DIR)/etcd $(TEMP_DIR)/etcd-$$version; \ + cp $(TEMP_DIR)/etcdctl $(TEMP_DIR)/etcdctl-$$version; \ done else # Download etcd in a golang container and cross-compile it statically # For each release create a tmp dir 'etcd_release_tmp_dir' and unpack the release tar there. - for tag in $(TAGS); do \ + for version in $(BUNDLED_ETCD_VERSIONS); do \ etcd_release_tmp_dir=$(shell mktemp -d); \ docker run --interactive -v $${etcd_release_tmp_dir}:/etcdbin golang:$(GOLANG_VERSION) /bin/bash -c \ "git clone https://github.com/coreos/etcd /go/src/github.com/coreos/etcd \ && cd /go/src/github.com/coreos/etcd \ - && git checkout v$${tag} \ + && git checkout v$${version} \ && GOARM=$(GOARM) GOARCH=$(ARCH) ./build \ && cp -f bin/$(ARCH)/etcd* bin/etcd* /etcdbin; echo 'done'"; \ cp $$etcd_release_tmp_dir/etcd $$etcd_release_tmp_dir/etcdctl $(TEMP_DIR)/; \ - cp $(TEMP_DIR)/etcd $(TEMP_DIR)/etcd-$$tag; \ - cp $(TEMP_DIR)/etcdctl $(TEMP_DIR)/etcdctl-$$tag; \ + cp $(TEMP_DIR)/etcd $(TEMP_DIR)/etcd-$$version; \ + cp $(TEMP_DIR)/etcdctl $(TEMP_DIR)/etcdctl-$$version; \ done # Add this ENV variable in order to workaround an unsupported arch blocker @@ -109,139 +115,36 @@ endif cd $(TEMP_DIR) && sed -i.bak 's|BASEIMAGE|$(BASEIMAGE)|g' Dockerfile # And build the image - docker build --pull -t $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) $(TEMP_DIR) + docker build --pull -t $(REGISTRY)/etcd-$(ARCH):$(IMAGE_TAG) $(TEMP_DIR) push: build - docker tag $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) $(PUSH_REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) - docker push $(PUSH_REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) + docker tag $(REGISTRY)/etcd-$(ARCH):$(IMAGE_TAG) $(PUSH_REGISTRY)/etcd-$(ARCH):$(IMAGE_TAG) + docker push $(PUSH_REGISTRY)/etcd-$(ARCH):$(IMAGE_TAG) ifeq ($(ARCH),amd64) # Backward compatibility. TODO: deprecate this image tag - docker tag $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) $(REGISTRY)/etcd:$(REGISTRY_TAG) - docker push $(REGISTRY)/etcd:$(REGISTRY_TAG) + docker tag $(REGISTRY)/etcd-$(ARCH):$(IMAGE_TAG) $(PUSH_REGISTRY)/etcd:$(IMAGE_TAG) + docker push $(PUSH_REGISTRY)/etcd:$(IMAGE_TAG) endif -ETCD2_ROLLBACK_NEW_TAG=3.0.17 -ETCD2_ROLLBACK_OLD_TAG=2.2.1 - -# Test a rollback to etcd2 from the earliest etcd3 version. -test-rollback-etcd2: - mkdir -p $(TEMP_DIR)/rollback-etcd2 - cd $(TEMP_DIR)/rollback-etcd2 - - @echo "Starting $(ETCD2_ROLLBACK_NEW_TAG) etcd and writing some sample data." - docker run --tty --interactive -v $(TEMP_DIR)/rollback-etcd2:/var/etcd \ - -e "TARGET_STORAGE=etcd3" \ - -e "TARGET_VERSION=$(ETCD2_ROLLBACK_NEW_TAG)" \ - -e "DATA_DIRECTORY=/var/etcd/data" \ - $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) /bin/sh -c \ - 'INITIAL_CLUSTER=etcd-$$(hostname)=http://localhost:2380 \ - /usr/local/bin/migrate-if-needed.sh && \ - source /usr/local/bin/start-stop-etcd.sh && \ - START_STORAGE=etcd3 START_VERSION=$(ETCD2_ROLLBACK_NEW_TAG) start_etcd && \ - ETCDCTL_API=3 /usr/local/bin/etcdctl-$(ETCD2_ROLLBACK_NEW_TAG) --endpoints http://127.0.0.1:$${ETCD_PORT} put /registry/k1 value1 && \ - stop_etcd && \ - [ $$(cat /var/etcd/data/version.txt) = $(ETCD2_ROLLBACK_NEW_TAG)/etcd3 ]' - - @echo "Rolling back to the previous version of etcd and recording keyspace to a flat file." - docker run --tty --interactive -v $(TEMP_DIR)/rollback-etcd2:/var/etcd \ - -e "TARGET_STORAGE=etcd2" \ - -e "TARGET_VERSION=$(ETCD2_ROLLBACK_OLD_TAG)" \ - -e "DATA_DIRECTORY=/var/etcd/data" \ - $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) /bin/sh -c \ - 'INITIAL_CLUSTER=etcd-$$(hostname)=http://localhost:2380 \ - /usr/local/bin/migrate-if-needed.sh && \ - source /usr/local/bin/start-stop-etcd.sh && \ - START_STORAGE=etcd2 START_VERSION=$(ETCD2_ROLLBACK_OLD_TAG) start_etcd && \ - /usr/local/bin/etcdctl-$(ETCD2_ROLLBACK_OLD_TAG) --endpoint 127.0.0.1:$${ETCD_PORT} get /registry/k1 > /var/etcd/keyspace.txt && \ - stop_etcd' - - @echo "Checking if rollback successfully downgraded etcd to $(ETCD2_ROLLBACK_OLD_TAG)" - docker run --tty --interactive -v $(TEMP_DIR)/rollback-etcd2:/var/etcd \ - $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) /bin/sh -c \ - '[ $$(cat /var/etcd/data/version.txt) = $(ETCD2_ROLLBACK_OLD_TAG)/etcd2 ] && \ - grep -q value1 /var/etcd/keyspace.txt' - -# Test a rollback from the latest version to the previous version. -test-rollback: - mkdir -p $(TEMP_DIR)/rollback-test - cd $(TEMP_DIR)/rollback-test - - @echo "Starting $(REGISTRY_TAG) etcd and writing some sample data." - docker run --tty --interactive -v $(TEMP_DIR)/rollback-test:/var/etcd \ - -e "TARGET_STORAGE=etcd3" \ - -e "TARGET_VERSION=$(REGISTRY_TAG)" \ - -e "DATA_DIRECTORY=/var/etcd/data" \ - $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) /bin/sh -c \ - 'INITIAL_CLUSTER=etcd-$$(hostname)=http://localhost:2380 \ - /usr/local/bin/migrate-if-needed.sh && \ - source /usr/local/bin/start-stop-etcd.sh && \ - START_STORAGE=etcd3 START_VERSION=$(REGISTRY_TAG) start_etcd && \ - ETCDCTL_API=3 /usr/local/bin/etcdctl --endpoints http://127.0.0.1:$${ETCD_PORT} put /registry/k1 value1 && \ - stop_etcd' - - @echo "Rolling back to the previous version of etcd and recording keyspace to a flat file." - docker run --tty --interactive -v $(TEMP_DIR)/rollback-test:/var/etcd \ - -e "TARGET_STORAGE=etcd3" \ - -e "TARGET_VERSION=$(ROLLBACK_REGISTRY_TAG)" \ - -e "DATA_DIRECTORY=/var/etcd/data" \ - $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) /bin/sh -c \ - 'INITIAL_CLUSTER=etcd-$$(hostname)=http://localhost:2380 \ - /usr/local/bin/migrate-if-needed.sh && \ - source /usr/local/bin/start-stop-etcd.sh && \ - START_STORAGE=etcd3 START_VERSION=$(ROLLBACK_REGISTRY_TAG) start_etcd && \ - ETCDCTL_API=3 /usr/local/bin/etcdctl --endpoints http://127.0.0.1:$${ETCD_PORT} get --prefix / > /var/etcd/keyspace.txt && \ - stop_etcd' - - @echo "Checking if rollback successfully downgraded etcd to $(ROLLBACK_REGISTRY_TAG)" - docker run --tty --interactive -v $(TEMP_DIR)/rollback-test:/var/etcd \ - $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) /bin/sh -c \ - '[ $$(cat /var/etcd/data/version.txt) = $(ROLLBACK_REGISTRY_TAG)/etcd3 ] && \ - grep -q value1 /var/etcd/keyspace.txt' - -# Test migrating from each supported versions to the latest version. -test-migrate: - for tag in $(TAGS); do \ - echo "Testing migration from $${tag} to $(REGISTRY_TAG)" && \ - mkdir -p $(TEMP_DIR)/migrate-$${tag} && \ - cd $(TEMP_DIR)/migrate-$${tag} && \ - MAJOR_VERSION=$$(echo $${tag} | cut -c 1) && \ - echo "Starting etcd $${tag} and writing sample data to keyspace" && \ - docker run --tty --interactive -v $(TEMP_DIR)/migrate-$${tag}:/var/etcd \ - -e "TARGET_STORAGE=etcd$${MAJOR_VERSION}" \ - -e "TARGET_VERSION=$${tag}" \ - -e "DATA_DIRECTORY=/var/etcd/data" \ - $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) /bin/sh -c \ - "INITIAL_CLUSTER=etcd-\$$(hostname)=http://localhost:2380 \ - /usr/local/bin/migrate-if-needed.sh && \ - source /usr/local/bin/start-stop-etcd.sh && \ - START_STORAGE=etcd$${MAJOR_VERSION} START_VERSION=$${tag} start_etcd && \ - if [ $${MAJOR_VERSION} == 2 ]; then \ - /usr/local/bin/etcdctl --endpoint http://127.0.0.1:\$${ETCD_PORT} set /registry/k1 value1; \ - else \ - ETCDCTL_API=3 /usr/local/bin/etcdctl --endpoints http://127.0.0.1:\$${ETCD_PORT} put /registry/k1 value1; \ - fi && \ - stop_etcd" && \ - echo " Migrating from $${tag} to $(REGISTRY_TAG) and capturing keyspace" && \ - docker run --tty --interactive -v $(TEMP_DIR)/migrate-$${tag}:/var/etcd \ - -e "TARGET_STORAGE=etcd3" \ - -e "TARGET_VERSION=$(REGISTRY_TAG)" \ - -e "DATA_DIRECTORY=/var/etcd/data" \ - $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) /bin/sh -c \ - 'INITIAL_CLUSTER=etcd-$$(hostname)=http://localhost:2380 \ - /usr/local/bin/migrate-if-needed.sh && \ - source /usr/local/bin/start-stop-etcd.sh && \ - START_STORAGE=etcd3 START_VERSION=$(REGISTRY_TAG) start_etcd && \ - ETCDCTL_API=3 /usr/local/bin/etcdctl --endpoints http://127.0.0.1:$${ETCD_PORT} get --prefix / > /var/etcd/keyspace.txt && \ - stop_etcd' && \ - echo "Checking if migrate from $${tag} successfully upgraded etcd to $(REGISTRY_TAG)" && \ - docker run --tty --interactive -v $(TEMP_DIR)/migrate-$${tag}:/var/etcd \ - $(REGISTRY)/etcd-$(ARCH):$(REGISTRY_TAG) /bin/sh -c \ - '[ $$(cat /var/etcd/data/version.txt) = $(REGISTRY_TAG)/etcd3 ] && \ - grep -q value1 /var/etcd/keyspace.txt'; \ - done - -test: test-rollback test-rollback-etcd2 test-migrate - +unit-test: + docker run --interactive -v $(shell pwd)/../../../:/go/src/k8s.io/kubernetes -e GOARCH=$(ARCH) golang:$(GOLANG_VERSION) \ + /bin/bash -c "CGO_ENABLED=0 go test -v k8s.io/kubernetes/cluster/images/etcd/migrate" + +# Integration tests require both a golang build environment and all the etcd binaries from a `k8s.gcr.io/etcd` image (`/usr/local/bin/etcd-`, ...). +# Since the `k8s.gcr.io/etcd` image is for runtime only and does not have a build golang environment, we create a new docker image to run integration tests +# with. +build-integration-test-image: build + cp -r $(TEMP_DIR) $(TEMP_DIR)_integration_test + cp Dockerfile $(TEMP_DIR)_integration_test/Dockerfile + cd $(TEMP_DIR)_integration_test && sed -i.bak 's|BASEIMAGE|golang:$(GOLANG_VERSION)|g' Dockerfile + docker build --pull -t etcd-integration-test $(TEMP_DIR)_integration_test + +integration-test: + docker run --interactive -v $(shell pwd)/../../../:/go/src/k8s.io/kubernetes -e GOARCH=$(ARCH) etcd-integration-test \ + /bin/bash -c "CGO_ENABLED=0 go test -tags=integration -v k8s.io/kubernetes/cluster/images/etcd/migrate -args -v 10 -logtostderr true" + +integration-build-test: build-integration-test-image integration-test +test: unit-test integration-build-test all: build test -.PHONY: build push test-rollback test-rollback-etcd2 test-migrate test +.PHONY: build push unit-test build-integration-test-image integration-test integration-build-test test diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/README.md b/vendor/k8s.io/kubernetes/cluster/images/etcd/README.md index 749612163..6ba178a62 100644 --- a/vendor/k8s.io/kubernetes/cluster/images/etcd/README.md +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/README.md @@ -1,17 +1,30 @@ -### etcd +### k8s.gcr.io/etcd docker image -This is a small etcd image used in Kubernetes setups where `etcd` is deployed as a docker image. +Provides docker images containing etcd and etcdctl binaries for multiple etcd +version as well as a migration operator utility for upgrading and downgrading +etcd--it's data directory in particular--to a target version. -For `amd64`, official `etcd` and `etcdctl` binaries are downloaded from Github to maintain official support. -For other architectures, `etcd` is cross-compiled from source. Arch-specific `busybox` images serve as base images. +#### Versioning -### Upgrading and Downgrading +Each `k8s.gcr.io/etcd` docker image is tagged with an version string of the form +`-`, e.g. `3.0.17-0`. The etcd version is the +SemVer of latest etcd version available in the image. The image revision +distinguishes between docker images with the same lastest etcd version but +changes (bug fixes and backward compatible improvements) to the migration +utility bundled with the image. -To upgrade to a newer etcd version, or to downgrade to the previous minor -version, always run `/usr/local/bin/migrate-if-needed.sh` before starting the -etcd server. +In addition to the latest etcd version, each `k8s.gcr.io/etcd` image contains +etcd and etcdctl binaries for older versions of etcd. These are used by the +migration operator utility when performing downgrades and multi-step upgrades, +but can also be used as the etcd target version. -`migrate-if-needed.sh` writes a `version.txt` file to track the "current" version +#### Usage + +Always run `/usr/local/bin/migrate` (or the +`/usr/local/bin/migrate-if-needed.sh` wrapper script) before starting the etcd +server. + +`migrate` writes a `version.txt` file to track the "current" version of etcd that was used to persist data to disk. A "target" version may also be provided by the `TARGET_STORAGE` (e.g. "etcd3") and `TARGET_VERSION` (e.g. "3.2.11" ) environment variables. If the persisted version differs from the target version, @@ -23,15 +36,30 @@ in steps to each minor version until the target version is reached. Downgrades to the previous minor version of the 3.x series and from 3.0 to 2.3.7 are supported. +#### Permissions + +By default, `migrate` will write data directory files with default permissions +according to the umask it is run with. When run in the published +`k8s.gcr.io/etcd` images the default umask is 0022 which will result in 0755 +directory permissions and 0644 file permissions. + +#### Cross building + +For `amd64`, official `etcd` and `etcdctl` binaries are downloaded from Github +to maintain official support. For other architectures, `etcd` is cross-compiled +from source. Arch-specific `busybox` images serve as base images. + #### How to release -First, run the migration and rollback tests. +First, update `ETCD_VERSION` and `REVSION` in the `Makefile`. + +Next, build and test the image: ```console $ make build test ``` -Next, build and push the docker images for all supported architectures. +Last, build and push the docker images for all supported architectures. ```console # Build for linux/amd64 (default) diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/attachlease/BUILD b/vendor/k8s.io/kubernetes/cluster/images/etcd/attachlease/BUILD deleted file mode 100644 index bf5b9a316..000000000 --- a/vendor/k8s.io/kubernetes/cluster/images/etcd/attachlease/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "attachlease", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["attachlease.go"], - importpath = "k8s.io/kubernetes/cluster/images/etcd/attachlease", - deps = [ - "//vendor/github.com/coreos/etcd/clientv3:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/attachlease/attachlease.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/attachlease/attachlease.go deleted file mode 100644 index 1c7d6b814..000000000 --- a/vendor/k8s.io/kubernetes/cluster/images/etcd/attachlease/attachlease.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -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 main - -import ( - "flag" - "strings" - "time" - - "github.com/coreos/etcd/clientv3" - "github.com/golang/glog" - "golang.org/x/net/context" -) - -var ( - etcdAddress = flag.String("etcd-address", "", "Etcd address") - ttlKeysPrefix = flag.String("ttl-keys-prefix", "", "Prefix for TTL keys") - leaseDuration = flag.Duration("lease-duration", time.Hour, "Lease duration (seconds granularity)") -) - -func main() { - flag.Parse() - - if *etcdAddress == "" { - glog.Fatalf("--etcd-address flag is required") - } - client, err := clientv3.New(clientv3.Config{Endpoints: []string{*etcdAddress}}) - if err != nil { - glog.Fatalf("Error while creating etcd client: %v", err) - } - - // Make sure that ttlKeysPrefix is ended with "/" so that we only get children "directories". - if !strings.HasSuffix(*ttlKeysPrefix, "/") { - *ttlKeysPrefix += "/" - } - ctx := context.Background() - - objectsResp, err := client.KV.Get(ctx, *ttlKeysPrefix, clientv3.WithPrefix()) - if err != nil { - glog.Fatalf("Error while getting objects to attach to the lease") - } - - lease, err := client.Lease.Grant(ctx, int64(*leaseDuration/time.Second)) - if err != nil { - glog.Fatalf("Error while creating lease: %v", err) - } - glog.Infof("Lease with TTL: %v created", lease.TTL) - - glog.Infof("Attaching lease to %d entries", len(objectsResp.Kvs)) - for _, kv := range objectsResp.Kvs { - _, err := client.KV.Put(ctx, string(kv.Key), string(kv.Value), clientv3.WithLease(lease.ID)) - if err != nil { - glog.Errorf("Error while attaching lease to: %s", string(kv.Key)) - } - } -} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate-if-needed.sh b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate-if-needed.sh index 6b5b67226..79c832f7e 100755 --- a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate-if-needed.sh +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate-if-needed.sh @@ -18,7 +18,7 @@ # This script performs etcd upgrade based on the following environmental # variables: # TARGET_STORAGE - API of etcd to be used (supported: 'etcd2', 'etcd3') -# TARGET_VERSION - etcd release to be used (supported: '2.2.1', '2.3.7', '3.0.17', '3.1.12') +# TARGET_VERSION - etcd release to be used (supported: '2.2.1', '2.3.7', '3.0.17', '3.1.12', '3.2.18') # DATA_DIRECTORY - directory with etcd data # # The current etcd version and storage format is detected based on the @@ -29,6 +29,7 @@ # - 2.2.1/etcd2 -> 2.3.7/etcd2 # - 2.3.7/etcd2 -> 3.0.17/etcd2 # - 3.0.17/etcd3 -> 3.1.12/etcd3 +# - 3.1.12/etcd3 -> 3.2.18/etcd3 # # NOTE: The releases supported in this script has to match release binaries # present in the etcd image (to make this script work correctly). @@ -39,95 +40,49 @@ set -o errexit set -o nounset -source $(dirname "$0")/start-stop-etcd.sh - -# Rollback to previous minor version of etcd 3.x, if needed. -# -# Warning: For HA etcd clusters (any cluster with more than one member), all members must be stopped before rolling back, zero -# downtime rollbacks are not supported. -rollback_etcd3_minor_version() { - if [ ${TARGET_MINOR_VERSION} != $((${CURRENT_MINOR_VERSION}-1)) ]; then - echo "Rollback from ${CURRENT_VERSION} to ${TARGET_VERSION} not supported, only rollbacks to the previous minor version are supported." - exit 1 - fi - echo "Performing etcd ${CURRENT_VERSION} -> ${TARGET_VERSION} rollback" - ROLLBACK_BACKUP_DIR="${DATA_DIRECTORY}.bak" - rm -rf "${ROLLBACK_BACKUP_DIR}" - SNAPSHOT_FILE="${DATA_DIRECTORY}.snapshot.db" - rm -rf "${SNAPSHOT_FILE}" - ETCD_CMD="/usr/local/bin/etcd-${CURRENT_VERSION}" - ETCDCTL_CMD="/usr/local/bin/etcdctl-${CURRENT_VERSION}" - - # Start CURRENT_VERSION of etcd. - START_VERSION="${CURRENT_VERSION}" - START_STORAGE="${CURRENT_STORAGE}" - echo "Starting etcd version ${START_VERSION} to capture rollback snapshot." - if ! start_etcd; then - echo "Unable to automatically downgrade etcd: starting etcd version ${START_VERSION} to capture rollback snapshot failed." - echo "See https://coreos.com/etcd/docs/latest/op-guide/recovery.html for manual downgrade options." - exit 1 - else - ETCDCTL_API=3 ${ETCDCTL_CMD} snapshot --endpoints "http://127.0.0.1:${ETCD_PORT}" save "${SNAPSHOT_FILE}" - fi - stop_etcd - - # Backup the data before rolling back. - mv "${DATA_DIRECTORY}" "${ROLLBACK_BACKUP_DIR}" - ETCDCTL_CMD="/usr/local/bin/etcdctl-${TARGET_VERSION}" - NAME="etcd-$(hostname)" - ETCDCTL_API=3 ${ETCDCTL_CMD} snapshot restore "${SNAPSHOT_FILE}" \ - --data-dir "${DATA_DIRECTORY}" --name "${NAME}" --initial-cluster "${INITIAL_CLUSTER}" - - CURRENT_VERSION="${TARGET_VERSION}" - echo "${CURRENT_VERSION}/${CURRENT_STORAGE}" > "${DATA_DIRECTORY}/${VERSION_FILE}" -} +# NOTE: BUNDLED_VERSION has to match release binaries present in the +# etcd image (to make this script work correctly). +BUNDLED_VERSIONS="2.2.1, 2.3.7, 3.0.17, 3.1.12, 3.2.18" -# Rollback from "3.0.x" version in 'etcd3' mode to "2.2.1" version in 'etcd2' mode, if needed. -rollback_to_etcd2() { - if [ "$(echo ${CURRENT_VERSION} | cut -c1-4)" != "3.0." -o "${TARGET_VERSION}" != "2.2.1" ]; then - echo "etcd3 -> etcd2 downgrade is supported only between 3.0.x and 2.2.1" - return 0 - fi - echo "Backup and remove all existing v2 data" - ROLLBACK_BACKUP_DIR="${DATA_DIRECTORY}.bak" - rm -rf "${ROLLBACK_BACKUP_DIR}" - mkdir -p "${ROLLBACK_BACKUP_DIR}" - cp -r "${DATA_DIRECTORY}" "${ROLLBACK_BACKUP_DIR}" - echo "Performing etcd3 -> etcd2 rollback" - ${ROLLBACK} --data-dir "${DATA_DIRECTORY}" - if [ "$?" -ne "0" ]; then - echo "Rollback to etcd2 failed" - exit 1 - fi - CURRENT_STORAGE="etcd2" - CURRENT_VERSION="2.2.1" - echo "${CURRENT_VERSION}/${CURRENT_STORAGE}" > "${DATA_DIRECTORY}/${VERSION_FILE}" -} +ETCD_NAME="${ETCD_NAME:-etcd-$(hostname)}" +if [ -z "${DATA_DIRECTORY:-}" ]; then + echo "DATA_DIRECTORY variable unset - unexpected failure" + exit 1 +fi +case "${DATA_DIRECTORY}" in + *event*) + ETCD_PEER_PORT=2381 + ETCD_CLIENT_PORT=18631 + ;; + *) + ETCD_PEER_PORT=2380 + ETCD_CLIENT_PORT=18629 + ;; +esac -if [ -z "${TARGET_STORAGE:-}" ]; then - echo "TARGET_STORAGE variable unset - unexpected failure" - exit 1 +if [ -z "${INITIAL_CLUSTER:-}" ]; then + echo "Warn: INITIAL_CLUSTER variable unset - defaulting to ${ETCD_NAME}=http://localhost:${ETCD_PEER_PORT}" + INITIAL_CLUSTER="${ETCD_NAME}=http://localhost:${ETCD_PEER_PORT}" +fi +if [ -z "${LISTEN_PEER_URLS:-}" ]; then + echo "Warn: LISTEN_PEER_URLS variable unset - defaulting to http://localhost:${ETCD_PEER_PORT}" + LISTEN_PEER_URLS="http://localhost:${ETCD_PEER_PORT}" +fi +if [ -z "${INITIAL_ADVERTISE_PEER_URLS:-}" ]; then + echo "Warn: INITIAL_ADVERTISE_PEER_URLS variable unset - defaulting to http://localhost:${ETCD_PEER_PORT}" + INITIAL_ADVERTISE_PEER_URLS="http://localhost:${ETCD_PEER_PORT}" fi if [ -z "${TARGET_VERSION:-}" ]; then echo "TARGET_VERSION variable unset - unexpected failure" exit 1 fi -if [ -z "${DATA_DIRECTORY:-}" ]; then - echo "DATA_DIRECTORY variable unset - unexpected failure" - exit 1 -fi -if [ -z "${INITIAL_CLUSTER:-}" ]; then - echo "Warn: INITIAL_CLUSTER variable unset - defaulting to etcd-$(hostname)=http://localhost:2380" - INITIAL_CLUSTER="etcd-$(hostname)=http://localhost:2380" -fi - -echo "$(date +'%Y-%m-%d %H:%M:%S') Detecting if migration is needed" - -if [ "${TARGET_STORAGE}" != "etcd2" -a "${TARGET_STORAGE}" != "etcd3" ]; then - echo "Not supported version of storage: ${TARGET_STORAGE}" +if [ -z "${TARGET_STORAGE:-}" ]; then + echo "TARGET_STORAGE variable unset - unexpected failure" exit 1 fi +ETCD_DATA_PREFIX="${ETCD_DATA_PREFIX:-/registry}" +ETCD_CREDS="${ETCD_CREDS:-}" # Correctly support upgrade and rollback to non-default version. if [ "${DO_NOT_MOVE_BINARIES:-}" != "true" ]; then @@ -135,144 +90,16 @@ if [ "${DO_NOT_MOVE_BINARIES:-}" != "true" ]; then cp "/usr/local/bin/etcdctl-${TARGET_VERSION}" "/usr/local/bin/etcdctl" fi -# NOTE: SUPPORTED_VERSION has to match release binaries present in the -# etcd image (to make this script work correctly). -# We cannot use array since sh doesn't support it. -SUPPORTED_VERSIONS_STRING="2.2.1 2.3.7 3.0.17 3.1.12" -SUPPORTED_VERSIONS=$(echo "${SUPPORTED_VERSIONS_STRING}" | tr " " "\n") - -VERSION_FILE="version.txt" -CURRENT_STORAGE="etcd2" -CURRENT_VERSION="2.2.1" -if [ -e "${DATA_DIRECTORY}/${VERSION_FILE}" ]; then - VERSION_CONTENTS="$(cat ${DATA_DIRECTORY}/${VERSION_FILE})" - # Example usage: if contents of VERSION_FILE is 2.3.7/etcd2, then - # - CURRENT_VERSION would be '2.3.7' - # - CURRENT_STORAGE would be 'etcd2' - CURRENT_VERSION="$(echo $VERSION_CONTENTS | cut -d '/' -f 1)" - CURRENT_STORAGE="$(echo $VERSION_CONTENTS | cut -d '/' -f 2)" -fi -ETCD_DATA_PREFIX="${ETCD_DATA_PREFIX:-/registry}" - -# If there is no data in DATA_DIRECTORY, this means that we are -# starting etcd from scratch. In that case, we don't need to do -# any migration. -if [ ! -d "${DATA_DIRECTORY}" ]; then - mkdir -p "${DATA_DIRECTORY}" -fi -if [ -z "$(ls -A ${DATA_DIRECTORY})" ]; then - echo "${DATA_DIRECTORY} is empty - skipping migration" - echo "${TARGET_VERSION}/${TARGET_STORAGE}" > "${DATA_DIRECTORY}/${VERSION_FILE}" - exit 0 -fi - -ATTACHLEASE="${ATTACHLEASE:-/usr/local/bin/attachlease}" -ROLLBACK="${ROLLBACK:-/usr/local/bin/rollback}" - -# If we are upgrading from 2.2.1 and this is the first try for upgrade, -# do the backup to allow restoring from it in case of failed upgrade. -BACKUP_DIR="${DATA_DIRECTORY}/migration-backup" -if [ "${CURRENT_VERSION}" = "2.2.1" -a "${CURRENT_VERSION}" != "${TARGET_VERSION}" -a ! -d "${BACKUP_DIR}" ]; then - echo "Backup etcd before starting migration" - mkdir ${BACKUP_DIR} - ETCDCTL_CMD="/usr/local/bin/etcdctl-2.2.1" - ETCDCTL_API=2 ${ETCDCTL_CMD} --debug backup --data-dir=${DATA_DIRECTORY} \ - --backup-dir=${BACKUP_DIR} - echo "Backup done in ${BACKUP_DIR}" -fi - -CURRENT_MINOR_VERSION="$(echo ${CURRENT_VERSION} | awk -F'.' '{print $2}')" -TARGET_MINOR_VERSION="$(echo ${TARGET_VERSION} | awk -F'.' '{print $2}')" - -# "rollback-if-needed" -case "${CURRENT_STORAGE}-${TARGET_STORAGE}" in - "etcd3-etcd3") - [ ${TARGET_MINOR_VERSION} -lt ${CURRENT_MINOR_VERSION} ] && rollback_etcd3_minor_version - break - ;; - "etcd3-etcd2") - rollback_to_etcd2 - break - ;; - *) - break - ;; -esac - -# Do the roll-forward migration if needed. -# The migration goes as following: -# 1. for all versions starting one after the current version of etcd -# we do "start, wait until healthy and stop etcd". This is the -# procedure that etcd documentation suggests for upgrading binaries. -# 2. For the first 3.0.x version that we encounter, if we are still in -# v2 API, we do upgrade to v3 API using the "etcdct migrate" and -# attachlease commands. -SKIP_STEP=true -for step in ${SUPPORTED_VERSIONS}; do - if [ "${step}" = "${CURRENT_VERSION}" ]; then - SKIP_STEP=false - elif [ "${SKIP_STEP}" != "true" ]; then - # Do the migration step, by just starting etcd in this version. - START_VERSION="${step}" - START_STORAGE="${CURRENT_STORAGE}" - if ! start_etcd; then - # Migration failed. - echo "Starting etcd ${step} failed" - exit 1 - fi - # Kill etcd and wait until this is down. - stop_etcd - CURRENT_VERSION=${step} - echo "${CURRENT_VERSION}/${CURRENT_STORAGE}" > "${DATA_DIRECTORY}/${VERSION_FILE}" - fi - if [ "$(echo ${CURRENT_VERSION} | cut -c1-2)" = "3." -a "${CURRENT_VERSION}" = "${step}" -a "${CURRENT_STORAGE}" = "etcd2" -a "${TARGET_STORAGE}" = "etcd3" ]; then - # If it is the first 3.x release in the list and we are migrating - # also from 'etcd2' to 'etcd3', do the migration now. - echo "Performing etcd2 -> etcd3 migration" - START_VERSION="${step}" - START_STORAGE="etcd3" - ETCDCTL_CMD="${ETCDCTL:-/usr/local/bin/etcdctl-${START_VERSION}}" - ETCDCTL_API=3 ${ETCDCTL_CMD} migrate --data-dir=${DATA_DIRECTORY} - echo "Attaching leases to TTL entries" - # Now attach lease to all keys. - # To do it, we temporarily start etcd on a random port (so that - # apiserver actually cannot access it). - if ! start_etcd; then - echo "Starting etcd ${step} in v3 mode failed" - exit 1 - fi - # Create a lease and attach all keys to it. - ${ATTACHLEASE} \ - --etcd-address http://127.0.0.1:${ETCD_PORT} \ - --ttl-keys-prefix "${TTL_KEYS_DIRECTORY:-${ETCD_DATA_PREFIX}/events}" \ - --lease-duration 1h - # Kill etcd and wait until this is down. - stop_etcd - CURRENT_STORAGE="etcd3" - echo "${CURRENT_VERSION}/${CURRENT_STORAGE}" > "${DATA_DIRECTORY}/${VERSION_FILE}" - fi - if [ "$(echo ${CURRENT_VERSION} | cut -c1-4)" = "3.1." -a "${CURRENT_VERSION}" = "${step}" -a "${CURRENT_STORAGE}" = "etcd3" ]; then - # If we are upgrading to 3.1.* release, if the cluster was migrated - # from v2 version, the v2 data may still be around. So now is the - # time to actually remove them. - echo "Remove stale v2 data" - START_VERSION="${step}" - START_STORAGE="etcd3" - ETCDCTL_CMD="${ETCDCTL:-/usr/local/bin/etcdctl-${START_VERSION}}" - if ! start_etcd; then - echo "Starting etcd ${step} in v3 mode failed" - exit 1 - fi - ${ETCDCTL_CMD} --endpoints "http://127.0.0.1:${ETCD_PORT}" rm --recursive "${ETCD_DATA_PREFIX}" - # Kill etcd and wait until this is down. - stop_etcd - echo "Successfully remove v2 data" - # Also remove backup from v2->v3 migration. - rm -rf "${BACKUP_DIR}" - fi - if [ "${CURRENT_VERSION}" = "${TARGET_VERSION}" -a "${CURRENT_STORAGE}" = "${TARGET_STORAGE}" ]; then - break - fi -done - -echo "$(date +'%Y-%m-%d %H:%M:%S') Migration finished" +/usr/local/bin/migrate \ + --name "${ETCD_NAME}" \ + --port "${ETCD_CLIENT_PORT}" \ + --listen-peer-urls "${LISTEN_PEER_URLS}" \ + --initial-advertise-peer-urls "${INITIAL_ADVERTISE_PEER_URLS}" \ + --data-dir "${DATA_DIRECTORY}" \ + --bundled-versions "${BUNDLED_VERSIONS}" \ + --initial-cluster "${INITIAL_CLUSTER}" \ + --target-version "${TARGET_VERSION}" \ + --target-storage "${TARGET_STORAGE}" \ + --etcd-data-prefix "${ETCD_DATA_PREFIX}" \ + --ttl-keys-directory "${TTL_KEYS_DIRECTORY:-${ETCD_DATA_PREFIX}/events}" \ + --etcd-server-extra-args "${ETCD_CREDS}" diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/BUILD b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/BUILD new file mode 100644 index 000000000..7212e4e96 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/BUILD @@ -0,0 +1,72 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_binary", + "go_library", + "go_test", +) + +go_binary( + name = "migrate", + embed = [":go_default_library"], +) + +go_library( + name = "go_default_library", + srcs = [ + "data_dir.go", + "migrate.go", + "migrate_client.go", + "migrate_server.go", + "migrator.go", + "rollback_v2.go", + "versions.go", + ], + importpath = "k8s.io/kubernetes/cluster/images/etcd/migrate", + deps = [ + "//third_party/forked/etcd221/wal:go_default_library", + "//vendor/github.com/blang/semver:go_default_library", + "//vendor/github.com/coreos/etcd/client:go_default_library", + "//vendor/github.com/coreos/etcd/clientv3:go_default_library", + "//vendor/github.com/coreos/etcd/etcdserver:go_default_library", + "//vendor/github.com/coreos/etcd/etcdserver/etcdserverpb:go_default_library", + "//vendor/github.com/coreos/etcd/etcdserver/membership:go_default_library", + "//vendor/github.com/coreos/etcd/mvcc/backend:go_default_library", + "//vendor/github.com/coreos/etcd/mvcc/mvccpb:go_default_library", + "//vendor/github.com/coreos/etcd/pkg/pbutil:go_default_library", + "//vendor/github.com/coreos/etcd/pkg/types:go_default_library", + "//vendor/github.com/coreos/etcd/raft/raftpb:go_default_library", + "//vendor/github.com/coreos/etcd/snap:go_default_library", + "//vendor/github.com/coreos/etcd/store:go_default_library", + "//vendor/github.com/coreos/etcd/wal:go_default_library", + "//vendor/github.com/coreos/etcd/wal/walpb:go_default_library", + "//vendor/github.com/coreos/go-semver/semver:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) + +go_test( + name = "go_default_test", + srcs = [ + "data_dir_test.go", + "versions_test.go", + ], + data = glob(["testdata/**"]), + embed = [":go_default_library"], + deps = ["//vendor/github.com/blang/semver:go_default_library"], +) diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/data_dir.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/data_dir.go new file mode 100644 index 000000000..75a605bf8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/data_dir.go @@ -0,0 +1,157 @@ +/* +Copyright 2018 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 main + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/golang/glog" +) + +// DataDirectory provides utilities for initializing and backing up an +// etcd "data-dir" as well as managing a version.txt file to track the +// etcd server version and storage verion of the etcd data in the +// directory. +type DataDirectory struct { + path string + versionFile *VersionFile +} + +// OpenOrCreateDataDirectory opens a data directory, creating the directory +// if it doesn't not already exist. +func OpenOrCreateDataDirectory(path string) (*DataDirectory, error) { + exists, err := exists(path) + if err != nil { + return nil, err + } + if !exists { + glog.Infof("data directory '%s' does not exist, creating it", path) + err := os.MkdirAll(path, 0777) + if err != nil { + return nil, fmt.Errorf("failed to create data directory %s: %v", path, err) + } + } + versionFile := &VersionFile{ + path: filepath.Join(path, versionFilename), + } + return &DataDirectory{path, versionFile}, nil +} + +// Initialize set the version.txt to the target version if the data +// directory is empty. If the data directory is non-empty, no +// version.txt file will be written since the actual version of etcd +// used to create the data is unknown. +func (d *DataDirectory) Initialize(target *EtcdVersionPair) error { + isEmpty, err := d.IsEmpty() + if err != nil { + return err + } + if isEmpty { + glog.Infof("data directory '%s' is empty, writing target version '%s' to version.txt", d.path, target) + err = d.versionFile.Write(target) + if err != nil { + return fmt.Errorf("failed to write version.txt to '%s': %v", d.path, err) + } + return nil + } + return nil +} + +// Backup creates a backup copy of data directory. +func (d *DataDirectory) Backup() error { + backupDir := fmt.Sprintf("%s.bak", d.path) + err := os.RemoveAll(backupDir) + if err != nil { + return err + } + err = os.MkdirAll(backupDir, 0777) + if err != nil { + return err + } + err = exec.Command("cp", "-r", d.path, backupDir).Run() + if err != nil { + return err + } + + return nil +} + +// IsEmpty returns true if the data directory is entirely empty. +func (d *DataDirectory) IsEmpty() (bool, error) { + dir, err := os.Open(d.path) + if err != nil { + return false, fmt.Errorf("failed to open data directory %s: %v", d.path, err) + } + defer dir.Close() + _, err = dir.Readdirnames(1) + if err == io.EOF { + return true, nil + } + return false, err +} + +// String returns the data directory path. +func (d *DataDirectory) String() string { + return d.path +} + +// VersionFile provides utilities for reading and writing version.txt files +// to etcd "data-dir" for tracking the etcd server and storage verions +// of the data in the directory. +type VersionFile struct { + path string +} + +// Exists returns true if a version.txt file exists on the filesystem. +func (v *VersionFile) Exists() (bool, error) { + return exists(v.path) +} + +// Read parses the version.txt file and returns it's contents. +func (v *VersionFile) Read() (*EtcdVersionPair, error) { + data, err := ioutil.ReadFile(v.path) + if err != nil { + return nil, fmt.Errorf("failed to read version file %s: %v", v.path, err) + } + txt := strings.TrimSpace(string(data)) + vp, err := ParseEtcdVersionPair(txt) + if err != nil { + return nil, fmt.Errorf("failed to parse etcd '/' string from version.txt file contents '%s': %v", txt, err) + } + return vp, nil +} + +// Write creates or overwrites the contents of the version.txt file with the given EtcdVersionPair. +func (v *VersionFile) Write(vp *EtcdVersionPair) error { + data := []byte(fmt.Sprintf("%s/%s", vp.version, vp.storageVersion)) + return ioutil.WriteFile(v.path, data, 0666) +} + +func exists(path string) (bool, error) { + if _, err := os.Stat(path); os.IsNotExist(err) { + return false, nil + } else if err != nil { + return false, err + } + return true, nil +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/data_dir_test.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/data_dir_test.go new file mode 100644 index 000000000..6fe64d4ab --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/data_dir_test.go @@ -0,0 +1,159 @@ +/* +Copyright 2018 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 main + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/blang/semver" +) + +var ( + latestVersion = semver.MustParse("3.1.12") +) + +func TestExistingDataDirWithVersionFile(t *testing.T) { + d, err := OpenOrCreateDataDirectory("testdata/datadir_with_version") + if err != nil { + t.Fatalf("Failed to open data dir: %v", err) + } + isEmpty, err := d.IsEmpty() + if err != nil { + t.Fatalf("Failed to check if data dir is empty: %v", err) + } + if isEmpty { + t.Errorf("Data directory is non-empty") + } + exists, err := d.versionFile.Exists() + if err != nil { + t.Fatal(err) + } + if !exists { + t.Fatalf("Expected version file %s to exist", d.versionFile.path) + } + vp, err := d.versionFile.Read() + if err != nil { + t.Fatalf("Failed to read version file %s: %v", d.versionFile.path, err) + } + expectedVersion := &EtcdVersionPair{&EtcdVersion{latestVersion}, storageEtcd3} + if !vp.Equals(expectedVersion) { + t.Errorf("Expected version file to contain %s, but got %s", expectedVersion, vp) + } +} + +func TestExistingDataDirWithoutVersionFile(t *testing.T) { + targetVersion := &EtcdVersionPair{&EtcdVersion{latestVersion}, storageEtcd3} + + d, err := OpenOrCreateDataDirectory("testdata/datadir_without_version") + if err != nil { + t.Fatalf("Failed to open data dir: %v", err) + } + exists, err := d.versionFile.Exists() + if err != nil { + t.Fatal(err) + } + if exists { + t.Errorf("Expected version file %s not to exist", d.versionFile.path) + } + err = d.Initialize(targetVersion) + if err != nil { + t.Fatalf("Failed initialize data directory %s: %v", d.path, err) + } + exists, err = d.versionFile.Exists() + if err != nil { + t.Fatal(err) + } + if exists { + t.Fatalf("Expected version file %s not to exist after initializing non-empty data-dir", d.versionFile.path) + } +} + +func TestNonexistingDataDir(t *testing.T) { + targetVersion := &EtcdVersionPair{&EtcdVersion{latestVersion}, storageEtcd3} + path := newTestPath(t) + d, err := OpenOrCreateDataDirectory(filepath.Join(path, "data-dir")) + if err != nil { + t.Fatalf("Failed to open data dir: %v", err) + } + isEmpty, err := d.IsEmpty() + if err != nil { + t.Fatalf("Failed to check if data dir is empty: %v", err) + } + if !isEmpty { + t.Errorf("Data directory is empty") + } + err = d.Initialize(targetVersion) + if err != nil { + t.Fatalf("Failed initialize data directory %s: %v", d.path, err) + } + exists, err := d.versionFile.Exists() + if err != nil { + t.Fatal(err) + } + if !exists { + t.Fatalf("Expected version file %s to exist", d.versionFile.path) + } + isEmpty, err = d.IsEmpty() + if err != nil { + t.Fatalf("Failed to check if data dir is empty: %v", err) + } + if isEmpty { + t.Errorf("Data directory is non-empty") + } + vp, err := d.versionFile.Read() + if err != nil { + t.Fatalf("Failed to read version file %s: %v", d.versionFile.path, err) + } + if !vp.Equals(targetVersion) { + t.Errorf("Expected version file to contain %s, but got %s", targetVersion, vp) + } +} + +func TestBackup(t *testing.T) { + path := newTestPath(t) + d, err := OpenOrCreateDataDirectory(filepath.Join(path, "data-dir")) + if err != nil { + t.Fatalf("Failed to open data dir: %v", err) + } + err = d.Backup() + if err != nil { + t.Fatalf("Failed to backup data directory %s: %v", d.path, err) + } + bak, err := OpenOrCreateDataDirectory(filepath.Join(path, "data-dir.bak")) + if err != nil { + t.Fatalf("Failed to open backup data dir: %v", err) + } + isEmpty, err := bak.IsEmpty() + if err != nil { + t.Fatal(err) + } + if isEmpty { + t.Errorf("Expected non-empty backup directory afer Backup()") + } +} + +func newTestPath(t *testing.T) string { + path, err := ioutil.TempDir("", "etcd-migrate-test-") + os.Chmod(path, 0777) + if err != nil { + t.Fatalf("Failed to create tmp dir for test: %v", err) + } + return path +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/integration_test.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/integration_test.go new file mode 100644 index 000000000..bd32e5d10 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/integration_test.go @@ -0,0 +1,356 @@ +// +build integration + +/* +Copyright 2018 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 main + +import ( + "bytes" + cryptorand "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "io/ioutil" + "math/big" + "net" + "os" + "path/filepath" + "strings" + "sync" + "testing" + "time" + + "github.com/blang/semver" +) + +var ( + testSupportedVersions = MustParseSupportedVersions("2.2.1, 2.3.7, 3.0.17, 3.1.12") + testVersionOldest = &EtcdVersion{semver.MustParse("2.2.1")} + testVersionPrevious = &EtcdVersion{semver.MustParse("3.0.17")} + testVersionLatest = &EtcdVersion{semver.MustParse("3.1.12")} +) + +func TestMigrate(t *testing.T) { + migrations := []struct { + title string + memberCount int + startVersion string + endVersion string + protocol string + }{ + // upgrades + {"v2-v3-up", 1, "2.2.1/etcd2", "3.0.17/etcd3", "https"}, + {"v3-v3-up", 1, "3.0.17/etcd3", "3.1.12/etcd3", "https"}, + {"oldest-newest-up", 1, "2.2.1/etcd2", "3.1.12/etcd3", "https"}, + + // warning: v2->v3 ha upgrades not currently supported. + {"ha-v3-v3-up", 3, "3.0.17/etcd3", "3.1.12/etcd3", "https"}, + + // downgrades + {"v3-v2-down", 1, "3.0.17/etcd3", "2.2.1/etcd2", "https"}, + {"v3-v3-down", 1, "3.1.12/etcd3", "3.0.17/etcd3", "https"}, + + // warning: ha downgrades not yet supported. + } + + for _, m := range migrations { + t.Run(m.title, func(t *testing.T) { + start := MustParseEtcdVersionPair(m.startVersion) + end := MustParseEtcdVersionPair(m.endVersion) + + testCfgs := clusterConfig(t, m.title, m.memberCount, m.protocol) + + servers := []*EtcdMigrateServer{} + for _, cfg := range testCfgs { + client, err := NewEtcdMigrateClient(cfg) + if err != nil { + t.Fatalf("Failed to create client: %v", err) + } + server := NewEtcdMigrateServer(cfg, client) + servers = append(servers, server) + } + + // Start the servers. + parallel(servers, func(server *EtcdMigrateServer) { + dataDir, err := OpenOrCreateDataDirectory(server.cfg.dataDirectory) + if err != nil { + t.Fatalf("Error opening or creating data directory %s: %v", server.cfg.dataDirectory, err) + } + migrator := &Migrator{server.cfg, dataDir, server.client} + err = migrator.MigrateIfNeeded(start) + if err != nil { + t.Fatalf("Migration failed: %v", err) + } + err = server.Start(start.version) + if err != nil { + t.Fatalf("Failed to start server: %v", err) + } + }) + + // Write a value to each server, read it back. + parallel(servers, func(server *EtcdMigrateServer) { + key := fmt.Sprintf("/registry/%s", server.cfg.name) + value := fmt.Sprintf("value-%s", server.cfg.name) + err := server.client.Put(start.version, key, value) + if err != nil { + t.Fatalf("failed to write text value: %v", err) + } + + checkVal, err := server.client.Get(start.version, key) + if err != nil { + t.Errorf("Error getting %s for validation: %v", key, err) + } + if checkVal != value { + t.Errorf("Expected %s from %s but got %s", value, key, checkVal) + } + }) + + // Migrate the servers in series. + serial(servers, func(server *EtcdMigrateServer) { + err := server.Stop() + if err != nil { + t.Fatalf("Stop server failed: %v", err) + } + dataDir, err := OpenOrCreateDataDirectory(server.cfg.dataDirectory) + if err != nil { + t.Fatalf("Error opening or creating data directory %s: %v", server.cfg.dataDirectory, err) + } + migrator := &Migrator{server.cfg, dataDir, server.client} + err = migrator.MigrateIfNeeded(end) + if err != nil { + t.Fatalf("Migration failed: %v", err) + } + err = server.Start(end.version) + if err != nil { + t.Fatalf("Start server failed: %v", err) + } + }) + + // Check that all test values can be read back from all the servers. + parallel(servers, func(server *EtcdMigrateServer) { + for _, s := range servers { + key := fmt.Sprintf("/registry/%s", s.cfg.name) + value := fmt.Sprintf("value-%s", s.cfg.name) + checkVal, err := server.client.Get(end.version, key) + if err != nil { + t.Errorf("Error getting %s from etcd 2.x after rollback from 3.x: %v", key, err) + } + if checkVal != value { + t.Errorf("Expected %s from %s but got %s when reading after rollback from %s to %s", value, key, checkVal, start, end) + } + } + }) + + // Stop the servers. + parallel(servers, func(server *EtcdMigrateServer) { + err := server.Stop() + if err != nil { + t.Fatalf("Failed to stop server: %v", err) + } + }) + + // Check that version.txt contains the correct end version. + parallel(servers, func(server *EtcdMigrateServer) { + dataDir, err := OpenOrCreateDataDirectory(server.cfg.dataDirectory) + v, err := dataDir.versionFile.Read() + if err != nil { + t.Fatalf("Failed to read version.txt file: %v", err) + } + if !v.Equals(end) { + t.Errorf("Expected version.txt to contain %s but got %s", end, v) + } + // Integration tests are run in a docker container with umask of 0022. + checkPermissions(t, server.cfg.dataDirectory, 0755|os.ModeDir) + checkPermissions(t, dataDir.versionFile.path, 0644) + }) + }) + } +} + +func parallel(servers []*EtcdMigrateServer, fn func(server *EtcdMigrateServer)) { + var wg sync.WaitGroup + wg.Add(len(servers)) + for _, server := range servers { + go func(s *EtcdMigrateServer) { + defer wg.Done() + fn(s) + }(server) + } + wg.Wait() +} + +func serial(servers []*EtcdMigrateServer, fn func(server *EtcdMigrateServer)) { + for _, server := range servers { + fn(server) + } +} + +func checkPermissions(t *testing.T, path string, expected os.FileMode) { + info, err := os.Stat(path) + if err != nil { + t.Fatalf("Failed to stat file %s: %v", path, err) + } + if info.Mode() != expected { + t.Errorf("Expected permissions for file %s of %s, but got %s", path, expected, info.Mode()) + } +} + +func clusterConfig(t *testing.T, name string, memberCount int, protocol string) []*EtcdMigrateCfg { + peers := []string{} + for i := 0; i < memberCount; i++ { + memberName := fmt.Sprintf("%s-%d", name, i) + peerPort := uint64(2380 + i*10000) + peer := fmt.Sprintf("%s=%s://127.0.0.1:%d", memberName, protocol, peerPort) + peers = append(peers, peer) + } + initialCluster := strings.Join(peers, ",") + + extraArgs := "" + if protocol == "https" { + extraArgs = getOrCreateTLSPeerCertArgs(t) + } + + cfgs := []*EtcdMigrateCfg{} + for i := 0; i < memberCount; i++ { + memberName := fmt.Sprintf("%s-%d", name, i) + peerURL := fmt.Sprintf("%s://127.0.0.1:%d", protocol, uint64(2380+i*10000)) + cfg := &EtcdMigrateCfg{ + binPath: "/usr/local/bin", + name: memberName, + initialCluster: initialCluster, + port: uint64(2379 + i*10000), + peerListenUrls: peerURL, + peerAdvertiseUrls: peerURL, + etcdDataPrefix: "/registry", + ttlKeysDirectory: "/registry/events", + supportedVersions: testSupportedVersions, + dataDirectory: fmt.Sprintf("/tmp/etcd-data-dir-%s", memberName), + etcdServerArgs: extraArgs, + } + cfgs = append(cfgs, cfg) + } + return cfgs +} + +func getOrCreateTLSPeerCertArgs(t *testing.T) string { + spec := TestCertSpec{ + host: "localhost", + ips: []string{"127.0.0.1"}, + } + certDir := "/tmp/certs" + certFile := filepath.Join(certDir, "test.crt") + keyFile := filepath.Join(certDir, "test.key") + err := getOrCreateTestCertFiles(certFile, keyFile, spec) + if err != nil { + t.Fatalf("failed to create server cert: %v", err) + } + return fmt.Sprintf("--peer-client-cert-auth --peer-trusted-ca-file=%s --peer-cert-file=%s --peer-key-file=%s", certFile, certFile, keyFile) +} + +type TestCertSpec struct { + host string + names, ips []string // in certificate +} + +func getOrCreateTestCertFiles(certFileName, keyFileName string, spec TestCertSpec) (err error) { + if _, err := os.Stat(certFileName); err == nil { + if _, err := os.Stat(keyFileName); err == nil { + return nil + } + } + + certPem, keyPem, err := generateSelfSignedCertKey(spec.host, parseIPList(spec.ips), spec.names) + if err != nil { + return err + } + + os.MkdirAll(filepath.Dir(certFileName), os.FileMode(0777)) + err = ioutil.WriteFile(certFileName, certPem, os.FileMode(0777)) + if err != nil { + return err + } + + os.MkdirAll(filepath.Dir(keyFileName), os.FileMode(0777)) + err = ioutil.WriteFile(keyFileName, keyPem, os.FileMode(0777)) + if err != nil { + return err + } + + return nil +} + +func parseIPList(ips []string) []net.IP { + var netIPs []net.IP + for _, ip := range ips { + netIPs = append(netIPs, net.ParseIP(ip)) + } + return netIPs +} + +// generateSelfSignedCertKey creates a self-signed certificate and key for the given host. +// Host may be an IP or a DNS name +// You may also specify additional subject alt names (either ip or dns names) for the certificate +func generateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS []string) ([]byte, []byte, error) { + priv, err := rsa.GenerateKey(cryptorand.Reader, 2048) + if err != nil { + return nil, nil, err + } + + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()), + }, + NotBefore: time.Unix(0, 0), + NotAfter: time.Now().Add(time.Hour * 24 * 365 * 100), + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + IsCA: true, + } + + if ip := net.ParseIP(host); ip != nil { + template.IPAddresses = append(template.IPAddresses, ip) + } else { + template.DNSNames = append(template.DNSNames, host) + } + + template.IPAddresses = append(template.IPAddresses, alternateIPs...) + template.DNSNames = append(template.DNSNames, alternateDNS...) + + derBytes, err := x509.CreateCertificate(cryptorand.Reader, &template, &template, &priv.PublicKey, priv) + if err != nil { + return nil, nil, err + } + + // Generate cert + certBuffer := bytes.Buffer{} + if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { + return nil, nil, err + } + + // Generate key + keyBuffer := bytes.Buffer{} + if err := pem.Encode(&keyBuffer, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil { + return nil, nil, err + } + + return certBuffer.Bytes(), keyBuffer.Bytes(), nil +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrate.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrate.go new file mode 100644 index 000000000..7b877db0b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrate.go @@ -0,0 +1,188 @@ +/* +Copyright 2018 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 main + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/golang/glog" + "github.com/spf13/cobra" +) + +const ( + versionFilename = "version.txt" + defaultPort uint64 = 18629 +) + +var ( + migrateCmd = &cobra.Command{ + Short: "Upgrade/downgrade etcd data across multiple versions", + Long: `Upgrade or downgrade etcd data across multiple versions to the target version + +Given a 'bin-dir' directory of etcd and etcdctl binaries, an etcd 'data-dir' with a 'version.txt' file and +a target etcd version, this tool will upgrade or downgrade the etcd data from the version specified in +'version.txt' to the target version. +`, + Run: func(cmd *cobra.Command, args []string) { + runMigrate() + }, + } + opts = migrateOpts{} +) + +type migrateOpts struct { + name string + port uint64 + peerListenUrls string + peerAdvertiseUrls string + binDir string + dataDir string + bundledVersionString string + etcdDataPrefix string + ttlKeysDirectory string + initialCluster string + targetVersion string + targetStorage string + etcdServerArgs string +} + +func main() { + flags := migrateCmd.Flags() + flags.StringVar(&opts.name, "name", "", "etcd cluster member name. Defaults to etcd-{hostname}") + flags.Uint64Var(&opts.port, "port", defaultPort, "etcd client port to use during migration operations. This should be a different port than typically used by etcd to avoid clients accidentally connecting during upgrade/downgrade operations.") + flags.StringVar(&opts.peerListenUrls, "listen-peer-urls", "", "etcd --listen-peer-urls flag, required for HA clusters") + flags.StringVar(&opts.peerAdvertiseUrls, "initial-advertise-peer-urls", "", "etcd --initial-advertise-peer-urls flag, required for HA clusters") + flags.StringVar(&opts.binDir, "bin-dir", "/usr/local/bin", "directory of etcd and etcdctl binaries, must contain etcd- and etcdctl- for each version listed in bindled-versions") + flags.StringVar(&opts.dataDir, "data-dir", "", "etcd data directory of etcd server to migrate") + flags.StringVar(&opts.bundledVersionString, "bundled-versions", "", "comma separated list of etcd binary versions present under the bin-dir") + flags.StringVar(&opts.etcdDataPrefix, "etcd-data-prefix", "/registry", "etcd key prefix under which all objects are kept") + flags.StringVar(&opts.ttlKeysDirectory, "ttl-keys-directory", "", "etcd key prefix under which all keys with TTLs are kept. Defaults to {etcd-data-prefix}/events") + flags.StringVar(&opts.initialCluster, "initial-cluster", "", "comma separated list of name=endpoint pairs. Defaults to etcd-{hostname}=http://localhost:2380") + flags.StringVar(&opts.targetVersion, "target-version", "", "version of etcd to migrate to. Format must be '..'") + flags.StringVar(&opts.targetStorage, "target-storage", "", "storage version of etcd to migrate to, one of: etcd2, etcd3") + flags.StringVar(&opts.etcdServerArgs, "etcd-server-extra-args", "", "additional etcd server args for starting etcd servers during migration steps, --peer-* TLS cert flags should be added for etcd clusters with more than 1 member that use mutual TLS for peer communication.") + migrateCmd.Execute() +} + +// runMigrate validates the command line flags and starts the migration. +func runMigrate() { + if opts.name == "" { + hostname, err := os.Hostname() + if err != nil { + glog.Errorf("Error while getting hostname to supply default --name: %v", err) + os.Exit(1) + } + opts.name = fmt.Sprintf("etcd-%s", hostname) + } + + if opts.ttlKeysDirectory == "" { + opts.ttlKeysDirectory = fmt.Sprintf("%s/events", opts.etcdDataPrefix) + } + if opts.initialCluster == "" { + opts.initialCluster = fmt.Sprintf("%s=http://localhost:2380", opts.name) + } + if opts.targetStorage == "" { + glog.Errorf("--target-storage is required") + os.Exit(1) + } + if opts.targetVersion == "" { + glog.Errorf("--target-version is required") + os.Exit(1) + } + if opts.dataDir == "" { + glog.Errorf("--data-dir is required") + os.Exit(1) + } + if opts.bundledVersionString == "" { + glog.Errorf("--bundled-versions is required") + os.Exit(1) + } + + bundledVersions, err := ParseSupportedVersions(opts.bundledVersionString) + if err != nil { + glog.Errorf("Failed to parse --supported-versions: %v", err) + } + err = validateBundledVersions(bundledVersions, opts.binDir) + if err != nil { + glog.Errorf("Failed to validate that 'etcd-' and 'etcdctl-' binaries exist in --bin-dir '%s' for all --bundled-verions '%s': %v", + opts.binDir, opts.bundledVersionString, err) + os.Exit(1) + } + + target := &EtcdVersionPair{ + version: MustParseEtcdVersion(opts.targetVersion), + storageVersion: MustParseEtcdStorageVersion(opts.targetStorage), + } + + migrate(opts.name, opts.port, opts.peerListenUrls, opts.peerAdvertiseUrls, opts.binDir, opts.dataDir, opts.etcdDataPrefix, opts.ttlKeysDirectory, opts.initialCluster, target, bundledVersions, opts.etcdServerArgs) +} + +// migrate opens or initializes the etcd data directory, configures the migrator, and starts the migration. +func migrate(name string, port uint64, peerListenUrls string, peerAdvertiseUrls string, binPath string, dataDirPath string, etcdDataPrefix string, ttlKeysDirectory string, + initialCluster string, target *EtcdVersionPair, bundledVersions SupportedVersions, etcdServerArgs string) { + + dataDir, err := OpenOrCreateDataDirectory(dataDirPath) + if err != nil { + glog.Errorf("Error opening or creating data directory %s: %v", dataDirPath, err) + os.Exit(1) + } + + cfg := &EtcdMigrateCfg{ + binPath: binPath, + name: name, + port: port, + peerListenUrls: peerListenUrls, + peerAdvertiseUrls: peerAdvertiseUrls, + etcdDataPrefix: etcdDataPrefix, + ttlKeysDirectory: ttlKeysDirectory, + initialCluster: initialCluster, + supportedVersions: bundledVersions, + dataDirectory: dataDirPath, + etcdServerArgs: etcdServerArgs, + } + client, err := NewEtcdMigrateClient(cfg) + if err != nil { + glog.Errorf("Migration failed: %v", err) + os.Exit(1) + } + defer client.Close() + + migrator := &Migrator{cfg, dataDir, client} + + err = migrator.MigrateIfNeeded(target) + if err != nil { + glog.Errorf("Migration failed: %v", err) + os.Exit(1) + } +} + +// validateBundledVersions checks that 'etcd-' and 'etcdctl-' binaries exist in the binDir +// for each version in the bundledVersions list. +func validateBundledVersions(bundledVersions SupportedVersions, binDir string) error { + for _, v := range bundledVersions { + for _, binaryName := range []string{"etcd", "etcdctl"} { + fn := filepath.Join(binDir, fmt.Sprintf("%s-%s", binaryName, v)) + if _, err := os.Stat(fn); err != nil { + return fmt.Errorf("failed to validate '%s' binary exists for bundled-version '%s': %v", fn, v, err) + } + + } + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrate_client.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrate_client.go new file mode 100644 index 000000000..5bb183cda --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrate_client.go @@ -0,0 +1,223 @@ +/* +Copyright 2018 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 main + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + "context" + + clientv2 "github.com/coreos/etcd/client" + "github.com/coreos/etcd/clientv3" + "github.com/golang/glog" +) + +// CombinedEtcdClient provides an implementation of EtcdMigrateClient using a combination of the etcd v2 client, v3 client +// and etcdctl commands called via the shell. +type CombinedEtcdClient struct { + cfg *EtcdMigrateCfg +} + +// NewEtcdMigrateClient creates a new EtcdMigrateClient from the given EtcdMigrateCfg. +func NewEtcdMigrateClient(cfg *EtcdMigrateCfg) (EtcdMigrateClient, error) { + return &CombinedEtcdClient{cfg}, nil +} + +// Close closes the client and releases any resources it holds. +func (e *CombinedEtcdClient) Close() error { + return nil +} + +// SetEtcdVersionKeyValue writes the given version to the etcd 'etcd_version' key. +// If no error is returned, the write was successful, indicating the etcd server is available +// and able to perform consensus writes. +func (e *CombinedEtcdClient) SetEtcdVersionKeyValue(version *EtcdVersion) error { + return e.Put(version, "etcd_version", version.String()) +} + +// Put write a single key value pair to etcd. +func (e *CombinedEtcdClient) Put(version *EtcdVersion, key, value string) error { + if version.Major == 2 { + v2client, err := e.clientV2() + if err != nil { + return err + } + _, err = v2client.Set(context.Background(), key, value, nil) + return err + } + v3client, err := e.clientV3() + if err != nil { + return err + } + defer v3client.Close() + _, err = v3client.KV.Put(context.Background(), key, value) + return err +} + +// Get reads a single value for a given key. +func (e *CombinedEtcdClient) Get(version *EtcdVersion, key string) (string, error) { + if version.Major == 2 { + v2client, err := e.clientV2() + if err != nil { + return "", err + } + resp, err := v2client.Get(context.Background(), key, nil) + if err != nil { + return "", err + } + return resp.Node.Value, nil + } + v3client, err := e.clientV3() + if err != nil { + return "", err + } + defer v3client.Close() + resp, err := v3client.KV.Get(context.Background(), key) + if err != nil { + return "", err + } + kvs := resp.Kvs + if len(kvs) != 1 { + return "", fmt.Errorf("expected exactly one value for key %s but got %d", key, len(kvs)) + } + + return string(kvs[0].Value), nil +} + +func (e *CombinedEtcdClient) clientV2() (clientv2.KeysAPI, error) { + v2client, err := clientv2.New(clientv2.Config{Endpoints: []string{e.endpoint()}}) + if err != nil { + return nil, err + } + return clientv2.NewKeysAPI(v2client), nil +} + +func (e *CombinedEtcdClient) clientV3() (*clientv3.Client, error) { + return clientv3.New(clientv3.Config{Endpoints: []string{e.endpoint()}}) +} + +// Backup creates a backup of an etcd2 data directory at the given backupDir. +func (e *CombinedEtcdClient) Backup(version *EtcdVersion, backupDir string) error { + // We cannot use etcd/client (v2) to make this call. It is implemented in the etcdctl client code. + if version.Major != 2 { + return fmt.Errorf("etcd 2.x required but got version '%s'", version) + } + return e.runEtcdctlCommand(version, + "--debug", + "backup", + "--data-dir", e.cfg.dataDirectory, + "--backup-dir", backupDir, + ) +} + +// Snapshot captures a snapshot from a running etcd3 server and saves it to the given snapshotFile. +// We cannot use etcd/clientv3 to make this call. It is implemented in the etcdctl client code. +func (e *CombinedEtcdClient) Snapshot(version *EtcdVersion, snapshotFile string) error { + if version.Major != 3 { + return fmt.Errorf("etcd 3.x required but got version '%s'", version) + } + return e.runEtcdctlCommand(version, + "--endpoints", e.endpoint(), + "snapshot", "save", snapshotFile, + ) +} + +// Restore restores a given snapshotFile into the data directory specified this clients config. +func (e *CombinedEtcdClient) Restore(version *EtcdVersion, snapshotFile string) error { + // We cannot use etcd/clientv3 to make this call. It is implemented in the etcdctl client code. + if version.Major != 3 { + return fmt.Errorf("etcd 3.x required but got version '%s'", version) + } + return e.runEtcdctlCommand(version, + "snapshot", "restore", snapshotFile, + "--data-dir", e.cfg.dataDirectory, + "--name", e.cfg.name, + "--initial-advertise-peer-urls", e.cfg.peerAdvertiseUrls, + "--initial-cluster", e.cfg.initialCluster, + ) +} + +// Migrate upgrades a 'etcd2' storage version data directory to a 'etcd3' storage version +// data directory. +func (e *CombinedEtcdClient) Migrate(version *EtcdVersion) error { + // We cannot use etcd/clientv3 to make this call as it is implemented in etcd/etcdctl. + if version.Major != 3 { + return fmt.Errorf("etcd 3.x required but got version '%s'", version) + } + return e.runEtcdctlCommand(version, + "migrate", + "--data-dir", e.cfg.dataDirectory, + ) +} + +func (e *CombinedEtcdClient) runEtcdctlCommand(version *EtcdVersion, args ...string) error { + etcdctlCmd := exec.Command(filepath.Join(e.cfg.binPath, fmt.Sprintf("etcdctl-%s", version)), args...) + etcdctlCmd.Env = []string{fmt.Sprintf("ETCDCTL_API=%d", version.Major)} + etcdctlCmd.Stdout = os.Stdout + etcdctlCmd.Stderr = os.Stderr + return etcdctlCmd.Run() +} + +// AttachLease attaches leases of the given leaseDuration to all the etcd objects under +// ttlKeysDirectory specified in this client's config. +func (e *CombinedEtcdClient) AttachLease(leaseDuration time.Duration) error { + ttlKeysPrefix := e.cfg.ttlKeysDirectory + // Make sure that ttlKeysPrefix is ended with "/" so that we only get children "directories". + if !strings.HasSuffix(ttlKeysPrefix, "/") { + ttlKeysPrefix += "/" + } + ctx := context.Background() + + v3client, err := e.clientV3() + if err != nil { + return err + } + defer v3client.Close() + objectsResp, err := v3client.KV.Get(ctx, ttlKeysPrefix, clientv3.WithPrefix()) + if err != nil { + return fmt.Errorf("Error while getting objects to attach to the lease") + } + + lease, err := v3client.Lease.Grant(ctx, int64(leaseDuration/time.Second)) + if err != nil { + return fmt.Errorf("Error while creating lease: %v", err) + } + glog.Infof("Lease with TTL: %v created", lease.TTL) + + glog.Infof("Attaching lease to %d entries", len(objectsResp.Kvs)) + for _, kv := range objectsResp.Kvs { + putResp, err := v3client.KV.Put(ctx, string(kv.Key), string(kv.Value), clientv3.WithLease(lease.ID), clientv3.WithPrevKV()) + if err != nil { + glog.Errorf("Error while attaching lease to: %s", string(kv.Key)) + } + if bytes.Compare(putResp.PrevKv.Value, kv.Value) != 0 { + return fmt.Errorf("concurrent access to key detected when setting lease on %s, expected previous value of %s but got %s", + kv.Key, kv.Value, putResp.PrevKv.Value) + } + } + return nil +} + +func (e *CombinedEtcdClient) endpoint() string { + return fmt.Sprintf("http://127.0.0.1:%d", e.cfg.port) +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrate_server.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrate_server.go new file mode 100644 index 000000000..a1dd1a732 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrate_server.go @@ -0,0 +1,132 @@ +/* +Copyright 2018 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 main + +import ( + "fmt" + "os" + "os/exec" + "strings" + "time" + + "github.com/golang/glog" +) + +// EtcdMigrateServer manages starting and stopping a versioned etcd server binary. +type EtcdMigrateServer struct { + cfg *EtcdMigrateCfg + client EtcdMigrateClient + cmd *exec.Cmd +} + +// NewEtcdMigrateServer creates a EtcdMigrateServer for starting and stopping a etcd server at the given version. +func NewEtcdMigrateServer(cfg *EtcdMigrateCfg, client EtcdMigrateClient) *EtcdMigrateServer { + return &EtcdMigrateServer{cfg: cfg, client: client} +} + +// Start starts an etcd server as a separate process, waits until it has started, and returns a exec.Cmd. +func (r *EtcdMigrateServer) Start(version *EtcdVersion) error { + etcdCmd := exec.Command( + fmt.Sprintf("%s/etcd-%s", r.cfg.binPath, version), + "--name", r.cfg.name, + "--initial-cluster", r.cfg.initialCluster, + "--debug", + "--data-dir", r.cfg.dataDirectory, + "--listen-client-urls", fmt.Sprintf("http://127.0.0.1:%d", r.cfg.port), + "--advertise-client-urls", fmt.Sprintf("http://127.0.0.1:%d", r.cfg.port), + "--listen-peer-urls", r.cfg.peerListenUrls, + "--initial-advertise-peer-urls", r.cfg.peerAdvertiseUrls, + ) + if r.cfg.etcdServerArgs != "" { + extraArgs := strings.Fields(r.cfg.etcdServerArgs) + etcdCmd.Args = append(etcdCmd.Args, extraArgs...) + } + fmt.Printf("Starting server %s: %+v\n", r.cfg.name, etcdCmd.Args) + + etcdCmd.Stdout = os.Stdout + etcdCmd.Stderr = os.Stderr + err := etcdCmd.Start() + if err != nil { + return err + } + interval := time.NewTicker(time.Millisecond * 500) + defer interval.Stop() + done := make(chan bool) + go func() { + time.Sleep(time.Minute * 2) + done <- true + }() + for { + select { + case <-interval.C: + err := r.client.SetEtcdVersionKeyValue(version) + if err != nil { + glog.Infof("Still waiting for etcd to start, current error: %v", err) + // keep waiting + } else { + glog.Infof("Etcd on port %d is up.", r.cfg.port) + r.cmd = etcdCmd + return nil + } + case <-done: + err = etcdCmd.Process.Kill() + if err != nil { + return fmt.Errorf("error killing etcd: %v", err) + } + return fmt.Errorf("Timed out waiting for etcd on port %d", r.cfg.port) + } + } +} + +// Stop terminates the etcd server process. If the etcd server process has not been started +// or is not still running, this returns an error. +func (r *EtcdMigrateServer) Stop() error { + if r.cmd == nil { + return fmt.Errorf("cannot stop EtcdMigrateServer that has not been started") + } + err := r.cmd.Process.Signal(os.Interrupt) + if err != nil { + return fmt.Errorf("error sending SIGINT to etcd for graceful shutdown: %v", err) + } + gracefulWait := time.Minute * 2 + stopped := make(chan bool) + timedout := make(chan bool) + go func() { + time.Sleep(gracefulWait) + timedout <- true + }() + go func() { + select { + case <-stopped: + return + case <-timedout: + glog.Infof("etcd server has not terminated gracefully after %s, killing it.", gracefulWait) + r.cmd.Process.Kill() + return + } + }() + err = r.cmd.Wait() + stopped <- true + if exiterr, ok := err.(*exec.ExitError); ok { + glog.Infof("etcd server stopped (signal: %s)", exiterr.Error()) + // stopped + } else if err != nil { + return fmt.Errorf("error waiting for etcd to stop: %v", err) + } + glog.Infof("Stopped etcd server %s", r.cfg.name) + return nil +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrator.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrator.go new file mode 100644 index 000000000..e1e64f182 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/migrator.go @@ -0,0 +1,258 @@ +/* +Copyright 2018 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 main + +import ( + "fmt" + "os" + "os/exec" + "time" + + "github.com/blang/semver" + "github.com/golang/glog" +) + +// EtcdMigrateCfg provides all configuration required to perform etcd data upgrade/downgrade migrations. +type EtcdMigrateCfg struct { + binPath string + name string + initialCluster string + port uint64 + peerListenUrls string + peerAdvertiseUrls string + etcdDataPrefix string + ttlKeysDirectory string + supportedVersions SupportedVersions + dataDirectory string + etcdServerArgs string +} + +// EtcdMigrateClient defines the etcd client operations required to perform migrations. +type EtcdMigrateClient interface { + SetEtcdVersionKeyValue(version *EtcdVersion) error + Get(version *EtcdVersion, key string) (string, error) + Put(version *EtcdVersion, key, value string) error + Backup(version *EtcdVersion, backupDir string) error + Snapshot(version *EtcdVersion, snapshotFile string) error + Restore(version *EtcdVersion, snapshotFile string) error + Migrate(version *EtcdVersion) error + AttachLease(leaseDuration time.Duration) error + Close() error +} + +// Migrator manages etcd data migrations. +type Migrator struct { + cfg *EtcdMigrateCfg // TODO: don't wire this directly in + dataDirectory *DataDirectory + client EtcdMigrateClient +} + +// MigrateIfNeeded upgrades or downgrades the etcd data directory to the given target version. +func (m *Migrator) MigrateIfNeeded(target *EtcdVersionPair) error { + glog.Infof("Starting migration to %s", target) + err := m.dataDirectory.Initialize(target) + if err != nil { + return fmt.Errorf("failed to initialize data directory %s: %v", m.dataDirectory.path, err) + } + + var current *EtcdVersionPair + vfExists, err := m.dataDirectory.versionFile.Exists() + if err != nil { + return err + } + if vfExists { + current, err = m.dataDirectory.versionFile.Read() + if err != nil { + return err + } + } else { + return fmt.Errorf("existing data directory '%s' is missing version.txt file, unable to migrate", m.dataDirectory.path) + } + + for { + glog.Infof("Converging current version '%s' to target version '%s'", current, target) + currentNextMinorVersion := &EtcdVersion{Version: semver.Version{Major: current.version.Major, Minor: current.version.Minor + 1}} + switch { + case current.version.MajorMinorEquals(target.version) || currentNextMinorVersion.MajorMinorEquals(target.version): + glog.Infof("current version '%s' equals or is one minor version previous of target version '%s' - migration complete", current, target) + err = m.dataDirectory.versionFile.Write(target) + if err != nil { + return fmt.Errorf("failed to write version.txt to '%s': %v", m.dataDirectory.path, err) + } + return nil + case current.storageVersion == storageEtcd2 && target.storageVersion == storageEtcd3: + glog.Infof("upgrading from etcd2 storage to etcd3 storage") + current, err = m.etcd2ToEtcd3Upgrade(current, target) + case current.version.Major == 3 && target.version.Major == 2: + glog.Infof("downgrading from etcd 3.x to 2.x") + current, err = m.rollbackToEtcd2(current, target) + case current.version.Major == target.version.Major && current.version.Minor < target.version.Minor: + stepVersion := m.cfg.supportedVersions.NextVersionPair(current) + glog.Infof("upgrading etcd from %s to %s", current, stepVersion) + current, err = m.minorVersionUpgrade(current, stepVersion) + case current.version.Major == 3 && target.version.Major == 3 && current.version.Minor > target.version.Minor: + glog.Infof("rolling etcd back from %s to %s", current, target) + current, err = m.rollbackEtcd3MinorVersion(current, target) + } + if err != nil { + return err + } + } +} + +func (m *Migrator) backupEtcd2(current *EtcdVersion) error { + backupDir := fmt.Sprintf("%s/%s", m.dataDirectory, "migration-backup") + glog.Infof("Backup etcd before starting migration") + err := os.Mkdir(backupDir, 0666) + if err != nil { + return fmt.Errorf("failed to create backup directory before starting migration: %v", err) + } + m.client.Backup(current, backupDir) + glog.Infof("Backup done in %s", backupDir) + return nil +} + +func (m *Migrator) rollbackEtcd3MinorVersion(current *EtcdVersionPair, target *EtcdVersionPair) (*EtcdVersionPair, error) { + if target.version.Minor != current.version.Minor-1 { + return nil, fmt.Errorf("rollback from %s to %s not supported, only rollbacks to the previous minor version are supported", current.version, target.version) + } + + glog.Infof("Performing etcd %s -> %s rollback", current.version, target.version) + err := m.dataDirectory.Backup() + if err != nil { + return nil, err + } + + snapshotFilename := fmt.Sprintf("%s.snapshot.db", m.dataDirectory.path) + err = os.Remove(snapshotFilename) + if err != nil && !os.IsNotExist(err) { + return nil, fmt.Errorf("failed to clean snapshot file before rollback: %v", err) + } + + // Start current version of etcd. + runner := m.newServer() + glog.Infof("Starting etcd version %s to capture rollback snapshot.", current.version) + err = runner.Start(current.version) + if err != nil { + glog.Fatalf("Unable to automatically downgrade etcd: starting etcd version %s to capture rollback snapshot failed: %v", current.version, err) + return nil, err + } + + glog.Infof("Snapshotting etcd %s to %s", current.version, snapshotFilename) + err = m.client.Snapshot(current.version, snapshotFilename) + if err != nil { + return nil, err + } + + err = runner.Stop() + if err != nil { + return nil, err + } + + glog.Infof("Backing up data before rolling back") + backupDir := fmt.Sprintf("%s.bak", m.dataDirectory) + err = os.RemoveAll(backupDir) + if err != nil { + return nil, err + } + origInfo, err := os.Stat(m.dataDirectory.path) + if err != nil { + return nil, err + } + err = exec.Command("mv", m.dataDirectory.path, backupDir).Run() + if err != nil { + return nil, err + } + + glog.Infof("Restoring etcd %s from %s", target.version, snapshotFilename) + err = m.client.Restore(target.version, snapshotFilename) + if err != nil { + return nil, err + } + err = os.Chmod(m.dataDirectory.path, origInfo.Mode()) + if err != nil { + return nil, err + } + + return target, nil +} + +func (m *Migrator) rollbackToEtcd2(current *EtcdVersionPair, target *EtcdVersionPair) (*EtcdVersionPair, error) { + if !(current.version.Major == 3 && current.version.Minor == 0 && target.version.Major == 2 && target.version.Minor == 2) { + return nil, fmt.Errorf("etcd3 -> etcd2 downgrade is supported only between 3.0.x and 2.2.x, got current %s target %s", current, target) + } + glog.Infof("Backup and remove all existing v2 data") + err := m.dataDirectory.Backup() + if err != nil { + return nil, err + } + err = RollbackV3ToV2(m.dataDirectory.path, time.Hour) + if err != nil { + return nil, fmt.Errorf("rollback to etcd 2.x failed: %v", err) + } + return target, nil + +} + +func (m *Migrator) etcd2ToEtcd3Upgrade(current *EtcdVersionPair, target *EtcdVersionPair) (*EtcdVersionPair, error) { + if current.storageVersion != storageEtcd2 || target.version.Major != 3 || target.storageVersion != storageEtcd3 { + return nil, fmt.Errorf("etcd2 to etcd3 upgrade is supported only for x.x.x/etcd2 to 3.0.x/etcd3, got current %s target %s", current, target) + } + runner := m.newServer() + + glog.Infof("Performing etcd2 -> etcd3 migration") + err := m.client.Migrate(target.version) + if err != nil { + return nil, err + } + glog.Infof("Attaching leases to TTL entries") + + // Now attach lease to all keys. + // To do it, we temporarily start etcd on a random port (so that + // apiserver actually cannot access it). + err = runner.Start(target.version) + if err != nil { + return nil, err + } + defer func() { + err = runner.Stop() + }() + + // Create a lease and attach all keys to it. + err = m.client.AttachLease(1 * time.Hour) + if err != nil { + return nil, err + } + + return target, err +} + +func (m *Migrator) minorVersionUpgrade(current *EtcdVersionPair, target *EtcdVersionPair) (*EtcdVersionPair, error) { + runner := m.newServer() + + // Do the migration step, by just starting etcd in the target version. + err := runner.Start(target.version) + if err != nil { + return nil, err + } + err = runner.Stop() + return target, err +} + +func (m *Migrator) newServer() *EtcdMigrateServer { + return NewEtcdMigrateServer(m.cfg, m.client) +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/rollback_v2.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/rollback_v2.go new file mode 100644 index 000000000..ce3cfdfbd --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/rollback_v2.go @@ -0,0 +1,328 @@ +/* +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 main + +import ( + "encoding/json" + "os" + "path" + "strconv" + "strings" + "time" + + // Uncomment when you want to rollback to 2.2.1 version. + oldwal "k8s.io/kubernetes/third_party/forked/etcd221/wal" + // Uncomment when you want to rollback to 2.3.7 version. + // oldwal "k8s.io/kubernetes/third_party/forked/etcd237/wal" + + "github.com/coreos/etcd/etcdserver" + pb "github.com/coreos/etcd/etcdserver/etcdserverpb" + "github.com/coreos/etcd/etcdserver/membership" + "github.com/coreos/etcd/mvcc/backend" + "github.com/coreos/etcd/mvcc/mvccpb" + "github.com/coreos/etcd/pkg/pbutil" + "github.com/coreos/etcd/pkg/types" + "github.com/coreos/etcd/raft/raftpb" + "github.com/coreos/etcd/snap" + "github.com/coreos/etcd/store" + "github.com/coreos/etcd/wal" + "github.com/coreos/etcd/wal/walpb" + "github.com/coreos/go-semver/semver" + "github.com/golang/glog" +) + +const rollbackVersion = "2.2.0" + +// RollbackV3ToV2 rolls back an etcd 3.0.x data directory to the 2.x.x version specified by rollbackVersion. +func RollbackV3ToV2(migrateDatadir string, ttl time.Duration) error { + dbpath := path.Join(migrateDatadir, "member", "snap", "db") + glog.Infof("Rolling db file %s back to etcd 2.x", dbpath) + + // etcd3 store backend. We will use it to parse v3 data files and extract information. + be := backend.NewDefaultBackend(dbpath) + tx := be.BatchTx() + + // etcd2 store backend. We will use v3 data to update this and then save snapshot to disk. + st := store.New(etcdserver.StoreClusterPrefix, etcdserver.StoreKeysPrefix) + expireTime := time.Now().Add(ttl) + + tx.Lock() + err := tx.UnsafeForEach([]byte("key"), func(k, v []byte) error { + kv := &mvccpb.KeyValue{} + kv.Unmarshal(v) + + // This is compact key. + if !strings.HasPrefix(string(kv.Key), "/") { + return nil + } + + ttlOpt := store.TTLOptionSet{} + if kv.Lease != 0 { + ttlOpt = store.TTLOptionSet{ExpireTime: expireTime} + } + + if !isTombstone(k) { + sk := path.Join(strings.Trim(etcdserver.StoreKeysPrefix, "/"), string(kv.Key)) + _, err := st.Set(sk, false, string(kv.Value), ttlOpt) + if err != nil { + return err + } + } else { + st.Delete(string(kv.Key), false, false) + } + + return nil + }) + if err != nil { + return err + } + tx.Unlock() + + if err := traverseAndDeleteEmptyDir(st, "/"); err != nil { + return err + } + + // rebuild cluster state. + metadata, hardstate, oldSt, err := rebuild(migrateDatadir) + if err != nil { + return err + } + + // In the following, it's low level logic that saves metadata and data into v2 snapshot. + backupPath := migrateDatadir + ".rollback.backup" + if err := os.Rename(migrateDatadir, backupPath); err != nil { + return err + } + if err := os.MkdirAll(path.Join(migrateDatadir, "member", "snap"), 0777); err != nil { + return err + } + walDir := path.Join(migrateDatadir, "member", "wal") + + w, err := oldwal.Create(walDir, metadata) + if err != nil { + return err + } + err = w.SaveSnapshot(walpb.Snapshot{Index: hardstate.Commit, Term: hardstate.Term}) + w.Close() + if err != nil { + return err + } + + event, err := oldSt.Get(etcdserver.StoreClusterPrefix, true, false) + if err != nil { + return err + } + // nodes (members info) for ConfState + nodes := []uint64{} + traverseMetadata(event.Node, func(n *store.NodeExtern) { + if n.Key != etcdserver.StoreClusterPrefix { + // update store metadata + v := "" + if !n.Dir { + v = *n.Value + } + if n.Key == path.Join(etcdserver.StoreClusterPrefix, "version") { + v = rollbackVersion + } + if _, err := st.Set(n.Key, n.Dir, v, store.TTLOptionSet{}); err != nil { + glog.Error(err) + } + + // update nodes + fields := strings.Split(n.Key, "/") + if len(fields) == 4 && fields[2] == "members" { + nodeID, err := strconv.ParseUint(fields[3], 16, 64) + if err != nil { + glog.Fatalf("failed to parse member ID (%s): %v", fields[3], err) + } + nodes = append(nodes, nodeID) + } + } + }) + + data, err := st.Save() + if err != nil { + return err + } + raftSnap := raftpb.Snapshot{ + Data: data, + Metadata: raftpb.SnapshotMetadata{ + Index: hardstate.Commit, + Term: hardstate.Term, + ConfState: raftpb.ConfState{ + Nodes: nodes, + }, + }, + } + snapshotter := snap.New(path.Join(migrateDatadir, "member", "snap")) + if err := snapshotter.SaveSnap(raftSnap); err != nil { + return err + } + glog.Infof("Finished successfully") + return nil +} + +func traverseMetadata(head *store.NodeExtern, handleFunc func(*store.NodeExtern)) { + q := []*store.NodeExtern{head} + + for len(q) > 0 { + n := q[0] + q = q[1:] + + handleFunc(n) + + for _, next := range n.Nodes { + q = append(q, next) + } + } +} + +const ( + revBytesLen = 8 + 1 + 8 + markedRevBytesLen = revBytesLen + 1 + markBytePosition = markedRevBytesLen - 1 + + markTombstone byte = 't' +) + +func isTombstone(b []byte) bool { + return len(b) == markedRevBytesLen && b[markBytePosition] == markTombstone +} + +func traverseAndDeleteEmptyDir(st store.Store, dir string) error { + e, err := st.Get(dir, true, false) + if err != nil { + return err + } + if len(e.Node.Nodes) == 0 { + st.Delete(dir, true, true) + return nil + } + for _, node := range e.Node.Nodes { + if !node.Dir { + glog.V(2).Infof("key: %s", node.Key[len(etcdserver.StoreKeysPrefix):]) + } else { + err := traverseAndDeleteEmptyDir(st, node.Key) + if err != nil { + return err + } + } + } + return nil +} + +func rebuild(datadir string) ([]byte, *raftpb.HardState, store.Store, error) { + waldir := path.Join(datadir, "member", "wal") + snapdir := path.Join(datadir, "member", "snap") + + ss := snap.New(snapdir) + snapshot, err := ss.Load() + if err != nil && err != snap.ErrNoSnapshot { + return nil, nil, nil, err + } + + var walsnap walpb.Snapshot + if snapshot != nil { + walsnap.Index, walsnap.Term = snapshot.Metadata.Index, snapshot.Metadata.Term + } + + w, err := wal.OpenForRead(waldir, walsnap) + if err != nil { + return nil, nil, nil, err + } + defer w.Close() + + meta, hardstate, ents, err := w.ReadAll() + if err != nil { + return nil, nil, nil, err + } + + st := store.New(etcdserver.StoreClusterPrefix, etcdserver.StoreKeysPrefix) + if snapshot != nil { + err := st.Recovery(snapshot.Data) + if err != nil { + return nil, nil, nil, err + } + } + + cluster := membership.NewCluster("") + cluster.SetStore(st) + cluster.Recover(func(*semver.Version) {}) + + applier := etcdserver.NewApplierV2(st, cluster) + for _, ent := range ents { + if ent.Type == raftpb.EntryConfChange { + var cc raftpb.ConfChange + pbutil.MustUnmarshal(&cc, ent.Data) + switch cc.Type { + case raftpb.ConfChangeAddNode: + m := new(membership.Member) + if err := json.Unmarshal(cc.Context, m); err != nil { + return nil, nil, nil, err + } + cluster.AddMember(m) + case raftpb.ConfChangeRemoveNode: + id := types.ID(cc.NodeID) + cluster.RemoveMember(id) + case raftpb.ConfChangeUpdateNode: + m := new(membership.Member) + if err := json.Unmarshal(cc.Context, m); err != nil { + return nil, nil, nil, err + } + cluster.UpdateRaftAttributes(m.ID, m.RaftAttributes) + } + continue + } + + var raftReq pb.InternalRaftRequest + if !pbutil.MaybeUnmarshal(&raftReq, ent.Data) { // backward compatible + var r pb.Request + pbutil.MustUnmarshal(&r, ent.Data) + applyRequest(&r, applier) + } else { + if raftReq.V2 != nil { + req := raftReq.V2 + applyRequest(req, applier) + } + } + } + + return meta, &hardstate, st, nil +} + +func toTTLOptions(r *pb.Request) store.TTLOptionSet { + refresh, _ := pbutil.GetBool(r.Refresh) + ttlOptions := store.TTLOptionSet{Refresh: refresh} + if r.Expiration != 0 { + ttlOptions.ExpireTime = time.Unix(0, r.Expiration) + } + return ttlOptions +} + +func applyRequest(r *pb.Request, applyV2 etcdserver.ApplierV2) { + toTTLOptions(r) + switch r.Method { + case "PUT": + applyV2.Put(r) + case "DELETE": + applyV2.Delete(r) + case "POST", "QGET", "SYNC": + return + default: + glog.Fatal("unknown command") + } +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/testdata/datadir_with_version/version.txt b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/testdata/datadir_with_version/version.txt new file mode 100644 index 000000000..d557c0269 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/testdata/datadir_with_version/version.txt @@ -0,0 +1 @@ +3.1.12/etcd3 diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/secret.json b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/testdata/datadir_without_version/.placeholder similarity index 100% rename from vendor/k8s.io/kubernetes/examples/openshift-origin/secret.json rename to vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/testdata/datadir_without_version/.placeholder diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/versions.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/versions.go new file mode 100644 index 000000000..5243330ae --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/versions.go @@ -0,0 +1,198 @@ +/* +Copyright 2018 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 main + +import ( + "fmt" + "strings" + + "github.com/blang/semver" +) + +// EtcdVersion specifies an etcd server binaries SemVer. +type EtcdVersion struct { + semver.Version +} + +// ParseEtcdVersion parses a SemVer string to an EtcdVersion. +func ParseEtcdVersion(s string) (*EtcdVersion, error) { + v, err := semver.Make(s) + if err != nil { + return nil, err + } + return &EtcdVersion{v}, nil +} + +// MustParseEtcdVersion parses a SemVer string to an EtcdVersion and panics if the parse fails. +func MustParseEtcdVersion(s string) *EtcdVersion { + return &EtcdVersion{semver.MustParse(s)} +} + +// String returns the version in SemVer string format. +func (v *EtcdVersion) String() string { + return v.Version.String() +} + +// Equals returns true if the versions are exactly equal. +func (v *EtcdVersion) Equals(o *EtcdVersion) bool { + return v.Version.Equals(o.Version) +} + +// MajorMinorEquals returns true if the major and minor parts of the versions are equal; +// if only patch versions differ, this returns true. +func (v *EtcdVersion) MajorMinorEquals(o *EtcdVersion) bool { + return v.Major == o.Major && v.Minor == o.Minor +} + +// EtcdStorageVersion identifies the storage version of an etcd data directory. +type EtcdStorageVersion int + +const ( + storageUnknown EtcdStorageVersion = iota + storageEtcd2 + storageEtcd3 +) + +// ParseEtcdStorageVersion parses an etcd storage version string to an EtcdStorageVersion. +func ParseEtcdStorageVersion(s string) (EtcdStorageVersion, error) { + switch s { + case "etcd2": + return storageEtcd2, nil + case "etcd3": + return storageEtcd3, nil + default: + return storageUnknown, fmt.Errorf("unrecognized storage version: %s", s) + } +} + +// MustParseEtcdStorageVersion parses an etcd storage version string to an EtcdStorageVersion and +// panics if the parse fails. +func MustParseEtcdStorageVersion(s string) EtcdStorageVersion { + version, err := ParseEtcdStorageVersion(s) + if err != nil { + panic(err) + } + return version +} + +// String returns the text representation of the EtcdStorageVersion, 'etcd2' or 'etcd3'. +func (v EtcdStorageVersion) String() string { + switch v { + case storageEtcd2: + return "etcd2" + case storageEtcd3: + return "etcd3" + default: + panic(fmt.Sprintf("enum value %d missing from EtcdStorageVersion String() function", v)) + } +} + +// EtcdVersionPair is composed of an etcd version and storage version. +type EtcdVersionPair struct { + version *EtcdVersion + storageVersion EtcdStorageVersion +} + +// ParseEtcdVersionPair parses a "/" string to an EtcdVersionPair. +func ParseEtcdVersionPair(s string) (*EtcdVersionPair, error) { + parts := strings.Split(s, "/") + if len(parts) != 2 { + return nil, fmt.Errorf("Malformed version file, expected ../ but got %s", s) + } + version, err := ParseEtcdVersion(parts[0]) + if err != nil { + return nil, err + } + storageVersion, err := ParseEtcdStorageVersion(parts[1]) + if err != nil { + return nil, err + } + return &EtcdVersionPair{version, storageVersion}, nil +} + +// MustParseEtcdVersionPair parses a "/" string to an EtcdVersionPair +// or panics if the parse fails. +func MustParseEtcdVersionPair(s string) *EtcdVersionPair { + pair, err := ParseEtcdVersionPair(s) + if err != nil { + panic(err) + } + return pair +} + +// String returns "/" string of the EtcdVersionPair. +func (vp *EtcdVersionPair) String() string { + return fmt.Sprintf("%s/%s", vp.version, vp.storageVersion) +} + +// Equals returns true if both the versions and storage versions are exactly equal. +func (vp *EtcdVersionPair) Equals(o *EtcdVersionPair) bool { + return vp.version.Equals(o.version) && vp.storageVersion == o.storageVersion +} + +// SupportedVersions provides a list of etcd versions that are "supported" for some purpose. +// The list must be sorted from lowest semantic version to high. +type SupportedVersions []*EtcdVersion + +// NextVersion returns the next supported version after the given current version, or nil if no +// next version exists. +func (sv SupportedVersions) NextVersion(current *EtcdVersion) *EtcdVersion { + var nextVersion *EtcdVersion + for i, supportedVersion := range sv { + if current.MajorMinorEquals(supportedVersion) && len(sv) > i+1 { + nextVersion = sv[i+1] + } + } + return nextVersion +} + +// NextVersionPair returns the next supported version after the given current version and infers +// the storage version from the major version part of the next version. +func (sv SupportedVersions) NextVersionPair(current *EtcdVersionPair) *EtcdVersionPair { + nextVersion := sv.NextVersion(current.version) + if nextVersion == nil { + return nil + } + storageVersion := storageEtcd3 + if nextVersion.Major == 2 { + storageVersion = storageEtcd2 + } + return &EtcdVersionPair{version: nextVersion, storageVersion: storageVersion} +} + +// ParseSupportedVersions parses a comma separated list of etcd versions. +func ParseSupportedVersions(s string) (SupportedVersions, error) { + var err error + list := strings.Split(s, ",") + versions := make(SupportedVersions, len(list)) + for i, v := range list { + versions[i], err = ParseEtcdVersion(strings.TrimSpace(v)) + if err != nil { + return nil, err + } + } + return versions, nil +} + +// MustParseSupportedVersions parses a comma separated list of etcd versions or panics if the parse fails. +func MustParseSupportedVersions(s string) SupportedVersions { + versions, err := ParseSupportedVersions(s) + if err != nil { + panic(err) + } + return versions +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/versions_test.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/versions_test.go new file mode 100644 index 000000000..add39c097 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/etcd/migrate/versions_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2018 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 main + +import ( + "testing" + + "github.com/blang/semver" +) + +func TestSerializeEtcdVersionPair(t *testing.T) { + cases := []struct { + versionTxt string + version *EtcdVersionPair + match bool + }{ + {"3.1.2/etcd3", &EtcdVersionPair{&EtcdVersion{semver.MustParse("3.1.2")}, storageEtcd3}, true}, + {"2.2.1/etcd2", &EtcdVersionPair{&EtcdVersion{semver.MustParse("2.2.1")}, storageEtcd2}, true}, + {"1.1.1-rc.0/etcd3", &EtcdVersionPair{&EtcdVersion{semver.MustParse("1.1.1-rc.0")}, storageEtcd3}, true}, + {"10.100.1000/etcd3", &EtcdVersionPair{&EtcdVersion{semver.MustParse("10.100.1000")}, storageEtcd3}, true}, + + {"2.2.2/etcd2", &EtcdVersionPair{&EtcdVersion{semver.MustParse("2.2.1")}, storageEtcd2}, false}, + {"2.2.1/etcd3", &EtcdVersionPair{&EtcdVersion{semver.MustParse("2.2.1")}, storageEtcd2}, false}, + } + + for _, c := range cases { + vp, err := ParseEtcdVersionPair(c.versionTxt) + if err != nil { + t.Errorf("Failed to parse '%s': %v", c.versionTxt, err) + } + if vp.Equals(c.version) != c.match { + t.Errorf("Expected '%s' to be parsed as '%+v', got '%+v'", c.versionTxt, c.version, vp) + } + if vp.String() != c.versionTxt { + t.Errorf("Expected round trip serialization back to '%s', got '%s'", c.versionTxt, vp.String()) + } + } + + unparsables := []string{ + "1.1/etcd3", + "1.1.1.1/etcd3", + "1.1.1/etcd4", + } + for _, unparsable := range unparsables { + vp, err := ParseEtcdVersionPair(unparsable) + if err == nil { + t.Errorf("Should have failed to parse '%s' but got '%s'", unparsable, vp) + } + } +} + +func TestMajorMinorEquals(t *testing.T) { + cases := []struct { + first *EtcdVersion + second *EtcdVersion + match bool + }{ + {&EtcdVersion{semver.Version{Major: 3, Minor: 1, Patch: 2}}, &EtcdVersion{semver.Version{Major: 3, Minor: 1, Patch: 0}}, true}, + {&EtcdVersion{semver.Version{Major: 3, Minor: 1, Patch: 2}}, &EtcdVersion{semver.Version{Major: 3, Minor: 1, Patch: 2}}, true}, + + {&EtcdVersion{semver.Version{Major: 3, Minor: 0, Patch: 0}}, &EtcdVersion{semver.Version{Major: 3, Minor: 1, Patch: 0}}, false}, + {&EtcdVersion{semver.Version{Major: 2, Minor: 0, Patch: 0}}, &EtcdVersion{semver.Version{Major: 3, Minor: 0, Patch: 0}}, false}, + } + + for _, c := range cases { + if c.first.MajorMinorEquals(c.second) != c.match { + t.Errorf("Expected (%+v == %+v) == %t, got %t", c.first, c.second, c.match, !c.match) + } + } +} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/rollback/BUILD b/vendor/k8s.io/kubernetes/cluster/images/etcd/rollback/BUILD deleted file mode 100644 index 5af9d7151..000000000 --- a/vendor/k8s.io/kubernetes/cluster/images/etcd/rollback/BUILD +++ /dev/null @@ -1,48 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "rollback", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["rollback.go"], - importpath = "k8s.io/kubernetes/cluster/images/etcd/rollback", - deps = [ - "//third_party/forked/etcd221/wal:go_default_library", - "//vendor/github.com/coreos/etcd/etcdserver:go_default_library", - "//vendor/github.com/coreos/etcd/etcdserver/etcdserverpb:go_default_library", - "//vendor/github.com/coreos/etcd/etcdserver/membership:go_default_library", - "//vendor/github.com/coreos/etcd/mvcc/backend:go_default_library", - "//vendor/github.com/coreos/etcd/mvcc/mvccpb:go_default_library", - "//vendor/github.com/coreos/etcd/pkg/pbutil:go_default_library", - "//vendor/github.com/coreos/etcd/pkg/types:go_default_library", - "//vendor/github.com/coreos/etcd/raft/raftpb:go_default_library", - "//vendor/github.com/coreos/etcd/snap:go_default_library", - "//vendor/github.com/coreos/etcd/store:go_default_library", - "//vendor/github.com/coreos/etcd/wal:go_default_library", - "//vendor/github.com/coreos/etcd/wal/walpb:go_default_library", - "//vendor/github.com/coreos/go-semver/semver:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/rollback/README.md b/vendor/k8s.io/kubernetes/cluster/images/etcd/rollback/README.md deleted file mode 100644 index 66a6c157d..000000000 --- a/vendor/k8s.io/kubernetes/cluster/images/etcd/rollback/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Rollback workflow - -Build it in this directory. -Make sure you have etcd dependency ready. Last time we use etcd v3.0.7. -``` -$ go build . -``` - - -Run it: -``` -$ ./rollback2 --data-dir $ETCD_DATA_DIR --ttl 1h -``` - -This will rollback KV pairs from v3 into v2. -If a key was attached to a lease before, it will be created with given TTL (default to 1h). - -On success, it will print at the end: -``` -Finished successfully -``` - -Repeat this on all etcd members. - -You can do simple check on keys (if any exists): -``` -etcdctl ls / -``` - -Important Note ------- - -This tool isn't recommended to use if any problem comes up in etcd3 backend. -Please report bugs and we will fix it soon. - -If it's still preferred to run this tool, please backup all your data beforehand. -This tool will also back up datadir to same path with ".rollback.backup" suffix. - -Caveats: -- The tool doesn't preserve versions of keys. -- If any v2 data exists before rollback, they will be wiped out. -- v3 data only exists in the backup after successful rollback. - - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/cluster/images/etcd/rollback/README.md?pixel)]() \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/rollback/rollback.go b/vendor/k8s.io/kubernetes/cluster/images/etcd/rollback/rollback.go deleted file mode 100644 index cfb3bea71..000000000 --- a/vendor/k8s.io/kubernetes/cluster/images/etcd/rollback/rollback.go +++ /dev/null @@ -1,336 +0,0 @@ -/* -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 main - -import ( - "encoding/json" - "flag" - "fmt" - "os" - "path" - "strconv" - "strings" - "time" - - // Uncomment when you want to rollback to 2.2.1 version. - oldwal "k8s.io/kubernetes/third_party/forked/etcd221/wal" - // Uncomment when you want to rollback to 2.3.7 version. - // oldwal "k8s.io/kubernetes/third_party/forked/etcd237/wal" - - "github.com/coreos/etcd/etcdserver" - pb "github.com/coreos/etcd/etcdserver/etcdserverpb" - "github.com/coreos/etcd/etcdserver/membership" - "github.com/coreos/etcd/mvcc/backend" - "github.com/coreos/etcd/mvcc/mvccpb" - "github.com/coreos/etcd/pkg/pbutil" - "github.com/coreos/etcd/pkg/types" - "github.com/coreos/etcd/raft/raftpb" - "github.com/coreos/etcd/snap" - "github.com/coreos/etcd/store" - "github.com/coreos/etcd/wal" - "github.com/coreos/etcd/wal/walpb" - "github.com/coreos/go-semver/semver" - "github.com/golang/glog" -) - -const rollbackVersion = "2.2.0" - -var ( - migrateDatadir = flag.String("data-dir", "", "Path to the data directory") - ttl = flag.Duration("ttl", time.Hour, "TTL of event keys (default 1 hour)") -) - -func main() { - flag.Parse() - if len(*migrateDatadir) == 0 { - glog.Fatal("need to set '--data-dir'") - } - dbpath := path.Join(*migrateDatadir, "member", "snap", "db") - - // etcd3 store backend. We will use it to parse v3 data files and extract information. - be := backend.NewDefaultBackend(dbpath) - tx := be.BatchTx() - - // etcd2 store backend. We will use v3 data to update this and then save snapshot to disk. - st := store.New(etcdserver.StoreClusterPrefix, etcdserver.StoreKeysPrefix) - expireTime := time.Now().Add(*ttl) - - tx.Lock() - err := tx.UnsafeForEach([]byte("key"), func(k, v []byte) error { - kv := &mvccpb.KeyValue{} - kv.Unmarshal(v) - - // This is compact key. - if !strings.HasPrefix(string(kv.Key), "/") { - return nil - } - - ttlOpt := store.TTLOptionSet{} - if kv.Lease != 0 { - ttlOpt = store.TTLOptionSet{ExpireTime: expireTime} - } - - if !isTombstone(k) { - sk := path.Join(strings.Trim(etcdserver.StoreKeysPrefix, "/"), string(kv.Key)) - _, err := st.Set(sk, false, string(kv.Value), ttlOpt) - if err != nil { - return err - } - } else { - st.Delete(string(kv.Key), false, false) - } - - return nil - }) - if err != nil { - glog.Fatal(err) - } - tx.Unlock() - - if err := traverseAndDeleteEmptyDir(st, "/"); err != nil { - glog.Fatal(err) - } - - // rebuild cluster state. - metadata, hardstate, oldSt, err := rebuild(*migrateDatadir) - if err != nil { - glog.Fatal(err) - } - - // In the following, it's low level logic that saves metadata and data into v2 snapshot. - backupPath := *migrateDatadir + ".rollback.backup" - if err := os.Rename(*migrateDatadir, backupPath); err != nil { - glog.Fatal(err) - } - if err := os.MkdirAll(path.Join(*migrateDatadir, "member", "snap"), 0700); err != nil { - glog.Fatal(err) - } - walDir := path.Join(*migrateDatadir, "member", "wal") - - w, err := oldwal.Create(walDir, metadata) - if err != nil { - glog.Fatal(err) - } - err = w.SaveSnapshot(walpb.Snapshot{Index: hardstate.Commit, Term: hardstate.Term}) - if err != nil { - glog.Fatal(err) - } - w.Close() - - event, err := oldSt.Get(etcdserver.StoreClusterPrefix, true, false) - if err != nil { - glog.Fatal(err) - } - // nodes (members info) for ConfState - nodes := []uint64{} - traverseMetadata(event.Node, func(n *store.NodeExtern) { - if n.Key != etcdserver.StoreClusterPrefix { - // update store metadata - v := "" - if !n.Dir { - v = *n.Value - } - if n.Key == path.Join(etcdserver.StoreClusterPrefix, "version") { - v = rollbackVersion - } - if _, err := st.Set(n.Key, n.Dir, v, store.TTLOptionSet{}); err != nil { - glog.Fatal(err) - } - - // update nodes - fields := strings.Split(n.Key, "/") - if len(fields) == 4 && fields[2] == "members" { - nodeID, err := strconv.ParseUint(fields[3], 16, 64) - if err != nil { - glog.Fatalf("failed to parse member ID (%s): %v", fields[3], err) - } - nodes = append(nodes, nodeID) - } - } - }) - - data, err := st.Save() - if err != nil { - glog.Fatal(err) - } - raftSnap := raftpb.Snapshot{ - Data: data, - Metadata: raftpb.SnapshotMetadata{ - Index: hardstate.Commit, - Term: hardstate.Term, - ConfState: raftpb.ConfState{ - Nodes: nodes, - }, - }, - } - snapshotter := snap.New(path.Join(*migrateDatadir, "member", "snap")) - if err := snapshotter.SaveSnap(raftSnap); err != nil { - glog.Fatal(err) - } - fmt.Println("Finished successfully") -} - -func traverseMetadata(head *store.NodeExtern, handleFunc func(*store.NodeExtern)) { - q := []*store.NodeExtern{head} - - for len(q) > 0 { - n := q[0] - q = q[1:] - - handleFunc(n) - - for _, next := range n.Nodes { - q = append(q, next) - } - } -} - -const ( - revBytesLen = 8 + 1 + 8 - markedRevBytesLen = revBytesLen + 1 - markBytePosition = markedRevBytesLen - 1 - - markTombstone byte = 't' -) - -func isTombstone(b []byte) bool { - return len(b) == markedRevBytesLen && b[markBytePosition] == markTombstone -} - -func traverseAndDeleteEmptyDir(st store.Store, dir string) error { - e, err := st.Get(dir, true, false) - if err != nil { - return err - } - if len(e.Node.Nodes) == 0 { - st.Delete(dir, true, true) - return nil - } - for _, node := range e.Node.Nodes { - if !node.Dir { - glog.V(2).Infof("key: %s", node.Key[len(etcdserver.StoreKeysPrefix):]) - } else { - err := traverseAndDeleteEmptyDir(st, node.Key) - if err != nil { - return err - } - } - } - return nil -} - -func rebuild(datadir string) ([]byte, *raftpb.HardState, store.Store, error) { - waldir := path.Join(datadir, "member", "wal") - snapdir := path.Join(datadir, "member", "snap") - - ss := snap.New(snapdir) - snapshot, err := ss.Load() - if err != nil && err != snap.ErrNoSnapshot { - return nil, nil, nil, err - } - - var walsnap walpb.Snapshot - if snapshot != nil { - walsnap.Index, walsnap.Term = snapshot.Metadata.Index, snapshot.Metadata.Term - } - - w, err := wal.OpenForRead(waldir, walsnap) - if err != nil { - return nil, nil, nil, err - } - defer w.Close() - - meta, hardstate, ents, err := w.ReadAll() - if err != nil { - return nil, nil, nil, err - } - - st := store.New(etcdserver.StoreClusterPrefix, etcdserver.StoreKeysPrefix) - if snapshot != nil { - err := st.Recovery(snapshot.Data) - if err != nil { - return nil, nil, nil, err - } - } - - cluster := membership.NewCluster("") - cluster.SetStore(st) - cluster.Recover(func(*semver.Version) {}) - - applier := etcdserver.NewApplierV2(st, cluster) - for _, ent := range ents { - if ent.Type == raftpb.EntryConfChange { - var cc raftpb.ConfChange - pbutil.MustUnmarshal(&cc, ent.Data) - switch cc.Type { - case raftpb.ConfChangeAddNode: - m := new(membership.Member) - if err := json.Unmarshal(cc.Context, m); err != nil { - return nil, nil, nil, err - } - cluster.AddMember(m) - case raftpb.ConfChangeRemoveNode: - id := types.ID(cc.NodeID) - cluster.RemoveMember(id) - case raftpb.ConfChangeUpdateNode: - m := new(membership.Member) - if err := json.Unmarshal(cc.Context, m); err != nil { - return nil, nil, nil, err - } - cluster.UpdateRaftAttributes(m.ID, m.RaftAttributes) - } - continue - } - - var raftReq pb.InternalRaftRequest - if !pbutil.MaybeUnmarshal(&raftReq, ent.Data) { // backward compatible - var r pb.Request - pbutil.MustUnmarshal(&r, ent.Data) - applyRequest(&r, applier) - } else { - if raftReq.V2 != nil { - req := raftReq.V2 - applyRequest(req, applier) - } - } - } - - return meta, &hardstate, st, nil -} - -func toTTLOptions(r *pb.Request) store.TTLOptionSet { - refresh, _ := pbutil.GetBool(r.Refresh) - ttlOptions := store.TTLOptionSet{Refresh: refresh} - if r.Expiration != 0 { - ttlOptions.ExpireTime = time.Unix(0, r.Expiration) - } - return ttlOptions -} - -func applyRequest(r *pb.Request, applyV2 etcdserver.ApplierV2) { - toTTLOptions(r) - switch r.Method { - case "PUT": - applyV2.Put(r) - case "DELETE": - applyV2.Delete(r) - case "POST", "QGET", "SYNC": - return - default: - glog.Fatal("unknown command") - } -} diff --git a/vendor/k8s.io/kubernetes/cluster/images/etcd/start-stop-etcd.sh b/vendor/k8s.io/kubernetes/cluster/images/etcd/start-stop-etcd.sh deleted file mode 100755 index 85d2951fa..000000000 --- a/vendor/k8s.io/kubernetes/cluster/images/etcd/start-stop-etcd.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh - -# 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. - -# Starts 'etcd' version ${START_VERSION} and writes to it: -# 'etcd_version' -> "${START_VERSION}" -# ETCD_CREDS may optionally be set to provide flags for TLS credentials -# such as '--cert-file' and '--peer-cert-file'. For a complete list of -# flags, see https://coreos.com/etcd/docs/latest/op-guide/security.html. -# Successful write confirms that etcd is up and running. -# Sets ETCD_PID at the end. -# Returns 0 if etcd was successfully started, non-0 otherwise. -start_etcd() { - # Use random ports, so that apiserver cannot connect to etcd. - ETCD_PORT=18629 - ETCD_PEER_PORT=2380 - ETCD_CREDS="${ETCD_CREDS:-}" - # Avoid collisions between etcd and event-etcd. - case "${DATA_DIRECTORY}" in - *event*) - ETCD_PORT=18631 - ETCD_PEER_PORT=2381 - ;; - esac - local ETCD_CMD="${ETCD:-/usr/local/bin/etcd-${START_VERSION}}" - local ETCDCTL_CMD="${ETCDCTL:-/usr/local/bin/etcdctl-${START_VERSION}}" - local API_VERSION="$(echo ${START_STORAGE} | cut -c5-5)" - if [ "${API_VERSION}" = "2" ]; then - ETCDCTL_CMD="${ETCDCTL_CMD} --debug --endpoint=http://127.0.0.1:${ETCD_PORT} set" - else - ETCDCTL_CMD="${ETCDCTL_CMD} --endpoints=http://127.0.0.1:${ETCD_PORT} put" - fi - ${ETCD_CMD} \ - --name="etcd-$(hostname)" \ - --initial-cluster="etcd-$(hostname)=http://127.0.0.1:${ETCD_PEER_PORT}" \ - --debug \ - --data-dir=${DATA_DIRECTORY} \ - --listen-client-urls http://127.0.0.1:${ETCD_PORT} \ - --advertise-client-urls http://127.0.0.1:${ETCD_PORT} \ - --listen-peer-urls http://127.0.0.1:${ETCD_PEER_PORT} \ - --initial-advertise-peer-urls http://127.0.0.1:${ETCD_PEER_PORT} \ - ${ETCD_CREDS} & - ETCD_PID=$! - # Wait until we can write to etcd. - for i in $(seq 240); do - sleep 0.5 - ETCDCTL_API="${API_VERSION}" ${ETCDCTL_CMD} 'etcd_version' ${START_VERSION} - if [ "$?" -eq "0" ]; then - echo "Etcd on port ${ETCD_PORT} is up." - return 0 - fi - done - echo "Timeout while waiting for etcd on port ${ETCD_PORT}" - return 1 -} - -# Stops etcd with ${ETCD_PID} pid. -stop_etcd() { - kill "${ETCD_PID-}" >/dev/null 2>&1 || : - wait "${ETCD_PID-}" >/dev/null 2>&1 || : -} diff --git a/vendor/k8s.io/kubernetes/cluster/images/hyperkube/Makefile b/vendor/k8s.io/kubernetes/cluster/images/hyperkube/Makefile index 5fc09b000..4c8a645d9 100644 --- a/vendor/k8s.io/kubernetes/cluster/images/hyperkube/Makefile +++ b/vendor/k8s.io/kubernetes/cluster/images/hyperkube/Makefile @@ -20,7 +20,7 @@ REGISTRY?=staging-k8s.gcr.io ARCH?=amd64 OUT_DIR?=_output -HYPERKUBE_BIN?=$(OUT_DIR)/dockerized/bin/linux/$(ARCH)/hyperkube +HYPERKUBE_BIN?=$(shell pwd)/../../../$(OUT_DIR)/dockerized/bin/linux/$(ARCH)/hyperkube BASEIMAGE=k8s.gcr.io/debian-hyperkube-base-$(ARCH):0.10 TEMP_DIR:=$(shell mktemp -d -t hyperkubeXXXXXX) @@ -33,7 +33,7 @@ ifndef VERSION $(error VERSION is undefined) endif cp -r ./* ${TEMP_DIR} - cp ../../../${HYPERKUBE_BIN} ${TEMP_DIR} + cp ${HYPERKUBE_BIN} ${TEMP_DIR} chmod a+rx ${TEMP_DIR}/hyperkube diff --git a/vendor/k8s.io/kubernetes/cluster/images/hyperkube/OWNERS b/vendor/k8s.io/kubernetes/cluster/images/hyperkube/OWNERS new file mode 100644 index 000000000..945f79576 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/images/hyperkube/OWNERS @@ -0,0 +1,8 @@ +reviewers: + - ixdy + - luxas + - mikedanese +approvers: + - ixdy + - luxas + - mikedanese diff --git a/vendor/k8s.io/kubernetes/cluster/juju/config-default.sh b/vendor/k8s.io/kubernetes/cluster/juju/config-default.sh index 4a509985e..05e5d63ea 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/config-default.sh +++ b/vendor/k8s.io/kubernetes/cluster/juju/config-default.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/juju/config-test.sh b/vendor/k8s.io/kubernetes/cluster/juju/config-test.sh index 806884547..eb58d012a 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/config-test.sh +++ b/vendor/k8s.io/kubernetes/cluster/juju/config-test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-e2e/actions/test b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-e2e/actions/test index 85406a691..56b930dee 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-e2e/actions/test +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-e2e/actions/test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-e2e/config.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-e2e/config.yaml index d765c0287..ca4b882c6 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-e2e/config.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-e2e/config.yaml @@ -1,6 +1,6 @@ options: channel: type: string - default: "1.9/stable" + default: "1.10/stable" description: | Snap channel to install Kubernetes snaps from diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/create-rbd-pv b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/create-rbd-pv index 6879ba8c0..697d8d922 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/create-rbd-pv +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/create-rbd-pv @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/local/sbin/charm-env python3 # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/namespace-create b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/namespace-create index 4384184ea..c1c2c6451 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/namespace-create +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/namespace-create @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/local/sbin/charm-env python3 import os from yaml import safe_load as load from charmhelpers.core.hookenv import ( diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/restart b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/restart index 76827ac4c..d13073321 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/restart +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/actions/restart @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set +ex diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/config.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/config.yaml index 735182c21..7057614c1 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/config.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/config.yaml @@ -31,9 +31,17 @@ options: privileged mode. If "auto", kube-apiserver will not run in privileged mode by default, but will switch to privileged mode if gpu hardware is detected on a worker node. + enable-nvidia-plugin: + type: string + default: "auto" + description: | + Load the nvidia device plugin daemonset. Supported values are + "auto" and "false". When "auto", the daemonset will be loaded + only if GPUs are detected. When "false" the nvidia device plugin + will not be loaded. channel: type: string - default: "1.9/stable" + default: "1.10/stable" description: | Snap channel to install Kubernetes master services from client_password: @@ -86,3 +94,8 @@ options: description: | The storage backend for kube-apiserver persistence. Can be "etcd2", "etcd3", or "auto". Auto mode will select etcd3 on new installations, or etcd2 on upgrades. + enable-metrics: + type: boolean + default: true + description: | + If true the metrics server for Kubernetes will be deployed onto the cluster. diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/exec.d/vmware-patch/charm-pre-install b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/exec.d/vmware-patch/charm-pre-install index 0f70f51ca..b5e6d97b5 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/exec.d/vmware-patch/charm-pre-install +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/exec.d/vmware-patch/charm-pre-install @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash MY_HOSTNAME=$(hostname) : ${JUJU_UNIT_NAME:=`uuidgen`} diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/layer.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/layer.yaml index ed496bc31..247f8c207 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/layer.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/layer.yaml @@ -15,6 +15,8 @@ includes: - 'interface:kube-dns' - 'interface:kube-control' - 'interface:public-address' + - 'interface:aws' + - 'interface:gcp' options: basic: packages: diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/metadata.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/metadata.yaml index fa1f62b74..52aab0afa 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/metadata.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/metadata.yaml @@ -40,6 +40,10 @@ requires: interface: public-address ceph-storage: interface: ceph-admin + aws: + interface: aws + gcp: + interface: gcp resources: kubectl: type: file diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py index 0e23297ac..f866471f9 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py @@ -28,10 +28,12 @@ from shutil import move +from pathlib import Path from shlex import split from subprocess import check_call from subprocess import check_output from subprocess import CalledProcessError +from urllib.request import Request, urlopen from charms import layer from charms.layer import snap @@ -39,7 +41,8 @@ from charms.reactive import remove_state from charms.reactive import set_state from charms.reactive import is_state -from charms.reactive import when, when_any, when_not +from charms.reactive import endpoint_from_flag +from charms.reactive import when, when_any, when_not, when_none from charms.reactive.helpers import data_changed, any_file_changed from charms.kubernetes.common import get_version from charms.kubernetes.common import retry @@ -60,6 +63,8 @@ # default regex in charmhelpers doesn't allow periods, but nagios itself does. nrpe.Check.shortname_re = '[\.A-Za-z0-9-_]+$' +gcp_creds_env_key = 'GOOGLE_APPLICATION_CREDENTIALS' + os.environ['PATH'] += os.pathsep + os.path.join(os.sep, 'snap', 'bin') @@ -228,13 +233,6 @@ def migrate_from_pre_snaps(): os.remove(file) -@when('kubernetes-master.upgrade-needed') -@when_not('kubernetes-master.upgrade-specified') -def upgrade_needed_status(): - msg = 'Needs manual upgrade, run the upgrade action' - hookenv.status_set('blocked', msg) - - @when('kubernetes-master.upgrade-specified') def do_upgrade(): install_snaps() @@ -378,8 +376,6 @@ def get_keys_from_leader(keys, overwrite_local=False): contents = leader_get(k) # Default to logging the warning and wait for leader data to be set if contents is None: - msg = "Waiting on leaders crypto keys." - hookenv.status_set('waiting', msg) hookenv.log('Missing content for file {}'.format(k)) return False # Write out the file and move on to the next item @@ -397,24 +393,67 @@ def set_app_version(): hookenv.application_version_set(version.split(b' v')[-1].rstrip()) -@when('cdk-addons.configured', 'kube-api-endpoint.available', - 'kube-control.connected') -@when_not('kubernetes-master.upgrade-needed') -def idle_status(kube_api, kube_control): - ''' Signal at the end of the run that we are running. ''' - if not all_kube_system_pods_running(): - hookenv.status_set('waiting', 'Waiting for kube-system pods to start') - elif hookenv.config('service-cidr') != service_cidr(): - msg = 'WARN: cannot change service-cidr, still using ' + service_cidr() - hookenv.status_set('active', msg) - else: +@hookenv.atexit +def set_final_status(): + ''' Set the final status of the charm as we leave hook execution ''' + if not is_state('kube-api-endpoint.available'): + hookenv.status_set('blocked', 'Waiting for kube-api-endpoint relation') + return + + if not is_state('kube-control.connected'): + hookenv.status_set('blocked', 'Waiting for workers.') + return + + upgrade_needed = is_state('kubernetes-master.upgrade-needed') + upgrade_specified = is_state('kubernetes-master.upgrade-specified') + if upgrade_needed and not upgrade_specified: + msg = 'Needs manual upgrade, run the upgrade action' + hookenv.status_set('blocked', msg) + return + + if is_state('kubernetes-master.components.started'): # All services should be up and running at this point. Double-check... failing_services = master_services_down() - if len(failing_services) == 0: - hookenv.status_set('active', 'Kubernetes master running.') - else: + if len(failing_services) != 0: msg = 'Stopped services: {}'.format(','.join(failing_services)) hookenv.status_set('blocked', msg) + return + + is_leader = is_state('leadership.is_leader') + authentication_setup = is_state('authentication.setup') + if not is_leader and not authentication_setup: + hookenv.status_set('waiting', 'Waiting on leaders crypto keys.') + return + + components_started = is_state('kubernetes-master.components.started') + addons_configured = is_state('cdk-addons.configured') + if components_started and not addons_configured: + hookenv.status_set('waiting', 'Waiting to retry addon deployment') + return + + req_sent = is_state('kubernetes-master.cloud-request-sent') + aws_ready = is_state('endpoint.aws.ready') + gcp_ready = is_state('endpoint.gcp.ready') + if req_sent and not (aws_ready or gcp_ready): + hookenv.status_set('waiting', 'waiting for cloud integration') + + if addons_configured and not all_kube_system_pods_running(): + hookenv.status_set('waiting', 'Waiting for kube-system pods to start') + return + + if hookenv.config('service-cidr') != service_cidr(): + msg = 'WARN: cannot change service-cidr, still using ' + service_cidr() + hookenv.status_set('active', msg) + return + + gpu_available = is_state('kube-control.gpu.available') + gpu_enabled = is_state('kubernetes-master.gpu.enabled') + if gpu_available and not gpu_enabled: + msg = 'GPUs available. Set allow-privileged="auto" to enable.' + hookenv.status_set('active', msg) + return + + hookenv.status_set('active', 'Kubernetes master running.') def master_services_down(): @@ -540,18 +579,6 @@ def create_service_configs(kube_control): remove_state('authentication.setup') -@when_not('kube-control.connected') -def missing_kube_control(): - """Inform the operator master is waiting for a relation to workers. - - If deploying via bundle this won't happen, but if operator is upgrading a - a charm in a deployment that pre-dates the kube-control relation, it'll be - missing. - - """ - hookenv.status_set('blocked', 'Waiting for workers.') - - @when('kube-api-endpoint.available') def push_service_data(kube_api): ''' Send configuration to the load balancer, and close access to the @@ -559,9 +586,9 @@ def push_service_data(kube_api): kube_api.configure(port=6443) -def get_ingress_address(relation): +def get_ingress_address(relation_name): try: - network_info = hookenv.network_get(relation.relation_name) + network_info = hookenv.network_get(relation_name) except NotImplementedError: network_info = [] @@ -585,7 +612,7 @@ def send_data(tls, kube_api_endpoint): kubernetes_service_ip = get_kubernetes_service_ip() # Get ingress address - ingress_ip = get_ingress_address(kube_api_endpoint) + ingress_ip = get_ingress_address(kube_api_endpoint.relation_name) domain = hookenv.config('dns_domain') # Create SANs that the tls layer will add to the server cert. @@ -638,18 +665,24 @@ def kick_api_server(tls): def configure_cdk_addons(): ''' Configure CDK addons ''' remove_state('cdk-addons.configured') + load_gpu_plugin = hookenv.config('enable-nvidia-plugin').lower() + gpuEnable = (get_version('kube-apiserver') >= (1, 9) and + load_gpu_plugin == "auto" and + is_state('kubernetes-master.gpu.enabled')) dbEnabled = str(hookenv.config('enable-dashboard-addons')).lower() dnsEnabled = str(hookenv.config('enable-kube-dns')).lower() + metricsEnabled = str(hookenv.config('enable-metrics')).lower() args = [ 'arch=' + arch(), 'dns-ip=' + get_deprecated_dns_ip(), 'dns-domain=' + hookenv.config('dns_domain'), 'enable-dashboard=' + dbEnabled, - 'enable-kube-dns=' + dnsEnabled + 'enable-kube-dns=' + dnsEnabled, + 'enable-metrics=' + metricsEnabled, + 'enable-gpu=' + str(gpuEnable).lower() ] check_call(['snap', 'set', 'cdk-addons'] + args) if not addons_ready(): - hookenv.status_set('waiting', 'Waiting to retry addon deployment') remove_state('cdk-addons.configured') return @@ -885,12 +918,10 @@ def on_gpu_available(kube_control): We need to run in privileged mode. """ + kube_version = get_version('kube-apiserver') config = hookenv.config() - if config['allow-privileged'].lower() == "false": - hookenv.status_set( - 'active', - 'GPUs available. Set allow-privileged="auto" to enable.' - ) + if (config['allow-privileged'].lower() == "false" and + kube_version < (1, 9)): return remove_state('kubernetes-master.components.started') @@ -898,11 +929,25 @@ def on_gpu_available(kube_control): @when('kubernetes-master.gpu.enabled') +@when('kubernetes-master.components.started') @when_not('kubernetes-master.privileged') -def disable_gpu_mode(): +def gpu_with_no_privileged(): """We were in gpu mode, but the operator has set allow-privileged="false", so we can't run in gpu mode anymore. + """ + if get_version('kube-apiserver') < (1, 9): + remove_state('kubernetes-master.gpu.enabled') + + +@when('kube-control.connected') +@when_not('kube-control.gpu.available') +@when('kubernetes-master.gpu.enabled') +@when('kubernetes-master.components.started') +def gpu_departed(kube_control): + """We were in gpu mode, but the workers informed us there is + no gpu support anymore. + """ remove_state('kubernetes-master.gpu.enabled') @@ -918,24 +963,18 @@ def shutdown(): def restart_apiserver(): - prev_state, prev_msg = hookenv.status_get() hookenv.status_set('maintenance', 'Restarting kube-apiserver') host.service_restart('snap.kube-apiserver.daemon') - hookenv.status_set(prev_state, prev_msg) def restart_controller_manager(): - prev_state, prev_msg = hookenv.status_get() hookenv.status_set('maintenance', 'Restarting kube-controller-manager') host.service_restart('snap.kube-controller-manager.daemon') - hookenv.status_set(prev_state, prev_msg) def restart_scheduler(): - prev_state, prev_msg = hookenv.status_get() hookenv.status_set('maintenance', 'Restarting kube-scheduler') host.service_restart('snap.kube-scheduler.daemon') - hookenv.status_set(prev_state, prev_msg) def arch(): @@ -1076,6 +1115,7 @@ def configure_kubernetes_service(service, base_args, extra_args_key): args = {} for arg in prev_args: # remove previous args by setting to null + # note this is so we remove them from the snap's config args[arg] = 'null' for k, v in base_args.items(): args[k] = v @@ -1099,6 +1139,14 @@ def configure_apiserver(etcd_connection_string, leader_etcd_version): server_cert_path = layer_options.get('server_certificate_path') server_key_path = layer_options.get('server_key_path') + # at one point in time, this code would set ca-client-cert, + # but this was removed. This was before configure_kubernetes_service + # kept track of old arguments and removed them, so client-ca-cert + # was able to hang around forever stored in the snap configuration. + # This removes that stale configuration from the snap if it still + # exists. + api_opts['client-ca-file'] = 'null' + if is_privileged(): api_opts['allow-privileged'] = 'true' set_state('kubernetes-master.privileged') @@ -1124,6 +1172,7 @@ def configure_apiserver(etcd_connection_string, leader_etcd_version): api_opts['service-account-key-file'] = '/root/cdk/serviceaccount.key' api_opts['kubelet-preferred-address-types'] = \ '[InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP]' + api_opts['advertise-address'] = get_ingress_address('kube-control') etcd_dir = '/root/cdk/etcd' etcd_ca = os.path.join(etcd_dir, 'client-ca.pem') @@ -1135,7 +1184,7 @@ def configure_apiserver(etcd_connection_string, leader_etcd_version): api_opts['etcd-certfile'] = etcd_cert api_opts['etcd-servers'] = etcd_connection_string - admission_control = [ + admission_control_pre_1_9 = [ 'Initializers', 'NamespaceLifecycle', 'LimitRanger', @@ -1144,19 +1193,54 @@ def configure_apiserver(etcd_connection_string, leader_etcd_version): 'DefaultTolerationSeconds' ] + admission_control = [ + 'NamespaceLifecycle', + 'LimitRanger', + 'ServiceAccount', + 'PersistentVolumeLabel', + 'DefaultStorageClass', + 'DefaultTolerationSeconds', + 'MutatingAdmissionWebhook', + 'ValidatingAdmissionWebhook', + 'ResourceQuota' + ] + auth_mode = hookenv.config('authorization-mode') if 'Node' in auth_mode: admission_control.append('NodeRestriction') api_opts['authorization-mode'] = auth_mode - if get_version('kube-apiserver') < (1, 6): + kube_version = get_version('kube-apiserver') + if kube_version < (1, 6): hookenv.log('Removing DefaultTolerationSeconds from admission-control') - admission_control.remove('DefaultTolerationSeconds') - if get_version('kube-apiserver') < (1, 7): + admission_control_pre_1_9.remove('DefaultTolerationSeconds') + if kube_version < (1, 7): hookenv.log('Removing Initializers from admission-control') - admission_control.remove('Initializers') - api_opts['admission-control'] = ','.join(admission_control) + admission_control_pre_1_9.remove('Initializers') + if kube_version < (1, 9): + api_opts['admission-control'] = ','.join(admission_control_pre_1_9) + else: + api_opts['admission-control'] = ','.join(admission_control) + + if kube_version > (1, 6) and \ + hookenv.config('enable-metrics'): + api_opts['requestheader-client-ca-file'] = ca_cert_path + api_opts['requestheader-allowed-names'] = 'client' + api_opts['requestheader-extra-headers-prefix'] = 'X-Remote-Extra-' + api_opts['requestheader-group-headers'] = 'X-Remote-Group' + api_opts['requestheader-username-headers'] = 'X-Remote-User' + api_opts['proxy-client-cert-file'] = client_cert_path + api_opts['proxy-client-key-file'] = client_key_path + api_opts['enable-aggregator-routing'] = 'true' + api_opts['client-ca-file'] = ca_cert_path + + if is_state('endpoint.aws.ready'): + api_opts['cloud-provider'] = 'aws' + elif is_state('endpoint.gcp.ready'): + cloud_config_path = _cloud_config_path('kube-apiserver') + api_opts['cloud-provider'] = 'gce' + api_opts['cloud-config'] = str(cloud_config_path) configure_kubernetes_service('kube-apiserver', api_opts, 'api-extra-args') restart_apiserver() @@ -1179,6 +1263,13 @@ def configure_controller_manager(): controller_opts['service-account-private-key-file'] = \ '/root/cdk/serviceaccount.key' + if is_state('endpoint.aws.ready'): + controller_opts['cloud-provider'] = 'aws' + elif is_state('endpoint.gcp.ready'): + cloud_config_path = _cloud_config_path('kube-controller-manager') + controller_opts['cloud-provider'] = 'gce' + controller_opts['cloud-config'] = str(cloud_config_path) + configure_kubernetes_service('kube-controller-manager', controller_opts, 'controller-manager-extra-args') restart_controller_manager() @@ -1278,19 +1369,88 @@ def all_kube_system_pods_running(): try: output = check_output(cmd).decode('utf-8') + result = json.loads(output) except CalledProcessError: hookenv.log('failed to get kube-system pod status') return False + hookenv.log('Checking system pods status: {}'.format(', '.join( + '='.join([pod['metadata']['name'], pod['status']['phase']]) + for pod in result['items']))) + + all_pending = all(pod['status']['phase'] == 'Pending' + for pod in result['items']) + if is_state('endpoint.gcp.ready') and all_pending: + poke_network_unavailable() + return False - result = json.loads(output) - for pod in result['items']: - status = pod['status']['phase'] - # Evicted nodes should re-spawn - if status != 'Running' and \ - pod['status'].get('reason', '') != 'Evicted': - return False + # All pods must be Running or Evicted (which should re-spawn) + all_running = all(pod['status']['phase'] == 'Running' or + pod['status'].get('reason', '') == 'Evicted' + for pod in result['items']) + return all_running - return True + +def poke_network_unavailable(): + """ + Work around https://github.com/kubernetes/kubernetes/issues/44254 by + manually poking the status into the API server to tell the nodes they have + a network route. + + This is needed because kubelet sets the NetworkUnavailable flag and expects + the network plugin to clear it, which only kubenet does. There is some + discussion about refactoring the affected code but nothing has happened + in a while. + """ + cmd = ['kubectl', 'get', 'nodes', '-o', 'json'] + + try: + output = check_output(cmd).decode('utf-8') + nodes = json.loads(output)['items'] + except CalledProcessError: + hookenv.log('failed to get kube-system nodes') + return + except (KeyError, json.JSONDecodeError) as e: + hookenv.log('failed to parse kube-system node status ' + '({}): {}'.format(e, output), hookenv.ERROR) + return + + for node in nodes: + node_name = node['metadata']['name'] + url = 'http://localhost:8080/api/v1/nodes/{}/status'.format(node_name) + with urlopen(url) as response: + code = response.getcode() + body = response.read().decode('utf8') + if code != 200: + hookenv.log('failed to get node status from {} [{}]: {}'.format( + url, code, body), hookenv.ERROR) + return + try: + node_info = json.loads(body) + conditions = node_info['status']['conditions'] + i = [c['type'] for c in conditions].index('NetworkUnavailable') + if conditions[i]['status'] == 'True': + hookenv.log('Clearing NetworkUnavailable from {}'.format( + node_name)) + conditions[i] = { + "type": "NetworkUnavailable", + "status": "False", + "reason": "RouteCreated", + "message": "Manually set through k8s api", + } + req = Request(url, method='PUT', + data=json.dumps(node_info).encode('utf8'), + headers={'Content-Type': 'application/json'}) + with urlopen(req) as response: + code = response.getcode() + body = response.read().decode('utf8') + if code not in (200, 201, 202): + hookenv.log('failed to update node status [{}]: {}'.format( + code, body), hookenv.ERROR) + return + except (json.JSONDecodeError, KeyError): + hookenv.log('failed to parse node status: {}'.format(body), + hookenv.ERROR) + return def apiserverVersion(): @@ -1311,3 +1471,124 @@ def getStorageBackend(): if storage_backend == 'auto': storage_backend = leader_get('auto_storage_backend') return storage_backend + + +@when('leadership.is_leader') +@when_not('leadership.set.cluster_tag') +def create_cluster_tag(): + cluster_tag = 'kubernetes-{}'.format(token_generator().lower()) + leader_set(cluster_tag=cluster_tag) + + +@when('leadership.set.cluster_tag', + 'kube-control.connected') +@when_not('kubernetes-master.cluster-tag-sent') +def send_cluster_tag(): + cluster_tag = leader_get('cluster_tag') + kube_control = endpoint_from_flag('kube-control.connected') + kube_control.set_cluster_tag(cluster_tag) + set_state('kubernetes-master.cluster-tag-sent') + + +@when_not('kube-control.connected') +def clear_cluster_tag_sent(): + remove_state('kubernetes-master.cluster-tag-sent') + + +@when_any('endpoint.aws.joined', + 'endpoint.gcp.joined') +@when('leadership.set.cluster_tag') +@when_not('kubernetes-master.cloud-request-sent') +def request_integration(): + hookenv.status_set('maintenance', 'requesting cloud integration') + cluster_tag = leader_get('cluster_tag') + if is_state('endpoint.aws.joined'): + cloud = endpoint_from_flag('endpoint.aws.joined') + cloud.tag_instance({ + 'kubernetes.io/cluster/{}'.format(cluster_tag): 'owned', + 'k8s.io/role/master': 'true', + }) + cloud.tag_instance_security_group({ + 'kubernetes.io/cluster/{}'.format(cluster_tag): 'owned', + }) + cloud.tag_instance_subnet({ + 'kubernetes.io/cluster/{}'.format(cluster_tag): 'owned', + }) + cloud.enable_object_storage_management(['kubernetes-*']) + cloud.enable_load_balancer_management() + elif is_state('endpoint.gcp.joined'): + cloud = endpoint_from_flag('endpoint.gcp.joined') + cloud.label_instance({ + 'k8s-io-cluster-name': cluster_tag, + 'k8s-io-role-master': 'master', + }) + cloud.enable_object_storage_management() + cloud.enable_security_management() + cloud.enable_instance_inspection() + cloud.enable_network_management() + cloud.enable_dns_management() + cloud.enable_block_storage_management() + set_state('kubernetes-master.cloud-request-sent') + + +@when_none('endpoint.aws.joined', + 'endpoint.gcp.joined') +@when('kubernetes-master.cloud-request-sent') +def clear_requested_integration(): + remove_state('kubernetes-master.cloud-request-sent') + + +@when_any('endpoint.aws.ready', + 'endpoint.gcp.ready') +@when_not('kubernetes-master.restarted-for-cloud') +def restart_for_cloud(): + if is_state('endpoint.gcp.ready'): + _write_gcp_snap_config('kube-apiserver') + _write_gcp_snap_config('kube-controller-manager') + set_state('kubernetes-master.restarted-for-cloud') + remove_state('kubernetes-master.components.started') # force restart + + +def _snap_common_path(component): + return Path('/var/snap/{}/common'.format(component)) + + +def _cloud_config_path(component): + return _snap_common_path(component) / 'cloud-config.conf' + + +def _gcp_creds_path(component): + return _snap_common_path(component) / 'gcp-creds.json' + + +def _daemon_env_path(component): + return _snap_common_path(component) / 'environment' + + +def _write_gcp_snap_config(component): + # gcp requires additional credentials setup + gcp = endpoint_from_flag('endpoint.gcp.ready') + creds_path = _gcp_creds_path(component) + with creds_path.open('w') as fp: + os.fchmod(fp.fileno(), 0o600) + fp.write(gcp.credentials) + + # create a cloud-config file that sets token-url to nil to make the + # services use the creds env var instead of the metadata server, as + # well as making the cluster multizone + cloud_config_path = _cloud_config_path(component) + cloud_config_path.write_text('[Global]\n' + 'token-url = nil\n' + 'multizone = true\n') + + daemon_env_path = _daemon_env_path(component) + if daemon_env_path.exists(): + daemon_env = daemon_env_path.read_text() + if not daemon_env.endswith('\n'): + daemon_env += '\n' + else: + daemon_env = '' + if gcp_creds_env_key not in daemon_env: + daemon_env += '{}={}\n'.format(gcp_creds_env_key, creds_path) + daemon_env_path.parent.mkdir(parents=True, exist_ok=True) + daemon_env_path.write_text(daemon_env) diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/microbot b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/microbot index 41663f253..85d7bf13b 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/microbot +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/microbot @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/local/sbin/charm-env python3 # Copyright 2015 The Kubernetes Authors. # @@ -21,7 +21,7 @@ from charmhelpers.core.hookenv import action_get from charmhelpers.core.hookenv import action_set from charmhelpers.core.hookenv import unit_public_ip from charms.templating.jinja2 import render -from subprocess import call +from subprocess import call, check_output os.environ['PATH'] += os.pathsep + os.path.join(os.sep, 'snap', 'bin') @@ -30,6 +30,9 @@ context['replicas'] = action_get('replicas') context['delete'] = action_get('delete') context['public_address'] = unit_public_ip() +arch = check_output(['dpkg', '--print-architecture']).rstrip() +context['arch'] = arch.decode('utf-8') + if not context['replicas']: context['replicas'] = 3 diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/pause b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/pause index 82b3d3838..184b10a67 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/pause +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/pause @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/registry b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/registry index 11d57ce88..81c8bc038 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/registry +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/registry @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/local/sbin/charm-env python3 # # For a usage examples, see README.md # @@ -25,7 +25,7 @@ from base64 import b64encode from charmhelpers.core.hookenv import action_get from charmhelpers.core.hookenv import action_set from charms.templating.jinja2 import render -from subprocess import call +from subprocess import call, check_output os.environ['PATH'] += os.pathsep + os.path.join(os.sep, 'snap', 'bin') @@ -33,6 +33,9 @@ deletion = action_get('delete') context = {} +arch = check_output(['dpkg', '--print-architecture']).rstrip() +context['arch'] = arch.decode('utf-8') + # These config options must be defined in the case of a creation param_error = False for param in ('tlscert', 'tlskey', 'domain', 'htpasswd', 'htpasswd-plain'): diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/resume b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/resume index f7ef0a17f..2092185ae 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/resume +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/actions/resume @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/config.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/config.yaml index 803f036cc..7f51776c1 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/config.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/config.yaml @@ -22,7 +22,7 @@ options: switch to privileged mode if gpu hardware is detected. channel: type: string - default: "1.9/stable" + default: "1.10/stable" description: | Snap channel to install Kubernetes worker services from require-manual-upgrade: diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/exec.d/vmware-patch/charm-pre-install b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/exec.d/vmware-patch/charm-pre-install index 0f70f51ca..b5e6d97b5 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/exec.d/vmware-patch/charm-pre-install +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/exec.d/vmware-patch/charm-pre-install @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash MY_HOSTNAME=$(hostname) : ${JUJU_UNIT_NAME:=`uuidgen`} diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/layer.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/layer.yaml index a008d6f8e..d8ee64898 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/layer.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/layer.yaml @@ -7,12 +7,14 @@ includes: - 'layer:metrics' - 'layer:nagios' - 'layer:tls-client' - - 'layer:nvidia-cuda' - 'layer:cdk-service-kicker' - 'interface:http' - 'interface:kubernetes-cni' - 'interface:kube-dns' - 'interface:kube-control' + - 'interface:aws' + - 'interface:gcp' + - 'interface:mount' config: deletes: - install_from_upstream diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/metadata.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/metadata.yaml index b367fcd94..df4a823c9 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/metadata.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/metadata.yaml @@ -7,6 +7,7 @@ maintainers: - Konstantinos Tsakalozos - Charles Butler - Matthew Bruzek + - Mike Wilson description: | Kubernetes is an open-source platform for deploying, scaling, and operations of application containers across a cluster of hosts. Kubernetes is portable @@ -28,6 +29,12 @@ requires: interface: kube-dns kube-control: interface: kube-control + aws: + interface: aws + gcp: + interface: gcp + nfs: + interface: mount provides: cni: interface: kubernetes-cni @@ -37,6 +44,10 @@ resources: type: file filename: cni.tgz description: CNI plugins for amd64 + cni-arm64: + type: file + filename: cni.tgz + description: CNI plugins for arm64 cni-s390x: type: file filename: cni.tgz diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py index 8d232e05f..82b7d3abc 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py @@ -21,6 +21,7 @@ import subprocess import time +from pathlib import Path from shlex import split from subprocess import check_call, check_output from subprocess import CalledProcessError @@ -29,8 +30,9 @@ from charms import layer from charms.layer import snap from charms.reactive import hook +from charms.reactive import endpoint_from_flag from charms.reactive import set_state, remove_state, is_state -from charms.reactive import when, when_any, when_not +from charms.reactive import when, when_any, when_not, when_none from charms.kubernetes.common import get_version @@ -49,6 +51,7 @@ kubeconfig_path = '/root/cdk/kubeconfig' kubeproxyconfig_path = '/root/cdk/kubeproxyconfig' kubeclientconfig_path = '/root/.kube/config' +gcp_creds_env_key = 'GOOGLE_APPLICATION_CREDENTIALS' os.environ['PATH'] += os.pathsep + os.path.join(os.sep, 'snap', 'bin') db = unitdata.kv() @@ -69,7 +72,14 @@ def upgrade_charm(): # Remove gpu.enabled state so we can reconfigure gpu-related kubelet flags, # since they can differ between k8s versions - remove_state('kubernetes-worker.gpu.enabled') + if is_state('kubernetes-worker.gpu.enabled'): + remove_state('kubernetes-worker.gpu.enabled') + try: + disable_gpu() + except ApplyNodeLabelFailed: + # Removing node label failed. Probably the master is unavailable. + # Proceed with the upgrade in hope GPUs will still be there. + hookenv.log('Failed to remove GPU labels. Proceed with upgrade.') remove_state('kubernetes-worker.cni-plugins.installed') remove_state('kubernetes-worker.config.created') @@ -356,9 +366,6 @@ def start_worker(kube_api, kube_control, auth_control, cni): creds = db.get('credentials') data_changed('kube-control.creds', creds) - # set --allow-privileged flag for kubelet - set_privileged() - create_config(random.choice(servers), creds) configure_kubelet(dns, ingress_ip) configure_kube_proxy(servers, cluster_cidr) @@ -610,16 +617,21 @@ def configure_kubelet(dns, ingress_ip): if (dns['enable-kube-dns']): kubelet_opts['cluster-dns'] = dns['sdn-ip'] - privileged = is_state('kubernetes-worker.privileged') - kubelet_opts['allow-privileged'] = 'true' if privileged else 'false' + # set --allow-privileged flag for kubelet + kubelet_opts['allow-privileged'] = set_privileged() if is_state('kubernetes-worker.gpu.enabled'): - if get_version('kubelet') < (1, 6): - hookenv.log('Adding --experimental-nvidia-gpus=1 to kubelet') - kubelet_opts['experimental-nvidia-gpus'] = '1' - else: - hookenv.log('Adding --feature-gates=Accelerators=true to kubelet') - kubelet_opts['feature-gates'] = 'Accelerators=true' + hookenv.log('Adding ' + '--feature-gates=DevicePlugins=true ' + 'to kubelet') + kubelet_opts['feature-gates'] = 'DevicePlugins=true' + + if is_state('endpoint.aws.ready'): + kubelet_opts['cloud-provider'] = 'aws' + elif is_state('endpoint.gcp.ready'): + cloud_config_path = _cloud_config_path('kubelet') + kubelet_opts['cloud-provider'] = 'gce' + kubelet_opts['cloud-config'] = str(cloud_config_path) configure_kubernetes_service('kubelet', kubelet_opts, 'kubelet-extra-args') @@ -705,6 +717,9 @@ def launch_default_ingress_controller(): if context['arch'] == 's390x': context['defaultbackend_image'] = \ "k8s.gcr.io/defaultbackend-s390x:1.4" + elif context['arch'] == 'arm64': + context['defaultbackend_image'] = \ + "k8s.gcr.io/defaultbackend-arm64:1.4" else: context['defaultbackend_image'] = \ "k8s.gcr.io/defaultbackend:1.4" @@ -728,9 +743,16 @@ def launch_default_ingress_controller(): if context['arch'] == 's390x': context['ingress_image'] = \ "docker.io/cdkbot/nginx-ingress-controller-s390x:0.9.0-beta.13" + elif context['arch'] == 'arm64': + context['ingress_image'] = \ + "k8s.gcr.io/nginx-ingress-controller-arm64:0.9.0-beta.15" else: context['ingress_image'] = \ - "k8s.gcr.io/nginx-ingress-controller:0.9.0-beta.15" # noqa + "k8s.gcr.io/nginx-ingress-controller:0.9.0-beta.15" # noqa + if get_version('kubelet') < (1, 9): + context['daemonset_api_version'] = 'extensions/v1beta1' + else: + context['daemonset_api_version'] = 'apps/v1beta2' context['juju_application'] = hookenv.service_name() manifest = addon_path.format('ingress-daemon-set.yaml') render('ingress-daemon-set.yaml', manifest, context) @@ -847,18 +869,25 @@ def remove_nrpe_config(nagios=None): def set_privileged(): - """Update the allow-privileged flag for kubelet. - + """Return 'true' if privileged containers are needed. + This is when a) the user requested them + b) user does not care (auto) and GPUs are available in a pre + 1.9 era """ privileged = hookenv.config('allow-privileged').lower() + gpu_needs_privileged = (is_state('kubernetes-worker.gpu.enabled') and + get_version('kubelet') < (1, 9)) + if privileged == 'auto': - gpu_enabled = is_state('kubernetes-worker.gpu.enabled') - privileged = 'true' if gpu_enabled else 'false' + privileged = 'true' if gpu_needs_privileged else 'false' - if privileged == 'true': - set_state('kubernetes-worker.privileged') - else: - remove_state('kubernetes-worker.privileged') + if privileged == 'false' and gpu_needs_privileged: + disable_gpu() + remove_state('kubernetes-worker.gpu.enabled') + # No need to restart kubernetes (set the restart-needed state) + # because set-privileged is already in the restart path + + return privileged @when('config.changed.allow-privileged') @@ -871,18 +900,17 @@ def on_config_allow_privileged_change(): remove_state('config.changed.allow-privileged') -@when('cuda.installed') +@when('nvidia-docker.installed') @when('kubernetes-worker.config.created') @when_not('kubernetes-worker.gpu.enabled') def enable_gpu(): """Enable GPU usage on this node. """ - config = hookenv.config() - if config['allow-privileged'] == "false": + if get_version('kubelet') < (1, 9): hookenv.status_set( 'active', - 'GPUs available. Set allow-privileged="auto" to enable.' + 'Upgrade to snap channel >= 1.9/stable to enable GPU suppport.' ) return @@ -897,7 +925,6 @@ def enable_gpu(): hookenv.log(cpe) return - # Apply node labels set_label('gpu', 'true') set_label('cuda', 'true') @@ -906,15 +933,19 @@ def enable_gpu(): @when('kubernetes-worker.gpu.enabled') -@when_not('kubernetes-worker.privileged') +@when_not('nvidia-docker.installed') @when_not('kubernetes-worker.restart-needed') +def nvidia_departed(): + """Cuda departed, probably due to the docker layer switching to a + non nvidia-docker.""" + disable_gpu() + remove_state('kubernetes-worker.gpu.enabled') + set_state('kubernetes-worker.restart-needed') + + def disable_gpu(): """Disable GPU usage on this node. - This handler fires when we're running in gpu mode, and then the operator - sets allow-privileged="false". Since we can no longer run privileged - containers, we need to disable gpu mode. - """ hookenv.log('Disabling gpu mode') @@ -922,9 +953,6 @@ def disable_gpu(): remove_label('gpu') remove_label('cuda') - remove_state('kubernetes-worker.gpu.enabled') - set_state('kubernetes-worker.restart-needed') - @when('kubernetes-worker.gpu.enabled') @when('kube-control.connected') @@ -1009,6 +1037,10 @@ def _systemctl_is_active(application): def get_node_name(): kubelet_extra_args = parse_extra_args('kubelet-extra-args') cloud_provider = kubelet_extra_args.get('cloud-provider', '') + if is_state('endpoint.aws.ready'): + cloud_provider = 'aws' + elif is_state('endpoint.gcp.ready'): + cloud_provider = 'gcp' if cloud_provider == 'aws': return getfqdn() else: @@ -1049,3 +1081,158 @@ def remove_label(label): retry = 'Failed to remove label {0}. Will retry.'.format(label) if not persistent_call(cmd, retry): raise ApplyNodeLabelFailed(retry) + + +@when_any('endpoint.aws.joined', + 'endpoint.gcp.joined') +@when('kube-control.cluster_tag.available') +@when_not('kubernetes-worker.cloud-request-sent') +def request_integration(): + hookenv.status_set('maintenance', 'requesting cloud integration') + kube_control = endpoint_from_flag('kube-control.cluster_tag.available') + cluster_tag = kube_control.get_cluster_tag() + if is_state('endpoint.aws.joined'): + cloud = endpoint_from_flag('endpoint.aws.joined') + cloud.tag_instance({ + 'kubernetes.io/cluster/{}'.format(cluster_tag): 'owned', + }) + cloud.tag_instance_security_group({ + 'kubernetes.io/cluster/{}'.format(cluster_tag): 'owned', + }) + cloud.tag_instance_subnet({ + 'kubernetes.io/cluster/{}'.format(cluster_tag): 'owned', + }) + cloud.enable_object_storage_management(['kubernetes-*']) + elif is_state('endpoint.gcp.joined'): + cloud = endpoint_from_flag('endpoint.gcp.joined') + cloud.label_instance({ + 'k8s-io-cluster-name': cluster_tag, + }) + cloud.enable_object_storage_management() + cloud.enable_instance_inspection() + cloud.enable_dns_management() + set_state('kubernetes-worker.cloud-request-sent') + hookenv.status_set('waiting', 'waiting for cloud integration') + + +@when_none('endpoint.aws.joined', + 'endpoint.gcp.joined') +def clear_requested_integration(): + remove_state('kubernetes-worker.cloud-request-sent') + + +@when_any('endpoint.aws.ready', + 'endpoint.gcp.ready') +@when_not('kubernetes-worker.restarted-for-cloud') +def restart_for_cloud(): + if is_state('endpoint.gcp.ready'): + _write_gcp_snap_config('kubelet') + set_state('kubernetes-worker.restarted-for-cloud') + set_state('kubernetes-worker.restart-needed') + + +def _snap_common_path(component): + return Path('/var/snap/{}/common'.format(component)) + + +def _cloud_config_path(component): + return _snap_common_path(component) / 'cloud-config.conf' + + +def _gcp_creds_path(component): + return _snap_common_path(component) / 'gcp-creds.json' + + +def _daemon_env_path(component): + return _snap_common_path(component) / 'environment' + + +def _write_gcp_snap_config(component): + # gcp requires additional credentials setup + gcp = endpoint_from_flag('endpoint.gcp.ready') + creds_path = _gcp_creds_path(component) + with creds_path.open('w') as fp: + os.fchmod(fp.fileno(), 0o600) + fp.write(gcp.credentials) + + # create a cloud-config file that sets token-url to nil to make the + # services use the creds env var instead of the metadata server, as + # well as making the cluster multizone + cloud_config_path = _cloud_config_path(component) + cloud_config_path.write_text('[Global]\n' + 'token-url = nil\n' + 'multizone = true\n') + + daemon_env_path = _daemon_env_path(component) + if daemon_env_path.exists(): + daemon_env = daemon_env_path.read_text() + if not daemon_env.endswith('\n'): + daemon_env += '\n' + else: + daemon_env = '' + if gcp_creds_env_key not in daemon_env: + daemon_env += '{}={}\n'.format(gcp_creds_env_key, creds_path) + daemon_env_path.parent.mkdir(parents=True, exist_ok=True) + daemon_env_path.write_text(daemon_env) + + +def get_first_mount(mount_relation): + mount_relation_list = mount_relation.mounts() + if mount_relation_list and len(mount_relation_list) > 0: + # mount relation list is a list of the mount layer relations + # for now we just use the first one that is nfs + for mount in mount_relation_list: + # for now we just check the first mount and use that. + # the nfs charm only supports one for now. + if ('mounts' in mount and + mount['mounts'][0]['fstype'] == 'nfs'): + return mount['mounts'][0] + return None + + +@when('nfs.available') +def nfs_state_control(mount): + ''' Determine if we should remove the state that controls the re-render + and execution of the nfs-relation-changed event because there + are changes in the relationship data, and we should re-render any + configs ''' + + mount_data = get_first_mount(mount) + if mount_data: + nfs_relation_data = { + 'options': mount_data['options'], + 'host': mount_data['hostname'], + 'mountpoint': mount_data['mountpoint'], + 'fstype': mount_data['fstype'] + } + + # Re-execute the rendering if the data has changed. + if data_changed('nfs-config', nfs_relation_data): + hookenv.log('reconfiguring nfs') + remove_state('nfs.configured') + + +@when('nfs.available') +@when_not('nfs.configured') +def nfs_storage(mount): + '''NFS on kubernetes requires nfs config rendered into a deployment of + the nfs client provisioner. That will handle the persistent volume claims + with no persistent volume to back them.''' + + mount_data = get_first_mount(mount) + if not mount_data: + return + + addon_path = '/root/cdk/addons/{}' + # Render the NFS deployment + manifest = addon_path.format('nfs-provisioner.yaml') + render('nfs-provisioner.yaml', manifest, mount_data) + hookenv.log('Creating the nfs provisioner.') + try: + kubectl('apply', '-f', manifest) + except CalledProcessError as e: + hookenv.log(e) + hookenv.log('Failed to create nfs provisioner. Will attempt again next update.') # noqa + return + + set_state('nfs.configured') diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/ingress-daemon-set.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/ingress-daemon-set.yaml index 1254f6d41..744913cab 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/ingress-daemon-set.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/ingress-daemon-set.yaml @@ -127,7 +127,7 @@ kind: ConfigMap metadata: name: nginx-load-balancer-{{ juju_application }}-conf --- -apiVersion: apps/v1beta2 +apiVersion: {{ daemonset_api_version }} kind: DaemonSet metadata: name: nginx-ingress-{{ juju_application }}-controller @@ -152,7 +152,6 @@ spec: containers: - image: {{ ingress_image }} name: nginx-ingress-{{ juju_application }} - imagePullPolicy: Always livenessProbe: httpGet: path: /healthz diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/microbot-example.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/microbot-example.yaml index e1d6f3067..323a07cef 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/microbot-example.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/microbot-example.yaml @@ -18,7 +18,7 @@ spec: app: microbot spec: containers: - - image: dontrebootme/microbot:v1 + - image: cdkbot/microbot-{{ arch }}:latest imagePullPolicy: "" name: microbot ports: diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/nfs-provisioner.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/nfs-provisioner.yaml new file mode 100644 index 000000000..de3023a65 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/nfs-provisioner.yaml @@ -0,0 +1,39 @@ +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: default + annotations: + storageclass.kubernetes.io/is-default-class: "true" +provisioner: fuseim.pri/ifs +--- +kind: Deployment +apiVersion: extensions/v1beta1 +metadata: + name: nfs-client-provisioner +spec: + replicas: 1 + strategy: + type: Recreate + template: + metadata: + labels: + app: nfs-client-provisioner + spec: + containers: + - name: nfs-client-provisioner + image: quay.io/external_storage/nfs-client-provisioner:latest + volumeMounts: + - name: nfs-client-root + mountPath: /persistentvolumes + env: + - name: PROVISIONER_NAME + value: fuseim.pri/ifs + - name: NFS_SERVER + value: {{ hostname }} + - name: NFS_PATH + value: {{ mountpoint }} + volumes: + - name: nfs-client-root + nfs: + server: {{ hostname }} + path: {{ mountpoint }} diff --git a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/registry.yaml b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/registry.yaml index d24b713ce..2503f3abf 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/registry.yaml +++ b/vendor/k8s.io/kubernetes/cluster/juju/layers/kubernetes-worker/templates/registry.yaml @@ -37,7 +37,7 @@ spec: spec: containers: - name: registry - image: registry:2 + image: cdkbot/registry-{{ arch }}:2.6 resources: # keep request = limit to keep this container in guaranteed class limits: diff --git a/vendor/k8s.io/kubernetes/cluster/juju/prereqs/ubuntu-juju.sh b/vendor/k8s.io/kubernetes/cluster/juju/prereqs/ubuntu-juju.sh index 0264442e0..74f256d78 100644 --- a/vendor/k8s.io/kubernetes/cluster/juju/prereqs/ubuntu-juju.sh +++ b/vendor/k8s.io/kubernetes/cluster/juju/prereqs/ubuntu-juju.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/juju/util.sh b/vendor/k8s.io/kubernetes/cluster/juju/util.sh index 8715b4418..ecc23b13b 100755 --- a/vendor/k8s.io/kubernetes/cluster/juju/util.sh +++ b/vendor/k8s.io/kubernetes/cluster/juju/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/kube-down.sh b/vendor/k8s.io/kubernetes/cluster/kube-down.sh index 2f89e6096..5993dc4a4 100755 --- a/vendor/k8s.io/kubernetes/cluster/kube-down.sh +++ b/vendor/k8s.io/kubernetes/cluster/kube-down.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/kube-up.sh b/vendor/k8s.io/kubernetes/cluster/kube-up.sh index a6eb37674..af85df0a8 100755 --- a/vendor/k8s.io/kubernetes/cluster/kube-up.sh +++ b/vendor/k8s.io/kubernetes/cluster/kube-up.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -63,6 +63,8 @@ echo "... calling verify-prereqs" >&2 verify-prereqs echo "... calling verify-kube-binaries" >&2 verify-kube-binaries +echo "... calling verify-release-tars" >&2 +verify-release-tars echo "... calling kube-up" >&2 kube-up diff --git a/vendor/k8s.io/kubernetes/cluster/kube-util.sh b/vendor/k8s.io/kubernetes/cluster/kube-util.sh index b35fddf4f..8c2ebe2c2 100755 --- a/vendor/k8s.io/kubernetes/cluster/kube-util.sh +++ b/vendor/k8s.io/kubernetes/cluster/kube-util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/kubeadm.sh b/vendor/k8s.io/kubernetes/cluster/kubeadm.sh index d5912abcf..bf4109020 100755 --- a/vendor/k8s.io/kubernetes/cluster/kubeadm.sh +++ b/vendor/k8s.io/kubernetes/cluster/kubeadm.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -19,7 +19,6 @@ set -o nounset set -o pipefail KUBE_ROOT=${KUBE_ROOT:-$(dirname "${BASH_SOURCE}")/..} -source "${KUBE_ROOT}/cluster/kube-util.sh" source "${KUBE_ROOT}/cluster/clientbin.sh" # If KUBEADM_PATH isn't set, gather up the list of likely places and use ls diff --git a/vendor/k8s.io/kubernetes/cluster/kubectl.sh b/vendor/k8s.io/kubernetes/cluster/kubectl.sh index 13cdf4791..4c03b6bfe 100755 --- a/vendor/k8s.io/kubernetes/cluster/kubectl.sh +++ b/vendor/k8s.io/kubernetes/cluster/kubectl.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/kubemark/gce/config-default.sh b/vendor/k8s.io/kubernetes/cluster/kubemark/gce/config-default.sh index 1e668ea53..b042ac431 100644 --- a/vendor/k8s.io/kubernetes/cluster/kubemark/gce/config-default.sh +++ b/vendor/k8s.io/kubernetes/cluster/kubemark/gce/config-default.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -37,7 +37,7 @@ EVENT_PD=${EVENT_PD:-false} MASTER_OS_DISTRIBUTION=${KUBE_MASTER_OS_DISTRIBUTION:-gci} NODE_OS_DISTRIBUTION=${KUBE_NODE_OS_DISTRIBUTION:-gci} -MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-cos-stable-63-10032-71-0} +MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-cos-stable-65-10323-64-0} MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-cos-cloud} # GPUs supported in GCE do not have compatible drivers in Debian 7. @@ -62,7 +62,7 @@ TERMINATED_POD_GC_THRESHOLD=${TERMINATED_POD_GC_THRESHOLD:-100} KUBE_APISERVER_REQUEST_TIMEOUT=300 ETCD_COMPACTION_INTERVAL_SEC="${KUBEMARK_ETCD_COMPACTION_INTERVAL_SEC:-}" -# Set etcd image (e.g. k8s.gcr.io/etcd) and version (e.g. 3.1.12) if you need +# Set etcd image (e.g. k8s.gcr.io/etcd) and version (e.g. 3.1.12-1) if you need # non-default version. ETCD_IMAGE="${TEST_ETCD_IMAGE:-}" ETCD_VERSION="${TEST_ETCD_VERSION:-}" @@ -73,7 +73,7 @@ STORAGE_BACKEND=${STORAGE_BACKEND:-} STORAGE_MEDIA_TYPE=${STORAGE_MEDIA_TYPE:-} # Default Log level for all components in test clusters and variables to override it in specific components. -TEST_CLUSTER_LOG_LEVEL="${TEST_CLUSTER_LOG_LEVEL:---v=2}" +TEST_CLUSTER_LOG_LEVEL="${TEST_CLUSTER_LOG_LEVEL:---v=4}" KUBELET_TEST_LOG_LEVEL="${KUBELET_TEST_LOG_LEVEL:-$TEST_CLUSTER_LOG_LEVEL}" API_SERVER_TEST_LOG_LEVEL="${API_SERVER_TEST_LOG_LEVEL:-$TEST_CLUSTER_LOG_LEVEL}" CONTROLLER_MANAGER_TEST_LOG_LEVEL="${CONTROLLER_MANAGER_TEST_LOG_LEVEL:-$TEST_CLUSTER_LOG_LEVEL}" @@ -89,10 +89,10 @@ TEST_CLUSTER_API_CONTENT_TYPE="${TEST_CLUSTER_API_CONTENT_TYPE:-}" KUBEMARK_MASTER_COMPONENTS_QPS_LIMITS="${KUBEMARK_MASTER_COMPONENTS_QPS_LIMITS:-}" -CUSTOM_ADMISSION_PLUGINS="${CUSTOM_ADMISSION_PLUGINS:-Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,PodPreset,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,Priority,StorageObjectInUseProtection,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota}" +CUSTOM_ADMISSION_PLUGINS="${CUSTOM_ADMISSION_PLUGINS:-Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,Priority,StorageObjectInUseProtection,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota}" # Master components' test arguments. -APISERVER_TEST_ARGS="${KUBEMARK_APISERVER_TEST_ARGS:-} --runtime-config=extensions/v1beta1 ${API_SERVER_TEST_LOG_LEVEL} ${TEST_CLUSTER_MAX_REQUESTS_INFLIGHT} ${TEST_CLUSTER_DELETE_COLLECTION_WORKERS}" +APISERVER_TEST_ARGS="${KUBEMARK_APISERVER_TEST_ARGS:-} --vmodule=httplog=3 --runtime-config=extensions/v1beta1,scheduling.k8s.io/v1alpha1 ${API_SERVER_TEST_LOG_LEVEL} ${TEST_CLUSTER_MAX_REQUESTS_INFLIGHT} ${TEST_CLUSTER_DELETE_COLLECTION_WORKERS}" CONTROLLER_MANAGER_TEST_ARGS="${KUBEMARK_CONTROLLER_MANAGER_TEST_ARGS:-} ${CONTROLLER_MANAGER_TEST_LOG_LEVEL} ${TEST_CLUSTER_RESYNC_PERIOD} ${TEST_CLUSTER_API_CONTENT_TYPE} ${KUBEMARK_MASTER_COMPONENTS_QPS_LIMITS}" SCHEDULER_TEST_ARGS="${KUBEMARK_SCHEDULER_TEST_ARGS:-} ${SCHEDULER_TEST_LOG_LEVEL} ${TEST_CLUSTER_API_CONTENT_TYPE} ${KUBEMARK_MASTER_COMPONENTS_QPS_LIMITS}" @@ -117,13 +117,13 @@ if [[ "${ENABLE_KUBEMARK_CLUSTER_AUTOSCALER}" == "true" ]]; then fi fi +#Optional: Enable kube dns. +ENABLE_KUBEMARK_KUBE_DNS="${ENABLE_KUBEMARK_KUBE_DNS:-true}" +KUBE_DNS_DOMAIN="${KUBE_DNS_DOMAIN:-cluster.local}" + # Optional: set feature gates FEATURE_GATES="${KUBE_FEATURE_GATES:-ExperimentalCriticalPodAnnotation=true}" -if [[ ! -z "${NODE_ACCELERATORS}" ]]; then - FEATURE_GATES="${FEATURE_GATES},Accelerators=true" -fi - # Enable a simple "AdvancedAuditing" setup for testing. ENABLE_APISERVER_ADVANCED_AUDIT="${ENABLE_APISERVER_ADVANCED_AUDIT:-false}" diff --git a/vendor/k8s.io/kubernetes/cluster/kubemark/pre-existing/config-default.sh b/vendor/k8s.io/kubernetes/cluster/kubemark/pre-existing/config-default.sh index d6e4ab518..de1931297 100644 --- a/vendor/k8s.io/kubernetes/cluster/kubemark/pre-existing/config-default.sh +++ b/vendor/k8s.io/kubernetes/cluster/kubemark/pre-existing/config-default.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/vendor/k8s.io/kubernetes/cluster/kubemark/util.sh b/vendor/k8s.io/kubernetes/cluster/kubemark/util.sh index 3b48f87a2..348f3d009 100644 --- a/vendor/k8s.io/kubernetes/cluster/kubemark/util.sh +++ b/vendor/k8s.io/kubernetes/cluster/kubemark/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/kubernetes-anywhere/util.sh b/vendor/k8s.io/kubernetes/cluster/kubernetes-anywhere/util.sh index 8d80b103d..46fedc140 100755 --- a/vendor/k8s.io/kubernetes/cluster/kubernetes-anywhere/util.sh +++ b/vendor/k8s.io/kubernetes/cluster/kubernetes-anywhere/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/vendor/k8s.io/kubernetes/cluster/local/util.sh b/vendor/k8s.io/kubernetes/cluster/local/util.sh index 92e328152..4c437f686 100755 --- a/vendor/k8s.io/kubernetes/cluster/local/util.sh +++ b/vendor/k8s.io/kubernetes/cluster/local/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/vendor/k8s.io/kubernetes/cluster/log-dump/log-dump.sh b/vendor/k8s.io/kubernetes/cluster/log-dump/log-dump.sh index f61c6de34..662001fa6 100755 --- a/vendor/k8s.io/kubernetes/cluster/log-dump/log-dump.sh +++ b/vendor/k8s.io/kubernetes/cluster/log-dump/log-dump.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -50,7 +50,7 @@ readonly gce_logfiles="startupscript" readonly kern_logfile="kern" readonly initd_logfiles="docker" readonly supervisord_logfiles="kubelet supervisor/supervisord supervisor/kubelet-stdout supervisor/kubelet-stderr supervisor/docker-stdout supervisor/docker-stderr" -readonly systemd_services="kubelet ${LOG_DUMP_SYSTEMD_SERVICES:-docker}" +readonly systemd_services="kubelet kubelet-monitor kube-container-runtime-monitor ${LOG_DUMP_SYSTEMD_SERVICES:-docker}" # Limit the number of concurrent node connections so that we don't run out of # file descriptors for large clusters. @@ -294,7 +294,7 @@ function dump_nodes_with_logexporter() { local -r service_account_credentials="$(cat ${GOOGLE_APPLICATION_CREDENTIALS} | base64 | tr -d '\n')" local -r cloud_provider="${KUBERNETES_PROVIDER}" local -r enable_hollow_node_logs="${ENABLE_HOLLOW_NODE_LOGS:-false}" - local -r logexport_sleep_seconds="$(( 90 + NUM_NODES / 5 ))" + local -r logexport_sleep_seconds="$(( 90 + NUM_NODES / 3 ))" # Fill in the parameters in the logexporter daemonset template. sed -i'' -e "s@{{.LogexporterNamespace}}@${logexporter_namespace}@g" "${KUBE_ROOT}/cluster/log-dump/logexporter-daemonset.yaml" @@ -345,6 +345,7 @@ function dump_nodes_with_logexporter() { done # Delete the logexporter resources and dump logs for the failed nodes (if any) through SSH. + "${KUBECTL}" get pods --namespace "${logexporter_namespace}" || true "${KUBECTL}" delete namespace "${logexporter_namespace}" || true if [[ "${#failed_nodes[@]}" != 0 ]]; then echo -e "Dumping logs through SSH for the following nodes:\n${failed_nodes[@]}" diff --git a/vendor/k8s.io/kubernetes/cluster/pre-existing/util.sh b/vendor/k8s.io/kubernetes/cluster/pre-existing/util.sh index 8443653c5..f77b15e91 100644 --- a/vendor/k8s.io/kubernetes/cluster/pre-existing/util.sh +++ b/vendor/k8s.io/kubernetes/cluster/pre-existing/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/restore-from-backup.sh b/vendor/k8s.io/kubernetes/cluster/restore-from-backup.sh index 1ef4d8619..5aab78f50 100755 --- a/vendor/k8s.io/kubernetes/cluster/restore-from-backup.sh +++ b/vendor/k8s.io/kubernetes/cluster/restore-from-backup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/skeleton/util.sh b/vendor/k8s.io/kubernetes/cluster/skeleton/util.sh index 0cd475610..6b15ca786 100644 --- a/vendor/k8s.io/kubernetes/cluster/skeleton/util.sh +++ b/vendor/k8s.io/kubernetes/cluster/skeleton/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/test-e2e.sh b/vendor/k8s.io/kubernetes/cluster/test-e2e.sh index 4b33ffca7..4ea71b80c 100755 --- a/vendor/k8s.io/kubernetes/cluster/test-e2e.sh +++ b/vendor/k8s.io/kubernetes/cluster/test-e2e.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/test-network.sh b/vendor/k8s.io/kubernetes/cluster/test-network.sh index 37f54ba03..239bb8aa1 100755 --- a/vendor/k8s.io/kubernetes/cluster/test-network.sh +++ b/vendor/k8s.io/kubernetes/cluster/test-network.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/test-smoke.sh b/vendor/k8s.io/kubernetes/cluster/test-smoke.sh index 11edd1854..3e0561d89 100755 --- a/vendor/k8s.io/kubernetes/cluster/test-smoke.sh +++ b/vendor/k8s.io/kubernetes/cluster/test-smoke.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cluster/update-storage-objects.sh b/vendor/k8s.io/kubernetes/cluster/update-storage-objects.sh index 364c1d7e3..386d23395 100755 --- a/vendor/k8s.io/kubernetes/cluster/update-storage-objects.sh +++ b/vendor/k8s.io/kubernetes/cluster/update-storage-objects.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -104,7 +104,8 @@ do # This happens when the instance has been deleted. We can hence ignore # this instance. echo "Looks like ${instance} got deleted. Ignoring it" - continue + success=1 + break fi output=$("${KUBECTL}" replace -f "${filename}" --namespace="${namespace}") || true rm "${filename}" diff --git a/vendor/k8s.io/kubernetes/cluster/validate-cluster.sh b/vendor/k8s.io/kubernetes/cluster/validate-cluster.sh index ec495069f..3a101193e 100755 --- a/vendor/k8s.io/kubernetes/cluster/validate-cluster.sh +++ b/vendor/k8s.io/kubernetes/cluster/validate-cluster.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/cmd/clicheck/BUILD b/vendor/k8s.io/kubernetes/cmd/clicheck/BUILD index cafcaec3a..db6e92a3c 100644 --- a/vendor/k8s.io/kubernetes/cmd/clicheck/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/clicheck/BUILD @@ -17,7 +17,6 @@ go_library( importpath = "k8s.io/kubernetes/cmd/clicheck", deps = [ "//pkg/kubectl/cmd:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util/sanity:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/clicheck/check_cli_conventions.go b/vendor/k8s.io/kubernetes/cmd/clicheck/check_cli_conventions.go index 524f9f05d..17d109d51 100644 --- a/vendor/k8s.io/kubernetes/cmd/clicheck/check_cli_conventions.go +++ b/vendor/k8s.io/kubernetes/cmd/clicheck/check_cli_conventions.go @@ -22,7 +22,6 @@ import ( "os" "k8s.io/kubernetes/pkg/kubectl/cmd" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdsanity "k8s.io/kubernetes/pkg/kubectl/cmd/util/sanity" ) @@ -33,7 +32,7 @@ var ( func main() { var errorCount int - kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + kubectl := cmd.NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard) errors := cmdsanity.RunCmdChecks(kubectl, cmdsanity.AllCmdChecks, []string{}) for _, err := range errors { errorCount++ diff --git a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/OWNERS b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/OWNERS index 5a58eee8c..85347d439 100644 --- a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/OWNERS +++ b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/OWNERS @@ -2,7 +2,9 @@ approvers: - thockin - luxas - wlan0 +- andrewsykim reviewers: - thockin - luxas - wlan0 +- andrewsykim diff --git a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/BUILD b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/BUILD index 3574f5d64..4fed506a5 100644 --- a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/BUILD @@ -26,7 +26,6 @@ go_library( "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/leaderelection:go_default_library", "//vendor/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library", - "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/config/BUILD b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/config/BUILD index 5f4ce185b..157c45435 100644 --- a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/config/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/config/BUILD @@ -5,7 +5,14 @@ go_library( srcs = ["config.go"], importpath = "k8s.io/kubernetes/cmd/cloud-controller-manager/app/config", visibility = ["//visibility:public"], - deps = ["//cmd/controller-manager/app:go_default_library"], + deps = [ + "//cmd/controller-manager/app:go_default_library", + "//pkg/apis/componentconfig:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", + ], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/config/config.go b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/config/config.go index ca31d87cd..3d201e475 100644 --- a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/config/config.go +++ b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/config/config.go @@ -17,25 +17,39 @@ limitations under the License. package app import ( - "time" - + apiserver "k8s.io/apiserver/pkg/server" + clientset "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/tools/record" genericcontrollermanager "k8s.io/kubernetes/cmd/controller-manager/app" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) -// ExtraConfig are part of Config, also can place your custom config here. -type ExtraConfig struct { - NodeStatusUpdateFrequency time.Duration -} - // Config is the main context object for the cloud controller manager. type Config struct { - Generic genericcontrollermanager.Config - Extra ExtraConfig + ComponentConfig componentconfig.CloudControllerManagerConfiguration + + SecureServing *apiserver.SecureServingInfo + // TODO: remove deprecated insecure serving + InsecureServing *genericcontrollermanager.InsecureServingInfo + Authentication apiserver.AuthenticationInfo + Authorization apiserver.AuthorizationInfo + + // the general kube client + Client *clientset.Clientset + + // the client only used for leader election + LeaderElectionClient *clientset.Clientset + + // the rest config for the master + Kubeconfig *restclient.Config + + // the event sink + EventRecorder record.EventRecorder } type completedConfig struct { - Generic genericcontrollermanager.CompletedConfig - Extra *ExtraConfig + *Config } // CompletedConfig same as Config, just to swap private object. @@ -46,10 +60,6 @@ type CompletedConfig struct { // Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. func (c *Config) Complete() *CompletedConfig { - cc := completedConfig{ - c.Generic.Complete(), - &c.Extra, - } - + cc := completedConfig{c} return &CompletedConfig{&cc} } diff --git a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/controllermanager.go b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/controllermanager.go index 36a83fc86..01c4bfe2b 100644 --- a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/controllermanager.go +++ b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/controllermanager.go @@ -34,7 +34,6 @@ import ( restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/leaderelection" "k8s.io/client-go/tools/leaderelection/resourcelock" - "k8s.io/client-go/tools/record" cloudcontrollerconfig "k8s.io/kubernetes/cmd/cloud-controller-manager/app/config" "k8s.io/kubernetes/cmd/cloud-controller-manager/app/options" genericcontrollermanager "k8s.io/kubernetes/cmd/controller-manager/app" @@ -55,7 +54,11 @@ const ( // NewCloudControllerManagerCommand creates a *cobra.Command object with default parameters func NewCloudControllerManagerCommand() *cobra.Command { - s := options.NewCloudControllerManagerOptions() + s, err := options.NewCloudControllerManagerOptions() + if err != nil { + glog.Fatalf("unable to initialize command options: %v", err) + } + cmd := &cobra.Command{ Use: "cloud-controller-manager", Long: `The Cloud controller manager is a daemon that embeds @@ -86,13 +89,13 @@ the cloud specific control loops shipped with Kubernetes.`, func resyncPeriod(c *cloudcontrollerconfig.CompletedConfig) func() time.Duration { return func() time.Duration { factor := rand.Float64() + 1 - return time.Duration(float64(c.Generic.ComponentConfig.MinResyncPeriod.Nanoseconds()) * factor) + return time.Duration(float64(c.ComponentConfig.GenericComponent.MinResyncPeriod.Nanoseconds()) * factor) } } // Run runs the ExternalCMServer. This should never exit. func Run(c *cloudcontrollerconfig.CompletedConfig) error { - cloud, err := cloudprovider.InitCloudProvider(c.Generic.ComponentConfig.CloudProvider, c.Generic.ComponentConfig.CloudConfigFile) + cloud, err := cloudprovider.InitCloudProvider(c.ComponentConfig.CloudProvider.Name, c.ComponentConfig.CloudProvider.CloudConfigFile) if err != nil { glog.Fatalf("Cloud provider could not be initialized: %v", err) } @@ -101,7 +104,7 @@ func Run(c *cloudcontrollerconfig.CompletedConfig) error { } if cloud.HasClusterID() == false { - if c.Generic.ComponentConfig.AllowUntaggedCloud == true { + if c.ComponentConfig.KubeCloudShared.AllowUntaggedCloud == true { glog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues") } else { glog.Fatalf("no ClusterID found. A ClusterID is required for the cloud provider to function properly. This check can be bypassed by setting the allow-untagged-cloud option") @@ -110,46 +113,50 @@ func Run(c *cloudcontrollerconfig.CompletedConfig) error { // setup /configz endpoint if cz, err := configz.New("componentconfig"); err == nil { - cz.Set(c.Generic.ComponentConfig) + cz.Set(c.ComponentConfig) } else { glog.Errorf("unable to register configz: %c", err) } // Start the controller manager HTTP server stopCh := make(chan struct{}) - if c.Generic.SecureServing != nil { - if err := genericcontrollermanager.Serve(&c.Generic, c.Generic.SecureServing.Serve, stopCh); err != nil { + if c.SecureServing != nil { + handler := genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Debugging) + handler = genericcontrollermanager.BuildHandlerChain(handler, &c.Authorization, &c.Authentication) + if err := c.SecureServing.Serve(handler, 0, stopCh); err != nil { return err } } - if c.Generic.InsecureServing != nil { - if err := genericcontrollermanager.Serve(&c.Generic, c.Generic.InsecureServing.Serve, stopCh); err != nil { + if c.InsecureServing != nil { + handler := genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Debugging) + handler = genericcontrollermanager.BuildHandlerChain(handler, &c.Authorization, &c.Authentication) + if err := c.InsecureServing.Serve(handler, 0, stopCh); err != nil { return err } } run := func(stop <-chan struct{}) { rootClientBuilder := controller.SimpleControllerClientBuilder{ - ClientConfig: c.Generic.Kubeconfig, + ClientConfig: c.Kubeconfig, } var clientBuilder controller.ControllerClientBuilder - if c.Generic.ComponentConfig.UseServiceAccountCredentials { + if c.ComponentConfig.KubeCloudShared.UseServiceAccountCredentials { clientBuilder = controller.SAControllerClientBuilder{ - ClientConfig: restclient.AnonymousClientConfig(c.Generic.Kubeconfig), - CoreClient: c.Generic.Client.CoreV1(), - AuthenticationClient: c.Generic.Client.AuthenticationV1(), + ClientConfig: restclient.AnonymousClientConfig(c.Kubeconfig), + CoreClient: c.Client.CoreV1(), + AuthenticationClient: c.Client.AuthenticationV1(), Namespace: "kube-system", } } else { clientBuilder = rootClientBuilder } - if err := startControllers(c, c.Generic.Kubeconfig, rootClientBuilder, clientBuilder, stop, c.Generic.EventRecorder, cloud); err != nil { + if err := startControllers(c, rootClientBuilder, clientBuilder, stop, cloud); err != nil { glog.Fatalf("error running controllers: %v", err) } } - if !c.Generic.ComponentConfig.LeaderElection.LeaderElect { + if !c.ComponentConfig.GenericComponent.LeaderElection.LeaderElect { run(nil) panic("unreachable") } @@ -163,13 +170,13 @@ func Run(c *cloudcontrollerconfig.CompletedConfig) error { id = id + "_" + string(uuid.NewUUID()) // Lock required for leader election - rl, err := resourcelock.New(c.Generic.ComponentConfig.LeaderElection.ResourceLock, + rl, err := resourcelock.New(c.ComponentConfig.GenericComponent.LeaderElection.ResourceLock, "kube-system", "cloud-controller-manager", - c.Generic.LeaderElectionClient.CoreV1(), + c.LeaderElectionClient.CoreV1(), resourcelock.ResourceLockConfig{ Identity: id, - EventRecorder: c.Generic.EventRecorder, + EventRecorder: c.EventRecorder, }) if err != nil { glog.Fatalf("error creating lock: %v", err) @@ -178,9 +185,9 @@ func Run(c *cloudcontrollerconfig.CompletedConfig) error { // Try and become the leader and start cloud controller manager loops leaderelection.RunOrDie(leaderelection.LeaderElectionConfig{ Lock: rl, - LeaseDuration: c.Generic.ComponentConfig.LeaderElection.LeaseDuration.Duration, - RenewDeadline: c.Generic.ComponentConfig.LeaderElection.RenewDeadline.Duration, - RetryPeriod: c.Generic.ComponentConfig.LeaderElection.RetryPeriod.Duration, + LeaseDuration: c.ComponentConfig.GenericComponent.LeaderElection.LeaseDuration.Duration, + RenewDeadline: c.ComponentConfig.GenericComponent.LeaderElection.RenewDeadline.Duration, + RetryPeriod: c.ComponentConfig.GenericComponent.LeaderElection.RetryPeriod.Duration, Callbacks: leaderelection.LeaderCallbacks{ OnStartedLeading: run, OnStoppedLeading: func() { @@ -192,7 +199,7 @@ func Run(c *cloudcontrollerconfig.CompletedConfig) error { } // startControllers starts the cloud specific controller loops. -func startControllers(c *cloudcontrollerconfig.CompletedConfig, kubeconfig *restclient.Config, rootClientBuilder, clientBuilder controller.ControllerClientBuilder, stop <-chan struct{}, recorder record.EventRecorder, cloud cloudprovider.Interface) error { +func startControllers(c *cloudcontrollerconfig.CompletedConfig, rootClientBuilder, clientBuilder controller.ControllerClientBuilder, stop <-chan struct{}, cloud cloudprovider.Interface) error { // Function to build the kube client object client := func(serviceAccountName string) kubernetes.Interface { return clientBuilder.ClientOrDie(serviceAccountName) @@ -210,17 +217,16 @@ func startControllers(c *cloudcontrollerconfig.CompletedConfig, kubeconfig *rest nodeController := cloudcontrollers.NewCloudNodeController( sharedInformers.Core().V1().Nodes(), client("cloud-node-controller"), cloud, - c.Generic.ComponentConfig.NodeMonitorPeriod.Duration, - c.Extra.NodeStatusUpdateFrequency) + c.ComponentConfig.KubeCloudShared.NodeMonitorPeriod.Duration, + c.ComponentConfig.NodeStatusUpdateFrequency.Duration) - nodeController.Run() - time.Sleep(wait.Jitter(c.Generic.ComponentConfig.ControllerStartInterval.Duration, ControllerStartJitter)) + nodeController.Run(stop) + time.Sleep(wait.Jitter(c.ComponentConfig.GenericComponent.ControllerStartInterval.Duration, ControllerStartJitter)) // Start the PersistentVolumeLabelController pvlController := cloudcontrollers.NewPersistentVolumeLabelController(client("pvl-controller"), cloud) - threads := 5 - go pvlController.Run(threads, stop) - time.Sleep(wait.Jitter(c.Generic.ComponentConfig.ControllerStartInterval.Duration, ControllerStartJitter)) + go pvlController.Run(5, stop) + time.Sleep(wait.Jitter(c.ComponentConfig.GenericComponent.ControllerStartInterval.Duration, ControllerStartJitter)) // Start the service controller serviceController, err := servicecontroller.New( @@ -228,34 +234,34 @@ func startControllers(c *cloudcontrollerconfig.CompletedConfig, kubeconfig *rest client("service-controller"), sharedInformers.Core().V1().Services(), sharedInformers.Core().V1().Nodes(), - c.Generic.ComponentConfig.ClusterName, + c.ComponentConfig.KubeCloudShared.ClusterName, ) if err != nil { glog.Errorf("Failed to start service controller: %v", err) } else { - go serviceController.Run(stop, int(c.Generic.ComponentConfig.ConcurrentServiceSyncs)) - time.Sleep(wait.Jitter(c.Generic.ComponentConfig.ControllerStartInterval.Duration, ControllerStartJitter)) + go serviceController.Run(stop, int(c.ComponentConfig.ServiceController.ConcurrentServiceSyncs)) + time.Sleep(wait.Jitter(c.ComponentConfig.GenericComponent.ControllerStartInterval.Duration, ControllerStartJitter)) } // If CIDRs should be allocated for pods and set on the CloudProvider, then start the route controller - if c.Generic.ComponentConfig.AllocateNodeCIDRs && c.Generic.ComponentConfig.ConfigureCloudRoutes { + if c.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs && c.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes { if routes, ok := cloud.Routes(); !ok { glog.Warning("configure-cloud-routes is set, but cloud provider does not support routes. Will not configure cloud provider routes.") } else { var clusterCIDR *net.IPNet - if len(strings.TrimSpace(c.Generic.ComponentConfig.ClusterCIDR)) != 0 { - _, clusterCIDR, err = net.ParseCIDR(c.Generic.ComponentConfig.ClusterCIDR) + if len(strings.TrimSpace(c.ComponentConfig.KubeCloudShared.ClusterCIDR)) != 0 { + _, clusterCIDR, err = net.ParseCIDR(c.ComponentConfig.KubeCloudShared.ClusterCIDR) if err != nil { - glog.Warningf("Unsuccessful parsing of cluster CIDR %v: %v", c.Generic.ComponentConfig.ClusterCIDR, err) + glog.Warningf("Unsuccessful parsing of cluster CIDR %v: %v", c.ComponentConfig.KubeCloudShared.ClusterCIDR, err) } } - routeController := routecontroller.New(routes, client("route-controller"), sharedInformers.Core().V1().Nodes(), c.Generic.ComponentConfig.ClusterName, clusterCIDR) - go routeController.Run(stop, c.Generic.ComponentConfig.RouteReconciliationPeriod.Duration) - time.Sleep(wait.Jitter(c.Generic.ComponentConfig.ControllerStartInterval.Duration, ControllerStartJitter)) + routeController := routecontroller.New(routes, client("route-controller"), sharedInformers.Core().V1().Nodes(), c.ComponentConfig.KubeCloudShared.ClusterName, clusterCIDR) + go routeController.Run(stop, c.ComponentConfig.KubeCloudShared.RouteReconciliationPeriod.Duration) + time.Sleep(wait.Jitter(c.ComponentConfig.GenericComponent.ControllerStartInterval.Duration, ControllerStartJitter)) } } else { - glog.Infof("Will not configure cloud provider routes for allocate-node-cidrs: %v, configure-cloud-routes: %v.", c.Generic.ComponentConfig.AllocateNodeCIDRs, c.Generic.ComponentConfig.ConfigureCloudRoutes) + glog.Infof("Will not configure cloud provider routes for allocate-node-cidrs: %v, configure-cloud-routes: %v.", c.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs, c.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes) } // If apiserver is not running we should wait for some time and fail only then. This is particularly diff --git a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/BUILD b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/BUILD index e1308993a..7e36ffa8d 100644 --- a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/BUILD @@ -13,13 +13,24 @@ go_library( deps = [ "//cmd/cloud-controller-manager/app/config:go_default_library", "//cmd/controller-manager/app/options:go_default_library", - "//pkg/client/leaderelectionconfig:go_default_library", + "//pkg/api/legacyscheme:go_default_library", + "//pkg/apis/componentconfig:go_default_library", + "//pkg/apis/componentconfig/v1alpha1:go_default_library", "//pkg/features:go_default_library", "//pkg/master/ports:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server/options: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/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/options.go b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/options.go index 530137ff6..2dc7a0534 100644 --- a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/options.go +++ b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/options.go @@ -18,71 +18,185 @@ package options import ( "fmt" - "time" + "net" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" utilerrors "k8s.io/apimachinery/pkg/util/errors" + apiserveroptions "k8s.io/apiserver/pkg/server/options" utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/client-go/kubernetes" + clientset "k8s.io/client-go/kubernetes" + v1core "k8s.io/client-go/kubernetes/typed/core/v1" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/record" cloudcontrollerconfig "k8s.io/kubernetes/cmd/cloud-controller-manager/app/config" cmoptions "k8s.io/kubernetes/cmd/controller-manager/app/options" - "k8s.io/kubernetes/pkg/client/leaderelectionconfig" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/componentconfig" + componentconfigv1alpha1 "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" "k8s.io/kubernetes/pkg/master/ports" - // add the kubernetes feature gates _ "k8s.io/kubernetes/pkg/features" + "github.com/golang/glog" "github.com/spf13/pflag" ) +const ( + // CloudControllerManagerUserAgent is the userAgent name when starting cloud-controller managers. + CloudControllerManagerUserAgent = "cloud-controller-manager" +) + // CloudControllerManagerOptions is the main context object for the controller manager. type CloudControllerManagerOptions struct { - Generic cmoptions.GenericControllerManagerOptions + CloudProvider *cmoptions.CloudProviderOptions + Debugging *cmoptions.DebuggingOptions + GenericComponent *cmoptions.GenericComponentConfigOptions + KubeCloudShared *cmoptions.KubeCloudSharedOptions + ServiceController *cmoptions.ServiceControllerOptions + + SecureServing *apiserveroptions.SecureServingOptions + // TODO: remove insecure serving mode + InsecureServing *cmoptions.InsecureServingOptions + Authentication *apiserveroptions.DelegatingAuthenticationOptions + Authorization *apiserveroptions.DelegatingAuthorizationOptions + + Master string + Kubeconfig string // NodeStatusUpdateFrequency is the frequency at which the controller updates nodes' status NodeStatusUpdateFrequency metav1.Duration } // NewCloudControllerManagerOptions creates a new ExternalCMServer with a default config. -func NewCloudControllerManagerOptions() *CloudControllerManagerOptions { - componentConfig := cmoptions.NewDefaultControllerManagerComponentConfig(ports.InsecureCloudControllerManagerPort) +func NewCloudControllerManagerOptions() (*CloudControllerManagerOptions, error) { + componentConfig, err := NewDefaultComponentConfig(ports.InsecureCloudControllerManagerPort) + if err != nil { + return nil, err + } s := CloudControllerManagerOptions{ - // The common/default are kept in 'cmd/kube-controller-manager/app/options/util.go'. - // Please make common changes there and put anything cloud specific here. - Generic: cmoptions.NewGenericControllerManagerOptions(componentConfig), - NodeStatusUpdateFrequency: metav1.Duration{Duration: 5 * time.Minute}, + CloudProvider: &cmoptions.CloudProviderOptions{}, + Debugging: &cmoptions.DebuggingOptions{}, + GenericComponent: cmoptions.NewGenericComponentConfigOptions(componentConfig.GenericComponent), + KubeCloudShared: cmoptions.NewKubeCloudSharedOptions(componentConfig.KubeCloudShared), + ServiceController: &cmoptions.ServiceControllerOptions{ + ConcurrentServiceSyncs: componentConfig.ServiceController.ConcurrentServiceSyncs, + }, + SecureServing: apiserveroptions.NewSecureServingOptions(), + InsecureServing: &cmoptions.InsecureServingOptions{ + BindAddress: net.ParseIP(componentConfig.KubeCloudShared.Address), + BindPort: int(componentConfig.KubeCloudShared.Port), + BindNetwork: "tcp", + }, + Authentication: nil, // TODO: enable with apiserveroptions.NewDelegatingAuthenticationOptions() + Authorization: nil, // TODO: enable with apiserveroptions.NewDelegatingAuthorizationOptions() + NodeStatusUpdateFrequency: componentConfig.NodeStatusUpdateFrequency, } - s.Generic.ComponentConfig.LeaderElection.LeaderElect = true - s.Generic.SecureServing.ServerCert.CertDirectory = "/var/run/kubernetes" - s.Generic.SecureServing.ServerCert.PairName = "cloud-controller-manager" + s.SecureServing.ServerCert.CertDirectory = "/var/run/kubernetes" + s.SecureServing.ServerCert.PairName = "cloud-controller-manager" + + // disable secure serving for now + // TODO: enable HTTPS by default + s.SecureServing.BindPort = 0 - return &s + return &s, nil +} + +// NewDefaultComponentConfig returns cloud-controller manager configuration object. +func NewDefaultComponentConfig(insecurePort int32) (componentconfig.CloudControllerManagerConfiguration, error) { + scheme := runtime.NewScheme() + componentconfigv1alpha1.AddToScheme(scheme) + componentconfig.AddToScheme(scheme) + + versioned := componentconfigv1alpha1.CloudControllerManagerConfiguration{} + scheme.Default(&versioned) + + internal := componentconfig.CloudControllerManagerConfiguration{} + if err := scheme.Convert(&versioned, &internal, nil); err != nil { + return internal, err + } + internal.KubeCloudShared.Port = insecurePort + return internal, nil } // AddFlags adds flags for a specific ExternalCMServer to the specified FlagSet func (o *CloudControllerManagerOptions) AddFlags(fs *pflag.FlagSet) { - o.Generic.AddFlags(fs) - - fs.StringVar(&o.Generic.ComponentConfig.CloudProvider, "cloud-provider", o.Generic.ComponentConfig.CloudProvider, "The provider of cloud services. Cannot be empty.") + o.CloudProvider.AddFlags(fs) + o.Debugging.AddFlags(fs) + o.GenericComponent.AddFlags(fs) + o.KubeCloudShared.AddFlags(fs) + o.ServiceController.AddFlags(fs) + + o.SecureServing.AddFlags(fs) + o.InsecureServing.AddFlags(fs) + o.Authentication.AddFlags(fs) + o.Authorization.AddFlags(fs) + + fs.StringVar(&o.Master, "master", o.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig).") + fs.StringVar(&o.Kubeconfig, "kubeconfig", o.Kubeconfig, "Path to kubeconfig file with authorization and master location information.") fs.DurationVar(&o.NodeStatusUpdateFrequency.Duration, "node-status-update-frequency", o.NodeStatusUpdateFrequency.Duration, "Specifies how often the controller updates nodes' status.") - // TODO: remove --service-account-private-key-file 6 months after 1.8 is released (~1.10) - fs.StringVar(&o.Generic.ComponentConfig.ServiceAccountKeyFile, "service-account-private-key-file", o.Generic.ComponentConfig.ServiceAccountKeyFile, "Filename containing a PEM-encoded private RSA or ECDSA key used to sign service account tokens.") - fs.MarkDeprecated("service-account-private-key-file", "This flag is currently no-op and will be deleted.") - fs.Int32Var(&o.Generic.ComponentConfig.ConcurrentServiceSyncs, "concurrent-service-syncs", o.Generic.ComponentConfig.ConcurrentServiceSyncs, "The number of services that are allowed to sync concurrently. Larger number = more responsive service management, but more CPU (and network) load") - - leaderelectionconfig.BindFlags(&o.Generic.ComponentConfig.LeaderElection, fs) utilfeature.DefaultFeatureGate.AddFlag(fs) } // ApplyTo fills up cloud controller manager config with options. -func (o *CloudControllerManagerOptions) ApplyTo(c *cloudcontrollerconfig.Config) error { - if err := o.Generic.ApplyTo(&c.Generic, "cloud-controller-manager"); err != nil { +func (o *CloudControllerManagerOptions) ApplyTo(c *cloudcontrollerconfig.Config, userAgent string) error { + if err := o.CloudProvider.ApplyTo(&c.ComponentConfig.CloudProvider); err != nil { + return err + } + if err := o.Debugging.ApplyTo(&c.ComponentConfig.Debugging); err != nil { + return err + } + if err := o.GenericComponent.ApplyTo(&c.ComponentConfig.GenericComponent); err != nil { + return err + } + if err := o.KubeCloudShared.ApplyTo(&c.ComponentConfig.KubeCloudShared); err != nil { + return err + } + if err := o.ServiceController.ApplyTo(&c.ComponentConfig.ServiceController); err != nil { + return err + } + if err := o.SecureServing.ApplyTo(&c.SecureServing); err != nil { + return err + } + if err := o.InsecureServing.ApplyTo(&c.InsecureServing); err != nil { + return err + } + if err := o.Authentication.ApplyTo(&c.Authentication, c.SecureServing, nil); err != nil { + return err + } + if err := o.Authorization.ApplyTo(&c.Authorization); err != nil { return err } - c.Extra.NodeStatusUpdateFrequency = o.NodeStatusUpdateFrequency.Duration + // sync back to component config + // TODO: find more elegant way than syncing back the values. + c.ComponentConfig.KubeCloudShared.Port = int32(o.InsecureServing.BindPort) + c.ComponentConfig.KubeCloudShared.Address = o.InsecureServing.BindAddress.String() + + var err error + c.Kubeconfig, err = clientcmd.BuildConfigFromFlags(o.Master, o.Kubeconfig) + if err != nil { + return err + } + c.Kubeconfig.ContentConfig.ContentType = o.GenericComponent.ContentType + c.Kubeconfig.QPS = o.GenericComponent.KubeAPIQPS + c.Kubeconfig.Burst = int(o.GenericComponent.KubeAPIBurst) + + c.Client, err = clientset.NewForConfig(restclient.AddUserAgent(c.Kubeconfig, userAgent)) + if err != nil { + return err + } + + c.LeaderElectionClient = clientset.NewForConfigOrDie(restclient.AddUserAgent(c.Kubeconfig, "leader-election")) + + c.EventRecorder = createRecorder(c.Client, userAgent) + c.ComponentConfig.NodeStatusUpdateFrequency = o.NodeStatusUpdateFrequency return nil } @@ -90,9 +204,18 @@ func (o *CloudControllerManagerOptions) ApplyTo(c *cloudcontrollerconfig.Config) // Validate is used to validate config before launching the cloud controller manager func (o *CloudControllerManagerOptions) Validate() error { errors := []error{} - errors = append(errors, o.Generic.Validate()...) - if len(o.Generic.ComponentConfig.CloudProvider) == 0 { + errors = append(errors, o.CloudProvider.Validate()...) + errors = append(errors, o.Debugging.Validate()...) + errors = append(errors, o.GenericComponent.Validate()...) + errors = append(errors, o.KubeCloudShared.Validate()...) + errors = append(errors, o.ServiceController.Validate()...) + errors = append(errors, o.SecureServing.Validate()...) + errors = append(errors, o.InsecureServing.Validate()...) + errors = append(errors, o.Authentication.Validate()...) + errors = append(errors, o.Authorization.Validate()...) + + if len(o.CloudProvider.Name) == 0 { errors = append(errors, fmt.Errorf("--cloud-provider cannot be empty")) } @@ -100,15 +223,23 @@ func (o *CloudControllerManagerOptions) Validate() error { } // Config return a cloud controller manager config objective -func (o CloudControllerManagerOptions) Config() (*cloudcontrollerconfig.Config, error) { +func (o *CloudControllerManagerOptions) Config() (*cloudcontrollerconfig.Config, error) { if err := o.Validate(); err != nil { return nil, err } c := &cloudcontrollerconfig.Config{} - if err := o.ApplyTo(c); err != nil { + if err := o.ApplyTo(c, CloudControllerManagerUserAgent); err != nil { return nil, err } return c, nil } + +func createRecorder(kubeClient kubernetes.Interface, userAgent string) record.EventRecorder { + eventBroadcaster := record.NewBroadcaster() + eventBroadcaster.StartLogging(glog.Infof) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) + // TODO: remove dependence on the legacyscheme + return eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: userAgent}) +} diff --git a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/options_test.go b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/options_test.go index e876f7250..0f6f54d6e 100644 --- a/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/options_test.go +++ b/vendor/k8s.io/kubernetes/cmd/cloud-controller-manager/app/options/options_test.go @@ -31,14 +31,78 @@ import ( "k8s.io/kubernetes/pkg/apis/componentconfig" ) +func TestDefaultFlags(t *testing.T) { + s, _ := NewCloudControllerManagerOptions() + + expected := &CloudControllerManagerOptions{ + CloudProvider: &cmoptions.CloudProviderOptions{ + Name: "", + CloudConfigFile: "", + }, + Debugging: &cmoptions.DebuggingOptions{ + EnableContentionProfiling: false, + }, + GenericComponent: &cmoptions.GenericComponentConfigOptions{ + MinResyncPeriod: metav1.Duration{Duration: 12 * time.Hour}, + ContentType: "application/vnd.kubernetes.protobuf", + KubeAPIQPS: 20.0, + KubeAPIBurst: 30, + ControllerStartInterval: metav1.Duration{Duration: 0}, + LeaderElection: componentconfig.LeaderElectionConfiguration{ + ResourceLock: "endpoints", + LeaderElect: true, + LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, + }, + }, + KubeCloudShared: &cmoptions.KubeCloudSharedOptions{ + Port: 10253, // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config + Address: "0.0.0.0", // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config + RouteReconciliationPeriod: metav1.Duration{Duration: 10 * time.Second}, + NodeMonitorPeriod: metav1.Duration{Duration: 5 * time.Second}, + ClusterName: "kubernetes", + ClusterCIDR: "", + AllocateNodeCIDRs: false, + CIDRAllocatorType: "", + ConfigureCloudRoutes: true, + }, + ServiceController: &cmoptions.ServiceControllerOptions{ + ConcurrentServiceSyncs: 1, + }, + SecureServing: &apiserveroptions.SecureServingOptions{ + BindPort: 0, + BindAddress: net.ParseIP("0.0.0.0"), + ServerCert: apiserveroptions.GeneratableKeyCert{ + CertDirectory: "/var/run/kubernetes", + PairName: "cloud-controller-manager", + }, + HTTP2MaxStreamsPerConnection: 0, + }, + InsecureServing: &cmoptions.InsecureServingOptions{ + BindAddress: net.ParseIP("0.0.0.0"), + BindPort: int(10253), + BindNetwork: "tcp", + }, + Kubeconfig: "", + Master: "", + NodeStatusUpdateFrequency: metav1.Duration{Duration: 5 * time.Minute}, + } + if !reflect.DeepEqual(expected, s) { + t.Errorf("Got different run options than expected.\nDifference detected on:\n%s", diff.ObjectReflectDiff(expected, s)) + } +} + func TestAddFlags(t *testing.T) { f := pflag.NewFlagSet("addflagstest", pflag.ContinueOnError) - s := NewCloudControllerManagerOptions() + s, _ := NewCloudControllerManagerOptions() s.AddFlags(f) args := []string{ "--address=192.168.4.10", "--allocate-node-cidrs=true", + "--bind-address=192.168.4.21", + "--cert-dir=/a/b/c", "--cloud-config=/cloud-config", "--cloud-provider=gce", "--cluster-cidr=1.2.3.4/24", @@ -47,7 +111,6 @@ func TestAddFlags(t *testing.T) { "--contention-profiling=true", "--controller-start-interval=2m", "--http2-max-streams-per-connection=47", - "--min-resync-period=5m", "--kube-api-burst=100", "--kube-api-content-type=application/vnd.kubernetes.protobuf", "--kube-api-qps=50.0", @@ -58,109 +121,68 @@ func TestAddFlags(t *testing.T) { "--leader-elect-resource-lock=configmap", "--leader-elect-retry-period=5s", "--master=192.168.4.20", - "--min-resync-period=8h", + "--min-resync-period=100m", + "--node-status-update-frequency=10m", "--port=10000", "--profiling=false", - "--node-status-update-frequency=10m", "--route-reconciliation-period=30s", - "--min-resync-period=100m", - "--use-service-account-credentials=false", - "--cert-dir=/a/b/c", - "--bind-address=192.168.4.21", "--secure-port=10001", + "--use-service-account-credentials=false", } f.Parse(args) expected := &CloudControllerManagerOptions{ - Generic: cmoptions.GenericControllerManagerOptions{ - ComponentConfig: componentconfig.KubeControllerManagerConfiguration{ - CloudProvider: "gce", - CloudConfigFile: "/cloud-config", - Port: 10253, // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config - Address: "0.0.0.0", // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config - ConcurrentEndpointSyncs: 5, - ConcurrentRSSyncs: 5, - ConcurrentResourceQuotaSyncs: 5, - ConcurrentDeploymentSyncs: 5, - ConcurrentDaemonSetSyncs: 2, - ConcurrentJobSyncs: 5, - ConcurrentNamespaceSyncs: 10, - ConcurrentSATokenSyncs: 5, - ConcurrentServiceSyncs: 1, - ConcurrentGCSyncs: 20, - ConcurrentRCSyncs: 5, - MinResyncPeriod: metav1.Duration{Duration: 100 * time.Minute}, - NodeMonitorPeriod: metav1.Duration{Duration: 5 * time.Second}, - ResourceQuotaSyncPeriod: metav1.Duration{Duration: 5 * time.Minute}, - NamespaceSyncPeriod: metav1.Duration{Duration: 5 * time.Minute}, - PVClaimBinderSyncPeriod: metav1.Duration{Duration: 15 * time.Second}, - HorizontalPodAutoscalerSyncPeriod: metav1.Duration{Duration: 30 * time.Second}, - HorizontalPodAutoscalerUpscaleForbiddenWindow: metav1.Duration{Duration: 3 * time.Minute}, - HorizontalPodAutoscalerDownscaleForbiddenWindow: metav1.Duration{Duration: 5 * time.Minute}, - HorizontalPodAutoscalerTolerance: 0.1, - DeploymentControllerSyncPeriod: metav1.Duration{Duration: 30 * time.Second}, - PodEvictionTimeout: metav1.Duration{Duration: 5 * time.Minute}, - NodeMonitorGracePeriod: metav1.Duration{Duration: 40 * time.Second}, - NodeStartupGracePeriod: metav1.Duration{Duration: 1 * time.Minute}, - ClusterSigningDuration: metav1.Duration{Duration: 8760 * time.Hour}, - ReconcilerSyncLoopPeriod: metav1.Duration{Duration: 1 * time.Minute}, - TerminatedPodGCThreshold: 12500, - RegisterRetryCount: 10, - ClusterName: "k8s", - ConfigureCloudRoutes: false, - AllocateNodeCIDRs: true, - EnableGarbageCollector: true, - EnableTaintManager: true, - HorizontalPodAutoscalerUseRESTClients: true, - VolumeConfiguration: componentconfig.VolumeConfiguration{ - EnableDynamicProvisioning: true, - EnableHostPathProvisioning: false, - FlexVolumePluginDir: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/", - PersistentVolumeRecyclerConfiguration: componentconfig.PersistentVolumeRecyclerConfiguration{ - MaximumRetry: 3, - MinimumTimeoutNFS: 300, - IncrementTimeoutNFS: 30, - MinimumTimeoutHostPath: 60, - IncrementTimeoutHostPath: 30, - }, - }, - ContentType: "application/vnd.kubernetes.protobuf", - ClusterSigningCertFile: "/etc/kubernetes/ca/ca.pem", - ClusterSigningKeyFile: "/etc/kubernetes/ca/ca.key", - EnableContentionProfiling: true, - KubeAPIQPS: 50.0, - KubeAPIBurst: 100, - LeaderElection: componentconfig.LeaderElectionConfiguration{ - ResourceLock: "configmap", - LeaderElect: false, - LeaseDuration: metav1.Duration{Duration: 30 * time.Second}, - RenewDeadline: metav1.Duration{Duration: 15 * time.Second}, - RetryPeriod: metav1.Duration{Duration: 5 * time.Second}, - }, - ControllerStartInterval: metav1.Duration{Duration: 2 * time.Minute}, - RouteReconciliationPeriod: metav1.Duration{Duration: 30 * time.Second}, - ClusterCIDR: "1.2.3.4/24", - NodeCIDRMaskSize: 24, - CIDRAllocatorType: "RangeAllocator", - Controllers: []string{"*"}, - }, - SecureServing: &apiserveroptions.SecureServingOptions{ - BindPort: 10001, - BindAddress: net.ParseIP("192.168.4.21"), - ServerCert: apiserveroptions.GeneratableKeyCert{ - CertDirectory: "/a/b/c", - PairName: "cloud-controller-manager", - }, - HTTP2MaxStreamsPerConnection: 47, + CloudProvider: &cmoptions.CloudProviderOptions{ + Name: "gce", + CloudConfigFile: "/cloud-config", + }, + Debugging: &cmoptions.DebuggingOptions{ + EnableContentionProfiling: true, + }, + GenericComponent: &cmoptions.GenericComponentConfigOptions{ + MinResyncPeriod: metav1.Duration{Duration: 100 * time.Minute}, + ContentType: "application/vnd.kubernetes.protobuf", + KubeAPIQPS: 50.0, + KubeAPIBurst: 100, + ControllerStartInterval: metav1.Duration{Duration: 2 * time.Minute}, + LeaderElection: componentconfig.LeaderElectionConfiguration{ + ResourceLock: "configmap", + LeaderElect: false, + LeaseDuration: metav1.Duration{Duration: 30 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 15 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 5 * time.Second}, }, - InsecureServing: &cmoptions.InsecureServingOptions{ - BindAddress: net.ParseIP("192.168.4.10"), - BindPort: int(10000), - BindNetwork: "tcp", + }, + KubeCloudShared: &cmoptions.KubeCloudSharedOptions{ + Port: 10253, // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config + Address: "0.0.0.0", // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config + RouteReconciliationPeriod: metav1.Duration{Duration: 30 * time.Second}, + NodeMonitorPeriod: metav1.Duration{Duration: 5 * time.Second}, + ClusterName: "k8s", + ClusterCIDR: "1.2.3.4/24", + AllocateNodeCIDRs: true, + CIDRAllocatorType: "RangeAllocator", + ConfigureCloudRoutes: false, + }, + ServiceController: &cmoptions.ServiceControllerOptions{ + ConcurrentServiceSyncs: 1, + }, + SecureServing: &apiserveroptions.SecureServingOptions{ + BindPort: 10001, + BindAddress: net.ParseIP("192.168.4.21"), + ServerCert: apiserveroptions.GeneratableKeyCert{ + CertDirectory: "/a/b/c", + PairName: "cloud-controller-manager", }, - Kubeconfig: "/kubeconfig", - Master: "192.168.4.20", + HTTP2MaxStreamsPerConnection: 47, + }, + InsecureServing: &cmoptions.InsecureServingOptions{ + BindAddress: net.ParseIP("192.168.4.10"), + BindPort: int(10000), + BindNetwork: "tcp", }, + Kubeconfig: "/kubeconfig", + Master: "192.168.4.20", NodeStatusUpdateFrequency: metav1.Duration{Duration: 10 * time.Minute}, } if !reflect.DeepEqual(expected, s) { diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/BUILD b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/BUILD index d36a9526e..c0bd85939 100644 --- a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/BUILD @@ -3,7 +3,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ - "config.go", "helper.go", "insecure_serving.go", "serve.go", @@ -25,8 +24,6 @@ go_library( "//vendor/k8s.io/apiserver/pkg/server/mux:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/routes:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/config.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/config.go deleted file mode 100644 index d67841562..000000000 --- a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/config.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2018 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 app - -import ( - apiserver "k8s.io/apiserver/pkg/server" - clientset "k8s.io/client-go/kubernetes" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/apis/componentconfig" -) - -// Config is the main context object for the controller manager. -type Config struct { - // TODO: split up the component config. This is not generic. - ComponentConfig componentconfig.KubeControllerManagerConfiguration - - SecureServing *apiserver.SecureServingInfo - // TODO: remove deprecated insecure serving - InsecureServing *InsecureServingInfo - Authentication apiserver.AuthenticationInfo - Authorization apiserver.AuthorizationInfo - - // the general kube client - Client *clientset.Clientset - - // the client only used for leader election - LeaderElectionClient *clientset.Clientset - - // the rest config for the master - Kubeconfig *restclient.Config - - // the event sink - EventRecorder record.EventRecorder -} - -type completedConfig struct { - *Config -} - -// CompletedConfig same as Config, just to swap private object. -type CompletedConfig struct { - // Embed a private pointer that cannot be instantiated outside of this package. - *completedConfig -} - -// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. -func (c *Config) Complete() CompletedConfig { - cc := completedConfig{c} - return CompletedConfig{&cc} -} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/insecure_serving.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/insecure_serving.go index d374a92e4..156fbadfc 100644 --- a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/insecure_serving.go +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/insecure_serving.go @@ -30,6 +30,8 @@ import ( type InsecureServingInfo struct { // Listener is the secure server network listener. Listener net.Listener + // optional server name for log messages + Name string } // Serve starts an insecure http server with the given handler. It fails only if @@ -41,6 +43,10 @@ func (s *InsecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.D MaxHeaderBytes: 1 << 20, } - glog.Infof("Serving insecurely on %s", s.Listener.Addr()) + if len(s.Name) > 0 { + glog.Infof("Serving %s insecurely on %s", s.Name, s.Listener.Addr()) + } else { + glog.Infof("Serving insecurely on %s", s.Listener.Addr()) + } return server.RunServer(insecureServer, s.Listener, shutdownTimeout, stopCh) } diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/BUILD b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/BUILD index b449fb9c2..83b848891 100644 --- a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/BUILD @@ -3,27 +3,40 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ + "attachdetachcontroller.go", + "cloudprovider.go", + "csrsigningcontroller.go", + "daemonsetcontroller.go", + "debugging.go", + "deploymentcontroller.go", + "deprecatedcontroller.go", + "endpointcontroller.go", + "garbagecollectorcontroller.go", + "generic.go", + "hpacontroller.go", "insecure_serving.go", - "options.go", + "jobcontroller.go", + "kubecloudshared.go", + "namespacecontroller.go", + "nodeipamcontroller.go", + "nodelifecyclecontroller.go", + "persistentvolumebindercontroller.go", + "podgccontroller.go", + "replicasetcontroller.go", + "replicationcontroller.go", + "resourcequotacontroller.go", + "serviceaccountcontroller.go", + "servicecontroller.go", ], importpath = "k8s.io/kubernetes/cmd/controller-manager/app/options", visibility = ["//visibility:public"], deps = [ "//cmd/controller-manager/app:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/componentconfig:go_default_library", "//pkg/client/leaderelectionconfig:go_default_library", - "//vendor/github.com/cloudflare/cfssl/helpers:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/attachdetachcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/attachdetachcontroller.go new file mode 100644 index 000000000..f34d5ea46 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/attachdetachcontroller.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// AttachDetachControllerOptions holds the AttachDetachController options. +type AttachDetachControllerOptions struct { + ReconcilerSyncLoopPeriod metav1.Duration + DisableAttachDetachReconcilerSync bool +} + +// AddFlags adds flags related to AttachDetachController for controller manager to the specified FlagSet. +func (o *AttachDetachControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.BoolVar(&o.DisableAttachDetachReconcilerSync, "disable-attach-detach-reconcile-sync", false, "Disable volume attach detach reconciler sync. Disabling this may cause volumes to be mismatched with pods. Use wisely.") + fs.DurationVar(&o.ReconcilerSyncLoopPeriod.Duration, "attach-detach-reconcile-sync-period", o.ReconcilerSyncLoopPeriod.Duration, "The reconciler sync wait time between volume attach detach. This duration must be larger than one second, and increasing this value from the default may allow for volumes to be mismatched with pods.") +} + +// ApplyTo fills up AttachDetachController config with options. +func (o *AttachDetachControllerOptions) ApplyTo(cfg *componentconfig.AttachDetachControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.DisableAttachDetachReconcilerSync = o.DisableAttachDetachReconcilerSync + cfg.ReconcilerSyncLoopPeriod = o.ReconcilerSyncLoopPeriod + + return nil +} + +// Validate checks validation of AttachDetachControllerOptions. +func (o *AttachDetachControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/cloudprovider.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/cloudprovider.go new file mode 100644 index 000000000..17541619d --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/cloudprovider.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// CloudProviderOptions holds the cloudprovider options. +type CloudProviderOptions struct { + CloudConfigFile string + Name string +} + +// Validate checks validation of cloudprovider options. +func (s *CloudProviderOptions) Validate() []error { + allErrors := []error{} + return allErrors +} + +// AddFlags adds flags related to cloudprovider for controller manager to the specified FlagSet. +func (s *CloudProviderOptions) AddFlags(fs *pflag.FlagSet) { + fs.StringVar(&s.Name, "cloud-provider", s.Name, + "The provider for cloud services. Empty string for no provider.") + + fs.StringVar(&s.CloudConfigFile, "cloud-config", s.CloudConfigFile, + "The path to the cloud provider configuration file. Empty string for no configuration file.") +} + +// ApplyTo fills up cloudprovider config with options. +func (s *CloudProviderOptions) ApplyTo(cfg *componentconfig.CloudProviderConfiguration) error { + if s == nil { + return nil + } + + cfg.Name = s.Name + cfg.CloudConfigFile = s.CloudConfigFile + + return nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/csrsigningcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/csrsigningcontroller.go new file mode 100644 index 000000000..bf55c9df8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/csrsigningcontroller.go @@ -0,0 +1,74 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +const ( + // These defaults are deprecated and exported so that we can warn if + // they are being used. + + // DefaultClusterSigningCertFile is deprecated. Do not use. + DefaultClusterSigningCertFile = "/etc/kubernetes/ca/ca.pem" + // DefaultClusterSigningKeyFile is deprecated. Do not use. + DefaultClusterSigningKeyFile = "/etc/kubernetes/ca/ca.key" +) + +// CSRSigningControllerOptions holds the CSRSigningController options. +type CSRSigningControllerOptions struct { + ClusterSigningDuration metav1.Duration + ClusterSigningKeyFile string + ClusterSigningCertFile string +} + +// AddFlags adds flags related to CSRSigningController for controller manager to the specified FlagSet. +func (o *CSRSigningControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.StringVar(&o.ClusterSigningCertFile, "cluster-signing-cert-file", o.ClusterSigningCertFile, "Filename containing a PEM-encoded X509 CA certificate used to issue cluster-scoped certificates") + fs.StringVar(&o.ClusterSigningKeyFile, "cluster-signing-key-file", o.ClusterSigningKeyFile, "Filename containing a PEM-encoded RSA or ECDSA private key used to sign cluster-scoped certificates") + fs.DurationVar(&o.ClusterSigningDuration.Duration, "experimental-cluster-signing-duration", o.ClusterSigningDuration.Duration, "The length of duration signed certificates will be given.") +} + +// ApplyTo fills up CSRSigningController config with options. +func (o *CSRSigningControllerOptions) ApplyTo(cfg *componentconfig.CSRSigningControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ClusterSigningCertFile = o.ClusterSigningCertFile + cfg.ClusterSigningKeyFile = o.ClusterSigningKeyFile + cfg.ClusterSigningDuration = o.ClusterSigningDuration + + return nil +} + +// Validate checks validation of CSRSigningControllerOptions. +func (o *CSRSigningControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/daemonsetcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/daemonsetcontroller.go new file mode 100644 index 000000000..df388edc7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/daemonsetcontroller.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// DaemonSetControllerOptions holds the DaemonSetController options. +type DaemonSetControllerOptions struct { + ConcurrentDaemonSetSyncs int32 +} + +// AddFlags adds flags related to DaemonSetController for controller manager to the specified FlagSet. +func (o *DaemonSetControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } +} + +// ApplyTo fills up DaemonSetController config with options. +func (o *DaemonSetControllerOptions) ApplyTo(cfg *componentconfig.DaemonSetControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ConcurrentDaemonSetSyncs = o.ConcurrentDaemonSetSyncs + + return nil +} + +// Validate checks validation of DaemonSetControllerOptions. +func (o *DaemonSetControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/debugging.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/debugging.go new file mode 100644 index 000000000..fa65caffc --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/debugging.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// DebuggingOptions holds the Debugging options. +type DebuggingOptions struct { + EnableProfiling bool + EnableContentionProfiling bool +} + +// AddFlags adds flags related to debugging for controller manager to the specified FlagSet. +func (o *DebuggingOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.BoolVar(&o.EnableProfiling, "profiling", o.EnableProfiling, + "Enable profiling via web interface host:port/debug/pprof/") + fs.BoolVar(&o.EnableContentionProfiling, "contention-profiling", o.EnableContentionProfiling, + "Enable lock contention profiling, if profiling is enabled") +} + +// ApplyTo fills up Debugging config with options. +func (o *DebuggingOptions) ApplyTo(cfg *componentconfig.DebuggingConfiguration) error { + if o == nil { + return nil + } + + cfg.EnableProfiling = o.EnableProfiling + cfg.EnableContentionProfiling = o.EnableContentionProfiling + + return nil +} + +// Validate checks validation of DebuggingOptions. +func (o *DebuggingOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/deploymentcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/deploymentcontroller.go new file mode 100644 index 000000000..5b3db9266 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/deploymentcontroller.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// DeploymentControllerOptions holds the DeploymentController options. +type DeploymentControllerOptions struct { + ConcurrentDeploymentSyncs int32 + DeploymentControllerSyncPeriod metav1.Duration +} + +// AddFlags adds flags related to DeploymentController for controller manager to the specified FlagSet. +func (o *DeploymentControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.Int32Var(&o.ConcurrentDeploymentSyncs, "concurrent-deployment-syncs", o.ConcurrentDeploymentSyncs, "The number of deployment objects that are allowed to sync concurrently. Larger number = more responsive deployments, but more CPU (and network) load") + fs.DurationVar(&o.DeploymentControllerSyncPeriod.Duration, "deployment-controller-sync-period", o.DeploymentControllerSyncPeriod.Duration, "Period for syncing the deployments.") +} + +// ApplyTo fills up DeploymentController config with options. +func (o *DeploymentControllerOptions) ApplyTo(cfg *componentconfig.DeploymentControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ConcurrentDeploymentSyncs = o.ConcurrentDeploymentSyncs + cfg.DeploymentControllerSyncPeriod = o.DeploymentControllerSyncPeriod + + return nil +} + +// Validate checks validation of DeploymentControllerOptions. +func (o *DeploymentControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/deprecatedcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/deprecatedcontroller.go new file mode 100644 index 000000000..3b8d0a1cd --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/deprecatedcontroller.go @@ -0,0 +1,67 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// DeprecatedControllerOptions holds the DeprecatedController options, those option are deprecated. +type DeprecatedControllerOptions struct { + DeletingPodsQPS float32 + DeletingPodsBurst int32 + RegisterRetryCount int32 +} + +// AddFlags adds flags related to DeprecatedController for controller manager to the specified FlagSet. +func (o *DeprecatedControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.Float32Var(&o.DeletingPodsQPS, "deleting-pods-qps", 0.1, "Number of nodes per second on which pods are deleted in case of node failure.") + fs.MarkDeprecated("deleting-pods-qps", "This flag is currently no-op and will be deleted.") + fs.Int32Var(&o.DeletingPodsBurst, "deleting-pods-burst", 0, "Number of nodes on which pods are bursty deleted in case of node failure. For more details look into RateLimiter.") + fs.MarkDeprecated("deleting-pods-burst", "This flag is currently no-op and will be deleted.") + fs.Int32Var(&o.RegisterRetryCount, "register-retry-count", o.RegisterRetryCount, ""+ + "The number of retries for initial node registration. Retry interval equals node-sync-period.") + fs.MarkDeprecated("register-retry-count", "This flag is currently no-op and will be deleted.") +} + +// ApplyTo fills up DeprecatedController config with options. +func (o *DeprecatedControllerOptions) ApplyTo(cfg *componentconfig.DeprecatedControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.DeletingPodsQps = o.DeletingPodsQPS + cfg.DeletingPodsBurst = o.DeletingPodsBurst + cfg.RegisterRetryCount = o.RegisterRetryCount + + return nil +} + +// Validate checks validation of DeprecatedControllerOptions. +func (o *DeprecatedControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/endpointcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/endpointcontroller.go new file mode 100644 index 000000000..2457650c9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/endpointcontroller.go @@ -0,0 +1,57 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// EndPointControllerOptions holds the EndPointController options. +type EndPointControllerOptions struct { + ConcurrentEndpointSyncs int32 +} + +// AddFlags adds flags related to EndPointController for controller manager to the specified FlagSet. +func (o *EndPointControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.Int32Var(&o.ConcurrentEndpointSyncs, "concurrent-endpoint-syncs", o.ConcurrentEndpointSyncs, "The number of endpoint syncing operations that will be done concurrently. Larger number = faster endpoint updating, but more CPU (and network) load") +} + +// ApplyTo fills up EndPointController config with options. +func (o *EndPointControllerOptions) ApplyTo(cfg *componentconfig.EndPointControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ConcurrentEndpointSyncs = o.ConcurrentEndpointSyncs + + return nil +} + +// Validate checks validation of EndPointControllerOptions. +func (o *EndPointControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/garbagecollectorcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/garbagecollectorcontroller.go new file mode 100644 index 000000000..85cf45e9b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/garbagecollectorcontroller.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// GarbageCollectorControllerOptions holds the GarbageCollectorController options. +type GarbageCollectorControllerOptions struct { + ConcurrentGCSyncs int32 + GCIgnoredResources []componentconfig.GroupResource + EnableGarbageCollector bool +} + +// AddFlags adds flags related to GarbageCollectorController for controller manager to the specified FlagSet. +func (o *GarbageCollectorControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.Int32Var(&o.ConcurrentGCSyncs, "concurrent-gc-syncs", o.ConcurrentGCSyncs, "The number of garbage collector workers that are allowed to sync concurrently.") + fs.BoolVar(&o.EnableGarbageCollector, "enable-garbage-collector", o.EnableGarbageCollector, "Enables the generic garbage collector. MUST be synced with the corresponding flag of the kube-apiserver.") +} + +// ApplyTo fills up GarbageCollectorController config with options. +func (o *GarbageCollectorControllerOptions) ApplyTo(cfg *componentconfig.GarbageCollectorControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ConcurrentGCSyncs = o.ConcurrentGCSyncs + cfg.GCIgnoredResources = o.GCIgnoredResources + cfg.EnableGarbageCollector = o.EnableGarbageCollector + + return nil +} + +// Validate checks validation of GarbageCollectorController. +func (o *GarbageCollectorControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/generic.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/generic.go new file mode 100644 index 000000000..d32b97569 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/generic.go @@ -0,0 +1,91 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" + "k8s.io/kubernetes/pkg/client/leaderelectionconfig" +) + +// GenericComponentConfigOptions holds the options which are generic. +type GenericComponentConfigOptions struct { + MinResyncPeriod metav1.Duration + ContentType string + KubeAPIQPS float32 + KubeAPIBurst int32 + ControllerStartInterval metav1.Duration + LeaderElection componentconfig.LeaderElectionConfiguration +} + +// NewGenericComponentConfigOptions returns generic configuration default values for both +// the kube-controller-manager and the cloud-contoller-manager. Any common changes should +// be made here. Any individual changes should be made in that controller. +func NewGenericComponentConfigOptions(cfg componentconfig.GenericComponentConfiguration) *GenericComponentConfigOptions { + o := &GenericComponentConfigOptions{ + MinResyncPeriod: cfg.MinResyncPeriod, + ContentType: cfg.ContentType, + KubeAPIQPS: cfg.KubeAPIQPS, + KubeAPIBurst: cfg.KubeAPIBurst, + ControllerStartInterval: cfg.ControllerStartInterval, + LeaderElection: cfg.LeaderElection, + } + + return o +} + +// AddFlags adds flags related to generic for controller manager to the specified FlagSet. +func (o *GenericComponentConfigOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.DurationVar(&o.MinResyncPeriod.Duration, "min-resync-period", o.MinResyncPeriod.Duration, "The resync period in reflectors will be random between MinResyncPeriod and 2*MinResyncPeriod.") + fs.StringVar(&o.ContentType, "kube-api-content-type", o.ContentType, "Content type of requests sent to apiserver.") + fs.Float32Var(&o.KubeAPIQPS, "kube-api-qps", o.KubeAPIQPS, "QPS to use while talking with kubernetes apiserver.") + fs.Int32Var(&o.KubeAPIBurst, "kube-api-burst", o.KubeAPIBurst, "Burst to use while talking with kubernetes apiserver.") + fs.DurationVar(&o.ControllerStartInterval.Duration, "controller-start-interval", o.ControllerStartInterval.Duration, "Interval between starting controller managers.") + + leaderelectionconfig.BindFlags(&o.LeaderElection, fs) +} + +// ApplyTo fills up generic config with options. +func (o *GenericComponentConfigOptions) ApplyTo(cfg *componentconfig.GenericComponentConfiguration) error { + if o == nil { + return nil + } + + cfg.MinResyncPeriod = o.MinResyncPeriod + cfg.ContentType = o.ContentType + cfg.KubeAPIQPS = o.KubeAPIQPS + cfg.KubeAPIBurst = o.KubeAPIBurst + cfg.ControllerStartInterval = o.ControllerStartInterval + cfg.LeaderElection = o.LeaderElection + + return nil +} + +// Validate checks validation of GenericOptions. +func (o *GenericComponentConfigOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/hpacontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/hpacontroller.go new file mode 100644 index 000000000..39fae9d92 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/hpacontroller.go @@ -0,0 +1,70 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// HPAControllerOptions holds the HPAController options. +type HPAControllerOptions struct { + HorizontalPodAutoscalerUseRESTClients bool + HorizontalPodAutoscalerTolerance float64 + HorizontalPodAutoscalerDownscaleForbiddenWindow metav1.Duration + HorizontalPodAutoscalerUpscaleForbiddenWindow metav1.Duration + HorizontalPodAutoscalerSyncPeriod metav1.Duration +} + +// AddFlags adds flags related to HPAController for controller manager to the specified FlagSet. +func (o *HPAControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.DurationVar(&o.HorizontalPodAutoscalerSyncPeriod.Duration, "horizontal-pod-autoscaler-sync-period", o.HorizontalPodAutoscalerSyncPeriod.Duration, "The period for syncing the number of pods in horizontal pod autoscaler.") + fs.DurationVar(&o.HorizontalPodAutoscalerUpscaleForbiddenWindow.Duration, "horizontal-pod-autoscaler-upscale-delay", o.HorizontalPodAutoscalerUpscaleForbiddenWindow.Duration, "The period since last upscale, before another upscale can be performed in horizontal pod autoscaler.") + fs.DurationVar(&o.HorizontalPodAutoscalerDownscaleForbiddenWindow.Duration, "horizontal-pod-autoscaler-downscale-delay", o.HorizontalPodAutoscalerDownscaleForbiddenWindow.Duration, "The period since last downscale, before another downscale can be performed in horizontal pod autoscaler.") + fs.Float64Var(&o.HorizontalPodAutoscalerTolerance, "horizontal-pod-autoscaler-tolerance", o.HorizontalPodAutoscalerTolerance, "The minimum change (from 1.0) in the desired-to-actual metrics ratio for the horizontal pod autoscaler to consider scaling.") + fs.BoolVar(&o.HorizontalPodAutoscalerUseRESTClients, "horizontal-pod-autoscaler-use-rest-clients", o.HorizontalPodAutoscalerUseRESTClients, "If set to true, causes the horizontal pod autoscaler controller to use REST clients through the kube-aggregator, instead of using the legacy metrics client through the API server proxy. This is required for custom metrics support in the horizontal pod autoscaler.") +} + +// ApplyTo fills up HPAController config with options. +func (o *HPAControllerOptions) ApplyTo(cfg *componentconfig.HPAControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.HorizontalPodAutoscalerSyncPeriod = o.HorizontalPodAutoscalerSyncPeriod + cfg.HorizontalPodAutoscalerUpscaleForbiddenWindow = o.HorizontalPodAutoscalerUpscaleForbiddenWindow + cfg.HorizontalPodAutoscalerDownscaleForbiddenWindow = o.HorizontalPodAutoscalerDownscaleForbiddenWindow + cfg.HorizontalPodAutoscalerTolerance = o.HorizontalPodAutoscalerTolerance + cfg.HorizontalPodAutoscalerUseRESTClients = o.HorizontalPodAutoscalerUseRESTClients + + return nil +} + +// Validate checks validation of HPAControllerOptions. +func (o *HPAControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/insecure_serving.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/insecure_serving.go index d93c182c9..aecb70446 100644 --- a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/insecure_serving.go +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/insecure_serving.go @@ -23,7 +23,6 @@ import ( "github.com/spf13/pflag" "k8s.io/apiserver/pkg/server/options" genericcontrollermanager "k8s.io/kubernetes/cmd/controller-manager/app" - "k8s.io/kubernetes/pkg/apis/componentconfig" ) // InsecureServingOptions are for creating an unauthenticated, unauthorized, insecure port. @@ -39,16 +38,20 @@ type InsecureServingOptions struct { // either Listener or BindAddress/BindPort/BindNetwork is set, // if Listener is set, use it and omit BindAddress/BindPort/BindNetwork. Listener net.Listener + + // ListenFunc can be overridden to create a custom listener, e.g. for mocking in tests. + // It defaults to options.CreateListener. + ListenFunc func(network, addr string) (net.Listener, int, error) } // Validate ensures that the insecure port values within the range of the port. func (s *InsecureServingOptions) Validate() []error { - errors := []error{} - if s == nil { return nil } + errors := []error{} + if s.BindPort < 0 || s.BindPort > 32767 { errors = append(errors, fmt.Errorf("--insecure-port %v must be between 0 and 32767, inclusive. 0 for turning off insecure (HTTP) port", s.BindPort)) } @@ -61,20 +64,10 @@ func (s *InsecureServingOptions) AddFlags(fs *pflag.FlagSet) { if s == nil { return } -} -// AddDeprecatedFlags adds deprecated flags related to insecure serving for controller manager to the specified FlagSet. -// TODO: remove it until kops stop using `--address` -func (s *InsecureServingOptions) AddDeprecatedFlags(fs *pflag.FlagSet) { - if s == nil { - return - } - - fs.IPVar(&s.BindAddress, "address", s.BindAddress, - "DEPRECATED: the IP address on which to listen for the --port port. See --bind-address instead.") + fs.IPVar(&s.BindAddress, "address", s.BindAddress, "DEPRECATED: the IP address on which to listen for the --port port (set to 0.0.0.0 for all IPv4 interfaces and :: for all IPv6 interfaces). See --bind-address instead.") // MarkDeprecated hides the flag from the help. We don't want that: // fs.MarkDeprecated("address", "see --bind-address instead.") - fs.IntVar(&s.BindPort, "port", s.BindPort, "DEPRECATED: the port on which to serve HTTP insecurely without authentication and authorization. If 0, don't serve HTTPS at all. See --secure-port instead.") // MarkDeprecated hides the flag from the help. We don't want that: // fs.MarkDeprecated("port", "see --secure-port instead.") @@ -82,7 +75,7 @@ func (s *InsecureServingOptions) AddDeprecatedFlags(fs *pflag.FlagSet) { // ApplyTo adds InsecureServingOptions to the insecureserverinfo amd kube-controller manager configuration. // Note: the double pointer allows to set the *InsecureServingInfo to nil without referencing the struct hosting this pointer. -func (s *InsecureServingOptions) ApplyTo(c **genericcontrollermanager.InsecureServingInfo, cfg *componentconfig.KubeControllerManagerConfiguration) error { +func (s *InsecureServingOptions) ApplyTo(c **genericcontrollermanager.InsecureServingInfo) error { if s == nil { return nil } @@ -92,8 +85,12 @@ func (s *InsecureServingOptions) ApplyTo(c **genericcontrollermanager.InsecureSe if s.Listener == nil { var err error + listen := options.CreateListener + if s.ListenFunc != nil { + listen = s.ListenFunc + } addr := net.JoinHostPort(s.BindAddress.String(), fmt.Sprintf("%d", s.BindPort)) - s.Listener, s.BindPort, err = options.CreateListener(s.BindNetwork, addr) + s.Listener, s.BindPort, err = listen(s.BindNetwork, addr) if err != nil { return fmt.Errorf("failed to create listener: %v", err) } @@ -103,10 +100,5 @@ func (s *InsecureServingOptions) ApplyTo(c **genericcontrollermanager.InsecureSe Listener: s.Listener, } - // sync back to component config - // TODO: find more elegant way than synching back the values. - cfg.Port = int32(s.BindPort) - cfg.Address = s.BindAddress.String() - return nil } diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/jobcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/jobcontroller.go new file mode 100644 index 000000000..9269a3682 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/jobcontroller.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// JobControllerOptions holds the JobController options. +type JobControllerOptions struct { + ConcurrentJobSyncs int32 +} + +// AddFlags adds flags related to JobController for controller manager to the specified FlagSet. +func (o *JobControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } +} + +// ApplyTo fills up JobController config with options. +func (o *JobControllerOptions) ApplyTo(cfg *componentconfig.JobControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ConcurrentJobSyncs = o.ConcurrentJobSyncs + + return nil +} + +// Validate checks validation of JobControllerOptions. +func (o *JobControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/kubecloudshared.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/kubecloudshared.go new file mode 100644 index 000000000..c92c4a51b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/kubecloudshared.go @@ -0,0 +1,112 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// KubeCloudSharedOptions holds the options shared between kube-controller-manager +// and cloud-controller-manager. +type KubeCloudSharedOptions struct { + Port int32 + Address string + UseServiceAccountCredentials bool + AllowUntaggedCloud bool + RouteReconciliationPeriod metav1.Duration + NodeMonitorPeriod metav1.Duration + ClusterName string + ClusterCIDR string + AllocateNodeCIDRs bool + CIDRAllocatorType string + ConfigureCloudRoutes bool + NodeSyncPeriod metav1.Duration +} + +// NewKubeCloudSharedOptions returns common/default configuration values for both +// the kube-controller-manager and the cloud-contoller-manager. Any common changes should +// be made here. Any individual changes should be made in that controller. +func NewKubeCloudSharedOptions(cfg componentconfig.KubeCloudSharedConfiguration) *KubeCloudSharedOptions { + o := &KubeCloudSharedOptions{ + Port: cfg.Port, + Address: cfg.Address, + RouteReconciliationPeriod: cfg.RouteReconciliationPeriod, + NodeMonitorPeriod: cfg.NodeMonitorPeriod, + ClusterName: cfg.ClusterName, + ConfigureCloudRoutes: cfg.ConfigureCloudRoutes, + } + + return o +} + +// AddFlags adds flags related to shared variable for controller manager to the specified FlagSet. +func (o *KubeCloudSharedOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.BoolVar(&o.UseServiceAccountCredentials, "use-service-account-credentials", o.UseServiceAccountCredentials, "If true, use individual service account credentials for each controller.") + fs.BoolVar(&o.AllowUntaggedCloud, "allow-untagged-cloud", false, "Allow the cluster to run without the cluster-id on cloud instances. This is a legacy mode of operation and a cluster-id will be required in the future.") + fs.MarkDeprecated("allow-untagged-cloud", "This flag is deprecated and will be removed in a future release. A cluster-id will be required on cloud instances.") + fs.DurationVar(&o.RouteReconciliationPeriod.Duration, "route-reconciliation-period", o.RouteReconciliationPeriod.Duration, "The period for reconciling routes created for Nodes by cloud provider.") + fs.DurationVar(&o.NodeMonitorPeriod.Duration, "node-monitor-period", o.NodeMonitorPeriod.Duration, + "The period for syncing NodeStatus in NodeController.") + fs.StringVar(&o.ClusterName, "cluster-name", o.ClusterName, "The instance prefix for the cluster.") + fs.StringVar(&o.ClusterCIDR, "cluster-cidr", o.ClusterCIDR, "CIDR Range for Pods in cluster. Requires --allocate-node-cidrs to be true") + fs.BoolVar(&o.AllocateNodeCIDRs, "allocate-node-cidrs", false, "Should CIDRs for Pods be allocated and set on the cloud provider.") + fs.StringVar(&o.CIDRAllocatorType, "cidr-allocator-type", "RangeAllocator", "Type of CIDR allocator to use") + fs.BoolVar(&o.ConfigureCloudRoutes, "configure-cloud-routes", true, "Should CIDRs allocated by allocate-node-cidrs be configured on the cloud provider.") + + fs.DurationVar(&o.NodeSyncPeriod.Duration, "node-sync-period", 0, ""+ + "This flag is deprecated and will be removed in future releases. See node-monitor-period for Node health checking or "+ + "route-reconciliation-period for cloud provider's route configuration settings.") + fs.MarkDeprecated("node-sync-period", "This flag is currently no-op and will be deleted.") +} + +// ApplyTo fills up KubeCloudShared config with options. +func (o *KubeCloudSharedOptions) ApplyTo(cfg *componentconfig.KubeCloudSharedConfiguration) error { + if o == nil { + return nil + } + + cfg.Port = o.Port + cfg.Address = o.Address + cfg.UseServiceAccountCredentials = o.UseServiceAccountCredentials + cfg.AllowUntaggedCloud = o.AllowUntaggedCloud + cfg.RouteReconciliationPeriod = o.RouteReconciliationPeriod + cfg.NodeMonitorPeriod = o.NodeMonitorPeriod + cfg.ClusterName = o.ClusterName + cfg.ClusterCIDR = o.ClusterCIDR + cfg.AllocateNodeCIDRs = o.AllocateNodeCIDRs + cfg.CIDRAllocatorType = o.CIDRAllocatorType + cfg.ConfigureCloudRoutes = o.ConfigureCloudRoutes + cfg.NodeSyncPeriod = o.NodeSyncPeriod + + return nil +} + +// Validate checks validation of KubeCloudSharedOptions. +func (o *KubeCloudSharedOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/namespacecontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/namespacecontroller.go new file mode 100644 index 000000000..718e7c98b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/namespacecontroller.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// NamespaceControllerOptions holds the NamespaceController options. +type NamespaceControllerOptions struct { + NamespaceSyncPeriod metav1.Duration + ConcurrentNamespaceSyncs int32 +} + +// AddFlags adds flags related to NamespaceController for controller manager to the specified FlagSet. +func (o *NamespaceControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.DurationVar(&o.NamespaceSyncPeriod.Duration, "namespace-sync-period", o.NamespaceSyncPeriod.Duration, "The period for syncing namespace life-cycle updates") + fs.Int32Var(&o.ConcurrentNamespaceSyncs, "concurrent-namespace-syncs", o.ConcurrentNamespaceSyncs, "The number of namespace objects that are allowed to sync concurrently. Larger number = more responsive namespace termination, but more CPU (and network) load") +} + +// ApplyTo fills up NamespaceController config with options. +func (o *NamespaceControllerOptions) ApplyTo(cfg *componentconfig.NamespaceControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.NamespaceSyncPeriod = o.NamespaceSyncPeriod + cfg.ConcurrentNamespaceSyncs = o.ConcurrentNamespaceSyncs + + return nil +} + +// Validate checks validation of NamespaceControllerOptions. +func (o *NamespaceControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/nodeipamcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/nodeipamcontroller.go new file mode 100644 index 000000000..65cea454b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/nodeipamcontroller.go @@ -0,0 +1,60 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// NodeIpamControllerOptions holds the NodeIpamController options. +type NodeIpamControllerOptions struct { + ServiceCIDR string + NodeCIDRMaskSize int32 +} + +// AddFlags adds flags related to NodeIpamController for controller manager to the specified FlagSet. +func (o *NodeIpamControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.StringVar(&o.ServiceCIDR, "service-cluster-ip-range", o.ServiceCIDR, "CIDR Range for Services in cluster. Requires --allocate-node-cidrs to be true") + fs.Int32Var(&o.NodeCIDRMaskSize, "node-cidr-mask-size", o.NodeCIDRMaskSize, "Mask size for node cidr in cluster.") +} + +// ApplyTo fills up NodeIpamController config with options. +func (o *NodeIpamControllerOptions) ApplyTo(cfg *componentconfig.NodeIpamControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ServiceCIDR = o.ServiceCIDR + cfg.NodeCIDRMaskSize = o.NodeCIDRMaskSize + + return nil +} + +// Validate checks validation of NodeIpamControllerOptions. +func (o *NodeIpamControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/nodelifecyclecontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/nodelifecyclecontroller.go new file mode 100644 index 000000000..005655576 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/nodelifecyclecontroller.go @@ -0,0 +1,83 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// NodeLifecycleControllerOptions holds the NodeLifecycleController options. +type NodeLifecycleControllerOptions struct { + EnableTaintManager bool + NodeEvictionRate float32 + SecondaryNodeEvictionRate float32 + NodeStartupGracePeriod metav1.Duration + NodeMonitorGracePeriod metav1.Duration + PodEvictionTimeout metav1.Duration + LargeClusterSizeThreshold int32 + UnhealthyZoneThreshold float32 +} + +// AddFlags adds flags related to NodeLifecycleController for controller manager to the specified FlagSet. +func (o *NodeLifecycleControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.DurationVar(&o.NodeStartupGracePeriod.Duration, "node-startup-grace-period", o.NodeStartupGracePeriod.Duration, + "Amount of time which we allow starting Node to be unresponsive before marking it unhealthy.") + fs.DurationVar(&o.NodeMonitorGracePeriod.Duration, "node-monitor-grace-period", o.NodeMonitorGracePeriod.Duration, + "Amount of time which we allow running Node to be unresponsive before marking it unhealthy. "+ + "Must be N times more than kubelet's nodeStatusUpdateFrequency, "+ + "where N means number of retries allowed for kubelet to post node status.") + fs.DurationVar(&o.PodEvictionTimeout.Duration, "pod-eviction-timeout", o.PodEvictionTimeout.Duration, "The grace period for deleting pods on failed nodes.") + fs.Float32Var(&o.NodeEvictionRate, "node-eviction-rate", 0.1, "Number of nodes per second on which pods are deleted in case of node failure when a zone is healthy (see --unhealthy-zone-threshold for definition of healthy/unhealthy). Zone refers to entire cluster in non-multizone clusters.") + fs.Float32Var(&o.SecondaryNodeEvictionRate, "secondary-node-eviction-rate", 0.01, "Number of nodes per second on which pods are deleted in case of node failure when a zone is unhealthy (see --unhealthy-zone-threshold for definition of healthy/unhealthy). Zone refers to entire cluster in non-multizone clusters. This value is implicitly overridden to 0 if the cluster size is smaller than --large-cluster-size-threshold.") + fs.Int32Var(&o.LargeClusterSizeThreshold, "large-cluster-size-threshold", 50, "Number of nodes from which NodeController treats the cluster as large for the eviction logic purposes. --secondary-node-eviction-rate is implicitly overridden to 0 for clusters this size or smaller.") + fs.Float32Var(&o.UnhealthyZoneThreshold, "unhealthy-zone-threshold", 0.55, "Fraction of Nodes in a zone which needs to be not Ready (minimum 3) for zone to be treated as unhealthy. ") + fs.BoolVar(&o.EnableTaintManager, "enable-taint-manager", o.EnableTaintManager, "WARNING: Beta feature. If set to true enables NoExecute Taints and will evict all not-tolerating Pod running on Nodes tainted with this kind of Taints.") +} + +// ApplyTo fills up NodeLifecycleController config with options. +func (o *NodeLifecycleControllerOptions) ApplyTo(cfg *componentconfig.NodeLifecycleControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.EnableTaintManager = o.EnableTaintManager + cfg.NodeStartupGracePeriod = o.NodeStartupGracePeriod + cfg.NodeMonitorGracePeriod = o.NodeMonitorGracePeriod + cfg.PodEvictionTimeout = o.PodEvictionTimeout + cfg.NodeEvictionRate = o.NodeEvictionRate + cfg.SecondaryNodeEvictionRate = o.SecondaryNodeEvictionRate + cfg.LargeClusterSizeThreshold = o.LargeClusterSizeThreshold + cfg.UnhealthyZoneThreshold = o.UnhealthyZoneThreshold + + return nil +} + +// Validate checks validation of NodeLifecycleControllerOptions. +func (o *NodeLifecycleControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/options.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/options.go deleted file mode 100644 index 8f468f4d1..000000000 --- a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/options.go +++ /dev/null @@ -1,242 +0,0 @@ -/* -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 options - -import ( - "net" - "time" - - "github.com/cloudflare/cfssl/helpers" - "github.com/golang/glog" - - "github.com/spf13/pflag" - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - apiserveroptions "k8s.io/apiserver/pkg/server/options" - "k8s.io/client-go/kubernetes" - clientset "k8s.io/client-go/kubernetes" - v1core "k8s.io/client-go/kubernetes/typed/core/v1" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/tools/record" - genericcontrollermanager "k8s.io/kubernetes/cmd/controller-manager/app" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/apis/componentconfig" - "k8s.io/kubernetes/pkg/client/leaderelectionconfig" -) - -// GenericControllerManagerOptions is the common structure for a controller manager. It works with NewGenericControllerManagerOptions -// and AddDefaultControllerFlags to create the common components of kube-controller-manager and cloud-controller-manager. -type GenericControllerManagerOptions struct { - // TODO: turn ComponentConfig into modular option structs. This is not generic. - ComponentConfig componentconfig.KubeControllerManagerConfiguration - - SecureServing *apiserveroptions.SecureServingOptions - // TODO: remove insecure serving mode - InsecureServing *InsecureServingOptions - Authentication *apiserveroptions.DelegatingAuthenticationOptions - Authorization *apiserveroptions.DelegatingAuthorizationOptions - - Master string - Kubeconfig string -} - -const ( - // These defaults are deprecated and exported so that we can warn if - // they are being used. - - // DefaultClusterSigningCertFile is deprecated. Do not use. - DefaultClusterSigningCertFile = "/etc/kubernetes/ca/ca.pem" - // DefaultClusterSigningKeyFile is deprecated. Do not use. - DefaultClusterSigningKeyFile = "/etc/kubernetes/ca/ca.key" -) - -// NewGenericControllerManagerOptions returns common/default configuration values for both -// the kube-controller-manager and the cloud-contoller-manager. Any common changes should -// be made here. Any individual changes should be made in that controller. -func NewGenericControllerManagerOptions(componentConfig componentconfig.KubeControllerManagerConfiguration) GenericControllerManagerOptions { - o := GenericControllerManagerOptions{ - ComponentConfig: componentConfig, - SecureServing: apiserveroptions.NewSecureServingOptions(), - InsecureServing: &InsecureServingOptions{ - BindAddress: net.ParseIP(componentConfig.Address), - BindPort: int(componentConfig.Port), - BindNetwork: "tcp", - }, - Authentication: nil, // TODO: enable with apiserveroptions.NewDelegatingAuthenticationOptions() - Authorization: nil, // TODO: enable with apiserveroptions.NewDelegatingAuthorizationOptions() - } - - // disable secure serving for now - // TODO: enable HTTPS by default - o.SecureServing.BindPort = 0 - - return o -} - -// NewDefaultControllerManagerComponentConfig returns default kube-controller manager configuration object. -func NewDefaultControllerManagerComponentConfig(insecurePort int32) componentconfig.KubeControllerManagerConfiguration { - return componentconfig.KubeControllerManagerConfiguration{ - Controllers: []string{"*"}, - Port: insecurePort, - Address: "0.0.0.0", - ConcurrentEndpointSyncs: 5, - ConcurrentServiceSyncs: 1, - ConcurrentRCSyncs: 5, - ConcurrentRSSyncs: 5, - ConcurrentDaemonSetSyncs: 2, - ConcurrentJobSyncs: 5, - ConcurrentResourceQuotaSyncs: 5, - ConcurrentDeploymentSyncs: 5, - ConcurrentNamespaceSyncs: 10, - ConcurrentSATokenSyncs: 5, - RouteReconciliationPeriod: metav1.Duration{Duration: 10 * time.Second}, - ResourceQuotaSyncPeriod: metav1.Duration{Duration: 5 * time.Minute}, - NamespaceSyncPeriod: metav1.Duration{Duration: 5 * time.Minute}, - PVClaimBinderSyncPeriod: metav1.Duration{Duration: 15 * time.Second}, - HorizontalPodAutoscalerSyncPeriod: metav1.Duration{Duration: 30 * time.Second}, - HorizontalPodAutoscalerUpscaleForbiddenWindow: metav1.Duration{Duration: 3 * time.Minute}, - HorizontalPodAutoscalerDownscaleForbiddenWindow: metav1.Duration{Duration: 5 * time.Minute}, - HorizontalPodAutoscalerTolerance: 0.1, - DeploymentControllerSyncPeriod: metav1.Duration{Duration: 30 * time.Second}, - MinResyncPeriod: metav1.Duration{Duration: 12 * time.Hour}, - RegisterRetryCount: 10, - PodEvictionTimeout: metav1.Duration{Duration: 5 * time.Minute}, - NodeMonitorGracePeriod: metav1.Duration{Duration: 40 * time.Second}, - NodeStartupGracePeriod: metav1.Duration{Duration: 60 * time.Second}, - NodeMonitorPeriod: metav1.Duration{Duration: 5 * time.Second}, - ClusterName: "kubernetes", - NodeCIDRMaskSize: 24, - ConfigureCloudRoutes: true, - TerminatedPodGCThreshold: 12500, - VolumeConfiguration: componentconfig.VolumeConfiguration{ - EnableHostPathProvisioning: false, - EnableDynamicProvisioning: true, - PersistentVolumeRecyclerConfiguration: componentconfig.PersistentVolumeRecyclerConfiguration{ - MaximumRetry: 3, - MinimumTimeoutNFS: 300, - IncrementTimeoutNFS: 30, - MinimumTimeoutHostPath: 60, - IncrementTimeoutHostPath: 30, - }, - FlexVolumePluginDir: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/", - }, - ContentType: "application/vnd.kubernetes.protobuf", - KubeAPIQPS: 20.0, - KubeAPIBurst: 30, - LeaderElection: leaderelectionconfig.DefaultLeaderElectionConfiguration(), - ControllerStartInterval: metav1.Duration{Duration: 0 * time.Second}, - EnableGarbageCollector: true, - ConcurrentGCSyncs: 20, - ClusterSigningCertFile: DefaultClusterSigningCertFile, - ClusterSigningKeyFile: DefaultClusterSigningKeyFile, - ClusterSigningDuration: metav1.Duration{Duration: helpers.OneYear}, - ReconcilerSyncLoopPeriod: metav1.Duration{Duration: 60 * time.Second}, - EnableTaintManager: true, - HorizontalPodAutoscalerUseRESTClients: true, - } -} - -// AddFlags adds common/default flags for both the kube and cloud Controller Manager Server to the -// specified FlagSet. Any common changes should be made here. Any individual changes should be made in that controller. -func (o *GenericControllerManagerOptions) AddFlags(fs *pflag.FlagSet) { - fs.BoolVar(&o.ComponentConfig.UseServiceAccountCredentials, "use-service-account-credentials", o.ComponentConfig.UseServiceAccountCredentials, "If true, use individual service account credentials for each controller.") - fs.StringVar(&o.ComponentConfig.CloudConfigFile, "cloud-config", o.ComponentConfig.CloudConfigFile, "The path to the cloud provider configuration file. Empty string for no configuration file.") - fs.BoolVar(&o.ComponentConfig.AllowUntaggedCloud, "allow-untagged-cloud", false, "Allow the cluster to run without the cluster-id on cloud instances. This is a legacy mode of operation and a cluster-id will be required in the future.") - fs.MarkDeprecated("allow-untagged-cloud", "This flag is deprecated and will be removed in a future release. A cluster-id will be required on cloud instances.") - fs.DurationVar(&o.ComponentConfig.RouteReconciliationPeriod.Duration, "route-reconciliation-period", o.ComponentConfig.RouteReconciliationPeriod.Duration, "The period for reconciling routes created for Nodes by cloud provider.") - fs.DurationVar(&o.ComponentConfig.MinResyncPeriod.Duration, "min-resync-period", o.ComponentConfig.MinResyncPeriod.Duration, "The resync period in reflectors will be random between MinResyncPeriod and 2*MinResyncPeriod.") - fs.DurationVar(&o.ComponentConfig.NodeMonitorPeriod.Duration, "node-monitor-period", o.ComponentConfig.NodeMonitorPeriod.Duration, - "The period for syncing NodeStatus in NodeController.") - fs.BoolVar(&o.ComponentConfig.EnableProfiling, "profiling", true, "Enable profiling via web interface host:port/debug/pprof/") - fs.BoolVar(&o.ComponentConfig.EnableContentionProfiling, "contention-profiling", false, "Enable lock contention profiling, if profiling is enabled.") - fs.StringVar(&o.ComponentConfig.ClusterName, "cluster-name", o.ComponentConfig.ClusterName, "The instance prefix for the cluster.") - fs.StringVar(&o.ComponentConfig.ClusterCIDR, "cluster-cidr", o.ComponentConfig.ClusterCIDR, "CIDR Range for Pods in cluster. Requires --allocate-node-cidrs to be true") - fs.BoolVar(&o.ComponentConfig.AllocateNodeCIDRs, "allocate-node-cidrs", false, "Should CIDRs for Pods be allocated and set on the cloud provider.") - fs.StringVar(&o.ComponentConfig.CIDRAllocatorType, "cidr-allocator-type", "RangeAllocator", "Type of CIDR allocator to use") - fs.BoolVar(&o.ComponentConfig.ConfigureCloudRoutes, "configure-cloud-routes", true, "Should CIDRs allocated by allocate-node-cidrs be configured on the cloud provider.") - fs.StringVar(&o.Master, "master", o.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig).") - fs.StringVar(&o.Kubeconfig, "kubeconfig", o.Kubeconfig, "Path to kubeconfig file with authorization and master location information.") - fs.StringVar(&o.ComponentConfig.ContentType, "kube-api-content-type", o.ComponentConfig.ContentType, "Content type of requests sent to apiserver.") - fs.Float32Var(&o.ComponentConfig.KubeAPIQPS, "kube-api-qps", o.ComponentConfig.KubeAPIQPS, "QPS to use while talking with kubernetes apiserver.") - fs.Int32Var(&o.ComponentConfig.KubeAPIBurst, "kube-api-burst", o.ComponentConfig.KubeAPIBurst, "Burst to use while talking with kubernetes apiserver.") - fs.DurationVar(&o.ComponentConfig.ControllerStartInterval.Duration, "controller-start-interval", o.ComponentConfig.ControllerStartInterval.Duration, "Interval between starting controller managers.") - - o.SecureServing.AddFlags(fs) - o.InsecureServing.AddFlags(fs) - o.InsecureServing.AddDeprecatedFlags(fs) - o.Authentication.AddFlags(fs) - o.Authorization.AddFlags(fs) -} - -// ApplyTo fills up controller manager config with options and userAgent -func (o *GenericControllerManagerOptions) ApplyTo(c *genericcontrollermanager.Config, userAgent string) error { - c.ComponentConfig = o.ComponentConfig - - if err := o.SecureServing.ApplyTo(&c.SecureServing); err != nil { - return err - } - if err := o.InsecureServing.ApplyTo(&c.InsecureServing, &c.ComponentConfig); err != nil { - return err - } - if err := o.Authentication.ApplyTo(&c.Authentication, c.SecureServing, nil); err != nil { - return err - } - if err := o.Authorization.ApplyTo(&c.Authorization); err != nil { - return err - } - - var err error - c.Kubeconfig, err = clientcmd.BuildConfigFromFlags(o.Master, o.Kubeconfig) - if err != nil { - return err - } - c.Kubeconfig.ContentConfig.ContentType = o.ComponentConfig.ContentType - c.Kubeconfig.QPS = o.ComponentConfig.KubeAPIQPS - c.Kubeconfig.Burst = int(o.ComponentConfig.KubeAPIBurst) - - c.Client, err = clientset.NewForConfig(restclient.AddUserAgent(c.Kubeconfig, userAgent)) - if err != nil { - return err - } - - c.LeaderElectionClient = clientset.NewForConfigOrDie(restclient.AddUserAgent(c.Kubeconfig, "leader-election")) - - c.EventRecorder = createRecorder(c.Client, userAgent) - - return nil -} - -// Validate checks GenericControllerManagerOptions and return a slice of found errors. -func (o *GenericControllerManagerOptions) Validate() []error { - errors := []error{} - errors = append(errors, o.SecureServing.Validate()...) - errors = append(errors, o.InsecureServing.Validate()...) - errors = append(errors, o.Authentication.Validate()...) - errors = append(errors, o.Authorization.Validate()...) - - // TODO: validate component config, master and kubeconfig - - return errors -} - -func createRecorder(kubeClient *kubernetes.Clientset, userAgent string) record.EventRecorder { - eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) - return eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: userAgent}) -} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/persistentvolumebindercontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/persistentvolumebindercontroller.go new file mode 100644 index 000000000..79aba3a2f --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/persistentvolumebindercontroller.go @@ -0,0 +1,69 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// PersistentVolumeBinderControllerOptions holds the PersistentVolumeBinderController options. +type PersistentVolumeBinderControllerOptions struct { + PVClaimBinderSyncPeriod metav1.Duration + VolumeConfiguration componentconfig.VolumeConfiguration +} + +// AddFlags adds flags related to PersistentVolumeBinderController for controller manager to the specified FlagSet. +func (o *PersistentVolumeBinderControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.DurationVar(&o.PVClaimBinderSyncPeriod.Duration, "pvclaimbinder-sync-period", o.PVClaimBinderSyncPeriod.Duration, "The period for syncing persistent volumes and persistent volume claims") + fs.StringVar(&o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.PodTemplateFilePathNFS, "pv-recycler-pod-template-filepath-nfs", o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.PodTemplateFilePathNFS, "The file path to a pod definition used as a template for NFS persistent volume recycling") + fs.Int32Var(&o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.MinimumTimeoutNFS, "pv-recycler-minimum-timeout-nfs", o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.MinimumTimeoutNFS, "The minimum ActiveDeadlineSeconds to use for an NFS Recycler pod") + fs.Int32Var(&o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.IncrementTimeoutNFS, "pv-recycler-increment-timeout-nfs", o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.IncrementTimeoutNFS, "the increment of time added per Gi to ActiveDeadlineSeconds for an NFS scrubber pod") + fs.StringVar(&o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.PodTemplateFilePathHostPath, "pv-recycler-pod-template-filepath-hostpath", o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.PodTemplateFilePathHostPath, "The file path to a pod definition used as a template for HostPath persistent volume recycling. This is for development and testing only and will not work in a multi-node cluster.") + fs.Int32Var(&o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.MinimumTimeoutHostPath, "pv-recycler-minimum-timeout-hostpath", o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.MinimumTimeoutHostPath, "The minimum ActiveDeadlineSeconds to use for a HostPath Recycler pod. This is for development and testing only and will not work in a multi-node cluster.") + fs.Int32Var(&o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.IncrementTimeoutHostPath, "pv-recycler-timeout-increment-hostpath", o.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.IncrementTimeoutHostPath, "the increment of time added per Gi to ActiveDeadlineSeconds for a HostPath scrubber pod. This is for development and testing only and will not work in a multi-node cluster.") + fs.BoolVar(&o.VolumeConfiguration.EnableHostPathProvisioning, "enable-hostpath-provisioner", o.VolumeConfiguration.EnableHostPathProvisioning, "Enable HostPath PV provisioning when running without a cloud provider. This allows testing and development of provisioning features. HostPath provisioning is not supported in any way, won't work in a multi-node cluster, and should not be used for anything other than testing or development.") + fs.BoolVar(&o.VolumeConfiguration.EnableDynamicProvisioning, "enable-dynamic-provisioning", o.VolumeConfiguration.EnableDynamicProvisioning, "Enable dynamic provisioning for environments that support it.") + fs.StringVar(&o.VolumeConfiguration.FlexVolumePluginDir, "flex-volume-plugin-dir", o.VolumeConfiguration.FlexVolumePluginDir, "Full path of the directory in which the flex volume plugin should search for additional third party volume plugins.") +} + +// ApplyTo fills up PersistentVolumeBinderController config with options. +func (o *PersistentVolumeBinderControllerOptions) ApplyTo(cfg *componentconfig.PersistentVolumeBinderControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.PVClaimBinderSyncPeriod = o.PVClaimBinderSyncPeriod + cfg.VolumeConfiguration = o.VolumeConfiguration + + return nil +} + +// Validate checks validation of PersistentVolumeBinderControllerOptions. +func (o *PersistentVolumeBinderControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/podgccontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/podgccontroller.go new file mode 100644 index 000000000..8eb82f11c --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/podgccontroller.go @@ -0,0 +1,57 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// PodGCControllerOptions holds the PodGCController options. +type PodGCControllerOptions struct { + TerminatedPodGCThreshold int32 +} + +// AddFlags adds flags related to PodGCController for controller manager to the specified FlagSet. +func (o *PodGCControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.Int32Var(&o.TerminatedPodGCThreshold, "terminated-pod-gc-threshold", o.TerminatedPodGCThreshold, "Number of terminated pods that can exist before the terminated pod garbage collector starts deleting terminated pods. If <= 0, the terminated pod garbage collector is disabled.") +} + +// ApplyTo fills up PodGCController config with options. +func (o *PodGCControllerOptions) ApplyTo(cfg *componentconfig.PodGCControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.TerminatedPodGCThreshold = o.TerminatedPodGCThreshold + + return nil +} + +// Validate checks validation of PodGCControllerOptions. +func (o *PodGCControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/replicasetcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/replicasetcontroller.go new file mode 100644 index 000000000..23e37d28f --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/replicasetcontroller.go @@ -0,0 +1,57 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// ReplicaSetControllerOptions holds the ReplicaSetController options. +type ReplicaSetControllerOptions struct { + ConcurrentRSSyncs int32 +} + +// AddFlags adds flags related to ReplicaSetController for controller manager to the specified FlagSet. +func (o *ReplicaSetControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.Int32Var(&o.ConcurrentRSSyncs, "concurrent-replicaset-syncs", o.ConcurrentRSSyncs, "The number of replica sets that are allowed to sync concurrently. Larger number = more responsive replica management, but more CPU (and network) load") +} + +// ApplyTo fills up ReplicaSetController config with options. +func (o *ReplicaSetControllerOptions) ApplyTo(cfg *componentconfig.ReplicaSetControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ConcurrentRSSyncs = o.ConcurrentRSSyncs + + return nil +} + +// Validate checks validation of ReplicaSetControllerOptions. +func (o *ReplicaSetControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/replicationcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/replicationcontroller.go new file mode 100644 index 000000000..a64b4fe6f --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/replicationcontroller.go @@ -0,0 +1,57 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// ReplicationControllerOptions holds the ReplicationController options. +type ReplicationControllerOptions struct { + ConcurrentRCSyncs int32 +} + +// AddFlags adds flags related to ReplicationController for controller manager to the specified FlagSet. +func (o *ReplicationControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.Int32Var(&o.ConcurrentRCSyncs, "concurrent_rc_syncs", o.ConcurrentRCSyncs, "The number of replication controllers that are allowed to sync concurrently. Larger number = more responsive replica management, but more CPU (and network) load") +} + +// ApplyTo fills up ReplicationController config with options. +func (o *ReplicationControllerOptions) ApplyTo(cfg *componentconfig.ReplicationControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ConcurrentRCSyncs = o.ConcurrentRCSyncs + + return nil +} + +// Validate checks validation of ReplicationControllerOptions. +func (o *ReplicationControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/resourcequotacontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/resourcequotacontroller.go new file mode 100644 index 000000000..b684e6e7e --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/resourcequotacontroller.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// ResourceQuotaControllerOptions holds the ResourceQuotaController options. +type ResourceQuotaControllerOptions struct { + ResourceQuotaSyncPeriod metav1.Duration + ConcurrentResourceQuotaSyncs int32 +} + +// AddFlags adds flags related to ResourceQuotaController for controller manager to the specified FlagSet. +func (o *ResourceQuotaControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.DurationVar(&o.ResourceQuotaSyncPeriod.Duration, "resource-quota-sync-period", o.ResourceQuotaSyncPeriod.Duration, "The period for syncing quota usage status in the system") + fs.Int32Var(&o.ConcurrentResourceQuotaSyncs, "concurrent-resource-quota-syncs", o.ConcurrentResourceQuotaSyncs, "The number of resource quotas that are allowed to sync concurrently. Larger number = more responsive quota management, but more CPU (and network) load") +} + +// ApplyTo fills up ResourceQuotaController config with options. +func (o *ResourceQuotaControllerOptions) ApplyTo(cfg *componentconfig.ResourceQuotaControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ResourceQuotaSyncPeriod = o.ResourceQuotaSyncPeriod + cfg.ConcurrentResourceQuotaSyncs = o.ConcurrentResourceQuotaSyncs + + return nil +} + +// Validate checks validation of ResourceQuotaControllerOptions. +func (o *ResourceQuotaControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/serviceaccountcontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/serviceaccountcontroller.go new file mode 100644 index 000000000..80b26fe9b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/serviceaccountcontroller.go @@ -0,0 +1,63 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// SAControllerOptions holds the ServiceAccountController options. +type SAControllerOptions struct { + ServiceAccountKeyFile string + ConcurrentSATokenSyncs int32 + RootCAFile string +} + +// AddFlags adds flags related to ServiceAccountController for controller manager to the specified FlagSet +func (o *SAControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.StringVar(&o.ServiceAccountKeyFile, "service-account-private-key-file", o.ServiceAccountKeyFile, "Filename containing a PEM-encoded private RSA or ECDSA key used to sign service account tokens.") + fs.Int32Var(&o.ConcurrentSATokenSyncs, "concurrent-serviceaccount-token-syncs", o.ConcurrentSATokenSyncs, "The number of service account token objects that are allowed to sync concurrently. Larger number = more responsive token generation, but more CPU (and network) load") + fs.StringVar(&o.RootCAFile, "root-ca-file", o.RootCAFile, "If set, this root certificate authority will be included in service account's token secret. This must be a valid PEM-encoded CA bundle.") +} + +// ApplyTo fills up ServiceAccountController config with options. +func (o *SAControllerOptions) ApplyTo(cfg *componentconfig.SAControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ServiceAccountKeyFile = o.ServiceAccountKeyFile + cfg.ConcurrentSATokenSyncs = o.ConcurrentSATokenSyncs + cfg.RootCAFile = o.RootCAFile + + return nil +} + +// Validate checks validation of ServiceAccountControllerOptions. +func (o *SAControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/servicecontroller.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/servicecontroller.go new file mode 100644 index 000000000..26cdf8a3c --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/options/servicecontroller.go @@ -0,0 +1,57 @@ +/* +Copyright 2018 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 options + +import ( + "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// ServiceControllerOptions holds the ServiceController options. +type ServiceControllerOptions struct { + ConcurrentServiceSyncs int32 +} + +// AddFlags adds flags related to ServiceController for controller manager to the specified FlagSet. +func (o *ServiceControllerOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.Int32Var(&o.ConcurrentServiceSyncs, "concurrent-service-syncs", o.ConcurrentServiceSyncs, "The number of services that are allowed to sync concurrently. Larger number = more responsive service management, but more CPU (and network) load") +} + +// ApplyTo fills up ServiceController config with options. +func (o *ServiceControllerOptions) ApplyTo(cfg *componentconfig.ServiceControllerConfiguration) error { + if o == nil { + return nil + } + + cfg.ConcurrentServiceSyncs = o.ConcurrentServiceSyncs + + return nil +} + +// Validate checks validation of ServiceControllerOptions. +func (o *ServiceControllerOptions) Validate() []error { + if o == nil { + return nil + } + + errs := []error{} + return errs +} diff --git a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/serve.go b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/serve.go index 7a9d36d11..305a3ba9d 100644 --- a/vendor/k8s.io/kubernetes/cmd/controller-manager/app/serve.go +++ b/vendor/k8s.io/kubernetes/cmd/controller-manager/app/serve.go @@ -19,45 +19,46 @@ package app import ( "net/http" goruntime "runtime" - "time" "github.com/prometheus/client_golang/prometheus" genericapifilters "k8s.io/apiserver/pkg/endpoints/filters" apirequest "k8s.io/apiserver/pkg/endpoints/request" + apiserver "k8s.io/apiserver/pkg/server" genericfilters "k8s.io/apiserver/pkg/server/filters" "k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/mux" "k8s.io/apiserver/pkg/server/routes" "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/util/configz" ) -type serveFunc func(handler http.Handler, shutdownTimeout time.Duration, stopCh <-chan struct{}) error +// BuildHandlerChain builds a handler chain with a base handler and CompletedConfig. +func BuildHandlerChain(apiHandler http.Handler, authorizationInfo *apiserver.AuthorizationInfo, authenticationInfo *apiserver.AuthenticationInfo) http.Handler { + requestInfoResolver := &apirequest.RequestInfoFactory{} + failedHandler := genericapifilters.Unauthorized(legacyscheme.Codecs, false) + + handler := genericapifilters.WithAuthorization(apiHandler, authorizationInfo.Authorizer, legacyscheme.Codecs) + handler = genericapifilters.WithAuthentication(handler, authenticationInfo.Authenticator, failedHandler) + handler = genericapifilters.WithRequestInfo(handler, requestInfoResolver) + handler = genericfilters.WithPanicRecovery(handler) + + return handler +} -// Serve creates a base handler chain for a controller manager. It runs the -// the chain with the given serveFunc. -func Serve(c *CompletedConfig, serveFunc serveFunc, stopCh <-chan struct{}) error { +// NewBaseHandler takes in CompletedConfig and returns a handler. +func NewBaseHandler(c *componentconfig.DebuggingConfiguration) http.Handler { mux := mux.NewPathRecorderMux("controller-manager") healthz.InstallHandler(mux) - if c.ComponentConfig.EnableProfiling { + if c.EnableProfiling { routes.Profiling{}.Install(mux) - if c.ComponentConfig.EnableContentionProfiling { + if c.EnableContentionProfiling { goruntime.SetBlockProfileRate(1) } } configz.InstallHandler(mux) mux.Handle("/metrics", prometheus.Handler()) - requestContextMapper := apirequest.NewRequestContextMapper() - requestInfoResolver := &apirequest.RequestInfoFactory{} - failedHandler := genericapifilters.Unauthorized(requestContextMapper, legacyscheme.Codecs, false) - - handler := genericapifilters.WithAuthorization(mux, requestContextMapper, c.Authorization.Authorizer, legacyscheme.Codecs) - handler = genericapifilters.WithAuthentication(handler, requestContextMapper, c.Authentication.Authenticator, failedHandler) - handler = genericapifilters.WithRequestInfo(handler, requestInfoResolver, requestContextMapper) - handler = apirequest.WithRequestContext(handler, requestContextMapper) - handler = genericfilters.WithPanicRecovery(handler) - - return serveFunc(handler, 0, stopCh) + return mux } diff --git a/vendor/k8s.io/kubernetes/cmd/gendocs/BUILD b/vendor/k8s.io/kubernetes/cmd/gendocs/BUILD index 44f9a9a2d..04897fb31 100644 --- a/vendor/k8s.io/kubernetes/cmd/gendocs/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/gendocs/BUILD @@ -18,7 +18,6 @@ go_library( deps = [ "//cmd/genutils:go_default_library", "//pkg/kubectl/cmd:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", "//vendor/github.com/spf13/cobra/doc:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/gendocs/gen_kubectl_docs.go b/vendor/k8s.io/kubernetes/cmd/gendocs/gen_kubectl_docs.go index 39c1d8f39..dc03a0e82 100644 --- a/vendor/k8s.io/kubernetes/cmd/gendocs/gen_kubectl_docs.go +++ b/vendor/k8s.io/kubernetes/cmd/gendocs/gen_kubectl_docs.go @@ -24,7 +24,6 @@ import ( "github.com/spf13/cobra/doc" "k8s.io/kubernetes/cmd/genutils" "k8s.io/kubernetes/pkg/kubectl/cmd" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ) func main() { @@ -47,6 +46,6 @@ func main() { // regardless of where we run. os.Setenv("HOME", "/home/username") // TODO os.Stdin should really be something like ioutil.Discard, but a Reader - kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + kubectl := cmd.NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard) doc.GenMarkdownTree(kubectl, outDir) } diff --git a/vendor/k8s.io/kubernetes/cmd/genkubedocs/BUILD b/vendor/k8s.io/kubernetes/cmd/genkubedocs/BUILD index fd5d3a064..9aebfb142 100644 --- a/vendor/k8s.io/kubernetes/cmd/genkubedocs/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/genkubedocs/BUILD @@ -31,6 +31,7 @@ go_library( "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/cobra/doc:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/genkubedocs/gen_kube_docs.go b/vendor/k8s.io/kubernetes/cmd/genkubedocs/gen_kube_docs.go index 975466f44..47c2e0b87 100644 --- a/vendor/k8s.io/kubernetes/cmd/genkubedocs/gen_kube_docs.go +++ b/vendor/k8s.io/kubernetes/cmd/genkubedocs/gen_kube_docs.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra/doc" "github.com/spf13/pflag" + "k8s.io/apiserver/pkg/server" ccmapp "k8s.io/kubernetes/cmd/cloud-controller-manager/app" "k8s.io/kubernetes/cmd/genutils" apiservapp "k8s.io/kubernetes/cmd/kube-apiserver/app" @@ -53,7 +54,7 @@ func main() { switch module { case "kube-apiserver": // generate docs for kube-apiserver - apiserver := apiservapp.NewAPIServerCommand() + apiserver := apiservapp.NewAPIServerCommand(server.SetupSignalHandler()) doc.GenMarkdownTree(apiserver, outDir) case "kube-controller-manager": // generate docs for kube-controller-manager @@ -73,7 +74,7 @@ func main() { doc.GenMarkdownTree(scheduler, outDir) case "kubelet": // generate docs for kubelet - kubelet := kubeletapp.NewKubeletCommand() + kubelet := kubeletapp.NewKubeletCommand(server.SetupSignalHandler()) doc.GenMarkdownTree(kubelet, outDir) case "kubeadm": // resets global flags created by kubelet or other commands e.g. diff --git a/vendor/k8s.io/kubernetes/cmd/genman/BUILD b/vendor/k8s.io/kubernetes/cmd/genman/BUILD index e9ee6dcba..82398a133 100644 --- a/vendor/k8s.io/kubernetes/cmd/genman/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/genman/BUILD @@ -25,10 +25,10 @@ go_library( "//cmd/kubeadm/app/cmd:go_default_library", "//cmd/kubelet/app:go_default_library", "//pkg/kubectl/cmd:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", "//vendor/github.com/cpuguy83/go-md2man/md2man:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/genman/gen_kube_man.go b/vendor/k8s.io/kubernetes/cmd/genman/gen_kube_man.go index 416d4a9f9..62ceaab52 100644 --- a/vendor/k8s.io/kubernetes/cmd/genman/gen_kube_man.go +++ b/vendor/k8s.io/kubernetes/cmd/genman/gen_kube_man.go @@ -26,6 +26,7 @@ import ( mangen "github.com/cpuguy83/go-md2man/md2man" "github.com/spf13/cobra" "github.com/spf13/pflag" + "k8s.io/apiserver/pkg/server" ccmapp "k8s.io/kubernetes/cmd/cloud-controller-manager/app" "k8s.io/kubernetes/cmd/genutils" apiservapp "k8s.io/kubernetes/cmd/kube-apiserver/app" @@ -35,7 +36,6 @@ import ( kubeadmapp "k8s.io/kubernetes/cmd/kubeadm/app/cmd" kubeletapp "k8s.io/kubernetes/cmd/kubelet/app" kubectlcmd "k8s.io/kubernetes/pkg/kubectl/cmd" - kubectlcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ) func main() { @@ -63,7 +63,7 @@ func main() { switch module { case "kube-apiserver": // generate manpage for kube-apiserver - apiserver := apiservapp.NewAPIServerCommand() + apiserver := apiservapp.NewAPIServerCommand(server.SetupSignalHandler()) genMarkdown(apiserver, "", outDir) for _, c := range apiserver.Commands() { genMarkdown(c, "kube-apiserver", outDir) @@ -98,7 +98,7 @@ func main() { } case "kubelet": // generate manpage for kubelet - kubelet := kubeletapp.NewKubeletCommand() + kubelet := kubeletapp.NewKubeletCommand(server.SetupSignalHandler()) genMarkdown(kubelet, "", outDir) for _, c := range kubelet.Commands() { genMarkdown(c, "kubelet", outDir) @@ -106,7 +106,7 @@ func main() { case "kubectl": // generate manpage for kubectl // TODO os.Stdin should really be something like ioutil.Discard, but a Reader - kubectl := kubectlcmd.NewKubectlCommand(kubectlcmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + kubectl := kubectlcmd.NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard) genMarkdown(kubectl, "", outDir) for _, c := range kubectl.Commands() { genMarkdown(c, "kubectl", outDir) diff --git a/vendor/k8s.io/kubernetes/cmd/genyaml/BUILD b/vendor/k8s.io/kubernetes/cmd/genyaml/BUILD index 0571d54d8..924e6144d 100644 --- a/vendor/k8s.io/kubernetes/cmd/genyaml/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/genyaml/BUILD @@ -18,7 +18,6 @@ go_library( deps = [ "//cmd/genutils:go_default_library", "//pkg/kubectl/cmd:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/gopkg.in/yaml.v2:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/genyaml/gen_kubectl_yaml.go b/vendor/k8s.io/kubernetes/cmd/genyaml/gen_kubectl_yaml.go index 376a1c712..c95ee2a3d 100644 --- a/vendor/k8s.io/kubernetes/cmd/genyaml/gen_kubectl_yaml.go +++ b/vendor/k8s.io/kubernetes/cmd/genyaml/gen_kubectl_yaml.go @@ -27,7 +27,6 @@ import ( "gopkg.in/yaml.v2" "k8s.io/kubernetes/cmd/genutils" "k8s.io/kubernetes/pkg/kubectl/cmd" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ) type cmdOption struct { @@ -66,7 +65,7 @@ func main() { // regardless of where we run. os.Setenv("HOME", "/home/username") // TODO os.Stdin should really be something like ioutil.Discard, but a Reader - kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + kubectl := cmd.NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard) genYaml(kubectl, "", outDir) for _, c := range kubectl.Commands() { genYaml(c, "kubectl", outDir) diff --git a/vendor/k8s.io/kubernetes/cmd/hyperkube/BUILD b/vendor/k8s.io/kubernetes/cmd/hyperkube/BUILD index 9b17e5eb7..7d60ed683 100644 --- a/vendor/k8s.io/kubernetes/cmd/hyperkube/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/hyperkube/BUILD @@ -29,6 +29,7 @@ go_library( "//pkg/version/prometheus:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/logs:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/cmd/hyperkube/main.go b/vendor/k8s.io/kubernetes/cmd/hyperkube/main.go index 1c5a276ea..8482ab1c3 100644 --- a/vendor/k8s.io/kubernetes/cmd/hyperkube/main.go +++ b/vendor/k8s.io/kubernetes/cmd/hyperkube/main.go @@ -32,6 +32,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" + "k8s.io/apiserver/pkg/server" utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/apiserver/pkg/util/logs" cloudcontrollermanager "k8s.io/kubernetes/cmd/cloud-controller-manager/app" @@ -48,7 +49,7 @@ import ( func main() { rand.Seed(time.Now().UTC().UnixNano()) - hyperkubeCommand, allCommandFns := NewHyperKubeCommand() + hyperkubeCommand, allCommandFns := NewHyperKubeCommand(server.SetupSignalHandler()) // TODO: once we switch everything over to Cobra commands, we can go back to calling // utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the @@ -82,12 +83,12 @@ func commandFor(basename string, defaultCommand *cobra.Command, commands []func( return defaultCommand } -// NewCmdRequestProject implement the OpenShift cli RequestProject command. -func NewHyperKubeCommand() (*cobra.Command, []func() *cobra.Command) { +// NewHyperKubeCommand is the entry point for hyperkube +func NewHyperKubeCommand(stopCh <-chan struct{}) (*cobra.Command, []func() *cobra.Command) { // these have to be functions since the command is polymorphic. Cobra wants you to be top level // command to get executed apiserver := func() *cobra.Command { - ret := kubeapiserver.NewAPIServerCommand() + ret := kubeapiserver.NewAPIServerCommand(stopCh) // add back some unfortunate aliases that should be removed ret.Aliases = []string{"apiserver"} return ret @@ -111,7 +112,7 @@ func NewHyperKubeCommand() (*cobra.Command, []func() *cobra.Command) { return ret } kubectlCmd := func() *cobra.Command { return kubectl.NewDefaultKubectlCommand() } - kubelet := func() *cobra.Command { return kubelet.NewKubeletCommand() } + kubelet := func() *cobra.Command { return kubelet.NewKubeletCommand(stopCh) } cloudController := func() *cobra.Command { return cloudcontrollermanager.NewCloudControllerManagerCommand() } commandFns := []func() *cobra.Command{ diff --git a/vendor/k8s.io/kubernetes/cmd/importverifier/importverifier.go b/vendor/k8s.io/kubernetes/cmd/importverifier/importverifier.go index 584a74bdb..c73dad68c 100644 --- a/vendor/k8s.io/kubernetes/cmd/importverifier/importverifier.go +++ b/vendor/k8s.io/kubernetes/cmd/importverifier/importverifier.go @@ -57,6 +57,8 @@ type ImportRestriction struct { // given as paths that would be used in a Go // import statement AllowedImports []string `yaml:"allowedImports"` + // ExcludeTests will skip checking test dependencies. + ExcludeTests bool `yaml:"excludeTests"` } // ForbiddenImportsFor determines all of the forbidden @@ -120,7 +122,11 @@ func isPathUnder(base, path string) (bool, error) { // and returns a deduplicated list of them func (i *ImportRestriction) forbiddenImportsFor(pkg Package) []string { forbiddenImportSet := map[string]struct{}{} - for _, imp := range append(pkg.Imports, append(pkg.TestImports, pkg.XTestImports...)...) { + imports := pkg.Imports + if !i.ExcludeTests { + imports = append(imports, append(pkg.TestImports, pkg.XTestImports...)...) + } + for _, imp := range imports { path := extractVendorPath(imp) if i.isForbidden(path) { forbiddenImportSet[path] = struct{}{} @@ -230,7 +236,7 @@ func resolvePackageTree(treeBase string) ([]Package, error) { if err != nil { var message string if ee, ok := err.(*exec.ExitError); ok { - message = fmt.Sprintf("%v\n%v", ee, ee.Stderr) + message = fmt.Sprintf("%v\n%v", ee, string(ee.Stderr)) } else { message = fmt.Sprintf("%v", err) } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/BUILD index e13b255fd..78684bd71 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/BUILD @@ -23,6 +23,7 @@ go_library( "//pkg/client/metrics/prometheus:go_default_library", "//pkg/version/prometheus:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/logs:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/OWNERS b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/OWNERS index d559b8c94..07cca6313 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/OWNERS +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/OWNERS @@ -18,4 +18,6 @@ reviewers: - liggitt - nikhiljindal - ncdc -- sttts \ No newline at end of file +- sttts +- hzxuzhonghu +- CaoShuFeng diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/apiserver.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/apiserver.go index 9d3ce436d..762c09f6d 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/apiserver.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/apiserver.go @@ -27,6 +27,7 @@ import ( "github.com/spf13/pflag" + "k8s.io/apiserver/pkg/server" utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/apiserver/pkg/util/logs" "k8s.io/kubernetes/cmd/kube-apiserver/app" @@ -37,7 +38,7 @@ import ( func main() { rand.Seed(time.Now().UTC().UnixNano()) - command := app.NewAPIServerCommand() + command := app.NewAPIServerCommand(server.SetupSignalHandler()) // TODO: once we switch everything over to Cobra commands, we can go back to calling // utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/BUILD index 876316b7a..690d0f019 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/BUILD @@ -70,6 +70,7 @@ go_library( "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/initializer:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library", @@ -78,9 +79,11 @@ go_library( "//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/etcd3/preflight:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//vendor/k8s.io/client-go/discovery/cached:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library", "//vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go index 9a1f5ad22..86bcc77ae 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go @@ -84,7 +84,7 @@ func createAggregatorConfig( if err := commandOptions.APIEnablement.ApplyTo( &genericConfig, aggregatorapiserver.DefaultAPIResourceConfigSource(), - aggregatorscheme.Registry); err != nil { + aggregatorscheme.Scheme); err != nil { return nil, err } @@ -139,7 +139,10 @@ func createAggregatorServer(aggregatorConfig *aggregatorapiserver.Config, delega go func() { // let the CRD controller process the initial set of CRDs before starting the autoregistration controller. // this prevents the autoregistration controller's initial sync from deleting APIServices for CRDs that still exist. - crdRegistrationController.WaitForInitialSync() + // we only need to do this if CRDs are enabled on this server. We can't use discovery because we are the source for discovery. + if aggregatorConfig.GenericConfig.MergedResourceConfig.AnyVersionForGroupEnabled("apiextensions.k8s.io") { + crdRegistrationController.WaitForInitialSync() + } autoRegistrationController.Run(5, context.StopCh) }() return nil @@ -260,6 +263,7 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{ {Group: "admissionregistration.k8s.io", Version: "v1"}: {group: 16700, version: 15}, {Group: "admissionregistration.k8s.io", Version: "v1beta1"}: {group: 16700, version: 12}, {Group: "admissionregistration.k8s.io", Version: "v1alpha1"}: {group: 16700, version: 9}, + {Group: "scheduling.k8s.io", Version: "v1beta1"}: {group: 16600, version: 12}, {Group: "scheduling.k8s.io", Version: "v1alpha1"}: {group: 16600, version: 9}, // Append a new group to the end of the list if unsure. // You can use min(existing group)-100 as the initial value for a group. diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/apiextensions.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/apiextensions.go index 688cf5f2a..b94b5f311 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/apiextensions.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/apiextensions.go @@ -35,6 +35,7 @@ func createAPIExtensionsConfig( externalInformers kubeexternalinformers.SharedInformerFactory, pluginInitializers []admission.PluginInitializer, commandOptions *options.ServerRunOptions, + masterCount int, ) (*apiextensionsapiserver.Config, error) { // make a shallow copy to let us twiddle a few things // most of the config actually remains the same. We only need to mess with a couple items related to the particulars of the apiextensions @@ -58,7 +59,7 @@ func createAPIExtensionsConfig( if err := commandOptions.APIEnablement.ApplyTo( &genericConfig, apiextensionsapiserver.DefaultAPIResourceConfigSource(), - apiextensionsapiserver.Registry); err != nil { + apiextensionsapiserver.Scheme); err != nil { return nil, err } @@ -69,6 +70,7 @@ func createAPIExtensionsConfig( }, ExtraConfig: apiextensionsapiserver.ExtraConfig{ CRDRESTOptionsGetter: apiextensionscmd.NewCRDRESTOptionsGetter(etcdOptions), + MasterCount: masterCount, }, } @@ -76,10 +78,5 @@ func createAPIExtensionsConfig( } func createAPIExtensionsServer(apiextensionsConfig *apiextensionsapiserver.Config, delegateAPIServer genericapiserver.DelegationTarget) (*apiextensionsapiserver.CustomResourceDefinitions, error) { - apiextensionsServer, err := apiextensionsConfig.Complete().New(delegateAPIServer) - if err != nil { - return nil, err - } - - return apiextensionsServer, nil + return apiextensionsConfig.Complete().New(delegateAPIServer) } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/BUILD index 5459e1ce7..265f07841 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/BUILD @@ -16,7 +16,6 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/core/validation:go_default_library", "//pkg/features:go_default_library", "//pkg/kubeapiserver/options:go_default_library", "//pkg/kubelet/client:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/options.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/options.go index 23088142a..bb8d8dc7e 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/options.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/options.go @@ -26,7 +26,6 @@ import ( genericoptions "k8s.io/apiserver/pkg/server/options" "k8s.io/apiserver/pkg/storage/storagebackend" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/validation" kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/master/ports" @@ -94,7 +93,7 @@ func NewServerRunOptions() *ServerRunOptions { EnableLogsHandler: true, EventTTL: 1 * time.Hour, MasterCount: 1, - EndpointReconcilerType: string(reconcilers.MasterCountReconcilerType), + EndpointReconcilerType: string(reconcilers.LeaseEndpointReconcilerType), KubeletConfig: kubeletclient.KubeletClientConfig{ Port: ports.KubeletPort, ReadOnlyPort: ports.KubeletReadOnlyPort, @@ -167,7 +166,7 @@ func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) { "Currently only applies to long-running requests.") fs.IntVar(&s.MasterCount, "apiserver-count", s.MasterCount, - "The number of apiservers running in the cluster, must be a positive number.") + "The number of apiservers running in the cluster, must be a positive number. (In use when --endpoint-reconciler-type=master-count is enabled.)") fs.StringVar(&s.EndpointReconcilerType, "endpoint-reconciler-type", string(s.EndpointReconcilerType), "Use an endpoint reconciler ("+strings.Join(reconcilers.AllTypes.Names(), ", ")+")") @@ -213,11 +212,10 @@ func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.KubeletConfig.CAFile, "kubelet-certificate-authority", s.KubeletConfig.CAFile, "Path to a cert file for the certificate authority.") - // TODO: delete this flag as soon as we identify and fix all clients that send malformed updates, like #14126. - fs.BoolVar(&validation.RepairMalformedUpdates, "repair-malformed-updates", validation.RepairMalformedUpdates, ""+ - "If true, server will do its best to fix the update request to pass the validation, "+ - "e.g., setting empty UID in update request to its existing value. This flag can be turned off "+ - "after we fix all the clients that send malformed updates.") + // TODO: delete this flag in 1.13 + repair := false + fs.BoolVar(&repair, "repair-malformed-updates", false, "deprecated") + fs.MarkDeprecated("repair-malformed-updates", "This flag will be removed in a future version") fs.StringVar(&s.ProxyClientCertFile, "proxy-client-cert-file", s.ProxyClientCertFile, ""+ "Client certificate used to prove the identity of the aggregator or kube-apiserver "+ @@ -236,6 +234,5 @@ func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) { "Turns on aggregator routing requests to endoints IP rather than cluster IP.") fs.StringVar(&s.ServiceAccountSigningKeyFile, "service-account-signing-key-file", s.ServiceAccountSigningKeyFile, ""+ - "Path to the file that contains the current private key of the service account token issuer. The issuer will sign issued ID tokens with this private key. (Ignored unless alpha TokenRequest is enabled") - + "Path to the file that contains the current private key of the service account token issuer. The issuer will sign issued ID tokens with this private key. (Requires the 'TokenRequest' feature gate.)") } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/options_test.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/options_test.go index d450cf6e2..8f9e3a921 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/options_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/options_test.go @@ -65,6 +65,7 @@ func TestAddFlags(t *testing.T) { "--audit-log-truncate-enabled=true", "--audit-log-truncate-max-batch-size=45", "--audit-log-truncate-max-event-size=44", + "--audit-log-version=audit.k8s.io/v1alpha1", "--audit-policy-file=/policy", "--audit-webhook-config-file=/webhook-config", "--audit-webhook-mode=blocking", @@ -78,9 +79,10 @@ func TestAddFlags(t *testing.T) { "--audit-webhook-truncate-max-batch-size=43", "--audit-webhook-truncate-max-event-size=42", "--audit-webhook-initial-backoff=2s", + "--audit-webhook-version=audit.k8s.io/v1alpha1", "--authentication-token-webhook-cache-ttl=3m", "--authentication-token-webhook-config-file=/token-webhook-config", - "--authorization-mode=AlwaysDeny", + "--authorization-mode=AlwaysDeny,RBAC", "--authorization-policy-file=/policy", "--authorization-webhook-cache-authorized-ttl=3m", "--authorization-webhook-cache-unauthorized-ttl=1m", @@ -94,7 +96,7 @@ func TestAddFlags(t *testing.T) { "--enable-aggregator-routing=true", "--enable-logs-handler=false", "--enable-swagger-ui=true", - "--endpoint-reconciler-type=" + string(reconcilers.MasterCountReconcilerType), + "--endpoint-reconciler-type=" + string(reconcilers.LeaseEndpointReconcilerType), "--etcd-quorum-read=false", "--etcd-keyfile=/var/run/kubernetes/etcd.key", "--etcd-certfile=/var/run/kubernetes/etcdce.crt", @@ -118,7 +120,7 @@ func TestAddFlags(t *testing.T) { ServiceNodePortRange: kubeoptions.DefaultServiceNodePortRange, ServiceClusterIPRange: kubeoptions.DefaultServiceIPCIDR, MasterCount: 5, - EndpointReconcilerType: string(reconcilers.MasterCountReconcilerType), + EndpointReconcilerType: string(reconcilers.LeaseEndpointReconcilerType), AllowPrivileged: false, GenericServerRunOptions: &apiserveroptions.ServerRunOptions{ AdvertiseAddress: net.ParseIP("192.168.10.10"), @@ -213,6 +215,7 @@ func TestAddFlags(t *testing.T) { MaxEventSize: 44, }, }, + GroupVersionString: "audit.k8s.io/v1alpha1", }, WebhookOptions: apiserveroptions.AuditWebhookOptions{ ConfigFile: "/webhook-config", @@ -234,7 +237,8 @@ func TestAddFlags(t *testing.T) { MaxEventSize: 42, }, }, - InitialBackoff: 2 * time.Second, + InitialBackoff: 2 * time.Second, + GroupVersionString: "audit.k8s.io/v1alpha1", }, PolicyFile: "/policy", }, @@ -269,7 +273,7 @@ func TestAddFlags(t *testing.T) { TokenFailureCacheTTL: 0, }, Authorization: &kubeoptions.BuiltInAuthorizationOptions{ - Mode: "AlwaysDeny", + Modes: []string{"AlwaysDeny", "RBAC"}, PolicyFile: "/policy", WebhookConfigFile: "/webhook-config", WebhookCacheAuthorizedTTL: 180000000000, @@ -280,8 +284,8 @@ func TestAddFlags(t *testing.T) { CloudProvider: "azure", }, StorageSerialization: &kubeoptions.StorageSerializationOptions{ - StorageVersions: legacyscheme.Registry.AllPreferredGroupVersions(), - DefaultStorageVersions: legacyscheme.Registry.AllPreferredGroupVersions(), + StorageVersions: kubeoptions.ToPreferredVersionString(legacyscheme.Scheme.PreferredVersionAllGroups()), + DefaultStorageVersions: kubeoptions.ToPreferredVersionString(legacyscheme.Scheme.PreferredVersionAllGroups()), }, APIEnablement: &apiserveroptions.APIEnablementOptions{ RuntimeConfig: utilflag.ConfigurationMap{}, diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/validation.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/validation.go index 44f1df11d..f12957566 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/validation.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/options/validation.go @@ -50,36 +50,39 @@ func validateServiceNodePort(options *ServerRunOptions) []error { } // Validate checks ServerRunOptions and return a slice of found errors. -func (options *ServerRunOptions) Validate() []error { +func (s *ServerRunOptions) Validate() []error { var errors []error - if errs := options.Etcd.Validate(); len(errs) > 0 { + if errs := s.Etcd.Validate(); len(errs) > 0 { errors = append(errors, errs...) } - if errs := validateClusterIPFlags(options); len(errs) > 0 { + if errs := validateClusterIPFlags(s); len(errs) > 0 { errors = append(errors, errs...) } - if errs := validateServiceNodePort(options); len(errs) > 0 { + if errs := validateServiceNodePort(s); len(errs) > 0 { errors = append(errors, errs...) } - if errs := options.SecureServing.Validate(); len(errs) > 0 { + if errs := s.SecureServing.Validate(); len(errs) > 0 { errors = append(errors, errs...) } - if errs := options.Authentication.Validate(); len(errs) > 0 { + if errs := s.Authentication.Validate(); len(errs) > 0 { errors = append(errors, errs...) } - if errs := options.Audit.Validate(); len(errs) > 0 { + if errs := s.Authorization.Validate(); len(errs) > 0 { errors = append(errors, errs...) } - if errs := options.Admission.Validate(); len(errs) > 0 { + if errs := s.Audit.Validate(); len(errs) > 0 { errors = append(errors, errs...) } - if errs := options.InsecureServing.Validate("insecure-port"); len(errs) > 0 { + if errs := s.Admission.Validate(); len(errs) > 0 { errors = append(errors, errs...) } - if options.MasterCount <= 0 { - errors = append(errors, fmt.Errorf("--apiserver-count should be a positive number, but value '%d' provided", options.MasterCount)) + if errs := s.InsecureServing.Validate(); len(errs) > 0 { + errors = append(errors, errs...) + } + if s.MasterCount <= 0 { + errors = append(errors, fmt.Errorf("--apiserver-count should be a positive number, but value '%d' provided", s.MasterCount)) } - if errs := options.APIEnablement.Validate(legacyscheme.Registry, apiextensionsapiserver.Registry, aggregatorscheme.Registry); len(errs) > 0 { + if errs := s.APIEnablement.Validate(legacyscheme.Scheme, apiextensionsapiserver.Scheme, aggregatorscheme.Scheme); len(errs) > 0 { errors = append(errors, errs...) } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/server.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/server.go index 417811217..b936c9ece 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/server.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/server.go @@ -27,7 +27,6 @@ import ( "net/http" "net/url" "os" - "reflect" "strconv" "strings" "time" @@ -36,6 +35,7 @@ import ( "github.com/golang/glog" "github.com/spf13/cobra" + extensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver" "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -47,7 +47,7 @@ import ( webhookinit "k8s.io/apiserver/pkg/admission/plugin/webhook/initializer" "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/apiserver/pkg/server" + openapinamer "k8s.io/apiserver/pkg/endpoints/openapi" genericapiserver "k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server/filters" serveroptions "k8s.io/apiserver/pkg/server/options" @@ -55,11 +55,14 @@ import ( serverstorage "k8s.io/apiserver/pkg/server/storage" "k8s.io/apiserver/pkg/storage/etcd3/preflight" utilfeature "k8s.io/apiserver/pkg/util/feature" + cacheddiscovery "k8s.io/client-go/discovery/cached" clientgoinformers "k8s.io/client-go/informers" clientgoclientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" certutil "k8s.io/client-go/util/cert" aggregatorapiserver "k8s.io/kube-aggregator/pkg/apiserver" + aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme" openapi "k8s.io/kube-openapi/pkg/common" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -105,7 +108,7 @@ const etcdRetryLimit = 60 const etcdRetryInterval = 1 * time.Second // NewAPIServerCommand creates a *cobra.Command object with default parameters -func NewAPIServerCommand() *cobra.Command { +func NewAPIServerCommand(stopCh <-chan struct{}) *cobra.Command { s := options.NewServerRunOptions() cmd := &cobra.Command{ Use: "kube-apiserver", @@ -113,15 +116,22 @@ func NewAPIServerCommand() *cobra.Command { for the api objects which include pods, services, replicationcontrollers, and others. The API Server services REST operations and provides the frontend to the cluster's shared state through which all other components interact.`, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { verflag.PrintAndExitIfRequested() utilflag.PrintFlags(cmd.Flags()) - stopCh := server.SetupSignalHandler() - if err := Run(s, stopCh); err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) + // set default options + completedOptions, err := Complete(s) + if err != nil { + return err } + + // validate options + if errs := completedOptions.Validate(); len(errs) != 0 { + return utilerrors.NewAggregate(errs) + } + + return Run(completedOptions, stopCh) }, } s.AddFlags(cmd.Flags()) @@ -130,11 +140,11 @@ cluster's shared state through which all other components interact.`, } // Run runs the specified APIServer. This should never exit. -func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error { +func Run(completeOptions completedServerRunOptions, stopCh <-chan struct{}) error { // To help debugging, immediately log version glog.Infof("Version: %+v", version.Get()) - server, err := CreateServerChain(runOptions, stopCh) + server, err := CreateServerChain(completeOptions, stopCh) if err != nil { return err } @@ -143,46 +153,32 @@ func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error { } // CreateServerChain creates the apiservers connected via delegation. -func CreateServerChain(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) (*genericapiserver.GenericAPIServer, error) { - nodeTunneler, proxyTransport, err := CreateNodeDialer(runOptions) +func CreateServerChain(completedOptions completedServerRunOptions, stopCh <-chan struct{}) (*genericapiserver.GenericAPIServer, error) { + nodeTunneler, proxyTransport, err := CreateNodeDialer(completedOptions) if err != nil { return nil, err } - kubeAPIServerConfig, sharedInformers, versionedInformers, insecureServingOptions, serviceResolver, pluginInitializer, err := CreateKubeAPIServerConfig(runOptions, nodeTunneler, proxyTransport) + kubeAPIServerConfig, sharedInformers, versionedInformers, insecureServingOptions, serviceResolver, pluginInitializer, admissionPostStartHook, err := CreateKubeAPIServerConfig(completedOptions, nodeTunneler, proxyTransport) if err != nil { return nil, err } - // TPRs are enabled and not yet beta, since this these are the successor, they fall under the same enablement rule // If additional API servers are added, they should be gated. - apiExtensionsConfig, err := createAPIExtensionsConfig(*kubeAPIServerConfig.GenericConfig, versionedInformers, pluginInitializer, runOptions) + apiExtensionsConfig, err := createAPIExtensionsConfig(*kubeAPIServerConfig.GenericConfig, versionedInformers, pluginInitializer, completedOptions.ServerRunOptions, completedOptions.MasterCount) if err != nil { return nil, err } - apiExtensionsServer, err := createAPIExtensionsServer(apiExtensionsConfig, genericapiserver.EmptyDelegate) + apiExtensionsServer, err := createAPIExtensionsServer(apiExtensionsConfig, genericapiserver.NewEmptyDelegate()) if err != nil { return nil, err } - kubeAPIServer, err := CreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer, sharedInformers, versionedInformers) + kubeAPIServer, err := CreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer, sharedInformers, versionedInformers, admissionPostStartHook) if err != nil { return nil, err } - // if we're starting up a hacked up version of this API server for a weird test case, - // just start the API server as is because clients don't get built correctly when you do this - if len(os.Getenv("KUBE_API_VERSIONS")) > 0 { - if insecureServingOptions != nil { - insecureHandlerChain := kubeserver.BuildInsecureHandlerChain(kubeAPIServer.GenericAPIServer.UnprotectedHandler(), kubeAPIServerConfig.GenericConfig) - if err := kubeserver.NonBlockingRun(insecureServingOptions, insecureHandlerChain, kubeAPIServerConfig.GenericConfig.RequestTimeout, stopCh); err != nil { - return nil, err - } - } - - return kubeAPIServer.GenericAPIServer, nil - } - // otherwise go down the normal path of standing the aggregator up in front of the API server // this wires up openapi kubeAPIServer.GenericAPIServer.PrepareRun() @@ -191,12 +187,10 @@ func CreateServerChain(runOptions *options.ServerRunOptions, stopCh <-chan struc apiExtensionsServer.GenericAPIServer.PrepareRun() // aggregator comes last in the chain - aggregatorConfig, err := createAggregatorConfig(*kubeAPIServerConfig.GenericConfig, runOptions, versionedInformers, serviceResolver, proxyTransport, pluginInitializer) + aggregatorConfig, err := createAggregatorConfig(*kubeAPIServerConfig.GenericConfig, completedOptions.ServerRunOptions, versionedInformers, serviceResolver, proxyTransport, pluginInitializer) if err != nil { return nil, err } - aggregatorConfig.ExtraConfig.ProxyTransport = proxyTransport - aggregatorConfig.ExtraConfig.ServiceResolver = serviceResolver aggregatorServer, err := createAggregatorServer(aggregatorConfig, kubeAPIServer.GenericAPIServer, apiExtensionsServer.Informers) if err != nil { // we don't need special handling for innerStopCh because the aggregator server doesn't create any go routines @@ -214,21 +208,23 @@ func CreateServerChain(runOptions *options.ServerRunOptions, stopCh <-chan struc } // CreateKubeAPIServer creates and wires a workable kube-apiserver -func CreateKubeAPIServer(kubeAPIServerConfig *master.Config, delegateAPIServer genericapiserver.DelegationTarget, sharedInformers informers.SharedInformerFactory, versionedInformers clientgoinformers.SharedInformerFactory) (*master.Master, error) { +func CreateKubeAPIServer(kubeAPIServerConfig *master.Config, delegateAPIServer genericapiserver.DelegationTarget, sharedInformers informers.SharedInformerFactory, versionedInformers clientgoinformers.SharedInformerFactory, admissionPostStartHook genericapiserver.PostStartHookFunc) (*master.Master, error) { kubeAPIServer, err := kubeAPIServerConfig.Complete(versionedInformers).New(delegateAPIServer) if err != nil { return nil, err } - kubeAPIServer.GenericAPIServer.AddPostStartHook("start-kube-apiserver-informers", func(context genericapiserver.PostStartHookContext) error { + + kubeAPIServer.GenericAPIServer.AddPostStartHookOrDie("start-kube-apiserver-informers", func(context genericapiserver.PostStartHookContext) error { sharedInformers.Start(context.StopCh) return nil }) + kubeAPIServer.GenericAPIServer.AddPostStartHookOrDie("start-kube-apiserver-admission-initializer", admissionPostStartHook) return kubeAPIServer, nil } // CreateNodeDialer creates the dialer infrastructure to connect to the nodes. -func CreateNodeDialer(s *options.ServerRunOptions) (tunneler.Tunneler, *http.Transport, error) { +func CreateNodeDialer(s completedServerRunOptions) (tunneler.Tunneler, *http.Transport, error) { // Setup nodeTunneler if needed var nodeTunneler tunneler.Tunneler var proxyDialerFn utilnet.DialFunc @@ -266,7 +262,7 @@ func CreateNodeDialer(s *options.ServerRunOptions) (tunneler.Tunneler, *http.Tra // Proxying to pods and services is IP-based... don't expect to be able to verify the hostname proxyTLSClientConfig := &tls.Config{InsecureSkipVerify: true} proxyTransport := utilnet.SetTransportDefaults(&http.Transport{ - Dial: proxyDialerFn, + DialContext: proxyDialerFn, TLSClientConfig: proxyTLSClientConfig, }) return nodeTunneler, proxyTransport, nil @@ -274,7 +270,7 @@ func CreateNodeDialer(s *options.ServerRunOptions) (tunneler.Tunneler, *http.Tra // CreateKubeAPIServerConfig creates all the resources for running the API server, but runs none of them func CreateKubeAPIServerConfig( - s *options.ServerRunOptions, + s completedServerRunOptions, nodeTunneler tunneler.Tunneler, proxyTransport *http.Transport, ) ( @@ -284,21 +280,11 @@ func CreateKubeAPIServerConfig( insecureServingInfo *kubeserver.InsecureServingInfo, serviceResolver aggregatorapiserver.ServiceResolver, pluginInitializers []admission.PluginInitializer, + admissionPostStartHook genericapiserver.PostStartHookFunc, lastErr error, ) { - // set defaults in the options before trying to create the generic config - if lastErr = defaultOptions(s); lastErr != nil { - return - } - - // validate options - if errs := s.Validate(); len(errs) != 0 { - lastErr = utilerrors.NewAggregate(errs) - return - } - var genericConfig *genericapiserver.Config - genericConfig, sharedInformers, versionedInformers, insecureServingInfo, serviceResolver, pluginInitializers, lastErr = BuildGenericConfig(s, proxyTransport) + genericConfig, sharedInformers, versionedInformers, insecureServingInfo, serviceResolver, pluginInitializers, admissionPostStartHook, lastErr = BuildGenericConfig(s.ServerRunOptions, proxyTransport) if lastErr != nil { return } @@ -326,7 +312,7 @@ func CreateKubeAPIServerConfig( return } - storageFactory, lastErr := BuildStorageFactory(s, genericConfig.MergedResourceConfig) + storageFactory, lastErr := BuildStorageFactory(s.ServerRunOptions, genericConfig.MergedResourceConfig) if lastErr != nil { return } @@ -346,7 +332,7 @@ func CreateKubeAPIServerConfig( s.Authentication.ServiceAccounts.Issuer != "" || len(s.Authentication.ServiceAccounts.APIAudiences) > 0 { if !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) { - lastErr = fmt.Errorf("the TokenRequest feature is not enabled but --service-account-signing-key-file and/or --service-account-issuer-id flags were passed") + lastErr = fmt.Errorf("the TokenRequest feature is not enabled but --service-account-signing-key-file, --service-account-issuer and/or --service-account-api-audiences flags were passed") return } if s.ServiceAccountSigningKeyFile == "" || @@ -379,7 +365,6 @@ func CreateKubeAPIServerConfig( APIResourceConfigSource: storageFactory.APIResourceConfigSource, StorageFactory: storageFactory, - EnableCoreControllers: true, EventTTL: s.EventTTL, KubeletClientConfig: s.KubeletConfig, EnableLogsSupport: s.EnableLogsHandler, @@ -421,6 +406,7 @@ func BuildGenericConfig( insecureServingInfo *kubeserver.InsecureServingInfo, serviceResolver aggregatorapiserver.ServiceResolver, pluginInitializers []admission.PluginInitializer, + admissionPostStartHook genericapiserver.PostStartHookFunc, lastErr error, ) { genericConfig = genericapiserver.NewConfig(legacyscheme.Codecs) @@ -443,15 +429,14 @@ func BuildGenericConfig( if lastErr = s.Features.ApplyTo(genericConfig); lastErr != nil { return } - if lastErr = s.APIEnablement.ApplyTo(genericConfig, master.DefaultAPIResourceConfigSource(), legacyscheme.Registry); lastErr != nil { + if lastErr = s.APIEnablement.ApplyTo(genericConfig, master.DefaultAPIResourceConfigSource(), legacyscheme.Scheme); lastErr != nil { return } - genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(generatedopenapi.GetOpenAPIDefinitions, legacyscheme.Scheme) + genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(generatedopenapi.GetOpenAPIDefinitions, openapinamer.NewDefinitionNamer(legacyscheme.Scheme, extensionsapiserver.Scheme, aggregatorscheme.Scheme)) genericConfig.OpenAPIConfig.PostProcessSpec = postProcessOpenAPISpecForBackwardCompatibility genericConfig.OpenAPIConfig.Info.Title = "Kubernetes" genericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig() - genericConfig.EnableMetrics = true genericConfig.LongRunningFunc = filters.BasicLongRunningRequestCheck( sets.NewString("watch", "proxy"), sets.NewString("attach", "exec", "proxy", "log", "portforward"), @@ -476,17 +461,8 @@ func BuildGenericConfig( client, err := internalclientset.NewForConfig(genericConfig.LoopbackClientConfig) if err != nil { - kubeAPIVersions := os.Getenv("KUBE_API_VERSIONS") - if len(kubeAPIVersions) == 0 { - lastErr = fmt.Errorf("failed to create clientset: %v", err) - return - } - - // KUBE_API_VERSIONS is used in test-update-storage-objects.sh, disabling a number of API - // groups. This leads to a nil client above and undefined behaviour further down. - // - // TODO: get rid of KUBE_API_VERSIONS or define sane behaviour if set - glog.Errorf("Failed to create clientset with KUBE_API_VERSIONS=%q. KUBE_API_VERSIONS is only for testing. Things will break.", kubeAPIVersions) + lastErr = fmt.Errorf("failed to create clientset: %v", err) + return } kubeClientConfig := genericConfig.LoopbackClientConfig @@ -516,7 +492,7 @@ func BuildGenericConfig( } serviceResolver = aggregatorapiserver.NewLoopbackServiceResolver(serviceResolver, localHost) - genericConfig.Authentication.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, storageFactory, client, clientgoExternalClient, sharedInformers) + genericConfig.Authentication.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, clientgoExternalClient, sharedInformers) if err != nil { lastErr = fmt.Errorf("invalid authentication config: %v", err) return @@ -527,7 +503,7 @@ func BuildGenericConfig( lastErr = fmt.Errorf("invalid authorization config: %v", err) return } - if !sets.NewString(s.Authorization.Modes()...).Has(modes.ModeRBAC) { + if !sets.NewString(s.Authorization.Modes...).Has(modes.ModeRBAC) { genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName) } @@ -547,14 +523,14 @@ func BuildGenericConfig( if err != nil { return nil, err } - if proxyTransport != nil && proxyTransport.Dial != nil { - ret.Dial = proxyTransport.Dial + if proxyTransport != nil && proxyTransport.DialContext != nil { + ret.Dial = proxyTransport.DialContext } return ret, err }, } } - pluginInitializers, err = BuildAdmissionPluginInitializers( + pluginInitializers, admissionPostStartHook, err = BuildAdmissionPluginInitializers( s, client, sharedInformers, @@ -586,7 +562,7 @@ func BuildAdmissionPluginInitializers( sharedInformers informers.SharedInformerFactory, serviceResolver aggregatorapiserver.ServiceResolver, webhookAuthWrapper webhookconfig.AuthenticationInfoResolverWrapper, -) ([]admission.PluginInitializer, error) { +) ([]admission.PluginInitializer, genericapiserver.PostStartHookFunc, error) { var cloudConfig []byte if s.CloudProvider.CloudConfigFile != "" { @@ -597,31 +573,35 @@ func BuildAdmissionPluginInitializers( } } - // TODO: use a dynamic restmapper. See https://github.com/kubernetes/kubernetes/pull/42615. - restMapper := legacyscheme.Registry.RESTMapper() + // We have a functional client so we can use that to build our discovery backed REST mapper + // Use a discovery client capable of being refreshed. + discoveryClient := cacheddiscovery.NewMemCacheClient(client.Discovery()) + discoveryRESTMapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) + + admissionPostStartHook := func(context genericapiserver.PostStartHookContext) error { + discoveryRESTMapper.Reset() + go utilwait.Until(discoveryRESTMapper.Reset, 30*time.Second, context.StopCh) + return nil + } quotaConfiguration := quotainstall.NewQuotaConfigurationForAdmission() - kubePluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, restMapper, quotaConfiguration) + kubePluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, discoveryRESTMapper, quotaConfiguration) webhookPluginInitializer := webhookinit.NewPluginInitializer(webhookAuthWrapper, serviceResolver) - return []admission.PluginInitializer{webhookPluginInitializer, kubePluginInitializer}, nil + return []admission.PluginInitializer{webhookPluginInitializer, kubePluginInitializer}, admissionPostStartHook, nil } // BuildAuthenticator constructs the authenticator -func BuildAuthenticator(s *options.ServerRunOptions, storageFactory serverstorage.StorageFactory, client internalclientset.Interface, extclient clientgoclientset.Interface, sharedInformers informers.SharedInformerFactory) (authenticator.Request, *spec.SecurityDefinitions, error) { +func BuildAuthenticator(s *options.ServerRunOptions, extclient clientgoclientset.Interface, sharedInformers informers.SharedInformerFactory) (authenticator.Request, *spec.SecurityDefinitions, error) { authenticatorConfig := s.Authentication.ToAuthenticationConfig() if s.Authentication.ServiceAccounts.Lookup { authenticatorConfig.ServiceAccountTokenGetter = serviceaccountcontroller.NewGetterFromClient(extclient) } - if client == nil || reflect.ValueOf(client).IsNil() { - // TODO: Remove check once client can never be nil. - glog.Errorf("Failed to setup bootstrap token authenticator because the loopback clientset was not setup properly.") - } else { - authenticatorConfig.BootstrapTokenAuthenticator = bootstrap.NewTokenAuthenticator( - sharedInformers.Core().InternalVersion().Secrets().Lister().Secrets(v1.NamespaceSystem), - ) - } + authenticatorConfig.BootstrapTokenAuthenticator = bootstrap.NewTokenAuthenticator( + sharedInformers.Core().InternalVersion().Secrets().Lister().Secrets(v1.NamespaceSystem), + ) + return authenticatorConfig.New() } @@ -640,7 +620,7 @@ func BuildStorageFactory(s *options.ServerRunOptions, apiResourceConfig *servers } storageFactory, err := kubeapiserver.NewStorageFactory( s.Etcd.StorageConfig, s.Etcd.DefaultStorageMediaType, legacyscheme.Codecs, - serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Registry), storageGroupsToEncodingVersion, + serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Scheme), storageGroupsToEncodingVersion, // The list includes resources that need to be stored in a different // group version than other resources in the groups. // FIXME (soltysh): this GroupVersionResource override should be configurable @@ -659,20 +639,11 @@ func BuildStorageFactory(s *options.ServerRunOptions, apiResourceConfig *servers storageFactory.AddCohabitatingResources(apps.Resource("daemonsets"), extensions.Resource("daemonsets")) storageFactory.AddCohabitatingResources(apps.Resource("replicasets"), extensions.Resource("replicasets")) storageFactory.AddCohabitatingResources(api.Resource("events"), events.Resource("events")) - // TODO(#54933): 1.11: switch to using policy storage and flip the order here - storageFactory.AddCohabitatingResources(extensions.Resource("podsecuritypolicies"), policy.Resource("podsecuritypolicies")) + storageFactory.AddCohabitatingResources(policy.Resource("podsecuritypolicies"), extensions.Resource("podsecuritypolicies")) for _, override := range s.Etcd.EtcdServersOverrides { tokens := strings.Split(override, "#") - if len(tokens) != 2 { - glog.Errorf("invalid value of etcd server overrides: %s", override) - continue - } - apiresource := strings.Split(tokens[0], "/") - if len(apiresource) != 2 { - glog.Errorf("invalid resource definition: %s", tokens[0]) - continue - } + group := apiresource[0] resource := apiresource[1] groupResource := schema.GroupResource{Group: group, Resource: resource} @@ -694,21 +665,29 @@ func BuildStorageFactory(s *options.ServerRunOptions, apiResourceConfig *servers return storageFactory, nil } -func defaultOptions(s *options.ServerRunOptions) error { +// completedServerRunOptions is a private wrapper that enforces a call of Complete() before Run can be invoked. +type completedServerRunOptions struct { + *options.ServerRunOptions +} + +// Complete set default ServerRunOptions. +// Should be called after kube-apiserver flags parsed. +func Complete(s *options.ServerRunOptions) (completedServerRunOptions, error) { + var options completedServerRunOptions // set defaults if err := s.GenericServerRunOptions.DefaultAdvertiseAddress(s.SecureServing.SecureServingOptions); err != nil { - return err + return options, err } if err := kubeoptions.DefaultAdvertiseAddress(s.GenericServerRunOptions, s.InsecureServing); err != nil { - return err + return options, err } serviceIPRange, apiServerServiceIP, err := master.DefaultServiceIPRange(s.ServiceClusterIPRange) if err != nil { - return fmt.Errorf("error determining service IP ranges: %v", err) + return options, fmt.Errorf("error determining service IP ranges: %v", err) } s.ServiceClusterIPRange = serviceIPRange if err := s.SecureServing.MaybeDefaultWithSelfSignedCerts(s.GenericServerRunOptions.AdvertiseAddress.String(), []string{"kubernetes.default.svc", "kubernetes.default", "kubernetes"}, []net.IP{apiServerServiceIP}); err != nil { - return fmt.Errorf("error creating self-signed certificates: %v", err) + return options, fmt.Errorf("error creating self-signed certificates: %v", err) } if len(s.GenericServerRunOptions.ExternalHost) == 0 { @@ -718,7 +697,7 @@ func defaultOptions(s *options.ServerRunOptions) error { if hostname, err := os.Hostname(); err == nil { s.GenericServerRunOptions.ExternalHost = hostname } else { - return fmt.Errorf("error finding host name: %v", err) + return options, fmt.Errorf("error finding host name: %v", err) } } glog.Infof("external host was not specified, using %v", s.GenericServerRunOptions.ExternalHost) @@ -773,7 +752,7 @@ func defaultOptions(s *options.ServerRunOptions) error { } s.Etcd.WatchCacheSizes, err = serveroptions.WriteWatchCacheSizes(sizes) if err != nil { - return err + return options, err } } @@ -790,8 +769,8 @@ func defaultOptions(s *options.ServerRunOptions) error { } } } - - return nil + options.ServerRunOptions = s + return options, nil } func readCAorNil(file string) ([]byte, error) { diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testserver.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testserver.go index 2d56fbd5d..d5c1e6429 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testserver.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testserver.go @@ -37,6 +37,12 @@ import ( // TearDownFunc is to be called to tear down a test server. type TearDownFunc func() +// TestServerInstanceOptions Instance options the TestServer +type TestServerInstanceOptions struct { + // DisableStorageCleanup Disable the automatic storage cleanup + DisableStorageCleanup bool +} + // TestServer return values supplied by kube-test-ApiServer type TestServer struct { ClientConfig *restclient.Config // Rest client config @@ -52,22 +58,36 @@ type Logger interface { Logf(format string, args ...interface{}) } +// NewDefaultTestServerOptions Default options for TestServer instances +func NewDefaultTestServerOptions() *TestServerInstanceOptions { + return &TestServerInstanceOptions{ + DisableStorageCleanup: false, + } +} + // StartTestServer starts a etcd server and kube-apiserver. A rest client config and a tear-down func, // and location of the tmpdir are returned. // // Note: we return a tear-down func instead of a stop channel because the later will leak temporary // files that because Golang testing's call to os.Exit will not give a stop channel go routine // enough time to remove temporary files. -func StartTestServer(t Logger, customFlags []string, storageConfig *storagebackend.Config) (result TestServer, err error) { +func StartTestServer(t Logger, instanceOptions *TestServerInstanceOptions, customFlags []string, storageConfig *storagebackend.Config) (result TestServer, err error) { + if instanceOptions == nil { + instanceOptions = NewDefaultTestServerOptions() + } // TODO : Remove TrackStorageCleanup below when PR // https://github.com/kubernetes/kubernetes/pull/50690 // merges as that shuts down storage properly - registry.TrackStorageCleanup() + if !instanceOptions.DisableStorageCleanup { + registry.TrackStorageCleanup() + } stopCh := make(chan struct{}) tearDown := func() { - registry.CleanupStorage() + if !instanceOptions.DisableStorageCleanup { + registry.CleanupStorage() + } close(stopCh) if len(result.TmpDir) != 0 { os.RemoveAll(result.TmpDir) @@ -102,9 +122,14 @@ func StartTestServer(t Logger, customFlags []string, storageConfig *storagebacke s.APIEnablement.RuntimeConfig.Set("api/all=true") fs.Parse(customFlags) + completedOptions, err := app.Complete(s) + if err != nil { + return result, fmt.Errorf("failed to set default ServerRunOptions: %v", err) + } + t.Logf("runtime-config=%v", completedOptions.APIEnablement.RuntimeConfig) t.Logf("Starting kube-apiserver on port %d...", s.SecureServing.BindPort) - server, err := app.CreateServerChain(s, stopCh) + server, err := app.CreateServerChain(completedOptions, stopCh) if err != nil { return result, fmt.Errorf("failed to create server chain: %v", err) @@ -143,9 +168,8 @@ func StartTestServer(t Logger, customFlags []string, storageConfig *storagebacke } // StartTestServerOrDie calls StartTestServer t.Fatal if it does not succeed. -func StartTestServerOrDie(t Logger, flags []string, storageConfig *storagebackend.Config) *TestServer { - - result, err := StartTestServer(t, flags, storageConfig) +func StartTestServerOrDie(t Logger, instanceOptions *TestServerInstanceOptions, flags []string, storageConfig *storagebackend.Config) *TestServer { + result, err := StartTestServer(t, instanceOptions, flags, storageConfig) if err == nil { return &result } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/BUILD index a3f98b1a9..64c82a719 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/BUILD @@ -11,7 +11,6 @@ go_library( "cloudproviders.go", "controllermanager.go", "core.go", - "extensions.go", "import_known_versions.go", "plugins.go", "policy.go", @@ -24,7 +23,6 @@ go_library( "//cmd/controller-manager/app/options:go_default_library", "//cmd/kube-controller-manager/app/config:go_default_library", "//cmd/kube-controller-manager/app/options:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/apps/install:go_default_library", "//pkg/apis/authentication/install:go_default_library", "//pkg/apis/authorization/install:go_default_library", @@ -110,19 +108,18 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_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/discovery:go_default_library", "//vendor/k8s.io/client-go/discovery/cached:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", "//vendor/k8s.io/client-go/scale:go_default_library", "//vendor/k8s.io/client-go/tools/leaderelection:go_default_library", "//vendor/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/apps.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/apps.go index 57898b5fc..7525f174b 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/apps.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/apps.go @@ -25,6 +25,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubernetes/pkg/controller/daemon" + "k8s.io/kubernetes/pkg/controller/deployment" + "k8s.io/kubernetes/pkg/controller/replicaset" "k8s.io/kubernetes/pkg/controller/statefulset" ) @@ -42,12 +44,12 @@ func startDaemonSetController(ctx ControllerContext) (bool, error) { if err != nil { return true, fmt.Errorf("error creating DaemonSets controller: %v", err) } - go dsc.Run(int(ctx.ComponentConfig.ConcurrentDaemonSetSyncs), ctx.Stop) + go dsc.Run(int(ctx.ComponentConfig.DaemonSetController.ConcurrentDaemonSetSyncs), ctx.Stop) return true, nil } func startStatefulSetController(ctx ControllerContext) (bool, error) { - if !ctx.AvailableResources[schema.GroupVersionResource{Group: "apps", Version: "v1beta1", Resource: "statefulsets"}] { + if !ctx.AvailableResources[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "statefulsets"}] { return false, nil } go statefulset.NewStatefulSetController( @@ -59,3 +61,33 @@ func startStatefulSetController(ctx ControllerContext) (bool, error) { ).Run(1, ctx.Stop) return true, nil } + +func startReplicaSetController(ctx ControllerContext) (bool, error) { + if !ctx.AvailableResources[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "replicasets"}] { + return false, nil + } + go replicaset.NewReplicaSetController( + ctx.InformerFactory.Apps().V1().ReplicaSets(), + ctx.InformerFactory.Core().V1().Pods(), + ctx.ClientBuilder.ClientOrDie("replicaset-controller"), + replicaset.BurstReplicas, + ).Run(int(ctx.ComponentConfig.ReplicaSetController.ConcurrentRSSyncs), ctx.Stop) + return true, nil +} + +func startDeploymentController(ctx ControllerContext) (bool, error) { + if !ctx.AvailableResources[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}] { + return false, nil + } + dc, err := deployment.NewDeploymentController( + ctx.InformerFactory.Apps().V1().Deployments(), + ctx.InformerFactory.Apps().V1().ReplicaSets(), + ctx.InformerFactory.Core().V1().Pods(), + ctx.ClientBuilder.ClientOrDie("deployment-controller"), + ) + if err != nil { + return true, fmt.Errorf("error creating Deployment controller: %v", err) + } + go dc.Run(int(ctx.ComponentConfig.DeploymentController.ConcurrentDeploymentSyncs), ctx.Stop) + return true, nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/autoscaling.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/autoscaling.go index e83ef0545..6971890ed 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/autoscaling.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/autoscaling.go @@ -21,10 +21,7 @@ limitations under the License. package app import ( - apimeta "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/discovery" - discocache "k8s.io/client-go/discovery/cached" "k8s.io/client-go/dynamic" "k8s.io/client-go/scale" "k8s.io/kubernetes/pkg/controller/podautoscaler" @@ -39,7 +36,7 @@ func startHPAController(ctx ControllerContext) (bool, error) { return false, nil } - if ctx.ComponentConfig.HorizontalPodAutoscalerUseRESTClients { + if ctx.ComponentConfig.HPAController.HorizontalPodAutoscalerUseRESTClients { // use the new-style clients if support for custom metrics is enabled return startHPAControllerWithRESTClient(ctx) } @@ -74,15 +71,10 @@ func startHPAControllerWithMetricsClient(ctx ControllerContext, metricsClient me hpaClient := ctx.ClientBuilder.ClientOrDie("horizontal-pod-autoscaler") hpaClientConfig := ctx.ClientBuilder.ConfigOrDie("horizontal-pod-autoscaler") - // TODO: we need something like deferred discovery REST mapper that calls invalidate - // on cache misses. - cachedDiscovery := discocache.NewMemCacheClient(hpaClientGoClient.Discovery()) - restMapper := discovery.NewDeferredDiscoveryRESTMapper(cachedDiscovery, apimeta.InterfacesForUnstructured) - restMapper.Reset() // we don't use cached discovery because DiscoveryScaleKindResolver does its own caching, // so we want to re-fetch every time when we actually ask for it scaleKindResolver := scale.NewDiscoveryScaleKindResolver(hpaClientGoClient.Discovery()) - scaleClient, err := scale.NewForConfig(hpaClientConfig, restMapper, dynamic.LegacyAPIPathResolverFunc, scaleKindResolver) + scaleClient, err := scale.NewForConfig(hpaClientConfig, ctx.RESTMapper, dynamic.LegacyAPIPathResolverFunc, scaleKindResolver) if err != nil { return false, err } @@ -90,18 +82,18 @@ func startHPAControllerWithMetricsClient(ctx ControllerContext, metricsClient me replicaCalc := podautoscaler.NewReplicaCalculator( metricsClient, hpaClient.CoreV1(), - ctx.ComponentConfig.HorizontalPodAutoscalerTolerance, + ctx.ComponentConfig.HPAController.HorizontalPodAutoscalerTolerance, ) go podautoscaler.NewHorizontalController( hpaClientGoClient.CoreV1(), scaleClient, hpaClient.AutoscalingV1(), - restMapper, + ctx.RESTMapper, replicaCalc, ctx.InformerFactory.Autoscaling().V1().HorizontalPodAutoscalers(), - ctx.ComponentConfig.HorizontalPodAutoscalerSyncPeriod.Duration, - ctx.ComponentConfig.HorizontalPodAutoscalerUpscaleForbiddenWindow.Duration, - ctx.ComponentConfig.HorizontalPodAutoscalerDownscaleForbiddenWindow.Duration, + ctx.ComponentConfig.HPAController.HorizontalPodAutoscalerSyncPeriod.Duration, + ctx.ComponentConfig.HPAController.HorizontalPodAutoscalerUpscaleForbiddenWindow.Duration, + ctx.ComponentConfig.HPAController.HorizontalPodAutoscalerDownscaleForbiddenWindow.Duration, ).Run(ctx.Stop) return true, nil } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/batch.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/batch.go index 31340eadf..24cf6e0fa 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/batch.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/batch.go @@ -36,7 +36,7 @@ func startJobController(ctx ControllerContext) (bool, error) { ctx.InformerFactory.Core().V1().Pods(), ctx.InformerFactory.Batch().V1().Jobs(), ctx.ClientBuilder.ClientOrDie("job-controller"), - ).Run(int(ctx.ComponentConfig.ConcurrentJobSyncs), ctx.Stop) + ).Run(int(ctx.ComponentConfig.JobController.ConcurrentJobSyncs), ctx.Stop) return true, nil } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/certificates.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/certificates.go index 98e2f2ce4..9e6e70cf3 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/certificates.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/certificates.go @@ -37,7 +37,7 @@ func startCSRSigningController(ctx ControllerContext) (bool, error) { if !ctx.AvailableResources[schema.GroupVersionResource{Group: "certificates.k8s.io", Version: "v1beta1", Resource: "certificatesigningrequests"}] { return false, nil } - if ctx.ComponentConfig.ClusterSigningCertFile == "" || ctx.ComponentConfig.ClusterSigningKeyFile == "" { + if ctx.ComponentConfig.CSRSigningController.ClusterSigningCertFile == "" || ctx.ComponentConfig.CSRSigningController.ClusterSigningKeyFile == "" { return false, nil } @@ -52,15 +52,15 @@ func startCSRSigningController(ctx ControllerContext) (bool, error) { // bail out of startController without logging. var keyFileExists, keyUsesDefault, certFileExists, certUsesDefault bool - _, err := os.Stat(ctx.ComponentConfig.ClusterSigningCertFile) + _, err := os.Stat(ctx.ComponentConfig.CSRSigningController.ClusterSigningCertFile) certFileExists = !os.IsNotExist(err) - certUsesDefault = (ctx.ComponentConfig.ClusterSigningCertFile == cmoptions.DefaultClusterSigningCertFile) + certUsesDefault = (ctx.ComponentConfig.CSRSigningController.ClusterSigningCertFile == cmoptions.DefaultClusterSigningCertFile) - _, err = os.Stat(ctx.ComponentConfig.ClusterSigningKeyFile) + _, err = os.Stat(ctx.ComponentConfig.CSRSigningController.ClusterSigningKeyFile) keyFileExists = !os.IsNotExist(err) - keyUsesDefault = (ctx.ComponentConfig.ClusterSigningKeyFile == cmoptions.DefaultClusterSigningKeyFile) + keyUsesDefault = (ctx.ComponentConfig.CSRSigningController.ClusterSigningKeyFile == cmoptions.DefaultClusterSigningKeyFile) switch { case (keyFileExists && keyUsesDefault) || (certFileExists && certUsesDefault): @@ -84,9 +84,9 @@ func startCSRSigningController(ctx ControllerContext) (bool, error) { signer, err := signer.NewCSRSigningController( c, ctx.InformerFactory.Certificates().V1beta1().CertificateSigningRequests(), - ctx.ComponentConfig.ClusterSigningCertFile, - ctx.ComponentConfig.ClusterSigningKeyFile, - ctx.ComponentConfig.ClusterSigningDuration.Duration, + ctx.ComponentConfig.CSRSigningController.ClusterSigningCertFile, + ctx.ComponentConfig.CSRSigningController.ClusterSigningKeyFile, + ctx.ComponentConfig.CSRSigningController.ClusterSigningDuration.Duration, ) if err != nil { return false, fmt.Errorf("failed to start certificate controller: %v", err) diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/config/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/config/BUILD index a9c61b0ab..73a13e94f 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/config/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/config/BUILD @@ -5,7 +5,14 @@ go_library( srcs = ["config.go"], importpath = "k8s.io/kubernetes/cmd/kube-controller-manager/app/config", visibility = ["//visibility:public"], - deps = ["//cmd/controller-manager/app:go_default_library"], + deps = [ + "//cmd/controller-manager/app:go_default_library", + "//pkg/apis/componentconfig:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", + ], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/config/config.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/config/config.go index 4eb9c3ff8..4713e9dfe 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/config/config.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/config/config.go @@ -17,25 +17,39 @@ limitations under the License. package config import ( - "time" - + apiserver "k8s.io/apiserver/pkg/server" + clientset "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/tools/record" genericcontrollermanager "k8s.io/kubernetes/cmd/controller-manager/app" + "k8s.io/kubernetes/pkg/apis/componentconfig" ) -// ExtraConfig are part of Config, also can place your custom config here. -type ExtraConfig struct { - NodeStatusUpdateFrequency time.Duration -} - // Config is the main context object for the controller manager. type Config struct { - Generic genericcontrollermanager.Config - Extra ExtraConfig + ComponentConfig componentconfig.KubeControllerManagerConfiguration + + SecureServing *apiserver.SecureServingInfo + // TODO: remove deprecated insecure serving + InsecureServing *genericcontrollermanager.InsecureServingInfo + Authentication apiserver.AuthenticationInfo + Authorization apiserver.AuthorizationInfo + + // the general kube client + Client *clientset.Clientset + + // the client only used for leader election + LeaderElectionClient *clientset.Clientset + + // the rest config for the master + Kubeconfig *restclient.Config + + // the event sink + EventRecorder record.EventRecorder } type completedConfig struct { - Generic genericcontrollermanager.CompletedConfig - Extra *ExtraConfig + *Config } // CompletedConfig same as Config, just to swap private object. @@ -46,10 +60,6 @@ type CompletedConfig struct { // Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. func (c *Config) Complete() *CompletedConfig { - cc := completedConfig{ - c.Generic.Complete(), - &c.Extra, - } - + cc := completedConfig{c} return &CompletedConfig{&cc} } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go index f6d0704dc..a235e8a11 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go @@ -35,12 +35,14 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" + cacheddiscovery "k8s.io/client-go/discovery/cached" "k8s.io/client-go/informers" restclient "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" "k8s.io/client-go/tools/leaderelection" "k8s.io/client-go/tools/leaderelection/resourcelock" certutil "k8s.io/client-go/util/cert" - genericcontrollerconfig "k8s.io/kubernetes/cmd/controller-manager/app" + genericcontrollermanager "k8s.io/kubernetes/cmd/controller-manager/app" "k8s.io/kubernetes/cmd/kube-controller-manager/app/config" "k8s.io/kubernetes/cmd/kube-controller-manager/app/options" "k8s.io/kubernetes/pkg/apis/componentconfig" @@ -68,7 +70,11 @@ const ( // NewControllerManagerCommand creates a *cobra.Command object with default parameters func NewControllerManagerCommand() *cobra.Command { - s := options.NewKubeControllerManagerOptions() + s, err := options.NewKubeControllerManagerOptions() + if err != nil { + glog.Fatalf("unable to initialize command options: %v", err) + } + cmd := &cobra.Command{ Use: "kube-controller-manager", Long: `The Kubernetes controller manager is a daemon that embeds @@ -106,7 +112,7 @@ controller, and serviceaccounts controller.`, func ResyncPeriod(c *config.CompletedConfig) func() time.Duration { return func() time.Duration { factor := rand.Float64() + 1 - return time.Duration(float64(c.Generic.ComponentConfig.MinResyncPeriod.Nanoseconds()) * factor) + return time.Duration(float64(c.ComponentConfig.GenericComponent.MinResyncPeriod.Nanoseconds()) * factor) } } @@ -116,39 +122,43 @@ func Run(c *config.CompletedConfig) error { glog.Infof("Version: %+v", version.Get()) if cfgz, err := configz.New("componentconfig"); err == nil { - cfgz.Set(c.Generic.ComponentConfig) + cfgz.Set(c.ComponentConfig) } else { glog.Errorf("unable to register configz: %c", err) } // Start the controller manager HTTP server stopCh := make(chan struct{}) - if c.Generic.SecureServing != nil { - if err := genericcontrollerconfig.Serve(&c.Generic, c.Generic.SecureServing.Serve, stopCh); err != nil { + if c.SecureServing != nil { + handler := genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Debugging) + handler = genericcontrollermanager.BuildHandlerChain(handler, &c.Authorization, &c.Authentication) + if err := c.SecureServing.Serve(handler, 0, stopCh); err != nil { return err } } - if c.Generic.InsecureServing != nil { - if err := genericcontrollerconfig.Serve(&c.Generic, c.Generic.InsecureServing.Serve, stopCh); err != nil { + if c.InsecureServing != nil { + handler := genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Debugging) + handler = genericcontrollermanager.BuildHandlerChain(handler, &c.Authorization, &c.Authentication) + if err := c.InsecureServing.Serve(handler, 0, stopCh); err != nil { return err } } run := func(stop <-chan struct{}) { rootClientBuilder := controller.SimpleControllerClientBuilder{ - ClientConfig: c.Generic.Kubeconfig, + ClientConfig: c.Kubeconfig, } var clientBuilder controller.ControllerClientBuilder - if c.Generic.ComponentConfig.UseServiceAccountCredentials { - if len(c.Generic.ComponentConfig.ServiceAccountKeyFile) == 0 { + if c.ComponentConfig.KubeCloudShared.UseServiceAccountCredentials { + if len(c.ComponentConfig.SAController.ServiceAccountKeyFile) == 0 { // It'c possible another controller process is creating the tokens for us. // If one isn't, we'll timeout and exit when our client builder is unable to create the tokens. glog.Warningf("--use-service-account-credentials was specified without providing a --service-account-private-key-file") } clientBuilder = controller.SAControllerClientBuilder{ - ClientConfig: restclient.AnonymousClientConfig(c.Generic.Kubeconfig), - CoreClient: c.Generic.Client.CoreV1(), - AuthenticationClient: c.Generic.Client.AuthenticationV1(), + ClientConfig: restclient.AnonymousClientConfig(c.Kubeconfig), + CoreClient: c.Client.CoreV1(), + AuthenticationClient: c.Client.AuthenticationV1(), Namespace: "kube-system", } } else { @@ -170,7 +180,7 @@ func Run(c *config.CompletedConfig) error { select {} } - if !c.Generic.ComponentConfig.LeaderElection.LeaderElect { + if !c.ComponentConfig.GenericComponent.LeaderElection.LeaderElect { run(wait.NeverStop) panic("unreachable") } @@ -182,13 +192,13 @@ func Run(c *config.CompletedConfig) error { // add a uniquifier so that two processes on the same host don't accidentally both become active id = id + "_" + string(uuid.NewUUID()) - rl, err := resourcelock.New(c.Generic.ComponentConfig.LeaderElection.ResourceLock, + rl, err := resourcelock.New(c.ComponentConfig.GenericComponent.LeaderElection.ResourceLock, "kube-system", "kube-controller-manager", - c.Generic.LeaderElectionClient.CoreV1(), + c.LeaderElectionClient.CoreV1(), resourcelock.ResourceLockConfig{ Identity: id, - EventRecorder: c.Generic.EventRecorder, + EventRecorder: c.EventRecorder, }) if err != nil { glog.Fatalf("error creating lock: %v", err) @@ -196,9 +206,9 @@ func Run(c *config.CompletedConfig) error { leaderelection.RunOrDie(leaderelection.LeaderElectionConfig{ Lock: rl, - LeaseDuration: c.Generic.ComponentConfig.LeaderElection.LeaseDuration.Duration, - RenewDeadline: c.Generic.ComponentConfig.LeaderElection.RenewDeadline.Duration, - RetryPeriod: c.Generic.ComponentConfig.LeaderElection.RetryPeriod.Duration, + LeaseDuration: c.ComponentConfig.GenericComponent.LeaderElection.LeaseDuration.Duration, + RenewDeadline: c.ComponentConfig.GenericComponent.LeaderElection.RenewDeadline.Duration, + RetryPeriod: c.ComponentConfig.GenericComponent.LeaderElection.RetryPeriod.Duration, Callbacks: leaderelection.LeaderCallbacks{ OnStartedLeading: run, OnStoppedLeading: func() { @@ -216,9 +226,14 @@ type ControllerContext struct { // InformerFactory gives access to informers for the controller. InformerFactory informers.SharedInformerFactory - // Options provides access to init options for a given controller + // ComponentConfig provides access to init options for a given controller ComponentConfig componentconfig.KubeControllerManagerConfiguration + // DeferredDiscoveryRESTMapper is a RESTMapper that will defer + // initialization of the RESTMapper until the first mapping is + // requested. + RESTMapper *restmapper.DeferredDiscoveryRESTMapper + // AvailableResources is a map listing currently available resources AvailableResources map[schema.GroupVersionResource]bool @@ -381,17 +396,25 @@ func CreateControllerContext(s *config.CompletedConfig, rootClientBuilder, clien // If apiserver is not running we should wait for some time and fail only then. This is particularly // important when we start apiserver and controller manager at the same time. - if err := genericcontrollerconfig.WaitForAPIServer(versionedClient, 10*time.Second); err != nil { + if err := genericcontrollermanager.WaitForAPIServer(versionedClient, 10*time.Second); err != nil { return ControllerContext{}, fmt.Errorf("failed to wait for apiserver being healthy: %v", err) } + // Use a discovery client capable of being refreshed. + discoveryClient := rootClientBuilder.ClientOrDie("controller-discovery") + cachedClient := cacheddiscovery.NewMemCacheClient(discoveryClient.Discovery()) + restMapper := restmapper.NewDeferredDiscoveryRESTMapper(cachedClient) + go wait.Until(func() { + restMapper.Reset() + }, 30*time.Second, stop) + availableResources, err := GetAvailableResources(rootClientBuilder) if err != nil { return ControllerContext{}, err } - cloud, loopMode, err := createCloudProvider(s.Generic.ComponentConfig.CloudProvider, s.Generic.ComponentConfig.ExternalCloudVolumePlugin, - s.Generic.ComponentConfig.CloudConfigFile, s.Generic.ComponentConfig.AllowUntaggedCloud, sharedInformers) + cloud, loopMode, err := createCloudProvider(s.ComponentConfig.CloudProvider.Name, s.ComponentConfig.ExternalCloudVolumePlugin, + s.ComponentConfig.CloudProvider.CloudConfigFile, s.ComponentConfig.KubeCloudShared.AllowUntaggedCloud, sharedInformers) if err != nil { return ControllerContext{}, err } @@ -399,7 +422,8 @@ func CreateControllerContext(s *config.CompletedConfig, rootClientBuilder, clien ctx := ControllerContext{ ClientBuilder: clientBuilder, InformerFactory: sharedInformers, - ComponentConfig: s.Generic.ComponentConfig, + ComponentConfig: s.ComponentConfig, + RESTMapper: restMapper, AvailableResources: availableResources, Cloud: cloud, LoopMode: loopMode, @@ -429,7 +453,7 @@ func StartControllers(ctx ControllerContext, startSATokenController InitFunc, co continue } - time.Sleep(wait.Jitter(ctx.ComponentConfig.ControllerStartInterval.Duration, ControllerStartJitter)) + time.Sleep(wait.Jitter(ctx.ComponentConfig.GenericComponent.ControllerStartInterval.Duration, ControllerStartJitter)) glog.V(1).Infof("Starting %q", controllerName) started, err := initFn(ctx) @@ -460,23 +484,23 @@ func (c serviceAccountTokenControllerStarter) startServiceAccountTokenController return false, nil } - if len(ctx.ComponentConfig.ServiceAccountKeyFile) == 0 { + if len(ctx.ComponentConfig.SAController.ServiceAccountKeyFile) == 0 { glog.Warningf("%q is disabled because there is no private key", saTokenControllerName) return false, nil } - privateKey, err := certutil.PrivateKeyFromFile(ctx.ComponentConfig.ServiceAccountKeyFile) + privateKey, err := certutil.PrivateKeyFromFile(ctx.ComponentConfig.SAController.ServiceAccountKeyFile) if err != nil { return true, fmt.Errorf("error reading key for service account token controller: %v", err) } var rootCA []byte - if ctx.ComponentConfig.RootCAFile != "" { - rootCA, err = ioutil.ReadFile(ctx.ComponentConfig.RootCAFile) + if ctx.ComponentConfig.SAController.RootCAFile != "" { + rootCA, err = ioutil.ReadFile(ctx.ComponentConfig.SAController.RootCAFile) if err != nil { - return true, fmt.Errorf("error reading root-ca-file at %s: %v", ctx.ComponentConfig.RootCAFile, err) + return true, fmt.Errorf("error reading root-ca-file at %s: %v", ctx.ComponentConfig.SAController.RootCAFile, err) } if _, err := certutil.ParseCertsPEM(rootCA); err != nil { - return true, fmt.Errorf("error parsing root-ca-file at %s: %v", ctx.ComponentConfig.RootCAFile, err) + return true, fmt.Errorf("error parsing root-ca-file at %s: %v", ctx.ComponentConfig.SAController.RootCAFile, err) } } else { rootCA = c.rootClientBuilder.ConfigOrDie("tokens-controller").CAData @@ -494,7 +518,7 @@ func (c serviceAccountTokenControllerStarter) startServiceAccountTokenController if err != nil { return true, fmt.Errorf("error creating Tokens controller: %v", err) } - go controller.Run(int(ctx.ComponentConfig.ConcurrentSATokenSyncs), ctx.Stop) + go controller.Run(int(ctx.ComponentConfig.SAController.ConcurrentSATokenSyncs), ctx.Stop) // start the first set of informers now so that other controllers can start ctx.InformerFactory.Start(ctx.Stop) diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/core.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/core.go index 6a61b19a9..4b0b97d5b 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/core.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/core.go @@ -29,14 +29,11 @@ import ( "github.com/golang/glog" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime/schema" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/client-go/discovery" cacheddiscovery "k8s.io/client-go/discovery/cached" "k8s.io/client-go/dynamic" clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/controller" endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint" "k8s.io/kubernetes/pkg/controller/garbagecollector" @@ -68,14 +65,14 @@ func startServiceController(ctx ControllerContext) (bool, error) { ctx.ClientBuilder.ClientOrDie("service-controller"), ctx.InformerFactory.Core().V1().Services(), ctx.InformerFactory.Core().V1().Nodes(), - ctx.ComponentConfig.ClusterName, + ctx.ComponentConfig.KubeCloudShared.ClusterName, ) if err != nil { // This error shouldn't fail. It lives like this as a legacy. glog.Errorf("Failed to start service controller: %v", err) return false, nil } - go serviceController.Run(ctx.Stop, int(ctx.ComponentConfig.ConcurrentServiceSyncs)) + go serviceController.Run(ctx.Stop, int(ctx.ComponentConfig.ServiceController.ConcurrentServiceSyncs)) return true, nil } @@ -83,22 +80,22 @@ func startNodeIpamController(ctx ControllerContext) (bool, error) { var clusterCIDR *net.IPNet = nil var serviceCIDR *net.IPNet = nil - if !ctx.ComponentConfig.AllocateNodeCIDRs { + if !ctx.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs { return false, nil } var err error - if len(strings.TrimSpace(ctx.ComponentConfig.ClusterCIDR)) != 0 { - _, clusterCIDR, err = net.ParseCIDR(ctx.ComponentConfig.ClusterCIDR) + if len(strings.TrimSpace(ctx.ComponentConfig.KubeCloudShared.ClusterCIDR)) != 0 { + _, clusterCIDR, err = net.ParseCIDR(ctx.ComponentConfig.KubeCloudShared.ClusterCIDR) if err != nil { - glog.Warningf("Unsuccessful parsing of cluster CIDR %v: %v", ctx.ComponentConfig.ClusterCIDR, err) + glog.Warningf("Unsuccessful parsing of cluster CIDR %v: %v", ctx.ComponentConfig.KubeCloudShared.ClusterCIDR, err) } } - if len(strings.TrimSpace(ctx.ComponentConfig.ServiceCIDR)) != 0 { - _, serviceCIDR, err = net.ParseCIDR(ctx.ComponentConfig.ServiceCIDR) + if len(strings.TrimSpace(ctx.ComponentConfig.NodeIpamController.ServiceCIDR)) != 0 { + _, serviceCIDR, err = net.ParseCIDR(ctx.ComponentConfig.NodeIpamController.ServiceCIDR) if err != nil { - glog.Warningf("Unsuccessful parsing of service CIDR %v: %v", ctx.ComponentConfig.ServiceCIDR, err) + glog.Warningf("Unsuccessful parsing of service CIDR %v: %v", ctx.ComponentConfig.NodeIpamController.ServiceCIDR, err) } } @@ -108,8 +105,8 @@ func startNodeIpamController(ctx ControllerContext) (bool, error) { ctx.ClientBuilder.ClientOrDie("node-controller"), clusterCIDR, serviceCIDR, - int(ctx.ComponentConfig.NodeCIDRMaskSize), - ipam.CIDRAllocatorType(ctx.ComponentConfig.CIDRAllocatorType), + int(ctx.ComponentConfig.NodeIpamController.NodeCIDRMaskSize), + ipam.CIDRAllocatorType(ctx.ComponentConfig.KubeCloudShared.CIDRAllocatorType), ) if err != nil { return true, err @@ -125,15 +122,15 @@ func startNodeLifecycleController(ctx ControllerContext) (bool, error) { ctx.InformerFactory.Extensions().V1beta1().DaemonSets(), ctx.Cloud, ctx.ClientBuilder.ClientOrDie("node-controller"), - ctx.ComponentConfig.NodeMonitorPeriod.Duration, - ctx.ComponentConfig.NodeStartupGracePeriod.Duration, - ctx.ComponentConfig.NodeMonitorGracePeriod.Duration, - ctx.ComponentConfig.PodEvictionTimeout.Duration, - ctx.ComponentConfig.NodeEvictionRate, - ctx.ComponentConfig.SecondaryNodeEvictionRate, - ctx.ComponentConfig.LargeClusterSizeThreshold, - ctx.ComponentConfig.UnhealthyZoneThreshold, - ctx.ComponentConfig.EnableTaintManager, + ctx.ComponentConfig.KubeCloudShared.NodeMonitorPeriod.Duration, + ctx.ComponentConfig.NodeLifecycleController.NodeStartupGracePeriod.Duration, + ctx.ComponentConfig.NodeLifecycleController.NodeMonitorGracePeriod.Duration, + ctx.ComponentConfig.NodeLifecycleController.PodEvictionTimeout.Duration, + ctx.ComponentConfig.NodeLifecycleController.NodeEvictionRate, + ctx.ComponentConfig.NodeLifecycleController.SecondaryNodeEvictionRate, + ctx.ComponentConfig.NodeLifecycleController.LargeClusterSizeThreshold, + ctx.ComponentConfig.NodeLifecycleController.UnhealthyZoneThreshold, + ctx.ComponentConfig.NodeLifecycleController.EnableTaintManager, utilfeature.DefaultFeatureGate.Enabled(features.TaintBasedEvictions), utilfeature.DefaultFeatureGate.Enabled(features.TaintNodesByCondition), ) @@ -145,8 +142,8 @@ func startNodeLifecycleController(ctx ControllerContext) (bool, error) { } func startRouteController(ctx ControllerContext) (bool, error) { - if !ctx.ComponentConfig.AllocateNodeCIDRs || !ctx.ComponentConfig.ConfigureCloudRoutes { - glog.Infof("Will not configure cloud provider routes for allocate-node-cidrs: %v, configure-cloud-routes: %v.", ctx.ComponentConfig.AllocateNodeCIDRs, ctx.ComponentConfig.ConfigureCloudRoutes) + if !ctx.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs || !ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes { + glog.Infof("Will not configure cloud provider routes for allocate-node-cidrs: %v, configure-cloud-routes: %v.", ctx.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs, ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes) return false, nil } if ctx.Cloud == nil { @@ -158,27 +155,28 @@ func startRouteController(ctx ControllerContext) (bool, error) { glog.Warning("configure-cloud-routes is set, but cloud provider does not support routes. Will not configure cloud provider routes.") return false, nil } - _, clusterCIDR, err := net.ParseCIDR(ctx.ComponentConfig.ClusterCIDR) + _, clusterCIDR, err := net.ParseCIDR(ctx.ComponentConfig.KubeCloudShared.ClusterCIDR) if err != nil { - glog.Warningf("Unsuccessful parsing of cluster CIDR %v: %v", ctx.ComponentConfig.ClusterCIDR, err) + glog.Warningf("Unsuccessful parsing of cluster CIDR %v: %v", ctx.ComponentConfig.KubeCloudShared.ClusterCIDR, err) } - routeController := routecontroller.New(routes, ctx.ClientBuilder.ClientOrDie("route-controller"), ctx.InformerFactory.Core().V1().Nodes(), ctx.ComponentConfig.ClusterName, clusterCIDR) - go routeController.Run(ctx.Stop, ctx.ComponentConfig.RouteReconciliationPeriod.Duration) + routeController := routecontroller.New(routes, ctx.ClientBuilder.ClientOrDie("route-controller"), ctx.InformerFactory.Core().V1().Nodes(), ctx.ComponentConfig.KubeCloudShared.ClusterName, clusterCIDR) + go routeController.Run(ctx.Stop, ctx.ComponentConfig.KubeCloudShared.RouteReconciliationPeriod.Duration) return true, nil } func startPersistentVolumeBinderController(ctx ControllerContext) (bool, error) { params := persistentvolumecontroller.ControllerParameters{ KubeClient: ctx.ClientBuilder.ClientOrDie("persistent-volume-binder"), - SyncPeriod: ctx.ComponentConfig.PVClaimBinderSyncPeriod.Duration, - VolumePlugins: ProbeControllerVolumePlugins(ctx.Cloud, ctx.ComponentConfig.VolumeConfiguration), + SyncPeriod: ctx.ComponentConfig.PersistentVolumeBinderController.PVClaimBinderSyncPeriod.Duration, + VolumePlugins: ProbeControllerVolumePlugins(ctx.Cloud, ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration), Cloud: ctx.Cloud, - ClusterName: ctx.ComponentConfig.ClusterName, + ClusterName: ctx.ComponentConfig.KubeCloudShared.ClusterName, VolumeInformer: ctx.InformerFactory.Core().V1().PersistentVolumes(), ClaimInformer: ctx.InformerFactory.Core().V1().PersistentVolumeClaims(), ClassInformer: ctx.InformerFactory.Storage().V1().StorageClasses(), PodInformer: ctx.InformerFactory.Core().V1().Pods(), - EnableDynamicProvisioning: ctx.ComponentConfig.VolumeConfiguration.EnableDynamicProvisioning, + NodeInformer: ctx.InformerFactory.Core().V1().Nodes(), + EnableDynamicProvisioning: ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration.EnableDynamicProvisioning, } volumeController, volumeControllerErr := persistentvolumecontroller.NewController(params) if volumeControllerErr != nil { @@ -189,7 +187,7 @@ func startPersistentVolumeBinderController(ctx ControllerContext) (bool, error) } func startAttachDetachController(ctx ControllerContext) (bool, error) { - if ctx.ComponentConfig.ReconcilerSyncLoopPeriod.Duration < time.Second { + if ctx.ComponentConfig.AttachDetachController.ReconcilerSyncLoopPeriod.Duration < time.Second { return true, fmt.Errorf("Duration time must be greater than one second as set via command line option reconcile-sync-loop-period.") } attachDetachController, attachDetachControllerErr := @@ -201,9 +199,9 @@ func startAttachDetachController(ctx ControllerContext) (bool, error) { ctx.InformerFactory.Core().V1().PersistentVolumes(), ctx.Cloud, ProbeAttachableVolumePlugins(), - GetDynamicPluginProber(ctx.ComponentConfig.VolumeConfiguration), - ctx.ComponentConfig.DisableAttachDetachReconcilerSync, - ctx.ComponentConfig.ReconcilerSyncLoopPeriod.Duration, + GetDynamicPluginProber(ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration), + ctx.ComponentConfig.AttachDetachController.DisableAttachDetachReconcilerSync, + ctx.ComponentConfig.AttachDetachController.ReconcilerSyncLoopPeriod.Duration, attachdetach.DefaultTimerConfig, ) if attachDetachControllerErr != nil { @@ -220,7 +218,7 @@ func startVolumeExpandController(ctx ControllerContext) (bool, error) { ctx.InformerFactory.Core().V1().PersistentVolumeClaims(), ctx.InformerFactory.Core().V1().PersistentVolumes(), ctx.Cloud, - ProbeExpandableVolumePlugins(ctx.ComponentConfig.VolumeConfiguration)) + ProbeExpandableVolumePlugins(ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration)) if expandControllerErr != nil { return true, fmt.Errorf("Failed to start volume expand controller : %v", expandControllerErr) @@ -237,7 +235,7 @@ func startEndpointController(ctx ControllerContext) (bool, error) { ctx.InformerFactory.Core().V1().Services(), ctx.InformerFactory.Core().V1().Endpoints(), ctx.ClientBuilder.ClientOrDie("endpoint-controller"), - ).Run(int(ctx.ComponentConfig.ConcurrentEndpointSyncs), ctx.Stop) + ).Run(int(ctx.ComponentConfig.EndPointController.ConcurrentEndpointSyncs), ctx.Stop) return true, nil } @@ -247,7 +245,7 @@ func startReplicationController(ctx ControllerContext) (bool, error) { ctx.InformerFactory.Core().V1().ReplicationControllers(), ctx.ClientBuilder.ClientOrDie("replication-controller"), replicationcontroller.BurstReplicas, - ).Run(int(ctx.ComponentConfig.ConcurrentRCSyncs), ctx.Stop) + ).Run(int(ctx.ComponentConfig.ReplicationController.ConcurrentRCSyncs), ctx.Stop) return true, nil } @@ -255,7 +253,7 @@ func startPodGCController(ctx ControllerContext) (bool, error) { go podgc.NewPodGC( ctx.ClientBuilder.ClientOrDie("pod-garbage-collector"), ctx.InformerFactory.Core().V1().Pods(), - int(ctx.ComponentConfig.TerminatedPodGCThreshold), + int(ctx.ComponentConfig.PodGCController.TerminatedPodGCThreshold), ).Run(ctx.Stop) return true, nil } @@ -269,7 +267,7 @@ func startResourceQuotaController(ctx ControllerContext) (bool, error) { resourceQuotaControllerOptions := &resourcequotacontroller.ResourceQuotaControllerOptions{ QuotaClient: resourceQuotaControllerClient.CoreV1(), ResourceQuotaInformer: ctx.InformerFactory.Core().V1().ResourceQuotas(), - ResyncPeriod: controller.StaticResyncPeriodFunc(ctx.ComponentConfig.ResourceQuotaSyncPeriod.Duration), + ResyncPeriod: controller.StaticResyncPeriodFunc(ctx.ComponentConfig.ResourceQuotaController.ResourceQuotaSyncPeriod.Duration), InformerFactory: ctx.InformerFactory, ReplenishmentResyncPeriod: ctx.ResyncPeriod, DiscoveryFunc: discoveryFunc, @@ -287,7 +285,7 @@ func startResourceQuotaController(ctx ControllerContext) (bool, error) { if err != nil { return false, err } - go resourceQuotaController.Run(int(ctx.ComponentConfig.ConcurrentResourceQuotaSyncs), ctx.Stop) + go resourceQuotaController.Run(int(ctx.ComponentConfig.ResourceQuotaController.ConcurrentResourceQuotaSyncs), ctx.Stop) // Periodically the quota controller to detect new resource types go resourceQuotaController.Sync(discoveryFunc, 30*time.Second, ctx.Stop) @@ -296,29 +294,30 @@ func startResourceQuotaController(ctx ControllerContext) (bool, error) { } func startNamespaceController(ctx ControllerContext) (bool, error) { - // TODO: should use a dynamic RESTMapper built from the discovery results. - restMapper := legacyscheme.Registry.RESTMapper() - // the namespace cleanup controller is very chatty. It makes lots of discovery calls and then it makes lots of delete calls // the ratelimiter negatively affects its speed. Deleting 100 total items in a namespace (that's only a few of each resource // including events), takes ~10 seconds by default. nsKubeconfig := ctx.ClientBuilder.ConfigOrDie("namespace-controller") - nsKubeconfig.QPS *= 10 - nsKubeconfig.Burst *= 10 + nsKubeconfig.QPS *= 20 + nsKubeconfig.Burst *= 100 namespaceKubeClient := clientset.NewForConfigOrDie(nsKubeconfig) - namespaceClientPool := dynamic.NewClientPool(nsKubeconfig, restMapper, dynamic.LegacyAPIPathResolverFunc) + + dynamicClient, err := dynamic.NewForConfig(nsKubeconfig) + if err != nil { + return true, err + } discoverResourcesFn := namespaceKubeClient.Discovery().ServerPreferredNamespacedResources namespaceController := namespacecontroller.NewNamespaceController( namespaceKubeClient, - namespaceClientPool, + dynamicClient, discoverResourcesFn, ctx.InformerFactory.Core().V1().Namespaces(), - ctx.ComponentConfig.NamespaceSyncPeriod.Duration, + ctx.ComponentConfig.NamespaceController.NamespaceSyncPeriod.Duration, v1.FinalizerKubernetes, ) - go namespaceController.Run(int(ctx.ComponentConfig.ConcurrentNamespaceSyncs), ctx.Stop) + go namespaceController.Run(int(ctx.ComponentConfig.NamespaceController.ConcurrentNamespaceSyncs), ctx.Stop) return true, nil } @@ -346,36 +345,28 @@ func startTTLController(ctx ControllerContext) (bool, error) { } func startGarbageCollectorController(ctx ControllerContext) (bool, error) { - if !ctx.ComponentConfig.EnableGarbageCollector { + if !ctx.ComponentConfig.GarbageCollectorController.EnableGarbageCollector { return false, nil } gcClientset := ctx.ClientBuilder.ClientOrDie("generic-garbage-collector") - - // Use a discovery client capable of being refreshed. discoveryClient := cacheddiscovery.NewMemCacheClient(gcClientset.Discovery()) - restMapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient, meta.InterfacesForUnstructured) - restMapper.Reset() config := ctx.ClientBuilder.ConfigOrDie("generic-garbage-collector") - config.ContentConfig = dynamic.ContentConfig() - // TODO: Make NewMetadataCodecFactory support arbitrary (non-compiled) - // resource types. Otherwise we'll be storing full Unstructured data in our - // caches for custom resources. Consider porting it to work with - // metav1beta1.PartialObjectMetadata. - metaOnlyClientPool := dynamic.NewClientPool(config, restMapper, dynamic.LegacyAPIPathResolverFunc) - clientPool := dynamic.NewClientPool(config, restMapper, dynamic.LegacyAPIPathResolverFunc) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + return true, err + } // Get an initial set of deletable resources to prime the garbage collector. deletableResources := garbagecollector.GetDeletableResources(discoveryClient) ignoredResources := make(map[schema.GroupResource]struct{}) - for _, r := range ctx.ComponentConfig.GCIgnoredResources { + for _, r := range ctx.ComponentConfig.GarbageCollectorController.GCIgnoredResources { ignoredResources[schema.GroupResource{Group: r.Group, Resource: r.Resource}] = struct{}{} } garbageCollector, err := garbagecollector.NewGarbageCollector( - metaOnlyClientPool, - clientPool, - restMapper, + dynamicClient, + ctx.RESTMapper, deletableResources, ignoredResources, ctx.InformerFactory, @@ -386,7 +377,7 @@ func startGarbageCollectorController(ctx ControllerContext) (bool, error) { } // Start the garbage collector. - workers := int(ctx.ComponentConfig.ConcurrentGCSyncs) + workers := int(ctx.ComponentConfig.GarbageCollectorController.ConcurrentGCSyncs) go garbageCollector.Run(workers, ctx.Stop) // Periodically refresh the RESTMapper with new discovery information and sync diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/extensions.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/extensions.go deleted file mode 100644 index 2c30fde86..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/extensions.go +++ /dev/null @@ -1,59 +0,0 @@ -/* -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 app implements a server that runs a set of active -// components. This includes replication controllers, service endpoints and -// nodes. -// -package app - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/pkg/controller/deployment" - "k8s.io/kubernetes/pkg/controller/replicaset" -) - -func startDeploymentController(ctx ControllerContext) (bool, error) { - if !ctx.AvailableResources[schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"}] { - return false, nil - } - dc, err := deployment.NewDeploymentController( - ctx.InformerFactory.Extensions().V1beta1().Deployments(), - ctx.InformerFactory.Extensions().V1beta1().ReplicaSets(), - ctx.InformerFactory.Core().V1().Pods(), - ctx.ClientBuilder.ClientOrDie("deployment-controller"), - ) - if err != nil { - return true, fmt.Errorf("error creating Deployment controller: %v", err) - } - go dc.Run(int(ctx.ComponentConfig.ConcurrentDeploymentSyncs), ctx.Stop) - return true, nil -} - -func startReplicaSetController(ctx ControllerContext) (bool, error) { - if !ctx.AvailableResources[schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "replicasets"}] { - return false, nil - } - go replicaset.NewReplicaSetController( - ctx.InformerFactory.Extensions().V1beta1().ReplicaSets(), - ctx.InformerFactory.Core().V1().Pods(), - ctx.ClientBuilder.ClientOrDie("replicaset-controller"), - replicaset.BurstReplicas, - ).Run(int(ctx.ComponentConfig.ConcurrentRSSyncs), ctx.Stop) - return true, nil -} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/import_known_versions.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/import_known_versions.go index f63e298a2..8b9a07da4 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/import_known_versions.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/import_known_versions.go @@ -20,9 +20,6 @@ package app // These imports are the API groups the client will support. import ( - "fmt" - - "k8s.io/kubernetes/pkg/api/legacyscheme" _ "k8s.io/kubernetes/pkg/apis/apps/install" _ "k8s.io/kubernetes/pkg/apis/authentication/install" _ "k8s.io/kubernetes/pkg/apis/authorization/install" @@ -38,9 +35,3 @@ import ( _ "k8s.io/kubernetes/pkg/apis/settings/install" _ "k8s.io/kubernetes/pkg/apis/storage/install" ) - -func init() { - if missingVersions := legacyscheme.Registry.ValidateEnvRequestedVersions(); len(missingVersions) != 0 { - panic(fmt.Sprintf("KUBE_API_VERSIONS contains versions that are not installed: %q.", missingVersions)) - } -} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/BUILD index 46c380fe9..3bba70af8 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/BUILD @@ -13,15 +13,25 @@ go_library( deps = [ "//cmd/controller-manager/app/options:go_default_library", "//cmd/kube-controller-manager/app/config:go_default_library", + "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/componentconfig:go_default_library", - "//pkg/client/leaderelectionconfig:go_default_library", + "//pkg/apis/componentconfig/v1alpha1:go_default_library", "//pkg/controller/garbagecollector:go_default_library", "//pkg/features:go_default_library", "//pkg/master/ports:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server/options: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/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/options.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/options.go index f9adc670c..2b26024e5 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/options.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/options.go @@ -20,135 +20,357 @@ package options import ( "fmt" + "net" "strings" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" + apiserveroptions "k8s.io/apiserver/pkg/server/options" utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/client-go/kubernetes" + clientset "k8s.io/client-go/kubernetes" + v1core "k8s.io/client-go/kubernetes/typed/core/v1" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/record" cmoptions "k8s.io/kubernetes/cmd/controller-manager/app/options" kubecontrollerconfig "k8s.io/kubernetes/cmd/kube-controller-manager/app/config" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/componentconfig" - "k8s.io/kubernetes/pkg/client/leaderelectionconfig" + componentconfigv1alpha1 "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" "k8s.io/kubernetes/pkg/controller/garbagecollector" "k8s.io/kubernetes/pkg/master/ports" - // add the kubernetes feature gates _ "k8s.io/kubernetes/pkg/features" + "github.com/golang/glog" "github.com/spf13/pflag" ) -// KubeControllerManagerOptions is the main context object for the controller manager. +// KubeControllerManagerOptions is the main context object for the kube-controller manager. type KubeControllerManagerOptions struct { - Generic cmoptions.GenericControllerManagerOptions + CloudProvider *cmoptions.CloudProviderOptions + Debugging *cmoptions.DebuggingOptions + GenericComponent *cmoptions.GenericComponentConfigOptions + KubeCloudShared *cmoptions.KubeCloudSharedOptions + + AttachDetachController *cmoptions.AttachDetachControllerOptions + CSRSigningController *cmoptions.CSRSigningControllerOptions + DaemonSetController *cmoptions.DaemonSetControllerOptions + DeploymentController *cmoptions.DeploymentControllerOptions + DeprecatedFlags *cmoptions.DeprecatedControllerOptions + EndPointController *cmoptions.EndPointControllerOptions + GarbageCollectorController *cmoptions.GarbageCollectorControllerOptions + HPAController *cmoptions.HPAControllerOptions + JobController *cmoptions.JobControllerOptions + NamespaceController *cmoptions.NamespaceControllerOptions + NodeIpamController *cmoptions.NodeIpamControllerOptions + NodeLifecycleController *cmoptions.NodeLifecycleControllerOptions + PersistentVolumeBinderController *cmoptions.PersistentVolumeBinderControllerOptions + PodGCController *cmoptions.PodGCControllerOptions + ReplicaSetController *cmoptions.ReplicaSetControllerOptions + ReplicationController *cmoptions.ReplicationControllerOptions + ResourceQuotaController *cmoptions.ResourceQuotaControllerOptions + SAController *cmoptions.SAControllerOptions + ServiceController *cmoptions.ServiceControllerOptions + + Controllers []string + ExternalCloudVolumePlugin string + + SecureServing *apiserveroptions.SecureServingOptions + // TODO: remove insecure serving mode + InsecureServing *cmoptions.InsecureServingOptions + Authentication *apiserveroptions.DelegatingAuthenticationOptions + Authorization *apiserveroptions.DelegatingAuthorizationOptions + + Master string + Kubeconfig string } // NewKubeControllerManagerOptions creates a new KubeControllerManagerOptions with a default config. -func NewKubeControllerManagerOptions() *KubeControllerManagerOptions { - componentConfig := cmoptions.NewDefaultControllerManagerComponentConfig(ports.InsecureKubeControllerManagerPort) +func NewKubeControllerManagerOptions() (*KubeControllerManagerOptions, error) { + componentConfig, err := NewDefaultComponentConfig(ports.InsecureKubeControllerManagerPort) + if err != nil { + return nil, err + } + s := KubeControllerManagerOptions{ - // The common/default are kept in 'cmd/kube-controller-manager/app/options/util.go'. - // Please make common changes there but put anything kube-controller specific here. - Generic: cmoptions.NewGenericControllerManagerOptions(componentConfig), + CloudProvider: &cmoptions.CloudProviderOptions{}, + Debugging: &cmoptions.DebuggingOptions{}, + GenericComponent: cmoptions.NewGenericComponentConfigOptions(componentConfig.GenericComponent), + KubeCloudShared: cmoptions.NewKubeCloudSharedOptions(componentConfig.KubeCloudShared), + AttachDetachController: &cmoptions.AttachDetachControllerOptions{ + ReconcilerSyncLoopPeriod: componentConfig.AttachDetachController.ReconcilerSyncLoopPeriod, + }, + CSRSigningController: &cmoptions.CSRSigningControllerOptions{ + ClusterSigningCertFile: componentConfig.CSRSigningController.ClusterSigningCertFile, + ClusterSigningKeyFile: componentConfig.CSRSigningController.ClusterSigningKeyFile, + ClusterSigningDuration: componentConfig.CSRSigningController.ClusterSigningDuration, + }, + DaemonSetController: &cmoptions.DaemonSetControllerOptions{ + ConcurrentDaemonSetSyncs: componentConfig.DaemonSetController.ConcurrentDaemonSetSyncs, + }, + DeploymentController: &cmoptions.DeploymentControllerOptions{ + ConcurrentDeploymentSyncs: componentConfig.DeploymentController.ConcurrentDeploymentSyncs, + DeploymentControllerSyncPeriod: componentConfig.DeploymentController.DeploymentControllerSyncPeriod, + }, + DeprecatedFlags: &cmoptions.DeprecatedControllerOptions{ + RegisterRetryCount: componentConfig.DeprecatedController.RegisterRetryCount, + }, + EndPointController: &cmoptions.EndPointControllerOptions{ + ConcurrentEndpointSyncs: componentConfig.EndPointController.ConcurrentEndpointSyncs, + }, + GarbageCollectorController: &cmoptions.GarbageCollectorControllerOptions{ + ConcurrentGCSyncs: componentConfig.GarbageCollectorController.ConcurrentGCSyncs, + EnableGarbageCollector: componentConfig.GarbageCollectorController.EnableGarbageCollector, + }, + HPAController: &cmoptions.HPAControllerOptions{ + HorizontalPodAutoscalerSyncPeriod: componentConfig.HPAController.HorizontalPodAutoscalerSyncPeriod, + HorizontalPodAutoscalerUpscaleForbiddenWindow: componentConfig.HPAController.HorizontalPodAutoscalerUpscaleForbiddenWindow, + HorizontalPodAutoscalerDownscaleForbiddenWindow: componentConfig.HPAController.HorizontalPodAutoscalerDownscaleForbiddenWindow, + HorizontalPodAutoscalerTolerance: componentConfig.HPAController.HorizontalPodAutoscalerTolerance, + HorizontalPodAutoscalerUseRESTClients: componentConfig.HPAController.HorizontalPodAutoscalerUseRESTClients, + }, + JobController: &cmoptions.JobControllerOptions{ + ConcurrentJobSyncs: componentConfig.JobController.ConcurrentJobSyncs, + }, + NamespaceController: &cmoptions.NamespaceControllerOptions{ + NamespaceSyncPeriod: componentConfig.NamespaceController.NamespaceSyncPeriod, + ConcurrentNamespaceSyncs: componentConfig.NamespaceController.ConcurrentNamespaceSyncs, + }, + NodeIpamController: &cmoptions.NodeIpamControllerOptions{ + NodeCIDRMaskSize: componentConfig.NodeIpamController.NodeCIDRMaskSize, + }, + NodeLifecycleController: &cmoptions.NodeLifecycleControllerOptions{ + EnableTaintManager: componentConfig.NodeLifecycleController.EnableTaintManager, + NodeMonitorGracePeriod: componentConfig.NodeLifecycleController.NodeMonitorGracePeriod, + NodeStartupGracePeriod: componentConfig.NodeLifecycleController.NodeStartupGracePeriod, + PodEvictionTimeout: componentConfig.NodeLifecycleController.PodEvictionTimeout, + }, + PersistentVolumeBinderController: &cmoptions.PersistentVolumeBinderControllerOptions{ + PVClaimBinderSyncPeriod: componentConfig.PersistentVolumeBinderController.PVClaimBinderSyncPeriod, + VolumeConfiguration: componentConfig.PersistentVolumeBinderController.VolumeConfiguration, + }, + PodGCController: &cmoptions.PodGCControllerOptions{ + TerminatedPodGCThreshold: componentConfig.PodGCController.TerminatedPodGCThreshold, + }, + ReplicaSetController: &cmoptions.ReplicaSetControllerOptions{ + ConcurrentRSSyncs: componentConfig.ReplicaSetController.ConcurrentRSSyncs, + }, + ReplicationController: &cmoptions.ReplicationControllerOptions{ + ConcurrentRCSyncs: componentConfig.ReplicationController.ConcurrentRCSyncs, + }, + ResourceQuotaController: &cmoptions.ResourceQuotaControllerOptions{ + ResourceQuotaSyncPeriod: componentConfig.ResourceQuotaController.ResourceQuotaSyncPeriod, + ConcurrentResourceQuotaSyncs: componentConfig.ResourceQuotaController.ConcurrentResourceQuotaSyncs, + }, + SAController: &cmoptions.SAControllerOptions{ + ConcurrentSATokenSyncs: componentConfig.SAController.ConcurrentSATokenSyncs, + }, + ServiceController: &cmoptions.ServiceControllerOptions{ + ConcurrentServiceSyncs: componentConfig.ServiceController.ConcurrentServiceSyncs, + }, + Controllers: componentConfig.Controllers, + SecureServing: apiserveroptions.NewSecureServingOptions(), + InsecureServing: &cmoptions.InsecureServingOptions{ + BindAddress: net.ParseIP(componentConfig.KubeCloudShared.Address), + BindPort: int(componentConfig.KubeCloudShared.Port), + BindNetwork: "tcp", + }, + Authentication: nil, // TODO: enable with apiserveroptions.NewDelegatingAuthenticationOptions() + Authorization: nil, // TODO: enable with apiserveroptions.NewDelegatingAuthorizationOptions() } - s.Generic.SecureServing.ServerCert.CertDirectory = "/var/run/kubernetes" - s.Generic.SecureServing.ServerCert.PairName = "kube-controller-manager" + s.SecureServing.ServerCert.CertDirectory = "/var/run/kubernetes" + s.SecureServing.ServerCert.PairName = "kube-controller-manager" + + // disable secure serving for now + // TODO: enable HTTPS by default + s.SecureServing.BindPort = 0 gcIgnoredResources := make([]componentconfig.GroupResource, 0, len(garbagecollector.DefaultIgnoredResources())) for r := range garbagecollector.DefaultIgnoredResources() { gcIgnoredResources = append(gcIgnoredResources, componentconfig.GroupResource{Group: r.Group, Resource: r.Resource}) } - s.Generic.ComponentConfig.GCIgnoredResources = gcIgnoredResources - s.Generic.ComponentConfig.LeaderElection.LeaderElect = true - return &s + s.GarbageCollectorController.GCIgnoredResources = gcIgnoredResources + + return &s, nil +} + +// NewDefaultComponentConfig returns kube-controller manager configuration object. +func NewDefaultComponentConfig(insecurePort int32) (componentconfig.KubeControllerManagerConfiguration, error) { + scheme := runtime.NewScheme() + componentconfigv1alpha1.AddToScheme(scheme) + componentconfig.AddToScheme(scheme) + + versioned := componentconfigv1alpha1.KubeControllerManagerConfiguration{} + scheme.Default(&versioned) + + internal := componentconfig.KubeControllerManagerConfiguration{} + if err := scheme.Convert(&versioned, &internal, nil); err != nil { + return internal, err + } + internal.KubeCloudShared.Port = insecurePort + return internal, nil } // AddFlags adds flags for a specific KubeControllerManagerOptions to the specified FlagSet func (s *KubeControllerManagerOptions) AddFlags(fs *pflag.FlagSet, allControllers []string, disabledByDefaultControllers []string) { - s.Generic.AddFlags(fs) + s.CloudProvider.AddFlags(fs) + s.Debugging.AddFlags(fs) + s.GenericComponent.AddFlags(fs) + s.KubeCloudShared.AddFlags(fs) + s.ServiceController.AddFlags(fs) - fs.StringSliceVar(&s.Generic.ComponentConfig.Controllers, "controllers", s.Generic.ComponentConfig.Controllers, fmt.Sprintf(""+ + s.SecureServing.AddFlags(fs) + s.InsecureServing.AddFlags(fs) + s.Authentication.AddFlags(fs) + s.Authorization.AddFlags(fs) + + s.AttachDetachController.AddFlags(fs) + s.CSRSigningController.AddFlags(fs) + s.DeploymentController.AddFlags(fs) + s.DaemonSetController.AddFlags(fs) + s.DeprecatedFlags.AddFlags(fs) + s.EndPointController.AddFlags(fs) + s.GarbageCollectorController.AddFlags(fs) + s.HPAController.AddFlags(fs) + s.JobController.AddFlags(fs) + s.NamespaceController.AddFlags(fs) + s.NodeIpamController.AddFlags(fs) + s.NodeLifecycleController.AddFlags(fs) + s.PersistentVolumeBinderController.AddFlags(fs) + s.PodGCController.AddFlags(fs) + s.ReplicaSetController.AddFlags(fs) + s.ReplicationController.AddFlags(fs) + s.ResourceQuotaController.AddFlags(fs) + s.SAController.AddFlags(fs) + + fs.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig).") + fs.StringVar(&s.Kubeconfig, "kubeconfig", s.Kubeconfig, "Path to kubeconfig file with authorization and master location information.") + fs.StringSliceVar(&s.Controllers, "controllers", s.Controllers, fmt.Sprintf(""+ "A list of controllers to enable. '*' enables all on-by-default controllers, 'foo' enables the controller "+ "named 'foo', '-foo' disables the controller named 'foo'.\nAll controllers: %s\nDisabled-by-default controllers: %s", strings.Join(allControllers, ", "), strings.Join(disabledByDefaultControllers, ", "))) - fs.StringVar(&s.Generic.ComponentConfig.CloudProvider, "cloud-provider", s.Generic.ComponentConfig.CloudProvider, "The provider for cloud services. Empty string for no provider.") - fs.StringVar(&s.Generic.ComponentConfig.ExternalCloudVolumePlugin, "external-cloud-volume-plugin", s.Generic.ComponentConfig.ExternalCloudVolumePlugin, "The plugin to use when cloud provider is set to external. Can be empty, should only be set when cloud-provider is external. Currently used to allow node and volume controllers to work for in tree cloud providers.") - fs.Int32Var(&s.Generic.ComponentConfig.ConcurrentEndpointSyncs, "concurrent-endpoint-syncs", s.Generic.ComponentConfig.ConcurrentEndpointSyncs, "The number of endpoint syncing operations that will be done concurrently. Larger number = faster endpoint updating, but more CPU (and network) load") - fs.Int32Var(&s.Generic.ComponentConfig.ConcurrentServiceSyncs, "concurrent-service-syncs", s.Generic.ComponentConfig.ConcurrentServiceSyncs, "The number of services that are allowed to sync concurrently. Larger number = more responsive service management, but more CPU (and network) load") - fs.Int32Var(&s.Generic.ComponentConfig.ConcurrentRCSyncs, "concurrent_rc_syncs", s.Generic.ComponentConfig.ConcurrentRCSyncs, "The number of replication controllers that are allowed to sync concurrently. Larger number = more responsive replica management, but more CPU (and network) load") - fs.Int32Var(&s.Generic.ComponentConfig.ConcurrentRSSyncs, "concurrent-replicaset-syncs", s.Generic.ComponentConfig.ConcurrentRSSyncs, "The number of replica sets that are allowed to sync concurrently. Larger number = more responsive replica management, but more CPU (and network) load") - - fs.Int32Var(&s.Generic.ComponentConfig.ConcurrentResourceQuotaSyncs, "concurrent-resource-quota-syncs", s.Generic.ComponentConfig.ConcurrentResourceQuotaSyncs, "The number of resource quotas that are allowed to sync concurrently. Larger number = more responsive quota management, but more CPU (and network) load") - fs.Int32Var(&s.Generic.ComponentConfig.ConcurrentDeploymentSyncs, "concurrent-deployment-syncs", s.Generic.ComponentConfig.ConcurrentDeploymentSyncs, "The number of deployment objects that are allowed to sync concurrently. Larger number = more responsive deployments, but more CPU (and network) load") - fs.Int32Var(&s.Generic.ComponentConfig.ConcurrentNamespaceSyncs, "concurrent-namespace-syncs", s.Generic.ComponentConfig.ConcurrentNamespaceSyncs, "The number of namespace objects that are allowed to sync concurrently. Larger number = more responsive namespace termination, but more CPU (and network) load") - fs.Int32Var(&s.Generic.ComponentConfig.ConcurrentSATokenSyncs, "concurrent-serviceaccount-token-syncs", s.Generic.ComponentConfig.ConcurrentSATokenSyncs, "The number of service account token objects that are allowed to sync concurrently. Larger number = more responsive token generation, but more CPU (and network) load") - fs.DurationVar(&s.Generic.ComponentConfig.NodeSyncPeriod.Duration, "node-sync-period", 0, ""+ - "This flag is deprecated and will be removed in future releases. See node-monitor-period for Node health checking or "+ - "route-reconciliation-period for cloud provider's route configuration settings.") - fs.MarkDeprecated("node-sync-period", "This flag is currently no-op and will be deleted.") - fs.DurationVar(&s.Generic.ComponentConfig.ResourceQuotaSyncPeriod.Duration, "resource-quota-sync-period", s.Generic.ComponentConfig.ResourceQuotaSyncPeriod.Duration, "The period for syncing quota usage status in the system") - fs.DurationVar(&s.Generic.ComponentConfig.NamespaceSyncPeriod.Duration, "namespace-sync-period", s.Generic.ComponentConfig.NamespaceSyncPeriod.Duration, "The period for syncing namespace life-cycle updates") - fs.DurationVar(&s.Generic.ComponentConfig.PVClaimBinderSyncPeriod.Duration, "pvclaimbinder-sync-period", s.Generic.ComponentConfig.PVClaimBinderSyncPeriod.Duration, "The period for syncing persistent volumes and persistent volume claims") - fs.StringVar(&s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.PodTemplateFilePathNFS, "pv-recycler-pod-template-filepath-nfs", s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.PodTemplateFilePathNFS, "The file path to a pod definition used as a template for NFS persistent volume recycling") - fs.Int32Var(&s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.MinimumTimeoutNFS, "pv-recycler-minimum-timeout-nfs", s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.MinimumTimeoutNFS, "The minimum ActiveDeadlineSeconds to use for an NFS Recycler pod") - fs.Int32Var(&s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.IncrementTimeoutNFS, "pv-recycler-increment-timeout-nfs", s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.IncrementTimeoutNFS, "the increment of time added per Gi to ActiveDeadlineSeconds for an NFS scrubber pod") - fs.StringVar(&s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.PodTemplateFilePathHostPath, "pv-recycler-pod-template-filepath-hostpath", s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.PodTemplateFilePathHostPath, "The file path to a pod definition used as a template for HostPath persistent volume recycling. This is for development and testing only and will not work in a multi-node cluster.") - fs.Int32Var(&s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.MinimumTimeoutHostPath, "pv-recycler-minimum-timeout-hostpath", s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.MinimumTimeoutHostPath, "The minimum ActiveDeadlineSeconds to use for a HostPath Recycler pod. This is for development and testing only and will not work in a multi-node cluster.") - fs.Int32Var(&s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.IncrementTimeoutHostPath, "pv-recycler-timeout-increment-hostpath", s.Generic.ComponentConfig.VolumeConfiguration.PersistentVolumeRecyclerConfiguration.IncrementTimeoutHostPath, "the increment of time added per Gi to ActiveDeadlineSeconds for a HostPath scrubber pod. This is for development and testing only and will not work in a multi-node cluster.") - fs.BoolVar(&s.Generic.ComponentConfig.VolumeConfiguration.EnableHostPathProvisioning, "enable-hostpath-provisioner", s.Generic.ComponentConfig.VolumeConfiguration.EnableHostPathProvisioning, "Enable HostPath PV provisioning when running without a cloud provider. This allows testing and development of provisioning features. HostPath provisioning is not supported in any way, won't work in a multi-node cluster, and should not be used for anything other than testing or development.") - fs.BoolVar(&s.Generic.ComponentConfig.VolumeConfiguration.EnableDynamicProvisioning, "enable-dynamic-provisioning", s.Generic.ComponentConfig.VolumeConfiguration.EnableDynamicProvisioning, "Enable dynamic provisioning for environments that support it.") - fs.StringVar(&s.Generic.ComponentConfig.VolumeConfiguration.FlexVolumePluginDir, "flex-volume-plugin-dir", s.Generic.ComponentConfig.VolumeConfiguration.FlexVolumePluginDir, "Full path of the directory in which the flex volume plugin should search for additional third party volume plugins.") - fs.Int32Var(&s.Generic.ComponentConfig.TerminatedPodGCThreshold, "terminated-pod-gc-threshold", s.Generic.ComponentConfig.TerminatedPodGCThreshold, "Number of terminated pods that can exist before the terminated pod garbage collector starts deleting terminated pods. If <= 0, the terminated pod garbage collector is disabled.") - fs.DurationVar(&s.Generic.ComponentConfig.HorizontalPodAutoscalerSyncPeriod.Duration, "horizontal-pod-autoscaler-sync-period", s.Generic.ComponentConfig.HorizontalPodAutoscalerSyncPeriod.Duration, "The period for syncing the number of pods in horizontal pod autoscaler.") - fs.DurationVar(&s.Generic.ComponentConfig.HorizontalPodAutoscalerUpscaleForbiddenWindow.Duration, "horizontal-pod-autoscaler-upscale-delay", s.Generic.ComponentConfig.HorizontalPodAutoscalerUpscaleForbiddenWindow.Duration, "The period since last upscale, before another upscale can be performed in horizontal pod autoscaler.") - fs.DurationVar(&s.Generic.ComponentConfig.HorizontalPodAutoscalerDownscaleForbiddenWindow.Duration, "horizontal-pod-autoscaler-downscale-delay", s.Generic.ComponentConfig.HorizontalPodAutoscalerDownscaleForbiddenWindow.Duration, "The period since last downscale, before another downscale can be performed in horizontal pod autoscaler.") - fs.Float64Var(&s.Generic.ComponentConfig.HorizontalPodAutoscalerTolerance, "horizontal-pod-autoscaler-tolerance", s.Generic.ComponentConfig.HorizontalPodAutoscalerTolerance, "The minimum change (from 1.0) in the desired-to-actual metrics ratio for the horizontal pod autoscaler to consider scaling.") - fs.DurationVar(&s.Generic.ComponentConfig.DeploymentControllerSyncPeriod.Duration, "deployment-controller-sync-period", s.Generic.ComponentConfig.DeploymentControllerSyncPeriod.Duration, "Period for syncing the deployments.") - fs.DurationVar(&s.Generic.ComponentConfig.PodEvictionTimeout.Duration, "pod-eviction-timeout", s.Generic.ComponentConfig.PodEvictionTimeout.Duration, "The grace period for deleting pods on failed nodes.") - fs.Float32Var(&s.Generic.ComponentConfig.DeletingPodsQps, "deleting-pods-qps", 0.1, "Number of nodes per second on which pods are deleted in case of node failure.") - fs.MarkDeprecated("deleting-pods-qps", "This flag is currently no-op and will be deleted.") - fs.Int32Var(&s.Generic.ComponentConfig.DeletingPodsBurst, "deleting-pods-burst", 0, "Number of nodes on which pods are bursty deleted in case of node failure. For more details look into RateLimiter.") - fs.MarkDeprecated("deleting-pods-burst", "This flag is currently no-op and will be deleted.") - fs.Int32Var(&s.Generic.ComponentConfig.RegisterRetryCount, "register-retry-count", s.Generic.ComponentConfig.RegisterRetryCount, ""+ - "The number of retries for initial node registration. Retry interval equals node-sync-period.") - fs.MarkDeprecated("register-retry-count", "This flag is currently no-op and will be deleted.") - fs.DurationVar(&s.Generic.ComponentConfig.NodeMonitorGracePeriod.Duration, "node-monitor-grace-period", s.Generic.ComponentConfig.NodeMonitorGracePeriod.Duration, - "Amount of time which we allow running Node to be unresponsive before marking it unhealthy. "+ - "Must be N times more than kubelet's nodeStatusUpdateFrequency, "+ - "where N means number of retries allowed for kubelet to post node status.") - fs.DurationVar(&s.Generic.ComponentConfig.NodeStartupGracePeriod.Duration, "node-startup-grace-period", s.Generic.ComponentConfig.NodeStartupGracePeriod.Duration, - "Amount of time which we allow starting Node to be unresponsive before marking it unhealthy.") - fs.StringVar(&s.Generic.ComponentConfig.ServiceAccountKeyFile, "service-account-private-key-file", s.Generic.ComponentConfig.ServiceAccountKeyFile, "Filename containing a PEM-encoded private RSA or ECDSA key used to sign service account tokens.") - fs.StringVar(&s.Generic.ComponentConfig.ClusterSigningCertFile, "cluster-signing-cert-file", s.Generic.ComponentConfig.ClusterSigningCertFile, "Filename containing a PEM-encoded X509 CA certificate used to issue cluster-scoped certificates") - fs.StringVar(&s.Generic.ComponentConfig.ClusterSigningKeyFile, "cluster-signing-key-file", s.Generic.ComponentConfig.ClusterSigningKeyFile, "Filename containing a PEM-encoded RSA or ECDSA private key used to sign cluster-scoped certificates") - fs.DurationVar(&s.Generic.ComponentConfig.ClusterSigningDuration.Duration, "experimental-cluster-signing-duration", s.Generic.ComponentConfig.ClusterSigningDuration.Duration, "The length of duration signed certificates will be given.") + fs.StringVar(&s.ExternalCloudVolumePlugin, "external-cloud-volume-plugin", s.ExternalCloudVolumePlugin, "The plugin to use when cloud provider is set to external. Can be empty, should only be set when cloud-provider is external. Currently used to allow node and volume controllers to work for in tree cloud providers.") var dummy string fs.MarkDeprecated("insecure-experimental-approve-all-kubelet-csrs-for-group", "This flag does nothing.") fs.StringVar(&dummy, "insecure-experimental-approve-all-kubelet-csrs-for-group", "", "This flag does nothing.") - fs.StringVar(&s.Generic.ComponentConfig.ServiceCIDR, "service-cluster-ip-range", s.Generic.ComponentConfig.ServiceCIDR, "CIDR Range for Services in cluster. Requires --allocate-node-cidrs to be true") - fs.Int32Var(&s.Generic.ComponentConfig.NodeCIDRMaskSize, "node-cidr-mask-size", s.Generic.ComponentConfig.NodeCIDRMaskSize, "Mask size for node cidr in cluster.") - fs.StringVar(&s.Generic.ComponentConfig.RootCAFile, "root-ca-file", s.Generic.ComponentConfig.RootCAFile, "If set, this root certificate authority will be included in service account's token secret. This must be a valid PEM-encoded CA bundle.") - fs.BoolVar(&s.Generic.ComponentConfig.EnableGarbageCollector, "enable-garbage-collector", s.Generic.ComponentConfig.EnableGarbageCollector, "Enables the generic garbage collector. MUST be synced with the corresponding flag of the kube-apiserver.") - fs.Int32Var(&s.Generic.ComponentConfig.ConcurrentGCSyncs, "concurrent-gc-syncs", s.Generic.ComponentConfig.ConcurrentGCSyncs, "The number of garbage collector workers that are allowed to sync concurrently.") - fs.Int32Var(&s.Generic.ComponentConfig.LargeClusterSizeThreshold, "large-cluster-size-threshold", 50, "Number of nodes from which NodeController treats the cluster as large for the eviction logic purposes. --secondary-node-eviction-rate is implicitly overridden to 0 for clusters this size or smaller.") - fs.Float32Var(&s.Generic.ComponentConfig.UnhealthyZoneThreshold, "unhealthy-zone-threshold", 0.55, "Fraction of Nodes in a zone which needs to be not Ready (minimum 3) for zone to be treated as unhealthy. ") - fs.BoolVar(&s.Generic.ComponentConfig.DisableAttachDetachReconcilerSync, "disable-attach-detach-reconcile-sync", false, "Disable volume attach detach reconciler sync. Disabling this may cause volumes to be mismatched with pods. Use wisely.") - fs.DurationVar(&s.Generic.ComponentConfig.ReconcilerSyncLoopPeriod.Duration, "attach-detach-reconcile-sync-period", s.Generic.ComponentConfig.ReconcilerSyncLoopPeriod.Duration, "The reconciler sync wait time between volume attach detach. This duration must be larger than one second, and increasing this value from the default may allow for volumes to be mismatched with pods.") - fs.BoolVar(&s.Generic.ComponentConfig.EnableTaintManager, "enable-taint-manager", s.Generic.ComponentConfig.EnableTaintManager, "WARNING: Beta feature. If set to true enables NoExecute Taints and will evict all not-tolerating Pod running on Nodes tainted with this kind of Taints.") - fs.BoolVar(&s.Generic.ComponentConfig.HorizontalPodAutoscalerUseRESTClients, "horizontal-pod-autoscaler-use-rest-clients", s.Generic.ComponentConfig.HorizontalPodAutoscalerUseRESTClients, "WARNING: alpha feature. If set to true, causes the horizontal pod autoscaler controller to use REST clients through the kube-aggregator, instead of using the legacy metrics client through the API server proxy. This is required for custom metrics support in the horizontal pod autoscaler.") - fs.Float32Var(&s.Generic.ComponentConfig.NodeEvictionRate, "node-eviction-rate", 0.1, "Number of nodes per second on which pods are deleted in case of node failure when a zone is healthy (see --unhealthy-zone-threshold for definition of healthy/unhealthy). Zone refers to entire cluster in non-multizone clusters.") - fs.Float32Var(&s.Generic.ComponentConfig.SecondaryNodeEvictionRate, "secondary-node-eviction-rate", 0.01, "Number of nodes per second on which pods are deleted in case of node failure when a zone is unhealthy (see --unhealthy-zone-threshold for definition of healthy/unhealthy). Zone refers to entire cluster in non-multizone clusters. This value is implicitly overridden to 0 if the cluster size is smaller than --large-cluster-size-threshold.") - - leaderelectionconfig.BindFlags(&s.Generic.ComponentConfig.LeaderElection, fs) - utilfeature.DefaultFeatureGate.AddFlag(fs) } // ApplyTo fills up controller manager config with options. -func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config) error { - err := s.Generic.ApplyTo(&c.Generic, "controller-manager") +func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config, userAgent string) error { + if err := s.CloudProvider.ApplyTo(&c.ComponentConfig.CloudProvider); err != nil { + return err + } + if err := s.Debugging.ApplyTo(&c.ComponentConfig.Debugging); err != nil { + return err + } + if err := s.GenericComponent.ApplyTo(&c.ComponentConfig.GenericComponent); err != nil { + return err + } + if err := s.KubeCloudShared.ApplyTo(&c.ComponentConfig.KubeCloudShared); err != nil { + return err + } + if err := s.AttachDetachController.ApplyTo(&c.ComponentConfig.AttachDetachController); err != nil { + return err + } + if err := s.CSRSigningController.ApplyTo(&c.ComponentConfig.CSRSigningController); err != nil { + return err + } + if err := s.DaemonSetController.ApplyTo(&c.ComponentConfig.DaemonSetController); err != nil { + return err + } + if err := s.DeploymentController.ApplyTo(&c.ComponentConfig.DeploymentController); err != nil { + return err + } + if err := s.DeprecatedFlags.ApplyTo(&c.ComponentConfig.DeprecatedController); err != nil { + return err + } + if err := s.EndPointController.ApplyTo(&c.ComponentConfig.EndPointController); err != nil { + return err + } + if err := s.GarbageCollectorController.ApplyTo(&c.ComponentConfig.GarbageCollectorController); err != nil { + return err + } + if err := s.HPAController.ApplyTo(&c.ComponentConfig.HPAController); err != nil { + return err + } + if err := s.JobController.ApplyTo(&c.ComponentConfig.JobController); err != nil { + return err + } + if err := s.NamespaceController.ApplyTo(&c.ComponentConfig.NamespaceController); err != nil { + return err + } + if err := s.NodeIpamController.ApplyTo(&c.ComponentConfig.NodeIpamController); err != nil { + return err + } + if err := s.NodeLifecycleController.ApplyTo(&c.ComponentConfig.NodeLifecycleController); err != nil { + return err + } + if err := s.PersistentVolumeBinderController.ApplyTo(&c.ComponentConfig.PersistentVolumeBinderController); err != nil { + return err + } + if err := s.PodGCController.ApplyTo(&c.ComponentConfig.PodGCController); err != nil { + return err + } + if err := s.ReplicaSetController.ApplyTo(&c.ComponentConfig.ReplicaSetController); err != nil { + return err + } + if err := s.ReplicationController.ApplyTo(&c.ComponentConfig.ReplicationController); err != nil { + return err + } + if err := s.ResourceQuotaController.ApplyTo(&c.ComponentConfig.ResourceQuotaController); err != nil { + return err + } + if err := s.SAController.ApplyTo(&c.ComponentConfig.SAController); err != nil { + return err + } + if err := s.ServiceController.ApplyTo(&c.ComponentConfig.ServiceController); err != nil { + return err + } + if err := s.SecureServing.ApplyTo(&c.SecureServing); err != nil { + return err + } + if err := s.InsecureServing.ApplyTo(&c.InsecureServing); err != nil { + return err + } + if err := s.Authentication.ApplyTo(&c.Authentication, c.SecureServing, nil); err != nil { + return err + } + if err := s.Authorization.ApplyTo(&c.Authorization); err != nil { + return err + } + + // sync back to component config + // TODO: find more elegant way than synching back the values. + c.ComponentConfig.KubeCloudShared.Port = int32(s.InsecureServing.BindPort) + c.ComponentConfig.KubeCloudShared.Address = s.InsecureServing.BindAddress.String() + + var err error + c.Kubeconfig, err = clientcmd.BuildConfigFromFlags(s.Master, s.Kubeconfig) + if err != nil { + return err + } + c.Kubeconfig.ContentConfig.ContentType = s.GenericComponent.ContentType + c.Kubeconfig.QPS = s.GenericComponent.KubeAPIQPS + c.Kubeconfig.Burst = int(s.GenericComponent.KubeAPIBurst) + + c.Client, err = clientset.NewForConfig(restclient.AddUserAgent(c.Kubeconfig, userAgent)) + if err != nil { + return err + } + + c.LeaderElectionClient = clientset.NewForConfigOrDie(restclient.AddUserAgent(c.Kubeconfig, "leader-election")) + + c.EventRecorder = createRecorder(c.Client, userAgent) + + c.ComponentConfig.Controllers = s.Controllers + c.ComponentConfig.ExternalCloudVolumePlugin = s.ExternalCloudVolumePlugin return err } @@ -157,8 +379,38 @@ func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config) e func (s *KubeControllerManagerOptions) Validate(allControllers []string, disabledByDefaultControllers []string) error { var errs []error + errs = append(errs, s.CloudProvider.Validate()...) + errs = append(errs, s.Debugging.Validate()...) + errs = append(errs, s.GenericComponent.Validate()...) + errs = append(errs, s.KubeCloudShared.Validate()...) + errs = append(errs, s.AttachDetachController.Validate()...) + errs = append(errs, s.CSRSigningController.Validate()...) + errs = append(errs, s.DaemonSetController.Validate()...) + errs = append(errs, s.DeploymentController.Validate()...) + errs = append(errs, s.DeprecatedFlags.Validate()...) + errs = append(errs, s.EndPointController.Validate()...) + errs = append(errs, s.GarbageCollectorController.Validate()...) + errs = append(errs, s.HPAController.Validate()...) + errs = append(errs, s.JobController.Validate()...) + errs = append(errs, s.NamespaceController.Validate()...) + errs = append(errs, s.NodeIpamController.Validate()...) + errs = append(errs, s.NodeLifecycleController.Validate()...) + errs = append(errs, s.PersistentVolumeBinderController.Validate()...) + errs = append(errs, s.PodGCController.Validate()...) + errs = append(errs, s.ReplicaSetController.Validate()...) + errs = append(errs, s.ReplicationController.Validate()...) + errs = append(errs, s.ResourceQuotaController.Validate()...) + errs = append(errs, s.SAController.Validate()...) + errs = append(errs, s.ServiceController.Validate()...) + errs = append(errs, s.SecureServing.Validate()...) + errs = append(errs, s.InsecureServing.Validate()...) + errs = append(errs, s.Authentication.Validate()...) + errs = append(errs, s.Authorization.Validate()...) + + // TODO: validate component config, master and kubeconfig + allControllersSet := sets.NewString(allControllers...) - for _, controller := range s.Generic.ComponentConfig.Controllers { + for _, controller := range s.Controllers { if controller == "*" { continue } @@ -181,9 +433,16 @@ func (s KubeControllerManagerOptions) Config(allControllers []string, disabledBy } c := &kubecontrollerconfig.Config{} - if err := s.ApplyTo(c); err != nil { + if err := s.ApplyTo(c, "kube-controller-manager"); err != nil { return nil, err } return c, nil } + +func createRecorder(kubeClient kubernetes.Interface, userAgent string) record.EventRecorder { + eventBroadcaster := record.NewBroadcaster() + eventBroadcaster.StartLogging(glog.Infof) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) + return eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: userAgent}) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/options_test.go b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/options_test.go index 1b722d17d..769b35b1b 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/options_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-controller-manager/app/options/options_test.go @@ -34,7 +34,7 @@ import ( func TestAddFlags(t *testing.T) { f := pflag.NewFlagSet("addflagstest", pflag.ContinueOnError) - s := NewKubeControllerManagerOptions() + s, _ := NewKubeControllerManagerOptions() s.AddFlags(f, []string{""}, []string{""}) args := []string{ @@ -113,125 +113,165 @@ func TestAddFlags(t *testing.T) { f.Parse(args) // Sort GCIgnoredResources because it's built from a map, which means the // insertion order is random. - sort.Sort(sortedGCIgnoredResources(s.Generic.ComponentConfig.GCIgnoredResources)) + sort.Sort(sortedGCIgnoredResources(s.GarbageCollectorController.GCIgnoredResources)) expected := &KubeControllerManagerOptions{ - Generic: cmoptions.GenericControllerManagerOptions{ - ComponentConfig: componentconfig.KubeControllerManagerConfiguration{ - Port: 10252, // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config - Address: "0.0.0.0", // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config - AllocateNodeCIDRs: true, - CloudConfigFile: "/cloud-config", - CloudProvider: "gce", - ClusterCIDR: "1.2.3.4/24", - ClusterName: "k8s", - ConcurrentDeploymentSyncs: 10, - ConcurrentEndpointSyncs: 10, - ConcurrentGCSyncs: 30, - ConcurrentNamespaceSyncs: 20, - ConcurrentRSSyncs: 10, - ConcurrentResourceQuotaSyncs: 10, - ConcurrentServiceSyncs: 2, - ConcurrentSATokenSyncs: 10, - ConcurrentRCSyncs: 10, - ConfigureCloudRoutes: false, - EnableContentionProfiling: true, - ControllerStartInterval: metav1.Duration{Duration: 2 * time.Minute}, - ConcurrentDaemonSetSyncs: 2, - ConcurrentJobSyncs: 5, - DeletingPodsQps: 0.1, - EnableProfiling: false, - CIDRAllocatorType: "CloudAllocator", - NodeCIDRMaskSize: 48, - ResourceQuotaSyncPeriod: metav1.Duration{Duration: 10 * time.Minute}, - NamespaceSyncPeriod: metav1.Duration{Duration: 10 * time.Minute}, - PVClaimBinderSyncPeriod: metav1.Duration{Duration: 30 * time.Second}, - HorizontalPodAutoscalerSyncPeriod: metav1.Duration{Duration: 45 * time.Second}, - DeploymentControllerSyncPeriod: metav1.Duration{Duration: 45 * time.Second}, - MinResyncPeriod: metav1.Duration{Duration: 8 * time.Hour}, - RegisterRetryCount: 10, - RouteReconciliationPeriod: metav1.Duration{Duration: 30 * time.Second}, - PodEvictionTimeout: metav1.Duration{Duration: 2 * time.Minute}, - NodeMonitorGracePeriod: metav1.Duration{Duration: 30 * time.Second}, - NodeStartupGracePeriod: metav1.Duration{Duration: 30 * time.Second}, - NodeMonitorPeriod: metav1.Duration{Duration: 10 * time.Second}, - HorizontalPodAutoscalerUpscaleForbiddenWindow: metav1.Duration{Duration: 1 * time.Minute}, - HorizontalPodAutoscalerDownscaleForbiddenWindow: metav1.Duration{Duration: 2 * time.Minute}, - HorizontalPodAutoscalerTolerance: 0.1, - TerminatedPodGCThreshold: 12000, - VolumeConfiguration: componentconfig.VolumeConfiguration{ - EnableDynamicProvisioning: false, - EnableHostPathProvisioning: true, - FlexVolumePluginDir: "/flex-volume-plugin", - PersistentVolumeRecyclerConfiguration: componentconfig.PersistentVolumeRecyclerConfiguration{ - MaximumRetry: 3, - MinimumTimeoutNFS: 200, - IncrementTimeoutNFS: 45, - MinimumTimeoutHostPath: 45, - IncrementTimeoutHostPath: 45, - }, - }, - ContentType: "application/json", - KubeAPIQPS: 50.0, - KubeAPIBurst: 100, - LeaderElection: componentconfig.LeaderElectionConfiguration{ - ResourceLock: "configmap", - LeaderElect: false, - LeaseDuration: metav1.Duration{Duration: 30 * time.Second}, - RenewDeadline: metav1.Duration{Duration: 15 * time.Second}, - RetryPeriod: metav1.Duration{Duration: 5 * time.Second}, - }, - ClusterSigningCertFile: "/cluster-signing-cert", - ClusterSigningKeyFile: "/cluster-signing-key", - ServiceAccountKeyFile: "/service-account-private-key", - ClusterSigningDuration: metav1.Duration{Duration: 10 * time.Hour}, - EnableGarbageCollector: false, - GCIgnoredResources: []componentconfig.GroupResource{ - {Group: "extensions", Resource: "replicationcontrollers"}, - {Group: "", Resource: "bindings"}, - {Group: "", Resource: "componentstatuses"}, - {Group: "", Resource: "events"}, - {Group: "authentication.k8s.io", Resource: "tokenreviews"}, - {Group: "authorization.k8s.io", Resource: "subjectaccessreviews"}, - {Group: "authorization.k8s.io", Resource: "selfsubjectaccessreviews"}, - {Group: "authorization.k8s.io", Resource: "localsubjectaccessreviews"}, - {Group: "authorization.k8s.io", Resource: "selfsubjectrulesreviews"}, - {Group: "apiregistration.k8s.io", Resource: "apiservices"}, - {Group: "apiextensions.k8s.io", Resource: "customresourcedefinitions"}, - }, - NodeEvictionRate: 0.2, - SecondaryNodeEvictionRate: 0.05, - LargeClusterSizeThreshold: 100, - UnhealthyZoneThreshold: 0.6, - DisableAttachDetachReconcilerSync: true, - ReconcilerSyncLoopPeriod: metav1.Duration{Duration: 30 * time.Second}, - Controllers: []string{"foo", "bar"}, - EnableTaintManager: false, - HorizontalPodAutoscalerUseRESTClients: true, - UseServiceAccountCredentials: true, + CloudProvider: &cmoptions.CloudProviderOptions{ + Name: "gce", + CloudConfigFile: "/cloud-config", + }, + Debugging: &cmoptions.DebuggingOptions{ + EnableProfiling: false, + EnableContentionProfiling: true, + }, + GenericComponent: &cmoptions.GenericComponentConfigOptions{ + MinResyncPeriod: metav1.Duration{Duration: 8 * time.Hour}, + ContentType: "application/json", + KubeAPIQPS: 50.0, + KubeAPIBurst: 100, + ControllerStartInterval: metav1.Duration{Duration: 2 * time.Minute}, + LeaderElection: componentconfig.LeaderElectionConfiguration{ + ResourceLock: "configmap", + LeaderElect: false, + LeaseDuration: metav1.Duration{Duration: 30 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 15 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 5 * time.Second}, + }, + }, + KubeCloudShared: &cmoptions.KubeCloudSharedOptions{ + Port: 10252, // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config + AllocateNodeCIDRs: true, + Address: "0.0.0.0", // Note: InsecureServingOptions.ApplyTo will write the flag value back into the component config + UseServiceAccountCredentials: true, + RouteReconciliationPeriod: metav1.Duration{Duration: 30 * time.Second}, + NodeMonitorPeriod: metav1.Duration{Duration: 10 * time.Second}, + ClusterName: "k8s", + ClusterCIDR: "1.2.3.4/24", + AllocateNodeCIDRs: true, + CIDRAllocatorType: "CloudAllocator", + ConfigureCloudRoutes: false, + }, + AttachDetachController: &cmoptions.AttachDetachControllerOptions{ + ReconcilerSyncLoopPeriod: metav1.Duration{Duration: 30 * time.Second}, + DisableAttachDetachReconcilerSync: true, + }, + CSRSigningController: &cmoptions.CSRSigningControllerOptions{ + ClusterSigningCertFile: "/cluster-signing-cert", + ClusterSigningKeyFile: "/cluster-signing-key", + ClusterSigningDuration: metav1.Duration{Duration: 10 * time.Hour}, + }, + DaemonSetController: &cmoptions.DaemonSetControllerOptions{ + ConcurrentDaemonSetSyncs: 2, + }, + DeploymentController: &cmoptions.DeploymentControllerOptions{ + ConcurrentDeploymentSyncs: 10, + DeploymentControllerSyncPeriod: metav1.Duration{Duration: 45 * time.Second}, + }, + DeprecatedFlags: &cmoptions.DeprecatedControllerOptions{ + DeletingPodsQPS: 0.1, + RegisterRetryCount: 10, + }, + EndPointController: &cmoptions.EndPointControllerOptions{ + ConcurrentEndpointSyncs: 10, + }, + GarbageCollectorController: &cmoptions.GarbageCollectorControllerOptions{ + ConcurrentGCSyncs: 30, + GCIgnoredResources: []componentconfig.GroupResource{ + {Group: "extensions", Resource: "replicationcontrollers"}, + {Group: "", Resource: "bindings"}, + {Group: "", Resource: "componentstatuses"}, + {Group: "", Resource: "events"}, + {Group: "authentication.k8s.io", Resource: "tokenreviews"}, + {Group: "authorization.k8s.io", Resource: "subjectaccessreviews"}, + {Group: "authorization.k8s.io", Resource: "selfsubjectaccessreviews"}, + {Group: "authorization.k8s.io", Resource: "localsubjectaccessreviews"}, + {Group: "authorization.k8s.io", Resource: "selfsubjectrulesreviews"}, }, - SecureServing: &apiserveroptions.SecureServingOptions{ - BindPort: 10001, - BindAddress: net.ParseIP("192.168.4.21"), - ServerCert: apiserveroptions.GeneratableKeyCert{ - CertDirectory: "/a/b/c", - PairName: "kube-controller-manager", + EnableGarbageCollector: false, + }, + HPAController: &cmoptions.HPAControllerOptions{ + HorizontalPodAutoscalerSyncPeriod: metav1.Duration{Duration: 45 * time.Second}, + HorizontalPodAutoscalerUpscaleForbiddenWindow: metav1.Duration{Duration: 1 * time.Minute}, + HorizontalPodAutoscalerDownscaleForbiddenWindow: metav1.Duration{Duration: 2 * time.Minute}, + HorizontalPodAutoscalerTolerance: 0.1, + HorizontalPodAutoscalerUseRESTClients: true, + }, + JobController: &cmoptions.JobControllerOptions{ + ConcurrentJobSyncs: 5, + }, + NamespaceController: &cmoptions.NamespaceControllerOptions{ + NamespaceSyncPeriod: metav1.Duration{Duration: 10 * time.Minute}, + ConcurrentNamespaceSyncs: 20, + }, + NodeIpamController: &cmoptions.NodeIpamControllerOptions{ + NodeCIDRMaskSize: 48, + }, + NodeLifecycleController: &cmoptions.NodeLifecycleControllerOptions{ + EnableTaintManager: false, + NodeEvictionRate: 0.2, + SecondaryNodeEvictionRate: 0.05, + NodeMonitorGracePeriod: metav1.Duration{Duration: 30 * time.Second}, + NodeStartupGracePeriod: metav1.Duration{Duration: 30 * time.Second}, + PodEvictionTimeout: metav1.Duration{Duration: 2 * time.Minute}, + LargeClusterSizeThreshold: 100, + UnhealthyZoneThreshold: 0.6, + }, + PersistentVolumeBinderController: &cmoptions.PersistentVolumeBinderControllerOptions{ + PVClaimBinderSyncPeriod: metav1.Duration{Duration: 30 * time.Second}, + VolumeConfiguration: componentconfig.VolumeConfiguration{ + EnableDynamicProvisioning: false, + EnableHostPathProvisioning: true, + FlexVolumePluginDir: "/flex-volume-plugin", + PersistentVolumeRecyclerConfiguration: componentconfig.PersistentVolumeRecyclerConfiguration{ + MaximumRetry: 3, + MinimumTimeoutNFS: 200, + IncrementTimeoutNFS: 45, + MinimumTimeoutHostPath: 45, + IncrementTimeoutHostPath: 45, }, - HTTP2MaxStreamsPerConnection: 47, }, - InsecureServing: &cmoptions.InsecureServingOptions{ - BindAddress: net.ParseIP("192.168.4.10"), - BindPort: int(10000), - BindNetwork: "tcp", + }, + PodGCController: &cmoptions.PodGCControllerOptions{ + TerminatedPodGCThreshold: 12000, + }, + ReplicaSetController: &cmoptions.ReplicaSetControllerOptions{ + ConcurrentRSSyncs: 10, + }, + ReplicationController: &cmoptions.ReplicationControllerOptions{ + ConcurrentRCSyncs: 10, + }, + ResourceQuotaController: &cmoptions.ResourceQuotaControllerOptions{ + ResourceQuotaSyncPeriod: metav1.Duration{Duration: 10 * time.Minute}, + ConcurrentResourceQuotaSyncs: 10, + }, + SAController: &cmoptions.SAControllerOptions{ + ServiceAccountKeyFile: "/service-account-private-key", + ConcurrentSATokenSyncs: 10, + }, + ServiceController: &cmoptions.ServiceControllerOptions{ + ConcurrentServiceSyncs: 2, + }, + Controllers: []string{"foo", "bar"}, + SecureServing: &apiserveroptions.SecureServingOptions{ + BindPort: 10001, + BindAddress: net.ParseIP("192.168.4.21"), + ServerCert: apiserveroptions.GeneratableKeyCert{ + CertDirectory: "/a/b/c", + PairName: "kube-controller-manager", }, - Kubeconfig: "/kubeconfig", - Master: "192.168.4.20", + HTTP2MaxStreamsPerConnection: 47, + }, + InsecureServing: &cmoptions.InsecureServingOptions{ + BindAddress: net.ParseIP("192.168.4.10"), + BindPort: int(10000), + BindNetwork: "tcp", }, + Kubeconfig: "/kubeconfig", + Master: "192.168.4.20", } // Sort GCIgnoredResources because it's built from a map, which means the // insertion order is random. - sort.Sort(sortedGCIgnoredResources(expected.Generic.ComponentConfig.GCIgnoredResources)) + sort.Sort(sortedGCIgnoredResources(expected.GarbageCollectorController.GCIgnoredResources)) if !reflect.DeepEqual(expected, s) { t.Errorf("Got different run options than expected.\nDifference detected on:\n%s", diff.ObjectReflectDiff(expected, s)) diff --git a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/BUILD index 3ae5ab8f0..295102156 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/BUILD @@ -64,7 +64,6 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubelet/qos:go_default_library", "//pkg/master/ports:go_default_library", "//pkg/proxy:go_default_library", @@ -115,70 +114,60 @@ go_library( "//vendor/k8s.io/utils/exec:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:android": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:darwin": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:dragonfly": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:freebsd": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:linux": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:nacl": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:netbsd": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:openbsd": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:plan9": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], "@io_bazel_rules_go//go/platform:solaris": [ - "//pkg/features:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/util/dbus:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", @@ -236,7 +225,6 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", - "//pkg/features:go_default_library", "//pkg/proxy/apis/kubeproxyconfig:go_default_library", "//pkg/util/configz:go_default_library", "//pkg/util/pointer:go_default_library", @@ -247,52 +235,42 @@ go_test( "@io_bazel_rules_go//go/platform:android": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:darwin": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:dragonfly": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:freebsd": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:linux": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:nacl": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:netbsd": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:openbsd": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:plan9": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "@io_bazel_rules_go//go/platform:solaris": [ "//pkg/proxy/ipvs:go_default_library", "//pkg/util/iptables:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "//conditions:default": [], }), diff --git a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server.go b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server.go index 7b42e6616..6161f15d9 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server.go @@ -51,7 +51,6 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/proxy" @@ -141,7 +140,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.config.ResourceContainer, "resource-container", o.config.ResourceContainer, "Absolute name of the resource-only container to create and run the Kube-proxy in (Default: /kube-proxy).") fs.MarkDeprecated("resource-container", "This feature will be removed in a later release.") fs.StringVar(&o.config.ClientConnection.KubeConfigFile, "kubeconfig", o.config.ClientConnection.KubeConfigFile, "Path to kubeconfig file with authorization information (the master location is set by the master flag).") - fs.Var(componentconfig.PortRangeVar{Val: &o.config.PortRange}, "proxy-port-range", "Range of host ports (beginPort-endPort, inclusive) that may be consumed in order to proxy service traffic. If unspecified (0-0) then ports will be randomly chosen.") + fs.Var(componentconfig.PortRangeVar{Val: &o.config.PortRange}, "proxy-port-range", "Range of host ports (beginPort-endPort, single port or beginPort+offset, inclusive) that may be consumed in order to proxy service traffic. If (unspecified, 0, or 0-0) then ports will be randomly chosen.") fs.StringVar(&o.config.HostnameOverride, "hostname-override", o.config.HostnameOverride, "If non-empty, will use this string as identification instead of the actual hostname.") fs.Var(&o.config.Mode, "proxy-mode", "Which proxy mode to use: 'userspace' (older) or 'iptables' (faster) or 'ipvs' (experimental). If blank, use the best-available proxy (currently iptables). If the iptables proxy is selected, regardless of how, but the system's kernel or iptables versions are insufficient, this always falls back to the userspace proxy.") fs.Int32Var(o.config.IPTables.MasqueradeBit, "iptables-masquerade-bit", utilpointer.Int32PtrDerefOr(o.config.IPTables.MasqueradeBit, 14), "If using the pure iptables proxy, the bit of the fwmark space to mark packets requiring SNAT with. Must be within the range [0, 31].") @@ -149,6 +148,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { fs.DurationVar(&o.config.IPTables.MinSyncPeriod.Duration, "iptables-min-sync-period", o.config.IPTables.MinSyncPeriod.Duration, "The minimum interval of how often the iptables rules can be refreshed as endpoints and services change (e.g. '5s', '1m', '2h22m').") fs.DurationVar(&o.config.IPVS.SyncPeriod.Duration, "ipvs-sync-period", o.config.IPVS.SyncPeriod.Duration, "The maximum interval of how often ipvs rules are refreshed (e.g. '5s', '1m', '2h22m'). Must be greater than 0.") fs.DurationVar(&o.config.IPVS.MinSyncPeriod.Duration, "ipvs-min-sync-period", o.config.IPVS.MinSyncPeriod.Duration, "The minimum interval of how often the ipvs rules can be refreshed as endpoints and services change (e.g. '5s', '1m', '2h22m').") + fs.StringSliceVar(&o.config.IPVS.ExcludeCIDRs, "ipvs-exclude-cidrs", o.config.IPVS.ExcludeCIDRs, "A comma-separated list of CIDR's which the ipvs proxier should not touch when cleaning up IPVS rules.") fs.DurationVar(&o.config.ConfigSyncPeriod.Duration, "config-sync-period", o.config.ConfigSyncPeriod.Duration, "How often configuration from the apiserver is refreshed. Must be greater than 0.") fs.BoolVar(&o.config.IPTables.MasqueradeAll, "masquerade-all", o.config.IPTables.MasqueradeAll, "If using the pure iptables proxy, SNAT all traffic sent via Service cluster IPs (this not commonly needed)") fs.StringVar(&o.config.ClusterCIDR, "cluster-cidr", o.config.ClusterCIDR, "The CIDR range of pods in the cluster. When configured, traffic sent to a Service cluster IP from outside this range will be masqueraded and traffic sent from pods to an external LoadBalancer IP will be directed to the respective cluster IP instead") @@ -352,9 +352,13 @@ with the apiserver API to configure the proxy.`, glog.Fatalf("failed OS init: %v", err) } - cmdutil.CheckErr(opts.Complete()) - cmdutil.CheckErr(opts.Validate(args)) - cmdutil.CheckErr(opts.Run()) + if err := opts.Complete(); err != nil { + glog.Fatalf("failed complete: %v", err) + } + if err := opts.Validate(args); err != nil { + glog.Fatalf("failed validate: %v", err) + } + glog.Fatal(opts.Run()) }, } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others.go b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others.go index 46b1acbe2..754d654f1 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others.go @@ -30,9 +30,7 @@ import ( "k8s.io/apimachinery/pkg/types" utilnet "k8s.io/apimachinery/pkg/util/net" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/proxy" proxyconfigapi "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" proxyconfig "k8s.io/kubernetes/pkg/proxy/config" @@ -92,9 +90,11 @@ func newProxyServer( dbus = utildbus.New() iptInterface = utiliptables.New(execer, dbus, protocol) - ipvsInterface = utilipvs.New(execer) kernelHandler = ipvs.NewLinuxKernelHandler() ipsetInterface = utilipset.New(execer) + if canUse, _ := ipvs.CanUseIPVSProxier(kernelHandler, ipsetInterface); canUse { + ipvsInterface = utilipvs.New(execer) + } // We omit creation of pretty much everything if we run in cleanup mode if cleanupAndExit { @@ -189,6 +189,7 @@ func newProxyServer( execer, config.IPVS.SyncPeriod.Duration, config.IPVS.MinSyncPeriod.Duration, + config.IPVS.ExcludeCIDRs, config.IPTables.MasqueradeAll, int(*config.IPTables.MasqueradeBit), config.ClusterCIDR, @@ -275,21 +276,13 @@ func newProxyServer( } func getProxyMode(proxyMode string, iptver iptables.IPTablesVersioner, khandle ipvs.KernelHandler, ipsetver ipvs.IPSetVersioner, kcompat iptables.KernelCompatTester) string { - if proxyMode == proxyModeUserspace { + switch proxyMode { + case proxyModeUserspace: return proxyModeUserspace - } - - if len(proxyMode) > 0 && proxyMode == proxyModeIPTables { + case proxyModeIPTables: return tryIPTablesProxy(iptver, kcompat) - } - - if utilfeature.DefaultFeatureGate.Enabled(features.SupportIPVSProxyMode) { - if proxyMode == proxyModeIPVS { - return tryIPVSProxy(iptver, khandle, ipsetver, kcompat) - } else { - glog.Warningf("Can't use ipvs proxier, trying iptables proxier") - return tryIPTablesProxy(iptver, kcompat) - } + case proxyModeIPVS: + return tryIPVSProxy(iptver, khandle, ipsetver, kcompat) } glog.Warningf("Flag proxy-mode=%q unknown, assuming iptables proxy", proxyMode) return tryIPTablesProxy(iptver, kcompat) diff --git a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others_test.go b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others_test.go index 01cc00dc1..f439f6186 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others_test.go @@ -22,7 +22,6 @@ import ( "fmt" "testing" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/proxy/ipvs" "k8s.io/kubernetes/pkg/util/iptables" ) @@ -88,114 +87,15 @@ func Test_getProxyMode(t *testing.T) { kernelCompat: true, expected: proxyModeIPTables, }, - { // specify ipvs, feature gateway disabled, iptables version ok, kernel is compatible - flag: "ipvs", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, - { // specify ipvs, feature gateway disabled, iptables version too low - flag: "ipvs", - iptablesVersion: "0.0.0", - expected: proxyModeUserspace, - }, - { // specify ipvs, feature gateway disabled, iptables version ok, kernel is not compatible - flag: "ipvs", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: false, - expected: proxyModeUserspace, - }, - } - for i, c := range cases { - versioner := &fakeIPTablesVersioner{c.iptablesVersion, c.iptablesError} - kcompater := &fakeKernelCompatTester{c.kernelCompat} - ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError} - khandler := &fakeKernelHandler{c.kmods} - r := getProxyMode(c.flag, versioner, khandler, ipsetver, kcompater) - if r != c.expected { - t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r) - } - } -} - -// This is a coarse test, but it offers some modicum of confidence as the code is evolved. -func Test_getProxyModeEnableFeatureGateway(t *testing.T) { - // enable IPVS feature gateway - utilfeature.DefaultFeatureGate.Set("SupportIPVSProxyMode=true") - - var cases = []struct { - flag string - iptablesVersion string - ipsetVersion string - kernelCompat bool - iptablesError error - ipsetError error - mods []string - expected string - }{ - { // flag says userspace - flag: "userspace", - expected: proxyModeUserspace, - }, - { // flag says iptables, error detecting version - flag: "iptables", - iptablesError: fmt.Errorf("oops!"), - expected: proxyModeUserspace, - }, - { // flag says iptables, version too low - flag: "iptables", - iptablesVersion: "0.0.0", - expected: proxyModeUserspace, - }, - { // flag says iptables, version ok, kernel not compatible - flag: "iptables", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: false, - expected: proxyModeUserspace, - }, - { // flag says iptables, version ok, kernel is compatible - flag: "iptables", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, - { // detect, error - flag: "", - iptablesError: fmt.Errorf("oops!"), - expected: proxyModeUserspace, - }, - { // detect, version too low - flag: "", - iptablesVersion: "0.0.0", - expected: proxyModeUserspace, - }, - { // detect, version ok, kernel not compatible - flag: "", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: false, - expected: proxyModeUserspace, - }, - { // detect, version ok, kernel is compatible - flag: "", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, - { // detect, version ok, kernel is compatible - flag: "", - iptablesVersion: iptables.MinCheckVersion, - kernelCompat: true, - expected: proxyModeIPTables, - }, { // flag says ipvs, ipset version ok, kernel modules installed flag: "ipvs", - mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, + kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, ipsetVersion: ipvs.MinIPSetCheckVersion, expected: proxyModeIPVS, }, { // flag says ipvs, ipset version too low, fallback on iptables mode flag: "ipvs", - mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, + kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, ipsetVersion: "0.0", iptablesVersion: iptables.MinCheckVersion, kernelCompat: true, @@ -203,7 +103,7 @@ func Test_getProxyModeEnableFeatureGateway(t *testing.T) { }, { // flag says ipvs, bad ipset version, fallback on iptables mode flag: "ipvs", - mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, + kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, ipsetVersion: "a.b.c", iptablesVersion: iptables.MinCheckVersion, kernelCompat: true, @@ -211,7 +111,7 @@ func Test_getProxyModeEnableFeatureGateway(t *testing.T) { }, { // flag says ipvs, required kernel modules are not installed, fallback on iptables mode flag: "ipvs", - mods: []string{"foo", "bar", "baz"}, + kmods: []string{"foo", "bar", "baz"}, ipsetVersion: ipvs.MinIPSetCheckVersion, iptablesVersion: iptables.MinCheckVersion, kernelCompat: true, @@ -219,7 +119,7 @@ func Test_getProxyModeEnableFeatureGateway(t *testing.T) { }, { // flag says ipvs, required kernel modules are not installed, iptables version too old, fallback on userspace mode flag: "ipvs", - mods: []string{"foo", "bar", "baz"}, + kmods: []string{"foo", "bar", "baz"}, ipsetVersion: ipvs.MinIPSetCheckVersion, iptablesVersion: "0.0.0", kernelCompat: true, @@ -227,7 +127,7 @@ func Test_getProxyModeEnableFeatureGateway(t *testing.T) { }, { // flag says ipvs, ipset version too low, iptables version too old, kernel not compatible, fallback on userspace mode flag: "ipvs", - mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, + kmods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"}, ipsetVersion: "0.0", iptablesVersion: iptables.MinCheckVersion, kernelCompat: false, @@ -238,8 +138,8 @@ func Test_getProxyModeEnableFeatureGateway(t *testing.T) { versioner := &fakeIPTablesVersioner{c.iptablesVersion, c.iptablesError} kcompater := &fakeKernelCompatTester{c.kernelCompat} ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError} - khandle := &fakeKernelHandler{c.mods} - r := getProxyMode(c.flag, versioner, khandle, ipsetver, kcompater) + khandler := &fakeKernelHandler{c.kmods} + r := getProxyMode(c.flag, versioner, khandler, ipsetver, kcompater) if r != c.expected { t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r) } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_test.go b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_test.go index 8a451e988..1ee6fdded 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_test.go @@ -29,7 +29,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/diff" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" "k8s.io/kubernetes/pkg/util/configz" utilpointer "k8s.io/kubernetes/pkg/util/pointer" @@ -189,8 +188,6 @@ conntrack: min: 1 tcpCloseWaitTimeout: 10s tcpEstablishedTimeout: 20s -featureGates: - SupportIPVSProxyMode: true healthzBindAddress: "%s" hostnameOverride: "foo" iptables: @@ -201,6 +198,9 @@ iptables: ipvs: minSyncPeriod: 10s syncPeriod: 60s + excludeCIDRs: + - "10.20.30.40/16" + - "fd00:1::0/64" kind: KubeProxyConfiguration metricsBindAddress: "%s" mode: "%s" @@ -304,7 +304,7 @@ nodePortAddresses: TCPCloseWaitTimeout: &metav1.Duration{Duration: 10 * time.Second}, TCPEstablishedTimeout: &metav1.Duration{Duration: 20 * time.Second}, }, - FeatureGates: map[string]bool{string(features.SupportIPVSProxyMode): true}, + FeatureGates: map[string]bool{}, HealthzBindAddress: tc.healthzBindAddress, HostnameOverride: "foo", IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ @@ -316,6 +316,7 @@ nodePortAddresses: IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ MinSyncPeriod: metav1.Duration{Duration: 10 * time.Second}, SyncPeriod: metav1.Duration{Duration: 60 * time.Second}, + ExcludeCIDRs: []string{"10.20.30.40/16", "fd00:1::0/64"}, }, MetricsBindAddress: tc.metricsBindAddress, Mode: kubeproxyconfig.ProxyMode(tc.mode), diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/OWNERS b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/OWNERS index d2792efd5..fe768eadb 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/OWNERS +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/OWNERS @@ -2,3 +2,5 @@ approvers: - sig-scheduling-maintainers reviewers: - sig-scheduling +labels: +- sig/scheduling diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/BUILD index 98b42fbff..a98dc3091 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/BUILD @@ -10,19 +10,18 @@ go_library( srcs = ["server.go"], importpath = "k8s.io/kubernetes/cmd/kube-scheduler/app", deps = [ + "//cmd/kube-scheduler/app/config:go_default_library", + "//cmd/kube-scheduler/app/options:go_default_library", "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/componentconfig:go_default_library", - "//pkg/apis/componentconfig/v1alpha1:go_default_library", - "//pkg/client/leaderelectionconfig:go_default_library", "//pkg/controller:go_default_library", "//pkg/features:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/master/ports:go_default_library", "//pkg/scheduler:go_default_library", "//pkg/scheduler/algorithmprovider:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/api/latest:go_default_library", "//pkg/scheduler/factory:go_default_library", + "//pkg/scheduler/metrics:go_default_library", "//pkg/util/configz:go_default_library", "//pkg/util/flag:go_default_library", "//pkg/version:go_default_library", @@ -30,29 +29,22 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", - "//vendor/github.com/spf13/pflag:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", + "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/filters:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/mux:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/routes:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//vendor/k8s.io/client-go/informers:go_default_library", - "//vendor/k8s.io/client-go/informers/core/v1:go_default_library", "//vendor/k8s.io/client-go/informers/storage/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//vendor/k8s.io/client-go/tools/leaderelection:go_default_library", - "//vendor/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library", - "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) @@ -65,6 +57,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//cmd/kube-scheduler/app/config:all-srcs", + "//cmd/kube-scheduler/app/options:all-srcs", + ], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/config/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/config/BUILD new file mode 100644 index 000000000..3ebc3a80c --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/config/BUILD @@ -0,0 +1,33 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["config.go"], + importpath = "k8s.io/kubernetes/cmd/kube-scheduler/app/config", + visibility = ["//visibility:public"], + deps = [ + "//cmd/controller-manager/app:go_default_library", + "//pkg/apis/componentconfig:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/informers/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/tools/leaderelection:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/config/config.go b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/config/config.go new file mode 100644 index 000000000..e57f9c224 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/config/config.go @@ -0,0 +1,75 @@ +/* +Copyright 2018 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 config + +import ( + apiserver "k8s.io/apiserver/pkg/server" + "k8s.io/client-go/informers" + coreinformers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes" + v1core "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/leaderelection" + "k8s.io/client-go/tools/record" + "k8s.io/kubernetes/cmd/controller-manager/app" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// Config has all the context to run a Scheduler +type Config struct { + // config is the scheduler server's configuration object. + ComponentConfig componentconfig.KubeSchedulerConfiguration + + InsecureServing *app.InsecureServingInfo // nil will disable serving on an insecure port + InsecureMetricsServing *app.InsecureServingInfo // non-nil if metrics should be served independently + Authentication apiserver.AuthenticationInfo + Authorization apiserver.AuthorizationInfo + SecureServing *apiserver.SecureServingInfo + + Client clientset.Interface + InformerFactory informers.SharedInformerFactory + PodInformer coreinformers.PodInformer + EventClient v1core.EventsGetter + Recorder record.EventRecorder + Broadcaster record.EventBroadcaster + + // LeaderElection is optional. + LeaderElection *leaderelection.LeaderElectionConfig +} + +type completedConfig struct { + *Config +} + +// CompletedConfig same as Config, just to swap private object. +type CompletedConfig struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *completedConfig +} + +// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. +func (c *Config) Complete() CompletedConfig { + cc := completedConfig{c} + + if c.InsecureServing != nil { + c.InsecureServing.Name = "healthz" + } + if c.InsecureMetricsServing != nil { + c.InsecureMetricsServing.Name = "metrics" + } + + return CompletedConfig{&cc} +} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/BUILD new file mode 100644 index 000000000..d44dddd46 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/BUILD @@ -0,0 +1,70 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "configfile.go", + "deprecated.go", + "insecure_serving.go", + "options.go", + ], + importpath = "k8s.io/kubernetes/cmd/kube-scheduler/app/options", + visibility = ["//visibility:public"], + deps = [ + "//cmd/controller-manager/app/options:go_default_library", + "//cmd/kube-scheduler/app/config:go_default_library", + "//pkg/api/legacyscheme:go_default_library", + "//pkg/apis/componentconfig:go_default_library", + "//pkg/apis/componentconfig/v1alpha1:go_default_library", + "//pkg/client/leaderelectionconfig:go_default_library", + "//pkg/scheduler/factory:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", + "//vendor/k8s.io/client-go/tools/leaderelection:go_default_library", + "//vendor/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = [ + "insecure_serving_test.go", + "options_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//cmd/controller-manager/app/options:go_default_library", + "//cmd/kube-scheduler/app/config:go_default_library", + "//pkg/apis/componentconfig:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/rand:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/configfile.go b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/configfile.go new file mode 100644 index 000000000..75d62a52e --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/configfile.go @@ -0,0 +1,89 @@ +/* +Copyright 2018 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 options + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/kubernetes/pkg/apis/componentconfig" + componentconfigv1alpha1 "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" +) + +var ( + configScheme = runtime.NewScheme() + configCodecs = serializer.NewCodecFactory(configScheme) +) + +func init() { + componentconfig.AddToScheme(configScheme) + componentconfigv1alpha1.AddToScheme(configScheme) +} + +func loadConfigFromFile(file string) (*componentconfig.KubeSchedulerConfiguration, error) { + data, err := ioutil.ReadFile(file) + if err != nil { + return nil, err + } + + return loadConfig(data) +} + +func loadConfig(data []byte) (*componentconfig.KubeSchedulerConfiguration, error) { + configObj, gvk, err := configCodecs.UniversalDecoder().Decode(data, nil, nil) + if err != nil { + return nil, err + } + config, ok := configObj.(*componentconfig.KubeSchedulerConfiguration) + if !ok { + return nil, fmt.Errorf("got unexpected config type: %v", gvk) + } + return config, nil +} + +// WriteConfigFile writes the config into the given file name as YAML. +func WriteConfigFile(fileName string, cfg *componentconfig.KubeSchedulerConfiguration) error { + var encoder runtime.Encoder + mediaTypes := configCodecs.SupportedMediaTypes() + for _, info := range mediaTypes { + if info.MediaType == "application/yaml" { + encoder = info.Serializer + break + } + } + if encoder == nil { + return errors.New("unable to locate yaml encoder") + } + encoder = json.NewYAMLSerializer(json.DefaultMetaFactory, configScheme, configScheme) + encoder = configCodecs.EncoderForVersion(encoder, componentconfigv1alpha1.SchemeGroupVersion) + + configFile, err := os.Create(fileName) + if err != nil { + return err + } + defer configFile.Close() + if err := encoder.Encode(cfg, configFile); err != nil { + return err + } + + return nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/deprecated.go b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/deprecated.go new file mode 100644 index 000000000..4a772d3c7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/deprecated.go @@ -0,0 +1,116 @@ +/* +Copyright 2018 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 options + +import ( + "fmt" + + "github.com/spf13/pflag" + + "k8s.io/kubernetes/pkg/apis/componentconfig" + "k8s.io/kubernetes/pkg/scheduler/factory" +) + +// DeprecatedOptions contains deprecated options and their flags. +// TODO remove these fields once the deprecated flags are removed. +type DeprecatedOptions struct { + // The fields below here are placeholders for flags that can't be directly + // mapped into componentconfig.KubeSchedulerConfiguration. + PolicyConfigFile string + PolicyConfigMapName string + PolicyConfigMapNamespace string + UseLegacyPolicyConfig bool + AlgorithmProvider string +} + +// AddFlags adds flags for the deprecated options. +func (o *DeprecatedOptions) AddFlags(fs *pflag.FlagSet, cfg *componentconfig.KubeSchedulerConfiguration) { + if o == nil { + return + } + + // TODO: unify deprecation mechanism, string prefix or MarkDeprecated (the latter hides the flag. We also don't want that). + + fs.StringVar(&o.AlgorithmProvider, "algorithm-provider", o.AlgorithmProvider, "DEPRECATED: the scheduling algorithm provider to use, one of: "+factory.ListAlgorithmProviders()) + fs.StringVar(&o.PolicyConfigFile, "policy-config-file", o.PolicyConfigFile, "DEPRECATED: file with scheduler policy configuration. This file is used if policy ConfigMap is not provided or --use-legacy-policy-config=true") + usage := fmt.Sprintf("DEPRECATED: name of the ConfigMap object that contains scheduler's policy configuration. It must exist in the system namespace before scheduler initialization if --use-legacy-policy-config=false. The config must be provided as the value of an element in 'Data' map with the key='%v'", componentconfig.SchedulerPolicyConfigMapKey) + fs.StringVar(&o.PolicyConfigMapName, "policy-configmap", o.PolicyConfigMapName, usage) + fs.StringVar(&o.PolicyConfigMapNamespace, "policy-configmap-namespace", o.PolicyConfigMapNamespace, "DEPRECATED: the namespace where policy ConfigMap is located. The kube-system namespace will be used if this is not provided or is empty.") + fs.BoolVar(&o.UseLegacyPolicyConfig, "use-legacy-policy-config", o.UseLegacyPolicyConfig, "DEPRECATED: when set to true, scheduler will ignore policy ConfigMap and uses policy config file") + + fs.BoolVar(&cfg.EnableProfiling, "profiling", cfg.EnableProfiling, "DEPRECATED: enable profiling via web interface host:port/debug/pprof/") + fs.BoolVar(&cfg.EnableContentionProfiling, "contention-profiling", cfg.EnableContentionProfiling, "DEPRECATED: enable lock contention profiling, if profiling is enabled") + fs.StringVar(&cfg.ClientConnection.KubeConfigFile, "kubeconfig", cfg.ClientConnection.KubeConfigFile, "DEPRECATED: path to kubeconfig file with authorization and master location information.") + fs.StringVar(&cfg.ClientConnection.ContentType, "kube-api-content-type", cfg.ClientConnection.ContentType, "DEPRECATED: content type of requests sent to apiserver.") + fs.Float32Var(&cfg.ClientConnection.QPS, "kube-api-qps", cfg.ClientConnection.QPS, "DEPRECATED: QPS to use while talking with kubernetes apiserver") + fs.Int32Var(&cfg.ClientConnection.Burst, "kube-api-burst", cfg.ClientConnection.Burst, "DEPRECATED: burst to use while talking with kubernetes apiserver") + fs.StringVar(&cfg.SchedulerName, "scheduler-name", cfg.SchedulerName, "DEPRECATED: name of the scheduler, used to select which pods will be processed by this scheduler, based on pod's \"spec.schedulerName\".") + fs.StringVar(&cfg.LeaderElection.LockObjectNamespace, "lock-object-namespace", cfg.LeaderElection.LockObjectNamespace, "DEPRECATED: define the namespace of the lock object.") + fs.StringVar(&cfg.LeaderElection.LockObjectName, "lock-object-name", cfg.LeaderElection.LockObjectName, "DEPRECATED: define the name of the lock object.") + + fs.Int32Var(&cfg.HardPodAffinitySymmetricWeight, "hard-pod-affinity-symmetric-weight", cfg.HardPodAffinitySymmetricWeight, + "RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule corresponding "+ + "to every RequiredDuringScheduling affinity rule. --hard-pod-affinity-symmetric-weight represents the weight of implicit PreferredDuringScheduling affinity rule.") + fs.MarkDeprecated("hard-pod-affinity-symmetric-weight", "This option was moved to the policy configuration file") + fs.StringVar(&cfg.FailureDomains, "failure-domains", cfg.FailureDomains, "Indicate the \"all topologies\" set for an empty topologyKey when it's used for PreferredDuringScheduling pod anti-affinity.") + fs.MarkDeprecated("failure-domains", "Doesn't have any effect. Will be removed in future version.") +} + +// Validate validates the deprecated scheduler options. +func (o *DeprecatedOptions) Validate() []error { + if o == nil { + return nil + } + return nil +} + +// ApplyTo sets cfg.AlgorithmSource from flags passed on the command line in the following precedence order: +// +// 1. --use-legacy-policy-config to use a policy file. +// 2. --policy-configmap to use a policy config map value. +// 3. --algorithm-provider to use a named algorithm provider. +func (o *DeprecatedOptions) ApplyTo(cfg *componentconfig.KubeSchedulerConfiguration) error { + if o == nil { + return nil + } + + switch { + case o.UseLegacyPolicyConfig || (len(o.PolicyConfigFile) > 0 && o.PolicyConfigMapName == ""): + cfg.AlgorithmSource = componentconfig.SchedulerAlgorithmSource{ + Policy: &componentconfig.SchedulerPolicySource{ + File: &componentconfig.SchedulerPolicyFileSource{ + Path: o.PolicyConfigFile, + }, + }, + } + case len(o.PolicyConfigMapName) > 0: + cfg.AlgorithmSource = componentconfig.SchedulerAlgorithmSource{ + Policy: &componentconfig.SchedulerPolicySource{ + ConfigMap: &componentconfig.SchedulerPolicyConfigMapSource{ + Name: o.PolicyConfigMapName, + Namespace: o.PolicyConfigMapNamespace, + }, + }, + } + case len(o.AlgorithmProvider) > 0: + cfg.AlgorithmSource = componentconfig.SchedulerAlgorithmSource{ + Provider: &o.AlgorithmProvider, + } + } + + return nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/insecure_serving.go b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/insecure_serving.go new file mode 100644 index 000000000..1ae913a59 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/insecure_serving.go @@ -0,0 +1,164 @@ +/* +Copyright 2018 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 options + +import ( + "fmt" + "net" + "strconv" + + "github.com/spf13/pflag" + + controlleroptions "k8s.io/kubernetes/cmd/controller-manager/app/options" + schedulerappconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +// CombinedInsecureServingOptions sets up up to two insecure listeners for healthz and metrics. The flags +// override the ComponentConfig and InsecureServingOptions values for both. +type CombinedInsecureServingOptions struct { + Healthz *controlleroptions.InsecureServingOptions + Metrics *controlleroptions.InsecureServingOptions + + BindPort int // overrides the structs above on ApplyTo, ignored on ApplyToFromLoadedConfig + BindAddress string // overrides the structs above on ApplyTo, ignored on ApplyToFromLoadedConfig +} + +// AddFlags adds flags for the insecure serving options. +func (o *CombinedInsecureServingOptions) AddFlags(fs *pflag.FlagSet) { + if o == nil { + return + } + + fs.StringVar(&o.BindAddress, "address", o.BindAddress, "DEPRECATED: the IP address on which to listen for the --port port (set to 0.0.0.0 for all IPv4 interfaces and :: for all IPv6 interfaces). See --bind-address instead.") + // MarkDeprecated hides the flag from the help. We don't want that: + // fs.MarkDeprecated("address", "see --bind-address instead.") + fs.IntVar(&o.BindPort, "port", o.BindPort, "DEPRECATED: the port on which to serve HTTP insecurely without authentication and authorization. If 0, don't serve HTTPS at all. See --secure-port instead.") + // MarkDeprecated hides the flag from the help. We don't want that: + // fs.MarkDeprecated("port", "see --secure-port instead.") +} + +func (o *CombinedInsecureServingOptions) applyTo(c *schedulerappconfig.Config, componentConfig *componentconfig.KubeSchedulerConfiguration) error { + if err := updateAddressFromInsecureServingOptions(&componentConfig.HealthzBindAddress, o.Healthz); err != nil { + return err + } + if err := updateAddressFromInsecureServingOptions(&componentConfig.MetricsBindAddress, o.Metrics); err != nil { + return err + } + + if err := o.Healthz.ApplyTo(&c.InsecureServing); err != nil { + return err + } + if o.Metrics != nil && (c.ComponentConfig.MetricsBindAddress != c.ComponentConfig.HealthzBindAddress || o.Healthz == nil) { + if err := o.Metrics.ApplyTo(&c.InsecureMetricsServing); err != nil { + return err + } + } + + return nil +} + +// ApplyTo applies the insecure serving options to the given scheduler app configuration, and updates the componentConfig. +func (o *CombinedInsecureServingOptions) ApplyTo(c *schedulerappconfig.Config, componentConfig *componentconfig.KubeSchedulerConfiguration) error { + if o == nil { + componentConfig.HealthzBindAddress = "" + componentConfig.MetricsBindAddress = "" + return nil + } + + if o.Healthz != nil { + o.Healthz.BindPort = o.BindPort + o.Healthz.BindAddress = net.ParseIP(o.BindAddress) + } + if o.Metrics != nil { + o.Metrics.BindPort = o.BindPort + o.Metrics.BindAddress = net.ParseIP(o.BindAddress) + } + + return o.applyTo(c, componentConfig) +} + +// ApplyToFromLoadedConfig updates the insecure serving options from the component config and then appies it to the given scheduler app configuration. +func (o *CombinedInsecureServingOptions) ApplyToFromLoadedConfig(c *schedulerappconfig.Config, componentConfig *componentconfig.KubeSchedulerConfiguration) error { + if o == nil { + return nil + } + + if err := updateInsecureServingOptionsFromAddress(o.Healthz, componentConfig.HealthzBindAddress); err != nil { + return fmt.Errorf("invalid healthz address: %v", err) + } + if err := updateInsecureServingOptionsFromAddress(o.Metrics, componentConfig.MetricsBindAddress); err != nil { + return fmt.Errorf("invalid metrics address: %v", err) + } + + return o.applyTo(c, componentConfig) +} + +func updateAddressFromInsecureServingOptions(addr *string, is *controlleroptions.InsecureServingOptions) error { + if is == nil { + *addr = "" + } else { + if is.Listener != nil { + *addr = is.Listener.Addr().String() + } else if is.BindPort == 0 { + *addr = "" + } else { + *addr = net.JoinHostPort(is.BindAddress.String(), strconv.Itoa(is.BindPort)) + } + } + + return nil +} + +func updateInsecureServingOptionsFromAddress(is *controlleroptions.InsecureServingOptions, addr string) error { + if is == nil { + return nil + } + if len(addr) == 0 { + is.BindPort = 0 + return nil + } + + host, portInt, err := splitHostIntPort(addr) + if err != nil { + return fmt.Errorf("invalid address %q", addr) + } + + is.BindAddress = net.ParseIP(host) + is.BindPort = portInt + + return nil +} + +// Validate validates the insecure serving options. +func (o *CombinedInsecureServingOptions) Validate() []error { + if o == nil { + return nil + } + + errors := []error{} + + if o.BindPort < 0 || o.BindPort > 32767 { + errors = append(errors, fmt.Errorf("--port %v must be between 0 and 32767, inclusive. 0 for turning off insecure (HTTP) port", o.BindPort)) + } + + if len(o.BindAddress) > 0 && net.ParseIP(o.BindAddress) == nil { + errors = append(errors, fmt.Errorf("--address has no valid IP address")) + } + + return errors +} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/insecure_serving_test.go b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/insecure_serving_test.go new file mode 100644 index 000000000..f04dfd8d1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/insecure_serving_test.go @@ -0,0 +1,276 @@ +/* +Copyright 2018 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 options + +import ( + "fmt" + "net" + "strconv" + "testing" + + "k8s.io/apimachinery/pkg/util/rand" + "k8s.io/kubernetes/cmd/controller-manager/app/options" + schedulerappconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config" + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +func TestOptions_ApplyTo(t *testing.T) { + tests := []struct { + name string + options Options + configLoaded bool + expectHealthzBindAddress, expectMetricsBindAddress string + expectInsecureServingAddress, expectInsecureMetricsServingAddress string + expectInsecureServingPort, expectInsecureMetricsServingPort int + wantErr bool + }{ + { + name: "no config, zero port", + options: Options{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + HealthzBindAddress: "1.2.3.4:1234", + MetricsBindAddress: "1.2.3.4:1234", + }, + CombinedInsecureServing: &CombinedInsecureServingOptions{ + Healthz: &options.InsecureServingOptions{}, + Metrics: &options.InsecureServingOptions{}, + BindPort: 0, + }, + }, + configLoaded: false, + }, + { + name: "config loaded, non-nil healthz", + options: Options{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + HealthzBindAddress: "1.2.3.4:1234", + MetricsBindAddress: "1.2.3.4:1234", + }, + CombinedInsecureServing: &CombinedInsecureServingOptions{ + Healthz: &options.InsecureServingOptions{}, + BindPort: 0, + }, + }, + configLoaded: true, + + expectHealthzBindAddress: "1.2.3.4:1234", + expectInsecureServingPort: 1234, + expectInsecureServingAddress: "1.2.3.4", + }, + { + name: "config loaded, non-nil metrics", + options: Options{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + HealthzBindAddress: "1.2.3.4:1234", + MetricsBindAddress: "1.2.3.4:1234", + }, + CombinedInsecureServing: &CombinedInsecureServingOptions{ + Metrics: &options.InsecureServingOptions{}, + BindPort: 0, + }, + }, + configLoaded: true, + + expectMetricsBindAddress: "1.2.3.4:1234", + expectInsecureMetricsServingPort: 1234, + expectInsecureMetricsServingAddress: "1.2.3.4", + }, + { + name: "config loaded, all set, zero BindPort", + options: Options{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + HealthzBindAddress: "1.2.3.4:1234", + MetricsBindAddress: "1.2.3.4:1234", + }, + CombinedInsecureServing: &CombinedInsecureServingOptions{ + Healthz: &options.InsecureServingOptions{}, + Metrics: &options.InsecureServingOptions{}, + BindPort: 0, + }, + }, + configLoaded: true, + + expectHealthzBindAddress: "1.2.3.4:1234", + expectInsecureServingPort: 1234, + expectInsecureServingAddress: "1.2.3.4", + + expectMetricsBindAddress: "1.2.3.4:1234", + }, + { + name: "config loaded, all set, different addresses", + options: Options{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + HealthzBindAddress: "1.2.3.4:1234", + MetricsBindAddress: "1.2.3.4:1235", + }, + CombinedInsecureServing: &CombinedInsecureServingOptions{ + Healthz: &options.InsecureServingOptions{}, + Metrics: &options.InsecureServingOptions{}, + BindPort: 0, + }, + }, + configLoaded: true, + + expectHealthzBindAddress: "1.2.3.4:1234", + expectInsecureServingPort: 1234, + expectInsecureServingAddress: "1.2.3.4", + + expectMetricsBindAddress: "1.2.3.4:1235", + expectInsecureMetricsServingPort: 1235, + expectInsecureMetricsServingAddress: "1.2.3.4", + }, + { + name: "no config, all set, port passed", + options: Options{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + HealthzBindAddress: "1.2.3.4:1234", + MetricsBindAddress: "1.2.3.4:1234", + }, + CombinedInsecureServing: &CombinedInsecureServingOptions{ + Healthz: &options.InsecureServingOptions{}, + Metrics: &options.InsecureServingOptions{}, + BindPort: 1236, + BindAddress: "1.2.3.4", + }, + }, + configLoaded: false, + + expectHealthzBindAddress: "1.2.3.4:1236", + expectInsecureServingPort: 1236, + expectInsecureServingAddress: "1.2.3.4", + + expectMetricsBindAddress: "1.2.3.4:1236", + }, + { + name: "no config, all set, address passed", + options: Options{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + HealthzBindAddress: "1.2.3.4:1234", + MetricsBindAddress: "1.2.3.4:1234", + }, + CombinedInsecureServing: &CombinedInsecureServingOptions{ + Healthz: &options.InsecureServingOptions{}, + Metrics: &options.InsecureServingOptions{}, + BindAddress: "2.3.4.5", + BindPort: 1234, + }, + }, + configLoaded: false, + + expectHealthzBindAddress: "2.3.4.5:1234", + expectInsecureServingPort: 1234, + expectInsecureServingAddress: "2.3.4.5", + + expectMetricsBindAddress: "2.3.4.5:1234", + }, + { + name: "no config, all set, zero port passed", + options: Options{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + HealthzBindAddress: "1.2.3.4:1234", + MetricsBindAddress: "1.2.3.4:1234", + }, + CombinedInsecureServing: &CombinedInsecureServingOptions{ + Healthz: &options.InsecureServingOptions{}, + Metrics: &options.InsecureServingOptions{}, + BindAddress: "2.3.4.5", + BindPort: 0, + }, + }, + configLoaded: false, + }, + } + for i, tt := range tests { + t.Run(fmt.Sprintf("%d-%s", i, tt.name), func(t *testing.T) { + c := schedulerappconfig.Config{ + ComponentConfig: tt.options.ComponentConfig, + } + + if tt.options.CombinedInsecureServing != nil { + if tt.options.CombinedInsecureServing.Healthz != nil { + tt.options.CombinedInsecureServing.Healthz.ListenFunc = createMockListener + } + if tt.options.CombinedInsecureServing.Metrics != nil { + tt.options.CombinedInsecureServing.Metrics.ListenFunc = createMockListener + } + } + + if tt.configLoaded { + if err := tt.options.CombinedInsecureServing.ApplyToFromLoadedConfig(&c, &c.ComponentConfig); (err != nil) != tt.wantErr { + t.Fatalf("%d - Options.ApplyTo() error = %v, wantErr %v", i, err, tt.wantErr) + } + } else { + if err := tt.options.CombinedInsecureServing.ApplyTo(&c, &c.ComponentConfig); (err != nil) != tt.wantErr { + t.Fatalf("%d - Options.ApplyTo() error = %v, wantErr %v", i, err, tt.wantErr) + } + } + if got, expect := c.ComponentConfig.HealthzBindAddress, tt.expectHealthzBindAddress; got != expect { + t.Errorf("%d - expected HealthzBindAddress %q, got %q", i, expect, got) + } + if got, expect := c.ComponentConfig.MetricsBindAddress, tt.expectMetricsBindAddress; got != expect { + t.Errorf("%d - expected MetricsBindAddress %q, got %q", i, expect, got) + } + if got, expect := c.InsecureServing != nil, tt.expectInsecureServingPort != 0; got != expect { + t.Errorf("%d - expected InsecureServing != nil to be %v, got %v", i, expect, got) + } else if c.InsecureServing != nil { + if got, expect := c.InsecureServing.Listener.(*mockListener).address, tt.expectInsecureServingAddress; got != expect { + t.Errorf("%d - expected healthz address %q, got %q", i, expect, got) + } + if got, expect := c.InsecureServing.Listener.(*mockListener).port, tt.expectInsecureServingPort; got != expect { + t.Errorf("%d - expected healthz port %v, got %v", i, expect, got) + } + } + if got, expect := c.InsecureMetricsServing != nil, tt.expectInsecureMetricsServingPort != 0; got != expect { + t.Errorf("%d - expected Metrics != nil to be %v, got %v", i, expect, got) + } else if c.InsecureMetricsServing != nil { + if got, expect := c.InsecureMetricsServing.Listener.(*mockListener).address, tt.expectInsecureMetricsServingAddress; got != expect { + t.Errorf("%d - expected metrics address %q, got %q", i, expect, got) + } + if got, expect := c.InsecureMetricsServing.Listener.(*mockListener).port, tt.expectInsecureMetricsServingPort; got != expect { + t.Errorf("%d - expected metrics port %v, got %v", i, expect, got) + } + } + }) + } +} + +type mockListener struct { + address string + port int +} + +func createMockListener(network, addr string) (net.Listener, int, error) { + host, portInt, err := splitHostIntPort(addr) + if err != nil { + return nil, 0, err + } + if portInt == 0 { + portInt = rand.IntnRange(1, 32767) + } + return &mockListener{host, portInt}, portInt, nil +} + +func (l *mockListener) Accept() (net.Conn, error) { return nil, nil } +func (l *mockListener) Close() error { return nil } +func (l *mockListener) Addr() net.Addr { + return mockAddr(net.JoinHostPort(l.address, strconv.Itoa(l.port))) +} + +type mockAddr string + +func (a mockAddr) Network() string { return "tcp" } +func (a mockAddr) String() string { return string(a) } diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/options.go b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/options.go new file mode 100644 index 000000000..89e27b746 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/options.go @@ -0,0 +1,300 @@ +/* +Copyright 2018 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 options + +import ( + "fmt" + "net" + "os" + "strconv" + + "github.com/golang/glog" + "github.com/spf13/pflag" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/uuid" + apiserveroptions "k8s.io/apiserver/pkg/server/options" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + v1core "k8s.io/client-go/kubernetes/typed/core/v1" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/client-go/tools/leaderelection" + "k8s.io/client-go/tools/leaderelection/resourcelock" + "k8s.io/client-go/tools/record" + controlleroptions "k8s.io/kubernetes/cmd/controller-manager/app/options" + schedulerappconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/componentconfig" + componentconfigv1alpha1 "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" + "k8s.io/kubernetes/pkg/client/leaderelectionconfig" + "k8s.io/kubernetes/pkg/scheduler/factory" +) + +// Options has all the params needed to run a Scheduler +type Options struct { + // The default values. These are overridden if ConfigFile is set or by values in InsecureServing. + ComponentConfig componentconfig.KubeSchedulerConfiguration + + SecureServing *apiserveroptions.SecureServingOptions + CombinedInsecureServing *CombinedInsecureServingOptions + Authentication *apiserveroptions.DelegatingAuthenticationOptions + Authorization *apiserveroptions.DelegatingAuthorizationOptions + Deprecated *DeprecatedOptions + + // ConfigFile is the location of the scheduler server's configuration file. + ConfigFile string + + // WriteConfigTo is the path where the default configuration will be written. + WriteConfigTo string + + Master string +} + +// NewOptions returns default scheduler app options. +func NewOptions() (*Options, error) { + cfg, err := newDefaultComponentConfig() + if err != nil { + return nil, err + } + + hhost, hport, err := splitHostIntPort(cfg.HealthzBindAddress) + if err != nil { + return nil, err + } + + o := &Options{ + ComponentConfig: *cfg, + SecureServing: nil, // TODO: enable with apiserveroptions.NewSecureServingOptions() + CombinedInsecureServing: &CombinedInsecureServingOptions{ + Healthz: &controlleroptions.InsecureServingOptions{ + BindNetwork: "tcp", + }, + Metrics: &controlleroptions.InsecureServingOptions{ + BindNetwork: "tcp", + }, + BindPort: hport, + BindAddress: hhost, + }, + Authentication: nil, // TODO: enable with apiserveroptions.NewDelegatingAuthenticationOptions() + Authorization: nil, // TODO: enable with apiserveroptions.NewDelegatingAuthorizationOptions() + Deprecated: &DeprecatedOptions{ + UseLegacyPolicyConfig: false, + PolicyConfigMapNamespace: metav1.NamespaceSystem, + }, + } + + return o, nil +} + +func splitHostIntPort(s string) (string, int, error) { + host, port, err := net.SplitHostPort(s) + if err != nil { + return "", 0, err + } + portInt, err := strconv.Atoi(port) + if err != nil { + return "", 0, err + } + return host, portInt, err +} + +func newDefaultComponentConfig() (*componentconfig.KubeSchedulerConfiguration, error) { + cfgv1alpha1 := componentconfigv1alpha1.KubeSchedulerConfiguration{} + configScheme.Default(&cfgv1alpha1) + cfg := componentconfig.KubeSchedulerConfiguration{} + if err := configScheme.Convert(&cfgv1alpha1, &cfg, nil); err != nil { + return nil, err + } + return &cfg, nil +} + +// AddFlags adds flags for the scheduler options. +func (o *Options) AddFlags(fs *pflag.FlagSet) { + fs.StringVar(&o.ConfigFile, "config", o.ConfigFile, "The path to the configuration file. Flags override values in this file.") + fs.StringVar(&o.WriteConfigTo, "write-config-to", o.WriteConfigTo, "If set, write the configuration values to this file and exit.") + fs.StringVar(&o.Master, "master", o.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig)") + + o.SecureServing.AddFlags(fs) + o.CombinedInsecureServing.AddFlags(fs) + o.Authentication.AddFlags(fs) + o.Authorization.AddFlags(fs) + o.Deprecated.AddFlags(fs, &o.ComponentConfig) + + leaderelectionconfig.BindFlags(&o.ComponentConfig.LeaderElection.LeaderElectionConfiguration, fs) + utilfeature.DefaultFeatureGate.AddFlag(fs) +} + +// ApplyTo applies the scheduler options to the given scheduler app configuration. +func (o *Options) ApplyTo(c *schedulerappconfig.Config) error { + if len(o.ConfigFile) == 0 { + c.ComponentConfig = o.ComponentConfig + + // only apply deprecated flags if no config file is loaded (this is the old behaviour). + if err := o.Deprecated.ApplyTo(&c.ComponentConfig); err != nil { + return err + } + if err := o.CombinedInsecureServing.ApplyTo(c, &c.ComponentConfig); err != nil { + return err + } + } else { + cfg, err := loadConfigFromFile(o.ConfigFile) + if err != nil { + return err + } + + // use the loaded config file only, with the exception of --address and --port. This means that + // none of the deprectated flags in o.Deprecated are taken into consideration. This is the old + // behaviour of the flags we have to keep. + c.ComponentConfig = *cfg + + if err := o.CombinedInsecureServing.ApplyToFromLoadedConfig(c, &c.ComponentConfig); err != nil { + return err + } + } + + if err := o.SecureServing.ApplyTo(&c.SecureServing); err != nil { + return err + } + if err := o.Authentication.ApplyTo(&c.Authentication, c.SecureServing, nil); err != nil { + return err + } + return o.Authorization.ApplyTo(&c.Authorization) +} + +// Validate validates all the required options. +func (o *Options) Validate() []error { + var errs []error + + errs = append(errs, o.SecureServing.Validate()...) + errs = append(errs, o.CombinedInsecureServing.Validate()...) + errs = append(errs, o.Authentication.Validate()...) + errs = append(errs, o.Authorization.Validate()...) + errs = append(errs, o.Deprecated.Validate()...) + + return errs +} + +// Config return a scheduler config object +func (o *Options) Config() (*schedulerappconfig.Config, error) { + c := &schedulerappconfig.Config{} + if err := o.ApplyTo(c); err != nil { + return nil, err + } + + // prepare kube clients. + client, leaderElectionClient, eventClient, err := createClients(c.ComponentConfig.ClientConnection, o.Master) + if err != nil { + return nil, err + } + + // Prepare event clients. + eventBroadcaster := record.NewBroadcaster() + recorder := eventBroadcaster.NewRecorder(legacyscheme.Scheme, corev1.EventSource{Component: c.ComponentConfig.SchedulerName}) + + // Set up leader election if enabled. + var leaderElectionConfig *leaderelection.LeaderElectionConfig + if c.ComponentConfig.LeaderElection.LeaderElect { + leaderElectionConfig, err = makeLeaderElectionConfig(c.ComponentConfig.LeaderElection, leaderElectionClient, recorder) + if err != nil { + return nil, err + } + } + + c.Client = client + c.InformerFactory = informers.NewSharedInformerFactory(client, 0) + c.PodInformer = factory.NewPodInformer(client, 0) + c.EventClient = eventClient + c.Recorder = recorder + c.Broadcaster = eventBroadcaster + c.LeaderElection = leaderElectionConfig + + return c, nil +} + +// makeLeaderElectionConfig builds a leader election configuration. It will +// create a new resource lock associated with the configuration. +func makeLeaderElectionConfig(config componentconfig.KubeSchedulerLeaderElectionConfiguration, client clientset.Interface, recorder record.EventRecorder) (*leaderelection.LeaderElectionConfig, error) { + hostname, err := os.Hostname() + if err != nil { + return nil, fmt.Errorf("unable to get hostname: %v", err) + } + // add a uniquifier so that two processes on the same host don't accidentally both become active + id := hostname + "_" + string(uuid.NewUUID()) + + rl, err := resourcelock.New(config.ResourceLock, + config.LockObjectNamespace, + config.LockObjectName, + client.CoreV1(), + resourcelock.ResourceLockConfig{ + Identity: id, + EventRecorder: recorder, + }) + if err != nil { + return nil, fmt.Errorf("couldn't create resource lock: %v", err) + } + + return &leaderelection.LeaderElectionConfig{ + Lock: rl, + LeaseDuration: config.LeaseDuration.Duration, + RenewDeadline: config.RenewDeadline.Duration, + RetryPeriod: config.RetryPeriod.Duration, + }, nil +} + +// createClients creates a kube client and an event client from the given config and masterOverride. +// TODO remove masterOverride when CLI flags are removed. +func createClients(config componentconfig.ClientConnectionConfiguration, masterOverride string) (clientset.Interface, clientset.Interface, v1core.EventsGetter, error) { + if len(config.KubeConfigFile) == 0 && len(masterOverride) == 0 { + glog.Warningf("Neither --kubeconfig nor --master was specified. Using default API client. This might not work.") + } + + // This creates a client, first loading any specified kubeconfig + // file, and then overriding the Master flag, if non-empty. + kubeConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + &clientcmd.ClientConfigLoadingRules{ExplicitPath: config.KubeConfigFile}, + &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterOverride}}).ClientConfig() + if err != nil { + return nil, nil, nil, err + } + + kubeConfig.AcceptContentTypes = config.AcceptContentTypes + kubeConfig.ContentType = config.ContentType + kubeConfig.QPS = config.QPS + //TODO make config struct use int instead of int32? + kubeConfig.Burst = int(config.Burst) + + client, err := clientset.NewForConfig(restclient.AddUserAgent(kubeConfig, "scheduler")) + if err != nil { + return nil, nil, nil, err + } + + leaderElectionClient, err := clientset.NewForConfig(restclient.AddUserAgent(kubeConfig, "leader-election")) + if err != nil { + return nil, nil, nil, err + } + + eventClient, err := clientset.NewForConfig(kubeConfig) + if err != nil { + return nil, nil, nil, err + } + + return client, leaderElectionClient, eventClient.CoreV1(), nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/options_test.go b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/options_test.go new file mode 100644 index 000000000..455b4d6ef --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/options_test.go @@ -0,0 +1,193 @@ +/* +Copyright 2018 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 options + +import ( + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "strings" + "testing" + + "k8s.io/kubernetes/pkg/apis/componentconfig" +) + +func TestSchedulerOptions(t *testing.T) { + // temp dir + tmpDir, err := ioutil.TempDir("", "scheduler-options") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + // record the username requests were made with + username := "" + // https server + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + username, _, _ = req.BasicAuth() + if username == "" { + username = "none, tls" + } + w.WriteHeader(200) + w.Write([]byte(`ok`)) + })) + defer server.Close() + // http server + insecureserver := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + username, _, _ = req.BasicAuth() + if username == "" { + username = "none, http" + } + w.WriteHeader(200) + w.Write([]byte(`ok`)) + })) + defer insecureserver.Close() + + // config file and kubeconfig + configFile := filepath.Join(tmpDir, "scheduler.yaml") + configKubeconfig := filepath.Join(tmpDir, "config.kubeconfig") + if err := ioutil.WriteFile(configFile, []byte(fmt.Sprintf(` +apiVersion: componentconfig/v1alpha1 +kind: KubeSchedulerConfiguration +clientConnection: + kubeconfig: "%s" +leaderElection: + leaderElect: true`, configKubeconfig)), os.FileMode(0600)); err != nil { + t.Fatal(err) + } + if err := ioutil.WriteFile(configKubeconfig, []byte(fmt.Sprintf(` +apiVersion: v1 +kind: Config +clusters: +- cluster: + insecure-skip-tls-verify: true + server: %s + name: default +contexts: +- context: + cluster: default + user: default + name: default +current-context: default +users: +- name: default + user: + username: config +`, server.URL)), os.FileMode(0600)); err != nil { + t.Fatal(err) + } + + // flag-specified kubeconfig + flagKubeconfig := filepath.Join(tmpDir, "flag.kubeconfig") + if err := ioutil.WriteFile(flagKubeconfig, []byte(fmt.Sprintf(` +apiVersion: v1 +kind: Config +clusters: +- cluster: + insecure-skip-tls-verify: true + server: %s + name: default +contexts: +- context: + cluster: default + user: default + name: default +current-context: default +users: +- name: default + user: + username: flag +`, server.URL)), os.FileMode(0600)); err != nil { + t.Fatal(err) + } + + // Insulate this test from picking up in-cluster config when run inside a pod + // We can't assume we have permissions to write to /var/run/secrets/... from a unit test to mock in-cluster config for testing + originalHost := os.Getenv("KUBERNETES_SERVICE_HOST") + if len(originalHost) > 0 { + os.Setenv("KUBERNETES_SERVICE_HOST", "") + defer os.Setenv("KUBERNETES_SERVICE_HOST", originalHost) + } + + testcases := []struct { + name string + options *Options + expectedUsername string + expectedError string + }{ + { + name: "config file", + options: &Options{ConfigFile: configFile}, + expectedUsername: "config", + }, + { + name: "kubeconfig flag", + options: &Options{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + ClientConnection: componentconfig.ClientConnectionConfiguration{ + KubeConfigFile: flagKubeconfig}}}, + expectedUsername: "flag", + }, + { + name: "overridden master", + options: &Options{Master: insecureserver.URL}, + expectedUsername: "none, http", + }, + { + name: "no config", + options: &Options{}, + expectedError: "no configuration has been provided", + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + // create the config + config, err := tc.options.Config() + + // handle errors + if err != nil { + if tc.expectedError == "" { + t.Error(err) + } else if !strings.Contains(err.Error(), tc.expectedError) { + t.Errorf("expected %q, got %q", tc.expectedError, err.Error()) + } + return + } + + // ensure we have a client + if config.Client == nil { + t.Error("unexpected nil client") + return + } + + // test the client talks to the endpoint we expect with the credentials we expect + username = "" + _, err = config.Client.Discovery().RESTClient().Get().AbsPath("/").DoRaw() + if err != nil { + t.Error(err) + return + } + if username != tc.expectedUsername { + t.Errorf("expected server call with user %s, got %s", tc.expectedUsername, username) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/server.go b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/server.go index e60c294a5..ee776c89b 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/server.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/server.go @@ -18,52 +18,41 @@ limitations under the License. package app import ( - "errors" "fmt" + "io" "io/ioutil" - "net" "net/http" "os" - "reflect" goruntime "runtime" - "strconv" - "time" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/serializer" + utilerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apiserver/pkg/authentication/authenticator" + "k8s.io/apiserver/pkg/authorization/authorizer" + genericapifilters "k8s.io/apiserver/pkg/endpoints/filters" + apirequest "k8s.io/apiserver/pkg/endpoints/request" + genericfilters "k8s.io/apiserver/pkg/server/filters" "k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/mux" "k8s.io/apiserver/pkg/server/routes" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/client-go/informers" - coreinformers "k8s.io/client-go/informers/core/v1" storageinformers "k8s.io/client-go/informers/storage/v1" - clientset "k8s.io/client-go/kubernetes" v1core "k8s.io/client-go/kubernetes/typed/core/v1" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/tools/leaderelection" - "k8s.io/client-go/tools/leaderelection/resourcelock" - "k8s.io/client-go/tools/record" + schedulerserverconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config" + "k8s.io/kubernetes/cmd/kube-scheduler/app/options" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/componentconfig" - componentconfigv1alpha1 "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" - "k8s.io/kubernetes/pkg/client/leaderelectionconfig" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/features" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/scheduler" "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" "k8s.io/kubernetes/pkg/scheduler/factory" + "k8s.io/kubernetes/pkg/scheduler/metrics" "k8s.io/kubernetes/pkg/util/configz" utilflag "k8s.io/kubernetes/pkg/util/flag" "k8s.io/kubernetes/pkg/version" @@ -72,255 +61,11 @@ import ( "github.com/golang/glog" "github.com/prometheus/client_golang/prometheus" "github.com/spf13/cobra" - "github.com/spf13/pflag" ) -// SchedulerServer has all the context and params needed to run a Scheduler -type Options struct { - // ConfigFile is the location of the scheduler server's configuration file. - ConfigFile string - - // config is the scheduler server's configuration object. - config *componentconfig.KubeSchedulerConfiguration - - scheme *runtime.Scheme - codecs serializer.CodecFactory - - // The fields below here are placeholders for flags that can't be directly - // mapped into componentconfig.KubeSchedulerConfiguration. - // - // TODO remove these fields once the deprecated flags are removed. - - // master is the address of the Kubernetes API server (overrides any - // value in kubeconfig). - master string - healthzAddress string - healthzPort int32 - policyConfigFile string - policyConfigMapName string - policyConfigMapNamespace string - useLegacyPolicyConfig bool - algorithmProvider string -} - -// AddFlags adds flags for a specific SchedulerServer to the specified FlagSet -func (o *Options) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&o.ConfigFile, "config", o.ConfigFile, "The path to the configuration file.") - - // All flags below here are deprecated and will eventually be removed. - - fs.Int32Var(&o.healthzPort, "port", ports.SchedulerPort, "The port that the scheduler's http service runs on") - fs.StringVar(&o.healthzAddress, "address", o.healthzAddress, "The IP address to serve on (set to 0.0.0.0 for all IPv4 interfaces and :: for all IPv6 interfaces).") - fs.StringVar(&o.algorithmProvider, "algorithm-provider", o.algorithmProvider, "The scheduling algorithm provider to use, one of: "+factory.ListAlgorithmProviders()) - fs.StringVar(&o.policyConfigFile, "policy-config-file", o.policyConfigFile, "File with scheduler policy configuration. This file is used if policy ConfigMap is not provided or --use-legacy-policy-config==true") - usage := fmt.Sprintf("Name of the ConfigMap object that contains scheduler's policy configuration. It must exist in the system namespace before scheduler initialization if --use-legacy-policy-config==false. The config must be provided as the value of an element in 'Data' map with the key='%v'", componentconfig.SchedulerPolicyConfigMapKey) - fs.StringVar(&o.policyConfigMapName, "policy-configmap", o.policyConfigMapName, usage) - fs.StringVar(&o.policyConfigMapNamespace, "policy-configmap-namespace", o.policyConfigMapNamespace, "The namespace where policy ConfigMap is located. The system namespace will be used if this is not provided or is empty.") - fs.BoolVar(&o.useLegacyPolicyConfig, "use-legacy-policy-config", false, "When set to true, scheduler will ignore policy ConfigMap and uses policy config file") - fs.BoolVar(&o.config.EnableProfiling, "profiling", o.config.EnableProfiling, "Enable profiling via web interface host:port/debug/pprof/") - fs.BoolVar(&o.config.EnableContentionProfiling, "contention-profiling", o.config.EnableContentionProfiling, "Enable lock contention profiling, if profiling is enabled") - fs.StringVar(&o.master, "master", o.master, "The address of the Kubernetes API server (overrides any value in kubeconfig)") - fs.StringVar(&o.config.ClientConnection.KubeConfigFile, "kubeconfig", o.config.ClientConnection.KubeConfigFile, "Path to kubeconfig file with authorization and master location information.") - fs.StringVar(&o.config.ClientConnection.ContentType, "kube-api-content-type", o.config.ClientConnection.ContentType, "Content type of requests sent to apiserver.") - fs.Float32Var(&o.config.ClientConnection.QPS, "kube-api-qps", o.config.ClientConnection.QPS, "QPS to use while talking with kubernetes apiserver") - fs.Int32Var(&o.config.ClientConnection.Burst, "kube-api-burst", o.config.ClientConnection.Burst, "Burst to use while talking with kubernetes apiserver") - fs.StringVar(&o.config.SchedulerName, "scheduler-name", o.config.SchedulerName, "Name of the scheduler, used to select which pods will be processed by this scheduler, based on pod's \"spec.SchedulerName\".") - fs.StringVar(&o.config.LeaderElection.LockObjectNamespace, "lock-object-namespace", o.config.LeaderElection.LockObjectNamespace, "Define the namespace of the lock object.") - fs.StringVar(&o.config.LeaderElection.LockObjectName, "lock-object-name", o.config.LeaderElection.LockObjectName, "Define the name of the lock object.") - fs.Int32Var(&o.config.HardPodAffinitySymmetricWeight, "hard-pod-affinity-symmetric-weight", o.config.HardPodAffinitySymmetricWeight, - "RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule corresponding "+ - "to every RequiredDuringScheduling affinity rule. --hard-pod-affinity-symmetric-weight represents the weight of implicit PreferredDuringScheduling affinity rule.") - fs.MarkDeprecated("hard-pod-affinity-symmetric-weight", "This option was moved to the policy configuration file") - fs.StringVar(&o.config.FailureDomains, "failure-domains", o.config.FailureDomains, "Indicate the \"all topologies\" set for an empty topologyKey when it's used for PreferredDuringScheduling pod anti-affinity.") - fs.MarkDeprecated("failure-domains", "Doesn't have any effect. Will be removed in future version.") - leaderelectionconfig.BindFlags(&o.config.LeaderElection.LeaderElectionConfiguration, fs) - utilfeature.DefaultFeatureGate.AddFlag(fs) -} - -func NewOptions() (*Options, error) { - o := &Options{ - config: new(componentconfig.KubeSchedulerConfiguration), - } - - o.scheme = runtime.NewScheme() - o.codecs = serializer.NewCodecFactory(o.scheme) - - if err := componentconfig.AddToScheme(o.scheme); err != nil { - return nil, err - } - if err := componentconfigv1alpha1.AddToScheme(o.scheme); err != nil { - return nil, err - } - - // TODO: we should fix this up better (PR 59732) - o.config.LeaderElection.LeaderElect = true - - return o, nil -} - -func (o *Options) Complete() error { - if len(o.ConfigFile) == 0 { - glog.Warning("WARNING: all flags other than --config are deprecated. Please begin using a config file ASAP.") - o.applyDeprecatedHealthzAddressToConfig() - o.applyDeprecatedHealthzPortToConfig() - o.applyDeprecatedAlgorithmSourceOptionsToConfig() - } - - return nil -} - -// applyDeprecatedHealthzAddressToConfig sets o.config.HealthzBindAddress and -// o.config.MetricsBindAddress from flags passed on the command line based on -// the following rules: -// -// 1. If --address is empty, leave the config as-is. -// 2. Otherwise, use the value of --address for the address portion of -// o.config.HealthzBindAddress -func (o *Options) applyDeprecatedHealthzAddressToConfig() { - if len(o.healthzAddress) == 0 { - return - } - - _, port, err := net.SplitHostPort(o.config.HealthzBindAddress) - if err != nil { - glog.Fatalf("invalid healthz bind address %q: %v", o.config.HealthzBindAddress, err) - } - o.config.HealthzBindAddress = net.JoinHostPort(o.healthzAddress, port) - o.config.MetricsBindAddress = net.JoinHostPort(o.healthzAddress, port) -} - -// applyDeprecatedHealthzPortToConfig sets o.config.HealthzBindAddress and -// o.config.MetricsBindAddress from flags passed on the command line based on -// the following rules: -// -// 1. If --port is -1, disable the healthz server. -// 2. Otherwise, use the value of --port for the port portion of -// o.config.HealthzBindAddress -func (o *Options) applyDeprecatedHealthzPortToConfig() { - if o.healthzPort == -1 { - o.config.HealthzBindAddress = "" - o.config.MetricsBindAddress = "" - return - } - - host, _, err := net.SplitHostPort(o.config.HealthzBindAddress) - if err != nil { - glog.Fatalf("invalid healthz bind address %q: %v", o.config.HealthzBindAddress, err) - } - o.config.HealthzBindAddress = net.JoinHostPort(host, strconv.Itoa(int(o.healthzPort))) - o.config.MetricsBindAddress = net.JoinHostPort(host, strconv.Itoa(int(o.healthzPort))) -} - -// applyDeprecatedAlgorithmSourceOptionsToConfig sets o.config.AlgorithmSource from -// flags passed on the command line in the following precedence order: -// -// 1. --use-legacy-policy-config to use a policy file. -// 2. --policy-configmap to use a policy config map value. -// 3. --algorithm-provider to use a named algorithm provider. -func (o *Options) applyDeprecatedAlgorithmSourceOptionsToConfig() { - switch { - case o.useLegacyPolicyConfig || (len(o.policyConfigFile) > 0 && o.policyConfigMapName == ""): - o.config.AlgorithmSource = componentconfig.SchedulerAlgorithmSource{ - Policy: &componentconfig.SchedulerPolicySource{ - File: &componentconfig.SchedulerPolicyFileSource{ - Path: o.policyConfigFile, - }, - }, - } - case len(o.policyConfigMapName) > 0: - o.config.AlgorithmSource = componentconfig.SchedulerAlgorithmSource{ - Policy: &componentconfig.SchedulerPolicySource{ - ConfigMap: &componentconfig.SchedulerPolicyConfigMapSource{ - Name: o.policyConfigMapName, - Namespace: o.policyConfigMapNamespace, - }, - }, - } - case len(o.algorithmProvider) > 0: - o.config.AlgorithmSource = componentconfig.SchedulerAlgorithmSource{ - Provider: &o.algorithmProvider, - } - } -} - -// Validate validates all the required options. -func (o *Options) Validate(args []string) error { - if len(args) != 0 { - return errors.New("no arguments are supported") - } - - return nil -} - -// loadConfigFromFile loads the contents of file and decodes it as a -// KubeSchedulerConfiguration object. -func (o *Options) loadConfigFromFile(file string) (*componentconfig.KubeSchedulerConfiguration, error) { - data, err := ioutil.ReadFile(file) - if err != nil { - return nil, err - } - - return o.loadConfig(data) -} - -// loadConfig decodes data as a KubeSchedulerConfiguration object. -func (o *Options) loadConfig(data []byte) (*componentconfig.KubeSchedulerConfiguration, error) { - configObj, gvk, err := o.codecs.UniversalDecoder().Decode(data, nil, nil) - if err != nil { - return nil, err - } - config, ok := configObj.(*componentconfig.KubeSchedulerConfiguration) - if !ok { - return nil, fmt.Errorf("got unexpected config type: %v", gvk) - } - return config, nil -} - -func (o *Options) ApplyDefaults(in *componentconfig.KubeSchedulerConfiguration) (*componentconfig.KubeSchedulerConfiguration, error) { - external, err := o.scheme.ConvertToVersion(in, componentconfigv1alpha1.SchemeGroupVersion) - if err != nil { - return nil, err - } - - o.scheme.Default(external) - - internal, err := o.scheme.ConvertToVersion(external, componentconfig.SchemeGroupVersion) - if err != nil { - return nil, err - } - - out := internal.(*componentconfig.KubeSchedulerConfiguration) - - return out, nil -} - -func (o *Options) Run() error { - config := o.config - - if len(o.ConfigFile) > 0 { - if c, err := o.loadConfigFromFile(o.ConfigFile); err != nil { - return err - } else { - config = c - } - } - - // Apply algorithms based on feature gates. - // TODO: make configurable? - algorithmprovider.ApplyFeatureGates() - - server, err := NewSchedulerServer(config, o.master) - if err != nil { - return err - } - - stop := make(chan struct{}) - return server.Run(stop) -} - // NewSchedulerCommand creates a *cobra.Command object with default parameters func NewSchedulerCommand() *cobra.Command { - opts, err := NewOptions() + opts, err := options.NewOptions() if err != nil { glog.Fatalf("unable to initialize command options: %v", err) } @@ -338,15 +83,36 @@ through the API as necessary.`, verflag.PrintAndExitIfRequested() utilflag.PrintFlags(cmd.Flags()) - cmdutil.CheckErr(opts.Complete()) - cmdutil.CheckErr(opts.Validate(args)) - cmdutil.CheckErr(opts.Run()) - }, - } + if len(args) != 0 { + fmt.Fprint(os.Stderr, "arguments are not supported\n") + } - opts.config, err = opts.ApplyDefaults(opts.config) - if err != nil { - glog.Fatalf("unable to apply config defaults: %v", err) + if errs := opts.Validate(); len(errs) > 0 { + fmt.Fprintf(os.Stderr, "%v\n", utilerrors.NewAggregate(errs)) + os.Exit(1) + } + + if len(opts.WriteConfigTo) > 0 { + if err := options.WriteConfigFile(opts.WriteConfigTo, &opts.ComponentConfig); err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + glog.Infof("Wrote configuration to: %s\n", opts.WriteConfigTo) + return + } + + c, err := opts.Config() + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + + stopCh := make(chan struct{}) + if err := Run(c.Complete(), stopCh); err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + }, } opts.AddFlags(cmd.Flags()) @@ -355,207 +121,23 @@ through the API as necessary.`, return cmd } -// SchedulerServer represents all the parameters required to start the -// Kubernetes scheduler server. -type SchedulerServer struct { - SchedulerName string - Client clientset.Interface - InformerFactory informers.SharedInformerFactory - PodInformer coreinformers.PodInformer - AlgorithmSource componentconfig.SchedulerAlgorithmSource - HardPodAffinitySymmetricWeight int32 - EventClient v1core.EventsGetter - Recorder record.EventRecorder - Broadcaster record.EventBroadcaster - // LeaderElection is optional. - LeaderElection *leaderelection.LeaderElectionConfig - // HealthzServer is optional. - HealthzServer *http.Server - // MetricsServer is optional. - MetricsServer *http.Server -} +func Run(c schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error { + // To help debugging, immediately log version + glog.Infof("Version: %+v", version.Get()) -// NewSchedulerServer creates a runnable SchedulerServer from configuration. -func NewSchedulerServer(config *componentconfig.KubeSchedulerConfiguration, master string) (*SchedulerServer, error) { - if config == nil { - return nil, errors.New("config is required") - } + // Apply algorithms based on feature gates. + // TODO: make configurable? + algorithmprovider.ApplyFeatureGates() // Configz registration. - // only register if we're actually exposing it somewhere - if len(config.MetricsBindAddress) > 0 || len(config.HealthzBindAddress) > 0 { - if c, err := configz.New("componentconfig"); err == nil { - c.Set(config) - } else { - return nil, fmt.Errorf("unable to register configz: %s", err) - } - } - - // Prepare some Kube clients. - client, leaderElectionClient, eventClient, err := createClients(config.ClientConnection, master) - if err != nil { - return nil, err - } - - // Prepare event clients. - eventBroadcaster := record.NewBroadcaster() - recorder := eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: config.SchedulerName}) - - // Set up leader election if enabled. - var leaderElectionConfig *leaderelection.LeaderElectionConfig - if config.LeaderElection.LeaderElect { - leaderElectionConfig, err = makeLeaderElectionConfig(config.LeaderElection, leaderElectionClient, recorder) - if err != nil { - return nil, err - } - } - - // Prepare a healthz server. If the metrics bind address is the same as the - // healthz bind address, consolidate the servers into one. - var healthzServer *http.Server - if len(config.HealthzBindAddress) > 0 { - healthzServer = makeHealthzServer(config) - } - - // Prepare a separate metrics server only if the bind address differs from the - // healthz bind address. - var metricsServer *http.Server - if len(config.MetricsBindAddress) > 0 && config.HealthzBindAddress != config.MetricsBindAddress { - metricsServer = makeMetricsServer(config) - } - - return &SchedulerServer{ - SchedulerName: config.SchedulerName, - Client: client, - InformerFactory: informers.NewSharedInformerFactory(client, 0), - PodInformer: factory.NewPodInformer(client, 0, config.SchedulerName), - AlgorithmSource: config.AlgorithmSource, - HardPodAffinitySymmetricWeight: config.HardPodAffinitySymmetricWeight, - EventClient: eventClient, - Recorder: recorder, - Broadcaster: eventBroadcaster, - LeaderElection: leaderElectionConfig, - HealthzServer: healthzServer, - MetricsServer: metricsServer, - }, nil -} - -// makeLeaderElectionConfig builds a leader election configuration. It will -// create a new resource lock associated with the configuration. -func makeLeaderElectionConfig(config componentconfig.KubeSchedulerLeaderElectionConfiguration, client clientset.Interface, recorder record.EventRecorder) (*leaderelection.LeaderElectionConfig, error) { - hostname, err := os.Hostname() - if err != nil { - return nil, fmt.Errorf("unable to get hostname: %v", err) - } - // add a uniquifier so that two processes on the same host don't accidentally both become active - id := hostname + "_" + string(uuid.NewUUID()) - - rl, err := resourcelock.New(config.ResourceLock, - config.LockObjectNamespace, - config.LockObjectName, - client.CoreV1(), - resourcelock.ResourceLockConfig{ - Identity: id, - EventRecorder: recorder, - }) - if err != nil { - return nil, fmt.Errorf("couldn't create resource lock: %v", err) - } - - return &leaderelection.LeaderElectionConfig{ - Lock: rl, - LeaseDuration: config.LeaseDuration.Duration, - RenewDeadline: config.RenewDeadline.Duration, - RetryPeriod: config.RetryPeriod.Duration, - }, nil -} - -// makeHealthzServer creates a healthz server from the config, and will also -// embed the metrics handler if the healthz and metrics address configurations -// are the same. -func makeHealthzServer(config *componentconfig.KubeSchedulerConfiguration) *http.Server { - mux := mux.NewPathRecorderMux("kube-scheduler") - healthz.InstallHandler(mux) - if config.HealthzBindAddress == config.MetricsBindAddress { - configz.InstallHandler(mux) - mux.Handle("/metrics", prometheus.Handler()) - } - if config.EnableProfiling { - routes.Profiling{}.Install(mux) - if config.EnableContentionProfiling { - goruntime.SetBlockProfileRate(1) - } - } - return &http.Server{ - Addr: config.HealthzBindAddress, - Handler: mux, - } -} - -// makeMetricsServer builds a metrics server from the config. -func makeMetricsServer(config *componentconfig.KubeSchedulerConfiguration) *http.Server { - mux := mux.NewPathRecorderMux("kube-scheduler") - configz.InstallHandler(mux) - mux.Handle("/metrics", prometheus.Handler()) - if config.EnableProfiling { - routes.Profiling{}.Install(mux) - if config.EnableContentionProfiling { - goruntime.SetBlockProfileRate(1) - } - } - return &http.Server{ - Addr: config.MetricsBindAddress, - Handler: mux, - } -} - -// createClients creates a kube client and an event client from the given config and masterOverride. -// TODO remove masterOverride when CLI flags are removed. -func createClients(config componentconfig.ClientConnectionConfiguration, masterOverride string) (clientset.Interface, clientset.Interface, v1core.EventsGetter, error) { - if len(config.KubeConfigFile) == 0 && len(masterOverride) == 0 { - glog.Warningf("Neither --kubeconfig nor --master was specified. Using default API client. This might not work.") - } - - // This creates a client, first loading any specified kubeconfig - // file, and then overriding the Master flag, if non-empty. - kubeConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - &clientcmd.ClientConfigLoadingRules{ExplicitPath: config.KubeConfigFile}, - &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterOverride}}).ClientConfig() - if err != nil { - return nil, nil, nil, err - } - - kubeConfig.AcceptContentTypes = config.AcceptContentTypes - kubeConfig.ContentType = config.ContentType - kubeConfig.QPS = config.QPS - //TODO make config struct use int instead of int32? - kubeConfig.Burst = int(config.Burst) - - client, err := clientset.NewForConfig(restclient.AddUserAgent(kubeConfig, "scheduler")) - if err != nil { - return nil, nil, nil, err - } - - leaderElectionClient, err := clientset.NewForConfig(restclient.AddUserAgent(kubeConfig, "leader-election")) - if err != nil { - return nil, nil, nil, err + if cz, err := configz.New("componentconfig"); err == nil { + cz.Set(c.ComponentConfig) + } else { + return fmt.Errorf("unable to register configz: %s", err) } - eventClient, err := clientset.NewForConfig(kubeConfig) - if err != nil { - return nil, nil, nil, err - } - - return client, leaderElectionClient, eventClient.CoreV1(), nil -} - -// Run runs the SchedulerServer. This should never exit. -func (s *SchedulerServer) Run(stop chan struct{}) error { - // To help debugging, immediately log version - glog.Infof("Version: %+v", version.Get()) - // Build a scheduler config from the provided algorithm source. - schedulerConfig, err := s.SchedulerConfig() + schedulerConfig, err := NewSchedulerConfig(c) if err != nil { return err } @@ -564,39 +146,39 @@ func (s *SchedulerServer) Run(stop chan struct{}) error { sched := scheduler.NewFromConfig(schedulerConfig) // Prepare the event broadcaster. - if !reflect.ValueOf(s.Broadcaster).IsNil() && !reflect.ValueOf(s.EventClient).IsNil() { - s.Broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: s.EventClient.Events("")}) + if c.Broadcaster != nil && c.EventClient != nil { + c.Broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: c.EventClient.Events("")}) } // Start up the healthz server. - if s.HealthzServer != nil { - go wait.Until(func() { - glog.Infof("starting healthz server on %v", s.HealthzServer.Addr) - err := s.HealthzServer.ListenAndServe() - if err != nil { - utilruntime.HandleError(fmt.Errorf("failed to start healthz server: %v", err)) - } - }, 5*time.Second, stop) + if c.InsecureServing != nil { + separateMetrics := c.InsecureMetricsServing != nil + handler := buildHandlerChain(newHealthzHandler(&c.ComponentConfig, separateMetrics), nil, nil) + if err := c.InsecureServing.Serve(handler, 0, stopCh); err != nil { + return fmt.Errorf("failed to start healthz server: %v", err) + } } - - // Start up the metrics server. - if s.MetricsServer != nil { - go wait.Until(func() { - glog.Infof("starting metrics server on %v", s.MetricsServer.Addr) - err := s.MetricsServer.ListenAndServe() - if err != nil { - utilruntime.HandleError(fmt.Errorf("failed to start metrics server: %v", err)) - } - }, 5*time.Second, stop) + if c.InsecureMetricsServing != nil { + handler := buildHandlerChain(newMetricsHandler(&c.ComponentConfig), nil, nil) + if err := c.InsecureMetricsServing.Serve(handler, 0, stopCh); err != nil { + return fmt.Errorf("failed to start metrics server: %v", err) + } + } + if c.SecureServing != nil { + handler := buildHandlerChain(newHealthzHandler(&c.ComponentConfig, false), c.Authentication.Authenticator, c.Authorization.Authorizer) + if err := c.SecureServing.Serve(handler, 0, stopCh); err != nil { + // fail early for secure handlers, removing the old error loop from above + return fmt.Errorf("failed to start healthz server: %v", err) + } } // Start all informers. - go s.PodInformer.Informer().Run(stop) - s.InformerFactory.Start(stop) + go c.PodInformer.Informer().Run(stopCh) + c.InformerFactory.Start(stopCh) // Wait for all caches to sync before scheduling. - s.InformerFactory.WaitForCacheSync(stop) - controller.WaitForCacheSync("scheduler", stop, s.PodInformer.Informer().HasSynced) + c.InformerFactory.WaitForCacheSync(stopCh) + controller.WaitForCacheSync("scheduler", stopCh, c.PodInformer.Informer().HasSynced) // Prepare a reusable run function. run := func(stopCh <-chan struct{}) { @@ -605,14 +187,14 @@ func (s *SchedulerServer) Run(stop chan struct{}) error { } // If leader election is enabled, run via LeaderElector until done and exit. - if s.LeaderElection != nil { - s.LeaderElection.Callbacks = leaderelection.LeaderCallbacks{ + if c.LeaderElection != nil { + c.LeaderElection.Callbacks = leaderelection.LeaderCallbacks{ OnStartedLeading: run, OnStoppedLeading: func() { utilruntime.HandleError(fmt.Errorf("lost master")) }, } - leaderElector, err := leaderelection.NewLeaderElector(*s.LeaderElection) + leaderElector, err := leaderelection.NewLeaderElector(*c.LeaderElection) if err != nil { return fmt.Errorf("couldn't create leader elector: %v", err) } @@ -623,13 +205,70 @@ func (s *SchedulerServer) Run(stop chan struct{}) error { } // Leader election is disabled, so run inline until done. - run(stop) + run(stopCh) return fmt.Errorf("finished without leader elect") } -// SchedulerConfig creates the scheduler configuration. This is exposed for use -// by tests. -func (s *SchedulerServer) SchedulerConfig() (*scheduler.Config, error) { +// buildHandlerChain wraps the given handler with the standard filters. +func buildHandlerChain(handler http.Handler, authn authenticator.Request, authz authorizer.Authorizer) http.Handler { + requestInfoResolver := &apirequest.RequestInfoFactory{} + failedHandler := genericapifilters.Unauthorized(legacyscheme.Codecs, false) + + handler = genericapifilters.WithRequestInfo(handler, requestInfoResolver) + handler = genericapifilters.WithAuthorization(handler, authz, legacyscheme.Codecs) + handler = genericapifilters.WithAuthentication(handler, authn, failedHandler) + handler = genericapifilters.WithRequestInfo(handler, requestInfoResolver) + handler = genericfilters.WithPanicRecovery(handler) + + return handler +} + +func installMetricHandler(pathRecorderMux *mux.PathRecorderMux) { + configz.InstallHandler(pathRecorderMux) + defaultMetricsHandler := prometheus.Handler().ServeHTTP + pathRecorderMux.HandleFunc("/metrics", func(w http.ResponseWriter, req *http.Request) { + if req.Method == "DELETE" { + metrics.Reset() + io.WriteString(w, "metrics reset\n") + return + } + defaultMetricsHandler(w, req) + }) +} + +// newMetricsHandler builds a metrics server from the config. +func newMetricsHandler(config *componentconfig.KubeSchedulerConfiguration) http.Handler { + pathRecorderMux := mux.NewPathRecorderMux("kube-scheduler") + installMetricHandler(pathRecorderMux) + if config.EnableProfiling { + routes.Profiling{}.Install(pathRecorderMux) + if config.EnableContentionProfiling { + goruntime.SetBlockProfileRate(1) + } + } + return pathRecorderMux +} + +// newHealthzServer creates a healthz server from the config, and will also +// embed the metrics handler if the healthz and metrics address configurations +// are the same. +func newHealthzHandler(config *componentconfig.KubeSchedulerConfiguration, separateMetrics bool) http.Handler { + pathRecorderMux := mux.NewPathRecorderMux("kube-scheduler") + healthz.InstallHandler(pathRecorderMux) + if !separateMetrics { + installMetricHandler(pathRecorderMux) + } + if config.EnableProfiling { + routes.Profiling{}.Install(pathRecorderMux) + if config.EnableContentionProfiling { + goruntime.SetBlockProfileRate(1) + } + } + return pathRecorderMux +} + +// NewSchedulerConfig creates the scheduler configuration. This is exposed for use by tests. +func NewSchedulerConfig(s schedulerserverconfig.CompletedConfig) (*scheduler.Config, error) { var storageClassInformer storageinformers.StorageClassInformer if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { storageClassInformer = s.InformerFactory.Storage().V1().StorageClasses() @@ -637,7 +276,7 @@ func (s *SchedulerServer) SchedulerConfig() (*scheduler.Config, error) { // Set up the configurator which can create schedulers from configs. configurator := factory.NewConfigFactory( - s.SchedulerName, + s.ComponentConfig.SchedulerName, s.Client, s.InformerFactory.Core().V1().Nodes(), s.PodInformer, @@ -649,11 +288,12 @@ func (s *SchedulerServer) SchedulerConfig() (*scheduler.Config, error) { s.InformerFactory.Core().V1().Services(), s.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(), storageClassInformer, - s.HardPodAffinitySymmetricWeight, + s.ComponentConfig.HardPodAffinitySymmetricWeight, utilfeature.DefaultFeatureGate.Enabled(features.EnableEquivalenceClassCache), + s.ComponentConfig.DisablePreemption, ) - source := s.AlgorithmSource + source := s.ComponentConfig.AlgorithmSource var config *scheduler.Config switch { case source.Provider != nil: @@ -708,5 +348,7 @@ func (s *SchedulerServer) SchedulerConfig() (*scheduler.Config, error) { } // Additional tweaks to the config produced by the configurator. config.Recorder = s.Recorder + + config.DisablePreemption = s.ComponentConfig.DisablePreemption return config, nil } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/.import-restrictions b/vendor/k8s.io/kubernetes/cmd/kubeadm/.import-restrictions new file mode 100644 index 000000000..a8bcd175b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/.import-restrictions @@ -0,0 +1,163 @@ +{ + "Rules": [ + { + "SelectorRegexp": "k8s[.]io/(api/|apimachinery/|apiextensions-apiserver/|apiserver/)", + "AllowedPrefixes": [ + "" + ] + }, + { + "SelectorRegexp": "k8s[.]io/client-go/", + "AllowedPrefixes": [ + "" + ] + }, + { + "SelectorRegexp": "k8s[.]io/kube-openapi/", + "AllowedPrefixes": [ + "k8s.io/kube-openapi/pkg/util/proto" + ] + }, + { + "SelectorRegexp": "k8s[.]io/kubernetes/cmd", + "AllowedPrefixes": [ + "k8s.io/kubernetes/cmd/kubeadm" + ] + }, + { + "SelectorRegexp": "k8s[.]io/kubernetes/test", + "AllowedPrefixes": [ + "k8s.io/kubernetes/test/e2e_node/system" + ] + }, + { + "SelectorRegexp": "k8s[.]io/utils", + "AllowedPrefixes": [ + "k8s.io/utils/exec" + ] + }, + { + "SelectorRegexp": "k8s[.]io/kubernetes/pkg", + "AllowedPrefixes": [ + "k8s.io/kubernetes/pkg/api/endpoints", + "k8s.io/kubernetes/pkg/api/events", + "k8s.io/kubernetes/pkg/api/legacyscheme", + "k8s.io/kubernetes/pkg/api/pod", + "k8s.io/kubernetes/pkg/api/ref", + "k8s.io/kubernetes/pkg/api/resource", + "k8s.io/kubernetes/pkg/api/service", + "k8s.io/kubernetes/pkg/api/v1/pod", + "k8s.io/kubernetes/pkg/apis/admissionregistration", + "k8s.io/kubernetes/pkg/apis/admissionregistration/install", + "k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1", + "k8s.io/kubernetes/pkg/apis/apps", + "k8s.io/kubernetes/pkg/apis/apps/v1", + "k8s.io/kubernetes/pkg/apis/apps/v1beta1", + "k8s.io/kubernetes/pkg/apis/authentication", + "k8s.io/kubernetes/pkg/apis/authentication/install", + "k8s.io/kubernetes/pkg/apis/authentication/v1beta1", + "k8s.io/kubernetes/pkg/apis/authorization", + "k8s.io/kubernetes/pkg/apis/authorization/install", + "k8s.io/kubernetes/pkg/apis/autoscaling", + "k8s.io/kubernetes/pkg/apis/batch", + "k8s.io/kubernetes/pkg/apis/batch/install", + "k8s.io/kubernetes/pkg/apis/batch/v1beta1", + "k8s.io/kubernetes/pkg/apis/batch/v2alpha1", + "k8s.io/kubernetes/pkg/apis/certificates", + "k8s.io/kubernetes/pkg/apis/componentconfig", + "k8s.io/kubernetes/pkg/apis/core", + "k8s.io/kubernetes/pkg/apis/core/helper", + "k8s.io/kubernetes/pkg/apis/core/pods", + "k8s.io/kubernetes/pkg/apis/core/v1", + "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos", + "k8s.io/kubernetes/pkg/apis/core/validation", + "k8s.io/kubernetes/pkg/apis/events", + "k8s.io/kubernetes/pkg/apis/extensions", + "k8s.io/kubernetes/pkg/apis/networking", + "k8s.io/kubernetes/pkg/apis/networking/v1", + "k8s.io/kubernetes/pkg/apis/policy", + "k8s.io/kubernetes/pkg/apis/rbac", + "k8s.io/kubernetes/pkg/apis/rbac/v1", + "k8s.io/kubernetes/pkg/apis/scheduling", + "k8s.io/kubernetes/pkg/apis/settings", + "k8s.io/kubernetes/pkg/apis/settings/install", + "k8s.io/kubernetes/pkg/apis/settings/v1alpha1", + "k8s.io/kubernetes/pkg/apis/storage", + "k8s.io/kubernetes/pkg/capabilities", + "k8s.io/kubernetes/pkg/cloudprovider", + "k8s.io/kubernetes/pkg/controller", + "k8s.io/kubernetes/pkg/controller/bootstrap", + "k8s.io/kubernetes/pkg/credentialprovider", + "k8s.io/kubernetes/pkg/features", + "k8s.io/kubernetes/pkg/fieldpath", + "k8s.io/kubernetes/pkg/generated", + "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes", + "k8s.io/kubernetes/pkg/kubectl", + "k8s.io/kubernetes/pkg/kubectl/apps", + "k8s.io/kubernetes/pkg/kubectl/cmd/scalejob", + "k8s.io/kubernetes/pkg/kubectl/cmd/templates", + "k8s.io/kubernetes/pkg/kubectl/cmd/util", + "k8s.io/kubernetes/pkg/kubectl/genericclioptions", + "k8s.io/kubernetes/pkg/kubectl/plugins", + "k8s.io/kubernetes/pkg/kubectl/scheme", + "k8s.io/kubernetes/pkg/kubectl/util", + "k8s.io/kubernetes/pkg/kubectl/util/i18n", + "k8s.io/kubernetes/pkg/kubectl/validation", + "k8s.io/kubernetes/pkg/kubelet/apis", + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig", + "k8s.io/kubernetes/pkg/kubelet/qos", + "k8s.io/kubernetes/pkg/kubelet/types", + "k8s.io/kubernetes/pkg/master/ports", + "k8s.io/kubernetes/pkg/master/reconcilers", + "k8s.io/kubernetes/pkg/printers", + "k8s.io/kubernetes/pkg/printers/internalversion", + "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig", + "k8s.io/kubernetes/pkg/registry/core/endpoint", + "k8s.io/kubernetes/pkg/registry/core/service/allocator", + "k8s.io/kubernetes/pkg/registry/core/service/ipallocator", + "k8s.io/kubernetes/pkg/registry/rbac/validation", + "k8s.io/kubernetes/pkg/scheduler/algorithm", + "k8s.io/kubernetes/pkg/scheduler/api", + "k8s.io/kubernetes/pkg/scheduler/cache", + "k8s.io/kubernetes/pkg/scheduler/util", + "k8s.io/kubernetes/pkg/security/apparmor", + "k8s.io/kubernetes/pkg/serviceaccount", + "k8s.io/kubernetes/pkg/util/file", + "k8s.io/kubernetes/pkg/util/hash", + "k8s.io/kubernetes/pkg/util/initsystem", + "k8s.io/kubernetes/pkg/util/interrupt", + "k8s.io/kubernetes/pkg/util/io", + "k8s.io/kubernetes/pkg/util/labels", + "k8s.io/kubernetes/pkg/util/metrics", + "k8s.io/kubernetes/pkg/util/mount", + "k8s.io/kubernetes/pkg/util/net/sets", + "k8s.io/kubernetes/pkg/util/node", + "k8s.io/kubernetes/pkg/util/normalizer", + "k8s.io/kubernetes/pkg/util/nsenter", + "k8s.io/kubernetes/pkg/util/parsers", + "k8s.io/kubernetes/pkg/util/pointer", + "k8s.io/kubernetes/pkg/util/procfs", + "k8s.io/kubernetes/pkg/util/slice", + "k8s.io/kubernetes/pkg/util/taints", + "k8s.io/kubernetes/pkg/util/version", + "k8s.io/kubernetes/pkg/util/ipvs", + "k8s.io/kubernetes/pkg/version", + "k8s.io/kubernetes/pkg/volume", + "k8s.io/kubernetes/pkg/volume/util" + ], + "ForbiddenPrefixes": [ + "k8s.io/kubernetes/pkg/cloudprovider/providers", + "k8s.io/kubernetes/pkg/cloudprovider/providers/aws", + "k8s.io/kubernetes/pkg/cloudprovider/providers/azure", + "k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack", + "k8s.io/kubernetes/pkg/cloudprovider/providers/fake", + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce", + "k8s.io/kubernetes/pkg/cloudprovider/providers/openstack", + "k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt", + "k8s.io/kubernetes/pkg/cloudprovider/providers/photon", + "k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere", + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + ] + } + ] +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/OWNERS b/vendor/k8s.io/kubernetes/cmd/kubeadm/OWNERS index 8da4cfe97..ce7a11020 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/OWNERS +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/OWNERS @@ -1,16 +1,19 @@ approvers: -- jbeda - luxas -- krousey - timothysc +- fabriziopandini reviewers: - luxas -- dmmcquay -- krousey - timothysc - fabriziopandini -- jamiehannaford - kad - xiangpengzhao -- mattmoyer -- kargakis +- stealthybox +- liztio +- chuckha +- detiber +- dixudx +# Might want to add @kargakis, @jamiehannaford, @krousey and/or @dmmcquay back in the future +labels: +- area/kubeadm +- sig/cluster-lifecycle diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD index 24502fd94..8fb20ee37 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD @@ -10,9 +10,10 @@ go_library( srcs = ["kubeadm.go"], importpath = "k8s.io/kubernetes/cmd/kubeadm/app", deps = [ - "//cmd/kubeadm/app/apis/kubeadm/install:go_default_library", "//cmd/kubeadm/app/cmd:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", ], ) @@ -43,6 +44,7 @@ filegroup( "//cmd/kubeadm/app/phases/kubeconfig:all-srcs", "//cmd/kubeadm/app/phases/kubelet:all-srcs", "//cmd/kubeadm/app/phases/markmaster:all-srcs", + "//cmd/kubeadm/app/phases/patchnode:all-srcs", "//cmd/kubeadm/app/phases/selfhosting:all-srcs", "//cmd/kubeadm/app/phases/upgrade:all-srcs", "//cmd/kubeadm/app/phases/uploadconfig:all-srcs", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/BUILD index 4465aeb64..866e8826f 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/BUILD @@ -3,11 +3,14 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( name = "go_default_library", srcs = [ + "bootstraptokenhelpers.go", + "bootstraptokenstring.go", "doc.go", "register.go", "types.go", @@ -17,10 +20,13 @@ go_library( deps = [ "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", + "//vendor/github.com/google/gofuzz:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/client-go/tools/bootstrap/token/api:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", ], ) @@ -36,9 +42,23 @@ filegroup( srcs = [ ":package-srcs", "//cmd/kubeadm/app/apis/kubeadm/fuzzer:all-srcs", - "//cmd/kubeadm/app/apis/kubeadm/install:all-srcs", + "//cmd/kubeadm/app/apis/kubeadm/scheme:all-srcs", "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:all-srcs", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:all-srcs", "//cmd/kubeadm/app/apis/kubeadm/validation:all-srcs", ], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = [ + "bootstraptokenhelpers_test.go", + "bootstraptokenstring_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers.go new file mode 100644 index 000000000..fc18701c6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers.go @@ -0,0 +1,168 @@ +/* +Copyright 2018 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 kubeadm + +import ( + "fmt" + "sort" + "strings" + "time" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" +) + +// ToSecret converts the given BootstrapToken object to its Secret representation that +// may be submitted to the API Server in order to be stored. +func (bt *BootstrapToken) ToSecret() *v1.Secret { + return &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: bootstraputil.BootstrapTokenSecretName(bt.Token.ID), + Namespace: metav1.NamespaceSystem, + }, + Type: v1.SecretType(bootstrapapi.SecretTypeBootstrapToken), + Data: encodeTokenSecretData(bt, time.Now()), + } +} + +// encodeTokenSecretData takes the token discovery object and an optional duration and returns the .Data for the Secret +// now is passed in order to be able to used in unit testing +func encodeTokenSecretData(token *BootstrapToken, now time.Time) map[string][]byte { + data := map[string][]byte{ + bootstrapapi.BootstrapTokenIDKey: []byte(token.Token.ID), + bootstrapapi.BootstrapTokenSecretKey: []byte(token.Token.Secret), + } + + if len(token.Description) > 0 { + data[bootstrapapi.BootstrapTokenDescriptionKey] = []byte(token.Description) + } + + // If for some strange reason both token.TTL and token.Expires would be set + // (they are mutually exlusive in validation so this shouldn't be the case), + // token.Expires has higher priority, as can be seen in the logic here. + if token.Expires != nil { + // Format the expiration date accordingly + // TODO: This maybe should be a helper function in bootstraputil? + expirationString := token.Expires.Time.Format(time.RFC3339) + data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(expirationString) + + } else if token.TTL != nil && token.TTL.Duration > 0 { + // Only if .Expires is unset, TTL might have an effect + // Get the current time, add the specified duration, and format it accordingly + expirationString := now.Add(token.TTL.Duration).Format(time.RFC3339) + data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(expirationString) + } + + for _, usage := range token.Usages { + data[bootstrapapi.BootstrapTokenUsagePrefix+usage] = []byte("true") + } + + if len(token.Groups) > 0 { + data[bootstrapapi.BootstrapTokenExtraGroupsKey] = []byte(strings.Join(token.Groups, ",")) + } + return data +} + +// BootstrapTokenFromSecret returns a BootstrapToken object from the given Secret +func BootstrapTokenFromSecret(secret *v1.Secret) (*BootstrapToken, error) { + // Get the Token ID field from the Secret data + tokenID := getSecretString(secret, bootstrapapi.BootstrapTokenIDKey) + if len(tokenID) == 0 { + return nil, fmt.Errorf("Bootstrap Token Secret has no token-id data: %s", secret.Name) + } + + // Enforce the right naming convention + if secret.Name != bootstraputil.BootstrapTokenSecretName(tokenID) { + return nil, fmt.Errorf("bootstrap token name is not of the form '%s(token-id)'. Actual: %q. Expected: %q", + bootstrapapi.BootstrapTokenSecretPrefix, secret.Name, bootstraputil.BootstrapTokenSecretName(tokenID)) + } + + tokenSecret := getSecretString(secret, bootstrapapi.BootstrapTokenSecretKey) + if len(tokenSecret) == 0 { + return nil, fmt.Errorf("Bootstrap Token Secret has no token-secret data: %s", secret.Name) + } + + // Create the BootstrapTokenString object based on the ID and Secret + bts, err := NewBootstrapTokenStringFromIDAndSecret(tokenID, tokenSecret) + if err != nil { + return nil, fmt.Errorf("Bootstrap Token Secret is invalid and couldn't be parsed: %v", err) + } + + // Get the description (if any) from the Secret + description := getSecretString(secret, bootstrapapi.BootstrapTokenDescriptionKey) + + // Expiration time is optional, if not specified this implies the token + // never expires. + secretExpiration := getSecretString(secret, bootstrapapi.BootstrapTokenExpirationKey) + var expires *metav1.Time + if len(secretExpiration) > 0 { + expTime, err := time.Parse(time.RFC3339, secretExpiration) + if err != nil { + return nil, fmt.Errorf("can't parse expiration time of bootstrap token %q: %v", secret.Name, err) + } + expires = &metav1.Time{Time: expTime} + } + + // Build an usages string slice from the Secret data + var usages []string + for k, v := range secret.Data { + // Skip all fields that don't include this prefix + if !strings.HasPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix) { + continue + } + // Skip those that don't have this usage set to true + if string(v) != "true" { + continue + } + usages = append(usages, strings.TrimPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix)) + } + // Only sort the slice if defined + if usages != nil { + sort.Strings(usages) + } + + // Get the extra groups information from the Secret + // It's done this way to make .Groups be nil in case there is no items, rather than an + // empty slice or an empty slice with a "" string only + var groups []string + groupsString := getSecretString(secret, bootstrapapi.BootstrapTokenExtraGroupsKey) + g := strings.Split(groupsString, ",") + if len(g) > 0 && len(g[0]) > 0 { + groups = g + } + + return &BootstrapToken{ + Token: bts, + Description: description, + Expires: expires, + Usages: usages, + Groups: groups, + }, nil +} + +// getSecretString returns the string value for the given key in the specified Secret +func getSecretString(secret *v1.Secret, key string) string { + if secret.Data == nil { + return "" + } + if val, ok := secret.Data[key]; ok { + return string(val) + } + return "" +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go new file mode 100644 index 000000000..153d08e7c --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go @@ -0,0 +1,473 @@ +/* +Copyright 2018 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 kubeadm + +import ( + "encoding/json" + "reflect" + "testing" + "time" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// This timestamp is used as the reference value when computing expiration dates based on TTLs in these unit tests +var refTime = time.Date(1970, time.January, 1, 1, 1, 1, 0, time.UTC) + +func TestToSecret(t *testing.T) { + + var tests = []struct { + bt *BootstrapToken + secret *v1.Secret + }{ + { + &BootstrapToken{ // all together + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + Expires: &metav1.Time{ + Time: refTime, + }, + Usages: []string{"signing", "authentication"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bootstrap-token-abcdef", + Namespace: "kube-system", + }, + Type: v1.SecretType("bootstrap.kubernetes.io/token"), + Data: map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + "expiration": []byte(refTime.Format(time.RFC3339)), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + }, + }, + } + for _, rt := range tests { + actual := rt.bt.ToSecret() + if !reflect.DeepEqual(actual, rt.secret) { + t.Errorf( + "failed BootstrapToken.ToSecret():\n\texpected: %v\n\t actual: %v", + rt.secret, + actual, + ) + } + } +} + +func TestBootstrapTokenToSecretRoundtrip(t *testing.T) { + var tests = []struct { + bt *BootstrapToken + }{ + { + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + Expires: &metav1.Time{ + Time: refTime, + }, + Usages: []string{"authentication", "signing"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + }, + } + for _, rt := range tests { + actual, err := BootstrapTokenFromSecret(rt.bt.ToSecret()) + if err != nil { + t.Errorf("failed BootstrapToken to Secret roundtrip with error: %v", err) + } + if !reflect.DeepEqual(actual, rt.bt) { + t.Errorf( + "failed BootstrapToken to Secret roundtrip:\n\texpected: %v\n\t actual: %v", + rt.bt, + actual, + ) + } + } +} + +func TestEncodeTokenSecretData(t *testing.T) { + var tests = []struct { + bt *BootstrapToken + data map[string][]byte + }{ + { + &BootstrapToken{ // the minimum amount of information needed to be specified + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + }, + }, + { + &BootstrapToken{ // adds description + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + }, + }, + { + &BootstrapToken{ // adds ttl + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + TTL: &metav1.Duration{ + Duration: mustParseDuration("2h", t), + }, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte(refTime.Add(mustParseDuration("2h", t)).Format(time.RFC3339)), + }, + }, + { + &BootstrapToken{ // adds expiration + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Expires: &metav1.Time{ + Time: refTime, + }, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte(refTime.Format(time.RFC3339)), + }, + }, + { + &BootstrapToken{ // adds ttl and expiration, should favor expiration + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + TTL: &metav1.Duration{ + Duration: mustParseDuration("2h", t), + }, + Expires: &metav1.Time{ + Time: refTime, + }, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte(refTime.Format(time.RFC3339)), + }, + }, + { + &BootstrapToken{ // adds usages + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Usages: []string{"authentication", "signing"}, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + }, + }, + { + &BootstrapToken{ // adds groups + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + }, + { + &BootstrapToken{ // all together + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + TTL: &metav1.Duration{ + Duration: mustParseDuration("2h", t), + }, + Expires: &metav1.Time{ + Time: refTime, + }, + Usages: []string{"authentication", "signing"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + "expiration": []byte(refTime.Format(time.RFC3339)), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + }, + } + for _, rt := range tests { + actual := encodeTokenSecretData(rt.bt, refTime) + if !reflect.DeepEqual(actual, rt.data) { + t.Errorf( + "failed encodeTokenSecretData:\n\texpected: %v\n\t actual: %v", + rt.data, + actual, + ) + } + } +} + +func mustParseDuration(durationStr string, t *testing.T) time.Duration { + d, err := time.ParseDuration(durationStr) + if err != nil { + t.Fatalf("couldn't parse duration %q: %v", durationStr, err) + } + return d +} + +func TestBootstrapTokenFromSecret(t *testing.T) { + var tests = []struct { + name string + data map[string][]byte + bt *BootstrapToken + expectedError bool + }{ + { // minimum information + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + }, + false, + }, + { // invalid token id + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdeF"), + "token-secret": []byte("abcdef0123456789"), + }, + nil, + true, + }, + { // invalid secret naming + "foo", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + }, + nil, + true, + }, + { // invalid token secret + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("ABCDEF0123456789"), + }, + nil, + true, + }, + { // adds description + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + }, + false, + }, + { // adds expiration + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte(refTime.Format(time.RFC3339)), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Expires: &metav1.Time{ + Time: refTime, + }, + }, + false, + }, + { // invalid expiration + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "expiration": []byte("invalid date"), + }, + nil, + true, + }, + { // adds usages + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Usages: []string{"authentication", "signing"}, + }, + false, + }, + { // should ignore usages that aren't set to true + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + "usage-bootstrap-foo": []byte("false"), + "usage-bootstrap-bar": []byte(""), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Usages: []string{"authentication", "signing"}, + }, + false, + }, + { // adds groups + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + false, + }, + { // all fields set + "bootstrap-token-abcdef", + map[string][]byte{ + "token-id": []byte("abcdef"), + "token-secret": []byte("abcdef0123456789"), + "description": []byte("foo"), + "expiration": []byte(refTime.Format(time.RFC3339)), + "usage-bootstrap-signing": []byte("true"), + "usage-bootstrap-authentication": []byte("true"), + "auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"), + }, + &BootstrapToken{ + Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + Description: "foo", + Expires: &metav1.Time{ + Time: refTime, + }, + Usages: []string{"authentication", "signing"}, + Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, + }, + false, + }, + } + for _, rt := range tests { + actual, err := BootstrapTokenFromSecret(&v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: rt.name, + Namespace: "kube-system", + }, + Type: v1.SecretType("bootstrap.kubernetes.io/token"), + Data: rt.data, + }) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed BootstrapTokenFromSecret\n\texpected error: %t\n\t actual error: %v", + rt.expectedError, + err, + ) + } else { + if actual == nil && rt.bt == nil { + // if both pointers are nil, it's okay, just continue + continue + } + // If one of the pointers is defined but the other isn't, throw error. If both pointers are defined but unequal, throw error + if (actual == nil && rt.bt != nil) || (actual != nil && rt.bt == nil) || !reflect.DeepEqual(*actual, *rt.bt) { + t.Errorf( + "failed BootstrapTokenFromSecret\n\texpected: %s\n\t actual: %s", + jsonMarshal(rt.bt), + jsonMarshal(actual), + ) + } + } + } +} + +func jsonMarshal(bt *BootstrapToken) string { + b, _ := json.Marshal(*bt) + return string(b) +} + +func TestGetSecretString(t *testing.T) { + var tests = []struct { + secret *v1.Secret + key string + expectedVal string + }{ + { + secret: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Data: map[string][]byte{ + "foo": []byte("bar"), + }, + }, + key: "foo", + expectedVal: "bar", + }, + { + secret: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Data: map[string][]byte{ + "foo": []byte("bar"), + }, + }, + key: "baz", + expectedVal: "", + }, + { + secret: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + }, + key: "foo", + expectedVal: "", + }, + } + for _, rt := range tests { + actual := getSecretString(rt.secret, rt.key) + if actual != rt.expectedVal { + t.Errorf( + "failed getSecretString:\n\texpected: %s\n\t actual: %s", + rt.expectedVal, + actual, + ) + } + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring.go new file mode 100644 index 000000000..440c2534a --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring.go @@ -0,0 +1,90 @@ +/* +Copyright 2018 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 kubeadm holds the internal kubeadm API types +// Note: This file should be kept in sync with the similar one for the external API +// TODO: The BootstrapTokenString object should move out to either k8s.io/client-go or k8s.io/api in the future +// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now. +package kubeadm + +import ( + "fmt" + "strings" + + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" +) + +// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used +// for both validation of the practically of the API server from a joining node's point +// of view and as an authentication method for the node in the bootstrap phase of +// "kubeadm join". This token is and should be short-lived +type BootstrapTokenString struct { + ID string + Secret string +} + +// MarshalJSON implements the json.Marshaler interface. +func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil +} + +// UnmarshalJSON implements the json.Unmarshaller interface. +func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error { + // If the token is represented as "", just return quickly without an error + if len(b) == 0 { + return nil + } + + // Remove unnecessary " characters coming from the JSON parser + token := strings.Replace(string(b), `"`, ``, -1) + // Convert the string Token to a BootstrapTokenString object + newbts, err := NewBootstrapTokenString(token) + if err != nil { + return err + } + bts.ID = newbts.ID + bts.Secret = newbts.Secret + return nil +} + +// String returns the string representation of the BootstrapTokenString +func (bts BootstrapTokenString) String() string { + if len(bts.ID) > 0 && len(bts.Secret) > 0 { + return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret) + } + return "" +} + +// NewBootstrapTokenString converts the given Bootstrap Token as a string +// to the BootstrapTokenString object used for serialization/deserialization +// and internal usage. It also automatically validates that the given token +// is of the right format +func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) { + substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token) + // TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works) + if len(substrs) != 3 { + return nil, fmt.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern) + } + + return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil +} + +// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString +// that allows the caller to specify the ID and Secret separately +func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) { + return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret)) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go new file mode 100644 index 000000000..8a389f83e --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go @@ -0,0 +1,236 @@ +/* +Copyright 2018 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 kubeadm + +import ( + "encoding/json" + "fmt" + "reflect" + "testing" +) + +func TestMarshalJSON(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`}, + {BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`}, + {BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`}, + } + for _, rt := range tests { + b, err := json.Marshal(rt.bts) + if err != nil { + t.Fatalf("json.Marshal returned an unexpected error: %v", err) + } + if string(b) != rt.expected { + t.Errorf( + "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", + rt.expected, + string(b), + ) + } + } +} + +func TestUnmarshalJSON(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + expectedError bool + }{ + {`"f.s"`, &BootstrapTokenString{}, true}, + {`"abcdef."`, &BootstrapTokenString{}, true}, + {`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true}, + {`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false}, + {`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false}, + } + for _, rt := range tests { + newbts := &BootstrapTokenString{} + err := json.Unmarshal([]byte(rt.input), newbts) + if (err != nil) != rt.expectedError { + t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) + } else if !reflect.DeepEqual(rt.bts, newbts) { + t.Errorf( + "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", + rt.bts, + newbts, + ) + } + } +} + +func TestJSONRoundtrip(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + }{ + {`"abcdef.abcdef0123456789"`, nil}, + {"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + } + for _, rt := range tests { + if err := roundtrip(rt.input, rt.bts); err != nil { + t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) + } + } +} + +func roundtrip(input string, bts *BootstrapTokenString) error { + var b []byte + var err error + newbts := &BootstrapTokenString{} + // If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string + if len(input) > 0 { + if err := json.Unmarshal([]byte(input), newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if b, err = json.Marshal(newbts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if input != string(b) { + return fmt.Errorf( + "expected token: %s\n\t actual: %s", + input, + string(b), + ) + } + } else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object + if b, err = json.Marshal(bts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if err := json.Unmarshal(b, newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if !reflect.DeepEqual(bts, newbts) { + return fmt.Errorf( + "expected object: %v\n\t actual: %v", + bts, + newbts, + ) + } + } + return nil +} + +func TestTokenFromIDAndSecret(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"}, + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"}, + {BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"}, + } + for _, rt := range tests { + actual := rt.bts.String() + if actual != rt.expected { + t.Errorf( + "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + +func TestNewBootstrapTokenString(t *testing.T) { + var tests = []struct { + token string + expectedError bool + bts *BootstrapTokenString + }{ + {token: "", expectedError: true, bts: nil}, + {token: ".", expectedError: true, bts: nil}, + {token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size + {token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456.", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation + {token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation + {token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id + {token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character + {token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, + } + for _, rt := range tests { + actual, err := NewBootstrapTokenString(rt.token) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", + rt.token, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", + rt.token, + rt.bts, + actual, + ) + } + } +} + +func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { + var tests = []struct { + id, secret string + expectedError bool + bts *BootstrapTokenString + }{ + {id: "", secret: "", expectedError: true, bts: nil}, + {id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id + {id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character + {id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, + } + for _, rt := range tests { + actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", + rt.id, + rt.secret, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", + rt.id, + rt.secret, + rt.bts, + actual, + ) + } + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD index 1682e9d03..f78847d71 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD @@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( @@ -15,6 +16,7 @@ go_library( "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", "//pkg/util/pointer:go_default_library", "//vendor/github.com/google/gofuzz:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", ], @@ -32,3 +34,13 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["fuzzer_test.go"], + embed = [":go_default_library"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go index 850f41b00..4478c92d1 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go @@ -19,8 +19,9 @@ package fuzzer import ( "time" - "github.com/google/gofuzz" + fuzz "github.com/google/gofuzz" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" @@ -39,44 +40,64 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { obj.API.AdvertiseAddress = "foo" obj.Networking.ServiceSubnet = "foo" obj.Networking.DNSDomain = "foo" - obj.AuthorizationModes = []string{"foo"} obj.CertificatesDir = "foo" obj.APIServerCertSANs = []string{"foo"} - obj.Etcd.ServerCertSANs = []string{"foo"} - obj.Etcd.PeerCertSANs = []string{"foo"} - obj.Token = "foo" - obj.CRISocket = "foo" - obj.TokenTTL = &metav1.Duration{Duration: 1 * time.Hour} - obj.TokenUsages = []string{"foo"} - obj.TokenGroups = []string{"foo"} - obj.Etcd.Image = "foo" - obj.Etcd.DataDir = "foo" + + obj.BootstrapTokens = []kubeadm.BootstrapToken{ + { + Token: &kubeadm.BootstrapTokenString{ + ID: "abcdef", + Secret: "abcdef0123456789", + }, + TTL: &metav1.Duration{Duration: 1 * time.Hour}, + Usages: []string{"foo"}, + Groups: []string{"foo"}, + }, + } obj.ImageRepository = "foo" obj.CIImageRepository = "" obj.UnifiedControlPlaneImage = "foo" obj.FeatureGates = map[string]bool{"foo": true} + obj.ClusterName = "foo" obj.APIServerExtraArgs = map[string]string{"foo": "foo"} obj.APIServerExtraVolumes = []kubeadm.HostPathMount{{ Name: "foo", HostPath: "foo", MountPath: "foo", + Writable: false, }} - obj.Etcd.ExtraArgs = map[string]string{"foo": "foo"} - obj.Etcd.SelfHosted = &kubeadm.SelfHostedEtcd{ - CertificatesDir: "/etc/kubernetes/pki/etcd", - ClusterServiceName: "etcd-cluster", - EtcdVersion: "v0.1.0", - OperatorVersion: "v0.1.0", + // Note: We don't set values here for obj.Etcd.External, as these are mutually exlusive. + // And to make sure the fuzzer doesn't set a random value for obj.Etcd.External, we let + // kubeadmapi.Etcd implement fuzz.Interface (we handle that ourselves) + obj.Etcd.Local = &kubeadm.LocalEtcd{ + Image: "foo", + DataDir: "foo", + ServerCertSANs: []string{"foo"}, + PeerCertSANs: []string{"foo"}, + ExtraArgs: map[string]string{"foo": "foo"}, + } + obj.NodeRegistration = kubeadm.NodeRegistrationOptions{ + CRISocket: "foo", + Name: "foo", + Taints: []v1.Taint{}, } obj.KubeletConfiguration = kubeadm.KubeletConfiguration{ BaseConfig: &kubeletconfigv1beta1.KubeletConfiguration{ StaticPodPath: "foo", ClusterDNS: []string{"foo"}, ClusterDomain: "foo", - Authorization: kubeletconfigv1beta1.KubeletAuthorization{Mode: "foo"}, + Authorization: kubeletconfigv1beta1.KubeletAuthorization{ + Mode: "Webhook", + }, Authentication: kubeletconfigv1beta1.KubeletAuthentication{ - X509: kubeletconfigv1beta1.KubeletX509Authentication{ClientCAFile: "foo"}, + X509: kubeletconfigv1beta1.KubeletX509Authentication{ + ClientCAFile: "/etc/kubernetes/pki/ca.crt", + }, + Anonymous: kubeletconfigv1beta1.KubeletAnonymousAuthentication{ + Enabled: utilpointer.BoolPtr(false), + }, }, + RotateCertificates: true, }, } kubeletconfigv1beta1.SetDefaults_KubeletConfiguration(obj.KubeletConfiguration.BaseConfig) @@ -127,9 +148,14 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { obj.DiscoveryFile = "foo" obj.DiscoveryToken = "foo" obj.DiscoveryTokenAPIServers = []string{"foo"} + obj.DiscoveryTimeout = &metav1.Duration{Duration: 1} obj.TLSBootstrapToken = "foo" obj.Token = "foo" - obj.CRISocket = "foo" + obj.ClusterName = "foo" + obj.NodeRegistration = kubeadm.NodeRegistrationOptions{ + CRISocket: "foo", + Name: "foo", + } }, } } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer_test.go new file mode 100644 index 000000000..79d99c3ce --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer_test.go @@ -0,0 +1,28 @@ +/* +Copyright 2018 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 fuzzer + +import ( + "testing" + + "k8s.io/apimachinery/pkg/api/testing/roundtrip" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" +) + +func TestRoundTripTypes(t *testing.T) { + roundtrip.RoundTripTestForAPIGroup(t, scheme.AddToScheme, Funcs) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/BUILD deleted file mode 100644 index 891b07141..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/BUILD +++ /dev/null @@ -1,47 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "install.go", - ], - importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install", - deps = [ - "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", - "//pkg/api/legacyscheme:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) - -go_test( - name = "go_default_test", - srcs = ["install_test.go"], - embed = [":go_default_library"], - deps = [ - "//cmd/kubeadm/app/apis/kubeadm/fuzzer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library", - ], -) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/doc.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/doc.go deleted file mode 100644 index a00b1043e..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/doc.go +++ /dev/null @@ -1,17 +0,0 @@ -/* -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 install // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install.go deleted file mode 100644 index 0e1ebfca4..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -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 install - -import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" - "k8s.io/kubernetes/pkg/api/legacyscheme" -) - -func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) -} - -// Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: kubeadm.GroupName, - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: kubeadm.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install_test.go deleted file mode 100644 index 116033df7..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install_test.go +++ /dev/null @@ -1,28 +0,0 @@ -/* -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 install - -import ( - "testing" - - "k8s.io/apimachinery/pkg/api/testing/roundtrip" - kubeadmfuzzer "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer" -) - -func TestRoundTripTypes(t *testing.T) { - roundtrip.RoundTripTestForAPIGroup(t, Install, kubeadmfuzzer.Funcs) -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme/BUILD new file mode 100644 index 000000000..a3e84850b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["scheme.go"], + importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme", + visibility = ["//visibility:public"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme/scheme.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme/scheme.go new file mode 100644 index 000000000..c7d477d71 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme/scheme.go @@ -0,0 +1,46 @@ +/* +Copyright 2018 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 scheme + +import ( + 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" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" +) + +// Scheme is the runtime.Scheme to which all kubeadm api types are registered. +var Scheme = runtime.NewScheme() + +// Codecs provides access to encoding and decoding for the scheme. +var Codecs = serializer.NewCodecFactory(Scheme) + +func init() { + metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + AddToScheme(Scheme) +} + +// AddToScheme builds the Kubeadm scheme using all known versions of the kubeadm api. +func AddToScheme(scheme *runtime.Scheme) { + kubeadm.AddToScheme(scheme) + v1alpha1.AddToScheme(scheme) + v1alpha2.AddToScheme(scheme) + scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go index 5f6c6c1b1..4391cfe64 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go @@ -17,6 +17,8 @@ limitations under the License. package kubeadm import ( + fuzz "github.com/google/gofuzz" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" @@ -30,6 +32,21 @@ import ( type MasterConfiguration struct { metav1.TypeMeta + // `kubeadm init`-only information. These fields are solely used the first time `kubeadm init` runs. + // After that, the information in the fields ARE NOT uploaded to the `kubeadm-config` ConfigMap + // that is used by `kubeadm upgrade` for instance. + + // BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create. + // This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature + BootstrapTokens []BootstrapToken + + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions + + // Cluster-wide configuration + // TODO: Move these fields under some kind of ClusterConfiguration or similar struct that describes + // one cluster. Eventually we want this kind of spec to align well with the Cluster API spec. + // API holds configuration for the k8s apiserver. API API // KubeProxy holds configuration for the k8s service proxy. @@ -42,37 +59,6 @@ type MasterConfiguration struct { Networking Networking // KubernetesVersion is the target version of the control plane. KubernetesVersion string - // CloudProvider is the name of the cloud provider. - CloudProvider string - // NodeName is the name of the node that will host the k8s control plane. - // Defaults to the hostname if not provided. - NodeName string - // AuthorizationModes is a set of authorization modes used inside the cluster. - // If not specified, defaults to Node and RBAC, meaning both the node - // authorizer and RBAC are enabled. - AuthorizationModes []string - // NoTaintMaster will, if set, suppress the tainting of the - // master node allowing workloads to be run on it (e.g. in - // single node configurations). - NoTaintMaster bool - - // Mark the controller and api server pods as privileged as some cloud - // controllers like openstack need escalated privileges under some conditions - // example - loading a config drive to fetch node information. - PrivilegedPods bool - - // Token is used for establishing bidirectional trust between nodes and masters. - // Used for joining nodes in the cluster. - Token string - // TokenTTL defines the ttl for Token. Defaults to 24h. - TokenTTL *metav1.Duration - // TokenUsages describes the ways in which this token can be used. - TokenUsages []string - // Extra groups that this token will authenticate as when used for authentication - TokenGroups []string - - // CRISocket is used to retrieve container runtime info. - CRISocket string // APIServerExtraArgs is a set of extra flags to pass to the API Server or override // default ones in form of =. @@ -104,9 +90,6 @@ type MasterConfiguration struct { // CertificatesDir specifies where to store or look for all required certificates. CertificatesDir string - // ImagePullPolicy for control plane images. Can be Always, IfNotPresent or Never. - ImagePullPolicy v1.PullPolicy - // ImageRepository is the container registry to pull control plane images from. ImageRepository string @@ -124,29 +107,52 @@ type MasterConfiguration struct { // FeatureGates enabled by the user. FeatureGates map[string]bool + + // The cluster name + ClusterName string } // API struct contains elements of API server address. type API struct { // AdvertiseAddress sets the IP address for the API server to advertise. AdvertiseAddress string - // ControlPlaneEndpoint sets the DNS address for the API server + // ControlPlaneEndpoint sets a stable IP address or DNS name for the control plane; it + // can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port. + // In case the ControlPlaneEndpoint is not specified, the AdvertiseAddress + BindPort + // are used; in case the ControlPlaneEndpoint is specified but without a TCP port, + // the BindPort is used. + // Possible usages are: + // e.g. In an cluster with more than one control plane instances, this field should be + // assigned the address of the external load balancer in front of the + // control plane instances. + // e.g. in environments with enforced node recycling, the ControlPlaneEndpoint + // could be used for assigning a stable DNS to the control plane. ControlPlaneEndpoint string // BindPort sets the secure port for the API Server to bind to. // Defaults to 6443. BindPort int32 } -// TokenDiscovery contains elements needed for token discovery. -type TokenDiscovery struct { - // ID is the first part of a bootstrap token. Considered public information. - // It is used when referring to a token without leaking the secret part. - ID string - // Secret is the second part of a bootstrap token. Should only be shared - // with trusted parties. - Secret string - // TODO: Seems unused. Remove? - // Addresses []string +// NodeRegistrationOptions holds fields that relate to registering a new master or node to the cluster, either via "kubeadm init" or "kubeadm join" +type NodeRegistrationOptions struct { + + // Name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm joiń` operation. + // This field is also used in the CommonName field of the kubelet's client certificate to the API server. + // Defaults to the hostname of the node if not provided. + Name string + + // CRISocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-use + CRISocket string + + // Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process + // it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your master node, set this field to an + // empty slice, i.e. `taints: {}` in the YAML file. This field is solely used for Node registration. + Taints []v1.Taint + + // KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file + // kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap + // Flags have higher higher priority when parsing. These values are local and specific to the node kubeadm is executing on. + KubeletExtraArgs map[string]string } // Networking contains elements describing cluster's networking configuration. @@ -159,48 +165,84 @@ type Networking struct { DNSDomain string } +// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster +// TODO: The BootstrapToken object should move out to either k8s.io/client-go or k8s.io/api in the future +// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now. +type BootstrapToken struct { + // Token is used for establishing bidirectional trust between nodes and masters. + // Used for joining nodes in the cluster. + Token *BootstrapTokenString + // Description sets a human-friendly message why this token exists and what it's used + // for, so other administrators can know its purpose. + Description string + // TTL defines the time to live for this token. Defaults to 24h. + // Expires and TTL are mutually exclusive. + TTL *metav1.Duration + // Expires specifies the timestamp when this token expires. Defaults to being set + // dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive. + Expires *metav1.Time + // Usages describes the ways in which this token can be used. Can by default be used + // for establishing bidirectional trust, but that can be changed here. + Usages []string + // Groups specifies the extra groups that this token will authenticate as when/if + // used for authentication + Groups []string +} + // Etcd contains elements describing Etcd configuration. type Etcd struct { - // Endpoints of etcd members. Useful for using external etcd. - // If not provided, kubeadm will run etcd in a static pod. - Endpoints []string - // CAFile is an SSL Certificate Authority file used to secure etcd communication. - CAFile string - // CertFile is an SSL certification file used to secure etcd communication. - CertFile string - // KeyFile is an SSL key file used to secure etcd communication. - KeyFile string + + // Local provides configuration knobs for configuring the local etcd instance + // Local and External are mutually exclusive + Local *LocalEtcd + + // External describes how to connect to an external etcd cluster + // Local and External are mutually exclusive + External *ExternalEtcd +} + +// Fuzz is a dummy function here to get the roundtrip tests working in cmd/kubeadm/app/apis/kubeadm/fuzzer working. +// As we split the monolith-etcd struct into two smaller pieces with pointers and they are mutually exclusive, roundtrip +// tests that randomize all values in this struct isn't feasible. Instead, we override the fuzzing function for .Etcd with +// this func by letting Etcd implement the fuzz.Interface interface. As this func does nothing, we rely on the values given +// in fuzzer/fuzzer.go for the roundtrip tests, which is exactly what we want. +// TODO: Remove this function when we remove the v1alpha1 API +func (e Etcd) Fuzz(c fuzz.Continue) {} + +// LocalEtcd describes that kubeadm should run an etcd cluster locally +type LocalEtcd struct { + + // Image specifies which container image to use for running etcd. + // If empty, automatically populated by kubeadm using the image + // repository and default etcd version. + Image string + // DataDir is the directory etcd will place its data. // Defaults to "/var/lib/etcd". DataDir string + // ExtraArgs are extra arguments provided to the etcd binary // when run inside a static pod. ExtraArgs map[string]string - // Image specifies which container image to use for running etcd. - // If empty, automatically populated by kubeadm using the image - // repository and default etcd version. - Image string - // SelfHosted holds configuration for self-hosting etcd. - SelfHosted *SelfHostedEtcd - // ServerCertSANs sets extra Subject Alternative Names for the etcd server - // signing cert. This is currently used for the etcd static-pod. + + // ServerCertSANs sets extra Subject Alternative Names for the etcd server signing cert. ServerCertSANs []string - // PeerCertSANs sets extra Subject Alternative Names for the etcd peer - // signing cert. This is currently used for the etcd static-pod. + // PeerCertSANs sets extra Subject Alternative Names for the etcd peer signing cert. PeerCertSANs []string } -// SelfHostedEtcd describes options required to configure self-hosted etcd. -type SelfHostedEtcd struct { - // CertificatesDir represents the directory where all etcd TLS assets are stored. - // Defaults to "/etc/kubernetes/pki/etcd". - CertificatesDir string - // ClusterServiceName is the name of the service that load balances the etcd cluster. - ClusterServiceName string - // EtcdVersion is the version of etcd running in the cluster. - EtcdVersion string - // OperatorVersion is the version of the etcd-operator to use. - OperatorVersion string +// ExternalEtcd describes an external etcd cluster +type ExternalEtcd struct { + + // Endpoints of etcd members. Useful for using external etcd. + // If not provided, kubeadm will run etcd in a static pod. + Endpoints []string + // CAFile is an SSL Certificate Authority file used to secure etcd communication. + CAFile string + // CertFile is an SSL certification file used to secure etcd communication. + CertFile string + // KeyFile is an SSL key file used to secure etcd communication. + KeyFile string } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -210,6 +252,9 @@ type SelfHostedEtcd struct { type NodeConfiguration struct { metav1.TypeMeta + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions + // CACertPath is the path to the SSL certificate authority used to // secure comunications between node and master. // Defaults to "/etc/kubernetes/pki/ca.crt". @@ -224,16 +269,15 @@ type NodeConfiguration struct { // will be fetched. Currently we only pay attention to one API server but // hope to support >1 in the future. DiscoveryTokenAPIServers []string - // NodeName is the name of the node to join the cluster. Defaults - // to the name of the host. - NodeName string + // DiscoveryTimeout modifies the discovery timeout + DiscoveryTimeout *metav1.Duration // TLSBootstrapToken is a token used for TLS bootstrapping. // Defaults to Token. TLSBootstrapToken string // Token is used for both discovery and TLS bootstrapping. Token string - // CRISocket is used to retrieve container runtime info. - CRISocket string + // The cluster name + ClusterName string // DiscoveryTokenCACertHashes specifies a set of public key pins to verify // when token-based discovery is used. The root CA found during discovery @@ -281,6 +325,10 @@ type HostPathMount struct { HostPath string // MountPath is the path inside the pod where hostPath will be mounted. MountPath string + // Writable controls write access to the volume + Writable bool + // PathType is the type of the HostPath. + PathType v1.HostPathType } // KubeProxy contains elements describing the proxy configuration. @@ -298,3 +346,50 @@ type AuditPolicyConfiguration struct { LogMaxAge *int32 //TODO(chuckha) add other options for audit policy. } + +// CommonConfiguration defines the list of common configuration elements and the getter +// methods that must exist for both the MasterConfiguration and NodeConfiguration objects. +// This is used internally to deduplicate the kubeadm preflight checks. +type CommonConfiguration interface { + GetCRISocket() string + GetNodeName() string + GetKubernetesVersion() string +} + +// GetCRISocket will return the CRISocket that is defined for the MasterConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *MasterConfiguration) GetCRISocket() string { + return cfg.NodeRegistration.CRISocket +} + +// GetNodeName will return the NodeName that is defined for the MasterConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *MasterConfiguration) GetNodeName() string { + return cfg.NodeRegistration.Name +} + +// GetKubernetesVersion will return the KubernetesVersion that is defined for the MasterConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *MasterConfiguration) GetKubernetesVersion() string { + return cfg.KubernetesVersion +} + +// GetCRISocket will return the CRISocket that is defined for the NodeConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *NodeConfiguration) GetCRISocket() string { + return cfg.NodeRegistration.CRISocket +} + +// GetNodeName will return the NodeName that is defined for the NodeConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *NodeConfiguration) GetNodeName() string { + return cfg.NodeRegistration.Name +} + +// GetKubernetesVersion will return an empty string since KubernetesVersion is not a +// defined property for NodeConfiguration. This will just cause the regex validation +// of the defined version to be skipped during the preflight checks. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *NodeConfiguration) GetKubernetesVersion() string { + return "" +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD index ba481069f..8315ddde7 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD @@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "conversion.go", "defaults.go", "doc.go", "register.go", @@ -52,21 +53,19 @@ go_library( deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", - "//cmd/kubeadm/app/features:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", - "//vendor/github.com/json-iterator/go:go_default_library", + "//pkg/util/pointer:go_default_library", "//vendor/github.com/ugorji/go/codec:go_default_library", - "//vendor/gopkg.in/yaml.v2:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/conversion: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:go_default_library", ], ) @@ -91,3 +90,13 @@ go_test( embed = [":go_default_library"], deps = ["//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library"], ) + +go_test( + name = "go_default_xtest", + srcs = ["conversion_test.go"], + deps = [ + ":go_default_library", + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion.go new file mode 100644 index 000000000..3bbad16e7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion.go @@ -0,0 +1,226 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + "fmt" + "reflect" + "strings" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" +) + +func addConversionFuncs(scheme *runtime.Scheme) error { + // Add non-generated conversion functions + err := scheme.AddConversionFuncs( + Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration, + Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration, + Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration, + Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration, + Convert_v1alpha1_Etcd_To_kubeadm_Etcd, + Convert_kubeadm_Etcd_To_v1alpha1_Etcd, + ) + if err != nil { + return err + } + + return nil +} + +// Upgrades below + +func Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error { + if err := autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in, out, s); err != nil { + return err + } + + UpgradeCloudProvider(in, out) + UpgradeAuthorizationModes(in, out) + UpgradeNodeRegistrationOptionsForMaster(in, out) + if err := UpgradeBootstrapTokens(in, out); err != nil { + return err + } + // We don't support migrating information from the .PrivilegedPods field which was removed in v1alpha2 + // We don't support migrating information from the .ImagePullPolicy field which was removed in v1alpha2 + + return nil +} + +func Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error { + if err := autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in, out, s); err != nil { + return err + } + + // .NodeName has moved to .NodeRegistration.Name + out.NodeRegistration.Name = in.NodeName + // .CRISocket has moved to .NodeRegistration.CRISocket + out.NodeRegistration.CRISocket = in.CRISocket + + return nil +} + +func Convert_v1alpha1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error { + if err := autoConvert_v1alpha1_Etcd_To_kubeadm_Etcd(in, out, s); err != nil { + return err + } + + // The .Etcd schema changed between v1alpha1 and v1alpha2 API types. The change was to basically only split up the fields into two sub-structs, which can be seen here + if len(in.Endpoints) != 0 { + out.External = &kubeadm.ExternalEtcd{ + Endpoints: in.Endpoints, + CAFile: in.CAFile, + CertFile: in.CertFile, + KeyFile: in.KeyFile, + } + } else { + out.Local = &kubeadm.LocalEtcd{ + Image: in.Image, + DataDir: in.DataDir, + ExtraArgs: in.ExtraArgs, + ServerCertSANs: in.ServerCertSANs, + PeerCertSANs: in.PeerCertSANs, + } + } + + // No need to transfer information about .Etcd.Selfhosted to v1alpha2 + return nil +} + +// UpgradeCloudProvider handles the removal of .CloudProvider as smoothly as possible +func UpgradeCloudProvider(in *MasterConfiguration, out *kubeadm.MasterConfiguration) { + if len(in.CloudProvider) != 0 { + if out.APIServerExtraArgs == nil { + out.APIServerExtraArgs = map[string]string{} + } + if out.ControllerManagerExtraArgs == nil { + out.ControllerManagerExtraArgs = map[string]string{} + } + if out.NodeRegistration.KubeletExtraArgs == nil { + out.NodeRegistration.KubeletExtraArgs = map[string]string{} + } + + out.APIServerExtraArgs["cloud-provider"] = in.CloudProvider + out.ControllerManagerExtraArgs["cloud-provider"] = in.CloudProvider + out.NodeRegistration.KubeletExtraArgs["cloud-provider"] = in.CloudProvider + } +} + +func UpgradeAuthorizationModes(in *MasterConfiguration, out *kubeadm.MasterConfiguration) { + // If .AuthorizationModes was set to something else than the default, preserve the information via extraargs + if !reflect.DeepEqual(in.AuthorizationModes, strings.Split(DefaultAuthorizationModes, ",")) { + + if out.APIServerExtraArgs == nil { + out.APIServerExtraArgs = map[string]string{} + } + out.APIServerExtraArgs["authorization-mode"] = strings.Join(in.AuthorizationModes, ",") + } +} + +func UpgradeNodeRegistrationOptionsForMaster(in *MasterConfiguration, out *kubeadm.MasterConfiguration) { + // .NodeName has moved to .NodeRegistration.Name + out.NodeRegistration.Name = in.NodeName + + // .CRISocket has moved to .NodeRegistration.CRISocket + out.NodeRegistration.CRISocket = in.CRISocket + + // Transfer the information from .NoTaintMaster to the new layout + if in.NoTaintMaster { + out.NodeRegistration.Taints = []v1.Taint{} + } else { + out.NodeRegistration.Taints = []v1.Taint{constants.MasterTaint} + } +} + +// UpgradeBootstrapTokens should create at least one empty bootstrap token in the out config. +func UpgradeBootstrapTokens(in *MasterConfiguration, out *kubeadm.MasterConfiguration) error { + bts, err := kubeadm.NewBootstrapTokenString(in.Token) + // Ignore the error if the incoming token was empty. + if err != nil && in.Token != "" { + return fmt.Errorf("can't parse .Token, and hence can't convert v1alpha1 API to a newer version: %v", err) + } + + out.BootstrapTokens = []kubeadm.BootstrapToken{ + { + Token: bts, + TTL: in.TokenTTL, + Usages: in.TokenUsages, + Groups: in.TokenGroups, + }, + } + return nil +} + +// Downgrades below + +// This downgrade path IS NOT SUPPORTED. This is just here for roundtripping purposes at the moment. +func Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { + if err := autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in, out, s); err != nil { + return err + } + + // Converting from newer API version to an older API version isn't supported. This is here only for the roundtrip tests meanwhile. + out.NodeName = in.NodeRegistration.Name + out.CRISocket = in.NodeRegistration.CRISocket + out.NoTaintMaster = in.NodeRegistration.Taints != nil && len(in.NodeRegistration.Taints) == 0 + + if len(in.BootstrapTokens) > 0 { + out.Token = in.BootstrapTokens[0].Token.String() + out.TokenTTL = in.BootstrapTokens[0].TTL + out.TokenUsages = in.BootstrapTokens[0].Usages + out.TokenGroups = in.BootstrapTokens[0].Groups + } + + return nil +} + +// This downgrade path IS NOT SUPPORTED. This is just here for roundtripping purposes at the moment. +func Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error { + if err := autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in, out, s); err != nil { + return err + } + + // Converting from newer API version to an older API version isn't supported. This is here only for the roundtrip tests meanwhile. + out.NodeName = in.NodeRegistration.Name + out.CRISocket = in.NodeRegistration.CRISocket + return nil +} + +// This downgrade path IS NOT SUPPORTED. This is just here for roundtripping purposes at the moment. +func Convert_kubeadm_Etcd_To_v1alpha1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error { + if err := autoConvert_kubeadm_Etcd_To_v1alpha1_Etcd(in, out, s); err != nil { + return err + } + + if in.External != nil { + out.Endpoints = in.External.Endpoints + out.CAFile = in.External.CAFile + out.CertFile = in.External.CertFile + out.KeyFile = in.External.KeyFile + } else { + out.Image = in.Local.Image + out.DataDir = in.Local.DataDir + out.ExtraArgs = in.Local.ExtraArgs + out.ServerCertSANs = in.Local.ServerCertSANs + out.PeerCertSANs = in.Local.PeerCertSANs + } + + return nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion_test.go new file mode 100644 index 000000000..52fcc3db8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/conversion_test.go @@ -0,0 +1,103 @@ +/* +Copyright 2018 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 v1alpha1_test + +import ( + "reflect" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" +) + +func TestUpgradeBootstrapTokens(t *testing.T) { + testcases := []struct { + name string + in *v1alpha1.MasterConfiguration + expectedOut *kubeadm.MasterConfiguration + expectError bool + }{ + { + name: "empty configs should create at least one token", + in: &v1alpha1.MasterConfiguration{}, + expectedOut: &kubeadm.MasterConfiguration{ + BootstrapTokens: []kubeadm.BootstrapToken{ + { + Token: nil, + }, + }, + }, + expectError: false, + }, + { + name: "fail at parsing incoming token", + in: &v1alpha1.MasterConfiguration{ + Token: "some fake token", + }, + expectError: true, + }, + { + name: "input has values", + in: &v1alpha1.MasterConfiguration{ + Token: "abcdef.abcdefghijklmnop", + TokenTTL: &metav1.Duration{ + Duration: time.Duration(10 * time.Hour), + }, + TokenUsages: []string{"action"}, + TokenGroups: []string{"group", "group2"}, + }, + expectedOut: &kubeadm.MasterConfiguration{ + BootstrapTokens: []kubeadm.BootstrapToken{ + { + Token: &kubeadm.BootstrapTokenString{ + ID: "abcdef", + Secret: "abcdefghijklmnop", + }, + TTL: &metav1.Duration{ + Duration: time.Duration(10 * time.Hour), + }, + Usages: []string{"action"}, + Groups: []string{"group", "group2"}, + }, + }, + }, + expectError: false, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + out := &kubeadm.MasterConfiguration{} + err := v1alpha1.UpgradeBootstrapTokens(tc.in, out) + + if tc.expectError { + if err == nil { + t.Fatal("expected an error but did not get one.") + } + // do not continue if we got an expected error + return + } + + if !reflect.DeepEqual(out.BootstrapTokens, tc.expectedOut.BootstrapTokens) { + t.Fatalf("\nexpected: %v\ngot: %v", tc.expectedOut.BootstrapTokens, out.BootstrapTokens) + } + }) + } + +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go index 5d21a860b..bb30de78c 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go @@ -19,15 +19,16 @@ package v1alpha1 import ( "net/url" "strings" + "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" kubeproxyscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme" kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" + utilpointer "k8s.io/kubernetes/pkg/util/pointer" ) const ( @@ -38,7 +39,7 @@ const ( // DefaultClusterDNSIP defines default DNS IP DefaultClusterDNSIP = "10.96.0.10" // DefaultKubernetesVersion defines default kubernetes version - DefaultKubernetesVersion = "stable-1.10" + DefaultKubernetesVersion = "stable-1.11" // DefaultAPIBindPort defines default API port DefaultAPIBindPort = 6443 // DefaultAuthorizationModes defines default authorization modes @@ -51,6 +52,8 @@ const ( DefaultManifestsDir = "/etc/kubernetes/manifests" // DefaultCRISocket defines the default cri socket DefaultCRISocket = "/var/run/dockershim.sock" + // DefaultClusterName defines the default cluster name + DefaultClusterName = "kubernetes" // DefaultEtcdDataDir defines default location of etcd where static pods will save data to DefaultEtcdDataDir = "/var/lib/etcd" @@ -68,6 +71,9 @@ const ( DefaultProxyBindAddressv6 = "::" // KubeproxyKubeConfigFileName defines the file name for the kube-proxy's KubeConfig file KubeproxyKubeConfigFileName = "/var/lib/kube-proxy/kubeconfig.conf" + + // DefaultDiscoveryTimeout specifies the default discovery timeout for kubeadm (used unless one is specified in the NodeConfiguration) + DefaultDiscoveryTimeout = 5 * time.Minute ) var ( @@ -132,10 +138,12 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) { obj.Etcd.DataDir = DefaultEtcdDataDir } - SetDefaultsEtcdSelfHosted(obj) - if features.Enabled(obj.FeatureGates, features.DynamicKubeletConfig) { - SetDefaults_KubeletConfiguration(obj) + if obj.ClusterName == "" { + obj.ClusterName = DefaultClusterName } + + SetDefaultsEtcdSelfHosted(obj) + SetDefaults_KubeletConfiguration(obj) SetDefaults_ProxyConfiguration(obj) SetDefaults_AuditPolicyConfiguration(obj) } @@ -177,6 +185,14 @@ func SetDefaults_NodeConfiguration(obj *NodeConfiguration) { obj.DiscoveryFile = u.Path } } + if obj.DiscoveryTimeout == nil { + obj.DiscoveryTimeout = &metav1.Duration{ + Duration: DefaultDiscoveryTimeout, + } + } + if obj.ClusterName == "" { + obj.ClusterName = DefaultClusterName + } } // SetDefaultsEtcdSelfHosted sets defaults for self-hosted etcd if used @@ -217,15 +233,32 @@ func SetDefaults_KubeletConfiguration(obj *MasterConfiguration) { } } if obj.KubeletConfiguration.BaseConfig.ClusterDomain == "" { - obj.KubeletConfiguration.BaseConfig.ClusterDomain = DefaultServiceDNSDomain - } - if obj.KubeletConfiguration.BaseConfig.Authorization.Mode == "" { - obj.KubeletConfiguration.BaseConfig.Authorization.Mode = kubeletconfigv1beta1.KubeletAuthorizationModeWebhook - } - if obj.KubeletConfiguration.BaseConfig.Authentication.X509.ClientCAFile == "" { - obj.KubeletConfiguration.BaseConfig.Authentication.X509.ClientCAFile = DefaultCACertPath + obj.KubeletConfiguration.BaseConfig.ClusterDomain = obj.Networking.DNSDomain } + // Enforce security-related kubelet options + + // Require all clients to the kubelet API to have client certs signed by the cluster CA + obj.KubeletConfiguration.BaseConfig.Authentication.X509.ClientCAFile = DefaultCACertPath + obj.KubeletConfiguration.BaseConfig.Authentication.Anonymous.Enabled = utilpointer.BoolPtr(false) + + // On every client request to the kubelet API, execute a webhook (SubjectAccessReview request) to the API server + // and ask it whether the client is authorized to access the kubelet API + obj.KubeletConfiguration.BaseConfig.Authorization.Mode = kubeletconfigv1beta1.KubeletAuthorizationModeWebhook + + // Let clients using other authentication methods like ServiceAccount tokens also access the kubelet API + obj.KubeletConfiguration.BaseConfig.Authentication.Webhook.Enabled = utilpointer.BoolPtr(true) + + // Disable the readonly port of the kubelet, in order to not expose unnecessary information + obj.KubeletConfiguration.BaseConfig.ReadOnlyPort = 0 + + // Enables client certificate rotation for the kubelet + obj.KubeletConfiguration.BaseConfig.RotateCertificates = true + + // Serve a /healthz webserver on localhost:10248 that kubeadm can talk to + obj.KubeletConfiguration.BaseConfig.HealthzBindAddress = "127.0.0.1" + obj.KubeletConfiguration.BaseConfig.HealthzPort = utilpointer.Int32Ptr(10248) + scheme, _, _ := kubeletscheme.NewSchemeAndCodecs() if scheme != nil { scheme.Default(obj.KubeletConfiguration.BaseConfig) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/register.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/register.go index 3f3e75e62..abb323ac5 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/register.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/register.go @@ -43,7 +43,7 @@ func init() { // We only register manually written functions here. The registration of the // generated functions takes place in the generated files. The separation // makes the code compile even when the generated files are missing. - localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs) + localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs, addConversionFuncs) } // Kind takes an unqualified kind and returns a Group qualified GroupKind diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/testdata/kubeadm196.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/testdata/kubeadm196.yaml deleted file mode 100644 index 08ee0b485..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/testdata/kubeadm196.yaml +++ /dev/null @@ -1,62 +0,0 @@ -api: - advertiseAddress: 172.31.93.180 - bindPort: 6443 -authorizationModes: -- Node -- RBAC -certificatesDir: /etc/kubernetes/pki -cloudProvider: aws -etcd: - caFile: "" - certFile: "" - dataDir: /var/lib/etcd - endpoints: null - image: "" - keyFile: "" -imageRepository: gcr.io/google_containers -kubeProxy: - config: - bindAddress: 0.0.0.0 - clientConnection: - acceptContentTypes: "" - burst: 10 - contentType: application/vnd.kubernetes.protobuf - kubeconfig: /var/lib/kube-proxy/kubeconfig.conf - qps: 5 - clusterCIDR: 192.168.0.0/16 - configSyncPeriod: 15m0s - conntrack: - max: null - maxPerCore: 32768 - min: 131072 - tcpCloseWaitTimeout: 1h0m0s - tcpEstablishedTimeout: 24h0m0s - enableProfiling: false - featureGates: "" - healthzBindAddress: 0.0.0.0:10256 - hostnameOverride: "" - iptables: - masqueradeAll: false - masqueradeBit: 14 - minSyncPeriod: 0s - syncPeriod: 30s - ipvs: - minSyncPeriod: 0s - scheduler: "" - syncPeriod: 30s - metricsBindAddress: 127.0.0.1:10249 - mode: "" - oomScoreAdj: -999 - portRange: "" - resourceContainer: /kube-proxy - udpTimeoutMilliseconds: 250ms -kubeletConfiguration: {} -kubernetesVersion: v1.9.6 -networking: - dnsDomain: cluster.local - podSubnet: 192.168.0.0/16 - serviceSubnet: 10.96.0.0/12 -nodeName: ip-172-31-93-180.ec2.internal -token: 8d69af.cd3e1c58f6228dfc -tokenTTL: 24h0m0s -unifiedControlPlaneImage: "" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go index 76911cf39..c5f8ab9e2 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go @@ -116,13 +116,26 @@ type MasterConfiguration struct { // FeatureGates enabled by the user. FeatureGates map[string]bool `json:"featureGates,omitempty"` + + // The cluster name + ClusterName string `json:"clusterName,omitempty"` } // API struct contains elements of API server address. type API struct { // AdvertiseAddress sets the IP address for the API server to advertise. AdvertiseAddress string `json:"advertiseAddress"` - // ControlPlaneEndpoint sets the DNS address for the API server + // ControlPlaneEndpoint sets a stable IP address or DNS name for the control plane; it + // can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port. + // In case the ControlPlaneEndpoint is not specified, the AdvertiseAddress + BindPort + // are used; in case the ControlPlaneEndpoint is specified but without a TCP port, + // the BindPort is used. + // Possible usages are: + // e.g. In an cluster with more than one control plane instances, this field should be + // assigned the address of the external load balancer in front of the + // control plane instances. + // e.g. in environments with enforced node recycling, the ControlPlaneEndpoint + // could be used for assigning a stable DNS to the control plane. ControlPlaneEndpoint string `json:"controlPlaneEndpoint"` // BindPort sets the secure port for the API Server to bind to. // Defaults to 6443. @@ -214,6 +227,8 @@ type NodeConfiguration struct { // will be fetched. Currently we only pay attention to one API server but // hope to support >1 in the future. DiscoveryTokenAPIServers []string `json:"discoveryTokenAPIServers,omitempty"` + // DiscoveryTimeout modifies the discovery timeout + DiscoveryTimeout *metav1.Duration `json:"discoveryTimeout,omitempty"` // NodeName is the name of the node to join the cluster. Defaults // to the name of the host. NodeName string `json:"nodeName"` @@ -224,6 +239,8 @@ type NodeConfiguration struct { Token string `json:"token"` // CRISocket is used to retrieve container runtime info. CRISocket string `json:"criSocket,omitempty"` + // ClusterName is the name for the cluster in kubeconfig. + ClusterName string `json:"clusterName,omitempty"` // DiscoveryTokenCACertHashes specifies a set of public key pins to verify // when token-based discovery is used. The root CA found during discovery @@ -259,6 +276,10 @@ type HostPathMount struct { HostPath string `json:"hostPath"` // MountPath is the path inside the pod where hostPath will be mounted. MountPath string `json:"mountPath"` + // Writable controls write access to the volume + Writable bool `json:"writable,omitempty"` + // PathType is the type of the HostPath. + PathType v1.HostPathType `json:"pathType,omitempty"` } // KubeProxy contains elements describing the proxy configuration. diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade.go index 212ef0d75..7c3dd133f 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade.go @@ -18,23 +18,18 @@ package v1alpha1 import ( "bytes" - "errors" "fmt" "reflect" "strconv" "strings" - "github.com/json-iterator/go" "github.com/ugorji/go/codec" - yaml "gopkg.in/yaml.v2" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - runtime "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" ) -var json = jsoniter.ConfigCompatibleWithStandardLibrary - type configMutationFunc func(map[string]interface{}) error // These migrations are a stop-gap until we get a properly-versioned configuration file for MasterConfiguration. @@ -47,7 +42,7 @@ var migrations = map[string][]configMutationFunc{ // Migrate takes a map representing a config file and an object to decode into. // The map is transformed into a format suitable for encoding into the supplied object, then serialised and decoded. -func Migrate(in map[string]interface{}, obj runtime.Object) error { +func Migrate(in map[string]interface{}, obj runtime.Object, codecs serializer.CodecFactory) error { kind := reflect.TypeOf(obj).Elem().Name() migrationsForKind := migrations[kind] @@ -65,7 +60,7 @@ func Migrate(in map[string]interface{}, obj runtime.Object) error { return fmt.Errorf("couldn't json encode object: %v", err) } - return runtime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), buf.Bytes(), obj) + return runtime.DecodeInto(codecs.UniversalDecoder(), buf.Bytes(), obj) } func proxyFeatureListToMap(m map[string]interface{}) error { @@ -101,35 +96,3 @@ func proxyFeatureListToMap(m map[string]interface{}) error { unstructured.SetNestedMap(m, gateMap, featureGatePath...) return nil } - -// LoadYAML is a small wrapper around go-yaml that ensures all nested structs are map[string]interface{} instead of map[interface{}]interface{}. -func LoadYAML(bytes []byte) (map[string]interface{}, error) { - var decoded map[interface{}]interface{} - if err := yaml.Unmarshal(bytes, &decoded); err != nil { - return map[string]interface{}{}, fmt.Errorf("couldn't unmarshal YAML: %v", err) - } - - converted, ok := convert(decoded).(map[string]interface{}) - if !ok { - return map[string]interface{}{}, errors.New("yaml is not a map") - } - - return converted, nil -} - -// https://stackoverflow.com/questions/40737122/convert-yaml-to-json-without-struct-golang -func convert(i interface{}) interface{} { - switch x := i.(type) { - case map[interface{}]interface{}: - m2 := map[string]interface{}{} - for k, v := range x { - m2[k.(string)] = convert(v) - } - return m2 - case []interface{}: - for i, v := range x { - x[i] = convert(v) - } - } - return i -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade_test.go index 6a1fca7e1..edb451dec 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/upgrade_test.go @@ -17,31 +17,11 @@ limitations under the License. package v1alpha1 import ( - "io/ioutil" "testing" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) -const test196 = "testdata/kubeadm196.yaml" - -func TestUpgrade(t *testing.T) { - testYAML, err := ioutil.ReadFile(test196) - if err != nil { - t.Fatalf("couldn't read test data: %v", err) - } - - decoded, err := LoadYAML(testYAML) - if err != nil { - t.Fatalf("couldn't unmarshal test yaml: %v", err) - } - - var obj MasterConfiguration - if err := Migrate(decoded, &obj); err != nil { - t.Fatalf("couldn't decode migrated object: %v", err) - } -} - func TestProxyFeatureListToMap(t *testing.T) { cases := []struct { diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go index 31a91217c..66fa39974 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -23,8 +23,8 @@ package v1alpha1 import ( unsafe "unsafe" - core_v1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/api/core/v1" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" @@ -58,10 +58,6 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kubeadm_Networking_To_v1alpha1_Networking, Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration, Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration, - Convert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd, - Convert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd, - Convert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery, - Convert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery, ) } @@ -114,47 +110,31 @@ func Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha1_AuditPolicyConfigurati } func autoConvert_v1alpha1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error { - out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints)) - out.CAFile = in.CAFile - out.CertFile = in.CertFile - out.KeyFile = in.KeyFile - out.DataDir = in.DataDir - out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) - out.Image = in.Image - out.SelfHosted = (*kubeadm.SelfHostedEtcd)(unsafe.Pointer(in.SelfHosted)) - out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) - out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) + // WARNING: in.Endpoints requires manual conversion: does not exist in peer-type + // WARNING: in.CAFile requires manual conversion: does not exist in peer-type + // WARNING: in.CertFile requires manual conversion: does not exist in peer-type + // WARNING: in.KeyFile requires manual conversion: does not exist in peer-type + // WARNING: in.DataDir requires manual conversion: does not exist in peer-type + // WARNING: in.ExtraArgs requires manual conversion: does not exist in peer-type + // WARNING: in.Image requires manual conversion: does not exist in peer-type + // WARNING: in.SelfHosted requires manual conversion: does not exist in peer-type + // WARNING: in.ServerCertSANs requires manual conversion: does not exist in peer-type + // WARNING: in.PeerCertSANs requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha1_Etcd_To_kubeadm_Etcd is an autogenerated conversion function. -func Convert_v1alpha1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error { - return autoConvert_v1alpha1_Etcd_To_kubeadm_Etcd(in, out, s) -} - func autoConvert_kubeadm_Etcd_To_v1alpha1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error { - out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints)) - out.CAFile = in.CAFile - out.CertFile = in.CertFile - out.KeyFile = in.KeyFile - out.DataDir = in.DataDir - out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) - out.Image = in.Image - out.SelfHosted = (*SelfHostedEtcd)(unsafe.Pointer(in.SelfHosted)) - out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) - out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) + // WARNING: in.Local requires manual conversion: does not exist in peer-type + // WARNING: in.External requires manual conversion: does not exist in peer-type return nil } -// Convert_kubeadm_Etcd_To_v1alpha1_Etcd is an autogenerated conversion function. -func Convert_kubeadm_Etcd_To_v1alpha1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error { - return autoConvert_kubeadm_Etcd_To_v1alpha1_Etcd(in, out, s) -} - func autoConvert_v1alpha1_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error { out.Name = in.Name out.HostPath = in.HostPath out.MountPath = in.MountPath + out.Writable = in.Writable + out.PathType = v1.HostPathType(in.PathType) return nil } @@ -167,6 +147,8 @@ func autoConvert_kubeadm_HostPathMount_To_v1alpha1_HostPathMount(in *kubeadm.Hos out.Name = in.Name out.HostPath = in.HostPath out.MountPath = in.MountPath + out.Writable = in.Writable + out.PathType = v1.HostPathType(in.PathType) return nil } @@ -232,16 +214,16 @@ func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in return err } out.KubernetesVersion = in.KubernetesVersion - out.CloudProvider = in.CloudProvider - out.NodeName = in.NodeName - out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes)) - out.NoTaintMaster = in.NoTaintMaster - out.PrivilegedPods = in.PrivilegedPods - out.Token = in.Token - out.TokenTTL = (*v1.Duration)(unsafe.Pointer(in.TokenTTL)) - out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages)) - out.TokenGroups = *(*[]string)(unsafe.Pointer(&in.TokenGroups)) - out.CRISocket = in.CRISocket + // WARNING: in.CloudProvider requires manual conversion: does not exist in peer-type + // WARNING: in.NodeName requires manual conversion: does not exist in peer-type + // WARNING: in.AuthorizationModes requires manual conversion: does not exist in peer-type + // WARNING: in.NoTaintMaster requires manual conversion: does not exist in peer-type + // WARNING: in.PrivilegedPods requires manual conversion: does not exist in peer-type + // WARNING: in.Token requires manual conversion: does not exist in peer-type + // WARNING: in.TokenTTL requires manual conversion: does not exist in peer-type + // WARNING: in.TokenUsages requires manual conversion: does not exist in peer-type + // WARNING: in.TokenGroups requires manual conversion: does not exist in peer-type + // WARNING: in.CRISocket requires manual conversion: does not exist in peer-type out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs)) out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs)) out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs)) @@ -251,21 +233,19 @@ func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs)) out.CertificatesDir = in.CertificatesDir out.ImageRepository = in.ImageRepository - out.ImagePullPolicy = core_v1.PullPolicy(in.ImagePullPolicy) + // WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage if err := Convert_v1alpha1_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(&in.AuditPolicyConfiguration, &out.AuditPolicyConfiguration, s); err != nil { return err } out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) + out.ClusterName = in.ClusterName return nil } -// Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration is an autogenerated conversion function. -func Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error { - return autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in, out, s) -} - func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { + // WARNING: in.BootstrapTokens requires manual conversion: does not exist in peer-type + // WARNING: in.NodeRegistration requires manual conversion: does not exist in peer-type if err := Convert_kubeadm_API_To_v1alpha1_API(&in.API, &out.API, s); err != nil { return err } @@ -282,16 +262,6 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in return err } out.KubernetesVersion = in.KubernetesVersion - out.CloudProvider = in.CloudProvider - out.NodeName = in.NodeName - out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes)) - out.NoTaintMaster = in.NoTaintMaster - out.PrivilegedPods = in.PrivilegedPods - out.Token = in.Token - out.TokenTTL = (*v1.Duration)(unsafe.Pointer(in.TokenTTL)) - out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages)) - out.TokenGroups = *(*[]string)(unsafe.Pointer(&in.TokenGroups)) - out.CRISocket = in.CRISocket out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs)) out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs)) out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs)) @@ -300,7 +270,6 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in out.SchedulerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.SchedulerExtraVolumes)) out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs)) out.CertificatesDir = in.CertificatesDir - out.ImagePullPolicy = core_v1.PullPolicy(in.ImagePullPolicy) out.ImageRepository = in.ImageRepository // INFO: in.CIImageRepository opted out of conversion generation out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage @@ -308,14 +277,10 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in return err } out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) + out.ClusterName = in.ClusterName return nil } -// Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration is an autogenerated conversion function. -func Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { - return autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in, out, s) -} - func autoConvert_v1alpha1_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error { out.ServiceSubnet = in.ServiceSubnet out.PodSubnet = in.PodSubnet @@ -345,85 +310,30 @@ func autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *Nod out.DiscoveryFile = in.DiscoveryFile out.DiscoveryToken = in.DiscoveryToken out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers)) - out.NodeName = in.NodeName + out.DiscoveryTimeout = (*meta_v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) + // WARNING: in.NodeName requires manual conversion: does not exist in peer-type out.TLSBootstrapToken = in.TLSBootstrapToken out.Token = in.Token - out.CRISocket = in.CRISocket + // WARNING: in.CRISocket requires manual conversion: does not exist in peer-type + out.ClusterName = in.ClusterName out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes)) out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) return nil } -// Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration is an autogenerated conversion function. -func Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error { - return autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in, out, s) -} - func autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error { + // WARNING: in.NodeRegistration requires manual conversion: does not exist in peer-type out.CACertPath = in.CACertPath out.DiscoveryFile = in.DiscoveryFile out.DiscoveryToken = in.DiscoveryToken out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers)) - out.NodeName = in.NodeName + out.DiscoveryTimeout = (*meta_v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) out.TLSBootstrapToken = in.TLSBootstrapToken out.Token = in.Token - out.CRISocket = in.CRISocket + out.ClusterName = in.ClusterName out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes)) out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) return nil } - -// Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration is an autogenerated conversion function. -func Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error { - return autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in, out, s) -} - -func autoConvert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd(in *SelfHostedEtcd, out *kubeadm.SelfHostedEtcd, s conversion.Scope) error { - out.CertificatesDir = in.CertificatesDir - out.ClusterServiceName = in.ClusterServiceName - out.EtcdVersion = in.EtcdVersion - out.OperatorVersion = in.OperatorVersion - return nil -} - -// Convert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd is an autogenerated conversion function. -func Convert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd(in *SelfHostedEtcd, out *kubeadm.SelfHostedEtcd, s conversion.Scope) error { - return autoConvert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd(in, out, s) -} - -func autoConvert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd(in *kubeadm.SelfHostedEtcd, out *SelfHostedEtcd, s conversion.Scope) error { - out.CertificatesDir = in.CertificatesDir - out.ClusterServiceName = in.ClusterServiceName - out.EtcdVersion = in.EtcdVersion - out.OperatorVersion = in.OperatorVersion - return nil -} - -// Convert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd is an autogenerated conversion function. -func Convert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd(in *kubeadm.SelfHostedEtcd, out *SelfHostedEtcd, s conversion.Scope) error { - return autoConvert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd(in, out, s) -} - -func autoConvert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery(in *TokenDiscovery, out *kubeadm.TokenDiscovery, s conversion.Scope) error { - out.ID = in.ID - out.Secret = in.Secret - return nil -} - -// Convert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery is an autogenerated conversion function. -func Convert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery(in *TokenDiscovery, out *kubeadm.TokenDiscovery, s conversion.Scope) error { - return autoConvert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery(in, out, s) -} - -func autoConvert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery(in *kubeadm.TokenDiscovery, out *TokenDiscovery, s conversion.Scope) error { - out.ID = in.ID - out.Secret = in.Secret - return nil -} - -// Convert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery is an autogenerated conversion function. -func Convert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery(in *kubeadm.TokenDiscovery, out *TokenDiscovery, s conversion.Scope) error { - return autoConvert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery(in, out, s) -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.deepcopy.go index 428f1e7af..0e2f11c41 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -309,6 +309,15 @@ func (in *NodeConfiguration) DeepCopyInto(out *NodeConfiguration) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.DiscoveryTimeout != nil { + in, out := &in.DiscoveryTimeout, &out.DiscoveryTimeout + if *in == nil { + *out = nil + } else { + *out = new(v1.Duration) + **out = **in + } + } if in.DiscoveryTokenCACertHashes != nil { in, out := &in.DiscoveryTokenCACertHashes, &out.DiscoveryTokenCACertHashes *out = make([]string, len(*in)) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go index 2d802f746..e1954bf38 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD new file mode 100644 index 000000000..380b5b6d8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD @@ -0,0 +1,88 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "bootstraptokenstring.go", + "defaults.go", + "doc.go", + "register.go", + "types.go", + "zz_generated.conversion.go", + "zz_generated.deepcopy.go", + "zz_generated.defaults.go", + ] + select({ + "@io_bazel_rules_go//go/platform:android": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:nacl": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "defaults_unix.go", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "defaults_windows.go", + ], + "//conditions:default": [], + }), + importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2", + visibility = ["//visibility:public"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", + "//pkg/util/pointer:go_default_library", + "//vendor/k8s.io/api/core/v1: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/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["bootstraptokenstring_test.go"], + embed = [":go_default_library"], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring.go new file mode 100644 index 000000000..d62d5a743 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring.go @@ -0,0 +1,90 @@ +/* +Copyright 2018 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 v1alpha2 holds the external kubeadm API types of version v1alpha2 +// Note: This file should be kept in sync with the similar one for the internal API +// TODO: The BootstrapTokenString object should move out to either k8s.io/client-go or k8s.io/api in the future +// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now. +package v1alpha2 + +import ( + "fmt" + "strings" + + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" +) + +// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used +// for both validation of the practically of the API server from a joining node's point +// of view and as an authentication method for the node in the bootstrap phase of +// "kubeadm join". This token is and should be short-lived +type BootstrapTokenString struct { + ID string + Secret string +} + +// MarshalJSON implements the json.Marshaler interface. +func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil +} + +// UnmarshalJSON implements the json.Unmarshaller interface. +func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error { + // If the token is represented as "", just return quickly without an error + if len(b) == 0 { + return nil + } + + // Remove unnecessary " characters coming from the JSON parser + token := strings.Replace(string(b), `"`, ``, -1) + // Convert the string Token to a BootstrapTokenString object + newbts, err := NewBootstrapTokenString(token) + if err != nil { + return err + } + bts.ID = newbts.ID + bts.Secret = newbts.Secret + return nil +} + +// String returns the string representation of the BootstrapTokenString +func (bts BootstrapTokenString) String() string { + if len(bts.ID) > 0 && len(bts.Secret) > 0 { + return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret) + } + return "" +} + +// NewBootstrapTokenString converts the given Bootstrap Token as a string +// to the BootstrapTokenString object used for serialization/deserialization +// and internal usage. It also automatically validates that the given token +// is of the right format +func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) { + substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token) + // TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works) + if len(substrs) != 3 { + return nil, fmt.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern) + } + + return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil +} + +// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString +// that allows the caller to specify the ID and Secret separately +func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) { + return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret)) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring_test.go new file mode 100644 index 000000000..0d06bd153 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/bootstraptokenstring_test.go @@ -0,0 +1,236 @@ +/* +Copyright 2018 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 v1alpha2 + +import ( + "encoding/json" + "fmt" + "reflect" + "testing" +) + +func TestMarshalJSON(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`}, + {BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`}, + {BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`}, + } + for _, rt := range tests { + b, err := json.Marshal(rt.bts) + if err != nil { + t.Fatalf("json.Marshal returned an unexpected error: %v", err) + } + if string(b) != rt.expected { + t.Errorf( + "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", + rt.expected, + string(b), + ) + } + } +} + +func TestUnmarshalJSON(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + expectedError bool + }{ + {`"f.s"`, &BootstrapTokenString{}, true}, + {`"abcdef."`, &BootstrapTokenString{}, true}, + {`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true}, + {`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false}, + {`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false}, + } + for _, rt := range tests { + newbts := &BootstrapTokenString{} + err := json.Unmarshal([]byte(rt.input), newbts) + if (err != nil) != rt.expectedError { + t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) + } else if !reflect.DeepEqual(rt.bts, newbts) { + t.Errorf( + "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", + rt.bts, + newbts, + ) + } + } +} + +func TestJSONRoundtrip(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + }{ + {`"abcdef.abcdef0123456789"`, nil}, + {"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + } + for _, rt := range tests { + if err := roundtrip(rt.input, rt.bts); err != nil { + t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) + } + } +} + +func roundtrip(input string, bts *BootstrapTokenString) error { + var b []byte + var err error + newbts := &BootstrapTokenString{} + // If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string + if len(input) > 0 { + if err := json.Unmarshal([]byte(input), newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if b, err = json.Marshal(newbts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if input != string(b) { + return fmt.Errorf( + "expected token: %s\n\t actual: %s", + input, + string(b), + ) + } + } else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object + if b, err = json.Marshal(bts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if err := json.Unmarshal(b, newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if !reflect.DeepEqual(bts, newbts) { + return fmt.Errorf( + "expected object: %v\n\t actual: %v", + bts, + newbts, + ) + } + } + return nil +} + +func TestTokenFromIDAndSecret(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"}, + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"}, + {BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"}, + } + for _, rt := range tests { + actual := rt.bts.String() + if actual != rt.expected { + t.Errorf( + "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + +func TestNewBootstrapTokenString(t *testing.T) { + var tests = []struct { + token string + expectedError bool + bts *BootstrapTokenString + }{ + {token: "", expectedError: true, bts: nil}, + {token: ".", expectedError: true, bts: nil}, + {token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size + {token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456.", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation + {token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation + {token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id + {token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character + {token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, + } + for _, rt := range tests { + actual, err := NewBootstrapTokenString(rt.token) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", + rt.token, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", + rt.token, + rt.bts, + actual, + ) + } + } +} + +func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { + var tests = []struct { + id, secret string + expectedError bool + bts *BootstrapTokenString + }{ + {id: "", secret: "", expectedError: true, bts: nil}, + {id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id + {id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character + {id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, + } + for _, rt := range tests { + actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", + rt.id, + rt.secret, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", + rt.id, + rt.secret, + rt.bts, + actual, + ) + } + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go new file mode 100644 index 000000000..c9b8980bd --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go @@ -0,0 +1,269 @@ +/* +Copyright 2018 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 v1alpha2 + +import ( + "net/url" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + kubeproxyscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme" + kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" + utilpointer "k8s.io/kubernetes/pkg/util/pointer" +) + +const ( + // DefaultServiceDNSDomain defines default cluster-internal domain name for Services and Pods + DefaultServiceDNSDomain = "cluster.local" + // DefaultServicesSubnet defines default service subnet range + DefaultServicesSubnet = "10.96.0.0/12" + // DefaultClusterDNSIP defines default DNS IP + DefaultClusterDNSIP = "10.96.0.10" + // DefaultKubernetesVersion defines default kubernetes version + DefaultKubernetesVersion = "stable-1.11" + // DefaultAPIBindPort defines default API port + DefaultAPIBindPort = 6443 + // DefaultCertificatesDir defines default certificate directory + DefaultCertificatesDir = "/etc/kubernetes/pki" + // DefaultImageRepository defines default image registry + DefaultImageRepository = "k8s.gcr.io" + // DefaultManifestsDir defines default manifests directory + DefaultManifestsDir = "/etc/kubernetes/manifests" + // DefaultCRISocket defines the default cri socket + DefaultCRISocket = "/var/run/dockershim.sock" + // DefaultClusterName defines the default cluster name + DefaultClusterName = "kubernetes" + + // DefaultEtcdDataDir defines default location of etcd where static pods will save data to + DefaultEtcdDataDir = "/var/lib/etcd" + // DefaultProxyBindAddressv4 is the default bind address when the advertise address is v4 + DefaultProxyBindAddressv4 = "0.0.0.0" + // DefaultProxyBindAddressv6 is the default bind address when the advertise address is v6 + DefaultProxyBindAddressv6 = "::" + // KubeproxyKubeConfigFileName defines the file name for the kube-proxy's KubeConfig file + KubeproxyKubeConfigFileName = "/var/lib/kube-proxy/kubeconfig.conf" + + // DefaultDiscoveryTimeout specifies the default discovery timeout for kubeadm (used unless one is specified in the NodeConfiguration) + DefaultDiscoveryTimeout = 5 * time.Minute +) + +var ( + // DefaultAuditPolicyLogMaxAge is defined as a var so its address can be taken + // It is the number of days to store audit logs + DefaultAuditPolicyLogMaxAge = int32(2) +) + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return RegisterDefaults(scheme) +} + +// SetDefaults_MasterConfiguration assigns default values to Master node +func SetDefaults_MasterConfiguration(obj *MasterConfiguration) { + if obj.KubernetesVersion == "" { + obj.KubernetesVersion = DefaultKubernetesVersion + } + + if obj.API.BindPort == 0 { + obj.API.BindPort = DefaultAPIBindPort + } + + if obj.Networking.ServiceSubnet == "" { + obj.Networking.ServiceSubnet = DefaultServicesSubnet + } + + if obj.Networking.DNSDomain == "" { + obj.Networking.DNSDomain = DefaultServiceDNSDomain + } + + if obj.CertificatesDir == "" { + obj.CertificatesDir = DefaultCertificatesDir + } + + if obj.ImageRepository == "" { + obj.ImageRepository = DefaultImageRepository + } + + if obj.ClusterName == "" { + obj.ClusterName = DefaultClusterName + } + + SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) + SetDefaults_BootstrapTokens(obj) + SetDefaults_KubeletConfiguration(obj) + SetDefaults_Etcd(obj) + SetDefaults_ProxyConfiguration(obj) + SetDefaults_AuditPolicyConfiguration(obj) +} + +// SetDefaults_Etcd assigns default values for the Proxy +func SetDefaults_Etcd(obj *MasterConfiguration) { + if obj.Etcd.External == nil && obj.Etcd.Local == nil { + obj.Etcd.Local = &LocalEtcd{} + } + if obj.Etcd.Local != nil { + if obj.Etcd.Local.DataDir == "" { + obj.Etcd.Local.DataDir = DefaultEtcdDataDir + } + } +} + +// SetDefaults_ProxyConfiguration assigns default values for the Proxy +func SetDefaults_ProxyConfiguration(obj *MasterConfiguration) { + if obj.KubeProxy.Config == nil { + obj.KubeProxy.Config = &kubeproxyconfigv1alpha1.KubeProxyConfiguration{} + } + if obj.KubeProxy.Config.ClusterCIDR == "" && obj.Networking.PodSubnet != "" { + obj.KubeProxy.Config.ClusterCIDR = obj.Networking.PodSubnet + } + + if obj.KubeProxy.Config.ClientConnection.KubeConfigFile == "" { + obj.KubeProxy.Config.ClientConnection.KubeConfigFile = KubeproxyKubeConfigFileName + } + + kubeproxyscheme.Scheme.Default(obj.KubeProxy.Config) +} + +// SetDefaults_NodeConfiguration assigns default values to a regular node +func SetDefaults_NodeConfiguration(obj *NodeConfiguration) { + if obj.CACertPath == "" { + obj.CACertPath = DefaultCACertPath + } + if len(obj.TLSBootstrapToken) == 0 { + obj.TLSBootstrapToken = obj.Token + } + if len(obj.DiscoveryToken) == 0 && len(obj.DiscoveryFile) == 0 { + obj.DiscoveryToken = obj.Token + } + // Make sure file URLs become paths + if len(obj.DiscoveryFile) != 0 { + u, err := url.Parse(obj.DiscoveryFile) + if err == nil && u.Scheme == "file" { + obj.DiscoveryFile = u.Path + } + } + if obj.DiscoveryTimeout == nil { + obj.DiscoveryTimeout = &metav1.Duration{ + Duration: DefaultDiscoveryTimeout, + } + } + if obj.ClusterName == "" { + obj.ClusterName = DefaultClusterName + } + + SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) +} + +// SetDefaults_KubeletConfiguration assigns default values to kubelet +func SetDefaults_KubeletConfiguration(obj *MasterConfiguration) { + if obj.KubeletConfiguration.BaseConfig == nil { + obj.KubeletConfiguration.BaseConfig = &kubeletconfigv1beta1.KubeletConfiguration{} + } + if obj.KubeletConfiguration.BaseConfig.StaticPodPath == "" { + obj.KubeletConfiguration.BaseConfig.StaticPodPath = DefaultManifestsDir + } + if obj.KubeletConfiguration.BaseConfig.ClusterDNS == nil { + dnsIP, err := constants.GetDNSIP(obj.Networking.ServiceSubnet) + if err != nil { + obj.KubeletConfiguration.BaseConfig.ClusterDNS = []string{DefaultClusterDNSIP} + } else { + obj.KubeletConfiguration.BaseConfig.ClusterDNS = []string{dnsIP.String()} + } + } + if obj.KubeletConfiguration.BaseConfig.ClusterDomain == "" { + obj.KubeletConfiguration.BaseConfig.ClusterDomain = obj.Networking.DNSDomain + } + + // Enforce security-related kubelet options + + // Require all clients to the kubelet API to have client certs signed by the cluster CA + obj.KubeletConfiguration.BaseConfig.Authentication.X509.ClientCAFile = DefaultCACertPath + obj.KubeletConfiguration.BaseConfig.Authentication.Anonymous.Enabled = utilpointer.BoolPtr(false) + + // On every client request to the kubelet API, execute a webhook (SubjectAccessReview request) to the API server + // and ask it whether the client is authorized to access the kubelet API + obj.KubeletConfiguration.BaseConfig.Authorization.Mode = kubeletconfigv1beta1.KubeletAuthorizationModeWebhook + + // Let clients using other authentication methods like ServiceAccount tokens also access the kubelet API + obj.KubeletConfiguration.BaseConfig.Authentication.Webhook.Enabled = utilpointer.BoolPtr(true) + + // Disable the readonly port of the kubelet, in order to not expose unnecessary information + obj.KubeletConfiguration.BaseConfig.ReadOnlyPort = 0 + + // Enables client certificate rotation for the kubelet + obj.KubeletConfiguration.BaseConfig.RotateCertificates = true + + // Serve a /healthz webserver on localhost:10248 that kubeadm can talk to + obj.KubeletConfiguration.BaseConfig.HealthzBindAddress = "127.0.0.1" + obj.KubeletConfiguration.BaseConfig.HealthzPort = utilpointer.Int32Ptr(10248) + + scheme, _, _ := kubeletscheme.NewSchemeAndCodecs() + if scheme != nil { + scheme.Default(obj.KubeletConfiguration.BaseConfig) + } +} + +func SetDefaults_NodeRegistrationOptions(obj *NodeRegistrationOptions) { + if obj.CRISocket == "" { + obj.CRISocket = DefaultCRISocket + } +} + +// SetDefaults_AuditPolicyConfiguration sets default values for the AuditPolicyConfiguration +func SetDefaults_AuditPolicyConfiguration(obj *MasterConfiguration) { + if obj.AuditPolicyConfiguration.LogDir == "" { + obj.AuditPolicyConfiguration.LogDir = constants.StaticPodAuditPolicyLogDir + } + if obj.AuditPolicyConfiguration.LogMaxAge == nil { + obj.AuditPolicyConfiguration.LogMaxAge = &DefaultAuditPolicyLogMaxAge + } +} + +// SetDefaults_BootstrapTokens sets the defaults for the .BootstrapTokens field +// If the slice is empty, it's defaulted with one token. Otherwise it just loops +// through the slice and sets the defaults for the omitempty fields that are TTL, +// Usages and Groups. Token is NOT defaulted with a random one in the API defaulting +// layer, but set to a random value later at runtime if not set before. +func SetDefaults_BootstrapTokens(obj *MasterConfiguration) { + + if obj.BootstrapTokens == nil || len(obj.BootstrapTokens) == 0 { + obj.BootstrapTokens = []BootstrapToken{{}} + } + + for _, bt := range obj.BootstrapTokens { + SetDefaults_BootstrapToken(&bt) + } +} + +// SetDefaults_BootstrapToken sets the defaults for an individual Bootstrap Token +func SetDefaults_BootstrapToken(bt *BootstrapToken) { + if bt.TTL == nil { + bt.TTL = &metav1.Duration{ + Duration: constants.DefaultTokenDuration, + } + } + if len(bt.Usages) == 0 { + bt.Usages = constants.DefaultTokenUsages + } + + if len(bt.Groups) == 0 { + bt.Groups = constants.DefaultTokenGroups + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults_unix.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults_unix.go new file mode 100644 index 000000000..7dbc7f21a --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults_unix.go @@ -0,0 +1,22 @@ +// +build !windows + +/* +Copyright 2018 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 v1alpha2 + +// DefaultCACertPath defines default location of CA certificate on Linux +const DefaultCACertPath = "/etc/kubernetes/pki/ca.crt" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults_windows.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults_windows.go new file mode 100644 index 000000000..bbbb46272 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults_windows.go @@ -0,0 +1,22 @@ +// +build windows + +/* +Copyright 2018 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 v1alpha2 + +// DefaultCACertPath defines default location of CA certificate on Windows +const DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/doc.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/doc.go new file mode 100644 index 000000000..578b1b226 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2018 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 v1alpha2 is the package that contains the libraries that drive the kubeadm binary. +// +k8s:defaulter-gen=TypeMeta +// +groupName=kubeadm.k8s.io +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm +package v1alpha2 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/register.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/register.go new file mode 100644 index 000000000..a5e15f9e8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/register.go @@ -0,0 +1,66 @@ +/* +Copyright 2018 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 v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "kubeadm.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"} + +var ( + // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + + // SchemeBuilder points to a list of functions added to Scheme. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // AddToScheme applies all the stored functions to the scheme. + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs) +} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &MasterConfiguration{}, + &NodeConfiguration{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/types.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/types.go new file mode 100644 index 000000000..7af1f79be --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/types.go @@ -0,0 +1,319 @@ +/* +Copyright 2018 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 v1alpha2 + +import ( + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MasterConfiguration contains a list of elements which make up master's +// configuration object. +type MasterConfiguration struct { + metav1.TypeMeta `json:",inline"` + + // `kubeadm init`-only information. These fields are solely used the first time `kubeadm init` runs. + // After that, the information in the fields ARE NOT uploaded to the `kubeadm-config` ConfigMap + // that is used by `kubeadm upgrade` for instance. These fields must be omitempty. + + // BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create. + // This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature + BootstrapTokens []BootstrapToken `json:"bootstrapTokens,omitempty"` + + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"` + + // Cluster-wide configuration + // TODO: Move these fields under some kind of ClusterConfiguration or similar struct that describes + // one cluster. Eventually we want this kind of spec to align well with the Cluster API spec. + + // API holds configuration for the k8s apiserver. + API API `json:"api"` + // KubeProxy holds configuration for the k8s service proxy. + KubeProxy KubeProxy `json:"kubeProxy"` + // Etcd holds configuration for etcd. + Etcd Etcd `json:"etcd"` + // KubeletConfiguration holds configuration for the kubelet. + KubeletConfiguration KubeletConfiguration `json:"kubeletConfiguration"` + // Networking holds configuration for the networking topology of the cluster. + Networking Networking `json:"networking"` + + // KubernetesVersion is the target version of the control plane. + KubernetesVersion string `json:"kubernetesVersion"` + + // APIServerExtraArgs is a set of extra flags to pass to the API Server or override + // default ones in form of =. + // TODO: This is temporary and ideally we would like to switch all components to + // use ComponentConfig + ConfigMaps. + APIServerExtraArgs map[string]string `json:"apiServerExtraArgs,omitempty"` + // ControllerManagerExtraArgs is a set of extra flags to pass to the Controller Manager + // or override default ones in form of = + // TODO: This is temporary and ideally we would like to switch all components to + // use ComponentConfig + ConfigMaps. + ControllerManagerExtraArgs map[string]string `json:"controllerManagerExtraArgs,omitempty"` + // SchedulerExtraArgs is a set of extra flags to pass to the Scheduler or override + // default ones in form of = + // TODO: This is temporary and ideally we would like to switch all components to + // use ComponentConfig + ConfigMaps. + SchedulerExtraArgs map[string]string `json:"schedulerExtraArgs,omitempty"` + + // APIServerExtraVolumes is an extra set of host volumes mounted to the API server. + APIServerExtraVolumes []HostPathMount `json:"apiServerExtraVolumes,omitempty"` + // ControllerManagerExtraVolumes is an extra set of host volumes mounted to the + // Controller Manager. + ControllerManagerExtraVolumes []HostPathMount `json:"controllerManagerExtraVolumes,omitempty"` + // SchedulerExtraVolumes is an extra set of host volumes mounted to the scheduler. + SchedulerExtraVolumes []HostPathMount `json:"schedulerExtraVolumes,omitempty"` + + // APIServerCertSANs sets extra Subject Alternative Names for the API Server signing cert. + APIServerCertSANs []string `json:"apiServerCertSANs,omitempty"` + // CertificatesDir specifies where to store or look for all required certificates. + CertificatesDir string `json:"certificatesDir"` + + // ImageRepository what container registry to pull control plane images from + ImageRepository string `json:"imageRepository"` + // UnifiedControlPlaneImage specifies if a specific container image should + // be used for all control plane components. + UnifiedControlPlaneImage string `json:"unifiedControlPlaneImage"` + + // AuditPolicyConfiguration defines the options for the api server audit system + AuditPolicyConfiguration AuditPolicyConfiguration `json:"auditPolicy"` + + // FeatureGates enabled by the user. + FeatureGates map[string]bool `json:"featureGates,omitempty"` + + // The cluster name + ClusterName string `json:"clusterName,omitempty"` +} + +// API struct contains elements of API server address. +type API struct { + // AdvertiseAddress sets the IP address for the API server to advertise. + AdvertiseAddress string `json:"advertiseAddress"` + // ControlPlaneEndpoint sets a stable IP address or DNS name for the control plane; it + // can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port. + // In case the ControlPlaneEndpoint is not specified, the AdvertiseAddress + BindPort + // are used; in case the ControlPlaneEndpoint is specified but without a TCP port, + // the BindPort is used. + // Possible usages are: + // e.g. In an cluster with more than one control plane instances, this field should be + // assigned the address of the external load balancer in front of the + // control plane instances. + // e.g. in environments with enforced node recycling, the ControlPlaneEndpoint + // could be used for assigning a stable DNS to the control plane. + ControlPlaneEndpoint string `json:"controlPlaneEndpoint"` + // BindPort sets the secure port for the API Server to bind to. + // Defaults to 6443. + BindPort int32 `json:"bindPort"` +} + +// NodeRegistrationOptions holds fields that relate to registering a new master or node to the cluster, either via "kubeadm init" or "kubeadm join" +type NodeRegistrationOptions struct { + + // Name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm joiń` operation. + // This field is also used in the CommonName field of the kubelet's client certificate to the API server. + // Defaults to the hostname of the node if not provided. + Name string `json:"name,omitempty"` + + // CRISocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-use + CRISocket string `json:"criSocket,omitempty"` + + // Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process + // it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your master node, set this field to an + // empty slice, i.e. `taints: {}` in the YAML file. This field is solely used for Node registration. + Taints []v1.Taint `json:"taints,omitempty"` + + // KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file + // kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap + // Flags have higher higher priority when parsing. These values are local and specific to the node kubeadm is executing on. + KubeletExtraArgs map[string]string `json:"kubeletExtraArgs,omitempty"` +} + +// Networking contains elements describing cluster's networking configuration +type Networking struct { + // ServiceSubnet is the subnet used by k8s services. Defaults to "10.96.0.0/12". + ServiceSubnet string `json:"serviceSubnet"` + // PodSubnet is the subnet used by pods. + PodSubnet string `json:"podSubnet"` + // DNSDomain is the dns domain used by k8s services. Defaults to "cluster.local". + DNSDomain string `json:"dnsDomain"` +} + +// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster +type BootstrapToken struct { + // Token is used for establishing bidirectional trust between nodes and masters. + // Used for joining nodes in the cluster. + Token *BootstrapTokenString `json:"token"` + // Description sets a human-friendly message why this token exists and what it's used + // for, so other administrators can know its purpose. + Description string `json:"description,omitempty"` + // TTL defines the time to live for this token. Defaults to 24h. + // Expires and TTL are mutually exclusive. + TTL *metav1.Duration `json:"ttl,omitempty"` + // Expires specifies the timestamp when this token expires. Defaults to being set + // dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive. + Expires *metav1.Time `json:"expires,omitempty"` + // Usages describes the ways in which this token can be used. Can by default be used + // for establishing bidirectional trust, but that can be changed here. + Usages []string `json:"usages,omitempty"` + // Groups specifies the extra groups that this token will authenticate as when/if + // used for authentication + Groups []string `json:"groups,omitempty"` +} + +// Etcd contains elements describing Etcd configuration. +type Etcd struct { + + // Local provides configuration knobs for configuring the local etcd instance + // Local and External are mutually exclusive + Local *LocalEtcd `json:"local,omitempty"` + + // External describes how to connect to an external etcd cluster + // Local and External are mutually exclusive + External *ExternalEtcd `json:"external,omitempty"` +} + +// LocalEtcd describes that kubeadm should run an etcd cluster locally +type LocalEtcd struct { + + // Image specifies which container image to use for running etcd. + // If empty, automatically populated by kubeadm using the image + // repository and default etcd version. + Image string `json:"image"` + + // DataDir is the directory etcd will place its data. + // Defaults to "/var/lib/etcd". + DataDir string `json:"dataDir"` + + // ExtraArgs are extra arguments provided to the etcd binary + // when run inside a static pod. + ExtraArgs map[string]string `json:"extraArgs,omitempty"` + + // ServerCertSANs sets extra Subject Alternative Names for the etcd server signing cert. + ServerCertSANs []string `json:"serverCertSANs,omitempty"` + // PeerCertSANs sets extra Subject Alternative Names for the etcd peer signing cert. + PeerCertSANs []string `json:"peerCertSANs,omitempty"` +} + +// ExternalEtcd describes an external etcd cluster +type ExternalEtcd struct { + + // Endpoints of etcd members. Useful for using external etcd. + // If not provided, kubeadm will run etcd in a static pod. + Endpoints []string `json:"endpoints"` + // CAFile is an SSL Certificate Authority file used to secure etcd communication. + CAFile string `json:"caFile"` + // CertFile is an SSL certification file used to secure etcd communication. + CertFile string `json:"certFile"` + // KeyFile is an SSL key file used to secure etcd communication. + KeyFile string `json:"keyFile"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NodeConfiguration contains elements describing a particular node. +// TODO: This struct should be replaced by dynamic kubelet configuration. +type NodeConfiguration struct { + metav1.TypeMeta `json:",inline"` + + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions `json:"nodeRegistration"` + + // CACertPath is the path to the SSL certificate authority used to + // secure comunications between node and master. + // Defaults to "/etc/kubernetes/pki/ca.crt". + CACertPath string `json:"caCertPath"` + // DiscoveryFile is a file or url to a kubeconfig file from which to + // load cluster information. + DiscoveryFile string `json:"discoveryFile"` + // DiscoveryToken is a token used to validate cluster information + // fetched from the master. + DiscoveryToken string `json:"discoveryToken"` + // DiscoveryTokenAPIServers is a set of IPs to API servers from which info + // will be fetched. Currently we only pay attention to one API server but + // hope to support >1 in the future. + DiscoveryTokenAPIServers []string `json:"discoveryTokenAPIServers,omitempty"` + // DiscoveryTimeout modifies the discovery timeout + DiscoveryTimeout *metav1.Duration `json:"discoveryTimeout,omitempty"` + // TLSBootstrapToken is a token used for TLS bootstrapping. + // Defaults to Token. + TLSBootstrapToken string `json:"tlsBootstrapToken"` + // Token is used for both discovery and TLS bootstrapping. + Token string `json:"token"` + + // ClusterName is the name for the cluster in kubeconfig. + ClusterName string `json:"clusterName,omitempty"` + + // DiscoveryTokenCACertHashes specifies a set of public key pins to verify + // when token-based discovery is used. The root CA found during discovery + // must match one of these values. Specifying an empty set disables root CA + // pinning, which can be unsafe. Each hash is specified as ":", + // where the only currently supported type is "sha256". This is a hex-encoded + // SHA-256 hash of the Subject Public Key Info (SPKI) object in DER-encoded + // ASN.1. These hashes can be calculated using, for example, OpenSSL: + // openssl x509 -pubkey -in ca.crt openssl rsa -pubin -outform der 2>&/dev/null | openssl dgst -sha256 -hex + DiscoveryTokenCACertHashes []string `json:"discoveryTokenCACertHashes,omitempty"` + + // DiscoveryTokenUnsafeSkipCAVerification allows token-based discovery + // without CA verification via DiscoveryTokenCACertHashes. This can weaken + // the security of kubeadm since other nodes can impersonate the master. + DiscoveryTokenUnsafeSkipCAVerification bool `json:"discoveryTokenUnsafeSkipCAVerification"` + + // FeatureGates enabled by the user. + FeatureGates map[string]bool `json:"featureGates,omitempty"` +} + +// KubeletConfiguration contains elements describing initial remote configuration of kubelet. +type KubeletConfiguration struct { + BaseConfig *kubeletconfigv1beta1.KubeletConfiguration `json:"baseConfig,omitempty"` +} + +// HostPathMount contains elements describing volumes that are mounted from the +// host. +type HostPathMount struct { + // Name of the volume inside the pod template. + Name string `json:"name"` + // HostPath is the path in the host that will be mounted inside + // the pod. + HostPath string `json:"hostPath"` + // MountPath is the path inside the pod where hostPath will be mounted. + MountPath string `json:"mountPath"` + // Writable controls write access to the volume + Writable bool `json:"writable,omitempty"` + // PathType is the type of the HostPath. + PathType v1.HostPathType `json:"pathType,omitempty"` +} + +// KubeProxy contains elements describing the proxy configuration. +type KubeProxy struct { + Config *kubeproxyconfigv1alpha1.KubeProxyConfiguration `json:"config,omitempty"` +} + +// AuditPolicyConfiguration holds the options for configuring the api server audit policy. +type AuditPolicyConfiguration struct { + // Path is the local path to an audit policy. + Path string `json:"path"` + // LogDir is the local path to the directory where logs should be stored. + LogDir string `json:"logDir"` + // LogMaxAge is the number of days logs will be stored for. 0 indicates forever. + LogMaxAge *int32 `json:"logMaxAge,omitempty"` + //TODO(chuckha) add other options for audit policy. +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go new file mode 100644 index 000000000..22ef44a14 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go @@ -0,0 +1,501 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + unsafe "unsafe" + + core_v1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(scheme *runtime.Scheme) error { + return scheme.AddGeneratedConversionFuncs( + Convert_v1alpha2_API_To_kubeadm_API, + Convert_kubeadm_API_To_v1alpha2_API, + Convert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration, + Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration, + Convert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken, + Convert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken, + Convert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString, + Convert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString, + Convert_v1alpha2_Etcd_To_kubeadm_Etcd, + Convert_kubeadm_Etcd_To_v1alpha2_Etcd, + Convert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd, + Convert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd, + Convert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount, + Convert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount, + Convert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy, + Convert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy, + Convert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration, + Convert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration, + Convert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd, + Convert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd, + Convert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration, + Convert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration, + Convert_v1alpha2_Networking_To_kubeadm_Networking, + Convert_kubeadm_Networking_To_v1alpha2_Networking, + Convert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration, + Convert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration, + Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions, + Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions, + ) +} + +func autoConvert_v1alpha2_API_To_kubeadm_API(in *API, out *kubeadm.API, s conversion.Scope) error { + out.AdvertiseAddress = in.AdvertiseAddress + out.ControlPlaneEndpoint = in.ControlPlaneEndpoint + out.BindPort = in.BindPort + return nil +} + +// Convert_v1alpha2_API_To_kubeadm_API is an autogenerated conversion function. +func Convert_v1alpha2_API_To_kubeadm_API(in *API, out *kubeadm.API, s conversion.Scope) error { + return autoConvert_v1alpha2_API_To_kubeadm_API(in, out, s) +} + +func autoConvert_kubeadm_API_To_v1alpha2_API(in *kubeadm.API, out *API, s conversion.Scope) error { + out.AdvertiseAddress = in.AdvertiseAddress + out.ControlPlaneEndpoint = in.ControlPlaneEndpoint + out.BindPort = in.BindPort + return nil +} + +// Convert_kubeadm_API_To_v1alpha2_API is an autogenerated conversion function. +func Convert_kubeadm_API_To_v1alpha2_API(in *kubeadm.API, out *API, s conversion.Scope) error { + return autoConvert_kubeadm_API_To_v1alpha2_API(in, out, s) +} + +func autoConvert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(in *AuditPolicyConfiguration, out *kubeadm.AuditPolicyConfiguration, s conversion.Scope) error { + out.Path = in.Path + out.LogDir = in.LogDir + out.LogMaxAge = (*int32)(unsafe.Pointer(in.LogMaxAge)) + return nil +} + +// Convert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration is an autogenerated conversion function. +func Convert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(in *AuditPolicyConfiguration, out *kubeadm.AuditPolicyConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(in, out, s) +} + +func autoConvert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration(in *kubeadm.AuditPolicyConfiguration, out *AuditPolicyConfiguration, s conversion.Scope) error { + out.Path = in.Path + out.LogDir = in.LogDir + out.LogMaxAge = (*int32)(unsafe.Pointer(in.LogMaxAge)) + return nil +} + +// Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration is an autogenerated conversion function. +func Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration(in *kubeadm.AuditPolicyConfiguration, out *AuditPolicyConfiguration, s conversion.Scope) error { + return autoConvert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration(in, out, s) +} + +func autoConvert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error { + out.Token = (*kubeadm.BootstrapTokenString)(unsafe.Pointer(in.Token)) + out.Description = in.Description + out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL)) + out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires)) + out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages)) + out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups)) + return nil +} + +// Convert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken is an autogenerated conversion function. +func Convert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error { + return autoConvert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken(in, out, s) +} + +func autoConvert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error { + out.Token = (*BootstrapTokenString)(unsafe.Pointer(in.Token)) + out.Description = in.Description + out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL)) + out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires)) + out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages)) + out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups)) + return nil +} + +// Convert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken is an autogenerated conversion function. +func Convert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error { + return autoConvert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken(in, out, s) +} + +func autoConvert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error { + out.ID = in.ID + out.Secret = in.Secret + return nil +} + +// Convert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString is an autogenerated conversion function. +func Convert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error { + return autoConvert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in, out, s) +} + +func autoConvert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error { + out.ID = in.ID + out.Secret = in.Secret + return nil +} + +// Convert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString is an autogenerated conversion function. +func Convert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error { + return autoConvert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString(in, out, s) +} + +func autoConvert_v1alpha2_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error { + out.Local = (*kubeadm.LocalEtcd)(unsafe.Pointer(in.Local)) + out.External = (*kubeadm.ExternalEtcd)(unsafe.Pointer(in.External)) + return nil +} + +// Convert_v1alpha2_Etcd_To_kubeadm_Etcd is an autogenerated conversion function. +func Convert_v1alpha2_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error { + return autoConvert_v1alpha2_Etcd_To_kubeadm_Etcd(in, out, s) +} + +func autoConvert_kubeadm_Etcd_To_v1alpha2_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error { + out.Local = (*LocalEtcd)(unsafe.Pointer(in.Local)) + out.External = (*ExternalEtcd)(unsafe.Pointer(in.External)) + return nil +} + +// Convert_kubeadm_Etcd_To_v1alpha2_Etcd is an autogenerated conversion function. +func Convert_kubeadm_Etcd_To_v1alpha2_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error { + return autoConvert_kubeadm_Etcd_To_v1alpha2_Etcd(in, out, s) +} + +func autoConvert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error { + out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints)) + out.CAFile = in.CAFile + out.CertFile = in.CertFile + out.KeyFile = in.KeyFile + return nil +} + +// Convert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd is an autogenerated conversion function. +func Convert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error { + return autoConvert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd(in, out, s) +} + +func autoConvert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error { + out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints)) + out.CAFile = in.CAFile + out.CertFile = in.CertFile + out.KeyFile = in.KeyFile + return nil +} + +// Convert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd is an autogenerated conversion function. +func Convert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error { + return autoConvert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd(in, out, s) +} + +func autoConvert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error { + out.Name = in.Name + out.HostPath = in.HostPath + out.MountPath = in.MountPath + out.Writable = in.Writable + out.PathType = core_v1.HostPathType(in.PathType) + return nil +} + +// Convert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount is an autogenerated conversion function. +func Convert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error { + return autoConvert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount(in, out, s) +} + +func autoConvert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error { + out.Name = in.Name + out.HostPath = in.HostPath + out.MountPath = in.MountPath + out.Writable = in.Writable + out.PathType = core_v1.HostPathType(in.PathType) + return nil +} + +// Convert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount is an autogenerated conversion function. +func Convert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error { + return autoConvert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount(in, out, s) +} + +func autoConvert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy(in *KubeProxy, out *kubeadm.KubeProxy, s conversion.Scope) error { + out.Config = (*v1alpha1.KubeProxyConfiguration)(unsafe.Pointer(in.Config)) + return nil +} + +// Convert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy is an autogenerated conversion function. +func Convert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy(in *KubeProxy, out *kubeadm.KubeProxy, s conversion.Scope) error { + return autoConvert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy(in, out, s) +} + +func autoConvert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy(in *kubeadm.KubeProxy, out *KubeProxy, s conversion.Scope) error { + out.Config = (*v1alpha1.KubeProxyConfiguration)(unsafe.Pointer(in.Config)) + return nil +} + +// Convert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy is an autogenerated conversion function. +func Convert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy(in *kubeadm.KubeProxy, out *KubeProxy, s conversion.Scope) error { + return autoConvert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy(in, out, s) +} + +func autoConvert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration(in *KubeletConfiguration, out *kubeadm.KubeletConfiguration, s conversion.Scope) error { + out.BaseConfig = (*v1beta1.KubeletConfiguration)(unsafe.Pointer(in.BaseConfig)) + return nil +} + +// Convert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration is an autogenerated conversion function. +func Convert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration(in *KubeletConfiguration, out *kubeadm.KubeletConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration(in, out, s) +} + +func autoConvert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration(in *kubeadm.KubeletConfiguration, out *KubeletConfiguration, s conversion.Scope) error { + out.BaseConfig = (*v1beta1.KubeletConfiguration)(unsafe.Pointer(in.BaseConfig)) + return nil +} + +// Convert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration is an autogenerated conversion function. +func Convert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration(in *kubeadm.KubeletConfiguration, out *KubeletConfiguration, s conversion.Scope) error { + return autoConvert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration(in, out, s) +} + +func autoConvert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error { + out.Image = in.Image + out.DataDir = in.DataDir + out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) + out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) + out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) + return nil +} + +// Convert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd is an autogenerated conversion function. +func Convert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error { + return autoConvert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd(in, out, s) +} + +func autoConvert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error { + out.Image = in.Image + out.DataDir = in.DataDir + out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) + out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) + out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) + return nil +} + +// Convert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd is an autogenerated conversion function. +func Convert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error { + return autoConvert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd(in, out, s) +} + +func autoConvert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error { + out.BootstrapTokens = *(*[]kubeadm.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens)) + if err := Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { + return err + } + if err := Convert_v1alpha2_API_To_kubeadm_API(&in.API, &out.API, s); err != nil { + return err + } + if err := Convert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy(&in.KubeProxy, &out.KubeProxy, s); err != nil { + return err + } + if err := Convert_v1alpha2_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil { + return err + } + if err := Convert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration(&in.KubeletConfiguration, &out.KubeletConfiguration, s); err != nil { + return err + } + if err := Convert_v1alpha2_Networking_To_kubeadm_Networking(&in.Networking, &out.Networking, s); err != nil { + return err + } + out.KubernetesVersion = in.KubernetesVersion + out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs)) + out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs)) + out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs)) + out.APIServerExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.APIServerExtraVolumes)) + out.ControllerManagerExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.ControllerManagerExtraVolumes)) + out.SchedulerExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.SchedulerExtraVolumes)) + out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs)) + out.CertificatesDir = in.CertificatesDir + out.ImageRepository = in.ImageRepository + out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage + if err := Convert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(&in.AuditPolicyConfiguration, &out.AuditPolicyConfiguration, s); err != nil { + return err + } + out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) + out.ClusterName = in.ClusterName + return nil +} + +// Convert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration is an autogenerated conversion function. +func Convert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in, out, s) +} + +func autoConvert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { + out.BootstrapTokens = *(*[]BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens)) + if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { + return err + } + if err := Convert_kubeadm_API_To_v1alpha2_API(&in.API, &out.API, s); err != nil { + return err + } + if err := Convert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy(&in.KubeProxy, &out.KubeProxy, s); err != nil { + return err + } + if err := Convert_kubeadm_Etcd_To_v1alpha2_Etcd(&in.Etcd, &out.Etcd, s); err != nil { + return err + } + if err := Convert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration(&in.KubeletConfiguration, &out.KubeletConfiguration, s); err != nil { + return err + } + if err := Convert_kubeadm_Networking_To_v1alpha2_Networking(&in.Networking, &out.Networking, s); err != nil { + return err + } + out.KubernetesVersion = in.KubernetesVersion + out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs)) + out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs)) + out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs)) + out.APIServerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.APIServerExtraVolumes)) + out.ControllerManagerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ControllerManagerExtraVolumes)) + out.SchedulerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.SchedulerExtraVolumes)) + out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs)) + out.CertificatesDir = in.CertificatesDir + out.ImageRepository = in.ImageRepository + // INFO: in.CIImageRepository opted out of conversion generation + out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage + if err := Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration(&in.AuditPolicyConfiguration, &out.AuditPolicyConfiguration, s); err != nil { + return err + } + out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) + out.ClusterName = in.ClusterName + return nil +} + +// Convert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration is an autogenerated conversion function. +func Convert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { + return autoConvert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in, out, s) +} + +func autoConvert_v1alpha2_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error { + out.ServiceSubnet = in.ServiceSubnet + out.PodSubnet = in.PodSubnet + out.DNSDomain = in.DNSDomain + return nil +} + +// Convert_v1alpha2_Networking_To_kubeadm_Networking is an autogenerated conversion function. +func Convert_v1alpha2_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error { + return autoConvert_v1alpha2_Networking_To_kubeadm_Networking(in, out, s) +} + +func autoConvert_kubeadm_Networking_To_v1alpha2_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error { + out.ServiceSubnet = in.ServiceSubnet + out.PodSubnet = in.PodSubnet + out.DNSDomain = in.DNSDomain + return nil +} + +// Convert_kubeadm_Networking_To_v1alpha2_Networking is an autogenerated conversion function. +func Convert_kubeadm_Networking_To_v1alpha2_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error { + return autoConvert_kubeadm_Networking_To_v1alpha2_Networking(in, out, s) +} + +func autoConvert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error { + if err := Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { + return err + } + out.CACertPath = in.CACertPath + out.DiscoveryFile = in.DiscoveryFile + out.DiscoveryToken = in.DiscoveryToken + out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers)) + out.DiscoveryTimeout = (*v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) + out.TLSBootstrapToken = in.TLSBootstrapToken + out.Token = in.Token + out.ClusterName = in.ClusterName + out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes)) + out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification + out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) + return nil +} + +// Convert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration is an autogenerated conversion function. +func Convert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration(in, out, s) +} + +func autoConvert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error { + if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { + return err + } + out.CACertPath = in.CACertPath + out.DiscoveryFile = in.DiscoveryFile + out.DiscoveryToken = in.DiscoveryToken + out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers)) + out.DiscoveryTimeout = (*v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout)) + out.TLSBootstrapToken = in.TLSBootstrapToken + out.Token = in.Token + out.ClusterName = in.ClusterName + out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes)) + out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification + out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) + return nil +} + +// Convert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration is an autogenerated conversion function. +func Convert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error { + return autoConvert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration(in, out, s) +} + +func autoConvert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error { + out.Name = in.Name + out.CRISocket = in.CRISocket + out.Taints = *(*[]core_v1.Taint)(unsafe.Pointer(&in.Taints)) + out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) + return nil +} + +// Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions is an autogenerated conversion function. +func Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error { + return autoConvert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in, out, s) +} + +func autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { + out.Name = in.Name + out.CRISocket = in.CRISocket + out.Taints = *(*[]core_v1.Taint)(unsafe.Pointer(&in.Taints)) + out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) + return nil +} + +// Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions is an autogenerated conversion function. +func Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { + return autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(in, out, s) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 000000000..d63be5c14 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,477 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + core_v1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *API) DeepCopyInto(out *API) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new API. +func (in *API) DeepCopy() *API { + if in == nil { + return nil + } + out := new(API) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuditPolicyConfiguration) DeepCopyInto(out *AuditPolicyConfiguration) { + *out = *in + if in.LogMaxAge != nil { + in, out := &in.LogMaxAge, &out.LogMaxAge + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuditPolicyConfiguration. +func (in *AuditPolicyConfiguration) DeepCopy() *AuditPolicyConfiguration { + if in == nil { + return nil + } + out := new(AuditPolicyConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) { + *out = *in + if in.Token != nil { + in, out := &in.Token, &out.Token + if *in == nil { + *out = nil + } else { + *out = new(BootstrapTokenString) + **out = **in + } + } + if in.TTL != nil { + in, out := &in.TTL, &out.TTL + if *in == nil { + *out = nil + } else { + *out = new(v1.Duration) + **out = **in + } + } + if in.Expires != nil { + in, out := &in.Expires, &out.Expires + if *in == nil { + *out = nil + } else { + *out = (*in).DeepCopy() + } + } + if in.Usages != nil { + in, out := &in.Usages, &out.Usages + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Groups != nil { + in, out := &in.Groups, &out.Groups + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken. +func (in *BootstrapToken) DeepCopy() *BootstrapToken { + if in == nil { + return nil + } + out := new(BootstrapToken) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString. +func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString { + if in == nil { + return nil + } + out := new(BootstrapTokenString) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Etcd) DeepCopyInto(out *Etcd) { + *out = *in + if in.Local != nil { + in, out := &in.Local, &out.Local + if *in == nil { + *out = nil + } else { + *out = new(LocalEtcd) + (*in).DeepCopyInto(*out) + } + } + if in.External != nil { + in, out := &in.External, &out.External + if *in == nil { + *out = nil + } else { + *out = new(ExternalEtcd) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Etcd. +func (in *Etcd) DeepCopy() *Etcd { + if in == nil { + return nil + } + out := new(Etcd) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExternalEtcd) DeepCopyInto(out *ExternalEtcd) { + *out = *in + if in.Endpoints != nil { + in, out := &in.Endpoints, &out.Endpoints + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalEtcd. +func (in *ExternalEtcd) DeepCopy() *ExternalEtcd { + if in == nil { + return nil + } + out := new(ExternalEtcd) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HostPathMount) DeepCopyInto(out *HostPathMount) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPathMount. +func (in *HostPathMount) DeepCopy() *HostPathMount { + if in == nil { + return nil + } + out := new(HostPathMount) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeProxy) DeepCopyInto(out *KubeProxy) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + if *in == nil { + *out = nil + } else { + *out = new(v1alpha1.KubeProxyConfiguration) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeProxy. +func (in *KubeProxy) DeepCopy() *KubeProxy { + if in == nil { + return nil + } + out := new(KubeProxy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) { + *out = *in + if in.BaseConfig != nil { + in, out := &in.BaseConfig, &out.BaseConfig + if *in == nil { + *out = nil + } else { + *out = new(v1beta1.KubeletConfiguration) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeletConfiguration. +func (in *KubeletConfiguration) DeepCopy() *KubeletConfiguration { + if in == nil { + return nil + } + out := new(KubeletConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) { + *out = *in + if in.ExtraArgs != nil { + in, out := &in.ExtraArgs, &out.ExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ServerCertSANs != nil { + in, out := &in.ServerCertSANs, &out.ServerCertSANs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.PeerCertSANs != nil { + in, out := &in.PeerCertSANs, &out.PeerCertSANs + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalEtcd. +func (in *LocalEtcd) DeepCopy() *LocalEtcd { + if in == nil { + return nil + } + out := new(LocalEtcd) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.BootstrapTokens != nil { + in, out := &in.BootstrapTokens, &out.BootstrapTokens + *out = make([]BootstrapToken, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.NodeRegistration.DeepCopyInto(&out.NodeRegistration) + out.API = in.API + in.KubeProxy.DeepCopyInto(&out.KubeProxy) + in.Etcd.DeepCopyInto(&out.Etcd) + in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration) + out.Networking = in.Networking + if in.APIServerExtraArgs != nil { + in, out := &in.APIServerExtraArgs, &out.APIServerExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ControllerManagerExtraArgs != nil { + in, out := &in.ControllerManagerExtraArgs, &out.ControllerManagerExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SchedulerExtraArgs != nil { + in, out := &in.SchedulerExtraArgs, &out.SchedulerExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.APIServerExtraVolumes != nil { + in, out := &in.APIServerExtraVolumes, &out.APIServerExtraVolumes + *out = make([]HostPathMount, len(*in)) + copy(*out, *in) + } + if in.ControllerManagerExtraVolumes != nil { + in, out := &in.ControllerManagerExtraVolumes, &out.ControllerManagerExtraVolumes + *out = make([]HostPathMount, len(*in)) + copy(*out, *in) + } + if in.SchedulerExtraVolumes != nil { + in, out := &in.SchedulerExtraVolumes, &out.SchedulerExtraVolumes + *out = make([]HostPathMount, len(*in)) + copy(*out, *in) + } + if in.APIServerCertSANs != nil { + in, out := &in.APIServerCertSANs, &out.APIServerCertSANs + *out = make([]string, len(*in)) + copy(*out, *in) + } + in.AuditPolicyConfiguration.DeepCopyInto(&out.AuditPolicyConfiguration) + if in.FeatureGates != nil { + in, out := &in.FeatureGates, &out.FeatureGates + *out = make(map[string]bool, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterConfiguration. +func (in *MasterConfiguration) DeepCopy() *MasterConfiguration { + if in == nil { + return nil + } + out := new(MasterConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MasterConfiguration) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Networking) DeepCopyInto(out *Networking) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Networking. +func (in *Networking) DeepCopy() *Networking { + if in == nil { + return nil + } + out := new(Networking) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeConfiguration) DeepCopyInto(out *NodeConfiguration) { + *out = *in + out.TypeMeta = in.TypeMeta + in.NodeRegistration.DeepCopyInto(&out.NodeRegistration) + if in.DiscoveryTokenAPIServers != nil { + in, out := &in.DiscoveryTokenAPIServers, &out.DiscoveryTokenAPIServers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.DiscoveryTimeout != nil { + in, out := &in.DiscoveryTimeout, &out.DiscoveryTimeout + if *in == nil { + *out = nil + } else { + *out = new(v1.Duration) + **out = **in + } + } + if in.DiscoveryTokenCACertHashes != nil { + in, out := &in.DiscoveryTokenCACertHashes, &out.DiscoveryTokenCACertHashes + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.FeatureGates != nil { + in, out := &in.FeatureGates, &out.FeatureGates + *out = make(map[string]bool, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeConfiguration. +func (in *NodeConfiguration) DeepCopy() *NodeConfiguration { + if in == nil { + return nil + } + out := new(NodeConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeConfiguration) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) { + *out = *in + if in.Taints != nil { + in, out := &in.Taints, &out.Taints + *out = make([]core_v1.Taint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KubeletExtraArgs != nil { + in, out := &in.KubeletExtraArgs, &out.KubeletExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRegistrationOptions. +func (in *NodeRegistrationOptions) DeepCopy() *NodeRegistrationOptions { + if in == nil { + return nil + } + out := new(NodeRegistrationOptions) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.defaults.go new file mode 100644 index 000000000..940e5621f --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.defaults.go @@ -0,0 +1,56 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + scheme.AddTypeDefaultingFunc(&MasterConfiguration{}, func(obj interface{}) { SetObjectDefaults_MasterConfiguration(obj.(*MasterConfiguration)) }) + scheme.AddTypeDefaultingFunc(&NodeConfiguration{}, func(obj interface{}) { SetObjectDefaults_NodeConfiguration(obj.(*NodeConfiguration)) }) + return nil +} + +func SetObjectDefaults_MasterConfiguration(in *MasterConfiguration) { + SetDefaults_MasterConfiguration(in) + for i := range in.BootstrapTokens { + a := &in.BootstrapTokens[i] + SetDefaults_BootstrapToken(a) + } + SetDefaults_NodeRegistrationOptions(&in.NodeRegistration) + if in.KubeProxy.Config != nil { + v1alpha1.SetDefaults_KubeProxyConfiguration(in.KubeProxy.Config) + } + if in.KubeletConfiguration.BaseConfig != nil { + v1beta1.SetDefaults_KubeletConfiguration(in.KubeletConfiguration.BaseConfig) + } +} + +func SetObjectDefaults_NodeConfiguration(in *NodeConfiguration) { + SetDefaults_NodeConfiguration(in) + SetDefaults_NodeRegistrationOptions(&in.NodeRegistration) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/BUILD index 022e9c7a3..abff6526c 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/BUILD @@ -10,17 +10,15 @@ go_library( "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", "//pkg/apis/core/validation:go_default_library", - "//pkg/kubeapiserver/authorizer/modes:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig/validation:go_default_library", "//pkg/proxy/apis/kubeproxyconfig:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/validation:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", - "//pkg/util/node:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation.go index dbef2b7a5..a85ba40a0 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation.go @@ -35,71 +35,42 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" apivalidation "k8s.io/kubernetes/pkg/apis/core/validation" - authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" kubeletvalidation "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation" "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" kubeproxyscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme" + kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" proxyvalidation "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" - "k8s.io/kubernetes/pkg/util/node" ) -// TODO: Break out the cloudprovider functionality out of core and only support the new flow -// described in https://github.com/kubernetes/community/pull/128 -var cloudproviders = []string{ - "aws", - "azure", - "cloudstack", - "gce", - "external", // Support for out-of-tree cloud providers - "openstack", - "ovirt", - "photon", - "vsphere", -} - -// Describes the authorization modes that are enforced by kubeadm -var requiredAuthzModes = []string{ - authzmodes.ModeRBAC, - authzmodes.ModeNode, -} - // ValidateMasterConfiguration validates master configuration and collects all encountered errors func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList { allErrs := field.ErrorList{} - allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudprovider"))...) - allErrs = append(allErrs, ValidateAuthorizationModes(c.AuthorizationModes, field.NewPath("authorization-modes"))...) allErrs = append(allErrs, ValidateNetworking(&c.Networking, field.NewPath("networking"))...) - allErrs = append(allErrs, ValidateCertSANs(c.APIServerCertSANs, field.NewPath("api-server-cert-altnames"))...) - allErrs = append(allErrs, ValidateCertSANs(c.Etcd.ServerCertSANs, field.NewPath("etcd-server-cert-altnames"))...) - allErrs = append(allErrs, ValidateCertSANs(c.Etcd.PeerCertSANs, field.NewPath("etcd-peer-cert-altnames"))...) - allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificates-dir"))...) - allErrs = append(allErrs, ValidateNodeName(c.NodeName, field.NewPath("node-name"))...) - allErrs = append(allErrs, ValidateToken(c.Token, field.NewPath("token"))...) - allErrs = append(allErrs, ValidateTokenUsages(c.TokenUsages, field.NewPath("tokenUsages"))...) - allErrs = append(allErrs, ValidateTokenGroups(c.TokenUsages, c.TokenGroups, field.NewPath("tokenGroups"))...) - allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("feature-gates"))...) - allErrs = append(allErrs, ValidateAPIEndpoint(c, field.NewPath("api-endpoint"))...) - allErrs = append(allErrs, ValidateProxy(c, field.NewPath("kube-proxy"))...) - if features.Enabled(c.FeatureGates, features.DynamicKubeletConfig) { - allErrs = append(allErrs, ValidateKubeletConfiguration(&c.KubeletConfiguration, field.NewPath("kubeletConfiguration"))...) - } + allErrs = append(allErrs, ValidateCertSANs(c.APIServerCertSANs, field.NewPath("apiServerCertSANs"))...) + allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificatesDir"))...) + allErrs = append(allErrs, ValidateNodeRegistrationOptions(&c.NodeRegistration, field.NewPath("nodeRegistration"))...) + allErrs = append(allErrs, ValidateBootstrapTokens(c.BootstrapTokens, field.NewPath("bootstrapTokens"))...) + allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("featureGates"))...) + allErrs = append(allErrs, ValidateAPIEndpoint(&c.API, field.NewPath("api"))...) + allErrs = append(allErrs, ValidateProxy(c.KubeProxy.Config, field.NewPath("kubeProxy").Child("config"))...) + allErrs = append(allErrs, ValidateEtcd(&c.Etcd, field.NewPath("etcd"))...) + allErrs = append(allErrs, ValidateKubeletConfiguration(&c.KubeletConfiguration, field.NewPath("kubeletConfiguration"))...) return allErrs } // ValidateProxy validates proxy configuration and collects all encountered errors -func ValidateProxy(c *kubeadm.MasterConfiguration, fldPath *field.Path) field.ErrorList { +func ValidateProxy(c *kubeproxyconfigv1alpha1.KubeProxyConfiguration, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} // Convert to the internal version internalcfg := &kubeproxyconfig.KubeProxyConfiguration{} - err := kubeproxyscheme.Scheme.Convert(c.KubeProxy.Config, internalcfg, nil) + err := kubeproxyscheme.Scheme.Convert(c, internalcfg, nil) if err != nil { - allErrs = append(allErrs, field.Invalid(fldPath, "KubeProxy.Config", err.Error())) + allErrs = append(allErrs, field.Invalid(fldPath, "", err.Error())) return allErrs } return proxyvalidation.Validate(internalcfg) @@ -108,49 +79,40 @@ func ValidateProxy(c *kubeadm.MasterConfiguration, fldPath *field.Path) field.Er // ValidateNodeConfiguration validates node configuration and collects all encountered errors func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList { allErrs := field.ErrorList{} - allErrs = append(allErrs, ValidateDiscovery(c, field.NewPath("discovery"))...) + allErrs = append(allErrs, ValidateDiscovery(c)...) + allErrs = append(allErrs, ValidateNodeRegistrationOptions(&c.NodeRegistration, field.NewPath("nodeRegistration"))...) if !filepath.IsAbs(c.CACertPath) || !strings.HasSuffix(c.CACertPath, ".crt") { - allErrs = append(allErrs, field.Invalid(field.NewPath("ca-cert-path"), c.CACertPath, "the ca certificate path must be an absolute path")) + allErrs = append(allErrs, field.Invalid(field.NewPath("caCertPath"), c.CACertPath, "the ca certificate path must be an absolute path")) } return allErrs } -// ValidateAuthorizationModes validates authorization modes and collects all encountered errors -func ValidateAuthorizationModes(authzModes []string, fldPath *field.Path) field.ErrorList { +// ValidateNodeRegistrationOptions validates the NodeRegistrationOptions object +func ValidateNodeRegistrationOptions(nro *kubeadm.NodeRegistrationOptions, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} - found := map[string]bool{} - for _, authzMode := range authzModes { - if !authzmodes.IsValidAuthorizationMode(authzMode) { - allErrs = append(allErrs, field.Invalid(fldPath, authzMode, "invalid authorization mode")) - } - - if found[authzMode] { - allErrs = append(allErrs, field.Invalid(fldPath, authzMode, "duplicate authorization mode")) - continue - } - found[authzMode] = true - } - for _, requiredMode := range requiredAuthzModes { - if !found[requiredMode] { - allErrs = append(allErrs, field.Required(fldPath, fmt.Sprintf("authorization mode %s must be enabled", requiredMode))) - } + if len(nro.Name) == 0 { + allErrs = append(allErrs, field.Required(fldPath, "--node-name or .nodeRegistration.name in the config file is a required value. It seems like this value couldn't be automatically detected in your environment, please specify the desired value using the CLI or config file.")) + } else { + allErrs = append(allErrs, apivalidation.ValidateDNS1123Subdomain(nro.Name, field.NewPath("name"))...) } + allErrs = append(allErrs, ValidateAbsolutePath(nro.CRISocket, fldPath.Child("criSocket"))...) + // TODO: Maybe validate .Taints as well in the future using something like validateNodeTaints() in pkg/apis/core/validation return allErrs } // ValidateDiscovery validates discovery related configuration and collects all encountered errors -func ValidateDiscovery(c *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList { +func ValidateDiscovery(c *kubeadm.NodeConfiguration) field.ErrorList { allErrs := field.ErrorList{} if len(c.DiscoveryToken) != 0 { - allErrs = append(allErrs, ValidateToken(c.DiscoveryToken, fldPath)...) + allErrs = append(allErrs, ValidateToken(c.DiscoveryToken, field.NewPath("discoveryToken"))...) } if len(c.DiscoveryFile) != 0 { - allErrs = append(allErrs, ValidateDiscoveryFile(c.DiscoveryFile, fldPath)...) + allErrs = append(allErrs, ValidateDiscoveryFile(c.DiscoveryFile, field.NewPath("discoveryFile"))...) } - allErrs = append(allErrs, ValidateArgSelection(c, fldPath)...) - allErrs = append(allErrs, ValidateToken(c.TLSBootstrapToken, fldPath)...) - allErrs = append(allErrs, ValidateJoinDiscoveryTokenAPIServer(c, fldPath)...) + allErrs = append(allErrs, ValidateArgSelection(c, field.NewPath("discovery"))...) + allErrs = append(allErrs, ValidateToken(c.TLSBootstrapToken, field.NewPath("tlsBootstrapToken"))...) + allErrs = append(allErrs, ValidateJoinDiscoveryTokenAPIServer(c.DiscoveryTokenAPIServers, field.NewPath("discoveryTokenAPIServers"))...) return allErrs } @@ -159,22 +121,22 @@ func ValidateDiscovery(c *kubeadm.NodeConfiguration, fldPath *field.Path) field. func ValidateArgSelection(cfg *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(cfg.DiscoveryToken) != 0 && len(cfg.DiscoveryFile) != 0 { - allErrs = append(allErrs, field.Invalid(fldPath, "", "DiscoveryToken and DiscoveryFile cannot both be set")) + allErrs = append(allErrs, field.Invalid(fldPath, "", "discoveryToken and discoveryFile cannot both be set")) } if len(cfg.DiscoveryToken) == 0 && len(cfg.DiscoveryFile) == 0 { - allErrs = append(allErrs, field.Invalid(fldPath, "", "DiscoveryToken or DiscoveryFile must be set")) + allErrs = append(allErrs, field.Invalid(fldPath, "", "discoveryToken or discoveryFile must be set")) } if len(cfg.DiscoveryTokenAPIServers) < 1 && len(cfg.DiscoveryToken) != 0 { - allErrs = append(allErrs, field.Required(fldPath, "DiscoveryTokenAPIServers not set")) + allErrs = append(allErrs, field.Required(fldPath, "discoveryTokenAPIServers not set")) } if len(cfg.DiscoveryFile) != 0 && len(cfg.DiscoveryTokenCACertHashes) != 0 { - allErrs = append(allErrs, field.Invalid(fldPath, "", "DiscoveryTokenCACertHashes cannot be used with DiscoveryFile")) + allErrs = append(allErrs, field.Invalid(fldPath, "", "discoveryTokenCACertHashes cannot be used with discoveryFile")) } if len(cfg.DiscoveryFile) == 0 && len(cfg.DiscoveryToken) != 0 && len(cfg.DiscoveryTokenCACertHashes) == 0 && !cfg.DiscoveryTokenUnsafeSkipCAVerification { - allErrs = append(allErrs, field.Invalid(fldPath, "", "using token-based discovery without DiscoveryTokenCACertHashes can be unsafe. set --discovery-token-unsafe-skip-ca-verification to continue")) + allErrs = append(allErrs, field.Invalid(fldPath, "", "using token-based discovery without discoveryTokenCACertHashes can be unsafe. set --discovery-token-unsafe-skip-ca-verification to continue")) } // TODO remove once we support multiple api servers @@ -185,9 +147,9 @@ func ValidateArgSelection(cfg *kubeadm.NodeConfiguration, fldPath *field.Path) f } // ValidateJoinDiscoveryTokenAPIServer validates discovery token for API server -func ValidateJoinDiscoveryTokenAPIServer(c *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList { +func ValidateJoinDiscoveryTokenAPIServer(apiServers []string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} - for _, m := range c.DiscoveryTokenAPIServers { + for _, m := range apiServers { _, _, err := net.SplitHostPort(m) if err != nil { allErrs = append(allErrs, field.Invalid(fldPath, m, err.Error())) @@ -214,23 +176,35 @@ func ValidateDiscoveryFile(discoveryFile string, fldPath *field.Path) field.Erro } if u.Scheme != "https" { - allErrs = append(allErrs, field.Invalid(fldPath, discoveryFile, "if an URL is used, the scheme must be https")) + allErrs = append(allErrs, field.Invalid(fldPath, discoveryFile, "if a URL is used, the scheme must be https")) } return allErrs } -// ValidateToken validates token -func ValidateToken(t string, fldPath *field.Path) field.ErrorList { +// ValidateBootstrapTokens validates a slice of BootstrapToken objects +func ValidateBootstrapTokens(bts []kubeadm.BootstrapToken, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} - - id, secret, err := tokenutil.ParseToken(t) - if err != nil { - allErrs = append(allErrs, field.Invalid(fldPath, t, err.Error())) + for i, bt := range bts { + btPath := fldPath.Child(fmt.Sprintf("%d", i)) + allErrs = append(allErrs, ValidateToken(bt.Token.String(), btPath.Child("token"))...) + allErrs = append(allErrs, ValidateTokenUsages(bt.Usages, btPath.Child("usages"))...) + allErrs = append(allErrs, ValidateTokenGroups(bt.Usages, bt.Groups, btPath.Child("groups"))...) + + if bt.Expires != nil && bt.TTL != nil { + allErrs = append(allErrs, field.Invalid(btPath, "", "the BootstrapToken .TTL and .Expires fields are mutually exclusive")) + } } + return allErrs +} - if len(id) == 0 || len(secret) == 0 { - allErrs = append(allErrs, field.Invalid(fldPath, t, "token must be of form '[a-z0-9]{6}.[a-z0-9]{16}'")) +// ValidateToken validates a Bootstrap Token +func ValidateToken(token string, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if !bootstraputil.IsValidBootstrapToken(token) { + allErrs = append(allErrs, field.Invalid(fldPath, token, "the bootstrap token is invalid")) } + return allErrs } @@ -267,6 +241,54 @@ func ValidateTokenUsages(usages []string, fldPath *field.Path) field.ErrorList { return allErrs } +// ValidateEtcd validates the .Etcd sub-struct. +func ValidateEtcd(e *kubeadm.Etcd, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + localPath := fldPath.Child("local") + externalPath := fldPath.Child("external") + + if e.Local == nil && e.External == nil { + allErrs = append(allErrs, field.Invalid(fldPath, "", "either .Etcd.Local or .Etcd.External is required")) + return allErrs + } + if e.Local != nil && e.External != nil { + allErrs = append(allErrs, field.Invalid(fldPath, "", ".Etcd.Local and .Etcd.External are mutually exclusive")) + return allErrs + } + if e.Local != nil { + allErrs = append(allErrs, ValidateAbsolutePath(e.Local.DataDir, localPath.Child("dataDir"))...) + allErrs = append(allErrs, ValidateCertSANs(e.Local.ServerCertSANs, localPath.Child("serverCertSANs"))...) + allErrs = append(allErrs, ValidateCertSANs(e.Local.PeerCertSANs, localPath.Child("peerCertSANs"))...) + } + if e.External != nil { + requireHTTPS := true + // Only allow the http scheme if no certs/keys are passed + if e.External.CAFile == "" && e.External.CertFile == "" && e.External.KeyFile == "" { + requireHTTPS = false + } + // Require either none or both of the cert/key pair + if (e.External.CertFile == "" && e.External.KeyFile != "") || (e.External.CertFile != "" && e.External.KeyFile == "") { + allErrs = append(allErrs, field.Invalid(externalPath, "", "either both or none of .Etcd.External.CertFile and .Etcd.External.KeyFile must be set")) + } + // If the cert and key are specified, require the VA as well + if e.External.CertFile != "" && e.External.KeyFile != "" && e.External.CAFile == "" { + allErrs = append(allErrs, field.Invalid(externalPath, "", "setting .Etcd.External.CertFile and .Etcd.External.KeyFile requires .Etcd.External.CAFile")) + } + + allErrs = append(allErrs, ValidateURLs(e.External.Endpoints, requireHTTPS, externalPath.Child("endpoints"))...) + if e.External.CAFile != "" { + allErrs = append(allErrs, ValidateAbsolutePath(e.External.CAFile, externalPath.Child("caFile"))...) + } + if e.External.CertFile != "" { + allErrs = append(allErrs, ValidateAbsolutePath(e.External.CertFile, externalPath.Child("certFile"))...) + } + if e.External.KeyFile != "" { + allErrs = append(allErrs, ValidateAbsolutePath(e.External.KeyFile, externalPath.Child("keyFile"))...) + } + } + return allErrs +} + // ValidateCertSANs validates alternative names func ValidateCertSANs(altnames []string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -278,6 +300,21 @@ func ValidateCertSANs(altnames []string, fldPath *field.Path) field.ErrorList { return allErrs } +// ValidateURLs validates the URLs given in the string slice, makes sure they are parseable. Optionally, it can enforcs HTTPS usage. +func ValidateURLs(urls []string, requireHTTPS bool, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + for _, urlstr := range urls { + u, err := url.Parse(urlstr) + if err != nil || u.Scheme == "" { + allErrs = append(allErrs, field.Invalid(fldPath, urlstr, "not a valid URL")) + } + if requireHTTPS && u.Scheme != "https" { + allErrs = append(allErrs, field.Invalid(fldPath, urlstr, "the URL must be using the HTTPS scheme")) + } + } + return allErrs +} + // ValidateIPFromString validates ip address func ValidateIPFromString(ipaddr string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -305,10 +342,10 @@ func ValidateIPNetFromString(subnet string, minAddrs int64, fldPath *field.Path) // ValidateNetworking validates networking configuration func ValidateNetworking(c *kubeadm.Networking, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} - allErrs = append(allErrs, apivalidation.ValidateDNS1123Subdomain(c.DNSDomain, field.NewPath("dns-domain"))...) - allErrs = append(allErrs, ValidateIPNetFromString(c.ServiceSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("service-subnet"))...) + allErrs = append(allErrs, apivalidation.ValidateDNS1123Subdomain(c.DNSDomain, field.NewPath("dnsDomain"))...) + allErrs = append(allErrs, ValidateIPNetFromString(c.ServiceSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("serviceSubnet"))...) if len(c.PodSubnet) != 0 { - allErrs = append(allErrs, ValidateIPNetFromString(c.PodSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("pod-subnet"))...) + allErrs = append(allErrs, ValidateIPNetFromString(c.PodSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("podSubnet"))...) } return allErrs } @@ -322,30 +359,6 @@ func ValidateAbsolutePath(path string, fldPath *field.Path) field.ErrorList { return allErrs } -// ValidateNodeName validates the name of a node -func ValidateNodeName(nodename string, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if node.GetHostname(nodename) != nodename { - allErrs = append(allErrs, field.Invalid(fldPath, nodename, "nodename is not valid, must be lower case")) - } - return allErrs -} - -// ValidateCloudProvider validates if cloud provider is supported -func ValidateCloudProvider(provider string, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if len(provider) == 0 { - return allErrs - } - for _, supported := range cloudproviders { - if provider == supported { - return allErrs - } - } - allErrs = append(allErrs, field.Invalid(fldPath, provider, "cloudprovider not supported")) - return allErrs -} - // ValidateMixedArguments validates passed arguments func ValidateMixedArguments(flag *pflag.FlagSet) error { // If --config isn't set, we have nothing to validate @@ -355,7 +368,7 @@ func ValidateMixedArguments(flag *pflag.FlagSet) error { mixedInvalidFlags := []string{} flag.Visit(func(f *pflag.Flag) { - if f.Name == "config" || f.Name == "ignore-preflight-errors" || strings.HasPrefix(f.Name, "skip-") || f.Name == "dry-run" || f.Name == "kubeconfig" { + if f.Name == "config" || f.Name == "ignore-preflight-errors" || strings.HasPrefix(f.Name, "skip-") || f.Name == "dry-run" || f.Name == "kubeconfig" || f.Name == "v" { // "--skip-*" flags or other whitelisted flags can be set with --config return } @@ -385,7 +398,7 @@ func ValidateFeatureGates(featureGates map[string]bool, fldPath *field.Path) fie } // ValidateAPIEndpoint validates API server's endpoint -func ValidateAPIEndpoint(c *kubeadm.MasterConfiguration, fldPath *field.Path) field.ErrorList { +func ValidateAPIEndpoint(c *kubeadm.API, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} endpoint, err := kubeadmutil.GetMasterEndpoint(c) @@ -420,6 +433,10 @@ func ValidateIgnorePreflightErrors(ignorePreflightErrors []string, skipPreflight func ValidateKubeletConfiguration(c *kubeadm.KubeletConfiguration, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + if c.BaseConfig == nil { + return allErrs + } + scheme, _, err := kubeletscheme.NewSchemeAndCodecs() if err != nil { allErrs = append(allErrs, field.Invalid(fldPath, "kubeletConfiguration", err.Error())) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go index a1aca11cb..151cde50b 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go @@ -33,7 +33,7 @@ import ( utilpointer "k8s.io/kubernetes/pkg/util/pointer" ) -func TestValidateTokenDiscovery(t *testing.T) { +func TestValidateToken(t *testing.T) { var tests = []struct { c *kubeadm.NodeConfiguration f *field.Path @@ -51,7 +51,7 @@ func TestValidateTokenDiscovery(t *testing.T) { err := ValidateToken(rt.c.Token, rt.f).ToAggregate() if (err == nil) != rt.expected { t.Errorf( - "failed ValidateTokenDiscovery:\n\texpected: %t\n\t actual: %t", + "failed ValidateToken:\n\texpected: %t\n\t actual: %t", rt.expected, (err == nil), ) @@ -104,76 +104,31 @@ func TestValidateTokenGroups(t *testing.T) { } } -func TestValidateAuthorizationModes(t *testing.T) { +func TestValidateNodeRegistrationOptions(t *testing.T) { var tests = []struct { - s []string - f *field.Path - expected bool + nodeName string + criSocket string + expectedErrors bool }{ - {[]string{""}, nil, false}, - {[]string{"rBAC"}, nil, false}, // mode not supported - {[]string{"rBAC", "Webhook"}, nil, false}, // mode not supported - {[]string{"RBAC", "Webhook"}, nil, false}, // mode Node required - {[]string{"Node", "RBAC", "Webhook", "Webhook"}, nil, false}, // no duplicates allowed - {[]string{"not valid"}, nil, false}, // invalid mode - {[]string{"Node", "RBAC"}, nil, true}, // supported - {[]string{"RBAC", "Node"}, nil, true}, // supported - {[]string{"Node", "RBAC", "Webhook", "ABAC"}, nil, true}, // supported + {"", "/some/path", true}, // node name can't be empty + {"valid-nodename", "", true}, // crisocket can't be empty + {"INVALID-NODENAME", "/some/path", true}, // Upper cases is invalid + {"invalid-nodename-", "/some/path", true}, // Can't have trailing dashes + {"invalid-node?name", "/some/path", true}, // Unsupported characters + {"valid-nodename", "relative/path", true}, // crisocket must be an absolute path + {"valid-nodename", "/some/path", false}, // supported + {"valid-nodename-with-numbers01234", "/some/path/with/numbers/01234/", false}, // supported, with numbers as well } for _, rt := range tests { - actual := ValidateAuthorizationModes(rt.s, rt.f) - if (len(actual) == 0) != rt.expected { + nro := kubeadm.NodeRegistrationOptions{Name: rt.nodeName, CRISocket: rt.criSocket} + actual := ValidateNodeRegistrationOptions(&nro, field.NewPath("nodeRegistration")) + actualErrors := len(actual) > 0 + if actualErrors != rt.expectedErrors { t.Errorf( - "failed ValidateAuthorizationModes:\n\texpected: %t\n\t actual: %t", - rt.expected, - (len(actual) == 0), - ) - } - } -} - -func TestValidateNodeName(t *testing.T) { - var tests = []struct { - s string - f *field.Path - expected bool - }{ - {"", nil, false}, // ok if not provided - {"1234", nil, true}, // supported - {"valid-nodename", nil, true}, // supported - {"INVALID-NODENAME", nil, false}, // Upper cases is invalid - } - for _, rt := range tests { - actual := ValidateNodeName(rt.s, rt.f) - if (len(actual) == 0) != rt.expected { - t.Errorf( - "failed ValidateNodeName:\n\texpected: %t\n\t actual: %t", - rt.expected, - (len(actual) == 0), - ) - } - } -} - -func TestValidateCloudProvider(t *testing.T) { - var tests = []struct { - s string - f *field.Path - expected bool - }{ - {"", nil, true}, // if not provided, ok, it's optional - {"1234", nil, false}, // not supported - {"awws", nil, false}, // not supported - {"aws", nil, true}, // supported - {"gce", nil, true}, // supported - } - for _, rt := range tests { - actual := ValidateCloudProvider(rt.s, rt.f) - if (len(actual) == 0) != rt.expected { - t.Errorf( - "failed ValidateCloudProvider:\n\texpected: %t\n\t actual: %t", - rt.expected, - (len(actual) == 0), + "failed ValidateNodeRegistrationOptions: value: %v\n\texpected: %t\n\t actual: %t", + nro, + rt.expectedErrors, + actualErrors, ) } } @@ -275,7 +230,73 @@ func TestValidateAPIEndpoint(t *testing.T) { expected: false, }, { - name: "Valid IPv4 address and default port", + name: "Valid DNS ControlPlaneEndpoint (with port), AdvertiseAddress and default port", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "cp.k8s.io:8081", + AdvertiseAddress: "4.5.6.7", + BindPort: 6443, + }, + }, + expected: true, + }, + { + name: "Valid IPv4 ControlPlaneEndpoint (with port), AdvertiseAddress and default port", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "1.2.3.4:8081", + AdvertiseAddress: "4.5.6.7", + BindPort: 6443, + }, + }, + expected: true, + }, + { + name: "Valid IPv6 ControlPlaneEndpoint (with port), ControlPlaneEndpoint and port", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "[2001:db7::1]:8081", + AdvertiseAddress: "2001:db7::2", + BindPort: 6443, + }, + }, + expected: true, + }, + { + name: "Valid DNS ControlPlaneEndpoint (without port), AdvertiseAddress and default port", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "cp.k8s.io", + AdvertiseAddress: "4.5.6.7", + BindPort: 6443, + }, + }, + expected: true, + }, + { + name: "Valid IPv4 ControlPlaneEndpoint (without port), AdvertiseAddress and default port", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "1.2.3.4", + AdvertiseAddress: "4.5.6.7", + BindPort: 6443, + }, + }, + expected: true, + }, + { + name: "Valid IPv6 ControlPlaneEndpoint (without port), ControlPlaneEndpoint and port", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "2001:db7::1", + AdvertiseAddress: "2001:db7::2", + BindPort: 6443, + }, + }, + expected: true, + }, + { + name: "Valid IPv4 AdvertiseAddress and default port", s: &kubeadm.MasterConfiguration{ API: kubeadm.API{ AdvertiseAddress: "1.2.3.4", @@ -285,7 +306,7 @@ func TestValidateAPIEndpoint(t *testing.T) { expected: true, }, { - name: "Valid IPv6 address and port", + name: "Valid IPv6 AdvertiseAddress and port", s: &kubeadm.MasterConfiguration{ API: kubeadm.API{ AdvertiseAddress: "2001:db7::1", @@ -295,7 +316,7 @@ func TestValidateAPIEndpoint(t *testing.T) { expected: true, }, { - name: "Invalid IPv4 address", + name: "Invalid IPv4 AdvertiseAddress", s: &kubeadm.MasterConfiguration{ API: kubeadm.API{ AdvertiseAddress: "1.2.34", @@ -305,7 +326,7 @@ func TestValidateAPIEndpoint(t *testing.T) { expected: false, }, { - name: "Invalid IPv6 address", + name: "Invalid IPv6 AdvertiseAddress", s: &kubeadm.MasterConfiguration{ API: kubeadm.API{ AdvertiseAddress: "2001:db7:1", @@ -314,9 +335,55 @@ func TestValidateAPIEndpoint(t *testing.T) { }, expected: false, }, + { + name: "Invalid BindPort", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + AdvertiseAddress: "1.2.3.4", + BindPort: 0, + }, + }, + expected: false, + }, + { + name: "Invalid DNS ControlPlaneEndpoint", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "bad!!.k8s.io", + }, + }, + expected: false, + }, + { + name: "Invalid ipv4 ControlPlaneEndpoint", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "1..3.4", + }, + }, + expected: false, + }, + { + name: "Invalid ipv6 ControlPlaneEndpoint", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "1200::AB00:1234::2552:7777:1313", + }, + }, + expected: false, + }, + { + name: "Invalid ControlPlaneEndpoint port", + s: &kubeadm.MasterConfiguration{ + API: kubeadm.API{ + ControlPlaneEndpoint: "1.2.3.4:0", + }, + }, + expected: false, + }, } for _, rt := range tests { - actual := ValidateAPIEndpoint(rt.s, nil) + actual := ValidateAPIEndpoint(&rt.s.API, nil) if (len(actual) == 0) != rt.expected { t.Errorf( "%s test case failed:\n\texpected: %t\n\t actual: %t", @@ -343,13 +410,12 @@ func TestValidateMasterConfiguration(t *testing.T) { AdvertiseAddress: "1.2.3.4", BindPort: 6443, }, - AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "10.96.0.1/12", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/cert/dir", - NodeName: nodename, + CertificatesDir: "/some/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, false}, {"invalid missing token with IPv6 service subnet", &kubeadm.MasterConfiguration{ @@ -357,13 +423,12 @@ func TestValidateMasterConfiguration(t *testing.T) { AdvertiseAddress: "1.2.3.4", BindPort: 6443, }, - AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "2001:db8::1/98", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/cert/dir", - NodeName: nodename, + CertificatesDir: "/some/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, false}, {"invalid missing node name", &kubeadm.MasterConfiguration{ @@ -371,13 +436,11 @@ func TestValidateMasterConfiguration(t *testing.T) { AdvertiseAddress: "1.2.3.4", BindPort: 6443, }, - AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "10.96.0.1/12", DNSDomain: "cluster.local", }, CertificatesDir: "/some/other/cert/dir", - Token: "abcdef.0123456789abcdef", }, false}, {"valid master configuration with incorrect IPv4 pod subnet", &kubeadm.MasterConfiguration{ @@ -385,15 +448,13 @@ func TestValidateMasterConfiguration(t *testing.T) { AdvertiseAddress: "1.2.3.4", BindPort: 6443, }, - AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "10.96.0.1/12", DNSDomain: "cluster.local", PodSubnet: "10.0.1.15", }, - CertificatesDir: "/some/other/cert/dir", - Token: "abcdef.0123456789abcdef", - NodeName: nodename, + CertificatesDir: "/some/other/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, false}, {"valid master configuration with IPv4 service subnet", &kubeadm.MasterConfiguration{ @@ -401,6 +462,11 @@ func TestValidateMasterConfiguration(t *testing.T) { AdvertiseAddress: "1.2.3.4", BindPort: 6443, }, + Etcd: kubeadm.Etcd{ + Local: &kubeadm.LocalEtcd{ + DataDir: "/some/path", + }, + }, KubeProxy: kubeadm.KubeProxy{ Config: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{ BindAddress: "192.168.59.103", @@ -427,15 +493,13 @@ func TestValidateMasterConfiguration(t *testing.T) { }, }, }, - AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "10.96.0.1/12", DNSDomain: "cluster.local", PodSubnet: "10.0.1.15/16", }, - CertificatesDir: "/some/other/cert/dir", - Token: "abcdef.0123456789abcdef", - NodeName: nodename, + CertificatesDir: "/some/other/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, true}, {"valid master configuration using IPv6 service subnet", &kubeadm.MasterConfiguration{ @@ -443,6 +507,11 @@ func TestValidateMasterConfiguration(t *testing.T) { AdvertiseAddress: "1:2:3::4", BindPort: 3446, }, + Etcd: kubeadm.Etcd{ + Local: &kubeadm.LocalEtcd{ + DataDir: "/some/path", + }, + }, KubeProxy: kubeadm.KubeProxy{ Config: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{ BindAddress: "192.168.59.103", @@ -469,14 +538,12 @@ func TestValidateMasterConfiguration(t *testing.T) { }, }, }, - AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "2001:db8::1/98", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/other/cert/dir", - Token: "abcdef.0123456789abcdef", - NodeName: nodename, + CertificatesDir: "/some/other/cert/dir", + NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"}, }, true}, } for _, rt := range tests { @@ -705,7 +772,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { } for _, successCase := range successCases { - if errs := ValidateProxy(&successCase, nil); len(errs) != 0 { + if errs := ValidateProxy(successCase.KubeProxy.Config, nil); len(errs) != 0 { t.Errorf("failed ValidateProxy: expect no errors but got %v", errs) } } @@ -909,7 +976,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { } for i, errorCase := range errorCases { - if errs := ValidateProxy(&errorCase.masterConfig, nil); len(errs) == 0 { + if errs := ValidateProxy(errorCase.masterConfig.KubeProxy.Config, nil); len(errs) == 0 { t.Errorf("%d failed ValidateProxy: expected error for %s, but got no error", i, errorCase.msg) } else if !strings.Contains(errs[0].Error(), errorCase.msg) { t.Errorf("%d failed ValidateProxy: unexpected error: %v, expected: %s", i, errs[0], errorCase.msg) @@ -1040,7 +1107,7 @@ func TestValidateJoinDiscoveryTokenAPIServer(t *testing.T) { }, } for _, rt := range tests { - actual := ValidateJoinDiscoveryTokenAPIServer(rt.s, nil) + actual := ValidateJoinDiscoveryTokenAPIServer(rt.s.DiscoveryTokenAPIServers, nil) if (len(actual) == 0) != rt.expected { t.Errorf( "failed ValidateJoinDiscoveryTokenAPIServer:\n\texpected: %t\n\t actual: %t", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go index 2448ac071..2295df241 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,6 +21,7 @@ limitations under the License. package kubeadm import ( + core_v1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" @@ -69,42 +70,97 @@ func (in *AuditPolicyConfiguration) DeepCopy() *AuditPolicyConfiguration { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Etcd) DeepCopyInto(out *Etcd) { +func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) { *out = *in - if in.Endpoints != nil { - in, out := &in.Endpoints, &out.Endpoints - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.ExtraArgs != nil { - in, out := &in.ExtraArgs, &out.ExtraArgs - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val + if in.Token != nil { + in, out := &in.Token, &out.Token + if *in == nil { + *out = nil + } else { + *out = new(BootstrapTokenString) + **out = **in } } - if in.SelfHosted != nil { - in, out := &in.SelfHosted, &out.SelfHosted + if in.TTL != nil { + in, out := &in.TTL, &out.TTL if *in == nil { *out = nil } else { - *out = new(SelfHostedEtcd) + *out = new(v1.Duration) **out = **in } } - if in.ServerCertSANs != nil { - in, out := &in.ServerCertSANs, &out.ServerCertSANs + if in.Expires != nil { + in, out := &in.Expires, &out.Expires + if *in == nil { + *out = nil + } else { + *out = (*in).DeepCopy() + } + } + if in.Usages != nil { + in, out := &in.Usages, &out.Usages *out = make([]string, len(*in)) copy(*out, *in) } - if in.PeerCertSANs != nil { - in, out := &in.PeerCertSANs, &out.PeerCertSANs + if in.Groups != nil { + in, out := &in.Groups, &out.Groups *out = make([]string, len(*in)) copy(*out, *in) } return } +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken. +func (in *BootstrapToken) DeepCopy() *BootstrapToken { + if in == nil { + return nil + } + out := new(BootstrapToken) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString. +func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString { + if in == nil { + return nil + } + out := new(BootstrapTokenString) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Etcd) DeepCopyInto(out *Etcd) { + *out = *in + if in.Local != nil { + in, out := &in.Local, &out.Local + if *in == nil { + *out = nil + } else { + *out = new(LocalEtcd) + (*in).DeepCopyInto(*out) + } + } + if in.External != nil { + in, out := &in.External, &out.External + if *in == nil { + *out = nil + } else { + *out = new(ExternalEtcd) + (*in).DeepCopyInto(*out) + } + } + return +} + // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Etcd. func (in *Etcd) DeepCopy() *Etcd { if in == nil { @@ -115,6 +171,27 @@ func (in *Etcd) DeepCopy() *Etcd { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExternalEtcd) DeepCopyInto(out *ExternalEtcd) { + *out = *in + if in.Endpoints != nil { + in, out := &in.Endpoints, &out.Endpoints + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalEtcd. +func (in *ExternalEtcd) DeepCopy() *ExternalEtcd { + if in == nil { + return nil + } + out := new(ExternalEtcd) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HostPathMount) DeepCopyInto(out *HostPathMount) { *out = *in @@ -182,38 +259,55 @@ func (in *KubeletConfiguration) DeepCopy() *KubeletConfiguration { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) { +func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) { *out = *in - out.TypeMeta = in.TypeMeta - out.API = in.API - in.KubeProxy.DeepCopyInto(&out.KubeProxy) - in.Etcd.DeepCopyInto(&out.Etcd) - in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration) - out.Networking = in.Networking - if in.AuthorizationModes != nil { - in, out := &in.AuthorizationModes, &out.AuthorizationModes - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.TokenTTL != nil { - in, out := &in.TokenTTL, &out.TokenTTL - if *in == nil { - *out = nil - } else { - *out = new(v1.Duration) - **out = **in + if in.ExtraArgs != nil { + in, out := &in.ExtraArgs, &out.ExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val } } - if in.TokenUsages != nil { - in, out := &in.TokenUsages, &out.TokenUsages + if in.ServerCertSANs != nil { + in, out := &in.ServerCertSANs, &out.ServerCertSANs *out = make([]string, len(*in)) copy(*out, *in) } - if in.TokenGroups != nil { - in, out := &in.TokenGroups, &out.TokenGroups + if in.PeerCertSANs != nil { + in, out := &in.PeerCertSANs, &out.PeerCertSANs *out = make([]string, len(*in)) copy(*out, *in) } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalEtcd. +func (in *LocalEtcd) DeepCopy() *LocalEtcd { + if in == nil { + return nil + } + out := new(LocalEtcd) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.BootstrapTokens != nil { + in, out := &in.BootstrapTokens, &out.BootstrapTokens + *out = make([]BootstrapToken, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.NodeRegistration.DeepCopyInto(&out.NodeRegistration) + out.API = in.API + in.KubeProxy.DeepCopyInto(&out.KubeProxy) + in.Etcd.DeepCopyInto(&out.Etcd) + in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration) + out.Networking = in.Networking if in.APIServerExtraArgs != nil { in, out := &in.APIServerExtraArgs, &out.APIServerExtraArgs *out = make(map[string]string, len(*in)) @@ -304,11 +398,21 @@ func (in *Networking) DeepCopy() *Networking { func (in *NodeConfiguration) DeepCopyInto(out *NodeConfiguration) { *out = *in out.TypeMeta = in.TypeMeta + in.NodeRegistration.DeepCopyInto(&out.NodeRegistration) if in.DiscoveryTokenAPIServers != nil { in, out := &in.DiscoveryTokenAPIServers, &out.DiscoveryTokenAPIServers *out = make([]string, len(*in)) copy(*out, *in) } + if in.DiscoveryTimeout != nil { + in, out := &in.DiscoveryTimeout, &out.DiscoveryTimeout + if *in == nil { + *out = nil + } else { + *out = new(v1.Duration) + **out = **in + } + } if in.DiscoveryTokenCACertHashes != nil { in, out := &in.DiscoveryTokenCACertHashes, &out.DiscoveryTokenCACertHashes *out = make([]string, len(*in)) @@ -343,33 +447,31 @@ func (in *NodeConfiguration) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SelfHostedEtcd) DeepCopyInto(out *SelfHostedEtcd) { +func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) { *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SelfHostedEtcd. -func (in *SelfHostedEtcd) DeepCopy() *SelfHostedEtcd { - if in == nil { - return nil + if in.Taints != nil { + in, out := &in.Taints, &out.Taints + *out = make([]core_v1.Taint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KubeletExtraArgs != nil { + in, out := &in.KubeletExtraArgs, &out.KubeletExtraArgs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } } - out := new(SelfHostedEtcd) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TokenDiscovery) DeepCopyInto(out *TokenDiscovery) { - *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenDiscovery. -func (in *TokenDiscovery) DeepCopy() *TokenDiscovery { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRegistrationOptions. +func (in *NodeRegistrationOptions) DeepCopy() *NodeRegistrationOptions { if in == nil { return nil } - out := new(TokenDiscovery) + out := new(NodeRegistrationOptions) in.DeepCopyInto(out) return out } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD index 7c9174a09..171dc94d4 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD @@ -21,9 +21,11 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/install:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", + "//cmd/kubeadm/app/cmd/options:go_default_library", "//cmd/kubeadm/app/cmd/phases:go_default_library", "//cmd/kubeadm/app/cmd/upgrade:go_default_library", "//cmd/kubeadm/app/cmd/util:go_default_library", @@ -41,6 +43,7 @@ go_library( "//cmd/kubeadm/app/phases/kubeconfig:go_default_library", "//cmd/kubeadm/app/phases/kubelet:go_default_library", "//cmd/kubeadm/app/phases/markmaster:go_default_library", + "//cmd/kubeadm/app/phases/patchnode:go_default_library", "//cmd/kubeadm/app/phases/selfhosting:go_default_library", "//cmd/kubeadm/app/phases/uploadconfig:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", @@ -50,28 +53,24 @@ go_library( "//cmd/kubeadm/app/util/config:go_default_library", "//cmd/kubeadm/app/util/dryrun:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", - "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", "//pkg/util/initsystem:go_default_library", - "//pkg/util/node:go_default_library", "//pkg/version:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/renstrom/dedent:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/duration:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], @@ -80,20 +79,30 @@ go_library( go_test( name = "go_default_test", srcs = [ + "completion_test.go", + "join_test.go", "reset_test.go", "token_test.go", + "version_test.go", ], embed = [":go_default_library"], deps = [ - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", + "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", "//vendor/k8s.io/utils/exec/testing:go_default_library", ], @@ -110,9 +119,22 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//cmd/kubeadm/app/cmd/options:all-srcs", "//cmd/kubeadm/app/cmd/phases:all-srcs", "//cmd/kubeadm/app/cmd/upgrade:all-srcs", "//cmd/kubeadm/app/cmd/util:all-srcs", ], tags = ["automanaged"], ) + +go_test( + name = "go_default_xtest", + srcs = ["config_test.go"], + deps = [ + ":go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", + "//cmd/kubeadm/app/features:go_default_library", + "//cmd/kubeadm/app/util/config:go_default_library", + "//vendor/github.com/renstrom/dedent:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/cmd.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/cmd.go index a3124b31b..d968e5373 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/cmd.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/cmd.go @@ -22,17 +22,14 @@ import ( "github.com/renstrom/dedent" "github.com/spf13/cobra" - "k8s.io/apiserver/pkg/util/flag" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade" - // Register the kubeadm configuration types because CLI flag generation // depends on the generated defaults. - _ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install" ) // NewKubeadmCommand return cobra.Command to run kubeadm command -func NewKubeadmCommand(_ io.Reader, out, err io.Writer) *cobra.Command { +func NewKubeadmCommand(in io.Reader, out, err io.Writer) *cobra.Command { cmds := &cobra.Command{ Use: "kubeadm", Short: "kubeadm: easily bootstrap a secure Kubernetes cluster", @@ -71,13 +68,12 @@ func NewKubeadmCommand(_ io.Reader, out, err io.Writer) *cobra.Command { } cmds.ResetFlags() - cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc) cmds.AddCommand(NewCmdCompletion(out, "")) cmds.AddCommand(NewCmdConfig(out)) cmds.AddCommand(NewCmdInit(out)) cmds.AddCommand(NewCmdJoin(out)) - cmds.AddCommand(NewCmdReset(out)) + cmds.AddCommand(NewCmdReset(in, out)) cmds.AddCommand(NewCmdVersion(out)) cmds.AddCommand(NewCmdToken(out, err)) cmds.AddCommand(upgrade.NewCmdUpgrade(out)) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/completion.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/completion.go index eb8a358a5..9e7722b7f 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/completion.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/completion.go @@ -21,6 +21,7 @@ import ( "fmt" "io" + "github.com/golang/glog" "github.com/renstrom/dedent" "github.com/spf13/cobra" @@ -50,17 +51,18 @@ var ( The shell code must be evaluated to provide interactive completion of kubeadm commands. This can be done by sourcing it from the .bash_profile. + + Note: this requires the bash-completion framework. - Note: this requires the bash-completion framework, which is not installed - by default on Mac. This can be installed by using homebrew: - + To install it on Mac use homebrew: $ brew install bash-completion - Once installed, bash_completion must be evaluated. This can be done by adding the following line to the .bash_profile - $ source $(brew --prefix)/etc/bash_completion + If bash-completion is not installed on Linux, please install the 'bash-completion' package + via your distribution's package manager. + Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2`) completionExample = dedent.Dedent(` @@ -88,13 +90,17 @@ var ( } ) -// NewCmdCompletion return command for executing "kubeadm completion" command -func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command { +// GetSupportedShells returns a list of supported shells +func GetSupportedShells() []string { shells := []string{} for s := range completionShells { shells = append(shells, s) } + return shells +} +// NewCmdCompletion returns the "kubeadm completion" command +func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command { cmd := &cobra.Command{ Use: "completion SHELL", Short: i18n.T("Output shell completion code for the specified shell (bash or zsh)."), @@ -104,7 +110,7 @@ func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command { err := RunCompletion(out, boilerPlate, cmd, args) kubeadmutil.CheckErr(err) }, - ValidArgs: shells, + ValidArgs: GetSupportedShells(), } return cmd @@ -133,6 +139,7 @@ func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args [ } func runCompletionBash(out io.Writer, kubeadm *cobra.Command) error { + glog.V(1).Infoln("[completion] writing completion code for Bash") return kubeadm.GenBashCompletion(out) } @@ -278,10 +285,12 @@ __kubeadm_convert_bash_to_zsh() { -e "s/\\\$(type${RWORD}/\$(__kubeadm_type/g" \ <<'BASH_COMPLETION_EOF' ` + glog.V(1).Infoln("[completion] writing completion code for Zsh") out.Write([]byte(zshInitialization)) buf := new(bytes.Buffer) kubeadm.GenBashCompletion(buf) + glog.V(1).Infoln("[completion] writing completion code for Bash") out.Write(buf.Bytes()) zshTail := ` diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/completion_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/completion_test.go new file mode 100644 index 000000000..e13eed481 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/completion_test.go @@ -0,0 +1,95 @@ +/* +Copyright 2018 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 cmd + +import ( + "bytes" + "testing" + + "github.com/spf13/cobra" +) + +const shellsError = "Unexpected empty completion shells list" + +func TestNewCmdCompletion(t *testing.T) { + var out bytes.Buffer + shells := GetSupportedShells() + if len(shells) == 0 { + t.Errorf(shellsError) + } + // test NewCmdCompletion with a valid shell. + // use a dummy parent command as NewCmdCompletion needs it. + parentCmd := &cobra.Command{} + args := []string{"completion", shells[0]} + parentCmd.SetArgs(args) + cmd := NewCmdCompletion(&out, "") + parentCmd.AddCommand(cmd) + if err := parentCmd.Execute(); err != nil { + t.Errorf("Cannot exectute NewCmdCompletion: %v", err) + } +} + +func TestRunCompletion(t *testing.T) { + var out bytes.Buffer + type TestCase struct { + name string + args []string + expectedError bool + } + + testCases := []TestCase{ + { + name: "invalid: missing argument", + args: []string{}, + expectedError: true, + }, + { + name: "invalid: too many arguments", + args: []string{"", ""}, + expectedError: true, + }, + { + name: "invalid: unsupported shell name", + args: []string{"unsupported"}, + expectedError: true, + }, + } + + // test all supported shells + shells := GetSupportedShells() + if len(shells) == 0 { + t.Errorf(shellsError) + } + for _, shell := range shells { + test := TestCase{ + name: "valid: test shell " + shell, + args: []string{shell}, + } + testCases = append(testCases, test) + } + + // use dummy cobra commands + parentCmd := &cobra.Command{} + cmd := &cobra.Command{} + parentCmd.AddCommand(cmd) + + for _, tc := range testCases { + if err := RunCompletion(&out, "", cmd, tc.args); (err != nil) != tc.expectedError { + t.Errorf("Test case %q: TestRunCompletion expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) + } + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/config.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/config.go index 00684a884..91cb09632 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/config.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/config.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 2018 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. @@ -19,21 +19,46 @@ package cmd import ( "fmt" "io" + "io/ioutil" + "strings" + "github.com/golang/glog" "github.com/renstrom/dedent" "github.com/spf13/cobra" + flag "github.com/spf13/pflag" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" + "k8s.io/kubernetes/cmd/kubeadm/app/images" "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - "k8s.io/kubernetes/pkg/api/legacyscheme" + utilsexec "k8s.io/utils/exec" +) + +const ( + // TODO: Figure out how to get these constants from the API machinery + masterConfig = "MasterConfiguration" + nodeConfig = "NodeConfiguration" +) + +var ( + availableAPIObjects = []string{masterConfig, nodeConfig} + // sillyToken is only set statically to make kubeadm not randomize the token on every run + sillyToken = kubeadmapiv1alpha2.BootstrapToken{ + Token: &kubeadmapiv1alpha2.BootstrapTokenString{ + ID: "abcdef", + Secret: "0123456789abcdef", + }, + } ) // NewCmdConfig returns cobra.Command for "kubeadm config" command @@ -59,9 +84,134 @@ func NewCmdConfig(out io.Writer) *cobra.Command { cmd.PersistentFlags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster.") + cmd.AddCommand(NewCmdConfigPrintDefault(out)) + cmd.AddCommand(NewCmdConfigMigrate(out)) cmd.AddCommand(NewCmdConfigUpload(out, &kubeConfigFile)) cmd.AddCommand(NewCmdConfigView(out, &kubeConfigFile)) + cmd.AddCommand(NewCmdConfigImages(out)) + return cmd +} + +// NewCmdConfigPrintDefault returns cobra.Command for "kubeadm config print-default" command +func NewCmdConfigPrintDefault(out io.Writer) *cobra.Command { + apiObjects := []string{} + cmd := &cobra.Command{ + Use: "print-default", + Aliases: []string{"print-defaults"}, + Short: "Print the default values for a kubeadm configuration object.", + Long: fmt.Sprintf(dedent.Dedent(` + This command prints the default MasterConfiguration object that is used for 'kubeadm init' and 'kubeadm upgrade', + and the default NodeConfiguration object that is used for 'kubeadm join'. + + Note that sensitive values like the Bootstrap Token fields are replaced with silly values like %q in order to pass validation but + not perform the real computation for creating a token. + `), sillyToken), + Run: func(cmd *cobra.Command, args []string) { + if len(apiObjects) == 0 { + apiObjects = availableAPIObjects + } + for i, apiObject := range apiObjects { + if i > 0 { + fmt.Fprintln(out, "---") + } + + cfgBytes, err := getDefaultAPIObjectBytes(apiObject) + kubeadmutil.CheckErr(err) + // Print the API object byte array + fmt.Fprintf(out, "%s", cfgBytes) + } + }, + } + cmd.Flags().StringSliceVar(&apiObjects, "api-objects", apiObjects, + fmt.Sprintf("A comma-separated list for API objects to print the default values for. Available values: %v. This flag unset means 'print all known objects'", availableAPIObjects)) + return cmd +} + +func getDefaultAPIObjectBytes(apiObject string) ([]byte, error) { + if apiObject == masterConfig { + + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1alpha2.MasterConfiguration{ + BootstrapTokens: []kubeadmapiv1alpha2.BootstrapToken{sillyToken}, + }) + kubeadmutil.CheckErr(err) + + return kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs) + } + if apiObject == nodeConfig { + internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1alpha2.NodeConfiguration{ + Token: sillyToken.Token.String(), + DiscoveryTokenAPIServers: []string{"kube-apiserver:6443"}, + DiscoveryTokenUnsafeSkipCAVerification: true, + }) + kubeadmutil.CheckErr(err) + + return kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs) + } + return []byte{}, fmt.Errorf("--api-object needs to be one of %v", availableAPIObjects) +} + +// NewCmdConfigMigrate returns cobra.Command for "kubeadm config migrate" command +func NewCmdConfigMigrate(out io.Writer) *cobra.Command { + var oldCfgPath, newCfgPath string + cmd := &cobra.Command{ + Use: "migrate", + Short: "Read an older version of the kubeadm configuration API types from a file, and output the similar config object for the newer version.", + Long: fmt.Sprintf(dedent.Dedent(` + This command lets you convert configuration objects of older versions to the latest supported version, + locally in the CLI tool without ever touching anything in the cluster. + In this version of kubeadm, the following API versions are supported: + - %s + - %s + + Further, kubeadm can only write out config of version %q, but read both types. + So regardless of what version you pass to the --old-config parameter here, the API object will be + read, deserialized, defaulted, converted, validated, and re-serialized when written to stdout or + --new-config if specified. + + In other words, the output of this command is what kubeadm actually would read internally if you + submitted this file to "kubeadm init" + `), kubeadmapiv1alpha2.SchemeGroupVersion.String(), kubeadmapiv1alpha1.SchemeGroupVersion.String(), kubeadmapiv1alpha2.SchemeGroupVersion.String()), + Run: func(cmd *cobra.Command, args []string) { + if len(oldCfgPath) == 0 { + kubeadmutil.CheckErr(fmt.Errorf("The --old-config flag is mandatory")) + } + + b, err := ioutil.ReadFile(oldCfgPath) + kubeadmutil.CheckErr(err) + + var outputBytes []byte + gvk, err := kubeadmutil.GroupVersionKindFromBytes(b, kubeadmscheme.Codecs) + kubeadmutil.CheckErr(err) + + switch gvk.Kind { + case masterConfig: + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(oldCfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + kubeadmutil.CheckErr(err) + outputBytes, err = kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs) + kubeadmutil.CheckErr(err) + case nodeConfig: + internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig(oldCfgPath, &kubeadmapiv1alpha2.NodeConfiguration{}) + kubeadmutil.CheckErr(err) + + // TODO: In the future we might not want to duplicate these two lines of code for every case here. + outputBytes, err = kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs) + kubeadmutil.CheckErr(err) + default: + kubeadmutil.CheckErr(fmt.Errorf("Didn't recognize type with GroupVersionKind: %v", gvk)) + } + + if newCfgPath == "" { + fmt.Fprint(out, string(outputBytes)) + } else { + if err := ioutil.WriteFile(newCfgPath, outputBytes, 0644); err != nil { + kubeadmutil.CheckErr(fmt.Errorf("failed to write the new configuration to the file %q: %v", newCfgPath, err)) + } + } + }, + } + cmd.Flags().StringVar(&oldCfgPath, "old-config", "", "Path to the kubeadm config file that is using an old API version and should be converted. This flag is mandatory.") + cmd.Flags().StringVar(&newCfgPath, "new-config", "", "Path to the resulting equivalent kubeadm config file using the new API version. Optional, if not specified output will be sent to STDOUT.") return cmd } @@ -89,6 +239,7 @@ func NewCmdConfigView(out io.Writer, kubeConfigFile *string) *cobra.Command { The configuration is located in the %q namespace in the %q ConfigMap. `), metav1.NamespaceSystem, constants.MasterConfigurationConfigMap), Run: func(cmd *cobra.Command, args []string) { + glog.V(1).Infoln("[config] retrieving ClientSet from file") client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) kubeadmutil.CheckErr(err) @@ -117,12 +268,15 @@ func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Co kubeadmutil.CheckErr(fmt.Errorf("The --config flag is mandatory")) } + glog.V(1).Infoln("[config] retrieving ClientSet from file") client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) kubeadmutil.CheckErr(err) // The default configuration is empty; everything should come from the file on disk - defaultcfg := &kubeadmapiext.MasterConfiguration{} + glog.V(1).Infoln("[config] creating empty default configuration") + defaultcfg := &kubeadmapiv1alpha2.MasterConfiguration{} // Upload the configuration using the file; don't care about the defaultcfg really + glog.V(1).Infof("[config] uploading configuration") err = uploadConfiguration(client, cfgPath, defaultcfg) kubeadmutil.CheckErr(err) }, @@ -133,8 +287,8 @@ func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Co // NewCmdConfigUploadFromFlags returns cobra.Command for "kubeadm config upload from-flags" command func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{} - legacyscheme.Scheme.Default(cfg) + cfg := &kubeadmapiv1alpha2.MasterConfiguration{} + kubeadmscheme.Scheme.Default(cfg) var featureGatesString string @@ -150,15 +304,17 @@ func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.C `), metav1.NamespaceSystem, constants.MasterConfigurationConfigMap), Run: func(cmd *cobra.Command, args []string) { var err error + glog.V(1).Infoln("[config] creating new FeatureGates") if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil { kubeadmutil.CheckErr(err) } - + glog.V(1).Infoln("[config] retrieving ClientSet from file") client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) kubeadmutil.CheckErr(err) // Default both statically and dynamically, convert to internal API type, and validate everything // The cfgPath argument is unset here as we shouldn't load a config file from disk, just go with cfg + glog.V(1).Infof("[config] uploading configuration") err = uploadConfiguration(client, "", cfg) kubeadmutil.CheckErr(err) }, @@ -170,6 +326,7 @@ func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.C // RunConfigView gets the configuration persisted in the cluster func RunConfigView(out io.Writer, client clientset.Interface) error { + glog.V(1).Infoln("[config] getting the cluster configuration") cfgConfigMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(constants.MasterConfigurationConfigMap, metav1.GetOptions{}) if err != nil { return err @@ -180,10 +337,11 @@ func RunConfigView(out io.Writer, client clientset.Interface) error { } // uploadConfiguration handles the uploading of the configuration internally -func uploadConfiguration(client clientset.Interface, cfgPath string, defaultcfg *kubeadmapiext.MasterConfiguration) error { +func uploadConfiguration(client clientset.Interface, cfgPath string, defaultcfg *kubeadmapiv1alpha2.MasterConfiguration) error { // Default both statically and dynamically, convert to internal API type, and validate everything // First argument is unset here as we shouldn't load a config file from disk + glog.V(1).Infoln("[config] converting to internal API type") internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg) if err != nil { return err @@ -192,3 +350,139 @@ func uploadConfiguration(client clientset.Interface, cfgPath string, defaultcfg // Then just call the uploadconfig phase to do the rest of the work return uploadconfig.UploadConfiguration(internalcfg, client) } + +// NewCmdConfigImages returns the "kubeadm config images" command +func NewCmdConfigImages(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "images", + Short: "Interact with container images used by kubeadm.", + RunE: cmdutil.SubCmdRunE("images"), + } + cmd.AddCommand(NewCmdConfigImagesList(out, nil)) + cmd.AddCommand(NewCmdConfigImagesPull()) + return cmd +} + +// NewCmdConfigImagesPull returns the `kubeadm config images pull` command +func NewCmdConfigImagesPull() *cobra.Command { + cfg := &kubeadmapiv1alpha2.MasterConfiguration{} + kubeadmscheme.Scheme.Default(cfg) + var cfgPath, featureGatesString string + var err error + + cmd := &cobra.Command{ + Use: "pull", + Short: "Pull images used by kubeadm.", + Run: func(_ *cobra.Command, _ []string) { + cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString) + kubeadmutil.CheckErr(err) + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg) + kubeadmutil.CheckErr(err) + puller, err := images.NewCRInterfacer(utilsexec.New(), internalcfg.GetCRISocket()) + kubeadmutil.CheckErr(err) + imagesPull := NewImagesPull(puller, images.GetAllImages(internalcfg)) + kubeadmutil.CheckErr(imagesPull.PullAll()) + }, + } + AddImagesCommonConfigFlags(cmd.PersistentFlags(), cfg, &cfgPath, &featureGatesString) + AddImagesPullFlags(cmd.PersistentFlags(), cfg) + + return cmd +} + +// ImagesPull is the struct used to hold information relating to image pulling +type ImagesPull struct { + puller images.Puller + images []string +} + +// NewImagesPull initializes and returns the `kubeadm config images pull` command +func NewImagesPull(puller images.Puller, images []string) *ImagesPull { + return &ImagesPull{ + puller: puller, + images: images, + } +} + +// PullAll pulls all images that the ImagesPull knows about +func (ip *ImagesPull) PullAll() error { + for _, image := range ip.images { + if err := ip.puller.Pull(image); err != nil { + return fmt.Errorf("failed to pull image %q: %v", image, err) + } + fmt.Printf("[config/images] Pulled %s\n", image) + } + return nil +} + +// NewCmdConfigImagesList returns the "kubeadm config images list" command +func NewCmdConfigImagesList(out io.Writer, mockK8sVersion *string) *cobra.Command { + cfg := &kubeadmapiv1alpha2.MasterConfiguration{} + kubeadmscheme.Scheme.Default(cfg) + var cfgPath, featureGatesString string + var err error + + // This just sets the kubernetes version for unit testing so kubeadm won't try to + // lookup the latest release from the internet. + if mockK8sVersion != nil { + cfg.KubernetesVersion = *mockK8sVersion + } + + cmd := &cobra.Command{ + Use: "list", + Short: "Print a list of images kubeadm will use. The configuration file is used in case any images or image repositories are customized.", + Run: func(_ *cobra.Command, _ []string) { + cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString) + kubeadmutil.CheckErr(err) + imagesList, err := NewImagesList(cfgPath, cfg) + kubeadmutil.CheckErr(err) + kubeadmutil.CheckErr(imagesList.Run(out)) + }, + } + AddImagesCommonConfigFlags(cmd.PersistentFlags(), cfg, &cfgPath, &featureGatesString) + + return cmd +} + +// NewImagesList returns the underlying struct for the "kubeadm config images list" command +func NewImagesList(cfgPath string, cfg *kubeadmapiv1alpha2.MasterConfiguration) (*ImagesList, error) { + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg) + if err != nil { + return nil, fmt.Errorf("could not convert cfg to an internal cfg: %v", err) + } + + return &ImagesList{ + cfg: internalcfg, + }, nil +} + +// ImagesList defines the struct used for "kubeadm config images list" +type ImagesList struct { + cfg *kubeadmapi.MasterConfiguration +} + +// Run runs the images command and writes the result to the io.Writer passed in +func (i *ImagesList) Run(out io.Writer) error { + imgs := images.GetAllImages(i.cfg) + for _, img := range imgs { + fmt.Fprintln(out, img) + } + + return nil +} + +// AddImagesCommonConfigFlags adds the flags that configure kubeadm (and affect the images kubeadm will use) +func AddImagesCommonConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.MasterConfiguration, cfgPath *string, featureGatesString *string) { + flagSet.StringVar( + &cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion, + `Choose a specific Kubernetes version for the control plane.`, + ) + flagSet.StringVar(featureGatesString, "feature-gates", *featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+ + "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) + flagSet.StringVar(cfgPath, "config", *cfgPath, "Path to kubeadm config file.") +} + +// AddImagesPullFlags adds flags related to the `kubeadm config images pull` command +func AddImagesPullFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.MasterConfiguration) { + flagSet.StringVar(&cfg.NodeRegistration.CRISocket, "cri-socket-path", cfg.NodeRegistration.CRISocket, "Path to the CRI socket.") +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/config_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/config_test.go new file mode 100644 index 000000000..18db0ec99 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/config_test.go @@ -0,0 +1,246 @@ +/* +Copyright 2018 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 cmd_test + +import ( + "bytes" + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/renstrom/dedent" + + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd" + "k8s.io/kubernetes/cmd/kubeadm/app/features" + "k8s.io/kubernetes/cmd/kubeadm/app/util/config" +) + +const ( + defaultNumberOfImages = 8 + // dummyKubernetesVersion is just used for unit testing, in order to not make + // kubeadm lookup dl.k8s.io to resolve what the latest stable release is + dummyKubernetesVersion = "v1.10.0" +) + +func TestNewCmdConfigImagesList(t *testing.T) { + var output bytes.Buffer + mockK8sVersion := dummyKubernetesVersion + images := cmd.NewCmdConfigImagesList(&output, &mockK8sVersion) + images.Run(nil, nil) + actual := strings.Split(output.String(), "\n") + if len(actual) != defaultNumberOfImages { + t.Fatalf("Expected %v but found %v images", defaultNumberOfImages, len(actual)) + } +} + +func TestImagesListRunWithCustomConfigPath(t *testing.T) { + testcases := []struct { + name string + expectedImageCount int + // each string provided here must appear in at least one image returned by Run + expectedImageSubstrings []string + configContents []byte + }{ + { + name: "set k8s version", + expectedImageCount: defaultNumberOfImages, + expectedImageSubstrings: []string{ + ":v1.10.1", + }, + configContents: []byte(dedent.Dedent(` + apiVersion: kubeadm.k8s.io/v1alpha2 + kind: MasterConfiguration + kubernetesVersion: v1.10.1 + `)), + }, + { + name: "use coredns", + expectedImageCount: defaultNumberOfImages, + expectedImageSubstrings: []string{ + "coredns", + }, + configContents: []byte(dedent.Dedent(` + apiVersion: kubeadm.k8s.io/v1alpha2 + kind: MasterConfiguration + kubernetesVersion: v1.11.0 + featureGates: + CoreDNS: True + `)), + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + tmpDir, err := ioutil.TempDir("", "kubeadm-images-test") + if err != nil { + t.Fatalf("Unable to create temporary directory: %v", err) + } + defer os.RemoveAll(tmpDir) + + configFilePath := filepath.Join(tmpDir, "test-config-file") + err = ioutil.WriteFile(configFilePath, tc.configContents, 0644) + if err != nil { + t.Fatalf("Failed writing a config file: %v", err) + } + + i, err := cmd.NewImagesList(configFilePath, &kubeadmapiv1alpha2.MasterConfiguration{ + KubernetesVersion: dummyKubernetesVersion, + }) + if err != nil { + t.Fatalf("Failed getting the kubeadm images command: %v", err) + } + var output bytes.Buffer + if i.Run(&output) != nil { + t.Fatalf("Error from running the images command: %v", err) + } + actual := strings.Split(output.String(), "\n") + if len(actual) != tc.expectedImageCount { + t.Fatalf("did not get the same number of images: actual: %v expected: %v. Actual value: %v", len(actual), tc.expectedImageCount, actual) + } + + for _, substring := range tc.expectedImageSubstrings { + if !strings.Contains(output.String(), substring) { + t.Errorf("Expected to find %v but did not in this list of images: %v", substring, actual) + } + } + }) + } +} + +func TestConfigImagesListRunWithoutPath(t *testing.T) { + testcases := []struct { + name string + cfg kubeadmapiv1alpha2.MasterConfiguration + expectedImages int + }{ + { + name: "empty config", + expectedImages: defaultNumberOfImages, + cfg: kubeadmapiv1alpha2.MasterConfiguration{ + KubernetesVersion: dummyKubernetesVersion, + }, + }, + { + name: "external etcd configuration", + cfg: kubeadmapiv1alpha2.MasterConfiguration{ + Etcd: kubeadmapiv1alpha2.Etcd{ + External: &kubeadmapiv1alpha2.ExternalEtcd{ + Endpoints: []string{"https://some.etcd.com:2379"}, + }, + }, + KubernetesVersion: dummyKubernetesVersion, + }, + expectedImages: defaultNumberOfImages - 1, + }, + { + name: "coredns enabled", + cfg: kubeadmapiv1alpha2.MasterConfiguration{ + FeatureGates: map[string]bool{ + features.CoreDNS: true, + }, + KubernetesVersion: dummyKubernetesVersion, + }, + expectedImages: defaultNumberOfImages, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + i, err := cmd.NewImagesList("", &tc.cfg) + if err != nil { + t.Fatalf("did not expect an error while creating the Images command: %v", err) + } + + var output bytes.Buffer + if i.Run(&output) != nil { + t.Fatalf("did not expect an error running the Images command: %v", err) + } + + actual := strings.Split(output.String(), "\n") + if len(actual) != tc.expectedImages { + t.Fatalf("expected %v images but got %v", tc.expectedImages, actual) + } + }) + } +} + +type fakePuller struct { + count map[string]int +} + +func (f *fakePuller) Pull(image string) error { + f.count[image]++ + return nil +} + +func TestImagesPull(t *testing.T) { + puller := &fakePuller{ + count: make(map[string]int), + } + images := []string{"a", "b", "c", "d", "a"} + ip := cmd.NewImagesPull(puller, images) + err := ip.PullAll() + if err != nil { + t.Fatalf("expected nil but found %v", err) + } + if puller.count["a"] != 2 { + t.Fatalf("expected 2 but found %v", puller.count["a"]) + } +} + +func TestMigrate(t *testing.T) { + cfg := []byte(dedent.Dedent(` + apiVersion: kubeadm.k8s.io/v1alpha2 + kind: MasterConfiguration + kubernetesVersion: v1.10.0 + `)) + configFile, cleanup := tempConfig(t, cfg) + defer cleanup() + + var output bytes.Buffer + command := cmd.NewCmdConfigMigrate(&output) + err := command.Flags().Set("old-config", configFile) + if err != nil { + t.Fatalf("failed to set old-config flag") + } + command.Run(nil, nil) + _, err = config.BytesToInternalConfig(output.Bytes()) + if err != nil { + t.Fatalf("Could not read output back into internal type: %v", err) + } +} + +// Returns the name of the file created and a cleanup callback +func tempConfig(t *testing.T, config []byte) (string, func()) { + t.Helper() + tmpDir, err := ioutil.TempDir("", "kubeadm-migration-test") + if err != nil { + t.Fatalf("Unable to create temporary directory: %v", err) + } + configFilePath := filepath.Join(tmpDir, "test-config-file") + err = ioutil.WriteFile(configFilePath, config, 0644) + if err != nil { + os.RemoveAll(tmpDir) + t.Fatalf("Failed writing a config file: %v", err) + } + return configFilePath, func() { + os.RemoveAll(tmpDir) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go index b5ce3d86f..5467b5995 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go @@ -26,17 +26,18 @@ import ( "text/template" "time" + "github.com/golang/glog" "github.com/renstrom/dedent" "github.com/spf13/cobra" flag "github.com/spf13/pflag" - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" clientset "k8s.io/client-go/kubernetes" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" @@ -51,6 +52,7 @@ import ( kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster" + patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" selfhostingphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting" uploadconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" @@ -60,7 +62,6 @@ import ( configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - "k8s.io/kubernetes/pkg/api/legacyscheme" utilsexec "k8s.io/utils/exec" ) @@ -92,23 +93,31 @@ var ( This error is likely caused by: - The kubelet is not running - The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled) - - Either there is no internet connection, or imagePullPolicy is set to "Never", - so the kubelet cannot pull or find the following control plane images: + - No internet connection is available so the kubelet cannot pull or find the following control plane images: - {{ .APIServerImage }} - {{ .ControllerManagerImage }} - {{ .SchedulerImage }} - - {{ .EtcdImage }} (only if no external etcd endpoints are configured) +{{ .EtcdImage }} + - You can check or miligate this in beforehand with "kubeadm config images pull" to make sure the images + are downloaded locally and cached. If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands: - 'systemctl status kubelet' - 'journalctl -xeu kubelet' + + Additionally, a control plane component may have crashed or exited when started by the container runtime. + To troubleshoot, list all containers using your preferred container runtimes CLI, e.g. docker. + Here is one example how you may list all Kubernetes containers running in docker: + - 'docker ps -a | grep kube | grep -v pause' + Once you have found the failing container, you can inspect its logs with: + - 'docker logs CONTAINERID' `))) ) // NewCmdInit returns "kubeadm init" command. func NewCmdInit(out io.Writer) *cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{} - legacyscheme.Scheme.Default(cfg) + externalcfg := &kubeadmapiv1alpha2.MasterConfiguration{} + kubeadmscheme.Scheme.Default(externalcfg) var cfgPath string var skipPreFlight bool @@ -116,38 +125,47 @@ func NewCmdInit(out io.Writer) *cobra.Command { var dryRun bool var featureGatesString string var ignorePreflightErrors []string + // Create the options object for the bootstrap token-related flags, and override the default value for .Description + bto := options.NewBootstrapTokenOptions() + bto.Description = "The default bootstrap token generated by 'kubeadm init'." cmd := &cobra.Command{ Use: "init", Short: "Run this command in order to set up the Kubernetes master.", Run: func(cmd *cobra.Command, args []string) { + + kubeadmscheme.Scheme.Default(externalcfg) + var err error - if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil { + if externalcfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil { kubeadmutil.CheckErr(err) } - legacyscheme.Scheme.Default(cfg) - internalcfg := &kubeadmapi.MasterConfiguration{} - legacyscheme.Scheme.Convert(cfg, internalcfg, nil) - ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight) kubeadmutil.CheckErr(err) - i, err := NewInit(cfgPath, internalcfg, ignorePreflightErrorsSet, skipTokenPrint, dryRun) + err = validation.ValidateMixedArguments(cmd.Flags()) + kubeadmutil.CheckErr(err) + + err = bto.ApplyTo(externalcfg) + kubeadmutil.CheckErr(err) + + i, err := NewInit(cfgPath, externalcfg, ignorePreflightErrorsSet, skipTokenPrint, dryRun) kubeadmutil.CheckErr(err) - kubeadmutil.CheckErr(i.Validate(cmd)) kubeadmutil.CheckErr(i.Run(out)) }, } - AddInitConfigFlags(cmd.PersistentFlags(), cfg, &featureGatesString) + AddInitConfigFlags(cmd.PersistentFlags(), externalcfg, &featureGatesString) AddInitOtherFlags(cmd.PersistentFlags(), &cfgPath, &skipPreFlight, &skipTokenPrint, &dryRun, &ignorePreflightErrors) + bto.AddTokenFlag(cmd.PersistentFlags()) + bto.AddTTLFlag(cmd.PersistentFlags()) return cmd } // AddInitConfigFlags adds init flags bound to the config to the specified flagset -func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiext.MasterConfiguration, featureGatesString *string) { +func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.MasterConfiguration, featureGatesString *string) { flagSet.StringVar( &cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address the API Server will advertise it's listening on. Specify '0.0.0.0' to use the address of the default network interface.", @@ -181,24 +199,15 @@ func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiext.MasterConfigur `Optional extra Subject Alternative Names (SANs) to use for the API Server serving certificate. Can be both IP addresses and DNS names.`, ) flagSet.StringVar( - &cfg.NodeName, "node-name", cfg.NodeName, + &cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, `Specify the node name.`, ) flagSet.StringVar( - &cfg.Token, "token", cfg.Token, - "The token to use for establishing bidirectional trust between nodes and masters.", - ) - flagSet.DurationVar( - &cfg.TokenTTL.Duration, "token-ttl", cfg.TokenTTL.Duration, - "The duration before the bootstrap token is automatically deleted. If set to '0', the token will never expire.", - ) - flagSet.StringVar( - &cfg.CRISocket, "cri-socket", cfg.CRISocket, + &cfg.NodeRegistration.CRISocket, "cri-socket", cfg.NodeRegistration.CRISocket, `Specify the CRI socket to connect to.`, ) flagSet.StringVar(featureGatesString, "feature-gates", *featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+ "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) - } // AddInitOtherFlags adds init flags that are not bound to a configuration file to the given flagset @@ -230,72 +239,85 @@ func AddInitOtherFlags(flagSet *flag.FlagSet, cfgPath *string, skipPreFlight, sk } // NewInit validates given arguments and instantiates Init struct with provided information. -func NewInit(cfgPath string, cfg *kubeadmapi.MasterConfiguration, ignorePreflightErrors sets.String, skipTokenPrint, dryRun bool) (*Init, error) { - - if cfgPath != "" { - b, err := ioutil.ReadFile(cfgPath) - if err != nil { - return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err) - } - if err := runtime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), b, cfg); err != nil { - return nil, fmt.Errorf("unable to decode config from %q [%v]", cfgPath, err) - } - } +func NewInit(cfgPath string, externalcfg *kubeadmapiv1alpha2.MasterConfiguration, ignorePreflightErrors sets.String, skipTokenPrint, dryRun bool) (*Init, error) { - // Set defaults dynamically that the API group defaulting can't (by fetching information from the internet, looking up network interfaces, etc.) - err := configutil.SetInitDynamicDefaults(cfg) + // Either use the config file if specified, or convert the defaults in the external to an internal cfg representation + cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, externalcfg) if err != nil { return nil, err } + glog.V(1).Infof("[init] validating feature gates") if err := features.ValidateVersion(features.InitFeatureGates, cfg.FeatureGates, cfg.KubernetesVersion); err != nil { return nil, err } - fmt.Printf("[init] Using Kubernetes version: %s\n", cfg.KubernetesVersion) - fmt.Printf("[init] Using Authorization modes: %v\n", cfg.AuthorizationModes) + fmt.Printf("[init] using Kubernetes version: %s\n", cfg.KubernetesVersion) - // Warn about the limitations with the current cloudprovider solution. - if cfg.CloudProvider != "" { - fmt.Println("[init] WARNING: For cloudprovider integrations to work --cloud-provider must be set for all kubelets in the cluster.") - fmt.Println("\t(/etc/systemd/system/kubelet.service.d/10-kubeadm.conf should be edited for this purpose)") - } - - fmt.Println("[preflight] Running pre-flight checks.") + fmt.Println("[preflight] running pre-flight checks") if err := preflight.RunInitMasterChecks(utilsexec.New(), cfg, ignorePreflightErrors); err != nil { return nil, err } - // Try to start the kubelet service in case it's inactive - preflight.TryStartKubelet(ignorePreflightErrors) + if !dryRun { + fmt.Println("[preflight/images] Pulling images required for setting up a Kubernetes cluster") + fmt.Println("[preflight/images] This might take a minute or two, depending on the speed of your internet connection") + fmt.Println("[preflight/images] You can also perform this action in beforehand using 'kubeadm config images pull'") + if err := preflight.RunPullImagesCheck(utilsexec.New(), cfg, ignorePreflightErrors); err != nil { + return nil, err + } + } else { + fmt.Println("[preflight/images] Would pull the required images (like 'kubeadm config images pull')") + } - return &Init{cfg: cfg, skipTokenPrint: skipTokenPrint, dryRun: dryRun}, nil + return &Init{cfg: cfg, skipTokenPrint: skipTokenPrint, dryRun: dryRun, ignorePreflightErrors: ignorePreflightErrors}, nil } // Init defines struct used by "kubeadm init" command type Init struct { - cfg *kubeadmapi.MasterConfiguration - skipTokenPrint bool - dryRun bool -} - -// Validate validates configuration passed to "kubeadm init" -func (i *Init) Validate(cmd *cobra.Command) error { - if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil { - return err - } - return validation.ValidateMasterConfiguration(i.cfg).ToAggregate() + cfg *kubeadmapi.MasterConfiguration + skipTokenPrint bool + dryRun bool + ignorePreflightErrors sets.String } // Run executes master node provisioning, including certificates, needed static pod manifests, etc. func (i *Init) Run(out io.Writer) error { + // Get directories to write files to; can be faked if we're dry-running + glog.V(1).Infof("[init] Getting certificates directory from configuration") realCertsDir := i.cfg.CertificatesDir - certsDirToWriteTo, kubeConfigDir, manifestDir, err := getDirectoriesToUse(i.dryRun, i.cfg.CertificatesDir) + certsDirToWriteTo, kubeConfigDir, manifestDir, kubeletDir, err := getDirectoriesToUse(i.dryRun, i.cfg.CertificatesDir) if err != nil { return fmt.Errorf("error getting directories to use: %v", err) } + + // First off, configure the kubelet. In this short timeframe, kubeadm is trying to stop/restart the kubelet + // Try to stop the kubelet service so no race conditions occur when configuring it + if !i.dryRun { + glog.V(1).Infof("Stopping the kubelet") + preflight.TryStopKubelet() + } + + // Write env file with flags for the kubelet to use. We do not need to write the --register-with-taints for the master, + // as we handle that ourselves in the markmaster phase + // TODO: Maybe we want to do that some time in the future, in order to remove some logic from the markmaster phase? + if err := kubeletphase.WriteKubeletDynamicEnvFile(&i.cfg.NodeRegistration, i.cfg.FeatureGates, false, kubeletDir); err != nil { + return fmt.Errorf("error writing a dynamic environment file for the kubelet: %v", err) + } + + // Write the kubelet configuration file to disk. + if err := kubeletphase.WriteConfigToDisk(i.cfg.KubeletConfiguration.BaseConfig, kubeletDir); err != nil { + return fmt.Errorf("error writing kubelet configuration to disk: %v", err) + } + + if !i.dryRun { + // Try to start the kubelet service in case it's inactive + glog.V(1).Infof("Starting the kubelet") + preflight.TryStartKubelet() + } + // certsDirToWriteTo is gonna equal cfg.CertificatesDir in the normal case, but gonna be a temp directory if dryrunning i.cfg.CertificatesDir = certsDirToWriteTo @@ -304,17 +326,19 @@ func (i *Init) Run(out io.Writer) error { if res, _ := certsphase.UsingExternalCA(i.cfg); !res { // PHASE 1: Generate certificates + glog.V(1).Infof("[init] creating PKI Assets") if err := certsphase.CreatePKIAssets(i.cfg); err != nil { return err } // PHASE 2: Generate kubeconfig files for the admin and the kubelet + glog.V(2).Infof("[init] generating kubeconfig files") if err := kubeconfigphase.CreateInitKubeConfigFiles(kubeConfigDir, i.cfg); err != nil { return err } } else { - fmt.Println("[externalca] The file 'ca.key' was not found, yet all other certificates are present. Using external CA mode - certificates or kubeconfig will not be generated.") + fmt.Println("[externalca] the file 'ca.key' was not found, yet all other certificates are present. Using external CA mode - certificates or kubeconfig will not be generated") } if features.Enabled(i.cfg.FeatureGates, features.Auditing) { @@ -337,11 +361,14 @@ func (i *Init) Run(out io.Writer) error { i.cfg.CertificatesDir = realCertsDir // PHASE 3: Bootstrap the control plane + glog.V(1).Infof("[init] bootstraping the control plane") + glog.V(1).Infof("[init] creating static pod manifest") if err := controlplanephase.CreateInitStaticPodManifestFiles(manifestDir, i.cfg); err != nil { return fmt.Errorf("error creating init static pod manifest files: %v", err) } // Add etcd static pod spec only if external etcd is not configured - if len(i.cfg.Etcd.Endpoints) == 0 { + if i.cfg.Etcd.External == nil { + glog.V(1).Infof("[init] no external etcd found. Creating manifest for local etcd static pod") if err := etcdphase.CreateLocalEtcdStaticPodManifestFile(manifestDir, i.cfg); err != nil { return fmt.Errorf("error creating local etcd static pod manifest file: %v", err) } @@ -355,30 +382,32 @@ func (i *Init) Run(out io.Writer) error { return fmt.Errorf("error printing files on dryrun: %v", err) } - // NOTE: flag "--dynamic-config-dir" should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf - if features.Enabled(i.cfg.FeatureGates, features.DynamicKubeletConfig) { - // Write base kubelet configuration for dynamic kubelet configuration feature. - if err := kubeletphase.WriteInitKubeletConfigToDiskOnMaster(i.cfg); err != nil { - return fmt.Errorf("error writing base kubelet configuration to disk: %v", err) - } - } - // Create a kubernetes client and wait for the API server to be healthy (if not dryrunning) + glog.V(1).Infof("creating Kubernetes client") client, err := createClient(i.cfg, i.dryRun) if err != nil { return fmt.Errorf("error creating client: %v", err) } // waiter holds the apiclient.Waiter implementation of choice, responsible for querying the API server in various ways and waiting for conditions to be fulfilled + glog.V(1).Infof("[init] waiting for the API server to be healthy") waiter := getWaiter(i, client) - if err := waitForAPIAndKubelet(waiter); err != nil { + fmt.Printf("[init] waiting for the kubelet to boot up the control plane as Static Pods from directory %q \n", kubeadmconstants.GetStaticPodDirectory()) + fmt.Println("[init] this might take a minute or longer if the control plane images have to be pulled") + + if err := waitForKubeletAndFunc(waiter, waiter.WaitForAPI); err != nil { ctx := map[string]string{ "Error": fmt.Sprintf("%v", err), "APIServerImage": images.GetCoreImage(kubeadmconstants.KubeAPIServer, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage), "ControllerManagerImage": images.GetCoreImage(kubeadmconstants.KubeControllerManager, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage), "SchedulerImage": images.GetCoreImage(kubeadmconstants.KubeScheduler, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage), - "EtcdImage": images.GetCoreImage(kubeadmconstants.Etcd, i.cfg.ImageRepository, i.cfg.KubernetesVersion, i.cfg.Etcd.Image), + } + // Set .EtcdImage conditionally + if i.cfg.Etcd.Local != nil { + ctx["EtcdImage"] = fmt.Sprintf(" - %s", images.GetCoreImage(kubeadmconstants.Etcd, i.cfg.ImageRepository, i.cfg.KubernetesVersion, i.cfg.Etcd.Local.Image)) + } else { + ctx["EtcdImage"] = "" } kubeletFailTempl.Execute(out, ctx) @@ -386,71 +415,104 @@ func (i *Init) Run(out io.Writer) error { return fmt.Errorf("couldn't initialize a Kubernetes cluster") } - // NOTE: flag "--dynamic-config-dir" should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf - if features.Enabled(i.cfg.FeatureGates, features.DynamicKubeletConfig) { - // Create base kubelet configuration for dynamic kubelet configuration feature. - if err := kubeletphase.CreateBaseKubeletConfiguration(i.cfg, client); err != nil { - return fmt.Errorf("error creating base kubelet configuration: %v", err) - } - } - // Upload currently used configuration to the cluster // Note: This is done right in the beginning of cluster initialization; as we might want to make other phases // depend on centralized information from this source in the future + glog.V(1).Infof("[init] uploading currently used configuration to the cluster") if err := uploadconfigphase.UploadConfiguration(i.cfg, client); err != nil { return fmt.Errorf("error uploading configuration: %v", err) } + glog.V(1).Infof("[init] creating kubelet configuration configmap") + if err := kubeletphase.CreateConfigMap(i.cfg, client); err != nil { + return fmt.Errorf("error creating kubelet configuration ConfigMap: %v", err) + } + // PHASE 4: Mark the master with the right label/taint - if err := markmasterphase.MarkMaster(client, i.cfg.NodeName, !i.cfg.NoTaintMaster); err != nil { + glog.V(1).Infof("[init] marking the master with right label") + if err := markmasterphase.MarkMaster(client, i.cfg.NodeRegistration.Name, i.cfg.NodeRegistration.Taints); err != nil { return fmt.Errorf("error marking master: %v", err) } + glog.V(1).Infof("[init] preserving the crisocket information for the master") + if err := patchnodephase.AnnotateCRISocket(client, i.cfg.NodeRegistration.Name, i.cfg.NodeRegistration.CRISocket); err != nil { + return fmt.Errorf("error uploading crisocket: %v", err) + } + + // This feature is disabled by default + if features.Enabled(i.cfg.FeatureGates, features.DynamicKubeletConfig) { + kubeletVersion, err := preflight.GetKubeletVersion(utilsexec.New()) + if err != nil { + return err + } + + // Enable dynamic kubelet configuration for the node. + if err := kubeletphase.EnableDynamicConfigForNode(client, i.cfg.NodeRegistration.Name, kubeletVersion); err != nil { + return fmt.Errorf("error enabling dynamic kubelet configuration: %v", err) + } + } + // PHASE 5: Set up the node bootstrap tokens + tokens := []string{} + for _, bt := range i.cfg.BootstrapTokens { + tokens = append(tokens, bt.Token.String()) + } if !i.skipTokenPrint { - fmt.Printf("[bootstraptoken] Using token: %s\n", i.cfg.Token) + if len(tokens) == 1 { + fmt.Printf("[bootstraptoken] using token: %s\n", tokens[0]) + } else if len(tokens) > 1 { + fmt.Printf("[bootstraptoken] using tokens: %v\n", tokens) + } } // Create the default node bootstrap token - tokenDescription := "The default bootstrap token generated by 'kubeadm init'." - if err := nodebootstraptokenphase.UpdateOrCreateToken(client, i.cfg.Token, false, i.cfg.TokenTTL.Duration, i.cfg.TokenUsages, i.cfg.TokenGroups, tokenDescription); err != nil { + glog.V(1).Infof("[init] creating RBAC rules to generate default bootstrap token") + if err := nodebootstraptokenphase.UpdateOrCreateTokens(client, false, i.cfg.BootstrapTokens); err != nil { return fmt.Errorf("error updating or creating token: %v", err) } // Create RBAC rules that makes the bootstrap tokens able to post CSRs + glog.V(1).Infof("[init] creating RBAC rules to allow bootstrap tokens to post CSR") if err := nodebootstraptokenphase.AllowBootstrapTokensToPostCSRs(client); err != nil { return fmt.Errorf("error allowing bootstrap tokens to post CSRs: %v", err) } // Create RBAC rules that makes the bootstrap tokens able to get their CSRs approved automatically + glog.V(1).Infof("[init] creating RBAC rules to automatic approval of CSRs automatically") if err := nodebootstraptokenphase.AutoApproveNodeBootstrapTokens(client); err != nil { return fmt.Errorf("error auto-approving node bootstrap tokens: %v", err) } // Create/update RBAC rules that makes the nodes to rotate certificates and get their CSRs approved automatically + glog.V(1).Infof("[init] creating/updating RBAC rules for rotating certificate") if err := nodebootstraptokenphase.AutoApproveNodeCertificateRotation(client); err != nil { return err } // Create the cluster-info ConfigMap with the associated RBAC rules + glog.V(1).Infof("[init] creating bootstrap configmap") if err := clusterinfophase.CreateBootstrapConfigMapIfNotExists(client, adminKubeConfigPath); err != nil { return fmt.Errorf("error creating bootstrap configmap: %v", err) } + glog.V(1).Infof("[init] creating ClusterInfo RBAC rules") if err := clusterinfophase.CreateClusterInfoRBACRules(client); err != nil { return fmt.Errorf("error creating clusterinfo RBAC rules: %v", err) } + glog.V(1).Infof("[init] ensuring DNS addon") if err := dnsaddonphase.EnsureDNSAddon(i.cfg, client); err != nil { return fmt.Errorf("error ensuring dns addon: %v", err) } + glog.V(1).Infof("[init] ensuring proxy addon") if err := proxyaddonphase.EnsureProxyAddon(i.cfg, client); err != nil { return fmt.Errorf("error ensuring proxy addon: %v", err) } // PHASE 7: Make the control plane self-hosted if feature gate is enabled if features.Enabled(i.cfg.FeatureGates, features.SelfHosting) { + glog.V(1).Infof("[init] feature gate is enabled. Making control plane self-hosted") // Temporary control plane is up, now we create our self hosted control // plane components and remove the static manifests: - fmt.Println("[self-hosted] Creating self-hosted control plane.") + fmt.Println("[self-hosted] creating self-hosted control plane") if err := selfhostingphase.CreateSelfHostedControlPlane(manifestDir, kubeConfigDir, i.cfg, client, waiter, i.dryRun); err != nil { return fmt.Errorf("error creating self hosted control plane: %v", err) } @@ -458,14 +520,23 @@ func (i *Init) Run(out io.Writer) error { // Exit earlier if we're dryrunning if i.dryRun { - fmt.Println("[dryrun] Finished dry-running successfully. Above are the resources that would be created.") + fmt.Println("[dryrun] finished dry-running successfully. Above are the resources that would be created") return nil } - // Gets the join command - joinCommand, err := cmdutil.GetJoinCommand(kubeadmconstants.GetAdminKubeConfigPath(), i.cfg.Token, i.skipTokenPrint) + // Prints the join command, multiple times in case the user has multiple tokens + for _, token := range tokens { + if err := printJoinCommand(out, adminKubeConfigPath, token, i.skipTokenPrint); err != nil { + return fmt.Errorf("failed to print join command: %v", err) + } + } + return nil +} + +func printJoinCommand(out io.Writer, adminKubeConfigPath, token string, skipTokenPrint bool) error { + joinCommand, err := cmdutil.GetJoinCommand(adminKubeConfigPath, token, skipTokenPrint) if err != nil { - return fmt.Errorf("failed to get join command: %v", err) + return err } ctx := map[string]string{ @@ -480,7 +551,7 @@ func (i *Init) Run(out io.Writer) error { func createClient(cfg *kubeadmapi.MasterConfiguration, dryRun bool) (clientset.Interface, error) { if dryRun { // If we're dry-running; we should create a faked client that answers some GETs in order to be able to do the full init flow and just logs the rest of requests - dryRunGetter := apiclient.NewInitDryRunGetter(cfg.NodeName, cfg.Networking.ServiceSubnet) + dryRunGetter := apiclient.NewInitDryRunGetter(cfg.NodeRegistration.Name, cfg.Networking.ServiceSubnet) return apiclient.NewDryRunClient(dryRunGetter, os.Stdout), nil } @@ -490,17 +561,17 @@ func createClient(cfg *kubeadmapi.MasterConfiguration, dryRun bool) (clientset.I // getDirectoriesToUse returns the (in order) certificates, kubeconfig and Static Pod manifest directories, followed by a possible error // This behaves differently when dry-running vs the normal flow -func getDirectoriesToUse(dryRun bool, defaultPkiDir string) (string, string, string, error) { +func getDirectoriesToUse(dryRun bool, defaultPkiDir string) (string, string, string, string, error) { if dryRun { dryRunDir, err := ioutil.TempDir("", "kubeadm-init-dryrun") if err != nil { - return "", "", "", fmt.Errorf("couldn't create a temporary directory: %v", err) + return "", "", "", "", fmt.Errorf("couldn't create a temporary directory: %v", err) } // Use the same temp dir for all - return dryRunDir, dryRunDir, dryRunDir, nil + return dryRunDir, dryRunDir, dryRunDir, dryRunDir, nil } - return defaultPkiDir, kubeadmconstants.KubernetesDir, kubeadmconstants.GetStaticPodDirectory(), nil + return defaultPkiDir, kubeadmconstants.KubernetesDir, kubeadmconstants.GetStaticPodDirectory(), kubeadmconstants.KubeletRunDirectory, nil } // printFilesIfDryRunning prints the Static Pod manifests to stdout and informs about the temporary directory to go and lookup @@ -509,17 +580,25 @@ func printFilesIfDryRunning(dryRun bool, manifestDir string) error { return nil } - fmt.Printf("[dryrun] Wrote certificates, kubeconfig files and control plane manifests to the %q directory.\n", manifestDir) - fmt.Println("[dryrun] The certificates or kubeconfig files would not be printed due to their sensitive nature.") - fmt.Printf("[dryrun] Please examine the %q directory for details about what would be written.\n", manifestDir) + fmt.Printf("[dryrun] wrote certificates, kubeconfig files and control plane manifests to the %q directory\n", manifestDir) + fmt.Println("[dryrun] the certificates or kubeconfig files would not be printed due to their sensitive nature") + fmt.Printf("[dryrun] please examine the %q directory for details about what would be written\n", manifestDir) // Print the contents of the upgraded manifests and pretend like they were in /etc/kubernetes/manifests files := []dryrunutil.FileToPrint{} + // Print static pod manifests for _, component := range kubeadmconstants.MasterComponents { realPath := kubeadmconstants.GetStaticPodFilepath(component, manifestDir) outputPath := kubeadmconstants.GetStaticPodFilepath(component, kubeadmconstants.GetStaticPodDirectory()) files = append(files, dryrunutil.NewFileToPrint(realPath, outputPath)) } + // Print kubelet config manifests + kubeletConfigFiles := []string{kubeadmconstants.KubeletConfigurationFileName, kubeadmconstants.KubeletEnvFileName} + for _, filename := range kubeletConfigFiles { + realPath := filepath.Join(manifestDir, filename) + outputPath := filepath.Join(kubeadmconstants.KubeletRunDirectory, filename) + files = append(files, dryrunutil.NewFileToPrint(realPath, outputPath)) + } return dryrunutil.PrintDryRunFiles(files, os.Stdout) } @@ -530,42 +609,30 @@ func getWaiter(i *Init, client clientset.Interface) apiclient.Waiter { return dryrunutil.NewWaiter() } - timeout := 30 * time.Minute - - // No need for a large timeout if we don't expect downloads - if i.cfg.ImagePullPolicy == v1.PullNever { - timeout = 60 * time.Second - } + // We know that the images should be cached locally already as we have pulled them using + // crictl in the preflight checks. Hence we can have a pretty short timeout for the kubelet + // to start creating Static Pods. + timeout := 4 * time.Minute return apiclient.NewKubeWaiter(client, timeout, os.Stdout) } -// waitForAPIAndKubelet waits primarily for the API server to come up. If that takes a long time, and the kubelet -// /healthz and /healthz/syncloop endpoints continuously are unhealthy, kubeadm will error out after a period of -// backoffing exponentially -func waitForAPIAndKubelet(waiter apiclient.Waiter) error { +// waitForKubeletAndFunc waits primarily for the function f to execute, even though it might take some time. If that takes a long time, and the kubelet +// /healthz continuously are unhealthy, kubeadm will error out after a period of exponential backoff +func waitForKubeletAndFunc(waiter apiclient.Waiter, f func() error) error { errorChan := make(chan error) - fmt.Printf("[init] Waiting for the kubelet to boot up the control plane as Static Pods from directory %q.\n", kubeadmconstants.GetStaticPodDirectory()) - fmt.Println("[init] This might take a minute or longer if the control plane images have to be pulled.") - - go func(errC chan error, waiter apiclient.Waiter) { - // This goroutine can only make kubeadm init fail. If this check succeeds, it won't do anything special - if err := waiter.WaitForHealthyKubelet(40*time.Second, "http://localhost:10255/healthz"); err != nil { - errC <- err - } - }(errorChan, waiter) - go func(errC chan error, waiter apiclient.Waiter) { // This goroutine can only make kubeadm init fail. If this check succeeds, it won't do anything special - if err := waiter.WaitForHealthyKubelet(60*time.Second, "http://localhost:10255/healthz/syncloop"); err != nil { + // TODO: Make 10248 a constant somewhere + if err := waiter.WaitForHealthyKubelet(40*time.Second, "http://localhost:10248/healthz"); err != nil { errC <- err } }(errorChan, waiter) go func(errC chan error, waiter apiclient.Waiter) { - // This main goroutine sends whatever WaitForAPI returns (error or not) to the channel - // This in order to continue on success (nil error), or just fail if - errC <- waiter.WaitForAPI() + // This main goroutine sends whatever the f function returns (error or not) to the channel + // This in order to continue on success (nil error), or just fail if the function returns an error + errC <- f() }(errorChan, waiter) // This call is blocking until one of the goroutines sends to errorChan diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go index de6a3e456..20ccfb4f0 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go @@ -19,29 +19,32 @@ package cmd import ( "fmt" "io" - "io/ioutil" + "os" "path/filepath" "strings" + "github.com/golang/glog" "github.com/renstrom/dedent" "github.com/spf13/cobra" flag "github.com/spf13/pflag" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/wait" certutil "k8s.io/client-go/util/cert" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/discovery" "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" + patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" + configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - "k8s.io/kubernetes/pkg/api/legacyscheme" - nodeutil "k8s.io/kubernetes/pkg/util/node" utilsexec "k8s.io/utils/exec" ) @@ -97,12 +100,25 @@ var ( Often times the same token is used for both parts. In this case, the --token flag can be used instead of specifying each token individually. `) + + kubeadmJoinFailMsgf = dedent.Dedent(` + Unfortunately, an error has occurred: + %v + + This error is likely caused by: + - The kubelet is not running + - The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled) + + If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands: + - 'systemctl status kubelet' + - 'journalctl -xeu kubelet' + `) ) // NewCmdJoin returns "kubeadm join" command. func NewCmdJoin(out io.Writer) *cobra.Command { - cfg := &kubeadmapiext.NodeConfiguration{} - legacyscheme.Scheme.Default(cfg) + cfg := &kubeadmapiv1alpha2.NodeConfiguration{} + kubeadmscheme.Scheme.Default(cfg) var skipPreFlight bool var cfgPath string @@ -114,23 +130,8 @@ func NewCmdJoin(out io.Writer) *cobra.Command { Short: "Run this on any machine you wish to join an existing cluster", Long: joinLongDescription, Run: func(cmd *cobra.Command, args []string) { - cfg.DiscoveryTokenAPIServers = args - - var err error - if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil { - kubeadmutil.CheckErr(err) - } - - legacyscheme.Scheme.Default(cfg) - internalcfg := &kubeadmapi.NodeConfiguration{} - legacyscheme.Scheme.Convert(cfg, internalcfg, nil) - - ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight) - kubeadmutil.CheckErr(err) - - j, err := NewJoin(cfgPath, args, internalcfg, ignorePreflightErrorsSet) + j, err := NewValidJoin(cmd.PersistentFlags(), cfg, args, skipPreFlight, cfgPath, featureGatesString, ignorePreflightErrors) kubeadmutil.CheckErr(err) - kubeadmutil.CheckErr(j.Validate(cmd)) kubeadmutil.CheckErr(j.Run(out)) }, } @@ -141,8 +142,29 @@ func NewCmdJoin(out io.Writer) *cobra.Command { return cmd } +// NewValidJoin validates the command line that are passed to the cobra command +func NewValidJoin(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.NodeConfiguration, args []string, skipPreFlight bool, cfgPath, featureGatesString string, ignorePreflightErrors []string) (*Join, error) { + cfg.DiscoveryTokenAPIServers = args + + var err error + if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil { + return nil, err + } + + if err := validation.ValidateMixedArguments(flagSet); err != nil { + return nil, err + } + + ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight) + if err != nil { + return nil, err + } + + return NewJoin(cfgPath, args, cfg, ignorePreflightErrorsSet) +} + // AddJoinConfigFlags adds join flags bound to the config to the specified flagset -func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiext.NodeConfiguration, featureGatesString *string) { +func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.NodeConfiguration, featureGatesString *string) { flagSet.StringVar( &cfg.DiscoveryFile, "discovery-file", "", "A file or url from which to load cluster information.") @@ -150,7 +172,7 @@ func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiext.NodeConfigurat &cfg.DiscoveryToken, "discovery-token", "", "A token used to validate cluster information fetched from the master.") flagSet.StringVar( - &cfg.NodeName, "node-name", "", + &cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, "Specify the node name.") flagSet.StringVar( &cfg.TLSBootstrapToken, "tls-bootstrap-token", "", @@ -169,7 +191,7 @@ func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiext.NodeConfigurat "A set of key=value pairs that describe feature gates for various features. "+ "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) flagSet.StringVar( - &cfg.CRISocket, "cri-socket", cfg.CRISocket, + &cfg.NodeRegistration.CRISocket, "cri-socket", cfg.NodeRegistration.CRISocket, `Specify the CRI socket to connect to.`, ) } @@ -193,71 +215,111 @@ func AddJoinOtherFlags(flagSet *flag.FlagSet, cfgPath *string, skipPreFlight *bo // Join defines struct used by kubeadm join command type Join struct { - cfg *kubeadmapi.NodeConfiguration + cfg *kubeadmapi.NodeConfiguration + ignorePreflightErrors sets.String } // NewJoin instantiates Join struct with given arguments -func NewJoin(cfgPath string, args []string, cfg *kubeadmapi.NodeConfiguration, ignorePreflightErrors sets.String) (*Join, error) { +func NewJoin(cfgPath string, args []string, defaultcfg *kubeadmapiv1alpha2.NodeConfiguration, ignorePreflightErrors sets.String) (*Join, error) { - if cfg.NodeName == "" { - cfg.NodeName = nodeutil.GetHostname("") + if defaultcfg.NodeRegistration.Name == "" { + glog.V(1).Infoln("[join] found NodeName empty") + glog.V(1).Infoln("[join] considered OS hostname as NodeName") } - if cfgPath != "" { - b, err := ioutil.ReadFile(cfgPath) - if err != nil { - return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err) - } - if err := runtime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), b, cfg); err != nil { - return nil, fmt.Errorf("unable to decode config from %q [%v]", cfgPath, err) - } + internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg) + if err != nil { + return nil, err } - fmt.Println("[preflight] Running pre-flight checks.") + fmt.Println("[preflight] running pre-flight checks") // Then continue with the others... - if err := preflight.RunJoinNodeChecks(utilsexec.New(), cfg, ignorePreflightErrors); err != nil { + glog.V(1).Infoln("[preflight] running various checks on all nodes") + if err := preflight.RunJoinNodeChecks(utilsexec.New(), internalcfg, ignorePreflightErrors); err != nil { return nil, err } - // Try to start the kubelet service in case it's inactive - preflight.TryStartKubelet(ignorePreflightErrors) - - return &Join{cfg: cfg}, nil -} - -// Validate validates mixed arguments passed to cobra.Command -func (j *Join) Validate(cmd *cobra.Command) error { - if err := validation.ValidateMixedArguments(cmd.PersistentFlags()); err != nil { - return err - } - return validation.ValidateNodeConfiguration(j.cfg).ToAggregate() + return &Join{cfg: internalcfg, ignorePreflightErrors: ignorePreflightErrors}, nil } // Run executes worker node provisioning and tries to join an existing cluster. func (j *Join) Run(out io.Writer) error { + + // Perform the Discovery, which turns a Bootstrap Token and optionally (and preferably) a CA cert hash into a KubeConfig + // file that may be used for the TLS Bootstrapping process the kubelet performs using the Certificates API. + glog.V(1).Infoln("[join] retrieving KubeConfig objects") cfg, err := discovery.For(j.cfg) if err != nil { return err } - kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName) + bootstrapKubeConfigFile := kubeadmconstants.GetBootstrapKubeletKubeConfigPath() // Write the bootstrap kubelet config file or the TLS-Boostrapped kubelet config file down to disk - if err := kubeconfigutil.WriteToDisk(kubeconfigFile, cfg); err != nil { + glog.V(1).Infoln("[join] writing bootstrap kubelet config file at", bootstrapKubeConfigFile) + if err := kubeconfigutil.WriteToDisk(bootstrapKubeConfigFile, cfg); err != nil { return fmt.Errorf("couldn't save bootstrap-kubelet.conf to disk: %v", err) } // Write the ca certificate to disk so kubelet can use it for authentication cluster := cfg.Contexts[cfg.CurrentContext].Cluster - err = certutil.WriteCert(j.cfg.CACertPath, cfg.Clusters[cluster].CertificateAuthorityData) - if err != nil { + if err := certutil.WriteCert(j.cfg.CACertPath, cfg.Clusters[cluster].CertificateAuthorityData); err != nil { return fmt.Errorf("couldn't save the CA certificate to disk: %v", err) } - // NOTE: flag "--dynamic-config-dir" should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf + kubeletVersion, err := preflight.GetKubeletVersion(utilsexec.New()) + if err != nil { + return err + } + + bootstrapClient, err := kubeconfigutil.ClientSetFromFile(bootstrapKubeConfigFile) + if err != nil { + return fmt.Errorf("couldn't create client from kubeconfig file %q", bootstrapKubeConfigFile) + } + + // Configure the kubelet. In this short timeframe, kubeadm is trying to stop/restart the kubelet + // Try to stop the kubelet service so no race conditions occur when configuring it + glog.V(1).Infof("Stopping the kubelet") + preflight.TryStopKubelet() + + // Write the configuration for the kubelet (using the bootstrap token credentials) to disk so the kubelet can start + if err := kubeletphase.DownloadConfig(bootstrapClient, kubeletVersion, kubeadmconstants.KubeletRunDirectory); err != nil { + return err + } + + // Write env file with flags for the kubelet to use. Also register taints + if err := kubeletphase.WriteKubeletDynamicEnvFile(&j.cfg.NodeRegistration, j.cfg.FeatureGates, true, kubeadmconstants.KubeletRunDirectory); err != nil { + return err + } + + // Try to start the kubelet service in case it's inactive + glog.V(1).Infof("Starting the kubelet") + preflight.TryStartKubelet() + + // Now the kubelet will perform the TLS Bootstrap, transforming /etc/kubernetes/bootstrap-kubelet.conf to /etc/kubernetes/kubelet.conf + // Wait for the kubelet to create the /etc/kubernetes/kubelet.conf KubeConfig file. If this process + // times out, display a somewhat user-friendly message. + waiter := apiclient.NewKubeWaiter(nil, kubeadmconstants.TLSBootstrapTimeout, os.Stdout) + if err := waitForKubeletAndFunc(waiter, waitForTLSBootstrappedClient); err != nil { + fmt.Printf(kubeadmJoinFailMsgf, err) + return err + } + + // When we know the /etc/kubernetes/kubelet.conf file is available, get the client + client, err := kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetKubeletKubeConfigPath()) + if err != nil { + return err + } + + glog.V(1).Infof("[join] preserving the crisocket information for the node") + if err := patchnodephase.AnnotateCRISocket(client, j.cfg.NodeRegistration.Name, j.cfg.NodeRegistration.CRISocket); err != nil { + return fmt.Errorf("error uploading crisocket: %v", err) + } + + // This feature is disabled by default in kubeadm if features.Enabled(j.cfg.FeatureGates, features.DynamicKubeletConfig) { - if err := kubeletphase.ConsumeBaseKubeletConfiguration(j.cfg.NodeName); err != nil { + if err := kubeletphase.EnableDynamicConfigForNode(client, j.cfg.NodeRegistration.Name, kubeletVersion); err != nil { return fmt.Errorf("error consuming base kubelet configuration: %v", err) } } @@ -265,3 +327,15 @@ func (j *Join) Run(out io.Writer) error { fmt.Fprintf(out, joinDoneMsgf) return nil } + +// waitForTLSBootstrappedClient waits for the /etc/kubernetes/kubelet.conf file to be available +func waitForTLSBootstrappedClient() error { + fmt.Println("[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...") + + kubeletKubeConfig := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName) + // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. + return wait.PollImmediate(kubeadmconstants.APICallRetryInterval, kubeadmconstants.TLSBootstrapTimeout, func() (bool, error) { + _, err := os.Stat(kubeletKubeConfig) + return (err == nil), nil + }) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join_test.go new file mode 100644 index 000000000..ee4d06fdf --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join_test.go @@ -0,0 +1,183 @@ +/* +Copyright 2018 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 cmd + +import ( + "bytes" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" +) + +const ( + testConfig = `apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: + server: localhost:9008 + name: prod +contexts: +- context: + cluster: prod + namespace: default + user: default-service-account + name: default +current-context: default +kind: Config +preferences: {} +users: +- name: kubernetes-admin + user: + client-certificate-data: + client-key-data: +` +) + +func TestNewValidJoin(t *testing.T) { + // create temp directory + tmpDir, err := ioutil.TempDir("", "kubeadm-join-test") + if err != nil { + t.Errorf("Unable to create temporary directory: %v", err) + } + defer os.RemoveAll(tmpDir) + + // create config file + configFilePath := filepath.Join(tmpDir, "test-config-file") + cfgFile, err := os.Create(configFilePath) + if err != nil { + t.Errorf("Unable to create file %q: %v", configFilePath, err) + } + defer cfgFile.Close() + + testCases := []struct { + name string + args []string + skipPreFlight bool + cfgPath string + configToWrite string + featureGatesString string + ignorePreflightErrors []string + testJoinValidate bool + testJoinRun bool + cmdPersistentFlags map[string]string + nodeConfig *kubeadm.NodeConfiguration + expectedError bool + }{ + { + name: "invalid: missing config file", + skipPreFlight: true, + cfgPath: "missing-path-to-a-config", + expectedError: true, + }, + { + name: "invalid: incorrect config file", + skipPreFlight: true, + cfgPath: configFilePath, + configToWrite: "bad-config-contents", + expectedError: true, + }, + { + name: "invalid: fail at preflight.RunJoinNodeChecks()", + skipPreFlight: false, + cfgPath: configFilePath, + configToWrite: testConfig, + expectedError: true, + }, + { + name: "invalid: incorrect ignorePreflight argument", + skipPreFlight: true, + cfgPath: configFilePath, + configToWrite: testConfig, + ignorePreflightErrors: []string{"some-unsupported-preflight-arg"}, + expectedError: true, + }, + { + name: "invalid: incorrect featureGatesString", + featureGatesString: "bad-feature-gate-string", + expectedError: true, + }, + { + name: "invalid: fail Join.Validate() with wrong flags", + skipPreFlight: true, + cfgPath: configFilePath, + configToWrite: testConfig, + testJoinValidate: true, + cmdPersistentFlags: map[string]string{ + "config": "some-config", + "node-name": "some-node-name", + }, + expectedError: true, + }, + { + name: "invalid: fail Join.Validate() with wrong node configuration", + skipPreFlight: true, + cfgPath: configFilePath, + configToWrite: testConfig, + testJoinValidate: true, + expectedError: true, + }, + { + name: "invalid: fail Join.Run() with invalid node config", + skipPreFlight: true, + cfgPath: configFilePath, + configToWrite: testConfig, + testJoinRun: true, + expectedError: true, + }, + } + + var out bytes.Buffer + cfg := &kubeadmapiv1alpha2.NodeConfiguration{} + kubeadmscheme.Scheme.Default(cfg) + + errorFormat := "Test case %q: NewValidJoin expected error: %v, saw: %v, error: %v" + + for _, tc := range testCases { + if _, err = cfgFile.WriteString(tc.configToWrite); err != nil { + t.Fatalf("Unable to write file %q: %v", tc.cfgPath, err) + } + + cmd := NewCmdJoin(&out) + if tc.cmdPersistentFlags != nil { + for key, value := range tc.cmdPersistentFlags { + cmd.PersistentFlags().Set(key, value) + } + } + + join, err := NewValidJoin(cmd.PersistentFlags(), cfg, tc.args, tc.skipPreFlight, tc.cfgPath, tc.featureGatesString, tc.ignorePreflightErrors) + + if tc.nodeConfig != nil { + join.cfg = tc.nodeConfig + } + + // test Join.Run() + if err == nil && tc.testJoinRun { + err = join.Run(&out) + if (err != nil) != tc.expectedError { + t.Fatalf(errorFormat, tc.name, tc.expectedError, (err != nil), err) + } + // check error for NewValidJoin() + } else if (err != nil) != tc.expectedError { + t.Fatalf(errorFormat, tc.name, tc.expectedError, (err != nil), err) + } + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/options/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/options/BUILD new file mode 100644 index 000000000..c04f725e5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/options/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "generic.go", + "token.go", + ], + importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options", + visibility = ["//visibility:public"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/options/generic.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/options/generic.go new file mode 100644 index 000000000..7aa8d82f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/options/generic.go @@ -0,0 +1,29 @@ +/* +Copyright 2018 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 options + +import "github.com/spf13/pflag" + +// AddKubeConfigFlag adds the --kubeconfig flag to the given flagset +func AddKubeConfigFlag(fs *pflag.FlagSet, kubeConfigFile *string) { + fs.StringVar(kubeConfigFile, "kubeconfig", *kubeConfigFile, "The KubeConfig file to use when talking to the cluster") +} + +// AddConfigFlag adds the --config flag to the given flagset +func AddConfigFlag(fs *pflag.FlagSet, cfgPath *string) { + fs.StringVar(cfgPath, "config", *cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/options/token.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/options/token.go new file mode 100644 index 000000000..d875eb9d5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/options/token.go @@ -0,0 +1,104 @@ +/* +Copyright 2018 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 options + +import ( + "fmt" + "strings" + + "github.com/spf13/pflag" + + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" +) + +// NewBootstrapTokenOptions creates a new BootstrapTokenOptions object with the default values +func NewBootstrapTokenOptions() *BootstrapTokenOptions { + bto := &BootstrapTokenOptions{&kubeadmapiv1alpha2.BootstrapToken{}, ""} + kubeadmapiv1alpha2.SetDefaults_BootstrapToken(bto.BootstrapToken) + return bto +} + +// BootstrapTokenOptions is a wrapper struct for adding bootstrap token-related flags to a FlagSet +// and applying the parsed flags to a MasterConfiguration object later at runtime +// TODO: In the future, we might want to group the flags in a better way than adding them all individually like this +type BootstrapTokenOptions struct { + *kubeadmapiv1alpha2.BootstrapToken + TokenStr string +} + +// AddTokenFlag adds the --token flag to the given flagset +func (bto *BootstrapTokenOptions) AddTokenFlag(fs *pflag.FlagSet) { + fs.StringVar( + &bto.TokenStr, "token", "", + "The token to use for establishing bidirectional trust between nodes and masters. The format is [a-z0-9]{6}\\.[a-z0-9]{16} - e.g. abcdef.0123456789abcdef", + ) +} + +// AddTTLFlag adds the --token-ttl flag to the given flagset +func (bto *BootstrapTokenOptions) AddTTLFlag(fs *pflag.FlagSet) { + bto.AddTTLFlagWithName(fs, "token-ttl") +} + +// AddTTLFlagWithName adds the --token-ttl flag with a custom flag name given flagset +func (bto *BootstrapTokenOptions) AddTTLFlagWithName(fs *pflag.FlagSet, flagName string) { + fs.DurationVar( + &bto.TTL.Duration, flagName, bto.TTL.Duration, + "The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire", + ) +} + +// AddUsagesFlag adds the --usages flag to the given flagset +func (bto *BootstrapTokenOptions) AddUsagesFlag(fs *pflag.FlagSet) { + fs.StringSliceVar( + &bto.Usages, "usages", bto.Usages, + fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s]", strings.Join(kubeadmconstants.DefaultTokenUsages, ",")), + ) +} + +// AddGroupsFlag adds the --groups flag to the given flagset +func (bto *BootstrapTokenOptions) AddGroupsFlag(fs *pflag.FlagSet) { + fs.StringSliceVar( + &bto.Groups, "groups", bto.Groups, + fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern), + ) +} + +// AddDescriptionFlag adds the --description flag to the given flagset +func (bto *BootstrapTokenOptions) AddDescriptionFlag(fs *pflag.FlagSet) { + fs.StringVar( + &bto.Description, "description", bto.Description, + "A human friendly description of how this token is used.", + ) +} + +// ApplyTo applies the values set internally in the BootstrapTokenOptions object to a MasterConfiguration object at runtime +// If --token was specified in the CLI (as a string), it's parsed and validated before it's added to the BootstrapToken object. +func (bto *BootstrapTokenOptions) ApplyTo(cfg *kubeadmapiv1alpha2.MasterConfiguration) error { + if len(bto.TokenStr) > 0 { + var err error + bto.Token, err = kubeadmapiv1alpha2.NewBootstrapTokenString(bto.TokenStr) + if err != nil { + return err + } + } + + // Set the token specified by the flags as the first and only token to create in case --config is not specified + cfg.BootstrapTokens = []kubeadmapiv1alpha2.BootstrapToken{*bto.BootstrapToken} + return nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/BUILD index da53a82de..4644b86b5 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/BUILD @@ -1,10 +1,4 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -15,6 +9,7 @@ go_library( "controlplane.go", "etcd.go", "kubeconfig.go", + "kubelet.go", "markmaster.go", "phase.go", "preflight.go", @@ -23,10 +18,13 @@ go_library( "util.go", ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases", + visibility = ["//visibility:public"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", + "//cmd/kubeadm/app/cmd/options:go_default_library", "//cmd/kubeadm/app/cmd/util:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", @@ -38,6 +36,7 @@ go_library( "//cmd/kubeadm/app/phases/controlplane:go_default_library", "//cmd/kubeadm/app/phases/etcd:go_default_library", "//cmd/kubeadm/app/phases/kubeconfig:go_default_library", + "//cmd/kubeadm/app/phases/kubelet:go_default_library", "//cmd/kubeadm/app/phases/markmaster:go_default_library", "//cmd/kubeadm/app/phases/selfhosting:go_default_library", "//cmd/kubeadm/app/phases/uploadconfig:go_default_library", @@ -46,8 +45,9 @@ go_library( "//cmd/kubeadm/app/util/apiclient:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//pkg/util/normalizer:go_default_library", + "//pkg/util/version:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -67,17 +67,18 @@ go_test( "controlplane_test.go", "etcd_test.go", "kubeconfig_test.go", + "kubelet_test.go", ], embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/install:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library", "//cmd/kubeadm/test:go_default_library", "//cmd/kubeadm/test/cmd:go_default_library", "//cmd/kubeadm/test/kubeconfig:go_default_library", "//pkg/util/node:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", ], ) @@ -93,4 +94,5 @@ filegroup( name = "all-srcs", srcs = [":package-srcs"], tags = ["automanaged"], + visibility = ["//visibility:public"], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons.go index c837113f9..26ce873ab 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons.go @@ -19,11 +19,13 @@ package phases import ( "strings" + "github.com/golang/glog" "github.com/spf13/cobra" clientset "k8s.io/client-go/kubernetes" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/features" @@ -32,30 +34,29 @@ import ( kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/util/normalizer" ) var ( allAddonsLongDesc = normalizer.LongDesc(` - Installs the kube-dns and the kube-proxys addons components via the API server. + Installs the CoreDNS and the kube-proxys addons components via the API server. Please note that although the DNS server is deployed, it will not be scheduled until CNI is installed. ` + cmdutil.AlphaDisclaimer) allAddonsExample = normalizer.Examples(` - # Installs the kube-dns and the kube-proxys addons components via the API server, + # Installs the CoreDNS and the kube-proxys addons components via the API server, # functionally equivalent to what installed by kubeadm init. kubeadm alpha phase selfhosting from-staticpods `) - kubednsAddonsLongDesc = normalizer.LongDesc(` - Installs the kube-dns addon components via the API server. + corednsAddonsLongDesc = normalizer.LongDesc(` + Installs the CoreDNS addon components via the API server. Please note that although the DNS server is deployed, it will not be scheduled until CNI is installed. ` + cmdutil.AlphaDisclaimer) kubeproxyAddonsLongDesc = normalizer.LongDesc(` - Installs the kube-proxy addon components via the API server. + Installs the kube-proxy addon components via the API server. ` + cmdutil.AlphaDisclaimer) ) @@ -80,6 +81,7 @@ func EnsureAllAddons(cfg *kubeadmapi.MasterConfiguration, client clientset.Inter proxyaddon.EnsureProxyAddon, } + glog.V(1).Infoln("[addon] installing all addons") for _, action := range addonActions { err := action(cfg, client) if err != nil { @@ -92,9 +94,9 @@ func EnsureAllAddons(cfg *kubeadmapi.MasterConfiguration, client clientset.Inter // getAddonsSubCommands returns sub commands for addons phase func getAddonsSubCommands() []*cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{} + cfg := &kubeadmapiv1alpha2.MasterConfiguration{} // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) var cfgPath, kubeConfigFile, featureGatesString string var subCmds []*cobra.Command @@ -114,9 +116,9 @@ func getAddonsSubCommands() []*cobra.Command { cmdFunc: EnsureAllAddons, }, { - use: "kube-dns", - short: "Installs the kube-dns addon to a Kubernetes cluster", - long: kubednsAddonsLongDesc, + use: "coredns", + short: "Installs the CoreDNS addon to a Kubernetes cluster", + long: corednsAddonsLongDesc, cmdFunc: dnsaddon.EnsureDNSAddon, }, { @@ -139,17 +141,17 @@ func getAddonsSubCommands() []*cobra.Command { // Add flags to the command cmd.Flags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster") - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental!") + cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental") cmd.Flags().StringVar(&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion, `Choose a specific Kubernetes version for the control plane`) cmd.Flags().StringVar(&cfg.ImageRepository, "image-repository", cfg.ImageRepository, `Choose a container registry to pull control plane images from`) if properties.use == "all" || properties.use == "kube-proxy" { - cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, `The IP address or DNS name the API server is accessible on`) + cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, `The IP address the API server is accessible on`) cmd.Flags().Int32Var(&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort, `The port the API server is accessible on`) cmd.Flags().StringVar(&cfg.Networking.PodSubnet, "pod-network-cidr", cfg.Networking.PodSubnet, `The range of IP addresses used for the Pod network`) } - if properties.use == "all" || properties.use == "kube-dns" { + if properties.use == "all" || properties.use == "coredns" { cmd.Flags().StringVar(&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain, `Alternative domain for services`) cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, `The range of IP address used for service VIPs`) cmd.Flags().StringVar(&featureGatesString, "feature-gates", featureGatesString, "A set of key=value pairs that describe feature gates for various features."+ @@ -162,7 +164,7 @@ func getAddonsSubCommands() []*cobra.Command { } // runAddonsCmdFunc creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters) -func runAddonsCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error, cfg *kubeadmapiext.MasterConfiguration, kubeConfigFile *string, cfgPath *string, featureGatesString *string) func(cmd *cobra.Command, args []string) { +func runAddonsCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error, cfg *kubeadmapiv1alpha2.MasterConfiguration, kubeConfigFile *string, cfgPath *string, featureGatesString *string) func(cmd *cobra.Command, args []string) { // the following statement build a clousure that wraps a call to a cmdFunc, binding // the function itself with the specific parameters of each sub command. @@ -180,7 +182,7 @@ func runAddonsCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration, client c } internalcfg := &kubeadmapi.MasterConfiguration{} - legacyscheme.Scheme.Convert(cfg, internalcfg, nil) + kubeadmscheme.Scheme.Convert(cfg, internalcfg, nil) client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) kubeadmutil.CheckErr(err) internalcfg, err = configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons_test.go index 424e31908..713e7f8db 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons_test.go @@ -19,9 +19,6 @@ package phases import ( "testing" - // required for triggering api machinery startup when running unit tests - _ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install" - cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd" ) @@ -59,7 +56,7 @@ func TestAddonsSubCommandsHasFlags(t *testing.T) { }, }, { - command: "kube-dns", + command: "coredns", additionalFlags: []string{ "service-dns-domain", "service-cidr", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/bootstraptoken.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/bootstraptoken.go index e9c237e15..02034e5d3 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/bootstraptoken.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/bootstraptoken.go @@ -18,30 +18,30 @@ package phases import ( "fmt" - "strings" + "github.com/golang/glog" "github.com/spf13/cobra" "github.com/spf13/pflag" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo" "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/util/normalizer" ) var ( allTokenLongDesc = normalizer.LongDesc(` - Bootstrap tokens are used for establishing bidirectional trust between a node joining + Bootstrap tokens are used for establishing bidirectional trust between a node joining the cluster and a the master node. This command makes all the configurations required to make bootstrap tokens works @@ -49,21 +49,21 @@ var ( ` + cmdutil.AlphaDisclaimer) allTokenExamples = normalizer.Examples(` - # Makes all the bootstrap token configurations and creates an initial token, functionally + # Makes all the bootstrap token configurations and creates an initial token, functionally # equivalent to what generated by kubeadm init. kubeadm alpha phase bootstrap-token all `) createTokenLongDesc = normalizer.LongDesc(` Creates a bootstrap token. If no token value is given, kubeadm will generate a random token instead. - + Alternatively, you can use kubeadm token. ` + cmdutil.AlphaDisclaimer) clusterInfoLongDesc = fmt.Sprintf(normalizer.LongDesc(` - Uploads the %q ConfigMap in the %q namespace, populating it with cluster information extracted from the - given kubeconfig file. The ConfigMap is used for the node bootstrap process in its initial phases, - before the client trusts the API server. + Uploads the %q ConfigMap in the %q namespace, populating it with cluster information extracted from the + given kubeconfig file. The ConfigMap is used for the node bootstrap process in its initial phases, + before the client trusts the API server. See online documentation about Authenticating with Bootstrap Tokens for more details. `+cmdutil.AlphaDisclaimer), bootstrapapi.ConfigMapClusterInfo, metav1.NamespacePublic) @@ -76,10 +76,10 @@ var ( ` + cmdutil.AlphaDisclaimer) nodeAutoApproveLongDesc = normalizer.LongDesc(` - Configures RBAC rules to allow the csrapprover controller to automatically approve + Configures RBAC rules to allow the csrapprover controller to automatically approve certificate signing requests generated by nodes joining the cluster. It configures also RBAC rules for certificates rotation (with auto approval of new certificates). - + See online documentation about TLS bootstrapping for more details. ` + cmdutil.AlphaDisclaimer) ) @@ -107,17 +107,18 @@ func NewCmdBootstrapToken() *cobra.Command { // NewSubCmdBootstrapTokenAll returns the Cobra command for running the token all sub-phase func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{ + cfg := &kubeadmapiv1alpha2.MasterConfiguration{ // KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.9.0", + KubernetesVersion: "v1.10.0", } // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) - var cfgPath, description string + var cfgPath string var skipTokenPrint bool + bto := options.NewBootstrapTokenOptions() cmd := &cobra.Command{ Use: "all", @@ -128,11 +129,14 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command { err := validation.ValidateMixedArguments(cmd.Flags()) kubeadmutil.CheckErr(err) + err = bto.ApplyTo(cfg) + kubeadmutil.CheckErr(err) + client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) kubeadmutil.CheckErr(err) // Creates the bootstap token - err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, skipTokenPrint) + err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, skipTokenPrint) kubeadmutil.CheckErr(err) // Create the cluster-info ConfigMap or update if it already exists @@ -158,24 +162,30 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command { } // Adds flags to the command - addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &skipTokenPrint) + addGenericFlags(cmd.Flags(), &cfgPath, &skipTokenPrint) + bto.AddTokenFlag(cmd.Flags()) + bto.AddTTLFlag(cmd.Flags()) + bto.AddUsagesFlag(cmd.Flags()) + bto.AddGroupsFlag(cmd.Flags()) + bto.AddDescriptionFlag(cmd.Flags()) return cmd } // NewSubCmdBootstrapToken returns the Cobra command for running the create token phase func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{ + cfg := &kubeadmapiv1alpha2.MasterConfiguration{ // KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.9.0", + KubernetesVersion: "v1.10.0", } // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) - var cfgPath, description string + var cfgPath string var skipTokenPrint bool + bto := options.NewBootstrapTokenOptions() cmd := &cobra.Command{ Use: "create", @@ -185,16 +195,24 @@ func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command { err := validation.ValidateMixedArguments(cmd.Flags()) kubeadmutil.CheckErr(err) + err = bto.ApplyTo(cfg) + kubeadmutil.CheckErr(err) + client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile) kubeadmutil.CheckErr(err) - err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, skipTokenPrint) + err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, skipTokenPrint) kubeadmutil.CheckErr(err) }, } // Adds flags to the command - addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &skipTokenPrint) + addGenericFlags(cmd.Flags(), &cfgPath, &skipTokenPrint) + bto.AddTokenFlag(cmd.Flags()) + bto.AddTTLFlag(cmd.Flags()) + bto.AddUsagesFlag(cmd.Flags()) + bto.AddGroupsFlag(cmd.Flags()) + bto.AddDescriptionFlag(cmd.Flags()) return cmd } @@ -277,30 +295,10 @@ func NewSubCmdNodeBootstrapTokenAutoApprove(kubeConfigFile *string) *cobra.Comma return cmd } -func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterConfiguration, cfgPath, description *string, skipTokenPrint *bool) { +func addGenericFlags(flagSet *pflag.FlagSet, cfgPath *string, skipTokenPrint *bool) { flagSet.StringVar( cfgPath, "config", *cfgPath, - "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)", - ) - flagSet.StringVar( - &cfg.Token, "token", cfg.Token, - "The token to use for establishing bidirectional trust between nodes and masters", - ) - flagSet.DurationVar( - &cfg.TokenTTL.Duration, "ttl", cfg.TokenTTL.Duration, - "The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire", - ) - flagSet.StringSliceVar( - &cfg.TokenUsages, "usages", cfg.TokenUsages, - fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s]", strings.Join(kubeadmconstants.DefaultTokenUsages, ",")), - ) - flagSet.StringSliceVar( - &cfg.TokenGroups, "groups", cfg.TokenGroups, - fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern), - ) - flagSet.StringVar( - description, "description", "The default bootstrap token generated by 'kubeadm init'.", - "A human friendly description of how this token is used.", + "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental", ) flagSet.BoolVar( skipTokenPrint, "skip-token-print", *skipTokenPrint, @@ -308,7 +306,7 @@ func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterCon ) } -func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, skipTokenPrint bool) error { +func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1alpha2.MasterConfiguration, skipTokenPrint bool) error { // This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg) @@ -316,19 +314,21 @@ func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfg return err } + glog.V(1).Infoln("[bootstraptoken] creating/updating token") // Creates or updates the token - if err := node.UpdateOrCreateToken(client, internalcfg.Token, false, internalcfg.TokenTTL.Duration, internalcfg.TokenUsages, internalcfg.TokenGroups, description); err != nil { + if err := node.UpdateOrCreateTokens(client, false, internalcfg.BootstrapTokens); err != nil { return err } - fmt.Println("[bootstraptoken] Bootstrap token Created") - fmt.Println("[bootstraptoken] You can now join any number of machines by running:") + fmt.Println("[bootstraptoken] bootstrap token created") + fmt.Println("[bootstraptoken] you can now join any number of machines by running:") - joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.Token, skipTokenPrint) - if err != nil { - return fmt.Errorf("failed to get join command: %v", err) + if len(internalcfg.BootstrapTokens) > 0 { + joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.BootstrapTokens[0].Token.String(), skipTokenPrint) + if err != nil { + return fmt.Errorf("failed to get join command: %v", err) + } + fmt.Println(joinCommand) } - fmt.Println(joinCommand) - return nil } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs.go index 7a9ffd74d..93b947505 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs.go @@ -22,14 +22,14 @@ import ( "github.com/spf13/cobra" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/util/normalizer" ) @@ -148,7 +148,7 @@ func NewCmdCerts() *cobra.Command { // getCertsSubCommands returns sub commands for certs phase func getCertsSubCommands(defaultKubernetesVersion string) []*cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{} + cfg := &kubeadmapiv1alpha2.MasterConfiguration{} // This is used for unit testing only... // If we wouldn't set this to something, the code would dynamically look up the version from the internet @@ -158,7 +158,7 @@ func getCertsSubCommands(defaultKubernetesVersion string) []*cobra.Command { } // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) var cfgPath string var subCmds []*cobra.Command @@ -256,12 +256,12 @@ func getCertsSubCommands(defaultKubernetesVersion string) []*cobra.Command { } // Add flags to the command - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") + cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental") cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where to save the certificates") if properties.use == "all" || properties.use == "apiserver" { cmd.Flags().StringVar(&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain, "Alternative domain for services, to use for the API server serving cert") cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, "Alternative range of IP address for service VIPs, from which derives the internal API server VIP that will be added to the API Server serving cert") - cmd.Flags().StringSliceVar(&cfg.APIServerCertSANs, "apiserver-cert-extra-sans", []string{}, "Optional extra altnames to use for the API server serving cert. Can be both IP addresses and dns names") + cmd.Flags().StringSliceVar(&cfg.APIServerCertSANs, "apiserver-cert-extra-sans", []string{}, "Optional extra altnames to use for the API server serving cert. Can be both IP addresses and DNS names") cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address the API server is accessible on, to use for the API server serving cert") } @@ -272,7 +272,7 @@ func getCertsSubCommands(defaultKubernetesVersion string) []*cobra.Command { } // runCmdFunc creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters) -func runCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration) error, cfgPath *string, cfg *kubeadmapiext.MasterConfiguration) func(cmd *cobra.Command, args []string) { +func runCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration) error, cfgPath *string, cfg *kubeadmapiv1alpha2.MasterConfiguration) func(cmd *cobra.Command, args []string) { // the following statement build a closure that wraps a call to a cmdFunc, binding // the function itself with the specific parameters of each sub command. diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs_test.go index 31b9b49ce..32b900274 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs_test.go @@ -21,9 +21,6 @@ import ( "os" "testing" - // required for triggering api machinery startup when running unit tests - _ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil" @@ -34,7 +31,7 @@ import ( ) // phaseTestK8sVersion is a fake kubernetes version to use when testing -const phaseTestK8sVersion = "v1.9.0" +const phaseTestK8sVersion = "v1.10.0" func TestCertsSubCommandsHasFlags(t *testing.T) { @@ -257,9 +254,9 @@ func TestSubCmdCertsCreateFilesWithConfigFile(t *testing.T) { certdir := tmpdir cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, - CertificatesDir: certdir, - NodeName: "valid-node-name", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, + CertificatesDir: certdir, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"}, } configPath := testutil.SetupMasterConfigurationFile(t, tmpdir, cfg) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane.go index 96f261087..13ebf91e4 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane.go @@ -24,7 +24,8 @@ import ( utilflag "k8s.io/apiserver/pkg/util/flag" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -32,7 +33,6 @@ import ( controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/util/normalizer" ) @@ -79,7 +79,7 @@ func NewCmdControlplane() *cobra.Command { // getControlPlaneSubCommands returns sub commands for Controlplane phase func getControlPlaneSubCommands(outDir, defaultKubernetesVersion string) []*cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{} + cfg := &kubeadmapiv1alpha2.MasterConfiguration{} // This is used for unit testing only... // If we wouldn't set this to something, the code would dynamically look up the version from the internet @@ -89,7 +89,7 @@ func getControlPlaneSubCommands(outDir, defaultKubernetesVersion string) []*cobr } // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) var cfgPath, featureGatesString string var subCmds []*cobra.Command @@ -110,19 +110,19 @@ func getControlPlaneSubCommands(outDir, defaultKubernetesVersion string) []*cobr }, { use: "apiserver", - short: "Generates the API server static Pod manifest.", + short: "Generates the API server static Pod manifest", long: apiServerControlplaneLongDesc, cmdFunc: controlplanephase.CreateAPIServerStaticPodManifestFile, }, { use: "controller-manager", - short: "Generates the controller-manager static Pod manifest.", + short: "Generates the controller-manager static Pod manifest", long: controllerManagerControlplaneLongDesc, cmdFunc: controlplanephase.CreateControllerManagerStaticPodManifestFile, }, { use: "scheduler", - short: "Generates the scheduler static Pod manifest.", + short: "Generates the scheduler static Pod manifest", long: schedulerControlplaneLongDesc, cmdFunc: controlplanephase.CreateSchedulerStaticPodManifestFile, }, @@ -160,7 +160,7 @@ func getControlPlaneSubCommands(outDir, defaultKubernetesVersion string) []*cobr cmd.Flags().Var(utilflag.NewMapStringString(&cfg.SchedulerExtraArgs), "scheduler-extra-args", "A set of extra flags to pass to the Scheduler or override default ones in form of =") } - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") + cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental") subCmds = append(subCmds, cmd) } @@ -169,7 +169,7 @@ func getControlPlaneSubCommands(outDir, defaultKubernetesVersion string) []*cobr } // runCmdControlPlane creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters) -func runCmdControlPlane(cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration) error, outDir, cfgPath *string, featureGatesString *string, cfg *kubeadmapiext.MasterConfiguration) func(cmd *cobra.Command, args []string) { +func runCmdControlPlane(cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration) error, outDir, cfgPath *string, featureGatesString *string, cfg *kubeadmapiv1alpha2.MasterConfiguration) func(cmd *cobra.Command, args []string) { // the following statement build a closure that wraps a call to a cmdFunc, binding // the function itself with the specific parameters of each sub command. diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane_test.go index 6333263df..c8c5d3b8e 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane_test.go @@ -21,9 +21,6 @@ import ( "os" "testing" - // required for triggering api machinery startup when running unit tests - _ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install" - testutil "k8s.io/kubernetes/cmd/kubeadm/test" cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd" ) @@ -93,7 +90,7 @@ func TestControlPlaneCreateFilesWithFlags(t *testing.T) { { command: "all", additionalFlags: []string{ - "--kubernetes-version=v1.9.0", + "--kubernetes-version=v1.10.0", "--apiserver-advertise-address=1.2.3.4", "--apiserver-bind-port=6443", "--service-cidr=1.2.3.4/16", @@ -108,7 +105,7 @@ func TestControlPlaneCreateFilesWithFlags(t *testing.T) { { command: "apiserver", additionalFlags: []string{ - "--kubernetes-version=v1.9.0", + "--kubernetes-version=v1.10.0", "--apiserver-advertise-address=1.2.3.4", "--apiserver-bind-port=6443", "--service-cidr=1.2.3.4/16", @@ -118,7 +115,7 @@ func TestControlPlaneCreateFilesWithFlags(t *testing.T) { { command: "controller-manager", additionalFlags: []string{ - "--kubernetes-version=v1.9.0", + "--kubernetes-version=v1.10.0", "--pod-network-cidr=1.2.3.4/16", }, expectedFiles: []string{"kube-controller-manager.yaml"}, @@ -126,7 +123,7 @@ func TestControlPlaneCreateFilesWithFlags(t *testing.T) { { command: "scheduler", additionalFlags: []string{ - "--kubernetes-version=v1.9.0", + "--kubernetes-version=v1.10.0", }, expectedFiles: []string{"kube-scheduler.yaml"}, }, diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd.go index 86501f1c8..f515604f7 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd.go @@ -22,11 +22,11 @@ import ( "github.com/spf13/cobra" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/util/normalizer" ) @@ -61,7 +61,7 @@ func NewCmdEtcd() *cobra.Command { // getEtcdSubCommands returns sub commands for etcd phase func getEtcdSubCommands(outDir, defaultKubernetesVersion string) []*cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{} + cfg := &kubeadmapiv1alpha2.MasterConfiguration{} // This is used for unit testing only... // If we wouldn't set this to something, the code would dynamically look up the version from the internet @@ -71,7 +71,7 @@ func getEtcdSubCommands(outDir, defaultKubernetesVersion string) []*cobra.Comman } // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) var cfgPath string var subCmds []*cobra.Command @@ -101,7 +101,7 @@ func getEtcdSubCommands(outDir, defaultKubernetesVersion string) []*cobra.Comman // Add flags to the command cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, `The path where certificates are stored`) - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") + cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental") subCmds = append(subCmds, cmd) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd_test.go index 90a82f96d..cc12e3c82 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd_test.go @@ -21,9 +21,6 @@ import ( "os" "testing" - // required for triggering api machinery startup when running unit tests - _ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install" - testutil "k8s.io/kubernetes/cmd/kubeadm/test" cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd" ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig.go index c7ca5437f..7a0dcb0ce 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig.go @@ -24,11 +24,11 @@ import ( "github.com/spf13/cobra" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/util/normalizer" ) @@ -51,9 +51,9 @@ var ( `+cmdutil.AlphaDisclaimer), kubeadmconstants.AdminKubeConfigFileName) kubeletKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(` - Generates the kubeconfig file for the kubelet to use and saves it to %s file. + Generates the kubeconfig file for the kubelet to use and saves it to %s file. - Please note that this should *only* be used for bootstrapping purposes. After your control plane is up, + Please note that this should *only* be used for bootstrapping purposes. After your control plane is up, you should request all kubelet credentials from the CSR API. `+cmdutil.AlphaDisclaimer), filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)) @@ -90,7 +90,7 @@ func NewCmdKubeConfig(out io.Writer) *cobra.Command { // getKubeConfigSubCommands returns sub commands for kubeconfig phase func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion string) []*cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{} + cfg := &kubeadmapiv1alpha2.MasterConfiguration{} // This is used for unit testing only... // If we wouldn't set this to something, the code would dynamically look up the version from the internet @@ -100,9 +100,10 @@ func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion st } // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) var cfgPath, token, clientName string + var organizations []string var subCmds []*cobra.Command subCmdProperties := []struct { @@ -127,7 +128,7 @@ func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion st }, { use: "kubelet", - short: "Generates a kubeconfig file for the kubelet to use. Please note that this should be used *only* for bootstrapping purposes.", + short: "Generates a kubeconfig file for the kubelet to use. Please note that this should be used *only* for bootstrapping purposes", long: kubeletKubeconfigLongDesc, cmdFunc: kubeconfigphase.CreateKubeletKubeConfigFile, }, @@ -159,7 +160,7 @@ func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion st } // Otherwise, write a kubeconfig file with a generate client cert - return kubeconfigphase.WriteKubeConfigWithClientCert(out, cfg, clientName) + return kubeconfigphase.WriteKubeConfigWithClientCert(out, cfg, clientName, organizations) }, }, } @@ -176,18 +177,19 @@ func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion st // Add flags to the command if properties.use != "user" { - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") + cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental") } cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where certificates are stored") cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address the API server is accessible on") cmd.Flags().Int32Var(&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort, "The port the API server is accessible on") - cmd.Flags().StringVar(&outDir, "kubeconfig-dir", outDir, "The port where to save the kubeconfig file") + cmd.Flags().StringVar(&outDir, "kubeconfig-dir", outDir, "The path where to save the kubeconfig file") if properties.use == "all" || properties.use == "kubelet" { - cmd.Flags().StringVar(&cfg.NodeName, "node-name", cfg.NodeName, `The node name that should be used for the kubelet client certificate`) + cmd.Flags().StringVar(&cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, `The node name that should be used for the kubelet client certificate`) } if properties.use == "user" { - cmd.Flags().StringVar(&token, "token", token, "The token that should be used as the authentication mechanism for this kubeconfig (instead of client certificates)") + cmd.Flags().StringVar(&token, "token", token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates") cmd.Flags().StringVar(&clientName, "client-name", clientName, "The name of user. It will be used as the CN if client certificates are created") + cmd.Flags().StringSliceVar(&organizations, "org", organizations, "The orgnizations of the client certificate. It will be used as the O if client certificates are created") } subCmds = append(subCmds, cmd) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go index 089147ada..f74538a6a 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go @@ -23,9 +23,6 @@ import ( "path/filepath" "testing" - // required for triggering api machinery startup when running unit tests - _ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install" - "k8s.io/client-go/tools/clientcmd" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -196,7 +193,7 @@ func TestKubeConfigSubCommandsThatCreateFilesWithFlags(t *testing.T) { // reads generated files config, err := clientcmd.LoadFromFile(filepath.Join(tmpdir, file)) if err != nil { - t.Errorf("Couldn't load generated kubeconfig file: %v", err) + t.Errorf("couldn't load generated kubeconfig file: %v", err) } // checks that CLI flags are properly propagated and kubeconfig properties are correct @@ -280,9 +277,9 @@ func TestKubeConfigSubCommandsThatCreateFilesWithConfigFile(t *testing.T) { // Adds a master configuration file cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, - CertificatesDir: pkidir, - NodeName: "valid-node-name", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234}, + CertificatesDir: pkidir, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"}, } cfgPath := testutil.SetupMasterConfigurationFile(t, tmpdir, cfg) @@ -302,7 +299,7 @@ func TestKubeConfigSubCommandsThatCreateFilesWithConfigFile(t *testing.T) { // reads generated files config, err := clientcmd.LoadFromFile(filepath.Join(tmpdir, file)) if err != nil { - t.Errorf("Couldn't load generated kubeconfig file: %v", err) + t.Errorf("couldn't load generated kubeconfig file: %v", err) } // checks that config file properties are properly propagated and kubeconfig properties are correct @@ -371,7 +368,7 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) { // reads kubeconfig written to stdout config, err := clientcmd.Load(buf.Bytes()) if err != nil { - t.Errorf("Couldn't read kubeconfig file from buffer: %v", err) + t.Errorf("couldn't read kubeconfig file from buffer: %v", err) continue } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubelet.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubelet.go new file mode 100644 index 000000000..f18171370 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubelet.go @@ -0,0 +1,334 @@ +/* +Copyright 2018 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 phases + +import ( + "fmt" + "io/ioutil" + + "github.com/spf13/cobra" + + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" + cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" + "k8s.io/kubernetes/cmd/kubeadm/app/preflight" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" + kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" + "k8s.io/kubernetes/pkg/util/normalizer" + "k8s.io/kubernetes/pkg/util/version" + utilsexec "k8s.io/utils/exec" +) + +const ( + // TODO: Figure out how to get these constants from the API machinery + masterConfig = "MasterConfiguration" + nodeConfig = "NodeConfiguration" +) + +var ( + kubeletWriteEnvFileLongDesc = normalizer.LongDesc(` + Writes an environment file with flags that should be passed to the kubelet executing on the master or node. + This --config flag can either consume a MasterConfiguration object or a NodeConfiguration one, as this + function is used for both "kubeadm init" and "kubeadm join". + ` + cmdutil.AlphaDisclaimer) + + kubeletWriteEnvFileExample = normalizer.Examples(` + # Writes a dynamic environment file with kubelet flags from a MasterConfiguration file. + kubeadm alpha phase kubelet write-env-file --config masterconfig.yaml + + # Writes a dynamic environment file with kubelet flags from a NodeConfiguration file. + kubeadm alpha phase kubelet write-env-file --config nodeConfig.yaml + `) + + kubeletConfigUploadLongDesc = normalizer.LongDesc(` + Uploads kubelet configuration extracted from the kubeadm MasterConfiguration object to a ConfigMap + of the form kubelet-config-1.X in the cluster, where X is the minor version of the current (API Server) Kubernetes version. + ` + cmdutil.AlphaDisclaimer) + + kubeletConfigUploadExample = normalizer.Examples(` + # Uploads the kubelet configuration from the kubeadm Config file to a ConfigMap in the cluster. + kubeadm alpha phase kubelet config upload --config kubeadm.yaml + `) + + kubeletConfigDownloadLongDesc = normalizer.LongDesc(` + Downloads the kubelet configuration from a ConfigMap of the form "kubelet-config-1.X" in the cluster, + where X is the minor version of the kubelet. Either kubeadm autodetects the kubelet version by exec-ing + "kubelet --version" or respects the --kubelet-version parameter. + ` + cmdutil.AlphaDisclaimer) + + kubeletConfigDownloadExample = normalizer.Examples(` + # Downloads the kubelet configuration from the ConfigMap in the cluster. Autodetects the kubelet version. + kubeadm alpha phase kubelet config download + + # Downloads the kubelet configuration from the ConfigMap in the cluster. Uses a specific desired kubelet version. + kubeadm alpha phase kubelet config download --kubelet-version v1.11.0 + `) + + kubeletConfigWriteToDiskLongDesc = normalizer.LongDesc(` + Writes kubelet configuration to disk, based on the kubeadm configuration passed via "--config". + ` + cmdutil.AlphaDisclaimer) + + kubeletConfigWriteToDiskExample = normalizer.Examples(` + # Extracts the kubelet configuration from a kubeadm configuration file + kubeadm alpha phase kubelet config write-to-disk --config kubeadm.yaml + `) + + kubeletConfigEnableDynamicLongDesc = normalizer.LongDesc(` + Enables or updates dynamic kubelet configuration for a Node, against the kubelet-config-1.X ConfigMap in the cluster, + where X is the minor version of the desired kubelet version. + + WARNING: This feature is still experimental, and disabled by default. Enable only if you know what you are doing, as it + may have surprising side-effects at this stage. + + ` + cmdutil.AlphaDisclaimer) + + kubeletConfigEnableDynamicExample = normalizer.Examples(` + # Enables dynamic kubelet configuration for a Node. + kubeadm alpha phase kubelet enable-dynamic-config --node-name node-1 --kubelet-version v1.11.0 + + WARNING: This feature is still experimental, and disabled by default. Enable only if you know what you are doing, as it + may have surprising side-effects at this stage. + `) +) + +// NewCmdKubelet returns command for `kubeadm phase kubelet` +func NewCmdKubelet() *cobra.Command { + cmd := &cobra.Command{ + Use: "kubelet", + Short: "Commands related to handling the kubelet.", + Long: cmdutil.MacroCommandLongDescription, + } + + cmd.AddCommand(NewCmdKubeletConfig()) + cmd.AddCommand(NewCmdKubeletWriteEnvFile()) + return cmd +} + +// NewCmdKubeletWriteEnvFile calls cobra.Command for writing the dynamic kubelet env file based on a MasterConfiguration or NodeConfiguration object +func NewCmdKubeletWriteEnvFile() *cobra.Command { + var cfgPath string + + cmd := &cobra.Command{ + Use: "write-env-file", + Short: "Writes an environment file with runtime flags for the kubelet.", + Long: kubeletWriteEnvFileLongDesc, + Example: kubeletWriteEnvFileExample, + Run: func(cmd *cobra.Command, args []string) { + err := RunKubeletWriteEnvFile(cfgPath) + kubeadmutil.CheckErr(err) + }, + } + + options.AddConfigFlag(cmd.Flags(), &cfgPath) + return cmd +} + +// RunKubeletWriteEnvFile is the function that is run when "kubeadm phase kubelet write-env-file" is executed +func RunKubeletWriteEnvFile(cfgPath string) error { + b, err := ioutil.ReadFile(cfgPath) + if err != nil { + return err + } + + gvk, err := kubeadmutil.GroupVersionKindFromBytes(b, kubeadmscheme.Codecs) + if err != nil { + return err + } + + var nodeRegistrationObj *kubeadmapi.NodeRegistrationOptions + var featureGates map[string]bool + var registerWithTaints bool + switch gvk.Kind { + case masterConfig: + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + if err != nil { + return err + } + nodeRegistrationObj = &internalcfg.NodeRegistration + featureGates = internalcfg.FeatureGates + registerWithTaints = false + case nodeConfig: + internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.NodeConfiguration{}) + if err != nil { + return err + } + nodeRegistrationObj = &internalcfg.NodeRegistration + featureGates = internalcfg.FeatureGates + registerWithTaints = true + default: + if err != nil { + return fmt.Errorf("Didn't recognize type with GroupVersionKind: %v", gvk) + } + } + if nodeRegistrationObj == nil { + return fmt.Errorf("couldn't load nodeRegistration field from config file") + } + + if err := kubeletphase.WriteKubeletDynamicEnvFile(nodeRegistrationObj, featureGates, registerWithTaints, constants.KubeletRunDirectory); err != nil { + return fmt.Errorf("error writing a dynamic environment file for the kubelet: %v", err) + } + return nil +} + +// NewCmdKubeletConfig returns command for `kubeadm phase kubelet config` +func NewCmdKubeletConfig() *cobra.Command { + cmd := &cobra.Command{ + Use: "config", + Short: "Handles kubelet configuration.", + Long: cmdutil.MacroCommandLongDescription, + } + + cmd.AddCommand(NewCmdKubeletConfigUpload()) + cmd.AddCommand(NewCmdKubeletConfigDownload()) + cmd.AddCommand(NewCmdKubeletConfigWriteToDisk()) + cmd.AddCommand(NewCmdKubeletConfigEnableDynamic()) + return cmd +} + +// NewCmdKubeletConfigUpload calls cobra.Command for uploading dynamic kubelet configuration +func NewCmdKubeletConfigUpload() *cobra.Command { + var cfgPath string + kubeConfigFile := constants.GetAdminKubeConfigPath() + + cmd := &cobra.Command{ + Use: "upload", + Short: "Uploads kubelet configuration to a ConfigMap based on a kubeadm MasterConfiguration file.", + Long: kubeletConfigUploadLongDesc, + Example: kubeletConfigUploadExample, + Run: func(cmd *cobra.Command, args []string) { + if len(cfgPath) == 0 { + kubeadmutil.CheckErr(fmt.Errorf("The --config argument is required")) + } + + // This call returns the ready-to-use configuration based on the configuration file + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + kubeadmutil.CheckErr(err) + + client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile) + kubeadmutil.CheckErr(err) + + err = kubeletphase.CreateConfigMap(internalcfg, client) + kubeadmutil.CheckErr(err) + }, + } + + options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile) + options.AddConfigFlag(cmd.Flags(), &cfgPath) + return cmd +} + +// NewCmdKubeletConfigDownload calls cobra.Command for downloading the kubelet configuration from the kubelet-config-1.X ConfigMap in the cluster +func NewCmdKubeletConfigDownload() *cobra.Command { + var kubeletVersionStr string + // TODO: Be smarter about this and be able to load multiple kubeconfig files in different orders of precedence + kubeConfigFile := constants.GetKubeletKubeConfigPath() + + cmd := &cobra.Command{ + Use: "download", + Short: "Downloads the kubelet configuration from the cluster ConfigMap kubelet-config-1.X, where X is the minor version of the kubelet.", + Long: kubeletConfigDownloadLongDesc, + Example: kubeletConfigDownloadExample, + Run: func(cmd *cobra.Command, args []string) { + kubeletVersion, err := getKubeletVersion(kubeletVersionStr) + kubeadmutil.CheckErr(err) + + client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile) + kubeadmutil.CheckErr(err) + + err = kubeletphase.DownloadConfig(client, kubeletVersion, constants.KubeletRunDirectory) + kubeadmutil.CheckErr(err) + }, + } + + options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile) + cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet. Defaults to being autodetected from 'kubelet --version'.") + return cmd +} + +func getKubeletVersion(kubeletVersionStr string) (*version.Version, error) { + if len(kubeletVersionStr) > 0 { + return version.ParseSemantic(kubeletVersionStr) + } + return preflight.GetKubeletVersion(utilsexec.New()) +} + +// NewCmdKubeletConfigWriteToDisk calls cobra.Command for writing init kubelet configuration +func NewCmdKubeletConfigWriteToDisk() *cobra.Command { + var cfgPath string + cmd := &cobra.Command{ + Use: "write-to-disk", + Short: "Writes kubelet configuration to disk, either based on the --config argument.", + Long: kubeletConfigWriteToDiskLongDesc, + Example: kubeletConfigWriteToDiskExample, + Run: func(cmd *cobra.Command, args []string) { + if len(cfgPath) == 0 { + kubeadmutil.CheckErr(fmt.Errorf("The --config argument is required")) + } + + // This call returns the ready-to-use configuration based on the configuration file + internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + kubeadmutil.CheckErr(err) + + err = kubeletphase.WriteConfigToDisk(internalcfg.KubeletConfiguration.BaseConfig, constants.KubeletRunDirectory) + kubeadmutil.CheckErr(err) + }, + } + + options.AddConfigFlag(cmd.Flags(), &cfgPath) + return cmd +} + +// NewCmdKubeletConfigEnableDynamic calls cobra.Command for enabling dynamic kubelet configuration on node +// This feature is still in alpha and an experimental state +func NewCmdKubeletConfigEnableDynamic() *cobra.Command { + var nodeName, kubeletVersionStr string + kubeConfigFile := constants.GetAdminKubeConfigPath() + + cmd := &cobra.Command{ + Use: "enable-dynamic", + Short: "EXPERIMENTAL: Enables or updates dynamic kubelet configuration for a Node", + Long: kubeletConfigEnableDynamicLongDesc, + Example: kubeletConfigEnableDynamicExample, + Run: func(cmd *cobra.Command, args []string) { + if len(nodeName) == 0 { + kubeadmutil.CheckErr(fmt.Errorf("The --node-name argument is required")) + } + if len(kubeletVersionStr) == 0 { + kubeadmutil.CheckErr(fmt.Errorf("The --kubelet-version argument is required")) + } + + kubeletVersion, err := version.ParseSemantic(kubeletVersionStr) + kubeadmutil.CheckErr(err) + + client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile) + kubeadmutil.CheckErr(err) + + err = kubeletphase.EnableDynamicConfigForNode(client, nodeName, kubeletVersion) + kubeadmutil.CheckErr(err) + }, + } + + options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile) + cmd.Flags().StringVar(&nodeName, "node-name", nodeName, "Name of the node that should enable the dynamic kubelet configuration") + cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet") + return cmd +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubelet_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubelet_test.go new file mode 100644 index 000000000..4abfdd5d7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubelet_test.go @@ -0,0 +1,82 @@ +/* +Copyright 2018 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 phases + +import ( + "testing" + + "github.com/spf13/cobra" + + cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd" +) + +func TestKubeletSubCommandsHasFlags(t *testing.T) { + subCmds := []*cobra.Command{ + NewCmdKubeletWriteEnvFile(), + NewCmdKubeletConfigUpload(), + NewCmdKubeletConfigDownload(), + NewCmdKubeletConfigWriteToDisk(), + NewCmdKubeletConfigEnableDynamic(), + } + + commonFlags := []string{} + + var tests = []struct { + command string + additionalFlags []string + }{ + { + command: "write-env-file", + additionalFlags: []string{ + "config", + }, + }, + { + command: "upload", + additionalFlags: []string{ + "kubeconfig", + "config", + }, + }, + { + command: "download", + additionalFlags: []string{ + "kubeconfig", + "kubelet-version", + }, + }, + { + command: "write-to-disk", + additionalFlags: []string{ + "config", + }, + }, + { + command: "enable-dynamic", + additionalFlags: []string{ + "kubeconfig", + "node-name", + "kubelet-version", + }, + }, + } + + for _, test := range tests { + expectedFlags := append(commonFlags, test.additionalFlags...) + cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/markmaster.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/markmaster.go index 7457834f2..9ba104e08 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/markmaster.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/markmaster.go @@ -19,14 +19,14 @@ package phases import ( "github.com/spf13/cobra" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/util/normalizer" ) @@ -47,14 +47,14 @@ var ( // NewCmdMarkMaster returns the Cobra command for running the mark-master phase func NewCmdMarkMaster() *cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{ + cfg := &kubeadmapiv1alpha2.MasterConfiguration{ // KubernetesVersion is not used by mark master, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.9.0", + KubernetesVersion: "v1.10.0", } // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) var cfgPath, kubeConfigFile string cmd := &cobra.Command{ @@ -75,14 +75,14 @@ func NewCmdMarkMaster() *cobra.Command { client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile) kubeadmutil.CheckErr(err) - err = markmasterphase.MarkMaster(client, internalcfg.NodeName, !internalcfg.NoTaintMaster) + err = markmasterphase.MarkMaster(client, internalcfg.NodeRegistration.Name, internalcfg.NodeRegistration.Taints) kubeadmutil.CheckErr(err) }, } cmd.Flags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster") - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") - cmd.Flags().StringVar(&cfg.NodeName, "node-name", cfg.NodeName, `The node name to which label and taints should apply`) + cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental") + cmd.Flags().StringVar(&cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, `The node name to which label and taints should apply`) return cmd } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/phase.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/phase.go index 2f5a42588..1ecd0a9ad 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/phase.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/phase.go @@ -36,6 +36,7 @@ func NewCmdPhase(out io.Writer) *cobra.Command { cmd.AddCommand(NewCmdCerts()) cmd.AddCommand(NewCmdControlplane()) cmd.AddCommand(NewCmdEtcd()) + cmd.AddCommand(NewCmdKubelet()) cmd.AddCommand(NewCmdKubeConfig(out)) cmd.AddCommand(NewCmdMarkMaster()) cmd.AddCommand(NewCmdPreFlight()) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/selfhosting.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/selfhosting.go index 9bf6530ee..b9152bdfe 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/selfhosting.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/selfhosting.go @@ -23,7 +23,8 @@ import ( "github.com/spf13/cobra" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -33,7 +34,6 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/util/normalizer" ) @@ -70,9 +70,9 @@ func NewCmdSelfhosting() *cobra.Command { // getSelfhostingSubCommand returns sub commands for Selfhosting phase func getSelfhostingSubCommand() *cobra.Command { - cfg := &kubeadmapiext.MasterConfiguration{} + cfg := &kubeadmapiv1alpha2.MasterConfiguration{} // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) var cfgPath, kubeConfigFile, featureGatesString string @@ -111,7 +111,7 @@ func getSelfhostingSubCommand() *cobra.Command { // Add flags to the command // flags bound to the configuration object cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, `The path where certificates are stored`) - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental!") + cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental") cmd.Flags().StringVar(&featureGatesString, "feature-gates", featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+ "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/uploadconfig.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/uploadconfig.go index ec11c2f33..99ebbc2f9 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/uploadconfig.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/uploadconfig.go @@ -22,7 +22,7 @@ import ( "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" @@ -57,12 +57,12 @@ func NewCmdUploadConfig() *cobra.Command { Aliases: []string{"uploadconfig"}, Run: func(_ *cobra.Command, args []string) { if len(cfgPath) == 0 { - kubeadmutil.CheckErr(fmt.Errorf("The --config flag is mandatory")) + kubeadmutil.CheckErr(fmt.Errorf("the --config flag is mandatory")) } client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile) kubeadmutil.CheckErr(err) - defaultcfg := &kubeadmapiext.MasterConfiguration{} + defaultcfg := &kubeadmapiv1alpha2.MasterConfiguration{} internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg) kubeadmutil.CheckErr(err) @@ -72,7 +72,7 @@ func NewCmdUploadConfig() *cobra.Command { } cmd.Flags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster") - cmd.Flags().StringVar(&cfgPath, "config", "", "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental!") + cmd.Flags().StringVar(&cfgPath, "config", "", "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental") return cmd } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/util.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/util.go index 92be3a187..9221ee7f6 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/util.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/util.go @@ -20,14 +20,14 @@ import ( "github.com/spf13/cobra" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" ) // runCmdPhase creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters) -func runCmdPhase(cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration) error, outDir, cfgPath *string, cfg *kubeadmapiext.MasterConfiguration) func(cmd *cobra.Command, args []string) { +func runCmdPhase(cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration) error, outDir, cfgPath *string, cfg *kubeadmapiv1alpha2.MasterConfiguration) func(cmd *cobra.Command, args []string) { // the following statement build a closure that wraps a call to a cmdFunc, binding // the function itself with the specific parameters of each sub command. diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go index 0a06dd65c..0dfee95e7 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go @@ -17,6 +17,8 @@ limitations under the License. package cmd import ( + "bufio" + "errors" "fmt" "io" "os" @@ -24,10 +26,11 @@ import ( "path/filepath" "strings" + "github.com/golang/glog" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/util/sets" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" @@ -37,11 +40,12 @@ import ( ) // NewCmdReset returns the "kubeadm reset" command -func NewCmdReset(out io.Writer) *cobra.Command { +func NewCmdReset(in io.Reader, out io.Writer) *cobra.Command { var skipPreFlight bool var certsDir string var criSocketPath string var ignorePreflightErrors []string + var forceReset bool cmd := &cobra.Command{ Use: "reset", @@ -50,7 +54,7 @@ func NewCmdReset(out io.Writer) *cobra.Command { ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight) kubeadmutil.CheckErr(err) - r, err := NewReset(ignorePreflightErrorsSet, certsDir, criSocketPath) + r, err := NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath) kubeadmutil.CheckErr(err) kubeadmutil.CheckErr(r.Run(out)) }, @@ -67,7 +71,7 @@ func NewCmdReset(out io.Writer) *cobra.Command { cmd.PersistentFlags().MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-preflight-errors=all") cmd.PersistentFlags().StringVar( - &certsDir, "cert-dir", kubeadmapiext.DefaultCertificatesDir, + &certsDir, "cert-dir", kubeadmapiv1alpha2.DefaultCertificatesDir, "The path to the directory where the certificates are stored. If specified, clean this directory.", ) @@ -76,6 +80,11 @@ func NewCmdReset(out io.Writer) *cobra.Command { "The path to the CRI socket to use with crictl when cleaning up containers.", ) + cmd.PersistentFlags().BoolVarP( + &forceReset, "force", "f", false, + "Reset the node without prompting for confirmation.", + ) + return cmd } @@ -86,9 +95,21 @@ type Reset struct { } // NewReset instantiate Reset struct -func NewReset(ignorePreflightErrors sets.String, certsDir, criSocketPath string) (*Reset, error) { - fmt.Println("[preflight] Running pre-flight checks.") +func NewReset(in io.Reader, ignorePreflightErrors sets.String, forceReset bool, certsDir, criSocketPath string) (*Reset, error) { + if !forceReset { + fmt.Println("[reset] WARNING: changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.") + fmt.Print("[reset] are you sure you want to proceed? [y/N]: ") + s := bufio.NewScanner(in) + s.Scan() + if err := s.Err(); err != nil { + return nil, err + } + if strings.ToLower(s.Text()) != "y" { + return nil, errors.New("Aborted reset operation") + } + } + fmt.Println("[preflight] running pre-flight checks") if err := preflight.RunRootCheckOnly(ignorePreflightErrors); err != nil { return nil, err } @@ -103,27 +124,30 @@ func NewReset(ignorePreflightErrors sets.String, certsDir, criSocketPath string) func (r *Reset) Run(out io.Writer) error { // Try to stop the kubelet service + glog.V(1).Infof("[reset] getting init system") initSystem, err := initsystem.GetInitSystem() if err != nil { - fmt.Println("[reset] WARNING: The kubelet service could not be stopped by kubeadm. Unable to detect a supported init system!") - fmt.Println("[reset] WARNING: Please ensure kubelet is stopped manually.") + glog.Warningln("[reset] the kubelet service could not be stopped by kubeadm. Unable to detect a supported init system!") + glog.Warningln("[reset] please ensure kubelet is stopped manually") } else { - fmt.Println("[reset] Stopping the kubelet service.") + fmt.Println("[reset] stopping the kubelet service") if err := initSystem.ServiceStop("kubelet"); err != nil { - fmt.Printf("[reset] WARNING: The kubelet service could not be stopped by kubeadm: [%v]\n", err) - fmt.Println("[reset] WARNING: Please ensure kubelet is stopped manually.") + glog.Warningf("[reset] the kubelet service could not be stopped by kubeadm: [%v]\n", err) + glog.Warningln("[reset] please ensure kubelet is stopped manually") } } // Try to unmount mounted directories under /var/lib/kubelet in order to be able to remove the /var/lib/kubelet directory later - fmt.Printf("[reset] Unmounting mounted directories in %q\n", "/var/lib/kubelet") + fmt.Printf("[reset] unmounting mounted directories in %q\n", "/var/lib/kubelet") umountDirsCmd := "awk '$2 ~ path {print $2}' path=/var/lib/kubelet /proc/mounts | xargs -r umount" + + glog.V(1).Infof("[reset] executing command %q", umountDirsCmd) umountOutputBytes, err := exec.Command("sh", "-c", umountDirsCmd).Output() if err != nil { - fmt.Printf("[reset] Failed to unmount mounted directories in /var/lib/kubelet: %s\n", string(umountOutputBytes)) + glog.Errorf("[reset] failed to unmount mounted directories in /var/lib/kubelet: %s\n", string(umountOutputBytes)) } - fmt.Println("[reset] Removing kubernetes-managed containers.") + fmt.Println("[reset] removing kubernetes-managed containers") dockerCheck := preflight.ServiceCheck{Service: "docker", CheckIfActive: true} execer := utilsexec.New() @@ -132,23 +156,27 @@ func (r *Reset) Run(out io.Writer) error { dirsToClean := []string{"/var/lib/kubelet", "/etc/cni/net.d", "/var/lib/dockershim", "/var/run/kubernetes"} // Only clear etcd data when the etcd manifest is found. In case it is not found, we must assume that the user - // provided external etcd endpoints. In that case, it is his own responsibility to reset etcd + // provided external etcd endpoints. In that case, it is their own responsibility to reset etcd etcdManifestPath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName, "etcd.yaml") + glog.V(1).Infof("[reset] checking for etcd manifest") if _, err := os.Stat(etcdManifestPath); err == nil { + glog.V(1).Infof("Found one at %s", etcdManifestPath) dirsToClean = append(dirsToClean, "/var/lib/etcd") } else { - fmt.Printf("[reset] No etcd manifest found in %q. Assuming external etcd.\n", etcdManifestPath) + fmt.Printf("[reset] no etcd manifest found in %q. Assuming external etcd\n", etcdManifestPath) } // Then clean contents from the stateful kubelet, etcd and cni directories - fmt.Printf("[reset] Deleting contents of stateful directories: %v\n", dirsToClean) + fmt.Printf("[reset] deleting contents of stateful directories: %v\n", dirsToClean) for _, dir := range dirsToClean { + glog.V(1).Infof("[reset] deleting content of %s", dir) cleanDir(dir) } // Remove contents from the config and pki directories - if r.certsDir != kubeadmapiext.DefaultCertificatesDir { - fmt.Printf("[reset] WARNING: Cleaning a non-default certificates directory: %q\n", r.certsDir) + glog.V(1).Infoln("[reset] removing contents from the config and pki directories") + if r.certsDir != kubeadmapiv1alpha2.DefaultCertificatesDir { + glog.Warningf("[reset] WARNING: cleaning a non-default certificates directory: %q\n", r.certsDir) } resetConfigDir(kubeadmconstants.KubernetesDir, r.certsDir) @@ -167,47 +195,49 @@ func reset(execer utilsexec.Interface, dockerCheck preflight.Checker, criSocketP func resetWithDocker(execer utilsexec.Interface, dockerCheck preflight.Checker) { if _, errors := dockerCheck.Check(); len(errors) == 0 { if err := execer.Command("sh", "-c", "docker ps -a --filter name=k8s_ -q | xargs -r docker rm --force --volumes").Run(); err != nil { - fmt.Println("[reset] Failed to stop the running containers.") + glog.Errorln("[reset] failed to stop the running containers") } } else { - fmt.Println("[reset] Docker doesn't seem to be running. Skipping the removal of running Kubernetes containers.") + fmt.Println("[reset] docker doesn't seem to be running. Skipping the removal of running Kubernetes containers") } } func resetWithCrictl(execer utilsexec.Interface, dockerCheck preflight.Checker, criSocketPath, crictlPath string) { if criSocketPath != "" { - fmt.Printf("[reset] Cleaning up running containers using crictl with socket %s\n", criSocketPath) - fmt.Println("[reset] Listing running pods using crictl") + fmt.Printf("[reset] cleaning up running containers using crictl with socket %s\n", criSocketPath) + glog.V(1).Infoln("[reset] listing running pods using crictl") + params := []string{"-r", criSocketPath, "pods", "--quiet"} - fmt.Printf("[reset] Executing command %s %s\n", crictlPath, strings.Join(params, " ")) + glog.V(1).Infof("[reset] Executing command %s %s", crictlPath, strings.Join(params, " ")) output, err := execer.Command(crictlPath, params...).CombinedOutput() if err != nil { - fmt.Printf("[reset] failed to list running pods using crictl: %v. Trying to use docker instead\n", err) + fmt.Printf("[reset] failed to list running pods using crictl: %v. Trying to use docker instead", err) resetWithDocker(execer, dockerCheck) return } - sandboxes := strings.Split(string(output), " ") + sandboxes := strings.Fields(string(output)) + glog.V(1).Infoln("[reset] Stopping and removing running containers using crictl") for _, s := range sandboxes { if strings.TrimSpace(s) == "" { continue } params = []string{"-r", criSocketPath, "stopp", s} - fmt.Printf("[reset] Executing command %s %s\n", crictlPath, strings.Join(params, " ")) + glog.V(1).Infof("[reset] Executing command %s %s", crictlPath, strings.Join(params, " ")) if err := execer.Command(crictlPath, params...).Run(); err != nil { - fmt.Printf("[reset] failed to stop the running containers using crictl: %v. Trying to use docker instead\n", err) + fmt.Printf("[reset] failed to stop the running containers using crictl: %v. Trying to use docker instead", err) resetWithDocker(execer, dockerCheck) return } params = []string{"-r", criSocketPath, "rmp", s} - fmt.Printf("[reset] executing command %s %s\n", crictlPath, strings.Join(params, " ")) + glog.V(1).Infof("[reset] Executing command %s %s", crictlPath, strings.Join(params, " ")) if err := execer.Command(crictlPath, params...).Run(); err != nil { - fmt.Printf("[reset] failed to remove the running containers using crictl: %v. Trying to use docker instead\n", err) + fmt.Printf("[reset] failed to remove the running containers using crictl: %v. Trying to use docker instead", err) resetWithDocker(execer, dockerCheck) return } } } else { - fmt.Println("[reset] CRI socket path not provided for crictl. Trying docker instead.") + fmt.Println("[reset] CRI socket path not provided for crictl. Trying to use docker instead") resetWithDocker(execer, dockerCheck) } } @@ -243,10 +273,10 @@ func resetConfigDir(configPathDir, pkiPathDir string) { filepath.Join(configPathDir, kubeadmconstants.ManifestsSubDirName), pkiPathDir, } - fmt.Printf("[reset] Deleting contents of config directories: %v\n", dirsToClean) + fmt.Printf("[reset] deleting contents of config directories: %v\n", dirsToClean) for _, dir := range dirsToClean { if err := cleanDir(dir); err != nil { - fmt.Printf("[reset] Failed to remove directory: %q [%v]\n", dir, err) + glog.Errorf("[reset] failed to remove directory: %q [%v]\n", dir, err) } } @@ -257,10 +287,10 @@ func resetConfigDir(configPathDir, pkiPathDir string) { filepath.Join(configPathDir, kubeadmconstants.ControllerManagerKubeConfigFileName), filepath.Join(configPathDir, kubeadmconstants.SchedulerKubeConfigFileName), } - fmt.Printf("[reset] Deleting files: %v\n", filesToClean) + fmt.Printf("[reset] deleting files: %v\n", filesToClean) for _, path := range filesToClean { if err := os.RemoveAll(path); err != nil { - fmt.Printf("[reset] Failed to remove file: %q [%v]\n", path, err) + glog.Errorf("[reset] failed to remove file: %q [%v]\n", path, err) } } } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset_test.go index 2fcfc232e..d0beb3bfd 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset_test.go @@ -18,12 +18,15 @@ package cmd import ( "errors" + "io" "io/ioutil" "os" "path/filepath" "strings" "testing" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" "k8s.io/utils/exec" @@ -52,8 +55,41 @@ func assertDirEmpty(t *testing.T, path string) { } } +func TestNewReset(t *testing.T) { + var in io.Reader + certsDir := kubeadmapiv1alpha2.DefaultCertificatesDir + criSocketPath := "/var/run/dockershim.sock" + skipPreFlight := false + forceReset := true + + ignorePreflightErrors := []string{"all"} + ignorePreflightErrorsSet, _ := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight) + NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath) + + ignorePreflightErrors = []string{} + ignorePreflightErrorsSet, _ = validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight) + NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath) +} + +func TestNewCmdReset(t *testing.T) { + var out io.Writer + var in io.Reader + cmd := NewCmdReset(in, out) + + tmpDir, err := ioutil.TempDir("", "kubeadm-reset-test") + if err != nil { + t.Errorf("Unable to create temporary directory: %v", err) + } + args := []string{"--ignore-preflight-errors=all", "--cert-dir=" + tmpDir, "--force"} + cmd.SetArgs(args) + if err := cmd.Execute(); err != nil { + t.Errorf("Cannot execute reset command: %v", err) + } +} + func TestConfigDirCleaner(t *testing.T) { tests := map[string]struct { + resetDir string setupDirs []string setupFiles []string verifyExists []string @@ -91,7 +127,7 @@ func TestConfigDirCleaner(t *testing.T) { "manifests", }, }, - "preserve cloud-config": { + "preserve unrelated file foo": { setupDirs: []string{ "manifests", "pki", @@ -102,12 +138,12 @@ func TestConfigDirCleaner(t *testing.T) { "pki/ca.pem", kubeadmconstants.AdminKubeConfigFileName, kubeadmconstants.KubeletKubeConfigFileName, - "cloud-config", + "foo", }, verifyExists: []string{ "manifests", "pki", - "cloud-config", + "foo", }, }, "preserve hidden files and directories": { @@ -122,13 +158,11 @@ func TestConfigDirCleaner(t *testing.T) { "pki/ca.pem", kubeadmconstants.AdminKubeConfigFileName, kubeadmconstants.KubeletKubeConfigFileName, - ".cloud-config", ".mydir/.myfile", }, verifyExists: []string{ "manifests", "pki", - ".cloud-config", ".mydir", ".mydir/.myfile", }, @@ -139,6 +173,12 @@ func TestConfigDirCleaner(t *testing.T) { "manifests", }, }, + "not a directory": { + resetDir: "test-path", + setupFiles: []string{ + "test-path", + }, + }, } for name, test := range tests { @@ -149,7 +189,6 @@ func TestConfigDirCleaner(t *testing.T) { if err != nil { t.Errorf("Unable to create temporary directory: %s", err) } - defer os.RemoveAll(tmpDir) for _, createDir := range test.setupDirs { err := os.Mkdir(filepath.Join(tmpDir, createDir), 0700) @@ -164,10 +203,13 @@ func TestConfigDirCleaner(t *testing.T) { if err != nil { t.Errorf("Unable to create test file: %s", err) } - defer f.Close() + f.Close() } - resetConfigDir(tmpDir, filepath.Join(tmpDir, "pki")) + if test.resetDir == "" { + test.resetDir = "pki" + } + resetConfigDir(tmpDir, filepath.Join(tmpDir, test.resetDir)) // Verify the files we cleanup implicitly in every test: assertExists(t, tmpDir) @@ -183,6 +225,8 @@ func TestConfigDirCleaner(t *testing.T) { for _, path := range test.verifyNotExists { assertNotExists(t, filepath.Join(tmpDir, path)) } + + os.RemoveAll(tmpDir) } } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go index 7781357ae..9368a656a 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go @@ -20,35 +20,36 @@ import ( "fmt" "io" "os" - "sort" "strings" "text/tabwriter" "time" + "github.com/golang/glog" "github.com/renstrom/dedent" "github.com/spf13/cobra" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/util/duration" clientset "k8s.io/client-go/kubernetes" bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" + "k8s.io/client-go/tools/clientcmd" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" tokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" - "k8s.io/kubernetes/pkg/api/legacyscheme" - api "k8s.io/kubernetes/pkg/apis/core" ) +const defaultKubeConfig = "/etc/kubernetes/admin.conf" + // NewCmdToken returns cobra.Command for token management func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { var kubeConfigFile string @@ -84,21 +85,23 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { } tokenCmd.PersistentFlags().StringVar(&kubeConfigFile, - "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster") + "kubeconfig", defaultKubeConfig, "The KubeConfig file to use when talking to the cluster. If the flag is not set a set of standard locations are searched for an existing KubeConfig file") tokenCmd.PersistentFlags().BoolVar(&dryRun, "dry-run", dryRun, "Whether to enable dry-run mode or not") - cfg := &kubeadmapiext.MasterConfiguration{ + cfg := &kubeadmapiv1alpha2.MasterConfiguration{ // KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.9.0", + KubernetesVersion: "v1.10.0", } // Default values for the cobra help text - legacyscheme.Scheme.Default(cfg) + kubeadmscheme.Scheme.Default(cfg) - var cfgPath, description string + var cfgPath string var printJoinCommand bool + bto := options.NewBootstrapTokenOptions() + createCmd := &cobra.Command{ Use: "create [token]", DisableFlagsInUseLine: true, @@ -112,35 +115,35 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { If no [token] is given, kubeadm will generate a random token instead. `), Run: func(tokenCmd *cobra.Command, args []string) { - if len(args) != 0 { - cfg.Token = args[0] + if len(args) > 0 { + bto.TokenStr = args[0] } - + glog.V(1).Infoln("[token] validating mixed arguments") err := validation.ValidateMixedArguments(tokenCmd.Flags()) kubeadmutil.CheckErr(err) + err = bto.ApplyTo(cfg) + kubeadmutil.CheckErr(err) + + glog.V(1).Infoln("[token] getting Clientsets from KubeConfig file") + kubeConfigFile = findExistingKubeConfig(kubeConfigFile) client, err := getClientset(kubeConfigFile, dryRun) kubeadmutil.CheckErr(err) - err = RunCreateToken(out, client, cfgPath, cfg, description, printJoinCommand, kubeConfigFile) + err = RunCreateToken(out, client, cfgPath, cfg, printJoinCommand, kubeConfigFile) kubeadmutil.CheckErr(err) }, } createCmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)") - createCmd.Flags().DurationVar(&cfg.TokenTTL.Duration, - "ttl", cfg.TokenTTL.Duration, "The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire.") - createCmd.Flags().StringSliceVar(&cfg.TokenUsages, - "usages", cfg.TokenUsages, fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s].", strings.Join(kubeadmconstants.DefaultTokenUsages, ","))) - createCmd.Flags().StringSliceVar(&cfg.TokenGroups, - "groups", cfg.TokenGroups, - fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q.", bootstrapapi.BootstrapGroupPattern)) - createCmd.Flags().StringVar(&description, - "description", "", "A human friendly description of how this token is used.") createCmd.Flags().BoolVar(&printJoinCommand, "print-join-command", false, "Instead of printing only the token, print the full 'kubeadm join' flag needed to join the cluster using the token.") - tokenCmd.AddCommand(createCmd) + bto.AddTTLFlagWithName(createCmd.Flags(), "ttl") + bto.AddUsagesFlag(createCmd.Flags()) + bto.AddGroupsFlag(createCmd.Flags()) + bto.AddDescriptionFlag(createCmd.Flags()) + tokenCmd.AddCommand(createCmd) tokenCmd.AddCommand(NewCmdTokenGenerate(out)) listCmd := &cobra.Command{ @@ -150,6 +153,7 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { This command will list all bootstrap tokens for you. `), Run: func(tokenCmd *cobra.Command, args []string) { + kubeConfigFile = findExistingKubeConfig(kubeConfigFile) client, err := getClientset(kubeConfigFile, dryRun) kubeadmutil.CheckErr(err) @@ -171,8 +175,9 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { `), Run: func(tokenCmd *cobra.Command, args []string) { if len(args) < 1 { - kubeadmutil.CheckErr(fmt.Errorf("missing subcommand; 'token delete' is missing token of form [%q]", tokenutil.TokenIDRegexpString)) + kubeadmutil.CheckErr(fmt.Errorf("missing subcommand; 'token delete' is missing token of form %q", bootstrapapi.BootstrapTokenIDPattern)) } + kubeConfigFile = findExistingKubeConfig(kubeConfigFile) client, err := getClientset(kubeConfigFile, dryRun) kubeadmutil.CheckErr(err) @@ -209,28 +214,29 @@ func NewCmdTokenGenerate(out io.Writer) *cobra.Command { } // RunCreateToken generates a new bootstrap token and stores it as a secret on the server. -func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, printJoinCommand bool, kubeConfigFile string) error { +func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1alpha2.MasterConfiguration, printJoinCommand bool, kubeConfigFile string) error { // This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags + glog.V(1).Infoln("[token] loading configurations") internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg) if err != nil { return err } - err = tokenphase.CreateNewToken(client, internalcfg.Token, internalcfg.TokenTTL.Duration, internalcfg.TokenUsages, internalcfg.TokenGroups, description) - if err != nil { + glog.V(1).Infoln("[token] creating token") + if err := tokenphase.CreateNewTokens(client, internalcfg.BootstrapTokens); err != nil { return err } // if --print-join-command was specified, print the full `kubeadm join` command // otherwise, just print the token if printJoinCommand { - joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.Token, false) + joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.BootstrapTokens[0].Token.String(), false) if err != nil { return fmt.Errorf("failed to get join command: %v", err) } fmt.Fprintln(out, joinCommand) } else { - fmt.Fprintln(out, internalcfg.Token) + fmt.Fprintln(out, internalcfg.BootstrapTokens[0].Token.String()) } return nil @@ -238,7 +244,8 @@ func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, c // RunGenerateToken just generates a random token for the user func RunGenerateToken(out io.Writer) error { - token, err := tokenutil.GenerateToken() + glog.V(1).Infoln("[token] generating random token") + token, err := bootstraputil.GenerateBootstrapToken() if err != nil { return err } @@ -250,15 +257,20 @@ func RunGenerateToken(out io.Writer) error { // RunListTokens lists details on all existing bootstrap tokens on the server. func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) error { // First, build our selector for bootstrap tokens only + glog.V(1).Infoln("[token] preparing selector for bootstrap token") tokenSelector := fields.SelectorFromSet( map[string]string{ - api.SecretTypeField: string(bootstrapapi.SecretTypeBootstrapToken), + // TODO: We hard-code "type" here until `field_constants.go` that is + // currently in `pkg/apis/core/` exists in the external API, i.e. + // k8s.io/api/v1. Should be v1.SecretTypeField + "type": string(bootstrapapi.SecretTypeBootstrapToken), }, ) listOptions := metav1.ListOptions{ FieldSelector: tokenSelector.String(), } + glog.V(1).Infoln("[token] retrieving list of bootstrap tokens") secrets, err := client.CoreV1().Secrets(metav1.NamespaceSystem).List(listOptions) if err != nil { return fmt.Errorf("failed to list bootstrap tokens [%v]", err) @@ -267,68 +279,17 @@ func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) er w := tabwriter.NewWriter(out, 10, 4, 3, ' ', 0) fmt.Fprintln(w, "TOKEN\tTTL\tEXPIRES\tUSAGES\tDESCRIPTION\tEXTRA GROUPS") for _, secret := range secrets.Items { - tokenID := getSecretString(&secret, bootstrapapi.BootstrapTokenIDKey) - if len(tokenID) == 0 { - fmt.Fprintf(errW, "bootstrap token has no token-id data: %s\n", secret.Name) - continue - } - - // enforce the right naming convention - if secret.Name != fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID) { - fmt.Fprintf(errW, "bootstrap token name is not of the form '%s(token-id)': %s\n", bootstrapapi.BootstrapTokenSecretPrefix, secret.Name) - continue - } - tokenSecret := getSecretString(&secret, bootstrapapi.BootstrapTokenSecretKey) - if len(tokenSecret) == 0 { - fmt.Fprintf(errW, "bootstrap token has no token-secret data: %s\n", secret.Name) + // Get the BootstrapToken struct representation from the Secret object + token, err := kubeadmapi.BootstrapTokenFromSecret(&secret) + if err != nil { + fmt.Fprintf(errW, "%v", err) continue } - td := &kubeadmapi.TokenDiscovery{ID: tokenID, Secret: tokenSecret} - - // Expiration time is optional, if not specified this implies the token - // never expires. - ttl := "" - expires := "" - secretExpiration := getSecretString(&secret, bootstrapapi.BootstrapTokenExpirationKey) - if len(secretExpiration) > 0 { - expireTime, err := time.Parse(time.RFC3339, secretExpiration) - if err != nil { - fmt.Fprintf(errW, "can't parse expiration time of bootstrap token %s\n", secret.Name) - continue - } - ttl = duration.ShortHumanDuration(expireTime.Sub(time.Now())) - expires = expireTime.Format(time.RFC3339) - } - - usages := []string{} - for k, v := range secret.Data { - // Skip all fields that don't include this prefix - if !strings.HasPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix) { - continue - } - // Skip those that don't have this usage set to true - if string(v) != "true" { - continue - } - usages = append(usages, strings.TrimPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix)) - } - sort.Strings(usages) - usageString := strings.Join(usages, ",") - if len(usageString) == 0 { - usageString = "" - } - description := getSecretString(&secret, bootstrapapi.BootstrapTokenDescriptionKey) - if len(description) == 0 { - description = "" - } - - groups := getSecretString(&secret, bootstrapapi.BootstrapTokenExtraGroupsKey) - if len(groups) == 0 { - groups = "" - } - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n", tokenutil.BearerToken(td), ttl, expires, usageString, description, groups) + // Get the human-friendly string representation for the token + humanFriendlyTokenOutput := humanReadableBootstrapToken(token) + fmt.Fprintln(w, humanFriendlyTokenOutput) } w.Flush() return nil @@ -338,13 +299,18 @@ func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) er func RunDeleteToken(out io.Writer, client clientset.Interface, tokenIDOrToken string) error { // Assume the given first argument is a token id and try to parse it tokenID := tokenIDOrToken - if err := tokenutil.ParseTokenID(tokenIDOrToken); err != nil { - if tokenID, _, err = tokenutil.ParseToken(tokenIDOrToken); err != nil { - return fmt.Errorf("given token or token id %q didn't match pattern [%q] or [%q]", tokenIDOrToken, tokenutil.TokenIDRegexpString, tokenutil.TokenRegexpString) + glog.V(1).Infoln("[token] parsing token ID") + if !bootstraputil.IsValidBootstrapTokenID(tokenIDOrToken) { + // Okay, the full token with both id and secret was probably passed. Parse it and extract the ID only + bts, err := kubeadmapiv1alpha2.NewBootstrapTokenString(tokenIDOrToken) + if err != nil { + return fmt.Errorf("given token or token id %q didn't match pattern %q or %q", tokenIDOrToken, bootstrapapi.BootstrapTokenIDPattern, bootstrapapi.BootstrapTokenIDPattern) } + tokenID = bts.ID } - tokenSecretName := fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID) + tokenSecretName := bootstraputil.BootstrapTokenSecretName(tokenID) + glog.V(1).Infoln("[token] deleting token") if err := client.CoreV1().Secrets(metav1.NamespaceSystem).Delete(tokenSecretName, nil); err != nil { return fmt.Errorf("failed to delete bootstrap token [%v]", err) } @@ -352,14 +318,30 @@ func RunDeleteToken(out io.Writer, client clientset.Interface, tokenIDOrToken st return nil } -func getSecretString(secret *v1.Secret, key string) string { - if secret.Data == nil { - return "" +func humanReadableBootstrapToken(token *kubeadmapi.BootstrapToken) string { + description := token.Description + if len(description) == 0 { + description = "" } - if val, ok := secret.Data[key]; ok { - return string(val) + + ttl := "" + expires := "" + if token.Expires != nil { + ttl = duration.ShortHumanDuration(token.Expires.Sub(time.Now())) + expires = token.Expires.Format(time.RFC3339) } - return "" + + usagesString := strings.Join(token.Usages, ",") + if len(usagesString) == 0 { + usagesString = "" + } + + groupsString := strings.Join(token.Groups, ",") + if len(groupsString) == 0 { + groupsString = "" + } + + return fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s\n", token.Token.String(), ttl, expires, usagesString, description, groupsString) } func getClientset(file string, dryRun bool) (clientset.Interface, error) { @@ -372,3 +354,16 @@ func getClientset(file string, dryRun bool) (clientset.Interface, error) { } return kubeconfigutil.ClientSetFromFile(file) } + +func findExistingKubeConfig(file string) string { + // The user did provide a --kubeconfig flag. Respect that and threat it as an + // explicit path without building a DefaultClientConfigLoadingRules object. + if file != defaultKubeConfig { + return file + } + // The user did not provide a --kubeconfig flag. Find a config in the standard + // locations using DefaultClientConfigLoadingRules, but also consider `defaultKubeConfig`. + rules := clientcmd.NewDefaultClientConfigLoadingRules() + rules.Precedence = append(rules.Precedence, defaultKubeConfig) + return rules.GetDefaultFilename() +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token_test.go index 10588af47..c919583a9 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token_test.go @@ -18,8 +18,17 @@ package cmd import ( "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "path/filepath" "regexp" + "strings" + "sync/atomic" "testing" + "time" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -27,11 +36,48 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + "k8s.io/client-go/tools/clientcmd" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" ) const ( - TokenExpectedRegex = "^\\S{6}\\.\\S{16}\n$" + tokenExpectedRegex = "^\\S{6}\\.\\S{16}\n$" + testConfigToken = `apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: + server: localhost:8000 + name: prod +contexts: +- context: + cluster: prod + namespace: default + user: default-service-account + name: default +current-context: default +kind: Config +preferences: {} +users: +- name: kubernetes-admin + user: + client-certificate-data: + client-key-data: +` + testConfigTokenCertAuthorityData = "certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRFM01USXhOREUxTlRFek1Gb1hEVEkzTVRJeE1qRTFOVEV6TUZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTlZrCnNkT0NjRDBIOG9ycXZ5djBEZ09jZEpjRGc4aTJPNGt3QVpPOWZUanJGRHJqbDZlVXRtdlMyZ1lZd0c4TGhPV2gKb0lkZ3AvbVkrbVlDakliUUJtTmE2Ums1V2JremhJRzM1c1lseE9NVUJJR0xXMzN0RTh4SlR1RVd3V0NmZnpLcQpyaU1UT1A3REF3MUxuM2xUNlpJNGRNM09NOE1IUk9Wd3lRMDVpbWo5eUx5R1lYdTlvSncwdTVXWVpFYmpUL3VpCjJBZ2QwVDMrZGFFb044aVBJOTlVQkQxMzRkc2VGSEJEY3hHcmsvVGlQdHBpSC9IOGoxRWZaYzRzTGlONzJmL2YKYUpacTROSHFiT2F5UkpITCtJejFNTW1DRkN3cjdHOHVENWVvWWp2dEdZN2xLc1pBTlUwK3VlUnJsTitxTzhQWQpxaTZNMDFBcmV1UzFVVHFuTkM4Q0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFNbXo4Nm9LMmFLa0owMnlLSC9ZcTlzaDZZcDEKYmhLS25mMFJCaTA1clRacWdhTi9oTnROdmQxSzJxZGRLNzhIT2pVdkpNRGp3NERieXF0Wll2V01XVFRCQnQrSgpPMGNyWkg5NXlqUW42YzRlcU1FTjFhOUFKNXRlclNnTDVhREJsK0FMTWxaNVpxTzBUOUJDdTJtNXV3dGNWaFZuCnh6cGpTT3V5WVdOQ3A5bW9mV2VPUTljNXhEcElWeUlMUkFvNmZ5Z2c3N25TSDN4ckVmd0VKUHFMd1RPYVk1bTcKeEZWWWJoR3dxUGU5V0I5aTR5cnNrZUFBWlpUSzdVbklKMXFkRmlHQk9aZlRtaDhYQ3BOTHZZcFBLQW9hWWlsRwpjOW1acVhpWVlESTV6R1IxMElpc2FWNXJUY2hDenNQVWRhQzRVbnpTZG01cTdKYTAyb0poQlU1TE1FMD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" + testConfigTokenNoCluster = `apiVersion: v1 +clusters: +- cluster: + server: + name: prod +contexts: +- context: + namespace: default + user: default-service-account + name: default +kind: Config +preferences: {} +` ) func TestRunGenerateToken(t *testing.T) { @@ -44,12 +90,12 @@ func TestRunGenerateToken(t *testing.T) { output := buf.String() - matched, err := regexp.MatchString(TokenExpectedRegex, output) + matched, err := regexp.MatchString(tokenExpectedRegex, output) if err != nil { - t.Fatalf("encountered an error while trying to match RunGenerateToken's output: %v", err) + t.Fatalf("Encountered an error while trying to match RunGenerateToken's output: %v", err) } if !matched { - t.Errorf("RunGenerateToken's output did not match expected regex; wanted: [%s], got: [%s]", TokenExpectedRegex, output) + t.Errorf("RunGenerateToken's output did not match expected regex; wanted: [%s], got: [%s]", tokenExpectedRegex, output) } } @@ -65,6 +111,7 @@ func TestRunCreateToken(t *testing.T) { token string usages []string extraGroups []string + printJoin bool expectedError bool }{ { @@ -88,13 +135,6 @@ func TestRunCreateToken(t *testing.T) { extraGroups: []string{}, expectedError: false, }, - { - name: "invalid: incorrect token", - token: "123456.AABBCCDDEEFFGGHH", - usages: []string{"signing", "authentication"}, - extraGroups: []string{}, - expectedError: true, - }, { name: "invalid: incorrect extraGroups", token: "abcdef.1234567890123456", @@ -123,22 +163,376 @@ func TestRunCreateToken(t *testing.T) { extraGroups: []string{"system:bootstrappers:foo"}, expectedError: true, }, + { + name: "invalid: print join command", + token: "", + usages: []string{"signing", "authentication"}, + extraGroups: []string{"system:bootstrappers:foo"}, + printJoin: true, + expectedError: true, + }, } for _, tc := range testCases { + bts, err := kubeadmapiv1alpha2.NewBootstrapTokenString(tc.token) + if err != nil && len(tc.token) != 0 { // if tc.token is "" it's okay as it will be generated later at runtime + t.Fatalf("token couldn't be parsed for testing: %v", err) + } + + cfg := &kubeadmapiv1alpha2.MasterConfiguration{ - cfg := &kubeadmapiext.MasterConfiguration{ // KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.9.0", - Token: tc.token, - TokenTTL: &metav1.Duration{Duration: 0}, - TokenUsages: tc.usages, - TokenGroups: tc.extraGroups, + KubernetesVersion: "v1.10.0", + BootstrapTokens: []kubeadmapiv1alpha2.BootstrapToken{ + { + Token: bts, + TTL: &metav1.Duration{Duration: 0}, + Usages: tc.usages, + Groups: tc.extraGroups, + }, + }, } - err := RunCreateToken(&buf, fakeClient, "", cfg, "", false, "") + err = RunCreateToken(&buf, fakeClient, "", cfg, tc.printJoin, "") if (err != nil) != tc.expectedError { t.Errorf("Test case %s: RunCreateToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) } } } + +func TestNewCmdTokenGenerate(t *testing.T) { + var buf bytes.Buffer + args := []string{} + + cmd := NewCmdTokenGenerate(&buf) + cmd.SetArgs(args) + + if err := cmd.Execute(); err != nil { + t.Errorf("Cannot execute token command: %v", err) + } +} + +func TestNewCmdToken(t *testing.T) { + var buf, bufErr bytes.Buffer + testConfigTokenFile := "test-config-file" + + tmpDir, err := ioutil.TempDir("", "kubeadm-token-test") + if err != nil { + t.Errorf("Unable to create temporary directory: %v", err) + } + defer os.RemoveAll(tmpDir) + fullPath := filepath.Join(tmpDir, testConfigTokenFile) + + f, err := os.Create(fullPath) + if err != nil { + t.Errorf("Unable to create test file %q: %v", fullPath, err) + } + defer f.Close() + + testCases := []struct { + name string + args []string + configToWrite string + kubeConfigEnv string + expectedError bool + }{ + { + name: "valid: generate", + args: []string{"generate"}, + configToWrite: "", + expectedError: false, + }, + { + name: "valid: delete from --kubeconfig", + args: []string{"delete", "abcdef.1234567890123456", "--dry-run", "--kubeconfig=" + fullPath}, + configToWrite: testConfigToken, + expectedError: false, + }, + { + name: "valid: delete from " + clientcmd.RecommendedConfigPathEnvVar, + args: []string{"delete", "abcdef.1234567890123456", "--dry-run"}, + configToWrite: testConfigToken, + kubeConfigEnv: fullPath, + expectedError: false, + }, + } + + for _, tc := range testCases { + // the command is created for each test so that the kubeConfigFile + // variable in NewCmdToken() is reset. + cmd := NewCmdToken(&buf, &bufErr) + if _, err = f.WriteString(tc.configToWrite); err != nil { + t.Errorf("Unable to write test file %q: %v", fullPath, err) + } + // store the current value of the environment variable. + storedEnv := os.Getenv(clientcmd.RecommendedConfigPathEnvVar) + if tc.kubeConfigEnv != "" { + os.Setenv(clientcmd.RecommendedConfigPathEnvVar, tc.kubeConfigEnv) + } + cmd.SetArgs(tc.args) + err := cmd.Execute() + if (err != nil) != tc.expectedError { + t.Errorf("Test case %q: NewCmdToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) + } + // restore the environment variable. + os.Setenv(clientcmd.RecommendedConfigPathEnvVar, storedEnv) + } +} + +func TestGetClientset(t *testing.T) { + testConfigTokenFile := "test-config-file" + + tmpDir, err := ioutil.TempDir("", "kubeadm-token-test") + if err != nil { + t.Errorf("Unable to create temporary directory: %v", err) + } + defer os.RemoveAll(tmpDir) + fullPath := filepath.Join(tmpDir, testConfigTokenFile) + + // test dryRun = false on a non-exisiting file + if _, err = getClientset(fullPath, false); err == nil { + t.Errorf("getClientset(); dry-run: false; did no fail for test file %q: %v", fullPath, err) + } + + // test dryRun = true on a non-exisiting file + if _, err = getClientset(fullPath, true); err == nil { + t.Errorf("getClientset(); dry-run: true; did no fail for test file %q: %v", fullPath, err) + } + + f, err := os.Create(fullPath) + if err != nil { + t.Errorf("Unable to create test file %q: %v", fullPath, err) + } + defer f.Close() + + if _, err = f.WriteString(testConfigToken); err != nil { + t.Errorf("Unable to write test file %q: %v", fullPath, err) + } + + // test dryRun = true on an exisiting file + if _, err = getClientset(fullPath, true); err != nil { + t.Errorf("getClientset(); dry-run: true; failed for test file %q: %v", fullPath, err) + } +} + +func TestRunDeleteToken(t *testing.T) { + var buf bytes.Buffer + + tmpDir, err := ioutil.TempDir("", "kubeadm-token-test") + if err != nil { + t.Errorf("Unable to create temporary directory: %v", err) + } + defer os.RemoveAll(tmpDir) + fullPath := filepath.Join(tmpDir, "test-config-file") + + f, err := os.Create(fullPath) + if err != nil { + t.Errorf("Unable to create test file %q: %v", fullPath, err) + } + defer f.Close() + + if _, err = f.WriteString(testConfigToken); err != nil { + t.Errorf("Unable to write test file %q: %v", fullPath, err) + } + + client, err := getClientset(fullPath, true) + if err != nil { + t.Errorf("Unable to run getClientset() for test file %q: %v", fullPath, err) + } + + // test valid; should not fail + // for some reason Secrets().Delete() does not fail even for this dummy config + if err = RunDeleteToken(&buf, client, "abcdef.1234567890123456"); err != nil { + t.Errorf("RunDeleteToken() failed for a valid token: %v", err) + } + + // test invalid token; should fail + if err = RunDeleteToken(&buf, client, "invalid-token"); err == nil { + t.Errorf("RunDeleteToken() succeeded for an invalid token: %v", err) + } +} + +var httpTestItr uint32 +var httpSentResponse uint32 = 1 + +func TestRunListTokens(t *testing.T) { + var err error + var bufOut, bufErr bytes.Buffer + + tmpDir, err := ioutil.TempDir("", "kubeadm-token-test") + if err != nil { + t.Errorf("Unable to create temporary directory: %v", err) + } + defer os.RemoveAll(tmpDir) + fullPath := filepath.Join(tmpDir, "test-config-file") + + f, err := os.Create(fullPath) + if err != nil { + t.Errorf("Unable to create test file %q: %v", fullPath, err) + } + defer f.Close() + + // test config without secrets; should fail + if _, err = f.WriteString(testConfigToken); err != nil { + t.Errorf("Unable to write test file %q: %v", fullPath, err) + } + + client, err := getClientset(fullPath, true) + if err != nil { + t.Errorf("Unable to run getClientset() for test file %q: %v", fullPath, err) + } + + if err = RunListTokens(&bufOut, &bufErr, client); err == nil { + t.Errorf("RunListTokens() did not fail for a config without secrets: %v", err) + } + + // test config without secrets but use a dummy API server that returns secrets + portString := "9008" + http.HandleFunc("/", httpHandler) + httpServer := &http.Server{Addr: "localhost:" + portString} + go func() { + err := httpServer.ListenAndServe() + if err != nil { + t.Errorf("Failed to start dummy API server: localhost:%s", portString) + } + }() + + fmt.Printf("dummy API server listening on localhost:%s\n", portString) + testConfigTokenOpenPort := strings.Replace(testConfigToken, "server: localhost:8000", "server: localhost:"+portString, -1) + + if _, err = f.WriteString(testConfigTokenOpenPort); err != nil { + t.Errorf("Unable to write test file %q: %v", fullPath, err) + } + + client, err = getClientset(fullPath, true) + if err != nil { + t.Errorf("Unable to run getClientset() for test file %q: %v", fullPath, err) + } + + // the order of these tests should match the case check + // for httpTestItr in httpHandler + testCases := []struct { + name string + expectedError bool + }{ + { + name: "token-id not defined", + expectedError: true, + }, + { + name: "secret name not formatted correctly", + expectedError: true, + }, + { + name: "token-secret not defined", + expectedError: true, + }, + { + name: "token expiration not formatted correctly", + expectedError: true, + }, + { + name: "token expiration formatted correctly", + expectedError: false, + }, + { + name: "token usage constant not true", + expectedError: false, + }, + { + name: "token usage constant set to true", + expectedError: false, + }, + } + for _, tc := range testCases { + bufErr.Reset() + atomic.StoreUint32(&httpSentResponse, 0) + fmt.Printf("Running HTTP test case (%d) %q\n", atomic.LoadUint32(&httpTestItr), tc.name) + // should always return nil here if a valid list of secrets if fetched + err := RunListTokens(&bufOut, &bufErr, client) + if err != nil { + t.Errorf("HTTP test case %d: Was unable to fetch a list of secrets", atomic.LoadUint32(&httpTestItr)) + } + // wait for a response from the dummy HTTP server + timeSpent := 0 * time.Millisecond + timeToSleep := 50 * time.Millisecond + timeMax := 2000 * time.Millisecond + for { + if atomic.LoadUint32(&httpSentResponse) == 1 { + break + } + if timeSpent >= timeMax { + t.Errorf("HTTP test case %d: The server did not respond within %d ms", atomic.LoadUint32(&httpTestItr), timeMax) + } + timeSpent += timeToSleep + time.Sleep(timeToSleep) + } + // check if an error is written in the error buffer + hasError := bufErr.Len() != 0 + if hasError != tc.expectedError { + t.Errorf("HTTP test case %d: RunListTokens expected error: %v, saw: %v; %v", atomic.LoadUint32(&httpTestItr), tc.expectedError, hasError, bufErr.String()) + } + } +} + +// only one of these should run at a time in a goroutine +func httpHandler(w http.ResponseWriter, r *http.Request) { + tokenID := []byte("07401b") + tokenSecret := []byte("f395accd246ae52d") + tokenExpire := []byte("2012-11-01T22:08:41+00:00") + badValue := "bad-value" + name := bootstrapapi.BootstrapTokenSecretPrefix + string(tokenID) + tokenUsageKey := bootstrapapi.BootstrapTokenUsagePrefix + "test" + + secret := v1.Secret{} + secret.Type = bootstrapapi.SecretTypeBootstrapToken + secret.TypeMeta = metav1.TypeMeta{APIVersion: "v1", Kind: "Secret"} + secret.Data = map[string][]byte{} + + switch atomic.LoadUint32(&httpTestItr) { + case 0: + secret.Data[bootstrapapi.BootstrapTokenIDKey] = []byte("") + case 1: + secret.Data[bootstrapapi.BootstrapTokenIDKey] = tokenID + secret.ObjectMeta = metav1.ObjectMeta{Name: badValue} + case 2: + secret.Data[bootstrapapi.BootstrapTokenIDKey] = tokenID + secret.Data[bootstrapapi.BootstrapTokenSecretKey] = []byte("") + secret.ObjectMeta = metav1.ObjectMeta{Name: name} + case 3: + secret.Data[bootstrapapi.BootstrapTokenIDKey] = tokenID + secret.Data[bootstrapapi.BootstrapTokenSecretKey] = tokenSecret + secret.Data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(badValue) + secret.ObjectMeta = metav1.ObjectMeta{Name: name} + case 4: + secret.Data[bootstrapapi.BootstrapTokenIDKey] = tokenID + secret.Data[bootstrapapi.BootstrapTokenSecretKey] = tokenSecret + secret.Data[bootstrapapi.BootstrapTokenExpirationKey] = tokenExpire + secret.ObjectMeta = metav1.ObjectMeta{Name: name} + case 5: + secret.Data[bootstrapapi.BootstrapTokenIDKey] = tokenID + secret.Data[bootstrapapi.BootstrapTokenSecretKey] = tokenSecret + secret.Data[bootstrapapi.BootstrapTokenExpirationKey] = tokenExpire + secret.Data[tokenUsageKey] = []byte("false") + secret.ObjectMeta = metav1.ObjectMeta{Name: name} + case 6: + secret.Data[bootstrapapi.BootstrapTokenIDKey] = tokenID + secret.Data[bootstrapapi.BootstrapTokenSecretKey] = tokenSecret + secret.Data[bootstrapapi.BootstrapTokenExpirationKey] = tokenExpire + secret.Data[tokenUsageKey] = []byte("true") + secret.ObjectMeta = metav1.ObjectMeta{Name: name} + } + + secretList := v1.SecretList{} + secretList.Items = []v1.Secret{secret} + secretList.TypeMeta = metav1.TypeMeta{APIVersion: "v1", Kind: "SecretList"} + + output, err := json.Marshal(secretList) + if err == nil { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + w.Write([]byte(output)) + } + atomic.AddUint32(&httpTestItr, 1) + atomic.StoreUint32(&httpSentResponse, 1) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/BUILD index d0d26536a..c55c9c6d1 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/BUILD @@ -5,6 +5,8 @@ go_library( srcs = [ "apply.go", "common.go", + "diff.go", + "node.go", "plan.go", "upgrade.go", ], @@ -12,12 +14,14 @@ go_library( visibility = ["//visibility:public"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", "//cmd/kubeadm/app/cmd/util:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/phases/controlplane:go_default_library", + "//cmd/kubeadm/app/phases/kubelet:go_default_library", "//cmd/kubeadm/app/phases/upgrade:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util:go_default_library", @@ -26,10 +30,15 @@ go_library( "//cmd/kubeadm/app/util/dryrun:go_default_library", "//cmd/kubeadm/app/util/etcd:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", - "//pkg/api/legacyscheme:go_default_library", + "//pkg/util/normalizer:go_default_library", "//pkg/util/version:go_default_library", - "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/pmezard/go-difflib/difflib:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/client-go/discovery/fake:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", @@ -41,11 +50,14 @@ go_test( srcs = [ "apply_test.go", "common_test.go", + "diff_test.go", "plan_test.go", ], + data = glob(["testdata/**"]), embed = [":go_default_library"], deps = [ - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/phases/upgrade:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go index 73127850a..e5922edb9 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go @@ -21,10 +21,12 @@ import ( "os" "time" + "github.com/golang/glog" "github.com/spf13/cobra" clientset "k8s.io/client-go/kubernetes" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -35,24 +37,28 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" - "k8s.io/kubernetes/pkg/api/legacyscheme" + etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd" "k8s.io/kubernetes/pkg/util/version" ) const ( - upgradeManifestTimeout = 1 * time.Minute + upgradeManifestTimeout = 5 * time.Minute + + defaultImagePullTimeout = 15 * time.Minute ) // applyFlags holds the information about the flags that can be passed to apply type applyFlags struct { + *applyPlanFlags + nonInteractiveMode bool force bool dryRun bool etcdUpgrade bool + criSocket string newK8sVersionStr string newK8sVersion *version.Version imagePullTimeout time.Duration - parent *cmdUpgradeFlags } // SessionIsInteractive returns true if the session is of an interactive type (the default, can be opted out of with -y, -f or --dry-run) @@ -61,11 +67,12 @@ func (f *applyFlags) SessionIsInteractive() bool { } // NewCmdApply returns the cobra command for `kubeadm upgrade apply` -func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command { +func NewCmdApply(apf *applyPlanFlags) *cobra.Command { flags := &applyFlags{ - parent: parentFlags, - imagePullTimeout: 15 * time.Minute, + applyPlanFlags: apf, + imagePullTimeout: defaultImagePullTimeout, etcdUpgrade: true, + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, } cmd := &cobra.Command{ @@ -74,16 +81,18 @@ func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command { Short: "Upgrade your Kubernetes cluster to the specified version.", Run: func(cmd *cobra.Command, args []string) { var err error - flags.parent.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(flags.parent.ignorePreflightErrors, flags.parent.skipPreFlight) + flags.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(flags.ignorePreflightErrors, flags.skipPreFlight) kubeadmutil.CheckErr(err) // Ensure the user is root - err = runPreflightChecks(flags.parent.ignorePreflightErrorsSet) + glog.V(1).Infof("running preflight checks") + err = runPreflightChecks(flags.ignorePreflightErrorsSet) kubeadmutil.CheckErr(err) // If the version is specified in config file, pick up that value. - if flags.parent.cfgPath != "" { - cfg, err := upgrade.FetchConfigurationFromFile(flags.parent.cfgPath) + if flags.cfgPath != "" { + glog.V(1).Infof("fetching configuration from file", flags.cfgPath) + cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) kubeadmutil.CheckErr(err) if cfg.KubernetesVersion != "" { @@ -111,13 +120,16 @@ func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command { }, } + // Register the common flags for apply and plan + addApplyPlanFlags(cmd.Flags(), flags.applyPlanFlags) // Specify the valid flags specific for apply cmd.Flags().BoolVarP(&flags.nonInteractiveMode, "yes", "y", flags.nonInteractiveMode, "Perform the upgrade and do not prompt for confirmation (non-interactive mode).") cmd.Flags().BoolVarP(&flags.force, "force", "f", flags.force, "Force upgrading although some requirements might not be met. This also implies non-interactive mode.") cmd.Flags().BoolVar(&flags.dryRun, "dry-run", flags.dryRun, "Do not change any state, just output what actions would be performed.") cmd.Flags().BoolVar(&flags.etcdUpgrade, "etcd-upgrade", flags.etcdUpgrade, "Perform the upgrade of etcd.") cmd.Flags().DurationVar(&flags.imagePullTimeout, "image-pull-timeout", flags.imagePullTimeout, "The maximum amount of time to wait for the control plane pods to be downloaded.") - + // TODO: Register this flag in a generic place + cmd.Flags().StringVar(&flags.criSocket, "cri-socket", flags.criSocket, "Specify the CRI socket to connect to.") return cmd } @@ -136,33 +148,38 @@ func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command { func RunApply(flags *applyFlags) error { // Start with the basics, verify that the cluster is healthy and get the configuration from the cluster (using the ConfigMap) - upgradeVars, err := enforceRequirements(flags.parent, flags.dryRun, flags.newK8sVersionStr) + glog.V(1).Infof("[upgrade/apply] verifying health of cluster") + glog.V(1).Infof("[upgrade/apply] retrieving configuration from cluster") + upgradeVars, err := enforceRequirements(flags.applyPlanFlags, flags.dryRun, flags.newK8sVersionStr) if err != nil { return err } - // Grab the external, versioned configuration and convert it to the internal type for usage here later - internalcfg := &kubeadmapi.MasterConfiguration{} - legacyscheme.Scheme.Convert(upgradeVars.cfg, internalcfg, nil) + if len(flags.criSocket) != 0 { + fmt.Println("[upgrade/apply] Respecting the --cri-socket flag that is set with higher priority than the config file.") + upgradeVars.cfg.NodeRegistration.CRISocket = flags.criSocket + } // Validate requested and validate actual version - if err := configutil.NormalizeKubernetesVersion(internalcfg); err != nil { + glog.V(1).Infof("[upgrade/apply] validating requested and actual version") + if err := configutil.NormalizeKubernetesVersion(upgradeVars.cfg); err != nil { return err } // Use normalized version string in all following code. - flags.newK8sVersionStr = internalcfg.KubernetesVersion + flags.newK8sVersionStr = upgradeVars.cfg.KubernetesVersion k8sVer, err := version.ParseSemantic(flags.newK8sVersionStr) if err != nil { return fmt.Errorf("unable to parse normalized version %q as a semantic version", flags.newK8sVersionStr) } flags.newK8sVersion = k8sVer - if err := features.ValidateVersion(features.InitFeatureGates, internalcfg.FeatureGates, internalcfg.KubernetesVersion); err != nil { + if err := features.ValidateVersion(features.InitFeatureGates, upgradeVars.cfg.FeatureGates, upgradeVars.cfg.KubernetesVersion); err != nil { return err } // Enforce the version skew policies + glog.V(1).Infof("[upgrade/version] enforcing version skew policies") if err := EnforceVersionPolicies(flags, upgradeVars.versionGetter); err != nil { return fmt.Errorf("[upgrade/version] FATAL: %v", err) } @@ -176,16 +193,19 @@ func RunApply(flags *applyFlags) error { // Use a prepuller implementation based on creating DaemonSets // and block until all DaemonSets are ready; then we know for sure that all control plane images are cached locally - prepuller := upgrade.NewDaemonSetPrepuller(upgradeVars.client, upgradeVars.waiter, internalcfg) + glog.V(1).Infof("[upgrade/apply] creating prepuller") + prepuller := upgrade.NewDaemonSetPrepuller(upgradeVars.client, upgradeVars.waiter, upgradeVars.cfg) upgrade.PrepullImagesInParallel(prepuller, flags.imagePullTimeout) // Now; perform the upgrade procedure - if err := PerformControlPlaneUpgrade(flags, upgradeVars.client, upgradeVars.waiter, internalcfg); err != nil { + glog.V(1).Infof("[upgrade/apply] performing upgrade") + if err := PerformControlPlaneUpgrade(flags, upgradeVars.client, upgradeVars.waiter, upgradeVars.cfg); err != nil { return fmt.Errorf("[upgrade/apply] FATAL: %v", err) } // Upgrade RBAC rules and addons. - if err := upgrade.PerformPostUpgradeTasks(upgradeVars.client, internalcfg, flags.newK8sVersion, flags.dryRun); err != nil { + glog.V(1).Infof("[upgrade/postupgrade] upgrading RBAC rules and addons") + if err := upgrade.PerformPostUpgradeTasks(upgradeVars.client, upgradeVars.cfg, flags.newK8sVersion, flags.dryRun); err != nil { return fmt.Errorf("[upgrade/postupgrade] FATAL post-upgrade error: %v", err) } @@ -197,7 +217,7 @@ func RunApply(flags *applyFlags) error { fmt.Println("") fmt.Printf("[upgrade/successful] SUCCESS! Your cluster was upgraded to %q. Enjoy!\n", flags.newK8sVersionStr) fmt.Println("") - fmt.Println("[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets in turn.") + fmt.Println("[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.") return nil } @@ -221,7 +241,7 @@ func SetImplicitFlags(flags *applyFlags) error { func EnforceVersionPolicies(flags *applyFlags, versionGetter upgrade.VersionGetter) error { fmt.Printf("[upgrade/version] You have chosen to change the cluster version to %q\n", flags.newK8sVersionStr) - versionSkewErrs := upgrade.EnforceVersionPolicies(versionGetter, flags.newK8sVersionStr, flags.newK8sVersion, flags.parent.allowExperimentalUpgrades, flags.parent.allowRCUpgrades) + versionSkewErrs := upgrade.EnforceVersionPolicies(versionGetter, flags.newK8sVersionStr, flags.newK8sVersion, flags.allowExperimentalUpgrades, flags.allowRCUpgrades) if versionSkewErrs != nil { if len(versionSkewErrs.Mandatory) > 0 { @@ -244,10 +264,12 @@ func EnforceVersionPolicies(flags *applyFlags, versionGetter upgrade.VersionGett func PerformControlPlaneUpgrade(flags *applyFlags, client clientset.Interface, waiter apiclient.Waiter, internalcfg *kubeadmapi.MasterConfiguration) error { // Check if the cluster is self-hosted and act accordingly + glog.V(1).Infoln("checking if cluster is self-hosted") if upgrade.IsControlPlaneSelfHosted(client) { fmt.Printf("[upgrade/apply] Upgrading your Self-Hosted control plane to version %q...\n", flags.newK8sVersionStr) // Upgrade the self-hosted cluster + glog.V(1).Infoln("[upgrade/apply] ugrading self-hosted cluster") return upgrade.SelfHostedControlPlane(client, waiter, internalcfg, flags.newK8sVersion) } @@ -258,17 +280,24 @@ func PerformControlPlaneUpgrade(flags *applyFlags, client clientset.Interface, w return DryRunStaticPodUpgrade(internalcfg) } + // Don't save etcd backup directory if etcd is HA, as this could cause corruption return PerformStaticPodUpgrade(client, waiter, internalcfg, flags.etcdUpgrade) } +// GetPathManagerForUpgrade returns a path manager properly configured for the given MasterConfiguration. +func GetPathManagerForUpgrade(internalcfg *kubeadmapi.MasterConfiguration, etcdUpgrade bool) (upgrade.StaticPodPathManager, error) { + isHAEtcd := etcdutil.CheckConfigurationIsHA(&internalcfg.Etcd) + return upgrade.NewKubeStaticPodPathManagerUsingTempDirs(constants.GetStaticPodDirectory(), true, etcdUpgrade && !isHAEtcd) +} + // PerformStaticPodUpgrade performs the upgrade of the control plane components for a static pod hosted cluster func PerformStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter, internalcfg *kubeadmapi.MasterConfiguration, etcdUpgrade bool) error { - pathManager, err := upgrade.NewKubeStaticPodPathManagerUsingTempDirs(constants.GetStaticPodDirectory()) + pathManager, err := GetPathManagerForUpgrade(internalcfg, etcdUpgrade) if err != nil { return err } - // The arguments, oldEtcdClient and newEtdClient, are uninitialized because passing in the clients allow for mocking the client during testing + // The arguments oldEtcdClient and newEtdClient, are uninitialized because passing in the clients allow for mocking the client during testing return upgrade.StaticPodControlPlane(waiter, pathManager, internalcfg, etcdUpgrade, nil, nil) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply_test.go index 24d1778f8..a7cd2394b 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply_test.go @@ -17,8 +17,13 @@ limitations under the License. package upgrade import ( + "io/ioutil" + "os" "reflect" "testing" + + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) func TestSetImplicitFlags(t *testing.T) { @@ -145,3 +150,90 @@ func TestSetImplicitFlags(t *testing.T) { } } } + +func TestGetPathManagerForUpgrade(t *testing.T) { + + haEtcd := &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"10.100.0.1:2379", "10.100.0.2:2379", "10.100.0.3:2379"}, + }, + }, + } + + noHAEtcd := &kubeadmapi.MasterConfiguration{} + + tests := []struct { + name string + cfg *kubeadmapi.MasterConfiguration + etcdUpgrade bool + shouldDeleteEtcd bool + }{ + { + name: "ha etcd but no etcd upgrade", + cfg: haEtcd, + etcdUpgrade: false, + shouldDeleteEtcd: true, + }, + { + name: "non-ha etcd with etcd upgrade", + cfg: noHAEtcd, + etcdUpgrade: true, + shouldDeleteEtcd: false, + }, + { + name: "ha etcd and etcd upgrade", + cfg: haEtcd, + etcdUpgrade: true, + shouldDeleteEtcd: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // Use a temporary directory + tmpdir, err := ioutil.TempDir("", "TestGetPathManagerForUpgrade") + if err != nil { + t.Fatalf("unexpected error making temporary directory: %v", err) + } + oldK8sDir := constants.KubernetesDir + constants.KubernetesDir = tmpdir + defer func() { + constants.KubernetesDir = oldK8sDir + os.RemoveAll(tmpdir) + }() + + pathmgr, err := GetPathManagerForUpgrade(test.cfg, test.etcdUpgrade) + if err != nil { + t.Fatalf("unexpected error creating path manager: %v", err) + } + + if _, err := os.Stat(pathmgr.BackupManifestDir()); os.IsNotExist(err) { + t.Errorf("expected manifest dir %s to exist, but it did not (%v)", pathmgr.BackupManifestDir(), err) + } + + if _, err := os.Stat(pathmgr.BackupEtcdDir()); os.IsNotExist(err) { + t.Errorf("expected etcd dir %s to exist, but it did not (%v)", pathmgr.BackupEtcdDir(), err) + } + + if err := pathmgr.CleanupDirs(); err != nil { + t.Fatalf("unexpected error cleaning up directories: %v", err) + } + + if _, err := os.Stat(pathmgr.BackupManifestDir()); os.IsNotExist(err) { + t.Errorf("expected manifest dir %s to exist, but it did not (%v)", pathmgr.BackupManifestDir(), err) + } + + if test.shouldDeleteEtcd { + if _, err := os.Stat(pathmgr.BackupEtcdDir()); !os.IsNotExist(err) { + t.Errorf("expected etcd dir %s not to exist, but it did (%v)", pathmgr.BackupEtcdDir(), err) + } + } else { + if _, err := os.Stat(pathmgr.BackupEtcdDir()); os.IsNotExist(err) { + t.Errorf("expected etcd dir %s to exist, but it did not", pathmgr.BackupEtcdDir()) + } + } + }) + } + +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go index 254c9afbc..9480c4661 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go @@ -24,16 +24,21 @@ import ( "os" "strings" - "github.com/ghodss/yaml" - + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" fakediscovery "k8s.io/client-go/discovery/fake" clientset "k8s.io/client-go/kubernetes" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" + configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" ) @@ -42,13 +47,14 @@ import ( // TODO - Restructure or rename upgradeVariables type upgradeVariables struct { client clientset.Interface - cfg *kubeadmapiext.MasterConfiguration + cfg *kubeadmapi.MasterConfiguration versionGetter upgrade.VersionGetter waiter apiclient.Waiter } // enforceRequirements verifies that it's okay to upgrade and then returns the variables needed for the rest of the procedure -func enforceRequirements(flags *cmdUpgradeFlags, dryRun bool, newK8sVersion string) (*upgradeVariables, error) { +func enforceRequirements(flags *applyPlanFlags, dryRun bool, newK8sVersion string) (*upgradeVariables, error) { + client, err := getClient(flags.kubeConfigPath, dryRun) if err != nil { return nil, fmt.Errorf("couldn't create a Kubernetes client from file %q: %v", flags.kubeConfigPath, err) @@ -60,8 +66,20 @@ func enforceRequirements(flags *cmdUpgradeFlags, dryRun bool, newK8sVersion stri } // Fetch the configuration from a file or ConfigMap and validate it - cfg, err := upgrade.FetchConfiguration(client, os.Stdout, flags.cfgPath) + fmt.Println("[upgrade/config] Making sure the configuration is correct:") + cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "upgrade/config", flags.cfgPath) if err != nil { + if apierrors.IsNotFound(err) { + fmt.Printf("[upgrade/config] In order to upgrade, a ConfigMap called %q in the %s namespace must exist.\n", constants.MasterConfigurationConfigMap, metav1.NamespaceSystem) + fmt.Println("[upgrade/config] Without this information, 'kubeadm upgrade' won't know how to configure your upgraded cluster.") + fmt.Println("") + fmt.Println("[upgrade/config] Next steps:") + fmt.Printf("\t- OPTION 1: Run 'kubeadm config upload from-flags' and specify the same CLI arguments you passed to 'kubeadm init' when you created your master.\n") + fmt.Printf("\t- OPTION 2: Run 'kubeadm config upload from-file' and specify the same config file you passed to 'kubeadm init' when you created your master.\n") + fmt.Printf("\t- OPTION 3: Pass a config file to 'kubeadm upgrade' using the --config flag.\n") + fmt.Println("") + err = fmt.Errorf("the ConfigMap %q in the %s namespace used for getting configuration information was not found", constants.MasterConfigurationConfigMap, metav1.NamespaceSystem) + } return nil, fmt.Errorf("[upgrade/config] FATAL: %v", err) } @@ -70,34 +88,40 @@ func enforceRequirements(flags *cmdUpgradeFlags, dryRun bool, newK8sVersion stri cfg.KubernetesVersion = newK8sVersion } + // If features gates are passed to the command line, use it (otherwise use featureGates from configuration) + if flags.featureGatesString != "" { + cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, flags.featureGatesString) + if err != nil { + return nil, fmt.Errorf("[upgrade/config] FATAL: %v", err) + } + } + // If the user told us to print this information out; do it! if flags.printConfig { printConfiguration(cfg, os.Stdout) } - cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, flags.featureGatesString) - if err != nil { - return nil, fmt.Errorf("[upgrade/config] FATAL: %v", err) - } - return &upgradeVariables{ client: client, cfg: cfg, // Use a real version getter interface that queries the API server, the kubeadm client and the Kubernetes CI system for latest versions - versionGetter: upgrade.NewKubeVersionGetter(client, os.Stdout), + versionGetter: upgrade.NewOfflineVersionGetter(upgrade.NewKubeVersionGetter(client, os.Stdout), newK8sVersion), // Use the waiter conditionally based on the dryrunning variable waiter: getWaiter(dryRun, client), }, nil } // printConfiguration prints the external version of the API to yaml -func printConfiguration(cfg *kubeadmapiext.MasterConfiguration, w io.Writer) { +func printConfiguration(cfg *kubeadmapi.MasterConfiguration, w io.Writer) { // Short-circuit if cfg is nil, so we can safely get the value of the pointer below if cfg == nil { return } - cfgYaml, err := yaml.Marshal(*cfg) + externalcfg := &kubeadmapiv1alpha2.MasterConfiguration{} + kubeadmscheme.Scheme.Convert(cfg, externalcfg, nil) + + cfgYaml, err := kubeadmutil.MarshalToYamlForCodecs(externalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs) if err == nil { fmt.Fprintln(w, "[upgrade/config] Configuration used:") @@ -131,7 +155,10 @@ func getClient(file string, dryRun bool) (clientset.Interface, error) { } // Get the fake clientset - fakeclient := apiclient.NewDryRunClient(dryRunGetter, os.Stdout) + dryRunOpts := apiclient.GetDefaultDryRunClientOptions(dryRunGetter, os.Stdout) + // Print GET and LIST requests + dryRunOpts.PrintGETAndLIST = true + fakeclient := apiclient.NewDryRunClientWithOpts(dryRunOpts) // As we know the return of Discovery() of the fake clientset is of type *fakediscovery.FakeDiscovery // we can convert it to that struct. fakeclientDiscovery, ok := fakeclient.Discovery().(*fakediscovery.FakeDiscovery) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common_test.go index 05515e3a0..7c0465515 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common_test.go @@ -20,12 +20,12 @@ import ( "bytes" "testing" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" ) func TestPrintConfiguration(t *testing.T) { var tests = []struct { - cfg *kubeadmapiext.MasterConfiguration + cfg *kubeadmapi.MasterConfiguration buf *bytes.Buffer expectedBytes []byte }{ @@ -34,27 +34,30 @@ func TestPrintConfiguration(t *testing.T) { expectedBytes: []byte(""), }, { - cfg: &kubeadmapiext.MasterConfiguration{ + cfg: &kubeadmapi.MasterConfiguration{ KubernetesVersion: "v1.7.1", + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + DataDir: "/some/path", + }, + }, }, expectedBytes: []byte(`[upgrade/config] Configuration used: api: advertiseAddress: "" bindPort: 0 controlPlaneEndpoint: "" + apiVersion: kubeadm.k8s.io/v1alpha2 auditPolicy: logDir: "" path: "" certificatesDir: "" - cloudProvider: "" etcd: - caFile: "" - certFile: "" - dataDir: "" - endpoints: null - image: "" - keyFile: "" + local: + dataDir: /some/path + image: "" imageRepository: "" + kind: MasterConfiguration kubeProxy: {} kubeletConfiguration: {} kubernetesVersion: v1.7.1 @@ -62,59 +65,19 @@ func TestPrintConfiguration(t *testing.T) { dnsDomain: "" podSubnet: "" serviceSubnet: "" - nodeName: "" - privilegedPods: false - token: "" + nodeRegistration: {} unifiedControlPlaneImage: "" `), }, { - cfg: &kubeadmapiext.MasterConfiguration{ + cfg: &kubeadmapi.MasterConfiguration{ KubernetesVersion: "v1.7.1", - Networking: kubeadmapiext.Networking{ + Networking: kubeadmapi.Networking{ ServiceSubnet: "10.96.0.1/12", }, - }, - expectedBytes: []byte(`[upgrade/config] Configuration used: - api: - advertiseAddress: "" - bindPort: 0 - controlPlaneEndpoint: "" - auditPolicy: - logDir: "" - path: "" - certificatesDir: "" - cloudProvider: "" - etcd: - caFile: "" - certFile: "" - dataDir: "" - endpoints: null - image: "" - keyFile: "" - imageRepository: "" - kubeProxy: {} - kubeletConfiguration: {} - kubernetesVersion: v1.7.1 - networking: - dnsDomain: "" - podSubnet: "" - serviceSubnet: 10.96.0.1/12 - nodeName: "" - privilegedPods: false - token: "" - unifiedControlPlaneImage: "" -`), - }, - { - cfg: &kubeadmapiext.MasterConfiguration{ - KubernetesVersion: "v1.7.1", - Etcd: kubeadmapiext.Etcd{ - SelfHosted: &kubeadmapiext.SelfHostedEtcd{ - CertificatesDir: "/var/foo", - ClusterServiceName: "foo", - EtcdVersion: "v0.1.0", - OperatorVersion: "v0.1.0", + Etcd: kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"https://one-etcd-instance:2379"}, }, }, }, @@ -123,34 +86,28 @@ func TestPrintConfiguration(t *testing.T) { advertiseAddress: "" bindPort: 0 controlPlaneEndpoint: "" + apiVersion: kubeadm.k8s.io/v1alpha2 auditPolicy: logDir: "" path: "" certificatesDir: "" - cloudProvider: "" etcd: - caFile: "" - certFile: "" - dataDir: "" - endpoints: null - image: "" - keyFile: "" - selfHosted: - certificatesDir: /var/foo - clusterServiceName: foo - etcdVersion: v0.1.0 - operatorVersion: v0.1.0 + external: + caFile: "" + certFile: "" + endpoints: + - https://one-etcd-instance:2379 + keyFile: "" imageRepository: "" + kind: MasterConfiguration kubeProxy: {} kubeletConfiguration: {} kubernetesVersion: v1.7.1 networking: dnsDomain: "" podSubnet: "" - serviceSubnet: "" - nodeName: "" - privilegedPods: false - token: "" + serviceSubnet: 10.96.0.1/12 + nodeRegistration: {} unifiedControlPlaneImage: "" `), }, diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff.go new file mode 100644 index 000000000..47180a54f --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff.go @@ -0,0 +1,147 @@ +/* +Copyright 2018 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 upgrade + +import ( + "fmt" + "io" + "io/ioutil" + + "github.com/golang/glog" + "github.com/pmezard/go-difflib/difflib" + "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" + kubeadmv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" + "k8s.io/kubernetes/pkg/util/version" +) + +type diffFlags struct { + apiServerManifestPath string + controllerManagerManifestPath string + schedulerManifestPath string + newK8sVersionStr string + contextLines int + cfgPath string + out io.Writer +} + +var ( + defaultAPIServerManifestPath = constants.GetStaticPodFilepath(constants.KubeAPIServer, constants.GetStaticPodDirectory()) + defaultControllerManagerManifestPath = constants.GetStaticPodFilepath(constants.KubeControllerManager, constants.GetStaticPodDirectory()) + defaultSchedulerManifestPath = constants.GetStaticPodFilepath(constants.KubeScheduler, constants.GetStaticPodDirectory()) +) + +// NewCmdDiff returns the cobra command for `kubeadm upgrade diff` +func NewCmdDiff(out io.Writer) *cobra.Command { + flags := &diffFlags{ + out: out, + } + + cmd := &cobra.Command{ + Use: "diff [version]", + Short: "Show what differences would be applied to existing static pod manifests. See also: kubeadm upgrade apply --dry-run", + Run: func(cmd *cobra.Command, args []string) { + // TODO: Run preflight checks for diff to check that the manifests already exist. + kubeadmutil.CheckErr(runDiff(flags, args)) + }, + } + + // TODO: Use the generic options.AddConfigFlag method instead + cmd.Flags().StringVar(&flags.cfgPath, "config", flags.cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental!") + cmd.Flags().StringVar(&flags.apiServerManifestPath, "api-server-manifest", defaultAPIServerManifestPath, "path to API server manifest") + cmd.Flags().StringVar(&flags.controllerManagerManifestPath, "controller-manager-manifest", defaultControllerManagerManifestPath, "path to controller manifest") + cmd.Flags().StringVar(&flags.schedulerManifestPath, "scheduler-manifest", defaultSchedulerManifestPath, "path to scheduler manifest") + cmd.Flags().IntVarP(&flags.contextLines, "context-lines", "c", 3, "How many lines of context in the diff") + + return cmd +} + +func runDiff(flags *diffFlags, args []string) error { + + // If the version is specified in config file, pick up that value. + glog.V(1).Infof("fetching configuration from file", flags.cfgPath) + cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.cfgPath, &kubeadmv1alpha2.MasterConfiguration{}) + if err != nil { + return err + } + + if cfg.KubernetesVersion != "" { + flags.newK8sVersionStr = cfg.KubernetesVersion + } + + // If the new version is already specified in config file, version arg is optional. + if flags.newK8sVersionStr == "" { + if err := cmdutil.ValidateExactArgNumber(args, []string{"version"}); err != nil { + return err + } + } + + // If option was specified in both args and config file, args will overwrite the config file. + if len(args) == 1 { + flags.newK8sVersionStr = args[0] + } + + k8sVer, err := version.ParseSemantic(flags.newK8sVersionStr) + if err != nil { + return err + } + + specs := controlplane.GetStaticPodSpecs(cfg, k8sVer) + for spec, pod := range specs { + var path string + switch spec { + case constants.KubeAPIServer: + path = flags.apiServerManifestPath + case constants.KubeControllerManager: + path = flags.controllerManagerManifestPath + case constants.KubeScheduler: + path = flags.schedulerManifestPath + default: + glog.Errorf("[diff] unknown spec %v", spec) + continue + } + + newManifest, err := kubeadmutil.MarshalToYaml(&pod, corev1.SchemeGroupVersion) + if err != nil { + return err + } + if path == "" { + return fmt.Errorf("empty manifest path") + } + existingManifest, err := ioutil.ReadFile(path) + if err != nil { + return err + } + + // Populated and write out the diff + diff := difflib.UnifiedDiff{ + A: difflib.SplitLines(string(existingManifest)), + B: difflib.SplitLines(string(newManifest)), + FromFile: path, + ToFile: "new manifest", + Context: flags.contextLines, + } + + difflib.WriteUnifiedDiff(flags.out, diff) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff_test.go new file mode 100644 index 000000000..a4de23b10 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff_test.go @@ -0,0 +1,90 @@ +/* +Copyright 2018 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 upgrade + +import ( + "io/ioutil" + "testing" +) + +const ( + testUpgradeDiffConfig = `testdata/diff_master_config.yaml` + testUpgradeDiffManifest = `testdata/diff_dummy_manifest.yaml` +) + +func TestRunDiff(t *testing.T) { + flags := &diffFlags{ + cfgPath: "", + out: ioutil.Discard, + } + + testCases := []struct { + name string + args []string + setManifestPath bool + manifestPath string + cfgPath string + expectedError bool + }{ + { + name: "valid: run diff on valid manifest path", + cfgPath: testUpgradeDiffConfig, + setManifestPath: true, + manifestPath: testUpgradeDiffManifest, + expectedError: false, + }, + { + name: "invalid: missing config file", + cfgPath: "missing-path-to-a-config", + expectedError: true, + }, + { + name: "invalid: valid config but empty manifest path", + cfgPath: testUpgradeDiffConfig, + setManifestPath: true, + manifestPath: "", + expectedError: true, + }, + { + name: "invalid: valid config but bad manifest path", + cfgPath: testUpgradeDiffConfig, + setManifestPath: true, + manifestPath: "bad-path", + expectedError: true, + }, + { + name: "invalid: badly formatted version as argument", + cfgPath: testUpgradeDiffConfig, + args: []string{"bad-version"}, + expectedError: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + flags.cfgPath = tc.cfgPath + if tc.setManifestPath { + flags.apiServerManifestPath = tc.manifestPath + flags.controllerManagerManifestPath = tc.manifestPath + flags.schedulerManifestPath = tc.manifestPath + } + if err := runDiff(flags, tc.args); (err != nil) != tc.expectedError { + t.Fatalf("expected error: %v, saw: %v, error: %v", tc.expectedError, (err != nil), err) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/node.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/node.go new file mode 100644 index 000000000..0c51d7cb7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/node.go @@ -0,0 +1,158 @@ +/* +Copyright 2018 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 upgrade + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "github.com/spf13/cobra" + + cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" + "k8s.io/kubernetes/pkg/util/normalizer" + "k8s.io/kubernetes/pkg/util/version" +) + +var ( + upgradeNodeConfigLongDesc = normalizer.LongDesc(` + Downloads the kubelet configuration from a ConfigMap of the form "kubelet-config-1.X" in the cluster, + where X is the minor version of the kubelet. kubeadm uses the --kubelet-version parameter to determine + what the _desired_ kubelet version is. Give + `) + + upgradeNodeConfigExample = normalizer.Examples(` + # Downloads the kubelet configuration from the ConfigMap in the cluster. Uses a specific desired kubelet version. + kubeadm upgrade node config --kubelet-version v1.11.0 + + # Simulates the downloading of the kubelet configuration from the ConfigMap in the cluster with a specific desired + # version. Does not change any state locally on the node. + kubeadm upgrade node config --kubelet-version v1.11.0 --dry-run + `) +) + +type nodeUpgradeFlags struct { + kubeConfigPath string + kubeletVersionStr string + dryRun bool +} + +// NewCmdNode returns the cobra command for `kubeadm upgrade node` +func NewCmdNode() *cobra.Command { + cmd := &cobra.Command{ + Use: "node", + Short: "Upgrade commands for a node in the cluster. Currently only supports upgrading the configuration, not the kubelet itself.", + RunE: cmdutil.SubCmdRunE("node"), + } + cmd.AddCommand(NewCmdUpgradeNodeConfig()) + return cmd +} + +// NewCmdUpgradeNodeConfig returns the cobra.Command for downloading the new/upgrading the kubelet configuration from the kubelet-config-1.X +// ConfigMap in the cluster +func NewCmdUpgradeNodeConfig() *cobra.Command { + flags := &nodeUpgradeFlags{ + kubeConfigPath: constants.GetKubeletKubeConfigPath(), + kubeletVersionStr: "", + dryRun: false, + } + + cmd := &cobra.Command{ + Use: "config", + Short: "Downloads the kubelet configuration from the cluster ConfigMap kubelet-config-1.X, where X is the minor version of the kubelet.", + Long: upgradeNodeConfigLongDesc, + Example: upgradeNodeConfigExample, + Run: func(cmd *cobra.Command, args []string) { + err := RunUpgradeNodeConfig(flags) + kubeadmutil.CheckErr(err) + }, + } + + // TODO: Unify the registration of common flags and e.g. use the generic options.AddKubeConfigFlag method instead + cmd.Flags().StringVar(&flags.kubeConfigPath, "kubeconfig", flags.kubeConfigPath, "The KubeConfig file to use when talking to the cluster.") + cmd.Flags().BoolVar(&flags.dryRun, "dry-run", flags.dryRun, "Do not change any state, just output the actions that would be performed.") + cmd.Flags().StringVar(&flags.kubeletVersionStr, "kubelet-version", flags.kubeletVersionStr, "The *desired* version for the kubelet after the upgrade.") + return cmd +} + +// RunUpgradeNodeConfig is executed when `kubeadm upgrade node config` runs. +func RunUpgradeNodeConfig(flags *nodeUpgradeFlags) error { + if len(flags.kubeletVersionStr) == 0 { + return fmt.Errorf("The --kubelet-version argument is required") + } + + // Set up the kubelet directory to use. If dry-running, use a fake directory + kubeletDir, err := getKubeletDir(flags.dryRun) + if err != nil { + return err + } + + client, err := getClient(flags.kubeConfigPath, flags.dryRun) + if err != nil { + return fmt.Errorf("couldn't create a Kubernetes client from file %q: %v", flags.kubeConfigPath, err) + } + + // Parse the desired kubelet version + kubeletVersion, err := version.ParseSemantic(flags.kubeletVersionStr) + if err != nil { + return err + } + // TODO: Checkpoint the current configuration first so that if something goes wrong it can be recovered + if err := kubeletphase.DownloadConfig(client, kubeletVersion, kubeletDir); err != nil { + return err + } + + // If we're dry-running, print the generated manifests, otherwise do nothing + if err := printFilesIfDryRunning(flags.dryRun, kubeletDir); err != nil { + return fmt.Errorf("error printing files on dryrun: %v", err) + } + + fmt.Println("[upgrade] The configuration for this node was successfully updated!") + fmt.Println("[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.") + return nil +} + +// getKubeletDir gets the kubelet directory based on whether the user is dry-running this command or not. +func getKubeletDir(dryRun bool) (string, error) { + if dryRun { + dryRunDir, err := ioutil.TempDir("", "kubeadm-init-dryrun") + if err != nil { + return "", fmt.Errorf("couldn't create a temporary directory: %v", err) + } + return dryRunDir, nil + } + return constants.KubeletRunDirectory, nil +} + +// printFilesIfDryRunning prints the Static Pod manifests to stdout and informs about the temporary directory to go and lookup +func printFilesIfDryRunning(dryRun bool, kubeletDir string) error { + if !dryRun { + return nil + } + + // Print the contents of the upgraded file and pretend like they were in kubeadmconstants.KubeletRunDirectory + fileToPrint := dryrunutil.FileToPrint{ + RealPath: filepath.Join(kubeletDir, constants.KubeletConfigurationFileName), + PrintPath: filepath.Join(constants.KubeletRunDirectory, constants.KubeletConfigurationFileName), + } + return dryrunutil.PrintDryRunFiles([]dryrunutil.FileToPrint{fileToPrint}, os.Stdout) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan.go index 375fccf53..c0409229c 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan.go @@ -23,41 +23,72 @@ import ( "sort" "text/tabwriter" + "github.com/golang/glog" "github.com/spf13/cobra" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd" ) +type planFlags struct { + *applyPlanFlags + + newK8sVersionStr string +} + // NewCmdPlan returns the cobra command for `kubeadm upgrade plan` -func NewCmdPlan(parentFlags *cmdUpgradeFlags) *cobra.Command { +func NewCmdPlan(apf *applyPlanFlags) *cobra.Command { + flags := &planFlags{ + applyPlanFlags: apf, + } + cmd := &cobra.Command{ - Use: "plan", - Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable.", - Run: func(_ *cobra.Command, _ []string) { + Use: "plan [version] [flags]", + Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter.", + Run: func(_ *cobra.Command, args []string) { var err error - parentFlags.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(parentFlags.ignorePreflightErrors, parentFlags.skipPreFlight) + flags.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(flags.ignorePreflightErrors, flags.skipPreFlight) kubeadmutil.CheckErr(err) // Ensure the user is root - err = runPreflightChecks(parentFlags.ignorePreflightErrorsSet) + err = runPreflightChecks(flags.ignorePreflightErrorsSet) kubeadmutil.CheckErr(err) - err = RunPlan(parentFlags) + // If the version is specified in config file, pick up that value. + if flags.cfgPath != "" { + glog.V(1).Infof("fetching configuration from file", flags.cfgPath) + cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{}) + kubeadmutil.CheckErr(err) + + if cfg.KubernetesVersion != "" { + flags.newK8sVersionStr = cfg.KubernetesVersion + } + } + // If option was specified in both args and config file, args will overwrite the config file. + if len(args) == 1 { + flags.newK8sVersionStr = args[0] + } + + err = RunPlan(flags) kubeadmutil.CheckErr(err) }, } + // Register the common flags for apply and plan + addApplyPlanFlags(cmd.Flags(), flags.applyPlanFlags) return cmd } // RunPlan takes care of outputting available versions to upgrade to for the user -func RunPlan(parentFlags *cmdUpgradeFlags) error { +func RunPlan(flags *planFlags) error { // Start with the basics, verify that the cluster is healthy, build a client and a versionGetter. Never dry-run when planning. - upgradeVars, err := enforceRequirements(parentFlags, false, "") + glog.V(1).Infof("[upgrade/plan] verifying health of cluster") + glog.V(1).Infof("[upgrade/plan] retrieving configuration from cluster") + upgradeVars, err := enforceRequirements(flags.applyPlanFlags, false, flags.newK8sVersionStr) if err != nil { return err } @@ -66,13 +97,13 @@ func RunPlan(parentFlags *cmdUpgradeFlags) error { // Currently this is the only method we have for distinguishing // external etcd vs static pod etcd - isExternalEtcd := len(upgradeVars.cfg.Etcd.Endpoints) > 0 + isExternalEtcd := upgradeVars.cfg.Etcd.External != nil if isExternalEtcd { client, err := etcdutil.New( - upgradeVars.cfg.Etcd.Endpoints, - upgradeVars.cfg.Etcd.CAFile, - upgradeVars.cfg.Etcd.CertFile, - upgradeVars.cfg.Etcd.KeyFile) + upgradeVars.cfg.Etcd.External.Endpoints, + upgradeVars.cfg.Etcd.External.CAFile, + upgradeVars.cfg.Etcd.External.CertFile, + upgradeVars.cfg.Etcd.External.KeyFile) if err != nil { return err } @@ -90,20 +121,20 @@ func RunPlan(parentFlags *cmdUpgradeFlags) error { } // Compute which upgrade possibilities there are - fmt.Println("[upgrade/plan] computing upgrade possibilities") - availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, parentFlags.allowExperimentalUpgrades, parentFlags.allowRCUpgrades, etcdClient, upgradeVars.cfg.FeatureGates) + glog.V(1).Infof("[upgrade/plan] computing upgrade possibilities") + availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, flags.allowExperimentalUpgrades, flags.allowRCUpgrades, etcdClient, upgradeVars.cfg.FeatureGates, upgradeVars.client) if err != nil { return fmt.Errorf("[upgrade/versions] FATAL: %v", err) } // Tell the user which upgrades are available - printAvailableUpgrades(availUpgrades, os.Stdout, upgradeVars.cfg.FeatureGates, isExternalEtcd) + printAvailableUpgrades(availUpgrades, os.Stdout, isExternalEtcd) return nil } // printAvailableUpgrades prints a UX-friendly overview of what versions are available to upgrade to // TODO look into columnize or some other formatter when time permits instead of using the tabwriter -func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, featureGates map[string]bool, isExternalEtcd bool) { +func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, isExternalEtcd bool) { // Return quickly if no upgrades can be made if len(upgrades) == 0 { @@ -141,7 +172,7 @@ func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, featureGate firstPrinted = true continue } - fmt.Fprintf(tabw, "\t\t%d x %s\t%s\n", nodeCount, oldVersion, upgrade.After.KubeVersion) + fmt.Fprintf(tabw, "\t%d x %s\t%s\n", nodeCount, oldVersion, upgrade.After.KubeVersion) } // We should flush the writer here at this stage; as the columns will now be of the right size, adjusted to the above content tabw.Flush() @@ -155,11 +186,37 @@ func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, featureGate fmt.Fprintf(tabw, "Controller Manager\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion) fmt.Fprintf(tabw, "Scheduler\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion) fmt.Fprintf(tabw, "Kube Proxy\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion) - if features.Enabled(featureGates, features.CoreDNS) { - fmt.Fprintf(tabw, "CoreDNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion) - } else { - fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion) + + // TODO There is currently no way to cleanly output upgrades that involve adding, removing, or changing components + // https://github.com/kubernetes/kubeadm/issues/810 was created to track addressing this. + printCoreDNS, printKubeDNS := false, false + coreDNSBeforeVersion, coreDNSAfterVersion, kubeDNSBeforeVersion, kubeDNSAfterVersion := "", "", "", "" + + switch upgrade.Before.DNSType { + case constants.CoreDNS: + printCoreDNS = true + coreDNSBeforeVersion = upgrade.Before.DNSVersion + case constants.KubeDNS: + printKubeDNS = true + kubeDNSBeforeVersion = upgrade.Before.DNSVersion + } + + switch upgrade.After.DNSType { + case constants.CoreDNS: + printCoreDNS = true + coreDNSAfterVersion = upgrade.After.DNSVersion + case constants.KubeDNS: + printKubeDNS = true + kubeDNSAfterVersion = upgrade.After.DNSVersion } + + if printCoreDNS { + fmt.Fprintf(tabw, "CoreDNS\t%s\t%s\n", coreDNSBeforeVersion, coreDNSAfterVersion) + } + if printKubeDNS { + fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", kubeDNSBeforeVersion, kubeDNSAfterVersion) + } + if !isExternalEtcd { fmt.Fprintf(tabw, "Etcd\t%s\t%s\n", upgrade.Before.EtcdVersion, upgrade.After.EtcdVersion) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan_test.go index 95886766d..f8513d660 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan_test.go @@ -60,7 +60,6 @@ func TestSortedSliceFromStringIntMap(t *testing.T) { // TODO Think about modifying this test to be less verbose checking b/c it can be brittle. func TestPrintAvailableUpgrades(t *testing.T) { - featureGates := make(map[string]bool) var tests = []struct { name string upgrades []upgrade.Upgrade @@ -92,12 +91,14 @@ func TestPrintAvailableUpgrades(t *testing.T) { "v1.8.1": 1, }, KubeadmVersion: "v1.8.2", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.8.3", KubeadmVersion: "v1.8.3", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, @@ -138,13 +139,15 @@ _____________________________________________________________________ "v1.8.3": 1, }, KubeadmVersion: "v1.9.0", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.0", KubeadmVersion: "v1.9.0", - DNSVersion: "1.14.8", + DNSType: "kube-dns", + DNSVersion: "1.14.10", EtcdVersion: "3.1.12", }, }, @@ -160,7 +163,7 @@ API Server v1.8.3 v1.9.0 Controller Manager v1.8.3 v1.9.0 Scheduler v1.8.3 v1.9.0 Kube Proxy v1.8.3 v1.9.0 -Kube DNS 1.14.5 1.14.8 +Kube DNS 1.14.5 1.14.10 Etcd 3.0.17 3.1.12 You can now apply the upgrade by executing the following command: @@ -182,12 +185,14 @@ _____________________________________________________________________ "v1.8.3": 1, }, KubeadmVersion: "v1.8.3", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.8.5", KubeadmVersion: "v1.8.3", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, @@ -200,13 +205,15 @@ _____________________________________________________________________ "v1.8.3": 1, }, KubeadmVersion: "v1.8.3", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.0", KubeadmVersion: "v1.9.0", - DNSVersion: "1.14.8", + DNSType: "kube-dns", + DNSVersion: "1.14.10", EtcdVersion: "3.1.12", }, }, @@ -242,7 +249,7 @@ API Server v1.8.3 v1.9.0 Controller Manager v1.8.3 v1.9.0 Scheduler v1.8.3 v1.9.0 Kube Proxy v1.8.3 v1.9.0 -Kube DNS 1.14.5 1.14.8 +Kube DNS 1.14.5 1.14.10 Etcd 3.0.17 3.1.12 You can now apply the upgrade by executing the following command: @@ -266,13 +273,15 @@ _____________________________________________________________________ "v1.8.5": 1, }, KubeadmVersion: "v1.8.5", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.0-beta.1", KubeadmVersion: "v1.9.0-beta.1", - DNSVersion: "1.14.8", + DNSType: "kube-dns", + DNSVersion: "1.14.10", EtcdVersion: "3.1.12", }, }, @@ -288,7 +297,7 @@ API Server v1.8.5 v1.9.0-beta.1 Controller Manager v1.8.5 v1.9.0-beta.1 Scheduler v1.8.5 v1.9.0-beta.1 Kube Proxy v1.8.5 v1.9.0-beta.1 -Kube DNS 1.14.5 1.14.8 +Kube DNS 1.14.5 1.14.10 Etcd 3.0.17 3.1.12 You can now apply the upgrade by executing the following command: @@ -312,13 +321,15 @@ _____________________________________________________________________ "v1.8.5": 1, }, KubeadmVersion: "v1.8.5", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.0-rc.1", KubeadmVersion: "v1.9.0-rc.1", - DNSVersion: "1.14.8", + DNSType: "kube-dns", + DNSVersion: "1.14.10", EtcdVersion: "3.1.12", }, }, @@ -334,7 +345,7 @@ API Server v1.8.5 v1.9.0-rc.1 Controller Manager v1.8.5 v1.9.0-rc.1 Scheduler v1.8.5 v1.9.0-rc.1 Kube Proxy v1.8.5 v1.9.0-rc.1 -Kube DNS 1.14.5 1.14.8 +Kube DNS 1.14.5 1.14.10 Etcd 3.0.17 3.1.12 You can now apply the upgrade by executing the following command: @@ -347,6 +358,57 @@ _____________________________________________________________________ `), }, + { + name: "multiple kubelet versions", + upgrades: []upgrade.Upgrade{ + { + Description: "version in the v1.9 series", + Before: upgrade.ClusterState{ + KubeVersion: "v1.9.2", + KubeletVersions: map[string]uint16{ + "v1.9.2": 1, + "v1.9.3": 2, + }, + KubeadmVersion: "v1.9.2", + DNSType: "kube-dns", + DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", + }, + After: upgrade.ClusterState{ + KubeVersion: "v1.9.3", + KubeadmVersion: "v1.9.3", + DNSType: "kube-dns", + DNSVersion: "1.14.8", + EtcdVersion: "3.1.12", + }, + }, + }, + expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': +COMPONENT CURRENT AVAILABLE +Kubelet 1 x v1.9.2 v1.9.3 + 2 x v1.9.3 v1.9.3 + +Upgrade to the latest version in the v1.9 series: + +COMPONENT CURRENT AVAILABLE +API Server v1.9.2 v1.9.3 +Controller Manager v1.9.2 v1.9.3 +Scheduler v1.9.2 v1.9.3 +Kube Proxy v1.9.2 v1.9.3 +Kube DNS 1.14.5 1.14.8 +Etcd 3.0.17 3.1.12 + +You can now apply the upgrade by executing the following command: + + kubeadm upgrade apply v1.9.3 + +Note: Before you can perform this upgrade, you have to update kubeadm to v1.9.3. + +_____________________________________________________________________ + +`), + }, + { name: "external etcd upgrade available", upgrades: []upgrade.Upgrade{ @@ -358,12 +420,14 @@ _____________________________________________________________________ "v1.9.2": 1, }, KubeadmVersion: "v1.9.2", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.3", KubeadmVersion: "v1.9.3", + DNSType: "kube-dns", DNSVersion: "1.14.8", EtcdVersion: "3.1.12", }, @@ -395,13 +459,153 @@ Note: Before you can perform this upgrade, you have to update kubeadm to v1.9.3. _____________________________________________________________________ +`), + }, + { + name: "kubedns to coredns", + upgrades: []upgrade.Upgrade{ + { + Description: "kubedns to coredns", + Before: upgrade.ClusterState{ + KubeVersion: "v1.10.2", + KubeletVersions: map[string]uint16{ + "v1.10.2": 1, + }, + KubeadmVersion: "v1.11.0", + DNSType: "kube-dns", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.11", + }, + After: upgrade.ClusterState{ + KubeVersion: "v1.11.0", + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.2.18", + }, + }, + }, + expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': +COMPONENT CURRENT AVAILABLE +Kubelet 1 x v1.10.2 v1.11.0 + +Upgrade to the latest kubedns to coredns: + +COMPONENT CURRENT AVAILABLE +API Server v1.10.2 v1.11.0 +Controller Manager v1.10.2 v1.11.0 +Scheduler v1.10.2 v1.11.0 +Kube Proxy v1.10.2 v1.11.0 +CoreDNS 1.0.6 +Kube DNS 1.14.7 +Etcd 3.1.11 3.2.18 + +You can now apply the upgrade by executing the following command: + + kubeadm upgrade apply v1.11.0 + +_____________________________________________________________________ + +`), + }, + { + name: "coredns", + upgrades: []upgrade.Upgrade{ + { + Description: "coredns", + Before: upgrade.ClusterState{ + KubeVersion: "v1.10.2", + KubeletVersions: map[string]uint16{ + "v1.10.2": 1, + }, + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.5", + EtcdVersion: "3.1.11", + }, + After: upgrade.ClusterState{ + KubeVersion: "v1.11.0", + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.2.18", + }, + }, + }, + expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': +COMPONENT CURRENT AVAILABLE +Kubelet 1 x v1.10.2 v1.11.0 + +Upgrade to the latest coredns: + +COMPONENT CURRENT AVAILABLE +API Server v1.10.2 v1.11.0 +Controller Manager v1.10.2 v1.11.0 +Scheduler v1.10.2 v1.11.0 +Kube Proxy v1.10.2 v1.11.0 +CoreDNS 1.0.5 1.0.6 +Etcd 3.1.11 3.2.18 + +You can now apply the upgrade by executing the following command: + + kubeadm upgrade apply v1.11.0 + +_____________________________________________________________________ + +`), + }, + { + name: "coredns to kubedns", + upgrades: []upgrade.Upgrade{ + { + Description: "coredns to kubedns", + Before: upgrade.ClusterState{ + KubeVersion: "v1.10.2", + KubeletVersions: map[string]uint16{ + "v1.10.2": 1, + }, + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.1.11", + }, + After: upgrade.ClusterState{ + KubeVersion: "v1.11.0", + KubeadmVersion: "v1.11.0", + DNSType: "kube-dns", + DNSVersion: "1.14.9", + EtcdVersion: "3.2.18", + }, + }, + }, + expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': +COMPONENT CURRENT AVAILABLE +Kubelet 1 x v1.10.2 v1.11.0 + +Upgrade to the latest coredns to kubedns: + +COMPONENT CURRENT AVAILABLE +API Server v1.10.2 v1.11.0 +Controller Manager v1.10.2 v1.11.0 +Scheduler v1.10.2 v1.11.0 +Kube Proxy v1.10.2 v1.11.0 +CoreDNS 1.0.6 +Kube DNS 1.14.9 +Etcd 3.1.11 3.2.18 + +You can now apply the upgrade by executing the following command: + + kubeadm upgrade apply v1.11.0 + +_____________________________________________________________________ + `), }, } for _, rt := range tests { t.Run(rt.name, func(t *testing.T) { rt.buf = bytes.NewBufferString("") - printAvailableUpgrades(rt.upgrades, rt.buf, featureGates, rt.externalEtcd) + printAvailableUpgrades(rt.upgrades, rt.buf, rt.externalEtcd) actualBytes := rt.buf.Bytes() if !bytes.Equal(actualBytes, rt.expectedBytes) { t.Errorf( diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/testdata/diff_dummy_manifest.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/testdata/diff_dummy_manifest.yaml new file mode 100644 index 000000000..b65b6743b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/testdata/diff_dummy_manifest.yaml @@ -0,0 +1 @@ +some-empty-file-to-diff diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/testdata/diff_master_config.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/testdata/diff_master_config.yaml new file mode 100644 index 000000000..7bfbed601 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/testdata/diff_master_config.yaml @@ -0,0 +1,3 @@ +apiVersion: kubeadm.k8s.io/v1alpha1 +kind: MasterConfiguration +kubernetesVersion: 1.11.0 diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/upgrade.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/upgrade.go index a78a3dad0..f361be602 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/upgrade.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/upgrade.go @@ -21,13 +21,15 @@ import ( "strings" "github.com/spf13/cobra" + "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/util/sets" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/features" ) -// cmdUpgradeFlags holds the values for the common flags in `kubeadm upgrade` -type cmdUpgradeFlags struct { +// applyPlanFlags holds the values for the common flags in `kubeadm upgrade apply` and `kubeadm upgrade plan` +type applyPlanFlags struct { kubeConfigPath string cfgPath string featureGatesString string @@ -37,11 +39,12 @@ type cmdUpgradeFlags struct { skipPreFlight bool ignorePreflightErrors []string ignorePreflightErrorsSet sets.String + out io.Writer } // NewCmdUpgrade returns the cobra command for `kubeadm upgrade` func NewCmdUpgrade(out io.Writer) *cobra.Command { - flags := &cmdUpgradeFlags{ + flags := &applyPlanFlags{ kubeConfigPath: "/etc/kubernetes/admin.conf", cfgPath: "", featureGatesString: "", @@ -50,6 +53,7 @@ func NewCmdUpgrade(out io.Writer) *cobra.Command { printConfig: false, skipPreFlight: false, ignorePreflightErrorsSet: sets.NewString(), + out: out, } cmd := &cobra.Command{ @@ -58,19 +62,24 @@ func NewCmdUpgrade(out io.Writer) *cobra.Command { RunE: cmdutil.SubCmdRunE("upgrade"), } - cmd.PersistentFlags().StringVar(&flags.kubeConfigPath, "kubeconfig", flags.kubeConfigPath, "The KubeConfig file to use when talking to the cluster.") - cmd.PersistentFlags().StringVar(&flags.cfgPath, "config", flags.cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental!") - cmd.PersistentFlags().BoolVar(&flags.allowExperimentalUpgrades, "allow-experimental-upgrades", flags.allowExperimentalUpgrades, "Show unstable versions of Kubernetes as an upgrade alternative and allow upgrading to an alpha/beta/release candidate versions of Kubernetes.") - cmd.PersistentFlags().BoolVar(&flags.allowRCUpgrades, "allow-release-candidate-upgrades", flags.allowRCUpgrades, "Show release candidate versions of Kubernetes as an upgrade alternative and allow upgrading to a release candidate versions of Kubernetes.") - cmd.PersistentFlags().BoolVar(&flags.printConfig, "print-config", flags.printConfig, "Specifies whether the configuration file that will be used in the upgrade should be printed or not.") - cmd.PersistentFlags().StringSliceVar(&flags.ignorePreflightErrors, "ignore-preflight-errors", flags.ignorePreflightErrors, "A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.") - cmd.PersistentFlags().BoolVar(&flags.skipPreFlight, "skip-preflight-checks", flags.skipPreFlight, "Skip preflight checks that normally run before modifying the system.") - cmd.PersistentFlags().MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-preflight-errors=all") - cmd.PersistentFlags().StringVar(&flags.featureGatesString, "feature-gates", flags.featureGatesString, "A set of key=value pairs that describe feature gates for various features."+ - "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) - cmd.AddCommand(NewCmdApply(flags)) cmd.AddCommand(NewCmdPlan(flags)) - + cmd.AddCommand(NewCmdDiff(out)) + cmd.AddCommand(NewCmdNode()) return cmd } + +func addApplyPlanFlags(fs *pflag.FlagSet, flags *applyPlanFlags) { + // TODO: Use the generic options.AddKubeConfigFlag and options.AddConfigFlag methods instead + fs.StringVar(&flags.kubeConfigPath, "kubeconfig", flags.kubeConfigPath, "The KubeConfig file to use when talking to the cluster.") + fs.StringVar(&flags.cfgPath, "config", flags.cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental!") + + fs.BoolVar(&flags.allowExperimentalUpgrades, "allow-experimental-upgrades", flags.allowExperimentalUpgrades, "Show unstable versions of Kubernetes as an upgrade alternative and allow upgrading to an alpha/beta/release candidate versions of Kubernetes.") + fs.BoolVar(&flags.allowRCUpgrades, "allow-release-candidate-upgrades", flags.allowRCUpgrades, "Show release candidate versions of Kubernetes as an upgrade alternative and allow upgrading to a release candidate versions of Kubernetes.") + fs.BoolVar(&flags.printConfig, "print-config", flags.printConfig, "Specifies whether the configuration file that will be used in the upgrade should be printed or not.") + fs.StringSliceVar(&flags.ignorePreflightErrors, "ignore-preflight-errors", flags.ignorePreflightErrors, "A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.") + fs.BoolVar(&flags.skipPreFlight, "skip-preflight-checks", flags.skipPreFlight, "Skip preflight checks that normally run before modifying the system.") + fs.MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-preflight-errors=all") + fs.StringVar(&flags.featureGatesString, "feature-gates", flags.featureGatesString, "A set of key=value pairs that describe feature gates for various features."+ + "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version.go index f28b61bd4..066e4c489 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version.go @@ -22,11 +22,11 @@ import ( "io" "github.com/ghodss/yaml" + "github.com/golang/glog" "github.com/spf13/cobra" apimachineryversion "k8s.io/apimachinery/pkg/version" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/version" ) @@ -53,12 +53,19 @@ func NewCmdVersion(out io.Writer) *cobra.Command { // RunVersion provides the version information of kubeadm in format depending on arguments // specified in cobra.Command. func RunVersion(out io.Writer, cmd *cobra.Command) error { + glog.V(1).Infoln("[version] retrieving version info") clientVersion := version.Get() v := Version{ ClientVersion: &clientVersion, } - switch of := cmdutil.GetFlagString(cmd, "output"); of { + const flag = "output" + of, err := cmd.Flags().GetString(flag) + if err != nil { + glog.Fatalf("error accessing flag %s for command %s: %v", flag, cmd.Name(), err) + } + + switch of { case "": fmt.Fprintf(out, "kubeadm version: %#v\n", v.ClientVersion) case "short": diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version_test.go new file mode 100644 index 000000000..1f661913a --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version_test.go @@ -0,0 +1,96 @@ +/* +Copyright 2018 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 cmd + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/ghodss/yaml" + "testing" +) + +func TestNewCmdVersion(t *testing.T) { + var buf bytes.Buffer + cmd := NewCmdVersion(&buf) + if err := cmd.Execute(); err != nil { + t.Errorf("Cannot execute version command: %v", err) + } +} + +func TestRunVersion(t *testing.T) { + var buf bytes.Buffer + iface := make(map[string]interface{}) + flagNameOutput := "output" + cmd := NewCmdVersion(&buf) + + testCases := []struct { + name string + flag string + expectedError bool + shouldBeValidYAML bool + shouldBeValidJSON bool + }{ + { + name: "valid: run without flags", + }, + { + name: "valid: run with flag 'short'", + flag: "short", + }, + { + name: "valid: run with flag 'yaml'", + flag: "yaml", + shouldBeValidYAML: true, + }, + { + name: "valid: run with flag 'json'", + flag: "json", + shouldBeValidJSON: true, + }, + { + name: "invalid: run with unsupported flag", + flag: "unsupported-flag", + expectedError: true, + }, + } + for _, tc := range testCases { + var err error + if len(tc.flag) > 0 { + if err = cmd.Flags().Set(flagNameOutput, tc.flag); err != nil { + goto error + } + } + buf.Reset() + if err = RunVersion(&buf, cmd); err != nil { + goto error + } + if buf.String() == "" { + err = fmt.Errorf("empty output") + goto error + } + if tc.shouldBeValidYAML { + err = yaml.Unmarshal(buf.Bytes(), &iface) + } else if tc.shouldBeValidJSON { + err = json.Unmarshal(buf.Bytes(), &iface) + } + error: + if (err != nil) != tc.expectedError { + t.Errorf("Test case %q: RunVersion expected error: %v, saw: %v; %v", tc.name, tc.expectedError, err != nil, err) + } + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants.go index 047bbf7ae..dcffdd069 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "net" "os" + "path" "path/filepath" "time" @@ -38,7 +39,8 @@ const ( // ManifestsSubDirName defines directory name to store manifests ManifestsSubDirName = "manifests" // TempDirForKubeadm defines temporary directory for kubeadm - TempDirForKubeadm = "/etc/kubernetes/tmp" + // should be joined with KubernetesDir. + TempDirForKubeadm = "tmp" // CACertAndKeyBaseName defines certificate authority base name CACertAndKeyBaseName = "ca" @@ -78,8 +80,6 @@ const ( EtcdServerCertName = "etcd/server.crt" // EtcdServerKeyName defines etcd's server key name EtcdServerKeyName = "etcd/server.key" - // EtcdServerCertCommonName defines etcd's server certificate common name (CN) - EtcdServerCertCommonName = "kube-etcd" // EtcdPeerCertAndKeyBaseName defines etcd's peer certificate and key base name EtcdPeerCertAndKeyBaseName = "etcd/peer" @@ -87,8 +87,6 @@ const ( EtcdPeerCertName = "etcd/peer.crt" // EtcdPeerKeyName defines etcd's peer key name EtcdPeerKeyName = "etcd/peer.key" - // EtcdPeerCertCommonName defines etcd's peer certificate common name (CN) - EtcdPeerCertCommonName = "kube-etcd-peer" // EtcdHealthcheckClientCertAndKeyBaseName defines etcd's healthcheck client certificate and key base name EtcdHealthcheckClientCertAndKeyBaseName = "etcd/healthcheck-client" @@ -161,17 +159,16 @@ const ( // system:nodes group subject is removed if present. NodesClusterRoleBinding = "system:node" - // KubeletBaseConfigMapRoleName defines the base kubelet configuration ConfigMap. - KubeletBaseConfigMapRoleName = "kubeadm:kubelet-base-configmap" - // APICallRetryInterval defines how long kubeadm should wait before retrying a failed API operation APICallRetryInterval = 500 * time.Millisecond // DiscoveryRetryInterval specifies how long kubeadm should wait before retrying to connect to the master when doing discovery DiscoveryRetryInterval = 5 * time.Second - // MarkMasterTimeout specifies how long kubeadm should wait for applying the label and taint on the master before timing out - MarkMasterTimeout = 2 * time.Minute + // PatchNodeTimeout specifies how long kubeadm should wait for applying the label and taint on the master before timing out + PatchNodeTimeout = 2 * time.Minute // UpdateNodeTimeout specifies how long kubeadm should wait for updating node with the initial remote configuration of kubelet before timing out UpdateNodeTimeout = 2 * time.Minute + // TLSBootstrapTimeout specifies how long kubeadm should wait for the kubelet to perform the TLS Bootstrap + TLSBootstrapTimeout = 2 * time.Minute // MinimumAddressesInServiceSubnet defines minimum amount of nodes the Service subnet should allow. // We need at least ten, because the DNS service is always at the tenth cluster clusterIP @@ -185,33 +182,51 @@ const ( // This is a duplicate definition of the constant in pkg/controller/service/service_controller.go LabelNodeRoleMaster = "node-role.kubernetes.io/master" + // AnnotationKubeadmCRISocket specifies the annotation kubeadm uses to preserve the crisocket information given to kubeadm at + // init/join time for use later. kubeadm annotates the node object with this information + AnnotationKubeadmCRISocket = "kubeadm.alpha.kubernetes.io/cri-socket" + // MasterConfigurationConfigMap specifies in what ConfigMap in the kube-system namespace the `kubeadm init` configuration should be stored MasterConfigurationConfigMap = "kubeadm-config" // MasterConfigurationConfigMapKey specifies in what ConfigMap key the master configuration should be stored MasterConfigurationConfigMapKey = "MasterConfiguration" - // KubeletBaseConfigurationConfigMap specifies in what ConfigMap in the kube-system namespace the initial remote configuration of kubelet should be stored - KubeletBaseConfigurationConfigMap = "kubelet-base-config-1.9" + // KubeletBaseConfigurationConfigMapPrefix specifies in what ConfigMap in the kube-system namespace the initial remote configuration of kubelet should be stored + KubeletBaseConfigurationConfigMapPrefix = "kubelet-config-" // KubeletBaseConfigurationConfigMapKey specifies in what ConfigMap key the initial remote configuration of kubelet should be stored - // TODO: Use the constant ("kubelet.config.k8s.io") defined in pkg/kubelet/kubeletconfig/util/keys/keys.go - // after https://github.com/kubernetes/kubernetes/pull/53833 being merged. KubeletBaseConfigurationConfigMapKey = "kubelet" - // KubeletBaseConfigurationDir specifies the directory on the node where stores the initial remote configuration of kubelet - KubeletBaseConfigurationDir = "/var/lib/kubelet/config/init" + // KubeletBaseConfigMapRolePrefix defines the base kubelet configuration ConfigMap. + KubeletBaseConfigMapRolePrefix = "kubeadm:kubelet-config-" + + // KubeletRunDirectory specifies the directory where the kubelet runtime information is stored. + // TODO: Make hard-coded "/var/lib/kubelet" strings reference this constant. + KubeletRunDirectory = "/var/lib/kubelet" + + // KubeletConfigurationFileName specifies the file name on the node which stores initial remote configuration of kubelet + // This file should exist under KubeletRunDirectory + KubeletConfigurationFileName = "config.yaml" + + // DynamicKubeletConfigurationDirectoryName specifies the directory which stores the dynamic configuration checkpoints for the kubelet + // This directory should exist under KubeletRunDirectory + DynamicKubeletConfigurationDirectoryName = "dynamic-config" + + // KubeletEnvFileName is a file "kubeadm init" writes at runtime. Using that interface, kubeadm can customize certain + // kubelet flags conditionally based on the environment at runtime. Also, parameters given to the configuration file + // might be passed through this file. "kubeadm init" writes one variable, with the name ${KubeletEnvFileVariableName}. + // This file should exist under KubeletRunDirectory + KubeletEnvFileName = "kubeadm-flags.env" - // KubeletBaseConfigurationFile specifies the file name on the node which stores initial remote configuration of kubelet - // TODO: Use the constant ("kubelet.config.k8s.io") defined in pkg/kubelet/kubeletconfig/util/keys/keys.go - // after https://github.com/kubernetes/kubernetes/pull/53833 being merged. - KubeletBaseConfigurationFile = "kubelet" + // KubeletEnvFileVariableName specifies the shell script variable name "kubeadm init" should write a value to in KubeletEnvFile + KubeletEnvFileVariableName = "KUBELET_KUBEADM_ARGS" // MinExternalEtcdVersion indicates minimum external etcd version which kubeadm supports - MinExternalEtcdVersion = "3.1.12" + MinExternalEtcdVersion = "3.2.17" // DefaultEtcdVersion indicates the default etcd version that kubeadm uses - DefaultEtcdVersion = "3.1.12" + DefaultEtcdVersion = "3.2.18" // Etcd defines variable used internally when referring to etcd component Etcd = "etcd" @@ -259,6 +274,17 @@ const ( KubeAuditPolicyLogVolumeName = "audit-log" // StaticPodAuditPolicyLogDir is the name of the directory in the static pod that will have the audit logs StaticPodAuditPolicyLogDir = "/var/log/kubernetes/audit" + + // LeaseEndpointReconcilerType will select a storage based reconciler + // Copied from pkg/master/reconcilers to avoid pulling extra dependencies + // TODO: Import this constant from a consts only package, that does not pull any further dependencies. + LeaseEndpointReconcilerType = "lease" + + // KubeDNSVersion is the version of kube-dns to be deployed if it is used + KubeDNSVersion = "1.14.10" + + // CoreDNSVersion is the version of CoreDNS to be deployed if it is used + CoreDNSVersion = "1.1.3" ) var ( @@ -274,11 +300,6 @@ var ( Effect: v1.TaintEffectNoSchedule, } - // AuthorizationPolicyPath defines the supported location of authorization policy file - AuthorizationPolicyPath = filepath.Join(KubernetesDir, "abac_policy.json") - // AuthorizationWebhookConfigPath defines the supported location of webhook config file - AuthorizationWebhookConfigPath = filepath.Join(KubernetesDir, "webhook_authz.conf") - // DefaultTokenUsages specifies the default functions a token will get DefaultTokenUsages = bootstrapapi.KnownTokenUsages @@ -289,16 +310,16 @@ var ( MasterComponents = []string{KubeAPIServer, KubeControllerManager, KubeScheduler} // MinimumControlPlaneVersion specifies the minimum control plane version kubeadm can deploy - MinimumControlPlaneVersion = version.MustParseSemantic("v1.9.0") + MinimumControlPlaneVersion = version.MustParseSemantic("v1.10.0") // MinimumKubeletVersion specifies the minimum version of kubelet which kubeadm supports - MinimumKubeletVersion = version.MustParseSemantic("v1.9.0") + MinimumKubeletVersion = version.MustParseSemantic("v1.10.0") // SupportedEtcdVersion lists officially supported etcd versions with corresponding kubernetes releases SupportedEtcdVersion = map[uint8]string{ - 9: "3.1.12", 10: "3.1.12", - 11: "3.1.12", + 11: "3.2.18", + 12: "3.2.18", } ) @@ -335,6 +356,16 @@ func GetAdminKubeConfigPath() string { return filepath.Join(KubernetesDir, AdminKubeConfigFileName) } +// GetBootstrapKubeletKubeConfigPath returns the location on the disk where bootstrap kubelet kubeconfig is located by default +func GetBootstrapKubeletKubeConfigPath() string { + return filepath.Join(KubernetesDir, KubeletBootstrapKubeConfigFileName) +} + +// GetKubeletKubeConfigPath returns the location on the disk where kubelet kubeconfig is located by default +func GetKubeletKubeConfigPath() string { + return filepath.Join(KubernetesDir, KubeletKubeConfigFileName) +} + // AddSelfHostedPrefix adds the self-hosted- prefix to the component name func AddSelfHostedPrefix(componentName string) string { return fmt.Sprintf("%s%s", SelfHostingPrefix, componentName) @@ -342,18 +373,36 @@ func AddSelfHostedPrefix(componentName string) string { // CreateTempDirForKubeadm is a function that creates a temporary directory under /etc/kubernetes/tmp (not using /tmp as that would potentially be dangerous) func CreateTempDirForKubeadm(dirName string) (string, error) { + tempDir := path.Join(KubernetesDir, TempDirForKubeadm) // creates target folder if not already exists - if err := os.MkdirAll(TempDirForKubeadm, 0700); err != nil { - return "", fmt.Errorf("failed to create directory %q: %v", TempDirForKubeadm, err) + if err := os.MkdirAll(tempDir, 0700); err != nil { + return "", fmt.Errorf("failed to create directory %q: %v", tempDir, err) } - tempDir, err := ioutil.TempDir(TempDirForKubeadm, dirName) + tempDir, err := ioutil.TempDir(tempDir, dirName) if err != nil { return "", fmt.Errorf("couldn't create a temporary directory: %v", err) } return tempDir, nil } +// CreateTimestampDirForKubeadm is a function that creates a temporary directory under /etc/kubernetes/tmp formatted with the current date +func CreateTimestampDirForKubeadm(dirName string) (string, error) { + tempDir := path.Join(KubernetesDir, TempDirForKubeadm) + // creates target folder if not already exists + if err := os.MkdirAll(tempDir, 0700); err != nil { + return "", fmt.Errorf("failed to create directory %q: %v", tempDir, err) + } + + timestampDirName := fmt.Sprintf("%s-%s", dirName, time.Now().Format("2006-01-02-15-04-05")) + timestampDir := path.Join(tempDir, timestampDirName) + if err := os.Mkdir(timestampDir, 0700); err != nil { + return "", fmt.Errorf("could not create timestamp directory: %v", err) + } + + return timestampDir, nil +} + // GetDNSIP returns a dnsIP, which is 10th IP in svcSubnet CIDR range func GetDNSIP(svcSubnet string) (net.IP, error) { // Get the service subnet CIDR @@ -375,3 +424,13 @@ func GetDNSIP(svcSubnet string) (net.IP, error) { func GetStaticPodAuditPolicyFile() string { return filepath.Join(KubernetesDir, AuditPolicyDir, AuditPolicyFile) } + +// GetDNSVersion is a handy function that returns the DNS version by DNS type +func GetDNSVersion(dnsType string) string { + switch dnsType { + case CoreDNS: + return CoreDNSVersion + default: + return KubeDNSVersion + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants_test.go index 39197c6e6..7bcec4262 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants_test.go @@ -18,9 +18,10 @@ package constants import ( "fmt" - "k8s.io/kubernetes/pkg/util/version" "strings" "testing" + + "k8s.io/kubernetes/pkg/util/version" ) func TestGetStaticPodDirectory(t *testing.T) { @@ -49,6 +50,32 @@ func TestGetAdminKubeConfigPath(t *testing.T) { } } +func TestGetBootstrapKubeletKubeConfigPath(t *testing.T) { + expected := "/etc/kubernetes/bootstrap-kubelet.conf" + actual := GetBootstrapKubeletKubeConfigPath() + + if actual != expected { + t.Errorf( + "failed GetBootstrapKubeletKubeConfigPath:\n\texpected: %s\n\t actual: %s", + expected, + actual, + ) + } +} + +func TestGetKubeletKubeConfigPath(t *testing.T) { + expected := "/etc/kubernetes/kubelet.conf" + actual := GetKubeletKubeConfigPath() + + if actual != expected { + t.Errorf( + "failed GetKubeletKubeConfigPath:\n\texpected: %s\n\t actual: %s", + expected, + actual, + ) + } +} + func TestGetStaticPodFilepath(t *testing.T) { var tests = []struct { componentName, manifestsDir, expected string @@ -126,23 +153,23 @@ func TestEtcdSupportedVersion(t *testing.T) { expectedError: fmt.Errorf("Unsupported or unknown kubernetes version(1.99.0)"), }, { - kubernetesVersion: "1.9.0", + kubernetesVersion: "1.10.0", expectedVersion: version.MustParseSemantic("3.1.12"), expectedError: nil, }, { - kubernetesVersion: "1.9.2", + kubernetesVersion: "1.10.2", expectedVersion: version.MustParseSemantic("3.1.12"), expectedError: nil, }, { - kubernetesVersion: "1.10.0", - expectedVersion: version.MustParseSemantic("3.1.12"), + kubernetesVersion: "1.11.0", + expectedVersion: version.MustParseSemantic("3.2.18"), expectedError: nil, }, { - kubernetesVersion: "1.10.1", - expectedVersion: version.MustParseSemantic("3.1.12"), + kubernetesVersion: "1.12.1", + expectedVersion: version.MustParseSemantic("3.2.18"), expectedError: nil, }, } @@ -171,3 +198,29 @@ func TestEtcdSupportedVersion(t *testing.T) { } } } + +func TestGetKubeDNSVersion(t *testing.T) { + var tests = []struct { + dns string + expected string + }{ + { + dns: KubeDNS, + expected: KubeDNSVersion, + }, + { + dns: CoreDNS, + expected: CoreDNSVersion, + }, + } + for _, rt := range tests { + actualDNSVersion := GetDNSVersion(rt.dns) + if actualDNSVersion != rt.expected { + t.Errorf( + "failed GetDNSVersion:\n\texpected: %s\n\t actual: %s", + rt.expected, + actualDNSVersion, + ) + } + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go index 4ac6e8f43..de5a31f16 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go @@ -43,7 +43,7 @@ func For(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Config, error) { return kubeconfigutil.CreateWithToken( clusterinfo.Server, - "kubernetes", + cfg.ClusterName, TokenUser, clusterinfo.CertificateAuthorityData, cfg.TLSBootstrapToken, @@ -55,17 +55,17 @@ func GetValidatedClusterInfoObject(cfg *kubeadmapi.NodeConfiguration) (*clientcm switch { case len(cfg.DiscoveryFile) != 0: if isHTTPSURL(cfg.DiscoveryFile) { - return https.RetrieveValidatedClusterInfo(cfg.DiscoveryFile) + return https.RetrieveValidatedClusterInfo(cfg.DiscoveryFile, cfg.ClusterName) } - return file.RetrieveValidatedClusterInfo(cfg.DiscoveryFile) + return file.RetrieveValidatedClusterInfo(cfg.DiscoveryFile, cfg.ClusterName) case len(cfg.DiscoveryToken) != 0: - return token.RetrieveValidatedClusterInfo(cfg.DiscoveryToken, cfg.DiscoveryTokenAPIServers, cfg.DiscoveryTokenCACertHashes) + return token.RetrieveValidatedClusterInfo(cfg) default: return nil, fmt.Errorf("couldn't find a valid discovery configuration") } } -// isHTTPSURL checks whether the string is parsable as an URL and whether the Scheme is https +// isHTTPSURL checks whether the string is parsable as a URL and whether the Scheme is https func isHTTPSURL(s string) bool { u, err := url.Parse(s) return err == nil && u.Scheme == "https" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go index c1cb537d5..f8ef38d2e 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go @@ -33,18 +33,18 @@ import ( // RetrieveValidatedClusterInfo connects to the API Server and makes sure it can talk // securely to the API Server using the provided CA cert and // optionally refreshes the cluster-info information from the cluster-info ConfigMap -func RetrieveValidatedClusterInfo(filepath string) (*clientcmdapi.Cluster, error) { +func RetrieveValidatedClusterInfo(filepath, clustername string) (*clientcmdapi.Cluster, error) { clusterinfo, err := clientcmd.LoadFromFile(filepath) if err != nil { return nil, err } - return ValidateClusterInfo(clusterinfo) + return ValidateClusterInfo(clusterinfo, clustername) } // ValidateClusterInfo connects to the API Server and makes sure it can talk // securely to the API Server using the provided CA cert and // optionally refreshes the cluster-info information from the cluster-info ConfigMap -func ValidateClusterInfo(clusterinfo *clientcmdapi.Config) (*clientcmdapi.Cluster, error) { +func ValidateClusterInfo(clusterinfo *clientcmdapi.Config, clustername string) (*clientcmdapi.Cluster, error) { err := validateClusterInfoKubeConfig(clusterinfo) if err != nil { return nil, err @@ -57,7 +57,7 @@ func ValidateClusterInfo(clusterinfo *clientcmdapi.Config) (*clientcmdapi.Cluste // We do this in order to not pick up other possible misconfigurations in the clusterinfo file configFromClusterInfo := kubeconfigutil.CreateBasic( defaultCluster.Server, - "kubernetes", + clustername, "", // no user provided defaultCluster.CertificateAuthorityData, ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go index ec647c539..23f154e57 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go @@ -29,7 +29,7 @@ import ( // RetrieveValidatedClusterInfo connects to the API Server and makes sure it can talk // securely to the API Server using the provided CA cert and // optionally refreshes the cluster-info information from the cluster-info ConfigMap -func RetrieveValidatedClusterInfo(httpsURL string) (*clientcmdapi.Cluster, error) { +func RetrieveValidatedClusterInfo(httpsURL, clustername string) (*clientcmdapi.Cluster, error) { client := &http.Client{Transport: netutil.SetOldTransportDefaults(&http.Transport{})} response, err := client.Get(httpsURL) if err != nil { @@ -46,5 +46,5 @@ func RetrieveValidatedClusterInfo(httpsURL string) (*clientcmdapi.Cluster, error if err != nil { return nil, err } - return file.ValidateClusterInfo(clusterinfo) + return file.ValidateClusterInfo(clusterinfo, clustername) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD index dcfa1e9a3..e5a9bba77 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD @@ -11,10 +11,10 @@ go_library( srcs = ["token.go"], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery/token", deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", "//cmd/kubeadm/app/util/pubkeypin:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", "//pkg/controller/bootstrap:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.go index 77bf6fe55..bd2d3b88a 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.go @@ -22,6 +22,7 @@ import ( "encoding/pem" "fmt" "sync" + "time" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,10 +30,10 @@ import ( bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" "k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" "k8s.io/kubernetes/pkg/controller/bootstrap" ) @@ -40,26 +41,26 @@ import ( const BootstrapUser = "token-bootstrap-client" // RetrieveValidatedClusterInfo connects to the API Server and tries to fetch the cluster-info ConfigMap -// It then makes sure it can trust the API Server by looking at the JWS-signed tokens and (if rootCAPubKeys is not empty) +// It then makes sure it can trust the API Server by looking at the JWS-signed tokens and (if cfg.DiscoveryTokenCACertHashes is not empty) // validating the cluster CA against a set of pinned public keys -func RetrieveValidatedClusterInfo(discoveryToken string, tokenAPIServers, rootCAPubKeys []string) (*clientcmdapi.Cluster, error) { - tokenID, tokenSecret, err := tokenutil.ParseToken(discoveryToken) +func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Cluster, error) { + token, err := kubeadmapi.NewBootstrapTokenString(cfg.DiscoveryToken) if err != nil { return nil, err } // Load the cfg.DiscoveryTokenCACertHashes into a pubkeypin.Set pubKeyPins := pubkeypin.NewSet() - err = pubKeyPins.Allow(rootCAPubKeys...) + err = pubKeyPins.Allow(cfg.DiscoveryTokenCACertHashes...) if err != nil { return nil, err } // The function below runs for every endpoint, and all endpoints races with each other. // The endpoint that wins the race and completes the task first gets its kubeconfig returned below - baseKubeConfig := runForEndpointsAndReturnFirst(tokenAPIServers, func(endpoint string) (*clientcmdapi.Config, error) { + baseKubeConfig, err := runForEndpointsAndReturnFirst(cfg.DiscoveryTokenAPIServers, cfg.DiscoveryTimeout.Duration, func(endpoint string) (*clientcmdapi.Config, error) { - insecureBootstrapConfig := buildInsecureBootstrapKubeConfig(endpoint) + insecureBootstrapConfig := buildInsecureBootstrapKubeConfig(endpoint, cfg.ClusterName) clusterName := insecureBootstrapConfig.Contexts[insecureBootstrapConfig.CurrentContext].Cluster insecureClient, err := kubeconfigutil.ToClientSet(insecureBootstrapConfig) @@ -86,11 +87,11 @@ func RetrieveValidatedClusterInfo(discoveryToken string, tokenAPIServers, rootCA if !ok || len(insecureKubeconfigString) == 0 { return nil, fmt.Errorf("there is no %s key in the %s ConfigMap. This API Server isn't set up for token bootstrapping, can't connect", bootstrapapi.KubeConfigKey, bootstrapapi.ConfigMapClusterInfo) } - detachedJWSToken, ok := insecureClusterInfo.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenID] + detachedJWSToken, ok := insecureClusterInfo.Data[bootstrapapi.JWSSignatureKeyPrefix+token.ID] if !ok || len(detachedJWSToken) == 0 { - return nil, fmt.Errorf("token id %q is invalid for this cluster or it has expired. Use \"kubeadm token create\" on the master node to creating a new valid token", tokenID) + return nil, fmt.Errorf("token id %q is invalid for this cluster or it has expired. Use \"kubeadm token create\" on the master node to creating a new valid token", token.ID) } - if !bootstrap.DetachedTokenIsValid(detachedJWSToken, insecureKubeconfigString, tokenID, tokenSecret) { + if !bootstrap.DetachedTokenIsValid(detachedJWSToken, insecureKubeconfigString, token.ID, token.Secret) { return nil, fmt.Errorf("failed to verify JWS signature of received cluster info object, can't trust this API Server") } insecureKubeconfigBytes := []byte(insecureKubeconfigString) @@ -126,7 +127,7 @@ func RetrieveValidatedClusterInfo(discoveryToken string, tokenAPIServers, rootCA } // Now that we know the proported cluster CA, connect back a second time validating with that CA - secureBootstrapConfig := buildSecureBootstrapKubeConfig(endpoint, clusterCABytes) + secureBootstrapConfig := buildSecureBootstrapKubeConfig(endpoint, clusterCABytes, clusterName) secureClient, err := kubeconfigutil.ToClientSet(secureBootstrapConfig) if err != nil { return nil, err @@ -158,28 +159,30 @@ func RetrieveValidatedClusterInfo(discoveryToken string, tokenAPIServers, rootCA fmt.Printf("[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server %q\n", endpoint) return secureKubeconfig, nil }) + if err != nil { + return nil, err + } return kubeconfigutil.GetClusterFromKubeConfig(baseKubeConfig), nil } // buildInsecureBootstrapKubeConfig makes a KubeConfig object that connects insecurely to the API Server for bootstrapping purposes -func buildInsecureBootstrapKubeConfig(endpoint string) *clientcmdapi.Config { +func buildInsecureBootstrapKubeConfig(endpoint, clustername string) *clientcmdapi.Config { masterEndpoint := fmt.Sprintf("https://%s", endpoint) - clusterName := "kubernetes" - bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, clusterName, BootstrapUser, []byte{}) - bootstrapConfig.Clusters[clusterName].InsecureSkipTLSVerify = true + bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, clustername, BootstrapUser, []byte{}) + bootstrapConfig.Clusters[clustername].InsecureSkipTLSVerify = true return bootstrapConfig } // buildSecureBootstrapKubeConfig makes a KubeConfig object that connects securely to the API Server for bootstrapping purposes (validating with the specified CA) -func buildSecureBootstrapKubeConfig(endpoint string, caCert []byte) *clientcmdapi.Config { +func buildSecureBootstrapKubeConfig(endpoint string, caCert []byte, clustername string) *clientcmdapi.Config { masterEndpoint := fmt.Sprintf("https://%s", endpoint) - bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, "kubernetes", BootstrapUser, caCert) + bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, clustername, BootstrapUser, caCert) return bootstrapConfig } // runForEndpointsAndReturnFirst loops the endpoints slice and let's the endpoints race for connecting to the master -func runForEndpointsAndReturnFirst(endpoints []string, fetchKubeConfigFunc func(string) (*clientcmdapi.Config, error)) *clientcmdapi.Config { +func runForEndpointsAndReturnFirst(endpoints []string, discoveryTimeout time.Duration, fetchKubeConfigFunc func(string) (*clientcmdapi.Config, error)) (*clientcmdapi.Config, error) { stopChan := make(chan struct{}) var resultingKubeConfig *clientcmdapi.Config var once sync.Once @@ -205,8 +208,17 @@ func runForEndpointsAndReturnFirst(endpoints []string, fetchKubeConfigFunc func( }, constants.DiscoveryRetryInterval, stopChan) }(endpoint) } - wg.Wait() - return resultingKubeConfig + select { + case <-time.After(discoveryTimeout): + close(stopChan) + err := fmt.Errorf("abort connecting to API servers after timeout of %v", discoveryTimeout) + fmt.Printf("[discovery] %v\n", err) + wg.Wait() + return nil, err + case <-stopChan: + wg.Wait() + return resultingKubeConfig, nil + } } // parsePEMCert decodes a PEM-formatted certificate and returns it as an x509.Certificate diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go index 4c59ddfbd..6140793bf 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go @@ -68,11 +68,14 @@ func TestRunForEndpointsAndReturnFirst(t *testing.T) { }, } for _, rt := range tests { - returnKubeConfig := runForEndpointsAndReturnFirst(rt.endpoints, func(endpoint string) (*clientcmdapi.Config, error) { + returnKubeConfig, err := runForEndpointsAndReturnFirst(rt.endpoints, 5*time.Minute, func(endpoint string) (*clientcmdapi.Config, error) { timeout, _ := strconv.Atoi(endpoint) time.Sleep(time.Second * time.Duration(timeout)) return kubeconfigutil.CreateBasic(endpoint, "foo", "foo", []byte{}), nil }) + if err != nil { + t.Errorf("unexpected error: %v for endpoint %s", err, rt.expectedEndpoint) + } endpoint := returnKubeConfig.Clusters[returnKubeConfig.Contexts[returnKubeConfig.CurrentContext].Cluster].Server if endpoint != rt.expectedEndpoint { t.Errorf( diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features.go index f9f5ee281..c85576cd1 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features.go @@ -30,7 +30,7 @@ const ( // HighAvailability is alpha in v1.9 HighAvailability = "HighAvailability" - // CoreDNS is alpha in v1.9 + // CoreDNS is GA in v1.11 CoreDNS = "CoreDNS" // SelfHosting is alpha in v1.8 and v1.9 @@ -46,16 +46,14 @@ const ( Auditing = "Auditing" ) -var v190 = version.MustParseSemantic("v1.9.0-alpha.1") - // InitFeatureGates are the default feature gates for the init command var InitFeatureGates = FeatureList{ SelfHosting: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}}, StoreCertsInSecrets: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}}, // We don't want to advertise this feature gate exists in v1.9 to avoid confusion as it is not yet working - HighAvailability: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}, MinimumVersion: v190, HiddenInHelpText: true}, - CoreDNS: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Beta}, MinimumVersion: v190}, - DynamicKubeletConfig: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}, MinimumVersion: v190}, + HighAvailability: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}, HiddenInHelpText: true}, + CoreDNS: {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.GA}}, + DynamicKubeletConfig: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}}, Auditing: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}}, } @@ -92,7 +90,10 @@ func ValidateVersion(allFeatures FeatureList, requestedFeatures map[string]bool, // Enabled indicates whether a feature name has been enabled func Enabled(featureList map[string]bool, featureName string) bool { - return featureList[string(featureName)] + if enabled, ok := featureList[string(featureName)]; ok { + return enabled + } + return InitFeatureGates[string(featureName)].Default } // Supports indicates whether a feature name is supported on the given diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features_test.go index 1d64da404..347918d19 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features_test.go @@ -121,7 +121,7 @@ func TestNewFeatureGate(t *testing.T) { func TestValidateVersion(t *testing.T) { var someFeatures = FeatureList{ "feature1": {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Beta}}, - "feature2": {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.Alpha}, MinimumVersion: v190}, + "feature2": {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.Alpha}}, } var tests = []struct { @@ -133,16 +133,10 @@ func TestValidateVersion(t *testing.T) { requestedFeatures: map[string]bool{"feature1": true}, expectedError: false, }, - { //min version but correct value given + { //no min version requestedFeatures: map[string]bool{"feature2": true}, - requestedVersion: "v1.9.0", expectedError: false, }, - { //min version and incorrect value given - requestedFeatures: map[string]bool{"feature2": true}, - requestedVersion: "v1.8.2", - expectedError: true, - }, } for _, test := range tests { @@ -168,8 +162,8 @@ func TestResolveFeatureGateDependencies(t *testing.T) { expectedFeatures: map[string]bool{}, }, { // others flags - inputFeatures: map[string]bool{CoreDNS: true}, - expectedFeatures: map[string]bool{CoreDNS: true}, + inputFeatures: map[string]bool{CoreDNS: false}, + expectedFeatures: map[string]bool{CoreDNS: false}, }, { // just StoreCertsInSecrets flags inputFeatures: map[string]bool{StoreCertsInSecrets: true}, @@ -189,3 +183,16 @@ func TestResolveFeatureGateDependencies(t *testing.T) { } } } + +// TestEnabledDefaults tests that Enabled returns the default values for +// each feature gate when no feature gates are specified. +func TestEnabledDefaults(t *testing.T) { + for featureName, feature := range InitFeatureGates { + featureList := make(map[string]bool) + + enabled := Enabled(featureList, featureName) + if enabled != feature.Default { + t.Errorf("Enabled returned %v instead of default value %v for feature %s", enabled, feature.Default, featureName) + } + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD index 2f9e30e51..487521176 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD @@ -8,11 +8,18 @@ load( go_library( name = "go_default_library", - srcs = ["images.go"], + srcs = [ + "images.go", + "interface.go", + ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/images", deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", ], ) @@ -20,7 +27,10 @@ go_test( name = "go_default_test", srcs = ["images_test.go"], embed = [":go_default_library"], - deps = ["//cmd/kubeadm/app/constants:go_default_library"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", + ], ) filegroup( @@ -35,3 +45,13 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_xtest", + srcs = ["interface_test.go"], + deps = [ + ":go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images.go index ef6ceb7ee..71aebf921 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images.go @@ -20,10 +20,22 @@ import ( "fmt" "runtime" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" ) +// GetGenericImage generates and returns a platform agnostic image (backed by manifest list) +func GetGenericImage(prefix, image, tag string) string { + return fmt.Sprintf("%s/%s:%s", prefix, image, tag) +} + +// GetGenericArchImage generates and returns an image based on the current runtime arch +func GetGenericArchImage(prefix, image, tag string) string { + return fmt.Sprintf("%s/%s-%s:%s", prefix, image, runtime.GOARCH, tag) +} + // GetCoreImage generates and returns the image for the core Kubernetes components or returns overrideImage if specified func GetCoreImage(image, repoPrefix, k8sVersion, overrideImage string) string { if overrideImage != "" { @@ -42,3 +54,32 @@ func GetCoreImage(image, repoPrefix, k8sVersion, overrideImage string) string { constants.KubeScheduler: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-scheduler", runtime.GOARCH, kubernetesImageTag), }[image] } + +// GetAllImages returns a list of container images kubeadm expects to use on a control plane node +func GetAllImages(cfg *kubeadmapi.MasterConfiguration) []string { + repoPrefix := cfg.GetControlPlaneImageRepository() + imgs := []string{} + imgs = append(imgs, GetCoreImage(constants.KubeAPIServer, repoPrefix, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage)) + imgs = append(imgs, GetCoreImage(constants.KubeControllerManager, repoPrefix, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage)) + imgs = append(imgs, GetCoreImage(constants.KubeScheduler, repoPrefix, cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage)) + imgs = append(imgs, fmt.Sprintf("%v/%v-%v:%v", repoPrefix, constants.KubeProxy, runtime.GOARCH, kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion))) + + // pause, etcd and kube-dns are not available on the ci image repository so use the default image repository. + imgs = append(imgs, GetGenericImage(cfg.ImageRepository, "pause", "3.1")) + + // if etcd is not external then add the image as it will be required + if cfg.Etcd.Local != nil { + imgs = append(imgs, GetCoreImage(constants.Etcd, cfg.ImageRepository, cfg.KubernetesVersion, cfg.Etcd.Local.Image)) + } + + // Append the appropriate DNS images + if features.Enabled(cfg.FeatureGates, features.CoreDNS) { + imgs = append(imgs, GetGenericImage(cfg.ImageRepository, constants.CoreDNS, constants.CoreDNSVersion)) + } else { + imgs = append(imgs, GetGenericArchImage(cfg.ImageRepository, "k8s-dns-kube-dns", constants.KubeDNSVersion)) + imgs = append(imgs, GetGenericArchImage(cfg.ImageRepository, "k8s-dns-sidecar", constants.KubeDNSVersion)) + imgs = append(imgs, GetGenericArchImage(cfg.ImageRepository, "k8s-dns-dnsmasq-nanny", constants.KubeDNSVersion)) + } + + return imgs +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images_test.go index 466f20450..38f237cc9 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images_test.go @@ -19,8 +19,10 @@ package images import ( "fmt" "runtime" + "strings" "testing" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) @@ -73,3 +75,46 @@ func TestGetCoreImage(t *testing.T) { } } } + +func TestGetAllImages(t *testing.T) { + testcases := []struct { + name string + cfg *kubeadmapi.MasterConfiguration + expect string + }{ + { + name: "defined CIImageRepository", + cfg: &kubeadmapi.MasterConfiguration{ + CIImageRepository: "test.repo", + }, + expect: "test.repo", + }, + { + name: "undefined CIImagerRepository should contain the default image prefix", + cfg: &kubeadmapi.MasterConfiguration{ + ImageRepository: "real.repo", + }, + expect: "real.repo", + }, + { + name: "test that etcd is returned when it is not external", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{}, + }, + }, + expect: constants.Etcd, + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + imgs := GetAllImages(tc.cfg) + for _, img := range imgs { + if strings.Contains(img, tc.expect) { + return + } + } + t.Fatalf("did not find %q in %q", tc.expect, imgs) + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/interface.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/interface.go new file mode 100644 index 000000000..c9bd6b16f --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/interface.go @@ -0,0 +1,89 @@ +/* +Copyright 2018 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 images + +import ( + "fmt" + + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + utilsexec "k8s.io/utils/exec" +) + +// Puller is an interface for pulling images +type Puller interface { + Pull(string) error +} + +// Existence is an interface to determine if an image exists on the system +// A nil error means the image was found +type Existence interface { + Exists(string) error +} + +// Images defines the set of behaviors needed for images relating to the CRI +type Images interface { + Puller + Existence +} + +// CRInterfacer is a struct that interfaces with the container runtime +type CRInterfacer struct { + criSocket string + exec utilsexec.Interface + crictlPath string + dockerPath string +} + +// NewCRInterfacer sets up and returns a CRInterfacer +func NewCRInterfacer(execer utilsexec.Interface, criSocket string) (*CRInterfacer, error) { + var crictlPath, dockerPath string + var err error + if criSocket != kubeadmapiv1alpha2.DefaultCRISocket { + if crictlPath, err = execer.LookPath("crictl"); err != nil { + return nil, fmt.Errorf("crictl is required for non docker container runtimes: %v", err) + } + } else { + // use the dockershim + if dockerPath, err = execer.LookPath("docker"); err != nil { + return nil, fmt.Errorf("`docker` is required when docker is the container runtime and the kubelet is not running: %v", err) + } + } + + return &CRInterfacer{ + exec: execer, + criSocket: criSocket, + crictlPath: crictlPath, + dockerPath: dockerPath, + }, nil +} + +// Pull pulls the actual image using either crictl or docker +func (cri *CRInterfacer) Pull(image string) error { + if cri.criSocket != kubeadmapiv1alpha2.DefaultCRISocket { + return cri.exec.Command(cri.crictlPath, "-r", cri.criSocket, "pull", image).Run() + } + return cri.exec.Command(cri.dockerPath, "pull", image).Run() +} + +// Exists checks to see if the image exists on the system already +// Returns an error if the image is not found. +func (cri *CRInterfacer) Exists(image string) error { + if cri.criSocket != kubeadmapiv1alpha2.DefaultCRISocket { + return cri.exec.Command(cri.crictlPath, "-r", cri.criSocket, "inspecti", image).Run() + } + return cri.exec.Command(cri.dockerPath, "inspect", image).Run() +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/interface_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/interface_test.go new file mode 100644 index 000000000..54e176aaf --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/interface_test.go @@ -0,0 +1,266 @@ +/* +Copyright 2018 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 images_test + +import ( + "context" + "errors" + "io" + "testing" + + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + "k8s.io/kubernetes/cmd/kubeadm/app/images" + "k8s.io/utils/exec" +) + +type fakeCmd struct { + err error +} + +func (f *fakeCmd) Run() error { + return f.err +} +func (f *fakeCmd) CombinedOutput() ([]byte, error) { return nil, nil } +func (f *fakeCmd) Output() ([]byte, error) { return nil, nil } +func (f *fakeCmd) SetDir(dir string) {} +func (f *fakeCmd) SetStdin(in io.Reader) {} +func (f *fakeCmd) SetStdout(out io.Writer) {} +func (f *fakeCmd) SetStderr(out io.Writer) {} +func (f *fakeCmd) Stop() {} + +type fakeExecer struct { + cmd exec.Cmd + findCrictl bool + findDocker bool +} + +func (f *fakeExecer) Command(cmd string, args ...string) exec.Cmd { return f.cmd } +func (f *fakeExecer) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { + return f.cmd +} +func (f *fakeExecer) LookPath(file string) (string, error) { + if file == "crictl" { + if f.findCrictl { + return "/path", nil + } + return "", errors.New("no crictl for you") + } + if file == "docker" { + if f.findDocker { + return "/path", nil + } + return "", errors.New("no docker for you") + } + return "", errors.New("unknown binary") +} + +func TestNewCRInterfacer(t *testing.T) { + testcases := []struct { + name string + criSocket string + findCrictl bool + findDocker bool + expectError bool + }{ + { + name: "need crictl but can only find docker should return an error", + criSocket: "/not/docker", + findCrictl: false, + findDocker: true, + expectError: true, + }, + { + name: "need crictl and cannot find either should return an error", + criSocket: "/not/docker", + findCrictl: false, + findDocker: false, + expectError: true, + }, + { + name: "need crictl and cannot find docker should return no error", + criSocket: "/not/docker", + findCrictl: true, + findDocker: false, + expectError: false, + }, + { + name: "need crictl and can find both should return no error", + criSocket: "/not/docker", + findCrictl: true, + findDocker: true, + expectError: false, + }, + { + name: "need docker and cannot find crictl should return no error", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + findCrictl: false, + findDocker: true, + expectError: false, + }, + { + name: "need docker and cannot find docker should return an error", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + findCrictl: false, + findDocker: false, + expectError: true, + }, + { + name: "need docker and can find both should return no error", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + findCrictl: true, + findDocker: true, + expectError: false, + }, + { + name: "need docker and can only find crictl should return an error", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + findCrictl: true, + findDocker: false, + expectError: true, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + fe := &fakeExecer{ + findCrictl: tc.findCrictl, + findDocker: tc.findDocker, + } + _, err := images.NewCRInterfacer(fe, tc.criSocket) + if tc.expectError && err == nil { + t.Fatal("expected an error but did not get one") + } + if !tc.expectError && err != nil { + t.Fatalf("did not expedt an error but got an error: %v", err) + } + }) + } +} + +func TestImagePuller(t *testing.T) { + testcases := []struct { + name string + criSocket string + pullFails bool + errorExpected bool + }{ + { + name: "using docker and pull fails", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + pullFails: true, + errorExpected: true, + }, + { + name: "using docker and pull succeeds", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + pullFails: false, + errorExpected: false, + }, + { + name: "using crictl pull fails", + criSocket: "/not/default", + pullFails: true, + errorExpected: true, + }, + { + name: "using crictl and pull succeeds", + criSocket: "/not/default", + pullFails: false, + errorExpected: false, + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + var err error + if tc.pullFails { + err = errors.New("error") + } + + fe := &fakeExecer{ + cmd: &fakeCmd{err}, + findCrictl: true, + findDocker: true, + } + ip, _ := images.NewCRInterfacer(fe, tc.criSocket) + + err = ip.Pull("imageName") + if tc.errorExpected && err == nil { + t.Fatal("expected an error and did not get one") + } + if !tc.errorExpected && err != nil { + t.Fatalf("expected no error but got one: %v", err) + } + }) + } +} + +func TestImageExists(t *testing.T) { + testcases := []struct { + name string + criSocket string + existFails bool + errorExpected bool + }{ + { + name: "using docker and exist fails", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + existFails: true, + errorExpected: true, + }, + { + name: "using docker and exist succeeds", + criSocket: kubeadmapiv1alpha2.DefaultCRISocket, + existFails: false, + errorExpected: false, + }, + { + name: "using crictl exist fails", + criSocket: "/not/default", + existFails: true, + errorExpected: true, + }, + { + name: "using crictl and exist succeeds", + criSocket: "/not/default", + existFails: false, + errorExpected: false, + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + var err error + if tc.existFails { + err = errors.New("error") + } + + fe := &fakeExecer{ + cmd: &fakeCmd{err}, + findCrictl: true, + findDocker: true, + } + ip, _ := images.NewCRInterfacer(fe, tc.criSocket) + + err = ip.Exists("imageName") + if tc.errorExpected && err == nil { + t.Fatal("expected an error and did not get one") + } + if !tc.errorExpected && err != nil { + t.Fatalf("expected no error but got one: %v", err) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go index ccf69ee8d..fddda5902 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go @@ -17,20 +17,33 @@ limitations under the License. package app import ( + "flag" "os" + _ "github.com/golang/glog" "github.com/spf13/pflag" - _ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install" + utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/kubernetes/cmd/kubeadm/app/cmd" ) // Run creates and executes new kubeadm command func Run() error { + pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc) + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) + + pflag.Set("logtostderr", "true") // We do not want these flags to show up in --help + // These MarkHidden calls must be after the lines above pflag.CommandLine.MarkHidden("version") pflag.CommandLine.MarkHidden("google-json-key") pflag.CommandLine.MarkHidden("log-flush-frequency") + pflag.CommandLine.MarkHidden("alsologtostderr") + pflag.CommandLine.MarkHidden("log-backtrace-at") + pflag.CommandLine.MarkHidden("log-dir") + pflag.CommandLine.MarkHidden("logtostderr") + pflag.CommandLine.MarkHidden("stderrthreshold") + pflag.CommandLine.MarkHidden("vmodule") cmd := cmd.NewKubeadmCommand(os.Stdin, os.Stdout, os.Stderr) return cmd.Execute() diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/BUILD index eddac8a2c..bb38323ee 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/BUILD @@ -8,16 +8,12 @@ load( go_test( name = "go_default_test", - srcs = [ - "dns_test.go", - "versions_test.go", - ], + srcs = ["dns_test.go"], embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/util/version:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -32,7 +28,6 @@ go_library( srcs = [ "dns.go", "manifests.go", - "versions.go", ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns", deps = [ @@ -41,8 +36,6 @@ go_library( "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//pkg/api/legacyscheme:go_default_library", - "//pkg/util/version:go_default_library", "//vendor/github.com/mholt/caddy/caddyfile:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -51,6 +44,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns.go index f7fc2cba5..50c2577e1 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns.go @@ -31,13 +31,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kuberuntime "k8s.io/apimachinery/pkg/runtime" clientset "k8s.io/client-go/kubernetes" + clientsetscheme "k8s.io/client-go/kubernetes/scheme" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/util/version" ) const ( @@ -48,19 +47,37 @@ const ( kubeDNSFederation = "federations" ) -// EnsureDNSAddon creates the kube-dns or CoreDNS addon -func EnsureDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { - k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion) +// DeployedDNSAddon returns the type of DNS addon currently deployed +func DeployedDNSAddon(client clientset.Interface) (string, string, error) { + deploymentsClient := client.AppsV1().Deployments(metav1.NamespaceSystem) + deployments, err := deploymentsClient.List(metav1.ListOptions{LabelSelector: "k8s-app=kube-dns"}) if err != nil { - return fmt.Errorf("couldn't parse kubernetes version %q: %v", cfg.KubernetesVersion, err) + return "", "", fmt.Errorf("couldn't retrieve DNS addon deployments: %v", err) + } + + switch len(deployments.Items) { + case 0: + return "", "", nil + case 1: + addonName := deployments.Items[0].Name + addonImage := deployments.Items[0].Spec.Template.Spec.Containers[0].Image + addonImageParts := strings.Split(addonImage, ":") + addonVersion := addonImageParts[len(addonImageParts)-1] + return addonName, addonVersion, nil + default: + return "", "", fmt.Errorf("multiple DNS addon deployments found: %v", deployments.Items) } +} + +// EnsureDNSAddon creates the kube-dns or CoreDNS addon +func EnsureDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { if features.Enabled(cfg.FeatureGates, features.CoreDNS) { - return coreDNSAddon(cfg, client, k8sVersion) + return coreDNSAddon(cfg, client) } - return kubeDNSAddon(cfg, client, k8sVersion) + return kubeDNSAddon(cfg, client) } -func kubeDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface, k8sVersion *version.Version) error { +func kubeDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { if err := CreateServiceAccount(client); err != nil { return err } @@ -79,18 +96,15 @@ func kubeDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interfac dnsProbeAddr = dnsBindAddr } - // Get the YAML manifest conditionally based on the k8s version - kubeDNSDeploymentBytes := GetKubeDNSManifest(k8sVersion) - dnsDeploymentBytes, err := kubeadmutil.ParseTemplate(kubeDNSDeploymentBytes, + dnsDeploymentBytes, err := kubeadmutil.ParseTemplate(KubeDNSDeployment, struct{ ImageRepository, Arch, Version, DNSBindAddr, DNSProbeAddr, DNSDomain, MasterTaintKey string }{ ImageRepository: cfg.ImageRepository, Arch: runtime.GOARCH, - // Get the kube-dns version conditionally based on the k8s version - Version: GetDNSVersion(k8sVersion, kubeadmconstants.KubeDNS), - DNSBindAddr: dnsBindAddr, - DNSProbeAddr: dnsProbeAddr, - DNSDomain: cfg.Networking.DNSDomain, - MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, + Version: kubeadmconstants.KubeDNSVersion, + DNSBindAddr: dnsBindAddr, + DNSProbeAddr: dnsProbeAddr, + DNSDomain: cfg.Networking.DNSDomain, + MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, }) if err != nil { return fmt.Errorf("error when parsing kube-dns deployment template: %v", err) @@ -123,7 +137,7 @@ func CreateServiceAccount(client clientset.Interface) error { func createKubeDNSAddon(deploymentBytes, serviceBytes []byte, client clientset.Interface) error { kubednsDeployment := &apps.Deployment{} - if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), deploymentBytes, kubednsDeployment); err != nil { + if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), deploymentBytes, kubednsDeployment); err != nil { return fmt.Errorf("unable to decode kube-dns deployment %v", err) } @@ -136,12 +150,12 @@ func createKubeDNSAddon(deploymentBytes, serviceBytes []byte, client clientset.I return createDNSService(kubednsService, serviceBytes, client) } -func coreDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface, k8sVersion *version.Version) error { - // Get the YAML manifest conditionally based on the k8s version - dnsDeploymentBytes := GetCoreDNSManifest(k8sVersion) - coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(dnsDeploymentBytes, struct{ MasterTaintKey, Version string }{ - MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, - Version: GetDNSVersion(k8sVersion, kubeadmconstants.CoreDNS), +func coreDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { + // Get the YAML manifest + coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(CoreDNSDeployment, struct{ ImageRepository, MasterTaintKey, Version string }{ + ImageRepository: cfg.ImageRepository, + MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, + Version: kubeadmconstants.CoreDNSVersion, }) if err != nil { return fmt.Errorf("error when parsing CoreDNS deployment template: %v", err) @@ -201,17 +215,17 @@ func coreDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interfac func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, client clientset.Interface) error { coreDNSConfigMap := &v1.ConfigMap{} - if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), configBytes, coreDNSConfigMap); err != nil { + if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), configBytes, coreDNSConfigMap); err != nil { return fmt.Errorf("unable to decode CoreDNS configmap %v", err) } - // Create the ConfigMap for CoreDNS or update it in case it already exists - if err := apiclient.CreateOrUpdateConfigMap(client, coreDNSConfigMap); err != nil { + // Create the ConfigMap for CoreDNS or retain it in case it already exists + if err := apiclient.CreateOrRetainConfigMap(client, coreDNSConfigMap, kubeadmconstants.CoreDNS); err != nil { return err } coreDNSClusterRoles := &rbac.ClusterRole{} - if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), []byte(CoreDNSClusterRole), coreDNSClusterRoles); err != nil { + if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), []byte(CoreDNSClusterRole), coreDNSClusterRoles); err != nil { return fmt.Errorf("unable to decode CoreDNS clusterroles %v", err) } @@ -221,7 +235,7 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien } coreDNSClusterRolesBinding := &rbac.ClusterRoleBinding{} - if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), []byte(CoreDNSClusterRoleBinding), coreDNSClusterRolesBinding); err != nil { + if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), []byte(CoreDNSClusterRoleBinding), coreDNSClusterRolesBinding); err != nil { return fmt.Errorf("unable to decode CoreDNS clusterrolebindings %v", err) } @@ -231,7 +245,7 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien } coreDNSServiceAccount := &v1.ServiceAccount{} - if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), []byte(CoreDNSServiceAccount), coreDNSServiceAccount); err != nil { + if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), []byte(CoreDNSServiceAccount), coreDNSServiceAccount); err != nil { return fmt.Errorf("unable to decode CoreDNS serviceaccount %v", err) } @@ -241,7 +255,7 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien } coreDNSDeployment := &apps.Deployment{} - if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), deploymentBytes, coreDNSDeployment); err != nil { + if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), deploymentBytes, coreDNSDeployment); err != nil { return fmt.Errorf("unable to decode CoreDNS deployment %v", err) } @@ -255,7 +269,7 @@ func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, clien } func createDNSService(dnsService *v1.Service, serviceBytes []byte, client clientset.Interface) error { - if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), serviceBytes, dnsService); err != nil { + if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), serviceBytes, dnsService); err != nil { return fmt.Errorf("unable to decode the DNS service %v", err) } @@ -278,6 +292,10 @@ func createDNSService(dnsService *v1.Service, serviceBytes []byte, client client // translateStubDomainOfKubeDNSToProxyCoreDNS translates StubDomain Data in kube-dns ConfigMap // in the form of Proxy for the CoreDNS Corefile. func translateStubDomainOfKubeDNSToProxyCoreDNS(dataField string, kubeDNSConfigMap *v1.ConfigMap) (string, error) { + if kubeDNSConfigMap == nil { + return "", nil + } + if proxy, ok := kubeDNSConfigMap.Data[dataField]; ok { stubDomainData := make(map[string][]string) err := json.Unmarshal([]byte(proxy), &stubDomainData) @@ -314,6 +332,10 @@ func translateStubDomainOfKubeDNSToProxyCoreDNS(dataField string, kubeDNSConfigM // translateUpstreamNameServerOfKubeDNSToUpstreamProxyCoreDNS translates UpstreamNameServer Data in kube-dns ConfigMap // in the form of Proxy for the CoreDNS Corefile. func translateUpstreamNameServerOfKubeDNSToUpstreamProxyCoreDNS(dataField string, kubeDNSConfigMap *v1.ConfigMap) (string, error) { + if kubeDNSConfigMap == nil { + return "", nil + } + if upstreamValues, ok := kubeDNSConfigMap.Data[dataField]; ok { var upstreamProxyIP []string @@ -331,6 +353,10 @@ func translateUpstreamNameServerOfKubeDNSToUpstreamProxyCoreDNS(dataField string // translateFederationsofKubeDNSToCoreDNS translates Federations Data in kube-dns ConfigMap // to Federation for CoreDNS Corefile. func translateFederationsofKubeDNSToCoreDNS(dataField, coreDNSDomain string, kubeDNSConfigMap *v1.ConfigMap) (string, error) { + if kubeDNSConfigMap == nil { + return "", nil + } + if federation, ok := kubeDNSConfigMap.Data[dataField]; ok { var ( federationStanza []interface{} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns_test.go index 2233bf182..d28219ff6 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns_test.go @@ -94,7 +94,7 @@ func TestCompileManifests(t *testing.T) { expected bool }{ { - manifest: v180AndAboveKubeDNSDeployment, + manifest: KubeDNSDeployment, data: struct{ ImageRepository, Arch, Version, DNSBindAddr, DNSProbeAddr, DNSDomain, MasterTaintKey string }{ ImageRepository: "foo", Arch: "foo", @@ -115,9 +115,10 @@ func TestCompileManifests(t *testing.T) { }, { manifest: CoreDNSDeployment, - data: struct{ MasterTaintKey, Version string }{ - MasterTaintKey: "foo", - Version: "foo", + data: struct{ ImageRepository, MasterTaintKey, Version string }{ + ImageRepository: "foo", + MasterTaintKey: "foo", + Version: "foo", }, expected: true, }, diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/manifests.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/manifests.go index 3a2449af6..175c7c81f 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/manifests.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/manifests.go @@ -17,8 +17,8 @@ limitations under the License. package dns const ( - // v180AndAboveKubeDNSDeployment is the kube-dns Deployment manifest for the kube-dns manifest for v1.7+ - v180AndAboveKubeDNSDeployment = ` + // KubeDNSDeployment is the kube-dns Deployment manifest for the kube-dns manifest for v1.7+ + KubeDNSDeployment = ` apiVersion: apps/v1 kind: Deployment metadata: @@ -173,16 +173,8 @@ spec: operator: Exists - key: {{ .MasterTaintKey }} effect: NoSchedule - # TODO: Remove this affinity field as soon as we are using manifest lists - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - {{ .Arch }} + nodeSelector: + beta.kubernetes.io/arch: {{ .Arch }} ` // KubeDNSService is the kube-dns Service manifest @@ -196,6 +188,9 @@ metadata: kubernetes.io/name: "KubeDNS" name: kube-dns namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" # Without this resourceVersion value, an update of the Service between versions will yield: # Service "kube-dns" is invalid: metadata.resourceVersion: Invalid value: "": must be specified for an update resourceVersion: "0" @@ -245,7 +240,7 @@ spec: effect: NoSchedule containers: - name: coredns - image: coredns/coredns:{{ .Version }} + image: {{ .ImageRepository }}/coredns:{{ .Version }} imagePullPolicy: IfNotPresent resources: limits: @@ -257,6 +252,7 @@ spec: volumeMounts: - name: config-volume mountPath: /etc/coredns + readOnly: true ports: - containerPort: 53 name: dns @@ -264,6 +260,9 @@ spec: - containerPort: 53 name: dns-tcp protocol: TCP + - containerPort: 9153 + name: metrics + protocol: TCP livenessProbe: httpGet: path: /health @@ -273,6 +272,14 @@ spec: timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - all + readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume @@ -303,6 +310,7 @@ data: prometheus :9153 proxy . {{ .UpstreamNameserver }} cache 30 + reload }{{ .StubDomain }} ` // CoreDNSClusterRole is the CoreDNS ClusterRole manifest diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions.go deleted file mode 100644 index 9a278dd09..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions.go +++ /dev/null @@ -1,57 +0,0 @@ -/* -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 dns - -import ( - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/pkg/util/version" -) - -const ( - kubeDNSv190AndAboveVersion = "1.14.8" - coreDNSVersion = "1.0.6" -) - -// GetDNSVersion returns the right kube-dns version for a specific k8s version -func GetDNSVersion(kubeVersion *version.Version, dns string) string { - // v1.9.0+ uses kube-dns 1.14.8 - // v1.9.0+ uses CoreDNS 1.0.6 if feature gate "CoreDNS" is enabled. - - // In the future when the version is bumped at HEAD; add conditional logic to return the right versions - // Also, the version might be bumped for different k8s releases on the same branch - switch dns { - case kubeadmconstants.CoreDNS: - // return the CoreDNS version - return coreDNSVersion - default: - return kubeDNSv190AndAboveVersion - } -} - -// GetKubeDNSManifest returns the right kube-dns YAML manifest for a specific k8s version -func GetKubeDNSManifest(kubeVersion *version.Version) string { - // v1.8.0+ has only one known YAML manifest spec, just return that here - // In the future when the kube-dns version is bumped at HEAD; add conditional logic to return the right manifest - return v180AndAboveKubeDNSDeployment -} - -// GetCoreDNSManifest returns the right CoreDNS YAML manifest for a specific k8s version -func GetCoreDNSManifest(kubeVersion *version.Version) string { - // v1.9.0+ has only one known YAML manifest spec, just return that here - // In the future when the CoreDNS version is bumped at HEAD; add conditional logic to return the right manifest - return CoreDNSDeployment -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions_test.go deleted file mode 100644 index c4ca3e78f..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions_test.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -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 dns - -import ( - "testing" - - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/pkg/util/version" -) - -func TestGetKubeDNSVersion(t *testing.T) { - var tests = []struct { - k8sVersion string - dns string - expected string - }{ - { - k8sVersion: "v1.9.0", - dns: kubeadmconstants.KubeDNS, - expected: kubeDNSv190AndAboveVersion, - }, - { - k8sVersion: "v1.10.0", - dns: kubeadmconstants.KubeDNS, - expected: kubeDNSv190AndAboveVersion, - }, - { - k8sVersion: "v1.9.0", - dns: kubeadmconstants.CoreDNS, - expected: coreDNSVersion, - }, - { - k8sVersion: "v1.10.0", - dns: kubeadmconstants.CoreDNS, - expected: coreDNSVersion, - }, - } - for _, rt := range tests { - k8sVersion, err := version.ParseSemantic(rt.k8sVersion) - if err != nil { - t.Fatalf("couldn't parse kubernetes version %q: %v", rt.k8sVersion, err) - } - - actualDNSVersion := GetDNSVersion(k8sVersion, rt.dns) - if actualDNSVersion != rt.expected { - t.Errorf( - "failed GetDNSVersion:\n\texpected: %s\n\t actual: %s", - rt.expected, - actualDNSVersion, - ) - } - } -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/BUILD index e05a783da..612ca29d5 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/BUILD @@ -11,7 +11,7 @@ go_test( srcs = ["proxy_test.go"], embed = [":go_default_library"], deps = [ - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", "//pkg/apis/core:go_default_library", @@ -34,19 +34,17 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", - "//pkg/scheduler/algorithm:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/manifests.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/manifests.go index f6e82319b..77caea96f 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/manifests.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/manifests.go @@ -69,7 +69,10 @@ spec: metadata: labels: k8s-app: kube-proxy + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" spec: + priorityClassName: system-node-critical containers: - name: kube-proxy image: {{ if .ImageOverride }}{{ .ImageOverride }}{{ else }}{{ .ImageRepository }}/kube-proxy-{{ .Arch }}:{{ .Version }}{{ end }} @@ -90,12 +93,6 @@ spec: readOnly: true hostNetwork: true serviceAccountName: kube-proxy - tolerations: - - key: {{ .MasterTaintKey }} - effect: NoSchedule - - key: {{ .CloudTaintKey }} - value: "true" - effect: NoSchedule volumes: - name: kube-proxy configMap: @@ -107,5 +104,11 @@ spec: - name: lib-modules hostPath: path: /lib/modules + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - operator: Exists + nodeSelector: + beta.kubernetes.io/arch: {{ .Arch }} ` ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy.go index a5e3dd2d1..cde76c439 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy.go @@ -27,14 +27,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kuberuntime "k8s.io/apimachinery/pkg/runtime" clientset "k8s.io/client-go/kubernetes" + clientsetscheme "k8s.io/client-go/kubernetes/scheme" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - "k8s.io/kubernetes/pkg/api/legacyscheme" kubeproxyconfigscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme" kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" - "k8s.io/kubernetes/pkg/scheduler/algorithm" ) const ( @@ -53,7 +51,7 @@ func EnsureProxyAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Inte } // Generate Master Enpoint kubeconfig file - masterEndpoint, err := kubeadmutil.GetMasterEndpoint(cfg) + masterEndpoint, err := kubeadmutil.GetMasterEndpoint(&cfg.API) if err != nil { return err } @@ -77,13 +75,11 @@ func EnsureProxyAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Inte if err != nil { return fmt.Errorf("error when parsing kube-proxy configmap template: %v", err) } - proxyDaemonSetBytes, err = kubeadmutil.ParseTemplate(KubeProxyDaemonSet19, struct{ ImageRepository, Arch, Version, ImageOverride, MasterTaintKey, CloudTaintKey string }{ + proxyDaemonSetBytes, err = kubeadmutil.ParseTemplate(KubeProxyDaemonSet19, struct{ ImageRepository, Arch, Version, ImageOverride string }{ ImageRepository: cfg.GetControlPlaneImageRepository(), Arch: runtime.GOARCH, Version: kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion), ImageOverride: cfg.UnifiedControlPlaneImage, - MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster, - CloudTaintKey: algorithm.TaintExternalCloudProvider, }) if err != nil { return fmt.Errorf("error when parsing kube-proxy daemonset template: %v", err) @@ -117,7 +113,7 @@ func CreateRBACRules(client clientset.Interface) error { func createKubeProxyAddon(configMapBytes, daemonSetbytes []byte, client clientset.Interface) error { kubeproxyConfigMap := &v1.ConfigMap{} - if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), configMapBytes, kubeproxyConfigMap); err != nil { + if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), configMapBytes, kubeproxyConfigMap); err != nil { return fmt.Errorf("unable to decode kube-proxy configmap %v", err) } @@ -127,7 +123,7 @@ func createKubeProxyAddon(configMapBytes, daemonSetbytes []byte, client clientse } kubeproxyDaemonSet := &apps.DaemonSet{} - if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), daemonSetbytes, kubeproxyDaemonSet); err != nil { + if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), daemonSetbytes, kubeproxyDaemonSet); err != nil { return fmt.Errorf("unable to decode kube-proxy daemonset %v", err) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go index 013452343..87c64ae91 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" clientsetfake "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" api "k8s.io/kubernetes/pkg/apis/core" @@ -174,12 +174,12 @@ func TestEnsureProxyAddon(t *testing.T) { // Create a fake client and set up default test configuration client := clientsetfake.NewSimpleClientset() - masterConfig := &kubeadmapiext.MasterConfiguration{ - API: kubeadmapiext.API{ + masterConfig := &kubeadmapiv1alpha2.MasterConfiguration{ + API: kubeadmapiv1alpha2.API{ AdvertiseAddress: "1.2.3.4", BindPort: 1234, }, - KubeProxy: kubeadmapiext.KubeProxy{ + KubeProxy: kubeadmapiv1alpha2.KubeProxy{ Config: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{ BindAddress: "", HealthzBindAddress: "0.0.0.0:10256", @@ -193,11 +193,11 @@ func TestEnsureProxyAddon(t *testing.T) { }, }, }, - Networking: kubeadmapiext.Networking{ + Networking: kubeadmapiv1alpha2.Networking{ PodSubnet: "5.6.7.8/24", }, ImageRepository: "someRepo", - KubernetesVersion: "v1.9.0", + KubernetesVersion: "v1.10.0", UnifiedControlPlaneImage: "someImage", } @@ -214,7 +214,7 @@ func TestEnsureProxyAddon(t *testing.T) { masterConfig.Networking.PodSubnet = "2001:101::/96" } - kubeadmapiext.SetDefaults_MasterConfiguration(masterConfig) + kubeadmapiv1alpha2.SetDefaults_MasterConfiguration(masterConfig) intMaster, err := cmdutil.ConfigFileAndDefaultsToInternalConfig("", masterConfig) if err != nil { t.Errorf(" test failed to convert v1alpha1 to internal version") diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/BUILD index d0a484b43..fb0d2816e 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/BUILD @@ -26,6 +26,7 @@ go_library( deps = [ "//cmd/kubeadm/app/util/apiclient:go_default_library", "//pkg/apis/rbac/v1:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go index 9cf9b01a7..badd2c712 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go @@ -19,6 +19,7 @@ package clusterinfo import ( "fmt" + "github.com/golang/glog" "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -39,8 +40,9 @@ const ( // CreateBootstrapConfigMapIfNotExists creates the kube-public ConfigMap if it doesn't exist already func CreateBootstrapConfigMapIfNotExists(client clientset.Interface, file string) error { - fmt.Printf("[bootstraptoken] Creating the %q ConfigMap in the %q namespace\n", bootstrapapi.ConfigMapClusterInfo, metav1.NamespacePublic) + fmt.Printf("[bootstraptoken] creating the %q ConfigMap in the %q namespace\n", bootstrapapi.ConfigMapClusterInfo, metav1.NamespacePublic) + glog.V(1).Infoln("[bootstraptoken] loading admin kubeconfig") adminConfig, err := clientcmd.LoadFromFile(file) if err != nil { return fmt.Errorf("failed to load admin kubeconfig [%v]", err) @@ -48,6 +50,7 @@ func CreateBootstrapConfigMapIfNotExists(client clientset.Interface, file string adminCluster := adminConfig.Contexts[adminConfig.CurrentContext].Cluster // Copy the cluster from admin.conf to the bootstrap kubeconfig, contains the CA cert and the server URL + glog.V(1).Infoln("[bootstraptoken] copying the cluster from admin.conf to the bootstrap kubeconfig") bootstrapConfig := &clientcmdapi.Config{ Clusters: map[string]*clientcmdapi.Cluster{ "": adminConfig.Clusters[adminCluster], @@ -59,6 +62,7 @@ func CreateBootstrapConfigMapIfNotExists(client clientset.Interface, file string } // Create or update the ConfigMap in the kube-public namespace + glog.V(1).Infoln("[bootstraptoken] creating/updating ConfigMap in kube-public namespace") return apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: bootstrapapi.ConfigMapClusterInfo, @@ -72,6 +76,7 @@ func CreateBootstrapConfigMapIfNotExists(client clientset.Interface, file string // CreateClusterInfoRBACRules creates the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace to unauthenticated users func CreateClusterInfoRBACRules(client clientset.Interface) error { + glog.V(1).Infoln("creating the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace") err := apiclient.CreateOrUpdateRole(client, &rbac.Role{ ObjectMeta: metav1.ObjectMeta{ Name: BootstrapSignerClusterRoleName, diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/BUILD index ae2634c29..c39f9ac2c 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/BUILD @@ -3,14 +3,6 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["token_test.go"], - embed = [":go_default_library"], - deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"], ) go_library( @@ -21,15 +13,12 @@ go_library( ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node", deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go index 5f3943339..334d6afdc 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/tlsbootstrap.go @@ -47,7 +47,7 @@ const ( // AllowBootstrapTokensToPostCSRs creates RBAC rules in a way the makes Node Bootstrap Tokens able to post CSRs func AllowBootstrapTokensToPostCSRs(client clientset.Interface) error { - fmt.Println("[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials") + fmt.Println("[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials") return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ @@ -69,7 +69,7 @@ func AllowBootstrapTokensToPostCSRs(client clientset.Interface) error { // AutoApproveNodeBootstrapTokens creates RBAC rules in a way that makes Node Bootstrap Tokens' CSR auto-approved by the csrapprover controller func AutoApproveNodeBootstrapTokens(client clientset.Interface) error { - fmt.Println("[bootstraptoken] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token") + fmt.Println("[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token") // Always create this kubeadm-specific binding though return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ @@ -92,7 +92,7 @@ func AutoApproveNodeBootstrapTokens(client clientset.Interface) error { // AutoApproveNodeCertificateRotation creates RBAC rules in a way that makes Node certificate rotation CSR auto-approved by the csrapprover controller func AutoApproveNodeCertificateRotation(client clientset.Interface) error { - fmt.Println("[bootstraptoken] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster") + fmt.Println("[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster") return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/token.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/token.go index 02f63b7ce..f24629865 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/token.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/token.go @@ -18,109 +18,43 @@ package node import ( "fmt" - "strings" - "time" - "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" - bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" ) -const tokenCreateRetries = 5 +// TODO(mattmoyer): Move CreateNewTokens, UpdateOrCreateTokens out of this package to client-go for a generic abstraction and client for a Bootstrap Token -// TODO(mattmoyer): Move CreateNewToken, UpdateOrCreateToken and encodeTokenSecretData out of this package to client-go for a generic abstraction and client for a Bootstrap Token - -// CreateNewToken tries to create a token and fails if one with the same ID already exists -func CreateNewToken(client clientset.Interface, token string, tokenDuration time.Duration, usages []string, extraGroups []string, description string) error { - return UpdateOrCreateToken(client, token, true, tokenDuration, usages, extraGroups, description) +// CreateNewTokens tries to create a token and fails if one with the same ID already exists +func CreateNewTokens(client clientset.Interface, tokens []kubeadmapi.BootstrapToken) error { + return UpdateOrCreateTokens(client, true, tokens) } -// UpdateOrCreateToken attempts to update a token with the given ID, or create if it does not already exist. -func UpdateOrCreateToken(client clientset.Interface, token string, failIfExists bool, tokenDuration time.Duration, usages []string, extraGroups []string, description string) error { - tokenID, tokenSecret, err := tokenutil.ParseToken(token) - if err != nil { - return err - } - secretName := fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID) - var lastErr error - for i := 0; i < tokenCreateRetries; i++ { +// UpdateOrCreateTokens attempts to update a token with the given ID, or create if it does not already exist. +func UpdateOrCreateTokens(client clientset.Interface, failIfExists bool, tokens []kubeadmapi.BootstrapToken) error { + + for _, token := range tokens { + + secretName := bootstraputil.BootstrapTokenSecretName(token.Token.ID) secret, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Get(secretName, metav1.GetOptions{}) - if err == nil { - if failIfExists { - return fmt.Errorf("a token with id %q already exists", tokenID) - } - // Secret with this ID already exists, update it: - tokenSecretData, err := encodeTokenSecretData(tokenID, tokenSecret, tokenDuration, usages, extraGroups, description) - if err != nil { - return err - } - secret.Data = tokenSecretData - if _, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Update(secret); err == nil { - return nil - } - lastErr = err - continue + if secret != nil && err == nil && failIfExists { + return fmt.Errorf("a token with id %q already exists", token.Token.ID) } - // Secret does not already exist: - if apierrors.IsNotFound(err) { - tokenSecretData, err := encodeTokenSecretData(tokenID, tokenSecret, tokenDuration, usages, extraGroups, description) - if err != nil { - return err - } - - secret = &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - }, - Type: v1.SecretType(bootstrapapi.SecretTypeBootstrapToken), - Data: tokenSecretData, + updatedOrNewSecret := token.ToSecret() + // Try to create or update the token with an exponential backoff + err = apiclient.TryRunCommand(func() error { + if err := apiclient.CreateOrUpdateSecret(client, updatedOrNewSecret); err != nil { + return fmt.Errorf("failed to create or update bootstrap token with name %s: %v", secretName, err) } - if _, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret); err == nil { - return nil - } - lastErr = err - continue + return nil + }, 5) + if err != nil { + return err } - - } - return fmt.Errorf( - "unable to create bootstrap token after %d attempts [%v]", - tokenCreateRetries, - lastErr, - ) -} - -// encodeTokenSecretData takes the token discovery object and an optional duration and returns the .Data for the Secret -func encodeTokenSecretData(tokenID, tokenSecret string, duration time.Duration, usages []string, extraGroups []string, description string) (map[string][]byte, error) { - data := map[string][]byte{ - bootstrapapi.BootstrapTokenIDKey: []byte(tokenID), - bootstrapapi.BootstrapTokenSecretKey: []byte(tokenSecret), - } - - if len(extraGroups) > 0 { - data[bootstrapapi.BootstrapTokenExtraGroupsKey] = []byte(strings.Join(extraGroups, ",")) - } - - if duration > 0 { - // Get the current time, add the specified duration, and format it accordingly - durationString := time.Now().Add(duration).Format(time.RFC3339) - data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(durationString) - } - if len(description) > 0 { - data[bootstrapapi.BootstrapTokenDescriptionKey] = []byte(description) - } - - // validate usages - if err := bootstraputil.ValidateUsages(usages); err != nil { - return nil, err - } - for _, usage := range usages { - data[bootstrapapi.BootstrapTokenUsagePrefix+usage] = []byte("true") } - return data, nil + return nil } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/token_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/token_test.go deleted file mode 100644 index 48bc8c1f1..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node/token_test.go +++ /dev/null @@ -1,59 +0,0 @@ -/* -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 node - -import ( - "bytes" - "testing" - "time" - - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" -) - -func TestEncodeTokenSecretData(t *testing.T) { - var tests = []struct { - token *kubeadmapi.TokenDiscovery - t time.Duration - }{ - {token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}}, // should use default - {token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}, t: time.Second}, // should use default - } - for _, rt := range tests { - actual, _ := encodeTokenSecretData(rt.token.ID, rt.token.Secret, rt.t, []string{}, []string{}, "") - if !bytes.Equal(actual["token-id"], []byte(rt.token.ID)) { - t.Errorf( - "failed EncodeTokenSecretData:\n\texpected: %s\n\t actual: %s", - rt.token.ID, - actual["token-id"], - ) - } - if !bytes.Equal(actual["token-secret"], []byte(rt.token.Secret)) { - t.Errorf( - "failed EncodeTokenSecretData:\n\texpected: %s\n\t actual: %s", - rt.token.Secret, - actual["token-secret"], - ) - } - if rt.t > 0 { - if actual["expiration"] == nil { - t.Errorf( - "failed EncodeTokenSecretData, duration was not added to time", - ) - } - } - } -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/BUILD index 3ac7c0fab..b72737bc6 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/BUILD @@ -30,6 +30,7 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs.go index 05c6a7525..fe0ae21b7 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs.go @@ -23,6 +23,8 @@ import ( "os" "path/filepath" + "github.com/golang/glog" + certutil "k8s.io/client-go/util/cert" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -32,7 +34,7 @@ import ( // CreatePKIAssets will create and write to disk all PKI assets necessary to establish the control plane. // If the PKI assets already exists in the target folder, they are used only if evaluated equal; otherwise an error is returned. func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating PKI assets") certActions := []func(cfg *kubeadmapi.MasterConfiguration) error{ CreateCACertAndKeyFiles, CreateAPIServerCertAndKeyFiles, @@ -49,8 +51,7 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration) error { CreateAPIServerEtcdClientCertAndKeyFiles, } - // Currently this is the only way we have to identify static pod etcd vs external etcd - if len(cfg.Etcd.Endpoints) == 0 { + if cfg.Etcd.Local != nil { certActions = append(certActions, etcdCertActions...) } @@ -61,7 +62,7 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration) error { } } - fmt.Printf("[certificates] Valid certificates and keys now exist in %q\n", cfg.CertificatesDir) + fmt.Printf("[certificates] valid certificates and keys now exist in %q\n", cfg.CertificatesDir) return nil } @@ -69,7 +70,7 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration) error { // CreateCACertAndKeyFiles create a new self signed cluster CA certificate and key files. // If the CA certificate and key files already exists in the target folder, they are used only if evaluated equal; otherwise an error is returned. func CreateCACertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("create a new self signed cluster CA certificate and key files") caCert, caKey, err := NewCACertAndKey() if err != nil { return err @@ -87,7 +88,7 @@ func CreateCACertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { // If the apiserver certificate and key files already exists in the target folder, they are used only if evaluated equal; otherwise an error is returned. // It assumes the cluster CA certificate and key files exist in the CertificatesDir. func CreateAPIServerCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating a new certificate and key files for the apiserver") caCert, caKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName) if err != nil { return err @@ -111,7 +112,7 @@ func CreateAPIServerCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { // If the apiserver-kubelet-client certificate and key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned. // It assumes the cluster CA certificate and key files exist in the CertificatesDir. func CreateAPIServerKubeletClientCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating a new certificate for kubelets calling apiserver") caCert, caKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName) if err != nil { return err @@ -136,7 +137,7 @@ func CreateAPIServerKubeletClientCertAndKeyFiles(cfg *kubeadmapi.MasterConfigura // This is a separate CA, so that kubernetes client identities cannot connect to etcd directly or peer with the etcd cluster. // If the etcd CA certificate and key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned. func CreateEtcdCACertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating a self signed etcd CA certificate and key files") etcdCACert, etcdCAKey, err := NewEtcdCACertAndKey() if err != nil { return err @@ -154,7 +155,7 @@ func CreateEtcdCACertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { // If the etcd serving certificate and key file already exist in the target folder, they are used only if evaluated equal; otherwise an error is returned. // It assumes the etcd CA certificate and key file exist in the CertificatesDir func CreateEtcdServerCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating a new server certificate and key files for etcd") etcdCACert, etcdCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName) if err != nil { return err @@ -178,7 +179,7 @@ func CreateEtcdServerCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error // If the etcd peer certificate and key file already exist in the target folder, they are used only if evaluated equal; otherwise an error is returned. // It assumes the etcd CA certificate and key file exist in the CertificatesDir func CreateEtcdPeerCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating a new certificate and key files for etcd peering") etcdCACert, etcdCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName) if err != nil { return err @@ -226,7 +227,7 @@ func CreateEtcdHealthcheckClientCertAndKeyFiles(cfg *kubeadmapi.MasterConfigurat // If the apiserver-etcd-client certificate and key file already exist in the target folder, they are used only if evaluated equal; otherwise an error is returned. // It assumes the etcd CA certificate and key file exist in the CertificatesDir func CreateAPIServerEtcdClientCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating a new client certificate for the apiserver calling etcd") etcdCACert, etcdCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName) if err != nil { return err @@ -249,7 +250,7 @@ func CreateAPIServerEtcdClientCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguratio // CreateServiceAccountKeyAndPublicKeyFiles create a new public/private key files for signing service account users. // If the sa public/private key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned. func CreateServiceAccountKeyAndPublicKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating a new public/private key files for signing service account users") saSigningKey, err := NewServiceAccountSigningKey() if err != nil { return err @@ -268,7 +269,7 @@ func CreateServiceAccountKeyAndPublicKeyFiles(cfg *kubeadmapi.MasterConfiguratio // as front proxies. // If the front proxy CA certificate and key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned. func CreateFrontProxyCACertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating a self signed front proxy CA certificate and key files") frontProxyCACert, frontProxyCAKey, err := NewFrontProxyCACertAndKey() if err != nil { return err @@ -286,7 +287,7 @@ func CreateFrontProxyCACertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) erro // If the front-proxy-client certificate and key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned. // It assumes the front proxy CA certificate and key files exist in the CertificatesDir. func CreateFrontProxyClientCertAndKeyFiles(cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating a new certificate for proxy server client") frontProxyCACert, frontProxyCAKey, err := loadCertificateAuthority(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertAndKeyBaseName) if err != nil { return err @@ -374,9 +375,9 @@ func NewEtcdServerCertAndKey(cfg *kubeadmapi.MasterConfiguration, caCert *x509.C } config := certutil.Config{ - CommonName: kubeadmconstants.EtcdServerCertCommonName, + CommonName: cfg.NodeRegistration.Name, AltNames: *altNames, - Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, } etcdServerCert, etcdServerKey, err := pkiutil.NewCertAndKey(caCert, caKey, config) if err != nil { @@ -395,7 +396,7 @@ func NewEtcdPeerCertAndKey(cfg *kubeadmapi.MasterConfiguration, caCert *x509.Cer } config := certutil.Config{ - CommonName: kubeadmconstants.EtcdPeerCertCommonName, + CommonName: cfg.NodeRegistration.Name, AltNames: *altNames, Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, } @@ -616,8 +617,9 @@ type certKeyLocation struct { uxName string } -// UsingExternalCA determines whether the user is relying on an external CA. We currently implicitly determine this is the case when the CA Cert -// is present but the CA Key is not. This allows us to, e.g., skip generating certs or not start the csr signing controller. +// UsingExternalCA determines whether the user is relying on an external CA. We currently implicitly determine this is the case +// when both the CA Cert and the front proxy CA Cert are present but the CA Key and front proxy CA Key are not. +// This allows us to, e.g., skip generating certs or not start the csr signing controller. func UsingExternalCA(cfg *kubeadmapi.MasterConfiguration) (bool, error) { if err := validateCACert(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName, "", "CA"}); err != nil { @@ -626,7 +628,7 @@ func UsingExternalCA(cfg *kubeadmapi.MasterConfiguration) (bool, error) { caKeyPath := filepath.Join(cfg.CertificatesDir, kubeadmconstants.CAKeyName) if _, err := os.Stat(caKeyPath); !os.IsNotExist(err) { - return false, fmt.Errorf("ca.key exists") + return false, fmt.Errorf("%s exists", kubeadmconstants.CAKeyName) } if err := validateSignedCert(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName, kubeadmconstants.APIServerCertAndKeyBaseName, "API server"}); err != nil { @@ -641,10 +643,15 @@ func UsingExternalCA(cfg *kubeadmapi.MasterConfiguration) (bool, error) { return false, err } - if err := validateCACertAndKey(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertAndKeyBaseName, "", "front-proxy CA"}); err != nil { + if err := validateCACert(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertAndKeyBaseName, "", "front-proxy CA"}); err != nil { return false, err } + frontProxyCAKeyPath := filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCAKeyName) + if _, err := os.Stat(frontProxyCAKeyPath); !os.IsNotExist(err) { + return false, fmt.Errorf("%s exists", kubeadmconstants.FrontProxyCAKeyName) + } + if err := validateSignedCert(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertAndKeyBaseName, kubeadmconstants.FrontProxyClientCertAndKeyBaseName, "front-proxy client"}); err != nil { return false, err } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs_test.go index 6fb5f3e32..f3db29c11 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs_test.go @@ -273,9 +273,9 @@ func TestNewAPIServerCertAndKey(t *testing.T) { advertiseAddresses := []string{"1.2.3.4", "1:2:3::4"} for _, addr := range advertiseAddresses { cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: addr}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: hostname, + API: kubeadmapi.API{AdvertiseAddress: addr}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: hostname}, } caCert, caKey, err := NewCACertAndKey() if err != nil { @@ -324,10 +324,15 @@ func TestNewEtcdServerCertAndKey(t *testing.T) { proxyIP := "10.10.10.100" cfg := &kubeadmapi.MasterConfiguration{ + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "etcd-server-cert", + }, Etcd: kubeadmapi.Etcd{ - ServerCertSANs: []string{ - proxy, - proxyIP, + Local: &kubeadmapi.LocalEtcd{ + ServerCertSANs: []string{ + proxy, + proxyIP, + }, }, }, } @@ -355,12 +360,14 @@ func TestNewEtcdPeerCertAndKey(t *testing.T) { advertiseAddresses := []string{"1.2.3.4", "1:2:3::4"} for _, addr := range advertiseAddresses { cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: addr}, - NodeName: hostname, + API: kubeadmapi.API{AdvertiseAddress: addr}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: hostname}, Etcd: kubeadmapi.Etcd{ - PeerCertSANs: []string{ - proxy, - proxyIP, + Local: &kubeadmapi.LocalEtcd{ + PeerCertSANs: []string{ + proxy, + proxyIP, + }, }, }, } @@ -466,6 +473,7 @@ func TestUsingExternalCA(t *testing.T) { setupFuncs: []func(cfg *kubeadmapi.MasterConfiguration) error{ CreatePKIAssets, deleteCAKey, + deleteFrontProxyCAKey, }, expected: true, }, @@ -476,10 +484,10 @@ func TestUsingExternalCA(t *testing.T) { defer os.RemoveAll(dir) cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", - CertificatesDir: dir, + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, + CertificatesDir: dir, } for _, f := range test.setupFuncs { @@ -559,10 +567,10 @@ func TestValidateMethods(t *testing.T) { test.loc.pkiDir = dir cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", - CertificatesDir: dir, + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, + CertificatesDir: dir, } fmt.Println("Testing", test.name) @@ -583,16 +591,17 @@ func TestValidateMethods(t *testing.T) { } func deleteCAKey(cfg *kubeadmapi.MasterConfiguration) error { - if err := os.Remove(filepath.Join(cfg.CertificatesDir, "ca.key")); err != nil { - return fmt.Errorf("failed removing ca.key: %v", err) + if err := os.Remove(filepath.Join(cfg.CertificatesDir, kubeadmconstants.CAKeyName)); err != nil { + return fmt.Errorf("failed removing %s: %v", kubeadmconstants.CAKeyName, err) } return nil } -func assertIsCa(t *testing.T, cert *x509.Certificate) { - if !cert.IsCA { - t.Error("cert is not a valida CA") +func deleteFrontProxyCAKey(cfg *kubeadmapi.MasterConfiguration) error { + if err := os.Remove(filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCAKeyName)); err != nil { + return fmt.Errorf("failed removing %s: %v", kubeadmconstants.FrontProxyCAKeyName, err) } + return nil } func TestCreateCertificateFilesMethods(t *testing.T) { @@ -690,14 +699,19 @@ func TestCreateCertificateFilesMethods(t *testing.T) { defer os.RemoveAll(tmpdir) cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", - CertificatesDir: tmpdir, + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, + Etcd: kubeadmapi.Etcd{Local: &kubeadmapi.LocalEtcd{}}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, + CertificatesDir: tmpdir, } if test.externalEtcd { - cfg.Etcd.Endpoints = []string{"192.168.1.1:2379"} + if cfg.Etcd.External == nil { + cfg.Etcd.External = &kubeadmapi.ExternalEtcd{} + } + cfg.Etcd.Local = nil + cfg.Etcd.External.Endpoints = []string{"192.168.1.1:2379"} } // executes setup func (if necessary) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/doc.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/doc.go index 0a60f992d..6f9801fd5 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/doc.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/doc.go @@ -24,8 +24,8 @@ package certs From MasterConfiguration .API.AdvertiseAddress is an optional parameter that can be passed for an extra addition to the SAN IPs .APIServerCertSANs is an optional parameter for adding DNS names and IPs to the API Server serving cert SAN - .Etcd.ServerCertSANs is an optional parameter for adding DNS names and IPs to the etcd serving cert SAN - .Etcd.PeerCertSANs is an optional parameter for adding DNS names and IPs to the etcd peer cert SAN + .Etcd.Local.ServerCertSANs is an optional parameter for adding DNS names and IPs to the etcd serving cert SAN + .Etcd.Local.PeerCertSANs is an optional parameter for adding DNS names and IPs to the etcd peer cert SAN .Networking.DNSDomain is needed for knowing which DNS name the internal kubernetes service has .Networking.ServiceSubnet is needed for knowing which IP the internal kubernetes service is going to point to .CertificatesDir is required for knowing where all certificates should be stored diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/BUILD index f4c8a7431..28d664faf 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/BUILD @@ -23,6 +23,7 @@ go_library( deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/util:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers.go index 996688ee6..e1d456b39 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers.go @@ -29,6 +29,7 @@ import ( certutil "k8s.io/client-go/util/cert" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" ) @@ -274,7 +275,7 @@ func GetAPIServerAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltNam // create AltNames with defaults DNSNames/IPs altNames := &certutil.AltNames{ DNSNames: []string{ - cfg.NodeName, + cfg.NodeRegistration.Name, "kubernetes", "kubernetes.default", "kubernetes.default.svc", @@ -286,9 +287,17 @@ func GetAPIServerAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltNam }, } - // add api server dns advertise address + // add api server controlPlaneEndpoint if present (dns or ip) if len(cfg.API.ControlPlaneEndpoint) > 0 { - altNames.DNSNames = append(altNames.DNSNames, cfg.API.ControlPlaneEndpoint) + if host, _, err := kubeadmutil.ParseHostPort(cfg.API.ControlPlaneEndpoint); err == nil { + if ip := net.ParseIP(host); ip != nil { + altNames.IPs = append(altNames.IPs, ip) + } else { + altNames.DNSNames = append(altNames.DNSNames, host) + } + } else { + return nil, fmt.Errorf("error parsing API api.controlPlaneEndpoint %q: %s", cfg.API.ControlPlaneEndpoint, err) + } } appendSANsToAltNames(altNames, cfg.APIServerCertSANs, kubeadmconstants.APIServerCertName) @@ -303,11 +312,13 @@ func GetAPIServerAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltNam func GetEtcdAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltNames, error) { // create AltNames with defaults DNSNames/IPs altNames := &certutil.AltNames{ - DNSNames: []string{"localhost"}, - IPs: []net.IP{net.IPv4(127, 0, 0, 1)}, + DNSNames: []string{cfg.NodeRegistration.Name, "localhost"}, + IPs: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback}, } - appendSANsToAltNames(altNames, cfg.Etcd.ServerCertSANs, kubeadmconstants.EtcdServerCertName) + if cfg.Etcd.Local != nil { + appendSANsToAltNames(altNames, cfg.Etcd.Local.ServerCertSANs, kubeadmconstants.EtcdServerCertName) + } return altNames, nil } @@ -325,11 +336,13 @@ func GetEtcdPeerAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltName // create AltNames with defaults DNSNames/IPs altNames := &certutil.AltNames{ - DNSNames: []string{cfg.NodeName}, - IPs: []net.IP{advertiseAddress}, + DNSNames: []string{cfg.NodeRegistration.Name, "localhost"}, + IPs: []net.IP{advertiseAddress, net.IPv4(127, 0, 0, 1), net.IPv6loopback}, } - appendSANsToAltNames(altNames, cfg.Etcd.PeerCertSANs, kubeadmconstants.EtcdPeerCertName) + if cfg.Etcd.Local != nil { + appendSANsToAltNames(altNames, cfg.Etcd.Local.PeerCertSANs, kubeadmconstants.EtcdPeerCertName) + } return altNames, nil } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers_test.go index ba4057c6c..cc2a5cb37 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil/pki_helpers_test.go @@ -436,48 +436,69 @@ func TestPathForPublicKey(t *testing.T) { } func TestGetAPIServerAltNames(t *testing.T) { - hostname := "valid-hostname" - advertiseIP := "1.2.3.4" - controlPlaneEndpoint := "api.k8s.io" - cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: advertiseIP, ControlPlaneEndpoint: controlPlaneEndpoint}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: hostname, - APIServerCertSANs: []string{"10.1.245.94", "10.1.245.95", "1.2.3.L", "invalid,commas,in,DNS"}, - } - altNames, err := GetAPIServerAltNames(cfg) - if err != nil { - t.Fatalf("failed calling GetAPIServerAltNames: %v", err) + var tests = []struct { + name string + cfg *kubeadmapi.MasterConfiguration + expectedDNSNames []string + expectedIPAddresses []string + }{ + { + name: "ControlPlaneEndpoint DNS", + cfg: &kubeadmapi.MasterConfiguration{ + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "api.k8s.io:6443"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, + APIServerCertSANs: []string{"10.1.245.94", "10.1.245.95", "1.2.3.L", "invalid,commas,in,DNS"}, + }, + expectedDNSNames: []string{"valid-hostname", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local", "api.k8s.io"}, + expectedIPAddresses: []string{"10.96.0.1", "1.2.3.4", "10.1.245.94", "10.1.245.95"}, + }, + { + name: "ControlPlaneEndpoint IP", + cfg: &kubeadmapi.MasterConfiguration{ + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", ControlPlaneEndpoint: "4.5.6.7:6443"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, + APIServerCertSANs: []string{"10.1.245.94", "10.1.245.95", "1.2.3.L", "invalid,commas,in,DNS"}, + }, + expectedDNSNames: []string{"valid-hostname", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local"}, + expectedIPAddresses: []string{"10.96.0.1", "1.2.3.4", "10.1.245.94", "10.1.245.95", "4.5.6.7"}, + }, } - expectedDNSNames := []string{hostname, "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local", controlPlaneEndpoint} - for _, DNSName := range expectedDNSNames { - found := false - for _, val := range altNames.DNSNames { - if val == DNSName { - found = true - break - } + for _, rt := range tests { + altNames, err := GetAPIServerAltNames(rt.cfg) + if err != nil { + t.Fatalf("failed calling GetAPIServerAltNames: %s: %v", rt.name, err) } - if !found { - t.Errorf("altNames does not contain DNSName %s", DNSName) - } - } + for _, DNSName := range rt.expectedDNSNames { + found := false + for _, val := range altNames.DNSNames { + if val == DNSName { + found = true + break + } + } - expectedIPAddresses := []string{"10.96.0.1", advertiseIP, "10.1.245.94", "10.1.245.95"} - for _, IPAddress := range expectedIPAddresses { - found := false - for _, val := range altNames.IPs { - if val.Equal(net.ParseIP(IPAddress)) { - found = true - break + if !found { + t.Errorf("%s: altNames does not contain DNSName %s but %v", rt.name, DNSName, altNames.DNSNames) } } - if !found { - t.Errorf("altNames does not contain IPAddress %s", IPAddress) + for _, IPAddress := range rt.expectedIPAddresses { + found := false + for _, val := range altNames.IPs { + if val.Equal(net.ParseIP(IPAddress)) { + found = true + break + } + } + + if !found { + t.Errorf("%s: altNames does not contain IPAddress %s but %v", rt.name, IPAddress, altNames.IPs) + } } } } @@ -487,11 +508,13 @@ func TestGetEtcdAltNames(t *testing.T) { proxyIP := "10.10.10.100" cfg := &kubeadmapi.MasterConfiguration{ Etcd: kubeadmapi.Etcd{ - ServerCertSANs: []string{ - proxy, - proxyIP, - "1.2.3.L", - "invalid,commas,in,DNS", + Local: &kubeadmapi.LocalEtcd{ + ServerCertSANs: []string{ + proxy, + proxyIP, + "1.2.3.L", + "invalid,commas,in,DNS", + }, }, }, } @@ -516,7 +539,7 @@ func TestGetEtcdAltNames(t *testing.T) { } } - expectedIPAddresses := []string{"127.0.0.1", proxyIP} + expectedIPAddresses := []string{"127.0.0.1", net.IPv6loopback.String(), proxyIP} for _, IPAddress := range expectedIPAddresses { found := false for _, val := range altNames.IPs { @@ -538,14 +561,16 @@ func TestGetEtcdPeerAltNames(t *testing.T) { proxyIP := "10.10.10.100" advertiseIP := "1.2.3.4" cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: advertiseIP}, - NodeName: hostname, + API: kubeadmapi.API{AdvertiseAddress: advertiseIP}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: hostname}, Etcd: kubeadmapi.Etcd{ - PeerCertSANs: []string{ - proxy, - proxyIP, - "1.2.3.L", - "invalid,commas,in,DNS", + Local: &kubeadmapi.LocalEtcd{ + PeerCertSANs: []string{ + proxy, + proxyIP, + "1.2.3.L", + "invalid,commas,in,DNS", + }, }, }, } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/BUILD index 8622f12fe..6e826f4fd 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/BUILD @@ -19,10 +19,11 @@ go_test( "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/phases/certs:go_default_library", "//cmd/kubeadm/test:go_default_library", - "//pkg/master/reconcilers:go_default_library", + "//pkg/kubeapiserver/authorizer/modes:go_default_library", "//pkg/util/pointer:go_default_library", "//pkg/util/version:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", ], ) @@ -35,7 +36,7 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/images:go_default_library", @@ -43,9 +44,8 @@ go_library( "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/staticpod:go_default_library", "//pkg/kubeapiserver/authorizer/modes:go_default_library", - "//pkg/master/reconcilers:go_default_library", - "//pkg/util/pointer:go_default_library", "//pkg/util/version:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/manifests.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/manifests.go index 2f6fe724c..1295ab5df 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/manifests.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/manifests.go @@ -24,10 +24,11 @@ import ( "strconv" "strings" + "github.com/golang/glog" + "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/sets" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/images" @@ -35,36 +36,30 @@ import ( kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod" authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" - "k8s.io/kubernetes/pkg/master/reconcilers" - utilpointer "k8s.io/kubernetes/pkg/util/pointer" "k8s.io/kubernetes/pkg/util/version" ) -// Static pod definitions in golang form are included below so that `kubeadm init` can get going. -const ( - DefaultCloudConfigPath = "/etc/kubernetes/cloud-config" - - deprecatedV19AdmissionControl = "NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" - defaultV19AdmissionControl = "NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" -) - // CreateInitStaticPodManifestFiles will write all static pod manifest files needed to bring up the control plane. func CreateInitStaticPodManifestFiles(manifestDir string, cfg *kubeadmapi.MasterConfiguration) error { + glog.V(1).Infoln("[controlplane] creating static pod files") return createStaticPodFiles(manifestDir, cfg, kubeadmconstants.KubeAPIServer, kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeScheduler) } // CreateAPIServerStaticPodManifestFile will write APIserver static pod manifest file. func CreateAPIServerStaticPodManifestFile(manifestDir string, cfg *kubeadmapi.MasterConfiguration) error { + glog.V(1).Infoln("creating APIserver static pod files") return createStaticPodFiles(manifestDir, cfg, kubeadmconstants.KubeAPIServer) } // CreateControllerManagerStaticPodManifestFile will write controller manager static pod manifest file. func CreateControllerManagerStaticPodManifestFile(manifestDir string, cfg *kubeadmapi.MasterConfiguration) error { + glog.V(1).Infoln("creating controller manager static pod files") return createStaticPodFiles(manifestDir, cfg, kubeadmconstants.KubeControllerManager) } // CreateSchedulerStaticPodManifestFile will write scheduler static pod manifest file. func CreateSchedulerStaticPodManifestFile(manifestDir string, cfg *kubeadmapi.MasterConfiguration) error { + glog.V(1).Infoln("creating scheduler static pod files") return createStaticPodFiles(manifestDir, cfg, kubeadmconstants.KubeScheduler) } @@ -79,8 +74,8 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version. kubeadmconstants.KubeAPIServer: staticpodutil.ComponentPod(v1.Container{ Name: kubeadmconstants.KubeAPIServer, Image: images.GetCoreImage(kubeadmconstants.KubeAPIServer, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage), - ImagePullPolicy: cfg.ImagePullPolicy, - Command: getAPIServerCommand(cfg, k8sVersion), + ImagePullPolicy: v1.PullIfNotPresent, + Command: getAPIServerCommand(cfg), VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeAPIServer)), LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeAPIServer, int(cfg.API.BindPort), "/healthz", v1.URISchemeHTTPS), Resources: staticpodutil.ComponentResources("250m"), @@ -89,7 +84,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version. kubeadmconstants.KubeControllerManager: staticpodutil.ComponentPod(v1.Container{ Name: kubeadmconstants.KubeControllerManager, Image: images.GetCoreImage(kubeadmconstants.KubeControllerManager, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage), - ImagePullPolicy: cfg.ImagePullPolicy, + ImagePullPolicy: v1.PullIfNotPresent, Command: getControllerManagerCommand(cfg, k8sVersion), VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeControllerManager)), LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeControllerManager, 10252, "/healthz", v1.URISchemeHTTP), @@ -99,7 +94,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version. kubeadmconstants.KubeScheduler: staticpodutil.ComponentPod(v1.Container{ Name: kubeadmconstants.KubeScheduler, Image: images.GetCoreImage(kubeadmconstants.KubeScheduler, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage), - ImagePullPolicy: cfg.ImagePullPolicy, + ImagePullPolicy: v1.PullIfNotPresent, Command: getSchedulerCommand(cfg), VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeScheduler)), LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeScheduler, 10251, "/healthz", v1.URISchemeHTTP), @@ -107,19 +102,6 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version. Env: getProxyEnvVars(), }, mounts.GetVolumes(kubeadmconstants.KubeScheduler)), } - - // Some cloud providers need extra privileges for example to load node information from a config drive - // TODO: when we fully to external cloud providers and the api server and controller manager do not need - // to call out to cloud provider code, we can remove the support for the PrivilegedPods - if cfg.PrivilegedPods { - staticPodSpecs[kubeadmconstants.KubeAPIServer].Spec.Containers[0].SecurityContext = &v1.SecurityContext{ - Privileged: utilpointer.BoolPtr(true), - } - staticPodSpecs[kubeadmconstants.KubeControllerManager].Spec.Containers[0].SecurityContext = &v1.SecurityContext{ - Privileged: utilpointer.BoolPtr(true), - } - } - return staticPodSpecs } @@ -132,6 +114,7 @@ func createStaticPodFiles(manifestDir string, cfg *kubeadmapi.MasterConfiguratio } // gets the StaticPodSpecs, actualized for the current MasterConfiguration + glog.V(1).Infoln("[controlplane] getting StaticPodSpecs") specs := GetStaticPodSpecs(cfg, k8sVersion) // creates required static pod specs @@ -147,18 +130,23 @@ func createStaticPodFiles(manifestDir string, cfg *kubeadmapi.MasterConfiguratio return fmt.Errorf("failed to create static pod manifest file for %q: %v", componentName, err) } - fmt.Printf("[controlplane] Wrote Static Pod manifest for component %s to %q\n", componentName, kubeadmconstants.GetStaticPodFilepath(componentName, manifestDir)) + fmt.Printf("[controlplane] wrote Static Pod manifest for component %s to %q\n", componentName, kubeadmconstants.GetStaticPodFilepath(componentName, manifestDir)) } return nil } // getAPIServerCommand builds the right API server command from the given config object and version -func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.Version) []string { +func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string { defaultArguments := map[string]string{ - "advertise-address": cfg.API.AdvertiseAddress, - "insecure-port": "0", - "admission-control": defaultV19AdmissionControl, + "advertise-address": cfg.API.AdvertiseAddress, + "insecure-port": "0", + "enable-admission-plugins": "NodeRestriction", + // TODO: remove `PersistentVolumeLabel` in kubeadm v1.11, as it's automatically disabled in v1.11. + // ref: https://github.com/kubernetes/kubernetes/pull/64326 + // we can't skip it now as we support v1.10 clusters still. + // remove it from the unit tests too. + "disable-admission-plugins": "PersistentVolumeLabel", "service-cluster-ip-range": cfg.Networking.ServiceSubnet, "service-account-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPublicKeyName), "client-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName), @@ -183,76 +171,69 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, k8sVersion *versio command := []string{"kube-apiserver"} - if cfg.CloudProvider == "aws" || cfg.CloudProvider == "gce" { - defaultArguments["admission-control"] = deprecatedV19AdmissionControl - } - - command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.APIServerExtraArgs)...) - command = append(command, getAuthzParameters(cfg.AuthorizationModes)...) - // If the user set endpoints for an external etcd cluster - if len(cfg.Etcd.Endpoints) > 0 { - command = append(command, fmt.Sprintf("--etcd-servers=%s", strings.Join(cfg.Etcd.Endpoints, ","))) + if cfg.Etcd.External != nil { + defaultArguments["etcd-servers"] = strings.Join(cfg.Etcd.External.Endpoints, ",") // Use any user supplied etcd certificates - if cfg.Etcd.CAFile != "" { - command = append(command, fmt.Sprintf("--etcd-cafile=%s", cfg.Etcd.CAFile)) + if cfg.Etcd.External.CAFile != "" { + defaultArguments["etcd-cafile"] = cfg.Etcd.External.CAFile } - if cfg.Etcd.CertFile != "" && cfg.Etcd.KeyFile != "" { - etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", cfg.Etcd.CertFile) - etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", cfg.Etcd.KeyFile) - command = append(command, etcdClientFileArg, etcdKeyFileArg) + if cfg.Etcd.External.CertFile != "" && cfg.Etcd.External.KeyFile != "" { + defaultArguments["etcd-certfile"] = cfg.Etcd.External.CertFile + defaultArguments["etcd-keyfile"] = cfg.Etcd.External.KeyFile } } else { // Default to etcd static pod on localhost - etcdEndpointsArg := "--etcd-servers=https://127.0.0.1:2379" - etcdCAFileArg := fmt.Sprintf("--etcd-cafile=%s", filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName)) - etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientCertName)) - etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientKeyName)) - command = append(command, etcdEndpointsArg, etcdCAFileArg, etcdClientFileArg, etcdKeyFileArg) - - // Warn for unused user supplied variables - if cfg.Etcd.CAFile != "" { - fmt.Printf("[controlplane] WARNING: Configuration for %s CAFile, %s, is unused without providing Endpoints for external %s\n", kubeadmconstants.Etcd, cfg.Etcd.CAFile, kubeadmconstants.Etcd) - } - if cfg.Etcd.CertFile != "" { - fmt.Printf("[controlplane] WARNING: Configuration for %s CertFile, %s, is unused without providing Endpoints for external %s\n", kubeadmconstants.Etcd, cfg.Etcd.CertFile, kubeadmconstants.Etcd) - } - if cfg.Etcd.KeyFile != "" { - fmt.Printf("[controlplane] WARNING: Configuration for %s KeyFile, %s, is unused without providing Endpoints for external %s\n", kubeadmconstants.Etcd, cfg.Etcd.KeyFile, kubeadmconstants.Etcd) - } - } - - if cfg.CloudProvider != "" { - command = append(command, "--cloud-provider="+cfg.CloudProvider) - - // Only append the --cloud-config option if there's a such file - if _, err := os.Stat(DefaultCloudConfigPath); err == nil { - command = append(command, "--cloud-config="+DefaultCloudConfigPath) - } + defaultArguments["etcd-servers"] = "https://127.0.0.1:2379" + defaultArguments["etcd-cafile"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName) + defaultArguments["etcd-certfile"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientCertName) + defaultArguments["etcd-keyfile"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientKeyName) } if features.Enabled(cfg.FeatureGates, features.HighAvailability) { - command = append(command, "--endpoint-reconciler-type="+reconcilers.LeaseEndpointReconcilerType) + defaultArguments["endpoint-reconciler-type"] = kubeadmconstants.LeaseEndpointReconcilerType } if features.Enabled(cfg.FeatureGates, features.DynamicKubeletConfig) { - command = append(command, "--feature-gates=DynamicKubeletConfig=true") + defaultArguments["feature-gates"] = "DynamicKubeletConfig=true" } if features.Enabled(cfg.FeatureGates, features.Auditing) { - command = append(command, "--audit-policy-file="+kubeadmconstants.GetStaticPodAuditPolicyFile()) - command = append(command, "--audit-log-path="+filepath.Join(kubeadmconstants.StaticPodAuditPolicyLogDir, kubeadmconstants.AuditPolicyLogFile)) + defaultArguments["audit-policy-file"] = kubeadmconstants.GetStaticPodAuditPolicyFile() + defaultArguments["audit-log-path"] = filepath.Join(kubeadmconstants.StaticPodAuditPolicyLogDir, kubeadmconstants.AuditPolicyLogFile) if cfg.AuditPolicyConfiguration.LogMaxAge == nil { - command = append(command, fmt.Sprintf("--audit-log-maxage=%d", kubeadmapiext.DefaultAuditPolicyLogMaxAge)) + defaultArguments["audit-log-maxage"] = fmt.Sprintf("%d", kubeadmapiv1alpha2.DefaultAuditPolicyLogMaxAge) } else { - command = append(command, fmt.Sprintf("--audit-log-maxage=%d", *cfg.AuditPolicyConfiguration.LogMaxAge)) + defaultArguments["audit-log-maxage"] = fmt.Sprintf("%d", *cfg.AuditPolicyConfiguration.LogMaxAge) } } + if cfg.APIServerExtraArgs == nil { + cfg.APIServerExtraArgs = map[string]string{} + } + cfg.APIServerExtraArgs["authorization-mode"] = getAuthzModes(cfg.APIServerExtraArgs["authorization-mode"]) + command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.APIServerExtraArgs)...) return command } +// getAuthzModes gets the authorization-related parameters to the api server +// Node,RBAC should be fixed in this order at the beginning +// AlwaysAllow and AlwaysDeny is ignored as they are only for testing +func getAuthzModes(authzModeExtraArgs string) string { + modes := []string{ + authzmodes.ModeNode, + authzmodes.ModeRBAC, + } + if strings.Contains(authzModeExtraArgs, authzmodes.ModeABAC) { + modes = append(modes, authzmodes.ModeABAC) + } + if strings.Contains(authzModeExtraArgs, authzmodes.ModeWebhook) { + modes = append(modes, authzmodes.ModeWebhook) + } + return strings.Join(modes, ",") +} + // calcNodeCidrSize determines the size of the subnets used on each node, based // on the pod subnet provided. For IPv4, we assume that the pod subnet will // be /16 and use /24. If the pod subnet cannot be parsed, the IPv4 value will @@ -270,9 +251,6 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, k8sVersion *versio // If the pod network size is /113 or larger, the node CIDR will be set to the same // size and this will be rejected later in validation. // -// NOTE: Currently, the pod network must be /66 or larger. It is not reflected here, -// but a smaller value will fail later validation. -// // NOTE: Currently, the design allows a maximum of 64K nodes. This algorithm splits // the available bits to maximize the number used for nodes, but still have the node // CIDR be a multiple of eight. @@ -321,25 +299,18 @@ func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration, k8sVersion defaultArguments["cluster-signing-cert-file"] = "" } - command := []string{"kube-controller-manager"} - command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.ControllerManagerExtraArgs)...) - - if cfg.CloudProvider != "" { - command = append(command, "--cloud-provider="+cfg.CloudProvider) - - // Only append the --cloud-config option if there's a such file - if _, err := os.Stat(DefaultCloudConfigPath); err == nil { - command = append(command, "--cloud-config="+DefaultCloudConfigPath) - } - } - // Let the controller-manager allocate Node CIDRs for the Pod network. // Each node will get a subspace of the address CIDR provided with --pod-network-cidr. if cfg.Networking.PodSubnet != "" { maskSize := calcNodeCidrSize(cfg.Networking.PodSubnet) - command = append(command, "--allocate-node-cidrs=true", "--cluster-cidr="+cfg.Networking.PodSubnet, - "--node-cidr-mask-size="+maskSize) + defaultArguments["allocate-node-cidrs"] = "true" + defaultArguments["cluster-cidr"] = cfg.Networking.PodSubnet + defaultArguments["node-cidr-mask-size"] = maskSize } + + command := []string{"kube-controller-manager"} + command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.ControllerManagerExtraArgs)...) + return command } @@ -374,25 +345,3 @@ func getProxyEnvVars() []v1.EnvVar { } return envs } - -// getAuthzParameters gets the authorization-related parameters to the api server -// At this point, we can assume the list of authorization modes is valid (due to that it has been validated in the API machinery code already) -// If the list is empty; it's defaulted (mostly for unit testing) -func getAuthzParameters(modes []string) []string { - command := []string{} - strset := sets.NewString(modes...) - - if len(modes) == 0 { - return []string{fmt.Sprintf("--authorization-mode=%s", kubeadmapiext.DefaultAuthorizationModes)} - } - - if strset.Has(authzmodes.ModeABAC) { - command = append(command, "--authorization-policy-file="+kubeadmconstants.AuthorizationPolicyPath) - } - if strset.Has(authzmodes.ModeWebhook) { - command = append(command, "--authorization-webhook-config-file="+kubeadmconstants.AuthorizationWebhookConfigPath) - } - - command = append(command, "--authorization-mode="+strings.Join(modes, ",")) - return command -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/manifests_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/manifests_test.go index 35c07f47e..58b816368 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/manifests_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/manifests_test.go @@ -22,13 +22,15 @@ import ( "path/filepath" "reflect" "sort" + "strings" "testing" + "k8s.io/apimachinery/pkg/util/sets" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" - "k8s.io/kubernetes/pkg/master/reconcilers" + authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" "k8s.io/kubernetes/pkg/util/version" testutil "k8s.io/kubernetes/cmd/kubeadm/test" @@ -136,74 +138,24 @@ func TestCreateStaticPodFilesAndWrappers(t *testing.T) { } } -func TestCreatePrivilegedContainerForOpenStack(t *testing.T) { - // Creates a Master Configuration with OpenStack cloud provider - var staticPodNames = []string{ - kubeadmconstants.KubeAPIServer, - kubeadmconstants.KubeControllerManager, - } - var assertions = []struct { - cloudProvider string - privilegedPods bool - expectedPrivilege bool - }{ - { - cloudProvider: "", - expectedPrivilege: false, - }, - { - cloudProvider: "aws", - expectedPrivilege: false, - }, - { - cloudProvider: "openstack", - privilegedPods: true, - expectedPrivilege: true, - }, - } - - for _, assertion := range assertions { - cfg := &kubeadmapi.MasterConfiguration{ - KubernetesVersion: "v1.9.0", - CloudProvider: assertion.cloudProvider, - PrivilegedPods: assertion.privilegedPods, - } - - k8sVersion, _ := version.ParseSemantic(cfg.KubernetesVersion) - specs := GetStaticPodSpecs(cfg, k8sVersion) - - for _, podname := range staticPodNames { - spec, _ := specs[podname] - sc := spec.Spec.Containers[0].SecurityContext - if assertion.expectedPrivilege == true { - if sc == nil || sc.Privileged == nil || *sc.Privileged == false { - t.Errorf("GetStaticPodSpecs did not enable privileged containers in %s pod for provider %s", podname, assertion.cloudProvider) - } - } else { - if sc != nil && sc.Privileged != nil && *sc.Privileged == true { - t.Errorf("GetStaticPodSpecs enabled privileged containers in %s pod for provider %s", podname, assertion.cloudProvider) - } - } - } - } -} - func TestGetAPIServerCommand(t *testing.T) { var tests = []struct { + name string cfg *kubeadmapi.MasterConfiguration expected []string }{ { + name: "testing defaults", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -231,53 +183,22 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "ignores the audit policy if the feature gate is not enabled", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - }, - expected: []string{ - "kube-apiserver", - "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", - "--service-cluster-ip-range=bar", - "--service-account-key-file=" + testCertsDir + "/sa.pub", - "--client-ca-file=" + testCertsDir + "/ca.crt", - "--tls-cert-file=" + testCertsDir + "/apiserver.crt", - "--tls-private-key-file=" + testCertsDir + "/apiserver.key", - "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", - "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - "--secure-port=123", - "--allow-privileged=true", - "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--enable-bootstrap-token-auth=true", - "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", - "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", - "--requestheader-username-headers=X-Remote-User", - "--requestheader-group-headers=X-Remote-Group", - "--requestheader-extra-headers-prefix=X-Remote-Extra-", - "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", - "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=Node,RBAC", - "--advertise-address=1.2.3.4", - "--etcd-servers=https://127.0.0.1:2379", - "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", - "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", - "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", - }, - }, - { - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.1", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + AuditPolicyConfiguration: kubeadmapi.AuditPolicyConfiguration{ + Path: "/foo/bar", + LogDir: "/foo/baz", + LogMaxAge: utilpointer.Int32Ptr(10), + }, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -286,7 +207,7 @@ func TestGetAPIServerCommand(t *testing.T) { "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", "--enable-bootstrap-token-auth=true", - "--secure-port=123", + fmt.Sprintf("--secure-port=%d", 123), "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", @@ -305,17 +226,17 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "ipv6 advertise address", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -324,7 +245,7 @@ func TestGetAPIServerCommand(t *testing.T) { "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", "--enable-bootstrap-token-auth=true", - "--secure-port=123", + fmt.Sprintf("--secure-port=%d", 123), "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", @@ -335,7 +256,7 @@ func TestGetAPIServerCommand(t *testing.T) { "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", "--authorization-mode=Node,RBAC", - "--advertise-address=4.3.2.1", + "--advertise-address=2001:db8::1", "--etcd-servers=https://127.0.0.1:2379", "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", @@ -343,22 +264,26 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "an external etcd with custom ca, certs and keys", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.3", - AuditPolicyConfiguration: kubeadmapi.AuditPolicyConfiguration{ - Path: "/foo/bar", - LogDir: "/foo/baz", - LogMaxAge: utilpointer.Int32Ptr(10), - }, // ignored without the feature gate + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + FeatureGates: map[string]bool{features.HighAvailability: true}, + Etcd: kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"https://8.6.4.1:2379", "https://8.6.4.2:2379"}, + CAFile: "fuz", + CertFile: "fiz", + KeyFile: "faz", + }, + }, + CertificatesDir: testCertsDir, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -366,10 +291,10 @@ func TestGetAPIServerCommand(t *testing.T) { "--tls-private-key-file=" + testCertsDir + "/apiserver.key", "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - "--enable-bootstrap-token-auth=true", fmt.Sprintf("--secure-port=%d", 123), "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", + "--enable-bootstrap-token-auth=true", "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", "--requestheader-username-headers=X-Remote-User", @@ -378,25 +303,31 @@ func TestGetAPIServerCommand(t *testing.T) { "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", "--authorization-mode=Node,RBAC", - "--advertise-address=4.3.2.1", - "--etcd-servers=https://127.0.0.1:2379", - "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", - "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", - "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", + "--advertise-address=2001:db8::1", + "--etcd-servers=https://8.6.4.1:2379,https://8.6.4.2:2379", + "--etcd-cafile=fuz", + "--etcd-certfile=fiz", + "--etcd-keyfile=faz", + fmt.Sprintf("--endpoint-reconciler-type=%s", kubeadmconstants.LeaseEndpointReconcilerType), }, }, { + name: "an insecure etcd", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + Etcd: kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"http://127.0.0.1:2379", "http://127.0.0.1:2380"}, + }, + }, + CertificatesDir: testCertsDir, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -404,10 +335,10 @@ func TestGetAPIServerCommand(t *testing.T) { "--tls-private-key-file=" + testCertsDir + "/apiserver.key", "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - "--enable-bootstrap-token-auth=true", fmt.Sprintf("--secure-port=%d", 123), "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", + "--enable-bootstrap-token-auth=true", "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", "--requestheader-username-headers=X-Remote-User", @@ -417,24 +348,25 @@ func TestGetAPIServerCommand(t *testing.T) { "--requestheader-allowed-names=front-proxy-client", "--authorization-mode=Node,RBAC", "--advertise-address=2001:db8::1", - "--etcd-servers=https://127.0.0.1:2379", - "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", - "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", - "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", + "--etcd-servers=http://127.0.0.1:2379,http://127.0.0.1:2380", }, }, { + name: "auditing and HA are enabled with a custom log max age of 0", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + FeatureGates: map[string]bool{features.HighAvailability: true, features.Auditing: true}, + CertificatesDir: testCertsDir, + AuditPolicyConfiguration: kubeadmapi.AuditPolicyConfiguration{ + LogMaxAge: utilpointer.Int32Ptr(0), + }, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -459,21 +391,25 @@ func TestGetAPIServerCommand(t *testing.T) { "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", + fmt.Sprintf("--endpoint-reconciler-type=%s", kubeadmconstants.LeaseEndpointReconcilerType), + "--audit-policy-file=/etc/kubernetes/audit/audit.yaml", + "--audit-log-path=/var/log/kubernetes/audit/audit.log", + "--audit-log-maxage=0", }, }, { + name: "ensure the DynamicKubelet flag gets passed through", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - FeatureGates: map[string]bool{features.HighAvailability: true}, - Etcd: kubeadmapi.Etcd{Endpoints: []string{"https://8.6.4.1:2379", "https://8.6.4.2:2379"}, CAFile: "fuz", CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + FeatureGates: map[string]bool{features.DynamicKubeletConfig: true}, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -481,49 +417,10 @@ func TestGetAPIServerCommand(t *testing.T) { "--tls-private-key-file=" + testCertsDir + "/apiserver.key", "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - fmt.Sprintf("--secure-port=%d", 123), - "--allow-privileged=true", - "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", "--enable-bootstrap-token-auth=true", - "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", - "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", - "--requestheader-username-headers=X-Remote-User", - "--requestheader-group-headers=X-Remote-Group", - "--requestheader-extra-headers-prefix=X-Remote-Extra-", - "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", - "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=Node,RBAC", - "--advertise-address=2001:db8::1", - "--etcd-servers=https://8.6.4.1:2379,https://8.6.4.2:2379", - "--etcd-cafile=fuz", - "--etcd-certfile=fiz", - "--etcd-keyfile=faz", - fmt.Sprintf("--endpoint-reconciler-type=%s", reconcilers.LeaseEndpointReconcilerType), - }, - }, - { - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{Endpoints: []string{"http://127.0.0.1:2379", "http://127.0.0.1:2380"}}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - }, - expected: []string{ - "kube-apiserver", - "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", - "--service-cluster-ip-range=bar", - "--service-account-key-file=" + testCertsDir + "/sa.pub", - "--client-ca-file=" + testCertsDir + "/ca.crt", - "--tls-cert-file=" + testCertsDir + "/apiserver.crt", - "--tls-private-key-file=" + testCertsDir + "/apiserver.key", - "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", - "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - fmt.Sprintf("--secure-port=%d", 123), + "--secure-port=123", "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--enable-bootstrap-token-auth=true", "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", "--requestheader-username-headers=X-Remote-User", @@ -532,33 +429,44 @@ func TestGetAPIServerCommand(t *testing.T) { "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", "--authorization-mode=Node,RBAC", - "--advertise-address=2001:db8::1", - "--etcd-servers=http://127.0.0.1:2379,http://127.0.0.1:2380", + "--advertise-address=1.2.3.4", + "--etcd-servers=https://127.0.0.1:2379", + "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", + "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", + "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", + "--feature-gates=DynamicKubeletConfig=true", }, }, { + name: "test APIServerExtraArgs works as expected", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CAFile: "fuz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + FeatureGates: map[string]bool{features.DynamicKubeletConfig: true, features.Auditing: true}, + APIServerExtraArgs: map[string]string{ + "service-cluster-ip-range": "baz", + "advertise-address": "9.9.9.9", + "audit-policy-file": "/etc/config/audit.yaml", + "audit-log-path": "/var/log/kubernetes", + }, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", - "--service-cluster-ip-range=bar", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", + "--service-cluster-ip-range=baz", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", "--tls-cert-file=" + testCertsDir + "/apiserver.crt", "--tls-private-key-file=" + testCertsDir + "/apiserver.key", "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - fmt.Sprintf("--secure-port=%d", 123), + "--enable-bootstrap-token-auth=true", + "--secure-port=123", "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--enable-bootstrap-token-auth=true", "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", "--requestheader-username-headers=X-Remote-User", @@ -567,28 +475,32 @@ func TestGetAPIServerCommand(t *testing.T) { "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", "--authorization-mode=Node,RBAC", - "--advertise-address=2001:db8::1", + "--advertise-address=9.9.9.9", "--etcd-servers=https://127.0.0.1:2379", "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", + "--feature-gates=DynamicKubeletConfig=true", + "--audit-policy-file=/etc/config/audit.yaml", + "--audit-log-path=/var/log/kubernetes", + "--audit-log-maxage=2", }, }, { + name: "authorization-mode extra-args ABAC", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - FeatureGates: map[string]bool{features.HighAvailability: true, features.Auditing: true}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - AuditPolicyConfiguration: kubeadmapi.AuditPolicyConfiguration{ - LogMaxAge: utilpointer.Int32Ptr(0), + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + APIServerExtraArgs: map[string]string{ + "authorization-mode": authzmodes.ModeABAC, }, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -596,10 +508,10 @@ func TestGetAPIServerCommand(t *testing.T) { "--tls-private-key-file=" + testCertsDir + "/apiserver.key", "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - fmt.Sprintf("--secure-port=%d", 123), + "--enable-bootstrap-token-auth=true", + "--secure-port=123", "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--enable-bootstrap-token-auth=true", "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", "--requestheader-username-headers=X-Remote-User", @@ -607,30 +519,29 @@ func TestGetAPIServerCommand(t *testing.T) { "--requestheader-extra-headers-prefix=X-Remote-Extra-", "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=Node,RBAC", - "--advertise-address=2001:db8::1", + "--authorization-mode=Node,RBAC,ABAC", + "--advertise-address=1.2.3.4", "--etcd-servers=https://127.0.0.1:2379", "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", - fmt.Sprintf("--endpoint-reconciler-type=%s", reconcilers.LeaseEndpointReconcilerType), - "--audit-policy-file=/etc/kubernetes/audit/audit.yaml", - "--audit-log-path=/var/log/kubernetes/audit/audit.log", - "--audit-log-maxage=0", }, }, { + name: "insecure-port extra-args", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - CloudProvider: "gce", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + APIServerExtraArgs: map[string]string{ + "insecure-port": "1234", + }, }, expected: []string{ "kube-apiserver", - "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--insecure-port=1234", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -655,21 +566,23 @@ func TestGetAPIServerCommand(t *testing.T) { "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", - "--cloud-provider=gce", }, }, { + name: "authorization-mode extra-args Webhook", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - CloudProvider: "aws", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + APIServerExtraArgs: map[string]string{ + "authorization-mode": authzmodes.ModeWebhook, + }, }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--enable-admission-plugins=NodeRestriction", + "--disable-admission-plugins=PersistentVolumeLabel", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -688,33 +601,54 @@ func TestGetAPIServerCommand(t *testing.T) { "--requestheader-extra-headers-prefix=X-Remote-Extra-", "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=Node,RBAC", + "--authorization-mode=Node,RBAC,Webhook", "--advertise-address=1.2.3.4", "--etcd-servers=https://127.0.0.1:2379", "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", - "--cloud-provider=aws", }, }, } for _, rt := range tests { - actual := getAPIServerCommand(rt.cfg, version.MustParseSemantic(rt.cfg.KubernetesVersion)) - sort.Strings(actual) - sort.Strings(rt.expected) - if !reflect.DeepEqual(actual, rt.expected) { - t.Errorf("failed getAPIServerCommand:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) - } + t.Run(rt.name, func(t *testing.T) { + actual := getAPIServerCommand(rt.cfg) + sort.Strings(actual) + sort.Strings(rt.expected) + if !reflect.DeepEqual(actual, rt.expected) { + errorDiffArguments(t, rt.name, actual, rt.expected) + } + }) } } +func errorDiffArguments(t *testing.T, name string, actual, expected []string) { + expectedShort := removeCommon(expected, actual) + actualShort := removeCommon(actual, expected) + t.Errorf( + "[%s] failed getAPIServerCommand:\nexpected:\n%v\nsaw:\n%v"+ + "\nexpectedShort:\n%v\nsawShort:\n%v\n", + name, expected, actual, + expectedShort, actualShort) +} + +// removeCommon removes common items from left list +// makes compairing two cmdline (with lots of arguments) easier +func removeCommon(left, right []string) []string { + origSet := sets.NewString(left...) + origSet.Delete(right...) + return origSet.List() +} + func TestGetControllerManagerCommand(t *testing.T) { var tests = []struct { + name string cfg *kubeadmapi.MasterConfiguration expected []string }{ { + name: "custom certs dir", cfg: &kubeadmapi.MasterConfiguration{ CertificatesDir: testCertsDir, KubernetesVersion: "v1.7.0", @@ -733,8 +667,9 @@ func TestGetControllerManagerCommand(t *testing.T) { }, }, { + name: "custom cloudprovider", cfg: &kubeadmapi.MasterConfiguration{ - CloudProvider: "foo", + Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16"}, CertificatesDir: testCertsDir, KubernetesVersion: "v1.7.0", }, @@ -749,14 +684,18 @@ func TestGetControllerManagerCommand(t *testing.T) { "--cluster-signing-key-file=" + testCertsDir + "/ca.key", "--use-service-account-credentials=true", "--controllers=*,bootstrapsigner,tokencleaner", - "--cloud-provider=foo", + "--allocate-node-cidrs=true", + "--cluster-cidr=10.0.1.15/16", + "--node-cidr-mask-size=24", }, }, { + name: "custom extra-args", cfg: &kubeadmapi.MasterConfiguration{ - Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.7.0", + Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16"}, + ControllerManagerExtraArgs: map[string]string{"node-cidr-mask-size": "20"}, + CertificatesDir: testCertsDir, + KubernetesVersion: "v1.7.0", }, expected: []string{ "kube-controller-manager", @@ -771,10 +710,11 @@ func TestGetControllerManagerCommand(t *testing.T) { "--controllers=*,bootstrapsigner,tokencleaner", "--allocate-node-cidrs=true", "--cluster-cidr=10.0.1.15/16", - "--node-cidr-mask-size=24", + "--node-cidr-mask-size=20", }, }, { + name: "custom IPv6 networking", cfg: &kubeadmapi.MasterConfiguration{ Networking: kubeadmapi.Networking{PodSubnet: "2001:db8::/64"}, CertificatesDir: testCertsDir, @@ -803,7 +743,7 @@ func TestGetControllerManagerCommand(t *testing.T) { sort.Strings(actual) sort.Strings(rt.expected) if !reflect.DeepEqual(actual, rt.expected) { - t.Errorf("failed getControllerManagerCommand:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) + errorDiffArguments(t, rt.name, actual, rt.expected) } } } @@ -859,16 +799,21 @@ func TestCalcNodeCidrSize(t *testing.T) { podSubnet: "2001:db8::/95", expectedPrefix: "104", }, - { - name: "V6: Largest subnet currently supported", - podSubnet: "2001:db8::/66", - expectedPrefix: "80", - }, { name: "V6: For /64 pod net, use /80", podSubnet: "2001:db8::/64", expectedPrefix: "80", }, + { + name: "V6: For /48 pod net, use /64", + podSubnet: "2001:db8::/48", + expectedPrefix: "64", + }, + { + name: "V6: For /32 pod net, use /48", + podSubnet: "2001:db8::/32", + expectedPrefix: "48", + }, } for _, test := range tests { actualPrefix := calcNodeCidrSize(test.podSubnet) @@ -882,16 +827,18 @@ func TestCalcNodeCidrSize(t *testing.T) { func TestGetControllerManagerCommandExternalCA(t *testing.T) { tests := []struct { + name string cfg *kubeadmapi.MasterConfiguration caKeyPresent bool expectedArgFunc func(dir string) []string }{ { + name: "caKeyPresent-false", cfg: &kubeadmapi.MasterConfiguration{ KubernetesVersion: "v1.7.0", API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, }, caKeyPresent: false, expectedArgFunc: func(tmpdir string) []string { @@ -910,11 +857,12 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { }, }, { + name: "caKeyPresent true", cfg: &kubeadmapi.MasterConfiguration{ KubernetesVersion: "v1.7.0", API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "valid-hostname", + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"}, }, caKeyPresent: true, expectedArgFunc: func(tmpdir string) []string { @@ -944,10 +892,13 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { t.Errorf("failed creating pki assets: %v", err) } - // delete ca.key if test.caKeyPresent is false + // delete ca.key and front-proxy-ca.key if test.caKeyPresent is false if !test.caKeyPresent { - if err := os.Remove(filepath.Join(test.cfg.CertificatesDir, "ca.key")); err != nil { - t.Errorf("failed removing ca.key: %v", err) + if err := os.Remove(filepath.Join(test.cfg.CertificatesDir, kubeadmconstants.CAKeyName)); err != nil { + t.Errorf("failed removing %s: %v", kubeadmconstants.CAKeyName, err) + } + if err := os.Remove(filepath.Join(test.cfg.CertificatesDir, kubeadmconstants.FrontProxyCAKeyName)); err != nil { + t.Errorf("failed removing %s: %v", kubeadmconstants.FrontProxyCAKeyName, err) } } @@ -956,18 +907,20 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { sort.Strings(actual) sort.Strings(expected) if !reflect.DeepEqual(actual, expected) { - t.Errorf("failed getControllerManagerCommand:\nexpected:\n%v\nsaw:\n%v", expected, actual) + errorDiffArguments(t, test.name, actual, expected) } } } func TestGetSchedulerCommand(t *testing.T) { var tests = []struct { + name string cfg *kubeadmapi.MasterConfiguration expected []string }{ { - cfg: &kubeadmapi.MasterConfiguration{}, + name: "scheduler defaults", + cfg: &kubeadmapi.MasterConfiguration{}, expected: []string{ "kube-scheduler", "--address=127.0.0.1", @@ -982,79 +935,81 @@ func TestGetSchedulerCommand(t *testing.T) { sort.Strings(actual) sort.Strings(rt.expected) if !reflect.DeepEqual(actual, rt.expected) { - t.Errorf("failed getSchedulerCommand:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) + errorDiffArguments(t, rt.name, actual, rt.expected) } } } -func TestGetAuthzParameters(t *testing.T) { +func TestGetAuthzModes(t *testing.T) { var tests = []struct { + name string authMode []string - expected []string + expected string }{ { + name: "default if empty", authMode: []string{}, - expected: []string{ - "--authorization-mode=Node,RBAC", - }, + expected: "Node,RBAC", }, { - authMode: []string{"RBAC"}, - expected: []string{ - "--authorization-mode=RBAC", - }, + name: "add missing Node", + authMode: []string{authzmodes.ModeRBAC}, + expected: "Node,RBAC", }, { - authMode: []string{"AlwaysAllow"}, - expected: []string{ - "--authorization-mode=AlwaysAllow", - }, + name: "add missing RBAC", + authMode: []string{authzmodes.ModeNode}, + expected: "Node,RBAC", }, { - authMode: []string{"AlwaysDeny"}, - expected: []string{ - "--authorization-mode=AlwaysDeny", - }, + name: "add defaults to ABAC", + authMode: []string{authzmodes.ModeABAC}, + expected: "Node,RBAC,ABAC", }, { - authMode: []string{"ABAC"}, - expected: []string{ - "--authorization-mode=ABAC", - "--authorization-policy-file=/etc/kubernetes/abac_policy.json", - }, + name: "add defaults to RBAC+Webhook", + authMode: []string{authzmodes.ModeRBAC, authzmodes.ModeWebhook}, + expected: "Node,RBAC,Webhook", }, { - authMode: []string{"ABAC", "Webhook"}, - expected: []string{ - "--authorization-mode=ABAC,Webhook", - "--authorization-policy-file=/etc/kubernetes/abac_policy.json", - "--authorization-webhook-config-file=/etc/kubernetes/webhook_authz.conf", - }, + name: "add default to Webhook", + authMode: []string{authzmodes.ModeWebhook}, + expected: "Node,RBAC,Webhook", }, { - authMode: []string{"ABAC", "RBAC", "Webhook"}, - expected: []string{ - "--authorization-mode=ABAC,RBAC,Webhook", - "--authorization-policy-file=/etc/kubernetes/abac_policy.json", - "--authorization-webhook-config-file=/etc/kubernetes/webhook_authz.conf", - }, + name: "AlwaysAllow ignored", + authMode: []string{authzmodes.ModeAlwaysAllow}, + expected: "Node,RBAC", }, { - authMode: []string{"Node", "RBAC", "Webhook", "ABAC"}, - expected: []string{ - "--authorization-mode=Node,RBAC,Webhook,ABAC", - "--authorization-policy-file=/etc/kubernetes/abac_policy.json", - "--authorization-webhook-config-file=/etc/kubernetes/webhook_authz.conf", - }, + name: "AlwaysDeny ignored", + authMode: []string{authzmodes.ModeAlwaysDeny}, + expected: "Node,RBAC", + }, + { + name: "Unspecified ignored", + authMode: []string{"FooAuthzMode"}, + expected: "Node,RBAC", + }, + { + name: "Multiple ignored", + authMode: []string{authzmodes.ModeAlwaysAllow, authzmodes.ModeAlwaysDeny, "foo"}, + expected: "Node,RBAC", + }, + { + name: "all", + authMode: []string{authzmodes.ModeNode, authzmodes.ModeRBAC, authzmodes.ModeWebhook, authzmodes.ModeABAC}, + expected: "Node,RBAC,ABAC,Webhook", }, } for _, rt := range tests { - actual := getAuthzParameters(rt.authMode) - sort.Strings(actual) - sort.Strings(rt.expected) - if !reflect.DeepEqual(actual, rt.expected) { - t.Errorf("failed getAuthzParameters:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) - } + + t.Run(rt.name, func(t *testing.T) { + actual := getAuthzModes(strings.Join(rt.authMode, ",")) + if actual != rt.expected { + t.Errorf("failed getAuthzParameters:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/volumes.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/volumes.go index 02191d6b8..9237d2c10 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/volumes.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/volumes.go @@ -33,16 +33,14 @@ import ( const ( caCertsVolumeName = "ca-certs" caCertsVolumePath = "/etc/ssl/certs" - caCertsPkiVolumeName = "ca-certs-etc-pki" flexvolumeDirVolumeName = "flexvolume-dir" - cloudConfigVolumeName = "cloud-config" flexvolumeDirVolumePath = "/usr/libexec/kubernetes/kubelet-plugins/volume/exec" ) -// caCertsPkiVolumePath specifies the path that can be conditionally mounted into the apiserver and controller-manager containers -// as /etc/ssl/certs might be a symlink to it. It's a variable since it may be changed in unit testing. This var MUST NOT be changed -// in normal codepaths during runtime. -var caCertsPkiVolumePath = "/etc/pki" +// caCertsExtraVolumePaths specifies the paths that can be conditionally mounted into the apiserver and controller-manager containers +// as /etc/ssl/certs might be or contain a symlink to them. It's a variable since it may be changed in unit testing. This var MUST +// NOT be changed in normal codepaths during runtime. +var caCertsExtraVolumePaths = []string{"/etc/pki", "/usr/share/ca-certificates", "/usr/local/share/ca-certificates", "/etc/ca-certificates"} // getHostPathVolumesForTheControlPlane gets the required hostPath volumes and mounts for the control plane func getHostPathVolumesForTheControlPlane(cfg *kubeadmapi.MasterConfiguration) controlPlaneHostPathMounts { @@ -64,8 +62,8 @@ func getHostPathVolumesForTheControlPlane(cfg *kubeadmapi.MasterConfiguration) c mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, kubeadmconstants.KubeAuditPolicyLogVolumeName, cfg.AuditPolicyConfiguration.LogDir, kubeadmconstants.StaticPodAuditPolicyLogDir, false, &hostPathDirectoryOrCreate) } // If external etcd is specified, mount the directories needed for accessing the CA/serving certs and the private key - if len(cfg.Etcd.Endpoints) != 0 { - etcdVols, etcdVolMounts := getEtcdCertVolumes(cfg.Etcd, cfg.CertificatesDir) + if cfg.Etcd.External != nil { + etcdVols, etcdVolMounts := getEtcdCertVolumes(cfg.Etcd.External, cfg.CertificatesDir) mounts.AddHostPathMounts(kubeadmconstants.KubeAPIServer, etcdVols, etcdVolMounts) } @@ -78,13 +76,6 @@ func getHostPathVolumesForTheControlPlane(cfg *kubeadmapi.MasterConfiguration) c // Read-only mount for the controller manager kubeconfig file controllerManagerKubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName) mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeConfigVolumeName, controllerManagerKubeConfigFile, controllerManagerKubeConfigFile, true, &hostPathFileOrCreate) - // Read-only mount of the cloud config file if present - if cfg.CloudProvider != "" { - if _, err := os.Stat(DefaultCloudConfigPath); err == nil { - mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, cloudConfigVolumeName, DefaultCloudConfigPath, DefaultCloudConfigPath, true, &hostPathFileOrCreate) - mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, cloudConfigVolumeName, DefaultCloudConfigPath, DefaultCloudConfigPath, true, &hostPathFileOrCreate) - } - } // Mount for the flexvolume directory (/usr/libexec/kubernetes/kubelet-plugins/volume/exec) directory // Flexvolume dir must NOT be readonly as it is used for third-party plugins to integrate with their storage backends via unix domain socket. if stat, err := os.Stat(flexvolumeDirVolumePath); err == nil && stat.IsDir() { @@ -96,18 +87,21 @@ func getHostPathVolumesForTheControlPlane(cfg *kubeadmapi.MasterConfiguration) c schedulerKubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName) mounts.NewHostPathMount(kubeadmconstants.KubeScheduler, kubeadmconstants.KubeConfigVolumeName, schedulerKubeConfigFile, schedulerKubeConfigFile, true, &hostPathFileOrCreate) - // On some systems were we host-mount /etc/ssl/certs, it is also required to mount /etc/pki. This is needed - // due to symlinks pointing from files in /etc/ssl/certs into /etc/pki/ - if isPkiVolumeMountNeeded() { - mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, caCertsPkiVolumeName, caCertsPkiVolumePath, caCertsPkiVolumePath, true, &hostPathDirectoryOrCreate) - mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, caCertsPkiVolumeName, caCertsPkiVolumePath, caCertsPkiVolumePath, true, &hostPathDirectoryOrCreate) + // On some systems were we host-mount /etc/ssl/certs, it is also required to mount additional directories. + // This is needed due to symlinks pointing from files in /etc/ssl/certs to these directories. + for _, caCertsExtraVolumePath := range caCertsExtraVolumePaths { + if isExtraVolumeMountNeeded(caCertsExtraVolumePath) { + caCertsExtraVolumeName := strings.Replace(caCertsExtraVolumePath, "/", "-", -1)[1:] + mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, caCertsExtraVolumeName, caCertsExtraVolumePath, caCertsExtraVolumePath, true, &hostPathDirectoryOrCreate) + mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, caCertsExtraVolumeName, caCertsExtraVolumePath, caCertsExtraVolumePath, true, &hostPathDirectoryOrCreate) + } } // Merge user defined mounts and ensure unique volume and volume mount // names - mounts.AddExtraHostPathMounts(kubeadmconstants.KubeAPIServer, cfg.APIServerExtraVolumes, true, &hostPathDirectoryOrCreate) - mounts.AddExtraHostPathMounts(kubeadmconstants.KubeControllerManager, cfg.ControllerManagerExtraVolumes, true, &hostPathDirectoryOrCreate) - mounts.AddExtraHostPathMounts(kubeadmconstants.KubeScheduler, cfg.SchedulerExtraVolumes, true, &hostPathDirectoryOrCreate) + mounts.AddExtraHostPathMounts(kubeadmconstants.KubeAPIServer, cfg.APIServerExtraVolumes) + mounts.AddExtraHostPathMounts(kubeadmconstants.KubeControllerManager, cfg.ControllerManagerExtraVolumes) + mounts.AddExtraHostPathMounts(kubeadmconstants.KubeScheduler, cfg.SchedulerExtraVolumes) return mounts } @@ -153,10 +147,11 @@ func (c *controlPlaneHostPathMounts) AddHostPathMounts(component string, vols [] // AddExtraHostPathMounts adds host path mounts and overwrites the default // paths in the case that a user specifies the same volume/volume mount name. -func (c *controlPlaneHostPathMounts) AddExtraHostPathMounts(component string, extraVols []kubeadmapi.HostPathMount, readOnly bool, hostPathType *v1.HostPathType) { +func (c *controlPlaneHostPathMounts) AddExtraHostPathMounts(component string, extraVols []kubeadmapi.HostPathMount) { for _, extraVol := range extraVols { fmt.Printf("[controlplane] Adding extra host path mount %q to %q\n", extraVol.Name, component) - c.NewHostPathMount(component, extraVol.Name, extraVol.HostPath, extraVol.MountPath, readOnly, hostPathType) + hostPathType := extraVol.PathType + c.NewHostPathMount(component, extraVol.Name, extraVol.HostPath, extraVol.MountPath, !extraVol.Writable, &hostPathType) } } @@ -183,7 +178,7 @@ func (c *controlPlaneHostPathMounts) addComponentVolumeMount(component string, v } // getEtcdCertVolumes returns the volumes/volumemounts needed for talking to an external etcd cluster -func getEtcdCertVolumes(etcdCfg kubeadmapi.Etcd, k8sCertificatesDir string) ([]v1.Volume, []v1.VolumeMount) { +func getEtcdCertVolumes(etcdCfg *kubeadmapi.ExternalEtcd, k8sCertificatesDir string) ([]v1.Volume, []v1.VolumeMount) { certPaths := []string{etcdCfg.CAFile, etcdCfg.CertFile, etcdCfg.KeyFile} certDirs := sets.NewString() for _, certPath := range certPaths { @@ -191,7 +186,14 @@ func getEtcdCertVolumes(etcdCfg kubeadmapi.Etcd, k8sCertificatesDir string) ([]v // Ignore ".", which is the result of passing an empty path. // Also ignore the cert directories that already may be mounted; /etc/ssl/certs, /etc/pki or Kubernetes CertificatesDir // If the etcd certs are in there, it's okay, we don't have to do anything - if certDir == "." || strings.HasPrefix(certDir, caCertsVolumePath) || strings.HasPrefix(certDir, caCertsPkiVolumePath) || strings.HasPrefix(certDir, k8sCertificatesDir) { + extraVolumePath := false + for _, caCertsExtraVolumePath := range caCertsExtraVolumePaths { + if strings.HasPrefix(certDir, caCertsExtraVolumePath) { + extraVolumePath = true + break + } + } + if certDir == "." || extraVolumePath || strings.HasPrefix(certDir, caCertsVolumePath) || strings.HasPrefix(certDir, k8sCertificatesDir) { continue } // Filter out any existing hostpath mounts in the list that contains a subset of the path @@ -222,11 +224,11 @@ func getEtcdCertVolumes(etcdCfg kubeadmapi.Etcd, k8sCertificatesDir string) ([]v return volumes, volumeMounts } -// isPkiVolumeMountNeeded specifies whether /etc/pki should be host-mounted into the containers +// isExtraVolumeMountNeeded specifies whether /etc/pki should be host-mounted into the containers // On some systems were we host-mount /etc/ssl/certs, it is also required to mount /etc/pki. This is needed // due to symlinks pointing from files in /etc/ssl/certs into /etc/pki/ -func isPkiVolumeMountNeeded() bool { - if _, err := os.Stat(caCertsPkiVolumePath); err == nil { +func isExtraVolumeMountNeeded(caCertsExtraVolumePath string) bool { + if _, err := os.Stat(caCertsExtraVolumePath); err == nil { return true } return false diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/volumes_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/volumes_test.go index febd2c429..492dc16ab 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/volumes_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/volumes_test.go @@ -234,7 +234,7 @@ func TestGetEtcdCertVolumes(t *testing.T) { } for _, rt := range tests { - actualVol, actualVolMount := getEtcdCertVolumes(kubeadmapi.Etcd{ + actualVol, actualVolMount := getEtcdCertVolumes(&kubeadmapi.ExternalEtcd{ CAFile: rt.ca, CertFile: rt.cert, KeyFile: rt.key, @@ -525,10 +525,12 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { cfg: &kubeadmapi.MasterConfiguration{ CertificatesDir: testCertsDir, Etcd: kubeadmapi.Etcd{ - Endpoints: []string{"foo"}, - CAFile: "/etc/certs/etcd/my-etcd-ca.crt", - CertFile: testCertsDir + "/etcd/my-etcd.crt", - KeyFile: "/var/lib/etcd/certs/my-etcd.key", + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"foo"}, + CAFile: "/etc/certs/etcd/my-etcd-ca.crt", + CertFile: testCertsDir + "/etcd/my-etcd.crt", + KeyFile: "/var/lib/etcd/certs/my-etcd.key", + }, }, }, vol: volMap2, @@ -542,9 +544,9 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { } defer os.RemoveAll(tmpdir) - // set up tmp caCertsPkiVolumePath for testing - caCertsPkiVolumePath = fmt.Sprintf("%s/etc/pki", tmpdir) - defer func() { caCertsPkiVolumePath = "/etc/pki" }() + // set up tmp caCertsExtraVolumePaths for testing + caCertsExtraVolumePaths = []string{fmt.Sprintf("%s/etc/pki", tmpdir), fmt.Sprintf("%s/usr/share/ca-certificates", tmpdir)} + defer func() { caCertsExtraVolumePaths = []string{"/etc/pki", "/usr/share/ca-certificates"} }() for _, rt := range tests { mounts := getHostPathVolumesForTheControlPlane(rt.cfg) @@ -556,9 +558,6 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) { if _, ok := mounts.volumeMounts[kubeadmconstants.KubeControllerManager][flexvolumeDirVolumeName]; ok { delete(mounts.volumeMounts[kubeadmconstants.KubeControllerManager], flexvolumeDirVolumeName) } - if _, ok := mounts.volumeMounts[kubeadmconstants.KubeControllerManager][cloudConfigVolumeName]; ok { - delete(mounts.volumeMounts[kubeadmconstants.KubeControllerManager], cloudConfigVolumeName) - } if !reflect.DeepEqual(mounts.volumes, rt.vol) { t.Errorf( "failed getHostPathVolumesForTheControlPlane:\n\texpected: %v\n\t actual: %v", @@ -615,30 +614,62 @@ func TestAddExtraHostPathMounts(t *testing.T) { mounts.AddHostPathMounts("component", vols, volMounts) hostPathMounts := []kubeadmapi.HostPathMount{ { - Name: "foo", - HostPath: "/tmp/qux", - MountPath: "/tmp/qux", + Name: "foo-0", + HostPath: "/tmp/qux-0", + MountPath: "/tmp/qux-0", + Writable: false, + PathType: v1.HostPathFile, }, - } - mounts.AddExtraHostPathMounts("component", hostPathMounts, true, &hostPathDirectoryOrCreate) - if _, ok := mounts.volumes["component"]["foo"]; !ok { - t.Errorf("Expected to find volume %q", "foo") - } - vol, _ := mounts.volumes["component"]["foo"] - if vol.Name != "foo" { - t.Errorf("Expected volume name %q", "foo") - } - if vol.HostPath.Path != "/tmp/qux" { - t.Errorf("Expected host path %q", "/tmp/qux") - } - if _, ok := mounts.volumeMounts["component"]["foo"]; !ok { - t.Errorf("Expected to find volume mount %q", "foo") - } - volMount, _ := mounts.volumeMounts["component"]["foo"] - if volMount.Name != "foo" { - t.Errorf("Expected volume mount name %q", "foo") - } - if volMount.MountPath != "/tmp/qux" { - t.Errorf("Expected container path %q", "/tmp/qux") + { + Name: "bar-0", + HostPath: "/tmp/asd-0", + MountPath: "/tmp/asd-0", + Writable: true, + PathType: v1.HostPathDirectory, + }, + { + Name: "foo-1", + HostPath: "/tmp/qux-1", + MountPath: "/tmp/qux-1", + Writable: false, + PathType: v1.HostPathFileOrCreate, + }, + { + Name: "bar-1", + HostPath: "/tmp/asd-1", + MountPath: "/tmp/asd-1", + Writable: true, + PathType: v1.HostPathDirectoryOrCreate, + }, + } + mounts.AddExtraHostPathMounts("component", hostPathMounts) + for _, hostMount := range hostPathMounts { + volumeName := hostMount.Name + if _, ok := mounts.volumes["component"][volumeName]; !ok { + t.Errorf("Expected to find volume %q", volumeName) + } + vol := mounts.volumes["component"][volumeName] + if vol.Name != volumeName { + t.Errorf("Expected volume name %q", volumeName) + } + if vol.HostPath.Path != hostMount.HostPath { + t.Errorf("Expected host path %q", hostMount.HostPath) + } + if _, ok := mounts.volumeMounts["component"][volumeName]; !ok { + t.Errorf("Expected to find volume mount %q", volumeName) + } + if *vol.HostPath.Type != v1.HostPathType(hostMount.PathType) { + t.Errorf("Expected to host path type %q", hostMount.PathType) + } + volMount, _ := mounts.volumeMounts["component"][volumeName] + if volMount.Name != volumeName { + t.Errorf("Expected volume mount name %q", volumeName) + } + if volMount.MountPath != hostMount.MountPath { + t.Errorf("Expected container path %q", hostMount.MountPath) + } + if volMount.ReadOnly != !hostMount.Writable { + t.Errorf("Expected volume writable setting %t", hostMount.Writable) + } } } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/BUILD index 8c1f83b02..361f8dab3 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/BUILD @@ -27,6 +27,7 @@ go_library( "//cmd/kubeadm/app/images:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/staticpod:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", ], ) @@ -40,9 +41,6 @@ filegroup( filegroup( name = "all-srcs", - srcs = [ - ":package-srcs", - "//cmd/kubeadm/app/phases/etcd/spec:all-srcs", - ], + srcs = [":package-srcs"], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/local.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/local.go index d12682cd7..5240d3357 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/local.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/local.go @@ -20,6 +20,8 @@ import ( "fmt" "path/filepath" + "github.com/golang/glog" + "k8s.io/api/core/v1" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -35,7 +37,7 @@ const ( // CreateLocalEtcdStaticPodManifestFile will write local etcd static pod manifest file. func CreateLocalEtcdStaticPodManifestFile(manifestDir string, cfg *kubeadmapi.MasterConfiguration) error { - + glog.V(1).Infoln("creating local etcd static pod manifest file") // gets etcd StaticPodSpec, actualized for the current MasterConfiguration spec := GetEtcdPodSpec(cfg) // writes etcd StaticPod to disk @@ -52,17 +54,17 @@ func CreateLocalEtcdStaticPodManifestFile(manifestDir string, cfg *kubeadmapi.Ma func GetEtcdPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.Pod { pathType := v1.HostPathDirectoryOrCreate etcdMounts := map[string]v1.Volume{ - etcdVolumeName: staticpodutil.NewVolume(etcdVolumeName, cfg.Etcd.DataDir, &pathType), + etcdVolumeName: staticpodutil.NewVolume(etcdVolumeName, cfg.Etcd.Local.DataDir, &pathType), certsVolumeName: staticpodutil.NewVolume(certsVolumeName, cfg.CertificatesDir+"/etcd", &pathType), } return staticpodutil.ComponentPod(v1.Container{ Name: kubeadmconstants.Etcd, Command: getEtcdCommand(cfg), - Image: images.GetCoreImage(kubeadmconstants.Etcd, cfg.ImageRepository, cfg.KubernetesVersion, cfg.Etcd.Image), - ImagePullPolicy: cfg.ImagePullPolicy, + Image: images.GetCoreImage(kubeadmconstants.Etcd, cfg.ImageRepository, cfg.KubernetesVersion, cfg.Etcd.Local.Image), + ImagePullPolicy: v1.PullIfNotPresent, // Mount the etcd datadir path read-write so etcd can store data in a more persistent manner VolumeMounts: []v1.VolumeMount{ - staticpodutil.NewVolumeMount(etcdVolumeName, cfg.Etcd.DataDir, false), + staticpodutil.NewVolumeMount(etcdVolumeName, cfg.Etcd.Local.DataDir, false), staticpodutil.NewVolumeMount(certsVolumeName, cfg.CertificatesDir+"/etcd", false), }, LivenessProbe: staticpodutil.EtcdProbe( @@ -75,20 +77,25 @@ func GetEtcdPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.Pod { // getEtcdCommand builds the right etcd command from the given config object func getEtcdCommand(cfg *kubeadmapi.MasterConfiguration) []string { defaultArguments := map[string]string{ - "listen-client-urls": "https://127.0.0.1:2379", - "advertise-client-urls": "https://127.0.0.1:2379", - "data-dir": cfg.Etcd.DataDir, - "cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerCertName), - "key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerKeyName), - "trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), - "client-cert-auth": "true", - "peer-cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerCertName), - "peer-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerKeyName), - "peer-trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), - "peer-client-cert-auth": "true", + "name": cfg.GetNodeName(), + "listen-client-urls": "https://127.0.0.1:2379", + "advertise-client-urls": "https://127.0.0.1:2379", + "listen-peer-urls": "https://127.0.0.1:2380", + "initial-advertise-peer-urls": "https://127.0.0.1:2380", + "data-dir": cfg.Etcd.Local.DataDir, + "cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerCertName), + "key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerKeyName), + "trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), + "client-cert-auth": "true", + "peer-cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerCertName), + "peer-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerKeyName), + "peer-trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), + "peer-client-cert-auth": "true", + "snapshot-count": "10000", + "initial-cluster": fmt.Sprintf("%s=https://127.0.0.1:2380", cfg.GetNodeName()), } command := []string{"etcd"} - command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.Etcd.ExtraArgs)...) + command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.Etcd.Local.ExtraArgs)...) return command } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/local_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/local_test.go index 6bd13e999..83f5f45ad 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/local_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/local_test.go @@ -34,6 +34,12 @@ func TestGetEtcdPodSpec(t *testing.T) { // Creates a Master Configuration cfg := &kubeadmapi.MasterConfiguration{ KubernetesVersion: "v1.7.0", + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + DataDir: "/var/lib/etcd", + Image: "", + }, + }, } // Executes GetEtcdPodSpec @@ -54,6 +60,12 @@ func TestCreateLocalEtcdStaticPodManifestFile(t *testing.T) { // Creates a Master Configuration cfg := &kubeadmapi.MasterConfiguration{ KubernetesVersion: "v1.7.0", + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + DataDir: "/var/lib/etcd", + Image: "k8s.gcr.io/etcd", + }, + }, } // Execute createStaticPodFunction @@ -75,12 +87,22 @@ func TestGetEtcdCommand(t *testing.T) { }{ { cfg: &kubeadmapi.MasterConfiguration{ - Etcd: kubeadmapi.Etcd{DataDir: "/var/lib/etcd"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "foo", + }, + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + DataDir: "/var/lib/etcd", + }, + }, }, expected: []string{ "etcd", + "--name=foo", "--listen-client-urls=https://127.0.0.1:2379", "--advertise-client-urls=https://127.0.0.1:2379", + "--listen-peer-urls=https://127.0.0.1:2380", + "--initial-advertise-peer-urls=https://127.0.0.1:2380", "--data-dir=/var/lib/etcd", "--cert-file=" + kubeadmconstants.EtcdServerCertName, "--key-file=" + kubeadmconstants.EtcdServerKeyName, @@ -89,23 +111,33 @@ func TestGetEtcdCommand(t *testing.T) { "--peer-cert-file=" + kubeadmconstants.EtcdPeerCertName, "--peer-key-file=" + kubeadmconstants.EtcdPeerKeyName, "--peer-trusted-ca-file=" + kubeadmconstants.EtcdCACertName, + "--snapshot-count=10000", "--peer-client-cert-auth=true", + "--initial-cluster=foo=https://127.0.0.1:2380", }, }, { cfg: &kubeadmapi.MasterConfiguration{ + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "bar", + }, Etcd: kubeadmapi.Etcd{ - DataDir: "/var/lib/etcd", - ExtraArgs: map[string]string{ - "listen-client-urls": "https://10.0.1.10:2379", - "advertise-client-urls": "https://10.0.1.10:2379", + Local: &kubeadmapi.LocalEtcd{ + DataDir: "/var/lib/etcd", + ExtraArgs: map[string]string{ + "listen-client-urls": "https://10.0.1.10:2379", + "advertise-client-urls": "https://10.0.1.10:2379", + }, }, }, }, expected: []string{ "etcd", + "--name=bar", "--listen-client-urls=https://10.0.1.10:2379", "--advertise-client-urls=https://10.0.1.10:2379", + "--listen-peer-urls=https://127.0.0.1:2380", + "--initial-advertise-peer-urls=https://127.0.0.1:2380", "--data-dir=/var/lib/etcd", "--cert-file=" + kubeadmconstants.EtcdServerCertName, "--key-file=" + kubeadmconstants.EtcdServerKeyName, @@ -114,17 +146,29 @@ func TestGetEtcdCommand(t *testing.T) { "--peer-cert-file=" + kubeadmconstants.EtcdPeerCertName, "--peer-key-file=" + kubeadmconstants.EtcdPeerKeyName, "--peer-trusted-ca-file=" + kubeadmconstants.EtcdCACertName, + "--snapshot-count=10000", "--peer-client-cert-auth=true", + "--initial-cluster=bar=https://127.0.0.1:2380", }, }, { cfg: &kubeadmapi.MasterConfiguration{ - Etcd: kubeadmapi.Etcd{DataDir: "/etc/foo"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "wombat", + }, + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + DataDir: "/etc/foo", + }, + }, }, expected: []string{ "etcd", + "--name=wombat", "--listen-client-urls=https://127.0.0.1:2379", "--advertise-client-urls=https://127.0.0.1:2379", + "--listen-peer-urls=https://127.0.0.1:2380", + "--initial-advertise-peer-urls=https://127.0.0.1:2380", "--data-dir=/etc/foo", "--cert-file=" + kubeadmconstants.EtcdServerCertName, "--key-file=" + kubeadmconstants.EtcdServerKeyName, @@ -133,7 +177,9 @@ func TestGetEtcdCommand(t *testing.T) { "--peer-cert-file=" + kubeadmconstants.EtcdPeerCertName, "--peer-key-file=" + kubeadmconstants.EtcdPeerKeyName, "--peer-trusted-ca-file=" + kubeadmconstants.EtcdCACertName, + "--snapshot-count=10000", "--peer-client-cert-auth=true", + "--initial-cluster=wombat=https://127.0.0.1:2380", }, }, } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/BUILD deleted file mode 100644 index 8c65b8b71..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "spec.go", - "zz_generated.deepcopy.go", - ], - importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/doc.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/doc.go deleted file mode 100644 index a91c65d7d..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -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. -*/ - -// +k8s:deepcopy-gen=package - -package spec diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/spec.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/spec.go deleted file mode 100644 index 622075478..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/spec.go +++ /dev/null @@ -1,205 +0,0 @@ -/* -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. -*/ - -// This file was collated from types used in: -// https://github.com/coreos/etcd-operator/tree/e7f18696bbdc127fa028a99ca8166a8519749328/pkg/apis/etcd/v1beta2. -// When kubeadm moves to its own repo and controls its own dependencies, -// this file will be no longer be needed. - -package spec - -import ( - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -const ( - // CRDResourceKind is the CRD resource kind - CRDResourceKind = "EtcdCluster" - // CRDResourcePlural is the CRD resource plural - CRDResourcePlural = "etcdclusters" - groupName = "etcd.database.coreos.com" -) - -var ( - // SchemeBuilder is a scheme builder - SchemeBuilder = runtime.NewSchemeBuilder(AddKnownTypes) - // AddToScheme adds to the scheme - AddToScheme = SchemeBuilder.AddToScheme - // SchemeGroupVersion is the scheme version - SchemeGroupVersion = schema.GroupVersion{Group: groupName, Version: "v1beta2"} - // CRDName is the name of the CRD - CRDName = CRDResourcePlural + "." + groupName -) - -// Resource gets an EtcdCluster GroupResource for a specified resource -func Resource(resource string) schema.GroupResource { - return SchemeGroupVersion.WithResource(resource).GroupResource() -} - -// AddKnownTypes adds the set of types defined in this package to the supplied scheme. -func AddKnownTypes(s *runtime.Scheme) error { - s.AddKnownTypes(SchemeGroupVersion, - &EtcdCluster{}, - &EtcdClusterList{}, - ) - metav1.AddToGroupVersion(s, SchemeGroupVersion) - return nil -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// EtcdClusterList is a list of etcd clusters. -type EtcdClusterList struct { - metav1.TypeMeta `json:",inline"` - // Standard list metadata - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - metav1.ListMeta `json:"metadata,omitempty"` - Items []EtcdCluster `json:"items"` -} - -// +genclient -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// EtcdCluster represents an etcd cluster -type EtcdCluster struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ClusterSpec `json:"spec"` -} - -// ClusterSpec represents a cluster spec -type ClusterSpec struct { - // Size is the expected size of the etcd cluster. - // The etcd-operator will eventually make the size of the running - // cluster equal to the expected size. - // The vaild range of the size is from 1 to 7. - Size int `json:"size"` - - // BaseImage is the base etcd image name that will be used to launch - // etcd clusters. This is useful for private registries, etc. - // - // If image is not set, default is quay.io/coreos/etcd - BaseImage string `json:"baseImage"` - - // Version is the expected version of the etcd cluster. - // The etcd-operator will eventually make the etcd cluster version - // equal to the expected version. - // - // The version must follow the [semver]( http://semver.org) format, for example "3.1.8". - // Only etcd released versions are supported: https://github.com/coreos/etcd/releases - // - // If version is not set, default is "3.1.8". - Version string `json:"version,omitempty"` - - // Paused is to pause the control of the operator for the etcd cluster. - Paused bool `json:"paused,omitempty"` - - // Pod defines the policy to create pod for the etcd pod. - // - // Updating Pod does not take effect on any existing etcd pods. - Pod *PodPolicy `json:"pod,omitempty"` - - // SelfHosted determines if the etcd cluster is used for a self-hosted - // Kubernetes cluster. - // - // SelfHosted is a cluster initialization configuration. It cannot be updated. - SelfHosted *SelfHostedPolicy `json:"selfHosted,omitempty"` - - // etcd cluster TLS configuration - TLS *TLSPolicy `json:"TLS,omitempty"` -} - -// PodPolicy defines the policy to create pod for the etcd container. -type PodPolicy struct { - // Labels specifies the labels to attach to pods the operator creates for the - // etcd cluster. - // "app" and "etcd_*" labels are reserved for the internal use of the etcd operator. - // Do not overwrite them. - Labels map[string]string `json:"labels,omitempty"` - - // NodeSelector specifies a map of key-value pairs. For the pod to be eligible - // to run on a node, the node must have each of the indicated key-value pairs as - // labels. - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - - // AntiAffinity determines if the etcd-operator tries to avoid putting - // the etcd members in the same cluster onto the same node. - AntiAffinity bool `json:"antiAffinity,omitempty"` - - // Resources is the resource requirements for the etcd container. - // This field cannot be updated once the cluster is created. - Resources v1.ResourceRequirements `json:"resources,omitempty"` - - // Tolerations specifies the pod's tolerations. - Tolerations []v1.Toleration `json:"tolerations,omitempty"` - - // List of environment variables to set in the etcd container. - // This is used to configure etcd process. etcd cluster cannot be created, when - // bad environement variables are provided. Do not overwrite any flags used to - // bootstrap the cluster (for example `--initial-cluster` flag). - // This field cannot be updated. - EtcdEnv []v1.EnvVar `json:"etcdEnv,omitempty"` - - // By default, kubernetes will mount a service account token into the etcd pods. - // AutomountServiceAccountToken indicates whether pods running with the service account should have an API token automatically mounted. - AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty"` -} - -// TLSPolicy defines the TLS policy of an etcd cluster -type TLSPolicy struct { - // StaticTLS enables user to generate static x509 certificates and keys, - // put them into Kubernetes secrets, and specify them into here. - Static *StaticTLS `json:"static,omitempty"` -} - -// StaticTLS represents static TLS -type StaticTLS struct { - // Member contains secrets containing TLS certs used by each etcd member pod. - Member *MemberSecret `json:"member,omitempty"` - // OperatorSecret is the secret containing TLS certs used by operator to - // talk securely to this cluster. - OperatorSecret string `json:"operatorSecret,omitempty"` -} - -// MemberSecret represents a member secret -type MemberSecret struct { - // PeerSecret is the secret containing TLS certs used by each etcd member pod - // for the communication between etcd peers. - PeerSecret string `json:"peerSecret,omitempty"` - // ServerSecret is the secret containing TLS certs used by each etcd member pod - // for the communication between etcd server and its clients. - ServerSecret string `json:"serverSecret,omitempty"` -} - -// SelfHostedPolicy represents a self-hosted policy -type SelfHostedPolicy struct { - // BootMemberClientEndpoint specifies a bootstrap member for the cluster. - // If there is no bootstrap member, a completely new cluster will be created. - // The boot member will be removed from the cluster once the self-hosted cluster - // setup successfully. - BootMemberClientEndpoint string `json:"bootMemberClientEndpoint,omitempty"` - - // SkipBootMemberRemoval specifies whether the removal of the bootstrap member - // should be skipped. By default the operator will automatically remove the - // bootstrap member from the new cluster - this happens during the pivot - // procedure and is the first step of decommissioning the bootstrap member. - // If unspecified, the default is `false`. If set to `true`, you are - // expected to remove the boot member yourself from the etcd cluster. - SkipBootMemberRemoval bool `json:"skipBootMemberRemoval,omitempty"` -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/zz_generated.deepcopy.go deleted file mode 100644 index 92c4ce4f4..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd/spec/zz_generated.deepcopy.go +++ /dev/null @@ -1,265 +0,0 @@ -// +build !ignore_autogenerated - -/* -Copyright 2018 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. -*/ - -// Code generated by deepcopy-gen. DO NOT EDIT. - -package spec - -import ( - v1 "k8s.io/api/core/v1" - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) { - *out = *in - if in.Pod != nil { - in, out := &in.Pod, &out.Pod - if *in == nil { - *out = nil - } else { - *out = new(PodPolicy) - (*in).DeepCopyInto(*out) - } - } - if in.SelfHosted != nil { - in, out := &in.SelfHosted, &out.SelfHosted - if *in == nil { - *out = nil - } else { - *out = new(SelfHostedPolicy) - **out = **in - } - } - if in.TLS != nil { - in, out := &in.TLS, &out.TLS - if *in == nil { - *out = nil - } else { - *out = new(TLSPolicy) - (*in).DeepCopyInto(*out) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSpec. -func (in *ClusterSpec) DeepCopy() *ClusterSpec { - if in == nil { - return nil - } - out := new(ClusterSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EtcdCluster) DeepCopyInto(out *EtcdCluster) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdCluster. -func (in *EtcdCluster) DeepCopy() *EtcdCluster { - if in == nil { - return nil - } - out := new(EtcdCluster) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *EtcdCluster) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EtcdClusterList) DeepCopyInto(out *EtcdClusterList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]EtcdCluster, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterList. -func (in *EtcdClusterList) DeepCopy() *EtcdClusterList { - if in == nil { - return nil - } - out := new(EtcdClusterList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *EtcdClusterList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MemberSecret) DeepCopyInto(out *MemberSecret) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemberSecret. -func (in *MemberSecret) DeepCopy() *MemberSecret { - if in == nil { - return nil - } - out := new(MemberSecret) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PodPolicy) DeepCopyInto(out *PodPolicy) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.NodeSelector != nil { - in, out := &in.NodeSelector, &out.NodeSelector - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - in.Resources.DeepCopyInto(&out.Resources) - if in.Tolerations != nil { - in, out := &in.Tolerations, &out.Tolerations - *out = make([]v1.Toleration, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.EtcdEnv != nil { - in, out := &in.EtcdEnv, &out.EtcdEnv - *out = make([]v1.EnvVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.AutomountServiceAccountToken != nil { - in, out := &in.AutomountServiceAccountToken, &out.AutomountServiceAccountToken - if *in == nil { - *out = nil - } else { - *out = new(bool) - **out = **in - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodPolicy. -func (in *PodPolicy) DeepCopy() *PodPolicy { - if in == nil { - return nil - } - out := new(PodPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SelfHostedPolicy) DeepCopyInto(out *SelfHostedPolicy) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SelfHostedPolicy. -func (in *SelfHostedPolicy) DeepCopy() *SelfHostedPolicy { - if in == nil { - return nil - } - out := new(SelfHostedPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *StaticTLS) DeepCopyInto(out *StaticTLS) { - *out = *in - if in.Member != nil { - in, out := &in.Member, &out.Member - if *in == nil { - *out = nil - } else { - *out = new(MemberSecret) - **out = **in - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StaticTLS. -func (in *StaticTLS) DeepCopy() *StaticTLS { - if in == nil { - return nil - } - out := new(StaticTLS) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TLSPolicy) DeepCopyInto(out *TLSPolicy) { - *out = *in - if in.Static != nil { - in, out := &in.Static, &out.Static - if *in == nil { - *out = nil - } else { - *out = new(StaticTLS) - (*in).DeepCopyInto(*out) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSPolicy. -func (in *TLSPolicy) DeepCopy() *TLSPolicy { - if in == nil { - return nil - } - out := new(TLSPolicy) - in.DeepCopyInto(out) - return out -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/BUILD index e9664603d..1c8281b5e 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/BUILD @@ -2,42 +2,55 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", - srcs = ["kubelet.go"], + srcs = [ + "config.go", + "dynamic.go", + "flags.go", + ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet", visibility = ["//visibility:public"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//cmd/kubeadm/app/util/kubeconfig:go_default_library", "//pkg/apis/rbac/v1:go_default_library", "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", + "//pkg/util/node:go_default_library", + "//pkg/util/procfs:go_default_library", + "//pkg/util/version:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", ], ) go_test( name = "go_default_test", - srcs = ["kubelet_test.go"], + srcs = [ + "config_test.go", + "dynamic_test.go", + "flags_test.go", + ], embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/constants:go_default_library", + "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", + "//pkg/util/version:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/config.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/config.go new file mode 100644 index 000000000..2f09b5347 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/config.go @@ -0,0 +1,180 @@ +/* +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 kubelet + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "k8s.io/api/core/v1" + rbac "k8s.io/api/rbac/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clientset "k8s.io/client-go/kubernetes" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" + rbachelper "k8s.io/kubernetes/pkg/apis/rbac/v1" + kubeletconfigscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + "k8s.io/kubernetes/pkg/util/version" +) + +// WriteConfigToDisk writes the kubelet config object down to a file +// Used at "kubeadm init" and "kubeadm upgrade" time +func WriteConfigToDisk(kubeletConfig *kubeletconfigv1beta1.KubeletConfiguration, kubeletDir string) error { + + kubeletBytes, err := getConfigBytes(kubeletConfig) + if err != nil { + return err + } + return writeConfigBytesToDisk(kubeletBytes, kubeletDir) +} + +// CreateConfigMap creates a ConfigMap with the generic kubelet configuration. +// Used at "kubeadm init" and "kubeadm upgrade" time +func CreateConfigMap(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { + + k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion) + if err != nil { + return err + } + + configMapName := configMapName(k8sVersion) + fmt.Printf("[kubelet] Creating a ConfigMap %q in namespace %s with the configuration for the kubelets in the cluster\n", configMapName, metav1.NamespaceSystem) + + kubeletBytes, err := getConfigBytes(cfg.KubeletConfiguration.BaseConfig) + if err != nil { + return err + } + + if err := apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: configMapName, + Namespace: metav1.NamespaceSystem, + }, + Data: map[string]string{ + kubeadmconstants.KubeletBaseConfigurationConfigMapKey: string(kubeletBytes), + }, + }); err != nil { + return err + } + + if err := createConfigMapRBACRules(client, k8sVersion); err != nil { + return fmt.Errorf("error creating kubelet configuration configmap RBAC rules: %v", err) + } + return nil +} + +// createConfigMapRBACRules creates the RBAC rules for exposing the base kubelet ConfigMap in the kube-system namespace to unauthenticated users +func createConfigMapRBACRules(client clientset.Interface, k8sVersion *version.Version) error { + if err := apiclient.CreateOrUpdateRole(client, &rbac.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: configMapRBACName(k8sVersion), + Namespace: metav1.NamespaceSystem, + }, + Rules: []rbac.PolicyRule{ + rbachelper.NewRule("get").Groups("").Resources("configmaps").Names(configMapName(k8sVersion)).RuleOrDie(), + }, + }); err != nil { + return err + } + + return apiclient.CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: configMapRBACName(k8sVersion), + Namespace: metav1.NamespaceSystem, + }, + RoleRef: rbac.RoleRef{ + APIGroup: rbac.GroupName, + Kind: "Role", + Name: configMapRBACName(k8sVersion), + }, + Subjects: []rbac.Subject{ + { + Kind: rbac.GroupKind, + Name: kubeadmconstants.NodesGroup, + }, + { + Kind: rbac.GroupKind, + Name: kubeadmconstants.NodeBootstrapTokenAuthGroup, + }, + }, + }) +} + +// DownloadConfig downloads the kubelet configuration from a ConfigMap and writes it to disk. +// Used at "kubeadm join" time +func DownloadConfig(client clientset.Interface, kubeletVersion *version.Version, kubeletDir string) error { + + // Download the ConfigMap from the cluster based on what version the kubelet is + configMapName := configMapName(kubeletVersion) + + fmt.Printf("[kubelet] Downloading configuration for the kubelet from the %q ConfigMap in the %s namespace\n", + configMapName, metav1.NamespaceSystem) + + kubeletCfg, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(configMapName, metav1.GetOptions{}) + // If the ConfigMap wasn't found and the kubelet version is v1.10.x, where we didn't support the config file yet + // just return, don't error out + if apierrors.IsNotFound(err) && kubeletVersion.Minor() == 10 { + return nil + } + if err != nil { + return err + } + + return writeConfigBytesToDisk([]byte(kubeletCfg.Data[kubeadmconstants.KubeletBaseConfigurationConfigMapKey]), kubeletDir) +} + +// configMapName returns the right ConfigMap name for the right branch of k8s +func configMapName(k8sVersion *version.Version) string { + return fmt.Sprintf("%s%d.%d", kubeadmconstants.KubeletBaseConfigurationConfigMapPrefix, k8sVersion.Major(), k8sVersion.Minor()) +} + +// configMapRBACName returns the name for the Role/RoleBinding for the kubelet config configmap for the right branch of k8s +func configMapRBACName(k8sVersion *version.Version) string { + return fmt.Sprintf("%s%d.%d", kubeadmconstants.KubeletBaseConfigMapRolePrefix, k8sVersion.Major(), k8sVersion.Minor()) +} + +// getConfigBytes marshals a kubeletconfiguration object to bytes +func getConfigBytes(kubeletConfig *kubeletconfigv1beta1.KubeletConfiguration) ([]byte, error) { + _, kubeletCodecs, err := kubeletconfigscheme.NewSchemeAndCodecs() + if err != nil { + return []byte{}, err + } + + return kubeadmutil.MarshalToYamlForCodecs(kubeletConfig, kubeletconfigv1beta1.SchemeGroupVersion, *kubeletCodecs) +} + +// writeConfigBytesToDisk writes a byte slice down to disk at the specific location of the kubelet config file +func writeConfigBytesToDisk(b []byte, kubeletDir string) error { + configFile := filepath.Join(kubeletDir, kubeadmconstants.KubeletConfigurationFileName) + fmt.Printf("[kubelet] Writing kubelet configuration to file %q\n", configFile) + + // creates target folder if not already exists + if err := os.MkdirAll(kubeletDir, 0700); err != nil { + return fmt.Errorf("failed to create directory %q: %v", kubeletDir, err) + } + + if err := ioutil.WriteFile(configFile, b, 0644); err != nil { + return fmt.Errorf("failed to write kubelet configuration to the file %q: %v", configFile, err) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/config_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/config_test.go new file mode 100644 index 000000000..dc21da453 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/config_test.go @@ -0,0 +1,78 @@ +/* +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 kubelet + +import ( + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" + core "k8s.io/client-go/testing" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + "k8s.io/kubernetes/pkg/util/version" +) + +func TestCreateConfigMap(t *testing.T) { + nodeName := "fake-node" + client := fake.NewSimpleClientset() + cfg := &kubeadmapi.MasterConfiguration{ + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: nodeName}, + KubernetesVersion: "v1.11.0", + KubeletConfiguration: kubeadmapi.KubeletConfiguration{ + BaseConfig: &kubeletconfigv1beta1.KubeletConfiguration{}, + }, + } + + client.PrependReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) { + return true, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: nodeName, + }, + Spec: v1.NodeSpec{}, + }, nil + }) + client.PrependReactor("create", "roles", func(action core.Action) (bool, runtime.Object, error) { + return true, nil, nil + }) + client.PrependReactor("create", "rolebindings", func(action core.Action) (bool, runtime.Object, error) { + return true, nil, nil + }) + client.PrependReactor("create", "configmaps", func(action core.Action) (bool, runtime.Object, error) { + return true, nil, nil + }) + + if err := CreateConfigMap(cfg, client); err != nil { + t.Errorf("CreateConfigMap: unexpected error %v", err) + } +} + +func TestCreateConfigMapRBACRules(t *testing.T) { + client := fake.NewSimpleClientset() + client.PrependReactor("create", "roles", func(action core.Action) (bool, runtime.Object, error) { + return true, nil, nil + }) + client.PrependReactor("create", "rolebindings", func(action core.Action) (bool, runtime.Object, error) { + return true, nil, nil + }) + + if err := createConfigMapRBACRules(client, version.MustParseSemantic("v1.11.0")); err != nil { + t.Errorf("createConfigMapRBACRules: unexpected error %v", err) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/dynamic.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/dynamic.go new file mode 100644 index 000000000..2470e8459 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/dynamic.go @@ -0,0 +1,59 @@ +/* +Copyright 2018 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 kubelet + +import ( + "fmt" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clientset "k8s.io/client-go/kubernetes" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" + "k8s.io/kubernetes/pkg/util/version" +) + +// EnableDynamicConfigForNode updates the Node's ConfigSource to enable Dynamic Kubelet Configuration, depending on what version the kubelet is +// Used at "kubeadm init", "kubeadm join" and "kubeadm upgrade" time +// This func is ONLY run if the user enables the `DynamicKubeletConfig` feature gate, which is by default off +func EnableDynamicConfigForNode(client clientset.Interface, nodeName string, kubeletVersion *version.Version) error { + + configMapName := configMapName(kubeletVersion) + fmt.Printf("[kubelet] Enabling Dynamic Kubelet Config for Node %q; config sourced from ConfigMap %q in namespace %s\n", + nodeName, configMapName, metav1.NamespaceSystem) + fmt.Println("[kubelet] WARNING: The Dynamic Kubelet Config feature is alpha and off by default. It hasn't been well-tested yet at this stage, use with caution.") + + _, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(configMapName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("couldn't get the kubelet configuration ConfigMap: %v", err) + } + + // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. + return apiclient.PatchNode(client, nodeName, func(n *v1.Node) { + patchNodeForDynamicConfig(n, configMapName) + }) +} + +func patchNodeForDynamicConfig(n *v1.Node, configMapName string) { + n.Spec.ConfigSource = &v1.NodeConfigSource{ + ConfigMap: &v1.ConfigMapNodeConfigSource{ + Name: configMapName, + Namespace: metav1.NamespaceSystem, + KubeletConfigKey: kubeadmconstants.KubeletBaseConfigurationConfigMapKey, + }, + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/dynamic_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/dynamic_test.go new file mode 100644 index 000000000..150eeda40 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/dynamic_test.go @@ -0,0 +1,65 @@ +/* +Copyright 2018 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 kubelet + +import ( + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" + core "k8s.io/client-go/testing" + kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + "k8s.io/kubernetes/pkg/util/version" +) + +func TestEnableDynamicConfigForNode(t *testing.T) { + nodeName := "fake-node" + client := fake.NewSimpleClientset() + client.PrependReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) { + return true, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: nodeName, + Labels: map[string]string{kubeletapis.LabelHostname: nodeName}, + }, + Spec: v1.NodeSpec{ + ConfigSource: &v1.NodeConfigSource{ + ConfigMap: &v1.ConfigMapNodeConfigSource{ + UID: "", + }, + }, + }, + }, nil + }) + client.PrependReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) { + return true, &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kubelet-config-1.11", + Namespace: metav1.NamespaceSystem, + UID: "fake-uid", + }, + }, nil + }) + client.PrependReactor("patch", "nodes", func(action core.Action) (bool, runtime.Object, error) { + return true, nil, nil + }) + + if err := EnableDynamicConfigForNode(client, nodeName, version.MustParseSemantic("v1.11.0")); err != nil { + t.Errorf("UpdateNodeWithConfigMap: unexpected error %v", err) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/flags.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/flags.go new file mode 100644 index 000000000..51277b81e --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/flags.go @@ -0,0 +1,130 @@ +/* +Copyright 2018 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 kubelet + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/golang/glog" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/features" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + nodeutil "k8s.io/kubernetes/pkg/util/node" + "k8s.io/kubernetes/pkg/util/procfs" + utilsexec "k8s.io/utils/exec" +) + +type kubeletFlagsOpts struct { + nodeRegOpts *kubeadmapi.NodeRegistrationOptions + featureGates map[string]bool + registerTaintsUsingFlags bool + execer utilsexec.Interface + pidOfFunc func(string) ([]int, error) + defaultHostname string +} + +// WriteKubeletDynamicEnvFile writes a environment file with dynamic flags to the kubelet. +// Used at "kubeadm init" and "kubeadm join" time. +func WriteKubeletDynamicEnvFile(nodeRegOpts *kubeadmapi.NodeRegistrationOptions, featureGates map[string]bool, registerTaintsUsingFlags bool, kubeletDir string) error { + + flagOpts := kubeletFlagsOpts{ + nodeRegOpts: nodeRegOpts, + featureGates: featureGates, + registerTaintsUsingFlags: registerTaintsUsingFlags, + execer: utilsexec.New(), + pidOfFunc: procfs.PidOf, + defaultHostname: nodeutil.GetHostname(""), + } + stringMap := buildKubeletArgMap(flagOpts) + argList := kubeadmutil.BuildArgumentListFromMap(stringMap, nodeRegOpts.KubeletExtraArgs) + envFileContent := fmt.Sprintf("%s=%s\n", constants.KubeletEnvFileVariableName, strings.Join(argList, " ")) + + return writeKubeletFlagBytesToDisk([]byte(envFileContent), kubeletDir) +} + +// buildKubeletArgMap takes a MasterConfiguration object and builds based on that a string-string map with flags +// that should be given to the local kubelet daemon. +func buildKubeletArgMap(opts kubeletFlagsOpts) map[string]string { + kubeletFlags := map[string]string{} + + if opts.nodeRegOpts.CRISocket == kubeadmapiv1alpha2.DefaultCRISocket { + // These flags should only be set when running docker + kubeletFlags["network-plugin"] = "cni" + kubeletFlags["cni-conf-dir"] = "/etc/cni/net.d" + kubeletFlags["cni-bin-dir"] = "/opt/cni/bin" + driver, err := kubeadmutil.GetCgroupDriverDocker(opts.execer) + if err != nil { + glog.Warningf("cannot automatically assign a '--cgroup-driver' value when starting the Kubelet: %v\n", err) + } else { + kubeletFlags["cgroup-driver"] = driver + } + } else { + kubeletFlags["container-runtime"] = "remote" + kubeletFlags["container-runtime-endpoint"] = opts.nodeRegOpts.CRISocket + } + + if opts.registerTaintsUsingFlags && opts.nodeRegOpts.Taints != nil && len(opts.nodeRegOpts.Taints) > 0 { + taintStrs := []string{} + for _, taint := range opts.nodeRegOpts.Taints { + taintStrs = append(taintStrs, taint.ToString()) + } + + kubeletFlags["register-with-taints"] = strings.Join(taintStrs, ",") + } + + if pids, _ := opts.pidOfFunc("systemd-resolved"); len(pids) > 0 { + // procfs.PidOf only returns an error if the regex is empty or doesn't compile, so we can ignore it + kubeletFlags["resolv-conf"] = "/run/systemd/resolve/resolv.conf" + } + + // Make sure the node name we're passed will work with Kubelet + if opts.nodeRegOpts.Name != "" && opts.nodeRegOpts.Name != opts.defaultHostname { + glog.V(1).Info("setting kubelet hostname-override to %q", opts.nodeRegOpts.Name) + kubeletFlags["hostname-override"] = opts.nodeRegOpts.Name + } + + // If the user enabled Dynamic Kubelet Configuration (which is disabled by default), set the directory + // in the CLI flags so that the feature actually gets enabled + if features.Enabled(opts.featureGates, features.DynamicKubeletConfig) { + kubeletFlags["dynamic-config-dir"] = filepath.Join(constants.KubeletRunDirectory, constants.DynamicKubeletConfigurationDirectoryName) + } + + // TODO: Conditionally set `--cgroup-driver` to either `systemd` or `cgroupfs` for CRI other than Docker + + return kubeletFlags +} + +// writeKubeletFlagBytesToDisk writes a byte slice down to disk at the specific location of the kubelet flag overrides file +func writeKubeletFlagBytesToDisk(b []byte, kubeletDir string) error { + kubeletEnvFilePath := filepath.Join(kubeletDir, constants.KubeletEnvFileName) + fmt.Printf("[kubelet] Writing kubelet environment file with flags to file %q\n", kubeletEnvFilePath) + + // creates target folder if not already exists + if err := os.MkdirAll(kubeletDir, 0700); err != nil { + return fmt.Errorf("failed to create directory %q: %v", kubeletDir, err) + } + if err := ioutil.WriteFile(kubeletEnvFilePath, b, 0644); err != nil { + return fmt.Errorf("failed to write kubelet configuration to the file %q: %v", kubeletEnvFilePath, err) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/flags_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/flags_test.go new file mode 100644 index 000000000..b50a658df --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/flags_test.go @@ -0,0 +1,277 @@ +/* +Copyright 2018 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 kubelet + +import ( + "context" + "errors" + "fmt" + "io" + "reflect" + "strings" + "testing" + + "k8s.io/api/core/v1" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/utils/exec" +) + +type fakeCmd struct { + b []byte + err error +} + +func (f fakeCmd) Run() error { return f.err } +func (f fakeCmd) CombinedOutput() ([]byte, error) { return f.b, f.err } +func (f fakeCmd) Output() ([]byte, error) { return f.b, f.err } +func (f fakeCmd) SetDir(dir string) {} +func (f fakeCmd) SetStdin(in io.Reader) {} +func (f fakeCmd) SetStdout(out io.Writer) {} +func (f fakeCmd) SetStderr(out io.Writer) {} +func (f fakeCmd) Stop() {} + +type fakeExecer struct { + ioMap map[string]fakeCmd +} + +func (f fakeExecer) Command(cmd string, args ...string) exec.Cmd { + cmds := []string{cmd} + cmds = append(cmds, args...) + return f.ioMap[strings.Join(cmds, " ")] +} +func (f fakeExecer) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { + return f.Command(cmd, args...) +} +func (f fakeExecer) LookPath(file string) (string, error) { return "", errors.New("unknown binary") } + +var ( + systemdCgroupExecer = fakeExecer{ + ioMap: map[string]fakeCmd{ + "docker info": { + b: []byte(`Cgroup Driver: systemd`), + }, + }, + } + + cgroupfsCgroupExecer = fakeExecer{ + ioMap: map[string]fakeCmd{ + "docker info": { + b: []byte(`Cgroup Driver: cgroupfs`), + }, + }, + } + + errCgroupExecer = fakeExecer{ + ioMap: map[string]fakeCmd{ + "docker info": { + err: fmt.Errorf("no such binary: docker"), + }, + }, + } +) + +func binaryRunningPidOfFunc(_ string) ([]int, error) { + return []int{1, 2, 3}, nil +} + +func binaryNotRunningPidOfFunc(_ string) ([]int, error) { + return []int{}, nil +} + +func TestBuildKubeletArgMap(t *testing.T) { + + tests := []struct { + name string + opts kubeletFlagsOpts + expected map[string]string + }{ + { + name: "the simplest case", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/dockershim.sock", + Name: "foo", + Taints: []v1.Taint{ // This should be ignored as registerTaintsUsingFlags is false + { + Key: "foo", + Value: "bar", + Effect: "baz", + }, + }, + }, + execer: errCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "network-plugin": "cni", + "cni-conf-dir": "/etc/cni/net.d", + "cni-bin-dir": "/opt/cni/bin", + }, + }, + { + name: "nodeRegOpts.Name != default hostname", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/dockershim.sock", + Name: "override-name", + }, + execer: errCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "default", + }, + expected: map[string]string{ + "network-plugin": "cni", + "cni-conf-dir": "/etc/cni/net.d", + "cni-bin-dir": "/opt/cni/bin", + "hostname-override": "override-name", + }, + }, + { + name: "systemd cgroup driver", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/dockershim.sock", + Name: "foo", + }, + execer: systemdCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "network-plugin": "cni", + "cni-conf-dir": "/etc/cni/net.d", + "cni-bin-dir": "/opt/cni/bin", + "cgroup-driver": "systemd", + }, + }, + { + name: "cgroupfs cgroup driver", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/dockershim.sock", + Name: "foo", + }, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "network-plugin": "cni", + "cni-conf-dir": "/etc/cni/net.d", + "cni-bin-dir": "/opt/cni/bin", + "cgroup-driver": "cgroupfs", + }, + }, + { + name: "external CRI runtime", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/containerd.sock", + Name: "foo", + }, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "container-runtime": "remote", + "container-runtime-endpoint": "/var/run/containerd.sock", + }, + }, + { + name: "register with taints", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/containerd.sock", + Name: "foo", + Taints: []v1.Taint{ + { + Key: "foo", + Value: "bar", + Effect: "baz", + }, + { + Key: "key", + Value: "val", + Effect: "eff", + }, + }, + }, + registerTaintsUsingFlags: true, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "container-runtime": "remote", + "container-runtime-endpoint": "/var/run/containerd.sock", + "register-with-taints": "foo=bar:baz,key=val:eff", + }, + }, + { + name: "systemd-resolved running", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/containerd.sock", + Name: "foo", + }, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "container-runtime": "remote", + "container-runtime-endpoint": "/var/run/containerd.sock", + "resolv-conf": "/run/systemd/resolve/resolv.conf", + }, + }, + { + name: "dynamic kubelet config enabled", + opts: kubeletFlagsOpts{ + nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ + CRISocket: "/var/run/containerd.sock", + Name: "foo", + }, + featureGates: map[string]bool{ + "DynamicKubeletConfig": true, + }, + execer: cgroupfsCgroupExecer, + pidOfFunc: binaryNotRunningPidOfFunc, + defaultHostname: "foo", + }, + expected: map[string]string{ + "container-runtime": "remote", + "container-runtime-endpoint": "/var/run/containerd.sock", + "dynamic-config-dir": "/var/lib/kubelet/dynamic-config", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actual := buildKubeletArgMap(test.opts) + if !reflect.DeepEqual(actual, test.expected) { + t.Errorf( + "failed buildKubeletArgMap:\n\texpected: %v\n\t actual: %v", + test.expected, + actual, + ) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/kubelet.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/kubelet.go deleted file mode 100644 index 13afaaa33..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/kubelet.go +++ /dev/null @@ -1,234 +0,0 @@ -/* -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 kubelet - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path/filepath" - - "k8s.io/api/core/v1" - rbac "k8s.io/api/rbac/v1" - apierrs "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/strategicpatch" - "k8s.io/apimachinery/pkg/util/wait" - clientset "k8s.io/client-go/kubernetes" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" - "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" - rbachelper "k8s.io/kubernetes/pkg/apis/rbac/v1" - kubeletconfigscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" - kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" -) - -// CreateBaseKubeletConfiguration creates base kubelet configuration for dynamic kubelet configuration feature. -func CreateBaseKubeletConfiguration(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { - fmt.Printf("[kubelet] Uploading a ConfigMap %q in namespace %s with base configuration for the kubelets in the cluster\n", - kubeadmconstants.KubeletBaseConfigurationConfigMap, metav1.NamespaceSystem) - - _, kubeletCodecs, err := kubeletconfigscheme.NewSchemeAndCodecs() - if err != nil { - return err - } - kubeletBytes, err := kubeadmutil.MarshalToYamlForCodecs(cfg.KubeletConfiguration.BaseConfig, kubeletconfigv1beta1.SchemeGroupVersion, *kubeletCodecs) - if err != nil { - return err - } - - if err = apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: kubeadmconstants.KubeletBaseConfigurationConfigMap, - Namespace: metav1.NamespaceSystem, - }, - Data: map[string]string{ - kubeadmconstants.KubeletBaseConfigurationConfigMapKey: string(kubeletBytes), - }, - }); err != nil { - return err - } - - if err := createKubeletBaseConfigMapRBACRules(client); err != nil { - return fmt.Errorf("error creating base kubelet configmap RBAC rules: %v", err) - } - - return updateNodeWithConfigMap(client, cfg.NodeName) -} - -// ConsumeBaseKubeletConfiguration consumes base kubelet configuration for dynamic kubelet configuration feature. -func ConsumeBaseKubeletConfiguration(nodeName string) error { - client, err := getLocalNodeTLSBootstrappedClient() - if err != nil { - return err - } - - kubeletCfg, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(kubeadmconstants.KubeletBaseConfigurationConfigMap, metav1.GetOptions{}) - if err != nil { - return err - } - - if err := writeInitKubeletConfigToDisk([]byte(kubeletCfg.Data[kubeadmconstants.KubeletBaseConfigurationConfigMapKey])); err != nil { - return fmt.Errorf("failed to write initial remote configuration of kubelet to disk for node %s: %v", nodeName, err) - } - - return updateNodeWithConfigMap(client, nodeName) -} - -// updateNodeWithConfigMap updates node ConfigSource with KubeletBaseConfigurationConfigMap -func updateNodeWithConfigMap(client clientset.Interface, nodeName string) error { - fmt.Printf("[kubelet] Using Dynamic Kubelet Config for node %q; config sourced from ConfigMap %q in namespace %s\n", - nodeName, kubeadmconstants.KubeletBaseConfigurationConfigMap, metav1.NamespaceSystem) - - // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. - return wait.Poll(kubeadmconstants.APICallRetryInterval, kubeadmconstants.UpdateNodeTimeout, func() (bool, error) { - node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) - if err != nil { - return false, nil - } - - oldData, err := json.Marshal(node) - if err != nil { - return false, err - } - - kubeletCfg, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(kubeadmconstants.KubeletBaseConfigurationConfigMap, metav1.GetOptions{}) - if err != nil { - return false, nil - } - - node.Spec.ConfigSource = &v1.NodeConfigSource{ - ConfigMapRef: &v1.ObjectReference{ - Name: kubeadmconstants.KubeletBaseConfigurationConfigMap, - Namespace: metav1.NamespaceSystem, - UID: kubeletCfg.UID, - }, - } - - newData, err := json.Marshal(node) - if err != nil { - return false, err - } - - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{}) - if err != nil { - return false, err - } - - if _, err := client.CoreV1().Nodes().Patch(node.Name, types.StrategicMergePatchType, patchBytes); err != nil { - if apierrs.IsConflict(err) { - fmt.Println("Temporarily unable to update node metadata due to conflict (will retry)") - return false, nil - } - return false, err - } - - return true, nil - }) -} - -// createKubeletBaseConfigMapRBACRules creates the RBAC rules for exposing the base kubelet ConfigMap in the kube-system namespace to unauthenticated users -func createKubeletBaseConfigMapRBACRules(client clientset.Interface) error { - if err := apiclient.CreateOrUpdateRole(client, &rbac.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: kubeadmconstants.KubeletBaseConfigMapRoleName, - Namespace: metav1.NamespaceSystem, - }, - Rules: []rbac.PolicyRule{ - rbachelper.NewRule("get").Groups("").Resources("configmaps").Names(kubeadmconstants.KubeletBaseConfigurationConfigMap).RuleOrDie(), - }, - }); err != nil { - return err - } - - return apiclient.CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: kubeadmconstants.KubeletBaseConfigMapRoleName, - Namespace: metav1.NamespaceSystem, - }, - RoleRef: rbac.RoleRef{ - APIGroup: rbac.GroupName, - Kind: "Role", - Name: kubeadmconstants.KubeletBaseConfigMapRoleName, - }, - Subjects: []rbac.Subject{ - { - Kind: rbac.GroupKind, - Name: kubeadmconstants.NodesGroup, - }, - { - Kind: rbac.GroupKind, - Name: kubeadmconstants.NodeBootstrapTokenAuthGroup, - }, - }, - }) -} - -// getLocalNodeTLSBootstrappedClient waits for the kubelet to perform the TLS bootstrap -// and then creates a client from config file /etc/kubernetes/kubelet.conf -func getLocalNodeTLSBootstrappedClient() (clientset.Interface, error) { - fmt.Println("[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...") - - kubeletKubeConfig := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName) - - // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. - err := wait.PollImmediateInfinite(kubeadmconstants.APICallRetryInterval, func() (bool, error) { - _, err := os.Stat(kubeletKubeConfig) - return (err == nil), nil - }) - if err != nil { - return nil, err - } - - return kubeconfigutil.ClientSetFromFile(kubeletKubeConfig) -} - -// WriteInitKubeletConfigToDiskOnMaster writes base kubelet configuration to disk on master. -func WriteInitKubeletConfigToDiskOnMaster(cfg *kubeadmapi.MasterConfiguration) error { - fmt.Printf("[kubelet] Writing base configuration of kubelets to disk on master node %s\n", cfg.NodeName) - - _, kubeletCodecs, err := kubeletconfigscheme.NewSchemeAndCodecs() - if err != nil { - return err - } - - kubeletBytes, err := kubeadmutil.MarshalToYamlForCodecs(cfg.KubeletConfiguration.BaseConfig, kubeletconfigv1beta1.SchemeGroupVersion, *kubeletCodecs) - if err != nil { - return err - } - - if err := writeInitKubeletConfigToDisk(kubeletBytes); err != nil { - return fmt.Errorf("failed to write base configuration of kubelet to disk on master node %s: %v", cfg.NodeName, err) - } - - return nil -} - -func writeInitKubeletConfigToDisk(kubeletConfig []byte) error { - if err := os.MkdirAll(kubeadmconstants.KubeletBaseConfigurationDir, 0644); err != nil { - return fmt.Errorf("failed to create directory %q: %v", kubeadmconstants.KubeletBaseConfigurationDir, err) - } - baseConfigFile := filepath.Join(kubeadmconstants.KubeletBaseConfigurationDir, kubeadmconstants.KubeletBaseConfigurationFile) - if err := ioutil.WriteFile(baseConfigFile, kubeletConfig, 0644); err != nil { - return fmt.Errorf("failed to write initial remote configuration of kubelet into file %q: %v", baseConfigFile, err) - } - return nil -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/kubelet_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/kubelet_test.go deleted file mode 100644 index 9c6935e4a..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet/kubelet_test.go +++ /dev/null @@ -1,134 +0,0 @@ -/* -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 kubelet - -import ( - "testing" - - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes/fake" - core "k8s.io/client-go/testing" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" -) - -func TestCreateBaseKubeletConfiguration(t *testing.T) { - nodeName := "fake-node" - client := fake.NewSimpleClientset() - cfg := &kubeadmapi.MasterConfiguration{ - NodeName: nodeName, - KubeletConfiguration: kubeadmapi.KubeletConfiguration{ - BaseConfig: &kubeletconfigv1beta1.KubeletConfiguration{ - TypeMeta: metav1.TypeMeta{ - Kind: "KubeletConfiguration", - }, - }, - }, - } - - client.PrependReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) { - return true, &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: nodeName, - }, - Spec: v1.NodeSpec{ - ConfigSource: &v1.NodeConfigSource{ - ConfigMapRef: &v1.ObjectReference{ - UID: "", - }, - }, - }, - }, nil - }) - client.PrependReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) { - return true, &v1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: kubeadmconstants.KubeletBaseConfigurationConfigMap, - Namespace: metav1.NamespaceSystem, - UID: "fake-uid", - }, - }, nil - }) - client.PrependReactor("patch", "nodes", func(action core.Action) (bool, runtime.Object, error) { - return true, nil, nil - }) - client.PrependReactor("create", "roles", func(action core.Action) (bool, runtime.Object, error) { - return true, nil, nil - }) - client.PrependReactor("create", "rolebindings", func(action core.Action) (bool, runtime.Object, error) { - return true, nil, nil - }) - client.PrependReactor("create", "configmaps", func(action core.Action) (bool, runtime.Object, error) { - return true, nil, nil - }) - - if err := CreateBaseKubeletConfiguration(cfg, client); err != nil { - t.Errorf("CreateBaseKubeletConfiguration: unexepected error %v", err) - } -} - -func TestUpdateNodeWithConfigMap(t *testing.T) { - nodeName := "fake-node" - client := fake.NewSimpleClientset() - client.PrependReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) { - return true, &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: nodeName, - }, - Spec: v1.NodeSpec{ - ConfigSource: &v1.NodeConfigSource{ - ConfigMapRef: &v1.ObjectReference{ - UID: "", - }, - }, - }, - }, nil - }) - client.PrependReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) { - return true, &v1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: kubeadmconstants.KubeletBaseConfigurationConfigMap, - Namespace: metav1.NamespaceSystem, - UID: "fake-uid", - }, - }, nil - }) - client.PrependReactor("patch", "nodes", func(action core.Action) (bool, runtime.Object, error) { - return true, nil, nil - }) - - if err := updateNodeWithConfigMap(client, nodeName); err != nil { - t.Errorf("UpdateNodeWithConfigMap: unexepected error %v", err) - } -} - -func TestCreateKubeletBaseConfigMapRBACRules(t *testing.T) { - client := fake.NewSimpleClientset() - client.PrependReactor("create", "roles", func(action core.Action) (bool, runtime.Object, error) { - return true, nil, nil - }) - client.PrependReactor("create", "rolebindings", func(action core.Action) (bool, runtime.Object, error) { - return true, nil, nil - }) - - if err := createKubeletBaseConfigMapRBACRules(client); err != nil { - t.Errorf("createKubeletBaseConfigMapRBACRules: unexepected error %v", err) - } -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/BUILD index e8590bb4f..aceff8cf3 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/BUILD @@ -27,13 +27,8 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster", deps = [ "//cmd/kubeadm/app/constants:go_default_library", - "//pkg/kubelet/apis:go_default_library", + "//cmd/kubeadm/app/util/apiclient:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/markmaster.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/markmaster.go index d3485470c..111970840 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/markmaster.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/markmaster.go @@ -17,105 +17,50 @@ limitations under the License. package markmaster import ( - "encoding/json" "fmt" "k8s.io/api/core/v1" - apierrs "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/strategicpatch" - "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" ) // MarkMaster taints the master and sets the master label -func MarkMaster(client clientset.Interface, masterName string, taint bool) error { +func MarkMaster(client clientset.Interface, masterName string, taints []v1.Taint) error { - if taint { - fmt.Printf("[markmaster] Will mark node %s as master by adding a label and a taint\n", masterName) - } else { - fmt.Printf("[markmaster] Will mark node %s as master by adding a label\n", masterName) - } - - // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. - return wait.Poll(kubeadmconstants.APICallRetryInterval, kubeadmconstants.MarkMasterTimeout, func() (bool, error) { - // First get the node object - n, err := client.CoreV1().Nodes().Get(masterName, metav1.GetOptions{}) - if err != nil { - return false, nil - } - - // The node may appear to have no labels at first, - // so we wait for it to get hostname label. - if _, found := n.ObjectMeta.Labels[kubeletapis.LabelHostname]; !found { - return false, nil - } - - oldData, err := json.Marshal(n) - if err != nil { - return false, err - } - - // The master node should be tainted and labelled accordingly - markMasterNode(n, taint) - - newData, err := json.Marshal(n) - if err != nil { - return false, err - } + fmt.Printf("[markmaster] Marking the node %s as master by adding the label \"%s=''\"\n", masterName, constants.LabelNodeRoleMaster) - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{}) - if err != nil { - return false, err - } - - if _, err := client.CoreV1().Nodes().Patch(n.Name, types.StrategicMergePatchType, patchBytes); err != nil { - if apierrs.IsConflict(err) { - fmt.Println("[markmaster] Temporarily unable to update master node metadata due to conflict (will retry)") - return false, nil - } - return false, err - } - - if taint { - fmt.Printf("[markmaster] Master %s tainted and labelled with key/value: %s=%q\n", masterName, kubeadmconstants.LabelNodeRoleMaster, "") - } else { - fmt.Printf("[markmaster] Master %s labelled with key/value: %s=%q\n", masterName, kubeadmconstants.LabelNodeRoleMaster, "") + if taints != nil && len(taints) > 0 { + taintStrs := []string{} + for _, taint := range taints { + taintStrs = append(taintStrs, taint.ToString()) } + fmt.Printf("[markmaster] Marking the node %s as master by adding the taints %v\n", masterName, taintStrs) + } - return true, nil + return apiclient.PatchNode(client, masterName, func(n *v1.Node) { + markMasterNode(n, taints) }) } -func markMasterNode(n *v1.Node, taint bool) { - n.ObjectMeta.Labels[kubeadmconstants.LabelNodeRoleMaster] = "" - if taint { - addTaintIfNotExists(n, kubeadmconstants.MasterTaint) - } else { - delTaintIfExists(n, kubeadmconstants.MasterTaint) - } -} - -func addTaintIfNotExists(n *v1.Node, t v1.Taint) { - for _, taint := range n.Spec.Taints { - if taint == t { - return +func taintExists(taint v1.Taint, taints []v1.Taint) bool { + for _, t := range taints { + if t == taint { + return true } } - n.Spec.Taints = append(n.Spec.Taints, t) + return false } -func delTaintIfExists(n *v1.Node, t v1.Taint) { - var taints []v1.Taint - for _, taint := range n.Spec.Taints { - if taint == t { - continue +func markMasterNode(n *v1.Node, taints []v1.Taint) { + n.ObjectMeta.Labels[constants.LabelNodeRoleMaster] = "" + + for _, nt := range n.Spec.Taints { + if !taintExists(nt, taints) { + taints = append(taints, nt) } - taints = append(taints, t) } + n.Spec.Taints = taints } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/markmaster_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/markmaster_test.go index d7d5a9345..c8f937abd 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/markmaster_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster/markmaster_test.go @@ -40,53 +40,70 @@ func TestMarkMaster(t *testing.T) { // will need to change if strategicpatch's behavior changes in the // future. tests := []struct { - name string - existingLabel string - existingTaint *v1.Taint - wantTaint bool - expectedPatch string + name string + existingLabel string + existingTaints []v1.Taint + newTaints []v1.Taint + expectedPatch string }{ { "master label and taint missing", "", nil, - true, + []v1.Taint{kubeadmconstants.MasterTaint}, "{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}},\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}", }, { "master label and taint missing but taint not wanted", "", nil, - false, + nil, "{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}", }, { "master label missing", "", - &kubeadmconstants.MasterTaint, - true, + []v1.Taint{kubeadmconstants.MasterTaint}, + []v1.Taint{kubeadmconstants.MasterTaint}, "{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}", }, { "master taint missing", kubeadmconstants.LabelNodeRoleMaster, nil, - true, + []v1.Taint{kubeadmconstants.MasterTaint}, "{\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}", }, { "nothing missing", kubeadmconstants.LabelNodeRoleMaster, - &kubeadmconstants.MasterTaint, - true, + []v1.Taint{kubeadmconstants.MasterTaint}, + []v1.Taint{kubeadmconstants.MasterTaint}, "{}", }, { - "nothing missing but taint unwanted", + "has taint and no new taints wanted", kubeadmconstants.LabelNodeRoleMaster, - &kubeadmconstants.MasterTaint, - false, - "{\"spec\":{\"taints\":null}}", + []v1.Taint{ + { + Key: "node.cloudprovider.kubernetes.io/uninitialized", + Effect: v1.TaintEffectNoSchedule, + }, + }, + nil, + "{}", + }, + { + "has taint and should merge with wanted taint", + kubeadmconstants.LabelNodeRoleMaster, + []v1.Taint{ + { + Key: "node.cloudprovider.kubernetes.io/uninitialized", + Effect: v1.TaintEffectNoSchedule, + }, + }, + []v1.Taint{kubeadmconstants.MasterTaint}, + "{\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"},{\"effect\":\"NoSchedule\",\"key\":\"node.cloudprovider.kubernetes.io/uninitialized\"}]}}", }, } @@ -105,8 +122,8 @@ func TestMarkMaster(t *testing.T) { masterNode.ObjectMeta.Labels[tc.existingLabel] = "" } - if tc.existingTaint != nil { - masterNode.Spec.Taints = append(masterNode.Spec.Taints, *tc.existingTaint) + if tc.existingTaints != nil { + masterNode.Spec.Taints = tc.existingTaints } jsonNode, err := json.Marshal(masterNode) @@ -144,8 +161,7 @@ func TestMarkMaster(t *testing.T) { t.Fatalf("MarkMaster(%s): unexpected error building clientset: %v", tc.name, err) } - err = MarkMaster(cs, hostname, tc.wantTaint) - if err != nil { + if err := MarkMaster(cs, hostname, tc.newTaints); err != nil { t.Errorf("MarkMaster(%s) returned unexpected error: %v", tc.name, err) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode/BUILD new file mode 100644 index 000000000..88c6fbd34 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode/BUILD @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["patchnode.go"], + importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode", + visibility = ["//visibility:public"], + deps = [ + "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/util/apiclient:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode/patchnode.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode/patchnode.go new file mode 100644 index 000000000..1ebf9b8a9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode/patchnode.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 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 patchnode + +import ( + "fmt" + + "k8s.io/api/core/v1" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" +) + +// AnnotateCRISocket annotates the node with the given crisocket +func AnnotateCRISocket(client clientset.Interface, nodeName string, criSocket string) error { + + fmt.Printf("[patchnode] Uploading the CRI Socket information %q to the Node API object %q as an annotation\n", criSocket, nodeName) + + return apiclient.PatchNode(client, nodeName, func(n *v1.Node) { + annotateNodeWithCRISocket(n, criSocket) + }) +} + +func annotateNodeWithCRISocket(n *v1.Node, criSocket string) { + n.ObjectMeta.Annotations[constants.AnnotationKubeadmCRISocket] = criSocket +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/BUILD index 7971d89ce..4503f0c71 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/BUILD @@ -17,7 +17,6 @@ go_test( deps = [ "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", - "//pkg/volume/util:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", ], @@ -37,11 +36,13 @@ go_library( "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//pkg/volume/util:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/selfhosting.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/selfhosting.go index 8456313a6..c5f2aa218 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/selfhosting.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/selfhosting.go @@ -18,18 +18,22 @@ package selfhosting import ( "fmt" + "io/ioutil" "os" "time" + "github.com/golang/glog" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" clientset "k8s.io/client-go/kubernetes" + clientscheme "k8s.io/client-go/kubernetes/scheme" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - volumeutil "k8s.io/kubernetes/pkg/volume/util" ) const ( @@ -53,11 +57,12 @@ const ( // Otherwise, there is a race condition when we proceed without kubelet having restarted the API server correctly and the next .Create call flakes // 9. Do that for the kube-apiserver, kube-controller-manager and kube-scheduler in a loop func CreateSelfHostedControlPlane(manifestsDir, kubeConfigDir string, cfg *kubeadmapi.MasterConfiguration, client clientset.Interface, waiter apiclient.Waiter, dryRun bool) error { - + glog.V(1).Infoln("creating self hosted control plane") // Adjust the timeout slightly to something self-hosting specific waiter.SetTimeout(selfHostingWaitTimeout) // Here the map of different mutators to use for the control plane's PodSpec is stored + glog.V(1).Infoln("getting mutators") mutators := GetMutatorsFromFeatureGates(cfg.FeatureGates) // Some extra work to be done if we should store the control plane certificates in Secrets @@ -82,12 +87,11 @@ func CreateSelfHostedControlPlane(manifestsDir, kubeConfigDir string, cfg *kubea continue } - // Load the Static Pod file in order to be able to create a self-hosted variant of that file - pod, err := volumeutil.LoadPodFromFile(manifestPath) + // Load the Static Pod spec in order to be able to create a self-hosted variant of that file + podSpec, err := loadPodSpecFromFile(manifestPath) if err != nil { return err } - podSpec := &pod.Spec // Build a DaemonSet object from the loaded PodSpec ds := BuildDaemonSet(componentName, podSpec, mutators) @@ -114,7 +118,7 @@ func CreateSelfHostedControlPlane(manifestsDir, kubeConfigDir string, cfg *kubea // Wait for the mirror Pod hash to be removed; otherwise we'll run into race conditions here when the kubelet hasn't had time to // remove the Static Pod (or the mirror Pod respectively). This implicitly also tests that the API server endpoint is healthy, // because this blocks until the API server returns a 404 Not Found when getting the Static Pod - staticPodName := fmt.Sprintf("%s-%s", componentName, cfg.NodeName) + staticPodName := fmt.Sprintf("%s-%s", componentName, cfg.NodeRegistration.Name) if err := waiter.WaitForPodToDisappear(staticPodName); err != nil { return err } @@ -171,3 +175,23 @@ func BuildSelfhostedComponentLabels(component string) map[string]string { func BuildSelfHostedComponentLabelQuery(componentName string) string { return fmt.Sprintf("k8s-app=%s", kubeadmconstants.AddSelfHostedPrefix(componentName)) } + +func loadPodSpecFromFile(filePath string) (*v1.PodSpec, error) { + podDef, err := ioutil.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("failed to read file path %s: %+v", filePath, err) + } + + if len(podDef) == 0 { + return nil, fmt.Errorf("file was empty: %s", filePath) + } + + codec := clientscheme.Codecs.UniversalDecoder() + pod := &v1.Pod{} + + if err = runtime.DecodeInto(codec, podDef, pod); err != nil { + return nil, fmt.Errorf("failed decoding pod: %v", err) + } + + return &pod.Spec, nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go index 5b30899d7..8d7e757f6 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go @@ -26,7 +26,6 @@ import ( apps "k8s.io/api/apps/v1" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/util" - volumeutil "k8s.io/kubernetes/pkg/volume/util" ) const ( @@ -494,11 +493,10 @@ func TestBuildDaemonSet(t *testing.T) { } defer os.Remove(tempFile) - pod, err := volumeutil.LoadPodFromFile(tempFile) + podSpec, err := loadPodSpecFromFile(tempFile) if err != nil { - t.Fatalf("couldn't load the specified Pod") + t.Fatalf("couldn't load the specified Pod Spec") } - podSpec := &pod.Spec ds := BuildDaemonSet(rt.component, podSpec, GetDefaultMutators()) dsBytes, err := util.MarshalToYaml(ds, apps.SchemeGroupVersion) @@ -517,6 +515,11 @@ func TestLoadPodSpecFromFile(t *testing.T) { content string expectError bool }{ + { + // No content + content: "", + expectError: true, + }, { // Good YAML content: ` @@ -570,11 +573,16 @@ spec: } defer os.Remove(tempFile) - _, err = volumeutil.LoadPodFromFile(tempFile) + _, err = loadPodSpecFromFile(tempFile) if (err != nil) != rt.expectError { t.Errorf("failed TestLoadPodSpecFromFile:\nexpected error:\n%t\nsaw:\n%v", rt.expectError, err) } } + + _, err := loadPodSpecFromFile("") + if err == nil { + t.Error("unexpected success: loadPodSpecFromFile should return error when no file is given") + } } func createTempFileWithContent(content []byte) (string, error) { diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/BUILD index 2ccac4815..81a36153a 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/BUILD @@ -4,7 +4,6 @@ go_library( name = "go_default_library", srcs = [ "compute.go", - "configuration.go", "health.go", "policy.go", "postupgrade.go", @@ -17,8 +16,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/images:go_default_library", @@ -29,15 +27,15 @@ go_library( "//cmd/kubeadm/app/phases/certs:go_default_library", "//cmd/kubeadm/app/phases/controlplane:go_default_library", "//cmd/kubeadm/app/phases/etcd:go_default_library", + "//cmd/kubeadm/app/phases/kubelet:go_default_library", + "//cmd/kubeadm/app/phases/patchnode:go_default_library", "//cmd/kubeadm/app/phases/selfhosting:go_default_library", "//cmd/kubeadm/app/phases/uploadconfig:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//cmd/kubeadm/app/util/config:go_default_library", "//cmd/kubeadm/app/util/dryrun:go_default_library", "//cmd/kubeadm/app/util/etcd:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//pkg/util/version:go_default_library", "//pkg/version:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", @@ -78,7 +76,8 @@ go_test( embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/phases/certs:go_default_library", "//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library", @@ -87,10 +86,13 @@ go_test( "//cmd/kubeadm/app/util/apiclient:go_default_library", "//cmd/kubeadm/app/util/etcd:go_default_library", "//cmd/kubeadm/test:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//pkg/util/version:go_default_library", "//vendor/github.com/coreos/etcd/clientv3:go_default_library", "//vendor/github.com/coreos/etcd/pkg/transport:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/compute.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/compute.go index dca2c9939..326951168 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/compute.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/compute.go @@ -20,11 +20,12 @@ import ( "fmt" "strings" + clientset "k8s.io/client-go/kubernetes" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns" etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd" - "k8s.io/kubernetes/pkg/util/version" + versionutil "k8s.io/kubernetes/pkg/util/version" ) // Upgrade defines an upgrade possibility to upgrade from a current version to a new one @@ -67,6 +68,8 @@ func ActiveDNSAddon(featureGates map[string]bool) string { type ClusterState struct { // KubeVersion describes the version of the Kubernetes API Server, Controller Manager, Scheduler and Proxy. KubeVersion string + // DNSType + DNSType string // DNSVersion describes the version of the kube-dns images used and manifest version DNSVersion string // KubeadmVersion describes the version of the kubeadm CLI @@ -79,7 +82,7 @@ type ClusterState struct { // GetAvailableUpgrades fetches all versions from the specified VersionGetter and computes which // kinds of upgrades can be performed -func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed bool, etcdClient etcdutil.ClusterInterrogator, featureGates map[string]bool) ([]Upgrade, error) { +func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed bool, etcdClient etcdutil.ClusterInterrogator, featureGates map[string]bool, client clientset.Interface) ([]Upgrade, error) { fmt.Println("[upgrade] Fetching available versions to upgrade to") // Collect the upgrades kubeadm can do in this list @@ -117,10 +120,16 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA return upgrades, err } + dnsType, dnsVersion, err := dns.DeployedDNSAddon(client) + if err != nil { + return nil, err + } + // Construct a descriptor for the current state of the world beforeState := ClusterState{ KubeVersion: clusterVersionStr, - DNSVersion: dns.GetDNSVersion(clusterVersion, ActiveDNSAddon(featureGates)), + DNSType: dnsType, + DNSVersion: dnsVersion, KubeadmVersion: kubeadmVersionStr, KubeletVersions: kubeletVersions, EtcdVersion: etcdVersion, @@ -163,7 +172,8 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA Before: beforeState, After: ClusterState{ KubeVersion: patchVersionStr, - DNSVersion: dns.GetDNSVersion(patchVersion, ActiveDNSAddon(featureGates)), + DNSType: ActiveDNSAddon(featureGates), + DNSVersion: kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)), KubeadmVersion: newKubeadmVer, EtcdVersion: getSuggestedEtcdVersion(patchVersionStr), // KubeletVersions is unset here as it is not used anywhere in .After @@ -179,7 +189,8 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA Before: beforeState, After: ClusterState{ KubeVersion: stableVersionStr, - DNSVersion: dns.GetDNSVersion(stableVersion, ActiveDNSAddon(featureGates)), + DNSType: ActiveDNSAddon(featureGates), + DNSVersion: kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)), KubeadmVersion: stableVersionStr, EtcdVersion: getSuggestedEtcdVersion(stableVersionStr), // KubeletVersions is unset here as it is not used anywhere in .After @@ -224,7 +235,8 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA Before: beforeState, After: ClusterState{ KubeVersion: previousBranchLatestVersionStr, - DNSVersion: dns.GetDNSVersion(previousBranchLatestVersion, ActiveDNSAddon(featureGates)), + DNSType: ActiveDNSAddon(featureGates), + DNSVersion: kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)), KubeadmVersion: previousBranchLatestVersionStr, EtcdVersion: getSuggestedEtcdVersion(previousBranchLatestVersionStr), // KubeletVersions is unset here as it is not used anywhere in .After @@ -237,12 +249,12 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA // Default to assume that the experimental version to show is the unstable one unstableKubeVersion := latestVersionStr - unstableKubeDNSVersion := dns.GetDNSVersion(latestVersion, ActiveDNSAddon(featureGates)) + unstableKubeDNSVersion := kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)) // Ẃe should not display alpha.0. The previous branch's beta/rc versions are more relevant due how the kube branching process works. if latestVersion.PreRelease() == "alpha.0" { unstableKubeVersion = previousBranchLatestVersionStr - unstableKubeDNSVersion = dns.GetDNSVersion(previousBranchLatestVersion, ActiveDNSAddon(featureGates)) + unstableKubeDNSVersion = kubeadmconstants.GetDNSVersion(ActiveDNSAddon(featureGates)) } upgrades = append(upgrades, Upgrade{ @@ -250,6 +262,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA Before: beforeState, After: ClusterState{ KubeVersion: unstableKubeVersion, + DNSType: ActiveDNSAddon(featureGates), DNSVersion: unstableKubeDNSVersion, KubeadmVersion: unstableKubeVersion, EtcdVersion: getSuggestedEtcdVersion(unstableKubeVersion), @@ -266,22 +279,23 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA } func getBranchFromVersion(version string) string { - return strings.TrimPrefix(version, "v")[:3] + v := versionutil.MustParseGeneric(version) + return fmt.Sprintf("%d.%d", v.Major(), v.Minor()) } -func patchVersionBranchExists(clusterVersion, stableVersion *version.Version) bool { +func patchVersionBranchExists(clusterVersion, stableVersion *versionutil.Version) bool { return stableVersion.AtLeast(clusterVersion) } -func patchUpgradePossible(clusterVersion, patchVersion *version.Version) bool { +func patchUpgradePossible(clusterVersion, patchVersion *versionutil.Version) bool { return clusterVersion.LessThan(patchVersion) } -func rcUpgradePossible(clusterVersion, previousBranchLatestVersion *version.Version) bool { +func rcUpgradePossible(clusterVersion, previousBranchLatestVersion *versionutil.Version) bool { return strings.HasPrefix(previousBranchLatestVersion.PreRelease(), "rc") && clusterVersion.LessThan(previousBranchLatestVersion) } -func minorUpgradePossibleWithPatchRelease(stableVersion, patchVersion *version.Version) bool { +func minorUpgradePossibleWithPatchRelease(stableVersion, patchVersion *versionutil.Version) bool { return patchVersion.LessThan(stableVersion) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/compute_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/compute_test.go index 55b211c8a..ee17ee76a 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/compute_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/compute_test.go @@ -23,6 +23,11 @@ import ( "time" "github.com/coreos/etcd/clientv3" + apps "k8s.io/api/apps/v1" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clientsetfake "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd" versionutil "k8s.io/kubernetes/pkg/util/version" ) @@ -51,7 +56,7 @@ func (f *fakeVersionGetter) VersionFromCILabel(ciVersionLabel, _ string) (string if ciVersionLabel == "latest" { return f.latestVersion, versionutil.MustParseSemantic(f.latestVersion), nil } - if ciVersionLabel == "latest-1.10" { + if ciVersionLabel == "latest-1.11" { return f.latestDevBranchVersion, versionutil.MustParseSemantic(f.latestDevBranchVersion), nil } return f.stablePatchVersion, versionutil.MustParseSemantic(f.stablePatchVersion), nil @@ -103,54 +108,106 @@ func (f fakeEtcdClient) GetClusterVersions() (map[string]string, error) { } func TestGetAvailableUpgrades(t *testing.T) { - featureGates := make(map[string]bool) etcdClient := fakeEtcdClient{} tests := []struct { - vg *fakeVersionGetter + name string + vg VersionGetter expectedUpgrades []Upgrade allowExperimental, allowRCs bool errExpected bool etcdClient etcdutil.ClusterInterrogator + beforeDNSType string + beforeDNSVersion string + featureGates map[string]bool }{ - { // no action needed, already up-to-date + { + name: "no action needed, already up-to-date", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.9.3", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.10.3", - stablePatchVersion: "v1.9.3", - stableVersion: "v1.9.3", + stablePatchVersion: "v1.10.3", + stableVersion: "v1.10.3", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "v1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{}, allowExperimental: false, errExpected: false, etcdClient: etcdClient, }, - { // simple patch version upgrade + { + name: "simple patch version upgrade", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.1", - kubeletVersion: "v1.9.1", // the kubelet are on the same version as the control plane - kubeadmVersion: "v1.9.2", + clusterVersion: "v1.10.1", + kubeletVersion: "v1.10.1", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.10.2", - stablePatchVersion: "v1.9.3", - stableVersion: "v1.9.3", + stablePatchVersion: "v1.10.3", + stableVersion: "v1.10.3", + }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), + expectedUpgrades: []Upgrade{ + { + Description: "version in the v1.10 series", + Before: ClusterState{ + KubeVersion: "v1.10.1", + KubeletVersions: map[string]uint16{ + "v1.10.1": 1, + }, + KubeadmVersion: "v1.10.2", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.1.12", + }, + After: ClusterState{ + KubeVersion: "v1.10.3", + KubeadmVersion: "v1.10.3", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.1.12", + }, + }, }, + allowExperimental: false, + errExpected: false, + etcdClient: etcdClient, + }, + { + name: "no version provided to offline version getter does not change behavior", + vg: NewOfflineVersionGetter(&fakeVersionGetter{ + clusterVersion: "v1.10.1", + kubeletVersion: "v1.10.1", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.10.2", + + stablePatchVersion: "v1.10.3", + stableVersion: "v1.10.3", + }, ""), + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { - Description: "version in the v1.9 series", + Description: "version in the v1.10 series", Before: ClusterState{ - KubeVersion: "v1.9.1", + KubeVersion: "v1.10.1", KubeletVersions: map[string]uint16{ - "v1.9.1": 1, + "v1.10.1": 1, }, - KubeadmVersion: "v1.9.2", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.2", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.9.3", - KubeadmVersion: "v1.9.3", - DNSVersion: "1.14.8", + KubeVersion: "v1.10.3", + KubeadmVersion: "v1.10.3", + DNSType: "coredns", + DNSVersion: "1.1.3", EtcdVersion: "3.1.12", }, }, @@ -159,32 +216,38 @@ func TestGetAvailableUpgrades(t *testing.T) { errExpected: false, etcdClient: etcdClient, }, - { // minor version upgrade only + { + name: "minor version upgrade only", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.1", - kubeletVersion: "v1.9.1", // the kubelet are on the same version as the control plane - kubeadmVersion: "v1.10.0", + clusterVersion: "v1.10.1", + kubeletVersion: "v1.10.1", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.11.0", - stablePatchVersion: "v1.9.1", - stableVersion: "v1.10.0", + stablePatchVersion: "v1.10.1", + stableVersion: "v1.11.0", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "stable version", Before: ClusterState{ - KubeVersion: "v1.9.1", + KubeVersion: "v1.10.1", KubeletVersions: map[string]uint16{ - "v1.9.1": 1, + "v1.10.1": 1, }, - KubeadmVersion: "v1.10.0", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.10.0", - KubeadmVersion: "v1.10.0", - DNSVersion: "1.14.8", - EtcdVersion: "3.1.12", + KubeVersion: "v1.11.0", + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", }, }, }, @@ -192,50 +255,58 @@ func TestGetAvailableUpgrades(t *testing.T) { errExpected: false, etcdClient: etcdClient, }, - { // both minor version upgrade and patch version upgrade available + { + name: "both minor version upgrade and patch version upgrade available", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", // the kubelet are on the same version as the control plane - kubeadmVersion: "v1.9.5", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.10.5", - stablePatchVersion: "v1.9.5", - stableVersion: "v1.10.1", + stablePatchVersion: "v1.10.5", + stableVersion: "v1.11.1", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { - Description: "version in the v1.9 series", + Description: "version in the v1.10 series", Before: ClusterState{ - KubeVersion: "v1.9.3", + KubeVersion: "v1.10.3", KubeletVersions: map[string]uint16{ - "v1.9.3": 1, + "v1.10.3": 1, }, - KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.5", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.9.5", - KubeadmVersion: "v1.9.5", // Note: The kubeadm version mustn't be "downgraded" here - DNSVersion: "1.14.8", + KubeVersion: "v1.10.5", + KubeadmVersion: "v1.10.5", // Note: The kubeadm version mustn't be "downgraded" here + DNSType: "coredns", + DNSVersion: "1.1.3", EtcdVersion: "3.1.12", }, }, { Description: "stable version", Before: ClusterState{ - KubeVersion: "v1.9.3", + KubeVersion: "v1.10.3", KubeletVersions: map[string]uint16{ - "v1.9.3": 1, + "v1.10.3": 1, }, - KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.5", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.10.1", - KubeadmVersion: "v1.10.1", - DNSVersion: "1.14.8", - EtcdVersion: "3.1.12", + KubeVersion: "v1.11.1", + KubeadmVersion: "v1.11.1", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", }, }, }, @@ -243,48 +314,58 @@ func TestGetAvailableUpgrades(t *testing.T) { errExpected: false, etcdClient: etcdClient, }, - { // allow experimental upgrades, but no upgrade available + { + name: "allow experimental upgrades, but no upgrade available", vg: &fakeVersionGetter{ - clusterVersion: "v1.10.0-alpha.2", - kubeletVersion: "v1.9.5", - kubeadmVersion: "v1.9.5", + clusterVersion: "v1.11.0-alpha.2", + kubeletVersion: "v1.10.5", + kubeadmVersion: "v1.10.5", - stablePatchVersion: "v1.9.5", - stableVersion: "v1.9.5", - latestVersion: "v1.10.0-alpha.2", + stablePatchVersion: "v1.10.5", + stableVersion: "v1.10.5", + latestVersion: "v1.11.0-alpha.2", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "v1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{}, allowExperimental: true, errExpected: false, etcdClient: etcdClient, }, - { // upgrade to an unstable version should be supported + { + name: "upgrade to an unstable version should be supported", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.5", - kubeletVersion: "v1.9.5", - kubeadmVersion: "v1.9.5", + clusterVersion: "v1.10.5", + kubeletVersion: "v1.10.5", + kubeadmVersion: "v1.10.5", - stablePatchVersion: "v1.9.5", - stableVersion: "v1.9.5", - latestVersion: "v1.10.0-alpha.2", + stablePatchVersion: "v1.10.5", + stableVersion: "v1.10.5", + latestVersion: "v1.11.0-alpha.2", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "experimental version", Before: ClusterState{ - KubeVersion: "v1.9.5", + KubeVersion: "v1.10.5", KubeletVersions: map[string]uint16{ - "v1.9.5": 1, + "v1.10.5": 1, }, - KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.5", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.10.0-alpha.2", - KubeadmVersion: "v1.10.0-alpha.2", - DNSVersion: "1.14.8", - EtcdVersion: "3.1.12", + KubeVersion: "v1.11.0-alpha.2", + KubeadmVersion: "v1.11.0-alpha.2", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", }, }, }, @@ -292,33 +373,39 @@ func TestGetAvailableUpgrades(t *testing.T) { errExpected: false, etcdClient: etcdClient, }, - { // upgrade from an unstable version to an unstable version should be supported + { + name: "upgrade from an unstable version to an unstable version should be supported", vg: &fakeVersionGetter{ - clusterVersion: "v1.10.0-alpha.1", - kubeletVersion: "v1.9.5", - kubeadmVersion: "v1.9.5", + clusterVersion: "v1.11.0-alpha.1", + kubeletVersion: "v1.10.5", + kubeadmVersion: "v1.10.5", - stablePatchVersion: "v1.9.5", - stableVersion: "v1.9.5", - latestVersion: "v1.10.0-alpha.2", + stablePatchVersion: "v1.10.5", + stableVersion: "v1.10.5", + latestVersion: "v1.11.0-alpha.2", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "experimental version", Before: ClusterState{ - KubeVersion: "v1.10.0-alpha.1", + KubeVersion: "v1.11.0-alpha.1", KubeletVersions: map[string]uint16{ - "v1.9.5": 1, + "v1.10.5": 1, }, - KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.5", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.10.0-alpha.2", - KubeadmVersion: "v1.10.0-alpha.2", - DNSVersion: "1.14.8", - EtcdVersion: "3.1.12", + KubeVersion: "v1.11.0-alpha.2", + KubeadmVersion: "v1.11.0-alpha.2", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", }, }, }, @@ -326,34 +413,40 @@ func TestGetAvailableUpgrades(t *testing.T) { errExpected: false, etcdClient: etcdClient, }, - { // v1.X.0-alpha.0 should be ignored + { + name: "v1.X.0-alpha.0 should be ignored", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.5", - kubeletVersion: "v1.9.5", - kubeadmVersion: "v1.9.5", - - stablePatchVersion: "v1.9.5", - stableVersion: "v1.9.5", - latestDevBranchVersion: "v1.10.0-beta.1", - latestVersion: "v1.11.0-alpha.0", + clusterVersion: "v1.10.5", + kubeletVersion: "v1.10.5", + kubeadmVersion: "v1.10.5", + + stablePatchVersion: "v1.10.5", + stableVersion: "v1.10.5", + latestDevBranchVersion: "v1.11.0-beta.1", + latestVersion: "v1.12.0-alpha.0", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "experimental version", Before: ClusterState{ - KubeVersion: "v1.9.5", + KubeVersion: "v1.10.5", KubeletVersions: map[string]uint16{ - "v1.9.5": 1, + "v1.10.5": 1, }, - KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.5", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.10.0-beta.1", - KubeadmVersion: "v1.10.0-beta.1", - DNSVersion: "1.14.8", - EtcdVersion: "3.1.12", + KubeVersion: "v1.11.0-beta.1", + KubeadmVersion: "v1.11.0-beta.1", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", }, }, }, @@ -361,34 +454,40 @@ func TestGetAvailableUpgrades(t *testing.T) { errExpected: false, etcdClient: etcdClient, }, - { // upgrade to an RC version should be supported + { + name: "upgrade to an RC version should be supported", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.5", - kubeletVersion: "v1.9.5", - kubeadmVersion: "v1.9.5", - - stablePatchVersion: "v1.9.5", - stableVersion: "v1.9.5", - latestDevBranchVersion: "v1.10.0-rc.1", - latestVersion: "v1.11.0-alpha.1", + clusterVersion: "v1.10.5", + kubeletVersion: "v1.10.5", + kubeadmVersion: "v1.10.5", + + stablePatchVersion: "v1.10.5", + stableVersion: "v1.10.5", + latestDevBranchVersion: "v1.11.0-rc.1", + latestVersion: "v1.12.0-alpha.1", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "release candidate version", Before: ClusterState{ - KubeVersion: "v1.9.5", + KubeVersion: "v1.10.5", KubeletVersions: map[string]uint16{ - "v1.9.5": 1, + "v1.10.5": 1, }, - KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.5", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.10.0-rc.1", - KubeadmVersion: "v1.10.0-rc.1", - DNSVersion: "1.14.8", - EtcdVersion: "3.1.12", + KubeVersion: "v1.11.0-rc.1", + KubeadmVersion: "v1.11.0-rc.1", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", }, }, }, @@ -396,34 +495,40 @@ func TestGetAvailableUpgrades(t *testing.T) { errExpected: false, etcdClient: etcdClient, }, - { // it is possible (but very uncommon) that the latest version from the previous branch is an rc and the current latest version is alpha.0. In that case, show the RC + { + name: "it is possible (but very uncommon) that the latest version from the previous branch is an rc and the current latest version is alpha.0. In that case, show the RC", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.5", - kubeletVersion: "v1.9.5", - kubeadmVersion: "v1.9.5", - - stablePatchVersion: "v1.9.5", - stableVersion: "v1.9.5", - latestDevBranchVersion: "v1.10.6-rc.1", - latestVersion: "v1.11.1-alpha.0", + clusterVersion: "v1.10.5", + kubeletVersion: "v1.10.5", + kubeadmVersion: "v1.10.5", + + stablePatchVersion: "v1.10.5", + stableVersion: "v1.10.5", + latestDevBranchVersion: "v1.11.6-rc.1", + latestVersion: "v1.12.1-alpha.0", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "experimental version", // Note that this is considered an experimental version in this uncommon scenario Before: ClusterState{ - KubeVersion: "v1.9.5", + KubeVersion: "v1.10.5", KubeletVersions: map[string]uint16{ - "v1.9.5": 1, + "v1.10.5": 1, }, - KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.5", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.10.6-rc.1", - KubeadmVersion: "v1.10.6-rc.1", - DNSVersion: "1.14.8", - EtcdVersion: "3.1.12", + KubeVersion: "v1.11.6-rc.1", + KubeadmVersion: "v1.11.6-rc.1", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", }, }, }, @@ -431,52 +536,60 @@ func TestGetAvailableUpgrades(t *testing.T) { errExpected: false, etcdClient: etcdClient, }, - { // upgrade to an RC version should be supported. There may also be an even newer unstable version. + { + name: "upgrade to an RC version should be supported. There may also be an even newer unstable version.", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.5", - kubeletVersion: "v1.9.5", - kubeadmVersion: "v1.9.5", - - stablePatchVersion: "v1.9.5", - stableVersion: "v1.9.5", - latestDevBranchVersion: "v1.10.0-rc.1", - latestVersion: "v1.11.0-alpha.2", + clusterVersion: "v1.10.5", + kubeletVersion: "v1.10.5", + kubeadmVersion: "v1.10.5", + + stablePatchVersion: "v1.10.5", + stableVersion: "v1.10.5", + latestDevBranchVersion: "v1.11.0-rc.1", + latestVersion: "v1.12.0-alpha.2", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "release candidate version", Before: ClusterState{ - KubeVersion: "v1.9.5", + KubeVersion: "v1.10.5", KubeletVersions: map[string]uint16{ - "v1.9.5": 1, + "v1.10.5": 1, }, - KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.5", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.10.0-rc.1", - KubeadmVersion: "v1.10.0-rc.1", - DNSVersion: "1.14.8", - EtcdVersion: "3.1.12", + KubeVersion: "v1.11.0-rc.1", + KubeadmVersion: "v1.11.0-rc.1", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", }, }, { Description: "experimental version", Before: ClusterState{ - KubeVersion: "v1.9.5", + KubeVersion: "v1.10.5", KubeletVersions: map[string]uint16{ - "v1.9.5": 1, + "v1.10.5": 1, }, - KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.8", + KubeadmVersion: "v1.10.5", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.11.0-alpha.2", - KubeadmVersion: "v1.11.0-alpha.2", - DNSVersion: "1.14.8", - EtcdVersion: "3.1.12", + KubeVersion: "v1.12.0-alpha.2", + KubeadmVersion: "v1.12.0-alpha.2", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", }, }, }, @@ -486,12 +599,13 @@ func TestGetAvailableUpgrades(t *testing.T) { etcdClient: etcdClient, }, { + name: "Upgrades with external etcd with mismatched versions should not be allowed.", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.9.3", - stablePatchVersion: "v1.9.3", - stableVersion: "v1.9.3", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.10.3", + stablePatchVersion: "v1.10.3", + stableVersion: "v1.10.3", }, allowRCs: false, allowExperimental: false, @@ -499,18 +613,158 @@ func TestGetAvailableUpgrades(t *testing.T) { expectedUpgrades: []Upgrade{}, errExpected: true, }, + { + name: "offline version getter", + vg: NewOfflineVersionGetter(&fakeVersionGetter{ + clusterVersion: "v1.11.1", + kubeletVersion: "v1.11.0", + kubeadmVersion: "v1.11.1", + }, "v1.12.1"), + etcdClient: etcdClient, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), + expectedUpgrades: []Upgrade{ + { + Description: "version in the v1.11 series", + Before: ClusterState{ + KubeVersion: "v1.11.1", + KubeletVersions: map[string]uint16{ + "v1.11.0": 1, + }, + KubeadmVersion: "v1.11.1", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.1.12", + }, + After: ClusterState{ + KubeVersion: "v1.12.1", + KubeadmVersion: "v1.12.1", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", + }, + }, + }, + }, + { + name: "kubedns to coredns", + vg: &fakeVersionGetter{ + clusterVersion: "v1.11.2", + kubeletVersion: "v1.11.2", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.12.0", + + stablePatchVersion: "v1.12.0", + stableVersion: "v1.12.0", + }, + etcdClient: etcdClient, + beforeDNSType: constants.KubeDNS, + beforeDNSVersion: "1.14.7", + featureGates: make(map[string]bool), + expectedUpgrades: []Upgrade{ + { + Description: "version in the v1.11 series", + Before: ClusterState{ + KubeVersion: "v1.11.2", + KubeletVersions: map[string]uint16{ + "v1.11.2": 1, + }, + KubeadmVersion: "v1.12.0", + DNSType: "kube-dns", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.12", + }, + After: ClusterState{ + KubeVersion: "v1.12.0", + KubeadmVersion: "v1.12.0", + DNSType: "coredns", + DNSVersion: "1.1.3", + EtcdVersion: "3.2.18", + }, + }, + }, + }, + { + name: "keep coredns", + vg: &fakeVersionGetter{ + clusterVersion: "v1.11.2", + kubeletVersion: "v1.11.2", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.12.0", + + stablePatchVersion: "v1.12.0", + stableVersion: "v1.12.0", + }, + etcdClient: etcdClient, + beforeDNSType: constants.KubeDNS, + beforeDNSVersion: "1.14.7", + featureGates: map[string]bool{"CoreDNS": false}, + expectedUpgrades: []Upgrade{ + { + Description: "version in the v1.11 series", + Before: ClusterState{ + KubeVersion: "v1.11.2", + KubeletVersions: map[string]uint16{ + "v1.11.2": 1, + }, + KubeadmVersion: "v1.12.0", + DNSType: "kube-dns", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.12", + }, + After: ClusterState{ + KubeVersion: "v1.12.0", + KubeadmVersion: "v1.12.0", + DNSType: "kube-dns", + DNSVersion: "1.14.10", + EtcdVersion: "3.2.18", + }, + }, + }, + }, } // Instantiating a fake etcd cluster for being able to get etcd version for a corresponding // kubernetes release. for _, rt := range tests { - actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs, rt.etcdClient, featureGates) - if !reflect.DeepEqual(actualUpgrades, rt.expectedUpgrades) { - t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades: %v\n\tgot: %v", rt.expectedUpgrades, actualUpgrades) - } - if (actualErr != nil) != rt.errExpected { - t.Errorf("failed TestGetAvailableUpgrades\n\texpected error: %t\n\tgot error: %t", rt.errExpected, (actualErr != nil)) - } + t.Run(rt.name, func(t *testing.T) { + + client := clientsetfake.NewSimpleClientset(&apps.Deployment{ + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: rt.beforeDNSType, + Namespace: "kube-system", + Labels: map[string]string{ + "k8s-app": "kube-dns", + }, + }, + Spec: apps.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Image: "test:" + rt.beforeDNSVersion, + }, + }, + }, + }, + }, + }) + + actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs, rt.etcdClient, rt.featureGates, client) + if !reflect.DeepEqual(actualUpgrades, rt.expectedUpgrades) { + t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades: %v\n\tgot: %v", rt.expectedUpgrades, actualUpgrades) + } + if (actualErr != nil) != rt.errExpected { + fmt.Printf("Hello error") + t.Errorf("failed TestGetAvailableUpgrades\n\texpected error: %t\n\tgot error: %t", rt.errExpected, (actualErr != nil)) + } + if !reflect.DeepEqual(actualUpgrades, rt.expectedUpgrades) { + t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades: %v\n\tgot: %v", rt.expectedUpgrades, actualUpgrades) + } + }) } } @@ -522,36 +776,36 @@ func TestKubeletUpgrade(t *testing.T) { }{ { // upgrade available before: map[string]uint16{ - "v1.9.1": 1, + "v1.10.1": 1, }, - after: "v1.9.3", + after: "v1.10.3", expected: true, }, { // upgrade available before: map[string]uint16{ - "v1.9.1": 1, - "v1.9.3": 100, + "v1.10.1": 1, + "v1.10.3": 100, }, - after: "v1.9.3", + after: "v1.10.3", expected: true, }, { // upgrade not available before: map[string]uint16{ - "v1.9.3": 1, + "v1.10.3": 1, }, - after: "v1.9.3", + after: "v1.10.3", expected: false, }, { // upgrade not available before: map[string]uint16{ - "v1.9.3": 100, + "v1.10.3": 100, }, - after: "v1.9.3", + after: "v1.10.3", expected: false, }, { // upgrade not available if we don't know anything about the earlier state before: map[string]uint16{}, - after: "v1.9.3", + after: "v1.10.3", expected: false, }, } @@ -572,3 +826,56 @@ func TestKubeletUpgrade(t *testing.T) { } } } + +func TestGetBranchFromVersion(t *testing.T) { + testCases := []struct { + version string + expectedVersion string + }{ + { + version: "v1.9.5", + expectedVersion: "1.9", + }, + { + version: "v1.9.0-alpha.2", + expectedVersion: "1.9", + }, + { + version: "v1.9.0-beta.0", + expectedVersion: "1.9", + }, + { + version: "v1.9.0-rc.1", + expectedVersion: "1.9", + }, + { + version: "v1.12.5", + expectedVersion: "1.12", + }, + { + version: "v1.11.0-alpha.0", + expectedVersion: "1.11", + }, + + { + version: "v1.11.0-beta.1", + expectedVersion: "1.11", + }, + { + version: "v1.11.0-rc.0", + expectedVersion: "1.11", + }, + { + version: "1.12.5", + expectedVersion: "1.12", + }, + } + + for _, tc := range testCases { + v := getBranchFromVersion(tc.version) + if v != tc.expectedVersion { + t.Errorf("expected version %s, got %s", tc.expectedVersion, v) + } + } + +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/configuration.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/configuration.go deleted file mode 100644 index 1d3fd5797..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/configuration.go +++ /dev/null @@ -1,128 +0,0 @@ -/* -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 upgrade - -import ( - "fmt" - "io" - "io/ioutil" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - clientset "k8s.io/client-go/kubernetes" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" - "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" - "k8s.io/kubernetes/cmd/kubeadm/app/constants" - configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" - "k8s.io/kubernetes/pkg/api/legacyscheme" -) - -// FetchConfiguration fetches configuration required for upgrading your cluster from a file (which has precedence) or a ConfigMap in the cluster -func FetchConfiguration(client clientset.Interface, w io.Writer, cfgPath string) (*kubeadmapiext.MasterConfiguration, error) { - fmt.Println("[upgrade/config] Making sure the configuration is correct:") - - // Load the configuration from a file or the cluster - configBytes, err := loadConfigurationBytes(client, w, cfgPath) - if err != nil { - return nil, err - } - - // Take the versioned configuration populated from the configmap, default it and validate - // Return the internal version of the API object - versionedcfg, err := bytesToValidatedMasterConfig(configBytes) - if err != nil { - return nil, fmt.Errorf("could not decode configuration: %v", err) - } - return versionedcfg, nil -} - -// FetchConfigurationFromFile fetch configuration from a file -func FetchConfigurationFromFile(cfgPath string) (*kubeadmapiext.MasterConfiguration, error) { - // Load the configuration from a file or the cluster - configBytes, err := ioutil.ReadFile(cfgPath) - if err != nil { - return nil, err - } - - // Take the versioned configuration populated from the configmap, default it and validate - // Return the internal version of the API object - versionedcfg, err := bytesToValidatedMasterConfig(configBytes) - if err != nil { - return nil, fmt.Errorf("could not decode configuration: %v", err) - } - return versionedcfg, nil -} - -// loadConfigurationBytes loads the configuration byte slice from either a file or the cluster ConfigMap -func loadConfigurationBytes(client clientset.Interface, w io.Writer, cfgPath string) ([]byte, error) { - if cfgPath != "" { - fmt.Printf("[upgrade/config] Reading configuration options from a file: %s\n", cfgPath) - return ioutil.ReadFile(cfgPath) - } - - fmt.Println("[upgrade/config] Reading configuration from the cluster...") - - configMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(constants.MasterConfigurationConfigMap, metav1.GetOptions{}) - if apierrors.IsNotFound(err) { - fmt.Printf("[upgrade/config] In order to upgrade, a ConfigMap called %q in the %s namespace must exist.\n", constants.MasterConfigurationConfigMap, metav1.NamespaceSystem) - fmt.Println("[upgrade/config] Without this information, 'kubeadm upgrade' won't know how to configure your upgraded cluster.") - fmt.Println("") - fmt.Println("[upgrade/config] Next steps:") - fmt.Printf("\t- OPTION 1: Run 'kubeadm config upload from-flags' and specify the same CLI arguments you passed to 'kubeadm init' when you created your master.\n") - fmt.Printf("\t- OPTION 2: Run 'kubeadm config upload from-file' and specify the same config file you passed to 'kubeadm init' when you created your master.\n") - fmt.Printf("\t- OPTION 3: Pass a config file to 'kubeadm upgrade' using the --config flag.\n") - fmt.Println("") - return []byte{}, fmt.Errorf("the ConfigMap %q in the %s namespace used for getting configuration information was not found", constants.MasterConfigurationConfigMap, metav1.NamespaceSystem) - } else if err != nil { - return []byte{}, fmt.Errorf("an unexpected error happened when trying to get the ConfigMap %q in the %s namespace: %v", constants.MasterConfigurationConfigMap, metav1.NamespaceSystem, err) - } - - fmt.Printf("[upgrade/config] FYI: You can look at this config file with 'kubectl -n %s get cm %s -oyaml'\n", metav1.NamespaceSystem, constants.MasterConfigurationConfigMap) - return []byte(configMap.Data[constants.MasterConfigurationConfigMapKey]), nil -} - -// bytesToValidatedMasterConfig converts a byte array to an external, defaulted and validated configuration object -func bytesToValidatedMasterConfig(b []byte) (*kubeadmapiext.MasterConfiguration, error) { - cfg := &kubeadmapiext.MasterConfiguration{} - finalCfg := &kubeadmapiext.MasterConfiguration{} - internalcfg := &kubeadmapi.MasterConfiguration{} - - decoded, err := kubeadmapiext.LoadYAML(b) - if err != nil { - return nil, fmt.Errorf("unable to decode config from bytes: %v", err) - } - - if err := kubeadmapiext.Migrate(decoded, cfg); err != nil { - return nil, fmt.Errorf("unable to migrate config from previous version: %v", err) - } - // Default and convert to the internal version - legacyscheme.Scheme.Default(cfg) - legacyscheme.Scheme.Convert(cfg, internalcfg, nil) - - // Applies dynamic defaults to settings not provided with flags - if err := configutil.SetInitDynamicDefaults(internalcfg); err != nil { - return nil, err - } - // Validates cfg (flags/configs + defaults + dynamic defaults) - if err := validation.ValidateMasterConfiguration(internalcfg).ToAggregate(); err != nil { - return nil, err - } - // Finally converts back to the external version - legacyscheme.Scheme.Convert(internalcfg, finalCfg, nil) - return finalCfg, nil -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/policy.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/policy.go index 807cd9dbe..25c5d4a20 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/policy.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/policy.go @@ -118,8 +118,7 @@ func EnforceVersionPolicies(versionGetter VersionGetter, newK8sVersionStr string if kubeadmVersion.Major() > newK8sVersion.Major() || kubeadmVersion.Minor() > newK8sVersion.Minor() { - skewErrors.Mandatory = append(skewErrors.Mandatory, fmt.Errorf("Kubeadm version %s can only be used to upgrade to Kubernetes versions %d.%d", kubeadmVersionStr, kubeadmVersion.Major(), kubeadmVersion.Minor())) - + skewErrors.Skippable = append(skewErrors.Skippable, fmt.Errorf("Kubeadm version %s can only be used to upgrade to Kubernetes version %d.%d", kubeadmVersionStr, kubeadmVersion.Major(), kubeadmVersion.Minor())) } // Detect if the version is unstable and the user didn't allow that diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/policy_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/policy_test.go index beb378193..ccf286127 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/policy_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/policy_test.go @@ -34,160 +34,162 @@ func TestEnforceVersionPolicies(t *testing.T) { { name: "minor upgrade", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.9.5", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.10.5", }, - newK8sVersion: "v1.9.5", + newK8sVersion: "v1.10.5", }, { name: "major upgrade", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.2", - kubeadmVersion: "v1.10.1", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.2", + kubeadmVersion: "v1.11.1", }, - newK8sVersion: "v1.10.0", + newK8sVersion: "v1.11.0", }, { name: "downgrade", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.9.3", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.10.3", }, - newK8sVersion: "v1.9.2", + newK8sVersion: "v1.10.2", }, { name: "same version upgrade", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.9.3", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.10.3", }, - newK8sVersion: "v1.9.3", + newK8sVersion: "v1.10.3", }, { - name: "new version must be higher than v1.9.0", + name: "new version must be higher than v1.10.0", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.9.3", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.10.3", }, - newK8sVersion: "v1.8.10", - expectedMandatoryErrs: 2, // version must be higher than v1.9.0, can't upgrade old k8s with newer kubeadm + newK8sVersion: "v1.9.10", + expectedMandatoryErrs: 1, // version must be higher than v1.10.0 + expectedSkippableErrs: 1, // can't upgrade old k8s with newer kubeadm }, { name: "upgrading two minor versions in one go is not supported", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.11.0", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.12.0", }, - newK8sVersion: "v1.11.0", + newK8sVersion: "v1.12.0", expectedMandatoryErrs: 1, // can't upgrade two minor versions expectedSkippableErrs: 1, // kubelet <-> apiserver skew too large }, { name: "downgrading two minor versions in one go is not supported", vg: &fakeVersionGetter{ - clusterVersion: "v1.11.3", - kubeletVersion: "v1.11.3", - kubeadmVersion: "v1.11.0", + clusterVersion: "v1.12.3", + kubeletVersion: "v1.12.3", + kubeadmVersion: "v1.12.0", }, - newK8sVersion: "v1.9.3", - expectedMandatoryErrs: 2, // can't downgrade two minor versions, can't upgrade old k8s with newer kubeadm + newK8sVersion: "v1.10.3", + expectedMandatoryErrs: 1, // can't downgrade two minor versions + expectedSkippableErrs: 1, // can't upgrade old k8s with newer kubeadm }, { name: "kubeadm version must be higher than the new kube version. However, patch version skews may be forced", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.9.3", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.10.3", }, - newK8sVersion: "v1.9.5", + newK8sVersion: "v1.10.5", expectedSkippableErrs: 1, }, { name: "kubeadm version must be higher than the new kube version. Trying to upgrade k8s to a higher minor version than kubeadm itself should never be supported", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.9.3", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.10.3", }, - newK8sVersion: "v1.10.0", + newK8sVersion: "v1.11.0", expectedMandatoryErrs: 1, }, { name: "the maximum skew between the cluster version and the kubelet versions should be one minor version. This may be forced through though.", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.8.8", - kubeadmVersion: "v1.10.0", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.9.8", + kubeadmVersion: "v1.11.0", }, - newK8sVersion: "v1.10.0", + newK8sVersion: "v1.11.0", expectedSkippableErrs: 1, }, { name: "experimental upgrades supported if the flag is set", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.10.0-beta.1", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.11.0-beta.1", }, - newK8sVersion: "v1.10.0-beta.1", + newK8sVersion: "v1.11.0-beta.1", allowExperimental: true, }, { name: "release candidate upgrades supported if the flag is set", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.10.0-rc.1", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.11.0-rc.1", }, - newK8sVersion: "v1.10.0-rc.1", + newK8sVersion: "v1.11.0-rc.1", allowRCs: true, }, { name: "release candidate upgrades supported if the flag is set", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.10.0-rc.1", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.11.0-rc.1", }, - newK8sVersion: "v1.10.0-rc.1", + newK8sVersion: "v1.11.0-rc.1", allowExperimental: true, }, { name: "the user should not be able to upgrade to an experimental version if they haven't opted into that", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.10.0-beta.1", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.11.0-beta.1", }, - newK8sVersion: "v1.10.0-beta.1", + newK8sVersion: "v1.11.0-beta.1", allowRCs: true, expectedSkippableErrs: 1, }, { name: "the user should not be able to upgrade to an release candidate version if they haven't opted into that", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.10.0-rc.1", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.11.0-rc.1", }, - newK8sVersion: "v1.10.0-rc.1", + newK8sVersion: "v1.11.0-rc.1", expectedSkippableErrs: 1, }, { name: "the user can't use a newer minor version of kubeadm to upgrade an older version of kubeadm", vg: &fakeVersionGetter{ - clusterVersion: "v1.9.3", - kubeletVersion: "v1.9.3", - kubeadmVersion: "v1.10.0", + clusterVersion: "v1.10.3", + kubeletVersion: "v1.10.3", + kubeadmVersion: "v1.11.0", }, - newK8sVersion: "v1.9.6", - expectedMandatoryErrs: 1, // can't upgrade old k8s with newer kubeadm + newK8sVersion: "v1.10.6", + expectedSkippableErrs: 1, // can't upgrade old k8s with newer kubeadm }, } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/postupgrade.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/postupgrade.go index fcfab59b0..15a0b2f5c 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/postupgrade.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/postupgrade.go @@ -18,6 +18,7 @@ package upgrade import ( "fmt" + "io/ioutil" "os" "path/filepath" "time" @@ -28,7 +29,7 @@ import ( clientset "k8s.io/client-go/kubernetes" certutil "k8s.io/client-go/util/cert" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns" @@ -36,6 +37,8 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo" nodebootstraptoken "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" + kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" + patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" "k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting" "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" @@ -43,7 +46,6 @@ import ( "k8s.io/kubernetes/pkg/util/version" ) -var v190alpha3 = version.MustParseSemantic("v1.9.0-alpha.3") var expiry = 180 * 24 * time.Hour // PerformPostUpgradeTasks runs nearly the same functions as 'kubeadm init' would do @@ -58,6 +60,23 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC errs = append(errs, err) } + // Create the new, version-branched kubelet ComponentConfig ConfigMap + if err := kubeletphase.CreateConfigMap(cfg, client); err != nil { + errs = append(errs, fmt.Errorf("error creating kubelet configuration ConfigMap: %v", err)) + } + + // Write the new kubelet config down to disk and the env file if needed + if err := writeKubeletConfigFiles(client, cfg, newK8sVer, dryRun); err != nil { + errs = append(errs, err) + } + + // Annotate the node with the crisocket information, sourced either from the MasterConfiguration struct or + // --cri-socket. + // TODO: In the future we want to use something more official like NodeStatus or similar for detecting this properly + if err := patchnodephase.AnnotateCRISocket(client, cfg.NodeRegistration.Name, cfg.NodeRegistration.CRISocket); err != nil { + errs = append(errs, fmt.Errorf("error uploading crisocket: %v", err)) + } + // Create/update RBAC rules that makes the bootstrap tokens able to post CSRs if err := nodebootstraptoken.AllowBootstrapTokensToPostCSRs(client); err != nil { errs = append(errs, err) @@ -74,7 +93,7 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC } // Upgrade to a self-hosted control plane if possible - if err := upgradeToSelfHosting(client, cfg, newK8sVer, dryRun); err != nil { + if err := upgradeToSelfHosting(client, cfg, dryRun); err != nil { errs = append(errs, err) } @@ -88,30 +107,18 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC errs = append(errs, err) } - certAndKeyDir := kubeadmapiext.DefaultCertificatesDir - shouldBackup, err := shouldBackupAPIServerCertAndKey(certAndKeyDir) - // Don't fail the upgrade phase if failing to determine to backup kube-apiserver cert and key. - if err != nil { - fmt.Printf("[postupgrade] WARNING: failed to determine to backup kube-apiserver cert and key: %v", err) - } else if shouldBackup { - // Don't fail the upgrade phase if failing to backup kube-apiserver cert and key. - if err := backupAPIServerCertAndKey(certAndKeyDir); err != nil { - fmt.Printf("[postupgrade] WARNING: failed to backup kube-apiserver cert and key: %v", err) - } - if err := certsphase.CreateAPIServerCertAndKeyFiles(cfg); err != nil { - errs = append(errs, err) - } + // Rotate the kube-apiserver cert and key if needed + if err := backupAPIServerCertIfNeeded(cfg, dryRun); err != nil { + errs = append(errs, err) } - // Upgrade kube-dns and kube-proxy + // Upgrade kube-dns/CoreDNS and kube-proxy if err := dns.EnsureDNSAddon(cfg, client); err != nil { errs = append(errs, err) } - // Remove the old kube-dns deployment if coredns is now used - if !dryRun { - if err := removeOldKubeDNSDeploymentIfCoreDNSIsUsed(cfg, client); err != nil { - errs = append(errs, err) - } + // Remove the old DNS deployment if a new DNS service is now used (kube-dns to CoreDNS or vice versa) + if err := removeOldDNSDeploymentIfAnotherDNSIsUsed(cfg, client, dryRun); err != nil { + errs = append(errs, err) } if err := proxy.EnsureProxyAddon(cfg, client); err != nil { @@ -120,28 +127,39 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC return errors.NewAggregate(errs) } -func removeOldKubeDNSDeploymentIfCoreDNSIsUsed(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { - if features.Enabled(cfg.FeatureGates, features.CoreDNS) { - return apiclient.TryRunCommand(func() error { - coreDNSDeployment, err := client.AppsV1().Deployments(metav1.NamespaceSystem).Get(kubeadmconstants.CoreDNS, metav1.GetOptions{}) +func removeOldDNSDeploymentIfAnotherDNSIsUsed(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface, dryRun bool) error { + return apiclient.TryRunCommand(func() error { + installedDeploymentName := kubeadmconstants.KubeDNS + deploymentToDelete := kubeadmconstants.CoreDNS + + if features.Enabled(cfg.FeatureGates, features.CoreDNS) { + installedDeploymentName = kubeadmconstants.CoreDNS + deploymentToDelete = kubeadmconstants.KubeDNS + } + + // If we're dry-running, we don't need to wait for the new DNS addon to become ready + if !dryRun { + dnsDeployment, err := client.AppsV1().Deployments(metav1.NamespaceSystem).Get(installedDeploymentName, metav1.GetOptions{}) if err != nil { return err } - if coreDNSDeployment.Status.ReadyReplicas == 0 { - return fmt.Errorf("the CoreDNS deployment isn't ready yet") + if dnsDeployment.Status.ReadyReplicas == 0 { + return fmt.Errorf("the DNS deployment isn't ready yet") } - err = apiclient.DeleteDeploymentForeground(client, metav1.NamespaceSystem, kubeadmconstants.KubeDNS) - if err != nil && !apierrors.IsNotFound(err) { - return err - } - return nil - }, 10) - } - return nil + } + + // We don't want to wait for the DNS deployment above to become ready when dryrunning (as it never will) + // but here we should execute the DELETE command against the dryrun clientset, as it will only be logged + err := apiclient.DeleteDeploymentForeground(client, metav1.NamespaceSystem, deploymentToDelete) + if err != nil && !apierrors.IsNotFound(err) { + return err + } + return nil + }, 10) } -func upgradeToSelfHosting(client clientset.Interface, cfg *kubeadmapi.MasterConfiguration, newK8sVer *version.Version, dryRun bool) error { - if features.Enabled(cfg.FeatureGates, features.SelfHosting) && !IsControlPlaneSelfHosted(client) && newK8sVer.AtLeast(v190alpha3) { +func upgradeToSelfHosting(client clientset.Interface, cfg *kubeadmapi.MasterConfiguration, dryRun bool) error { + if features.Enabled(cfg.FeatureGates, features.SelfHosting) && !IsControlPlaneSelfHosted(client) { waiter := getWaiter(dryRun, client) @@ -154,6 +172,69 @@ func upgradeToSelfHosting(client clientset.Interface, cfg *kubeadmapi.MasterConf return nil } +func backupAPIServerCertIfNeeded(cfg *kubeadmapi.MasterConfiguration, dryRun bool) error { + certAndKeyDir := kubeadmapiv1alpha2.DefaultCertificatesDir + shouldBackup, err := shouldBackupAPIServerCertAndKey(certAndKeyDir) + if err != nil { + // Don't fail the upgrade phase if failing to determine to backup kube-apiserver cert and key. + return fmt.Errorf("[postupgrade] WARNING: failed to determine to backup kube-apiserver cert and key: %v", err) + } + + if !shouldBackup { + return nil + } + + // If dry-running, just say that this would happen to the user and exit + if dryRun { + fmt.Println("[postupgrade] Would rotate the API server certificate and key.") + return nil + } + + // Don't fail the upgrade phase if failing to backup kube-apiserver cert and key, just continue rotating the cert + // TODO: We might want to reconsider this choice. + if err := backupAPIServerCertAndKey(certAndKeyDir); err != nil { + fmt.Printf("[postupgrade] WARNING: failed to backup kube-apiserver cert and key: %v", err) + } + return certsphase.CreateAPIServerCertAndKeyFiles(cfg) +} + +func writeKubeletConfigFiles(client clientset.Interface, cfg *kubeadmapi.MasterConfiguration, newK8sVer *version.Version, dryRun bool) error { + kubeletDir, err := getKubeletDir(dryRun) + if err != nil { + // The error here should never occur in reality, would only be thrown if /tmp doesn't exist on the machine. + return err + } + errs := []error{} + // Write the configuration for the kubelet down to disk so the upgraded kubelet can start with fresh config + if err := kubeletphase.DownloadConfig(client, newK8sVer, kubeletDir); err != nil { + // Tolerate the error being NotFound when dryrunning, as there is a pretty common scenario: the dryrun process + // *would* post the new kubelet-config-1.X configmap that doesn't exist now when we're trying to download it + // again. + if !(apierrors.IsNotFound(err) && dryRun) { + errs = append(errs, fmt.Errorf("error downloading kubelet configuration from the ConfigMap: %v", err)) + } + } + + if dryRun { // Print what contents would be written + dryrunutil.PrintDryRunFile(kubeadmconstants.KubeletConfigurationFileName, kubeletDir, kubeadmconstants.KubeletRunDirectory, os.Stdout) + } + + envFilePath := filepath.Join(kubeadmconstants.KubeletRunDirectory, kubeadmconstants.KubeletEnvFileName) + if _, err := os.Stat(envFilePath); os.IsNotExist(err) { + // Write env file with flags for the kubelet to use. We do not need to write the --register-with-taints for the master, + // as we handle that ourselves in the markmaster phase + // TODO: Maybe we want to do that some time in the future, in order to remove some logic from the markmaster phase? + if err := kubeletphase.WriteKubeletDynamicEnvFile(&cfg.NodeRegistration, cfg.FeatureGates, false, kubeletDir); err != nil { + errs = append(errs, fmt.Errorf("error writing a dynamic environment file for the kubelet: %v", err)) + } + + if dryRun { // Print what contents would be written + dryrunutil.PrintDryRunFile(kubeadmconstants.KubeletEnvFileName, kubeletDir, kubeadmconstants.KubeletRunDirectory, os.Stdout) + } + } + return errors.NewAggregate(errs) +} + // getWaiter gets the right waiter implementation for the right occasion // TODO: Consolidate this with what's in init.go? func getWaiter(dryRun bool, client clientset.Interface) apiclient.Waiter { @@ -163,6 +244,15 @@ func getWaiter(dryRun bool, client clientset.Interface) apiclient.Waiter { return apiclient.NewKubeWaiter(client, 30*time.Minute, os.Stdout) } +// getKubeletDir gets the kubelet directory based on whether the user is dry-running this command or not. +// TODO: Consolidate this with similar funcs? +func getKubeletDir(dryRun bool) (string, error) { + if dryRun { + return ioutil.TempDir("", "kubeadm-upgrade-dryrun") + } + return kubeadmconstants.KubeletRunDirectory, nil +} + // backupAPIServerCertAndKey backups the old cert and key of kube-apiserver to a specified directory. func backupAPIServerCertAndKey(certAndKeyDir string) error { subDir := filepath.Join(certAndKeyDir, "expired") diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go index 652dee2e4..c25387e8e 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go @@ -131,9 +131,9 @@ func TestRollbackFiles(t *testing.T) { func TestShouldBackupAPIServerCertAndKey(t *testing.T) { cfg := &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - NodeName: "test-node", + API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "test-node"}, } for desc, test := range map[string]struct { diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/prepull.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/prepull.go index c3ec257a7..848c5f580 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/prepull.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/prepull.go @@ -87,7 +87,7 @@ func (d *DaemonSetPrepuller) DeleteFunc(component string) error { // PrepullImagesInParallel creates DaemonSets synchronously but waits in parallel for the images to pull func PrepullImagesInParallel(kubePrepuller Prepuller, timeout time.Duration) error { - componentsToPrepull := constants.MasterComponents + componentsToPrepull := append(constants.MasterComponents, constants.Etcd) fmt.Printf("[upgrade/prepull] Will prepull images for components %v\n", componentsToPrepull) timeoutChan := time.After(timeout) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods.go index 488a85063..33b1a0dae 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods.go @@ -51,6 +51,8 @@ type StaticPodPathManager interface { BackupManifestDir() string // BackupEtcdDir should point to the backup directory used for backuping manifests during the transition BackupEtcdDir() string + // CleanupDirs cleans up all temporary directories + CleanupDirs() error } // KubeStaticPodPathManager is a real implementation of StaticPodPathManager that is used when upgrading a static pod cluster @@ -59,34 +61,39 @@ type KubeStaticPodPathManager struct { tempManifestDir string backupManifestDir string backupEtcdDir string + + keepManifestDir bool + keepEtcdDir bool } // NewKubeStaticPodPathManager creates a new instance of KubeStaticPodPathManager -func NewKubeStaticPodPathManager(realDir, tempDir, backupDir, backupEtcdDir string) StaticPodPathManager { +func NewKubeStaticPodPathManager(realDir, tempDir, backupDir, backupEtcdDir string, keepManifestDir, keepEtcdDir bool) StaticPodPathManager { return &KubeStaticPodPathManager{ realManifestDir: realDir, tempManifestDir: tempDir, backupManifestDir: backupDir, backupEtcdDir: backupEtcdDir, + keepManifestDir: keepManifestDir, + keepEtcdDir: keepEtcdDir, } } // NewKubeStaticPodPathManagerUsingTempDirs creates a new instance of KubeStaticPodPathManager with temporary directories backing it -func NewKubeStaticPodPathManagerUsingTempDirs(realManifestDir string) (StaticPodPathManager, error) { +func NewKubeStaticPodPathManagerUsingTempDirs(realManifestDir string, saveManifestsDir, saveEtcdDir bool) (StaticPodPathManager, error) { upgradedManifestsDir, err := constants.CreateTempDirForKubeadm("kubeadm-upgraded-manifests") if err != nil { return nil, err } - backupManifestsDir, err := constants.CreateTempDirForKubeadm("kubeadm-backup-manifests") + backupManifestsDir, err := constants.CreateTimestampDirForKubeadm("kubeadm-backup-manifests") if err != nil { return nil, err } - backupEtcdDir, err := constants.CreateTempDirForKubeadm("kubeadm-backup-etcd") + backupEtcdDir, err := constants.CreateTimestampDirForKubeadm("kubeadm-backup-etcd") if err != nil { return nil, err } - return NewKubeStaticPodPathManager(realManifestDir, upgradedManifestsDir, backupManifestsDir, backupEtcdDir), nil + return NewKubeStaticPodPathManager(realManifestDir, upgradedManifestsDir, backupManifestsDir, backupEtcdDir, saveManifestsDir, saveEtcdDir), nil } // MoveFile should move a file from oldPath to newPath @@ -129,6 +136,26 @@ func (spm *KubeStaticPodPathManager) BackupEtcdDir() string { return spm.backupEtcdDir } +// CleanupDirs cleans up all temporary directories except those the user has requested to keep around +func (spm *KubeStaticPodPathManager) CleanupDirs() error { + if err := os.RemoveAll(spm.TempManifestDir()); err != nil { + return err + } + if !spm.keepManifestDir { + if err := os.RemoveAll(spm.BackupManifestDir()); err != nil { + return err + } + } + + if !spm.keepEtcdDir { + if err := os.RemoveAll(spm.BackupEtcdDir()); err != nil { + return err + } + } + + return nil +} + func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.MasterConfiguration, beforePodHash string, recoverManifests map[string]string, isTLSUpgrade bool) error { // Special treatment is required for etcd case, when rollbackOldManifests should roll back etcd // manifests only for the case when component is Etcd @@ -206,7 +233,7 @@ func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticP // notice the removal of the Static Pod, leading to a false positive below where we check that the API endpoint is healthy // If we don't do this, there is a case where we remove the Static Pod manifest, kubelet is slow to react, kubeadm checks the // API endpoint below of the OLD Static Pod component and proceeds quickly enough, which might lead to unexpected results. - if err := waiter.WaitForStaticPodHashChange(cfg.NodeName, component, beforePodHash); err != nil { + if err := waiter.WaitForStaticPodHashChange(cfg.NodeRegistration.Name, component, beforePodHash); err != nil { return rollbackOldManifests(recoverManifests, err, pathMgr, recoverEtcd) } @@ -226,7 +253,7 @@ func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticP // performEtcdStaticPodUpgrade performs upgrade of etcd, it returns bool which indicates fatal error or not and the actual error. func performEtcdStaticPodUpgrade(waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.MasterConfiguration, recoverManifests map[string]string, isTLSUpgrade bool, oldEtcdClient, newEtcdClient etcdutil.ClusterInterrogator) (bool, error) { // Add etcd static pod spec only if external etcd is not configured - if len(cfg.Etcd.Endpoints) != 0 { + if cfg.Etcd.External != nil { return false, fmt.Errorf("external etcd detected, won't try to change any etcd state") } @@ -238,7 +265,7 @@ func performEtcdStaticPodUpgrade(waiter apiclient.Waiter, pathMgr StaticPodPathM // Backing up etcd data store backupEtcdDir := pathMgr.BackupEtcdDir() - runningEtcdDir := cfg.Etcd.DataDir + runningEtcdDir := cfg.Etcd.Local.DataDir if err := util.CopyDir(runningEtcdDir, backupEtcdDir); err != nil { return true, fmt.Errorf("failed to back up etcd data: %v", err) } @@ -266,7 +293,7 @@ func performEtcdStaticPodUpgrade(waiter apiclient.Waiter, pathMgr StaticPodPathM return false, nil } - beforeEtcdPodHash, err := waiter.WaitForStaticPodSingleHash(cfg.NodeName, constants.Etcd) + beforeEtcdPodHash, err := waiter.WaitForStaticPodSingleHash(cfg.NodeRegistration.Name, constants.Etcd) if err != nil { return true, fmt.Errorf("failed to get etcd pod's hash: %v", err) } @@ -376,20 +403,20 @@ func StaticPodControlPlane(waiter apiclient.Waiter, pathMgr StaticPodPathManager var isTLSUpgrade bool var isExternalEtcd bool - beforePodHashMap, err := waiter.WaitForStaticPodControlPlaneHashes(cfg.NodeName) + beforePodHashMap, err := waiter.WaitForStaticPodControlPlaneHashes(cfg.NodeRegistration.Name) if err != nil { return err } if oldEtcdClient == nil { - if len(cfg.Etcd.Endpoints) > 0 { + if cfg.Etcd.External != nil { // External etcd isExternalEtcd = true client, err := etcdutil.New( - cfg.Etcd.Endpoints, - cfg.Etcd.CAFile, - cfg.Etcd.CertFile, - cfg.Etcd.KeyFile, + cfg.Etcd.External.Endpoints, + cfg.Etcd.External.CAFile, + cfg.Etcd.External.CertFile, + cfg.Etcd.External.KeyFile, ) if err != nil { return fmt.Errorf("failed to create etcd client for external etcd: %v", err) @@ -449,11 +476,7 @@ func StaticPodControlPlane(waiter apiclient.Waiter, pathMgr StaticPodPathManager // Remove the temporary directories used on a best-effort (don't fail if the calls error out) // The calls are set here by design; we should _not_ use "defer" above as that would remove the directories // even in the "fail and rollback" case, where we want the directories preserved for the user. - os.RemoveAll(pathMgr.TempManifestDir()) - os.RemoveAll(pathMgr.BackupManifestDir()) - os.RemoveAll(pathMgr.BackupEtcdDir()) - - return nil + return pathMgr.CleanupDirs() } // rollbackOldManifests rolls back the backed-up manifests if something went wrong. @@ -482,7 +505,7 @@ func rollbackOldManifests(oldManifests map[string]string, origErr error, pathMgr // When the folder contents are successfully rolled back, nil is returned, otherwise an error is returned. func rollbackEtcdData(cfg *kubeadmapi.MasterConfiguration, pathMgr StaticPodPathManager) error { backupEtcdDir := pathMgr.BackupEtcdDir() - runningEtcdDir := cfg.Etcd.DataDir + runningEtcdDir := cfg.Etcd.Local.DataDir if err := util.CopyDir(backupEtcdDir, runningEtcdDir); err != nil { // Let the user know there we're problems, but we tried to reçover diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods_test.go index 7561c323a..9a4fe92f9 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods_test.go @@ -30,14 +30,14 @@ import ( "github.com/coreos/etcd/pkg/transport" "k8s.io/apimachinery/pkg/runtime" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/constants" certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane" etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd" - "k8s.io/kubernetes/pkg/api/legacyscheme" ) const ( @@ -46,27 +46,19 @@ const ( waitForPodsWithLabel = "wait-for-pods-with-label" testConfiguration = ` +apiVersion: kubeadm.k8s.io/v1alpha2 +kind: MasterConfiguration api: advertiseAddress: 1.2.3.4 bindPort: 6443 apiServerCertSANs: null apiServerExtraArgs: null -authorizationModes: -- Node -- RBAC certificatesDir: %s -cloudProvider: "" controllerManagerExtraArgs: null etcd: - caFile: "" - certFile: "" - dataDir: %s - endpoints: null - extraArgs: null - image: "" - keyFile: "" - serverCertSANs: null - peerCertSANs: null + local: + dataDir: %s + image: "" featureFlags: null imageRepository: k8s.gcr.io kubernetesVersion: %s @@ -74,7 +66,9 @@ networking: dnsDomain: cluster.local podSubnet: "" serviceSubnet: 10.96.0.0/12 -nodeName: thegopher +nodeRegistration: + name: foo + criSocket: "" schedulerExtraArgs: null token: ce3aa5.5ec8455bb76b379f tokenTTL: 24h @@ -209,6 +203,16 @@ func (spm *fakeStaticPodPathManager) BackupEtcdDir() string { return spm.backupEtcdDir } +func (spm *fakeStaticPodPathManager) CleanupDirs() error { + if err := os.RemoveAll(spm.TempManifestDir()); err != nil { + return err + } + if err := os.RemoveAll(spm.BackupManifestDir()); err != nil { + return err + } + return os.RemoveAll(spm.BackupEtcdDir()) +} + type fakeTLSEtcdClient struct{ TLS bool } func (c fakeTLSEtcdClient) HasTLS() bool { @@ -509,12 +513,91 @@ func getAPIServerHash(dir string) (string, error) { return fmt.Sprintf("%x", sha256.Sum256(fileBytes)), nil } +// TODO: Make this test function use the rest of the "official" API machinery helper funcs we have inside of kubeadm func getConfig(version, certsDir, etcdDataDir string) (*kubeadmapi.MasterConfiguration, error) { - externalcfg := &kubeadmapiv1alpha1.MasterConfiguration{} + externalcfg := &kubeadmapiv1alpha2.MasterConfiguration{} internalcfg := &kubeadmapi.MasterConfiguration{} - if err := runtime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), []byte(fmt.Sprintf(testConfiguration, certsDir, etcdDataDir, version)), externalcfg); err != nil { + if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), []byte(fmt.Sprintf(testConfiguration, certsDir, etcdDataDir, version)), externalcfg); err != nil { return nil, fmt.Errorf("unable to decode config: %v", err) } - legacyscheme.Scheme.Convert(externalcfg, internalcfg, nil) + kubeadmscheme.Scheme.Convert(externalcfg, internalcfg, nil) return internalcfg, nil } + +func getTempDir(t *testing.T, name string) (string, func()) { + dir, err := ioutil.TempDir(os.TempDir(), name) + if err != nil { + t.Fatalf("couldn't make temporary directory: %v", err) + } + + return dir, func() { + os.RemoveAll(dir) + } +} + +func TestCleanupDirs(t *testing.T) { + tests := []struct { + name string + keepManifest, keepEtcd bool + }{ + { + name: "save manifest backup", + keepManifest: true, + }, + { + name: "save both etcd and manifest", + keepManifest: true, + keepEtcd: true, + }, + { + name: "save nothing", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + realManifestDir, cleanup := getTempDir(t, "realManifestDir") + defer cleanup() + + tempManifestDir, cleanup := getTempDir(t, "tempManifestDir") + defer cleanup() + + backupManifestDir, cleanup := getTempDir(t, "backupManifestDir") + defer cleanup() + + backupEtcdDir, cleanup := getTempDir(t, "backupEtcdDir") + defer cleanup() + + mgr := NewKubeStaticPodPathManager(realManifestDir, tempManifestDir, backupManifestDir, backupEtcdDir, test.keepManifest, test.keepEtcd) + err := mgr.CleanupDirs() + if err != nil { + t.Errorf("unexpected error cleaning up: %v", err) + } + + if _, err := os.Stat(tempManifestDir); !os.IsNotExist(err) { + t.Errorf("%q should not have existed", tempManifestDir) + } + _, err = os.Stat(backupManifestDir) + if test.keepManifest { + if err != nil { + t.Errorf("unexpected error getting backup manifest dir") + } + } else { + if !os.IsNotExist(err) { + t.Error("expected backup manifest to not exist") + } + } + + _, err = os.Stat(backupEtcdDir) + if test.keepEtcd { + if err != nil { + t.Errorf("unexpected error getting backup etcd dir") + } + } else { + if !os.IsNotExist(err) { + t.Error("expected backup etcd dir to not exist") + } + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/versiongetter.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/versiongetter.go index 13c65294e..d9c9d69aa 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/versiongetter.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/versiongetter.go @@ -122,3 +122,30 @@ func computeKubeletVersions(nodes []v1.Node) map[string]uint16 { } return kubeletVersions } + +// OfflineVersionGetter will use the version provided or +type OfflineVersionGetter struct { + VersionGetter + version string +} + +// NewOfflineVersionGetter wraps a VersionGetter and skips online communication if default information is supplied. +// Version can be "" and the behavior will be identical to the versionGetter passed in. +func NewOfflineVersionGetter(versionGetter VersionGetter, version string) VersionGetter { + return &OfflineVersionGetter{ + VersionGetter: versionGetter, + version: version, + } +} + +// VersionFromCILabel will return the version that was passed into the struct +func (o *OfflineVersionGetter) VersionFromCILabel(ciVersionLabel, description string) (string, *versionutil.Version, error) { + if o.version == "" { + return o.VersionGetter.VersionFromCILabel(ciVersionLabel, description) + } + ver, err := versionutil.ParseSemantic(o.version) + if err != nil { + return "", nil, fmt.Errorf("Couldn't parse version %s: %v", description, err) + } + return o.version, ver, nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/BUILD index eac5ac9a2..faa9a5ae4 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/BUILD @@ -12,11 +12,11 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//pkg/api/legacyscheme:go_default_library", - "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", @@ -42,9 +42,9 @@ go_test( embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go index 42ed20d47..7445b4361 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go @@ -19,31 +19,33 @@ package uploadconfig import ( "fmt" - "github.com/ghodss/yaml" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - "k8s.io/kubernetes/pkg/api/legacyscheme" ) // UploadConfiguration saves the MasterConfiguration used for later reference (when upgrading for instance) func UploadConfiguration(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { - fmt.Printf("[uploadconfig] Storing the configuration used in ConfigMap %q in the %q Namespace\n", kubeadmconstants.MasterConfigurationConfigMap, metav1.NamespaceSystem) + fmt.Printf("[uploadconfig] storing the configuration used in ConfigMap %q in the %q Namespace\n", kubeadmconstants.MasterConfigurationConfigMap, metav1.NamespaceSystem) // Convert cfg to the external version as that's the only version of the API that can be deserialized later - externalcfg := &kubeadmapiext.MasterConfiguration{} - legacyscheme.Scheme.Convert(cfg, externalcfg, nil) + externalcfg := &kubeadmapiv1alpha2.MasterConfiguration{} + kubeadmscheme.Scheme.Convert(cfg, externalcfg, nil) // Removes sensitive info from the data that will be stored in the config map - externalcfg.Token = "" + externalcfg.BootstrapTokens = nil + // Clear the NodeRegistration object. + externalcfg.NodeRegistration = kubeadmapiv1alpha2.NodeRegistrationOptions{} - cfgYaml, err := yaml.Marshal(*externalcfg) + cfgYaml, err := util.MarshalToYamlForCodecs(externalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, scheme.Codecs) if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go index 69b6fd783..327f4f9e2 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go @@ -25,9 +25,9 @@ import ( clientsetfake "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/pkg/api/legacyscheme" ) func TestUploadConfiguration(t *testing.T) { @@ -63,8 +63,19 @@ func TestUploadConfiguration(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cfg := &kubeadmapi.MasterConfiguration{ - KubernetesVersion: "1.7.3", - Token: "1234567", + KubernetesVersion: "v1.10.3", + BootstrapTokens: []kubeadmapi.BootstrapToken{ + { + Token: &kubeadmapi.BootstrapTokenString{ + ID: "abcdef", + Secret: "abcdef0123456789", + }, + }, + }, + NodeRegistration: kubeadmapi.NodeRegistrationOptions{ + Name: "node-foo", + CRISocket: "/var/run/custom-cri.sock", + }, } client := clientsetfake.NewSimpleClientset() if tt.errOnCreate != nil { @@ -96,22 +107,36 @@ func TestUploadConfiguration(t *testing.T) { t.Errorf("Fail to find ConfigMap key") } - decodedExtCfg := &kubeadmapiext.MasterConfiguration{} + decodedExtCfg := &kubeadmapiv1alpha2.MasterConfiguration{} decodedCfg := &kubeadmapi.MasterConfiguration{} - if err := runtime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), []byte(configData), decodedExtCfg); err != nil { + if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), []byte(configData), decodedExtCfg); err != nil { t.Errorf("unable to decode config from bytes: %v", err) } // Default and convert to the internal version - legacyscheme.Scheme.Default(decodedExtCfg) - legacyscheme.Scheme.Convert(decodedExtCfg, decodedCfg, nil) + kubeadmscheme.Scheme.Default(decodedExtCfg) + kubeadmscheme.Scheme.Convert(decodedExtCfg, decodedCfg, nil) if decodedCfg.KubernetesVersion != cfg.KubernetesVersion { t.Errorf("Decoded value doesn't match, decoded = %#v, expected = %#v", decodedCfg.KubernetesVersion, cfg.KubernetesVersion) } - if decodedCfg.Token != "" { - t.Errorf("Decoded value contains token (sensitive info), decoded = %#v, expected = empty", decodedCfg.Token) + // If the decoded cfg has a BootstrapTokens array, verify the sensitive information we had isn't still there. + if len(decodedCfg.BootstrapTokens) > 0 && decodedCfg.BootstrapTokens[0].Token != nil && decodedCfg.BootstrapTokens[0].Token.String() == cfg.BootstrapTokens[0].Token.String() { + t.Errorf("Decoded value contains .BootstrapTokens (sensitive info), decoded = %#v, expected = empty", decodedCfg.BootstrapTokens) + } + + // Make sure no information from NodeRegistrationOptions was uploaded. + if decodedCfg.NodeRegistration.Name == cfg.NodeRegistration.Name || decodedCfg.NodeRegistration.CRISocket != kubeadmapiv1alpha2.DefaultCRISocket { + t.Errorf("Decoded value contains .NodeRegistration (node-specific info shouldn't be uploaded), decoded = %#v, expected = empty", decodedCfg.NodeRegistration) + } + + if decodedExtCfg.Kind != "MasterConfiguration" { + t.Errorf("Expected kind MasterConfiguration, got %v", decodedExtCfg.Kind) + } + + if decodedExtCfg.APIVersion != "kubeadm.k8s.io/v1alpha2" { + t.Errorf("Expected apiVersion kubeadm.k8s.io/v1alpha2, got %v", decodedExtCfg.APIVersion) } } }) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/BUILD index d81a5fbd4..aae4c5d45 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/BUILD @@ -49,21 +49,19 @@ go_library( }), importpath = "k8s.io/kubernetes/cmd/kubeadm/app/preflight", deps = [ - "//cmd/kube-apiserver/app/options:go_default_library", - "//cmd/kube-controller-manager/app/options:go_default_library", - "//cmd/kube-scheduler/app:go_default_library", "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", - "//pkg/apis/core/validation:go_default_library", - "//pkg/kubeapiserver/authorizer/modes:go_default_library", + "//cmd/kubeadm/app/images:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", "//pkg/util/initsystem:go_default_library", + "//pkg/util/ipvs:go_default_library", "//pkg/util/version:go_default_library", "//pkg/version:go_default_library", "//test/e2e_node/system:go_default_library", "//vendor/github.com/PuerkitoBio/purell:go_default_library", "//vendor/github.com/blang/semver:go_default_library", - "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks.go index a5168bd80..28d98e6eb 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks.go @@ -19,6 +19,8 @@ package preflight import ( "bufio" "bytes" + "crypto/tls" + "crypto/x509" "encoding/json" "errors" "fmt" @@ -26,32 +28,26 @@ import ( "io/ioutil" "net" "net/http" + "net/url" "os" "path/filepath" "runtime" "strings" "time" - "crypto/tls" - "crypto/x509" - "github.com/PuerkitoBio/purell" "github.com/blang/semver" - "github.com/spf13/pflag" - - "net/url" + "github.com/golang/glog" netutil "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/sets" - apiservoptions "k8s.io/kubernetes/cmd/kube-apiserver/app/options" - cmoptions "k8s.io/kubernetes/cmd/kube-controller-manager/app/options" - schedulerapp "k8s.io/kubernetes/cmd/kube-scheduler/app" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmdefaults "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/pkg/apis/core/validation" - authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" + "k8s.io/kubernetes/cmd/kubeadm/app/images" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" "k8s.io/kubernetes/pkg/util/initsystem" + ipvsutil "k8s.io/kubernetes/pkg/util/ipvs" versionutil "k8s.io/kubernetes/pkg/util/version" kubeadmversion "k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/test/e2e_node/system" @@ -61,6 +57,8 @@ import ( const ( bridgenf = "/proc/sys/net/bridge/bridge-nf-call-iptables" bridgenf6 = "/proc/sys/net/bridge/bridge-nf-call-ip6tables" + ipv4Forward = "/proc/sys/net/ipv4/ip_forward" + ipv6DefaultForwarding = "/proc/sys/net/ipv6/conf/default/forwarding" externalEtcdRequestTimeout = time.Duration(10 * time.Second) externalEtcdRequestRetries = 3 externalEtcdRequestInterval = time.Duration(5 * time.Second) @@ -75,10 +73,16 @@ type Error struct { Msg string } +// Error implements the standard error interface func (e *Error) Error() string { return fmt.Sprintf("[preflight] Some fatal errors occurred:\n%s%s", e.Msg, "[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`") } +// Preflight identifies this error as a preflight error +func (e *Error) Preflight() bool { + return true +} + // Checker validates the state of the system to ensure kubeadm will be // successful as often as possible. type Checker interface { @@ -99,13 +103,14 @@ func (CRICheck) Name() string { // Check validates the container runtime through the CRI. func (criCheck CRICheck) Check() (warnings, errors []error) { + glog.V(1).Infoln("validating the container runtime through the CRI") crictlPath, err := criCheck.exec.LookPath("crictl") if err != nil { - errors = append(errors, fmt.Errorf("unable to find command crictl: %v", err)) + errors = append(errors, fmt.Errorf("unable to find command crictl: %s", err)) return warnings, errors } if err := criCheck.exec.Command(crictlPath, "-r", criCheck.socket, "info").Run(); err != nil { - errors = append(errors, fmt.Errorf("unable to check if the container runtime at %q is running: %v", criCheck.socket, err)) + errors = append(errors, fmt.Errorf("unable to check if the container runtime at %q is running: %s", criCheck.socket, err)) return warnings, errors } return warnings, errors @@ -130,6 +135,7 @@ func (sc ServiceCheck) Name() string { // Check validates if the service is enabled and active. func (sc ServiceCheck) Check() (warnings, errors []error) { + glog.V(1).Infoln("validating if the service is enabled and active") initSystem, err := initsystem.GetInitSystem() if err != nil { return []error{err}, nil @@ -170,6 +176,7 @@ func (FirewalldCheck) Name() string { // Check validates if the firewall is enabled and active. func (fc FirewalldCheck) Check() (warnings, errors []error) { + glog.V(1).Infoln("validating if the firewall is enabled and active") initSystem, err := initsystem.GetInitSystem() if err != nil { return []error{err}, nil @@ -206,6 +213,7 @@ func (poc PortOpenCheck) Name() string { // Check validates if the particular port is available. func (poc PortOpenCheck) Check() (warnings, errors []error) { + glog.V(1).Infof("validating availability of port %d", poc.port) errors = []error{} ln, err := net.Listen("tcp", fmt.Sprintf(":%d", poc.port)) if err != nil { @@ -242,6 +250,7 @@ func (dac DirAvailableCheck) Name() string { // Check validates if a directory does not exist or empty. func (dac DirAvailableCheck) Check() (warnings, errors []error) { + glog.V(1).Infof("validating the existence and emptiness of directory %s", dac.Path) errors = []error{} // If it doesn't exist we are good: if _, err := os.Stat(dac.Path); os.IsNotExist(err) { @@ -279,6 +288,7 @@ func (fac FileAvailableCheck) Name() string { // Check validates if the given file does not already exist. func (fac FileAvailableCheck) Check() (warnings, errors []error) { + glog.V(1).Infof("validating the existence of file %s", fac.Path) errors = []error{} if _, err := os.Stat(fac.Path); err == nil { errors = append(errors, fmt.Errorf("%s already exists", fac.Path)) @@ -302,6 +312,7 @@ func (fac FileExistingCheck) Name() string { // Check validates if the given file already exists. func (fac FileExistingCheck) Check() (warnings, errors []error) { + glog.V(1).Infof("validating the existence of file %s", fac.Path) errors = []error{} if _, err := os.Stat(fac.Path); err != nil { errors = append(errors, fmt.Errorf("%s doesn't exist", fac.Path)) @@ -326,6 +337,7 @@ func (fcc FileContentCheck) Name() string { // Check validates if the given file contains the given content. func (fcc FileContentCheck) Check() (warnings, errors []error) { + glog.V(1).Infof("validating the contents of file %s", fcc.Path) f, err := os.Open(fcc.Path) if err != nil { return nil, []error{fmt.Errorf("%s does not exist", fcc.Path)} @@ -366,6 +378,7 @@ func (ipc InPathCheck) Name() string { // Check validates if the given executable is present in the path. func (ipc InPathCheck) Check() (warnings, errs []error) { + glog.V(1).Infof("validating the presence of executable %s", ipc.executable) _, err := ipc.exec.LookPath(ipc.executable) if err != nil { if ipc.mandatory { @@ -395,11 +408,9 @@ func (HostnameCheck) Name() string { // Check validates if hostname match dns sub domain regex. func (hc HostnameCheck) Check() (warnings, errors []error) { + glog.V(1).Infof("checking whether the given node name is reachable using net.LookupHost") errors = []error{} warnings = []error{} - for _, msg := range validation.ValidateNodeName(hc.nodeName, false) { - errors = append(errors, fmt.Errorf("hostname \"%s\" %s", hc.nodeName, msg)) - } addr, err := net.LookupHost(hc.nodeName) if addr == nil { warnings = append(warnings, fmt.Errorf("hostname \"%s\" could not be reached", hc.nodeName)) @@ -424,7 +435,7 @@ func (hst HTTPProxyCheck) Name() string { // Check validates http connectivity type, direct or via proxy. func (hst HTTPProxyCheck) Check() (warnings, errors []error) { - + glog.V(1).Infof("validating if the connectivity type is via proxy or direct") u := (&url.URL{Scheme: hst.Proto, Host: hst.Host}).String() req, err := http.NewRequest("GET", u, nil) @@ -460,7 +471,7 @@ func (HTTPProxyCIDRCheck) Name() string { // Check validates http connectivity to first IP address in the CIDR. // If it is not directly connected and goes via proxy it will produce warning. func (subnet HTTPProxyCIDRCheck) Check() (warnings, errors []error) { - + glog.V(1).Infoln("validating http connectivity to first IP address in the CIDR") if len(subnet.CIDR) == 0 { return nil, nil } @@ -497,55 +508,6 @@ func (subnet HTTPProxyCIDRCheck) Check() (warnings, errors []error) { return nil, nil } -// ExtraArgsCheck checks if arguments are valid. -type ExtraArgsCheck struct { - APIServerExtraArgs map[string]string - ControllerManagerExtraArgs map[string]string - SchedulerExtraArgs map[string]string -} - -// Name will return ExtraArgs as name for ExtraArgsCheck -func (ExtraArgsCheck) Name() string { - return "ExtraArgs" -} - -// Check validates additional arguments of the control plane components. -func (eac ExtraArgsCheck) Check() (warnings, errors []error) { - argsCheck := func(name string, args map[string]string, f *pflag.FlagSet) []error { - errs := []error{} - for k, v := range args { - if err := f.Set(k, v); err != nil { - errs = append(errs, fmt.Errorf("%s: failed to parse extra argument --%s=%s", name, k, v)) - } - } - return errs - } - - warnings = []error{} - if len(eac.APIServerExtraArgs) > 0 { - flags := pflag.NewFlagSet("", pflag.ContinueOnError) - s := apiservoptions.NewServerRunOptions() - s.AddFlags(flags) - warnings = append(warnings, argsCheck("kube-apiserver", eac.APIServerExtraArgs, flags)...) - } - if len(eac.ControllerManagerExtraArgs) > 0 { - flags := pflag.NewFlagSet("", pflag.ContinueOnError) - s := cmoptions.NewKubeControllerManagerOptions() - s.AddFlags(flags, []string{}, []string{}) - warnings = append(warnings, argsCheck("kube-controller-manager", eac.ControllerManagerExtraArgs, flags)...) - } - if len(eac.SchedulerExtraArgs) > 0 { - opts, err := schedulerapp.NewOptions() - if err != nil { - warnings = append(warnings, err) - } - flags := pflag.NewFlagSet("", pflag.ContinueOnError) - opts.AddFlags(flags) - warnings = append(warnings, argsCheck("kube-scheduler", eac.SchedulerExtraArgs, flags)...) - } - return warnings, nil -} - // SystemVerificationCheck defines struct used for for running the system verification node check in test/e2e_node/system type SystemVerificationCheck struct { CRISocket string @@ -558,6 +520,7 @@ func (SystemVerificationCheck) Name() string { // Check runs all individual checks func (sysver SystemVerificationCheck) Check() (warnings, errors []error) { + glog.V(1).Infoln("running all checks") // Create a buffered writer and choose a quite large value (1M) and suppose the output from the system verification test won't exceed the limit // Run the system verification check, but write to out buffered writer instead of stdout bufw := bufio.NewWriterSize(os.Stdout, 1*1024*1024) @@ -570,7 +533,7 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) { &system.KernelValidator{Reporter: reporter}} // run the docker validator only with dockershim - if sysver.CRISocket == "/var/run/dockershim.sock" { + if sysver.CRISocket == kubeadmdefaults.DefaultCRISocket { // https://github.com/kubernetes/kubeadm/issues/533 validators = append(validators, &system.DockerValidator{Reporter: reporter}) } @@ -615,7 +578,7 @@ func (KubernetesVersionCheck) Name() string { // Check validates kubernetes and kubeadm versions func (kubever KubernetesVersionCheck) Check() (warnings, errors []error) { - + glog.V(1).Infoln("validating kubernetes and kubeadm version") // Skip this check for "super-custom builds", where apimachinery/the overall codebase version is not set. if strings.HasPrefix(kubever.KubeadmVersion, "v0.0.0") { return nil, nil @@ -656,6 +619,7 @@ func (KubeletVersionCheck) Name() string { // Check validates kubelet version. It should be not less than minimal supported version func (kubever KubeletVersionCheck) Check() (warnings, errors []error) { + glog.V(1).Infoln("validating kubelet version") kubeletVersion, err := GetKubeletVersion(kubever.exec) if err != nil { return nil, []error{fmt.Errorf("couldn't get kubelet version: %v", err)} @@ -686,6 +650,7 @@ func (SwapCheck) Name() string { // Check validates whether swap is enabled or not func (swc SwapCheck) Check() (warnings, errors []error) { + glog.V(1).Infoln("validating whether swap is enabled or not") f, err := os.Open("/proc/swaps") if err != nil { // /proc/swaps not available, thus no reasons to warn @@ -724,7 +689,15 @@ func (ExternalEtcdVersionCheck) Name() string { } // Check validates external etcd version +// TODO: Use the official etcd Golang client for this instead? func (evc ExternalEtcdVersionCheck) Check() (warnings, errors []error) { + glog.V(1).Infoln("validating the external etcd version") + + // Return quickly if the user isn't using external etcd + if evc.Etcd.External.Endpoints == nil { + return nil, nil + } + var config *tls.Config var err error if config, err = evc.configRootCAs(config); err != nil { @@ -737,7 +710,7 @@ func (evc ExternalEtcdVersionCheck) Check() (warnings, errors []error) { } client := evc.getHTTPClient(config) - for _, endpoint := range evc.Etcd.Endpoints { + for _, endpoint := range evc.Etcd.External.Endpoints { if _, err := url.Parse(endpoint); err != nil { errors = append(errors, fmt.Errorf("failed to parse external etcd endpoint %s : %v", endpoint, err)) continue @@ -773,10 +746,10 @@ func (evc ExternalEtcdVersionCheck) Check() (warnings, errors []error) { // configRootCAs configures and returns a reference to tls.Config instance if CAFile is provided func (evc ExternalEtcdVersionCheck) configRootCAs(config *tls.Config) (*tls.Config, error) { var CACertPool *x509.CertPool - if evc.Etcd.CAFile != "" { - CACert, err := ioutil.ReadFile(evc.Etcd.CAFile) + if evc.Etcd.External.CAFile != "" { + CACert, err := ioutil.ReadFile(evc.Etcd.External.CAFile) if err != nil { - return nil, fmt.Errorf("couldn't load external etcd's server certificate %s: %v", evc.Etcd.CAFile, err) + return nil, fmt.Errorf("couldn't load external etcd's server certificate %s: %v", evc.Etcd.External.CAFile, err) } CACertPool = x509.NewCertPool() CACertPool.AppendCertsFromPEM(CACert) @@ -793,11 +766,11 @@ func (evc ExternalEtcdVersionCheck) configRootCAs(config *tls.Config) (*tls.Conf // configCertAndKey configures and returns a reference to tls.Config instance if CertFile and KeyFile pair is provided func (evc ExternalEtcdVersionCheck) configCertAndKey(config *tls.Config) (*tls.Config, error) { var cert tls.Certificate - if evc.Etcd.CertFile != "" && evc.Etcd.KeyFile != "" { + if evc.Etcd.External.CertFile != "" && evc.Etcd.External.KeyFile != "" { var err error - cert, err = tls.LoadX509KeyPair(evc.Etcd.CertFile, evc.Etcd.KeyFile) + cert, err = tls.LoadX509KeyPair(evc.Etcd.External.CertFile, evc.Etcd.External.KeyFile) if err != nil { - return nil, fmt.Errorf("couldn't load external etcd's certificate and key pair %s, %s: %v", evc.Etcd.CertFile, evc.Etcd.KeyFile, err) + return nil, fmt.Errorf("couldn't load external etcd's certificate and key pair %s, %s: %v", evc.Etcd.External.CertFile, evc.Etcd.External.KeyFile, err) } if config == nil { config = &tls.Config{} @@ -850,6 +823,31 @@ func getEtcdVersionResponse(client *http.Client, url string, target interface{}) return err } +// ImagePullCheck will pull container images used by kubeadm +type ImagePullCheck struct { + Images images.Images + ImageList []string +} + +// Name returns the label for ImagePullCheck +func (ImagePullCheck) Name() string { + return "ImagePull" +} + +// Check pulls images required by kubeadm. This is a mutating check +func (i ImagePullCheck) Check() (warnings, errors []error) { + for _, image := range i.ImageList { + glog.V(1).Infoln("pulling ", image) + if err := i.Images.Exists(image); err == nil { + continue + } + if err := i.Images.Pull(image); err != nil { + errors = append(errors, fmt.Errorf("failed to pull image [%s]: %v", image, err)) + } + } + return warnings, errors +} + // RunInitMasterChecks executes all individual, applicable to Master node checks. func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfiguration, ignorePreflightErrors sets.String) error { // First, check if we're root separately from the other preflight checks and fail fast @@ -857,91 +855,57 @@ func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfi return err } - // check if we can use crictl to perform checks via the CRI - criCtlChecker := InPathCheck{ - executable: "crictl", - mandatory: false, - exec: execer, - suggestion: fmt.Sprintf("go get %v", kubeadmconstants.CRICtlPackage), - } - manifestsDir := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName) - checks := []Checker{ KubernetesVersionCheck{KubernetesVersion: cfg.KubernetesVersion, KubeadmVersion: kubeadmversion.Get().GitVersion}, - SystemVerificationCheck{CRISocket: cfg.CRISocket}, - IsPrivilegedUserCheck{}, - HostnameCheck{nodeName: cfg.NodeName}, - KubeletVersionCheck{KubernetesVersion: cfg.KubernetesVersion, exec: execer}, - ServiceCheck{Service: "kubelet", CheckIfActive: false}, - ServiceCheck{Service: "docker", CheckIfActive: true}, // assume docker FirewalldCheck{ports: []int{int(cfg.API.BindPort), 10250}}, PortOpenCheck{port: int(cfg.API.BindPort)}, - PortOpenCheck{port: 10250}, PortOpenCheck{port: 10251}, PortOpenCheck{port: 10252}, FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeAPIServer, manifestsDir)}, FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeControllerManager, manifestsDir)}, FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeScheduler, manifestsDir)}, FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.Etcd, manifestsDir)}, - FileContentCheck{Path: bridgenf, Content: []byte{'1'}}, - SwapCheck{}, - InPathCheck{executable: "ip", mandatory: true, exec: execer}, - InPathCheck{executable: "iptables", mandatory: true, exec: execer}, - InPathCheck{executable: "mount", mandatory: true, exec: execer}, - InPathCheck{executable: "nsenter", mandatory: true, exec: execer}, - InPathCheck{executable: "ebtables", mandatory: false, exec: execer}, - InPathCheck{executable: "ethtool", mandatory: false, exec: execer}, - InPathCheck{executable: "socat", mandatory: false, exec: execer}, - InPathCheck{executable: "tc", mandatory: false, exec: execer}, - InPathCheck{executable: "touch", mandatory: false, exec: execer}, - criCtlChecker, - ExtraArgsCheck{ - APIServerExtraArgs: cfg.APIServerExtraArgs, - ControllerManagerExtraArgs: cfg.ControllerManagerExtraArgs, - SchedulerExtraArgs: cfg.SchedulerExtraArgs, - }, HTTPProxyCheck{Proto: "https", Host: cfg.API.AdvertiseAddress}, HTTPProxyCIDRCheck{Proto: "https", CIDR: cfg.Networking.ServiceSubnet}, HTTPProxyCIDRCheck{Proto: "https", CIDR: cfg.Networking.PodSubnet}, } + checks = addCommonChecks(execer, cfg, checks) - if len(cfg.Etcd.Endpoints) == 0 { + // Check ipvs required kernel module once we use ipvs kube-proxy mode + if cfg.KubeProxy.Config != nil && cfg.KubeProxy.Config.Mode == ipvsutil.IPVSProxyMode { + checks = append(checks, + ipvsutil.RequiredIPVSKernelModulesAvailableCheck{Executor: execer}, + ) + } + + if cfg.Etcd.Local != nil { // Only do etcd related checks when no external endpoints were specified checks = append(checks, PortOpenCheck{port: 2379}, - DirAvailableCheck{Path: cfg.Etcd.DataDir}, + DirAvailableCheck{Path: cfg.Etcd.Local.DataDir}, ) - } else { + } + + if cfg.Etcd.External != nil { // Only check etcd version when external endpoints are specified - if cfg.Etcd.CAFile != "" { - checks = append(checks, FileExistingCheck{Path: cfg.Etcd.CAFile}) + if cfg.Etcd.External.CAFile != "" { + checks = append(checks, FileExistingCheck{Path: cfg.Etcd.External.CAFile, Label: "ExternalEtcdClientCertificates"}) } - if cfg.Etcd.CertFile != "" { - checks = append(checks, FileExistingCheck{Path: cfg.Etcd.CertFile}) + if cfg.Etcd.External.CertFile != "" { + checks = append(checks, FileExistingCheck{Path: cfg.Etcd.External.CertFile, Label: "ExternalEtcdClientCertificates"}) } - if cfg.Etcd.KeyFile != "" { - checks = append(checks, FileExistingCheck{Path: cfg.Etcd.KeyFile}) - } - checks = append(checks, - ExternalEtcdVersionCheck{Etcd: cfg.Etcd}, - ) - } - - // Check the config for authorization mode - for _, authzMode := range cfg.AuthorizationModes { - switch authzMode { - case authzmodes.ModeABAC: - checks = append(checks, FileExistingCheck{Path: kubeadmconstants.AuthorizationPolicyPath}) - case authzmodes.ModeWebhook: - checks = append(checks, FileExistingCheck{Path: kubeadmconstants.AuthorizationWebhookConfigPath}) + if cfg.Etcd.External.KeyFile != "" { + checks = append(checks, FileExistingCheck{Path: cfg.Etcd.External.KeyFile, Label: "ExternalEtcdClientCertificates"}) } + checks = append(checks, ExternalEtcdVersionCheck{Etcd: cfg.Etcd}) } if ip := net.ParseIP(cfg.API.AdvertiseAddress); ip != nil { if ip.To4() == nil && ip.To16() != nil { checks = append(checks, FileContentCheck{Path: bridgenf6, Content: []byte{'1'}}, + FileContentCheck{Path: ipv6DefaultForwarding, Content: []byte{'1'}}, ) } } @@ -955,75 +919,78 @@ func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.NodeConfigura return err } - // check if we can use crictl to perform checks via the CRI - criCtlChecker := InPathCheck{ - executable: "crictl", - mandatory: false, - exec: execer, - suggestion: fmt.Sprintf("go get %v", kubeadmconstants.CRICtlPackage), - } - warns, _ := criCtlChecker.Check() - useCRI := len(warns) == 0 - checks := []Checker{ - SystemVerificationCheck{CRISocket: cfg.CRISocket}, - IsPrivilegedUserCheck{}, - HostnameCheck{cfg.NodeName}, - KubeletVersionCheck{exec: execer}, - ServiceCheck{Service: "kubelet", CheckIfActive: false}, - PortOpenCheck{port: 10250}, DirAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName)}, FileAvailableCheck{Path: cfg.CACertPath}, FileAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)}, FileAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName)}, + ipvsutil.RequiredIPVSKernelModulesAvailableCheck{Executor: execer}, } - if useCRI { - checks = append(checks, CRICheck{socket: cfg.CRISocket, exec: execer}) - } else { - // assume docker - checks = append(checks, ServiceCheck{Service: "docker", CheckIfActive: true}) - } - //non-windows checks - if runtime.GOOS == "linux" { - checks = append(checks, - FileContentCheck{Path: bridgenf, Content: []byte{'1'}}, - SwapCheck{}, - InPathCheck{executable: "ip", mandatory: true, exec: execer}, - InPathCheck{executable: "iptables", mandatory: true, exec: execer}, - InPathCheck{executable: "mount", mandatory: true, exec: execer}, - InPathCheck{executable: "nsenter", mandatory: true, exec: execer}, - InPathCheck{executable: "ebtables", mandatory: false, exec: execer}, - InPathCheck{executable: "ethtool", mandatory: false, exec: execer}, - InPathCheck{executable: "socat", mandatory: false, exec: execer}, - InPathCheck{executable: "tc", mandatory: false, exec: execer}, - InPathCheck{executable: "touch", mandatory: false, exec: execer}, - criCtlChecker) - } + checks = addCommonChecks(execer, cfg, checks) - var bridgenf6Check Checker + addIPv6Checks := false for _, server := range cfg.DiscoveryTokenAPIServers { ipstr, _, err := net.SplitHostPort(server) if err == nil { checks = append(checks, HTTPProxyCheck{Proto: "https", Host: ipstr}, ) - if bridgenf6Check == nil { + if !addIPv6Checks { if ip := net.ParseIP(ipstr); ip != nil { if ip.To4() == nil && ip.To16() != nil { - // This check should be added only once - bridgenf6Check = FileContentCheck{Path: bridgenf6, Content: []byte{'1'}} + addIPv6Checks = true } } } } } - if bridgenf6Check != nil { - checks = append(checks, bridgenf6Check) + if addIPv6Checks { + checks = append(checks, + FileContentCheck{Path: bridgenf6, Content: []byte{'1'}}, + FileContentCheck{Path: ipv6DefaultForwarding, Content: []byte{'1'}}, + ) } return RunChecks(checks, os.Stderr, ignorePreflightErrors) } +// addCommonChecks is a helper function to deplicate checks that are common between both the +// kubeadm init and join commands +func addCommonChecks(execer utilsexec.Interface, cfg kubeadmapi.CommonConfiguration, checks []Checker) []Checker { + // Check whether or not the CRI socket defined is the default + if cfg.GetCRISocket() != kubeadmdefaults.DefaultCRISocket { + checks = append(checks, CRICheck{socket: cfg.GetCRISocket(), exec: execer}) + } else { + checks = append(checks, ServiceCheck{Service: "docker", CheckIfActive: true}) + } + + // non-windows checks + if runtime.GOOS == "linux" { + checks = append(checks, + FileContentCheck{Path: bridgenf, Content: []byte{'1'}}, + FileContentCheck{Path: ipv4Forward, Content: []byte{'1'}}, + SwapCheck{}, + InPathCheck{executable: "crictl", mandatory: true, exec: execer}, + InPathCheck{executable: "ip", mandatory: true, exec: execer}, + InPathCheck{executable: "iptables", mandatory: true, exec: execer}, + InPathCheck{executable: "mount", mandatory: true, exec: execer}, + InPathCheck{executable: "nsenter", mandatory: true, exec: execer}, + InPathCheck{executable: "ebtables", mandatory: false, exec: execer}, + InPathCheck{executable: "ethtool", mandatory: false, exec: execer}, + InPathCheck{executable: "socat", mandatory: false, exec: execer}, + InPathCheck{executable: "tc", mandatory: false, exec: execer}, + InPathCheck{executable: "touch", mandatory: false, exec: execer}) + } + checks = append(checks, + SystemVerificationCheck{CRISocket: cfg.GetCRISocket()}, + IsPrivilegedUserCheck{}, + HostnameCheck{nodeName: cfg.GetNodeName()}, + KubeletVersionCheck{KubernetesVersion: cfg.GetKubernetesVersion(), exec: execer}, + ServiceCheck{Service: "kubelet", CheckIfActive: false}, + PortOpenCheck{port: 10250}) + return checks +} + // RunRootCheckOnly initializes checks slice of structs and call RunChecks func RunRootCheckOnly(ignorePreflightErrors sets.String) error { checks := []Checker{ @@ -1033,6 +1000,19 @@ func RunRootCheckOnly(ignorePreflightErrors sets.String) error { return RunChecks(checks, os.Stderr, ignorePreflightErrors) } +// RunPullImagesCheck will pull images kubeadm needs if the are not found on the system +func RunPullImagesCheck(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfiguration, ignorePreflightErrors sets.String) error { + criInterfacer, err := images.NewCRInterfacer(execer, cfg.GetCRISocket()) + if err != nil { + return err + } + + checks := []Checker{ + ImagePullCheck{Images: criInterfacer, ImageList: images.GetAllImages(cfg)}, + } + return RunChecks(checks, os.Stderr, ignorePreflightErrors) +} + // RunChecks runs each check, displays it's warnings/errors, and once all // are processed will exit if any errors occurred. func RunChecks(checks []Checker, ww io.Writer, ignorePreflightErrors sets.String) error { @@ -1072,21 +1052,43 @@ func RunChecks(checks []Checker, ww io.Writer, ignorePreflightErrors sets.String } // TryStartKubelet attempts to bring up kubelet service -func TryStartKubelet(ignorePreflightErrors sets.String) { - if setHasItemOrAll(ignorePreflightErrors, "StartKubelet") { +// TODO: Move these kubelet start/stop functions to some other place, e.g. phases/kubelet +func TryStartKubelet() { + // If we notice that the kubelet service is inactive, try to start it + initSystem, err := initsystem.GetInitSystem() + if err != nil { + fmt.Println("[preflight] no supported init system detected, won't make sure the kubelet is running properly.") return } + + if !initSystem.ServiceExists("kubelet") { + fmt.Println("[preflight] couldn't detect a kubelet service, can't make sure the kubelet is running properly.") + } + + fmt.Println("[preflight] Activating the kubelet service") + // This runs "systemctl daemon-reload && systemctl restart kubelet" + if err := initSystem.ServiceRestart("kubelet"); err != nil { + fmt.Printf("[preflight] WARNING: unable to start the kubelet service: [%v]\n", err) + fmt.Printf("[preflight] please ensure kubelet is reloaded and running manually.\n") + } +} + +// TryStopKubelet attempts to bring down the kubelet service momentarily +func TryStopKubelet() { // If we notice that the kubelet service is inactive, try to start it initSystem, err := initsystem.GetInitSystem() if err != nil { - fmt.Println("[preflight] No supported init system detected, won't ensure kubelet is running.") - } else if initSystem.ServiceExists("kubelet") && !initSystem.ServiceIsActive("kubelet") { + fmt.Println("[preflight] no supported init system detected, won't make sure the kubelet not running for a short period of time while setting up configuration for it.") + return + } - fmt.Println("[preflight] Starting the kubelet service") - if err := initSystem.ServiceStart("kubelet"); err != nil { - fmt.Printf("[preflight] WARNING: Unable to start the kubelet service: [%v]\n", err) - fmt.Println("[preflight] WARNING: Please ensure kubelet is running manually.") - } + if !initSystem.ServiceExists("kubelet") { + fmt.Println("[preflight] couldn't detect a kubelet service, can't make sure the kubelet not running for a short period of time while setting up configuration for it.") + } + + // This runs "systemctl daemon-reload && systemctl stop kubelet" + if err := initSystem.ServiceStop("kubelet"); err != nil { + fmt.Printf("[preflight] WARNING: unable to stop the kubelet service momentarily: [%v]\n", err) } } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks_test.go index dbf2cecf2..f6908c7c3 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks_test.go @@ -18,6 +18,7 @@ package preflight import ( "bytes" + "errors" "fmt" "io/ioutil" "strings" @@ -196,21 +197,21 @@ func TestRunInitMasterChecks(t *testing.T) { { name: "Test CA file exists if specfied", cfg: &kubeadmapi.MasterConfiguration{ - Etcd: kubeadmapi.Etcd{CAFile: "/foo"}, + Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CAFile: "/foo"}}, }, expected: false, }, { name: "Test Cert file exists if specfied", cfg: &kubeadmapi.MasterConfiguration{ - Etcd: kubeadmapi.Etcd{CertFile: "/foo"}, + Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CertFile: "/foo"}}, }, expected: false, }, { name: "Test Key file exists if specfied", cfg: &kubeadmapi.MasterConfiguration{ - Etcd: kubeadmapi.Etcd{CertFile: "/foo"}, + Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CertFile: "/foo"}}, }, expected: false, }, @@ -288,17 +289,6 @@ func TestRunChecks(t *testing.T) { {[]Checker{FileContentCheck{Path: "/", Content: []byte("does not exist")}}, false, ""}, {[]Checker{InPathCheck{executable: "foobarbaz", exec: exec.New()}}, true, "\t[WARNING FileExisting-foobarbaz]: foobarbaz not found in system path\n"}, {[]Checker{InPathCheck{executable: "foobarbaz", mandatory: true, exec: exec.New()}}, false, ""}, - {[]Checker{ExtraArgsCheck{ - APIServerExtraArgs: map[string]string{"secure-port": "1234"}, - ControllerManagerExtraArgs: map[string]string{"use-service-account-credentials": "true"}, - SchedulerExtraArgs: map[string]string{"leader-elect": "true"}, - }}, true, ""}, - {[]Checker{ExtraArgsCheck{ - APIServerExtraArgs: map[string]string{"secure-port": "foo"}, - }}, true, "\t[WARNING ExtraArgs]: kube-apiserver: failed to parse extra argument --secure-port=foo\n"}, - {[]Checker{ExtraArgsCheck{ - APIServerExtraArgs: map[string]string{"invalid-argument": "foo"}, - }}, true, "\t[WARNING ExtraArgs]: kube-apiserver: failed to parse extra argument --invalid-argument=foo\n"}, {[]Checker{InPathCheck{executable: "foobar", mandatory: false, exec: exec.New(), suggestion: "install foobar"}}, true, "\t[WARNING FileExisting-foobar]: foobar not found in system path\nSuggestion: install foobar\n"}, } for _, rt := range tokenTest { @@ -330,7 +320,7 @@ func TestConfigRootCAs(t *testing.T) { t.Errorf("failed configRootCAs:\n\texpected: succeed writing contents to temp CA file %s\n\tactual:%v", f.Name(), err) } - c := ExternalEtcdVersionCheck{Etcd: kubeadmapi.Etcd{CAFile: f.Name()}} + c := ExternalEtcdVersionCheck{Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CAFile: f.Name()}}} config, err := c.configRootCAs(nil) if err != nil { @@ -378,10 +368,14 @@ func TestConfigCertAndKey(t *testing.T) { err, ) } - c := ExternalEtcdVersionCheck{Etcd: kubeadmapi.Etcd{ - CertFile: certFile.Name(), - KeyFile: keyFile.Name(), - }} + c := ExternalEtcdVersionCheck{ + Etcd: kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + CertFile: certFile.Name(), + KeyFile: keyFile.Name(), + }, + }, + } config, err := c.configCertAndKey(nil) if err != nil { @@ -638,13 +632,13 @@ func TestKubeletVersionCheck(t *testing.T) { expectErrors bool expectWarnings bool }{ - {"v1.10.2", "", false, false}, // check minimally supported version when there is no information about control plane - {"v1.7.3", "v1.7.8", true, false}, // too old kubelet (older than kubeadmconstants.MinimumKubeletVersion), should fail. - {"v1.9.0", "v1.9.5", false, false}, // kubelet within same major.minor as control plane - {"v1.9.5", "v1.9.1", false, false}, // kubelet is newer, but still within same major.minor as control plane - {"v1.9.0", "v1.10.1", false, false}, // kubelet is lower than control plane, but newer than minimally supported - {"v1.10.0-alpha.1", "v1.9.1", true, false}, // kubelet is newer (development build) than control plane, should fail. - {"v1.10.0", "v1.9.5", true, false}, // kubelet is newer (release) than control plane, should fail. + {"v1.11.2", "", false, false}, // check minimally supported version when there is no information about control plane + {"v1.8.3", "v1.8.8", true, false}, // too old kubelet (older than kubeadmconstants.MinimumKubeletVersion), should fail. + {"v1.10.0", "v1.10.5", false, false}, // kubelet within same major.minor as control plane + {"v1.10.5", "v1.10.1", false, false}, // kubelet is newer, but still within same major.minor as control plane + {"v1.10.0", "v1.11.1", false, false}, // kubelet is lower than control plane, but newer than minimally supported + {"v1.11.0-alpha.1", "v1.10.1", true, false}, // kubelet is newer (development build) than control plane, should fail. + {"v1.11.0", "v1.10.5", true, false}, // kubelet is newer (release) than control plane, should fail. } for _, tc := range cases { @@ -703,3 +697,32 @@ func TestSetHasItemOrAll(t *testing.T) { } } } + +type imgs struct{} + +func (i *imgs) Pull(image string) error { + if image == "bad pull" { + return errors.New("pull error") + } + return nil +} +func (i *imgs) Exists(image string) error { + if image == "found" { + return nil + } + return errors.New("error") +} + +func TestImagePullCheck(t *testing.T) { + i := ImagePullCheck{ + Images: &imgs{}, + ImageList: []string{"found", "not found", "bad pull"}, + } + warnings, errors := i.Check() + if len(warnings) != 0 { + t.Fatalf("did not expect any warnings but got %q", warnings) + } + if len(errors) != 1 { + t.Fatalf("expected 1 errors but got %d: %q", len(errors), errors) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/BUILD index 681f8fa81..190579665 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/BUILD @@ -10,6 +10,7 @@ go_library( name = "go_default_library", srcs = [ "arguments.go", + "cgroupdriver.go", "copy.go", "endpoint.go", "error.go", @@ -20,7 +21,8 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/preflight:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//vendor/gopkg.in/yaml.v2: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:go_default_library", @@ -28,6 +30,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", ], ) @@ -35,15 +38,20 @@ go_test( name = "go_default_test", srcs = [ "arguments_test.go", + "cgroupdriver_test.go", "endpoint_test.go", "error_test.go", + "marshal_test.go", "template_test.go", "version_test.go", ], embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/preflight:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", ], ) @@ -66,7 +74,6 @@ filegroup( "//cmd/kubeadm/app/util/kubeconfig:all-srcs", "//cmd/kubeadm/app/util/pubkeypin:all-srcs", "//cmd/kubeadm/app/util/staticpod:all-srcs", - "//cmd/kubeadm/app/util/token:all-srcs", ], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/BUILD index 5704d1228..d702b7328 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/BUILD @@ -19,6 +19,7 @@ go_library( deps = [ "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", + "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", @@ -28,8 +29,10 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go index cf48237e7..3841a715f 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go @@ -34,7 +34,7 @@ import ( // ClientBackedDryRunGetter implements the DryRunGetter interface for use in NewDryRunClient() and proxies all GET and LIST requests to the backing API server reachable via rest.Config type ClientBackedDryRunGetter struct { client clientset.Interface - dynClientPool dynamic.ClientPool + dynamicClient dynamic.Interface } // InitDryRunGetter should implement the DryRunGetter interface @@ -46,10 +46,14 @@ func NewClientBackedDryRunGetter(config *rest.Config) (*ClientBackedDryRunGetter if err != nil { return nil, err } + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + return nil, err + } return &ClientBackedDryRunGetter{ client: client, - dynClientPool: dynamic.NewDynamicClientPool(config), + dynamicClient: dynamicClient, }, nil } @@ -68,22 +72,15 @@ func NewClientBackedDryRunGetterFromKubeconfig(file string) (*ClientBackedDryRun // HandleGetAction handles GET actions to the dryrun clientset this interface supports func (clg *ClientBackedDryRunGetter) HandleGetAction(action core.GetAction) (bool, runtime.Object, error) { - rc, err := clg.actionToResourceClient(action) - if err != nil { - return true, nil, err - } - - unversionedObj, err := rc.Get(action.GetName(), metav1.GetOptions{}) + unstructuredObj, err := clg.dynamicClient.Resource(action.GetResource()).Namespace(action.GetNamespace()).Get(action.GetName(), metav1.GetOptions{}) + // Inform the user that the requested object wasn't found. + printIfNotExists(err) if err != nil { return true, nil, err } - // If the unversioned object does not have .apiVersion; the inner object is probably nil - if len(unversionedObj.GetAPIVersion()) == 0 { - return true, nil, apierrors.NewNotFound(action.GetResource().GroupResource(), action.GetName()) - } - newObj, err := decodeUnversionedIntoAPIObject(action, unversionedObj) + newObj, err := decodeUnstructuredIntoAPIObject(action, unstructuredObj) if err != nil { - fmt.Printf("error after decode: %v %v\n", unversionedObj, err) + fmt.Printf("error after decode: %v %v\n", unstructuredObj, err) return true, nil, err } return true, newObj, err @@ -91,27 +88,18 @@ func (clg *ClientBackedDryRunGetter) HandleGetAction(action core.GetAction) (boo // HandleListAction handles LIST actions to the dryrun clientset this interface supports func (clg *ClientBackedDryRunGetter) HandleListAction(action core.ListAction) (bool, runtime.Object, error) { - rc, err := clg.actionToResourceClient(action) - if err != nil { - return true, nil, err - } - listOpts := metav1.ListOptions{ LabelSelector: action.GetListRestrictions().Labels.String(), FieldSelector: action.GetListRestrictions().Fields.String(), } - unversionedList, err := rc.List(listOpts) + unstructuredList, err := clg.dynamicClient.Resource(action.GetResource()).Namespace(action.GetNamespace()).List(listOpts) if err != nil { return true, nil, err } - // If the runtime.Object here is nil, we should return successfully with no result - if unversionedList == nil { - return true, unversionedList, nil - } - newObj, err := decodeUnversionedIntoAPIObject(action, unversionedList) + newObj, err := decodeUnstructuredIntoAPIObject(action, unstructuredList) if err != nil { - fmt.Printf("error after decode: %v %v\n", unversionedList, err) + fmt.Printf("error after decode: %v %v\n", unstructuredList, err) return true, nil, err } return true, newObj, err @@ -122,28 +110,10 @@ func (clg *ClientBackedDryRunGetter) Client() clientset.Interface { return clg.client } -// actionToResourceClient returns the ResourceInterface for the given action -// First; the function gets the right API group interface from the resource type. The API group struct behind the interface -// returned may be cached in the dynamic client pool. Then, an APIResource object is constructed so that it can be passed to -// dynamic.Interface's Resource() function, which will give us the final ResourceInterface to query -func (clg *ClientBackedDryRunGetter) actionToResourceClient(action core.Action) (dynamic.ResourceInterface, error) { - dynIface, err := clg.dynClientPool.ClientForGroupVersionResource(action.GetResource()) - if err != nil { - return nil, err - } - - apiResource := &metav1.APIResource{ - Name: action.GetResource().Resource, - Namespaced: action.GetNamespace() != "", - } - - return dynIface.Resource(apiResource, action.GetNamespace()), nil -} - // decodeUnversionedIntoAPIObject converts the *unversioned.Unversioned object returned from the dynamic client // to bytes; and then decodes it back _to an external api version (k8s.io/api vs k8s.io/kubernetes/pkg/api*)_ using the normal API machinery -func decodeUnversionedIntoAPIObject(action core.Action, unversionedObj runtime.Object) (runtime.Object, error) { - objBytes, err := json.Marshal(unversionedObj) +func decodeUnstructuredIntoAPIObject(action core.Action, unstructuredObj runtime.Unstructured) (runtime.Object, error) { + objBytes, err := json.Marshal(unstructuredObj) if err != nil { return nil, err } @@ -153,3 +123,9 @@ func decodeUnversionedIntoAPIObject(action core.Action, unversionedObj runtime.O } return newObj, nil } + +func printIfNotExists(err error) { + if apierrors.IsNotFound(err) { + fmt.Println("[dryrun] The GET request didn't yield any result, the API Server returned a NotFound error.") + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/dryrunclient.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/dryrunclient.go index 6c0d796e6..4d4a52d70 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/dryrunclient.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/dryrunclient.go @@ -55,6 +55,18 @@ type DryRunClientOptions struct { PrintGETAndLIST bool } +// GetDefaultDryRunClientOptions returns the default DryRunClientOptions values +func GetDefaultDryRunClientOptions(drg DryRunGetter, w io.Writer) DryRunClientOptions { + return DryRunClientOptions{ + Writer: w, + Getter: drg, + PrependReactors: []core.Reactor{}, + AppendReactors: []core.Reactor{}, + MarshalFunc: DefaultMarshalFunc, + PrintGETAndLIST: false, + } +} + // actionWithName is the generic interface for an action that has a name associated with it // This just makes it easier to catch all actions that has a name; instead of hard-coding all request that has it associated type actionWithName interface { @@ -71,14 +83,7 @@ type actionWithObject interface { // NewDryRunClient is a wrapper for NewDryRunClientWithOpts using some default values func NewDryRunClient(drg DryRunGetter, w io.Writer) clientset.Interface { - return NewDryRunClientWithOpts(DryRunClientOptions{ - Writer: w, - Getter: drg, - PrependReactors: []core.Reactor{}, - AppendReactors: []core.Reactor{}, - MarshalFunc: DefaultMarshalFunc, - PrintGETAndLIST: false, - }) + return NewDryRunClientWithOpts(GetDefaultDryRunClientOptions(drg, w)) } // NewDryRunClientWithOpts returns a clientset.Interface that can be used normally for talking to the Kubernetes API. diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/idempotency.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/idempotency.go index 03f60be77..bc36f65eb 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/idempotency.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/idempotency.go @@ -17,6 +17,7 @@ limitations under the License. package apiclient import ( + "encoding/json" "fmt" apps "k8s.io/api/apps/v1" @@ -24,7 +25,12 @@ import ( rbac "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" ) // TODO: We should invent a dynamic mechanism for this using the dynamic client instead of hard-coding these functions per-type @@ -44,6 +50,21 @@ func CreateOrUpdateConfigMap(client clientset.Interface, cm *v1.ConfigMap) error return nil } +// CreateOrRetainConfigMap creates a ConfigMap if the target resource doesn't exist. If the resource exists already, this function will retain the resource instead. +func CreateOrRetainConfigMap(client clientset.Interface, cm *v1.ConfigMap, configMapName string) error { + if _, err := client.CoreV1().ConfigMaps(cm.ObjectMeta.Namespace).Get(configMapName, metav1.GetOptions{}); err != nil { + if !apierrors.IsNotFound(err) { + return nil + } + if _, err := client.CoreV1().ConfigMaps(cm.ObjectMeta.Namespace).Create(cm); err != nil { + if !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("unable to create configmap: %v", err) + } + } + } + return nil +} + // CreateOrUpdateSecret creates a Secret if the target resource doesn't exist. If the resource exists already, this function will update the resource instead. func CreateOrUpdateSecret(client clientset.Interface, secret *v1.Secret) error { if _, err := client.CoreV1().Secrets(secret.ObjectMeta.Namespace).Create(secret); err != nil { @@ -171,3 +192,49 @@ func CreateOrUpdateClusterRoleBinding(client clientset.Interface, clusterRoleBin } return nil } + +// PatchNode tries to patch a node using the following client, executing patchFn for the actual mutating logic +func PatchNode(client clientset.Interface, nodeName string, patchFn func(*v1.Node)) error { + // Loop on every false return. Return with an error if raised. Exit successfully if true is returned. + return wait.Poll(constants.APICallRetryInterval, constants.PatchNodeTimeout, func() (bool, error) { + // First get the node object + n, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) + if err != nil { + return false, nil + } + + // The node may appear to have no labels at first, + // so we wait for it to get hostname label. + if _, found := n.ObjectMeta.Labels[kubeletapis.LabelHostname]; !found { + return false, nil + } + + oldData, err := json.Marshal(n) + if err != nil { + return false, err + } + + // Execute the mutating function + patchFn(n) + + newData, err := json.Marshal(n) + if err != nil { + return false, err + } + + patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{}) + if err != nil { + return false, err + } + + if _, err := client.CoreV1().Nodes().Patch(n.Name, types.StrategicMergePatchType, patchBytes); err != nil { + if apierrors.IsConflict(err) { + fmt.Println("[patchnode] Temporarily unable to update node metadata due to conflict (will retry)") + return false, nil + } + return false, err + } + + return true, nil + }) +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/init_dryrun.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/init_dryrun.go index ab31a9866..f4da31f8c 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/init_dryrun.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/init_dryrun.go @@ -132,9 +132,7 @@ func (idr *InitDryRunGetter) handleGetNode(action core.GetAction) (bool, runtime Labels: map[string]string{ "kubernetes.io/hostname": idr.masterName, }, - }, - Spec: v1.NodeSpec{ - ExternalID: idr.masterName, + Annotations: map[string]string{}, }, }, nil } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go index fbcc71993..d5f89dd2b 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go @@ -46,7 +46,7 @@ func TestHandleGetAction(t *testing.T) { { action: core.NewRootGetAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, masterName), expectedHandled: true, - expectedObjectJSON: []byte(`{"metadata":{"name":"master-foo","creationTimestamp":null,"labels":{"kubernetes.io/hostname":"master-foo"}},"spec":{"externalID":"master-foo"},"status":{"daemonEndpoints":{"kubeletEndpoint":{"Port":0}},"nodeInfo":{"machineID":"","systemUUID":"","bootID":"","kernelVersion":"","osImage":"","containerRuntimeVersion":"","kubeletVersion":"","kubeProxyVersion":"","operatingSystem":"","architecture":""}}}`), + expectedObjectJSON: []byte(`{"metadata":{"name":"master-foo","creationTimestamp":null,"labels":{"kubernetes.io/hostname":"master-foo"}},"spec":{},"status":{"daemonEndpoints":{"kubeletEndpoint":{"Port":0}},"nodeInfo":{"machineID":"","systemUUID":"","bootID":"","kernelVersion":"","osImage":"","containerRuntimeVersion":"","kubeletVersion":"","kubeProxyVersion":"","operatingSystem":"","architecture":""}}}`), expectedErr: false, }, { diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/arguments.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/arguments.go index 323b2da94..60dfb6eac 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/arguments.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/arguments.go @@ -18,17 +18,32 @@ package util import ( "fmt" + "sort" "strings" ) -// BuildArgumentListFromMap takes two string-string maps, one with the base arguments and one with optional override arguments +// BuildArgumentListFromMap takes two string-string maps, one with the base arguments and one +// with optional override arguments. In the return list override arguments will precede base +// arguments func BuildArgumentListFromMap(baseArguments map[string]string, overrideArguments map[string]string) []string { var command []string - for k, v := range overrideArguments { + var keys []string + for k := range overrideArguments { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + v := overrideArguments[k] // values of "" are allowed as well command = append(command, fmt.Sprintf("--%s=%s", k, v)) } - for k, v := range baseArguments { + keys = []string{} + for k := range baseArguments { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + v := baseArguments[k] if _, overrideExists := overrideArguments[k]; !overrideExists { command = append(command, fmt.Sprintf("--%s=%s", k, v)) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/arguments_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/arguments_test.go index f2c6373bf..bdfd5e414 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/arguments_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/arguments_test.go @@ -39,8 +39,8 @@ func TestBuildArgumentListFromMap(t *testing.T) { }, expected: []string{ "--admission-control=NamespaceLifecycle,LimitRanger", - "--insecure-bind-address=127.0.0.1", "--allow-privileged=true", + "--insecure-bind-address=127.0.0.1", }, }, { // add an argument that is not in base @@ -53,8 +53,8 @@ func TestBuildArgumentListFromMap(t *testing.T) { }, expected: []string{ "--admission-control=NamespaceLifecycle,LimitRanger", - "--insecure-bind-address=127.0.0.1", "--allow-privileged=true", + "--insecure-bind-address=127.0.0.1", }, }, { // allow empty strings in base @@ -68,8 +68,8 @@ func TestBuildArgumentListFromMap(t *testing.T) { }, expected: []string{ "--admission-control=NamespaceLifecycle,LimitRanger", - "--insecure-bind-address=127.0.0.1", "--allow-privileged=true", + "--insecure-bind-address=127.0.0.1", "--something-that-allows-empty-string=", }, }, @@ -85,17 +85,15 @@ func TestBuildArgumentListFromMap(t *testing.T) { }, expected: []string{ "--admission-control=NamespaceLifecycle,LimitRanger", - "--insecure-bind-address=127.0.0.1", - "--allow-privileged=true", "--something-that-allows-empty-string=", + "--allow-privileged=true", + "--insecure-bind-address=127.0.0.1", }, }, } for _, rt := range tests { actual := BuildArgumentListFromMap(rt.base, rt.overrides) - sort.Strings(actual) - sort.Strings(rt.expected) if !reflect.DeepEqual(actual, rt.expected) { t.Errorf("failed BuildArgumentListFromMap:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/BUILD index 7f5453fab..cd3098c00 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/BUILD @@ -8,8 +8,10 @@ go_library( deps = [ "//cmd/kubeadm/app/util:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/audit/install:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", ], ) @@ -18,8 +20,9 @@ go_test( srcs = ["utils_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/kubectl/scheme:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/audit/install:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/utils.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/utils.go index 688d8f0f6..8155d096b 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/utils.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/utils.go @@ -23,8 +23,10 @@ import ( "path/filepath" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apiserver/pkg/apis/audit/install" auditv1beta1 "k8s.io/apiserver/pkg/apis/audit/v1beta1" - "k8s.io/client-go/kubernetes/scheme" "k8s.io/kubernetes/cmd/kubeadm/app/util" ) @@ -32,7 +34,7 @@ import ( func CreateDefaultAuditLogPolicy(policyFile string) error { policy := auditv1beta1.Policy{ TypeMeta: metav1.TypeMeta{ - APIVersion: "audit.k8s.io/v1beta1", + APIVersion: auditv1beta1.SchemeGroupVersion.String(), Kind: "Policy", }, Rules: []auditv1beta1.PolicyRule{ @@ -50,11 +52,15 @@ func writePolicyToDisk(policyFile string, policy *auditv1beta1.Policy) error { return fmt.Errorf("failed to create directory %q: %v", filepath.Dir(policyFile), err) } - // Registers auditv1beta1 with the runtime Scheme - auditv1beta1.AddToScheme(scheme.Scheme) + scheme := runtime.NewScheme() + // Registers the API group with the scheme and adds types to a scheme + install.Install(scheme) + + codecs := serializer.NewCodecFactory(scheme) // writes the policy to disk - serialized, err := util.MarshalToYaml(policy, auditv1beta1.SchemeGroupVersion) + serialized, err := util.MarshalToYamlForCodecs(policy, auditv1beta1.SchemeGroupVersion, codecs) + if err != nil { return fmt.Errorf("failed to marshal audit policy to YAML: %v", err) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/utils_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/utils_test.go index 113488a75..01fde9eb8 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/utils_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/audit/utils_test.go @@ -23,8 +23,9 @@ import ( "testing" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apiserver/pkg/apis/audit/install" auditv1beta1 "k8s.io/apiserver/pkg/apis/audit/v1beta1" - "k8s.io/kubernetes/pkg/kubectl/scheme" ) func cleanup(t *testing.T, path string) { @@ -50,8 +51,11 @@ func TestCreateDefaultAuditLogPolicy(t *testing.T) { if err != nil { t.Fatalf("failed to read %v: %v", auditPolicyFile, err) } + scheme := runtime.NewScheme() + install.Install(scheme) + codecs := serializer.NewCodecFactory(scheme) policy := auditv1beta1.Policy{} - err = runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), policyBytes, &policy) + err = runtime.DecodeInto(codecs.UniversalDecoder(), policyBytes, &policy) if err != nil { t.Fatalf("failed to decode written policy: %v", err) } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/cgroupdriver.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/cgroupdriver.go new file mode 100644 index 000000000..b03a29912 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/cgroupdriver.go @@ -0,0 +1,75 @@ +/* +Copyright 2018 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 ( + "fmt" + "strings" + + utilsexec "k8s.io/utils/exec" +) + +// TODO: add support for detecting the cgroup driver for CRI other than +// Docker. Currently only Docker driver detection is supported: +// Discussion: +// https://github.com/kubernetes/kubeadm/issues/844 + +// GetCgroupDriverDocker runs 'docker info' to obtain the docker cgroup driver +func GetCgroupDriverDocker(execer utilsexec.Interface) (string, error) { + info, err := callDockerInfo(execer) + if err != nil { + return "", err + } + return getCgroupDriverFromDockerInfo(info) +} + +func validateCgroupDriver(driver string) error { + if driver != "cgroupfs" && driver != "systemd" { + return fmt.Errorf("unknown cgroup driver %q", driver) + } + return nil +} + +// TODO: Docker 1.13 has a new way to obatain the cgroup driver: +// docker info -f "{{.CgroupDriver}} +// If the minimum supported Docker version in K8s becomes 1.13, move to +// this syntax. +func callDockerInfo(execer utilsexec.Interface) (string, error) { + out, err := execer.Command("docker", "info").Output() + if err != nil { + return "", fmt.Errorf("cannot execute 'docker info': %v", err) + } + return string(out), nil +} + +func getCgroupDriverFromDockerInfo(info string) (string, error) { + lineSeparator := ": " + prefix := "Cgroup Driver" + for _, line := range strings.Split(info, "\n") { + if !strings.Contains(line, prefix+lineSeparator) { + continue + } + lineSplit := strings.Split(line, lineSeparator) + // At this point len(lineSplit) is always >= 2 + driver := lineSplit[1] + if err := validateCgroupDriver(driver); err != nil { + return "", err + } + return driver, nil + } + return "", fmt.Errorf("cgroup driver is not defined in 'docker info'") +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/cgroupdriver_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/cgroupdriver_test.go new file mode 100644 index 000000000..ca1ba3a45 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/cgroupdriver_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2018 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 TestGetCgroupDriverDocker(t *testing.T) { + testCases := []struct { + name string + info string + expectedError bool + }{ + { + name: "valid: value is 'cgroupfs'", + info: `Cgroup Driver: cgroupfs`, + expectedError: false, + }, + { + name: "valid: value is 'systemd'", + info: `Cgroup Driver: systemd`, + expectedError: false, + }, + { + name: "invalid: missing 'Cgroup Driver' key and value", + info: "", + expectedError: true, + }, + { + name: "invalid: only a 'Cgroup Driver' key is present", + info: `Cgroup Driver`, + expectedError: true, + }, + { + name: "invalid: empty 'Cgroup Driver' value", + info: `Cgroup Driver: `, + expectedError: true, + }, + { + name: "invalid: unknown 'Cgroup Driver' value", + info: `Cgroup Driver: invalid-value`, + expectedError: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if _, err := getCgroupDriverFromDockerInfo(tc.info); (err != nil) != tc.expectedError { + t.Fatalf("expected error: %v, saw: %v, error: %v", tc.expectedError, (err != nil), err) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/BUILD index 340e6c7a9..b73f62f00 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/BUILD @@ -8,27 +8,52 @@ load( go_library( name = "go_default_library", - srcs = ["masterconfig.go"], + srcs = [ + "cluster.go", + "masterconfig.go", + "nodeconfig.go", + ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/config", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", - "//cmd/kubeadm/app/util/token:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//pkg/util/node:go_default_library", "//pkg/util/version:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", ], ) go_test( name = "go_default_test", - srcs = ["masterconfig_test.go"], + srcs = [ + "masterconfig_test.go", + "nodeconfig_test.go", + ], + data = glob(["testdata/**"]), embed = [":go_default_library"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library", + "//cmd/kubeadm/app/util:go_default_library", + "//vendor/github.com/pmezard/go-difflib/difflib: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:go_default_library", + ], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/cluster.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/cluster.go new file mode 100644 index 000000000..f2ec1a777 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/cluster.go @@ -0,0 +1,65 @@ +/* +Copyright 2018 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 config + +import ( + "fmt" + "io" + "io/ioutil" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clientset "k8s.io/client-go/kubernetes" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" +) + +// TODO: Add unit tests for this file + +// FetchConfigFromFileOrCluster fetches configuration required for upgrading your cluster from a file (which has precedence) or a ConfigMap in the cluster +func FetchConfigFromFileOrCluster(client clientset.Interface, w io.Writer, logPrefix, cfgPath string) (*kubeadmapi.MasterConfiguration, error) { + // Load the configuration from a file or the cluster + configBytes, err := loadConfigurationBytes(client, w, logPrefix, cfgPath) + if err != nil { + return nil, err + } + + // Take the versioned configuration populated from the file or ConfigMap, convert it to internal, default and validate + return BytesToInternalConfig(configBytes) +} + +// loadConfigurationBytes loads the configuration byte slice from either a file or the cluster ConfigMap +func loadConfigurationBytes(client clientset.Interface, w io.Writer, logPrefix, cfgPath string) ([]byte, error) { + // The config file has the highest priority + if cfgPath != "" { + fmt.Fprintf(w, "[%s] Reading configuration options from a file: %s\n", logPrefix, cfgPath) + return ioutil.ReadFile(cfgPath) + } + + fmt.Fprintf(w, "[%s] Reading configuration from the cluster...\n", logPrefix) + + configMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(constants.MasterConfigurationConfigMap, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + // Return the apierror directly so the caller of this function can know what type of error occurred and act based on that + return []byte{}, err + } else if err != nil { + return []byte{}, fmt.Errorf("an unexpected error happened when trying to get the ConfigMap %q in the %s namespace: %v", constants.MasterConfigurationConfigMap, metav1.NamespaceSystem, err) + } + + fmt.Fprintf(w, "[%s] FYI: You can look at this config file with 'kubectl -n %s get cm %s -oyaml'\n", logPrefix, metav1.NamespaceSystem, constants.MasterConfigurationConfigMap) + return []byte(configMap.Data[constants.MasterConfigurationConfigMapKey]), nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig.go index d109dab38..03ef03743 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig.go @@ -14,72 +14,86 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package config import ( "fmt" "io/ioutil" "net" + "strings" + "github.com/golang/glog" + + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" netutil "k8s.io/apimachinery/pkg/util/net" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" - tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/util/node" "k8s.io/kubernetes/pkg/util/version" ) -// SetInitDynamicDefaults checks and sets configuration values for Master node +// SetInitDynamicDefaults checks and sets configuration values for the MasterConfiguration object func SetInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error { + // validate cfg.API.AdvertiseAddress. + addressIP := net.ParseIP(cfg.API.AdvertiseAddress) + if addressIP == nil && cfg.API.AdvertiseAddress != "" { + return fmt.Errorf("couldn't use \"%s\" as \"apiserver-advertise-address\", must be ipv4 or ipv6 address", cfg.API.AdvertiseAddress) + } // Choose the right address for the API Server to advertise. If the advertise address is localhost or 0.0.0.0, the default interface's IP address is used // This is the same logic as the API Server uses - ip, err := netutil.ChooseBindAddress(net.ParseIP(cfg.API.AdvertiseAddress)) + ip, err := netutil.ChooseBindAddress(addressIP) if err != nil { return err } cfg.API.AdvertiseAddress = ip.String() ip = net.ParseIP(cfg.API.AdvertiseAddress) if ip.To4() != nil { - cfg.KubeProxy.Config.BindAddress = kubeadmapiext.DefaultProxyBindAddressv4 + cfg.KubeProxy.Config.BindAddress = kubeadmapiv1alpha2.DefaultProxyBindAddressv4 } else { - cfg.KubeProxy.Config.BindAddress = kubeadmapiext.DefaultProxyBindAddressv6 + cfg.KubeProxy.Config.BindAddress = kubeadmapiv1alpha2.DefaultProxyBindAddressv6 } // Resolve possible version labels and validate version string - err = NormalizeKubernetesVersion(cfg) - if err != nil { + if err := NormalizeKubernetesVersion(cfg); err != nil { return err } - if cfg.Token == "" { - var err error - cfg.Token, err = tokenutil.GenerateToken() + // Downcase SANs. Some domain names (like ELBs) have capitals in them. + LowercaseSANs(cfg.APIServerCertSANs) + + // Populate the .Token field with a random value if unset + // We do this at this layer, and not the API defaulting layer + // because of possible security concerns, and more practically + // because we can't return errors in the API object defaulting + // process but here we can. + for i, bt := range cfg.BootstrapTokens { + if bt.Token != nil && len(bt.Token.String()) > 0 { + continue + } + + tokenStr, err := bootstraputil.GenerateBootstrapToken() if err != nil { return fmt.Errorf("couldn't generate random token: %v", err) } + token, err := kubeadmapi.NewBootstrapTokenString(tokenStr) + if err != nil { + return err + } + cfg.BootstrapTokens[i].Token = token } - cfg.NodeName = node.GetHostname(cfg.NodeName) - - return nil -} - -// TryLoadMasterConfiguration tries to loads a Master configuration from the given file (if defined) -func TryLoadMasterConfiguration(cfgPath string, cfg *kubeadmapiext.MasterConfiguration) error { + cfg.NodeRegistration.Name = node.GetHostname(cfg.NodeRegistration.Name) - if cfgPath != "" { - b, err := ioutil.ReadFile(cfgPath) - if err != nil { - return fmt.Errorf("unable to read config from %q [%v]", cfgPath, err) - } - if err := runtime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), b, cfg); err != nil { - return fmt.Errorf("unable to decode config from %q [%v]", cfgPath, err) - } + // Only if the slice is nil, we should append the master taint. This allows the user to specify an empty slice for no default master taint + if cfg.NodeRegistration.Taints == nil { + cfg.NodeRegistration.Taints = []v1.Taint{kubeadmconstants.MasterTaint} } return nil @@ -90,29 +104,93 @@ func TryLoadMasterConfiguration(cfgPath string, cfg *kubeadmapiext.MasterConfigu // Then the external, versioned configuration is defaulted and converted to the internal type. // Right thereafter, the configuration is defaulted again with dynamic values (like IP addresses of a machine, etc) // Lastly, the internal config is validated and returned. -func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *kubeadmapiext.MasterConfiguration) (*kubeadmapi.MasterConfiguration, error) { +func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *kubeadmapiv1alpha2.MasterConfiguration) (*kubeadmapi.MasterConfiguration, error) { internalcfg := &kubeadmapi.MasterConfiguration{} - // Loads configuration from config file, if provided - // Nb. --config overrides command line flags - if err := TryLoadMasterConfiguration(cfgPath, defaultversionedcfg); err != nil { - return nil, err + if cfgPath != "" { + // Loads configuration from config file, if provided + // Nb. --config overrides command line flags + glog.V(1).Infoln("loading configuration from the given file") + + b, err := ioutil.ReadFile(cfgPath) + if err != nil { + return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err) + } + return BytesToInternalConfig(b) } // Takes passed flags into account; the defaulting is executed once again enforcing assignement of // static default values to cfg only for values not provided with flags - legacyscheme.Scheme.Default(defaultversionedcfg) - legacyscheme.Scheme.Convert(defaultversionedcfg, internalcfg, nil) + kubeadmscheme.Scheme.Default(defaultversionedcfg) + kubeadmscheme.Scheme.Convert(defaultversionedcfg, internalcfg, nil) + + return defaultAndValidate(internalcfg) +} + +// BytesToInternalConfig converts a byte array to an internal, defaulted and validated configuration object +func BytesToInternalConfig(b []byte) (*kubeadmapi.MasterConfiguration, error) { + internalcfg := &kubeadmapi.MasterConfiguration{} + + decoded, err := kubeadmutil.LoadYAML(b) + if err != nil { + return nil, fmt.Errorf("unable to decode config from bytes: %v", err) + } + + // As there was a bug in kubeadm v1.10 and earlier that made the YAML uploaded to the cluster configmap NOT have metav1.TypeMeta information + // we need to populate this here manually. If kind or apiVersion is empty, we know the apiVersion is v1alpha1, as by the time kubeadm had this bug, + // it could only write + // TODO: Remove this "hack" in v1.12 when we know the ConfigMap always contains v1alpha2 content written by kubeadm v1.11. Also, we will drop support for + // v1alpha1 in v1.12 + kind := decoded["kind"] + apiVersion := decoded["apiVersion"] + if kind == nil || len(kind.(string)) == 0 { + decoded["kind"] = "MasterConfiguration" + } + if apiVersion == nil || len(apiVersion.(string)) == 0 { + decoded["apiVersion"] = kubeadmapiv1alpha1.SchemeGroupVersion.String() + } + + // Between v1.9 and v1.10 the proxy componentconfig in the v1alpha1 MasterConfiguration changed unexpectedly, which broke unmarshalling out-of-the-box + // Hence, we need to workaround this bug in the v1alpha1 API + if decoded["apiVersion"] == kubeadmapiv1alpha1.SchemeGroupVersion.String() { + v1alpha1cfg := &kubeadmapiv1alpha1.MasterConfiguration{} + if err := kubeadmapiv1alpha1.Migrate(decoded, v1alpha1cfg, kubeadmscheme.Codecs); err != nil { + return nil, fmt.Errorf("unable to migrate config from previous version: %v", err) + } + + // Default and convert to the internal version + kubeadmscheme.Scheme.Default(v1alpha1cfg) + kubeadmscheme.Scheme.Convert(v1alpha1cfg, internalcfg, nil) + } else if decoded["apiVersion"] == kubeadmapiv1alpha2.SchemeGroupVersion.String() { + v1alpha2cfg := &kubeadmapiv1alpha2.MasterConfiguration{} + if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), b, v1alpha2cfg); err != nil { + return nil, fmt.Errorf("unable to decode config: %v", err) + } + + // Default and convert to the internal version + kubeadmscheme.Scheme.Default(v1alpha2cfg) + kubeadmscheme.Scheme.Convert(v1alpha2cfg, internalcfg, nil) + } else { + // TODO: Add support for an upcoming v1alpha2 API + // TODO: In the future, we can unmarshal any two or more external types into the internal object directly using the following syntax. + // Long-term we don't need this if/else clause. In the future this will do + // runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmapiv2alpha3.SchemeGroupVersion), b, internalcfg) + return nil, fmt.Errorf("unknown API version for kubeadm configuration") + } + + return defaultAndValidate(internalcfg) +} + +func defaultAndValidate(cfg *kubeadmapi.MasterConfiguration) (*kubeadmapi.MasterConfiguration, error) { // Applies dynamic defaults to settings not provided with flags - if err := SetInitDynamicDefaults(internalcfg); err != nil { + if err := SetInitDynamicDefaults(cfg); err != nil { return nil, err } - // Validates cfg (flags/configs + defaults + dynamic defaults) - if err := validation.ValidateMasterConfiguration(internalcfg).ToAggregate(); err != nil { + if err := validation.ValidateMasterConfiguration(cfg).ToAggregate(); err != nil { return nil, err } - return internalcfg, nil + return cfg, nil } // NormalizeKubernetesVersion resolves version labels, sets alternative @@ -141,3 +219,14 @@ func NormalizeKubernetesVersion(cfg *kubeadmapi.MasterConfiguration) error { } return nil } + +// LowercaseSANs can be used to force all SANs to be lowercase so it passes IsDNS1123Subdomain +func LowercaseSANs(sans []string) { + for i, san := range sans { + lowercase := strings.ToLower(san) + if lowercase != san { + glog.V(1).Infof("lowercasing SAN %q to %q", san, lowercase) + sans[i] = lowercase + } + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig_test.go index 6d428badb..a8a6115c7 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig_test.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 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. @@ -14,4 +14,212 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package config + +import ( + "bytes" + "io/ioutil" + "testing" + + "github.com/pmezard/go-difflib/difflib" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" +) + +const ( + master_v1alpha1YAML = "testdata/conversion/master/v1alpha1.yaml" + master_v1alpha1WithoutTypeMetaYAML = "testdata/conversion/master/v1alpha1_without_TypeMeta.yaml" + master_v1alpha2YAML = "testdata/conversion/master/v1alpha2.yaml" + master_internalYAML = "testdata/conversion/master/internal.yaml" + master_incompleteYAML = "testdata/defaulting/master/incomplete.yaml" + master_defaultedYAML = "testdata/defaulting/master/defaulted.yaml" + master_invalidYAML = "testdata/validation/invalid_mastercfg.yaml" + master_beforeUpgradeYAML = "testdata/v1alpha1_upgrade/before.yaml" + master_afterUpgradeYAML = "testdata/v1alpha1_upgrade/after.yaml" +) + +func diff(expected, actual []byte) string { + // Write out the diff + var diffBytes bytes.Buffer + difflib.WriteUnifiedDiff(&diffBytes, difflib.UnifiedDiff{ + A: difflib.SplitLines(string(expected)), + B: difflib.SplitLines(string(actual)), + FromFile: "expected", + ToFile: "actual", + Context: 3, + }) + return diffBytes.String() +} + +func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) { + var tests = []struct { + name, in, out string + groupVersion schema.GroupVersion + expectedErr bool + }{ + // These tests are reading one file, loading it using ConfigFileAndDefaultsToInternalConfig that all of kubeadm is using for unmarshal of our API types, + // and then marshals the internal object to the expected groupVersion + { // v1alpha1 (faulty) -> internal + name: "v1alpha1WithoutTypeMetaToInternal", + in: master_v1alpha1WithoutTypeMetaYAML, + out: master_internalYAML, + groupVersion: kubeadm.SchemeGroupVersion, + }, + { // v1alpha1 -> internal + name: "v1alpha1ToInternal", + in: master_v1alpha1YAML, + out: master_internalYAML, + groupVersion: kubeadm.SchemeGroupVersion, + }, + { // v1alpha2 -> internal + name: "v1alpha2ToInternal", + in: master_v1alpha2YAML, + out: master_internalYAML, + groupVersion: kubeadm.SchemeGroupVersion, + }, + { // v1alpha1 (faulty) -> internal -> v1alpha2 + name: "v1alpha1WithoutTypeMetaTov1alpha2", + in: master_v1alpha1WithoutTypeMetaYAML, + out: master_v1alpha2YAML, + groupVersion: v1alpha2.SchemeGroupVersion, + }, + { // v1alpha1 -> internal -> v1alpha2 + name: "v1alpha1Tov1alpha2", + in: master_v1alpha1YAML, + out: master_v1alpha2YAML, + groupVersion: v1alpha2.SchemeGroupVersion, + }, + // These tests are reading one file that has only a subset of the fields populated, loading it using ConfigFileAndDefaultsToInternalConfig, + // and then marshals the internal object to the expected groupVersion + { // v1alpha1 (faulty) -> default -> validate -> internal -> v1alpha2 + name: "incompleteYAMLToDefaultedv1alpha2", + in: master_incompleteYAML, + out: master_defaultedYAML, + groupVersion: v1alpha2.SchemeGroupVersion, + }, + { // v1alpha1 (faulty) -> validation should fail + name: "invalidYAMLShouldFail", + in: master_invalidYAML, + expectedErr: true, + }, + } + + for _, rt := range tests { + t.Run(rt.name, func(t2 *testing.T) { + + internalcfg, err := ConfigFileAndDefaultsToInternalConfig(rt.in, &v1alpha2.MasterConfiguration{}) + if err != nil { + if rt.expectedErr { + return + } + t2.Fatalf("couldn't unmarshal test data: %v", err) + } + + actual, err := kubeadmutil.MarshalToYamlForCodecs(internalcfg, rt.groupVersion, scheme.Codecs) + if err != nil { + t2.Fatalf("couldn't marshal internal object: %v", err) + } + + expected, err := ioutil.ReadFile(rt.out) + if err != nil { + t2.Fatalf("couldn't read test data: %v", err) + } + + if !bytes.Equal(expected, actual) { + t2.Errorf("the expected and actual output differs.\n\tin: %s\n\tout: %s\n\tgroupversion: %s\n\tdiff: \n%s\n", + rt.in, rt.out, rt.groupVersion.String(), diff(expected, actual)) + } + }) + } +} + +// TestUpgrade tests reading a faulty YAML representation of the MasterConfiguration object (as found in kubeadm clusters <= v1.9.x), +// fixes the problems internally and verifies the marshalled output is the expected output +func TestUpgrade(t *testing.T) { + before, err := ioutil.ReadFile(master_beforeUpgradeYAML) + if err != nil { + t.Fatalf("couldn't read test data: %v", err) + } + + afterExpected, err := ioutil.ReadFile(master_afterUpgradeYAML) + if err != nil { + t.Fatalf("couldn't read test data: %v", err) + } + + decoded, err := kubeadmutil.LoadYAML(before) + if err != nil { + t.Fatalf("couldn't unmarshal test yaml: %v", err) + } + + scheme := runtime.NewScheme() + v1alpha1.AddToScheme(scheme) + codecs := serializer.NewCodecFactory(scheme) + + obj := &v1alpha1.MasterConfiguration{} + if err := v1alpha1.Migrate(decoded, obj, codecs); err != nil { + t.Fatalf("couldn't decode migrated object: %v", err) + } + + afterActual, err := kubeadmutil.MarshalToYamlForCodecs(obj, v1alpha1.SchemeGroupVersion, codecs) + if err != nil { + t.Fatalf("couldn't marshal object: %v", err) + } + + if !bytes.Equal(afterExpected, afterActual) { + t.Errorf("v1alpha1 object after unmarshal, conversion and marshal didn't match expected value.\n\tdiff: \n%s\n", diff(afterExpected, afterActual)) + } +} + +func TestLowercaseSANs(t *testing.T) { + tests := []struct { + name string + in []string + out []string + }{ + { + name: "empty struct", + }, + { + name: "already lowercase", + in: []string{"example.k8s.io"}, + out: []string{"example.k8s.io"}, + }, + { + name: "ip addresses and uppercase", + in: []string{"EXAMPLE.k8s.io", "10.100.0.1"}, + out: []string{"example.k8s.io", "10.100.0.1"}, + }, + { + name: "punycode and uppercase", + in: []string{"xn--7gq663byk9a.xn--fiqz9s", "ANOTHEREXAMPLE.k8s.io"}, + out: []string{"xn--7gq663byk9a.xn--fiqz9s", "anotherexample.k8s.io"}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + cfg := &v1alpha2.MasterConfiguration{ + APIServerCertSANs: test.in, + } + + LowercaseSANs(cfg.APIServerCertSANs) + + if len(cfg.APIServerCertSANs) != len(test.out) { + t.Fatalf("expected %d elements, got %d", len(test.out), len(cfg.APIServerCertSANs)) + } + + for i, expected := range test.out { + if cfg.APIServerCertSANs[i] != expected { + t.Errorf("expected element %d to be %q, got %q", i, expected, cfg.APIServerCertSANs[i]) + } + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig.go new file mode 100644 index 000000000..77bcf8b32 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig.go @@ -0,0 +1,71 @@ +/* +Copyright 2018 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 config + +import ( + "fmt" + "io/ioutil" + + "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/runtime" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" + "k8s.io/kubernetes/pkg/util/node" +) + +// SetJoinDynamicDefaults checks and sets configuration values for the NodeConfiguration object +func SetJoinDynamicDefaults(cfg *kubeadmapi.NodeConfiguration) error { + cfg.NodeRegistration.Name = node.GetHostname(cfg.NodeRegistration.Name) + return nil +} + +// NodeConfigFileAndDefaultsToInternalConfig +func NodeConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *kubeadmapiv1alpha2.NodeConfiguration) (*kubeadmapi.NodeConfiguration, error) { + internalcfg := &kubeadmapi.NodeConfiguration{} + + if cfgPath != "" { + // Loads configuration from config file, if provided + // Nb. --config overrides command line flags + glog.V(1).Infoln("loading configuration from the given file") + + b, err := ioutil.ReadFile(cfgPath) + if err != nil { + return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err) + } + runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha1.SchemeGroupVersion, kubeadmapiv1alpha2.SchemeGroupVersion), b, internalcfg) + } else { + // Takes passed flags into account; the defaulting is executed once again enforcing assignement of + // static default values to cfg only for values not provided with flags + kubeadmscheme.Scheme.Default(defaultversionedcfg) + kubeadmscheme.Scheme.Convert(defaultversionedcfg, internalcfg, nil) + } + + // Applies dynamic defaults to settings not provided with flags + if err := SetJoinDynamicDefaults(internalcfg); err != nil { + return nil, err + } + // Validates cfg (flags/configs + defaults) + if err := validation.ValidateNodeConfiguration(internalcfg).ToAggregate(); err != nil { + return nil, err + } + + return internalcfg, nil +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig_test.go new file mode 100644 index 000000000..dcf679815 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig_test.go @@ -0,0 +1,108 @@ +/* +Copyright 2018 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 config + +import ( + "bytes" + "io/ioutil" + "testing" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" +) + +const ( + node_v1alpha1YAML = "testdata/conversion/node/v1alpha1.yaml" + node_v1alpha2YAML = "testdata/conversion/node/v1alpha2.yaml" + node_internalYAML = "testdata/conversion/node/internal.yaml" + node_incompleteYAML = "testdata/defaulting/node/incomplete.yaml" + node_defaultedYAML = "testdata/defaulting/node/defaulted.yaml" + node_invalidYAML = "testdata/validation/invalid_nodecfg.yaml" +) + +func TestNodeConfigFileAndDefaultsToInternalConfig(t *testing.T) { + var tests = []struct { + name, in, out string + groupVersion schema.GroupVersion + expectedErr bool + }{ + // These tests are reading one file, loading it using NodeConfigFileAndDefaultsToInternalConfig that all of kubeadm is using for unmarshal of our API types, + // and then marshals the internal object to the expected groupVersion + { // v1alpha1 -> internal + name: "v1alpha1ToInternal", + in: node_v1alpha1YAML, + out: node_internalYAML, + groupVersion: kubeadm.SchemeGroupVersion, + }, + { // v1alpha2 -> internal + name: "v1alpha2ToInternal", + in: node_v1alpha2YAML, + out: node_internalYAML, + groupVersion: kubeadm.SchemeGroupVersion, + }, + { // v1alpha1 -> internal -> v1alpha2 + name: "v1alpha1WithoutTypeMetaTov1alpha2", + in: node_v1alpha1YAML, + out: node_v1alpha2YAML, + groupVersion: v1alpha2.SchemeGroupVersion, + }, + // These tests are reading one file that has only a subset of the fields populated, loading it using NodeConfigFileAndDefaultsToInternalConfig, + // and then marshals the internal object to the expected groupVersion + { // v1alpha1 -> default -> validate -> internal -> v1alpha2 + name: "incompleteYAMLToDefaulted", + in: node_incompleteYAML, + out: node_defaultedYAML, + groupVersion: v1alpha2.SchemeGroupVersion, + }, + { // v1alpha1 (faulty) -> validation should fail + name: "invalidYAMLShouldFail", + in: node_invalidYAML, + expectedErr: true, + }, + } + + for _, rt := range tests { + t.Run(rt.name, func(t2 *testing.T) { + + internalcfg, err := NodeConfigFileAndDefaultsToInternalConfig(rt.in, &v1alpha2.NodeConfiguration{}) + if err != nil { + if rt.expectedErr { + return + } + t2.Fatalf("couldn't unmarshal test data: %v", err) + } + + actual, err := kubeadmutil.MarshalToYamlForCodecs(internalcfg, rt.groupVersion, scheme.Codecs) + if err != nil { + t2.Fatalf("couldn't marshal internal object: %v", err) + } + + expected, err := ioutil.ReadFile(rt.out) + if err != nil { + t2.Fatalf("couldn't read test data: %v", err) + } + + if !bytes.Equal(expected, actual) { + t2.Errorf("the expected and actual output differs.\n\tin: %s\n\tout: %s\n\tgroupversion: %s\n\tdiff: \n%s\n", + rt.in, rt.out, rt.groupVersion.String(), diff(expected, actual)) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/internal.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/internal.yaml new file mode 100644 index 000000000..3364c14fd --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/internal.yaml @@ -0,0 +1,161 @@ +API: + AdvertiseAddress: 192.168.2.2 + BindPort: 6443 + ControlPlaneEndpoint: "" +APIServerCertSANs: null +APIServerExtraArgs: + authorization-mode: Node,RBAC,Webhook +APIServerExtraVolumes: null +AuditPolicyConfiguration: + LogDir: /var/log/kubernetes/audit + LogMaxAge: 2 + Path: "" +BootstrapTokens: +- Description: "" + Expires: null + Groups: + - system:bootstrappers:kubeadm:default-node-token + TTL: 24h0m0s + Token: s73ybu.6tw6wnqgp5z0wb77 + Usages: + - signing + - authentication +CIImageRepository: "" +CertificatesDir: /etc/kubernetes/pki +ClusterName: kubernetes +ControllerManagerExtraArgs: null +ControllerManagerExtraVolumes: null +Etcd: + External: null + Local: + DataDir: /var/lib/etcd + ExtraArgs: null + Image: "" + PeerCertSANs: null + ServerCertSANs: null +FeatureGates: null +ImageRepository: k8s.gcr.io +KubeProxy: + Config: + bindAddress: 0.0.0.0 + clientConnection: + acceptContentTypes: "" + burst: 10 + contentType: application/vnd.kubernetes.protobuf + kubeconfig: /var/lib/kube-proxy/kubeconfig.conf + qps: 5 + clusterCIDR: "" + configSyncPeriod: 15m0s + conntrack: + max: null + maxPerCore: 32768 + min: 131072 + tcpCloseWaitTimeout: 1h0m0s + tcpEstablishedTimeout: 24h0m0s + enableProfiling: false + featureGates: + ServiceNodeExclusion: true + SupportIPVSProxyMode: true + healthzBindAddress: 0.0.0.0:10256 + hostnameOverride: "" + iptables: + masqueradeAll: false + masqueradeBit: 14 + minSyncPeriod: 0s + syncPeriod: 30s + ipvs: + excludeCIDRs: null + minSyncPeriod: 0s + scheduler: "" + syncPeriod: 30s + metricsBindAddress: 127.0.0.1:10249 + mode: "" + nodePortAddresses: null + oomScoreAdj: -999 + portRange: "" + resourceContainer: /kube-proxy + udpIdleTimeout: 250ms +KubeletConfiguration: + BaseConfig: + address: 0.0.0.0 + authentication: + anonymous: + enabled: false + webhook: + cacheTTL: 2m0s + enabled: true + x509: + clientCAFile: /etc/kubernetes/pki/ca.crt + authorization: + mode: Webhook + webhook: + cacheAuthorizedTTL: 5m0s + cacheUnauthorizedTTL: 30s + cgroupDriver: cgroupfs + cgroupsPerQOS: true + clusterDNS: + - 10.96.0.10 + clusterDomain: cluster.local + containerLogMaxFiles: 5 + containerLogMaxSize: 10Mi + contentType: application/vnd.kubernetes.protobuf + cpuCFSQuota: true + cpuManagerPolicy: none + cpuManagerReconcilePeriod: 10s + enableControllerAttachDetach: true + enableDebuggingHandlers: true + enforceNodeAllocatable: + - pods + eventBurst: 10 + eventRecordQPS: 5 + evictionHard: + imagefs.available: 15% + memory.available: 100Mi + nodefs.available: 10% + nodefs.inodesFree: 5% + evictionPressureTransitionPeriod: 5m0s + failSwapOn: true + fileCheckFrequency: 20s + hairpinMode: promiscuous-bridge + healthzBindAddress: 127.0.0.1 + healthzPort: 10248 + httpCheckFrequency: 20s + imageGCHighThresholdPercent: 85 + imageGCLowThresholdPercent: 80 + imageMinimumGCAge: 2m0s + iptablesDropBit: 15 + iptablesMasqueradeBit: 14 + kubeAPIBurst: 10 + kubeAPIQPS: 5 + makeIPTablesUtilChains: true + maxOpenFiles: 1000000 + maxPods: 110 + nodeStatusUpdateFrequency: 10s + oomScoreAdj: -999 + podPidsLimit: -1 + port: 10250 + registryBurst: 10 + registryPullQPS: 5 + resolvConf: /etc/resolv.conf + rotateCertificates: true + runtimeRequestTimeout: 2m0s + serializeImagePulls: true + staticPodPath: /etc/kubernetes/manifests + streamingConnectionIdleTimeout: 4h0m0s + syncFrequency: 1m0s + volumeStatsAggPeriod: 1m0s +KubernetesVersion: v1.10.2 +Networking: + DNSDomain: cluster.local + PodSubnet: "" + ServiceSubnet: 10.96.0.0/12 +NodeRegistration: + CRISocket: /var/run/dockershim.sock + KubeletExtraArgs: null + Name: master-1 + Taints: + - effect: NoSchedule + key: node-role.kubernetes.io/master +SchedulerExtraArgs: null +SchedulerExtraVolumes: null +UnifiedControlPlaneImage: "" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1.yaml new file mode 100644 index 000000000..1ad3415af --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1.yaml @@ -0,0 +1,149 @@ +api: + advertiseAddress: 192.168.2.2 + bindPort: 6443 + controlPlaneEndpoint: "" +apiVersion: kubeadm.k8s.io/v1alpha1 +auditPolicy: + logDir: /var/log/kubernetes/audit + logMaxAge: 2 + path: "" +authorizationModes: +- Node +- RBAC +- Webhook +certificatesDir: /etc/kubernetes/pki +cloudProvider: "" +clusterName: kubernetes +criSocket: /var/run/dockershim.sock +etcd: + caFile: "" + certFile: "" + dataDir: /var/lib/etcd + endpoints: null + image: "" + keyFile: "" +imageRepository: k8s.gcr.io +kind: MasterConfiguration +kubeProxy: + config: + bindAddress: 0.0.0.0 + clientConnection: + acceptContentTypes: "" + burst: 10 + contentType: application/vnd.kubernetes.protobuf + kubeconfig: /var/lib/kube-proxy/kubeconfig.conf + qps: 5 + clusterCIDR: "" + configSyncPeriod: 15m0s + conntrack: + max: null + maxPerCore: 32768 + min: 131072 + tcpCloseWaitTimeout: 1h0m0s + tcpEstablishedTimeout: 24h0m0s + enableProfiling: false + featureGates: + ServiceNodeExclusion: true + SupportIPVSProxyMode: true + healthzBindAddress: 0.0.0.0:10256 + hostnameOverride: "" + iptables: + masqueradeAll: false + masqueradeBit: 14 + minSyncPeriod: 0s + syncPeriod: 30s + ipvs: + excludeCIDRs: null + minSyncPeriod: 0s + scheduler: "" + syncPeriod: 30s + metricsBindAddress: 127.0.0.1:10249 + mode: "" + nodePortAddresses: null + oomScoreAdj: -999 + portRange: "" + resourceContainer: /kube-proxy + udpIdleTimeout: 250ms +kubeletConfiguration: + baseConfig: + address: 0.0.0.0 + authentication: + anonymous: + enabled: false + webhook: + cacheTTL: 2m0s + enabled: true + x509: + clientCAFile: /etc/kubernetes/pki/ca.crt + authorization: + mode: Webhook + webhook: + cacheAuthorizedTTL: 5m0s + cacheUnauthorizedTTL: 30s + cgroupDriver: cgroupfs + cgroupsPerQOS: true + clusterDNS: + - 10.96.0.10 + clusterDomain: cluster.local + containerLogMaxFiles: 5 + containerLogMaxSize: 10Mi + contentType: application/vnd.kubernetes.protobuf + cpuCFSQuota: true + cpuManagerPolicy: none + cpuManagerReconcilePeriod: 10s + enableControllerAttachDetach: true + enableDebuggingHandlers: true + enforceNodeAllocatable: + - pods + eventBurst: 10 + eventRecordQPS: 5 + evictionHard: + imagefs.available: 15% + memory.available: 100Mi + nodefs.available: 10% + nodefs.inodesFree: 5% + evictionPressureTransitionPeriod: 5m0s + failSwapOn: true + fileCheckFrequency: 20s + hairpinMode: promiscuous-bridge + healthzBindAddress: 127.0.0.1 + healthzPort: 10248 + httpCheckFrequency: 20s + imageGCHighThresholdPercent: 85 + imageGCLowThresholdPercent: 80 + imageMinimumGCAge: 2m0s + iptablesDropBit: 15 + iptablesMasqueradeBit: 14 + kubeAPIBurst: 10 + kubeAPIQPS: 5 + makeIPTablesUtilChains: true + maxOpenFiles: 1000000 + maxPods: 110 + nodeStatusUpdateFrequency: 10s + oomScoreAdj: -999 + podPidsLimit: -1 + port: 10250 + registryBurst: 10 + registryPullQPS: 5 + resolvConf: /etc/resolv.conf + runtimeRequestTimeout: 2m0s + serializeImagePulls: true + staticPodPath: /etc/kubernetes/manifests + streamingConnectionIdleTimeout: 4h0m0s + syncFrequency: 1m0s + volumeStatsAggPeriod: 1m0s +kubernetesVersion: v1.10.2 +networking: + dnsDomain: cluster.local + podSubnet: "" + serviceSubnet: 10.96.0.0/12 +nodeName: master-1 +privilegedPods: false +token: s73ybu.6tw6wnqgp5z0wb77 +tokenGroups: +- system:bootstrappers:kubeadm:default-node-token +tokenTTL: 24h0m0s +tokenUsages: +- signing +- authentication +unifiedControlPlaneImage: "" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1_without_TypeMeta.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1_without_TypeMeta.yaml new file mode 100644 index 000000000..dfaccd795 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha1_without_TypeMeta.yaml @@ -0,0 +1,146 @@ +# This file don't have TypeMeta set. kubeadm should then unmarshal it as a apiVersion=kubeadm.k8s.io/v1alpha1 and kind=MasterConfiguration +api: + advertiseAddress: 192.168.2.2 + bindPort: 6443 + controlPlaneEndpoint: "" +auditPolicy: + logDir: /var/log/kubernetes/audit + logMaxAge: 2 + path: "" +authorizationModes: +- Node +- RBAC +- Webhook +certificatesDir: /etc/kubernetes/pki +cloudProvider: "" +clusterName: kubernetes +criSocket: /var/run/dockershim.sock +etcd: + caFile: "" + certFile: "" + dataDir: /var/lib/etcd + endpoints: null + image: "" + keyFile: "" +imageRepository: k8s.gcr.io +kubeProxy: + config: + bindAddress: 0.0.0.0 + clientConnection: + acceptContentTypes: "" + burst: 10 + contentType: application/vnd.kubernetes.protobuf + kubeconfig: /var/lib/kube-proxy/kubeconfig.conf + qps: 5 + clusterCIDR: "" + configSyncPeriod: 15m0s + conntrack: + max: null + maxPerCore: 32768 + min: 131072 + tcpCloseWaitTimeout: 1h0m0s + tcpEstablishedTimeout: 24h0m0s + enableProfiling: false + featureGates: "SupportIPVSProxyMode=true,ServiceNodeExclusion=true" + healthzBindAddress: 0.0.0.0:10256 + hostnameOverride: "" + iptables: + masqueradeAll: false + masqueradeBit: 14 + minSyncPeriod: 0s + syncPeriod: 30s + ipvs: + excludeCIDRs: null + minSyncPeriod: 0s + scheduler: "" + syncPeriod: 30s + metricsBindAddress: 127.0.0.1:10249 + mode: "" + nodePortAddresses: null + oomScoreAdj: -999 + portRange: "" + resourceContainer: /kube-proxy + udpIdleTimeout: 250ms +kubeletConfiguration: + baseConfig: + address: 0.0.0.0 + authentication: + anonymous: + enabled: false + webhook: + cacheTTL: 2m0s + enabled: true + x509: + clientCAFile: /etc/kubernetes/pki/ca.crt + authorization: + mode: Webhook + webhook: + cacheAuthorizedTTL: 5m0s + cacheUnauthorizedTTL: 30s + cgroupDriver: cgroupfs + cgroupsPerQOS: true + clusterDNS: + - 10.96.0.10 + clusterDomain: cluster.local + containerLogMaxFiles: 5 + containerLogMaxSize: 10Mi + contentType: application/vnd.kubernetes.protobuf + cpuCFSQuota: true + cpuManagerPolicy: none + cpuManagerReconcilePeriod: 10s + enableControllerAttachDetach: true + enableDebuggingHandlers: true + enforceNodeAllocatable: + - pods + eventBurst: 10 + eventRecordQPS: 5 + evictionHard: + imagefs.available: 15% + memory.available: 100Mi + nodefs.available: 10% + nodefs.inodesFree: 5% + evictionPressureTransitionPeriod: 5m0s + failSwapOn: true + fileCheckFrequency: 20s + hairpinMode: promiscuous-bridge + healthzBindAddress: 127.0.0.1 + healthzPort: 10248 + httpCheckFrequency: 20s + imageGCHighThresholdPercent: 85 + imageGCLowThresholdPercent: 80 + imageMinimumGCAge: 2m0s + iptablesDropBit: 15 + iptablesMasqueradeBit: 14 + kubeAPIBurst: 10 + kubeAPIQPS: 5 + makeIPTablesUtilChains: true + maxOpenFiles: 1000000 + maxPods: 110 + nodeStatusUpdateFrequency: 10s + oomScoreAdj: -999 + podPidsLimit: -1 + port: 10250 + registryBurst: 10 + registryPullQPS: 5 + resolvConf: /etc/resolv.conf + runtimeRequestTimeout: 2m0s + serializeImagePulls: true + staticPodPath: /etc/kubernetes/manifests + streamingConnectionIdleTimeout: 4h0m0s + syncFrequency: 1m0s + volumeStatsAggPeriod: 1m0s +kubernetesVersion: v1.10.2 +networking: + dnsDomain: cluster.local + podSubnet: "" + serviceSubnet: 10.96.0.0/12 +nodeName: master-1 +privilegedPods: false +token: s73ybu.6tw6wnqgp5z0wb77 +tokenGroups: +- system:bootstrappers:kubeadm:default-node-token +tokenTTL: 24h0m0s +tokenUsages: +- signing +- authentication +unifiedControlPlaneImage: "" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha2.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha2.yaml new file mode 100644 index 000000000..f8af262b3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha2.yaml @@ -0,0 +1,148 @@ +api: + advertiseAddress: 192.168.2.2 + bindPort: 6443 + controlPlaneEndpoint: "" +apiServerExtraArgs: + authorization-mode: Node,RBAC,Webhook +apiVersion: kubeadm.k8s.io/v1alpha2 +auditPolicy: + logDir: /var/log/kubernetes/audit + logMaxAge: 2 + path: "" +bootstrapTokens: +- groups: + - system:bootstrappers:kubeadm:default-node-token + token: s73ybu.6tw6wnqgp5z0wb77 + ttl: 24h0m0s + usages: + - signing + - authentication +certificatesDir: /etc/kubernetes/pki +clusterName: kubernetes +etcd: + local: + dataDir: /var/lib/etcd + image: "" +imageRepository: k8s.gcr.io +kind: MasterConfiguration +kubeProxy: + config: + bindAddress: 0.0.0.0 + clientConnection: + acceptContentTypes: "" + burst: 10 + contentType: application/vnd.kubernetes.protobuf + kubeconfig: /var/lib/kube-proxy/kubeconfig.conf + qps: 5 + clusterCIDR: "" + configSyncPeriod: 15m0s + conntrack: + max: null + maxPerCore: 32768 + min: 131072 + tcpCloseWaitTimeout: 1h0m0s + tcpEstablishedTimeout: 24h0m0s + enableProfiling: false + featureGates: + ServiceNodeExclusion: true + SupportIPVSProxyMode: true + healthzBindAddress: 0.0.0.0:10256 + hostnameOverride: "" + iptables: + masqueradeAll: false + masqueradeBit: 14 + minSyncPeriod: 0s + syncPeriod: 30s + ipvs: + excludeCIDRs: null + minSyncPeriod: 0s + scheduler: "" + syncPeriod: 30s + metricsBindAddress: 127.0.0.1:10249 + mode: "" + nodePortAddresses: null + oomScoreAdj: -999 + portRange: "" + resourceContainer: /kube-proxy + udpIdleTimeout: 250ms +kubeletConfiguration: + baseConfig: + address: 0.0.0.0 + authentication: + anonymous: + enabled: false + webhook: + cacheTTL: 2m0s + enabled: true + x509: + clientCAFile: /etc/kubernetes/pki/ca.crt + authorization: + mode: Webhook + webhook: + cacheAuthorizedTTL: 5m0s + cacheUnauthorizedTTL: 30s + cgroupDriver: cgroupfs + cgroupsPerQOS: true + clusterDNS: + - 10.96.0.10 + clusterDomain: cluster.local + containerLogMaxFiles: 5 + containerLogMaxSize: 10Mi + contentType: application/vnd.kubernetes.protobuf + cpuCFSQuota: true + cpuManagerPolicy: none + cpuManagerReconcilePeriod: 10s + enableControllerAttachDetach: true + enableDebuggingHandlers: true + enforceNodeAllocatable: + - pods + eventBurst: 10 + eventRecordQPS: 5 + evictionHard: + imagefs.available: 15% + memory.available: 100Mi + nodefs.available: 10% + nodefs.inodesFree: 5% + evictionPressureTransitionPeriod: 5m0s + failSwapOn: true + fileCheckFrequency: 20s + hairpinMode: promiscuous-bridge + healthzBindAddress: 127.0.0.1 + healthzPort: 10248 + httpCheckFrequency: 20s + imageGCHighThresholdPercent: 85 + imageGCLowThresholdPercent: 80 + imageMinimumGCAge: 2m0s + iptablesDropBit: 15 + iptablesMasqueradeBit: 14 + kubeAPIBurst: 10 + kubeAPIQPS: 5 + makeIPTablesUtilChains: true + maxOpenFiles: 1000000 + maxPods: 110 + nodeStatusUpdateFrequency: 10s + oomScoreAdj: -999 + podPidsLimit: -1 + port: 10250 + registryBurst: 10 + registryPullQPS: 5 + resolvConf: /etc/resolv.conf + rotateCertificates: true + runtimeRequestTimeout: 2m0s + serializeImagePulls: true + staticPodPath: /etc/kubernetes/manifests + streamingConnectionIdleTimeout: 4h0m0s + syncFrequency: 1m0s + volumeStatsAggPeriod: 1m0s +kubernetesVersion: v1.10.2 +networking: + dnsDomain: cluster.local + podSubnet: "" + serviceSubnet: 10.96.0.0/12 +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: master-1 + taints: + - effect: NoSchedule + key: node-role.kubernetes.io/master +unifiedControlPlaneImage: "" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/node/internal.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/node/internal.yaml new file mode 100644 index 000000000..cd820682b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/node/internal.yaml @@ -0,0 +1,17 @@ +CACertPath: /etc/kubernetes/pki/ca.crt +ClusterName: kubernetes +DiscoveryFile: "" +DiscoveryTimeout: 5m0s +DiscoveryToken: abcdef.0123456789abcdef +DiscoveryTokenAPIServers: +- kube-apiserver:6443 +DiscoveryTokenCACertHashes: null +DiscoveryTokenUnsafeSkipCAVerification: true +FeatureGates: null +NodeRegistration: + CRISocket: /var/run/dockershim.sock + KubeletExtraArgs: null + Name: master-1 + Taints: null +TLSBootstrapToken: abcdef.0123456789abcdef +Token: abcdef.0123456789abcdef diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha1.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha1.yaml new file mode 100644 index 000000000..a85b233b6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha1.yaml @@ -0,0 +1,14 @@ +apiVersion: kubeadm.k8s.io/v1alpha1 +kind: NodeConfiguration +caCertPath: /etc/kubernetes/pki/ca.crt +clusterName: kubernetes +criSocket: /var/run/dockershim.sock +discoveryFile: "" +discoveryTimeout: 5m0s +discoveryToken: abcdef.0123456789abcdef +discoveryTokenAPIServers: +- kube-apiserver:6443 +discoveryTokenUnsafeSkipCAVerification: true +nodeName: master-1 +tlsBootstrapToken: abcdef.0123456789abcdef +token: abcdef.0123456789abcdef diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha2.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha2.yaml new file mode 100644 index 000000000..40754a588 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/node/v1alpha2.yaml @@ -0,0 +1,15 @@ +apiVersion: kubeadm.k8s.io/v1alpha2 +caCertPath: /etc/kubernetes/pki/ca.crt +clusterName: kubernetes +discoveryFile: "" +discoveryTimeout: 5m0s +discoveryToken: abcdef.0123456789abcdef +discoveryTokenAPIServers: +- kube-apiserver:6443 +discoveryTokenUnsafeSkipCAVerification: true +kind: NodeConfiguration +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: master-1 +tlsBootstrapToken: abcdef.0123456789abcdef +token: abcdef.0123456789abcdef diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml new file mode 100644 index 000000000..70ea5986e --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml @@ -0,0 +1,143 @@ +api: + advertiseAddress: 192.168.2.2 + bindPort: 6443 + controlPlaneEndpoint: "" +apiVersion: kubeadm.k8s.io/v1alpha2 +auditPolicy: + logDir: /var/log/kubernetes/audit + logMaxAge: 2 + path: "" +bootstrapTokens: +- groups: + - system:bootstrappers:kubeadm:default-node-token + token: s73ybu.6tw6wnqgp5z0wb77 + ttl: 24h0m0s + usages: + - signing + - authentication +certificatesDir: /var/lib/kubernetes/pki +clusterName: kubernetes +etcd: + local: + dataDir: /var/lib/etcd + image: "" +imageRepository: my-company.com +kind: MasterConfiguration +kubeProxy: + config: + bindAddress: 0.0.0.0 + clientConnection: + acceptContentTypes: "" + burst: 10 + contentType: application/vnd.kubernetes.protobuf + kubeconfig: /var/lib/kube-proxy/kubeconfig.conf + qps: 5 + clusterCIDR: "" + configSyncPeriod: 15m0s + conntrack: + max: null + maxPerCore: 32768 + min: 131072 + tcpCloseWaitTimeout: 1h0m0s + tcpEstablishedTimeout: 24h0m0s + enableProfiling: false + healthzBindAddress: 0.0.0.0:10256 + hostnameOverride: "" + iptables: + masqueradeAll: false + masqueradeBit: 14 + minSyncPeriod: 0s + syncPeriod: 30s + ipvs: + excludeCIDRs: null + minSyncPeriod: 0s + scheduler: "" + syncPeriod: 30s + metricsBindAddress: 127.0.0.1:10249 + mode: "" + nodePortAddresses: null + oomScoreAdj: -999 + portRange: "" + resourceContainer: /kube-proxy + udpIdleTimeout: 250ms +kubeletConfiguration: + baseConfig: + address: 0.0.0.0 + authentication: + anonymous: + enabled: false + webhook: + cacheTTL: 2m0s + enabled: true + x509: + clientCAFile: /etc/kubernetes/pki/ca.crt + authorization: + mode: Webhook + webhook: + cacheAuthorizedTTL: 5m0s + cacheUnauthorizedTTL: 30s + cgroupDriver: cgroupfs + cgroupsPerQOS: true + clusterDNS: + - 10.192.0.10 + clusterDomain: cluster.global + containerLogMaxFiles: 5 + containerLogMaxSize: 10Mi + contentType: application/vnd.kubernetes.protobuf + cpuCFSQuota: true + cpuManagerPolicy: none + cpuManagerReconcilePeriod: 10s + enableControllerAttachDetach: true + enableDebuggingHandlers: true + enforceNodeAllocatable: + - pods + eventBurst: 10 + eventRecordQPS: 5 + evictionHard: + imagefs.available: 15% + memory.available: 100Mi + nodefs.available: 10% + nodefs.inodesFree: 5% + evictionPressureTransitionPeriod: 5m0s + failSwapOn: true + fileCheckFrequency: 20s + hairpinMode: promiscuous-bridge + healthzBindAddress: 127.0.0.1 + healthzPort: 10248 + httpCheckFrequency: 20s + imageGCHighThresholdPercent: 85 + imageGCLowThresholdPercent: 80 + imageMinimumGCAge: 2m0s + iptablesDropBit: 15 + iptablesMasqueradeBit: 14 + kubeAPIBurst: 10 + kubeAPIQPS: 5 + makeIPTablesUtilChains: true + maxOpenFiles: 1000000 + maxPods: 110 + nodeStatusUpdateFrequency: 10s + oomScoreAdj: -999 + podPidsLimit: -1 + port: 10250 + registryBurst: 10 + registryPullQPS: 5 + resolvConf: /etc/resolv.conf + rotateCertificates: true + runtimeRequestTimeout: 2m0s + serializeImagePulls: true + staticPodPath: /etc/kubernetes/manifests + streamingConnectionIdleTimeout: 4h0m0s + syncFrequency: 1m0s + volumeStatsAggPeriod: 1m0s +kubernetesVersion: v1.10.2 +networking: + dnsDomain: cluster.global + podSubnet: "" + serviceSubnet: 10.196.0.0/12 +nodeRegistration: + criSocket: /var/run/criruntime.sock + name: master-1 + taints: + - effect: NoSchedule + key: node-role.kubernetes.io/master +unifiedControlPlaneImage: "" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml new file mode 100644 index 000000000..e2d6be82b --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml @@ -0,0 +1,15 @@ +# This file _should_ set TypeMeta, but at some point earlier we supported deserializing MasterConfigurations without TypeMeta, so we need to support that as long as we +# support the v1alpha1 API. In the meantime kubeadm will treat this as v1alpha1 automatically when unmarshalling. +api: + advertiseAddress: 192.168.2.2 + bindPort: 6443 +certificatesDir: /var/lib/kubernetes/pki +clusterName: kubernetes +criSocket: /var/run/criruntime.sock +imageRepository: my-company.com +kubernetesVersion: v1.10.2 +networking: + dnsDomain: cluster.global + serviceSubnet: 10.196.0.0/12 +nodeName: master-1 +token: s73ybu.6tw6wnqgp5z0wb77 diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml new file mode 100644 index 000000000..85c6b9b48 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml @@ -0,0 +1,15 @@ +apiVersion: kubeadm.k8s.io/v1alpha2 +caCertPath: /etc/kubernetes/pki/ca.crt +clusterName: kubernetes +discoveryFile: "" +discoveryTimeout: 5m0s +discoveryToken: abcdef.0123456789abcdef +discoveryTokenAPIServers: +- kube-apiserver:6443 +discoveryTokenUnsafeSkipCAVerification: true +kind: NodeConfiguration +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: thegopher +tlsBootstrapToken: abcdef.0123456789abcdef +token: abcdef.0123456789abcdef diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/node/incomplete.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/node/incomplete.yaml new file mode 100644 index 000000000..adb46dd5f --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/defaulting/node/incomplete.yaml @@ -0,0 +1,7 @@ +apiVersion: kubeadm.k8s.io/v1alpha1 +kind: NodeConfiguration +discoveryTokenAPIServers: +- kube-apiserver:6443 +discoveryTokenUnsafeSkipCAVerification: true +nodeName: thegopher +token: abcdef.0123456789abcdef diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/after.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/after.yaml new file mode 100644 index 000000000..a08a94a54 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/after.yaml @@ -0,0 +1,73 @@ +api: + advertiseAddress: 172.31.93.180 + bindPort: 6443 + controlPlaneEndpoint: "" +apiVersion: kubeadm.k8s.io/v1alpha1 +auditPolicy: + logDir: "" + path: "" +authorizationModes: +- Node +- RBAC +certificatesDir: /etc/kubernetes/pki +cloudProvider: aws +etcd: + caFile: "" + certFile: "" + dataDir: /var/lib/etcd + endpoints: null + image: "" + keyFile: "" +imageRepository: gcr.io/google_containers +kind: MasterConfiguration +kubeProxy: + config: + bindAddress: 0.0.0.0 + clientConnection: + acceptContentTypes: "" + burst: 10 + contentType: application/vnd.kubernetes.protobuf + kubeconfig: /var/lib/kube-proxy/kubeconfig.conf + qps: 5 + clusterCIDR: 192.168.0.0/16 + configSyncPeriod: 15m0s + conntrack: + max: null + maxPerCore: 32768 + min: 131072 + tcpCloseWaitTimeout: 1h0m0s + tcpEstablishedTimeout: 24h0m0s + enableProfiling: false + featureGates: + ServiceNodeExclusion: true + SupportIPVSProxyMode: true + healthzBindAddress: 0.0.0.0:10256 + hostnameOverride: "" + iptables: + masqueradeAll: false + masqueradeBit: 14 + minSyncPeriod: 0s + syncPeriod: 30s + ipvs: + excludeCIDRs: null + minSyncPeriod: 0s + scheduler: "" + syncPeriod: 30s + metricsBindAddress: 127.0.0.1:10249 + mode: "" + nodePortAddresses: null + oomScoreAdj: -999 + portRange: "" + resourceContainer: /kube-proxy + udpIdleTimeout: 0s +kubeletConfiguration: {} +kubernetesVersion: v1.9.6 +networking: + dnsDomain: cluster.local + podSubnet: 192.168.0.0/16 + serviceSubnet: 10.96.0.0/12 +nodeName: ip-172-31-93-180.ec2.internal +privilegedPods: false +token: 8d69af.cd3e1c58f6228dfc +tokenTTL: 24h0m0s +unifiedControlPlaneImage: "" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/before.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/before.yaml new file mode 100644 index 000000000..986f01675 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/v1alpha1_upgrade/before.yaml @@ -0,0 +1,64 @@ +# This MasterConfiguration object is wrong in two ways: it hasn't TypeMeta set, and .kubeProxy.config.featureGates is a string as it was in v1.9 +# In v1.10 however, it changed in an inbackwards-compatible way to a map[string]string, so we have to workaround that to unmarshal this object +api: + advertiseAddress: 172.31.93.180 + bindPort: 6443 +authorizationModes: +- Node +- RBAC +certificatesDir: /etc/kubernetes/pki +cloudProvider: aws +etcd: + caFile: "" + certFile: "" + dataDir: /var/lib/etcd + endpoints: null + image: "" + keyFile: "" +imageRepository: gcr.io/google_containers +kubeProxy: + config: + bindAddress: 0.0.0.0 + clientConnection: + acceptContentTypes: "" + burst: 10 + contentType: application/vnd.kubernetes.protobuf + kubeconfig: /var/lib/kube-proxy/kubeconfig.conf + qps: 5 + clusterCIDR: 192.168.0.0/16 + configSyncPeriod: 15m0s + conntrack: + max: null + maxPerCore: 32768 + min: 131072 + tcpCloseWaitTimeout: 1h0m0s + tcpEstablishedTimeout: 24h0m0s + enableProfiling: false + featureGates: "SupportIPVSProxyMode=true,ServiceNodeExclusion=true" + healthzBindAddress: 0.0.0.0:10256 + hostnameOverride: "" + iptables: + masqueradeAll: false + masqueradeBit: 14 + minSyncPeriod: 0s + syncPeriod: 30s + ipvs: + minSyncPeriod: 0s + scheduler: "" + syncPeriod: 30s + metricsBindAddress: 127.0.0.1:10249 + mode: "" + oomScoreAdj: -999 + portRange: "" + resourceContainer: /kube-proxy + udpTimeoutMilliseconds: 250ms +kubeletConfiguration: {} +kubernetesVersion: v1.9.6 +networking: + dnsDomain: cluster.local + podSubnet: 192.168.0.0/16 + serviceSubnet: 10.96.0.0/12 +nodeName: ip-172-31-93-180.ec2.internal +token: 8d69af.cd3e1c58f6228dfc +tokenTTL: 24h0m0s +unifiedControlPlaneImage: "" diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/validation/invalid_mastercfg.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/validation/invalid_mastercfg.yaml new file mode 100644 index 000000000..4935ea721 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/validation/invalid_mastercfg.yaml @@ -0,0 +1,12 @@ +api: + bindPort: 0 +certificatesDir: relativepath +clusterName: kubernetes +criSocket: relativepath +imageRepository: my-company.com +kubernetesVersion: v1.10.2 +networking: + dnsDomain: cluster.GLOBAL + serviceSubnet: 10.196.1000.0/100 +nodeName: MASTER +token: s7bu.6tw6wn diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/validation/invalid_nodecfg.yaml b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/validation/invalid_nodecfg.yaml new file mode 100644 index 000000000..a1d863485 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/validation/invalid_nodecfg.yaml @@ -0,0 +1,11 @@ +apiVersion: kubeadm.k8s.io/v1alpha1 +kind: NodeConfiguration +caCertPath: relativepath +criSocket: relativepath +discoveryFile: relativepath +discoveryTimeout: not-a-time +discoveryTokenAPIServers: +- INVALID_URL +discoveryTokenUnsafeSkipCAVerification: false +nodeName: NODE-1 +token: invalidtoken diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun/dryrun.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun/dryrun.go index d02206f23..7c18df067 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun/dryrun.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun/dryrun.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "io/ioutil" + "path/filepath" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -43,6 +44,13 @@ func NewFileToPrint(realPath, printPath string) FileToPrint { } } +// PrintDryRunFile is a helper method around PrintDryRunFiles +func PrintDryRunFile(fileName, realDir, printDir string, w io.Writer) error { + return PrintDryRunFiles([]FileToPrint{ + NewFileToPrint(filepath.Join(realDir, fileName), filepath.Join(printDir, fileName)), + }, w) +} + // PrintDryRunFiles prints the contents of the FileToPrints given to it to the writer w func PrintDryRunFiles(files []FileToPrint, w io.Writer) error { errs := []error{} @@ -81,7 +89,7 @@ func NewWaiter() apiclient.Waiter { // WaitForAPI just returns a dummy nil, to indicate that the program should just proceed func (w *Waiter) WaitForAPI() error { - fmt.Println("[dryrun] Would wait for the API Server's /healthz endpoint to return 'ok'") + fmt.Println("[dryrun] Would wait for the API Server's /healthz endpoint to return 'ok'") return nil } @@ -99,7 +107,7 @@ func (w *Waiter) WaitForPodToDisappear(podName string) error { // WaitForHealthyKubelet blocks until the kubelet /healthz endpoint returns 'ok' func (w *Waiter) WaitForHealthyKubelet(_ time.Duration, healthzEndpoint string) error { - fmt.Printf("[dryrun] Would make sure the kubelet %q endpoint is healthy\n", healthzEndpoint) + fmt.Printf("[dryrun] Would make sure the kubelet %q endpoint is healthy\n", healthzEndpoint) return nil } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/endpoint.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/endpoint.go index fb46d5b81..1e46ad9e6 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/endpoint.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/endpoint.go @@ -19,45 +19,101 @@ package util import ( "fmt" "net" + "net/url" "strconv" "k8s.io/apimachinery/pkg/util/validation" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" ) -// GetMasterEndpoint returns a properly formatted Master Endpoint -// or passes the error from GetMasterHostPort. -func GetMasterEndpoint(cfg *kubeadmapi.MasterConfiguration) (string, error) { +// GetMasterEndpoint returns a properly formatted endpoint for the control plane built according following rules: +// - If the api.ControlPlaneEndpoint is defined, use it. +// - if the api.ControlPlaneEndpoint is defined but without a port number, use the api.ControlPlaneEndpoint + api.BindPort is used. +// - Otherwise, in case the api.ControlPlaneEndpoint is not defined, use the api.AdvertiseAddress + the api.BindPort. +func GetMasterEndpoint(api *kubeadmapi.API) (string, error) { + // parse the bind port + var bindPort = strconv.Itoa(int(api.BindPort)) + if _, err := parsePort(bindPort); err != nil { + return "", fmt.Errorf("invalid value %q given for api.bindPort: %s", api.BindPort, err) + } - hostPort, err := GetMasterHostPort(cfg) - if err != nil { - return "", err + // parse the AdvertiseAddress + var ip = net.ParseIP(api.AdvertiseAddress) + if ip == nil { + return "", fmt.Errorf("invalid value `%s` given for api.advertiseAddress", api.AdvertiseAddress) + } + + // set the master url using cfg.API.AdvertiseAddress + the cfg.API.BindPort + masterURL := &url.URL{ + Scheme: "https", + Host: net.JoinHostPort(ip.String(), bindPort), } - return fmt.Sprintf("https://%s", hostPort), nil -} -// GetMasterHostPort returns a properly formatted Master IP/port pair or error -// if the IP address can not be parsed or port is outside the valid TCP range. -func GetMasterHostPort(cfg *kubeadmapi.MasterConfiguration) (string, error) { - var masterIP string - if len(cfg.API.ControlPlaneEndpoint) > 0 { - errs := validation.IsDNS1123Subdomain(cfg.API.ControlPlaneEndpoint) - if len(errs) > 0 { - return "", fmt.Errorf("error parsing `ControlPlaneEndpoint` to valid dns subdomain with errors: %s", errs) + // if the controlplane endpoint is defined + if len(api.ControlPlaneEndpoint) > 0 { + // parse the controlplane endpoint + var host, port string + var err error + if host, port, err = ParseHostPort(api.ControlPlaneEndpoint); err != nil { + return "", fmt.Errorf("invalid value %q given for api.controlPlaneEndpoint: %s", api.ControlPlaneEndpoint, err) } - masterIP = cfg.API.ControlPlaneEndpoint - } else { - ip := net.ParseIP(cfg.API.AdvertiseAddress) - if ip == nil { - return "", fmt.Errorf("error parsing address %s", cfg.API.AdvertiseAddress) + + // if a port is provided within the controlPlaneAddress warn the users we are using it, else use the bindport + if port != "" { + fmt.Println("[endpoint] WARNING: port specified in api.controlPlaneEndpoint overrides api.bindPort in the controlplane address") + } else { + port = bindPort + } + + // overrides the master url using the controlPlaneAddress (and eventually the bindport) + masterURL = &url.URL{ + Scheme: "https", + Host: net.JoinHostPort(host, port), } - masterIP = ip.String() } - if cfg.API.BindPort < 0 || cfg.API.BindPort > 65535 { - return "", fmt.Errorf("api server port must be between 0 and 65535") + return masterURL.String(), nil +} + +// ParseHostPort parses a network address of the form "host:port", "ipv4:port", "[ipv6]:port" into host and port; +// ":port" can be eventually omitted. +// If the string is not a valid representation of network address, ParseHostPort returns an error. +func ParseHostPort(hostport string) (string, string, error) { + var host, port string + var err error + + // try to split host and port + if host, port, err = net.SplitHostPort(hostport); err != nil { + // if SplitHostPort returns an error, the entire hostport is considered as host + host = hostport + } + + // if port is defined, parse and validate it + if port != "" { + if _, err := parsePort(port); err != nil { + return "", "", fmt.Errorf("port must be a valid number between 1 and 65535, inclusive") + } + } + + // if host is a valid IP, returns it + if ip := net.ParseIP(host); ip != nil { + return host, port, nil + } + + // if host is a validate RFC-1123 subdomain, returns it + if errs := validation.IsDNS1123Subdomain(host); len(errs) == 0 { + return host, port, nil + } + + return "", "", fmt.Errorf("host must be a valid IP address or a valid RFC-1123 DNS subdomain") +} + +// ParsePort parses a string representing a TCP port. +// If the string is not a valid representation of a TCP port, ParsePort returns an error. +func parsePort(port string) (int, error) { + if portInt, err := strconv.Atoi(port); err == nil && (1 <= portInt && portInt <= 65535) { + return portInt, nil } - hostPort := net.JoinHostPort(masterIP, strconv.Itoa(int(cfg.API.BindPort))) - return hostPort, nil + return 0, fmt.Errorf("port must be a valid number between 1 and 65535, inclusive") } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/endpoint_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/endpoint_test.go index bd3be4a7e..1bf738c09 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/endpoint_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/endpoint_test.go @@ -24,234 +24,322 @@ import ( func TestGetMasterEndpoint(t *testing.T) { var tests = []struct { - name string - cfg *kubeadmapi.MasterConfiguration - endpoint string - expected bool + name string + api *kubeadmapi.API + expectedEndpoint string + expectedError bool }{ { - name: "bad controlplane endpooint dns", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - ControlPlaneEndpoint: "bad!!cp.k8s.io", - BindPort: 1234, - }, + name: "use ControlPlaneEndpoint (dns) if fully defined", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "cp.k8s.io:1234", + BindPort: 4567, + AdvertiseAddress: "4.5.6.7", }, - endpoint: "https://cp.k8s.io:1234", - expected: false, + expectedEndpoint: "https://cp.k8s.io:1234", }, { - name: "both DNS and IP passed", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1.2.3.4", - ControlPlaneEndpoint: "cp.k8s.io", - BindPort: 1234, - }, + name: "use ControlPlaneEndpoint (ipv4) if fully defined", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "1.2.3.4:1234", + BindPort: 4567, + AdvertiseAddress: "4.5.6.7", }, - endpoint: "https://cp.k8s.io:1234", - expected: true, + expectedEndpoint: "https://1.2.3.4:1234", }, { - name: "valid DNS endpoint", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - ControlPlaneEndpoint: "cp.k8s.io", - BindPort: 1234, - }, + name: "use ControlPlaneEndpoint (ipv6) if fully defined", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "[2001:db8::1]:1234", + BindPort: 4567, + AdvertiseAddress: "4.5.6.7", }, - endpoint: "https://cp.k8s.io:1234", - expected: true, + expectedEndpoint: "https://[2001:db8::1]:1234", }, { - name: "valid IPv4 endpoint", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1.2.3.4", - BindPort: 1234, - }, + name: "use ControlPlaneEndpoint (dns) + BindPort if ControlPlaneEndpoint defined without port", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "cp.k8s.io", + BindPort: 4567, + AdvertiseAddress: "4.5.6.7", }, - endpoint: "https://1.2.3.4:1234", - expected: true, + expectedEndpoint: "https://cp.k8s.io:4567", }, { - name: "valid IPv6 endpoint", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "2001:db8::1", - BindPort: 4321, - }, + name: "use ControlPlaneEndpoint (ipv4) + BindPort if ControlPlaneEndpoint defined without port", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "1.2.3.4", + BindPort: 4567, + AdvertiseAddress: "4.5.6.7", }, - endpoint: "https://[2001:db8::1]:4321", - expected: true, + expectedEndpoint: "https://1.2.3.4:4567", }, { - name: "invalid IPv4 endpoint", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1.2.3.4", - BindPort: 1234, - }, + name: "use ControlPlaneEndpoint (ipv6) + BindPort if ControlPlaneEndpoint defined without port", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "2001:db8::1", + BindPort: 4567, + AdvertiseAddress: "4.5.6.7", }, - endpoint: "https://[1.2.3.4]:1234", - expected: false, + expectedEndpoint: "https://[2001:db8::1]:4567", }, { - name: "invalid IPv6 endpoint", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "2001:db8::1", - BindPort: 4321, - }, + name: "use AdvertiseAddress (ipv4) + BindPort if ControlPlaneEndpoint is not defined", + api: &kubeadmapi.API{ + BindPort: 4567, + AdvertiseAddress: "4.5.6.7", }, - endpoint: "https://2001:db8::1:4321", - expected: false, + expectedEndpoint: "https://4.5.6.7:4567", }, { - name: "invalid IPv4 AdvertiseAddress", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1.2.34", - BindPort: 1234, - }, + name: "use AdvertiseAddress (ipv6) + BindPort if ControlPlaneEndpoint is not defined", + api: &kubeadmapi.API{ + BindPort: 4567, + AdvertiseAddress: "2001:db8::1", }, - endpoint: "https://1.2.3.4:1234", - expected: false, + expectedEndpoint: "https://[2001:db8::1]:4567", }, { - name: "invalid IPv6 AdvertiseAddress", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "2001::db8::1", - BindPort: 4321, - }, + name: "fail if invalid BindPort", + api: &kubeadmapi.API{ + BindPort: 0, }, - endpoint: "https://[2001:db8::1]:4321", - expected: false, + expectedError: true, + }, + { + name: "fail if invalid ControlPlaneEndpoint (dns)", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "bad!!.cp.k8s.io", + BindPort: 4567, + }, + expectedError: true, + }, + { + name: "fail if invalid ControlPlaneEndpoint (ip4)", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "1..0", + BindPort: 4567, + }, + expectedError: true, + }, + { + name: "fail if invalid ControlPlaneEndpoint (ip6)", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "1200::AB00:1234::2552:7777:1313", + BindPort: 4567, + }, + expectedError: true, + }, + { + name: "fail if invalid ControlPlaneEndpoint (port)", + api: &kubeadmapi.API{ + ControlPlaneEndpoint: "cp.k8s.io:0", + BindPort: 4567, + }, + expectedError: true, + }, + { + name: "fail if invalid AdvertiseAddress (ip4)", + api: &kubeadmapi.API{ + AdvertiseAddress: "1..0", + BindPort: 4567, + }, + expectedError: true, + }, + { + name: "fail if invalid AdvertiseAddress (ip6)", + api: &kubeadmapi.API{ + AdvertiseAddress: "1200::AB00:1234::2552:7777:1313", + BindPort: 4567, + }, + expectedError: true, }, } + for _, rt := range tests { - actual, err := GetMasterEndpoint(rt.cfg) - if err != nil && rt.expected { - t.Error(err) + actualEndpoint, actualError := GetMasterEndpoint(rt.api) + + if (actualError != nil) && !rt.expectedError { + t.Errorf("%s unexpected failure: %v", rt.name, actualError) + continue + } else if (actualError == nil) && rt.expectedError { + t.Errorf("%s passed when expected to fail", rt.name) + continue } - if actual != rt.endpoint && rt.expected { - t.Errorf( - "%s test case failed:\n\texpected: %s\n\t actual: %s", - rt.name, - rt.endpoint, - (actual), - ) + + if actualEndpoint != rt.expectedEndpoint { + t.Errorf("%s returned invalid endpoint %s, expected %s", rt.name, actualEndpoint, rt.expectedEndpoint) } } } -func TestGetMasterHostPort(t *testing.T) { +func TestParseHostPort(t *testing.T) { + var tests = []struct { - name string - cfg *kubeadmapi.MasterConfiguration - hostPort string - expected bool + name string + hostport string + expectedHost string + expectedPort string + expectedError bool }{ { - name: "valid IPv4 master host and port", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1.2.3.4", - BindPort: 1234, - }, - }, - hostPort: "1.2.3.4:1234", - expected: true, + name: "valid dns", + hostport: "cp.k8s.io", + expectedHost: "cp.k8s.io", + expectedPort: "", }, { - name: "valid IPv6 master host port", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "2001:db8::1", - BindPort: 4321, - }, - }, - hostPort: "[2001:db8::1]:4321", - expected: true, + name: "valid dns:port", + hostport: "cp.k8s.io:1234", + expectedHost: "cp.k8s.io", + expectedPort: "1234", }, { - name: "invalid IPv4 address", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1.2.34", - BindPort: 1234, - }, - }, - hostPort: "1.2.3.4:1234", - expected: false, + name: "valid ip4", + hostport: "1.2.3.4", + expectedHost: "1.2.3.4", + expectedPort: "", }, { - name: "invalid IPv6 address", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "2001::db8::1", - BindPort: 4321, - }, - }, - hostPort: "[2001:db8::1]:4321", - expected: false, + name: "valid ipv4:port", + hostport: "1.2.3.4:1234", + expectedHost: "1.2.3.4", + expectedPort: "1234", }, { - name: "invalid TCP port number", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1.2.3.4", - BindPort: 987654321, - }, - }, - hostPort: "1.2.3.4:987654321", - expected: false, + name: "valid ipv6", + hostport: "2001:db8::1", + expectedHost: "2001:db8::1", + expectedPort: "", }, { - name: "invalid negative TCP port number", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1.2.3.4", - BindPort: -987654321, - }, - }, - hostPort: "1.2.3.4:-987654321", - expected: false, + name: "valid ipv6:port", + hostport: "[2001:db8::1]:1234", + expectedHost: "2001:db8::1", + expectedPort: "1234", }, { - name: "unspecified IPv4 TCP port", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1.2.3.4", - }, - }, - hostPort: "1.2.3.4:0", - expected: true, + name: "invalid port(not a number)", + hostport: "cp.k8s.io:aaa", + expectedError: true, }, { - name: "unspecified IPv6 TCP port", - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{ - AdvertiseAddress: "1:2:3::4", - }, - }, - hostPort: "[1:2:3::4]:0", - expected: true, + name: "invalid port(out of range, positive port number)", + hostport: "cp.k8s.io:987654321", + expectedError: true, + }, + { + name: "invalid port(out of range, negative port number)", + hostport: "cp.k8s.io:-987654321", + expectedError: true, + }, + { + name: "invalid port(out of range, negative port number)", + hostport: "cp.k8s.io:123:123", + expectedError: true, + }, + { + name: "invalid dns", + hostport: "bad!!cp.k8s.io", + expectedError: true, + }, + { + name: "invalid valid dns:port", + hostport: "bad!!cp.k8s.io:1234", + expectedError: true, + }, + { + name: "invalid ip4, but valid DNS", + hostport: "259.2.3.4", + expectedHost: "259.2.3.4", + }, + { + name: "invalid ip4", + hostport: "1..3.4", + expectedError: true, + }, + { + name: "invalid ip4(2):port", + hostport: "1..3.4:1234", + expectedError: true, + }, + { + name: "invalid ipv6", + hostport: "1200::AB00:1234::2552:7777:1313", + expectedError: true, + }, + { + name: "invalid ipv6:port", + hostport: "[1200::AB00:1234::2552:7777:1313]:1234", + expectedError: true, }, } + for _, rt := range tests { - actual, err := GetMasterHostPort(rt.cfg) - if err != nil && rt.expected { - t.Error(err) + actualHost, actualPort, actualError := ParseHostPort(rt.hostport) + + if (actualError != nil) && !rt.expectedError { + t.Errorf("%s unexpected failure: %v", rt.name, actualError) + continue + } else if (actualError == nil) && rt.expectedError { + t.Errorf("%s passed when expected to fail", rt.name) + continue + } + + if actualHost != rt.expectedHost { + t.Errorf("%s returned invalid host %s, expected %s", rt.name, actualHost, rt.expectedHost) + continue } - if actual != rt.hostPort && rt.expected { - t.Errorf( - "%s test case failed:\n\texpected: %s\n\t actual: %s", - rt.name, - rt.hostPort, - (actual), - ) + + if actualPort != rt.expectedPort { + t.Errorf("%s returned invalid port %s, expected %s", rt.name, actualPort, rt.expectedPort) + } + } +} + +func TestParsePort(t *testing.T) { + + var tests = []struct { + name string + port string + expectedPort int + expectedError bool + }{ + { + name: "valid port", + port: "1234", + expectedPort: 1234, + }, + { + name: "invalid port (not a number)", + port: "a", + expectedError: true, + }, + { + name: "invalid port (<1)", + port: "-10", + expectedError: true, + }, + { + name: "invalid port (>65535)", + port: "66535", + expectedError: true, + }, + } + + for _, rt := range tests { + actualPort, actualError := parsePort(rt.port) + + if (actualError != nil) && !rt.expectedError { + t.Errorf("%s unexpected failure: %v", rt.name, actualError) + continue + } else if (actualError == nil) && rt.expectedError { + t.Errorf("%s passed when expected to fail", rt.name) + continue + } + + if actualPort != rt.expectedPort { + t.Errorf("%s returned invalid port %d, expected %d", rt.name, actualPort, rt.expectedPort) } } } diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error.go index 61327cf56..4eaf984fd 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error.go @@ -22,7 +22,6 @@ import ( "strings" utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/kubernetes/cmd/kubeadm/app/preflight" ) const ( @@ -34,10 +33,6 @@ const ( ValidationExitCode = 3 ) -type debugError interface { - DebugError() (msg string, args []interface{}) -} - // fatal prints the message if set and then exits. func fatal(msg string, code int) { if len(msg) > 0 { @@ -57,16 +52,22 @@ func fatal(msg string, code int) { // This method is generic to the command in use and may be used by non-Kubectl // commands. func CheckErr(err error) { - checkErr("", err, fatal) + checkErr(err, fatal) +} + +// preflightError allows us to know if the error is a preflight error or not +// defining the interface here avoids an import cycle of pulling in preflight into the util package +type preflightError interface { + Preflight() bool } // checkErr formats a given error as a string and calls the passed handleErr -// func with that string and an kubectl exit code. -func checkErr(prefix string, err error, handleErr func(string, int)) { +// func with that string and an exit code. +func checkErr(err error, handleErr func(string, int)) { switch err.(type) { case nil: return - case *preflight.Error: + case preflightError: handleErr(err.Error(), PreFlightExitCode) case utilerrors.Aggregate: handleErr(err.Error(), ValidationExitCode) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error_test.go index c28a6cc05..20c4fdb8f 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error_test.go @@ -19,10 +19,12 @@ package util import ( "fmt" "testing" - - "k8s.io/kubernetes/cmd/kubeadm/app/preflight" ) +type pferror struct{} + +func (p *pferror) Preflight() bool { return true } +func (p *pferror) Error() string { return "" } func TestCheckErr(t *testing.T) { var codeReturned int errHandle := func(err string, code int) { @@ -35,12 +37,12 @@ func TestCheckErr(t *testing.T) { }{ {nil, 0}, {fmt.Errorf(""), DefaultErrorExitCode}, - {&preflight.Error{}, PreFlightExitCode}, + {&pferror{}, PreFlightExitCode}, } for _, rt := range tokenTest { codeReturned = 0 - checkErr("", rt.e, errHandle) + checkErr(rt.e, errHandle) if codeReturned != rt.expected { t.Errorf( "failed checkErr:\n\texpected: %d\n\t actual: %d", diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/BUILD index 8a439c273..852e914f8 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/BUILD @@ -6,6 +6,7 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd", visibility = ["//visibility:public"], deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/staticpod:go_default_library", "//vendor/github.com/coreos/etcd/clientv3:go_default_library", @@ -17,7 +18,10 @@ go_test( name = "go_default_test", srcs = ["etcd_test.go"], embed = [":go_default_library"], - deps = ["//cmd/kubeadm/test:go_default_library"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/test:go_default_library", + ], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/etcd.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/etcd.go index 3bd3e8034..3470da6b5 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/etcd.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/etcd.go @@ -26,6 +26,7 @@ import ( "github.com/coreos/etcd/clientv3" "github.com/coreos/etcd/pkg/transport" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod" ) @@ -133,14 +134,10 @@ func (c Client) GetVersion() (string, error) { return "", err } for _, v := range versions { - if clusterVersion == "" { - // This is the first version we've seen - clusterVersion = v - } else if v != clusterVersion { + if clusterVersion != "" && clusterVersion != v { return "", fmt.Errorf("etcd cluster contains endpoints with mismatched versions: %v", versions) - } else { - clusterVersion = v } + clusterVersion = v } if clusterVersion == "" { return "", fmt.Errorf("could not determine cluster etcd version") @@ -220,3 +217,8 @@ func (c Client) WaitForClusterAvailable(delay time.Duration, retries int, retryI } return false, fmt.Errorf("timeout waiting for etcd cluster to be available") } + +// CheckConfigurationIsHA returns true if the given MasterConfiguration etcd block appears to be an HA configuration. +func CheckConfigurationIsHA(cfg *kubeadmapi.Etcd) bool { + return cfg.External != nil && len(cfg.External.Endpoints) > 1 +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/etcd_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/etcd_test.go index 1003f6cf2..58e133eca 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/etcd_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/etcd/etcd_test.go @@ -22,6 +22,7 @@ import ( "path/filepath" "testing" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" testutil "k8s.io/kubernetes/cmd/kubeadm/test" ) @@ -83,6 +84,64 @@ spec: type: DirectoryOrCreate name: etcd-certs status: {} +` + secureExposedEtcdPod = ` +apiVersion: v1 +kind: Pod +metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + creationTimestamp: null + labels: + component: etcd + tier: control-plane + name: etcd + namespace: kube-system +spec: + containers: + - command: + - etcd + - --advertise-client-urls=https://10.0.5.5:2379 + - --data-dir=/var/lib/etcd + - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key + - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt + - --listen-client-urls=https://[::0:0]:2379 + - --peer-client-cert-auth=true + - --cert-file=/etc/kubernetes/pki/etcd/server.crt + - --key-file=/etc/kubernetes/pki/etcd/server.key + - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt + - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt + - --client-cert-auth=true + image: k8s.gcr.io/etcd-amd64:3.1.12 + livenessProbe: + exec: + command: + - /bin/sh + - -ec + - ETCDCTL_API=3 etcdctl --endpoints=https://[::1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt + --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key + get foo + failureThreshold: 8 + initialDelaySeconds: 15 + timeoutSeconds: 15 + name: etcd + resources: {} + volumeMounts: + - mountPath: /var/lib/etcd + name: etcd-data + - mountPath: /etc/kubernetes/pki/etcd + name: etcd-certs + hostNetwork: true + volumes: + - hostPath: + path: /var/lib/etcd + type: DirectoryOrCreate + name: etcd-data + - hostPath: + path: /etc/kubernetes/pki/etcd + type: DirectoryOrCreate + name: etcd-certs +status: {} ` insecureEtcdPod = `# generated by kubeadm v1.9.6 apiVersion: v1 @@ -144,6 +203,13 @@ func TestPodManifestHasTLS(t *testing.T) { writeManifest: true, expectErr: false, }, + { + description: "secure exposed etcd returns true", + podYaml: secureExposedEtcdPod, + hasTLS: true, + writeManifest: true, + expectErr: false, + }, { description: "insecure etcd returns false", podYaml: insecureEtcdPod, @@ -195,3 +261,50 @@ func TestPodManifestHasTLS(t *testing.T) { } } } + +func TestCheckConfigurationIsHA(t *testing.T) { + var tests = []struct { + name string + cfg *kubeadmapi.Etcd + expected bool + }{ + { + name: "HA etcd", + cfg: &kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"10.100.0.1:2379", "10.100.0.2:2379", "10.100.0.3:2379"}, + }, + }, + expected: true, + }, + { + name: "single External etcd", + cfg: &kubeadmapi.Etcd{ + External: &kubeadmapi.ExternalEtcd{ + Endpoints: []string{"10.100.0.1:2379"}, + }, + }, + expected: false, + }, + { + name: "local etcd", + cfg: &kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{}, + }, + expected: false, + }, + { + name: "empty etcd struct", + cfg: &kubeadmapi.Etcd{}, + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if isHA := CheckConfigurationIsHA(test.cfg); isHA != test.expected { + t.Errorf("expected isHA to be %v, got %v", test.expected, isHA) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/marshal.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/marshal.go index 0d2d8df59..aa201cabb 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/marshal.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/marshal.go @@ -17,12 +17,16 @@ limitations under the License. package util import ( + "errors" "fmt" + yaml "gopkg.in/yaml.v2" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" clientsetscheme "k8s.io/client-go/kubernetes/scheme" + kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" ) // MarshalToYaml marshals an object into yaml. @@ -31,6 +35,8 @@ func MarshalToYaml(obj runtime.Object, gv schema.GroupVersion) ([]byte, error) { } // MarshalToYamlForCodecs marshals an object into yaml using the specified codec +// TODO: Is specifying the gv really needed here? +// TODO: Can we support json out of the box easily here? func MarshalToYamlForCodecs(obj runtime.Object, gv schema.GroupVersion, codecs serializer.CodecFactory) ([]byte, error) { mediaType := "application/yaml" info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType) @@ -48,6 +54,8 @@ func UnmarshalFromYaml(buffer []byte, gv schema.GroupVersion) (runtime.Object, e } // UnmarshalFromYamlForCodecs unmarshals yaml into an object using the specified codec +// TODO: Is specifying the gv really needed here? +// TODO: Can we support json out of the box easily here? func UnmarshalFromYamlForCodecs(buffer []byte, gv schema.GroupVersion, codecs serializer.CodecFactory) (runtime.Object, error) { mediaType := "application/yaml" info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType) @@ -58,3 +66,69 @@ func UnmarshalFromYamlForCodecs(buffer []byte, gv schema.GroupVersion, codecs se decoder := codecs.DecoderToVersion(info.Serializer, gv) return runtime.Decode(decoder, buffer) } + +// GroupVersionKindFromBytes parses the bytes and returns the gvk +func GroupVersionKindFromBytes(buffer []byte, codecs serializer.CodecFactory) (schema.GroupVersionKind, error) { + + decoded, err := LoadYAML(buffer) + if err != nil { + return schema.EmptyObjectKind.GroupVersionKind(), fmt.Errorf("unable to decode config from bytes: %v", err) + } + kindStr, apiVersionStr := "", "" + + // As there was a bug in kubeadm v1.10 and earlier that made the YAML uploaded to the cluster configmap NOT have metav1.TypeMeta information + // we need to populate this here manually. If kind or apiVersion is empty, we know the apiVersion is v1alpha1, as by the time kubeadm had this bug, + // it could only write + // TODO: Remove this "hack" in v1.12 when we know the ConfigMap always contains v1alpha2 content written by kubeadm v1.11. Also, we will drop support for + // v1alpha1 in v1.12 + kind := decoded["kind"] + apiVersion := decoded["apiVersion"] + if kind == nil || len(kind.(string)) == 0 { + kindStr = "MasterConfiguration" + } else { + kindStr = kind.(string) + } + if apiVersion == nil || len(apiVersion.(string)) == 0 { + apiVersionStr = kubeadmapiv1alpha1.SchemeGroupVersion.String() + } else { + apiVersionStr = apiVersion.(string) + } + gv, err := schema.ParseGroupVersion(apiVersionStr) + if err != nil { + return schema.EmptyObjectKind.GroupVersionKind(), fmt.Errorf("unable to parse apiVersion: %v", err) + } + + return gv.WithKind(kindStr), nil +} + +// LoadYAML is a small wrapper around go-yaml that ensures all nested structs are map[string]interface{} instead of map[interface{}]interface{}. +func LoadYAML(bytes []byte) (map[string]interface{}, error) { + var decoded map[interface{}]interface{} + if err := yaml.Unmarshal(bytes, &decoded); err != nil { + return map[string]interface{}{}, fmt.Errorf("couldn't unmarshal YAML: %v", err) + } + + converted, ok := convert(decoded).(map[string]interface{}) + if !ok { + return map[string]interface{}{}, errors.New("yaml is not a map") + } + + return converted, nil +} + +// https://stackoverflow.com/questions/40737122/convert-yaml-to-json-without-struct-golang +func convert(i interface{}) interface{} { + switch x := i.(type) { + case map[interface{}]interface{}: + m2 := map[string]interface{}{} + for k, v := range x { + m2[k.(string)] = convert(v) + } + return m2 + case []interface{}: + for i, v := range x { + x[i] = convert(v) + } + } + return i +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/marshal_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/marshal_test.go new file mode 100644 index 000000000..33c37afc5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/marshal_test.go @@ -0,0 +1,125 @@ +/* +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 util + +import ( + "reflect" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" +) + +func TestMarshalUnmarshalYaml(t *testing.T) { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "someName", + Namespace: "testNamespace", + Labels: map[string]string{ + "test": "yes", + }, + }, + Spec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyAlways, + }, + } + + bytes, err := MarshalToYaml(pod, corev1.SchemeGroupVersion) + if err != nil { + t.Fatalf("unexpected error marshalling: %v", err) + } + + t.Logf("\n%s", bytes) + + obj2, err := UnmarshalFromYaml(bytes, corev1.SchemeGroupVersion) + if err != nil { + t.Fatalf("unexpected error marshalling: %v", err) + } + + pod2, ok := obj2.(*corev1.Pod) + if !ok { + t.Fatal("did not get a Pod") + } + + if pod2.Name != pod.Name { + t.Errorf("expected %q, got %q", pod.Name, pod2.Name) + } + + if pod2.Namespace != pod.Namespace { + t.Errorf("expected %q, got %q", pod.Namespace, pod2.Namespace) + } + + if !reflect.DeepEqual(pod2.Labels, pod.Labels) { + t.Errorf("expected %v, got %v", pod.Labels, pod2.Labels) + } + + if pod2.Spec.RestartPolicy != pod.Spec.RestartPolicy { + t.Errorf("expected %q, got %q", pod.Spec.RestartPolicy, pod2.Spec.RestartPolicy) + } +} + +func TestMarshalUnmarshalToYamlForCodecs(t *testing.T) { + cfg := &kubeadmapiext.MasterConfiguration{ + API: kubeadmapiext.API{ + AdvertiseAddress: "10.100.0.1", + BindPort: 4332, + }, + NodeName: "testNode", + NoTaintMaster: true, + Networking: kubeadmapiext.Networking{ + ServiceSubnet: "10.100.0.0/24", + PodSubnet: "10.100.1.0/24", + }, + } + + bytes, err := MarshalToYamlForCodecs(cfg, kubeadmapiext.SchemeGroupVersion, scheme.Codecs) + if err != nil { + t.Fatalf("unexpected error marshalling MasterConfiguration: %v", err) + } + t.Logf("\n%s", bytes) + + obj, err := UnmarshalFromYamlForCodecs(bytes, kubeadmapiext.SchemeGroupVersion, scheme.Codecs) + if err != nil { + t.Fatalf("unexpected error unmarshalling MasterConfiguration: %v", err) + } + + cfg2, ok := obj.(*kubeadmapiext.MasterConfiguration) + if !ok { + t.Fatal("did not get MasterConfiguration back") + } + + if cfg2.API.AdvertiseAddress != cfg.API.AdvertiseAddress { + t.Errorf("expected %q, got %q", cfg.API.AdvertiseAddress, cfg2.API.AdvertiseAddress) + } + if cfg2.API.BindPort != cfg.API.BindPort { + t.Errorf("expected %d, got %d", cfg.API.BindPort, cfg2.API.BindPort) + } + if cfg2.NodeName != cfg.NodeName { + t.Errorf("expected %q, got %q", cfg.NodeName, cfg2.NodeName) + } + if cfg2.NoTaintMaster != cfg.NoTaintMaster { + t.Errorf("expected %v, got %v", cfg.NoTaintMaster, cfg2.NoTaintMaster) + } + if cfg2.Networking.ServiceSubnet != cfg.Networking.ServiceSubnet { + t.Errorf("expected %v, got %v", cfg.Networking.ServiceSubnet, cfg2.Networking.ServiceSubnet) + } + if cfg2.Networking.PodSubnet != cfg.Networking.PodSubnet { + t.Errorf("expected %v, got %v", cfg.Networking.PodSubnet, cfg2.Networking.PodSubnet) + } +} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod/utils.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod/utils.go index 57b1b0137..76d2ecb32 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod/utils.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod/utils.go @@ -64,9 +64,10 @@ func ComponentPod(container v1.Container, volumes map[string]v1.Volume) v1.Pod { Labels: map[string]string{"component": container.Name, "tier": "control-plane"}, }, Spec: v1.PodSpec{ - Containers: []v1.Container{container}, - HostNetwork: true, - Volumes: VolumeMapToSlice(volumes), + Containers: []v1.Container{container}, + PriorityClassName: "system-cluster-critical", + HostNetwork: true, + Volumes: VolumeMapToSlice(volumes), }, } } @@ -101,7 +102,7 @@ func ComponentProbe(cfg *kubeadmapi.MasterConfiguration, componentName string, p func EtcdProbe(cfg *kubeadmapi.MasterConfiguration, componentName string, port int, certsDir string, CACertName string, CertName string, KeyName string) *v1.Probe { tlsFlags := fmt.Sprintf("--cacert=%[1]s/%[2]s --cert=%[1]s/%[3]s --key=%[1]s/%[4]s", certsDir, CACertName, CertName, KeyName) // etcd pod is alive if a linearizable get succeeds. - cmd := fmt.Sprintf("ETCDCTL_API=3 etcdctl --endpoints=%s:%d %s get foo", GetProbeAddress(cfg, componentName), port, tlsFlags) + cmd := fmt.Sprintf("ETCDCTL_API=3 etcdctl --endpoints=https://[%s]:%d %s get foo", GetProbeAddress(cfg, componentName), port, tlsFlags) return &v1.Probe{ Handler: v1.Handler{ @@ -241,8 +242,8 @@ func GetProbeAddress(cfg *kubeadmapi.MasterConfiguration, componentName string) return addr } case componentName == kubeadmconstants.Etcd: - if cfg.Etcd.ExtraArgs != nil { - if arg, exists := cfg.Etcd.ExtraArgs[etcdListenClientURLsArg]; exists { + if cfg.Etcd.Local != nil && cfg.Etcd.Local.ExtraArgs != nil { + if arg, exists := cfg.Etcd.Local.ExtraArgs[etcdListenClientURLsArg]; exists { // Use the first url in the listen-client-urls if multiple url's are specified. if strings.ContainsAny(arg, ",") { arg = strings.Split(arg, ",")[0] @@ -253,6 +254,13 @@ func GetProbeAddress(cfg *kubeadmapi.MasterConfiguration, componentName string) } // Return the IP if the URL contains an address instead of a name. if ip := net.ParseIP(parsedURL.Hostname()); ip != nil { + // etcdctl doesn't support auto-converting zero addresses into loopback addresses + if ip.Equal(net.IPv4zero) { + return "127.0.0.1" + } + if ip.Equal(net.IPv6zero) { + return net.IPv6loopback.String() + } return ip.String() } // Use the local resolver to try resolving the name within the URL. diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod/utils_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod/utils_test.go index 7d9bd315b..815e8434d 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod/utils_test.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod/utils_test.go @@ -207,8 +207,10 @@ func TestEtcdProbe(t *testing.T) { name: "valid etcd probe using listen-client-urls IPv4 addresses", cfg: &kubeadmapi.MasterConfiguration{ Etcd: kubeadmapi.Etcd{ - ExtraArgs: map[string]string{ - "listen-client-urls": "http://1.2.3.4:2379,http://4.3.2.1:2379"}, + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://1.2.3.4:2379,http://4.3.2.1:2379"}, + }, }, }, component: kubeadmconstants.Etcd, @@ -217,14 +219,88 @@ func TestEtcdProbe(t *testing.T) { cacert: "ca1", cert: "cert1", key: "key1", - expected: "ETCDCTL_API=3 etcdctl --endpoints=1.2.3.4:1 --cacert=secretsA/ca1 --cert=secretsA/cert1 --key=secretsA/key1 get foo", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[1.2.3.4]:1 --cacert=secretsA/ca1 --cert=secretsA/cert1 --key=secretsA/key1 get foo", + }, + { + name: "valid etcd probe using listen-client-urls unspecified IPv6 address", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://[0:0:0:0:0:0:0:0]:2379"}, + }, + }, + }, + component: kubeadmconstants.Etcd, + port: 1, + certsDir: "secretsB", + cacert: "ca2", + cert: "cert2", + key: "key2", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[::1]:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", + }, + { + name: "valid etcd probe using listen-client-urls unspecified IPv6 address 2", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://[::0:0]:2379"}, + }, + }, + }, + component: kubeadmconstants.Etcd, + port: 1, + certsDir: "secretsB", + cacert: "ca2", + cert: "cert2", + key: "key2", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[::1]:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", + }, + { + name: "valid etcd probe using listen-client-urls unspecified IPv6 address 3", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://[::]:2379"}, + }, + }, + }, + component: kubeadmconstants.Etcd, + port: 1, + certsDir: "secretsB", + cacert: "ca2", + cert: "cert2", + key: "key2", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[::1]:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", + }, + { + name: "valid etcd probe using listen-client-urls unspecified IPv4 address", + cfg: &kubeadmapi.MasterConfiguration{ + Etcd: kubeadmapi.Etcd{ + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://1.2.3.4:2379,http://4.3.2.1:2379"}, + }, + }, + }, + component: kubeadmconstants.Etcd, + port: 1, + certsDir: "secretsA", + cacert: "ca1", + cert: "cert1", + key: "key1", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[1.2.3.4]:1 --cacert=secretsA/ca1 --cert=secretsA/cert1 --key=secretsA/key1 get foo", }, { name: "valid etcd probe using listen-client-urls IPv6 addresses", cfg: &kubeadmapi.MasterConfiguration{ Etcd: kubeadmapi.Etcd{ - ExtraArgs: map[string]string{ - "listen-client-urls": "http://[2001:db8::1]:2379,http://[2001:db8::2]:2379"}, + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://[2001:db8::1]:2379,http://[2001:db8::2]:2379"}, + }, }, }, component: kubeadmconstants.Etcd, @@ -233,14 +309,16 @@ func TestEtcdProbe(t *testing.T) { cacert: "ca2", cert: "cert2", key: "key2", - expected: "ETCDCTL_API=3 etcdctl --endpoints=2001:db8::1:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[2001:db8::1]:1 --cacert=secretsB/ca2 --cert=secretsB/cert2 --key=secretsB/key2 get foo", }, { name: "valid IPv4 etcd probe using hostname for listen-client-urls", cfg: &kubeadmapi.MasterConfiguration{ Etcd: kubeadmapi.Etcd{ - ExtraArgs: map[string]string{ - "listen-client-urls": "http://localhost:2379"}, + Local: &kubeadmapi.LocalEtcd{ + ExtraArgs: map[string]string{ + "listen-client-urls": "http://localhost:2379"}, + }, }, }, component: kubeadmconstants.Etcd, @@ -249,7 +327,7 @@ func TestEtcdProbe(t *testing.T) { cacert: "ca3", cert: "cert3", key: "key3", - expected: "ETCDCTL_API=3 etcdctl --endpoints=127.0.0.1:1 --cacert=secretsC/ca3 --cert=secretsC/cert3 --key=secretsC/key3 get foo", + expected: "ETCDCTL_API=3 etcdctl --endpoints=https://[127.0.0.1]:1 --cacert=secretsC/ca3 --cert=secretsC/cert3 --key=secretsC/key3 get foo", }, } for _, rt := range tests { @@ -286,8 +364,9 @@ func TestComponentPod(t *testing.T) { Name: "foo", }, }, - HostNetwork: true, - Volumes: []v1.Volume{}, + PriorityClassName: "system-cluster-critical", + HostNetwork: true, + Volumes: []v1.Volume{}, }, }, }, diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/token/BUILD b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/token/BUILD deleted file mode 100644 index d16eb5018..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/token/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["tokens_test.go"], - embed = [":go_default_library"], - deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["tokens.go"], - importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/token", - deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/token/tokens.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/token/tokens.go deleted file mode 100644 index 6be926000..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/token/tokens.go +++ /dev/null @@ -1,125 +0,0 @@ -/* -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 token - -import ( - "bufio" - "crypto/rand" - "fmt" - "regexp" - - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" -) - -const ( - // TokenIDBytes defines a number of bytes used for a token id - TokenIDBytes = 6 - // TokenSecretBytes defines a number of bytes used for a secret - TokenSecretBytes = 16 -) - -var ( - // TokenIDRegexpString defines token's id regular expression pattern - TokenIDRegexpString = "^([a-z0-9]{6})$" - // TokenIDRegexp is a compiled regular expression of TokenIDRegexpString - TokenIDRegexp = regexp.MustCompile(TokenIDRegexpString) - // TokenRegexpString defines id.secret regular expression pattern - TokenRegexpString = "^([a-z0-9]{6})\\.([a-z0-9]{16})$" - // TokenRegexp is a compiled regular expression of TokenRegexpString - TokenRegexp = regexp.MustCompile(TokenRegexpString) -) - -const validBootstrapTokenChars = "0123456789abcdefghijklmnopqrstuvwxyz" - -func randBytes(length int) (string, error) { - // len("0123456789abcdefghijklmnopqrstuvwxyz") = 36 which doesn't evenly divide - // the possible values of a byte: 256 mod 36 = 4. Discard any random bytes we - // read that are >= 252 so the bytes we evenly divide the character set. - const maxByteValue = 252 - - var ( - b byte - err error - token = make([]byte, length) - ) - - reader := bufio.NewReaderSize(rand.Reader, length*2) - for i := range token { - for { - if b, err = reader.ReadByte(); err != nil { - return "", err - } - if b < maxByteValue { - break - } - } - - token[i] = validBootstrapTokenChars[int(b)%len(validBootstrapTokenChars)] - } - - return string(token), nil -} - -// GenerateToken generates a new token with a token ID that is valid as a -// Kubernetes DNS label. -// For more info, see kubernetes/pkg/util/validation/validation.go. -func GenerateToken() (string, error) { - tokenID, err := randBytes(TokenIDBytes) - if err != nil { - return "", err - } - - tokenSecret, err := randBytes(TokenSecretBytes) - if err != nil { - return "", err - } - - return fmt.Sprintf("%s.%s", tokenID, tokenSecret), nil -} - -// ParseTokenID tries and parse a valid token ID from a string. -// An error is returned in case of failure. -func ParseTokenID(s string) error { - if !TokenIDRegexp.MatchString(s) { - return fmt.Errorf("token ID [%q] was not of form [%q]", s, TokenIDRegexpString) - } - return nil -} - -// ParseToken tries and parse a valid token from a string. -// A token ID and token secret are returned in case of success, an error otherwise. -func ParseToken(s string) (string, string, error) { - split := TokenRegexp.FindStringSubmatch(s) - if len(split) != 3 { - return "", "", fmt.Errorf("token [%q] was not of form [%q]", s, TokenRegexpString) - } - return split[1], split[2], nil -} - -// BearerToken returns a string representation of the passed token. -func BearerToken(d *kubeadmapi.TokenDiscovery) string { - return fmt.Sprintf("%s.%s", d.ID, d.Secret) -} - -// ValidateToken validates whether a token is well-formed. -// In case it's not, the corresponding error is returned as well. -func ValidateToken(d *kubeadmapi.TokenDiscovery) (bool, error) { - if _, _, err := ParseToken(d.ID + "." + d.Secret); err != nil { - return false, err - } - return true, nil -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/token/tokens_test.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/token/tokens_test.go deleted file mode 100644 index 4146a0270..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/token/tokens_test.go +++ /dev/null @@ -1,173 +0,0 @@ -/* -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 token - -import ( - "testing" - - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" -) - -func TestTokenParse(t *testing.T) { - var tests = []struct { - token string - expected bool - }{ - {token: "1234567890123456789012", expected: false}, // invalid parcel size - {token: "12345.1234567890123456", expected: false}, // invalid parcel size - {token: ".1234567890123456", expected: false}, // invalid parcel size - {token: "123456:1234567890.123456", expected: false}, // invalid separation - {token: "abcdef:1234567890123456", expected: false}, // invalid separation - {token: "Abcdef.1234567890123456", expected: false}, // invalid token id - {token: "123456.AABBCCDDEEFFGGHH", expected: false}, // invalid token secret - {token: "abcdef.1234567890123456", expected: true}, - {token: "123456.aabbccddeeffgghh", expected: true}, - } - - for _, rt := range tests { - _, _, actual := ParseToken(rt.token) - if (actual == nil) != rt.expected { - t.Errorf( - "failed ParseToken for this token: [%s]\n\texpected: %t\n\t actual: %t", - rt.token, - rt.expected, - (actual == nil), - ) - } - } - -} - -func TestParseTokenID(t *testing.T) { - var tests = []struct { - tokenID string - expected bool - }{ - {tokenID: "", expected: false}, - {tokenID: "1234567890123456789012", expected: false}, - {tokenID: "12345", expected: false}, - {tokenID: "Abcdef", expected: false}, - {tokenID: "abcdef", expected: true}, - {tokenID: "123456", expected: true}, - } - for _, rt := range tests { - actual := ParseTokenID(rt.tokenID) - if (actual == nil) != rt.expected { - t.Errorf( - "failed ParseTokenID for this token ID: [%s]\n\texpected: %t\n\t actual: %t", - rt.tokenID, - rt.expected, - (actual == nil), - ) - } - } -} - -func TestValidateToken(t *testing.T) { - var tests = []struct { - token *kubeadmapi.TokenDiscovery - expected bool - }{ - {token: &kubeadmapi.TokenDiscovery{ID: "", Secret: ""}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "1234567890123456789012", Secret: ""}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "", Secret: "1234567890123456789012"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "12345", Secret: "1234567890123456"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "Abcdef", Secret: "1234567890123456"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "123456", Secret: "AABBCCDDEEFFGGHH"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "abc*ef", Secret: "1234567890123456"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "abcdef", Secret: "123456789*123456"}, expected: false}, - {token: &kubeadmapi.TokenDiscovery{ID: "abcdef", Secret: "1234567890123456"}, expected: true}, - {token: &kubeadmapi.TokenDiscovery{ID: "123456", Secret: "aabbccddeeffgghh"}, expected: true}, - {token: &kubeadmapi.TokenDiscovery{ID: "abc456", Secret: "1234567890123456"}, expected: true}, - {token: &kubeadmapi.TokenDiscovery{ID: "abcdef", Secret: "123456ddeeffgghh"}, expected: true}, - } - for _, rt := range tests { - valid, actual := ValidateToken(rt.token) - if (actual == nil) != rt.expected { - t.Errorf( - "failed ValidateToken for this token ID: [%s]\n\texpected: %t\n\t actual: %t", - rt.token, - rt.expected, - (actual == nil), - ) - } - if (valid == true) != rt.expected { - t.Errorf( - "failed ValidateToken for this token ID: [%s]\n\texpected: %t\n\t actual: %t", - rt.token, - rt.expected, - (actual == nil), - ) - } - } -} - -func TestGenerateToken(t *testing.T) { - token, err := GenerateToken() - if err != nil { - t.Fatalf("GenerateToken returned an unexpected error: %+v", err) - } - tokenID, tokenSecret, err := ParseToken(token) - if err != nil { - t.Fatalf("GenerateToken returned an unexpected error: %+v", err) - } - if len(tokenID) != 6 { - t.Errorf("failed GenerateToken first part length:\n\texpected: 6\n\t actual: %d", len(tokenID)) - } - if len(tokenSecret) != 16 { - t.Errorf("failed GenerateToken second part length:\n\texpected: 16\n\t actual: %d", len(tokenSecret)) - } -} - -func TestRandBytes(t *testing.T) { - var randTest = []int{ - 0, - 1, - 2, - 3, - 100, - } - - for _, rt := range randTest { - actual, err := randBytes(rt) - if err != nil { - t.Errorf("failed randBytes: %v", err) - } - if len(actual) != rt { - t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt, len(actual)) - } - } -} - -func TestBearerToken(t *testing.T) { - var tests = []struct { - token *kubeadmapi.TokenDiscovery - expected string - }{ - {token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}, expected: "foo.bar"}, // should use default - } - for _, rt := range tests { - actual := BearerToken(rt.token) - if actual != rt.expected { - t.Errorf( - "failed BearerToken:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual, - ) - } - } -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubeadm/test/util.go b/vendor/k8s.io/kubernetes/cmd/kubeadm/test/util.go index 025df6503..afe20702c 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubeadm/test/util.go +++ b/vendor/k8s.io/kubernetes/cmd/kubeadm/test/util.go @@ -53,13 +53,15 @@ func SetupMasterConfigurationFile(t *testing.T, tmpdir string, cfg *kubeadmapi.M } cfgTemplate := template.Must(template.New("init").Parse(dedent.Dedent(` - apiVersion: kubeadm.k8s.io/v1alpha1 + apiVersion: kubeadm.k8s.io/v1alpha2 kind: MasterConfiguration certificatesDir: {{.CertificatesDir}} api: - advertiseAddress: {{.API.AdvertiseAddress}} - bindPort: {{.API.BindPort}} - nodeName: {{.NodeName}} + advertiseAddress: {{.API.AdvertiseAddress}} + bindPort: {{.API.BindPort}} + nodeRegistration: + name: {{.NodeRegistration.Name}} + kubernetesVersion: v1.10.0 `))) f, err := os.Create(cfgPath) diff --git a/vendor/k8s.io/kubernetes/cmd/kubectl/BUILD b/vendor/k8s.io/kubernetes/cmd/kubectl/BUILD index 3e361cdd2..01be15a76 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubectl/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubectl/BUILD @@ -20,9 +20,9 @@ go_library( visibility = ["//visibility:private"], deps = [ "//pkg/kubectl/cmd:go_default_library", + "//pkg/kubectl/util/logs:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/logs:go_default_library", "//vendor/k8s.io/client-go/plugin/pkg/client/auth:go_default_library", ], ) @@ -35,10 +35,7 @@ filegroup( filegroup( name = "all-srcs", - srcs = [ - ":package-srcs", - "//cmd/kubectl/app:all-srcs", - ], + srcs = [":package-srcs"], tags = ["automanaged"], visibility = [ "//build/visible_to:cmd_kubectl_CONSUMERS", diff --git a/vendor/k8s.io/kubernetes/cmd/kubectl/app/BUILD b/vendor/k8s.io/kubernetes/cmd/kubectl/app/BUILD deleted file mode 100644 index ea19ac1d7..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubectl/app/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["kubectl.go"], - importpath = "k8s.io/kubernetes/cmd/kubectl/app", - visibility = [ - "//build/visible_to:cmd_kubectl_app_CONSUMERS", - ], - deps = [ - "//pkg/client/metrics/prometheus:go_default_library", - "//pkg/kubectl/cmd:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/kubectl/util/logs:go_default_library", - "//pkg/version/prometheus:go_default_library", - "//vendor/k8s.io/client-go/plugin/pkg/client/auth:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = [ - "//build/visible_to:cmd_kubectl_app_CONSUMERS", - ], -) diff --git a/vendor/k8s.io/kubernetes/cmd/kubectl/app/kubectl.go b/vendor/k8s.io/kubernetes/cmd/kubectl/app/kubectl.go deleted file mode 100644 index ddcdfb922..000000000 --- a/vendor/k8s.io/kubernetes/cmd/kubectl/app/kubectl.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -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 app - -import ( - "os" - - _ "k8s.io/client-go/plugin/pkg/client/auth" // kubectl auth providers. - _ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration - "k8s.io/kubernetes/pkg/kubectl/cmd" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/util/logs" - _ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration -) - -/* -WARNING: this logic is duplicated, with minor changes, in cmd/hyperkube/kubectl.go -Any salient changes here will need to be manually reflected in that file. -*/ - -// Run runs the kubectl program (creates and executes a new cobra command). -func Run() error { - logs.InitLogs() - defer logs.FlushLogs() - - cmd := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr) - return cmd.Execute() -} diff --git a/vendor/k8s.io/kubernetes/cmd/kubectl/kubectl.go b/vendor/k8s.io/kubernetes/cmd/kubectl/kubectl.go index 5ca950ed4..b568c7fa6 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubectl/kubectl.go +++ b/vendor/k8s.io/kubernetes/cmd/kubectl/kubectl.go @@ -26,8 +26,8 @@ import ( "github.com/spf13/pflag" utilflag "k8s.io/apiserver/pkg/util/flag" - "k8s.io/apiserver/pkg/util/logs" "k8s.io/kubernetes/pkg/kubectl/cmd" + "k8s.io/kubernetes/pkg/kubectl/util/logs" // Import to initialize client auth plugins. _ "k8s.io/client-go/plugin/pkg/client/auth" diff --git a/vendor/k8s.io/kubernetes/cmd/kubelet/BUILD b/vendor/k8s.io/kubernetes/cmd/kubelet/BUILD index e787c70f7..690698e8b 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubelet/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubelet/BUILD @@ -21,6 +21,7 @@ go_library( "//cmd/kubelet/app:go_default_library", "//pkg/client/metrics/prometheus:go_default_library", "//pkg/version/prometheus:go_default_library", + "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/logs:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/cmd/kubelet/app/BUILD b/vendor/k8s.io/kubernetes/cmd/kubelet/app/BUILD index cbfb90ff1..b2f3efbc7 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubelet/app/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kubelet/app/BUILD @@ -84,6 +84,7 @@ go_library( "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/validation:go_default_library", "//pkg/kubelet/cadvisor:go_default_library", "//pkg/kubelet/certificate:go_default_library", "//pkg/kubelet/certificate/bootstrap:go_default_library", @@ -91,14 +92,14 @@ go_library( "//pkg/kubelet/config:go_default_library", "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/dockershim:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + "//pkg/kubelet/dockershim/network/cni:go_default_library", + "//pkg/kubelet/dockershim/network/kubenet:go_default_library", "//pkg/kubelet/dockershim/remote:go_default_library", "//pkg/kubelet/eviction:go_default_library", "//pkg/kubelet/eviction/api:go_default_library", "//pkg/kubelet/kubeletconfig:go_default_library", "//pkg/kubelet/kubeletconfig/configfiles:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/cni:go_default_library", - "//pkg/kubelet/network/kubenet:go_default_library", "//pkg/kubelet/server:go_default_library", "//pkg/kubelet/server/streaming:go_default_library", "//pkg/kubelet/types:go_default_library", @@ -109,6 +110,7 @@ go_library( "//pkg/util/io:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/node:go_default_library", + "//pkg/util/nsenter:go_default_library", "//pkg/util/oom:go_default_library", "//pkg/util/rlimit:go_default_library", "//pkg/version:go_default_library", @@ -169,6 +171,7 @@ go_library( "//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library", "//vendor/k8s.io/client-go/util/certificate:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:linux": [ "//vendor/golang.org/x/exp/inotify:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kubelet/app/options/container_runtime.go b/vendor/k8s.io/kubernetes/cmd/kubelet/app/options/container_runtime.go index 4225e8dd5..d07cfb699 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubelet/app/options/container_runtime.go +++ b/vendor/k8s.io/kubernetes/cmd/kubelet/app/options/container_runtime.go @@ -29,14 +29,11 @@ const ( // When these values are updated, also update test/e2e/framework/util.go defaultPodSandboxImageName = "k8s.gcr.io/pause" defaultPodSandboxImageVersion = "3.1" - // From pkg/kubelet/rkt/rkt.go to avoid circular import - defaultRktAPIServiceEndpoint = "localhost:15441" ) var ( defaultPodSandboxImage = defaultPodSandboxImageName + - "-" + runtime.GOARCH + ":" + - defaultPodSandboxImageVersion + ":" + defaultPodSandboxImageVersion ) // NewContainerRuntimeOptions will create a new ContainerRuntimeOptions with @@ -48,13 +45,13 @@ func NewContainerRuntimeOptions() *config.ContainerRuntimeOptions { } return &config.ContainerRuntimeOptions{ - ContainerRuntime: kubetypes.DockerContainerRuntime, - DockerEndpoint: dockerEndpoint, - DockershimRootDirectory: "/var/lib/dockershim", - DockerDisableSharedPID: true, - PodSandboxImage: defaultPodSandboxImage, - ImagePullProgressDeadline: metav1.Duration{Duration: 1 * time.Minute}, - RktAPIEndpoint: defaultRktAPIServiceEndpoint, - ExperimentalDockershim: false, + ContainerRuntime: kubetypes.DockerContainerRuntime, + RedirectContainerStreaming: false, + DockerEndpoint: dockerEndpoint, + DockershimRootDirectory: "/var/lib/dockershim", + DockerDisableSharedPID: true, + PodSandboxImage: defaultPodSandboxImage, + ImagePullProgressDeadline: metav1.Duration{Duration: 1 * time.Minute}, + ExperimentalDockershim: false, } } diff --git a/vendor/k8s.io/kubernetes/cmd/kubelet/app/options/options.go b/vendor/k8s.io/kubernetes/cmd/kubelet/app/options/options.go index edac8e9b2..048637bda 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubelet/app/options/options.go +++ b/vendor/k8s.io/kubernetes/cmd/kubelet/app/options/options.go @@ -54,7 +54,6 @@ const defaultRootDir = "/var/lib/kubelet" type KubeletFlags struct { KubeConfig string BootstrapKubeconfig string - RotateCertificates bool // Insert a probability of random errors during calls to the master. ChaosChance float64 @@ -151,10 +150,6 @@ type KubeletFlags struct { // This flag, if set, will avoid including `EvictionHard` limits while computing Node Allocatable. // Refer to [Node Allocatable](https://git.k8s.io/community/contributors/design-proposals/node-allocatable.md) doc for more information. ExperimentalNodeAllocatableIgnoreEvictionThreshold bool - // A set of ResourceName=Percentage (e.g. memory=50%) pairs that describe - // how pod resource requests are reserved at the QoS level. - // Currently only memory is supported. [default=none]" - ExperimentalQOSReserved map[string]string // Node Labels are the node labels to add when registering the node in the cluster NodeLabels map[string]string // volumePluginDir is the full path of the directory in which to search @@ -174,6 +169,9 @@ type KubeletFlags struct { // bootstrapCheckpointPath is the path to the directory containing pod checkpoints to // run on restore BootstrapCheckpointPath string + // NodeStatusMaxImages caps the number of images reported in Node.Status.Images. + // This is an experimental, short-term flag to help with node scalability. + NodeStatusMaxImages int32 // DEPRECATED FLAGS // minimumGCAge is the minimum age for a finished container before it is @@ -197,10 +195,8 @@ type KubeletFlags struct { // 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 - // enable gathering custom metrics. - EnableCustomMetrics bool // allowPrivileged enables containers to request privileged mode. - // Defaults to false. + // Defaults to true. AllowPrivileged bool // hostNetworkSources is a comma-separated list of sources from which the // Kubelet allows pods to use of host network. Defaults to "*". Valid @@ -235,20 +231,20 @@ func NewKubeletFlags() *KubeletFlags { NonMasqueradeCIDR: "10.0.0.0/8", RegisterSchedulable: true, ExperimentalKernelMemcgNotification: false, - ExperimentalQOSReserved: make(map[string]string), RemoteRuntimeEndpoint: remoteRuntimeEndpoint, - RotateCertificates: false, - // TODO(#54161:v1.11.0): Remove --enable-custom-metrics flag, it is deprecated. - EnableCustomMetrics: false, - NodeLabels: make(map[string]string), - VolumePluginDir: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/", - RegisterNode: true, - SeccompProfileRoot: filepath.Join(defaultRootDir, "seccomp"), - HostNetworkSources: []string{kubetypes.AllSource}, - HostPIDSources: []string{kubetypes.AllSource}, - HostIPCSources: []string{kubetypes.AllSource}, - // TODO(#56523): default CAdvisorPort to 0 (disabled) and deprecate it - CAdvisorPort: 4194, + NodeLabels: make(map[string]string), + VolumePluginDir: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/", + RegisterNode: true, + SeccompProfileRoot: filepath.Join(defaultRootDir, "seccomp"), + HostNetworkSources: []string{kubetypes.AllSource}, + HostPIDSources: []string{kubetypes.AllSource}, + HostIPCSources: []string{kubetypes.AllSource}, + // TODO(#56523:v1.12.0): Remove --cadvisor-port, it has been deprecated since v1.10 + CAdvisorPort: 0, + // TODO(#58010:v1.13.0): Remove --allow-privileged, it is deprecated + AllowPrivileged: true, + // prior to the introduction of this flag, there was a hardcoded cap of 50 images + NodeStatusMaxImages: 50, } } @@ -260,6 +256,9 @@ func ValidateKubeletFlags(f *KubeletFlags) error { if f.CAdvisorPort != 0 && utilvalidation.IsValidPortNum(int(f.CAdvisorPort)) != nil { return fmt.Errorf("invalid configuration: CAdvisorPort (--cadvisor-port) %v must be between 0 and 65535, inclusive", f.CAdvisorPort) } + if f.NodeStatusMaxImages < -1 { + return fmt.Errorf("invalid configuration: NodeStatusMaxImages (--node-status-max-images) must be -1 or greater") + } return nil } @@ -355,7 +354,6 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { "If the file specified by --kubeconfig does not exist, the bootstrap kubeconfig is used to request a client certificate from the API server. "+ "On success, a kubeconfig file referencing the generated client certificate and key is written to the path specified by --kubeconfig. "+ "The client certificate and key file will be stored in the directory pointed by --cert-dir.") - fs.BoolVar(&f.RotateCertificates, "rotate-certificates", f.RotateCertificates, " Auto rotate the kubelet client certificates by requesting new certificates from the kube-apiserver when the certificate expiration approaches.") fs.BoolVar(&f.ReallyCrashForTesting, "really-crash-for-testing", f.ReallyCrashForTesting, "If true, when panics occur crash. Intended for testing.") fs.Float64Var(&f.ChaosChance, "chaos-chance", f.ChaosChance, "If > 0.0, introduce random client errors and latency. Intended for testing.") @@ -363,7 +361,7 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { fs.BoolVar(&f.RunOnce, "runonce", f.RunOnce, "If true, exit after spawning pods from static pod files or remote urls. Exclusive with --enable-server") fs.BoolVar(&f.EnableServer, "enable-server", f.EnableServer, "Enable the Kubelet's server") - fs.StringVar(&f.HostnameOverride, "hostname-override", f.HostnameOverride, "If non-empty, will use this string as identification instead of the actual hostname.") + fs.StringVar(&f.HostnameOverride, "hostname-override", f.HostnameOverride, "If non-empty, will use this string as identification instead of the actual hostname. If --cloud-provider is set, the cloud provider determines the name of the node (consult cloud provider documentation to determine if and how the hostname is used).") fs.StringVar(&f.NodeIP, "node-ip", f.NodeIP, "IP address of the node. If set, kubelet will use this IP address for the node") @@ -372,12 +370,12 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { fs.StringVar(&f.CertDirectory, "cert-dir", f.CertDirectory, "The directory where the TLS certs are located. "+ "If --tls-cert-file and --tls-private-key-file are provided, this flag will be ignored.") - fs.StringVar(&f.CloudProvider, "cloud-provider", f.CloudProvider, "The provider for cloud services. Specify empty string for running with no cloud provider.") + fs.StringVar(&f.CloudProvider, "cloud-provider", f.CloudProvider, "The provider for cloud services. Specify empty string for running with no cloud provider. If set, the cloud provider determines the name of the node (consult cloud provider documentation to determine if and how the hostname is used).") fs.StringVar(&f.CloudConfigFile, "cloud-config", f.CloudConfigFile, "The path to the cloud provider configuration file. Empty string for no configuration file.") fs.StringVar(&f.RootDirectory, "root-dir", f.RootDirectory, "Directory path for managing kubelet files (volume mounts,etc).") - fs.Var(&f.DynamicConfigDir, "dynamic-config-dir", "The Kubelet will use this directory for checkpointing downloaded configurations and tracking configuration health. The Kubelet will create this directory if it does not already exist. The path may be absolute or relative; relative paths start at the Kubelet's current working directory. Providing this flag enables dynamic Kubelet configuration. Presently, you must also enable the DynamicKubeletConfig feature gate to pass this flag.") + fs.Var(&f.DynamicConfigDir, "dynamic-config-dir", "The Kubelet will use this directory for checkpointing downloaded configurations and tracking configuration health. The Kubelet will create this directory if it does not already exist. The path may be absolute or relative; relative paths start at the Kubelet's current working directory. Providing this flag enables dynamic Kubelet configuration. The DynamicKubeletConfig feature gate must be enabled to pass this flag; this gate currently defaults to true because the feature is beta.") fs.BoolVar(&f.RegisterNode, "register-node", f.RegisterNode, "Register the node with the apiserver. If --kubeconfig is not provided, this flag is irrelevant, as the Kubelet won't have an apiserver to register with. Default=true.") fs.Var(utiltaints.NewTaintsVar(&f.RegisterWithTaints), "register-with-taints", "Register the node with the given list of taints (comma separated \"=:\"). No-op if register-node is false.") @@ -385,13 +383,12 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { // EXPERIMENTAL FLAGS fs.StringVar(&f.ExperimentalMounterPath, "experimental-mounter-path", f.ExperimentalMounterPath, "[Experimental] Path of mounter binary. Leave empty to use the default mount.") - fs.StringSliceVar(&f.AllowedUnsafeSysctls, "experimental-allowed-unsafe-sysctls", f.AllowedUnsafeSysctls, "Comma-separated whitelist of unsafe sysctls or unsafe sysctl patterns (ending in *). Use these at your own risk.") + fs.StringSliceVar(&f.AllowedUnsafeSysctls, "allowed-unsafe-sysctls", f.AllowedUnsafeSysctls, "Comma-separated whitelist of unsafe sysctls or unsafe sysctl patterns (ending in *). Use these at your own risk. Sysctls feature gate is enabled by default.") fs.BoolVar(&f.ExperimentalKernelMemcgNotification, "experimental-kernel-memcg-notification", f.ExperimentalKernelMemcgNotification, "If enabled, the kubelet will integrate with the kernel memcg notification to determine if memory eviction thresholds are crossed rather than polling.") fs.StringVar(&f.RemoteRuntimeEndpoint, "container-runtime-endpoint", f.RemoteRuntimeEndpoint, "[Experimental] The endpoint of remote runtime service. Currently unix socket is supported on Linux, and tcp is supported on windows. Examples:'unix:///var/run/dockershim.sock', 'tcp://localhost:3735'") fs.StringVar(&f.RemoteImageEndpoint, "image-service-endpoint", f.RemoteImageEndpoint, "[Experimental] The endpoint of remote image service. If not specified, it will be the same with container-runtime-endpoint by default. Currently unix socket is supported on Linux, and tcp is supported on windows. Examples:'unix:///var/run/dockershim.sock', 'tcp://localhost:3735'") fs.BoolVar(&f.ExperimentalCheckNodeCapabilitiesBeforeMount, "experimental-check-node-capabilities-before-mount", f.ExperimentalCheckNodeCapabilitiesBeforeMount, "[Experimental] if set true, the kubelet will check the underlying node for required components (binaries, etc.) before performing the mount") fs.BoolVar(&f.ExperimentalNodeAllocatableIgnoreEvictionThreshold, "experimental-allocatable-ignore-eviction", f.ExperimentalNodeAllocatableIgnoreEvictionThreshold, "When set to 'true', Hard Eviction Thresholds will be ignored while calculating Node Allocatable. See https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/ for more details. [default=false]") - fs.Var(flag.NewMapStringString(&f.ExperimentalQOSReserved), "experimental-qos-reserved", "A set of ResourceName=Percentage (e.g. memory=50%) pairs that describe how pod resource requests are reserved at the QoS level. Currently only memory is supported. [default=none]") bindableNodeLabels := flag.ConfigurationMap(f.NodeLabels) fs.Var(&bindableNodeLabels, "node-labels", " Labels to add when registering the node in the cluster. Labels must be key=value pairs separated by ','.") fs.StringVar(&f.VolumePluginDir, "volume-plugin-dir", f.VolumePluginDir, "The full path of the directory in which to search for additional third party volume plugins") @@ -399,12 +396,13 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { fs.BoolVar(&f.ExitOnLockContention, "exit-on-lock-contention", f.ExitOnLockContention, "Whether kubelet should exit upon lock-file contention.") fs.StringVar(&f.SeccompProfileRoot, "seccomp-profile-root", f.SeccompProfileRoot, " Directory path for seccomp profiles.") fs.StringVar(&f.BootstrapCheckpointPath, "bootstrap-checkpoint-path", f.BootstrapCheckpointPath, " Path to to the directory where the checkpoints are stored") + fs.Int32Var(&f.NodeStatusMaxImages, "node-status-max-images", f.NodeStatusMaxImages, " The maximum number of images to report in Node.Status.Images. If -1 is specified, no cap will be applied. Default: 50") // DEPRECATED FLAGS fs.StringVar(&f.BootstrapKubeconfig, "experimental-bootstrap-kubeconfig", f.BootstrapKubeconfig, "") fs.MarkDeprecated("experimental-bootstrap-kubeconfig", "Use --bootstrap-kubeconfig") fs.Int32Var(&f.CAdvisorPort, "cadvisor-port", f.CAdvisorPort, "The port of the localhost cAdvisor endpoint (set to 0 to disable)") - fs.MarkDeprecated("cadvisor-port", "The default will change to 0 (disabled) in 1.12, and the cadvisor port will be removed entirely in 1.13") + fs.MarkDeprecated("cadvisor-port", "The default will change to 0 (disabled) in 1.11, and the cadvisor port will be removed entirely in 1.12") fs.DurationVar(&f.MinimumGCAge.Duration, "minimum-container-ttl-duration", f.MinimumGCAge.Duration, "Minimum age for a finished container before it is garbage collected. Examples: '300ms', '10s' or '2h45m'") fs.MarkDeprecated("minimum-container-ttl-duration", "Use --eviction-hard or --eviction-soft instead. Will be removed in a future version.") fs.Int32Var(&f.MaxPerPodContainerCount, "maximum-dead-containers-per-container", f.MaxPerPodContainerCount, "Maximum number of old instances to retain per container. Each container takes up some disk space.") @@ -419,11 +417,8 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { fs.MarkDeprecated("non-masquerade-cidr", "will be removed in a future version") fs.BoolVar(&f.KeepTerminatedPodVolumes, "keep-terminated-pod-volumes", f.KeepTerminatedPodVolumes, "Keep terminated pod volumes mounted to the node after the pod terminates. Can be useful for debugging volume related issues.") fs.MarkDeprecated("keep-terminated-pod-volumes", "will be removed in a future version") - // TODO(#54161:v1.11.0): Remove --enable-custom-metrics flag, it is deprecated. - fs.BoolVar(&f.EnableCustomMetrics, "enable-custom-metrics", f.EnableCustomMetrics, "Support for gathering custom metrics.") - fs.MarkDeprecated("enable-custom-metrics", "will be removed in a future version") - // TODO(#58010:v1.12.0): Remove --allow-privileged, it is deprecated - fs.BoolVar(&f.AllowPrivileged, "allow-privileged", f.AllowPrivileged, "If true, allow containers to request privileged mode.") + // TODO(#58010:v1.13.0): Remove --allow-privileged, it is deprecated + fs.BoolVar(&f.AllowPrivileged, "allow-privileged", f.AllowPrivileged, "If true, allow containers to request privileged mode. Default: true") fs.MarkDeprecated("allow-privileged", "will be removed in a future version") // TODO(#58010:v1.12.0): Remove --host-network-sources, it is deprecated fs.StringSliceVar(&f.HostNetworkSources, "host-network-sources", f.HostNetworkSources, "Comma-separated list of sources from which the Kubelet allows pods to use of host network.") @@ -494,13 +489,17 @@ func AddKubeletConfigFlags(mainfs *pflag.FlagSet, c *kubeletconfig.KubeletConfig "If --tls-cert-file and --tls-private-key-file are not provided, a self-signed certificate and key "+ "are generated for the public address and saved to the directory passed to --cert-dir.") fs.StringVar(&c.TLSPrivateKeyFile, "tls-private-key-file", c.TLSPrivateKeyFile, "File containing x509 private key matching --tls-cert-file.") + + tlsCipherPossibleValues := flag.TLSCipherPossibleValues() fs.StringSliceVar(&c.TLSCipherSuites, "tls-cipher-suites", c.TLSCipherSuites, "Comma-separated list of cipher suites for the server. "+ - "Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). "+ - "If omitted, the default Go cipher suites will be used") + "If omitted, the default Go cipher suites will be used. "+ + "Possible values: "+strings.Join(tlsCipherPossibleValues, ",")) + tlsPossibleVersions := flag.TLSPossibleVersions() fs.StringVar(&c.TLSMinVersion, "tls-min-version", c.TLSMinVersion, "Minimum TLS version supported. "+ - "Value must match version names from https://golang.org/pkg/crypto/tls/#pkg-constants.") + "Possible values: "+strings.Join(tlsPossibleVersions, ", ")) + fs.BoolVar(&c.RotateCertificates, "rotate-certificates", c.RotateCertificates, " Auto rotate the kubelet client certificates by requesting new certificates from the kube-apiserver when the certificate expiration approaches.") fs.Int32Var(&c.RegistryPullQPS, "registry-qps", c.RegistryPullQPS, "If > 0, limit registry pull QPS to this value. If 0, unlimited.") fs.Int32Var(&c.RegistryBurst, "registry-burst", c.RegistryBurst, "Maximum size of a bursty pulls, temporarily allows pulls to burst to this number, while still not exceeding registry-qps. Only used if --registry-qps > 0") @@ -518,8 +517,8 @@ func AddKubeletConfigFlags(mainfs *pflag.FlagSet, c *kubeletconfig.KubeletConfig fs.DurationVar(&c.StreamingConnectionIdleTimeout.Duration, "streaming-connection-idle-timeout", c.StreamingConnectionIdleTimeout.Duration, "Maximum time a streaming connection can be idle before the connection is automatically closed. 0 indicates no timeout. Example: '5m'") fs.DurationVar(&c.NodeStatusUpdateFrequency.Duration, "node-status-update-frequency", c.NodeStatusUpdateFrequency.Duration, "Specifies how often kubelet posts node status to master. Note: be cautious when changing the constant, it must work with nodeMonitorGracePeriod in nodecontroller.") fs.DurationVar(&c.ImageMinimumGCAge.Duration, "minimum-image-ttl-duration", c.ImageMinimumGCAge.Duration, "Minimum age for an unused image before it is garbage collected. Examples: '300ms', '10s' or '2h45m'.") - fs.Int32Var(&c.ImageGCHighThresholdPercent, "image-gc-high-threshold", c.ImageGCHighThresholdPercent, "The percent of disk usage after which image garbage collection is always run.") - fs.Int32Var(&c.ImageGCLowThresholdPercent, "image-gc-low-threshold", c.ImageGCLowThresholdPercent, "The percent of disk usage before which image garbage collection is never run. Lowest disk usage to garbage collect to.") + fs.Int32Var(&c.ImageGCHighThresholdPercent, "image-gc-high-threshold", c.ImageGCHighThresholdPercent, "The percent of disk usage after which image garbage collection is always run. Values must be within the range [0, 100], To disable image garbage collection, set to 100. ") + fs.Int32Var(&c.ImageGCLowThresholdPercent, "image-gc-low-threshold", c.ImageGCLowThresholdPercent, "The percent of disk usage before which image garbage collection is never run. Lowest disk usage to garbage collect to. Values must be within the range [0, 100] and should not be larger than that of --image-gc-high-threshold.") fs.DurationVar(&c.VolumeStatsAggPeriod.Duration, "volume-stats-agg-period", c.VolumeStatsAggPeriod.Duration, "Specifies interval for kubelet to calculate and cache the volume disk usage for all pods and volumes. To disable volume calculations, set to 0.") fs.Var(flag.NewMapStringBool(&c.FeatureGates), "feature-gates", "A set of key=value pairs that describe feature gates for alpha/experimental features. "+ "Options are:\n"+strings.Join(utilfeature.DefaultFeatureGate.KnownFeatures(), "\n")) @@ -529,8 +528,9 @@ func AddKubeletConfigFlags(mainfs *pflag.FlagSet, c *kubeletconfig.KubeletConfig fs.BoolVar(&c.CgroupsPerQOS, "cgroups-per-qos", c.CgroupsPerQOS, "Enable creation of QoS cgroup hierarchy, if true top level QoS and pod cgroups are created.") fs.StringVar(&c.CgroupDriver, "cgroup-driver", c.CgroupDriver, "Driver that the kubelet uses to manipulate cgroups on the host. Possible values: 'cgroupfs', 'systemd'") fs.StringVar(&c.CgroupRoot, "cgroup-root", c.CgroupRoot, "Optional root cgroup to use for pods. This is handled by the container runtime on a best effort basis. Default: '', which means use the container runtime default.") - fs.StringVar(&c.CPUManagerPolicy, "cpu-manager-policy", c.CPUManagerPolicy, " CPU Manager policy to use. Possible values: 'none', 'static'. Default: 'none'") + fs.StringVar(&c.CPUManagerPolicy, "cpu-manager-policy", c.CPUManagerPolicy, "CPU Manager policy to use. Possible values: 'none', 'static'. Default: 'none'") fs.DurationVar(&c.CPUManagerReconcilePeriod.Duration, "cpu-manager-reconcile-period", c.CPUManagerReconcilePeriod.Duration, " CPU Manager reconciliation period. Examples: '10s', or '1m'. If not supplied, defaults to `NodeStatusUpdateFrequency`") + fs.Var(flag.NewMapStringString(&c.QOSReserved), "qos-reserved", " A set of ResourceName=Percentage (e.g. memory=50%) pairs that describe how pod resource requests are reserved at the QoS level. Currently only memory is supported. Requires the QOSReserved feature gate to be enabled.") fs.DurationVar(&c.RuntimeRequestTimeout.Duration, "runtime-request-timeout", c.RuntimeRequestTimeout.Duration, "Timeout of all runtime requests except long running request - pull, logs, exec and attach. When timeout exceeded, kubelet will cancel the request, throw out an error and retry later.") fs.StringVar(&c.HairpinMode, "hairpin-mode", c.HairpinMode, "How should the kubelet setup hairpin NAT. This allows endpoints of a Service to loadbalance back to themselves if they should try to access their own Service. Valid values are \"promiscuous-bridge\", \"hairpin-veth\" and \"none\".") fs.Int32Var(&c.MaxPods, "max-pods", c.MaxPods, "Number of Pods that can run on this Kubelet.") @@ -544,8 +544,8 @@ func AddKubeletConfigFlags(mainfs *pflag.FlagSet, c *kubeletconfig.KubeletConfig fs.BoolVar(&c.MakeIPTablesUtilChains, "make-iptables-util-chains", c.MakeIPTablesUtilChains, "If true, kubelet will ensure iptables utility rules are present on host.") fs.Int32Var(&c.IPTablesMasqueradeBit, "iptables-masquerade-bit", c.IPTablesMasqueradeBit, "The bit of the fwmark space to mark packets for SNAT. Must be within the range [0, 31]. Please match this parameter with corresponding parameter in kube-proxy.") fs.Int32Var(&c.IPTablesDropBit, "iptables-drop-bit", c.IPTablesDropBit, "The bit of the fwmark space to mark packets for dropping. Must be within the range [0, 31].") - fs.StringVar(&c.ContainerLogMaxSize, "container-log-max-size", c.ContainerLogMaxSize, " Set the maximum size (e.g. 10Mi) of container log file before it is rotated.") - fs.Int32Var(&c.ContainerLogMaxFiles, "container-log-max-files", c.ContainerLogMaxFiles, " Set the maximum number of container log files that can be present for a container. The number must be >= 2.") + fs.StringVar(&c.ContainerLogMaxSize, "container-log-max-size", c.ContainerLogMaxSize, " Set the maximum size (e.g. 10Mi) of container log file before it is rotated. This flag can only be used with --container-runtime=remote.") + fs.Int32Var(&c.ContainerLogMaxFiles, "container-log-max-files", c.ContainerLogMaxFiles, " Set the maximum number of container log files that can be present for a container. The number must be >= 2. This flag can only be used with --container-runtime=remote.") // Flags intended for testing, not recommended used in production environments. fs.Int64Var(&c.MaxOpenFiles, "max-open-files", c.MaxOpenFiles, "Number of files that can be opened by Kubelet process.") diff --git a/vendor/k8s.io/kubernetes/cmd/kubelet/app/plugins.go b/vendor/k8s.io/kubernetes/cmd/kubelet/app/plugins.go index ef41bb8e9..22700b051 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubelet/app/plugins.go +++ b/vendor/k8s.io/kubernetes/cmd/kubelet/app/plugins.go @@ -24,9 +24,9 @@ import ( _ "k8s.io/kubernetes/pkg/credentialprovider/gcp" _ "k8s.io/kubernetes/pkg/credentialprovider/rancher" // Network plugins - "k8s.io/kubernetes/pkg/kubelet/network" - "k8s.io/kubernetes/pkg/kubelet/network/cni" - "k8s.io/kubernetes/pkg/kubelet/network/kubenet" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet" // Volume plugins "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/aws_ebs" @@ -114,12 +114,12 @@ func GetDynamicPluginProber(pluginDir string) volume.DynamicPluginProber { } // ProbeNetworkPlugins collects all compiled-in plugins -func ProbeNetworkPlugins(cniConfDir, cniBinDir string) []network.NetworkPlugin { +func ProbeNetworkPlugins(cniConfDir string, cniBinDirs []string) []network.NetworkPlugin { allPlugins := []network.NetworkPlugin{} // for each existing plugin, add to the list - allPlugins = append(allPlugins, cni.ProbeNetworkPlugins(cniConfDir, cniBinDir)...) - allPlugins = append(allPlugins, kubenet.NewPlugin(cniBinDir)) + allPlugins = append(allPlugins, cni.ProbeNetworkPlugins(cniConfDir, cniBinDirs)...) + allPlugins = append(allPlugins, kubenet.NewPlugin(cniBinDirs)) return allPlugins } diff --git a/vendor/k8s.io/kubernetes/cmd/kubelet/app/server.go b/vendor/k8s.io/kubernetes/cmd/kubelet/app/server.go index 4cd0a445e..bcd5ea562 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubelet/app/server.go +++ b/vendor/k8s.io/kubernetes/cmd/kubelet/app/server.go @@ -68,6 +68,7 @@ import ( kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + kubeletconfigvalidation "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation" "k8s.io/kubernetes/pkg/kubelet/cadvisor" kubeletcertificate "k8s.io/kubernetes/pkg/kubelet/certificate" "k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap" @@ -90,10 +91,12 @@ import ( kubeio "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" nodeutil "k8s.io/kubernetes/pkg/util/node" + "k8s.io/kubernetes/pkg/util/nsenter" "k8s.io/kubernetes/pkg/util/oom" "k8s.io/kubernetes/pkg/util/rlimit" "k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/version/verflag" + "k8s.io/utils/exec" ) const ( @@ -102,7 +105,7 @@ const ( ) // NewKubeletCommand creates a *cobra.Command object with default parameters -func NewKubeletCommand() *cobra.Command { +func NewKubeletCommand(stopCh <-chan struct{}) *cobra.Command { cleanFlagSet := pflag.NewFlagSet(componentKubelet, pflag.ContinueOnError) cleanFlagSet.SetNormalizeFunc(flag.WordSepNormalizeFunc) kubeletFlags := options.NewKubeletFlags() @@ -145,6 +148,13 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API glog.Fatal(err) } + // check if there are non-flag arguments in the command line + cmds := cleanFlagSet.Args() + if len(cmds) > 0 { + cmd.Usage() + glog.Fatalf("unknown command: %s", cmds[0]) + } + // short-circuit on help help, err := cleanFlagSet.GetBool("help") if err != nil { @@ -169,6 +179,10 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API glog.Fatal(err) } + if kubeletFlags.ContainerRuntime == "remote" && cleanFlagSet.Changed("pod-infra-container-image") { + glog.Warning("Warning: For remote container runtime, --pod-infra-container-image is ignored in kubelet, which should be set in that remote runtime instead") + } + // load kubelet config file, if provided if configFile := kubeletFlags.KubeletConfigFile; len(configFile) > 0 { kubeletConfig, err = loadConfigFile(configFile) @@ -187,22 +201,35 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API } } + // We always validate the local configuration (command line + config file). + // This is the default "last-known-good" config for dynamic config, and must always remain valid. + if err := kubeletconfigvalidation.ValidateKubeletConfiguration(kubeletConfig); err != nil { + glog.Fatal(err) + } + // use dynamic kubelet config, if enabled var kubeletConfigController *dynamickubeletconfig.Controller if dynamicConfigDir := kubeletFlags.DynamicConfigDir.Value(); len(dynamicConfigDir) > 0 { - kubeletConfig, kubeletConfigController, err = BootstrapKubeletConfigController(kubeletConfig, dynamicConfigDir) + var dynamicKubeletConfig *kubeletconfiginternal.KubeletConfiguration + dynamicKubeletConfig, kubeletConfigController, err = BootstrapKubeletConfigController(dynamicConfigDir, + func(kc *kubeletconfiginternal.KubeletConfiguration) error { + // Here, we enforce flag precedence inside the controller, prior to the controller's validation sequence, + // so that we get a complete validation at the same point where we can decide to reject dynamic config. + // This fixes the flag-precedence component of issue #63305. + // See issue #56171 for general details on flag precedence. + return kubeletConfigFlagPrecedence(kc, args) + }) if err != nil { glog.Fatal(err) } - // We must enforce flag precedence by re-parsing the command line into the new object. - // This is necessary to preserve backwards-compatibility across binary upgrades. - // See issue #56171 for more details. - if err := kubeletConfigFlagPrecedence(kubeletConfig, args); err != nil { - glog.Fatal(err) - } - // update feature gates based on new config - if err := utilfeature.DefaultFeatureGate.SetFromMap(kubeletConfig.FeatureGates); err != nil { - glog.Fatal(err) + // If we should just use our existing, local config, the controller will return a nil config + if dynamicKubeletConfig != nil { + kubeletConfig = dynamicKubeletConfig + // Note: flag precedence was already enforced in the controller, prior to validation, + // by our above transform function. Now we simply update feature gates from the new config. + if err := utilfeature.DefaultFeatureGate.SetFromMap(kubeletConfig.FeatureGates); err != nil { + glog.Fatal(err) + } } } @@ -223,13 +250,15 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API // start the experimental docker shim, if enabled if kubeletServer.KubeletFlags.ExperimentalDockershim { - if err := RunDockershim(&kubeletServer.KubeletFlags, kubeletConfig); err != nil { + if err := RunDockershim(&kubeletServer.KubeletFlags, kubeletConfig, stopCh); err != nil { glog.Fatal(err) } + return } // run the kubelet - if err := Run(kubeletServer, kubeletDeps); err != nil { + glog.V(5).Infof("KubeletConfiguration: %#v", kubeletServer.KubeletConfiguration) + if err := Run(kubeletServer, kubeletDeps, stopCh); err != nil { glog.Fatal(err) } }, @@ -334,8 +363,12 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err var writer kubeio.Writer = &kubeio.StdWriter{} if s.Containerized { glog.V(2).Info("Running kubelet in containerized mode") - mounter = mount.NewNsenterMounter() - writer = &kubeio.NsenterWriter{} + ne, err := nsenter.NewNsenter(nsenter.DefaultHostRootFsPath, exec.New()) + if err != nil { + return nil, err + } + mounter = mount.NewNsenterMounter(s.RootDirectory, ne) + writer = kubeio.NewNsenterWriter(ne) } var dockerClientConfig *dockershim.ClientConfig @@ -358,7 +391,6 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err ExternalKubeClient: nil, EventClient: nil, Mounter: mounter, - NetworkPlugins: ProbeNetworkPlugins(s.CNIConfDir, s.CNIBinDir), OOMAdjuster: oom.NewOOMAdjuster(), OSInterface: kubecontainer.RealOS{}, Writer: writer, @@ -371,13 +403,13 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err // The kubeDeps argument may be nil - if so, it is initialized from the settings on KubeletServer. // Otherwise, the caller is assumed to have set up the Dependencies object and a default one will // not be generated. -func Run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) error { +func Run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan struct{}) error { // To help debugging, immediately log version glog.Infof("Version: %+v", version.Get()) if err := initForOS(s.KubeletFlags.WindowsService); err != nil { return fmt.Errorf("failed OS init: %v", err) } - if err := run(s, kubeDeps); err != nil { + if err := run(s, kubeDeps, stopCh); err != nil { return fmt.Errorf("failed to run Kubelet: %v", err) } return nil @@ -434,7 +466,7 @@ func makeEventRecorder(kubeDeps *kubelet.Dependencies, nodeName types.NodeName) } } -func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) (err error) { +func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan struct{}) (err error) { // Set global feature gates based on the value on the initial KubeletServer err = utilfeature.DefaultFeatureGate.SetFromMap(s.KubeletConfiguration.FeatureGates) if err != nil { @@ -587,7 +619,9 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) (err error) { // If the kubelet config controller is available, and dynamic config is enabled, start the config and status sync loops if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && len(s.DynamicConfigDir.Value()) > 0 && kubeDeps.KubeletConfigController != nil && !standaloneMode && !s.RunOnce { - kubeDeps.KubeletConfigController.StartSync(kubeDeps.KubeClient, kubeDeps.EventClient, string(nodeName)) + if err := kubeDeps.KubeletConfigController.StartSync(kubeDeps.KubeClient, kubeDeps.EventClient, string(nodeName)); err != nil { + return err + } } if kubeDeps.Auth == nil { @@ -630,7 +664,7 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) (err error) { return err } } - experimentalQOSReserved, err := cm.ParseQOSReserved(s.ExperimentalQOSReserved) + experimentalQOSReserved, err := cm.ParseQOSReserved(s.QOSReserved) if err != nil { return err } @@ -658,7 +692,7 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) (err error) { SystemReserved: systemReserved, HardEvictionThresholds: hardEvictionThresholds, }, - ExperimentalQOSReserved: *experimentalQOSReserved, + QOSReserved: *experimentalQOSReserved, ExperimentalCPUManagerPolicy: s.CPUManagerPolicy, ExperimentalCPUManagerReconcilePeriod: s.CPUManagerReconcilePeriod.Duration, ExperimentalPodPidsLimit: s.PodPidsLimit, @@ -708,7 +742,13 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) (err error) { // If systemd is used, notify it that we have started go daemon.SdNotify(false, "READY=1") - <-done + select { + case <-done: + break + case <-stopCh: + break + } + return nil } @@ -737,7 +777,7 @@ func getNodeName(cloud cloudprovider.Interface, hostname string) (types.NodeName // InitializeTLS checks for a configured TLSCertFile and TLSPrivateKeyFile: if unspecified a new self-signed // certificate and key file are generated. Returns a configured server.TLSOptions object. func InitializeTLS(kf *options.KubeletFlags, kc *kubeletconfiginternal.KubeletConfiguration) (*server.TLSOptions, error) { - if !utilfeature.DefaultFeatureGate.Enabled(features.RotateKubeletServerCertificate) && kc.TLSCertFile == "" && kc.TLSPrivateKeyFile == "" { + if !kc.ServerTLSBootstrap && kc.TLSCertFile == "" && kc.TLSPrivateKeyFile == "" { kc.TLSCertFile = path.Join(kf.CertDirectory, "kubelet.crt") kc.TLSPrivateKeyFile = path.Join(kf.CertDirectory, "kubelet.key") @@ -920,7 +960,8 @@ func RunKubelet(kubeFlags *options.KubeletFlags, kubeCfg *kubeletconfiginternal. kubeFlags.KeepTerminatedPodVolumes, kubeFlags.NodeLabels, kubeFlags.SeccompProfileRoot, - kubeFlags.BootstrapCheckpointPath) + kubeFlags.BootstrapCheckpointPath, + kubeFlags.NodeStatusMaxImages) if err != nil { return fmt.Errorf("failed to create kubelet: %v", err) } @@ -1004,7 +1045,8 @@ func CreateAndInitKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, keepTerminatedPodVolumes bool, nodeLabels map[string]string, seccompProfileRoot string, - bootstrapCheckpointPath string) (k kubelet.Bootstrap, err error) { + bootstrapCheckpointPath string, + nodeStatusMaxImages int32) (k kubelet.Bootstrap, err error) { // TODO: block until all sources have delivered at least one update to the channel, or break the sync loop // up into "per source" synchronizations @@ -1037,7 +1079,8 @@ func CreateAndInitKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, keepTerminatedPodVolumes, nodeLabels, seccompProfileRoot, - bootstrapCheckpointPath) + bootstrapCheckpointPath, + nodeStatusMaxImages) if err != nil { return nil, err } @@ -1076,8 +1119,7 @@ func parseResourceList(m map[string]string) (v1.ResourceList, error) { } // BootstrapKubeletConfigController constructs and bootstrap a configuration controller -func BootstrapKubeletConfigController(defaultConfig *kubeletconfiginternal.KubeletConfiguration, - dynamicConfigDir string) (*kubeletconfiginternal.KubeletConfiguration, *dynamickubeletconfig.Controller, error) { +func BootstrapKubeletConfigController(dynamicConfigDir string, transform dynamickubeletconfig.TransformFunc) (*kubeletconfiginternal.KubeletConfiguration, *dynamickubeletconfig.Controller, error) { if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { return nil, nil, fmt.Errorf("failed to bootstrap Kubelet config controller, you must enable the DynamicKubeletConfig feature gate") } @@ -1091,7 +1133,7 @@ func BootstrapKubeletConfigController(defaultConfig *kubeletconfiginternal.Kubel return nil, nil, fmt.Errorf("failed to get absolute path for --dynamic-config-dir=%s", dynamicConfigDir) } // get the latest KubeletConfiguration checkpoint from disk, or return the default config if no valid checkpoints exist - c := dynamickubeletconfig.NewController(defaultConfig, dir) + c := dynamickubeletconfig.NewController(dir, transform) kc, err := c.Bootstrap() if err != nil { return nil, nil, fmt.Errorf("failed to determine a valid configuration, error: %v", err) @@ -1101,7 +1143,7 @@ func BootstrapKubeletConfigController(defaultConfig *kubeletconfiginternal.Kubel // RunDockershim only starts the dockershim in current process. This is only used for cri validate testing purpose // TODO(random-liu): Move this to a separate binary. -func RunDockershim(f *options.KubeletFlags, c *kubeletconfiginternal.KubeletConfiguration) error { +func RunDockershim(f *options.KubeletFlags, c *kubeletconfiginternal.KubeletConfiguration, stopCh <-chan struct{}) error { r := &f.ContainerRuntimeOptions // Initialize docker client configuration. @@ -1112,15 +1154,13 @@ func RunDockershim(f *options.KubeletFlags, c *kubeletconfiginternal.KubeletConf } // Initialize network plugin settings. - nh := &kubelet.NoOpLegacyHost{} pluginSettings := dockershim.NetworkPluginSettings{ - HairpinMode: kubeletconfiginternal.HairpinMode(c.HairpinMode), - NonMasqueradeCIDR: f.NonMasqueradeCIDR, - PluginName: r.NetworkPluginName, - PluginConfDir: r.CNIConfDir, - PluginBinDir: r.CNIBinDir, - MTU: int(r.NetworkPluginMTU), - LegacyRuntimeHost: nh, + HairpinMode: kubeletconfiginternal.HairpinMode(c.HairpinMode), + NonMasqueradeCIDR: f.NonMasqueradeCIDR, + PluginName: r.NetworkPluginName, + PluginConfDir: r.CNIConfDir, + PluginBinDirString: r.CNIBinDir, + MTU: int(r.NetworkPluginMTU), } // Initialize streaming configuration. (Not using TLS now) @@ -1133,8 +1173,9 @@ func RunDockershim(f *options.KubeletFlags, c *kubeletconfiginternal.KubeletConf SupportedPortForwardProtocols: streaming.DefaultConfig.SupportedPortForwardProtocols, } + // Standalone dockershim will always start the local streaming server. ds, err := dockershim.NewDockerService(dockerClientConfig, r.PodSandboxImage, streamingConfig, &pluginSettings, - f.RuntimeCgroups, c.CgroupDriver, r.DockershimRootDirectory, r.DockerDisableSharedPID) + f.RuntimeCgroups, c.CgroupDriver, r.DockershimRootDirectory, r.DockerDisableSharedPID, true /*startLocalStreamingServer*/) if err != nil { return err } @@ -1143,8 +1184,6 @@ func RunDockershim(f *options.KubeletFlags, c *kubeletconfiginternal.KubeletConf if err := server.Start(); err != nil { return err } - - // Start the streaming server - addr := net.JoinHostPort(c.Address, strconv.Itoa(int(c.Port))) - return http.ListenAndServe(addr, ds) + <-stopCh + return nil } diff --git a/vendor/k8s.io/kubernetes/cmd/kubelet/kubelet.go b/vendor/k8s.io/kubernetes/cmd/kubelet/kubelet.go index 3f5b29377..8f254adb4 100644 --- a/vendor/k8s.io/kubernetes/cmd/kubelet/kubelet.go +++ b/vendor/k8s.io/kubernetes/cmd/kubelet/kubelet.go @@ -26,6 +26,7 @@ import ( "os" "time" + "k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/util/logs" "k8s.io/kubernetes/cmd/kubelet/app" _ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration @@ -35,7 +36,7 @@ import ( func main() { rand.Seed(time.Now().UTC().UnixNano()) - command := app.NewKubeletCommand() + command := app.NewKubeletCommand(server.SetupSignalHandler()) logs.InitLogs() defer logs.FlushLogs() diff --git a/vendor/k8s.io/kubernetes/docs/.generated_docs b/vendor/k8s.io/kubernetes/docs/.generated_docs index c0198d775..0fd748bcf 100644 --- a/vendor/k8s.io/kubernetes/docs/.generated_docs +++ b/vendor/k8s.io/kubernetes/docs/.generated_docs @@ -9,7 +9,7 @@ docs/admin/kubeadm_alpha.md docs/admin/kubeadm_alpha_phase.md docs/admin/kubeadm_alpha_phase_addon.md docs/admin/kubeadm_alpha_phase_addon_all.md -docs/admin/kubeadm_alpha_phase_addon_kube-dns.md +docs/admin/kubeadm_alpha_phase_addon_coredns.md docs/admin/kubeadm_alpha_phase_addon_kube-proxy.md docs/admin/kubeadm_alpha_phase_bootstrap-token.md docs/admin/kubeadm_alpha_phase_bootstrap-token_all.md @@ -45,6 +45,13 @@ docs/admin/kubeadm_alpha_phase_kubeconfig_controller-manager.md docs/admin/kubeadm_alpha_phase_kubeconfig_kubelet.md docs/admin/kubeadm_alpha_phase_kubeconfig_scheduler.md docs/admin/kubeadm_alpha_phase_kubeconfig_user.md +docs/admin/kubeadm_alpha_phase_kubelet.md +docs/admin/kubeadm_alpha_phase_kubelet_config.md +docs/admin/kubeadm_alpha_phase_kubelet_config_download.md +docs/admin/kubeadm_alpha_phase_kubelet_config_enable-dynamic.md +docs/admin/kubeadm_alpha_phase_kubelet_config_upload.md +docs/admin/kubeadm_alpha_phase_kubelet_config_write-to-disk.md +docs/admin/kubeadm_alpha_phase_kubelet_write-env-file.md docs/admin/kubeadm_alpha_phase_mark-master.md docs/admin/kubeadm_alpha_phase_preflight.md docs/admin/kubeadm_alpha_phase_preflight_master.md @@ -54,6 +61,11 @@ docs/admin/kubeadm_alpha_phase_selfhosting_convert-from-staticpods.md docs/admin/kubeadm_alpha_phase_upload-config.md docs/admin/kubeadm_completion.md docs/admin/kubeadm_config.md +docs/admin/kubeadm_config_images.md +docs/admin/kubeadm_config_images_list.md +docs/admin/kubeadm_config_images_pull.md +docs/admin/kubeadm_config_migrate.md +docs/admin/kubeadm_config_print-default.md docs/admin/kubeadm_config_upload.md docs/admin/kubeadm_config_upload_from-file.md docs/admin/kubeadm_config_upload_from-flags.md @@ -68,6 +80,9 @@ docs/admin/kubeadm_token_generate.md docs/admin/kubeadm_token_list.md docs/admin/kubeadm_upgrade.md docs/admin/kubeadm_upgrade_apply.md +docs/admin/kubeadm_upgrade_diff.md +docs/admin/kubeadm_upgrade_node.md +docs/admin/kubeadm_upgrade_node_config.md docs/admin/kubeadm_upgrade_plan.md docs/admin/kubeadm_version.md docs/admin/kubelet.md @@ -77,7 +92,7 @@ docs/man/man1/kube-controller-manager.1 docs/man/man1/kube-proxy.1 docs/man/man1/kube-scheduler.1 docs/man/man1/kubeadm-alpha-phase-addon-all.1 -docs/man/man1/kubeadm-alpha-phase-addon-kube-dns.1 +docs/man/man1/kubeadm-alpha-phase-addon-coredns.1 docs/man/man1/kubeadm-alpha-phase-addon-kube-proxy.1 docs/man/man1/kubeadm-alpha-phase-addon.1 docs/man/man1/kubeadm-alpha-phase-bootstrap-token-all.1 @@ -114,6 +129,13 @@ docs/man/man1/kubeadm-alpha-phase-kubeconfig-kubelet.1 docs/man/man1/kubeadm-alpha-phase-kubeconfig-scheduler.1 docs/man/man1/kubeadm-alpha-phase-kubeconfig-user.1 docs/man/man1/kubeadm-alpha-phase-kubeconfig.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config-download.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config-enable-dynamic.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config-upload.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config-write-to-disk.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-config.1 +docs/man/man1/kubeadm-alpha-phase-kubelet-write-env-file.1 +docs/man/man1/kubeadm-alpha-phase-kubelet.1 docs/man/man1/kubeadm-alpha-phase-mark-master.1 docs/man/man1/kubeadm-alpha-phase-preflight-master.1 docs/man/man1/kubeadm-alpha-phase-preflight-node.1 @@ -124,6 +146,11 @@ docs/man/man1/kubeadm-alpha-phase-upload-config.1 docs/man/man1/kubeadm-alpha-phase.1 docs/man/man1/kubeadm-alpha.1 docs/man/man1/kubeadm-completion.1 +docs/man/man1/kubeadm-config-images-list.1 +docs/man/man1/kubeadm-config-images-pull.1 +docs/man/man1/kubeadm-config-images.1 +docs/man/man1/kubeadm-config-migrate.1 +docs/man/man1/kubeadm-config-print-default.1 docs/man/man1/kubeadm-config-upload-from-file.1 docs/man/man1/kubeadm-config-upload-from-flags.1 docs/man/man1/kubeadm-config-upload.1 @@ -138,6 +165,9 @@ docs/man/man1/kubeadm-token-generate.1 docs/man/man1/kubeadm-token-list.1 docs/man/man1/kubeadm-token.1 docs/man/man1/kubeadm-upgrade-apply.1 +docs/man/man1/kubeadm-upgrade-diff.1 +docs/man/man1/kubeadm-upgrade-node-config.1 +docs/man/man1/kubeadm-upgrade-node.1 docs/man/man1/kubeadm-upgrade-plan.1 docs/man/man1/kubeadm-upgrade.1 docs/man/man1/kubeadm-version.1 @@ -145,6 +175,7 @@ docs/man/man1/kubeadm.1 docs/man/man1/kubectl-alpha-diff.1 docs/man/man1/kubectl-alpha.1 docs/man/man1/kubectl-annotate.1 +docs/man/man1/kubectl-api-resources.1 docs/man/man1/kubectl-api-versions.1 docs/man/man1/kubectl-apply-edit-last-applied.1 docs/man/man1/kubectl-apply-set-last-applied.1 @@ -239,12 +270,14 @@ docs/man/man1/kubectl-top-pod.1 docs/man/man1/kubectl-top.1 docs/man/man1/kubectl-uncordon.1 docs/man/man1/kubectl-version.1 +docs/man/man1/kubectl-wait.1 docs/man/man1/kubectl.1 docs/man/man1/kubelet.1 docs/user-guide/kubectl/kubectl.md docs/user-guide/kubectl/kubectl_alpha.md docs/user-guide/kubectl/kubectl_alpha_diff.md docs/user-guide/kubectl/kubectl_annotate.md +docs/user-guide/kubectl/kubectl_api-resources.md docs/user-guide/kubectl/kubectl_api-versions.md docs/user-guide/kubectl/kubectl_apply.md docs/user-guide/kubectl/kubectl_apply_edit-last-applied.md @@ -316,7 +349,6 @@ docs/user-guide/kubectl/kubectl_plugin.md docs/user-guide/kubectl/kubectl_port-forward.md docs/user-guide/kubectl/kubectl_proxy.md docs/user-guide/kubectl/kubectl_replace.md -docs/user-guide/kubectl/kubectl_rolling-update.md docs/user-guide/kubectl/kubectl_rollout.md docs/user-guide/kubectl/kubectl_rollout_history.md docs/user-guide/kubectl/kubectl_rollout_pause.md @@ -338,9 +370,11 @@ docs/user-guide/kubectl/kubectl_top_node.md docs/user-guide/kubectl/kubectl_top_pod.md docs/user-guide/kubectl/kubectl_uncordon.md docs/user-guide/kubectl/kubectl_version.md +docs/user-guide/kubectl/kubectl_wait.md docs/yaml/kubectl/kubectl.yaml docs/yaml/kubectl/kubectl_alpha.yaml docs/yaml/kubectl/kubectl_annotate.yaml +docs/yaml/kubectl/kubectl_api-resources.yaml docs/yaml/kubectl/kubectl_api-versions.yaml docs/yaml/kubectl/kubectl_apply.yaml docs/yaml/kubectl/kubectl_attach.yaml @@ -380,3 +414,4 @@ docs/yaml/kubectl/kubectl_taint.yaml docs/yaml/kubectl/kubectl_top.yaml docs/yaml/kubectl/kubectl_uncordon.yaml docs/yaml/kubectl/kubectl_version.yaml +docs/yaml/kubectl/kubectl_wait.yaml diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_addon_kube-dns.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_addon_coredns.md similarity index 100% rename from vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_addon_kube-dns.md rename to vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_addon_coredns.md diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-addon-kube-dns.1 b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet.md similarity index 100% rename from vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-addon-kube-dns.1 rename to vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet.md diff --git a/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_rolling-update.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config.md similarity index 100% rename from vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_rolling-update.md rename to vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config.md diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_download.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_download.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_download.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_enable-dynamic.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_enable-dynamic.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_enable-dynamic.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_upload.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_upload.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_upload.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_write-to-disk.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_write-to-disk.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_config_write-to-disk.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_write-env-file.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_write-env-file.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_alpha_phase_kubelet_write-env-file.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_images.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_images.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_images.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_images_list.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_images_list.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_images_list.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_images_pull.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_images_pull.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_images_pull.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_migrate.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_migrate.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_migrate.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_print-default.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_print-default.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_config_print-default.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_upgrade_diff.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_upgrade_diff.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_upgrade_diff.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_upgrade_node.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_upgrade_node.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_upgrade_node.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/admin/kubeadm_upgrade_node_config.md b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_upgrade_node_config.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/admin/kubeadm_upgrade_node_config.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/admissionregistration.k8s.io/v1beta1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/admissionregistration.k8s.io/v1beta1/definitions.html index 1a9b9a4a3..b080f0a26 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/admissionregistration.k8s.io/v1beta1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/admissionregistration.k8s.io/v1beta1/definitions.html @@ -1598,7 +1598,7 @@

v1beta1.WebhookClientConfig


If the webhook is running within the cluster, then you should use service.

-If there is only one port open for the service, that port will be used. If there are multiple ports open, port 443 will be used if it is open, otherwise it is an error.

+Port 443 will be used if it is open, otherwise it is an error.

true

v1beta1.ServiceReference

diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1/definitions.html index a7cef2ba1..1712412d0 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1/definitions.html @@ -512,7 +512,7 @@

v1.Affinity

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -534,8 +534,15 @@

v1.NodeSelectorTerm

- - + + + + + + + + + @@ -809,7 +816,7 @@

v1.VolumeMount

- + @@ -1334,6 +1341,9 @@

v1.GitRepoVolumeSource

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+

matchExpressions

Required. A list of node selector requirements. The requirements are ANDed.

true

A list of node selector requirements by node’s labels.

false

v1.NodeSelectorRequirement array

matchFields

A list of node selector requirements by node’s fields.

false

v1.NodeSelectorRequirement array

mountPropagation

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.

false

v1.MountPropagationMode

@@ -1550,6 +1560,54 @@

v1.Capabilities

+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -3213,7 +3271,7 @@

v1.Volume

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -3468,6 +3526,13 @@

v1.VolumeProjection

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -3949,6 +4014,13 @@

v1.PodSpec

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -5716,6 +5788,13 @@

v1.PodSecurityContext

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + @@ -5781,6 +5860,40 @@

v1.ReplicaSet

+
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

+

v1.OwnerReference

@@ -5910,14 +6023,14 @@

v1.RollingUpdateDeployment

maxUnavailable

-

The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.

+

The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.

false

string

maxSurge

-

The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.

+

The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.

false

string

@@ -6420,6 +6533,13 @@

v1.CinderVolumeSource

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -7378,6 +7498,47 @@

v1.NodeSelector

+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.DeploymentSpec

diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1beta1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1beta1/definitions.html index afcfeabc6..48774c68d 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1beta1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1beta1/definitions.html @@ -623,7 +623,7 @@

v1beta1.RollingUpdateStateful

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -645,8 +645,15 @@

v1.NodeSelectorTerm

- - + + + + + + + + + @@ -837,7 +844,7 @@

v1.VolumeMount

- + @@ -1187,14 +1194,14 @@

v1beta1.RollingUpdateDeployment

- + - + @@ -1266,6 +1273,9 @@

v1.GitRepoVolumeSource

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+

matchExpressions

Required. A list of node selector requirements. The requirements are ANDed.

true

A list of node selector requirements by node’s labels.

false

v1.NodeSelectorRequirement array

matchFields

A list of node selector requirements by node’s fields.

false

v1.NodeSelectorRequirement array

mountPropagation

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.

false

v1.MountPropagationMode

maxUnavailable

The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.

The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.

false

string

maxSurge

The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.

The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.

false

string

@@ -1441,6 +1451,54 @@

v1.Capabilities

+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -3210,7 +3268,7 @@

v1.Volume

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -3465,6 +3523,13 @@

v1.VolumeProjection

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -4002,6 +4067,13 @@

v1.PodSpec

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -5851,6 +5923,47 @@

v1.PodSecurityContext

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + + + + +
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

+
+ +++++++ + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

@@ -6335,6 +6448,13 @@

v1.CinderVolumeSource

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -6836,6 +6956,47 @@

v1.NodeSelector

+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1beta2/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1beta2/definitions.html index 527bee3ce..247331f16 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1beta2/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/apps/v1beta2/definitions.html @@ -515,7 +515,7 @@

v1.Affinity

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -537,8 +537,15 @@

v1.NodeSelectorTerm

- - + + + + + + + + + @@ -784,7 +791,7 @@

v1.VolumeMount

- + @@ -1447,6 +1454,9 @@

v1.GitRepoVolumeSource

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+

matchExpressions

Required. A list of node selector requirements. The requirements are ANDed.

true

A list of node selector requirements by node’s labels.

false

v1.NodeSelectorRequirement array

matchFields

A list of node selector requirements by node’s fields.

false

v1.NodeSelectorRequirement array

mountPropagation

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.

false

v1.MountPropagationMode

@@ -1622,6 +1632,54 @@

v1.Capabilities

+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -3916,7 +3974,7 @@

v1.Volume

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -4171,6 +4229,13 @@

v1.VolumeProjection

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -4618,6 +4683,13 @@

v1.PodSpec

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -6185,6 +6257,47 @@

v1.PodSecurityContext

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + + + + +
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

+
+ +++++++ + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

@@ -6614,6 +6727,13 @@

v1.CinderVolumeSource

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -7183,14 +7303,14 @@

v1beta2.RollingUpdateDeployment

maxUnavailable

-

The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.

+

The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.

false

string

maxSurge

-

The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.

+

The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.

false

string

@@ -7369,6 +7489,47 @@

v1beta2.DaemonSetSpec

+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/batch/v1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/batch/v1/definitions.html index 1bfc0d5d3..724b186f9 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/batch/v1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/batch/v1/definitions.html @@ -488,7 +488,7 @@

v1.Affinity

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -510,8 +510,15 @@

v1.NodeSelectorTerm

- - + + + + + + + + + @@ -702,7 +709,7 @@

v1.VolumeMount

- + @@ -1021,6 +1028,9 @@

v1.GitRepoVolumeSource

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+

matchExpressions

Required. A list of node selector requirements. The requirements are ANDed.

true

A list of node selector requirements by node’s labels.

false

v1.NodeSelectorRequirement array

matchFields

A list of node selector requirements by node’s fields.

false

v1.NodeSelectorRequirement array

mountPropagation

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.

false

v1.MountPropagationMode

@@ -1196,6 +1206,54 @@

v1.Capabilities

+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -2580,7 +2638,7 @@

v1.Volume

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -2835,6 +2893,13 @@

v1.VolumeProjection

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -3282,6 +3347,13 @@

v1.PodSpec

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -4656,6 +4728,13 @@

v1.PodSecurityContext

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + @@ -4728,6 +4807,40 @@

v1.JobStatus

+
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

+

v1.OwnerReference

@@ -5154,6 +5267,13 @@

v1.CinderVolumeSource

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -5768,6 +5888,47 @@

v1.NodeSelector

+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/batch/v1beta1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/batch/v1beta1/definitions.html index 960585cbf..ebe33dc0c 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/batch/v1beta1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/batch/v1beta1/definitions.html @@ -488,7 +488,7 @@

v1.Affinity

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -510,8 +510,15 @@

v1.NodeSelectorTerm

- - + + + + + + + + + @@ -743,7 +750,7 @@

v1.VolumeMount

- + @@ -1062,6 +1069,9 @@

v1.GitRepoVolumeSource

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+

matchExpressions

Required. A list of node selector requirements. The requirements are ANDed.

true

A list of node selector requirements by node’s labels.

false

v1.NodeSelectorRequirement array

matchFields

A list of node selector requirements by node’s fields.

false

v1.NodeSelectorRequirement array

mountPropagation

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.

false

v1.MountPropagationMode

@@ -1237,6 +1247,54 @@

v1.Capabilities

+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -2614,7 +2672,7 @@

v1.Volume

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -2869,6 +2927,13 @@

v1.VolumeProjection

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -3316,6 +3381,13 @@

v1.PodSpec

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -4025,6 +4097,54 @@

v1.Initializers

+
+
+

v1.PodDNSConfig

+
+

PodDNSConfig defines the DNS parameters of a pod in addition to those generated from DNSPolicy.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

nameservers

A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. Duplicated nameservers will be removed.

false

string array

searches

A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. Duplicated search paths will be removed.

false

string array

options

A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. Duplicated entries will be removed. Resolution options given in Options will override those that appear in the base DNSPolicy.

false

v1.PodDNSConfigOption array

+

v1.Status

@@ -4108,54 +4228,6 @@

v1.Status

-
-
-

v1.PodDNSConfig

-
-

PodDNSConfig defines the DNS parameters of a pod in addition to those generated from DNSPolicy.

-
- ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionRequiredSchemaDefault

nameservers

A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. Duplicated nameservers will be removed.

false

string array

searches

A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. Duplicated search paths will be removed.

false

string array

options

A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. Duplicated entries will be removed. Resolution options given in Options will override those that appear in the base DNSPolicy.

false

v1.PodDNSConfigOption array

-

v1.NFSVolumeSource

@@ -4807,6 +4879,47 @@

v1.PodSecurityContext

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + + + + +
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

+
+ +++++++ + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

@@ -5101,12 +5214,9 @@

v1.HostPathVolumeSource

-

v1.SecretProjection

-
-

Adapts a secret into a projected volume.

-
+

v1.PodDNSConfigOption

-

The contents of the target Secret’s Data field will be presented in a projected volume as files using the keys in the Data field as the file names. Note that this is identical to a secret volume source without the default mode.

+

PodDNSConfigOption defines DNS resolver options of a pod.

@@ -5128,33 +5238,29 @@

v1.SecretProjection

- + - - - - + - - - - - - + +

name

Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names

Required.

false

string

items

If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the .. path or start with ...

false

v1.KeyToPath array

value

optional

Specify whether the Secret or its key must be defined

false

boolean

false

string

-

v1.PodDNSConfigOption

+

v1.SecretProjection

-

PodDNSConfigOption defines DNS resolver options of a pod.

+

Adapts a secret into a projected volume.

+
+
+

The contents of the target Secret’s Data field will be presented in a projected volume as files using the keys in the Data field as the file names. Note that this is identical to a secret volume source without the default mode.

@@ -5176,18 +5282,25 @@

v1.PodDNSConfigOption

- + - - + + - + + + + + + + +

name

Required.

Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names

false

string

value

items

If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the .. path or start with ...

false

string

v1.KeyToPath array

optional

Specify whether the Secret or its key must be defined

false

boolean

false

@@ -5291,6 +5404,13 @@

v1.CinderVolumeSource

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -5788,6 +5908,47 @@

v1.NodeSelector

+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/batch/v2alpha1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/batch/v2alpha1/definitions.html index 5e2eb6718..a65cda841 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/batch/v2alpha1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/batch/v2alpha1/definitions.html @@ -488,7 +488,7 @@

v1.Affinity

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -510,8 +510,15 @@

v1.NodeSelectorTerm

- - + + + + + + + + + @@ -702,7 +709,7 @@

v1.VolumeMount

- + @@ -1021,6 +1028,9 @@

v1.GitRepoVolumeSource

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+

matchExpressions

Required. A list of node selector requirements. The requirements are ANDed.

true

A list of node selector requirements by node’s labels.

false

v1.NodeSelectorRequirement array

matchFields

A list of node selector requirements by node’s fields.

false

v1.NodeSelectorRequirement array

mountPropagation

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.

false

v1.MountPropagationMode

@@ -1196,6 +1206,54 @@

v1.Capabilities

+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -2587,7 +2645,7 @@

v1.Volume

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -2842,6 +2900,13 @@

v1.VolumeProjection

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -3289,6 +3354,13 @@

v1.PodSpec

v1.PodDNSConfig

+ +

readinessGates

+

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

+

false

+

v1.PodReadinessGate array

+ + @@ -3922,6 +3994,54 @@

v1.Initializers

+
+
+

v1.PodDNSConfig

+
+

PodDNSConfig defines the DNS parameters of a pod in addition to those generated from DNSPolicy.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

nameservers

A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. Duplicated nameservers will be removed.

false

string array

searches

A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. Duplicated search paths will be removed.

false

string array

options

A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. Duplicated entries will be removed. Resolution options given in Options will override those that appear in the base DNSPolicy.

false

v1.PodDNSConfigOption array

+

v1.Status

@@ -4005,54 +4125,6 @@

v1.Status

-
-
-

v1.PodDNSConfig

-
-

PodDNSConfig defines the DNS parameters of a pod in addition to those generated from DNSPolicy.

-
- ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionRequiredSchemaDefault

nameservers

A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. Duplicated nameservers will be removed.

false

string array

searches

A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. Duplicated search paths will be removed.

false

string array

options

A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. Duplicated entries will be removed. Resolution options given in Options will override those that appear in the base DNSPolicy.

false

v1.PodDNSConfigOption array

-

v1.NFSVolumeSource

@@ -4663,6 +4735,47 @@

v1.PodSecurityContext

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + + + + +
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

+
+ +++++++ + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

@@ -4957,12 +5070,9 @@

v1.HostPathVolumeSource

-

v1.SecretProjection

-
-

Adapts a secret into a projected volume.

-
+

v1.PodDNSConfigOption

-

The contents of the target Secret’s Data field will be presented in a projected volume as files using the keys in the Data field as the file names. Note that this is identical to a secret volume source without the default mode.

+

PodDNSConfigOption defines DNS resolver options of a pod.

@@ -4984,33 +5094,29 @@

v1.SecretProjection

- + - - - - + - - - - - - + +

name

Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names

Required.

false

string

items

If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the .. path or start with ...

false

v1.KeyToPath array

value

optional

Specify whether the Secret or its key must be defined

false

boolean

false

string

-

v1.PodDNSConfigOption

+

v1.SecretProjection

-

PodDNSConfigOption defines DNS resolver options of a pod.

+

Adapts a secret into a projected volume.

+
+
+

The contents of the target Secret’s Data field will be presented in a projected volume as files using the keys in the Data field as the file names. Note that this is identical to a secret volume source without the default mode.

@@ -5032,18 +5138,25 @@

v1.PodDNSConfigOption

- + - - + + - + + + + + + + +

name

Required.

Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names

false

string

value

items

If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the .. path or start with ...

false

string

v1.KeyToPath array

optional

Specify whether the Secret or its key must be defined

false

boolean

false

@@ -5092,6 +5205,13 @@

v1.CinderVolumeSource

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -5671,6 +5791,47 @@

v1.NodeSelector

+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1.Patch

diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/certificates.k8s.io/v1beta1/operations.html b/vendor/k8s.io/kubernetes/docs/api-reference/certificates.k8s.io/v1beta1/operations.html index fca601ec9..fff9fff02 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/certificates.k8s.io/v1beta1/operations.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/certificates.k8s.io/v1beta1/operations.html @@ -1549,6 +1549,117 @@

Tags

+

read status of the specified CertificateSigningRequest

+
+
+
GET /apis/certificates.k8s.io/v1beta1/certificatesigningrequests/{name}/status
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

PathParameter

name

name of the CertificateSigningRequest

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1beta1.CertificateSigningRequest

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscertificates.k8s.iov1beta1

    +
  • +
+
+
+
+

replace status of the specified CertificateSigningRequest

@@ -1556,7 +1667,7 @@

replace stat

-

Parameters

+

Parameters

@@ -1606,7 +1717,7 @@

Parameters

-

Responses

+

Responses

@@ -1636,7 +1747,7 @@

Responses

-

Consumes

+

Consumes

  • @@ -1646,7 +1757,7 @@

    Consumes

-

Produces

+

Produces

  • @@ -1662,7 +1773,132 @@

    Produces

-

Tags

+

Tags

+
+
    +
  • +

    apiscertificates.k8s.iov1beta1

    +
  • +
+
+
+ +
+

partially update status of the specified CertificateSigningRequest

+
+
+
PATCH /apis/certificates.k8s.io/v1beta1/certificatesigningrequests/{name}/status
+
+
+
+

Parameters

+
++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

BodyParameter

body

true

v1.Patch

PathParameter

name

name of the CertificateSigningRequest

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1beta1.CertificateSigningRequest

+ +
+
+

Consumes

+
+
    +
  • +

    application/json-patch+json

    +
  • +
  • +

    application/merge-patch+json

    +
  • +
  • +

    application/strategic-merge-patch+json

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

  • @@ -1680,7 +1916,7 @@

    watch

-

Parameters

+

Parameters

@@ -1779,7 +2015,7 @@

Parameters

-

Responses

+

Responses

@@ -1804,7 +2040,7 @@

Responses

-

Consumes

+

Consumes

  • @@ -1814,7 +2050,7 @@

    Consumes

-

Produces

+

Produces

  • @@ -1836,7 +2072,7 @@

    Produces

-

Tags

+

Tags

  • @@ -1854,7 +2090,7 @@

    watch cha

-

Parameters

+

Parameters

@@ -1961,7 +2197,7 @@

Parameters

-

Responses

+

Responses

@@ -1986,7 +2222,7 @@

Responses

-

Consumes

+

Consumes

  • @@ -1996,7 +2232,7 @@

    Consumes

-

Produces

+

Produces

  • @@ -2018,7 +2254,7 @@

    Produces

-

Tags

+

Tags

  • diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/extensions/v1beta1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/extensions/v1beta1/definitions.html index 891411a76..f436de0cd 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/extensions/v1beta1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/extensions/v1beta1/definitions.html @@ -421,7 +421,7 @@

    Definitions

    v1beta1.AllowedHostPath

    -

    defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.

    +

    AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined. Deprecated: use AllowedHostPath from policy API Group instead.

@@ -443,13 +443,20 @@

v1beta1.AllowedHostPath

- + + + + + + +

pathPrefix

is the path prefix that the host volume must match. It does not support *. Trailing slashes are trimmed when validating the path prefix with a host path.
+

pathPrefix is the path prefix that the host volume must match. It does not support *. Trailing slashes are trimmed when validating the path prefix with a host path.

Examples: /foo would allow /foo, /foo/ and /foo/bar /foo would not allow /food or /etc/foo

false

string

readOnly

when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.

false

boolean

false

@@ -740,7 +747,7 @@

v1beta1.DaemonSetStatus

v1.NodeSelectorTerm

-

A null or empty node selector term matches no objects.

+

A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

@@ -762,8 +769,15 @@

v1.NodeSelectorTerm

- - + + + + + + + + + @@ -1002,7 +1016,7 @@

v1.VolumeMount

- + @@ -1508,7 +1522,7 @@

v1.GCEPersistentDiskVolumeSource

v1beta1.PodSecurityPolicyList

-

Pod Security Policy List is a list of PodSecurityPolicy objects.

+

PodSecurityPolicyList is a list of PodSecurityPolicy objects. Deprecated: use PodSecurityPolicyList from policy API Group instead.

matchExpressions

Required. A list of node selector requirements. The requirements are ANDed.

true

A list of node selector requirements by node’s labels.

false

v1.NodeSelectorRequirement array

matchFields

A list of node selector requirements by node’s fields.

false

v1.NodeSelectorRequirement array

mountPropagation

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.

false

v1.MountPropagationMode

@@ -1551,7 +1565,7 @@

v1beta1.PodSecurityPolicyList

- + @@ -1604,7 +1618,7 @@

v1beta1.RollingUpdateDeployment

v1beta1.FSGroupStrategyOptions

-

FSGroupStrategyOptions defines the strategy type and options used to create the strategy.

+

FSGroupStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use FSGroupStrategyOptions from policy API Group instead.

items

Items is a list of schema objects.

items is a list of schema objects.

true

v1beta1.PodSecurityPolicy array

@@ -1626,14 +1640,14 @@

v1beta1.FSGroupStrategyOptions

- + - + @@ -1739,6 +1753,9 @@

v1.GitRepoVolumeSource

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+

rule

Rule is the strategy that will dictate what FSGroup is used in the SecurityContext.

rule is the strategy that will dictate what FSGroup is used in the SecurityContext.

false

string

ranges

Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end.

ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs.

false

v1beta1.IDRange array

@@ -1914,6 +1931,54 @@

v1.Capabilities

+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -2989,7 +3054,7 @@

v1.ListMeta

v1beta1.SELinuxStrategyOptions

-

SELinux Strategy Options defines the strategy type and any options used to create the strategy.

+

SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use SELinuxStrategyOptions from policy API Group instead.

@@ -3011,7 +3076,7 @@

v1beta1.SELinuxStrategyOptions

- + @@ -3030,7 +3095,7 @@

v1beta1.SELinuxStrategyOptions

v1beta1.RunAsUserStrategyOptions

-

Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.

+

RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use RunAsUserStrategyOptions from policy API Group instead.

rule

type is the strategy that will dictate the allowable labels that may be set.

rule is the strategy that will dictate the allowable labels that may be set.

true

string

@@ -3052,14 +3117,14 @@

v1beta1.RunAsUserStrategyOptions

- + - + @@ -3362,7 +3427,7 @@

v1.LoadBalancerIngress

v1beta1.SupplementalGroupsStrategyOptions

-

SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy.

+

SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead.

rule

Rule is the strategy that will dictate the allowable RunAsUser values that may be set.

rule is the strategy that will dictate the allowable RunAsUser values that may be set.

true

string

ranges

Ranges are the allowed ranges of uids that may be used.

ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs.

false

v1beta1.IDRange array

@@ -3384,14 +3449,14 @@

v1beta1.SupplementalGroupsSt

- + - + @@ -3399,6 +3464,44 @@

v1beta1.SupplementalGroupsSt

rule

Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.

rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.

false

string

ranges

Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end.

ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs.

false

v1beta1.IDRange array

+
+
+

v1beta1.DaemonSetUpdateStrategy

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

type

Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is OnDelete.

false

string

rollingUpdate

Rolling update config params. Present only if type = "RollingUpdate".

false

v1beta1.RollingUpdateDaemonSet

+

v1.AzureDiskVolumeSource

@@ -3516,44 +3619,6 @@

v1.KeyToPath

-
-
-

v1beta1.DaemonSetUpdateStrategy

- ------- - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionRequiredSchemaDefault

type

Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is OnDelete.

false

string

rollingUpdate

Rolling update config params. Present only if type = "RollingUpdate".

false

v1beta1.RollingUpdateDaemonSet

-

v1.VsphereVirtualDiskVolumeSource

@@ -3794,7 +3859,7 @@

v1.Volume

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -4049,6 +4114,13 @@

v1.VolumeProjection

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + @@ -4318,7 +4390,7 @@

v1.SecretKeySelector

v1beta1.PodSecurityPolicy

-

Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.

+

PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container. Deprecated: use PodSecurityPolicy from policy API Group instead.

@@ -4641,6 +4713,13 @@

v1.PodSpec

+ + + + + + +

v1.PodDNSConfig

readinessGates

If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

false

v1.PodReadinessGate array

@@ -6137,21 +6216,25 @@

v1beta1.NetworkPolicyPeer

podSelector

-

This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace.

+

This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.
+
+If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy’s own Namespace.

false

v1.LabelSelector

namespaceSelector

-

Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces.

+

Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.
+
+If PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector.

false

v1.LabelSelector

ipBlock

-

IPBlock defines policy on a particular IPBlock

+

IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.

false

v1beta1.IPBlock

@@ -6566,6 +6649,13 @@

v1.PodSecurityContext

integer (int64)

+ +

sysctls

+

Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

+

false

+

v1.Sysctl array

+ + @@ -6610,6 +6700,40 @@

v1beta1.NetworkPolicyIngressRule

+
+
+

v1.PodReadinessGate

+
+

PodReadinessGate contains the reference to a pod condition

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

conditionType

ConditionType refers to a condition in the pod’s condition list with matching type.

true

string

+

v1.OwnerReference

@@ -6752,7 +6876,7 @@

v1beta1.ReplicaSetStatus

v1beta1.AllowedFlexVolume

-

AllowedFlexVolume represents a single Flexvolume that is allowed to be used.

+

AllowedFlexVolume represents a single Flexvolume that is allowed to be used. Deprecated: use AllowedFlexVolume from policy API Group instead.

@@ -6774,7 +6898,7 @@

v1beta1.AllowedFlexVolume

- + @@ -7304,6 +7428,13 @@

v1.CinderVolumeSource

+ + + + + + +

driver

Driver is the name of the Flexvolume driver.

driver is the name of the Flexvolume driver.

true

string

boolean

false

secretRef

Optional: points to a secret object containing parameters used to connect to OpenStack.

false

v1.LocalObjectReference

@@ -7518,7 +7649,7 @@

v1.QuobyteVolumeSource

v1beta1.HostPortRange

-

Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.

+

HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined. Deprecated: use HostPortRange from policy API Group instead.

@@ -7846,6 +7977,47 @@

v1.NodeSelector

+
+
+

v1.Sysctl

+
+

Sysctl defines a kernel parameter to be set

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

Name of a property to set

true

string

value

Value of a property to set

true

string

+

v1beta1.NetworkPolicyPort

@@ -7897,7 +8069,7 @@

v1.Patch

v1beta1.PodSecurityPolicySpec

-

Pod Security Policy Spec defines the policy enforced.

+

PodSecurityPolicySpec defines the policy enforced. Deprecated: use PodSecurityPolicySpec from policy API Group instead.

@@ -7926,28 +8098,28 @@

v1beta1.PodSecurityPolicySpec

- + - + - + - + @@ -7996,53 +8168,71 @@

v1beta1.PodSecurityPolicySpec

- + - + - + - + - + - + - + + + + + + + + + + + + + + +

defaultAddCapabilities

DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list.

defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.

false

v1.Capability array

requiredDropCapabilities

RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.

requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.

false

v1.Capability array

allowedCapabilities

AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author’s discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities.

allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author’s discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities.

false

v1.Capability array

volumes

volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.

volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use *.

false

v1beta1.FSType array

supplementalGroups

SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.

supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.

true

v1beta1.SupplementalGroupsStrategyOptions

fsGroup

FSGroup is the strategy that will dictate what fs group is used by the SecurityContext.

fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.

true

v1beta1.FSGroupStrategyOptions

readOnlyRootFilesystem

ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.

readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.

false

boolean

false

defaultAllowPrivilegeEscalation

DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.

defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.

false

boolean

false

allowPrivilegeEscalation

AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.

allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.

false

boolean

false

allowedHostPaths

is a white list of allowed host paths. Empty indicates that all host paths may be used.

allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.

false

v1beta1.AllowedHostPath array

allowedFlexVolumes

AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the "Volumes" field.

allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the "volumes" field.

false

v1beta1.AllowedFlexVolume array

allowedUnsafeSysctls

allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in "" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.
+
+Examples: e.g. "foo/
" allows "foo/bar", "foo/baz", etc. e.g. "foo.*" allows "foo.bar", "foo.baz", etc.

false

string array

forbiddenSysctls

forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in "" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.
+
+Examples: e.g. "foo/
" forbids "foo/bar", "foo/baz", etc. e.g. "foo.*" forbids "foo.bar", "foo.baz", etc.

false

string array

@@ -8311,7 +8501,7 @@

v1.PreferredSchedulingTerm

v1beta1.IDRange

-

ID Range provides a min/max of an allowed range of IDs.

+

IDRange provides a min/max of an allowed range of IDs. Deprecated: use IDRange from policy API Group instead.

@@ -8333,14 +8523,14 @@

v1beta1.IDRange

- + - + diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/networking.k8s.io/v1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/networking.k8s.io/v1/definitions.html index cd9647d88..b8fd5e22c 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/networking.k8s.io/v1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/networking.k8s.io/v1/definitions.html @@ -918,7 +918,7 @@

v1.NetworkPolicy

v1.NetworkPolicyPeer

-

NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields must be specified.

+

NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of fields are allowed

min

Min is the start of the range, inclusive.

min is the start of the range, inclusive.

true

integer (int64)

max

Max is the end of the range, inclusive.

max is the end of the range, inclusive.

true

integer (int64)

@@ -940,21 +940,25 @@

v1.NetworkPolicyPeer

- + - + - + diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/policy/v1beta1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/policy/v1beta1/definitions.html index 7ee64c22b..69c98d7a6 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/policy/v1beta1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/policy/v1beta1/definitions.html @@ -391,7 +391,7 @@

Definitions

v1beta1.AllowedHostPath

-

defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.

+

AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.

podSelector

This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace.

This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.
+
+If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy’s own Namespace.

false

v1.LabelSelector

namespaceSelector

Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces.

Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.
+
+If PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector.

false

v1.LabelSelector

ipBlock

IPBlock defines policy on a particular IPBlock

IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.

false

v1.IPBlock

@@ -413,13 +413,20 @@

v1beta1.AllowedHostPath

- + + + + + + +

pathPrefix

is the path prefix that the host volume must match. It does not support *. Trailing slashes are trimmed when validating the path prefix with a host path.
+

pathPrefix is the path prefix that the host volume must match. It does not support *. Trailing slashes are trimmed when validating the path prefix with a host path.

Examples: /foo would allow /foo, /foo/ and /foo/bar /foo would not allow /food or /etc/foo

false

string

readOnly

when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.

false

boolean

false

@@ -596,7 +603,7 @@

v1beta1.FSType

v1beta1.SELinuxStrategyOptions

-

SELinux Strategy Options defines the strategy type and any options used to create the strategy.

+

SELinuxStrategyOptions defines the strategy type and any options used to create the strategy.

@@ -618,7 +625,7 @@

v1beta1.SELinuxStrategyOptions

- + @@ -637,7 +644,7 @@

v1beta1.SELinuxStrategyOptions

v1beta1.HostPortRange

-

Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.

+

HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.

rule

type is the strategy that will dictate the allowable labels that may be set.

rule is the strategy that will dictate the allowable labels that may be set.

true

string

@@ -946,7 +953,7 @@

v1beta1.PodDisruptionBudgetList

v1beta1.RunAsUserStrategyOptions

-

Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.

+

RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy.

@@ -968,14 +975,14 @@

v1beta1.RunAsUserStrategyOptions

- + - + @@ -1140,14 +1147,14 @@

v1beta1.SupplementalGroupsSt

- + - + @@ -1159,7 +1166,7 @@

v1beta1.SupplementalGroupsSt

v1beta1.PodSecurityPolicyList

-

Pod Security Policy List is a list of PodSecurityPolicy objects.

+

PodSecurityPolicyList is a list of PodSecurityPolicy objects.

rule

Rule is the strategy that will dictate the allowable RunAsUser values that may be set.

rule is the strategy that will dictate the allowable RunAsUser values that may be set.

true

string

ranges

Ranges are the allowed ranges of uids that may be used.

ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs.

false

v1beta1.IDRange array

rule

Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.

rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.

false

string

ranges

Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end.

ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs.

false

v1beta1.IDRange array

@@ -1202,7 +1209,7 @@

v1beta1.PodSecurityPolicyList

- + @@ -1236,14 +1243,14 @@

v1beta1.FSGroupStrategyOptions

- + - + @@ -1330,7 +1337,7 @@

v1.DeleteOptions

v1beta1.PodSecurityPolicySpec

-

Pod Security Policy Spec defines the policy enforced.

+

PodSecurityPolicySpec defines the policy enforced.

items

Items is a list of schema objects.

items is a list of schema objects.

true

v1beta1.PodSecurityPolicy array

rule

Rule is the strategy that will dictate what FSGroup is used in the SecurityContext.

rule is the strategy that will dictate what FSGroup is used in the SecurityContext.

false

string

ranges

Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end.

ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs.

false

v1beta1.IDRange array

@@ -1359,28 +1366,28 @@

v1beta1.PodSecurityPolicySpec

- + - + - + - + @@ -1429,53 +1436,71 @@

v1beta1.PodSecurityPolicySpec

- + - + - + - + - + - + - + + + + + + + + + + + + + + +

defaultAddCapabilities

DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list.

defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.

false

v1.Capability array

requiredDropCapabilities

RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.

requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.

false

v1.Capability array

allowedCapabilities

AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author’s discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities.

allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author’s discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities.

false

v1.Capability array

volumes

volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.

volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use *.

false

v1beta1.FSType array

supplementalGroups

SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.

supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.

true

v1beta1.SupplementalGroupsStrategyOptions

fsGroup

FSGroup is the strategy that will dictate what fs group is used by the SecurityContext.

fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.

true

v1beta1.FSGroupStrategyOptions

readOnlyRootFilesystem

ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.

readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.

false

boolean

false

defaultAllowPrivilegeEscalation

DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.

defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.

false

boolean

false

allowPrivilegeEscalation

AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.

allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.

false

boolean

false

allowedHostPaths

is a white list of allowed host paths. Empty indicates that all host paths may be used.

allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.

false

v1beta1.AllowedHostPath array

allowedFlexVolumes

AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the "Volumes" field.

allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the "volumes" field.

false

v1beta1.AllowedFlexVolume array

allowedUnsafeSysctls

allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in "" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.
+
+Examples: e.g. "foo/
" allows "foo/bar", "foo/baz", etc. e.g. "foo.*" allows "foo.bar", "foo.baz", etc.

false

string array

forbiddenSysctls

forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in "" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.
+
+Examples: e.g. "foo/
" forbids "foo/bar", "foo/baz", etc. e.g. "foo.*" forbids "foo.bar", "foo.baz", etc.

false

string array

@@ -1655,7 +1680,7 @@

v1beta1.PodDisruptionBudgetStatus

v1beta1.PodSecurityPolicy

-

Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.

+

PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.

@@ -1714,7 +1739,7 @@

v1.Capability

v1beta1.IDRange

-

ID Range provides a min/max of an allowed range of IDs.

+

IDRange provides a min/max of an allowed range of IDs.

@@ -1736,14 +1761,14 @@

v1beta1.IDRange

- + - + @@ -2001,7 +2026,7 @@

v1beta1.AllowedFlexVolume

- + diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1/definitions.html index 2972fea36..204669f59 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1/definitions.html @@ -502,7 +502,7 @@

v1.ClusterRoleBinding

- + @@ -1443,7 +1443,7 @@

v1.RoleBinding

- + diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/definitions.html index 9a95c0685..8605a9c95 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/definitions.html @@ -924,7 +924,7 @@

v1alpha1.RoleBinding

- + @@ -1791,7 +1791,7 @@

v1alpha1.ClusterRoleBinding

- + diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1beta1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1beta1/definitions.html index 86664748e..5007ef02f 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1beta1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/rbac.authorization.k8s.io/v1beta1/definitions.html @@ -1196,7 +1196,7 @@

v1beta1.ClusterRoleBinding

- + @@ -1930,7 +1930,7 @@

v1beta1.RoleBinding

- + diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/scheduling.k8s.io/v1beta1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/scheduling.k8s.io/v1beta1/definitions.html new file mode 100755 index 000000000..4b8adef58 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/api-reference/scheduling.k8s.io/v1beta1/definitions.html @@ -0,0 +1,1375 @@ + + + + + + +Top Level API Objects + + + + +
+
+

Top Level API Objects

+ +
+
+

Definitions

+
+
+

v1.APIResourceList

+
+

APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.

+
+

min

Min is the start of the range, inclusive.

min is the start of the range, inclusive.

true

integer (int64)

max

Max is the end of the range, inclusive.

max is the end of the range, inclusive.

true

integer (int64)

driver

Driver is the name of the Flexvolume driver.

driver is the name of the Flexvolume driver.

true

string

subjects

Subjects holds references to the objects the role applies to.

true

false

v1.Subject array

subjects

Subjects holds references to the objects the role applies to.

true

false

v1.Subject array

subjects

Subjects holds references to the objects the role applies to.

true

false

v1alpha1.Subject array

subjects

Subjects holds references to the objects the role applies to.

true

false

v1alpha1.Subject array

subjects

Subjects holds references to the objects the role applies to.

true

false

v1beta1.Subject array

subjects

Subjects holds references to the objects the role applies to.

true

false

v1beta1.Subject array

+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

groupVersion

groupVersion is the group and version this APIResourceList is for.

true

string

resources

resources contains the name of the resources and if they are namespaced.

true

v1.APIResource array

+ +
+
+

v1.Patch

+
+

Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.

+
+
+
+

v1.DeleteOptions

+
+

DeleteOptions may be provided when deleting an API object.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

gracePeriodSeconds

The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.

false

integer (int64)

preconditions

Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned.

false

v1.Preconditions

orphanDependents

Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the "orphan" finalizer will be added to/removed from the object’s finalizers list. Either this field or PropagationPolicy may be set, but not both.

false

boolean

false

propagationPolicy

Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: Orphan - orphan the dependents; Background - allow the garbage collector to delete the dependents in the background; Foreground - a cascading policy that deletes all dependents in the foreground.

false

v1.DeletionPropagation

+ +
+
+

v1.ListMeta

+
+

ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

selfLink

selfLink is a URL representing this object. Populated by the system. Read-only.

false

string

resourceVersion

String that identifies the server’s internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency

false

string

continue

continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response.

false

string

+ +
+
+

v1beta1.PriorityClass

+
+

PriorityClass defines mapping from a priority class name to the priority integer value. The value can be any valid integer.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

metadata

Standard object’s metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

v1.ObjectMeta

value

The value of this priority class. This is the actual priority that pods receive when they have the name of this class in their pod spec.

true

integer (int32)

globalDefault

globalDefault specifies whether this PriorityClass should be considered as the default priority for pods that do not have any priority class. Only one PriorityClass can be marked as globalDefault. However, if more than one PriorityClasses exists with their globalDefault field set to true, the smallest value of such global default PriorityClasses will be used as the default priority.

false

boolean

false

description

description is an arbitrary string that usually provides guidelines on when this priority class should be used.

false

string

+ +
+
+

v1.StatusDetails

+
+

StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described).

false

string

group

The group attribute of the resource associated with the status StatusReason.

false

string

kind

The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

uid

UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids

false

string

causes

The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes.

false

v1.StatusCause array

retryAfterSeconds

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

+ +
+
+

v1.Preconditions

+
+

Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

uid

Specifies the target UID.

false

types.UID

+ +
+
+

v1.Initializers

+
+

Initializers tracks the progress of initialization.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

pending

Pending is a list of initializers that must execute in order before this object is visible. When the last pending initializer is removed, and no failing result is set, the initializers struct will be set to nil and the object is considered as initialized and visible to all clients.

true

v1.Initializer array

result

If result is set with the Failure field, the object will be persisted to storage and then deleted, ensuring that other clients can observe the deletion.

false

v1.Status

+ +
+
+

v1.Initializer

+
+

Initializer is information about an initializer that has not yet completed.

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

name of the process that is responsible for initializing this object.

true

string

+ +
+
+

v1.Status

+
+

Status is a return value for calls that don’t return other objects.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

metadata

Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

v1.ListMeta

status

Status of the operation. One of: "Success" or "Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

false

string

message

A human-readable description of the status of this operation.

false

string

reason

A machine-readable description of why this operation is in the "Failure" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it.

false

string

details

Extended data associated with the reason. Each reason may define its own extended details. This field is optional and the data returned is not guaranteed to conform to any schema except that defined by the reason type.

false

v1.StatusDetails

code

Suggested HTTP return code for this status, 0 if not set.

false

integer (int32)

+ +
+
+

v1.WatchEvent

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

type

true

string

object

true

string

+ +
+
+

v1.ObjectMeta

+
+

ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names

false

string

generateName

GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.
+
+If this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).
+
+Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency

false

string

namespace

Namespace defines the space within each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.
+
+Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces

false

string

selfLink

SelfLink is a URL representing this object. Populated by the system. Read-only.

false

string

uid

UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.
+
+Populated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids

false

string

resourceVersion

An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.
+
+Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency

false

string

generation

A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.

false

integer (int64)

creationTimestamp

CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.
+
+Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

string

deletionTimestamp

DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.
+
+Populated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

string

deletionGracePeriodSeconds

Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.

false

integer (int64)

labels

Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels

false

object

annotations

Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations

false

object

ownerReferences

List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.

false

v1.OwnerReference array

initializers

An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven’t explicitly asked to observe uninitialized objects.
+
+When an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user.

false

v1.Initializers

finalizers

Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed.

false

string array

clusterName

The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.

false

string

+ +
+
+

v1.OwnerReference

+
+

OwnerReference contains enough information to let you identify an owning object. Currently, an owning object must be in the same namespace, so there is no namespace field.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

apiVersion

API version of the referent.

true

string

kind

Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

true

string

name

Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names

true

string

uid

UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids

true

string

controller

If true, this reference points to the managing controller.

false

boolean

false

blockOwnerDeletion

If true, AND if the owner has the "foregroundDeletion" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. Defaults to false. To set this field, a user needs "delete" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned.

false

boolean

false

+ +
+
+

v1.APIResource

+
+

APIResource specifies the name of a resource and whether it is namespaced.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

name is the plural name of the resource.

true

string

singularName

singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface.

true

string

namespaced

namespaced indicates if a resource is namespaced or not.

true

boolean

false

group

group is the preferred group of the resource. Empty implies the group of the containing resource list. For subresources, this may have a different value, for example: Scale".

false

string

version

version is the preferred version of the resource. Empty implies the version of the containing resource list For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource’s group)".

false

string

kind

kind is the kind for the resource (e.g. Foo is the kind for a resource foo)

true

string

verbs

verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)

true

string array

shortNames

shortNames is a list of suggested short names of the resource.

false

string array

categories

categories is a list of the grouped resources this resource belongs to (e.g. all)

false

string array

+ +
+
+

types.UID

+ +
+
+

v1beta1.PriorityClassList

+
+

PriorityClassList is a collection of priority classes.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

metadata

Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

v1.ListMeta

items

items is the list of PriorityClasses

true

v1beta1.PriorityClass array

+ +
+
+

v1.StatusCause

+
+

StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

reason

A machine-readable description of the cause of the error. If this value is empty there is no information available.

false

string

message

A human-readable description of the cause of the error. This field may be presented as-is to a reader.

false

string

field

The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.
+
+Examples:
+ "name" - the field "name" on the current resource
+ "items[0].name" - the field "name" on the first array entry in "items"

false

string

+ +
+
+

v1.DeletionPropagation

+ +
+
+

any

+
+

Represents an untyped JSON map - see the description of the field for more info about the structure of this object.

+
+
+
+
+
+ + + \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/scheduling.k8s.io/v1beta1/operations.html b/vendor/k8s.io/kubernetes/docs/api-reference/scheduling.k8s.io/v1beta1/operations.html new file mode 100755 index 000000000..8c9c1566c --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/api-reference/scheduling.k8s.io/v1beta1/operations.html @@ -0,0 +1,1792 @@ + + + + + + +Operations + + + + +
+
+

Operations

+
+
+

get available resources

+
+
+
GET /apis/scheduling.k8s.io/v1beta1
+
+
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

default

success

v1.APIResourceList

+ +
+
+

Consumes

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+

list or watch objects of kind PriorityClass

+
+
+
GET /apis/scheduling.k8s.io/v1beta1/priorityclasses
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1beta1.PriorityClassList

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+

delete collection of PriorityClass

+
+
+
DELETE /apis/scheduling.k8s.io/v1beta1/priorityclasses
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.Status

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+

create a PriorityClass

+
+
+
POST /apis/scheduling.k8s.io/v1beta1/priorityclasses
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

BodyParameter

body

true

v1beta1.PriorityClass

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

202

Accepted

v1beta1.PriorityClass

200

success

v1beta1.PriorityClass

201

Created

v1beta1.PriorityClass

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+

read the specified PriorityClass

+
+
+
GET /apis/scheduling.k8s.io/v1beta1/priorityclasses/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

export

Should this value be exported. Export strips fields that a user can not specify.

false

boolean

QueryParameter

exact

Should the export be exact. Exact export maintains cluster-specific fields like Namespace.

false

boolean

PathParameter

name

name of the PriorityClass

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1beta1.PriorityClass

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+

replace the specified PriorityClass

+
+
+
PUT /apis/scheduling.k8s.io/v1beta1/priorityclasses/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

BodyParameter

body

true

v1beta1.PriorityClass

PathParameter

name

name of the PriorityClass

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1beta1.PriorityClass

201

Created

v1beta1.PriorityClass

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+

delete a PriorityClass

+
+
+
DELETE /apis/scheduling.k8s.io/v1beta1/priorityclasses/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

BodyParameter

body

true

v1.DeleteOptions

QueryParameter

gracePeriodSeconds

The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.

false

integer (int32)

QueryParameter

orphanDependents

Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the "orphan" finalizer will be added to/removed from the object’s finalizers list. Either this field or PropagationPolicy may be set, but not both.

false

boolean

QueryParameter

propagationPolicy

Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: Orphan - orphan the dependents; Background - allow the garbage collector to delete the dependents in the background; Foreground - a cascading policy that deletes all dependents in the foreground.

false

string

PathParameter

name

name of the PriorityClass

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.Status

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+

partially update the specified PriorityClass

+
+
+
PATCH /apis/scheduling.k8s.io/v1beta1/priorityclasses/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

BodyParameter

body

true

v1.Patch

PathParameter

name

name of the PriorityClass

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1beta1.PriorityClass

+ +
+
+

Consumes

+
+
    +
  • +

    application/json-patch+json

    +
  • +
  • +

    application/merge-patch+json

    +
  • +
  • +

    application/strategic-merge-patch+json

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+

watch individual changes to a list of PriorityClass

+
+
+
GET /apis/scheduling.k8s.io/v1beta1/watch/priorityclasses
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.WatchEvent

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+

watch changes to an object of kind PriorityClass

+
+
+
GET /apis/scheduling.k8s.io/v1beta1/watch/priorityclasses/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

PathParameter

name

name of the PriorityClass

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.WatchEvent

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apisscheduling.k8s.iov1beta1

    +
  • +
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html index e048b45f8..3ba8dcd77 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html @@ -941,7 +941,7 @@

v1.VolumeMount

mountPropagation

-

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.

+

mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.

false

v1.MountPropagationMode

@@ -1370,6 +1370,9 @@

v1.GitRepoVolumeSource

Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

+
+

DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

+
@@ -1573,6 +1576,54 @@

v1.StatusDetails

+
+
+

v1.ServiceAccountTokenProjection

+
+

ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

audience

Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

false

string

expirationSeconds

ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

false

integer (int64)

path

Path is the path relative to the mount point of the file to project the token into.

true

string

+

v1.Initializer

@@ -2378,6 +2429,13 @@

v1.CinderVolumeSource

boolean

false

+ +

secretRef

+

Optional: points to a secret object containing parameters used to connect to OpenStack.

+

false

+

v1.LocalObjectReference

+ + @@ -3365,7 +3423,7 @@

v1.Volume

gitRepo

-

GitRepo represents a git repository at a particular revision.

+

GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

false

v1.GitRepoVolumeSource

@@ -3726,6 +3784,13 @@

v1.VolumeProjection

v1.ConfigMapProjection

+ +

serviceAccountToken

+

information about the serviceAccountToken data to project

+

false

+

v1.ServiceAccountTokenProjection

+ + diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/storage.k8s.io/v1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/storage.k8s.io/v1/definitions.html index a8b980f1f..6d6bed86b 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/storage.k8s.io/v1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/storage.k8s.io/v1/definitions.html @@ -559,6 +559,47 @@

v1.ListMeta

+
+
+

v1.TopologySelectorLabelRequirement

+
+

A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

key

The label key that the selector applies to.

true

string

values

An array of string values. One value must match the label to be selected. Each entry in Values is ORed.

true

string array

+

v1.StatusDetails

@@ -1003,6 +1044,13 @@

v1.StorageClass

v1.VolumeBindingMode

+ +

allowedTopologies

+

Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.

+

false

+

v1.TopologySelectorTerm array

+ + @@ -1230,6 +1278,40 @@

v1.OwnerReference

+
+
+

v1.TopologySelectorTerm

+
+

A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

matchLabelExpressions

A list of topology selector requirements by labels.

false

v1.TopologySelectorLabelRequirement array

+

v1.PersistentVolumeReclaimPolicy

diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/storage.k8s.io/v1beta1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/storage.k8s.io/v1beta1/definitions.html index 1e36a2452..77fec9d25 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/storage.k8s.io/v1beta1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/storage.k8s.io/v1beta1/definitions.html @@ -779,6 +779,40 @@

v1beta1.VolumeAttachmentSource

v1.PersistentVolumeReclaimPolicy

+
+
+

v1.TopologySelectorTerm

+
+

A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

matchLabelExpressions

A list of topology selector requirements by labels.

false

v1.TopologySelectorLabelRequirement array

+

v1beta1.VolumeAttachmentList

@@ -1041,6 +1075,47 @@

v1.StatusDetails

+
+
+

v1.TopologySelectorLabelRequirement

+
+

A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

key

The label key that the selector applies to.

true

string

values

An array of string values. One value must match the label to be selected. Each entry in Values is ORed.

true

string array

+

v1.Initializer

@@ -1075,6 +1150,47 @@

v1.Initializer

+
+
+

v1beta1.VolumeError

+
+

VolumeError captures an error encountered during a volume operation.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

time

Time the error was encountered.

false

string

message

String detailing the error encountered during Attach or Detach operation. This string maybe logged, so it should not contain sensitive information.

false

string

+

v1beta1.StorageClass

@@ -1165,45 +1281,11 @@

v1beta1.StorageClass

v1beta1.VolumeBindingMode

- - - -
-
-

v1beta1.VolumeError

-
-

VolumeError captures an error encountered during a volume operation.

-
- ------- - - - - - - - - - - - - + + - - - - - - - - + diff --git a/vendor/k8s.io/kubernetes/docs/api-reference/v1/definitions.html b/vendor/k8s.io/kubernetes/docs/api-reference/v1/definitions.html index d3fdf533c..5cbafdb60 100755 --- a/vendor/k8s.io/kubernetes/docs/api-reference/v1/definitions.html +++ b/vendor/k8s.io/kubernetes/docs/api-reference/v1/definitions.html @@ -403,9 +403,6 @@

Top Level API Objects

v1.Node

  • -

    v1.NodeConfigSource

    -
  • -
  • v1.NodeList

  • @@ -970,6 +967,9 @@

    v1.GitRepoVolumeSource

    Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.

    +
    +

    DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

    +
  • NameDescriptionRequiredSchemaDefault

    time

    Time the error was encountered.

    allowedTopologies

    Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.

    false

    string

    message

    String detailing the error encountered during Attach or Detach operation. This string maybe logged, so it should not contain sensitive information.

    false

    string

    v1.TopologySelectorTerm array

    @@ -2999,6 +2999,13 @@

    v1.NodeStatus

    + + + + + + +

    v1.AttachedVolume array

    config

    Status of the config assigned to the node via the dynamic Kubelet config feature.

    false

    v1.NodeConfigStatus

    @@ -3661,6 +3668,68 @@

    v1.HTTPHeader

    +
    +
    +

    v1.ConfigMapNodeConfigSource

    +
    +

    ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.

    +
    + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDescriptionRequiredSchemaDefault

    namespace

    Namespace is the metadata.namespace of the referenced ConfigMap. This field is required in all cases.

    true

    string

    name

    Name is the metadata.name of the referenced ConfigMap. This field is required in all cases.

    true

    string

    uid

    UID is the metadata.UID of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status.

    false

    string

    resourceVersion

    ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status.

    false

    string

    kubeletConfigKey

    KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure This field is required in all cases.

    true

    string

    +

    v1.EndpointPort

    @@ -4068,7 +4137,7 @@

    v1.PersistentVolumeSpec

    cinder

    Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md

    false

    -

    v1.CinderVolumeSource

    +

    v1.CinderPersistentVolumeSource

    @@ -4289,6 +4358,13 @@

    v1.PodSecurityContext

    integer (int64)

    + +

    sysctls

    +

    Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.

    +

    false

    +

    v1.Sysctl array

    + + @@ -4907,6 +4983,13 @@

    v1.CinderVolumeSource

    boolean

    false

    + +

    secretRef

    +

    Optional: points to a secret object containing parameters used to connect to OpenStack.

    +

    false

    +

    v1.LocalObjectReference

    + + @@ -5651,6 +5734,47 @@

    v1.PersistentVolumeList

    +
    +
    +

    v1.Sysctl

    +
    +

    Sysctl defines a kernel parameter to be set

    +
    + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDescriptionRequiredSchemaDefault

    name

    Name of a property to set

    true

    string

    value

    Value of a property to set

    true

    string

    +

    v1.Patch

    @@ -5830,24 +5954,10 @@

    v1.NodeConfigSource

    -

    kind

    -

    Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

    -

    false

    -

    string

    - - - -

    apiVersion

    -

    APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

    -

    false

    -

    string

    - - - -

    configMapRef

    - +

    configMap

    +

    ConfigMap is a reference to a Node’s ConfigMap

    false

    -

    v1.ObjectReference

    +

    v1.ConfigMapNodeConfigSource

    @@ -5901,6 +6011,40 @@

    v1.ConfigMapKeySelector

    +
    +
    +

    v1.ScopeSelector

    +
    +

    A scope selector represents the AND of the selectors represented by the scoped-resource selector requirements.

    +
    + +++++++ + + + + + + + + + + + + + + + + + + +
    NameDescriptionRequiredSchemaDefault

    matchExpressions

    A list of scope selector requirements by scope of the resources.

    false

    v1.ScopedResourceSelectorRequirement array

    +

    v1.NodeSystemInfo

    @@ -6101,7 +6245,7 @@

    v1.ServiceSpec

    publishNotReadyAddresses

    -

    publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet’s Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery. This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints when that annotation is deprecated and all clients have been converted to use this field.

    +

    publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet’s Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery.

    false

    boolean

    false

    @@ -6455,9 +6599,9 @@

    v1.PersistentVolumeClaimList

    -

    v1.NodeSelectorTerm

    +

    v1.LocalVolumeSource

    -

    A null or empty node selector term matches no objects.

    +

    Local represents directly-attached storage with node affinity (Beta feature)

    @@ -6478,10 +6622,10 @@

    v1.NodeSelectorTerm

    - - + + - + @@ -6489,9 +6633,9 @@

    v1.NodeSelectorTerm

    -

    v1.LocalVolumeSource

    +

    v1.NodeSelectorTerm

    -

    Local represents directly-attached storage with node affinity

    +

    A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.

    matchExpressions

    Required. A list of node selector requirements. The requirements are ANDed.

    path

    The full path to the volume on the node. It can be either a directory or block device (disk, partition, …). Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. Block devices can be represented only by VolumeMode=Block, which also requires the BlockVolume alpha feature gate to be enabled.

    true

    v1.NodeSelectorRequirement array

    string

    @@ -6512,10 +6656,17 @@

    v1.LocalVolumeSource

    - - - - + + + + + + + + + + + @@ -6630,7 +6781,7 @@

    v1.VolumeMount

    - + @@ -6801,7 +6952,7 @@

    v1.ResourceQuotaSpec

    - + @@ -6813,6 +6964,13 @@

    v1.ResourceQuotaSpec

    + + + + + + +

    path

    The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device

    true

    string

    matchExpressions

    A list of node selector requirements by node’s labels.

    false

    v1.NodeSelectorRequirement array

    matchFields

    A list of node selector requirements by node’s fields.

    false

    v1.NodeSelectorRequirement array

    mountPropagation

    mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.

    mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.

    false

    v1.MountPropagationMode

    hard

    Hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/

    hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/

    false

    object

    v1.ResourceQuotaScope array

    scopeSelector

    scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota but expressed using ScopeSelectorOperator in combination with possible values. For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched.

    false

    v1.ScopeSelector

    @@ -7241,6 +7399,54 @@

    v1.NodeCondition

    +
    +
    +

    v1.ServiceAccountTokenProjection

    +
    +

    ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).

    +
    + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDescriptionRequiredSchemaDefault

    audience

    Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.

    false

    string

    expirationSeconds

    ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.

    false

    integer (int64)

    path

    Path is the path relative to the mount point of the file to project the token into.

    true

    string

    +

    v1.LocalObjectReference

    @@ -7840,6 +8046,116 @@

    v1.ResourceQuotaList

    v1.UniqueVolumeName

    +
    +
    +

    v1.CinderPersistentVolumeSource

    +
    +

    Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.

    +
    + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDescriptionRequiredSchemaDefault

    volumeID

    volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md

    true

    string

    fsType

    Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md

    false

    string

    readOnly

    Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md

    false

    boolean

    false

    secretRef

    Optional: points to a secret object containing parameters used to connect to OpenStack.

    false

    v1.SecretReference

    + +
    +
    +

    v1.NodeConfigStatus

    +
    +

    NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource.

    +
    + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDescriptionRequiredSchemaDefault

    assigned

    Assigned reports the checkpointed config the node will try to use. When Node.Spec.ConfigSource is updated, the node checkpoints the associated config payload to local disk, along with a record indicating intended config. The node refers to this record to choose its config checkpoint, and reports this record in Assigned. Assigned only updates in the status after the record has been checkpointed to disk. When the Kubelet is restarted, it tries to make the Assigned config the Active config by loading and validating the checkpointed payload identified by Assigned.

    false

    v1.NodeConfigSource

    active

    Active reports the checkpointed config the node is actively using. Active will represent either the current version of the Assigned config, or the current LastKnownGood config, depending on whether attempting to use the Assigned config results in an error.

    false

    v1.NodeConfigSource

    lastKnownGood

    LastKnownGood reports the checkpointed config the node will fall back to when it encounters an error attempting to use the Assigned config. The Assigned config becomes the LastKnownGood config when the node determines that the Assigned config is stable and correct. This is currently implemented as a 10-minute soak period starting when the local record of Assigned config is updated. If the Assigned config is Active at the end of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, because the local default config is always assumed good. You should not make assumptions about the node’s method of determining config stability and correctness, as this may change or become configurable in the future.

    false

    v1.NodeConfigSource

    error

    Error describes any problems reconciling the Spec.ConfigSource to the Active config. Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting to load or validate the Assigned config, etc. Errors may occur at different points while syncing config. Earlier errors (e.g. download or checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error by fixing the config assigned in Spec.ConfigSource. You can find additional information for debugging by searching the error message in the Kubelet log. Error is a human-readable description of the error state; machines can check whether or not Error is empty, but should not rely on the stability of the Error text across Kubelet versions.

    false

    string

    +

    v1.CSIPersistentVolumeSource

    @@ -7887,7 +8203,7 @@

    v1.CSIPersistentVolumeSource

    fsType

    -

    Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.

    +

    Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs".

    false

    string

    @@ -8152,9 +8468,9 @@

    v1.VsphereVirtualDiskVolumeSource
    -

    v1.LimitRangeList

    +

    v1.ServiceAccountList

    -

    LimitRangeList is a list of LimitRange items.

    +

    ServiceAccountList is a list of ServiceAccount objects

    @@ -8197,9 +8513,9 @@

    v1.LimitRangeList

    - + - + @@ -8207,9 +8523,9 @@

    v1.LimitRangeList

    -

    v1.ServiceAccountList

    +

    v1.LimitRangeList

    -

    ServiceAccountList is a list of ServiceAccount objects

    +

    LimitRangeList is a list of LimitRange items.

    items

    Items is a list of LimitRange objects. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

    List of ServiceAccounts. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/

    true

    v1.LimitRange array

    v1.ServiceAccount array

    @@ -8252,9 +8568,9 @@

    v1.ServiceAccountList

    - + - + @@ -8456,7 +8772,7 @@

    v1.Volume

    - + @@ -8663,6 +8979,13 @@

    v1.VolumeProjection

    + + + + + + +

    items

    List of ServiceAccounts. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/

    Items is a list of LimitRange objects. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

    true

    v1.ServiceAccount array

    v1.LimitRange array

    gitRepo

    GitRepo represents a git repository at a particular revision.

    GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod’s container.

    false

    v1.GitRepoVolumeSource

    v1.ConfigMapProjection

    serviceAccountToken

    information about the serviceAccountToken data to project

    false

    v1.ServiceAccountTokenProjection

    @@ -9046,7 +9369,7 @@

    v1.DownwardAPIVolumeFile

    v1.PodStatus

    -

    PodStatus represents information about the status of a pod. Status may trail the actual state of a system.

    +

    PodStatus represents information about the status of a pod. Status may trail the actual state of a system, especially if the node that hosts the pod cannot contact the control plane.

    @@ -9068,7 +9391,11 @@

    v1.PodStatus

    - + @@ -9359,6 +9686,61 @@

    v1.PodSpec

    + + + + + + + + +

    phase

    Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase

    The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod’s status. There are five possible phase values:
    +
    +Pending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.
    +
    +More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase

    false

    string

    v1.PodDNSConfig

    readinessGates

    If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md

    false

    v1.PodReadinessGate array

    + +
    +
    +

    v1.ScopedResourceSelectorRequirement

    +
    +

    A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.

    +
    + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDescriptionRequiredSchemaDefault

    scopeName

    The name of the scope that the selector applies to.

    true

    string

    operator

    Represents a scope’s relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist.

    true

    string

    values

    An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.

    false

    string array

    @@ -9525,7 +9907,7 @@

    v1.PodCondition

    type

    -

    Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions

    +

    Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions

    true

    string

    @@ -10211,6 +10593,40 @@

    v1.ReplicationControllerStatus

    +
    +
    +

    v1.PodReadinessGate

    +
    +

    PodReadinessGate contains the reference to a pod condition

    +
    + +++++++ + + + + + + + + + + + + + + + + + + +
    NameDescriptionRequiredSchemaDefault

    conditionType

    ConditionType refers to a condition in the pod’s condition list with matching type.

    true

    string

    +

    v1.ComponentCondition

    @@ -10583,44 +10999,6 @@

    v1.ReplicationControllerList

    -
    -
    -

    v1.WatchEvent

    - ------- - - - - - - - - - - - - - - - - - - - - - - - - - -
    NameDescriptionRequiredSchemaDefault

    type

    true

    string

    object

    true

    string

    -

    v1.Secret

    @@ -10690,6 +11068,44 @@

    v1.Secret

    +
    +
    +

    v1.WatchEvent

    + +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDescriptionRequiredSchemaDefault

    type

    true

    string

    object

    true

    string

    +

    v1.LabelSelectorRequirement

    @@ -11385,13 +11801,6 @@

    v1.NodeSpec

    -

    externalID

    -

    External ID of the node assigned by some machine database (e.g. a cloud provider). Deprecated.

    -

    false

    -

    string

    - - -

    providerID

    ID of the node assigned by the cloud provider in the format: <ProviderName>://<ProviderSpecificNodeID>

    false

    @@ -11419,6 +11828,13 @@

    v1.NodeSpec

    v1.NodeConfigSource

    + +

    externalID

    +

    Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966

    +

    false

    +

    string

    + + diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-addon-coredns.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-addon-coredns.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-addon-coredns.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-download.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-download.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-download.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-enable-dynamic.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-enable-dynamic.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-enable-dynamic.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-upload.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-upload.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-upload.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-write-to-disk.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-write-to-disk.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config-write-to-disk.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-config.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-write-env-file.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-write-env-file.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet-write-env-file.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-alpha-phase-kubelet.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images-list-images.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images-list-images.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images-list-images.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images-list.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images-list.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images-list.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images-pull.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images-pull.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images-pull.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-images.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-migrate.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-migrate.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-migrate.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-print-default.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-print-default.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-config-print-default.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-upgrade-diff.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-upgrade-diff.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-upgrade-diff.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-upgrade-node-config.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-upgrade-node-config.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-upgrade-node-config.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-upgrade-node.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-upgrade-node.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubeadm-upgrade-node.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubectl-api-resources.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubectl-api-resources.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubectl-api-resources.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubectl-wait.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubectl-wait.1 new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubectl-wait.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_api-resources.md b/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_api-resources.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_api-resources.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_wait.md b/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_wait.md new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_wait.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/yaml/kubectl/kubectl_api-resources.yaml b/vendor/k8s.io/kubernetes/docs/yaml/kubectl/kubectl_api-resources.yaml new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/yaml/kubectl/kubectl_api-resources.yaml @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/yaml/kubectl/kubectl_wait.yaml b/vendor/k8s.io/kubernetes/docs/yaml/kubectl/kubectl_wait.yaml new file mode 100644 index 000000000..b6fd7a0f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/yaml/kubectl/kubectl_wait.yaml @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/examples/BUILD b/vendor/k8s.io/kubernetes/examples/BUILD deleted file mode 100644 index 65c8be3a6..000000000 --- a/vendor/k8s.io/kubernetes/examples/BUILD +++ /dev/null @@ -1,70 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -filegroup( - name = "config", - srcs = glob([ - "**/*.yaml", - "**/*.yml", - "**/*.json", - ]) + [ - "pod", - ], -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - importpath = "k8s.io/kubernetes/examples", -) - -go_test( - name = "go_default_xtest", - srcs = ["examples_test.go"], - tags = ["manual"], # this test is broken and examples in-tree is deprecated - deps = [ - "//pkg/api/testapi:go_default_library", - "//pkg/apis/apps:go_default_library", - "//pkg/apis/apps/validation:go_default_library", - "//pkg/apis/batch:go_default_library", - "//pkg/apis/core:go_default_library", - "//pkg/apis/core/validation:go_default_library", - "//pkg/apis/extensions:go_default_library", - "//pkg/apis/extensions/validation:go_default_library", - "//pkg/capabilities:go_default_library", - "//pkg/registry/batch/job:go_default_library", - "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/api/latest:go_default_library", - "//pkg/scheduler/api/validation:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//examples/explorer:all-srcs", - "//examples/guestbook-go:all-srcs", - "//examples/https-nginx:all-srcs", - "//examples/sharing-clusters:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/examples/OWNERS b/vendor/k8s.io/kubernetes/examples/OWNERS deleted file mode 100644 index 315623ca8..000000000 --- a/vendor/k8s.io/kubernetes/examples/OWNERS +++ /dev/null @@ -1,10 +0,0 @@ -reviewers: - - brendandburns - - thockin - - zmerlynn - - zouyee -approvers: - - brendandburns - - eparis - - thockin - - zmerlynn diff --git a/vendor/k8s.io/kubernetes/examples/README.md b/vendor/k8s.io/kubernetes/examples/README.md deleted file mode 100644 index 6ea45f700..000000000 --- a/vendor/k8s.io/kubernetes/examples/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/README.md](https://github.com/kubernetes/examples/blob/master/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/cloud-controller-manager/persistent-volume-label-initializer-config.yaml b/vendor/k8s.io/kubernetes/examples/cloud-controller-manager/persistent-volume-label-initializer-config.yaml deleted file mode 100644 index 4a2576cc2..000000000 --- a/vendor/k8s.io/kubernetes/examples/cloud-controller-manager/persistent-volume-label-initializer-config.yaml +++ /dev/null @@ -1,13 +0,0 @@ -kind: InitializerConfiguration -apiVersion: admissionregistration.k8s.io/v1alpha1 -metadata: - name: pvlabel.kubernetes.io -initializers: - - name: pvlabel.kubernetes.io - rules: - - apiGroups: - - "" - apiVersions: - - "*" - resources: - - persistentvolumes diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/README.md b/vendor/k8s.io/kubernetes/examples/cluster-dns/README.md deleted file mode 100644 index c7b23c627..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/cluster-dns/README.md](https://github.com/kubernetes/examples/blob/master/staging/cluster-dns/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/dns-backend-rc.yaml b/vendor/k8s.io/kubernetes/examples/cluster-dns/dns-backend-rc.yaml deleted file mode 100644 index 4af1b0dcb..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/dns-backend-rc.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: dns-backend - labels: - name: dns-backend -spec: - replicas: 1 - selector: - name: dns-backend - template: - metadata: - labels: - name: dns-backend - spec: - containers: - - name: dns-backend - image: k8s.gcr.io/example-dns-backend:v1 - ports: - - name: backend-port - containerPort: 8000 diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/dns-backend-service.yaml b/vendor/k8s.io/kubernetes/examples/cluster-dns/dns-backend-service.yaml deleted file mode 100644 index 0a814ce18..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/dns-backend-service.yaml +++ /dev/null @@ -1,9 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: dns-backend -spec: - ports: - - port: 8000 - selector: - name: dns-backend diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/dns-frontend-pod.yaml b/vendor/k8s.io/kubernetes/examples/cluster-dns/dns-frontend-pod.yaml deleted file mode 100644 index 4a7695f11..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/dns-frontend-pod.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: dns-frontend - labels: - name: dns-frontend -spec: - containers: - - name: dns-frontend - image: k8s.gcr.io/example-dns-frontend:v1 - command: - - python - - client.py - - http://dns-backend.development.svc.cluster.local:8000 - imagePullPolicy: Always - restartPolicy: Never diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/backend/Dockerfile b/vendor/k8s.io/kubernetes/examples/cluster-dns/images/backend/Dockerfile deleted file mode 100644 index c2a4e7cf6..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/backend/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -# 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. - -FROM python:2.7-slim - -COPY . /dns-backend -WORKDIR /dns-backend - -CMD ["python", "server.py"] diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/backend/Makefile b/vendor/k8s.io/kubernetes/examples/cluster-dns/images/backend/Makefile deleted file mode 100644 index bac8c8987..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/backend/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# 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. - -TAG = v1 -PREFIX = staging-k8s.gcr.io -IMAGE = example-dns-backend - -all: push - -image: - docker build --pull -t $(PREFIX)/$(IMAGE):$(TAG) . - -push: image - gcloud docker -- push $(PREFIX)/$(IMAGE) - -clean: diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/backend/server.py b/vendor/k8s.io/kubernetes/examples/cluster-dns/images/backend/server.py deleted file mode 100644 index 5dcfb93b9..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/backend/server.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer - -PORT_NUMBER = 8000 - -# This class will handles any incoming request. -class HTTPHandler(BaseHTTPRequestHandler): - # Handler for the GET requests - def do_GET(self): - self.send_response(200) - self.send_header('Content-type','text/html') - self.end_headers() - self.wfile.write("Hello World!") - -try: - # Create a web server and define the handler to manage the incoming request. - server = HTTPServer(('', PORT_NUMBER), HTTPHandler) - print 'Started httpserver on port ' , PORT_NUMBER - server.serve_forever() -except KeyboardInterrupt: - print '^C received, shutting down the web server' - server.socket.close() diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/frontend/Dockerfile b/vendor/k8s.io/kubernetes/examples/cluster-dns/images/frontend/Dockerfile deleted file mode 100644 index 56da6eb71..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/frontend/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -# 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. - -FROM python:2.7-slim - -RUN pip install requests - -COPY . /dns-frontend -WORKDIR /dns-frontend - -CMD ["python", "client.py"] diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/frontend/Makefile b/vendor/k8s.io/kubernetes/examples/cluster-dns/images/frontend/Makefile deleted file mode 100644 index 4c17fb59f..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/frontend/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# 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. - -TAG = v1 -PREFIX = staging-k8s.gcr.io -IMAGE = example-dns-frontend - -all: push - -image: - docker build --pull -t $(PREFIX)/$(IMAGE):$(TAG) . - -push: image - gcloud docker -- push $(PREFIX)/$(IMAGE) - -clean: diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/frontend/client.py b/vendor/k8s.io/kubernetes/examples/cluster-dns/images/frontend/client.py deleted file mode 100644 index 1a56df504..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/images/frontend/client.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python - -# 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. - -import argparse -import requests -import socket - -from urlparse import urlparse - - -def CheckServiceAddress(address): - hostname = urlparse(address).hostname - service_address = socket.gethostbyname(hostname) - print service_address - - -def GetServerResponse(address): - print 'Send request to:', address - response = requests.get(address) - print response - print response.content - - -def Main(): - parser = argparse.ArgumentParser() - parser.add_argument('address') - args = parser.parse_args() - CheckServiceAddress(args.address) - GetServerResponse(args.address) - - -if __name__ == "__main__": - Main() diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/namespace-dev.yaml b/vendor/k8s.io/kubernetes/examples/cluster-dns/namespace-dev.yaml deleted file mode 100644 index 149c2f665..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/namespace-dev.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: "development" - labels: - name: "development" diff --git a/vendor/k8s.io/kubernetes/examples/cluster-dns/namespace-prod.yaml b/vendor/k8s.io/kubernetes/examples/cluster-dns/namespace-prod.yaml deleted file mode 100644 index 04bb44c1d..000000000 --- a/vendor/k8s.io/kubernetes/examples/cluster-dns/namespace-prod.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: "production" - labels: - name: "production" diff --git a/vendor/k8s.io/kubernetes/examples/cockroachdb/OWNERS b/vendor/k8s.io/kubernetes/examples/cockroachdb/OWNERS deleted file mode 100644 index 9b4cd15cb..000000000 --- a/vendor/k8s.io/kubernetes/examples/cockroachdb/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -reviewers: - - a-robinson -approvers: - - a-robinson diff --git a/vendor/k8s.io/kubernetes/examples/cockroachdb/README.md b/vendor/k8s.io/kubernetes/examples/cockroachdb/README.md deleted file mode 100644 index 23ffcbdce..000000000 --- a/vendor/k8s.io/kubernetes/examples/cockroachdb/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/cockroachdb/README.md](https://github.com/kubernetes/examples/blob/master/staging/cockroachdb/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/cockroachdb/cockroachdb-statefulset.yaml b/vendor/k8s.io/kubernetes/examples/cockroachdb/cockroachdb-statefulset.yaml deleted file mode 100644 index 0afdef391..000000000 --- a/vendor/k8s.io/kubernetes/examples/cockroachdb/cockroachdb-statefulset.yaml +++ /dev/null @@ -1,171 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - # This service is meant to be used by clients of the database. It exposes a ClusterIP that will - # automatically load balance connections to the different database pods. - name: cockroachdb-public - labels: - app: cockroachdb -spec: - ports: - # The main port, served by gRPC, serves Postgres-flavor SQL, internode - # traffic and the cli. - - port: 26257 - targetPort: 26257 - name: grpc - # The secondary port serves the UI as well as health and debug endpoints. - - port: 8080 - targetPort: 8080 - name: http - selector: - app: cockroachdb ---- -apiVersion: v1 -kind: Service -metadata: - # This service only exists to create DNS entries for each pod in the stateful - # set such that they can resolve each other's IP addresses. It does not - # create a load-balanced ClusterIP and should not be used directly by clients - # in most circumstances. - name: cockroachdb - labels: - app: cockroachdb - annotations: - # This is needed to make the peer-finder work properly and to help avoid - # edge cases where instance 0 comes up after losing its data and needs to - # decide whether it should create a new cluster or try to join an existing - # one. If it creates a new cluster when it should have joined an existing - # one, we'd end up with two separate clusters listening at the same service - # endpoint, which would be very bad. - service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" - # Enable automatic monitoring of all instances when Prometheus is running in the cluster. - prometheus.io/scrape: "true" - prometheus.io/path: "_status/vars" - prometheus.io/port: "8080" -spec: - ports: - - port: 26257 - targetPort: 26257 - name: grpc - - port: 8080 - targetPort: 8080 - name: http - clusterIP: None - selector: - app: cockroachdb ---- -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: cockroachdb-budget - labels: - app: cockroachdb -spec: - selector: - matchLabels: - app: cockroachdb - minAvailable: 67% ---- -apiVersion: apps/v1beta1 -kind: StatefulSet -metadata: - name: cockroachdb -spec: - serviceName: "cockroachdb" - replicas: 3 - template: - metadata: - labels: - app: cockroachdb - spec: - # Init containers are run only once in the lifetime of a pod, before - # it's started up for the first time. It has to exit successfully - # before the pod's main containers are allowed to start. - # This particular init container does a DNS lookup for other pods in - # the set to help determine whether or not a cluster already exists. - # If any other pods exist, it creates a file in the cockroach-data - # directory to pass that information along to the primary container that - # has to decide what command-line flags to use when starting CockroachDB. - # This only matters when a pod's persistent volume is empty - if it has - # data from a previous execution, that data will always be used. - # - # If your Kubernetes cluster uses a custom DNS domain, you will have - # to add an additional arg to this pod: "-domain=" - initContainers: - - name: bootstrap - image: cockroachdb/cockroach-k8s-init:0.2 - imagePullPolicy: IfNotPresent - args: - - "-on-start=/on-start.sh" - - "-service=cockroachdb" - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - volumeMounts: - - name: datadir - mountPath: "/cockroach/cockroach-data" - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - cockroachdb - topologyKey: kubernetes.io/hostname - containers: - - name: cockroachdb - image: cockroachdb/cockroach:v1.1.0 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 26257 - name: grpc - - containerPort: 8080 - name: http - volumeMounts: - - name: datadir - mountPath: /cockroach/cockroach-data - command: - - "/bin/bash" - - "-ecx" - - | - # The use of qualified `hostname -f` is crucial: - # Other nodes aren't able to look up the unqualified hostname. - CRARGS=("start" "--logtostderr" "--insecure" "--host" "$(hostname -f)" "--http-host" "0.0.0.0") - # We only want to initialize a new cluster (by omitting the join flag) - # if we're sure that we're the first node (i.e. index 0) and that - # there aren't any other nodes running as part of the cluster that - # this is supposed to be a part of (which indicates that a cluster - # already exists and we should make sure not to create a new one). - # It's fine to run without --join on a restart if there aren't any - # other nodes. - if [ ! "$(hostname)" == "cockroachdb-0" ] || \ - [ -e "/cockroach/cockroach-data/cluster_exists_marker" ] - then - # We don't join cockroachdb in order to avoid a node attempting - # to join itself, which currently doesn't work - # (https://github.com/cockroachdb/cockroach/issues/9625). - CRARGS+=("--join" "cockroachdb-public") - fi - exec /cockroach/cockroach ${CRARGS[*]} - # No pre-stop hook is required, a SIGTERM plus some time is all that's - # needed for graceful shutdown of a node. - terminationGracePeriodSeconds: 60 - volumes: - - name: datadir - persistentVolumeClaim: - claimName: datadir - volumeClaimTemplates: - - metadata: - name: datadir - spec: - accessModes: - - "ReadWriteOnce" - resources: - requests: - storage: 1Gi diff --git a/vendor/k8s.io/kubernetes/examples/cockroachdb/demo.sh b/vendor/k8s.io/kubernetes/examples/cockroachdb/demo.sh deleted file mode 100755 index f96f54277..000000000 --- a/vendor/k8s.io/kubernetes/examples/cockroachdb/demo.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -# 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. - -set -euo pipefail - -function sql() { - # TODO(knz): Why does the more idiomatic read from stdin not produce any - # output? - kubectl exec "cockroachdb-${1}" -- /cockroach/cockroach sql \ - --host "cockroachdb-${1}.cockroachdb" \ - --insecure \ - -e "$(cat /dev/stdin)" -} - -function kill() { - ! kubectl exec -t "cockroachdb-${1}" -- /bin/bash -c "while true; do kill 1; done" &> /dev/null -} - -# Create database on second node (idempotently for convenience). -cat <= 1 CPU - shared.yaml | >= 1 CPU - exclusive-1.yaml | >= 2 CPU - exclusive-2.yaml | >= 3 CPU - exclusive-3.yaml | >= 4 CPU - exclusive-4.yaml | >= 5 CPU -``` - -### Example - -Run a pod with a single container in the shared pool, and another pod -with a single container in an exclusive cpuset with one CPU. - -``` -$ kubectl create -f examples/cpu-manager/shared.yaml -$ kubectl create -f examples/cpu-manager/exclusive-1.yaml -``` - -To list IP addresses of the pods running in the local cluster, do: - -``` -$ watch ./examples/cpu-manager/pod-ips -exclusive-1 http://172.17.0.4 -shared http://172.17.0.3 -``` - -#### Sample cpuset-visualizer output - -![Sample cpuset-visualizer output](https://user-images.githubusercontent.com/379372/28648573-974693ce-7223-11e7-84ed-17cce11910ff.png) diff --git a/vendor/k8s.io/kubernetes/examples/cpu-manager/be.yaml b/vendor/k8s.io/kubernetes/examples/cpu-manager/be.yaml deleted file mode 100644 index 05d34a122..000000000 --- a/vendor/k8s.io/kubernetes/examples/cpu-manager/be.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: be -spec: - containers: - - image: quay.io/connordoyle/cpuset-visualizer - name: be diff --git a/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-1.yaml b/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-1.yaml deleted file mode 100644 index 98dd57c81..000000000 --- a/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-1.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: exclusive-1 -spec: - containers: - - image: quay.io/connordoyle/cpuset-visualizer - name: exclusive-1 - resources: - requests: - cpu: 1 - memory: "256M" - limits: - cpu: 1 - memory: "256M" diff --git a/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-2.yaml b/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-2.yaml deleted file mode 100644 index 6003be0dd..000000000 --- a/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-2.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: exclusive-2 -spec: - containers: - - image: quay.io/connordoyle/cpuset-visualizer - name: exclusive-2 - resources: - requests: - cpu: 2 - memory: "256M" - limits: - cpu: 2 - memory: "256M" diff --git a/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-3.yaml b/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-3.yaml deleted file mode 100644 index 25234fffe..000000000 --- a/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-3.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: exclusive-3 -spec: - containers: - - image: quay.io/connordoyle/cpuset-visualizer - name: exclusive-3 - resources: - requests: - cpu: 3 - memory: "256M" - limits: - cpu: 3 - memory: "256M" diff --git a/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-4.yaml b/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-4.yaml deleted file mode 100644 index da342acd2..000000000 --- a/vendor/k8s.io/kubernetes/examples/cpu-manager/exclusive-4.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: exclusive-4 -spec: - containers: - - image: quay.io/connordoyle/cpuset-visualizer - name: exclusive-4 - resources: - requests: - cpu: 4 - memory: "256M" - limits: - cpu: 4 - memory: "256M" diff --git a/vendor/k8s.io/kubernetes/examples/cpu-manager/pod-ips b/vendor/k8s.io/kubernetes/examples/cpu-manager/pod-ips deleted file mode 100755 index 66ee35509..000000000 --- a/vendor/k8s.io/kubernetes/examples/cpu-manager/pod-ips +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -# 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. - -# Requires `jq`. See https://stedolan.github.io/jq/download - -set -o nounset -o pipefail -o errexit - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -KUBECTL="$DIR/../../cluster/kubectl.sh" -export KUBECONFIG="${KUBECONFIG:-/var/run/kubernetes/admin.kubeconfig}" - -$KUBECTL get pods -o json | \ - jq -r '.items[] | "\(.metadata.name) http://\(.status.podIP)"' diff --git a/vendor/k8s.io/kubernetes/examples/cpu-manager/shared.yaml b/vendor/k8s.io/kubernetes/examples/cpu-manager/shared.yaml deleted file mode 100644 index 0f09d0c99..000000000 --- a/vendor/k8s.io/kubernetes/examples/cpu-manager/shared.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: shared -spec: - containers: - - image: quay.io/connordoyle/cpuset-visualizer - name: shared - resources: - requests: - cpu: 100m diff --git a/vendor/k8s.io/kubernetes/examples/doc.go b/vendor/k8s.io/kubernetes/examples/doc.go deleted file mode 100644 index 85b3b214b..000000000 --- a/vendor/k8s.io/kubernetes/examples/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -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. -*/ - -// Examples contains sample applications for trying out the concepts in Kubernetes. -package examples // import "k8s.io/kubernetes/examples" diff --git a/vendor/k8s.io/kubernetes/examples/elasticsearch/README.md b/vendor/k8s.io/kubernetes/examples/elasticsearch/README.md deleted file mode 100644 index 75ecfe69a..000000000 --- a/vendor/k8s.io/kubernetes/examples/elasticsearch/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/elasticsearch/README.md](https://github.com/kubernetes/examples/blob/master/staging/elasticsearch/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/examples_test.go b/vendor/k8s.io/kubernetes/examples/examples_test.go deleted file mode 100644 index beac4cc91..000000000 --- a/vendor/k8s.io/kubernetes/examples/examples_test.go +++ /dev/null @@ -1,466 +0,0 @@ -/* -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 examples_test - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "regexp" - "strings" - "testing" - - "github.com/golang/glog" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/validation/field" - "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apis/apps" - appsvalidation "k8s.io/kubernetes/pkg/apis/apps/validation" - "k8s.io/kubernetes/pkg/apis/batch" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/validation" - "k8s.io/kubernetes/pkg/apis/extensions" - expvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" - "k8s.io/kubernetes/pkg/capabilities" - "k8s.io/kubernetes/pkg/registry/batch/job" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulerapilatest "k8s.io/kubernetes/pkg/scheduler/api/latest" - schedulerapivalidation "k8s.io/kubernetes/pkg/scheduler/api/validation" -) - -func validateObject(obj runtime.Object) (errors field.ErrorList) { - switch t := obj.(type) { - case *api.ReplicationController: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = validation.ValidateReplicationController(t) - case *api.ReplicationControllerList: - for i := range t.Items { - errors = append(errors, validateObject(&t.Items[i])...) - } - case *api.Service: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = validation.ValidateService(t) - case *api.ServiceList: - for i := range t.Items { - errors = append(errors, validateObject(&t.Items[i])...) - } - case *api.Pod: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = validation.ValidatePod(t) - case *api.PodList: - for i := range t.Items { - errors = append(errors, validateObject(&t.Items[i])...) - } - case *api.PersistentVolume: - errors = validation.ValidatePersistentVolume(t) - case *api.PersistentVolumeClaim: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = validation.ValidatePersistentVolumeClaim(t) - case *api.PodTemplate: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = validation.ValidatePodTemplate(t) - case *api.Endpoints: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = validation.ValidateEndpoints(t) - case *api.Namespace: - errors = validation.ValidateNamespace(t) - case *api.Secret: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = validation.ValidateSecret(t) - case *api.LimitRange: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = validation.ValidateLimitRange(t) - case *api.ResourceQuota: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = validation.ValidateResourceQuota(t) - case *extensions.Deployment: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = expvalidation.ValidateDeployment(t) - case *batch.Job: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - // Job needs generateSelector called before validation, and job.Validate does this. - // See: https://github.com/kubernetes/kubernetes/issues/20951#issuecomment-187787040 - t.ObjectMeta.UID = types.UID("fakeuid") - errors = job.Strategy.Validate(nil, t) - case *extensions.Ingress: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = expvalidation.ValidateIngress(t) - case *extensions.DaemonSet: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = expvalidation.ValidateDaemonSet(t) - case *apps.StatefulSet: - if t.Namespace == "" { - t.Namespace = metav1.NamespaceDefault - } - errors = appsvalidation.ValidateStatefulSet(t) - default: - errors = field.ErrorList{} - errors = append(errors, field.InternalError(field.NewPath(""), fmt.Errorf("no validation defined for %#v", obj))) - } - return errors -} - -func validateschedulerpolicy(obj runtime.Object) error { - switch t := obj.(type) { - case *schedulerapi.Policy: - return schedulerapivalidation.ValidatePolicy(*t) - default: - return fmt.Errorf("obj type is not schedulerapi.Policy") - } -} - -func walkJSONFiles(inDir string, fn func(name, path string, data []byte)) error { - return filepath.Walk(inDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - if info.IsDir() && path != inDir { - return filepath.SkipDir - } - - file := filepath.Base(path) - if ext := filepath.Ext(file); ext == ".json" || ext == ".yaml" { - glog.Infof("Testing %s", path) - data, err := ioutil.ReadFile(path) - if err != nil { - return err - } - name := strings.TrimSuffix(file, ext) - - if ext == ".yaml" { - out, err := yaml.ToJSON(data) - if err != nil { - return fmt.Errorf("%s: %v", path, err) - } - data = out - } - - fn(name, path, data) - } - return nil - }) -} - -func TestExampleObjectSchemas(t *testing.T) { - cases := map[string]map[string]runtime.Object{ - "../examples/guestbook": { - "frontend-deployment": &extensions.Deployment{}, - "redis-slave-deployment": &extensions.Deployment{}, - "redis-master-deployment": &extensions.Deployment{}, - "frontend-service": &api.Service{}, - "redis-master-service": &api.Service{}, - "redis-slave-service": &api.Service{}, - }, - "../examples/guestbook/legacy": { - "frontend-controller": &api.ReplicationController{}, - "redis-slave-controller": &api.ReplicationController{}, - "redis-master-controller": &api.ReplicationController{}, - }, - "../examples/guestbook-go": { - "guestbook-controller": &api.ReplicationController{}, - "redis-slave-controller": &api.ReplicationController{}, - "redis-master-controller": &api.ReplicationController{}, - "guestbook-service": &api.Service{}, - "redis-master-service": &api.Service{}, - "redis-slave-service": &api.Service{}, - }, - "../examples/volumes/iscsi": { - "chap-secret": &api.Secret{}, - "iscsi": &api.Pod{}, - "iscsi-chap": &api.Pod{}, - }, - "../examples/volumes/glusterfs": { - "glusterfs-pod": &api.Pod{}, - "glusterfs-endpoints": &api.Endpoints{}, - "glusterfs-service": &api.Service{}, - }, - "../examples": { - "scheduler-policy-config": &schedulerapi.Policy{}, - "scheduler-policy-config-with-extender": &schedulerapi.Policy{}, - }, - "../examples/volumes/rbd/secret": { - "ceph-secret": &api.Secret{}, - }, - "../examples/volumes/rbd": { - "rbd": &api.Pod{}, - "rbd-with-secret": &api.Pod{}, - }, - "../examples/cluster-dns": { - "dns-backend-rc": &api.ReplicationController{}, - "dns-backend-service": &api.Service{}, - "dns-frontend-pod": &api.Pod{}, - "namespace-dev": &api.Namespace{}, - "namespace-prod": &api.Namespace{}, - }, - "../examples/explorer": { - "pod": &api.Pod{}, - }, - "../examples/storage/hazelcast": { - "hazelcast-deployment": &extensions.Deployment{}, - "hazelcast-service": &api.Service{}, - }, - "../examples/meteor": { - "meteor-controller": &api.ReplicationController{}, - "meteor-service": &api.Service{}, - "mongo-pod": &api.Pod{}, - "mongo-service": &api.Service{}, - }, - "../examples/mysql-wordpress-pd": { - "gce-volumes": &api.PersistentVolume{}, - "local-volumes": &api.PersistentVolume{}, - "mysql-deployment": &api.Service{}, - "wordpress-deployment": &api.Service{}, - }, - "../examples/volumes/nfs": { - "nfs-busybox-rc": &api.ReplicationController{}, - "nfs-server-rc": &api.ReplicationController{}, - "nfs-server-service": &api.Service{}, - "nfs-pv": &api.PersistentVolume{}, - "nfs-pvc": &api.PersistentVolumeClaim{}, - "nfs-web-rc": &api.ReplicationController{}, - "nfs-web-service": &api.Service{}, - }, - "../examples/openshift-origin": { - "openshift-origin-namespace": &api.Namespace{}, - "openshift-controller": &extensions.Deployment{}, - "openshift-service": &api.Service{}, - "etcd-controller": &extensions.Deployment{}, - "etcd-service": &api.Service{}, - "etcd-discovery-controller": &extensions.Deployment{}, - "etcd-discovery-service": &api.Service{}, - "secret": nil, - }, - "../examples/phabricator": { - "phabricator-controller": &api.ReplicationController{}, - "phabricator-service": &api.Service{}, - }, - "../examples/storage/redis": { - "redis-controller": &api.ReplicationController{}, - "redis-master": &api.Pod{}, - "redis-sentinel-controller": &api.ReplicationController{}, - "redis-sentinel-service": &api.Service{}, - }, - "../examples/storage/rethinkdb": { - "admin-pod": &api.Pod{}, - "admin-service": &api.Service{}, - "driver-service": &api.Service{}, - "rc": &api.ReplicationController{}, - }, - "../examples/spark": { - "namespace-spark-cluster": &api.Namespace{}, - "spark-master-controller": &api.ReplicationController{}, - "spark-master-service": &api.Service{}, - "spark-ui-proxy-controller": &api.ReplicationController{}, - "spark-ui-proxy-service": &api.Service{}, - "spark-worker-controller": &api.ReplicationController{}, - "zeppelin-controller": &api.ReplicationController{}, - "zeppelin-service": &api.Service{}, - }, - "../examples/spark/spark-gluster": { - "spark-master-service": &api.Service{}, - "spark-master-controller": &api.ReplicationController{}, - "spark-worker-controller": &api.ReplicationController{}, - "glusterfs-endpoints": &api.Endpoints{}, - }, - "../examples/storm": { - "storm-nimbus-service": &api.Service{}, - "storm-nimbus": &api.Pod{}, - "storm-worker-controller": &api.ReplicationController{}, - "zookeeper-service": &api.Service{}, - "zookeeper": &api.Pod{}, - }, - "../examples/volumes/cephfs/": { - "cephfs": &api.Pod{}, - "cephfs-with-secret": &api.Pod{}, - }, - "../examples/volumes/fibre_channel": { - "fc": &api.Pod{}, - }, - "../examples/javaweb-tomcat-sidecar": { - "javaweb": &api.Pod{}, - "javaweb-2": &api.Pod{}, - }, - "../examples/volumes/azure_file": { - "azure": &api.Pod{}, - }, - "../examples/volumes/azure_disk": { - "azure": &api.Pod{}, - }, - } - - capabilities.SetForTests(capabilities.Capabilities{ - AllowPrivileged: true, - }) - - for path, expected := range cases { - tested := 0 - err := walkJSONFiles(path, func(name, path string, data []byte) { - expectedType, found := expected[name] - if !found { - t.Errorf("%s: %s does not have a test case defined", path, name) - return - } - tested++ - if expectedType == nil { - t.Logf("skipping : %s/%s\n", path, name) - return - } - if strings.Contains(name, "scheduler-policy-config") { - if err := runtime.DecodeInto(schedulerapilatest.Codec, data, expectedType); err != nil { - t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data)) - return - } - if err := validateschedulerpolicy(expectedType); err != nil { - t.Errorf("%s did not validate correctly: %v\n%s", path, err, string(data)) - return - } - } else { - codec, err := testapi.GetCodecForObject(expectedType) - if err != nil { - t.Errorf("Could not get codec for %s: %s", expectedType, err) - } - if err := runtime.DecodeInto(codec, data, expectedType); err != nil { - t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data)) - return - } - if errors := validateObject(expectedType); len(errors) > 0 { - t.Errorf("%s did not validate correctly: %v", path, errors) - } - } - }) - if err != nil { - t.Errorf("Expected no error, Got %v", err) - } - if tested != len(expected) { - t.Errorf("Directory %v: Expected %d examples, Got %d", path, len(expected), tested) - } - } -} - -// This regex is tricky, but it works. For future me, here is the decode: -// -// Flags: (?ms) = multiline match, allow . to match \n -// 1) Look for a line that starts with ``` (a markdown code block) -// 2) (?: ... ) = non-capturing group -// 3) (P) = capture group as "name" -// 4) Look for #1 followed by either: -// 4a) "yaml" followed by any word-characters followed by a newline (e.g. ```yamlfoo\n) -// 4b) "any word-characters followed by a newline (e.g. ```json\n) -// 5) Look for either: -// 5a) #4a followed by one or more characters (non-greedy) -// 5b) #4b followed by { followed by one or more characters (non-greedy) followed by } -// 6) Look for #5 followed by a newline followed by ``` (end of the code block) -// -// This could probably be simplified, but is already too delicate. Before any -// real changes, we should have a testscase that just tests this regex. -var sampleRegexp = regexp.MustCompile("(?ms)^```(?:(?Pyaml)\\w*\\n(?P.+?)|\\w*\\n(?P\\{.+?\\}))\\n^```") -var subsetRegexp = regexp.MustCompile("(?ms)\\.{3}") - -func TestReadme(t *testing.T) { - paths := []struct { - file string - expectedType []runtime.Object - }{ - {"../README.md", []runtime.Object{&api.Pod{}}}, - {"../examples/volumes/iscsi/README.md", []runtime.Object{&api.Secret{}}}, - } - - for _, path := range paths { - data, err := ioutil.ReadFile(path.file) - if err != nil { - t.Errorf("Unable to read file %s: %v", path, err) - continue - } - - matches := sampleRegexp.FindAllStringSubmatch(string(data), -1) - if matches == nil { - continue - } - ix := 0 - for _, match := range matches { - var content, subtype string - for i, name := range sampleRegexp.SubexpNames() { - if name == "type" { - subtype = match[i] - } - if name == "content" && match[i] != "" { - content = match[i] - } - } - if subtype == "yaml" && subsetRegexp.FindString(content) != "" { - t.Logf("skipping (%s): \n%s", subtype, content) - continue - } - - var expectedType runtime.Object - if len(path.expectedType) == 1 { - expectedType = path.expectedType[0] - } else { - expectedType = path.expectedType[ix] - ix++ - } - json, err := yaml.ToJSON([]byte(content)) - if err != nil { - t.Errorf("%s could not be converted to JSON: %v\n%s", path, err, string(content)) - } - if err := runtime.DecodeInto(testapi.Default.Codec(), json, expectedType); err != nil { - t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(content)) - continue - } - if errors := validateObject(expectedType); len(errors) > 0 { - t.Errorf("%s did not validate correctly: %v", path, errors) - } - _, err = runtime.Encode(testapi.Default.Codec(), expectedType) - if err != nil { - t.Errorf("Could not encode object: %v", err) - continue - } - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/explorer/BUILD b/vendor/k8s.io/kubernetes/examples/explorer/BUILD deleted file mode 100644 index 680d702ec..000000000 --- a/vendor/k8s.io/kubernetes/examples/explorer/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "explorer", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["explorer.go"], - importpath = "k8s.io/kubernetes/examples/explorer", - deps = ["//vendor/github.com/davecgh/go-spew/spew:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/examples/explorer/Dockerfile b/vendor/k8s.io/kubernetes/examples/explorer/Dockerfile deleted file mode 100644 index 71c686c56..000000000 --- a/vendor/k8s.io/kubernetes/examples/explorer/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -# 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. - -FROM scratch -ADD explorer explorer -ADD README.md README.md -EXPOSE 8080 -ENTRYPOINT ["/explorer"] diff --git a/vendor/k8s.io/kubernetes/examples/explorer/Makefile b/vendor/k8s.io/kubernetes/examples/explorer/Makefile deleted file mode 100644 index f550a15a1..000000000 --- a/vendor/k8s.io/kubernetes/examples/explorer/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# 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. - -all: push - -# Keep this one version ahead, so no one accidentally blows away the latest published version. -TAG = 1.1 - -explorer: explorer.go - CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./explorer.go - -container: explorer - docker build --pull -t staging-k8s.gcr.io/explorer:$(TAG) . - -push: container - gcloud docker -- push staging-k8s.gcr.io/explorer:$(TAG) - -clean: - rm -f explorer diff --git a/vendor/k8s.io/kubernetes/examples/explorer/README.md b/vendor/k8s.io/kubernetes/examples/explorer/README.md deleted file mode 100644 index 5451e2b30..000000000 --- a/vendor/k8s.io/kubernetes/examples/explorer/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/explorer/README.md](https://github.com/kubernetes/examples/blob/master/staging/explorer/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/explorer/explorer.go b/vendor/k8s.io/kubernetes/examples/explorer/explorer.go deleted file mode 100644 index cdba95f54..000000000 --- a/vendor/k8s.io/kubernetes/examples/explorer/explorer.go +++ /dev/null @@ -1,122 +0,0 @@ -/* -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. -*/ - -// A tiny web server for viewing the environment kubernetes creates for your -// containers. It exposes the filesystem and environment variables via http -// server. -package main - -import ( - "flag" - "fmt" - "log" - "net" - "net/http" - "os" - - "github.com/davecgh/go-spew/spew" -) - -var ( - port = flag.Int("port", 8080, "Port number to serve at.") -) - -func main() { - flag.Parse() - hostname, err := os.Hostname() - if err != nil { - log.Fatalf("Error getting hostname: %v", err) - } - - links := []struct { - link, desc string - }{ - {"/fs/", "Complete file system as seen by this container."}, - {"/vars/", "Environment variables as seen by this container."}, - {"/hostname/", "Hostname as seen by this container."}, - {"/dns?q=google.com", "Explore DNS records seen by this container."}, - {"/quit", "Cause this container to exit."}, - } - - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, " Kubernetes environment explorer

    ") - for _, v := range links { - fmt.Fprintf(w, `%v: %v
    `, v.link, v.link, v.desc) - } - }) - - http.Handle("/fs/", http.StripPrefix("/fs/", http.FileServer(http.Dir("/")))) - http.HandleFunc("/vars/", func(w http.ResponseWriter, r *http.Request) { - for _, v := range os.Environ() { - fmt.Fprintf(w, "%v\n", v) - } - }) - http.HandleFunc("/hostname/", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, hostname) - }) - http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) { - os.Exit(0) - }) - http.HandleFunc("/dns", dns) - - go log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", *port), nil)) - - select {} -} - -func dns(w http.ResponseWriter, r *http.Request) { - q := r.URL.Query().Get("q") - // Note that the below is NOT safe from input attacks, but that's OK - // because this is just for debugging. - fmt.Fprintf(w, ` -
    - - -
    -

    `, q)
    -	{
    -		res, err := net.LookupNS(q)
    -		spew.Fprintf(w, "LookupNS(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
    -	}
    -	{
    -		res, err := net.LookupTXT(q)
    -		spew.Fprintf(w, "LookupTXT(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
    -	}
    -	{
    -		cname, res, err := net.LookupSRV("", "", q)
    -		spew.Fprintf(w, `LookupSRV("", "", %v):
    -cname: %v
    -Result: %#v
    -Error: %v
    -
    -`, q, cname, res, err)
    -	}
    -	{
    -		res, err := net.LookupHost(q)
    -		spew.Fprintf(w, "LookupHost(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
    -	}
    -	{
    -		res, err := net.LookupIP(q)
    -		spew.Fprintf(w, "LookupIP(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
    -	}
    -	{
    -		res, err := net.LookupMX(q)
    -		spew.Fprintf(w, "LookupMX(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
    -	}
    -	fmt.Fprintf(w, `
    - -`) -} diff --git a/vendor/k8s.io/kubernetes/examples/explorer/pod.yaml b/vendor/k8s.io/kubernetes/examples/explorer/pod.yaml deleted file mode 100644 index 0437a2492..000000000 --- a/vendor/k8s.io/kubernetes/examples/explorer/pod.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: explorer -spec: - containers: - - name: explorer - image: k8s.gcr.io/explorer:1.0 - args: ["-port=8080"] - ports: - - containerPort: 8080 - protocol: TCP - volumeMounts: - - mountPath: "/mount/test-volume" - name: test-volume - volumes: - - name: test-volume - emptyDir: {} diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/.gitignore b/vendor/k8s.io/kubernetes/examples/guestbook-go/.gitignore deleted file mode 100644 index a45a95c2f..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/.gitignore +++ /dev/null @@ -1 +0,0 @@ -guestbook_bin diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/BUILD b/vendor/k8s.io/kubernetes/examples/guestbook-go/BUILD deleted file mode 100644 index 66bc4f93a..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "guestbook-go", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["main.go"], - importpath = "k8s.io/kubernetes/examples/guestbook-go", - deps = [ - "//vendor/github.com/codegangsta/negroni:go_default_library", - "//vendor/github.com/gorilla/mux:go_default_library", - "//vendor/github.com/xyproto/simpleredis:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/Dockerfile b/vendor/k8s.io/kubernetes/examples/guestbook-go/Dockerfile deleted file mode 100644 index a58ebae38..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -# 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. - -FROM busybox:ubuntu-14.04 - -ADD ./guestbook_bin /app/guestbook -ADD ./public/index.html /app/public/index.html -ADD ./public/script.js /app/public/script.js -ADD ./public/style.css /app/public/style.css - -WORKDIR /app -CMD ["./guestbook"] -EXPOSE 3000 diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/Makefile b/vendor/k8s.io/kubernetes/examples/guestbook-go/Makefile deleted file mode 100644 index ce17d07e8..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# 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. - -# Build the guestbook-go example - -# Usage: -# [VERSION=v3] [REGISTRY="staging-k8s.gcr.io"] make build -VERSION?=v3 -REGISTRY?=staging-k8s.gcr.io - -release: clean build push clean - -# builds a docker image that builds the app and packages it into a minimal docker image -build: - @cp ../../bazel-bin/examples/guestbook-go/guestbook-go guestbook_bin - docker build --pull --rm --force-rm -t ${REGISTRY}/guestbook-builder . - docker run --rm ${REGISTRY}/guestbook-builder | docker build --pull -t "${REGISTRY}/guestbook:${VERSION}" - - -# push the image to an registry -push: - gcloud docker -- push ${REGISTRY}/guestbook:${VERSION} - -# remove previous images and containers -clean: - rm -f guestbook_bin - docker rm -f ${REGISTRY}/guestbook-builder 2> /dev/null || true - docker rmi -f ${REGISTRY}/guestbook-builder || true - docker rmi -f "${REGISTRY}/guestbook:${VERSION}" || true - -.PHONY: release clean build push diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/README.md b/vendor/k8s.io/kubernetes/examples/guestbook-go/README.md deleted file mode 100644 index 512503931..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/guestbook-go/README.md](https://github.com/kubernetes/examples/blob/master/guestbook-go/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/guestbook-controller.json b/vendor/k8s.io/kubernetes/examples/guestbook-go/guestbook-controller.json deleted file mode 100644 index 0e3553c86..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/guestbook-controller.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "kind":"ReplicationController", - "apiVersion":"v1", - "metadata":{ - "name":"guestbook", - "labels":{ - "app":"guestbook" - } - }, - "spec":{ - "replicas":3, - "selector":{ - "app":"guestbook" - }, - "template":{ - "metadata":{ - "labels":{ - "app":"guestbook" - } - }, - "spec":{ - "containers":[ - { - "name":"guestbook", - "image":"k8s.gcr.io/guestbook:v3", - "ports":[ - { - "name":"http-server", - "containerPort":3000 - } - ] - } - ] - } - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/guestbook-page.png b/vendor/k8s.io/kubernetes/examples/guestbook-go/guestbook-page.png deleted file mode 100644 index 776835fd2..000000000 Binary files a/vendor/k8s.io/kubernetes/examples/guestbook-go/guestbook-page.png and /dev/null differ diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/guestbook-service.json b/vendor/k8s.io/kubernetes/examples/guestbook-go/guestbook-service.json deleted file mode 100644 index cc7640e4c..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/guestbook-service.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "kind":"Service", - "apiVersion":"v1", - "metadata":{ - "name":"guestbook", - "labels":{ - "app":"guestbook" - } - }, - "spec":{ - "ports": [ - { - "port":3000, - "targetPort":"http-server" - } - ], - "selector":{ - "app":"guestbook" - }, - "type": "LoadBalancer" - } -} diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/main.go b/vendor/k8s.io/kubernetes/examples/guestbook-go/main.go deleted file mode 100644 index c6e8cf187..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/main.go +++ /dev/null @@ -1,91 +0,0 @@ -/* -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 main - -import ( - "encoding/json" - "net/http" - "os" - "strings" - - "github.com/codegangsta/negroni" - "github.com/gorilla/mux" - "github.com/xyproto/simpleredis" -) - -var ( - masterPool *simpleredis.ConnectionPool - slavePool *simpleredis.ConnectionPool -) - -func ListRangeHandler(rw http.ResponseWriter, req *http.Request) { - key := mux.Vars(req)["key"] - list := simpleredis.NewList(slavePool, key) - members := HandleError(list.GetAll()).([]string) - membersJSON := HandleError(json.MarshalIndent(members, "", " ")).([]byte) - rw.Write(membersJSON) -} - -func ListPushHandler(rw http.ResponseWriter, req *http.Request) { - key := mux.Vars(req)["key"] - value := mux.Vars(req)["value"] - list := simpleredis.NewList(masterPool, key) - HandleError(nil, list.Add(value)) - ListRangeHandler(rw, req) -} - -func InfoHandler(rw http.ResponseWriter, req *http.Request) { - info := HandleError(masterPool.Get(0).Do("INFO")).([]byte) - rw.Write(info) -} - -func EnvHandler(rw http.ResponseWriter, req *http.Request) { - environment := make(map[string]string) - for _, item := range os.Environ() { - splits := strings.Split(item, "=") - key := splits[0] - val := strings.Join(splits[1:], "=") - environment[key] = val - } - - envJSON := HandleError(json.MarshalIndent(environment, "", " ")).([]byte) - rw.Write(envJSON) -} - -func HandleError(result interface{}, err error) (r interface{}) { - if err != nil { - panic(err) - } - return result -} - -func main() { - masterPool = simpleredis.NewConnectionPoolHost("redis-master:6379") - defer masterPool.Close() - slavePool = simpleredis.NewConnectionPoolHost("redis-slave:6379") - defer slavePool.Close() - - r := mux.NewRouter() - r.Path("/lrange/{key}").Methods("GET").HandlerFunc(ListRangeHandler) - r.Path("/rpush/{key}/{value}").Methods("GET").HandlerFunc(ListPushHandler) - r.Path("/info").Methods("GET").HandlerFunc(InfoHandler) - r.Path("/env").Methods("GET").HandlerFunc(EnvHandler) - - n := negroni.Classic() - n.UseHandler(r) - n.Run(":3000") -} diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/public/index.html b/vendor/k8s.io/kubernetes/examples/guestbook-go/public/index.html deleted file mode 100644 index f525f4b76..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/public/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - Guestbook - - - - -
    -

    Waiting for database connection...

    -
    - -
    -
    - - Submit -
    -
    - -
    -

    -

    /env - /info

    -
    - - - - diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/public/script.js b/vendor/k8s.io/kubernetes/examples/guestbook-go/public/script.js deleted file mode 100644 index a0a545b05..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/public/script.js +++ /dev/null @@ -1,46 +0,0 @@ -$(document).ready(function() { - var headerTitleElement = $("#header h1"); - var entriesElement = $("#guestbook-entries"); - var formElement = $("#guestbook-form"); - var submitElement = $("#guestbook-submit"); - var entryContentElement = $("#guestbook-entry-content"); - var hostAddressElement = $("#guestbook-host-address"); - - var appendGuestbookEntries = function(data) { - entriesElement.empty(); - $.each(data, function(key, val) { - entriesElement.append("

    " + val + "

    "); - }); - } - - var handleSubmission = function(e) { - e.preventDefault(); - var entryValue = entryContentElement.val() - if (entryValue.length > 0) { - entriesElement.append("

    ...

    "); - $.getJSON("rpush/guestbook/" + entryValue, appendGuestbookEntries); - } - return false; - } - - // colors = purple, blue, red, green, yellow - var colors = ["#549", "#18d", "#d31", "#2a4", "#db1"]; - var randomColor = colors[Math.floor(5 * Math.random())]; - (function setElementsColor(color) { - headerTitleElement.css("color", color); - entryContentElement.css("box-shadow", "inset 0 0 0 2px " + color); - submitElement.css("background-color", color); - })(randomColor); - - submitElement.click(handleSubmission); - formElement.submit(handleSubmission); - hostAddressElement.append(document.URL); - - // Poll every second. - (function fetchGuestbook() { - $.getJSON("lrange/guestbook").done(appendGuestbookEntries).always( - function() { - setTimeout(fetchGuestbook, 1000); - }); - })(); -}); diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/public/style.css b/vendor/k8s.io/kubernetes/examples/guestbook-go/public/style.css deleted file mode 100644 index fd1c393fb..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/public/style.css +++ /dev/null @@ -1,61 +0,0 @@ -body, input { - color: #123; - font-family: "Gill Sans", sans-serif; -} - -div { - overflow: hidden; - padding: 1em 0; - position: relative; - text-align: center; -} - -h1, h2, p, input, a { - font-weight: 300; - margin: 0; -} - -h1 { - color: #BDB76B; - font-size: 3.5em; -} - -h2 { - color: #999; -} - -form { - margin: 0 auto; - max-width: 50em; - text-align: center; -} - -input { - border: 0; - border-radius: 1000px; - box-shadow: inset 0 0 0 2px #BDB76B; - display: inline; - font-size: 1.5em; - margin-bottom: 1em; - outline: none; - padding: .5em 5%; - width: 55%; -} - -form a { - background: #BDB76B; - border: 0; - border-radius: 1000px; - color: #FFF; - font-size: 1.25em; - font-weight: 400; - padding: .75em 2em; - text-decoration: none; - text-transform: uppercase; - white-space: normal; -} - -p { - font-size: 1.5em; - line-height: 1.5; -} diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-master-controller.json b/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-master-controller.json deleted file mode 100644 index 4ffe53a72..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-master-controller.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "kind":"ReplicationController", - "apiVersion":"v1", - "metadata":{ - "name":"redis-master", - "labels":{ - "app":"redis", - "role":"master" - } - }, - "spec":{ - "replicas":1, - "selector":{ - "app":"redis", - "role":"master" - }, - "template":{ - "metadata":{ - "labels":{ - "app":"redis", - "role":"master" - } - }, - "spec":{ - "containers":[ - { - "name":"redis-master", - "image":"redis:2.8.23", - "ports":[ - { - "name":"redis-server", - "containerPort":6379 - } - ] - } - ] - } - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-master-service.json b/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-master-service.json deleted file mode 100644 index 3a7426ead..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-master-service.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "kind":"Service", - "apiVersion":"v1", - "metadata":{ - "name":"redis-master", - "labels":{ - "app":"redis", - "role":"master" - } - }, - "spec":{ - "ports": [ - { - "port":6379, - "targetPort":"redis-server" - } - ], - "selector":{ - "app":"redis", - "role":"master" - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-slave-controller.json b/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-slave-controller.json deleted file mode 100644 index eec652afa..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-slave-controller.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "kind":"ReplicationController", - "apiVersion":"v1", - "metadata":{ - "name":"redis-slave", - "labels":{ - "app":"redis", - "role":"slave" - } - }, - "spec":{ - "replicas":2, - "selector":{ - "app":"redis", - "role":"slave" - }, - "template":{ - "metadata":{ - "labels":{ - "app":"redis", - "role":"slave" - } - }, - "spec":{ - "containers":[ - { - "name":"redis-slave", - "image":"kubernetes/redis-slave:v2", - "ports":[ - { - "name":"redis-server", - "containerPort":6379 - } - ] - } - ] - } - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-slave-service.json b/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-slave-service.json deleted file mode 100644 index 7e8f49a6a..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook-go/redis-slave-service.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "kind":"Service", - "apiVersion":"v1", - "metadata":{ - "name":"redis-slave", - "labels":{ - "app":"redis", - "role":"slave" - } - }, - "spec":{ - "ports": [ - { - "port":6379, - "targetPort":"redis-server" - } - ], - "selector":{ - "app":"redis", - "role":"slave" - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/README.md b/vendor/k8s.io/kubernetes/examples/guestbook/README.md deleted file mode 100644 index baee2f834..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/guestbook/README.md](https://github.com/kubernetes/examples/blob/master/guestbook/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/all-in-one/frontend.yaml b/vendor/k8s.io/kubernetes/examples/guestbook/all-in-one/frontend.yaml deleted file mode 100644 index edcaa5c5d..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/all-in-one/frontend.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: frontend - labels: - app: guestbook - tier: frontend -spec: - # if your cluster supports it, uncomment the following to automatically create - # an external load-balanced IP for the frontend service. - # type: LoadBalancer - ports: - - port: 80 - selector: - app: guestbook - tier: frontend ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: frontend -spec: - replicas: 3 - template: - metadata: - labels: - app: guestbook - tier: frontend - spec: - containers: - - name: php-redis - image: gcr.io/google-samples/gb-frontend:v4 - resources: - requests: - cpu: 100m - memory: 100Mi - env: - - name: GET_HOSTS_FROM - value: dns - # If your cluster config does not include a dns service, then to - # instead access environment variables to find service host - # info, comment out the 'value: dns' line above, and uncomment the - # line below: - # value: env - ports: - - containerPort: 80 diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/all-in-one/guestbook-all-in-one.yaml b/vendor/k8s.io/kubernetes/examples/guestbook/all-in-one/guestbook-all-in-one.yaml deleted file mode 100644 index a3415d6a9..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/all-in-one/guestbook-all-in-one.yaml +++ /dev/null @@ -1,133 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: redis-master - labels: - app: redis - tier: backend - role: master -spec: - ports: - - port: 6379 - targetPort: 6379 - selector: - app: redis - tier: backend - role: master ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: redis-master -spec: - replicas: 1 - template: - metadata: - labels: - app: redis - role: master - tier: backend - spec: - containers: - - name: master - image: k8s.gcr.io/redis:e2e # or just image: redis - resources: - requests: - cpu: 100m - memory: 100Mi - ports: - - containerPort: 6379 ---- -apiVersion: v1 -kind: Service -metadata: - name: redis-slave - labels: - app: redis - tier: backend - role: slave -spec: - ports: - - port: 6379 - selector: - app: redis - tier: backend - role: slave ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: redis-slave -spec: - replicas: 2 - template: - metadata: - labels: - app: redis - role: slave - tier: backend - spec: - containers: - - name: slave - image: gcr.io/google_samples/gb-redisslave:v1 - resources: - requests: - cpu: 100m - memory: 100Mi - env: - - name: GET_HOSTS_FROM - value: dns - # If your cluster config does not include a dns service, then to - # instead access an environment variable to find the master - # service's host, comment out the 'value: dns' line above, and - # uncomment the line below: - # value: env - ports: - - containerPort: 6379 ---- -apiVersion: v1 -kind: Service -metadata: - name: frontend - labels: - app: guestbook - tier: frontend -spec: - # if your cluster supports it, uncomment the following to automatically create - # an external load-balanced IP for the frontend service. - # type: LoadBalancer - ports: - - port: 80 - selector: - app: guestbook - tier: frontend ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: frontend -spec: - replicas: 3 - template: - metadata: - labels: - app: guestbook - tier: frontend - spec: - containers: - - name: php-redis - image: gcr.io/google-samples/gb-frontend:v4 - resources: - requests: - cpu: 100m - memory: 100Mi - env: - - name: GET_HOSTS_FROM - value: dns - # If your cluster config does not include a dns service, then to - # instead access environment variables to find service host - # info, comment out the 'value: dns' line above, and uncomment the - # line below: - # value: env - ports: - - containerPort: 80 diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/all-in-one/redis-slave.yaml b/vendor/k8s.io/kubernetes/examples/guestbook/all-in-one/redis-slave.yaml deleted file mode 100644 index c076b084c..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/all-in-one/redis-slave.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: redis-slave - labels: - app: redis - role: slave - tier: backend -spec: - ports: - - port: 6379 - selector: - app: redis - role: slave - tier: backend ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: redis-slave -spec: - replicas: 2 - template: - metadata: - labels: - app: redis - role: slave - tier: backend - spec: - containers: - - name: slave - image: gcr.io/google_samples/gb-redisslave:v1 - resources: - requests: - cpu: 100m - memory: 100Mi - env: - - name: GET_HOSTS_FROM - value: dns - # If your cluster config does not include a dns service, then to - # instead access an environment variable to find the master - # service's host, comment out the 'value: dns' line above, and - # uncomment the line below: - # value: env - ports: - - containerPort: 6379 diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/frontend-deployment.yaml b/vendor/k8s.io/kubernetes/examples/guestbook/frontend-deployment.yaml deleted file mode 100644 index 1888836b3..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/frontend-deployment.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: frontend -spec: - replicas: 3 - template: - metadata: - labels: - app: guestbook - tier: frontend - spec: - containers: - - name: php-redis - image: gcr.io/google-samples/gb-frontend:v4 - resources: - requests: - cpu: 100m - memory: 100Mi - env: - - name: GET_HOSTS_FROM - value: dns - # If your cluster config does not include a dns service, then to - # instead access environment variables to find service host - # info, comment out the 'value: dns' line above, and uncomment the - # line below: - # value: env - ports: - - containerPort: 80 diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/frontend-service.yaml b/vendor/k8s.io/kubernetes/examples/guestbook/frontend-service.yaml deleted file mode 100644 index ee50fd847..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/frontend-service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: frontend - labels: - app: guestbook - tier: frontend -spec: - # if your cluster supports it, uncomment the following to automatically create - # an external load-balanced IP for the frontend service. - # type: LoadBalancer - ports: - - port: 80 - selector: - app: guestbook - tier: frontend diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/Dockerfile b/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/Dockerfile deleted file mode 100644 index e6f5a2f84..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -# 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. - -FROM php:5-apache - -RUN apt-get update -RUN apt-get install -y php-pear -RUN pear channel-discover pear.nrk.io -RUN pear install nrk/Predis - -# If the container's stdio is connected to systemd-journald, -# /proc/self/fd/{1,2} are Unix sockets and apache will not be able to open() -# them. Use "cat" to write directly to the already opened fds without opening -# them again. -RUN sed -i 's#ErrorLog /proc/self/fd/2#ErrorLog "|$/bin/cat 1>\&2"#' /etc/apache2/apache2.conf -RUN sed -i 's#CustomLog /proc/self/fd/1 combined#CustomLog "|/bin/cat" combined#' /etc/apache2/apache2.conf - -ADD guestbook.php /var/www/html/guestbook.php -ADD controllers.js /var/www/html/controllers.js -ADD index.html /var/www/html/index.html diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/controllers.js b/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/controllers.js deleted file mode 100644 index 1e4b55042..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/controllers.js +++ /dev/null @@ -1,29 +0,0 @@ -var redisApp = angular.module('redis', ['ui.bootstrap']); - -/** - * Constructor - */ -function RedisController() {} - -RedisController.prototype.onRedis = function() { - this.scope_.messages.push(this.scope_.msg); - this.scope_.msg = ""; - var value = this.scope_.messages.join(); - this.http_.get("guestbook.php?cmd=set&key=messages&value=" + value) - .success(angular.bind(this, function(data) { - this.scope_.redisResponse = "Updated."; - })); -}; - -redisApp.controller('RedisCtrl', function ($scope, $http, $location) { - $scope.controller = new RedisController(); - $scope.controller.scope_ = $scope; - $scope.controller.location_ = $location; - $scope.controller.http_ = $http; - - $scope.controller.http_.get("guestbook.php?cmd=get&key=messages") - .success(function(data) { - console.log(data); - $scope.messages = data.data.split(","); - }); -}); diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/guestbook.php b/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/guestbook.php deleted file mode 100644 index ee0670ee6..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/guestbook.php +++ /dev/null @@ -1,41 +0,0 @@ - 'tcp', - 'host' => $host, - 'port' => 6379, - ]); - - $client->set($_GET['key'], $_GET['value']); - print('{"message": "Updated"}'); - } else { - $host = 'redis-slave'; - if (getenv('GET_HOSTS_FROM') == 'env') { - $host = getenv('REDIS_SLAVE_SERVICE_HOST'); - } - $client = new Predis\Client([ - 'scheme' => 'tcp', - 'host' => $host, - 'port' => 6379, - ]); - - $value = $client->get($_GET['key']); - print('{"data": "' . $value . '"}'); - } -} else { - phpinfo(); -} ?> diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/index.html b/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/index.html deleted file mode 100644 index 4ffb4ed2a..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/php-redis/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - Guestbook - - - - - - -
    -

    Guestbook

    -
    -
    -
    - -
    -
    -
    -
    - {{msg}} -
    -
    -
    - - diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/redis-master-deployment.yaml b/vendor/k8s.io/kubernetes/examples/guestbook/redis-master-deployment.yaml deleted file mode 100644 index d457a0993..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/redis-master-deployment.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: redis-master -spec: - replicas: 1 - template: - metadata: - labels: - app: redis - role: master - tier: backend - spec: - containers: - - name: master - image: k8s.gcr.io/redis:e2e # or just image: redis - resources: - requests: - cpu: 100m - memory: 100Mi - ports: - - containerPort: 6379 diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/redis-master-service.yaml b/vendor/k8s.io/kubernetes/examples/guestbook/redis-master-service.yaml deleted file mode 100644 index a484014f1..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/redis-master-service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: redis-master - labels: - app: redis - role: master - tier: backend -spec: - ports: - - port: 6379 - targetPort: 6379 - selector: - app: redis - role: master - tier: backend diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave-deployment.yaml b/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave-deployment.yaml deleted file mode 100644 index 2bea4a513..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave-deployment.yaml +++ /dev/null @@ -1,30 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: redis-slave -spec: - replicas: 2 - template: - metadata: - labels: - app: redis - role: slave - tier: backend - spec: - containers: - - name: slave - image: gcr.io/google_samples/gb-redisslave:v1 - resources: - requests: - cpu: 100m - memory: 100Mi - env: - - name: GET_HOSTS_FROM - value: dns - # If your cluster config does not include a dns service, then to - # instead access an environment variable to find the master - # service's host, comment out the 'value: dns' line above, and - # uncomment the line below: - # value: env - ports: - - containerPort: 6379 diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave-service.yaml b/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave-service.yaml deleted file mode 100644 index 238fd63fb..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave-service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: redis-slave - labels: - app: redis - role: slave - tier: backend -spec: - ports: - - port: 6379 - selector: - app: redis - role: slave - tier: backend diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave/Dockerfile b/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave/Dockerfile deleted file mode 100644 index e90b22588..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -# 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. - -FROM redis - -ADD run.sh /run.sh - -RUN chmod a+x /run.sh - -CMD /run.sh diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave/run.sh b/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave/run.sh deleted file mode 100755 index d9037d48c..000000000 --- a/vendor/k8s.io/kubernetes/examples/guestbook/redis-slave/run.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -# 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. - -if [[ ${GET_HOSTS_FROM:-dns} == "env" ]]; then - redis-server --slaveof ${REDIS_MASTER_SERVICE_HOST} 6379 -else - redis-server --slaveof redis-master 6379 -fi diff --git a/vendor/k8s.io/kubernetes/examples/guidelines.md b/vendor/k8s.io/kubernetes/examples/guidelines.md deleted file mode 100644 index c4a99c560..000000000 --- a/vendor/k8s.io/kubernetes/examples/guidelines.md +++ /dev/null @@ -1,88 +0,0 @@ -# Example Guidelines - -## An Example Is - -An example demonstrates running an application/framework/workload on -Kubernetes in a meaningful way. It is educational and informative. - -Examples are not: - -* Full app deployments, ready to use, with no explanation. These - belong to [Helm charts](https://github.com/kubernetes/charts). -* Simple toys to show how to use a Kubernetes feature. These belong in - the [user guide](https://kubernetes.io/docs/user-guide/). -* Demos that follow a script to show a Kubernetes feature in - action. Example: killing a node to demonstrate controller - self-healing. -* A tutorial which guides the user through multiple progressively more - complex deployments to arrive at the final solution. An example - should just demonstrate how to setup the correct deployment - -## An Example Includes - -### Up front - -* Has a "this is what you'll learn" section. -* Has a Table of Contents. -* Has a section that brings up the app in the fewest number of - commands (TL;DR / quickstart), without cloning the repo (kubectl - apply -f http://...). -* Points to documentation of prerequisites. - * [Create a cluster](https://kubernetes.io/docs/getting-started-guides/) (e.g., single-node docker). - * [Setup kubectl](https://kubernetes.io/docs/user-guide/prereqs.md). - * etc. -* Should specify which release of Kubernetes is required and any other - prerequisites, such as DNS, a cloudprovider with PV provisioning, a - cloudprovider with external load balancers, etc. - * Point to general documentation about alternatives for those - mechanisms rather than present the alternatives in each example. - * Tries to balance between using using new features, and being - compatible across environments. - -### Throughout - -* Should point to documentation on first mention: - [kubectl](https://kubernetes.io/docs/user-guide/kubectl-overview.md), - [pods](https://kubernetes.io/docs/user-guide/pods.md), - [services](https://kubernetes.io/docs/user-guide/services.md), - [deployments](https://kubernetes.io/docs/user-guide/deployments.md), - [replication controllers](https://kubernetes.io/docs/user-guide/replication-controller.md), - [jobs](https://kubernetes.io/docs/user-guide/jobs.md), - [labels](https://kubernetes.io/docs/user-guide/labels.md), - [persistent volumes](https://kubernetes.io/docs/user-guide/persistent-volumes.md), - etc. -* Most examples should be cloudprovider-independent (e.g., using PVCs, not PDs). - * Other examples with cloudprovider-specific bits could be somewhere else. -* Actually show the app working -- console output, and or screenshots. - * Ascii animations and screencasts are recommended. -* Follows [config best practices](https://kubernetes.io/docs/user-guide/config-best-practices.md). -* Shouldn't duplicate the [thorough walk-through](https://kubernetes.io/docs/user-guide/#thorough-walkthrough). -* Docker images are pre-built, and source is contained in a subfolder. - * Source is the Dockerfile and any custom files needed beyond the - upstream app being packaged. - * Images are pushed to `gcr.io/google-samples`. Contact @jeffmendoza - to have an image pushed - * Images are tagged with a version (not latest) that is referenced - in the example config. -* Only use the code highlighting types - [supported by Rouge](https://github.com/jneen/rouge/wiki/list-of-supported-languages-and-lexers), - as this is what GitHub Pages uses. -* Commands to be copied use the `shell` syntax highlighting type, and - do not include any kind of prompt. -* Example output is in a separate block quote to distinguish it from - the command (which doesn't have a prompt). -* When providing an example command or config for which the user is - expected to substitute text with something specific to them, use - angle brackets: `` for the text to be substituted. -* Use `kubectl` instead of `cluster\kubectl.sh` for example cli - commands. - -### At the end - -* Should have a section suggesting what to look at next, both in terms - of "additional resources" and "what example to look at next". - - - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/guidelines.md?pixel)]() - diff --git a/vendor/k8s.io/kubernetes/examples/https-nginx/BUILD b/vendor/k8s.io/kubernetes/examples/https-nginx/BUILD deleted file mode 100644 index b82ab738c..000000000 --- a/vendor/k8s.io/kubernetes/examples/https-nginx/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "https-nginx", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["make_secret.go"], - importpath = "k8s.io/kubernetes/examples/https-nginx", - deps = [ - "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core:go_default_library", - "//pkg/apis/core/install:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/examples/https-nginx/Dockerfile b/vendor/k8s.io/kubernetes/examples/https-nginx/Dockerfile deleted file mode 100644 index f58408861..000000000 --- a/vendor/k8s.io/kubernetes/examples/https-nginx/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -# 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. - -FROM nginx - - -COPY index2.html /usr/share/nginx/html/index2.html -RUN chmod +r /usr/share/nginx/html/index2.html -COPY auto-reload-nginx.sh /home/auto-reload-nginx.sh -RUN chmod +x /home/auto-reload-nginx.sh - -# install inotify -RUN apt-get update && apt-get install -y inotify-tools diff --git a/vendor/k8s.io/kubernetes/examples/https-nginx/Makefile b/vendor/k8s.io/kubernetes/examples/https-nginx/Makefile deleted file mode 100644 index f8203dcac..000000000 --- a/vendor/k8s.io/kubernetes/examples/https-nginx/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# 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. - -all: - -TAG = 1.0 -PREFIX = bprashanth/nginxhttps -KEY = /tmp/nginx.key -CERT = /tmp/nginx.crt -SECRET = /tmp/secret.json - -keys: - # The CName used here is specific to the service specified in nginx-app.yaml. - openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout $(KEY) -out $(CERT) -subj "/CN=nginxsvc/O=nginxsvc" - -secret: - go run make_secret.go -crt $(CERT) -key $(KEY) > $(SECRET) - -container: - docker build --pull -t $(PREFIX):$(TAG) . - -push: container - docker push $(PREFIX):$(TAG) - -clean: - rm $(KEY) - rm $(CERT) diff --git a/vendor/k8s.io/kubernetes/examples/https-nginx/README.md b/vendor/k8s.io/kubernetes/examples/https-nginx/README.md deleted file mode 100644 index 6ce72378c..000000000 --- a/vendor/k8s.io/kubernetes/examples/https-nginx/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/https-nginx/README.md](https://github.com/kubernetes/examples/blob/master/staging/https-nginx/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/https-nginx/auto-reload-nginx.sh b/vendor/k8s.io/kubernetes/examples/https-nginx/auto-reload-nginx.sh deleted file mode 100755 index 78144b059..000000000 --- a/vendor/k8s.io/kubernetes/examples/https-nginx/auto-reload-nginx.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -# 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. - -nginx "$@" -oldcksum=`cksum /etc/nginx/conf.d/default.conf` - -inotifywait -e modify,move,create,delete -mr --timefmt '%d/%m/%y %H:%M' --format '%T' \ -/etc/nginx/conf.d/ | while read date time; do - - newcksum=`cksum /etc/nginx/conf.d/default.conf` - if [ "$newcksum" != "$oldcksum" ]; then - echo "At ${time} on ${date}, config file update detected." - oldcksum=$newcksum - nginx -s reload - fi - -done diff --git a/vendor/k8s.io/kubernetes/examples/https-nginx/default.conf b/vendor/k8s.io/kubernetes/examples/https-nginx/default.conf deleted file mode 100644 index d91a5ba6d..000000000 --- a/vendor/k8s.io/kubernetes/examples/https-nginx/default.conf +++ /dev/null @@ -1,17 +0,0 @@ -server { - listen 80 default_server; - listen [::]:80 default_server ipv6only=on; - - listen 443 ssl; - - root /usr/share/nginx/html; - index index.html; - - server_name localhost; - ssl_certificate /etc/nginx/ssl/nginx.crt; - ssl_certificate_key /etc/nginx/ssl/nginx.key; - - location / { - try_files $uri $uri/ =404; - } -} diff --git a/vendor/k8s.io/kubernetes/examples/https-nginx/index2.html b/vendor/k8s.io/kubernetes/examples/https-nginx/index2.html deleted file mode 100644 index 99a96085f..000000000 --- a/vendor/k8s.io/kubernetes/examples/https-nginx/index2.html +++ /dev/null @@ -1,28 +0,0 @@ - - - -Nginx reloaded! - - - -

    Nginx has been reloaded!

    -

    If you see this page, the nginx web server has been automatically reloaded, since the config file has been updated using Kubernetes.

    - - -

    For online documentation and support please refer to -kubernetes.io.

    - -

    For online documentation and support please refer to -nginx.org.
    -Commercial support is available at -nginx.com.

    - -

    Thank you for using nginx.

    - - diff --git a/vendor/k8s.io/kubernetes/examples/https-nginx/make_secret.go b/vendor/k8s.io/kubernetes/examples/https-nginx/make_secret.go deleted file mode 100644 index e85838ee7..000000000 --- a/vendor/k8s.io/kubernetes/examples/https-nginx/make_secret.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -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. -*/ - -// A small script that converts the given open ssl public/private keys to -// a secret that it writes to stdout as json. Most common use case is to -// create a secret from self signed certificates used to authenticate with -// a devserver. Usage: go run make_secret.go -crt ca.crt -key priv.key > secret.json -package main - -import ( - "flag" - "fmt" - "io/ioutil" - "log" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/api/legacyscheme" - api "k8s.io/kubernetes/pkg/apis/core" - - // This installs the legacy v1 API - _ "k8s.io/kubernetes/pkg/apis/core/install" -) - -// TODO: -// Add a -o flag that writes to the specified destination file. -// Teach the script to create crt and key if -crt and -key aren't specified. -var ( - crt = flag.String("crt", "", "path to nginx certificates.") - key = flag.String("key", "", "path to nginx private key.") -) - -func read(file string) []byte { - b, err := ioutil.ReadFile(file) - if err != nil { - log.Fatalf("Cannot read file %v, %v", file, err) - } - return b -} - -func main() { - flag.Parse() - if *crt == "" || *key == "" { - log.Fatalf("Need to specify -crt -key and -template") - } - nginxCrt := read(*crt) - nginxKey := read(*key) - secret := &api.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "nginxsecret", - }, - Data: map[string][]byte{ - "nginx.crt": nginxCrt, - "nginx.key": nginxKey, - }, - } - fmt.Printf(runtime.EncodeOrDie(legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), secret)) -} diff --git a/vendor/k8s.io/kubernetes/examples/https-nginx/nginx-app.yaml b/vendor/k8s.io/kubernetes/examples/https-nginx/nginx-app.yaml deleted file mode 100644 index a5ce0bd37..000000000 --- a/vendor/k8s.io/kubernetes/examples/https-nginx/nginx-app.yaml +++ /dev/null @@ -1,54 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: nginxsvc - labels: - app: nginx -spec: - type: NodePort - ports: - - port: 80 - protocol: TCP - name: http - - port: 443 - protocol: TCP - name: https - selector: - app: nginx ---- -apiVersion: v1 -kind: ReplicationController -metadata: - name: my-nginx -spec: - replicas: 1 - template: - metadata: - labels: - app: nginx - spec: - volumes: - - name: secret-volume - secret: - secretName: nginxsecret - - name: configmap-volume - configMap: - name: nginxconfigmap - containers: - - name: nginxhttps - image: ymqytw/nginxhttps:1.5 - command: ["/home/auto-reload-nginx.sh"] - ports: - - containerPort: 443 - - containerPort: 80 - livenessProbe: - httpGet: - path: /index.html - port: 80 - initialDelaySeconds: 30 - timeoutSeconds: 1 - volumeMounts: - - mountPath: /etc/nginx/ssl - name: secret-volume - - mountPath: /etc/nginx/conf.d - name: configmap-volume diff --git a/vendor/k8s.io/kubernetes/examples/javaee/README.md b/vendor/k8s.io/kubernetes/examples/javaee/README.md deleted file mode 100644 index 1fcd411ac..000000000 --- a/vendor/k8s.io/kubernetes/examples/javaee/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/javaee/README.md](https://github.com/kubernetes/examples/blob/master/staging/javaee/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/javaee/mysql-pod.yaml b/vendor/k8s.io/kubernetes/examples/javaee/mysql-pod.yaml deleted file mode 100644 index b8884f386..000000000 --- a/vendor/k8s.io/kubernetes/examples/javaee/mysql-pod.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: mysql-pod - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - containers: - - - name: mysql - image: mysql:latest - env: - - - name: "MYSQL_USER" - value: "mysql" - - - name: "MYSQL_PASSWORD" - value: "mysql" - - - name: "MYSQL_DATABASE" - value: "sample" - - - name: "MYSQL_ROOT_PASSWORD" - value: "supersecret" - ports: - - - containerPort: 3306 diff --git a/vendor/k8s.io/kubernetes/examples/javaee/mysql-service.yaml b/vendor/k8s.io/kubernetes/examples/javaee/mysql-service.yaml deleted file mode 100644 index 0cbb329a8..000000000 --- a/vendor/k8s.io/kubernetes/examples/javaee/mysql-service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mysql-service - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - ports: - # the port that this service should serve on - - port: 3306 - # label keys and values that must match in order to receive traffic for this service - selector: - name: mysql-pod - context: docker-k8s-lab diff --git a/vendor/k8s.io/kubernetes/examples/javaee/wildfly-rc.yaml b/vendor/k8s.io/kubernetes/examples/javaee/wildfly-rc.yaml deleted file mode 100644 index 303b63f8d..000000000 --- a/vendor/k8s.io/kubernetes/examples/javaee/wildfly-rc.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: wildfly-rc - labels: - name: wildfly - context: docker-k8s-lab -spec: - replicas: 1 - template: - metadata: - labels: - name: wildfly - spec: - containers: - - name: wildfly-rc-pod - image: arungupta/wildfly-mysql-javaee7:k8s - ports: - - containerPort: 8080 \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/README.md b/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/README.md deleted file mode 100644 index 2537a86fd..000000000 --- a/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/javaweb-tomcat-sidecar/README.md](https://github.com/kubernetes/examples/blob/master/staging/javaweb-tomcat-sidecar/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/javaweb-2.yaml b/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/javaweb-2.yaml deleted file mode 100644 index b34d5ab6e..000000000 --- a/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/javaweb-2.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: javaweb-2 -spec: - containers: - - image: resouer/sample:v2 - name: war - lifecycle: - postStart: - exec: - command: - - "cp" - - "/sample.war" - - "/app" - volumeMounts: - - mountPath: /app - name: app-volume - - image: resouer/mytomcat:7.0 - name: tomcat - command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"] - volumeMounts: - - mountPath: /root/apache-tomcat-7.0.42-v2/webapps - name: app-volume - ports: - - containerPort: 8080 - hostPort: 8001 - volumes: - - name: app-volume - emptyDir: {} - diff --git a/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/javaweb.yaml b/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/javaweb.yaml deleted file mode 100644 index d77f6a727..000000000 --- a/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/javaweb.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: javaweb -spec: - containers: - - image: resouer/sample:v1 - name: war - volumeMounts: - - mountPath: /app - name: app-volume - - image: resouer/mytomcat:7.0 - name: tomcat - command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"] - volumeMounts: - - mountPath: /root/apache-tomcat-7.0.42-v2/webapps - name: app-volume - ports: - - containerPort: 8080 - hostPort: 8001 - volumes: - - name: app-volume - emptyDir: {} - diff --git a/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/workflow.png b/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/workflow.png deleted file mode 100644 index 7be56d082..000000000 Binary files a/vendor/k8s.io/kubernetes/examples/javaweb-tomcat-sidecar/workflow.png and /dev/null differ diff --git a/vendor/k8s.io/kubernetes/examples/job/expansions/README.md b/vendor/k8s.io/kubernetes/examples/job/expansions/README.md deleted file mode 100644 index 4346ab253..000000000 --- a/vendor/k8s.io/kubernetes/examples/job/expansions/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/job/expansions/README.md](https://github.com/kubernetes/examples/blob/master/staging/job/expansions/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/job/work-queue-1/README.md b/vendor/k8s.io/kubernetes/examples/job/work-queue-1/README.md deleted file mode 100644 index 8ac3051cf..000000000 --- a/vendor/k8s.io/kubernetes/examples/job/work-queue-1/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/job/work-queue-1/README.md](https://github.com/kubernetes/examples/blob/master/staging/job/work-queue-1/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/job/work-queue-2/README.md b/vendor/k8s.io/kubernetes/examples/job/work-queue-2/README.md deleted file mode 100644 index f0e175d83..000000000 --- a/vendor/k8s.io/kubernetes/examples/job/work-queue-2/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/job/work-queue-2/README.md](https://github.com/kubernetes/examples/blob/master/staging/job/work-queue-2/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/kubectl-container/.gitignore b/vendor/k8s.io/kubernetes/examples/kubectl-container/.gitignore deleted file mode 100644 index 50a4a06fd..000000000 --- a/vendor/k8s.io/kubernetes/examples/kubectl-container/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -kubectl -.tag diff --git a/vendor/k8s.io/kubernetes/examples/kubectl-container/Dockerfile b/vendor/k8s.io/kubernetes/examples/kubectl-container/Dockerfile deleted file mode 100644 index add0569c0..000000000 --- a/vendor/k8s.io/kubernetes/examples/kubectl-container/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -# 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. - -FROM scratch -ADD kubectl kubectl -ENTRYPOINT ["/kubectl"] diff --git a/vendor/k8s.io/kubernetes/examples/kubectl-container/Makefile b/vendor/k8s.io/kubernetes/examples/kubectl-container/Makefile deleted file mode 100644 index a4094ff8b..000000000 --- a/vendor/k8s.io/kubernetes/examples/kubectl-container/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# 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. - -# Use: -# -# `make kubectl` will build kubectl. -# `make tag` will suggest a tag. -# `make container` will build a container-- you must supply a tag. -# `make push` will push the container-- you must supply a tag. - -GOARCH?=$(shell go env GOARCH) -GOOS?=$(shell go env GOOS) - -kubectl: - make -C ../../ WHAT=cmd/kubectl KUBE_STATIC_OVERRIDES="kubectl"; \ - cp ../../_output/local/bin/$(GOOS)/$(GOARCH)/kubectl . - -.tag: kubectl - ./kubectl version --client | grep -o 'GitVersion:"[^"]*"' | sed 's/[^"]*"\([^"+]*\).*/\1/' > .tag - -tag: .tag - @echo "Suggest using TAG=$(shell cat .tag)" - @echo "$$ make container TAG=$(shell cat .tag)" - @echo "or" - @echo "$$ make push TAG=$(shell cat .tag)" - -container: - $(if $(TAG),,$(error TAG is not defined. Use 'make tag' to see a suggestion)) - docker build --pull -t staging-k8s.gcr.io/kubectl:$(TAG) . - -push: container - $(if $(TAG),,$(error TAG is not defined. Use 'make tag' to see a suggestion)) - gcloud docker -- push staging-k8s.gcr.io/kubectl:$(TAG) - -clean: - rm -f kubectl - rm -f .tag diff --git a/vendor/k8s.io/kubernetes/examples/kubectl-container/README.md b/vendor/k8s.io/kubernetes/examples/kubectl-container/README.md deleted file mode 100644 index bb2c3d2eb..000000000 --- a/vendor/k8s.io/kubernetes/examples/kubectl-container/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/kubectl-container/README.md](https://github.com/kubernetes/examples/blob/master/staging/kubectl-container/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/kubectl-container/pod.json b/vendor/k8s.io/kubernetes/examples/kubectl-container/pod.json deleted file mode 100644 index 540715a6c..000000000 --- a/vendor/k8s.io/kubernetes/examples/kubectl-container/pod.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "kubectl-tester" - }, - "spec": { - "containers": [ - { - "name": "bb", - "image": "k8s.gcr.io/busybox", - "command": [ - "sh", "-c", "sleep 5; wget -O - ${KUBERNETES_RO_SERVICE_HOST}:${KUBERNETES_RO_SERVICE_PORT}/api/v1/pods/; sleep 10000" - ], - "ports": [ - { - "containerPort": 8080 - } - ], - "env": [ - { - "name": "KUBERNETES_RO_SERVICE_HOST", - "value": "127.0.0.1" - }, - { - "name": "KUBERNETES_RO_SERVICE_PORT", - "value": "8001" - } - ], - "volumeMounts": [ - { - "name": "test-volume", - "mountPath": "/mount/test-volume" - } - ] - }, - { - "name": "kubectl", - "image": "k8s.gcr.io/kubectl:v0.18.0-120-gaeb4ac55ad12b1-dirty", - "imagePullPolicy": "Always", - "args": [ - "proxy", "-p", "8001" - ] - } - ], - "volumes": [ - { - "name": "test-volume", - "emptyDir": {} - } - ] - } -} diff --git a/vendor/k8s.io/kubernetes/examples/meteor/README.md b/vendor/k8s.io/kubernetes/examples/meteor/README.md deleted file mode 100644 index 81f4d9fd4..000000000 --- a/vendor/k8s.io/kubernetes/examples/meteor/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/meteor/README.md](https://github.com/kubernetes/examples/blob/master/staging/meteor/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/meteor/dockerbase/Dockerfile b/vendor/k8s.io/kubernetes/examples/meteor/dockerbase/Dockerfile deleted file mode 100644 index 708e2cb43..000000000 --- a/vendor/k8s.io/kubernetes/examples/meteor/dockerbase/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -# 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. - -FROM node:0.10 - -ONBUILD WORKDIR /appsrc -ONBUILD COPY . /appsrc - -ONBUILD RUN curl https://install.meteor.com/ | sh && \ - meteor build ../app --directory --architecture os.linux.x86_64 && \ - rm -rf /appsrc -# TODO rm meteor so it doesn't take space in the image? - -ONBUILD WORKDIR /app/bundle - -ONBUILD RUN (cd programs/server && npm install) -EXPOSE 8080 -CMD [] -ENV PORT 8080 -ENTRYPOINT MONGO_URL=mongodb://$MONGO_SERVICE_HOST:$MONGO_SERVICE_PORT /usr/local/bin/node main.js diff --git a/vendor/k8s.io/kubernetes/examples/meteor/dockerbase/README.md b/vendor/k8s.io/kubernetes/examples/meteor/dockerbase/README.md deleted file mode 100644 index 2a9026948..000000000 --- a/vendor/k8s.io/kubernetes/examples/meteor/dockerbase/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/meteor/dockerbase/README.md](https://github.com/kubernetes/examples/blob/master/staging/meteor/dockerbase/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/meteor/meteor-controller.json b/vendor/k8s.io/kubernetes/examples/meteor/meteor-controller.json deleted file mode 100644 index fa85afdcb..000000000 --- a/vendor/k8s.io/kubernetes/examples/meteor/meteor-controller.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "kind": "ReplicationController", - "apiVersion": "v1", - "metadata": { - "name": "meteor-controller", - "labels": { - "name": "meteor" - } - }, - "spec": { - "replicas": 2, - "template": { - "metadata": { - "labels": { - "name": "meteor" - } - }, - "spec": { - "containers": [ - { - "name": "meteor", - "image": "chees/meteor-gke-example:latest", - "ports": [ - { - "name": "http-server", - "containerPort": 8080 - } - ] - } - ] - } - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/meteor/meteor-service.json b/vendor/k8s.io/kubernetes/examples/meteor/meteor-service.json deleted file mode 100644 index 2e494c0a2..000000000 --- a/vendor/k8s.io/kubernetes/examples/meteor/meteor-service.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "meteor" - }, - "spec": { - "ports": [ - { - "port": 80, - "targetPort": "http-server" - } - ], - "selector": { - "name": "meteor" - }, - "sessionAffinity": "ClientIP", - "sessionAffinityConfig": { - "clientIP": { - "timeoutSeconds": 90 - } - }, - "type": "LoadBalancer" - } -} diff --git a/vendor/k8s.io/kubernetes/examples/meteor/mongo-pod.json b/vendor/k8s.io/kubernetes/examples/meteor/mongo-pod.json deleted file mode 100644 index a5b80ac5d..000000000 --- a/vendor/k8s.io/kubernetes/examples/meteor/mongo-pod.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "mongo", - "labels": { - "name": "mongo", - "role": "mongo" - } - }, - "spec": { - "volumes": [ - { - "name": "mongo-disk", - "gcePersistentDisk": { - "pdName": "mongo-disk", - "fsType": "ext4" - } - } - ], - "containers": [ - { - "name": "mongo", - "image": "mongo:latest", - "ports": [ - { - "name": "mongo", - "containerPort": 27017 - } - ], - "volumeMounts": [ - { - "name": "mongo-disk", - "mountPath": "/data/db" - } - ] - } - ] - } -} diff --git a/vendor/k8s.io/kubernetes/examples/meteor/mongo-service.json b/vendor/k8s.io/kubernetes/examples/meteor/mongo-service.json deleted file mode 100644 index bec687e99..000000000 --- a/vendor/k8s.io/kubernetes/examples/meteor/mongo-service.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "mongo", - "labels": { - "name": "mongo" - } - }, - "spec": { - "ports": [ - { - "port": 27017, - "targetPort": "mongo" - } - ], - "selector": { - "name": "mongo", - "role": "mongo" - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/mysql-cinder-pd/README.md b/vendor/k8s.io/kubernetes/examples/mysql-cinder-pd/README.md deleted file mode 100644 index ac84d00fe..000000000 --- a/vendor/k8s.io/kubernetes/examples/mysql-cinder-pd/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/mysql-cinder-pd/README.md](https://github.com/kubernetes/examples/blob/master/staging/mysql-cinder-pd/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/mysql-cinder-pd/mysql-service.yaml b/vendor/k8s.io/kubernetes/examples/mysql-cinder-pd/mysql-service.yaml deleted file mode 100644 index 6e2c019ac..000000000 --- a/vendor/k8s.io/kubernetes/examples/mysql-cinder-pd/mysql-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - name: mysql - name: mysql -spec: - ports: - # the port that this service should serve on - - port: 3306 - # label keys and values that must match in order to receive traffic for this service - selector: - name: mysql \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/mysql-cinder-pd/mysql.yaml b/vendor/k8s.io/kubernetes/examples/mysql-cinder-pd/mysql.yaml deleted file mode 100644 index e224d0afe..000000000 --- a/vendor/k8s.io/kubernetes/examples/mysql-cinder-pd/mysql.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: mysql - labels: - name: mysql -spec: - containers: - - resources: - limits : - cpu: 0.5 - image: mysql - name: mysql - args: - - "--ignore-db-dir" - - "lost+found" - env: - - name: MYSQL_ROOT_PASSWORD - # change this - value: yourpassword - ports: - - containerPort: 3306 - name: mysql - volumeMounts: - # name must match the volume name below - - name: mysql-persistent-storage - # mount path within the container - mountPath: /var/lib/mysql - volumes: - - name: mysql-persistent-storage - cinder: - volumeID: bd82f7e2-wece-4c01-a505-4acf60b07f4a - fsType: ext4 diff --git a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/OWNERS b/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/OWNERS deleted file mode 100644 index d349c8eeb..000000000 --- a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/OWNERS +++ /dev/null @@ -1,20 +0,0 @@ -approvers: -- jeffmendoza -reviewers: -- thockin -- lavalamp -- brendandburns -- caesarxuchao -- mikedanese -- davidopp -- pmorie -- dchen1107 -- janetkuo -- roberthbailey -- eparis -- mwielgus -- jlowdermilk -- david-mcmahon -- jeffvance -- jeffmendoza -- RichieEscarez diff --git a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/README.md b/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/README.md deleted file mode 100644 index 48601ec81..000000000 --- a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/mysql-wordpress-pd/README.md](https://github.com/kubernetes/examples/blob/master/mysql-wordpress-pd/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/WordPress.png b/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/WordPress.png deleted file mode 100644 index cabcd09a6..000000000 Binary files a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/WordPress.png and /dev/null differ diff --git a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/gce-volumes.yaml b/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/gce-volumes.yaml deleted file mode 100644 index 17aeb0596..000000000 --- a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/gce-volumes.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: wordpress-pv-1 -spec: - capacity: - storage: 20Gi - accessModes: - - ReadWriteOnce - gcePersistentDisk: - pdName: wordpress-1 - fsType: ext4 ---- -apiVersion: v1 -kind: PersistentVolume -metadata: - name: wordpress-pv-2 -spec: - capacity: - storage: 20Gi - accessModes: - - ReadWriteOnce - gcePersistentDisk: - pdName: wordpress-2 - fsType: ext4 diff --git a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/local-volumes.yaml b/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/local-volumes.yaml deleted file mode 100644 index 896411333..000000000 --- a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/local-volumes.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: local-pv-1 - labels: - type: local -spec: - capacity: - storage: 20Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /tmp/data/pv-1 ---- -apiVersion: v1 -kind: PersistentVolume -metadata: - name: local-pv-2 - labels: - type: local -spec: - capacity: - storage: 20Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /tmp/data/pv-2 diff --git a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/mysql-deployment.yaml b/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/mysql-deployment.yaml deleted file mode 100644 index 2dafc08f0..000000000 --- a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/mysql-deployment.yaml +++ /dev/null @@ -1,63 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: wordpress-mysql - labels: - app: wordpress -spec: - ports: - - port: 3306 - selector: - app: wordpress - tier: mysql - clusterIP: None ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: mysql-pv-claim - labels: - app: wordpress -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 20Gi ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: wordpress-mysql - labels: - app: wordpress -spec: - strategy: - type: Recreate - template: - metadata: - labels: - app: wordpress - tier: mysql - spec: - containers: - - image: mysql:5.6 - name: mysql - env: - # $ kubectl create secret generic mysql-pass --from-file=password.txt - # make sure password.txt does not have a trailing newline - - name: MYSQL_ROOT_PASSWORD - valueFrom: - secretKeyRef: - name: mysql-pass - key: password.txt - ports: - - containerPort: 3306 - name: mysql - volumeMounts: - - name: mysql-persistent-storage - mountPath: /var/lib/mysql - volumes: - - name: mysql-persistent-storage - persistentVolumeClaim: - claimName: mysql-pv-claim diff --git a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/wordpress-deployment.yaml b/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/wordpress-deployment.yaml deleted file mode 100644 index a631361f2..000000000 --- a/vendor/k8s.io/kubernetes/examples/mysql-wordpress-pd/wordpress-deployment.yaml +++ /dev/null @@ -1,63 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: wordpress - labels: - app: wordpress -spec: - ports: - - port: 80 - selector: - app: wordpress - tier: frontend - type: LoadBalancer ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: wp-pv-claim - labels: - app: wordpress -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 20Gi ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: wordpress - labels: - app: wordpress -spec: - strategy: - type: Recreate - template: - metadata: - labels: - app: wordpress - tier: frontend - spec: - containers: - - image: wordpress:4.8.0-apache - name: wordpress - env: - - name: WORDPRESS_DB_HOST - value: wordpress-mysql - - name: WORDPRESS_DB_PASSWORD - valueFrom: - secretKeyRef: - name: mysql-pass - key: password.txt - ports: - - containerPort: 80 - name: wordpress - volumeMounts: - - name: wordpress-persistent-storage - mountPath: /var/www/html - volumes: - - name: wordpress-persistent-storage - persistentVolumeClaim: - claimName: wp-pv-claim diff --git a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/.gitignore b/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/.gitignore deleted file mode 100644 index 2ad9294d5..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.local diff --git a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/README.md b/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/README.md deleted file mode 100644 index c86a194d0..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/README.md +++ /dev/null @@ -1,146 +0,0 @@ -## New Relic Infrastructure Server Monitoring Agent Example - -This example shows how to run a New Relic Infrastructure server monitoring agent as a pod in a DaemonSet on an existing Kubernetes cluster. - -This example will create a DaemonSet which places the New Relic Infrastructure monitoring agent on every node in the cluster. It's also fairly trivial to exclude specific Kubernetes nodes from the DaemonSet to just monitor specific servers. (The prior nrsysmond has been deprecated.) - -### Step 0: Prerequisites - -This process will create privileged containers which have full access to the host system for logging. Beware of the security implications of this. - -DaemonSets must be enabled on your cluster. Instructions for enabling DaemonSet can be found [here](../../docs/api.md#enabling-the-extensions-group). - -### Step 1: Configure New Relic Infrastructure Agent - -The New Relic Infrastructure agent is configured via environment variables. We will configure these environment variables in a sourced bash script, encode the environment file data, and store it in a secret which will be loaded at container runtime. (Reread this sentence a few times, it's *HOW* the entire container works.) - -The [New Relic Linux Infrastructure Server configuration page](https://docs.newrelic.com/docs/servers/new-relic-servers-linux/installation-configuration/configuring-servers-linux) lists all the other settings for the Infrastructure process. - -To create an environment variable for a setting, prepend NRIA_ to its name and capitalize all of the env variable. For example, - -```console -log_file=/var/log/nr-infra.log -``` - -translates to - -```console -NRIA_LOG_FILE=/var/log/nr-infra.log -``` - -Edit examples/newrelic-infrastructure/nrconfig.env and configure relevant environment variables for your NewRelic Infrastructure agent. There are a few defaults defined, but the only required variable is the New Relic license key. - -Now, let's vendor the config into a secret. - -```console -$ cd examples/newrelic-infrastructure/ -$ ./config-to-secret.sh -``` - - - -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: newrelic-config -type: Opaque -data: - config: {{config_data}} -``` - -[Download example](newrelic-config-template.yaml?raw=true) - - -The script will encode the config file and write it to `newrelic-config.yaml`. - -Finally, submit the config to the cluster: - -```console -$ kubectl create -f examples/newrelic-infrastructure/newrelic-config.yaml -``` - -### Step 2: Create the DaemonSet definition. - -The DaemonSet definition instructs Kubernetes to place a newrelic Infrastructure agent on each Kubernetes node. - - - -```yaml -apiVersion: extensions/v1beta1 -kind: DaemonSet -metadata: - name: newrelic-infra-agent - labels: - tier: monitoring - app: newrelic-infra-agent - version: v1 -spec: - template: - metadata: - labels: - name: newrelic - spec: - # Filter to specific nodes: - # nodeSelector: - # app: newrelic - hostPID: true - hostIPC: true - hostNetwork: true - containers: - - resources: - requests: - cpu: 0.15 - securityContext: - privileged: true - image: newrelic/infrastructure - name: newrelic - command: [ "bash", "-c", "source /etc/kube-nr-infra/config && /usr/bin/newrelic-infra" ] - volumeMounts: - - name: newrelic-config - mountPath: /etc/kube-nr-infra - readOnly: true - - name: dev - mountPath: /dev - - name: run - mountPath: /var/run/docker.sock - - name: log - mountPath: /var/log - - name: host-root - mountPath: /host - readOnly: true - volumes: - - name: newrelic-config - secret: - secretName: newrelic-config - - name: dev - hostPath: - path: /dev - - name: run - hostPath: - path: /var/run/docker.sock - - name: log - hostPath: - path: /var/log - - name: host-root - hostPath: - path: / -``` - -[Download example](newrelic-infra-daemonset.yaml?raw=true) - - -The daemonset instructs Kubernetes to spawn pods on each node, mapping /dev/, /run/, and /var/log to the container. It also maps the entire kube node / to /host/ in the container with a read-only mount. It also maps the secrets we set up earlier to /etc/kube-newrelic/config, and sources them in the startup script, configuring the agent properly. - -#### DaemonSet customization - -- There are more environment variables for fine tuning the infrastructure agent's operation (or a yaml file that you'd have to construct). See [Infrastructure Agent Environment Variables][(https://docs.newrelic.com/docs/infrastructure/new-relic-infrastructure/configuration/configure-infrastructure-agent) for the full list. - - -### Known issues - -It's a bit cludgy to define the environment variables like we do here in these config files. There is [another issue](https://github.com/kubernetes/kubernetes/issues/4710) to discuss adding mapping secrets to environment variables in Kubernetes. (Personally I don't like that method and prefer to use the config secrets.) - - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/newrelic/README.md?pixel)]() - diff --git a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/config-to-secret.sh b/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/config-to-secret.sh deleted file mode 100755 index 520c71990..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/config-to-secret.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# 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. - -# Encodes the environment variables into a Kubernetes secret. - -BASE64_ENC=$(cat nrconfig.env | base64 | tr -d '\n') -sed -e "s#{{config_data}}#${BASE64_ENC}#g" ./newrelic-config-template.yaml > newrelic-config.yaml diff --git a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/newrelic-config-template.yaml b/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/newrelic-config-template.yaml deleted file mode 100644 index 361a30792..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/newrelic-config-template.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: newrelic-config -type: Opaque -data: - config: {{config_data}} diff --git a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/newrelic-infra-daemonset.yaml b/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/newrelic-infra-daemonset.yaml deleted file mode 100644 index 395ab9722..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/newrelic-infra-daemonset.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: DaemonSet -metadata: - name: newrelic-infra-agent - labels: - tier: monitoring - app: newrelic-infra-agent - version: v1 -spec: - template: - metadata: - labels: - name: newrelic - spec: - # Filter to specific nodes: - # nodeSelector: - # app: newrelic - hostPID: true - hostIPC: true - hostNetwork: true - containers: - - resources: - requests: - cpu: 0.15 - securityContext: - privileged: true - image: newrelic/infrastructure - name: newrelic - command: [ "bash", "-c", "source /etc/kube-nr-infra/config && /usr/bin/newrelic-infra" ] - volumeMounts: - - name: newrelic-config - mountPath: /etc/kube-nr-infra - readOnly: true - - name: dev - mountPath: /dev - - name: run - mountPath: /var/run/docker.sock - - name: log - mountPath: /var/log - - name: host-root - mountPath: /host - readOnly: true - volumes: - - name: newrelic-config - secret: - secretName: newrelic-config - - name: dev - hostPath: - path: /dev - - name: run - hostPath: - path: /var/run/docker.sock - - name: log - hostPath: - path: /var/log - - name: host-root - hostPath: - path: / diff --git a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/nrconfig.env b/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/nrconfig.env deleted file mode 100644 index ced09727c..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic-infrastructure/nrconfig.env +++ /dev/null @@ -1,9 +0,0 @@ -#--REQUIRED-- -# Put your license key in this variable -export NRIA_LICENSE_KEY=REPLACE_LICENSE_KEY_HERE -# -#--OPTIONAL-- -# Set to 1 for debug output in the log -export NRIA_VERBOSE=0 -# Can log to any file, but will not create directories -export NRIA_LOG_FILE=/var/log/nr-infra.log diff --git a/vendor/k8s.io/kubernetes/examples/newrelic/README.md b/vendor/k8s.io/kubernetes/examples/newrelic/README.md deleted file mode 100644 index e5c429c76..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/newrelic/README.md](https://github.com/kubernetes/examples/blob/master/staging/newrelic/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/newrelic/config-to-secret.sh b/vendor/k8s.io/kubernetes/examples/newrelic/config-to-secret.sh deleted file mode 100755 index 520c71990..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic/config-to-secret.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# 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. - -# Encodes the environment variables into a Kubernetes secret. - -BASE64_ENC=$(cat nrconfig.env | base64 | tr -d '\n') -sed -e "s#{{config_data}}#${BASE64_ENC}#g" ./newrelic-config-template.yaml > newrelic-config.yaml diff --git a/vendor/k8s.io/kubernetes/examples/newrelic/newrelic-config-template.yaml b/vendor/k8s.io/kubernetes/examples/newrelic/newrelic-config-template.yaml deleted file mode 100644 index 361a30792..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic/newrelic-config-template.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: newrelic-config -type: Opaque -data: - config: {{config_data}} diff --git a/vendor/k8s.io/kubernetes/examples/newrelic/newrelic-config.yaml b/vendor/k8s.io/kubernetes/examples/newrelic/newrelic-config.yaml deleted file mode 100644 index d2b551aa6..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic/newrelic-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# This file should be overwritten by ./config-to-secret.sh -# This file is in place to satisfy the kubernetes documentation tests. - -# apiVersion: v1 -# kind: Secret -# metadata: -# name: newrelic-config -# type: Opaque -# data: -# config: base64 encoded diff --git a/vendor/k8s.io/kubernetes/examples/newrelic/newrelic-daemonset.yaml b/vendor/k8s.io/kubernetes/examples/newrelic/newrelic-daemonset.yaml deleted file mode 100644 index fd4697220..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic/newrelic-daemonset.yaml +++ /dev/null @@ -1,61 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: DaemonSet -metadata: - name: newrelic-agent - labels: - tier: monitoring - app: newrelic-agent - version: v1 -spec: - template: - metadata: - labels: - name: newrelic - spec: - # Filter to specific nodes: - # nodeSelector: - # app: newrelic - hostPID: true - hostIPC: true - hostNetwork: true - containers: - - resources: - requests: - cpu: 0.15 - securityContext: - privileged: true - env: - - name: NRSYSMOND_logfile - value: "/var/log/nrsysmond.log" - image: newrelic/nrsysmond - name: newrelic - command: [ "bash", "-c", "source /etc/kube-newrelic/config && /usr/sbin/nrsysmond -E -F" ] - volumeMounts: - - name: newrelic-config - mountPath: /etc/kube-newrelic - readOnly: true - - name: dev - mountPath: /dev - - name: run - mountPath: /var/run/docker.sock - - name: sys - mountPath: /sys - - name: log - mountPath: /var/log - volumes: - - name: newrelic-config - secret: - secretName: newrelic-config - - name: dev - hostPath: - path: /dev - - name: run - hostPath: - path: /var/run/docker.sock - type: Socket - - name: sys - hostPath: - path: /sys - - name: log - hostPath: - path: /var/log diff --git a/vendor/k8s.io/kubernetes/examples/newrelic/nrconfig.env b/vendor/k8s.io/kubernetes/examples/newrelic/nrconfig.env deleted file mode 100644 index ddce85294..000000000 --- a/vendor/k8s.io/kubernetes/examples/newrelic/nrconfig.env +++ /dev/null @@ -1,2 +0,0 @@ -export NRSYSMOND_loglevel=debug -export NRSYSMOND_license_key=REPLACE_LICENSE_KEY_HERE diff --git a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/README.md b/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/README.md deleted file mode 100644 index 7f84108b3..000000000 --- a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/nodesjs-mongodb/README.md](https://github.com/kubernetes/examples/blob/master/staging/nodesjs-mongodb/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/mongo-controller.yaml b/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/mongo-controller.yaml deleted file mode 100644 index e9288151d..000000000 --- a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/mongo-controller.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - labels: - name: mongo - name: mongo-controller -spec: - replicas: 1 - template: - metadata: - labels: - name: mongo - spec: - containers: - - image: mongo - name: mongo - ports: - - name: mongo - containerPort: 27017 - hostPort: 27017 - volumeMounts: - - name: mongo-persistent-storage - mountPath: /data/db - volumes: - - name: mongo-persistent-storage - gcePersistentDisk: - pdName: mongo-disk - fsType: ext4 \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/mongo-service.yaml b/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/mongo-service.yaml deleted file mode 100644 index 81785d5b8..000000000 --- a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/mongo-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - name: mongo - name: mongo -spec: - ports: - - port: 27017 - targetPort: 27017 - selector: - name: mongo \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/web-controller-demo.yaml b/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/web-controller-demo.yaml deleted file mode 100644 index 5fa8ef84e..000000000 --- a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/web-controller-demo.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - labels: - name: web - name: web-controller -spec: - replicas: 2 - selector: - name: web - template: - metadata: - labels: - name: web - spec: - containers: - - image: node:0.10.40 - command: ['/bin/sh', '-c'] - args: ['cd /home && git clone https://github.com/ijason/NodeJS-Sample-App.git demo && cd demo/EmployeeDB/ && npm install && sed -i -- ''s/localhost/mongo/g'' app.js && node app.js'] - name: web - ports: - - containerPort: 3000 - name: http-server \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/web-controller.yaml b/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/web-controller.yaml deleted file mode 100644 index 654138099..000000000 --- a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/web-controller.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - labels: - name: web - name: web-controller -spec: - replicas: 2 - selector: - name: web - template: - metadata: - labels: - name: web - spec: - containers: - - image: - name: web - ports: - - containerPort: 3000 - name: http-server \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/web-service.yaml b/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/web-service.yaml deleted file mode 100644 index 4cef05b33..000000000 --- a/vendor/k8s.io/kubernetes/examples/nodesjs-mongodb/web-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: web - labels: - name: web -spec: - type: LoadBalancer - ports: - - port: 80 - targetPort: 3000 - protocol: TCP - selector: - name: web \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/oms/README.md b/vendor/k8s.io/kubernetes/examples/oms/README.md deleted file mode 100644 index 096e03af2..000000000 --- a/vendor/k8s.io/kubernetes/examples/oms/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/oms/README.md](https://github.com/kubernetes/examples/blob/master/staging/oms/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/oms/images/connected-resources.png b/vendor/k8s.io/kubernetes/examples/oms/images/connected-resources.png deleted file mode 100644 index 32bd05791..000000000 Binary files a/vendor/k8s.io/kubernetes/examples/oms/images/connected-resources.png and /dev/null differ diff --git a/vendor/k8s.io/kubernetes/examples/oms/images/oms-container-solution.png b/vendor/k8s.io/kubernetes/examples/oms/images/oms-container-solution.png deleted file mode 100644 index 1bc90d11d..000000000 Binary files a/vendor/k8s.io/kubernetes/examples/oms/images/oms-container-solution.png and /dev/null differ diff --git a/vendor/k8s.io/kubernetes/examples/oms/images/oms-portal.png b/vendor/k8s.io/kubernetes/examples/oms/images/oms-portal.png deleted file mode 100644 index 300114e1f..000000000 Binary files a/vendor/k8s.io/kubernetes/examples/oms/images/oms-portal.png and /dev/null differ diff --git a/vendor/k8s.io/kubernetes/examples/oms/omsagent-daemonset.yaml b/vendor/k8s.io/kubernetes/examples/oms/omsagent-daemonset.yaml deleted file mode 100644 index 8ab523f06..000000000 --- a/vendor/k8s.io/kubernetes/examples/oms/omsagent-daemonset.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: DaemonSet -metadata: - name: omsagent -spec: - template: - metadata: - labels: - app: omsagent - spec: - containers: - - env: - - name: WSID - value: - - name: KEY - value: - image: microsoft/oms - name: omsagent - ports: - - containerPort: 25225 - protocol: TCP - securityContext: - privileged: true - volumeMounts: - - mountPath: /var/run/docker.sock - name: docker-sock - volumes: - - name: docker-sock - hostPath: - path: /var/run/docker.sock - type: Socket diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/.gitignore b/vendor/k8s.io/kubernetes/examples/openshift-origin/.gitignore deleted file mode 100644 index f733c4b5f..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -config/ diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/README.md b/vendor/k8s.io/kubernetes/examples/openshift-origin/README.md deleted file mode 100644 index c01effb2b..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/openshift-origin/README.md](https://github.com/kubernetes/examples/blob/master/staging/openshift-origin/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/cleanup.sh b/vendor/k8s.io/kubernetes/examples/openshift-origin/cleanup.sh deleted file mode 100755 index a2c931571..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/cleanup.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -# 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. - -# Cleans up resources from the example, assumed to be run from Kubernetes repo root -echo -echo -export OPENSHIFT_EXAMPLE=$(pwd)/examples/openshift-origin -export OPENSHIFT_CONFIG=${OPENSHIFT_EXAMPLE}/config - -echo "===> Removing the OpenShift namespace:" -kubectl delete namespace openshift-origin -echo - -echo "===> Removing local files:" -rm -rf ${OPENSHIFT_CONFIG} -rm ${OPENSHIFT_EXAMPLE}/openshift-startup.log -rm ${OPENSHIFT_EXAMPLE}/secret.json -touch ${OPENSHIFT_EXAMPLE}/secret.json -echo - -echo "===> Restoring changed YAML specifcations:" -if [ -f "${OPENSHIFT_EXAMPLE}/etcd-controller.yaml.bak" ]; then - rm ${OPENSHIFT_EXAMPLE}/etcd-controller.yaml - mv -v ${OPENSHIFT_EXAMPLE}/etcd-controller.yaml.bak ${OPENSHIFT_EXAMPLE}/etcd-controller.yaml -else - echo "No changed specifications found." -fi -echo - -echo Done. diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/create.sh b/vendor/k8s.io/kubernetes/examples/openshift-origin/create.sh deleted file mode 100755 index 717df61b7..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/create.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/bash - -# 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. - -set -e - -# Creates resources from the example, assumed to be run from Kubernetes repo root -echo -echo "===> Initializing:" -if [ ! $(which python) ] -then - echo "Python is a prerequisite for running this script. Please install Python and try running again." - exit 1 -fi - -if [ ! $(which gcloud) ] -then - echo "gcloud is a prerequisite for running this script. Please install gcloud and try running again." - exit 1 -fi - -gcloud_instances=$(gcloud compute instances list | grep "\-master") -if [ -z "$gcloud_instances" ] || [ -z "${KUBE_GCE_INSTANCE_PREFIX}" ] -then - echo "This script is only able to supply the necessary serviceaccount key if you are running on Google" - echo "Compute Engine using a cluster/kube-up.sh script with KUBE_GCE_INSTANCE_PREFIX set. If this is not" - echo "the case, be ready to supply a path to the serviceaccount public key." - if [ -z "${KUBE_GCE_INSTANCE_PREFIX}" ] - then - echo "Please provide your KUBE_GCE_INSTANCE_PREFIX now:" - read KUBE_GCE_INSTANCE_PREFIX - fi -fi - -export OPENSHIFT_EXAMPLE=$(pwd)/examples/openshift-origin -echo Set OPENSHIFT_EXAMPLE=${OPENSHIFT_EXAMPLE} -export OPENSHIFT_CONFIG=${OPENSHIFT_EXAMPLE}/config -echo Set OPENSHIFT_CONFIG=${OPENSHIFT_CONFIG} -mkdir ${OPENSHIFT_CONFIG} -echo Made dir ${OPENSHIFT_CONFIG} -echo - -echo "===> Setting up OpenShift-Origin namespace:" -kubectl create -f ${OPENSHIFT_EXAMPLE}/openshift-origin-namespace.yaml -echo - -echo "===> Setting up etcd-discovery:" -# A token etcd uses to generate unique cluster ID and member ID. Conforms to [a-z0-9]{40} -export ETCD_INITIAL_CLUSTER_TOKEN=$(python -c "import string; import random; print(''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(40)))") - -# A unique token used by the discovery service. Conforms to etcd-cluster-[a-z0-9]{5} -export ETCD_DISCOVERY_TOKEN=$(python -c "import string; import random; print(\"etcd-cluster-\" + ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(5)))") -sed -i.bak -e "s/INSERT_ETCD_INITIAL_CLUSTER_TOKEN/\"${ETCD_INITIAL_CLUSTER_TOKEN}\"/g" -e "s/INSERT_ETCD_DISCOVERY_TOKEN/\"${ETCD_DISCOVERY_TOKEN}\"/g" ${OPENSHIFT_EXAMPLE}/etcd-controller.yaml - -kubectl create -f ${OPENSHIFT_EXAMPLE}/etcd-discovery-controller.yaml --namespace='openshift-origin' -kubectl create -f ${OPENSHIFT_EXAMPLE}/etcd-discovery-service.yaml --namespace='openshift-origin' -echo - -echo "===> Setting up etcd:" -kubectl create -f ${OPENSHIFT_EXAMPLE}/etcd-controller.yaml --namespace='openshift-origin' -kubectl create -f ${OPENSHIFT_EXAMPLE}/etcd-service.yaml --namespace='openshift-origin' -echo - -echo "===> Setting up openshift-origin:" -kubectl config view --output=yaml --flatten=true --minify=true > ${OPENSHIFT_CONFIG}/kubeconfig -kubectl create -f ${OPENSHIFT_EXAMPLE}/openshift-service.yaml --namespace='openshift-origin' -echo - -export PUBLIC_OPENSHIFT_IP="" -echo "===> Waiting for public IP to be set for the OpenShift Service." -echo "Mistakes in service setup can cause this to loop infinitely if an" -echo "external IP is never set. Ensure that the OpenShift service" -echo "is set to use an external load balancer. This process may take" -echo "a few minutes. Errors can be found in the log file found at:" -echo ${OPENSHIFT_EXAMPLE}/openshift-startup.log -echo "" > ${OPENSHIFT_EXAMPLE}/openshift-startup.log -while [ ${#PUBLIC_OPENSHIFT_IP} -lt 1 ]; do - echo -n . - sleep 1 - { - export PUBLIC_OPENSHIFT_IP=$(kubectl get services openshift --namespace="openshift-origin" --template="{{ index .status.loadBalancer.ingress 0 \"ip\" }}") - } >> ${OPENSHIFT_EXAMPLE}/openshift-startup.log 2>&1 - if [[ ! ${PUBLIC_OPENSHIFT_IP} =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then - export PUBLIC_OPENSHIFT_IP="" - fi -done -echo -echo "Public OpenShift IP set to: ${PUBLIC_OPENSHIFT_IP}" -echo - -echo "===> Configuring OpenShift:" -docker run --privileged -v ${OPENSHIFT_CONFIG}:/config openshift/origin start master --write-config=/config --kubeconfig=/config/kubeconfig --master=https://localhost:8443 --public-master=https://${PUBLIC_OPENSHIFT_IP}:8443 --etcd=http://etcd:2379 -sudo -E chown -R ${USER} ${OPENSHIFT_CONFIG} - -# The following assumes GCE and that KUBE_GCE_INSTANCE_PREFIX is set -export ZONE=$(gcloud compute instances list | grep "${KUBE_GCE_INSTANCE_PREFIX}\-master" | awk '{print $2}' | head -1) -echo "sudo cat /srv/kubernetes/server.key; exit;" | gcloud compute ssh ${KUBE_GCE_INSTANCE_PREFIX}-master --zone ${ZONE} | grep -Ex "(^\-.*\-$|^\S+$)" > ${OPENSHIFT_CONFIG}/serviceaccounts.private.key -# The following insertion will fail if indentation changes -sed -i -e 's/publicKeyFiles:.*$/publicKeyFiles:/g' -e '/publicKeyFiles:/a \ \ - serviceaccounts.private.key' ${OPENSHIFT_CONFIG}/master-config.yaml - -docker run -it --privileged -e="KUBECONFIG=/config/admin.kubeconfig" -v ${OPENSHIFT_CONFIG}:/config openshift/origin cli secrets new openshift-config /config -o json &> ${OPENSHIFT_EXAMPLE}/secret.json -kubectl create -f ${OPENSHIFT_EXAMPLE}/secret.json --namespace='openshift-origin' -echo - -echo "===> Running OpenShift Master:" -kubectl create -f ${OPENSHIFT_EXAMPLE}/openshift-controller.yaml --namespace='openshift-origin' -echo - -echo Done. diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-controller.yaml b/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-controller.yaml deleted file mode 100644 index 419c57dbd..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-controller.yaml +++ /dev/null @@ -1,52 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: etcd -spec: - strategy: - type: Recreate - replicas: 3 - selector: - matchLabels: - name: etcd - template: - metadata: - labels: - name: etcd - spec: - containers: - - name: member - image: openshift/etcd-20-centos7 - ports: - - containerPort: 2379 - protocol: TCP - - containerPort: 2380 - protocol: TCP - env: - # ETCD_NUM_MEMBERS is the maximum number of members to launch (have to match with # of replicas) - - name: ETCD_NUM_MEMBERS - value: "3" - - name: ETCD_INITIAL_CLUSTER_STATE - value: "new" - # ETCD_INITIAL_CLUSTER_TOKEN is a token etcd uses to generate unique cluster ID and member ID. Conforms to [a-z0-9]{40} - - name: ETCD_INITIAL_CLUSTER_TOKEN - value: INSERT_ETCD_INITIAL_CLUSTER_TOKEN - # ETCD_DISCOVERY_TOKEN is a unique token used by the discovery service. Conforms to etcd-cluster-[a-z0-9]{5} - - name: ETCD_DISCOVERY_TOKEN - value: INSERT_ETCD_DISCOVERY_TOKEN - # ETCD_DISCOVERY_URL connects etcd instances together by storing a list of peer addresses, - # metadata and the initial size of the cluster under a unique address - - name: ETCD_DISCOVERY_URL - value: "http://etcd-discovery:2379" - - name: ETCDCTL_PEERS - value: "http://etcd:2379" - resources: {} - terminationMessagePath: "/dev/termination-log" - imagePullPolicy: IfNotPresent - securityContext: - capabilities: {} - privileged: false - restartPolicy: Always - dnsPolicy: ClusterFirst - serviceAccount: '' -status: {} diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-discovery-controller.yaml b/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-discovery-controller.yaml deleted file mode 100644 index 33f593ac7..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-discovery-controller.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: etcd-discovery -spec: - strategy: - type: Recreate - replicas: 1 - selector: - matchLabels: - name: etcd-discovery - template: - metadata: - labels: - name: etcd-discovery - spec: - containers: - - name: discovery - image: openshift/etcd-20-centos7 - args: - - etcd-discovery.sh - ports: - - containerPort: 2379 - protocol: TCP - resources: {} - terminationMessagePath: "/dev/termination-log" - imagePullPolicy: IfNotPresent - securityContext: - capabilities: {} - privileged: false - restartPolicy: Always - dnsPolicy: ClusterFirst - serviceAccount: '' -status: {} diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-discovery-service.yaml b/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-discovery-service.yaml deleted file mode 100644 index 99f464716..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-discovery-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: etcd-discovery - labels: - name: etcd-discovery -spec: - ports: - - protocol: TCP - port: 2379 - targetPort: 2379 - nodePort: 0 - selector: - name: etcd-discovery - sessionAffinity: None - type: ClusterIP -status: - loadBalancer: {} diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-service.yaml b/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-service.yaml deleted file mode 100644 index 00bc56ef0..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/etcd-service.yaml +++ /dev/null @@ -1,24 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: etcd - labels: - name: etcd -spec: - ports: - - name: client - protocol: TCP - port: 2379 - targetPort: 2379 - nodePort: 0 - - name: server - protocol: TCP - port: 2380 - targetPort: 2380 - nodePort: 0 - selector: - name: etcd - sessionAffinity: None - type: ClusterIP -status: - loadBalancer: {} diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/openshift-controller.yaml b/vendor/k8s.io/kubernetes/examples/openshift-origin/openshift-controller.yaml deleted file mode 100644 index 1844a70cc..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/openshift-controller.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - labels: - name: openshift - name: openshift -spec: - replicas: 1 - selector: - matchLabels: - name: openshift - template: - metadata: - labels: - name: openshift - spec: - containers: - - args: - - start - - master - - --config=/config/master-config.yaml - image: "openshift/origin" - name: origin - ports: - - containerPort: 8443 - name: openshift - volumeMounts: - - mountPath: /config - name: config - readOnly: true - volumes: - - name: config - secret: - secretName: openshift-config \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/openshift-origin-namespace.yaml b/vendor/k8s.io/kubernetes/examples/openshift-origin/openshift-origin-namespace.yaml deleted file mode 100644 index 1596417f6..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/openshift-origin-namespace.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Namespace -apiVersion: v1 -metadata: - name: "openshift-origin" - labels: - name: "openshift-origin" \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/openshift-origin/openshift-service.yaml b/vendor/k8s.io/kubernetes/examples/openshift-origin/openshift-service.yaml deleted file mode 100644 index a8d599da6..000000000 --- a/vendor/k8s.io/kubernetes/examples/openshift-origin/openshift-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: openshift -spec: - ports: - - name: openshift - port: 8443 - targetPort: 8443 - selector: - name: openshift - type: LoadBalancer diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/README.md b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/README.md deleted file mode 100644 index df49ca3b5..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/persistent-volume-provisioning/README.md](https://github.com/kubernetes/examples/blob/master/staging/persistent-volume-provisioning/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/aws-ebs.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/aws-ebs.yaml deleted file mode 100644 index 4fc5ba924..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/aws-ebs.yaml +++ /dev/null @@ -1,9 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: slow -provisioner: kubernetes.io/aws-ebs -parameters: - type: io1 - zone: us-east-1d - iopsPerGB: "10" diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/cinder/cinder-storage-class.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/cinder/cinder-storage-class.yaml deleted file mode 100644 index 3dc066cd5..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/cinder/cinder-storage-class.yaml +++ /dev/null @@ -1,8 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: gold -provisioner: kubernetes.io/cinder -parameters: - type: fast - availability: nova diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/cinder/example-pod.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/cinder/example-pod.yaml deleted file mode 100644 index bc14b1205..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/cinder/example-pod.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: server -spec: - replicas: 1 - selector: - role: server - template: - metadata: - labels: - role: server - spec: - containers: - - name: server - image: nginx - volumeMounts: - - mountPath: /var/lib/www/html - name: cinderpvc - volumes: - - name: cinderpvc - persistentVolumeClaim: - claimName: claim1 diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/claim1.json b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/claim1.json deleted file mode 100644 index 75c71a669..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/claim1.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "claim1" - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "3Gi" - } - }, - "storageClassName": "slow" - } -} diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/gce-pd.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/gce-pd.yaml deleted file mode 100644 index 3d8e134ba..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/gce-pd.yaml +++ /dev/null @@ -1,8 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: slow -provisioner: kubernetes.io/gce-pd -parameters: - type: pd-standard - zone: us-central1-a diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/glusterfs/glusterfs-secret.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/glusterfs/glusterfs-secret.yaml deleted file mode 100644 index bb9c806a2..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/glusterfs/glusterfs-secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: heketi-secret - namespace: default -data: - # base64 encoded password. E.g.: echo -n "mypassword" | base64 - key: bXlwYXNzd29yZA== -type: kubernetes.io/glusterfs diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/glusterfs/glusterfs-storageclass.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/glusterfs/glusterfs-storageclass.yaml deleted file mode 100644 index ad2e76597..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/glusterfs/glusterfs-storageclass.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - name: slow -provisioner: kubernetes.io/glusterfs -parameters: - resturl: "http://127.0.0.1:8081" - clusterid: "630372ccdc720a92c681fb928f27b53f" - restuser: "admin" - secretNamespace: "default" - secretName: "heketi-secret" - gidMin: "40000" - gidMax: "50000" - volumetype: "replicate:3" diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/quobyte/example-pod.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/quobyte/example-pod.yaml deleted file mode 100644 index eb814f552..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/quobyte/example-pod.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: server -spec: - replicas: 1 - selector: - role: server - template: - metadata: - labels: - role: server - spec: - containers: - - name: server - image: nginx - volumeMounts: - - mountPath: /var/lib/www/html - name: quobytepvc - volumes: - - name: quobytepvc - persistentVolumeClaim: - claimName: claim1 diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/quobyte/quobyte-admin-secret.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/quobyte/quobyte-admin-secret.yaml deleted file mode 100644 index 24cc76773..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/quobyte/quobyte-admin-secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: quobyte-admin-secret -type: "kubernetes.io/quobyte" -data: - password: cXVvYnl0ZQ== - user: YWRtaW4= -type: kubernetes.io/quobyte diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/quobyte/quobyte-storage-class.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/quobyte/quobyte-storage-class.yaml deleted file mode 100644 index b9679d61d..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/quobyte/quobyte-storage-class.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - name: slow -provisioner: kubernetes.io/quobyte -parameters: - quobyteAPIServer: "http://138.68.74.142:7860" - registry: "138.68.74.142:7861" - adminSecretName: "quobyte-admin-secret" - adminSecretNamespace: "kube-system" - user: "root" - group: "root" - quobyteConfig: "BASE" - quobyteTenant: "DEFAULT" - createQuota: "False" diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/ceph-secret-admin.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/ceph-secret-admin.yaml deleted file mode 100644 index 894a9df6b..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/ceph-secret-admin.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: ceph-secret-admin -type: "kubernetes.io/rbd" -data: -#Please note this value is base64 encoded. - key: QVFEQ1pMdFhPUnQrSmhBQUFYaERWNHJsZ3BsMmNjcDR6RFZST0E9PQ== diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/ceph-secret-user.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/ceph-secret-user.yaml deleted file mode 100644 index e538dcafb..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/ceph-secret-user.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: ceph-secret-user -type: "kubernetes.io/rbd" -data: -#Please note this value is base64 encoded. - key: QVFBTWdYaFZ3QkNlRGhBQTlubFBhRnlmVVNhdEdENGRyRldEdlE9PQ== diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/pod.yaml b/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/pod.yaml deleted file mode 100644 index 6eea26f94..000000000 --- a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/pod.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: server -spec: - replicas: 1 - selector: - role: server - template: - metadata: - labels: - role: server - spec: - containers: - - name: server - image: nginx - volumeMounts: - - mountPath: /var/lib/www/html - name: mypvc - volumes: - - name: mypvc - persistentVolumeClaim: - claimName: claim1 diff --git a/vendor/k8s.io/kubernetes/examples/phabricator/README.md b/vendor/k8s.io/kubernetes/examples/phabricator/README.md deleted file mode 100644 index b33ddb255..000000000 --- a/vendor/k8s.io/kubernetes/examples/phabricator/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/phabricator/README.md](https://github.com/kubernetes/examples/blob/master/staging/phabricator/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/phabricator/phabricator-controller.json b/vendor/k8s.io/kubernetes/examples/phabricator/phabricator-controller.json deleted file mode 100644 index b13103e11..000000000 --- a/vendor/k8s.io/kubernetes/examples/phabricator/phabricator-controller.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "kind": "ReplicationController", - "apiVersion": "v1", - "metadata": { - "name": "phabricator-controller", - "labels": { - "name": "phabricator" - } - }, - "spec": { - "replicas": 1, - "selector": { - "name": "phabricator" - }, - "template": { - "metadata": { - "labels": { - "name": "phabricator" - } - }, - "spec": { - "containers": [ - { - "name": "phabricator", - "image": "fgrzadkowski/example-php-phabricator", - "ports": [ - { - "name": "http-server", - "containerPort": 80 - } - ], - "env": [ - { - "name": "MYSQL_SERVICE_IP", - "value": "1.2.3.4" - }, - { - "name": "MYSQL_SERVICE_PORT", - "value": "3306" - }, - { - "name": "MYSQL_PASSWORD", - "value": "1234" - } - ] - } - ] - } - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/phabricator/phabricator-service.json b/vendor/k8s.io/kubernetes/examples/phabricator/phabricator-service.json deleted file mode 100644 index b2ec74cf4..000000000 --- a/vendor/k8s.io/kubernetes/examples/phabricator/phabricator-service.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "phabricator" - }, - "spec": { - "ports": [ - { - "port": 80, - "targetPort": "http-server" - } - ], - "selector": { - "name": "phabricator" - }, - "type": "LoadBalancer" - } -} diff --git a/vendor/k8s.io/kubernetes/examples/phabricator/php-phabricator/000-default.conf b/vendor/k8s.io/kubernetes/examples/phabricator/php-phabricator/000-default.conf deleted file mode 100644 index 2ec64d687..000000000 --- a/vendor/k8s.io/kubernetes/examples/phabricator/php-phabricator/000-default.conf +++ /dev/null @@ -1,12 +0,0 @@ - - Require all granted - - - - DocumentRoot /home/www-data/phabricator/webroot - - RewriteEngine on - RewriteRule ^/rsrc/(.*) - [L,QSA] - RewriteRule ^/favicon.ico - [L,QSA] - RewriteRule ^(.*)$ /index.php?__path__=$1 [B,L,QSA] - diff --git a/vendor/k8s.io/kubernetes/examples/phabricator/php-phabricator/Dockerfile b/vendor/k8s.io/kubernetes/examples/phabricator/php-phabricator/Dockerfile deleted file mode 100644 index 779e799ce..000000000 --- a/vendor/k8s.io/kubernetes/examples/phabricator/php-phabricator/Dockerfile +++ /dev/null @@ -1,44 +0,0 @@ -# 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. - -FROM ubuntu:14.04 - -# Install all the required packages. -RUN apt-get update && \ - apt-get -y install \ - git apache2 dpkg-dev python-pygments \ - php5 php5-mysql php5-gd php5-dev php5-curl php-apc php5-cli php5-json php5-xhprof && \ - apt-get -y clean autoclean && \ - rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -#Configure php -RUN a2enmod rewrite && \ - apt-get source php5 && \ - (cd `ls -1F | grep '^php5-.*/$'`/ext/pcntl && phpize && ./configure && make && sudo make install) - -# Load code source. -RUN mkdir /home/www-data -RUN cd /home/www-data && git clone https://github.com/phacility/libphutil.git && \ - cd /home/www-data && git clone https://github.com/phacility/arcanist.git && \ - cd /home/www-data && git clone https://github.com/phacility/phabricator.git && \ - chown -R www-data /home/www-data && \ - chgrp -R www-data /home/www-data - -ADD 000-default.conf /etc/apache2/sites-available/000-default.conf -ADD run.sh /run.sh -RUN chmod a+x /*.sh - -# Run Apache2. -EXPOSE 80 -CMD ["/run.sh"] diff --git a/vendor/k8s.io/kubernetes/examples/phabricator/php-phabricator/run.sh b/vendor/k8s.io/kubernetes/examples/phabricator/php-phabricator/run.sh deleted file mode 100755 index 1f2b8387f..000000000 --- a/vendor/k8s.io/kubernetes/examples/phabricator/php-phabricator/run.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# 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. - -echo "MySQL host IP ${MYSQL_SERVICE_IP} port ${MYSQL_SERVICE_PORT}." -/home/www-data/phabricator/bin/config set mysql.host $MYSQL_SERVICE_IP -/home/www-data/phabricator/bin/config set mysql.port $MYSQL_SERVICE_PORT -/home/www-data/phabricator/bin/config set mysql.pass $MYSQL_PASSWORD - -echo "Running storage upgrade" -/home/www-data/phabricator/bin/storage --force upgrade || exit 1 - -source /etc/apache2/envvars -echo "Starting Apache2" -apache2 -D FOREGROUND - diff --git a/vendor/k8s.io/kubernetes/examples/phabricator/setup.sh b/vendor/k8s.io/kubernetes/examples/phabricator/setup.sh deleted file mode 100755 index 588b1f5f9..000000000 --- a/vendor/k8s.io/kubernetes/examples/phabricator/setup.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# 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. - -echo "Create Phabricator replication controller" && kubectl create -f phabricator-controller.json -echo "Create Phabricator service" && kubectl create -f phabricator-service.json -echo "Create firewall rule" && gcloud compute firewall-rules create phabricator-node-80 --allow=tcp:80 --target-tags kubernetes-node - diff --git a/vendor/k8s.io/kubernetes/examples/phabricator/teardown.sh b/vendor/k8s.io/kubernetes/examples/phabricator/teardown.sh deleted file mode 100755 index 266313912..000000000 --- a/vendor/k8s.io/kubernetes/examples/phabricator/teardown.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# 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. - -echo "Deleting Phabricator service" && kubectl delete -f phabricator-service.json -echo "Deleting Phabricator replication controller" && kubectl delete rc phabricator-controller -echo "Delete firewall rule" && gcloud compute firewall-rules delete -q phabricator-node-80 - diff --git a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/OWNERS b/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/OWNERS deleted file mode 100644 index 63eee4bb6..000000000 --- a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/OWNERS +++ /dev/null @@ -1,11 +0,0 @@ -approvers: - - deads2k - - ericchiang - - liggitt - - tallclair -reviewers: - - deads2k - - ericchiang - - liggitt - - php-coder - - tallclair diff --git a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/README.md b/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/README.md deleted file mode 100644 index 66af1b7c1..000000000 --- a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/podsecuritypolicy/rbac/README.md](https://github.com/kubernetes/examples/blob/master/staging/podsecuritypolicy/rbac/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/bindings.yaml b/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/bindings.yaml deleted file mode 100644 index f61b73b21..000000000 --- a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/bindings.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# privileged-psp-users gives the privileged-psp-user role -# to the group privileged-psp-users. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: privileged-psp-users -subjects: -- kind: Group - apiGroup: rbac.authorization.k8s.io - name: privileged-psp-users -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: privileged-psp-user ---- -# restricted-psp-users grants the restricted-psp-user role to -# the groups restricted-psp-users and privileged-psp-users. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: restricted-psp-users -subjects: -- kind: Group - apiGroup: rbac.authorization.k8s.io - name: restricted-psp-users -- kind: Group - apiGroup: rbac.authorization.k8s.io - name: privileged-psp-users -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: restricted-psp-user ---- -# edit grants edit role to the groups -# restricted-psp-users and privileged-psp-users. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: edit -subjects: -- kind: Group - apiGroup: rbac.authorization.k8s.io - name: privileged-psp-users -- kind: Group - apiGroup: rbac.authorization.k8s.io - name: restricted-psp-users -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: edit diff --git a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/pod.yaml b/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/pod.yaml deleted file mode 100644 index 5b7b1efdc..000000000 --- a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/pod.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: nginx - labels: - name: nginx -spec: - containers: - - name: nginx - image: nginx - ports: - - containerPort: 80 diff --git a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/pod_priv.yaml b/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/pod_priv.yaml deleted file mode 100644 index 6c638c449..000000000 --- a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/pod_priv.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: nginx - labels: - name: nginx -spec: - containers: - - name: nginx - image: nginx - ports: - - containerPort: 80 - securityContext: - privileged: true diff --git a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/policies.yaml b/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/policies.yaml deleted file mode 100644 index d8c0ca063..000000000 --- a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/policies.yaml +++ /dev/null @@ -1,49 +0,0 @@ -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: privileged -spec: - fsGroup: - rule: RunAsAny - privileged: true - runAsUser: - rule: RunAsAny - seLinux: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - volumes: - - '*' - allowedCapabilities: - - '*' - hostPID: true - hostIPC: true - hostNetwork: true - hostPorts: - - min: 1 - max: 65536 ---- -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: restricted -spec: - privileged: false - fsGroup: - rule: RunAsAny - runAsUser: - rule: MustRunAsNonRoot - seLinux: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - volumes: - - 'emptyDir' - - 'secret' - - 'downwardAPI' - - 'configMap' - - 'persistentVolumeClaim' - - 'projected' - hostPID: false - hostIPC: false - hostNetwork: false diff --git a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/roles.yaml b/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/roles.yaml deleted file mode 100644 index 55d591d5d..000000000 --- a/vendor/k8s.io/kubernetes/examples/podsecuritypolicy/rbac/roles.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# restricted-psp-user grants access to use the restricted PSP. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: restricted-psp-user -rules: -- apiGroups: - - policy - resources: - - podsecuritypolicies - resourceNames: - - restricted - verbs: - - use ---- -# privileged-psp-user grants access to use the privileged PSP. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: privileged-psp-user -rules: -- apiGroups: - - policy - resources: - - podsecuritypolicies - resourceNames: - - privileged - verbs: - - use - - diff --git a/vendor/k8s.io/kubernetes/examples/runtime-constraints/README.md b/vendor/k8s.io/kubernetes/examples/runtime-constraints/README.md deleted file mode 100644 index 3f245a12d..000000000 --- a/vendor/k8s.io/kubernetes/examples/runtime-constraints/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/runtime-constraints/README.md](https://github.com/kubernetes/examples/blob/master/staging/runtime-constraints/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/scheduler-policy-config-with-extender.json b/vendor/k8s.io/kubernetes/examples/scheduler-policy-config-with-extender.json deleted file mode 100644 index cc1a9bd6f..000000000 --- a/vendor/k8s.io/kubernetes/examples/scheduler-policy-config-with-extender.json +++ /dev/null @@ -1,30 +0,0 @@ -{ -"kind" : "Policy", -"apiVersion" : "v1", -"predicates" : [ - {"name" : "PodFitsHostPorts"}, - {"name" : "PodFitsResources"}, - {"name" : "NoDiskConflict"}, - {"name" : "MatchNodeSelector"}, - {"name" : "HostName"} - ], -"priorities" : [ - {"name" : "LeastRequestedPriority", "weight" : 1}, - {"name" : "BalancedResourceAllocation", "weight" : 1}, - {"name" : "ServiceSpreadingPriority", "weight" : 1}, - {"name" : "EqualPriority", "weight" : 1} - ], -"extenders" : [ - { - "urlPrefix": "http://127.0.0.1:12346/scheduler", - "filterVerb": "filter", - "bindVerb": "bind", - "prioritizeVerb": "prioritize", - "weight": 5, - "enableHttps": false, - "nodeCacheCapable": false - } - ], -"hardPodAffinitySymmetricWeight" : 10, -"alwaysCheckAllPredicates" : false -} diff --git a/vendor/k8s.io/kubernetes/examples/scheduler-policy-config.json b/vendor/k8s.io/kubernetes/examples/scheduler-policy-config.json deleted file mode 100644 index 048299e5e..000000000 --- a/vendor/k8s.io/kubernetes/examples/scheduler-policy-config.json +++ /dev/null @@ -1,20 +0,0 @@ -{ -"kind" : "Policy", -"apiVersion" : "v1", -"predicates" : [ - {"name" : "PodFitsHostPorts"}, - {"name" : "PodFitsResources"}, - {"name" : "NoDiskConflict"}, - {"name" : "NoVolumeZoneConflict"}, - {"name" : "MatchNodeSelector"}, - {"name" : "HostName"} - ], -"priorities" : [ - {"name" : "LeastRequestedPriority", "weight" : 1}, - {"name" : "BalancedResourceAllocation", "weight" : 1}, - {"name" : "ServiceSpreadingPriority", "weight" : 1}, - {"name" : "EqualPriority", "weight" : 1} - ], -"hardPodAffinitySymmetricWeight" : 10, -"alwaysCheckAllPredicates" : false -} diff --git a/vendor/k8s.io/kubernetes/examples/selenium/README.md b/vendor/k8s.io/kubernetes/examples/selenium/README.md deleted file mode 100644 index e36593711..000000000 --- a/vendor/k8s.io/kubernetes/examples/selenium/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/selenium/README.md](https://github.com/kubernetes/examples/blob/master/staging/selenium/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/selenium/selenium-hub-rc.yaml b/vendor/k8s.io/kubernetes/examples/selenium/selenium-hub-rc.yaml deleted file mode 100644 index f48510e1c..000000000 --- a/vendor/k8s.io/kubernetes/examples/selenium/selenium-hub-rc.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: selenium-hub - labels: - app: selenium-hub -spec: - replicas: 1 - selector: - app: selenium-hub - template: - metadata: - labels: - app: selenium-hub - spec: - containers: - - name: selenium-hub - image: selenium/hub:2.53.0 - ports: - - containerPort: 4444 - resources: - limits: - memory: "1000Mi" - cpu: ".5" - livenessProbe: - httpGet: - path: /grid/console - port: 4444 - initialDelaySeconds: 30 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: /grid/console - port: 4444 - initialDelaySeconds: 30 - timeoutSeconds: 5 diff --git a/vendor/k8s.io/kubernetes/examples/selenium/selenium-hub-svc.yaml b/vendor/k8s.io/kubernetes/examples/selenium/selenium-hub-svc.yaml deleted file mode 100644 index 0b252ede3..000000000 --- a/vendor/k8s.io/kubernetes/examples/selenium/selenium-hub-svc.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: selenium-hub - labels: - app: selenium-hub -spec: - ports: - - port: 4444 - targetPort: 4444 - name: port0 - selector: - app: selenium-hub - type: NodePort - sessionAffinity: None diff --git a/vendor/k8s.io/kubernetes/examples/selenium/selenium-node-chrome-rc.yaml b/vendor/k8s.io/kubernetes/examples/selenium/selenium-node-chrome-rc.yaml deleted file mode 100644 index 3c49c1b43..000000000 --- a/vendor/k8s.io/kubernetes/examples/selenium/selenium-node-chrome-rc.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: selenium-node-chrome - labels: - app: selenium-node-chrome -spec: - replicas: 2 - selector: - app: selenium-node-chrome - template: - metadata: - labels: - app: selenium-node-chrome - spec: - containers: - - name: selenium-node-chrome - image: selenium/node-chrome-debug:2.53.0 - ports: - - containerPort: 5900 - env: - - name: HUB_PORT_4444_TCP_ADDR - value: "selenium-hub" - - name: HUB_PORT_4444_TCP_PORT - value: "4444" - resources: - limits: - memory: "1000Mi" - cpu: ".5" diff --git a/vendor/k8s.io/kubernetes/examples/selenium/selenium-node-firefox-rc.yaml b/vendor/k8s.io/kubernetes/examples/selenium/selenium-node-firefox-rc.yaml deleted file mode 100644 index d6f665785..000000000 --- a/vendor/k8s.io/kubernetes/examples/selenium/selenium-node-firefox-rc.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: selenium-node-firefox - labels: - app: selenium-node-firefox -spec: - replicas: 2 - selector: - app: selenium-node-firefox - template: - metadata: - labels: - app: selenium-node-firefox - spec: - containers: - - name: selenium-node-firefox - image: selenium/node-firefox-debug:2.53.0 - ports: - - containerPort: 5900 - env: - - name: HUB_PORT_4444_TCP_ADDR - value: "selenium-hub" - - name: HUB_PORT_4444_TCP_PORT - value: "4444" - resources: - limits: - memory: "1000Mi" - cpu: ".5" diff --git a/vendor/k8s.io/kubernetes/examples/selenium/selenium-test.py b/vendor/k8s.io/kubernetes/examples/selenium/selenium-test.py deleted file mode 100644 index 80d598a3b..000000000 --- a/vendor/k8s.io/kubernetes/examples/selenium/selenium-test.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from selenium import webdriver -from selenium.webdriver.common.desired_capabilities import DesiredCapabilities - -def check_browser(browser): - driver = webdriver.Remote( - command_executor='http://selenium-hub:4444/wd/hub', - desired_capabilities=getattr(DesiredCapabilities, browser) - ) - driver.get("http://google.com") - assert "google" in driver.page_source - driver.close() - print("Browser %s checks out!" % browser) - - -check_browser("FIREFOX") -check_browser("CHROME") - diff --git a/vendor/k8s.io/kubernetes/examples/sharing-clusters/BUILD b/vendor/k8s.io/kubernetes/examples/sharing-clusters/BUILD deleted file mode 100644 index bc1611f87..000000000 --- a/vendor/k8s.io/kubernetes/examples/sharing-clusters/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "sharing-clusters", - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["make_secret.go"], - importpath = "k8s.io/kubernetes/examples/sharing-clusters", - deps = [ - "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/examples/sharing-clusters/README.md b/vendor/k8s.io/kubernetes/examples/sharing-clusters/README.md deleted file mode 100644 index ffd44e29a..000000000 --- a/vendor/k8s.io/kubernetes/examples/sharing-clusters/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/sharing-clusters/README.md](https://github.com/kubernetes/examples/blob/master/staging/sharing-clusters/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/sharing-clusters/make_secret.go b/vendor/k8s.io/kubernetes/examples/sharing-clusters/make_secret.go deleted file mode 100644 index ece55eab3..000000000 --- a/vendor/k8s.io/kubernetes/examples/sharing-clusters/make_secret.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -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. -*/ - -// A tiny script to help conver a given kubeconfig into a secret. -package main - -import ( - "flag" - "fmt" - "io/ioutil" - "log" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/api/legacyscheme" - api "k8s.io/kubernetes/pkg/apis/core" -) - -// TODO: -// Add a -o flag that writes to the specified destination file. -var ( - kubeconfig = flag.String("kubeconfig", "", "path to kubeconfig file.") - name = flag.String("name", "kubeconfig", "name to use in the metadata of the secret.") - ns = flag.String("ns", "default", "namespace of the secret.") -) - -func read(file string) []byte { - b, err := ioutil.ReadFile(file) - if err != nil { - log.Fatalf("Cannot read file %v, %v", file, err) - } - return b -} - -func main() { - flag.Parse() - if *kubeconfig == "" { - log.Fatalf("Need to specify --kubeconfig") - } - cfg := read(*kubeconfig) - secret := &api.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: *name, - Namespace: *ns, - }, - Data: map[string][]byte{ - "config": cfg, - }, - } - fmt.Printf(runtime.EncodeOrDie(legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), secret)) -} diff --git a/vendor/k8s.io/kubernetes/examples/simple-nginx.md b/vendor/k8s.io/kubernetes/examples/simple-nginx.md deleted file mode 100644 index 4d9bb9514..000000000 --- a/vendor/k8s.io/kubernetes/examples/simple-nginx.md +++ /dev/null @@ -1,62 +0,0 @@ -## Running your first containers in Kubernetes - -Ok, you've run one of the [getting started guides](https://kubernetes.io/docs/getting-started-guides/) and you have -successfully turned up a Kubernetes cluster. Now what? This guide will help you get oriented -to Kubernetes and running your first containers on the cluster. - -### Running a container (simple version) - -From this point onwards, it is assumed that `kubectl` is on your path from one of the getting started guides. - -The [`kubectl run`](https://kubernetes.io/docs/user-guide/kubectl/kubectl_run.md) line below will create two [nginx](https://registry.hub.docker.com/_/nginx/) [pods](https://kubernetes.io/docs/user-guide/pods.md) listening on port 80. It will also create a [deployment](https://kubernetes.io/docs/user-guide/deployments.md) named `my-nginx` to ensure that there are always two pods running. - -```bash -kubectl run my-nginx --image=nginx --replicas=2 --port=80 -``` - -Once the pods are created, you can list them to see what is up and running: - -```bash -kubectl get pods -``` - -You can also see the deployment that was created: - -```bash -kubectl get deployment -``` - -### Exposing your pods to the internet. - -On some platforms (for example Google Compute Engine) the kubectl command can integrate with your cloud provider to add a [public IP address](https://kubernetes.io/docs/user-guide/services.md#publishing-services---service-types) for the pods, -to do this run: - -```bash -kubectl expose deployment my-nginx --port=80 --type=LoadBalancer -``` - -This should print the service that has been created, and map an external IP address to the service. Where to find this external IP address will depend on the environment you run in. For instance, for Google Compute Engine the external IP address is listed as part of the newly created service and can be retrieved by running - -```bash -kubectl get services -``` - -In order to access your nginx landing page, you also have to make sure that traffic from external IPs is allowed. Do this by opening a firewall to allow traffic on port 80. - -### Cleanup - -To delete the two replicated containers, delete the deployment: - -```bash -kubectl delete deployment my-nginx -``` - -### Next: Configuration files - -Most people will eventually want to use declarative configuration files for creating/modifying their applications. A [simplified introduction](https://kubernetes.io/docs/user-guide/deploying-applications.md) -is given in a different document. - - - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/simple-nginx.md?pixel)]() - diff --git a/vendor/k8s.io/kubernetes/examples/spark/README.md b/vendor/k8s.io/kubernetes/examples/spark/README.md deleted file mode 100644 index edfe3efd2..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/spark/README.md](https://github.com/kubernetes/examples/blob/master/staging/spark/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/spark/namespace-spark-cluster.yaml b/vendor/k8s.io/kubernetes/examples/spark/namespace-spark-cluster.yaml deleted file mode 100644 index 1f3dce83c..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/namespace-spark-cluster.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: "spark-cluster" - labels: - name: "spark-cluster" diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/README.md b/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/README.md deleted file mode 100644 index 07d2a8d0f..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/spark/spark-gluster/README.md](https://github.com/kubernetes/examples/blob/master/staging/spark/spark-gluster/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/glusterfs-endpoints.yaml b/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/glusterfs-endpoints.yaml deleted file mode 100644 index 357fdb766..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/glusterfs-endpoints.yaml +++ /dev/null @@ -1,14 +0,0 @@ -kind: Endpoints -apiVersion: v1 -metadata: - name: glusterfs-cluster - namespace: spark-cluster -subsets: - - addresses: - - ip: 192.168.30.104 - ports: - - port: 1 - - addresses: - - ip: 192.168.30.105 - ports: - - port: 1 diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/spark-master-controller.yaml b/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/spark-master-controller.yaml deleted file mode 100644 index 28cb6ac3f..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/spark-master-controller.yaml +++ /dev/null @@ -1,34 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: spark-master-controller - namespace: spark-cluster - labels: - component: spark-master -spec: - replicas: 1 - selector: - component: spark-master - template: - metadata: - labels: - component: spark-master - spec: - containers: - - name: spark-master - image: k8s.gcr.io/spark:1.5.2_v1 - command: ["/start-master"] - ports: - - containerPort: 7077 - volumeMounts: - - mountPath: /mnt/glusterfs - name: glusterfsvol - resources: - requests: - cpu: 100m - volumes: - - name: glusterfsvol - glusterfs: - endpoints: glusterfs-cluster - path: MyVolume - readOnly: false diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/spark-master-service.yaml b/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/spark-master-service.yaml deleted file mode 100644 index 2f5bdb15d..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/spark-master-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: spark-master - namespace: spark-cluster - labels: - component: spark-master-service -spec: - ports: - - port: 7077 - targetPort: 7077 - selector: - component: spark-master diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/spark-worker-controller.yaml b/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/spark-worker-controller.yaml deleted file mode 100644 index 0030d8a66..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-gluster/spark-worker-controller.yaml +++ /dev/null @@ -1,35 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: spark-gluster-worker-controller - namespace: spark-cluster - labels: - component: spark-worker -spec: - replicas: 2 - selector: - component: spark-worker - template: - metadata: - labels: - component: spark-worker - uses: spark-master - spec: - containers: - - name: spark-worker - image: k8s.gcr.io/spark:1.5.2_v1 - command: ["/start-worker"] - ports: - - containerPort: 8888 - volumeMounts: - - mountPath: /mnt/glusterfs - name: glusterfsvol - resources: - requests: - cpu: 100m - volumes: - - name: glusterfsvol - glusterfs: - endpoints: glusterfs-cluster - path: MyVolume - readOnly: false diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-master-controller.yaml b/vendor/k8s.io/kubernetes/examples/spark/spark-master-controller.yaml deleted file mode 100644 index ceaef078d..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-master-controller.yaml +++ /dev/null @@ -1,23 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: spark-master-controller -spec: - replicas: 1 - selector: - component: spark-master - template: - metadata: - labels: - component: spark-master - spec: - containers: - - name: spark-master - image: k8s.gcr.io/spark:1.5.2_v1 - command: ["/start-master"] - ports: - - containerPort: 7077 - - containerPort: 8080 - resources: - requests: - cpu: 100m diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-master-service.yaml b/vendor/k8s.io/kubernetes/examples/spark/spark-master-service.yaml deleted file mode 100644 index 794147d28..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-master-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: spark-master -spec: - ports: - - port: 7077 - targetPort: 7077 - name: spark - - port: 8080 - targetPort: 8080 - name: http - selector: - component: spark-master diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-ui-proxy-controller.yaml b/vendor/k8s.io/kubernetes/examples/spark/spark-ui-proxy-controller.yaml deleted file mode 100644 index 3bd0566cd..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-ui-proxy-controller.yaml +++ /dev/null @@ -1,29 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: spark-ui-proxy-controller -spec: - replicas: 1 - selector: - component: spark-ui-proxy - template: - metadata: - labels: - component: spark-ui-proxy - spec: - containers: - - name: spark-ui-proxy - image: elsonrodriguez/spark-ui-proxy:1.0 - ports: - - containerPort: 80 - resources: - requests: - cpu: 100m - args: - - spark-master:8080 - livenessProbe: - httpGet: - path: / - port: 80 - initialDelaySeconds: 120 - timeoutSeconds: 5 diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-ui-proxy-service.yaml b/vendor/k8s.io/kubernetes/examples/spark/spark-ui-proxy-service.yaml deleted file mode 100644 index ebd6b7c94..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-ui-proxy-service.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: spark-ui-proxy -spec: - ports: - - port: 80 - targetPort: 80 - selector: - component: spark-ui-proxy - type: LoadBalancer diff --git a/vendor/k8s.io/kubernetes/examples/spark/spark-worker-controller.yaml b/vendor/k8s.io/kubernetes/examples/spark/spark-worker-controller.yaml deleted file mode 100644 index 3e5ed50ce..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/spark-worker-controller.yaml +++ /dev/null @@ -1,23 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: spark-worker-controller -spec: - replicas: 2 - selector: - component: spark-worker - template: - metadata: - labels: - component: spark-worker - spec: - containers: - - name: spark-worker - image: k8s.gcr.io/spark:1.5.2_v1 - command: ["/start-worker"] - ports: - - containerPort: 8081 - resources: - requests: - cpu: 100m - diff --git a/vendor/k8s.io/kubernetes/examples/spark/zeppelin-controller.yaml b/vendor/k8s.io/kubernetes/examples/spark/zeppelin-controller.yaml deleted file mode 100644 index 2f578fcfc..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/zeppelin-controller.yaml +++ /dev/null @@ -1,21 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: zeppelin-controller -spec: - replicas: 1 - selector: - component: zeppelin - template: - metadata: - labels: - component: zeppelin - spec: - containers: - - name: zeppelin - image: k8s.gcr.io/zeppelin:v0.5.6_v1 - ports: - - containerPort: 8080 - resources: - requests: - cpu: 100m diff --git a/vendor/k8s.io/kubernetes/examples/spark/zeppelin-service.yaml b/vendor/k8s.io/kubernetes/examples/spark/zeppelin-service.yaml deleted file mode 100644 index f2c7838ad..000000000 --- a/vendor/k8s.io/kubernetes/examples/spark/zeppelin-service.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: zeppelin -spec: - ports: - - port: 80 - targetPort: 8080 - selector: - component: zeppelin - type: LoadBalancer diff --git a/vendor/k8s.io/kubernetes/examples/storage/cassandra/README.md b/vendor/k8s.io/kubernetes/examples/storage/cassandra/README.md deleted file mode 100644 index 52b4a9e55..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/cassandra/README.md +++ /dev/null @@ -1 +0,0 @@ -This example has been moved to [https://github.com/kubernetes/examples/blob/master/cassandra](https://github.com/kubernetes/examples/blob/master/cassandra) diff --git a/vendor/k8s.io/kubernetes/examples/storage/hazelcast/README.md b/vendor/k8s.io/kubernetes/examples/storage/hazelcast/README.md deleted file mode 100644 index fd46e2757..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/hazelcast/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/storage/hazelcast/README.md](https://github.com/kubernetes/examples/blob/master/staging/storage/hazelcast/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/storage/hazelcast/hazelcast-deployment.yaml b/vendor/k8s.io/kubernetes/examples/storage/hazelcast/hazelcast-deployment.yaml deleted file mode 100644 index bbf61b092..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/hazelcast/hazelcast-deployment.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: hazelcast - labels: - name: hazelcast -spec: - template: - metadata: - labels: - name: hazelcast - spec: - containers: - - name: hazelcast - image: quay.io/pires/hazelcast-kubernetes:3.8_1 - imagePullPolicy: Always - env: - - name: "DNS_DOMAIN" - value: "cluster.local" - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - ports: - - name: hazelcast - containerPort: 5701 diff --git a/vendor/k8s.io/kubernetes/examples/storage/hazelcast/hazelcast-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/hazelcast/hazelcast-service.yaml deleted file mode 100644 index 0c9dc55da..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/hazelcast/hazelcast-service.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - name: hazelcast - name: hazelcast -spec: - ports: - - port: 5701 - selector: - name: hazelcast diff --git a/vendor/k8s.io/kubernetes/examples/storage/minio/README.md b/vendor/k8s.io/kubernetes/examples/storage/minio/README.md deleted file mode 100644 index 43b3a6e6b..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/minio/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/storage/minio/README.md](https://github.com/kubernetes/examples/blob/master/staging/storage/minio/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-distributed-headless-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/minio/minio-distributed-headless-service.yaml deleted file mode 100644 index a822d76eb..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-distributed-headless-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: minio - labels: - app: minio -spec: - clusterIP: None - ports: - - port: 9000 - name: minio - selector: - app: minio diff --git a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-distributed-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/minio/minio-distributed-service.yaml deleted file mode 100644 index 60514a863..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-distributed-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: minio-service -spec: - type: LoadBalancer - ports: - - port: 9000 - targetPort: 9000 - protocol: TCP - selector: - app: minio diff --git a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-distributed-statefulset.yaml b/vendor/k8s.io/kubernetes/examples/storage/minio/minio-distributed-statefulset.yaml deleted file mode 100644 index de6eef0a9..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-distributed-statefulset.yaml +++ /dev/null @@ -1,50 +0,0 @@ -apiVersion: apps/v1beta2 -kind: StatefulSet -metadata: - name: minio -spec: - selector: - matchLabels: - app: minio - serviceName: minio - replicas: 4 - template: - metadata: - annotations: - pod.alpha.kubernetes.io/initialized: "true" - labels: - app: minio - spec: - containers: - - name: minio - env: - - name: MINIO_ACCESS_KEY - value: "minio" - - name: MINIO_SECRET_KEY - value: "minio123" - image: minio/minio:latest - args: - - server - - http://minio-0.minio.default.svc.cluster.local/data - - http://minio-1.minio.default.svc.cluster.local/data - - http://minio-2.minio.default.svc.cluster.local/data - - http://minio-3.minio.default.svc.cluster.local/data - ports: - - containerPort: 9000 - hostPort: 9000 - # These volume mounts are persistent. Each pod in the StatefulSet - # gets a volume mounted based on this field. - volumeMounts: - - name: data - mountPath: /data - # These are converted to volume claims by the controller - # and mounted at the paths mentioned above. - volumeClaimTemplates: - - metadata: - name: data - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi diff --git a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-standalone-deployment.yaml b/vendor/k8s.io/kubernetes/examples/storage/minio/minio-standalone-deployment.yaml deleted file mode 100644 index a6dee7d03..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-standalone-deployment.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - # This name uniquely identifies the Deployment - name: minio-deployment -spec: - selector: - matchLabels: - app: minio - strategy: - type: Recreate - template: - metadata: - labels: - # Label is used as selector in the service. - app: minio - spec: - # Refer to the PVC created earlier - volumes: - - name: storage - persistentVolumeClaim: - # Name of the PVC created earlier - claimName: minio-pv-claim - containers: - - name: minio - # Pulls the default Minio image from Docker Hub - image: minio/minio:latest - args: - - server - - /storage - env: - # Minio access key and secret key - - name: MINIO_ACCESS_KEY - value: "minio" - - name: MINIO_SECRET_KEY - value: "minio123" - ports: - - containerPort: 9000 - hostPort: 9000 - # Mount the volume into the pod - volumeMounts: - - name: storage # must match the volume name, above - mountPath: "/storage" diff --git a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-standalone-pvc.yaml b/vendor/k8s.io/kubernetes/examples/storage/minio/minio-standalone-pvc.yaml deleted file mode 100644 index 66b1c9800..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-standalone-pvc.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - # This name uniquely identifies the PVC. Will be used in deployment below. - name: minio-pv-claim - labels: - app: minio-storage-claim -spec: - # Read more about access modes here: http://kubernetes.io/docs/user-guide/persistent-volumes/#access-modes - accessModes: - - ReadWriteOnce - resources: - # This is the request for storage. Should be available in the cluster. - requests: - storage: 10Gi diff --git a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-standalone-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/minio/minio-standalone-service.yaml deleted file mode 100644 index 60514a863..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/minio/minio-standalone-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: minio-service -spec: - type: LoadBalancer - ports: - - port: 9000 - targetPort: 9000 - protocol: TCP - selector: - app: minio diff --git a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/README.md b/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/README.md deleted file mode 100644 index 1930bad24..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/storage/mysql-galera/README.md](https://github.com/kubernetes/examples/blob/master/staging/storage/mysql-galera/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/Dockerfile b/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/Dockerfile deleted file mode 100644 index 53a068c8c..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/Dockerfile +++ /dev/null @@ -1,56 +0,0 @@ -# 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. - -FROM ubuntu:trusty - -# add our user and group first to make sure their IDs get assigned -# consistently, regardless of whatever dependencies get added -RUN groupadd -r mysql && useradd -r -g mysql mysql - -ENV PERCONA_XTRADB_VERSION 5.6 -ENV MYSQL_VERSION 5.6 -ENV TERM linux - -RUN apt-get update -RUN DEBIAN_FRONTEND=noninteractive apt-get install -y perl --no-install-recommends && rm -rf /var/lib/apt/lists/* - -RUN apt-key adv --keyserver keys.gnupg.net --recv-keys 8507EFA5 - -RUN echo "deb http://repo.percona.com/apt trusty main" > /etc/apt/sources.list.d/percona.list -RUN echo "deb-src http://repo.percona.com/apt trusty main" >> /etc/apt/sources.list.d/percona.list - -# the "/var/lib/mysql" stuff here is because the mysql-server -# postinst doesn't have an explicit way to disable the -# mysql_install_db codepath besides having a database already -# "configured" (ie, stuff in /var/lib/mysql/mysql) -# also, we set debconf keys to make APT a little quieter -RUN { \ - echo percona-server-server-5.6 percona-server-server/data-dir select ''; \ - echo percona-server-server-5.6 percona-server-server/root_password password ''; \ - } | debconf-set-selections \ - && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y percona-xtradb-cluster-client-"${MYSQL_VERSION}" \ - percona-xtradb-cluster-common-"${MYSQL_VERSION}" percona-xtradb-cluster-server-"${MYSQL_VERSION}" \ - && rm -rf /var/lib/apt/lists/* \ - && rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql && chown -R mysql:mysql /var/lib/mysql - -VOLUME /var/lib/mysql - -COPY my.cnf /etc/mysql/my.cnf -COPY cluster.cnf /etc/mysql/conf.d/cluster.cnf - -COPY docker-entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] - -EXPOSE 3306 4444 4567 4568 -CMD ["mysqld"] diff --git a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/cluster.cnf b/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/cluster.cnf deleted file mode 100644 index 87d70442a..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/cluster.cnf +++ /dev/null @@ -1,12 +0,0 @@ -[mysqld] - -wsrep_provider=/usr/lib/libgalera_smm.so -wsrep_cluster_address=gcomm:// -binlog_format=ROW -default_storage_engine=InnoDB -innodb_autoinc_lock_mode=2 - -wsrep_sst_method=xtrabackup-v2 -wsrep_node_address=127.0.0.1 -wsrep_cluster_name=galera_kubernetes -wsrep_sst_auth=sstuser:changethis diff --git a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/docker-entrypoint.sh b/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/docker-entrypoint.sh deleted file mode 100755 index 50185562f..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/docker-entrypoint.sh +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/bash - -# 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. - -# -# This script does the following: -# -# 1. Sets up database privileges by building an SQL script -# 2. MySQL is initially started with this script a first time -# 3. Modify my.cnf and cluster.cnf to reflect available nodes to join -# - -# if NUM_NODES not passed, default to 3 -if [ -z "$NUM_NODES" ]; then - NUM_NODES=3 -fi - -if [ "${1:0:1}" = '-' ]; then - set -- mysqld "$@" -fi - -# if the command passed is 'mysqld' via CMD, then begin processing. -if [ "$1" = 'mysqld' ]; then - # read DATADIR from the MySQL config - DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" - - # only check if system tables not created from mysql_install_db and permissions - # set with initial SQL script before proceeding to build SQL script - if [ ! -d "$DATADIR/mysql" ]; then - # fail if user didn't supply a root password - if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then - echo >&2 'error: database is uninitialized and MYSQL_ROOT_PASSWORD not set' - echo >&2 ' Did you forget to add -e MYSQL_ROOT_PASSWORD=... ?' - exit 1 - fi - - # mysql_install_db installs system tables - echo 'Running mysql_install_db ...' - mysql_install_db --datadir="$DATADIR" - echo 'Finished mysql_install_db' - - # this script will be run once when MySQL first starts to set up - # prior to creating system tables and will ensure proper user permissions - tempSqlFile='/tmp/mysql-first-time.sql' - cat > "$tempSqlFile" <<-EOSQL -DELETE FROM mysql.user ; -CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; -GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ; -EOSQL - - if [ "$MYSQL_DATABASE" ]; then - echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" >> "$tempSqlFile" - fi - - if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then - echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" >> "$tempSqlFile" - - if [ "$MYSQL_DATABASE" ]; then - echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" >> "$tempSqlFile" - fi - fi - - # Add SST (Single State Transfer) user if Clustering is turned on - if [ -n "$GALERA_CLUSTER" ]; then - # this is the Single State Transfer user (SST, initial dump or xtrabackup user) - WSREP_SST_USER=${WSREP_SST_USER:-"sst"} - if [ -z "$WSREP_SST_PASSWORD" ]; then - echo >&2 'error: Galera cluster is enabled and WSREP_SST_PASSWORD is not set' - echo >&2 ' Did you forget to add -e WSREP_SST__PASSWORD=... ?' - exit 1 - fi - # add single state transfer (SST) user privileges - echo "CREATE USER '${WSREP_SST_USER}'@'localhost' IDENTIFIED BY '${WSREP_SST_PASSWORD}';" >> "$tempSqlFile" - echo "GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO '${WSREP_SST_USER}'@'localhost';" >> "$tempSqlFile" - fi - - echo 'FLUSH PRIVILEGES ;' >> "$tempSqlFile" - - # Add the SQL file to mysqld's command line args - set -- "$@" --init-file="$tempSqlFile" - fi - - chown -R mysql:mysql "$DATADIR" -fi - -# if cluster is turned on, then proceed to build cluster setting strings -# that will be interpolated into the config files -if [ -n "$GALERA_CLUSTER" ]; then - # this is the Single State Transfer user (SST, initial dump or xtrabackup user) - WSREP_SST_USER=${WSREP_SST_USER:-"sst"} - if [ -z "$WSREP_SST_PASSWORD" ]; then - echo >&2 'error: database is uninitialized and WSREP_SST_PASSWORD not set' - echo >&2 ' Did you forget to add -e WSREP_SST_PASSWORD=xxx ?' - exit 1 - fi - - # user/password for SST user - sed -i -e "s|^wsrep_sst_auth=sstuser:changethis|wsrep_sst_auth=${WSREP_SST_USER}:${WSREP_SST_PASSWORD}|" /etc/mysql/conf.d/cluster.cnf - - # set nodes own address - WSREP_NODE_ADDRESS=`ip addr show | grep -E '^[ ]*inet' | grep -m1 global | awk '{ print $2 }' | sed -e 's/\/.*//'` - if [ -n "$WSREP_NODE_ADDRESS" ]; then - sed -i -e "s|^wsrep_node_address=.*$|wsrep_node_address=${WSREP_NODE_ADDRESS}|" /etc/mysql/conf.d/cluster.cnf - fi - - # if the string is not defined or it only is 'gcomm://', this means bootstrap - if [ -z "$WSREP_CLUSTER_ADDRESS" -o "$WSREP_CLUSTER_ADDRESS" == "gcomm://" ]; then - # if empty, set to 'gcomm://' - # NOTE: this list does not imply membership. - # It only means "obtain SST and join from one of these..." - if [ -z "$WSREP_CLUSTER_ADDRESS" ]; then - WSREP_CLUSTER_ADDRESS="gcomm://" - fi - - # loop through number of nodes - for NUM in `seq 1 $NUM_NODES`; do - NODE_SERVICE_HOST="PXC_NODE${NUM}_SERVICE_HOST" - - # if set - if [ -n "${!NODE_SERVICE_HOST}" ]; then - # if not its own IP, then add it - if [ $(expr "$HOSTNAME" : "pxc-node${NUM}") -eq 0 ]; then - # if not the first bootstrap node add comma - if [ $WSREP_CLUSTER_ADDRESS != "gcomm://" ]; then - WSREP_CLUSTER_ADDRESS="${WSREP_CLUSTER_ADDRESS}," - fi - # append - # if user specifies USE_IP, use that - if [ -n "${USE_IP}" ]; then - WSREP_CLUSTER_ADDRESS="${WSREP_CLUSTER_ADDRESS}"${!NODE_SERVICE_HOST} - # otherwise use DNS - else - WSREP_CLUSTER_ADDRESS="${WSREP_CLUSTER_ADDRESS}pxc-node${NUM}" - fi - fi - fi - done - fi - - # WSREP_CLUSTER_ADDRESS is now complete and will be interpolated into the - # cluster address string (wsrep_cluster_address) in the cluster - # configuration file, cluster.cnf - if [ -n "$WSREP_CLUSTER_ADDRESS" -a "$WSREP_CLUSTER_ADDRESS" != "gcomm://" ]; then - sed -i -e "s|^wsrep_cluster_address=gcomm://|wsrep_cluster_address=${WSREP_CLUSTER_ADDRESS}|" /etc/mysql/conf.d/cluster.cnf - fi -fi - -# random server ID needed -sed -i -e "s/^server\-id=.*$/server-id=${RANDOM}/" /etc/mysql/my.cnf - -# finally, start mysql -exec "$@" diff --git a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/my.cnf b/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/my.cnf deleted file mode 100644 index 078bd6fe6..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/image/my.cnf +++ /dev/null @@ -1,55 +0,0 @@ -[client] -port=3306 -socket=/var/run/mysqld/mysqld.sock - -[mysqld_safe] -socket=/var/run/mysqld/mysqld.sock -nice=0 - -[mysqld] -user=mysql -pid-file=/var/run/mysqld/mysqld.pid -socket=/var/run/mysqld/mysqld.sock -port=3306 -basedir=/usr -datadir=/var/lib/mysql -tmpdir=/tmp -lc-messages-dir=/usr/share/mysql -skip-external-locking - -key_buffer=16M -max_allowed_packet=16M -thread_stack=192K -thread_cache_size=8 - -myisam-recover=BACKUP -#max_connections=100 -query_cache_limit=1M -query_cache_size=16M -slow_query_log=1 -slow_query_log_file=/var/log/mysql/mysql-slow.log -long_query_time=2 -log-queries-not-using-indexes - -server-id=12345 -log_bin=/var/log/mysql/mysql-bin.log -expire_logs_days=4 -max_binlog_size=100M - -default_storage_engine=InnoDB -innodb_file_per_table -innodb_log_file_size=100M -innodb_log_buffer_size=10M -innodb_log_files_in_group=2 -innodb_buffer_pool_instances=4 -innodb_buffer_pool_size=100M - -[mysqldump] -quick -quote-names -max_allowed_packet=16M - -[isamchk] -key_buffer=16M - -!includedir /etc/mysql/conf.d/ diff --git a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-cluster-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-cluster-service.yaml deleted file mode 100644 index f0bfd5e9a..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-cluster-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: pxc-cluster - labels: - unit: pxc-cluster -spec: - ports: - - port: 3306 - name: mysql - selector: - unit: pxc-cluster \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-node1.yaml b/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-node1.yaml deleted file mode 100644 index fa1163bdc..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-node1.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: pxc-node1 - labels: - node: pxc-node1 -spec: - ports: - - port: 3306 - name: mysql - - port: 4444 - name: state-snapshot-transfer - - port: 4567 - name: replication-traffic - - port: 4568 - name: incremental-state-transfer - selector: - node: pxc-node1 ---- -apiVersion: v1 -kind: ReplicationController -metadata: - name: pxc-node1 -spec: - replicas: 1 - template: - metadata: - labels: - node: pxc-node1 - unit: pxc-cluster - spec: - containers: - - resources: - limits: - cpu: 0.3 - image: capttofu/percona_xtradb_cluster_5_6:beta - name: pxc-node1 - ports: - - containerPort: 3306 - - containerPort: 4444 - - containerPort: 4567 - - containerPort: 4568 - env: - - name: GALERA_CLUSTER - value: "true" - - name: WSREP_CLUSTER_ADDRESS - value: gcomm:// - - name: WSREP_SST_USER - value: sst - - name: WSREP_SST_PASSWORD - value: sst - - name: MYSQL_USER - value: mysql - - name: MYSQL_PASSWORD - value: mysql - - name: MYSQL_ROOT_PASSWORD - value: c-krit diff --git a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-node2.yaml b/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-node2.yaml deleted file mode 100644 index ead3675d7..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-node2.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: pxc-node2 - labels: - node: pxc-node2 -spec: - ports: - - port: 3306 - name: mysql - - port: 4444 - name: state-snapshot-transfer - - port: 4567 - name: replication-traffic - - port: 4568 - name: incremental-state-transfer - selector: - node: pxc-node2 - ---- -apiVersion: v1 -kind: ReplicationController -metadata: - name: pxc-node2 -spec: - replicas: 1 - template: - metadata: - labels: - node: pxc-node2 - unit: pxc-cluster - spec: - containers: - - resources: - limits: - cpu: 0.3 - image: capttofu/percona_xtradb_cluster_5_6:beta - name: pxc-node2 - ports: - - containerPort: 3306 - - containerPort: 4444 - - containerPort: 4567 - - containerPort: 4568 - env: - - name: GALERA_CLUSTER - value: "true" - - name: WSREP_CLUSTER_ADDRESS - value: gcomm:// - - name: WSREP_SST_USER - value: sst - - name: WSREP_SST_PASSWORD - value: sst - - name: MYSQL_USER - value: mysql - - name: MYSQL_PASSWORD - value: mysql - - name: MYSQL_ROOT_PASSWORD - value: c-krit diff --git a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-node3.yaml b/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-node3.yaml deleted file mode 100644 index fbb368b27..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/mysql-galera/pxc-node3.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: pxc-node3 - labels: - node: pxc-node3 -spec: - ports: - - port: 3306 - name: mysql - - port: 4444 - name: state-snapshot-transfer - - port: 4567 - name: replication-traffic - - port: 4568 - name: incremental-state-transfer - selector: - node: pxc-node3 - ---- -apiVersion: v1 -kind: ReplicationController -metadata: - name: pxc-node3 -spec: - replicas: 1 - template: - metadata: - labels: - node: pxc-node3 - unit: pxc-cluster - spec: - containers: - - resources: - limits: - cpu: 0.3 - image: capttofu/percona_xtradb_cluster_5_6:beta - name: pxc-node3 - ports: - - containerPort: 3306 - - containerPort: 4444 - - containerPort: 4567 - - containerPort: 4568 - env: - - name: GALERA_CLUSTER - value: "true" - - name: WSREP_CLUSTER_ADDRESS - value: gcomm:// - - name: WSREP_SST_USER - value: sst - - name: WSREP_SST_PASSWORD - value: sst - - name: MYSQL_USER - value: mysql - - name: MYSQL_PASSWORD - value: mysql - - name: MYSQL_ROOT_PASSWORD - value: c-krit diff --git a/vendor/k8s.io/kubernetes/examples/storage/redis/README.md b/vendor/k8s.io/kubernetes/examples/storage/redis/README.md deleted file mode 100644 index c24b9702f..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/redis/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/storage/redis/README.md](https://github.com/kubernetes/examples/blob/master/staging/storage/redis/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/storage/redis/image/Dockerfile b/vendor/k8s.io/kubernetes/examples/storage/redis/image/Dockerfile deleted file mode 100644 index 9f619a5ad..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/redis/image/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# 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. - -FROM alpine:3.4 - -RUN apk add --no-cache redis sed bash - -COPY redis-master.conf /redis-master/redis.conf -COPY redis-slave.conf /redis-slave/redis.conf -COPY run.sh /run.sh - -CMD [ "/run.sh" ] - -ENTRYPOINT [ "bash", "-c" ] diff --git a/vendor/k8s.io/kubernetes/examples/storage/redis/image/redis-master.conf b/vendor/k8s.io/kubernetes/examples/storage/redis/image/redis-master.conf deleted file mode 100644 index 29ae1bb41..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/redis/image/redis-master.conf +++ /dev/null @@ -1,828 +0,0 @@ -# Redis configuration file example - -# Note on units: when memory size is needed, it is possible to specify -# it in the usual form of 1k 5GB 4M and so forth: -# -# 1k => 1000 bytes -# 1kb => 1024 bytes -# 1m => 1000000 bytes -# 1mb => 1024*1024 bytes -# 1g => 1000000000 bytes -# 1gb => 1024*1024*1024 bytes -# -# units are case insensitive so 1GB 1Gb 1gB are all the same. - -################################## INCLUDES ################################### - -# Include one or more other config files here. This is useful if you -# have a standard template that goes to all Redis servers but also need -# to customize a few per-server settings. Include files can include -# other files, so use this wisely. -# -# Notice option "include" won't be rewritten by command "CONFIG REWRITE" -# from admin or Redis Sentinel. Since Redis always uses the last processed -# line as value of a configuration directive, you'd better put includes -# at the beginning of this file to avoid overwriting config change at runtime. -# -# If instead you are interested in using includes to override configuration -# options, it is better to use include as the last line. -# -# include /path/to/local.conf -# include /path/to/other.conf - -################################ GENERAL ##################################### - -# By default Redis does not run as a daemon. Use 'yes' if you need it. -# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. -daemonize no - -# When running daemonized, Redis writes a pid file in /var/run/redis.pid by -# default. You can specify a custom pid file location here. -pidfile /var/run/redis.pid - -# Accept connections on the specified port, default is 6379. -# If port 0 is specified Redis will not listen on a TCP socket. -port 6379 - -# TCP listen() backlog. -# -# In high requests-per-second environments you need an high backlog in order -# to avoid slow clients connections issues. Note that the Linux kernel -# will silently truncate it to the value of /proc/sys/net/core/somaxconn so -# make sure to raise both the value of somaxconn and tcp_max_syn_backlog -# in order to get the desired effect. -tcp-backlog 511 - -# By default Redis listens for connections from all the network interfaces -# available on the server. It is possible to listen to just one or multiple -# interfaces using the "bind" configuration directive, followed by one or -# more IP addresses. -# -# Examples: -# -# bind 192.168.1.100 10.0.0.1 - -bind 0.0.0.0 - -# Specify the path for the Unix socket that will be used to listen for -# incoming connections. There is no default, so Redis will not listen -# on a unix socket when not specified. -# -# unixsocket /tmp/redis.sock -# unixsocketperm 700 - -# Close the connection after a client is idle for N seconds (0 to disable) -timeout 0 - -# TCP keepalive. -# -# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence -# of communication. This is useful for two reasons: -# -# 1) Detect dead peers. -# 2) Take the connection alive from the point of view of network -# equipment in the middle. -# -# On Linux, the specified value (in seconds) is the period used to send ACKs. -# Note that to close the connection the double of the time is needed. -# On other kernels the period depends on the kernel configuration. -# -# A reasonable value for this option is 60 seconds. -tcp-keepalive 60 - -# Specify the server verbosity level. -# This can be one of: -# debug (a lot of information, useful for development/testing) -# verbose (many rarely useful info, but not a mess like the debug level) -# notice (moderately verbose, what you want in production probably) -# warning (only very important / critical messages are logged) -loglevel notice - -# Specify the log file name. Also the empty string can be used to force -# Redis to log on the standard output. Note that if you use standard -# output for logging but daemonize, logs will be sent to /dev/null -logfile "" - -# To enable logging to the system logger, just set 'syslog-enabled' to yes, -# and optionally update the other syslog parameters to suit your needs. -# syslog-enabled no - -# Specify the syslog identity. -# syslog-ident redis - -# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. -# syslog-facility local0 - -# Set the number of databases. The default database is DB 0, you can select -# a different one on a per-connection basis using SELECT where -# dbid is a number between 0 and 'databases'-1 -databases 16 - -################################ SNAPSHOTTING ################################ -# -# Save the DB on disk: -# -# save -# -# Will save the DB if both the given number of seconds and the given -# number of write operations against the DB occurred. -# -# In the example below the behaviour will be to save: -# after 900 sec (15 min) if at least 1 key changed -# after 300 sec (5 min) if at least 10 keys changed -# after 60 sec if at least 10000 keys changed -# -# Note: you can disable saving completely by commenting out all "save" lines. -# -# It is also possible to remove all the previously configured save -# points by adding a save directive with a single empty string argument -# like in the following example: -# -# save "" - -save 900 1 -save 300 10 -save 60 10000 - -# By default Redis will stop accepting writes if RDB snapshots are enabled -# (at least one save point) and the latest background save failed. -# This will make the user aware (in a hard way) that data is not persisting -# on disk properly, otherwise chances are that no one will notice and some -# disaster will happen. -# -# If the background saving process will start working again Redis will -# automatically allow writes again. -# -# However if you have setup your proper monitoring of the Redis server -# and persistence, you may want to disable this feature so that Redis will -# continue to work as usual even if there are problems with disk, -# permissions, and so forth. -stop-writes-on-bgsave-error yes - -# Compress string objects using LZF when dump .rdb databases? -# For default that's set to 'yes' as it's almost always a win. -# If you want to save some CPU in the saving child set it to 'no' but -# the dataset will likely be bigger if you have compressible values or keys. -rdbcompression yes - -# Since version 5 of RDB a CRC64 checksum is placed at the end of the file. -# This makes the format more resistant to corruption but there is a performance -# hit to pay (around 10%) when saving and loading RDB files, so you can disable it -# for maximum performances. -# -# RDB files created with checksum disabled have a checksum of zero that will -# tell the loading code to skip the check. -rdbchecksum yes - -# The filename where to dump the DB -dbfilename dump.rdb - -# The working directory. -# -# The DB will be written inside this directory, with the filename specified -# above using the 'dbfilename' configuration directive. -# -# The Append Only File will also be created inside this directory. -# -# Note that you must specify a directory here, not a file name. -dir /redis-master-data - -################################# REPLICATION ################################# - -# Master-Slave replication. Use slaveof to make a Redis instance a copy of -# another Redis server. A few things to understand ASAP about Redis replication. -# -# 1) Redis replication is asynchronous, but you can configure a master to -# stop accepting writes if it appears to be not connected with at least -# a given number of slaves. -# 2) Redis slaves are able to perform a partial resynchronization with the -# master if the replication link is lost for a relatively small amount of -# time. You may want to configure the replication backlog size (see the next -# sections of this file) with a sensible value depending on your needs. -# 3) Replication is automatic and does not need user intervention. After a -# network partition slaves automatically try to reconnect to masters -# and resynchronize with them. -# -# slaveof - -# If the master is password protected (using the "requirepass" configuration -# directive below) it is possible to tell the slave to authenticate before -# starting the replication synchronization process, otherwise the master will -# refuse the slave request. -# -# masterauth - -# When a slave loses its connection with the master, or when the replication -# is still in progress, the slave can act in two different ways: -# -# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will -# still reply to client requests, possibly with out of date data, or the -# data set may just be empty if this is the first synchronization. -# -# 2) if slave-serve-stale-data is set to 'no' the slave will reply with -# an error "SYNC with master in progress" to all the kind of commands -# but to INFO and SLAVEOF. -# -slave-serve-stale-data yes - -# You can configure a slave instance to accept writes or not. Writing against -# a slave instance may be useful to store some ephemeral data (because data -# written on a slave will be easily deleted after resync with the master) but -# may also cause problems if clients are writing to it because of a -# misconfiguration. -# -# Since Redis 2.6 by default slaves are read-only. -# -# Note: read only slaves are not designed to be exposed to untrusted clients -# on the internet. It's just a protection layer against misuse of the instance. -# Still a read only slave exports by default all the administrative commands -# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve -# security of read only slaves using 'rename-command' to shadow all the -# administrative / dangerous commands. -slave-read-only yes - -# Replication SYNC strategy: disk or socket. -# -# ------------------------------------------------------- -# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY -# ------------------------------------------------------- -# -# New slaves and reconnecting slaves that are not able to continue the replication -# process just receiving differences, need to do what is called a "full -# synchronization". An RDB file is transmitted from the master to the slaves. -# The transmission can happen in two different ways: -# -# 1) Disk-backed: The Redis master creates a new process that writes the RDB -# file on disk. Later the file is transferred by the parent -# process to the slaves incrementally. -# 2) Diskless: The Redis master creates a new process that directly writes the -# RDB file to slave sockets, without touching the disk at all. -# -# With disk-backed replication, while the RDB file is generated, more slaves -# can be queued and served with the RDB file as soon as the current child producing -# the RDB file finishes its work. With diskless replication instead once -# the transfer starts, new slaves arriving will be queued and a new transfer -# will start when the current one terminates. -# -# When diskless replication is used, the master waits a configurable amount of -# time (in seconds) before starting the transfer in the hope that multiple slaves -# will arrive and the transfer can be parallelized. -# -# With slow disks and fast (large bandwidth) networks, diskless replication -# works better. -repl-diskless-sync no - -# When diskless replication is enabled, it is possible to configure the delay -# the server waits in order to spawn the child that trnasfers the RDB via socket -# to the slaves. -# -# This is important since once the transfer starts, it is not possible to serve -# new slaves arriving, that will be queued for the next RDB transfer, so the server -# waits a delay in order to let more slaves arrive. -# -# The delay is specified in seconds, and by default is 5 seconds. To disable -# it entirely just set it to 0 seconds and the transfer will start ASAP. -repl-diskless-sync-delay 5 - -# Slaves send PINGs to server in a predefined interval. It's possible to change -# this interval with the repl_ping_slave_period option. The default value is 10 -# seconds. -# -# repl-ping-slave-period 10 - -# The following option sets the replication timeout for: -# -# 1) Bulk transfer I/O during SYNC, from the point of view of slave. -# 2) Master timeout from the point of view of slaves (data, pings). -# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings). -# -# It is important to make sure that this value is greater than the value -# specified for repl-ping-slave-period otherwise a timeout will be detected -# every time there is low traffic between the master and the slave. -# -# repl-timeout 60 - -# Disable TCP_NODELAY on the slave socket after SYNC? -# -# If you select "yes" Redis will use a smaller number of TCP packets and -# less bandwidth to send data to slaves. But this can add a delay for -# the data to appear on the slave side, up to 40 milliseconds with -# Linux kernels using a default configuration. -# -# If you select "no" the delay for data to appear on the slave side will -# be reduced but more bandwidth will be used for replication. -# -# By default we optimize for low latency, but in very high traffic conditions -# or when the master and slaves are many hops away, turning this to "yes" may -# be a good idea. -repl-disable-tcp-nodelay no - -# Set the replication backlog size. The backlog is a buffer that accumulates -# slave data when slaves are disconnected for some time, so that when a slave -# wants to reconnect again, often a full resync is not needed, but a partial -# resync is enough, just passing the portion of data the slave missed while -# disconnected. -# -# The bigger the replication backlog, the longer the time the slave can be -# disconnected and later be able to perform a partial resynchronization. -# -# The backlog is only allocated once there is at least a slave connected. -# -# repl-backlog-size 1mb - -# After a master has no longer connected slaves for some time, the backlog -# will be freed. The following option configures the amount of seconds that -# need to elapse, starting from the time the last slave disconnected, for -# the backlog buffer to be freed. -# -# A value of 0 means to never release the backlog. -# -# repl-backlog-ttl 3600 - -# The slave priority is an integer number published by Redis in the INFO output. -# It is used by Redis Sentinel in order to select a slave to promote into a -# master if the master is no longer working correctly. -# -# A slave with a low priority number is considered better for promotion, so -# for instance if there are three slaves with priority 10, 100, 25 Sentinel will -# pick the one with priority 10, that is the lowest. -# -# However a special priority of 0 marks the slave as not able to perform the -# role of master, so a slave with priority of 0 will never be selected by -# Redis Sentinel for promotion. -# -# By default the priority is 100. -slave-priority 100 - -# It is possible for a master to stop accepting writes if there are less than -# N slaves connected, having a lag less or equal than M seconds. -# -# The N slaves need to be in "online" state. -# -# The lag in seconds, that must be <= the specified value, is calculated from -# the last ping received from the slave, that is usually sent every second. -# -# This option does not GUARANTEE that N replicas will accept the write, but -# will limit the window of exposure for lost writes in case not enough slaves -# are available, to the specified number of seconds. -# -# For example to require at least 3 slaves with a lag <= 10 seconds use: -# -# min-slaves-to-write 3 -# min-slaves-max-lag 10 -# -# Setting one or the other to 0 disables the feature. -# -# By default min-slaves-to-write is set to 0 (feature disabled) and -# min-slaves-max-lag is set to 10. - -################################## SECURITY ################################### - -# Require clients to issue AUTH before processing any other -# commands. This might be useful in environments in which you do not trust -# others with access to the host running redis-server. -# -# This should stay commented out for backward compatibility and because most -# people do not need auth (e.g. they run their own servers). -# -# Warning: since Redis is pretty fast an outside user can try up to -# 150k passwords per second against a good box. This means that you should -# use a very strong password otherwise it will be very easy to break. -# -# requirepass foobared - -# Command renaming. -# -# It is possible to change the name of dangerous commands in a shared -# environment. For instance the CONFIG command may be renamed into something -# hard to guess so that it will still be available for internal-use tools -# but not available for general clients. -# -# Example: -# -# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 -# -# It is also possible to completely kill a command by renaming it into -# an empty string: -# -# rename-command CONFIG "" -# -# Please note that changing the name of commands that are logged into the -# AOF file or transmitted to slaves may cause problems. - -################################### LIMITS #################################### - -# Set the max number of connected clients at the same time. By default -# this limit is set to 10000 clients, however if the Redis server is not -# able to configure the process file limit to allow for the specified limit -# the max number of allowed clients is set to the current file limit -# minus 32 (as Redis reserves a few file descriptors for internal uses). -# -# Once the limit is reached Redis will close all the new connections sending -# an error 'max number of clients reached'. -# -# maxclients 10000 - -# Don't use more memory than the specified amount of bytes. -# When the memory limit is reached Redis will try to remove keys -# according to the eviction policy selected (see maxmemory-policy). -# -# If Redis can't remove keys according to the policy, or if the policy is -# set to 'noeviction', Redis will start to reply with errors to commands -# that would use more memory, like SET, LPUSH, and so on, and will continue -# to reply to read-only commands like GET. -# -# This option is usually useful when using Redis as an LRU cache, or to set -# a hard memory limit for an instance (using the 'noeviction' policy). -# -# WARNING: If you have slaves attached to an instance with maxmemory on, -# the size of the output buffers needed to feed the slaves are subtracted -# from the used memory count, so that network problems / resyncs will -# not trigger a loop where keys are evicted, and in turn the output -# buffer of slaves is full with DELs of keys evicted triggering the deletion -# of more keys, and so forth until the database is completely emptied. -# -# In short... if you have slaves attached it is suggested that you set a lower -# limit for maxmemory so that there is some free RAM on the system for slave -# output buffers (but this is not needed if the policy is 'noeviction'). -# -# maxmemory - -# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory -# is reached. You can select among five behaviors: -# -# volatile-lru -> remove the key with an expire set using an LRU algorithm -# allkeys-lru -> remove any key according to the LRU algorithm -# volatile-random -> remove a random key with an expire set -# allkeys-random -> remove a random key, any key -# volatile-ttl -> remove the key with the nearest expire time (minor TTL) -# noeviction -> don't expire at all, just return an error on write operations -# -# Note: with any of the above policies, Redis will return an error on write -# operations, when there are no suitable keys for eviction. -# -# At the date of writing these commands are: set setnx setex append -# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd -# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby -# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby -# getset mset msetnx exec sort -# -# The default is: -# -# maxmemory-policy volatile-lru - -# LRU and minimal TTL algorithms are not precise algorithms but approximated -# algorithms (in order to save memory), so you can select as well the sample -# size to check. For instance for default Redis will check three keys and -# pick the one that was used less recently, you can change the sample size -# using the following configuration directive. -# -# maxmemory-samples 3 - -############################## APPEND ONLY MODE ############################### - -# By default Redis asynchronously dumps the dataset on disk. This mode is -# good enough in many applications, but an issue with the Redis process or -# a power outage may result into a few minutes of writes lost (depending on -# the configured save points). -# -# The Append Only File is an alternative persistence mode that provides -# much better durability. For instance using the default data fsync policy -# (see later in the config file) Redis can lose just one second of writes in a -# dramatic event like a server power outage, or a single write if something -# wrong with the Redis process itself happens, but the operating system is -# still running correctly. -# -# AOF and RDB persistence can be enabled at the same time without problems. -# If the AOF is enabled on startup Redis will load the AOF, that is the file -# with the better durability guarantees. -# -# Please check http://redis.io/topics/persistence for more information. - -appendonly yes - -# The name of the append only file (default: "appendonly.aof") - -appendfilename "appendonly.aof" - -# The fsync() call tells the Operating System to actually write data on disk -# instead of waiting for more data in the output buffer. Some OS will really flush -# data on disk, some other OS will just try to do it ASAP. -# -# Redis supports three different modes: -# -# no: don't fsync, just let the OS flush the data when it wants. Faster. -# always: fsync after every write to the append only log. Slow, Safest. -# everysec: fsync only one time every second. Compromise. -# -# The default is "everysec", as that's usually the right compromise between -# speed and data safety. It's up to you to understand if you can relax this to -# "no" that will let the operating system flush the output buffer when -# it wants, for better performances (but if you can live with the idea of -# some data loss consider the default persistence mode that's snapshotting), -# or on the contrary, use "always" that's very slow but a bit safer than -# everysec. -# -# More details please check the following article: -# http://antirez.com/post/redis-persistence-demystified.html -# -# If unsure, use "everysec". - -# appendfsync always -appendfsync everysec -# appendfsync no - -# When the AOF fsync policy is set to always or everysec, and a background -# saving process (a background save or AOF log background rewriting) is -# performing a lot of I/O against the disk, in some Linux configurations -# Redis may block too long on the fsync() call. Note that there is no fix for -# this currently, as even performing fsync in a different thread will block -# our synchronous write(2) call. -# -# In order to mitigate this problem it's possible to use the following option -# that will prevent fsync() from being called in the main process while a -# BGSAVE or BGREWRITEAOF is in progress. -# -# This means that while another child is saving, the durability of Redis is -# the same as "appendfsync none". In practical terms, this means that it is -# possible to lose up to 30 seconds of log in the worst scenario (with the -# default Linux settings). -# -# If you have latency problems turn this to "yes". Otherwise leave it as -# "no" that is the safest pick from the point of view of durability. - -no-appendfsync-on-rewrite no - -# Automatic rewrite of the append only file. -# Redis is able to automatically rewrite the log file implicitly calling -# BGREWRITEAOF when the AOF log size grows by the specified percentage. -# -# This is how it works: Redis remembers the size of the AOF file after the -# latest rewrite (if no rewrite has happened since the restart, the size of -# the AOF at startup is used). -# -# This base size is compared to the current size. If the current size is -# bigger than the specified percentage, the rewrite is triggered. Also -# you need to specify a minimal size for the AOF file to be rewritten, this -# is useful to avoid rewriting the AOF file even if the percentage increase -# is reached but it is still pretty small. -# -# Specify a percentage of zero in order to disable the automatic AOF -# rewrite feature. - -auto-aof-rewrite-percentage 100 -auto-aof-rewrite-min-size 64mb - -# An AOF file may be found to be truncated at the end during the Redis -# startup process, when the AOF data gets loaded back into memory. -# This may happen when the system where Redis is running -# crashes, especially when an ext4 filesystem is mounted without the -# data=ordered option (however this can't happen when Redis itself -# crashes or aborts but the operating system still works correctly). -# -# Redis can either exit with an error when this happens, or load as much -# data as possible (the default now) and start if the AOF file is found -# to be truncated at the end. The following option controls this behavior. -# -# If aof-load-truncated is set to yes, a truncated AOF file is loaded and -# the Redis server starts emitting a log to inform the user of the event. -# Otherwise if the option is set to no, the server aborts with an error -# and refuses to start. When the option is set to no, the user requires -# to fix the AOF file using the "redis-check-aof" utility before to restart -# the server. -# -# Note that if the AOF file will be found to be corrupted in the middle -# the server will still exit with an error. This option only applies when -# Redis will try to read more data from the AOF file but not enough bytes -# will be found. -aof-load-truncated yes - -################################ LUA SCRIPTING ############################### - -# Max execution time of a Lua script in milliseconds. -# -# If the maximum execution time is reached Redis will log that a script is -# still in execution after the maximum allowed time and will start to -# reply to queries with an error. -# -# When a long running script exceeds the maximum execution time only the -# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be -# used to stop a script that did not yet called write commands. The second -# is the only way to shut down the server in the case a write command was -# already issued by the script but the user doesn't want to wait for the natural -# termination of the script. -# -# Set it to 0 or a negative value for unlimited execution without warnings. -lua-time-limit 5000 - -################################## SLOW LOG ################################### - -# The Redis Slow Log is a system to log queries that exceeded a specified -# execution time. The execution time does not include the I/O operations -# like talking with the client, sending the reply and so forth, -# but just the time needed to actually execute the command (this is the only -# stage of command execution where the thread is blocked and can not serve -# other requests in the meantime). -# -# You can configure the slow log with two parameters: one tells Redis -# what is the execution time, in microseconds, to exceed in order for the -# command to get logged, and the other parameter is the length of the -# slow log. When a new command is logged the oldest one is removed from the -# queue of logged commands. - -# The following time is expressed in microseconds, so 1000000 is equivalent -# to one second. Note that a negative number disables the slow log, while -# a value of zero forces the logging of every command. -slowlog-log-slower-than 10000 - -# There is no limit to this length. Just be aware that it will consume memory. -# You can reclaim memory used by the slow log with SLOWLOG RESET. -slowlog-max-len 128 - -################################ LATENCY MONITOR ############################## - -# The Redis latency monitoring subsystem samples different operations -# at runtime in order to collect data related to possible sources of -# latency of a Redis instance. -# -# Via the LATENCY command this information is available to the user that can -# print graphs and obtain reports. -# -# The system only logs operations that were performed in a time equal or -# greater than the amount of milliseconds specified via the -# latency-monitor-threshold configuration directive. When its value is set -# to zero, the latency monitor is turned off. -# -# By default latency monitoring is disabled since it is mostly not needed -# if you don't have latency issues, and collecting data has a performance -# impact, that while very small, can be measured under big load. Latency -# monitoring can easily be enabled at runtime using the command -# "CONFIG SET latency-monitor-threshold " if needed. -latency-monitor-threshold 0 - -############################# Event notification ############################## - -# Redis can notify Pub/Sub clients about events happening in the key space. -# This feature is documented at http://redis.io/topics/notifications -# -# For instance if keyspace events notification is enabled, and a client -# performs a DEL operation on key "foo" stored in the Database 0, two -# messages will be published via Pub/Sub: -# -# PUBLISH __keyspace@0__:foo del -# PUBLISH __keyevent@0__:del foo -# -# It is possible to select the events that Redis will notify among a set -# of classes. Every class is identified by a single character: -# -# K Keyspace events, published with __keyspace@__ prefix. -# E Keyevent events, published with __keyevent@__ prefix. -# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... -# $ String commands -# l List commands -# s Set commands -# h Hash commands -# z Sorted set commands -# x Expired events (events generated every time a key expires) -# e Evicted events (events generated when a key is evicted for maxmemory) -# A Alias for g$lshzxe, so that the "AKE" string means all the events. -# -# The "notify-keyspace-events" takes as argument a string that is composed -# of zero or multiple characters. The empty string means that notifications -# are disabled. -# -# Example: to enable list and generic events, from the point of view of the -# event name, use: -# -# notify-keyspace-events Elg -# -# Example 2: to get the stream of the expired keys subscribing to channel -# name __keyevent@0__:expired use: -# -# notify-keyspace-events Ex -# -# By default all notifications are disabled because most users don't need -# this feature and the feature has some overhead. Note that if you don't -# specify at least one of K or E, no events will be delivered. -notify-keyspace-events "" - -############################### ADVANCED CONFIG ############################### - -# Hashes are encoded using a memory efficient data structure when they have a -# small number of entries, and the biggest entry does not exceed a given -# threshold. These thresholds can be configured using the following directives. -hash-max-ziplist-entries 512 -hash-max-ziplist-value 64 - -# Similarly to hashes, small lists are also encoded in a special way in order -# to save a lot of space. The special representation is only used when -# you are under the following limits: -list-max-ziplist-entries 512 -list-max-ziplist-value 64 - -# Sets have a special encoding in just one case: when a set is composed -# of just strings that happen to be integers in radix 10 in the range -# of 64 bit signed integers. -# The following configuration setting sets the limit in the size of the -# set in order to use this special memory saving encoding. -set-max-intset-entries 512 - -# Similarly to hashes and lists, sorted sets are also specially encoded in -# order to save a lot of space. This encoding is only used when the length and -# elements of a sorted set are below the following limits: -zset-max-ziplist-entries 128 -zset-max-ziplist-value 64 - -# HyperLogLog sparse representation bytes limit. The limit includes the -# 16 bytes header. When an HyperLogLog using the sparse representation crosses -# this limit, it is converted into the dense representation. -# -# A value greater than 16000 is totally useless, since at that point the -# dense representation is more memory efficient. -# -# The suggested value is ~ 3000 in order to have the benefits of -# the space efficient encoding without slowing down too much PFADD, -# which is O(N) with the sparse encoding. The value can be raised to -# ~ 10000 when CPU is not a concern, but space is, and the data set is -# composed of many HyperLogLogs with cardinality in the 0 - 15000 range. -hll-sparse-max-bytes 3000 - -# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in -# order to help rehashing the main Redis hash table (the one mapping top-level -# keys to values). The hash table implementation Redis uses (see dict.c) -# performs a lazy rehashing: the more operation you run into a hash table -# that is rehashing, the more rehashing "steps" are performed, so if the -# server is idle the rehashing is never complete and some more memory is used -# by the hash table. -# -# The default is to use this millisecond 10 times every second in order to -# actively rehash the main dictionaries, freeing memory when possible. -# -# If unsure: -# use "activerehashing no" if you have hard latency requirements and it is -# not a good thing in your environment that Redis can reply from time to time -# to queries with 2 milliseconds delay. -# -# use "activerehashing yes" if you don't have such hard requirements but -# want to free memory asap when possible. -activerehashing yes - -# The client output buffer limits can be used to force disconnection of clients -# that are not reading data from the server fast enough for some reason (a -# common reason is that a Pub/Sub client can't consume messages as fast as the -# publisher can produce them). -# -# The limit can be set differently for the three different classes of clients: -# -# normal -> normal clients including MONITOR clients -# slave -> slave clients -# pubsub -> clients subscribed to at least one pubsub channel or pattern -# -# The syntax of every client-output-buffer-limit directive is the following: -# -# client-output-buffer-limit -# -# A client is immediately disconnected once the hard limit is reached, or if -# the soft limit is reached and remains reached for the specified number of -# seconds (continuously). -# So for instance if the hard limit is 32 megabytes and the soft limit is -# 16 megabytes / 10 seconds, the client will get disconnected immediately -# if the size of the output buffers reach 32 megabytes, but will also get -# disconnected if the client reaches 16 megabytes and continuously overcomes -# the limit for 10 seconds. -# -# By default normal clients are not limited because they don't receive data -# without asking (in a push way), but just after a request, so only -# asynchronous clients may create a scenario where data is requested faster -# than it can read. -# -# Instead there is a default limit for pubsub and slave clients, since -# subscribers and slaves receive data in a push fashion. -# -# Both the hard or the soft limit can be disabled by setting them to zero. -client-output-buffer-limit normal 0 0 0 -client-output-buffer-limit slave 256mb 64mb 60 -client-output-buffer-limit pubsub 32mb 8mb 60 - -# Redis calls an internal function to perform many background tasks, like -# closing connections of clients in timeout, purging expired keys that are -# never requested, and so forth. -# -# Not all tasks are performed with the same frequency, but Redis checks for -# tasks to perform according to the specified "hz" value. -# -# By default "hz" is set to 10. Raising the value will use more CPU when -# Redis is idle, but at the same time will make Redis more responsive when -# there are many keys expiring at the same time, and timeouts may be -# handled with more precision. -# -# The range is between 1 and 500, however a value over 100 is usually not -# a good idea. Most users should use the default of 10 and raise this up to -# 100 only in environments where very low latency is required. -hz 10 - -# When a child rewrites the AOF file, if the following option is enabled -# the file will be fsync-ed every 32 MB of data generated. This is useful -# in order to commit the file to the disk more incrementally and avoid -# big latency spikes. -aof-rewrite-incremental-fsync yes diff --git a/vendor/k8s.io/kubernetes/examples/storage/redis/image/redis-slave.conf b/vendor/k8s.io/kubernetes/examples/storage/redis/image/redis-slave.conf deleted file mode 100644 index afd0a45fd..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/redis/image/redis-slave.conf +++ /dev/null @@ -1,828 +0,0 @@ -# Redis configuration file example - -# Note on units: when memory size is needed, it is possible to specify -# it in the usual form of 1k 5GB 4M and so forth: -# -# 1k => 1000 bytes -# 1kb => 1024 bytes -# 1m => 1000000 bytes -# 1mb => 1024*1024 bytes -# 1g => 1000000000 bytes -# 1gb => 1024*1024*1024 bytes -# -# units are case insensitive so 1GB 1Gb 1gB are all the same. - -################################## INCLUDES ################################### - -# Include one or more other config files here. This is useful if you -# have a standard template that goes to all Redis servers but also need -# to customize a few per-server settings. Include files can include -# other files, so use this wisely. -# -# Notice option "include" won't be rewritten by command "CONFIG REWRITE" -# from admin or Redis Sentinel. Since Redis always uses the last processed -# line as value of a configuration directive, you'd better put includes -# at the beginning of this file to avoid overwriting config change at runtime. -# -# If instead you are interested in using includes to override configuration -# options, it is better to use include as the last line. -# -# include /path/to/local.conf -# include /path/to/other.conf - -################################ GENERAL ##################################### - -# By default Redis does not run as a daemon. Use 'yes' if you need it. -# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. -daemonize no - -# When running daemonized, Redis writes a pid file in /var/run/redis.pid by -# default. You can specify a custom pid file location here. -pidfile /var/run/redis.pid - -# Accept connections on the specified port, default is 6379. -# If port 0 is specified Redis will not listen on a TCP socket. -port 6379 - -# TCP listen() backlog. -# -# In high requests-per-second environments you need an high backlog in order -# to avoid slow clients connections issues. Note that the Linux kernel -# will silently truncate it to the value of /proc/sys/net/core/somaxconn so -# make sure to raise both the value of somaxconn and tcp_max_syn_backlog -# in order to get the desired effect. -tcp-backlog 511 - -# By default Redis listens for connections from all the network interfaces -# available on the server. It is possible to listen to just one or multiple -# interfaces using the "bind" configuration directive, followed by one or -# more IP addresses. -# -# Examples: -# -# bind 192.168.1.100 10.0.0.1 - -bind 0.0.0.0 - -# Specify the path for the Unix socket that will be used to listen for -# incoming connections. There is no default, so Redis will not listen -# on a unix socket when not specified. -# -# unixsocket /tmp/redis.sock -# unixsocketperm 700 - -# Close the connection after a client is idle for N seconds (0 to disable) -timeout 0 - -# TCP keepalive. -# -# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence -# of communication. This is useful for two reasons: -# -# 1) Detect dead peers. -# 2) Take the connection alive from the point of view of network -# equipment in the middle. -# -# On Linux, the specified value (in seconds) is the period used to send ACKs. -# Note that to close the connection the double of the time is needed. -# On other kernels the period depends on the kernel configuration. -# -# A reasonable value for this option is 60 seconds. -tcp-keepalive 60 - -# Specify the server verbosity level. -# This can be one of: -# debug (a lot of information, useful for development/testing) -# verbose (many rarely useful info, but not a mess like the debug level) -# notice (moderately verbose, what you want in production probably) -# warning (only very important / critical messages are logged) -loglevel notice - -# Specify the log file name. Also the empty string can be used to force -# Redis to log on the standard output. Note that if you use standard -# output for logging but daemonize, logs will be sent to /dev/null -logfile "" - -# To enable logging to the system logger, just set 'syslog-enabled' to yes, -# and optionally update the other syslog parameters to suit your needs. -# syslog-enabled no - -# Specify the syslog identity. -# syslog-ident redis - -# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. -# syslog-facility local0 - -# Set the number of databases. The default database is DB 0, you can select -# a different one on a per-connection basis using SELECT where -# dbid is a number between 0 and 'databases'-1 -databases 16 - -################################ SNAPSHOTTING ################################ -# -# Save the DB on disk: -# -# save -# -# Will save the DB if both the given number of seconds and the given -# number of write operations against the DB occurred. -# -# In the example below the behaviour will be to save: -# after 900 sec (15 min) if at least 1 key changed -# after 300 sec (5 min) if at least 10 keys changed -# after 60 sec if at least 10000 keys changed -# -# Note: you can disable saving completely by commenting out all "save" lines. -# -# It is also possible to remove all the previously configured save -# points by adding a save directive with a single empty string argument -# like in the following example: -# -# save "" - -save 900 1 -save 300 10 -save 60 10000 - -# By default Redis will stop accepting writes if RDB snapshots are enabled -# (at least one save point) and the latest background save failed. -# This will make the user aware (in a hard way) that data is not persisting -# on disk properly, otherwise chances are that no one will notice and some -# disaster will happen. -# -# If the background saving process will start working again Redis will -# automatically allow writes again. -# -# However if you have setup your proper monitoring of the Redis server -# and persistence, you may want to disable this feature so that Redis will -# continue to work as usual even if there are problems with disk, -# permissions, and so forth. -stop-writes-on-bgsave-error yes - -# Compress string objects using LZF when dump .rdb databases? -# For default that's set to 'yes' as it's almost always a win. -# If you want to save some CPU in the saving child set it to 'no' but -# the dataset will likely be bigger if you have compressible values or keys. -rdbcompression yes - -# Since version 5 of RDB a CRC64 checksum is placed at the end of the file. -# This makes the format more resistant to corruption but there is a performance -# hit to pay (around 10%) when saving and loading RDB files, so you can disable it -# for maximum performances. -# -# RDB files created with checksum disabled have a checksum of zero that will -# tell the loading code to skip the check. -rdbchecksum yes - -# The filename where to dump the DB -dbfilename dump.rdb - -# The working directory. -# -# The DB will be written inside this directory, with the filename specified -# above using the 'dbfilename' configuration directive. -# -# The Append Only File will also be created inside this directory. -# -# Note that you must specify a directory here, not a file name. -dir "./" - -################################# REPLICATION ################################# - -# Master-Slave replication. Use slaveof to make a Redis instance a copy of -# another Redis server. A few things to understand ASAP about Redis replication. -# -# 1) Redis replication is asynchronous, but you can configure a master to -# stop accepting writes if it appears to be not connected with at least -# a given number of slaves. -# 2) Redis slaves are able to perform a partial resynchronization with the -# master if the replication link is lost for a relatively small amount of -# time. You may want to configure the replication backlog size (see the next -# sections of this file) with a sensible value depending on your needs. -# 3) Replication is automatic and does not need user intervention. After a -# network partition slaves automatically try to reconnect to masters -# and resynchronize with them. -# -slaveof %master-ip% %master-port% - -# If the master is password protected (using the "requirepass" configuration -# directive below) it is possible to tell the slave to authenticate before -# starting the replication synchronization process, otherwise the master will -# refuse the slave request. -# -# masterauth - -# When a slave loses its connection with the master, or when the replication -# is still in progress, the slave can act in two different ways: -# -# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will -# still reply to client requests, possibly with out of date data, or the -# data set may just be empty if this is the first synchronization. -# -# 2) if slave-serve-stale-data is set to 'no' the slave will reply with -# an error "SYNC with master in progress" to all the kind of commands -# but to INFO and SLAVEOF. -# -slave-serve-stale-data yes - -# You can configure a slave instance to accept writes or not. Writing against -# a slave instance may be useful to store some ephemeral data (because data -# written on a slave will be easily deleted after resync with the master) but -# may also cause problems if clients are writing to it because of a -# misconfiguration. -# -# Since Redis 2.6 by default slaves are read-only. -# -# Note: read only slaves are not designed to be exposed to untrusted clients -# on the internet. It's just a protection layer against misuse of the instance. -# Still a read only slave exports by default all the administrative commands -# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve -# security of read only slaves using 'rename-command' to shadow all the -# administrative / dangerous commands. -slave-read-only yes - -# Replication SYNC strategy: disk or socket. -# -# ------------------------------------------------------- -# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY -# ------------------------------------------------------- -# -# New slaves and reconnecting slaves that are not able to continue the replication -# process just receiving differences, need to do what is called a "full -# synchronization". An RDB file is transmitted from the master to the slaves. -# The transmission can happen in two different ways: -# -# 1) Disk-backed: The Redis master creates a new process that writes the RDB -# file on disk. Later the file is transferred by the parent -# process to the slaves incrementally. -# 2) Diskless: The Redis master creates a new process that directly writes the -# RDB file to slave sockets, without touching the disk at all. -# -# With disk-backed replication, while the RDB file is generated, more slaves -# can be queued and served with the RDB file as soon as the current child producing -# the RDB file finishes its work. With diskless replication instead once -# the transfer starts, new slaves arriving will be queued and a new transfer -# will start when the current one terminates. -# -# When diskless replication is used, the master waits a configurable amount of -# time (in seconds) before starting the transfer in the hope that multiple slaves -# will arrive and the transfer can be parallelized. -# -# With slow disks and fast (large bandwidth) networks, diskless replication -# works better. -repl-diskless-sync no - -# When diskless replication is enabled, it is possible to configure the delay -# the server waits in order to spawn the child that trnasfers the RDB via socket -# to the slaves. -# -# This is important since once the transfer starts, it is not possible to serve -# new slaves arriving, that will be queued for the next RDB transfer, so the server -# waits a delay in order to let more slaves arrive. -# -# The delay is specified in seconds, and by default is 5 seconds. To disable -# it entirely just set it to 0 seconds and the transfer will start ASAP. -repl-diskless-sync-delay 5 - -# Slaves send PINGs to server in a predefined interval. It's possible to change -# this interval with the repl_ping_slave_period option. The default value is 10 -# seconds. -# -# repl-ping-slave-period 10 - -# The following option sets the replication timeout for: -# -# 1) Bulk transfer I/O during SYNC, from the point of view of slave. -# 2) Master timeout from the point of view of slaves (data, pings). -# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings). -# -# It is important to make sure that this value is greater than the value -# specified for repl-ping-slave-period otherwise a timeout will be detected -# every time there is low traffic between the master and the slave. -# -# repl-timeout 60 - -# Disable TCP_NODELAY on the slave socket after SYNC? -# -# If you select "yes" Redis will use a smaller number of TCP packets and -# less bandwidth to send data to slaves. But this can add a delay for -# the data to appear on the slave side, up to 40 milliseconds with -# Linux kernels using a default configuration. -# -# If you select "no" the delay for data to appear on the slave side will -# be reduced but more bandwidth will be used for replication. -# -# By default we optimize for low latency, but in very high traffic conditions -# or when the master and slaves are many hops away, turning this to "yes" may -# be a good idea. -repl-disable-tcp-nodelay no - -# Set the replication backlog size. The backlog is a buffer that accumulates -# slave data when slaves are disconnected for some time, so that when a slave -# wants to reconnect again, often a full resync is not needed, but a partial -# resync is enough, just passing the portion of data the slave missed while -# disconnected. -# -# The bigger the replication backlog, the longer the time the slave can be -# disconnected and later be able to perform a partial resynchronization. -# -# The backlog is only allocated once there is at least a slave connected. -# -# repl-backlog-size 1mb - -# After a master has no longer connected slaves for some time, the backlog -# will be freed. The following option configures the amount of seconds that -# need to elapse, starting from the time the last slave disconnected, for -# the backlog buffer to be freed. -# -# A value of 0 means to never release the backlog. -# -# repl-backlog-ttl 3600 - -# The slave priority is an integer number published by Redis in the INFO output. -# It is used by Redis Sentinel in order to select a slave to promote into a -# master if the master is no longer working correctly. -# -# A slave with a low priority number is considered better for promotion, so -# for instance if there are three slaves with priority 10, 100, 25 Sentinel will -# pick the one with priority 10, that is the lowest. -# -# However a special priority of 0 marks the slave as not able to perform the -# role of master, so a slave with priority of 0 will never be selected by -# Redis Sentinel for promotion. -# -# By default the priority is 100. -slave-priority 100 - -# It is possible for a master to stop accepting writes if there are less than -# N slaves connected, having a lag less or equal than M seconds. -# -# The N slaves need to be in "online" state. -# -# The lag in seconds, that must be <= the specified value, is calculated from -# the last ping received from the slave, that is usually sent every second. -# -# This option does not GUARANTEE that N replicas will accept the write, but -# will limit the window of exposure for lost writes in case not enough slaves -# are available, to the specified number of seconds. -# -# For example to require at least 3 slaves with a lag <= 10 seconds use: -# -# min-slaves-to-write 3 -# min-slaves-max-lag 10 -# -# Setting one or the other to 0 disables the feature. -# -# By default min-slaves-to-write is set to 0 (feature disabled) and -# min-slaves-max-lag is set to 10. - -################################## SECURITY ################################### - -# Require clients to issue AUTH before processing any other -# commands. This might be useful in environments in which you do not trust -# others with access to the host running redis-server. -# -# This should stay commented out for backward compatibility and because most -# people do not need auth (e.g. they run their own servers). -# -# Warning: since Redis is pretty fast an outside user can try up to -# 150k passwords per second against a good box. This means that you should -# use a very strong password otherwise it will be very easy to break. -# -# requirepass foobared - -# Command renaming. -# -# It is possible to change the name of dangerous commands in a shared -# environment. For instance the CONFIG command may be renamed into something -# hard to guess so that it will still be available for internal-use tools -# but not available for general clients. -# -# Example: -# -# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 -# -# It is also possible to completely kill a command by renaming it into -# an empty string: -# -# rename-command CONFIG "" -# -# Please note that changing the name of commands that are logged into the -# AOF file or transmitted to slaves may cause problems. - -################################### LIMITS #################################### - -# Set the max number of connected clients at the same time. By default -# this limit is set to 10000 clients, however if the Redis server is not -# able to configure the process file limit to allow for the specified limit -# the max number of allowed clients is set to the current file limit -# minus 32 (as Redis reserves a few file descriptors for internal uses). -# -# Once the limit is reached Redis will close all the new connections sending -# an error 'max number of clients reached'. -# -# maxclients 10000 - -# Don't use more memory than the specified amount of bytes. -# When the memory limit is reached Redis will try to remove keys -# according to the eviction policy selected (see maxmemory-policy). -# -# If Redis can't remove keys according to the policy, or if the policy is -# set to 'noeviction', Redis will start to reply with errors to commands -# that would use more memory, like SET, LPUSH, and so on, and will continue -# to reply to read-only commands like GET. -# -# This option is usually useful when using Redis as an LRU cache, or to set -# a hard memory limit for an instance (using the 'noeviction' policy). -# -# WARNING: If you have slaves attached to an instance with maxmemory on, -# the size of the output buffers needed to feed the slaves are subtracted -# from the used memory count, so that network problems / resyncs will -# not trigger a loop where keys are evicted, and in turn the output -# buffer of slaves is full with DELs of keys evicted triggering the deletion -# of more keys, and so forth until the database is completely emptied. -# -# In short... if you have slaves attached it is suggested that you set a lower -# limit for maxmemory so that there is some free RAM on the system for slave -# output buffers (but this is not needed if the policy is 'noeviction'). -# -# maxmemory - -# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory -# is reached. You can select among five behaviors: -# -# volatile-lru -> remove the key with an expire set using an LRU algorithm -# allkeys-lru -> remove any key according to the LRU algorithm -# volatile-random -> remove a random key with an expire set -# allkeys-random -> remove a random key, any key -# volatile-ttl -> remove the key with the nearest expire time (minor TTL) -# noeviction -> don't expire at all, just return an error on write operations -# -# Note: with any of the above policies, Redis will return an error on write -# operations, when there are no suitable keys for eviction. -# -# At the date of writing these commands are: set setnx setex append -# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd -# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby -# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby -# getset mset msetnx exec sort -# -# The default is: -# -# maxmemory-policy volatile-lru - -# LRU and minimal TTL algorithms are not precise algorithms but approximated -# algorithms (in order to save memory), so you can select as well the sample -# size to check. For instance for default Redis will check three keys and -# pick the one that was used less recently, you can change the sample size -# using the following configuration directive. -# -# maxmemory-samples 3 - -############################## APPEND ONLY MODE ############################### - -# By default Redis asynchronously dumps the dataset on disk. This mode is -# good enough in many applications, but an issue with the Redis process or -# a power outage may result into a few minutes of writes lost (depending on -# the configured save points). -# -# The Append Only File is an alternative persistence mode that provides -# much better durability. For instance using the default data fsync policy -# (see later in the config file) Redis can lose just one second of writes in a -# dramatic event like a server power outage, or a single write if something -# wrong with the Redis process itself happens, but the operating system is -# still running correctly. -# -# AOF and RDB persistence can be enabled at the same time without problems. -# If the AOF is enabled on startup Redis will load the AOF, that is the file -# with the better durability guarantees. -# -# Please check http://redis.io/topics/persistence for more information. - -appendonly yes - -# The name of the append only file (default: "appendonly.aof") - -appendfilename "appendonly.aof" - -# The fsync() call tells the Operating System to actually write data on disk -# instead of waiting for more data in the output buffer. Some OS will really flush -# data on disk, some other OS will just try to do it ASAP. -# -# Redis supports three different modes: -# -# no: don't fsync, just let the OS flush the data when it wants. Faster. -# always: fsync after every write to the append only log. Slow, Safest. -# everysec: fsync only one time every second. Compromise. -# -# The default is "everysec", as that's usually the right compromise between -# speed and data safety. It's up to you to understand if you can relax this to -# "no" that will let the operating system flush the output buffer when -# it wants, for better performances (but if you can live with the idea of -# some data loss consider the default persistence mode that's snapshotting), -# or on the contrary, use "always" that's very slow but a bit safer than -# everysec. -# -# More details please check the following article: -# http://antirez.com/post/redis-persistence-demystified.html -# -# If unsure, use "everysec". - -# appendfsync always -appendfsync everysec -# appendfsync no - -# When the AOF fsync policy is set to always or everysec, and a background -# saving process (a background save or AOF log background rewriting) is -# performing a lot of I/O against the disk, in some Linux configurations -# Redis may block too long on the fsync() call. Note that there is no fix for -# this currently, as even performing fsync in a different thread will block -# our synchronous write(2) call. -# -# In order to mitigate this problem it's possible to use the following option -# that will prevent fsync() from being called in the main process while a -# BGSAVE or BGREWRITEAOF is in progress. -# -# This means that while another child is saving, the durability of Redis is -# the same as "appendfsync none". In practical terms, this means that it is -# possible to lose up to 30 seconds of log in the worst scenario (with the -# default Linux settings). -# -# If you have latency problems turn this to "yes". Otherwise leave it as -# "no" that is the safest pick from the point of view of durability. - -no-appendfsync-on-rewrite no - -# Automatic rewrite of the append only file. -# Redis is able to automatically rewrite the log file implicitly calling -# BGREWRITEAOF when the AOF log size grows by the specified percentage. -# -# This is how it works: Redis remembers the size of the AOF file after the -# latest rewrite (if no rewrite has happened since the restart, the size of -# the AOF at startup is used). -# -# This base size is compared to the current size. If the current size is -# bigger than the specified percentage, the rewrite is triggered. Also -# you need to specify a minimal size for the AOF file to be rewritten, this -# is useful to avoid rewriting the AOF file even if the percentage increase -# is reached but it is still pretty small. -# -# Specify a percentage of zero in order to disable the automatic AOF -# rewrite feature. - -auto-aof-rewrite-percentage 100 -auto-aof-rewrite-min-size 64mb - -# An AOF file may be found to be truncated at the end during the Redis -# startup process, when the AOF data gets loaded back into memory. -# This may happen when the system where Redis is running -# crashes, especially when an ext4 filesystem is mounted without the -# data=ordered option (however this can't happen when Redis itself -# crashes or aborts but the operating system still works correctly). -# -# Redis can either exit with an error when this happens, or load as much -# data as possible (the default now) and start if the AOF file is found -# to be truncated at the end. The following option controls this behavior. -# -# If aof-load-truncated is set to yes, a truncated AOF file is loaded and -# the Redis server starts emitting a log to inform the user of the event. -# Otherwise if the option is set to no, the server aborts with an error -# and refuses to start. When the option is set to no, the user requires -# to fix the AOF file using the "redis-check-aof" utility before to restart -# the server. -# -# Note that if the AOF file will be found to be corrupted in the middle -# the server will still exit with an error. This option only applies when -# Redis will try to read more data from the AOF file but not enough bytes -# will be found. -aof-load-truncated yes - -################################ LUA SCRIPTING ############################### - -# Max execution time of a Lua script in milliseconds. -# -# If the maximum execution time is reached Redis will log that a script is -# still in execution after the maximum allowed time and will start to -# reply to queries with an error. -# -# When a long running script exceeds the maximum execution time only the -# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be -# used to stop a script that did not yet called write commands. The second -# is the only way to shut down the server in the case a write command was -# already issued by the script but the user doesn't want to wait for the natural -# termination of the script. -# -# Set it to 0 or a negative value for unlimited execution without warnings. -lua-time-limit 5000 - -################################## SLOW LOG ################################### - -# The Redis Slow Log is a system to log queries that exceeded a specified -# execution time. The execution time does not include the I/O operations -# like talking with the client, sending the reply and so forth, -# but just the time needed to actually execute the command (this is the only -# stage of command execution where the thread is blocked and can not serve -# other requests in the meantime). -# -# You can configure the slow log with two parameters: one tells Redis -# what is the execution time, in microseconds, to exceed in order for the -# command to get logged, and the other parameter is the length of the -# slow log. When a new command is logged the oldest one is removed from the -# queue of logged commands. - -# The following time is expressed in microseconds, so 1000000 is equivalent -# to one second. Note that a negative number disables the slow log, while -# a value of zero forces the logging of every command. -slowlog-log-slower-than 10000 - -# There is no limit to this length. Just be aware that it will consume memory. -# You can reclaim memory used by the slow log with SLOWLOG RESET. -slowlog-max-len 128 - -################################ LATENCY MONITOR ############################## - -# The Redis latency monitoring subsystem samples different operations -# at runtime in order to collect data related to possible sources of -# latency of a Redis instance. -# -# Via the LATENCY command this information is available to the user that can -# print graphs and obtain reports. -# -# The system only logs operations that were performed in a time equal or -# greater than the amount of milliseconds specified via the -# latency-monitor-threshold configuration directive. When its value is set -# to zero, the latency monitor is turned off. -# -# By default latency monitoring is disabled since it is mostly not needed -# if you don't have latency issues, and collecting data has a performance -# impact, that while very small, can be measured under big load. Latency -# monitoring can easily be enabled at runtime using the command -# "CONFIG SET latency-monitor-threshold " if needed. -latency-monitor-threshold 0 - -############################# Event notification ############################## - -# Redis can notify Pub/Sub clients about events happening in the key space. -# This feature is documented at http://redis.io/topics/notifications -# -# For instance if keyspace events notification is enabled, and a client -# performs a DEL operation on key "foo" stored in the Database 0, two -# messages will be published via Pub/Sub: -# -# PUBLISH __keyspace@0__:foo del -# PUBLISH __keyevent@0__:del foo -# -# It is possible to select the events that Redis will notify among a set -# of classes. Every class is identified by a single character: -# -# K Keyspace events, published with __keyspace@__ prefix. -# E Keyevent events, published with __keyevent@__ prefix. -# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... -# $ String commands -# l List commands -# s Set commands -# h Hash commands -# z Sorted set commands -# x Expired events (events generated every time a key expires) -# e Evicted events (events generated when a key is evicted for maxmemory) -# A Alias for g$lshzxe, so that the "AKE" string means all the events. -# -# The "notify-keyspace-events" takes as argument a string that is composed -# of zero or multiple characters. The empty string means that notifications -# are disabled. -# -# Example: to enable list and generic events, from the point of view of the -# event name, use: -# -# notify-keyspace-events Elg -# -# Example 2: to get the stream of the expired keys subscribing to channel -# name __keyevent@0__:expired use: -# -# notify-keyspace-events Ex -# -# By default all notifications are disabled because most users don't need -# this feature and the feature has some overhead. Note that if you don't -# specify at least one of K or E, no events will be delivered. -notify-keyspace-events "" - -############################### ADVANCED CONFIG ############################### - -# Hashes are encoded using a memory efficient data structure when they have a -# small number of entries, and the biggest entry does not exceed a given -# threshold. These thresholds can be configured using the following directives. -hash-max-ziplist-entries 512 -hash-max-ziplist-value 64 - -# Similarly to hashes, small lists are also encoded in a special way in order -# to save a lot of space. The special representation is only used when -# you are under the following limits: -list-max-ziplist-entries 512 -list-max-ziplist-value 64 - -# Sets have a special encoding in just one case: when a set is composed -# of just strings that happen to be integers in radix 10 in the range -# of 64 bit signed integers. -# The following configuration setting sets the limit in the size of the -# set in order to use this special memory saving encoding. -set-max-intset-entries 512 - -# Similarly to hashes and lists, sorted sets are also specially encoded in -# order to save a lot of space. This encoding is only used when the length and -# elements of a sorted set are below the following limits: -zset-max-ziplist-entries 128 -zset-max-ziplist-value 64 - -# HyperLogLog sparse representation bytes limit. The limit includes the -# 16 bytes header. When an HyperLogLog using the sparse representation crosses -# this limit, it is converted into the dense representation. -# -# A value greater than 16000 is totally useless, since at that point the -# dense representation is more memory efficient. -# -# The suggested value is ~ 3000 in order to have the benefits of -# the space efficient encoding without slowing down too much PFADD, -# which is O(N) with the sparse encoding. The value can be raised to -# ~ 10000 when CPU is not a concern, but space is, and the data set is -# composed of many HyperLogLogs with cardinality in the 0 - 15000 range. -hll-sparse-max-bytes 3000 - -# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in -# order to help rehashing the main Redis hash table (the one mapping top-level -# keys to values). The hash table implementation Redis uses (see dict.c) -# performs a lazy rehashing: the more operation you run into a hash table -# that is rehashing, the more rehashing "steps" are performed, so if the -# server is idle the rehashing is never complete and some more memory is used -# by the hash table. -# -# The default is to use this millisecond 10 times every second in order to -# actively rehash the main dictionaries, freeing memory when possible. -# -# If unsure: -# use "activerehashing no" if you have hard latency requirements and it is -# not a good thing in your environment that Redis can reply from time to time -# to queries with 2 milliseconds delay. -# -# use "activerehashing yes" if you don't have such hard requirements but -# want to free memory asap when possible. -activerehashing yes - -# The client output buffer limits can be used to force disconnection of clients -# that are not reading data from the server fast enough for some reason (a -# common reason is that a Pub/Sub client can't consume messages as fast as the -# publisher can produce them). -# -# The limit can be set differently for the three different classes of clients: -# -# normal -> normal clients including MONITOR clients -# slave -> slave clients -# pubsub -> clients subscribed to at least one pubsub channel or pattern -# -# The syntax of every client-output-buffer-limit directive is the following: -# -# client-output-buffer-limit -# -# A client is immediately disconnected once the hard limit is reached, or if -# the soft limit is reached and remains reached for the specified number of -# seconds (continuously). -# So for instance if the hard limit is 32 megabytes and the soft limit is -# 16 megabytes / 10 seconds, the client will get disconnected immediately -# if the size of the output buffers reach 32 megabytes, but will also get -# disconnected if the client reaches 16 megabytes and continuously overcomes -# the limit for 10 seconds. -# -# By default normal clients are not limited because they don't receive data -# without asking (in a push way), but just after a request, so only -# asynchronous clients may create a scenario where data is requested faster -# than it can read. -# -# Instead there is a default limit for pubsub and slave clients, since -# subscribers and slaves receive data in a push fashion. -# -# Both the hard or the soft limit can be disabled by setting them to zero. -client-output-buffer-limit normal 0 0 0 -client-output-buffer-limit slave 256mb 64mb 60 -client-output-buffer-limit pubsub 32mb 8mb 60 - -# Redis calls an internal function to perform many background tasks, like -# closing connections of clients in timeout, purging expired keys that are -# never requested, and so forth. -# -# Not all tasks are performed with the same frequency, but Redis checks for -# tasks to perform according to the specified "hz" value. -# -# By default "hz" is set to 10. Raising the value will use more CPU when -# Redis is idle, but at the same time will make Redis more responsive when -# there are many keys expiring at the same time, and timeouts may be -# handled with more precision. -# -# The range is between 1 and 500, however a value over 100 is usually not -# a good idea. Most users should use the default of 10 and raise this up to -# 100 only in environments where very low latency is required. -hz 10 - -# When a child rewrites the AOF file, if the following option is enabled -# the file will be fsync-ed every 32 MB of data generated. This is useful -# in order to commit the file to the disk more incrementally and avoid -# big latency spikes. -aof-rewrite-incremental-fsync yes diff --git a/vendor/k8s.io/kubernetes/examples/storage/redis/image/run.sh b/vendor/k8s.io/kubernetes/examples/storage/redis/image/run.sh deleted file mode 100755 index 6fed5af4a..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/redis/image/run.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -# 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. - -function launchmaster() { - if [[ ! -e /redis-master-data ]]; then - echo "Redis master data doesn't exist, data won't be persistent!" - mkdir /redis-master-data - fi - redis-server /redis-master/redis.conf --protected-mode no -} - -function launchsentinel() { - while true; do - master=$(redis-cli -h ${REDIS_SENTINEL_SERVICE_HOST} -p ${REDIS_SENTINEL_SERVICE_PORT} --csv SENTINEL get-master-addr-by-name mymaster | tr ',' ' ' | cut -d' ' -f1) - if [[ -n ${master} ]]; then - master="${master//\"}" - else - master=$(hostname -i) - fi - - redis-cli -h ${master} INFO - if [[ "$?" == "0" ]]; then - break - fi - echo "Connecting to master failed. Waiting..." - sleep 10 - done - - sentinel_conf=sentinel.conf - - echo "sentinel monitor mymaster ${master} 6379 2" > ${sentinel_conf} - echo "sentinel down-after-milliseconds mymaster 60000" >> ${sentinel_conf} - echo "sentinel failover-timeout mymaster 180000" >> ${sentinel_conf} - echo "sentinel parallel-syncs mymaster 1" >> ${sentinel_conf} - echo "bind 0.0.0.0" >> ${sentinel_conf} - - redis-sentinel ${sentinel_conf} --protected-mode no -} - -function launchslave() { - while true; do - master=$(redis-cli -h ${REDIS_SENTINEL_SERVICE_HOST} -p ${REDIS_SENTINEL_SERVICE_PORT} --csv SENTINEL get-master-addr-by-name mymaster | tr ',' ' ' | cut -d' ' -f1) - if [[ -n ${master} ]]; then - master="${master//\"}" - else - echo "Failed to find master." - sleep 60 - exit 1 - fi - redis-cli -h ${master} INFO - if [[ "$?" == "0" ]]; then - break - fi - echo "Connecting to master failed. Waiting..." - sleep 10 - done - sed -i "s/%master-ip%/${master}/" /redis-slave/redis.conf - sed -i "s/%master-port%/6379/" /redis-slave/redis.conf - redis-server /redis-slave/redis.conf --protected-mode no -} - -if [[ "${MASTER}" == "true" ]]; then - launchmaster - exit 0 -fi - -if [[ "${SENTINEL}" == "true" ]]; then - launchsentinel - exit 0 -fi - -launchslave diff --git a/vendor/k8s.io/kubernetes/examples/storage/redis/redis-controller.yaml b/vendor/k8s.io/kubernetes/examples/storage/redis/redis-controller.yaml deleted file mode 100644 index dab2f7f1a..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/redis/redis-controller.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: redis -spec: - replicas: 1 - selector: - name: redis - template: - metadata: - labels: - name: redis - spec: - containers: - - name: redis - image: k8s.gcr.io/redis:v1 - ports: - - containerPort: 6379 - resources: - limits: - cpu: "0.1" - volumeMounts: - - mountPath: /redis-master-data - name: data - volumes: - - name: data - emptyDir: {} - diff --git a/vendor/k8s.io/kubernetes/examples/storage/redis/redis-sentinel-controller.yaml b/vendor/k8s.io/kubernetes/examples/storage/redis/redis-sentinel-controller.yaml deleted file mode 100644 index 6c4b14347..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/redis/redis-sentinel-controller.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: redis-sentinel -spec: - replicas: 1 - selector: - redis-sentinel: "true" - template: - metadata: - labels: - name: redis-sentinel - redis-sentinel: "true" - role: sentinel - spec: - containers: - - name: sentinel - image: k8s.gcr.io/redis:v1 - env: - - name: SENTINEL - value: "true" - ports: - - containerPort: 26379 diff --git a/vendor/k8s.io/kubernetes/examples/storage/redis/redis-sentinel-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/redis/redis-sentinel-service.yaml deleted file mode 100644 index c670a8241..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/redis/redis-sentinel-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - name: sentinel - role: service - name: redis-sentinel -spec: - ports: - - port: 26379 - targetPort: 26379 - selector: - redis-sentinel: "true" diff --git a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/README.md b/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/README.md deleted file mode 100644 index f15a56838..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/storage/rethinkdb/README.md](https://github.com/kubernetes/examples/blob/master/staging/storage/rethinkdb/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/admin-pod.yaml b/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/admin-pod.yaml deleted file mode 100644 index 12163909d..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/admin-pod.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - labels: - db: rethinkdb - role: admin - name: rethinkdb-admin -spec: - containers: - - image: k8s.gcr.io/rethinkdb:1.16.0_1 - name: rethinkdb - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - ports: - - containerPort: 8080 - name: admin-port - - containerPort: 28015 - name: driver-port - - containerPort: 29015 - name: cluster-port - volumeMounts: - - mountPath: /data/rethinkdb_data - name: rethinkdb-storage - volumes: - - name: rethinkdb-storage - emptyDir: {} diff --git a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/admin-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/admin-service.yaml deleted file mode 100644 index 0ae37c026..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/admin-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - db: rethinkdb - name: rethinkdb-admin -spec: - ports: - - port: 8080 - targetPort: 8080 - type: LoadBalancer - selector: - db: rethinkdb - role: admin diff --git a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/driver-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/driver-service.yaml deleted file mode 100644 index c2c559adf..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/driver-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - db: rethinkdb - name: rethinkdb-driver -spec: - ports: - - port: 28015 - targetPort: 28015 - selector: - db: rethinkdb diff --git a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/gen-pod.sh b/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/gen-pod.sh deleted file mode 100755 index 90a44f230..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/gen-pod.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash - -# 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. - -set -o errexit -set -o nounset -set -o pipefail - -: ${VERSION:=1.16.0} - -readonly NAME=${1-} -if [[ -z "${NAME}" ]]; then - echo -e "\033[1;31mName must be specified\033[0m" - exit 1 -fi - -ADMIN="" -if [[ ${NAME} == "admin" ]]; then - ADMIN="role: admin" -fi - -NODE="" -# One needs to label a node with the same key/value pair, -# i.e., 'kubectl label nodes name=${2}' -if [[ ! -z "${2-}" ]]; then - NODE="nodeSelector: { name: ${2} }" -fi - -cat << EOF -apiVersion: v1 -kind: Pod -metadata: - labels: - ${ADMIN} - db: rethinkdb - name: rethinkdb-${NAME}-${VERSION} - namespace: rethinkdb -spec: - containers: - - image: antmanler/rethinkdb:${VERSION} - name: rethinkdb - ports: - - containerPort: 8080 - name: admin-port - protocol: TCP - - containerPort: 28015 - name: driver-port - protocol: TCP - - containerPort: 29015 - name: cluster-port - protocol: TCP - volumeMounts: - - mountPath: /data/rethinkdb_data - name: rethinkdb-storage - ${NODE} - restartPolicy: Always - volumes: - - hostPath: - path: /data/db/rethinkdb - name: rethinkdb-storage -EOF diff --git a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/image/Dockerfile b/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/image/Dockerfile deleted file mode 100644 index ff650cd24..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/image/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# 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. - -FROM rethinkdb:1.16.0 - - -RUN apt-get update && \ - apt-get install -yq curl && \ - rm -rf /var/cache/apt/* && rm -rf /var/lib/apt/lists/* && \ - curl -L http://stedolan.github.io/jq/download/linux64/jq > /usr/bin/jq && \ - chmod u+x /usr/bin/jq - -COPY ./run.sh /usr/bin/run.sh -RUN chmod u+x /usr/bin/run.sh - -CMD "/usr/bin/run.sh" diff --git a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/image/run.sh b/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/image/run.sh deleted file mode 100644 index 607eb59ed..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/image/run.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -# 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. - -set -o pipefail - -echo Checking for other nodes -IP="" -if [[ -n "${KUBERNETES_SERVICE_HOST}" ]]; then - - POD_NAMESPACE=${POD_NAMESPACE:-default} - MYHOST=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/') - echo My host: ${MYHOST} - - URL="https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/api/v1/namespaces/${POD_NAMESPACE}/endpoints/rethinkdb-driver" - echo "Endpont url: ${URL}" - echo "Looking for IPs..." - token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) - # try to pick up first different ip from endpoints - IP=$(curl -s ${URL} --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header "Authorization: Bearer ${token}" \ - | jq -s -r --arg h "${MYHOST}" '.[0].subsets | .[].addresses | [ .[].ip ] | map(select(. != $h)) | .[0]') || exit 1 - [[ "${IP}" == null ]] && IP="" -fi - -if [[ -n "${IP}" ]]; then - ENDPOINT="${IP}:29015" - echo "Join to ${ENDPOINT}" - exec rethinkdb --bind all --join ${ENDPOINT} -else - echo "Start single instance" - exec rethinkdb --bind all -fi diff --git a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/rc.yaml b/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/rc.yaml deleted file mode 100644 index 23becb6e8..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/rethinkdb/rc.yaml +++ /dev/null @@ -1,38 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - labels: - db: rethinkdb - name: rethinkdb-rc -spec: - replicas: 1 - selector: - db: rethinkdb - role: replicas - template: - metadata: - labels: - db: rethinkdb - role: replicas - spec: - containers: - - image: k8s.gcr.io/rethinkdb:1.16.0_1 - name: rethinkdb - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - ports: - - containerPort: 8080 - name: admin-port - - containerPort: 28015 - name: driver-port - - containerPort: 29015 - name: cluster-port - volumeMounts: - - mountPath: /data/rethinkdb_data - name: rethinkdb-storage - volumes: - - name: rethinkdb-storage - emptyDir: {} diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/README.md b/vendor/k8s.io/kubernetes/examples/storage/vitess/README.md deleted file mode 100644 index 6b350d8e5..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/storage/vitess/README.md](https://github.com/kubernetes/examples/blob/master/staging/storage/vitess/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/configure.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/configure.sh deleted file mode 100755 index 7166c7fbb..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/configure.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash - -# 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. - -# This script generates config.sh, which is a site-local config file that is not -# checked into source control. - -# Select and configure Backup Storage Implementation. -storage=gcs -read -p "Backup Storage (file, gcs) [gcs]: " -if [ -n "$REPLY" ]; then storage="$REPLY"; fi - -case "$storage" in -gcs) - # Google Cloud Storage - project=$(gcloud config list project | grep 'project\s*=' | sed -r 's/^.*=\s*(.*)$/\1/') - read -p "Google Developers Console Project [$project]: " - if [ -n "$REPLY" ]; then project="$REPLY"; fi - if [ -z "$project" ]; then - echo "ERROR: Project name must not be empty." - exit 1 - fi - - read -p "Google Cloud Storage bucket for Vitess backups: " bucket - if [ -z "$bucket" ]; then - echo "ERROR: Bucket name must not be empty." - exit 1 - fi - echo - echo "NOTE: If you haven't already created this bucket, you can do so by running:" - echo " gsutil mb gs://$bucket" - echo - - backup_flags=$(echo -backup_storage_implementation gcs \ - -gcs_backup_storage_project "'$project'" \ - -gcs_backup_storage_bucket "'$bucket'") - ;; -file) - # Mounted volume (e.g. NFS) - read -p "Root directory for backups (usually an NFS mount): " file_root - if [ -z "$file_root" ]; then - echo "ERROR: Root directory must not be empty." - exit 1 - fi - echo - echo "NOTE: You must add your NFS mount to the vtctld-controller-template" - echo " and vttablet-pod-template as described in the Kubernetes docs:" - echo " http://kubernetes.io/v1.0/docs/user-guide/volumes.html#nfs" - echo - - backup_flags=$(echo -backup_storage_implementation file \ - -file_backup_storage_root "'$file_root'") - ;; -*) - echo "ERROR: Unsupported backup storage implementation: $storage" - exit 1 -esac - -echo "Saving config.sh..." -echo "backup_flags=\"$backup_flags\"" > config.sh - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/create_test_table.sql b/vendor/k8s.io/kubernetes/examples/storage/vitess/create_test_table.sql deleted file mode 100644 index 0a6ef3609..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/create_test_table.sql +++ /dev/null @@ -1,8 +0,0 @@ -CREATE TABLE messages ( - page BIGINT(20) UNSIGNED, - time_created_ns BIGINT(20) UNSIGNED, - keyspace_id BIGINT(20) UNSIGNED, - message VARCHAR(10000), - PRIMARY KEY (page, time_created_ns) -) ENGINE=InnoDB - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/env.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/env.sh deleted file mode 100644 index 49b06c800..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/env.sh +++ /dev/null @@ -1,63 +0,0 @@ -# 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. - -# This is an include file used by the other scripts in this directory. - -# Most clusters will just be accessed with 'kubectl' on $PATH. -# However, some might require a different command. For example, GKE required -# KUBECTL='gcloud beta container kubectl' for a while. Now that most of our -# use cases just need KUBECTL=kubectl, we'll make that the default. -KUBECTL=${KUBECTL:-kubectl} - -# This should match the nodePort in vtctld-service.yaml -VTCTLD_PORT=${VTCTLD_PORT:-30001} - -# Customizable parameters -SHARDS=${SHARDS:-'-80,80-'} -TABLETS_PER_SHARD=${TABLETS_PER_SHARD:-2} -RDONLY_COUNT=${RDONLY_COUNT:-0} -MAX_TASK_WAIT_RETRIES=${MAX_TASK_WAIT_RETRIES:-300} -MAX_VTTABLET_TOPO_WAIT_RETRIES=${MAX_VTTABLET_TOPO_WAIT_RETRIES:-180} -VTTABLET_TEMPLATE=${VTTABLET_TEMPLATE:-'vttablet-pod-template.yaml'} -VTGATE_TEMPLATE=${VTGATE_TEMPLATE:-'vtgate-controller-template.yaml'} -VTGATE_COUNT=${VTGATE_COUNT:-1} -CELLS=${CELLS:-'test'} -ETCD_REPLICAS=3 - -VTGATE_REPLICAS=$VTGATE_COUNT - -# Get the ExternalIP of any node. -get_node_ip() { - $KUBECTL get -o template -t '{{range (index .items 0).status.addresses}}{{if eq .type "ExternalIP"}}{{.address}}{{end}}{{end}}' nodes -} - -# Try to find vtctld address if not provided. -get_vtctld_addr() { - if [ -z "$VTCTLD_ADDR" ]; then - node_ip=$(get_node_ip) - if [ -n "$node_ip" ]; then - VTCTLD_ADDR="$node_ip:$VTCTLD_PORT" - fi - fi - echo "$VTCTLD_ADDR" -} - -config_file=`dirname "${BASH_SOURCE}"`/config.sh -if [ ! -f $config_file ]; then - echo "Please run ./configure.sh first to generate config.sh file." - exit 1 -fi - -source $config_file - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-controller-template.yaml b/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-controller-template.yaml deleted file mode 100644 index dcd7980bd..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-controller-template.yaml +++ /dev/null @@ -1,54 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: etcd-{{cell}} -spec: - replicas: {{replicas}} - template: - metadata: - labels: - component: etcd - cell: {{cell}} - app: vitess - spec: - volumes: - - name: certs - hostPath: {path: /etc/ssl/certs} - containers: - - name: etcd - image: vitess/etcd:v2.0.13-lite - volumeMounts: - - name: certs - readOnly: true - mountPath: /etc/ssl/certs - resources: - limits: - memory: "128Mi" - cpu: "100m" - command: - - bash - - "-c" - - >- - ipaddr=$(hostname -i) - - global_etcd=$ETCD_GLOBAL_SERVICE_HOST:$ETCD_GLOBAL_SERVICE_PORT - - cell="{{cell}}" && - local_etcd_host_var="ETCD_${cell^^}_SERVICE_HOST" && - local_etcd_port_var="ETCD_${cell^^}_SERVICE_PORT" && - local_etcd=${!local_etcd_host_var}:${!local_etcd_port_var} - - if [ "{{cell}}" != "global" ]; then - until etcdctl -C "http://$global_etcd" - set "/vt/cells/{{cell}}" "http://$local_etcd"; do - echo "[$(date)] waiting for global etcd to register cell '{{cell}}'"; - sleep 1; - done; - fi - - etcd -name $HOSTNAME -discovery {{discovery}} - -advertise-client-urls http://$ipaddr:4001 - -initial-advertise-peer-urls http://$ipaddr:7001 - -listen-client-urls http://$ipaddr:4001 - -listen-peer-urls http://$ipaddr:7001 - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-down.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-down.sh deleted file mode 100755 index 1f3ca258c..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-down.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that tears down the etcd servers started by -# etcd-up.sh. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -CELLS=${CELLS:-'test'} -cells=`echo $CELLS | tr ',' ' '` - -# Delete replication controllers -for cell in 'global' $cells; do - echo "Deleting etcd replicationcontroller for $cell cell..." - $KUBECTL delete replicationcontroller etcd-$cell - - echo "Deleting etcd service for $cell cell..." - $KUBECTL delete service etcd-$cell -done - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-service-template.yaml b/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-service-template.yaml deleted file mode 100644 index 817c3e132..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-service-template.yaml +++ /dev/null @@ -1,16 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: etcd-{{cell}} - labels: - component: etcd - cell: {{cell}} - app: vitess -spec: - ports: - - port: 4001 - selector: - component: etcd - cell: {{cell}} - app: vitess - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-up.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-up.sh deleted file mode 100755 index b97e36900..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/etcd-up.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that creates etcd clusters. -# Vitess requires a global cluster, as well as one for each cell. -# -# For automatic discovery, an etcd cluster can be bootstrapped from an -# existing cluster. In this example, we use an externally-run discovery -# service, but you can use your own. See the etcd docs for more: -# https://github.com/coreos/etcd/blob/v2.0.13/Documentation/clustering.md - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -replicas=${ETCD_REPLICAS:-3} - -CELLS=${CELLS:-'test'} -cells=`echo $CELLS | tr ',' ' '` - -for cell in 'global' $cells; do - # Generate a discovery token. - echo "Generating discovery token for $cell cell..." - discovery=$(curl -sL https://discovery.etcd.io/new?size=$replicas) - if [ -z "$discovery" ]; then - echo "Failed to get etcd discovery token for cell '$cell'." - exit 1 - fi - - # Create the client service, which will load-balance across all replicas. - echo "Creating etcd service for $cell cell..." - cat etcd-service-template.yaml | \ - sed -e "s/{{cell}}/$cell/g" | \ - $KUBECTL create -f - - - # Expand template variables - sed_script="" - for var in cell discovery replicas; do - sed_script+="s,{{$var}},${!var},g;" - done - - # Create the replication controller. - echo "Creating etcd replicationcontroller for $cell cell..." - cat etcd-controller-template.yaml | sed -e "$sed_script" | $KUBECTL create -f - -done - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-controller.yaml b/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-controller.yaml deleted file mode 100644 index 1c5ca5a18..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-controller.yaml +++ /dev/null @@ -1,23 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: guestbook -spec: - replicas: 3 - template: - metadata: - labels: - component: guestbook - app: vitess - spec: - containers: - - name: guestbook - image: vitess/guestbook:v2.0.0-alpha5 - ports: - - name: http-server - containerPort: 8080 - resources: - limits: - memory: "128Mi" - cpu: "100m" - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-down.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-down.sh deleted file mode 100755 index bac48ed32..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-down.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that stops guestbook. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Deleting guestbook replicationcontroller..." -$KUBECTL delete replicationcontroller guestbook - -echo "Deleting guestbook service..." -$KUBECTL delete service guestbook diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-service.yaml deleted file mode 100644 index 5435f7fa8..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: guestbook - labels: - component: guestbook - app: vitess -spec: - ports: - - port: 80 - targetPort: http-server - selector: - component: guestbook - app: vitess - type: LoadBalancer - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-up.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-up.sh deleted file mode 100755 index b3afe9f05..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/guestbook-up.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that starts a guestbook replicationcontroller. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Creating guestbook service..." -$KUBECTL create -f guestbook-service.yaml - -echo "Creating guestbook replicationcontroller..." -$KUBECTL create -f guestbook-controller.yaml diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vitess-down.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/vitess-down.sh deleted file mode 100755 index dc3884a35..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vitess-down.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# 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. - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -./vtgate-down.sh -SHARDS=$SHARDS CELLS=$CELLS TABLETS_PER_SHARD=$TABLETS_PER_SHARD ./vttablet-down.sh -./vtctld-down.sh -./etcd-down.sh diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vitess-up.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/vitess-up.sh deleted file mode 100755 index 4add4ee7e..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vitess-up.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that creates a fully functional vitess cluster. -# It performs the following steps: -# - Create etcd clusters -# - Create vtctld pod -# - Create vttablet pods -# - Perform vtctl initialization: -# SetKeyspaceShardingInfo, Rebuild Keyspace, Reparent Shard, Apply Schema -# - Create vtgate pods - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -cells=`echo $CELLS | tr ',' ' '` -num_cells=`echo $cells | wc -w` - -function update_spinner_value () { - spinner='-\|/' - cur_spinner=${spinner:$(($1%${#spinner})):1} -} - -function wait_for_running_tasks () { - # This function waits for pods to be in the "Running" state - # 1. task_name: Name that the desired task begins with - # 2. num_tasks: Number of tasks to wait for - # Returns: - # 0 if successful, -1 if timed out - task_name=$1 - num_tasks=$2 - counter=0 - - echo "Waiting for ${num_tasks}x $task_name to enter state Running" - - while [ $counter -lt $MAX_TASK_WAIT_RETRIES ]; do - # Get status column of pods with name starting with $task_name, - # count how many are in state Running - num_running=`$KUBECTL get pods | grep ^$task_name | grep Running | wc -l` - - echo -en "\r$task_name: $num_running out of $num_tasks in state Running..." - if [ $num_running -eq $num_tasks ] - then - echo Complete - return 0 - fi - update_spinner_value $counter - echo -n $cur_spinner - let counter=counter+1 - sleep 1 - done - echo Timed out - return -1 -} - -if [ -z "$GOPATH" ]; then - echo "ERROR: GOPATH undefined, can't obtain vtctlclient" - exit -1 -fi - -export KUBECTL='kubectl' - -echo "Downloading and installing vtctlclient..." -go get -u github.com/youtube/vitess/go/cmd/vtctlclient -num_shards=`echo $SHARDS | tr "," " " | wc -w` -total_tablet_count=$(($num_shards*$TABLETS_PER_SHARD*$num_cells)) -vtgate_count=$VTGATE_COUNT -if [ $vtgate_count -eq 0 ]; then - vtgate_count=$(($total_tablet_count/4>3?$total_tablet_count/4:3)) -fi - -echo "****************************" -echo "*Creating vitess cluster:" -echo "* Shards: $SHARDS" -echo "* Tablets per shard: $TABLETS_PER_SHARD" -echo "* Rdonly per shard: $RDONLY_COUNT" -echo "* VTGate count: $vtgate_count" -echo "* Cells: $cells" -echo "****************************" - -echo 'Running etcd-up.sh' && CELLS=$CELLS ./etcd-up.sh -wait_for_running_tasks etcd-global 3 -for cell in $cells; do - wait_for_running_tasks etcd-$cell 3 -done - -echo 'Running vtctld-up.sh' && ./vtctld-up.sh -echo 'Running vttablet-up.sh' && CELLS=$CELLS ./vttablet-up.sh -echo 'Running vtgate-up.sh' && ./vtgate-up.sh - -wait_for_running_tasks vtctld 1 -wait_for_running_tasks vttablet $total_tablet_count -wait_for_running_tasks vtgate $vtgate_count - -vtctld_port=30001 -vtctld_ip=`kubectl get -o yaml nodes | grep 'type: ExternalIP' -B 1 | head -1 | awk '{print $NF}'` -vtctl_server="$vtctld_ip:$vtctld_port" -kvtctl="$GOPATH/bin/vtctlclient -server $vtctl_server" - -echo Waiting for tablets to be visible in the topology -counter=0 -while [ $counter -lt $MAX_VTTABLET_TOPO_WAIT_RETRIES ]; do - num_tablets=0 - for cell in $cells; do - num_tablets=$(($num_tablets+`$kvtctl ListAllTablets $cell | wc -l`)) - done - echo -en "\r$num_tablets out of $total_tablet_count in topology..." - if [ $num_tablets -eq $total_tablet_count ] - then - echo Complete - break - fi - update_spinner_value $counter - echo -n $cur_spinner - let counter=counter+1 - sleep 1 - if [ $counter -eq $MAX_VTTABLET_TOPO_WAIT_RETRIES ] - then - echo Timed out - fi -done - -# split_shard_count = num_shards for sharded keyspace, 0 for unsharded -split_shard_count=$num_shards -if [ $split_shard_count -eq 1 ]; then - split_shard_count=0 -fi - -echo -n Setting Keyspace Sharding Info... -$kvtctl SetKeyspaceShardingInfo -force -split_shard_count $split_shard_count test_keyspace keyspace_id uint64 -echo Done -echo -n Rebuilding Keyspace Graph... -$kvtctl RebuildKeyspaceGraph test_keyspace -echo Done -echo -n Reparenting... -shard_num=1 -for shard in $(echo $SHARDS | tr "," " "); do - $kvtctl InitShardMaster -force test_keyspace/$shard `echo $cells | awk '{print $1}'`-0000000${shard_num}00 - let shard_num=shard_num+1 -done -echo Done -echo -n Applying Schema... -$kvtctl ApplySchema -sql "$(cat create_test_table.sql)" test_keyspace -echo Done - -echo "****************************" -echo "* Complete!" -echo "* Use the following line to make an alias to kvtctl:" -echo "* alias kvtctl='\$GOPATH/bin/vtctlclient -server $vtctl_server'" -echo "* See the vtctld UI at: http://${vtctld_ip}:30000" -echo "****************************" - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-controller-template.yaml b/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-controller-template.yaml deleted file mode 100644 index 72fe245a2..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-controller-template.yaml +++ /dev/null @@ -1,55 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: vtctld -spec: - replicas: 1 - template: - metadata: - labels: - component: vtctld - app: vitess - spec: - containers: - - name: vtctld - image: vitess/lite:v2.0.0-alpha5 - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - - name: certs - readOnly: true - mountPath: /etc/ssl/certs - resources: - limits: - memory: "128Mi" - cpu: "100m" - command: - - sh - - "-c" - - >- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt && - su -p -c "/vt/bin/vtctld - -debug - -templates $VTTOP/go/cmd/vtctld/templates - -web_dir $VTTOP/web/vtctld - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port 15000 - -grpc_port 15001 - -service_map 'grpc-vtctl' - -topo_implementation etcd - -tablet_protocol grpc - -tablet_manager_protocol grpc - -etcd_global_addrs http://$ETCD_GLOBAL_SERVICE_HOST:$ETCD_GLOBAL_SERVICE_PORT - {{backup_flags}}" vitess - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - emptyDir: {} - - name: certs - hostPath: {path: /etc/ssl/certs} - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-down.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-down.sh deleted file mode 100755 index d5a0dfb18..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-down.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that stops vtctld. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Deleting vtctld replicationcontroller..." -$KUBECTL delete replicationcontroller vtctld - -echo "Deleting vtctld service..." -$KUBECTL delete service vtctld diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-service.yaml deleted file mode 100644 index 70d619a87..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-service.yaml +++ /dev/null @@ -1,22 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: vtctld - labels: - component: vtctld - app: vitess -spec: - ports: - - port: 15000 - name: web - targetPort: 15000 - nodePort: 30000 - - port: 15001 - name: grpc - targetPort: 15001 - nodePort: 30001 - selector: - component: vtctld - app: vitess - type: NodePort - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-up.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-up.sh deleted file mode 100755 index 257b2d773..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtctld-up.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that starts vtctld. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Creating vtctld service..." -$KUBECTL create -f vtctld-service.yaml - -echo "Creating vtctld replicationcontroller..." -# Expand template variables -sed_script="" -for var in backup_flags; do - sed_script+="s,{{$var}},${!var},g;" -done - -# Instantiate template and send to kubectl. -cat vtctld-controller-template.yaml | sed -e "$sed_script" | $KUBECTL create -f - - -server=$(get_vtctld_addr) -echo -echo "vtctld address: http://$server" - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-controller-template.yaml b/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-controller-template.yaml deleted file mode 100644 index 03c9665b2..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-controller-template.yaml +++ /dev/null @@ -1,45 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: vtgate -spec: - replicas: {{replicas}} - template: - metadata: - labels: - component: vtgate - app: vitess - spec: - containers: - - name: vtgate - image: vitess/lite:v2.0.0-alpha5 - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - resources: - limits: - memory: "512Mi" - cpu: "500m" - command: - - sh - - "-c" - - >- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt && - su -p -c "/vt/bin/vtgate - -topo_implementation etcd - -etcd_global_addrs http://$ETCD_GLOBAL_SERVICE_HOST:$ETCD_GLOBAL_SERVICE_PORT - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port 15001 - -tablet_protocol grpc - -service_map 'bsonrpc-vt-vtgateservice' - -cell test" vitess - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - emptyDir: {} - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-down.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-down.sh deleted file mode 100755 index cf72e840b..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-down.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that stops vtgate. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Deleting vtgate replicationcontroller..." -$KUBECTL delete replicationcontroller vtgate - -echo "Deleting vtgate service..." -$KUBECTL delete service vtgate diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-service.yaml b/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-service.yaml deleted file mode 100644 index 192968aa2..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: vtgate - labels: - component: vtgate - app: vitess -spec: - ports: - - port: 15001 - selector: - component: vtgate - app: vitess - type: LoadBalancer - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-up.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-up.sh deleted file mode 100755 index b7e327cc6..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vtgate-up.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that starts a vtgate replicationcontroller. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -VTGATE_REPLICAS=${VTGATE_REPLICAS:-3} -VTGATE_TEMPLATE=${VTGATE_TEMPLATE:-'vtgate-controller-template.yaml'} - -replicas=$VTGATE_REPLICAS - -echo "Creating vtgate service..." -$KUBECTL create -f vtgate-service.yaml - -sed_script="" -for var in replicas; do - sed_script+="s,{{$var}},${!var},g;" -done - -echo "Creating vtgate replicationcontroller..." -cat $VTGATE_TEMPLATE | sed -e "$sed_script" | $KUBECTL create -f - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vttablet-down.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/vttablet-down.sh deleted file mode 100755 index 0683f1f7d..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vttablet-down.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that tears down the vttablet pods started by -# vttablet-up.sh. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -server=$(get_vtctld_addr) - -# Delete the pods for all shards -CELLS=${CELLS:-'test'} -keyspace='test_keyspace' -SHARDS=${SHARDS:-'0'} -TABLETS_PER_SHARD=${TABLETS_PER_SHARD:-5} -UID_BASE=${UID_BASE:-100} - -num_shards=`echo $SHARDS | tr "," " " | wc -w` -uid_base=$UID_BASE - -for shard in `seq 1 $num_shards`; do - cell_index=0 - for cell in `echo $CELLS | tr "," " "`; do - for uid_index in `seq 0 $(($TABLETS_PER_SHARD-1))`; do - uid=$[$uid_base + $uid_index + $cell_index] - printf -v alias '%s-%010d' $cell $uid - - echo "Deleting pod for tablet $alias..." - $KUBECTL delete pod vttablet-$uid - done - let cell_index=cell_index+100000000 - done - let uid_base=uid_base+100 -done - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vttablet-pod-template.yaml b/vendor/k8s.io/kubernetes/examples/storage/vitess/vttablet-pod-template.yaml deleted file mode 100644 index d3d097e8f..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vttablet-pod-template.yaml +++ /dev/null @@ -1,128 +0,0 @@ -kind: Pod -apiVersion: v1 -metadata: - name: vttablet-{{uid}} - labels: - component: vttablet - keyspace: "{{keyspace}}" - shard: "{{shard_label}}" - tablet: "{{alias}}" - app: vitess -spec: - containers: - - name: vttablet - image: vitess/lite:v2.0.0-alpha5 - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - - name: certs - readOnly: true - mountPath: /etc/ssl/certs - resources: - limits: - memory: "1Gi" - cpu: "500m" - command: - - bash - - "-c" - - >- - set -e - - mysql_socket="$VTDATAROOT/{{tablet_subdir}}/mysql.sock" - - mkdir -p $VTDATAROOT/tmp - - chown -R vitess /vt - - while [ ! -e $mysql_socket ]; do - echo "[$(date)] waiting for $mysql_socket" ; - sleep 1 ; - done - - su -p -s /bin/bash -c "mysql -u vt_dba -S $mysql_socket - -e 'CREATE DATABASE IF NOT EXISTS vt_{{keyspace}}'" vitess - - su -p -s /bin/bash -c "/vt/bin/vttablet - -topo_implementation etcd - -etcd_global_addrs http://$ETCD_GLOBAL_SERVICE_HOST:$ETCD_GLOBAL_SERVICE_PORT - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port {{port}} - -grpc_port {{grpc_port}} - -service_map 'grpc-queryservice,grpc-tabletmanager,grpc-updatestream' - -binlog_player_protocol grpc - -tablet-path {{alias}} - -tablet_hostname $(hostname -i) - -init_keyspace {{keyspace}} - -init_shard {{shard}} - -target_tablet_type {{tablet_type}} - -mysqlctl_socket $VTDATAROOT/mysqlctl.sock - -db-config-app-uname vt_app - -db-config-app-dbname vt_{{keyspace}} - -db-config-app-charset utf8 - -db-config-dba-uname vt_dba - -db-config-dba-dbname vt_{{keyspace}} - -db-config-dba-charset utf8 - -db-config-repl-uname vt_repl - -db-config-repl-dbname vt_{{keyspace}} - -db-config-repl-charset utf8 - -db-config-filtered-uname vt_filtered - -db-config-filtered-dbname vt_{{keyspace}} - -db-config-filtered-charset utf8 - -enable-rowcache - -rowcache-bin /usr/bin/memcached - -rowcache-socket $VTDATAROOT/{{tablet_subdir}}/memcache.sock - -health_check_interval 5s - -restore_from_backup {{backup_flags}}" vitess - - name: mysql - image: vitess/lite:v2.0.0-alpha5 - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - resources: - limits: - memory: "1Gi" - cpu: "500m" - command: - - sh - - "-c" - - >- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt - - su -p -c "/vt/bin/mysqlctld - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -tablet_uid {{uid}} - -socket_file $VTDATAROOT/mysqlctl.sock - -db-config-app-uname vt_app - -db-config-app-dbname vt_{{keyspace}} - -db-config-app-charset utf8 - -db-config-dba-uname vt_dba - -db-config-dba-dbname vt_{{keyspace}} - -db-config-dba-charset utf8 - -db-config-repl-uname vt_repl - -db-config-repl-dbname vt_{{keyspace}} - -db-config-repl-charset utf8 - -db-config-filtered-uname vt_filtered - -db-config-filtered-dbname vt_{{keyspace}} - -db-config-filtered-charset utf8 - -bootstrap_archive mysql-db-dir_10.0.13-MariaDB.tbz" vitess - # The bootstrap archive above contains an empty mysql data dir - # with user permissions set up as required by Vitess. The archive is - # included in the Docker image. - env: - - name: EXTRA_MY_CNF - value: /vt/config/mycnf/master_mariadb.cnf - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - emptyDir: {} - - name: certs - hostPath: {path: /etc/ssl/certs} - diff --git a/vendor/k8s.io/kubernetes/examples/storage/vitess/vttablet-up.sh b/vendor/k8s.io/kubernetes/examples/storage/vitess/vttablet-up.sh deleted file mode 100755 index 231b7589b..000000000 --- a/vendor/k8s.io/kubernetes/examples/storage/vitess/vttablet-up.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash - -# 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. - -# This is an example script that creates a vttablet deployment. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -# Create the pods for shard-0 -CELLS=${CELLS:-'test'} -keyspace='test_keyspace' -SHARDS=${SHARDS:-'0'} -TABLETS_PER_SHARD=${TABLETS_PER_SHARD:-5} -port=15002 -grpc_port=16002 -UID_BASE=${UID_BASE:-100} -VTTABLET_TEMPLATE=${VTTABLET_TEMPLATE:-'vttablet-pod-template.yaml'} -RDONLY_COUNT=${RDONLY_COUNT:-2} - -uid_base=$UID_BASE -for shard in $(echo $SHARDS | tr "," " "); do - cell_index=0 - for cell in `echo $CELLS | tr ',' ' '`; do - echo "Creating $keyspace.shard-$shard pods in cell $CELL..." - for uid_index in `seq 0 $(($TABLETS_PER_SHARD-1))`; do - uid=$[$uid_base + $uid_index + $cell_index] - printf -v alias '%s-%010d' $cell $uid - printf -v tablet_subdir 'vt_%010d' $uid - - echo "Creating pod for tablet $alias..." - - # Add xx to beginning or end if there is a dash. K8s does not allow for - # leading or trailing dashes for labels - shard_label=`echo $shard | sed s'/[-]$/-xx/' | sed s'/^-/xx-/'` - - tablet_type=replica - if [ $uid_index -gt $(($TABLETS_PER_SHARD-$RDONLY_COUNT-1)) ]; then - tablet_type=rdonly - fi - - # Expand template variables - sed_script="" - for var in alias cell uid keyspace shard shard_label port grpc_port tablet_subdir tablet_type backup_flags; do - sed_script+="s,{{$var}},${!var},g;" - done - - # Instantiate template and send to kubectl. - cat $VTTABLET_TEMPLATE | sed -e "$sed_script" | $KUBECTL create -f - - done - let cell_index=cell_index+100000000 - done - let uid_base=uid_base+100 -done diff --git a/vendor/k8s.io/kubernetes/examples/storm/README.md b/vendor/k8s.io/kubernetes/examples/storm/README.md deleted file mode 100644 index 0867b35f1..000000000 --- a/vendor/k8s.io/kubernetes/examples/storm/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/storm/README.md](https://github.com/kubernetes/examples/blob/master/staging/storm/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/storm/storm-nimbus-service.json b/vendor/k8s.io/kubernetes/examples/storm/storm-nimbus-service.json deleted file mode 100644 index 2a8f71349..000000000 --- a/vendor/k8s.io/kubernetes/examples/storm/storm-nimbus-service.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "nimbus", - "labels": { - "name": "nimbus" - } - }, - "spec": { - "ports": [ - { - "port": 6627 - } - ], - "selector": { - "name": "nimbus" - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/storm/storm-nimbus.json b/vendor/k8s.io/kubernetes/examples/storm/storm-nimbus.json deleted file mode 100644 index e9a2f927a..000000000 --- a/vendor/k8s.io/kubernetes/examples/storm/storm-nimbus.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "nimbus", - "labels": { - "name": "nimbus" - } - }, - "spec": { - "containers": [ - { - "name": "nimbus", - "image": "mattf/storm-nimbus", - "ports": [ - { - "containerPort": 6627 - } - ], - "resources": { - "limits": { - "cpu": "100m" - } - } - } - ] - } -} diff --git a/vendor/k8s.io/kubernetes/examples/storm/storm-worker-controller.json b/vendor/k8s.io/kubernetes/examples/storm/storm-worker-controller.json deleted file mode 100644 index 0806b2745..000000000 --- a/vendor/k8s.io/kubernetes/examples/storm/storm-worker-controller.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "kind": "ReplicationController", - "apiVersion": "v1", - "metadata": { - "name": "storm-worker-controller", - "labels": { - "name": "storm-worker" - } - }, - "spec": { - "replicas": 2, - "selector": { - "name": "storm-worker" - }, - "template": { - "metadata": { - "labels": { - "name": "storm-worker", - "uses": "nimbus" - } - }, - "spec": { - "containers": [ - { - "name": "storm-worker", - "image": "mattf/storm-worker", - "ports": [ - { - "hostPort": 6700, - "containerPort": 6700 - }, - { - "hostPort": 6701, - "containerPort": 6701 - }, - { - "hostPort": 6702, - "containerPort": 6702 - }, - { - "hostPort": 6703, - "containerPort": 6703 - } - ], - "resources": { - "limits": { - "cpu": "200m" - } - } - } - ] - } - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/storm/zookeeper-service.json b/vendor/k8s.io/kubernetes/examples/storm/zookeeper-service.json deleted file mode 100644 index bbfc515bd..000000000 --- a/vendor/k8s.io/kubernetes/examples/storm/zookeeper-service.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "zookeeper", - "labels": { - "name": "zookeeper" - } - }, - "spec": { - "ports": [ - { - "port": 2181 - } - ], - "selector": { - "name": "zookeeper" - } - } -} diff --git a/vendor/k8s.io/kubernetes/examples/storm/zookeeper.json b/vendor/k8s.io/kubernetes/examples/storm/zookeeper.json deleted file mode 100644 index 89b82b7bc..000000000 --- a/vendor/k8s.io/kubernetes/examples/storm/zookeeper.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "zookeeper", - "labels": { - "name": "zookeeper" - } - }, - "spec": { - "containers": [ - { - "name": "zookeeper", - "image": "mattf/zookeeper", - "ports": [ - { - "containerPort": 2181 - } - ], - "resources": { - "limits": { - "cpu": "100m" - } - } - } - ] - } -} diff --git a/vendor/k8s.io/kubernetes/examples/sysdig-cloud/README.md b/vendor/k8s.io/kubernetes/examples/sysdig-cloud/README.md deleted file mode 100644 index 23678fe16..000000000 --- a/vendor/k8s.io/kubernetes/examples/sysdig-cloud/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/sysdig-cloud/README.md](https://github.com/kubernetes/examples/blob/master/staging/sysdig-cloud/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/sysdig-cloud/sysdig-daemonset.yaml b/vendor/k8s.io/kubernetes/examples/sysdig-cloud/sysdig-daemonset.yaml deleted file mode 100644 index 3cfd4a54f..000000000 --- a/vendor/k8s.io/kubernetes/examples/sysdig-cloud/sysdig-daemonset.yaml +++ /dev/null @@ -1,73 +0,0 @@ -#Use this sysdig.yaml when Daemon Sets are enabled on Kubernetes (minimum version 1.1.1). Otherwise use the RC method. - -apiVersion: extensions/v1beta1 -kind: DaemonSet -metadata: - name: sysdig-agent - labels: - app: sysdig-agent -spec: - template: - metadata: - labels: - name: sysdig-agent - spec: - volumes: - - name: docker-sock - hostPath: - path: /var/run/docker.sock - type: Socket - - name: dev-vol - hostPath: - path: /dev - - name: proc-vol - hostPath: - path: /proc - - name: boot-vol - hostPath: - path: /boot - - name: modules-vol - hostPath: - path: /lib/modules - - name: usr-vol - hostPath: - path: /usr - hostNetwork: true - hostPID: true - containers: - - name: sysdig-agent - image: sysdig/agent - securityContext: - privileged: true - env: - - name: ACCESS_KEY #REQUIRED - replace with your Sysdig Cloud access key - value: 8312341g-5678-abcd-4a2b2c-33bcsd655 -# - name: TAGS #OPTIONAL -# value: linux:ubuntu,dept:dev,local:nyc -# - name: COLLECTOR #OPTIONAL - on-prem install only -# value: 192.168.183.200 -# - name: SECURE #OPTIONAL - on-prem install only -# value: false -# - name: CHECK_CERTIFICATE #OPTIONAL - on-prem install only -# value: false -# - name: ADDITIONAL_CONF #OPTIONAL pass additional parameters to the agent such as authentication example provided here -# value: "k8s_uri: https://myacct:mypass@localhost:4430\nk8s_ca_certificate: k8s-ca.crt\nk8s_ssl_verify_certificate: true" - volumeMounts: - - mountPath: /host/var/run/docker.sock - name: docker-sock - readOnly: false - - mountPath: /host/dev - name: dev-vol - readOnly: false - - mountPath: /host/proc - name: proc-vol - readOnly: true - - mountPath: /host/boot - name: boot-vol - readOnly: true - - mountPath: /host/lib/modules - name: modules-vol - readOnly: true - - mountPath: /host/usr - name: usr-vol - readOnly: true diff --git a/vendor/k8s.io/kubernetes/examples/sysdig-cloud/sysdig-rc.yaml b/vendor/k8s.io/kubernetes/examples/sysdig-cloud/sysdig-rc.yaml deleted file mode 100644 index dfef08de1..000000000 --- a/vendor/k8s.io/kubernetes/examples/sysdig-cloud/sysdig-rc.yaml +++ /dev/null @@ -1,78 +0,0 @@ -#Use this sysdig.yaml when Daemon Sets are NOT enabled on Kubernetes (minimum version 1.1.1). If Daemon Sets are available, use the other example sysdig.yaml - that is the recommended method. - -apiVersion: v1 -kind: ReplicationController -metadata: - name: sysdig-agent - labels: - app: sysdig-agent -spec: - replicas: 100 #REQUIRED - replace with the maximum number of slave nodes in the cluster - template: - spec: - volumes: - - name: docker-sock - hostPath: - path: /var/run/docker.sock - type: Socket - - name: dev-vol - hostPath: - path: /dev - - name: proc-vol - hostPath: - path: /proc - - name: boot-vol - hostPath: - path: /boot - - name: modules-vol - hostPath: - path: /lib/modules - - name: usr-vol - hostPath: - path: /usr - hostNetwork: true - hostPID: true - containers: - - name: sysdig-agent - image: sysdig/agent - ports: - - containerPort: 6666 - hostPort: 6666 - securityContext: - privileged: true - env: - - name: ACCESS_KEY #REQUIRED - replace with your Sysdig Cloud access key - value: 8312341g-5678-abcd-4a2b2c-33bcsd655 -# - name: K8S_DELEGATED_NODE #OPTIONAL - only necessary when connecting remotely to API server -# value: -# - name: K8S_API_URI #OPTIONAL - only necessary when connecting remotely to API server -# value: "http[s]://[username:passwd@]host[:port]" -# - name: TAGS #OPTIONAL -# value: linux:ubuntu,dept:dev,local:nyc -# - name: COLLECTOR #OPTIONAL -# value: 192.168.183.200 -# - name: SECURE #OPTIONAL -# value: false -# - name: CHECK_CERTIFICATE #OPTIONAL -# value: false -# - name: ADDITIONAL_CONF #OPTIONAL -# value: "app_checks:\n - name: nginx\n check_module: nginx\n pattern:\n comm: nginx\n conf:\n nginx_status_url: "http://localhost:{port}/nginx_status\"" - volumeMounts: - - mountPath: /host/var/run/docker.sock - name: docker-sock - readOnly: false - - mountPath: /host/dev - name: dev-vol - readOnly: false - - mountPath: /host/proc - name: proc-vol - readOnly: true - - mountPath: /host/boot - name: boot-vol - readOnly: true - - mountPath: /host/lib/modules - name: modules-vol - readOnly: true - - mountPath: /host/usr - name: usr-vol - readOnly: true diff --git a/vendor/k8s.io/kubernetes/examples/volumes/aws_ebs/README.md b/vendor/k8s.io/kubernetes/examples/volumes/aws_ebs/README.md deleted file mode 100644 index 3edf78fef..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/aws_ebs/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/aws_ebs/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/aws_ebs/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/aws_ebs/aws-ebs-web.yaml b/vendor/k8s.io/kubernetes/examples/volumes/aws_ebs/aws-ebs-web.yaml deleted file mode 100644 index 56667f538..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/aws_ebs/aws-ebs-web.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: aws-web -spec: - containers: - - name: web - image: nginx - ports: - - name: web - containerPort: 80 - protocol: tcp - volumeMounts: - - name: html-volume - mountPath: "/usr/share/nginx/html" - volumes: - - name: html-volume - awsElasticBlockStore: - # Enter the volume ID below - volumeID: volume_ID - fsType: ext4 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/azure_disk/README.md b/vendor/k8s.io/kubernetes/examples/volumes/azure_disk/README.md deleted file mode 100644 index f495261e3..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/azure_disk/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/azure_disk/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/azure_disk/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/azure_disk/azure.yaml b/vendor/k8s.io/kubernetes/examples/volumes/azure_disk/azure.yaml deleted file mode 100644 index 04df7fb9b..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/azure_disk/azure.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: azure -spec: - containers: - - image: kubernetes/pause - name: azure - volumeMounts: - - name: azure - mountPath: /mnt/azure - volumes: - - name: azure - azureDisk: - diskName: test.vhd - diskURI: https://someaccount.blob.microsoft.net/vhds/test.vhd diff --git a/vendor/k8s.io/kubernetes/examples/volumes/azure_file/README.md b/vendor/k8s.io/kubernetes/examples/volumes/azure_file/README.md deleted file mode 100644 index 007a6841b..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/azure_file/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/azure_file/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/azure_file/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/azure_file/azure.yaml b/vendor/k8s.io/kubernetes/examples/volumes/azure_file/azure.yaml deleted file mode 100644 index 6567f3079..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/azure_file/azure.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: azure -spec: - containers: - - image: kubernetes/pause - name: azure - volumeMounts: - - name: azure - mountPath: /mnt/azure - volumes: - - name: azure - azureFile: - secretName: azure-secret - shareName: k8stest - readOnly: false diff --git a/vendor/k8s.io/kubernetes/examples/volumes/azure_file/secret/azure-secret.yaml b/vendor/k8s.io/kubernetes/examples/volumes/azure_file/secret/azure-secret.yaml deleted file mode 100644 index bf448bd9c..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/azure_file/secret/azure-secret.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: azure-secret -type: Opaque -data: - azurestorageaccountname: azhzdGVzdA== - azurestorageaccountkey: eElGMXpKYm5ub2pGTE1Ta0JwNTBteDAyckhzTUsyc2pVN21GdDRMMTNob0I3ZHJBYUo4akQ2K0E0NDNqSm9nVjd5MkZVT2hRQ1dQbU02WWFOSHk3cWc9PQ== diff --git a/vendor/k8s.io/kubernetes/examples/volumes/cephfs/README.md b/vendor/k8s.io/kubernetes/examples/volumes/cephfs/README.md deleted file mode 100644 index 851e01c57..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/cephfs/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/cephfs/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/cephfs/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/cephfs/cephfs-with-secret.yaml b/vendor/k8s.io/kubernetes/examples/volumes/cephfs/cephfs-with-secret.yaml deleted file mode 100644 index c3d7a02cb..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/cephfs/cephfs-with-secret.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: cephfs2 -spec: - containers: - - name: cephfs-rw - image: kubernetes/pause - volumeMounts: - - mountPath: "/mnt/cephfs" - name: cephfs - volumes: - - name: cephfs - cephfs: - monitors: - - 10.16.154.78:6789 - - 10.16.154.82:6789 - - 10.16.154.83:6789 - user: admin - secretRef: - name: ceph-secret - readOnly: true diff --git a/vendor/k8s.io/kubernetes/examples/volumes/cephfs/cephfs.yaml b/vendor/k8s.io/kubernetes/examples/volumes/cephfs/cephfs.yaml deleted file mode 100644 index e4eb395b6..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/cephfs/cephfs.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: cephfs -spec: - containers: - - name: cephfs-rw - image: kubernetes/pause - volumeMounts: - - mountPath: "/mnt/cephfs" - name: cephfs - volumes: - - name: cephfs - cephfs: - monitors: - - 10.16.154.78:6789 - - 10.16.154.82:6789 - - 10.16.154.83:6789 - # by default the path is /, but you can override and mount a specific path of the filesystem by using the path attribute - # path: /some/path/in/side/cephfs - user: admin - secretFile: "/etc/ceph/admin.secret" - readOnly: true diff --git a/vendor/k8s.io/kubernetes/examples/volumes/cephfs/secret/ceph-secret.yaml b/vendor/k8s.io/kubernetes/examples/volumes/cephfs/secret/ceph-secret.yaml deleted file mode 100644 index e29a5535a..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/cephfs/secret/ceph-secret.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: ceph-secret -data: - key: QVFCMTZWMVZvRjVtRXhBQTVrQ1FzN2JCajhWVUxSdzI2Qzg0SEE9PQ== diff --git a/vendor/k8s.io/kubernetes/examples/volumes/cinder/README.md b/vendor/k8s.io/kubernetes/examples/volumes/cinder/README.md deleted file mode 100644 index 4d008c58e..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/cinder/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/cinder/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/cinder/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/cinder/cinder-web.yaml b/vendor/k8s.io/kubernetes/examples/volumes/cinder/cinder-web.yaml deleted file mode 100644 index 4692ac868..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/cinder/cinder-web.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: cinder-web -spec: - containers: - - name: web - image: nginx - ports: - - name: web - containerPort: 80 - protocol: tcp - volumeMounts: - - name: html-volume - mountPath: "/usr/share/nginx/html" - volumes: - - name: html-volume - cinder: - # Enter the volume ID below - volumeID: volume_ID - fsType: ext4 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/fibre_channel/README.md b/vendor/k8s.io/kubernetes/examples/volumes/fibre_channel/README.md deleted file mode 100644 index 308bae602..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/fibre_channel/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/fibre_channel/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/fibre_channel/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/fibre_channel/fc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/fibre_channel/fc.yaml deleted file mode 100644 index ac28bee4a..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/fibre_channel/fc.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: fc -spec: - containers: - - image: kubernetes/pause - name: fc - volumeMounts: - - name: fc-vol - mountPath: /mnt/fc - volumes: - - name: fc-vol - fc: - targetWWNs: ['500a0982991b8dc5', '500a0982891b8dc5'] - lun: 2 - fsType: ext4 - readOnly: true diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/README.md b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/README.md deleted file mode 100644 index a872b6524..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/community/blob/master/contributors/devel/flexvolume.md](https://github.com/kubernetes/community/blob/master/contributors/devel/flexvolume.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/Dockerfile b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/Dockerfile deleted file mode 100644 index 55ef6011a..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2018 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. - -FROM busybox -WORKDIR . - -# TODO Change to your desired driver. -COPY ./drivers/dummy /dummy - -COPY deploy.sh /deploy.sh -CMD /bin/sh /deploy.sh diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/README.md b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/README.md deleted file mode 100644 index f9b0480a3..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/README.md +++ /dev/null @@ -1,7 +0,0 @@ -This directory contains an example of the DaemonSet Flexvolume driver deployment method. See documentation [here](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/flexvolume-deployment.md#recommended-driver-deployment-method). - -Steps to use the DaemonSet deployment method: -1. Copy the Flexvolume driver to `drivers` directory. To get a basic example running, copy the `dummy` driver from the parent directory. -1. If you'd like to just get a basic example running, you could skip this step. Otherwise, change the places marked with `TODO` in all files. -1. Build the deployment Docker image and upload to your container registry. -1. Create the DaemonSet. diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/deploy.sh b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/deploy.sh deleted file mode 100755 index ee8ae0ee2..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/deploy.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# Copyright 2018 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. - -set -o errexit -set -o pipefail - -# TODO change to your desired driver. -VENDOR=${VENDOR:-k8s} -DRIVER=${DRIVER:-dummy} - -# Assuming the single driver file is located at /$DRIVER inside the DaemonSet image. - -driver_dir=$VENDOR${VENDOR:+"~"}${DRIVER} -if [ ! -d "/flexmnt/$driver_dir" ]; then - mkdir "/flexmnt/$driver_dir" -fi - -tmp_driver=.tmp_$DRIVER -cp "/$DRIVER" "/flexmnt/$driver_dir/$tmp_driver" -mv -f "/flexmnt/$driver_dir/$tmp_driver" "/flexmnt/$driver_dir/$DRIVER" - -while : ; do - sleep 3600 -done diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/ds.yaml b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/ds.yaml deleted file mode 100644 index 9089bd19f..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/deploy/ds.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: DaemonSet -metadata: - name: flex-ds -spec: - template: - metadata: - name: flex-deploy - labels: - app: flex-deploy - spec: - containers: - # TODO Change to your container registry. - - image: "" - name: flex-deploy - securityContext: - privileged: true - volumeMounts: - - mountPath: /flexmnt - name: flexvolume-mount - volumes: - - name: flexvolume-mount - hostPath: - # TODO Change to the Flexvolume plugin directory of your cluster. - path: /usr/libexec/kubernetes/kubelet-plugins/volume/exec/ diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/dummy b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/dummy deleted file mode 100755 index 4b4012ced..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/dummy +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh - -# 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. - -# This driver implements a tmpfs with a pre-populated file index.html. - -FLEX_DUMMY_LOG=${FLEX_DUMMY_LOG:-"/tmp/flex-dummy.log"} - -log() { - printf "$*" >&1 -} - -debug() { - echo "$(date) $*" >> "${FLEX_DUMMY_LOG}" -} - -domount() { - debug "domount $@" - MNTPATH=$1 - mkdir -p ${MNTPATH} >/dev/null 2>&1 - mount -t tmpfs none ${MNTPATH} >/dev/null 2>&1 - echo "Hello from flexvolume!" >> "${MNTPATH}/index.html" - log "{\"status\":\"Success\"}" - exit 0 -} - -unmount() { - debug "unmount $@" - MNTPATH=$1 - rm ${MNTPATH}/index.html >/dev/null 2>&1 - umount ${MNTPATH} >/dev/null 2>&1 - log "{\"status\":\"Success\"}" - exit 0 -} - -op=$1 - -if [ "$op" = "init" ]; then - debug "init $@" - log "{\"status\":\"Success\",\"capabilities\":{\"attach\":false}}" - exit 0 -fi - -shift - -case "$op" in - mount) - domount $* - ;; - unmount) - unmount $* - ;; - *) - log "{\"status\":\"Not supported\"}" - exit 0 -esac - -exit 1 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/dummy-attachable b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/dummy-attachable deleted file mode 100755 index 8afd6b4bf..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/dummy-attachable +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/sh - -# 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. - -# This driver implements a tmpfs with a pre-populated file index.html. -# Attach is required, but it is a no-op that always returns success. - -FLEX_DUMMY_LOG=${FLEX_DUMMY_LOG:-"/tmp/flex-dummy.log"} - -VALID_MNTDEVICE=foo - -# attach always returns one valid mount device so a different device -# showing up in a subsequent driver call implies a bug -validateMountDeviceOrDie() { - MNTDEVICE=$1 - CALL=$2 - if [ "$MNTDEVICE" != "$VALID_MNTDEVICE" ]; then - log "{\"status\":\"Failure\",\"message\":\"call "${CALL}" expected device "${VALID_MNTDEVICE}", got device "${MNTDEVICE}"\"}" - exit 0 - fi -} - -log() { - printf "$*" >&1 -} - -debug() { - echo "$(date) $*" >> "${FLEX_DUMMY_LOG}" -} - -attach() { - debug "attach $@" - log "{\"status\":\"Success\",\"device\":\""${VALID_MNTDEVICE}"\"}" - exit 0 -} - -detach() { - debug "detach $@" - log "{\"status\":\"Success\"}" - exit 0 -} - -waitforattach() { - debug "waitforattach $@" - MNTDEVICE=$1 - validateMountDeviceOrDie "$MNTDEVICE" "waitforattach" - log "{\"status\":\"Success\",\"device\":\""${MNTDEVICE}"\"}" - exit 0 -} - -isattached() { - debug "isattached $@" - log "{\"status\":\"Success\",\"attached\":true}" - exit 0 -} - -domountdevice() { - debug "domountdevice $@" - MNTDEVICE=$2 - validateMountDeviceOrDie "$MNTDEVICE" "domountdevice" - MNTPATH=$1 - mkdir -p ${MNTPATH} >/dev/null 2>&1 - mount -t tmpfs none ${MNTPATH} >/dev/null 2>&1 - echo "Hello from flexvolume!" >> "${MNTPATH}/index.html" - log "{\"status\":\"Success\"}" - exit 0 -} - -unmountdevice() { - debug "unmountdevice $@" - MNTDEVICE=$2 - validateMountDeviceOrDie "$MNTDEVICE" "unmountdevice" - MNTPATH=$1 - rm "${MNTPATH}/index.html" >/dev/null 2>&1 - umount ${MNTPATH} >/dev/null 2>&1 - log "{\"status\":\"Success\"}" - exit 0 -} - -op=$1 - -if [ "$op" = "init" ]; then - debug "init $@" - log "{\"status\":\"Success\",\"capabilities\":{\"attach\":true}}" - exit 0 -fi - -shift - -case "$op" in - attach) - attach $* - ;; - detach) - detach $* - ;; - waitforattach) - waitforattach $* - ;; - isattached) - isattached $* - ;; - mountdevice) - domountdevice $* - ;; - unmountdevice) - unmountdevice $* - ;; - *) - log "{\"status\":\"Not supported\"}" - exit 0 -esac - -exit 1 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/lvm b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/lvm deleted file mode 100755 index f60af4840..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/lvm +++ /dev/null @@ -1,182 +0,0 @@ -#!/bin/bash - -# 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. - -# Notes: -# - Please install "jq" package before using this driver. -usage() { - err "Invalid usage. Usage: " - err "\t$0 init" - err "\t$0 attach " - err "\t$0 detach " - err "\t$0 waitforattach " - err "\t$0 mountdevice " - err "\t$0 unmountdevice " - err "\t$0 isattached " - exit 1 -} - -err() { - echo -ne $* 1>&2 -} - -log() { - echo -ne $* >&1 -} - -ismounted() { - MOUNT=`findmnt -n ${MNTPATH} 2>/dev/null | cut -d' ' -f1` - if [ "${MOUNT}" == "${MNTPATH}" ]; then - echo "1" - else - echo "0" - fi -} - -getdevice() { - VOLUMEID=$(echo ${JSON_PARAMS} | jq -r '.volumeID') - VG=$(echo ${JSON_PARAMS}|jq -r '.volumegroup') - - # LVM substitutes - with -- - VOLUMEID=`echo $VOLUMEID|sed s/-/--/g` - VG=`echo $VG|sed s/-/--/g` - - DMDEV="/dev/mapper/${VG}-${VOLUMEID}" - echo ${DMDEV} -} - -attach() { - JSON_PARAMS=$1 - SIZE=$(echo $1 | jq -r '.size') - - DMDEV=$(getdevice) - if [ ! -b "${DMDEV}" ]; then - err "{\"status\": \"Failure\", \"message\": \"Volume ${VOLUMEID} does not exist\"}" - exit 1 - fi - log "{\"status\": \"Success\", \"device\":\"${DMDEV}\"}" - exit 0 -} - -detach() { - log "{\"status\": \"Success\"}" - exit 0 -} - -waitforattach() { - shift - attach $* -} - -domountdevice() { - MNTPATH=$1 - DMDEV=$2 - FSTYPE=$(echo $3|jq -r '.["kubernetes.io/fsType"]') - - if [ ! -b "${DMDEV}" ]; then - err "{\"status\": \"Failure\", \"message\": \"${DMDEV} does not exist\"}" - exit 1 - fi - - if [ $(ismounted) -eq 1 ] ; then - log "{\"status\": \"Success\"}" - exit 0 - fi - - VOLFSTYPE=`blkid -o udev ${DMDEV} 2>/dev/null|grep "ID_FS_TYPE"|cut -d"=" -f2` - if [ "${VOLFSTYPE}" == "" ]; then - mkfs -t ${FSTYPE} ${DMDEV} >/dev/null 2>&1 - if [ $? -ne 0 ]; then - err "{ \"status\": \"Failure\", \"message\": \"Failed to create fs ${FSTYPE} on device ${DMDEV}\"}" - exit 1 - fi - fi - - mkdir -p ${MNTPATH} &> /dev/null - - mount ${DMDEV} ${MNTPATH} &> /dev/null - if [ $? -ne 0 ]; then - err "{ \"status\": \"Failure\", \"message\": \"Failed to mount device ${DMDEV} at ${MNTPATH}\"}" - exit 1 - fi - log "{\"status\": \"Success\"}" - exit 0 -} - -unmountdevice() { - MNTPATH=$1 - if [ ! -d ${MNTPATH} ]; then - log "{\"status\": \"Success\"}" - exit 0 - fi - - if [ $(ismounted) -eq 0 ] ; then - log "{\"status\": \"Success\"}" - exit 0 - fi - - umount ${MNTPATH} &> /dev/null - if [ $? -ne 0 ]; then - err "{ \"status\": \"Failed\", \"message\": \"Failed to unmount volume at ${MNTPATH}\"}" - exit 1 - fi - - log "{\"status\": \"Success\"}" - exit 0 -} - -isattached() { - log "{\"status\": \"Success\", \"attached\":true}" - exit 0 -} - -op=$1 - -if [ "$op" = "init" ]; then - log "{\"status\": \"Success\"}" - exit 0 -fi - -if [ $# -lt 2 ]; then - usage -fi - -shift - -case "$op" in - attach) - attach $* - ;; - detach) - detach $* - ;; - waitforattach) - waitforattach $* - ;; - mountdevice) - domountdevice $* - ;; - unmountdevice) - unmountdevice $* - ;; - isattached) - isattached $* - ;; - *) - log "{ \"status\": \"Not supported\" }" - exit 0 -esac - -exit 1 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nfs b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nfs deleted file mode 100755 index 4d0977cec..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nfs +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/bash - -# 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. - -# Notes: -# - Please install "jq" package before using this driver. -usage() { - err "Invalid usage. Usage: " - err "\t$0 init" - err "\t$0 mount " - err "\t$0 unmount " - exit 1 -} - -err() { - echo -ne $* 1>&2 -} - -log() { - echo -ne $* >&1 -} - -ismounted() { - MOUNT=`findmnt -n ${MNTPATH} 2>/dev/null | cut -d' ' -f1` - if [ "${MOUNT}" == "${MNTPATH}" ]; then - echo "1" - else - echo "0" - fi -} - -domount() { - MNTPATH=$1 - - NFS_SERVER=$(echo $2 | jq -r '.server') - SHARE=$(echo $2 | jq -r '.share') - - if [ $(ismounted) -eq 1 ] ; then - log '{"status": "Success"}' - exit 0 - fi - - mkdir -p ${MNTPATH} &> /dev/null - - mount -t nfs ${NFS_SERVER}:/${SHARE} ${MNTPATH} &> /dev/null - if [ $? -ne 0 ]; then - err "{ \"status\": \"Failure\", \"message\": \"Failed to mount ${NFS_SERVER}:${SHARE} at ${MNTPATH}\"}" - exit 1 - fi - log '{"status": "Success"}' - exit 0 -} - -unmount() { - MNTPATH=$1 - if [ $(ismounted) -eq 0 ] ; then - log '{"status": "Success"}' - exit 0 - fi - - umount ${MNTPATH} &> /dev/null - if [ $? -ne 0 ]; then - err "{ \"status\": \"Failed\", \"message\": \"Failed to unmount volume at ${MNTPATH}\"}" - exit 1 - fi - - log '{"status": "Success"}' - exit 0 -} - -op=$1 - -if ! command -v jq >/dev/null 2>&1; then - err "{ \"status\": \"Failure\", \"message\": \"'jq' binary not found. Please install jq package before using this driver\"}" - exit 1 -fi - -if [ "$op" = "init" ]; then - log '{"status": "Success", "capabilities": {"attach": false}}' - exit 0 -fi - -if [ $# -lt 2 ]; then - usage -fi - -shift - -case "$op" in - mount) - domount $* - ;; - unmount) - unmount $* - ;; - *) - log '{"status": "Not supported"}' - exit 0 -esac - -exit 1 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-dummy-attachable.yaml b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-dummy-attachable.yaml deleted file mode 100644 index 80b322c98..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-dummy-attachable.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: nginx-dummy-attachable - namespace: default -spec: - containers: - - name: nginx-dummy-attachable - image: nginx - volumeMounts: - - name: dummy-attachable - mountPath: /data - ports: - - containerPort: 80 - volumes: - - name: dummy-attachable - flexVolume: - driver: "k8s/dummy-attachable" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-dummy.yaml b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-dummy.yaml deleted file mode 100644 index 33ee34251..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-dummy.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: nginx-dummy - namespace: default -spec: - containers: - - name: nginx-dummy - image: nginx - volumeMounts: - - name: dummy - mountPath: /data - ports: - - containerPort: 80 - volumes: - - name: dummy - flexVolume: - driver: "k8s/dummy" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-lvm.yaml b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-lvm.yaml deleted file mode 100644 index c7d7859cc..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-lvm.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: nginx - namespace: default -spec: - containers: - - name: nginx - image: nginx - volumeMounts: - - name: test - mountPath: /data - ports: - - containerPort: 80 - volumes: - - name: test - flexVolume: - driver: "kubernetes.io/lvm" - fsType: "ext4" - options: - volumeID: "vol1" - size: "1000m" - volumegroup: "kube_vg" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-nfs.yaml b/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-nfs.yaml deleted file mode 100644 index 177c1e8f4..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flexvolume/nginx-nfs.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: nginx-nfs - namespace: default -spec: - containers: - - name: nginx-nfs - image: nginx - volumeMounts: - - name: test - mountPath: /data - ports: - - containerPort: 80 - volumes: - - name: test - flexVolume: - driver: "k8s/nfs" - fsType: "nfs" - options: - server: "172.16.0.25" - share: "dws_nas_scratch" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flocker/README.md b/vendor/k8s.io/kubernetes/examples/volumes/flocker/README.md deleted file mode 100644 index 906446f4c..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flocker/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/flocker/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/flocker/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flocker/flocker-pod-with-rc.yml b/vendor/k8s.io/kubernetes/examples/volumes/flocker/flocker-pod-with-rc.yml deleted file mode 100644 index 01a40f881..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flocker/flocker-pod-with-rc.yml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: flocker-ghost - labels: - app: flocker-ghost -spec: - ports: - # the port that this service should serve on - - port: 80 - targetPort: 80 - selector: - app: flocker-ghost ---- -apiVersion: v1 -kind: ReplicationController -metadata: - name: flocker-ghost - # these labels can be applied automatically - # from the labels in the pod template if not set - labels: - purpose: demo -spec: - replicas: 1 - template: - metadata: - labels: - app: flocker-ghost - spec: - containers: - - name: flocker-ghost - image: ghost:0.7.1 - env: - - name: GET_HOSTS_FROM - value: dns - ports: - - containerPort: 2368 - hostPort: 80 - protocol: TCP - volumeMounts: - # name must match the volume name below - - name: ghost-data - mountPath: "/var/lib/ghost" - volumes: - - name: ghost-data - flocker: - datasetName: my-flocker-vol diff --git a/vendor/k8s.io/kubernetes/examples/volumes/flocker/flocker-pod.yml b/vendor/k8s.io/kubernetes/examples/volumes/flocker/flocker-pod.yml deleted file mode 100644 index fb923cd49..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/flocker/flocker-pod.yml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: flocker-web -spec: - containers: - - name: web - image: nginx - ports: - - name: web - containerPort: 80 - volumeMounts: - # name must match the volume name below - - name: www-root - mountPath: "/usr/share/nginx/html" - volumes: - - name: www-root - flocker: - datasetName: my-flocker-vol diff --git a/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/README.md b/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/README.md deleted file mode 100644 index ae7d23c5f..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/glusterfs/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/glusterfs/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/glusterfs-endpoints.json b/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/glusterfs-endpoints.json deleted file mode 100644 index 740ce4258..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/glusterfs-endpoints.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "kind": "Endpoints", - "apiVersion": "v1", - "metadata": { - "name": "glusterfs-cluster" - }, - "subsets": [ - { - "addresses": [ - { - "ip": "10.240.106.152" - } - ], - "ports": [ - { - "port": 1 - } - ] - }, - { - "addresses": [ - { - "ip": "10.240.79.157" - } - ], - "ports": [ - { - "port": 1 - } - ] - } - ] -} diff --git a/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/glusterfs-pod.json b/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/glusterfs-pod.json deleted file mode 100644 index 63c075be6..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/glusterfs-pod.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "glusterfs" - }, - "spec": { - "containers": [ - { - "name": "glusterfs", - "image": "nginx", - "volumeMounts": [ - { - "mountPath": "/mnt/glusterfs", - "name": "glusterfsvol" - } - ] - } - ], - "volumes": [ - { - "name": "glusterfsvol", - "glusterfs": { - "endpoints": "glusterfs-cluster", - "path": "kube_vol", - "readOnly": true - } - } - ] - } -} diff --git a/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/glusterfs-service.json b/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/glusterfs-service.json deleted file mode 100644 index 79139febd..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/glusterfs/glusterfs-service.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "glusterfs-cluster" - }, - "spec": { - "ports": [ - {"port": 1} - ] - } -} diff --git a/vendor/k8s.io/kubernetes/examples/volumes/iscsi/README.md b/vendor/k8s.io/kubernetes/examples/volumes/iscsi/README.md deleted file mode 100644 index 6b8ca9a85..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/iscsi/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/iscsi/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/iscsi/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/iscsi/chap-secret.yaml b/vendor/k8s.io/kubernetes/examples/volumes/iscsi/chap-secret.yaml deleted file mode 100644 index 5bc9cc874..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/iscsi/chap-secret.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: chap-secret -type: "kubernetes.io/iscsi-chap" -data: - discovery.sendtargets.auth.username: dXNlcg== - discovery.sendtargets.auth.password: ZGVtbw== - discovery.sendtargets.auth.username_in: bXVzZXI= - discovery.sendtargets.auth.password_in: bXBhc3M= - node.session.auth.username: dXNlcm5hbWU= - node.session.auth.password: cGFzc3dvcmQ= - node.session.auth.username_in: bXVzZXIy - node.session.auth.password_in: bXBhc3My diff --git a/vendor/k8s.io/kubernetes/examples/volumes/iscsi/iscsi-chap.yaml b/vendor/k8s.io/kubernetes/examples/volumes/iscsi/iscsi-chap.yaml deleted file mode 100644 index 1ddc2f02c..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/iscsi/iscsi-chap.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -apiVersion: v1 -kind: Pod -metadata: - name: iscsipd -spec: - containers: - - name: iscsipd-ro - image: kubernetes/pause - volumeMounts: - - mountPath: "/mnt/iscsipd" - name: iscsivol - volumes: - - name: iscsivol - iscsi: - targetPortal: 127.0.0.1 - iqn: iqn.2015-02.example.com:test - lun: 0 - fsType: ext4 - readOnly: true - chapAuthDiscovery: true - chapAuthSession: true - secretRef: - name: chap-secret diff --git a/vendor/k8s.io/kubernetes/examples/volumes/iscsi/iscsi.yaml b/vendor/k8s.io/kubernetes/examples/volumes/iscsi/iscsi.yaml deleted file mode 100644 index 46736eda8..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/iscsi/iscsi.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -apiVersion: v1 -kind: Pod -metadata: - name: iscsipd -spec: - containers: - - name: iscsipd-rw - image: kubernetes/pause - volumeMounts: - - mountPath: "/mnt/iscsipd" - name: iscsipd-rw - volumes: - - name: iscsipd-rw - iscsi: - targetPortal: 10.0.2.15:3260 - portals: ['10.0.2.16:3260', '10.0.2.17:3260'] - iqn: iqn.2001-04.com.example:storage.kube.sys1.xyz - lun: 0 - fsType: ext4 - readOnly: true diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/README.md b/vendor/k8s.io/kubernetes/examples/volumes/nfs/README.md deleted file mode 100644 index acd56f937..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/nfs/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/nfs/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-busybox-rc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-busybox-rc.yaml deleted file mode 100644 index 617d02755..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-busybox-rc.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# This mounts the nfs volume claim into /mnt and continuously -# overwrites /mnt/index.html with the time and hostname of the pod. - -apiVersion: v1 -kind: ReplicationController -metadata: - name: nfs-busybox -spec: - replicas: 2 - selector: - name: nfs-busybox - template: - metadata: - labels: - name: nfs-busybox - spec: - containers: - - image: busybox - command: - - sh - - -c - - 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep $(($RANDOM % 5 + 5)); done' - imagePullPolicy: IfNotPresent - name: busybox - volumeMounts: - # name must match the volume name below - - name: nfs - mountPath: "/mnt" - volumes: - - name: nfs - persistentVolumeClaim: - claimName: nfs diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/Dockerfile b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/Dockerfile deleted file mode 100644 index 96986bd80..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# 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. - -FROM centos -RUN yum -y install /usr/bin/ps nfs-utils && yum clean all -RUN mkdir -p /exports -ADD run_nfs.sh /usr/local/bin/ -ADD index.html /tmp/index.html -RUN chmod 644 /tmp/index.html - -# expose mountd 20048/tcp and nfsd 2049/tcp and rpcbind 111/tcp -EXPOSE 2049/tcp 20048/tcp 111/tcp 111/udp - -ENTRYPOINT ["/usr/local/bin/run_nfs.sh", "/exports"] diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/README.md b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/README.md deleted file mode 100644 index 0b3a8b319..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/nfs/nfs-data/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/nfs/nfs-data/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/index.html b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/index.html deleted file mode 100644 index cd0875583..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/index.html +++ /dev/null @@ -1 +0,0 @@ -Hello world! diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/run_nfs.sh b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/run_nfs.sh deleted file mode 100755 index fa7b165c0..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-data/run_nfs.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash - -# 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. - -function start() -{ - - # prepare /etc/exports - for i in "$@"; do - # fsid=0: needed for NFSv4 - echo "$i *(rw,fsid=0,insecure,no_root_squash)" >> /etc/exports - # move index.html to here - /bin/cp /tmp/index.html $i/ - chmod 644 $i/index.html - echo "Serving $i" - done - - # start rpcbind if it is not started yet - /usr/sbin/rpcinfo 127.0.0.1 > /dev/null; s=$? - if [ $s -ne 0 ]; then - echo "Starting rpcbind" - /usr/sbin/rpcbind -w - fi - - mount -t nfsd nfds /proc/fs/nfsd - - # -N 4.x: disable NFSv4 - # -V 3: enable NFSv3 - /usr/sbin/rpc.mountd -N 2 -V 3 -N 4 -N 4.1 - - /usr/sbin/exportfs -r - # -G 10 to reduce grace time to 10 seconds (the lowest allowed) - /usr/sbin/rpc.nfsd -G 10 -N 2 -V 3 -N 4 -N 4.1 2 - /usr/sbin/rpc.statd --no-notify - echo "NFS started" -} - -function stop() -{ - echo "Stopping NFS" - - /usr/sbin/rpc.nfsd 0 - /usr/sbin/exportfs -au - /usr/sbin/exportfs -f - - kill $( pidof rpc.mountd ) - umount /proc/fs/nfsd - echo > /etc/exports - exit 0 -} - - -trap stop TERM - -start "$@" - -# Ugly hack to do nothing and wait for SIGTERM -while true; do - sleep 5 -done diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-pv.png b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-pv.png deleted file mode 100644 index 1ac5fc0d1..000000000 Binary files a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-pv.png and /dev/null differ diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-pv.yaml b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-pv.yaml deleted file mode 100644 index 258f4d4c9..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-pv.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: nfs -spec: - capacity: - storage: 1Mi - accessModes: - - ReadWriteMany - nfs: - # FIXME: use the right IP - server: 10.244.1.4 - path: "/exports" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-pvc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-pvc.yaml deleted file mode 100644 index 9c1821f7c..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-pvc.yaml +++ /dev/null @@ -1,10 +0,0 @@ -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: nfs -spec: - accessModes: - - ReadWriteMany - resources: - requests: - storage: 1Mi diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-server-rc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-server-rc.yaml deleted file mode 100644 index c83ed1db8..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-server-rc.yaml +++ /dev/null @@ -1,32 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: nfs-server -spec: - replicas: 1 - selector: - role: nfs-server - template: - metadata: - labels: - role: nfs-server - spec: - containers: - - name: nfs-server - image: gcr.io/google-samples/nfs-server:1.1 - ports: - - name: nfs - containerPort: 2049 - - name: mountd - containerPort: 20048 - - name: rpcbind - containerPort: 111 - securityContext: - privileged: true - volumeMounts: - - mountPath: /exports - name: mypvc - volumes: - - name: mypvc - persistentVolumeClaim: - claimName: nfs-pv-provisioning-demo diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-server-service.yaml b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-server-service.yaml deleted file mode 100644 index 9654d1583..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-server-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: nfs-server -spec: - ports: - - name: nfs - port: 2049 - - name: mountd - port: 20048 - - name: rpcbind - port: 111 - selector: - role: nfs-server diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-web-rc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-web-rc.yaml deleted file mode 100644 index 6c96682cb..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-web-rc.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# This pod mounts the nfs volume claim into /usr/share/nginx/html and -# serves a simple web page. - -apiVersion: v1 -kind: ReplicationController -metadata: - name: nfs-web -spec: - replicas: 2 - selector: - role: web-frontend - template: - metadata: - labels: - role: web-frontend - spec: - containers: - - name: web - image: nginx - ports: - - name: web - containerPort: 80 - volumeMounts: - # name must match the volume name below - - name: nfs - mountPath: "/usr/share/nginx/html" - volumes: - - name: nfs - persistentVolumeClaim: - claimName: nfs diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-web-service.yaml b/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-web-service.yaml deleted file mode 100644 index b73cac2bc..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/nfs-web-service.yaml +++ /dev/null @@ -1,9 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: nfs-web -spec: - ports: - - port: 80 - selector: - role: web-frontend diff --git a/vendor/k8s.io/kubernetes/examples/volumes/nfs/provisioner/nfs-server-gce-pv.yaml b/vendor/k8s.io/kubernetes/examples/volumes/nfs/provisioner/nfs-server-gce-pv.yaml deleted file mode 100644 index cccb9a42a..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/nfs/provisioner/nfs-server-gce-pv.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: nfs-pv-provisioning-demo - labels: - demo: nfs-pv-provisioning -spec: - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - storage: 200Gi diff --git a/vendor/k8s.io/kubernetes/examples/volumes/portworx/README.md b/vendor/k8s.io/kubernetes/examples/volumes/portworx/README.md deleted file mode 100644 index d1ab62468..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/portworx/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/portworx/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/portworx/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pod.yaml deleted file mode 100644 index f44302f59..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pod.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: test-portworx-volume-pod -spec: - containers: - - image: k8s.gcr.io/test-webserver - name: test-container - volumeMounts: - - mountPath: /test-portworx-volume - name: test-volume - volumes: - - name: test-volume - # This Portworx volume must already exist. - portworxVolume: - volumeID: "vol1" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pv.yaml b/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pv.yaml deleted file mode 100644 index af4e0114f..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pv.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: pv0001 -spec: - capacity: - storage: 2Gi - accessModes: - - ReadWriteOnce - persistentVolumeReclaimPolicy: Retain - portworxVolume: - volumeID: "pv0001" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvc.yaml deleted file mode 100644 index 181a3848d..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvc.yaml +++ /dev/null @@ -1,10 +0,0 @@ -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: pvc0001 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvcpod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvcpod.yaml deleted file mode 100644 index bef2d4965..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvcpod.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: pvpod -spec: - containers: - - name: test-container - image: k8s.gcr.io/test-webserver - volumeMounts: - - name: test-volume - mountPath: /test-portworx-volume - volumes: - - name: test-volume - persistentVolumeClaim: - claimName: pvc0001 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvcsc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvcsc.yaml deleted file mode 100644 index 736e67fee..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvcsc.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: pvcsc001 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi - storageClassName: portworx-io-priority-high diff --git a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvcscpod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvcscpod.yaml deleted file mode 100644 index 8bdd51319..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-pvcscpod.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: pvpod -spec: - containers: - - name: test-container - image: k8s.gcr.io/test-webserver - volumeMounts: - - name: test-volume - mountPath: /test-portworx-volume - volumes: - - name: test-volume - persistentVolumeClaim: - claimName: pvcsc001 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-sc-high.yaml b/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-sc-high.yaml deleted file mode 100644 index 8fc732377..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/portworx/portworx-volume-sc-high.yaml +++ /dev/null @@ -1,9 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: portworx-io-priority-high -provisioner: kubernetes.io/portworx-volume -parameters: - repl: "1" - snap_interval: "70" - io_priority: "high" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/quobyte/Readme.md b/vendor/k8s.io/kubernetes/examples/volumes/quobyte/Readme.md deleted file mode 100644 index fe41c8e59..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/quobyte/Readme.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/quobyte/Readme.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/quobyte/Readme.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/quobyte/quobyte-pod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/quobyte/quobyte-pod.yaml deleted file mode 100644 index f731a53ea..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/quobyte/quobyte-pod.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: quobyte -spec: - containers: - - name: quobyte - image: kubernetes/pause - volumeMounts: - - mountPath: /mnt - name: quobytevolume - volumes: - - name: quobytevolume - quobyte: - registry: registry:7861 - volume: testVolume - readOnly: false - user: root - group: root diff --git a/vendor/k8s.io/kubernetes/examples/volumes/rbd/README.md b/vendor/k8s.io/kubernetes/examples/volumes/rbd/README.md deleted file mode 100644 index 46b19d8d3..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/rbd/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/rbd/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/rbd/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/rbd/rbd-with-secret.json b/vendor/k8s.io/kubernetes/examples/volumes/rbd/rbd-with-secret.json deleted file mode 100644 index 30375583d..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/rbd/rbd-with-secret.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "rbd2" - }, - "spec": { - "containers": [ - { - "name": "rbd-rw", - "image": "kubernetes/pause", - "volumeMounts": [ - { - "mountPath": "/mnt/rbd", - "name": "rbdpd" - } - ] - } - ], - "volumes": [ - { - "name": "rbdpd", - "rbd": { - "monitors": [ - "10.16.154.78:6789", - "10.16.154.82:6789", - "10.16.154.83:6789" - ], - "pool": "kube", - "image": "foo", - "user": "admin", - "secretRef": { - "name": "ceph-secret" - }, - "fsType": "ext4", - "readOnly": true - } - } - ] - } -} diff --git a/vendor/k8s.io/kubernetes/examples/volumes/rbd/rbd.json b/vendor/k8s.io/kubernetes/examples/volumes/rbd/rbd.json deleted file mode 100644 index 68033bffd..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/rbd/rbd.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "rbd" - }, - "spec": { - "containers": [ - { - "name": "rbd-rw", - "image": "kubernetes/pause", - "volumeMounts": [ - { - "mountPath": "/mnt/rbd", - "name": "rbdpd" - } - ] - } - ], - "volumes": [ - { - "name": "rbdpd", - "rbd": { - "monitors": [ - "10.16.154.78:6789", - "10.16.154.82:6789", - "10.16.154.83:6789" - ], - "pool": "kube", - "image": "foo", - "user": "admin", - "keyring": "/etc/ceph/keyring", - "fsType": "ext4", - "readOnly": true - } - } - ] - } -} diff --git a/vendor/k8s.io/kubernetes/examples/volumes/rbd/secret/ceph-secret.yaml b/vendor/k8s.io/kubernetes/examples/volumes/rbd/secret/ceph-secret.yaml deleted file mode 100644 index f717f9005..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/rbd/secret/ceph-secret.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: ceph-secret -type: "kubernetes.io/rbd" -data: - key: QVFCMTZWMVZvRjVtRXhBQTVrQ1FzN2JCajhWVUxSdzI2Qzg0SEE9PQ== diff --git a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/README.md b/vendor/k8s.io/kubernetes/examples/volumes/scaleio/README.md deleted file mode 100644 index fb7f9a6fa..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/scaleio/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/scaleio/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/pod-sc-pvc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/scaleio/pod-sc-pvc.yaml deleted file mode 100644 index c94e7bc39..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/pod-sc-pvc.yaml +++ /dev/null @@ -1,15 +0,0 @@ -kind: Pod -apiVersion: v1 -metadata: - name: pod-sio-small -spec: - containers: - - name: pod-sio-small-container - image: k8s.gcr.io/test-webserver - volumeMounts: - - mountPath: /test - name: test-data - volumes: - - name: test-data - persistentVolumeClaim: - claimName: pvc-sio-small diff --git a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/pod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/scaleio/pod.yaml deleted file mode 100644 index b13ec668c..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/pod.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: pod-0 -spec: - containers: - - image: k8s.gcr.io/test-webserver - name: pod-0 - volumeMounts: - - mountPath: /test-pd - name: vol-0 - volumes: - - name: vol-0 - scaleIO: - gateway: https://localhost:443/api - system: scaleio - volumeName: vol-0 - secretRef: - name: sio-secret - fsType: xfs diff --git a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/sc-pvc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/scaleio/sc-pvc.yaml deleted file mode 100644 index 078fb6354..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/sc-pvc.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: pvc-sio-small -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi - storageClassName: sio-small diff --git a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/sc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/scaleio/sc.yaml deleted file mode 100644 index 2ff4c028f..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/sc.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: sio-small -provisioner: kubernetes.io/scaleio -parameters: - gateway: https://localhost:443/api - system: scaleio - protectionDomain: default - secretRef: sio-secret - fsType: xfs diff --git a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/secret.yaml b/vendor/k8s.io/kubernetes/examples/volumes/scaleio/secret.yaml deleted file mode 100644 index b2fad68af..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/scaleio/secret.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: sio-secret -type: kubernetes.io/scaleio -data: - username: YWRtaW4= - password: c0NhbGVpbzEyMw== diff --git a/vendor/k8s.io/kubernetes/examples/volumes/storageos/README.md b/vendor/k8s.io/kubernetes/examples/volumes/storageos/README.md deleted file mode 100644 index c2d6f74db..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/storageos/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/storageos/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/storageos/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pod.yaml deleted file mode 100644 index 8225c5481..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pod.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - labels: - name: redis - role: master - name: test-storageos-redis -spec: - containers: - - name: master - image: kubernetes/redis:v1 - env: - - name: MASTER - value: "true" - ports: - - containerPort: 6379 - resources: - limits: - cpu: "0.1" - volumeMounts: - - mountPath: /redis-master-data - name: redis-data - volumes: - - name: redis-data - storageos: - # This volume must already exist within StorageOS - volumeName: redis-vol01 - # Namespace is optional, and specifies the volume scope within - # StorageOS. If no namespace is provided, it will use the namespace - # of the pod. Set to `default` or leave blank if you are not using - # namespaces. - #namespace: test-storageos - # The name of the storageos pool to use. Will use `default` if not - # specified, which should be available on most StorageOS clusters. - pool: default - # The filesystem type to create on the volume, if required. - fsType: ext4 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pv.yaml b/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pv.yaml deleted file mode 100644 index 3afe09094..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pv.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: pv0001 -spec: - capacity: - storage: 5Gi - accessModes: - - ReadWriteOnce - persistentVolumeReclaimPolicy: Delete - storageClassName: fast - storageos: - # This volume must already exist within StorageOS - volumeName: pv0001 - # volumeNamespace is optional, and specifies the volume scope within - # StorageOS. Set to `default` or leave blank if you are not using - # namespaces. - #volumeNamespace: default - # The filesystem type to create on the volume, if required. - fsType: ext4 - # The secret name for API credentials - secretName: storageos-secret diff --git a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pvc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pvc.yaml deleted file mode 100644 index 4eecf3644..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pvc.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: pvc0001 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi - storageClassName: fast diff --git a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pvcpod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pvcpod.yaml deleted file mode 100644 index dbea02c2c..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-pvcpod.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - labels: - name: redis - role: master - name: test-storageos-redis-pvc -spec: - containers: - - name: master - image: kubernetes/redis:v1 - env: - - name: MASTER - value: "true" - ports: - - containerPort: 6379 - resources: - limits: - cpu: "0.1" - volumeMounts: - - mountPath: /redis-master-data - name: redis-data - volumes: - - name: redis-data - persistentVolumeClaim: - claimName: pvc0001 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-sc-pvc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-sc-pvc.yaml deleted file mode 100644 index 96d7b1341..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-sc-pvc.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: fast0001 -spec: - accessModes: - - ReadWriteOnce - storageClassName: fast - resources: - requests: - storage: 5Gi diff --git a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-sc-pvcpod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-sc-pvcpod.yaml deleted file mode 100644 index a75a6c51a..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-sc-pvcpod.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - labels: - name: redis - role: master - name: test-storageos-redis-sc-pvc -spec: - containers: - - name: master - image: kubernetes/redis:v1 - env: - - name: MASTER - value: "true" - ports: - - containerPort: 6379 - resources: - limits: - cpu: "0.1" - volumeMounts: - - mountPath: /redis-master-data - name: redis-data - volumes: - - name: redis-data - persistentVolumeClaim: - claimName: fast0001 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-sc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-sc.yaml deleted file mode 100644 index 4f7bd6038..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-sc.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: sc-fast -provisioner: kubernetes.io/storageos -parameters: - pool: default - description: Kubernetes volume - fsType: ext4 - adminSecretNamespace: default - adminSecretName: storageos-secret \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-secret.yaml b/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-secret.yaml deleted file mode 100644 index f837eb138..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/storageos/storageos-secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: storageos-secret -type: "kubernetes.io/storageos" -data: - apiAddress: dGNwOi8vMTI3LjAuMC4xOjU3MDU= - apiUsername: c3RvcmFnZW9z - apiPassword: c3RvcmFnZW9z diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/README.md b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/README.md deleted file mode 100644 index 11c6e1abe..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/README.md +++ /dev/null @@ -1 +0,0 @@ -This file has moved to [https://github.com/kubernetes/examples/blob/master/staging/volumes/vsphere/README.md](https://github.com/kubernetes/examples/blob/master/staging/volumes/vsphere/README.md) diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/deployment.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/deployment.yaml deleted file mode 100644 index 1ea779b8a..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/deployment.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: deployment -spec: - replicas: 1 - template: - metadata: - labels: - app: redis - spec: - containers: - - name: redis - image: redis - volumeMounts: - - name: vmfs-vmdk-storage - mountPath: /data/ - volumes: - - name: vmfs-vmdk-storage - vsphereVolume: - volumePath: "[Datastore] volumes/testdir" - fsType: ext4 \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/simple-statefulset.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/simple-statefulset.yaml deleted file mode 100644 index d9de93c25..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/simple-statefulset.yaml +++ /dev/null @@ -1,45 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: nginx - labels: - app: nginx -spec: - ports: - - port: 80 - name: web - clusterIP: None - selector: - app: nginx ---- -apiVersion: apps/v1beta1 -kind: StatefulSet -metadata: - name: web -spec: - serviceName: "nginx" - replicas: 14 - template: - metadata: - labels: - app: nginx - spec: - containers: - - name: nginx - image: k8s.gcr.io/nginx-slim:0.8 - ports: - - containerPort: 80 - name: web - volumeMounts: - - name: www - mountPath: /usr/share/nginx/html - volumeClaimTemplates: - - metadata: - name: www - spec: - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - storage: 1Gi - storageClassName: thin-disk diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/simple-storageclass.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/simple-storageclass.yaml deleted file mode 100644 index 87327836f..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/simple-storageclass.yaml +++ /dev/null @@ -1,7 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: thin-disk -provisioner: kubernetes.io/vsphere-volume -parameters: - diskformat: thin diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pod.yaml deleted file mode 100644 index 0204ad3a5..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pod.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: test-vmdk -spec: - containers: - - image: k8s.gcr.io/test-webserver - name: test-container - volumeMounts: - - mountPath: /test-vmdk - name: test-volume - volumes: - - name: test-volume - # This VMDK volume must already exist. - vsphereVolume: - volumePath: "[DatastoreName] volumes/myDisk" - fsType: ext4 \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pv.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pv.yaml deleted file mode 100644 index 5bc278288..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pv.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: pv0001 -spec: - capacity: - storage: 2Gi - accessModes: - - ReadWriteOnce - persistentVolumeReclaimPolicy: Retain - vsphereVolume: - volumePath: "[DatastoreName] volumes/myDisk" - fsType: ext4 \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvc.yaml deleted file mode 100644 index 181a3848d..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvc.yaml +++ /dev/null @@ -1,10 +0,0 @@ -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: pvc0001 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvcpod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvcpod.yaml deleted file mode 100644 index 326c0031f..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvcpod.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: pvpod -spec: - containers: - - name: test-container - image: k8s.gcr.io/test-webserver - volumeMounts: - - name: test-volume - mountPath: /test-vmdk - volumes: - - name: test-volume - persistentVolumeClaim: - claimName: pvc0001 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvcsc.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvcsc.yaml deleted file mode 100644 index 03f3f8f8f..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvcsc.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: pvcsc001 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi - storageClassName: fast diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvcscpod.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvcscpod.yaml deleted file mode 100644 index c569a0b36..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-pvcscpod.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: pvpod -spec: - containers: - - name: test-container - image: k8s.gcr.io/test-webserver - volumeMounts: - - name: test-volume - mountPath: /test-vmdk - volumes: - - name: test-volume - persistentVolumeClaim: - claimName: pvcsc001 diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-fast.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-fast.yaml deleted file mode 100644 index 959e28e88..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-fast.yaml +++ /dev/null @@ -1,8 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: fast -provisioner: kubernetes.io/vsphere-volume -parameters: - diskformat: zeroedthick - fstype: ext3 \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-vsancapabilities-with-datastore.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-vsancapabilities-with-datastore.yaml deleted file mode 100644 index 5c4a9a665..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-vsancapabilities-with-datastore.yaml +++ /dev/null @@ -1,10 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: fast -provisioner: kubernetes.io/vsphere-volume -parameters: - diskformat: zeroedthick - datastore: vsanDatastore - hostFailuresToTolerate: "2" - cachereservation: "20" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-vsancapabilities.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-vsancapabilities.yaml deleted file mode 100644 index 5f8f9f2fc..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-vsancapabilities.yaml +++ /dev/null @@ -1,9 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: fast -provisioner: kubernetes.io/vsphere-volume -parameters: - diskformat: zeroedthick - hostFailuresToTolerate: "2" - cachereservation: "20" diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-with-datastore.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-with-datastore.yaml deleted file mode 100644 index 3fb56bf1a..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-sc-with-datastore.yaml +++ /dev/null @@ -1,8 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: fast -provisioner: kubernetes.io/vsphere-volume -parameters: - diskformat: zeroedthick - datastore: vsanDatastore diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-spbm-policy-with-datastore.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-spbm-policy-with-datastore.yaml deleted file mode 100644 index 43e22c506..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-spbm-policy-with-datastore.yaml +++ /dev/null @@ -1,9 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: fast -provisioner: kubernetes.io/vsphere-volume -parameters: - diskformat: zeroedthick - storagePolicyName: gold - datastore: VSANDatastore diff --git a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-spbm-policy.yaml b/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-spbm-policy.yaml deleted file mode 100644 index 0d68f680c..000000000 --- a/vendor/k8s.io/kubernetes/examples/volumes/vsphere/vsphere-volume-spbm-policy.yaml +++ /dev/null @@ -1,8 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: fast -provisioner: kubernetes.io/vsphere-volume -parameters: - diskformat: zeroedthick - storagePolicyName: gold diff --git a/vendor/k8s.io/kubernetes/hack/.golint_failures b/vendor/k8s.io/kubernetes/hack/.golint_failures index 95a0b7fb9..0a5ba6fea 100644 --- a/vendor/k8s.io/kubernetes/hack/.golint_failures +++ b/vendor/k8s.io/kubernetes/hack/.golint_failures @@ -1,20 +1,21 @@ + cluster/images/etcd-version-monitor cmd/hyperkube +cmd/kube-apiserver/app cmd/kube-controller-manager/app cmd/kube-proxy/app cmd/kube-scheduler/app cmd/kubeadm/app -cmd/kubeadm/app/apis/kubeadm/v1alpha1 +cmd/kubeadm/app/apis/kubeadm/v1alpha2 +cmd/kubeadm/app/util/config cmd/kubelet/app cmd/kubelet/app/options cmd/kubemark -examples/guestbook-go pkg/api/endpoints pkg/api/ref pkg/api/testapi pkg/api/testing pkg/api/testing/compat -pkg/api/unversioned pkg/api/v1/endpoints pkg/api/v1/pod pkg/api/v1/resource @@ -66,6 +67,7 @@ pkg/apis/rbac/v1beta1 pkg/apis/rbac/validation pkg/apis/scheduling pkg/apis/scheduling/v1alpha1 +pkg/apis/scheduling/v1beta1 pkg/apis/settings pkg/apis/settings/v1alpha1 pkg/apis/storage @@ -100,7 +102,6 @@ pkg/controller/deployment/util pkg/controller/disruption pkg/controller/endpoint pkg/controller/garbagecollector -pkg/controller/garbagecollector/metaonly pkg/controller/job pkg/controller/namespace pkg/controller/namespace/deletion @@ -135,22 +136,24 @@ pkg/kubeapiserver/authorizer/modes pkg/kubeapiserver/options pkg/kubeapiserver/server pkg/kubectl -pkg/kubectl/categories pkg/kubectl/cmd pkg/kubectl/cmd/auth pkg/kubectl/cmd/config +pkg/kubectl/cmd/create +pkg/kubectl/cmd/get pkg/kubectl/cmd/rollout pkg/kubectl/cmd/set pkg/kubectl/cmd/templates pkg/kubectl/cmd/testing pkg/kubectl/cmd/util pkg/kubectl/cmd/util/editor -pkg/kubectl/cmd/util/jsonmerge pkg/kubectl/cmd/util/sanity +pkg/kubectl/cmd/wait +pkg/kubectl/genericclioptions +pkg/kubectl/genericclioptions/printers +pkg/kubectl/genericclioptions/resource pkg/kubectl/metricsutil -pkg/kubectl/resource pkg/kubectl/util -pkg/kubectl/util/crlf pkg/kubectl/util/slice pkg/kubelet pkg/kubelet/apis @@ -160,10 +163,15 @@ pkg/kubelet/apis/deviceplugin/v1alpha pkg/kubelet/apis/deviceplugin/v1beta1 pkg/kubelet/apis/kubeletconfig pkg/kubelet/apis/kubeletconfig/v1beta1 +pkg/kubelet/apis/pluginregistration/v1alpha1 pkg/kubelet/cadvisor pkg/kubelet/cadvisor/testing +pkg/kubelet/checkpoint +pkg/kubelet/checkpointmanager/checksum +pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1 pkg/kubelet/client pkg/kubelet/cm +pkg/kubelet/cm/devicemanager/checkpoint pkg/kubelet/cm/util pkg/kubelet/config pkg/kubelet/configmap @@ -172,22 +180,19 @@ pkg/kubelet/custommetrics pkg/kubelet/dockershim pkg/kubelet/dockershim/cm pkg/kubelet/dockershim/libdocker -pkg/kubelet/dockershim/testing +pkg/kubelet/dockershim/network +pkg/kubelet/dockershim/network/cni +pkg/kubelet/dockershim/network/cni/testing +pkg/kubelet/dockershim/network/hostport +pkg/kubelet/dockershim/network/hostport/testing +pkg/kubelet/dockershim/network/kubenet +pkg/kubelet/dockershim/network/testing pkg/kubelet/events -pkg/kubelet/gpu pkg/kubelet/images pkg/kubelet/kuberuntime pkg/kubelet/leaky pkg/kubelet/lifecycle pkg/kubelet/metrics -pkg/kubelet/network -pkg/kubelet/network/cni -pkg/kubelet/network/cni/testing -pkg/kubelet/network/hairpin -pkg/kubelet/network/hostport -pkg/kubelet/network/hostport/testing -pkg/kubelet/network/kubenet -pkg/kubelet/network/testing pkg/kubelet/pleg pkg/kubelet/pod pkg/kubelet/pod/testing @@ -197,7 +202,6 @@ pkg/kubelet/prober/results pkg/kubelet/prober/testing pkg/kubelet/qos pkg/kubelet/remote -pkg/kubelet/rkt pkg/kubelet/secret pkg/kubelet/server pkg/kubelet/server/portforward @@ -211,12 +215,16 @@ pkg/kubelet/sysctl pkg/kubelet/types pkg/kubelet/util pkg/kubelet/util/cache +pkg/kubelet/util/pluginwatcher +pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1 +pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2 pkg/kubelet/util/queue pkg/kubelet/util/sliceutils pkg/kubemark pkg/master pkg/master/controller/crdregistration pkg/master/tunneler +pkg/printers pkg/printers/internalversion pkg/printers/storage pkg/probe @@ -324,7 +332,6 @@ pkg/registry/storage/rest pkg/registry/storage/storageclass pkg/registry/storage/storageclass/storage pkg/routes -pkg/scheduler/api pkg/security/apparmor pkg/security/podsecuritypolicy pkg/security/podsecuritypolicy/group @@ -374,7 +381,9 @@ pkg/volume/azure_dd pkg/volume/azure_file pkg/volume/cephfs pkg/volume/configmap +pkg/volume/csi pkg/volume/csi/fake +pkg/volume/csi/labelmanager pkg/volume/empty_dir pkg/volume/fc pkg/volume/flexvolume @@ -400,10 +409,8 @@ pkg/volume/vsphere_volume plugin/pkg/admission/antiaffinity plugin/pkg/admission/eventratelimit/apis/eventratelimit plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1 -plugin/pkg/admission/initialresources plugin/pkg/admission/limitranger plugin/pkg/admission/noderestriction -plugin/pkg/admission/persistentvolume/label plugin/pkg/admission/podnodeselector plugin/pkg/admission/podpreset plugin/pkg/admission/podtolerationrestriction @@ -443,18 +450,13 @@ staging/src/k8s.io/api/rbac/v1 staging/src/k8s.io/api/rbac/v1alpha1 staging/src/k8s.io/api/rbac/v1beta1 staging/src/k8s.io/api/scheduling/v1alpha1 +staging/src/k8s.io/api/scheduling/v1beta1 staging/src/k8s.io/api/settings/v1alpha1 staging/src/k8s.io/api/storage/v1 staging/src/k8s.io/api/storage/v1alpha1 staging/src/k8s.io/api/storage/v1beta1 staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1 -staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned -staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake -staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme -staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1 -staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake -staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1 staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver @@ -469,8 +471,6 @@ staging/src/k8s.io/apimachinery/pkg/api/testing/fuzzer staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip staging/src/k8s.io/apimachinery/pkg/api/validation staging/src/k8s.io/apimachinery/pkg/api/validation/path -staging/src/k8s.io/apimachinery/pkg/apimachinery/announced -staging/src/k8s.io/apimachinery/pkg/apimachinery/registered staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured @@ -505,7 +505,6 @@ staging/src/k8s.io/apimachinery/pkg/util/proxy staging/src/k8s.io/apimachinery/pkg/util/rand staging/src/k8s.io/apimachinery/pkg/util/remotecommand staging/src/k8s.io/apimachinery/pkg/util/runtime -staging/src/k8s.io/apimachinery/pkg/util/sets staging/src/k8s.io/apimachinery/pkg/util/sets/types staging/src/k8s.io/apimachinery/pkg/util/strategicpatch staging/src/k8s.io/apimachinery/pkg/util/uuid @@ -552,6 +551,7 @@ staging/src/k8s.io/apiserver/pkg/endpoints/handlers staging/src/k8s.io/apiserver/pkg/endpoints/handlers/negotiation staging/src/k8s.io/apiserver/pkg/endpoints/metrics staging/src/k8s.io/apiserver/pkg/endpoints/openapi/testing +staging/src/k8s.io/apiserver/pkg/endpoints/request staging/src/k8s.io/apiserver/pkg/endpoints/testing staging/src/k8s.io/apiserver/pkg/features staging/src/k8s.io/apiserver/pkg/registry/generic @@ -591,6 +591,7 @@ staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook +staging/src/k8s.io/client-go/deprecated-dynamic staging/src/k8s.io/client-go/discovery/cached staging/src/k8s.io/client-go/dynamic staging/src/k8s.io/client-go/dynamic/fake @@ -706,6 +707,7 @@ test/e2e/ui test/e2e/upgrades test/e2e/upgrades/apps test/e2e/upgrades/storage +test/e2e_kubeadm test/e2e_node test/e2e_node/builder test/e2e_node/environment diff --git a/vendor/k8s.io/kubernetes/hack/BUILD b/vendor/k8s.io/kubernetes/hack/BUILD index d562a4488..0eaeae8c5 100644 --- a/vendor/k8s.io/kubernetes/hack/BUILD +++ b/vendor/k8s.io/kubernetes/hack/BUILD @@ -19,7 +19,6 @@ filegroup( srcs = [ ":package-srcs", "//hack/boilerplate:all-srcs", - "//hack/cmd/teststale:all-srcs", "//hack/e2e-internal:all-srcs", "//hack/lib:all-srcs", "//hack/make-rules:all-srcs", @@ -72,3 +71,10 @@ go_library( srcs = ["e2e.go"], importpath = "k8s.io/kubernetes/hack", ) + +sh_binary( + name = "update-mirror", + srcs = ["update-workspace-mirror.sh"], + args = ["$(location @workspace_urls//:urls.txt)"], + data = ["@workspace_urls//:urls.txt"], +) diff --git a/vendor/k8s.io/kubernetes/hack/OWNERS b/vendor/k8s.io/kubernetes/hack/OWNERS index cdcdfb94a..7cb8939be 100644 --- a/vendor/k8s.io/kubernetes/hack/OWNERS +++ b/vendor/k8s.io/kubernetes/hack/OWNERS @@ -4,6 +4,7 @@ reviewers: - fejta - ixdy - jbeda + - juanvallejo - lavalamp - zmerlynn - sttts @@ -25,3 +26,5 @@ approvers: - gmarek - vishh - liggitt + - soltysh # for sig-cli related stuff + - dims # for local-up-cluster related files diff --git a/vendor/k8s.io/kubernetes/hack/benchmark-go.sh b/vendor/k8s.io/kubernetes/hack/benchmark-go.sh index 01c06a742..17aa8c56f 100755 --- a/vendor/k8s.io/kubernetes/hack/benchmark-go.sh +++ b/vendor/k8s.io/kubernetes/hack/benchmark-go.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/boilerplate/boilerplate.generatego.txt b/vendor/k8s.io/kubernetes/hack/boilerplate/boilerplate.generatego.txt new file mode 100644 index 000000000..b7c650da4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/hack/boilerplate/boilerplate.generatego.txt @@ -0,0 +1,16 @@ +/* +Copyright 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. +*/ + diff --git a/vendor/k8s.io/kubernetes/hack/boilerplate/boilerplate.py b/vendor/k8s.io/kubernetes/hack/boilerplate/boilerplate.py index 7165d8e67..d952d4af5 100755 --- a/vendor/k8s.io/kubernetes/hack/boilerplate/boilerplate.py +++ b/vendor/k8s.io/kubernetes/hack/boilerplate/boilerplate.py @@ -20,8 +20,6 @@ import datetime import difflib import glob -import json -import mmap import os import re import sys @@ -63,6 +61,14 @@ def get_refs(): return refs +def is_generated_file(filename, data, regexs): + for d in skipped_ungenerated_files: + if d in filename: + return False + + p = regexs["generated"] + return p.search(data) + def file_passes(filename, refs, regexs): try: f = open(filename, 'r') @@ -73,15 +79,22 @@ def file_passes(filename, refs, regexs): data = f.read() f.close() + # determine if the file is automatically generated + generated = is_generated_file(filename, data, regexs) + basename = os.path.basename(filename) - extension = file_extension(filename) + if generated: + extension = "generatego" + else: + extension = file_extension(filename) + if extension != "": ref = refs[extension] else: ref = refs[basename] # remove build tags from the top of Go files - if extension == "go": + if extension == "go" or extension =="generatego": p = regexs["go_build_constraints"] (data, found) = p.subn("", data, 1) @@ -105,15 +118,19 @@ def file_passes(filename, refs, regexs): p = regexs["year"] for d in data: if p.search(d): - print('File %s is missing the year' % filename, file=verbose_out) + if generated: + print('File %s has the YEAR field, but it should not be in generated file' % filename, file=verbose_out) + else: + print('File %s has the YEAR field, but missing the year of date' % filename, file=verbose_out) return False - # Replace all occurrences of the regex "2014|2015|2016|2017|2018" with "YEAR" - p = regexs["date"] - for i, d in enumerate(data): - (data[i], found) = p.subn('YEAR', d) - if found != 0: - break + if not generated: + # Replace all occurrences of the regex "2014|2015|2016|2017|2018" with "YEAR" + p = regexs["date"] + for i, d in enumerate(data): + (data[i], found) = p.subn('YEAR', d) + if found != 0: + break # if we don't match the reference at this point, fail if ref != data: @@ -134,6 +151,10 @@ def file_extension(filename): "vendor", "test/e2e/generated/bindata.go", "hack/boilerplate/test", "pkg/generated/bindata.go"] +# list all the files contain 'DO NOT EDIT', but are not generated +skipped_ungenerated_files = ['hack/build-ui.sh', 'hack/lib/swagger.sh', + 'hack/boilerplate/boilerplate.py'] + def normalize_files(files): newfiles = [] for pathname in files: @@ -187,6 +208,8 @@ def get_regexs(): regexs["go_build_constraints"] = re.compile(r"^(// \+build.*\n)+\n", re.MULTILINE) # strip #!.* from shell scripts regexs["shebang"] = re.compile(r"^(#!.*\n)\n*", re.MULTILINE) + # Search for generated files + regexs["generated"] = re.compile( 'DO NOT EDIT' ) return regexs def main(): diff --git a/vendor/k8s.io/kubernetes/hack/build-cross.sh b/vendor/k8s.io/kubernetes/hack/build-cross.sh index d4cc70b30..00199528c 100755 --- a/vendor/k8s.io/kubernetes/hack/build-cross.sh +++ b/vendor/k8s.io/kubernetes/hack/build-cross.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/build-go.sh b/vendor/k8s.io/kubernetes/hack/build-go.sh index 3dedf3a84..a2ff89399 100755 --- a/vendor/k8s.io/kubernetes/hack/build-go.sh +++ b/vendor/k8s.io/kubernetes/hack/build-go.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/build-ui.sh b/vendor/k8s.io/kubernetes/hack/build-ui.sh index 6e2e0e5d5..490473cf7 100755 --- a/vendor/k8s.io/kubernetes/hack/build-ui.sh +++ b/vendor/k8s.io/kubernetes/hack/build-ui.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -30,7 +30,8 @@ if ! which go-bindata > /dev/null 2>&1 ; then exit 1 fi -readonly TMP_DATAFILE="/tmp/datafile.go" +kube::util::ensure-temp-dir +readonly TMP_DATAFILE="${KUBE_TEMP}/datafile.go" readonly SWAGGER_SRC="third_party/swagger-ui/..." readonly SWAGGER_PKG="swagger" @@ -42,7 +43,7 @@ function kube::hack::build_ui() { go-bindata -nocompress -o "${output_file}" -prefix ${PWD} -pkg "${pkg}" "${src}" local year=$(date +%Y) - cat hack/boilerplate/boilerplate.go.txt | sed "s/YEAR/${year}/" > "${TMP_DATAFILE}" + cat hack/boilerplate/boilerplate.generatego.txt > "${TMP_DATAFILE}" echo -e "// generated by hack/build-ui.sh; DO NOT EDIT\n" >> "${TMP_DATAFILE}" cat "${output_file}" >> "${TMP_DATAFILE}" diff --git a/vendor/k8s.io/kubernetes/hack/cherry_pick_pull.sh b/vendor/k8s.io/kubernetes/hack/cherry_pick_pull.sh index 3dab5a494..f75694cc3 100755 --- a/vendor/k8s.io/kubernetes/hack/cherry_pick_pull.sh +++ b/vendor/k8s.io/kubernetes/hack/cherry_pick_pull.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/cmd/teststale/BUILD b/vendor/k8s.io/kubernetes/hack/cmd/teststale/BUILD deleted file mode 100644 index 0fab86f81..000000000 --- a/vendor/k8s.io/kubernetes/hack/cmd/teststale/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", - "go_test", -) - -go_binary( - name = "teststale", - embed = [":go_default_library"], -) - -go_test( - name = "go_default_test", - srcs = ["teststale_test.go"], - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["teststale.go"], - importpath = "k8s.io/kubernetes/hack/cmd/teststale", - deps = ["//vendor/github.com/golang/glog:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/hack/cmd/teststale/teststale.go b/vendor/k8s.io/kubernetes/hack/cmd/teststale/teststale.go deleted file mode 100644 index 45cbc6a3f..000000000 --- a/vendor/k8s.io/kubernetes/hack/cmd/teststale/teststale.go +++ /dev/null @@ -1,209 +0,0 @@ -/* -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. -*/ - -// teststale checks the staleness of a test binary. go test -c builds a test -// binary but it does no staleness check. In other words, every time one runs -// go test -c, it compiles the test packages and links the binary even when -// nothing has changed. This program helps to mitigate that problem by allowing -// to check the staleness of a given test package and its binary. -package main - -import ( - "encoding/json" - "flag" - "fmt" - "io" - "os" - "os/exec" - "path/filepath" - "time" - - "github.com/golang/glog" -) - -const usageHelp = "" + - `This program checks the staleness of a given test package and its test -binary so that one can make a decision about re-building the test binary. - -Usage: - teststale -binary=/path/to/test/binary -package=package - -Example: - teststale -binary="$HOME/gosrc/bin/e2e.test" -package="k8s.io/kubernetes/test/e2e" - -` - -var ( - binary = flag.String("binary", "", "filesystem path to the test binary file. Example: \"$HOME/gosrc/bin/e2e.test\"") - pkgPath = flag.String("package", "", "import path of the test package in the format used while importing packages. Example: \"k8s.io/kubernetes/test/e2e\"") -) - -func usage() { - fmt.Fprintln(os.Stderr, usageHelp) - fmt.Fprintln(os.Stderr, "Flags:") - flag.PrintDefaults() - os.Exit(2) -} - -// golist is an interface emulating the `go list` command to get package information. -// TODO: Evaluate using `go/build` package instead. It doesn't provide staleness -// information, but we can probably run `go list` and `go/build.Import()` concurrently -// in goroutines and merge the results. Evaluate if that's faster. -type golist interface { - pkgInfo(pkgPaths []string) ([]pkg, error) -} - -// execmd implements the `golist` interface. -type execcmd struct { - cmd string - args []string - env []string -} - -func (e *execcmd) pkgInfo(pkgPaths []string) ([]pkg, error) { - args := append(e.args, pkgPaths...) - cmd := exec.Command(e.cmd, args...) - cmd.Env = e.env - - stdout, err := cmd.StdoutPipe() - if err != nil { - return nil, fmt.Errorf("failed to obtain the metadata output stream: %v", err) - } - - dec := json.NewDecoder(stdout) - - // Start executing the command - if err := cmd.Start(); err != nil { - return nil, fmt.Errorf("command did not start: %v", err) - } - - var pkgs []pkg - for { - var p pkg - if err := dec.Decode(&p); err == io.EOF { - break - } else if err != nil { - return nil, fmt.Errorf("failed to unmarshal metadata for package %s: %v", p.ImportPath, err) - } - pkgs = append(pkgs, p) - } - - if err := cmd.Wait(); err != nil { - return nil, fmt.Errorf("command did not complete: %v", err) - } - return pkgs, nil -} - -type pkg struct { - Dir string - ImportPath string - Target string - Stale bool - TestGoFiles []string - TestImports []string - XTestGoFiles []string - XTestImports []string -} - -func (p *pkg) isNewerThan(cmd golist, buildTime time.Time) bool { - // If the package itself is stale, then we have to rebuild the whole thing anyway. - if p.Stale { - return true - } - - // Test for file staleness - for _, f := range p.TestGoFiles { - if isNewerThan(filepath.Join(p.Dir, f), buildTime) { - glog.V(4).Infof("test Go file %s is stale", f) - return true - } - } - for _, f := range p.XTestGoFiles { - if isNewerThan(filepath.Join(p.Dir, f), buildTime) { - glog.V(4).Infof("external test Go file %s is stale", f) - return true - } - } - - imps := []string{} - imps = append(imps, p.TestImports...) - imps = append(imps, p.XTestImports...) - - // This calls `go list` the second time. This is required because the first - // call to `go list` checks the staleness of the package in question by - // looking the non-test dependencies, but it doesn't look at the test - // dependencies. However, it returns the list of test dependencies. This - // second call to `go list` checks the staleness of all the test - // dependencies. - pkgs, err := cmd.pkgInfo(imps) - if err != nil || len(pkgs) < 1 { - glog.V(4).Infof("failed to obtain metadata for packages %s: %v", imps, err) - return true - } - - for _, p := range pkgs { - if p.Stale { - glog.V(4).Infof("import %q is stale", p.ImportPath) - return true - } - } - - return false -} - -func isNewerThan(filename string, buildTime time.Time) bool { - stat, err := os.Stat(filename) - if err != nil { - return true - } - return stat.ModTime().After(buildTime) -} - -// isTestStale checks if the test binary is stale and needs to rebuilt. -// Some of the ideas here are inspired by how Go does staleness checks. -func isTestStale(cmd golist, binPath, pkgPath string) bool { - bStat, err := os.Stat(binPath) - if err != nil { - glog.V(4).Infof("Couldn't obtain the modified time of the binary %s: %v", binPath, err) - return true - } - buildTime := bStat.ModTime() - - pkgs, err := cmd.pkgInfo([]string{pkgPath}) - if err != nil || len(pkgs) < 1 { - glog.V(4).Infof("Couldn't retrieve test package information for package %s: %v", pkgPath, err) - return false - } - - return pkgs[0].isNewerThan(cmd, buildTime) -} - -func main() { - flag.Usage = usage - flag.Parse() - - cmd := &execcmd{ - cmd: "go", - args: []string{ - "list", - "-json", - }, - env: os.Environ(), - } - if !isTestStale(cmd, *binary, *pkgPath) { - os.Exit(1) - } -} diff --git a/vendor/k8s.io/kubernetes/hack/cmd/teststale/teststale_test.go b/vendor/k8s.io/kubernetes/hack/cmd/teststale/teststale_test.go deleted file mode 100644 index aa4e4fc21..000000000 --- a/vendor/k8s.io/kubernetes/hack/cmd/teststale/teststale_test.go +++ /dev/null @@ -1,325 +0,0 @@ -/* -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 main - -import ( - "fmt" - "io/ioutil" - "math/rand" - "os" - "path" - "path/filepath" - "testing" - "time" -) - -const ( - // seed for rand.Source to generate data for files - seed int64 = 42 - - // 1K binary file - binLen = 1024 - - // Directory of the test package relative to $GOPATH - testImportDir = "example.com/proj/pkg" -) - -var ( - pastHour = time.Now().Add(-1 * time.Hour) - - // The test package we are testing against - testPkg = path.Join(testImportDir, "test") -) - -// fakegolist implements the `golist` interface providing fake package information for testing. -type fakegolist struct { - dir string - importMap map[string]pkg - testFiles []string - binfile string -} - -func newFakegolist() (*fakegolist, error) { - dir, err := ioutil.TempDir("", "teststale") - if err != nil { - // test can't proceed without a temp directory. - return nil, fmt.Errorf("failed to create a temp directory for testing: %v", err) - } - - // Set the temp directory as the $GOPATH - if err := os.Setenv("GOPATH", dir); err != nil { - // can't proceed without pointing the $GOPATH to the temp directory. - return nil, fmt.Errorf("failed to set \"$GOPATH\" pointing to %q: %v", dir, err) - } - - // Setup $GOPATH directory layout. - // Yeah! I am bored of repeatedly writing "if err != nil {}"! - if os.MkdirAll(filepath.Join(dir, "bin"), 0750) != nil || - os.MkdirAll(filepath.Join(dir, "pkg", "linux_amd64"), 0750) != nil || - os.MkdirAll(filepath.Join(dir, "src"), 0750) != nil { - return nil, fmt.Errorf("failed to setup the $GOPATH directory structure") - } - - // Create a temp file to represent the test binary. - binfile, err := ioutil.TempFile("", "testbin") - if err != nil { - return nil, fmt.Errorf("failed to create the temp file to represent the test binary: %v", err) - } - - // Could have used crypto/rand instead, but it doesn't matter. - rr := rand.New(rand.NewSource(42)) - bin := make([]byte, binLen) - if _, err = rr.Read(bin); err != nil { - return nil, fmt.Errorf("couldn't read from the random source: %v", err) - } - if _, err := binfile.Write(bin); err != nil { - return nil, fmt.Errorf("couldn't write to the binary file %q: %v", binfile.Name(), err) - } - if err := binfile.Close(); err != nil { - // It is arguable whether this should be fatal. - return nil, fmt.Errorf("failed to close the binary file %q: %v", binfile.Name(), err) - } - - if err := os.Chtimes(binfile.Name(), time.Now(), time.Now()); err != nil { - return nil, fmt.Errorf("failed to modify the mtime of the binary file %q: %v", binfile.Name(), err) - } - - // Create test source files directory. - testdir := filepath.Join(dir, "src", testPkg) - if err := os.MkdirAll(testdir, 0750); err != nil { - return nil, fmt.Errorf("failed to create test source directory %q: %v", testdir, err) - } - - fgl := &fakegolist{ - dir: dir, - importMap: map[string]pkg{ - "example.com/proj/pkg/test": { - Dir: path.Join(dir, "src", testPkg), - ImportPath: testPkg, - Target: path.Join(dir, "pkg", "linux_amd64", testImportDir, "test.a"), - Stale: false, - TestGoFiles: []string{ - "foo_test.go", - "bar_test.go", - }, - TestImports: []string{ - "example.com/proj/pkg/p1", - "example.com/proj/pkg/p1/c11", - "example.com/proj/pkg/p2", - "example.com/proj/cmd/p3/c12/c23", - "strings", - "testing", - }, - XTestGoFiles: []string{ - "xfoo_test.go", - "xbar_test.go", - "xbaz_test.go", - }, - XTestImports: []string{ - "example.com/proj/pkg/test", - "example.com/proj/pkg/p1", - "example.com/proj/cmd/p3/c12/c23", - "os", - "testing", - }, - }, - "example.com/proj/pkg/p1": {Stale: false}, - "example.com/proj/pkg/p1/c11": {Stale: false}, - "example.com/proj/pkg/p2": {Stale: false}, - "example.com/proj/cmd/p3/c12/c23": {Stale: false}, - "strings": {Stale: false}, - "testing": {Stale: false}, - "os": {Stale: false}, - }, - testFiles: []string{ - "foo_test.go", - "bar_test.go", - "xfoo_test.go", - "xbar_test.go", - "xbaz_test.go", - }, - binfile: binfile.Name(), - } - - // Create test source files. - for _, fn := range fgl.testFiles { - fp := filepath.Join(testdir, fn) - if _, err := os.Create(fp); err != nil { - return nil, fmt.Errorf("failed to create the test file %q: %v", fp, err) - } - if err := os.Chtimes(fp, time.Now(), pastHour); err != nil { - return nil, fmt.Errorf("failed to modify the mtime of the test file %q: %v", binfile.Name(), err) - } - } - - return fgl, nil -} - -func (fgl *fakegolist) pkgInfo(pkgPaths []string) ([]pkg, error) { - var pkgs []pkg - for _, path := range pkgPaths { - p, ok := fgl.importMap[path] - if !ok { - return nil, fmt.Errorf("package %q not found", path) - } - pkgs = append(pkgs, p) - } - return pkgs, nil -} - -func (fgl *fakegolist) chMtime(filename string, mtime time.Time) error { - for _, fn := range fgl.testFiles { - if fn == filename { - fp := filepath.Join(fgl.dir, "src", testPkg, fn) - if err := os.Chtimes(fp, time.Now(), mtime); err != nil { - return fmt.Errorf("failed to modify the mtime of %q: %v", filename, err) - } - return nil - } - } - return fmt.Errorf("file %q not found", filename) -} - -func (fgl *fakegolist) chStale(pkg string, stale bool) error { - if p, ok := fgl.importMap[pkg]; ok { - p.Stale = stale - fgl.importMap[pkg] = p - return nil - } - return fmt.Errorf("package %q not found", pkg) -} - -func (fgl *fakegolist) cleanup() { - os.RemoveAll(fgl.dir) - os.Remove(fgl.binfile) -} - -func TestIsTestStale(t *testing.T) { - cases := []struct { - fileMtime map[string]time.Time - pkgStaleness map[string]bool - result bool - }{ - // Basic test: binary is fresh, all modifications were before the binary was built. - { - result: false, - }, - // A local test file is new, hence binary must be stale. - { - fileMtime: map[string]time.Time{ - "foo_test.go": time.Now().Add(1 * time.Hour), - }, - result: true, - }, - // Test package is new, so binary must be stale. - { - pkgStaleness: map[string]bool{ - "example.com/proj/pkg/test": true, - }, - result: true, - }, - // Test package dependencies are new, so binary must be stale. - { - pkgStaleness: map[string]bool{ - "example.com/proj/cmd/p3/c12/c23": true, - "strings": true, - }, - result: true, - }, - // External test files are new, hence binary must be stale. - { - fileMtime: map[string]time.Time{ - "xfoo_test.go": time.Now().Add(1 * time.Hour), - "xbar_test.go": time.Now().Add(2 * time.Hour), - }, - result: true, - }, - // External test dependency is new, so binary must be stale. - { - pkgStaleness: map[string]bool{ - "os": true, - }, - result: true, - }, - // Multiple source files and dependencies are new, so binary must be stale. - { - fileMtime: map[string]time.Time{ - "foo_test.go": time.Now().Add(1 * time.Hour), - "xfoo_test.go": time.Now().Add(2 * time.Hour), - "xbar_test.go": time.Now().Add(3 * time.Hour), - }, - pkgStaleness: map[string]bool{ - "example.com/proj/pkg/p1": true, - "example.com/proj/pkg/p1/c11": true, - "example.com/proj/pkg/p2": true, - "example.com/proj/cmd/p3/c12/c23": true, - "strings": true, - "os": true, - }, - result: true, - }, - // Everything is new, so binary must be stale. - { - fileMtime: map[string]time.Time{ - "foo_test.go": time.Now().Add(3 * time.Hour), - "bar_test.go": time.Now().Add(1 * time.Hour), - "xfoo_test.go": time.Now().Add(2 * time.Hour), - "xbar_test.go": time.Now().Add(1 * time.Hour), - "xbaz_test.go": time.Now().Add(2 * time.Hour), - }, - pkgStaleness: map[string]bool{ - "example.com/proj/pkg/p1": true, - "example.com/proj/pkg/p1/c11": true, - "example.com/proj/pkg/p2": true, - "example.com/proj/cmd/p3/c12/c23": true, - "example.com/proj/pkg/test": true, - "strings": true, - "testing": true, - "os": true, - }, - result: true, - }, - } - - for _, tc := range cases { - fgl, err := newFakegolist() - if err != nil { - t.Fatalf("failed to setup the test: %v", err) - } - defer fgl.cleanup() - - for fn, mtime := range tc.fileMtime { - if err := fgl.chMtime(fn, mtime); err != nil { - t.Fatalf("failed to change the mtime of %q: %v", fn, err) - } - } - - for pkg, stale := range tc.pkgStaleness { - if err := fgl.chStale(pkg, stale); err != nil { - t.Fatalf("failed to change the staleness of %q: %v", pkg, err) - } - } - - if tc.result != isTestStale(fgl, fgl.binfile, testPkg) { - if tc.result { - t.Errorf("Expected test package %q to be stale", testPkg) - } else { - t.Errorf("Expected test package %q to be not stale", testPkg) - } - } - } -} diff --git a/vendor/k8s.io/kubernetes/hack/dev-build-and-push.sh b/vendor/k8s.io/kubernetes/hack/dev-build-and-push.sh index 7510bb49c..83721142c 100755 --- a/vendor/k8s.io/kubernetes/hack/dev-build-and-push.sh +++ b/vendor/k8s.io/kubernetes/hack/dev-build-and-push.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/dev-build-and-up.sh b/vendor/k8s.io/kubernetes/hack/dev-build-and-up.sh index 9d2a9a104..816f85f82 100755 --- a/vendor/k8s.io/kubernetes/hack/dev-build-and-up.sh +++ b/vendor/k8s.io/kubernetes/hack/dev-build-and-up.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-cluster-size.sh b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-cluster-size.sh index a0921c374..8e604b9e3 100755 --- a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-cluster-size.sh +++ b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-cluster-size.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-down.sh b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-down.sh index 99bbc4380..87bcb9a41 100755 --- a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-down.sh +++ b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-down.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-grow-cluster.sh b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-grow-cluster.sh index 148ac3ed1..67b8603d2 100755 --- a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-grow-cluster.sh +++ b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-grow-cluster.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-shrink-cluster.sh b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-shrink-cluster.sh index 33e7e1945..4e67b9813 100755 --- a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-shrink-cluster.sh +++ b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-shrink-cluster.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-status.sh b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-status.sh index 37691ea81..59a4559e9 100755 --- a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-status.sh +++ b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-status.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-up.sh b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-up.sh index 6f8facb45..24f4f6a58 100755 --- a/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-up.sh +++ b/vendor/k8s.io/kubernetes/hack/e2e-internal/e2e-up.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/e2e-node-test.sh b/vendor/k8s.io/kubernetes/hack/e2e-node-test.sh index e74faabbe..4d697602f 100755 --- a/vendor/k8s.io/kubernetes/hack/e2e-node-test.sh +++ b/vendor/k8s.io/kubernetes/hack/e2e-node-test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/e2e.go b/vendor/k8s.io/kubernetes/hack/e2e.go index c016926c4..6352f42f6 100644 --- a/vendor/k8s.io/kubernetes/hack/e2e.go +++ b/vendor/k8s.io/kubernetes/hack/e2e.go @@ -46,6 +46,7 @@ func parse(args []string) (flags, error) { fs := flag.NewFlagSet(args[0], flag.ContinueOnError) get := fs.Bool("get", getDefault, "go get -u kubetest if old or not installed") old := fs.Duration("old", oldDefault, "Consider kubetest old if it exceeds this") + verbose := fs.Bool("v", true, "this flag is translated to kubetest's --verbose-commands") var a []string if err := fs.Parse(args[1:]); err == flag.ErrHelp { os.Stderr.WriteString(" -- kubetestArgs\n") @@ -58,7 +59,8 @@ func parse(args []string) (flags, error) { log.Print(" The -- flag separator also suppresses this message") a = args[len(args)-fs.NArg()-1:] } else { - a = fs.Args() + a = append(a, fmt.Sprintf("--verbose-commands=%t", *verbose)) + a = append(a, fs.Args()...) } return flags{*get, *old, a}, nil } diff --git a/vendor/k8s.io/kubernetes/hack/e2e_test.go b/vendor/k8s.io/kubernetes/hack/e2e_test.go index 77aca4ed5..cbede2409 100644 --- a/vendor/k8s.io/kubernetes/hack/e2e_test.go +++ b/vendor/k8s.io/kubernetes/hack/e2e_test.go @@ -62,14 +62,24 @@ func TestParse(t *testing.T) { expected flags err error }{ + { + []string{"foo", "-v=false"}, + flags{getDefault, oldDefault, []string{"--verbose-commands=false"}}, + nil, + }, + { + []string{"foo", "-v"}, + flags{getDefault, oldDefault, []string{"--verbose-commands=true"}}, + nil, + }, { []string{"hello", "world"}, - flags{getDefault, oldDefault, []string{"world"}}, + flags{getDefault, oldDefault, []string{"--verbose-commands=true", "world"}}, nil, }, { []string{"hello", "--", "--venus", "--karaoke"}, - flags{getDefault, oldDefault, []string{"--venus", "--karaoke"}}, + flags{getDefault, oldDefault, []string{"--verbose-commands=true", "--venus", "--karaoke"}}, nil, }, { @@ -84,12 +94,12 @@ func TestParse(t *testing.T) { }, { []string{"omg", "--get=false", "--", "ugh"}, - flags{false, oldDefault, []string{"ugh"}}, + flags{false, oldDefault, []string{"--verbose-commands=true", "ugh"}}, nil, }, { []string{"wee", "--old=5m", "--get"}, - flags{true, 5 * time.Minute, []string{}}, + flags{true, 5 * time.Minute, []string{"--verbose-commands=true"}}, nil, }, { @@ -104,7 +114,7 @@ func TestParse(t *testing.T) { }, { []string{"wut", "--", "-h"}, - flags{getDefault, oldDefault, []string{"-h"}}, + flags{getDefault, oldDefault, []string{"--verbose-commands=true", "-h"}}, nil, }, } diff --git a/vendor/k8s.io/kubernetes/hack/gen-swagger-doc/gen-swagger-docs.sh b/vendor/k8s.io/kubernetes/hack/gen-swagger-doc/gen-swagger-docs.sh index a6c9b2b86..381499d2f 100755 --- a/vendor/k8s.io/kubernetes/hack/gen-swagger-doc/gen-swagger-docs.sh +++ b/vendor/k8s.io/kubernetes/hack/gen-swagger-doc/gen-swagger-docs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/generate-bindata.sh b/vendor/k8s.io/kubernetes/hack/generate-bindata.sh index 6d2ec0a5d..f5153cfc5 100755 --- a/vendor/k8s.io/kubernetes/hack/generate-bindata.sh +++ b/vendor/k8s.io/kubernetes/hack/generate-bindata.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -18,20 +18,18 @@ set -o errexit set -o pipefail set -o nounset -if [[ -z "${KUBE_ROOT:-}" ]]; then - KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. -fi - +export KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. +source "${KUBE_ROOT}/hack/lib/init.sh" source "${KUBE_ROOT}/hack/lib/logging.sh" -if [[ ! -d "${KUBE_ROOT}/examples" ]]; then - echo "${KUBE_ROOT}/examples not detected. This script should be run from a location where the source dirs are available." +if [[ ! -d "${KUBE_ROOT}/pkg" ]]; then + echo "${KUBE_ROOT}/pkg not detected. This script should be run from a location where the source dirs are available." exit 1 fi # kube::golang::build_kube_toolchain installs the vendored go-bindata in # $GOPATH/bin, so make sure that's explicitly part of our $PATH. -export PATH="${GOPATH}/bin:${PATH}" +export PATH="${KUBE_OUTPUT_BINPATH}:${PATH}" if ! which go-bindata &>/dev/null ; then echo "Cannot find go-bindata." @@ -43,9 +41,10 @@ pushd "${KUBE_ROOT}" >/dev/null # These are files for e2e tests. BINDATA_OUTPUT="test/e2e/generated/bindata.go" +# IMPORTANT: if you make any changes to these arguments, you must also update +# test/e2e/generated/BUILD and/or build/bindata.bzl. go-bindata -nometadata -o "${BINDATA_OUTPUT}.tmp" -pkg generated \ - -ignore .jpg -ignore .png -ignore .md \ - "examples/..." \ + -ignore .jpg -ignore .png -ignore .md -ignore 'BUILD(\.bazel)?' \ "test/e2e/testing-manifests/..." \ "test/images/..." \ "test/fixtures/..." @@ -66,8 +65,10 @@ rm -f "${BINDATA_OUTPUT}.tmp" # These are files for runtime code BINDATA_OUTPUT="pkg/generated/bindata.go" +# IMPORTANT: if you make any changes to these arguments, you must also update +# pkg/generated/BUILD and/or build/bindata.bzl. go-bindata -nometadata -nocompress -o "${BINDATA_OUTPUT}.tmp" -pkg generated \ - -ignore .jpg -ignore .png -ignore .md \ + -ignore .jpg -ignore .png -ignore .md -ignore 'BUILD(\.bazel)?' \ "translations/..." gofmt -s -w "${BINDATA_OUTPUT}.tmp" diff --git a/vendor/k8s.io/kubernetes/hack/generate-docs.sh b/vendor/k8s.io/kubernetes/hack/generate-docs.sh index 8fdf81a7d..6071d562f 100755 --- a/vendor/k8s.io/kubernetes/hack/generate-docs.sh +++ b/vendor/k8s.io/kubernetes/hack/generate-docs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/get-build.sh b/vendor/k8s.io/kubernetes/hack/get-build.sh index 1e4d75791..f1fbe0289 100755 --- a/vendor/k8s.io/kubernetes/hack/get-build.sh +++ b/vendor/k8s.io/kubernetes/hack/get-build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/ginkgo-e2e.sh b/vendor/k8s.io/kubernetes/hack/ginkgo-e2e.sh index bc7540186..0cac8afc6 100755 --- a/vendor/k8s.io/kubernetes/hack/ginkgo-e2e.sh +++ b/vendor/k8s.io/kubernetes/hack/ginkgo-e2e.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -159,7 +159,8 @@ export PATH=$(dirname "${e2e_test}"):"${PATH}" --network="${KUBE_GCE_NETWORK:-${KUBE_GKE_NETWORK:-e2e}}" \ --node-tag="${NODE_TAG:-}" \ --master-tag="${MASTER_TAG:-}" \ - --cluster-monitoring-mode="${KUBE_ENABLE_CLUSTER_MONITORING:-influxdb}" \ + --cluster-monitoring-mode="${KUBE_ENABLE_CLUSTER_MONITORING:-standalone}" \ + --prometheus-monitoring="${KUBE_ENABLE_PROMETHEUS_MONITORING:-false}" \ ${KUBE_CONTAINER_RUNTIME:+"--container-runtime=${KUBE_CONTAINER_RUNTIME}"} \ ${MASTER_OS_DISTRIBUTION:+"--master-os-distro=${MASTER_OS_DISTRIBUTION}"} \ ${NODE_OS_DISTRIBUTION:+"--node-os-distro=${NODE_OS_DISTRIBUTION}"} \ diff --git a/vendor/k8s.io/kubernetes/hack/godep-restore.sh b/vendor/k8s.io/kubernetes/hack/godep-restore.sh index 5da18d8f0..02b7dbb55 100755 --- a/vendor/k8s.io/kubernetes/hack/godep-restore.sh +++ b/vendor/k8s.io/kubernetes/hack/godep-restore.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/godep-save.sh b/vendor/k8s.io/kubernetes/hack/godep-save.sh index a7146f13b..1ed15517f 100755 --- a/vendor/k8s.io/kubernetes/hack/godep-save.sh +++ b/vendor/k8s.io/kubernetes/hack/godep-save.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -59,6 +59,8 @@ REQUIRED_BINS=( "github.com/jteeuwen/go-bindata/go-bindata" "github.com/tools/godep" "github.com/client9/misspell/cmd/misspell" + "github.com/bazelbuild/bazel-gazelle/cmd/gazelle" + "github.com/kubernetes/repo-infra/kazel" "./..." ) @@ -81,6 +83,11 @@ done rm -rf vendor/github.com/docker/docker/project/ kube::log::status "Updating BUILD files" +# Assume that anything imported through godep doesn't need Bazel to build. +# Prune out any Bazel build files, since these can break the build due to +# missing dependencies that aren't included by godep. +find vendor/ -type f \( -name BUILD -o -name BUILD.bazel -o -name WORKSPACE \) \ + -exec rm -f {} \; hack/update-bazel.sh >/dev/null kube::log::status "Updating LICENSES file" diff --git a/vendor/k8s.io/kubernetes/hack/grab-profiles.sh b/vendor/k8s.io/kubernetes/hack/grab-profiles.sh index e1d44f3a5..e9b4b09f5 100755 --- a/vendor/k8s.io/kubernetes/hack/grab-profiles.sh +++ b/vendor/k8s.io/kubernetes/hack/grab-profiles.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/import-restrictions.yaml b/vendor/k8s.io/kubernetes/hack/import-restrictions.yaml index c9b99ae24..19e12ac1e 100644 --- a/vendor/k8s.io/kubernetes/hack/import-restrictions.yaml +++ b/vendor/k8s.io/kubernetes/hack/import-restrictions.yaml @@ -17,6 +17,15 @@ ignoredSubTrees: - "./pkg/apis/core/validation" +- baseImportPath: "./pkg/kubectl/genericclioptions/" + allowedImports: + - k8s.io/apimachinery + - k8s.io/client-go + # TODO this one should be tightened. We depend on it for testing, but we should instead create our own scheme + - k8s.io/api/core/v1 + - k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers + - k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource + - baseImportPath: "./vendor/k8s.io/apimachinery/" allowedImports: - k8s.io/apimachinery @@ -41,6 +50,28 @@ - k8s.io/apimachinery - k8s.io/client-go +# prevent core machinery from taking explicit v1 references unless +# necessary +- baseImportPath: "./vendor/k8s.io/client-go/rest/" + excludeTests: true + allowedImports: + - k8s.io/apimachinery + - k8s.io/client-go +- baseImportPath: "./vendor/k8s.io/client-go/tools/" + excludeTests: true + ignoredSubTrees: + - "./vendor/k8s.io/client-go/tools/bootstrap/token/api" + - "./vendor/k8s.io/client-go/tools/cache/testing" + - "./vendor/k8s.io/client-go/tools/leaderelection/resourcelock" + - "./vendor/k8s.io/client-go/tools/portforward" + - "./vendor/k8s.io/client-go/tools/record" + - "./vendor/k8s.io/client-go/tools/reference" + - "./vendor/k8s.io/client-go/tools/remotecommand" + allowedImports: + - k8s.io/apimachinery + - k8s.io/client-go + + - baseImportPath: "./vendor/k8s.io/apiserver/" allowedImports: - k8s.io/api diff --git a/vendor/k8s.io/kubernetes/hack/install-etcd.sh b/vendor/k8s.io/kubernetes/hack/install-etcd.sh index 365bab8aa..3f5961a53 100755 --- a/vendor/k8s.io/kubernetes/hack/install-etcd.sh +++ b/vendor/k8s.io/kubernetes/hack/install-etcd.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/jenkins/benchmark-dockerized.sh b/vendor/k8s.io/kubernetes/hack/jenkins/benchmark-dockerized.sh index 2d21f8f80..4171cf651 100755 --- a/vendor/k8s.io/kubernetes/hack/jenkins/benchmark-dockerized.sh +++ b/vendor/k8s.io/kubernetes/hack/jenkins/benchmark-dockerized.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/jenkins/build.sh b/vendor/k8s.io/kubernetes/hack/jenkins/build.sh index ca25459a9..02b90370f 100755 --- a/vendor/k8s.io/kubernetes/hack/jenkins/build.sh +++ b/vendor/k8s.io/kubernetes/hack/jenkins/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/jenkins/gotest.sh b/vendor/k8s.io/kubernetes/hack/jenkins/gotest.sh index df9e6696d..cc298ccaa 100755 --- a/vendor/k8s.io/kubernetes/hack/jenkins/gotest.sh +++ b/vendor/k8s.io/kubernetes/hack/jenkins/gotest.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/jenkins/test-dockerized.sh b/vendor/k8s.io/kubernetes/hack/jenkins/test-dockerized.sh index f16e48da0..48f8306ce 100755 --- a/vendor/k8s.io/kubernetes/hack/jenkins/test-dockerized.sh +++ b/vendor/k8s.io/kubernetes/hack/jenkins/test-dockerized.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/jenkins/upload-to-gcs.sh b/vendor/k8s.io/kubernetes/hack/jenkins/upload-to-gcs.sh index aca420eeb..116a8aea1 100755 --- a/vendor/k8s.io/kubernetes/hack/jenkins/upload-to-gcs.sh +++ b/vendor/k8s.io/kubernetes/hack/jenkins/upload-to-gcs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/jenkins/verify-dockerized.sh b/vendor/k8s.io/kubernetes/hack/jenkins/verify-dockerized.sh index ba34d07df..a15c811aa 100755 --- a/vendor/k8s.io/kubernetes/hack/jenkins/verify-dockerized.sh +++ b/vendor/k8s.io/kubernetes/hack/jenkins/verify-dockerized.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/jenkins/verify.sh b/vendor/k8s.io/kubernetes/hack/jenkins/verify.sh index 7393f6b4a..6c2f85708 100755 --- a/vendor/k8s.io/kubernetes/hack/jenkins/verify.sh +++ b/vendor/k8s.io/kubernetes/hack/jenkins/verify.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/lib/etcd.sh b/vendor/k8s.io/kubernetes/hack/lib/etcd.sh index c5d690cc9..3719dbf67 100755 --- a/vendor/k8s.io/kubernetes/hack/lib/etcd.sh +++ b/vendor/k8s.io/kubernetes/hack/lib/etcd.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -16,7 +16,7 @@ # A set of helpers for starting/running etcd for tests -ETCD_VERSION=${ETCD_VERSION:-3.1.12} +ETCD_VERSION=${ETCD_VERSION:-3.2.18} ETCD_HOST=${ETCD_HOST:-127.0.0.1} ETCD_PORT=${ETCD_PORT:-2379} diff --git a/vendor/k8s.io/kubernetes/hack/lib/golang.sh b/vendor/k8s.io/kubernetes/hack/lib/golang.sh index 5f56a8150..c5d463483 100755 --- a/vendor/k8s.io/kubernetes/hack/lib/golang.sh +++ b/vendor/k8s.io/kubernetes/hack/lib/golang.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -213,17 +213,27 @@ readonly KUBE_STATIC_LIBRARIES=( kubectl ) -# Add any files with those //generate annotations in the array below. -readonly KUBE_BINDATAS=( - test/e2e/generated/gobindata_util.go -) +# KUBE_CGO_OVERRIDES is a space-separated list of binaries which should be built +# with CGO enabled, assuming CGO is supported on the target platform. +# This overrides any entry in KUBE_STATIC_LIBRARIES. +IFS=" " read -ra KUBE_CGO_OVERRIDES <<< "${KUBE_CGO_OVERRIDES:-}" +readonly KUBE_CGO_OVERRIDES +# KUBE_STATIC_OVERRIDES is a space-separated list of binaries which should be +# built with CGO disabled. This is in addition to the list in +# KUBE_STATIC_LIBRARIES. +IFS=" " read -ra KUBE_STATIC_OVERRIDES <<< "${KUBE_STATIC_OVERRIDES:-}" +readonly KUBE_STATIC_OVERRIDES kube::golang::is_statically_linked_library() { local e + # Explicitly enable cgo when building kubectl for darwin from darwin. + [[ "$(go env GOHOSTOS)" == "darwin" && "$(go env GOOS)" == "darwin" && + "$1" == *"/kubectl" ]] && return 1 + if [[ -n "${KUBE_CGO_OVERRIDES:+x}" ]]; then + for e in "${KUBE_CGO_OVERRIDES[@]}"; do [[ "$1" == *"/$e" ]] && return 1; done; + fi for e in "${KUBE_STATIC_LIBRARIES[@]}"; do [[ "$1" == *"/$e" ]] && return 0; done; - # Allow individual overrides--e.g., so that you can get a static build of - # kubectl for inclusion in a container. - if [ -n "${KUBE_STATIC_OVERRIDES:+x}" ]; then + if [[ -n "${KUBE_STATIC_OVERRIDES:+x}" ]]; then for e in "${KUBE_STATIC_OVERRIDES[@]}"; do [[ "$1" == *"/$e" ]] && return 0; done; fi return 1; @@ -326,7 +336,7 @@ EOF local go_version IFS=" " read -ra go_version <<< "$(go version)" local minimum_go_version - minimum_go_version=go1.9.1 + minimum_go_version=go1.10.2 if [[ "${minimum_go_version}" != $(echo -e "${minimum_go_version}\n${go_version[2]}" | sort -s -t. -k 1,1 -k 2,2n -k 3,3n | head -n1) && "${go_version[2]}" != "devel" ]]; then kube::log::usage_from_stdin < "/tmp//${platform//\//_}.build" & done @@ -709,7 +607,7 @@ kube::golang::build_binaries() { kube::log::status "Building go targets for ${platform}:" "${targets[@]}" ( kube::golang::set_platform_envs "${platform}" - kube::golang::build_binaries_for_platform ${platform} ${use_go_build:-} + kube::golang::build_binaries_for_platform ${platform} ) done fi diff --git a/vendor/k8s.io/kubernetes/hack/lib/init.sh b/vendor/k8s.io/kubernetes/hack/lib/init.sh index bd0a5e3fb..2f1a33a0b 100755 --- a/vendor/k8s.io/kubernetes/hack/lib/init.sh +++ b/vendor/k8s.io/kubernetes/hack/lib/init.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -81,6 +81,7 @@ rbac.authorization.k8s.io/v1 \ rbac.authorization.k8s.io/v1beta1 \ rbac.authorization.k8s.io/v1alpha1 \ scheduling.k8s.io/v1alpha1 \ +scheduling.k8s.io/v1beta1 \ settings.k8s.io/v1alpha1 \ storage.k8s.io/v1beta1 \ storage.k8s.io/v1 \ diff --git a/vendor/k8s.io/kubernetes/hack/lib/logging.sh b/vendor/k8s.io/kubernetes/hack/lib/logging.sh index 1c74f6652..458c21886 100644 --- a/vendor/k8s.io/kubernetes/hack/lib/logging.sh +++ b/vendor/k8s.io/kubernetes/hack/lib/logging.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/lib/protoc.sh b/vendor/k8s.io/kubernetes/hack/lib/protoc.sh index 1adcea4b9..2ba21ecee 100644 --- a/vendor/k8s.io/kubernetes/hack/lib/protoc.sh +++ b/vendor/k8s.io/kubernetes/hack/lib/protoc.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -71,8 +71,7 @@ function kube::protoc::format() { local package=${1} # Update boilerplate for the generated file. - echo "$(cat hack/boilerplate/boilerplate.go.txt ${package}/api.pb.go)" > ${package}/api.pb.go - sed -i".bak" "s/Copyright YEAR/Copyright $(date '+%Y')/g" ${package}/api.pb.go + echo "$(cat hack/boilerplate/boilerplate.generatego.txt ${package}/api.pb.go)" > ${package}/api.pb.go # Run gofmt to clean up the generated code. kube::golang::verify_go_version diff --git a/vendor/k8s.io/kubernetes/hack/lib/swagger.sh b/vendor/k8s.io/kubernetes/hack/lib/swagger.sh index af872d807..da63a90d9 100644 --- a/vendor/k8s.io/kubernetes/hack/lib/swagger.sh +++ b/vendor/k8s.io/kubernetes/hack/lib/swagger.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -34,7 +34,7 @@ kube::swagger::gen_types_swagger_doc() { echo "Generating swagger type docs for ${group_version} at ${gv_dir}" - sed 's/YEAR/2016/' hack/boilerplate/boilerplate.go.txt > "$TMPFILE" + echo -e "$(cat hack/boilerplate/boilerplate.generatego.txt)\n" > "$TMPFILE" echo "package ${group_version##*/}" >> "$TMPFILE" cat >> "$TMPFILE" </dev/null || { kube::log::usage "curl must be installed" @@ -32,7 +33,7 @@ kube::util::wait_for_url() { local i for i in $(seq 1 "$times"); do local out - if out=$(curl --max-time 1 -gkfs "$url" 2>/dev/null); then + if out=$(curl --max-time "$maxtime" -gkfs "$url" 2>/dev/null); then kube::log::status "On try ${i}, ${prefix}: ${out}" return 0 fi @@ -275,9 +276,6 @@ kube::util::group-version-to-pkg-path() { meta/v1beta1) echo "vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1" ;; - unversioned) - echo "pkg/api/unversioned" - ;; *.k8s.io) echo "pkg/apis/${group_version%.*k8s.io}" ;; @@ -430,7 +428,7 @@ kube::util::ensure_clean_working_dir() { # Ensure that the given godep version is installed and in the path. Almost # nobody should use any version but the default. kube::util::ensure_godep_version() { - GODEP_VERSION=${1:-"v79"} # this version is known to work + GODEP_VERSION=${1:-"v80"} # this version is known to work if [[ "$(godep version 2>/dev/null)" == *"godep ${GODEP_VERSION}"* ]]; then return @@ -438,12 +436,19 @@ kube::util::ensure_godep_version() { kube::log::status "Installing godep version ${GODEP_VERSION}" go install ./vendor/github.com/tools/godep/ - GP="$(echo $GOPATH | cut -f1 -d:)" - hash -r # force bash to clear PATH cache - PATH="${GP}/bin:${PATH}" + if ! which godep >/dev/null 2>&1; then + kube::log::error "Can't find godep - is your GOPATH 'bin' in your PATH?" + kube::log::error " GOPATH: ${GOPATH}" + kube::log::error " PATH: ${PATH}" + return 1 + fi if [[ "$(godep version 2>/dev/null)" != *"godep ${GODEP_VERSION}"* ]]; then - kube::log::error "Expected godep ${GODEP_VERSION}, got $(godep version)" + kube::log::error "Wrong godep version - is your GOPATH 'bin' in your PATH?" + kube::log::error " expected: godep ${GODEP_VERSION}" + kube::log::error " got: $(godep version)" + kube::log::error " GOPATH: ${GOPATH}" + kube::log::error " PATH: ${PATH}" return 1 fi } @@ -469,23 +474,6 @@ kube::util::ensure_no_staging_repos_in_gopath() { fi } -# Installs the specified go package at a particular commit. -kube::util::go_install_from_commit() { - local -r pkg=$1 - local -r commit=$2 - - kube::util::ensure-temp-dir - mkdir -p "${KUBE_TEMP}/go/src" - GOPATH="${KUBE_TEMP}/go" go get -d -u "${pkg}" - ( - cd "${KUBE_TEMP}/go/src/${pkg}" - git checkout -q "${commit}" - GOPATH="${KUBE_TEMP}/go" go install "${pkg}" - ) - PATH="${KUBE_TEMP}/go/bin:${PATH}" - hash -r # force bash to clear PATH cache -} - # Checks that the GOPATH is simple, i.e. consists only of one directory, not multiple. kube::util::ensure_single_dir_gopath() { if [[ "${GOPATH}" == *:* ]]; then @@ -566,7 +554,7 @@ function kube::util::create_signing_certkey { local id=$3 local purpose=$4 # Create client ca - ${sudo} /bin/bash -e < "${dest_dir}/${id}-ca-config.json" @@ -588,7 +576,7 @@ function kube::util::create_client_certkey { SEP="," shift 1 done - ${sudo} /bin/bash -e < "/tmp/${client_id}.kubeconfig" mv -f "/tmp/${client_id}.kubeconfig" "${dest_dir}/${client_id}.kubeconfig" chown ${username} "${dest_dir}/${client_id}.kubeconfig" diff --git a/vendor/k8s.io/kubernetes/hack/lib/version.sh b/vendor/k8s.io/kubernetes/hack/lib/version.sh index 5d77bd0b9..5096ac3ab 100644 --- a/vendor/k8s.io/kubernetes/hack/lib/version.sh +++ b/vendor/k8s.io/kubernetes/hack/lib/version.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -99,7 +99,7 @@ kube::version::get_version_vars() { # If KUBE_GIT_VERSION is not a valid Semantic Version, then refuse to build. if ! [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then - echo "KUBE_GIT_VERSION should be a valid Semantic Version" + echo "KUBE_GIT_VERSION should be a valid Semantic Version. Current value: ${KUBE_GIT_VERSION}" echo "Please see more details here: https://semver.org" exit 1 fi diff --git a/vendor/k8s.io/kubernetes/hack/list-feature-tests.sh b/vendor/k8s.io/kubernetes/hack/list-feature-tests.sh index 72ae00126..5d5fcf433 100755 --- a/vendor/k8s.io/kubernetes/hack/list-feature-tests.sh +++ b/vendor/k8s.io/kubernetes/hack/list-feature-tests.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/local-up-cluster.sh b/vendor/k8s.io/kubernetes/hack/local-up-cluster.sh index 412e33b4d..8291ac761 100755 --- a/vendor/k8s.io/kubernetes/hack/local-up-cluster.sh +++ b/vendor/k8s.io/kubernetes/hack/local-up-cluster.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -22,6 +22,7 @@ KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. DOCKER_OPTS=${DOCKER_OPTS:-""} DOCKER=(docker ${DOCKER_OPTS}) DOCKERIZE_KUBELET=${DOCKERIZE_KUBELET:-""} +DOCKER_ROOT=${DOCKER_ROOT:-""} ALLOW_PRIVILEGED=${ALLOW_PRIVILEGED:-""} DENY_SECURITY_CONTEXT_ADMISSION=${DENY_SECURITY_CONTEXT_ADMISSION:-""} PSP_ADMISSION=${PSP_ADMISSION:-""} @@ -31,6 +32,7 @@ KUBELET_AUTHORIZATION_WEBHOOK=${KUBELET_AUTHORIZATION_WEBHOOK:-""} KUBELET_AUTHENTICATION_WEBHOOK=${KUBELET_AUTHENTICATION_WEBHOOK:-""} POD_MANIFEST_PATH=${POD_MANIFEST_PATH:-"/var/run/kubernetes/static-pods"} KUBELET_FLAGS=${KUBELET_FLAGS:-""} +KUBELET_IMAGE=${KUBELET_IMAGE:-""} # many dev environments run with swap on, so we don't fail in this env FAIL_SWAP_ON=${FAIL_SWAP_ON:-"false"} # Name of the network plugin, eg: "kubenet" @@ -61,8 +63,9 @@ KUBE_PROXY_MODE=${KUBE_PROXY_MODE:-""} ENABLE_CLUSTER_DNS=${KUBE_ENABLE_CLUSTER_DNS:-true} DNS_SERVER_IP=${KUBE_DNS_SERVER_IP:-10.0.0.10} DNS_DOMAIN=${KUBE_DNS_NAME:-"cluster.local"} -KUBECTL=${KUBECTL:-cluster/kubectl.sh} +KUBECTL=${KUBECTL:-"${KUBE_ROOT}/cluster/kubectl.sh"} WAIT_FOR_URL_API_SERVER=${WAIT_FOR_URL_API_SERVER:-60} +MAX_TIME_FOR_URL_API_SERVER=${MAX_TIME_FOR_URL_API_SERVER:-1} ENABLE_DAEMON=${ENABLE_DAEMON:-false} HOSTNAME_OVERRIDE=${HOSTNAME_OVERRIDE:-"127.0.0.1"} EXTERNAL_CLOUD_PROVIDER=${EXTERNAL_CLOUD_PROVIDER:-false} @@ -71,6 +74,8 @@ CLOUD_PROVIDER=${CLOUD_PROVIDER:-""} CLOUD_CONFIG=${CLOUD_CONFIG:-""} FEATURE_GATES=${FEATURE_GATES:-"AllAlpha=false"} STORAGE_BACKEND=${STORAGE_BACKEND:-"etcd3"} +# preserve etcd data. you also need to set ETCD_DIR. +PRESERVE_ETCD="${PRESERVE_ETCD:-false}" # enable swagger ui ENABLE_SWAGGER_UI=${ENABLE_SWAGGER_UI:-false} # enable Pod priority and preemption @@ -90,8 +95,9 @@ AUTH_ARGS=${AUTH_ARGS:-""} # Install a default storage class (enabled by default) DEFAULT_STORAGE_CLASS=${KUBE_DEFAULT_STORAGE_CLASS:-true} -# start the cache mutation detector by default so that cache mutators will be found -KUBE_CACHE_MUTATION_DETECTOR="${KUBE_CACHE_MUTATION_DETECTOR:-true}" +# Do not run the mutation detector by default on a local cluster. +# It is intended for a specific type of testing and inherently leaks memory. +KUBE_CACHE_MUTATION_DETECTOR="${KUBE_CACHE_MUTATION_DETECTOR:-false}" export KUBE_CACHE_MUTATION_DETECTOR # panic the server on watch decode errors since they are considered coder mistakes @@ -120,13 +126,11 @@ if [ "${CLOUD_PROVIDER}" == "openstack" ]; then fi fi -# set feature gates if using ipvs mode +# load required kernel modules if proxy mode is set to "ipvs". if [ "${KUBE_PROXY_MODE}" == "ipvs" ]; then # If required kernel modules are not available, fall back to iptables. sudo modprobe -a ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack_ipv4 - if [[ $? -eq 0 ]]; then - FEATURE_GATES="${FEATURE_GATES},SupportIPVSProxyMode=true" - else + if [[ $? -ne 0 ]]; then echo "Required kernel modules for ipvs not found. Falling back to iptables mode." KUBE_PROXY_MODE=iptables fi @@ -139,7 +143,7 @@ fi # warn if users are running with swap allowed if [ "${FAIL_SWAP_ON}" == "false" ]; then - echo "WARNING : The kubelet is configured to not fail if swap is enabled; production deployments should disable swap." + echo "WARNING : The kubelet is configured to not fail even if swap is enabled; production deployments should disable swap." fi if [ "$(id -u)" != "0" ]; then @@ -203,23 +207,6 @@ else echo "skipped the build." fi -function test_rkt { - if [[ -n "${RKT_PATH}" ]]; then - ${RKT_PATH} list 2> /dev/null 1> /dev/null - if [ "$?" != "0" ]; then - echo "Failed to successfully run 'rkt list', please verify that ${RKT_PATH} is the path of rkt binary." - exit 1 - fi - else - rkt list 2> /dev/null 1> /dev/null - if [ "$?" != "0" ]; then - echo "Failed to successfully run 'rkt list', please verify that rkt is in \$PATH." - exit 1 - fi - fi -} - - # Shut down anyway if there's an error. set +e @@ -230,6 +217,7 @@ API_SECURE_PORT=${API_SECURE_PORT:-6443} API_HOST=${API_HOST:-localhost} API_HOST_IP=${API_HOST_IP:-"127.0.0.1"} ADVERTISE_ADDRESS=${ADVERTISE_ADDRESS:-""} +NODE_PORT_RANGE=${NODE_PORT_RANGE:-""} API_BIND_ADDR=${API_BIND_ADDR:-"0.0.0.0"} EXTERNAL_HOSTNAME=${EXTERNAL_HOSTNAME:-localhost} @@ -244,8 +232,6 @@ LOG_DIR=${LOG_DIR:-"/tmp"} CONTAINER_RUNTIME=${CONTAINER_RUNTIME:-"docker"} CONTAINER_RUNTIME_ENDPOINT=${CONTAINER_RUNTIME_ENDPOINT:-""} IMAGE_SERVICE_ENDPOINT=${IMAGE_SERVICE_ENDPOINT:-""} -RKT_PATH=${RKT_PATH:-""} -RKT_STAGE1_IMAGE=${RKT_STAGE1_IMAGE:-""} CHAOS_CHANCE=${CHAOS_CHANCE:-0.0} CPU_CFS_QUOTA=${CPU_CFS_QUOTA:-true} ENABLE_HOSTPATH_PROVISIONER=${ENABLE_HOSTPATH_PROVISIONER:-"false"} @@ -355,6 +341,13 @@ cleanup_dockerized_kubelet() if [[ -e $KUBELET_CIDFILE ]]; then docker kill $(<$KUBELET_CIDFILE) > /dev/null rm -f $KUBELET_CIDFILE + + # Save the docker logs + if [[ -f /var/log/docker.log ]]; then + sudo cp /var/log/docker.log ${LOG_DIR}/docker.log + elif command -v journalctl &>/dev/null; then + journalctl -u docker --no-pager > ${LOG_DIR}/docker.log + fi fi } @@ -371,35 +364,73 @@ cleanup() # Check if the API server is still running [[ -n "${APISERVER_PID-}" ]] && APISERVER_PIDS=$(pgrep -P ${APISERVER_PID} ; ps -o pid= -p ${APISERVER_PID}) - [[ -n "${APISERVER_PIDS-}" ]] && sudo kill ${APISERVER_PIDS} + [[ -n "${APISERVER_PIDS-}" ]] && sudo kill ${APISERVER_PIDS} 2>/dev/null # Check if the controller-manager is still running [[ -n "${CTLRMGR_PID-}" ]] && CTLRMGR_PIDS=$(pgrep -P ${CTLRMGR_PID} ; ps -o pid= -p ${CTLRMGR_PID}) - [[ -n "${CTLRMGR_PIDS-}" ]] && sudo kill ${CTLRMGR_PIDS} + [[ -n "${CTLRMGR_PIDS-}" ]] && sudo kill ${CTLRMGR_PIDS} 2>/dev/null if [[ -n "$DOCKERIZE_KUBELET" ]]; then cleanup_dockerized_kubelet else # Check if the kubelet is still running [[ -n "${KUBELET_PID-}" ]] && KUBELET_PIDS=$(pgrep -P ${KUBELET_PID} ; ps -o pid= -p ${KUBELET_PID}) - [[ -n "${KUBELET_PIDS-}" ]] && sudo kill ${KUBELET_PIDS} + [[ -n "${KUBELET_PIDS-}" ]] && sudo kill ${KUBELET_PIDS} 2>/dev/null fi # Check if the proxy is still running [[ -n "${PROXY_PID-}" ]] && PROXY_PIDS=$(pgrep -P ${PROXY_PID} ; ps -o pid= -p ${PROXY_PID}) - [[ -n "${PROXY_PIDS-}" ]] && sudo kill ${PROXY_PIDS} + [[ -n "${PROXY_PIDS-}" ]] && sudo kill ${PROXY_PIDS} 2>/dev/null # Check if the scheduler is still running [[ -n "${SCHEDULER_PID-}" ]] && SCHEDULER_PIDS=$(pgrep -P ${SCHEDULER_PID} ; ps -o pid= -p ${SCHEDULER_PID}) - [[ -n "${SCHEDULER_PIDS-}" ]] && sudo kill ${SCHEDULER_PIDS} + [[ -n "${SCHEDULER_PIDS-}" ]] && sudo kill ${SCHEDULER_PIDS} 2>/dev/null # Check if the etcd is still running [[ -n "${ETCD_PID-}" ]] && kube::etcd::stop - [[ -n "${ETCD_DIR-}" ]] && kube::etcd::clean_etcd_dir - + if [[ "${PRESERVE_ETCD}" == "false" ]]; then + [[ -n "${ETCD_DIR-}" ]] && kube::etcd::clean_etcd_dir + fi exit 0 } +# Check if all processes are still running. Prints a warning once each time +# a process dies unexpectedly. +function healthcheck { + if [[ -n "${APISERVER_PID-}" ]] && ! sudo kill -0 ${APISERVER_PID} 2>/dev/null; then + warning "API server terminated unexpectedly, see ${APISERVER_LOG}" + APISERVER_PID= + fi + + if [[ -n "${CTLRMGR_PID-}" ]] && ! sudo kill -0 ${CTLRMGR_PID} 2>/dev/null; then + warning "kube-controller-manager terminated unexpectedly, see ${CTLRMGR_LOG}" + CTLRMGR_PID= + fi + + if [[ -n "$DOCKERIZE_KUBELET" ]]; then + # TODO (https://github.com/kubernetes/kubernetes/issues/62474): check health also in this case + : + elif [[ -n "${KUBELET_PID-}" ]] && ! sudo kill -0 ${KUBELET_PID} 2>/dev/null; then + warning "kubelet terminated unexpectedly, see ${KUBELET_LOG}" + KUBELET_PID= + fi + + if [[ -n "${PROXY_PID-}" ]] && ! sudo kill -0 ${PROXY_PID} 2>/dev/null; then + warning "kube-proxy terminated unexpectedly, see ${PROXY_LOG}" + PROXY_PID= + fi + + if [[ -n "${SCHEDULER_PID-}" ]] && ! sudo kill -0 ${SCHEDULER_PID} 2>/dev/null; then + warning "scheduler terminated unexpectedly, see ${SCHEDULER_LOG}" + SCHEDULER_PID= + fi + + if [[ -n "${ETCD_PID-}" ]] && ! sudo kill -0 ${ETCD_PID} 2>/dev/null; then + warning "etcd terminated unexpectedly" + ETCD_PID= + fi +} + function warning { message=$1 @@ -446,7 +477,7 @@ function start_apiserver { # Admission Controllers to invoke prior to persisting objects in cluster # # The order defined here dose not matter. - ENABLE_ADMISSION_PLUGINS=Initializers,LimitRanger,ServiceAccount${security_admission},DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset,StorageObjectInUseProtection + ENABLE_ADMISSION_PLUGINS=Initializers,LimitRanger,ServiceAccount${security_admission},DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,StorageObjectInUseProtection audit_arg="" APISERVER_BASIC_AUDIT_LOG="" @@ -487,13 +518,6 @@ function start_apiserver { RUNTIME_CONFIG+="admissionregistration.k8s.io/v1alpha1" fi - if [[ ${ENABLE_ADMISSION_PLUGINS} == *"PodPreset"* ]]; then - if [[ -n "${RUNTIME_CONFIG}" ]]; then - RUNTIME_CONFIG+="," - fi - RUNTIME_CONFIG+="settings.k8s.io/v1alpha1" - fi - runtime_config="" if [[ -n "${RUNTIME_CONFIG}" ]]; then runtime_config="--runtime-config=${RUNTIME_CONFIG}" @@ -508,6 +532,10 @@ function start_apiserver { if [[ "${ADVERTISE_ADDRESS}" != "" ]] ; then advertise_address="--advertise-address=${ADVERTISE_ADDRESS}" fi + node_port_range="" + if [[ "${NODE_PORT_RANGE}" != "" ]] ; then + node_port_range="--service-node-port-range=${NODE_PORT_RANGE}" + fi # Create CA signers if [[ "${ENABLE_SINGLE_CA_SIGNER:-}" = true ]]; then @@ -549,6 +577,7 @@ function start_apiserver { ${CONTROLPLANE_SUDO} "${GO_OUT}/hyperkube" apiserver ${swagger_arg} ${audit_arg} ${authorizer_arg} ${priv_arg} ${runtime_config} \ ${cloud_config_arg} \ ${advertise_address} \ + ${node_port_range} \ --v=${LOG_LEVEL} \ --vmodule="${LOG_SPEC}" \ --cert-dir="${CERT_DIR}" \ @@ -581,10 +610,7 @@ function start_apiserver { # Wait for kube-apiserver to come up before launching the rest of the components. echo "Waiting for apiserver to come up" - # this uses the API port because if you don't have any authenticator, you can't seem to use the secure port at all. - # this matches what happened with the combination in 1.4. - # TODO change this conditionally based on whether API_PORT is on or off - kube::util::wait_for_url "https://${API_HOST_IP}:${API_SECURE_PORT}/healthz" "apiserver: " 1 ${WAIT_FOR_URL_API_SERVER} \ + kube::util::wait_for_url "https://${API_HOST_IP}:${API_SECURE_PORT}/healthz" "apiserver: " 1 ${WAIT_FOR_URL_API_SERVER} ${MAX_TIME_FOR_URL_API_SERVER} \ || { echo "check apiserver logs: ${APISERVER_LOG}" ; exit 1 ; } # Create kubeconfigs for all components, using client certs @@ -684,92 +710,94 @@ function start_kubelet { fi mkdir -p "/var/lib/kubelet" &>/dev/null || sudo mkdir -p "/var/lib/kubelet" - if [[ -z "${DOCKERIZE_KUBELET}" ]]; then - # Enable dns - if [[ "${ENABLE_CLUSTER_DNS}" = true ]]; then - dns_args="--cluster-dns=${DNS_SERVER_IP} --cluster-domain=${DNS_DOMAIN}" - else - # To start a private DNS server set ENABLE_CLUSTER_DNS and - # DNS_SERVER_IP/DOMAIN. This will at least provide a working - # DNS server for real world hostnames. - dns_args="--cluster-dns=8.8.8.8" - fi + # Enable dns + if [[ "${ENABLE_CLUSTER_DNS}" = true ]]; then + dns_args="--cluster-dns=${DNS_SERVER_IP} --cluster-domain=${DNS_DOMAIN}" + else + # To start a private DNS server set ENABLE_CLUSTER_DNS and + # DNS_SERVER_IP/DOMAIN. This will at least provide a working + # DNS server for real world hostnames. + dns_args="--cluster-dns=8.8.8.8" + fi + net_plugin_args="" + if [[ -n "${NET_PLUGIN}" ]]; then + net_plugin_args="--network-plugin=${NET_PLUGIN}" + fi - net_plugin_args="" - if [[ -n "${NET_PLUGIN}" ]]; then - net_plugin_args="--network-plugin=${NET_PLUGIN}" - fi + auth_args="" + if [[ -n "${KUBELET_AUTHORIZATION_WEBHOOK:-}" ]]; then + auth_args="${auth_args} --authorization-mode=Webhook" + fi + if [[ -n "${KUBELET_AUTHENTICATION_WEBHOOK:-}" ]]; then + auth_args="${auth_args} --authentication-token-webhook" + fi + if [[ -n "${CLIENT_CA_FILE:-}" ]]; then + auth_args="${auth_args} --client-ca-file=${CLIENT_CA_FILE}" + fi - auth_args="" - if [[ -n "${KUBELET_AUTHORIZATION_WEBHOOK:-}" ]]; then - auth_args="${auth_args} --authorization-mode=Webhook" - fi - if [[ -n "${KUBELET_AUTHENTICATION_WEBHOOK:-}" ]]; then - auth_args="${auth_args} --authentication-token-webhook" - fi - if [[ -n "${CLIENT_CA_FILE:-}" ]]; then - auth_args="${auth_args} --client-ca-file=${CLIENT_CA_FILE}" - fi + cni_conf_dir_args="" + if [[ -n "${CNI_CONF_DIR}" ]]; then + cni_conf_dir_args="--cni-conf-dir=${CNI_CONF_DIR}" + fi - cni_conf_dir_args="" - if [[ -n "${CNI_CONF_DIR}" ]]; then - cni_conf_dir_args="--cni-conf-dir=${CNI_CONF_DIR}" - fi + cni_bin_dir_args="" + if [[ -n "${CNI_BIN_DIR}" ]]; then + cni_bin_dir_args="--cni-bin-dir=${CNI_BIN_DIR}" + fi - cni_bin_dir_args="" - if [[ -n "${CNI_BIN_DIR}" ]]; then - cni_bin_dir_args="--cni-bin-dir=${CNI_BIN_DIR}" - fi + container_runtime_endpoint_args="" + if [[ -n "${CONTAINER_RUNTIME_ENDPOINT}" ]]; then + container_runtime_endpoint_args="--container-runtime-endpoint=${CONTAINER_RUNTIME_ENDPOINT}" + fi - container_runtime_endpoint_args="" - if [[ -n "${CONTAINER_RUNTIME_ENDPOINT}" ]]; then - container_runtime_endpoint_args="--container-runtime-endpoint=${CONTAINER_RUNTIME_ENDPOINT}" - fi + image_service_endpoint_args="" + if [[ -n "${IMAGE_SERVICE_ENDPOINT}" ]]; then + image_service_endpoint_args="--image-service-endpoint=${IMAGE_SERVICE_ENDPOINT}" + fi - image_service_endpoint_args="" - if [[ -n "${IMAGE_SERVICE_ENDPOINT}" ]]; then - image_service_endpoint_args="--image-service-endpoint=${IMAGE_SERVICE_ENDPOINT}" - fi + all_kubelet_flags=( + ${priv_arg} + --v="${LOG_LEVEL}" + --vmodule="${LOG_SPEC}" + --chaos-chance="${CHAOS_CHANCE}" + --container-runtime="${CONTAINER_RUNTIME}" + --hostname-override="${HOSTNAME_OVERRIDE}" + ${cloud_config_arg} + --address="${KUBELET_HOST}" + --kubeconfig "$CERT_DIR"/kubelet.kubeconfig + --feature-gates="${FEATURE_GATES}" + --cpu-cfs-quota="${CPU_CFS_QUOTA}" + --enable-controller-attach-detach="${ENABLE_CONTROLLER_ATTACH_DETACH}" + --cgroups-per-qos="${CGROUPS_PER_QOS}" + --cgroup-driver="${CGROUP_DRIVER}" + --keep-terminated-pod-volumes="${KEEP_TERMINATED_POD_VOLUMES}" + --eviction-hard="${EVICTION_HARD}" + --eviction-soft="${EVICTION_SOFT}" + --eviction-pressure-transition-period="${EVICTION_PRESSURE_TRANSITION_PERIOD}" + --pod-manifest-path="${POD_MANIFEST_PATH}" + --fail-swap-on="${FAIL_SWAP_ON}" + ${auth_args} + ${dns_args} + ${cni_conf_dir_args} + ${cni_bin_dir_args} + ${net_plugin_args} + ${container_runtime_endpoint_args} + ${image_service_endpoint_args} + --port="$KUBELET_PORT" + ${KUBELET_FLAGS} + ) - sudo -E "${GO_OUT}/hyperkube" kubelet ${priv_arg}\ - --v=${LOG_LEVEL} \ - --vmodule="${LOG_SPEC}" \ - --chaos-chance="${CHAOS_CHANCE}" \ - --container-runtime="${CONTAINER_RUNTIME}" \ - --rkt-path="${RKT_PATH}" \ - --rkt-stage1-image="${RKT_STAGE1_IMAGE}" \ - --hostname-override="${HOSTNAME_OVERRIDE}" \ - ${cloud_config_arg} \ - --address="${KUBELET_HOST}" \ - --kubeconfig "$CERT_DIR"/kubelet.kubeconfig \ - --feature-gates="${FEATURE_GATES}" \ - --cpu-cfs-quota=${CPU_CFS_QUOTA} \ - --enable-controller-attach-detach="${ENABLE_CONTROLLER_ATTACH_DETACH}" \ - --cgroups-per-qos=${CGROUPS_PER_QOS} \ - --cgroup-driver=${CGROUP_DRIVER} \ - --keep-terminated-pod-volumes=${KEEP_TERMINATED_POD_VOLUMES} \ - --eviction-hard=${EVICTION_HARD} \ - --eviction-soft=${EVICTION_SOFT} \ - --eviction-pressure-transition-period=${EVICTION_PRESSURE_TRANSITION_PERIOD} \ - --pod-manifest-path="${POD_MANIFEST_PATH}" \ - --fail-swap-on="${FAIL_SWAP_ON}" \ - ${auth_args} \ - ${dns_args} \ - ${cni_conf_dir_args} \ - ${cni_bin_dir_args} \ - ${net_plugin_args} \ - ${container_runtime_endpoint_args} \ - ${image_service_endpoint_args} \ - --port="$KUBELET_PORT" \ - ${KUBELET_FLAGS} >"${KUBELET_LOG}" 2>&1 & + if [[ -z "${DOCKERIZE_KUBELET}" ]]; then + sudo -E "${GO_OUT}/hyperkube" kubelet "${all_kubelet_flags[@]}" >"${KUBELET_LOG}" 2>&1 & KUBELET_PID=$! - # Quick check that kubelet is running. - if ps -p $KUBELET_PID > /dev/null ; then - echo "kubelet ( $KUBELET_PID ) is running." - else - cat ${KUBELET_LOG} ; exit 1 - fi else + + # Build the hyperkube container image if necessary + if [[ -z "$KUBELET_IMAGE" && -n "$DOCKERIZE_KUBELET" ]]; then + HYPERKUBE_BIN="${GO_OUT}/hyperkube" REGISTRY="k8s.gcr.io" VERSION="latest" make -C "${KUBE_ROOT}/cluster/images/hyperkube" build + KUBELET_IMAGE="k8s.gcr.io/hyperkube-amd64:latest" + fi + # Docker won't run a container with a cidfile (container id file) # unless that file does not already exist; clean up an existing # dockerized kubelet that might be running. @@ -789,22 +817,51 @@ function start_kubelet { if [[ -n "${cloud_cred}" ]]; then cred_bind="--volume=${cloud_cred}:${cloud_cred}:ro" fi + all_kubelet_flags+=(--containerized) - docker run \ - --volume=/:/rootfs:ro \ + all_kubelet_volumes=( + --volume=/:/rootfs:ro,rslave \ --volume=/var/run:/var/run:rw \ --volume=/sys:/sys:ro \ - --volume=/var/lib/docker/:/var/lib/docker:ro \ - --volume=/var/lib/kubelet/:/var/lib/kubelet:rw \ + --volume=/var/lib/docker/:/var/lib/docker:rslave \ + --volume=/var/lib/kubelet/:/var/lib/kubelet:rslave \ --volume=/dev:/dev \ --volume=/run/xtables.lock:/run/xtables.lock:rw \ + ) + + if [[ -n "${DOCKER_ROOT}" ]]; then + all_kubelet_flags+=(--root-dir="${DOCKER_ROOT}") + all_kubelet_volumes+=(--volume="${DOCKER_ROOT}:${DOCKER_ROOT}:rslave") + fi + + docker run --rm --name kubelet \ + "${all_kubelet_volumes[@]}" \ ${cred_bind} \ --net=host \ + --pid=host \ --privileged=true \ -i \ --cidfile=$KUBELET_CIDFILE \ - k8s.gcr.io/kubelet \ - /kubelet --v=${LOG_LEVEL} --containerized ${priv_arg}--chaos-chance="${CHAOS_CHANCE}" --pod-manifest-path="${POD_MANIFEST_PATH}" --hostname-override="${HOSTNAME_OVERRIDE}" ${cloud_config_arg} \ --address="127.0.0.1" --kubeconfig "$CERT_DIR"/kubelet.kubeconfig --port="$KUBELET_PORT" --enable-controller-attach-detach="${ENABLE_CONTROLLER_ATTACH_DETACH}" &> $KUBELET_LOG & + "${KUBELET_IMAGE}" \ + /kubelet "${all_kubelet_flags[@]}" >"${KUBELET_LOG}" 2>&1 & + # Get PID of kubelet container. + for i in {1..3}; do + echo -n "Trying to get PID of kubelet container..." + KUBELET_PID=$(docker inspect kubelet -f '{{.State.Pid}}' 2>/dev/null || true) + if [[ -n ${KUBELET_PID} && ${KUBELET_PID} -gt 0 ]]; then + echo " ok, $KUBELET_PID." + break + else + echo " failed, retry in 1 second." + sleep 1 + fi + done + fi + # Quick check that kubelet is running. + if [ -n "$KUBELET_PID" ] && ps -p $KUBELET_PID > /dev/null; then + echo "kubelet ( $KUBELET_PID ) is running." + else + cat ${KUBELET_LOG} ; exit 1 fi } @@ -819,10 +876,18 @@ clientConnection: hostnameOverride: ${HOSTNAME_OVERRIDE} mode: ${KUBE_PROXY_MODE} EOF + if [[ -n ${FEATURE_GATES} ]]; then + echo "featureGates:" + # Convert from foo=true,bar=false to + # foo: true + # bar: false + for gate in $(echo ${FEATURE_GATES} | tr ',' ' '); do + echo $gate | sed -e 's/\(.*\)=\(.*\)/ \1: \2/' + done + fi >>/tmp/kube-proxy.yaml sudo "${GO_OUT}/hyperkube" proxy \ --v=${LOG_LEVEL} \ - --feature-gates="${FEATURE_GATES}" \ --config=/tmp/kube-proxy.yaml \ --master="https://${API_HOST}:${API_SECURE_PORT}" >"${PROXY_LOG}" 2>&1 & PROXY_PID=$! @@ -838,7 +903,7 @@ EOF function start_kubedns { if [[ "${ENABLE_CLUSTER_DNS}" = true ]]; then - cp "${KUBE_ROOT}/cluster/addons/dns/kube-dns.yaml.in" kube-dns.yaml + cp "${KUBE_ROOT}/cluster/addons/dns/kube-dns/kube-dns.yaml.in" kube-dns.yaml sed -i -e "s/{{ pillar\['dns_domain'\] }}/${DNS_DOMAIN}/g" kube-dns.yaml sed -i -e "s/{{ pillar\['dns_server'\] }}/${DNS_SERVER_IP}/g" kube-dns.yaml @@ -953,7 +1018,15 @@ if [[ "${KUBETEST_IN_DOCKER:-}" == "true" ]]; then ${KUBE_ROOT}/hack/install-etcd.sh export PATH="${KUBE_ROOT}/third_party/etcd:${PATH}" KUBE_FASTBUILD=true make ginkgo cross + apt install -y sudo + apt-get remove -y systemd + + # configure shared mounts to prevent failure in DIND scenarios + mount --make-rshared / + + # kubekins has a special directory for docker root + DOCKER_ROOT="/docker-graph" fi # validate that etcd is: not running, in path, and has minimum required version. @@ -965,10 +1038,6 @@ if [ "${CONTAINER_RUNTIME}" == "docker" ] && ! kube::util::ensure_docker_daemon_ exit 1 fi -if [[ "${CONTAINER_RUNTIME}" == "rkt" ]]; then - test_rkt -fi - if [[ "${START_MODE}" != "kubeletonly" ]]; then test_apiserver_off fi @@ -1029,7 +1098,7 @@ fi print_success if [[ "${ENABLE_DAEMON}" = false ]]; then - while true; do sleep 1; done + while true; do sleep 1; healthcheck; done fi if [[ "${KUBETEST_IN_DOCKER:-}" == "true" ]]; then @@ -1037,4 +1106,4 @@ if [[ "${KUBETEST_IN_DOCKER:-}" == "true" ]]; then cluster/kubectl.sh config set-credentials myself --client-key=/var/run/kubernetes/client-admin.key --client-certificate=/var/run/kubernetes/client-admin.crt cluster/kubectl.sh config set-context local --cluster=local --user=myself cluster/kubectl.sh config use-context local -fi \ No newline at end of file +fi diff --git a/vendor/k8s.io/kubernetes/hack/lookup_pull.py b/vendor/k8s.io/kubernetes/hack/lookup_pull.py deleted file mode 100755 index e290981d5..000000000 --- a/vendor/k8s.io/kubernetes/hack/lookup_pull.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python - -# 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. - -# Script to print out PR info in release note format. - -import json -import sys -import urllib2 - -PULLQUERY=("https://api.github.com/repos/" - "kubernetes/kubernetes/pulls/{pull}") -LOGIN="login" -TITLE="title" -USER="user" - -def print_pulls(pulls): - for pull in pulls: - d = json.loads(urllib2.urlopen(PULLQUERY.format(pull=pull)).read()) - print "* {title} #{pull} ({author})".format( - title=d[TITLE], pull=pull, author=d[USER][LOGIN]) - -if __name__ == "__main__": - if len(sys.argv) < 2: - print ("Usage: {cmd} ...: Prints out short " + - "markdown description for PRs appropriate for release notes.") - sys.exit(1) - print_pulls(sys.argv[1:]) diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/build.sh b/vendor/k8s.io/kubernetes/hack/make-rules/build.sh index 472151af1..b2496eee1 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/build.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/clean.sh b/vendor/k8s.io/kubernetes/hack/make-rules/clean.sh index ccf0dfc0d..2dc229ebe 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/clean.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/clean.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/cross.sh b/vendor/k8s.io/kubernetes/hack/make-rules/cross.sh index e2c2f9f44..8e1e93854 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/cross.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/cross.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/helpers/cache_go_dirs.sh b/vendor/k8s.io/kubernetes/hack/make-rules/helpers/cache_go_dirs.sh index 82402c667..390f8a21b 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/helpers/cache_go_dirs.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/helpers/cache_go_dirs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -47,8 +47,7 @@ function kfind() { -path ./staging -o \ -path ./_\* -o \ -path ./.\* -o \ - -path ./docs -o \ - -path ./examples \ + -path ./docs \ \) -prune \ \) \ \) \ diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/make-help.sh b/vendor/k8s.io/kubernetes/hack/make-rules/make-help.sh index e34c41708..7228a4bd4 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/make-help.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/make-help.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd-util.sh b/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd-util.sh index 4ecc5a6e6..c5879f4e8 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd-util.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd-util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -77,6 +77,7 @@ selfsubjectaccessreviews="selfsubjectaccessreviews" customresourcedefinitions="customresourcedefinitions" daemonsets="daemonsets" controllerrevisions="controllerrevisions" +job="jobs" # include shell2junit library @@ -226,7 +227,7 @@ function wait-for-pods-with-label() { local i for i in $(seq 1 10); do - kubeout=`kubectl get po -l $1 --template '{{range.items}}{{.metadata.name}}{{end}}' --sort-by metadata.name "${kube_flags[@]}"` + kubeout=`kubectl get po -l $1 --output=go-template --template='{{range.items}}{{.metadata.name}}{{end}}' --sort-by metadata.name "${kube_flags[@]}"` if [[ $kubeout = $2 ]]; then return fi @@ -360,7 +361,7 @@ run_pod_tests() { kube::test::get_object_assert 'pods/valid-pod' "{{.metadata.namespace}} {{.metadata.name}}" ' valid-pod' "--export=true" ### Dump current valid-pod POD - output_pod=$(kubectl get pod valid-pod -o yaml --output-version=v1 "${kube_flags[@]}") + output_pod=$(kubectl get pod valid-pod -o yaml "${kube_flags[@]}") ### Delete POD valid-pod by id # Pre-condition: valid-pod POD exists @@ -532,7 +533,7 @@ run_pod_tests() { kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" '' # Command kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}" - kubectl create -f examples/storage/redis/redis-master.yaml "${kube_flags[@]}" + kubectl create -f test/e2e/testing-manifests/kubectl/redis-master-pod.yaml "${kube_flags[@]}" # Post-condition: valid-pod and redis-master PODs are created kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'redis-master:valid-pod:' @@ -591,9 +592,10 @@ run_pod_tests() { # Post-condition: valid-pod's record annotation still contains command with --record=true kube::test::get_object_assert 'pod valid-pod' "{{range$annotations_field}}{{.}}:{{end}}" ".*--record=true.*" - ### Record label change with unspecified flag and previous change already recorded + ### Record label change with specified flag and previous change already recorded + ### we are no longer tricked by data from another user into revealing more information about our client # Command - kubectl label pods valid-pod new-record-change=true "${kube_flags[@]}" + kubectl label pods valid-pod new-record-change=true --record=true "${kube_flags[@]}" # Post-condition: valid-pod's record annotation contains new change kube::test::get_object_assert 'pod valid-pod' "{{range$annotations_field}}{{.}}:{{end}}" ".*new-record-change=true.*" @@ -655,7 +657,7 @@ run_pod_tests() { kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" '' ## kubectl create --edit can update the label filed of multiple resources. tmp-editor.sh is a fake editor TEMP=$(mktemp /tmp/tmp-editor-XXXXXXXX.sh) - echo -e "#!/bin/bash\n${SED} -i \"s/mock/modified/g\" \$1" > ${TEMP} + echo -e "#!/usr/bin/env bash\n${SED} -i \"s/mock/modified/g\" \$1" > ${TEMP} chmod +x ${TEMP} # Command EDITOR=${TEMP} kubectl create --edit -f hack/testdata/multi-resource-json.json "${kube_flags[@]}" @@ -691,7 +693,7 @@ run_pod_tests() { kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:' ## Patch can modify a local object - kubectl patch --local -f pkg/kubectl/validation/testdata/v1/validPod.yaml --patch='{"spec": {"restartPolicy":"Never"}}' -o jsonpath='{.spec.restartPolicy}' | grep -q "Never" + kubectl patch --local -f pkg/kubectl/validation/testdata/v1/validPod.yaml --patch='{"spec": {"restartPolicy":"Never"}}' -o yaml | grep -q "Never" ## Patch fails with error message "not patched" and exit code 1 output_message=$(! kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"replicas":7}}' 2>&1) @@ -719,9 +721,9 @@ run_pod_tests() { kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'changed-with-yaml:' ## Patch pod from JSON can change image # Command - kubectl patch "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "k8s.gcr.io/pause-amd64:3.1"}]}}' + kubectl patch "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "k8s.gcr.io/pause:3.1"}]}}' # Post-condition: valid-pod POD has expected image - kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'k8s.gcr.io/pause-amd64:3.1:' + kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'k8s.gcr.io/pause:3.1:' ## If resourceVersion is specified in the patch, it will be treated as a precondition, i.e., if the resourceVersion is different from that is stored in the server, the Patch should be rejected ERROR_FILE="${KUBE_TEMP}/conflict-error" @@ -802,7 +804,7 @@ __EOF__ kubectl delete node node-v1-test "${kube_flags[@]}" ## kubectl edit can update the image field of a POD. tmp-editor.sh is a fake editor - echo -e "#!/bin/bash\n${SED} -i \"s/nginx/k8s.gcr.io\/serve_hostname/g\" \$1" > /tmp/tmp-editor.sh + echo -e "#!/usr/bin/env bash\n${SED} -i \"s/nginx/k8s.gcr.io\/serve_hostname/g\" \$1" > /tmp/tmp-editor.sh chmod +x /tmp/tmp-editor.sh # Pre-condition: valid-pod POD has image nginx kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:' @@ -1183,6 +1185,39 @@ run_kubectl_apply_deployments_tests() { set +o errexit } +# Runs tests for kubectl alpha diff +run_kubectl_diff_tests() { + set -o nounset + set -o errexit + + create_and_use_new_namespace + kube::log::status "Testing kubectl alpha diff" + + kubectl apply -f hack/testdata/pod.yaml + + # Ensure that selfLink has been added, and shown in the diff + output_message=$(kubectl alpha diff -f hack/testdata/pod.yaml) + kube::test::if_has_string "${output_message}" 'selfLink' + output_message=$(kubectl alpha diff LOCAL LIVE -f hack/testdata/pod.yaml) + kube::test::if_has_string "${output_message}" 'selfLink' + output_message=$(kubectl alpha diff LOCAL MERGED -f hack/testdata/pod.yaml) + kube::test::if_has_string "${output_message}" 'selfLink' + + output_message=$(kubectl alpha diff MERGED MERGED -f hack/testdata/pod.yaml) + kube::test::if_empty_string "${output_message}" + output_message=$(kubectl alpha diff LIVE LIVE -f hack/testdata/pod.yaml) + kube::test::if_empty_string "${output_message}" + output_message=$(kubectl alpha diff LAST LAST -f hack/testdata/pod.yaml) + kube::test::if_empty_string "${output_message}" + output_message=$(kubectl alpha diff LOCAL LOCAL -f hack/testdata/pod.yaml) + kube::test::if_empty_string "${output_message}" + + kubectl delete -f hack/testdata/pod.yaml + + set +o nounset + set +o errexit +} + # Runs tests for --save-config tests. run_save_config_tests() { set -o nounset @@ -1208,7 +1243,7 @@ run_save_config_tests() { ! [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]] # Command: edit the pod "test-pod" temp_editor="${KUBE_TEMP}/tmp-editor.sh" - echo -e "#!/bin/bash\n${SED} -i \"s/test-pod-label/test-pod-label-edited/g\" \$@" > "${temp_editor}" + echo -e "#!/usr/bin/env bash\n${SED} -i \"s/test-pod-label/test-pod-label-edited/g\" \$@" > "${temp_editor}" chmod +x "${temp_editor}" EDITOR=${temp_editor} kubectl edit pod test-pod --save-config "${kube_flags[@]}" # Post-Condition: pod "test-pod" has configuration annotation @@ -1295,9 +1330,9 @@ run_kubectl_run_tests() { kubectl run nginx-extensions "--image=$IMAGE_NGINX" "${kube_flags[@]}" # Post-Condition: Deployment "nginx" is created kube::test::get_object_assert deployment.extensions "{{range.items}}{{$id_field}}:{{end}}" 'nginx-extensions:' - # and old generator was used, iow. old defaults are applied + # new generator was used output_message=$(kubectl get deployment.extensions/nginx-extensions -o jsonpath='{.spec.revisionHistoryLimit}') - kube::test::if_has_not_string "${output_message}" '2' + kube::test::if_has_string "${output_message}" '2' # Clean up kubectl delete deployment nginx-extensions "${kube_flags[@]}" # Command @@ -1316,6 +1351,18 @@ run_kubectl_run_tests() { kubectl run pi --schedule="*/5 * * * *" --generator=cronjob/v1beta1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}" # Post-Condition: CronJob "pi" is created kube::test::get_object_assert cronjobs "{{range.items}}{{$id_field}}:{{end}}" 'pi:' + + # Pre-condition: cronjob has perl image, not custom image + output_message=$(kubectl get cronjob/pi -o jsonpath='{..image}') + kube::test::if_has_not_string "${output_message}" "custom-image" + kube::test::if_has_string "${output_message}" "${IMAGE_PERL}" + # Set cronjob image + kubectl set image cronjob/pi '*=custom-image' + # Post-condition: cronjob has custom image, not perl image + output_message=$(kubectl get cronjob/pi -o jsonpath='{..image}') + kube::test::if_has_string "${output_message}" "custom-image" + kube::test::if_has_not_string "${output_message}" "${IMAGE_PERL}" + # Clean up kubectl delete cronjobs pi "${kube_flags[@]}" @@ -1323,15 +1370,15 @@ run_kubectl_run_tests() { set +o errexit } -run_kubectl_server_print_tests() { +run_kubectl_old_print_tests() { set -o nounset set -o errexit create_and_use_new_namespace - kube::log::status "Testing kubectl get --experimental-server-print" + kube::log::status "Testing kubectl get --server-print=false" ### Test retrieval of all types in discovery # Pre-condition: no resources exist - output_message=$(kubectl get pods --experimental-server-print 2>&1 "${kube_flags[@]}") + output_message=$(kubectl get pods --server-print=false 2>&1 "${kube_flags[@]}") # Post-condition: Expect text indicating no resources were found kube::test::if_has_string "${output_message}" 'No resources found.' @@ -1342,9 +1389,15 @@ run_kubectl_server_print_tests() { # Compare "old" output with experimental output and ensure both are the same # remove the last column, as it contains the object's AGE, which could cause a mismatch. expected_output=$(kubectl get pod "${kube_flags[@]}" | awk 'NF{NF--};1') - actual_output=$(kubectl get pod --experimental-server-print "${kube_flags[@]}" | awk 'NF{NF--};1') + actual_output=$(kubectl get pod --server-print=false "${kube_flags[@]}" | awk 'NF{NF--};1') kube::test::if_has_string "${actual_output}" "${expected_output}" + # Test printing objects with --use-openapi-print-columns + actual_output=$(kubectl get namespaces --use-openapi-print-columns --v=7 "${kube_flags[@]}" 2>&1) + # it should request full objects (not server-side printing) + kube::test::if_has_not_string "${actual_output}" 'application/json;as=Table' + kube::test::if_has_string "${actual_output}" 'application/json' + ### Test retrieval of daemonsets against server-side printing kubectl apply -f hack/testdata/rollingupdate-daemonset.yaml "${kube_flags[@]}" # Post-condition: daemonset is created @@ -1352,7 +1405,7 @@ run_kubectl_server_print_tests() { # Compare "old" output with experimental output and ensure both are the same # remove the last column, as it contains the object's AGE, which could cause a mismatch. expected_output=$(kubectl get ds "${kube_flags[@]}" | awk 'NF{NF--};1') - actual_output=$(kubectl get ds --experimental-server-print "${kube_flags[@]}" | awk 'NF{NF--};1') + actual_output=$(kubectl get ds --server-print=false "${kube_flags[@]}" | awk 'NF{NF--};1') kube::test::if_has_string "${actual_output}" "${expected_output}" ### Test retrieval of replicationcontrollers against server-side printing @@ -1362,7 +1415,7 @@ run_kubectl_server_print_tests() { # Compare "old" output with experimental output and ensure both are the same # remove the last column, as it contains the object's AGE, which could cause a mismatch. expected_output=$(kubectl get rc "${kube_flags[@]}" | awk 'NF{NF--};1') - actual_output=$(kubectl get rc --experimental-server-print "${kube_flags[@]}" | awk 'NF{NF--};1') + actual_output=$(kubectl get rc --server-print=false "${kube_flags[@]}" | awk 'NF{NF--};1') kube::test::if_has_string "${actual_output}" "${expected_output}" ### Test retrieval of replicasets against server-side printing @@ -1372,7 +1425,7 @@ run_kubectl_server_print_tests() { # Compare "old" output with experimental output and ensure both are the same # remove the last column, as it contains the object's AGE, which could cause a mismatch. expected_output=$(kubectl get rs "${kube_flags[@]}" | awk 'NF{NF--};1') - actual_output=$(kubectl get rs --experimental-server-print "${kube_flags[@]}" | awk 'NF{NF--};1') + actual_output=$(kubectl get rs --server-print=false "${kube_flags[@]}" | awk 'NF{NF--};1') kube::test::if_has_string "${actual_output}" "${expected_output}" ### Test retrieval of jobs against server-side printing @@ -1382,7 +1435,7 @@ run_kubectl_server_print_tests() { # Compare "old" output with experimental output and ensure both are the same # remove the last column, as it contains the object's AGE, which could cause a mismatch. expected_output=$(kubectl get jobs/pi "${kube_flags[@]}" | awk 'NF{NF--};1') - actual_output=$(kubectl get jobs/pi --experimental-server-print "${kube_flags[@]}" | awk 'NF{NF--};1') + actual_output=$(kubectl get jobs/pi --server-print=false "${kube_flags[@]}" | awk 'NF{NF--};1') kube::test::if_has_string "${actual_output}" "${expected_output}" ### Test retrieval of clusterroles against server-side printing @@ -1392,7 +1445,7 @@ run_kubectl_server_print_tests() { # Compare "old" output with experimental output and ensure both are the same # remove the last column, as it contains the object's AGE, which could cause a mismatch. expected_output=$(kubectl get clusterroles/sample-role "${kube_flags[@]}" | awk 'NF{NF--};1') - actual_output=$(kubectl get clusterroles/sample-role --experimental-server-print "${kube_flags[@]}" | awk 'NF{NF--};1') + actual_output=$(kubectl get clusterroles/sample-role --server-print=false "${kube_flags[@]}" | awk 'NF{NF--};1') kube::test::if_has_string "${actual_output}" "${expected_output}" ### Test retrieval of crds against server-side printing @@ -1406,6 +1459,7 @@ run_kubectl_server_print_tests() { "spec": { "group": "company.com", "version": "v1", + "scope": "Namespaced", "names": { "plural": "foos", "kind": "Foo" @@ -1420,8 +1474,8 @@ __EOF__ # Test that we can list this new CustomResource kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" '' # Compare "old" output with experimental output and ensure both are the same - expected_output=$(kubectl get foos "${kube_flags[@]}") - actual_output=$(kubectl get foos --experimental-server-print "${kube_flags[@]}" | awk 'NF{NF--};1') + expected_output=$(kubectl get foos "${kube_flags[@]}" | awk 'NF{NF--};1') + actual_output=$(kubectl get foos --server-print=false "${kube_flags[@]}" | awk 'NF{NF--};1') kube::test::if_has_string "${actual_output}" "${expected_output}" # teardown @@ -1432,6 +1486,9 @@ __EOF__ kubectl delete rc frontend "${kube_flags[@]}" kubectl delete ds bind "${kube_flags[@]}" kubectl delete pod valid-pod "${kube_flags[@]}" + + set +o nounset + set +o errexit } run_kubectl_get_tests() { @@ -1569,6 +1626,10 @@ run_kubectl_get_tests() { ## check --allow-missing-template-keys defaults to true for go templates kubectl get "${kube_flags[@]}" pod valid-pod -o go-template='{{.missing}}' + ## check --template flag causes go-template to be printed, even when no --output value is provided + output_message=$(kubectl get "${kube_flags[@]}" pod valid-pod --template="{{$id_field}}:") + kube::test::if_has_string "${output_message}" 'valid-pod:' + ## check --allow-missing-template-keys=false results in an error for a missing key with jsonpath output_message=$(! kubectl get pod valid-pod --allow-missing-template-keys=false -o jsonpath='{.missing}' "${kube_flags[@]}") kube::test::if_has_string "${output_message}" 'missing is not found' @@ -1649,6 +1710,220 @@ run_kubectl_request_timeout_tests() { set +o errexit } +run_template_output_tests() { + set -o nounset + set -o errexit + + kube::log::status "Testing --template support on commands" + ### Test global request timeout option + # Pre-condition: no POD exists + create_and_use_new_namespace + kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" '' + # Command + # check that create supports --template output + kubectl create "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml + # Post-condition: valid-pod POD is created + kubectl get "${kube_flags[@]}" pods -o json + kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:' + + # check that patch command supports --template output + output_message=$(kubectl "${kube_flags[@]}" patch --dry-run pods/valid-pod -p '{"patched":"value3"}' --type=merge --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'valid-pod:' + + # check that label command supports --template output + output_message=$(kubectl "${kube_flags[@]}" label --dry-run pods/valid-pod label=value --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'valid-pod:' + + # check that annotate command supports --template output + output_message=$(kubectl "${kube_flags[@]}" annotate --dry-run pods/valid-pod annotation=value --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'valid-pod:' + + # check that apply command supports --template output + output_message=$(kubectl "${kube_flags[@]}" apply --dry-run -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'valid-pod:' + + # check that create command supports --template output + output_message=$(kubectl "${kube_flags[@]}" create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml --dry-run --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'valid-pod:' + + # check that autoscale command supports --template output + output_message=$(kubectl "${kube_flags[@]}" autoscale --max=2 -f hack/testdata/scale-deploy-1.yaml --dry-run --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'scale-1:' + + # check that expose command supports --template output + output_message=$(kubectl "${kube_flags[@]}" expose -f hack/testdata/redis-slave-replicaset.yaml --save-config --port=80 --target-port=8000 --dry-run --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'redis-slave:' + + # check that convert command supports --template output + output_message=$(kubectl "${kube_flags[@]}" convert -f hack/testdata/deployment-revision1.yaml --output-version=apps/v1beta1 --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'nginx:' + + # check that run command supports --template output + output_message=$(kubectl "${kube_flags[@]}" run --dry-run --template="{{ .metadata.name }}:" pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)') + kube::test::if_has_string "${output_message}" 'pi:' + + # check that taint command supports --template output + output_message=$(kubectl "${kube_flags[@]}" taint node 127.0.0.1 dedicated=foo:PreferNoSchedule --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" '127.0.0.1:' + # untaint node + kubectl taint node 127.0.0.1 dedicated- + + # check that "apply set-last-applied" command supports --template output + kubectl "${kube_flags[@]}" create -f test/e2e/testing-manifests/statefulset/cassandra/controller.yaml + output_message=$(kubectl "${kube_flags[@]}" apply set-last-applied -f test/e2e/testing-manifests/statefulset/cassandra/controller.yaml --dry-run --create-annotation --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'cassandra:' + + # check that "auth reconcile" command supports --template output + output_message=$(kubectl "${kube_flags[@]}" auth reconcile --dry-run -f test/fixtures/pkg/kubectl/cmd/auth/rbac-resource-plus.yaml --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'testing-CR:testing-CRB:testing-RB:testing-R:' + + # check that "create clusterrole" command supports --template output + output_message=$(kubectl "${kube_flags[@]}" create clusterrole --template="{{ .metadata.name }}:" --verb get myclusterrole --non-resource-url /logs/ --resource pods) + kube::test::if_has_string "${output_message}" 'myclusterrole:' + + # check that "create clusterrolebinding" command supports --template output + output_message=$(kubectl "${kube_flags[@]}" create clusterrolebinding foo --clusterrole=myclusterrole --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'foo:' + + # check that "create configmap" command supports --template output + output_message=$(kubectl "${kube_flags[@]}" create configmap cm --dry-run --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'cm:' + + # check that "create deployment" command supports --template output + output_message=$(kubectl "${kube_flags[@]}" create deployment deploy --dry-run --image=nginx --template="{{ .metadata.name }}:") + kube::test::if_has_string "${output_message}" 'deploy:' + + # check that "create job" command supports --template output + kubectl create "${kube_flags[@]}" -f - < /tmp/tmp-editor.sh + echo -e '#!/usr/bin/env bash\nsed -i "s/image: busybox/image: prom\/busybox/g" $1' > /tmp/tmp-editor.sh chmod +x /tmp/tmp-editor.sh output_message=$(! EDITOR=/tmp/tmp-editor.sh kubectl edit -f hack/testdata/recursive/pod --recursive 2>&1 "${kube_flags[@]}") # Post-condition: busybox0 & busybox1 PODs are not edited, and since busybox2 is malformed, it should error @@ -2137,8 +2451,7 @@ run_recursive_resources_tests() { kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx:' kube::test::get_object_assert deployment "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:" # Command - output_message=$(kubectl convert --local -f hack/testdata/deployment-revision1.yaml --output-version=apps/v1beta1 -o go-template='{{ .apiVersion }}' "${kube_flags[@]}") - echo $output_message + output_message=$(kubectl convert --local -f hack/testdata/deployment-revision1.yaml --output-version=apps/v1beta1 -o yaml "${kube_flags[@]}") # Post-condition: apiVersion is still extensions/v1beta1 in the live deployment, but command output is the new value kube::test::get_object_assert 'deployment nginx' "{{ .apiVersion }}" 'extensions/v1beta1' kube::test::if_has_string "${output_message}" "apps/v1beta1" @@ -2336,7 +2649,11 @@ run_namespace_tests() { # Post-condition: namespace 'my-namespace' is created. kube::test::get_object_assert 'namespaces/my-namespace' "{{$id_field}}" 'my-namespace' # Clean up - kubectl delete namespace my-namespace + kubectl delete namespace my-namespace --wait=false + # make sure that wait properly waits for finalization + kubectl wait --for=delete ns/my-namespace + output_message=$(! kubectl get ns/my-namespace 2>&1 "${kube_flags[@]}") + kube::test::if_has_string "${output_message}" ' not found' ###################### # Pods in Namespaces # @@ -2386,11 +2703,12 @@ run_secrets_test() { create_and_use_new_namespace kube::log::status "Testing secrets" - # Ensure dry run succeeds and includes kind, apiVersion and data - output_message=$(kubectl create secret generic test --from-literal=key1=value1 --dry-run -o yaml) + # Ensure dry run succeeds and includes kind, apiVersion and data, and doesn't require a server connection + output_message=$(kubectl create secret generic test --from-literal=key1=value1 --dry-run -o yaml --server=example.com --v=6) kube::test::if_has_string "${output_message}" 'kind: Secret' kube::test::if_has_string "${output_message}" 'apiVersion: v1' kube::test::if_has_string "${output_message}" 'key1: dmFsdWUx' + kube::test::if_has_not_string "${output_message}" 'example.com' ### Create a new namespace # Pre-condition: the test-secrets namespace does not exist @@ -2531,7 +2849,7 @@ run_service_tests() { # Pre-condition: Only the default kubernetes services exist kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:' # Command - kubectl create -f examples/guestbook/redis-master-service.yaml "${kube_flags[@]}" + kubectl create -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml "${kube_flags[@]}" # Post-condition: redis-master service exists kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:' # Describe command should print detailed information @@ -2556,14 +2874,14 @@ run_service_tests() { kube::test::get_object_assert 'services redis-master' "{{range$service_selector_field}}{{.}}:{{end}}" "redis:master:backend:" # Set selector of a local file without talking to the server - kubectl set selector -f examples/guestbook/redis-master-service.yaml role=padawan --local -o yaml "${kube_flags[@]}" - ! kubectl set selector -f examples/guestbook/redis-master-service.yaml role=padawan --dry-run -o yaml "${kube_flags[@]}" + kubectl set selector -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml role=padawan --local -o yaml "${kube_flags[@]}" + ! kubectl set selector -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml role=padawan --dry-run -o yaml "${kube_flags[@]}" # Set command to change the selector. - kubectl set selector -f examples/guestbook/redis-master-service.yaml role=padawan + kubectl set selector -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml role=padawan # prove role=padawan kube::test::get_object_assert 'services redis-master' "{{range$service_selector_field}}{{.}}:{{end}}" "padawan:" # Set command to reset the selector back to the original one. - kubectl set selector -f examples/guestbook/redis-master-service.yaml app=redis,role=master,tier=backend + kubectl set selector -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml app=redis,role=master,tier=backend # prove role=master kube::test::get_object_assert 'services redis-master' "{{range$service_selector_field}}{{.}}:{{end}}" "redis:master:backend:" # Show dry-run works on running selector @@ -2572,7 +2890,7 @@ run_service_tests() { kube::test::get_object_assert 'services redis-master' "{{range$service_selector_field}}{{.}}:{{end}}" "redis:master:backend:" ### Dump current redis-master service - output_service=$(kubectl get service redis-master -o json --output-version=v1 "${kube_flags[@]}") + output_service=$(kubectl get service redis-master -o json "${kube_flags[@]}") ### Delete redis-master-service by id # Pre-condition: redis-master service exists @@ -2637,8 +2955,8 @@ __EOF__ # Pre-condition: Only the default kubernetes services exist kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:' # Command - kubectl create -f examples/guestbook/redis-master-service.yaml "${kube_flags[@]}" - kubectl create -f examples/guestbook/redis-slave-service.yaml "${kube_flags[@]}" + kubectl create -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml "${kube_flags[@]}" + kubectl create -f test/e2e/testing-manifests/guestbook/redis-slave-service.yaml "${kube_flags[@]}" # Post-condition: redis-master and redis-slave services are created kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:redis-slave:' @@ -2757,8 +3075,8 @@ run_rc_tests() { kubectl delete rc frontend "${kube_flags[@]}" ### Scale multiple replication controllers - kubectl create -f examples/guestbook/legacy/redis-master-controller.yaml "${kube_flags[@]}" - kubectl create -f examples/guestbook/legacy/redis-slave-controller.yaml "${kube_flags[@]}" + kubectl create -f test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml "${kube_flags[@]}" + kubectl create -f test/e2e/testing-manifests/guestbook/legacy/redis-slave-controller.yaml "${kube_flags[@]}" # Command kubectl scale rc/redis-master rc/redis-slave --replicas=4 "${kube_flags[@]}" # Post-condition: 4 replicas each @@ -2840,7 +3158,7 @@ run_rc_tests() { # Pre-condition: default run without --name flag; should succeed by truncating the inherited name output_message=$(kubectl expose -f hack/testdata/pod-with-large-name.yaml --port=8081 2>&1 "${kube_flags[@]}") # Post-condition: inherited name from pod has been truncated - kube::test::if_has_string "${output_message}" '\"kubernetes-serve-hostname-testing-sixty-three-characters-in-len\" exposed' + kube::test::if_has_string "${output_message}" 'kubernetes-serve-hostname-testing-sixty-three-characters-in-len exposed' # Clean-up kubectl delete svc kubernetes-serve-hostname-testing-sixty-three-characters-in-len "${kube_flags[@]}" @@ -2848,7 +3166,7 @@ run_rc_tests() { # Pre-condition: don't use --port flag output_message=$(kubectl expose -f test/fixtures/doc-yaml/admin/high-availability/etcd.yaml --selector=test=etcd 2>&1 "${kube_flags[@]}") # Post-condition: expose succeeded - kube::test::if_has_string "${output_message}" '\"etcd-server\" exposed' + kube::test::if_has_string "${output_message}" 'etcd-server exposed' # Post-condition: generated service has both ports from the exposed pod kube::test::get_object_assert 'service etcd-server' "{{$port_name}} {{$port_field}}" 'port-1 2380' kube::test::get_object_assert 'service etcd-server' "{{$second_port_name}} {{$second_port_field}}" 'port-2 2379' @@ -2868,7 +3186,7 @@ run_rc_tests() { kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" '' # Command kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}" - kubectl create -f examples/guestbook/legacy/redis-slave-controller.yaml "${kube_flags[@]}" + kubectl create -f test/e2e/testing-manifests/guestbook/legacy/redis-slave-controller.yaml "${kube_flags[@]}" # Post-condition: frontend and redis-slave kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:redis-slave:' @@ -3127,12 +3445,22 @@ run_deployment_tests() { kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx-deployment:' kube::test::get_object_assert configmap "{{range.items}}{{$id_field}}:{{end}}" 'test-set-env-config:' kube::test::get_object_assert secret "{{range.items}}{{$id_field}}:{{end}}" 'test-set-env-secret:' + # Set env of deployments by configmap from keys + kubectl set env deployment nginx-deployment --keys=key-2 --from=configmap/test-set-env-config "${kube_flags[@]}" + # Assert correct value in deployment env + kube::test::get_object_assert 'deploy nginx-deployment' "{{ (index (index .spec.template.spec.containers 0).env 0).name}}" 'KEY_2' + # Assert single value in deployment env + kube::test::get_object_assert 'deploy nginx-deployment' "{{ len (index .spec.template.spec.containers 0).env }}" '1' + # Set env of deployments by configmap + kubectl set env deployment nginx-deployment --from=configmap/test-set-env-config "${kube_flags[@]}" + # Assert all values in deployment env + kube::test::get_object_assert 'deploy nginx-deployment' "{{ len (index .spec.template.spec.containers 0).env }}" '2' # Set env of deployments for all container kubectl set env deployment nginx-deployment env=prod "${kube_flags[@]}" # Set env of deployments for specific container - kubectl set env deployment nginx-deployment env=prod -c=nginx "${kube_flags[@]}" - # Set env of deployments by configmap - kubectl set env deployment nginx-deployment --from=configmap/test-set-env-config "${kube_flags[@]}" + kubectl set env deployment nginx-deployment superenv=superprod -c=nginx "${kube_flags[@]}" + # Set env of deployments by secret from keys + kubectl set env deployment nginx-deployment --keys=username --from=secret/test-set-env-secret "${kube_flags[@]}" # Set env of deployments by secret kubectl set env deployment nginx-deployment --from=secret/test-set-env-secret "${kube_flags[@]}" # Remove specific env of deployment @@ -3142,18 +3470,6 @@ run_deployment_tests() { kubectl delete configmap test-set-env-config "${kube_flags[@]}" kubectl delete secret test-set-env-secret "${kube_flags[@]}" - ### Delete a deployment with initializer - # Pre-condition: no deployment exists - kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" '' - # Create a deployment - kubectl create --request-timeout=1 -f hack/testdata/deployment-with-initializer.yaml 2>&1 "${kube_flags[@]}" || true - kube::test::get_object_assert 'deployment web' "{{$id_field}}" 'web' - # Delete a deployment - kubectl delete deployment web "${kube_flags[@]}" - # Check Deployment web doesn't exist - output_message=$(! kubectl get deployment web 2>&1 "${kube_flags[@]}") - kube::test::if_has_string "${output_message}" '"web" not found' - set +o nounset set +o errexit } @@ -3173,13 +3489,15 @@ run_rs_tests() { kube::log::status "Deleting rs" kubectl delete rs frontend "${kube_flags[@]}" # Post-condition: no pods from frontend replica set - kube::test::get_object_assert 'pods -l "tier=frontend"' "{{range.items}}{{$id_field}}:{{end}}" '' + kube::test::wait_object_assert 'pods -l "tier=frontend"' "{{range.items}}{{$id_field}}:{{end}}" '' ### Create and then delete a replica set with cascade=false, make sure it doesn't delete pods. # Pre-condition: no replica set exists kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" '' # Command kubectl create -f hack/testdata/frontend-replicaset.yaml "${kube_flags[@]}" + # wait for all 3 pods to be set up + kube::test::wait_object_assert 'pods -l "tier=frontend"' "{{range.items}}{{$pod_container_name_field}}:{{end}}" 'php-redis:php-redis:php-redis:' kube::log::status "Deleting rs" kubectl delete rs frontend "${kube_flags[@]}" --cascade=false # Wait for the rs to be deleted. @@ -3295,18 +3613,6 @@ run_rs_tests() { # Post-condition: no replica set exists kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" '' - ### Delete a rs with initializer - # Pre-condition: no rs exists - kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" '' - # Create a rs - kubectl create --request-timeout=1 -f hack/testdata/replicaset-with-initializer.yaml 2>&1 "${kube_flags[@]}" || true - kube::test::get_object_assert 'rs nginx' "{{$id_field}}" 'nginx' - # Delete a rs - kubectl delete rs nginx "${kube_flags[@]}" - # check rs nginx doesn't exist - output_message=$(! kubectl get rs nginx 2>&1 "${kube_flags[@]}") - kube::test::if_has_string "${output_message}" '"nginx" not found' - if kube::test::if_supports_resource "${horizontalpodautoscalers}" ; then ### Auto scale replica set # Pre-condition: no replica set exists @@ -3554,7 +3860,7 @@ run_multi_resources_tests() { fi # Command: kubectl edit multiple resources temp_editor="${KUBE_TEMP}/tmp-editor.sh" - echo -e "#!/bin/bash\n${SED} -i \"s/status\:\ replaced/status\:\ edited/g\" \$@" > "${temp_editor}" + echo -e "#!/usr/bin/env bash\n${SED} -i \"s/status\:\ replaced/status\:\ edited/g\" \$@" > "${temp_editor}" chmod +x "${temp_editor}" EDITOR="${temp_editor}" kubectl edit "${kube_flags[@]}" -f "${file}" # Post-condition: mock service (and mock2) and mock rc (and mock2) are edited @@ -3755,6 +4061,8 @@ run_clusterroles_tests() { kubectl create "${kube_flags[@]}" clusterrole url-reader --verb=get --non-resource-url=/logs/* --non-resource-url=/healthz/* kube::test::get_object_assert clusterrole/url-reader "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" 'get:' kube::test::get_object_assert clusterrole/url-reader "{{range.rules}}{{range.nonResourceURLs}}{{.}}:{{end}}{{end}}" '/logs/\*:/healthz/\*:' + kubectl create "${kube_flags[@]}" clusterrole aggregation-reader --aggregation-rule="foo1=foo2" + kube::test::get_object_assert clusterrole/aggregation-reader "{{$id_field}}" 'aggregation-reader' # test `kubectl create clusterrolebinding` # test `kubectl set subject clusterrolebinding` @@ -3779,6 +4087,12 @@ run_clusterroles_tests() { kube::test::get_object_assert clusterrolebinding/super-sa "{{range.subjects}}{{.namespace}}:{{end}}" 'otherns:otherfoo:' kube::test::get_object_assert clusterrolebinding/super-sa "{{range.subjects}}{{.name}}:{{end}}" 'sa-name:foo:' + # test `kubectl set subject clusterrolebinding --all` + kubectl set subject "${kube_flags[@]}" clusterrolebinding --all --user=test-all-user + kube::test::get_object_assert clusterrolebinding/super-admin "{{range.subjects}}{{.name}}:{{end}}" 'super-admin:foo:test-all-user:' + kube::test::get_object_assert clusterrolebinding/super-group "{{range.subjects}}{{.name}}:{{end}}" 'the-group:foo:test-all-user:' + kube::test::get_object_assert clusterrolebinding/super-sa "{{range.subjects}}{{.name}}:{{end}}" 'sa-name:foo:test-all-user:' + # test `kubectl create rolebinding` # test `kubectl set subject rolebinding` kubectl create "${kube_flags[@]}" rolebinding admin --clusterrole=admin --user=default-admin @@ -3800,6 +4114,12 @@ run_clusterroles_tests() { kube::test::get_object_assert rolebinding/sarole "{{range.subjects}}{{.namespace}}:{{end}}" 'otherns:otherfoo:' kube::test::get_object_assert rolebinding/sarole "{{range.subjects}}{{.name}}:{{end}}" 'sa-name:foo:' + # test `kubectl set subject rolebinding --all` + kubectl set subject "${kube_flags[@]}" rolebinding --all --user=test-all-user + kube::test::get_object_assert rolebinding/admin "{{range.subjects}}{{.name}}:{{end}}" 'default-admin:foo:test-all-user:' + kube::test::get_object_assert rolebinding/localrole "{{range.subjects}}{{.name}}:{{end}}" 'the-group:foo:test-all-user:' + kube::test::get_object_assert rolebinding/sarole "{{range.subjects}}{{.name}}:{{end}}" 'sa-name:foo:test-all-user:' + set +o nounset set +o errexit } @@ -3875,7 +4195,7 @@ run_assert_categories_tests() { set -o errexit kube::log::status "Testing propagation of categories for resources" - output_message=$(kubectl get --raw=/api/v1 | grep -Po '"name":"pods".*?}') + output_message=$(kubectl get --raw=/api/v1 | grep -o '"name":"pods"[^}]*}') kube::test::if_has_string "${output_message}" '"categories":\["all"\]' set +o nounset @@ -3922,7 +4242,7 @@ run_cmd_with_img_tests() { # Test that a valid image reference value is provided as the value of --image in `kubectl run --image` output_message=$(kubectl run test1 --image=validname) - kube::test::if_has_string "${output_message}" 'deployment.apps "test1" created' + kube::test::if_has_string "${output_message}" 'deployment.apps/test1 created' kubectl delete deployments test1 # test invalid image name output_message=$(! kubectl run test2 --image=InvalidImageName 2>&1) @@ -4013,6 +4333,50 @@ run_service_accounts_tests() { set +o errexit } +run_job_tests() { + set -o nounset + set -o errexit + + create_and_use_new_namespace + kube::log::status "Testing job" + + ### Create a new namespace + # Pre-condition: the test-jobs namespace does not exist + kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-jobs\" }}found{{end}}{{end}}:' ':' + # Command + kubectl create namespace test-jobs + # Post-condition: namespace 'test-jobs' is created. + kube::test::get_object_assert 'namespaces/test-jobs' "{{$id_field}}" 'test-jobs' + + ### Create a cronjob in a specific namespace + kubectl run pi --schedule="59 23 31 2 *" --namespace=test-jobs --generator=cronjob/v1beta1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}" + # Post-Condition: assertion object exists + kube::test::get_object_assert 'cronjob/pi --namespace=test-jobs' "{{$id_field}}" 'pi' + kubectl get cronjob/pi --namespace=test-jobs + kubectl describe cronjob/pi --namespace=test-jobs + + ### Create a job in dry-run mode + output_message=$(kubectl create job test-job --from=cronjob/pi --dry-run=true --namespace=test-jobs -o name) + # Post-condition: The text 'job.batch/test-job' should be part of the output + kube::test::if_has_string "${output_message}" 'job.batch/test-job' + # Post-condition: The test-job wasn't created actually + kube::test::get_object_assert jobs "{{range.items}}{{$id_field}}{{end}}" '' + + ### Create a job in a specific namespace + kubectl create job test-job --from=cronjob/pi --namespace=test-jobs + # Post-Condition: assertion object exists + kube::test::get_object_assert 'job/test-job --namespace=test-jobs' "{{$id_field}}" 'test-job' + kubectl get job/test-job --namespace=test-jobs + kubectl describe job/test-job --namespace=test-jobs + #Clean up + kubectl delete job test-job --namespace=test-jobs + kubectl delete cronjob pi --namespace=test-jobs + kubectl delete namespace test-jobs + + set +o nounset + set +o errexit +} + run_pod_templates_tests() { set -o nounset set -o errexit @@ -4428,6 +4792,20 @@ run_kubectl_all_namespace_tests() { # Command kubectl get pods --all-namespaces --namespace=default + ### Check --all-namespaces option shows namespaces + # Create objects in multiple namespaces + kubectl create "${kube_flags[@]}" namespace all-ns-test-1 + kubectl create "${kube_flags[@]}" serviceaccount test -n all-ns-test-1 + kubectl create "${kube_flags[@]}" namespace all-ns-test-2 + kubectl create "${kube_flags[@]}" serviceaccount test -n all-ns-test-2 + # Ensure listing across namespaces displays the namespace + output_message=$(kubectl get serviceaccounts --all-namespaces "${kube_flags[@]}") + kube::test::if_has_string "${output_message}" "all-ns-test-1" + kube::test::if_has_string "${output_message}" "all-ns-test-2" + # Clean up + kubectl delete "${kube_flags[@]}" namespace all-ns-test-1 + kubectl delete "${kube_flags[@]}" namespace all-ns-test-2 + ### Clean up # Pre-condition: valid-pod exists kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:' @@ -4545,6 +4923,17 @@ __EOF__ } __EOF__ + # taint/untaint + # Pre-condition: node has no taints + kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.taints}}" '' + # taint can add a taint + kubectl taint node 127.0.0.1 dedicated=foo:PreferNoSchedule + kube::test::get_object_assert "nodes 127.0.0.1" '{{range .spec.taints}}{{.effect}}{{end}}' 'PreferNoSchedule' + # taint can remove a taint + kubectl taint node 127.0.0.1 dedicated- + # Post-condition: node has no taints + kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.taints}}" '' + ### kubectl cordon update with --dry-run does not mark node unschedulable # Pre-condition: node is schedulable kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" '' @@ -4600,7 +4989,7 @@ __EOF__ kube::test::if_has_string "${response}" 'must provide one or more resources' # test=label matches our node response=$(kubectl cordon --selector test=label) - kube::test::if_has_string "${response}" 'node "127.0.0.1" cordoned' + kube::test::if_has_string "${response}" 'node/127.0.0.1 cordoned' # invalid=label does not match any nodes response=$(kubectl cordon --selector invalid=label) kube::test::if_has_not_string "${response}" 'cordoned' @@ -4736,13 +5125,15 @@ runTests() { kube::log::status "Checking kubectl version" kubectl version - # use timestamp as the name of namespace because increasing the variable inside subshell - # does not affect the value of the variable outside the subshell. + # Generate a random namespace name, based on the current time (to make + # debugging slightly easier) and a random number. Don't use `date +%N` + # because that doesn't work on OSX. create_and_use_new_namespace() { - namespace_number=$(date +%s%N) - kube::log::status "Creating namespace namespace${namespace_number}" - kubectl create namespace "namespace${namespace_number}" - kubectl config set-context "${CONTEXT}" --namespace="namespace${namespace_number}" + local ns_name + ns_name="namespace-$(date +%s)-${RANDOM}" + kube::log::status "Creating namespace ${ns_name}" + kubectl create namespace "${ns_name}" + kubectl config set-context "${CONTEXT}" --namespace="${ns_name}" } kube_flags=( @@ -4837,6 +5228,11 @@ runTests() { record_command run_RESTMapper_evaluation_tests + # find all resources + kubectl "${kube_flags[@]}" api-resources + # find all namespaced resources that support list by name and get them + kubectl "${kube_flags[@]}" api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl "${kube_flags[@]}" get -o name + ################ # Cluster Role # ################ @@ -4893,13 +5289,18 @@ runTests() { record_command run_kubectl_apply_deployments_tests fi + ################ + # Kubectl diff # + ################ + record_command run_kubectl_diff_tests + ############### # Kubectl get # ############### if kube::test::if_supports_resource "${pods}" ; then record_command run_kubectl_get_tests - record_command run_kubectl_server_print_tests + record_command run_kubectl_old_print_tests fi @@ -4987,6 +5388,14 @@ runTests() { record_command run_service_accounts_tests fi + #################### + # Job # + #################### + + if kube::test::if_supports_resource "${job}" ; then + record_command run_job_tests + fi + ################# # Pod templates # ################# @@ -5132,6 +5541,12 @@ runTests() { output_message=$(kubectl auth can-i list jobs.batch/bar -n foo --quiet 2>&1 "${kube_flags[@]}") kube::test::if_empty_string "${output_message}" + + output_message=$(kubectl auth can-i get pods --subresource=log 2>&1 "${kube_flags[@]}"; echo $?) + kube::test::if_has_string "${output_message}" '0' + + output_message=$(kubectl auth can-i get pods --subresource=log --quiet 2>&1 "${kube_flags[@]}"; echo $?) + kube::test::if_has_string "${output_message}" '0' fi # kubectl auth reconcile @@ -5199,6 +5614,14 @@ runTests() { fi fi + ###################### + # kubectl --template # + ###################### + + if kube::test::if_supports_resource "${pods}" ; then + record_command run_template_output_tests + fi + ################ # Certificates # ################ @@ -5260,8 +5683,6 @@ run_initializer_tests() { output_message=$(kubectl get deployments web 2>&1 "${kube_flags[@]}") # Post-condition: I assume "web" is the deployment name kube::test::if_has_string "${output_message}" 'web' - # Command - output_message=$(kubectl get deployments --show-all 2>&1 "${kube_flags[@]}") # Post-condition: The text "No resources found" should be part of the output kube::test::if_has_string "${output_message}" 'No resources found' diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd.sh b/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd.sh index b68f1eeca..a4b4ef33b 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/test-e2e-node.sh b/vendor/k8s.io/kubernetes/hack/make-rules/test-e2e-node.sh index 3ce6fa36e..2e5c95ae2 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/test-e2e-node.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/test-e2e-node.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/test-integration.sh b/vendor/k8s.io/kubernetes/hack/make-rules/test-integration.sh index b545e2574..b69124df0 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/test-integration.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/test-integration.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/test-kubeadm-cmd.sh b/vendor/k8s.io/kubernetes/hack/make-rules/test-kubeadm-cmd.sh index fadb83bdf..86d82b089 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/test-kubeadm-cmd.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/test-kubeadm-cmd.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/test.sh b/vendor/k8s.io/kubernetes/hack/make-rules/test.sh index 54feeea8e..639ee5397 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/test.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -57,6 +57,7 @@ kube::test::find_dirs() { -o -path './target/*' \ -o -path './test/e2e/*' \ -o -path './test/e2e_node/*' \ + -o -path './test/e2e_kubeadm/*' \ -o -path './test/integration/*' \ -o -path './third_party/*' \ -o -path './staging/*' \ @@ -278,12 +279,6 @@ runTests() { # command, which is much faster. if [[ ! ${KUBE_COVER} =~ ^[yY]$ ]]; then kube::log::status "Running tests without code coverage" - # `go test` does not install the things it builds. `go test -i` installs - # the build artifacts but doesn't run the tests. The two together provide - # a large speedup for tests that do not need to be rebuilt. - go test -i "${goflags[@]:+${goflags[@]}}" \ - ${KUBE_RACE} ${KUBE_TIMEOUT} "${@}" \ - "${testargs[@]:+${testargs[@]}}" go test "${goflags[@]:+${goflags[@]}}" \ ${KUBE_RACE} ${KUBE_TIMEOUT} "${@}" \ "${testargs[@]:+${testargs[@]}}" \ @@ -319,21 +314,11 @@ runTests() { for path in $(echo $cover_ignore_dirs | sed 's/|/ /g'); do echo -e "skipped\tk8s.io/kubernetes/$path" done - # - # `go test` does not install the things it builds. `go test -i` installs - # the build artifacts but doesn't run the tests. The two together provide - # a large speedup for tests that do not need to be rebuilt. + printf "%s\n" "${@}" \ | grep -Ev $cover_ignore_dirs \ | xargs -I{} -n 1 -P ${KUBE_COVERPROCS} \ bash -c "set -o pipefail; _pkg=\"\$0\"; _pkg_out=\${_pkg//\//_}; \ - go test -i ${goflags[@]:+${goflags[@]}} \ - ${KUBE_RACE} \ - ${KUBE_TIMEOUT} \ - -cover -covermode=\"${KUBE_COVERMODE}\" \ - -coverprofile=\"${cover_report_dir}/\${_pkg}/${cover_profile}\" \ - \"\${_pkg}\" \ - ${testargs[@]:+${testargs[@]}} go test ${goflags[@]:+${goflags[@]}} \ ${KUBE_RACE} \ ${KUBE_TIMEOUT} \ diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/update.sh b/vendor/k8s.io/kubernetes/hack/make-rules/update.sh index 3ba685e86..0dd3ba222 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/update.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/update.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/verify.sh b/vendor/k8s.io/kubernetes/hack/make-rules/verify.sh index 13fe2a13b..1492fb850 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/verify.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/verify.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -40,7 +40,6 @@ QUICK_PATTERNS+=( "verify-api-groups.sh" "verify-bazel.sh" "verify-boilerplate.sh" - "verify-generated-files-remake" "verify-godep-licenses.sh" "verify-gofmt.sh" "verify-imports.sh" diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/vet.sh b/vendor/k8s.io/kubernetes/hack/make-rules/vet.sh index 0b6efb051..65a0d4945 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/vet.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/vet.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/run-in-gopath.sh b/vendor/k8s.io/kubernetes/hack/run-in-gopath.sh index bbd4dd3d1..e83dc2cd6 100755 --- a/vendor/k8s.io/kubernetes/hack/run-in-gopath.sh +++ b/vendor/k8s.io/kubernetes/hack/run-in-gopath.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/test-cmd.sh b/vendor/k8s.io/kubernetes/hack/test-cmd.sh deleted file mode 100755 index f4e5abeb0..000000000 --- a/vendor/k8s.io/kubernetes/hack/test-cmd.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -# 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. - -# This script is a vestigial redirection. Please do not add "real" logic. - -set -o errexit -set -o nounset -set -o pipefail - -KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. - -# For help output -ARGHELP="" -if [[ "$#" -gt 0 ]]; then - ARGHELP="" -fi - -echo "NOTE: $0 has been replaced by 'make test-cmd'" -echo -echo "The equivalent of this invocation is: " -echo " make test-cmd ${ARGHELP}" -echo -echo -make --no-print-directory -C "${KUBE_ROOT}" test-cmd diff --git a/vendor/k8s.io/kubernetes/hack/test-go.sh b/vendor/k8s.io/kubernetes/hack/test-go.sh index a1e4e9218..380e8d18d 100755 --- a/vendor/k8s.io/kubernetes/hack/test-go.sh +++ b/vendor/k8s.io/kubernetes/hack/test-go.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/test-integration.sh b/vendor/k8s.io/kubernetes/hack/test-integration.sh index ad928e03f..59a082c73 100755 --- a/vendor/k8s.io/kubernetes/hack/test-integration.sh +++ b/vendor/k8s.io/kubernetes/hack/test-integration.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/test-update-storage-objects.sh b/vendor/k8s.io/kubernetes/hack/test-update-storage-objects.sh index b568a3085..f2e53edc6 100755 --- a/vendor/k8s.io/kubernetes/hack/test-update-storage-objects.sh +++ b/vendor/k8s.io/kubernetes/hack/test-update-storage-objects.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -40,7 +40,6 @@ ETCD_PORT=${ETCD_PORT:-2379} ETCD_PREFIX=${ETCD_PREFIX:-randomPrefix} API_PORT=${API_PORT:-8080} API_HOST=${API_HOST:-127.0.0.1} -KUBE_API_VERSIONS="" RUNTIME_CONFIG="" ETCDCTL=$(which etcdctl) @@ -51,13 +50,12 @@ DISABLE_ADMISSION_PLUGINS="ServiceAccount,NamespaceLifecycle,LimitRanger,Mutatin function startApiServer() { local storage_versions=${1:-""} local storage_media_type=${2:-""} - kube::log::status "Starting kube-apiserver with KUBE_API_VERSIONS: ${KUBE_API_VERSIONS}" - kube::log::status " and storage-media-type: ${storage_media_type}" - kube::log::status " and runtime-config: ${RUNTIME_CONFIG}" - kube::log::status " and storage-version overrides: ${storage_versions}" + kube::log::status "Starting kube-apiserver with..." + kube::log::status " storage-media-type: ${storage_media_type}" + kube::log::status " runtime-config: ${RUNTIME_CONFIG}" + kube::log::status " storage-version overrides: ${storage_versions}" - KUBE_API_VERSIONS="${KUBE_API_VERSIONS}" \ - "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \ + "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \ --insecure-bind-address="${API_HOST}" \ --bind-address="${API_HOST}" \ --insecure-port="${API_PORT}" \ @@ -97,7 +95,6 @@ function cleanup() { trap cleanup EXIT SIGINT make -C "${KUBE_ROOT}" WHAT=cmd/kube-apiserver -make -C "${KUBE_ROOT}" WHAT=cluster/images/etcd/attachlease kube::etcd::start echo "${ETCD_VERSION}" > "${ETCD_DIR}/version.txt" @@ -106,11 +103,11 @@ echo "${ETCD_VERSION}" > "${ETCD_DIR}/version.txt" # source_file,resource,namespace,name,old_version,new_version tests=( -examples/persistent-volume-provisioning/rbd/rbd-storage-class.yaml,storageclasses,,slow,v1beta1,v1 +test/e2e/testing-manifests/rbd-storage-class.yaml,storageclasses,,slow,v1beta1,v1 ) KUBE_OLD_API_VERSION="networking.k8s.io/v1,storage.k8s.io/v1beta1,extensions/v1beta1" -KUBE_NEW_API_VERSION="networking.k8s.io/v1,storage.k8s.io/v1,extensions/v1beta1" +KUBE_NEW_API_VERSION="networking.k8s.io/v1,storage.k8s.io/v1,extensions/v1beta1,policy/v1beta1" KUBE_OLD_STORAGE_VERSIONS="storage.k8s.io/v1beta1" KUBE_NEW_STORAGE_VERSIONS="storage.k8s.io/v1" @@ -121,8 +118,7 @@ KUBE_NEW_STORAGE_VERSIONS="storage.k8s.io/v1" # but KUBE_OLD_API_VERSION is the latest (storage) version. # Additionally use KUBE_STORAGE_MEDIA_TYPE_JSON for storage encoding. ####################################################### -KUBE_API_VERSIONS="v1,${KUBE_OLD_API_VERSION},${KUBE_NEW_API_VERSION}" -RUNTIME_CONFIG="api/all=false,api/v1=true,${KUBE_OLD_API_VERSION}=true,${KUBE_NEW_API_VERSION}=true" +RUNTIME_CONFIG="api/all=false,api/v1=true,apiregistration.k8s.io/v1=true,${KUBE_OLD_API_VERSION}=true,${KUBE_NEW_API_VERSION}=true" startApiServer ${KUBE_OLD_STORAGE_VERSIONS} ${KUBE_STORAGE_MEDIA_TYPE_JSON} @@ -156,8 +152,7 @@ killApiServer # Still use KUBE_STORAGE_MEDIA_TYPE_JSON for storage encoding. ####################################################### -KUBE_API_VERSIONS="v1,${KUBE_NEW_API_VERSION},${KUBE_OLD_API_VERSION}" -RUNTIME_CONFIG="api/all=false,api/v1=true,${KUBE_OLD_API_VERSION}=true,${KUBE_NEW_API_VERSION}=true" +RUNTIME_CONFIG="api/all=false,api/v1=true,apiregistration.k8s.io/v1=true,${KUBE_OLD_API_VERSION}=true,${KUBE_NEW_API_VERSION}=true" startApiServer ${KUBE_NEW_STORAGE_VERSIONS} ${KUBE_STORAGE_MEDIA_TYPE_JSON} # Update etcd objects, so that will now be stored in the new api version. @@ -187,8 +182,7 @@ killApiServer # However, change storage encoding to KUBE_STORAGE_MEDIA_TYPE_PROTOBUF. ####################################################### -KUBE_API_VERSIONS="v1,${KUBE_NEW_API_VERSION}" -RUNTIME_CONFIG="api/all=false,api/v1=true,${KUBE_NEW_API_VERSION}=true" +RUNTIME_CONFIG="api/all=false,api/v1=true,apiregistration.k8s.io/v1=true,${KUBE_NEW_API_VERSION}=true" # This seems to reduce flakiness. sleep 1 diff --git a/vendor/k8s.io/kubernetes/hack/testdata/deployment-label-change3.yaml b/vendor/k8s.io/kubernetes/hack/testdata/deployment-label-change3.yaml index 15ce288dc..dbe91dadd 100644 --- a/vendor/k8s.io/kubernetes/hack/testdata/deployment-label-change3.yaml +++ b/vendor/k8s.io/kubernetes/hack/testdata/deployment-label-change3.yaml @@ -17,6 +17,6 @@ spec: spec: containers: - name: nginx - image: gcr.io/google-containers/nginx:test-cmd + image: k8s.gcr.io/nginx:test-cmd ports: - containerPort: 80 diff --git a/vendor/k8s.io/kubernetes/hack/testdata/deployment-with-initializer.yaml b/vendor/k8s.io/kubernetes/hack/testdata/deployment-with-initializer.yaml deleted file mode 100644 index 2fb81498c..000000000 --- a/vendor/k8s.io/kubernetes/hack/testdata/deployment-with-initializer.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: web - labels: - run: web - initializers: - pending: - - name: podimage.initializer.com -spec: - replicas: 5 - selector: - matchLabels: - run: web - template: - metadata: - labels: - run: web - spec: - containers: - - image: nginx:1.10 - name: web - ports: - - containerPort: 80 - protocol: TCP diff --git a/vendor/k8s.io/kubernetes/hack/testdata/pod-with-precision.json b/vendor/k8s.io/kubernetes/hack/testdata/pod-with-precision.json index 6835de64d..f96fb21e4 100644 --- a/vendor/k8s.io/kubernetes/hack/testdata/pod-with-precision.json +++ b/vendor/k8s.io/kubernetes/hack/testdata/pod-with-precision.json @@ -9,7 +9,7 @@ "containers": [ { "name": "kubernetes-pause", - "image": "k8s.gcr.io/pause-amd64:3.1" + "image": "k8s.gcr.io/pause:3.1" } ], "restartPolicy": "Never", diff --git a/vendor/k8s.io/kubernetes/hack/testdata/replicaset-with-initializer.yaml b/vendor/k8s.io/kubernetes/hack/testdata/replicaset-with-initializer.yaml deleted file mode 100644 index 8530faf90..000000000 --- a/vendor/k8s.io/kubernetes/hack/testdata/replicaset-with-initializer.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: ReplicaSet -metadata: - name: nginx - initializers: - pending: - - name: podimage.initializer.com -spec: - replicas: 3 - selector: - matchLabels: - app: nginx - template: - metadata: - name: nginx - labels: - app: nginx - spec: - containers: - - name: nginx - image: nginx:1.10 - ports: - - containerPort: 80 diff --git a/vendor/k8s.io/kubernetes/hack/update-all.sh b/vendor/k8s.io/kubernetes/hack/update-all.sh index 2a9f282bf..ba4311f1c 100755 --- a/vendor/k8s.io/kubernetes/hack/update-all.sh +++ b/vendor/k8s.io/kubernetes/hack/update-all.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-api-reference-docs.sh b/vendor/k8s.io/kubernetes/hack/update-api-reference-docs.sh index 6fb808f7a..59296e462 100755 --- a/vendor/k8s.io/kubernetes/hack/update-api-reference-docs.sh +++ b/vendor/k8s.io/kubernetes/hack/update-api-reference-docs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-bazel.sh b/vendor/k8s.io/kubernetes/hack/update-bazel.sh index 25c858f7d..cce18c0aa 100755 --- a/vendor/k8s.io/kubernetes/hack/update-bazel.sh +++ b/vendor/k8s.io/kubernetes/hack/update-bazel.sh @@ -26,13 +26,14 @@ kube::util::ensure-gnu-sed # TODO(spxtr): Remove this line once Bazel is the only way to build. rm -f "${KUBE_ROOT}/pkg/generated/openapi/zz_generated.openapi.go" -# The git commit sha1s here should match the values in $KUBE_ROOT/WORKSPACE. -kube::util::go_install_from_commit \ - github.com/kubernetes/repo-infra/kazel \ - 97099dccc8807e9159dc28f374a8f0602cab07e1 -kube::util::go_install_from_commit \ - github.com/bazelbuild/bazel-gazelle/cmd/gazelle \ - 578e73e57d6a4054ef933db1553405c9284322c7 +# Ensure that we find the binaries we build before anything else. +export GOBIN="${KUBE_OUTPUT_BINPATH}" +PATH="${GOBIN}:${PATH}" + +# Install tools we need, but only from vendor/... +go install ./vendor/github.com/bazelbuild/bazel-gazelle/cmd/gazelle + +go install ./vendor/github.com/kubernetes/repo-infra/kazel touch "${KUBE_ROOT}/vendor/BUILD" diff --git a/vendor/k8s.io/kubernetes/hack/update-cloudprovider-gce.sh b/vendor/k8s.io/kubernetes/hack/update-cloudprovider-gce.sh index 90b8659c5..b35c429f8 100755 --- a/vendor/k8s.io/kubernetes/hack/update-cloudprovider-gce.sh +++ b/vendor/k8s.io/kubernetes/hack/update-cloudprovider-gce.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-codegen.sh b/vendor/k8s.io/kubernetes/hack/update-codegen.sh index 23bc3105c..a099b1dc6 100755 --- a/vendor/k8s.io/kubernetes/hack/update-codegen.sh +++ b/vendor/k8s.io/kubernetes/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -72,7 +72,7 @@ INTERNAL_DIRS_CSV=$(IFS=',';echo "${INTERNAL_DIRS[*]// /,}";IFS=$) # This can be called with one flag, --verify-only, so it works for both the # update- and verify- scripts. ${clientgen} --input-base="k8s.io/kubernetes/pkg/apis" --input="${INTERNAL_DIRS_CSV}" "$@" -${clientgen} --output-base "${KUBE_ROOT}/vendor" --output-package="k8s.io/client-go" --clientset-name="kubernetes" --input-base="k8s.io/kubernetes/vendor/k8s.io/api" --input="${GV_DIRS_CSV}" --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.go.txt "$@" +${clientgen} --output-base "${KUBE_ROOT}/vendor" --output-package="k8s.io/client-go" --clientset-name="kubernetes" --input-base="k8s.io/kubernetes/vendor/k8s.io/api" --input="${GV_DIRS_CSV}" --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.generatego.txt "$@" listergen_internal_apis=( $( @@ -91,7 +91,7 @@ $( ) ) listergen_external_apis_csv=$(IFS=,; echo "${listergen_external_apis[*]}") -${listergen} --output-base "${KUBE_ROOT}/vendor" --output-package "k8s.io/client-go/listers" --input-dirs "${listergen_external_apis_csv}" --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.go.txt "$@" +${listergen} --output-base "${KUBE_ROOT}/vendor" --output-package "k8s.io/client-go/listers" --input-dirs "${listergen_external_apis_csv}" --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.generatego.txt "$@" informergen_internal_apis=( $( @@ -105,7 +105,7 @@ ${informergen} \ --input-dirs "${informergen_internal_apis_csv}" \ --internal-clientset-package k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset \ --listers-package k8s.io/kubernetes/pkg/client/listers \ - --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.go.txt \ + --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.generatego.txt \ "$@" informergen_external_apis=( @@ -125,7 +125,7 @@ ${informergen} \ --input-dirs "${informergen_external_apis_csv}" \ --versioned-clientset-package k8s.io/client-go/kubernetes \ --listers-package k8s.io/client-go/listers \ - --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.go.txt \ + --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.generatego.txt \ "$@" # You may add additional calls of code generators like set-gen above. @@ -137,3 +137,4 @@ CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/sample-apiserver/hack/u CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/sample-controller/hack/update-codegen.sh CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/apiextensions-apiserver/hack/update-codegen.sh CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/metrics/hack/update-codegen.sh +CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-device-plugin-dockerized.sh b/vendor/k8s.io/kubernetes/hack/update-generated-device-plugin-dockerized.sh index 132f0650b..62c5fb34d 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-device-plugin-dockerized.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-device-plugin-dockerized.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-device-plugin.sh b/vendor/k8s.io/kubernetes/hack/update-generated-device-plugin.sh index b7e2b5723..bfd63d865 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-device-plugin.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-device-plugin.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-docs.sh b/vendor/k8s.io/kubernetes/hack/update-generated-docs.sh index 6d5ed939f..d1f49ef53 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-docs.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-docs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-kms-dockerized.sh b/vendor/k8s.io/kubernetes/hack/update-generated-kms-dockerized.sh index d28ab214f..7d61e67e2 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-kms-dockerized.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-kms-dockerized.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Kubernetes Authors. # @@ -54,8 +54,7 @@ PATH="${gogopath}:${PATH}" \ --gogo_out=plugins=grpc:${KUBE_KMS_GRPC_ROOT} ${KUBE_KMS_GRPC_ROOT}/service.proto # Update boilerplate for the generated file. -echo "$(cat hack/boilerplate/boilerplate.go.txt ${KUBE_KMS_GRPC_ROOT}/service.pb.go)" > ${KUBE_KMS_GRPC_ROOT}/service.pb.go -sed -i".bak" "s/Copyright YEAR/Copyright $(date '+%Y')/g" ${KUBE_KMS_GRPC_ROOT}/service.pb.go +echo "$(cat hack/boilerplate/boilerplate.generatego.txt ${KUBE_KMS_GRPC_ROOT}/service.pb.go)" > ${KUBE_KMS_GRPC_ROOT}/service.pb.go # Run gofmt to clean up the generated code. kube::golang::verify_go_version diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-kms.sh b/vendor/k8s.io/kubernetes/hack/update-generated-kms.sh index 95a0ee80c..431b1bf41 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-kms.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-kms.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-kubelet-plugin-registration-dockerized.sh b/vendor/k8s.io/kubernetes/hack/update-generated-kubelet-plugin-registration-dockerized.sh new file mode 100755 index 000000000..daf5abbd3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/hack/update-generated-kubelet-plugin-registration-dockerized.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Copyright 2018 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. + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT="$(cd "$(dirname "${BASH_SOURCE}")/../" && pwd -P)" +KUBELET_PLUGIN_REGISTRATION_ROOT="${KUBE_ROOT}/pkg/kubelet/apis/pluginregistration/v1alpha1/" +KUBELET_EXAMPLE_PLUGIN_V1BETA1="${KUBE_ROOT}/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/" +KUBELET_EXAMPLE_PLUGIN_V1BETA2="${KUBE_ROOT}/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/" + +source "${KUBE_ROOT}/hack/lib/protoc.sh" +kube::protoc::generate_proto ${KUBELET_PLUGIN_REGISTRATION_ROOT} +kube::protoc::generate_proto ${KUBELET_EXAMPLE_PLUGIN_V1BETA1} +kube::protoc::generate_proto ${KUBELET_EXAMPLE_PLUGIN_V1BETA2} diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-kubelet-plugin-registration.sh b/vendor/k8s.io/kubernetes/hack/update-generated-kubelet-plugin-registration.sh new file mode 100755 index 000000000..308733c02 --- /dev/null +++ b/vendor/k8s.io/kubernetes/hack/update-generated-kubelet-plugin-registration.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Copyright 2018 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. + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. + +# NOTE: All output from this script needs to be copied back to the calling +# source tree. This is managed in kube::build::copy_output in build/common.sh. +# If the output set is changed update that function. + +${KUBE_ROOT}/build/run.sh hack/update-generated-kubelet-plugin-registration-dockerized.sh "$@" diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-protobuf-dockerized.sh b/vendor/k8s.io/kubernetes/hack/update-generated-protobuf-dockerized.sh index 658a82942..d86e4d53d 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-protobuf-dockerized.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-protobuf-dockerized.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -68,6 +68,7 @@ PACKAGES=( k8s.io/api/certificates/v1beta1 k8s.io/api/imagepolicy/v1alpha1 k8s.io/api/scheduling/v1alpha1 + k8s.io/api/scheduling/v1beta1 k8s.io/api/settings/v1alpha1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 @@ -94,5 +95,5 @@ PATH="${KUBE_ROOT}/_output/bin:${PATH}" \ --proto-import="${KUBE_ROOT}/vendor" \ --proto-import="${KUBE_ROOT}/third_party/protobuf" \ --packages=$(IFS=, ; echo "${PACKAGES[*]}") \ - --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.go.txt \ + --go-header-file ${KUBE_ROOT}/hack/boilerplate/boilerplate.generatego.txt \ "$@" diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-protobuf.sh b/vendor/k8s.io/kubernetes/hack/update-generated-protobuf.sh index f2cf01c0f..bf8c5d400 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-protobuf.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-protobuf.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-runtime-dockerized.sh b/vendor/k8s.io/kubernetes/hack/update-generated-runtime-dockerized.sh index 724c5d155..43dbc560f 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-runtime-dockerized.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-runtime-dockerized.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -54,8 +54,7 @@ PATH="${gogopath}:${PATH}" \ --gogo_out=plugins=grpc:${KUBE_REMOTE_RUNTIME_ROOT} ${KUBE_REMOTE_RUNTIME_ROOT}/api.proto # Update boilerplate for the generated file. -echo "$(cat hack/boilerplate/boilerplate.go.txt ${KUBE_REMOTE_RUNTIME_ROOT}/api.pb.go)" > ${KUBE_REMOTE_RUNTIME_ROOT}/api.pb.go -sed -i".bak" "s/Copyright YEAR/Copyright $(date '+%Y')/g" ${KUBE_REMOTE_RUNTIME_ROOT}/api.pb.go +echo "$(cat hack/boilerplate/boilerplate.generatego.txt ${KUBE_REMOTE_RUNTIME_ROOT}/api.pb.go)" > ${KUBE_REMOTE_RUNTIME_ROOT}/api.pb.go # Run gofmt to clean up the generated code. kube::golang::verify_go_version diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-runtime.sh b/vendor/k8s.io/kubernetes/hack/update-generated-runtime.sh index c347c01a6..04b879910 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-runtime.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-runtime.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-generated-swagger-docs.sh b/vendor/k8s.io/kubernetes/hack/update-generated-swagger-docs.sh index 0e91c9941..536ec65b1 100755 --- a/vendor/k8s.io/kubernetes/hack/update-generated-swagger-docs.sh +++ b/vendor/k8s.io/kubernetes/hack/update-generated-swagger-docs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-godep-licenses.sh b/vendor/k8s.io/kubernetes/hack/update-godep-licenses.sh index 8d5a38c20..bd9679968 100755 --- a/vendor/k8s.io/kubernetes/hack/update-godep-licenses.sh +++ b/vendor/k8s.io/kubernetes/hack/update-godep-licenses.sh @@ -37,7 +37,7 @@ export LC_ALL=C # Process package content # # @param package The incoming package name -# @param type The type of content (LICENSE or COPYRIGHT) +# @param type The type of content (LICENSE, COPYRIGHT or COPYING) # process_content () { local package=$1 @@ -65,15 +65,19 @@ process_content () { find_maxdepth=3 ensure_pattern="copyright" ;; + COPYING) find_names=(-iname 'copying*') + find_maxdepth=1 + ensure_pattern="license|copyright" + ;; esac # Start search at package root case ${package} in github.com/*|golang.org/*|bitbucket.org/*) - package_root=$(echo ${package} |awk -F/ '{ print $1"/"$2"/"$3 }') + package_root=$(echo "${package}" |awk -F/ '{ print $1"/"$2"/"$3 }') ;; go4.org/*) - package_root=$(echo ${package} |awk -F/ '{ print $1 }') + package_root=$(echo "${package}" |awk -F/ '{ print $1 }') ;; gopkg.in/*) # Root of gopkg.in package always ends with '.v(number)' and my contain @@ -81,10 +85,10 @@ process_content () { # - gopkg.in/yaml.v2 # - gopkg.in/inf.v0 # - gopkg.in/square/go-jose.v2 - package_root=$(echo ${package} |grep -oh '.*\.v[0-9]') + package_root=$(echo "${package}" |grep -oh '.*\.v[0-9]') ;; *) - package_root=$(echo ${package} |awk -F/ '{ print $1"/"$2 }') + package_root=$(echo "${package}" |awk -F/ '{ print $1"/"$2 }') ;; esac @@ -94,7 +98,7 @@ process_content () { [[ -d ${DEPS_DIR}/${dir_root} ]] || continue # One (set) of these is fine - find ${DEPS_DIR}/${dir_root} \ + find "${DEPS_DIR}/${dir_root}" \ -xdev -follow -maxdepth ${find_maxdepth} \ -type f "${find_names[@]}" done | sort -u)) @@ -103,9 +107,14 @@ process_content () { local f index="${package}-${type}" if [[ -z "${CONTENT[${index}]-}" ]]; then - for f in ${local_files[@]-}; do + for f in "${local_files[@]-}"; do + if [[ -z "$f" ]]; then + # Set the default value and then check it to prevent + # accessing potentially empty array + continue + fi # Find some copyright info in any file and break - if egrep -i -wq "${ensure_pattern}" "${f}"; then + if grep -E -i -wq "${ensure_pattern}" "${f}"; then CONTENT[${index}]="${f}" break fi @@ -147,18 +156,17 @@ declare -Ag CONTENT echo "================================================================================" echo "= Kubernetes licensed under: =" echo -cat ${LICENSE_ROOT}/LICENSE +cat "${LICENSE_ROOT}/LICENSE" echo -echo "= LICENSE $(cat ${LICENSE_ROOT}/LICENSE | md5sum | awk '{print $1}')" +echo "= LICENSE $(cat "${LICENSE_ROOT}/LICENSE" | md5sum | awk '{print $1}')" echo "================================================================================" ) > ${TMP_LICENSE_FILE} # Loop through every package in Godeps.json -for PACKAGE in $(cat Godeps/Godeps.json | \ - jq -r ".Deps[].ImportPath" | \ - sort -f); do - process_content ${PACKAGE} LICENSE - process_content ${PACKAGE} COPYRIGHT +for PACKAGE in $(jq -r ".Deps[].ImportPath" < Godeps/Godeps.json | sort -f); do + process_content "${PACKAGE}" LICENSE + process_content "${PACKAGE}" COPYRIGHT + process_content "${PACKAGE}" COPYING # display content echo @@ -171,16 +179,18 @@ for PACKAGE in $(cat Godeps/Godeps.json | \ file="${CONTENT[${PACKAGE}-LICENSE]-}" elif [[ -n "${CONTENT[${PACKAGE}-COPYRIGHT]-}" ]]; then file="${CONTENT[${PACKAGE}-COPYRIGHT]-}" + elif [[ -n "${CONTENT[${PACKAGE}-COPYING]-}" ]]; then + file="${CONTENT[${PACKAGE}-COPYING]-}" fi if [[ -z "${file}" ]]; then cat > /dev/stderr << __EOF__ No license could be found for ${PACKAGE} - aborting. Options: -1. Check if the upstream repository has a newer version with LICENSE and/or - COPYRIGHT files. -2. Contact the author of the package to ensure there is a LICENSE and/or - COPYRIGHT file present. +1. Check if the upstream repository has a newer version with LICENSE, COPYRIGHT and/or + COPYING files. +2. Contact the author of the package to ensure there is a LICENSE, COPYRIGHT and/or + COPYING file present. 3. Do not use this package in Kubernetes. __EOF__ exit 9 @@ -188,7 +198,7 @@ __EOF__ cat "${file}" echo - echo "= ${file} $(cat ${file} | md5sum | awk '{print $1}')" + echo "= ${file} $(cat "${file}" | md5sum | awk '{print $1}')" echo "================================================================================" echo done >> ${TMP_LICENSE_FILE} diff --git a/vendor/k8s.io/kubernetes/hack/update-gofmt.sh b/vendor/k8s.io/kubernetes/hack/update-gofmt.sh index 83800c6ee..c3220e3bb 100755 --- a/vendor/k8s.io/kubernetes/hack/update-gofmt.sh +++ b/vendor/k8s.io/kubernetes/hack/update-gofmt.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-openapi-spec.sh b/vendor/k8s.io/kubernetes/hack/update-openapi-spec.sh index b0016bc29..8b940552b 100755 --- a/vendor/k8s.io/kubernetes/hack/update-openapi-spec.sh +++ b/vendor/k8s.io/kubernetes/hack/update-openapi-spec.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -31,7 +31,11 @@ make -C "${KUBE_ROOT}" WHAT=cmd/kube-apiserver function cleanup() { - [[ -n ${APISERVER_PID-} ]] && kill ${APISERVER_PID} 1>&2 2>/dev/null + if [[ -n ${APISERVER_PID-} ]]; then + kill ${APISERVER_PID} 1>&2 2>/dev/null + wait ${APISERVER_PID} || true + fi + unset APISERVER_PID kube::etcd::cleanup diff --git a/vendor/k8s.io/kubernetes/hack/update-staging-godeps-dockerized.sh b/vendor/k8s.io/kubernetes/hack/update-staging-godeps-dockerized.sh index 9399ba7bf..877e43b2d 100755 --- a/vendor/k8s.io/kubernetes/hack/update-staging-godeps-dockerized.sh +++ b/vendor/k8s.io/kubernetes/hack/update-staging-godeps-dockerized.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-staging-godeps.sh b/vendor/k8s.io/kubernetes/hack/update-staging-godeps.sh index 0b5c11b1d..75da7a411 100755 --- a/vendor/k8s.io/kubernetes/hack/update-staging-godeps.sh +++ b/vendor/k8s.io/kubernetes/hack/update-staging-godeps.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-swagger-spec.sh b/vendor/k8s.io/kubernetes/hack/update-swagger-spec.sh index fc363fa57..fef20e8e5 100755 --- a/vendor/k8s.io/kubernetes/hack/update-swagger-spec.sh +++ b/vendor/k8s.io/kubernetes/hack/update-swagger-spec.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/update-translations.sh b/vendor/k8s.io/kubernetes/hack/update-translations.sh index 46c7cfd73..69b4e50c8 100755 --- a/vendor/k8s.io/kubernetes/hack/update-translations.sh +++ b/vendor/k8s.io/kubernetes/hack/update-translations.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -14,6 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. +source "${KUBE_ROOT}/hack/lib/util.sh" + KUBECTL_FILES="pkg/kubectl/cmd/*.go pkg/kubectl/cmd/*/*.go" generate_pot="false" @@ -62,8 +65,9 @@ if [[ "${generate_pot}" == "true" ]]; then perl -pi -e 's/CHARSET/UTF-8/' tmp.pot perl -pi -e 's/\\\(/\\\\\(/g' tmp.pot perl -pi -e 's/\\\)/\\\\\)/g' tmp.pot - if msgcat -s tmp.pot > /tmp/template.pot; then - mv /tmp/template.pot translations/kubectl/template.pot + kube::util::ensure-temp-dir + if msgcat -s tmp.pot > "${KUBE_TEMP}/template.pot"; then + mv "${KUBE_TEMP}/template.pot" translations/kubectl/template.pot rm tmp.pot else echo "Failed to update template.pot" diff --git a/vendor/k8s.io/kubernetes/hack/update-workspace-mirror.sh b/vendor/k8s.io/kubernetes/hack/update-workspace-mirror.sh new file mode 100755 index 000000000..98380974c --- /dev/null +++ b/vendor/k8s.io/kubernetes/hack/update-workspace-mirror.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Copyright 2018 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. + +set -o errexit +set -o nounset +set -o pipefail + +if [[ $# -ne 1 ]]; then + echo 'use "bazel run //hack:update-mirror"' + echo "(usage: $0 )" + exit 1 +fi + +BUCKET="gs://k8s-bazel-cache" + +gsutil acl get "${BUCKET}" > /dev/null + +tmpfile=$(mktemp bazel_workspace_mirror.XXXXXX) +trap "rm ${tmpfile}" EXIT +cat "$1" | while read url; do + echo "${url}" + if gsutil ls "${BUCKET}/${url}" &> /dev/null; then + echo present + else + echo missing + if curl -fLag "${url}" > "${tmpfile}"; then + gsutil cp -a public-read "${tmpfile}" "${BUCKET}/${url}" + fi + fi +done diff --git a/vendor/k8s.io/kubernetes/hack/update_owners.py b/vendor/k8s.io/kubernetes/hack/update_owners.py index 233f60086..43a7bdedc 100755 --- a/vendor/k8s.io/kubernetes/hack/update_owners.py +++ b/vendor/k8s.io/kubernetes/hack/update_owners.py @@ -17,10 +17,10 @@ import argparse import collections import csv -import re import json import os import random +import re import subprocess import sys import time diff --git a/vendor/k8s.io/kubernetes/hack/verify-all.sh b/vendor/k8s.io/kubernetes/hack/verify-all.sh index 45a9a571e..75ab1e9e9 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-all.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-all.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-api-groups.sh b/vendor/k8s.io/kubernetes/hack/verify-api-groups.sh index 88de8b7f6..275637301 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-api-groups.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-api-groups.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-api-reference-docs.sh b/vendor/k8s.io/kubernetes/hack/verify-api-reference-docs.sh index e41256f9c..afc2c79cc 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-api-reference-docs.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-api-reference-docs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-bazel.sh b/vendor/k8s.io/kubernetes/hack/verify-bazel.sh index 87c61cdc1..4e49cdf2a 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-bazel.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-bazel.sh @@ -31,7 +31,7 @@ fi # TODO(spxtr): Remove this line once Bazel is the only way to build. rm -f "${KUBE_ROOT}/pkg/generated/openapi/zz_generated.openapi.go" -_tmpdir="$(mktemp -d -t verify-bazel.XXXXXX)" +_tmpdir="$(kube::realpath $(mktemp -d -t verify-bazel.XXXXXX))" kube::util::trap_add "rm -rf ${_tmpdir}" EXIT _tmp_gopath="${_tmpdir}/go" @@ -40,9 +40,9 @@ mkdir -p "${_tmp_kuberoot}/.." cp -a "${KUBE_ROOT}" "${_tmp_kuberoot}/.." cd "${_tmp_kuberoot}" -GOPATH="${_tmp_gopath}" ./hack/update-bazel.sh +GOPATH="${_tmp_gopath}" PATH="${_tmp_gopath}/bin:${PATH}" ./hack/update-bazel.sh -diff=$(diff -Naupr "${KUBE_ROOT}" "${_tmp_kuberoot}" || true) +diff=$(diff -Naupr -x '_output' "${KUBE_ROOT}" "${_tmp_kuberoot}" || true) if [[ -n "${diff}" ]]; then echo "${diff}" >&2 diff --git a/vendor/k8s.io/kubernetes/hack/verify-boilerplate.sh b/vendor/k8s.io/kubernetes/hack/verify-boilerplate.sh index 149bf1171..cb45b73dd 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-boilerplate.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-boilerplate.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-cli-conventions.sh b/vendor/k8s.io/kubernetes/hack/verify-cli-conventions.sh index d768eb0a5..337bec95c 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-cli-conventions.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-cli-conventions.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # @@ -30,7 +30,7 @@ make -C "${KUBE_ROOT}" WHAT="${BINS[*]}" clicheck=$(kube::util::find-binary "clicheck") -if ! output=`$clicheck 2>&1` +if ! output=$($clicheck 2>&1) then echo "$output" echo diff --git a/vendor/k8s.io/kubernetes/hack/verify-cloudprovider-gce.sh b/vendor/k8s.io/kubernetes/hack/verify-cloudprovider-gce.sh index 1aae5aae4..c6b3bd89a 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-cloudprovider-gce.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-cloudprovider-gce.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-codegen.sh b/vendor/k8s.io/kubernetes/hack/verify-codegen.sh index 02b979c2f..3a5b69394 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-codegen.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-description.sh b/vendor/k8s.io/kubernetes/hack/verify-description.sh index 95bb06800..d35145f95 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-description.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-description.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # @@ -49,7 +49,7 @@ find_files() { } if [[ $# -eq 0 ]]; then - versioned_api_files=$(find_files | egrep "pkg/.[^/]*/((v.[^/]*)|unversioned)/types\.go") + versioned_api_files=$(find_files | egrep "pkg/.[^/]*/((v.[^/]*)|unversioned)/types\.go") || true else versioned_api_files="${*}" fi diff --git a/vendor/k8s.io/kubernetes/hack/verify-flags-underscore.py b/vendor/k8s.io/kubernetes/hack/verify-flags-underscore.py index 6839f643a..169f79449 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-flags-underscore.py +++ b/vendor/k8s.io/kubernetes/hack/verify-flags-underscore.py @@ -16,12 +16,10 @@ from __future__ import print_function -import json -import mmap +import argparse import os import re import sys -import argparse parser = argparse.ArgumentParser() parser.add_argument("filenames", help="list of files to check, all files if unspecified", nargs='*') diff --git a/vendor/k8s.io/kubernetes/hack/verify-generated-device-plugin.sh b/vendor/k8s.io/kubernetes/hack/verify-generated-device-plugin.sh index 7427a9811..817ffda36 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-generated-device-plugin.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-generated-device-plugin.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-generated-docs.sh b/vendor/k8s.io/kubernetes/hack/verify-generated-docs.sh index 9331343b1..d583abc05 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-generated-docs.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-generated-docs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-generated-files-remake.sh b/vendor/k8s.io/kubernetes/hack/verify-generated-files-remake.sh index c4b43415e..9c80a6bc0 100644 --- a/vendor/k8s.io/kubernetes/hack/verify-generated-files-remake.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-generated-files-remake.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-generated-files.sh b/vendor/k8s.io/kubernetes/hack/verify-generated-files.sh new file mode 100755 index 000000000..f43678068 --- /dev/null +++ b/vendor/k8s.io/kubernetes/hack/verify-generated-files.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# Copyright 2018 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. + +set -o errexit +set -o nounset +set -o pipefail + +export KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. +source "${KUBE_ROOT}/hack/lib/init.sh" + +kube::util::ensure_clean_working_dir + +_tmpdir="$(kube::realpath $(mktemp -d -t verify-generated-files.XXXXXX))" +kube::util::trap_add "rm -rf ${_tmpdir}" EXIT + +_tmp_gopath="${_tmpdir}/go" +_tmp_kuberoot="${_tmp_gopath}/src/k8s.io/kubernetes" +mkdir -p "${_tmp_kuberoot}/.." +cp -a "${KUBE_ROOT}" "${_tmp_kuberoot}/.." + +cd "${_tmp_kuberoot}" + +# clean out anything from the temp dir that's not checked in +git clean -ffxd +# regenerate any generated code +make generated_files + +diff=$(git diff --name-only) + +if [[ -n "${diff}" ]]; then + echo "!!! Generated code is out of date:" >&2 + echo "${diff}" >&2 + echo >&2 + echo "Please run make generated_files." >&2 + exit 1 +fi diff --git a/vendor/k8s.io/kubernetes/hack/verify-generated-kms.sh b/vendor/k8s.io/kubernetes/hack/verify-generated-kms.sh index 03738b52e..eeff02dbf 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-generated-kms.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-generated-kms.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-generated-kubelet-plugin-registration.sh b/vendor/k8s.io/kubernetes/hack/verify-generated-kubelet-plugin-registration.sh new file mode 100755 index 000000000..3dfffa8dc --- /dev/null +++ b/vendor/k8s.io/kubernetes/hack/verify-generated-kubelet-plugin-registration.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Copyright 2018 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. + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. +ERROR="Kubelet Plugin Registration api is out of date. Please run hack/update-generated-kubelet-plugin-registration.sh" +KUBELET_PLUGIN_REGISTRATION_ROOT="${KUBE_ROOT}/pkg/kubelet/apis/pluginregistration/v1alpha1/" + +source "${KUBE_ROOT}/hack/lib/protoc.sh" +kube::golang::setup_env + +function cleanup { + rm -rf ${KUBELET_PLUGIN_REGISTRATION_ROOT}/_tmp/ +} + +trap cleanup EXIT + +mkdir -p ${KUBELET_PLUGIN_REGISTRATION_ROOT}/_tmp +cp ${KUBELET_PLUGIN_REGISTRATION_ROOT}/api.pb.go ${KUBELET_PLUGIN_REGISTRATION_ROOT}/_tmp/ + +KUBE_VERBOSE=3 "${KUBE_ROOT}/hack/update-generated-kubelet-plugin-registration.sh" +kube::protoc::diff "${KUBELET_PLUGIN_REGISTRATION_ROOT}/api.pb.go" "${KUBELET_PLUGIN_REGISTRATION_ROOT}/_tmp/api.pb.go" ${ERROR} +echo "Generated Kubelet Plugin Registration api is up to date." diff --git a/vendor/k8s.io/kubernetes/hack/verify-generated-protobuf.sh b/vendor/k8s.io/kubernetes/hack/verify-generated-protobuf.sh index a57f0fe4d..a692687e2 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-generated-protobuf.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-generated-protobuf.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-generated-runtime.sh b/vendor/k8s.io/kubernetes/hack/verify-generated-runtime.sh index 3e1132547..6443cc4f9 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-generated-runtime.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-generated-runtime.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-generated-swagger-docs.sh b/vendor/k8s.io/kubernetes/hack/verify-generated-swagger-docs.sh index ef93c4e06..eec14769b 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-generated-swagger-docs.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-generated-swagger-docs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-godeps.sh b/vendor/k8s.io/kubernetes/hack/verify-godeps.sh index b03826e74..a7f46f99a 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-godeps.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-godeps.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -35,7 +35,7 @@ kube::util::ensure_godep_version if [[ -z ${TMP_GOPATH:-} ]]; then # Create a nice clean place to put our new godeps - _tmpdir="$(mktemp -d -t gopath.XXXXXX)" + _tmpdir="$(kube::realpath $(mktemp -d -t gopath.XXXXXX))" else # reuse what we might have saved previously _tmpdir="${TMP_GOPATH}" @@ -64,8 +64,9 @@ _kubetmp="${_kubetmp}/kubernetes" # Do all our work in the new GOPATH export GOPATH="${_tmpdir}" +export PATH="${GOPATH}/bin:${PATH}" -pushd "${_kubetmp}" 2>&1 > /dev/null +pushd "${_kubetmp}" > /dev/null 2>&1 # Restore the Godeps into our temp directory hack/godep-restore.sh @@ -78,11 +79,11 @@ pushd "${_kubetmp}" 2>&1 > /dev/null # Recreate the Godeps using the nice clean set we just downloaded hack/godep-save.sh -popd 2>&1 > /dev/null +popd > /dev/null 2>&1 ret=0 -pushd "${KUBE_ROOT}" 2>&1 > /dev/null +pushd "${KUBE_ROOT}" > /dev/null 2>&1 # Test for diffs if ! _out="$(diff -Naupr --ignore-matching-lines='^\s*\"GoVersion\":' --ignore-matching-line='^\s*\"GodepVersion\":' --ignore-matching-lines='^\s*\"Comment\":' Godeps/Godeps.json ${_kubetmp}/Godeps/Godeps.json)"; then echo "Your Godeps.json is different:" >&2 @@ -117,9 +118,9 @@ pushd "${KUBE_ROOT}" 2>&1 > /dev/null fi ret=1 fi -popd 2>&1 > /dev/null +popd > /dev/null 2>&1 -if [[ ${ret} > 0 ]]; then +if [[ ${ret} -gt 0 ]]; then exit ${ret} fi diff --git a/vendor/k8s.io/kubernetes/hack/verify-gofmt.sh b/vendor/k8s.io/kubernetes/hack/verify-gofmt.sh index 3ec0e61d6..ff8797d18 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-gofmt.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-gofmt.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-golint.sh b/vendor/k8s.io/kubernetes/hack/verify-golint.sh index 1b0b04430..0829f18ef 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-golint.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-golint.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-govet.sh b/vendor/k8s.io/kubernetes/hack/verify-govet.sh index 223821d08..edc0d314a 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-govet.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-govet.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-import-boss.sh b/vendor/k8s.io/kubernetes/hack/verify-import-boss.sh index 7e112a4ac..30681fbbd 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-import-boss.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-import-boss.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-imports.sh b/vendor/k8s.io/kubernetes/hack/verify-imports.sh index a845fa2a0..ba9951bda 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-imports.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-imports.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-linkcheck.sh b/vendor/k8s.io/kubernetes/hack/verify-linkcheck.sh index 69427f3ba..493c0f870 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-linkcheck.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-linkcheck.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-no-vendor-cycles.sh b/vendor/k8s.io/kubernetes/hack/verify-no-vendor-cycles.sh index 02fa8b294..e245f7695 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-no-vendor-cycles.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-no-vendor-cycles.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-openapi-spec.sh b/vendor/k8s.io/kubernetes/hack/verify-openapi-spec.sh index 08b1edcbe..0fa039664 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-openapi-spec.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-openapi-spec.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-pkg-names.sh b/vendor/k8s.io/kubernetes/hack/verify-pkg-names.sh index 8fbb09282..346607284 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-pkg-names.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-pkg-names.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-readonly-packages.sh b/vendor/k8s.io/kubernetes/hack/verify-readonly-packages.sh index babf558e8..87864a61a 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-readonly-packages.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-readonly-packages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-spelling.sh b/vendor/k8s.io/kubernetes/hack/verify-spelling.sh index fdd7ba9ef..27d92501d 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-spelling.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-spelling.sh @@ -20,15 +20,12 @@ set -o pipefail export KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. source "${KUBE_ROOT}/hack/lib/init.sh" +# Ensure that we find the binaries we build before anything else. +export GOBIN="${KUBE_OUTPUT_BINPATH}" +PATH="${GOBIN}:${PATH}" + # Install tools we need, but only from vendor/... -cd ${KUBE_ROOT} go install ./vendor/github.com/client9/misspell/cmd/misspell -if ! which misspell >/dev/null 2>&1; then - echo "Can't find misspell - is your GOPATH 'bin' in your PATH?" >&2 - echo " GOPATH: ${GOPATH}" >&2 - echo " PATH: ${PATH}" >&2 - exit 1 -fi # Spell checking # All the skipping files are defined in hack/.spelling_failures diff --git a/vendor/k8s.io/kubernetes/hack/verify-staging-godeps.sh b/vendor/k8s.io/kubernetes/hack/verify-staging-godeps.sh index 7177ac639..e984d164a 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-staging-godeps.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-staging-godeps.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-swagger-spec.sh b/vendor/k8s.io/kubernetes/hack/verify-swagger-spec.sh index 92ee2bcb6..864df660b 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-swagger-spec.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-swagger-spec.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-symbols.sh b/vendor/k8s.io/kubernetes/hack/verify-symbols.sh index aa5870a29..ebd09aab1 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-symbols.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-symbols.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-test-images.sh b/vendor/k8s.io/kubernetes/hack/verify-test-images.sh index 8c60fb435..7ef6a081f 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-test-images.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-test-images.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/hack/verify-typecheck.sh b/vendor/k8s.io/kubernetes/hack/verify-typecheck.sh index bd55f5929..b31ae3aea 100755 --- a/vendor/k8s.io/kubernetes/hack/verify-typecheck.sh +++ b/vendor/k8s.io/kubernetes/hack/verify-typecheck.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Kubernetes Authors. # @@ -25,9 +25,7 @@ kube::golang::verify_go_version cd "${KUBE_ROOT}" -if [[ ! -f test/e2e/generated/bindata.go ]]; then - make --no-print-directory -C "${KUBE_ROOT}" verify_generated_files -fi +make --no-print-directory -C "${KUBE_ROOT}" generated_files ret=0 go run test/typecheck/main.go "$@" || ret=$? diff --git a/vendor/k8s.io/kubernetes/pkg/BUILD b/vendor/k8s.io/kubernetes/pkg/BUILD index 037dbecae..b46fd1f6f 100644 --- a/vendor/k8s.io/kubernetes/pkg/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/BUILD @@ -22,7 +22,6 @@ filegroup( "//pkg/api/service:all-srcs", "//pkg/api/testapi:all-srcs", "//pkg/api/testing:all-srcs", - "//pkg/api/unversioned:all-srcs", "//pkg/api/v1/endpoints:all-srcs", "//pkg/api/v1/node:all-srcs", "//pkg/api/v1/pod:all-srcs", diff --git a/vendor/k8s.io/kubernetes/pkg/api/legacyscheme/BUILD b/vendor/k8s.io/kubernetes/pkg/api/legacyscheme/BUILD index 42136a953..0a8768895 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/legacyscheme/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/api/legacyscheme/BUILD @@ -6,8 +6,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/api/legacyscheme", visibility = ["//visibility:public"], deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/api/legacyscheme/scheme.go b/vendor/k8s.io/kubernetes/pkg/api/legacyscheme/scheme.go index 64c63a360..acfcc8f8e 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/legacyscheme/scheme.go +++ b/vendor/k8s.io/kubernetes/pkg/api/legacyscheme/scheme.go @@ -17,21 +17,10 @@ limitations under the License. package legacyscheme import ( - "os" - - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" ) -// GroupFactoryRegistry is the APIGroupFactoryRegistry (overlaps a bit with Registry, see comments in package for details) -var GroupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - -// Registry is an instance of an API registry. This is an interim step to start removing the idea of a global -// API registry. -var Registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) - // Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. // NOTE: If you are copying this file to start a new api group, STOP! Copy the // extensions group instead. This Scheme is special and should appear ONLY in diff --git a/vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util.go b/vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util.go index d36f7c0cd..d5a93667a 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util.go +++ b/vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util.go @@ -61,6 +61,10 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool { return false } } + case source.Cinder != nil: + if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Namespace, source.Cinder.SecretRef.Name, true /* kubeletVisible */) { + return false + } case source.FlexVolume != nil: if source.FlexVolume.SecretRef != nil { // previously persisted PV objects use claimRef namespace diff --git a/vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util_test.go b/vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util_test.go index e2d5a1527..ffa361cc9 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util_test.go @@ -58,6 +58,12 @@ func TestPVSecrets(t *testing.T) { CephFS: &api.CephFSPersistentVolumeSource{ SecretRef: &api.SecretReference{ Name: "Spec.PersistentVolumeSource.CephFS.SecretRef"}}}}}, + {Spec: api.PersistentVolumeSpec{ + PersistentVolumeSource: api.PersistentVolumeSource{ + Cinder: &api.CinderPersistentVolumeSource{ + SecretRef: &api.SecretReference{ + Name: "Spec.PersistentVolumeSource.Cinder.SecretRef", + Namespace: "cinder"}}}}}, {Spec: api.PersistentVolumeSpec{ ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"}, PersistentVolumeSource: api.PersistentVolumeSource{ @@ -159,6 +165,7 @@ func TestPVSecrets(t *testing.T) { expectedSecretPaths := sets.NewString( "Spec.PersistentVolumeSource.AzureFile.SecretName", "Spec.PersistentVolumeSource.CephFS.SecretRef", + "Spec.PersistentVolumeSource.Cinder.SecretRef", "Spec.PersistentVolumeSource.FlexVolume.SecretRef", "Spec.PersistentVolumeSource.RBD.SecretRef", "Spec.PersistentVolumeSource.ScaleIO.SecretRef", @@ -195,6 +202,8 @@ func TestPVSecrets(t *testing.T) { "claimrefns/Spec.PersistentVolumeSource.CephFS.SecretRef", "cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef", + "cinder/Spec.PersistentVolumeSource.Cinder.SecretRef", + "claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef", "flexns/Spec.PersistentVolumeSource.FlexVolume.SecretRef", diff --git a/vendor/k8s.io/kubernetes/pkg/api/pod/util.go b/vendor/k8s.io/kubernetes/pkg/api/pod/util.go index 0d17feef3..c46285542 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/pod/util.go +++ b/vendor/k8s.io/kubernetes/pkg/api/pod/util.go @@ -58,6 +58,10 @@ func VisitPodSecretNames(pod *api.Pod, visitor Visitor) bool { if source.CephFS.SecretRef != nil && !visitor(source.CephFS.SecretRef.Name) { return false } + case source.Cinder != nil: + if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Name) { + return false + } case source.FlexVolume != nil: if source.FlexVolume.SecretRef != nil && !visitor(source.FlexVolume.SecretRef.Name) { return false diff --git a/vendor/k8s.io/kubernetes/pkg/api/pod/util_test.go b/vendor/k8s.io/kubernetes/pkg/api/pod/util_test.go index 1c7eb328f..b29f82201 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/pod/util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/api/pod/util_test.go @@ -64,6 +64,10 @@ func TestPodSecrets(t *testing.T) { CephFS: &api.CephFSVolumeSource{ SecretRef: &api.LocalObjectReference{ Name: "Spec.Volumes[*].VolumeSource.CephFS.SecretRef"}}}}, { + VolumeSource: api.VolumeSource{ + Cinder: &api.CinderVolumeSource{ + SecretRef: &api.LocalObjectReference{ + Name: "Spec.Volumes[*].VolumeSource.Cinder.SecretRef"}}}}, { VolumeSource: api.VolumeSource{ FlexVolume: &api.FlexVolumeSource{ SecretRef: &api.LocalObjectReference{ @@ -118,6 +122,7 @@ func TestPodSecrets(t *testing.T) { "Spec.InitContainers[*].Env[*].ValueFrom.SecretKeyRef", "Spec.Volumes[*].VolumeSource.AzureFile.SecretName", "Spec.Volumes[*].VolumeSource.CephFS.SecretRef", + "Spec.Volumes[*].VolumeSource.Cinder.SecretRef", "Spec.Volumes[*].VolumeSource.FlexVolume.SecretRef", "Spec.Volumes[*].VolumeSource.Projected.Sources[*].Secret", "Spec.Volumes[*].VolumeSource.RBD.SecretRef", @@ -314,7 +319,7 @@ func TestDropAlphaVolumeDevices(t *testing.T) { t.Error("VolumeDevices in Container should not have been dropped based on feature-gate") } if testPod.Spec.InitContainers[0].VolumeDevices == nil { - t.Error("VolumeDevices in Container should not have been dropped based on feature-gate") + t.Error("VolumeDevices in InitContainers should not have been dropped based on feature-gate") } } diff --git a/vendor/k8s.io/kubernetes/pkg/api/testapi/BUILD b/vendor/k8s.io/kubernetes/pkg/api/testapi/BUILD index 6c6f853f5..3e33f7c7a 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testapi/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/api/testapi/BUILD @@ -48,7 +48,6 @@ go_library( "//pkg/apis/settings/install:go_default_library", "//pkg/apis/storage:go_default_library", "//pkg/apis/storage/install:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta: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/recognizer:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/api/testapi/testapi.go b/vendor/k8s.io/kubernetes/pkg/api/testapi/testapi.go index c1232e91c..53adb8ec3 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testapi/testapi.go +++ b/vendor/k8s.io/kubernetes/pkg/api/testapi/testapi.go @@ -30,7 +30,6 @@ import ( "reflect" "strings" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer/recognizer" @@ -75,23 +74,16 @@ import ( ) var ( - Groups = make(map[string]TestGroup) - Default TestGroup - Authorization TestGroup - Autoscaling TestGroup - Batch TestGroup - Extensions TestGroup - Events TestGroup - Apps TestGroup - Policy TestGroup - Rbac TestGroup - Certificates TestGroup - Scheduling TestGroup - Settings TestGroup - Storage TestGroup - ImagePolicy TestGroup - Admission TestGroup - Networking TestGroup + Groups = make(map[string]TestGroup) + Default TestGroup + Autoscaling TestGroup + Batch TestGroup + Extensions TestGroup + Apps TestGroup + Policy TestGroup + Rbac TestGroup + Storage TestGroup + Admission TestGroup serializer runtime.SerializerInfo storageSerializer runtime.SerializerInfo @@ -99,9 +91,6 @@ var ( type TestGroup struct { externalGroupVersion schema.GroupVersion - internalGroupVersion schema.GroupVersion - internalTypes map[string]reflect.Type - externalTypes map[string]reflect.Type } func init() { @@ -140,32 +129,22 @@ func init() { panic(fmt.Sprintf("Error parsing groupversion %v: %v", gvString, err)) } - internalGroupVersion := schema.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal} Groups[groupVersion.Group] = TestGroup{ externalGroupVersion: groupVersion, - internalGroupVersion: internalGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(internalGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(groupVersion), } } } if _, ok := Groups[api.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: api.GroupName, Version: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: api.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(api.GroupName)[0].Version} Groups[api.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: api.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(api.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[extensions.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: extensions.GroupName, Version: legacyscheme.Registry.GroupOrDie(extensions.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: extensions.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(extensions.GroupName)[0].Version} Groups[extensions.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: extensions.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(extensions.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[autoscaling.GroupName]; !ok { @@ -176,12 +155,9 @@ func init() { } internalTypes[k] = t } - externalGroupVersion := schema.GroupVersion{Group: autoscaling.GroupName, Version: legacyscheme.Registry.GroupOrDie(autoscaling.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: autoscaling.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(autoscaling.GroupName)[0].Version} Groups[autoscaling.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: extensions.SchemeGroupVersion, - internalTypes: internalTypes, - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[autoscaling.GroupName+"IntraGroup"]; !ok { @@ -192,138 +168,93 @@ func init() { break } } - externalGroupVersion := schema.GroupVersion{Group: autoscaling.GroupName, Version: legacyscheme.Registry.GroupOrDie(autoscaling.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: autoscaling.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(autoscaling.GroupName)[0].Version} Groups[autoscaling.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: autoscaling.SchemeGroupVersion, - internalTypes: internalTypes, - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[batch.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: batch.GroupName, Version: legacyscheme.Registry.GroupOrDie(batch.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: batch.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(batch.GroupName)[0].Version} Groups[batch.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: batch.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(batch.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[apps.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: apps.GroupName, Version: legacyscheme.Registry.GroupOrDie(apps.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: apps.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(apps.GroupName)[0].Version} Groups[apps.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: apps.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(apps.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[policy.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: policy.GroupName, Version: legacyscheme.Registry.GroupOrDie(policy.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: policy.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(policy.GroupName)[0].Version} Groups[policy.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: policy.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(policy.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[rbac.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: rbac.GroupName, Version: legacyscheme.Registry.GroupOrDie(rbac.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: rbac.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(rbac.GroupName)[0].Version} Groups[rbac.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: rbac.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(rbac.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[scheduling.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: scheduling.GroupName, Version: legacyscheme.Registry.GroupOrDie(scheduling.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: scheduling.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(scheduling.GroupName)[0].Version} Groups[scheduling.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: scheduling.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(scheduling.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[settings.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: settings.GroupName, Version: legacyscheme.Registry.GroupOrDie(settings.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: settings.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(settings.GroupName)[0].Version} Groups[settings.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: settings.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(settings.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[storage.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: storage.GroupName, Version: legacyscheme.Registry.GroupOrDie(storage.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: storage.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(storage.GroupName)[0].Version} Groups[storage.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: storage.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(storage.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[certificates.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: certificates.GroupName, Version: legacyscheme.Registry.GroupOrDie(certificates.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: certificates.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(certificates.GroupName)[0].Version} Groups[certificates.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: certificates.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(certificates.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[imagepolicy.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: imagepolicy.GroupName, Version: legacyscheme.Registry.GroupOrDie(imagepolicy.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: imagepolicy.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(imagepolicy.GroupName)[0].Version} Groups[imagepolicy.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: imagepolicy.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(imagepolicy.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[authorization.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: authorization.GroupName, Version: legacyscheme.Registry.GroupOrDie(authorization.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: authorization.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(authorization.GroupName)[0].Version} Groups[authorization.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: authorization.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(authorization.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[admissionregistration.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: admissionregistration.GroupName, Version: legacyscheme.Registry.GroupOrDie(admissionregistration.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: admissionregistration.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(admissionregistration.GroupName)[0].Version} Groups[admissionregistration.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: admissionregistration.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(admissionregistration.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[admission.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: admission.GroupName, Version: legacyscheme.Registry.GroupOrDie(admission.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: admission.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(admission.GroupName)[0].Version} Groups[admission.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: admission.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(admission.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[networking.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: networking.GroupName, Version: legacyscheme.Registry.GroupOrDie(networking.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: networking.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(networking.GroupName)[0].Version} Groups[networking.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: networking.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(networking.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[events.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: events.GroupName, Version: legacyscheme.Registry.GroupOrDie(events.GroupName).GroupVersion.Version} + externalGroupVersion := schema.GroupVersion{Group: events.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(events.GroupName)[0].Version} Groups[events.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, - internalGroupVersion: events.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(events.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), } } @@ -332,21 +263,10 @@ func init() { Batch = Groups[batch.GroupName] Apps = Groups[apps.GroupName] Policy = Groups[policy.GroupName] - Certificates = Groups[certificates.GroupName] Extensions = Groups[extensions.GroupName] - Events = Groups[events.GroupName] Rbac = Groups[rbac.GroupName] - Scheduling = Groups[scheduling.GroupName] - Settings = Groups[settings.GroupName] Storage = Groups[storage.GroupName] - ImagePolicy = Groups[imagepolicy.GroupName] - Authorization = Groups[authorization.GroupName] Admission = Groups[admission.GroupName] - Networking = Groups[networking.GroupName] -} - -func (g TestGroup) ContentConfig() (string, *schema.GroupVersion, runtime.Codec) { - return "application/json", g.GroupVersion(), g.Codec() } func (g TestGroup) GroupVersion() *schema.GroupVersion { @@ -354,22 +274,6 @@ func (g TestGroup) GroupVersion() *schema.GroupVersion { return ©OfGroupVersion } -// InternalGroupVersion returns the group,version used to identify the internal -// types for this API -func (g TestGroup) InternalGroupVersion() schema.GroupVersion { - return g.internalGroupVersion -} - -// InternalTypes returns a map of internal API types' kind names to their Go types. -func (g TestGroup) InternalTypes() map[string]reflect.Type { - return g.internalTypes -} - -// ExternalTypes returns a map of external API types' kind names to their Go types. -func (g TestGroup) ExternalTypes() map[string]reflect.Type { - return g.externalTypes -} - // Codec returns the codec for the API version to test against, as set by the // KUBE_TEST_API_TYPE env var. func (g TestGroup) Codec() runtime.Codec { @@ -379,11 +283,6 @@ func (g TestGroup) Codec() runtime.Codec { return legacyscheme.Codecs.CodecForVersions(serializer.Serializer, legacyscheme.Codecs.UniversalDeserializer(), schema.GroupVersions{g.externalGroupVersion}, nil) } -// NegotiatedSerializer returns the negotiated serializer for the server. -func (g TestGroup) NegotiatedSerializer() runtime.NegotiatedSerializer { - return legacyscheme.Codecs -} - func StorageMediaType() string { return os.Getenv("KUBE_TEST_API_STORAGE_TYPE") } @@ -407,26 +306,6 @@ func (g TestGroup) StorageCodec() runtime.Codec { return legacyscheme.Codecs.CodecForVersions(s, ds, schema.GroupVersions{g.externalGroupVersion}, nil) } -// Converter returns the legacyscheme.Scheme for the API version to test against, as set by the -// KUBE_TEST_API env var. -func (g TestGroup) Converter() runtime.ObjectConvertor { - interfaces, err := legacyscheme.Registry.GroupOrDie(g.externalGroupVersion.Group).InterfacesFor(g.externalGroupVersion) - if err != nil { - panic(err) - } - return interfaces.ObjectConvertor -} - -// MetadataAccessor returns the MetadataAccessor for the API version to test against, -// as set by the KUBE_TEST_API env var. -func (g TestGroup) MetadataAccessor() meta.MetadataAccessor { - interfaces, err := legacyscheme.Registry.GroupOrDie(g.externalGroupVersion.Group).InterfacesFor(g.externalGroupVersion) - if err != nil { - panic(err) - } - return interfaces.MetadataAccessor -} - // SelfLink returns a self link that will appear to be for the version Version(). // 'resource' should be the resource path, e.g. "pods" for the Pod type. 'name' should be // empty for lists. @@ -493,51 +372,3 @@ func (g TestGroup) SubResourcePath(resource, namespace, name, sub string) string return path } - -// RESTMapper returns RESTMapper in legacyscheme.Registry. -func (g TestGroup) RESTMapper() meta.RESTMapper { - return legacyscheme.Registry.RESTMapper() -} - -// ExternalGroupVersions returns all external group versions allowed for the server. -func ExternalGroupVersions() schema.GroupVersions { - versions := []schema.GroupVersion{} - for _, g := range Groups { - gv := g.GroupVersion() - versions = append(versions, *gv) - } - return versions -} - -// GetCodecForObject gets codec based on runtime.Object -func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) { - kinds, _, err := legacyscheme.Scheme.ObjectKinds(obj) - if err != nil { - return nil, fmt.Errorf("unexpected encoding error: %v", err) - } - kind := kinds[0] - - for _, group := range Groups { - if group.GroupVersion().Group != kind.Group { - continue - } - - if legacyscheme.Scheme.Recognizes(kind) { - return group.Codec(), nil - } - } - // Codec used for unversioned types - if legacyscheme.Scheme.Recognizes(kind) { - serializer, ok := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) - if !ok { - return nil, fmt.Errorf("no serializer registered for json") - } - return serializer.Serializer, nil - } - return nil, fmt.Errorf("unexpected kind: %v", kind) -} - -// NewTestGroup creates a new TestGroup. -func NewTestGroup(external, internal schema.GroupVersion, internalTypes map[string]reflect.Type, externalTypes map[string]reflect.Type) TestGroup { - return TestGroup{external, internal, internalTypes, externalTypes} -} diff --git a/vendor/k8s.io/kubernetes/pkg/api/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/api/testing/BUILD index 5b7ba9b52..677c51b6d 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testing/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/api/testing/BUILD @@ -96,6 +96,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/conversion: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/json: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", diff --git a/vendor/k8s.io/kubernetes/pkg/api/testing/compat/BUILD b/vendor/k8s.io/kubernetes/pkg/api/testing/compat/BUILD index b08e25c8d..a5890df53 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testing/compat/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/api/testing/compat/BUILD @@ -11,7 +11,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/api/testing/compat", deps = [ "//pkg/api/legacyscheme:go_default_library", - "//pkg/printers: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/util/validation/field:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/api/testing/compat/compatibility_tester.go b/vendor/k8s.io/kubernetes/pkg/api/testing/compat/compatibility_tester.go index 5fbdc01e3..68b4bc9a8 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testing/compat/compatibility_tester.go +++ b/vendor/k8s.io/kubernetes/pkg/api/testing/compat/compatibility_tester.go @@ -19,7 +19,6 @@ package compat import ( "encoding/json" "fmt" - "os" "reflect" "regexp" "strconv" @@ -30,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/printers" ) // Based on: https://github.com/openshift/origin/blob/master/pkg/api/compatibility_test.go @@ -72,14 +70,11 @@ func TestCompatibility( t.Fatalf("Unexpected error: %v", err) } - hasError := false for k, expectedValue := range expectedKeys { keys := strings.Split(k, ".") if actualValue, ok, err := getJSONValue(generic, keys...); err != nil || !ok { t.Errorf("Unexpected error for %s: %v", k, err) - hasError = true } else if !reflect.DeepEqual(expectedValue, fmt.Sprintf("%v", actualValue)) { - hasError = true t.Errorf("Unexpected value for %v: expected %v, got %v", k, expectedValue, actualValue) } } @@ -89,14 +84,17 @@ func TestCompatibility( actualValue, ok, err := getJSONValue(generic, keys...) if err == nil || ok { t.Errorf("Unexpected value found for key %s: %v", absentKey, actualValue) - hasError = true } } - if hasError { - printer := &printers.JSONPrinter{} - printer.PrintObj(obj, os.Stdout) - t.Logf("2: Encoded value: %#v", string(output)) + if t.Failed() { + data, err := json.MarshalIndent(obj, "", " ") + if err != nil { + t.Log(err) + } else { + t.Log(string(data)) + } + t.Logf("2: Encoded value: %v", string(output)) } } diff --git a/vendor/k8s.io/kubernetes/pkg/api/testing/conversion_test.go b/vendor/k8s.io/kubernetes/pkg/api/testing/conversion_test.go index 3cb174fcd..e572a6e78 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testing/conversion_test.go +++ b/vendor/k8s.io/kubernetes/pkg/api/testing/conversion_test.go @@ -24,6 +24,7 @@ import ( apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/testing/fuzzer" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" @@ -46,11 +47,11 @@ func BenchmarkPodConversion(b *testing.B) { scheme := legacyscheme.Scheme for i := 0; i < b.N; i++ { pod := &items[i%width] - versionedObj, err := scheme.UnsafeConvertToVersion(pod, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion) + versionedObj, err := scheme.UnsafeConvertToVersion(pod, schema.GroupVersion{Group: "", Version: "v1"}) if err != nil { b.Fatalf("Conversion error: %v", err) } - if _, err = scheme.UnsafeConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion()); err != nil { + if _, err = scheme.UnsafeConvertToVersion(versionedObj, schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal}); err != nil { b.Fatalf("Conversion error: %v", err) } } @@ -70,11 +71,11 @@ func BenchmarkNodeConversion(b *testing.B) { var result *api.Node b.ResetTimer() for i := 0; i < b.N; i++ { - versionedObj, err := scheme.UnsafeConvertToVersion(&node, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion) + versionedObj, err := scheme.UnsafeConvertToVersion(&node, schema.GroupVersion{Group: "", Version: "v1"}) if err != nil { b.Fatalf("Conversion error: %v", err) } - obj, err := scheme.UnsafeConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion()) + obj, err := scheme.UnsafeConvertToVersion(versionedObj, schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal}) if err != nil { b.Fatalf("Conversion error: %v", err) } @@ -100,11 +101,11 @@ func BenchmarkReplicationControllerConversion(b *testing.B) { var result *api.ReplicationController b.ResetTimer() for i := 0; i < b.N; i++ { - versionedObj, err := scheme.UnsafeConvertToVersion(&replicationController, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion) + versionedObj, err := scheme.UnsafeConvertToVersion(&replicationController, schema.GroupVersion{Group: "", Version: "v1"}) if err != nil { b.Fatalf("Conversion error: %v", err) } - obj, err := scheme.UnsafeConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion()) + obj, err := scheme.UnsafeConvertToVersion(versionedObj, schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal}) if err != nil { b.Fatalf("Conversion error: %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/api/testing/copy_test.go b/vendor/k8s.io/kubernetes/pkg/api/testing/copy_test.go index 103246bb3..c8a7891e6 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testing/copy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/api/testing/copy_test.go @@ -26,16 +26,15 @@ import ( "k8s.io/apimachinery/pkg/api/testing/fuzzer" "k8s.io/apimachinery/pkg/api/testing/roundtrip" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/api/testapi" - api "k8s.io/kubernetes/pkg/apis/core" ) func TestDeepCopyApiObjects(t *testing.T) { for i := 0; i < *roundtrip.FuzzIters; i++ { - for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion} { + for _, version := range []schema.GroupVersion{{Group: "", Version: runtime.APIVersionInternal}, {Group: "", Version: "v1"}} { f := fuzzer.FuzzerFor(FuzzerFuncs, rand.NewSource(rand.Int63()), legacyscheme.Codecs) for kind := range legacyscheme.Scheme.KnownTypes(version) { doDeepCopyTest(t, version.WithKind(kind), f) @@ -79,7 +78,7 @@ func doDeepCopyTest(t *testing.T, kind schema.GroupVersionKind, f *fuzz.Fuzzer) func TestDeepCopySingleType(t *testing.T) { for i := 0; i < *roundtrip.FuzzIters; i++ { - for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion} { + for _, version := range []schema.GroupVersion{{Group: "", Version: runtime.APIVersionInternal}, {Group: "", Version: "v1"}} { f := fuzzer.FuzzerFor(FuzzerFuncs, rand.NewSource(rand.Int63()), legacyscheme.Codecs) doDeepCopyTest(t, version.WithKind("Pod"), f) } diff --git a/vendor/k8s.io/kubernetes/pkg/api/testing/defaulting_test.go b/vendor/k8s.io/kubernetes/pkg/api/testing/defaulting_test.go index 4ac2d1c5d..0dfe70959 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testing/defaulting_test.go +++ b/vendor/k8s.io/kubernetes/pkg/api/testing/defaulting_test.go @@ -155,7 +155,7 @@ func TestDefaulting(t *testing.T) { c.FuzzNoCustom(s) s.MatchExpressions = nil // need to fuzz this specially }, - func(s *apiv1.ListOptions, c fuzz.Continue) { + func(s *metav1.ListOptions, c fuzz.Continue) { c.FuzzNoCustom(s) s.LabelSelector = "" // need to fuzz requirement strings specially s.FieldSelector = "" // need to fuzz requirement strings specially diff --git a/vendor/k8s.io/kubernetes/pkg/api/testing/meta_test.go b/vendor/k8s.io/kubernetes/pkg/api/testing/meta_test.go index d7a62798c..384ad2906 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testing/meta_test.go +++ b/vendor/k8s.io/kubernetes/pkg/api/testing/meta_test.go @@ -30,7 +30,7 @@ import ( var _ metav1.Object = &metav1.ObjectMeta{} func TestAccessorImplementations(t *testing.T) { - for _, gv := range legacyscheme.Registry.EnabledVersions() { + for _, gv := range legacyscheme.Scheme.PrioritizedVersionsAllGroups() { internalGV := schema.GroupVersion{Group: gv.Group, Version: runtime.APIVersionInternal} for _, gv := range []schema.GroupVersion{gv, internalGV} { for kind, knownType := range legacyscheme.Scheme.KnownTypes(gv) { diff --git a/vendor/k8s.io/kubernetes/pkg/api/testing/serialization_test.go b/vendor/k8s.io/kubernetes/pkg/api/testing/serialization_test.go index 36b96f23c..cccccedb8 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testing/serialization_test.go +++ b/vendor/k8s.io/kubernetes/pkg/api/testing/serialization_test.go @@ -37,6 +37,7 @@ import ( "k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/apimachinery/pkg/runtime/serializer/streaming" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/sets" @@ -89,7 +90,7 @@ func TestSetControllerConversion(t *testing.T) { extGroup := testapi.Extensions defaultGroup := testapi.Default - fuzzInternalObject(t, extGroup.InternalGroupVersion(), rs, rand.Int63()) + fuzzInternalObject(t, schema.GroupVersion{Group: "extensions", Version: runtime.APIVersionInternal}, rs, rand.Int63()) // explicitly set the selector to something that is convertible to old-style selectors // (since normally we'll fuzz the selectors with things that aren't convertible) @@ -299,6 +300,9 @@ func TestObjectWatchFraming(t *testing.T) { f := fuzzer.FuzzerFor(FuzzerFuncs, rand.NewSource(benchmarkSeed), legacyscheme.Codecs) secret := &api.Secret{} f.Fuzz(secret) + if secret.Data == nil { + secret.Data = map[string][]byte{} + } 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) @@ -557,9 +561,10 @@ func BenchmarkDecodeIntoJSONCodecGenConfigFast(b *testing.B) { b.StopTimer() } -// BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary -// provides a baseline for JSON decode performance -// with jsoniter.ConfigCompatibleWithStandardLibrary +// BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary provides a +// baseline for JSON decode performance with +// jsoniter.ConfigCompatibleWithStandardLibrary, but with case sensitivity set +// to true func BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary(b *testing.B) { kcodec := testapi.Default.Codec() items := benchmarkItems(b) @@ -574,9 +579,10 @@ func BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary(b *testi } b.ResetTimer() + iter := k8s_json.CaseSensitiveJsonIterator() for i := 0; i < b.N; i++ { obj := v1.Pod{} - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(encoded[i%width], &obj); err != nil { + if err := iter.Unmarshal(encoded[i%width], &obj); err != nil { b.Fatal(err) } } diff --git a/vendor/k8s.io/kubernetes/pkg/api/testing/unstructured_test.go b/vendor/k8s.io/kubernetes/pkg/api/testing/unstructured_test.go index 005b5d4a9..7e991878a 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/testing/unstructured_test.go +++ b/vendor/k8s.io/kubernetes/pkg/api/testing/unstructured_test.go @@ -30,6 +30,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metaunstruct "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/json" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -37,11 +38,11 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" ) -func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) { +func doRoundTrip(t *testing.T, internalVersion schema.GroupVersion, externalVersion schema.GroupVersion, 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 := legacyscheme.Scheme.New(group.InternalGroupVersion().WithKind(kind)) + internalObj, err := legacyscheme.Scheme.New(internalVersion.WithKind(kind)) if err != nil { t.Fatalf("Couldn't create internal object %v: %v", kind, err) } @@ -62,7 +63,7 @@ func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) { }, ).Fuzz(internalObj) - item, err := legacyscheme.Scheme.New(group.GroupVersion().WithKind(kind)) + item, err := legacyscheme.Scheme.New(externalVersion.WithKind(kind)) if err != nil { t.Fatalf("Couldn't create external object %v: %v", kind, err) } @@ -118,13 +119,13 @@ func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) { func TestRoundTrip(t *testing.T) { for groupKey, group := range testapi.Groups { - for kind := range group.ExternalTypes() { + for kind := range legacyscheme.Scheme.KnownTypes(*group.GroupVersion()) { if nonRoundTrippableTypes.Has(kind) { continue } t.Logf("Testing: %v in %v", kind, groupKey) for i := 0; i < 50; i++ { - doRoundTrip(t, group, kind) + doRoundTrip(t, schema.GroupVersion{Group: groupKey, Version: runtime.APIVersionInternal}, *group.GroupVersion(), kind) if t.Failed() { break } @@ -135,7 +136,7 @@ func TestRoundTrip(t *testing.T) { func TestRoundTripWithEmptyCreationTimestamp(t *testing.T) { for groupKey, group := range testapi.Groups { - for kind := range group.ExternalTypes() { + for kind := range legacyscheme.Scheme.KnownTypes(*group.GroupVersion()) { if nonRoundTrippableTypes.Has(kind) { continue } diff --git a/vendor/k8s.io/kubernetes/pkg/api/unversioned/BUILD b/vendor/k8s.io/kubernetes/pkg/api/unversioned/BUILD deleted file mode 100644 index c0d661e8f..000000000 --- a/vendor/k8s.io/kubernetes/pkg/api/unversioned/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "duration.go", - "time.go", - "types.go", - ], - importpath = "k8s.io/kubernetes/pkg/api/unversioned", - deps = ["//vendor/github.com/google/gofuzz:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/api/unversioned/duration.go b/vendor/k8s.io/kubernetes/pkg/api/unversioned/duration.go deleted file mode 100644 index 6b9a4371e..000000000 --- a/vendor/k8s.io/kubernetes/pkg/api/unversioned/duration.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -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 unversioned - -import ( - "encoding/json" - "time" -) - -// Duration is a wrapper around time.Duration which supports correct -// marshaling to YAML and JSON. In particular, it marshals into strings, which -// can be used as map keys in json. -type Duration struct { - time.Duration `protobuf:"-"` -} - -// UnmarshalJSON implements the json.Unmarshaller interface. -func (d *Duration) UnmarshalJSON(b []byte) error { - var str string - json.Unmarshal(b, &str) - - pd, err := time.ParseDuration(str) - if err != nil { - return err - } - d.Duration = pd - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (d Duration) MarshalJSON() ([]byte, error) { - return json.Marshal(d.Duration.String()) -} diff --git a/vendor/k8s.io/kubernetes/pkg/api/unversioned/time.go b/vendor/k8s.io/kubernetes/pkg/api/unversioned/time.go deleted file mode 100644 index 34da5ba39..000000000 --- a/vendor/k8s.io/kubernetes/pkg/api/unversioned/time.go +++ /dev/null @@ -1,172 +0,0 @@ -/* -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 unversioned - -import ( - "encoding/json" - "time" - - "github.com/google/gofuzz" -) - -// Time is a wrapper around time.Time which supports correct -// marshaling to YAML and JSON. Wrappers are provided for many -// of the factory methods that the time package offers. -type Time struct { - time.Time `protobuf:"-"` -} - -// DeepCopyInto creates a deep-copy of the Time value. The underlying time.Time -// type is effectively immutable in the time API, so it is safe to -// copy-by-assign, despite the presence of (unexported) Pointer fields. -func (t *Time) DeepCopyInto(out *Time) { - *out = *t -} - -// String returns the representation of the time. -func (t Time) String() string { - return t.Time.String() -} - -// NewTime returns a wrapped instance of the provided time -func NewTime(time time.Time) Time { - return Time{time} -} - -// Date returns the Time corresponding to the supplied parameters -// by wrapping time.Date. -func Date(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) Time { - return Time{time.Date(year, month, day, hour, min, sec, nsec, loc)} -} - -// Now returns the current local time. -func Now() Time { - return Time{time.Now()} -} - -// IsZero returns true if the value is nil or time is zero. -func (t *Time) IsZero() bool { - if t == nil { - return true - } - return t.Time.IsZero() -} - -// Before reports whether the time instant t is before u. -func (t Time) Before(u Time) bool { - return t.Time.Before(u.Time) -} - -// Equal reports whether the time instant t is equal to u. -func (t Time) Equal(u Time) bool { - return t.Time.Equal(u.Time) -} - -// Unix returns the local time corresponding to the given Unix time -// by wrapping time.Unix. -func Unix(sec int64, nsec int64) Time { - return Time{time.Unix(sec, nsec)} -} - -// Rfc3339Copy returns a copy of the Time at second-level precision. -func (t Time) Rfc3339Copy() Time { - copied, _ := time.Parse(time.RFC3339, t.Format(time.RFC3339)) - return Time{copied} -} - -// UnmarshalJSON implements the json.Unmarshaller interface. -func (t *Time) UnmarshalJSON(b []byte) error { - if len(b) == 4 && string(b) == "null" { - t.Time = time.Time{} - return nil - } - - var str string - json.Unmarshal(b, &str) - - pt, err := time.Parse(time.RFC3339, str) - if err != nil { - return err - } - - t.Time = pt.Local() - return nil -} - -// UnmarshalQueryParameter converts from a URL query parameter value to an object -func (t *Time) UnmarshalQueryParameter(str string) error { - if len(str) == 0 { - t.Time = time.Time{} - return nil - } - // Tolerate requests from older clients that used JSON serialization to build query params - if len(str) == 4 && str == "null" { - t.Time = time.Time{} - return nil - } - - pt, err := time.Parse(time.RFC3339, str) - if err != nil { - return err - } - - t.Time = pt.Local() - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (t Time) MarshalJSON() ([]byte, error) { - if t.IsZero() { - // Encode unset/nil objects as JSON's "null". - return []byte("null"), nil - } - - return json.Marshal(t.UTC().Format(time.RFC3339)) -} - -// OpenAPISchemaType is used by the kube-openapi generator when constructing -// the OpenAPI spec of this type. -// -// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators -func (_ Time) OpenAPISchemaType() []string { return []string{"string"} } - -// OpenAPISchemaFormat is used by the kube-openapi generator when constructing -// the OpenAPI spec of this type. -func (_ Time) OpenAPISchemaFormat() string { return "date-time" } - -// MarshalQueryParameter converts to a URL query parameter value -func (t Time) MarshalQueryParameter() (string, error) { - if t.IsZero() { - // Encode unset/nil objects as an empty string - return "", nil - } - - return t.UTC().Format(time.RFC3339), nil -} - -// Fuzz satisfies fuzz.Interface. -func (t *Time) Fuzz(c fuzz.Continue) { - if t == nil { - return - } - // Allow for about 1000 years of randomness. Leave off nanoseconds - // because JSON doesn't represent them so they can't round-trip - // properly. - t.Time = time.Unix(c.Rand.Int63n(1000*365*24*60*60), 0) -} - -var _ fuzz.Interface = &Time{} diff --git a/vendor/k8s.io/kubernetes/pkg/api/unversioned/types.go b/vendor/k8s.io/kubernetes/pkg/api/unversioned/types.go deleted file mode 100644 index 61137725a..000000000 --- a/vendor/k8s.io/kubernetes/pkg/api/unversioned/types.go +++ /dev/null @@ -1,60 +0,0 @@ -/* -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 unversioned is deprecated and has been replaced with pkg/apis/meta/v1 -// -// DEPRECATED - Do not reference or add types to this package, it will be removed -// once Heapster is updated to use pkg/apis/meta/v1. -package unversioned - -// TypeMeta describes an individual object in an API response or request -// with strings representing the type of the object and its API schema version. -// Structures that are versioned or persisted should inline TypeMeta. -type TypeMeta struct { - // Kind is a string value representing the REST resource this object represents. - // Servers may infer this from the endpoint the client submits requests to. - // Cannot be updated. - // In CamelCase. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"` - - // APIVersion defines the versioned schema of this representation of an object. - // Servers should convert recognized schemas to the latest internal value, and - // may reject unrecognized values. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources - // +optional - APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"` -} - -// ListMeta describes metadata that synthetic resources must have, including lists and -// various status objects. A resource may have only one of {ObjectMeta, ListMeta}. -type ListMeta struct { - // SelfLink is a URL representing this object. - // Populated by the system. - // Read-only. - // +optional - SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,1,opt,name=selfLink"` - - // String that identifies the server's internal version of this object that - // can be used by clients to determine when objects have changed. - // Value must be treated as opaque by clients and passed unmodified back to the server. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency - // +optional - ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,2,opt,name=resourceVersion"` -} diff --git a/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go b/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go index aa79c7250..e84295092 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go +++ b/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go @@ -84,6 +84,10 @@ func VisitPodSecretNames(pod *v1.Pod, visitor Visitor) bool { if source.CephFS.SecretRef != nil && !visitor(source.CephFS.SecretRef.Name) { return false } + case source.Cinder != nil: + if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Name) { + return false + } case source.FlexVolume != nil: if source.FlexVolume.SecretRef != nil && !visitor(source.FlexVolume.SecretRef.Name) { return false @@ -257,9 +261,18 @@ func GetPodCondition(status *v1.PodStatus, conditionType v1.PodConditionType) (i if status == nil { return -1, nil } - for i := range status.Conditions { - if status.Conditions[i].Type == conditionType { - return i, &status.Conditions[i] + return GetPodConditionFromList(status.Conditions, conditionType) +} + +// GetPodConditionFromList extracts the provided condition from the given list of condition and +// returns the index of the condition and the condition. Returns -1 and nil if the condition is not present. +func GetPodConditionFromList(conditions []v1.PodCondition, conditionType v1.PodConditionType) (int, *v1.PodCondition) { + if conditions == nil { + return -1, nil + } + for i := range conditions { + if conditions[i].Type == conditionType { + return i, &conditions[i] } } return -1, nil diff --git a/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util_test.go b/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util_test.go index 5310bc328..aad3a258b 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util_test.go @@ -233,6 +233,10 @@ func TestPodSecrets(t *testing.T) { CephFS: &v1.CephFSVolumeSource{ SecretRef: &v1.LocalObjectReference{ Name: "Spec.Volumes[*].VolumeSource.CephFS.SecretRef"}}}}, { + VolumeSource: v1.VolumeSource{ + Cinder: &v1.CinderVolumeSource{ + SecretRef: &v1.LocalObjectReference{ + Name: "Spec.Volumes[*].VolumeSource.Cinder.SecretRef"}}}}, { VolumeSource: v1.VolumeSource{ FlexVolume: &v1.FlexVolumeSource{ SecretRef: &v1.LocalObjectReference{ @@ -287,6 +291,7 @@ func TestPodSecrets(t *testing.T) { "Spec.InitContainers[*].Env[*].ValueFrom.SecretKeyRef", "Spec.Volumes[*].VolumeSource.AzureFile.SecretName", "Spec.Volumes[*].VolumeSource.CephFS.SecretRef", + "Spec.Volumes[*].VolumeSource.Cinder.SecretRef", "Spec.Volumes[*].VolumeSource.FlexVolume.SecretRef", "Spec.Volumes[*].VolumeSource.Projected.Sources[*].Secret", "Spec.Volumes[*].VolumeSource.RBD.SecretRef", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/abac/v0/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/abac/v0/zz_generated.deepcopy.go index 3e6dcb682..d2eb7135f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/abac/v0/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/abac/v0/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.conversion.go index d52ed7cfd..fa90be74d 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.deepcopy.go index e0557b64e..19c37edb5 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.defaults.go index 544e569dc..73e63fc11 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/abac/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/abac/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/abac/zz_generated.deepcopy.go index 9379b9ca3..d660b6ad7 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/abac/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/abac/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admission/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/admission/install/BUILD index a7f52efee..d39ff9d17 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admission/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/admission/install/BUILD @@ -13,10 +13,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/admission:go_default_library", "//pkg/apis/admission/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admission/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/admission/install/install.go index 404f549c3..82a1cb4a4 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admission/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admission/install/install.go @@ -19,32 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/admission" "k8s.io/kubernetes/pkg/apis/admission/v1beta1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: admission.GroupName, - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("AdmissionReview"), - AddInternalObjectsToScheme: admission.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(admission.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admission/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/admission/v1beta1/zz_generated.conversion.go index d72004a30..9deb9da5f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admission/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admission/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admission/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/admission/v1beta1/zz_generated.defaults.go index 544e569dc..73e63fc11 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admission/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admission/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admission/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/admission/zz_generated.deepcopy.go index 1d13899c1..9c75d5f48 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admission/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admission/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/install/BUILD index 04bb06074..76a85b291 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/install/BUILD @@ -14,10 +14,8 @@ go_library( "//pkg/apis/admissionregistration:go_default_library", "//pkg/apis/admissionregistration/v1alpha1:go_default_library", "//pkg/apis/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/install/install.go index 81f4ff2ff..65a38b2fb 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/install/install.go @@ -17,10 +17,8 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/admissionregistration" "k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1" @@ -28,23 +26,13 @@ import ( ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: admissionregistration.GroupName, - RootScopedKinds: sets.NewString("InitializerConfiguration", "ValidatingWebhookConfiguration", "MutatingWebhookConfiguration"), - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version, v1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: admissionregistration.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(admissionregistration.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/types.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/types.go index 829688a0e..1d71bc694 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/types.go @@ -298,9 +298,7 @@ type WebhookClientConfig struct { // // If the webhook is running within the cluster, then you should use `service`. // - // If there is only one port open for the service, that port will be - // used. If there are multiple ports open, port 443 will be used if it - // is open, otherwise it is an error. + // Port 443 will be used if it is open, otherwise it is an error. // // +optional Service *ServiceReference diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1/zz_generated.conversion.go index ca7a24fb7..21e9e0832 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1/zz_generated.conversion.go index 8bdeae37e..8e2a07701 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1/zz_generated.defaults.go index 623028e1f..bf559d6ab 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/zz_generated.deepcopy.go index c40fd6cd3..f59c503ae 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/fuzzer/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/apps/fuzzer/BUILD index 80ee7db32..3e37df54c 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/fuzzer/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/fuzzer/BUILD @@ -12,6 +12,7 @@ go_library( deps = [ "//pkg/apis/apps:go_default_library", "//vendor/github.com/google/gofuzz:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/fuzzer/fuzzer.go index 8013a273b..edd83be25 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/fuzzer/fuzzer.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/fuzzer/fuzzer.go @@ -19,6 +19,7 @@ package fuzzer import ( fuzz "github.com/google/gofuzz" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/kubernetes/pkg/apis/apps" ) @@ -46,6 +47,12 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { if s.Status.CollisionCount == nil { s.Status.CollisionCount = new(int32) } + if s.Spec.Selector == nil { + s.Spec.Selector = &metav1.LabelSelector{MatchLabels: s.Spec.Template.Labels} + } + if len(s.Labels) == 0 { + s.Labels = s.Spec.Template.Labels + } }, } } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/apps/install/BUILD index e33b4cb24..622fb3175 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/install/BUILD @@ -15,9 +15,8 @@ go_library( "//pkg/apis/apps/v1:go_default_library", "//pkg/apis/apps/v1beta1:go_default_library", "//pkg/apis/apps/v1beta2:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/install/install.go index 4f9dcfe9a..c53860afb 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/install/install.go @@ -19,9 +19,8 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/apps/v1" @@ -30,23 +29,14 @@ import ( ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: apps.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version, v1beta2.SchemeGroupVersion.Version, v1beta1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: apps.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - v1beta2.SchemeGroupVersion.Version: v1beta2.AddToScheme, - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(apps.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(v1beta2.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta2.SchemeGroupVersion, v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/conversion.go index 0908f7fc2..565430b0e 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/conversion.go @@ -182,6 +182,7 @@ func Convert_v1_Deployment_To_extensions_Deployment(in *appsv1.Deployment, out * out.Spec.RollbackTo = new(extensions.RollbackConfig) out.Spec.RollbackTo.Revision = revision64 } + out.Annotations = deepCopyStringMap(out.Annotations) delete(out.Annotations, appsv1.DeprecatedRollbackTo) } else { out.Spec.RollbackTo = nil @@ -195,6 +196,8 @@ func Convert_v1_Deployment_To_extensions_Deployment(in *appsv1.Deployment, out * func Convert_extensions_Deployment_To_v1_Deployment(in *extensions.Deployment, out *appsv1.Deployment, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta + out.Annotations = deepCopyStringMap(out.Annotations) // deep copy because we modify it below + if err := Convert_extensions_DeploymentSpec_To_v1_DeploymentSpec(&in.Spec, &out.Spec, s); err != nil { return err } @@ -235,9 +238,8 @@ func Convert_v1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet(in * func Convert_extensions_DaemonSet_To_v1_DaemonSet(in *extensions.DaemonSet, out *appsv1.DaemonSet, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if out.Annotations == nil { - out.Annotations = make(map[string]string) - } + out.Annotations = deepCopyStringMap(out.Annotations) // deep copy annotations because we change them below + out.Annotations[appsv1.DeprecatedTemplateGeneration] = strconv.FormatInt(in.Spec.TemplateGeneration, 10) if err := Convert_extensions_DaemonSetSpec_To_v1_DaemonSetSpec(&in.Spec, &out.Spec, s); err != nil { return err @@ -287,6 +289,7 @@ func Convert_v1_DaemonSet_To_extensions_DaemonSet(in *appsv1.DaemonSet, out *ext return err } else { out.Spec.TemplateGeneration = value64 + out.Annotations = deepCopyStringMap(out.Annotations) delete(out.Annotations, appsv1.DeprecatedTemplateGeneration) } } @@ -496,3 +499,11 @@ func Convert_apps_StatefulSetStatus_To_v1_StatefulSetStatus(in *apps.StatefulSet } return nil } + +func deepCopyStringMap(m map[string]string) map[string]string { + ret := make(map[string]string, len(m)) + for k, v := range m { + ret[k] = v + } + return ret +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/zz_generated.conversion.go index 2fc9fa23f..3bdf1f42c 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/zz_generated.defaults.go index 5029d8b49..8a4a0a5d7 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -86,6 +86,9 @@ func SetObjectDefaults_DaemonSet(in *v1.DaemonSet) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -230,6 +233,9 @@ func SetObjectDefaults_Deployment(in *v1.Deployment) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -374,6 +380,9 @@ func SetObjectDefaults_ReplicaSet(in *v1.ReplicaSet) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -518,6 +527,9 @@ func SetObjectDefaults_StatefulSet(in *v1.StatefulSet) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta1/zz_generated.conversion.go index e56a55bdd..43547d188 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta1/zz_generated.defaults.go index a61212ccd..656f61edc 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -82,6 +82,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -226,6 +229,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta1.StatefulSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/conversion.go index f71de4f28..a3671668f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/conversion.go @@ -415,6 +415,7 @@ func Convert_v1beta2_Deployment_To_extensions_Deployment(in *appsv1beta2.Deploym out.Spec.RollbackTo = new(extensions.RollbackConfig) out.Spec.RollbackTo.Revision = revision64 } + out.Annotations = deepCopyStringMap(out.Annotations) delete(out.Annotations, appsv1beta2.DeprecatedRollbackTo) } else { out.Spec.RollbackTo = nil @@ -440,6 +441,8 @@ func Convert_v1beta2_ReplicaSetSpec_To_extensions_ReplicaSetSpec(in *appsv1beta2 func Convert_extensions_Deployment_To_v1beta2_Deployment(in *extensions.Deployment, out *appsv1beta2.Deployment, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta + out.Annotations = deepCopyStringMap(out.Annotations) // deep copy because we modify annotations below + if err := Convert_extensions_DeploymentSpec_To_v1beta2_DeploymentSpec(&in.Spec, &out.Spec, s); err != nil { return err } @@ -463,9 +466,7 @@ func Convert_extensions_Deployment_To_v1beta2_Deployment(in *extensions.Deployme func Convert_extensions_DaemonSet_To_v1beta2_DaemonSet(in *extensions.DaemonSet, out *appsv1beta2.DaemonSet, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if out.Annotations == nil { - out.Annotations = make(map[string]string) - } + out.Annotations = deepCopyStringMap(out.Annotations) out.Annotations[appsv1beta2.DeprecatedTemplateGeneration] = strconv.FormatInt(in.Spec.TemplateGeneration, 10) if err := Convert_extensions_DaemonSetSpec_To_v1beta2_DaemonSetSpec(&in.Spec, &out.Spec, s); err != nil { return err @@ -515,6 +516,7 @@ func Convert_v1beta2_DaemonSet_To_extensions_DaemonSet(in *appsv1beta2.DaemonSet return err } else { out.Spec.TemplateGeneration = value64 + out.Annotations = deepCopyStringMap(out.Annotations) delete(out.Annotations, appsv1beta2.DeprecatedTemplateGeneration) } } @@ -552,3 +554,11 @@ func Convert_v1beta2_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrate } return nil } + +func deepCopyStringMap(m map[string]string) map[string]string { + ret := make(map[string]string, len(m)) + for k, v := range m { + ret[k] = v + } + return ret +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/zz_generated.conversion.go index 45c19d0d3..f13ed3f8c 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/zz_generated.defaults.go index 059718d33..713bcaa78 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/v1beta2/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -86,6 +86,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta2.DaemonSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -230,6 +233,9 @@ func SetObjectDefaults_Deployment(in *v1beta2.Deployment) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -374,6 +380,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta2.ReplicaSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -518,6 +527,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta2.StatefulSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/validation/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/apps/validation/BUILD index b9af06637..04366cf54 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/validation/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/validation/BUILD @@ -14,6 +14,7 @@ go_library( "//pkg/apis/apps:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/validation:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/validation/validation.go index 77f6a6cd4..d2eabd5c6 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/validation/validation.go @@ -18,8 +18,8 @@ package validation import ( "fmt" - "reflect" + apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/labels" @@ -149,7 +149,7 @@ func ValidateStatefulSetUpdate(statefulSet, oldStatefulSet *apps.StatefulSet) fi restoreStrategy := statefulSet.Spec.UpdateStrategy statefulSet.Spec.UpdateStrategy = oldStatefulSet.Spec.UpdateStrategy - if !reflect.DeepEqual(statefulSet.Spec, oldStatefulSet.Spec) { + if !apiequality.Semantic.DeepEqual(statefulSet.Spec, oldStatefulSet.Spec) { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbidden.")) } statefulSet.Spec.Replicas = restoreReplicas diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/zz_generated.deepcopy.go index e711a930b..42e3ea671 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/authentication/BUILD index 1d09c7766..1781f6342 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authentication/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/BUILD @@ -37,6 +37,7 @@ filegroup( "//pkg/apis/authentication/install:all-srcs", "//pkg/apis/authentication/v1:all-srcs", "//pkg/apis/authentication/v1beta1:all-srcs", + "//pkg/apis/authentication/validation:all-srcs", ], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/authentication/install/BUILD index ec4744b94..c65bab329 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authentication/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/install/BUILD @@ -14,10 +14,8 @@ go_library( "//pkg/apis/authentication:go_default_library", "//pkg/apis/authentication/v1:go_default_library", "//pkg/apis/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/authentication/install/install.go index 3e1271dcb..7974cb91d 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authentication/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/install/install.go @@ -19,10 +19,8 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/authentication" "k8s.io/kubernetes/pkg/apis/authentication/v1" @@ -30,23 +28,13 @@ import ( ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: authentication.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version, v1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("TokenReview"), - AddInternalObjectsToScheme: authentication.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(authentication.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1/zz_generated.conversion.go index cec47e2df..58180c059 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1/zz_generated.defaults.go index ee4b71be3..25e259790 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1beta1/zz_generated.conversion.go index 3031f7172..a788d3852 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1beta1/zz_generated.defaults.go index 544e569dc..73e63fc11 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/validation/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/authentication/validation/BUILD new file mode 100644 index 000000000..3192543f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/validation/BUILD @@ -0,0 +1,26 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["validation.go"], + importpath = "k8s.io/kubernetes/pkg/apis/authentication/validation", + visibility = ["//visibility:public"], + deps = [ + "//pkg/apis/authentication:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/authentication/validation/validation.go new file mode 100644 index 000000000..b174ddfc1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/validation/validation.go @@ -0,0 +1,41 @@ +/* +Copyright 2018 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 validation contains methods to validate kinds in the +// authentication.k8s.io API group. +package validation + +import ( + "time" + + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/kubernetes/pkg/apis/authentication" +) + +// ValidateTokenRequest validates a TokenRequest. +func ValidateTokenRequest(tr *authentication.TokenRequest) field.ErrorList { + allErrs := field.ErrorList{} + specPath := field.NewPath("spec") + + const min = 10 * time.Minute + if tr.Spec.ExpirationSeconds < int64(min.Seconds()) { + allErrs = append(allErrs, field.Invalid(specPath.Child("expirationSeconds"), tr.Spec.ExpirationSeconds, "may not specify a duration less than 10 minutes")) + } + if tr.Spec.ExpirationSeconds > 1<<32 { + allErrs = append(allErrs, field.Invalid(specPath.Child("expirationSeconds"), tr.Spec.ExpirationSeconds, "may not specify a duration larger than 2^32 seconds")) + } + return allErrs +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authentication/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/authentication/zz_generated.deepcopy.go index 90b6067f0..c0209f6ef 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authentication/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authentication/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authorization/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/authorization/install/BUILD index 9825a5afd..22dcec212 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authorization/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/authorization/install/BUILD @@ -14,10 +14,8 @@ go_library( "//pkg/apis/authorization:go_default_library", "//pkg/apis/authorization/v1:go_default_library", "//pkg/apis/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authorization/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/authorization/install/install.go index 2a9cbf6bd..f9af4928d 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authorization/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authorization/install/install.go @@ -19,10 +19,8 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/authorization" "k8s.io/kubernetes/pkg/apis/authorization/v1" @@ -30,23 +28,13 @@ import ( ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: authorization.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version, v1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("SubjectAccessReview", "SelfSubjectAccessReview", "SelfSubjectRulesReview"), - AddInternalObjectsToScheme: authorization.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(authorization.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1/zz_generated.conversion.go index c96b61ea3..e42d35662 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/zz_generated.conversion.go index 0e563f1ec..e6a0df63f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/zz_generated.defaults.go index 544e569dc..73e63fc11 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/authorization/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/authorization/zz_generated.deepcopy.go index 78453c878..b86507774 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/authorization/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/authorization/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/install/BUILD index d1cb4d5dc..968a92c22 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/install/BUILD @@ -14,9 +14,8 @@ go_library( "//pkg/apis/autoscaling:go_default_library", "//pkg/apis/autoscaling/v1:go_default_library", "//pkg/apis/autoscaling/v2beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/install/install.go index 507f2b17f..62236a0c7 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/install/install.go @@ -19,9 +19,8 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/autoscaling/v1" @@ -29,22 +28,13 @@ import ( ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: autoscaling.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version, v2beta1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: autoscaling.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - v2beta1.SchemeGroupVersion.Version: v2beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(autoscaling.AddToScheme(scheme)) + utilruntime.Must(v2beta1.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v2beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v1/zz_generated.conversion.go index 3b13fab2e..ea8ee6b96 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v1/zz_generated.defaults.go index 860e1ebe2..5e0f8779f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v2beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v2beta1/zz_generated.conversion.go index d9c8791b3..0b4cecc7f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v2beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v2beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v2beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v2beta1/zz_generated.defaults.go index dfe73d84a..dd7c9b2fa 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v2beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/v2beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/zz_generated.deepcopy.go index c01971384..12c518d36 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/autoscaling/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/fuzzer/fuzzer.go index 4b0a8b906..b6f82a2b1 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/fuzzer/fuzzer.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/fuzzer/fuzzer.go @@ -32,6 +32,14 @@ func newBool(val bool) *bool { // Funcs returns the fuzzer functions for the batch api group. var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ + func(j *batch.Job, c fuzz.Continue) { + c.FuzzNoCustom(j) // fuzz self without calling this function again + + // match defaulting + if len(j.Labels) == 0 { + j.Labels = j.Spec.Template.Labels + } + }, func(j *batch.JobSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // fuzz self without calling this function again completions := int32(c.Rand.Int31()) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/batch/install/BUILD index 3445e3f35..b0399ab6b 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/install/BUILD @@ -15,9 +15,8 @@ go_library( "//pkg/apis/batch/v1:go_default_library", "//pkg/apis/batch/v1beta1:go_default_library", "//pkg/apis/batch/v2alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/install/install.go index e04f92605..c87c186cc 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/install/install.go @@ -19,9 +19,8 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/batch/v1" @@ -30,23 +29,14 @@ import ( ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: batch.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version, v1beta1.SchemeGroupVersion.Version, v2alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: batch.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - v2alpha1.SchemeGroupVersion.Version: v2alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(batch.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(v2alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion, v2alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/v1/zz_generated.conversion.go index 816503828..32d2cae91 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/v1/zz_generated.defaults.go index 9b02de39a..859d17b76 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -80,6 +80,9 @@ func SetObjectDefaults_Job(in *v1.Job) { } } } + if b.ServiceAccountToken != nil { + core_v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/v1beta1/zz_generated.conversion.go index 2d57654ac..98121acca 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/v1beta1/zz_generated.defaults.go index 1d05468cf..d90031c32 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -81,6 +81,9 @@ func SetObjectDefaults_CronJob(in *v1beta1.CronJob) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -224,6 +227,9 @@ func SetObjectDefaults_JobTemplate(in *v1beta1.JobTemplate) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/v2alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/v2alpha1/zz_generated.conversion.go index 76a34b588..1c5509b34 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/v2alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/v2alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/v2alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/v2alpha1/zz_generated.defaults.go index eec4cfb91..367c56b15 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/v2alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/v2alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -81,6 +81,9 @@ func SetObjectDefaults_CronJob(in *v2alpha1.CronJob) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -224,6 +227,9 @@ func SetObjectDefaults_JobTemplate(in *v2alpha1.JobTemplate) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/zz_generated.deepcopy.go index 7155d5c61..af8e57ea0 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/certificates/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/certificates/install/BUILD index e8962d640..0ef7bd712 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/certificates/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/certificates/install/BUILD @@ -13,10 +13,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/certificates:go_default_library", "//pkg/apis/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/certificates/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/certificates/install/install.go index a4e9bb39d..8f685da60 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/certificates/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/certificates/install/install.go @@ -19,32 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/certificates" "k8s.io/kubernetes/pkg/apis/certificates/v1beta1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: certificates.GroupName, - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("CertificateSigningRequest"), - AddInternalObjectsToScheme: certificates.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(certificates.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/certificates/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/certificates/v1beta1/zz_generated.conversion.go index 47a3d1f46..2c393df4e 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/certificates/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/certificates/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/certificates/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/certificates/v1beta1/zz_generated.defaults.go index 6c987c871..beb1ee2d1 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/certificates/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/certificates/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/certificates/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/certificates/zz_generated.deepcopy.go index fda9d3aa5..997e4692a 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/certificates/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/certificates/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/install/BUILD index fb58da06e..847ba6e5c 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/install/BUILD @@ -13,9 +13,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/componentconfig:go_default_library", "//pkg/apis/componentconfig/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/install/install.go index d5e48363b..74ed50129 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/install/install.go @@ -19,30 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: componentconfig.GroupName, - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: componentconfig.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(componentconfig.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/types.go b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/types.go index 89671f046..51f79b151 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/types.go @@ -111,12 +111,16 @@ type KubeSchedulerConfiguration struct { // Indicate the "all topologies" set for empty topologyKey when it's used for PreferredDuringScheduling pod anti-affinity. // DEPRECATED: This is no longer used. FailureDomains string + + // DisablePreemption disables the pod preemption feature. + DisablePreemption bool } // KubeSchedulerLeaderElectionConfiguration expands LeaderElectionConfiguration // to include scheduler specific configuration. type KubeSchedulerLeaderElectionConfiguration struct { LeaderElectionConfiguration + // LockObjectNamespace defines the namespace of the lock object LockObjectNamespace string // LockObjectName defines the lock object name @@ -163,13 +167,137 @@ type GroupResource struct { type KubeControllerManagerConfiguration struct { metav1.TypeMeta + // CloudProviderConfiguration holds configuration for CloudProvider related features. + CloudProvider CloudProviderConfiguration + // DebuggingConfiguration holds configuration for Debugging related features. + Debugging DebuggingConfiguration + // GenericComponentConfiguration holds configuration for GenericComponent + // related features both in cloud controller manager and kube-controller manager. + GenericComponent GenericComponentConfiguration + // KubeCloudSharedConfiguration holds configuration for shared related features + // both in cloud controller manager and kube-controller manager. + KubeCloudShared KubeCloudSharedConfiguration + + // AttachDetachControllerConfiguration holds configuration for + // AttachDetachController related features. + AttachDetachController AttachDetachControllerConfiguration + // CSRSigningControllerConfiguration holds configuration for + // CSRSigningController related features. + CSRSigningController CSRSigningControllerConfiguration + // DaemonSetControllerConfiguration holds configuration for DaemonSetController + // related features. + DaemonSetController DaemonSetControllerConfiguration + // DeploymentControllerConfiguration holds configuration for + // DeploymentController related features. + DeploymentController DeploymentControllerConfiguration + // DeprecatedControllerConfiguration holds configuration for some deprecated + // features. + DeprecatedController DeprecatedControllerConfiguration + // EndPointControllerConfiguration holds configuration for EndPointController + // related features. + EndPointController EndPointControllerConfiguration + // GarbageCollectorControllerConfiguration holds configuration for + // GarbageCollectorController related features. + GarbageCollectorController GarbageCollectorControllerConfiguration + // HPAControllerConfiguration holds configuration for HPAController related features. + HPAController HPAControllerConfiguration + // JobControllerConfiguration holds configuration for JobController related features. + JobController JobControllerConfiguration + // NamespaceControllerConfiguration holds configuration for + // NamespaceController related features. + NamespaceController NamespaceControllerConfiguration + // NodeIpamControllerConfiguration holds configuration for NodeIpamController + // related features. + NodeIpamController NodeIpamControllerConfiguration + // NodeLifecycleControllerConfiguration holds configuration for + // NodeLifecycleController related features. + NodeLifecycleController NodeLifecycleControllerConfiguration + // PersistentVolumeBinderControllerConfiguration holds configuration for + // PersistentVolumeBinderController related features. + PersistentVolumeBinderController PersistentVolumeBinderControllerConfiguration + // PodGCControllerConfiguration holds configuration for PodGCController + // related features. + PodGCController PodGCControllerConfiguration + // ReplicaSetControllerConfiguration holds configuration for ReplicaSet related features. + ReplicaSetController ReplicaSetControllerConfiguration + // ReplicationControllerConfiguration holds configuration for + // ReplicationController related features. + ReplicationController ReplicationControllerConfiguration + // ResourceQuotaControllerConfiguration holds configuration for + // ResourceQuotaController related features. + ResourceQuotaController ResourceQuotaControllerConfiguration + // SAControllerConfiguration holds configuration for ServiceAccountController + // related features. + SAController SAControllerConfiguration + // ServiceControllerConfiguration holds configuration for ServiceController + // related features. + ServiceController ServiceControllerConfiguration + // Controllers is the list of controllers to enable or disable // '*' means "all enabled by default controllers" // 'foo' means "enable 'foo'" // '-foo' means "disable 'foo'" // first item for a particular name wins Controllers []string + // externalCloudVolumePlugin specifies the plugin to use when cloudProvider is "external". + // It is currently used by the in repo cloud providers to handle node and volume control in the KCM. + ExternalCloudVolumePlugin string +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type CloudControllerManagerConfiguration struct { + metav1.TypeMeta + + // CloudProviderConfiguration holds configuration for CloudProvider related features. + CloudProvider CloudProviderConfiguration + // DebuggingConfiguration holds configuration for Debugging related features. + Debugging DebuggingConfiguration + // GenericComponentConfiguration holds configuration for GenericComponent + // related features both in cloud controller manager and kube-controller manager. + GenericComponent GenericComponentConfiguration + // KubeCloudSharedConfiguration holds configuration for shared related features + // both in cloud controller manager and kube-controller manager. + KubeCloudShared KubeCloudSharedConfiguration + // ServiceControllerConfiguration holds configuration for ServiceController + // related features. + ServiceController ServiceControllerConfiguration + // NodeStatusUpdateFrequency is the frequency at which the controller updates nodes' status + NodeStatusUpdateFrequency metav1.Duration +} +type CloudProviderConfiguration struct { + // Name is the provider for cloud services. + Name string + // cloudConfigFile is the path to the cloud provider configuration file. + CloudConfigFile string +} + +type DebuggingConfiguration struct { + // enableProfiling enables profiling via web interface host:port/debug/pprof/ + EnableProfiling bool + // EnableContentionProfiling enables lock contention profiling, if + // EnableProfiling is true. + EnableContentionProfiling bool +} + +type GenericComponentConfiguration struct { + // minResyncPeriod is the resync period in reflectors; will be random between + // minResyncPeriod and 2*minResyncPeriod. + MinResyncPeriod metav1.Duration + // contentType is contentType of requests sent to apiserver. + ContentType string + // kubeAPIQPS is the QPS to use while talking with kubernetes apiserver. + KubeAPIQPS float32 + // kubeAPIBurst is the burst to use while talking with kubernetes apiserver. + KubeAPIBurst int32 + // How long to wait between starting controller managers + ControllerStartInterval metav1.Duration + // leaderElection defines the configuration of leader election client. + LeaderElection LeaderElectionConfiguration +} + +type KubeCloudSharedConfiguration struct { // port is the port that the controller-manager's http service runs on. Port int32 // address is the IP address to serve on (set to 0.0.0.0 for all interfaces). @@ -177,134 +305,16 @@ type KubeControllerManagerConfiguration struct { // useServiceAccountCredentials indicates whether controllers should be run with // individual service account credentials. UseServiceAccountCredentials bool - // cloudProvider is the provider for cloud services. - CloudProvider string - // cloudConfigFile is the path to the cloud provider configuration file. - CloudConfigFile string - // externalCloudVolumePlugin specifies the plugin to use when cloudProvider is "external". - // It is currently used by the in repo cloud providers to handle node and volume control in the KCM. - ExternalCloudVolumePlugin string // run with untagged cloud instances AllowUntaggedCloud bool - // concurrentEndpointSyncs is the number of endpoint syncing operations - // that will be done concurrently. Larger number = faster endpoint updating, - // but more CPU (and network) load. - ConcurrentEndpointSyncs int32 - // concurrentRSSyncs is the number of replica sets that are allowed to sync - // concurrently. Larger number = more responsive replica management, but more - // CPU (and network) load. - ConcurrentRSSyncs int32 - // concurrentRCSyncs is the number of replication controllers that are - // allowed to sync concurrently. Larger number = more responsive replica - // management, but more CPU (and network) load. - ConcurrentRCSyncs int32 - // concurrentServiceSyncs is the number of services that are - // allowed to sync concurrently. Larger number = more responsive service - // management, but more CPU (and network) load. - ConcurrentServiceSyncs int32 - // concurrentResourceQuotaSyncs is the number of resource quotas that are - // allowed to sync concurrently. Larger number = more responsive quota - // management, but more CPU (and network) load. - ConcurrentResourceQuotaSyncs int32 - // concurrentDeploymentSyncs is the number of deployment objects that are - // allowed to sync concurrently. Larger number = more responsive deployments, - // but more CPU (and network) load. - ConcurrentDeploymentSyncs int32 - // concurrentDaemonSetSyncs is the number of daemonset objects that are - // allowed to sync concurrently. Larger number = more responsive daemonset, - // but more CPU (and network) load. - ConcurrentDaemonSetSyncs int32 - // concurrentJobSyncs is the number of job objects that are - // allowed to sync concurrently. Larger number = more responsive jobs, - // but more CPU (and network) load. - ConcurrentJobSyncs int32 - // concurrentNamespaceSyncs is the number of namespace objects that are - // allowed to sync concurrently. - ConcurrentNamespaceSyncs int32 - // concurrentSATokenSyncs is the number of service account token syncing operations - // that will be done concurrently. - ConcurrentSATokenSyncs int32 - // lookupCacheSizeForRC is the size of lookup cache for replication controllers. - // Larger number = more responsive replica management, but more MEM load. - // nodeSyncPeriod is the period for syncing nodes from cloudprovider. Longer - // periods will result in fewer calls to cloud provider, but may delay addition - // of new nodes to cluster. - NodeSyncPeriod metav1.Duration // routeReconciliationPeriod is the period for reconciling routes created for Nodes by cloud provider.. RouteReconciliationPeriod metav1.Duration - // resourceQuotaSyncPeriod is the period for syncing quota usage status - // in the system. - ResourceQuotaSyncPeriod metav1.Duration - // namespaceSyncPeriod is the period for syncing namespace life-cycle - // updates. - NamespaceSyncPeriod metav1.Duration - // pvClaimBinderSyncPeriod is the period for syncing persistent volumes - // and persistent volume claims. - PVClaimBinderSyncPeriod metav1.Duration - // minResyncPeriod is the resync period in reflectors; will be random between - // minResyncPeriod and 2*minResyncPeriod. - MinResyncPeriod metav1.Duration - // terminatedPodGCThreshold is the number of terminated pods that can exist - // before the terminated pod garbage collector starts deleting terminated pods. - // If <= 0, the terminated pod garbage collector is disabled. - TerminatedPodGCThreshold int32 - // horizontalPodAutoscalerSyncPeriod is the period for syncing the number of - // pods in horizontal pod autoscaler. - HorizontalPodAutoscalerSyncPeriod metav1.Duration - // horizontalPodAutoscalerUpscaleForbiddenWindow is a period after which next upscale allowed. - HorizontalPodAutoscalerUpscaleForbiddenWindow metav1.Duration - // horizontalPodAutoscalerDownscaleForbiddenWindow is a period after which next downscale allowed. - HorizontalPodAutoscalerDownscaleForbiddenWindow metav1.Duration - // horizontalPodAutoscalerTolerance is the tolerance for when - // resource usage suggests upscaling/downscaling - HorizontalPodAutoscalerTolerance float64 - // deploymentControllerSyncPeriod is the period for syncing the deployments. - DeploymentControllerSyncPeriod metav1.Duration - // podEvictionTimeout is the grace period for deleting pods on failed nodes. - PodEvictionTimeout metav1.Duration - // DEPRECATED: deletingPodsQps is the number of nodes per second on which pods are deleted in - // case of node failure. - DeletingPodsQps float32 - // DEPRECATED: deletingPodsBurst is the number of nodes on which pods are bursty deleted in - // case of node failure. For more details look into RateLimiter. - DeletingPodsBurst int32 - // nodeMontiorGracePeriod is the amount of time which we allow a running node to be - // unresponsive before marking it unhealthy. Must be N times more than kubelet's - // nodeStatusUpdateFrequency, where N means number of retries allowed for kubelet - // to post node status. - NodeMonitorGracePeriod metav1.Duration - // registerRetryCount is the number of retries for initial node registration. - // Retry interval equals node-sync-period. - RegisterRetryCount int32 - // nodeStartupGracePeriod is the amount of time which we allow starting a node to - // be unresponsive before marking it unhealthy. - NodeStartupGracePeriod metav1.Duration // nodeMonitorPeriod is the period for syncing NodeStatus in NodeController. NodeMonitorPeriod metav1.Duration - // serviceAccountKeyFile is the filename containing a PEM-encoded private RSA key - // used to sign service account tokens. - ServiceAccountKeyFile string - // clusterSigningCertFile is the filename containing a PEM-encoded - // X509 CA certificate used to issue cluster-scoped certificates - ClusterSigningCertFile string - // clusterSigningCertFile is the filename containing a PEM-encoded - // RSA or ECDSA private key used to issue cluster-scoped certificates - ClusterSigningKeyFile string - // clusterSigningDuration is the length of duration signed certificates - // will be given. - ClusterSigningDuration metav1.Duration - // enableProfiling enables profiling via web interface host:port/debug/pprof/ - EnableProfiling bool - // enableContentionProfiling enables lock contention profiling, if enableProfiling is true. - EnableContentionProfiling bool // clusterName is the instance prefix for the cluster. ClusterName string // clusterCIDR is CIDR Range for Pods in cluster. ClusterCIDR string - // serviceCIDR is CIDR Range for Services in cluster. - ServiceCIDR string - // NodeCIDRMaskSize is the mask size for node cidr in cluster. - NodeCIDRMaskSize int32 // AllocateNodeCIDRs enables CIDRs for Pods to be allocated and, if // ConfigureCloudRoutes is true, to be set on the cloud provider. AllocateNodeCIDRs bool @@ -313,21 +323,70 @@ type KubeControllerManagerConfiguration struct { // configureCloudRoutes enables CIDRs allocated with allocateNodeCIDRs // to be configured on the cloud provider. ConfigureCloudRoutes bool - // rootCAFile is the root certificate authority will be included in service - // account's token secret. This must be a valid PEM-encoded CA bundle. - RootCAFile string - // contentType is contentType of requests sent to apiserver. - ContentType string - // kubeAPIQPS is the QPS to use while talking with kubernetes apiserver. - KubeAPIQPS float32 - // kubeAPIBurst is the burst to use while talking with kubernetes apiserver. - KubeAPIBurst int32 - // leaderElection defines the configuration of leader election client. - LeaderElection LeaderElectionConfiguration - // volumeConfiguration holds configuration for volume related features. - VolumeConfiguration VolumeConfiguration - // How long to wait between starting controller managers - ControllerStartInterval metav1.Duration + // nodeSyncPeriod is the period for syncing nodes from cloudprovider. Longer + // periods will result in fewer calls to cloud provider, but may delay addition + // of new nodes to cluster. + NodeSyncPeriod metav1.Duration +} + +type AttachDetachControllerConfiguration struct { + // Reconciler runs a periodic loop to reconcile the desired state of the with + // the actual state of the world by triggering attach detach operations. + // This flag enables or disables reconcile. Is false by default, and thus enabled. + DisableAttachDetachReconcilerSync bool + // ReconcilerSyncLoopPeriod is the amount of time the reconciler sync states loop + // wait between successive executions. Is set to 5 sec by default. + ReconcilerSyncLoopPeriod metav1.Duration +} + +type CSRSigningControllerConfiguration struct { + // clusterSigningCertFile is the filename containing a PEM-encoded + // X509 CA certificate used to issue cluster-scoped certificates + ClusterSigningCertFile string + // clusterSigningCertFile is the filename containing a PEM-encoded + // RSA or ECDSA private key used to issue cluster-scoped certificates + ClusterSigningKeyFile string + // clusterSigningDuration is the length of duration signed certificates + // will be given. + ClusterSigningDuration metav1.Duration +} + +type DaemonSetControllerConfiguration struct { + // concurrentDaemonSetSyncs is the number of daemonset objects that are + // allowed to sync concurrently. Larger number = more responsive daemonset, + // but more CPU (and network) load. + ConcurrentDaemonSetSyncs int32 +} + +type DeploymentControllerConfiguration struct { + // concurrentDeploymentSyncs is the number of deployment objects that are + // allowed to sync concurrently. Larger number = more responsive deployments, + // but more CPU (and network) load. + ConcurrentDeploymentSyncs int32 + // deploymentControllerSyncPeriod is the period for syncing the deployments. + DeploymentControllerSyncPeriod metav1.Duration +} + +type DeprecatedControllerConfiguration struct { + // DEPRECATED: deletingPodsQps is the number of nodes per second on which pods are deleted in + // case of node failure. + DeletingPodsQps float32 + // DEPRECATED: deletingPodsBurst is the number of nodes on which pods are bursty deleted in + // case of node failure. For more details look into RateLimiter. + DeletingPodsBurst int32 + // registerRetryCount is the number of retries for initial node registration. + // Retry interval equals node-sync-period. + RegisterRetryCount int32 +} + +type EndPointControllerConfiguration struct { + // concurrentEndpointSyncs is the number of endpoint syncing operations + // that will be done concurrently. Larger number = faster endpoint updating, + // but more CPU (and network) load. + ConcurrentEndpointSyncs int32 +} + +type GarbageCollectorControllerConfiguration struct { // enables the generic garbage collector. MUST be synced with the // corresponding flag of the kube-apiserver. WARNING: the generic garbage // collector is an alpha feature. @@ -337,29 +396,129 @@ type KubeControllerManagerConfiguration struct { ConcurrentGCSyncs int32 // gcIgnoredResources is the list of GroupResources that garbage collection should ignore. GCIgnoredResources []GroupResource +} + +type HPAControllerConfiguration struct { + // horizontalPodAutoscalerSyncPeriod is the period for syncing the number of + // pods in horizontal pod autoscaler. + HorizontalPodAutoscalerSyncPeriod metav1.Duration + // horizontalPodAutoscalerUpscaleForbiddenWindow is a period after which next upscale allowed. + HorizontalPodAutoscalerUpscaleForbiddenWindow metav1.Duration + // horizontalPodAutoscalerDownscaleForbiddenWindow is a period after which next downscale allowed. + HorizontalPodAutoscalerDownscaleForbiddenWindow metav1.Duration + // horizontalPodAutoscalerTolerance is the tolerance for when + // resource usage suggests upscaling/downscaling + HorizontalPodAutoscalerTolerance float64 + // HorizontalPodAutoscalerUseRESTClients causes the HPA controller to use REST clients + // through the kube-aggregator when enabled, instead of using the legacy metrics client + // through the API server proxy. + HorizontalPodAutoscalerUseRESTClients bool +} + +type JobControllerConfiguration struct { + // concurrentJobSyncs is the number of job objects that are + // allowed to sync concurrently. Larger number = more responsive jobs, + // but more CPU (and network) load. + ConcurrentJobSyncs int32 +} + +type NamespaceControllerConfiguration struct { + // namespaceSyncPeriod is the period for syncing namespace life-cycle + // updates. + NamespaceSyncPeriod metav1.Duration + // concurrentNamespaceSyncs is the number of namespace objects that are + // allowed to sync concurrently. + ConcurrentNamespaceSyncs int32 +} + +type NodeIpamControllerConfiguration struct { + // serviceCIDR is CIDR Range for Services in cluster. + ServiceCIDR string + // NodeCIDRMaskSize is the mask size for node cidr in cluster. + NodeCIDRMaskSize int32 +} + +type NodeLifecycleControllerConfiguration struct { + // If set to true enables NoExecute Taints and will evict all not-tolerating + // Pod running on Nodes tainted with this kind of Taints. + EnableTaintManager bool // nodeEvictionRate is the number of nodes per second on which pods are deleted in case of node failure when a zone is healthy NodeEvictionRate float32 // secondaryNodeEvictionRate is the number of nodes per second on which pods are deleted in case of node failure when a zone is unhealthy SecondaryNodeEvictionRate float32 + // nodeStartupGracePeriod is the amount of time which we allow starting a node to + // be unresponsive before marking it unhealthy. + NodeStartupGracePeriod metav1.Duration + // nodeMontiorGracePeriod is the amount of time which we allow a running node to be + // unresponsive before marking it unhealthy. Must be N times more than kubelet's + // nodeStatusUpdateFrequency, where N means number of retries allowed for kubelet + // to post node status. + NodeMonitorGracePeriod metav1.Duration + // podEvictionTimeout is the grace period for deleting pods on failed nodes. + PodEvictionTimeout metav1.Duration // secondaryNodeEvictionRate is implicitly overridden to 0 for clusters smaller than or equal to largeClusterSizeThreshold LargeClusterSizeThreshold int32 // Zone is treated as unhealthy in nodeEvictionRate and secondaryNodeEvictionRate when at least // unhealthyZoneThreshold (no less than 3) of Nodes in the zone are NotReady UnhealthyZoneThreshold float32 - // Reconciler runs a periodic loop to reconcile the desired state of the with - // the actual state of the world by triggering attach detach operations. - // This flag enables or disables reconcile. Is false by default, and thus enabled. - DisableAttachDetachReconcilerSync bool - // ReconcilerSyncLoopPeriod is the amount of time the reconciler sync states loop - // wait between successive executions. Is set to 5 sec by default. - ReconcilerSyncLoopPeriod metav1.Duration - // If set to true enables NoExecute Taints and will evict all not-tolerating - // Pod running on Nodes tainted with this kind of Taints. - EnableTaintManager bool - // HorizontalPodAutoscalerUseRESTClients causes the HPA controller to use REST clients - // through the kube-aggregator when enabled, instead of using the legacy metrics client - // through the API server proxy. - HorizontalPodAutoscalerUseRESTClients bool +} + +type PersistentVolumeBinderControllerConfiguration struct { + // pvClaimBinderSyncPeriod is the period for syncing persistent volumes + // and persistent volume claims. + PVClaimBinderSyncPeriod metav1.Duration + // volumeConfiguration holds configuration for volume related features. + VolumeConfiguration VolumeConfiguration +} + +type PodGCControllerConfiguration struct { + // terminatedPodGCThreshold is the number of terminated pods that can exist + // before the terminated pod garbage collector starts deleting terminated pods. + // If <= 0, the terminated pod garbage collector is disabled. + TerminatedPodGCThreshold int32 +} + +type ReplicaSetControllerConfiguration struct { + // concurrentRSSyncs is the number of replica sets that are allowed to sync + // concurrently. Larger number = more responsive replica management, but more + // CPU (and network) load. + ConcurrentRSSyncs int32 +} + +type ReplicationControllerConfiguration struct { + // concurrentRCSyncs is the number of replication controllers that are + // allowed to sync concurrently. Larger number = more responsive replica + // management, but more CPU (and network) load. + ConcurrentRCSyncs int32 +} + +type ResourceQuotaControllerConfiguration struct { + // resourceQuotaSyncPeriod is the period for syncing quota usage status + // in the system. + ResourceQuotaSyncPeriod metav1.Duration + // concurrentResourceQuotaSyncs is the number of resource quotas that are + // allowed to sync concurrently. Larger number = more responsive quota + // management, but more CPU (and network) load. + ConcurrentResourceQuotaSyncs int32 +} + +type SAControllerConfiguration struct { + // serviceAccountKeyFile is the filename containing a PEM-encoded private RSA key + // used to sign service account tokens. + ServiceAccountKeyFile string + // concurrentSATokenSyncs is the number of service account token syncing operations + // that will be done concurrently. + ConcurrentSATokenSyncs int32 + // rootCAFile is the root certificate authority will be included in service + // account's token secret. This must be a valid PEM-encoded CA bundle. + RootCAFile string +} + +type ServiceControllerConfiguration struct { + // concurrentServiceSyncs is the number of services that are + // allowed to sync concurrently. Larger number = more responsive service + // management, but more CPU (and network) load. + ConcurrentServiceSyncs int32 } // VolumeConfiguration contains *all* enumerated flags meant to configure all volume diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/BUILD index e89709d1e..e4ba55589 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/BUILD @@ -23,6 +23,7 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/master/ports:go_default_library", + "//pkg/util/pointer: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/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/defaults.go index 0528b6cb6..225b279a0 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/defaults.go @@ -26,12 +26,195 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/master/ports" + utilpointer "k8s.io/kubernetes/pkg/util/pointer" ) func addDefaultingFuncs(scheme *kruntime.Scheme) error { return RegisterDefaults(scheme) } +func SetDefaults_CloudControllerManagerConfiguration(obj *CloudControllerManagerConfiguration) { + zero := metav1.Duration{} + if obj.ServiceController.ConcurrentServiceSyncs == 0 { + obj.ServiceController.ConcurrentServiceSyncs = 1 + } + if obj.NodeStatusUpdateFrequency == zero { + obj.NodeStatusUpdateFrequency = metav1.Duration{Duration: 5 * time.Minute} + } +} + +func SetDefaults_KubeControllerManagerConfiguration(obj *KubeControllerManagerConfiguration) { + zero := metav1.Duration{} + if len(obj.Controllers) == 0 { + obj.Controllers = []string{"*"} + } + if obj.EndPointController.ConcurrentEndpointSyncs == 0 { + obj.EndPointController.ConcurrentEndpointSyncs = 5 + } + if obj.ServiceController.ConcurrentServiceSyncs == 0 { + obj.ServiceController.ConcurrentServiceSyncs = 1 + } + if obj.ReplicationController.ConcurrentRCSyncs == 0 { + obj.ReplicationController.ConcurrentRCSyncs = 5 + } + if obj.ReplicaSetController.ConcurrentRSSyncs == 0 { + obj.ReplicaSetController.ConcurrentRSSyncs = 5 + } + if obj.DaemonSetController.ConcurrentDaemonSetSyncs == 0 { + obj.DaemonSetController.ConcurrentDaemonSetSyncs = 2 + } + if obj.JobController.ConcurrentJobSyncs == 0 { + obj.JobController.ConcurrentJobSyncs = 5 + } + if obj.ResourceQuotaController.ConcurrentResourceQuotaSyncs == 0 { + obj.ResourceQuotaController.ConcurrentResourceQuotaSyncs = 5 + } + if obj.DeploymentController.ConcurrentDeploymentSyncs == 0 { + obj.DeploymentController.ConcurrentDeploymentSyncs = 5 + } + if obj.NamespaceController.ConcurrentNamespaceSyncs == 0 { + obj.NamespaceController.ConcurrentNamespaceSyncs = 10 + } + if obj.SAController.ConcurrentSATokenSyncs == 0 { + obj.SAController.ConcurrentSATokenSyncs = 5 + } + if obj.ResourceQuotaController.ResourceQuotaSyncPeriod == zero { + obj.ResourceQuotaController.ResourceQuotaSyncPeriod = metav1.Duration{Duration: 5 * time.Minute} + } + if obj.NamespaceController.NamespaceSyncPeriod == zero { + obj.NamespaceController.NamespaceSyncPeriod = metav1.Duration{Duration: 5 * time.Minute} + } + if obj.PersistentVolumeBinderController.PVClaimBinderSyncPeriod == zero { + obj.PersistentVolumeBinderController.PVClaimBinderSyncPeriod = metav1.Duration{Duration: 15 * time.Second} + } + if obj.HPAController.HorizontalPodAutoscalerSyncPeriod == zero { + obj.HPAController.HorizontalPodAutoscalerSyncPeriod = metav1.Duration{Duration: 30 * time.Second} + } + if obj.HPAController.HorizontalPodAutoscalerUpscaleForbiddenWindow == zero { + obj.HPAController.HorizontalPodAutoscalerUpscaleForbiddenWindow = metav1.Duration{Duration: 3 * time.Minute} + } + if obj.HPAController.HorizontalPodAutoscalerDownscaleForbiddenWindow == zero { + obj.HPAController.HorizontalPodAutoscalerDownscaleForbiddenWindow = metav1.Duration{Duration: 5 * time.Minute} + } + if obj.HPAController.HorizontalPodAutoscalerTolerance == 0 { + obj.HPAController.HorizontalPodAutoscalerTolerance = 0.1 + } + if obj.DeploymentController.DeploymentControllerSyncPeriod == zero { + obj.DeploymentController.DeploymentControllerSyncPeriod = metav1.Duration{Duration: 30 * time.Second} + } + if obj.DeprecatedController.RegisterRetryCount == 0 { + obj.DeprecatedController.RegisterRetryCount = 10 + } + if obj.NodeLifecycleController.PodEvictionTimeout == zero { + obj.NodeLifecycleController.PodEvictionTimeout = metav1.Duration{Duration: 5 * time.Minute} + } + if obj.NodeLifecycleController.NodeMonitorGracePeriod == zero { + obj.NodeLifecycleController.NodeMonitorGracePeriod = metav1.Duration{Duration: 40 * time.Second} + } + if obj.NodeLifecycleController.NodeStartupGracePeriod == zero { + obj.NodeLifecycleController.NodeStartupGracePeriod = metav1.Duration{Duration: 60 * time.Second} + } + if obj.NodeIpamController.NodeCIDRMaskSize == 0 { + obj.NodeIpamController.NodeCIDRMaskSize = 24 + } + if obj.PodGCController.TerminatedPodGCThreshold == 0 { + obj.PodGCController.TerminatedPodGCThreshold = 12500 + } + if obj.GarbageCollectorController.EnableGarbageCollector == nil { + obj.GarbageCollectorController.EnableGarbageCollector = utilpointer.BoolPtr(true) + } + if obj.GarbageCollectorController.ConcurrentGCSyncs == 0 { + obj.GarbageCollectorController.ConcurrentGCSyncs = 20 + } + if obj.CSRSigningController.ClusterSigningCertFile == "" { + obj.CSRSigningController.ClusterSigningCertFile = "/etc/kubernetes/ca/ca.pem" + } + if obj.CSRSigningController.ClusterSigningKeyFile == "" { + obj.CSRSigningController.ClusterSigningKeyFile = "/etc/kubernetes/ca/ca.key" + } + if obj.CSRSigningController.ClusterSigningDuration == zero { + obj.CSRSigningController.ClusterSigningDuration = metav1.Duration{Duration: 365 * 24 * time.Hour} + } + if obj.AttachDetachController.ReconcilerSyncLoopPeriod == zero { + obj.AttachDetachController.ReconcilerSyncLoopPeriod = metav1.Duration{Duration: 60 * time.Second} + } + if obj.NodeLifecycleController.EnableTaintManager == nil { + obj.NodeLifecycleController.EnableTaintManager = utilpointer.BoolPtr(true) + } + if obj.HPAController.HorizontalPodAutoscalerUseRESTClients == nil { + obj.HPAController.HorizontalPodAutoscalerUseRESTClients = utilpointer.BoolPtr(true) + } +} + +func SetDefaults_GenericComponentConfiguration(obj *GenericComponentConfiguration) { + zero := metav1.Duration{} + if obj.MinResyncPeriod == zero { + obj.MinResyncPeriod = metav1.Duration{Duration: 12 * time.Hour} + } + if obj.ContentType == "" { + obj.ContentType = "application/vnd.kubernetes.protobuf" + } + if obj.KubeAPIQPS == 0 { + obj.KubeAPIQPS = 20.0 + } + if obj.KubeAPIBurst == 0 { + obj.KubeAPIBurst = 30 + } + if obj.ControllerStartInterval == zero { + obj.ControllerStartInterval = metav1.Duration{Duration: 0 * time.Second} + } +} + +func SetDefaults_KubeCloudSharedConfiguration(obj *KubeCloudSharedConfiguration) { + zero := metav1.Duration{} + // Port + if obj.Address == "" { + obj.Address = "0.0.0.0" + } + if obj.RouteReconciliationPeriod == zero { + obj.RouteReconciliationPeriod = metav1.Duration{Duration: 10 * time.Second} + } + if obj.NodeMonitorPeriod == zero { + obj.NodeMonitorPeriod = metav1.Duration{Duration: 5 * time.Second} + } + if obj.ClusterName == "" { + obj.ClusterName = "kubernetes" + } + if obj.ConfigureCloudRoutes == nil { + obj.ConfigureCloudRoutes = utilpointer.BoolPtr(true) + } +} + +func SetDefaults_PersistentVolumeRecyclerConfiguration(obj *PersistentVolumeRecyclerConfiguration) { + if obj.MaximumRetry == 0 { + obj.MaximumRetry = 3 + } + if obj.MinimumTimeoutNFS == 0 { + obj.MinimumTimeoutNFS = 300 + } + if obj.IncrementTimeoutNFS == 0 { + obj.IncrementTimeoutNFS = 30 + } + if obj.MinimumTimeoutHostPath == 0 { + obj.MinimumTimeoutHostPath = 60 + } + if obj.IncrementTimeoutHostPath == 0 { + obj.IncrementTimeoutHostPath = 30 + } +} + +func SetDefaults_VolumeConfiguration(obj *VolumeConfiguration) { + if obj.EnableHostPathProvisioning == nil { + obj.EnableHostPathProvisioning = utilpointer.BoolPtr(false) + } + if obj.EnableDynamicProvisioning == nil { + obj.EnableDynamicProvisioning = utilpointer.BoolPtr(true) + } + if obj.FlexVolumePluginDir == "" { + obj.FlexVolumePluginDir = "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/" + } +} + func SetDefaults_KubeSchedulerConfiguration(obj *KubeSchedulerConfiguration) { if len(obj.SchedulerName) == 0 { obj.SchedulerName = api.DefaultSchedulerName @@ -108,4 +291,7 @@ func SetDefaults_LeaderElectionConfiguration(obj *LeaderElectionConfiguration) { // obj.ResourceLock = rl.EndpointsResourceLock obj.ResourceLock = "endpoints" } + if obj.LeaderElect == nil { + obj.LeaderElect = utilpointer.BoolPtr(true) + } } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/defaults_test.go b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/defaults_test.go index 14ae4bc00..77bd8931e 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/defaults_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/defaults_test.go @@ -41,3 +41,21 @@ func TestSchedulerDefaults(t *testing.T) { t.Errorf("Expected:\n%#v\n\nGot:\n%#v", ks1, ks2) } } + +func TestControllerDefaultsRoundTrip(t *testing.T) { + ks1 := &KubeControllerManagerConfiguration{} + SetDefaults_KubeControllerManagerConfiguration(ks1) + cm, err := componentconfig.ConvertObjToConfigMap("KubeControllerManagerConfiguration", ks1) + if err != nil { + t.Errorf("unexpected ConvertObjToConfigMap error %v", err) + } + + ks2 := &KubeControllerManagerConfiguration{} + if err = json.Unmarshal([]byte(cm.Data["KubeControllerManagerConfiguration"]), ks2); err != nil { + t.Errorf("unexpected error unserializing controller manager config %v", err) + } + + if !reflect.DeepEqual(ks2, ks1) { + t.Errorf("Expected:\n%#v\n\nGot:\n%#v", ks1, ks2) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/types.go b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/types.go index 55e99fb42..55b10a115 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/types.go @@ -106,6 +106,9 @@ type KubeSchedulerConfiguration struct { // Indicate the "all topologies" set for empty topologyKey when it's used for PreferredDuringScheduling pod anti-affinity. FailureDomains string `json:"failureDomains"` + + // DisablePreemption disables the pod preemption feature. + DisablePreemption bool `json:"disablePreemption"` } // LeaderElectionConfiguration defines the configuration of leader election @@ -146,6 +149,421 @@ type KubeSchedulerLeaderElectionConfiguration struct { LockObjectName string `json:"lockObjectName"` } +type PersistentVolumeRecyclerConfiguration struct { + // maximumRetry is number of retries the PV recycler will execute on failure to recycle + // PV. + MaximumRetry int32 `json:"maximumRetry"` + // minimumTimeoutNFS is the minimum ActiveDeadlineSeconds to use for an NFS Recycler + // pod. + MinimumTimeoutNFS int32 `json:"minimumTimeoutNFS"` + // podTemplateFilePathNFS is the file path to a pod definition used as a template for + // NFS persistent volume recycling + PodTemplateFilePathNFS string `json:"podTemplateFilePathNFS"` + // incrementTimeoutNFS is the increment of time added per Gi to ActiveDeadlineSeconds + // for an NFS scrubber pod. + IncrementTimeoutNFS int32 `json:"incrementTimeoutNFS"` + // podTemplateFilePathHostPath is the file path to a pod definition used as a template for + // HostPath persistent volume recycling. This is for development and testing only and + // will not work in a multi-node cluster. + PodTemplateFilePathHostPath string `json:"podTemplateFilePathHostPath"` + // minimumTimeoutHostPath is the minimum ActiveDeadlineSeconds to use for a HostPath + // Recycler pod. This is for development and testing only and will not work in a multi-node + // cluster. + MinimumTimeoutHostPath int32 `json:"minimumTimeoutHostPath"` + // incrementTimeoutHostPath is the increment of time added per Gi to ActiveDeadlineSeconds + // for a HostPath scrubber pod. This is for development and testing only and will not work + // in a multi-node cluster. + IncrementTimeoutHostPath int32 `json:"incrementTimeoutHostPath"` +} + +// VolumeConfiguration contains *all* enumerated flags meant to configure all volume +// plugins. From this config, the controller-manager binary will create many instances of +// volume.VolumeConfig, each containing only the configuration needed for that plugin which +// are then passed to the appropriate plugin. The ControllerManager binary is the only part +// of the code which knows what plugins are supported and which flags correspond to each plugin. +type VolumeConfiguration struct { + // enableHostPathProvisioning enables HostPath PV provisioning when running without a + // cloud provider. This allows testing and development of provisioning features. HostPath + // provisioning is not supported in any way, won't work in a multi-node cluster, and + // should not be used for anything other than testing or development. + EnableHostPathProvisioning *bool `json:"enableHostPathProvisioning"` + // enableDynamicProvisioning enables the provisioning of volumes when running within an environment + // that supports dynamic provisioning. Defaults to true. + EnableDynamicProvisioning *bool `json:"enableDynamicProvisioning"` + // persistentVolumeRecyclerConfiguration holds configuration for persistent volume plugins. + PersistentVolumeRecyclerConfiguration PersistentVolumeRecyclerConfiguration `json:"persistentVolumeRecyclerConfiguration"` + // volumePluginDir is the full path of the directory in which the flex + // volume plugin should search for additional third party volume plugins + FlexVolumePluginDir string `json:"flexVolumePluginDir"` +} + +type GroupResource struct { + // group is the group portion of the GroupResource. + Group string `json:"group"` + // resource is the resource portion of the GroupResource. + Resource string `json:"resource"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type KubeControllerManagerConfiguration struct { + metav1.TypeMeta `json:",inline"` + + // CloudProviderConfiguration holds configuration for CloudProvider related features. + CloudProvider CloudProviderConfiguration + // DebuggingConfiguration holds configuration for Debugging related features. + Debugging DebuggingConfiguration + // GenericComponentConfiguration holds configuration for GenericComponent + // related features both in cloud controller manager and kube-controller manager. + GenericComponent GenericComponentConfiguration + // KubeCloudSharedConfiguration holds configuration for shared related features + // both in cloud controller manager and kube-controller manager. + KubeCloudShared KubeCloudSharedConfiguration + + // AttachDetachControllerConfiguration holds configuration for + // AttachDetachController related features. + AttachDetachController AttachDetachControllerConfiguration + // CSRSigningControllerConfiguration holds configuration for + // CSRSigningController related features. + CSRSigningController CSRSigningControllerConfiguration + // DaemonSetControllerConfiguration holds configuration for DaemonSetController + // related features. + DaemonSetController DaemonSetControllerConfiguration + // DeploymentControllerConfiguration holds configuration for + // DeploymentController related features. + DeploymentController DeploymentControllerConfiguration + // DeprecatedControllerConfiguration holds configuration for some deprecated + // features. + DeprecatedController DeprecatedControllerConfiguration + // EndPointControllerConfiguration holds configuration for EndPointController + // related features. + EndPointController EndPointControllerConfiguration + // GarbageCollectorControllerConfiguration holds configuration for + // GarbageCollectorController related features. + GarbageCollectorController GarbageCollectorControllerConfiguration + // HPAControllerConfiguration holds configuration for HPAController related features. + HPAController HPAControllerConfiguration + // JobControllerConfiguration holds configuration for JobController related features. + JobController JobControllerConfiguration + // NamespaceControllerConfiguration holds configuration for NamespaceController + // related features. + NamespaceController NamespaceControllerConfiguration + // NodeIpamControllerConfiguration holds configuration for NodeIpamController + // related features. + NodeIpamController NodeIpamControllerConfiguration + // NodeLifecycleControllerConfiguration holds configuration for + // NodeLifecycleController related features. + NodeLifecycleController NodeLifecycleControllerConfiguration + // PersistentVolumeBinderControllerConfiguration holds configuration for + // PersistentVolumeBinderController related features. + PersistentVolumeBinderController PersistentVolumeBinderControllerConfiguration + // PodGCControllerConfiguration holds configuration for PodGCController + // related features. + PodGCController PodGCControllerConfiguration + // ReplicaSetControllerConfiguration holds configuration for ReplicaSet related features. + ReplicaSetController ReplicaSetControllerConfiguration + // ReplicationControllerConfiguration holds configuration for + // ReplicationController related features. + ReplicationController ReplicationControllerConfiguration + // ResourceQuotaControllerConfiguration holds configuration for + // ResourceQuotaController related features. + ResourceQuotaController ResourceQuotaControllerConfiguration + // SAControllerConfiguration holds configuration for ServiceAccountController + // related features. + SAController SAControllerConfiguration + // ServiceControllerConfiguration holds configuration for ServiceController + // related features. + ServiceController ServiceControllerConfiguration + + // Controllers is the list of controllers to enable or disable + // '*' means "all enabled by default controllers" + // 'foo' means "enable 'foo'" + // '-foo' means "disable 'foo'" + // first item for a particular name wins + Controllers []string `json:"controllers"` + // externalCloudVolumePlugin specifies the plugin to use when cloudProvider is "external". + // It is currently used by the in repo cloud providers to handle node and volume control in the KCM. + ExternalCloudVolumePlugin string `json:"externalCloudVolumePlugin"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type CloudControllerManagerConfiguration struct { + metav1.TypeMeta `json:",inline"` + + // CloudProviderConfiguration holds configuration for CloudProvider related features. + CloudProvider CloudProviderConfiguration + // DebuggingConfiguration holds configuration for Debugging related features. + Debugging DebuggingConfiguration + // GenericComponentConfiguration holds configuration for GenericComponent + // related features both in cloud controller manager and kube-controller manager. + GenericComponent GenericComponentConfiguration + // KubeCloudSharedConfiguration holds configuration for shared related features + // both in cloud controller manager and kube-controller manager. + KubeCloudShared KubeCloudSharedConfiguration + // ServiceControllerConfiguration holds configuration for ServiceController + // related features. + ServiceController ServiceControllerConfiguration + // NodeStatusUpdateFrequency is the frequency at which the controller updates nodes' status + NodeStatusUpdateFrequency metav1.Duration +} + +type CloudProviderConfiguration struct { + // Name is the provider for cloud services. + Name string `json:"cloudProvider"` + // cloudConfigFile is the path to the cloud provider configuration file. + CloudConfigFile string `json:"cloudConfigFile"` +} + +type DebuggingConfiguration struct { + // enableProfiling enables profiling via web interface host:port/debug/pprof/ + EnableProfiling bool `json:"enableProfiling"` + // EnableContentionProfiling enables lock contention profiling, if + // EnableProfiling is true. + EnableContentionProfiling bool `json:"enableContentionProfiling"` +} + +type GenericComponentConfiguration struct { + + // minResyncPeriod is the resync period in reflectors; will be random between + // minResyncPeriod and 2*minResyncPeriod. + MinResyncPeriod metav1.Duration `json:"minResyncPeriod"` + // contentType is contentType of requests sent to apiserver. + ContentType string `json:"contentType"` + // kubeAPIQPS is the QPS to use while talking with kubernetes apiserver. + KubeAPIQPS float32 `json:"kubeAPIQPS"` + // kubeAPIBurst is the burst to use while talking with kubernetes apiserver. + KubeAPIBurst int32 `json:"kubeAPIBurst"` + // How long to wait between starting controller managers + ControllerStartInterval metav1.Duration `json:"controllerStartInterval"` + // leaderElection defines the configuration of leader election client. + LeaderElection LeaderElectionConfiguration `json:"leaderElection"` +} + +type KubeCloudSharedConfiguration struct { + // port is the port that the controller-manager's http service runs on. + Port int32 `json:"port"` + // address is the IP address to serve on (set to 0.0.0.0 for all interfaces). + Address string `json:"address"` + // useServiceAccountCredentials indicates whether controllers should be run with + // individual service account credentials. + UseServiceAccountCredentials bool `json:"useServiceAccountCredentials"` + // run with untagged cloud instances + AllowUntaggedCloud bool `json:"allowUntaggedCloud"` + // routeReconciliationPeriod is the period for reconciling routes created for Nodes by cloud provider.. + RouteReconciliationPeriod metav1.Duration `json:"routeReconciliationPeriod"` + // nodeMonitorPeriod is the period for syncing NodeStatus in NodeController. + NodeMonitorPeriod metav1.Duration `json:"nodeMonitorPeriod"` + // clusterName is the instance prefix for the cluster. + ClusterName string `json:"clusterName"` + // clusterCIDR is CIDR Range for Pods in cluster. + ClusterCIDR string `json:"clusterCIDR"` + // AllocateNodeCIDRs enables CIDRs for Pods to be allocated and, if + // ConfigureCloudRoutes is true, to be set on the cloud provider. + AllocateNodeCIDRs bool `json:"allocateNodeCIDRs"` + // CIDRAllocatorType determines what kind of pod CIDR allocator will be used. + CIDRAllocatorType string `json:"cIDRAllocatorType"` + // configureCloudRoutes enables CIDRs allocated with allocateNodeCIDRs + // to be configured on the cloud provider. + ConfigureCloudRoutes *bool `json:"configureCloudRoutes"` + // nodeSyncPeriod is the period for syncing nodes from cloudprovider. Longer + // periods will result in fewer calls to cloud provider, but may delay addition + // of new nodes to cluster. + NodeSyncPeriod metav1.Duration `json:"nodeSyncPeriod"` +} + +type AttachDetachControllerConfiguration struct { + // Reconciler runs a periodic loop to reconcile the desired state of the with + // the actual state of the world by triggering attach detach operations. + // This flag enables or disables reconcile. Is false by default, and thus enabled. + DisableAttachDetachReconcilerSync bool `json:"disableAttachDetachReconcilerSync"` + // ReconcilerSyncLoopPeriod is the amount of time the reconciler sync states loop + // wait between successive executions. Is set to 5 sec by default. + ReconcilerSyncLoopPeriod metav1.Duration `json:"reconcilerSyncLoopPeriod"` +} + +type CSRSigningControllerConfiguration struct { + // clusterSigningCertFile is the filename containing a PEM-encoded + // X509 CA certificate used to issue cluster-scoped certificates + ClusterSigningCertFile string `json:"clusterSigningCertFile"` + // clusterSigningCertFile is the filename containing a PEM-encoded + // RSA or ECDSA private key used to issue cluster-scoped certificates + ClusterSigningKeyFile string `json:"clusterSigningKeyFile"` + // clusterSigningDuration is the length of duration signed certificates + // will be given. + ClusterSigningDuration metav1.Duration `json:"clusterSigningDuration"` +} + +type DaemonSetControllerConfiguration struct { + // concurrentDaemonSetSyncs is the number of daemonset objects that are + // allowed to sync concurrently. Larger number = more responsive daemonset, + // but more CPU (and network) load. + ConcurrentDaemonSetSyncs int32 `json:"concurrentDaemonSetSyncs"` +} + +type DeploymentControllerConfiguration struct { + // concurrentDeploymentSyncs is the number of deployment objects that are + // allowed to sync concurrently. Larger number = more responsive deployments, + // but more CPU (and network) load. + ConcurrentDeploymentSyncs int32 `json:"concurrentDeploymentSyncs"` + // deploymentControllerSyncPeriod is the period for syncing the deployments. + DeploymentControllerSyncPeriod metav1.Duration `json:"deploymentControllerSyncPeriod"` +} + +type DeprecatedControllerConfiguration struct { + // DEPRECATED: deletingPodsQps is the number of nodes per second on which pods are deleted in + // case of node failure. + DeletingPodsQps float32 `json:"deletingPodsQps"` + // DEPRECATED: deletingPodsBurst is the number of nodes on which pods are bursty deleted in + // case of node failure. For more details look into RateLimiter. + DeletingPodsBurst int32 `json:"deletingPodsBurst"` + // registerRetryCount is the number of retries for initial node registration. + // Retry interval equals node-sync-period. + RegisterRetryCount int32 `json:"registerRetryCount"` +} + +type EndPointControllerConfiguration struct { + // concurrentEndpointSyncs is the number of endpoint syncing operations + // that will be done concurrently. Larger number = faster endpoint updating, + // but more CPU (and network) load. + ConcurrentEndpointSyncs int32 `json:"concurrentEndpointSyncs"` +} + +type GarbageCollectorControllerConfiguration struct { + // enables the generic garbage collector. MUST be synced with the + // corresponding flag of the kube-apiserver. WARNING: the generic garbage + // collector is an alpha feature. + EnableGarbageCollector *bool `json:"enableGarbageCollector"` + // concurrentGCSyncs is the number of garbage collector workers that are + // allowed to sync concurrently. + ConcurrentGCSyncs int32 `json:"concurrentGCSyncs"` + // gcIgnoredResources is the list of GroupResources that garbage collection should ignore. + GCIgnoredResources []GroupResource `json:"gCIgnoredResources"` +} + +type HPAControllerConfiguration struct { + // horizontalPodAutoscalerSyncPeriod is the period for syncing the number of + // pods in horizontal pod autoscaler. + HorizontalPodAutoscalerSyncPeriod metav1.Duration `json:"horizontalPodAutoscalerSyncPeriod"` + // horizontalPodAutoscalerUpscaleForbiddenWindow is a period after which next upscale allowed. + HorizontalPodAutoscalerUpscaleForbiddenWindow metav1.Duration `json:"horizontalPodAutoscalerUpscaleForbiddenWindow"` + // horizontalPodAutoscalerDownscaleForbiddenWindow is a period after which next downscale allowed. + HorizontalPodAutoscalerDownscaleForbiddenWindow metav1.Duration `json:"horizontalPodAutoscalerDownscaleForbiddenWindow"` + // horizontalPodAutoscalerTolerance is the tolerance for when + // resource usage suggests upscaling/downscaling + HorizontalPodAutoscalerTolerance float64 `json:"horizontalPodAutoscalerTolerance"` + // HorizontalPodAutoscalerUseRESTClients causes the HPA controller to use REST clients + // through the kube-aggregator when enabled, instead of using the legacy metrics client + // through the API server proxy. + HorizontalPodAutoscalerUseRESTClients *bool `json:"horizontalPodAutoscalerUseRESTClients"` +} + +type JobControllerConfiguration struct { + // concurrentJobSyncs is the number of job objects that are + // allowed to sync concurrently. Larger number = more responsive jobs, + // but more CPU (and network) load. + ConcurrentJobSyncs int32 +} + +type NamespaceControllerConfiguration struct { + // namespaceSyncPeriod is the period for syncing namespace life-cycle + // updates. + NamespaceSyncPeriod metav1.Duration `json:"namespaceSyncPeriod"` + // concurrentNamespaceSyncs is the number of namespace objects that are + // allowed to sync concurrently. + ConcurrentNamespaceSyncs int32 `json:"concurrentNamespaceSyncs"` +} + +type NodeIpamControllerConfiguration struct { + // serviceCIDR is CIDR Range for Services in cluster. + ServiceCIDR string `json:"serviceCIDR"` + // NodeCIDRMaskSize is the mask size for node cidr in cluster. + NodeCIDRMaskSize int32 `json:"nodeCIDRMaskSize"` +} + +type NodeLifecycleControllerConfiguration struct { + // If set to true enables NoExecute Taints and will evict all not-tolerating + // Pod running on Nodes tainted with this kind of Taints. + EnableTaintManager *bool `json:"enableTaintManager"` + // nodeEvictionRate is the number of nodes per second on which pods are deleted in case of node failure when a zone is healthy + NodeEvictionRate float32 `json:"nodeEvictionRate"` + // secondaryNodeEvictionRate is the number of nodes per second on which pods are deleted in case of node failure when a zone is unhealthy + SecondaryNodeEvictionRate float32 `json:"secondaryNodeEvictionRate"` + // nodeStartupGracePeriod is the amount of time which we allow starting a node to + // be unresponsive before marking it unhealthy. + NodeStartupGracePeriod metav1.Duration `json:"nodeStartupGracePeriod"` + // nodeMontiorGracePeriod is the amount of time which we allow a running node to be + // unresponsive before marking it unhealthy. Must be N times more than kubelet's + // nodeStatusUpdateFrequency, where N means number of retries allowed for kubelet + // to post node status. + NodeMonitorGracePeriod metav1.Duration `json:"nodeMonitorGracePeriod"` + // podEvictionTimeout is the grace period for deleting pods on failed nodes. + PodEvictionTimeout metav1.Duration `json:"podEvictionTimeout"` + // secondaryNodeEvictionRate is implicitly overridden to 0 for clusters smaller than or equal to largeClusterSizeThreshold + LargeClusterSizeThreshold int32 `json:"largeClusterSizeThreshold"` + // Zone is treated as unhealthy in nodeEvictionRate and secondaryNodeEvictionRate when at least + // unhealthyZoneThreshold (no less than 3) of Nodes in the zone are NotReady + UnhealthyZoneThreshold float32 `json:"unhealthyZoneThreshold"` +} + +type PersistentVolumeBinderControllerConfiguration struct { + // pvClaimBinderSyncPeriod is the period for syncing persistent volumes + // and persistent volume claims. + PVClaimBinderSyncPeriod metav1.Duration `json:"pVClaimBinderSyncPeriod"` + // volumeConfiguration holds configuration for volume related features. + VolumeConfiguration VolumeConfiguration `json:"volumeConfiguration"` +} + +type PodGCControllerConfiguration struct { + // terminatedPodGCThreshold is the number of terminated pods that can exist + // before the terminated pod garbage collector starts deleting terminated pods. + // If <= 0, the terminated pod garbage collector is disabled. + TerminatedPodGCThreshold int32 `json:"terminatedPodGCThreshold"` +} + +type ReplicaSetControllerConfiguration struct { + // concurrentRSSyncs is the number of replica sets that are allowed to sync + // concurrently. Larger number = more responsive replica management, but more + // CPU (and network) load. + ConcurrentRSSyncs int32 `json:"concurrentRSSyncs"` +} + +type ReplicationControllerConfiguration struct { + // concurrentRCSyncs is the number of replication controllers that are + // allowed to sync concurrently. Larger number = more responsive replica + // management, but more CPU (and network) load. + ConcurrentRCSyncs int32 `json:"concurrentRCSyncs"` +} + +type ResourceQuotaControllerConfiguration struct { + // resourceQuotaSyncPeriod is the period for syncing quota usage status + // in the system. + ResourceQuotaSyncPeriod metav1.Duration `json:"resourceQuotaSyncPeriod"` + // concurrentResourceQuotaSyncs is the number of resource quotas that are + // allowed to sync concurrently. Larger number = more responsive quota + // management, but more CPU (and network) load. + ConcurrentResourceQuotaSyncs int32 `json:"concurrentResourceQuotaSyncs"` +} + +type SAControllerConfiguration struct { + // serviceAccountKeyFile is the filename containing a PEM-encoded private RSA key + // used to sign service account tokens. + ServiceAccountKeyFile string `json:"serviceAccountKeyFile"` + // concurrentSATokenSyncs is the number of service account token syncing operations + // that will be done concurrently. + ConcurrentSATokenSyncs int32 `json:"concurrentSATokenSyncs"` + // rootCAFile is the root certificate authority will be included in service + // account's token secret. This must be a valid PEM-encoded CA bundle. + RootCAFile string `json:"rootCAFile"` +} + +type ServiceControllerConfiguration struct { + // concurrentServiceSyncs is the number of services that are + // allowed to sync concurrently. Larger number = more responsive service + // management, but more CPU (and network) load. + ConcurrentServiceSyncs int32 `json:"concurrentServiceSyncs"` +} + const ( // "kube-system" is the default scheduler lock object namespace SchedulerDefaultLockObjectNamespace string = "kube-system" diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go index b006f9ecc..3412cc7c0 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -37,14 +37,66 @@ func init() { // Public to allow building arbitrary schemes. func RegisterConversions(scheme *runtime.Scheme) error { return scheme.AddGeneratedConversionFuncs( + Convert_v1alpha1_AttachDetachControllerConfiguration_To_componentconfig_AttachDetachControllerConfiguration, + Convert_componentconfig_AttachDetachControllerConfiguration_To_v1alpha1_AttachDetachControllerConfiguration, + Convert_v1alpha1_CSRSigningControllerConfiguration_To_componentconfig_CSRSigningControllerConfiguration, + Convert_componentconfig_CSRSigningControllerConfiguration_To_v1alpha1_CSRSigningControllerConfiguration, Convert_v1alpha1_ClientConnectionConfiguration_To_componentconfig_ClientConnectionConfiguration, Convert_componentconfig_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration, + Convert_v1alpha1_CloudControllerManagerConfiguration_To_componentconfig_CloudControllerManagerConfiguration, + Convert_componentconfig_CloudControllerManagerConfiguration_To_v1alpha1_CloudControllerManagerConfiguration, + Convert_v1alpha1_CloudProviderConfiguration_To_componentconfig_CloudProviderConfiguration, + Convert_componentconfig_CloudProviderConfiguration_To_v1alpha1_CloudProviderConfiguration, + Convert_v1alpha1_DaemonSetControllerConfiguration_To_componentconfig_DaemonSetControllerConfiguration, + Convert_componentconfig_DaemonSetControllerConfiguration_To_v1alpha1_DaemonSetControllerConfiguration, + Convert_v1alpha1_DebuggingConfiguration_To_componentconfig_DebuggingConfiguration, + Convert_componentconfig_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration, + Convert_v1alpha1_DeploymentControllerConfiguration_To_componentconfig_DeploymentControllerConfiguration, + Convert_componentconfig_DeploymentControllerConfiguration_To_v1alpha1_DeploymentControllerConfiguration, + Convert_v1alpha1_DeprecatedControllerConfiguration_To_componentconfig_DeprecatedControllerConfiguration, + Convert_componentconfig_DeprecatedControllerConfiguration_To_v1alpha1_DeprecatedControllerConfiguration, + Convert_v1alpha1_EndPointControllerConfiguration_To_componentconfig_EndPointControllerConfiguration, + Convert_componentconfig_EndPointControllerConfiguration_To_v1alpha1_EndPointControllerConfiguration, + Convert_v1alpha1_GarbageCollectorControllerConfiguration_To_componentconfig_GarbageCollectorControllerConfiguration, + Convert_componentconfig_GarbageCollectorControllerConfiguration_To_v1alpha1_GarbageCollectorControllerConfiguration, + Convert_v1alpha1_GenericComponentConfiguration_To_componentconfig_GenericComponentConfiguration, + Convert_componentconfig_GenericComponentConfiguration_To_v1alpha1_GenericComponentConfiguration, + Convert_v1alpha1_GroupResource_To_componentconfig_GroupResource, + Convert_componentconfig_GroupResource_To_v1alpha1_GroupResource, + Convert_v1alpha1_HPAControllerConfiguration_To_componentconfig_HPAControllerConfiguration, + Convert_componentconfig_HPAControllerConfiguration_To_v1alpha1_HPAControllerConfiguration, + Convert_v1alpha1_JobControllerConfiguration_To_componentconfig_JobControllerConfiguration, + Convert_componentconfig_JobControllerConfiguration_To_v1alpha1_JobControllerConfiguration, + Convert_v1alpha1_KubeCloudSharedConfiguration_To_componentconfig_KubeCloudSharedConfiguration, + Convert_componentconfig_KubeCloudSharedConfiguration_To_v1alpha1_KubeCloudSharedConfiguration, + Convert_v1alpha1_KubeControllerManagerConfiguration_To_componentconfig_KubeControllerManagerConfiguration, + Convert_componentconfig_KubeControllerManagerConfiguration_To_v1alpha1_KubeControllerManagerConfiguration, Convert_v1alpha1_KubeSchedulerConfiguration_To_componentconfig_KubeSchedulerConfiguration, Convert_componentconfig_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration, Convert_v1alpha1_KubeSchedulerLeaderElectionConfiguration_To_componentconfig_KubeSchedulerLeaderElectionConfiguration, Convert_componentconfig_KubeSchedulerLeaderElectionConfiguration_To_v1alpha1_KubeSchedulerLeaderElectionConfiguration, Convert_v1alpha1_LeaderElectionConfiguration_To_componentconfig_LeaderElectionConfiguration, Convert_componentconfig_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration, + Convert_v1alpha1_NamespaceControllerConfiguration_To_componentconfig_NamespaceControllerConfiguration, + Convert_componentconfig_NamespaceControllerConfiguration_To_v1alpha1_NamespaceControllerConfiguration, + Convert_v1alpha1_NodeIpamControllerConfiguration_To_componentconfig_NodeIpamControllerConfiguration, + Convert_componentconfig_NodeIpamControllerConfiguration_To_v1alpha1_NodeIpamControllerConfiguration, + Convert_v1alpha1_NodeLifecycleControllerConfiguration_To_componentconfig_NodeLifecycleControllerConfiguration, + Convert_componentconfig_NodeLifecycleControllerConfiguration_To_v1alpha1_NodeLifecycleControllerConfiguration, + Convert_v1alpha1_PersistentVolumeBinderControllerConfiguration_To_componentconfig_PersistentVolumeBinderControllerConfiguration, + Convert_componentconfig_PersistentVolumeBinderControllerConfiguration_To_v1alpha1_PersistentVolumeBinderControllerConfiguration, + Convert_v1alpha1_PersistentVolumeRecyclerConfiguration_To_componentconfig_PersistentVolumeRecyclerConfiguration, + Convert_componentconfig_PersistentVolumeRecyclerConfiguration_To_v1alpha1_PersistentVolumeRecyclerConfiguration, + Convert_v1alpha1_PodGCControllerConfiguration_To_componentconfig_PodGCControllerConfiguration, + Convert_componentconfig_PodGCControllerConfiguration_To_v1alpha1_PodGCControllerConfiguration, + Convert_v1alpha1_ReplicaSetControllerConfiguration_To_componentconfig_ReplicaSetControllerConfiguration, + Convert_componentconfig_ReplicaSetControllerConfiguration_To_v1alpha1_ReplicaSetControllerConfiguration, + Convert_v1alpha1_ReplicationControllerConfiguration_To_componentconfig_ReplicationControllerConfiguration, + Convert_componentconfig_ReplicationControllerConfiguration_To_v1alpha1_ReplicationControllerConfiguration, + Convert_v1alpha1_ResourceQuotaControllerConfiguration_To_componentconfig_ResourceQuotaControllerConfiguration, + Convert_componentconfig_ResourceQuotaControllerConfiguration_To_v1alpha1_ResourceQuotaControllerConfiguration, + Convert_v1alpha1_SAControllerConfiguration_To_componentconfig_SAControllerConfiguration, + Convert_componentconfig_SAControllerConfiguration_To_v1alpha1_SAControllerConfiguration, Convert_v1alpha1_SchedulerAlgorithmSource_To_componentconfig_SchedulerAlgorithmSource, Convert_componentconfig_SchedulerAlgorithmSource_To_v1alpha1_SchedulerAlgorithmSource, Convert_v1alpha1_SchedulerPolicyConfigMapSource_To_componentconfig_SchedulerPolicyConfigMapSource, @@ -53,9 +105,59 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_componentconfig_SchedulerPolicyFileSource_To_v1alpha1_SchedulerPolicyFileSource, Convert_v1alpha1_SchedulerPolicySource_To_componentconfig_SchedulerPolicySource, Convert_componentconfig_SchedulerPolicySource_To_v1alpha1_SchedulerPolicySource, + Convert_v1alpha1_ServiceControllerConfiguration_To_componentconfig_ServiceControllerConfiguration, + Convert_componentconfig_ServiceControllerConfiguration_To_v1alpha1_ServiceControllerConfiguration, + Convert_v1alpha1_VolumeConfiguration_To_componentconfig_VolumeConfiguration, + Convert_componentconfig_VolumeConfiguration_To_v1alpha1_VolumeConfiguration, ) } +func autoConvert_v1alpha1_AttachDetachControllerConfiguration_To_componentconfig_AttachDetachControllerConfiguration(in *AttachDetachControllerConfiguration, out *componentconfig.AttachDetachControllerConfiguration, s conversion.Scope) error { + out.DisableAttachDetachReconcilerSync = in.DisableAttachDetachReconcilerSync + out.ReconcilerSyncLoopPeriod = in.ReconcilerSyncLoopPeriod + return nil +} + +// Convert_v1alpha1_AttachDetachControllerConfiguration_To_componentconfig_AttachDetachControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_AttachDetachControllerConfiguration_To_componentconfig_AttachDetachControllerConfiguration(in *AttachDetachControllerConfiguration, out *componentconfig.AttachDetachControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_AttachDetachControllerConfiguration_To_componentconfig_AttachDetachControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_AttachDetachControllerConfiguration_To_v1alpha1_AttachDetachControllerConfiguration(in *componentconfig.AttachDetachControllerConfiguration, out *AttachDetachControllerConfiguration, s conversion.Scope) error { + out.DisableAttachDetachReconcilerSync = in.DisableAttachDetachReconcilerSync + out.ReconcilerSyncLoopPeriod = in.ReconcilerSyncLoopPeriod + return nil +} + +// Convert_componentconfig_AttachDetachControllerConfiguration_To_v1alpha1_AttachDetachControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_AttachDetachControllerConfiguration_To_v1alpha1_AttachDetachControllerConfiguration(in *componentconfig.AttachDetachControllerConfiguration, out *AttachDetachControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_AttachDetachControllerConfiguration_To_v1alpha1_AttachDetachControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_CSRSigningControllerConfiguration_To_componentconfig_CSRSigningControllerConfiguration(in *CSRSigningControllerConfiguration, out *componentconfig.CSRSigningControllerConfiguration, s conversion.Scope) error { + out.ClusterSigningCertFile = in.ClusterSigningCertFile + out.ClusterSigningKeyFile = in.ClusterSigningKeyFile + out.ClusterSigningDuration = in.ClusterSigningDuration + return nil +} + +// Convert_v1alpha1_CSRSigningControllerConfiguration_To_componentconfig_CSRSigningControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_CSRSigningControllerConfiguration_To_componentconfig_CSRSigningControllerConfiguration(in *CSRSigningControllerConfiguration, out *componentconfig.CSRSigningControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_CSRSigningControllerConfiguration_To_componentconfig_CSRSigningControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_CSRSigningControllerConfiguration_To_v1alpha1_CSRSigningControllerConfiguration(in *componentconfig.CSRSigningControllerConfiguration, out *CSRSigningControllerConfiguration, s conversion.Scope) error { + out.ClusterSigningCertFile = in.ClusterSigningCertFile + out.ClusterSigningKeyFile = in.ClusterSigningKeyFile + out.ClusterSigningDuration = in.ClusterSigningDuration + return nil +} + +// Convert_componentconfig_CSRSigningControllerConfiguration_To_v1alpha1_CSRSigningControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_CSRSigningControllerConfiguration_To_v1alpha1_CSRSigningControllerConfiguration(in *componentconfig.CSRSigningControllerConfiguration, out *CSRSigningControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_CSRSigningControllerConfiguration_To_v1alpha1_CSRSigningControllerConfiguration(in, out, s) +} + func autoConvert_v1alpha1_ClientConnectionConfiguration_To_componentconfig_ClientConnectionConfiguration(in *ClientConnectionConfiguration, out *componentconfig.ClientConnectionConfiguration, s conversion.Scope) error { out.KubeConfigFile = in.KubeConfigFile out.AcceptContentTypes = in.AcceptContentTypes @@ -84,6 +186,528 @@ func Convert_componentconfig_ClientConnectionConfiguration_To_v1alpha1_ClientCon return autoConvert_componentconfig_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(in, out, s) } +func autoConvert_v1alpha1_CloudControllerManagerConfiguration_To_componentconfig_CloudControllerManagerConfiguration(in *CloudControllerManagerConfiguration, out *componentconfig.CloudControllerManagerConfiguration, s conversion.Scope) error { + if err := Convert_v1alpha1_CloudProviderConfiguration_To_componentconfig_CloudProviderConfiguration(&in.CloudProvider, &out.CloudProvider, s); err != nil { + return err + } + if err := Convert_v1alpha1_DebuggingConfiguration_To_componentconfig_DebuggingConfiguration(&in.Debugging, &out.Debugging, s); err != nil { + return err + } + if err := Convert_v1alpha1_GenericComponentConfiguration_To_componentconfig_GenericComponentConfiguration(&in.GenericComponent, &out.GenericComponent, s); err != nil { + return err + } + if err := Convert_v1alpha1_KubeCloudSharedConfiguration_To_componentconfig_KubeCloudSharedConfiguration(&in.KubeCloudShared, &out.KubeCloudShared, s); err != nil { + return err + } + if err := Convert_v1alpha1_ServiceControllerConfiguration_To_componentconfig_ServiceControllerConfiguration(&in.ServiceController, &out.ServiceController, s); err != nil { + return err + } + out.NodeStatusUpdateFrequency = in.NodeStatusUpdateFrequency + return nil +} + +// Convert_v1alpha1_CloudControllerManagerConfiguration_To_componentconfig_CloudControllerManagerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_CloudControllerManagerConfiguration_To_componentconfig_CloudControllerManagerConfiguration(in *CloudControllerManagerConfiguration, out *componentconfig.CloudControllerManagerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_CloudControllerManagerConfiguration_To_componentconfig_CloudControllerManagerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_CloudControllerManagerConfiguration_To_v1alpha1_CloudControllerManagerConfiguration(in *componentconfig.CloudControllerManagerConfiguration, out *CloudControllerManagerConfiguration, s conversion.Scope) error { + if err := Convert_componentconfig_CloudProviderConfiguration_To_v1alpha1_CloudProviderConfiguration(&in.CloudProvider, &out.CloudProvider, s); err != nil { + return err + } + if err := Convert_componentconfig_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(&in.Debugging, &out.Debugging, s); err != nil { + return err + } + if err := Convert_componentconfig_GenericComponentConfiguration_To_v1alpha1_GenericComponentConfiguration(&in.GenericComponent, &out.GenericComponent, s); err != nil { + return err + } + if err := Convert_componentconfig_KubeCloudSharedConfiguration_To_v1alpha1_KubeCloudSharedConfiguration(&in.KubeCloudShared, &out.KubeCloudShared, s); err != nil { + return err + } + if err := Convert_componentconfig_ServiceControllerConfiguration_To_v1alpha1_ServiceControllerConfiguration(&in.ServiceController, &out.ServiceController, s); err != nil { + return err + } + out.NodeStatusUpdateFrequency = in.NodeStatusUpdateFrequency + return nil +} + +// Convert_componentconfig_CloudControllerManagerConfiguration_To_v1alpha1_CloudControllerManagerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_CloudControllerManagerConfiguration_To_v1alpha1_CloudControllerManagerConfiguration(in *componentconfig.CloudControllerManagerConfiguration, out *CloudControllerManagerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_CloudControllerManagerConfiguration_To_v1alpha1_CloudControllerManagerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_CloudProviderConfiguration_To_componentconfig_CloudProviderConfiguration(in *CloudProviderConfiguration, out *componentconfig.CloudProviderConfiguration, s conversion.Scope) error { + out.Name = in.Name + out.CloudConfigFile = in.CloudConfigFile + return nil +} + +// Convert_v1alpha1_CloudProviderConfiguration_To_componentconfig_CloudProviderConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_CloudProviderConfiguration_To_componentconfig_CloudProviderConfiguration(in *CloudProviderConfiguration, out *componentconfig.CloudProviderConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_CloudProviderConfiguration_To_componentconfig_CloudProviderConfiguration(in, out, s) +} + +func autoConvert_componentconfig_CloudProviderConfiguration_To_v1alpha1_CloudProviderConfiguration(in *componentconfig.CloudProviderConfiguration, out *CloudProviderConfiguration, s conversion.Scope) error { + out.Name = in.Name + out.CloudConfigFile = in.CloudConfigFile + return nil +} + +// Convert_componentconfig_CloudProviderConfiguration_To_v1alpha1_CloudProviderConfiguration is an autogenerated conversion function. +func Convert_componentconfig_CloudProviderConfiguration_To_v1alpha1_CloudProviderConfiguration(in *componentconfig.CloudProviderConfiguration, out *CloudProviderConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_CloudProviderConfiguration_To_v1alpha1_CloudProviderConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_DaemonSetControllerConfiguration_To_componentconfig_DaemonSetControllerConfiguration(in *DaemonSetControllerConfiguration, out *componentconfig.DaemonSetControllerConfiguration, s conversion.Scope) error { + out.ConcurrentDaemonSetSyncs = in.ConcurrentDaemonSetSyncs + return nil +} + +// Convert_v1alpha1_DaemonSetControllerConfiguration_To_componentconfig_DaemonSetControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_DaemonSetControllerConfiguration_To_componentconfig_DaemonSetControllerConfiguration(in *DaemonSetControllerConfiguration, out *componentconfig.DaemonSetControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_DaemonSetControllerConfiguration_To_componentconfig_DaemonSetControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_DaemonSetControllerConfiguration_To_v1alpha1_DaemonSetControllerConfiguration(in *componentconfig.DaemonSetControllerConfiguration, out *DaemonSetControllerConfiguration, s conversion.Scope) error { + out.ConcurrentDaemonSetSyncs = in.ConcurrentDaemonSetSyncs + return nil +} + +// Convert_componentconfig_DaemonSetControllerConfiguration_To_v1alpha1_DaemonSetControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_DaemonSetControllerConfiguration_To_v1alpha1_DaemonSetControllerConfiguration(in *componentconfig.DaemonSetControllerConfiguration, out *DaemonSetControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_DaemonSetControllerConfiguration_To_v1alpha1_DaemonSetControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_DebuggingConfiguration_To_componentconfig_DebuggingConfiguration(in *DebuggingConfiguration, out *componentconfig.DebuggingConfiguration, s conversion.Scope) error { + out.EnableProfiling = in.EnableProfiling + out.EnableContentionProfiling = in.EnableContentionProfiling + return nil +} + +// Convert_v1alpha1_DebuggingConfiguration_To_componentconfig_DebuggingConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_DebuggingConfiguration_To_componentconfig_DebuggingConfiguration(in *DebuggingConfiguration, out *componentconfig.DebuggingConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_DebuggingConfiguration_To_componentconfig_DebuggingConfiguration(in, out, s) +} + +func autoConvert_componentconfig_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(in *componentconfig.DebuggingConfiguration, out *DebuggingConfiguration, s conversion.Scope) error { + out.EnableProfiling = in.EnableProfiling + out.EnableContentionProfiling = in.EnableContentionProfiling + return nil +} + +// Convert_componentconfig_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration is an autogenerated conversion function. +func Convert_componentconfig_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(in *componentconfig.DebuggingConfiguration, out *DebuggingConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_DeploymentControllerConfiguration_To_componentconfig_DeploymentControllerConfiguration(in *DeploymentControllerConfiguration, out *componentconfig.DeploymentControllerConfiguration, s conversion.Scope) error { + out.ConcurrentDeploymentSyncs = in.ConcurrentDeploymentSyncs + out.DeploymentControllerSyncPeriod = in.DeploymentControllerSyncPeriod + return nil +} + +// Convert_v1alpha1_DeploymentControllerConfiguration_To_componentconfig_DeploymentControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_DeploymentControllerConfiguration_To_componentconfig_DeploymentControllerConfiguration(in *DeploymentControllerConfiguration, out *componentconfig.DeploymentControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_DeploymentControllerConfiguration_To_componentconfig_DeploymentControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_DeploymentControllerConfiguration_To_v1alpha1_DeploymentControllerConfiguration(in *componentconfig.DeploymentControllerConfiguration, out *DeploymentControllerConfiguration, s conversion.Scope) error { + out.ConcurrentDeploymentSyncs = in.ConcurrentDeploymentSyncs + out.DeploymentControllerSyncPeriod = in.DeploymentControllerSyncPeriod + return nil +} + +// Convert_componentconfig_DeploymentControllerConfiguration_To_v1alpha1_DeploymentControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_DeploymentControllerConfiguration_To_v1alpha1_DeploymentControllerConfiguration(in *componentconfig.DeploymentControllerConfiguration, out *DeploymentControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_DeploymentControllerConfiguration_To_v1alpha1_DeploymentControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_DeprecatedControllerConfiguration_To_componentconfig_DeprecatedControllerConfiguration(in *DeprecatedControllerConfiguration, out *componentconfig.DeprecatedControllerConfiguration, s conversion.Scope) error { + out.DeletingPodsQps = in.DeletingPodsQps + out.DeletingPodsBurst = in.DeletingPodsBurst + out.RegisterRetryCount = in.RegisterRetryCount + return nil +} + +// Convert_v1alpha1_DeprecatedControllerConfiguration_To_componentconfig_DeprecatedControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_DeprecatedControllerConfiguration_To_componentconfig_DeprecatedControllerConfiguration(in *DeprecatedControllerConfiguration, out *componentconfig.DeprecatedControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_DeprecatedControllerConfiguration_To_componentconfig_DeprecatedControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_DeprecatedControllerConfiguration_To_v1alpha1_DeprecatedControllerConfiguration(in *componentconfig.DeprecatedControllerConfiguration, out *DeprecatedControllerConfiguration, s conversion.Scope) error { + out.DeletingPodsQps = in.DeletingPodsQps + out.DeletingPodsBurst = in.DeletingPodsBurst + out.RegisterRetryCount = in.RegisterRetryCount + return nil +} + +// Convert_componentconfig_DeprecatedControllerConfiguration_To_v1alpha1_DeprecatedControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_DeprecatedControllerConfiguration_To_v1alpha1_DeprecatedControllerConfiguration(in *componentconfig.DeprecatedControllerConfiguration, out *DeprecatedControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_DeprecatedControllerConfiguration_To_v1alpha1_DeprecatedControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_EndPointControllerConfiguration_To_componentconfig_EndPointControllerConfiguration(in *EndPointControllerConfiguration, out *componentconfig.EndPointControllerConfiguration, s conversion.Scope) error { + out.ConcurrentEndpointSyncs = in.ConcurrentEndpointSyncs + return nil +} + +// Convert_v1alpha1_EndPointControllerConfiguration_To_componentconfig_EndPointControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_EndPointControllerConfiguration_To_componentconfig_EndPointControllerConfiguration(in *EndPointControllerConfiguration, out *componentconfig.EndPointControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_EndPointControllerConfiguration_To_componentconfig_EndPointControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_EndPointControllerConfiguration_To_v1alpha1_EndPointControllerConfiguration(in *componentconfig.EndPointControllerConfiguration, out *EndPointControllerConfiguration, s conversion.Scope) error { + out.ConcurrentEndpointSyncs = in.ConcurrentEndpointSyncs + return nil +} + +// Convert_componentconfig_EndPointControllerConfiguration_To_v1alpha1_EndPointControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_EndPointControllerConfiguration_To_v1alpha1_EndPointControllerConfiguration(in *componentconfig.EndPointControllerConfiguration, out *EndPointControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_EndPointControllerConfiguration_To_v1alpha1_EndPointControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_GarbageCollectorControllerConfiguration_To_componentconfig_GarbageCollectorControllerConfiguration(in *GarbageCollectorControllerConfiguration, out *componentconfig.GarbageCollectorControllerConfiguration, s conversion.Scope) error { + if err := v1.Convert_Pointer_bool_To_bool(&in.EnableGarbageCollector, &out.EnableGarbageCollector, s); err != nil { + return err + } + out.ConcurrentGCSyncs = in.ConcurrentGCSyncs + out.GCIgnoredResources = *(*[]componentconfig.GroupResource)(unsafe.Pointer(&in.GCIgnoredResources)) + return nil +} + +// Convert_v1alpha1_GarbageCollectorControllerConfiguration_To_componentconfig_GarbageCollectorControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_GarbageCollectorControllerConfiguration_To_componentconfig_GarbageCollectorControllerConfiguration(in *GarbageCollectorControllerConfiguration, out *componentconfig.GarbageCollectorControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_GarbageCollectorControllerConfiguration_To_componentconfig_GarbageCollectorControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_GarbageCollectorControllerConfiguration_To_v1alpha1_GarbageCollectorControllerConfiguration(in *componentconfig.GarbageCollectorControllerConfiguration, out *GarbageCollectorControllerConfiguration, s conversion.Scope) error { + if err := v1.Convert_bool_To_Pointer_bool(&in.EnableGarbageCollector, &out.EnableGarbageCollector, s); err != nil { + return err + } + out.ConcurrentGCSyncs = in.ConcurrentGCSyncs + out.GCIgnoredResources = *(*[]GroupResource)(unsafe.Pointer(&in.GCIgnoredResources)) + return nil +} + +// Convert_componentconfig_GarbageCollectorControllerConfiguration_To_v1alpha1_GarbageCollectorControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_GarbageCollectorControllerConfiguration_To_v1alpha1_GarbageCollectorControllerConfiguration(in *componentconfig.GarbageCollectorControllerConfiguration, out *GarbageCollectorControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_GarbageCollectorControllerConfiguration_To_v1alpha1_GarbageCollectorControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_GenericComponentConfiguration_To_componentconfig_GenericComponentConfiguration(in *GenericComponentConfiguration, out *componentconfig.GenericComponentConfiguration, s conversion.Scope) error { + out.MinResyncPeriod = in.MinResyncPeriod + out.ContentType = in.ContentType + out.KubeAPIQPS = in.KubeAPIQPS + out.KubeAPIBurst = in.KubeAPIBurst + out.ControllerStartInterval = in.ControllerStartInterval + if err := Convert_v1alpha1_LeaderElectionConfiguration_To_componentconfig_LeaderElectionConfiguration(&in.LeaderElection, &out.LeaderElection, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_GenericComponentConfiguration_To_componentconfig_GenericComponentConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_GenericComponentConfiguration_To_componentconfig_GenericComponentConfiguration(in *GenericComponentConfiguration, out *componentconfig.GenericComponentConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_GenericComponentConfiguration_To_componentconfig_GenericComponentConfiguration(in, out, s) +} + +func autoConvert_componentconfig_GenericComponentConfiguration_To_v1alpha1_GenericComponentConfiguration(in *componentconfig.GenericComponentConfiguration, out *GenericComponentConfiguration, s conversion.Scope) error { + out.MinResyncPeriod = in.MinResyncPeriod + out.ContentType = in.ContentType + out.KubeAPIQPS = in.KubeAPIQPS + out.KubeAPIBurst = in.KubeAPIBurst + out.ControllerStartInterval = in.ControllerStartInterval + if err := Convert_componentconfig_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration(&in.LeaderElection, &out.LeaderElection, s); err != nil { + return err + } + return nil +} + +// Convert_componentconfig_GenericComponentConfiguration_To_v1alpha1_GenericComponentConfiguration is an autogenerated conversion function. +func Convert_componentconfig_GenericComponentConfiguration_To_v1alpha1_GenericComponentConfiguration(in *componentconfig.GenericComponentConfiguration, out *GenericComponentConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_GenericComponentConfiguration_To_v1alpha1_GenericComponentConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_GroupResource_To_componentconfig_GroupResource(in *GroupResource, out *componentconfig.GroupResource, s conversion.Scope) error { + out.Group = in.Group + out.Resource = in.Resource + return nil +} + +// Convert_v1alpha1_GroupResource_To_componentconfig_GroupResource is an autogenerated conversion function. +func Convert_v1alpha1_GroupResource_To_componentconfig_GroupResource(in *GroupResource, out *componentconfig.GroupResource, s conversion.Scope) error { + return autoConvert_v1alpha1_GroupResource_To_componentconfig_GroupResource(in, out, s) +} + +func autoConvert_componentconfig_GroupResource_To_v1alpha1_GroupResource(in *componentconfig.GroupResource, out *GroupResource, s conversion.Scope) error { + out.Group = in.Group + out.Resource = in.Resource + return nil +} + +// Convert_componentconfig_GroupResource_To_v1alpha1_GroupResource is an autogenerated conversion function. +func Convert_componentconfig_GroupResource_To_v1alpha1_GroupResource(in *componentconfig.GroupResource, out *GroupResource, s conversion.Scope) error { + return autoConvert_componentconfig_GroupResource_To_v1alpha1_GroupResource(in, out, s) +} + +func autoConvert_v1alpha1_HPAControllerConfiguration_To_componentconfig_HPAControllerConfiguration(in *HPAControllerConfiguration, out *componentconfig.HPAControllerConfiguration, s conversion.Scope) error { + out.HorizontalPodAutoscalerSyncPeriod = in.HorizontalPodAutoscalerSyncPeriod + out.HorizontalPodAutoscalerUpscaleForbiddenWindow = in.HorizontalPodAutoscalerUpscaleForbiddenWindow + out.HorizontalPodAutoscalerDownscaleForbiddenWindow = in.HorizontalPodAutoscalerDownscaleForbiddenWindow + out.HorizontalPodAutoscalerTolerance = in.HorizontalPodAutoscalerTolerance + if err := v1.Convert_Pointer_bool_To_bool(&in.HorizontalPodAutoscalerUseRESTClients, &out.HorizontalPodAutoscalerUseRESTClients, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_HPAControllerConfiguration_To_componentconfig_HPAControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_HPAControllerConfiguration_To_componentconfig_HPAControllerConfiguration(in *HPAControllerConfiguration, out *componentconfig.HPAControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_HPAControllerConfiguration_To_componentconfig_HPAControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_HPAControllerConfiguration_To_v1alpha1_HPAControllerConfiguration(in *componentconfig.HPAControllerConfiguration, out *HPAControllerConfiguration, s conversion.Scope) error { + out.HorizontalPodAutoscalerSyncPeriod = in.HorizontalPodAutoscalerSyncPeriod + out.HorizontalPodAutoscalerUpscaleForbiddenWindow = in.HorizontalPodAutoscalerUpscaleForbiddenWindow + out.HorizontalPodAutoscalerDownscaleForbiddenWindow = in.HorizontalPodAutoscalerDownscaleForbiddenWindow + out.HorizontalPodAutoscalerTolerance = in.HorizontalPodAutoscalerTolerance + if err := v1.Convert_bool_To_Pointer_bool(&in.HorizontalPodAutoscalerUseRESTClients, &out.HorizontalPodAutoscalerUseRESTClients, s); err != nil { + return err + } + return nil +} + +// Convert_componentconfig_HPAControllerConfiguration_To_v1alpha1_HPAControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_HPAControllerConfiguration_To_v1alpha1_HPAControllerConfiguration(in *componentconfig.HPAControllerConfiguration, out *HPAControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_HPAControllerConfiguration_To_v1alpha1_HPAControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_JobControllerConfiguration_To_componentconfig_JobControllerConfiguration(in *JobControllerConfiguration, out *componentconfig.JobControllerConfiguration, s conversion.Scope) error { + out.ConcurrentJobSyncs = in.ConcurrentJobSyncs + return nil +} + +// Convert_v1alpha1_JobControllerConfiguration_To_componentconfig_JobControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_JobControllerConfiguration_To_componentconfig_JobControllerConfiguration(in *JobControllerConfiguration, out *componentconfig.JobControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_JobControllerConfiguration_To_componentconfig_JobControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_JobControllerConfiguration_To_v1alpha1_JobControllerConfiguration(in *componentconfig.JobControllerConfiguration, out *JobControllerConfiguration, s conversion.Scope) error { + out.ConcurrentJobSyncs = in.ConcurrentJobSyncs + return nil +} + +// Convert_componentconfig_JobControllerConfiguration_To_v1alpha1_JobControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_JobControllerConfiguration_To_v1alpha1_JobControllerConfiguration(in *componentconfig.JobControllerConfiguration, out *JobControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_JobControllerConfiguration_To_v1alpha1_JobControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_KubeCloudSharedConfiguration_To_componentconfig_KubeCloudSharedConfiguration(in *KubeCloudSharedConfiguration, out *componentconfig.KubeCloudSharedConfiguration, s conversion.Scope) error { + out.Port = in.Port + out.Address = in.Address + out.UseServiceAccountCredentials = in.UseServiceAccountCredentials + out.AllowUntaggedCloud = in.AllowUntaggedCloud + out.RouteReconciliationPeriod = in.RouteReconciliationPeriod + out.NodeMonitorPeriod = in.NodeMonitorPeriod + out.ClusterName = in.ClusterName + out.ClusterCIDR = in.ClusterCIDR + out.AllocateNodeCIDRs = in.AllocateNodeCIDRs + out.CIDRAllocatorType = in.CIDRAllocatorType + if err := v1.Convert_Pointer_bool_To_bool(&in.ConfigureCloudRoutes, &out.ConfigureCloudRoutes, s); err != nil { + return err + } + out.NodeSyncPeriod = in.NodeSyncPeriod + return nil +} + +// Convert_v1alpha1_KubeCloudSharedConfiguration_To_componentconfig_KubeCloudSharedConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_KubeCloudSharedConfiguration_To_componentconfig_KubeCloudSharedConfiguration(in *KubeCloudSharedConfiguration, out *componentconfig.KubeCloudSharedConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_KubeCloudSharedConfiguration_To_componentconfig_KubeCloudSharedConfiguration(in, out, s) +} + +func autoConvert_componentconfig_KubeCloudSharedConfiguration_To_v1alpha1_KubeCloudSharedConfiguration(in *componentconfig.KubeCloudSharedConfiguration, out *KubeCloudSharedConfiguration, s conversion.Scope) error { + out.Port = in.Port + out.Address = in.Address + out.UseServiceAccountCredentials = in.UseServiceAccountCredentials + out.AllowUntaggedCloud = in.AllowUntaggedCloud + out.RouteReconciliationPeriod = in.RouteReconciliationPeriod + out.NodeMonitorPeriod = in.NodeMonitorPeriod + out.ClusterName = in.ClusterName + out.ClusterCIDR = in.ClusterCIDR + out.AllocateNodeCIDRs = in.AllocateNodeCIDRs + out.CIDRAllocatorType = in.CIDRAllocatorType + if err := v1.Convert_bool_To_Pointer_bool(&in.ConfigureCloudRoutes, &out.ConfigureCloudRoutes, s); err != nil { + return err + } + out.NodeSyncPeriod = in.NodeSyncPeriod + return nil +} + +// Convert_componentconfig_KubeCloudSharedConfiguration_To_v1alpha1_KubeCloudSharedConfiguration is an autogenerated conversion function. +func Convert_componentconfig_KubeCloudSharedConfiguration_To_v1alpha1_KubeCloudSharedConfiguration(in *componentconfig.KubeCloudSharedConfiguration, out *KubeCloudSharedConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_KubeCloudSharedConfiguration_To_v1alpha1_KubeCloudSharedConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_KubeControllerManagerConfiguration_To_componentconfig_KubeControllerManagerConfiguration(in *KubeControllerManagerConfiguration, out *componentconfig.KubeControllerManagerConfiguration, s conversion.Scope) error { + if err := Convert_v1alpha1_CloudProviderConfiguration_To_componentconfig_CloudProviderConfiguration(&in.CloudProvider, &out.CloudProvider, s); err != nil { + return err + } + if err := Convert_v1alpha1_DebuggingConfiguration_To_componentconfig_DebuggingConfiguration(&in.Debugging, &out.Debugging, s); err != nil { + return err + } + if err := Convert_v1alpha1_GenericComponentConfiguration_To_componentconfig_GenericComponentConfiguration(&in.GenericComponent, &out.GenericComponent, s); err != nil { + return err + } + if err := Convert_v1alpha1_KubeCloudSharedConfiguration_To_componentconfig_KubeCloudSharedConfiguration(&in.KubeCloudShared, &out.KubeCloudShared, s); err != nil { + return err + } + if err := Convert_v1alpha1_AttachDetachControllerConfiguration_To_componentconfig_AttachDetachControllerConfiguration(&in.AttachDetachController, &out.AttachDetachController, s); err != nil { + return err + } + if err := Convert_v1alpha1_CSRSigningControllerConfiguration_To_componentconfig_CSRSigningControllerConfiguration(&in.CSRSigningController, &out.CSRSigningController, s); err != nil { + return err + } + if err := Convert_v1alpha1_DaemonSetControllerConfiguration_To_componentconfig_DaemonSetControllerConfiguration(&in.DaemonSetController, &out.DaemonSetController, s); err != nil { + return err + } + if err := Convert_v1alpha1_DeploymentControllerConfiguration_To_componentconfig_DeploymentControllerConfiguration(&in.DeploymentController, &out.DeploymentController, s); err != nil { + return err + } + if err := Convert_v1alpha1_DeprecatedControllerConfiguration_To_componentconfig_DeprecatedControllerConfiguration(&in.DeprecatedController, &out.DeprecatedController, s); err != nil { + return err + } + if err := Convert_v1alpha1_EndPointControllerConfiguration_To_componentconfig_EndPointControllerConfiguration(&in.EndPointController, &out.EndPointController, s); err != nil { + return err + } + if err := Convert_v1alpha1_GarbageCollectorControllerConfiguration_To_componentconfig_GarbageCollectorControllerConfiguration(&in.GarbageCollectorController, &out.GarbageCollectorController, s); err != nil { + return err + } + if err := Convert_v1alpha1_HPAControllerConfiguration_To_componentconfig_HPAControllerConfiguration(&in.HPAController, &out.HPAController, s); err != nil { + return err + } + if err := Convert_v1alpha1_JobControllerConfiguration_To_componentconfig_JobControllerConfiguration(&in.JobController, &out.JobController, s); err != nil { + return err + } + if err := Convert_v1alpha1_NamespaceControllerConfiguration_To_componentconfig_NamespaceControllerConfiguration(&in.NamespaceController, &out.NamespaceController, s); err != nil { + return err + } + if err := Convert_v1alpha1_NodeIpamControllerConfiguration_To_componentconfig_NodeIpamControllerConfiguration(&in.NodeIpamController, &out.NodeIpamController, s); err != nil { + return err + } + if err := Convert_v1alpha1_NodeLifecycleControllerConfiguration_To_componentconfig_NodeLifecycleControllerConfiguration(&in.NodeLifecycleController, &out.NodeLifecycleController, s); err != nil { + return err + } + if err := Convert_v1alpha1_PersistentVolumeBinderControllerConfiguration_To_componentconfig_PersistentVolumeBinderControllerConfiguration(&in.PersistentVolumeBinderController, &out.PersistentVolumeBinderController, s); err != nil { + return err + } + if err := Convert_v1alpha1_PodGCControllerConfiguration_To_componentconfig_PodGCControllerConfiguration(&in.PodGCController, &out.PodGCController, s); err != nil { + return err + } + if err := Convert_v1alpha1_ReplicaSetControllerConfiguration_To_componentconfig_ReplicaSetControllerConfiguration(&in.ReplicaSetController, &out.ReplicaSetController, s); err != nil { + return err + } + if err := Convert_v1alpha1_ReplicationControllerConfiguration_To_componentconfig_ReplicationControllerConfiguration(&in.ReplicationController, &out.ReplicationController, s); err != nil { + return err + } + if err := Convert_v1alpha1_ResourceQuotaControllerConfiguration_To_componentconfig_ResourceQuotaControllerConfiguration(&in.ResourceQuotaController, &out.ResourceQuotaController, s); err != nil { + return err + } + if err := Convert_v1alpha1_SAControllerConfiguration_To_componentconfig_SAControllerConfiguration(&in.SAController, &out.SAController, s); err != nil { + return err + } + if err := Convert_v1alpha1_ServiceControllerConfiguration_To_componentconfig_ServiceControllerConfiguration(&in.ServiceController, &out.ServiceController, s); err != nil { + return err + } + out.Controllers = *(*[]string)(unsafe.Pointer(&in.Controllers)) + out.ExternalCloudVolumePlugin = in.ExternalCloudVolumePlugin + return nil +} + +// Convert_v1alpha1_KubeControllerManagerConfiguration_To_componentconfig_KubeControllerManagerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_KubeControllerManagerConfiguration_To_componentconfig_KubeControllerManagerConfiguration(in *KubeControllerManagerConfiguration, out *componentconfig.KubeControllerManagerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_KubeControllerManagerConfiguration_To_componentconfig_KubeControllerManagerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_KubeControllerManagerConfiguration_To_v1alpha1_KubeControllerManagerConfiguration(in *componentconfig.KubeControllerManagerConfiguration, out *KubeControllerManagerConfiguration, s conversion.Scope) error { + if err := Convert_componentconfig_CloudProviderConfiguration_To_v1alpha1_CloudProviderConfiguration(&in.CloudProvider, &out.CloudProvider, s); err != nil { + return err + } + if err := Convert_componentconfig_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(&in.Debugging, &out.Debugging, s); err != nil { + return err + } + if err := Convert_componentconfig_GenericComponentConfiguration_To_v1alpha1_GenericComponentConfiguration(&in.GenericComponent, &out.GenericComponent, s); err != nil { + return err + } + if err := Convert_componentconfig_KubeCloudSharedConfiguration_To_v1alpha1_KubeCloudSharedConfiguration(&in.KubeCloudShared, &out.KubeCloudShared, s); err != nil { + return err + } + if err := Convert_componentconfig_AttachDetachControllerConfiguration_To_v1alpha1_AttachDetachControllerConfiguration(&in.AttachDetachController, &out.AttachDetachController, s); err != nil { + return err + } + if err := Convert_componentconfig_CSRSigningControllerConfiguration_To_v1alpha1_CSRSigningControllerConfiguration(&in.CSRSigningController, &out.CSRSigningController, s); err != nil { + return err + } + if err := Convert_componentconfig_DaemonSetControllerConfiguration_To_v1alpha1_DaemonSetControllerConfiguration(&in.DaemonSetController, &out.DaemonSetController, s); err != nil { + return err + } + if err := Convert_componentconfig_DeploymentControllerConfiguration_To_v1alpha1_DeploymentControllerConfiguration(&in.DeploymentController, &out.DeploymentController, s); err != nil { + return err + } + if err := Convert_componentconfig_DeprecatedControllerConfiguration_To_v1alpha1_DeprecatedControllerConfiguration(&in.DeprecatedController, &out.DeprecatedController, s); err != nil { + return err + } + if err := Convert_componentconfig_EndPointControllerConfiguration_To_v1alpha1_EndPointControllerConfiguration(&in.EndPointController, &out.EndPointController, s); err != nil { + return err + } + if err := Convert_componentconfig_GarbageCollectorControllerConfiguration_To_v1alpha1_GarbageCollectorControllerConfiguration(&in.GarbageCollectorController, &out.GarbageCollectorController, s); err != nil { + return err + } + if err := Convert_componentconfig_HPAControllerConfiguration_To_v1alpha1_HPAControllerConfiguration(&in.HPAController, &out.HPAController, s); err != nil { + return err + } + if err := Convert_componentconfig_JobControllerConfiguration_To_v1alpha1_JobControllerConfiguration(&in.JobController, &out.JobController, s); err != nil { + return err + } + if err := Convert_componentconfig_NamespaceControllerConfiguration_To_v1alpha1_NamespaceControllerConfiguration(&in.NamespaceController, &out.NamespaceController, s); err != nil { + return err + } + if err := Convert_componentconfig_NodeIpamControllerConfiguration_To_v1alpha1_NodeIpamControllerConfiguration(&in.NodeIpamController, &out.NodeIpamController, s); err != nil { + return err + } + if err := Convert_componentconfig_NodeLifecycleControllerConfiguration_To_v1alpha1_NodeLifecycleControllerConfiguration(&in.NodeLifecycleController, &out.NodeLifecycleController, s); err != nil { + return err + } + if err := Convert_componentconfig_PersistentVolumeBinderControllerConfiguration_To_v1alpha1_PersistentVolumeBinderControllerConfiguration(&in.PersistentVolumeBinderController, &out.PersistentVolumeBinderController, s); err != nil { + return err + } + if err := Convert_componentconfig_PodGCControllerConfiguration_To_v1alpha1_PodGCControllerConfiguration(&in.PodGCController, &out.PodGCController, s); err != nil { + return err + } + if err := Convert_componentconfig_ReplicaSetControllerConfiguration_To_v1alpha1_ReplicaSetControllerConfiguration(&in.ReplicaSetController, &out.ReplicaSetController, s); err != nil { + return err + } + if err := Convert_componentconfig_ReplicationControllerConfiguration_To_v1alpha1_ReplicationControllerConfiguration(&in.ReplicationController, &out.ReplicationController, s); err != nil { + return err + } + if err := Convert_componentconfig_ResourceQuotaControllerConfiguration_To_v1alpha1_ResourceQuotaControllerConfiguration(&in.ResourceQuotaController, &out.ResourceQuotaController, s); err != nil { + return err + } + if err := Convert_componentconfig_SAControllerConfiguration_To_v1alpha1_SAControllerConfiguration(&in.SAController, &out.SAController, s); err != nil { + return err + } + if err := Convert_componentconfig_ServiceControllerConfiguration_To_v1alpha1_ServiceControllerConfiguration(&in.ServiceController, &out.ServiceController, s); err != nil { + return err + } + out.Controllers = *(*[]string)(unsafe.Pointer(&in.Controllers)) + out.ExternalCloudVolumePlugin = in.ExternalCloudVolumePlugin + return nil +} + +// Convert_componentconfig_KubeControllerManagerConfiguration_To_v1alpha1_KubeControllerManagerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_KubeControllerManagerConfiguration_To_v1alpha1_KubeControllerManagerConfiguration(in *componentconfig.KubeControllerManagerConfiguration, out *KubeControllerManagerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_KubeControllerManagerConfiguration_To_v1alpha1_KubeControllerManagerConfiguration(in, out, s) +} + func autoConvert_v1alpha1_KubeSchedulerConfiguration_To_componentconfig_KubeSchedulerConfiguration(in *KubeSchedulerConfiguration, out *componentconfig.KubeSchedulerConfiguration, s conversion.Scope) error { out.SchedulerName = in.SchedulerName if err := Convert_v1alpha1_SchedulerAlgorithmSource_To_componentconfig_SchedulerAlgorithmSource(&in.AlgorithmSource, &out.AlgorithmSource, s); err != nil { @@ -101,6 +725,7 @@ func autoConvert_v1alpha1_KubeSchedulerConfiguration_To_componentconfig_KubeSche out.EnableProfiling = in.EnableProfiling out.EnableContentionProfiling = in.EnableContentionProfiling out.FailureDomains = in.FailureDomains + out.DisablePreemption = in.DisablePreemption return nil } @@ -126,6 +751,7 @@ func autoConvert_componentconfig_KubeSchedulerConfiguration_To_v1alpha1_KubeSche out.EnableProfiling = in.EnableProfiling out.EnableContentionProfiling = in.EnableContentionProfiling out.FailureDomains = in.FailureDomains + out.DisablePreemption = in.DisablePreemption return nil } @@ -194,6 +820,252 @@ func Convert_componentconfig_LeaderElectionConfiguration_To_v1alpha1_LeaderElect return autoConvert_componentconfig_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration(in, out, s) } +func autoConvert_v1alpha1_NamespaceControllerConfiguration_To_componentconfig_NamespaceControllerConfiguration(in *NamespaceControllerConfiguration, out *componentconfig.NamespaceControllerConfiguration, s conversion.Scope) error { + out.NamespaceSyncPeriod = in.NamespaceSyncPeriod + out.ConcurrentNamespaceSyncs = in.ConcurrentNamespaceSyncs + return nil +} + +// Convert_v1alpha1_NamespaceControllerConfiguration_To_componentconfig_NamespaceControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_NamespaceControllerConfiguration_To_componentconfig_NamespaceControllerConfiguration(in *NamespaceControllerConfiguration, out *componentconfig.NamespaceControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_NamespaceControllerConfiguration_To_componentconfig_NamespaceControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_NamespaceControllerConfiguration_To_v1alpha1_NamespaceControllerConfiguration(in *componentconfig.NamespaceControllerConfiguration, out *NamespaceControllerConfiguration, s conversion.Scope) error { + out.NamespaceSyncPeriod = in.NamespaceSyncPeriod + out.ConcurrentNamespaceSyncs = in.ConcurrentNamespaceSyncs + return nil +} + +// Convert_componentconfig_NamespaceControllerConfiguration_To_v1alpha1_NamespaceControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_NamespaceControllerConfiguration_To_v1alpha1_NamespaceControllerConfiguration(in *componentconfig.NamespaceControllerConfiguration, out *NamespaceControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_NamespaceControllerConfiguration_To_v1alpha1_NamespaceControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_NodeIpamControllerConfiguration_To_componentconfig_NodeIpamControllerConfiguration(in *NodeIpamControllerConfiguration, out *componentconfig.NodeIpamControllerConfiguration, s conversion.Scope) error { + out.ServiceCIDR = in.ServiceCIDR + out.NodeCIDRMaskSize = in.NodeCIDRMaskSize + return nil +} + +// Convert_v1alpha1_NodeIpamControllerConfiguration_To_componentconfig_NodeIpamControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_NodeIpamControllerConfiguration_To_componentconfig_NodeIpamControllerConfiguration(in *NodeIpamControllerConfiguration, out *componentconfig.NodeIpamControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_NodeIpamControllerConfiguration_To_componentconfig_NodeIpamControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_NodeIpamControllerConfiguration_To_v1alpha1_NodeIpamControllerConfiguration(in *componentconfig.NodeIpamControllerConfiguration, out *NodeIpamControllerConfiguration, s conversion.Scope) error { + out.ServiceCIDR = in.ServiceCIDR + out.NodeCIDRMaskSize = in.NodeCIDRMaskSize + return nil +} + +// Convert_componentconfig_NodeIpamControllerConfiguration_To_v1alpha1_NodeIpamControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_NodeIpamControllerConfiguration_To_v1alpha1_NodeIpamControllerConfiguration(in *componentconfig.NodeIpamControllerConfiguration, out *NodeIpamControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_NodeIpamControllerConfiguration_To_v1alpha1_NodeIpamControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_NodeLifecycleControllerConfiguration_To_componentconfig_NodeLifecycleControllerConfiguration(in *NodeLifecycleControllerConfiguration, out *componentconfig.NodeLifecycleControllerConfiguration, s conversion.Scope) error { + if err := v1.Convert_Pointer_bool_To_bool(&in.EnableTaintManager, &out.EnableTaintManager, s); err != nil { + return err + } + out.NodeEvictionRate = in.NodeEvictionRate + out.SecondaryNodeEvictionRate = in.SecondaryNodeEvictionRate + out.NodeStartupGracePeriod = in.NodeStartupGracePeriod + out.NodeMonitorGracePeriod = in.NodeMonitorGracePeriod + out.PodEvictionTimeout = in.PodEvictionTimeout + out.LargeClusterSizeThreshold = in.LargeClusterSizeThreshold + out.UnhealthyZoneThreshold = in.UnhealthyZoneThreshold + return nil +} + +// Convert_v1alpha1_NodeLifecycleControllerConfiguration_To_componentconfig_NodeLifecycleControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_NodeLifecycleControllerConfiguration_To_componentconfig_NodeLifecycleControllerConfiguration(in *NodeLifecycleControllerConfiguration, out *componentconfig.NodeLifecycleControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_NodeLifecycleControllerConfiguration_To_componentconfig_NodeLifecycleControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_NodeLifecycleControllerConfiguration_To_v1alpha1_NodeLifecycleControllerConfiguration(in *componentconfig.NodeLifecycleControllerConfiguration, out *NodeLifecycleControllerConfiguration, s conversion.Scope) error { + if err := v1.Convert_bool_To_Pointer_bool(&in.EnableTaintManager, &out.EnableTaintManager, s); err != nil { + return err + } + out.NodeEvictionRate = in.NodeEvictionRate + out.SecondaryNodeEvictionRate = in.SecondaryNodeEvictionRate + out.NodeStartupGracePeriod = in.NodeStartupGracePeriod + out.NodeMonitorGracePeriod = in.NodeMonitorGracePeriod + out.PodEvictionTimeout = in.PodEvictionTimeout + out.LargeClusterSizeThreshold = in.LargeClusterSizeThreshold + out.UnhealthyZoneThreshold = in.UnhealthyZoneThreshold + return nil +} + +// Convert_componentconfig_NodeLifecycleControllerConfiguration_To_v1alpha1_NodeLifecycleControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_NodeLifecycleControllerConfiguration_To_v1alpha1_NodeLifecycleControllerConfiguration(in *componentconfig.NodeLifecycleControllerConfiguration, out *NodeLifecycleControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_NodeLifecycleControllerConfiguration_To_v1alpha1_NodeLifecycleControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_PersistentVolumeBinderControllerConfiguration_To_componentconfig_PersistentVolumeBinderControllerConfiguration(in *PersistentVolumeBinderControllerConfiguration, out *componentconfig.PersistentVolumeBinderControllerConfiguration, s conversion.Scope) error { + out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod + if err := Convert_v1alpha1_VolumeConfiguration_To_componentconfig_VolumeConfiguration(&in.VolumeConfiguration, &out.VolumeConfiguration, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_PersistentVolumeBinderControllerConfiguration_To_componentconfig_PersistentVolumeBinderControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_PersistentVolumeBinderControllerConfiguration_To_componentconfig_PersistentVolumeBinderControllerConfiguration(in *PersistentVolumeBinderControllerConfiguration, out *componentconfig.PersistentVolumeBinderControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_PersistentVolumeBinderControllerConfiguration_To_componentconfig_PersistentVolumeBinderControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_PersistentVolumeBinderControllerConfiguration_To_v1alpha1_PersistentVolumeBinderControllerConfiguration(in *componentconfig.PersistentVolumeBinderControllerConfiguration, out *PersistentVolumeBinderControllerConfiguration, s conversion.Scope) error { + out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod + if err := Convert_componentconfig_VolumeConfiguration_To_v1alpha1_VolumeConfiguration(&in.VolumeConfiguration, &out.VolumeConfiguration, s); err != nil { + return err + } + return nil +} + +// Convert_componentconfig_PersistentVolumeBinderControllerConfiguration_To_v1alpha1_PersistentVolumeBinderControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_PersistentVolumeBinderControllerConfiguration_To_v1alpha1_PersistentVolumeBinderControllerConfiguration(in *componentconfig.PersistentVolumeBinderControllerConfiguration, out *PersistentVolumeBinderControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_PersistentVolumeBinderControllerConfiguration_To_v1alpha1_PersistentVolumeBinderControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_PersistentVolumeRecyclerConfiguration_To_componentconfig_PersistentVolumeRecyclerConfiguration(in *PersistentVolumeRecyclerConfiguration, out *componentconfig.PersistentVolumeRecyclerConfiguration, s conversion.Scope) error { + out.MaximumRetry = in.MaximumRetry + out.MinimumTimeoutNFS = in.MinimumTimeoutNFS + out.PodTemplateFilePathNFS = in.PodTemplateFilePathNFS + out.IncrementTimeoutNFS = in.IncrementTimeoutNFS + out.PodTemplateFilePathHostPath = in.PodTemplateFilePathHostPath + out.MinimumTimeoutHostPath = in.MinimumTimeoutHostPath + out.IncrementTimeoutHostPath = in.IncrementTimeoutHostPath + return nil +} + +// Convert_v1alpha1_PersistentVolumeRecyclerConfiguration_To_componentconfig_PersistentVolumeRecyclerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_PersistentVolumeRecyclerConfiguration_To_componentconfig_PersistentVolumeRecyclerConfiguration(in *PersistentVolumeRecyclerConfiguration, out *componentconfig.PersistentVolumeRecyclerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_PersistentVolumeRecyclerConfiguration_To_componentconfig_PersistentVolumeRecyclerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_PersistentVolumeRecyclerConfiguration_To_v1alpha1_PersistentVolumeRecyclerConfiguration(in *componentconfig.PersistentVolumeRecyclerConfiguration, out *PersistentVolumeRecyclerConfiguration, s conversion.Scope) error { + out.MaximumRetry = in.MaximumRetry + out.MinimumTimeoutNFS = in.MinimumTimeoutNFS + out.PodTemplateFilePathNFS = in.PodTemplateFilePathNFS + out.IncrementTimeoutNFS = in.IncrementTimeoutNFS + out.PodTemplateFilePathHostPath = in.PodTemplateFilePathHostPath + out.MinimumTimeoutHostPath = in.MinimumTimeoutHostPath + out.IncrementTimeoutHostPath = in.IncrementTimeoutHostPath + return nil +} + +// Convert_componentconfig_PersistentVolumeRecyclerConfiguration_To_v1alpha1_PersistentVolumeRecyclerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_PersistentVolumeRecyclerConfiguration_To_v1alpha1_PersistentVolumeRecyclerConfiguration(in *componentconfig.PersistentVolumeRecyclerConfiguration, out *PersistentVolumeRecyclerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_PersistentVolumeRecyclerConfiguration_To_v1alpha1_PersistentVolumeRecyclerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_PodGCControllerConfiguration_To_componentconfig_PodGCControllerConfiguration(in *PodGCControllerConfiguration, out *componentconfig.PodGCControllerConfiguration, s conversion.Scope) error { + out.TerminatedPodGCThreshold = in.TerminatedPodGCThreshold + return nil +} + +// Convert_v1alpha1_PodGCControllerConfiguration_To_componentconfig_PodGCControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_PodGCControllerConfiguration_To_componentconfig_PodGCControllerConfiguration(in *PodGCControllerConfiguration, out *componentconfig.PodGCControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_PodGCControllerConfiguration_To_componentconfig_PodGCControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_PodGCControllerConfiguration_To_v1alpha1_PodGCControllerConfiguration(in *componentconfig.PodGCControllerConfiguration, out *PodGCControllerConfiguration, s conversion.Scope) error { + out.TerminatedPodGCThreshold = in.TerminatedPodGCThreshold + return nil +} + +// Convert_componentconfig_PodGCControllerConfiguration_To_v1alpha1_PodGCControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_PodGCControllerConfiguration_To_v1alpha1_PodGCControllerConfiguration(in *componentconfig.PodGCControllerConfiguration, out *PodGCControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_PodGCControllerConfiguration_To_v1alpha1_PodGCControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_ReplicaSetControllerConfiguration_To_componentconfig_ReplicaSetControllerConfiguration(in *ReplicaSetControllerConfiguration, out *componentconfig.ReplicaSetControllerConfiguration, s conversion.Scope) error { + out.ConcurrentRSSyncs = in.ConcurrentRSSyncs + return nil +} + +// Convert_v1alpha1_ReplicaSetControllerConfiguration_To_componentconfig_ReplicaSetControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_ReplicaSetControllerConfiguration_To_componentconfig_ReplicaSetControllerConfiguration(in *ReplicaSetControllerConfiguration, out *componentconfig.ReplicaSetControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_ReplicaSetControllerConfiguration_To_componentconfig_ReplicaSetControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_ReplicaSetControllerConfiguration_To_v1alpha1_ReplicaSetControllerConfiguration(in *componentconfig.ReplicaSetControllerConfiguration, out *ReplicaSetControllerConfiguration, s conversion.Scope) error { + out.ConcurrentRSSyncs = in.ConcurrentRSSyncs + return nil +} + +// Convert_componentconfig_ReplicaSetControllerConfiguration_To_v1alpha1_ReplicaSetControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_ReplicaSetControllerConfiguration_To_v1alpha1_ReplicaSetControllerConfiguration(in *componentconfig.ReplicaSetControllerConfiguration, out *ReplicaSetControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_ReplicaSetControllerConfiguration_To_v1alpha1_ReplicaSetControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_ReplicationControllerConfiguration_To_componentconfig_ReplicationControllerConfiguration(in *ReplicationControllerConfiguration, out *componentconfig.ReplicationControllerConfiguration, s conversion.Scope) error { + out.ConcurrentRCSyncs = in.ConcurrentRCSyncs + return nil +} + +// Convert_v1alpha1_ReplicationControllerConfiguration_To_componentconfig_ReplicationControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_ReplicationControllerConfiguration_To_componentconfig_ReplicationControllerConfiguration(in *ReplicationControllerConfiguration, out *componentconfig.ReplicationControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_ReplicationControllerConfiguration_To_componentconfig_ReplicationControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_ReplicationControllerConfiguration_To_v1alpha1_ReplicationControllerConfiguration(in *componentconfig.ReplicationControllerConfiguration, out *ReplicationControllerConfiguration, s conversion.Scope) error { + out.ConcurrentRCSyncs = in.ConcurrentRCSyncs + return nil +} + +// Convert_componentconfig_ReplicationControllerConfiguration_To_v1alpha1_ReplicationControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_ReplicationControllerConfiguration_To_v1alpha1_ReplicationControllerConfiguration(in *componentconfig.ReplicationControllerConfiguration, out *ReplicationControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_ReplicationControllerConfiguration_To_v1alpha1_ReplicationControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_ResourceQuotaControllerConfiguration_To_componentconfig_ResourceQuotaControllerConfiguration(in *ResourceQuotaControllerConfiguration, out *componentconfig.ResourceQuotaControllerConfiguration, s conversion.Scope) error { + out.ResourceQuotaSyncPeriod = in.ResourceQuotaSyncPeriod + out.ConcurrentResourceQuotaSyncs = in.ConcurrentResourceQuotaSyncs + return nil +} + +// Convert_v1alpha1_ResourceQuotaControllerConfiguration_To_componentconfig_ResourceQuotaControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_ResourceQuotaControllerConfiguration_To_componentconfig_ResourceQuotaControllerConfiguration(in *ResourceQuotaControllerConfiguration, out *componentconfig.ResourceQuotaControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceQuotaControllerConfiguration_To_componentconfig_ResourceQuotaControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_ResourceQuotaControllerConfiguration_To_v1alpha1_ResourceQuotaControllerConfiguration(in *componentconfig.ResourceQuotaControllerConfiguration, out *ResourceQuotaControllerConfiguration, s conversion.Scope) error { + out.ResourceQuotaSyncPeriod = in.ResourceQuotaSyncPeriod + out.ConcurrentResourceQuotaSyncs = in.ConcurrentResourceQuotaSyncs + return nil +} + +// Convert_componentconfig_ResourceQuotaControllerConfiguration_To_v1alpha1_ResourceQuotaControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_ResourceQuotaControllerConfiguration_To_v1alpha1_ResourceQuotaControllerConfiguration(in *componentconfig.ResourceQuotaControllerConfiguration, out *ResourceQuotaControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_ResourceQuotaControllerConfiguration_To_v1alpha1_ResourceQuotaControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_SAControllerConfiguration_To_componentconfig_SAControllerConfiguration(in *SAControllerConfiguration, out *componentconfig.SAControllerConfiguration, s conversion.Scope) error { + out.ServiceAccountKeyFile = in.ServiceAccountKeyFile + out.ConcurrentSATokenSyncs = in.ConcurrentSATokenSyncs + out.RootCAFile = in.RootCAFile + return nil +} + +// Convert_v1alpha1_SAControllerConfiguration_To_componentconfig_SAControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_SAControllerConfiguration_To_componentconfig_SAControllerConfiguration(in *SAControllerConfiguration, out *componentconfig.SAControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_SAControllerConfiguration_To_componentconfig_SAControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_SAControllerConfiguration_To_v1alpha1_SAControllerConfiguration(in *componentconfig.SAControllerConfiguration, out *SAControllerConfiguration, s conversion.Scope) error { + out.ServiceAccountKeyFile = in.ServiceAccountKeyFile + out.ConcurrentSATokenSyncs = in.ConcurrentSATokenSyncs + out.RootCAFile = in.RootCAFile + return nil +} + +// Convert_componentconfig_SAControllerConfiguration_To_v1alpha1_SAControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_SAControllerConfiguration_To_v1alpha1_SAControllerConfiguration(in *componentconfig.SAControllerConfiguration, out *SAControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_SAControllerConfiguration_To_v1alpha1_SAControllerConfiguration(in, out, s) +} + func autoConvert_v1alpha1_SchedulerAlgorithmSource_To_componentconfig_SchedulerAlgorithmSource(in *SchedulerAlgorithmSource, out *componentconfig.SchedulerAlgorithmSource, s conversion.Scope) error { out.Policy = (*componentconfig.SchedulerPolicySource)(unsafe.Pointer(in.Policy)) out.Provider = (*string)(unsafe.Pointer(in.Provider)) @@ -279,3 +1151,61 @@ func autoConvert_componentconfig_SchedulerPolicySource_To_v1alpha1_SchedulerPoli func Convert_componentconfig_SchedulerPolicySource_To_v1alpha1_SchedulerPolicySource(in *componentconfig.SchedulerPolicySource, out *SchedulerPolicySource, s conversion.Scope) error { return autoConvert_componentconfig_SchedulerPolicySource_To_v1alpha1_SchedulerPolicySource(in, out, s) } + +func autoConvert_v1alpha1_ServiceControllerConfiguration_To_componentconfig_ServiceControllerConfiguration(in *ServiceControllerConfiguration, out *componentconfig.ServiceControllerConfiguration, s conversion.Scope) error { + out.ConcurrentServiceSyncs = in.ConcurrentServiceSyncs + return nil +} + +// Convert_v1alpha1_ServiceControllerConfiguration_To_componentconfig_ServiceControllerConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_ServiceControllerConfiguration_To_componentconfig_ServiceControllerConfiguration(in *ServiceControllerConfiguration, out *componentconfig.ServiceControllerConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_ServiceControllerConfiguration_To_componentconfig_ServiceControllerConfiguration(in, out, s) +} + +func autoConvert_componentconfig_ServiceControllerConfiguration_To_v1alpha1_ServiceControllerConfiguration(in *componentconfig.ServiceControllerConfiguration, out *ServiceControllerConfiguration, s conversion.Scope) error { + out.ConcurrentServiceSyncs = in.ConcurrentServiceSyncs + return nil +} + +// Convert_componentconfig_ServiceControllerConfiguration_To_v1alpha1_ServiceControllerConfiguration is an autogenerated conversion function. +func Convert_componentconfig_ServiceControllerConfiguration_To_v1alpha1_ServiceControllerConfiguration(in *componentconfig.ServiceControllerConfiguration, out *ServiceControllerConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_ServiceControllerConfiguration_To_v1alpha1_ServiceControllerConfiguration(in, out, s) +} + +func autoConvert_v1alpha1_VolumeConfiguration_To_componentconfig_VolumeConfiguration(in *VolumeConfiguration, out *componentconfig.VolumeConfiguration, s conversion.Scope) error { + if err := v1.Convert_Pointer_bool_To_bool(&in.EnableHostPathProvisioning, &out.EnableHostPathProvisioning, s); err != nil { + return err + } + if err := v1.Convert_Pointer_bool_To_bool(&in.EnableDynamicProvisioning, &out.EnableDynamicProvisioning, s); err != nil { + return err + } + if err := Convert_v1alpha1_PersistentVolumeRecyclerConfiguration_To_componentconfig_PersistentVolumeRecyclerConfiguration(&in.PersistentVolumeRecyclerConfiguration, &out.PersistentVolumeRecyclerConfiguration, s); err != nil { + return err + } + out.FlexVolumePluginDir = in.FlexVolumePluginDir + return nil +} + +// Convert_v1alpha1_VolumeConfiguration_To_componentconfig_VolumeConfiguration is an autogenerated conversion function. +func Convert_v1alpha1_VolumeConfiguration_To_componentconfig_VolumeConfiguration(in *VolumeConfiguration, out *componentconfig.VolumeConfiguration, s conversion.Scope) error { + return autoConvert_v1alpha1_VolumeConfiguration_To_componentconfig_VolumeConfiguration(in, out, s) +} + +func autoConvert_componentconfig_VolumeConfiguration_To_v1alpha1_VolumeConfiguration(in *componentconfig.VolumeConfiguration, out *VolumeConfiguration, s conversion.Scope) error { + if err := v1.Convert_bool_To_Pointer_bool(&in.EnableHostPathProvisioning, &out.EnableHostPathProvisioning, s); err != nil { + return err + } + if err := v1.Convert_bool_To_Pointer_bool(&in.EnableDynamicProvisioning, &out.EnableDynamicProvisioning, s); err != nil { + return err + } + if err := Convert_componentconfig_PersistentVolumeRecyclerConfiguration_To_v1alpha1_PersistentVolumeRecyclerConfiguration(&in.PersistentVolumeRecyclerConfiguration, &out.PersistentVolumeRecyclerConfiguration, s); err != nil { + return err + } + out.FlexVolumePluginDir = in.FlexVolumePluginDir + return nil +} + +// Convert_componentconfig_VolumeConfiguration_To_v1alpha1_VolumeConfiguration is an autogenerated conversion function. +func Convert_componentconfig_VolumeConfiguration_To_v1alpha1_VolumeConfiguration(in *componentconfig.VolumeConfiguration, out *VolumeConfiguration, s conversion.Scope) error { + return autoConvert_componentconfig_VolumeConfiguration_To_v1alpha1_VolumeConfiguration(in, out, s) +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.deepcopy.go index 512979985..45cf5d9af 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,40 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AttachDetachControllerConfiguration) DeepCopyInto(out *AttachDetachControllerConfiguration) { + *out = *in + out.ReconcilerSyncLoopPeriod = in.ReconcilerSyncLoopPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AttachDetachControllerConfiguration. +func (in *AttachDetachControllerConfiguration) DeepCopy() *AttachDetachControllerConfiguration { + if in == nil { + return nil + } + out := new(AttachDetachControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CSRSigningControllerConfiguration) DeepCopyInto(out *CSRSigningControllerConfiguration) { + *out = *in + out.ClusterSigningDuration = in.ClusterSigningDuration + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSRSigningControllerConfiguration. +func (in *CSRSigningControllerConfiguration) DeepCopy() *CSRSigningControllerConfiguration { + if in == nil { + return nil + } + out := new(CSRSigningControllerConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientConnectionConfiguration) DeepCopyInto(out *ClientConnectionConfiguration) { *out = *in @@ -40,6 +74,324 @@ func (in *ClientConnectionConfiguration) DeepCopy() *ClientConnectionConfigurati return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CloudControllerManagerConfiguration) DeepCopyInto(out *CloudControllerManagerConfiguration) { + *out = *in + out.TypeMeta = in.TypeMeta + out.CloudProvider = in.CloudProvider + out.Debugging = in.Debugging + in.GenericComponent.DeepCopyInto(&out.GenericComponent) + in.KubeCloudShared.DeepCopyInto(&out.KubeCloudShared) + out.ServiceController = in.ServiceController + out.NodeStatusUpdateFrequency = in.NodeStatusUpdateFrequency + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudControllerManagerConfiguration. +func (in *CloudControllerManagerConfiguration) DeepCopy() *CloudControllerManagerConfiguration { + if in == nil { + return nil + } + out := new(CloudControllerManagerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CloudControllerManagerConfiguration) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CloudProviderConfiguration) DeepCopyInto(out *CloudProviderConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudProviderConfiguration. +func (in *CloudProviderConfiguration) DeepCopy() *CloudProviderConfiguration { + if in == nil { + return nil + } + out := new(CloudProviderConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DaemonSetControllerConfiguration) DeepCopyInto(out *DaemonSetControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DaemonSetControllerConfiguration. +func (in *DaemonSetControllerConfiguration) DeepCopy() *DaemonSetControllerConfiguration { + if in == nil { + return nil + } + out := new(DaemonSetControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DebuggingConfiguration) DeepCopyInto(out *DebuggingConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DebuggingConfiguration. +func (in *DebuggingConfiguration) DeepCopy() *DebuggingConfiguration { + if in == nil { + return nil + } + out := new(DebuggingConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentControllerConfiguration) DeepCopyInto(out *DeploymentControllerConfiguration) { + *out = *in + out.DeploymentControllerSyncPeriod = in.DeploymentControllerSyncPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentControllerConfiguration. +func (in *DeploymentControllerConfiguration) DeepCopy() *DeploymentControllerConfiguration { + if in == nil { + return nil + } + out := new(DeploymentControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeprecatedControllerConfiguration) DeepCopyInto(out *DeprecatedControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeprecatedControllerConfiguration. +func (in *DeprecatedControllerConfiguration) DeepCopy() *DeprecatedControllerConfiguration { + if in == nil { + return nil + } + out := new(DeprecatedControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EndPointControllerConfiguration) DeepCopyInto(out *EndPointControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndPointControllerConfiguration. +func (in *EndPointControllerConfiguration) DeepCopy() *EndPointControllerConfiguration { + if in == nil { + return nil + } + out := new(EndPointControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarbageCollectorControllerConfiguration) DeepCopyInto(out *GarbageCollectorControllerConfiguration) { + *out = *in + if in.EnableGarbageCollector != nil { + in, out := &in.EnableGarbageCollector, &out.EnableGarbageCollector + if *in == nil { + *out = nil + } else { + *out = new(bool) + **out = **in + } + } + if in.GCIgnoredResources != nil { + in, out := &in.GCIgnoredResources, &out.GCIgnoredResources + *out = make([]GroupResource, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarbageCollectorControllerConfiguration. +func (in *GarbageCollectorControllerConfiguration) DeepCopy() *GarbageCollectorControllerConfiguration { + if in == nil { + return nil + } + out := new(GarbageCollectorControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GenericComponentConfiguration) DeepCopyInto(out *GenericComponentConfiguration) { + *out = *in + out.MinResyncPeriod = in.MinResyncPeriod + out.ControllerStartInterval = in.ControllerStartInterval + in.LeaderElection.DeepCopyInto(&out.LeaderElection) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenericComponentConfiguration. +func (in *GenericComponentConfiguration) DeepCopy() *GenericComponentConfiguration { + if in == nil { + return nil + } + out := new(GenericComponentConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GroupResource) DeepCopyInto(out *GroupResource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupResource. +func (in *GroupResource) DeepCopy() *GroupResource { + if in == nil { + return nil + } + out := new(GroupResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HPAControllerConfiguration) DeepCopyInto(out *HPAControllerConfiguration) { + *out = *in + out.HorizontalPodAutoscalerSyncPeriod = in.HorizontalPodAutoscalerSyncPeriod + out.HorizontalPodAutoscalerUpscaleForbiddenWindow = in.HorizontalPodAutoscalerUpscaleForbiddenWindow + out.HorizontalPodAutoscalerDownscaleForbiddenWindow = in.HorizontalPodAutoscalerDownscaleForbiddenWindow + if in.HorizontalPodAutoscalerUseRESTClients != nil { + in, out := &in.HorizontalPodAutoscalerUseRESTClients, &out.HorizontalPodAutoscalerUseRESTClients + if *in == nil { + *out = nil + } else { + *out = new(bool) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HPAControllerConfiguration. +func (in *HPAControllerConfiguration) DeepCopy() *HPAControllerConfiguration { + if in == nil { + return nil + } + out := new(HPAControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JobControllerConfiguration) DeepCopyInto(out *JobControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JobControllerConfiguration. +func (in *JobControllerConfiguration) DeepCopy() *JobControllerConfiguration { + if in == nil { + return nil + } + out := new(JobControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeCloudSharedConfiguration) DeepCopyInto(out *KubeCloudSharedConfiguration) { + *out = *in + out.RouteReconciliationPeriod = in.RouteReconciliationPeriod + out.NodeMonitorPeriod = in.NodeMonitorPeriod + if in.ConfigureCloudRoutes != nil { + in, out := &in.ConfigureCloudRoutes, &out.ConfigureCloudRoutes + if *in == nil { + *out = nil + } else { + *out = new(bool) + **out = **in + } + } + out.NodeSyncPeriod = in.NodeSyncPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeCloudSharedConfiguration. +func (in *KubeCloudSharedConfiguration) DeepCopy() *KubeCloudSharedConfiguration { + if in == nil { + return nil + } + out := new(KubeCloudSharedConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeControllerManagerConfiguration) DeepCopyInto(out *KubeControllerManagerConfiguration) { + *out = *in + out.TypeMeta = in.TypeMeta + out.CloudProvider = in.CloudProvider + out.Debugging = in.Debugging + in.GenericComponent.DeepCopyInto(&out.GenericComponent) + in.KubeCloudShared.DeepCopyInto(&out.KubeCloudShared) + out.AttachDetachController = in.AttachDetachController + out.CSRSigningController = in.CSRSigningController + out.DaemonSetController = in.DaemonSetController + out.DeploymentController = in.DeploymentController + out.DeprecatedController = in.DeprecatedController + out.EndPointController = in.EndPointController + in.GarbageCollectorController.DeepCopyInto(&out.GarbageCollectorController) + in.HPAController.DeepCopyInto(&out.HPAController) + out.JobController = in.JobController + out.NamespaceController = in.NamespaceController + out.NodeIpamController = in.NodeIpamController + in.NodeLifecycleController.DeepCopyInto(&out.NodeLifecycleController) + in.PersistentVolumeBinderController.DeepCopyInto(&out.PersistentVolumeBinderController) + out.PodGCController = in.PodGCController + out.ReplicaSetController = in.ReplicaSetController + out.ReplicationController = in.ReplicationController + out.ResourceQuotaController = in.ResourceQuotaController + out.SAController = in.SAController + out.ServiceController = in.ServiceController + if in.Controllers != nil { + in, out := &in.Controllers, &out.Controllers + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeControllerManagerConfiguration. +func (in *KubeControllerManagerConfiguration) DeepCopy() *KubeControllerManagerConfiguration { + if in == nil { + return nil + } + out := new(KubeControllerManagerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeControllerManagerConfiguration) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KubeSchedulerConfiguration) DeepCopyInto(out *KubeSchedulerConfiguration) { *out = *in @@ -113,6 +465,182 @@ func (in *LeaderElectionConfiguration) DeepCopy() *LeaderElectionConfiguration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespaceControllerConfiguration) DeepCopyInto(out *NamespaceControllerConfiguration) { + *out = *in + out.NamespaceSyncPeriod = in.NamespaceSyncPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceControllerConfiguration. +func (in *NamespaceControllerConfiguration) DeepCopy() *NamespaceControllerConfiguration { + if in == nil { + return nil + } + out := new(NamespaceControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeIpamControllerConfiguration) DeepCopyInto(out *NodeIpamControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeIpamControllerConfiguration. +func (in *NodeIpamControllerConfiguration) DeepCopy() *NodeIpamControllerConfiguration { + if in == nil { + return nil + } + out := new(NodeIpamControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeLifecycleControllerConfiguration) DeepCopyInto(out *NodeLifecycleControllerConfiguration) { + *out = *in + if in.EnableTaintManager != nil { + in, out := &in.EnableTaintManager, &out.EnableTaintManager + if *in == nil { + *out = nil + } else { + *out = new(bool) + **out = **in + } + } + out.NodeStartupGracePeriod = in.NodeStartupGracePeriod + out.NodeMonitorGracePeriod = in.NodeMonitorGracePeriod + out.PodEvictionTimeout = in.PodEvictionTimeout + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeLifecycleControllerConfiguration. +func (in *NodeLifecycleControllerConfiguration) DeepCopy() *NodeLifecycleControllerConfiguration { + if in == nil { + return nil + } + out := new(NodeLifecycleControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PersistentVolumeBinderControllerConfiguration) DeepCopyInto(out *PersistentVolumeBinderControllerConfiguration) { + *out = *in + out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod + in.VolumeConfiguration.DeepCopyInto(&out.VolumeConfiguration) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistentVolumeBinderControllerConfiguration. +func (in *PersistentVolumeBinderControllerConfiguration) DeepCopy() *PersistentVolumeBinderControllerConfiguration { + if in == nil { + return nil + } + out := new(PersistentVolumeBinderControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PersistentVolumeRecyclerConfiguration) DeepCopyInto(out *PersistentVolumeRecyclerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistentVolumeRecyclerConfiguration. +func (in *PersistentVolumeRecyclerConfiguration) DeepCopy() *PersistentVolumeRecyclerConfiguration { + if in == nil { + return nil + } + out := new(PersistentVolumeRecyclerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodGCControllerConfiguration) DeepCopyInto(out *PodGCControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodGCControllerConfiguration. +func (in *PodGCControllerConfiguration) DeepCopy() *PodGCControllerConfiguration { + if in == nil { + return nil + } + out := new(PodGCControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReplicaSetControllerConfiguration) DeepCopyInto(out *ReplicaSetControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicaSetControllerConfiguration. +func (in *ReplicaSetControllerConfiguration) DeepCopy() *ReplicaSetControllerConfiguration { + if in == nil { + return nil + } + out := new(ReplicaSetControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReplicationControllerConfiguration) DeepCopyInto(out *ReplicationControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationControllerConfiguration. +func (in *ReplicationControllerConfiguration) DeepCopy() *ReplicationControllerConfiguration { + if in == nil { + return nil + } + out := new(ReplicationControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceQuotaControllerConfiguration) DeepCopyInto(out *ResourceQuotaControllerConfiguration) { + *out = *in + out.ResourceQuotaSyncPeriod = in.ResourceQuotaSyncPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceQuotaControllerConfiguration. +func (in *ResourceQuotaControllerConfiguration) DeepCopy() *ResourceQuotaControllerConfiguration { + if in == nil { + return nil + } + out := new(ResourceQuotaControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SAControllerConfiguration) DeepCopyInto(out *SAControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SAControllerConfiguration. +func (in *SAControllerConfiguration) DeepCopy() *SAControllerConfiguration { + if in == nil { + return nil + } + out := new(SAControllerConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SchedulerAlgorithmSource) DeepCopyInto(out *SchedulerAlgorithmSource) { *out = *in @@ -212,3 +740,54 @@ func (in *SchedulerPolicySource) DeepCopy() *SchedulerPolicySource { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceControllerConfiguration) DeepCopyInto(out *ServiceControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceControllerConfiguration. +func (in *ServiceControllerConfiguration) DeepCopy() *ServiceControllerConfiguration { + if in == nil { + return nil + } + out := new(ServiceControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeConfiguration) DeepCopyInto(out *VolumeConfiguration) { + *out = *in + if in.EnableHostPathProvisioning != nil { + in, out := &in.EnableHostPathProvisioning, &out.EnableHostPathProvisioning + if *in == nil { + *out = nil + } else { + *out = new(bool) + **out = **in + } + } + if in.EnableDynamicProvisioning != nil { + in, out := &in.EnableDynamicProvisioning, &out.EnableDynamicProvisioning + if *in == nil { + *out = nil + } else { + *out = new(bool) + **out = **in + } + } + out.PersistentVolumeRecyclerConfiguration = in.PersistentVolumeRecyclerConfiguration + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeConfiguration. +func (in *VolumeConfiguration) DeepCopy() *VolumeConfiguration { + if in == nil { + return nil + } + out := new(VolumeConfiguration) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.defaults.go index 74da948de..75fd9b762 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -28,10 +28,32 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { + scheme.AddTypeDefaultingFunc(&CloudControllerManagerConfiguration{}, func(obj interface{}) { + SetObjectDefaults_CloudControllerManagerConfiguration(obj.(*CloudControllerManagerConfiguration)) + }) + scheme.AddTypeDefaultingFunc(&KubeControllerManagerConfiguration{}, func(obj interface{}) { + SetObjectDefaults_KubeControllerManagerConfiguration(obj.(*KubeControllerManagerConfiguration)) + }) scheme.AddTypeDefaultingFunc(&KubeSchedulerConfiguration{}, func(obj interface{}) { SetObjectDefaults_KubeSchedulerConfiguration(obj.(*KubeSchedulerConfiguration)) }) return nil } +func SetObjectDefaults_CloudControllerManagerConfiguration(in *CloudControllerManagerConfiguration) { + SetDefaults_CloudControllerManagerConfiguration(in) + SetDefaults_GenericComponentConfiguration(&in.GenericComponent) + SetDefaults_LeaderElectionConfiguration(&in.GenericComponent.LeaderElection) + SetDefaults_KubeCloudSharedConfiguration(&in.KubeCloudShared) +} + +func SetObjectDefaults_KubeControllerManagerConfiguration(in *KubeControllerManagerConfiguration) { + SetDefaults_KubeControllerManagerConfiguration(in) + SetDefaults_GenericComponentConfiguration(&in.GenericComponent) + SetDefaults_LeaderElectionConfiguration(&in.GenericComponent.LeaderElection) + SetDefaults_KubeCloudSharedConfiguration(&in.KubeCloudShared) + SetDefaults_VolumeConfiguration(&in.PersistentVolumeBinderController.VolumeConfiguration) + SetDefaults_PersistentVolumeRecyclerConfiguration(&in.PersistentVolumeBinderController.VolumeConfiguration.PersistentVolumeRecyclerConfiguration) +} + func SetObjectDefaults_KubeSchedulerConfiguration(in *KubeSchedulerConfiguration) { SetDefaults_KubeSchedulerConfiguration(in) SetDefaults_LeaderElectionConfiguration(&in.LeaderElection.LeaderElectionConfiguration) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/zz_generated.deepcopy.go index 1efd2d4af..c8317d119 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/componentconfig/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,40 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AttachDetachControllerConfiguration) DeepCopyInto(out *AttachDetachControllerConfiguration) { + *out = *in + out.ReconcilerSyncLoopPeriod = in.ReconcilerSyncLoopPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AttachDetachControllerConfiguration. +func (in *AttachDetachControllerConfiguration) DeepCopy() *AttachDetachControllerConfiguration { + if in == nil { + return nil + } + out := new(AttachDetachControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CSRSigningControllerConfiguration) DeepCopyInto(out *CSRSigningControllerConfiguration) { + *out = *in + out.ClusterSigningDuration = in.ClusterSigningDuration + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSRSigningControllerConfiguration. +func (in *CSRSigningControllerConfiguration) DeepCopy() *CSRSigningControllerConfiguration { + if in == nil { + return nil + } + out := new(CSRSigningControllerConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientConnectionConfiguration) DeepCopyInto(out *ClientConnectionConfiguration) { *out = *in @@ -40,6 +74,174 @@ func (in *ClientConnectionConfiguration) DeepCopy() *ClientConnectionConfigurati return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CloudControllerManagerConfiguration) DeepCopyInto(out *CloudControllerManagerConfiguration) { + *out = *in + out.TypeMeta = in.TypeMeta + out.CloudProvider = in.CloudProvider + out.Debugging = in.Debugging + out.GenericComponent = in.GenericComponent + out.KubeCloudShared = in.KubeCloudShared + out.ServiceController = in.ServiceController + out.NodeStatusUpdateFrequency = in.NodeStatusUpdateFrequency + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudControllerManagerConfiguration. +func (in *CloudControllerManagerConfiguration) DeepCopy() *CloudControllerManagerConfiguration { + if in == nil { + return nil + } + out := new(CloudControllerManagerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CloudControllerManagerConfiguration) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CloudProviderConfiguration) DeepCopyInto(out *CloudProviderConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudProviderConfiguration. +func (in *CloudProviderConfiguration) DeepCopy() *CloudProviderConfiguration { + if in == nil { + return nil + } + out := new(CloudProviderConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DaemonSetControllerConfiguration) DeepCopyInto(out *DaemonSetControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DaemonSetControllerConfiguration. +func (in *DaemonSetControllerConfiguration) DeepCopy() *DaemonSetControllerConfiguration { + if in == nil { + return nil + } + out := new(DaemonSetControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DebuggingConfiguration) DeepCopyInto(out *DebuggingConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DebuggingConfiguration. +func (in *DebuggingConfiguration) DeepCopy() *DebuggingConfiguration { + if in == nil { + return nil + } + out := new(DebuggingConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentControllerConfiguration) DeepCopyInto(out *DeploymentControllerConfiguration) { + *out = *in + out.DeploymentControllerSyncPeriod = in.DeploymentControllerSyncPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentControllerConfiguration. +func (in *DeploymentControllerConfiguration) DeepCopy() *DeploymentControllerConfiguration { + if in == nil { + return nil + } + out := new(DeploymentControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeprecatedControllerConfiguration) DeepCopyInto(out *DeprecatedControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeprecatedControllerConfiguration. +func (in *DeprecatedControllerConfiguration) DeepCopy() *DeprecatedControllerConfiguration { + if in == nil { + return nil + } + out := new(DeprecatedControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EndPointControllerConfiguration) DeepCopyInto(out *EndPointControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndPointControllerConfiguration. +func (in *EndPointControllerConfiguration) DeepCopy() *EndPointControllerConfiguration { + if in == nil { + return nil + } + out := new(EndPointControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarbageCollectorControllerConfiguration) DeepCopyInto(out *GarbageCollectorControllerConfiguration) { + *out = *in + if in.GCIgnoredResources != nil { + in, out := &in.GCIgnoredResources, &out.GCIgnoredResources + *out = make([]GroupResource, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarbageCollectorControllerConfiguration. +func (in *GarbageCollectorControllerConfiguration) DeepCopy() *GarbageCollectorControllerConfiguration { + if in == nil { + return nil + } + out := new(GarbageCollectorControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GenericComponentConfiguration) DeepCopyInto(out *GenericComponentConfiguration) { + *out = *in + out.MinResyncPeriod = in.MinResyncPeriod + out.ControllerStartInterval = in.ControllerStartInterval + out.LeaderElection = in.LeaderElection + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenericComponentConfiguration. +func (in *GenericComponentConfiguration) DeepCopy() *GenericComponentConfiguration { + if in == nil { + return nil + } + out := new(GenericComponentConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GroupResource) DeepCopyInto(out *GroupResource) { *out = *in @@ -56,6 +258,25 @@ func (in *GroupResource) DeepCopy() *GroupResource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HPAControllerConfiguration) DeepCopyInto(out *HPAControllerConfiguration) { + *out = *in + out.HorizontalPodAutoscalerSyncPeriod = in.HorizontalPodAutoscalerSyncPeriod + out.HorizontalPodAutoscalerUpscaleForbiddenWindow = in.HorizontalPodAutoscalerUpscaleForbiddenWindow + out.HorizontalPodAutoscalerDownscaleForbiddenWindow = in.HorizontalPodAutoscalerDownscaleForbiddenWindow + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HPAControllerConfiguration. +func (in *HPAControllerConfiguration) DeepCopy() *HPAControllerConfiguration { + if in == nil { + return nil + } + out := new(HPAControllerConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IPPortVar) DeepCopyInto(out *IPPortVar) { *out = *in @@ -106,39 +327,73 @@ func (in *IPVar) DeepCopy() *IPVar { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JobControllerConfiguration) DeepCopyInto(out *JobControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JobControllerConfiguration. +func (in *JobControllerConfiguration) DeepCopy() *JobControllerConfiguration { + if in == nil { + return nil + } + out := new(JobControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeCloudSharedConfiguration) DeepCopyInto(out *KubeCloudSharedConfiguration) { + *out = *in + out.RouteReconciliationPeriod = in.RouteReconciliationPeriod + out.NodeMonitorPeriod = in.NodeMonitorPeriod + out.NodeSyncPeriod = in.NodeSyncPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeCloudSharedConfiguration. +func (in *KubeCloudSharedConfiguration) DeepCopy() *KubeCloudSharedConfiguration { + if in == nil { + return nil + } + out := new(KubeCloudSharedConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KubeControllerManagerConfiguration) DeepCopyInto(out *KubeControllerManagerConfiguration) { *out = *in out.TypeMeta = in.TypeMeta + out.CloudProvider = in.CloudProvider + out.Debugging = in.Debugging + out.GenericComponent = in.GenericComponent + out.KubeCloudShared = in.KubeCloudShared + out.AttachDetachController = in.AttachDetachController + out.CSRSigningController = in.CSRSigningController + out.DaemonSetController = in.DaemonSetController + out.DeploymentController = in.DeploymentController + out.DeprecatedController = in.DeprecatedController + out.EndPointController = in.EndPointController + in.GarbageCollectorController.DeepCopyInto(&out.GarbageCollectorController) + out.HPAController = in.HPAController + out.JobController = in.JobController + out.NamespaceController = in.NamespaceController + out.NodeIpamController = in.NodeIpamController + out.NodeLifecycleController = in.NodeLifecycleController + out.PersistentVolumeBinderController = in.PersistentVolumeBinderController + out.PodGCController = in.PodGCController + out.ReplicaSetController = in.ReplicaSetController + out.ReplicationController = in.ReplicationController + out.ResourceQuotaController = in.ResourceQuotaController + out.SAController = in.SAController + out.ServiceController = in.ServiceController if in.Controllers != nil { in, out := &in.Controllers, &out.Controllers *out = make([]string, len(*in)) copy(*out, *in) } - out.NodeSyncPeriod = in.NodeSyncPeriod - out.RouteReconciliationPeriod = in.RouteReconciliationPeriod - out.ResourceQuotaSyncPeriod = in.ResourceQuotaSyncPeriod - out.NamespaceSyncPeriod = in.NamespaceSyncPeriod - out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod - out.MinResyncPeriod = in.MinResyncPeriod - out.HorizontalPodAutoscalerSyncPeriod = in.HorizontalPodAutoscalerSyncPeriod - out.HorizontalPodAutoscalerUpscaleForbiddenWindow = in.HorizontalPodAutoscalerUpscaleForbiddenWindow - out.HorizontalPodAutoscalerDownscaleForbiddenWindow = in.HorizontalPodAutoscalerDownscaleForbiddenWindow - out.DeploymentControllerSyncPeriod = in.DeploymentControllerSyncPeriod - out.PodEvictionTimeout = in.PodEvictionTimeout - out.NodeMonitorGracePeriod = in.NodeMonitorGracePeriod - out.NodeStartupGracePeriod = in.NodeStartupGracePeriod - out.NodeMonitorPeriod = in.NodeMonitorPeriod - out.ClusterSigningDuration = in.ClusterSigningDuration - out.LeaderElection = in.LeaderElection - out.VolumeConfiguration = in.VolumeConfiguration - out.ControllerStartInterval = in.ControllerStartInterval - if in.GCIgnoredResources != nil { - in, out := &in.GCIgnoredResources, &out.GCIgnoredResources - *out = make([]GroupResource, len(*in)) - copy(*out, *in) - } - out.ReconcilerSyncLoopPeriod = in.ReconcilerSyncLoopPeriod return } @@ -224,6 +479,76 @@ func (in *LeaderElectionConfiguration) DeepCopy() *LeaderElectionConfiguration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespaceControllerConfiguration) DeepCopyInto(out *NamespaceControllerConfiguration) { + *out = *in + out.NamespaceSyncPeriod = in.NamespaceSyncPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceControllerConfiguration. +func (in *NamespaceControllerConfiguration) DeepCopy() *NamespaceControllerConfiguration { + if in == nil { + return nil + } + out := new(NamespaceControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeIpamControllerConfiguration) DeepCopyInto(out *NodeIpamControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeIpamControllerConfiguration. +func (in *NodeIpamControllerConfiguration) DeepCopy() *NodeIpamControllerConfiguration { + if in == nil { + return nil + } + out := new(NodeIpamControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeLifecycleControllerConfiguration) DeepCopyInto(out *NodeLifecycleControllerConfiguration) { + *out = *in + out.NodeStartupGracePeriod = in.NodeStartupGracePeriod + out.NodeMonitorGracePeriod = in.NodeMonitorGracePeriod + out.PodEvictionTimeout = in.PodEvictionTimeout + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeLifecycleControllerConfiguration. +func (in *NodeLifecycleControllerConfiguration) DeepCopy() *NodeLifecycleControllerConfiguration { + if in == nil { + return nil + } + out := new(NodeLifecycleControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PersistentVolumeBinderControllerConfiguration) DeepCopyInto(out *PersistentVolumeBinderControllerConfiguration) { + *out = *in + out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod + out.VolumeConfiguration = in.VolumeConfiguration + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistentVolumeBinderControllerConfiguration. +func (in *PersistentVolumeBinderControllerConfiguration) DeepCopy() *PersistentVolumeBinderControllerConfiguration { + if in == nil { + return nil + } + out := new(PersistentVolumeBinderControllerConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PersistentVolumeRecyclerConfiguration) DeepCopyInto(out *PersistentVolumeRecyclerConfiguration) { *out = *in @@ -240,6 +565,22 @@ func (in *PersistentVolumeRecyclerConfiguration) DeepCopy() *PersistentVolumeRec return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodGCControllerConfiguration) DeepCopyInto(out *PodGCControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodGCControllerConfiguration. +func (in *PodGCControllerConfiguration) DeepCopy() *PodGCControllerConfiguration { + if in == nil { + return nil + } + out := new(PodGCControllerConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PortRangeVar) DeepCopyInto(out *PortRangeVar) { *out = *in @@ -265,6 +606,71 @@ func (in *PortRangeVar) DeepCopy() *PortRangeVar { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReplicaSetControllerConfiguration) DeepCopyInto(out *ReplicaSetControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicaSetControllerConfiguration. +func (in *ReplicaSetControllerConfiguration) DeepCopy() *ReplicaSetControllerConfiguration { + if in == nil { + return nil + } + out := new(ReplicaSetControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReplicationControllerConfiguration) DeepCopyInto(out *ReplicationControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationControllerConfiguration. +func (in *ReplicationControllerConfiguration) DeepCopy() *ReplicationControllerConfiguration { + if in == nil { + return nil + } + out := new(ReplicationControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceQuotaControllerConfiguration) DeepCopyInto(out *ResourceQuotaControllerConfiguration) { + *out = *in + out.ResourceQuotaSyncPeriod = in.ResourceQuotaSyncPeriod + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceQuotaControllerConfiguration. +func (in *ResourceQuotaControllerConfiguration) DeepCopy() *ResourceQuotaControllerConfiguration { + if in == nil { + return nil + } + out := new(ResourceQuotaControllerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SAControllerConfiguration) DeepCopyInto(out *SAControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SAControllerConfiguration. +func (in *SAControllerConfiguration) DeepCopy() *SAControllerConfiguration { + if in == nil { + return nil + } + out := new(SAControllerConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SchedulerAlgorithmSource) DeepCopyInto(out *SchedulerAlgorithmSource) { *out = *in @@ -365,6 +771,22 @@ func (in *SchedulerPolicySource) DeepCopy() *SchedulerPolicySource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceControllerConfiguration) DeepCopyInto(out *ServiceControllerConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceControllerConfiguration. +func (in *ServiceControllerConfiguration) DeepCopy() *ServiceControllerConfiguration { + if in == nil { + return nil + } + out := new(ServiceControllerConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VolumeConfiguration) DeepCopyInto(out *VolumeConfiguration) { *out = *in diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/core/BUILD index 8d54d6726..026cd897a 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/BUILD @@ -21,8 +21,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/annotation_key_constants.go b/vendor/k8s.io/kubernetes/pkg/apis/core/annotation_key_constants.go index 131fdd990..a1e6daae4 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/annotation_key_constants.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/annotation_key_constants.go @@ -45,24 +45,17 @@ const ( // to one container of a pod. SeccompContainerAnnotationKeyPrefix string = "container.seccomp.security.alpha.kubernetes.io/" + // SeccompProfileRuntimeDefault represents the default seccomp profile used by container runtime. + SeccompProfileRuntimeDefault string = "runtime/default" + + // DeprecatedSeccompProfileDockerDefault represents the default seccomp profile used by docker. + // This is now deprecated and should be replaced by SeccompProfileRuntimeDefault. + DeprecatedSeccompProfileDockerDefault string = "docker/default" + // PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized) // in the Annotations of a Node. PreferAvoidPodsAnnotationKey string = "scheduler.alpha.kubernetes.io/preferAvoidPods" - // SysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Only a limited set of whitelisted and isolated sysctls is supported by - // the kubelet. Pods with other sysctls will fail to launch. - SysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/sysctls" - - // UnsafeSysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Unsafe sysctls must be explicitly enabled for a kubelet. They are properly - // namespaced to a pod or a container, but their isolation is usually unclear or weak. Their use - // is at-your-own-risk. Pods that attempt to set an unsafe sysctl that is not enabled for a kubelet - // will fail to launch. - UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls" - // ObjectTTLAnnotations represents a suggestion for kubelet for how long it can cache // an object (e.g. secret, config map) before fetching it again from apiserver. // This annotation can be attached to node. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/fuzzer/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/core/fuzzer/BUILD index dc0984547..fe33b1108 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/fuzzer/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/fuzzer/BUILD @@ -14,8 +14,6 @@ go_library( "//vendor/github.com/google/gofuzz: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/fields:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels: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:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/pkg/apis/core/fuzzer/fuzzer.go index 837694083..dede9ceb6 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/fuzzer/fuzzer.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/fuzzer/fuzzer.go @@ -25,8 +25,6 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" @@ -50,12 +48,6 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) j.FieldPath = c.RandString() }, - func(j *core.ListOptions, c fuzz.Continue) { - label, _ := labels.Parse("a=b") - j.LabelSelector = label - field, _ := fields.ParseSelector("a=b") - j.FieldSelector = field - }, func(j *core.PodExecOptions, c fuzz.Continue) { j.Stdout = true j.Stderr = true @@ -101,6 +93,19 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { c.Fuzz(&j.ObjectMeta) j.Target.Name = c.RandString() }, + func(j *core.ReplicationController, c fuzz.Continue) { + c.FuzzNoCustom(j) + + // match defaulting + if j.Spec.Template != nil { + if len(j.Labels) == 0 { + j.Labels = j.Spec.Template.Labels + } + if len(j.Spec.Selector) == 0 { + j.Spec.Selector = j.Spec.Template.Labels + } + } + }, func(j *core.ReplicationControllerSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // fuzz self without calling this function again //j.TemplateRef = nil // this is required for round trip @@ -477,10 +482,6 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { ss.SessionAffinityConfig = nil } }, - func(n *core.Node, c fuzz.Continue) { - c.FuzzNoCustom(n) - n.Spec.ExternalID = "external" - }, func(s *core.NodeStatus, c fuzz.Continue) { c.FuzzNoCustom(s) s.Allocatable = s.Capacity diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers.go b/vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers.go index 96899f184..7be34a857 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers.go @@ -103,6 +103,7 @@ var standardResourceQuotaScopes = sets.NewString( string(core.ResourceQuotaScopeNotTerminating), string(core.ResourceQuotaScopeBestEffort), string(core.ResourceQuotaScopeNotBestEffort), + string(core.ResourceQuotaScopePriorityClass), ) // IsStandardResourceQuotaScope returns true if the scope is a standard value @@ -126,7 +127,7 @@ var podComputeQuotaResources = sets.NewString( // IsResourceQuotaScopeValidForResource returns true if the resource applies to the specified scope func IsResourceQuotaScopeValidForResource(scope core.ResourceQuotaScope, resource string) bool { switch scope { - case core.ResourceQuotaScopeTerminating, core.ResourceQuotaScopeNotTerminating, core.ResourceQuotaScopeNotBestEffort: + case core.ResourceQuotaScopeTerminating, core.ResourceQuotaScopeNotTerminating, core.ResourceQuotaScopeNotBestEffort, core.ResourceQuotaScopePriorityClass: return podObjectCountQuotaResources.Has(resource) || podComputeQuotaResources.Has(resource) case core.ResourceQuotaScopeBestEffort: return podObjectCountQuotaResources.Has(resource) @@ -153,7 +154,7 @@ func IsStandardContainerResourceName(str string) bool { // to avoid confusion with the convention in quota // 3. it satisfies the rules in IsQualifiedName() after converted into quota resource name func IsExtendedResourceName(name core.ResourceName) bool { - if IsDefaultNamespaceResource(name) || strings.HasPrefix(string(name), core.DefaultResourceRequestsPrefix) { + if IsNativeResource(name) || strings.HasPrefix(string(name), core.DefaultResourceRequestsPrefix) { return false } // Ensure it satisfies the rules in IsQualifiedName() after converted into quota resource name @@ -164,22 +165,19 @@ func IsExtendedResourceName(name core.ResourceName) bool { return true } -// IsDefaultNamespaceResource returns true if the resource name is in the +// IsNativeResource returns true if the resource name is in the // *kubernetes.io/ namespace. Partially-qualified (unprefixed) names are // implicitly in the kubernetes.io/ namespace. -func IsDefaultNamespaceResource(name core.ResourceName) bool { +func IsNativeResource(name core.ResourceName) bool { return !strings.Contains(string(name), "/") || strings.Contains(string(name), core.ResourceDefaultNamespacePrefix) } -var overcommitBlacklist = sets.NewString(string(core.ResourceNvidiaGPU)) - // IsOvercommitAllowed returns true if the resource is in the default -// namespace and not blacklisted. +// namespace and is not hugepages. func IsOvercommitAllowed(name core.ResourceName) bool { - return IsDefaultNamespaceResource(name) && - !IsHugePageResourceName(name) && - !overcommitBlacklist.Has(string(name)) + return IsNativeResource(name) && + !IsHugePageResourceName(name) } var standardLimitRangeTypes = sets.NewString( @@ -326,16 +324,6 @@ func ingressEqual(lhs, rhs *core.LoadBalancerIngress) bool { return true } -// TODO: make method on LoadBalancerStatus? -func LoadBalancerStatusDeepCopy(lb *core.LoadBalancerStatus) *core.LoadBalancerStatus { - c := &core.LoadBalancerStatus{} - c.Ingress = make([]core.LoadBalancerIngress, len(lb.Ingress)) - for i := range lb.Ingress { - c.Ingress[i] = lb.Ingress[i] - } - return c -} - // GetAccessModesAsString returns a string representation of an array of access modes. // modes, when present, are always in the same order: RWO,ROX,RWX. func GetAccessModesAsString(modes []core.PersistentVolumeAccessMode) string { @@ -425,6 +413,38 @@ func NodeSelectorRequirementsAsSelector(nsm []core.NodeSelectorRequirement) (lab return selector, nil } +// NodeSelectorRequirementsAsFieldSelector converts the []NodeSelectorRequirement core type into a struct that implements +// fields.Selector. +func NodeSelectorRequirementsAsFieldSelector(nsm []core.NodeSelectorRequirement) (fields.Selector, error) { + if len(nsm) == 0 { + return fields.Nothing(), nil + } + + selectors := []fields.Selector{} + for _, expr := range nsm { + switch expr.Operator { + case core.NodeSelectorOpIn: + if len(expr.Values) != 1 { + return nil, fmt.Errorf("unexpected number of value (%d) for node field selector operator %q", + len(expr.Values), expr.Operator) + } + selectors = append(selectors, fields.OneTermEqualSelector(expr.Key, expr.Values[0])) + + case core.NodeSelectorOpNotIn: + if len(expr.Values) != 1 { + return nil, fmt.Errorf("unexpected number of value (%d) for node field selector operator %q", + len(expr.Values), expr.Operator) + } + selectors = append(selectors, fields.OneTermNotEqualSelector(expr.Key, expr.Values[0])) + + default: + return nil, fmt.Errorf("%q is not a valid node field selector operator", expr.Operator) + } + } + + return fields.AndSelectors(selectors...), nil +} + // GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations // and converts it to the []Toleration type in core. func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]core.Toleration, error) { @@ -479,54 +499,6 @@ func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]core.Taint, return taints, nil } -// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls -// and a slice of unsafe Sysctls. This is only a convenience wrapper around -// SysctlsFromPodAnnotation. -func SysctlsFromPodAnnotations(a map[string]string) ([]core.Sysctl, []core.Sysctl, error) { - safe, err := SysctlsFromPodAnnotation(a[core.SysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - unsafe, err := SysctlsFromPodAnnotation(a[core.UnsafeSysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - - return safe, unsafe, nil -} - -// SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls. -func SysctlsFromPodAnnotation(annotation string) ([]core.Sysctl, error) { - if len(annotation) == 0 { - return nil, nil - } - - kvs := strings.Split(annotation, ",") - sysctls := make([]core.Sysctl, len(kvs)) - for i, kv := range kvs { - cs := strings.Split(kv, "=") - if len(cs) != 2 || len(cs[0]) == 0 { - return nil, fmt.Errorf("sysctl %q not of the format sysctl_name=value", kv) - } - sysctls[i].Name = cs[0] - sysctls[i].Value = cs[1] - } - return sysctls, nil -} - -// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls. -func PodAnnotationsFromSysctls(sysctls []core.Sysctl) string { - if len(sysctls) == 0 { - return "" - } - - kvs := make([]string, len(sysctls)) - for i := range sysctls { - kvs[i] = fmt.Sprintf("%s=%s", sysctls[i].Name, sysctls[i].Value) - } - return strings.Join(kvs, ",") -} - // GetPersistentVolumeClass returns StorageClassName. func GetPersistentVolumeClass(volume *core.PersistentVolume) string { // Use beta annotation first @@ -566,32 +538,27 @@ func PersistentVolumeClaimHasClass(claim *core.PersistentVolumeClaim) bool { return false } -// GetStorageNodeAffinityFromAnnotation gets the json serialized data from PersistentVolume.Annotations -// and converts it to the NodeAffinity type in core. -// TODO: update when storage node affinity graduates to beta -func GetStorageNodeAffinityFromAnnotation(annotations map[string]string) (*core.NodeAffinity, error) { - if len(annotations) > 0 && annotations[core.AlphaStorageNodeAffinityAnnotation] != "" { - var affinity core.NodeAffinity - err := json.Unmarshal([]byte(annotations[core.AlphaStorageNodeAffinityAnnotation]), &affinity) - if err != nil { - return nil, err - } - return &affinity, nil - } - return nil, nil -} - -// Converts NodeAffinity type to Alpha annotation for use in PersistentVolumes -// TODO: update when storage node affinity graduates to beta -func StorageNodeAffinityToAlphaAnnotation(annotations map[string]string, affinity *core.NodeAffinity) error { - if affinity == nil { - return nil +// ScopedResourceSelectorRequirementsAsSelector converts the ScopedResourceSelectorRequirement api type into a struct that implements +// labels.Selector. +func ScopedResourceSelectorRequirementsAsSelector(ssr core.ScopedResourceSelectorRequirement) (labels.Selector, error) { + selector := labels.NewSelector() + var op selection.Operator + switch ssr.Operator { + case core.ScopeSelectorOpIn: + op = selection.In + case core.ScopeSelectorOpNotIn: + op = selection.NotIn + case core.ScopeSelectorOpExists: + op = selection.Exists + case core.ScopeSelectorOpDoesNotExist: + op = selection.DoesNotExist + default: + return nil, fmt.Errorf("%q is not a valid scope selector operator", ssr.Operator) } - - json, err := json.Marshal(*affinity) + r, err := labels.NewRequirement(string(ssr.ScopeName), op, ssr.Values) if err != nil { - return err + return nil, err } - annotations[core.AlphaStorageNodeAffinityAnnotation] = string(json) - return nil + selector = selector.Add(*r) + return selector, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers_test.go index 03e01f808..2d1700b15 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers_test.go @@ -239,140 +239,6 @@ func TestNodeSelectorRequirementsAsSelector(t *testing.T) { } } -func TestSysctlsFromPodAnnotation(t *testing.T) { - type Test struct { - annotation string - expectValue []core.Sysctl - expectErr bool - } - for i, test := range []Test{ - { - annotation: "", - expectValue: nil, - }, - { - annotation: "foo.bar", - expectErr: true, - }, - { - annotation: "=123", - expectErr: true, - }, - { - annotation: "foo.bar=", - expectValue: []core.Sysctl{{Name: "foo.bar", Value: ""}}, - }, - { - annotation: "foo.bar=42", - expectValue: []core.Sysctl{{Name: "foo.bar", Value: "42"}}, - }, - { - annotation: "foo.bar=42,", - expectErr: true, - }, - { - annotation: "foo.bar=42,abc.def=1", - expectValue: []core.Sysctl{{Name: "foo.bar", Value: "42"}, {Name: "abc.def", Value: "1"}}, - }, - } { - sysctls, err := SysctlsFromPodAnnotation(test.annotation) - if test.expectErr && err == nil { - t.Errorf("[%v]expected error but got none", i) - } else if !test.expectErr && err != nil { - t.Errorf("[%v]did not expect error but got: %v", i, err) - } else if !reflect.DeepEqual(sysctls, test.expectValue) { - t.Errorf("[%v]expect value %v but got %v", i, test.expectValue, sysctls) - } - } -} - -// TODO: remove when alpha support for topology constraints is removed -func TestGetNodeAffinityFromAnnotations(t *testing.T) { - testCases := []struct { - annotations map[string]string - expectErr bool - }{ - { - annotations: nil, - expectErr: false, - }, - { - annotations: map[string]string{}, - expectErr: false, - }, - { - annotations: map[string]string{ - core.AlphaStorageNodeAffinityAnnotation: `{ - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [ - { "matchExpressions": [ - { "key": "test-key1", - "operator": "In", - "values": ["test-value1", "test-value2"] - }, - { "key": "test-key2", - "operator": "In", - "values": ["test-value1", "test-value2"] - } - ]} - ]} - }`, - }, - expectErr: false, - }, - { - annotations: map[string]string{ - core.AlphaStorageNodeAffinityAnnotation: `[{ - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [ - { "matchExpressions": [ - { "key": "test-key1", - "operator": "In", - "values": ["test-value1", "test-value2"] - }, - { "key": "test-key2", - "operator": "In", - "values": ["test-value1", "test-value2"] - } - ]} - ]} - }]`, - }, - expectErr: true, - }, - { - annotations: map[string]string{ - core.AlphaStorageNodeAffinityAnnotation: `{ - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": - "matchExpressions": [ - { "key": "test-key1", - "operator": "In", - "values": ["test-value1", "test-value2"] - }, - { "key": "test-key2", - "operator": "In", - "values": ["test-value1", "test-value2"] - } - ]} - } - }`, - }, - expectErr: true, - }, - } - - for i, tc := range testCases { - _, err := GetStorageNodeAffinityFromAnnotation(tc.annotations) - if err == nil && tc.expectErr { - t.Errorf("[%v]expected error but got none.", i) - } - if err != nil && !tc.expectErr { - t.Errorf("[%v]did not expect error but got: %v", i, err) - } - } -} - func TestIsHugePageResourceName(t *testing.T) { testCases := []struct { name core.ResourceName @@ -474,10 +340,6 @@ func TestIsOvercommitAllowed(t *testing.T) { name: core.ResourceMemory, allowed: true, }, - { - name: core.ResourceNvidiaGPU, - allowed: false, - }, { name: HugePageResourceName(resource.MustParse("2Mi")), allowed: false, diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/core/install/BUILD index 49e816153..a5b6505f1 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/install/BUILD @@ -14,10 +14,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) @@ -28,7 +26,7 @@ go_test( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/core/install/install.go index cae514ec7..d2d82e27d 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/install/install.go @@ -19,49 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/v1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: core.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: core.AddToScheme, - RootScopedKinds: sets.NewString( - "Node", - "Namespace", - "PersistentVolume", - "ComponentStatus", - ), - IgnoredKinds: sets.NewString( - "ListOptions", - "DeleteOptions", - "Status", - "PodLogOptions", - "PodExecOptions", - "PodAttachOptions", - "PodPortForwardOptions", - "PodProxyOptions", - "NodeProxyOptions", - "ServiceProxyOptions", - ), - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(core.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/install/install_test.go b/vendor/k8s.io/kubernetes/pkg/apis/core/install/install_test.go index b580c56c4..adc0c84e9 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/install/install_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/install/install_test.go @@ -21,7 +21,7 @@ import ( "reflect" "testing" - "k8s.io/api/core/v1" + "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" @@ -30,18 +30,8 @@ import ( ) func TestResourceVersioner(t *testing.T) { - g, err := legacyscheme.Registry.Group(v1.GroupName) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - intf, err := g.DefaultInterfacesFor(v1.SchemeGroupVersion) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - accessor := intf.MetadataAccessor - pod := internal.Pod{ObjectMeta: metav1.ObjectMeta{ResourceVersion: "10"}} - version, err := accessor.ResourceVersion(&pod) + version, err := meta.NewAccessor().ResourceVersion(&pod) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -50,7 +40,7 @@ func TestResourceVersioner(t *testing.T) { } podList := internal.PodList{ListMeta: metav1.ListMeta{ResourceVersion: "10"}} - version, err = accessor.ResourceVersion(&podList) + version, err = meta.NewAccessor().ResourceVersion(&podList) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -63,7 +53,7 @@ func TestCodec(t *testing.T) { pod := internal.Pod{} // We do want to use package registered rather than testapi here, because we // want to test if the package install and package registered work as expected. - data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.GroupOrDie(internal.GroupName).GroupVersion), &pod) + data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(schema.GroupVersion{Group: "", Version: "v1"}), &pod) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -71,64 +61,11 @@ func TestCodec(t *testing.T) { if err := json.Unmarshal(data, &other); err != nil { t.Fatalf("unexpected error: %v", err) } - if other.APIVersion != legacyscheme.Registry.GroupOrDie(internal.GroupName).GroupVersion.Version || other.Kind != "Pod" { + if other.APIVersion != "v1" || other.Kind != "Pod" { t.Errorf("unexpected unmarshalled object %#v", other) } } -func TestInterfacesFor(t *testing.T) { - if _, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).InterfacesFor(internal.SchemeGroupVersion); err == nil { - t.Fatalf("unexpected non-error: %v", err) - } - for i, version := range legacyscheme.Registry.GroupOrDie(internal.GroupName).GroupVersions { - if vi, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).InterfacesFor(version); err != nil || vi == nil { - t.Fatalf("%d: unexpected result: %v", i, err) - } - } -} - -func TestRESTMapper(t *testing.T) { - gv := schema.GroupVersion{Group: "", Version: "v1"} - rcGVK := gv.WithKind("ReplicationController") - podTemplateGVK := gv.WithKind("PodTemplate") - - if gvk, err := legacyscheme.Registry.RESTMapper().KindFor(internal.SchemeGroupVersion.WithResource("replicationcontrollers")); err != nil || gvk != rcGVK { - t.Errorf("unexpected version mapping: %v %v", gvk, err) - } - - if m, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).RESTMapper.RESTMapping(podTemplateGVK.GroupKind(), ""); err != nil || m.GroupVersionKind != podTemplateGVK || m.Resource != "podtemplates" { - t.Errorf("unexpected version mapping: %#v %v", m, err) - } - - for _, version := range legacyscheme.Registry.GroupOrDie(internal.GroupName).GroupVersions { - mapping, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).RESTMapper.RESTMapping(rcGVK.GroupKind(), version.Version) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if mapping.Resource != "replicationControllers" && mapping.Resource != "replicationcontrollers" { - t.Errorf("incorrect resource name: %#v", mapping) - } - if mapping.GroupVersionKind.GroupVersion() != version { - t.Errorf("incorrect version: %v", mapping) - } - - interfaces, _ := legacyscheme.Registry.GroupOrDie(internal.GroupName).InterfacesFor(version) - if mapping.ObjectConvertor != interfaces.ObjectConvertor { - t.Errorf("unexpected: %#v, expected: %#v", mapping, interfaces) - } - - rc := &internal.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} - name, err := mapping.MetadataAccessor.Name(rc) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if name != "foo" { - t.Errorf("unable to retrieve object meta with: %v", mapping.MetadataAccessor) - } - } -} - func TestUnversioned(t *testing.T) { for _, obj := range []runtime.Object{ &metav1.Status{}, diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/register.go b/vendor/k8s.io/kubernetes/pkg/apis/core/register.go index 2784cbe15..c6cd8681d 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/register.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/register.go @@ -60,7 +60,6 @@ func addKnownTypes(scheme *runtime.Scheme) error { &ServiceProxyOptions{}, &NodeList{}, &Node{}, - &NodeConfigSource{}, &NodeProxyOptions{}, &Endpoints{}, &EndpointsList{}, diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/resource.go b/vendor/k8s.io/kubernetes/pkg/apis/core/resource.go index 1910cd921..1367e00e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/resource.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/resource.go @@ -47,13 +47,6 @@ func (self *ResourceList) Pods() *resource.Quantity { return &resource.Quantity{} } -func (self *ResourceList) NvidiaGPU() *resource.Quantity { - if val, ok := (*self)[ResourceNvidiaGPU]; ok { - return &val - } - return &resource.Quantity{} -} - func (self *ResourceList) StorageEphemeral() *resource.Quantity { if val, ok := (*self)[ResourceEphemeralStorage]; ok { return &val diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/types.go b/vendor/k8s.io/kubernetes/pkg/apis/core/types.go index e1b3853b6..1669edc41 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/types.go @@ -20,177 +20,10 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" ) -// Common string formats -// --------------------- -// Many fields in this API have formatting requirements. The commonly used -// formats are defined here. -// -// C_IDENTIFIER: This is a string that conforms to the definition of an "identifier" -// in the C language. This is captured by the following regex: -// [A-Za-z_][A-Za-z0-9_]* -// This defines the format, but not the length restriction, which should be -// specified at the definition of any field of this type. -// -// DNS_LABEL: This is a string, no more than 63 characters long, that conforms -// to the definition of a "label" in RFCs 1035 and 1123. This is captured -// by the following regex: -// [a-z0-9]([-a-z0-9]*[a-z0-9])? -// -// DNS_SUBDOMAIN: This is a string, no more than 253 characters long, that conforms -// to the definition of a "subdomain" in RFCs 1035 and 1123. This is captured -// by the following regex: -// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* -// or more simply: -// DNS_LABEL(\.DNS_LABEL)* -// -// IANA_SVC_NAME: This is a string, no more than 15 characters long, that -// conforms to the definition of IANA service name in RFC 6335. -// It must contains at least one letter [a-z] and it must contains only [a-z0-9-]. -// Hypens ('-') cannot be leading or trailing character of the string -// and cannot be adjacent to other hyphens. - -// ObjectMeta is metadata that all persisted resources must have, which includes all objects -// users must create. -// DEPRECATED: Use k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta instead - this type will be removed soon. -type ObjectMeta struct { - // Name is unique within a namespace. Name is required when creating resources, although - // some resources may allow a client to request the generation of an appropriate name - // automatically. Name is primarily intended for creation idempotence and configuration - // definition. - // +optional - Name string - - // GenerateName indicates that the name should be made unique by the server prior to persisting - // it. A non-empty value for the field indicates the name will be made unique (and the name - // returned to the client will be different than the name passed). The value of this field will - // be combined with a unique suffix on the server if the Name field has not been provided. - // The provided value must be valid within the rules for Name, and may be truncated by the length - // of the suffix required to make the value unique on the server. - // - // If this field is specified, and Name is not present, the server will NOT return a 409 if the - // generated name exists - instead, it will either return 201 Created or 500 with Reason - // ServerTimeout indicating a unique name could not be found in the time allotted, and the client - // should retry (optionally after the time indicated in the Retry-After header). - // +optional - GenerateName string - - // Namespace defines the space within which name must be unique. An empty namespace is - // equivalent to the "default" namespace, but "default" is the canonical representation. - // Not all objects are required to be scoped to a namespace - the value of this field for - // those objects will be empty. - // +optional - Namespace string - - // SelfLink is a URL representing this object. - // +optional - SelfLink string - - // UID is the unique in time and space value for this object. It is typically generated by - // the server on successful creation of a resource and is not allowed to change on PUT - // operations. - // +optional - UID types.UID - - // An opaque value that represents the version of this resource. May be used for optimistic - // concurrency, change detection, and the watch operation on a resource or set of resources. - // Clients must treat these values as opaque and values may only be valid for a particular - // resource or set of resources. Only servers will generate resource versions. - // +optional - ResourceVersion string - - // A sequence number representing a specific generation of the desired state. - // Populated by the system. Read-only. - // +optional - Generation int64 - - // CreationTimestamp is a timestamp representing the server time when this object was - // created. It is not guaranteed to be set in happens-before order across separate operations. - // Clients may not set this value. It is represented in RFC3339 form and is in UTC. - // +optional - CreationTimestamp metav1.Time - - // DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This - // field is set by the server when a graceful deletion is requested by the user, and is not - // directly settable by a client. The resource is expected to be deleted (no longer visible - // from resource lists, and not reachable by name) after the time in this field. Once set, - // this value may not be unset or be set further into the future, although it may be shortened - // or the resource may be deleted prior to this time. For example, a user may request that - // a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination - // signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard - // termination signal (SIGKILL) to the container and after cleanup, remove the pod from the - // API. In the presence of network partitions, this object may still exist after this - // timestamp, until an administrator or automated process can determine the resource is - // fully terminated. - // If not set, graceful deletion of the object has not been requested. - // - // Populated by the system when a graceful deletion is requested. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - DeletionTimestamp *metav1.Time - - // DeletionGracePeriodSeconds records the graceful deletion value set when graceful deletion - // was requested. Represents the most recent grace period, and may only be shortened once set. - // +optional - DeletionGracePeriodSeconds *int64 - - // Labels are key value pairs that may be used to scope and select individual resources. - // Label keys are of the form: - // label-key ::= prefixed-name | name - // prefixed-name ::= prefix '/' name - // prefix ::= DNS_SUBDOMAIN - // name ::= DNS_LABEL - // The prefix is optional. If the prefix is not specified, the key is assumed to be private - // to the user. Other system components that wish to use labels must specify a prefix. The - // "kubernetes.io/" prefix is reserved for use by kubernetes components. - // +optional - Labels map[string]string - - // Annotations are unstructured key value data stored with a resource that may be set by - // external tooling. They are not queryable and should be preserved when modifying - // objects. Annotation keys have the same formatting restrictions as Label keys. See the - // comments on Labels for details. - // +optional - Annotations map[string]string - - // List of objects depended by this object. If ALL objects in the list have - // been deleted, this object will be garbage collected. If this object is managed by a controller, - // then an entry in this list will point to this controller, with the controller field set to true. - // There cannot be more than one managing controller. - // +optional - OwnerReferences []metav1.OwnerReference - - // An initializer is a controller which enforces some system invariant at object creation time. - // This field is a list of initializers that have not yet acted on this object. If nil or empty, - // this object has been completely initialized. Otherwise, the object is considered uninitialized - // and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to - // observe uninitialized objects. - // - // When an object is created, the system will populate this list with the current set of initializers. - // Only privileged users may set or modify this list. Once it is empty, it may not be modified further - // by any user. - Initializers *metav1.Initializers - - // Must be empty before the object is deleted from the registry. Each entry - // is an identifier for the responsible component that will remove the entry - // from the list. If the deletionTimestamp of the object is non-nil, entries - // in this list can only be removed. - // +optional - Finalizers []string - - // The name of the cluster which the object belongs to. - // This is used to distinguish resources with same name and namespace in different clusters. - // This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. - // +optional - ClusterName string -} - const ( // NamespaceDefault means the object is in the default namespace which is applied when not specified by clients NamespaceDefault string = "default" @@ -242,6 +75,9 @@ type VolumeSource struct { // +optional AWSElasticBlockStore *AWSElasticBlockStoreVolumeSource // GitRepo represents a git repository at a particular revision. + // DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an + // EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir + // into the Pod's container. // +optional GitRepo *GitRepoVolumeSource // Secret represents a secret that should populate this volume. @@ -357,7 +193,7 @@ type PersistentVolumeSource struct { FlexVolume *FlexPersistentVolumeSource // Cinder represents a cinder volume attached and mounted on kubelets host machine // +optional - Cinder *CinderVolumeSource + Cinder *CinderPersistentVolumeSource // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime // +optional CephFS *CephFSPersistentVolumeSource @@ -412,10 +248,6 @@ const ( // MountOptionAnnotation defines mount option annotation used in PVs MountOptionAnnotation = "volume.beta.kubernetes.io/mount-options" - - // AlphaStorageNodeAffinityAnnotation defines node affinity policies for a PersistentVolume. - // Value is a string of the json representation of type NodeAffinity - AlphaStorageNodeAffinityAnnotation = "volume.alpha.kubernetes.io/node-affinity" ) // +genclient @@ -961,6 +793,10 @@ type AWSElasticBlockStoreVolumeSource struct { // Represents a volume that is populated with the contents of a git repository. // Git repo volumes do not support ownership management. // Git repo volumes support SELinux relabeling. +// +// DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an +// EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir +// into the Pod's container. type GitRepoVolumeSource struct { // Repository URL Repository string @@ -1163,6 +999,32 @@ type CinderVolumeSource struct { // the ReadOnly setting in VolumeMounts. // +optional ReadOnly bool + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *LocalObjectReference +} + +// Represents a cinder volume resource in Openstack. A Cinder volume +// must exist before mounting to a container. The volume must also be +// in the same region as the kubelet. Cinder volumes support ownership +// management and SELinux relabeling. +type CinderPersistentVolumeSource struct { + // Unique id of the volume used to identify the cinder volume + VolumeID string + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // +optional + FSType string + // Optional: Defaults to false (read/write). ReadOnly here will force + // the ReadOnly setting in VolumeMounts. + // +optional + ReadOnly bool + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *SecretReference } // Represents a Ceph Filesystem mount that lasts the lifetime of a pod @@ -1562,6 +1424,28 @@ type ConfigMapProjection struct { Optional *bool } +// ServiceAccountTokenProjection represents a projected service account token +// volume. This projection can be used to insert a service account token into +// the pods runtime filesystem for use against APIs (Kubernetes API Server or +// otherwise). +type ServiceAccountTokenProjection struct { + // Audience is the intended audience of the token. A recipient of a token + // must identify itself with an identifier specified in the audience of the + // token, and otherwise should reject the token. The audience defaults to the + // identifier of the apiserver. + Audience string + // ExpirationSeconds is the requested duration of validity of the service + // account token. As the token approaches expiration, the kubelet volume + // plugin will proactively rotate the service account token. The kubelet will + // start trying to rotate the token if the token is older than 80 percent of + // its time to live or if the token is older than 24 hours.Defaults to 1 hour + // and must be at least 10 minutes. + ExpirationSeconds int64 + // Path is the path relative to the mount point of the file to project the + // token into. + Path string +} + // Represents a projected volume source type ProjectedVolumeSource struct { // list of volume projections @@ -1585,6 +1469,8 @@ type VolumeProjection struct { DownwardAPI *DownwardAPIProjection // information about the configMap data to project ConfigMap *ConfigMapProjection + // information about the serviceAccountToken data to project + ServiceAccountToken *ServiceAccountTokenProjection } // Maps a string key to a path within a volume. @@ -1605,11 +1491,13 @@ type KeyToPath struct { Mode *int32 } -// Local represents directly-attached storage with node affinity +// Local represents directly-attached storage with node affinity (Beta feature) type LocalVolumeSource struct { - // The full path to the volume on the node - // For alpha, this path must be a directory - // Once block as a source is supported, then this path can point to a block device + // The full path to the volume on the node. + // It can be either a directory or block device (disk, partition, ...). + // Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. + // Block devices can be represented only by VolumeMode=Block, which also requires the + // BlockVolume alpha feature gate to be enabled. Path string } @@ -1631,7 +1519,7 @@ type CSIPersistentVolumeSource struct { // Filesystem type to mount. // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // Ex. "ext4", "xfs", "ntfs". // +optional FSType string @@ -1701,7 +1589,7 @@ type VolumeMount struct { SubPath string // mountPropagation determines how mounts are propagated from the host // to container and the other way around. - // When not set, MountPropagationHostToContainer is used. + // When not set, MountPropagationNone is used. // This field is beta in 1.10. // +optional MountPropagation *MountPropagationMode @@ -2206,6 +2094,8 @@ const ( // PodReasonUnschedulable reason in PodScheduled PodCondition means that the scheduler // can't schedule the pod right now, for example due to insufficient resources in the cluster. PodReasonUnschedulable = "Unschedulable" + // ContainersReady indicates whether all containers in the pod are ready. + ContainersReady PodConditionType = "ContainersReady" ) type PodCondition struct { @@ -2276,10 +2166,14 @@ type NodeSelector struct { NodeSelectorTerms []NodeSelectorTerm } -// A null or empty node selector term matches no objects. +// A null or empty node selector term matches no objects. The requirements of +// them are ANDed. +// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. type NodeSelectorTerm struct { - //Required. A list of node selector requirements. The requirements are ANDed. + // A list of node selector requirements by node's labels. MatchExpressions []NodeSelectorRequirement + // A list of node selector requirements by node's fields. + MatchFields []NodeSelectorRequirement } // A node selector requirement is a selector that contains values, a key, and an operator @@ -2312,6 +2206,27 @@ const ( NodeSelectorOpLt NodeSelectorOperator = "Lt" ) +// A topology selector term represents the result of label queries. +// A null or empty topology selector term matches no objects. +// The requirements of them are ANDed. +// It provides a subset of functionality as NodeSelectorTerm. +// This is an alpha feature and may change in the future. +type TopologySelectorTerm struct { + // A list of topology selector requirements by labels. + // +optional + MatchLabelExpressions []TopologySelectorLabelRequirement +} + +// A topology selector requirement is a selector that matches given label. +// This is an alpha feature and may change in the future. +type TopologySelectorLabelRequirement struct { + // The label key that the selector applies to. + Key string + // An array of string values. One value must match the label to be selected. + // Each entry in Values is ORed. + Values []string +} + // Affinity is a group of affinity scheduling rules. type Affinity struct { // Describes node affinity scheduling rules for the pod. @@ -2544,6 +2459,12 @@ const ( TolerationOpEqual TolerationOperator = "Equal" ) +// PodReadinessGate contains the reference to a pod condition +type PodReadinessGate struct { + // ConditionType refers to a condition in the pod's condition list with matching type. + ConditionType PodConditionType +} + // PodSpec is a description of a pod type PodSpec struct { Volumes []Volume @@ -2640,6 +2561,12 @@ type PodSpec struct { // configuration based on DNSPolicy. // +optional DNSConfig *PodDNSConfig + // If specified, all readiness gates will be evaluated for pod readiness. + // A pod is ready when all its containers are ready AND + // all conditions specified in the readiness gates have status equal to "True" + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md + // +optional + ReadinessGates []PodReadinessGate } // HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the @@ -2732,6 +2659,10 @@ type PodSecurityContext struct { // If unset, the Kubelet will not modify the ownership and permissions of any volume. // +optional FSGroup *int64 + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // +optional + Sysctls []Sysctl } // PodQOSClass defines the supported qos classes of Pods. @@ -3219,9 +3150,6 @@ type ServiceSpec struct { // The primary use case for setting this field is to use a StatefulSet's Headless Service // to propagate SRV records for its Pods without respect to their readiness for purpose // of peer discovery. - // This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints - // when that annotation is deprecated and all clients have been converted to use this - // field. // +optional PublishNotReadyAddresses bool } @@ -3399,10 +3327,6 @@ type NodeSpec struct { // +optional PodCIDR string - // External ID of the node assigned by some machine database (e.g. a cloud provider) - // +optional - ExternalID string - // ID of the node assigned by the cloud provider // Note: format is "://" // +optional @@ -3420,14 +3344,40 @@ type NodeSpec struct { // The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field // +optional ConfigSource *NodeConfigSource -} -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + // Deprecated. Not all kubelets will set this field. Remove field after 1.13. + // see: https://issues.k8s.io/61966 + // +optional + DoNotUse_ExternalID string +} // NodeConfigSource specifies a source of node configuration. Exactly one subfield must be non-nil. type NodeConfigSource struct { - metav1.TypeMeta - ConfigMapRef *ObjectReference + ConfigMap *ConfigMapNodeConfigSource +} + +type ConfigMapNodeConfigSource struct { + // Namespace is the metadata.namespace of the referenced ConfigMap. + // This field is required in all cases. + Namespace string + + // Name is the metadata.name of the referenced ConfigMap. + // This field is required in all cases. + Name string + + // UID is the metadata.UID of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + UID types.UID + + // ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + ResourceVersion string + + // KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure + // This field is required in all cases. + KubeletConfigKey string } // DaemonEndpoint contains information about a single Daemon endpoint. @@ -3477,6 +3427,53 @@ type NodeSystemInfo struct { Architecture string } +// NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource. +type NodeConfigStatus struct { + // Assigned reports the checkpointed config the node will try to use. + // When Node.Spec.ConfigSource is updated, the node checkpoints the associated + // config payload to local disk, along with a record indicating intended + // config. The node refers to this record to choose its config checkpoint, and + // reports this record in Assigned. Assigned only updates in the status after + // the record has been checkpointed to disk. When the Kubelet is restarted, + // it tries to make the Assigned config the Active config by loading and + // validating the checkpointed payload identified by Assigned. + // +optional + Assigned *NodeConfigSource + // Active reports the checkpointed config the node is actively using. + // Active will represent either the current version of the Assigned config, + // or the current LastKnownGood config, depending on whether attempting to use the + // Assigned config results in an error. + // +optional + Active *NodeConfigSource + // LastKnownGood reports the checkpointed config the node will fall back to + // when it encounters an error attempting to use the Assigned config. + // The Assigned config becomes the LastKnownGood config when the node determines + // that the Assigned config is stable and correct. + // This is currently implemented as a 10-minute soak period starting when the local + // record of Assigned config is updated. If the Assigned config is Active at the end + // of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is + // reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, + // because the local default config is always assumed good. + // You should not make assumptions about the node's method of determining config stability + // and correctness, as this may change or become configurable in the future. + // +optional + LastKnownGood *NodeConfigSource + // Error describes any problems reconciling the Spec.ConfigSource to the Active config. + // Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned + // record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting + // to load or validate the Assigned config, etc. + // Errors may occur at different points while syncing config. Earlier errors (e.g. download or + // checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across + // Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in + // a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error + // by fixing the config assigned in Spec.ConfigSource. + // You can find additional information for debugging by searching the error message in the Kubelet log. + // Error is a human-readable description of the error state; machines can check whether or not Error + // is empty, but should not rely on the stability of the Error text across Kubelet versions. + // +optional + Error string +} + // NodeStatus is information about the current status of a node. type NodeStatus struct { // Capacity represents the total resources of a node. @@ -3509,6 +3506,9 @@ type NodeStatus struct { // List of volumes that are attached to the node. // +optional VolumesAttached []AttachedVolume + // Status of the config assigned to the node via the dynamic Kubelet config feature. + // +optional + Config *NodeConfigStatus } type UniqueVolumeName string @@ -3593,8 +3593,6 @@ const ( NodeDiskPressure NodeConditionType = "DiskPressure" // NodeNetworkUnavailable means that network for the node is not correctly configured. NodeNetworkUnavailable NodeConditionType = "NetworkUnavailable" - // NodeKubeletConfigOk indicates whether the kubelet is correctly configured - NodeKubeletConfigOk NodeConditionType = "KubeletConfigOk" ) type NodeCondition struct { @@ -3651,8 +3649,6 @@ const ( // Local ephemeral storage, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024) // The resource name for ResourceEphemeralStorage is alpha and it can change across releases. ResourceEphemeralStorage ResourceName = "ephemeral-storage" - // NVIDIA GPU, in devices. Alpha, might change: although fractional and allowing values >1, only one whole device per node is assigned. - ResourceNvidiaGPU ResourceName = "alpha.kubernetes.io/nvidia-gpu" ) const ( @@ -3660,6 +3656,8 @@ const ( ResourceDefaultNamespacePrefix = "kubernetes.io/" // Name prefix for huge page resources (alpha). ResourceHugePagesPrefix = "hugepages-" + // Name prefix for storage resource limits + ResourceAttachableVolumesPrefix = "attachable-volumes-" ) // ResourceList is a set of (resource name, quantity) pairs. @@ -3780,86 +3778,6 @@ type Preconditions struct { UID *types.UID } -// DeletionPropagation decides whether and how garbage collection will be performed. -type DeletionPropagation string - -const ( - // Orphans the dependents. - DeletePropagationOrphan DeletionPropagation = "Orphan" - // Deletes the object from the key-value store, the garbage collector will delete the dependents in the background. - DeletePropagationBackground DeletionPropagation = "Background" - // The object exists in the key-value store until the garbage collector deletes all the dependents whose ownerReference.blockOwnerDeletion=true from the key-value store. - // API sever will put the "DeletingDependents" finalizer on the object, and sets its deletionTimestamp. - // This policy is cascading, i.e., the dependents will be deleted with Foreground. - DeletePropagationForeground DeletionPropagation = "Foreground" -) - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// DeleteOptions may be provided when deleting an API object -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -type DeleteOptions struct { - metav1.TypeMeta - - // Optional duration in seconds before the object should be deleted. Value must be non-negative integer. - // The value zero indicates delete immediately. If this value is nil, the default grace period for the - // specified type will be used. - // +optional - GracePeriodSeconds *int64 - - // Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be - // returned. - // +optional - Preconditions *Preconditions - - // Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. - // Should the dependent objects be orphaned. If true/false, the "orphan" - // finalizer will be added to/removed from the object's finalizers list. - // Either this field or PropagationPolicy may be set, but not both. - // +optional - OrphanDependents *bool - - // Whether and how garbage collection will be performed. - // Either this field or OrphanDependents may be set, but not both. - // The default policy is decided by the existing finalizer set in the - // metadata.finalizers and the resource-specific default policy. - // Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - - // allow the garbage collector to delete the dependents in the background; - // 'Foreground' - a cascading policy that deletes all dependents in the - // foreground. - // +optional - PropagationPolicy *DeletionPropagation -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// ListOptions is the query options to a standard REST list call, and has future support for -// watch calls. -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -type ListOptions struct { - metav1.TypeMeta - - // A selector based on labels - LabelSelector labels.Selector - // A selector based on fields - FieldSelector fields.Selector - - // If true, partially initialized resources are included in the response. - IncludeUninitialized bool - - // If true, watch for changes to this list - Watch bool - // When specified with a watch call, shows changes that occur after that particular version of a resource. - // Defaults to changes from the beginning of history. - // When specified for list: - // - if unset, then the result is returned from remote storage based on quorum-read flag; - // - if it's 0, then we simply return what we currently have in cache, no guarantee; - // - if set to non zero, then the result is at least as fresh as given rv. - ResourceVersion string - // Timeout for the list/watch call. - TimeoutSeconds *int64 -} - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // PodLogOptions is the query options for a Pod's logs REST call @@ -4278,6 +4196,8 @@ const ( ResourceQuotaScopeBestEffort ResourceQuotaScope = "BestEffort" // Match all pod objects that do not have best effort quality of service ResourceQuotaScopeNotBestEffort ResourceQuotaScope = "NotBestEffort" + // Match all pod objects that have priority class mentioned + ResourceQuotaScopePriorityClass ResourceQuotaScope = "PriorityClass" ) // ResourceQuotaSpec defines the desired hard limits to enforce for Quota @@ -4289,8 +4209,47 @@ type ResourceQuotaSpec struct { // If not specified, the quota matches all objects. // +optional Scopes []ResourceQuotaScope + // ScopeSelector is also a collection of filters like Scopes that must match each object tracked by a quota + // but expressed using ScopeSelectorOperator in combination with possible values. + // +optional + ScopeSelector *ScopeSelector } +// A scope selector represents the AND of the selectors represented +// by the scoped-resource selector terms. +type ScopeSelector struct { + // A list of scope selector requirements by scope of the resources. + // +optional + MatchExpressions []ScopedResourceSelectorRequirement +} + +// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator +// that relates the scope name and values. +type ScopedResourceSelectorRequirement struct { + // The name of the scope that the selector applies to. + ScopeName ResourceQuotaScope + // Represents a scope's relationship to a set of values. + // Valid operators are In, NotIn, Exists, DoesNotExist. + Operator ScopeSelectorOperator + // An array of string values. If the operator is In or NotIn, + // the values array must be non-empty. If the operator is Exists or DoesNotExist, + // the values array must be empty. + // This array is replaced during a strategic merge patch. + // +optional + Values []string +} + +// A scope selector operator is the set of operators that can be used in +// a scope selector requirement. +type ScopeSelectorOperator string + +const ( + ScopeSelectorOpIn ScopeSelectorOperator = "In" + ScopeSelectorOpNotIn ScopeSelectorOperator = "NotIn" + ScopeSelectorOpExists ScopeSelectorOperator = "Exists" + ScopeSelectorOpDoesNotExist ScopeSelectorOperator = "DoesNotExist" +) + // ResourceQuotaStatus defines the enforced hard limits and observed use type ResourceQuotaStatus struct { // Hard is the set of enforced hard limits for each named resource diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/conversion.go index d5bce756c..bc431d147 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/conversion.go @@ -495,6 +495,14 @@ func Convert_core_PodSecurityContext_To_v1_PodSecurityContext(in *core.PodSecuri out.RunAsGroup = in.RunAsGroup out.RunAsNonRoot = in.RunAsNonRoot out.FSGroup = in.FSGroup + if in.Sysctls != nil { + out.Sysctls = make([]v1.Sysctl, len(in.Sysctls)) + for i, sysctl := range in.Sysctls { + if err := Convert_core_Sysctl_To_v1_Sysctl(&sysctl, &out.Sysctls[i], s); err != nil { + return err + } + } + } return nil } @@ -512,6 +520,15 @@ func Convert_v1_PodSecurityContext_To_core_PodSecurityContext(in *v1.PodSecurity out.RunAsGroup = in.RunAsGroup out.RunAsNonRoot = in.RunAsNonRoot out.FSGroup = in.FSGroup + if in.Sysctls != nil { + out.Sysctls = make([]core.Sysctl, len(in.Sysctls)) + for i, sysctl := range in.Sysctls { + if err := Convert_v1_Sysctl_To_core_Sysctl(&sysctl, &out.Sysctls[i], s); err != nil { + return err + } + } + } + return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/defaults.go index c2aeafc3d..110ef54df 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/defaults.go @@ -17,6 +17,8 @@ limitations under the License. package v1 import ( + "time" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" @@ -223,6 +225,12 @@ func SetDefaults_ProjectedVolumeSource(obj *v1.ProjectedVolumeSource) { obj.DefaultMode = &perm } } +func SetDefaults_ServiceAccountTokenProjection(obj *v1.ServiceAccountTokenProjection) { + hour := int64(time.Hour.Seconds()) + if obj.ExpirationSeconds == nil { + obj.ExpirationSeconds = &hour + } +} func SetDefaults_PersistentVolume(obj *v1.PersistentVolume) { if obj.Status.Phase == "" { obj.Status.Phase = v1.VolumePending @@ -296,11 +304,6 @@ func SetDefaults_NamespaceStatus(obj *v1.NamespaceStatus) { obj.Phase = v1.NamespaceActive } } -func SetDefaults_Node(obj *v1.Node) { - if obj.Spec.ExternalID == "" { - obj.Spec.ExternalID = obj.Name - } -} func SetDefaults_NodeStatus(obj *v1.NodeStatus) { if obj.Allocatable == nil && obj.Capacity != nil { obj.Allocatable = make(v1.ResourceList, len(obj.Capacity)) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/defaults_test.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/defaults_test.go index fceab578f..e5fd61da1 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/defaults_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/defaults_test.go @@ -1033,20 +1033,6 @@ func TestSetDefaultPodSpecHostNetwork(t *testing.T) { } } -func TestSetDefaultNodeExternalID(t *testing.T) { - name := "node0" - n := &v1.Node{} - n.Name = name - obj2 := roundTrip(t, runtime.Object(n)) - n2 := obj2.(*v1.Node) - if n2.Spec.ExternalID != name { - t.Errorf("Expected default External ID: %s, got: %s", name, n2.Spec.ExternalID) - } - if n2.Spec.ProviderID != "" { - t.Errorf("Expected empty default Cloud Provider ID, got: %s", n2.Spec.ProviderID) - } -} - func TestSetDefaultNodeStatusAllocatable(t *testing.T) { capacity := v1.ResourceList{ v1.ResourceCPU: resource.MustParse("1000m"), diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/BUILD index 6c74f416a..2fc1eda5f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/BUILD @@ -15,6 +15,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/api/equality: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/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", ], ) @@ -27,9 +28,9 @@ go_library( "//pkg/apis/core/helper:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource: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/selection:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers.go index bb6d9385f..c8dbbdce9 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers.go @@ -23,9 +23,9 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/selection" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/kubernetes/pkg/apis/core/helper" ) @@ -36,7 +36,7 @@ import ( // to avoid confusion with the convention in quota // 3. it satisfies the rules in IsQualifiedName() after converted into quota resource name func IsExtendedResourceName(name v1.ResourceName) bool { - if IsDefaultNamespaceResource(name) || strings.HasPrefix(string(name), v1.DefaultResourceRequestsPrefix) { + if IsNativeResource(name) || strings.HasPrefix(string(name), v1.DefaultResourceRequestsPrefix) { return false } // Ensure it satisfies the rules in IsQualifiedName() after converted into quota resource name @@ -47,13 +47,18 @@ func IsExtendedResourceName(name v1.ResourceName) bool { return true } -// IsDefaultNamespaceResource returns true if the resource name is in the +// IsPrefixedNativeResource returns true if the resource name is in the +// *kubernetes.io/ namespace. +func IsPrefixedNativeResource(name v1.ResourceName) bool { + return strings.Contains(string(name), v1.ResourceDefaultNamespacePrefix) +} + +// IsNativeResource returns true if the resource name is in the // *kubernetes.io/ namespace. Partially-qualified (unprefixed) names are // implicitly in the kubernetes.io/ namespace. -func IsDefaultNamespaceResource(name v1.ResourceName) bool { +func IsNativeResource(name v1.ResourceName) bool { return !strings.Contains(string(name), "/") || - strings.Contains(string(name), v1.ResourceDefaultNamespacePrefix) - + IsPrefixedNativeResource(name) } // IsHugePageResourceName returns true if the resource name has the huge page @@ -80,19 +85,21 @@ func HugePageSizeFromResourceName(name v1.ResourceName) (resource.Quantity, erro return resource.ParseQuantity(pageSize) } -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 is not hugepages. func IsOvercommitAllowed(name v1.ResourceName) bool { - return IsDefaultNamespaceResource(name) && - !IsHugePageResourceName(name) && - !overcommitBlacklist.Has(string(name)) + return IsNativeResource(name) && + !IsHugePageResourceName(name) +} + +func IsAttachableVolumeResourceName(name v1.ResourceName) bool { + return strings.HasPrefix(string(name), v1.ResourceAttachableVolumesPrefix) } // Extended and Hugepages resources func IsScalarResourceName(name v1.ResourceName) bool { - return IsExtendedResourceName(name) || IsHugePageResourceName(name) + return IsExtendedResourceName(name) || IsHugePageResourceName(name) || + IsPrefixedNativeResource(name) || IsAttachableVolumeResourceName(name) } // this function aims to check if the service's ClusterIP is set or not @@ -244,6 +251,115 @@ func NodeSelectorRequirementsAsSelector(nsm []v1.NodeSelectorRequirement) (label return selector, nil } +// NodeSelectorRequirementsAsFieldSelector converts the []NodeSelectorRequirement core type into a struct that implements +// fields.Selector. +func NodeSelectorRequirementsAsFieldSelector(nsm []v1.NodeSelectorRequirement) (fields.Selector, error) { + if len(nsm) == 0 { + return fields.Nothing(), nil + } + + selectors := []fields.Selector{} + for _, expr := range nsm { + switch expr.Operator { + case v1.NodeSelectorOpIn: + if len(expr.Values) != 1 { + return nil, fmt.Errorf("unexpected number of value (%d) for node field selector operator %q", + len(expr.Values), expr.Operator) + } + selectors = append(selectors, fields.OneTermEqualSelector(expr.Key, expr.Values[0])) + + case v1.NodeSelectorOpNotIn: + if len(expr.Values) != 1 { + return nil, fmt.Errorf("unexpected number of value (%d) for node field selector operator %q", + len(expr.Values), expr.Operator) + } + selectors = append(selectors, fields.OneTermNotEqualSelector(expr.Key, expr.Values[0])) + + default: + return nil, fmt.Errorf("%q is not a valid node field selector operator", expr.Operator) + } + } + + return fields.AndSelectors(selectors...), nil +} + +// MatchNodeSelectorTerms checks whether the node labels and fields match node selector terms in ORed; +// nil or empty term matches no objects. +func MatchNodeSelectorTerms( + nodeSelectorTerms []v1.NodeSelectorTerm, + nodeLabels labels.Set, + nodeFields fields.Set, +) bool { + for _, req := range nodeSelectorTerms { + // nil or empty term selects no objects + if len(req.MatchExpressions) == 0 && len(req.MatchFields) == 0 { + continue + } + + if len(req.MatchExpressions) != 0 { + labelSelector, err := NodeSelectorRequirementsAsSelector(req.MatchExpressions) + if err != nil || !labelSelector.Matches(nodeLabels) { + continue + } + } + + if len(req.MatchFields) != 0 { + fieldSelector, err := NodeSelectorRequirementsAsFieldSelector(req.MatchFields) + if err != nil || !fieldSelector.Matches(nodeFields) { + continue + } + } + + return true + } + + return false +} + +// TopologySelectorRequirementsAsSelector converts the []TopologySelectorLabelRequirement api type into a struct +// that implements labels.Selector. +func TopologySelectorRequirementsAsSelector(tsm []v1.TopologySelectorLabelRequirement) (labels.Selector, error) { + if len(tsm) == 0 { + return labels.Nothing(), nil + } + + selector := labels.NewSelector() + for _, expr := range tsm { + r, err := labels.NewRequirement(expr.Key, selection.In, expr.Values) + if err != nil { + return nil, err + } + selector = selector.Add(*r) + } + + return selector, nil +} + +// MatchTopologySelectorTerms checks whether given labels match topology selector terms in ORed; +// nil or empty term matches no objects; while empty term list matches all objects. +func MatchTopologySelectorTerms(topologySelectorTerms []v1.TopologySelectorTerm, lbls labels.Set) bool { + if len(topologySelectorTerms) == 0 { + // empty term list matches all objects + return true + } + + for _, req := range topologySelectorTerms { + // nil or empty term selects no objects + if len(req.MatchLabelExpressions) == 0 { + continue + } + + labelSelector, err := TopologySelectorRequirementsAsSelector(req.MatchLabelExpressions) + if err != nil || !labelSelector.Matches(lbls) { + continue + } + + return true + } + + return false +} + // AddOrUpdateTolerationInPodSpec tries to add a toleration to the toleration list in PodSpec. // Returns true if something was updated, false otherwise. func AddOrUpdateTolerationInPodSpec(spec *v1.PodSpec, toleration *v1.Toleration) bool { @@ -346,54 +462,6 @@ func GetAvoidPodsFromNodeAnnotations(annotations map[string]string) (v1.AvoidPod return avoidPods, nil } -// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls -// and a slice of unsafe Sysctls. This is only a convenience wrapper around -// SysctlsFromPodAnnotation. -func SysctlsFromPodAnnotations(a map[string]string) ([]v1.Sysctl, []v1.Sysctl, error) { - safe, err := SysctlsFromPodAnnotation(a[v1.SysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - unsafe, err := SysctlsFromPodAnnotation(a[v1.UnsafeSysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - - return safe, unsafe, nil -} - -// SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls. -func SysctlsFromPodAnnotation(annotation string) ([]v1.Sysctl, error) { - if len(annotation) == 0 { - return nil, nil - } - - kvs := strings.Split(annotation, ",") - sysctls := make([]v1.Sysctl, len(kvs)) - for i, kv := range kvs { - cs := strings.Split(kv, "=") - if len(cs) != 2 || len(cs[0]) == 0 { - return nil, fmt.Errorf("sysctl %q not of the format sysctl_name=value", kv) - } - sysctls[i].Name = cs[0] - sysctls[i].Value = cs[1] - } - return sysctls, nil -} - -// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls. -func PodAnnotationsFromSysctls(sysctls []v1.Sysctl) string { - if len(sysctls) == 0 { - return "" - } - - kvs := make([]string, len(sysctls)) - for i := range sysctls { - kvs[i] = fmt.Sprintf("%s=%s", sysctls[i].Name, sysctls[i].Value) - } - return strings.Join(kvs, ",") -} - // GetPersistentVolumeClass returns StorageClassName. func GetPersistentVolumeClass(volume *v1.PersistentVolume) string { // Use beta annotation first @@ -418,33 +486,3 @@ func GetPersistentVolumeClaimClass(claim *v1.PersistentVolumeClaim) string { return "" } - -// GetStorageNodeAffinityFromAnnotation gets the json serialized data from PersistentVolume.Annotations -// and converts it to the NodeAffinity type in api. -// TODO: update when storage node affinity graduates to beta -func GetStorageNodeAffinityFromAnnotation(annotations map[string]string) (*v1.NodeAffinity, error) { - if len(annotations) > 0 && annotations[v1.AlphaStorageNodeAffinityAnnotation] != "" { - var affinity v1.NodeAffinity - err := json.Unmarshal([]byte(annotations[v1.AlphaStorageNodeAffinityAnnotation]), &affinity) - if err != nil { - return nil, err - } - return &affinity, nil - } - return nil, nil -} - -// Converts NodeAffinity type to Alpha annotation for use in PersistentVolumes -// TODO: update when storage node affinity graduates to beta -func StorageNodeAffinityToAlphaAnnotation(annotations map[string]string, affinity *v1.NodeAffinity) error { - if affinity == nil { - return nil - } - - json, err := json.Marshal(*affinity) - if err != nil { - return err - } - annotations[v1.AlphaStorageNodeAffinityAnnotation] = string(json) - return nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers_test.go index be1ecfaf9..950edb9b9 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers_test.go @@ -25,10 +25,11 @@ import ( apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" ) -func TestIsDefaultNamespaceResource(t *testing.T) { +func TestIsNativeResource(t *testing.T) { testCases := []struct { resourceName v1.ResourceName expectVal bool @@ -58,7 +59,7 @@ func TestIsDefaultNamespaceResource(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) { t.Parallel() - v := IsDefaultNamespaceResource(tc.resourceName) + v := IsNativeResource(tc.resourceName) if v != tc.expectVal { t.Errorf("Got %v but expected %v", v, tc.expectVal) } @@ -125,10 +126,6 @@ func TestIsOvercommitAllowed(t *testing.T) { resourceName: "kubernetes.io/resource-foo", expectVal: true, }, - { - resourceName: "alpha.kubernetes.io/nvidia-gpu", - expectVal: false, - }, { resourceName: "hugepages-100m", expectVal: false, @@ -304,6 +301,71 @@ func TestNodeSelectorRequirementsAsSelector(t *testing.T) { } } +func TestTopologySelectorRequirementsAsSelector(t *testing.T) { + mustParse := func(s string) labels.Selector { + out, e := labels.Parse(s) + if e != nil { + panic(e) + } + return out + } + tc := []struct { + in []v1.TopologySelectorLabelRequirement + out labels.Selector + expectErr bool + }{ + {in: nil, out: labels.Nothing()}, + {in: []v1.TopologySelectorLabelRequirement{}, out: labels.Nothing()}, + { + in: []v1.TopologySelectorLabelRequirement{{ + Key: "foo", + Values: []string{"bar", "baz"}, + }}, + out: mustParse("foo in (baz,bar)"), + }, + { + in: []v1.TopologySelectorLabelRequirement{{ + Key: "foo", + Values: []string{}, + }}, + expectErr: true, + }, + { + in: []v1.TopologySelectorLabelRequirement{ + { + Key: "foo", + Values: []string{"bar", "baz"}, + }, + { + Key: "invalid", + Values: []string{}, + }, + }, + expectErr: true, + }, + { + in: []v1.TopologySelectorLabelRequirement{{ + Key: "/invalidkey", + Values: []string{"bar", "baz"}, + }}, + expectErr: true, + }, + } + + for i, tc := range tc { + out, err := TopologySelectorRequirementsAsSelector(tc.in) + if err == nil && tc.expectErr { + t.Errorf("[%v]expected error but got none.", i) + } + if err != nil && !tc.expectErr { + t.Errorf("[%v]did not expect error but got: %v", i, err) + } + if !reflect.DeepEqual(out, tc.out) { + t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out) + } + } +} + func TestTolerationsTolerateTaintsWithFilter(t *testing.T) { testCases := []struct { description string @@ -520,136 +582,686 @@ func TestGetAvoidPodsFromNode(t *testing.T) { } } -func TestSysctlsFromPodAnnotation(t *testing.T) { - type Test struct { - annotation string - expectValue []v1.Sysctl - expectErr bool +func TestMatchNodeSelectorTerms(t *testing.T) { + type args struct { + nodeSelectorTerms []v1.NodeSelectorTerm + nodeLabels labels.Set + nodeFields fields.Set } - for i, test := range []Test{ + + tests := []struct { + name string + args args + want bool + }{ + { + name: "nil terms", + args: args{ + nodeSelectorTerms: nil, + nodeLabels: nil, + nodeFields: nil, + }, + want: false, + }, + { + name: "node label matches matchExpressions terms", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val"}, + }}, + }, + }, + nodeLabels: map[string]string{"label_1": "label_1_val"}, + nodeFields: nil, + }, + want: true, + }, + { + name: "node field matches matchFields terms", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }}, + }, + }, + nodeLabels: nil, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: true, + }, { - annotation: "", - expectValue: nil, + name: "invalid node field requirement", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1, host_2"}, + }}, + }, + }, + nodeLabels: nil, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: false, }, { - annotation: "foo.bar", - expectErr: true, + name: "fieldSelectorTerm with node labels", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }}, + }, + }, + nodeLabels: map[string]string{ + "metadata.name": "host_1", + }, + nodeFields: nil, + }, + want: false, }, { - annotation: "=123", - expectErr: true, + name: "labelSelectorTerm with node fields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }}, + }, + }, + nodeLabels: nil, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: false, }, { - annotation: "foo.bar=", - expectValue: []v1.Sysctl{{Name: "foo.bar", Value: ""}}, + name: "labelSelectorTerm and fieldSelectorTerm was set, but only node fields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }}, + }, + }, + nodeLabels: nil, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: false, }, { - annotation: "foo.bar=42", - expectValue: []v1.Sysctl{{Name: "foo.bar", Value: "42"}}, + name: "labelSelectorTerm and fieldSelectorTerm was set, both node fields and labels (both matched)", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }}, + }, + }, + nodeLabels: map[string]string{ + "label_1": "label_1_val", + }, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: true, }, { - annotation: "foo.bar=42,", - expectErr: true, + name: "labelSelectorTerm and fieldSelectorTerm was set, both node fields and labels (one mismatched)", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }}, + }, + }, + nodeLabels: map[string]string{ + "label_1": "label_1_val-failed", + }, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: false, }, { - annotation: "foo.bar=42,abc.def=1", - expectValue: []v1.Sysctl{{Name: "foo.bar", Value: "42"}, {Name: "abc.def", Value: "1"}}, + name: "multi-selector was set, both node fields and labels (one mismatched)", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val"}, + }}, + }, + { + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }}, + }, + }, + nodeLabels: map[string]string{ + "label_1": "label_1_val-failed", + }, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: true, }, - } { - sysctls, err := SysctlsFromPodAnnotation(test.annotation) - if test.expectErr && err == nil { - t.Errorf("[%v]expected error but got none", i) - } else if !test.expectErr && err != nil { - t.Errorf("[%v]did not expect error but got: %v", i, err) - } else if !reflect.DeepEqual(sysctls, test.expectValue) { - t.Errorf("[%v]expect value %v but got %v", i, test.expectValue, sysctls) - } + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := MatchNodeSelectorTerms(tt.args.nodeSelectorTerms, tt.args.nodeLabels, tt.args.nodeFields); got != tt.want { + t.Errorf("MatchNodeSelectorTermsORed() = %v, want %v", got, tt.want) + } + }) } } -// TODO: remove when alpha support for topology constraints is removed -func TestGetNodeAffinityFromAnnotations(t *testing.T) { - testCases := []struct { - annotations map[string]string - expectErr bool +// TestMatchNodeSelectorTermsStateless ensures MatchNodeSelectorTerms() +// is invoked in a "stateless" manner, i.e. nodeSelectorTerms should NOT +// be deeply modifed after invoking +func TestMatchNodeSelectorTermsStateless(t *testing.T) { + type args struct { + nodeSelectorTerms []v1.NodeSelectorTerm + nodeLabels labels.Set + nodeFields fields.Set + } + + tests := []struct { + name string + args args + want []v1.NodeSelectorTerm }{ { - annotations: nil, - expectErr: false, + name: "nil terms", + args: args{ + nodeSelectorTerms: nil, + nodeLabels: nil, + nodeFields: nil, + }, + want: nil, }, { - annotations: map[string]string{}, - expectErr: false, + name: "nodeLabels: preordered matchExpressions and nil matchFields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val", "label_2_val"}, + }}, + }, + }, + nodeLabels: map[string]string{"label_1": "label_1_val"}, + nodeFields: nil, + }, + want: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val", "label_2_val"}, + }}, + }, + }, }, { - annotations: map[string]string{ - v1.AlphaStorageNodeAffinityAnnotation: `{ - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [ - { "matchExpressions": [ - { "key": "test-key1", - "operator": "In", - "values": ["test-value1", "test-value2"] - }, - { "key": "test-key2", - "operator": "In", - "values": ["test-value1", "test-value2"] - } - ]} - ]} - }`, + name: "nodeLabels: unordered matchExpressions and nil matchFields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_2_val", "label_1_val"}, + }}, + }, + }, + nodeLabels: map[string]string{"label_1": "label_1_val"}, + nodeFields: nil, + }, + want: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_2_val", "label_1_val"}, + }}, + }, + }, + }, + { + name: "nodeFields: nil matchExpressions and preordered matchFields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1", "host_2"}, + }}, + }, + }, + nodeLabels: nil, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1", "host_2"}, + }}, + }, }, - expectErr: false, }, { - annotations: map[string]string{ - v1.AlphaStorageNodeAffinityAnnotation: `[{ - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [ - { "matchExpressions": [ - { "key": "test-key1", - "operator": "In", - "values": ["test-value1", "test-value2"] - }, - { "key": "test-key2", - "operator": "In", - "values": ["test-value1", "test-value2"] - } - ]} - ]} - }]`, + name: "nodeFields: nil matchExpressions and unordered matchFields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_2", "host_1"}, + }}, + }, + }, + nodeLabels: nil, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_2", "host_1"}, + }}, + }, }, - expectErr: true, }, { - annotations: map[string]string{ - v1.AlphaStorageNodeAffinityAnnotation: `{ - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": - "matchExpressions": [ - { "key": "test-key1", - "operator": "In", - "values": ["test-value1", "test-value2"] - }, - { "key": "test-key2", - "operator": "In", - "values": ["test-value1", "test-value2"] - } - ]} - } - }`, + name: "nodeLabels and nodeFields: ordered matchExpressions and ordered matchFields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val", "label_2_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1", "host_2"}, + }}, + }, + }, + nodeLabels: map[string]string{ + "label_1": "label_1_val", + }, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val", "label_2_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1", "host_2"}, + }}, + }, + }, + }, + { + name: "nodeLabels and nodeFields: ordered matchExpressions and unordered matchFields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val", "label_2_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_2", "host_1"}, + }}, + }, + }, + nodeLabels: map[string]string{ + "label_1": "label_1_val", + }, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_1_val", "label_2_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_2", "host_1"}, + }}, + }, + }, + }, + { + name: "nodeLabels and nodeFields: unordered matchExpressions and ordered matchFields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_2_val", "label_1_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1", "host_2"}, + }}, + }, + }, + nodeLabels: map[string]string{ + "label_1": "label_1_val", + }, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_2_val", "label_1_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1", "host_2"}, + }}, + }, + }, + }, + { + name: "nodeLabels and nodeFields: unordered matchExpressions and unordered matchFields", + args: args{ + nodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_2_val", "label_1_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_2", "host_1"}, + }}, + }, + }, + nodeLabels: map[string]string{ + "label_1": "label_1_val", + }, + nodeFields: map[string]string{ + "metadata.name": "host_1", + }, + }, + want: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{{ + Key: "label_1", + Operator: v1.NodeSelectorOpIn, + Values: []string{"label_2_val", "label_1_val"}, + }}, + MatchFields: []v1.NodeSelectorRequirement{{ + Key: "metadata.name", + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_2", "host_1"}, + }}, + }, }, - expectErr: true, }, } - for i, tc := range testCases { - _, err := GetStorageNodeAffinityFromAnnotation(tc.annotations) - if err == nil && tc.expectErr { - t.Errorf("[%v]expected error but got none.", i) - } - if err != nil && !tc.expectErr { - t.Errorf("[%v]did not expect error but got: %v", i, err) - } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + MatchNodeSelectorTerms(tt.args.nodeSelectorTerms, tt.args.nodeLabels, tt.args.nodeFields) + if !apiequality.Semantic.DeepEqual(tt.args.nodeSelectorTerms, tt.want) { + // fail when tt.args.nodeSelectorTerms is deeply modified + t.Errorf("MatchNodeSelectorTerms() got = %v, want %v", tt.args.nodeSelectorTerms, tt.want) + } + }) + } +} + +func TestMatchTopologySelectorTerms(t *testing.T) { + type args struct { + topologySelectorTerms []v1.TopologySelectorTerm + labels labels.Set + } + + tests := []struct { + name string + args args + want bool + }{ + { + name: "nil term list", + args: args{ + topologySelectorTerms: nil, + labels: nil, + }, + want: true, + }, + { + name: "nil term", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{}, + }, + }, + labels: nil, + }, + want: false, + }, + { + name: "label matches MatchLabelExpressions terms", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_1", + Values: []string{"label_1_val"}, + }}, + }, + }, + labels: map[string]string{"label_1": "label_1_val"}, + }, + want: true, + }, + { + name: "label does not match MatchLabelExpressions terms", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_1", + Values: []string{"label_1_val"}, + }}, + }, + }, + labels: map[string]string{"label_1": "label_1_val-failed"}, + }, + want: false, + }, + { + name: "multi-values in one requirement, one matched", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_1", + Values: []string{"label_1_val1", "label_1_val2"}, + }}, + }, + }, + labels: map[string]string{"label_1": "label_1_val2"}, + }, + want: true, + }, + { + name: "multi-terms was set, one matched", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_1", + Values: []string{"label_1_val"}, + }}, + }, + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{{ + Key: "label_2", + Values: []string{"label_2_val"}, + }}, + }, + }, + labels: map[string]string{ + "label_2": "label_2_val", + }, + }, + want: true, + }, + { + name: "multi-requirement in one term, fully matched", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ + { + Key: "label_1", + Values: []string{"label_1_val"}, + }, + { + Key: "label_2", + Values: []string{"label_2_val"}, + }, + }, + }, + }, + labels: map[string]string{ + "label_1": "label_1_val", + "label_2": "label_2_val", + }, + }, + want: true, + }, + { + name: "multi-requirement in one term, partial matched", + args: args{ + topologySelectorTerms: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ + { + Key: "label_1", + Values: []string{"label_1_val"}, + }, + { + Key: "label_2", + Values: []string{"label_2_val"}, + }, + }, + }, + }, + labels: map[string]string{ + "label_1": "label_1_val-failed", + "label_2": "label_2_val", + }, + }, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := MatchTopologySelectorTerms(tt.args.topologySelectorTerms, tt.args.labels); got != tt.want { + t.Errorf("MatchTopologySelectorTermsORed() = %v, want %v", got, tt.want) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/qos/qos_test.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/qos/qos_test.go index 0685d4e65..7e9b71fef 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/qos/qos_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/qos/qos_test.go @@ -38,12 +38,6 @@ func TestGetPodQOS(t *testing.T) { }), expected: v1.PodQOSGuaranteed, }, - { - pod: newPod("guaranteed-with-gpu", []v1.Container{ - newContainer("guaranteed", getResourceList("100m", "100Mi"), addResource("nvidia-gpu", "2", getResourceList("100m", "100Mi"))), - }), - expected: v1.PodQOSGuaranteed, - }, { pod: newPod("guaranteed-guaranteed", []v1.Container{ newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")), @@ -51,13 +45,6 @@ func TestGetPodQOS(t *testing.T) { }), expected: v1.PodQOSGuaranteed, }, - { - pod: newPod("guaranteed-guaranteed-with-gpu", []v1.Container{ - newContainer("guaranteed", getResourceList("100m", "100Mi"), addResource("nvidia-gpu", "2", getResourceList("100m", "100Mi"))), - newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")), - }), - expected: v1.PodQOSGuaranteed, - }, { pod: newPod("best-effort-best-effort", []v1.Container{ newContainer("best-effort", getResourceList("", ""), getResourceList("", "")), @@ -66,28 +53,21 @@ func TestGetPodQOS(t *testing.T) { expected: v1.PodQOSBestEffort, }, { - pod: newPod("best-effort-best-effort-with-gpu", []v1.Container{ - newContainer("best-effort", getResourceList("", ""), addResource("nvidia-gpu", "2", getResourceList("", ""))), + pod: newPod("best-effort", []v1.Container{ newContainer("best-effort", getResourceList("", ""), getResourceList("", "")), }), expected: v1.PodQOSBestEffort, }, - { - pod: newPod("best-effort-with-gpu", []v1.Container{ - newContainer("best-effort", getResourceList("", ""), addResource("nvidia-gpu", "2", getResourceList("", ""))), - }), - expected: v1.PodQOSBestEffort, - }, { pod: newPod("best-effort-burstable", []v1.Container{ - newContainer("best-effort", getResourceList("", ""), addResource("nvidia-gpu", "2", getResourceList("", ""))), + newContainer("best-effort", getResourceList("", ""), getResourceList("", "")), newContainer("burstable", getResourceList("1", ""), getResourceList("2", "")), }), expected: v1.PodQOSBurstable, }, { pod: newPod("best-effort-guaranteed", []v1.Container{ - newContainer("best-effort", getResourceList("", ""), addResource("nvidia-gpu", "2", getResourceList("", ""))), + newContainer("best-effort", getResourceList("", ""), getResourceList("", "")), newContainer("guaranteed", getResourceList("10m", "100Mi"), getResourceList("10m", "100Mi")), }), expected: v1.PodQOSBurstable, @@ -126,7 +106,7 @@ func TestGetPodQOS(t *testing.T) { }, { pod: newPod("burstable-2", []v1.Container{ - newContainer("burstable", getResourceList("0", "0"), addResource("nvidia-gpu", "2", getResourceList("100m", "200Mi"))), + newContainer("burstable", getResourceList("0", "0"), getResourceList("100m", "200Mi")), }), expected: v1.PodQOSBurstable, }, diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/BUILD index 2bc429732..ed794151c 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/BUILD @@ -23,6 +23,8 @@ go_test( deps = [ "//vendor/k8s.io/api/core/v1: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/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/validation.go index cba05040c..023622332 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/validation.go @@ -61,8 +61,6 @@ func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath } else if quantity.Cmp(limitQuantity) > 0 { allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be less than or equal to %s limit", resourceName))) } - } else if resourceName == v1.ResourceNvidiaGPU { - allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s request", v1.ResourceNvidiaGPU))) } } @@ -75,7 +73,7 @@ func validateContainerResourceName(value string, fldPath *field.Path) field.Erro if !helper.IsStandardContainerResourceName(value) { return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers")) } - } else if !v1helper.IsDefaultNamespaceResource(v1.ResourceName(value)) { + } else if !v1helper.IsNativeResource(v1.ResourceName(value)) { if !v1helper.IsExtendedResourceName(v1.ResourceName(value)) { return append(allErrs, field.Invalid(fldPath, value, "doesn't follow extended resource name standard")) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/validation_test.go index 2a33d7ebd..5ff038f3c 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/validation/validation_test.go @@ -21,6 +21,8 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" ) @@ -30,36 +32,15 @@ func TestValidateResourceRequirements(t *testing.T) { requirements v1.ResourceRequirements }{ { - Name: "GPU only setting Limits", + Name: "Resources with Requests equal to Limits", requirements: v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"), - }, - }, - }, - { - Name: "GPU setting Limits equals Requests", - requirements: v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"), - }, Requests: v1.ResourceList{ - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"), - }, - }, - }, - { - Name: "Resources with GPU with Requests", - requirements: v1.ResourceRequirements{ - Requests: v1.ResourceList{ - v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"), - v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"), - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("1"), + v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"), + v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"), }, Limits: v1.ResourceList{ - v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"), - v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"), - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("1"), + v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"), + v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"), }, }, }, @@ -109,36 +90,6 @@ func TestValidateResourceRequirements(t *testing.T) { Name string requirements v1.ResourceRequirements }{ - { - Name: "GPU only setting Requests", - requirements: v1.ResourceRequirements{ - Requests: v1.ResourceList{ - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"), - }, - }, - }, - { - Name: "GPU setting Limits less than Requests", - requirements: v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"), - }, - Requests: v1.ResourceList{ - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("11"), - }, - }, - }, - { - Name: "GPU setting Limits larger than Requests", - requirements: v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"), - }, - Requests: v1.ResourceList{ - v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("9"), - }, - }, - }, { Name: "Resources with Requests Larger Than Limits", requirements: v1.ResourceRequirements{ @@ -177,3 +128,226 @@ func TestValidateResourceRequirements(t *testing.T) { } } } + +func TestValidatePodLogOptions(t *testing.T) { + + var ( + positiveLine = int64(8) + negativeLine = int64(-8) + limitBytesGreaterThan1 = int64(12) + limitBytesLessThan1 = int64(0) + sinceSecondsGreaterThan1 = int64(10) + sinceSecondsLessThan1 = int64(0) + timestamp = metav1.Now() + ) + + successCase := []struct { + Name string + podLogOptions v1.PodLogOptions + }{ + { + Name: "Empty PodLogOptions", + podLogOptions: v1.PodLogOptions{}, + }, + { + Name: "PodLogOptions with TailLines", + podLogOptions: v1.PodLogOptions{ + TailLines: &positiveLine, + }, + }, + { + Name: "PodLogOptions with LimitBytes", + podLogOptions: v1.PodLogOptions{ + LimitBytes: &limitBytesGreaterThan1, + }, + }, + { + Name: "PodLogOptions with only sinceSeconds", + podLogOptions: v1.PodLogOptions{ + SinceSeconds: &sinceSecondsGreaterThan1, + }, + }, + { + Name: "PodLogOptions with LimitBytes with TailLines", + podLogOptions: v1.PodLogOptions{ + LimitBytes: &limitBytesGreaterThan1, + TailLines: &positiveLine, + }, + }, + { + Name: "PodLogOptions with LimitBytes with TailLines with SinceSeconds", + podLogOptions: v1.PodLogOptions{ + LimitBytes: &limitBytesGreaterThan1, + TailLines: &positiveLine, + SinceSeconds: &sinceSecondsGreaterThan1, + }, + }, + } + for _, tc := range successCase { + if errs := ValidatePodLogOptions(&tc.podLogOptions); len(errs) != 0 { + t.Errorf("%q unexpected error: %v", tc.Name, errs) + } + } + + errorCase := []struct { + Name string + podLogOptions v1.PodLogOptions + }{ + { + Name: "Invalid podLogOptions with Negative TailLines", + podLogOptions: v1.PodLogOptions{ + TailLines: &negativeLine, + LimitBytes: &limitBytesGreaterThan1, + SinceSeconds: &sinceSecondsGreaterThan1, + }, + }, + { + Name: "Invalid podLogOptions with zero or negative LimitBytes", + podLogOptions: v1.PodLogOptions{ + TailLines: &positiveLine, + LimitBytes: &limitBytesLessThan1, + SinceSeconds: &sinceSecondsGreaterThan1, + }, + }, + { + Name: "Invalid podLogOptions with zero or negative SinceSeconds", + podLogOptions: v1.PodLogOptions{ + TailLines: &negativeLine, + LimitBytes: &limitBytesGreaterThan1, + SinceSeconds: &sinceSecondsLessThan1, + }, + }, { + Name: "Invalid podLogOptions with both SinceSeconds and SinceTime set", + podLogOptions: v1.PodLogOptions{ + TailLines: &negativeLine, + LimitBytes: &limitBytesGreaterThan1, + SinceSeconds: &sinceSecondsGreaterThan1, + SinceTime: ×tamp, + }, + }, + } + for _, tc := range errorCase { + if errs := ValidatePodLogOptions(&tc.podLogOptions); len(errs) == 0 { + t.Errorf("%q expected error", tc.Name) + } + } +} + +func TestAccumulateUniqueHostPorts(t *testing.T) { + successCase := []struct { + containers []v1.Container + accumulator *sets.String + fldPath *field.Path + result string + }{ + { + containers: []v1.Container{ + { + Ports: []v1.ContainerPort{ + { + HostPort: 8080, + Protocol: v1.ProtocolUDP, + }, + }, + }, + { + Ports: []v1.ContainerPort{ + { + HostPort: 8080, + Protocol: v1.ProtocolTCP, + }, + }, + }, + }, + accumulator: &sets.String{}, + fldPath: field.NewPath("spec", "containers"), + result: "HostPort is not allocated", + }, + { + containers: []v1.Container{ + { + Ports: []v1.ContainerPort{ + { + HostPort: 8080, + Protocol: v1.ProtocolUDP, + }, + }, + }, + { + Ports: []v1.ContainerPort{ + { + HostPort: 8081, + Protocol: v1.ProtocolUDP, + }, + }, + }, + }, + accumulator: &sets.String{}, + fldPath: field.NewPath("spec", "containers"), + result: "HostPort is not allocated", + }, + } + for index, tc := range successCase { + if errs := AccumulateUniqueHostPorts(tc.containers, tc.accumulator, tc.fldPath); len(errs) != 0 { + t.Errorf("unexpected error for test case %v: %v", index, errs) + } + } + errorCase := []struct { + containers []v1.Container + accumulator *sets.String + fldPath *field.Path + result string + }{ + { + containers: []v1.Container{ + { + Ports: []v1.ContainerPort{ + { + HostPort: 8080, + Protocol: v1.ProtocolUDP, + }, + }, + }, + { + Ports: []v1.ContainerPort{ + { + HostPort: 8080, + Protocol: v1.ProtocolUDP, + }, + }, + }, + }, + accumulator: &sets.String{}, + fldPath: field.NewPath("spec", "containers"), + result: "HostPort is already allocated", + }, + { + containers: []v1.Container{ + { + Ports: []v1.ContainerPort{ + { + HostPort: 8080, + Protocol: v1.ProtocolUDP, + }, + }, + }, + { + Ports: []v1.ContainerPort{ + { + HostPort: 8081, + Protocol: v1.ProtocolUDP, + }, + }, + }, + }, + accumulator: &sets.String{"8080/UDP": sets.Empty{}}, + fldPath: field.NewPath("spec", "containers"), + result: "HostPort is already allocated", + }, + } + for index, tc := range errorCase { + if errs := AccumulateUniqueHostPorts(tc.containers, tc.accumulator, tc.fldPath); len(errs) == 0 { + t.Errorf("test case %v: expected error %v, but get nil", index, tc.result) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go index cd8ae5299..6ef20a5f7 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -64,6 +64,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource, Convert_v1_CephFSVolumeSource_To_core_CephFSVolumeSource, Convert_core_CephFSVolumeSource_To_v1_CephFSVolumeSource, + Convert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource, + Convert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource, Convert_v1_CinderVolumeSource_To_core_CinderVolumeSource, Convert_core_CinderVolumeSource_To_v1_CinderVolumeSource, Convert_v1_ClientIPConfig_To_core_ClientIPConfig, @@ -82,6 +84,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_ConfigMapKeySelector_To_v1_ConfigMapKeySelector, Convert_v1_ConfigMapList_To_core_ConfigMapList, Convert_core_ConfigMapList_To_v1_ConfigMapList, + Convert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource, + Convert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource, Convert_v1_ConfigMapProjection_To_core_ConfigMapProjection, Convert_core_ConfigMapProjection_To_v1_ConfigMapProjection, Convert_v1_ConfigMapVolumeSource_To_core_ConfigMapVolumeSource, @@ -104,8 +108,6 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_ContainerStatus_To_v1_ContainerStatus, Convert_v1_DaemonEndpoint_To_core_DaemonEndpoint, Convert_core_DaemonEndpoint_To_v1_DaemonEndpoint, - Convert_v1_DeleteOptions_To_core_DeleteOptions, - Convert_core_DeleteOptions_To_v1_DeleteOptions, Convert_v1_DownwardAPIProjection_To_core_DownwardAPIProjection, Convert_core_DownwardAPIProjection_To_v1_DownwardAPIProjection, Convert_v1_DownwardAPIVolumeFile_To_core_DownwardAPIVolumeFile, @@ -182,8 +184,6 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_LimitRangeSpec_To_v1_LimitRangeSpec, Convert_v1_List_To_core_List, Convert_core_List_To_v1_List, - Convert_v1_ListOptions_To_core_ListOptions, - Convert_core_ListOptions_To_v1_ListOptions, Convert_v1_LoadBalancerIngress_To_core_LoadBalancerIngress, Convert_core_LoadBalancerIngress_To_v1_LoadBalancerIngress, Convert_v1_LoadBalancerStatus_To_core_LoadBalancerStatus, @@ -212,6 +212,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_NodeCondition_To_v1_NodeCondition, Convert_v1_NodeConfigSource_To_core_NodeConfigSource, Convert_core_NodeConfigSource_To_v1_NodeConfigSource, + Convert_v1_NodeConfigStatus_To_core_NodeConfigStatus, + Convert_core_NodeConfigStatus_To_v1_NodeConfigStatus, Convert_v1_NodeDaemonEndpoints_To_core_NodeDaemonEndpoints, Convert_core_NodeDaemonEndpoints_To_v1_NodeDaemonEndpoints, Convert_v1_NodeList_To_core_NodeList, @@ -234,8 +236,6 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_NodeSystemInfo_To_v1_NodeSystemInfo, Convert_v1_ObjectFieldSelector_To_core_ObjectFieldSelector, Convert_core_ObjectFieldSelector_To_v1_ObjectFieldSelector, - Convert_v1_ObjectMeta_To_core_ObjectMeta, - Convert_core_ObjectMeta_To_v1_ObjectMeta, Convert_v1_ObjectReference_To_core_ObjectReference, Convert_core_ObjectReference_To_v1_ObjectReference, Convert_v1_PersistentVolume_To_core_PersistentVolume, @@ -288,6 +288,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_PodPortForwardOptions_To_v1_PodPortForwardOptions, Convert_v1_PodProxyOptions_To_core_PodProxyOptions, Convert_core_PodProxyOptions_To_v1_PodProxyOptions, + Convert_v1_PodReadinessGate_To_core_PodReadinessGate, + Convert_core_PodReadinessGate_To_v1_PodReadinessGate, Convert_v1_PodSecurityContext_To_core_PodSecurityContext, Convert_core_PodSecurityContext_To_v1_PodSecurityContext, Convert_v1_PodSignature_To_core_PodSignature, @@ -352,6 +354,10 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_ScaleIOPersistentVolumeSource_To_v1_ScaleIOPersistentVolumeSource, Convert_v1_ScaleIOVolumeSource_To_core_ScaleIOVolumeSource, Convert_core_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource, + Convert_v1_ScopeSelector_To_core_ScopeSelector, + Convert_core_ScopeSelector_To_v1_ScopeSelector, + Convert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement, + Convert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement, Convert_v1_Secret_To_core_Secret, Convert_core_Secret_To_v1_Secret, Convert_v1_SecretEnvSource_To_core_SecretEnvSource, @@ -376,6 +382,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_ServiceAccount_To_v1_ServiceAccount, Convert_v1_ServiceAccountList_To_core_ServiceAccountList, Convert_core_ServiceAccountList_To_v1_ServiceAccountList, + Convert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection, + Convert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection, Convert_v1_ServiceList_To_core_ServiceList, Convert_core_ServiceList_To_v1_ServiceList, Convert_v1_ServicePort_To_core_ServicePort, @@ -400,6 +408,10 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_core_Taint_To_v1_Taint, Convert_v1_Toleration_To_core_Toleration, Convert_core_Toleration_To_v1_Toleration, + Convert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement, + Convert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement, + Convert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm, + Convert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm, Convert_v1_Volume_To_core_Volume, Convert_core_Volume_To_v1_Volume, Convert_v1_VolumeDevice_To_core_VolumeDevice, @@ -733,10 +745,37 @@ func Convert_core_CephFSVolumeSource_To_v1_CephFSVolumeSource(in *core.CephFSVol return autoConvert_core_CephFSVolumeSource_To_v1_CephFSVolumeSource(in, out, s) } +func autoConvert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource(in *v1.CinderPersistentVolumeSource, out *core.CinderPersistentVolumeSource, s conversion.Scope) error { + out.VolumeID = in.VolumeID + out.FSType = in.FSType + out.ReadOnly = in.ReadOnly + out.SecretRef = (*core.SecretReference)(unsafe.Pointer(in.SecretRef)) + return nil +} + +// Convert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource is an autogenerated conversion function. +func Convert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource(in *v1.CinderPersistentVolumeSource, out *core.CinderPersistentVolumeSource, s conversion.Scope) error { + return autoConvert_v1_CinderPersistentVolumeSource_To_core_CinderPersistentVolumeSource(in, out, s) +} + +func autoConvert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource(in *core.CinderPersistentVolumeSource, out *v1.CinderPersistentVolumeSource, s conversion.Scope) error { + out.VolumeID = in.VolumeID + out.FSType = in.FSType + out.ReadOnly = in.ReadOnly + out.SecretRef = (*v1.SecretReference)(unsafe.Pointer(in.SecretRef)) + return nil +} + +// Convert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource is an autogenerated conversion function. +func Convert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource(in *core.CinderPersistentVolumeSource, out *v1.CinderPersistentVolumeSource, s conversion.Scope) error { + return autoConvert_core_CinderPersistentVolumeSource_To_v1_CinderPersistentVolumeSource(in, out, s) +} + func autoConvert_v1_CinderVolumeSource_To_core_CinderVolumeSource(in *v1.CinderVolumeSource, out *core.CinderVolumeSource, s conversion.Scope) error { out.VolumeID = in.VolumeID out.FSType = in.FSType out.ReadOnly = in.ReadOnly + out.SecretRef = (*core.LocalObjectReference)(unsafe.Pointer(in.SecretRef)) return nil } @@ -749,6 +788,7 @@ func autoConvert_core_CinderVolumeSource_To_v1_CinderVolumeSource(in *core.Cinde out.VolumeID = in.VolumeID out.FSType = in.FSType out.ReadOnly = in.ReadOnly + out.SecretRef = (*v1.LocalObjectReference)(unsafe.Pointer(in.SecretRef)) return nil } @@ -947,6 +987,34 @@ func Convert_core_ConfigMapList_To_v1_ConfigMapList(in *core.ConfigMapList, out return autoConvert_core_ConfigMapList_To_v1_ConfigMapList(in, out, s) } +func autoConvert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource(in *v1.ConfigMapNodeConfigSource, out *core.ConfigMapNodeConfigSource, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + out.UID = types.UID(in.UID) + out.ResourceVersion = in.ResourceVersion + out.KubeletConfigKey = in.KubeletConfigKey + return nil +} + +// Convert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource is an autogenerated conversion function. +func Convert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource(in *v1.ConfigMapNodeConfigSource, out *core.ConfigMapNodeConfigSource, s conversion.Scope) error { + return autoConvert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource(in, out, s) +} + +func autoConvert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource(in *core.ConfigMapNodeConfigSource, out *v1.ConfigMapNodeConfigSource, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + out.UID = types.UID(in.UID) + out.ResourceVersion = in.ResourceVersion + out.KubeletConfigKey = in.KubeletConfigKey + return nil +} + +// Convert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource is an autogenerated conversion function. +func Convert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource(in *core.ConfigMapNodeConfigSource, out *v1.ConfigMapNodeConfigSource, s conversion.Scope) error { + return autoConvert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource(in, out, s) +} + func autoConvert_v1_ConfigMapProjection_To_core_ConfigMapProjection(in *v1.ConfigMapProjection, out *core.ConfigMapProjection, s conversion.Scope) error { if err := Convert_v1_LocalObjectReference_To_core_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil { return err @@ -1295,32 +1363,6 @@ func Convert_core_DaemonEndpoint_To_v1_DaemonEndpoint(in *core.DaemonEndpoint, o return autoConvert_core_DaemonEndpoint_To_v1_DaemonEndpoint(in, out, s) } -func autoConvert_v1_DeleteOptions_To_core_DeleteOptions(in *v1.DeleteOptions, out *core.DeleteOptions, s conversion.Scope) error { - out.GracePeriodSeconds = (*int64)(unsafe.Pointer(in.GracePeriodSeconds)) - out.Preconditions = (*core.Preconditions)(unsafe.Pointer(in.Preconditions)) - out.OrphanDependents = (*bool)(unsafe.Pointer(in.OrphanDependents)) - out.PropagationPolicy = (*core.DeletionPropagation)(unsafe.Pointer(in.PropagationPolicy)) - return nil -} - -// Convert_v1_DeleteOptions_To_core_DeleteOptions is an autogenerated conversion function. -func Convert_v1_DeleteOptions_To_core_DeleteOptions(in *v1.DeleteOptions, out *core.DeleteOptions, s conversion.Scope) error { - return autoConvert_v1_DeleteOptions_To_core_DeleteOptions(in, out, s) -} - -func autoConvert_core_DeleteOptions_To_v1_DeleteOptions(in *core.DeleteOptions, out *v1.DeleteOptions, s conversion.Scope) error { - out.GracePeriodSeconds = (*int64)(unsafe.Pointer(in.GracePeriodSeconds)) - out.Preconditions = (*v1.Preconditions)(unsafe.Pointer(in.Preconditions)) - out.OrphanDependents = (*bool)(unsafe.Pointer(in.OrphanDependents)) - out.PropagationPolicy = (*v1.DeletionPropagation)(unsafe.Pointer(in.PropagationPolicy)) - return nil -} - -// Convert_core_DeleteOptions_To_v1_DeleteOptions is an autogenerated conversion function. -func Convert_core_DeleteOptions_To_v1_DeleteOptions(in *core.DeleteOptions, out *v1.DeleteOptions, s conversion.Scope) error { - return autoConvert_core_DeleteOptions_To_v1_DeleteOptions(in, out, s) -} - func autoConvert_v1_DownwardAPIProjection_To_core_DownwardAPIProjection(in *v1.DownwardAPIProjection, out *core.DownwardAPIProjection, s conversion.Scope) error { out.Items = *(*[]core.DownwardAPIVolumeFile)(unsafe.Pointer(&in.Items)) return nil @@ -2311,44 +2353,6 @@ func Convert_core_List_To_v1_List(in *core.List, out *v1.List, s conversion.Scop return autoConvert_core_List_To_v1_List(in, out, s) } -func autoConvert_v1_ListOptions_To_core_ListOptions(in *v1.ListOptions, out *core.ListOptions, s conversion.Scope) error { - if err := meta_v1.Convert_string_To_labels_Selector(&in.LabelSelector, &out.LabelSelector, s); err != nil { - return err - } - if err := meta_v1.Convert_string_To_fields_Selector(&in.FieldSelector, &out.FieldSelector, s); err != nil { - return err - } - out.IncludeUninitialized = in.IncludeUninitialized - out.Watch = in.Watch - out.ResourceVersion = in.ResourceVersion - out.TimeoutSeconds = (*int64)(unsafe.Pointer(in.TimeoutSeconds)) - return nil -} - -// Convert_v1_ListOptions_To_core_ListOptions is an autogenerated conversion function. -func Convert_v1_ListOptions_To_core_ListOptions(in *v1.ListOptions, out *core.ListOptions, s conversion.Scope) error { - return autoConvert_v1_ListOptions_To_core_ListOptions(in, out, s) -} - -func autoConvert_core_ListOptions_To_v1_ListOptions(in *core.ListOptions, out *v1.ListOptions, s conversion.Scope) error { - if err := meta_v1.Convert_labels_Selector_To_string(&in.LabelSelector, &out.LabelSelector, s); err != nil { - return err - } - if err := meta_v1.Convert_fields_Selector_To_string(&in.FieldSelector, &out.FieldSelector, s); err != nil { - return err - } - out.IncludeUninitialized = in.IncludeUninitialized - out.Watch = in.Watch - out.ResourceVersion = in.ResourceVersion - out.TimeoutSeconds = (*int64)(unsafe.Pointer(in.TimeoutSeconds)) - return nil -} - -// Convert_core_ListOptions_To_v1_ListOptions is an autogenerated conversion function. -func Convert_core_ListOptions_To_v1_ListOptions(in *core.ListOptions, out *v1.ListOptions, s conversion.Scope) error { - return autoConvert_core_ListOptions_To_v1_ListOptions(in, out, s) -} - func autoConvert_v1_LoadBalancerIngress_To_core_LoadBalancerIngress(in *v1.LoadBalancerIngress, out *core.LoadBalancerIngress, s conversion.Scope) error { out.IP = in.IP out.Hostname = in.Hostname @@ -2656,7 +2660,7 @@ func Convert_core_NodeCondition_To_v1_NodeCondition(in *core.NodeCondition, out } func autoConvert_v1_NodeConfigSource_To_core_NodeConfigSource(in *v1.NodeConfigSource, out *core.NodeConfigSource, s conversion.Scope) error { - out.ConfigMapRef = (*core.ObjectReference)(unsafe.Pointer(in.ConfigMapRef)) + out.ConfigMap = (*core.ConfigMapNodeConfigSource)(unsafe.Pointer(in.ConfigMap)) return nil } @@ -2666,7 +2670,7 @@ func Convert_v1_NodeConfigSource_To_core_NodeConfigSource(in *v1.NodeConfigSourc } func autoConvert_core_NodeConfigSource_To_v1_NodeConfigSource(in *core.NodeConfigSource, out *v1.NodeConfigSource, s conversion.Scope) error { - out.ConfigMapRef = (*v1.ObjectReference)(unsafe.Pointer(in.ConfigMapRef)) + out.ConfigMap = (*v1.ConfigMapNodeConfigSource)(unsafe.Pointer(in.ConfigMap)) return nil } @@ -2675,6 +2679,32 @@ func Convert_core_NodeConfigSource_To_v1_NodeConfigSource(in *core.NodeConfigSou return autoConvert_core_NodeConfigSource_To_v1_NodeConfigSource(in, out, s) } +func autoConvert_v1_NodeConfigStatus_To_core_NodeConfigStatus(in *v1.NodeConfigStatus, out *core.NodeConfigStatus, s conversion.Scope) error { + out.Assigned = (*core.NodeConfigSource)(unsafe.Pointer(in.Assigned)) + out.Active = (*core.NodeConfigSource)(unsafe.Pointer(in.Active)) + out.LastKnownGood = (*core.NodeConfigSource)(unsafe.Pointer(in.LastKnownGood)) + out.Error = in.Error + return nil +} + +// Convert_v1_NodeConfigStatus_To_core_NodeConfigStatus is an autogenerated conversion function. +func Convert_v1_NodeConfigStatus_To_core_NodeConfigStatus(in *v1.NodeConfigStatus, out *core.NodeConfigStatus, s conversion.Scope) error { + return autoConvert_v1_NodeConfigStatus_To_core_NodeConfigStatus(in, out, s) +} + +func autoConvert_core_NodeConfigStatus_To_v1_NodeConfigStatus(in *core.NodeConfigStatus, out *v1.NodeConfigStatus, s conversion.Scope) error { + out.Assigned = (*v1.NodeConfigSource)(unsafe.Pointer(in.Assigned)) + out.Active = (*v1.NodeConfigSource)(unsafe.Pointer(in.Active)) + out.LastKnownGood = (*v1.NodeConfigSource)(unsafe.Pointer(in.LastKnownGood)) + out.Error = in.Error + return nil +} + +// Convert_core_NodeConfigStatus_To_v1_NodeConfigStatus is an autogenerated conversion function. +func Convert_core_NodeConfigStatus_To_v1_NodeConfigStatus(in *core.NodeConfigStatus, out *v1.NodeConfigStatus, s conversion.Scope) error { + return autoConvert_core_NodeConfigStatus_To_v1_NodeConfigStatus(in, out, s) +} + func autoConvert_v1_NodeDaemonEndpoints_To_core_NodeDaemonEndpoints(in *v1.NodeDaemonEndpoints, out *core.NodeDaemonEndpoints, s conversion.Scope) error { if err := Convert_v1_DaemonEndpoint_To_core_DaemonEndpoint(&in.KubeletEndpoint, &out.KubeletEndpoint, s); err != nil { return err @@ -2807,6 +2837,7 @@ func Convert_core_NodeSelectorRequirement_To_v1_NodeSelectorRequirement(in *core func autoConvert_v1_NodeSelectorTerm_To_core_NodeSelectorTerm(in *v1.NodeSelectorTerm, out *core.NodeSelectorTerm, s conversion.Scope) error { out.MatchExpressions = *(*[]core.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions)) + out.MatchFields = *(*[]core.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchFields)) return nil } @@ -2817,6 +2848,7 @@ func Convert_v1_NodeSelectorTerm_To_core_NodeSelectorTerm(in *v1.NodeSelectorTer func autoConvert_core_NodeSelectorTerm_To_v1_NodeSelectorTerm(in *core.NodeSelectorTerm, out *v1.NodeSelectorTerm, s conversion.Scope) error { out.MatchExpressions = *(*[]v1.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions)) + out.MatchFields = *(*[]v1.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchFields)) return nil } @@ -2827,11 +2859,11 @@ func Convert_core_NodeSelectorTerm_To_v1_NodeSelectorTerm(in *core.NodeSelectorT func autoConvert_v1_NodeSpec_To_core_NodeSpec(in *v1.NodeSpec, out *core.NodeSpec, s conversion.Scope) error { out.PodCIDR = in.PodCIDR - out.ExternalID = in.ExternalID out.ProviderID = in.ProviderID out.Unschedulable = in.Unschedulable out.Taints = *(*[]core.Taint)(unsafe.Pointer(&in.Taints)) out.ConfigSource = (*core.NodeConfigSource)(unsafe.Pointer(in.ConfigSource)) + out.DoNotUse_ExternalID = in.DoNotUse_ExternalID return nil } @@ -2842,11 +2874,11 @@ func Convert_v1_NodeSpec_To_core_NodeSpec(in *v1.NodeSpec, out *core.NodeSpec, s func autoConvert_core_NodeSpec_To_v1_NodeSpec(in *core.NodeSpec, out *v1.NodeSpec, s conversion.Scope) error { out.PodCIDR = in.PodCIDR - out.ExternalID = in.ExternalID out.ProviderID = in.ProviderID out.Unschedulable = in.Unschedulable out.Taints = *(*[]v1.Taint)(unsafe.Pointer(&in.Taints)) out.ConfigSource = (*v1.NodeConfigSource)(unsafe.Pointer(in.ConfigSource)) + out.DoNotUse_ExternalID = in.DoNotUse_ExternalID return nil } @@ -2870,6 +2902,7 @@ func autoConvert_v1_NodeStatus_To_core_NodeStatus(in *v1.NodeStatus, out *core.N out.Images = *(*[]core.ContainerImage)(unsafe.Pointer(&in.Images)) out.VolumesInUse = *(*[]core.UniqueVolumeName)(unsafe.Pointer(&in.VolumesInUse)) out.VolumesAttached = *(*[]core.AttachedVolume)(unsafe.Pointer(&in.VolumesAttached)) + out.Config = (*core.NodeConfigStatus)(unsafe.Pointer(in.Config)) return nil } @@ -2893,6 +2926,7 @@ func autoConvert_core_NodeStatus_To_v1_NodeStatus(in *core.NodeStatus, out *v1.N out.Images = *(*[]v1.ContainerImage)(unsafe.Pointer(&in.Images)) out.VolumesInUse = *(*[]v1.UniqueVolumeName)(unsafe.Pointer(&in.VolumesInUse)) out.VolumesAttached = *(*[]v1.AttachedVolume)(unsafe.Pointer(&in.VolumesAttached)) + out.Config = (*v1.NodeConfigStatus)(unsafe.Pointer(in.Config)) return nil } @@ -2961,56 +2995,6 @@ func Convert_core_ObjectFieldSelector_To_v1_ObjectFieldSelector(in *core.ObjectF return autoConvert_core_ObjectFieldSelector_To_v1_ObjectFieldSelector(in, out, s) } -func autoConvert_v1_ObjectMeta_To_core_ObjectMeta(in *v1.ObjectMeta, out *core.ObjectMeta, s conversion.Scope) error { - out.Name = in.Name - out.GenerateName = in.GenerateName - out.Namespace = in.Namespace - out.SelfLink = in.SelfLink - out.UID = types.UID(in.UID) - out.ResourceVersion = in.ResourceVersion - out.Generation = in.Generation - out.CreationTimestamp = in.CreationTimestamp - out.DeletionTimestamp = (*meta_v1.Time)(unsafe.Pointer(in.DeletionTimestamp)) - out.DeletionGracePeriodSeconds = (*int64)(unsafe.Pointer(in.DeletionGracePeriodSeconds)) - out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels)) - out.Annotations = *(*map[string]string)(unsafe.Pointer(&in.Annotations)) - out.OwnerReferences = *(*[]meta_v1.OwnerReference)(unsafe.Pointer(&in.OwnerReferences)) - out.Initializers = (*meta_v1.Initializers)(unsafe.Pointer(in.Initializers)) - out.Finalizers = *(*[]string)(unsafe.Pointer(&in.Finalizers)) - out.ClusterName = in.ClusterName - return nil -} - -// Convert_v1_ObjectMeta_To_core_ObjectMeta is an autogenerated conversion function. -func Convert_v1_ObjectMeta_To_core_ObjectMeta(in *v1.ObjectMeta, out *core.ObjectMeta, s conversion.Scope) error { - return autoConvert_v1_ObjectMeta_To_core_ObjectMeta(in, out, s) -} - -func autoConvert_core_ObjectMeta_To_v1_ObjectMeta(in *core.ObjectMeta, out *v1.ObjectMeta, s conversion.Scope) error { - out.Name = in.Name - out.GenerateName = in.GenerateName - out.Namespace = in.Namespace - out.SelfLink = in.SelfLink - out.UID = types.UID(in.UID) - out.ResourceVersion = in.ResourceVersion - out.Generation = in.Generation - out.CreationTimestamp = in.CreationTimestamp - out.DeletionTimestamp = (*meta_v1.Time)(unsafe.Pointer(in.DeletionTimestamp)) - out.DeletionGracePeriodSeconds = (*int64)(unsafe.Pointer(in.DeletionGracePeriodSeconds)) - out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels)) - out.Annotations = *(*map[string]string)(unsafe.Pointer(&in.Annotations)) - out.OwnerReferences = *(*[]meta_v1.OwnerReference)(unsafe.Pointer(&in.OwnerReferences)) - out.Initializers = (*meta_v1.Initializers)(unsafe.Pointer(in.Initializers)) - out.Finalizers = *(*[]string)(unsafe.Pointer(&in.Finalizers)) - out.ClusterName = in.ClusterName - return nil -} - -// Convert_core_ObjectMeta_To_v1_ObjectMeta is an autogenerated conversion function. -func Convert_core_ObjectMeta_To_v1_ObjectMeta(in *core.ObjectMeta, out *v1.ObjectMeta, s conversion.Scope) error { - return autoConvert_core_ObjectMeta_To_v1_ObjectMeta(in, out, s) -} - func autoConvert_v1_ObjectReference_To_core_ObjectReference(in *v1.ObjectReference, out *core.ObjectReference, s conversion.Scope) error { out.Kind = in.Kind out.Namespace = in.Namespace @@ -3291,7 +3275,7 @@ func autoConvert_v1_PersistentVolumeSource_To_core_PersistentVolumeSource(in *v1 out.NFS = (*core.NFSVolumeSource)(unsafe.Pointer(in.NFS)) out.RBD = (*core.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD)) out.ISCSI = (*core.ISCSIPersistentVolumeSource)(unsafe.Pointer(in.ISCSI)) - out.Cinder = (*core.CinderVolumeSource)(unsafe.Pointer(in.Cinder)) + out.Cinder = (*core.CinderPersistentVolumeSource)(unsafe.Pointer(in.Cinder)) out.CephFS = (*core.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS)) out.FC = (*core.FCVolumeSource)(unsafe.Pointer(in.FC)) out.Flocker = (*core.FlockerVolumeSource)(unsafe.Pointer(in.Flocker)) @@ -3324,7 +3308,7 @@ func autoConvert_core_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *co out.Quobyte = (*v1.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte)) out.ISCSI = (*v1.ISCSIPersistentVolumeSource)(unsafe.Pointer(in.ISCSI)) out.FlexVolume = (*v1.FlexPersistentVolumeSource)(unsafe.Pointer(in.FlexVolume)) - out.Cinder = (*v1.CinderVolumeSource)(unsafe.Pointer(in.Cinder)) + out.Cinder = (*v1.CinderPersistentVolumeSource)(unsafe.Pointer(in.Cinder)) out.CephFS = (*v1.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS)) out.FC = (*v1.FCVolumeSource)(unsafe.Pointer(in.FC)) out.Flocker = (*v1.FlockerVolumeSource)(unsafe.Pointer(in.Flocker)) @@ -3771,6 +3755,26 @@ func Convert_core_PodProxyOptions_To_v1_PodProxyOptions(in *core.PodProxyOptions return autoConvert_core_PodProxyOptions_To_v1_PodProxyOptions(in, out, s) } +func autoConvert_v1_PodReadinessGate_To_core_PodReadinessGate(in *v1.PodReadinessGate, out *core.PodReadinessGate, s conversion.Scope) error { + out.ConditionType = core.PodConditionType(in.ConditionType) + return nil +} + +// Convert_v1_PodReadinessGate_To_core_PodReadinessGate is an autogenerated conversion function. +func Convert_v1_PodReadinessGate_To_core_PodReadinessGate(in *v1.PodReadinessGate, out *core.PodReadinessGate, s conversion.Scope) error { + return autoConvert_v1_PodReadinessGate_To_core_PodReadinessGate(in, out, s) +} + +func autoConvert_core_PodReadinessGate_To_v1_PodReadinessGate(in *core.PodReadinessGate, out *v1.PodReadinessGate, s conversion.Scope) error { + out.ConditionType = v1.PodConditionType(in.ConditionType) + return nil +} + +// Convert_core_PodReadinessGate_To_v1_PodReadinessGate is an autogenerated conversion function. +func Convert_core_PodReadinessGate_To_v1_PodReadinessGate(in *core.PodReadinessGate, out *v1.PodReadinessGate, s conversion.Scope) error { + return autoConvert_core_PodReadinessGate_To_v1_PodReadinessGate(in, out, s) +} + func autoConvert_v1_PodSecurityContext_To_core_PodSecurityContext(in *v1.PodSecurityContext, out *core.PodSecurityContext, s conversion.Scope) error { out.SELinuxOptions = (*core.SELinuxOptions)(unsafe.Pointer(in.SELinuxOptions)) out.RunAsUser = (*int64)(unsafe.Pointer(in.RunAsUser)) @@ -3778,6 +3782,7 @@ func autoConvert_v1_PodSecurityContext_To_core_PodSecurityContext(in *v1.PodSecu out.RunAsNonRoot = (*bool)(unsafe.Pointer(in.RunAsNonRoot)) out.SupplementalGroups = *(*[]int64)(unsafe.Pointer(&in.SupplementalGroups)) out.FSGroup = (*int64)(unsafe.Pointer(in.FSGroup)) + out.Sysctls = *(*[]core.Sysctl)(unsafe.Pointer(&in.Sysctls)) return nil } @@ -3792,6 +3797,7 @@ func autoConvert_core_PodSecurityContext_To_v1_PodSecurityContext(in *core.PodSe out.RunAsNonRoot = (*bool)(unsafe.Pointer(in.RunAsNonRoot)) out.SupplementalGroups = *(*[]int64)(unsafe.Pointer(&in.SupplementalGroups)) out.FSGroup = (*int64)(unsafe.Pointer(in.FSGroup)) + out.Sysctls = *(*[]v1.Sysctl)(unsafe.Pointer(&in.Sysctls)) return nil } @@ -3881,6 +3887,7 @@ func autoConvert_v1_PodSpec_To_core_PodSpec(in *v1.PodSpec, out *core.PodSpec, s out.PriorityClassName = in.PriorityClassName out.Priority = (*int32)(unsafe.Pointer(in.Priority)) out.DNSConfig = (*core.PodDNSConfig)(unsafe.Pointer(in.DNSConfig)) + out.ReadinessGates = *(*[]core.PodReadinessGate)(unsafe.Pointer(&in.ReadinessGates)) return nil } @@ -3945,6 +3952,7 @@ func autoConvert_core_PodSpec_To_v1_PodSpec(in *core.PodSpec, out *v1.PodSpec, s out.PriorityClassName = in.PriorityClassName out.Priority = (*int32)(unsafe.Pointer(in.Priority)) out.DNSConfig = (*v1.PodDNSConfig)(unsafe.Pointer(in.DNSConfig)) + out.ReadinessGates = *(*[]v1.PodReadinessGate)(unsafe.Pointer(&in.ReadinessGates)) return nil } @@ -4233,7 +4241,17 @@ func Convert_core_Probe_To_v1_Probe(in *core.Probe, out *v1.Probe, s conversion. } func autoConvert_v1_ProjectedVolumeSource_To_core_ProjectedVolumeSource(in *v1.ProjectedVolumeSource, out *core.ProjectedVolumeSource, s conversion.Scope) error { - out.Sources = *(*[]core.VolumeProjection)(unsafe.Pointer(&in.Sources)) + if in.Sources != nil { + in, out := &in.Sources, &out.Sources + *out = make([]core.VolumeProjection, len(*in)) + for i := range *in { + if err := Convert_v1_VolumeProjection_To_core_VolumeProjection(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Sources = nil + } out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode)) return nil } @@ -4244,7 +4262,17 @@ func Convert_v1_ProjectedVolumeSource_To_core_ProjectedVolumeSource(in *v1.Proje } func autoConvert_core_ProjectedVolumeSource_To_v1_ProjectedVolumeSource(in *core.ProjectedVolumeSource, out *v1.ProjectedVolumeSource, s conversion.Scope) error { - out.Sources = *(*[]v1.VolumeProjection)(unsafe.Pointer(&in.Sources)) + if in.Sources != nil { + in, out := &in.Sources, &out.Sources + *out = make([]v1.VolumeProjection, len(*in)) + for i := range *in { + if err := Convert_core_VolumeProjection_To_v1_VolumeProjection(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Sources = nil + } out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode)) return nil } @@ -4623,6 +4651,7 @@ func Convert_core_ResourceQuotaList_To_v1_ResourceQuotaList(in *core.ResourceQuo func autoConvert_v1_ResourceQuotaSpec_To_core_ResourceQuotaSpec(in *v1.ResourceQuotaSpec, out *core.ResourceQuotaSpec, s conversion.Scope) error { out.Hard = *(*core.ResourceList)(unsafe.Pointer(&in.Hard)) out.Scopes = *(*[]core.ResourceQuotaScope)(unsafe.Pointer(&in.Scopes)) + out.ScopeSelector = (*core.ScopeSelector)(unsafe.Pointer(in.ScopeSelector)) return nil } @@ -4634,6 +4663,7 @@ func Convert_v1_ResourceQuotaSpec_To_core_ResourceQuotaSpec(in *v1.ResourceQuota func autoConvert_core_ResourceQuotaSpec_To_v1_ResourceQuotaSpec(in *core.ResourceQuotaSpec, out *v1.ResourceQuotaSpec, s conversion.Scope) error { out.Hard = *(*v1.ResourceList)(unsafe.Pointer(&in.Hard)) out.Scopes = *(*[]v1.ResourceQuotaScope)(unsafe.Pointer(&in.Scopes)) + out.ScopeSelector = (*v1.ScopeSelector)(unsafe.Pointer(in.ScopeSelector)) return nil } @@ -4788,6 +4818,50 @@ func Convert_core_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in *core.ScaleIO return autoConvert_core_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in, out, s) } +func autoConvert_v1_ScopeSelector_To_core_ScopeSelector(in *v1.ScopeSelector, out *core.ScopeSelector, s conversion.Scope) error { + out.MatchExpressions = *(*[]core.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions)) + return nil +} + +// Convert_v1_ScopeSelector_To_core_ScopeSelector is an autogenerated conversion function. +func Convert_v1_ScopeSelector_To_core_ScopeSelector(in *v1.ScopeSelector, out *core.ScopeSelector, s conversion.Scope) error { + return autoConvert_v1_ScopeSelector_To_core_ScopeSelector(in, out, s) +} + +func autoConvert_core_ScopeSelector_To_v1_ScopeSelector(in *core.ScopeSelector, out *v1.ScopeSelector, s conversion.Scope) error { + out.MatchExpressions = *(*[]v1.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions)) + return nil +} + +// Convert_core_ScopeSelector_To_v1_ScopeSelector is an autogenerated conversion function. +func Convert_core_ScopeSelector_To_v1_ScopeSelector(in *core.ScopeSelector, out *v1.ScopeSelector, s conversion.Scope) error { + return autoConvert_core_ScopeSelector_To_v1_ScopeSelector(in, out, s) +} + +func autoConvert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement(in *v1.ScopedResourceSelectorRequirement, out *core.ScopedResourceSelectorRequirement, s conversion.Scope) error { + out.ScopeName = core.ResourceQuotaScope(in.ScopeName) + out.Operator = core.ScopeSelectorOperator(in.Operator) + out.Values = *(*[]string)(unsafe.Pointer(&in.Values)) + return nil +} + +// Convert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement is an autogenerated conversion function. +func Convert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement(in *v1.ScopedResourceSelectorRequirement, out *core.ScopedResourceSelectorRequirement, s conversion.Scope) error { + return autoConvert_v1_ScopedResourceSelectorRequirement_To_core_ScopedResourceSelectorRequirement(in, out, s) +} + +func autoConvert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement(in *core.ScopedResourceSelectorRequirement, out *v1.ScopedResourceSelectorRequirement, s conversion.Scope) error { + out.ScopeName = v1.ResourceQuotaScope(in.ScopeName) + out.Operator = v1.ScopeSelectorOperator(in.Operator) + out.Values = *(*[]string)(unsafe.Pointer(&in.Values)) + return nil +} + +// Convert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement is an autogenerated conversion function. +func Convert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement(in *core.ScopedResourceSelectorRequirement, out *v1.ScopedResourceSelectorRequirement, s conversion.Scope) error { + return autoConvert_core_ScopedResourceSelectorRequirement_To_v1_ScopedResourceSelectorRequirement(in, out, s) +} + func autoConvert_v1_Secret_To_core_Secret(in *v1.Secret, out *core.Secret, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta out.Data = *(*map[string][]byte)(unsafe.Pointer(&in.Data)) @@ -5113,6 +5187,34 @@ func Convert_core_ServiceAccountList_To_v1_ServiceAccountList(in *core.ServiceAc return autoConvert_core_ServiceAccountList_To_v1_ServiceAccountList(in, out, s) } +func autoConvert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection(in *v1.ServiceAccountTokenProjection, out *core.ServiceAccountTokenProjection, s conversion.Scope) error { + out.Audience = in.Audience + if err := meta_v1.Convert_Pointer_int64_To_int64(&in.ExpirationSeconds, &out.ExpirationSeconds, s); err != nil { + return err + } + out.Path = in.Path + return nil +} + +// Convert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection is an autogenerated conversion function. +func Convert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection(in *v1.ServiceAccountTokenProjection, out *core.ServiceAccountTokenProjection, s conversion.Scope) error { + return autoConvert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection(in, out, s) +} + +func autoConvert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection(in *core.ServiceAccountTokenProjection, out *v1.ServiceAccountTokenProjection, s conversion.Scope) error { + out.Audience = in.Audience + if err := meta_v1.Convert_int64_To_Pointer_int64(&in.ExpirationSeconds, &out.ExpirationSeconds, s); err != nil { + return err + } + out.Path = in.Path + return nil +} + +// Convert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection is an autogenerated conversion function. +func Convert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection(in *core.ServiceAccountTokenProjection, out *v1.ServiceAccountTokenProjection, s conversion.Scope) error { + return autoConvert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection(in, out, s) +} + func autoConvert_v1_ServiceList_To_core_ServiceList(in *v1.ServiceList, out *core.ServiceList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { @@ -5445,6 +5547,48 @@ func Convert_core_Toleration_To_v1_Toleration(in *core.Toleration, out *v1.Toler return autoConvert_core_Toleration_To_v1_Toleration(in, out, s) } +func autoConvert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement(in *v1.TopologySelectorLabelRequirement, out *core.TopologySelectorLabelRequirement, s conversion.Scope) error { + out.Key = in.Key + out.Values = *(*[]string)(unsafe.Pointer(&in.Values)) + return nil +} + +// Convert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement is an autogenerated conversion function. +func Convert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement(in *v1.TopologySelectorLabelRequirement, out *core.TopologySelectorLabelRequirement, s conversion.Scope) error { + return autoConvert_v1_TopologySelectorLabelRequirement_To_core_TopologySelectorLabelRequirement(in, out, s) +} + +func autoConvert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement(in *core.TopologySelectorLabelRequirement, out *v1.TopologySelectorLabelRequirement, s conversion.Scope) error { + out.Key = in.Key + out.Values = *(*[]string)(unsafe.Pointer(&in.Values)) + return nil +} + +// Convert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement is an autogenerated conversion function. +func Convert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement(in *core.TopologySelectorLabelRequirement, out *v1.TopologySelectorLabelRequirement, s conversion.Scope) error { + return autoConvert_core_TopologySelectorLabelRequirement_To_v1_TopologySelectorLabelRequirement(in, out, s) +} + +func autoConvert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm(in *v1.TopologySelectorTerm, out *core.TopologySelectorTerm, s conversion.Scope) error { + out.MatchLabelExpressions = *(*[]core.TopologySelectorLabelRequirement)(unsafe.Pointer(&in.MatchLabelExpressions)) + return nil +} + +// Convert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm is an autogenerated conversion function. +func Convert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm(in *v1.TopologySelectorTerm, out *core.TopologySelectorTerm, s conversion.Scope) error { + return autoConvert_v1_TopologySelectorTerm_To_core_TopologySelectorTerm(in, out, s) +} + +func autoConvert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm(in *core.TopologySelectorTerm, out *v1.TopologySelectorTerm, s conversion.Scope) error { + out.MatchLabelExpressions = *(*[]v1.TopologySelectorLabelRequirement)(unsafe.Pointer(&in.MatchLabelExpressions)) + return nil +} + +// Convert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm is an autogenerated conversion function. +func Convert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm(in *core.TopologySelectorTerm, out *v1.TopologySelectorTerm, s conversion.Scope) error { + return autoConvert_core_TopologySelectorTerm_To_v1_TopologySelectorTerm(in, out, s) +} + func autoConvert_v1_Volume_To_core_Volume(in *v1.Volume, out *core.Volume, s conversion.Scope) error { out.Name = in.Name if err := Convert_v1_VolumeSource_To_core_VolumeSource(&in.VolumeSource, &out.VolumeSource, s); err != nil { @@ -5545,6 +5689,15 @@ func autoConvert_v1_VolumeProjection_To_core_VolumeProjection(in *v1.VolumeProje out.Secret = (*core.SecretProjection)(unsafe.Pointer(in.Secret)) out.DownwardAPI = (*core.DownwardAPIProjection)(unsafe.Pointer(in.DownwardAPI)) out.ConfigMap = (*core.ConfigMapProjection)(unsafe.Pointer(in.ConfigMap)) + if in.ServiceAccountToken != nil { + in, out := &in.ServiceAccountToken, &out.ServiceAccountToken + *out = new(core.ServiceAccountTokenProjection) + if err := Convert_v1_ServiceAccountTokenProjection_To_core_ServiceAccountTokenProjection(*in, *out, s); err != nil { + return err + } + } else { + out.ServiceAccountToken = nil + } return nil } @@ -5557,6 +5710,15 @@ func autoConvert_core_VolumeProjection_To_v1_VolumeProjection(in *core.VolumePro out.Secret = (*v1.SecretProjection)(unsafe.Pointer(in.Secret)) out.DownwardAPI = (*v1.DownwardAPIProjection)(unsafe.Pointer(in.DownwardAPI)) out.ConfigMap = (*v1.ConfigMapProjection)(unsafe.Pointer(in.ConfigMap)) + if in.ServiceAccountToken != nil { + in, out := &in.ServiceAccountToken, &out.ServiceAccountToken + *out = new(v1.ServiceAccountTokenProjection) + if err := Convert_core_ServiceAccountTokenProjection_To_v1_ServiceAccountTokenProjection(*in, *out, s); err != nil { + return err + } + } else { + out.ServiceAccountToken = nil + } return nil } @@ -5589,7 +5751,15 @@ func autoConvert_v1_VolumeSource_To_core_VolumeSource(in *v1.VolumeSource, out * out.Quobyte = (*core.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte)) out.AzureDisk = (*core.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk)) out.PhotonPersistentDisk = (*core.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) - out.Projected = (*core.ProjectedVolumeSource)(unsafe.Pointer(in.Projected)) + if in.Projected != nil { + in, out := &in.Projected, &out.Projected + *out = new(core.ProjectedVolumeSource) + if err := Convert_v1_ProjectedVolumeSource_To_core_ProjectedVolumeSource(*in, *out, s); err != nil { + return err + } + } else { + out.Projected = nil + } out.PortworxVolume = (*core.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.ScaleIO = (*core.ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO)) out.StorageOS = (*core.StorageOSVolumeSource)(unsafe.Pointer(in.StorageOS)) @@ -5625,7 +5795,15 @@ func autoConvert_core_VolumeSource_To_v1_VolumeSource(in *core.VolumeSource, out out.VsphereVolume = (*v1.VsphereVirtualDiskVolumeSource)(unsafe.Pointer(in.VsphereVolume)) out.AzureDisk = (*v1.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk)) out.PhotonPersistentDisk = (*v1.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) - out.Projected = (*v1.ProjectedVolumeSource)(unsafe.Pointer(in.Projected)) + if in.Projected != nil { + in, out := &in.Projected, &out.Projected + *out = new(v1.ProjectedVolumeSource) + if err := Convert_core_ProjectedVolumeSource_To_v1_ProjectedVolumeSource(*in, *out, s); err != nil { + return err + } + } else { + out.Projected = nil + } out.PortworxVolume = (*v1.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.ScaleIO = (*v1.ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO)) out.StorageOS = (*v1.StorageOSVolumeSource)(unsafe.Pointer(in.StorageOS)) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.defaults.go index 084c9516b..00e0b384a 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -115,7 +115,6 @@ func SetObjectDefaults_NamespaceList(in *v1.NamespaceList) { } func SetObjectDefaults_Node(in *v1.Node) { - SetDefaults_Node(in) SetDefaults_NodeStatus(&in.Status) SetDefaults_ResourceList(&in.Status.Capacity) SetDefaults_ResourceList(&in.Status.Allocatable) @@ -214,6 +213,9 @@ func SetObjectDefaults_Pod(in *v1.Pod) { } } } + if b.ServiceAccountToken != nil { + SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -357,6 +359,9 @@ func SetObjectDefaults_PodTemplate(in *v1.PodTemplate) { } } } + if b.ServiceAccountToken != nil { + SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -502,6 +507,9 @@ func SetObjectDefaults_ReplicationController(in *v1.ReplicationController) { } } } + if b.ServiceAccountToken != nil { + SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/BUILD index f2a9c4890..9594b47fe 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/BUILD @@ -14,7 +14,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/apis/core/validation", visibility = ["//visibility:public"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/service:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/helper:go_default_library", @@ -29,13 +28,11 @@ go_library( "//vendor/github.com/golang/glog: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/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema: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/sets:go_default_library", @@ -53,13 +50,12 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", "//pkg/capabilities:go_default_library", "//pkg/features:go_default_library", "//pkg/security/apparmor:go_default_library", + "//pkg/util/pointer:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/events.go b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/events.go index ab265bd76..8a860aba9 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/events.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/events.go @@ -20,12 +20,9 @@ import ( "fmt" "time" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/core" ) @@ -90,40 +87,8 @@ func ValidateEvent(event *core.Event) field.ErrorList { } } - // For kinds we recognize, make sure InvolvedObject.Namespace is set for namespaced kinds - if namespaced, err := isNamespacedKind(event.InvolvedObject.Kind, event.InvolvedObject.APIVersion); err == nil { - if namespaced && len(event.InvolvedObject.Namespace) == 0 { - allErrs = append(allErrs, field.Required(field.NewPath("involvedObject", "namespace"), fmt.Sprintf("required for kind %s", event.InvolvedObject.Kind))) - } - if !namespaced && len(event.InvolvedObject.Namespace) > 0 { - allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, fmt.Sprintf("not allowed for kind %s", event.InvolvedObject.Kind))) - } - } - for _, msg := range validation.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, msg)) } return allErrs } - -// 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) - if err != nil { - return false, err - } - g, err := legacyscheme.Registry.Group(gv.Group) - if err != nil { - return false, err - } - - restMapping, err := g.RESTMapper.RESTMapping(schema.GroupKind{Group: gv.Group, Kind: kind}, gv.Version) - if err != nil { - return false, err - } - scopeName := restMapping.Scope.Name() - if scopeName == meta.RESTScopeNameNamespace { - return true, nil - } - return false, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation.go index 8d12dad07..7050c604e 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation.go @@ -55,10 +55,6 @@ import ( "k8s.io/kubernetes/pkg/security/apparmor" ) -// TODO: delete this global variable when we enable the validation of common -// fields by default. -var RepairMalformedUpdates bool = apimachineryvalidation.RepairMalformedUpdates - const isNegativeErrorMsg string = apimachineryvalidation.IsNegativeErrorMsg const isInvalidQuotaResource string = `must be a standard resource for quota` const fieldImmutableErrorMsg string = apimachineryvalidation.FieldImmutableErrorMsg @@ -133,23 +129,6 @@ func ValidatePodSpecificAnnotations(annotations map[string]string, spec *core.Po allErrs = append(allErrs, ValidateSeccompPodAnnotations(annotations, fldPath)...) allErrs = append(allErrs, ValidateAppArmorPodAnnotations(annotations, spec, fldPath)...) - sysctls, err := helper.SysctlsFromPodAnnotation(annotations[core.SysctlsPodAnnotationKey]) - if err != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Key(core.SysctlsPodAnnotationKey), annotations[core.SysctlsPodAnnotationKey], err.Error())) - } else { - allErrs = append(allErrs, validateSysctls(sysctls, fldPath.Key(core.SysctlsPodAnnotationKey))...) - } - unsafeSysctls, err := helper.SysctlsFromPodAnnotation(annotations[core.UnsafeSysctlsPodAnnotationKey]) - if err != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Key(core.UnsafeSysctlsPodAnnotationKey), annotations[core.UnsafeSysctlsPodAnnotationKey], err.Error())) - } else { - allErrs = append(allErrs, validateSysctls(unsafeSysctls, fldPath.Key(core.UnsafeSysctlsPodAnnotationKey))...) - } - inBoth := sysctlIntersection(sysctls, unsafeSysctls) - if len(inBoth) > 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Key(core.UnsafeSysctlsPodAnnotationKey), strings.Join(inBoth, ", "), "can not be safe and unsafe")) - } - return allErrs } @@ -379,29 +358,25 @@ func ValidateVolumes(volumes []core.Volume, fldPath *field.Path) (map[string]cor func IsMatchedVolume(name string, volumes map[string]core.VolumeSource) bool { if _, ok := volumes[name]; ok { return true - } else { - return false } + return false } func isMatchedDevice(name string, volumes map[string]core.VolumeSource) (bool, bool) { if source, ok := volumes[name]; ok { if source.PersistentVolumeClaim != nil { return true, true - } else { - return true, false } - } else { - return false, false + return true, false } + return false, false } func mountNameAlreadyExists(name string, devices map[string]string) bool { if _, ok := devices[name]; ok { return true - } else { - return false } + return false } func mountPathAlreadyExists(mountPath string, devices map[string]string) bool { @@ -417,9 +392,8 @@ func mountPathAlreadyExists(mountPath string, devices map[string]string) bool { func deviceNameAlreadyExists(name string, mounts map[string]string) bool { if _, ok := mounts[name]; ok { return true - } else { - return false } + return false } func devicePathAlreadyExists(devicePath string, mounts map[string]string) bool { @@ -993,74 +967,79 @@ func validateProjectionSources(projection *core.ProjectedVolumeSource, projectio allErrs := field.ErrorList{} allPaths := sets.String{} - for _, source := range projection.Sources { + for i, source := range projection.Sources { numSources := 0 - if source.Secret != nil { - if numSources > 0 { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("secret"), "may not specify more than 1 volume type")) - } else { - numSources++ - if len(source.Secret.Name) == 0 { - allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) - } - itemsPath := fldPath.Child("items") - for i, kp := range source.Secret.Items { - itemPath := itemsPath.Index(i) - allErrs = append(allErrs, validateKeyToPath(&kp, itemPath)...) - if len(kp.Path) > 0 { - curPath := kp.Path - if !allPaths.Has(curPath) { - allPaths.Insert(curPath) - } else { - allErrs = append(allErrs, field.Invalid(fldPath, source.Secret.Name, "conflicting duplicate paths")) - } + srcPath := fldPath.Child("sources").Index(i) + if projPath := srcPath.Child("secret"); source.Secret != nil { + numSources++ + if len(source.Secret.Name) == 0 { + allErrs = append(allErrs, field.Required(projPath.Child("name"), "")) + } + itemsPath := projPath.Child("items") + for i, kp := range source.Secret.Items { + itemPath := itemsPath.Index(i) + allErrs = append(allErrs, validateKeyToPath(&kp, itemPath)...) + if len(kp.Path) > 0 { + curPath := kp.Path + if !allPaths.Has(curPath) { + allPaths.Insert(curPath) + } else { + allErrs = append(allErrs, field.Invalid(fldPath, source.Secret.Name, "conflicting duplicate paths")) } } } } - if source.ConfigMap != nil { - if numSources > 0 { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("configMap"), "may not specify more than 1 volume type")) - } else { - numSources++ - if len(source.ConfigMap.Name) == 0 { - allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) - } - itemsPath := fldPath.Child("items") - for i, kp := range source.ConfigMap.Items { - itemPath := itemsPath.Index(i) - allErrs = append(allErrs, validateKeyToPath(&kp, itemPath)...) - if len(kp.Path) > 0 { - curPath := kp.Path - if !allPaths.Has(curPath) { - allPaths.Insert(curPath) - } else { - allErrs = append(allErrs, field.Invalid(fldPath, source.ConfigMap.Name, "conflicting duplicate paths")) - } - + if projPath := srcPath.Child("configMap"); source.ConfigMap != nil { + numSources++ + if len(source.ConfigMap.Name) == 0 { + allErrs = append(allErrs, field.Required(projPath.Child("name"), "")) + } + itemsPath := projPath.Child("items") + for i, kp := range source.ConfigMap.Items { + itemPath := itemsPath.Index(i) + allErrs = append(allErrs, validateKeyToPath(&kp, itemPath)...) + if len(kp.Path) > 0 { + curPath := kp.Path + if !allPaths.Has(curPath) { + allPaths.Insert(curPath) + } else { + allErrs = append(allErrs, field.Invalid(fldPath, source.ConfigMap.Name, "conflicting duplicate paths")) } } } } - if source.DownwardAPI != nil { - if numSources > 0 { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("downwardAPI"), "may not specify more than 1 volume type")) - } else { - numSources++ - for _, file := range source.DownwardAPI.Items { - allErrs = append(allErrs, validateDownwardAPIVolumeFile(&file, fldPath.Child("downwardAPI"))...) - if len(file.Path) > 0 { - curPath := file.Path - if !allPaths.Has(curPath) { - allPaths.Insert(curPath) - } else { - allErrs = append(allErrs, field.Invalid(fldPath, curPath, "conflicting duplicate paths")) - } - + if projPath := srcPath.Child("downwardAPI"); source.DownwardAPI != nil { + numSources++ + for _, file := range source.DownwardAPI.Items { + allErrs = append(allErrs, validateDownwardAPIVolumeFile(&file, projPath)...) + if len(file.Path) > 0 { + curPath := file.Path + if !allPaths.Has(curPath) { + allPaths.Insert(curPath) + } else { + allErrs = append(allErrs, field.Invalid(fldPath, curPath, "conflicting duplicate paths")) } } } } + if projPath := fldPath.Child("serviceAccountToken"); source.ServiceAccountToken != nil { + numSources++ + if !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequestProjection) { + allErrs = append(allErrs, field.Forbidden(projPath, "TokenRequestProjection feature is not enabled")) + } + if source.ServiceAccountToken.ExpirationSeconds < 10*60 { + allErrs = append(allErrs, field.Invalid(projPath.Child("expirationSeconds"), source.ServiceAccountToken.ExpirationSeconds, "may not specify a duration less than 10 minutes")) + } + if source.ServiceAccountToken.ExpirationSeconds > 1<<32 { + allErrs = append(allErrs, field.Invalid(projPath.Child("expirationSeconds"), source.ServiceAccountToken.ExpirationSeconds, "may not specify a duration larger than 2^32 seconds")) + } + if source.ServiceAccountToken.Path == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("path"), "")) + } + } + if numSources > 1 { + allErrs = append(allErrs, field.Forbidden(srcPath, "may not specify more than 1 volume type")) + } } return allErrs } @@ -1200,6 +1179,27 @@ func validateCinderVolumeSource(cd *core.CinderVolumeSource, fldPath *field.Path if len(cd.VolumeID) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("volumeID"), "")) } + if cd.SecretRef != nil { + if len(cd.SecretRef.Name) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("secretRef", "name"), "")) + } + } + return allErrs +} + +func validateCinderPersistentVolumeSource(cd *core.CinderPersistentVolumeSource, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if len(cd.VolumeID) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("volumeID"), "")) + } + if cd.SecretRef != nil { + if len(cd.SecretRef.Name) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("secretRef", "name"), "")) + } + if len(cd.SecretRef.Namespace) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("secretRef", "namespace"), "")) + } + } return allErrs } @@ -1533,18 +1533,9 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList { } } - nodeAffinitySpecified, errs := validateStorageNodeAffinityAnnotation(pv.ObjectMeta.Annotations, metaPath.Child("annotations")) + nodeAffinitySpecified, errs := validateVolumeNodeAffinity(pv.Spec.NodeAffinity, specPath.Child("nodeAffinity")) allErrs = append(allErrs, errs...) - volumeNodeAffinitySpecified, errs := validateVolumeNodeAffinity(pv.Spec.NodeAffinity, specPath.Child("nodeAffinity")) - allErrs = append(allErrs, errs...) - - if nodeAffinitySpecified && volumeNodeAffinitySpecified { - allErrs = append(allErrs, field.Forbidden(specPath.Child("nodeAffinity"), "may not specify both alpha nodeAffinity annotation and nodeAffinity field")) - } - - nodeAffinitySpecified = nodeAffinitySpecified || volumeNodeAffinitySpecified - numVolumes := 0 if pv.Spec.HostPath != nil { if numVolumes > 0 { @@ -1635,7 +1626,7 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList { allErrs = append(allErrs, field.Forbidden(specPath.Child("cinder"), "may not specify more than 1 volume type")) } else { numVolumes++ - allErrs = append(allErrs, validateCinderVolumeSource(pv.Spec.Cinder, specPath.Child("cinder"))...) + allErrs = append(allErrs, validateCinderPersistentVolumeSource(pv.Spec.Cinder, specPath.Child("cinder"))...) } } if pv.Spec.FC != nil { @@ -2515,7 +2506,7 @@ func validatePullPolicy(policy core.PullPolicy, fldPath *field.Path) field.Error func validateInitContainers(containers, otherContainers []core.Container, deviceVolumes map[string]core.VolumeSource, fldPath *field.Path) field.ErrorList { var allErrs field.ErrorList if len(containers) > 0 { - allErrs = append(allErrs, validateContainers(containers, deviceVolumes, fldPath)...) + allErrs = append(allErrs, validateContainers(containers, true, deviceVolumes, fldPath)...) } allNames := sets.String{} @@ -2543,7 +2534,7 @@ func validateInitContainers(containers, otherContainers []core.Container, device return allErrs } -func validateContainers(containers []core.Container, volumes map[string]core.VolumeSource, fldPath *field.Path) field.ErrorList { +func validateContainers(containers []core.Container, isInitContainers bool, volumes map[string]core.VolumeSource, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(containers) == 0 { @@ -2600,8 +2591,16 @@ func validateContainers(containers []core.Container, volumes map[string]core.Vol allErrs = append(allErrs, ValidateResourceRequirements(&ctr.Resources, idxPath.Child("resources"))...) allErrs = append(allErrs, ValidateSecurityContext(ctr.SecurityContext, idxPath.Child("securityContext"))...) } - // Check for colliding ports across all containers. - allErrs = append(allErrs, checkHostPortConflicts(containers, fldPath)...) + + if isInitContainers { + // check initContainers one by one since they are running in sequential order. + for _, initContainer := range containers { + allErrs = append(allErrs, checkHostPortConflicts([]core.Container{initContainer}, fldPath)...) + } + } else { + // Check for colliding ports across all containers. + allErrs = append(allErrs, checkHostPortConflicts(containers, fldPath)...) + } return allErrs } @@ -2652,6 +2651,19 @@ const ( MaxDNSSearchListChars = 256 ) +func validateReadinessGates(readinessGates []core.PodReadinessGate, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if !utilfeature.DefaultFeatureGate.Enabled(features.PodReadinessGates) && len(readinessGates) > 0 { + return append(allErrs, field.Forbidden(fldPath, "PodReadinessGates is disabled by feature gate")) + } + for i, value := range readinessGates { + for _, msg := range validation.IsQualifiedName(string(value.ConditionType)) { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("conditionType"), string(value.ConditionType), msg)) + } + } + return allErrs +} + func validatePodDNSConfig(dnsConfig *core.PodDNSConfig, dnsPolicy *core.DNSPolicy, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -2769,7 +2781,7 @@ func validateTaintEffect(effect *core.TaintEffect, allowEmpty bool, fldPath *fie // TODO: Uncomment this block when implement TaintEffectNoScheduleNoAdmit. // string(core.TaintEffectNoScheduleNoAdmit), } - allErrors = append(allErrors, field.NotSupported(fldPath, effect, validValues)) + allErrors = append(allErrors, field.NotSupported(fldPath, *effect, validValues)) } return allErrors } @@ -2931,7 +2943,7 @@ func ValidatePodSpec(spec *core.PodSpec, fldPath *field.Path) field.ErrorList { vols, vErrs := ValidateVolumes(spec.Volumes, fldPath.Child("volumes")) allErrs = append(allErrs, vErrs...) - allErrs = append(allErrs, validateContainers(spec.Containers, vols, fldPath.Child("containers"))...) + allErrs = append(allErrs, validateContainers(spec.Containers, false, vols, fldPath.Child("containers"))...) allErrs = append(allErrs, validateInitContainers(spec.InitContainers, spec.Containers, vols, fldPath.Child("initContainers"))...) allErrs = append(allErrs, validateRestartPolicy(&spec.RestartPolicy, fldPath.Child("restartPolicy"))...) allErrs = append(allErrs, validateDNSPolicy(&spec.DNSPolicy, fldPath.Child("dnsPolicy"))...) @@ -2940,6 +2952,7 @@ func ValidatePodSpec(spec *core.PodSpec, fldPath *field.Path) field.ErrorList { allErrs = append(allErrs, validateImagePullSecrets(spec.ImagePullSecrets, fldPath.Child("imagePullSecrets"))...) allErrs = append(allErrs, validateAffinity(spec.Affinity, fldPath.Child("affinity"))...) allErrs = append(allErrs, validatePodDNSConfig(spec.DNSConfig, &spec.DNSPolicy, fldPath.Child("dnsConfig"))...) + allErrs = append(allErrs, validateReadinessGates(spec.ReadinessGates, fldPath.Child("readinessGates"))...) if len(spec.ServiceAccountName) > 0 { for _, msg := range ValidateServiceAccountName(spec.ServiceAccountName, false) { allErrs = append(allErrs, field.Invalid(fldPath.Child("serviceAccountName"), spec.ServiceAccountName, msg)) @@ -3006,7 +3019,40 @@ func ValidateNodeSelectorRequirement(rq core.NodeSelectorRequirement, fldPath *f default: allErrs = append(allErrs, field.Invalid(fldPath.Child("operator"), rq.Operator, "not a valid selector operator")) } + allErrs = append(allErrs, unversionedvalidation.ValidateLabelName(rq.Key, fldPath.Child("key"))...) + + return allErrs +} + +var nodeFieldSelectorValidators = map[string]func(string, bool) []string{ + core.ObjectNameField: ValidateNodeName, +} + +// ValidateNodeFieldSelectorRequirement tests that the specified NodeSelectorRequirement fields has valid data +func ValidateNodeFieldSelectorRequirement(req core.NodeSelectorRequirement, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + switch req.Operator { + case core.NodeSelectorOpIn, core.NodeSelectorOpNotIn: + if len(req.Values) != 1 { + allErrs = append(allErrs, field.Required(fldPath.Child("values"), + "must be only one value when `operator` is 'In' or 'NotIn' for node field selector")) + } + default: + allErrs = append(allErrs, field.Invalid(fldPath.Child("operator"), req.Operator, "not a valid selector operator")) + } + + if vf, found := nodeFieldSelectorValidators[req.Key]; !found { + allErrs = append(allErrs, field.Invalid(fldPath.Child("key"), req.Key, "not a valid field selector key")) + } else { + for i, v := range req.Values { + for _, msg := range vf(v, false) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("values").Index(i), v, msg)) + } + } + } + return allErrs } @@ -3017,6 +3063,11 @@ func ValidateNodeSelectorTerm(term core.NodeSelectorTerm, fldPath *field.Path) f for j, req := range term.MatchExpressions { allErrs = append(allErrs, ValidateNodeSelectorRequirement(req, fldPath.Child("matchExpressions").Index(j))...) } + + for j, req := range term.MatchFields { + allErrs = append(allErrs, ValidateNodeFieldSelectorRequirement(req, fldPath.Child("matchFields").Index(j))...) + } + return allErrs } @@ -3036,6 +3087,32 @@ func ValidateNodeSelector(nodeSelector *core.NodeSelector, fldPath *field.Path) return allErrs } +// validateTopologySelectorLabelRequirement tests that the specified TopologySelectorLabelRequirement fields has valid data +func validateTopologySelectorLabelRequirement(rq core.TopologySelectorLabelRequirement, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if len(rq.Values) == 0 { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("values"), "must specify as least one value")) + } + allErrs = append(allErrs, unversionedvalidation.ValidateLabelName(rq.Key, fldPath.Child("key"))...) + + return allErrs +} + +// ValidateTopologySelectorTerm tests that the specified topology selector term has valid data +func ValidateTopologySelectorTerm(term core.TopologySelectorTerm, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + for i, req := range term.MatchLabelExpressions { + allErrs = append(allErrs, validateTopologySelectorLabelRequirement(req, fldPath.Child("matchLabelExpressions").Index(i))...) + } + } else if len(term.MatchLabelExpressions) != 0 { + allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate DynamicProvisioningScheduling")) + } + + return allErrs +} + // ValidateAvoidPodsInNodeAnnotations tests that the serialized AvoidPods in Node.Annotations has valid data func ValidateAvoidPodsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -3182,7 +3259,7 @@ func validatePodAffinity(podAffinity *core.PodAffinity, fldPath *field.Path) fie } func ValidateSeccompProfile(p string, fldPath *field.Path) field.ErrorList { - if p == "docker/default" { + if p == core.SeccompProfileRuntimeDefault || p == core.DeprecatedSeccompProfileDockerDefault { return nil } if p == "unconfined" { @@ -3270,12 +3347,16 @@ func IsValidSysctlName(name string) bool { func validateSysctls(sysctls []core.Sysctl, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + names := make(map[string]struct{}) for i, s := range sysctls { if len(s.Name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("name"), "")) } else if !IsValidSysctlName(s.Name) { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("name"), s.Name, fmt.Sprintf("must have at most %d characters and match regex %s", SysctlMaxLength, SysctlFmt))) + } else if _, ok := names[s.Name]; ok { + allErrs = append(allErrs, field.Duplicate(fldPath.Index(i).Child("name"), s.Name)) } + names[s.Name] = struct{}{} } return allErrs } @@ -3314,6 +3395,14 @@ func ValidatePodSecurityContext(securityContext *core.PodSecurityContext, spec * allErrs = append(allErrs, field.Invalid(fldPath.Child("shareProcessNamespace"), *securityContext.ShareProcessNamespace, "ShareProcessNamespace and HostPID cannot both be enabled")) } } + + if len(securityContext.Sysctls) != 0 { + if utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) { + allErrs = append(allErrs, validateSysctls(securityContext.Sysctls, fldPath.Child("sysctls"))...) + } else { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("sysctls"), "Sysctls are disabled by Sysctls feature-gate")) + } + } } return allErrs @@ -3452,6 +3541,7 @@ func ValidatePodStatusUpdate(newPod, oldPod *core.Pod) field.ErrorList { fldPath := field.NewPath("metadata") allErrs := ValidateObjectMetaUpdate(&newPod.ObjectMeta, &oldPod.ObjectMeta, fldPath) allErrs = append(allErrs, ValidatePodSpecificAnnotationUpdates(newPod, oldPod, fldPath.Child("annotations"))...) + allErrs = append(allErrs, validatePodConditions(newPod.Status.Conditions, fldPath.Child("conditions"))...) fldPath = field.NewPath("status") if newPod.Spec.NodeName != oldPod.Spec.NodeName { @@ -3475,6 +3565,21 @@ func ValidatePodStatusUpdate(newPod, oldPod *core.Pod) field.ErrorList { return allErrs } +// validatePodConditions tests if the custom pod conditions are valid. +func validatePodConditions(conditions []core.PodCondition, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + systemConditions := sets.NewString(string(core.PodScheduled), string(core.PodReady), string(core.PodInitialized)) + for i, condition := range conditions { + if systemConditions.Has(string(condition.Type)) { + continue + } + for _, msg := range validation.IsQualifiedName(string(condition.Type)) { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("Type"), string(condition.Type), msg)) + } + } + return allErrs +} + // ValidatePodBinding tests if required fields in the pod binding are legal. func ValidatePodBinding(binding *core.Binding) field.ErrorList { allErrs := field.ErrorList{} @@ -3982,14 +4087,14 @@ func ValidateNode(node *core.Node) field.ErrorList { // That said, if specified, we need to ensure they are valid. allErrs = append(allErrs, ValidateNodeResources(node)...) - // external ID is required. - if len(node.Spec.ExternalID) == 0 { - allErrs = append(allErrs, field.Required(field.NewPath("spec", "externalID"), "")) - } - - // Only allow Node.Spec.ConfigSource to be set if the DynamicKubeletConfig feature gate is enabled - if node.Spec.ConfigSource != nil && !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "configSource"), "configSource may only be set if the DynamicKubeletConfig feature gate is enabled)")) + // Only allow Spec.ConfigSource and Status.Config to be set if the DynamicKubeletConfig feature gate is enabled + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { + if node.Spec.ConfigSource != nil { + allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "configSource"), "configSource may only be set if the DynamicKubeletConfig feature gate is enabled)")) + } + if node.Status.Config != nil { + allErrs = append(allErrs, field.Forbidden(field.NewPath("status", "config"), "config may only be set if the DynamicKubeletConfig feature gate is enabled)")) + } } if len(node.Spec.PodCIDR) != 0 { @@ -4074,6 +4179,18 @@ func ValidateNodeUpdate(node, oldNode *core.Node) field.ErrorList { } } + // Allow and validate updates to Node.Spec.ConfigSource and Node.Status.Config if DynamicKubeletConfig feature gate is enabled + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { + if node.Spec.ConfigSource != nil { + allErrs = append(allErrs, validateNodeConfigSourceSpec(node.Spec.ConfigSource, field.NewPath("spec", "configSource"))...) + } + oldNode.Spec.ConfigSource = node.Spec.ConfigSource + if node.Status.Config != nil { + allErrs = append(allErrs, validateNodeConfigStatus(node.Status.Config, field.NewPath("status", "config"))...) + } + oldNode.Status.Config = node.Status.Config + } + // TODO: move reset function to its own location // Ignore metadata changes now that they have been tested oldNode.ObjectMeta = node.ObjectMeta @@ -4090,11 +4207,6 @@ func ValidateNodeUpdate(node, oldNode *core.Node) field.ErrorList { } oldNode.Spec.Taints = node.Spec.Taints - // Allow updates to Node.Spec.ConfigSource if DynamicKubeletConfig feature gate is enabled - if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { - oldNode.Spec.ConfigSource = node.Spec.ConfigSource - } - // We made allowed changes to oldNode, and now we compare oldNode to node. Any remaining differences indicate changes to protected fields. // TODO: Add a 'real' error type for this error and provide print actual diffs. if !apiequality.Semantic.DeepEqual(oldNode, node) { @@ -4105,6 +4217,111 @@ func ValidateNodeUpdate(node, oldNode *core.Node) field.ErrorList { return allErrs } +// validation specific to Node.Spec.ConfigSource +func validateNodeConfigSourceSpec(source *core.NodeConfigSource, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + count := int(0) + if source.ConfigMap != nil { + count++ + allErrs = append(allErrs, validateConfigMapNodeConfigSourceSpec(source.ConfigMap, fldPath.Child("configMap"))...) + } + // add more subfields here in the future as they are added to NodeConfigSource + + // exactly one reference subfield must be non-nil + if count != 1 { + allErrs = append(allErrs, field.Invalid(fldPath, source, "exactly one reference subfield must be non-nil")) + } + return allErrs +} + +// validation specific to Node.Spec.ConfigSource.ConfigMap +func validateConfigMapNodeConfigSourceSpec(source *core.ConfigMapNodeConfigSource, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + // uid and resourceVersion must not be set in spec + if string(source.UID) != "" { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("uid"), "uid must not be set in spec")) + } + if source.ResourceVersion != "" { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("resourceVersion"), "resourceVersion must not be set in spec")) + } + return append(allErrs, validateConfigMapNodeConfigSource(source, fldPath)...) +} + +// validation specififc to Node.Status.Config +func validateNodeConfigStatus(status *core.NodeConfigStatus, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if status.Assigned != nil { + allErrs = append(allErrs, validateNodeConfigSourceStatus(status.Assigned, fldPath.Child("assigned"))...) + } + if status.Active != nil { + allErrs = append(allErrs, validateNodeConfigSourceStatus(status.Active, fldPath.Child("active"))...) + } + if status.LastKnownGood != nil { + allErrs = append(allErrs, validateNodeConfigSourceStatus(status.LastKnownGood, fldPath.Child("lastKnownGood"))...) + } + return allErrs +} + +// validation specific to Node.Status.Config.(Active|Assigned|LastKnownGood) +func validateNodeConfigSourceStatus(source *core.NodeConfigSource, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + count := int(0) + if source.ConfigMap != nil { + count++ + allErrs = append(allErrs, validateConfigMapNodeConfigSourceStatus(source.ConfigMap, fldPath.Child("configMap"))...) + } + // add more subfields here in the future as they are added to NodeConfigSource + + // exactly one reference subfield must be non-nil + if count != 1 { + allErrs = append(allErrs, field.Invalid(fldPath, source, "exactly one reference subfield must be non-nil")) + } + return allErrs +} + +// validation specific to Node.Status.Config.(Active|Assigned|LastKnownGood).ConfigMap +func validateConfigMapNodeConfigSourceStatus(source *core.ConfigMapNodeConfigSource, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + // uid and resourceVersion must be set in status + if string(source.UID) == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("uid"), "uid must be set in status")) + } + if source.ResourceVersion == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("resourceVersion"), "resourceVersion must be set in status")) + } + return append(allErrs, validateConfigMapNodeConfigSource(source, fldPath)...) +} + +// common validation +func validateConfigMapNodeConfigSource(source *core.ConfigMapNodeConfigSource, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + // validate target configmap namespace + if source.Namespace == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("namespace"), "namespace must be set")) + } else { + for _, msg := range ValidateNameFunc(ValidateNamespaceName)(source.Namespace, false) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), source.Namespace, msg)) + } + } + // validate target configmap name + if source.Name == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("name"), "name must be set")) + } else { + for _, msg := range ValidateNameFunc(ValidateConfigMapName)(source.Name, false) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), source.Name, msg)) + } + } + // validate kubeletConfigKey against rules for configMap key names + if source.KubeletConfigKey == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("kubeletConfigKey"), "kubeletConfigKey must be set")) + } else { + for _, msg := range validation.IsConfigMapKey(source.KubeletConfigKey) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("kubeletConfigKey"), source.KubeletConfigKey, msg)) + } + } + return allErrs +} + // Validate compute resource typename. // Refer to docs/design/resources.md for more details. func validateResourceName(value string, fldPath *field.Path) field.ErrorList { @@ -4134,7 +4351,7 @@ func validateContainerResourceName(value string, fldPath *field.Path) field.Erro if !helper.IsStandardContainerResourceName(value) { return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers")) } - } else if !helper.IsDefaultNamespaceResource(core.ResourceName(value)) { + } else if !helper.IsNativeResource(core.ResourceName(value)) { if !helper.IsExtendedResourceName(core.ResourceName(value)) { return append(allErrs, field.Invalid(fldPath, value, "doesn't follow extended resource name standard")) } @@ -4147,9 +4364,8 @@ func isLocalStorageResource(name string) bool { if name == string(core.ResourceEphemeralStorage) || name == string(core.ResourceRequestsEphemeralStorage) || name == string(core.ResourceLimitsEphemeralStorage) { return true - } else { - return false } + return false } // Validate resource names that can go in a resource quota @@ -4591,6 +4807,74 @@ func validateResourceQuotaScopes(resourceQuotaSpec *core.ResourceQuotaSpec, fld return allErrs } +// validateScopedResourceSelectorRequirement tests that the match expressions has valid data +func validateScopedResourceSelectorRequirement(resourceQuotaSpec *core.ResourceQuotaSpec, fld *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + hardLimits := sets.NewString() + for k := range resourceQuotaSpec.Hard { + hardLimits.Insert(string(k)) + } + fldPath := fld.Child("matchExpressions") + scopeSet := sets.NewString() + for _, req := range resourceQuotaSpec.ScopeSelector.MatchExpressions { + if !helper.IsStandardResourceQuotaScope(string(req.ScopeName)) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("scopeName"), req.ScopeName, "unsupported scope")) + } + for _, k := range hardLimits.List() { + if helper.IsStandardQuotaResourceName(k) && !helper.IsResourceQuotaScopeValidForResource(req.ScopeName, k) { + allErrs = append(allErrs, field.Invalid(fldPath, resourceQuotaSpec.ScopeSelector, "unsupported scope applied to resource")) + } + } + switch req.ScopeName { + case core.ResourceQuotaScopeBestEffort, core.ResourceQuotaScopeNotBestEffort, core.ResourceQuotaScopeTerminating, core.ResourceQuotaScopeNotTerminating: + if req.Operator != core.ScopeSelectorOpExists { + allErrs = append(allErrs, field.Invalid(fldPath.Child("operator"), req.Operator, + "must be 'Exist' only operator when scope is any of ResourceQuotaScopeTerminating, ResourceQuotaScopeNotTerminating, ResourceQuotaScopeBestEffort and ResourceQuotaScopeNotBestEffort")) + } + } + + switch req.Operator { + case core.ScopeSelectorOpIn, core.ScopeSelectorOpNotIn: + if len(req.Values) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("values"), + "must be atleast one value when `operator` is 'In' or 'NotIn' for scope selector")) + } + case core.ScopeSelectorOpExists, core.ScopeSelectorOpDoesNotExist: + if len(req.Values) != 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("values"), req.Values, + "must be no value when `operator` is 'Exist' or 'DoesNotExist' for scope selector")) + } + default: + allErrs = append(allErrs, field.Invalid(fldPath.Child("operator"), req.Operator, "not a valid selector operator")) + } + scopeSet.Insert(string(req.ScopeName)) + } + invalidScopePairs := []sets.String{ + sets.NewString(string(core.ResourceQuotaScopeBestEffort), string(core.ResourceQuotaScopeNotBestEffort)), + sets.NewString(string(core.ResourceQuotaScopeTerminating), string(core.ResourceQuotaScopeNotTerminating)), + } + for _, invalidScopePair := range invalidScopePairs { + if scopeSet.HasAll(invalidScopePair.List()...) { + allErrs = append(allErrs, field.Invalid(fldPath, resourceQuotaSpec.Scopes, "conflicting scopes")) + } + } + + return allErrs +} + +// validateScopeSelector tests that the specified scope selector has valid data +func validateScopeSelector(resourceQuotaSpec *core.ResourceQuotaSpec, fld *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if resourceQuotaSpec.ScopeSelector == nil { + return allErrs + } + if !utilfeature.DefaultFeatureGate.Enabled(features.ResourceQuotaScopeSelectors) && resourceQuotaSpec.ScopeSelector != nil { + allErrs = append(allErrs, field.Forbidden(fld.Child("scopeSelector"), "ResourceQuotaScopeSelectors feature-gate is disabled")) + } + allErrs = append(allErrs, validateScopedResourceSelectorRequirement(resourceQuotaSpec, fld.Child("scopeSelector"))...) + return allErrs +} + // ValidateResourceQuota tests if required fields in the ResourceQuota are set. func ValidateResourceQuota(resourceQuota *core.ResourceQuota) field.ErrorList { allErrs := ValidateObjectMeta(&resourceQuota.ObjectMeta, true, ValidateResourceQuotaName, field.NewPath("metadata")) @@ -4630,6 +4914,7 @@ func ValidateResourceQuotaSpec(resourceQuotaSpec *core.ResourceQuotaSpec, fld *f allErrs = append(allErrs, ValidateResourceQuantityValue(string(k), v, resPath)...) } allErrs = append(allErrs, validateResourceQuotaScopes(resourceQuotaSpec, fld)...) + allErrs = append(allErrs, validateScopeSelector(resourceQuotaSpec, fld)...) return allErrs } @@ -4989,49 +5274,6 @@ func ValidateLoadBalancerStatus(status *core.LoadBalancerStatus, fldPath *field. return allErrs } -func sysctlIntersection(a []core.Sysctl, b []core.Sysctl) []string { - lookup := make(map[string]struct{}, len(a)) - result := []string{} - for i := range a { - lookup[a[i].Name] = struct{}{} - } - for i := range b { - if _, found := lookup[b[i].Name]; found { - result = append(result, b[i].Name) - } - } - return result -} - -// validateStorageNodeAffinityAnnotation tests that the serialized TopologyConstraints in PersistentVolume.Annotations has valid data -func validateStorageNodeAffinityAnnotation(annotations map[string]string, fldPath *field.Path) (bool, field.ErrorList) { - allErrs := field.ErrorList{} - - na, err := helper.GetStorageNodeAffinityFromAnnotation(annotations) - if err != nil { - allErrs = append(allErrs, field.Invalid(fldPath, core.AlphaStorageNodeAffinityAnnotation, err.Error())) - return false, allErrs - } - if na == nil { - return false, allErrs - } - - if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - allErrs = append(allErrs, field.Forbidden(fldPath, "Storage node affinity is disabled by feature-gate")) - } - - policySpecified := false - if na.RequiredDuringSchedulingIgnoredDuringExecution != nil { - allErrs = append(allErrs, ValidateNodeSelector(na.RequiredDuringSchedulingIgnoredDuringExecution, fldPath.Child("requiredDuringSchedulingIgnoredDuringExecution"))...) - policySpecified = true - } - - if len(na.PreferredDuringSchedulingIgnoredDuringExecution) > 0 { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("preferredDuringSchedulingIgnoredDuringExection"), "Storage node affinity does not support preferredDuringSchedulingIgnoredDuringExecution")) - } - return policySpecified, allErrs -} - // validateVolumeNodeAffinity tests that the PersistentVolume.NodeAffinity has valid data // returns: // - true if volumeNodeAffinity is set diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation_test.go index f7bcb00ee..6929ff2e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation_test.go @@ -32,13 +32,12 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" - "k8s.io/kubernetes/pkg/api/legacyscheme" _ "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/capabilities" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/security/apparmor" + utilpointer "k8s.io/kubernetes/pkg/util/pointer" ) const ( @@ -65,24 +64,6 @@ func testVolume(name string, namespace string, spec core.PersistentVolumeSpec) * } } -func testVolumeWithAlphaNodeAffinity(t *testing.T, name string, namespace string, affinity *core.NodeAffinity, spec core.PersistentVolumeSpec) *core.PersistentVolume { - objMeta := metav1.ObjectMeta{Name: name} - if namespace != "" { - objMeta.Namespace = namespace - } - - objMeta.Annotations = map[string]string{} - err := helper.StorageNodeAffinityToAlphaAnnotation(objMeta.Annotations, affinity) - if err != nil { - t.Fatalf("Failed to get node affinity annotation: %v", err) - } - - return &core.PersistentVolume{ - ObjectMeta: objMeta, - Spec: spec, - } -} - func TestValidatePersistentVolumes(t *testing.T) { validMode := core.PersistentVolumeFilesystem scenarios := map[string]struct { @@ -512,29 +493,6 @@ func TestValidateLocalVolumes(t *testing.T) { isExpectedFailure bool volume *core.PersistentVolume }{ - "alpha valid local volume": { - isExpectedFailure: false, - volume: testVolumeWithAlphaNodeAffinity( - t, - "valid-local-volume", - "", - &core.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{ - NodeSelectorTerms: []core.NodeSelectorTerm{ - { - MatchExpressions: []core.NodeSelectorRequirement{ - { - Key: "test-label-key", - Operator: core.NodeSelectorOpIn, - Values: []string{"test-label-value"}, - }, - }, - }, - }, - }, - }, - testLocalVolume("/foo", nil)), - }, "alpha invalid local volume nil annotations": { isExpectedFailure: true, volume: testVolume( @@ -542,75 +500,6 @@ func TestValidateLocalVolumes(t *testing.T) { "", testLocalVolume("/foo", nil)), }, - "alpha invalid local volume empty affinity": { - isExpectedFailure: true, - volume: testVolumeWithAlphaNodeAffinity( - t, - "invalid-local-volume-empty-affinity", - "", - &core.NodeAffinity{}, - testLocalVolume("/foo", nil)), - }, - "alpha invalid local volume preferred affinity": { - isExpectedFailure: true, - volume: testVolumeWithAlphaNodeAffinity( - t, - "invalid-local-volume-preferred-affinity", - "", - &core.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{ - NodeSelectorTerms: []core.NodeSelectorTerm{ - { - MatchExpressions: []core.NodeSelectorRequirement{ - { - Key: "test-label-key", - Operator: core.NodeSelectorOpIn, - Values: []string{"test-label-value"}, - }, - }, - }, - }, - }, - PreferredDuringSchedulingIgnoredDuringExecution: []core.PreferredSchedulingTerm{ - { - Weight: 10, - Preference: core.NodeSelectorTerm{ - MatchExpressions: []core.NodeSelectorRequirement{ - { - Key: "test-label-key", - Operator: core.NodeSelectorOpIn, - Values: []string{"test-label-value"}, - }, - }, - }, - }, - }, - }, - testLocalVolume("/foo", nil)), - }, - "alpha and beta local volume": { - isExpectedFailure: true, - volume: testVolumeWithAlphaNodeAffinity( - t, - "invalid-alpha-beta-local-volume", - "", - &core.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{ - NodeSelectorTerms: []core.NodeSelectorTerm{ - { - MatchExpressions: []core.NodeSelectorRequirement{ - { - Key: "test-label-key", - Operator: core.NodeSelectorOpIn, - Values: []string{"test-label-value"}, - }, - }, - }, - }, - }, - }, - testLocalVolume("/foo", simpleVolumeNodeAffinity("foo", "bar"))), - }, "valid local volume": { isExpectedFailure: false, volume: testVolume("valid-local-volume", "", @@ -654,29 +543,6 @@ func TestValidateLocalVolumesDisabled(t *testing.T) { isExpectedFailure bool volume *core.PersistentVolume }{ - "alpha disabled valid local volume": { - isExpectedFailure: true, - volume: testVolumeWithAlphaNodeAffinity( - t, - "valid-local-volume", - "", - &core.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{ - NodeSelectorTerms: []core.NodeSelectorTerm{ - { - MatchExpressions: []core.NodeSelectorRequirement{ - { - Key: "test-label-key", - Operator: core.NodeSelectorOpIn, - Values: []string{"test-label-value"}, - }, - }, - }, - }, - }, - }, - testLocalVolume("/foo", nil)), - }, "feature disabled valid local volume": { isExpectedFailure: true, volume: testVolume("valid-local-volume", "", @@ -1694,7 +1560,7 @@ func TestValidateKeyToPath(t *testing.T) { ok: true, }, { - kp: core.KeyToPath{Key: "k", Path: "p", Mode: newInt32(0644)}, + kp: core.KeyToPath{Key: "k", Path: "p", Mode: utilpointer.Int32Ptr(0644)}, ok: true, }, { @@ -1728,12 +1594,12 @@ func TestValidateKeyToPath(t *testing.T) { errtype: field.ErrorTypeInvalid, }, { - kp: core.KeyToPath{Key: "k", Path: "p", Mode: newInt32(01000)}, + kp: core.KeyToPath{Key: "k", Path: "p", Mode: utilpointer.Int32Ptr(01000)}, ok: false, errtype: field.ErrorTypeInvalid, }, { - kp: core.KeyToPath{Key: "k", Path: "p", Mode: newInt32(-1)}, + kp: core.KeyToPath{Key: "k", Path: "p", Mode: utilpointer.Int32Ptr(-1)}, ok: false, errtype: field.ErrorTypeInvalid, }, @@ -1970,14 +1836,6 @@ func TestValidateCSIVolumeSource(t *testing.T) { t.Errorf("Failed to disable feature gate for CSIPersistentVolumes: %v", err) return } - -} - -// helper -func newInt32(val int) *int32 { - p := new(int32) - *p = int32(val) - return p } // This test is a little too top-to-bottom. Ideally we would test each volume @@ -1986,12 +1844,17 @@ func newInt32(val int) *int32 { func TestValidateVolumes(t *testing.T) { validInitiatorName := "iqn.2015-02.example.com:init" invalidInitiatorName := "2015-02.example.com:init" + + type verr struct { + etype field.ErrorType + field string + detail string + } + testCases := []struct { - name string - vol core.Volume - errtype field.ErrorType - errfield string - errdetail string + name string + vol core.Volume + errs []verr }{ // EmptyDir and basic volume names { @@ -2036,8 +1899,10 @@ func TestValidateVolumes(t *testing.T) { Name: "", VolumeSource: core.VolumeSource{EmptyDir: &core.EmptyDirVolumeSource{}}, }, - errtype: field.ErrorTypeRequired, - errfield: "name", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "name", + }}, }, { name: "name > 63 characters", @@ -2045,9 +1910,11 @@ func TestValidateVolumes(t *testing.T) { Name: strings.Repeat("a", 64), VolumeSource: core.VolumeSource{EmptyDir: &core.EmptyDirVolumeSource{}}, }, - errtype: field.ErrorTypeInvalid, - errfield: "name", - errdetail: "must be no more than", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "name", + detail: "must be no more than", + }}, }, { name: "name not a DNS label", @@ -2055,9 +1922,11 @@ func TestValidateVolumes(t *testing.T) { Name: "a.b.c", VolumeSource: core.VolumeSource{EmptyDir: &core.EmptyDirVolumeSource{}}, }, - errtype: field.ErrorTypeInvalid, - errfield: "name", - errdetail: dnsLabelErrMsg, + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "name", + detail: dnsLabelErrMsg, + }}, }, // More than one source field specified. { @@ -2072,9 +1941,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeForbidden, - errfield: "hostPath", - errdetail: "may not specify more than 1 volume", + errs: []verr{{ + etype: field.ErrorTypeForbidden, + field: "hostPath", + detail: "may not specify more than 1 volume", + }}, }, // HostPath Default { @@ -2114,8 +1985,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeNotSupported, - errfield: "type", + errs: []verr{{ + etype: field.ErrorTypeNotSupported, + field: "type", + }}, }, { name: "invalid HostPath backsteps", @@ -2128,9 +2001,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "path", - errdetail: "must not contain '..'", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "path", + detail: "must not contain '..'", + }}, }, // GcePersistentDisk { @@ -2211,9 +2086,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "gitRepo.directory", - errdetail: `must not contain '..'`, + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "gitRepo.directory", + detail: `must not contain '..'`, + }}, }, { name: "GitRepo contains ..", @@ -2226,9 +2103,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "gitRepo.directory", - errdetail: `must not contain '..'`, + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "gitRepo.directory", + detail: `must not contain '..'`, + }}, }, { name: "GitRepo absolute target", @@ -2241,8 +2120,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "gitRepo.directory", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "gitRepo.directory", + }}, }, // ISCSI { @@ -2304,8 +2185,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "iscsi.targetPortal", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "iscsi.targetPortal", + }}, }, { name: "empty iqn", @@ -2321,8 +2204,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "iscsi.iqn", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "iscsi.iqn", + }}, }, { name: "invalid IQN: iqn format", @@ -2338,8 +2223,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "iscsi.iqn", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "iscsi.iqn", + }}, }, { name: "invalid IQN: eui format", @@ -2355,8 +2242,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "iscsi.iqn", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "iscsi.iqn", + }}, }, { name: "invalid IQN: naa format", @@ -2372,8 +2261,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "iscsi.iqn", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "iscsi.iqn", + }}, }, { name: "valid initiatorName", @@ -2406,8 +2297,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "iscsi.initiatorname", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "iscsi.initiatorname", + }}, }, { name: "empty secret", @@ -2424,8 +2317,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "iscsi.secretRef", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "iscsi.secretRef", + }}, }, { name: "empty secret", @@ -2442,8 +2337,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "iscsi.secretRef", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "iscsi.secretRef", + }}, }, // Secret { @@ -2464,7 +2361,7 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ Secret: &core.SecretVolumeSource{ SecretName: "my-secret", - DefaultMode: newInt32(0644), + DefaultMode: utilpointer.Int32Ptr(0644), }, }, }, @@ -2479,7 +2376,7 @@ func TestValidateVolumes(t *testing.T) { Items: []core.KeyToPath{{ Key: "key", Path: "filename", - Mode: newInt32(0644), + Mode: utilpointer.Int32Ptr(0644), }}, }, }, @@ -2511,8 +2408,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "secret.items[0].path", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "secret.items[0].path", + }}, }, { name: "secret with leading ..", @@ -2525,8 +2424,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "secret.items[0].path", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "secret.items[0].path", + }}, }, { name: "secret with .. inside", @@ -2539,8 +2440,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "secret.items[0].path", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "secret.items[0].path", + }}, }, { name: "secret with invalid positive defaultMode", @@ -2549,12 +2452,14 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ Secret: &core.SecretVolumeSource{ SecretName: "s", - DefaultMode: newInt32(01000), + DefaultMode: utilpointer.Int32Ptr(01000), }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "secret.defaultMode", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "secret.defaultMode", + }}, }, { name: "secret with invalid negative defaultMode", @@ -2563,12 +2468,14 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ Secret: &core.SecretVolumeSource{ SecretName: "s", - DefaultMode: newInt32(-1), + DefaultMode: utilpointer.Int32Ptr(-1), }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "secret.defaultMode", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "secret.defaultMode", + }}, }, // ConfigMap { @@ -2593,7 +2500,7 @@ func TestValidateVolumes(t *testing.T) { LocalObjectReference: core.LocalObjectReference{ Name: "my-cfgmap", }, - DefaultMode: newInt32(0644), + DefaultMode: utilpointer.Int32Ptr(0644), }, }, }, @@ -2609,7 +2516,7 @@ func TestValidateVolumes(t *testing.T) { Items: []core.KeyToPath{{ Key: "key", Path: "filename", - Mode: newInt32(0644), + Mode: utilpointer.Int32Ptr(0644), }}, }, }, @@ -2642,8 +2549,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "configMap.items[0].path", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "configMap.items[0].path", + }}, }, { name: "configmap with leading ..", @@ -2656,8 +2565,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "configMap.items[0].path", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "configMap.items[0].path", + }}, }, { name: "configmap with .. inside", @@ -2670,8 +2581,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "configMap.items[0].path", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "configMap.items[0].path", + }}, }, { name: "configmap with invalid positive defaultMode", @@ -2680,12 +2593,14 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ ConfigMap: &core.ConfigMapVolumeSource{ LocalObjectReference: core.LocalObjectReference{Name: "c"}, - DefaultMode: newInt32(01000), + DefaultMode: utilpointer.Int32Ptr(01000), }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "configMap.defaultMode", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "configMap.defaultMode", + }}, }, { name: "configmap with invalid negative defaultMode", @@ -2694,12 +2609,14 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ ConfigMap: &core.ConfigMapVolumeSource{ LocalObjectReference: core.LocalObjectReference{Name: "c"}, - DefaultMode: newInt32(-1), + DefaultMode: utilpointer.Int32Ptr(-1), }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "configMap.defaultMode", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "configMap.defaultMode", + }}, }, // Glusterfs { @@ -2727,8 +2644,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "glusterfs.endpoints", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "glusterfs.endpoints", + }}, }, { name: "empty path", @@ -2742,8 +2661,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "glusterfs.path", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "glusterfs.path", + }}, }, // Flocker { @@ -2778,8 +2699,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "flocker", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "flocker", + }}, }, { name: "both specified", @@ -2792,8 +2715,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "flocker", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "flocker", + }}, }, { name: "slash in flocker datasetName", @@ -2805,9 +2730,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "flocker.datasetName", - errdetail: "must not contain '/'", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "flocker.datasetName", + detail: "must not contain '/'", + }}, }, // RBD { @@ -2835,8 +2762,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "rbd.monitors", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "rbd.monitors", + }}, }, { name: "empty image", @@ -2850,8 +2779,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "rbd.image", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "rbd.image", + }}, }, // Cinder { @@ -2889,8 +2820,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "cephfs.monitors", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "cephfs.monitors", + }}, }, // DownwardAPI { @@ -3023,7 +2956,7 @@ func TestValidateVolumes(t *testing.T) { Name: "downapi", VolumeSource: core.VolumeSource{ DownwardAPI: &core.DownwardAPIVolumeSource{ - DefaultMode: newInt32(0644), + DefaultMode: utilpointer.Int32Ptr(0644), }, }, }, @@ -3035,7 +2968,7 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ DownwardAPI: &core.DownwardAPIVolumeSource{ Items: []core.DownwardAPIVolumeFile{{ - Mode: newInt32(0644), + Mode: utilpointer.Int32Ptr(0644), Path: "path", FieldRef: &core.ObjectFieldSelector{ APIVersion: "v1", @@ -3053,7 +2986,7 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ DownwardAPI: &core.DownwardAPIVolumeSource{ Items: []core.DownwardAPIVolumeFile{{ - Mode: newInt32(01000), + Mode: utilpointer.Int32Ptr(01000), Path: "path", FieldRef: &core.ObjectFieldSelector{ APIVersion: "v1", @@ -3063,8 +2996,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "downwardAPI.mode", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "downwardAPI.mode", + }}, }, { name: "downapi invalid negative item mode", @@ -3073,7 +3008,7 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ DownwardAPI: &core.DownwardAPIVolumeSource{ Items: []core.DownwardAPIVolumeFile{{ - Mode: newInt32(-1), + Mode: utilpointer.Int32Ptr(-1), Path: "path", FieldRef: &core.ObjectFieldSelector{ APIVersion: "v1", @@ -3083,8 +3018,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "downwardAPI.mode", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "downwardAPI.mode", + }}, }, { name: "downapi empty metatada path", @@ -3102,8 +3039,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "downwardAPI.path", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "downwardAPI.path", + }}, }, { name: "downapi absolute path", @@ -3121,8 +3060,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "downwardAPI.path", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "downwardAPI.path", + }}, }, { name: "downapi dot dot path", @@ -3140,9 +3081,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "downwardAPI.path", - errdetail: `must not contain '..'`, + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "downwardAPI.path", + detail: `must not contain '..'`, + }}, }, { name: "downapi dot dot file name", @@ -3160,9 +3103,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "downwardAPI.path", - errdetail: `must not start with '..'`, + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "downwardAPI.path", + detail: `must not start with '..'`, + }}, }, { name: "downapi dot dot first level dirent", @@ -3180,9 +3125,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "downwardAPI.path", - errdetail: `must not start with '..'`, + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "downwardAPI.path", + detail: `must not start with '..'`, + }}, }, { name: "downapi fieldRef and ResourceFieldRef together", @@ -3204,9 +3151,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "downwardAPI", - errdetail: "fieldRef and resourceFieldRef can not be specified simultaneously", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "downwardAPI", + detail: "fieldRef and resourceFieldRef can not be specified simultaneously", + }}, }, { name: "downapi invalid positive defaultMode", @@ -3214,12 +3163,14 @@ func TestValidateVolumes(t *testing.T) { Name: "downapi", VolumeSource: core.VolumeSource{ DownwardAPI: &core.DownwardAPIVolumeSource{ - DefaultMode: newInt32(01000), + DefaultMode: utilpointer.Int32Ptr(01000), }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "downwardAPI.defaultMode", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "downwardAPI.defaultMode", + }}, }, { name: "downapi invalid negative defaultMode", @@ -3227,12 +3178,14 @@ func TestValidateVolumes(t *testing.T) { Name: "downapi", VolumeSource: core.VolumeSource{ DownwardAPI: &core.DownwardAPIVolumeSource{ - DefaultMode: newInt32(-1), + DefaultMode: utilpointer.Int32Ptr(-1), }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "downwardAPI.defaultMode", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "downwardAPI.defaultMode", + }}, }, // FC { @@ -3242,7 +3195,7 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ FC: &core.FCVolumeSource{ TargetWWNs: []string{"some_wwn"}, - Lun: newInt32(1), + Lun: utilpointer.Int32Ptr(1), FSType: "ext4", ReadOnly: false, }, @@ -3269,16 +3222,18 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ FC: &core.FCVolumeSource{ TargetWWNs: []string{}, - Lun: newInt32(1), + Lun: utilpointer.Int32Ptr(1), WWIDs: []string{}, FSType: "ext4", ReadOnly: false, }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "fc.targetWWNs", - errdetail: "must specify either targetWWNs or wwids", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "fc.targetWWNs", + detail: "must specify either targetWWNs or wwids", + }}, }, { name: "FC invalid: both targetWWNs and wwids simultaneously", @@ -3287,16 +3242,18 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ FC: &core.FCVolumeSource{ TargetWWNs: []string{"some_wwn"}, - Lun: newInt32(1), + Lun: utilpointer.Int32Ptr(1), WWIDs: []string{"some_wwid"}, FSType: "ext4", ReadOnly: false, }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "fc.targetWWNs", - errdetail: "targetWWNs and wwids can not be specified simultaneously", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "fc.targetWWNs", + detail: "targetWWNs and wwids can not be specified simultaneously", + }}, }, { name: "FC valid targetWWNs and empty lun", @@ -3311,9 +3268,11 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "fc.lun", - errdetail: "lun is required if targetWWNs is specified", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "fc.lun", + detail: "lun is required if targetWWNs is specified", + }}, }, { name: "FC valid targetWWNs and invalid lun", @@ -3322,15 +3281,17 @@ func TestValidateVolumes(t *testing.T) { VolumeSource: core.VolumeSource{ FC: &core.FCVolumeSource{ TargetWWNs: []string{"wwn"}, - Lun: newInt32(256), + Lun: utilpointer.Int32Ptr(256), FSType: "ext4", ReadOnly: false, }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "fc.lun", - errdetail: validation.InclusiveRangeError(0, 255), + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "fc.lun", + detail: validation.InclusiveRangeError(0, 255), + }}, }, // FlexVolume { @@ -3371,8 +3332,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "azureFile.secretName", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "azureFile.secretName", + }}, }, { name: "AzureFile empty share", @@ -3386,8 +3349,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "azureFile.shareName", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "azureFile.shareName", + }}, }, // Quobyte { @@ -3415,8 +3380,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "quobyte.registry", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "quobyte.registry", + }}, }, { name: "wrong format registry quobyte", @@ -3429,8 +3396,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "quobyte.registry", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "quobyte.registry", + }}, }, { name: "wrong format multiple registries quobyte", @@ -3443,8 +3412,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeInvalid, - errfield: "quobyte.registry", + errs: []verr{{ + etype: field.ErrorTypeInvalid, + field: "quobyte.registry", + }}, }, { name: "empty volume quobyte", @@ -3456,8 +3427,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "quobyte.volume", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "quobyte.volume", + }}, }, // AzureDisk { @@ -3483,8 +3456,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "azureDisk.diskName", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "azureDisk.diskName", + }}, }, { name: "AzureDisk empty disk uri", @@ -3497,8 +3472,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "azureDisk.diskURI", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "azureDisk.diskURI", + }}, }, // ScaleIO { @@ -3526,8 +3503,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "scaleIO.volumeName", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "scaleIO.volumeName", + }}, }, { name: "ScaleIO with empty gateway", @@ -3541,8 +3520,10 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "scaleIO.gateway", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "scaleIO.gateway", + }}, }, { name: "ScaleIO with empty system", @@ -3556,32 +3537,100 @@ func TestValidateVolumes(t *testing.T) { }, }, }, - errtype: field.ErrorTypeRequired, - errfield: "scaleIO.system", + errs: []verr{{ + etype: field.ErrorTypeRequired, + field: "scaleIO.system", + }}, + }, + // ProjectedVolumeSource + { + name: "ProjectedVolumeSource more than one projection in a source", + vol: core.Volume{ + Name: "projected-volume", + VolumeSource: core.VolumeSource{ + Projected: &core.ProjectedVolumeSource{ + Sources: []core.VolumeProjection{ + { + Secret: &core.SecretProjection{ + LocalObjectReference: core.LocalObjectReference{ + Name: "foo", + }, + }, + }, + { + Secret: &core.SecretProjection{ + LocalObjectReference: core.LocalObjectReference{ + Name: "foo", + }, + }, + DownwardAPI: &core.DownwardAPIProjection{}, + }, + }, + }, + }, + }, + errs: []verr{{ + etype: field.ErrorTypeForbidden, + field: "projected.sources[1]", + }}, + }, + { + name: "ProjectedVolumeSource more than one projection in a source", + vol: core.Volume{ + Name: "projected-volume", + VolumeSource: core.VolumeSource{ + Projected: &core.ProjectedVolumeSource{ + Sources: []core.VolumeProjection{ + { + Secret: &core.SecretProjection{}, + }, + { + Secret: &core.SecretProjection{}, + DownwardAPI: &core.DownwardAPIProjection{}, + }, + }, + }, + }, + }, + errs: []verr{ + { + etype: field.ErrorTypeRequired, + field: "projected.sources[0].secret.name", + }, + { + etype: field.ErrorTypeRequired, + field: "projected.sources[1].secret.name", + }, + { + etype: field.ErrorTypeForbidden, + field: "projected.sources[1]", + }, + }, }, } - for i, tc := range testCases { - names, errs := ValidateVolumes([]core.Volume{tc.vol}, field.NewPath("field")) - if len(errs) > 0 && tc.errtype == "" { - t.Errorf("[%d: %q] unexpected error(s): %v", i, tc.name, errs) - } else if len(errs) > 1 { - t.Errorf("[%d: %q] expected 1 error, got %d: %v", i, tc.name, len(errs), errs) - } else if len(errs) == 0 && tc.errtype != "" { - t.Errorf("[%d: %q] expected error type %v", i, tc.name, tc.errtype) - } else if len(errs) == 1 { - if errs[0].Type != tc.errtype { - t.Errorf("[%d: %q] expected error type %v, got %v", i, tc.name, tc.errtype, errs[0].Type) - } else if !strings.HasSuffix(errs[0].Field, "."+tc.errfield) { - t.Errorf("[%d: %q] expected error on field %q, got %q", i, tc.name, tc.errfield, errs[0].Field) - } else if !strings.Contains(errs[0].Detail, tc.errdetail) { - t.Errorf("[%d: %q] expected error detail %q, got %q", i, tc.name, tc.errdetail, errs[0].Detail) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + names, errs := ValidateVolumes([]core.Volume{tc.vol}, field.NewPath("field")) + if len(errs) != len(tc.errs) { + t.Fatalf("unexpected error(s): got %d, want %d: %v", len(tc.errs), len(errs), errs) } - } else { - if len(names) != 1 || !IsMatchedVolume(tc.vol.Name, names) { - t.Errorf("[%d: %q] wrong names result: %v", i, tc.name, names) + if len(errs) == 0 && (len(names) > 1 || !IsMatchedVolume(tc.vol.Name, names)) { + t.Errorf("wrong names result: %v", names) } - } + for i, err := range errs { + expErr := tc.errs[i] + if err.Type != expErr.etype { + t.Errorf("unexpected error type: got %v, want %v", expErr.etype, err.Type) + } + if !strings.HasSuffix(err.Field, "."+expErr.field) { + t.Errorf("unexpected error field: got %v, want %v", expErr.field, err.Field) + } + if !strings.Contains(err.Detail, expErr.detail) { + t.Errorf("unexpected error detail: got %v, want %v", expErr.detail, err.Detail) + } + } + }) } dupsCase := []core.Volume{ @@ -4166,7 +4215,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.annotations['key']", }, }, @@ -4175,7 +4224,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.labels['key']", }, }, @@ -4184,7 +4233,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.name", }, }, @@ -4193,7 +4242,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.namespace", }, }, @@ -4202,7 +4251,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.uid", }, }, @@ -4211,7 +4260,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "spec.nodeName", }, }, @@ -4220,7 +4269,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "spec.serviceAccountName", }, }, @@ -4229,7 +4278,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "status.hostIP", }, }, @@ -4238,7 +4287,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "status.podIP", }, }, @@ -4307,7 +4356,7 @@ func TestValidateEnv(t *testing.T) { Value: "foo", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.name", }, }, @@ -4328,7 +4377,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.name", }, SecretKeyRef: &core.SecretKeySelector{ @@ -4347,7 +4396,7 @@ func TestValidateEnv(t *testing.T) { Name: "some_var_name", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.name", }, ConfigMapKeyRef: &core.ConfigMapKeySelector{ @@ -4366,7 +4415,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.name", }, SecretKeyRef: &core.SecretKeySelector{ @@ -4419,7 +4468,7 @@ func TestValidateEnv(t *testing.T) { Name: "abc", ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", }, }, }}, @@ -4444,7 +4493,7 @@ func TestValidateEnv(t *testing.T) { ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ FieldPath: "metadata.whoops", - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", }, }, }}, @@ -4522,7 +4571,7 @@ func TestValidateEnv(t *testing.T) { ValueFrom: &core.EnvVarSource{ FieldRef: &core.ObjectFieldSelector{ FieldPath: "status.phase", - APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(), + APIVersion: "v1", }, }, }}, @@ -5190,25 +5239,7 @@ func TestValidateContainers(t *testing.T) { TerminationMessagePolicy: "File", }, { - Name: "resources-test-with-gpu-with-request", - Image: "image", - Resources: core.ResourceRequirements{ - Requests: core.ResourceList{ - core.ResourceName(core.ResourceCPU): resource.MustParse("10"), - core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), - core.ResourceName(core.ResourceNvidiaGPU): resource.MustParse("1"), - }, - Limits: core.ResourceList{ - core.ResourceName(core.ResourceCPU): resource.MustParse("10"), - core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), - core.ResourceName(core.ResourceNvidiaGPU): resource.MustParse("1"), - }, - }, - ImagePullPolicy: "IfNotPresent", - TerminationMessagePolicy: "File", - }, - { - Name: "resources-test-with-gpu-without-request", + Name: "resources-test-with-request-and-limit", Image: "image", Resources: core.ResourceRequirements{ Requests: core.ResourceList{ @@ -5216,9 +5247,8 @@ func TestValidateContainers(t *testing.T) { core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), }, Limits: core.ResourceList{ - core.ResourceName(core.ResourceCPU): resource.MustParse("10"), - core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), - core.ResourceName(core.ResourceNvidiaGPU): resource.MustParse("1"), + core.ResourceName(core.ResourceCPU): resource.MustParse("10"), + core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), }, }, ImagePullPolicy: "IfNotPresent", @@ -5323,7 +5353,7 @@ func TestValidateContainers(t *testing.T) { }, {Name: "abc-1234", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", SecurityContext: fakeValidSecurityContext(true)}, } - if errs := validateContainers(successCase, volumeDevices, field.NewPath("field")); len(errs) != 0 { + if errs := validateContainers(successCase, false, volumeDevices, field.NewPath("field")); len(errs) != 0 { t.Errorf("expected success: %v", errs) } @@ -5507,48 +5537,26 @@ func TestValidateContainers(t *testing.T) { TerminationMessagePolicy: "File", }, }, - "Resource GPU limit must match request": { + "Request limit simple invalid": { { - Name: "gpu-resource-request-limit", + Name: "abc-123", Image: "image", Resources: core.ResourceRequirements{ - Requests: core.ResourceList{ - core.ResourceName(core.ResourceCPU): resource.MustParse("10"), - core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), - core.ResourceName(core.ResourceNvidiaGPU): resource.MustParse("0"), - }, - Limits: core.ResourceList{ - core.ResourceName(core.ResourceCPU): resource.MustParse("10"), - core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), - core.ResourceName(core.ResourceNvidiaGPU): resource.MustParse("1"), - }, + Limits: getResourceLimits("5", "3"), + Requests: getResourceLimits("6", "3"), }, - TerminationMessagePolicy: "File", ImagePullPolicy: "IfNotPresent", - }, - }, - "Resource GPU invalid setting only request": { - { - Name: "gpu-resource-request-limit", - Image: "image", - Resources: core.ResourceRequirements{ - Requests: core.ResourceList{ - core.ResourceName(core.ResourceCPU): resource.MustParse("10"), - core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), - core.ResourceName(core.ResourceNvidiaGPU): resource.MustParse("1"), - }, - }, TerminationMessagePolicy: "File", - ImagePullPolicy: "IfNotPresent", }, }, - "Request limit simple invalid": { + "Invalid storage limit request": { { Name: "abc-123", Image: "image", Resources: core.ResourceRequirements{ - Limits: getResourceLimits("5", "3"), - Requests: getResourceLimits("6", "3"), + Limits: core.ResourceList{ + core.ResourceName("attachable-volumes-aws-ebs"): *resource.NewQuantity(10, resource.DecimalSI), + }, }, ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", @@ -5585,7 +5593,67 @@ func TestValidateContainers(t *testing.T) { }, } for k, v := range errorCases { - if errs := validateContainers(v, volumeDevices, field.NewPath("field")); len(errs) == 0 { + if errs := validateContainers(v, false, volumeDevices, field.NewPath("field")); len(errs) == 0 { + t.Errorf("expected failure for %s", k) + } + } +} + +func TestValidateInitContainers(t *testing.T) { + volumeDevices := make(map[string]core.VolumeSource) + capabilities.SetForTests(capabilities.Capabilities{ + AllowPrivileged: true, + }) + + successCase := []core.Container{ + { + Name: "container-1-same-host-port-different-protocol", + Image: "image", + Ports: []core.ContainerPort{ + {ContainerPort: 80, HostPort: 80, Protocol: "TCP"}, + {ContainerPort: 80, HostPort: 80, Protocol: "UDP"}, + }, + ImagePullPolicy: "IfNotPresent", + TerminationMessagePolicy: "File", + }, + { + Name: "container-2-same-host-port-different-protocol", + Image: "image", + Ports: []core.ContainerPort{ + {ContainerPort: 80, HostPort: 80, Protocol: "TCP"}, + {ContainerPort: 80, HostPort: 80, Protocol: "UDP"}, + }, + ImagePullPolicy: "IfNotPresent", + TerminationMessagePolicy: "File", + }, + } + if errs := validateContainers(successCase, true, volumeDevices, field.NewPath("field")); len(errs) != 0 { + t.Errorf("expected success: %v", errs) + } + + capabilities.SetForTests(capabilities.Capabilities{ + AllowPrivileged: false, + }) + errorCases := map[string][]core.Container{ + "duplicate ports": { + { + Name: "abc", + Image: "image", + Ports: []core.ContainerPort{ + { + ContainerPort: 8080, HostPort: 8080, Protocol: "TCP", + }, + { + ContainerPort: 8080, HostPort: 8080, Protocol: "TCP", + }, + }, + ImagePullPolicy: "IfNotPresent", + TerminationMessagePolicy: "File", + }, + }, + } + for k, v := range errorCases { + if errs := validateContainers(v, true, volumeDevices, field.NewPath("field")); len(errs) == 0 { t.Errorf("expected failure for %s", k) } } @@ -5761,51 +5829,194 @@ func TestValidatePodDNSConfig(t *testing.T) { generateTestSearchPathFunc(50), }, }, - expectedError: true, + expectedError: true, + }, + { + desc: "invalid search path", + dnsConfig: &core.PodDNSConfig{ + Searches: []string{"custom?"}, + }, + expectedError: true, + }, + { + desc: "invalid nameserver", + dnsConfig: &core.PodDNSConfig{ + Nameservers: []string{"invalid"}, + }, + expectedError: true, + }, + { + desc: "invalid empty option name", + dnsConfig: &core.PodDNSConfig{ + Options: []core.PodDNSConfigOption{ + {Value: &testOptionValue}, + }, + }, + expectedError: true, + }, + { + desc: "invalid: DNSNone with 0 nameserver", + dnsConfig: &core.PodDNSConfig{ + Searches: []string{"custom"}, + }, + dnsPolicy: &testDNSNone, + expectedError: true, + }, + } + + for _, tc := range testCases { + if tc.dnsPolicy == nil { + tc.dnsPolicy = &testDNSClusterFirst + } + + errs := validatePodDNSConfig(tc.dnsConfig, tc.dnsPolicy, field.NewPath("dnsConfig")) + if len(errs) != 0 && !tc.expectedError { + t.Errorf("%v: validatePodDNSConfig(%v) = %v, want nil", tc.desc, tc.dnsConfig, errs) + } else if len(errs) == 0 && tc.expectedError { + t.Errorf("%v: validatePodDNSConfig(%v) = nil, want error", tc.desc, tc.dnsConfig) + } + } +} + +func TestValidatePodReadinessGates(t *testing.T) { + podReadinessGatesEnabled := utilfeature.DefaultFeatureGate.Enabled(features.PodReadinessGates) + defer func() { + // Restoring the old value. + if err := utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=%v", features.PodReadinessGates, podReadinessGatesEnabled)); err != nil { + t.Errorf("Failed to restore PodReadinessGates feature gate: %v", err) + } + }() + if err := utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.PodReadinessGates)); err != nil { + t.Errorf("Failed to enable PodReadinessGates feature gate: %v", err) + } + + successCases := []struct { + desc string + readinessGates []core.PodReadinessGate + }{ + { + "no gate", + []core.PodReadinessGate{}, + }, + { + "one readiness gate", + []core.PodReadinessGate{ + { + ConditionType: core.PodConditionType("example.com/condition"), + }, + }, + }, + { + "two readiness gates", + []core.PodReadinessGate{ + { + ConditionType: core.PodConditionType("example.com/condition1"), + }, + { + ConditionType: core.PodConditionType("example.com/condition2"), + }, + }, }, + } + for _, tc := range successCases { + if errs := validateReadinessGates(tc.readinessGates, field.NewPath("field")); len(errs) != 0 { + t.Errorf("expect tc %q to success: %v", tc.desc, errs) + } + } + + errorCases := []struct { + desc string + readinessGates []core.PodReadinessGate + }{ { - desc: "invalid search path", - dnsConfig: &core.PodDNSConfig{ - Searches: []string{"custom?"}, + "invalid condition type", + []core.PodReadinessGate{ + { + ConditionType: core.PodConditionType("invalid/condition/type"), + }, }, - expectedError: true, }, + } + for _, tc := range errorCases { + if errs := validateReadinessGates(tc.readinessGates, field.NewPath("field")); len(errs) == 0 { + t.Errorf("expected tc %q to fail", tc.desc) + } + } +} + +func TestValidatePodConditions(t *testing.T) { + successCases := []struct { + desc string + podConditions []core.PodCondition + }{ { - desc: "invalid nameserver", - dnsConfig: &core.PodDNSConfig{ - Nameservers: []string{"invalid"}, + "no condition", + []core.PodCondition{}, + }, + { + "one system condition", + []core.PodCondition{ + { + Type: core.PodReady, + Status: core.ConditionTrue, + }, }, - expectedError: true, }, { - desc: "invalid empty option name", - dnsConfig: &core.PodDNSConfig{ - Options: []core.PodDNSConfigOption{ - {Value: &testOptionValue}, + "one system condition and one custom condition", + []core.PodCondition{ + { + Type: core.PodReady, + Status: core.ConditionTrue, + }, + { + Type: core.PodConditionType("example.com/condition"), + Status: core.ConditionFalse, }, }, - expectedError: true, }, { - desc: "invalid: DNSNone with 0 nameserver", - dnsConfig: &core.PodDNSConfig{ - Searches: []string{"custom"}, + "two custom condition", + []core.PodCondition{ + { + Type: core.PodConditionType("foobar"), + Status: core.ConditionTrue, + }, + { + Type: core.PodConditionType("example.com/condition"), + Status: core.ConditionFalse, + }, }, - dnsPolicy: &testDNSNone, - expectedError: true, }, } - for _, tc := range testCases { - if tc.dnsPolicy == nil { - tc.dnsPolicy = &testDNSClusterFirst + for _, tc := range successCases { + if errs := validatePodConditions(tc.podConditions, field.NewPath("field")); len(errs) != 0 { + t.Errorf("expected tc %q to success, but got: %v", tc.desc, errs) } + } - errs := validatePodDNSConfig(tc.dnsConfig, tc.dnsPolicy, field.NewPath("dnsConfig")) - if len(errs) != 0 && !tc.expectedError { - t.Errorf("%v: validatePodDNSConfig(%v) = %v, want nil", tc.desc, tc.dnsConfig, errs) - } else if len(errs) == 0 && tc.expectedError { - t.Errorf("%v: validatePodDNSConfig(%v) = nil, want error", tc.desc, tc.dnsConfig) + errorCases := []struct { + desc string + podConditions []core.PodCondition + }{ + { + "one system condition and a invalid custom condition", + []core.PodCondition{ + { + Type: core.PodReady, + Status: core.ConditionStatus("True"), + }, + { + Type: core.PodConditionType("invalid/custom/condition"), + Status: core.ConditionStatus("True"), + }, + }, + }, + } + for _, tc := range errorCases { + if errs := validatePodConditions(tc.podConditions, field.NewPath("field")); len(errs) == 0 { + t.Errorf("expected tc %q to fail", tc.desc) } } } @@ -6243,6 +6454,13 @@ func TestValidatePod(t *testing.T) { Values: []string{"value1", "value2"}, }, }, + MatchFields: []core.NodeSelectorRequirement{ + { + Key: "metadata.name", + Operator: core.NodeSelectorOpIn, + Values: []string{"host1"}, + }, + }, }, }, }, @@ -6471,12 +6689,22 @@ func TestValidatePod(t *testing.T) { }, Spec: extendPodSpecwithTolerations(validPodSpec(nil), []core.Toleration{{Key: "node.kubernetes.io/not-ready", Operator: "Exists", Effect: "NoExecute", TolerationSeconds: &[]int64{-2}[0]}}), }, + { // runtime default seccomp profile + ObjectMeta: metav1.ObjectMeta{ + Name: "123", + Namespace: "ns", + Annotations: map[string]string{ + core.SeccompPodAnnotationKey: core.SeccompProfileRuntimeDefault, + }, + }, + Spec: validPodSpec(nil), + }, { // docker default seccomp profile ObjectMeta: metav1.ObjectMeta{ Name: "123", Namespace: "ns", Annotations: map[string]string{ - core.SeccompPodAnnotationKey: "docker/default", + core.SeccompPodAnnotationKey: core.DeprecatedSeccompProfileDockerDefault, }, }, Spec: validPodSpec(nil), @@ -6550,12 +6778,28 @@ func TestValidatePod(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "123", Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "kernel.shmmni=32768,kernel.shmmax=1000000000", - core.UnsafeSysctlsPodAnnotationKey: "knet.ipv4.route.min_pmtu=1000", + }, + Spec: core.PodSpec{ + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + SecurityContext: &core.PodSecurityContext{ + Sysctls: []core.Sysctl{ + { + Name: "kernel.shmmni", + Value: "32768", + }, + { + Name: "kernel.shmmax", + Value: "1000000000", + }, + { + Name: "knet.ipv4.route.min_pmtu", + Value: "1000", + }, + }, }, }, - Spec: validPodSpec(nil), }, { // valid extended resources for init container ObjectMeta: metav1.ObjectMeta{Name: "valid-extended", Namespace: "ns"}, @@ -6735,6 +6979,83 @@ func TestValidatePod(t *testing.T) { }), }, }, + "invalid node field selector requirement in node affinity, more values for field selector": { + expectedError: "spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchFields[0].values", + spec: core.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "123", + Namespace: "ns", + }, + Spec: validPodSpec(&core.Affinity{ + NodeAffinity: &core.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{ + NodeSelectorTerms: []core.NodeSelectorTerm{ + { + MatchFields: []core.NodeSelectorRequirement{ + { + Key: "metadata.name", + Operator: core.NodeSelectorOpIn, + Values: []string{"host1", "host2"}, + }, + }, + }, + }, + }, + }, + }), + }, + }, + "invalid node field selector requirement in node affinity, invalid operator": { + expectedError: "spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchFields[0].operator", + spec: core.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "123", + Namespace: "ns", + }, + Spec: validPodSpec(&core.Affinity{ + NodeAffinity: &core.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{ + NodeSelectorTerms: []core.NodeSelectorTerm{ + { + MatchFields: []core.NodeSelectorRequirement{ + { + Key: "metadata.name", + Operator: core.NodeSelectorOpExists, + }, + }, + }, + }, + }, + }, + }), + }, + }, + "invalid node field selector requirement in node affinity, invalid key": { + expectedError: "spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchFields[0].key", + spec: core.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "123", + Namespace: "ns", + }, + Spec: validPodSpec(&core.Affinity{ + NodeAffinity: &core.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{ + NodeSelectorTerms: []core.NodeSelectorTerm{ + { + MatchFields: []core.NodeSelectorRequirement{ + { + Key: "metadata.namespace", + Operator: core.NodeSelectorOpIn, + Values: []string{"ns1"}, + }, + }, + }, + }, + }, + }, + }), + }, + }, "invalid preferredSchedulingTerm in node affinity, weight should be in range 1-100": { expectedError: "must be in the range 1-100", spec: core.Pod{ @@ -7159,59 +7480,6 @@ func TestValidatePod(t *testing.T) { Spec: validPodSpec(nil), }, }, - "invalid sysctl annotation": { - expectedError: "metadata.annotations[security.alpha.kubernetes.io/sysctls]", - spec: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "foo:", - }, - }, - Spec: validPodSpec(nil), - }, - }, - "invalid comma-separated sysctl annotation": { - expectedError: "not of the format sysctl_name=value", - spec: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "kernel.msgmax,", - }, - }, - Spec: validPodSpec(nil), - }, - }, - "invalid unsafe sysctl annotation": { - expectedError: "metadata.annotations[security.alpha.kubernetes.io/sysctls]", - spec: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "foo:", - }, - }, - Spec: validPodSpec(nil), - }, - }, - "intersecting safe sysctls and unsafe sysctls annotations": { - expectedError: "can not be safe and unsafe", - spec: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - core.SysctlsPodAnnotationKey: "kernel.shmmax=10000000", - core.UnsafeSysctlsPodAnnotationKey: "kernel.shmmax=10000000", - }, - }, - Spec: validPodSpec(nil), - }, - }, "invalid extended resource requirement: request must be == limit": { expectedError: "must be equal to example.com/a", spec: core.Pod{ @@ -7554,7 +7822,7 @@ func TestValidatePodUpdate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "foo", DeletionTimestamp: &now}, Spec: core.PodSpec{Containers: []core.Container{{Image: "foo:V1"}}}, }, - "", + "metadata.deletionTimestamp", "deletion timestamp removed", }, { @@ -8879,7 +9147,7 @@ func TestValidateService(t *testing.T) { s.Spec.SessionAffinity = core.ServiceAffinityClientIP s.Spec.SessionAffinityConfig = &core.SessionAffinityConfig{ ClientIP: &core.ClientIPConfig{ - TimeoutSeconds: newInt32(-1), + TimeoutSeconds: utilpointer.Int32Ptr(-1), }, } }, @@ -8892,7 +9160,7 @@ func TestValidateService(t *testing.T) { s.Spec.SessionAffinity = core.ServiceAffinityNone s.Spec.SessionAffinityConfig = &core.SessionAffinityConfig{ ClientIP: &core.ClientIPConfig{ - TimeoutSeconds: newInt32(90), + TimeoutSeconds: utilpointer.Int32Ptr(90), }, } }, @@ -9584,9 +9852,6 @@ func TestValidateNode(t *testing.T) { core.ResourceName("hugepages-1Gi"): resource.MustParse("0"), }, }, - Spec: core.NodeSpec{ - ExternalID: "external", - }, }, { ObjectMeta: metav1.ObjectMeta{ @@ -9601,9 +9866,6 @@ func TestValidateNode(t *testing.T) { core.ResourceName(core.ResourceMemory): resource.MustParse("0"), }, }, - Spec: core.NodeSpec{ - ExternalID: "external", - }, }, { ObjectMeta: metav1.ObjectMeta{ @@ -9619,7 +9881,6 @@ func TestValidateNode(t *testing.T) { }, }, Spec: core.NodeSpec{ - ExternalID: "external", // Add a valid taint to a node Taints: []core.Taint{{Key: "GPU", Value: "true", Effect: "NoSchedule"}}, }, @@ -9657,9 +9918,6 @@ func TestValidateNode(t *testing.T) { core.ResourceName(core.ResourceMemory): resource.MustParse("0"), }, }, - Spec: core.NodeSpec{ - ExternalID: "external", - }, }, { ObjectMeta: metav1.ObjectMeta{ @@ -9675,8 +9933,7 @@ func TestValidateNode(t *testing.T) { }, }, Spec: core.NodeSpec{ - ExternalID: "external", - PodCIDR: "192.168.0.0/16", + PodCIDR: "192.168.0.0/16", }, }, } @@ -9699,9 +9956,6 @@ func TestValidateNode(t *testing.T) { core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), }, }, - Spec: core.NodeSpec{ - ExternalID: "external", - }, }, "invalid-labels": { ObjectMeta: metav1.ObjectMeta{ @@ -9714,28 +9968,12 @@ func TestValidateNode(t *testing.T) { core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), }, }, - Spec: core.NodeSpec{ - ExternalID: "external", - }, - }, - "missing-external-id": { - ObjectMeta: metav1.ObjectMeta{ - Name: "abc-123", - Labels: validSelector, - }, - Status: core.NodeStatus{ - Capacity: core.ResourceList{ - core.ResourceName(core.ResourceCPU): resource.MustParse("10"), - core.ResourceName(core.ResourceMemory): resource.MustParse("10G"), - }, - }, }, "missing-taint-key": { ObjectMeta: metav1.ObjectMeta{ Name: "dedicated-node1", }, Spec: core.NodeSpec{ - ExternalID: "external", // Add a taint with an empty key to a node Taints: []core.Taint{{Key: "", Value: "special-user-1", Effect: "NoSchedule"}}, }, @@ -9745,7 +9983,6 @@ func TestValidateNode(t *testing.T) { Name: "dedicated-node1", }, Spec: core.NodeSpec{ - ExternalID: "external", // Add a taint with an invalid key to a node Taints: []core.Taint{{Key: "NoUppercaseOrSpecialCharsLike=Equals", Value: "special-user-1", Effect: "NoSchedule"}}, }, @@ -9764,7 +10001,6 @@ func TestValidateNode(t *testing.T) { }, }, Spec: core.NodeSpec{ - ExternalID: "external", // Add a taint with a bad value to a node Taints: []core.Taint{{Key: "dedicated", Value: "some\\bad\\value", Effect: "NoSchedule"}}, }, @@ -9783,7 +10019,6 @@ func TestValidateNode(t *testing.T) { }, }, Spec: core.NodeSpec{ - ExternalID: "external", // Add a taint with an empty effect to a node Taints: []core.Taint{{Key: "dedicated", Value: "special-user-3", Effect: ""}}, }, @@ -9802,7 +10037,6 @@ func TestValidateNode(t *testing.T) { }, }, Spec: core.NodeSpec{ - ExternalID: "external", // Add a taint with NoExecute effect to a node Taints: []core.Taint{{Key: "dedicated", Value: "special-user-3", Effect: "NoScheduleNoAdmit"}}, }, @@ -9812,7 +10046,6 @@ func TestValidateNode(t *testing.T) { Name: "dedicated-node1", }, Spec: core.NodeSpec{ - ExternalID: "external", // Add two taints to the node with the same key and effect; should be rejected. Taints: []core.Taint{ {Key: "dedicated", Value: "special-user-1", Effect: "NoSchedule"}, @@ -9842,9 +10075,6 @@ func TestValidateNode(t *testing.T) { core.ResourceName(core.ResourceMemory): resource.MustParse("0"), }, }, - Spec: core.NodeSpec{ - ExternalID: "external", - }, }, "invalid-podController": { ObjectMeta: metav1.ObjectMeta{ @@ -9877,9 +10107,6 @@ func TestValidateNode(t *testing.T) { core.ResourceName(core.ResourceMemory): resource.MustParse("0"), }, }, - Spec: core.NodeSpec{ - ExternalID: "external", - }, }, "multiple-pre-allocated-hugepages": { ObjectMeta: metav1.ObjectMeta{ @@ -9898,9 +10125,6 @@ func TestValidateNode(t *testing.T) { core.ResourceName("hugepages-1Gi"): resource.MustParse("10Gi"), }, }, - Spec: core.NodeSpec{ - ExternalID: "external", - }, }, "invalid-pod-cidr": { ObjectMeta: metav1.ObjectMeta{ @@ -9916,8 +10140,7 @@ func TestValidateNode(t *testing.T) { }, }, Spec: core.NodeSpec{ - ExternalID: "external", - PodCIDR: "192.168.0.0", + PodCIDR: "192.168.0.0", }, }, } @@ -10387,7 +10610,7 @@ func TestValidateServiceUpdate(t *testing.T) { newSvc.Spec.SessionAffinity = "ClientIP" newSvc.Spec.SessionAffinityConfig = &core.SessionAffinityConfig{ ClientIP: &core.ClientIPConfig{ - TimeoutSeconds: newInt32(90), + TimeoutSeconds: utilpointer.Int32Ptr(90), }, } }, @@ -11248,6 +11471,18 @@ func TestValidateResourceQuota(t *testing.T) { Scopes: []core.ResourceQuotaScope{core.ResourceQuotaScopeNotBestEffort}, } + scopeSelectorSpec := core.ResourceQuotaSpec{ + ScopeSelector: &core.ScopeSelector{ + MatchExpressions: []core.ScopedResourceSelectorRequirement{ + { + ScopeName: core.ResourceQuotaScopePriorityClass, + Operator: core.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + } + // storage is not yet supported as a quota tracked resource invalidQuotaResourceSpec := core.ResourceQuotaSpec{ Hard: core.ResourceList{ @@ -11340,6 +11575,13 @@ func TestValidateResourceQuota(t *testing.T) { }, Spec: bestEffortSpec, }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "abc", + Namespace: "foo", + }, + Spec: scopeSelectorSpec, + }, { ObjectMeta: metav1.ObjectMeta{ Name: "abc", @@ -11348,12 +11590,13 @@ func TestValidateResourceQuota(t *testing.T) { Spec: nonBestEffortSpec, }, } - + utilfeature.DefaultFeatureGate.Set("ResourceQuotaScopeSelectors=true") for _, successCase := range successCases { if errs := ValidateResourceQuota(&successCase); len(errs) != 0 { t.Errorf("expected success: %v", errs) } } + utilfeature.DefaultFeatureGate.Set("ResourceQuotaScopeSelectors=false") errorCases := map[string]struct { R core.ResourceQuota @@ -11399,6 +11642,10 @@ func TestValidateResourceQuota(t *testing.T) { core.ResourceQuota{ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: invalidScopeNameSpec}, "unsupported scope", }, + "forbidden-quota-scope-selector": { + core.ResourceQuota{ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: scopeSelectorSpec}, + "feature-gate is disabled", + }, } for k, v := range errorCases { errs := ValidateResourceQuota(&v.R) @@ -12521,6 +12768,11 @@ func TestValidateSysctls(t *testing.T) { "_invalid", } + duplicates := []string{ + "kernel.shmmax", + "kernel.shmmax", + } + sysctls := make([]core.Sysctl, len(valid)) for i, sysctl := range valid { sysctls[i].Name = sysctl @@ -12545,6 +12797,17 @@ func TestValidateSysctls(t *testing.T) { t.Errorf("unexpected errors: expected=%q, got=%q", expected, got) } } + + sysctls = make([]core.Sysctl, len(duplicates)) + for i, sysctl := range duplicates { + sysctls[i].Name = sysctl + } + errs = validateSysctls(sysctls, field.NewPath("foo")) + if len(errs) != 1 { + t.Errorf("unexpected validation errors: %v", errs) + } else if errs[0].Type != field.ErrorTypeDuplicate { + t.Errorf("expected error type %v, got %v", field.ErrorTypeDuplicate, errs[0].Type) + } } func newNodeNameEndpoint(nodeName string) *core.Endpoints { @@ -12681,17 +12944,17 @@ func TestValidateOrSetClientIPAffinityConfig(t *testing.T) { successCases := map[string]*core.SessionAffinityConfig{ "non-empty config, valid timeout: 1": { ClientIP: &core.ClientIPConfig{ - TimeoutSeconds: newInt32(1), + TimeoutSeconds: utilpointer.Int32Ptr(1), }, }, "non-empty config, valid timeout: core.MaxClientIPServiceAffinitySeconds-1": { ClientIP: &core.ClientIPConfig{ - TimeoutSeconds: newInt32(int(core.MaxClientIPServiceAffinitySeconds - 1)), + TimeoutSeconds: utilpointer.Int32Ptr(core.MaxClientIPServiceAffinitySeconds - 1), }, }, "non-empty config, valid timeout: core.MaxClientIPServiceAffinitySeconds": { ClientIP: &core.ClientIPConfig{ - TimeoutSeconds: newInt32(int(core.MaxClientIPServiceAffinitySeconds)), + TimeoutSeconds: utilpointer.Int32Ptr(core.MaxClientIPServiceAffinitySeconds), }, }, } @@ -12714,17 +12977,17 @@ func TestValidateOrSetClientIPAffinityConfig(t *testing.T) { }, "non-empty config, invalid timeout: core.MaxClientIPServiceAffinitySeconds+1": { ClientIP: &core.ClientIPConfig{ - TimeoutSeconds: newInt32(int(core.MaxClientIPServiceAffinitySeconds + 1)), + TimeoutSeconds: utilpointer.Int32Ptr(core.MaxClientIPServiceAffinitySeconds + 1), }, }, "non-empty config, invalid timeout: -1": { ClientIP: &core.ClientIPConfig{ - TimeoutSeconds: newInt32(-1), + TimeoutSeconds: utilpointer.Int32Ptr(-1), }, }, "non-empty config, invalid timeout: 0": { ClientIP: &core.ClientIPConfig{ - TimeoutSeconds: newInt32(0), + TimeoutSeconds: utilpointer.Int32Ptr(0), }, }, } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/core/zz_generated.deepcopy.go index 35225755d..3331f6e1f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -380,9 +380,43 @@ func (in *CephFSVolumeSource) DeepCopy() *CephFSVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CinderPersistentVolumeSource) DeepCopyInto(out *CinderPersistentVolumeSource) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(SecretReference) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CinderPersistentVolumeSource. +func (in *CinderPersistentVolumeSource) DeepCopy() *CinderPersistentVolumeSource { + if in == nil { + return nil + } + out := new(CinderPersistentVolumeSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CinderVolumeSource) DeepCopyInto(out *CinderVolumeSource) { *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(LocalObjectReference) + **out = **in + } + } return } @@ -631,6 +665,22 @@ func (in *ConfigMapList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigMapNodeConfigSource) DeepCopyInto(out *ConfigMapNodeConfigSource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapNodeConfigSource. +func (in *ConfigMapNodeConfigSource) DeepCopy() *ConfigMapNodeConfigSource { + if in == nil { + return nil + } + out := new(ConfigMapNodeConfigSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConfigMapProjection) DeepCopyInto(out *ConfigMapProjection) { *out = *in @@ -965,67 +1015,6 @@ func (in *DaemonEndpoint) DeepCopy() *DaemonEndpoint { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DeleteOptions) DeepCopyInto(out *DeleteOptions) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.GracePeriodSeconds != nil { - in, out := &in.GracePeriodSeconds, &out.GracePeriodSeconds - if *in == nil { - *out = nil - } else { - *out = new(int64) - **out = **in - } - } - if in.Preconditions != nil { - in, out := &in.Preconditions, &out.Preconditions - if *in == nil { - *out = nil - } else { - *out = new(Preconditions) - (*in).DeepCopyInto(*out) - } - } - if in.OrphanDependents != nil { - in, out := &in.OrphanDependents, &out.OrphanDependents - if *in == nil { - *out = nil - } else { - *out = new(bool) - **out = **in - } - } - if in.PropagationPolicy != nil { - in, out := &in.PropagationPolicy, &out.PropagationPolicy - if *in == nil { - *out = nil - } else { - *out = new(DeletionPropagation) - **out = **in - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeleteOptions. -func (in *DeleteOptions) DeepCopy() *DeleteOptions { - if in == nil { - return nil - } - out := new(DeleteOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *DeleteOptions) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DownwardAPIProjection) DeepCopyInto(out *DownwardAPIProjection) { *out = *in @@ -2145,50 +2134,6 @@ func (in *List) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ListOptions) DeepCopyInto(out *ListOptions) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.LabelSelector == nil { - out.LabelSelector = nil - } else { - out.LabelSelector = in.LabelSelector.DeepCopySelector() - } - if in.FieldSelector == nil { - out.FieldSelector = nil - } else { - out.FieldSelector = in.FieldSelector.DeepCopySelector() - } - if in.TimeoutSeconds != nil { - in, out := &in.TimeoutSeconds, &out.TimeoutSeconds - if *in == nil { - *out = nil - } else { - *out = new(int64) - **out = **in - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListOptions. -func (in *ListOptions) DeepCopy() *ListOptions { - if in == nil { - return nil - } - out := new(ListOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ListOptions) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancerIngress) DeepCopyInto(out *LoadBalancerIngress) { *out = *in @@ -2469,13 +2414,12 @@ func (in *NodeCondition) DeepCopy() *NodeCondition { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeConfigSource) DeepCopyInto(out *NodeConfigSource) { *out = *in - out.TypeMeta = in.TypeMeta - if in.ConfigMapRef != nil { - in, out := &in.ConfigMapRef, &out.ConfigMapRef + if in.ConfigMap != nil { + in, out := &in.ConfigMap, &out.ConfigMap if *in == nil { *out = nil } else { - *out = new(ObjectReference) + *out = new(ConfigMapNodeConfigSource) **out = **in } } @@ -2492,12 +2436,47 @@ func (in *NodeConfigSource) DeepCopy() *NodeConfigSource { return out } -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NodeConfigSource) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeConfigStatus) DeepCopyInto(out *NodeConfigStatus) { + *out = *in + if in.Assigned != nil { + in, out := &in.Assigned, &out.Assigned + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigSource) + (*in).DeepCopyInto(*out) + } } - return nil + if in.Active != nil { + in, out := &in.Active, &out.Active + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigSource) + (*in).DeepCopyInto(*out) + } + } + if in.LastKnownGood != nil { + in, out := &in.LastKnownGood, &out.LastKnownGood + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigSource) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeConfigStatus. +func (in *NodeConfigStatus) DeepCopy() *NodeConfigStatus { + if in == nil { + return nil + } + out := new(NodeConfigStatus) + in.DeepCopyInto(out) + return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -2652,6 +2631,13 @@ func (in *NodeSelectorTerm) DeepCopyInto(out *NodeSelectorTerm) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.MatchFields != nil { + in, out := &in.MatchFields, &out.MatchFields + *out = make([]NodeSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -2745,6 +2731,15 @@ func (in *NodeStatus) DeepCopyInto(out *NodeStatus) { *out = make([]AttachedVolume, len(*in)) copy(*out, *in) } + if in.Config != nil { + in, out := &in.Config, &out.Config + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigStatus) + (*in).DeepCopyInto(*out) + } + } return } @@ -2790,75 +2785,6 @@ func (in *ObjectFieldSelector) DeepCopy() *ObjectFieldSelector { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ObjectMeta) DeepCopyInto(out *ObjectMeta) { - *out = *in - in.CreationTimestamp.DeepCopyInto(&out.CreationTimestamp) - if in.DeletionTimestamp != nil { - in, out := &in.DeletionTimestamp, &out.DeletionTimestamp - if *in == nil { - *out = nil - } else { - *out = (*in).DeepCopy() - } - } - if in.DeletionGracePeriodSeconds != nil { - in, out := &in.DeletionGracePeriodSeconds, &out.DeletionGracePeriodSeconds - if *in == nil { - *out = nil - } else { - *out = new(int64) - **out = **in - } - } - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Annotations != nil { - in, out := &in.Annotations, &out.Annotations - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.OwnerReferences != nil { - in, out := &in.OwnerReferences, &out.OwnerReferences - *out = make([]v1.OwnerReference, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Initializers != nil { - in, out := &in.Initializers, &out.Initializers - if *in == nil { - *out = nil - } else { - *out = new(v1.Initializers) - (*in).DeepCopyInto(*out) - } - } - if in.Finalizers != nil { - in, out := &in.Finalizers, &out.Finalizers - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectMeta. -func (in *ObjectMeta) DeepCopy() *ObjectMeta { - if in == nil { - return nil - } - out := new(ObjectMeta) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { *out = *in @@ -3212,8 +3138,8 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) { if *in == nil { *out = nil } else { - *out = new(CinderVolumeSource) - **out = **in + *out = new(CinderPersistentVolumeSource) + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { @@ -3827,6 +3753,22 @@ func (in *PodProxyOptions) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodReadinessGate) DeepCopyInto(out *PodReadinessGate) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodReadinessGate. +func (in *PodReadinessGate) DeepCopy() *PodReadinessGate { + if in == nil { + return nil + } + out := new(PodReadinessGate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { *out = *in @@ -3889,6 +3831,11 @@ func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { **out = **in } } + if in.Sysctls != nil { + in, out := &in.Sysctls, &out.Sysctls + *out = make([]Sysctl, len(*in)) + copy(*out, *in) + } return } @@ -4040,6 +3987,11 @@ func (in *PodSpec) DeepCopyInto(out *PodSpec) { (*in).DeepCopyInto(*out) } } + if in.ReadinessGates != nil { + in, out := &in.ReadinessGates, &out.ReadinessGates + *out = make([]PodReadinessGate, len(*in)) + copy(*out, *in) + } return } @@ -4683,6 +4635,15 @@ func (in *ResourceQuotaSpec) DeepCopyInto(out *ResourceQuotaSpec) { *out = make([]ResourceQuotaScope, len(*in)) copy(*out, *in) } + if in.ScopeSelector != nil { + in, out := &in.ScopeSelector, &out.ScopeSelector + if *in == nil { + *out = nil + } else { + *out = new(ScopeSelector) + (*in).DeepCopyInto(*out) + } + } return } @@ -4822,6 +4783,50 @@ func (in *ScaleIOVolumeSource) DeepCopy() *ScaleIOVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopeSelector) DeepCopyInto(out *ScopeSelector) { + *out = *in + if in.MatchExpressions != nil { + in, out := &in.MatchExpressions, &out.MatchExpressions + *out = make([]ScopedResourceSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopeSelector. +func (in *ScopeSelector) DeepCopy() *ScopeSelector { + if in == nil { + return nil + } + out := new(ScopeSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopedResourceSelectorRequirement) DeepCopyInto(out *ScopedResourceSelectorRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopedResourceSelectorRequirement. +func (in *ScopedResourceSelectorRequirement) DeepCopy() *ScopedResourceSelectorRequirement { + if in == nil { + return nil + } + out := new(ScopedResourceSelectorRequirement) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Secret) DeepCopyInto(out *Secret) { *out = *in @@ -5255,6 +5260,22 @@ func (in *ServiceAccountList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAccountTokenProjection) DeepCopyInto(out *ServiceAccountTokenProjection) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountTokenProjection. +func (in *ServiceAccountTokenProjection) DeepCopy() *ServiceAccountTokenProjection { + if in == nil { + return nil + } + out := new(ServiceAccountTokenProjection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceList) DeepCopyInto(out *ServiceList) { *out = *in @@ -5551,6 +5572,50 @@ func (in *Toleration) DeepCopy() *Toleration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorLabelRequirement) DeepCopyInto(out *TopologySelectorLabelRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorLabelRequirement. +func (in *TopologySelectorLabelRequirement) DeepCopy() *TopologySelectorLabelRequirement { + if in == nil { + return nil + } + out := new(TopologySelectorLabelRequirement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorTerm) DeepCopyInto(out *TopologySelectorTerm) { + *out = *in + if in.MatchLabelExpressions != nil { + in, out := &in.MatchLabelExpressions, &out.MatchLabelExpressions + *out = make([]TopologySelectorLabelRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorTerm. +func (in *TopologySelectorTerm) DeepCopy() *TopologySelectorTerm { + if in == nil { + return nil + } + out := new(TopologySelectorTerm) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Volume) DeepCopyInto(out *Volume) { *out = *in @@ -5664,6 +5729,15 @@ func (in *VolumeProjection) DeepCopyInto(out *VolumeProjection) { (*in).DeepCopyInto(*out) } } + if in.ServiceAccountToken != nil { + in, out := &in.ServiceAccountToken, &out.ServiceAccountToken + if *in == nil { + *out = nil + } else { + *out = new(ServiceAccountTokenProjection) + **out = **in + } + } return } @@ -5803,7 +5877,7 @@ func (in *VolumeSource) DeepCopyInto(out *VolumeSource) { *out = nil } else { *out = new(CinderVolumeSource) - **out = **in + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/events/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/events/install/BUILD index 01c67e2ed..a3150f73f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/events/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/events/install/BUILD @@ -9,9 +9,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/events:go_default_library", "//pkg/apis/events/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/events/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/events/install/install.go index 9dbc1b4d4..28ac59e91 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/events/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/events/install/install.go @@ -19,30 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/events" "k8s.io/kubernetes/pkg/apis/events/v1beta1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: events.GroupName, - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: events.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(events.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/events/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/events/v1beta1/zz_generated.conversion.go index 94a67e1bd..f4961ba74 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/events/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/events/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/events/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/events/v1beta1/zz_generated.defaults.go index 544e569dc..73e63fc11 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/events/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/events/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/extensions/BUILD index eecd17571..511011b5e 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/BUILD @@ -3,20 +3,12 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["helpers_test.go"], - embed = [":go_default_library"], ) go_library( name = "go_default_library", srcs = [ "doc.go", - "helpers.go", "register.go", "types.go", "zz_generated.deepcopy.go", @@ -26,6 +18,7 @@ go_library( "//pkg/apis/autoscaling:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/networking:go_default_library", + "//pkg/apis/policy: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/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/fuzzer/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/extensions/fuzzer/BUILD index 712d0f4e6..4f4bf9cce 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/fuzzer/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/fuzzer/BUILD @@ -12,6 +12,7 @@ go_library( deps = [ "//pkg/apis/extensions:go_default_library", "//vendor/github.com/google/gofuzz:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/fuzzer/fuzzer.go index 006d04f9f..277a327c9 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/fuzzer/fuzzer.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/fuzzer/fuzzer.go @@ -21,6 +21,7 @@ import ( fuzz "github.com/google/gofuzz" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/kubernetes/pkg/apis/extensions" @@ -29,6 +30,17 @@ import ( // Funcs returns the fuzzer functions for the extensions api group. var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ + func(j *extensions.Deployment, c fuzz.Continue) { + c.FuzzNoCustom(j) + + // match defaulting + if j.Spec.Selector == nil { + j.Spec.Selector = &metav1.LabelSelector{MatchLabels: j.Spec.Template.Labels} + } + if len(j.Labels) == 0 { + j.Labels = j.Spec.Template.Labels + } + }, func(j *extensions.DeploymentSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // fuzz self without calling this function again rhl := int32(c.Rand.Int31()) @@ -54,33 +66,14 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { j.RollingUpdate = &rollingUpdate } }, - func(psp *extensions.PodSecurityPolicySpec, c fuzz.Continue) { - c.FuzzNoCustom(psp) // fuzz self without calling this function again - - runAsUserRules := []extensions.RunAsUserStrategy{ - extensions.RunAsUserStrategyMustRunAsNonRoot, - extensions.RunAsUserStrategyMustRunAs, - extensions.RunAsUserStrategyRunAsAny, - } - psp.RunAsUser.Rule = runAsUserRules[c.Rand.Intn(len(runAsUserRules))] - - seLinuxRules := []extensions.SELinuxStrategy{ - extensions.SELinuxStrategyMustRunAs, - extensions.SELinuxStrategyRunAsAny, - } - psp.SELinux.Rule = seLinuxRules[c.Rand.Intn(len(seLinuxRules))] - - supplementalGroupsRules := []extensions.SupplementalGroupsStrategyType{ - extensions.SupplementalGroupsStrategyRunAsAny, - extensions.SupplementalGroupsStrategyMustRunAs, - } - psp.SupplementalGroups.Rule = supplementalGroupsRules[c.Rand.Intn(len(supplementalGroupsRules))] + func(j *extensions.DaemonSet, c fuzz.Continue) { + c.FuzzNoCustom(j) - fsGroupRules := []extensions.FSGroupStrategyType{ - extensions.FSGroupStrategyMustRunAs, - extensions.FSGroupStrategyRunAsAny, + // match defaulter + j.Spec.Template.Generation = 0 + if len(j.ObjectMeta.Labels) == 0 { + j.ObjectMeta.Labels = j.Spec.Template.ObjectMeta.Labels } - psp.FSGroup.Rule = fsGroupRules[c.Rand.Intn(len(fsGroupRules))] }, func(j *extensions.DaemonSetSpec, c fuzz.Continue) { c.FuzzNoCustom(j) // fuzz self without calling this function again @@ -106,5 +99,16 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { j.RollingUpdate = &rollingUpdate } }, + func(j *extensions.ReplicaSet, c fuzz.Continue) { + c.FuzzNoCustom(j) + + // match defaulter + if j.Spec.Selector == nil { + j.Spec.Selector = &metav1.LabelSelector{MatchLabels: j.Spec.Template.Labels} + } + if len(j.Labels) == 0 { + j.Labels = j.Spec.Template.Labels + } + }, } } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/helpers.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/helpers.go deleted file mode 100644 index 27d3e23ad..000000000 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/helpers.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -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 extensions - -import ( - "strings" -) - -// SysctlsFromPodSecurityPolicyAnnotation parses an annotation value of the key -// SysctlsSecurityPolocyAnnotationKey into a slice of sysctls. An empty slice -// is returned if annotation is the empty string. -func SysctlsFromPodSecurityPolicyAnnotation(annotation string) ([]string, error) { - if len(annotation) == 0 { - return []string{}, nil - } - - return strings.Split(annotation, ","), nil -} - -// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls. -func PodAnnotationsFromSysctls(sysctls []string) string { - return strings.Join(sysctls, ",") -} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/helpers_test.go deleted file mode 100644 index 29ae139ec..000000000 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/helpers_test.go +++ /dev/null @@ -1,62 +0,0 @@ -/* -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 extensions - -import ( - "reflect" - "testing" -) - -func TestPodAnnotationsFromSysctls(t *testing.T) { - type Test struct { - sysctls []string - expectedValue string - } - for _, test := range []Test{ - {sysctls: []string{"a.b"}, expectedValue: "a.b"}, - {sysctls: []string{"a.b", "c.d"}, expectedValue: "a.b,c.d"}, - {sysctls: []string{"a.b", "a.b"}, expectedValue: "a.b,a.b"}, - {sysctls: []string{}, expectedValue: ""}, - {sysctls: nil, expectedValue: ""}, - } { - a := PodAnnotationsFromSysctls(test.sysctls) - if a != test.expectedValue { - t.Errorf("wrong value for %v: got=%q wanted=%q", test.sysctls, a, test.expectedValue) - } - } -} - -func TestSysctlsFromPodSecurityPolicyAnnotation(t *testing.T) { - type Test struct { - expectedValue []string - annotation string - } - for _, test := range []Test{ - {annotation: "a.b", expectedValue: []string{"a.b"}}, - {annotation: "a.b,c.d", expectedValue: []string{"a.b", "c.d"}}, - {annotation: "a.b,a.b", expectedValue: []string{"a.b", "a.b"}}, - {annotation: "", expectedValue: []string{}}, - } { - sysctls, err := SysctlsFromPodSecurityPolicyAnnotation(test.annotation) - if err != nil { - t.Errorf("error for %q: %v", test.annotation, err) - } - if !reflect.DeepEqual(sysctls, test.expectedValue) { - t.Errorf("wrong value for %q: got=%v wanted=%v", test.annotation, sysctls, test.expectedValue) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/extensions/install/BUILD index 886ce927a..89384d6ed 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/install/BUILD @@ -13,10 +13,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/install/install.go index dfa899101..c22ad5901 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/install/install.go @@ -19,32 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: extensions.GroupName, - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("PodSecurityPolicy"), - AddInternalObjectsToScheme: extensions.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(extensions.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/register.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/register.go index 48137fc69..84c2071ae 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/register.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/register.go @@ -21,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/networking" + "k8s.io/kubernetes/pkg/apis/policy" ) // GroupName is the group name use in this package @@ -58,8 +59,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &IngressList{}, &ReplicaSet{}, &ReplicaSetList{}, - &PodSecurityPolicy{}, - &PodSecurityPolicyList{}, + &policy.PodSecurityPolicy{}, + &policy.PodSecurityPolicyList{}, &autoscaling.Scale{}, &networking.NetworkPolicy{}, &networking.NetworkPolicyList{}, diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/types.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/types.go index e36972846..a2330c45d 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/types.go @@ -35,13 +35,6 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" ) -const ( - // SysctlsPodSecurityPolicyAnnotationKey represents the key of a whitelist of - // allowed safe and unsafe sysctls in a pod spec. It's a comma-separated list of plain sysctl - // names or sysctl patterns (which end in *). The string "*" matches all sysctls. - SysctlsPodSecurityPolicyAnnotationKey string = "security.alpha.kubernetes.io/sysctls" -) - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Dummy definition @@ -780,270 +773,3 @@ type ReplicaSetCondition struct { // +optional Message string } - -// +genclient -// +genclient:nonNamespaced -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// PodSecurityPolicy governs the ability to make requests that affect the SecurityContext -// that will be applied to a pod and container. -type PodSecurityPolicy struct { - metav1.TypeMeta - // +optional - metav1.ObjectMeta - - // Spec defines the policy enforced. - // +optional - Spec PodSecurityPolicySpec -} - -// PodSecurityPolicySpec defines the policy enforced. -type PodSecurityPolicySpec struct { - // Privileged determines if a pod can request to be run as privileged. - // +optional - Privileged bool - // DefaultAddCapabilities is the default set of capabilities that will be added to the container - // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. - // +optional - DefaultAddCapabilities []api.Capability - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These - // are required to be dropped and cannot be added. - // +optional - RequiredDropCapabilities []api.Capability - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. - // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. - // To allow all capabilities you may use '*'. - // +optional - AllowedCapabilities []api.Capability - // Volumes is a white list of allowed volume plugins. Empty indicates that all plugins - // may be used. - // +optional - Volumes []FSType - // HostNetwork determines if the policy allows the use of HostNetwork in the pod spec. - // +optional - HostNetwork bool - // HostPorts determines which host port ranges are allowed to be exposed. - // +optional - HostPorts []HostPortRange - // HostPID determines if the policy allows the use of HostPID in the pod spec. - // +optional - HostPID bool - // HostIPC determines if the policy allows the use of HostIPC in the pod spec. - // +optional - HostIPC bool - // SELinux is the strategy that will dictate the allowable labels that may be set. - SELinux SELinuxStrategyOptions - // RunAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. - RunAsUser RunAsUserStrategyOptions - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. - SupplementalGroups SupplementalGroupsStrategyOptions - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. - FSGroup FSGroupStrategyOptions - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file - // system. If the container specifically requests to run with a non-read only root file system - // the PSP should deny the pod. - // If set to false the container may run with a read only root file system if it wishes but it - // will not be forced to. - // +optional - ReadOnlyRootFilesystem bool - // DefaultAllowPrivilegeEscalation controls the default setting for whether a - // process can gain more privileges than its parent process. - // +optional - DefaultAllowPrivilegeEscalation *bool - // AllowPrivilegeEscalation determines if a pod can request to allow - // privilege escalation. If unspecified, defaults to true. - // +optional - AllowPrivilegeEscalation bool - // AllowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used. - // +optional - AllowedHostPaths []AllowedHostPath - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all - // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. - // +optional - AllowedFlexVolumes []AllowedFlexVolume -} - -// AllowedHostPath defines the host volume conditions that will be enabled by a policy -// for pods to use. It requires the path prefix to be defined. -type AllowedHostPath struct { - // PathPrefix is the path prefix that the host volume must match. - // PathPrefix does not support `*`. - // Trailing slashes are trimmed when validating the path prefix with a host path. - // - // Examples: - // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` - // `/foo` would not allow `/food` or `/etc/foo` - PathPrefix string -} - -// HostPortRange defines a range of host ports that will be enabled by a policy -// for pods to use. It requires both the start and end to be defined. -type HostPortRange struct { - // Min is the start of the range, inclusive. - Min int32 - // Max is the end of the range, inclusive. - Max int32 -} - -// AllowAllCapabilities can be used as a value for the PodSecurityPolicy.AllowAllCapabilities -// field and means that any capabilities are allowed to be requested. -var AllowAllCapabilities api.Capability = "*" - -// FSType gives strong typing to different file systems that are used by volumes. -type FSType string - -var ( - AzureFile FSType = "azureFile" - Flocker FSType = "flocker" - FlexVolume FSType = "flexVolume" - HostPath FSType = "hostPath" - EmptyDir FSType = "emptyDir" - GCEPersistentDisk FSType = "gcePersistentDisk" - AWSElasticBlockStore FSType = "awsElasticBlockStore" - GitRepo FSType = "gitRepo" - Secret FSType = "secret" - NFS FSType = "nfs" - ISCSI FSType = "iscsi" - Glusterfs FSType = "glusterfs" - PersistentVolumeClaim FSType = "persistentVolumeClaim" - RBD FSType = "rbd" - Cinder FSType = "cinder" - CephFS FSType = "cephFS" - DownwardAPI FSType = "downwardAPI" - FC FSType = "fc" - ConfigMap FSType = "configMap" - VsphereVolume FSType = "vsphereVolume" - Quobyte FSType = "quobyte" - AzureDisk FSType = "azureDisk" - PhotonPersistentDisk FSType = "photonPersistentDisk" - StorageOS FSType = "storageos" - Projected FSType = "projected" - PortworxVolume FSType = "portworxVolume" - ScaleIO FSType = "scaleIO" - CSI FSType = "csi" - All FSType = "*" -) - -// AllowedFlexVolume represents a single Flexvolume that is allowed to be used. -type AllowedFlexVolume struct { - // Driver is the name of the Flexvolume driver. - Driver string -} - -// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. -type SELinuxStrategyOptions struct { - // Rule is the strategy that will dictate the allowable labels that may be set. - Rule SELinuxStrategy - // seLinuxOptions required to run as; required for MustRunAs - // More info: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#selinux - // +optional - SELinuxOptions *api.SELinuxOptions -} - -// SELinuxStrategy denotes strategy types for generating SELinux options for a -// Security. -type SELinuxStrategy string - -const ( - // container must have SELinux labels of X applied. - SELinuxStrategyMustRunAs SELinuxStrategy = "MustRunAs" - // container may make requests for any SELinux context labels. - SELinuxStrategyRunAsAny SELinuxStrategy = "RunAsAny" -) - -// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. -type RunAsUserStrategyOptions struct { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. - Rule RunAsUserStrategy - // Ranges are the allowed ranges of uids that may be used. - // +optional - Ranges []UserIDRange -} - -// UserIDRange provides a min/max of an allowed range of UserIDs. -type UserIDRange struct { - // Min is the start of the range, inclusive. - Min int64 - // Max is the end of the range, inclusive. - Max int64 -} - -// GroupIDRange provides a min/max of an allowed range of GroupIDs. -type GroupIDRange struct { - // Min is the start of the range, inclusive. - Min int64 - // Max is the end of the range, inclusive. - Max int64 -} - -// RunAsUserStrategy denotes strategy types for generating RunAsUser values for a -// SecurityContext. -type RunAsUserStrategy string - -const ( - // container must run as a particular uid. - RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs" - // container must run as a non-root uid - RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot" - // container may make requests for any uid. - RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny" -) - -// FSGroupStrategyOptions defines the strategy type and options used to create the strategy. -type FSGroupStrategyOptions struct { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. - // +optional - Rule FSGroupStrategyType - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. - // +optional - Ranges []GroupIDRange -} - -// FSGroupStrategyType denotes strategy types for generating FSGroup values for a -// SecurityContext -type FSGroupStrategyType string - -const ( - // container must have FSGroup of X applied. - FSGroupStrategyMustRunAs FSGroupStrategyType = "MustRunAs" - // container may make requests for any FSGroup labels. - FSGroupStrategyRunAsAny FSGroupStrategyType = "RunAsAny" -) - -// SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. -type SupplementalGroupsStrategyOptions struct { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. - // +optional - Rule SupplementalGroupsStrategyType - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. - // +optional - Ranges []GroupIDRange -} - -// SupplementalGroupsStrategyType denotes strategy types for determining valid supplemental -// groups for a SecurityContext. -type SupplementalGroupsStrategyType string - -const ( - // container must run as a particular gid. - SupplementalGroupsStrategyMustRunAs SupplementalGroupsStrategyType = "MustRunAs" - // container may make requests for any gid. - SupplementalGroupsStrategyRunAsAny SupplementalGroupsStrategyType = "RunAsAny" -) - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// PodSecurityPolicyList is a list of PodSecurityPolicy objects. -type PodSecurityPolicyList struct { - metav1.TypeMeta - // +optional - metav1.ListMeta - - Items []PodSecurityPolicy -} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/BUILD index cf1f13f4a..10e903916 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/BUILD @@ -23,6 +23,7 @@ go_library( "//pkg/apis/core/v1:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/apis/networking:go_default_library", + "//pkg/apis/policy: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/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion.go index d236a415e..ce7b78ae2 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion.go @@ -61,7 +61,6 @@ func addConversionFuncs(scheme *runtime.Scheme) error { Convert_networking_NetworkPolicyPort_To_v1beta1_NetworkPolicyPort, Convert_v1beta1_NetworkPolicySpec_To_networking_NetworkPolicySpec, Convert_networking_NetworkPolicySpec_To_v1beta1_NetworkPolicySpec, - Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec, Convert_v1beta1_IPBlock_To_networking_IPBlock, Convert_networking_IPBlock_To_v1beta1_IPBlock, Convert_networking_NetworkPolicyEgressRule_To_v1beta1_NetworkPolicyEgressRule, @@ -503,7 +502,3 @@ func Convert_networking_NetworkPolicyList_To_v1beta1_NetworkPolicyList(in *netwo } return nil } - -func Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *extensions.PodSecurityPolicySpec, out *extensionsv1beta1.PodSecurityPolicySpec, s conversion.Scope) error { - return autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in, out, s) -} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/doc.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/doc.go index da219b9d2..96f579d1e 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/doc.go @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/policy // +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/extensions // +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/autoscaling // +k8s:conversion-gen-external-types=k8s.io/api/extensions/v1beta1 diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/zz_generated.conversion.go index 9cefeb8d6..2eb34cb40 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,6 +32,7 @@ import ( core "k8s.io/kubernetes/pkg/apis/core" core_v1 "k8s.io/kubernetes/pkg/apis/core/v1" extensions "k8s.io/kubernetes/pkg/apis/extensions" + policy "k8s.io/kubernetes/pkg/apis/policy" ) func init() { @@ -42,10 +43,10 @@ func init() { // Public to allow building arbitrary schemes. func RegisterConversions(scheme *runtime.Scheme) error { return scheme.AddGeneratedConversionFuncs( - Convert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume, - Convert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume, - Convert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath, - Convert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath, + Convert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume, + Convert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume, + Convert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath, + Convert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath, Convert_v1beta1_CustomMetricCurrentStatus_To_extensions_CustomMetricCurrentStatus, Convert_extensions_CustomMetricCurrentStatus_To_v1beta1_CustomMetricCurrentStatus, Convert_v1beta1_CustomMetricCurrentStatusList_To_extensions_CustomMetricCurrentStatusList, @@ -80,14 +81,16 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_extensions_DeploymentStatus_To_v1beta1_DeploymentStatus, Convert_v1beta1_DeploymentStrategy_To_extensions_DeploymentStrategy, Convert_extensions_DeploymentStrategy_To_v1beta1_DeploymentStrategy, - Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions, - Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions, + Convert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions, + Convert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions, Convert_v1beta1_HTTPIngressPath_To_extensions_HTTPIngressPath, Convert_extensions_HTTPIngressPath_To_v1beta1_HTTPIngressPath, Convert_v1beta1_HTTPIngressRuleValue_To_extensions_HTTPIngressRuleValue, Convert_extensions_HTTPIngressRuleValue_To_v1beta1_HTTPIngressRuleValue, - Convert_v1beta1_HostPortRange_To_extensions_HostPortRange, - Convert_extensions_HostPortRange_To_v1beta1_HostPortRange, + Convert_v1beta1_HostPortRange_To_policy_HostPortRange, + Convert_policy_HostPortRange_To_v1beta1_HostPortRange, + Convert_v1beta1_IDRange_To_policy_IDRange, + Convert_policy_IDRange_To_v1beta1_IDRange, Convert_v1beta1_Ingress_To_extensions_Ingress, Convert_extensions_Ingress_To_v1beta1_Ingress, Convert_v1beta1_IngressBackend_To_extensions_IngressBackend, @@ -104,12 +107,12 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_extensions_IngressStatus_To_v1beta1_IngressStatus, Convert_v1beta1_IngressTLS_To_extensions_IngressTLS, Convert_extensions_IngressTLS_To_v1beta1_IngressTLS, - Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy, - Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy, - Convert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList, - Convert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList, - Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec, - Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec, + Convert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy, + Convert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy, + Convert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList, + Convert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList, + Convert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec, + Convert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec, Convert_v1beta1_ReplicaSet_To_extensions_ReplicaSet, Convert_extensions_ReplicaSet_To_v1beta1_ReplicaSet, Convert_v1beta1_ReplicaSetCondition_To_extensions_ReplicaSetCondition, @@ -128,59 +131,61 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_extensions_RollingUpdateDaemonSet_To_v1beta1_RollingUpdateDaemonSet, Convert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment, Convert_extensions_RollingUpdateDeployment_To_v1beta1_RollingUpdateDeployment, - Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions, - Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions, - Convert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions, - Convert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions, + Convert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions, + Convert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions, + Convert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions, + Convert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions, Convert_v1beta1_Scale_To_autoscaling_Scale, Convert_autoscaling_Scale_To_v1beta1_Scale, Convert_v1beta1_ScaleSpec_To_autoscaling_ScaleSpec, Convert_autoscaling_ScaleSpec_To_v1beta1_ScaleSpec, Convert_v1beta1_ScaleStatus_To_autoscaling_ScaleStatus, Convert_autoscaling_ScaleStatus_To_v1beta1_ScaleStatus, - Convert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions, - Convert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions, + Convert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions, + Convert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions, ) } -func autoConvert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume(in *v1beta1.AllowedFlexVolume, out *extensions.AllowedFlexVolume, s conversion.Scope) error { +func autoConvert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume(in *v1beta1.AllowedFlexVolume, out *policy.AllowedFlexVolume, s conversion.Scope) error { out.Driver = in.Driver return nil } -// Convert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume is an autogenerated conversion function. -func Convert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume(in *v1beta1.AllowedFlexVolume, out *extensions.AllowedFlexVolume, s conversion.Scope) error { - return autoConvert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume(in, out, s) +// Convert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume is an autogenerated conversion function. +func Convert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume(in *v1beta1.AllowedFlexVolume, out *policy.AllowedFlexVolume, s conversion.Scope) error { + return autoConvert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume(in, out, s) } -func autoConvert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *extensions.AllowedFlexVolume, out *v1beta1.AllowedFlexVolume, s conversion.Scope) error { +func autoConvert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *policy.AllowedFlexVolume, out *v1beta1.AllowedFlexVolume, s conversion.Scope) error { out.Driver = in.Driver return nil } -// Convert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume is an autogenerated conversion function. -func Convert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *extensions.AllowedFlexVolume, out *v1beta1.AllowedFlexVolume, s conversion.Scope) error { - return autoConvert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in, out, s) +// Convert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume is an autogenerated conversion function. +func Convert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *policy.AllowedFlexVolume, out *v1beta1.AllowedFlexVolume, s conversion.Scope) error { + return autoConvert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in, out, s) } -func autoConvert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath(in *v1beta1.AllowedHostPath, out *extensions.AllowedHostPath, s conversion.Scope) error { +func autoConvert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in *v1beta1.AllowedHostPath, out *policy.AllowedHostPath, s conversion.Scope) error { out.PathPrefix = in.PathPrefix + out.ReadOnly = in.ReadOnly return nil } -// Convert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath is an autogenerated conversion function. -func Convert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath(in *v1beta1.AllowedHostPath, out *extensions.AllowedHostPath, s conversion.Scope) error { - return autoConvert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath(in, out, s) +// Convert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath is an autogenerated conversion function. +func Convert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in *v1beta1.AllowedHostPath, out *policy.AllowedHostPath, s conversion.Scope) error { + return autoConvert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in, out, s) } -func autoConvert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath(in *extensions.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { +func autoConvert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath(in *policy.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { out.PathPrefix = in.PathPrefix + out.ReadOnly = in.ReadOnly return nil } -// Convert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath is an autogenerated conversion function. -func Convert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath(in *extensions.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { - return autoConvert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath(in, out, s) +// Convert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath is an autogenerated conversion function. +func Convert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath(in *policy.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { + return autoConvert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath(in, out, s) } func autoConvert_v1beta1_CustomMetricCurrentStatus_To_extensions_CustomMetricCurrentStatus(in *v1beta1.CustomMetricCurrentStatus, out *extensions.CustomMetricCurrentStatus, s conversion.Scope) error { @@ -715,26 +720,26 @@ func autoConvert_extensions_DeploymentStrategy_To_v1beta1_DeploymentStrategy(in return nil } -func autoConvert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(in *v1beta1.FSGroupStrategyOptions, out *extensions.FSGroupStrategyOptions, s conversion.Scope) error { - out.Rule = extensions.FSGroupStrategyType(in.Rule) - out.Ranges = *(*[]extensions.GroupIDRange)(unsafe.Pointer(&in.Ranges)) +func autoConvert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions(in *v1beta1.FSGroupStrategyOptions, out *policy.FSGroupStrategyOptions, s conversion.Scope) error { + out.Rule = policy.FSGroupStrategyType(in.Rule) + out.Ranges = *(*[]policy.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions is an autogenerated conversion function. -func Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(in *v1beta1.FSGroupStrategyOptions, out *extensions.FSGroupStrategyOptions, s conversion.Scope) error { - return autoConvert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(in, out, s) +// Convert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions is an autogenerated conversion function. +func Convert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions(in *v1beta1.FSGroupStrategyOptions, out *policy.FSGroupStrategyOptions, s conversion.Scope) error { + return autoConvert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions(in, out, s) } -func autoConvert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in *extensions.FSGroupStrategyOptions, out *v1beta1.FSGroupStrategyOptions, s conversion.Scope) error { +func autoConvert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in *policy.FSGroupStrategyOptions, out *v1beta1.FSGroupStrategyOptions, s conversion.Scope) error { out.Rule = v1beta1.FSGroupStrategyType(in.Rule) out.Ranges = *(*[]v1beta1.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions is an autogenerated conversion function. -func Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in *extensions.FSGroupStrategyOptions, out *v1beta1.FSGroupStrategyOptions, s conversion.Scope) error { - return autoConvert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in, out, s) +// Convert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions is an autogenerated conversion function. +func Convert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in *policy.FSGroupStrategyOptions, out *v1beta1.FSGroupStrategyOptions, s conversion.Scope) error { + return autoConvert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in, out, s) } func autoConvert_v1beta1_HTTPIngressPath_To_extensions_HTTPIngressPath(in *v1beta1.HTTPIngressPath, out *extensions.HTTPIngressPath, s conversion.Scope) error { @@ -783,26 +788,48 @@ func Convert_extensions_HTTPIngressRuleValue_To_v1beta1_HTTPIngressRuleValue(in return autoConvert_extensions_HTTPIngressRuleValue_To_v1beta1_HTTPIngressRuleValue(in, out, s) } -func autoConvert_v1beta1_HostPortRange_To_extensions_HostPortRange(in *v1beta1.HostPortRange, out *extensions.HostPortRange, s conversion.Scope) error { +func autoConvert_v1beta1_HostPortRange_To_policy_HostPortRange(in *v1beta1.HostPortRange, out *policy.HostPortRange, s conversion.Scope) error { out.Min = in.Min out.Max = in.Max return nil } -// Convert_v1beta1_HostPortRange_To_extensions_HostPortRange is an autogenerated conversion function. -func Convert_v1beta1_HostPortRange_To_extensions_HostPortRange(in *v1beta1.HostPortRange, out *extensions.HostPortRange, s conversion.Scope) error { - return autoConvert_v1beta1_HostPortRange_To_extensions_HostPortRange(in, out, s) +// Convert_v1beta1_HostPortRange_To_policy_HostPortRange is an autogenerated conversion function. +func Convert_v1beta1_HostPortRange_To_policy_HostPortRange(in *v1beta1.HostPortRange, out *policy.HostPortRange, s conversion.Scope) error { + return autoConvert_v1beta1_HostPortRange_To_policy_HostPortRange(in, out, s) } -func autoConvert_extensions_HostPortRange_To_v1beta1_HostPortRange(in *extensions.HostPortRange, out *v1beta1.HostPortRange, s conversion.Scope) error { +func autoConvert_policy_HostPortRange_To_v1beta1_HostPortRange(in *policy.HostPortRange, out *v1beta1.HostPortRange, s conversion.Scope) error { out.Min = in.Min out.Max = in.Max return nil } -// Convert_extensions_HostPortRange_To_v1beta1_HostPortRange is an autogenerated conversion function. -func Convert_extensions_HostPortRange_To_v1beta1_HostPortRange(in *extensions.HostPortRange, out *v1beta1.HostPortRange, s conversion.Scope) error { - return autoConvert_extensions_HostPortRange_To_v1beta1_HostPortRange(in, out, s) +// Convert_policy_HostPortRange_To_v1beta1_HostPortRange is an autogenerated conversion function. +func Convert_policy_HostPortRange_To_v1beta1_HostPortRange(in *policy.HostPortRange, out *v1beta1.HostPortRange, s conversion.Scope) error { + return autoConvert_policy_HostPortRange_To_v1beta1_HostPortRange(in, out, s) +} + +func autoConvert_v1beta1_IDRange_To_policy_IDRange(in *v1beta1.IDRange, out *policy.IDRange, s conversion.Scope) error { + out.Min = in.Min + out.Max = in.Max + return nil +} + +// Convert_v1beta1_IDRange_To_policy_IDRange is an autogenerated conversion function. +func Convert_v1beta1_IDRange_To_policy_IDRange(in *v1beta1.IDRange, out *policy.IDRange, s conversion.Scope) error { + return autoConvert_v1beta1_IDRange_To_policy_IDRange(in, out, s) +} + +func autoConvert_policy_IDRange_To_v1beta1_IDRange(in *policy.IDRange, out *v1beta1.IDRange, s conversion.Scope) error { + out.Min = in.Min + out.Max = in.Max + return nil +} + +// Convert_policy_IDRange_To_v1beta1_IDRange is an autogenerated conversion function. +func Convert_policy_IDRange_To_v1beta1_IDRange(in *policy.IDRange, out *v1beta1.IDRange, s conversion.Scope) error { + return autoConvert_policy_IDRange_To_v1beta1_IDRange(in, out, s) } func autoConvert_v1beta1_Ingress_To_extensions_Ingress(in *v1beta1.Ingress, out *extensions.Ingress, s conversion.Scope) error { @@ -999,39 +1026,39 @@ func Convert_extensions_IngressTLS_To_v1beta1_IngressTLS(in *extensions.IngressT return autoConvert_extensions_IngressTLS_To_v1beta1_IngressTLS(in, out, s) } -func autoConvert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(in *v1beta1.PodSecurityPolicy, out *extensions.PodSecurityPolicy, s conversion.Scope) error { +func autoConvert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy(in *v1beta1.PodSecurityPolicy, out *policy.PodSecurityPolicy, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy is an autogenerated conversion function. -func Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(in *v1beta1.PodSecurityPolicy, out *extensions.PodSecurityPolicy, s conversion.Scope) error { - return autoConvert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(in, out, s) +// Convert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy is an autogenerated conversion function. +func Convert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy(in *v1beta1.PodSecurityPolicy, out *policy.PodSecurityPolicy, s conversion.Scope) error { + return autoConvert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy(in, out, s) } -func autoConvert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *extensions.PodSecurityPolicy, out *v1beta1.PodSecurityPolicy, s conversion.Scope) error { +func autoConvert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *policy.PodSecurityPolicy, out *v1beta1.PodSecurityPolicy, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy is an autogenerated conversion function. -func Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *extensions.PodSecurityPolicy, out *v1beta1.PodSecurityPolicy, s conversion.Scope) error { - return autoConvert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in, out, s) +// Convert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy is an autogenerated conversion function. +func Convert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *policy.PodSecurityPolicy, out *v1beta1.PodSecurityPolicy, s conversion.Scope) error { + return autoConvert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in, out, s) } -func autoConvert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList(in *v1beta1.PodSecurityPolicyList, out *extensions.PodSecurityPolicyList, s conversion.Scope) error { +func autoConvert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList(in *v1beta1.PodSecurityPolicyList, out *policy.PodSecurityPolicyList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]extensions.PodSecurityPolicy, len(*in)) + *out = make([]policy.PodSecurityPolicy, len(*in)) for i := range *in { - if err := Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1041,18 +1068,18 @@ func autoConvert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyLi return nil } -// Convert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList is an autogenerated conversion function. -func Convert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList(in *v1beta1.PodSecurityPolicyList, out *extensions.PodSecurityPolicyList, s conversion.Scope) error { - return autoConvert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList(in, out, s) +// Convert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList is an autogenerated conversion function. +func Convert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList(in *v1beta1.PodSecurityPolicyList, out *policy.PodSecurityPolicyList, s conversion.Scope) error { + return autoConvert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList(in, out, s) } -func autoConvert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *extensions.PodSecurityPolicyList, out *v1beta1.PodSecurityPolicyList, s conversion.Scope) error { +func autoConvert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *policy.PodSecurityPolicyList, out *v1beta1.PodSecurityPolicyList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]v1beta1.PodSecurityPolicy, len(*in)) for i := range *in { - if err := Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1062,31 +1089,31 @@ func autoConvert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyLi return nil } -// Convert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList is an autogenerated conversion function. -func Convert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *extensions.PodSecurityPolicyList, out *v1beta1.PodSecurityPolicyList, s conversion.Scope) error { - return autoConvert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in, out, s) +// Convert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList is an autogenerated conversion function. +func Convert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *policy.PodSecurityPolicyList, out *v1beta1.PodSecurityPolicyList, s conversion.Scope) error { + return autoConvert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in, out, s) } -func autoConvert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(in *v1beta1.PodSecurityPolicySpec, out *extensions.PodSecurityPolicySpec, s conversion.Scope) error { +func autoConvert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(in *v1beta1.PodSecurityPolicySpec, out *policy.PodSecurityPolicySpec, s conversion.Scope) error { out.Privileged = in.Privileged out.DefaultAddCapabilities = *(*[]core.Capability)(unsafe.Pointer(&in.DefaultAddCapabilities)) out.RequiredDropCapabilities = *(*[]core.Capability)(unsafe.Pointer(&in.RequiredDropCapabilities)) out.AllowedCapabilities = *(*[]core.Capability)(unsafe.Pointer(&in.AllowedCapabilities)) - out.Volumes = *(*[]extensions.FSType)(unsafe.Pointer(&in.Volumes)) + out.Volumes = *(*[]policy.FSType)(unsafe.Pointer(&in.Volumes)) out.HostNetwork = in.HostNetwork - out.HostPorts = *(*[]extensions.HostPortRange)(unsafe.Pointer(&in.HostPorts)) + out.HostPorts = *(*[]policy.HostPortRange)(unsafe.Pointer(&in.HostPorts)) out.HostPID = in.HostPID out.HostIPC = in.HostIPC - if err := Convert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions(&in.SELinux, &out.SELinux, s); err != nil { + if err := Convert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions(&in.SELinux, &out.SELinux, s); err != nil { return err } - if err := Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil { + if err := Convert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil { return err } - if err := Convert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions(&in.SupplementalGroups, &out.SupplementalGroups, s); err != nil { + if err := Convert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions(&in.SupplementalGroups, &out.SupplementalGroups, s); err != nil { return err } - if err := Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(&in.FSGroup, &out.FSGroup, s); err != nil { + if err := Convert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions(&in.FSGroup, &out.FSGroup, s); err != nil { return err } out.ReadOnlyRootFilesystem = in.ReadOnlyRootFilesystem @@ -1094,17 +1121,19 @@ func autoConvert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySp if err := meta_v1.Convert_Pointer_bool_To_bool(&in.AllowPrivilegeEscalation, &out.AllowPrivilegeEscalation, s); err != nil { return err } - out.AllowedHostPaths = *(*[]extensions.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) - out.AllowedFlexVolumes = *(*[]extensions.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedHostPaths = *(*[]policy.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) + out.AllowedFlexVolumes = *(*[]policy.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedUnsafeSysctls = *(*[]string)(unsafe.Pointer(&in.AllowedUnsafeSysctls)) + out.ForbiddenSysctls = *(*[]string)(unsafe.Pointer(&in.ForbiddenSysctls)) return nil } -// Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec is an autogenerated conversion function. -func Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(in *v1beta1.PodSecurityPolicySpec, out *extensions.PodSecurityPolicySpec, s conversion.Scope) error { - return autoConvert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(in, out, s) +// Convert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec is an autogenerated conversion function. +func Convert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(in *v1beta1.PodSecurityPolicySpec, out *policy.PodSecurityPolicySpec, s conversion.Scope) error { + return autoConvert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(in, out, s) } -func autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *extensions.PodSecurityPolicySpec, out *v1beta1.PodSecurityPolicySpec, s conversion.Scope) error { +func autoConvert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *policy.PodSecurityPolicySpec, out *v1beta1.PodSecurityPolicySpec, s conversion.Scope) error { out.Privileged = in.Privileged out.DefaultAddCapabilities = *(*[]v1.Capability)(unsafe.Pointer(&in.DefaultAddCapabilities)) out.RequiredDropCapabilities = *(*[]v1.Capability)(unsafe.Pointer(&in.RequiredDropCapabilities)) @@ -1114,16 +1143,16 @@ func autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySp out.HostPorts = *(*[]v1beta1.HostPortRange)(unsafe.Pointer(&in.HostPorts)) out.HostPID = in.HostPID out.HostIPC = in.HostIPC - if err := Convert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(&in.SELinux, &out.SELinux, s); err != nil { + if err := Convert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(&in.SELinux, &out.SELinux, s); err != nil { return err } - if err := Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil { + if err := Convert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil { return err } - if err := Convert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(&in.SupplementalGroups, &out.SupplementalGroups, s); err != nil { + if err := Convert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(&in.SupplementalGroups, &out.SupplementalGroups, s); err != nil { return err } - if err := Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(&in.FSGroup, &out.FSGroup, s); err != nil { + if err := Convert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(&in.FSGroup, &out.FSGroup, s); err != nil { return err } out.ReadOnlyRootFilesystem = in.ReadOnlyRootFilesystem @@ -1133,9 +1162,16 @@ func autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySp } out.AllowedHostPaths = *(*[]v1beta1.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) out.AllowedFlexVolumes = *(*[]v1beta1.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedUnsafeSysctls = *(*[]string)(unsafe.Pointer(&in.AllowedUnsafeSysctls)) + out.ForbiddenSysctls = *(*[]string)(unsafe.Pointer(&in.ForbiddenSysctls)) return nil } +// Convert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec is an autogenerated conversion function. +func Convert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *policy.PodSecurityPolicySpec, out *v1beta1.PodSecurityPolicySpec, s conversion.Scope) error { + return autoConvert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in, out, s) +} + func autoConvert_v1beta1_ReplicaSet_To_extensions_ReplicaSet(in *v1beta1.ReplicaSet, out *extensions.ReplicaSet, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1beta1_ReplicaSetSpec_To_extensions_ReplicaSetSpec(&in.Spec, &out.Spec, s); err != nil { @@ -1352,48 +1388,48 @@ func autoConvert_extensions_RollingUpdateDeployment_To_v1beta1_RollingUpdateDepl return nil } -func autoConvert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(in *v1beta1.RunAsUserStrategyOptions, out *extensions.RunAsUserStrategyOptions, s conversion.Scope) error { - out.Rule = extensions.RunAsUserStrategy(in.Rule) - out.Ranges = *(*[]extensions.UserIDRange)(unsafe.Pointer(&in.Ranges)) +func autoConvert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions(in *v1beta1.RunAsUserStrategyOptions, out *policy.RunAsUserStrategyOptions, s conversion.Scope) error { + out.Rule = policy.RunAsUserStrategy(in.Rule) + out.Ranges = *(*[]policy.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions is an autogenerated conversion function. -func Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(in *v1beta1.RunAsUserStrategyOptions, out *extensions.RunAsUserStrategyOptions, s conversion.Scope) error { - return autoConvert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(in, out, s) +// Convert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions is an autogenerated conversion function. +func Convert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions(in *v1beta1.RunAsUserStrategyOptions, out *policy.RunAsUserStrategyOptions, s conversion.Scope) error { + return autoConvert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions(in, out, s) } -func autoConvert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *extensions.RunAsUserStrategyOptions, out *v1beta1.RunAsUserStrategyOptions, s conversion.Scope) error { +func autoConvert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *policy.RunAsUserStrategyOptions, out *v1beta1.RunAsUserStrategyOptions, s conversion.Scope) error { out.Rule = v1beta1.RunAsUserStrategy(in.Rule) out.Ranges = *(*[]v1beta1.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions is an autogenerated conversion function. -func Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *extensions.RunAsUserStrategyOptions, out *v1beta1.RunAsUserStrategyOptions, s conversion.Scope) error { - return autoConvert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in, out, s) +// Convert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions is an autogenerated conversion function. +func Convert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *policy.RunAsUserStrategyOptions, out *v1beta1.RunAsUserStrategyOptions, s conversion.Scope) error { + return autoConvert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in, out, s) } -func autoConvert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions(in *v1beta1.SELinuxStrategyOptions, out *extensions.SELinuxStrategyOptions, s conversion.Scope) error { - out.Rule = extensions.SELinuxStrategy(in.Rule) +func autoConvert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions(in *v1beta1.SELinuxStrategyOptions, out *policy.SELinuxStrategyOptions, s conversion.Scope) error { + out.Rule = policy.SELinuxStrategy(in.Rule) out.SELinuxOptions = (*core.SELinuxOptions)(unsafe.Pointer(in.SELinuxOptions)) return nil } -// Convert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions is an autogenerated conversion function. -func Convert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions(in *v1beta1.SELinuxStrategyOptions, out *extensions.SELinuxStrategyOptions, s conversion.Scope) error { - return autoConvert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions(in, out, s) +// Convert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions is an autogenerated conversion function. +func Convert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions(in *v1beta1.SELinuxStrategyOptions, out *policy.SELinuxStrategyOptions, s conversion.Scope) error { + return autoConvert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions(in, out, s) } -func autoConvert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in *extensions.SELinuxStrategyOptions, out *v1beta1.SELinuxStrategyOptions, s conversion.Scope) error { +func autoConvert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in *policy.SELinuxStrategyOptions, out *v1beta1.SELinuxStrategyOptions, s conversion.Scope) error { out.Rule = v1beta1.SELinuxStrategy(in.Rule) out.SELinuxOptions = (*v1.SELinuxOptions)(unsafe.Pointer(in.SELinuxOptions)) return nil } -// Convert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions is an autogenerated conversion function. -func Convert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in *extensions.SELinuxStrategyOptions, out *v1beta1.SELinuxStrategyOptions, s conversion.Scope) error { - return autoConvert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in, out, s) +// Convert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions is an autogenerated conversion function. +func Convert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in *policy.SELinuxStrategyOptions, out *v1beta1.SELinuxStrategyOptions, s conversion.Scope) error { + return autoConvert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in, out, s) } func autoConvert_v1beta1_Scale_To_autoscaling_Scale(in *v1beta1.Scale, out *autoscaling.Scale, s conversion.Scope) error { @@ -1461,24 +1497,24 @@ func autoConvert_autoscaling_ScaleStatus_To_v1beta1_ScaleStatus(in *autoscaling. return nil } -func autoConvert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions(in *v1beta1.SupplementalGroupsStrategyOptions, out *extensions.SupplementalGroupsStrategyOptions, s conversion.Scope) error { - out.Rule = extensions.SupplementalGroupsStrategyType(in.Rule) - out.Ranges = *(*[]extensions.GroupIDRange)(unsafe.Pointer(&in.Ranges)) +func autoConvert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions(in *v1beta1.SupplementalGroupsStrategyOptions, out *policy.SupplementalGroupsStrategyOptions, s conversion.Scope) error { + out.Rule = policy.SupplementalGroupsStrategyType(in.Rule) + out.Ranges = *(*[]policy.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions is an autogenerated conversion function. -func Convert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions(in *v1beta1.SupplementalGroupsStrategyOptions, out *extensions.SupplementalGroupsStrategyOptions, s conversion.Scope) error { - return autoConvert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions(in, out, s) +// Convert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions is an autogenerated conversion function. +func Convert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions(in *v1beta1.SupplementalGroupsStrategyOptions, out *policy.SupplementalGroupsStrategyOptions, s conversion.Scope) error { + return autoConvert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions(in, out, s) } -func autoConvert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in *extensions.SupplementalGroupsStrategyOptions, out *v1beta1.SupplementalGroupsStrategyOptions, s conversion.Scope) error { +func autoConvert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in *policy.SupplementalGroupsStrategyOptions, out *v1beta1.SupplementalGroupsStrategyOptions, s conversion.Scope) error { out.Rule = v1beta1.SupplementalGroupsStrategyType(in.Rule) out.Ranges = *(*[]v1beta1.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions is an autogenerated conversion function. -func Convert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in *extensions.SupplementalGroupsStrategyOptions, out *v1beta1.SupplementalGroupsStrategyOptions, s conversion.Scope) error { - return autoConvert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in, out, s) +// Convert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions is an autogenerated conversion function. +func Convert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in *policy.SupplementalGroupsStrategyOptions, out *v1beta1.SupplementalGroupsStrategyOptions, s conversion.Scope) error { + return autoConvert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in, out, s) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/zz_generated.defaults.go index 3b009bef2..0fa4c321c 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -88,6 +88,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta1.DaemonSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -232,6 +235,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { @@ -398,6 +404,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta1.ReplicaSet) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/BUILD index 82eaf8e82..e56e11627 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/BUILD @@ -14,15 +14,11 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/security/apparmor:go_default_library", - "//pkg/security/podsecuritypolicy/seccomp:go_default_library", - "//pkg/security/podsecuritypolicy/util:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], @@ -35,9 +31,6 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/security/apparmor:go_default_library", - "//pkg/security/podsecuritypolicy/seccomp:go_default_library", - "//pkg/security/podsecuritypolicy/util:go_default_library", "//vendor/github.com/davecgh/go-spew/spew:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/validation.go index a1f9aee6d..3f0d37470 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/validation.go @@ -17,10 +17,7 @@ limitations under the License. package validation import ( - "fmt" "net" - - "path/filepath" "regexp" "strconv" "strings" @@ -30,15 +27,11 @@ import ( unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" apivalidation "k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/security/apparmor" - "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" - psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) // ValidateDaemonSet tests if required fields in the DaemonSet are set. @@ -613,299 +606,3 @@ func ValidatePodTemplateSpecForReplicaSet(template *api.PodTemplateSpec, selecto } return allErrs } - -// ValidatePodSecurityPolicyName can be used to check whether the given -// pod security policy name is valid. -// Prefix indicates this name will be used as part of generation, in which case -// trailing dashes are allowed. -var ValidatePodSecurityPolicyName = apivalidation.NameIsDNSSubdomain - -func ValidatePodSecurityPolicy(psp *extensions.PodSecurityPolicy) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&psp.ObjectMeta, false, ValidatePodSecurityPolicyName, field.NewPath("metadata"))...) - allErrs = append(allErrs, ValidatePodSecurityPolicySpecificAnnotations(psp.Annotations, field.NewPath("metadata").Child("annotations"))...) - allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&psp.Spec, field.NewPath("spec"))...) - return allErrs -} - -func ValidatePodSecurityPolicySpec(spec *extensions.PodSecurityPolicySpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - - allErrs = append(allErrs, validatePSPRunAsUser(fldPath.Child("runAsUser"), &spec.RunAsUser)...) - allErrs = append(allErrs, validatePSPSELinux(fldPath.Child("seLinux"), &spec.SELinux)...) - allErrs = append(allErrs, validatePSPSupplementalGroup(fldPath.Child("supplementalGroups"), &spec.SupplementalGroups)...) - allErrs = append(allErrs, validatePSPFSGroup(fldPath.Child("fsGroup"), &spec.FSGroup)...) - allErrs = append(allErrs, validatePodSecurityPolicyVolumes(fldPath, spec.Volumes)...) - if len(spec.RequiredDropCapabilities) > 0 && hasCap(extensions.AllowAllCapabilities, spec.AllowedCapabilities) { - allErrs = append(allErrs, field.Invalid(field.NewPath("requiredDropCapabilities"), spec.RequiredDropCapabilities, - "must be empty when all capabilities are allowed by a wildcard")) - } - allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.DefaultAddCapabilities, field.NewPath("defaultAddCapabilities"))...) - allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.AllowedCapabilities, field.NewPath("allowedCapabilities"))...) - allErrs = append(allErrs, validatePSPDefaultAllowPrivilegeEscalation(fldPath.Child("defaultAllowPrivilegeEscalation"), spec.DefaultAllowPrivilegeEscalation, spec.AllowPrivilegeEscalation)...) - allErrs = append(allErrs, validatePSPAllowedHostPaths(fldPath.Child("allowedHostPaths"), spec.AllowedHostPaths)...) - allErrs = append(allErrs, validatePSPAllowedFlexVolumes(fldPath.Child("allowedFlexVolumes"), spec.AllowedFlexVolumes)...) - - return allErrs -} - -func ValidatePodSecurityPolicySpecificAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - - if p := annotations[apparmor.DefaultProfileAnnotationKey]; p != "" { - if err := apparmor.ValidateProfileFormat(p); err != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.DefaultProfileAnnotationKey), p, err.Error())) - } - } - if allowed := annotations[apparmor.AllowedProfilesAnnotationKey]; allowed != "" { - for _, p := range strings.Split(allowed, ",") { - if err := apparmor.ValidateProfileFormat(p); err != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.AllowedProfilesAnnotationKey), allowed, err.Error())) - } - } - } - - sysctlAnnotation := annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] - sysctlFldPath := fldPath.Key(extensions.SysctlsPodSecurityPolicyAnnotationKey) - sysctls, err := extensions.SysctlsFromPodSecurityPolicyAnnotation(sysctlAnnotation) - if err != nil { - allErrs = append(allErrs, field.Invalid(sysctlFldPath, sysctlAnnotation, err.Error())) - } else { - allErrs = append(allErrs, validatePodSecurityPolicySysctls(sysctlFldPath, sysctls)...) - } - - if p := annotations[seccomp.DefaultProfileAnnotationKey]; p != "" { - allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.DefaultProfileAnnotationKey))...) - } - if allowed := annotations[seccomp.AllowedProfilesAnnotationKey]; allowed != "" { - for _, p := range strings.Split(allowed, ",") { - if p == seccomp.AllowAny { - continue - } - allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.AllowedProfilesAnnotationKey))...) - } - } - return allErrs -} - -// validatePSPAllowedHostPaths makes sure all allowed host paths follow: -// 1. path prefix is required -// 2. path prefix does not have any element which is ".." -func validatePSPAllowedHostPaths(fldPath *field.Path, allowedHostPaths []extensions.AllowedHostPath) field.ErrorList { - allErrs := field.ErrorList{} - - for i, target := range allowedHostPaths { - if target.PathPrefix == "" { - allErrs = append(allErrs, field.Required(fldPath.Index(i), "is required")) - break - } - parts := strings.Split(filepath.ToSlash(target.PathPrefix), "/") - for _, item := range parts { - if item == ".." { - allErrs = append(allErrs, field.Invalid(fldPath.Index(i), target.PathPrefix, "must not contain '..'")) - break // even for `../../..`, one error is sufficient to make the point - } - } - } - - return allErrs -} - -// validatePSPAllowedFlexVolumes -func validatePSPAllowedFlexVolumes(fldPath *field.Path, flexVolumes []extensions.AllowedFlexVolume) field.ErrorList { - allErrs := field.ErrorList{} - if len(flexVolumes) > 0 { - for idx, fv := range flexVolumes { - if len(fv.Driver) == 0 { - allErrs = append(allErrs, field.Required(fldPath.Child("allowedFlexVolumes").Index(idx).Child("driver"), - "must specify a driver")) - } - } - } - return allErrs -} - -// validatePSPSELinux validates the SELinux fields of PodSecurityPolicy. -func validatePSPSELinux(fldPath *field.Path, seLinux *extensions.SELinuxStrategyOptions) field.ErrorList { - allErrs := field.ErrorList{} - - // ensure the selinux strategy has a valid rule - supportedSELinuxRules := sets.NewString(string(extensions.SELinuxStrategyMustRunAs), - string(extensions.SELinuxStrategyRunAsAny)) - if !supportedSELinuxRules.Has(string(seLinux.Rule)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), seLinux.Rule, supportedSELinuxRules.List())) - } - - return allErrs -} - -// validatePSPRunAsUser validates the RunAsUser fields of PodSecurityPolicy. -func validatePSPRunAsUser(fldPath *field.Path, runAsUser *extensions.RunAsUserStrategyOptions) field.ErrorList { - allErrs := field.ErrorList{} - - // ensure the user strategy has a valid rule - supportedRunAsUserRules := sets.NewString(string(extensions.RunAsUserStrategyMustRunAs), - string(extensions.RunAsUserStrategyMustRunAsNonRoot), - string(extensions.RunAsUserStrategyRunAsAny)) - if !supportedRunAsUserRules.Has(string(runAsUser.Rule)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), runAsUser.Rule, supportedRunAsUserRules.List())) - } - - // validate range settings - for idx, rng := range runAsUser.Ranges { - allErrs = append(allErrs, validateUserIDRange(fldPath.Child("ranges").Index(idx), rng)...) - } - - return allErrs -} - -// validatePSPFSGroup validates the FSGroupStrategyOptions fields of the PodSecurityPolicy. -func validatePSPFSGroup(fldPath *field.Path, groupOptions *extensions.FSGroupStrategyOptions) field.ErrorList { - allErrs := field.ErrorList{} - - supportedRules := sets.NewString( - string(extensions.FSGroupStrategyMustRunAs), - string(extensions.FSGroupStrategyRunAsAny), - ) - if !supportedRules.Has(string(groupOptions.Rule)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), groupOptions.Rule, supportedRules.List())) - } - - for idx, rng := range groupOptions.Ranges { - allErrs = append(allErrs, validateGroupIDRange(fldPath.Child("ranges").Index(idx), rng)...) - } - return allErrs -} - -// validatePSPSupplementalGroup validates the SupplementalGroupsStrategyOptions fields of the PodSecurityPolicy. -func validatePSPSupplementalGroup(fldPath *field.Path, groupOptions *extensions.SupplementalGroupsStrategyOptions) field.ErrorList { - allErrs := field.ErrorList{} - - supportedRules := sets.NewString( - string(extensions.SupplementalGroupsStrategyRunAsAny), - string(extensions.SupplementalGroupsStrategyMustRunAs), - ) - if !supportedRules.Has(string(groupOptions.Rule)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), groupOptions.Rule, supportedRules.List())) - } - - for idx, rng := range groupOptions.Ranges { - allErrs = append(allErrs, validateGroupIDRange(fldPath.Child("ranges").Index(idx), rng)...) - } - return allErrs -} - -// validatePodSecurityPolicyVolumes validates the volume fields of PodSecurityPolicy. -func validatePodSecurityPolicyVolumes(fldPath *field.Path, volumes []extensions.FSType) field.ErrorList { - allErrs := field.ErrorList{} - allowed := psputil.GetAllFSTypesAsSet() - // add in the * value since that is a pseudo type that is not included by default - allowed.Insert(string(extensions.All)) - for _, v := range volumes { - if !allowed.Has(string(v)) { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("volumes"), v, allowed.List())) - } - } - return allErrs -} - -// validatePSPDefaultAllowPrivilegeEscalation validates the DefaultAllowPrivilegeEscalation field against the AllowPrivilegeEscalation field of a PodSecurityPolicy. -func validatePSPDefaultAllowPrivilegeEscalation(fldPath *field.Path, defaultAllowPrivilegeEscalation *bool, allowPrivilegeEscalation bool) field.ErrorList { - allErrs := field.ErrorList{} - if defaultAllowPrivilegeEscalation != nil && *defaultAllowPrivilegeEscalation && !allowPrivilegeEscalation { - allErrs = append(allErrs, field.Invalid(fldPath, defaultAllowPrivilegeEscalation, "Cannot set DefaultAllowPrivilegeEscalation to true without also setting AllowPrivilegeEscalation to true")) - } - - return allErrs -} - -const sysctlPatternSegmentFmt string = "([a-z0-9][-_a-z0-9]*)?[a-z0-9*]" -const SysctlPatternFmt string = "(" + apivalidation.SysctlSegmentFmt + "\\.)*" + sysctlPatternSegmentFmt - -var sysctlPatternRegexp = regexp.MustCompile("^" + SysctlPatternFmt + "$") - -func IsValidSysctlPattern(name string) bool { - if len(name) > apivalidation.SysctlMaxLength { - return false - } - return sysctlPatternRegexp.MatchString(name) -} - -// validatePodSecurityPolicySysctls validates the sysctls fields of PodSecurityPolicy. -func validatePodSecurityPolicySysctls(fldPath *field.Path, sysctls []string) field.ErrorList { - allErrs := field.ErrorList{} - for i, s := range sysctls { - if !IsValidSysctlPattern(string(s)) { - allErrs = append( - allErrs, - field.Invalid(fldPath.Index(i), sysctls[i], fmt.Sprintf("must have at most %d characters and match regex %s", - apivalidation.SysctlMaxLength, - SysctlPatternFmt, - )), - ) - } - } - - return allErrs -} - -func validateUserIDRange(fldPath *field.Path, rng extensions.UserIDRange) field.ErrorList { - return validateIDRanges(fldPath, int64(rng.Min), int64(rng.Max)) -} - -func validateGroupIDRange(fldPath *field.Path, rng extensions.GroupIDRange) field.ErrorList { - return validateIDRanges(fldPath, int64(rng.Min), int64(rng.Max)) -} - -// validateIDRanges ensures the range is valid. -func validateIDRanges(fldPath *field.Path, min, max int64) field.ErrorList { - allErrs := field.ErrorList{} - - // if 0 <= Min <= Max then we do not need to validate max. It is always greater than or - // equal to 0 and Min. - if min < 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), min, "min cannot be negative")) - } - if max < 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("max"), max, "max cannot be negative")) - } - if min > max { - allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), min, "min cannot be greater than max")) - } - - return allErrs -} - -// validatePSPCapsAgainstDrops ensures an allowed cap is not listed in the required drops. -func validatePSPCapsAgainstDrops(requiredDrops []api.Capability, capsToCheck []api.Capability, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if requiredDrops == nil { - return allErrs - } - for _, cap := range capsToCheck { - if hasCap(cap, requiredDrops) { - allErrs = append(allErrs, field.Invalid(fldPath, cap, - fmt.Sprintf("capability is listed in %s and requiredDropCapabilities", fldPath.String()))) - } - } - return allErrs -} - -// hasCap checks for needle in haystack. -func hasCap(needle api.Capability, haystack []api.Capability) bool { - for _, c := range haystack { - if needle == c { - return true - } - } - return false -} - -// ValidatePodSecurityPolicyUpdate validates a PSP for updates. -func ValidatePodSecurityPolicyUpdate(old *extensions.PodSecurityPolicy, new *extensions.PodSecurityPolicy) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&new.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))...) - allErrs = append(allErrs, ValidatePodSecurityPolicySpecificAnnotations(new.Annotations, field.NewPath("metadata").Child("annotations"))...) - allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&new.Spec, field.NewPath("spec"))...) - return allErrs -} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/validation_test.go index d3a0d0fce..cd56129a9 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/validation/validation_test.go @@ -28,9 +28,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/security/apparmor" - "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" - psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) func TestValidateDaemonSetStatusUpdate(t *testing.T) { @@ -2317,499 +2314,3 @@ func TestValidateReplicaSet(t *testing.T) { } } } - -func TestValidatePodSecurityPolicy(t *testing.T) { - validPSP := func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Annotations: map[string]string{}, - }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, - }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, - }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, - }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, - }, - AllowedHostPaths: []extensions.AllowedHostPath{ - {PathPrefix: "/foo/bar"}, - {PathPrefix: "/baz/"}, - }, - }, - } - } - - noUserOptions := validPSP() - noUserOptions.Spec.RunAsUser.Rule = "" - - noSELinuxOptions := validPSP() - noSELinuxOptions.Spec.SELinux.Rule = "" - - invalidUserStratType := validPSP() - invalidUserStratType.Spec.RunAsUser.Rule = "invalid" - - invalidSELinuxStratType := validPSP() - invalidSELinuxStratType.Spec.SELinux.Rule = "invalid" - - invalidUIDPSP := validPSP() - invalidUIDPSP.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAs - invalidUIDPSP.Spec.RunAsUser.Ranges = []extensions.UserIDRange{{Min: -1, Max: 1}} - - missingObjectMetaName := validPSP() - missingObjectMetaName.ObjectMeta.Name = "" - - noFSGroupOptions := validPSP() - noFSGroupOptions.Spec.FSGroup.Rule = "" - - invalidFSGroupStratType := validPSP() - invalidFSGroupStratType.Spec.FSGroup.Rule = "invalid" - - noSupplementalGroupsOptions := validPSP() - noSupplementalGroupsOptions.Spec.SupplementalGroups.Rule = "" - - invalidSupGroupStratType := validPSP() - invalidSupGroupStratType.Spec.SupplementalGroups.Rule = "invalid" - - invalidRangeMinGreaterThanMax := validPSP() - invalidRangeMinGreaterThanMax.Spec.FSGroup.Ranges = []extensions.GroupIDRange{ - {Min: 2, Max: 1}, - } - - invalidRangeNegativeMin := validPSP() - invalidRangeNegativeMin.Spec.FSGroup.Ranges = []extensions.GroupIDRange{ - {Min: -1, Max: 10}, - } - - invalidRangeNegativeMax := validPSP() - invalidRangeNegativeMax.Spec.FSGroup.Ranges = []extensions.GroupIDRange{ - {Min: 1, Max: -10}, - } - - wildcardAllowedCapAndRequiredDrop := validPSP() - wildcardAllowedCapAndRequiredDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} - wildcardAllowedCapAndRequiredDrop.Spec.AllowedCapabilities = []api.Capability{extensions.AllowAllCapabilities} - - requiredCapAddAndDrop := validPSP() - requiredCapAddAndDrop.Spec.DefaultAddCapabilities = []api.Capability{"foo"} - requiredCapAddAndDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} - - allowedCapListedInRequiredDrop := validPSP() - allowedCapListedInRequiredDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} - allowedCapListedInRequiredDrop.Spec.AllowedCapabilities = []api.Capability{"foo"} - - invalidAppArmorDefault := validPSP() - invalidAppArmorDefault.Annotations = map[string]string{ - apparmor.DefaultProfileAnnotationKey: "not-good", - } - invalidAppArmorAllowed := validPSP() - invalidAppArmorAllowed.Annotations = map[string]string{ - apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + ",not-good", - } - - invalidSysctlPattern := validPSP() - invalidSysctlPattern.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "a.*.b" - - invalidSeccompDefault := validPSP() - invalidSeccompDefault.Annotations = map[string]string{ - seccomp.DefaultProfileAnnotationKey: "not-good", - } - invalidSeccompAllowAnyDefault := validPSP() - invalidSeccompAllowAnyDefault.Annotations = map[string]string{ - seccomp.DefaultProfileAnnotationKey: "*", - } - invalidSeccompAllowed := validPSP() - invalidSeccompAllowed.Annotations = map[string]string{ - seccomp.AllowedProfilesAnnotationKey: "docker/default,not-good", - } - - invalidAllowedHostPathMissingPath := validPSP() - invalidAllowedHostPathMissingPath.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ - {PathPrefix: ""}, - } - - invalidAllowedHostPathBacksteps := validPSP() - invalidAllowedHostPathBacksteps.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ - {PathPrefix: "/dont/allow/backsteps/.."}, - } - - invalidDefaultAllowPrivilegeEscalation := validPSP() - pe := true - invalidDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe - - emptyFlexDriver := validPSP() - emptyFlexDriver.Spec.Volumes = []extensions.FSType{extensions.FlexVolume} - emptyFlexDriver.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{{}} - - nonEmptyFlexVolumes := validPSP() - nonEmptyFlexVolumes.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{{Driver: "example/driver"}} - - type testCase struct { - psp *extensions.PodSecurityPolicy - errorType field.ErrorType - errorDetail string - } - errorCases := map[string]testCase{ - "no user options": { - psp: noUserOptions, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "MustRunAsNonRoot", "RunAsAny"`, - }, - "no selinux options": { - psp: noSELinuxOptions, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "no fsgroup options": { - psp: noFSGroupOptions, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "no sup group options": { - psp: noSupplementalGroupsOptions, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "invalid user strategy type": { - psp: invalidUserStratType, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "MustRunAsNonRoot", "RunAsAny"`, - }, - "invalid selinux strategy type": { - psp: invalidSELinuxStratType, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "invalid sup group strategy type": { - psp: invalidSupGroupStratType, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "invalid fs group strategy type": { - psp: invalidFSGroupStratType, - errorType: field.ErrorTypeNotSupported, - errorDetail: `supported values: "MustRunAs", "RunAsAny"`, - }, - "invalid uid": { - psp: invalidUIDPSP, - errorType: field.ErrorTypeInvalid, - errorDetail: "min cannot be negative", - }, - "missing object meta name": { - psp: missingObjectMetaName, - errorType: field.ErrorTypeRequired, - errorDetail: "name or generateName is required", - }, - "invalid range min greater than max": { - psp: invalidRangeMinGreaterThanMax, - errorType: field.ErrorTypeInvalid, - errorDetail: "min cannot be greater than max", - }, - "invalid range negative min": { - psp: invalidRangeNegativeMin, - errorType: field.ErrorTypeInvalid, - errorDetail: "min cannot be negative", - }, - "invalid range negative max": { - psp: invalidRangeNegativeMax, - errorType: field.ErrorTypeInvalid, - errorDetail: "max cannot be negative", - }, - "non-empty required drops and all caps are allowed by a wildcard": { - psp: wildcardAllowedCapAndRequiredDrop, - errorType: field.ErrorTypeInvalid, - errorDetail: "must be empty when all capabilities are allowed by a wildcard", - }, - "invalid required caps": { - psp: requiredCapAddAndDrop, - errorType: field.ErrorTypeInvalid, - errorDetail: "capability is listed in defaultAddCapabilities and requiredDropCapabilities", - }, - "allowed cap listed in required drops": { - psp: allowedCapListedInRequiredDrop, - errorType: field.ErrorTypeInvalid, - errorDetail: "capability is listed in allowedCapabilities and requiredDropCapabilities", - }, - "invalid AppArmor default profile": { - psp: invalidAppArmorDefault, - errorType: field.ErrorTypeInvalid, - errorDetail: "invalid AppArmor profile name: \"not-good\"", - }, - "invalid AppArmor allowed profile": { - psp: invalidAppArmorAllowed, - errorType: field.ErrorTypeInvalid, - errorDetail: "invalid AppArmor profile name: \"not-good\"", - }, - "invalid sysctl pattern": { - psp: invalidSysctlPattern, - errorType: field.ErrorTypeInvalid, - errorDetail: fmt.Sprintf("must have at most 253 characters and match regex %s", SysctlPatternFmt), - }, - "invalid seccomp default profile": { - psp: invalidSeccompDefault, - errorType: field.ErrorTypeInvalid, - errorDetail: "must be a valid seccomp profile", - }, - "invalid seccomp allow any default profile": { - psp: invalidSeccompAllowAnyDefault, - errorType: field.ErrorTypeInvalid, - errorDetail: "must be a valid seccomp profile", - }, - "invalid seccomp allowed profile": { - psp: invalidSeccompAllowed, - errorType: field.ErrorTypeInvalid, - errorDetail: "must be a valid seccomp profile", - }, - "invalid defaultAllowPrivilegeEscalation": { - psp: invalidDefaultAllowPrivilegeEscalation, - errorType: field.ErrorTypeInvalid, - errorDetail: "Cannot set DefaultAllowPrivilegeEscalation to true without also setting AllowPrivilegeEscalation to true", - }, - "invalid allowed host path empty path": { - psp: invalidAllowedHostPathMissingPath, - errorType: field.ErrorTypeRequired, - errorDetail: "is required", - }, - "invalid allowed host path with backsteps": { - psp: invalidAllowedHostPathBacksteps, - errorType: field.ErrorTypeInvalid, - errorDetail: "must not contain '..'", - }, - "empty flex volume driver": { - psp: emptyFlexDriver, - errorType: field.ErrorTypeRequired, - errorDetail: "must specify a driver", - }, - } - - for k, v := range errorCases { - errs := ValidatePodSecurityPolicy(v.psp) - if len(errs) == 0 { - t.Errorf("%s expected errors but got none", k) - continue - } - if errs[0].Type != v.errorType { - t.Errorf("[%s] received an unexpected error type. Expected: '%s' got: '%s'", k, v.errorType, errs[0].Type) - } - if errs[0].Detail != v.errorDetail { - t.Errorf("[%s] received an unexpected error detail. Expected '%s' got: '%s'", k, v.errorDetail, errs[0].Detail) - } - } - - // Update error is different for 'missing object meta name'. - errorCases["missing object meta name"] = testCase{ - psp: errorCases["missing object meta name"].psp, - errorType: field.ErrorTypeInvalid, - errorDetail: "field is immutable", - } - - // Should not be able to update to an invalid policy. - for k, v := range errorCases { - v.psp.ResourceVersion = "444" // Required for updates. - errs := ValidatePodSecurityPolicyUpdate(validPSP(), v.psp) - if len(errs) == 0 { - t.Errorf("[%s] expected update errors but got none", k) - continue - } - if errs[0].Type != v.errorType { - t.Errorf("[%s] received an unexpected error type. Expected: '%s' got: '%s'", k, v.errorType, errs[0].Type) - } - if errs[0].Detail != v.errorDetail { - t.Errorf("[%s] received an unexpected error detail. Expected '%s' got: '%s'", k, v.errorDetail, errs[0].Detail) - } - } - - mustRunAs := validPSP() - mustRunAs.Spec.FSGroup.Rule = extensions.FSGroupStrategyMustRunAs - mustRunAs.Spec.SupplementalGroups.Rule = extensions.SupplementalGroupsStrategyMustRunAs - mustRunAs.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAs - mustRunAs.Spec.RunAsUser.Ranges = []extensions.UserIDRange{ - {Min: 1, Max: 1}, - } - mustRunAs.Spec.SELinux.Rule = extensions.SELinuxStrategyMustRunAs - - runAsNonRoot := validPSP() - runAsNonRoot.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAsNonRoot - - caseInsensitiveAddDrop := validPSP() - caseInsensitiveAddDrop.Spec.DefaultAddCapabilities = []api.Capability{"foo"} - caseInsensitiveAddDrop.Spec.RequiredDropCapabilities = []api.Capability{"FOO"} - - caseInsensitiveAllowedDrop := validPSP() - caseInsensitiveAllowedDrop.Spec.RequiredDropCapabilities = []api.Capability{"FOO"} - caseInsensitiveAllowedDrop.Spec.AllowedCapabilities = []api.Capability{"foo"} - - validAppArmor := validPSP() - validAppArmor.Annotations = map[string]string{ - apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault, - apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + "," + apparmor.ProfileNamePrefix + "foo", - } - - withSysctl := validPSP() - withSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "net.*" - - validSeccomp := validPSP() - validSeccomp.Annotations = map[string]string{ - seccomp.DefaultProfileAnnotationKey: "docker/default", - seccomp.AllowedProfilesAnnotationKey: "docker/default,unconfined,localhost/foo,*", - } - - validDefaultAllowPrivilegeEscalation := validPSP() - pe = true - validDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe - validDefaultAllowPrivilegeEscalation.Spec.AllowPrivilegeEscalation = true - - flexvolumeWhenFlexVolumesAllowed := validPSP() - flexvolumeWhenFlexVolumesAllowed.Spec.Volumes = []extensions.FSType{extensions.FlexVolume} - flexvolumeWhenFlexVolumesAllowed.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{ - {Driver: "example/driver1"}, - } - - flexvolumeWhenAllVolumesAllowed := validPSP() - flexvolumeWhenAllVolumesAllowed.Spec.Volumes = []extensions.FSType{extensions.All} - flexvolumeWhenAllVolumesAllowed.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{ - {Driver: "example/driver2"}, - } - successCases := map[string]struct { - psp *extensions.PodSecurityPolicy - }{ - "must run as": { - psp: mustRunAs, - }, - "run as any": { - psp: validPSP(), - }, - "run as non-root (user only)": { - psp: runAsNonRoot, - }, - "comparison for add -> drop is case sensitive": { - psp: caseInsensitiveAddDrop, - }, - "comparison for allowed -> drop is case sensitive": { - psp: caseInsensitiveAllowedDrop, - }, - "valid AppArmor annotations": { - psp: validAppArmor, - }, - "with network sysctls": { - psp: withSysctl, - }, - "valid seccomp annotations": { - psp: validSeccomp, - }, - "valid defaultAllowPrivilegeEscalation as true": { - psp: validDefaultAllowPrivilegeEscalation, - }, - "allow white-listed flexVolume when flex volumes are allowed": { - psp: flexvolumeWhenFlexVolumesAllowed, - }, - "allow white-listed flexVolume when all volumes are allowed": { - psp: flexvolumeWhenAllVolumesAllowed, - }, - } - - for k, v := range successCases { - if errs := ValidatePodSecurityPolicy(v.psp); len(errs) != 0 { - t.Errorf("Expected success for %s, got %v", k, errs) - } - - // Should be able to update to a valid PSP. - v.psp.ResourceVersion = "444" // Required for updates. - if errs := ValidatePodSecurityPolicyUpdate(validPSP(), v.psp); len(errs) != 0 { - t.Errorf("Expected success for %s update, got %v", k, errs) - } - } -} - -func TestValidatePSPVolumes(t *testing.T) { - validPSP := func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "foo"}, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, - }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, - }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, - }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, - }, - }, - } - } - - volumes := psputil.GetAllFSTypesAsSet() - // add in the * value since that is a pseudo type that is not included by default - volumes.Insert(string(extensions.All)) - - for _, strVolume := range volumes.List() { - psp := validPSP() - psp.Spec.Volumes = []extensions.FSType{extensions.FSType(strVolume)} - errs := ValidatePodSecurityPolicy(psp) - if len(errs) != 0 { - t.Errorf("%s validation expected no errors but received %v", strVolume, errs) - } - } -} - -func TestIsValidSysctlPattern(t *testing.T) { - valid := []string{ - "a.b.c.d", - "a", - "a_b", - "a-b", - "abc", - "abc.def", - "*", - "a.*", - "*", - "abc*", - "a.abc*", - "a.b.*", - } - invalid := []string{ - "", - "ä", - "a_", - "_", - "_a", - "_a._b", - "__", - "-", - ".", - "a.", - ".a", - "a.b.", - "a*.b", - "a*b", - "*a", - "Abc", - func(n int) string { - x := make([]byte, n) - for i := range x { - x[i] = byte('a') - } - return string(x) - }(256), - } - for _, s := range valid { - if !IsValidSysctlPattern(s) { - t.Errorf("%q expected to be a valid sysctl pattern", s) - } - } - for _, s := range invalid { - if IsValidSysctlPattern(s) { - t.Errorf("%q expected to be an invalid sysctl pattern", s) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/extensions/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/extensions/zz_generated.deepcopy.go index b7a91b05d..199db30fd 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/extensions/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/extensions/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -23,41 +23,8 @@ package extensions import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" - core "k8s.io/kubernetes/pkg/apis/core" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AllowedFlexVolume) DeepCopyInto(out *AllowedFlexVolume) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllowedFlexVolume. -func (in *AllowedFlexVolume) DeepCopy() *AllowedFlexVolume { - if in == nil { - return nil - } - out := new(AllowedFlexVolume) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AllowedHostPath) DeepCopyInto(out *AllowedHostPath) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllowedHostPath. -func (in *AllowedHostPath) DeepCopy() *AllowedHostPath { - if in == nil { - return nil - } - out := new(AllowedHostPath) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomMetricCurrentStatus) DeepCopyInto(out *CustomMetricCurrentStatus) { *out = *in @@ -532,43 +499,6 @@ func (in *DeploymentStrategy) DeepCopy() *DeploymentStrategy { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FSGroupStrategyOptions) DeepCopyInto(out *FSGroupStrategyOptions) { - *out = *in - if in.Ranges != nil { - in, out := &in.Ranges, &out.Ranges - *out = make([]GroupIDRange, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FSGroupStrategyOptions. -func (in *FSGroupStrategyOptions) DeepCopy() *FSGroupStrategyOptions { - if in == nil { - return nil - } - out := new(FSGroupStrategyOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GroupIDRange) DeepCopyInto(out *GroupIDRange) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupIDRange. -func (in *GroupIDRange) DeepCopy() *GroupIDRange { - if in == nil { - return nil - } - out := new(GroupIDRange) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPIngressPath) DeepCopyInto(out *HTTPIngressPath) { *out = *in @@ -607,22 +537,6 @@ func (in *HTTPIngressRuleValue) DeepCopy() *HTTPIngressRuleValue { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HostPortRange) DeepCopyInto(out *HostPortRange) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPortRange. -func (in *HostPortRange) DeepCopy() *HostPortRange { - if in == nil { - return nil - } - out := new(HostPortRange) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Ingress) DeepCopyInto(out *Ingress) { *out = *in @@ -820,130 +734,6 @@ func (in *IngressTLS) DeepCopy() *IngressTLS { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PodSecurityPolicy) DeepCopyInto(out *PodSecurityPolicy) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSecurityPolicy. -func (in *PodSecurityPolicy) DeepCopy() *PodSecurityPolicy { - if in == nil { - return nil - } - out := new(PodSecurityPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *PodSecurityPolicy) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PodSecurityPolicyList) DeepCopyInto(out *PodSecurityPolicyList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]PodSecurityPolicy, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSecurityPolicyList. -func (in *PodSecurityPolicyList) DeepCopy() *PodSecurityPolicyList { - if in == nil { - return nil - } - out := new(PodSecurityPolicyList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *PodSecurityPolicyList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PodSecurityPolicySpec) DeepCopyInto(out *PodSecurityPolicySpec) { - *out = *in - if in.DefaultAddCapabilities != nil { - in, out := &in.DefaultAddCapabilities, &out.DefaultAddCapabilities - *out = make([]core.Capability, len(*in)) - copy(*out, *in) - } - if in.RequiredDropCapabilities != nil { - in, out := &in.RequiredDropCapabilities, &out.RequiredDropCapabilities - *out = make([]core.Capability, len(*in)) - copy(*out, *in) - } - if in.AllowedCapabilities != nil { - in, out := &in.AllowedCapabilities, &out.AllowedCapabilities - *out = make([]core.Capability, len(*in)) - copy(*out, *in) - } - if in.Volumes != nil { - in, out := &in.Volumes, &out.Volumes - *out = make([]FSType, len(*in)) - copy(*out, *in) - } - if in.HostPorts != nil { - in, out := &in.HostPorts, &out.HostPorts - *out = make([]HostPortRange, len(*in)) - copy(*out, *in) - } - in.SELinux.DeepCopyInto(&out.SELinux) - in.RunAsUser.DeepCopyInto(&out.RunAsUser) - in.SupplementalGroups.DeepCopyInto(&out.SupplementalGroups) - in.FSGroup.DeepCopyInto(&out.FSGroup) - if in.DefaultAllowPrivilegeEscalation != nil { - in, out := &in.DefaultAllowPrivilegeEscalation, &out.DefaultAllowPrivilegeEscalation - if *in == nil { - *out = nil - } else { - *out = new(bool) - **out = **in - } - } - if in.AllowedHostPaths != nil { - in, out := &in.AllowedHostPaths, &out.AllowedHostPaths - *out = make([]AllowedHostPath, len(*in)) - copy(*out, *in) - } - if in.AllowedFlexVolumes != nil { - in, out := &in.AllowedFlexVolumes, &out.AllowedFlexVolumes - *out = make([]AllowedFlexVolume, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSecurityPolicySpec. -func (in *PodSecurityPolicySpec) DeepCopy() *PodSecurityPolicySpec { - if in == nil { - return nil - } - out := new(PodSecurityPolicySpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ReplicaSet) DeepCopyInto(out *ReplicaSet) { *out = *in @@ -1146,86 +936,3 @@ func (in *RollingUpdateDeployment) DeepCopy() *RollingUpdateDeployment { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RunAsUserStrategyOptions) DeepCopyInto(out *RunAsUserStrategyOptions) { - *out = *in - if in.Ranges != nil { - in, out := &in.Ranges, &out.Ranges - *out = make([]UserIDRange, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunAsUserStrategyOptions. -func (in *RunAsUserStrategyOptions) DeepCopy() *RunAsUserStrategyOptions { - if in == nil { - return nil - } - out := new(RunAsUserStrategyOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SELinuxStrategyOptions) DeepCopyInto(out *SELinuxStrategyOptions) { - *out = *in - if in.SELinuxOptions != nil { - in, out := &in.SELinuxOptions, &out.SELinuxOptions - if *in == nil { - *out = nil - } else { - *out = new(core.SELinuxOptions) - **out = **in - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SELinuxStrategyOptions. -func (in *SELinuxStrategyOptions) DeepCopy() *SELinuxStrategyOptions { - if in == nil { - return nil - } - out := new(SELinuxStrategyOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SupplementalGroupsStrategyOptions) DeepCopyInto(out *SupplementalGroupsStrategyOptions) { - *out = *in - if in.Ranges != nil { - in, out := &in.Ranges, &out.Ranges - *out = make([]GroupIDRange, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SupplementalGroupsStrategyOptions. -func (in *SupplementalGroupsStrategyOptions) DeepCopy() *SupplementalGroupsStrategyOptions { - if in == nil { - return nil - } - out := new(SupplementalGroupsStrategyOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *UserIDRange) DeepCopyInto(out *UserIDRange) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserIDRange. -func (in *UserIDRange) DeepCopy() *UserIDRange { - if in == nil { - return nil - } - out := new(UserIDRange) - in.DeepCopyInto(out) - return out -} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/install/BUILD index 77b3a196e..620376bca 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/install/BUILD @@ -13,10 +13,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/imagepolicy:go_default_library", "//pkg/apis/imagepolicy/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/install/install.go index 75f5ba1f4..f4937181c 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/install/install.go @@ -19,32 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/imagepolicy" "k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: imagepolicy.GroupName, - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("ImageReview"), - AddInternalObjectsToScheme: imagepolicy.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(imagepolicy.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1/zz_generated.conversion.go index 7aacf8500..7177af5f9 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/zz_generated.deepcopy.go index d726e82fc..bd69648e4 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/imagepolicy/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/networking/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/networking/install/BUILD index a5ce49004..687a53d35 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/networking/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/networking/install/BUILD @@ -13,9 +13,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/networking:go_default_library", "//pkg/apis/networking/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/networking/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/networking/install/install.go index 59a3d043c..4cef1acaf 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/networking/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/networking/install/install.go @@ -19,30 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/networking" "k8s.io/kubernetes/pkg/apis/networking/v1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: networking.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: networking.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(networking.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/networking/types.go b/vendor/k8s.io/kubernetes/pkg/apis/networking/types.go index ae37fcd5e..b92e03295 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/networking/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/networking/types.go @@ -159,22 +159,28 @@ type IPBlock struct { Except []string } -// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields -// must be specified. +// NetworkPolicyPeer describes a peer to allow traffic from. type NetworkPolicyPeer struct { - // This is a label selector which selects Pods in this namespace. This field - // follows standard label selector semantics. If present but empty, this selector - // selects all pods in this namespace. + // This is a label selector which selects Pods. This field follows standard label + // selector semantics; if present but empty, it selects all pods. + // + // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. // +optional PodSelector *metav1.LabelSelector - // Selects Namespaces using cluster scoped-labels. This matches all pods in all - // namespaces selected by this label selector. This field follows standard label - // selector semantics. If present but empty, this selector selects all namespaces. + // Selects Namespaces using cluster-scoped labels. This field follows standard label + // selector semantics; if present but empty, it selects all namespaces. + // + // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. // +optional NamespaceSelector *metav1.LabelSelector - // IPBlock defines policy on a particular IPBlock + // IPBlock defines policy on a particular IPBlock. If this field is set then + // neither of the other fields can be. // +optional IPBlock *IPBlock } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/networking/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/networking/v1/zz_generated.conversion.go index a2407cca4..c6f815634 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/networking/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/networking/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/networking/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/networking/v1/zz_generated.defaults.go index 80b602454..3962a1376 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/networking/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/networking/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/networking/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/networking/validation/validation.go index 9f0a04c81..dc1934ca1 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/networking/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/networking/validation/validation.go @@ -33,6 +33,55 @@ func ValidateNetworkPolicyName(name string, prefix bool) []string { return apivalidation.NameIsDNSSubdomain(name, prefix) } +// ValidateNetworkPolicyPort validates a NetworkPolicyPort +func ValidateNetworkPolicyPort(port *networking.NetworkPolicyPort, portPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if port.Protocol != nil && *port.Protocol != api.ProtocolTCP && *port.Protocol != api.ProtocolUDP { + allErrs = append(allErrs, field.NotSupported(portPath.Child("protocol"), *port.Protocol, []string{string(api.ProtocolTCP), string(api.ProtocolUDP)})) + } + if port.Port != nil { + if port.Port.Type == intstr.Int { + for _, msg := range validation.IsValidPortNum(int(port.Port.IntVal)) { + allErrs = append(allErrs, field.Invalid(portPath.Child("port"), port.Port.IntVal, msg)) + } + } else { + for _, msg := range validation.IsValidPortName(port.Port.StrVal) { + allErrs = append(allErrs, field.Invalid(portPath.Child("port"), port.Port.StrVal, msg)) + } + } + } + + return allErrs +} + +// ValidateNetworkPolicyPeer validates a NetworkPolicyPeer +func ValidateNetworkPolicyPeer(peer *networking.NetworkPolicyPeer, peerPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + numPeers := 0 + + if peer.PodSelector != nil { + numPeers++ + allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(peer.PodSelector, peerPath.Child("podSelector"))...) + } + if peer.NamespaceSelector != nil { + numPeers++ + allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(peer.NamespaceSelector, peerPath.Child("namespaceSelector"))...) + } + if peer.IPBlock != nil { + numPeers++ + allErrs = append(allErrs, ValidateIPBlock(peer.IPBlock, peerPath.Child("ipBlock"))...) + } + + if numPeers == 0 { + allErrs = append(allErrs, field.Required(peerPath, "must specify a peer")) + } else if numPeers > 1 && peer.IPBlock != nil { + allErrs = append(allErrs, field.Forbidden(peerPath, "may not specify both ipBlock and another peer")) + } + + return allErrs +} + // ValidateNetworkPolicySpec tests if required fields in the networkpolicy spec are set. func ValidateNetworkPolicySpec(spec *networking.NetworkPolicySpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -43,41 +92,11 @@ func ValidateNetworkPolicySpec(spec *networking.NetworkPolicySpec, fldPath *fiel ingressPath := fldPath.Child("ingress").Index(i) for i, port := range ingress.Ports { portPath := ingressPath.Child("ports").Index(i) - if port.Protocol != nil && *port.Protocol != api.ProtocolTCP && *port.Protocol != api.ProtocolUDP { - allErrs = append(allErrs, field.NotSupported(portPath.Child("protocol"), *port.Protocol, []string{string(api.ProtocolTCP), string(api.ProtocolUDP)})) - } - if port.Port != nil { - if port.Port.Type == intstr.Int { - for _, msg := range validation.IsValidPortNum(int(port.Port.IntVal)) { - allErrs = append(allErrs, field.Invalid(portPath.Child("port"), port.Port.IntVal, msg)) - } - } else { - for _, msg := range validation.IsValidPortName(port.Port.StrVal) { - allErrs = append(allErrs, field.Invalid(portPath.Child("port"), port.Port.StrVal, msg)) - } - } - } + allErrs = append(allErrs, ValidateNetworkPolicyPort(&port, portPath)...) } for i, from := range ingress.From { fromPath := ingressPath.Child("from").Index(i) - numFroms := 0 - if from.PodSelector != nil { - numFroms++ - allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(from.PodSelector, fromPath.Child("podSelector"))...) - } - if from.NamespaceSelector != nil { - numFroms++ - allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(from.NamespaceSelector, fromPath.Child("namespaceSelector"))...) - } - if from.IPBlock != nil { - numFroms++ - allErrs = append(allErrs, ValidateIPBlock(from.IPBlock, fromPath.Child("ipBlock"))...) - } - if numFroms == 0 { - allErrs = append(allErrs, field.Required(fromPath, "must specify a from type")) - } else if numFroms > 1 { - allErrs = append(allErrs, field.Forbidden(fromPath, "may not specify more than 1 from type")) - } + allErrs = append(allErrs, ValidateNetworkPolicyPeer(&from, fromPath)...) } } // Validate egress rules @@ -85,41 +104,11 @@ func ValidateNetworkPolicySpec(spec *networking.NetworkPolicySpec, fldPath *fiel egressPath := fldPath.Child("egress").Index(i) for i, port := range egress.Ports { portPath := egressPath.Child("ports").Index(i) - if port.Protocol != nil && *port.Protocol != api.ProtocolTCP && *port.Protocol != api.ProtocolUDP { - allErrs = append(allErrs, field.NotSupported(portPath.Child("protocol"), *port.Protocol, []string{string(api.ProtocolTCP), string(api.ProtocolUDP)})) - } - if port.Port != nil { - if port.Port.Type == intstr.Int { - for _, msg := range validation.IsValidPortNum(int(port.Port.IntVal)) { - allErrs = append(allErrs, field.Invalid(portPath.Child("port"), port.Port.IntVal, msg)) - } - } else { - for _, msg := range validation.IsValidPortName(port.Port.StrVal) { - allErrs = append(allErrs, field.Invalid(portPath.Child("port"), port.Port.StrVal, msg)) - } - } - } + allErrs = append(allErrs, ValidateNetworkPolicyPort(&port, portPath)...) } for i, to := range egress.To { toPath := egressPath.Child("to").Index(i) - numTo := 0 - if to.PodSelector != nil { - numTo++ - allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(to.PodSelector, toPath.Child("podSelector"))...) - } - if to.NamespaceSelector != nil { - numTo++ - allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(to.NamespaceSelector, toPath.Child("namespaceSelector"))...) - } - if to.IPBlock != nil { - numTo++ - allErrs = append(allErrs, ValidateIPBlock(to.IPBlock, toPath.Child("ipBlock"))...) - } - if numTo == 0 { - allErrs = append(allErrs, field.Required(toPath, "must specify a to type")) - } else if numTo > 1 { - allErrs = append(allErrs, field.Forbidden(toPath, "may not specify more than 1 to type")) - } + allErrs = append(allErrs, ValidateNetworkPolicyPeer(&to, toPath)...) } } // Validate PolicyTypes diff --git a/vendor/k8s.io/kubernetes/pkg/apis/networking/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/apis/networking/validation/validation_test.go index 3af353d8c..67ebc24f9 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/networking/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/networking/validation/validation_test.go @@ -122,6 +122,28 @@ func TestValidateNetworkPolicy(t *testing.T) { }, }, }, + { + ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, + Spec: networking.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"a": "b"}, + }, + Ingress: []networking.NetworkPolicyIngressRule{ + { + From: []networking.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"c": "d"}, + }, + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"e": "f"}, + }, + }, + }, + }, + }, + }, + }, { ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: networking.NetworkPolicySpec{ @@ -256,7 +278,7 @@ func TestValidateNetworkPolicy(t *testing.T) { invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} errorCases := map[string]networking.NetworkPolicy{ - "namespaceSelector and podSelector": { + "namespaceSelector and ipBlock": { ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: networking.NetworkPolicySpec{ PodSelector: metav1.LabelSelector{ @@ -266,16 +288,25 @@ func TestValidateNetworkPolicy(t *testing.T) { { From: []networking.NetworkPolicyPeer{ { - PodSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, - }, NamespaceSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"c": "d"}, }, + IPBlock: &networking.IPBlock{ + CIDR: "192.168.0.0/16", + Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, + }, }, }, }, }, + }, + }, + "podSelector and ipBlock": { + ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, + Spec: networking.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"a": "b"}, + }, Egress: []networking.NetworkPolicyEgressRule{ { To: []networking.NetworkPolicyPeer{ @@ -283,8 +314,9 @@ func TestValidateNetworkPolicy(t *testing.T) { PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"c": "d"}, }, - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"c": "d"}, + IPBlock: &networking.IPBlock{ + CIDR: "192.168.0.0/16", + Except: []string{"192.168.3.0/24", "192.168.4.0/24"}, }, }, }, diff --git a/vendor/k8s.io/kubernetes/pkg/apis/networking/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/networking/zz_generated.deepcopy.go index 47121a572..43b6f5a78 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/networking/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/networking/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/policy/BUILD index 7bc57e36f..2b429bb08 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/BUILD @@ -15,7 +15,7 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/apis/policy", deps = [ - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/core:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/fuzzer/fuzzer.go index e6b5a6b97..184004fed 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/fuzzer/fuzzer.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/fuzzer/fuzzer.go @@ -30,5 +30,33 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { c.FuzzNoCustom(s) // fuzz self without calling this function again s.PodDisruptionsAllowed = int32(c.Rand.Intn(2)) }, + func(psp *policy.PodSecurityPolicySpec, c fuzz.Continue) { + c.FuzzNoCustom(psp) // fuzz self without calling this function again + + runAsUserRules := []policy.RunAsUserStrategy{ + policy.RunAsUserStrategyMustRunAsNonRoot, + policy.RunAsUserStrategyMustRunAs, + policy.RunAsUserStrategyRunAsAny, + } + psp.RunAsUser.Rule = runAsUserRules[c.Rand.Intn(len(runAsUserRules))] + + seLinuxRules := []policy.SELinuxStrategy{ + policy.SELinuxStrategyMustRunAs, + policy.SELinuxStrategyRunAsAny, + } + psp.SELinux.Rule = seLinuxRules[c.Rand.Intn(len(seLinuxRules))] + + supplementalGroupsRules := []policy.SupplementalGroupsStrategyType{ + policy.SupplementalGroupsStrategyRunAsAny, + policy.SupplementalGroupsStrategyMustRunAs, + } + psp.SupplementalGroups.Rule = supplementalGroupsRules[c.Rand.Intn(len(supplementalGroupsRules))] + + fsGroupRules := []policy.FSGroupStrategyType{ + policy.FSGroupStrategyMustRunAs, + policy.FSGroupStrategyRunAsAny, + } + psp.FSGroup.Rule = fsGroupRules[c.Rand.Intn(len(fsGroupRules))] + }, } } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/policy/install/BUILD index c42408b00..de072f8ed 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/install/BUILD @@ -13,10 +13,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/apis/policy/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/install/install.go index 7a6db9572..0d91720e4 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/install/install.go @@ -19,32 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/policy/v1beta1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: policy.GroupName, - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("PodSecurityPolicy"), - AddInternalObjectsToScheme: policy.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(policy.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/register.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/register.go index 6a91919e0..c82e200a1 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/register.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/register.go @@ -19,7 +19,6 @@ package policy import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/pkg/apis/extensions" ) // GroupName is the group name use in this package @@ -49,8 +48,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &PodDisruptionBudget{}, &PodDisruptionBudgetList{}, - &extensions.PodSecurityPolicy{}, - &extensions.PodSecurityPolicyList{}, + &PodSecurityPolicy{}, + &PodSecurityPolicyList{}, &Eviction{}, ) return nil diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/types.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/types.go index ddbf72296..298fcd0e4 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/types.go @@ -19,6 +19,7 @@ package policy import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + api "k8s.io/kubernetes/pkg/apis/core" ) // PodDisruptionBudgetSpec is a description of a PodDisruptionBudget. @@ -122,3 +123,285 @@ type Eviction struct { // +optional DeleteOptions *metav1.DeleteOptions } + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PodSecurityPolicy governs the ability to make requests that affect the SecurityContext +// that will be applied to a pod and container. +type PodSecurityPolicy struct { + metav1.TypeMeta + // +optional + metav1.ObjectMeta + + // Spec defines the policy enforced. + // +optional + Spec PodSecurityPolicySpec +} + +// PodSecurityPolicySpec defines the policy enforced. +type PodSecurityPolicySpec struct { + // Privileged determines if a pod can request to be run as privileged. + // +optional + Privileged bool + // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // unless the pod spec specifically drops the capability. You may not list a capability in both + // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the AllowedCapabilities list. + // +optional + DefaultAddCapabilities []api.Capability + // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // are required to be dropped and cannot be added. + // +optional + RequiredDropCapabilities []api.Capability + // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // Capabilities in this field may be added at the pod author's discretion. + // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // To allow all capabilities you may use '*'. + // +optional + AllowedCapabilities []api.Capability + // Volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. + // +optional + Volumes []FSType + // HostNetwork determines if the policy allows the use of HostNetwork in the pod spec. + // +optional + HostNetwork bool + // HostPorts determines which host port ranges are allowed to be exposed. + // +optional + HostPorts []HostPortRange + // HostPID determines if the policy allows the use of HostPID in the pod spec. + // +optional + HostPID bool + // HostIPC determines if the policy allows the use of HostIPC in the pod spec. + // +optional + HostIPC bool + // SELinux is the strategy that will dictate the allowable labels that may be set. + SELinux SELinuxStrategyOptions + // RunAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. + RunAsUser RunAsUserStrategyOptions + // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + SupplementalGroups SupplementalGroupsStrategyOptions + // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + FSGroup FSGroupStrategyOptions + // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // system. If the container specifically requests to run with a non-read only root file system + // the PSP should deny the pod. + // If set to false the container may run with a read only root file system if it wishes but it + // will not be forced to. + // +optional + ReadOnlyRootFilesystem bool + // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // process can gain more privileges than its parent process. + // +optional + DefaultAllowPrivilegeEscalation *bool + // AllowPrivilegeEscalation determines if a pod can request to allow + // privilege escalation. If unspecified, defaults to true. + // +optional + AllowPrivilegeEscalation bool + // AllowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used. + // +optional + AllowedHostPaths []AllowedHostPath + // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes + // is allowed in the "Volumes" field. + // +optional + AllowedFlexVolumes []AllowedFlexVolume + // AllowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + AllowedUnsafeSysctls []string + // ForbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + ForbiddenSysctls []string +} + +// AllowedHostPath defines the host volume conditions that will be enabled by a policy +// for pods to use. It requires the path prefix to be defined. +type AllowedHostPath struct { + // PathPrefix is the path prefix that the host volume must match. + // PathPrefix does not support `*`. + // Trailing slashes are trimmed when validating the path prefix with a host path. + // + // Examples: + // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` + // `/foo` would not allow `/food` or `/etc/foo` + PathPrefix string + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + ReadOnly bool +} + +// HostPortRange defines a range of host ports that will be enabled by a policy +// for pods to use. It requires both the start and end to be defined. +type HostPortRange struct { + // Min is the start of the range, inclusive. + Min int32 + // Max is the end of the range, inclusive. + Max int32 +} + +// AllowAllCapabilities can be used as a value for the PodSecurityPolicy.AllowAllCapabilities +// field and means that any capabilities are allowed to be requested. +var AllowAllCapabilities api.Capability = "*" + +// FSType gives strong typing to different file systems that are used by volumes. +type FSType string + +var ( + AzureFile FSType = "azureFile" + Flocker FSType = "flocker" + FlexVolume FSType = "flexVolume" + HostPath FSType = "hostPath" + EmptyDir FSType = "emptyDir" + GCEPersistentDisk FSType = "gcePersistentDisk" + AWSElasticBlockStore FSType = "awsElasticBlockStore" + GitRepo FSType = "gitRepo" + Secret FSType = "secret" + NFS FSType = "nfs" + ISCSI FSType = "iscsi" + Glusterfs FSType = "glusterfs" + PersistentVolumeClaim FSType = "persistentVolumeClaim" + RBD FSType = "rbd" + Cinder FSType = "cinder" + CephFS FSType = "cephFS" + DownwardAPI FSType = "downwardAPI" + FC FSType = "fc" + ConfigMap FSType = "configMap" + VsphereVolume FSType = "vsphereVolume" + Quobyte FSType = "quobyte" + AzureDisk FSType = "azureDisk" + PhotonPersistentDisk FSType = "photonPersistentDisk" + StorageOS FSType = "storageos" + Projected FSType = "projected" + PortworxVolume FSType = "portworxVolume" + ScaleIO FSType = "scaleIO" + CSI FSType = "csi" + All FSType = "*" +) + +// AllowedFlexVolume represents a single Flexvolume that is allowed to be used. +type AllowedFlexVolume struct { + // Driver is the name of the Flexvolume driver. + Driver string +} + +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. +type SELinuxStrategyOptions struct { + // Rule is the strategy that will dictate the allowable labels that may be set. + Rule SELinuxStrategy + // SELinuxOptions required to run as; required for MustRunAs + // More info: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#selinux + // +optional + SELinuxOptions *api.SELinuxOptions +} + +// SELinuxStrategy denotes strategy types for generating SELinux options for a +// Security. +type SELinuxStrategy string + +const ( + // SELinuxStrategyMustRunAs means that container must have SELinux labels of X applied. + SELinuxStrategyMustRunAs SELinuxStrategy = "MustRunAs" + // SELinuxStrategyRunAsAny means that container may make requests for any SELinux context labels. + SELinuxStrategyRunAsAny SELinuxStrategy = "RunAsAny" +) + +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. +type RunAsUserStrategyOptions struct { + // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + Rule RunAsUserStrategy + // Ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. + // +optional + Ranges []IDRange +} + +// IDRange provides a min/max of an allowed range of IDs. +type IDRange struct { + // Min is the start of the range, inclusive. + Min int64 + // Max is the end of the range, inclusive. + Max int64 +} + +// RunAsUserStrategy denotes strategy types for generating RunAsUser values for a +// SecurityContext. +type RunAsUserStrategy string + +const ( + // RunAsUserStrategyMustRunAs means that container must run as a particular uid. + RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs" + // RunAsUserStrategyMustRunAsNonRoot means that container must run as a non-root uid + RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot" + // RunAsUserStrategyRunAsAny means that container may make requests for any uid. + RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny" +) + +// FSGroupStrategyOptions defines the strategy type and options used to create the strategy. +type FSGroupStrategyOptions struct { + // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // +optional + Rule FSGroupStrategyType + // Ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. + // +optional + Ranges []IDRange +} + +// FSGroupStrategyType denotes strategy types for generating FSGroup values for a +// SecurityContext +type FSGroupStrategyType string + +const ( + // FSGroupStrategyMustRunAs means that container must have FSGroup of X applied. + FSGroupStrategyMustRunAs FSGroupStrategyType = "MustRunAs" + // FSGroupStrategyRunAsAny means that container may make requests for any FSGroup labels. + FSGroupStrategyRunAsAny FSGroupStrategyType = "RunAsAny" +) + +// SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. +type SupplementalGroupsStrategyOptions struct { + // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // +optional + Rule SupplementalGroupsStrategyType + // Ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. + // +optional + Ranges []IDRange +} + +// SupplementalGroupsStrategyType denotes strategy types for determining valid supplemental +// groups for a SecurityContext. +type SupplementalGroupsStrategyType string + +const ( + // SupplementalGroupsStrategyMustRunAs means that container must run as a particular gid. + SupplementalGroupsStrategyMustRunAs SupplementalGroupsStrategyType = "MustRunAs" + // SupplementalGroupsStrategyRunAsAny means that container may make requests for any gid. + SupplementalGroupsStrategyRunAsAny SupplementalGroupsStrategyType = "RunAsAny" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. +type PodSecurityPolicyList struct { + metav1.TypeMeta + // +optional + metav1.ListMeta + + Items []PodSecurityPolicy +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/BUILD index 3cf454b61..527320c00 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/BUILD @@ -17,7 +17,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/apis/policy/v1beta1", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", "//pkg/apis/policy:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/doc.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/doc.go index 925a0b742..9629da3fc 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/doc.go @@ -15,7 +15,6 @@ limitations under the License. */ // +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/policy -// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/extensions // +k8s:conversion-gen-external-types=k8s.io/api/policy/v1beta1 // +k8s:defaulter-gen=TypeMeta // +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/policy/v1beta1 diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/zz_generated.conversion.go index 1b2641798..4e4e3cb1b 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -30,7 +30,6 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" intstr "k8s.io/apimachinery/pkg/util/intstr" core "k8s.io/kubernetes/pkg/apis/core" - extensions "k8s.io/kubernetes/pkg/apis/extensions" policy "k8s.io/kubernetes/pkg/apis/policy" ) @@ -42,16 +41,18 @@ func init() { // Public to allow building arbitrary schemes. func RegisterConversions(scheme *runtime.Scheme) error { return scheme.AddGeneratedConversionFuncs( - Convert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume, - Convert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume, - Convert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath, - Convert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath, + Convert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume, + Convert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume, + Convert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath, + Convert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath, Convert_v1beta1_Eviction_To_policy_Eviction, Convert_policy_Eviction_To_v1beta1_Eviction, - Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions, - Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions, - Convert_v1beta1_HostPortRange_To_extensions_HostPortRange, - Convert_extensions_HostPortRange_To_v1beta1_HostPortRange, + Convert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions, + Convert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions, + Convert_v1beta1_HostPortRange_To_policy_HostPortRange, + Convert_policy_HostPortRange_To_v1beta1_HostPortRange, + Convert_v1beta1_IDRange_To_policy_IDRange, + Convert_policy_IDRange_To_v1beta1_IDRange, Convert_v1beta1_PodDisruptionBudget_To_policy_PodDisruptionBudget, Convert_policy_PodDisruptionBudget_To_v1beta1_PodDisruptionBudget, Convert_v1beta1_PodDisruptionBudgetList_To_policy_PodDisruptionBudgetList, @@ -60,59 +61,61 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_policy_PodDisruptionBudgetSpec_To_v1beta1_PodDisruptionBudgetSpec, Convert_v1beta1_PodDisruptionBudgetStatus_To_policy_PodDisruptionBudgetStatus, Convert_policy_PodDisruptionBudgetStatus_To_v1beta1_PodDisruptionBudgetStatus, - Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy, - Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy, - Convert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList, - Convert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList, - Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec, - Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec, - Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions, - Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions, - Convert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions, - Convert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions, - Convert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions, - Convert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions, + Convert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy, + Convert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy, + Convert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList, + Convert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList, + Convert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec, + Convert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec, + Convert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions, + Convert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions, + Convert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions, + Convert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions, + Convert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions, + Convert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions, ) } -func autoConvert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume(in *v1beta1.AllowedFlexVolume, out *extensions.AllowedFlexVolume, s conversion.Scope) error { +func autoConvert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume(in *v1beta1.AllowedFlexVolume, out *policy.AllowedFlexVolume, s conversion.Scope) error { out.Driver = in.Driver return nil } -// Convert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume is an autogenerated conversion function. -func Convert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume(in *v1beta1.AllowedFlexVolume, out *extensions.AllowedFlexVolume, s conversion.Scope) error { - return autoConvert_v1beta1_AllowedFlexVolume_To_extensions_AllowedFlexVolume(in, out, s) +// Convert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume is an autogenerated conversion function. +func Convert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume(in *v1beta1.AllowedFlexVolume, out *policy.AllowedFlexVolume, s conversion.Scope) error { + return autoConvert_v1beta1_AllowedFlexVolume_To_policy_AllowedFlexVolume(in, out, s) } -func autoConvert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *extensions.AllowedFlexVolume, out *v1beta1.AllowedFlexVolume, s conversion.Scope) error { +func autoConvert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *policy.AllowedFlexVolume, out *v1beta1.AllowedFlexVolume, s conversion.Scope) error { out.Driver = in.Driver return nil } -// Convert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume is an autogenerated conversion function. -func Convert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *extensions.AllowedFlexVolume, out *v1beta1.AllowedFlexVolume, s conversion.Scope) error { - return autoConvert_extensions_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in, out, s) +// Convert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume is an autogenerated conversion function. +func Convert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in *policy.AllowedFlexVolume, out *v1beta1.AllowedFlexVolume, s conversion.Scope) error { + return autoConvert_policy_AllowedFlexVolume_To_v1beta1_AllowedFlexVolume(in, out, s) } -func autoConvert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath(in *v1beta1.AllowedHostPath, out *extensions.AllowedHostPath, s conversion.Scope) error { +func autoConvert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in *v1beta1.AllowedHostPath, out *policy.AllowedHostPath, s conversion.Scope) error { out.PathPrefix = in.PathPrefix + out.ReadOnly = in.ReadOnly return nil } -// Convert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath is an autogenerated conversion function. -func Convert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath(in *v1beta1.AllowedHostPath, out *extensions.AllowedHostPath, s conversion.Scope) error { - return autoConvert_v1beta1_AllowedHostPath_To_extensions_AllowedHostPath(in, out, s) +// Convert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath is an autogenerated conversion function. +func Convert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in *v1beta1.AllowedHostPath, out *policy.AllowedHostPath, s conversion.Scope) error { + return autoConvert_v1beta1_AllowedHostPath_To_policy_AllowedHostPath(in, out, s) } -func autoConvert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath(in *extensions.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { +func autoConvert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath(in *policy.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { out.PathPrefix = in.PathPrefix + out.ReadOnly = in.ReadOnly return nil } -// Convert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath is an autogenerated conversion function. -func Convert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath(in *extensions.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { - return autoConvert_extensions_AllowedHostPath_To_v1beta1_AllowedHostPath(in, out, s) +// Convert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath is an autogenerated conversion function. +func Convert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath(in *policy.AllowedHostPath, out *v1beta1.AllowedHostPath, s conversion.Scope) error { + return autoConvert_policy_AllowedHostPath_To_v1beta1_AllowedHostPath(in, out, s) } func autoConvert_v1beta1_Eviction_To_policy_Eviction(in *v1beta1.Eviction, out *policy.Eviction, s conversion.Scope) error { @@ -137,48 +140,70 @@ func Convert_policy_Eviction_To_v1beta1_Eviction(in *policy.Eviction, out *v1bet return autoConvert_policy_Eviction_To_v1beta1_Eviction(in, out, s) } -func autoConvert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(in *v1beta1.FSGroupStrategyOptions, out *extensions.FSGroupStrategyOptions, s conversion.Scope) error { - out.Rule = extensions.FSGroupStrategyType(in.Rule) - out.Ranges = *(*[]extensions.GroupIDRange)(unsafe.Pointer(&in.Ranges)) +func autoConvert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions(in *v1beta1.FSGroupStrategyOptions, out *policy.FSGroupStrategyOptions, s conversion.Scope) error { + out.Rule = policy.FSGroupStrategyType(in.Rule) + out.Ranges = *(*[]policy.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions is an autogenerated conversion function. -func Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(in *v1beta1.FSGroupStrategyOptions, out *extensions.FSGroupStrategyOptions, s conversion.Scope) error { - return autoConvert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(in, out, s) +// Convert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions is an autogenerated conversion function. +func Convert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions(in *v1beta1.FSGroupStrategyOptions, out *policy.FSGroupStrategyOptions, s conversion.Scope) error { + return autoConvert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions(in, out, s) } -func autoConvert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in *extensions.FSGroupStrategyOptions, out *v1beta1.FSGroupStrategyOptions, s conversion.Scope) error { +func autoConvert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in *policy.FSGroupStrategyOptions, out *v1beta1.FSGroupStrategyOptions, s conversion.Scope) error { out.Rule = v1beta1.FSGroupStrategyType(in.Rule) out.Ranges = *(*[]v1beta1.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions is an autogenerated conversion function. -func Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in *extensions.FSGroupStrategyOptions, out *v1beta1.FSGroupStrategyOptions, s conversion.Scope) error { - return autoConvert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in, out, s) +// Convert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions is an autogenerated conversion function. +func Convert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in *policy.FSGroupStrategyOptions, out *v1beta1.FSGroupStrategyOptions, s conversion.Scope) error { + return autoConvert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in, out, s) } -func autoConvert_v1beta1_HostPortRange_To_extensions_HostPortRange(in *v1beta1.HostPortRange, out *extensions.HostPortRange, s conversion.Scope) error { +func autoConvert_v1beta1_HostPortRange_To_policy_HostPortRange(in *v1beta1.HostPortRange, out *policy.HostPortRange, s conversion.Scope) error { out.Min = in.Min out.Max = in.Max return nil } -// Convert_v1beta1_HostPortRange_To_extensions_HostPortRange is an autogenerated conversion function. -func Convert_v1beta1_HostPortRange_To_extensions_HostPortRange(in *v1beta1.HostPortRange, out *extensions.HostPortRange, s conversion.Scope) error { - return autoConvert_v1beta1_HostPortRange_To_extensions_HostPortRange(in, out, s) +// Convert_v1beta1_HostPortRange_To_policy_HostPortRange is an autogenerated conversion function. +func Convert_v1beta1_HostPortRange_To_policy_HostPortRange(in *v1beta1.HostPortRange, out *policy.HostPortRange, s conversion.Scope) error { + return autoConvert_v1beta1_HostPortRange_To_policy_HostPortRange(in, out, s) } -func autoConvert_extensions_HostPortRange_To_v1beta1_HostPortRange(in *extensions.HostPortRange, out *v1beta1.HostPortRange, s conversion.Scope) error { +func autoConvert_policy_HostPortRange_To_v1beta1_HostPortRange(in *policy.HostPortRange, out *v1beta1.HostPortRange, s conversion.Scope) error { out.Min = in.Min out.Max = in.Max return nil } -// Convert_extensions_HostPortRange_To_v1beta1_HostPortRange is an autogenerated conversion function. -func Convert_extensions_HostPortRange_To_v1beta1_HostPortRange(in *extensions.HostPortRange, out *v1beta1.HostPortRange, s conversion.Scope) error { - return autoConvert_extensions_HostPortRange_To_v1beta1_HostPortRange(in, out, s) +// Convert_policy_HostPortRange_To_v1beta1_HostPortRange is an autogenerated conversion function. +func Convert_policy_HostPortRange_To_v1beta1_HostPortRange(in *policy.HostPortRange, out *v1beta1.HostPortRange, s conversion.Scope) error { + return autoConvert_policy_HostPortRange_To_v1beta1_HostPortRange(in, out, s) +} + +func autoConvert_v1beta1_IDRange_To_policy_IDRange(in *v1beta1.IDRange, out *policy.IDRange, s conversion.Scope) error { + out.Min = in.Min + out.Max = in.Max + return nil +} + +// Convert_v1beta1_IDRange_To_policy_IDRange is an autogenerated conversion function. +func Convert_v1beta1_IDRange_To_policy_IDRange(in *v1beta1.IDRange, out *policy.IDRange, s conversion.Scope) error { + return autoConvert_v1beta1_IDRange_To_policy_IDRange(in, out, s) +} + +func autoConvert_policy_IDRange_To_v1beta1_IDRange(in *policy.IDRange, out *v1beta1.IDRange, s conversion.Scope) error { + out.Min = in.Min + out.Max = in.Max + return nil +} + +// Convert_policy_IDRange_To_v1beta1_IDRange is an autogenerated conversion function. +func Convert_policy_IDRange_To_v1beta1_IDRange(in *policy.IDRange, out *v1beta1.IDRange, s conversion.Scope) error { + return autoConvert_policy_IDRange_To_v1beta1_IDRange(in, out, s) } func autoConvert_v1beta1_PodDisruptionBudget_To_policy_PodDisruptionBudget(in *v1beta1.PodDisruptionBudget, out *policy.PodDisruptionBudget, s conversion.Scope) error { @@ -289,39 +314,39 @@ func Convert_policy_PodDisruptionBudgetStatus_To_v1beta1_PodDisruptionBudgetStat return autoConvert_policy_PodDisruptionBudgetStatus_To_v1beta1_PodDisruptionBudgetStatus(in, out, s) } -func autoConvert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(in *v1beta1.PodSecurityPolicy, out *extensions.PodSecurityPolicy, s conversion.Scope) error { +func autoConvert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy(in *v1beta1.PodSecurityPolicy, out *policy.PodSecurityPolicy, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy is an autogenerated conversion function. -func Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(in *v1beta1.PodSecurityPolicy, out *extensions.PodSecurityPolicy, s conversion.Scope) error { - return autoConvert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(in, out, s) +// Convert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy is an autogenerated conversion function. +func Convert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy(in *v1beta1.PodSecurityPolicy, out *policy.PodSecurityPolicy, s conversion.Scope) error { + return autoConvert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy(in, out, s) } -func autoConvert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *extensions.PodSecurityPolicy, out *v1beta1.PodSecurityPolicy, s conversion.Scope) error { +func autoConvert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *policy.PodSecurityPolicy, out *v1beta1.PodSecurityPolicy, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - if err := Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil { + if err := Convert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil { return err } return nil } -// Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy is an autogenerated conversion function. -func Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *extensions.PodSecurityPolicy, out *v1beta1.PodSecurityPolicy, s conversion.Scope) error { - return autoConvert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in, out, s) +// Convert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy is an autogenerated conversion function. +func Convert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *policy.PodSecurityPolicy, out *v1beta1.PodSecurityPolicy, s conversion.Scope) error { + return autoConvert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in, out, s) } -func autoConvert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList(in *v1beta1.PodSecurityPolicyList, out *extensions.PodSecurityPolicyList, s conversion.Scope) error { +func autoConvert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList(in *v1beta1.PodSecurityPolicyList, out *policy.PodSecurityPolicyList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]extensions.PodSecurityPolicy, len(*in)) + *out = make([]policy.PodSecurityPolicy, len(*in)) for i := range *in { - if err := Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_PodSecurityPolicy_To_policy_PodSecurityPolicy(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -331,18 +356,18 @@ func autoConvert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyLi return nil } -// Convert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList is an autogenerated conversion function. -func Convert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList(in *v1beta1.PodSecurityPolicyList, out *extensions.PodSecurityPolicyList, s conversion.Scope) error { - return autoConvert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList(in, out, s) +// Convert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList is an autogenerated conversion function. +func Convert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList(in *v1beta1.PodSecurityPolicyList, out *policy.PodSecurityPolicyList, s conversion.Scope) error { + return autoConvert_v1beta1_PodSecurityPolicyList_To_policy_PodSecurityPolicyList(in, out, s) } -func autoConvert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *extensions.PodSecurityPolicyList, out *v1beta1.PodSecurityPolicyList, s conversion.Scope) error { +func autoConvert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *policy.PodSecurityPolicyList, out *v1beta1.PodSecurityPolicyList, s conversion.Scope) error { out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]v1beta1.PodSecurityPolicy, len(*in)) for i := range *in { - if err := Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_policy_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -352,31 +377,31 @@ func autoConvert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyLi return nil } -// Convert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList is an autogenerated conversion function. -func Convert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *extensions.PodSecurityPolicyList, out *v1beta1.PodSecurityPolicyList, s conversion.Scope) error { - return autoConvert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in, out, s) +// Convert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList is an autogenerated conversion function. +func Convert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *policy.PodSecurityPolicyList, out *v1beta1.PodSecurityPolicyList, s conversion.Scope) error { + return autoConvert_policy_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in, out, s) } -func autoConvert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(in *v1beta1.PodSecurityPolicySpec, out *extensions.PodSecurityPolicySpec, s conversion.Scope) error { +func autoConvert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(in *v1beta1.PodSecurityPolicySpec, out *policy.PodSecurityPolicySpec, s conversion.Scope) error { out.Privileged = in.Privileged out.DefaultAddCapabilities = *(*[]core.Capability)(unsafe.Pointer(&in.DefaultAddCapabilities)) out.RequiredDropCapabilities = *(*[]core.Capability)(unsafe.Pointer(&in.RequiredDropCapabilities)) out.AllowedCapabilities = *(*[]core.Capability)(unsafe.Pointer(&in.AllowedCapabilities)) - out.Volumes = *(*[]extensions.FSType)(unsafe.Pointer(&in.Volumes)) + out.Volumes = *(*[]policy.FSType)(unsafe.Pointer(&in.Volumes)) out.HostNetwork = in.HostNetwork - out.HostPorts = *(*[]extensions.HostPortRange)(unsafe.Pointer(&in.HostPorts)) + out.HostPorts = *(*[]policy.HostPortRange)(unsafe.Pointer(&in.HostPorts)) out.HostPID = in.HostPID out.HostIPC = in.HostIPC - if err := Convert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions(&in.SELinux, &out.SELinux, s); err != nil { + if err := Convert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions(&in.SELinux, &out.SELinux, s); err != nil { return err } - if err := Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil { + if err := Convert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil { return err } - if err := Convert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions(&in.SupplementalGroups, &out.SupplementalGroups, s); err != nil { + if err := Convert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions(&in.SupplementalGroups, &out.SupplementalGroups, s); err != nil { return err } - if err := Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(&in.FSGroup, &out.FSGroup, s); err != nil { + if err := Convert_v1beta1_FSGroupStrategyOptions_To_policy_FSGroupStrategyOptions(&in.FSGroup, &out.FSGroup, s); err != nil { return err } out.ReadOnlyRootFilesystem = in.ReadOnlyRootFilesystem @@ -384,17 +409,19 @@ func autoConvert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySp if err := v1.Convert_Pointer_bool_To_bool(&in.AllowPrivilegeEscalation, &out.AllowPrivilegeEscalation, s); err != nil { return err } - out.AllowedHostPaths = *(*[]extensions.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) - out.AllowedFlexVolumes = *(*[]extensions.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedHostPaths = *(*[]policy.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) + out.AllowedFlexVolumes = *(*[]policy.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedUnsafeSysctls = *(*[]string)(unsafe.Pointer(&in.AllowedUnsafeSysctls)) + out.ForbiddenSysctls = *(*[]string)(unsafe.Pointer(&in.ForbiddenSysctls)) return nil } -// Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec is an autogenerated conversion function. -func Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(in *v1beta1.PodSecurityPolicySpec, out *extensions.PodSecurityPolicySpec, s conversion.Scope) error { - return autoConvert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(in, out, s) +// Convert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec is an autogenerated conversion function. +func Convert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(in *v1beta1.PodSecurityPolicySpec, out *policy.PodSecurityPolicySpec, s conversion.Scope) error { + return autoConvert_v1beta1_PodSecurityPolicySpec_To_policy_PodSecurityPolicySpec(in, out, s) } -func autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *extensions.PodSecurityPolicySpec, out *v1beta1.PodSecurityPolicySpec, s conversion.Scope) error { +func autoConvert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *policy.PodSecurityPolicySpec, out *v1beta1.PodSecurityPolicySpec, s conversion.Scope) error { out.Privileged = in.Privileged out.DefaultAddCapabilities = *(*[]core_v1.Capability)(unsafe.Pointer(&in.DefaultAddCapabilities)) out.RequiredDropCapabilities = *(*[]core_v1.Capability)(unsafe.Pointer(&in.RequiredDropCapabilities)) @@ -404,16 +431,16 @@ func autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySp out.HostPorts = *(*[]v1beta1.HostPortRange)(unsafe.Pointer(&in.HostPorts)) out.HostPID = in.HostPID out.HostIPC = in.HostIPC - if err := Convert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(&in.SELinux, &out.SELinux, s); err != nil { + if err := Convert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(&in.SELinux, &out.SELinux, s); err != nil { return err } - if err := Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil { + if err := Convert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil { return err } - if err := Convert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(&in.SupplementalGroups, &out.SupplementalGroups, s); err != nil { + if err := Convert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(&in.SupplementalGroups, &out.SupplementalGroups, s); err != nil { return err } - if err := Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(&in.FSGroup, &out.FSGroup, s); err != nil { + if err := Convert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(&in.FSGroup, &out.FSGroup, s); err != nil { return err } out.ReadOnlyRootFilesystem = in.ReadOnlyRootFilesystem @@ -423,76 +450,78 @@ func autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySp } out.AllowedHostPaths = *(*[]v1beta1.AllowedHostPath)(unsafe.Pointer(&in.AllowedHostPaths)) out.AllowedFlexVolumes = *(*[]v1beta1.AllowedFlexVolume)(unsafe.Pointer(&in.AllowedFlexVolumes)) + out.AllowedUnsafeSysctls = *(*[]string)(unsafe.Pointer(&in.AllowedUnsafeSysctls)) + out.ForbiddenSysctls = *(*[]string)(unsafe.Pointer(&in.ForbiddenSysctls)) return nil } -// Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec is an autogenerated conversion function. -func Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *extensions.PodSecurityPolicySpec, out *v1beta1.PodSecurityPolicySpec, s conversion.Scope) error { - return autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in, out, s) +// Convert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec is an autogenerated conversion function. +func Convert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *policy.PodSecurityPolicySpec, out *v1beta1.PodSecurityPolicySpec, s conversion.Scope) error { + return autoConvert_policy_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in, out, s) } -func autoConvert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(in *v1beta1.RunAsUserStrategyOptions, out *extensions.RunAsUserStrategyOptions, s conversion.Scope) error { - out.Rule = extensions.RunAsUserStrategy(in.Rule) - out.Ranges = *(*[]extensions.UserIDRange)(unsafe.Pointer(&in.Ranges)) +func autoConvert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions(in *v1beta1.RunAsUserStrategyOptions, out *policy.RunAsUserStrategyOptions, s conversion.Scope) error { + out.Rule = policy.RunAsUserStrategy(in.Rule) + out.Ranges = *(*[]policy.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions is an autogenerated conversion function. -func Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(in *v1beta1.RunAsUserStrategyOptions, out *extensions.RunAsUserStrategyOptions, s conversion.Scope) error { - return autoConvert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(in, out, s) +// Convert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions is an autogenerated conversion function. +func Convert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions(in *v1beta1.RunAsUserStrategyOptions, out *policy.RunAsUserStrategyOptions, s conversion.Scope) error { + return autoConvert_v1beta1_RunAsUserStrategyOptions_To_policy_RunAsUserStrategyOptions(in, out, s) } -func autoConvert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *extensions.RunAsUserStrategyOptions, out *v1beta1.RunAsUserStrategyOptions, s conversion.Scope) error { +func autoConvert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *policy.RunAsUserStrategyOptions, out *v1beta1.RunAsUserStrategyOptions, s conversion.Scope) error { out.Rule = v1beta1.RunAsUserStrategy(in.Rule) out.Ranges = *(*[]v1beta1.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions is an autogenerated conversion function. -func Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *extensions.RunAsUserStrategyOptions, out *v1beta1.RunAsUserStrategyOptions, s conversion.Scope) error { - return autoConvert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in, out, s) +// Convert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions is an autogenerated conversion function. +func Convert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *policy.RunAsUserStrategyOptions, out *v1beta1.RunAsUserStrategyOptions, s conversion.Scope) error { + return autoConvert_policy_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in, out, s) } -func autoConvert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions(in *v1beta1.SELinuxStrategyOptions, out *extensions.SELinuxStrategyOptions, s conversion.Scope) error { - out.Rule = extensions.SELinuxStrategy(in.Rule) +func autoConvert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions(in *v1beta1.SELinuxStrategyOptions, out *policy.SELinuxStrategyOptions, s conversion.Scope) error { + out.Rule = policy.SELinuxStrategy(in.Rule) out.SELinuxOptions = (*core.SELinuxOptions)(unsafe.Pointer(in.SELinuxOptions)) return nil } -// Convert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions is an autogenerated conversion function. -func Convert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions(in *v1beta1.SELinuxStrategyOptions, out *extensions.SELinuxStrategyOptions, s conversion.Scope) error { - return autoConvert_v1beta1_SELinuxStrategyOptions_To_extensions_SELinuxStrategyOptions(in, out, s) +// Convert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions is an autogenerated conversion function. +func Convert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions(in *v1beta1.SELinuxStrategyOptions, out *policy.SELinuxStrategyOptions, s conversion.Scope) error { + return autoConvert_v1beta1_SELinuxStrategyOptions_To_policy_SELinuxStrategyOptions(in, out, s) } -func autoConvert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in *extensions.SELinuxStrategyOptions, out *v1beta1.SELinuxStrategyOptions, s conversion.Scope) error { +func autoConvert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in *policy.SELinuxStrategyOptions, out *v1beta1.SELinuxStrategyOptions, s conversion.Scope) error { out.Rule = v1beta1.SELinuxStrategy(in.Rule) out.SELinuxOptions = (*core_v1.SELinuxOptions)(unsafe.Pointer(in.SELinuxOptions)) return nil } -// Convert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions is an autogenerated conversion function. -func Convert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in *extensions.SELinuxStrategyOptions, out *v1beta1.SELinuxStrategyOptions, s conversion.Scope) error { - return autoConvert_extensions_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in, out, s) +// Convert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions is an autogenerated conversion function. +func Convert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in *policy.SELinuxStrategyOptions, out *v1beta1.SELinuxStrategyOptions, s conversion.Scope) error { + return autoConvert_policy_SELinuxStrategyOptions_To_v1beta1_SELinuxStrategyOptions(in, out, s) } -func autoConvert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions(in *v1beta1.SupplementalGroupsStrategyOptions, out *extensions.SupplementalGroupsStrategyOptions, s conversion.Scope) error { - out.Rule = extensions.SupplementalGroupsStrategyType(in.Rule) - out.Ranges = *(*[]extensions.GroupIDRange)(unsafe.Pointer(&in.Ranges)) +func autoConvert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions(in *v1beta1.SupplementalGroupsStrategyOptions, out *policy.SupplementalGroupsStrategyOptions, s conversion.Scope) error { + out.Rule = policy.SupplementalGroupsStrategyType(in.Rule) + out.Ranges = *(*[]policy.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions is an autogenerated conversion function. -func Convert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions(in *v1beta1.SupplementalGroupsStrategyOptions, out *extensions.SupplementalGroupsStrategyOptions, s conversion.Scope) error { - return autoConvert_v1beta1_SupplementalGroupsStrategyOptions_To_extensions_SupplementalGroupsStrategyOptions(in, out, s) +// Convert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions is an autogenerated conversion function. +func Convert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions(in *v1beta1.SupplementalGroupsStrategyOptions, out *policy.SupplementalGroupsStrategyOptions, s conversion.Scope) error { + return autoConvert_v1beta1_SupplementalGroupsStrategyOptions_To_policy_SupplementalGroupsStrategyOptions(in, out, s) } -func autoConvert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in *extensions.SupplementalGroupsStrategyOptions, out *v1beta1.SupplementalGroupsStrategyOptions, s conversion.Scope) error { +func autoConvert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in *policy.SupplementalGroupsStrategyOptions, out *v1beta1.SupplementalGroupsStrategyOptions, s conversion.Scope) error { out.Rule = v1beta1.SupplementalGroupsStrategyType(in.Rule) out.Ranges = *(*[]v1beta1.IDRange)(unsafe.Pointer(&in.Ranges)) return nil } -// Convert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions is an autogenerated conversion function. -func Convert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in *extensions.SupplementalGroupsStrategyOptions, out *v1beta1.SupplementalGroupsStrategyOptions, s conversion.Scope) error { - return autoConvert_extensions_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in, out, s) +// Convert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions is an autogenerated conversion function. +func Convert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in *policy.SupplementalGroupsStrategyOptions, out *v1beta1.SupplementalGroupsStrategyOptions, s conversion.Scope) error { + return autoConvert_policy_SupplementalGroupsStrategyOptions_To_v1beta1_SupplementalGroupsStrategyOptions(in, out, s) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/zz_generated.defaults.go index 769d0152e..c0cd579f5 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/BUILD index 1faa84cff..14fcee1d6 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/BUILD @@ -11,11 +11,18 @@ go_library( srcs = ["validation.go"], importpath = "k8s.io/kubernetes/pkg/apis/policy/validation", deps = [ + "//pkg/apis/core:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/apis/extensions/validation:go_default_library", "//pkg/apis/policy:go_default_library", + "//pkg/features:go_default_library", + "//pkg/security/apparmor:go_default_library", + "//pkg/security/podsecuritypolicy/seccomp:go_default_library", + "//pkg/security/podsecuritypolicy/util:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) @@ -24,7 +31,12 @@ go_test( srcs = ["validation_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/apis/core:go_default_library", "//pkg/apis/policy:go_default_library", + "//pkg/security/apparmor:go_default_library", + "//pkg/security/podsecuritypolicy/seccomp:go_default_library", + "//pkg/security/podsecuritypolicy/util:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/validation.go index cae1609de..aa898ad8f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/validation.go @@ -17,13 +17,25 @@ limitations under the License. package validation import ( + "fmt" + "path/filepath" "reflect" + "regexp" + "strings" unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" + core "k8s.io/kubernetes/pkg/apis/core" apivalidation "k8s.io/kubernetes/pkg/apis/core/validation" extensionsvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" "k8s.io/kubernetes/pkg/apis/policy" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/security/apparmor" + "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" + psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" + + utilfeature "k8s.io/apiserver/pkg/util/feature" ) func ValidatePodDisruptionBudget(pdb *policy.PodDisruptionBudget) field.ErrorList { @@ -77,3 +89,355 @@ func ValidatePodDisruptionBudgetStatus(status policy.PodDisruptionBudgetStatus, allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.ExpectedPods), fldPath.Child("expectedPods"))...) return allErrs } + +// ValidatePodSecurityPolicyName can be used to check whether the given +// pod security policy name is valid. +// Prefix indicates this name will be used as part of generation, in which case +// trailing dashes are allowed. +var ValidatePodSecurityPolicyName = apivalidation.NameIsDNSSubdomain + +func ValidatePodSecurityPolicy(psp *policy.PodSecurityPolicy) field.ErrorList { + allErrs := field.ErrorList{} + allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&psp.ObjectMeta, false, ValidatePodSecurityPolicyName, field.NewPath("metadata"))...) + allErrs = append(allErrs, ValidatePodSecurityPolicySpecificAnnotations(psp.Annotations, field.NewPath("metadata").Child("annotations"))...) + allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&psp.Spec, field.NewPath("spec"))...) + return allErrs +} + +func ValidatePodSecurityPolicySpec(spec *policy.PodSecurityPolicySpec, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + allErrs = append(allErrs, validatePSPRunAsUser(fldPath.Child("runAsUser"), &spec.RunAsUser)...) + allErrs = append(allErrs, validatePSPSELinux(fldPath.Child("seLinux"), &spec.SELinux)...) + allErrs = append(allErrs, validatePSPSupplementalGroup(fldPath.Child("supplementalGroups"), &spec.SupplementalGroups)...) + allErrs = append(allErrs, validatePSPFSGroup(fldPath.Child("fsGroup"), &spec.FSGroup)...) + allErrs = append(allErrs, validatePodSecurityPolicyVolumes(fldPath, spec.Volumes)...) + if len(spec.RequiredDropCapabilities) > 0 && hasCap(policy.AllowAllCapabilities, spec.AllowedCapabilities) { + allErrs = append(allErrs, field.Invalid(field.NewPath("requiredDropCapabilities"), spec.RequiredDropCapabilities, + "must be empty when all capabilities are allowed by a wildcard")) + } + allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.DefaultAddCapabilities, field.NewPath("defaultAddCapabilities"))...) + allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.AllowedCapabilities, field.NewPath("allowedCapabilities"))...) + allErrs = append(allErrs, validatePSPDefaultAllowPrivilegeEscalation(fldPath.Child("defaultAllowPrivilegeEscalation"), spec.DefaultAllowPrivilegeEscalation, spec.AllowPrivilegeEscalation)...) + allErrs = append(allErrs, validatePSPAllowedHostPaths(fldPath.Child("allowedHostPaths"), spec.AllowedHostPaths)...) + allErrs = append(allErrs, validatePSPAllowedFlexVolumes(fldPath.Child("allowedFlexVolumes"), spec.AllowedFlexVolumes)...) + allErrs = append(allErrs, validatePodSecurityPolicySysctls(fldPath.Child("allowedUnsafeSysctls"), spec.AllowedUnsafeSysctls)...) + allErrs = append(allErrs, validatePodSecurityPolicySysctls(fldPath.Child("forbiddenSysctls"), spec.ForbiddenSysctls)...) + allErrs = append(allErrs, validatePodSecurityPolicySysctlListsDoNotOverlap(fldPath.Child("allowedUnsafeSysctls"), fldPath.Child("forbiddenSysctls"), spec.AllowedUnsafeSysctls, spec.ForbiddenSysctls)...) + + return allErrs +} + +func ValidatePodSecurityPolicySpecificAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if p := annotations[apparmor.DefaultProfileAnnotationKey]; p != "" { + if err := apparmor.ValidateProfileFormat(p); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.DefaultProfileAnnotationKey), p, err.Error())) + } + } + if allowed := annotations[apparmor.AllowedProfilesAnnotationKey]; allowed != "" { + for _, p := range strings.Split(allowed, ",") { + if err := apparmor.ValidateProfileFormat(p); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.AllowedProfilesAnnotationKey), allowed, err.Error())) + } + } + } + + if p := annotations[seccomp.DefaultProfileAnnotationKey]; p != "" { + allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.DefaultProfileAnnotationKey))...) + } + if allowed := annotations[seccomp.AllowedProfilesAnnotationKey]; allowed != "" { + for _, p := range strings.Split(allowed, ",") { + if p == seccomp.AllowAny { + continue + } + allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.AllowedProfilesAnnotationKey))...) + } + } + return allErrs +} + +// validatePSPAllowedHostPaths makes sure all allowed host paths follow: +// 1. path prefix is required +// 2. path prefix does not have any element which is ".." +func validatePSPAllowedHostPaths(fldPath *field.Path, allowedHostPaths []policy.AllowedHostPath) field.ErrorList { + allErrs := field.ErrorList{} + + for i, target := range allowedHostPaths { + if target.PathPrefix == "" { + allErrs = append(allErrs, field.Required(fldPath.Index(i), "is required")) + break + } + parts := strings.Split(filepath.ToSlash(target.PathPrefix), "/") + for _, item := range parts { + if item == ".." { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i), target.PathPrefix, "must not contain '..'")) + break // even for `../../..`, one error is sufficient to make the point + } + } + } + + return allErrs +} + +func validatePSPAllowedFlexVolumes(fldPath *field.Path, flexVolumes []policy.AllowedFlexVolume) field.ErrorList { + allErrs := field.ErrorList{} + if len(flexVolumes) > 0 { + for idx, fv := range flexVolumes { + if len(fv.Driver) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("allowedFlexVolumes").Index(idx).Child("driver"), + "must specify a driver")) + } + } + } + return allErrs +} + +// validatePSPSELinux validates the SELinux fields of PodSecurityPolicy. +func validatePSPSELinux(fldPath *field.Path, seLinux *policy.SELinuxStrategyOptions) field.ErrorList { + allErrs := field.ErrorList{} + + // ensure the selinux strategy has a valid rule + supportedSELinuxRules := sets.NewString( + string(policy.SELinuxStrategyMustRunAs), + string(policy.SELinuxStrategyRunAsAny), + ) + if !supportedSELinuxRules.Has(string(seLinux.Rule)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), seLinux.Rule, supportedSELinuxRules.List())) + } + + return allErrs +} + +// validatePSPRunAsUser validates the RunAsUser fields of PodSecurityPolicy. +func validatePSPRunAsUser(fldPath *field.Path, runAsUser *policy.RunAsUserStrategyOptions) field.ErrorList { + allErrs := field.ErrorList{} + + // ensure the user strategy has a valid rule + supportedRunAsUserRules := sets.NewString( + string(policy.RunAsUserStrategyMustRunAs), + string(policy.RunAsUserStrategyMustRunAsNonRoot), + string(policy.RunAsUserStrategyRunAsAny), + ) + if !supportedRunAsUserRules.Has(string(runAsUser.Rule)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), runAsUser.Rule, supportedRunAsUserRules.List())) + } + + // validate range settings + for idx, rng := range runAsUser.Ranges { + allErrs = append(allErrs, validateUserIDRange(fldPath.Child("ranges").Index(idx), rng)...) + } + + return allErrs +} + +// validatePSPFSGroup validates the FSGroupStrategyOptions fields of the PodSecurityPolicy. +func validatePSPFSGroup(fldPath *field.Path, groupOptions *policy.FSGroupStrategyOptions) field.ErrorList { + allErrs := field.ErrorList{} + + supportedRules := sets.NewString( + string(policy.FSGroupStrategyMustRunAs), + string(policy.FSGroupStrategyRunAsAny), + ) + if !supportedRules.Has(string(groupOptions.Rule)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), groupOptions.Rule, supportedRules.List())) + } + + for idx, rng := range groupOptions.Ranges { + allErrs = append(allErrs, validateGroupIDRange(fldPath.Child("ranges").Index(idx), rng)...) + } + return allErrs +} + +// validatePSPSupplementalGroup validates the SupplementalGroupsStrategyOptions fields of the PodSecurityPolicy. +func validatePSPSupplementalGroup(fldPath *field.Path, groupOptions *policy.SupplementalGroupsStrategyOptions) field.ErrorList { + allErrs := field.ErrorList{} + + supportedRules := sets.NewString( + string(policy.SupplementalGroupsStrategyRunAsAny), + string(policy.SupplementalGroupsStrategyMustRunAs), + ) + if !supportedRules.Has(string(groupOptions.Rule)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("rule"), groupOptions.Rule, supportedRules.List())) + } + + for idx, rng := range groupOptions.Ranges { + allErrs = append(allErrs, validateGroupIDRange(fldPath.Child("ranges").Index(idx), rng)...) + } + return allErrs +} + +// validatePodSecurityPolicyVolumes validates the volume fields of PodSecurityPolicy. +func validatePodSecurityPolicyVolumes(fldPath *field.Path, volumes []policy.FSType) field.ErrorList { + allErrs := field.ErrorList{} + allowed := psputil.GetAllFSTypesAsSet() + // add in the * value since that is a pseudo type that is not included by default + allowed.Insert(string(policy.All)) + for _, v := range volumes { + if !allowed.Has(string(v)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("volumes"), v, allowed.List())) + } + } + return allErrs +} + +// validatePSPDefaultAllowPrivilegeEscalation validates the DefaultAllowPrivilegeEscalation field against the AllowPrivilegeEscalation field of a PodSecurityPolicy. +func validatePSPDefaultAllowPrivilegeEscalation(fldPath *field.Path, defaultAllowPrivilegeEscalation *bool, allowPrivilegeEscalation bool) field.ErrorList { + allErrs := field.ErrorList{} + if defaultAllowPrivilegeEscalation != nil && *defaultAllowPrivilegeEscalation && !allowPrivilegeEscalation { + allErrs = append(allErrs, field.Invalid(fldPath, defaultAllowPrivilegeEscalation, "Cannot set DefaultAllowPrivilegeEscalation to true without also setting AllowPrivilegeEscalation to true")) + } + + return allErrs +} + +const sysctlPatternSegmentFmt string = "([a-z0-9][-_a-z0-9]*)?[a-z0-9*]" +const SysctlPatternFmt string = "(" + apivalidation.SysctlSegmentFmt + "\\.)*" + sysctlPatternSegmentFmt + +var sysctlPatternRegexp = regexp.MustCompile("^" + SysctlPatternFmt + "$") + +func IsValidSysctlPattern(name string) bool { + if len(name) > apivalidation.SysctlMaxLength { + return false + } + return sysctlPatternRegexp.MatchString(name) +} + +func validatePodSecurityPolicySysctlListsDoNotOverlap(allowedSysctlsFldPath, forbiddenSysctlsFldPath *field.Path, allowedUnsafeSysctls, forbiddenSysctls []string) field.ErrorList { + allErrs := field.ErrorList{} + for i, allowedSysctl := range allowedUnsafeSysctls { + isAllowedSysctlPattern := false + allowedSysctlPrefix := "" + if strings.HasSuffix(allowedSysctl, "*") { + isAllowedSysctlPattern = true + allowedSysctlPrefix = strings.TrimSuffix(allowedSysctl, "*") + } + for j, forbiddenSysctl := range forbiddenSysctls { + isForbiddenSysctlPattern := false + forbiddenSysctlPrefix := "" + if strings.HasSuffix(forbiddenSysctl, "*") { + isForbiddenSysctlPattern = true + forbiddenSysctlPrefix = strings.TrimSuffix(forbiddenSysctl, "*") + } + switch { + case isAllowedSysctlPattern && isForbiddenSysctlPattern: + if strings.HasPrefix(allowedSysctlPrefix, forbiddenSysctlPrefix) { + allErrs = append(allErrs, field.Invalid(allowedSysctlsFldPath.Index(i), allowedUnsafeSysctls[i], fmt.Sprintf("sysctl overlaps with %v", forbiddenSysctl))) + } else if strings.HasPrefix(forbiddenSysctlPrefix, allowedSysctlPrefix) { + allErrs = append(allErrs, field.Invalid(forbiddenSysctlsFldPath.Index(j), forbiddenSysctls[j], fmt.Sprintf("sysctl overlaps with %v", allowedSysctl))) + } + case isAllowedSysctlPattern: + if strings.HasPrefix(forbiddenSysctl, allowedSysctlPrefix) { + allErrs = append(allErrs, field.Invalid(forbiddenSysctlsFldPath.Index(j), forbiddenSysctls[j], fmt.Sprintf("sysctl overlaps with %v", allowedSysctl))) + } + case isForbiddenSysctlPattern: + if strings.HasPrefix(allowedSysctl, forbiddenSysctlPrefix) { + allErrs = append(allErrs, field.Invalid(allowedSysctlsFldPath.Index(i), allowedUnsafeSysctls[i], fmt.Sprintf("sysctl overlaps with %v", forbiddenSysctl))) + } + default: + if allowedSysctl == forbiddenSysctl { + allErrs = append(allErrs, field.Invalid(allowedSysctlsFldPath.Index(i), allowedUnsafeSysctls[i], fmt.Sprintf("sysctl overlaps with %v", forbiddenSysctl))) + } + } + } + } + return allErrs +} + +// validatePodSecurityPolicySysctls validates the sysctls fields of PodSecurityPolicy. +func validatePodSecurityPolicySysctls(fldPath *field.Path, sysctls []string) field.ErrorList { + allErrs := field.ErrorList{} + + if len(sysctls) == 0 { + return allErrs + } + + if !utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) { + return append(allErrs, field.Forbidden(fldPath, "Sysctls are disabled by Sysctls feature-gate")) + } + + coversAll := false + for i, s := range sysctls { + if len(s) == 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i), sysctls[i], fmt.Sprintf("empty sysctl not allowed"))) + } else if !IsValidSysctlPattern(string(s)) { + allErrs = append( + allErrs, + field.Invalid(fldPath.Index(i), sysctls[i], fmt.Sprintf("must have at most %d characters and match regex %s", + apivalidation.SysctlMaxLength, + SysctlPatternFmt, + )), + ) + } else if s[0] == '*' { + coversAll = true + } + } + + if coversAll && len(sysctls) > 1 { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("items"), fmt.Sprintf("if '*' is present, must not specify other sysctls"))) + } + + return allErrs +} + +func validateUserIDRange(fldPath *field.Path, rng policy.IDRange) field.ErrorList { + return validateIDRanges(fldPath, rng.Min, rng.Max) +} + +func validateGroupIDRange(fldPath *field.Path, rng policy.IDRange) field.ErrorList { + return validateIDRanges(fldPath, rng.Min, rng.Max) +} + +// validateIDRanges ensures the range is valid. +func validateIDRanges(fldPath *field.Path, min, max int64) field.ErrorList { + allErrs := field.ErrorList{} + + // if 0 <= Min <= Max then we do not need to validate max. It is always greater than or + // equal to 0 and Min. + if min < 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), min, "min cannot be negative")) + } + if max < 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("max"), max, "max cannot be negative")) + } + if min > max { + allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), min, "min cannot be greater than max")) + } + + return allErrs +} + +// validatePSPCapsAgainstDrops ensures an allowed cap is not listed in the required drops. +func validatePSPCapsAgainstDrops(requiredDrops []core.Capability, capsToCheck []core.Capability, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if requiredDrops == nil { + return allErrs + } + for _, cap := range capsToCheck { + if hasCap(cap, requiredDrops) { + allErrs = append(allErrs, field.Invalid(fldPath, cap, + fmt.Sprintf("capability is listed in %s and requiredDropCapabilities", fldPath.String()))) + } + } + return allErrs +} + +// ValidatePodSecurityPolicyUpdate validates a PSP for updates. +func ValidatePodSecurityPolicyUpdate(old *policy.PodSecurityPolicy, new *policy.PodSecurityPolicy) field.ErrorList { + allErrs := field.ErrorList{} + allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&new.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))...) + allErrs = append(allErrs, ValidatePodSecurityPolicySpecificAnnotations(new.Annotations, field.NewPath("metadata").Child("annotations"))...) + allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&new.Spec, field.NewPath("spec"))...) + return allErrs +} + +// hasCap checks for needle in haystack. +func hasCap(needle core.Capability, haystack []core.Capability) bool { + for _, c := range haystack { + if needle == c { + return true + } + } + return false +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/validation_test.go index c2ba5b61f..552fd8cec 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/validation/validation_test.go @@ -17,11 +17,17 @@ limitations under the License. package validation import ( + "fmt" "testing" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/validation/field" + api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/policy" + "k8s.io/kubernetes/pkg/security/apparmor" + "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" + psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) func TestValidatePodDisruptionBudgetSpec(t *testing.T) { @@ -221,3 +227,559 @@ func TestValidatePodDisruptionBudgetUpdate(t *testing.T) { } } } + +func TestValidatePodSecurityPolicy(t *testing.T) { + validPSP := func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Annotations: map[string]string{}, + }, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, + }, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, + }, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, + }, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, + }, + AllowedHostPaths: []policy.AllowedHostPath{ + {PathPrefix: "/foo/bar"}, + {PathPrefix: "/baz/"}, + }, + }, + } + } + + noUserOptions := validPSP() + noUserOptions.Spec.RunAsUser.Rule = "" + + noSELinuxOptions := validPSP() + noSELinuxOptions.Spec.SELinux.Rule = "" + + invalidUserStratType := validPSP() + invalidUserStratType.Spec.RunAsUser.Rule = "invalid" + + invalidSELinuxStratType := validPSP() + invalidSELinuxStratType.Spec.SELinux.Rule = "invalid" + + invalidUIDPSP := validPSP() + invalidUIDPSP.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAs + invalidUIDPSP.Spec.RunAsUser.Ranges = []policy.IDRange{{Min: -1, Max: 1}} + + missingObjectMetaName := validPSP() + missingObjectMetaName.ObjectMeta.Name = "" + + noFSGroupOptions := validPSP() + noFSGroupOptions.Spec.FSGroup.Rule = "" + + invalidFSGroupStratType := validPSP() + invalidFSGroupStratType.Spec.FSGroup.Rule = "invalid" + + noSupplementalGroupsOptions := validPSP() + noSupplementalGroupsOptions.Spec.SupplementalGroups.Rule = "" + + invalidSupGroupStratType := validPSP() + invalidSupGroupStratType.Spec.SupplementalGroups.Rule = "invalid" + + invalidRangeMinGreaterThanMax := validPSP() + invalidRangeMinGreaterThanMax.Spec.FSGroup.Ranges = []policy.IDRange{ + {Min: 2, Max: 1}, + } + + invalidRangeNegativeMin := validPSP() + invalidRangeNegativeMin.Spec.FSGroup.Ranges = []policy.IDRange{ + {Min: -1, Max: 10}, + } + + invalidRangeNegativeMax := validPSP() + invalidRangeNegativeMax.Spec.FSGroup.Ranges = []policy.IDRange{ + {Min: 1, Max: -10}, + } + + wildcardAllowedCapAndRequiredDrop := validPSP() + wildcardAllowedCapAndRequiredDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} + wildcardAllowedCapAndRequiredDrop.Spec.AllowedCapabilities = []api.Capability{policy.AllowAllCapabilities} + + requiredCapAddAndDrop := validPSP() + requiredCapAddAndDrop.Spec.DefaultAddCapabilities = []api.Capability{"foo"} + requiredCapAddAndDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} + + allowedCapListedInRequiredDrop := validPSP() + allowedCapListedInRequiredDrop.Spec.RequiredDropCapabilities = []api.Capability{"foo"} + allowedCapListedInRequiredDrop.Spec.AllowedCapabilities = []api.Capability{"foo"} + + invalidAppArmorDefault := validPSP() + invalidAppArmorDefault.Annotations = map[string]string{ + apparmor.DefaultProfileAnnotationKey: "not-good", + } + invalidAppArmorAllowed := validPSP() + invalidAppArmorAllowed.Annotations = map[string]string{ + apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + ",not-good", + } + + invalidAllowedUnsafeSysctlPattern := validPSP() + invalidAllowedUnsafeSysctlPattern.Spec.AllowedUnsafeSysctls = []string{"a.*.b"} + + invalidForbiddenSysctlPattern := validPSP() + invalidForbiddenSysctlPattern.Spec.ForbiddenSysctls = []string{"a.*.b"} + + invalidOverlappingSysctls := validPSP() + invalidOverlappingSysctls.Spec.ForbiddenSysctls = []string{"kernel.*", "net.ipv4.ip_local_port_range"} + invalidOverlappingSysctls.Spec.AllowedUnsafeSysctls = []string{"kernel.shmmax", "net.ipv4.ip_local_port_range"} + + invalidDuplicatedSysctls := validPSP() + invalidDuplicatedSysctls.Spec.ForbiddenSysctls = []string{"net.ipv4.ip_local_port_range"} + invalidDuplicatedSysctls.Spec.AllowedUnsafeSysctls = []string{"net.ipv4.ip_local_port_range"} + + invalidSeccompDefault := validPSP() + invalidSeccompDefault.Annotations = map[string]string{ + seccomp.DefaultProfileAnnotationKey: "not-good", + } + invalidSeccompAllowAnyDefault := validPSP() + invalidSeccompAllowAnyDefault.Annotations = map[string]string{ + seccomp.DefaultProfileAnnotationKey: "*", + } + invalidSeccompAllowed := validPSP() + invalidSeccompAllowed.Annotations = map[string]string{ + seccomp.AllowedProfilesAnnotationKey: api.SeccompProfileRuntimeDefault + ",not-good", + } + + invalidAllowedHostPathMissingPath := validPSP() + invalidAllowedHostPathMissingPath.Spec.AllowedHostPaths = []policy.AllowedHostPath{ + {PathPrefix: ""}, + } + + invalidAllowedHostPathBacksteps := validPSP() + invalidAllowedHostPathBacksteps.Spec.AllowedHostPaths = []policy.AllowedHostPath{ + {PathPrefix: "/dont/allow/backsteps/.."}, + } + + invalidDefaultAllowPrivilegeEscalation := validPSP() + pe := true + invalidDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe + + emptyFlexDriver := validPSP() + emptyFlexDriver.Spec.Volumes = []policy.FSType{policy.FlexVolume} + emptyFlexDriver.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{{}} + + nonEmptyFlexVolumes := validPSP() + nonEmptyFlexVolumes.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{{Driver: "example/driver"}} + + type testCase struct { + psp *policy.PodSecurityPolicy + errorType field.ErrorType + errorDetail string + } + errorCases := map[string]testCase{ + "no user options": { + psp: noUserOptions, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "MustRunAsNonRoot", "RunAsAny"`, + }, + "no selinux options": { + psp: noSELinuxOptions, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "no fsgroup options": { + psp: noFSGroupOptions, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "no sup group options": { + psp: noSupplementalGroupsOptions, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "invalid user strategy type": { + psp: invalidUserStratType, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "MustRunAsNonRoot", "RunAsAny"`, + }, + "invalid selinux strategy type": { + psp: invalidSELinuxStratType, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "invalid sup group strategy type": { + psp: invalidSupGroupStratType, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "invalid fs group strategy type": { + psp: invalidFSGroupStratType, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "MustRunAs", "RunAsAny"`, + }, + "invalid uid": { + psp: invalidUIDPSP, + errorType: field.ErrorTypeInvalid, + errorDetail: "min cannot be negative", + }, + "missing object meta name": { + psp: missingObjectMetaName, + errorType: field.ErrorTypeRequired, + errorDetail: "name or generateName is required", + }, + "invalid range min greater than max": { + psp: invalidRangeMinGreaterThanMax, + errorType: field.ErrorTypeInvalid, + errorDetail: "min cannot be greater than max", + }, + "invalid range negative min": { + psp: invalidRangeNegativeMin, + errorType: field.ErrorTypeInvalid, + errorDetail: "min cannot be negative", + }, + "invalid range negative max": { + psp: invalidRangeNegativeMax, + errorType: field.ErrorTypeInvalid, + errorDetail: "max cannot be negative", + }, + "non-empty required drops and all caps are allowed by a wildcard": { + psp: wildcardAllowedCapAndRequiredDrop, + errorType: field.ErrorTypeInvalid, + errorDetail: "must be empty when all capabilities are allowed by a wildcard", + }, + "invalid required caps": { + psp: requiredCapAddAndDrop, + errorType: field.ErrorTypeInvalid, + errorDetail: "capability is listed in defaultAddCapabilities and requiredDropCapabilities", + }, + "allowed cap listed in required drops": { + psp: allowedCapListedInRequiredDrop, + errorType: field.ErrorTypeInvalid, + errorDetail: "capability is listed in allowedCapabilities and requiredDropCapabilities", + }, + "invalid AppArmor default profile": { + psp: invalidAppArmorDefault, + errorType: field.ErrorTypeInvalid, + errorDetail: "invalid AppArmor profile name: \"not-good\"", + }, + "invalid AppArmor allowed profile": { + psp: invalidAppArmorAllowed, + errorType: field.ErrorTypeInvalid, + errorDetail: "invalid AppArmor profile name: \"not-good\"", + }, + "invalid allowed unsafe sysctl pattern": { + psp: invalidAllowedUnsafeSysctlPattern, + errorType: field.ErrorTypeInvalid, + errorDetail: fmt.Sprintf("must have at most 253 characters and match regex %s", SysctlPatternFmt), + }, + "invalid forbidden sysctl pattern": { + psp: invalidForbiddenSysctlPattern, + errorType: field.ErrorTypeInvalid, + errorDetail: fmt.Sprintf("must have at most 253 characters and match regex %s", SysctlPatternFmt), + }, + "invalid overlapping sysctl pattern": { + psp: invalidOverlappingSysctls, + errorType: field.ErrorTypeInvalid, + errorDetail: fmt.Sprintf("sysctl overlaps with %s", invalidOverlappingSysctls.Spec.ForbiddenSysctls[0]), + }, + "invalid duplicated sysctls": { + psp: invalidDuplicatedSysctls, + errorType: field.ErrorTypeInvalid, + errorDetail: fmt.Sprintf("sysctl overlaps with %s", invalidDuplicatedSysctls.Spec.AllowedUnsafeSysctls[0]), + }, + "invalid seccomp default profile": { + psp: invalidSeccompDefault, + errorType: field.ErrorTypeInvalid, + errorDetail: "must be a valid seccomp profile", + }, + "invalid seccomp allow any default profile": { + psp: invalidSeccompAllowAnyDefault, + errorType: field.ErrorTypeInvalid, + errorDetail: "must be a valid seccomp profile", + }, + "invalid seccomp allowed profile": { + psp: invalidSeccompAllowed, + errorType: field.ErrorTypeInvalid, + errorDetail: "must be a valid seccomp profile", + }, + "invalid defaultAllowPrivilegeEscalation": { + psp: invalidDefaultAllowPrivilegeEscalation, + errorType: field.ErrorTypeInvalid, + errorDetail: "Cannot set DefaultAllowPrivilegeEscalation to true without also setting AllowPrivilegeEscalation to true", + }, + "invalid allowed host path empty path": { + psp: invalidAllowedHostPathMissingPath, + errorType: field.ErrorTypeRequired, + errorDetail: "is required", + }, + "invalid allowed host path with backsteps": { + psp: invalidAllowedHostPathBacksteps, + errorType: field.ErrorTypeInvalid, + errorDetail: "must not contain '..'", + }, + "empty flex volume driver": { + psp: emptyFlexDriver, + errorType: field.ErrorTypeRequired, + errorDetail: "must specify a driver", + }, + } + + for k, v := range errorCases { + errs := ValidatePodSecurityPolicy(v.psp) + if len(errs) == 0 { + t.Errorf("%s expected errors but got none", k) + continue + } + if errs[0].Type != v.errorType { + t.Errorf("[%s] received an unexpected error type. Expected: '%s' got: '%s'", k, v.errorType, errs[0].Type) + } + if errs[0].Detail != v.errorDetail { + t.Errorf("[%s] received an unexpected error detail. Expected '%s' got: '%s'", k, v.errorDetail, errs[0].Detail) + } + } + + // Update error is different for 'missing object meta name'. + errorCases["missing object meta name"] = testCase{ + psp: errorCases["missing object meta name"].psp, + errorType: field.ErrorTypeInvalid, + errorDetail: "field is immutable", + } + + // Should not be able to update to an invalid policy. + for k, v := range errorCases { + v.psp.ResourceVersion = "444" // Required for updates. + errs := ValidatePodSecurityPolicyUpdate(validPSP(), v.psp) + if len(errs) == 0 { + t.Errorf("[%s] expected update errors but got none", k) + continue + } + if errs[0].Type != v.errorType { + t.Errorf("[%s] received an unexpected error type. Expected: '%s' got: '%s'", k, v.errorType, errs[0].Type) + } + if errs[0].Detail != v.errorDetail { + t.Errorf("[%s] received an unexpected error detail. Expected '%s' got: '%s'", k, v.errorDetail, errs[0].Detail) + } + } + + mustRunAs := validPSP() + mustRunAs.Spec.FSGroup.Rule = policy.FSGroupStrategyMustRunAs + mustRunAs.Spec.SupplementalGroups.Rule = policy.SupplementalGroupsStrategyMustRunAs + mustRunAs.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAs + mustRunAs.Spec.RunAsUser.Ranges = []policy.IDRange{ + {Min: 1, Max: 1}, + } + mustRunAs.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs + + runAsNonRoot := validPSP() + runAsNonRoot.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAsNonRoot + + caseInsensitiveAddDrop := validPSP() + caseInsensitiveAddDrop.Spec.DefaultAddCapabilities = []api.Capability{"foo"} + caseInsensitiveAddDrop.Spec.RequiredDropCapabilities = []api.Capability{"FOO"} + + caseInsensitiveAllowedDrop := validPSP() + caseInsensitiveAllowedDrop.Spec.RequiredDropCapabilities = []api.Capability{"FOO"} + caseInsensitiveAllowedDrop.Spec.AllowedCapabilities = []api.Capability{"foo"} + + validAppArmor := validPSP() + validAppArmor.Annotations = map[string]string{ + apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault, + apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + "," + apparmor.ProfileNamePrefix + "foo", + } + + withForbiddenSysctl := validPSP() + withForbiddenSysctl.Spec.ForbiddenSysctls = []string{"net.*"} + + withAllowedUnsafeSysctl := validPSP() + withAllowedUnsafeSysctl.Spec.AllowedUnsafeSysctls = []string{"net.ipv4.tcp_max_syn_backlog"} + + validSeccomp := validPSP() + validSeccomp.Annotations = map[string]string{ + seccomp.DefaultProfileAnnotationKey: api.SeccompProfileRuntimeDefault, + seccomp.AllowedProfilesAnnotationKey: api.SeccompProfileRuntimeDefault + ",unconfined,localhost/foo,*", + } + + validDefaultAllowPrivilegeEscalation := validPSP() + pe = true + validDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe + validDefaultAllowPrivilegeEscalation.Spec.AllowPrivilegeEscalation = true + + flexvolumeWhenFlexVolumesAllowed := validPSP() + flexvolumeWhenFlexVolumesAllowed.Spec.Volumes = []policy.FSType{policy.FlexVolume} + flexvolumeWhenFlexVolumesAllowed.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{ + {Driver: "example/driver1"}, + } + + flexvolumeWhenAllVolumesAllowed := validPSP() + flexvolumeWhenAllVolumesAllowed.Spec.Volumes = []policy.FSType{policy.All} + flexvolumeWhenAllVolumesAllowed.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{ + {Driver: "example/driver2"}, + } + successCases := map[string]struct { + psp *policy.PodSecurityPolicy + }{ + "must run as": { + psp: mustRunAs, + }, + "run as any": { + psp: validPSP(), + }, + "run as non-root (user only)": { + psp: runAsNonRoot, + }, + "comparison for add -> drop is case sensitive": { + psp: caseInsensitiveAddDrop, + }, + "comparison for allowed -> drop is case sensitive": { + psp: caseInsensitiveAllowedDrop, + }, + "valid AppArmor annotations": { + psp: validAppArmor, + }, + "with network sysctls forbidden": { + psp: withForbiddenSysctl, + }, + "with unsafe net.ipv4.tcp_max_syn_backlog sysctl allowed": { + psp: withAllowedUnsafeSysctl, + }, + "valid seccomp annotations": { + psp: validSeccomp, + }, + "valid defaultAllowPrivilegeEscalation as true": { + psp: validDefaultAllowPrivilegeEscalation, + }, + "allow white-listed flexVolume when flex volumes are allowed": { + psp: flexvolumeWhenFlexVolumesAllowed, + }, + "allow white-listed flexVolume when all volumes are allowed": { + psp: flexvolumeWhenAllVolumesAllowed, + }, + } + + for k, v := range successCases { + if errs := ValidatePodSecurityPolicy(v.psp); len(errs) != 0 { + t.Errorf("Expected success for %s, got %v", k, errs) + } + + // Should be able to update to a valid PSP. + v.psp.ResourceVersion = "444" // Required for updates. + if errs := ValidatePodSecurityPolicyUpdate(validPSP(), v.psp); len(errs) != 0 { + t.Errorf("Expected success for %s update, got %v", k, errs) + } + } +} + +func TestValidatePSPVolumes(t *testing.T) { + validPSP := func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, + }, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, + }, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, + }, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, + }, + }, + } + } + + volumes := psputil.GetAllFSTypesAsSet() + // add in the * value since that is a pseudo type that is not included by default + volumes.Insert(string(policy.All)) + + for _, strVolume := range volumes.List() { + psp := validPSP() + psp.Spec.Volumes = []policy.FSType{policy.FSType(strVolume)} + errs := ValidatePodSecurityPolicy(psp) + if len(errs) != 0 { + t.Errorf("%s validation expected no errors but received %v", strVolume, errs) + } + } +} + +func TestIsValidSysctlPattern(t *testing.T) { + valid := []string{ + "a.b.c.d", + "a", + "a_b", + "a-b", + "abc", + "abc.def", + "*", + "a.*", + "*", + "abc*", + "a.abc*", + "a.b.*", + } + invalid := []string{ + "", + "ä", + "a_", + "_", + "_a", + "_a._b", + "__", + "-", + ".", + "a.", + ".a", + "a.b.", + "a*.b", + "a*b", + "*a", + "Abc", + func(n int) string { + x := make([]byte, n) + for i := range x { + x[i] = byte('a') + } + return string(x) + }(256), + } + for _, s := range valid { + if !IsValidSysctlPattern(s) { + t.Errorf("%q expected to be a valid sysctl pattern", s) + } + } + for _, s := range invalid { + if IsValidSysctlPattern(s) { + t.Errorf("%q expected to be an invalid sysctl pattern", s) + } + } +} + +func Test_validatePSPRunAsUser(t *testing.T) { + var testCases = []struct { + name string + runAsUserStrategy policy.RunAsUserStrategyOptions + fail bool + }{ + {"Invalid RunAsUserStrategy", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategy("someInvalidStrategy")}, true}, + {"RunAsUserStrategyMustRunAs", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategyMustRunAs}, false}, + {"RunAsUserStrategyMustRunAsNonRoot", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategyMustRunAsNonRoot}, false}, + {"RunAsUserStrategyMustRunAsNonRoot With Valid Range", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategyMustRunAs, Ranges: []policy.IDRange{{Min: 2, Max: 3}, {Min: 4, Max: 5}}}, false}, + {"RunAsUserStrategyMustRunAsNonRoot With Invalid Range", policy.RunAsUserStrategyOptions{Rule: policy.RunAsUserStrategyMustRunAs, Ranges: []policy.IDRange{{Min: 2, Max: 3}, {Min: 5, Max: 4}}}, true}, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + errList := validatePSPRunAsUser(field.NewPath("status"), &testCase.runAsUserStrategy) + actualErrors := len(errList) + expectedErrors := 1 + if !testCase.fail { + expectedErrors = 0 + } + if actualErrors != expectedErrors { + t.Errorf("In testCase %v, expected %v errors, got %v errors", testCase.name, expectedErrors, actualErrors) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/policy/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/policy/zz_generated.deepcopy.go index c039c4fb5..3bb51ae48 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/policy/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/policy/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,8 +24,41 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" intstr "k8s.io/apimachinery/pkg/util/intstr" + core "k8s.io/kubernetes/pkg/apis/core" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllowedFlexVolume) DeepCopyInto(out *AllowedFlexVolume) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllowedFlexVolume. +func (in *AllowedFlexVolume) DeepCopy() *AllowedFlexVolume { + if in == nil { + return nil + } + out := new(AllowedFlexVolume) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllowedHostPath) DeepCopyInto(out *AllowedHostPath) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllowedHostPath. +func (in *AllowedHostPath) DeepCopy() *AllowedHostPath { + if in == nil { + return nil + } + out := new(AllowedHostPath) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Eviction) DeepCopyInto(out *Eviction) { *out = *in @@ -61,6 +94,59 @@ func (in *Eviction) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FSGroupStrategyOptions) DeepCopyInto(out *FSGroupStrategyOptions) { + *out = *in + if in.Ranges != nil { + in, out := &in.Ranges, &out.Ranges + *out = make([]IDRange, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FSGroupStrategyOptions. +func (in *FSGroupStrategyOptions) DeepCopy() *FSGroupStrategyOptions { + if in == nil { + return nil + } + out := new(FSGroupStrategyOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HostPortRange) DeepCopyInto(out *HostPortRange) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPortRange. +func (in *HostPortRange) DeepCopy() *HostPortRange { + if in == nil { + return nil + } + out := new(HostPortRange) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IDRange) DeepCopyInto(out *IDRange) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IDRange. +func (in *IDRange) DeepCopy() *IDRange { + if in == nil { + return nil + } + out := new(IDRange) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodDisruptionBudget) DeepCopyInto(out *PodDisruptionBudget) { *out = *in @@ -187,3 +273,204 @@ func (in *PodDisruptionBudgetStatus) DeepCopy() *PodDisruptionBudgetStatus { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodSecurityPolicy) DeepCopyInto(out *PodSecurityPolicy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSecurityPolicy. +func (in *PodSecurityPolicy) DeepCopy() *PodSecurityPolicy { + if in == nil { + return nil + } + out := new(PodSecurityPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PodSecurityPolicy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodSecurityPolicyList) DeepCopyInto(out *PodSecurityPolicyList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]PodSecurityPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSecurityPolicyList. +func (in *PodSecurityPolicyList) DeepCopy() *PodSecurityPolicyList { + if in == nil { + return nil + } + out := new(PodSecurityPolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PodSecurityPolicyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodSecurityPolicySpec) DeepCopyInto(out *PodSecurityPolicySpec) { + *out = *in + if in.DefaultAddCapabilities != nil { + in, out := &in.DefaultAddCapabilities, &out.DefaultAddCapabilities + *out = make([]core.Capability, len(*in)) + copy(*out, *in) + } + if in.RequiredDropCapabilities != nil { + in, out := &in.RequiredDropCapabilities, &out.RequiredDropCapabilities + *out = make([]core.Capability, len(*in)) + copy(*out, *in) + } + if in.AllowedCapabilities != nil { + in, out := &in.AllowedCapabilities, &out.AllowedCapabilities + *out = make([]core.Capability, len(*in)) + copy(*out, *in) + } + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]FSType, len(*in)) + copy(*out, *in) + } + if in.HostPorts != nil { + in, out := &in.HostPorts, &out.HostPorts + *out = make([]HostPortRange, len(*in)) + copy(*out, *in) + } + in.SELinux.DeepCopyInto(&out.SELinux) + in.RunAsUser.DeepCopyInto(&out.RunAsUser) + in.SupplementalGroups.DeepCopyInto(&out.SupplementalGroups) + in.FSGroup.DeepCopyInto(&out.FSGroup) + if in.DefaultAllowPrivilegeEscalation != nil { + in, out := &in.DefaultAllowPrivilegeEscalation, &out.DefaultAllowPrivilegeEscalation + if *in == nil { + *out = nil + } else { + *out = new(bool) + **out = **in + } + } + if in.AllowedHostPaths != nil { + in, out := &in.AllowedHostPaths, &out.AllowedHostPaths + *out = make([]AllowedHostPath, len(*in)) + copy(*out, *in) + } + if in.AllowedFlexVolumes != nil { + in, out := &in.AllowedFlexVolumes, &out.AllowedFlexVolumes + *out = make([]AllowedFlexVolume, len(*in)) + copy(*out, *in) + } + if in.AllowedUnsafeSysctls != nil { + in, out := &in.AllowedUnsafeSysctls, &out.AllowedUnsafeSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ForbiddenSysctls != nil { + in, out := &in.ForbiddenSysctls, &out.ForbiddenSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSecurityPolicySpec. +func (in *PodSecurityPolicySpec) DeepCopy() *PodSecurityPolicySpec { + if in == nil { + return nil + } + out := new(PodSecurityPolicySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunAsUserStrategyOptions) DeepCopyInto(out *RunAsUserStrategyOptions) { + *out = *in + if in.Ranges != nil { + in, out := &in.Ranges, &out.Ranges + *out = make([]IDRange, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunAsUserStrategyOptions. +func (in *RunAsUserStrategyOptions) DeepCopy() *RunAsUserStrategyOptions { + if in == nil { + return nil + } + out := new(RunAsUserStrategyOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SELinuxStrategyOptions) DeepCopyInto(out *SELinuxStrategyOptions) { + *out = *in + if in.SELinuxOptions != nil { + in, out := &in.SELinuxOptions, &out.SELinuxOptions + if *in == nil { + *out = nil + } else { + *out = new(core.SELinuxOptions) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SELinuxStrategyOptions. +func (in *SELinuxStrategyOptions) DeepCopy() *SELinuxStrategyOptions { + if in == nil { + return nil + } + out := new(SELinuxStrategyOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SupplementalGroupsStrategyOptions) DeepCopyInto(out *SupplementalGroupsStrategyOptions) { + *out = *in + if in.Ranges != nil { + in, out := &in.Ranges, &out.Ranges + *out = make([]IDRange, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SupplementalGroupsStrategyOptions. +func (in *SupplementalGroupsStrategyOptions) DeepCopy() *SupplementalGroupsStrategyOptions { + if in == nil { + return nil + } + out := new(SupplementalGroupsStrategyOptions) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/helpers.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/helpers.go index 373711500..b7b4b78c8 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/helpers.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/helpers.go @@ -21,40 +21,9 @@ import ( "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" ) -func RoleRefGroupKind(roleRef RoleRef) schema.GroupKind { - return schema.GroupKind{Group: roleRef.APIGroup, Kind: roleRef.Kind} -} - -func VerbMatches(rule *PolicyRule, requestedVerb string) bool { - for _, ruleVerb := range rule.Verbs { - if ruleVerb == VerbAll { - return true - } - if ruleVerb == requestedVerb { - return true - } - } - - return false -} - -func APIGroupMatches(rule *PolicyRule, requestedGroup string) bool { - for _, ruleGroup := range rule.APIGroups { - if ruleGroup == APIGroupAll { - return true - } - if ruleGroup == requestedGroup { - return true - } - } - - return false -} - func ResourceMatches(rule *PolicyRule, combinedRequestedResource, requestedSubresource string) bool { for _, ruleResource := range rule.Resources { // if everything is allowed, we match @@ -83,36 +52,6 @@ func ResourceMatches(rule *PolicyRule, combinedRequestedResource, requestedSubre return false } -func ResourceNameMatches(rule *PolicyRule, requestedName string) bool { - if len(rule.ResourceNames) == 0 { - return true - } - - for _, ruleName := range rule.ResourceNames { - if ruleName == requestedName { - return true - } - } - - return false -} - -func NonResourceURLMatches(rule *PolicyRule, requestedURL string) bool { - for _, ruleURL := range rule.NonResourceURLs { - if ruleURL == NonResourceAll { - return true - } - if ruleURL == requestedURL { - return true - } - if strings.HasSuffix(ruleURL, "*") && strings.HasPrefix(requestedURL, strings.TrimRight(ruleURL, "*")) { - return true - } - } - - return false -} - // subjectsStrings returns users, groups, serviceaccounts, unknown for display purposes. func SubjectsStrings(subjects []Subject) ([]string, []string, []string, []string) { users := []string{} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/helpers_test.go index 8723796e8..d6e7593bc 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/helpers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/helpers_test.go @@ -175,3 +175,132 @@ func TestResourceMatches(t *testing.T) { }) } } + +func TestPolicyRuleBuilder(t *testing.T) { + tests := []struct { + testName string + verbs []string + groups []string + resources []string + names []string + urls []string + expected bool + policyRule rbac.PolicyRule + }{ + { + testName: "all empty", + verbs: nil, + groups: nil, + resources: nil, + names: nil, + urls: nil, + expected: false, + policyRule: rbac.PolicyRule{}, + }, + { + testName: "normal resource case", + verbs: []string{"get"}, + groups: []string{""}, + resources: []string{"pod"}, + names: []string{"gakki"}, + urls: nil, + expected: true, + policyRule: rbac.PolicyRule{ + Verbs: []string{"get"}, + APIGroups: []string{""}, + Resources: []string{"pod"}, + ResourceNames: []string{"gakki"}, + NonResourceURLs: []string{}, + }, + }, + { + testName: "normal noResourceURLs case", + verbs: []string{"get"}, + groups: nil, + resources: nil, + names: nil, + urls: []string{"/api/registry/healthz"}, + expected: true, + policyRule: rbac.PolicyRule{ + Verbs: []string{"get"}, + APIGroups: []string{}, + Resources: []string{}, + ResourceNames: []string{}, + NonResourceURLs: []string{"/api/registry/healthz"}, + }, + }, + { + testName: "nonResourceURLs with no-empty groups", + verbs: []string{"get"}, + groups: []string{""}, + resources: nil, + names: nil, + urls: []string{"/api/registry/healthz"}, + expected: false, + policyRule: rbac.PolicyRule{}, + }, + { + testName: "nonResourceURLs with no-empty resources", + verbs: []string{"get"}, + groups: nil, + resources: []string{"deployments", "secrets"}, + names: nil, + urls: []string{"/api/registry/healthz"}, + expected: false, + policyRule: rbac.PolicyRule{}, + }, + { + testName: "nonResourceURLs with no-empty resourceNames", + verbs: []string{"get"}, + groups: nil, + resources: nil, + names: []string{"gakki"}, + urls: []string{"/api/registry/healthz"}, + expected: false, + policyRule: rbac.PolicyRule{}, + }, + { + testName: "resource without apiGroups", + verbs: []string{"get"}, + groups: nil, + resources: []string{"pod"}, + names: []string{""}, + urls: nil, + expected: false, + policyRule: rbac.PolicyRule{}, + }, + { + testName: "resourceNames with illegal verb", + verbs: []string{"list", "watch", "create", "deletecollection"}, + groups: []string{""}, + resources: []string{"pod"}, + names: []string{"gakki"}, + urls: nil, + expected: false, + policyRule: rbac.PolicyRule{}, + }, + { + testName: "no nonResourceURLs nor resources", + verbs: []string{"get"}, + groups: []string{"rbac.authorization.k8s.io"}, + resources: nil, + names: []string{"gakki"}, + urls: nil, + expected: false, + policyRule: rbac.PolicyRule{}, + }, + } + for _, tc := range tests { + actual, err := rbac.NewRule(tc.verbs...).Groups(tc.groups...).Resources(tc.resources...).Names(tc.names...).URLs(tc.urls...).Rule() + if err != nil { + if tc.expected { + t.Error(err) + } else { + continue + } + } + if !reflect.DeepEqual(actual, tc.policyRule) { + t.Errorf("Expected %s got %s.", tc.policyRule, actual) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/rbac/install/BUILD index 5c699a006..bffb40331 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/install/BUILD @@ -15,10 +15,8 @@ go_library( "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/rbac/v1alpha1:go_default_library", "//pkg/apis/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/install/install.go index b03d8475c..545523d0a 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/install/install.go @@ -19,10 +19,8 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac/v1" @@ -31,27 +29,14 @@ import ( ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: rbac.GroupName, - // Rollout plan: - // 1.10 (once all stored objects are at v1): - // * remove v1alpha1 (announced deprecated in 1.8) - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version, v1beta1.SchemeGroupVersion.Version, v1alpha1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("ClusterRole", "ClusterRoleBinding"), - AddInternalObjectsToScheme: rbac.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(rbac.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/BUILD index 5aa5b5fc7..9eb4029fc 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/BUILD @@ -10,9 +10,11 @@ go_library( srcs = [ "defaults.go", "doc.go", + "evaluation_helpers.go", "helpers.go", "register.go", "zz_generated.conversion.go", + "zz_generated.deepcopy.go", "zz_generated.defaults.go", ], importpath = "k8s.io/kubernetes/pkg/apis/rbac/v1", diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/doc.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/doc.go index 1668eabe3..5608caba7 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/doc.go @@ -18,6 +18,7 @@ limitations under the License. // +k8s:conversion-gen-external-types=k8s.io/api/rbac/v1 // +k8s:defaulter-gen=TypeMeta // +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/rbac/v1 +// +k8s:deepcopy-gen=package // +groupName=rbac.authorization.k8s.io package v1 // import "k8s.io/kubernetes/pkg/apis/rbac/v1" diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/evaluation_helpers.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/evaluation_helpers.go new file mode 100644 index 000000000..3707760bf --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/evaluation_helpers.go @@ -0,0 +1,179 @@ +/* +Copyright 2018 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" + "strings" + + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func RoleRefGroupKind(roleRef rbacv1.RoleRef) schema.GroupKind { + return schema.GroupKind{Group: roleRef.APIGroup, Kind: roleRef.Kind} +} + +func VerbMatches(rule *rbacv1.PolicyRule, requestedVerb string) bool { + for _, ruleVerb := range rule.Verbs { + if ruleVerb == rbacv1.VerbAll { + return true + } + if ruleVerb == requestedVerb { + return true + } + } + + return false +} + +func APIGroupMatches(rule *rbacv1.PolicyRule, requestedGroup string) bool { + for _, ruleGroup := range rule.APIGroups { + if ruleGroup == rbacv1.APIGroupAll { + return true + } + if ruleGroup == requestedGroup { + return true + } + } + + return false +} + +func ResourceMatches(rule *rbacv1.PolicyRule, combinedRequestedResource, requestedSubresource string) bool { + for _, ruleResource := range rule.Resources { + // if everything is allowed, we match + if ruleResource == rbacv1.ResourceAll { + return true + } + // if we have an exact match, we match + if ruleResource == combinedRequestedResource { + return true + } + + // We can also match a */subresource. + // if there isn't a subresource, then continue + if len(requestedSubresource) == 0 { + continue + } + // if the rule isn't in the format */subresource, then we don't match, continue + if len(ruleResource) == len(requestedSubresource)+2 && + strings.HasPrefix(ruleResource, "*/") && + strings.HasSuffix(ruleResource, requestedSubresource) { + return true + + } + } + + return false +} + +func ResourceNameMatches(rule *rbacv1.PolicyRule, requestedName string) bool { + if len(rule.ResourceNames) == 0 { + return true + } + + for _, ruleName := range rule.ResourceNames { + if ruleName == requestedName { + return true + } + } + + return false +} + +func NonResourceURLMatches(rule *rbacv1.PolicyRule, requestedURL string) bool { + for _, ruleURL := range rule.NonResourceURLs { + if ruleURL == rbacv1.NonResourceAll { + return true + } + if ruleURL == requestedURL { + return true + } + if strings.HasSuffix(ruleURL, "*") && strings.HasPrefix(requestedURL, strings.TrimRight(ruleURL, "*")) { + return true + } + } + + return false +} + +// subjectsStrings returns users, groups, serviceaccounts, unknown for display purposes. +func SubjectsStrings(subjects []rbacv1.Subject) ([]string, []string, []string, []string) { + users := []string{} + groups := []string{} + sas := []string{} + others := []string{} + + for _, subject := range subjects { + switch subject.Kind { + case rbacv1.ServiceAccountKind: + sas = append(sas, fmt.Sprintf("%s/%s", subject.Namespace, subject.Name)) + + case rbacv1.UserKind: + users = append(users, subject.Name) + + case rbacv1.GroupKind: + groups = append(groups, subject.Name) + + default: + others = append(others, fmt.Sprintf("%s/%s/%s", subject.Kind, subject.Namespace, subject.Name)) + } + } + + return users, groups, sas, others +} + +func String(r rbacv1.PolicyRule) string { + return "PolicyRule" + CompactString(r) +} + +// CompactString exposes a compact string representation for use in escalation error messages +func CompactString(r rbacv1.PolicyRule) string { + formatStringParts := []string{} + formatArgs := []interface{}{} + if len(r.APIGroups) > 0 { + formatStringParts = append(formatStringParts, "APIGroups:%q") + formatArgs = append(formatArgs, r.APIGroups) + } + if len(r.Resources) > 0 { + formatStringParts = append(formatStringParts, "Resources:%q") + formatArgs = append(formatArgs, r.Resources) + } + if len(r.NonResourceURLs) > 0 { + formatStringParts = append(formatStringParts, "NonResourceURLs:%q") + formatArgs = append(formatArgs, r.NonResourceURLs) + } + if len(r.ResourceNames) > 0 { + formatStringParts = append(formatStringParts, "ResourceNames:%q") + formatArgs = append(formatArgs, r.ResourceNames) + } + if len(r.Verbs) > 0 { + formatStringParts = append(formatStringParts, "Verbs:%q") + formatArgs = append(formatArgs, r.Verbs) + } + formatString := "{" + strings.Join(formatStringParts, ", ") + "}" + return fmt.Sprintf(formatString, formatArgs...) +} + +type SortableRuleSlice []rbacv1.PolicyRule + +func (s SortableRuleSlice) Len() int { return len(s) } +func (s SortableRuleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s SortableRuleSlice) Less(i, j int) bool { + return strings.Compare(s[i].String(), s[j].String()) < 0 +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/helpers.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/helpers.go index 6bde41408..539fe85b4 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/helpers.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/helpers.go @@ -21,9 +21,13 @@ import ( rbacv1 "k8s.io/api/rbac/v1" + "sort" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// +k8s:deepcopy-gen=false + // PolicyRuleBuilder let's us attach methods. A no-no for API types. // We use it to construct rules in code. It's more compact than trying to write them // out in a literal and allows us to perform some basic checking during construction @@ -87,9 +91,16 @@ func (r *PolicyRuleBuilder) Rule() (rbacv1.PolicyRule, error) { return rbacv1.PolicyRule{}, fmt.Errorf("a rule must have either nonResourceURLs or resources: %#v", r.PolicyRule) } + sort.Strings(r.PolicyRule.Resources) + sort.Strings(r.PolicyRule.ResourceNames) + sort.Strings(r.PolicyRule.APIGroups) + sort.Strings(r.PolicyRule.NonResourceURLs) + sort.Strings(r.PolicyRule.Verbs) return r.PolicyRule, nil } +// +k8s:deepcopy-gen=false + // ClusterRoleBindingBuilder let's us attach methods. A no-no for API types. // We use it to construct bindings in code. It's more compact than trying to write them // out in a literal. @@ -112,14 +123,14 @@ func NewClusterBinding(clusterRoleName string) *ClusterRoleBindingBuilder { func (r *ClusterRoleBindingBuilder) Groups(groups ...string) *ClusterRoleBindingBuilder { for _, group := range groups { - r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.GroupKind, Name: group}) + r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{APIGroup: rbacv1.GroupName, Kind: rbacv1.GroupKind, Name: group}) } return r } func (r *ClusterRoleBindingBuilder) Users(users ...string) *ClusterRoleBindingBuilder { for _, user := range users { - r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.UserKind, Name: user}) + r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{APIGroup: rbacv1.GroupName, Kind: rbacv1.UserKind, Name: user}) } return r } @@ -146,3 +157,91 @@ func (r *ClusterRoleBindingBuilder) Binding() (rbacv1.ClusterRoleBinding, error) return r.ClusterRoleBinding, nil } + +// +k8s:deepcopy-gen=false + +// RoleBindingBuilder let's us attach methods. It is similar to +// ClusterRoleBindingBuilder above. +type RoleBindingBuilder struct { + RoleBinding rbacv1.RoleBinding +} + +// NewRoleBinding creates a RoleBinding builder that can be used +// to define the subjects of a role binding. At least one of +// the `Groups`, `Users` or `SAs` method must be called before +// calling the `Binding*` methods. +func NewRoleBinding(roleName, namespace string) *RoleBindingBuilder { + return &RoleBindingBuilder{ + RoleBinding: rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + Namespace: namespace, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: GroupName, + Kind: "Role", + Name: roleName, + }, + }, + } +} + +func NewRoleBindingForClusterRole(roleName, namespace string) *RoleBindingBuilder { + return &RoleBindingBuilder{ + RoleBinding: rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + Namespace: namespace, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: GroupName, + Kind: "ClusterRole", + Name: roleName, + }, + }, + } +} + +// Groups adds the specified groups as the subjects of the RoleBinding. +func (r *RoleBindingBuilder) Groups(groups ...string) *RoleBindingBuilder { + for _, group := range groups { + r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.GroupKind, APIGroup: GroupName, Name: group}) + } + return r +} + +// Users adds the specified users as the subjects of the RoleBinding. +func (r *RoleBindingBuilder) Users(users ...string) *RoleBindingBuilder { + for _, user := range users { + r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: GroupName, Name: user}) + } + return r +} + +// SAs adds the specified service accounts as the subjects of the +// RoleBinding. +func (r *RoleBindingBuilder) SAs(namespace string, serviceAccountNames ...string) *RoleBindingBuilder { + for _, saName := range serviceAccountNames { + r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Namespace: namespace, Name: saName}) + } + return r +} + +// BindingOrDie calls the binding method and panics if there is an error. +func (r *RoleBindingBuilder) BindingOrDie() rbacv1.RoleBinding { + ret, err := r.Binding() + if err != nil { + panic(err) + } + return ret +} + +// Binding builds and returns the RoleBinding API object from the builder +// object. +func (r *RoleBindingBuilder) Binding() (rbacv1.RoleBinding, error) { + if len(r.RoleBinding.Subjects) == 0 { + return rbacv1.RoleBinding{}, fmt.Errorf("subjects are required: %#v", r.RoleBinding) + } + + return r.RoleBinding, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go index cf600e63a..f1e40df78 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go new file mode 100644 index 000000000..0a68a2343 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go @@ -0,0 +1,94 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterRoleBindingBuilder) DeepCopyInto(out *ClusterRoleBindingBuilder) { + *out = *in + in.ClusterRoleBinding.DeepCopyInto(&out.ClusterRoleBinding) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRoleBindingBuilder. +func (in *ClusterRoleBindingBuilder) DeepCopy() *ClusterRoleBindingBuilder { + if in == nil { + return nil + } + out := new(ClusterRoleBindingBuilder) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyRuleBuilder) DeepCopyInto(out *PolicyRuleBuilder) { + *out = *in + in.PolicyRule.DeepCopyInto(&out.PolicyRule) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyRuleBuilder. +func (in *PolicyRuleBuilder) DeepCopy() *PolicyRuleBuilder { + if in == nil { + return nil + } + out := new(PolicyRuleBuilder) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleBindingBuilder) DeepCopyInto(out *RoleBindingBuilder) { + *out = *in + in.RoleBinding.DeepCopyInto(&out.RoleBinding) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleBindingBuilder. +func (in *RoleBindingBuilder) DeepCopy() *RoleBindingBuilder { + if in == nil { + return nil + } + out := new(RoleBindingBuilder) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in SortableRuleSlice) DeepCopyInto(out *SortableRuleSlice) { + { + in := &in + *out = make(SortableRuleSlice, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SortableRuleSlice. +func (in SortableRuleSlice) DeepCopy() SortableRuleSlice { + if in == nil { + return nil + } + out := new(SortableRuleSlice) + in.DeepCopyInto(out) + return *out +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go index aa5fbd149..f0d53c172 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1alpha1/zz_generated.conversion.go index bc9fa3f15..c9df6f6f2 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1alpha1/zz_generated.defaults.go index 2d9e42b91..54977814e 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1beta1/zz_generated.conversion.go index f98642dda..2f441d02a 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1beta1/zz_generated.defaults.go index 878390508..8eb654424 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/validation/validation.go index 92fc5bdb1..1cb0850cc 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/validation/validation.go @@ -25,19 +25,20 @@ import ( "k8s.io/kubernetes/pkg/apis/rbac" ) +// ValidateRBACName is exported to allow types outside of the RBAC API group to reuse this validation logic // Minimal validation of names for roles and bindings. Identical to the validation for Openshift. See: // * https://github.com/kubernetes/kubernetes/blob/60db50/pkg/api/validation/name.go // * https://github.com/openshift/origin/blob/388478/pkg/api/helpers.go -func minimalNameRequirements(name string, prefix bool) []string { +func ValidateRBACName(name string, prefix bool) []string { return path.IsValidPathSegmentName(name) } func ValidateRole(role *rbac.Role) field.ErrorList { allErrs := field.ErrorList{} - allErrs = append(allErrs, validation.ValidateObjectMeta(&role.ObjectMeta, true, minimalNameRequirements, field.NewPath("metadata"))...) + allErrs = append(allErrs, validation.ValidateObjectMeta(&role.ObjectMeta, true, ValidateRBACName, field.NewPath("metadata"))...) for i, rule := range role.Rules { - if err := validatePolicyRule(rule, true, field.NewPath("rules").Index(i)); err != nil { + if err := ValidatePolicyRule(rule, true, field.NewPath("rules").Index(i)); err != nil { allErrs = append(allErrs, err...) } } @@ -56,10 +57,10 @@ func ValidateRoleUpdate(role *rbac.Role, oldRole *rbac.Role) field.ErrorList { func ValidateClusterRole(role *rbac.ClusterRole) field.ErrorList { allErrs := field.ErrorList{} - allErrs = append(allErrs, validation.ValidateObjectMeta(&role.ObjectMeta, false, minimalNameRequirements, field.NewPath("metadata"))...) + allErrs = append(allErrs, validation.ValidateObjectMeta(&role.ObjectMeta, false, ValidateRBACName, field.NewPath("metadata"))...) for i, rule := range role.Rules { - if err := validatePolicyRule(rule, false, field.NewPath("rules").Index(i)); err != nil { + if err := ValidatePolicyRule(rule, false, field.NewPath("rules").Index(i)); err != nil { allErrs = append(allErrs, err...) } } @@ -92,7 +93,8 @@ func ValidateClusterRoleUpdate(role *rbac.ClusterRole, oldRole *rbac.ClusterRole return allErrs } -func validatePolicyRule(rule rbac.PolicyRule, isNamespaced bool, fldPath *field.Path) field.ErrorList { +// ValidatePolicyRule is exported to allow types outside of the RBAC API group to embed a rbac.PolicyRule and reuse this validation logic +func ValidatePolicyRule(rule rbac.PolicyRule, isNamespaced bool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(rule.Verbs) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("verbs"), "verbs must contain at least one value")) @@ -119,7 +121,7 @@ func validatePolicyRule(rule rbac.PolicyRule, isNamespaced bool, fldPath *field. func ValidateRoleBinding(roleBinding *rbac.RoleBinding) field.ErrorList { allErrs := field.ErrorList{} - allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, true, minimalNameRequirements, field.NewPath("metadata"))...) + allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, true, ValidateRBACName, field.NewPath("metadata"))...) // TODO allow multiple API groups. For now, restrict to one, but I can envision other experimental roles in other groups taking // advantage of the binding infrastructure @@ -137,14 +139,14 @@ func ValidateRoleBinding(roleBinding *rbac.RoleBinding) field.ErrorList { if len(roleBinding.RoleRef.Name) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("roleRef", "name"), "")) } else { - for _, msg := range minimalNameRequirements(roleBinding.RoleRef.Name, false) { + for _, msg := range ValidateRBACName(roleBinding.RoleRef.Name, false) { allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "name"), roleBinding.RoleRef.Name, msg)) } } subjectsPath := field.NewPath("subjects") for i, subject := range roleBinding.Subjects { - allErrs = append(allErrs, validateRoleBindingSubject(subject, true, subjectsPath.Index(i))...) + allErrs = append(allErrs, ValidateRoleBindingSubject(subject, true, subjectsPath.Index(i))...) } return allErrs @@ -163,7 +165,7 @@ func ValidateRoleBindingUpdate(roleBinding *rbac.RoleBinding, oldRoleBinding *rb func ValidateClusterRoleBinding(roleBinding *rbac.ClusterRoleBinding) field.ErrorList { allErrs := field.ErrorList{} - allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, false, minimalNameRequirements, field.NewPath("metadata"))...) + allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, false, ValidateRBACName, field.NewPath("metadata"))...) // TODO allow multiple API groups. For now, restrict to one, but I can envision other experimental roles in other groups taking // advantage of the binding infrastructure @@ -181,14 +183,14 @@ func ValidateClusterRoleBinding(roleBinding *rbac.ClusterRoleBinding) field.Erro if len(roleBinding.RoleRef.Name) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("roleRef", "name"), "")) } else { - for _, msg := range minimalNameRequirements(roleBinding.RoleRef.Name, false) { + for _, msg := range ValidateRBACName(roleBinding.RoleRef.Name, false) { allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "name"), roleBinding.RoleRef.Name, msg)) } } subjectsPath := field.NewPath("subjects") for i, subject := range roleBinding.Subjects { - allErrs = append(allErrs, validateRoleBindingSubject(subject, false, subjectsPath.Index(i))...) + allErrs = append(allErrs, ValidateRoleBindingSubject(subject, false, subjectsPath.Index(i))...) } return allErrs @@ -205,7 +207,8 @@ func ValidateClusterRoleBindingUpdate(roleBinding *rbac.ClusterRoleBinding, oldR return allErrs } -func validateRoleBindingSubject(subject rbac.Subject, isNamespaced bool, fldPath *field.Path) field.ErrorList { +// ValidateRoleBindingSubject is exported to allow types outside of the RBAC API group to embed a rbac.Subject and reuse this validation logic +func ValidateRoleBindingSubject(subject rbac.Subject, isNamespaced bool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(subject.Name) == 0 { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go index c916c0c7e..bb735c233 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/BUILD index 58811a512..61a76279f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/BUILD @@ -3,12 +3,14 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( name = "go_default_library", srcs = [ "doc.go", + "helpers.go", "register.go", "types.go", "zz_generated.deepcopy.go", @@ -35,7 +37,15 @@ filegroup( "//pkg/apis/scheduling/fuzzer:all-srcs", "//pkg/apis/scheduling/install:all-srcs", "//pkg/apis/scheduling/v1alpha1:all-srcs", + "//pkg/apis/scheduling/v1beta1:all-srcs", "//pkg/apis/scheduling/validation:all-srcs", ], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["helpers_test.go"], + embed = [":go_default_library"], + deps = ["//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/helpers.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/helpers.go new file mode 100644 index 000000000..58b379975 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/helpers.go @@ -0,0 +1,65 @@ +/* +Copyright 2018 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 scheduling + +import ( + "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// SystemPriorityClasses define system priority classes that are auto-created at cluster bootstrapping. +// Our API validation logic ensures that any priority class that has a system prefix or its value +// is higher than HighestUserDefinablePriority is equal to one of these SystemPriorityClasses. +var systemPriorityClasses = []*PriorityClass{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: SystemNodeCritical, + }, + Value: SystemCriticalPriority + 1000, + Description: "Used for system critical pods that must not be moved from their current node.", + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: SystemClusterCritical, + }, + Value: SystemCriticalPriority, + Description: "Used for system critical pods that must run in the cluster, but can be moved to another node if necessary.", + }, +} + +// SystemPriorityClasses returns the list of system priority classes. +// NOTE: be careful not to modify any of elements of the returned array directly. +func SystemPriorityClasses() []*PriorityClass { + return systemPriorityClasses +} + +// IsKnownSystemPriorityClass checks that "pc" is equal to one of the system PriorityClasses. +// It ignores "description", labels, annotations, etc. of the PriorityClass. +func IsKnownSystemPriorityClass(pc *PriorityClass) (bool, error) { + for _, spc := range systemPriorityClasses { + if spc.Name == pc.Name { + if spc.Value != pc.Value { + return false, fmt.Errorf("value of %v PriorityClass must be %v", spc.Name, spc.Value) + } + if spc.GlobalDefault != pc.GlobalDefault { + return false, fmt.Errorf("globalDefault of %v PriorityClass must be %v", spc.Name, spc.GlobalDefault) + } + return true, nil + } + } + return false, fmt.Errorf("%v is not a known system priority class", pc.Name) +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/helpers_test.go new file mode 100644 index 000000000..b0fe132b8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/helpers_test.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 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 scheduling + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestIsKnownSystemPriorityClass(t *testing.T) { + tests := []struct { + name string + pc *PriorityClass + expected bool + }{ + { + name: "system priority class", + pc: SystemPriorityClasses()[0], + expected: true, + }, + { + name: "non-system priority class", + pc: &PriorityClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: SystemNodeCritical, + }, + Value: SystemCriticalPriority, // This is the value of system cluster critical + Description: "Used for system critical pods that must not be moved from their current node.", + }, + expected: false, + }, + } + + for _, test := range tests { + if is, err := IsKnownSystemPriorityClass(test.pc); test.expected != is { + t.Errorf("Test [%v]: Expected %v, but got %v. Error: %v", test.name, test.expected, is, err) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/install/BUILD index b15164848..dabfec236 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/install/BUILD @@ -13,10 +13,9 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/scheduling:go_default_library", "//pkg/apis/scheduling/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", + "//pkg/apis/scheduling/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/install/install.go index 0a47a8815..ef9cb435f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/install/install.go @@ -19,32 +19,22 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/scheduling" "k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1" + "k8s.io/kubernetes/pkg/apis/scheduling/v1beta1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: scheduling.GroupName, - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("PriorityClass"), - AddInternalObjectsToScheme: scheduling.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(scheduling.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/types.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/types.go index d5db894a8..29c950157 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/types.go @@ -23,9 +23,17 @@ const ( // that do not specify any priority class and there is no priority class // marked as default. DefaultPriorityWhenNoDefaultClassExists = 0 + // HighestUserDefinablePriority is the highest priority for user defined priority classes. Priority values larger than 1 billion are reserved for Kubernetes system use. + HighestUserDefinablePriority = int32(1000000000) + // SystemCriticalPriority is the beginning of the range of priority values for critical system components. + SystemCriticalPriority = 2 * HighestUserDefinablePriority // SystemPriorityClassPrefix is the prefix reserved for system priority class names. Other priority // classes are not allowed to start with this prefix. SystemPriorityClassPrefix = "system-" + // NOTE: In order to avoid conflict of names with user-defined priority classes, all the names must + // start with SystemPriorityClassPrefix. + SystemClusterCritical = SystemPriorityClassPrefix + "cluster-critical" + SystemNodeCritical = SystemPriorityClassPrefix + "node-critical" ) // +genclient diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1/zz_generated.conversion.go index 18fe164df..96c958888 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/BUILD new file mode 100644 index 000000000..32c2fce12 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/BUILD @@ -0,0 +1,37 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "register.go", + "zz_generated.conversion.go", + "zz_generated.defaults.go", + ], + importpath = "k8s.io/kubernetes/pkg/apis/scheduling/v1beta1", + deps = [ + "//pkg/apis/scheduling:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/doc.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/doc.go new file mode 100644 index 000000000..117381f65 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2018 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. +*/ + +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/scheduling +// +k8s:conversion-gen-external-types=k8s.io/api/scheduling/v1beta1 +// +groupName=scheduling.k8s.io +// +k8s:defaulter-gen=TypeMeta +// +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/scheduling/v1beta1 +package v1beta1 // import "k8s.io/kubernetes/pkg/apis/scheduling/v1beta1" diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/register.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/register.go new file mode 100644 index 000000000..45eae937c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/register.go @@ -0,0 +1,45 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "scheduling.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + localSchemeBuilder = &schedulingv1beta1.SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(RegisterDefaults) +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/zz_generated.conversion.go new file mode 100644 index 000000000..570ed9893 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/zz_generated.conversion.go @@ -0,0 +1,93 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1beta1 + +import ( + unsafe "unsafe" + + v1beta1 "k8s.io/api/scheduling/v1beta1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + scheduling "k8s.io/kubernetes/pkg/apis/scheduling" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(scheme *runtime.Scheme) error { + return scheme.AddGeneratedConversionFuncs( + Convert_v1beta1_PriorityClass_To_scheduling_PriorityClass, + Convert_scheduling_PriorityClass_To_v1beta1_PriorityClass, + Convert_v1beta1_PriorityClassList_To_scheduling_PriorityClassList, + Convert_scheduling_PriorityClassList_To_v1beta1_PriorityClassList, + ) +} + +func autoConvert_v1beta1_PriorityClass_To_scheduling_PriorityClass(in *v1beta1.PriorityClass, out *scheduling.PriorityClass, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.Value = in.Value + out.GlobalDefault = in.GlobalDefault + out.Description = in.Description + return nil +} + +// Convert_v1beta1_PriorityClass_To_scheduling_PriorityClass is an autogenerated conversion function. +func Convert_v1beta1_PriorityClass_To_scheduling_PriorityClass(in *v1beta1.PriorityClass, out *scheduling.PriorityClass, s conversion.Scope) error { + return autoConvert_v1beta1_PriorityClass_To_scheduling_PriorityClass(in, out, s) +} + +func autoConvert_scheduling_PriorityClass_To_v1beta1_PriorityClass(in *scheduling.PriorityClass, out *v1beta1.PriorityClass, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.Value = in.Value + out.GlobalDefault = in.GlobalDefault + out.Description = in.Description + return nil +} + +// Convert_scheduling_PriorityClass_To_v1beta1_PriorityClass is an autogenerated conversion function. +func Convert_scheduling_PriorityClass_To_v1beta1_PriorityClass(in *scheduling.PriorityClass, out *v1beta1.PriorityClass, s conversion.Scope) error { + return autoConvert_scheduling_PriorityClass_To_v1beta1_PriorityClass(in, out, s) +} + +func autoConvert_v1beta1_PriorityClassList_To_scheduling_PriorityClassList(in *v1beta1.PriorityClassList, out *scheduling.PriorityClassList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]scheduling.PriorityClass)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1beta1_PriorityClassList_To_scheduling_PriorityClassList is an autogenerated conversion function. +func Convert_v1beta1_PriorityClassList_To_scheduling_PriorityClassList(in *v1beta1.PriorityClassList, out *scheduling.PriorityClassList, s conversion.Scope) error { + return autoConvert_v1beta1_PriorityClassList_To_scheduling_PriorityClassList(in, out, s) +} + +func autoConvert_scheduling_PriorityClassList_To_v1beta1_PriorityClassList(in *scheduling.PriorityClassList, out *v1beta1.PriorityClassList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1beta1.PriorityClass)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_scheduling_PriorityClassList_To_v1beta1_PriorityClassList is an autogenerated conversion function. +func Convert_scheduling_PriorityClassList_To_v1beta1_PriorityClassList(in *scheduling.PriorityClassList, out *v1beta1.PriorityClassList, s conversion.Scope) error { + return autoConvert_scheduling_PriorityClassList_To_v1beta1_PriorityClassList(in, out, s) +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/zz_generated.defaults.go new file mode 100644 index 000000000..73e63fc11 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/v1beta1/zz_generated.defaults.go @@ -0,0 +1,32 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/validation/validation.go index c8b85ef85..5f2998157 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/validation/validation.go @@ -17,6 +17,7 @@ limitations under the License. package validation import ( + "fmt" "strings" "k8s.io/apimachinery/pkg/util/validation/field" @@ -24,22 +25,21 @@ import ( "k8s.io/kubernetes/pkg/apis/scheduling" ) -// ValidatePriorityClassName checks whether the given priority class name is valid. -func ValidatePriorityClassName(name string, prefix bool) []string { - var allErrs []string - if strings.HasPrefix(name, scheduling.SystemPriorityClassPrefix) { - allErrs = append(allErrs, "priority class names with '"+scheduling.SystemPriorityClassPrefix+"' prefix are reserved for system use only") - } - allErrs = append(allErrs, apivalidation.NameIsDNSSubdomain(name, prefix)...) - return allErrs -} - // ValidatePriorityClass tests whether required fields in the PriorityClass are // set correctly. func ValidatePriorityClass(pc *scheduling.PriorityClass) field.ErrorList { allErrs := field.ErrorList{} - allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&pc.ObjectMeta, false, ValidatePriorityClassName, field.NewPath("metadata"))...) - // The "Value" field can be any valid integer. So, no need to validate. + allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&pc.ObjectMeta, false, apivalidation.NameIsDNSSubdomain, field.NewPath("metadata"))...) + // If the priorityClass starts with a system prefix, it must be one of the + // predefined system priority classes. + if strings.HasPrefix(pc.Name, scheduling.SystemPriorityClassPrefix) { + if is, err := scheduling.IsKnownSystemPriorityClass(pc); !is { + allErrs = append(allErrs, field.Forbidden(field.NewPath("metadata", "name"), "priority class names with '"+scheduling.SystemPriorityClassPrefix+"' prefix are reserved for system use only. error: "+err.Error())) + } + } else if pc.Value > scheduling.HighestUserDefinablePriority { + // Non-system critical priority classes are not allowed to have a value larger than HighestUserDefinablePriority. + allErrs = append(allErrs, field.Forbidden(field.NewPath("value"), fmt.Sprintf("maximum allowed value of a user defined priority is %v", scheduling.HighestUserDefinablePriority))) + } return allErrs } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/validation/validation_test.go index e35ee4269..3d7373e20 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/validation/validation_test.go @@ -25,6 +25,7 @@ import ( ) func TestValidatePriorityClass(t *testing.T) { + spcs := scheduling.SystemPriorityClasses() successCases := map[string]scheduling.PriorityClass{ "no description": { ObjectMeta: metav1.ObjectMeta{Name: "tier1", Namespace: ""}, @@ -36,6 +37,12 @@ func TestValidatePriorityClass(t *testing.T) { GlobalDefault: false, Description: "Used for the highest priority pods.", }, + "system node critical": { + ObjectMeta: metav1.ObjectMeta{Name: spcs[0].Name, Namespace: ""}, + Value: spcs[0].Value, + GlobalDefault: spcs[0].GlobalDefault, + Description: "system priority class 0", + }, } for k, v := range successCases { @@ -53,9 +60,15 @@ func TestValidatePriorityClass(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "tier&1", Namespace: ""}, Value: 100, }, - "invalid system name": { - ObjectMeta: metav1.ObjectMeta{Name: scheduling.SystemPriorityClassPrefix + "test"}, - Value: 100, + "incorrect system class name": { + ObjectMeta: metav1.ObjectMeta{Name: spcs[0].Name, Namespace: ""}, + Value: 0, + GlobalDefault: spcs[0].GlobalDefault, + }, + "incorrect system class value": { + ObjectMeta: metav1.ObjectMeta{Name: "system-something", Namespace: ""}, + Value: spcs[0].Value, + GlobalDefault: spcs[0].GlobalDefault, }, } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/zz_generated.deepcopy.go index c425f864b..8584caa58 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/scheduling/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/scheduling/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/settings/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/settings/install/BUILD index 9a6ffe726..78fc97fd7 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/settings/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/settings/install/BUILD @@ -13,9 +13,8 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/settings:go_default_library", "//pkg/apis/settings/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/settings/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/settings/install/install.go index bf4ae5c57..c4cf5e788 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/settings/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/settings/install/install.go @@ -19,30 +19,20 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/settings" "k8s.io/kubernetes/pkg/apis/settings/v1alpha1" ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: settings.GroupName, - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: settings.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(settings.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/settings/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/settings/v1alpha1/zz_generated.conversion.go index 7689abf1d..bb3a4faea 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/settings/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/settings/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/settings/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/settings/v1alpha1/zz_generated.defaults.go index f7604a421..b8559cf3e 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/settings/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/settings/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -86,6 +86,9 @@ func SetObjectDefaults_PodPreset(in *v1alpha1.PodPreset) { } } } + if b.ServiceAccountToken != nil { + v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken) + } } } if a.VolumeSource.ScaleIO != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/settings/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/settings/zz_generated.deepcopy.go index 74f79a490..e404f515d 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/settings/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/settings/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/install/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/storage/install/BUILD index 798341862..0e1c479f1 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/install/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/install/BUILD @@ -15,10 +15,8 @@ go_library( "//pkg/apis/storage/v1:go_default_library", "//pkg/apis/storage/v1alpha1:go_default_library", "//pkg/apis/storage/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/install/install.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/install/install.go index 28fa78659..8ebe9e8b7 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/install/install.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/install/install.go @@ -19,10 +19,8 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/storage" "k8s.io/kubernetes/pkg/apis/storage/v1" @@ -31,27 +29,14 @@ import ( ) func init() { - Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme) + Install(legacyscheme.Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: storage.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version, v1beta1.SchemeGroupVersion.Version, v1alpha1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString( - "StorageClass", - "VolumeAttachment", - ), - AddInternalObjectsToScheme: storage.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(storage.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/types.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/types.go index e44b327d3..cd86b02f2 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/types.go @@ -72,6 +72,14 @@ type StorageClass struct { // the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + AllowedTopologies []api.TopologySelectorTerm } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/util/BUILD b/vendor/k8s.io/kubernetes/pkg/apis/storage/util/BUILD index 7a5a5fd33..c095396fb 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/util/BUILD @@ -39,6 +39,7 @@ go_test( srcs = ["util_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/apis/core:go_default_library", "//pkg/apis/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/util/util.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/util/util.go index 9d1340435..c81a95b81 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/util/util.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/util/util.go @@ -27,4 +27,7 @@ func DropDisabledAlphaFields(class *storage.StorageClass) { if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { class.VolumeBindingMode = nil } + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + class.AllowedTopologies = nil + } } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/util/util_test.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/util/util_test.go index 1a0ef70b0..f783c2ee4 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/util/util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/util/util_test.go @@ -17,39 +17,60 @@ limitations under the License. package util import ( + "reflect" "testing" utilfeature "k8s.io/apiserver/pkg/util/feature" + api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/storage" ) func TestDropAlphaFields(t *testing.T) { bindingMode := storage.VolumeBindingWaitForFirstConsumer + allowedTopologies := []api.TopologySelectorTerm{ + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "kubernetes.io/hostname", + Values: []string{"node1"}, + }, + }, + }, + } // Test that field gets dropped when feature gate is not set - if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false"); err != nil { - t.Fatalf("Failed to set feature gate for VolumeScheduling: %v", err) + if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false,DynamicProvisioningScheduling=false"); err != nil { + t.Fatalf("Failed to set feature gate for VolumeScheduling or DynamicProvisioningScheduling: %v", err) } class := &storage.StorageClass{ VolumeBindingMode: &bindingMode, + AllowedTopologies: allowedTopologies, } DropDisabledAlphaFields(class) if class.VolumeBindingMode != nil { t.Errorf("VolumeBindingMode field didn't get dropped: %+v", class.VolumeBindingMode) } + if class.AllowedTopologies != nil { + t.Errorf("AllowedTopologies field didn't get dropped: %+v", class.AllowedTopologies) + } // Test that field does not get dropped when feature gate is set class = &storage.StorageClass{ VolumeBindingMode: &bindingMode, + AllowedTopologies: allowedTopologies, } - if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=true"); err != nil { - t.Fatalf("Failed to set feature gate for VolumeScheduling: %v", err) + if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=true,DynamicProvisioningScheduling=true"); err != nil { + t.Fatalf("Failed to set feature gate for VolumeScheduling or DynamicProvisioningScheduling: %v", err) } DropDisabledAlphaFields(class) if class.VolumeBindingMode != &bindingMode { t.Errorf("VolumeBindingMode field got unexpectantly modified: %+v", class.VolumeBindingMode) } - if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false"); err != nil { - t.Fatalf("Failed to disable feature gate for VolumeScheduling: %v", err) + if !reflect.DeepEqual(class.AllowedTopologies, allowedTopologies) { + t.Errorf("AllowedTopologies field got unexpectantly modified: %+v", class.AllowedTopologies) + } + + if err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false,DynamicProvisioningScheduling=false"); err != nil { + t.Fatalf("Failed to disable feature gate for VolumeScheduling or DynamicProvisioningScheduling: %v", err) } } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1/zz_generated.conversion.go index 391d169bb..1ec5a534f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -54,6 +54,7 @@ func autoConvert_v1_StorageClass_To_storage_StorageClass(in *v1.StorageClass, ou out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions)) out.AllowVolumeExpansion = (*bool)(unsafe.Pointer(in.AllowVolumeExpansion)) out.VolumeBindingMode = (*storage.VolumeBindingMode)(unsafe.Pointer(in.VolumeBindingMode)) + out.AllowedTopologies = *(*[]core.TopologySelectorTerm)(unsafe.Pointer(&in.AllowedTopologies)) return nil } @@ -70,6 +71,7 @@ func autoConvert_storage_StorageClass_To_v1_StorageClass(in *storage.StorageClas out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions)) out.AllowVolumeExpansion = (*bool)(unsafe.Pointer(in.AllowVolumeExpansion)) out.VolumeBindingMode = (*v1.VolumeBindingMode)(unsafe.Pointer(in.VolumeBindingMode)) + out.AllowedTopologies = *(*[]core_v1.TopologySelectorTerm)(unsafe.Pointer(&in.AllowedTopologies)) return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1/zz_generated.defaults.go index f066b2eaa..93fe2514f 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1alpha1/zz_generated.conversion.go index 35a6306f3..84de29ee3 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1beta1/zz_generated.conversion.go index 8d0fc10c8..8fdadeb46 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,6 +66,7 @@ func autoConvert_v1beta1_StorageClass_To_storage_StorageClass(in *v1beta1.Storag out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions)) out.AllowVolumeExpansion = (*bool)(unsafe.Pointer(in.AllowVolumeExpansion)) out.VolumeBindingMode = (*storage.VolumeBindingMode)(unsafe.Pointer(in.VolumeBindingMode)) + out.AllowedTopologies = *(*[]core.TopologySelectorTerm)(unsafe.Pointer(&in.AllowedTopologies)) return nil } @@ -82,6 +83,7 @@ func autoConvert_storage_StorageClass_To_v1beta1_StorageClass(in *storage.Storag out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions)) out.AllowVolumeExpansion = (*bool)(unsafe.Pointer(in.AllowVolumeExpansion)) out.VolumeBindingMode = (*v1beta1.VolumeBindingMode)(unsafe.Pointer(in.VolumeBindingMode)) + out.AllowedTopologies = *(*[]v1.TopologySelectorTerm)(unsafe.Pointer(&in.AllowedTopologies)) return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1beta1/zz_generated.defaults.go index 5bf3557fb..80830c4db 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/validation/validation.go index e9f66e938..1c29df8f4 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/validation/validation.go @@ -47,6 +47,7 @@ func ValidateStorageClass(storageClass *storage.StorageClass) field.ErrorList { allErrs = append(allErrs, validateReclaimPolicy(storageClass.ReclaimPolicy, field.NewPath("reclaimPolicy"))...) allErrs = append(allErrs, validateAllowVolumeExpansion(storageClass.AllowVolumeExpansion, field.NewPath("allowVolumeExpansion"))...) allErrs = append(allErrs, validateVolumeBindingMode(storageClass.VolumeBindingMode, field.NewPath("volumeBindingMode"))...) + allErrs = append(allErrs, validateAllowedTopologies(storageClass.AllowedTopologies, field.NewPath("allowedTopologies"))...) return allErrs } @@ -239,3 +240,22 @@ func validateVolumeBindingMode(mode *storage.VolumeBindingMode, fldPath *field.P return allErrs } + +// validateAllowedTopology tests that AllowedTopologies specifies valid values. +func validateAllowedTopologies(topologies []api.TopologySelectorTerm, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if topologies == nil || len(topologies) == 0 { + return allErrs + } + + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate DynamicProvisioningScheduling")) + } + + for i, term := range topologies { + allErrs = append(allErrs, apivalidation.ValidateTopologySelectorTerm(term, fldPath.Index(i))...) + } + + return allErrs +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/validation/validation_test.go index 7e6f79687..06ed6c744 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/validation/validation_test.go @@ -450,21 +450,22 @@ func TestVolumeAttachmentUpdateValidation(t *testing.T) { } } -func makeClassWithBinding(mode *storage.VolumeBindingMode) *storage.StorageClass { +func makeClass(mode *storage.VolumeBindingMode, topologies []api.TopologySelectorTerm) *storage.StorageClass { return &storage.StorageClass{ ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "foo"}, Provisioner: "kubernetes.io/foo-provisioner", ReclaimPolicy: &deleteReclaimPolicy, VolumeBindingMode: mode, + AllowedTopologies: topologies, } } // TODO: Remove these tests once feature gate is not required func TestValidateVolumeBindingModeAlphaDisabled(t *testing.T) { errorCases := map[string]*storage.StorageClass{ - "immediate mode": makeClassWithBinding(&immediateMode1), - "waiting mode": makeClassWithBinding(&waitingMode), - "invalid mode": makeClassWithBinding(&invalidMode), + "immediate mode": makeClass(&immediateMode1, nil), + "waiting mode": makeClass(&waitingMode, nil), + "invalid mode": makeClass(&invalidMode, nil), } err := utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false") @@ -486,19 +487,19 @@ type bindingTest struct { func TestValidateVolumeBindingMode(t *testing.T) { cases := map[string]bindingTest{ "no mode": { - class: makeClassWithBinding(nil), + class: makeClass(nil, nil), shouldSucceed: false, }, "immediate mode": { - class: makeClassWithBinding(&immediateMode1), + class: makeClass(&immediateMode1, nil), shouldSucceed: true, }, "waiting mode": { - class: makeClassWithBinding(&waitingMode), + class: makeClass(&waitingMode, nil), shouldSucceed: true, }, "invalid mode": { - class: makeClassWithBinding(&invalidMode), + class: makeClass(&invalidMode, nil), shouldSucceed: false, }, } @@ -532,10 +533,10 @@ type updateTest struct { } func TestValidateUpdateVolumeBindingMode(t *testing.T) { - noBinding := makeClassWithBinding(nil) - immediateBinding1 := makeClassWithBinding(&immediateMode1) - immediateBinding2 := makeClassWithBinding(&immediateMode2) - waitBinding := makeClassWithBinding(&waitingMode) + noBinding := makeClass(nil, nil) + immediateBinding1 := makeClass(&immediateMode1, nil) + immediateBinding2 := makeClass(&immediateMode2, nil) + waitBinding := makeClass(&waitingMode, nil) cases := map[string]updateTest{ "old and new no mode": { @@ -591,3 +592,102 @@ func TestValidateUpdateVolumeBindingMode(t *testing.T) { t.Fatalf("Failed to disable feature gate for VolumeScheduling: %v", err) } } + +func TestValidateAllowedTopologies(t *testing.T) { + + validTopology := []api.TopologySelectorTerm{ + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "failure-domain.beta.kubernetes.io/zone", + Values: []string{"zone1"}, + }, + { + Key: "kubernetes.io/hostname", + Values: []string{"node1"}, + }, + }, + }, + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "failure-domain.beta.kubernetes.io/zone", + Values: []string{"zone2"}, + }, + { + Key: "kubernetes.io/hostname", + Values: []string{"node2"}, + }, + }, + }, + } + + topologyInvalidKey := []api.TopologySelectorTerm{ + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "/invalidkey", + Values: []string{"zone1"}, + }, + }, + }, + } + + topologyLackOfValues := []api.TopologySelectorTerm{ + { + MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ + { + Key: "kubernetes.io/hostname", + Values: []string{}, + }, + }, + }, + } + + cases := map[string]bindingTest{ + "no topology": { + class: makeClass(nil, nil), + shouldSucceed: true, + }, + "valid topology": { + class: makeClass(nil, validTopology), + shouldSucceed: true, + }, + "topology invalid key": { + class: makeClass(nil, topologyInvalidKey), + shouldSucceed: false, + }, + "topology lack of values": { + class: makeClass(nil, topologyLackOfValues), + shouldSucceed: false, + }, + } + + // TODO: remove when feature gate not required + err := utilfeature.DefaultFeatureGate.Set("DynamicProvisioningScheduling=true") + if err != nil { + t.Fatalf("Failed to enable feature gate for DynamicProvisioningScheduling: %v", err) + } + + for testName, testCase := range cases { + errs := ValidateStorageClass(testCase.class) + if testCase.shouldSucceed && len(errs) != 0 { + t.Errorf("Expected success for test %q, got %v", testName, errs) + } + if !testCase.shouldSucceed && len(errs) == 0 { + t.Errorf("Expected failure for test %q, got success", testName) + } + } + + err = utilfeature.DefaultFeatureGate.Set("DynamicProvisioningScheduling=false") + if err != nil { + t.Fatalf("Failed to disable feature gate for DynamicProvisioningScheduling: %v", err) + } + + for testName, testCase := range cases { + errs := ValidateStorageClass(testCase.class) + if len(errs) == 0 && testCase.class.AllowedTopologies != nil { + t.Errorf("Expected failure for test %q, got success", testName) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/apis/storage/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/apis/storage/zz_generated.deepcopy.go index 7c5fdf78a..f10b66563 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/storage/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/storage/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -69,6 +69,13 @@ func (in *StorageClass) DeepCopyInto(out *StorageClass) { **out = **in } } + if in.AllowedTopologies != nil { + in, out := &in.AllowedTopologies, &out.AllowedTopologies + *out = make([]core.TopologySelectorTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/vendor/k8s.io/kubernetes/pkg/auth/OWNERS b/vendor/k8s.io/kubernetes/pkg/auth/OWNERS index 2d126eacd..a6d8763e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/auth/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/auth/OWNERS @@ -2,5 +2,7 @@ approvers: - erictune - liggitt - deads2k +- mikedanese reviewers: +- mikedanese - enj diff --git a/vendor/k8s.io/kubernetes/pkg/auth/authorizer/OWNERS b/vendor/k8s.io/kubernetes/pkg/auth/authorizer/OWNERS deleted file mode 100755 index 944879920..000000000 --- a/vendor/k8s.io/kubernetes/pkg/auth/authorizer/OWNERS +++ /dev/null @@ -1 +0,0 @@ -reviewers: diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/BUILD b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/BUILD index 219323e9e..595530237 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/BUILD @@ -29,7 +29,6 @@ go_library( "//pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/settings/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/storage/internalversion:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/clientset.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/clientset.go index 44c675b12..94928b5e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/clientset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package internalclientset import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -246,7 +245,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/doc.go index 22ccee919..01b3d5e0f 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go index 57a67ac3f..f097dbac5 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -71,9 +71,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -83,7 +84,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/register.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/register.go index d91c71e7d..8bb51e622 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/register.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/BUILD b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/BUILD index 97e20c749..46c2682a3 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/BUILD @@ -31,8 +31,6 @@ go_library( "//pkg/apis/scheduling/install:go_default_library", "//pkg/apis/settings/install:go_default_library", "//pkg/apis/storage/install:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/register.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/register.go index 26f60c8d2..6f7d8813a 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/register.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,10 +19,6 @@ limitations under the License. package scheme import ( - os "os" - - announced "k8s.io/apimachinery/pkg/apimachinery/announced" - registered "k8s.io/apimachinery/pkg/apimachinery/registered" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -49,32 +45,29 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) -var Registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) -var GroupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - func init() { v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - Install(GroupFactoryRegistry, Registry, Scheme) + Install(Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - admissionregistration.Install(groupFactoryRegistry, registry, scheme) - core.Install(groupFactoryRegistry, registry, scheme) - apps.Install(groupFactoryRegistry, registry, scheme) - authentication.Install(groupFactoryRegistry, registry, scheme) - authorization.Install(groupFactoryRegistry, registry, scheme) - autoscaling.Install(groupFactoryRegistry, registry, scheme) - batch.Install(groupFactoryRegistry, registry, scheme) - certificates.Install(groupFactoryRegistry, registry, scheme) - events.Install(groupFactoryRegistry, registry, scheme) - extensions.Install(groupFactoryRegistry, registry, scheme) - networking.Install(groupFactoryRegistry, registry, scheme) - policy.Install(groupFactoryRegistry, registry, scheme) - rbac.Install(groupFactoryRegistry, registry, scheme) - scheduling.Install(groupFactoryRegistry, registry, scheme) - settings.Install(groupFactoryRegistry, registry, scheme) - storage.Install(groupFactoryRegistry, registry, scheme) +func Install(scheme *runtime.Scheme) { + admissionregistration.Install(scheme) + core.Install(scheme) + apps.Install(scheme) + authentication.Install(scheme) + authorization.Install(scheme) + autoscaling.Install(scheme) + batch.Install(scheme) + certificates.Install(scheme) + events.Install(scheme) + extensions.Install(scheme) + networking.Install(scheme) + policy.Install(scheme) + rbac.Install(scheme) + scheduling.Install(scheme) + settings.Install(scheme) + storage.Install(scheme) - ExtraInstall(groupFactoryRegistry, registry, scheme) + ExtraInstall(scheme) } diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/register_custom.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/register_custom.go index d54eb1cce..d00f12b9b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/register_custom.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme/register_custom.go @@ -17,13 +17,11 @@ limitations under the License. package scheme import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" componentconfig "k8s.io/kubernetes/pkg/apis/componentconfig/install" ) -func ExtraInstall(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { +func ExtraInstall(scheme *runtime.Scheme) { // componentconfig is an apigroup, but we don't have an API endpoint because its objects are just embedded in ConfigMaps. - componentconfig.Install(groupFactoryRegistry, registry, scheme) + componentconfig.Install(scheme) } diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/admissionregistration_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/admissionregistration_client.go index a8dc6d258..9ecefad4c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/admissionregistration_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -76,17 +76,12 @@ func New(c rest.Interface) *AdmissionregistrationClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("admissionregistration.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("admissionregistration.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("admissionregistration.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_admissionregistration_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_admissionregistration_client.go index 85da63b84..e4ae5c20a 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_admissionregistration_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_initializerconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_initializerconfiguration.go index 6a35f5863..a9b9f8aa6 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_initializerconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeInitializerConfigurations) List(opts v1.ListOptions) (result *admis if label == nil { label = labels.Everything() } - list := &admissionregistration.InitializerConfigurationList{} + list := &admissionregistration.InitializerConfigurationList{ListMeta: obj.(*admissionregistration.InitializerConfigurationList).ListMeta} for _, item := range obj.(*admissionregistration.InitializerConfigurationList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_mutatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_mutatingwebhookconfiguration.go index 0a2591566..626269eab 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeMutatingWebhookConfigurations) List(opts v1.ListOptions) (result *a if label == nil { label = labels.Everything() } - list := &admissionregistration.MutatingWebhookConfigurationList{} + list := &admissionregistration.MutatingWebhookConfigurationList{ListMeta: obj.(*admissionregistration.MutatingWebhookConfigurationList).ListMeta} for _, item := range obj.(*admissionregistration.MutatingWebhookConfigurationList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_validatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_validatingwebhookconfiguration.go index 3d270e3ea..f7e11128d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_validatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/fake/fake_validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeValidatingWebhookConfigurations) List(opts v1.ListOptions) (result if label == nil { label = labels.Everything() } - list := &admissionregistration.ValidatingWebhookConfigurationList{} + list := &admissionregistration.ValidatingWebhookConfigurationList{ListMeta: obj.(*admissionregistration.ValidatingWebhookConfigurationList).ListMeta} for _, item := range obj.(*admissionregistration.ValidatingWebhookConfigurationList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/generated_expansion.go index 2bb32341e..4cc8f66b7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/initializerconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/initializerconfiguration.go index d6e325420..b792b5470 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/initializerconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/mutatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/mutatingwebhookconfiguration.go index 47edb0d36..c35d780fb 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/validatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/validatingwebhookconfiguration.go index e3bf756c7..980d9b5b8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/validatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion/validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/apps_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/apps_client.go index 3aaaf7fd0..abcdc639f 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/apps_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -71,17 +71,12 @@ func New(c rest.Interface) *AppsClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("apps") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("apps")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("apps")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/controllerrevision.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/controllerrevision.go index 9cbb44dc8..33a28c3a3 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_apps_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_apps_client.go index d365ad7bf..de71ebdf7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_apps_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_controllerrevision.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_controllerrevision.go index efff64573..a3e72f239 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_controllerrevision.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *apps.Contro if label == nil { label = labels.Everything() } - list := &apps.ControllerRevisionList{} + list := &apps.ControllerRevisionList{ListMeta: obj.(*apps.ControllerRevisionList).ListMeta} for _, item := range obj.(*apps.ControllerRevisionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_statefulset.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_statefulset.go index 4ae621686..bdf8dd412 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_statefulset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake/fake_statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -63,7 +63,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *apps.StatefulSetLi if label == nil { label = labels.Everything() } - list := &apps.StatefulSetList{} + list := &apps.StatefulSetList{ListMeta: obj.(*apps.StatefulSetList).ListMeta} for _, item := range obj.(*apps.StatefulSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/generated_expansion.go index f77de9fe0..9bfab8576 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/statefulset.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/statefulset.go index 42a638cca..4d1e5fa16 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/statefulset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/authentication_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/authentication_client.go index 29de235c1..086b38b46 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/authentication_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *AuthenticationClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("authentication.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("authentication.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("authentication.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/fake_authentication_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/fake_authentication_client.go index 486b32a62..8328a297f 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/fake_authentication_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/fake_authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/fake_tokenreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/fake_tokenreview.go index c7774ac12..57747669a 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/fake_tokenreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake/fake_tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/generated_expansion.go index 4a52863e4..1b59c8431 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/tokenreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/tokenreview.go index c7f71bdaf..04939f148 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/tokenreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/authorization_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/authorization_client.go index 3207f0e0e..f97f54644 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/authorization_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -81,17 +81,12 @@ func New(c rest.Interface) *AuthorizationClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("authorization.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("authorization.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("authorization.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_authorization_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_authorization_client.go index c9f44dbe7..004beb512 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_authorization_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_localsubjectaccessreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_localsubjectaccessreview.go index 81dd8d0ad..598b53cd9 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_localsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_selfsubjectaccessreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_selfsubjectaccessreview.go index 80c46f706..cf65fabb5 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_selfsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_selfsubjectrulesreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_selfsubjectrulesreview.go index 3c332745a..39eefcf14 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_selfsubjectrulesreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_subjectaccessreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_subjectaccessreview.go index a3c76e257..b51347ef6 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_subjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake/fake_subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/generated_expansion.go index 4a52863e4..1b59c8431 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/localsubjectaccessreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/localsubjectaccessreview.go index db51f0ac1..b98f8b0a7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/localsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/selfsubjectaccessreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/selfsubjectaccessreview.go index ff7bc593a..978ca20c1 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/selfsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/selfsubjectrulesreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/selfsubjectrulesreview.go index 211f76605..1a1d5701b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/selfsubjectrulesreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/subjectaccessreview.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/subjectaccessreview.go index d2514f2b2..f442b59a1 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/subjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/autoscaling_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/autoscaling_client.go index c555299ad..e00bc9191 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/autoscaling_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *AutoscalingClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("autoscaling") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("autoscaling")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("autoscaling")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/fake_autoscaling_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/fake_autoscaling_client.go index b107bc783..cfb590b39 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/fake_autoscaling_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/fake_autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/fake_horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/fake_horizontalpodautoscaler.go index 52475e117..c35e9c937 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/fake_horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake/fake_horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *autosc if label == nil { label = labels.Everything() } - list := &autoscaling.HorizontalPodAutoscalerList{} + list := &autoscaling.HorizontalPodAutoscalerList{ListMeta: obj.(*autoscaling.HorizontalPodAutoscalerList).ListMeta} for _, item := range obj.(*autoscaling.HorizontalPodAutoscalerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/generated_expansion.go index d7d647db4..f00428522 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/horizontalpodautoscaler.go index 3bc0cc92d..39ec41254 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/batch_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/batch_client.go index b20b4ba5f..ebfcb85a2 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/batch_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -71,17 +71,12 @@ func New(c rest.Interface) *BatchClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("batch") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("batch")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("batch")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/cronjob.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/cronjob.go index c2e9d5162..72cb6cffa 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/cronjob.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_batch_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_batch_client.go index 56af4fc2b..2e6a3b756 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_batch_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_cronjob.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_cronjob.go index 83241b224..98c511531 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_cronjob.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeCronJobs) List(opts v1.ListOptions) (result *batch.CronJobList, err if label == nil { label = labels.Everything() } - list := &batch.CronJobList{} + list := &batch.CronJobList{ListMeta: obj.(*batch.CronJobList).ListMeta} for _, item := range obj.(*batch.CronJobList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_job.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_job.go index 7522f140d..a96541eb7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_job.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake/fake_job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeJobs) List(opts v1.ListOptions) (result *batch.JobList, err error) if label == nil { label = labels.Everything() } - list := &batch.JobList{} + list := &batch.JobList{ListMeta: obj.(*batch.JobList).ListMeta} for _, item := range obj.(*batch.JobList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/generated_expansion.go index d1cd2076d..e8f42d1c5 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/job.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/job.go index b9f96aaed..e9f9dc545 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/job.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/certificates_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/certificates_client.go index 7399b1b67..852a42975 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/certificates_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/certificates_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *CertificatesClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("certificates.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("certificates.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("certificates.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/certificatesigningrequest.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/certificatesigningrequest.go index 338b15486..8a5b7b380 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/certificatesigningrequest.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/fake_certificates_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/fake_certificates_client.go index 3fc4b767c..eac0f91ce 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/fake_certificates_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/fake_certificates_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/fake_certificatesigningrequest.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/fake_certificatesigningrequest.go index b7c658b09..1fa45aeca 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/fake_certificatesigningrequest.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake/fake_certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeCertificateSigningRequests) List(opts v1.ListOptions) (result *cert if label == nil { label = labels.Everything() } - list := &certificates.CertificateSigningRequestList{} + list := &certificates.CertificateSigningRequestList{ListMeta: obj.(*certificates.CertificateSigningRequestList).ListMeta} for _, item := range obj.(*certificates.CertificateSigningRequestList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/generated_expansion.go index 4a52863e4..1b59c8431 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/componentstatus.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/componentstatus.go index c9d7c6ae4..07b75daab 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/componentstatus.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/configmap.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/configmap.go index c118ccc90..af1fc1fa1 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/configmap.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/core_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/core_client.go index d7129f33b..6ba341b91 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/core_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/core_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -141,17 +141,12 @@ func New(c rest.Interface) *CoreClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("") - if err != nil { - return err - } - config.APIPath = "/api" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/endpoints.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/endpoints.go index 6fe53fad1..acb3fd21e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/endpoints.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/event.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/event.go index de8d38197..16dbe6596 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/event.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_componentstatus.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_componentstatus.go index 9c0db3947..21201c52b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_componentstatus.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeComponentStatuses) List(opts v1.ListOptions) (result *core.Componen if label == nil { label = labels.Everything() } - list := &core.ComponentStatusList{} + list := &core.ComponentStatusList{ListMeta: obj.(*core.ComponentStatusList).ListMeta} for _, item := range obj.(*core.ComponentStatusList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_configmap.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_configmap.go index 113b7a9e8..f9152053a 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_configmap.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeConfigMaps) List(opts v1.ListOptions) (result *core.ConfigMapList, if label == nil { label = labels.Everything() } - list := &core.ConfigMapList{} + list := &core.ConfigMapList{ListMeta: obj.(*core.ConfigMapList).ListMeta} for _, item := range obj.(*core.ConfigMapList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_core_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_core_client.go index d9516c263..657b72349 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_core_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_core_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_endpoints.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_endpoints.go index 01ff8a7b4..8feff7919 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_endpoints.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeEndpoints) List(opts v1.ListOptions) (result *core.EndpointsList, e if label == nil { label = labels.Everything() } - list := &core.EndpointsList{} + list := &core.EndpointsList{ListMeta: obj.(*core.EndpointsList).ListMeta} for _, item := range obj.(*core.EndpointsList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_event.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_event.go index af69f5944..6f9870010 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_event.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeEvents) List(opts v1.ListOptions) (result *core.EventList, err erro if label == nil { label = labels.Everything() } - list := &core.EventList{} + list := &core.EventList{ListMeta: obj.(*core.EventList).ListMeta} for _, item := range obj.(*core.EventList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_limitrange.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_limitrange.go index 37fd7367e..f6c46cd78 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_limitrange.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeLimitRanges) List(opts v1.ListOptions) (result *core.LimitRangeList if label == nil { label = labels.Everything() } - list := &core.LimitRangeList{} + list := &core.LimitRangeList{ListMeta: obj.(*core.LimitRangeList).ListMeta} for _, item := range obj.(*core.LimitRangeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_namespace.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_namespace.go index 5186339d4..ef5e1cd41 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_namespace.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeNamespaces) List(opts v1.ListOptions) (result *core.NamespaceList, if label == nil { label = labels.Everything() } - list := &core.NamespaceList{} + list := &core.NamespaceList{ListMeta: obj.(*core.NamespaceList).ListMeta} for _, item := range obj.(*core.NamespaceList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_node.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_node.go index 59d304c6b..24c3a4bf0 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_node.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeNodes) List(opts v1.ListOptions) (result *core.NodeList, err error) if label == nil { label = labels.Everything() } - list := &core.NodeList{} + list := &core.NodeList{ListMeta: obj.(*core.NodeList).ListMeta} for _, item := range obj.(*core.NodeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_persistentvolume.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_persistentvolume.go index 973026c69..619a06aa4 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_persistentvolume.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePersistentVolumes) List(opts v1.ListOptions) (result *core.Persiste if label == nil { label = labels.Everything() } - list := &core.PersistentVolumeList{} + list := &core.PersistentVolumeList{ListMeta: obj.(*core.PersistentVolumeList).ListMeta} for _, item := range obj.(*core.PersistentVolumeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_persistentvolumeclaim.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_persistentvolumeclaim.go index 68f4f50ba..f5f4ad94a 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_persistentvolumeclaim.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePersistentVolumeClaims) List(opts v1.ListOptions) (result *core.Per if label == nil { label = labels.Everything() } - list := &core.PersistentVolumeClaimList{} + list := &core.PersistentVolumeClaimList{ListMeta: obj.(*core.PersistentVolumeClaimList).ListMeta} for _, item := range obj.(*core.PersistentVolumeClaimList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_pod.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_pod.go index 849a0690a..58b1b14ac 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_pod.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePods) List(opts v1.ListOptions) (result *core.PodList, err error) { if label == nil { label = labels.Everything() } - list := &core.PodList{} + list := &core.PodList{ListMeta: obj.(*core.PodList).ListMeta} for _, item := range obj.(*core.PodList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_podtemplate.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_podtemplate.go index 986e9dd59..5e9e4bd89 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_podtemplate.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePodTemplates) List(opts v1.ListOptions) (result *core.PodTemplateLi if label == nil { label = labels.Everything() } - list := &core.PodTemplateList{} + list := &core.PodTemplateList{ListMeta: obj.(*core.PodTemplateList).ListMeta} for _, item := range obj.(*core.PodTemplateList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_replicationcontroller.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_replicationcontroller.go index 6d1f55efd..9850d1091 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_replicationcontroller.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -63,7 +63,7 @@ func (c *FakeReplicationControllers) List(opts v1.ListOptions) (result *core.Rep if label == nil { label = labels.Everything() } - list := &core.ReplicationControllerList{} + list := &core.ReplicationControllerList{ListMeta: obj.(*core.ReplicationControllerList).ListMeta} for _, item := range obj.(*core.ReplicationControllerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_resourcequota.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_resourcequota.go index b00d4cdc3..211302b73 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_resourcequota.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeResourceQuotas) List(opts v1.ListOptions) (result *core.ResourceQuo if label == nil { label = labels.Everything() } - list := &core.ResourceQuotaList{} + list := &core.ResourceQuotaList{ListMeta: obj.(*core.ResourceQuotaList).ListMeta} for _, item := range obj.(*core.ResourceQuotaList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_secret.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_secret.go index 25d211652..4b374e663 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_secret.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeSecrets) List(opts v1.ListOptions) (result *core.SecretList, err er if label == nil { label = labels.Everything() } - list := &core.SecretList{} + list := &core.SecretList{ListMeta: obj.(*core.SecretList).ListMeta} for _, item := range obj.(*core.SecretList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_service.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_service.go index 76d8924e7..26c7127f0 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_service.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeServices) List(opts v1.ListOptions) (result *core.ServiceList, err if label == nil { label = labels.Everything() } - list := &core.ServiceList{} + list := &core.ServiceList{ListMeta: obj.(*core.ServiceList).ListMeta} for _, item := range obj.(*core.ServiceList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_serviceaccount.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_serviceaccount.go index 06ab82bcb..7c42f9d4a 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_serviceaccount.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake/fake_serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeServiceAccounts) List(opts v1.ListOptions) (result *core.ServiceAcc if label == nil { label = labels.Everything() } - list := &core.ServiceAccountList{} + list := &core.ServiceAccountList{ListMeta: obj.(*core.ServiceAccountList).ListMeta} for _, item := range obj.(*core.ServiceAccountList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/generated_expansion.go index 1b30a3590..641c92260 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/limitrange.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/limitrange.go index 4968e5a47..d16b9b5ae 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/limitrange.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/namespace.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/namespace.go index 032c315f2..5a0f413d3 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/namespace.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/node.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/node.go index 33a14cdcc..515663c4d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/node.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/persistentvolume.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/persistentvolume.go index 194482fa9..fb717d8a3 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/persistentvolume.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/persistentvolumeclaim.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/persistentvolumeclaim.go index 472e27276..a0111d67c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/persistentvolumeclaim.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/pod.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/pod.go index 6d76794d4..b73b5b465 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/pod.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/podtemplate.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/podtemplate.go index a23f90448..a9ef5caec 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/podtemplate.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/replicationcontroller.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/replicationcontroller.go index 8d5012cdc..225f020fe 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/replicationcontroller.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/resourcequota.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/resourcequota.go index f0f86fc0d..990451072 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/resourcequota.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/secret.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/secret.go index 3d99463bc..c3fe44d5d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/secret.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/service.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/service.go index 86c160b28..e05f53376 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/service.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/serviceaccount.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/serviceaccount.go index a19299e32..c2b6012c4 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/serviceaccount.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/events_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/events_client.go index 5c4665104..9eb8b7c52 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/events_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/events_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -61,17 +61,12 @@ func New(c rest.Interface) *EventsClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("events.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("events.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("events.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake/fake_events_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake/fake_events_client.go index ff2505b45..b538a24ff 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake/fake_events_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake/fake_events_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/generated_expansion.go index 4a52863e4..1b59c8431 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/BUILD b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/BUILD index 85d27b165..43401c363 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/BUILD @@ -15,7 +15,6 @@ go_library( "extensions_client.go", "generated_expansion.go", "ingress.go", - "podsecuritypolicy.go", "replicaset.go", ], importpath = "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion", diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/daemonset.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/daemonset.go index 3e0be5ff1..66fd1af05 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/daemonset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/deployment.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/deployment.go index b7cc4d918..074ea47f7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/deployment.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/extensions_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/extensions_client.go index e2a757cc9..43ea79be3 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/extensions_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/extensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -28,7 +28,6 @@ type ExtensionsInterface interface { DaemonSetsGetter DeploymentsGetter IngressesGetter - PodSecurityPoliciesGetter ReplicaSetsGetter } @@ -49,10 +48,6 @@ func (c *ExtensionsClient) Ingresses(namespace string) IngressInterface { return newIngresses(c, namespace) } -func (c *ExtensionsClient) PodSecurityPolicies() PodSecurityPolicyInterface { - return newPodSecurityPolicies(c) -} - func (c *ExtensionsClient) ReplicaSets(namespace string) ReplicaSetInterface { return newReplicaSets(c, namespace) } @@ -86,17 +81,12 @@ func New(c rest.Interface) *ExtensionsClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("extensions") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("extensions")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("extensions")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/BUILD b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/BUILD index 91755daa6..65a03fb36 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/BUILD @@ -14,7 +14,6 @@ go_library( "fake_deployment_expansion.go", "fake_extensions_client.go", "fake_ingress.go", - "fake_podsecuritypolicy.go", "fake_replicaset.go", ], importpath = "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake", diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_daemonset.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_daemonset.go index 26867e758..a8f9cf603 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_daemonset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *extensions.DaemonSet if label == nil { label = labels.Everything() } - list := &extensions.DaemonSetList{} + list := &extensions.DaemonSetList{ListMeta: obj.(*extensions.DaemonSetList).ListMeta} for _, item := range obj.(*extensions.DaemonSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_deployment.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_deployment.go index 0789c44c4..3545ac377 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_deployment.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -63,7 +63,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *extensions.Deployme if label == nil { label = labels.Everything() } - list := &extensions.DeploymentList{} + list := &extensions.DeploymentList{ListMeta: obj.(*extensions.DeploymentList).ListMeta} for _, item := range obj.(*extensions.DeploymentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_extensions_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_extensions_client.go index 39923e840..1336d8558 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_extensions_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_extensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -40,10 +40,6 @@ func (c *FakeExtensions) Ingresses(namespace string) internalversion.IngressInte return &FakeIngresses{c, namespace} } -func (c *FakeExtensions) PodSecurityPolicies() internalversion.PodSecurityPolicyInterface { - return &FakePodSecurityPolicies{c} -} - func (c *FakeExtensions) ReplicaSets(namespace string) internalversion.ReplicaSetInterface { return &FakeReplicaSets{c, namespace} } diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_ingress.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_ingress.go index a95fae532..480ba7b62 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_ingress.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeIngresses) List(opts v1.ListOptions) (result *extensions.IngressLis if label == nil { label = labels.Everything() } - list := &extensions.IngressList{} + list := &extensions.IngressList{ListMeta: obj.(*extensions.IngressList).ListMeta} for _, item := range obj.(*extensions.IngressList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_podsecuritypolicy.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_podsecuritypolicy.go deleted file mode 100644 index 7c7248295..000000000 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_podsecuritypolicy.go +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright 2018 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. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - schema "k8s.io/apimachinery/pkg/runtime/schema" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" - extensions "k8s.io/kubernetes/pkg/apis/extensions" -) - -// FakePodSecurityPolicies implements PodSecurityPolicyInterface -type FakePodSecurityPolicies struct { - Fake *FakeExtensions -} - -var podsecuritypoliciesResource = schema.GroupVersionResource{Group: "extensions", Version: "", Resource: "podsecuritypolicies"} - -var podsecuritypoliciesKind = schema.GroupVersionKind{Group: "extensions", Version: "", Kind: "PodSecurityPolicy"} - -// Get takes name of the podSecurityPolicy, and returns the corresponding podSecurityPolicy object, and an error if there is any. -func (c *FakePodSecurityPolicies) Get(name string, options v1.GetOptions) (result *extensions.PodSecurityPolicy, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootGetAction(podsecuritypoliciesResource, name), &extensions.PodSecurityPolicy{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.PodSecurityPolicy), err -} - -// List takes label and field selectors, and returns the list of PodSecurityPolicies that match those selectors. -func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *extensions.PodSecurityPolicyList, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootListAction(podsecuritypoliciesResource, podsecuritypoliciesKind, opts), &extensions.PodSecurityPolicyList{}) - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &extensions.PodSecurityPolicyList{} - for _, item := range obj.(*extensions.PodSecurityPolicyList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested podSecurityPolicies. -func (c *FakePodSecurityPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewRootWatchAction(podsecuritypoliciesResource, opts)) -} - -// Create takes the representation of a podSecurityPolicy and creates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any. -func (c *FakePodSecurityPolicies) Create(podSecurityPolicy *extensions.PodSecurityPolicy) (result *extensions.PodSecurityPolicy, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootCreateAction(podsecuritypoliciesResource, podSecurityPolicy), &extensions.PodSecurityPolicy{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.PodSecurityPolicy), err -} - -// Update takes the representation of a podSecurityPolicy and updates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any. -func (c *FakePodSecurityPolicies) Update(podSecurityPolicy *extensions.PodSecurityPolicy) (result *extensions.PodSecurityPolicy, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootUpdateAction(podsecuritypoliciesResource, podSecurityPolicy), &extensions.PodSecurityPolicy{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.PodSecurityPolicy), err -} - -// Delete takes name of the podSecurityPolicy and deletes it. Returns an error if one occurs. -func (c *FakePodSecurityPolicies) Delete(name string, options *v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewRootDeleteAction(podsecuritypoliciesResource, name), &extensions.PodSecurityPolicy{}) - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakePodSecurityPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewRootDeleteCollectionAction(podsecuritypoliciesResource, listOptions) - - _, err := c.Fake.Invokes(action, &extensions.PodSecurityPolicyList{}) - return err -} - -// Patch applies the patch and returns the patched podSecurityPolicy. -func (c *FakePodSecurityPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *extensions.PodSecurityPolicy, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(podsecuritypoliciesResource, name, data, subresources...), &extensions.PodSecurityPolicy{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.PodSecurityPolicy), err -} diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_replicaset.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_replicaset.go index 6bf71e559..6018c8b2a 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_replicaset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake/fake_replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -63,7 +63,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *extensions.ReplicaS if label == nil { label = labels.Everything() } - list := &extensions.ReplicaSetList{} + list := &extensions.ReplicaSetList{ListMeta: obj.(*extensions.ReplicaSetList).ListMeta} for _, item := range obj.(*extensions.ReplicaSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/generated_expansion.go index 85e06f402..2560f4a32 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,6 +22,4 @@ type DaemonSetExpansion interface{} type IngressExpansion interface{} -type PodSecurityPolicyExpansion interface{} - type ReplicaSetExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/ingress.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/ingress.go index f234f12cb..bbe7577cc 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/ingress.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/podsecuritypolicy.go deleted file mode 100644 index 19a8843a7..000000000 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/podsecuritypolicy.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2018 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. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package internalversion - -import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" - extensions "k8s.io/kubernetes/pkg/apis/extensions" - scheme "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme" -) - -// PodSecurityPoliciesGetter has a method to return a PodSecurityPolicyInterface. -// A group's client should implement this interface. -type PodSecurityPoliciesGetter interface { - PodSecurityPolicies() PodSecurityPolicyInterface -} - -// PodSecurityPolicyInterface has methods to work with PodSecurityPolicy resources. -type PodSecurityPolicyInterface interface { - Create(*extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error) - Update(*extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error) - Delete(name string, options *v1.DeleteOptions) error - DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error - Get(name string, options v1.GetOptions) (*extensions.PodSecurityPolicy, error) - List(opts v1.ListOptions) (*extensions.PodSecurityPolicyList, error) - Watch(opts v1.ListOptions) (watch.Interface, error) - Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *extensions.PodSecurityPolicy, err error) - PodSecurityPolicyExpansion -} - -// podSecurityPolicies implements PodSecurityPolicyInterface -type podSecurityPolicies struct { - client rest.Interface -} - -// newPodSecurityPolicies returns a PodSecurityPolicies -func newPodSecurityPolicies(c *ExtensionsClient) *podSecurityPolicies { - return &podSecurityPolicies{ - client: c.RESTClient(), - } -} - -// Get takes name of the podSecurityPolicy, and returns the corresponding podSecurityPolicy object, and an error if there is any. -func (c *podSecurityPolicies) Get(name string, options v1.GetOptions) (result *extensions.PodSecurityPolicy, err error) { - result = &extensions.PodSecurityPolicy{} - err = c.client.Get(). - Resource("podsecuritypolicies"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of PodSecurityPolicies that match those selectors. -func (c *podSecurityPolicies) List(opts v1.ListOptions) (result *extensions.PodSecurityPolicyList, err error) { - result = &extensions.PodSecurityPolicyList{} - err = c.client.Get(). - Resource("podsecuritypolicies"). - VersionedParams(&opts, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested podSecurityPolicies. -func (c *podSecurityPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) { - opts.Watch = true - return c.client.Get(). - Resource("podsecuritypolicies"). - VersionedParams(&opts, scheme.ParameterCodec). - Watch() -} - -// Create takes the representation of a podSecurityPolicy and creates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any. -func (c *podSecurityPolicies) Create(podSecurityPolicy *extensions.PodSecurityPolicy) (result *extensions.PodSecurityPolicy, err error) { - result = &extensions.PodSecurityPolicy{} - err = c.client.Post(). - Resource("podsecuritypolicies"). - Body(podSecurityPolicy). - Do(). - Into(result) - return -} - -// Update takes the representation of a podSecurityPolicy and updates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any. -func (c *podSecurityPolicies) Update(podSecurityPolicy *extensions.PodSecurityPolicy) (result *extensions.PodSecurityPolicy, err error) { - result = &extensions.PodSecurityPolicy{} - err = c.client.Put(). - Resource("podsecuritypolicies"). - Name(podSecurityPolicy.Name). - Body(podSecurityPolicy). - Do(). - Into(result) - return -} - -// Delete takes name of the podSecurityPolicy and deletes it. Returns an error if one occurs. -func (c *podSecurityPolicies) Delete(name string, options *v1.DeleteOptions) error { - return c.client.Delete(). - Resource("podsecuritypolicies"). - Name(name). - Body(options). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *podSecurityPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - return c.client.Delete(). - Resource("podsecuritypolicies"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Body(options). - Do(). - Error() -} - -// Patch applies the patch and returns the patched podSecurityPolicy. -func (c *podSecurityPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *extensions.PodSecurityPolicy, err error) { - result = &extensions.PodSecurityPolicy{} - err = c.client.Patch(pt). - Resource("podsecuritypolicies"). - SubResource(subresources...). - Name(name). - Body(data). - Do(). - Into(result) - return -} diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/replicaset.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/replicaset.go index 02e61d624..b2263cb09 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/replicaset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/fake_networking_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/fake_networking_client.go index 133b8976c..7f083460e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/fake_networking_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/fake_networking_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/fake_networkpolicy.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/fake_networkpolicy.go index 9d6ccdf6c..8dcbc30aa 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/fake_networkpolicy.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/fake/fake_networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeNetworkPolicies) List(opts v1.ListOptions) (result *networking.Netw if label == nil { label = labels.Everything() } - list := &networking.NetworkPolicyList{} + list := &networking.NetworkPolicyList{ListMeta: obj.(*networking.NetworkPolicyList).ListMeta} for _, item := range obj.(*networking.NetworkPolicyList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/generated_expansion.go index 045b840cc..8406486f4 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/networking_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/networking_client.go index 344eb2b90..1d2f9ab0e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/networking_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/networking_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *NetworkingClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("networking.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("networking.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("networking.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/networkpolicy.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/networkpolicy.go index 838caf2d4..6a0cdbc3b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/networkpolicy.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion/networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/BUILD b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/BUILD index 517a1c0bb..ec825bb7c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/BUILD @@ -13,6 +13,7 @@ go_library( "eviction_expansion.go", "generated_expansion.go", "poddisruptionbudget.go", + "podsecuritypolicy.go", "policy_client.go", ], importpath = "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion", diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/eviction.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/eviction.go index 49058cf8e..37297cbb8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/eviction.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/eviction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/BUILD b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/BUILD index 7842be40a..363fe7f04 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/BUILD @@ -12,6 +12,7 @@ go_library( "fake_eviction.go", "fake_eviction_expansion.go", "fake_poddisruptionbudget.go", + "fake_podsecuritypolicy.go", "fake_policy_client.go", ], importpath = "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake", diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_eviction.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_eviction.go index c6b6a946b..ef12b0d80 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_eviction.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_eviction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_poddisruptionbudget.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_poddisruptionbudget.go index 3bcdd95fb..00e2e91ba 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_poddisruptionbudget.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePodDisruptionBudgets) List(opts v1.ListOptions) (result *policy.Pod if label == nil { label = labels.Everything() } - list := &policy.PodDisruptionBudgetList{} + list := &policy.PodDisruptionBudgetList{ListMeta: obj.(*policy.PodDisruptionBudgetList).ListMeta} for _, item := range obj.(*policy.PodDisruptionBudgetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_podsecuritypolicy.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_podsecuritypolicy.go new file mode 100644 index 000000000..e5ce26b0a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_podsecuritypolicy.go @@ -0,0 +1,120 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + policy "k8s.io/kubernetes/pkg/apis/policy" +) + +// FakePodSecurityPolicies implements PodSecurityPolicyInterface +type FakePodSecurityPolicies struct { + Fake *FakePolicy +} + +var podsecuritypoliciesResource = schema.GroupVersionResource{Group: "policy", Version: "", Resource: "podsecuritypolicies"} + +var podsecuritypoliciesKind = schema.GroupVersionKind{Group: "policy", Version: "", Kind: "PodSecurityPolicy"} + +// Get takes name of the podSecurityPolicy, and returns the corresponding podSecurityPolicy object, and an error if there is any. +func (c *FakePodSecurityPolicies) Get(name string, options v1.GetOptions) (result *policy.PodSecurityPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(podsecuritypoliciesResource, name), &policy.PodSecurityPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*policy.PodSecurityPolicy), err +} + +// List takes label and field selectors, and returns the list of PodSecurityPolicies that match those selectors. +func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *policy.PodSecurityPolicyList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(podsecuritypoliciesResource, podsecuritypoliciesKind, opts), &policy.PodSecurityPolicyList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &policy.PodSecurityPolicyList{ListMeta: obj.(*policy.PodSecurityPolicyList).ListMeta} + for _, item := range obj.(*policy.PodSecurityPolicyList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested podSecurityPolicies. +func (c *FakePodSecurityPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(podsecuritypoliciesResource, opts)) +} + +// Create takes the representation of a podSecurityPolicy and creates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any. +func (c *FakePodSecurityPolicies) Create(podSecurityPolicy *policy.PodSecurityPolicy) (result *policy.PodSecurityPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(podsecuritypoliciesResource, podSecurityPolicy), &policy.PodSecurityPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*policy.PodSecurityPolicy), err +} + +// Update takes the representation of a podSecurityPolicy and updates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any. +func (c *FakePodSecurityPolicies) Update(podSecurityPolicy *policy.PodSecurityPolicy) (result *policy.PodSecurityPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(podsecuritypoliciesResource, podSecurityPolicy), &policy.PodSecurityPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*policy.PodSecurityPolicy), err +} + +// Delete takes name of the podSecurityPolicy and deletes it. Returns an error if one occurs. +func (c *FakePodSecurityPolicies) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(podsecuritypoliciesResource, name), &policy.PodSecurityPolicy{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakePodSecurityPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(podsecuritypoliciesResource, listOptions) + + _, err := c.Fake.Invokes(action, &policy.PodSecurityPolicyList{}) + return err +} + +// Patch applies the patch and returns the patched podSecurityPolicy. +func (c *FakePodSecurityPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *policy.PodSecurityPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(podsecuritypoliciesResource, name, data, subresources...), &policy.PodSecurityPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*policy.PodSecurityPolicy), err +} diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_policy_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_policy_client.go index 351530d9a..91a0f7ca3 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_policy_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_policy_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -36,6 +36,10 @@ func (c *FakePolicy) PodDisruptionBudgets(namespace string) internalversion.PodD return &FakePodDisruptionBudgets{c, namespace} } +func (c *FakePolicy) PodSecurityPolicies() internalversion.PodSecurityPolicyInterface { + return &FakePodSecurityPolicies{c} +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakePolicy) RESTClient() rest.Interface { diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/generated_expansion.go index 2a9f87109..a3ff5ba02 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,3 +19,5 @@ limitations under the License. package internalversion type PodDisruptionBudgetExpansion interface{} + +type PodSecurityPolicyExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/poddisruptionbudget.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/poddisruptionbudget.go index 6d3898a84..7e7abfcb2 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/poddisruptionbudget.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/podsecuritypolicy.go new file mode 100644 index 000000000..17c162fa4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/podsecuritypolicy.go @@ -0,0 +1,147 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package internalversion + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + policy "k8s.io/kubernetes/pkg/apis/policy" + scheme "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme" +) + +// PodSecurityPoliciesGetter has a method to return a PodSecurityPolicyInterface. +// A group's client should implement this interface. +type PodSecurityPoliciesGetter interface { + PodSecurityPolicies() PodSecurityPolicyInterface +} + +// PodSecurityPolicyInterface has methods to work with PodSecurityPolicy resources. +type PodSecurityPolicyInterface interface { + Create(*policy.PodSecurityPolicy) (*policy.PodSecurityPolicy, error) + Update(*policy.PodSecurityPolicy) (*policy.PodSecurityPolicy, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*policy.PodSecurityPolicy, error) + List(opts v1.ListOptions) (*policy.PodSecurityPolicyList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *policy.PodSecurityPolicy, err error) + PodSecurityPolicyExpansion +} + +// podSecurityPolicies implements PodSecurityPolicyInterface +type podSecurityPolicies struct { + client rest.Interface +} + +// newPodSecurityPolicies returns a PodSecurityPolicies +func newPodSecurityPolicies(c *PolicyClient) *podSecurityPolicies { + return &podSecurityPolicies{ + client: c.RESTClient(), + } +} + +// Get takes name of the podSecurityPolicy, and returns the corresponding podSecurityPolicy object, and an error if there is any. +func (c *podSecurityPolicies) Get(name string, options v1.GetOptions) (result *policy.PodSecurityPolicy, err error) { + result = &policy.PodSecurityPolicy{} + err = c.client.Get(). + Resource("podsecuritypolicies"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of PodSecurityPolicies that match those selectors. +func (c *podSecurityPolicies) List(opts v1.ListOptions) (result *policy.PodSecurityPolicyList, err error) { + result = &policy.PodSecurityPolicyList{} + err = c.client.Get(). + Resource("podsecuritypolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested podSecurityPolicies. +func (c *podSecurityPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Resource("podsecuritypolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a podSecurityPolicy and creates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any. +func (c *podSecurityPolicies) Create(podSecurityPolicy *policy.PodSecurityPolicy) (result *policy.PodSecurityPolicy, err error) { + result = &policy.PodSecurityPolicy{} + err = c.client.Post(). + Resource("podsecuritypolicies"). + Body(podSecurityPolicy). + Do(). + Into(result) + return +} + +// Update takes the representation of a podSecurityPolicy and updates it. Returns the server's representation of the podSecurityPolicy, and an error, if there is any. +func (c *podSecurityPolicies) Update(podSecurityPolicy *policy.PodSecurityPolicy) (result *policy.PodSecurityPolicy, err error) { + result = &policy.PodSecurityPolicy{} + err = c.client.Put(). + Resource("podsecuritypolicies"). + Name(podSecurityPolicy.Name). + Body(podSecurityPolicy). + Do(). + Into(result) + return +} + +// Delete takes name of the podSecurityPolicy and deletes it. Returns an error if one occurs. +func (c *podSecurityPolicies) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("podsecuritypolicies"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *podSecurityPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Resource("podsecuritypolicies"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched podSecurityPolicy. +func (c *podSecurityPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *policy.PodSecurityPolicy, err error) { + result = &policy.PodSecurityPolicy{} + err = c.client.Patch(pt). + Resource("podsecuritypolicies"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/policy_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/policy_client.go index 025e74878..8040244dd 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/policy_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/policy_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -27,6 +27,7 @@ type PolicyInterface interface { RESTClient() rest.Interface EvictionsGetter PodDisruptionBudgetsGetter + PodSecurityPoliciesGetter } // PolicyClient is used to interact with features provided by the policy group. @@ -42,6 +43,10 @@ func (c *PolicyClient) PodDisruptionBudgets(namespace string) PodDisruptionBudge return newPodDisruptionBudgets(c, namespace) } +func (c *PolicyClient) PodSecurityPolicies() PodSecurityPolicyInterface { + return newPodSecurityPolicies(c) +} + // NewForConfig creates a new PolicyClient for the given config. func NewForConfig(c *rest.Config) (*PolicyClient, error) { config := *c @@ -71,17 +76,12 @@ func New(c rest.Interface) *PolicyClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("policy") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("policy")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("policy")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/clusterrole.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/clusterrole.go index 1f230fd93..985e90f16 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/clusterrole.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/clusterrolebinding.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/clusterrolebinding.go index d05021a60..01dcf2275 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_clusterrole.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_clusterrole.go index acbbc092d..41dcfe9fa 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_clusterrole.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *rbac.ClusterRoleLi if label == nil { label = labels.Everything() } - list := &rbac.ClusterRoleList{} + list := &rbac.ClusterRoleList{ListMeta: obj.(*rbac.ClusterRoleList).ListMeta} for _, item := range obj.(*rbac.ClusterRoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_clusterrolebinding.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_clusterrolebinding.go index a282140fe..9e2edc2e7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *rbac.Cluste if label == nil { label = labels.Everything() } - list := &rbac.ClusterRoleBindingList{} + list := &rbac.ClusterRoleBindingList{ListMeta: obj.(*rbac.ClusterRoleBindingList).ListMeta} for _, item := range obj.(*rbac.ClusterRoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_rbac_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_rbac_client.go index c948ee166..2827f14dc 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_rbac_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_role.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_role.go index b3fa38f56..0a28fd28f 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_role.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *rbac.RoleList, err error) if label == nil { label = labels.Everything() } - list := &rbac.RoleList{} + list := &rbac.RoleList{ListMeta: obj.(*rbac.RoleList).ListMeta} for _, item := range obj.(*rbac.RoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_rolebinding.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_rolebinding.go index e7644fbfa..a48c92a85 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_rolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake/fake_rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *rbac.RoleBindingLi if label == nil { label = labels.Everything() } - list := &rbac.RoleBindingList{} + list := &rbac.RoleBindingList{ListMeta: obj.(*rbac.RoleBindingList).ListMeta} for _, item := range obj.(*rbac.RoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/generated_expansion.go index 18e1320f7..bd6d9237d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/rbac_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/rbac_client.go index e9d90952f..269fe8791 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/rbac_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -81,17 +81,12 @@ func New(c rest.Interface) *RbacClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("rbac.authorization.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("rbac.authorization.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("rbac.authorization.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/role.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/role.go index e1270b727..7272550e8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/role.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/rolebinding.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/rolebinding.go index f17780ff1..bed5dcdf9 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/rolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/fake_priorityclass.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/fake_priorityclass.go index 3b6f2a60a..710b2cb61 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/fake_priorityclass.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/fake_priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *scheduling.Prio if label == nil { label = labels.Everything() } - list := &scheduling.PriorityClassList{} + list := &scheduling.PriorityClassList{ListMeta: obj.(*scheduling.PriorityClassList).ListMeta} for _, item := range obj.(*scheduling.PriorityClassList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/fake_scheduling_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/fake_scheduling_client.go index c2c96923b..0bbb4abfd 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/fake_scheduling_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/fake/fake_scheduling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/generated_expansion.go index 1f369def4..df00c75e8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/priorityclass.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/priorityclass.go index 8a787cfe8..8d5f992da 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/priorityclass.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/scheduling_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/scheduling_client.go index 4ed579879..c30bb6f4d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/scheduling_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion/scheduling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *SchedulingClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("scheduling.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("scheduling.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("scheduling.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/fake_podpreset.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/fake_podpreset.go index 3b8b2c82e..1bf4b5be4 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/fake_podpreset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/fake_podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePodPresets) List(opts v1.ListOptions) (result *settings.PodPresetLi if label == nil { label = labels.Everything() } - list := &settings.PodPresetList{} + list := &settings.PodPresetList{ListMeta: obj.(*settings.PodPresetList).ListMeta} for _, item := range obj.(*settings.PodPresetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/fake_settings_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/fake_settings_client.go index ceb155254..a79d665e1 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/fake_settings_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/fake/fake_settings_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/generated_expansion.go index 83279e27b..e673a5ca8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/podpreset.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/podpreset.go index b2fb3bc90..334c2180c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/podpreset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/settings_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/settings_client.go index 5da169c58..8c365dc6f 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/settings_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/settings/internalversion/settings_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *SettingsClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("settings.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("settings.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("settings.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_storage_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_storage_client.go index 0e5bddf42..1935235ea 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_storage_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_storageclass.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_storageclass.go index d425c8825..b8d2c2905 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_storageclass.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeStorageClasses) List(opts v1.ListOptions) (result *storage.StorageC if label == nil { label = labels.Everything() } - list := &storage.StorageClassList{} + list := &storage.StorageClassList{ListMeta: obj.(*storage.StorageClassList).ListMeta} for _, item := range obj.(*storage.StorageClassList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_volumeattachment.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_volumeattachment.go index 5351f8e75..f4584a11c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_volumeattachment.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake/fake_volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeVolumeAttachments) List(opts v1.ListOptions) (result *storage.Volum if label == nil { label = labels.Everything() } - list := &storage.VolumeAttachmentList{} + list := &storage.VolumeAttachmentList{ListMeta: obj.(*storage.VolumeAttachmentList).ListMeta} for _, item := range obj.(*storage.VolumeAttachmentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/generated_expansion.go index 05b67fff4..d74dc56fe 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/storage_client.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/storage_client.go index c79fdd6f4..9272e2b9c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/storage_client.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -71,17 +71,12 @@ func New(c rest.Interface) *StorageClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("storage.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("storage.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("storage.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/storageclass.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/storageclass.go index c4f475699..4939d7af8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/storageclass.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/volumeattachment.go b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/volumeattachment.go index 512af86f9..2ce2c9784 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/volumeattachment.go +++ b/vendor/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/interface.go index dfd08ec07..2ff34d93f 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/initializerconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/initializerconfiguration.go index 8486090e9..898fd4867 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/initializerconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/interface.go index 0c1c8cb04..9955e6b9c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/mutatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/mutatingwebhookconfiguration.go index 5d713aa17..01b65bd56 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/validatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/validatingwebhookconfiguration.go index 87d0dd912..b1bcb715f 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/validatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/admissionregistration/internalversion/validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/interface.go index dccba7736..1291f3979 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/controllerrevision.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/controllerrevision.go index 13e231d59..ed1386067 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/interface.go index 8d2a857c0..9dbb8fcb7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/statefulset.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/statefulset.go index 86c44ae44..32c6f583a 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/statefulset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/apps/internalversion/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/interface.go index 5ddd3e8b9..b918859fb 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/internalversion/horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/internalversion/horizontalpodautoscaler.go index 5b5c6f713..4bdf2f610 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/internalversion/horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/internalversion/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/internalversion/interface.go index 3a3ae9b3a..b1f4104a0 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/autoscaling/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/interface.go index cd8f75235..84416cb37 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/cronjob.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/cronjob.go index 0ffa71d7c..66388b5fe 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/cronjob.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/interface.go index ac6fc29d4..7f808b5ba 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/job.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/job.go index 26324a1ac..0926fcddb 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/job.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/batch/internalversion/job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/interface.go index d17220007..7f8746805 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/internalversion/certificatesigningrequest.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/internalversion/certificatesigningrequest.go index 40bdf7cd9..49be6ed0d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/internalversion/certificatesigningrequest.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/internalversion/certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/internalversion/interface.go index da372c1e5..7cad24c3e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/certificates/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/interface.go index 1a5efd5a6..b0a9365d4 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/componentstatus.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/componentstatus.go index 99086e780..68521873f 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/componentstatus.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/configmap.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/configmap.go index 7ea518009..7c15f2320 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/configmap.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/endpoints.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/endpoints.go index 9d93a579d..64078fcc2 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/endpoints.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/event.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/event.go index 08147dc2b..d1a01e655 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/event.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/interface.go index 6e5fd45a9..57ba13604 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/limitrange.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/limitrange.go index 5655fa1cc..aec069188 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/limitrange.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/namespace.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/namespace.go index a12b87669..538c3f5fd 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/namespace.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/node.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/node.go index 340b9b5ac..aa2493537 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/node.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/persistentvolume.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/persistentvolume.go index 356c46c8a..708cb3732 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/persistentvolume.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/persistentvolumeclaim.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/persistentvolumeclaim.go index 04561b1cc..bc70a44a1 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/persistentvolumeclaim.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/pod.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/pod.go index 19f0d40ab..de3377eeb 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/pod.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/podtemplate.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/podtemplate.go index 2ce73b155..25718f44e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/podtemplate.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/replicationcontroller.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/replicationcontroller.go index 59c431f59..1819ad981 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/replicationcontroller.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/resourcequota.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/resourcequota.go index 3ed48d908..63a80dd89 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/resourcequota.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/secret.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/secret.go index e7cbe2301..eb5ed238c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/secret.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/service.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/service.go index 5a9cb6ff5..a1bbff437 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/service.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/serviceaccount.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/serviceaccount.go index 7cb44d913..49e6de949 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/serviceaccount.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion/serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/interface.go index c6c24a40e..2cdeff7c7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/BUILD b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/BUILD index 4b31f38ce..93daed923 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/BUILD @@ -12,7 +12,6 @@ go_library( "deployment.go", "ingress.go", "interface.go", - "podsecuritypolicy.go", "replicaset.go", ], importpath = "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion", diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/daemonset.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/daemonset.go index 3f5383063..af0758255 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/daemonset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/deployment.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/deployment.go index 682861490..76267c8f0 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/deployment.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/ingress.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/ingress.go index 92139faf5..31a963ef7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/ingress.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/interface.go index 43e8779c9..a6c2aee0f 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -30,8 +30,6 @@ type Interface interface { Deployments() DeploymentInformer // Ingresses returns a IngressInformer. Ingresses() IngressInformer - // PodSecurityPolicies returns a PodSecurityPolicyInformer. - PodSecurityPolicies() PodSecurityPolicyInformer // ReplicaSets returns a ReplicaSetInformer. ReplicaSets() ReplicaSetInformer } @@ -62,11 +60,6 @@ func (v *version) Ingresses() IngressInformer { return &ingressInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } -// PodSecurityPolicies returns a PodSecurityPolicyInformer. -func (v *version) PodSecurityPolicies() PodSecurityPolicyInformer { - return &podSecurityPolicyInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} -} - // ReplicaSets returns a ReplicaSetInformer. func (v *version) ReplicaSets() ReplicaSetInformer { return &replicaSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/podsecuritypolicy.go deleted file mode 100644 index 396843f3d..000000000 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/podsecuritypolicy.go +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright 2018 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. -*/ - -// Code generated by informer-gen. DO NOT EDIT. - -package internalversion - -import ( - time "time" - - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" - extensions "k8s.io/kubernetes/pkg/apis/extensions" - internalclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - internalinterfaces "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/internalinterfaces" - internalversion "k8s.io/kubernetes/pkg/client/listers/extensions/internalversion" -) - -// PodSecurityPolicyInformer provides access to a shared informer and lister for -// PodSecurityPolicies. -type PodSecurityPolicyInformer interface { - Informer() cache.SharedIndexInformer - Lister() internalversion.PodSecurityPolicyLister -} - -type podSecurityPolicyInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// NewPodSecurityPolicyInformer constructs a new informer for PodSecurityPolicy type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewPodSecurityPolicyInformer(client internalclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredPodSecurityPolicyInformer(client, resyncPeriod, indexers, nil) -} - -// NewFilteredPodSecurityPolicyInformer constructs a new informer for PodSecurityPolicy type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredPodSecurityPolicyInformer(client internalclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.Extensions().PodSecurityPolicies().List(options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.Extensions().PodSecurityPolicies().Watch(options) - }, - }, - &extensions.PodSecurityPolicy{}, - resyncPeriod, - indexers, - ) -} - -func (f *podSecurityPolicyInformer) defaultInformer(client internalclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredPodSecurityPolicyInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *podSecurityPolicyInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&extensions.PodSecurityPolicy{}, f.defaultInformer) -} - -func (f *podSecurityPolicyInformer) Lister() internalversion.PodSecurityPolicyLister { - return internalversion.NewPodSecurityPolicyLister(f.Informer().GetIndexer()) -} diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/replicaset.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/replicaset.go index 894482ca3..9a8defe61 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/replicaset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/factory.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/factory.go index 452d2cc2c..4745143f0 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/factory.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -44,12 +44,16 @@ import ( storage "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client internalclientset.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -57,23 +61,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client internalclientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -122,7 +165,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/generic.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/generic.go index 5f9611d15..d28aa26ff 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/generic.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -133,8 +133,6 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Extensions().InternalVersion().Deployments().Informer()}, nil case extensions.SchemeGroupVersion.WithResource("ingresses"): return &genericInformer{resource: resource.GroupResource(), informer: f.Extensions().InternalVersion().Ingresses().Informer()}, nil - case extensions.SchemeGroupVersion.WithResource("podsecuritypolicies"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Extensions().InternalVersion().PodSecurityPolicies().Informer()}, nil case extensions.SchemeGroupVersion.WithResource("replicasets"): return &genericInformer{resource: resource.GroupResource(), informer: f.Extensions().InternalVersion().ReplicaSets().Informer()}, nil @@ -145,6 +143,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource // Group=policy, Version=internalVersion case policy.SchemeGroupVersion.WithResource("poddisruptionbudgets"): return &genericInformer{resource: resource.GroupResource(), informer: f.Policy().InternalVersion().PodDisruptionBudgets().Informer()}, nil + case policy.SchemeGroupVersion.WithResource("podsecuritypolicies"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Policy().InternalVersion().PodSecurityPolicies().Informer()}, nil // Group=rbac.authorization.k8s.io, Version=internalVersion case rbac.SchemeGroupVersion.WithResource("clusterroles"): diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/internalinterfaces/factory_interfaces.go index 42cb80185..692cb19d7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/interface.go index c96a74636..fe91bff98 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/internalversion/interface.go index 8070e2d55..cc483b452 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/internalversion/networkpolicy.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/internalversion/networkpolicy.go index 3dcf72eb1..52628d613 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/internalversion/networkpolicy.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/networking/internalversion/networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/interface.go index 7c910f93e..0c9c08b96 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/BUILD b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/BUILD index c01088bc4..4be7c1cc5 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/BUILD @@ -10,6 +10,7 @@ go_library( srcs = [ "interface.go", "poddisruptionbudget.go", + "podsecuritypolicy.go", ], importpath = "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion", deps = [ diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/interface.go index 8ccd8ce58..9d76ddd32 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,6 +26,8 @@ import ( type Interface interface { // PodDisruptionBudgets returns a PodDisruptionBudgetInformer. PodDisruptionBudgets() PodDisruptionBudgetInformer + // PodSecurityPolicies returns a PodSecurityPolicyInformer. + PodSecurityPolicies() PodSecurityPolicyInformer } type version struct { @@ -43,3 +45,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList func (v *version) PodDisruptionBudgets() PodDisruptionBudgetInformer { return &podDisruptionBudgetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } + +// PodSecurityPolicies returns a PodSecurityPolicyInformer. +func (v *version) PodSecurityPolicies() PodSecurityPolicyInformer { + return &podSecurityPolicyInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/poddisruptionbudget.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/poddisruptionbudget.go index a48310d96..3ac3fa7f0 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/poddisruptionbudget.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/podsecuritypolicy.go new file mode 100644 index 000000000..2ef2d8032 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/policy/internalversion/podsecuritypolicy.go @@ -0,0 +1,88 @@ +/* +Copyright 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package internalversion + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + policy "k8s.io/kubernetes/pkg/apis/policy" + internalclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + internalinterfaces "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/internalinterfaces" + internalversion "k8s.io/kubernetes/pkg/client/listers/policy/internalversion" +) + +// PodSecurityPolicyInformer provides access to a shared informer and lister for +// PodSecurityPolicies. +type PodSecurityPolicyInformer interface { + Informer() cache.SharedIndexInformer + Lister() internalversion.PodSecurityPolicyLister +} + +type podSecurityPolicyInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewPodSecurityPolicyInformer constructs a new informer for PodSecurityPolicy type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewPodSecurityPolicyInformer(client internalclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredPodSecurityPolicyInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredPodSecurityPolicyInformer constructs a new informer for PodSecurityPolicy type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredPodSecurityPolicyInformer(client internalclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Policy().PodSecurityPolicies().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Policy().PodSecurityPolicies().Watch(options) + }, + }, + &policy.PodSecurityPolicy{}, + resyncPeriod, + indexers, + ) +} + +func (f *podSecurityPolicyInformer) defaultInformer(client internalclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredPodSecurityPolicyInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *podSecurityPolicyInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&policy.PodSecurityPolicy{}, f.defaultInformer) +} + +func (f *podSecurityPolicyInformer) Lister() internalversion.PodSecurityPolicyLister { + return internalversion.NewPodSecurityPolicyLister(f.Informer().GetIndexer()) +} diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/interface.go index 63f618e45..f4c338111 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/clusterrole.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/clusterrole.go index 552c22c09..776679047 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/clusterrole.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/clusterrolebinding.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/clusterrolebinding.go index 0536f98eb..60dfa9d73 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/interface.go index c336a61fd..12bcb26c7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/role.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/role.go index 2d9af7d28..712b26b25 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/role.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/rolebinding.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/rolebinding.go index 6eb1dc9b7..ee4be7307 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/rolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/rbac/internalversion/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/interface.go index a1380471e..ee1cf8a8e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/internalversion/interface.go index 053e14cc2..eb0b54890 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/internalversion/priorityclass.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/internalversion/priorityclass.go index f3bdd79f8..c01ad50f7 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/internalversion/priorityclass.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/scheduling/internalversion/priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/interface.go index c8a397b45..da1e47c4e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/internalversion/interface.go index 01c72ac6d..aa899a8ca 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/internalversion/podpreset.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/internalversion/podpreset.go index 56b689614..21e72d285 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/internalversion/podpreset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/settings/internalversion/podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/interface.go index b25e93a6b..781e41109 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/interface.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/interface.go index 7695a6df6..4ba68c407 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/storageclass.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/storageclass.go index 114a22145..a6c635aa9 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/storageclass.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/volumeattachment.go b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/volumeattachment.go index 4e30c7c21..965f87b85 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/volumeattachment.go +++ b/vendor/k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/storage/internalversion/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/leaderelectionconfig/BUILD b/vendor/k8s.io/kubernetes/pkg/client/leaderelectionconfig/BUILD index 5814cbd6f..68617620d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/leaderelectionconfig/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/leaderelectionconfig/BUILD @@ -12,8 +12,6 @@ go_library( deps = [ "//pkg/apis/componentconfig:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/client/leaderelectionconfig/config.go b/vendor/k8s.io/kubernetes/pkg/client/leaderelectionconfig/config.go index ffa0bfd19..acbcee8fc 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/leaderelectionconfig/config.go +++ b/vendor/k8s.io/kubernetes/pkg/client/leaderelectionconfig/config.go @@ -20,27 +20,13 @@ import ( "time" "github.com/spf13/pflag" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - rl "k8s.io/client-go/tools/leaderelection/resourcelock" "k8s.io/kubernetes/pkg/apis/componentconfig" ) const ( DefaultLeaseDuration = 15 * time.Second - DefaultRenewDeadline = 10 * time.Second - DefaultRetryPeriod = 2 * time.Second ) -func DefaultLeaderElectionConfiguration() componentconfig.LeaderElectionConfiguration { - return componentconfig.LeaderElectionConfiguration{ - LeaderElect: false, - LeaseDuration: metav1.Duration{Duration: DefaultLeaseDuration}, - RenewDeadline: metav1.Duration{Duration: DefaultRenewDeadline}, - RetryPeriod: metav1.Duration{Duration: DefaultRetryPeriod}, - ResourceLock: rl.EndpointsResourceLock, - } -} - // BindFlags binds the common LeaderElectionCLIConfig flags to a flagset func BindFlags(l *componentconfig.LeaderElectionConfiguration, fs *pflag.FlagSet) { fs.BoolVar(&l.LeaderElect, "leader-elect", l.LeaderElect, ""+ diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/expansion_generated.go index b03e30bb1..125c1a9ff 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/initializerconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/initializerconfiguration.go index bad503613..8563e203d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/initializerconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/mutatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/mutatingwebhookconfiguration.go index 663e519f8..bb8d590db 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/validatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/validatingwebhookconfiguration.go index 29cd5e4d1..12f38aba4 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/validatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/admissionregistration/internalversion/validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/controllerrevision.go b/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/controllerrevision.go index 613265e04..0814c4f11 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/expansion_generated.go index ad7c9afd0..7278af3da 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/statefulset.go b/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/statefulset.go index b2c634155..4accadc1e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/statefulset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/apps/internalversion/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/authentication/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/authentication/internalversion/expansion_generated.go index a1cb0c3c4..7bb8df82b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/authentication/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/authentication/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/authentication/internalversion/tokenreview.go b/vendor/k8s.io/kubernetes/pkg/client/listers/authentication/internalversion/tokenreview.go index 286b81a39..c51641429 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/authentication/internalversion/tokenreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/authentication/internalversion/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/expansion_generated.go index 86f2e539d..8f4398862 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/localsubjectaccessreview.go b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/localsubjectaccessreview.go index 7a853a3ab..cecd1a895 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/localsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/selfsubjectaccessreview.go b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/selfsubjectaccessreview.go index 8ac17ab19..d1ce35880 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/selfsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/selfsubjectrulesreview.go b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/selfsubjectrulesreview.go index fa956f7a8..b70603e6c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/selfsubjectrulesreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/subjectaccessreview.go b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/subjectaccessreview.go index 10c0c07ba..ba9dc8fda 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/subjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/authorization/internalversion/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/autoscaling/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/autoscaling/internalversion/expansion_generated.go index f83edbdeb..4cc32824d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/autoscaling/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/autoscaling/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/autoscaling/internalversion/horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/pkg/client/listers/autoscaling/internalversion/horizontalpodautoscaler.go index f1a9dcb08..9f8451420 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/autoscaling/internalversion/horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/autoscaling/internalversion/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/cronjob.go b/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/cronjob.go index 8e7185dbf..aeebb4f4d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/cronjob.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/expansion_generated.go index 0ff3e18c8..2bf27b1d6 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/job.go b/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/job.go index df35e55ef..b67b84e7b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/job.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/batch/internalversion/job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/certificates/internalversion/certificatesigningrequest.go b/vendor/k8s.io/kubernetes/pkg/client/listers/certificates/internalversion/certificatesigningrequest.go index c63428689..76c80a373 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/certificates/internalversion/certificatesigningrequest.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/certificates/internalversion/certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/certificates/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/certificates/internalversion/expansion_generated.go index 9fa1a05da..b85935075 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/certificates/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/certificates/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/componentstatus.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/componentstatus.go index bb8afc714..821247b4d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/componentstatus.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/configmap.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/configmap.go index d05669f06..46780e148 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/configmap.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/endpoints.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/endpoints.go index a97c81d66..d46e1bdd4 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/endpoints.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/event.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/event.go index 84a6f2711..017333fb1 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/event.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/expansion_generated.go index 2e9317629..ea2156b9e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/limitrange.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/limitrange.go index cb68ef58e..4d76d078c 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/limitrange.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/namespace.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/namespace.go index a371c7b50..1f4f19182 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/namespace.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/node.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/node.go index 5a50f5210..f68c94f29 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/node.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/persistentvolume.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/persistentvolume.go index bacd417f9..450096a48 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/persistentvolume.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/persistentvolumeclaim.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/persistentvolumeclaim.go index 2e287c7dd..431d7a4ce 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/persistentvolumeclaim.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/pod.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/pod.go index 2933319ff..55918afc6 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/pod.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/podtemplate.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/podtemplate.go index d2805a122..73fb61bc3 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/podtemplate.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/replicationcontroller.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/replicationcontroller.go index 0bc43e811..a16fa0ebe 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/replicationcontroller.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/resourcequota.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/resourcequota.go index 19b8b1a62..9b9e4bc96 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/resourcequota.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/secret.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/secret.go index 8b35ecaac..71c76488d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/secret.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/service.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/service.go index 147e7b797..4dd38cb08 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/service.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/serviceaccount.go b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/serviceaccount.go index 8a18d4798..c8dfce6f8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/serviceaccount.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/core/internalversion/serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/BUILD b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/BUILD index 464b8603c..c3df71ac2 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/BUILD @@ -15,7 +15,6 @@ go_library( "deployment_expansion.go", "expansion_generated.go", "ingress.go", - "podsecuritypolicy.go", "replicaset.go", "replicaset_expansion.go", ], diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/daemonset.go b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/daemonset.go index 21940cca3..d6725e984 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/daemonset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/deployment.go b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/deployment.go index 5f0a7c3fb..f18e6d4b8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/deployment.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/expansion_generated.go index 48d8f033b..546c98520 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,3 @@ type IngressListerExpansion interface{} // IngressNamespaceListerExpansion allows custom methods to be added to // IngressNamespaceLister. type IngressNamespaceListerExpansion interface{} - -// PodSecurityPolicyListerExpansion allows custom methods to be added to -// PodSecurityPolicyLister. -type PodSecurityPolicyListerExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/ingress.go b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/ingress.go index d3afedbb1..185b67891 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/ingress.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/podsecuritypolicy.go deleted file mode 100644 index 397323b3a..000000000 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/podsecuritypolicy.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2018 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. -*/ - -// Code generated by lister-gen. DO NOT EDIT. - -package internalversion - -import ( - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" - extensions "k8s.io/kubernetes/pkg/apis/extensions" -) - -// PodSecurityPolicyLister helps list PodSecurityPolicies. -type PodSecurityPolicyLister interface { - // List lists all PodSecurityPolicies in the indexer. - List(selector labels.Selector) (ret []*extensions.PodSecurityPolicy, err error) - // Get retrieves the PodSecurityPolicy from the index for a given name. - Get(name string) (*extensions.PodSecurityPolicy, error) - PodSecurityPolicyListerExpansion -} - -// podSecurityPolicyLister implements the PodSecurityPolicyLister interface. -type podSecurityPolicyLister struct { - indexer cache.Indexer -} - -// NewPodSecurityPolicyLister returns a new PodSecurityPolicyLister. -func NewPodSecurityPolicyLister(indexer cache.Indexer) PodSecurityPolicyLister { - return &podSecurityPolicyLister{indexer: indexer} -} - -// List lists all PodSecurityPolicies in the indexer. -func (s *podSecurityPolicyLister) List(selector labels.Selector) (ret []*extensions.PodSecurityPolicy, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*extensions.PodSecurityPolicy)) - }) - return ret, err -} - -// Get retrieves the PodSecurityPolicy from the index for a given name. -func (s *podSecurityPolicyLister) Get(name string) (*extensions.PodSecurityPolicy, error) { - obj, exists, err := s.indexer.GetByKey(name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(extensions.Resource("podsecuritypolicy"), name) - } - return obj.(*extensions.PodSecurityPolicy), nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/replicaset.go b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/replicaset.go index cb9f426e7..439713235 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/replicaset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/extensions/internalversion/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/imagepolicy/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/imagepolicy/internalversion/expansion_generated.go index 52b4577ae..95bf10fab 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/imagepolicy/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/imagepolicy/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/imagepolicy/internalversion/imagereview.go b/vendor/k8s.io/kubernetes/pkg/client/listers/imagepolicy/internalversion/imagereview.go index 9301d5f71..c2dbfe1b9 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/imagepolicy/internalversion/imagereview.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/imagepolicy/internalversion/imagereview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/networking/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/networking/internalversion/expansion_generated.go index 2ccf608a9..0f3b48a7d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/networking/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/networking/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/networking/internalversion/networkpolicy.go b/vendor/k8s.io/kubernetes/pkg/client/listers/networking/internalversion/networkpolicy.go index 98de2f2f2..bfde8db6a 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/networking/internalversion/networkpolicy.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/networking/internalversion/networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/BUILD b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/BUILD index c120deb3b..4d0d4fdb5 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/BUILD @@ -12,6 +12,7 @@ go_library( "expansion_generated.go", "poddisruptionbudget.go", "poddisruptionbudget_expansion.go", + "podsecuritypolicy.go", ], importpath = "k8s.io/kubernetes/pkg/client/listers/policy/internalversion", deps = [ diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/eviction.go b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/eviction.go index a39fde45b..29acba5d8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/eviction.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/eviction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/expansion_generated.go index e89fa4c8b..663d240e6 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,3 +25,7 @@ type EvictionListerExpansion interface{} // EvictionNamespaceListerExpansion allows custom methods to be added to // EvictionNamespaceLister. type EvictionNamespaceListerExpansion interface{} + +// PodSecurityPolicyListerExpansion allows custom methods to be added to +// PodSecurityPolicyLister. +type PodSecurityPolicyListerExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/poddisruptionbudget.go b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/poddisruptionbudget.go index c8ae24eb3..1549f8a93 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/poddisruptionbudget.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/podsecuritypolicy.go new file mode 100644 index 000000000..f1464f78b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/policy/internalversion/podsecuritypolicy.go @@ -0,0 +1,65 @@ +/* +Copyright 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package internalversion + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + policy "k8s.io/kubernetes/pkg/apis/policy" +) + +// PodSecurityPolicyLister helps list PodSecurityPolicies. +type PodSecurityPolicyLister interface { + // List lists all PodSecurityPolicies in the indexer. + List(selector labels.Selector) (ret []*policy.PodSecurityPolicy, err error) + // Get retrieves the PodSecurityPolicy from the index for a given name. + Get(name string) (*policy.PodSecurityPolicy, error) + PodSecurityPolicyListerExpansion +} + +// podSecurityPolicyLister implements the PodSecurityPolicyLister interface. +type podSecurityPolicyLister struct { + indexer cache.Indexer +} + +// NewPodSecurityPolicyLister returns a new PodSecurityPolicyLister. +func NewPodSecurityPolicyLister(indexer cache.Indexer) PodSecurityPolicyLister { + return &podSecurityPolicyLister{indexer: indexer} +} + +// List lists all PodSecurityPolicies in the indexer. +func (s *podSecurityPolicyLister) List(selector labels.Selector) (ret []*policy.PodSecurityPolicy, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*policy.PodSecurityPolicy)) + }) + return ret, err +} + +// Get retrieves the PodSecurityPolicy from the index for a given name. +func (s *podSecurityPolicyLister) Get(name string) (*policy.PodSecurityPolicy, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(policy.Resource("podsecuritypolicy"), name) + } + return obj.(*policy.PodSecurityPolicy), nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/clusterrole.go b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/clusterrole.go index ce6ea2695..36288ec37 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/clusterrole.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/clusterrolebinding.go b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/clusterrolebinding.go index 774c25b54..d2bc6eabd 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/expansion_generated.go index 2af26bffb..e0b20a5b8 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/role.go b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/role.go index 897d1cb03..2eb554d53 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/role.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/rolebinding.go b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/rolebinding.go index 7c508c7e1..00cd2e24e 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/rolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/rbac/internalversion/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/scheduling/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/scheduling/internalversion/expansion_generated.go index 4565581d5..a0828e84b 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/scheduling/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/scheduling/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/scheduling/internalversion/priorityclass.go b/vendor/k8s.io/kubernetes/pkg/client/listers/scheduling/internalversion/priorityclass.go index 514494ebd..b7d30c7da 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/scheduling/internalversion/priorityclass.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/scheduling/internalversion/priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/settings/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/settings/internalversion/expansion_generated.go index 583204a51..3346f5213 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/settings/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/settings/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/settings/internalversion/podpreset.go b/vendor/k8s.io/kubernetes/pkg/client/listers/settings/internalversion/podpreset.go index 797d6e1b2..4ca09ad19 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/settings/internalversion/podpreset.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/settings/internalversion/podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/expansion_generated.go index 8f104043d..4a38620de 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/storageclass.go b/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/storageclass.go index a96eb5c87..f60d04097 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/storageclass.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/volumeattachment.go b/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/volumeattachment.go index af905d67d..1f1231f5d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/volumeattachment.go +++ b/vendor/k8s.io/kubernetes/pkg/client/listers/storage/internalversion/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/client/tests/listwatch_test.go b/vendor/k8s.io/kubernetes/pkg/client/tests/listwatch_test.go index a4b6c2118..ed9907ff3 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/tests/listwatch_test.go +++ b/vendor/k8s.io/kubernetes/pkg/client/tests/listwatch_test.go @@ -26,11 +26,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" restclient "k8s.io/client-go/rest" . "k8s.io/client-go/tools/cache" utiltesting "k8s.io/client-go/util/testing" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" ) @@ -61,7 +61,7 @@ func buildLocation(resourcePath string, query url.Values) string { } func TestListWatchesCanList(t *testing.T) { - fieldSelectorQueryParamName := metav1.FieldSelectorQueryParam(legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()) + fieldSelectorQueryParamName := metav1.FieldSelectorQueryParam("v1") table := []struct { location string resource string @@ -102,7 +102,7 @@ func TestListWatchesCanList(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) lw := NewListWatchFromClient(client.Core().RESTClient(), item.resource, item.namespace, item.fieldSelector) lw.DisableChunking = true // This test merely tests that the correct request is made. @@ -112,7 +112,7 @@ func TestListWatchesCanList(t *testing.T) { } func TestListWatchesCanWatch(t *testing.T) { - fieldSelectorQueryParamName := metav1.FieldSelectorQueryParam(legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()) + fieldSelectorQueryParamName := metav1.FieldSelectorQueryParam("v1") table := []struct { rv string location string @@ -169,7 +169,7 @@ func TestListWatchesCanWatch(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) lw := NewListWatchFromClient(client.Core().RESTClient(), item.resource, item.namespace, item.fieldSelector) // This test merely tests that the correct request is made. lw.Watch(metav1.ListOptions{ResourceVersion: item.rv}) diff --git a/vendor/k8s.io/kubernetes/pkg/client/tests/remotecommand_test.go b/vendor/k8s.io/kubernetes/pkg/client/tests/remotecommand_test.go index 285a8a29e..143ee2e7d 100644 --- a/vendor/k8s.io/kubernetes/pkg/client/tests/remotecommand_test.go +++ b/vendor/k8s.io/kubernetes/pkg/client/tests/remotecommand_test.go @@ -38,7 +38,7 @@ import ( restclient "k8s.io/client-go/rest" remoteclient "k8s.io/client-go/tools/remotecommand" "k8s.io/client-go/transport/spdy" - "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" ) @@ -223,7 +223,7 @@ func TestStream(t *testing.T) { url, _ := url.ParseRequestURI(server.URL) config := restclient.ContentConfig{ GroupVersion: &schema.GroupVersion{Group: "x"}, - NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), + NegotiatedSerializer: legacyscheme.Codecs, } c, err := restclient.NewRESTClient(url, "", config, -1, -1, nil, nil) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/OWNERS b/vendor/k8s.io/kubernetes/pkg/cloudprovider/OWNERS index 176769b7d..07cf4dbda 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/OWNERS @@ -41,3 +41,4 @@ reviewers: - jingxu97 - wlan0 - cheftako +- andrewsykim diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/cloud.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/cloud.go index 9ca91ebf3..0358890bc 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/cloud.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/cloud.go @@ -130,10 +130,8 @@ type Instances interface { // from the node whose nodeaddresses are being queried. i.e. local metadata // services cannot be used in this method to obtain nodeaddresses NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) - // ExternalID returns the cloud provider ID of the node with the specified NodeName. - // Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound) - ExternalID(ctx context.Context, nodeName types.NodeName) (string, error) // InstanceID returns the cloud provider ID of the node with the specified NodeName. + // Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) // InstanceType returns the type of the specified instance. InstanceType(ctx context.Context, name types.NodeName) (string, error) @@ -148,6 +146,8 @@ type Instances interface { // InstanceExistsByProviderID returns true if the instance for the given provider id still is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) + // InstanceShutdownByProviderID returns true if the instance is shutdown in cloudprovider + InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) } // Route is a representation of an advanced routing rule. diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/plugins.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/plugins.go index 739c09613..7777997f9 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/plugins.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/plugins.go @@ -33,8 +33,16 @@ type Factory func(config io.Reader) (Interface, error) // All registered cloud providers. var ( - providersMutex sync.Mutex - providers = make(map[string]Factory) + providersMutex sync.Mutex + providers = make(map[string]Factory) + deprecatedCloudProviders = []struct { + name string + external bool + detail string + }{ + {"openstack", true, "https://github.com/kubernetes/cloud-provider-openstack"}, + {"photon", false, "The Photon Controller project is no longer maintained."}, + } ) const externalCloudProvider = "external" @@ -95,6 +103,18 @@ func InitCloudProvider(name string, configFilePath string) (Interface, error) { return nil, nil } + for _, provider := range deprecatedCloudProviders { + if provider.name == name { + detail := provider.detail + if provider.external { + detail = fmt.Sprintf("Please use 'external' cloud provider for %s: %s", name, provider.detail) + } + glog.Warningf("WARNING: %s built-in cloud provider is now deprecated. %s", name, detail) + + break + } + } + if configFilePath != "" { var config *os.File config, err = os.Open(configFilePath) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws.go index 1c006ebce..22a1114fb 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws.go @@ -44,7 +44,6 @@ import ( "github.com/aws/aws-sdk-go/service/kms" "github.com/aws/aws-sdk-go/service/sts" "github.com/golang/glog" - "github.com/prometheus/client_golang/prometheus" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" @@ -430,7 +429,7 @@ type Volumes interface { // Attach the disk to the node with the specified NodeName // nodeName can be empty to mean "the instance on which we are running" // Returns the device (e.g. /dev/xvdf) where we attached the volume - AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName, readOnly bool) (string, error) + AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName) (string, error) // Detach the disk from the node with the specified NodeName // nodeName can be empty to mean "the instance on which we are running" // Returns the device where the volume was attached @@ -754,7 +753,7 @@ func (s *awsSdkEC2) DescribeInstances(request *ec2.DescribeInstancesInput) ([]*e for { response, err := s.ec2.DescribeInstances(request) if err != nil { - recordAwsMetric("describe_instance", 0, err) + recordAWSMetric("describe_instance", 0, err) return nil, fmt.Errorf("error listing AWS instances: %q", err) } @@ -769,7 +768,7 @@ func (s *awsSdkEC2) DescribeInstances(request *ec2.DescribeInstancesInput) ([]*e request.NextToken = nextToken } timeTaken := time.Since(requestTime).Seconds() - recordAwsMetric("describe_instance", timeTaken, nil) + recordAWSMetric("describe_instance", timeTaken, nil) return results, nil } @@ -787,7 +786,7 @@ func (s *awsSdkEC2) AttachVolume(request *ec2.AttachVolumeInput) (*ec2.VolumeAtt requestTime := time.Now() resp, err := s.ec2.AttachVolume(request) timeTaken := time.Since(requestTime).Seconds() - recordAwsMetric("attach_volume", timeTaken, err) + recordAWSMetric("attach_volume", timeTaken, err) return resp, err } @@ -795,7 +794,7 @@ func (s *awsSdkEC2) DetachVolume(request *ec2.DetachVolumeInput) (*ec2.VolumeAtt requestTime := time.Now() resp, err := s.ec2.DetachVolume(request) timeTaken := time.Since(requestTime).Seconds() - recordAwsMetric("detach_volume", timeTaken, err) + recordAWSMetric("detach_volume", timeTaken, err) return resp, err } @@ -808,7 +807,7 @@ func (s *awsSdkEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) ([]*ec2.V response, err := s.ec2.DescribeVolumes(request) if err != nil { - recordAwsMetric("describe_volume", 0, err) + recordAWSMetric("describe_volume", 0, err) return nil, err } @@ -821,7 +820,7 @@ func (s *awsSdkEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) ([]*ec2.V request.NextToken = nextToken } timeTaken := time.Since(requestTime).Seconds() - recordAwsMetric("describe_volume", timeTaken, nil) + recordAWSMetric("describe_volume", timeTaken, nil) return results, nil } @@ -829,7 +828,7 @@ func (s *awsSdkEC2) CreateVolume(request *ec2.CreateVolumeInput) (*ec2.Volume, e requestTime := time.Now() resp, err := s.ec2.CreateVolume(request) timeTaken := time.Since(requestTime).Seconds() - recordAwsMetric("create_volume", timeTaken, err) + recordAWSMetric("create_volume", timeTaken, err) return resp, err } @@ -837,7 +836,7 @@ func (s *awsSdkEC2) DeleteVolume(request *ec2.DeleteVolumeInput) (*ec2.DeleteVol requestTime := time.Now() resp, err := s.ec2.DeleteVolume(request) timeTaken := time.Since(requestTime).Seconds() - recordAwsMetric("delete_volume", timeTaken, err) + recordAWSMetric("delete_volume", timeTaken, err) return resp, err } @@ -845,7 +844,7 @@ func (s *awsSdkEC2) ModifyVolume(request *ec2.ModifyVolumeInput) (*ec2.ModifyVol requestTime := time.Now() resp, err := s.ec2.ModifyVolume(request) timeTaken := time.Since(requestTime).Seconds() - recordAwsMetric("modify_volume", timeTaken, err) + recordAWSMetric("modify_volume", timeTaken, err) return resp, err } @@ -856,7 +855,7 @@ func (s *awsSdkEC2) DescribeVolumeModifications(request *ec2.DescribeVolumesModi for { resp, err := s.ec2.DescribeVolumesModifications(request) if err != nil { - recordAwsMetric("describe_volume_modification", 0, err) + recordAWSMetric("describe_volume_modification", 0, err) return nil, fmt.Errorf("error listing volume modifictions : %v", err) } results = append(results, resp.VolumesModifications...) @@ -867,7 +866,7 @@ func (s *awsSdkEC2) DescribeVolumeModifications(request *ec2.DescribeVolumesModi request.NextToken = nextToken } timeTaken := time.Since(requestTime).Seconds() - recordAwsMetric("describe_volume_modification", timeTaken, nil) + recordAWSMetric("describe_volume_modification", timeTaken, nil) return results, nil } @@ -900,7 +899,7 @@ func (s *awsSdkEC2) CreateTags(request *ec2.CreateTagsInput) (*ec2.CreateTagsOut requestTime := time.Now() resp, err := s.ec2.CreateTags(request) timeTaken := time.Since(requestTime).Seconds() - recordAwsMetric("create_tags", timeTaken, err) + recordAWSMetric("create_tags", timeTaken, err) return resp, err } @@ -1147,7 +1146,7 @@ func (c *Cloud) Initialize(clientBuilder controller.ControllerClientBuilder) { c.kubeClient = clientBuilder.ClientOrDie("aws-cloud-provider") c.eventBroadcaster = record.NewBroadcaster() c.eventBroadcaster.StartLogging(glog.Infof) - c.eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(c.kubeClient.CoreV1().RESTClient()).Events("")}) + c.eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: c.kubeClient.CoreV1().Events("")}) c.eventRecorder = c.eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "aws-cloud-provider"}) } @@ -1318,24 +1317,6 @@ func (c *Cloud) NodeAddressesByProviderID(ctx context.Context, providerID string return extractNodeAddresses(instance) } -// ExternalID returns the cloud provider ID of the node with the specified nodeName (deprecated). -func (c *Cloud) ExternalID(ctx context.Context, nodeName types.NodeName) (string, error) { - if c.selfAWSInstance.nodeName == nodeName { - // We assume that if this is run on the instance itself, the instance exists and is alive - return c.selfAWSInstance.awsID, nil - } - // We must verify that the instance still exists - // Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound) - instance, err := c.findInstanceByNodeName(nodeName) - if err != nil { - return "", err - } - if instance == nil { - return "", cloudprovider.InstanceNotFound - } - return aws.StringValue(instance.InstanceId), nil -} - // InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. func (c *Cloud) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) { @@ -1368,6 +1349,11 @@ func (c *Cloud) InstanceExistsByProviderID(ctx context.Context, providerID strin return true, nil } +// InstanceShutdownByProviderID returns true if the instance is in safe state to detach volumes +func (c *Cloud) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, cloudprovider.NotImplemented +} + // InstanceID returns the cloud provider ID of the node with the specified nodeName. func (c *Cloud) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) { // In the future it is possible to also return an endpoint as: @@ -1377,6 +1363,10 @@ func (c *Cloud) InstanceID(ctx context.Context, nodeName types.NodeName) (string } inst, err := c.getInstanceByNodeName(nodeName) if err != nil { + if err == cloudprovider.InstanceNotFound { + // The Instances interface requires that we return InstanceNotFound (without wrapping) + return "", err + } return "", fmt.Errorf("getInstanceByNodeName failed for %q with %q", nodeName, err) } return "/" + aws.StringValue(inst.Placement.AvailabilityZone) + "/" + aws.StringValue(inst.InstanceId), nil @@ -1970,7 +1960,7 @@ func wrapAttachError(err error, disk *awsDisk, instance string) error { } // AttachDisk implements Volumes.AttachDisk -func (c *Cloud) AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName, readOnly bool) (string, error) { +func (c *Cloud) AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName) (string, error) { disk, err := newAWSDisk(c, diskName) if err != nil { return "", err @@ -1981,12 +1971,6 @@ func (c *Cloud) AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName, return "", fmt.Errorf("error finding instance %s: %q", nodeName, err) } - if readOnly { - // TODO: We could enforce this when we mount the volume (?) - // TODO: We could also snapshot the volume and attach copies of it - return "", errors.New("AWS volumes cannot be mounted read-only") - } - // mountDevice will hold the device where we should try to attach the disk var mountDevice mountDevice // alreadyAttached is true if we have already called AttachVolume on this disk @@ -3697,7 +3681,11 @@ func findSecurityGroupForInstance(instance *ec2.Instance, taggedSecurityGroups m // We create instances with one SG // If users create multiple SGs, they must tag one of them as being k8s owned if len(tagged) != 1 { - return nil, fmt.Errorf("Multiple tagged security groups found for instance %s; ensure only the k8s security group is tagged", instanceID) + taggedGroups := "" + for _, v := range tagged { + taggedGroups += fmt.Sprintf("%s(%s) ", *v.GroupId, *v.GroupName) + } + return nil, fmt.Errorf("Multiple tagged security groups found for instance %s; ensure only the k8s security group is tagged; the tagged groups were %v", instanceID, taggedGroups) } return tagged[0], nil } @@ -4342,12 +4330,3 @@ func setNodeDisk( } volumeMap[volumeID] = check } - -func recordAwsMetric(actionName string, timeTaken float64, err error) { - if err != nil { - awsApiErrorMetric.With(prometheus.Labels{"request": actionName}).Inc() - } else { - awsApiMetric.With(prometheus.Labels{"request": actionName}).Observe(timeTaken) - } - -} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_loadbalancer.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_loadbalancer.go index 438b5617f..c148be378 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_loadbalancer.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_loadbalancer.go @@ -1027,10 +1027,10 @@ func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBala if elbProtocolsAreEqual(actual.InstanceProtocol, expected.InstanceProtocol) { continue } - if orZero(actual.InstancePort) != orZero(expected.InstancePort) { + if aws.Int64Value(actual.InstancePort) != aws.Int64Value(expected.InstancePort) { continue } - if orZero(actual.LoadBalancerPort) != orZero(expected.LoadBalancerPort) { + if aws.Int64Value(actual.LoadBalancerPort) != aws.Int64Value(expected.LoadBalancerPort) { continue } if awsArnEquals(actual.SSLCertificateId, expected.SSLCertificateId) { @@ -1375,8 +1375,7 @@ func (c *Cloud) ensureSSLNegotiationPolicy(loadBalancer *elb.LoadBalancerDescrip if err != nil { if aerr, ok := err.(awserr.Error); ok { switch aerr.Code() { - case "PolicyNotFound": - // TODO change from string to `elb.ErrCodePolicyNotFoundException` once the AWS SDK is updated + case elb.ErrCodePolicyNotFoundException: default: return fmt.Errorf("error describing security policies on load balancer: %q", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_metrics.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_metrics.go index ded8a7b5f..aa434d926 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_metrics.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_metrics.go @@ -18,23 +18,43 @@ package aws import "github.com/prometheus/client_golang/prometheus" -var awsApiMetric = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "cloudprovider_aws_api_request_duration_seconds", - Help: "Latency of aws api call", - }, - []string{"request"}, +var ( + awsAPIMetric = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "cloudprovider_aws_api_request_duration_seconds", + Help: "Latency of AWS API calls", + }, + []string{"request"}) + + awsAPIErrorMetric = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "cloudprovider_aws_api_request_errors", + Help: "AWS API errors", + }, + []string{"request"}) + + awsAPIThrottlesMetric = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "cloudprovider_aws_api_throttled_requests_total", + Help: "AWS API throttled requests", + }, + []string{"operation_name"}) ) -var awsApiErrorMetric = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "cloudprovider_aws_api_request_errors", - Help: "AWS Api errors", - }, - []string{"request"}, -) +func recordAWSMetric(actionName string, timeTaken float64, err error) { + if err != nil { + awsAPIErrorMetric.With(prometheus.Labels{"request": actionName}).Inc() + } else { + awsAPIMetric.With(prometheus.Labels{"request": actionName}).Observe(timeTaken) + } +} + +func recordAWSThrottlesMetric(operation string) { + awsAPIThrottlesMetric.With(prometheus.Labels{"operation_name": operation}).Inc() +} func registerMetrics() { - prometheus.MustRegister(awsApiMetric) - prometheus.MustRegister(awsApiErrorMetric) + prometheus.MustRegister(awsAPIMetric) + prometheus.MustRegister(awsAPIErrorMetric) + prometheus.MustRegister(awsAPIThrottlesMetric) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_test.go index 1d307c616..770b908f0 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_test.go @@ -1319,6 +1319,29 @@ func TestEnsureLoadBalancerHealthCheck(t *testing.T) { }) } +func TestFindSecurityGroupForInstance(t *testing.T) { + groups := map[string]*ec2.SecurityGroup{"sg123": {GroupId: aws.String("sg123")}} + id, err := findSecurityGroupForInstance(&ec2.Instance{SecurityGroups: []*ec2.GroupIdentifier{{GroupId: aws.String("sg123"), GroupName: aws.String("my_group")}}}, groups) + if err != nil { + t.Error() + } + assert.Equal(t, *id.GroupId, "sg123") + assert.Equal(t, *id.GroupName, "my_group") +} + +func TestFindSecurityGroupForInstanceMultipleTagged(t *testing.T) { + groups := map[string]*ec2.SecurityGroup{"sg123": {GroupId: aws.String("sg123")}} + _, err := findSecurityGroupForInstance(&ec2.Instance{ + SecurityGroups: []*ec2.GroupIdentifier{ + {GroupId: aws.String("sg123"), GroupName: aws.String("my_group")}, + {GroupId: aws.String("sg123"), GroupName: aws.String("another_group")}, + }, + }, groups) + require.Error(t, err) + assert.Contains(t, err.Error(), "sg123(my_group)") + assert.Contains(t, err.Error(), "sg123(another_group)") +} + func newMockedFakeAWSServices(id string) *FakeAWSServices { s := NewFakeAWSServices(id) s.ec2 = &MockedFakeEC2{FakeEC2Impl: s.ec2.(*FakeEC2Impl)} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_utils.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_utils.go index a0fa8eb89..b56699f85 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_utils.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_utils.go @@ -42,9 +42,3 @@ func stringSetFromPointers(in []*string) sets.String { } return out } - -// orZero returns the value, or 0 if the pointer is nil -// Deprecated: prefer aws.Int64Value -func orZero(v *int64) int64 { - return aws.Int64Value(v) -} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler.go index 8c063f8e8..f403168e6 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler.go @@ -69,16 +69,19 @@ func (c *CrossRequestRetryDelay) BeforeSign(r *request.Request) { } } -// Return a user-friendly string describing the request, for use in log messages -func describeRequest(r *request.Request) string { - service := r.ClientInfo.ServiceName - +// Return the operation name, for use in log messages and metrics +func operationName(r *request.Request) string { name := "?" if r.Operation != nil { name = r.Operation.Name } + return name +} - return service + "::" + name +// Return a user-friendly string describing the request, for use in log messages +func describeRequest(r *request.Request) string { + service := r.ClientInfo.ServiceName + return service + "::" + operationName(r) } // Added to the AfterRetry chain; called after any error @@ -92,6 +95,7 @@ func (c *CrossRequestRetryDelay) AfterRetry(r *request.Request) { } if awsError.Code() == "RequestLimitExceeded" { c.backoff.ReportError() + recordAWSThrottlesMetric(operationName(r)) glog.Warningf("Got RequestLimitExceeded error on AWS request (%s)", describeRequest(r)) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/tags.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/tags.go index 40947cb37..43130c360 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/tags.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/tags.go @@ -138,10 +138,10 @@ func (t *awsTagging) hasClusterTag(tags []*ec2.Tag) bool { for _, tag := range tags { tagKey := aws.StringValue(tag.Key) // For 1.6, we continue to recognize the legacy tags, for the 1.5 -> 1.6 upgrade - if tagKey == TagNameKubernetesClusterLegacy { - return aws.StringValue(tag.Value) == t.ClusterID + // Note that we want to continue traversing tag list if we see a legacy tag with value != ClusterID + if (tagKey == TagNameKubernetesClusterLegacy) && (aws.StringValue(tag.Value) == t.ClusterID) { + return true } - if tagKey == clusterTagKey { return true } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/BUILD b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/BUILD index c629ee796..1adae321e 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/BUILD @@ -42,11 +42,10 @@ go_library( "//pkg/controller:go_default_library", "//pkg/version:go_default_library", "//pkg/volume:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/compute:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/disk:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/network:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/storage:go_default_library", + "//pkg/volume/util:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute:go_default_library", + "//vendor/github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network:go_default_library", + "//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/storage:go_default_library", "//vendor/github.com/Azure/go-autorest/autorest:go_default_library", "//vendor/github.com/Azure/go-autorest/autorest/adal:go_default_library", @@ -57,6 +56,7 @@ go_library( "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/github.com/rubiojr/go-vhd/vhd:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", @@ -89,10 +89,9 @@ go_test( "//pkg/cloudprovider:go_default_library", "//pkg/cloudprovider/providers/azure/auth:go_default_library", "//pkg/kubelet/apis:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/compute:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/network:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/storage:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute:go_default_library", + "//vendor/github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network:go_default_library", + "//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage:go_default_library", "//vendor/github.com/Azure/go-autorest/autorest:go_default_library", "//vendor/github.com/Azure/go-autorest/autorest/to:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure.go index 38a1aa442..f06faf7d3 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure.go @@ -49,6 +49,14 @@ const ( vmTypeVMSS = "vmss" vmTypeStandard = "standard" + + loadBalancerSkuBasic = "basic" + loadBalancerSkuStandard = "standard" +) + +var ( + // Master nodes are not added to standard load balancer by default. + defaultExcludeMasterFromStandardLB = true ) // Config holds the configuration parsed from the --cloud-config flag @@ -109,6 +117,13 @@ type Config struct { // Use instance metadata service where possible UseInstanceMetadata bool `json:"useInstanceMetadata" yaml:"useInstanceMetadata"` + // Sku of Load Balancer and Public IP. Candidate values are: basic and standard. + // If not set, it will be default to basic. + LoadBalancerSku string `json:"loadBalancerSku" yaml:"loadBalancerSku"` + // ExcludeMasterFromStandardLB excludes master nodes from standard load balancer. + // If not set, it will be default to true. + ExcludeMasterFromStandardLB *bool `json:"excludeMasterFromStandardLB" yaml:"excludeMasterFromStandardLB"` + // Maximum allowed LoadBalancer Rule Count is the limit enforced by Azure Load balancer MaximumLoadBalancerRuleCount int `json:"maximumLoadBalancerRuleCount" yaml:"maximumLoadBalancerRuleCount"` } @@ -208,7 +223,11 @@ func NewCloud(configReader io.Reader) (cloudprovider.Interface, error) { glog.V(2).Infof("Azure cloudprovider (write ops) using rate limit config: QPS=%g, bucket=%d", config.CloudProviderRateLimitQPSWrite, config.CloudProviderRateLimitBucketWrite) + } + // Do not add master nodes to standard LB by default. + if config.ExcludeMasterFromStandardLB == nil { + config.ExcludeMasterFromStandardLB = &defaultExcludeMasterFromStandardLB } azClientConfig := &azClientConfig{ diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_backoff.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_backoff.go index a8caa53d5..6272fd67b 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_backoff.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_backoff.go @@ -20,9 +20,8 @@ import ( "context" "net/http" - "github.com/Azure/azure-sdk-for-go/arm/compute" - "github.com/Azure/azure-sdk-for-go/arm/network" - computepreview "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest" "github.com/golang/glog" @@ -72,10 +71,11 @@ func (az *Cloud) GetVirtualMachineWithRetry(name types.NodeName) (compute.Virtua // VirtualMachineClientListWithRetry invokes az.VirtualMachinesClient.List with exponential backoff retry func (az *Cloud) VirtualMachineClientListWithRetry() ([]compute.VirtualMachine, error) { allNodes := []compute.VirtualMachine{} - var result compute.VirtualMachineListResult err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { var retryErr error - result, retryErr = az.VirtualMachinesClient.List(az.ResourceGroup) + ctx, cancel := getContextWithCancel() + defer cancel() + allNodes, retryErr = az.VirtualMachinesClient.List(ctx, az.ResourceGroup) if retryErr != nil { glog.Errorf("VirtualMachinesClient.List(%v) - backoff: failure, will retry,err=%v", az.ResourceGroup, @@ -89,30 +89,6 @@ func (az *Cloud) VirtualMachineClientListWithRetry() ([]compute.VirtualMachine, return nil, err } - appendResults := (result.Value != nil && len(*result.Value) > 0) - for appendResults { - allNodes = append(allNodes, *result.Value...) - appendResults = false - // follow the next link to get all the vms for resource group - if result.NextLink != nil { - err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - var retryErr error - result, retryErr = az.VirtualMachinesClient.ListNextResults(az.ResourceGroup, result) - if retryErr != nil { - glog.Errorf("VirtualMachinesClient.ListNextResults(%v) - backoff: failure, will retry,err=%v", - az.ResourceGroup, retryErr) - return false, retryErr - } - glog.V(2).Infof("VirtualMachinesClient.ListNextResults(%v): success", az.ResourceGroup) - return true, nil - }) - if err != nil { - return allNodes, err - } - appendResults = (result.Value != nil && len(*result.Value) > 0) - } - } - return allNodes, err } @@ -135,11 +111,12 @@ func (az *Cloud) GetIPForMachineWithRetry(name types.NodeName) (string, string, // CreateOrUpdateSGWithRetry invokes az.SecurityGroupsClient.CreateOrUpdate with exponential backoff retry func (az *Cloud) CreateOrUpdateSGWithRetry(sg network.SecurityGroup) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.SecurityGroupsClient.CreateOrUpdate(az.ResourceGroup, *sg.Name, sg, nil) - resp := <-respChan - err := <-errChan + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.SecurityGroupsClient.CreateOrUpdate(ctx, az.ResourceGroup, *sg.Name, sg) glog.V(10).Infof("SecurityGroupsClient.CreateOrUpdate(%s): end", *sg.Name) - done, err := processRetryResponse(resp.Response, err) + done, err := processHTTPRetryResponse(resp, err) if done && err == nil { // Invalidate the cache right after updating az.nsgCache.Delete(*sg.Name) @@ -151,11 +128,12 @@ func (az *Cloud) CreateOrUpdateSGWithRetry(sg network.SecurityGroup) error { // CreateOrUpdateLBWithRetry invokes az.LoadBalancerClient.CreateOrUpdate with exponential backoff retry func (az *Cloud) CreateOrUpdateLBWithRetry(lb network.LoadBalancer) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.LoadBalancerClient.CreateOrUpdate(az.ResourceGroup, *lb.Name, lb, nil) - resp := <-respChan - err := <-errChan + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.LoadBalancerClient.CreateOrUpdate(ctx, az.ResourceGroup, *lb.Name, lb) glog.V(10).Infof("LoadBalancerClient.CreateOrUpdate(%s): end", *lb.Name) - done, err := processRetryResponse(resp.Response, err) + done, err := processHTTPRetryResponse(resp, err) if done && err == nil { // Invalidate the cache right after updating az.lbCache.Delete(*lb.Name) @@ -166,12 +144,14 @@ func (az *Cloud) CreateOrUpdateLBWithRetry(lb network.LoadBalancer) error { // ListLBWithRetry invokes az.LoadBalancerClient.List with exponential backoff retry func (az *Cloud) ListLBWithRetry() ([]network.LoadBalancer, error) { - allLBs := []network.LoadBalancer{} - var result network.LoadBalancerListResult + var allLBs []network.LoadBalancer err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { var retryErr error - result, retryErr = az.LoadBalancerClient.List(az.ResourceGroup) + ctx, cancel := getContextWithCancel() + defer cancel() + + allLBs, retryErr = az.LoadBalancerClient.List(ctx, az.ResourceGroup) if retryErr != nil { glog.Errorf("LoadBalancerClient.List(%v) - backoff: failure, will retry,err=%v", az.ResourceGroup, @@ -185,42 +165,19 @@ func (az *Cloud) ListLBWithRetry() ([]network.LoadBalancer, error) { return nil, err } - appendResults := (result.Value != nil && len(*result.Value) > 0) - for appendResults { - allLBs = append(allLBs, *result.Value...) - appendResults = false - - // follow the next link to get all the vms for resource group - if result.NextLink != nil { - err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - var retryErr error - result, retryErr = az.LoadBalancerClient.ListNextResults(az.ResourceGroup, result) - if retryErr != nil { - glog.Errorf("LoadBalancerClient.ListNextResults(%v) - backoff: failure, will retry,err=%v", - az.ResourceGroup, - retryErr) - return false, retryErr - } - glog.V(2).Infof("LoadBalancerClient.ListNextResults(%v) - backoff: success", az.ResourceGroup) - return true, nil - }) - if err != nil { - return allLBs, err - } - appendResults = (result.Value != nil && len(*result.Value) > 0) - } - } - return allLBs, nil } // ListPIPWithRetry list the PIP resources in the given resource group func (az *Cloud) ListPIPWithRetry(pipResourceGroup string) ([]network.PublicIPAddress, error) { - allPIPs := []network.PublicIPAddress{} - var result network.PublicIPAddressListResult + var allPIPs []network.PublicIPAddress + err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { var retryErr error - result, retryErr = az.PublicIPAddressesClient.List(pipResourceGroup) + ctx, cancel := getContextWithCancel() + defer cancel() + + allPIPs, retryErr = az.PublicIPAddressesClient.List(ctx, pipResourceGroup) if retryErr != nil { glog.Errorf("PublicIPAddressesClient.List(%v) - backoff: failure, will retry,err=%v", pipResourceGroup, @@ -234,74 +191,52 @@ func (az *Cloud) ListPIPWithRetry(pipResourceGroup string) ([]network.PublicIPAd return nil, err } - appendResults := (result.Value != nil && len(*result.Value) > 0) - for appendResults { - allPIPs = append(allPIPs, *result.Value...) - appendResults = false - - // follow the next link to get all the pip resources for resource group - if result.NextLink != nil { - err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - var retryErr error - result, retryErr = az.PublicIPAddressesClient.ListNextResults(az.ResourceGroup, result) - if retryErr != nil { - glog.Errorf("PublicIPAddressesClient.ListNextResults(%v) - backoff: failure, will retry,err=%v", - pipResourceGroup, - retryErr) - return false, retryErr - } - glog.V(2).Infof("PublicIPAddressesClient.ListNextResults(%v) - backoff: success", pipResourceGroup) - return true, nil - }) - if err != nil { - return allPIPs, err - } - appendResults = (result.Value != nil && len(*result.Value) > 0) - } - } - return allPIPs, nil } // CreateOrUpdatePIPWithRetry invokes az.PublicIPAddressesClient.CreateOrUpdate with exponential backoff retry func (az *Cloud) CreateOrUpdatePIPWithRetry(pipResourceGroup string, pip network.PublicIPAddress) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.PublicIPAddressesClient.CreateOrUpdate(pipResourceGroup, *pip.Name, pip, nil) - resp := <-respChan - err := <-errChan + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.PublicIPAddressesClient.CreateOrUpdate(ctx, pipResourceGroup, *pip.Name, pip) glog.V(10).Infof("PublicIPAddressesClient.CreateOrUpdate(%s, %s): end", pipResourceGroup, *pip.Name) - return processRetryResponse(resp.Response, err) + return processHTTPRetryResponse(resp, err) }) } // CreateOrUpdateInterfaceWithRetry invokes az.PublicIPAddressesClient.CreateOrUpdate with exponential backoff retry func (az *Cloud) CreateOrUpdateInterfaceWithRetry(nic network.Interface) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.InterfacesClient.CreateOrUpdate(az.ResourceGroup, *nic.Name, nic, nil) - resp := <-respChan - err := <-errChan + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.InterfacesClient.CreateOrUpdate(ctx, az.ResourceGroup, *nic.Name, nic) glog.V(10).Infof("InterfacesClient.CreateOrUpdate(%s): end", *nic.Name) - return processRetryResponse(resp.Response, err) + return processHTTPRetryResponse(resp, err) }) } // DeletePublicIPWithRetry invokes az.PublicIPAddressesClient.Delete with exponential backoff retry func (az *Cloud) DeletePublicIPWithRetry(pipResourceGroup string, pipName string) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.PublicIPAddressesClient.Delete(pipResourceGroup, pipName, nil) - resp := <-respChan - err := <-errChan - return processRetryResponse(resp, err) + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.PublicIPAddressesClient.Delete(ctx, pipResourceGroup, pipName) + return processHTTPRetryResponse(resp, err) }) } // DeleteLBWithRetry invokes az.LoadBalancerClient.Delete with exponential backoff retry func (az *Cloud) DeleteLBWithRetry(lbName string) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.LoadBalancerClient.Delete(az.ResourceGroup, lbName, nil) - resp := <-respChan - err := <-errChan - done, err := processRetryResponse(resp, err) + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.LoadBalancerClient.Delete(ctx, az.ResourceGroup, lbName) + done, err := processHTTPRetryResponse(resp, err) if done && err == nil { // Invalidate the cache right after deleting az.lbCache.Delete(lbName) @@ -313,48 +248,52 @@ func (az *Cloud) DeleteLBWithRetry(lbName string) error { // CreateOrUpdateRouteTableWithRetry invokes az.RouteTablesClient.CreateOrUpdate with exponential backoff retry func (az *Cloud) CreateOrUpdateRouteTableWithRetry(routeTable network.RouteTable) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.RouteTablesClient.CreateOrUpdate(az.ResourceGroup, az.RouteTableName, routeTable, nil) - resp := <-respChan - err := <-errChan - return processRetryResponse(resp.Response, err) + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.RouteTablesClient.CreateOrUpdate(ctx, az.ResourceGroup, az.RouteTableName, routeTable) + return processHTTPRetryResponse(resp, err) }) } // CreateOrUpdateRouteWithRetry invokes az.RoutesClient.CreateOrUpdate with exponential backoff retry func (az *Cloud) CreateOrUpdateRouteWithRetry(route network.Route) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.RoutesClient.CreateOrUpdate(az.ResourceGroup, az.RouteTableName, *route.Name, route, nil) - resp := <-respChan - err := <-errChan + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.RoutesClient.CreateOrUpdate(ctx, az.ResourceGroup, az.RouteTableName, *route.Name, route) glog.V(10).Infof("RoutesClient.CreateOrUpdate(%s): end", *route.Name) - return processRetryResponse(resp.Response, err) + return processHTTPRetryResponse(resp, err) }) } // DeleteRouteWithRetry invokes az.RoutesClient.Delete with exponential backoff retry func (az *Cloud) DeleteRouteWithRetry(routeName string) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.RoutesClient.Delete(az.ResourceGroup, az.RouteTableName, routeName, nil) - resp := <-respChan - err := <-errChan + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.RoutesClient.Delete(ctx, az.ResourceGroup, az.RouteTableName, routeName) glog.V(10).Infof("RoutesClient.Delete(%s): end", az.RouteTableName) - return processRetryResponse(resp, err) + return processHTTPRetryResponse(resp, err) }) } // CreateOrUpdateVMWithRetry invokes az.VirtualMachinesClient.CreateOrUpdate with exponential backoff retry func (az *Cloud) CreateOrUpdateVMWithRetry(vmName string, newVM compute.VirtualMachine) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - respChan, errChan := az.VirtualMachinesClient.CreateOrUpdate(az.ResourceGroup, vmName, newVM, nil) - resp := <-respChan - err := <-errChan + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.VirtualMachinesClient.CreateOrUpdate(ctx, az.ResourceGroup, vmName, newVM) glog.V(10).Infof("VirtualMachinesClient.CreateOrUpdate(%s): end", vmName) - return processRetryResponse(resp.Response, err) + return processHTTPRetryResponse(resp, err) }) } // UpdateVmssVMWithRetry invokes az.VirtualMachineScaleSetVMsClient.Update with exponential backoff retry -func (az *Cloud) UpdateVmssVMWithRetry(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters computepreview.VirtualMachineScaleSetVM) error { +func (az *Cloud) UpdateVmssVMWithRetry(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters compute.VirtualMachineScaleSetVM) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { resp, err := az.VirtualMachineScaleSetVMsClient.Update(ctx, resourceGroupName, VMScaleSetName, instanceID, parameters) glog.V(10).Infof("VirtualMachinesClient.CreateOrUpdate(%s,%s): end", VMScaleSetName, instanceID) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_blobDiskController.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_blobDiskController.go index 265b96af9..c0cb5941d 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_blobDiskController.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_blobDiskController.go @@ -27,7 +27,7 @@ import ( "sync/atomic" "time" - storage "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" azstorage "github.com/Azure/azure-sdk-for-go/storage" "github.com/Azure/go-autorest/autorest/to" "github.com/golang/glog" @@ -277,7 +277,10 @@ func (c *BlobDiskController) getStorageAccountKey(SAName string) (string, error) if account, exists := c.accounts[SAName]; exists && account.key != "" { return c.accounts[SAName].key, nil } - listKeysResult, err := c.common.cloud.StorageAccountClient.ListKeys(c.common.resourceGroup, SAName) + + ctx, cancel := getContextWithCancel() + defer cancel() + listKeysResult, err := c.common.cloud.StorageAccountClient.ListKeys(ctx, c.common.resourceGroup, SAName) if err != nil { return "", err } @@ -432,7 +435,9 @@ func (c *BlobDiskController) getDiskCount(SAName string) (int, error) { } func (c *BlobDiskController) getAllStorageAccounts() (map[string]*storageAccountState, error) { - accountListResult, err := c.common.cloud.StorageAccountClient.ListByResourceGroup(c.common.resourceGroup) + ctx, cancel := getContextWithCancel() + defer cancel() + accountListResult, err := c.common.cloud.StorageAccountClient.ListByResourceGroup(ctx, c.common.resourceGroup) if err != nil { return nil, err } @@ -483,13 +488,15 @@ func (c *BlobDiskController) createStorageAccount(storageAccountName string, sto glog.V(2).Infof("azureDisk - Creating storage account %s type %s", storageAccountName, string(storageAccountType)) cp := storage.AccountCreateParameters{ - Sku: &storage.Sku{Name: storageAccountType}, - Tags: &map[string]*string{"created-by": to.StringPtr("azure-dd")}, + Sku: &storage.Sku{Name: storageAccountType}, + // switch to use StorageV2 as it's recommended according to https://docs.microsoft.com/en-us/azure/storage/common/storage-account-options + Kind: storage.StorageV2, + Tags: map[string]*string{"created-by": to.StringPtr("azure-dd")}, Location: &location} - cancel := make(chan struct{}) + ctx, cancel := getContextWithCancel() + defer cancel() - _, errChan := c.common.cloud.StorageAccountClient.Create(c.common.resourceGroup, storageAccountName, cp, cancel) - err := <-errChan + _, err := c.common.cloud.StorageAccountClient.Create(ctx, c.common.resourceGroup, storageAccountName, cp) if err != nil { return fmt.Errorf(fmt.Sprintf("Create Storage Account: %s, error: %s", storageAccountName, err)) } @@ -584,7 +591,9 @@ func (c *BlobDiskController) findSANameForDisk(storageAccountType storage.SkuNam //Gets storage account exist, provisionStatus, Error if any func (c *BlobDiskController) getStorageAccountState(storageAccountName string) (bool, storage.ProvisioningState, error) { - account, err := c.common.cloud.StorageAccountClient.GetProperties(c.common.resourceGroup, storageAccountName) + ctx, cancel := getContextWithCancel() + defer cancel() + account, err := c.common.cloud.StorageAccountClient.GetProperties(ctx, c.common.resourceGroup, storageAccountName) if err != nil { return false, "", err } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_client.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_client.go index 594a19776..335a0ffaf 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_client.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_client.go @@ -22,11 +22,9 @@ import ( "net/http" "time" - "github.com/Azure/azure-sdk-for-go/arm/compute" - "github.com/Azure/azure-sdk-for-go/arm/disk" - "github.com/Azure/azure-sdk-for-go/arm/network" - "github.com/Azure/azure-sdk-for-go/arm/storage" - computepreview "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/adal" "github.com/golang/glog" @@ -43,104 +41,94 @@ func createARMRateLimitErr(isWrite bool, opName string) error { return fmt.Errorf("azure - ARM rate limited(%s) for operation:%s", opType, opName) } -func createARMRateLimitErrChannel(isWrite bool, opName string) chan error { - err := createARMRateLimitErr(isWrite, opName) - errChan := make(chan error, 1) - errChan <- err - return errChan -} - // VirtualMachinesClient defines needed functions for azure compute.VirtualMachinesClient type VirtualMachinesClient interface { - CreateOrUpdate(resourceGroupName string, VMName string, parameters compute.VirtualMachine, cancel <-chan struct{}) (<-chan compute.VirtualMachine, <-chan error) - Get(resourceGroupName string, VMName string, expand compute.InstanceViewTypes) (result compute.VirtualMachine, err error) - List(resourceGroupName string) (result compute.VirtualMachineListResult, err error) - ListNextResults(resourceGroupName string, lastResults compute.VirtualMachineListResult) (result compute.VirtualMachineListResult, err error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, VMName string, parameters compute.VirtualMachine) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, VMName string, expand compute.InstanceViewTypes) (result compute.VirtualMachine, err error) + List(ctx context.Context, resourceGroupName string) (result []compute.VirtualMachine, err error) } // InterfacesClient defines needed functions for azure network.InterfacesClient type InterfacesClient interface { - CreateOrUpdate(resourceGroupName string, networkInterfaceName string, parameters network.Interface, cancel <-chan struct{}) (<-chan network.Interface, <-chan error) - Get(resourceGroupName string, networkInterfaceName string, expand string) (result network.Interface, err error) - GetVirtualMachineScaleSetNetworkInterface(resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, expand string) (result network.Interface, err error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, networkInterfaceName string, parameters network.Interface) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, networkInterfaceName string, expand string) (result network.Interface, err error) + GetVirtualMachineScaleSetNetworkInterface(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, expand string) (result network.Interface, err error) } // LoadBalancersClient defines needed functions for azure network.LoadBalancersClient type LoadBalancersClient interface { - CreateOrUpdate(resourceGroupName string, loadBalancerName string, parameters network.LoadBalancer, cancel <-chan struct{}) (<-chan network.LoadBalancer, <-chan error) - Delete(resourceGroupName string, loadBalancerName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) - Get(resourceGroupName string, loadBalancerName string, expand string) (result network.LoadBalancer, err error) - List(resourceGroupName string) (result network.LoadBalancerListResult, err error) - ListNextResults(resourceGroupName string, lastResult network.LoadBalancerListResult) (result network.LoadBalancerListResult, err error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, loadBalancerName string, parameters network.LoadBalancer) (resp *http.Response, err error) + Delete(ctx context.Context, resourceGroupName string, loadBalancerName string) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, loadBalancerName string, expand string) (result network.LoadBalancer, err error) + List(ctx context.Context, resourceGroupName string) (result []network.LoadBalancer, err error) } // PublicIPAddressesClient defines needed functions for azure network.PublicIPAddressesClient type PublicIPAddressesClient interface { - CreateOrUpdate(resourceGroupName string, publicIPAddressName string, parameters network.PublicIPAddress, cancel <-chan struct{}) (<-chan network.PublicIPAddress, <-chan error) - Delete(resourceGroupName string, publicIPAddressName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) - Get(resourceGroupName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) - List(resourceGroupName string) (result network.PublicIPAddressListResult, err error) - ListNextResults(resourceGroupName string, lastResults network.PublicIPAddressListResult) (result network.PublicIPAddressListResult, err error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, publicIPAddressName string, parameters network.PublicIPAddress) (resp *http.Response, err error) + Delete(ctx context.Context, resourceGroupName string, publicIPAddressName string) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) + List(ctx context.Context, resourceGroupName string) (result []network.PublicIPAddress, err error) } // SubnetsClient defines needed functions for azure network.SubnetsClient type SubnetsClient interface { - CreateOrUpdate(resourceGroupName string, virtualNetworkName string, subnetName string, subnetParameters network.Subnet, cancel <-chan struct{}) (<-chan network.Subnet, <-chan error) - Delete(resourceGroupName string, virtualNetworkName string, subnetName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) - Get(resourceGroupName string, virtualNetworkName string, subnetName string, expand string) (result network.Subnet, err error) - List(resourceGroupName string, virtualNetworkName string) (result network.SubnetListResult, err error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string, subnetParameters network.Subnet) (resp *http.Response, err error) + Delete(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string, expand string) (result network.Subnet, err error) + List(ctx context.Context, resourceGroupName string, virtualNetworkName string) (result []network.Subnet, err error) } // SecurityGroupsClient defines needed functions for azure network.SecurityGroupsClient type SecurityGroupsClient interface { - CreateOrUpdate(resourceGroupName string, networkSecurityGroupName string, parameters network.SecurityGroup, cancel <-chan struct{}) (<-chan network.SecurityGroup, <-chan error) - Delete(resourceGroupName string, networkSecurityGroupName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) - Get(resourceGroupName string, networkSecurityGroupName string, expand string) (result network.SecurityGroup, err error) - List(resourceGroupName string) (result network.SecurityGroupListResult, err error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, parameters network.SecurityGroup) (resp *http.Response, err error) + Delete(ctx context.Context, resourceGroupName string, networkSecurityGroupName string) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, expand string) (result network.SecurityGroup, err error) + List(ctx context.Context, resourceGroupName string) (result []network.SecurityGroup, err error) } -// VirtualMachineScaleSetsClient defines needed functions for azure computepreview.VirtualMachineScaleSetsClient +// VirtualMachineScaleSetsClient defines needed functions for azure compute.VirtualMachineScaleSetsClient type VirtualMachineScaleSetsClient interface { - CreateOrUpdate(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters computepreview.VirtualMachineScaleSet) (resp *http.Response, err error) - Get(ctx context.Context, resourceGroupName string, VMScaleSetName string) (result computepreview.VirtualMachineScaleSet, err error) - List(ctx context.Context, resourceGroupName string) (result []computepreview.VirtualMachineScaleSet, err error) - UpdateInstances(ctx context.Context, resourceGroupName string, VMScaleSetName string, VMInstanceIDs computepreview.VirtualMachineScaleSetVMInstanceRequiredIDs) (resp *http.Response, err error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, VMScaleSetName string) (result compute.VirtualMachineScaleSet, err error) + List(ctx context.Context, resourceGroupName string) (result []compute.VirtualMachineScaleSet, err error) + UpdateInstances(ctx context.Context, resourceGroupName string, VMScaleSetName string, VMInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) (resp *http.Response, err error) } -// VirtualMachineScaleSetVMsClient defines needed functions for azure computepreview.VirtualMachineScaleSetVMsClient +// VirtualMachineScaleSetVMsClient defines needed functions for azure compute.VirtualMachineScaleSetVMsClient type VirtualMachineScaleSetVMsClient interface { - Get(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result computepreview.VirtualMachineScaleSetVM, err error) - GetInstanceView(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result computepreview.VirtualMachineScaleSetVMInstanceView, err error) - List(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result []computepreview.VirtualMachineScaleSetVM, err error) - Update(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters computepreview.VirtualMachineScaleSetVM) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result compute.VirtualMachineScaleSetVM, err error) + GetInstanceView(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result compute.VirtualMachineScaleSetVMInstanceView, err error) + List(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result []compute.VirtualMachineScaleSetVM, err error) + Update(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters compute.VirtualMachineScaleSetVM) (resp *http.Response, err error) } // RoutesClient defines needed functions for azure network.RoutesClient type RoutesClient interface { - CreateOrUpdate(resourceGroupName string, routeTableName string, routeName string, routeParameters network.Route, cancel <-chan struct{}) (<-chan network.Route, <-chan error) - Delete(resourceGroupName string, routeTableName string, routeName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, routeTableName string, routeName string, routeParameters network.Route) (resp *http.Response, err error) + Delete(ctx context.Context, resourceGroupName string, routeTableName string, routeName string) (resp *http.Response, err error) } // RouteTablesClient defines needed functions for azure network.RouteTablesClient type RouteTablesClient interface { - CreateOrUpdate(resourceGroupName string, routeTableName string, parameters network.RouteTable, cancel <-chan struct{}) (<-chan network.RouteTable, <-chan error) - Get(resourceGroupName string, routeTableName string, expand string) (result network.RouteTable, err error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, routeTableName string, parameters network.RouteTable) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, routeTableName string, expand string) (result network.RouteTable, err error) } // StorageAccountClient defines needed functions for azure storage.AccountsClient type StorageAccountClient interface { - Create(resourceGroupName string, accountName string, parameters storage.AccountCreateParameters, cancel <-chan struct{}) (<-chan storage.Account, <-chan error) - Delete(resourceGroupName string, accountName string) (result autorest.Response, err error) - ListKeys(resourceGroupName string, accountName string) (result storage.AccountListKeysResult, err error) - ListByResourceGroup(resourceGroupName string) (result storage.AccountListResult, err error) - GetProperties(resourceGroupName string, accountName string) (result storage.Account, err error) + Create(ctx context.Context, resourceGroupName string, accountName string, parameters storage.AccountCreateParameters) (result *http.Response, err error) + Delete(ctx context.Context, resourceGroupName string, accountName string) (result autorest.Response, err error) + ListKeys(ctx context.Context, resourceGroupName string, accountName string) (result storage.AccountListKeysResult, err error) + ListByResourceGroup(ctx context.Context, resourceGroupName string) (result storage.AccountListResult, err error) + GetProperties(ctx context.Context, resourceGroupName string, accountName string) (result storage.Account, err error) } -// DisksClient defines needed functions for azure disk.DisksClient +// DisksClient defines needed functions for azure compute.DisksClient type DisksClient interface { - CreateOrUpdate(resourceGroupName string, diskName string, diskParameter disk.Model, cancel <-chan struct{}) (<-chan disk.Model, <-chan error) - Delete(resourceGroupName string, diskName string, cancel <-chan struct{}) (<-chan disk.OperationStatusResponse, <-chan error) - Get(resourceGroupName string, diskName string) (result disk.Model, err error) + CreateOrUpdate(ctx context.Context, resourceGroupName string, diskName string, diskParameter compute.Disk) (resp *http.Response, err error) + Delete(ctx context.Context, resourceGroupName string, diskName string) (resp *http.Response, err error) + Get(ctx context.Context, resourceGroupName string, diskName string) (result compute.Disk, err error) } // azClientConfig contains all essential information to create an Azure client. @@ -179,13 +167,11 @@ func newAzVirtualMachinesClient(config *azClientConfig) *azVirtualMachinesClient } } -func (az *azVirtualMachinesClient) CreateOrUpdate(resourceGroupName string, VMName string, parameters compute.VirtualMachine, cancel <-chan struct{}) (<-chan compute.VirtualMachine, <-chan error) { - /* Write rate limiting */ +func (az *azVirtualMachinesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, VMName string, parameters compute.VirtualMachine) (resp *http.Response, err error) { + // /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "NSGCreateOrUpdate") - resultChan := make(chan compute.VirtualMachine, 1) - resultChan <- compute.VirtualMachine{} - return resultChan, errChan + err = createARMRateLimitErr(true, "VMCreateOrUpdate") + return } glog.V(10).Infof("azVirtualMachinesClient.CreateOrUpdate(%q, %q): start", resourceGroupName, VMName) @@ -193,16 +179,18 @@ func (az *azVirtualMachinesClient) CreateOrUpdate(resourceGroupName string, VMNa glog.V(10).Infof("azVirtualMachinesClient.CreateOrUpdate(%q, %q): end", resourceGroupName, VMName) }() - errChan := make(chan error, 1) mc := newMetricContext("vm", "create_or_update", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.CreateOrUpdate(resourceGroupName, VMName, parameters, cancel) - err := <-proxyErrChan + future, err := az.client.CreateOrUpdate(ctx, resourceGroupName, VMName, parameters) + if err != nil { + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azVirtualMachinesClient) Get(resourceGroupName string, VMName string, expand compute.InstanceViewTypes) (result compute.VirtualMachine, err error) { +func (az *azVirtualMachinesClient) Get(ctx context.Context, resourceGroupName string, VMName string, expand compute.InstanceViewTypes) (result compute.VirtualMachine, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "VMGet") return @@ -214,12 +202,12 @@ func (az *azVirtualMachinesClient) Get(resourceGroupName string, VMName string, }() mc := newMetricContext("vm", "get", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.Get(resourceGroupName, VMName, expand) + result, err = az.client.Get(ctx, resourceGroupName, VMName, expand) mc.Observe(err) return } -func (az *azVirtualMachinesClient) List(resourceGroupName string) (result compute.VirtualMachineListResult, err error) { +func (az *azVirtualMachinesClient) List(ctx context.Context, resourceGroupName string) (result []compute.VirtualMachine, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "VMList") return @@ -231,26 +219,22 @@ func (az *azVirtualMachinesClient) List(resourceGroupName string) (result comput }() mc := newMetricContext("vm", "list", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.List(resourceGroupName) + iterator, err := az.client.ListComplete(ctx, resourceGroupName) mc.Observe(err) - return -} - -func (az *azVirtualMachinesClient) ListNextResults(resourceGroupName string, lastResults compute.VirtualMachineListResult) (result compute.VirtualMachineListResult, err error) { - if !az.rateLimiterReader.TryAccept() { - err = createARMRateLimitErr(false, "VMListNextResults") - return + if err != nil { + return nil, err } - glog.V(10).Infof("azVirtualMachinesClient.ListNextResults(%q): start", lastResults) - defer func() { - glog.V(10).Infof("azVirtualMachinesClient.ListNextResults(%q): end", lastResults) - }() + result = make([]compute.VirtualMachine, 0) + for ; iterator.NotDone(); err = iterator.Next() { + if err != nil { + return nil, err + } - mc := newMetricContext("vm", "list_next_results", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.ListNextResults(lastResults) - mc.Observe(err) - return + result = append(result, iterator.Value()) + } + + return result, nil } // azInterfacesClient implements InterfacesClient. @@ -274,13 +258,11 @@ func newAzInterfacesClient(config *azClientConfig) *azInterfacesClient { } } -func (az *azInterfacesClient) CreateOrUpdate(resourceGroupName string, networkInterfaceName string, parameters network.Interface, cancel <-chan struct{}) (<-chan network.Interface, <-chan error) { +func (az *azInterfacesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, networkInterfaceName string, parameters network.Interface) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "NiCreateOrUpdate") - resultChan := make(chan network.Interface, 1) - resultChan <- network.Interface{} - return resultChan, errChan + err = createARMRateLimitErr(true, "NiCreateOrUpdate") + return } glog.V(10).Infof("azInterfacesClient.CreateOrUpdate(%q,%q): start", resourceGroupName, networkInterfaceName) @@ -288,16 +270,19 @@ func (az *azInterfacesClient) CreateOrUpdate(resourceGroupName string, networkIn glog.V(10).Infof("azInterfacesClient.CreateOrUpdate(%q,%q): end", resourceGroupName, networkInterfaceName) }() - errChan := make(chan error, 1) mc := newMetricContext("interfaces", "create_or_update", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.CreateOrUpdate(resourceGroupName, networkInterfaceName, parameters, cancel) - err := <-proxyErrChan + future, err := az.client.CreateOrUpdate(ctx, resourceGroupName, networkInterfaceName, parameters) + if err != nil { + mc.Observe(err) + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azInterfacesClient) Get(resourceGroupName string, networkInterfaceName string, expand string) (result network.Interface, err error) { +func (az *azInterfacesClient) Get(ctx context.Context, resourceGroupName string, networkInterfaceName string, expand string) (result network.Interface, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "NicGet") return @@ -309,12 +294,12 @@ func (az *azInterfacesClient) Get(resourceGroupName string, networkInterfaceName }() mc := newMetricContext("interfaces", "get", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.Get(resourceGroupName, networkInterfaceName, expand) + result, err = az.client.Get(ctx, resourceGroupName, networkInterfaceName, expand) mc.Observe(err) return } -func (az *azInterfacesClient) GetVirtualMachineScaleSetNetworkInterface(resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, expand string) (result network.Interface, err error) { +func (az *azInterfacesClient) GetVirtualMachineScaleSetNetworkInterface(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, expand string) (result network.Interface, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "NicGetVirtualMachineScaleSetNetworkInterface") return @@ -326,7 +311,7 @@ func (az *azInterfacesClient) GetVirtualMachineScaleSetNetworkInterface(resource }() mc := newMetricContext("interfaces", "get_vmss_ni", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.GetVirtualMachineScaleSetNetworkInterface(resourceGroupName, virtualMachineScaleSetName, virtualmachineIndex, networkInterfaceName, expand) + result, err = az.client.GetVirtualMachineScaleSetNetworkInterface(ctx, resourceGroupName, virtualMachineScaleSetName, virtualmachineIndex, networkInterfaceName, expand) mc.Observe(err) return } @@ -352,13 +337,11 @@ func newAzLoadBalancersClient(config *azClientConfig) *azLoadBalancersClient { } } -func (az *azLoadBalancersClient) CreateOrUpdate(resourceGroupName string, loadBalancerName string, parameters network.LoadBalancer, cancel <-chan struct{}) (<-chan network.LoadBalancer, <-chan error) { +func (az *azLoadBalancersClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, loadBalancerName string, parameters network.LoadBalancer) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "LBCreateOrUpdate") - resultChan := make(chan network.LoadBalancer, 1) - resultChan <- network.LoadBalancer{} - return resultChan, errChan + err = createARMRateLimitErr(true, "LBCreateOrUpdate") + return nil, err } glog.V(10).Infof("azLoadBalancersClient.CreateOrUpdate(%q,%q): start", resourceGroupName, loadBalancerName) @@ -366,22 +349,23 @@ func (az *azLoadBalancersClient) CreateOrUpdate(resourceGroupName string, loadBa glog.V(10).Infof("azLoadBalancersClient.CreateOrUpdate(%q,%q): end", resourceGroupName, loadBalancerName) }() - errChan := make(chan error, 1) mc := newMetricContext("load_balancers", "create_or_update", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.CreateOrUpdate(resourceGroupName, loadBalancerName, parameters, cancel) - err := <-proxyErrChan + future, err := az.client.CreateOrUpdate(ctx, resourceGroupName, loadBalancerName, parameters) mc.Observe(err) - errChan <- err - return resultChan, errChan + if err != nil { + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) + mc.Observe(err) + return future.Response(), err } -func (az *azLoadBalancersClient) Delete(resourceGroupName string, loadBalancerName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (az *azLoadBalancersClient) Delete(ctx context.Context, resourceGroupName string, loadBalancerName string) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "LBDelete") - resultChan := make(chan autorest.Response, 1) - resultChan <- autorest.Response{} - return resultChan, errChan + err = createARMRateLimitErr(true, "LBDelete") + return nil, err } glog.V(10).Infof("azLoadBalancersClient.Delete(%q,%q): start", resourceGroupName, loadBalancerName) @@ -389,16 +373,19 @@ func (az *azLoadBalancersClient) Delete(resourceGroupName string, loadBalancerNa glog.V(10).Infof("azLoadBalancersClient.Delete(%q,%q): end", resourceGroupName, loadBalancerName) }() - errChan := make(chan error, 1) mc := newMetricContext("load_balancers", "delete", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.Delete(resourceGroupName, loadBalancerName, cancel) - err := <-proxyErrChan + future, err := az.client.Delete(ctx, resourceGroupName, loadBalancerName) mc.Observe(err) - errChan <- err - return resultChan, errChan + if err != nil { + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) + mc.Observe(err) + return future.Response(), err } -func (az *azLoadBalancersClient) Get(resourceGroupName string, loadBalancerName string, expand string) (result network.LoadBalancer, err error) { +func (az *azLoadBalancersClient) Get(ctx context.Context, resourceGroupName string, loadBalancerName string, expand string) (result network.LoadBalancer, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "LBGet") return @@ -410,15 +397,15 @@ func (az *azLoadBalancersClient) Get(resourceGroupName string, loadBalancerName }() mc := newMetricContext("load_balancers", "get", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.Get(resourceGroupName, loadBalancerName, expand) + result, err = az.client.Get(ctx, resourceGroupName, loadBalancerName, expand) mc.Observe(err) return } -func (az *azLoadBalancersClient) List(resourceGroupName string) (result network.LoadBalancerListResult, err error) { +func (az *azLoadBalancersClient) List(ctx context.Context, resourceGroupName string) ([]network.LoadBalancer, error) { if !az.rateLimiterReader.TryAccept() { - err = createARMRateLimitErr(false, "LBList") - return + err := createARMRateLimitErr(false, "LBList") + return nil, err } glog.V(10).Infof("azLoadBalancersClient.List(%q): start", resourceGroupName) @@ -427,26 +414,22 @@ func (az *azLoadBalancersClient) List(resourceGroupName string) (result network. }() mc := newMetricContext("load_balancers", "list", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.List(resourceGroupName) + iterator, err := az.client.ListComplete(ctx, resourceGroupName) mc.Observe(err) - return -} - -func (az *azLoadBalancersClient) ListNextResults(resourceGroupName string, lastResult network.LoadBalancerListResult) (result network.LoadBalancerListResult, err error) { - if !az.rateLimiterReader.TryAccept() { - err = createARMRateLimitErr(false, "LBListNextResults") - return + if err != nil { + return nil, err } - glog.V(10).Infof("azLoadBalancersClient.ListNextResults(%q): start", lastResult) - defer func() { - glog.V(10).Infof("azLoadBalancersClient.ListNextResults(%q): end", lastResult) - }() + result := make([]network.LoadBalancer, 0) + for ; iterator.NotDone(); err = iterator.Next() { + if err != nil { + return nil, err + } - mc := newMetricContext("load_balancers", "list_next_results", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.ListNextResults(lastResult) - mc.Observe(err) - return + result = append(result, iterator.Value()) + } + + return result, nil } // azPublicIPAddressesClient implements PublicIPAddressesClient. @@ -470,13 +453,11 @@ func newAzPublicIPAddressesClient(config *azClientConfig) *azPublicIPAddressesCl } } -func (az *azPublicIPAddressesClient) CreateOrUpdate(resourceGroupName string, publicIPAddressName string, parameters network.PublicIPAddress, cancel <-chan struct{}) (<-chan network.PublicIPAddress, <-chan error) { +func (az *azPublicIPAddressesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, publicIPAddressName string, parameters network.PublicIPAddress) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "PublicIPCreateOrUpdate") - resultChan := make(chan network.PublicIPAddress, 1) - resultChan <- network.PublicIPAddress{} - return resultChan, errChan + err = createARMRateLimitErr(true, "PublicIPCreateOrUpdate") + return nil, err } glog.V(10).Infof("azPublicIPAddressesClient.CreateOrUpdate(%q,%q): start", resourceGroupName, publicIPAddressName) @@ -484,22 +465,23 @@ func (az *azPublicIPAddressesClient) CreateOrUpdate(resourceGroupName string, pu glog.V(10).Infof("azPublicIPAddressesClient.CreateOrUpdate(%q,%q): end", resourceGroupName, publicIPAddressName) }() - errChan := make(chan error, 1) mc := newMetricContext("public_ip_addresses", "create_or_update", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.CreateOrUpdate(resourceGroupName, publicIPAddressName, parameters, cancel) - err := <-proxyErrChan + future, err := az.client.CreateOrUpdate(ctx, resourceGroupName, publicIPAddressName, parameters) + mc.Observe(err) + if err != nil { + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azPublicIPAddressesClient) Delete(resourceGroupName string, publicIPAddressName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (az *azPublicIPAddressesClient) Delete(ctx context.Context, resourceGroupName string, publicIPAddressName string) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "PublicIPDelete") - resultChan := make(chan autorest.Response, 1) - resultChan <- autorest.Response{} - return resultChan, errChan + err = createARMRateLimitErr(true, "PublicIPDelete") + return nil, err } glog.V(10).Infof("azPublicIPAddressesClient.Delete(%q,%q): start", resourceGroupName, publicIPAddressName) @@ -507,16 +489,19 @@ func (az *azPublicIPAddressesClient) Delete(resourceGroupName string, publicIPAd glog.V(10).Infof("azPublicIPAddressesClient.Delete(%q,%q): end", resourceGroupName, publicIPAddressName) }() - errChan := make(chan error, 1) mc := newMetricContext("public_ip_addresses", "delete", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.Delete(resourceGroupName, publicIPAddressName, cancel) - err := <-proxyErrChan + future, err := az.client.Delete(ctx, resourceGroupName, publicIPAddressName) + mc.Observe(err) + if err != nil { + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azPublicIPAddressesClient) Get(resourceGroupName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) { +func (az *azPublicIPAddressesClient) Get(ctx context.Context, resourceGroupName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "PublicIPGet") return @@ -528,15 +513,14 @@ func (az *azPublicIPAddressesClient) Get(resourceGroupName string, publicIPAddre }() mc := newMetricContext("public_ip_addresses", "get", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.Get(resourceGroupName, publicIPAddressName, expand) + result, err = az.client.Get(ctx, resourceGroupName, publicIPAddressName, expand) mc.Observe(err) return } -func (az *azPublicIPAddressesClient) List(resourceGroupName string) (result network.PublicIPAddressListResult, err error) { +func (az *azPublicIPAddressesClient) List(ctx context.Context, resourceGroupName string) ([]network.PublicIPAddress, error) { if !az.rateLimiterReader.TryAccept() { - err = createARMRateLimitErr(false, "PublicIPList") - return + return nil, createARMRateLimitErr(false, "PublicIPList") } glog.V(10).Infof("azPublicIPAddressesClient.List(%q): start", resourceGroupName) @@ -545,26 +529,22 @@ func (az *azPublicIPAddressesClient) List(resourceGroupName string) (result netw }() mc := newMetricContext("public_ip_addresses", "list", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.List(resourceGroupName) + iterator, err := az.client.ListComplete(ctx, resourceGroupName) mc.Observe(err) - return -} - -func (az *azPublicIPAddressesClient) ListNextResults(resourceGroupName string, lastResults network.PublicIPAddressListResult) (result network.PublicIPAddressListResult, err error) { - if !az.rateLimiterReader.TryAccept() { - err = createARMRateLimitErr(false, "PublicIPListNextResults") - return + if err != nil { + return nil, err } - glog.V(10).Infof("azPublicIPAddressesClient.ListNextResults(%q): start", lastResults) - defer func() { - glog.V(10).Infof("azPublicIPAddressesClient.ListNextResults(%q): end", lastResults) - }() + result := make([]network.PublicIPAddress, 0) + for ; iterator.NotDone(); err = iterator.Next() { + if err != nil { + return nil, err + } - mc := newMetricContext("public_ip_addresses", "list_next_results", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.ListNextResults(lastResults) - mc.Observe(err) - return + result = append(result, iterator.Value()) + } + + return result, nil } // azSubnetsClient implements SubnetsClient. @@ -588,13 +568,11 @@ func newAzSubnetsClient(config *azClientConfig) *azSubnetsClient { } } -func (az *azSubnetsClient) CreateOrUpdate(resourceGroupName string, virtualNetworkName string, subnetName string, subnetParameters network.Subnet, cancel <-chan struct{}) (<-chan network.Subnet, <-chan error) { +func (az *azSubnetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string, subnetParameters network.Subnet) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "SubnetCreateOrUpdate") - resultChan := make(chan network.Subnet, 1) - resultChan <- network.Subnet{} - return resultChan, errChan + err = createARMRateLimitErr(true, "SubnetCreateOrUpdate") + return } glog.V(10).Infof("azSubnetsClient.CreateOrUpdate(%q,%q,%q): start", resourceGroupName, virtualNetworkName, subnetName) @@ -602,22 +580,23 @@ func (az *azSubnetsClient) CreateOrUpdate(resourceGroupName string, virtualNetwo glog.V(10).Infof("azSubnetsClient.CreateOrUpdate(%q,%q,%q): end", resourceGroupName, virtualNetworkName, subnetName) }() - errChan := make(chan error, 1) mc := newMetricContext("subnets", "create_or_update", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.CreateOrUpdate(resourceGroupName, virtualNetworkName, subnetName, subnetParameters, cancel) - err := <-proxyErrChan + future, err := az.client.CreateOrUpdate(ctx, resourceGroupName, virtualNetworkName, subnetName, subnetParameters) + if err != nil { + mc.Observe(err) + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azSubnetsClient) Delete(resourceGroupName string, virtualNetworkName string, subnetName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (az *azSubnetsClient) Delete(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "SubnetDelete") - resultChan := make(chan autorest.Response, 1) - resultChan <- autorest.Response{} - return resultChan, errChan + err = createARMRateLimitErr(true, "SubnetDelete") + return } glog.V(10).Infof("azSubnetsClient.Delete(%q,%q,%q): start", resourceGroupName, virtualNetworkName, subnetName) @@ -625,16 +604,19 @@ func (az *azSubnetsClient) Delete(resourceGroupName string, virtualNetworkName s glog.V(10).Infof("azSubnetsClient.Delete(%q,%q,%q): end", resourceGroupName, virtualNetworkName, subnetName) }() - errChan := make(chan error, 1) mc := newMetricContext("subnets", "delete", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.Delete(resourceGroupName, virtualNetworkName, subnetName, cancel) - err := <-proxyErrChan + future, err := az.client.Delete(ctx, resourceGroupName, virtualNetworkName, subnetName) + if err != nil { + mc.Observe(err) + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azSubnetsClient) Get(resourceGroupName string, virtualNetworkName string, subnetName string, expand string) (result network.Subnet, err error) { +func (az *azSubnetsClient) Get(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string, expand string) (result network.Subnet, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "SubnetGet") return @@ -646,15 +628,14 @@ func (az *azSubnetsClient) Get(resourceGroupName string, virtualNetworkName stri }() mc := newMetricContext("subnets", "get", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.Get(resourceGroupName, virtualNetworkName, subnetName, expand) + result, err = az.client.Get(ctx, resourceGroupName, virtualNetworkName, subnetName, expand) mc.Observe(err) return } -func (az *azSubnetsClient) List(resourceGroupName string, virtualNetworkName string) (result network.SubnetListResult, err error) { +func (az *azSubnetsClient) List(ctx context.Context, resourceGroupName string, virtualNetworkName string) ([]network.Subnet, error) { if !az.rateLimiterReader.TryAccept() { - err = createARMRateLimitErr(false, "SubnetList") - return + return nil, createARMRateLimitErr(false, "SubnetList") } glog.V(10).Infof("azSubnetsClient.List(%q,%q): start", resourceGroupName, virtualNetworkName) @@ -663,9 +644,22 @@ func (az *azSubnetsClient) List(resourceGroupName string, virtualNetworkName str }() mc := newMetricContext("subnets", "list", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.List(resourceGroupName, virtualNetworkName) - mc.Observe(err) - return + iterator, err := az.client.ListComplete(ctx, resourceGroupName, virtualNetworkName) + if err != nil { + mc.Observe(err) + return nil, err + } + + result := make([]network.Subnet, 0) + for ; iterator.NotDone(); err = iterator.Next() { + if err != nil { + return nil, err + } + + result = append(result, iterator.Value()) + } + + return result, nil } // azSecurityGroupsClient implements SecurityGroupsClient. @@ -689,13 +683,11 @@ func newAzSecurityGroupsClient(config *azClientConfig) *azSecurityGroupsClient { } } -func (az *azSecurityGroupsClient) CreateOrUpdate(resourceGroupName string, networkSecurityGroupName string, parameters network.SecurityGroup, cancel <-chan struct{}) (<-chan network.SecurityGroup, <-chan error) { +func (az *azSecurityGroupsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, parameters network.SecurityGroup) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "NSGCreateOrUpdate") - resultChan := make(chan network.SecurityGroup, 1) - resultChan <- network.SecurityGroup{} - return resultChan, errChan + err = createARMRateLimitErr(true, "NSGCreateOrUpdate") + return } glog.V(10).Infof("azSecurityGroupsClient.CreateOrUpdate(%q,%q): start", resourceGroupName, networkSecurityGroupName) @@ -703,22 +695,23 @@ func (az *azSecurityGroupsClient) CreateOrUpdate(resourceGroupName string, netwo glog.V(10).Infof("azSecurityGroupsClient.CreateOrUpdate(%q,%q): end", resourceGroupName, networkSecurityGroupName) }() - errChan := make(chan error, 1) mc := newMetricContext("security_groups", "create_or_update", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.CreateOrUpdate(resourceGroupName, networkSecurityGroupName, parameters, cancel) - err := <-proxyErrChan + future, err := az.client.CreateOrUpdate(ctx, resourceGroupName, networkSecurityGroupName, parameters) + if err != nil { + mc.Observe(err) + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azSecurityGroupsClient) Delete(resourceGroupName string, networkSecurityGroupName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (az *azSecurityGroupsClient) Delete(ctx context.Context, resourceGroupName string, networkSecurityGroupName string) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "NSGDelete") - resultChan := make(chan autorest.Response, 1) - resultChan <- autorest.Response{} - return resultChan, errChan + err = createARMRateLimitErr(true, "NSGDelete") + return } glog.V(10).Infof("azSecurityGroupsClient.Delete(%q,%q): start", resourceGroupName, networkSecurityGroupName) @@ -726,16 +719,19 @@ func (az *azSecurityGroupsClient) Delete(resourceGroupName string, networkSecuri glog.V(10).Infof("azSecurityGroupsClient.Delete(%q,%q): end", resourceGroupName, networkSecurityGroupName) }() - errChan := make(chan error, 1) mc := newMetricContext("security_groups", "delete", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.Delete(resourceGroupName, networkSecurityGroupName, cancel) - err := <-proxyErrChan + future, err := az.client.Delete(ctx, resourceGroupName, networkSecurityGroupName) + if err != nil { + mc.Observe(err) + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azSecurityGroupsClient) Get(resourceGroupName string, networkSecurityGroupName string, expand string) (result network.SecurityGroup, err error) { +func (az *azSecurityGroupsClient) Get(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, expand string) (result network.SecurityGroup, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "NSGGet") return @@ -747,15 +743,14 @@ func (az *azSecurityGroupsClient) Get(resourceGroupName string, networkSecurityG }() mc := newMetricContext("security_groups", "get", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.Get(resourceGroupName, networkSecurityGroupName, expand) + result, err = az.client.Get(ctx, resourceGroupName, networkSecurityGroupName, expand) mc.Observe(err) return } -func (az *azSecurityGroupsClient) List(resourceGroupName string) (result network.SecurityGroupListResult, err error) { +func (az *azSecurityGroupsClient) List(ctx context.Context, resourceGroupName string) ([]network.SecurityGroup, error) { if !az.rateLimiterReader.TryAccept() { - err = createARMRateLimitErr(false, "NSGList") - return + return nil, createARMRateLimitErr(false, "NSGList") } glog.V(10).Infof("azSecurityGroupsClient.List(%q): start", resourceGroupName) @@ -764,20 +759,33 @@ func (az *azSecurityGroupsClient) List(resourceGroupName string) (result network }() mc := newMetricContext("security_groups", "list", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.List(resourceGroupName) + iterator, err := az.client.ListComplete(ctx, resourceGroupName) mc.Observe(err) - return + if err != nil { + return nil, err + } + + result := make([]network.SecurityGroup, 0) + for ; iterator.NotDone(); err = iterator.Next() { + if err != nil { + return nil, err + } + + result = append(result, iterator.Value()) + } + + return result, nil } // azVirtualMachineScaleSetsClient implements VirtualMachineScaleSetsClient. type azVirtualMachineScaleSetsClient struct { - client computepreview.VirtualMachineScaleSetsClient + client compute.VirtualMachineScaleSetsClient rateLimiterReader flowcontrol.RateLimiter rateLimiterWriter flowcontrol.RateLimiter } func newAzVirtualMachineScaleSetsClient(config *azClientConfig) *azVirtualMachineScaleSetsClient { - virtualMachineScaleSetsClient := computepreview.NewVirtualMachineScaleSetsClient(config.subscriptionID) + virtualMachineScaleSetsClient := compute.NewVirtualMachineScaleSetsClient(config.subscriptionID) virtualMachineScaleSetsClient.BaseURI = config.resourceManagerEndpoint virtualMachineScaleSetsClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) virtualMachineScaleSetsClient.PollingDelay = 5 * time.Second @@ -790,7 +798,7 @@ func newAzVirtualMachineScaleSetsClient(config *azClientConfig) *azVirtualMachin } } -func (az *azVirtualMachineScaleSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters computepreview.VirtualMachineScaleSet) (resp *http.Response, err error) { +func (az *azVirtualMachineScaleSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { err = createARMRateLimitErr(true, "VMSSCreateOrUpdate") @@ -814,7 +822,7 @@ func (az *azVirtualMachineScaleSetsClient) CreateOrUpdate(ctx context.Context, r return future.Response(), err } -func (az *azVirtualMachineScaleSetsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string) (result computepreview.VirtualMachineScaleSet, err error) { +func (az *azVirtualMachineScaleSetsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string) (result compute.VirtualMachineScaleSet, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "VMSSGet") return @@ -831,7 +839,7 @@ func (az *azVirtualMachineScaleSetsClient) Get(ctx context.Context, resourceGrou return } -func (az *azVirtualMachineScaleSetsClient) List(ctx context.Context, resourceGroupName string) (result []computepreview.VirtualMachineScaleSet, err error) { +func (az *azVirtualMachineScaleSetsClient) List(ctx context.Context, resourceGroupName string) (result []compute.VirtualMachineScaleSet, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "VMSSList") return @@ -849,7 +857,7 @@ func (az *azVirtualMachineScaleSetsClient) List(ctx context.Context, resourceGro return nil, err } - result = make([]computepreview.VirtualMachineScaleSet, 0) + result = make([]compute.VirtualMachineScaleSet, 0) for ; iterator.NotDone(); err = iterator.Next() { if err != nil { return nil, err @@ -861,7 +869,7 @@ func (az *azVirtualMachineScaleSetsClient) List(ctx context.Context, resourceGro return result, nil } -func (az *azVirtualMachineScaleSetsClient) UpdateInstances(ctx context.Context, resourceGroupName string, VMScaleSetName string, VMInstanceIDs computepreview.VirtualMachineScaleSetVMInstanceRequiredIDs) (resp *http.Response, err error) { +func (az *azVirtualMachineScaleSetsClient) UpdateInstances(ctx context.Context, resourceGroupName string, VMScaleSetName string, VMInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { err = createARMRateLimitErr(true, "VMSSUpdateInstances") @@ -887,13 +895,13 @@ func (az *azVirtualMachineScaleSetsClient) UpdateInstances(ctx context.Context, // azVirtualMachineScaleSetVMsClient implements VirtualMachineScaleSetVMsClient. type azVirtualMachineScaleSetVMsClient struct { - client computepreview.VirtualMachineScaleSetVMsClient + client compute.VirtualMachineScaleSetVMsClient rateLimiterReader flowcontrol.RateLimiter rateLimiterWriter flowcontrol.RateLimiter } func newAzVirtualMachineScaleSetVMsClient(config *azClientConfig) *azVirtualMachineScaleSetVMsClient { - virtualMachineScaleSetVMsClient := computepreview.NewVirtualMachineScaleSetVMsClient(config.subscriptionID) + virtualMachineScaleSetVMsClient := compute.NewVirtualMachineScaleSetVMsClient(config.subscriptionID) virtualMachineScaleSetVMsClient.BaseURI = config.resourceManagerEndpoint virtualMachineScaleSetVMsClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) virtualMachineScaleSetVMsClient.PollingDelay = 5 * time.Second @@ -906,7 +914,7 @@ func newAzVirtualMachineScaleSetVMsClient(config *azClientConfig) *azVirtualMach } } -func (az *azVirtualMachineScaleSetVMsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result computepreview.VirtualMachineScaleSetVM, err error) { +func (az *azVirtualMachineScaleSetVMsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result compute.VirtualMachineScaleSetVM, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "VMSSGet") return @@ -923,7 +931,7 @@ func (az *azVirtualMachineScaleSetVMsClient) Get(ctx context.Context, resourceGr return } -func (az *azVirtualMachineScaleSetVMsClient) GetInstanceView(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result computepreview.VirtualMachineScaleSetVMInstanceView, err error) { +func (az *azVirtualMachineScaleSetVMsClient) GetInstanceView(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result compute.VirtualMachineScaleSetVMInstanceView, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "VMSSGetInstanceView") return @@ -940,7 +948,7 @@ func (az *azVirtualMachineScaleSetVMsClient) GetInstanceView(ctx context.Context return } -func (az *azVirtualMachineScaleSetVMsClient) List(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result []computepreview.VirtualMachineScaleSetVM, err error) { +func (az *azVirtualMachineScaleSetVMsClient) List(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result []compute.VirtualMachineScaleSetVM, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "VMSSList") return @@ -958,7 +966,7 @@ func (az *azVirtualMachineScaleSetVMsClient) List(ctx context.Context, resourceG return nil, err } - result = make([]computepreview.VirtualMachineScaleSetVM, 0) + result = make([]compute.VirtualMachineScaleSetVM, 0) for ; iterator.NotDone(); err = iterator.Next() { if err != nil { return nil, err @@ -970,7 +978,7 @@ func (az *azVirtualMachineScaleSetVMsClient) List(ctx context.Context, resourceG return result, nil } -func (az *azVirtualMachineScaleSetVMsClient) Update(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters computepreview.VirtualMachineScaleSetVM) (resp *http.Response, err error) { +func (az *azVirtualMachineScaleSetVMsClient) Update(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters compute.VirtualMachineScaleSetVM) (resp *http.Response, err error) { if !az.rateLimiterWriter.TryAccept() { err = createARMRateLimitErr(true, "VMSSUpdate") return @@ -1014,13 +1022,11 @@ func newAzRoutesClient(config *azClientConfig) *azRoutesClient { } } -func (az *azRoutesClient) CreateOrUpdate(resourceGroupName string, routeTableName string, routeName string, routeParameters network.Route, cancel <-chan struct{}) (<-chan network.Route, <-chan error) { +func (az *azRoutesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, routeTableName string, routeName string, routeParameters network.Route) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "RouteCreateOrUpdate") - resultChan := make(chan network.Route, 1) - resultChan <- network.Route{} - return resultChan, errChan + err = createARMRateLimitErr(true, "RouteCreateOrUpdate") + return } glog.V(10).Infof("azRoutesClient.CreateOrUpdate(%q,%q,%q): start", resourceGroupName, routeTableName, routeName) @@ -1028,22 +1034,23 @@ func (az *azRoutesClient) CreateOrUpdate(resourceGroupName string, routeTableNam glog.V(10).Infof("azRoutesClient.CreateOrUpdate(%q,%q,%q): end", resourceGroupName, routeTableName, routeName) }() - errChan := make(chan error, 1) mc := newMetricContext("routes", "create_or_update", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.CreateOrUpdate(resourceGroupName, routeTableName, routeName, routeParameters, cancel) - err := <-proxyErrChan + future, err := az.client.CreateOrUpdate(ctx, resourceGroupName, routeTableName, routeName, routeParameters) + if err != nil { + mc.Observe(err) + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azRoutesClient) Delete(resourceGroupName string, routeTableName string, routeName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (az *azRoutesClient) Delete(ctx context.Context, resourceGroupName string, routeTableName string, routeName string) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "RouteDelete") - resultChan := make(chan autorest.Response, 1) - resultChan <- autorest.Response{} - return resultChan, errChan + err = createARMRateLimitErr(true, "RouteDelete") + return } glog.V(10).Infof("azRoutesClient.Delete(%q,%q,%q): start", resourceGroupName, routeTableName, routeName) @@ -1051,13 +1058,16 @@ func (az *azRoutesClient) Delete(resourceGroupName string, routeTableName string glog.V(10).Infof("azRoutesClient.Delete(%q,%q,%q): end", resourceGroupName, routeTableName, routeName) }() - errChan := make(chan error, 1) mc := newMetricContext("routes", "delete", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.Delete(resourceGroupName, routeTableName, routeName, cancel) - err := <-proxyErrChan + future, err := az.client.Delete(ctx, resourceGroupName, routeTableName, routeName) + if err != nil { + mc.Observe(err) + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } // azRouteTablesClient implements RouteTablesClient. @@ -1081,13 +1091,11 @@ func newAzRouteTablesClient(config *azClientConfig) *azRouteTablesClient { } } -func (az *azRouteTablesClient) CreateOrUpdate(resourceGroupName string, routeTableName string, parameters network.RouteTable, cancel <-chan struct{}) (<-chan network.RouteTable, <-chan error) { +func (az *azRouteTablesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, routeTableName string, parameters network.RouteTable) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "RouteTableCreateOrUpdate") - resultChan := make(chan network.RouteTable, 1) - resultChan <- network.RouteTable{} - return resultChan, errChan + err = createARMRateLimitErr(true, "RouteTableCreateOrUpdate") + return } glog.V(10).Infof("azRouteTablesClient.CreateOrUpdate(%q,%q): start", resourceGroupName, routeTableName) @@ -1095,16 +1103,19 @@ func (az *azRouteTablesClient) CreateOrUpdate(resourceGroupName string, routeTab glog.V(10).Infof("azRouteTablesClient.CreateOrUpdate(%q,%q): end", resourceGroupName, routeTableName) }() - errChan := make(chan error, 1) mc := newMetricContext("route_tables", "create_or_update", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.CreateOrUpdate(resourceGroupName, routeTableName, parameters, cancel) - err := <-proxyErrChan + future, err := az.client.CreateOrUpdate(ctx, resourceGroupName, routeTableName, parameters) + mc.Observe(err) + if err != nil { + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azRouteTablesClient) Get(resourceGroupName string, routeTableName string, expand string) (result network.RouteTable, err error) { +func (az *azRouteTablesClient) Get(ctx context.Context, resourceGroupName string, routeTableName string, expand string) (result network.RouteTable, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "GetRouteTable") return @@ -1116,7 +1127,7 @@ func (az *azRouteTablesClient) Get(resourceGroupName string, routeTableName stri }() mc := newMetricContext("route_tables", "get", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.Get(resourceGroupName, routeTableName, expand) + result, err = az.client.Get(ctx, resourceGroupName, routeTableName, expand) mc.Observe(err) return } @@ -1141,13 +1152,11 @@ func newAzStorageAccountClient(config *azClientConfig) *azStorageAccountClient { } } -func (az *azStorageAccountClient) Create(resourceGroupName string, accountName string, parameters storage.AccountCreateParameters, cancel <-chan struct{}) (<-chan storage.Account, <-chan error) { +func (az *azStorageAccountClient) Create(ctx context.Context, resourceGroupName string, accountName string, parameters storage.AccountCreateParameters) (result *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "StorageAccountCreate") - resultChan := make(chan storage.Account, 1) - resultChan <- storage.Account{} - return resultChan, errChan + err = createARMRateLimitErr(true, "StorageAccountCreate") + return } glog.V(10).Infof("azStorageAccountClient.Create(%q,%q): start", resourceGroupName, accountName) @@ -1155,16 +1164,18 @@ func (az *azStorageAccountClient) Create(resourceGroupName string, accountName s glog.V(10).Infof("azStorageAccountClient.Create(%q,%q): end", resourceGroupName, accountName) }() - errChan := make(chan error, 1) mc := newMetricContext("storage_account", "create", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.Create(resourceGroupName, accountName, parameters, cancel) - err := <-proxyErrChan + future, err := az.client.Create(ctx, resourceGroupName, accountName, parameters) + if err != nil { + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) mc.Observe(err) - errChan <- err - return resultChan, errChan + return future.Response(), err } -func (az *azStorageAccountClient) Delete(resourceGroupName string, accountName string) (result autorest.Response, err error) { +func (az *azStorageAccountClient) Delete(ctx context.Context, resourceGroupName string, accountName string) (result autorest.Response, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "DeleteStorageAccount") return @@ -1176,12 +1187,12 @@ func (az *azStorageAccountClient) Delete(resourceGroupName string, accountName s }() mc := newMetricContext("storage_account", "delete", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.Delete(resourceGroupName, accountName) + result, err = az.client.Delete(ctx, resourceGroupName, accountName) mc.Observe(err) return } -func (az *azStorageAccountClient) ListKeys(resourceGroupName string, accountName string) (result storage.AccountListKeysResult, err error) { +func (az *azStorageAccountClient) ListKeys(ctx context.Context, resourceGroupName string, accountName string) (result storage.AccountListKeysResult, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "ListStorageAccountKeys") return @@ -1193,12 +1204,12 @@ func (az *azStorageAccountClient) ListKeys(resourceGroupName string, accountName }() mc := newMetricContext("storage_account", "list_keys", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.ListKeys(resourceGroupName, accountName) + result, err = az.client.ListKeys(ctx, resourceGroupName, accountName) mc.Observe(err) return } -func (az *azStorageAccountClient) ListByResourceGroup(resourceGroupName string) (result storage.AccountListResult, err error) { +func (az *azStorageAccountClient) ListByResourceGroup(ctx context.Context, resourceGroupName string) (result storage.AccountListResult, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "ListStorageAccountsByResourceGroup") return @@ -1210,12 +1221,12 @@ func (az *azStorageAccountClient) ListByResourceGroup(resourceGroupName string) }() mc := newMetricContext("storage_account", "list_by_resource_group", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.ListByResourceGroup(resourceGroupName) + result, err = az.client.ListByResourceGroup(ctx, resourceGroupName) mc.Observe(err) return } -func (az *azStorageAccountClient) GetProperties(resourceGroupName string, accountName string) (result storage.Account, err error) { +func (az *azStorageAccountClient) GetProperties(ctx context.Context, resourceGroupName string, accountName string) (result storage.Account, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "GetStorageAccount/Properties") return @@ -1227,20 +1238,20 @@ func (az *azStorageAccountClient) GetProperties(resourceGroupName string, accoun }() mc := newMetricContext("storage_account", "get_properties", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.GetProperties(resourceGroupName, accountName) + result, err = az.client.GetProperties(ctx, resourceGroupName, accountName) mc.Observe(err) return } // azDisksClient implements DisksClient. type azDisksClient struct { - client disk.DisksClient + client compute.DisksClient rateLimiterReader flowcontrol.RateLimiter rateLimiterWriter flowcontrol.RateLimiter } func newAzDisksClient(config *azClientConfig) *azDisksClient { - disksClient := disk.NewDisksClientWithBaseURI(config.resourceManagerEndpoint, config.subscriptionID) + disksClient := compute.NewDisksClientWithBaseURI(config.resourceManagerEndpoint, config.subscriptionID) disksClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) disksClient.PollingDelay = 5 * time.Second configureUserAgent(&disksClient.Client) @@ -1252,13 +1263,11 @@ func newAzDisksClient(config *azClientConfig) *azDisksClient { } } -func (az *azDisksClient) CreateOrUpdate(resourceGroupName string, diskName string, diskParameter disk.Model, cancel <-chan struct{}) (<-chan disk.Model, <-chan error) { +func (az *azDisksClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, diskName string, diskParameter compute.Disk) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "DiskCreateOrUpdate") - resultChan := make(chan disk.Model, 1) - resultChan <- disk.Model{} - return resultChan, errChan + err = createARMRateLimitErr(true, "DiskCreateOrUpdate") + return } glog.V(10).Infof("azDisksClient.CreateOrUpdate(%q,%q): start", resourceGroupName, diskName) @@ -1266,22 +1275,23 @@ func (az *azDisksClient) CreateOrUpdate(resourceGroupName string, diskName strin glog.V(10).Infof("azDisksClient.CreateOrUpdate(%q,%q): end", resourceGroupName, diskName) }() - errChan := make(chan error, 1) mc := newMetricContext("disks", "create_or_update", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.CreateOrUpdate(resourceGroupName, diskName, diskParameter, cancel) - err := <-proxyErrChan + future, err := az.client.CreateOrUpdate(ctx, resourceGroupName, diskName, diskParameter) mc.Observe(err) - errChan <- err - return resultChan, errChan + if err != nil { + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) + mc.Observe(err) + return future.Response(), err } -func (az *azDisksClient) Delete(resourceGroupName string, diskName string, cancel <-chan struct{}) (<-chan disk.OperationStatusResponse, <-chan error) { +func (az *azDisksClient) Delete(ctx context.Context, resourceGroupName string, diskName string) (resp *http.Response, err error) { /* Write rate limiting */ if !az.rateLimiterWriter.TryAccept() { - errChan := createARMRateLimitErrChannel(true, "DiskDelete") - resultChan := make(chan disk.OperationStatusResponse, 1) - resultChan <- disk.OperationStatusResponse{} - return resultChan, errChan + err = createARMRateLimitErr(true, "DiskDelete") + return } glog.V(10).Infof("azDisksClient.Delete(%q,%q): start", resourceGroupName, diskName) @@ -1289,16 +1299,19 @@ func (az *azDisksClient) Delete(resourceGroupName string, diskName string, cance glog.V(10).Infof("azDisksClient.Delete(%q,%q): end", resourceGroupName, diskName) }() - errChan := make(chan error, 1) mc := newMetricContext("disks", "delete", resourceGroupName, az.client.SubscriptionID) - resultChan, proxyErrChan := az.client.Delete(resourceGroupName, diskName, cancel) - err := <-proxyErrChan + future, err := az.client.Delete(ctx, resourceGroupName, diskName) mc.Observe(err) - errChan <- err - return resultChan, errChan + if err != nil { + return future.Response(), err + } + + err = future.WaitForCompletion(ctx, az.client.Client) + mc.Observe(err) + return future.Response(), err } -func (az *azDisksClient) Get(resourceGroupName string, diskName string) (result disk.Model, err error) { +func (az *azDisksClient) Get(ctx context.Context, resourceGroupName string, diskName string) (result compute.Disk, err error) { if !az.rateLimiterReader.TryAccept() { err = createARMRateLimitErr(false, "GetDisk") return @@ -1310,7 +1323,7 @@ func (az *azDisksClient) Get(resourceGroupName string, diskName string) (result }() mc := newMetricContext("disks", "get", resourceGroupName, az.client.SubscriptionID) - result, err = az.client.Get(resourceGroupName, diskName) + result, err = az.client.Get(ctx, resourceGroupName, diskName) mc.Observe(err) return } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_common.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_common.go index 84a911c4c..b0068b6d7 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_common.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_common.go @@ -20,10 +20,12 @@ import ( "fmt" "time" - "github.com/Azure/azure-sdk-for-go/arm/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/golang/glog" "k8s.io/apimachinery/pkg/types" kwait "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/pkg/cloudprovider" ) const ( @@ -56,137 +58,131 @@ type controllerCommon struct { cloud *Cloud } -// AttachDisk attaches a vhd to vm. The vhd must exist, can be identified by diskName, diskURI, and lun. -func (c *controllerCommon) AttachDisk(isManagedDisk bool, diskName, diskURI string, nodeName types.NodeName, lun int32, cachingMode compute.CachingTypes) error { - // 1. vmType is standard, attach with availabilitySet.AttachDisk. +// getNodeVMSet gets the VMSet interface based on config.VMType and the real virtual machine type. +func (c *controllerCommon) getNodeVMSet(nodeName types.NodeName) (VMSet, error) { + // 1. vmType is standard, return cloud.vmSet directly. if c.cloud.VMType == vmTypeStandard { - return c.cloud.vmSet.AttachDisk(isManagedDisk, diskName, diskURI, nodeName, lun, cachingMode) + return c.cloud.vmSet, nil } // 2. vmType is Virtual Machine Scale Set (vmss), convert vmSet to scaleSet. ss, ok := c.cloud.vmSet.(*scaleSet) if !ok { - return fmt.Errorf("error of converting vmSet (%q) to scaleSet with vmType %q", c.cloud.vmSet, c.cloud.VMType) + return nil, fmt.Errorf("error of converting vmSet (%q) to scaleSet with vmType %q", c.cloud.vmSet, c.cloud.VMType) } - // 3. If the node is managed by availability set, then attach with availabilitySet.AttachDisk. + // 3. If the node is managed by availability set, then return ss.availabilitySet. managedByAS, err := ss.isNodeManagedByAvailabilitySet(mapNodeNameToVMName(nodeName)) if err != nil { - return err + return nil, err } if managedByAS { // vm is managed by availability set. - return ss.availabilitySet.AttachDisk(isManagedDisk, diskName, diskURI, nodeName, lun, cachingMode) + return ss.availabilitySet, nil } - // 4. Node is managed by vmss, attach with scaleSet.AttachDisk. - return ss.AttachDisk(isManagedDisk, diskName, diskURI, nodeName, lun, cachingMode) + // 4. Node is managed by vmss + return ss, nil } -// DetachDiskByName detaches a vhd from host. The vhd can be identified by diskName or diskURI. -func (c *controllerCommon) DetachDiskByName(diskName, diskURI string, nodeName types.NodeName) error { - // 1. vmType is standard, detach with availabilitySet.DetachDiskByName. - if c.cloud.VMType == vmTypeStandard { - return c.cloud.vmSet.DetachDiskByName(diskName, diskURI, nodeName) +// AttachDisk attaches a vhd to vm. The vhd must exist, can be identified by diskName, diskURI, and lun. +func (c *controllerCommon) AttachDisk(isManagedDisk bool, diskName, diskURI string, nodeName types.NodeName, lun int32, cachingMode compute.CachingTypes) error { + vmset, err := c.getNodeVMSet(nodeName) + if err != nil { + return err } - // 2. vmType is Virtual Machine Scale Set (vmss), convert vmSet to scaleSet. - ss, ok := c.cloud.vmSet.(*scaleSet) - if !ok { - return fmt.Errorf("error of converting vmSet (%q) to scaleSet with vmType %q", c.cloud.vmSet, c.cloud.VMType) - } + return vmset.AttachDisk(isManagedDisk, diskName, diskURI, nodeName, lun, cachingMode) +} - // 3. If the node is managed by availability set, then detach with availabilitySet.DetachDiskByName. - managedByAS, err := ss.isNodeManagedByAvailabilitySet(mapNodeNameToVMName(nodeName)) +// DetachDiskByName detaches a vhd from host. The vhd can be identified by diskName or diskURI. +func (c *controllerCommon) DetachDiskByName(diskName, diskURI string, nodeName types.NodeName) error { + vmset, err := c.getNodeVMSet(nodeName) if err != nil { return err } - if managedByAS { - // vm is managed by availability set. - return ss.availabilitySet.DetachDiskByName(diskName, diskURI, nodeName) - } - // 4. Node is managed by vmss, detach with scaleSet.DetachDiskByName. - return ss.DetachDiskByName(diskName, diskURI, nodeName) + return vmset.DetachDiskByName(diskName, diskURI, nodeName) } -// GetDiskLun finds the lun on the host that the vhd is attached to, given a vhd's diskName and diskURI. -func (c *controllerCommon) GetDiskLun(diskName, diskURI string, nodeName types.NodeName) (int32, error) { - // 1. vmType is standard, get with availabilitySet.GetDiskLun. - if c.cloud.VMType == vmTypeStandard { - return c.cloud.vmSet.GetDiskLun(diskName, diskURI, nodeName) +// getNodeDataDisks invokes vmSet interfaces to get data disks for the node. +func (c *controllerCommon) getNodeDataDisks(nodeName types.NodeName) ([]compute.DataDisk, error) { + vmset, err := c.getNodeVMSet(nodeName) + if err != nil { + return nil, err } - // 2. vmType is Virtual Machine Scale Set (vmss), convert vmSet to scaleSet. - ss, ok := c.cloud.vmSet.(*scaleSet) - if !ok { - return -1, fmt.Errorf("error of converting vmSet (%q) to scaleSet with vmType %q", c.cloud.vmSet, c.cloud.VMType) - } + return vmset.GetDataDisks(nodeName) +} - // 3. If the node is managed by availability set, then get with availabilitySet.GetDiskLun. - managedByAS, err := ss.isNodeManagedByAvailabilitySet(mapNodeNameToVMName(nodeName)) +// GetDiskLun finds the lun on the host that the vhd is attached to, given a vhd's diskName and diskURI. +func (c *controllerCommon) GetDiskLun(diskName, diskURI string, nodeName types.NodeName) (int32, error) { + disks, err := c.getNodeDataDisks(nodeName) if err != nil { + glog.Errorf("error of getting data disks for node %q: %v", nodeName, err) return -1, err } - if managedByAS { - // vm is managed by availability set. - return ss.availabilitySet.GetDiskLun(diskName, diskURI, nodeName) - } - // 4. Node is managed by vmss, get with scaleSet.GetDiskLun. - return ss.GetDiskLun(diskName, diskURI, nodeName) + for _, disk := range disks { + if disk.Lun != nil && (disk.Name != nil && diskName != "" && *disk.Name == diskName) || + (disk.Vhd != nil && disk.Vhd.URI != nil && diskURI != "" && *disk.Vhd.URI == diskURI) || + (disk.ManagedDisk != nil && *disk.ManagedDisk.ID == diskURI) { + // found the disk + glog.V(4).Infof("azureDisk - find disk: lun %d name %q uri %q", *disk.Lun, diskName, diskURI) + return *disk.Lun, nil + } + } + return -1, fmt.Errorf("Cannot find Lun for disk %s", diskName) } // GetNextDiskLun searches all vhd attachment on the host and find unused lun. Return -1 if all luns are used. func (c *controllerCommon) GetNextDiskLun(nodeName types.NodeName) (int32, error) { - // 1. vmType is standard, get with availabilitySet.GetNextDiskLun. - if c.cloud.VMType == vmTypeStandard { - return c.cloud.vmSet.GetNextDiskLun(nodeName) - } - - // 2. vmType is Virtual Machine Scale Set (vmss), convert vmSet to scaleSet. - ss, ok := c.cloud.vmSet.(*scaleSet) - if !ok { - return -1, fmt.Errorf("error of converting vmSet (%q) to scaleSet with vmType %q", c.cloud.vmSet, c.cloud.VMType) - } - - // 3. If the node is managed by availability set, then get with availabilitySet.GetNextDiskLun. - managedByAS, err := ss.isNodeManagedByAvailabilitySet(mapNodeNameToVMName(nodeName)) + disks, err := c.getNodeDataDisks(nodeName) if err != nil { + glog.Errorf("error of getting data disks for node %q: %v", nodeName, err) return -1, err } - if managedByAS { - // vm is managed by availability set. - return ss.availabilitySet.GetNextDiskLun(nodeName) - } - // 4. Node is managed by vmss, get with scaleSet.GetNextDiskLun. - return ss.GetNextDiskLun(nodeName) + used := make([]bool, maxLUN) + for _, disk := range disks { + if disk.Lun != nil { + used[*disk.Lun] = true + } + } + for k, v := range used { + if !v { + return int32(k), nil + } + } + return -1, fmt.Errorf("all luns are used") } // DisksAreAttached checks if a list of volumes are attached to the node with the specified NodeName. func (c *controllerCommon) DisksAreAttached(diskNames []string, nodeName types.NodeName) (map[string]bool, error) { - // 1. vmType is standard, check with availabilitySet.DisksAreAttached. - if c.cloud.VMType == vmTypeStandard { - return c.cloud.vmSet.DisksAreAttached(diskNames, nodeName) - } - - // 2. vmType is Virtual Machine Scale Set (vmss), convert vmSet to scaleSet. - ss, ok := c.cloud.vmSet.(*scaleSet) - if !ok { - return nil, fmt.Errorf("error of converting vmSet (%q) to scaleSet with vmType %q", c.cloud.vmSet, c.cloud.VMType) + attached := make(map[string]bool) + for _, diskName := range diskNames { + attached[diskName] = false } - // 3. If the node is managed by availability set, then check with availabilitySet.DisksAreAttached. - managedByAS, err := ss.isNodeManagedByAvailabilitySet(mapNodeNameToVMName(nodeName)) + disks, err := c.getNodeDataDisks(nodeName) if err != nil { - return nil, err + if err == cloudprovider.InstanceNotFound { + // if host doesn't exist, no need to detach + glog.Warningf("azureDisk - Cannot find node %q, DisksAreAttached will assume disks %v are not attached to it.", + nodeName, diskNames) + return attached, nil + } + + return attached, err } - if managedByAS { - // vm is managed by availability set. - return ss.availabilitySet.DisksAreAttached(diskNames, nodeName) + + for _, disk := range disks { + for _, diskName := range diskNames { + if disk.Name != nil && diskName != "" && *disk.Name == diskName { + attached[diskName] = true + } + } } - // 4. Node is managed by vmss, check with scaleSet.DisksAreAttached. - return ss.DisksAreAttached(diskNames, nodeName) + return attached, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_standard.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_standard.go index 5563f4cf7..63ef47ffc 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_standard.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_standard.go @@ -20,11 +20,10 @@ import ( "fmt" "strings" - "github.com/Azure/azure-sdk-for-go/arm/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" "github.com/golang/glog" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/cloudprovider" ) // AttachDisk attaches a vhd to vm @@ -70,10 +69,10 @@ func (as *availabilitySet) AttachDisk(isManagedDisk bool, diskName, diskURI stri } vmName := mapNodeNameToVMName(nodeName) glog.V(2).Infof("azureDisk - update(%s): vm(%s) - attach disk", as.resourceGroup, vmName) - respChan, errChan := as.VirtualMachinesClient.CreateOrUpdate(as.resourceGroup, vmName, newVM, nil) - resp := <-respChan - err = <-errChan - if as.CloudProviderBackoff && shouldRetryAPIRequest(resp.Response, err) { + ctx, cancel := getContextWithCancel() + defer cancel() + resp, err := as.VirtualMachinesClient.CreateOrUpdate(ctx, as.resourceGroup, vmName, newVM) + if as.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { glog.V(2).Infof("azureDisk - update(%s) backing off: vm(%s)", as.resourceGroup, vmName) retryErr := as.CreateOrUpdateVMWithRetry(vmName, newVM) if retryErr != nil { @@ -135,10 +134,10 @@ func (as *availabilitySet) DetachDiskByName(diskName, diskURI string, nodeName t } vmName := mapNodeNameToVMName(nodeName) glog.V(2).Infof("azureDisk - update(%s): vm(%s) - detach disk", as.resourceGroup, vmName) - respChan, errChan := as.VirtualMachinesClient.CreateOrUpdate(as.resourceGroup, vmName, newVM, nil) - resp := <-respChan - err = <-errChan - if as.CloudProviderBackoff && shouldRetryAPIRequest(resp.Response, err) { + ctx, cancel := getContextWithCancel() + defer cancel() + resp, err := as.VirtualMachinesClient.CreateOrUpdate(ctx, as.resourceGroup, vmName, newVM) + if as.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { glog.V(2).Infof("azureDisk - update(%s) backing off: vm(%s)", as.resourceGroup, vmName) retryErr := as.CreateOrUpdateVMWithRetry(vmName, newVM) if retryErr != nil { @@ -156,71 +155,16 @@ func (as *availabilitySet) DetachDiskByName(diskName, diskURI string, nodeName t return err } -// GetDiskLun finds the lun on the host that the vhd is attached to, given a vhd's diskName and diskURI -func (as *availabilitySet) GetDiskLun(diskName, diskURI string, nodeName types.NodeName) (int32, error) { +// GetDataDisks gets a list of data disks attached to the node. +func (as *availabilitySet) GetDataDisks(nodeName types.NodeName) ([]compute.DataDisk, error) { vm, err := as.getVirtualMachine(nodeName) if err != nil { - return -1, err - } - disks := *vm.StorageProfile.DataDisks - for _, disk := range disks { - if disk.Lun != nil && (disk.Name != nil && diskName != "" && *disk.Name == diskName) || - (disk.Vhd != nil && disk.Vhd.URI != nil && diskURI != "" && *disk.Vhd.URI == diskURI) || - (disk.ManagedDisk != nil && *disk.ManagedDisk.ID == diskURI) { - // found the disk - glog.V(4).Infof("azureDisk - find disk: lun %d name %q uri %q", *disk.Lun, diskName, diskURI) - return *disk.Lun, nil - } - } - return -1, fmt.Errorf("Cannot find Lun for disk %s", diskName) -} - -// GetNextDiskLun searches all vhd attachment on the host and find unused lun -// return -1 if all luns are used -func (as *availabilitySet) GetNextDiskLun(nodeName types.NodeName) (int32, error) { - vm, err := as.getVirtualMachine(nodeName) - if err != nil { - return -1, err - } - used := make([]bool, maxLUN) - disks := *vm.StorageProfile.DataDisks - for _, disk := range disks { - if disk.Lun != nil { - used[*disk.Lun] = true - } - } - for k, v := range used { - if !v { - return int32(k), nil - } - } - return -1, fmt.Errorf("All Luns are used") -} - -// DisksAreAttached checks if a list of volumes are attached to the node with the specified NodeName -func (as *availabilitySet) DisksAreAttached(diskNames []string, nodeName types.NodeName) (map[string]bool, error) { - attached := make(map[string]bool) - for _, diskName := range diskNames { - attached[diskName] = false - } - vm, err := as.getVirtualMachine(nodeName) - if err == cloudprovider.InstanceNotFound { - // if host doesn't exist, no need to detach - glog.Warningf("azureDisk - Cannot find node %q, DisksAreAttached will assume disks %v are not attached to it.", - nodeName, diskNames) - return attached, nil - } else if err != nil { - return attached, err + return nil, err } - disks := *vm.StorageProfile.DataDisks - for _, disk := range disks { - for _, diskName := range diskNames { - if disk.Name != nil && diskName != "" && *disk.Name == diskName { - attached[diskName] = true - } - } + if vm.StorageProfile.DataDisks == nil { + return nil, nil } - return attached, nil + return *vm.StorageProfile.DataDisks, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_vmss.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_vmss.go index ea07a8a30..76e3f1261 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_vmss.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_controller_vmss.go @@ -20,12 +20,10 @@ import ( "fmt" "strings" - "github.com/Azure/azure-sdk-for-go/arm/compute" - computepreview "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" "github.com/golang/glog" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/cloudprovider" ) // AttachDisk attaches a vhd to vm @@ -36,27 +34,30 @@ func (ss *scaleSet) AttachDisk(isManagedDisk bool, diskName, diskURI string, nod return err } - disks := *vm.StorageProfile.DataDisks + disks := []compute.DataDisk{} + if vm.StorageProfile != nil && vm.StorageProfile.DataDisks != nil { + disks = *vm.StorageProfile.DataDisks + } if isManagedDisk { disks = append(disks, - computepreview.DataDisk{ + compute.DataDisk{ Name: &diskName, Lun: &lun, - Caching: computepreview.CachingTypes(cachingMode), + Caching: compute.CachingTypes(cachingMode), CreateOption: "attach", - ManagedDisk: &computepreview.ManagedDiskParameters{ + ManagedDisk: &compute.ManagedDiskParameters{ ID: &diskURI, }, }) } else { disks = append(disks, - computepreview.DataDisk{ + compute.DataDisk{ Name: &diskName, - Vhd: &computepreview.VirtualHardDisk{ + Vhd: &compute.VirtualHardDisk{ URI: &diskURI, }, Lun: &lun, - Caching: computepreview.CachingTypes(cachingMode), + Caching: compute.CachingTypes(cachingMode), CreateOption: "attach", }) } @@ -97,7 +98,10 @@ func (ss *scaleSet) DetachDiskByName(diskName, diskURI string, nodeName types.No return err } - disks := *vm.StorageProfile.DataDisks + disks := []compute.DataDisk{} + if vm.StorageProfile != nil && vm.StorageProfile.DataDisks != nil { + disks = *vm.StorageProfile.DataDisks + } bFoundDisk := false for i, disk := range disks { if disk.Lun != nil && (disk.Name != nil && diskName != "" && *disk.Name == diskName) || @@ -139,76 +143,16 @@ func (ss *scaleSet) DetachDiskByName(diskName, diskURI string, nodeName types.No return err } -// GetDiskLun finds the lun on the host that the vhd is attached to, given a vhd's diskName and diskURI -func (ss *scaleSet) GetDiskLun(diskName, diskURI string, nodeName types.NodeName) (int32, error) { - _, _, vm, err := ss.getVmssVM(string(nodeName)) - if err != nil { - return -1, err - } - - disks := *vm.StorageProfile.DataDisks - for _, disk := range disks { - if disk.Lun != nil && (disk.Name != nil && diskName != "" && *disk.Name == diskName) || - (disk.Vhd != nil && disk.Vhd.URI != nil && diskURI != "" && *disk.Vhd.URI == diskURI) || - (disk.ManagedDisk != nil && *disk.ManagedDisk.ID == diskURI) { - // found the disk - glog.V(4).Infof("azureDisk - find disk: lun %d name %q uri %q", *disk.Lun, diskName, diskURI) - return *disk.Lun, nil - } - } - return -1, fmt.Errorf("Cannot find Lun for disk %s", diskName) -} - -// GetNextDiskLun searches all vhd attachment on the host and find unused lun -// return -1 if all luns are used -func (ss *scaleSet) GetNextDiskLun(nodeName types.NodeName) (int32, error) { - _, _, vm, err := ss.getVmssVM(string(nodeName)) - if err != nil { - return -1, err - } - - used := make([]bool, maxLUN) - disks := *vm.StorageProfile.DataDisks - for _, disk := range disks { - if disk.Lun != nil { - used[*disk.Lun] = true - } - } - for k, v := range used { - if !v { - return int32(k), nil - } - } - return -1, fmt.Errorf("All Luns are used") -} - -// DisksAreAttached checks if a list of volumes are attached to the node with the specified NodeName -func (ss *scaleSet) DisksAreAttached(diskNames []string, nodeName types.NodeName) (map[string]bool, error) { - attached := make(map[string]bool) - for _, diskName := range diskNames { - attached[diskName] = false - } - +// GetDataDisks gets a list of data disks attached to the node. +func (ss *scaleSet) GetDataDisks(nodeName types.NodeName) ([]compute.DataDisk, error) { _, _, vm, err := ss.getVmssVM(string(nodeName)) if err != nil { - if err == cloudprovider.InstanceNotFound { - // if host doesn't exist, no need to detach - glog.Warningf("azureDisk - Cannot find node %q, DisksAreAttached will assume disks %v are not attached to it.", - nodeName, diskNames) - return attached, nil - } - - return attached, err + return nil, err } - disks := *vm.StorageProfile.DataDisks - for _, disk := range disks { - for _, diskName := range diskNames { - if disk.Name != nil && diskName != "" && *disk.Name == diskName { - attached[diskName] = true - } - } + if vm.StorageProfile == nil || vm.StorageProfile.DataDisks == nil { + return nil, nil } - return attached, nil + return *vm.StorageProfile.DataDisks, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_fakes.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_fakes.go index 69be811de..a79e7e190 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_fakes.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_fakes.go @@ -29,11 +29,9 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/cloudprovider" - "github.com/Azure/azure-sdk-for-go/arm/compute" - "github.com/Azure/azure-sdk-for-go/arm/disk" - "github.com/Azure/azure-sdk-for-go/arm/network" - "github.com/Azure/azure-sdk-for-go/arm/storage" - computepreview "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/to" ) @@ -50,19 +48,10 @@ func newFakeAzureLBClient() *fakeAzureLBClient { return fLBC } -func (fLBC *fakeAzureLBClient) CreateOrUpdate(resourceGroupName string, loadBalancerName string, parameters network.LoadBalancer, cancel <-chan struct{}) (<-chan network.LoadBalancer, <-chan error) { +func (fLBC *fakeAzureLBClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, loadBalancerName string, parameters network.LoadBalancer) (resp *http.Response, err error) { fLBC.mutex.Lock() defer fLBC.mutex.Unlock() - resultChan := make(chan network.LoadBalancer, 1) - errChan := make(chan error, 1) - var result network.LoadBalancer - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() + if _, ok := fLBC.FakeStore[resourceGroupName]; !ok { fLBC.FakeStore[resourceGroupName] = make(map[string]network.LoadBalancer) } @@ -78,48 +67,27 @@ func (fLBC *fakeAzureLBClient) CreateOrUpdate(resourceGroupName string, loadBala } } fLBC.FakeStore[resourceGroupName][loadBalancerName] = parameters - result = fLBC.FakeStore[resourceGroupName][loadBalancerName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + + return nil, nil } -func (fLBC *fakeAzureLBClient) Delete(resourceGroupName string, loadBalancerName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (fLBC *fakeAzureLBClient) Delete(ctx context.Context, resourceGroupName string, loadBalancerName string) (resp *http.Response, err error) { fLBC.mutex.Lock() defer fLBC.mutex.Unlock() - respChan := make(chan autorest.Response, 1) - errChan := make(chan error, 1) - var resp autorest.Response - var err error - defer func() { - respChan <- resp - errChan <- err - close(respChan) - close(errChan) - }() + if rgLBs, ok := fLBC.FakeStore[resourceGroupName]; ok { if _, ok := rgLBs[loadBalancerName]; ok { delete(rgLBs, loadBalancerName) - resp.Response = &http.Response{ - StatusCode: http.StatusAccepted, - } - err = nil - return respChan, errChan + return nil, nil } } - resp.Response = &http.Response{ - StatusCode: http.StatusNotFound, - } - err = autorest.DetailedError{ + + return &http.Response{ StatusCode: http.StatusNotFound, - Message: "Not such LB", - } - return respChan, errChan + }, nil } -func (fLBC *fakeAzureLBClient) Get(resourceGroupName string, loadBalancerName string, expand string) (result network.LoadBalancer, err error) { +func (fLBC *fakeAzureLBClient) Get(ctx context.Context, resourceGroupName string, loadBalancerName string, expand string) (result network.LoadBalancer, err error) { fLBC.mutex.Lock() defer fLBC.mutex.Unlock() if _, ok := fLBC.FakeStore[resourceGroupName]; ok { @@ -133,32 +101,17 @@ func (fLBC *fakeAzureLBClient) Get(resourceGroupName string, loadBalancerName st } } -func (fLBC *fakeAzureLBClient) List(resourceGroupName string) (result network.LoadBalancerListResult, err error) { +func (fLBC *fakeAzureLBClient) List(ctx context.Context, resourceGroupName string) (result []network.LoadBalancer, err error) { fLBC.mutex.Lock() defer fLBC.mutex.Unlock() + var value []network.LoadBalancer if _, ok := fLBC.FakeStore[resourceGroupName]; ok { for _, v := range fLBC.FakeStore[resourceGroupName] { value = append(value, v) } } - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - result.NextLink = nil - result.Value = &value - return result, nil -} - -func (fLBC *fakeAzureLBClient) ListNextResults(resourceGroupName string, lastResult network.LoadBalancerListResult) (result network.LoadBalancerListResult, err error) { - fLBC.mutex.Lock() - defer fLBC.mutex.Unlock() - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - result.NextLink = nil - result.Value = nil - return result, nil + return value, nil } type fakeAzurePIPClient struct { @@ -186,19 +139,10 @@ func newFakeAzurePIPClient(subscriptionID string) *fakeAzurePIPClient { return fAPC } -func (fAPC *fakeAzurePIPClient) CreateOrUpdate(resourceGroupName string, publicIPAddressName string, parameters network.PublicIPAddress, cancel <-chan struct{}) (<-chan network.PublicIPAddress, <-chan error) { +func (fAPC *fakeAzurePIPClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, publicIPAddressName string, parameters network.PublicIPAddress) (resp *http.Response, err error) { fAPC.mutex.Lock() defer fAPC.mutex.Unlock() - resultChan := make(chan network.PublicIPAddress, 1) - errChan := make(chan error, 1) - var result network.PublicIPAddress - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() + if _, ok := fAPC.FakeStore[resourceGroupName]; !ok { fAPC.FakeStore[resourceGroupName] = make(map[string]network.PublicIPAddress) } @@ -215,48 +159,27 @@ func (fAPC *fakeAzurePIPClient) CreateOrUpdate(resourceGroupName string, publicI } fAPC.FakeStore[resourceGroupName][publicIPAddressName] = parameters - result = fAPC.FakeStore[resourceGroupName][publicIPAddressName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + + return nil, nil } -func (fAPC *fakeAzurePIPClient) Delete(resourceGroupName string, publicIPAddressName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (fAPC *fakeAzurePIPClient) Delete(ctx context.Context, resourceGroupName string, publicIPAddressName string) (resp *http.Response, err error) { fAPC.mutex.Lock() defer fAPC.mutex.Unlock() - respChan := make(chan autorest.Response, 1) - errChan := make(chan error, 1) - var resp autorest.Response - var err error - defer func() { - respChan <- resp - errChan <- err - close(respChan) - close(errChan) - }() + if rgPIPs, ok := fAPC.FakeStore[resourceGroupName]; ok { if _, ok := rgPIPs[publicIPAddressName]; ok { delete(rgPIPs, publicIPAddressName) - resp.Response = &http.Response{ - StatusCode: http.StatusAccepted, - } - err = nil - return respChan, errChan + return nil, nil } } - resp.Response = &http.Response{ - StatusCode: http.StatusNotFound, - } - err = autorest.DetailedError{ + + return &http.Response{ StatusCode: http.StatusNotFound, - Message: "Not such PIP", - } - return respChan, errChan + }, nil } -func (fAPC *fakeAzurePIPClient) Get(resourceGroupName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) { +func (fAPC *fakeAzurePIPClient) Get(ctx context.Context, resourceGroupName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err error) { fAPC.mutex.Lock() defer fAPC.mutex.Unlock() if _, ok := fAPC.FakeStore[resourceGroupName]; ok { @@ -270,27 +193,18 @@ func (fAPC *fakeAzurePIPClient) Get(resourceGroupName string, publicIPAddressNam } } -func (fAPC *fakeAzurePIPClient) ListNextResults(resourceGroupName string, lastResults network.PublicIPAddressListResult) (result network.PublicIPAddressListResult, err error) { +func (fAPC *fakeAzurePIPClient) List(ctx context.Context, resourceGroupName string) (result []network.PublicIPAddress, err error) { fAPC.mutex.Lock() defer fAPC.mutex.Unlock() - return network.PublicIPAddressListResult{}, nil -} -func (fAPC *fakeAzurePIPClient) List(resourceGroupName string) (result network.PublicIPAddressListResult, err error) { - fAPC.mutex.Lock() - defer fAPC.mutex.Unlock() var value []network.PublicIPAddress if _, ok := fAPC.FakeStore[resourceGroupName]; ok { for _, v := range fAPC.FakeStore[resourceGroupName] { value = append(value, v) } } - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - result.NextLink = nil - result.Value = &value - return result, nil + + return value, nil } type fakeAzureInterfacesClient struct { @@ -306,33 +220,19 @@ func newFakeAzureInterfacesClient() *fakeAzureInterfacesClient { return fIC } -func (fIC *fakeAzureInterfacesClient) CreateOrUpdate(resourceGroupName string, networkInterfaceName string, parameters network.Interface, cancel <-chan struct{}) (<-chan network.Interface, <-chan error) { +func (fIC *fakeAzureInterfacesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, networkInterfaceName string, parameters network.Interface) (resp *http.Response, err error) { fIC.mutex.Lock() defer fIC.mutex.Unlock() - resultChan := make(chan network.Interface, 1) - errChan := make(chan error, 1) - var result network.Interface - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() + if _, ok := fIC.FakeStore[resourceGroupName]; !ok { fIC.FakeStore[resourceGroupName] = make(map[string]network.Interface) } fIC.FakeStore[resourceGroupName][networkInterfaceName] = parameters - result = fIC.FakeStore[resourceGroupName][networkInterfaceName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + return nil, nil } -func (fIC *fakeAzureInterfacesClient) Get(resourceGroupName string, networkInterfaceName string, expand string) (result network.Interface, err error) { +func (fIC *fakeAzureInterfacesClient) Get(ctx context.Context, resourceGroupName string, networkInterfaceName string, expand string) (result network.Interface, err error) { fIC.mutex.Lock() defer fIC.mutex.Unlock() if _, ok := fIC.FakeStore[resourceGroupName]; ok { @@ -346,7 +246,7 @@ func (fIC *fakeAzureInterfacesClient) Get(resourceGroupName string, networkInter } } -func (fIC *fakeAzureInterfacesClient) GetVirtualMachineScaleSetNetworkInterface(resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, expand string) (result network.Interface, err error) { +func (fIC *fakeAzureInterfacesClient) GetVirtualMachineScaleSetNetworkInterface(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, expand string) (result network.Interface, err error) { return result, nil } @@ -362,32 +262,19 @@ func newFakeAzureVirtualMachinesClient() *fakeAzureVirtualMachinesClient { return fVMC } -func (fVMC *fakeAzureVirtualMachinesClient) CreateOrUpdate(resourceGroupName string, VMName string, parameters compute.VirtualMachine, cancel <-chan struct{}) (<-chan compute.VirtualMachine, <-chan error) { +func (fVMC *fakeAzureVirtualMachinesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, VMName string, parameters compute.VirtualMachine) (resp *http.Response, err error) { fVMC.mutex.Lock() defer fVMC.mutex.Unlock() - resultChan := make(chan compute.VirtualMachine, 1) - errChan := make(chan error, 1) - var result compute.VirtualMachine - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() + if _, ok := fVMC.FakeStore[resourceGroupName]; !ok { fVMC.FakeStore[resourceGroupName] = make(map[string]compute.VirtualMachine) } fVMC.FakeStore[resourceGroupName][VMName] = parameters - result = fVMC.FakeStore[resourceGroupName][VMName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + + return nil, nil } -func (fVMC *fakeAzureVirtualMachinesClient) Get(resourceGroupName string, VMName string, expand compute.InstanceViewTypes) (result compute.VirtualMachine, err error) { +func (fVMC *fakeAzureVirtualMachinesClient) Get(ctx context.Context, resourceGroupName string, VMName string, expand compute.InstanceViewTypes) (result compute.VirtualMachine, err error) { fVMC.mutex.Lock() defer fVMC.mutex.Unlock() if _, ok := fVMC.FakeStore[resourceGroupName]; ok { @@ -401,27 +288,19 @@ func (fVMC *fakeAzureVirtualMachinesClient) Get(resourceGroupName string, VMName } } -func (fVMC *fakeAzureVirtualMachinesClient) List(resourceGroupName string) (result compute.VirtualMachineListResult, err error) { +func (fVMC *fakeAzureVirtualMachinesClient) List(ctx context.Context, resourceGroupName string) (result []compute.VirtualMachine, err error) { fVMC.mutex.Lock() defer fVMC.mutex.Unlock() - var value []compute.VirtualMachine + + result = []compute.VirtualMachine{} if _, ok := fVMC.FakeStore[resourceGroupName]; ok { for _, v := range fVMC.FakeStore[resourceGroupName] { - value = append(value, v) + result = append(result, v) } } - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - result.NextLink = nil - result.Value = &value + return result, nil } -func (fVMC *fakeAzureVirtualMachinesClient) ListNextResults(resourceGroupName string, lastResults compute.VirtualMachineListResult) (result compute.VirtualMachineListResult, err error) { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - return compute.VirtualMachineListResult{}, nil -} type fakeAzureSubnetsClient struct { mutex *sync.Mutex @@ -435,67 +314,37 @@ func newFakeAzureSubnetsClient() *fakeAzureSubnetsClient { return fASC } -func (fASC *fakeAzureSubnetsClient) CreateOrUpdate(resourceGroupName string, virtualNetworkName string, subnetName string, subnetParameters network.Subnet, cancel <-chan struct{}) (<-chan network.Subnet, <-chan error) { +func (fASC *fakeAzureSubnetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string, subnetParameters network.Subnet) (resp *http.Response, err error) { fASC.mutex.Lock() defer fASC.mutex.Unlock() - resultChan := make(chan network.Subnet, 1) - errChan := make(chan error, 1) - var result network.Subnet - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() + rgVnet := strings.Join([]string{resourceGroupName, virtualNetworkName}, "AND") if _, ok := fASC.FakeStore[rgVnet]; !ok { fASC.FakeStore[rgVnet] = make(map[string]network.Subnet) } fASC.FakeStore[rgVnet][subnetName] = subnetParameters - result = fASC.FakeStore[rgVnet][subnetName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + + return nil, nil } -func (fASC *fakeAzureSubnetsClient) Delete(resourceGroupName string, virtualNetworkName string, subnetName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (fASC *fakeAzureSubnetsClient) Delete(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string) (resp *http.Response, err error) { fASC.mutex.Lock() defer fASC.mutex.Unlock() - respChan := make(chan autorest.Response, 1) - errChan := make(chan error, 1) - var resp autorest.Response - var err error - defer func() { - respChan <- resp - errChan <- err - close(respChan) - close(errChan) - }() rgVnet := strings.Join([]string{resourceGroupName, virtualNetworkName}, "AND") if rgSubnets, ok := fASC.FakeStore[rgVnet]; ok { if _, ok := rgSubnets[subnetName]; ok { delete(rgSubnets, subnetName) - resp.Response = &http.Response{ - StatusCode: http.StatusAccepted, - } - err = nil - return respChan, errChan + return nil, nil } } - resp.Response = &http.Response{ - StatusCode: http.StatusNotFound, - } - err = autorest.DetailedError{ + + return &http.Response{ StatusCode: http.StatusNotFound, - Message: "Not such Subnet", - } - return respChan, errChan + }, nil } -func (fASC *fakeAzureSubnetsClient) Get(resourceGroupName string, virtualNetworkName string, subnetName string, expand string) (result network.Subnet, err error) { + +func (fASC *fakeAzureSubnetsClient) Get(ctx context.Context, resourceGroupName string, virtualNetworkName string, subnetName string, expand string) (result network.Subnet, err error) { fASC.mutex.Lock() defer fASC.mutex.Unlock() rgVnet := strings.Join([]string{resourceGroupName, virtualNetworkName}, "AND") @@ -509,9 +358,11 @@ func (fASC *fakeAzureSubnetsClient) Get(resourceGroupName string, virtualNetwork Message: "Not such Subnet", } } -func (fASC *fakeAzureSubnetsClient) List(resourceGroupName string, virtualNetworkName string) (result network.SubnetListResult, err error) { + +func (fASC *fakeAzureSubnetsClient) List(ctx context.Context, resourceGroupName string, virtualNetworkName string) (result []network.Subnet, err error) { fASC.mutex.Lock() defer fASC.mutex.Unlock() + rgVnet := strings.Join([]string{resourceGroupName, virtualNetworkName}, "AND") var value []network.Subnet if _, ok := fASC.FakeStore[rgVnet]; ok { @@ -519,12 +370,8 @@ func (fASC *fakeAzureSubnetsClient) List(resourceGroupName string, virtualNetwor value = append(value, v) } } - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - result.NextLink = nil - result.Value = &value - return result, nil + + return value, nil } type fakeAzureNSGClient struct { @@ -539,65 +386,35 @@ func newFakeAzureNSGClient() *fakeAzureNSGClient { return fNSG } -func (fNSG *fakeAzureNSGClient) CreateOrUpdate(resourceGroupName string, networkSecurityGroupName string, parameters network.SecurityGroup, cancel <-chan struct{}) (<-chan network.SecurityGroup, <-chan error) { +func (fNSG *fakeAzureNSGClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, parameters network.SecurityGroup) (resp *http.Response, err error) { fNSG.mutex.Lock() defer fNSG.mutex.Unlock() - resultChan := make(chan network.SecurityGroup, 1) - errChan := make(chan error, 1) - var result network.SecurityGroup - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() + if _, ok := fNSG.FakeStore[resourceGroupName]; !ok { fNSG.FakeStore[resourceGroupName] = make(map[string]network.SecurityGroup) } fNSG.FakeStore[resourceGroupName][networkSecurityGroupName] = parameters - result = fNSG.FakeStore[resourceGroupName][networkSecurityGroupName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + + return nil, nil } -func (fNSG *fakeAzureNSGClient) Delete(resourceGroupName string, networkSecurityGroupName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (fNSG *fakeAzureNSGClient) Delete(ctx context.Context, resourceGroupName string, networkSecurityGroupName string) (resp *http.Response, err error) { fNSG.mutex.Lock() defer fNSG.mutex.Unlock() - respChan := make(chan autorest.Response, 1) - errChan := make(chan error, 1) - var resp autorest.Response - var err error - defer func() { - respChan <- resp - errChan <- err - close(respChan) - close(errChan) - }() + if rgSGs, ok := fNSG.FakeStore[resourceGroupName]; ok { if _, ok := rgSGs[networkSecurityGroupName]; ok { delete(rgSGs, networkSecurityGroupName) - resp.Response = &http.Response{ - StatusCode: http.StatusAccepted, - } - err = nil - return respChan, errChan + return nil, nil } } - resp.Response = &http.Response{ - StatusCode: http.StatusNotFound, - } - err = autorest.DetailedError{ + + return &http.Response{ StatusCode: http.StatusNotFound, - Message: "Not such NSG", - } - return respChan, errChan + }, nil } -func (fNSG *fakeAzureNSGClient) Get(resourceGroupName string, networkSecurityGroupName string, expand string) (result network.SecurityGroup, err error) { +func (fNSG *fakeAzureNSGClient) Get(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, expand string) (result network.SecurityGroup, err error) { fNSG.mutex.Lock() defer fNSG.mutex.Unlock() if _, ok := fNSG.FakeStore[resourceGroupName]; ok { @@ -611,21 +428,18 @@ func (fNSG *fakeAzureNSGClient) Get(resourceGroupName string, networkSecurityGro } } -func (fNSG *fakeAzureNSGClient) List(resourceGroupName string) (result network.SecurityGroupListResult, err error) { +func (fNSG *fakeAzureNSGClient) List(ctx context.Context, resourceGroupName string) (result []network.SecurityGroup, err error) { fNSG.mutex.Lock() defer fNSG.mutex.Unlock() + var value []network.SecurityGroup if _, ok := fNSG.FakeStore[resourceGroupName]; ok { for _, v := range fNSG.FakeStore[resourceGroupName] { value = append(value, v) } } - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - result.NextLink = nil - result.Value = &value - return result, nil + + return value, nil } func getRandomIPPtr() *string { @@ -635,29 +449,29 @@ func getRandomIPPtr() *string { type fakeVirtualMachineScaleSetVMsClient struct { mutex *sync.Mutex - FakeStore map[string]map[string]computepreview.VirtualMachineScaleSetVM + FakeStore map[string]map[string]compute.VirtualMachineScaleSetVM } func newFakeVirtualMachineScaleSetVMsClient() *fakeVirtualMachineScaleSetVMsClient { fVMC := &fakeVirtualMachineScaleSetVMsClient{} - fVMC.FakeStore = make(map[string]map[string]computepreview.VirtualMachineScaleSetVM) + fVMC.FakeStore = make(map[string]map[string]compute.VirtualMachineScaleSetVM) fVMC.mutex = &sync.Mutex{} return fVMC } -func (fVMC *fakeVirtualMachineScaleSetVMsClient) setFakeStore(store map[string]map[string]computepreview.VirtualMachineScaleSetVM) { +func (fVMC *fakeVirtualMachineScaleSetVMsClient) setFakeStore(store map[string]map[string]compute.VirtualMachineScaleSetVM) { fVMC.mutex.Lock() defer fVMC.mutex.Unlock() fVMC.FakeStore = store } -func (fVMC *fakeVirtualMachineScaleSetVMsClient) List(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result []computepreview.VirtualMachineScaleSetVM, err error) { +func (fVMC *fakeVirtualMachineScaleSetVMsClient) List(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result []compute.VirtualMachineScaleSetVM, err error) { fVMC.mutex.Lock() defer fVMC.mutex.Unlock() - result = []computepreview.VirtualMachineScaleSetVM{} + result = []compute.VirtualMachineScaleSetVM{} if _, ok := fVMC.FakeStore[resourceGroupName]; ok { for _, v := range fVMC.FakeStore[resourceGroupName] { result = append(result, v) @@ -667,7 +481,7 @@ func (fVMC *fakeVirtualMachineScaleSetVMsClient) List(ctx context.Context, resou return result, nil } -func (fVMC *fakeVirtualMachineScaleSetVMsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result computepreview.VirtualMachineScaleSetVM, err error) { +func (fVMC *fakeVirtualMachineScaleSetVMsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result compute.VirtualMachineScaleSetVM, err error) { fVMC.mutex.Lock() defer fVMC.mutex.Unlock() @@ -684,7 +498,7 @@ func (fVMC *fakeVirtualMachineScaleSetVMsClient) Get(ctx context.Context, resour } } -func (fVMC *fakeVirtualMachineScaleSetVMsClient) GetInstanceView(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result computepreview.VirtualMachineScaleSetVMInstanceView, err error) { +func (fVMC *fakeVirtualMachineScaleSetVMsClient) GetInstanceView(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string) (result compute.VirtualMachineScaleSetVMInstanceView, err error) { _, err = fVMC.Get(ctx, resourceGroupName, VMScaleSetName, instanceID) if err != nil { return result, err @@ -693,7 +507,7 @@ func (fVMC *fakeVirtualMachineScaleSetVMsClient) GetInstanceView(ctx context.Con return result, nil } -func (fVMC *fakeVirtualMachineScaleSetVMsClient) Update(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters computepreview.VirtualMachineScaleSetVM) (resp *http.Response, err error) { +func (fVMC *fakeVirtualMachineScaleSetVMsClient) Update(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters compute.VirtualMachineScaleSetVM) (resp *http.Response, err error) { fVMC.mutex.Lock() defer fVMC.mutex.Unlock() @@ -709,37 +523,37 @@ func (fVMC *fakeVirtualMachineScaleSetVMsClient) Update(ctx context.Context, res type fakeVirtualMachineScaleSetsClient struct { mutex *sync.Mutex - FakeStore map[string]map[string]computepreview.VirtualMachineScaleSet + FakeStore map[string]map[string]compute.VirtualMachineScaleSet } func newFakeVirtualMachineScaleSetsClient() *fakeVirtualMachineScaleSetsClient { fVMSSC := &fakeVirtualMachineScaleSetsClient{} - fVMSSC.FakeStore = make(map[string]map[string]computepreview.VirtualMachineScaleSet) + fVMSSC.FakeStore = make(map[string]map[string]compute.VirtualMachineScaleSet) fVMSSC.mutex = &sync.Mutex{} return fVMSSC } -func (fVMSSC *fakeVirtualMachineScaleSetsClient) setFakeStore(store map[string]map[string]computepreview.VirtualMachineScaleSet) { +func (fVMSSC *fakeVirtualMachineScaleSetsClient) setFakeStore(store map[string]map[string]compute.VirtualMachineScaleSet) { fVMSSC.mutex.Lock() defer fVMSSC.mutex.Unlock() fVMSSC.FakeStore = store } -func (fVMSSC *fakeVirtualMachineScaleSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters computepreview.VirtualMachineScaleSet) (resp *http.Response, err error) { +func (fVMSSC *fakeVirtualMachineScaleSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) (resp *http.Response, err error) { fVMSSC.mutex.Lock() defer fVMSSC.mutex.Unlock() if _, ok := fVMSSC.FakeStore[resourceGroupName]; !ok { - fVMSSC.FakeStore[resourceGroupName] = make(map[string]computepreview.VirtualMachineScaleSet) + fVMSSC.FakeStore[resourceGroupName] = make(map[string]compute.VirtualMachineScaleSet) } fVMSSC.FakeStore[resourceGroupName][VMScaleSetName] = parameters return nil, nil } -func (fVMSSC *fakeVirtualMachineScaleSetsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string) (result computepreview.VirtualMachineScaleSet, err error) { +func (fVMSSC *fakeVirtualMachineScaleSetsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string) (result compute.VirtualMachineScaleSet, err error) { fVMSSC.mutex.Lock() defer fVMSSC.mutex.Unlock() @@ -755,11 +569,11 @@ func (fVMSSC *fakeVirtualMachineScaleSetsClient) Get(ctx context.Context, resour } } -func (fVMSSC *fakeVirtualMachineScaleSetsClient) List(ctx context.Context, resourceGroupName string) (result []computepreview.VirtualMachineScaleSet, err error) { +func (fVMSSC *fakeVirtualMachineScaleSetsClient) List(ctx context.Context, resourceGroupName string) (result []compute.VirtualMachineScaleSet, err error) { fVMSSC.mutex.Lock() defer fVMSSC.mutex.Unlock() - result = []computepreview.VirtualMachineScaleSet{} + result = []compute.VirtualMachineScaleSet{} if _, ok := fVMSSC.FakeStore[resourceGroupName]; ok { for _, v := range fVMSSC.FakeStore[resourceGroupName] { result = append(result, v) @@ -769,7 +583,7 @@ func (fVMSSC *fakeVirtualMachineScaleSetsClient) List(ctx context.Context, resou return result, nil } -func (fVMSSC *fakeVirtualMachineScaleSetsClient) UpdateInstances(ctx context.Context, resourceGroupName string, VMScaleSetName string, VMInstanceIDs computepreview.VirtualMachineScaleSetVMInstanceRequiredIDs) (resp *http.Response, err error) { +func (fVMSSC *fakeVirtualMachineScaleSetsClient) UpdateInstances(ctx context.Context, resourceGroupName string, VMScaleSetName string, VMInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) (resp *http.Response, err error) { return nil, nil } @@ -785,66 +599,32 @@ func newFakeRoutesClient() *fakeRoutesClient { return fRC } -func (fRC *fakeRoutesClient) CreateOrUpdate(resourceGroupName string, routeTableName string, routeName string, routeParameters network.Route, cancel <-chan struct{}) (<-chan network.Route, <-chan error) { +func (fRC *fakeRoutesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, routeTableName string, routeName string, routeParameters network.Route) (resp *http.Response, err error) { fRC.mutex.Lock() defer fRC.mutex.Unlock() - resultChan := make(chan network.Route, 1) - errChan := make(chan error, 1) - var result network.Route - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() - if _, ok := fRC.FakeStore[routeTableName]; !ok { fRC.FakeStore[routeTableName] = make(map[string]network.Route) } fRC.FakeStore[routeTableName][routeName] = routeParameters - result = fRC.FakeStore[routeTableName][routeName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + + return nil, nil } -func (fRC *fakeRoutesClient) Delete(resourceGroupName string, routeTableName string, routeName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) { +func (fRC *fakeRoutesClient) Delete(ctx context.Context, resourceGroupName string, routeTableName string, routeName string) (resp *http.Response, err error) { fRC.mutex.Lock() defer fRC.mutex.Unlock() - respChan := make(chan autorest.Response, 1) - errChan := make(chan error, 1) - var resp autorest.Response - var err error - defer func() { - respChan <- resp - errChan <- err - close(respChan) - close(errChan) - }() if routes, ok := fRC.FakeStore[routeTableName]; ok { if _, ok := routes[routeName]; ok { delete(routes, routeName) - resp.Response = &http.Response{ - StatusCode: http.StatusAccepted, - } - - err = nil - return respChan, errChan + return nil, nil } } - resp.Response = &http.Response{ - StatusCode: http.StatusNotFound, - } - err = autorest.DetailedError{ + + return &http.Response{ StatusCode: http.StatusNotFound, - Message: "Not such Route", - } - return respChan, errChan + }, nil } type fakeRouteTablesClient struct { @@ -860,36 +640,21 @@ func newFakeRouteTablesClient() *fakeRouteTablesClient { return fRTC } -func (fRTC *fakeRouteTablesClient) CreateOrUpdate(resourceGroupName string, routeTableName string, parameters network.RouteTable, cancel <-chan struct{}) (<-chan network.RouteTable, <-chan error) { +func (fRTC *fakeRouteTablesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, routeTableName string, parameters network.RouteTable) (resp *http.Response, err error) { fRTC.mutex.Lock() defer fRTC.mutex.Unlock() fRTC.Calls = append(fRTC.Calls, "CreateOrUpdate") - resultChan := make(chan network.RouteTable, 1) - errChan := make(chan error, 1) - var result network.RouteTable - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() - if _, ok := fRTC.FakeStore[resourceGroupName]; !ok { fRTC.FakeStore[resourceGroupName] = make(map[string]network.RouteTable) } fRTC.FakeStore[resourceGroupName][routeTableName] = parameters - result = fRTC.FakeStore[resourceGroupName][routeTableName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + + return nil, nil } -func (fRTC *fakeRouteTablesClient) Get(resourceGroupName string, routeTableName string, expand string) (result network.RouteTable, err error) { +func (fRTC *fakeRouteTablesClient) Get(ctx context.Context, resourceGroupName string, routeTableName string, expand string) (result network.RouteTable, err error) { fRTC.mutex.Lock() defer fRTC.mutex.Unlock() @@ -936,21 +701,10 @@ func newFakeStorageAccountClient() *fakeStorageAccountClient { return fSAC } -func (fSAC *fakeStorageAccountClient) Create(resourceGroupName string, accountName string, parameters storage.AccountCreateParameters, cancel <-chan struct{}) (<-chan storage.Account, <-chan error) { +func (fSAC *fakeStorageAccountClient) Create(ctx context.Context, resourceGroupName string, accountName string, parameters storage.AccountCreateParameters) (resp *http.Response, err error) { fSAC.mutex.Lock() defer fSAC.mutex.Unlock() - resultChan := make(chan storage.Account, 1) - errChan := make(chan error, 1) - var result storage.Account - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() - if _, ok := fSAC.FakeStore[resourceGroupName]; !ok { fSAC.FakeStore[resourceGroupName] = make(map[string]storage.Account) } @@ -963,15 +717,11 @@ func (fSAC *fakeStorageAccountClient) Create(resourceGroupName string, accountNa Tags: parameters.Tags, AccountProperties: &storage.AccountProperties{}, } - result = fSAC.FakeStore[resourceGroupName][accountName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + + return nil, nil } -func (fSAC *fakeStorageAccountClient) Delete(resourceGroupName string, accountName string) (result autorest.Response, err error) { +func (fSAC *fakeStorageAccountClient) Delete(ctx context.Context, resourceGroupName string, accountName string) (result autorest.Response, err error) { fSAC.mutex.Lock() defer fSAC.mutex.Unlock() @@ -995,15 +745,15 @@ func (fSAC *fakeStorageAccountClient) Delete(resourceGroupName string, accountNa return result, err } -func (fSAC *fakeStorageAccountClient) ListKeys(resourceGroupName string, accountName string) (result storage.AccountListKeysResult, err error) { +func (fSAC *fakeStorageAccountClient) ListKeys(ctx context.Context, resourceGroupName string, accountName string) (result storage.AccountListKeysResult, err error) { return fSAC.Keys, fSAC.Err } -func (fSAC *fakeStorageAccountClient) ListByResourceGroup(resourceGroupName string) (result storage.AccountListResult, err error) { +func (fSAC *fakeStorageAccountClient) ListByResourceGroup(ctx context.Context, resourceGroupName string) (result storage.AccountListResult, err error) { return fSAC.Accounts, fSAC.Err } -func (fSAC *fakeStorageAccountClient) GetProperties(resourceGroupName string, accountName string) (result storage.Account, err error) { +func (fSAC *fakeStorageAccountClient) GetProperties(ctx context.Context, resourceGroupName string, accountName string) (result storage.Account, err error) { fSAC.mutex.Lock() defer fSAC.mutex.Unlock() @@ -1021,83 +771,45 @@ func (fSAC *fakeStorageAccountClient) GetProperties(resourceGroupName string, ac type fakeDisksClient struct { mutex *sync.Mutex - FakeStore map[string]map[string]disk.Model + FakeStore map[string]map[string]compute.Disk } func newFakeDisksClient() *fakeDisksClient { fDC := &fakeDisksClient{} - fDC.FakeStore = make(map[string]map[string]disk.Model) + fDC.FakeStore = make(map[string]map[string]compute.Disk) fDC.mutex = &sync.Mutex{} return fDC } -func (fDC *fakeDisksClient) CreateOrUpdate(resourceGroupName string, diskName string, diskParameter disk.Model, cancel <-chan struct{}) (<-chan disk.Model, <-chan error) { +func (fDC *fakeDisksClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, diskName string, diskParameter compute.Disk) (resp *http.Response, err error) { fDC.mutex.Lock() defer fDC.mutex.Unlock() - resultChan := make(chan disk.Model, 1) - errChan := make(chan error, 1) - var result disk.Model - var err error - defer func() { - resultChan <- result - errChan <- err - close(resultChan) - close(errChan) - }() - if _, ok := fDC.FakeStore[resourceGroupName]; !ok { - fDC.FakeStore[resourceGroupName] = make(map[string]disk.Model) + fDC.FakeStore[resourceGroupName] = make(map[string]compute.Disk) } fDC.FakeStore[resourceGroupName][diskName] = diskParameter - result = fDC.FakeStore[resourceGroupName][diskName] - result.Response.Response = &http.Response{ - StatusCode: http.StatusOK, - } - err = nil - return resultChan, errChan + + return nil, nil } -func (fDC *fakeDisksClient) Delete(resourceGroupName string, diskName string, cancel <-chan struct{}) (<-chan disk.OperationStatusResponse, <-chan error) { +func (fDC *fakeDisksClient) Delete(ctx context.Context, resourceGroupName string, diskName string) (resp *http.Response, err error) { fDC.mutex.Lock() defer fDC.mutex.Unlock() - respChan := make(chan disk.OperationStatusResponse, 1) - errChan := make(chan error, 1) - var resp disk.OperationStatusResponse - var err error - defer func() { - respChan <- resp - errChan <- err - close(respChan) - close(errChan) - }() if rgDisks, ok := fDC.FakeStore[resourceGroupName]; ok { if _, ok := rgDisks[diskName]; ok { delete(rgDisks, diskName) - resp.Response = autorest.Response{ - Response: &http.Response{ - StatusCode: http.StatusAccepted, - }, - } - - err = nil - return respChan, errChan + return nil, nil } } - resp.Response = autorest.Response{ - Response: &http.Response{ - StatusCode: http.StatusNotFound, - }, - } - err = autorest.DetailedError{ - StatusCode: http.StatusNotFound, - Message: "Not such Disk", - } - return respChan, errChan + + return &http.Response{ + StatusCode: http.StatusAccepted, + }, nil } -func (fDC *fakeDisksClient) Get(resourceGroupName string, diskName string) (result disk.Model, err error) { +func (fDC *fakeDisksClient) Get(ctx context.Context, resourceGroupName string, diskName string) (result compute.Disk, err error) { fDC.mutex.Lock() defer fDC.mutex.Unlock() @@ -1114,7 +826,7 @@ func (fDC *fakeDisksClient) Get(resourceGroupName string, diskName string) (resu } type fakeVMSet struct { - NodeToIP map[string]map[string]string + NodeToIP map[string]string Err error } @@ -1126,19 +838,16 @@ func (f *fakeVMSet) GetInstanceTypeByNodeName(name string) (string, error) { return "", fmt.Errorf("unimplemented") } -func (f *fakeVMSet) GetIPByNodeName(name, vmSetName string) (string, string, error) { - nodes, found := f.NodeToIP[vmSetName] - if !found { - return "", "", fmt.Errorf("not found") - } - ip, found := nodes[name] +func (f *fakeVMSet) GetIPByNodeName(name string) (string, string, error) { + ip, found := f.NodeToIP[name] if !found { return "", "", fmt.Errorf("not found") } + return ip, "", nil } -func (f *fakeVMSet) GetPrimaryInterface(nodeName, vmSetName string) (network.Interface, error) { +func (f *fakeVMSet) GetPrimaryInterface(nodeName string) (network.Interface, error) { return network.Interface{}, fmt.Errorf("unimplemented") } @@ -1158,11 +867,11 @@ func (f *fakeVMSet) GetVMSetNames(service *v1.Service, nodes []*v1.Node) (availa return nil, fmt.Errorf("unimplemented") } -func (f *fakeVMSet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, backendPoolID string, vmSetName string) error { +func (f *fakeVMSet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, backendPoolID string, vmSetName string, isInternal bool) error { return fmt.Errorf("unimplemented") } -func (f *fakeVMSet) EnsureBackendPoolDeleted(poolID, vmSetName string) error { +func (f *fakeVMSet) EnsureBackendPoolDeleted(poolID, vmSetName string, backendAddressPools *[]network.BackendAddressPool) error { return fmt.Errorf("unimplemented") } @@ -1174,14 +883,6 @@ func (f *fakeVMSet) DetachDiskByName(diskName, diskURI string, nodeName types.No return fmt.Errorf("unimplemented") } -func (f *fakeVMSet) GetDiskLun(diskName, diskURI string, nodeName types.NodeName) (int32, error) { - return -1, fmt.Errorf("unimplemented") -} - -func (f *fakeVMSet) GetNextDiskLun(nodeName types.NodeName) (int32, error) { - return -1, fmt.Errorf("unimplemented") -} - -func (f *fakeVMSet) DisksAreAttached(diskNames []string, nodeName types.NodeName) (map[string]bool, error) { +func (f *fakeVMSet) GetDataDisks(nodeName types.NodeName) ([]compute.DataDisk, error) { return nil, fmt.Errorf("unimplemented") } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_instances.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_instances.go index bedaf06c3..804553c32 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_instances.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_instances.go @@ -18,7 +18,6 @@ package azure import ( "context" - "fmt" "os" "strings" @@ -96,11 +95,6 @@ func (az *Cloud) NodeAddressesByProviderID(ctx context.Context, providerID strin return az.NodeAddresses(ctx, name) } -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (az *Cloud) ExternalID(ctx context.Context, name types.NodeName) (string, error) { - return az.InstanceID(ctx, name) -} - // InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. func (az *Cloud) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) { @@ -120,6 +114,11 @@ func (az *Cloud) InstanceExistsByProviderID(ctx context.Context, providerID stri return true, nil } +// InstanceShutdownByProviderID returns true if the instance is in safe state to detach volumes +func (az *Cloud) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, cloudprovider.NotImplemented +} + func (az *Cloud) isCurrentInstance(name types.NodeName) (bool, error) { nodeName := mapNodeNameToVMName(name) metadataName, err := az.metadata.Text("instance/compute/name") @@ -216,7 +215,7 @@ func (az *Cloud) InstanceType(ctx context.Context, name types.NodeName) (string, // AddSSHKeyToAllInstances adds an SSH public key as a legal identity for all instances // expected format for the key is standard ssh-keygen format: func (az *Cloud) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error { - return fmt.Errorf("not supported") + return cloudprovider.NotImplemented } // CurrentNodeName returns the name of the node we are currently running on. diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_loadbalancer.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_loadbalancer.go index 5cbe3fc4b..fca68fbb4 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_loadbalancer.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_loadbalancer.go @@ -28,7 +28,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" serviceapi "k8s.io/kubernetes/pkg/api/v1/service" - "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" "github.com/golang/glog" ) @@ -70,6 +70,17 @@ const ( // ServiceAnnotationLoadBalancerResourceGroup is the annotation used on the service // to specify the resource group of load balancer objects that are not in the same resource group as the cluster. ServiceAnnotationLoadBalancerResourceGroup = "service.beta.kubernetes.io/azure-load-balancer-resource-group" + + // ServiceAnnotationAllowedServiceTag is the annotation used on the service + // to specify a list of allowed service tags separated by comma + ServiceAnnotationAllowedServiceTag = "service.beta.kubernetes.io/azure-allowed-service-tags" +) + +var ( + // supportedServiceTags holds a list of supported service tags on Azure. + // Refer https://docs.microsoft.com/en-us/azure/virtual-network/security-overview#service-tags for more information. + supportedServiceTags = sets.NewString("VirtualNetwork", "VIRTUAL_NETWORK", "AzureLoadBalancer", "AZURE_LOADBALANCER", + "Internet", "INTERNET", "AzureTrafficManager", "Storage", "Sql") ) // GetLoadBalancer returns whether the specified load balancer exists, and @@ -210,8 +221,14 @@ func (az *Cloud) getServiceLoadBalancer(service *v1.Service, clusterName string, } } - // service does not have a load balancer, select one - if wantLb { + hasMode, _, _ := getServiceLoadBalancerMode(service) + if az.useStandardLoadBalancer() && hasMode { + return nil, nil, false, fmt.Errorf("standard load balancer doesn't work with annotation %q", ServiceAnnotationLoadBalancerMode) + } + + // service does not have a basic load balancer, select one. + // Standard load balancer doesn't need this because all backends nodes should be added to same LB. + if wantLb && !az.useStandardLoadBalancer() { // select new load balancer for service selectedLB, exists, err := az.selectLoadBalancer(clusterName, service, &existingLBs, nodes) if err != nil { @@ -228,6 +245,11 @@ func (az *Cloud) getServiceLoadBalancer(service *v1.Service, clusterName string, Location: &az.Location, LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{}, } + if az.useStandardLoadBalancer() { + defaultLB.Sku = &network.LoadBalancerSku{ + Name: network.LoadBalancerSkuNameStandard, + } + } } return defaultLB, nil, false, nil @@ -419,7 +441,13 @@ func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domai DomainNameLabel: &domainNameLabel, } } - pip.Tags = &map[string]*string{"service": &serviceName} + pip.Tags = map[string]*string{"service": &serviceName} + if az.useStandardLoadBalancer() { + pip.Sku = &network.PublicIPAddressSku{ + Name: network.PublicIPAddressSkuNameStandard, + } + } + glog.V(2).Infof("ensurePublicIPExists for service(%s): pip(%s) - creating", serviceName, *pip.Name) glog.V(10).Infof("CreateOrUpdatePIPWithRetry(%s, %q): start", pipResourceGroup, *pip.Name) err = az.CreateOrUpdatePIPWithRetry(pipResourceGroup, pip) @@ -429,7 +457,9 @@ func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domai } glog.V(10).Infof("CreateOrUpdatePIPWithRetry(%s, %q): end", pipResourceGroup, *pip.Name) - pip, err = az.PublicIPAddressesClient.Get(pipResourceGroup, *pip.Name, "") + ctx, cancel := getContextWithCancel() + defer cancel() + pip, err = az.PublicIPAddressesClient.Get(ctx, pipResourceGroup, *pip.Name, "") if err != nil { return nil, err } @@ -757,7 +787,7 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service, // Remove backend pools from vmSets. This is required for virtual machine scale sets before removing the LB. vmSetName := az.mapLoadBalancerNameToVMSet(lbName, clusterName) glog.V(10).Infof("EnsureBackendPoolDeleted(%s, %s): start", lbBackendPoolID, vmSetName) - err := az.vmSet.EnsureBackendPoolDeleted(lbBackendPoolID, vmSetName) + err := az.vmSet.EnsureBackendPoolDeleted(lbBackendPoolID, vmSetName, lb.BackendAddressPools) if err != nil { glog.Errorf("EnsureBackendPoolDeleted(%s, %s) failed: %v", lbBackendPoolID, vmSetName, err) return nil, err @@ -798,7 +828,7 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service, if wantLb && nodes != nil { // Add the machines to the backend pool if they're not already vmSetName := az.mapLoadBalancerNameToVMSet(lbName, clusterName) - err := az.vmSet.EnsureHostsInPool(serviceName, nodes, lbBackendPoolID, vmSetName) + err := az.vmSet.EnsureHostsInPool(serviceName, nodes, lbBackendPoolID, vmSetName, isInternal) if err != nil { return nil, err } @@ -843,8 +873,12 @@ func (az *Cloud) reconcileSecurityGroup(clusterName string, service *v1.Service, if err != nil { return nil, err } + serviceTags, err := getServiceTags(service) + if err != nil { + return nil, err + } var sourceAddressPrefixes []string - if sourceRanges == nil || serviceapi.IsAllowAll(sourceRanges) { + if (sourceRanges == nil || serviceapi.IsAllowAll(sourceRanges)) && len(serviceTags) == 0 { if !requiresInternalLoadBalancer(service) { sourceAddressPrefixes = []string{"Internet"} } @@ -852,6 +886,9 @@ func (az *Cloud) reconcileSecurityGroup(clusterName string, service *v1.Service, for _, ip := range sourceRanges { sourceAddressPrefixes = append(sourceAddressPrefixes, ip.String()) } + for _, serviceTag := range serviceTags { + sourceAddressPrefixes = append(sourceAddressPrefixes, serviceTag) + } } expectedSecurityRules := []network.SecurityRule{} @@ -889,8 +926,8 @@ func (az *Cloud) reconcileSecurityGroup(clusterName string, service *v1.Service, // update security rules dirtySg := false var updatedRules []network.SecurityRule - if sg.SecurityRules != nil { - updatedRules = *sg.SecurityRules + if sg.SecurityGroupPropertiesFormat != nil && sg.SecurityGroupPropertiesFormat.SecurityRules != nil { + updatedRules = *sg.SecurityGroupPropertiesFormat.SecurityRules } for _, r := range updatedRules { @@ -1171,8 +1208,8 @@ func (az *Cloud) reconcilePublicIP(clusterName string, service *v1.Service, want for _, pip := range pips { if pip.Tags != nil && - (*pip.Tags)["service"] != nil && - *(*pip.Tags)["service"] == serviceName { + (pip.Tags)["service"] != nil && + *(pip.Tags)["service"] == serviceName { // We need to process for pips belong to this service pipName := *pip.Name if wantLb && !isInternal && pipName == desiredPipName { @@ -1341,3 +1378,23 @@ func useSharedSecurityRule(service *v1.Service) bool { return false } + +func getServiceTags(service *v1.Service) ([]string, error) { + if serviceTags, found := service.Annotations[ServiceAnnotationAllowedServiceTag]; found { + tags := strings.Split(strings.TrimSpace(serviceTags), ",") + for _, tag := range tags { + // Storage and Sql service tags support setting regions with suffix ".Region" + if strings.HasPrefix(tag, "Storage.") || strings.HasPrefix(tag, "Sql.") { + continue + } + + if !supportedServiceTags.Has(tag) { + return nil, fmt.Errorf("only %q are allowed in service tags", supportedServiceTags.List()) + } + } + + return tags, nil + } + + return nil, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_loadbalancer_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_loadbalancer_test.go index 2afea9baa..ee0ed967d 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_loadbalancer_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_loadbalancer_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" "github.com/stretchr/testify/assert" ) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_managedDiskController.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_managedDiskController.go index 207392680..ade2dbba5 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_managedDiskController.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_managedDiskController.go @@ -17,13 +17,17 @@ limitations under the License. package azure import ( + "fmt" "path" "strings" - "github.com/Azure/azure-sdk-for-go/arm/disk" - storage "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/api/resource" kwait "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/pkg/volume/util" ) //ManagedDiskController : managed disk controller struct @@ -36,7 +40,8 @@ func newManagedDiskController(common *controllerCommon) (*ManagedDiskController, } //CreateManagedDisk : create managed disk -func (c *ManagedDiskController) CreateManagedDisk(diskName string, storageAccountType storage.SkuName, sizeGB int, tags map[string]string) (string, error) { +func (c *ManagedDiskController) CreateManagedDisk(diskName string, storageAccountType storage.SkuName, resourceGroup string, + sizeGB int, tags map[string]string) (string, error) { glog.V(4).Infof("azureDisk - creating new managed Name:%s StorageAccountType:%s Size:%v", diskName, storageAccountType, sizeGB) newTags := make(map[string]*string) @@ -54,18 +59,24 @@ func (c *ManagedDiskController) CreateManagedDisk(diskName string, storageAccoun } diskSizeGB := int32(sizeGB) - model := disk.Model{ + model := compute.Disk{ Location: &c.common.location, - Tags: &newTags, - Properties: &disk.Properties{ - AccountType: disk.StorageAccountTypes(storageAccountType), + Tags: newTags, + Sku: &compute.DiskSku{ + Name: compute.StorageAccountTypes(storageAccountType), + }, + DiskProperties: &compute.DiskProperties{ DiskSizeGB: &diskSizeGB, - CreationData: &disk.CreationData{CreateOption: disk.Empty}, + CreationData: &compute.CreationData{CreateOption: compute.Empty}, }} - cancel := make(chan struct{}) - respChan, errChan := c.common.cloud.DisksClient.CreateOrUpdate(c.common.resourceGroup, diskName, model, cancel) - <-respChan - err := <-errChan + + if resourceGroup == "" { + resourceGroup = c.common.resourceGroup + } + + ctx, cancel := getContextWithCancel() + defer cancel() + _, err := c.common.cloud.DisksClient.CreateOrUpdate(ctx, resourceGroup, diskName, model) if err != nil { return "", err } @@ -73,7 +84,7 @@ func (c *ManagedDiskController) CreateManagedDisk(diskName string, storageAccoun diskID := "" err = kwait.ExponentialBackoff(defaultBackOff, func() (bool, error) { - provisionState, id, err := c.getDisk(diskName) + provisionState, id, err := c.getDisk(resourceGroup, diskName) diskID = id // We are waiting for provisioningState==Succeeded // We don't want to hand-off managed disks to k8s while they are @@ -99,10 +110,15 @@ func (c *ManagedDiskController) CreateManagedDisk(diskName string, storageAccoun //DeleteManagedDisk : delete managed disk func (c *ManagedDiskController) DeleteManagedDisk(diskURI string) error { diskName := path.Base(diskURI) - cancel := make(chan struct{}) - respChan, errChan := c.common.cloud.DisksClient.Delete(c.common.resourceGroup, diskName, cancel) - <-respChan - err := <-errChan + resourceGroup, err := getResourceGroupFromDiskURI(diskURI) + if err != nil { + return err + } + + ctx, cancel := getContextWithCancel() + defer cancel() + + _, err = c.common.cloud.DisksClient.Delete(ctx, resourceGroup, diskName) if err != nil { return err } @@ -115,15 +131,73 @@ func (c *ManagedDiskController) DeleteManagedDisk(diskURI string) error { } // return: disk provisionState, diskID, error -func (c *ManagedDiskController) getDisk(diskName string) (string, string, error) { - result, err := c.common.cloud.DisksClient.Get(c.common.resourceGroup, diskName) +func (c *ManagedDiskController) getDisk(resourceGroup, diskName string) (string, string, error) { + ctx, cancel := getContextWithCancel() + defer cancel() + + result, err := c.common.cloud.DisksClient.Get(ctx, resourceGroup, diskName) if err != nil { return "", "", err } - if result.Properties != nil && (*result.Properties).ProvisioningState != nil { - return *(*result.Properties).ProvisioningState, *result.ID, nil + if result.DiskProperties != nil && (*result.DiskProperties).ProvisioningState != nil { + return *(*result.DiskProperties).ProvisioningState, *result.ID, nil } return "", "", err } + +// ResizeDisk Expand the disk to new size +func (c *ManagedDiskController) ResizeDisk(diskURI string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error) { + ctx, cancel := getContextWithCancel() + defer cancel() + + diskName := path.Base(diskURI) + resourceGroup, err := getResourceGroupFromDiskURI(diskURI) + if err != nil { + return oldSize, err + } + + result, err := c.common.cloud.DisksClient.Get(ctx, resourceGroup, diskName) + if err != nil { + return oldSize, err + } + + if result.DiskProperties == nil || result.DiskProperties.DiskSizeGB == nil { + return oldSize, fmt.Errorf("DiskProperties of disk(%s) is nil", diskName) + } + + requestBytes := newSize.Value() + // Azure resizes in chunks of GiB (not GB) + requestGiB := int32(util.RoundUpSize(requestBytes, 1024*1024*1024)) + newSizeQuant := resource.MustParse(fmt.Sprintf("%dGi", requestGiB)) + + glog.V(2).Infof("azureDisk - begin to resize disk(%s) with new size(%d), old size(%v)", diskName, requestGiB, oldSize) + // If disk already of greater or equal size than requested we return + if *result.DiskProperties.DiskSizeGB >= requestGiB { + return newSizeQuant, nil + } + + result.DiskProperties.DiskSizeGB = &requestGiB + + ctx, cancel = getContextWithCancel() + defer cancel() + if _, err := c.common.cloud.DisksClient.CreateOrUpdate(ctx, resourceGroup, diskName, result); err != nil { + return oldSize, err + } + + glog.V(2).Infof("azureDisk - resize disk(%s) with new size(%d) completed", diskName, requestGiB) + + return newSizeQuant, nil +} + +// get resource group name from a managed disk URI, e.g. return {group-name} according to +// /subscriptions/{sub-id}/resourcegroups/{group-name}/providers/microsoft.compute/disks/{disk-id} +// according to https://docs.microsoft.com/en-us/rest/api/compute/disks/get +func getResourceGroupFromDiskURI(diskURI string) (string, error) { + fields := strings.Split(diskURI, "/") + if len(fields) != 9 || fields[3] != "resourceGroups" { + return "", fmt.Errorf("invalid disk URI: %s", diskURI) + } + return fields[4], nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_routes.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_routes.go index 292bb3c37..7f627a98a 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_routes.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_routes.go @@ -22,7 +22,7 @@ import ( "k8s.io/kubernetes/pkg/cloudprovider" - "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" "github.com/golang/glog" "k8s.io/apimachinery/pkg/types" @@ -81,13 +81,13 @@ func (az *Cloud) createRouteTable() error { RouteTablePropertiesFormat: &network.RouteTablePropertiesFormat{}, } - glog.V(3).Infof("createRouteTable: creating routetable. routeTableName=%q", az.RouteTableName) - respChan, errChan := az.RouteTablesClient.CreateOrUpdate(az.ResourceGroup, az.RouteTableName, routeTable, nil) - resp := <-respChan - err := <-errChan + glog.V(3).Infof("createRouteTableIfNotExists: creating routetable. routeTableName=%q", az.RouteTableName) + ctx, cancel := getContextWithCancel() + defer cancel() + resp, err := az.RouteTablesClient.CreateOrUpdate(ctx, az.ResourceGroup, az.RouteTableName, routeTable) glog.V(10).Infof("RouteTablesClient.CreateOrUpdate(%q): end", az.RouteTableName) - if az.CloudProviderBackoff && shouldRetryAPIRequest(resp.Response, err) { - glog.V(2).Infof("createRouteTable backing off: creating routetable. routeTableName=%q", az.RouteTableName) + if az.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { + glog.V(2).Infof("createRouteTableIfNotExists backing off: creating routetable. routeTableName=%q", az.RouteTableName) retryErr := az.CreateOrUpdateRouteTableWithRetry(routeTable) if retryErr != nil { err = retryErr @@ -126,12 +126,12 @@ func (az *Cloud) CreateRoute(ctx context.Context, clusterName string, nameHint s }, } - glog.V(2).Infof("CreateRoute: creating route: instance=%q cidr=%q", kubeRoute.TargetNode, kubeRoute.DestinationCIDR) - respChan, errChan := az.RoutesClient.CreateOrUpdate(az.ResourceGroup, az.RouteTableName, *route.Name, route, nil) - resp := <-respChan - err = <-errChan + glog.V(3).Infof("CreateRoute: creating route: instance=%q cidr=%q", kubeRoute.TargetNode, kubeRoute.DestinationCIDR) + ctx, cancel := getContextWithCancel() + defer cancel() + resp, err := az.RoutesClient.CreateOrUpdate(ctx, az.ResourceGroup, az.RouteTableName, *route.Name, route) glog.V(10).Infof("RoutesClient.CreateOrUpdate(%q): end", az.RouteTableName) - if az.CloudProviderBackoff && shouldRetryAPIRequest(resp.Response, err) { + if az.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { glog.V(2).Infof("CreateRoute backing off: creating route: instance=%q cidr=%q", kubeRoute.TargetNode, kubeRoute.DestinationCIDR) retryErr := az.CreateOrUpdateRouteWithRetry(route) if retryErr != nil { @@ -152,13 +152,13 @@ func (az *Cloud) CreateRoute(ctx context.Context, clusterName string, nameHint s func (az *Cloud) DeleteRoute(ctx context.Context, clusterName string, kubeRoute *cloudprovider.Route) error { glog.V(2).Infof("DeleteRoute: deleting route. clusterName=%q instance=%q cidr=%q", clusterName, kubeRoute.TargetNode, kubeRoute.DestinationCIDR) + ctx, cancel := getContextWithCancel() + defer cancel() routeName := mapNodeNameToRouteName(kubeRoute.TargetNode) - respChan, errChan := az.RoutesClient.Delete(az.ResourceGroup, az.RouteTableName, routeName, nil) - resp := <-respChan - err := <-errChan + resp, err := az.RoutesClient.Delete(ctx, az.ResourceGroup, az.RouteTableName, routeName) glog.V(10).Infof("RoutesClient.Delete(%q): end", az.RouteTableName) - if az.CloudProviderBackoff && shouldRetryAPIRequest(resp, err) { + if az.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { glog.V(2).Infof("DeleteRoute backing off: deleting route. clusterName=%q instance=%q cidr=%q", clusterName, kubeRoute.TargetNode, kubeRoute.DestinationCIDR) retryErr := az.DeleteRouteWithRetry(routeName) if retryErr != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_routes_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_routes_test.go index e4906b2d9..cc248ee52 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_routes_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_routes_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/kubernetes/pkg/cloudprovider" - "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" ) @@ -94,10 +94,8 @@ func TestCreateRoute(t *testing.T) { route := cloudprovider.Route{TargetNode: "node", DestinationCIDR: "1.2.3.4/24"} nodeIP := "2.4.6.8" - fakeVM.NodeToIP = map[string]map[string]string{ - "": { - "node": nodeIP, - }, + fakeVM.NodeToIP = map[string]string{ + "node": nodeIP, } err := cloud.CreateRoute(context.TODO(), "cluster", "unused", &route) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_standard.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_standard.go index c9c8da00d..9591ca92a 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_standard.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_standard.go @@ -28,8 +28,8 @@ import ( "k8s.io/api/core/v1" "k8s.io/kubernetes/pkg/cloudprovider" - "github.com/Azure/azure-sdk-for-go/arm/compute" - "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" "github.com/golang/glog" "k8s.io/apimachinery/pkg/types" @@ -52,13 +52,15 @@ const ( InternalLoadBalancerNameSuffix = "-internal" // nodeLabelRole specifies the role of a node - nodeLabelRole = "kubernetes.io/role" + nodeLabelRole = "kubernetes.io/role" + nicFailedState = "Failed" storageAccountNameMaxLength = 24 ) var errNotInVMSet = errors.New("vm is not in the vmset") var providerIDRE = regexp.MustCompile(`^` + CloudProviderName + `://(?:.*)/Microsoft.Compute/virtualMachines/(.+)$`) +var backendPoolIDRE = regexp.MustCompile(`^/subscriptions/(?:.*)/resourceGroups/(?:.*)/providers/Microsoft.Network/loadBalancers/(.+)/backendAddressPools/(?:.*)`) // getStandardMachineID returns the full identifier of a virtual machine. func (az *Cloud) getStandardMachineID(machineName string) string { @@ -123,7 +125,7 @@ func (az *Cloud) mapLoadBalancerNameToVMSet(lbName string, clusterName string) ( // This would be the name for Azure LoadBalancer resource. func (az *Cloud) getLoadBalancerName(clusterName string, vmSetName string, isInternal bool) string { lbNamePrefix := vmSetName - if strings.EqualFold(vmSetName, az.vmSet.GetPrimaryVMSetName()) { + if strings.EqualFold(vmSetName, az.vmSet.GetPrimaryVMSetName()) || az.useStandardLoadBalancer() { lbNamePrefix = clusterName } if isInternal { @@ -288,7 +290,7 @@ outer: } func (az *Cloud) getIPForMachine(nodeName types.NodeName) (string, string, error) { - return az.vmSet.GetIPByNodeName(string(nodeName), "") + return az.vmSet.GetIPByNodeName(string(nodeName)) } var polyTable = crc32.MakeTable(crc32.Koopman) @@ -428,8 +430,8 @@ func (as *availabilitySet) GetPrimaryVMSetName() string { } // GetIPByNodeName gets machine private IP and public IP by node name. -func (as *availabilitySet) GetIPByNodeName(name, vmSetName string) (string, string, error) { - nic, err := as.GetPrimaryInterface(name, vmSetName) +func (as *availabilitySet) GetIPByNodeName(name string) (string, string, error) { + nic, err := as.GetPrimaryInterface(name) if err != nil { return "", "", err } @@ -553,8 +555,13 @@ func (as *availabilitySet) GetVMSetNames(service *v1.Service, nodes []*v1.Node) return availabilitySetNames, nil } -// GetPrimaryInterface gets machine primary network interface by node name and vmSet. -func (as *availabilitySet) GetPrimaryInterface(nodeName, vmSetName string) (network.Interface, error) { +// GetPrimaryInterface gets machine primary network interface by node name. +func (as *availabilitySet) GetPrimaryInterface(nodeName string) (network.Interface, error) { + return as.getPrimaryInterfaceWithVMSet(nodeName, "") +} + +// getPrimaryInterfaceWithVMSet gets machine primary network interface by node name and vmSet. +func (as *availabilitySet) getPrimaryInterfaceWithVMSet(nodeName, vmSetName string) (network.Interface, error) { var machine compute.VirtualMachine machine, err := as.GetVirtualMachineWithRetry(types.NodeName(nodeName)) @@ -572,8 +579,14 @@ func (as *availabilitySet) GetPrimaryInterface(nodeName, vmSetName string) (netw return network.Interface{}, err } - // Check availability set - if vmSetName != "" { + // Check availability set name. Note that vmSetName is empty string when getting + // the Node's IP address. While vmSetName is not empty, it should be checked with + // Node's real availability set name: + // - For basic SKU load balancer, errNotInVMSet should be returned if the node's + // availability set is mismatched with vmSetName. + // - For standard SKU load balancer, backend could belong to multiple VMAS, so we + // don't check vmSet for it. + if vmSetName != "" && !as.useStandardLoadBalancer() { expectedAvailabilitySetName := as.getAvailabilitySetID(vmSetName) if machine.AvailabilitySet == nil || !strings.EqualFold(*machine.AvailabilitySet.ID, expectedAvailabilitySetName) { glog.V(3).Infof( @@ -582,7 +595,9 @@ func (as *availabilitySet) GetPrimaryInterface(nodeName, vmSetName string) (netw } } - nic, err := as.InterfacesClient.Get(as.ResourceGroup, nicName, "") + ctx, cancel := getContextWithCancel() + defer cancel() + nic, err := as.InterfacesClient.Get(ctx, as.ResourceGroup, nicName, "") if err != nil { return network.Interface{}, err } @@ -592,9 +607,9 @@ func (as *availabilitySet) GetPrimaryInterface(nodeName, vmSetName string) (netw // ensureHostInPool ensures the given VM's Primary NIC's Primary IP Configuration is // participating in the specified LoadBalancer Backend Pool. -func (as *availabilitySet) ensureHostInPool(serviceName string, nodeName types.NodeName, backendPoolID string, vmSetName string) error { +func (as *availabilitySet) ensureHostInPool(serviceName string, nodeName types.NodeName, backendPoolID string, vmSetName string, isInternal bool) error { vmName := mapNodeNameToVMName(nodeName) - nic, err := as.GetPrimaryInterface(vmName, vmSetName) + nic, err := as.getPrimaryInterfaceWithVMSet(vmName, vmSetName) if err != nil { if err == errNotInVMSet { glog.V(3).Infof("ensureHostInPool skips node %s because it is not in the vmSet %s", nodeName, vmSetName) @@ -605,6 +620,11 @@ func (as *availabilitySet) ensureHostInPool(serviceName string, nodeName types.N return err } + if nic.ProvisioningState != nil && *nic.ProvisioningState == nicFailedState { + glog.V(3).Infof("ensureHostInPool skips node %s because its primdary nic %s is in Failed state", nodeName, nic.Name) + return nil + } + var primaryIPConfig *network.InterfaceIPConfiguration primaryIPConfig, err = getPrimaryIPConfig(nic) if err != nil { @@ -623,6 +643,24 @@ func (as *availabilitySet) ensureHostInPool(serviceName string, nodeName types.N } } if !foundPool { + if as.useStandardLoadBalancer() && len(newBackendPools) > 0 { + // Although standard load balancer supports backends from multiple availability + // sets, the same network interface couldn't be added to more than one load balancer of + // the same type. Omit those nodes (e.g. masters) so Azure ARM won't complain + // about this. + for _, pool := range newBackendPools { + backendPool := *pool.ID + matches := backendPoolIDRE.FindStringSubmatch(backendPool) + if len(matches) == 2 { + lbName := matches[1] + if strings.HasSuffix(lbName, InternalLoadBalancerNameSuffix) == isInternal { + glog.V(4).Infof("Node %q has already been added to LB %q, omit adding it to a new one", nodeName, lbName) + return nil + } + } + } + } + newBackendPools = append(newBackendPools, network.BackendAddressPool{ ID: to.StringPtr(backendPoolID), @@ -632,11 +670,11 @@ func (as *availabilitySet) ensureHostInPool(serviceName string, nodeName types.N nicName := *nic.Name glog.V(3).Infof("nicupdate(%s): nic(%s) - updating", serviceName, nicName) - respChan, errChan := as.InterfacesClient.CreateOrUpdate(as.ResourceGroup, *nic.Name, nic, nil) - resp := <-respChan - err := <-errChan + ctx, cancel := getContextWithCancel() + defer cancel() + resp, err := as.InterfacesClient.CreateOrUpdate(ctx, as.ResourceGroup, *nic.Name, nic) glog.V(10).Infof("InterfacesClient.CreateOrUpdate(%q): end", *nic.Name) - if as.CloudProviderBackoff && shouldRetryAPIRequest(resp.Response, err) { + if as.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { glog.V(2).Infof("nicupdate(%s) backing off: nic(%s) - updating, err=%v", serviceName, nicName, err) retryErr := as.CreateOrUpdateInterfaceWithRetry(nic) if retryErr != nil { @@ -653,18 +691,23 @@ func (as *availabilitySet) ensureHostInPool(serviceName string, nodeName types.N // EnsureHostsInPool ensures the given Node's primary IP configurations are // participating in the specified LoadBalancer Backend Pool. -func (as *availabilitySet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, backendPoolID string, vmSetName string) error { - hostUpdates := make([]func() error, len(nodes)) - for i, node := range nodes { +func (as *availabilitySet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, backendPoolID string, vmSetName string, isInternal bool) error { + hostUpdates := make([]func() error, 0, len(nodes)) + for _, node := range nodes { localNodeName := node.Name + if as.useStandardLoadBalancer() && as.excludeMasterNodesFromStandardLB() && isMasterNode(node) { + glog.V(4).Infof("Excluding master node %q from load balancer backendpool %q", localNodeName, backendPoolID) + continue + } + f := func() error { - err := as.ensureHostInPool(serviceName, types.NodeName(localNodeName), backendPoolID, vmSetName) + err := as.ensureHostInPool(serviceName, types.NodeName(localNodeName), backendPoolID, vmSetName, isInternal) if err != nil { return fmt.Errorf("ensure(%s): backendPoolID(%s) - failed to ensure host in pool: %q", serviceName, backendPoolID, err) } return nil } - hostUpdates[i] = f + hostUpdates = append(hostUpdates, f) } errs := utilerrors.AggregateGoroutines(hostUpdates...) @@ -676,7 +719,7 @@ func (as *availabilitySet) EnsureHostsInPool(serviceName string, nodes []*v1.Nod } // EnsureBackendPoolDeleted ensures the loadBalancer backendAddressPools deleted from the specified vmSet. -func (as *availabilitySet) EnsureBackendPoolDeleted(poolID, vmSetName string) error { +func (as *availabilitySet) EnsureBackendPoolDeleted(poolID, vmSetName string, backendAddressPools *[]network.BackendAddressPool) error { // Do nothing for availability set. return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_standard_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_standard_test.go index 5de3e3c4b..d5071192f 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_standard_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_standard_test.go @@ -130,6 +130,7 @@ func TestMapLoadBalancerNameToVMSet(t *testing.T) { cases := []struct { description string lbName string + useStandardLB bool clusterName string expectedVMSet string }{ @@ -160,7 +161,93 @@ func TestMapLoadBalancerNameToVMSet(t *testing.T) { } for _, c := range cases { + if c.useStandardLB { + az.Config.LoadBalancerSku = loadBalancerSkuStandard + } else { + az.Config.LoadBalancerSku = loadBalancerSkuBasic + } vmset := az.mapLoadBalancerNameToVMSet(c.lbName, c.clusterName) assert.Equal(t, c.expectedVMSet, vmset, c.description) } } + +func TestGetLoadBalancerName(t *testing.T) { + az := getTestCloud() + az.PrimaryAvailabilitySetName = "primary" + + cases := []struct { + description string + vmSet string + isInternal bool + useStandardLB bool + clusterName string + expected string + }{ + { + description: "default external LB should get primary vmset", + vmSet: "primary", + clusterName: "azure", + expected: "azure", + }, + { + description: "default internal LB should get primary vmset", + vmSet: "primary", + clusterName: "azure", + isInternal: true, + expected: "azure-internal", + }, + { + description: "non-default external LB should get its own vmset", + vmSet: "as", + clusterName: "azure", + expected: "as", + }, + { + description: "non-default internal LB should get its own vmset", + vmSet: "as", + clusterName: "azure", + isInternal: true, + expected: "as-internal", + }, + { + description: "default standard external LB should get cluster name", + vmSet: "primary", + useStandardLB: true, + clusterName: "azure", + expected: "azure", + }, + { + description: "default standard internal LB should get cluster name", + vmSet: "primary", + useStandardLB: true, + isInternal: true, + clusterName: "azure", + expected: "azure-internal", + }, + { + description: "non-default standard external LB should get cluster-name", + vmSet: "as", + useStandardLB: true, + clusterName: "azure", + expected: "azure", + }, + { + description: "non-default standard internal LB should get cluster-name", + vmSet: "as", + useStandardLB: true, + isInternal: true, + clusterName: "azure", + expected: "azure-internal", + }, + } + + for _, c := range cases { + if c.useStandardLB { + az.Config.LoadBalancerSku = loadBalancerSkuStandard + } else { + az.Config.LoadBalancerSku = loadBalancerSkuBasic + } + loadbalancerName := az.getLoadBalancerName(c.clusterName, c.vmSet, c.isInternal) + assert.Equal(t, c.expected, loadbalancerName, c.description) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storage.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storage.go index 03d919daa..7e70282e3 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storage.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storage.go @@ -19,7 +19,7 @@ package azure import ( "fmt" - "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" "github.com/golang/glog" ) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storage_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storage_test.go index 6a1298ffb..f358b32b0 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storage_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storage_test.go @@ -19,7 +19,7 @@ package azure import ( "testing" - "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" ) func TestCreateFileShare(t *testing.T) { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storageaccount.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storageaccount.go index 8425463b5..e6610d22a 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storageaccount.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storageaccount.go @@ -20,7 +20,7 @@ import ( "fmt" "strings" - "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" "github.com/Azure/go-autorest/autorest/to" "github.com/golang/glog" ) @@ -31,7 +31,9 @@ type accountWithLocation struct { // getStorageAccounts gets name, type, location of all storage accounts in a resource group which matches matchingAccountType, matchingLocation func (az *Cloud) getStorageAccounts(matchingAccountType, matchingLocation string) ([]accountWithLocation, error) { - result, err := az.StorageAccountClient.ListByResourceGroup(az.ResourceGroup) + ctx, cancel := getContextWithCancel() + defer cancel() + result, err := az.StorageAccountClient.ListByResourceGroup(ctx, az.ResourceGroup) if err != nil { return nil, err } @@ -60,7 +62,10 @@ func (az *Cloud) getStorageAccounts(matchingAccountType, matchingLocation string // getStorageAccesskey gets the storage account access key func (az *Cloud) getStorageAccesskey(account string) (string, error) { - result, err := az.StorageAccountClient.ListKeys(az.ResourceGroup, account) + ctx, cancel := getContextWithCancel() + defer cancel() + + result, err := az.StorageAccountClient.ListKeys(ctx, az.ResourceGroup, account) if err != nil { return "", err } @@ -107,13 +112,16 @@ func (az *Cloud) ensureStorageAccount(accountName, accountType, location, genAcc glog.V(2).Infof("azure - no matching account found, begin to create a new account %s in resource group %s, location: %s, accountType: %s", accountName, az.ResourceGroup, location, accountType) cp := storage.AccountCreateParameters{ - Sku: &storage.Sku{Name: storage.SkuName(accountType)}, - Tags: &map[string]*string{"created-by": to.StringPtr("azure")}, + Sku: &storage.Sku{Name: storage.SkuName(accountType)}, + // switch to use StorageV2 as it's recommended according to https://docs.microsoft.com/en-us/azure/storage/common/storage-account-options + Kind: storage.StorageV2, + AccountPropertiesCreateParameters: &storage.AccountPropertiesCreateParameters{EnableHTTPSTrafficOnly: to.BoolPtr(true)}, + Tags: map[string]*string{"created-by": to.StringPtr("azure")}, Location: &location} - cancel := make(chan struct{}) - _, errchan := az.StorageAccountClient.Create(az.ResourceGroup, accountName, cp, cancel) - err := <-errchan + ctx, cancel := getContextWithCancel() + defer cancel() + _, err := az.StorageAccountClient.Create(ctx, az.ResourceGroup, accountName, cp) if err != nil { return "", "", fmt.Errorf(fmt.Sprintf("Failed to create storage account %s, error: %s", accountName, err)) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storageaccount_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storageaccount_test.go index 86befc1ae..0bb86ccd2 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storageaccount_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_storageaccount_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" ) func TestGetStorageAccessKeys(t *testing.T) { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_test.go index 1569ec34a..c8b0eb7be 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_test.go @@ -35,8 +35,8 @@ import ( "k8s.io/kubernetes/pkg/cloudprovider/providers/azure/auth" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" - "github.com/Azure/azure-sdk-for-go/arm/compute" - "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" "github.com/stretchr/testify/assert" ) @@ -215,9 +215,11 @@ func testLoadBalancerServiceDefaultModeSelection(t *testing.T, isInternal bool) expectedLBName = testClusterName + "-internal" } - result, _ := az.LoadBalancerClient.List(az.Config.ResourceGroup) - lb := (*result.Value)[0] - lbCount := len(*result.Value) + ctx, cancel := getContextWithCancel() + defer cancel() + result, _ := az.LoadBalancerClient.List(ctx, az.Config.ResourceGroup) + lb := result[0] + lbCount := len(result) expectedNumOfLB := 1 if lbCount != expectedNumOfLB { t.Errorf("Unexpected number of LB's: Expected (%d) Found (%d)", expectedNumOfLB, lbCount) @@ -265,15 +267,17 @@ func testLoadBalancerServiceAutoModeSelection(t *testing.T, isInternal bool) { // expected is MIN(index, availabilitySetCount) expectedNumOfLB := int(math.Min(float64(index), float64(availabilitySetCount))) - result, _ := az.LoadBalancerClient.List(az.Config.ResourceGroup) - lbCount := len(*result.Value) + ctx, cancel := getContextWithCancel() + defer cancel() + result, _ := az.LoadBalancerClient.List(ctx, az.Config.ResourceGroup) + lbCount := len(result) if lbCount != expectedNumOfLB { t.Errorf("Unexpected number of LB's: Expected (%d) Found (%d)", expectedNumOfLB, lbCount) } maxRules := 0 minRules := serviceCount - for _, lb := range *result.Value { + for _, lb := range result { ruleCount := len(*lb.LoadBalancingRules) if ruleCount < minRules { minRules = ruleCount @@ -328,8 +332,10 @@ func testLoadBalancerServicesSpecifiedSelection(t *testing.T, isInternal bool) { // expected is MIN(index, 2) expectedNumOfLB := int(math.Min(float64(index), float64(2))) - result, _ := az.LoadBalancerClient.List(az.Config.ResourceGroup) - lbCount := len(*result.Value) + ctx, cancel := getContextWithCancel() + defer cancel() + result, _ := az.LoadBalancerClient.List(ctx, az.Config.ResourceGroup) + lbCount := len(result) if lbCount != expectedNumOfLB { t.Errorf("Unexpected number of LB's: Expected (%d) Found (%d)", expectedNumOfLB, lbCount) } @@ -366,8 +372,10 @@ func testLoadBalancerMaxRulesServices(t *testing.T, isInternal bool) { // expected is MIN(index, az.Config.MaximumLoadBalancerRuleCount) expectedNumOfLBRules := int(math.Min(float64(index), float64(az.Config.MaximumLoadBalancerRuleCount))) - result, _ := az.LoadBalancerClient.List(az.Config.ResourceGroup) - lbCount := len(*result.Value) + ctx, cancel := getContextWithCancel() + defer cancel() + result, _ := az.LoadBalancerClient.List(ctx, az.Config.ResourceGroup) + lbCount := len(result) if lbCount != expectedNumOfLBRules { t.Errorf("Unexpected number of LB's: Expected (%d) Found (%d)", expectedNumOfLBRules, lbCount) } @@ -436,8 +444,10 @@ func testLoadBalancerServiceAutoModeDeleteSelection(t *testing.T, isInternal boo // expected is MIN(index, availabilitySetCount) expectedNumOfLB := int(math.Min(float64(index), float64(availabilitySetCount))) - result, _ := az.LoadBalancerClient.List(az.Config.ResourceGroup) - lbCount := len(*result.Value) + ctx, cancel := getContextWithCancel() + defer cancel() + result, _ := az.LoadBalancerClient.List(ctx, az.Config.ResourceGroup) + lbCount := len(result) if lbCount != expectedNumOfLB { t.Errorf("Unexpected number of LB's: Expected (%d) Found (%d)", expectedNumOfLB, lbCount) } @@ -1046,7 +1056,9 @@ func getClusterResources(az *Cloud, vmCount int, availabilitySetCount int) (clus }, }, } - az.InterfacesClient.CreateOrUpdate(az.Config.ResourceGroup, nicName, newNIC, nil) + ctx, cancel := getContextWithCancel() + defer cancel() + az.InterfacesClient.CreateOrUpdate(ctx, az.Config.ResourceGroup, nicName, newNIC) // create vm asID := az.getAvailabilitySetID(asName) @@ -1067,8 +1079,10 @@ func getClusterResources(az *Cloud, vmCount int, availabilitySetCount int) (clus }, } - _, errChan := az.VirtualMachinesClient.CreateOrUpdate(az.Config.ResourceGroup, vmName, newVM, nil) - if err := <-errChan; err != nil { + vmCtx, vmCancel := getContextWithCancel() + defer vmCancel() + _, err := az.VirtualMachinesClient.CreateOrUpdate(vmCtx, az.Config.ResourceGroup, vmName, newVM) + if err != nil { } // add to kubernetes newNode := &v1.Node{ @@ -1164,11 +1178,13 @@ func getTestSecurityGroup(az *Cloud, services ...v1.Service) *network.SecurityGr }, } + ctx, cancel := getContextWithCancel() + defer cancel() az.SecurityGroupsClient.CreateOrUpdate( + ctx, az.ResourceGroup, az.SecurityGroupName, - sg, - nil) + sg) return &sg } @@ -1314,12 +1330,12 @@ func validatePublicIP(t *testing.T, publicIP *network.PublicIPAddress, service * t.Errorf("Expected publicIP resource exists, when it is not an internal service") } - if publicIP.Tags == nil || (*publicIP.Tags)["service"] == nil { + if publicIP.Tags == nil || publicIP.Tags["service"] == nil { t.Errorf("Expected publicIP resource has tags[service]") } serviceName := getServiceName(service) - if serviceName != *(*publicIP.Tags)["service"] { + if serviceName != *(publicIP.Tags["service"]) { t.Errorf("Expected publicIP resource has matching tags[service]") } // We cannot use service.Spec.LoadBalancerIP to compare with @@ -1842,13 +1858,15 @@ func addTestSubnet(t *testing.T, az *Cloud, svc *v1.Service) { az.VnetName, subName) - _, errChan := az.SubnetsClient.CreateOrUpdate(az.VnetResourceGroup, az.VnetName, subName, + ctx, cancel := getContextWithCancel() + defer cancel() + _, err := az.SubnetsClient.CreateOrUpdate(ctx, az.VnetResourceGroup, az.VnetName, subName, network.Subnet{ ID: &subnetID, Name: &subName, - }, nil) + }) - if err := <-errChan; err != nil { + if err != nil { t.Errorf("Subnet cannot be created or update, %v", err) } svc.Annotations[ServiceAnnotationLoadBalancerInternalSubnet] = subName @@ -2681,3 +2699,39 @@ func TestCanCombineSharedAndPrivateRulesInSameGroup(t *testing.T) { // func TestIfServiceIsEditedFromSharedRuleToOwnRuleThenItIsRemovedFromSharedRuleAndOwnRuleIsCreated(t *testing.T) { // t.Error() // } + +func TestGetResourceGroupFromDiskURI(t *testing.T) { + tests := []struct { + diskURL string + expectedResult string + expectError bool + }{ + { + diskURL: "/subscriptions/4be8920b-2978-43d7-axyz-04d8549c1d05/resourceGroups/azure-k8s1102/providers/Microsoft.Compute/disks/andy-mghyb1102-dynamic-pvc-f7f014c9-49f4-11e8-ab5c-000d3af7b38e", + expectedResult: "azure-k8s1102", + expectError: false, + }, + { + diskURL: "/4be8920b-2978-43d7-axyz-04d8549c1d05/resourceGroups/azure-k8s1102/providers/Microsoft.Compute/disks/andy-mghyb1102-dynamic-pvc-f7f014c9-49f4-11e8-ab5c-000d3af7b38e", + expectedResult: "", + expectError: true, + }, + { + diskURL: "", + expectedResult: "", + expectError: true, + }, + } + + for _, test := range tests { + result, err := getResourceGroupFromDiskURI(test.diskURL) + assert.Equal(t, result, test.expectedResult, "Expect result not equal with getResourceGroupFromDiskURI(%s) return: %q, expected: %q", + test.diskURL, result, test.expectedResult) + + if test.expectError { + assert.NotNil(t, err, "Expect error during getResourceGroupFromDiskURI(%s)", test.diskURL) + } else { + assert.Nil(t, err, "Expect error is nil during getResourceGroupFromDiskURI(%s)", test.diskURL) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmsets.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmsets.go index 4d78b7595..34b69e859 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmsets.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmsets.go @@ -17,8 +17,8 @@ limitations under the License. package azure import ( - "github.com/Azure/azure-sdk-for-go/arm/compute" - "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" @@ -35,9 +35,9 @@ type VMSet interface { // GetInstanceTypeByNodeName gets the instance type by node name. GetInstanceTypeByNodeName(name string) (string, error) // GetIPByNodeName gets machine private IP and public IP by node name. - GetIPByNodeName(name, vmSetName string) (string, string, error) - // GetPrimaryInterface gets machine primary network interface by node name and vmSet. - GetPrimaryInterface(nodeName, vmSetName string) (network.Interface, error) + GetIPByNodeName(name string) (string, string, error) + // GetPrimaryInterface gets machine primary network interface by node name. + GetPrimaryInterface(nodeName string) (network.Interface, error) // GetNodeNameByProviderID gets the node name by provider ID. GetNodeNameByProviderID(providerID string) (types.NodeName, error) @@ -54,18 +54,14 @@ type VMSet interface { GetVMSetNames(service *v1.Service, nodes []*v1.Node) (availabilitySetNames *[]string, err error) // EnsureHostsInPool ensures the given Node's primary IP configurations are // participating in the specified LoadBalancer Backend Pool. - EnsureHostsInPool(serviceName string, nodes []*v1.Node, backendPoolID string, vmSetName string) error + EnsureHostsInPool(serviceName string, nodes []*v1.Node, backendPoolID string, vmSetName string, isInternal bool) error // EnsureBackendPoolDeleted ensures the loadBalancer backendAddressPools deleted from the specified vmSet. - EnsureBackendPoolDeleted(poolID, vmSetName string) error + EnsureBackendPoolDeleted(poolID, vmSetName string, backendAddressPools *[]network.BackendAddressPool) error // AttachDisk attaches a vhd to vm. The vhd must exist, can be identified by diskName, diskURI, and lun. AttachDisk(isManagedDisk bool, diskName, diskURI string, nodeName types.NodeName, lun int32, cachingMode compute.CachingTypes) error // DetachDiskByName detaches a vhd from host. The vhd can be identified by diskName or diskURI. DetachDiskByName(diskName, diskURI string, nodeName types.NodeName) error - // GetDiskLun finds the lun on the host that the vhd is attached to, given a vhd's diskName and diskURI. - GetDiskLun(diskName, diskURI string, nodeName types.NodeName) (int32, error) - // GetNextDiskLun searches all vhd attachment on the host and find unused lun. Return -1 if all luns are used. - GetNextDiskLun(nodeName types.NodeName) (int32, error) - // DisksAreAttached checks if a list of volumes are attached to the node with the specified NodeName. - DisksAreAttached(diskNames []string, nodeName types.NodeName) (map[string]bool, error) + // GetDataDisks gets a list of data disks attached to the node. + GetDataDisks(nodeName types.NodeName) ([]compute.DataDisk, error) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss.go index bc064bbd2..c7fa190b1 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss.go @@ -24,13 +24,14 @@ import ( "strconv" "strings" - "github.com/Azure/azure-sdk-for-go/arm/network" - computepreview "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" "github.com/golang/glog" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/cloudprovider" ) @@ -90,7 +91,7 @@ func newScaleSet(az *Cloud) (VMSet, error) { // getVmssVM gets virtualMachineScaleSetVM by nodeName from cache. // It returns cloudprovider.InstanceNotFound if node does not belong to any scale sets. -func (ss *scaleSet) getVmssVM(nodeName string) (ssName, instanceID string, vm computepreview.VirtualMachineScaleSetVM, err error) { +func (ss *scaleSet) getVmssVM(nodeName string) (ssName, instanceID string, vm compute.VirtualMachineScaleSetVM, err error) { instanceID, err = getScaleSetVMInstanceID(nodeName) if err != nil { return ssName, instanceID, vm, err @@ -116,12 +117,12 @@ func (ss *scaleSet) getVmssVM(nodeName string) (ssName, instanceID string, vm co return ssName, instanceID, vm, cloudprovider.InstanceNotFound } - return ssName, instanceID, *(cachedVM.(*computepreview.VirtualMachineScaleSetVM)), nil + return ssName, instanceID, *(cachedVM.(*compute.VirtualMachineScaleSetVM)), nil } // getCachedVirtualMachineByInstanceID gets scaleSetVMInfo from cache. // The node must belong to one of scale sets. -func (ss *scaleSet) getVmssVMByInstanceID(scaleSetName, instanceID string) (vm computepreview.VirtualMachineScaleSetVM, err error) { +func (ss *scaleSet) getVmssVMByInstanceID(scaleSetName, instanceID string) (vm compute.VirtualMachineScaleSetVM, err error) { vmName := ss.makeVmssVMName(scaleSetName, instanceID) cachedVM, err := ss.vmssVMCache.Get(vmName) if err != nil { @@ -133,7 +134,7 @@ func (ss *scaleSet) getVmssVMByInstanceID(scaleSetName, instanceID string) (vm c return vm, cloudprovider.InstanceNotFound } - return *(cachedVM.(*computepreview.VirtualMachineScaleSetVM)), nil + return *(cachedVM.(*compute.VirtualMachineScaleSetVM)), nil } // GetInstanceIDByNodeName gets the cloud provider ID by node name. @@ -161,7 +162,7 @@ func (ss *scaleSet) GetInstanceIDByNodeName(name string) (string, error) { // GetNodeNameByProviderID gets the node name by provider ID. func (ss *scaleSet) GetNodeNameByProviderID(providerID string) (types.NodeName, error) { // NodeName is not part of providerID for vmss instances. - scaleSetName, err := extractScaleSetNameByExternalID(providerID) + scaleSetName, err := extractScaleSetNameByProviderID(providerID) if err != nil { glog.V(4).Infof("Can not extract scale set name from providerID (%s), assuming it is mananaged by availability set: %v", providerID, err) return ss.availabilitySet.GetNodeNameByProviderID(providerID) @@ -246,10 +247,10 @@ func (ss *scaleSet) GetPrimaryVMSetName() string { // GetIPByNodeName gets machine private IP and public IP by node name. // TODO(feiskyer): Azure vmss doesn't support associating a public IP to single virtual machine yet, // fix this after it is supported. -func (ss *scaleSet) GetIPByNodeName(nodeName, vmSetName string) (string, string, error) { - nic, err := ss.GetPrimaryInterface(nodeName, vmSetName) +func (ss *scaleSet) GetIPByNodeName(nodeName string) (string, string, error) { + nic, err := ss.GetPrimaryInterface(nodeName) if err != nil { - glog.Errorf("error: ss.GetIPByNodeName(%s), GetPrimaryInterface(%q, %q), err=%v", nodeName, nodeName, vmSetName, err) + glog.Errorf("error: ss.GetIPByNodeName(%s), GetPrimaryInterface(%q), err=%v", nodeName, nodeName, err) return "", "", err } @@ -264,7 +265,7 @@ func (ss *scaleSet) GetIPByNodeName(nodeName, vmSetName string) (string, string, } // This returns the full identifier of the primary NIC for the given VM. -func (ss *scaleSet) getPrimaryInterfaceID(machine computepreview.VirtualMachineScaleSetVM) (string, error) { +func (ss *scaleSet) getPrimaryInterfaceID(machine compute.VirtualMachineScaleSetVM) (string, error) { if len(*machine.NetworkProfile.NetworkInterfaces) == 1 { return *(*machine.NetworkProfile.NetworkInterfaces)[0].ID, nil } @@ -295,9 +296,9 @@ func getScaleSetVMInstanceID(machineName string) (string, error) { return fmt.Sprintf("%d", instanceID), nil } -// extractScaleSetNameByExternalID extracts the scaleset name by node's externalID. -func extractScaleSetNameByExternalID(externalID string) (string, error) { - matches := scaleSetNameRE.FindStringSubmatch(externalID) +// extractScaleSetNameByProviderID extracts the scaleset name by node's ProviderID. +func extractScaleSetNameByProviderID(providerID string) (string, error) { + matches := scaleSetNameRE.FindStringSubmatch(providerID) if len(matches) != 2 { return "", ErrorNotVmssInstance } @@ -326,12 +327,12 @@ func (ss *scaleSet) listScaleSets() ([]string, error) { } // listScaleSetVMs lists VMs belonging to the specified scale set. -func (ss *scaleSet) listScaleSetVMs(scaleSetName string) ([]computepreview.VirtualMachineScaleSetVM, error) { +func (ss *scaleSet) listScaleSetVMs(scaleSetName string) ([]compute.VirtualMachineScaleSetVM, error) { var err error ctx, cancel := getContextWithCancel() defer cancel() - allVMs, err := ss.VirtualMachineScaleSetVMsClient.List(ctx, ss.ResourceGroup, scaleSetName, "", "", string(computepreview.InstanceView)) + allVMs, err := ss.VirtualMachineScaleSetVMsClient.List(ctx, ss.ResourceGroup, scaleSetName, "", "", string(compute.InstanceView)) if err != nil { glog.Errorf("VirtualMachineScaleSetVMsClient.List failed: %v", err) return nil, err @@ -417,7 +418,7 @@ func (ss *scaleSet) GetVMSetNames(service *v1.Service, nodes []*v1.Node) (vmSetN } // GetPrimaryInterface gets machine primary network interface by node name and vmSet. -func (ss *scaleSet) GetPrimaryInterface(nodeName, vmSetName string) (network.Interface, error) { +func (ss *scaleSet) GetPrimaryInterface(nodeName string) (network.Interface, error) { managedByAS, err := ss.isNodeManagedByAvailabilitySet(nodeName) if err != nil { glog.Errorf("Failed to check isNodeManagedByAvailabilitySet: %v", err) @@ -425,7 +426,7 @@ func (ss *scaleSet) GetPrimaryInterface(nodeName, vmSetName string) (network.Int } if managedByAS { // vm is managed by availability set. - return ss.availabilitySet.GetPrimaryInterface(nodeName, "") + return ss.availabilitySet.GetPrimaryInterface(nodeName) } ssName, instanceID, vm, err := ss.getVmssVM(nodeName) @@ -434,11 +435,6 @@ func (ss *scaleSet) GetPrimaryInterface(nodeName, vmSetName string) (network.Int return network.Interface{}, err } - // Check scale set name. - if vmSetName != "" && !strings.EqualFold(ssName, vmSetName) { - return network.Interface{}, errNotInVMSet - } - primaryInterfaceID, err := ss.getPrimaryInterfaceID(vm) if err != nil { glog.Errorf("error: ss.GetPrimaryInterface(%s), ss.getPrimaryInterfaceID(), err=%v", nodeName, err) @@ -451,7 +447,9 @@ func (ss *scaleSet) GetPrimaryInterface(nodeName, vmSetName string) (network.Int return network.Interface{}, err } - nic, err := ss.InterfacesClient.GetVirtualMachineScaleSetNetworkInterface(ss.ResourceGroup, ssName, instanceID, nicName, "") + ctx, cancel := getContextWithCancel() + defer cancel() + nic, err := ss.InterfacesClient.GetVirtualMachineScaleSetNetworkInterface(ctx, ss.ResourceGroup, ssName, instanceID, nicName, "") if err != nil { glog.Errorf("error: ss.GetPrimaryInterface(%s), ss.GetVirtualMachineScaleSetNetworkInterface.Get(%s, %s, %s), err=%v", nodeName, ss.ResourceGroup, ssName, nicName, err) return network.Interface{}, err @@ -467,8 +465,8 @@ func (ss *scaleSet) GetPrimaryInterface(nodeName, vmSetName string) (network.Int } // getScaleSetWithRetry gets scale set with exponential backoff retry -func (ss *scaleSet) getScaleSetWithRetry(name string) (computepreview.VirtualMachineScaleSet, bool, error) { - var result computepreview.VirtualMachineScaleSet +func (ss *scaleSet) getScaleSetWithRetry(name string) (compute.VirtualMachineScaleSet, bool, error) { + var result compute.VirtualMachineScaleSet var exists bool err := wait.ExponentialBackoff(ss.requestBackoff(), func() (bool, error) { @@ -481,7 +479,7 @@ func (ss *scaleSet) getScaleSetWithRetry(name string) (computepreview.VirtualMac if cached != nil { exists = true - result = *(cached.(*computepreview.VirtualMachineScaleSet)) + result = *(cached.(*compute.VirtualMachineScaleSet)) } return true, nil @@ -491,7 +489,7 @@ func (ss *scaleSet) getScaleSetWithRetry(name string) (computepreview.VirtualMac } // getPrimaryNetworkConfiguration gets primary network interface configuration for scale sets. -func (ss *scaleSet) getPrimaryNetworkConfiguration(networkConfigurationList *[]computepreview.VirtualMachineScaleSetNetworkConfiguration, scaleSetName string) (*computepreview.VirtualMachineScaleSetNetworkConfiguration, error) { +func (ss *scaleSet) getPrimaryNetworkConfiguration(networkConfigurationList *[]compute.VirtualMachineScaleSetNetworkConfiguration, scaleSetName string) (*compute.VirtualMachineScaleSetNetworkConfiguration, error) { networkConfigurations := *networkConfigurationList if len(networkConfigurations) == 1 { return &networkConfigurations[0], nil @@ -507,7 +505,7 @@ func (ss *scaleSet) getPrimaryNetworkConfiguration(networkConfigurationList *[]c return nil, fmt.Errorf("failed to find a primary network configuration for the scale set %q", scaleSetName) } -func (ss *scaleSet) getPrimaryIPConfigForScaleSet(config *computepreview.VirtualMachineScaleSetNetworkConfiguration, scaleSetName string) (*computepreview.VirtualMachineScaleSetIPConfiguration, error) { +func (ss *scaleSet) getPrimaryIPConfigForScaleSet(config *compute.VirtualMachineScaleSetNetworkConfiguration, scaleSetName string) (*compute.VirtualMachineScaleSetIPConfiguration, error) { ipConfigurations := *config.IPConfigurations if len(ipConfigurations) == 1 { return &ipConfigurations[0], nil @@ -524,7 +522,7 @@ func (ss *scaleSet) getPrimaryIPConfigForScaleSet(config *computepreview.Virtual } // createOrUpdateVMSSWithRetry invokes ss.VirtualMachineScaleSetsClient.CreateOrUpdate with exponential backoff retry. -func (ss *scaleSet) createOrUpdateVMSSWithRetry(virtualMachineScaleSet computepreview.VirtualMachineScaleSet) error { +func (ss *scaleSet) createOrUpdateVMSSWithRetry(virtualMachineScaleSet compute.VirtualMachineScaleSet) error { return wait.ExponentialBackoff(ss.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -535,7 +533,7 @@ func (ss *scaleSet) createOrUpdateVMSSWithRetry(virtualMachineScaleSet computepr } // updateVMSSInstancesWithRetry invokes ss.VirtualMachineScaleSetsClient.UpdateInstances with exponential backoff retry. -func (ss *scaleSet) updateVMSSInstancesWithRetry(scaleSetName string, vmInstanceIDs computepreview.VirtualMachineScaleSetVMInstanceRequiredIDs) error { +func (ss *scaleSet) updateVMSSInstancesWithRetry(scaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) error { return wait.ExponentialBackoff(ss.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -545,9 +543,44 @@ func (ss *scaleSet) updateVMSSInstancesWithRetry(scaleSetName string, vmInstance }) } -// EnsureHostsInPool ensures the given Node's primary IP configurations are -// participating in the specified LoadBalancer Backend Pool. -func (ss *scaleSet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, backendPoolID string, vmSetName string) error { +// getNodesScaleSets returns scalesets with instanceIDs and standard node names for given nodes. +func (ss *scaleSet) getNodesScaleSets(nodes []*v1.Node) (map[string]sets.String, []*v1.Node, error) { + scalesets := make(map[string]sets.String) + standardNodes := []*v1.Node{} + + for _, curNode := range nodes { + if ss.useStandardLoadBalancer() && ss.excludeMasterNodesFromStandardLB() && isMasterNode(curNode) { + glog.V(4).Infof("Excluding master node %q from load balancer backendpool", curNode.Name) + continue + } + + curScaleSetName, err := extractScaleSetNameByProviderID(curNode.Spec.ProviderID) + if err != nil { + glog.V(4).Infof("Node %q is not belonging to any scale sets, assuming it is belong to availability sets", curNode.Name) + standardNodes = append(standardNodes, curNode) + continue + } + + if _, ok := scalesets[curScaleSetName]; !ok { + scalesets[curScaleSetName] = sets.NewString() + } + + instanceID, err := getLastSegment(curNode.Spec.ProviderID) + if err != nil { + glog.Errorf("Failed to get instance ID for node %q: %v", curNode.Spec.ProviderID, err) + return nil, nil, err + } + + scalesets[curScaleSetName].Insert(instanceID) + } + + return scalesets, standardNodes, nil +} + +// ensureHostsInVMSetPool ensures the given Node's primary IP configurations are +// participating in the vmSet's LoadBalancer Backend Pool. +func (ss *scaleSet) ensureHostsInVMSetPool(serviceName string, backendPoolID string, vmSetName string, instanceIDs []string, isInternal bool) error { + glog.V(3).Infof("ensuring hosts %q of scaleset %q in LB backendpool %q", instanceIDs, vmSetName, backendPoolID) virtualMachineScaleSet, exists, err := ss.getScaleSetWithRetry(vmSetName) if err != nil { glog.Errorf("ss.getScaleSetWithRetry(%s) for service %q failed: %v", vmSetName, serviceName, err) @@ -574,7 +607,7 @@ func (ss *scaleSet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, back // Update primary IP configuration's LoadBalancerBackendAddressPools. foundPool := false - newBackendPools := []computepreview.SubResource{} + newBackendPools := []compute.SubResource{} if primaryIPConfiguration.LoadBalancerBackendAddressPools != nil { newBackendPools = *primaryIPConfiguration.LoadBalancerBackendAddressPools } @@ -585,8 +618,26 @@ func (ss *scaleSet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, back } } if !foundPool { + if ss.useStandardLoadBalancer() && len(newBackendPools) > 0 { + // Although standard load balancer supports backends from multiple vmss, + // the same network interface couldn't be added to more than one load balancer of + // the same type. Omit those nodes (e.g. masters) so Azure ARM won't complain + // about this. + for _, pool := range newBackendPools { + backendPool := *pool.ID + matches := backendPoolIDRE.FindStringSubmatch(backendPool) + if len(matches) == 2 { + lbName := matches[1] + if strings.HasSuffix(lbName, InternalLoadBalancerNameSuffix) == isInternal { + glog.V(4).Infof("vmss %q has already been added to LB %q, omit adding it to a new one", vmSetName, lbName) + return nil + } + } + } + } + newBackendPools = append(newBackendPools, - computepreview.SubResource{ + compute.SubResource{ ID: to.StringPtr(backendPoolID), }) primaryIPConfiguration.LoadBalancerBackendAddressPools = &newBackendPools @@ -609,30 +660,8 @@ func (ss *scaleSet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, back } } - // Construct instanceIDs from nodes. - instanceIDs := []string{} - for _, curNode := range nodes { - curScaleSetName, err := extractScaleSetNameByExternalID(curNode.Spec.ExternalID) - if err != nil { - glog.V(4).Infof("Node %q is not belonging to any scale sets, omitting it", curNode.Name) - continue - } - if curScaleSetName != vmSetName { - glog.V(4).Infof("Node %q is not belonging to scale set %q, omitting it", curNode.Name, vmSetName) - continue - } - - instanceID, err := getLastSegment(curNode.Spec.ExternalID) - if err != nil { - glog.Errorf("Failed to get last segment from %q: %v", curNode.Spec.ExternalID, err) - return err - } - - instanceIDs = append(instanceIDs, instanceID) - } - // Update instances to latest VMSS model. - vmInstanceIDs := computepreview.VirtualMachineScaleSetVMInstanceRequiredIDs{ + vmInstanceIDs := compute.VirtualMachineScaleSetVMInstanceRequiredIDs{ InstanceIds: &instanceIDs, } ctx, cancel := getContextWithCancel() @@ -654,27 +683,68 @@ func (ss *scaleSet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, back return nil } -// EnsureBackendPoolDeleted ensures the loadBalancer backendAddressPools deleted from the specified vmSet. -func (ss *scaleSet) EnsureBackendPoolDeleted(poolID, vmSetName string) error { - virtualMachineScaleSet, exists, err := ss.getScaleSetWithRetry(vmSetName) +// EnsureHostsInPool ensures the given Node's primary IP configurations are +// participating in the specified LoadBalancer Backend Pool. +func (ss *scaleSet) EnsureHostsInPool(serviceName string, nodes []*v1.Node, backendPoolID string, vmSetName string, isInternal bool) error { + scalesets, standardNodes, err := ss.getNodesScaleSets(nodes) if err != nil { - glog.Errorf("ss.EnsureBackendPoolDeleted(%s, %s) getScaleSetWithRetry(%s) failed: %v", poolID, vmSetName, vmSetName, err) + glog.Errorf("getNodesScaleSets() for service %q failed: %v", serviceName, err) + return err + } + + for ssName, instanceIDs := range scalesets { + // Only add nodes belonging to specified vmSet for basic SKU LB. + if !ss.useStandardLoadBalancer() && !strings.EqualFold(ssName, vmSetName) { + continue + } + + if instanceIDs.Len() == 0 { + // This may happen when scaling a vmss capacity to 0. + glog.V(3).Infof("scale set %q has 0 nodes, adding it to load balancer anyway", ssName) + // InstanceIDs is required to update vmss, use * instead here since there are no nodes actually. + instanceIDs.Insert("*") + } + + err := ss.ensureHostsInVMSetPool(serviceName, backendPoolID, ssName, instanceIDs.List(), isInternal) + if err != nil { + glog.Errorf("ensureHostsInVMSetPool() with scaleSet %q for service %q failed: %v", ssName, serviceName, err) + return err + } + } + + if ss.useStandardLoadBalancer() && len(standardNodes) > 0 { + err := ss.availabilitySet.EnsureHostsInPool(serviceName, standardNodes, backendPoolID, "", isInternal) + if err != nil { + glog.Errorf("availabilitySet.EnsureHostsInPool() for service %q failed: %v", serviceName, err) + return err + } + } + + return nil +} + +// ensureScaleSetBackendPoolDeleted ensures the loadBalancer backendAddressPools deleted from the specified scaleset. +func (ss *scaleSet) ensureScaleSetBackendPoolDeleted(poolID, ssName string) error { + glog.V(3).Infof("ensuring backend pool %q deleted from scaleset %q", poolID, ssName) + virtualMachineScaleSet, exists, err := ss.getScaleSetWithRetry(ssName) + if err != nil { + glog.Errorf("ss.ensureScaleSetBackendPoolDeleted(%s, %s) getScaleSetWithRetry(%s) failed: %v", poolID, ssName, ssName, err) return err } if !exists { - glog.V(2).Infof("ss.EnsureBackendPoolDeleted(%s, %s), scale set %s has already been non-exist", poolID, vmSetName, vmSetName) + glog.V(2).Infof("ss.ensureScaleSetBackendPoolDeleted(%s, %s), scale set %s has already been non-exist", poolID, ssName, ssName) return nil } // Find primary network interface configuration. networkConfigureList := virtualMachineScaleSet.VirtualMachineProfile.NetworkProfile.NetworkInterfaceConfigurations - primaryNetworkConfiguration, err := ss.getPrimaryNetworkConfiguration(networkConfigureList, vmSetName) + primaryNetworkConfiguration, err := ss.getPrimaryNetworkConfiguration(networkConfigureList, ssName) if err != nil { return err } // Find primary IP configuration. - primaryIPConfiguration, err := ss.getPrimaryIPConfigForScaleSet(primaryNetworkConfiguration, vmSetName) + primaryIPConfiguration, err := ss.getPrimaryIPConfigForScaleSet(primaryNetworkConfiguration, ssName) if err != nil { return err } @@ -684,12 +754,12 @@ func (ss *scaleSet) EnsureBackendPoolDeleted(poolID, vmSetName string) error { return nil } existingBackendPools := *primaryIPConfiguration.LoadBalancerBackendAddressPools - newBackendPools := []computepreview.SubResource{} + newBackendPools := []compute.SubResource{} foundPool := false for i := len(existingBackendPools) - 1; i >= 0; i-- { curPool := existingBackendPools[i] if strings.EqualFold(poolID, *curPool.ID) { - glog.V(10).Infof("EnsureBackendPoolDeleted gets unwanted backend pool %q for scale set %q", poolID, vmSetName) + glog.V(10).Infof("ensureScaleSetBackendPoolDeleted gets unwanted backend pool %q for scale set %q", poolID, ssName) foundPool = true newBackendPools = append(existingBackendPools[:i], existingBackendPools[i+1:]...) } @@ -701,17 +771,17 @@ func (ss *scaleSet) EnsureBackendPoolDeleted(poolID, vmSetName string) error { // Update scale set with backoff. primaryIPConfiguration.LoadBalancerBackendAddressPools = &newBackendPools - glog.V(3).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating", vmSetName) + glog.V(3).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating", ssName) ctx, cancel := getContextWithCancel() defer cancel() - resp, err := ss.VirtualMachineScaleSetsClient.CreateOrUpdate(ctx, ss.ResourceGroup, vmSetName, virtualMachineScaleSet) - glog.V(10).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate(%q): end", vmSetName) + resp, err := ss.VirtualMachineScaleSetsClient.CreateOrUpdate(ctx, ss.ResourceGroup, ssName, virtualMachineScaleSet) + glog.V(10).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate(%q): end", ssName) if ss.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { - glog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating, err=%v", vmSetName, err) + glog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating, err=%v", ssName, err) retryErr := ss.createOrUpdateVMSSWithRetry(virtualMachineScaleSet) if retryErr != nil { err = retryErr - glog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate abort backoff: scale set (%s) - updating", vmSetName) + glog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate abort backoff: scale set (%s) - updating", ssName) } } if err != nil { @@ -720,17 +790,19 @@ func (ss *scaleSet) EnsureBackendPoolDeleted(poolID, vmSetName string) error { // Update instances to latest VMSS model. instanceIDs := []string{"*"} - vmInstanceIDs := computepreview.VirtualMachineScaleSetVMInstanceRequiredIDs{ + vmInstanceIDs := compute.VirtualMachineScaleSetVMInstanceRequiredIDs{ InstanceIds: &instanceIDs, } - instanceResp, err := ss.VirtualMachineScaleSetsClient.UpdateInstances(ctx, ss.ResourceGroup, vmSetName, vmInstanceIDs) - glog.V(10).Infof("VirtualMachineScaleSetsClient.UpdateInstances(%q): end", vmSetName) + instanceCtx, instanceCancel := getContextWithCancel() + defer instanceCancel() + instanceResp, err := ss.VirtualMachineScaleSetsClient.UpdateInstances(instanceCtx, ss.ResourceGroup, ssName, vmInstanceIDs) + glog.V(10).Infof("VirtualMachineScaleSetsClient.UpdateInstances(%q): end", ssName) if ss.CloudProviderBackoff && shouldRetryHTTPRequest(instanceResp, err) { - glog.V(2).Infof("VirtualMachineScaleSetsClient.UpdateInstances scale set (%s) - updating, err=%v", vmSetName, err) - retryErr := ss.updateVMSSInstancesWithRetry(vmSetName, vmInstanceIDs) + glog.V(2).Infof("VirtualMachineScaleSetsClient.UpdateInstances scale set (%s) - updating, err=%v", ssName, err) + retryErr := ss.updateVMSSInstancesWithRetry(ssName, vmInstanceIDs) if retryErr != nil { err = retryErr - glog.V(2).Infof("VirtualMachineScaleSetsClient.UpdateInstances abort backoff: scale set (%s) - updating", vmSetName) + glog.V(2).Infof("VirtualMachineScaleSetsClient.UpdateInstances abort backoff: scale set (%s) - updating", ssName) } } if err != nil { @@ -740,14 +812,16 @@ func (ss *scaleSet) EnsureBackendPoolDeleted(poolID, vmSetName string) error { // Update virtualMachineScaleSet again. This is a workaround for removing VMSS reference from LB. // TODO: remove this workaround when figuring out the root cause. if len(newBackendPools) == 0 { - glog.V(3).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating second time", vmSetName) - resp, err = ss.VirtualMachineScaleSetsClient.CreateOrUpdate(ctx, ss.ResourceGroup, vmSetName, virtualMachineScaleSet) - glog.V(10).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate(%q): end", vmSetName) + updateCtx, updateCancel := getContextWithCancel() + defer updateCancel() + glog.V(3).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating second time", ssName) + resp, err = ss.VirtualMachineScaleSetsClient.CreateOrUpdate(updateCtx, ss.ResourceGroup, ssName, virtualMachineScaleSet) + glog.V(10).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate(%q): end", ssName) if ss.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { - glog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating, err=%v", vmSetName, err) + glog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating, err=%v", ssName, err) retryErr := ss.createOrUpdateVMSSWithRetry(virtualMachineScaleSet) if retryErr != nil { - glog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate abort backoff: scale set (%s) - updating", vmSetName) + glog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate abort backoff: scale set (%s) - updating", ssName) } } } @@ -755,6 +829,48 @@ func (ss *scaleSet) EnsureBackendPoolDeleted(poolID, vmSetName string) error { return nil } +// EnsureBackendPoolDeleted ensures the loadBalancer backendAddressPools deleted from the specified vmSet. +func (ss *scaleSet) EnsureBackendPoolDeleted(poolID, vmSetName string, backendAddressPools *[]network.BackendAddressPool) error { + if backendAddressPools == nil { + return nil + } + + scalesets := sets.NewString() + for _, backendPool := range *backendAddressPools { + if strings.EqualFold(*backendPool.ID, poolID) && backendPool.BackendIPConfigurations != nil { + for _, ipConfigurations := range *backendPool.BackendIPConfigurations { + if ipConfigurations.ID == nil { + continue + } + + ssName, err := extractScaleSetNameByProviderID(*ipConfigurations.ID) + if err != nil { + glog.V(4).Infof("backend IP configuration %q is not belonging to any vmss, omit it") + continue + } + + scalesets.Insert(ssName) + } + break + } + } + + for ssName := range scalesets { + // Only remove nodes belonging to specified vmSet to basic LB backends. + if !ss.useStandardLoadBalancer() && !strings.EqualFold(ssName, vmSetName) { + continue + } + + err := ss.ensureScaleSetBackendPoolDeleted(poolID, ssName) + if err != nil { + glog.Errorf("ensureScaleSetBackendPoolDeleted() with scaleSet %q failed: %v", ssName, err) + return err + } + } + + return nil +} + // getVmssMachineID returns the full identifier of a vmss virtual machine. func (az *Cloud) getVmssMachineID(scaleSetName, instanceID string) string { return fmt.Sprintf( diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss_cache.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss_cache.go index e224845f3..5542b7ca0 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss_cache.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss_cache.go @@ -67,12 +67,13 @@ func (ss *scaleSet) newVmssCache() (*timedCache, error) { ctx, cancel := getContextWithCancel() defer cancel() result, err := ss.VirtualMachineScaleSetsClient.Get(ctx, ss.ResourceGroup, key) - exists, realErr := checkResourceExistsFromError(err) + exists, message, realErr := checkResourceExistsFromError(err) if realErr != nil { return nil, realErr } if !exists { + glog.V(2).Infof("Virtual machine scale set %q not found with message: %q", key, message) return nil, nil } @@ -147,12 +148,13 @@ func (ss *scaleSet) newVmssVMCache() (*timedCache, error) { ctx, cancel := getContextWithCancel() defer cancel() result, err := ss.VirtualMachineScaleSetVMsClient.Get(ctx, ss.ResourceGroup, ssName, instanceID) - exists, realErr := checkResourceExistsFromError(err) + exists, message, realErr := checkResourceExistsFromError(err) if realErr != nil { return nil, realErr } if !exists { + glog.V(2).Infof("Virtual machine scale set VM %q not found with message: %q", key, message) return nil, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss_test.go index e2403f258..192537d30 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_vmss_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - computepreview "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + compute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" "github.com/stretchr/testify/assert" ) @@ -37,8 +37,8 @@ func newTestScaleSet(scaleSetName string, vmList []string) (*scaleSet, error) { func setTestVirtualMachineCloud(ss *Cloud, scaleSetName string, vmList []string) { virtualMachineScaleSetsClient := newFakeVirtualMachineScaleSetsClient() - scaleSets := make(map[string]map[string]computepreview.VirtualMachineScaleSet) - scaleSets["rg"] = map[string]computepreview.VirtualMachineScaleSet{ + scaleSets := make(map[string]map[string]compute.VirtualMachineScaleSet) + scaleSets["rg"] = map[string]compute.VirtualMachineScaleSet{ scaleSetName: { Name: &scaleSetName, }, @@ -46,24 +46,24 @@ func setTestVirtualMachineCloud(ss *Cloud, scaleSetName string, vmList []string) virtualMachineScaleSetsClient.setFakeStore(scaleSets) virtualMachineScaleSetVMsClient := newFakeVirtualMachineScaleSetVMsClient() - ssVMs := make(map[string]map[string]computepreview.VirtualMachineScaleSetVM) - ssVMs["rg"] = make(map[string]computepreview.VirtualMachineScaleSetVM) + ssVMs := make(map[string]map[string]compute.VirtualMachineScaleSetVM) + ssVMs["rg"] = make(map[string]compute.VirtualMachineScaleSetVM) for i := range vmList { ID := fmt.Sprintf("/subscriptions/script/resourceGroups/rg/providers/Microsoft.Compute/virtualMachineScaleSets/%s/virtualMachines/%d", scaleSetName, i) nodeName := vmList[i] instanceID := fmt.Sprintf("%d", i) vmName := fmt.Sprintf("%s_%s", scaleSetName, instanceID) - networkInterfaces := []computepreview.NetworkInterfaceReference{ + networkInterfaces := []compute.NetworkInterfaceReference{ { ID: &nodeName, }, } - ssVMs["rg"][vmName] = computepreview.VirtualMachineScaleSetVM{ - VirtualMachineScaleSetVMProperties: &computepreview.VirtualMachineScaleSetVMProperties{ - OsProfile: &computepreview.OSProfile{ + ssVMs["rg"][vmName] = compute.VirtualMachineScaleSetVM{ + VirtualMachineScaleSetVMProperties: &compute.VirtualMachineScaleSetVMProperties{ + OsProfile: &compute.OSProfile{ ComputerName: &nodeName, }, - NetworkProfile: &computepreview.NetworkProfile{ + NetworkProfile: &compute.NetworkProfile{ NetworkInterfaces: &networkInterfaces, }, }, diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_wrap.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_wrap.go index 4c295c1a7..a02ebae93 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_wrap.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_wrap.go @@ -19,11 +19,13 @@ package azure import ( "fmt" "net/http" + "strings" "time" - "github.com/Azure/azure-sdk-for-go/arm/compute" - "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest" + "github.com/golang/glog" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/cloudprovider" @@ -39,18 +41,18 @@ var ( // checkExistsFromError inspects an error and returns a true if err is nil, // false if error is an autorest.Error with StatusCode=404 and will return the // error back if error is another status code or another type of error. -func checkResourceExistsFromError(err error) (bool, error) { +func checkResourceExistsFromError(err error) (bool, string, error) { if err == nil { - return true, nil + return true, "", nil } v, ok := err.(autorest.DetailedError) if !ok { - return false, err + return false, "", err } if v.StatusCode == http.StatusNotFound { - return false, nil + return false, err.Error(), nil } - return false, v + return false, "", v } // If it is StatusNotFound return nil, @@ -103,13 +105,17 @@ func (az *Cloud) getPublicIPAddress(pipResourceGroup string, pipName string) (pi } var realErr error - pip, err = az.PublicIPAddressesClient.Get(resourceGroup, pipName, "") - exists, realErr = checkResourceExistsFromError(err) + var message string + ctx, cancel := getContextWithCancel() + defer cancel() + pip, err = az.PublicIPAddressesClient.Get(ctx, resourceGroup, pipName, "") + exists, message, realErr = checkResourceExistsFromError(err) if realErr != nil { return pip, false, realErr } if !exists { + glog.V(2).Infof("Public IP %q not found with message: %q", pipName, message) return pip, false, nil } @@ -118,6 +124,7 @@ func (az *Cloud) getPublicIPAddress(pipResourceGroup string, pipName string) (pi func (az *Cloud) getSubnet(virtualNetworkName string, subnetName string) (subnet network.Subnet, exists bool, err error) { var realErr error + var message string var rg string if len(az.VnetResourceGroup) > 0 { @@ -126,13 +133,16 @@ func (az *Cloud) getSubnet(virtualNetworkName string, subnetName string) (subnet rg = az.ResourceGroup } - subnet, err = az.SubnetsClient.Get(rg, virtualNetworkName, subnetName, "") - exists, realErr = checkResourceExistsFromError(err) + ctx, cancel := getContextWithCancel() + defer cancel() + subnet, err = az.SubnetsClient.Get(ctx, rg, virtualNetworkName, subnetName, "") + exists, message, realErr = checkResourceExistsFromError(err) if realErr != nil { return subnet, false, realErr } if !exists { + glog.V(2).Infof("Subnet %q not found with message: %q", subnetName, message) return subnet, false, nil } @@ -153,6 +163,10 @@ func (az *Cloud) getAzureLoadBalancer(name string) (lb network.LoadBalancer, exi } func (az *Cloud) getSecurityGroup() (nsg network.SecurityGroup, err error) { + if az.SecurityGroupName == "" { + return nsg, fmt.Errorf("securityGroupName is not configured") + } + securityGroup, err := az.nsgCache.Get(az.SecurityGroupName) if err != nil { return nsg, err @@ -173,13 +187,16 @@ func (az *Cloud) newVMCache() (*timedCache, error) { // case we do get instance view every time to fulfill the azure_zones requirement without hitting // throttling. // Consider adding separate parameter for controlling 'InstanceView' once node update issue #56276 is fixed - vm, err := az.VirtualMachinesClient.Get(az.ResourceGroup, key, compute.InstanceView) - exists, realErr := checkResourceExistsFromError(err) + ctx, cancel := getContextWithCancel() + defer cancel() + vm, err := az.VirtualMachinesClient.Get(ctx, az.ResourceGroup, key, compute.InstanceView) + exists, message, realErr := checkResourceExistsFromError(err) if realErr != nil { return nil, realErr } if !exists { + glog.V(2).Infof("Virtual machine %q not found with message: %q", key, message) return nil, nil } @@ -191,13 +208,17 @@ func (az *Cloud) newVMCache() (*timedCache, error) { func (az *Cloud) newLBCache() (*timedCache, error) { getter := func(key string) (interface{}, error) { - lb, err := az.LoadBalancerClient.Get(az.ResourceGroup, key, "") - exists, realErr := checkResourceExistsFromError(err) + ctx, cancel := getContextWithCancel() + defer cancel() + + lb, err := az.LoadBalancerClient.Get(ctx, az.ResourceGroup, key, "") + exists, message, realErr := checkResourceExistsFromError(err) if realErr != nil { return nil, realErr } if !exists { + glog.V(2).Infof("Load balancer %q not found with message: %q", key, message) return nil, nil } @@ -209,13 +230,16 @@ func (az *Cloud) newLBCache() (*timedCache, error) { func (az *Cloud) newNSGCache() (*timedCache, error) { getter := func(key string) (interface{}, error) { - nsg, err := az.SecurityGroupsClient.Get(az.ResourceGroup, key, "") - exists, realErr := checkResourceExistsFromError(err) + ctx, cancel := getContextWithCancel() + defer cancel() + nsg, err := az.SecurityGroupsClient.Get(ctx, az.ResourceGroup, key, "") + exists, message, realErr := checkResourceExistsFromError(err) if realErr != nil { return nil, realErr } if !exists { + glog.V(2).Infof("Security group %q not found with message: %q", key, message) return nil, nil } @@ -227,13 +251,16 @@ func (az *Cloud) newNSGCache() (*timedCache, error) { func (az *Cloud) newRouteTableCache() (*timedCache, error) { getter := func(key string) (interface{}, error) { - rt, err := az.RouteTablesClient.Get(az.ResourceGroup, key, "") - exists, realErr := checkResourceExistsFromError(err) + ctx, cancel := getContextWithCancel() + defer cancel() + rt, err := az.RouteTablesClient.Get(ctx, az.ResourceGroup, key, "") + exists, message, realErr := checkResourceExistsFromError(err) if realErr != nil { return nil, realErr } if !exists { + glog.V(2).Infof("Route table %q not found with message: %q", key, message) return nil, nil } @@ -242,3 +269,11 @@ func (az *Cloud) newRouteTableCache() (*timedCache, error) { return newTimedcache(rtCacheTTL, getter) } + +func (az *Cloud) useStandardLoadBalancer() bool { + return strings.EqualFold(az.LoadBalancerSku, loadBalancerSkuStandard) +} + +func (az *Cloud) excludeMasterNodesFromStandardLB() bool { + return az.ExcludeMasterFromStandardLB != nil && *az.ExcludeMasterFromStandardLB +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_wrap_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_wrap_test.go index 380194ba9..5ab090c2a 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_wrap_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/azure/azure_wrap_test.go @@ -42,7 +42,7 @@ func TestExtractNotFound(t *testing.T) { } for _, test := range tests { - exists, err := checkResourceExistsFromError(test.err) + exists, _, err := checkResourceExistsFromError(test.err) if test.exists != exists { t.Errorf("expected: %v, saw: %v", test.exists, exists) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack/cloudstack_instances.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack/cloudstack_instances.go index cf8559a2b..264f43d1b 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack/cloudstack_instances.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack/cloudstack_instances.go @@ -80,11 +80,6 @@ func (cs *CSCloud) nodeAddresses(instance *cloudstack.VirtualMachine) ([]v1.Node return addresses, nil } -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (cs *CSCloud) ExternalID(ctx context.Context, name types.NodeName) (string, error) { - return cs.InstanceID(ctx, name) -} - // InstanceID returns the cloud provider ID of the specified instance. func (cs *CSCloud) InstanceID(ctx context.Context, name types.NodeName) (string, error) { instance, count, err := cs.client.VirtualMachine.GetVirtualMachineByName( @@ -135,7 +130,7 @@ func (cs *CSCloud) InstanceTypeByProviderID(ctx context.Context, providerID stri // AddSSHKeyToAllInstances is currently not implemented. func (cs *CSCloud) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error { - return errors.New("AddSSHKeyToAllInstances not implemented") + return cloudprovider.NotImplemented } // CurrentNodeName returns the name of the node we are currently running on. @@ -158,3 +153,8 @@ func (cs *CSCloud) InstanceExistsByProviderID(ctx context.Context, providerID st return true, nil } + +// InstanceShutdownByProviderID returns true if the instance is in safe state to detach volumes +func (cs *CSCloud) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, cloudprovider.NotImplemented +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack/metadata.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack/metadata.go index bffeb49cf..a7204d5d3 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack/metadata.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/cloudstack/metadata.go @@ -69,11 +69,6 @@ func (m *metadata) NodeAddressesByProviderID(ctx context.Context, providerID str return nil, errors.New("NodeAddressesByProviderID not implemented") } -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (m *metadata) ExternalID(ctx context.Context, name types.NodeName) (string, error) { - return m.InstanceID(ctx, name) -} - // InstanceID returns the cloud provider ID of the specified instance. func (m *metadata) InstanceID(ctx context.Context, name types.NodeName) (string, error) { instanceID, err := m.get(metadataTypeInstanceID) @@ -106,7 +101,7 @@ func (m *metadata) InstanceTypeByProviderID(ctx context.Context, providerID stri // AddSSHKeyToAllInstances is currently not implemented. func (m *metadata) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error { - return errors.New("AddSSHKeyToAllInstances not implemented") + return cloudprovider.NotImplemented } // CurrentNodeName returns the name of the node we are currently running on. @@ -119,6 +114,11 @@ func (m *metadata) InstanceExistsByProviderID(ctx context.Context, providerID st return false, errors.New("InstanceExistsByProviderID not implemented") } +// InstanceShutdownByProviderID returns if the instance is shutdown. +func (m *metadata) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, cloudprovider.NotImplemented +} + // GetZone returns the Zone containing the region that the program is running in. func (m *metadata) GetZone(ctx context.Context) (cloudprovider.Zone, error) { zone := cloudprovider.Zone{} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/fake.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/fake.go index 6b4ee6825..b4e065a59 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/fake.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/fake.go @@ -50,8 +50,10 @@ type FakeCloud struct { Exists bool Err error - ExistsByProviderID bool - ErrByProviderID error + ExistsByProviderID bool + ErrByProviderID error + NodeShutdown bool + ErrShutdownByProviderID error Calls []string Addresses []v1.NodeAddress @@ -208,14 +210,6 @@ func (f *FakeCloud) NodeAddressesByProviderID(ctx context.Context, providerID st return f.Addresses, f.Err } -// ExternalID is a test-spy implementation of Instances.ExternalID. -// It adds an entry "external-id" into the internal method call record. -// It returns an external id to the mapped instance name, if not found, it will return "ext-{instance}" -func (f *FakeCloud) ExternalID(ctx context.Context, nodeName types.NodeName) (string, error) { - f.addCall("external-id") - return f.ExtID[nodeName], f.Err -} - // InstanceID returns the cloud provider ID of the node with the specified Name. func (f *FakeCloud) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) { f.addCall("instance-id") @@ -241,6 +235,12 @@ func (f *FakeCloud) InstanceExistsByProviderID(ctx context.Context, providerID s return f.ExistsByProviderID, f.ErrByProviderID } +// InstanceShutdownByProviderID returns true if the instances is in safe state to detach volumes +func (f *FakeCloud) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + f.addCall("instance-shutdown-by-provider-id") + return f.NodeShutdown, f.ErrShutdownByProviderID +} + // List is a test-spy implementation of Instances.List. // It adds an entry "list" into the internal method call record. func (f *FakeCloud) List(filter string) ([]types.NodeName, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/BUILD b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/BUILD index 5c04c1748..9368a8cf6 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/BUILD @@ -13,7 +13,6 @@ go_library( "gce.go", "gce_address_manager.go", "gce_addresses.go", - "gce_addresses_fakes.go", "gce_alpha.go", "gce_annotations.go", "gce_backendservice.go", @@ -32,8 +31,8 @@ go_library( "gce_loadbalancer_internal.go", "gce_loadbalancer_naming.go", "gce_networkendpointgroup.go", - "gce_op.go", "gce_routes.go", + "gce_securitypolicy.go", "gce_targetpool.go", "gce_targetproxy.go", "gce_tpu.go", @@ -70,7 +69,7 @@ go_library( "//vendor/google.golang.org/api/compute/v1:go_default_library", "//vendor/google.golang.org/api/container/v1:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", - "//vendor/google.golang.org/api/tpu/v1alpha1:go_default_library", + "//vendor/google.golang.org/api/tpu/v1:go_default_library", "//vendor/gopkg.in/gcfg.v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -101,16 +100,22 @@ go_test( "gce_disks_test.go", "gce_healthchecks_test.go", "gce_loadbalancer_external_test.go", + "gce_loadbalancer_internal_test.go", + "gce_loadbalancer_test.go", + "gce_loadbalancer_utils_test.go", "gce_test.go", "gce_util_test.go", "metrics_test.go", ], embed = [":go_default_library"], deps = [ + "//pkg/api/v1/service:go_default_library", "//pkg/cloudprovider:go_default_library", "//pkg/cloudprovider/providers/gce/cloud:go_default_library", + "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", "//pkg/cloudprovider/providers/gce/cloud/mock:go_default_library", "//pkg/kubelet/apis:go_default_library", + "//pkg/util/net/sets:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/golang.org/x/oauth2/google:go_default_library", @@ -122,6 +127,8 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/BUILD b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/BUILD index fa4631077..de46184e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/BUILD @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "constants.go", + "context.go", "doc.go", "gce_projects.go", "gen.go", @@ -31,6 +32,8 @@ go_test( srcs = [ "gen_test.go", "mock_test.go", + "ratelimit_test.go", + "service_test.go", "utils_test.go", ], embed = [":go_default_library"], diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/context.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/context.go new file mode 100644 index 000000000..307a0a7a4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/context.go @@ -0,0 +1,31 @@ +/* +Copyright 2018 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 cloud + +import ( + "context" + "time" +) + +const ( + defaultCallTimeout = 1 * time.Hour +) + +// ContextWithCallTimeout returns a context with a default timeout, used for generated client calls. +func ContextWithCallTimeout() (context.Context, context.CancelFunc) { + return context.WithTimeout(context.Background(), defaultCallTimeout) +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/doc.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/doc.go index a6b121457..23b4ae838 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/doc.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/doc.go @@ -109,4 +109,9 @@ limitations under the License. // func (gce *GCEInstanceGroups) MyMethod() { // // Custom implementation. // } +// +// Update generated codes +// +// Run hack/update-cloudprovider-gce.sh to update the generated codes. +// package cloud diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen.go index 3992adca9..2b6e24583 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen.go @@ -43,12 +43,12 @@ type Cloud interface { BetaAddresses() BetaAddresses GlobalAddresses() GlobalAddresses BackendServices() BackendServices + BetaBackendServices() BetaBackendServices AlphaBackendServices() AlphaBackendServices RegionBackendServices() RegionBackendServices AlphaRegionBackendServices() AlphaRegionBackendServices Disks() Disks - AlphaDisks() AlphaDisks - AlphaRegionDisks() AlphaRegionDisks + BetaRegionDisks() BetaRegionDisks Firewalls() Firewalls ForwardingRules() ForwardingRules AlphaForwardingRules() AlphaForwardingRules @@ -65,6 +65,7 @@ type Cloud interface { Projects() Projects Regions() Regions Routes() Routes + BetaSecurityPolicies() BetaSecurityPolicies SslCertificates() SslCertificates TargetHttpProxies() TargetHttpProxies TargetHttpsProxies() TargetHttpsProxies @@ -81,12 +82,12 @@ func NewGCE(s *Service) *GCE { gceBetaAddresses: &GCEBetaAddresses{s}, gceGlobalAddresses: &GCEGlobalAddresses{s}, gceBackendServices: &GCEBackendServices{s}, + gceBetaBackendServices: &GCEBetaBackendServices{s}, gceAlphaBackendServices: &GCEAlphaBackendServices{s}, gceRegionBackendServices: &GCERegionBackendServices{s}, gceAlphaRegionBackendServices: &GCEAlphaRegionBackendServices{s}, gceDisks: &GCEDisks{s}, - gceAlphaDisks: &GCEAlphaDisks{s}, - gceAlphaRegionDisks: &GCEAlphaRegionDisks{s}, + gceBetaRegionDisks: &GCEBetaRegionDisks{s}, gceFirewalls: &GCEFirewalls{s}, gceForwardingRules: &GCEForwardingRules{s}, gceAlphaForwardingRules: &GCEAlphaForwardingRules{s}, @@ -103,6 +104,7 @@ func NewGCE(s *Service) *GCE { gceProjects: &GCEProjects{s}, gceRegions: &GCERegions{s}, gceRoutes: &GCERoutes{s}, + gceBetaSecurityPolicies: &GCEBetaSecurityPolicies{s}, gceSslCertificates: &GCESslCertificates{s}, gceTargetHttpProxies: &GCETargetHttpProxies{s}, gceTargetHttpsProxies: &GCETargetHttpsProxies{s}, @@ -123,12 +125,12 @@ type GCE struct { gceBetaAddresses *GCEBetaAddresses gceGlobalAddresses *GCEGlobalAddresses gceBackendServices *GCEBackendServices + gceBetaBackendServices *GCEBetaBackendServices gceAlphaBackendServices *GCEAlphaBackendServices gceRegionBackendServices *GCERegionBackendServices gceAlphaRegionBackendServices *GCEAlphaRegionBackendServices gceDisks *GCEDisks - gceAlphaDisks *GCEAlphaDisks - gceAlphaRegionDisks *GCEAlphaRegionDisks + gceBetaRegionDisks *GCEBetaRegionDisks gceFirewalls *GCEFirewalls gceForwardingRules *GCEForwardingRules gceAlphaForwardingRules *GCEAlphaForwardingRules @@ -145,6 +147,7 @@ type GCE struct { gceProjects *GCEProjects gceRegions *GCERegions gceRoutes *GCERoutes + gceBetaSecurityPolicies *GCEBetaSecurityPolicies gceSslCertificates *GCESslCertificates gceTargetHttpProxies *GCETargetHttpProxies gceTargetHttpsProxies *GCETargetHttpsProxies @@ -178,6 +181,11 @@ func (gce *GCE) BackendServices() BackendServices { return gce.gceBackendServices } +// BetaBackendServices returns the interface for the beta BackendServices. +func (gce *GCE) BetaBackendServices() BetaBackendServices { + return gce.gceBetaBackendServices +} + // AlphaBackendServices returns the interface for the alpha BackendServices. func (gce *GCE) AlphaBackendServices() AlphaBackendServices { return gce.gceAlphaBackendServices @@ -198,14 +206,9 @@ func (gce *GCE) Disks() Disks { return gce.gceDisks } -// AlphaDisks returns the interface for the alpha Disks. -func (gce *GCE) AlphaDisks() AlphaDisks { - return gce.gceAlphaDisks -} - -// AlphaRegionDisks returns the interface for the alpha RegionDisks. -func (gce *GCE) AlphaRegionDisks() AlphaRegionDisks { - return gce.gceAlphaRegionDisks +// BetaRegionDisks returns the interface for the beta RegionDisks. +func (gce *GCE) BetaRegionDisks() BetaRegionDisks { + return gce.gceBetaRegionDisks } // Firewalls returns the interface for the ga Firewalls. @@ -288,6 +291,11 @@ func (gce *GCE) Routes() Routes { return gce.gceRoutes } +// BetaSecurityPolicies returns the interface for the beta SecurityPolicies. +func (gce *GCE) BetaSecurityPolicies() BetaSecurityPolicies { + return gce.gceBetaSecurityPolicies +} + // SslCertificates returns the interface for the ga SslCertificates. func (gce *GCE) SslCertificates() SslCertificates { return gce.gceSslCertificates @@ -338,6 +346,7 @@ func NewMockGCE(projectRouter ProjectRouter) *MockGCE { mockRegionDisksObjs := map[meta.Key]*MockRegionDisksObj{} mockRegionsObjs := map[meta.Key]*MockRegionsObj{} mockRoutesObjs := map[meta.Key]*MockRoutesObj{} + mockSecurityPoliciesObjs := map[meta.Key]*MockSecurityPoliciesObj{} mockSslCertificatesObjs := map[meta.Key]*MockSslCertificatesObj{} mockTargetHttpProxiesObjs := map[meta.Key]*MockTargetHttpProxiesObj{} mockTargetHttpsProxiesObjs := map[meta.Key]*MockTargetHttpsProxiesObj{} @@ -351,12 +360,12 @@ func NewMockGCE(projectRouter ProjectRouter) *MockGCE { MockBetaAddresses: NewMockBetaAddresses(projectRouter, mockAddressesObjs), MockGlobalAddresses: NewMockGlobalAddresses(projectRouter, mockGlobalAddressesObjs), MockBackendServices: NewMockBackendServices(projectRouter, mockBackendServicesObjs), + MockBetaBackendServices: NewMockBetaBackendServices(projectRouter, mockBackendServicesObjs), MockAlphaBackendServices: NewMockAlphaBackendServices(projectRouter, mockBackendServicesObjs), MockRegionBackendServices: NewMockRegionBackendServices(projectRouter, mockRegionBackendServicesObjs), MockAlphaRegionBackendServices: NewMockAlphaRegionBackendServices(projectRouter, mockRegionBackendServicesObjs), MockDisks: NewMockDisks(projectRouter, mockDisksObjs), - MockAlphaDisks: NewMockAlphaDisks(projectRouter, mockDisksObjs), - MockAlphaRegionDisks: NewMockAlphaRegionDisks(projectRouter, mockRegionDisksObjs), + MockBetaRegionDisks: NewMockBetaRegionDisks(projectRouter, mockRegionDisksObjs), MockFirewalls: NewMockFirewalls(projectRouter, mockFirewallsObjs), MockForwardingRules: NewMockForwardingRules(projectRouter, mockForwardingRulesObjs), MockAlphaForwardingRules: NewMockAlphaForwardingRules(projectRouter, mockForwardingRulesObjs), @@ -373,6 +382,7 @@ func NewMockGCE(projectRouter ProjectRouter) *MockGCE { MockProjects: NewMockProjects(projectRouter, mockProjectsObjs), MockRegions: NewMockRegions(projectRouter, mockRegionsObjs), MockRoutes: NewMockRoutes(projectRouter, mockRoutesObjs), + MockBetaSecurityPolicies: NewMockBetaSecurityPolicies(projectRouter, mockSecurityPoliciesObjs), MockSslCertificates: NewMockSslCertificates(projectRouter, mockSslCertificatesObjs), MockTargetHttpProxies: NewMockTargetHttpProxies(projectRouter, mockTargetHttpProxiesObjs), MockTargetHttpsProxies: NewMockTargetHttpsProxies(projectRouter, mockTargetHttpsProxiesObjs), @@ -393,12 +403,12 @@ type MockGCE struct { MockBetaAddresses *MockBetaAddresses MockGlobalAddresses *MockGlobalAddresses MockBackendServices *MockBackendServices + MockBetaBackendServices *MockBetaBackendServices MockAlphaBackendServices *MockAlphaBackendServices MockRegionBackendServices *MockRegionBackendServices MockAlphaRegionBackendServices *MockAlphaRegionBackendServices MockDisks *MockDisks - MockAlphaDisks *MockAlphaDisks - MockAlphaRegionDisks *MockAlphaRegionDisks + MockBetaRegionDisks *MockBetaRegionDisks MockFirewalls *MockFirewalls MockForwardingRules *MockForwardingRules MockAlphaForwardingRules *MockAlphaForwardingRules @@ -415,6 +425,7 @@ type MockGCE struct { MockProjects *MockProjects MockRegions *MockRegions MockRoutes *MockRoutes + MockBetaSecurityPolicies *MockBetaSecurityPolicies MockSslCertificates *MockSslCertificates MockTargetHttpProxies *MockTargetHttpProxies MockTargetHttpsProxies *MockTargetHttpsProxies @@ -448,6 +459,11 @@ func (mock *MockGCE) BackendServices() BackendServices { return mock.MockBackendServices } +// BetaBackendServices returns the interface for the beta BackendServices. +func (mock *MockGCE) BetaBackendServices() BetaBackendServices { + return mock.MockBetaBackendServices +} + // AlphaBackendServices returns the interface for the alpha BackendServices. func (mock *MockGCE) AlphaBackendServices() AlphaBackendServices { return mock.MockAlphaBackendServices @@ -468,14 +484,9 @@ func (mock *MockGCE) Disks() Disks { return mock.MockDisks } -// AlphaDisks returns the interface for the alpha Disks. -func (mock *MockGCE) AlphaDisks() AlphaDisks { - return mock.MockAlphaDisks -} - -// AlphaRegionDisks returns the interface for the alpha RegionDisks. -func (mock *MockGCE) AlphaRegionDisks() AlphaRegionDisks { - return mock.MockAlphaRegionDisks +// BetaRegionDisks returns the interface for the beta RegionDisks. +func (mock *MockGCE) BetaRegionDisks() BetaRegionDisks { + return mock.MockBetaRegionDisks } // Firewalls returns the interface for the ga Firewalls. @@ -558,6 +569,11 @@ func (mock *MockGCE) Routes() Routes { return mock.MockRoutes } +// BetaSecurityPolicies returns the interface for the beta SecurityPolicies. +func (mock *MockGCE) BetaSecurityPolicies() BetaSecurityPolicies { + return mock.MockBetaSecurityPolicies +} + // SslCertificates returns the interface for the ga SslCertificates. func (mock *MockGCE) SslCertificates() SslCertificates { return mock.MockSslCertificates @@ -654,6 +670,19 @@ func (m *MockBackendServicesObj) ToAlpha() *alpha.BackendService { return ret } +// ToBeta retrieves the given version of the object. +func (m *MockBackendServicesObj) ToBeta() *beta.BackendService { + if ret, ok := m.Obj.(*beta.BackendService); ok { + return ret + } + // Convert the object via JSON copying to the type that was requested. + ret := &beta.BackendService{} + if err := copyViaJSON(ret, m.Obj); err != nil { + glog.Errorf("Could not convert %T to *beta.BackendService via JSON: %v", m.Obj, err) + } + return ret +} + // ToGA retrieves the given version of the object. func (m *MockBackendServicesObj) ToGA() *ga.BackendService { if ret, ok := m.Obj.(*ga.BackendService); ok { @@ -674,19 +703,6 @@ type MockDisksObj struct { Obj interface{} } -// ToAlpha retrieves the given version of the object. -func (m *MockDisksObj) ToAlpha() *alpha.Disk { - if ret, ok := m.Obj.(*alpha.Disk); ok { - return ret - } - // Convert the object via JSON copying to the type that was requested. - ret := &alpha.Disk{} - if err := copyViaJSON(ret, m.Obj); err != nil { - glog.Errorf("Could not convert %T to *alpha.Disk via JSON: %v", m.Obj, err) - } - return ret -} - // ToGA retrieves the given version of the object. func (m *MockDisksObj) ToGA() *ga.Disk { if ret, ok := m.Obj.(*ga.Disk); ok { @@ -1012,15 +1028,15 @@ type MockRegionDisksObj struct { Obj interface{} } -// ToAlpha retrieves the given version of the object. -func (m *MockRegionDisksObj) ToAlpha() *alpha.Disk { - if ret, ok := m.Obj.(*alpha.Disk); ok { +// ToBeta retrieves the given version of the object. +func (m *MockRegionDisksObj) ToBeta() *beta.Disk { + if ret, ok := m.Obj.(*beta.Disk); ok { return ret } // Convert the object via JSON copying to the type that was requested. - ret := &alpha.Disk{} + ret := &beta.Disk{} if err := copyViaJSON(ret, m.Obj); err != nil { - glog.Errorf("Could not convert %T to *alpha.Disk via JSON: %v", m.Obj, err) + glog.Errorf("Could not convert %T to *beta.Disk via JSON: %v", m.Obj, err) } return ret } @@ -1065,6 +1081,26 @@ func (m *MockRoutesObj) ToGA() *ga.Route { return ret } +// MockSecurityPoliciesObj is used to store the various object versions in the shared +// map of mocked objects. This allows for multiple API versions to co-exist and +// share the same "view" of the objects in the backend. +type MockSecurityPoliciesObj struct { + Obj interface{} +} + +// ToBeta retrieves the given version of the object. +func (m *MockSecurityPoliciesObj) ToBeta() *beta.SecurityPolicy { + if ret, ok := m.Obj.(*beta.SecurityPolicy); ok { + return ret + } + // Convert the object via JSON copying to the type that was requested. + ret := &beta.SecurityPolicy{} + if err := copyViaJSON(ret, m.Obj); err != nil { + glog.Errorf("Could not convert %T to *beta.SecurityPolicy via JSON: %v", m.Obj, err) + } + return ret +} + // MockSslCertificatesObj is used to store the various object versions in the shared // map of mocked objects. This allows for multiple API versions to co-exist and // share the same "view" of the objects in the backend. @@ -2526,6 +2562,7 @@ type BackendServices interface { Insert(ctx context.Context, key *meta.Key, obj *ga.BackendService) error Delete(ctx context.Context, key *meta.Key) error GetHealth(context.Context, *meta.Key, *ga.ResourceGroupReference) (*ga.BackendServiceGroupHealth, error) + Patch(context.Context, *meta.Key, *ga.BackendService) error Update(context.Context, *meta.Key, *ga.BackendService) error } @@ -2567,6 +2604,7 @@ type MockBackendServices struct { InsertHook func(ctx context.Context, key *meta.Key, obj *ga.BackendService, m *MockBackendServices) (bool, error) DeleteHook func(ctx context.Context, key *meta.Key, m *MockBackendServices) (bool, error) GetHealthHook func(context.Context, *meta.Key, *ga.ResourceGroupReference, *MockBackendServices) (*ga.BackendServiceGroupHealth, error) + PatchHook func(context.Context, *meta.Key, *ga.BackendService, *MockBackendServices) error UpdateHook func(context.Context, *meta.Key, *ga.BackendService, *MockBackendServices) error // X is extra state that can be used as part of the mock. Generated code @@ -2721,6 +2759,14 @@ func (m *MockBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 return nil, fmt.Errorf("GetHealthHook must be set") } +// Patch is a mock for the corresponding method. +func (m *MockBackendServices) Patch(ctx context.Context, key *meta.Key, arg0 *ga.BackendService) error { + if m.PatchHook != nil { + return m.PatchHook(ctx, key, arg0, m) + } + return nil +} + // Update is a mock for the corresponding method. func (m *MockBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *ga.BackendService) error { if m.UpdateHook != nil { @@ -2899,6 +2945,39 @@ func (g *GCEBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 return v, err } +// Patch is a method on GCEBackendServices. +func (g *GCEBackendServices) Patch(ctx context.Context, key *meta.Key, arg0 *ga.BackendService) error { + glog.V(5).Infof("GCEBackendServices.Patch(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEBackendServices.Patch(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "BackendServices") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Patch", + Version: meta.Version("ga"), + Service: "BackendServices", + } + glog.V(5).Infof("GCEBackendServices.Patch(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEBackendServices.Patch(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.GA.BackendServices.Patch(projectID, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEBackendServices.Patch(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEBackendServices.Patch(%v, %v, ...) = %+v", ctx, key, err) + return err +} + // Update is a method on GCEBackendServices. func (g *GCEBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *ga.BackendService) error { glog.V(5).Infof("GCEBackendServices.Update(%v, %v, ...): called", ctx, key) @@ -2932,18 +3011,18 @@ func (g *GCEBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *ga return err } -// AlphaBackendServices is an interface that allows for mocking of BackendServices. -type AlphaBackendServices interface { - Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) - List(ctx context.Context, fl *filter.F) ([]*alpha.BackendService, error) - Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error +// BetaBackendServices is an interface that allows for mocking of BackendServices. +type BetaBackendServices interface { + Get(ctx context.Context, key *meta.Key) (*beta.BackendService, error) + List(ctx context.Context, fl *filter.F) ([]*beta.BackendService, error) + Insert(ctx context.Context, key *meta.Key, obj *beta.BackendService) error Delete(ctx context.Context, key *meta.Key) error - Update(context.Context, *meta.Key, *alpha.BackendService) error + SetSecurityPolicy(context.Context, *meta.Key, *beta.SecurityPolicyReference) error } -// NewMockAlphaBackendServices returns a new mock for BackendServices. -func NewMockAlphaBackendServices(pr ProjectRouter, objs map[meta.Key]*MockBackendServicesObj) *MockAlphaBackendServices { - mock := &MockAlphaBackendServices{ +// NewMockBetaBackendServices returns a new mock for BackendServices. +func NewMockBetaBackendServices(pr ProjectRouter, objs map[meta.Key]*MockBackendServicesObj) *MockBetaBackendServices { + mock := &MockBetaBackendServices{ ProjectRouter: pr, Objects: objs, @@ -2954,8 +3033,8 @@ func NewMockAlphaBackendServices(pr ProjectRouter, objs map[meta.Key]*MockBacken return mock } -// MockAlphaBackendServices is the mock for BackendServices. -type MockAlphaBackendServices struct { +// MockBetaBackendServices is the mock for BackendServices. +type MockBetaBackendServices struct { Lock sync.Mutex ProjectRouter ProjectRouter @@ -2974,11 +3053,11 @@ type MockAlphaBackendServices struct { // order to add your own logic. Return (true, _, _) to prevent the normal // execution flow of the mock. Return (false, nil, nil) to continue with // normal mock behavior/ after the hook function executes. - GetHook func(ctx context.Context, key *meta.Key, m *MockAlphaBackendServices) (bool, *alpha.BackendService, error) - ListHook func(ctx context.Context, fl *filter.F, m *MockAlphaBackendServices) (bool, []*alpha.BackendService, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.BackendService, m *MockAlphaBackendServices) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaBackendServices) (bool, error) - UpdateHook func(context.Context, *meta.Key, *alpha.BackendService, *MockAlphaBackendServices) error + GetHook func(ctx context.Context, key *meta.Key, m *MockBetaBackendServices) (bool, *beta.BackendService, error) + ListHook func(ctx context.Context, fl *filter.F, m *MockBetaBackendServices) (bool, []*beta.BackendService, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *beta.BackendService, m *MockBetaBackendServices) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockBetaBackendServices) (bool, error) + SetSecurityPolicyHook func(context.Context, *meta.Key, *beta.SecurityPolicyReference, *MockBetaBackendServices) error // X is extra state that can be used as part of the mock. Generated code // will not use this field. @@ -2986,10 +3065,10 @@ type MockAlphaBackendServices struct { } // Get returns the object from the mock. -func (m *MockAlphaBackendServices) Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) { +func (m *MockBetaBackendServices) Get(ctx context.Context, key *meta.Key) (*beta.BackendService, error) { if m.GetHook != nil { if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaBackendServices.Get(%v, %s) = %+v, %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaBackendServices.Get(%v, %s) = %+v, %v", ctx, key, obj, err) return obj, err } } @@ -3001,28 +3080,28 @@ func (m *MockAlphaBackendServices) Get(ctx context.Context, key *meta.Key) (*alp defer m.Lock.Unlock() if err, ok := m.GetError[*key]; ok { - glog.V(5).Infof("MockAlphaBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockBetaBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToAlpha() - glog.V(5).Infof("MockAlphaBackendServices.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + typedObj := obj.ToBeta() + glog.V(5).Infof("MockBetaBackendServices.Get(%v, %s) = %+v, nil", ctx, key, typedObj) return typedObj, nil } err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaBackendServices %v not found", key), + Message: fmt.Sprintf("MockBetaBackendServices %v not found", key), } - glog.V(5).Infof("MockAlphaBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockBetaBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } // List all of the objects in the mock. -func (m *MockAlphaBackendServices) List(ctx context.Context, fl *filter.F) ([]*alpha.BackendService, error) { +func (m *MockBetaBackendServices) List(ctx context.Context, fl *filter.F) ([]*beta.BackendService, error) { if m.ListHook != nil { if intercept, objs, err := m.ListHook(ctx, fl, m); intercept { - glog.V(5).Infof("MockAlphaBackendServices.List(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) + glog.V(5).Infof("MockBetaBackendServices.List(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) return objs, err } } @@ -3032,28 +3111,28 @@ func (m *MockAlphaBackendServices) List(ctx context.Context, fl *filter.F) ([]*a if m.ListError != nil { err := *m.ListError - glog.V(5).Infof("MockAlphaBackendServices.List(%v, %v) = nil, %v", ctx, fl, err) + glog.V(5).Infof("MockBetaBackendServices.List(%v, %v) = nil, %v", ctx, fl, err) return nil, *m.ListError } - var objs []*alpha.BackendService + var objs []*beta.BackendService for _, obj := range m.Objects { - if !fl.Match(obj.ToAlpha()) { + if !fl.Match(obj.ToBeta()) { continue } - objs = append(objs, obj.ToAlpha()) + objs = append(objs, obj.ToBeta()) } - glog.V(5).Infof("MockAlphaBackendServices.List(%v, %v) = [%v items], nil", ctx, fl, len(objs)) + glog.V(5).Infof("MockBetaBackendServices.List(%v, %v) = [%v items], nil", ctx, fl, len(objs)) return objs, nil } // Insert is a mock for inserting/creating a new object. -func (m *MockAlphaBackendServices) Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error { +func (m *MockBetaBackendServices) Insert(ctx context.Context, key *meta.Key, obj *beta.BackendService) error { if m.InsertHook != nil { if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - glog.V(5).Infof("MockAlphaBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } } @@ -3065,32 +3144,32 @@ func (m *MockAlphaBackendServices) Insert(ctx context.Context, key *meta.Key, ob defer m.Lock.Unlock() if err, ok := m.InsertError[*key]; ok { - glog.V(5).Infof("MockAlphaBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } if _, ok := m.Objects[*key]; ok { err := &googleapi.Error{ Code: http.StatusConflict, - Message: fmt.Sprintf("MockAlphaBackendServices %v exists", key), + Message: fmt.Sprintf("MockBetaBackendServices %v exists", key), } - glog.V(5).Infof("MockAlphaBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "alpha", "backendServices") - obj.SelfLink = SelfLink(meta.VersionAlpha, projectID, "backendServices", key) + projectID := m.ProjectRouter.ProjectID(ctx, "beta", "backendServices") + obj.SelfLink = SelfLink(meta.VersionBeta, projectID, "backendServices", key) m.Objects[*key] = &MockBackendServicesObj{obj} - glog.V(5).Infof("MockAlphaBackendServices.Insert(%v, %v, %+v) = nil", ctx, key, obj) + glog.V(5).Infof("MockBetaBackendServices.Insert(%v, %v, %+v) = nil", ctx, key, obj) return nil } // Delete is a mock for deleting the object. -func (m *MockAlphaBackendServices) Delete(ctx context.Context, key *meta.Key) error { +func (m *MockBetaBackendServices) Delete(ctx context.Context, key *meta.Key) error { if m.DeleteHook != nil { if intercept, err := m.DeleteHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } } @@ -3102,224 +3181,224 @@ func (m *MockAlphaBackendServices) Delete(ctx context.Context, key *meta.Key) er defer m.Lock.Unlock() if err, ok := m.DeleteError[*key]; ok { - glog.V(5).Infof("MockAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } if _, ok := m.Objects[*key]; !ok { err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaBackendServices %v not found", key), + Message: fmt.Sprintf("MockBetaBackendServices %v not found", key), } - glog.V(5).Infof("MockAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } delete(m.Objects, *key) - glog.V(5).Infof("MockAlphaBackendServices.Delete(%v, %v) = nil", ctx, key) + glog.V(5).Infof("MockBetaBackendServices.Delete(%v, %v) = nil", ctx, key) return nil } // Obj wraps the object for use in the mock. -func (m *MockAlphaBackendServices) Obj(o *alpha.BackendService) *MockBackendServicesObj { +func (m *MockBetaBackendServices) Obj(o *beta.BackendService) *MockBackendServicesObj { return &MockBackendServicesObj{o} } -// Update is a mock for the corresponding method. -func (m *MockAlphaBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { - if m.UpdateHook != nil { - return m.UpdateHook(ctx, key, arg0, m) +// SetSecurityPolicy is a mock for the corresponding method. +func (m *MockBetaBackendServices) SetSecurityPolicy(ctx context.Context, key *meta.Key, arg0 *beta.SecurityPolicyReference) error { + if m.SetSecurityPolicyHook != nil { + return m.SetSecurityPolicyHook(ctx, key, arg0, m) } return nil } -// GCEAlphaBackendServices is a simplifying adapter for the GCE BackendServices. -type GCEAlphaBackendServices struct { +// GCEBetaBackendServices is a simplifying adapter for the GCE BackendServices. +type GCEBetaBackendServices struct { s *Service } // Get the BackendService named by key. -func (g *GCEAlphaBackendServices) Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) { - glog.V(5).Infof("GCEAlphaBackendServices.Get(%v, %v): called", ctx, key) +func (g *GCEBetaBackendServices) Get(ctx context.Context, key *meta.Key) (*beta.BackendService, error) { + glog.V(5).Infof("GCEBetaBackendServices.Get(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaBackendServices.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaBackendServices.Get(%v, %v): key is invalid (%#v)", ctx, key, key) return nil, fmt.Errorf("invalid GCE key (%#v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Get", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "BackendServices", } - glog.V(5).Infof("GCEAlphaBackendServices.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaBackendServices.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaBackendServices.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaBackendServices.Get(%v, %v): RateLimiter error: %v", ctx, key, err) return nil, err } - call := g.s.Alpha.BackendServices.Get(projectID, key.Name) + call := g.s.Beta.BackendServices.Get(projectID, key.Name) call.Context(ctx) v, err := call.Do() - glog.V(4).Infof("GCEAlphaBackendServices.Get(%v, %v) = %+v, %v", ctx, key, v, err) + glog.V(4).Infof("GCEBetaBackendServices.Get(%v, %v) = %+v, %v", ctx, key, v, err) return v, err } // List all BackendService objects. -func (g *GCEAlphaBackendServices) List(ctx context.Context, fl *filter.F) ([]*alpha.BackendService, error) { - glog.V(5).Infof("GCEAlphaBackendServices.List(%v, %v) called", ctx, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") +func (g *GCEBetaBackendServices) List(ctx context.Context, fl *filter.F) ([]*beta.BackendService, error) { + glog.V(5).Infof("GCEBetaBackendServices.List(%v, %v) called", ctx, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "List", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "BackendServices", } if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { return nil, err } - glog.V(5).Infof("GCEAlphaBackendServices.List(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) - call := g.s.Alpha.BackendServices.List(projectID) + glog.V(5).Infof("GCEBetaBackendServices.List(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) + call := g.s.Beta.BackendServices.List(projectID) if fl != filter.None { call.Filter(fl.String()) } - var all []*alpha.BackendService - f := func(l *alpha.BackendServiceList) error { - glog.V(5).Infof("GCEAlphaBackendServices.List(%v, ..., %v): page %+v", ctx, fl, l) + var all []*beta.BackendService + f := func(l *beta.BackendServiceList) error { + glog.V(5).Infof("GCEBetaBackendServices.List(%v, ..., %v): page %+v", ctx, fl, l) all = append(all, l.Items...) return nil } if err := call.Pages(ctx, f); err != nil { - glog.V(4).Infof("GCEAlphaBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + glog.V(4).Infof("GCEBetaBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) return nil, err } if glog.V(4) { - glog.V(4).Infof("GCEAlphaBackendServices.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + glog.V(4).Infof("GCEBetaBackendServices.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) } else if glog.V(5) { var asStr []string for _, o := range all { asStr = append(asStr, fmt.Sprintf("%+v", o)) } - glog.V(5).Infof("GCEAlphaBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + glog.V(5).Infof("GCEBetaBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) } return all, nil } // Insert BackendService with key of value obj. -func (g *GCEAlphaBackendServices) Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error { - glog.V(5).Infof("GCEAlphaBackendServices.Insert(%v, %v, %+v): called", ctx, key, obj) +func (g *GCEBetaBackendServices) Insert(ctx context.Context, key *meta.Key, obj *beta.BackendService) error { + glog.V(5).Infof("GCEBetaBackendServices.Insert(%v, %v, %+v): called", ctx, key, obj) if !key.Valid() { - glog.V(2).Infof("GCEAlphaBackendServices.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaBackendServices.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Insert", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "BackendServices", } - glog.V(5).Infof("GCEAlphaBackendServices.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaBackendServices.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaBackendServices.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaBackendServices.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } obj.Name = key.Name - call := g.s.Alpha.BackendServices.Insert(projectID, obj) + call := g.s.Beta.BackendServices.Insert(projectID, obj) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaBackendServices.Insert(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEBetaBackendServices.Insert(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaBackendServices.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + glog.V(4).Infof("GCEBetaBackendServices.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) return err } // Delete the BackendService referenced by key. -func (g *GCEAlphaBackendServices) Delete(ctx context.Context, key *meta.Key) error { - glog.V(5).Infof("GCEAlphaBackendServices.Delete(%v, %v): called", ctx, key) +func (g *GCEBetaBackendServices) Delete(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCEBetaBackendServices.Delete(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaBackendServices.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaBackendServices.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Delete", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "BackendServices", } - glog.V(5).Infof("GCEAlphaBackendServices.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaBackendServices.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaBackendServices.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaBackendServices.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.Alpha.BackendServices.Delete(projectID, key.Name) + call := g.s.Beta.BackendServices.Delete(projectID, key.Name) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEBetaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEBetaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } -// Update is a method on GCEAlphaBackendServices. -func (g *GCEAlphaBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { - glog.V(5).Infof("GCEAlphaBackendServices.Update(%v, %v, ...): called", ctx, key) +// SetSecurityPolicy is a method on GCEBetaBackendServices. +func (g *GCEBetaBackendServices) SetSecurityPolicy(ctx context.Context, key *meta.Key, arg0 *beta.SecurityPolicyReference) error { + glog.V(5).Infof("GCEBetaBackendServices.SetSecurityPolicy(%v, %v, ...): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaBackendServices.Update(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaBackendServices.SetSecurityPolicy(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, - Operation: "Update", - Version: meta.Version("alpha"), + Operation: "SetSecurityPolicy", + Version: meta.Version("beta"), Service: "BackendServices", } - glog.V(5).Infof("GCEAlphaBackendServices.Update(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaBackendServices.SetSecurityPolicy(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaBackendServices.Update(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaBackendServices.SetSecurityPolicy(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.Alpha.BackendServices.Update(projectID, key.Name, arg0) + call := g.s.Beta.BackendServices.SetSecurityPolicy(projectID, key.Name, arg0) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEBetaBackendServices.SetSecurityPolicy(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEBetaBackendServices.SetSecurityPolicy(%v, %v, ...) = %+v", ctx, key, err) return err } -// RegionBackendServices is an interface that allows for mocking of RegionBackendServices. -type RegionBackendServices interface { - Get(ctx context.Context, key *meta.Key) (*ga.BackendService, error) - List(ctx context.Context, region string, fl *filter.F) ([]*ga.BackendService, error) - Insert(ctx context.Context, key *meta.Key, obj *ga.BackendService) error +// AlphaBackendServices is an interface that allows for mocking of BackendServices. +type AlphaBackendServices interface { + Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) + List(ctx context.Context, fl *filter.F) ([]*alpha.BackendService, error) + Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error Delete(ctx context.Context, key *meta.Key) error - GetHealth(context.Context, *meta.Key, *ga.ResourceGroupReference) (*ga.BackendServiceGroupHealth, error) - Update(context.Context, *meta.Key, *ga.BackendService) error + SetSecurityPolicy(context.Context, *meta.Key, *alpha.SecurityPolicyReference) error + Update(context.Context, *meta.Key, *alpha.BackendService) error } -// NewMockRegionBackendServices returns a new mock for RegionBackendServices. -func NewMockRegionBackendServices(pr ProjectRouter, objs map[meta.Key]*MockRegionBackendServicesObj) *MockRegionBackendServices { - mock := &MockRegionBackendServices{ +// NewMockAlphaBackendServices returns a new mock for BackendServices. +func NewMockAlphaBackendServices(pr ProjectRouter, objs map[meta.Key]*MockBackendServicesObj) *MockAlphaBackendServices { + mock := &MockAlphaBackendServices{ ProjectRouter: pr, Objects: objs, @@ -3330,14 +3409,14 @@ func NewMockRegionBackendServices(pr ProjectRouter, objs map[meta.Key]*MockRegio return mock } -// MockRegionBackendServices is the mock for RegionBackendServices. -type MockRegionBackendServices struct { +// MockAlphaBackendServices is the mock for BackendServices. +type MockAlphaBackendServices struct { Lock sync.Mutex ProjectRouter ProjectRouter // Objects maintained by the mock. - Objects map[meta.Key]*MockRegionBackendServicesObj + Objects map[meta.Key]*MockBackendServicesObj // If an entry exists for the given key and operation, then the error // will be returned instead of the operation. @@ -3350,12 +3429,12 @@ type MockRegionBackendServices struct { // order to add your own logic. Return (true, _, _) to prevent the normal // execution flow of the mock. Return (false, nil, nil) to continue with // normal mock behavior/ after the hook function executes. - GetHook func(ctx context.Context, key *meta.Key, m *MockRegionBackendServices) (bool, *ga.BackendService, error) - ListHook func(ctx context.Context, region string, fl *filter.F, m *MockRegionBackendServices) (bool, []*ga.BackendService, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *ga.BackendService, m *MockRegionBackendServices) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockRegionBackendServices) (bool, error) - GetHealthHook func(context.Context, *meta.Key, *ga.ResourceGroupReference, *MockRegionBackendServices) (*ga.BackendServiceGroupHealth, error) - UpdateHook func(context.Context, *meta.Key, *ga.BackendService, *MockRegionBackendServices) error + GetHook func(ctx context.Context, key *meta.Key, m *MockAlphaBackendServices) (bool, *alpha.BackendService, error) + ListHook func(ctx context.Context, fl *filter.F, m *MockAlphaBackendServices) (bool, []*alpha.BackendService, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.BackendService, m *MockAlphaBackendServices) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaBackendServices) (bool, error) + SetSecurityPolicyHook func(context.Context, *meta.Key, *alpha.SecurityPolicyReference, *MockAlphaBackendServices) error + UpdateHook func(context.Context, *meta.Key, *alpha.BackendService, *MockAlphaBackendServices) error // X is extra state that can be used as part of the mock. Generated code // will not use this field. @@ -3363,10 +3442,10 @@ type MockRegionBackendServices struct { } // Get returns the object from the mock. -func (m *MockRegionBackendServices) Get(ctx context.Context, key *meta.Key) (*ga.BackendService, error) { +func (m *MockAlphaBackendServices) Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) { if m.GetHook != nil { if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - glog.V(5).Infof("MockRegionBackendServices.Get(%v, %s) = %+v, %v", ctx, key, obj, err) + glog.V(5).Infof("MockAlphaBackendServices.Get(%v, %s) = %+v, %v", ctx, key, obj, err) return obj, err } } @@ -3378,28 +3457,28 @@ func (m *MockRegionBackendServices) Get(ctx context.Context, key *meta.Key) (*ga defer m.Lock.Unlock() if err, ok := m.GetError[*key]; ok { - glog.V(5).Infof("MockRegionBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockAlphaBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToGA() - glog.V(5).Infof("MockRegionBackendServices.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + typedObj := obj.ToAlpha() + glog.V(5).Infof("MockAlphaBackendServices.Get(%v, %s) = %+v, nil", ctx, key, typedObj) return typedObj, nil } err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockRegionBackendServices %v not found", key), + Message: fmt.Sprintf("MockAlphaBackendServices %v not found", key), } - glog.V(5).Infof("MockRegionBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockAlphaBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } -// List all of the objects in the mock in the given region. -func (m *MockRegionBackendServices) List(ctx context.Context, region string, fl *filter.F) ([]*ga.BackendService, error) { +// List all of the objects in the mock. +func (m *MockAlphaBackendServices) List(ctx context.Context, fl *filter.F) ([]*alpha.BackendService, error) { if m.ListHook != nil { - if intercept, objs, err := m.ListHook(ctx, region, fl, m); intercept { - glog.V(5).Infof("MockRegionBackendServices.List(%v, %q, %v) = [%v items], %v", ctx, region, fl, len(objs), err) + if intercept, objs, err := m.ListHook(ctx, fl, m); intercept { + glog.V(5).Infof("MockAlphaBackendServices.List(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) return objs, err } } @@ -3409,31 +3488,28 @@ func (m *MockRegionBackendServices) List(ctx context.Context, region string, fl if m.ListError != nil { err := *m.ListError - glog.V(5).Infof("MockRegionBackendServices.List(%v, %q, %v) = nil, %v", ctx, region, fl, err) + glog.V(5).Infof("MockAlphaBackendServices.List(%v, %v) = nil, %v", ctx, fl, err) return nil, *m.ListError } - var objs []*ga.BackendService - for key, obj := range m.Objects { - if key.Region != region { - continue - } - if !fl.Match(obj.ToGA()) { + var objs []*alpha.BackendService + for _, obj := range m.Objects { + if !fl.Match(obj.ToAlpha()) { continue } - objs = append(objs, obj.ToGA()) + objs = append(objs, obj.ToAlpha()) } - glog.V(5).Infof("MockRegionBackendServices.List(%v, %q, %v) = [%v items], nil", ctx, region, fl, len(objs)) + glog.V(5).Infof("MockAlphaBackendServices.List(%v, %v) = [%v items], nil", ctx, fl, len(objs)) return objs, nil } // Insert is a mock for inserting/creating a new object. -func (m *MockRegionBackendServices) Insert(ctx context.Context, key *meta.Key, obj *ga.BackendService) error { +func (m *MockAlphaBackendServices) Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error { if m.InsertHook != nil { if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - glog.V(5).Infof("MockRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockAlphaBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } } @@ -3445,32 +3521,32 @@ func (m *MockRegionBackendServices) Insert(ctx context.Context, key *meta.Key, o defer m.Lock.Unlock() if err, ok := m.InsertError[*key]; ok { - glog.V(5).Infof("MockRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockAlphaBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } if _, ok := m.Objects[*key]; ok { err := &googleapi.Error{ Code: http.StatusConflict, - Message: fmt.Sprintf("MockRegionBackendServices %v exists", key), + Message: fmt.Sprintf("MockAlphaBackendServices %v exists", key), } - glog.V(5).Infof("MockRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockAlphaBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "ga", "backendServices") - obj.SelfLink = SelfLink(meta.VersionGA, projectID, "backendServices", key) + projectID := m.ProjectRouter.ProjectID(ctx, "alpha", "backendServices") + obj.SelfLink = SelfLink(meta.VersionAlpha, projectID, "backendServices", key) - m.Objects[*key] = &MockRegionBackendServicesObj{obj} - glog.V(5).Infof("MockRegionBackendServices.Insert(%v, %v, %+v) = nil", ctx, key, obj) + m.Objects[*key] = &MockBackendServicesObj{obj} + glog.V(5).Infof("MockAlphaBackendServices.Insert(%v, %v, %+v) = nil", ctx, key, obj) return nil } // Delete is a mock for deleting the object. -func (m *MockRegionBackendServices) Delete(ctx context.Context, key *meta.Key) error { +func (m *MockAlphaBackendServices) Delete(ctx context.Context, key *meta.Key) error { if m.DeleteHook != nil { if intercept, err := m.DeleteHook(ctx, key, m); intercept { - glog.V(5).Infof("MockRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } } @@ -3482,259 +3558,265 @@ func (m *MockRegionBackendServices) Delete(ctx context.Context, key *meta.Key) e defer m.Lock.Unlock() if err, ok := m.DeleteError[*key]; ok { - glog.V(5).Infof("MockRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } if _, ok := m.Objects[*key]; !ok { err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockRegionBackendServices %v not found", key), + Message: fmt.Sprintf("MockAlphaBackendServices %v not found", key), } - glog.V(5).Infof("MockRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } delete(m.Objects, *key) - glog.V(5).Infof("MockRegionBackendServices.Delete(%v, %v) = nil", ctx, key) + glog.V(5).Infof("MockAlphaBackendServices.Delete(%v, %v) = nil", ctx, key) return nil } // Obj wraps the object for use in the mock. -func (m *MockRegionBackendServices) Obj(o *ga.BackendService) *MockRegionBackendServicesObj { - return &MockRegionBackendServicesObj{o} +func (m *MockAlphaBackendServices) Obj(o *alpha.BackendService) *MockBackendServicesObj { + return &MockBackendServicesObj{o} } -// GetHealth is a mock for the corresponding method. -func (m *MockRegionBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 *ga.ResourceGroupReference) (*ga.BackendServiceGroupHealth, error) { - if m.GetHealthHook != nil { - return m.GetHealthHook(ctx, key, arg0, m) +// SetSecurityPolicy is a mock for the corresponding method. +func (m *MockAlphaBackendServices) SetSecurityPolicy(ctx context.Context, key *meta.Key, arg0 *alpha.SecurityPolicyReference) error { + if m.SetSecurityPolicyHook != nil { + return m.SetSecurityPolicyHook(ctx, key, arg0, m) } - return nil, fmt.Errorf("GetHealthHook must be set") + return nil } // Update is a mock for the corresponding method. -func (m *MockRegionBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *ga.BackendService) error { +func (m *MockAlphaBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { if m.UpdateHook != nil { return m.UpdateHook(ctx, key, arg0, m) } return nil } -// GCERegionBackendServices is a simplifying adapter for the GCE RegionBackendServices. -type GCERegionBackendServices struct { +// GCEAlphaBackendServices is a simplifying adapter for the GCE BackendServices. +type GCEAlphaBackendServices struct { s *Service } // Get the BackendService named by key. -func (g *GCERegionBackendServices) Get(ctx context.Context, key *meta.Key) (*ga.BackendService, error) { - glog.V(5).Infof("GCERegionBackendServices.Get(%v, %v): called", ctx, key) +func (g *GCEAlphaBackendServices) Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) { + glog.V(5).Infof("GCEAlphaBackendServices.Get(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCERegionBackendServices.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEAlphaBackendServices.Get(%v, %v): key is invalid (%#v)", ctx, key, key) return nil, fmt.Errorf("invalid GCE key (%#v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Get", - Version: meta.Version("ga"), - Service: "RegionBackendServices", + Version: meta.Version("alpha"), + Service: "BackendServices", } - glog.V(5).Infof("GCERegionBackendServices.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEAlphaBackendServices.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCERegionBackendServices.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaBackendServices.Get(%v, %v): RateLimiter error: %v", ctx, key, err) return nil, err } - call := g.s.GA.RegionBackendServices.Get(projectID, key.Region, key.Name) + call := g.s.Alpha.BackendServices.Get(projectID, key.Name) call.Context(ctx) v, err := call.Do() - glog.V(4).Infof("GCERegionBackendServices.Get(%v, %v) = %+v, %v", ctx, key, v, err) + glog.V(4).Infof("GCEAlphaBackendServices.Get(%v, %v) = %+v, %v", ctx, key, v, err) return v, err } // List all BackendService objects. -func (g *GCERegionBackendServices) List(ctx context.Context, region string, fl *filter.F) ([]*ga.BackendService, error) { - glog.V(5).Infof("GCERegionBackendServices.List(%v, %v, %v) called", ctx, region, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") +func (g *GCEAlphaBackendServices) List(ctx context.Context, fl *filter.F) ([]*alpha.BackendService, error) { + glog.V(5).Infof("GCEAlphaBackendServices.List(%v, %v) called", ctx, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "List", - Version: meta.Version("ga"), - Service: "RegionBackendServices", + Version: meta.Version("alpha"), + Service: "BackendServices", } if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { return nil, err } - glog.V(5).Infof("GCERegionBackendServices.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, region, fl, projectID, rk) - call := g.s.GA.RegionBackendServices.List(projectID, region) + glog.V(5).Infof("GCEAlphaBackendServices.List(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) + call := g.s.Alpha.BackendServices.List(projectID) if fl != filter.None { call.Filter(fl.String()) } - var all []*ga.BackendService - f := func(l *ga.BackendServiceList) error { - glog.V(5).Infof("GCERegionBackendServices.List(%v, ..., %v): page %+v", ctx, fl, l) + var all []*alpha.BackendService + f := func(l *alpha.BackendServiceList) error { + glog.V(5).Infof("GCEAlphaBackendServices.List(%v, ..., %v): page %+v", ctx, fl, l) all = append(all, l.Items...) return nil } if err := call.Pages(ctx, f); err != nil { - glog.V(4).Infof("GCERegionBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + glog.V(4).Infof("GCEAlphaBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) return nil, err } if glog.V(4) { - glog.V(4).Infof("GCERegionBackendServices.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + glog.V(4).Infof("GCEAlphaBackendServices.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) } else if glog.V(5) { var asStr []string for _, o := range all { asStr = append(asStr, fmt.Sprintf("%+v", o)) } - glog.V(5).Infof("GCERegionBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + glog.V(5).Infof("GCEAlphaBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) } return all, nil } // Insert BackendService with key of value obj. -func (g *GCERegionBackendServices) Insert(ctx context.Context, key *meta.Key, obj *ga.BackendService) error { - glog.V(5).Infof("GCERegionBackendServices.Insert(%v, %v, %+v): called", ctx, key, obj) +func (g *GCEAlphaBackendServices) Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error { + glog.V(5).Infof("GCEAlphaBackendServices.Insert(%v, %v, %+v): called", ctx, key, obj) if !key.Valid() { - glog.V(2).Infof("GCERegionBackendServices.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEAlphaBackendServices.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Insert", - Version: meta.Version("ga"), - Service: "RegionBackendServices", + Version: meta.Version("alpha"), + Service: "BackendServices", } - glog.V(5).Infof("GCERegionBackendServices.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEAlphaBackendServices.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCERegionBackendServices.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaBackendServices.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } obj.Name = key.Name - call := g.s.GA.RegionBackendServices.Insert(projectID, key.Region, obj) + call := g.s.Alpha.BackendServices.Insert(projectID, obj) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCERegionBackendServices.Insert(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEAlphaBackendServices.Insert(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCERegionBackendServices.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + glog.V(4).Infof("GCEAlphaBackendServices.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) return err } // Delete the BackendService referenced by key. -func (g *GCERegionBackendServices) Delete(ctx context.Context, key *meta.Key) error { - glog.V(5).Infof("GCERegionBackendServices.Delete(%v, %v): called", ctx, key) +func (g *GCEAlphaBackendServices) Delete(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCEAlphaBackendServices.Delete(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCERegionBackendServices.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEAlphaBackendServices.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Delete", - Version: meta.Version("ga"), - Service: "RegionBackendServices", + Version: meta.Version("alpha"), + Service: "BackendServices", } - glog.V(5).Infof("GCERegionBackendServices.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEAlphaBackendServices.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCERegionBackendServices.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaBackendServices.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.GA.RegionBackendServices.Delete(projectID, key.Region, key.Name) + call := g.s.Alpha.BackendServices.Delete(projectID, key.Name) + call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCERegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCERegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } -// GetHealth is a method on GCERegionBackendServices. -func (g *GCERegionBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 *ga.ResourceGroupReference) (*ga.BackendServiceGroupHealth, error) { - glog.V(5).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...): called", ctx, key) +// SetSecurityPolicy is a method on GCEAlphaBackendServices. +func (g *GCEAlphaBackendServices) SetSecurityPolicy(ctx context.Context, key *meta.Key, arg0 *alpha.SecurityPolicyReference) error { + glog.V(5).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...): key is invalid (%#v)", ctx, key, key) - return nil, fmt.Errorf("invalid GCE key (%+v)", key) + glog.V(2).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, - Operation: "GetHealth", - Version: meta.Version("ga"), - Service: "RegionBackendServices", + Operation: "SetSecurityPolicy", + Version: meta.Version("alpha"), + Service: "BackendServices", } - glog.V(5).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...): RateLimiter error: %v", ctx, key, err) - return nil, err + glog.V(4).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err } - call := g.s.GA.RegionBackendServices.GetHealth(projectID, key.Region, key.Name, arg0) + call := g.s.Alpha.BackendServices.SetSecurityPolicy(projectID, key.Name, arg0) call.Context(ctx) - v, err := call.Do() - glog.V(4).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...) = %+v, %v", ctx, key, v, err) - return v, err + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEAlphaBackendServices.SetSecurityPolicy(%v, %v, ...) = %+v", ctx, key, err) + return err } -// Update is a method on GCERegionBackendServices. -func (g *GCERegionBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *ga.BackendService) error { - glog.V(5).Infof("GCERegionBackendServices.Update(%v, %v, ...): called", ctx, key) +// Update is a method on GCEAlphaBackendServices. +func (g *GCEAlphaBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { + glog.V(5).Infof("GCEAlphaBackendServices.Update(%v, %v, ...): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCERegionBackendServices.Update(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEAlphaBackendServices.Update(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "BackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Update", - Version: meta.Version("ga"), - Service: "RegionBackendServices", + Version: meta.Version("alpha"), + Service: "BackendServices", } - glog.V(5).Infof("GCERegionBackendServices.Update(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEAlphaBackendServices.Update(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCERegionBackendServices.Update(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaBackendServices.Update(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.GA.RegionBackendServices.Update(projectID, key.Region, key.Name, arg0) + call := g.s.Alpha.BackendServices.Update(projectID, key.Name, arg0) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCERegionBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEAlphaBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCERegionBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEAlphaBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) return err } -// AlphaRegionBackendServices is an interface that allows for mocking of RegionBackendServices. -type AlphaRegionBackendServices interface { - Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) - List(ctx context.Context, region string, fl *filter.F) ([]*alpha.BackendService, error) - Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error +// RegionBackendServices is an interface that allows for mocking of RegionBackendServices. +type RegionBackendServices interface { + Get(ctx context.Context, key *meta.Key) (*ga.BackendService, error) + List(ctx context.Context, region string, fl *filter.F) ([]*ga.BackendService, error) + Insert(ctx context.Context, key *meta.Key, obj *ga.BackendService) error Delete(ctx context.Context, key *meta.Key) error - GetHealth(context.Context, *meta.Key, *alpha.ResourceGroupReference) (*alpha.BackendServiceGroupHealth, error) - Update(context.Context, *meta.Key, *alpha.BackendService) error + GetHealth(context.Context, *meta.Key, *ga.ResourceGroupReference) (*ga.BackendServiceGroupHealth, error) + Update(context.Context, *meta.Key, *ga.BackendService) error } -// NewMockAlphaRegionBackendServices returns a new mock for RegionBackendServices. -func NewMockAlphaRegionBackendServices(pr ProjectRouter, objs map[meta.Key]*MockRegionBackendServicesObj) *MockAlphaRegionBackendServices { - mock := &MockAlphaRegionBackendServices{ +// NewMockRegionBackendServices returns a new mock for RegionBackendServices. +func NewMockRegionBackendServices(pr ProjectRouter, objs map[meta.Key]*MockRegionBackendServicesObj) *MockRegionBackendServices { + mock := &MockRegionBackendServices{ ProjectRouter: pr, Objects: objs, @@ -3745,8 +3827,8 @@ func NewMockAlphaRegionBackendServices(pr ProjectRouter, objs map[meta.Key]*Mock return mock } -// MockAlphaRegionBackendServices is the mock for RegionBackendServices. -type MockAlphaRegionBackendServices struct { +// MockRegionBackendServices is the mock for RegionBackendServices. +type MockRegionBackendServices struct { Lock sync.Mutex ProjectRouter ProjectRouter @@ -3765,12 +3847,12 @@ type MockAlphaRegionBackendServices struct { // order to add your own logic. Return (true, _, _) to prevent the normal // execution flow of the mock. Return (false, nil, nil) to continue with // normal mock behavior/ after the hook function executes. - GetHook func(ctx context.Context, key *meta.Key, m *MockAlphaRegionBackendServices) (bool, *alpha.BackendService, error) - ListHook func(ctx context.Context, region string, fl *filter.F, m *MockAlphaRegionBackendServices) (bool, []*alpha.BackendService, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.BackendService, m *MockAlphaRegionBackendServices) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaRegionBackendServices) (bool, error) - GetHealthHook func(context.Context, *meta.Key, *alpha.ResourceGroupReference, *MockAlphaRegionBackendServices) (*alpha.BackendServiceGroupHealth, error) - UpdateHook func(context.Context, *meta.Key, *alpha.BackendService, *MockAlphaRegionBackendServices) error + GetHook func(ctx context.Context, key *meta.Key, m *MockRegionBackendServices) (bool, *ga.BackendService, error) + ListHook func(ctx context.Context, region string, fl *filter.F, m *MockRegionBackendServices) (bool, []*ga.BackendService, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *ga.BackendService, m *MockRegionBackendServices) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockRegionBackendServices) (bool, error) + GetHealthHook func(context.Context, *meta.Key, *ga.ResourceGroupReference, *MockRegionBackendServices) (*ga.BackendServiceGroupHealth, error) + UpdateHook func(context.Context, *meta.Key, *ga.BackendService, *MockRegionBackendServices) error // X is extra state that can be used as part of the mock. Generated code // will not use this field. @@ -3778,10 +3860,10 @@ type MockAlphaRegionBackendServices struct { } // Get returns the object from the mock. -func (m *MockAlphaRegionBackendServices) Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) { +func (m *MockRegionBackendServices) Get(ctx context.Context, key *meta.Key) (*ga.BackendService, error) { if m.GetHook != nil { if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaRegionBackendServices.Get(%v, %s) = %+v, %v", ctx, key, obj, err) + glog.V(5).Infof("MockRegionBackendServices.Get(%v, %s) = %+v, %v", ctx, key, obj, err) return obj, err } } @@ -3793,28 +3875,28 @@ func (m *MockAlphaRegionBackendServices) Get(ctx context.Context, key *meta.Key) defer m.Lock.Unlock() if err, ok := m.GetError[*key]; ok { - glog.V(5).Infof("MockAlphaRegionBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockRegionBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToAlpha() - glog.V(5).Infof("MockAlphaRegionBackendServices.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + typedObj := obj.ToGA() + glog.V(5).Infof("MockRegionBackendServices.Get(%v, %s) = %+v, nil", ctx, key, typedObj) return typedObj, nil } err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaRegionBackendServices %v not found", key), + Message: fmt.Sprintf("MockRegionBackendServices %v not found", key), } - glog.V(5).Infof("MockAlphaRegionBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockRegionBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } // List all of the objects in the mock in the given region. -func (m *MockAlphaRegionBackendServices) List(ctx context.Context, region string, fl *filter.F) ([]*alpha.BackendService, error) { +func (m *MockRegionBackendServices) List(ctx context.Context, region string, fl *filter.F) ([]*ga.BackendService, error) { if m.ListHook != nil { if intercept, objs, err := m.ListHook(ctx, region, fl, m); intercept { - glog.V(5).Infof("MockAlphaRegionBackendServices.List(%v, %q, %v) = [%v items], %v", ctx, region, fl, len(objs), err) + glog.V(5).Infof("MockRegionBackendServices.List(%v, %q, %v) = [%v items], %v", ctx, region, fl, len(objs), err) return objs, err } } @@ -3824,31 +3906,31 @@ func (m *MockAlphaRegionBackendServices) List(ctx context.Context, region string if m.ListError != nil { err := *m.ListError - glog.V(5).Infof("MockAlphaRegionBackendServices.List(%v, %q, %v) = nil, %v", ctx, region, fl, err) + glog.V(5).Infof("MockRegionBackendServices.List(%v, %q, %v) = nil, %v", ctx, region, fl, err) return nil, *m.ListError } - var objs []*alpha.BackendService + var objs []*ga.BackendService for key, obj := range m.Objects { if key.Region != region { continue } - if !fl.Match(obj.ToAlpha()) { + if !fl.Match(obj.ToGA()) { continue } - objs = append(objs, obj.ToAlpha()) + objs = append(objs, obj.ToGA()) } - glog.V(5).Infof("MockAlphaRegionBackendServices.List(%v, %q, %v) = [%v items], nil", ctx, region, fl, len(objs)) + glog.V(5).Infof("MockRegionBackendServices.List(%v, %q, %v) = [%v items], nil", ctx, region, fl, len(objs)) return objs, nil } // Insert is a mock for inserting/creating a new object. -func (m *MockAlphaRegionBackendServices) Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error { +func (m *MockRegionBackendServices) Insert(ctx context.Context, key *meta.Key, obj *ga.BackendService) error { if m.InsertHook != nil { if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - glog.V(5).Infof("MockAlphaRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } } @@ -3860,32 +3942,32 @@ func (m *MockAlphaRegionBackendServices) Insert(ctx context.Context, key *meta.K defer m.Lock.Unlock() if err, ok := m.InsertError[*key]; ok { - glog.V(5).Infof("MockAlphaRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } if _, ok := m.Objects[*key]; ok { err := &googleapi.Error{ Code: http.StatusConflict, - Message: fmt.Sprintf("MockAlphaRegionBackendServices %v exists", key), + Message: fmt.Sprintf("MockRegionBackendServices %v exists", key), } - glog.V(5).Infof("MockAlphaRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "alpha", "backendServices") - obj.SelfLink = SelfLink(meta.VersionAlpha, projectID, "backendServices", key) + projectID := m.ProjectRouter.ProjectID(ctx, "ga", "backendServices") + obj.SelfLink = SelfLink(meta.VersionGA, projectID, "backendServices", key) m.Objects[*key] = &MockRegionBackendServicesObj{obj} - glog.V(5).Infof("MockAlphaRegionBackendServices.Insert(%v, %v, %+v) = nil", ctx, key, obj) + glog.V(5).Infof("MockRegionBackendServices.Insert(%v, %v, %+v) = nil", ctx, key, obj) return nil } // Delete is a mock for deleting the object. -func (m *MockAlphaRegionBackendServices) Delete(ctx context.Context, key *meta.Key) error { +func (m *MockRegionBackendServices) Delete(ctx context.Context, key *meta.Key) error { if m.DeleteHook != nil { if intercept, err := m.DeleteHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } } @@ -3897,30 +3979,30 @@ func (m *MockAlphaRegionBackendServices) Delete(ctx context.Context, key *meta.K defer m.Lock.Unlock() if err, ok := m.DeleteError[*key]; ok { - glog.V(5).Infof("MockAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } if _, ok := m.Objects[*key]; !ok { err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaRegionBackendServices %v not found", key), + Message: fmt.Sprintf("MockRegionBackendServices %v not found", key), } - glog.V(5).Infof("MockAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } delete(m.Objects, *key) - glog.V(5).Infof("MockAlphaRegionBackendServices.Delete(%v, %v) = nil", ctx, key) + glog.V(5).Infof("MockRegionBackendServices.Delete(%v, %v) = nil", ctx, key) return nil } // Obj wraps the object for use in the mock. -func (m *MockAlphaRegionBackendServices) Obj(o *alpha.BackendService) *MockRegionBackendServicesObj { +func (m *MockRegionBackendServices) Obj(o *ga.BackendService) *MockRegionBackendServicesObj { return &MockRegionBackendServicesObj{o} } // GetHealth is a mock for the corresponding method. -func (m *MockAlphaRegionBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 *alpha.ResourceGroupReference) (*alpha.BackendServiceGroupHealth, error) { +func (m *MockRegionBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 *ga.ResourceGroupReference) (*ga.BackendServiceGroupHealth, error) { if m.GetHealthHook != nil { return m.GetHealthHook(ctx, key, arg0, m) } @@ -3928,226 +4010,228 @@ func (m *MockAlphaRegionBackendServices) GetHealth(ctx context.Context, key *met } // Update is a mock for the corresponding method. -func (m *MockAlphaRegionBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { +func (m *MockRegionBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *ga.BackendService) error { if m.UpdateHook != nil { return m.UpdateHook(ctx, key, arg0, m) } return nil } -// GCEAlphaRegionBackendServices is a simplifying adapter for the GCE RegionBackendServices. -type GCEAlphaRegionBackendServices struct { +// GCERegionBackendServices is a simplifying adapter for the GCE RegionBackendServices. +type GCERegionBackendServices struct { s *Service } // Get the BackendService named by key. -func (g *GCEAlphaRegionBackendServices) Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) { - glog.V(5).Infof("GCEAlphaRegionBackendServices.Get(%v, %v): called", ctx, key) +func (g *GCERegionBackendServices) Get(ctx context.Context, key *meta.Key) (*ga.BackendService, error) { + glog.V(5).Infof("GCERegionBackendServices.Get(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionBackendServices.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCERegionBackendServices.Get(%v, %v): key is invalid (%#v)", ctx, key, key) return nil, fmt.Errorf("invalid GCE key (%#v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Get", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "RegionBackendServices", } - glog.V(5).Infof("GCEAlphaRegionBackendServices.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCERegionBackendServices.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionBackendServices.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.Get(%v, %v): RateLimiter error: %v", ctx, key, err) return nil, err } - call := g.s.Alpha.RegionBackendServices.Get(projectID, key.Region, key.Name) + call := g.s.GA.RegionBackendServices.Get(projectID, key.Region, key.Name) call.Context(ctx) v, err := call.Do() - glog.V(4).Infof("GCEAlphaRegionBackendServices.Get(%v, %v) = %+v, %v", ctx, key, v, err) + glog.V(4).Infof("GCERegionBackendServices.Get(%v, %v) = %+v, %v", ctx, key, v, err) return v, err } // List all BackendService objects. -func (g *GCEAlphaRegionBackendServices) List(ctx context.Context, region string, fl *filter.F) ([]*alpha.BackendService, error) { - glog.V(5).Infof("GCEAlphaRegionBackendServices.List(%v, %v, %v) called", ctx, region, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") +func (g *GCERegionBackendServices) List(ctx context.Context, region string, fl *filter.F) ([]*ga.BackendService, error) { + glog.V(5).Infof("GCERegionBackendServices.List(%v, %v, %v) called", ctx, region, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "List", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "RegionBackendServices", } if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { return nil, err } - glog.V(5).Infof("GCEAlphaRegionBackendServices.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, region, fl, projectID, rk) - call := g.s.Alpha.RegionBackendServices.List(projectID, region) + glog.V(5).Infof("GCERegionBackendServices.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, region, fl, projectID, rk) + call := g.s.GA.RegionBackendServices.List(projectID, region) if fl != filter.None { call.Filter(fl.String()) } - var all []*alpha.BackendService - f := func(l *alpha.BackendServiceList) error { - glog.V(5).Infof("GCEAlphaRegionBackendServices.List(%v, ..., %v): page %+v", ctx, fl, l) + var all []*ga.BackendService + f := func(l *ga.BackendServiceList) error { + glog.V(5).Infof("GCERegionBackendServices.List(%v, ..., %v): page %+v", ctx, fl, l) all = append(all, l.Items...) return nil } if err := call.Pages(ctx, f); err != nil { - glog.V(4).Infof("GCEAlphaRegionBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + glog.V(4).Infof("GCERegionBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) return nil, err } if glog.V(4) { - glog.V(4).Infof("GCEAlphaRegionBackendServices.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + glog.V(4).Infof("GCERegionBackendServices.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) } else if glog.V(5) { var asStr []string for _, o := range all { asStr = append(asStr, fmt.Sprintf("%+v", o)) } - glog.V(5).Infof("GCEAlphaRegionBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + glog.V(5).Infof("GCERegionBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) } return all, nil } // Insert BackendService with key of value obj. -func (g *GCEAlphaRegionBackendServices) Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error { - glog.V(5).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, %+v): called", ctx, key, obj) +func (g *GCERegionBackendServices) Insert(ctx context.Context, key *meta.Key, obj *ga.BackendService) error { + glog.V(5).Infof("GCERegionBackendServices.Insert(%v, %v, %+v): called", ctx, key, obj) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCERegionBackendServices.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Insert", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "RegionBackendServices", } - glog.V(5).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCERegionBackendServices.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } obj.Name = key.Name - call := g.s.Alpha.RegionBackendServices.Insert(projectID, key.Region, obj) + call := g.s.GA.RegionBackendServices.Insert(projectID, key.Region, obj) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.Insert(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + glog.V(4).Infof("GCERegionBackendServices.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) return err } // Delete the BackendService referenced by key. -func (g *GCEAlphaRegionBackendServices) Delete(ctx context.Context, key *meta.Key) error { - glog.V(5).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v): called", ctx, key) +func (g *GCERegionBackendServices) Delete(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCERegionBackendServices.Delete(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCERegionBackendServices.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Delete", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "RegionBackendServices", } - glog.V(5).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCERegionBackendServices.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.Alpha.RegionBackendServices.Delete(projectID, key.Region, key.Name) + call := g.s.GA.RegionBackendServices.Delete(projectID, key.Region, key.Name) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } -// GetHealth is a method on GCEAlphaRegionBackendServices. -func (g *GCEAlphaRegionBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 *alpha.ResourceGroupReference) (*alpha.BackendServiceGroupHealth, error) { - glog.V(5).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...): called", ctx, key) +// GetHealth is a method on GCERegionBackendServices. +func (g *GCERegionBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 *ga.ResourceGroupReference) (*ga.BackendServiceGroupHealth, error) { + glog.V(5).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return nil, fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "GetHealth", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "RegionBackendServices", } - glog.V(5).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return nil, err } - call := g.s.Alpha.RegionBackendServices.GetHealth(projectID, key.Region, key.Name, arg0) + call := g.s.GA.RegionBackendServices.GetHealth(projectID, key.Region, key.Name, arg0) call.Context(ctx) v, err := call.Do() - glog.V(4).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...) = %+v, %v", ctx, key, v, err) + glog.V(4).Infof("GCERegionBackendServices.GetHealth(%v, %v, ...) = %+v, %v", ctx, key, v, err) return v, err } -// Update is a method on GCEAlphaRegionBackendServices. -func (g *GCEAlphaRegionBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { - glog.V(5).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...): called", ctx, key) +// Update is a method on GCERegionBackendServices. +func (g *GCERegionBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *ga.BackendService) error { + glog.V(5).Infof("GCERegionBackendServices.Update(%v, %v, ...): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCERegionBackendServices.Update(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Update", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "RegionBackendServices", } - glog.V(5).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCERegionBackendServices.Update(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.Update(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.Alpha.RegionBackendServices.Update(projectID, key.Region, key.Name, arg0) + call := g.s.GA.RegionBackendServices.Update(projectID, key.Region, key.Name, arg0) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCERegionBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) return err } -// Disks is an interface that allows for mocking of Disks. -type Disks interface { - Get(ctx context.Context, key *meta.Key) (*ga.Disk, error) - List(ctx context.Context, zone string, fl *filter.F) ([]*ga.Disk, error) - Insert(ctx context.Context, key *meta.Key, obj *ga.Disk) error +// AlphaRegionBackendServices is an interface that allows for mocking of RegionBackendServices. +type AlphaRegionBackendServices interface { + Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) + List(ctx context.Context, region string, fl *filter.F) ([]*alpha.BackendService, error) + Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error Delete(ctx context.Context, key *meta.Key) error + GetHealth(context.Context, *meta.Key, *alpha.ResourceGroupReference) (*alpha.BackendServiceGroupHealth, error) + Update(context.Context, *meta.Key, *alpha.BackendService) error } -// NewMockDisks returns a new mock for Disks. -func NewMockDisks(pr ProjectRouter, objs map[meta.Key]*MockDisksObj) *MockDisks { - mock := &MockDisks{ +// NewMockAlphaRegionBackendServices returns a new mock for RegionBackendServices. +func NewMockAlphaRegionBackendServices(pr ProjectRouter, objs map[meta.Key]*MockRegionBackendServicesObj) *MockAlphaRegionBackendServices { + mock := &MockAlphaRegionBackendServices{ ProjectRouter: pr, Objects: objs, @@ -4158,14 +4242,14 @@ func NewMockDisks(pr ProjectRouter, objs map[meta.Key]*MockDisksObj) *MockDisks return mock } -// MockDisks is the mock for Disks. -type MockDisks struct { +// MockAlphaRegionBackendServices is the mock for RegionBackendServices. +type MockAlphaRegionBackendServices struct { Lock sync.Mutex ProjectRouter ProjectRouter // Objects maintained by the mock. - Objects map[meta.Key]*MockDisksObj + Objects map[meta.Key]*MockRegionBackendServicesObj // If an entry exists for the given key and operation, then the error // will be returned instead of the operation. @@ -4178,10 +4262,12 @@ type MockDisks struct { // order to add your own logic. Return (true, _, _) to prevent the normal // execution flow of the mock. Return (false, nil, nil) to continue with // normal mock behavior/ after the hook function executes. - GetHook func(ctx context.Context, key *meta.Key, m *MockDisks) (bool, *ga.Disk, error) - ListHook func(ctx context.Context, zone string, fl *filter.F, m *MockDisks) (bool, []*ga.Disk, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *ga.Disk, m *MockDisks) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockDisks) (bool, error) + GetHook func(ctx context.Context, key *meta.Key, m *MockAlphaRegionBackendServices) (bool, *alpha.BackendService, error) + ListHook func(ctx context.Context, region string, fl *filter.F, m *MockAlphaRegionBackendServices) (bool, []*alpha.BackendService, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.BackendService, m *MockAlphaRegionBackendServices) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaRegionBackendServices) (bool, error) + GetHealthHook func(context.Context, *meta.Key, *alpha.ResourceGroupReference, *MockAlphaRegionBackendServices) (*alpha.BackendServiceGroupHealth, error) + UpdateHook func(context.Context, *meta.Key, *alpha.BackendService, *MockAlphaRegionBackendServices) error // X is extra state that can be used as part of the mock. Generated code // will not use this field. @@ -4189,10 +4275,10 @@ type MockDisks struct { } // Get returns the object from the mock. -func (m *MockDisks) Get(ctx context.Context, key *meta.Key) (*ga.Disk, error) { +func (m *MockAlphaRegionBackendServices) Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) { if m.GetHook != nil { if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - glog.V(5).Infof("MockDisks.Get(%v, %s) = %+v, %v", ctx, key, obj, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.Get(%v, %s) = %+v, %v", ctx, key, obj, err) return obj, err } } @@ -4204,28 +4290,28 @@ func (m *MockDisks) Get(ctx context.Context, key *meta.Key) (*ga.Disk, error) { defer m.Lock.Unlock() if err, ok := m.GetError[*key]; ok { - glog.V(5).Infof("MockDisks.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToGA() - glog.V(5).Infof("MockDisks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + typedObj := obj.ToAlpha() + glog.V(5).Infof("MockAlphaRegionBackendServices.Get(%v, %s) = %+v, nil", ctx, key, typedObj) return typedObj, nil } err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockDisks %v not found", key), + Message: fmt.Sprintf("MockAlphaRegionBackendServices %v not found", key), } - glog.V(5).Infof("MockDisks.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } -// List all of the objects in the mock in the given zone. -func (m *MockDisks) List(ctx context.Context, zone string, fl *filter.F) ([]*ga.Disk, error) { +// List all of the objects in the mock in the given region. +func (m *MockAlphaRegionBackendServices) List(ctx context.Context, region string, fl *filter.F) ([]*alpha.BackendService, error) { if m.ListHook != nil { - if intercept, objs, err := m.ListHook(ctx, zone, fl, m); intercept { - glog.V(5).Infof("MockDisks.List(%v, %q, %v) = [%v items], %v", ctx, zone, fl, len(objs), err) + if intercept, objs, err := m.ListHook(ctx, region, fl, m); intercept { + glog.V(5).Infof("MockAlphaRegionBackendServices.List(%v, %q, %v) = [%v items], %v", ctx, region, fl, len(objs), err) return objs, err } } @@ -4235,31 +4321,31 @@ func (m *MockDisks) List(ctx context.Context, zone string, fl *filter.F) ([]*ga. if m.ListError != nil { err := *m.ListError - glog.V(5).Infof("MockDisks.List(%v, %q, %v) = nil, %v", ctx, zone, fl, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.List(%v, %q, %v) = nil, %v", ctx, region, fl, err) return nil, *m.ListError } - var objs []*ga.Disk + var objs []*alpha.BackendService for key, obj := range m.Objects { - if key.Zone != zone { + if key.Region != region { continue } - if !fl.Match(obj.ToGA()) { + if !fl.Match(obj.ToAlpha()) { continue } - objs = append(objs, obj.ToGA()) + objs = append(objs, obj.ToAlpha()) } - glog.V(5).Infof("MockDisks.List(%v, %q, %v) = [%v items], nil", ctx, zone, fl, len(objs)) + glog.V(5).Infof("MockAlphaRegionBackendServices.List(%v, %q, %v) = [%v items], nil", ctx, region, fl, len(objs)) return objs, nil } // Insert is a mock for inserting/creating a new object. -func (m *MockDisks) Insert(ctx context.Context, key *meta.Key, obj *ga.Disk) error { +func (m *MockAlphaRegionBackendServices) Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error { if m.InsertHook != nil { if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - glog.V(5).Infof("MockDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } } @@ -4271,32 +4357,32 @@ func (m *MockDisks) Insert(ctx context.Context, key *meta.Key, obj *ga.Disk) err defer m.Lock.Unlock() if err, ok := m.InsertError[*key]; ok { - glog.V(5).Infof("MockDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } if _, ok := m.Objects[*key]; ok { err := &googleapi.Error{ Code: http.StatusConflict, - Message: fmt.Sprintf("MockDisks %v exists", key), + Message: fmt.Sprintf("MockAlphaRegionBackendServices %v exists", key), } - glog.V(5).Infof("MockDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "ga", "disks") - obj.SelfLink = SelfLink(meta.VersionGA, projectID, "disks", key) + projectID := m.ProjectRouter.ProjectID(ctx, "alpha", "backendServices") + obj.SelfLink = SelfLink(meta.VersionAlpha, projectID, "backendServices", key) - m.Objects[*key] = &MockDisksObj{obj} - glog.V(5).Infof("MockDisks.Insert(%v, %v, %+v) = nil", ctx, key, obj) + m.Objects[*key] = &MockRegionBackendServicesObj{obj} + glog.V(5).Infof("MockAlphaRegionBackendServices.Insert(%v, %v, %+v) = nil", ctx, key, obj) return nil } // Delete is a mock for deleting the object. -func (m *MockDisks) Delete(ctx context.Context, key *meta.Key) error { +func (m *MockAlphaRegionBackendServices) Delete(ctx context.Context, key *meta.Key) error { if m.DeleteHook != nil { if intercept, err := m.DeleteHook(ctx, key, m); intercept { - glog.V(5).Infof("MockDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } } @@ -4308,180 +4394,258 @@ func (m *MockDisks) Delete(ctx context.Context, key *meta.Key) error { defer m.Lock.Unlock() if err, ok := m.DeleteError[*key]; ok { - glog.V(5).Infof("MockDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } if _, ok := m.Objects[*key]; !ok { err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockDisks %v not found", key), + Message: fmt.Sprintf("MockAlphaRegionBackendServices %v not found", key), } - glog.V(5).Infof("MockDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } delete(m.Objects, *key) - glog.V(5).Infof("MockDisks.Delete(%v, %v) = nil", ctx, key) + glog.V(5).Infof("MockAlphaRegionBackendServices.Delete(%v, %v) = nil", ctx, key) return nil } // Obj wraps the object for use in the mock. -func (m *MockDisks) Obj(o *ga.Disk) *MockDisksObj { - return &MockDisksObj{o} +func (m *MockAlphaRegionBackendServices) Obj(o *alpha.BackendService) *MockRegionBackendServicesObj { + return &MockRegionBackendServicesObj{o} } -// GCEDisks is a simplifying adapter for the GCE Disks. -type GCEDisks struct { - s *Service -} +// GetHealth is a mock for the corresponding method. +func (m *MockAlphaRegionBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 *alpha.ResourceGroupReference) (*alpha.BackendServiceGroupHealth, error) { + if m.GetHealthHook != nil { + return m.GetHealthHook(ctx, key, arg0, m) + } + return nil, fmt.Errorf("GetHealthHook must be set") +} -// Get the Disk named by key. -func (g *GCEDisks) Get(ctx context.Context, key *meta.Key) (*ga.Disk, error) { - glog.V(5).Infof("GCEDisks.Get(%v, %v): called", ctx, key) +// Update is a mock for the corresponding method. +func (m *MockAlphaRegionBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { + if m.UpdateHook != nil { + return m.UpdateHook(ctx, key, arg0, m) + } + return nil +} + +// GCEAlphaRegionBackendServices is a simplifying adapter for the GCE RegionBackendServices. +type GCEAlphaRegionBackendServices struct { + s *Service +} + +// Get the BackendService named by key. +func (g *GCEAlphaRegionBackendServices) Get(ctx context.Context, key *meta.Key) (*alpha.BackendService, error) { + glog.V(5).Infof("GCEAlphaRegionBackendServices.Get(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEDisks.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEAlphaRegionBackendServices.Get(%v, %v): key is invalid (%#v)", ctx, key, key) return nil, fmt.Errorf("invalid GCE key (%#v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Get", - Version: meta.Version("ga"), - Service: "Disks", + Version: meta.Version("alpha"), + Service: "RegionBackendServices", } - glog.V(5).Infof("GCEDisks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEAlphaRegionBackendServices.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEDisks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaRegionBackendServices.Get(%v, %v): RateLimiter error: %v", ctx, key, err) return nil, err } - call := g.s.GA.Disks.Get(projectID, key.Zone, key.Name) + call := g.s.Alpha.RegionBackendServices.Get(projectID, key.Region, key.Name) call.Context(ctx) v, err := call.Do() - glog.V(4).Infof("GCEDisks.Get(%v, %v) = %+v, %v", ctx, key, v, err) + glog.V(4).Infof("GCEAlphaRegionBackendServices.Get(%v, %v) = %+v, %v", ctx, key, v, err) return v, err } -// List all Disk objects. -func (g *GCEDisks) List(ctx context.Context, zone string, fl *filter.F) ([]*ga.Disk, error) { - glog.V(5).Infof("GCEDisks.List(%v, %v, %v) called", ctx, zone, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") +// List all BackendService objects. +func (g *GCEAlphaRegionBackendServices) List(ctx context.Context, region string, fl *filter.F) ([]*alpha.BackendService, error) { + glog.V(5).Infof("GCEAlphaRegionBackendServices.List(%v, %v, %v) called", ctx, region, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "List", - Version: meta.Version("ga"), - Service: "Disks", + Version: meta.Version("alpha"), + Service: "RegionBackendServices", } if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { return nil, err } - glog.V(5).Infof("GCEDisks.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, zone, fl, projectID, rk) - call := g.s.GA.Disks.List(projectID, zone) + glog.V(5).Infof("GCEAlphaRegionBackendServices.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, region, fl, projectID, rk) + call := g.s.Alpha.RegionBackendServices.List(projectID, region) if fl != filter.None { call.Filter(fl.String()) } - var all []*ga.Disk - f := func(l *ga.DiskList) error { - glog.V(5).Infof("GCEDisks.List(%v, ..., %v): page %+v", ctx, fl, l) + var all []*alpha.BackendService + f := func(l *alpha.BackendServiceList) error { + glog.V(5).Infof("GCEAlphaRegionBackendServices.List(%v, ..., %v): page %+v", ctx, fl, l) all = append(all, l.Items...) return nil } if err := call.Pages(ctx, f); err != nil { - glog.V(4).Infof("GCEDisks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + glog.V(4).Infof("GCEAlphaRegionBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) return nil, err } if glog.V(4) { - glog.V(4).Infof("GCEDisks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + glog.V(4).Infof("GCEAlphaRegionBackendServices.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) } else if glog.V(5) { var asStr []string for _, o := range all { asStr = append(asStr, fmt.Sprintf("%+v", o)) } - glog.V(5).Infof("GCEDisks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + glog.V(5).Infof("GCEAlphaRegionBackendServices.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) } return all, nil } -// Insert Disk with key of value obj. -func (g *GCEDisks) Insert(ctx context.Context, key *meta.Key, obj *ga.Disk) error { - glog.V(5).Infof("GCEDisks.Insert(%v, %v, %+v): called", ctx, key, obj) +// Insert BackendService with key of value obj. +func (g *GCEAlphaRegionBackendServices) Insert(ctx context.Context, key *meta.Key, obj *alpha.BackendService) error { + glog.V(5).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, %+v): called", ctx, key, obj) if !key.Valid() { - glog.V(2).Infof("GCEDisks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Insert", - Version: meta.Version("ga"), - Service: "Disks", + Version: meta.Version("alpha"), + Service: "RegionBackendServices", } - glog.V(5).Infof("GCEDisks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEDisks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } obj.Name = key.Name - call := g.s.GA.Disks.Insert(projectID, key.Zone, obj) + call := g.s.Alpha.RegionBackendServices.Insert(projectID, key.Region, obj) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEDisks.Insert(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEDisks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + glog.V(4).Infof("GCEAlphaRegionBackendServices.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) return err } -// Delete the Disk referenced by key. -func (g *GCEDisks) Delete(ctx context.Context, key *meta.Key) error { - glog.V(5).Infof("GCEDisks.Delete(%v, %v): called", ctx, key) +// Delete the BackendService referenced by key. +func (g *GCEAlphaRegionBackendServices) Delete(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEDisks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Delete", - Version: meta.Version("ga"), - Service: "Disks", + Version: meta.Version("alpha"), + Service: "RegionBackendServices", } - glog.V(5).Infof("GCEDisks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEDisks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.GA.Disks.Delete(projectID, key.Zone, key.Name) + call := g.s.Alpha.RegionBackendServices.Delete(projectID, key.Region, key.Name) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEAlphaRegionBackendServices.Delete(%v, %v) = %v", ctx, key, err) + return err +} + +// GetHealth is a method on GCEAlphaRegionBackendServices. +func (g *GCEAlphaRegionBackendServices) GetHealth(ctx context.Context, key *meta.Key, arg0 *alpha.ResourceGroupReference) (*alpha.BackendServiceGroupHealth, error) { + glog.V(5).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return nil, fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "GetHealth", + Version: meta.Version("alpha"), + Service: "RegionBackendServices", + } + glog.V(5).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return nil, err + } + call := g.s.Alpha.RegionBackendServices.GetHealth(projectID, key.Region, key.Name, arg0) + call.Context(ctx) + v, err := call.Do() + glog.V(4).Infof("GCEAlphaRegionBackendServices.GetHealth(%v, %v, ...) = %+v, %v", ctx, key, v, err) + return v, err +} + +// Update is a method on GCEAlphaRegionBackendServices. +func (g *GCEAlphaRegionBackendServices) Update(ctx context.Context, key *meta.Key, arg0 *alpha.BackendService) error { + glog.V(5).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionBackendServices") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Update", + Version: meta.Version("alpha"), + Service: "RegionBackendServices", + } + glog.V(5).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Alpha.RegionBackendServices.Update(projectID, key.Region, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEAlphaRegionBackendServices.Update(%v, %v, ...) = %+v", ctx, key, err) return err } -// AlphaDisks is an interface that allows for mocking of Disks. -type AlphaDisks interface { - Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) - List(ctx context.Context, zone string, fl *filter.F) ([]*alpha.Disk, error) - Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error +// Disks is an interface that allows for mocking of Disks. +type Disks interface { + Get(ctx context.Context, key *meta.Key) (*ga.Disk, error) + List(ctx context.Context, zone string, fl *filter.F) ([]*ga.Disk, error) + Insert(ctx context.Context, key *meta.Key, obj *ga.Disk) error Delete(ctx context.Context, key *meta.Key) error + Resize(context.Context, *meta.Key, *ga.DisksResizeRequest) error } -// NewMockAlphaDisks returns a new mock for Disks. -func NewMockAlphaDisks(pr ProjectRouter, objs map[meta.Key]*MockDisksObj) *MockAlphaDisks { - mock := &MockAlphaDisks{ +// NewMockDisks returns a new mock for Disks. +func NewMockDisks(pr ProjectRouter, objs map[meta.Key]*MockDisksObj) *MockDisks { + mock := &MockDisks{ ProjectRouter: pr, Objects: objs, @@ -4492,8 +4656,8 @@ func NewMockAlphaDisks(pr ProjectRouter, objs map[meta.Key]*MockDisksObj) *MockA return mock } -// MockAlphaDisks is the mock for Disks. -type MockAlphaDisks struct { +// MockDisks is the mock for Disks. +type MockDisks struct { Lock sync.Mutex ProjectRouter ProjectRouter @@ -4512,10 +4676,11 @@ type MockAlphaDisks struct { // order to add your own logic. Return (true, _, _) to prevent the normal // execution flow of the mock. Return (false, nil, nil) to continue with // normal mock behavior/ after the hook function executes. - GetHook func(ctx context.Context, key *meta.Key, m *MockAlphaDisks) (bool, *alpha.Disk, error) - ListHook func(ctx context.Context, zone string, fl *filter.F, m *MockAlphaDisks) (bool, []*alpha.Disk, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.Disk, m *MockAlphaDisks) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaDisks) (bool, error) + GetHook func(ctx context.Context, key *meta.Key, m *MockDisks) (bool, *ga.Disk, error) + ListHook func(ctx context.Context, zone string, fl *filter.F, m *MockDisks) (bool, []*ga.Disk, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *ga.Disk, m *MockDisks) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockDisks) (bool, error) + ResizeHook func(context.Context, *meta.Key, *ga.DisksResizeRequest, *MockDisks) error // X is extra state that can be used as part of the mock. Generated code // will not use this field. @@ -4523,10 +4688,10 @@ type MockAlphaDisks struct { } // Get returns the object from the mock. -func (m *MockAlphaDisks) Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) { +func (m *MockDisks) Get(ctx context.Context, key *meta.Key) (*ga.Disk, error) { if m.GetHook != nil { if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaDisks.Get(%v, %s) = %+v, %v", ctx, key, obj, err) + glog.V(5).Infof("MockDisks.Get(%v, %s) = %+v, %v", ctx, key, obj, err) return obj, err } } @@ -4538,28 +4703,28 @@ func (m *MockAlphaDisks) Get(ctx context.Context, key *meta.Key) (*alpha.Disk, e defer m.Lock.Unlock() if err, ok := m.GetError[*key]; ok { - glog.V(5).Infof("MockAlphaDisks.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockDisks.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToAlpha() - glog.V(5).Infof("MockAlphaDisks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + typedObj := obj.ToGA() + glog.V(5).Infof("MockDisks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) return typedObj, nil } err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaDisks %v not found", key), + Message: fmt.Sprintf("MockDisks %v not found", key), } - glog.V(5).Infof("MockAlphaDisks.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockDisks.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } // List all of the objects in the mock in the given zone. -func (m *MockAlphaDisks) List(ctx context.Context, zone string, fl *filter.F) ([]*alpha.Disk, error) { +func (m *MockDisks) List(ctx context.Context, zone string, fl *filter.F) ([]*ga.Disk, error) { if m.ListHook != nil { if intercept, objs, err := m.ListHook(ctx, zone, fl, m); intercept { - glog.V(5).Infof("MockAlphaDisks.List(%v, %q, %v) = [%v items], %v", ctx, zone, fl, len(objs), err) + glog.V(5).Infof("MockDisks.List(%v, %q, %v) = [%v items], %v", ctx, zone, fl, len(objs), err) return objs, err } } @@ -4569,31 +4734,31 @@ func (m *MockAlphaDisks) List(ctx context.Context, zone string, fl *filter.F) ([ if m.ListError != nil { err := *m.ListError - glog.V(5).Infof("MockAlphaDisks.List(%v, %q, %v) = nil, %v", ctx, zone, fl, err) + glog.V(5).Infof("MockDisks.List(%v, %q, %v) = nil, %v", ctx, zone, fl, err) return nil, *m.ListError } - var objs []*alpha.Disk + var objs []*ga.Disk for key, obj := range m.Objects { if key.Zone != zone { continue } - if !fl.Match(obj.ToAlpha()) { + if !fl.Match(obj.ToGA()) { continue } - objs = append(objs, obj.ToAlpha()) + objs = append(objs, obj.ToGA()) } - glog.V(5).Infof("MockAlphaDisks.List(%v, %q, %v) = [%v items], nil", ctx, zone, fl, len(objs)) + glog.V(5).Infof("MockDisks.List(%v, %q, %v) = [%v items], nil", ctx, zone, fl, len(objs)) return objs, nil } // Insert is a mock for inserting/creating a new object. -func (m *MockAlphaDisks) Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error { +func (m *MockDisks) Insert(ctx context.Context, key *meta.Key, obj *ga.Disk) error { if m.InsertHook != nil { if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - glog.V(5).Infof("MockAlphaDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } } @@ -4605,32 +4770,32 @@ func (m *MockAlphaDisks) Insert(ctx context.Context, key *meta.Key, obj *alpha.D defer m.Lock.Unlock() if err, ok := m.InsertError[*key]; ok { - glog.V(5).Infof("MockAlphaDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } if _, ok := m.Objects[*key]; ok { err := &googleapi.Error{ Code: http.StatusConflict, - Message: fmt.Sprintf("MockAlphaDisks %v exists", key), + Message: fmt.Sprintf("MockDisks %v exists", key), } - glog.V(5).Infof("MockAlphaDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "alpha", "disks") - obj.SelfLink = SelfLink(meta.VersionAlpha, projectID, "disks", key) + projectID := m.ProjectRouter.ProjectID(ctx, "ga", "disks") + obj.SelfLink = SelfLink(meta.VersionGA, projectID, "disks", key) m.Objects[*key] = &MockDisksObj{obj} - glog.V(5).Infof("MockAlphaDisks.Insert(%v, %v, %+v) = nil", ctx, key, obj) + glog.V(5).Infof("MockDisks.Insert(%v, %v, %+v) = nil", ctx, key, obj) return nil } // Delete is a mock for deleting the object. -func (m *MockAlphaDisks) Delete(ctx context.Context, key *meta.Key) error { +func (m *MockDisks) Delete(ctx context.Context, key *meta.Key) error { if m.DeleteHook != nil { if intercept, err := m.DeleteHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockDisks.Delete(%v, %v) = %v", ctx, key, err) return err } } @@ -4642,180 +4807,222 @@ func (m *MockAlphaDisks) Delete(ctx context.Context, key *meta.Key) error { defer m.Lock.Unlock() if err, ok := m.DeleteError[*key]; ok { - glog.V(5).Infof("MockAlphaDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockDisks.Delete(%v, %v) = %v", ctx, key, err) return err } if _, ok := m.Objects[*key]; !ok { err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaDisks %v not found", key), + Message: fmt.Sprintf("MockDisks %v not found", key), } - glog.V(5).Infof("MockAlphaDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockDisks.Delete(%v, %v) = %v", ctx, key, err) return err } delete(m.Objects, *key) - glog.V(5).Infof("MockAlphaDisks.Delete(%v, %v) = nil", ctx, key) + glog.V(5).Infof("MockDisks.Delete(%v, %v) = nil", ctx, key) return nil } // Obj wraps the object for use in the mock. -func (m *MockAlphaDisks) Obj(o *alpha.Disk) *MockDisksObj { +func (m *MockDisks) Obj(o *ga.Disk) *MockDisksObj { return &MockDisksObj{o} } -// GCEAlphaDisks is a simplifying adapter for the GCE Disks. -type GCEAlphaDisks struct { +// Resize is a mock for the corresponding method. +func (m *MockDisks) Resize(ctx context.Context, key *meta.Key, arg0 *ga.DisksResizeRequest) error { + if m.ResizeHook != nil { + return m.ResizeHook(ctx, key, arg0, m) + } + return nil +} + +// GCEDisks is a simplifying adapter for the GCE Disks. +type GCEDisks struct { s *Service } // Get the Disk named by key. -func (g *GCEAlphaDisks) Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) { - glog.V(5).Infof("GCEAlphaDisks.Get(%v, %v): called", ctx, key) +func (g *GCEDisks) Get(ctx context.Context, key *meta.Key) (*ga.Disk, error) { + glog.V(5).Infof("GCEDisks.Get(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaDisks.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEDisks.Get(%v, %v): key is invalid (%#v)", ctx, key, key) return nil, fmt.Errorf("invalid GCE key (%#v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "Disks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Get", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "Disks", } - glog.V(5).Infof("GCEAlphaDisks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEDisks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaDisks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEDisks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) return nil, err } - call := g.s.Alpha.Disks.Get(projectID, key.Zone, key.Name) + call := g.s.GA.Disks.Get(projectID, key.Zone, key.Name) call.Context(ctx) v, err := call.Do() - glog.V(4).Infof("GCEAlphaDisks.Get(%v, %v) = %+v, %v", ctx, key, v, err) + glog.V(4).Infof("GCEDisks.Get(%v, %v) = %+v, %v", ctx, key, v, err) return v, err } // List all Disk objects. -func (g *GCEAlphaDisks) List(ctx context.Context, zone string, fl *filter.F) ([]*alpha.Disk, error) { - glog.V(5).Infof("GCEAlphaDisks.List(%v, %v, %v) called", ctx, zone, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "Disks") +func (g *GCEDisks) List(ctx context.Context, zone string, fl *filter.F) ([]*ga.Disk, error) { + glog.V(5).Infof("GCEDisks.List(%v, %v, %v) called", ctx, zone, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "List", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "Disks", } if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { return nil, err } - glog.V(5).Infof("GCEAlphaDisks.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, zone, fl, projectID, rk) - call := g.s.Alpha.Disks.List(projectID, zone) + glog.V(5).Infof("GCEDisks.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, zone, fl, projectID, rk) + call := g.s.GA.Disks.List(projectID, zone) if fl != filter.None { call.Filter(fl.String()) } - var all []*alpha.Disk - f := func(l *alpha.DiskList) error { - glog.V(5).Infof("GCEAlphaDisks.List(%v, ..., %v): page %+v", ctx, fl, l) + var all []*ga.Disk + f := func(l *ga.DiskList) error { + glog.V(5).Infof("GCEDisks.List(%v, ..., %v): page %+v", ctx, fl, l) all = append(all, l.Items...) return nil } if err := call.Pages(ctx, f); err != nil { - glog.V(4).Infof("GCEAlphaDisks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + glog.V(4).Infof("GCEDisks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) return nil, err } if glog.V(4) { - glog.V(4).Infof("GCEAlphaDisks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + glog.V(4).Infof("GCEDisks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) } else if glog.V(5) { var asStr []string for _, o := range all { asStr = append(asStr, fmt.Sprintf("%+v", o)) } - glog.V(5).Infof("GCEAlphaDisks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + glog.V(5).Infof("GCEDisks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) } return all, nil } // Insert Disk with key of value obj. -func (g *GCEAlphaDisks) Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error { - glog.V(5).Infof("GCEAlphaDisks.Insert(%v, %v, %+v): called", ctx, key, obj) +func (g *GCEDisks) Insert(ctx context.Context, key *meta.Key, obj *ga.Disk) error { + glog.V(5).Infof("GCEDisks.Insert(%v, %v, %+v): called", ctx, key, obj) if !key.Valid() { - glog.V(2).Infof("GCEAlphaDisks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEDisks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "Disks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Insert", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "Disks", } - glog.V(5).Infof("GCEAlphaDisks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEDisks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaDisks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEDisks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } obj.Name = key.Name - call := g.s.Alpha.Disks.Insert(projectID, key.Zone, obj) + call := g.s.GA.Disks.Insert(projectID, key.Zone, obj) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaDisks.Insert(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEDisks.Insert(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaDisks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + glog.V(4).Infof("GCEDisks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) return err } // Delete the Disk referenced by key. -func (g *GCEAlphaDisks) Delete(ctx context.Context, key *meta.Key) error { - glog.V(5).Infof("GCEAlphaDisks.Delete(%v, %v): called", ctx, key) +func (g *GCEDisks) Delete(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCEDisks.Delete(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaDisks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEDisks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "Disks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Delete", - Version: meta.Version("alpha"), + Version: meta.Version("ga"), Service: "Disks", } - glog.V(5).Infof("GCEAlphaDisks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEDisks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaDisks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEDisks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.Alpha.Disks.Delete(projectID, key.Zone, key.Name) + call := g.s.GA.Disks.Delete(projectID, key.Zone, key.Name) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEDisks.Delete(%v, %v) = %v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEDisks.Delete(%v, %v) = %v", ctx, key, err) + return err +} + +// Resize is a method on GCEDisks. +func (g *GCEDisks) Resize(ctx context.Context, key *meta.Key, arg0 *ga.DisksResizeRequest) error { + glog.V(5).Infof("GCEDisks.Resize(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEDisks.Resize(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Disks") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Resize", + Version: meta.Version("ga"), + Service: "Disks", + } + glog.V(5).Infof("GCEDisks.Resize(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEDisks.Resize(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.GA.Disks.Resize(projectID, key.Zone, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEDisks.Resize(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEDisks.Resize(%v, %v, ...) = %+v", ctx, key, err) return err } -// AlphaRegionDisks is an interface that allows for mocking of RegionDisks. -type AlphaRegionDisks interface { - Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) - List(ctx context.Context, region string, fl *filter.F) ([]*alpha.Disk, error) - Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error +// BetaRegionDisks is an interface that allows for mocking of RegionDisks. +type BetaRegionDisks interface { + Get(ctx context.Context, key *meta.Key) (*beta.Disk, error) + List(ctx context.Context, region string, fl *filter.F) ([]*beta.Disk, error) + Insert(ctx context.Context, key *meta.Key, obj *beta.Disk) error Delete(ctx context.Context, key *meta.Key) error + Resize(context.Context, *meta.Key, *beta.RegionDisksResizeRequest) error } -// NewMockAlphaRegionDisks returns a new mock for RegionDisks. -func NewMockAlphaRegionDisks(pr ProjectRouter, objs map[meta.Key]*MockRegionDisksObj) *MockAlphaRegionDisks { - mock := &MockAlphaRegionDisks{ +// NewMockBetaRegionDisks returns a new mock for RegionDisks. +func NewMockBetaRegionDisks(pr ProjectRouter, objs map[meta.Key]*MockRegionDisksObj) *MockBetaRegionDisks { + mock := &MockBetaRegionDisks{ ProjectRouter: pr, Objects: objs, @@ -4826,8 +5033,8 @@ func NewMockAlphaRegionDisks(pr ProjectRouter, objs map[meta.Key]*MockRegionDisk return mock } -// MockAlphaRegionDisks is the mock for RegionDisks. -type MockAlphaRegionDisks struct { +// MockBetaRegionDisks is the mock for RegionDisks. +type MockBetaRegionDisks struct { Lock sync.Mutex ProjectRouter ProjectRouter @@ -4846,10 +5053,11 @@ type MockAlphaRegionDisks struct { // order to add your own logic. Return (true, _, _) to prevent the normal // execution flow of the mock. Return (false, nil, nil) to continue with // normal mock behavior/ after the hook function executes. - GetHook func(ctx context.Context, key *meta.Key, m *MockAlphaRegionDisks) (bool, *alpha.Disk, error) - ListHook func(ctx context.Context, region string, fl *filter.F, m *MockAlphaRegionDisks) (bool, []*alpha.Disk, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *alpha.Disk, m *MockAlphaRegionDisks) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockAlphaRegionDisks) (bool, error) + GetHook func(ctx context.Context, key *meta.Key, m *MockBetaRegionDisks) (bool, *beta.Disk, error) + ListHook func(ctx context.Context, region string, fl *filter.F, m *MockBetaRegionDisks) (bool, []*beta.Disk, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *beta.Disk, m *MockBetaRegionDisks) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockBetaRegionDisks) (bool, error) + ResizeHook func(context.Context, *meta.Key, *beta.RegionDisksResizeRequest, *MockBetaRegionDisks) error // X is extra state that can be used as part of the mock. Generated code // will not use this field. @@ -4857,10 +5065,10 @@ type MockAlphaRegionDisks struct { } // Get returns the object from the mock. -func (m *MockAlphaRegionDisks) Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) { +func (m *MockBetaRegionDisks) Get(ctx context.Context, key *meta.Key) (*beta.Disk, error) { if m.GetHook != nil { if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaRegionDisks.Get(%v, %s) = %+v, %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaRegionDisks.Get(%v, %s) = %+v, %v", ctx, key, obj, err) return obj, err } } @@ -4872,28 +5080,28 @@ func (m *MockAlphaRegionDisks) Get(ctx context.Context, key *meta.Key) (*alpha.D defer m.Lock.Unlock() if err, ok := m.GetError[*key]; ok { - glog.V(5).Infof("MockAlphaRegionDisks.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToAlpha() - glog.V(5).Infof("MockAlphaRegionDisks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + typedObj := obj.ToBeta() + glog.V(5).Infof("MockBetaRegionDisks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) return typedObj, nil } err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaRegionDisks %v not found", key), + Message: fmt.Sprintf("MockBetaRegionDisks %v not found", key), } - glog.V(5).Infof("MockAlphaRegionDisks.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } // List all of the objects in the mock in the given region. -func (m *MockAlphaRegionDisks) List(ctx context.Context, region string, fl *filter.F) ([]*alpha.Disk, error) { +func (m *MockBetaRegionDisks) List(ctx context.Context, region string, fl *filter.F) ([]*beta.Disk, error) { if m.ListHook != nil { if intercept, objs, err := m.ListHook(ctx, region, fl, m); intercept { - glog.V(5).Infof("MockAlphaRegionDisks.List(%v, %q, %v) = [%v items], %v", ctx, region, fl, len(objs), err) + glog.V(5).Infof("MockBetaRegionDisks.List(%v, %q, %v) = [%v items], %v", ctx, region, fl, len(objs), err) return objs, err } } @@ -4903,31 +5111,31 @@ func (m *MockAlphaRegionDisks) List(ctx context.Context, region string, fl *filt if m.ListError != nil { err := *m.ListError - glog.V(5).Infof("MockAlphaRegionDisks.List(%v, %q, %v) = nil, %v", ctx, region, fl, err) + glog.V(5).Infof("MockBetaRegionDisks.List(%v, %q, %v) = nil, %v", ctx, region, fl, err) return nil, *m.ListError } - var objs []*alpha.Disk + var objs []*beta.Disk for key, obj := range m.Objects { if key.Region != region { continue } - if !fl.Match(obj.ToAlpha()) { + if !fl.Match(obj.ToBeta()) { continue } - objs = append(objs, obj.ToAlpha()) + objs = append(objs, obj.ToBeta()) } - glog.V(5).Infof("MockAlphaRegionDisks.List(%v, %q, %v) = [%v items], nil", ctx, region, fl, len(objs)) + glog.V(5).Infof("MockBetaRegionDisks.List(%v, %q, %v) = [%v items], nil", ctx, region, fl, len(objs)) return objs, nil } // Insert is a mock for inserting/creating a new object. -func (m *MockAlphaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error { +func (m *MockBetaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *beta.Disk) error { if m.InsertHook != nil { if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - glog.V(5).Infof("MockAlphaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } } @@ -4939,32 +5147,32 @@ func (m *MockAlphaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *a defer m.Lock.Unlock() if err, ok := m.InsertError[*key]; ok { - glog.V(5).Infof("MockAlphaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } if _, ok := m.Objects[*key]; ok { err := &googleapi.Error{ Code: http.StatusConflict, - Message: fmt.Sprintf("MockAlphaRegionDisks %v exists", key), + Message: fmt.Sprintf("MockBetaRegionDisks %v exists", key), } - glog.V(5).Infof("MockAlphaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaRegionDisks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "alpha", "disks") - obj.SelfLink = SelfLink(meta.VersionAlpha, projectID, "disks", key) + projectID := m.ProjectRouter.ProjectID(ctx, "beta", "disks") + obj.SelfLink = SelfLink(meta.VersionBeta, projectID, "disks", key) m.Objects[*key] = &MockRegionDisksObj{obj} - glog.V(5).Infof("MockAlphaRegionDisks.Insert(%v, %v, %+v) = nil", ctx, key, obj) + glog.V(5).Infof("MockBetaRegionDisks.Insert(%v, %v, %+v) = nil", ctx, key, obj) return nil } // Delete is a mock for deleting the object. -func (m *MockAlphaRegionDisks) Delete(ctx context.Context, key *meta.Key) error { +func (m *MockBetaRegionDisks) Delete(ctx context.Context, key *meta.Key) error { if m.DeleteHook != nil { if intercept, err := m.DeleteHook(ctx, key, m); intercept { - glog.V(5).Infof("MockAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) return err } } @@ -4976,166 +5184,207 @@ func (m *MockAlphaRegionDisks) Delete(ctx context.Context, key *meta.Key) error defer m.Lock.Unlock() if err, ok := m.DeleteError[*key]; ok { - glog.V(5).Infof("MockAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) return err } if _, ok := m.Objects[*key]; !ok { err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockAlphaRegionDisks %v not found", key), + Message: fmt.Sprintf("MockBetaRegionDisks %v not found", key), } - glog.V(5).Infof("MockAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) return err } delete(m.Objects, *key) - glog.V(5).Infof("MockAlphaRegionDisks.Delete(%v, %v) = nil", ctx, key) + glog.V(5).Infof("MockBetaRegionDisks.Delete(%v, %v) = nil", ctx, key) return nil } // Obj wraps the object for use in the mock. -func (m *MockAlphaRegionDisks) Obj(o *alpha.Disk) *MockRegionDisksObj { +func (m *MockBetaRegionDisks) Obj(o *beta.Disk) *MockRegionDisksObj { return &MockRegionDisksObj{o} } -// GCEAlphaRegionDisks is a simplifying adapter for the GCE RegionDisks. -type GCEAlphaRegionDisks struct { +// Resize is a mock for the corresponding method. +func (m *MockBetaRegionDisks) Resize(ctx context.Context, key *meta.Key, arg0 *beta.RegionDisksResizeRequest) error { + if m.ResizeHook != nil { + return m.ResizeHook(ctx, key, arg0, m) + } + return nil +} + +// GCEBetaRegionDisks is a simplifying adapter for the GCE RegionDisks. +type GCEBetaRegionDisks struct { s *Service } // Get the Disk named by key. -func (g *GCEAlphaRegionDisks) Get(ctx context.Context, key *meta.Key) (*alpha.Disk, error) { - glog.V(5).Infof("GCEAlphaRegionDisks.Get(%v, %v): called", ctx, key) +func (g *GCEBetaRegionDisks) Get(ctx context.Context, key *meta.Key) (*beta.Disk, error) { + glog.V(5).Infof("GCEBetaRegionDisks.Get(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionDisks.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaRegionDisks.Get(%v, %v): key is invalid (%#v)", ctx, key, key) return nil, fmt.Errorf("invalid GCE key (%#v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionDisks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Get", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "RegionDisks", } - glog.V(5).Infof("GCEAlphaRegionDisks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaRegionDisks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) return nil, err } - call := g.s.Alpha.RegionDisks.Get(projectID, key.Region, key.Name) + call := g.s.Beta.RegionDisks.Get(projectID, key.Region, key.Name) call.Context(ctx) v, err := call.Do() - glog.V(4).Infof("GCEAlphaRegionDisks.Get(%v, %v) = %+v, %v", ctx, key, v, err) + glog.V(4).Infof("GCEBetaRegionDisks.Get(%v, %v) = %+v, %v", ctx, key, v, err) return v, err } // List all Disk objects. -func (g *GCEAlphaRegionDisks) List(ctx context.Context, region string, fl *filter.F) ([]*alpha.Disk, error) { - glog.V(5).Infof("GCEAlphaRegionDisks.List(%v, %v, %v) called", ctx, region, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionDisks") +func (g *GCEBetaRegionDisks) List(ctx context.Context, region string, fl *filter.F) ([]*beta.Disk, error) { + glog.V(5).Infof("GCEBetaRegionDisks.List(%v, %v, %v) called", ctx, region, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "List", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "RegionDisks", } if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { return nil, err } - glog.V(5).Infof("GCEAlphaRegionDisks.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, region, fl, projectID, rk) - call := g.s.Alpha.RegionDisks.List(projectID, region) + glog.V(5).Infof("GCEBetaRegionDisks.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, region, fl, projectID, rk) + call := g.s.Beta.RegionDisks.List(projectID, region) if fl != filter.None { call.Filter(fl.String()) } - var all []*alpha.Disk - f := func(l *alpha.DiskList) error { - glog.V(5).Infof("GCEAlphaRegionDisks.List(%v, ..., %v): page %+v", ctx, fl, l) + var all []*beta.Disk + f := func(l *beta.DiskList) error { + glog.V(5).Infof("GCEBetaRegionDisks.List(%v, ..., %v): page %+v", ctx, fl, l) all = append(all, l.Items...) return nil } if err := call.Pages(ctx, f); err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + glog.V(4).Infof("GCEBetaRegionDisks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) return nil, err } if glog.V(4) { - glog.V(4).Infof("GCEAlphaRegionDisks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + glog.V(4).Infof("GCEBetaRegionDisks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) } else if glog.V(5) { var asStr []string for _, o := range all { asStr = append(asStr, fmt.Sprintf("%+v", o)) } - glog.V(5).Infof("GCEAlphaRegionDisks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + glog.V(5).Infof("GCEBetaRegionDisks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) } return all, nil } // Insert Disk with key of value obj. -func (g *GCEAlphaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *alpha.Disk) error { - glog.V(5).Infof("GCEAlphaRegionDisks.Insert(%v, %v, %+v): called", ctx, key, obj) +func (g *GCEBetaRegionDisks) Insert(ctx context.Context, key *meta.Key, obj *beta.Disk) error { + glog.V(5).Infof("GCEBetaRegionDisks.Insert(%v, %v, %+v): called", ctx, key, obj) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionDisks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaRegionDisks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionDisks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Insert", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "RegionDisks", } - glog.V(5).Infof("GCEAlphaRegionDisks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaRegionDisks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } obj.Name = key.Name - call := g.s.Alpha.RegionDisks.Insert(projectID, key.Region, obj) + call := g.s.Beta.RegionDisks.Insert(projectID, key.Region, obj) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Insert(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Insert(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaRegionDisks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + glog.V(4).Infof("GCEBetaRegionDisks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) return err } // Delete the Disk referenced by key. -func (g *GCEAlphaRegionDisks) Delete(ctx context.Context, key *meta.Key) error { - glog.V(5).Infof("GCEAlphaRegionDisks.Delete(%v, %v): called", ctx, key) +func (g *GCEBetaRegionDisks) Delete(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCEBetaRegionDisks.Delete(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCEAlphaRegionDisks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaRegionDisks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "alpha", "RegionDisks") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Delete", - Version: meta.Version("alpha"), + Version: meta.Version("beta"), Service: "RegionDisks", } - glog.V(5).Infof("GCEAlphaRegionDisks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaRegionDisks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.Alpha.RegionDisks.Delete(projectID, key.Region, key.Name) + call := g.s.Beta.RegionDisks.Delete(projectID, key.Region, key.Name) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCEAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCEAlphaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEBetaRegionDisks.Delete(%v, %v) = %v", ctx, key, err) + return err +} + +// Resize is a method on GCEBetaRegionDisks. +func (g *GCEBetaRegionDisks) Resize(ctx context.Context, key *meta.Key, arg0 *beta.RegionDisksResizeRequest) error { + glog.V(5).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "RegionDisks") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Resize", + Version: meta.Version("beta"), + Service: "RegionDisks", + } + glog.V(5).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Beta.RegionDisks.Resize(projectID, key.Region, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEBetaRegionDisks.Resize(%v, %v, ...) = %+v", ctx, key, err) return err } @@ -10786,24 +11035,366 @@ func (m *MockRoutes) Get(ctx context.Context, key *meta.Key) (*ga.Route, error) return nil, err } if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToGA() - glog.V(5).Infof("MockRoutes.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + typedObj := obj.ToGA() + glog.V(5).Infof("MockRoutes.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + return typedObj, nil + } + + err := &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("MockRoutes %v not found", key), + } + glog.V(5).Infof("MockRoutes.Get(%v, %s) = nil, %v", ctx, key, err) + return nil, err +} + +// List all of the objects in the mock. +func (m *MockRoutes) List(ctx context.Context, fl *filter.F) ([]*ga.Route, error) { + if m.ListHook != nil { + if intercept, objs, err := m.ListHook(ctx, fl, m); intercept { + glog.V(5).Infof("MockRoutes.List(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) + return objs, err + } + } + + m.Lock.Lock() + defer m.Lock.Unlock() + + if m.ListError != nil { + err := *m.ListError + glog.V(5).Infof("MockRoutes.List(%v, %v) = nil, %v", ctx, fl, err) + + return nil, *m.ListError + } + + var objs []*ga.Route + for _, obj := range m.Objects { + if !fl.Match(obj.ToGA()) { + continue + } + objs = append(objs, obj.ToGA()) + } + + glog.V(5).Infof("MockRoutes.List(%v, %v) = [%v items], nil", ctx, fl, len(objs)) + return objs, nil +} + +// Insert is a mock for inserting/creating a new object. +func (m *MockRoutes) Insert(ctx context.Context, key *meta.Key, obj *ga.Route) error { + if m.InsertHook != nil { + if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { + glog.V(5).Infof("MockRoutes.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + return err + } + } + if !key.Valid() { + return fmt.Errorf("invalid GCE key (%+v)", key) + } + + m.Lock.Lock() + defer m.Lock.Unlock() + + if err, ok := m.InsertError[*key]; ok { + glog.V(5).Infof("MockRoutes.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + return err + } + if _, ok := m.Objects[*key]; ok { + err := &googleapi.Error{ + Code: http.StatusConflict, + Message: fmt.Sprintf("MockRoutes %v exists", key), + } + glog.V(5).Infof("MockRoutes.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + return err + } + + obj.Name = key.Name + projectID := m.ProjectRouter.ProjectID(ctx, "ga", "routes") + obj.SelfLink = SelfLink(meta.VersionGA, projectID, "routes", key) + + m.Objects[*key] = &MockRoutesObj{obj} + glog.V(5).Infof("MockRoutes.Insert(%v, %v, %+v) = nil", ctx, key, obj) + return nil +} + +// Delete is a mock for deleting the object. +func (m *MockRoutes) Delete(ctx context.Context, key *meta.Key) error { + if m.DeleteHook != nil { + if intercept, err := m.DeleteHook(ctx, key, m); intercept { + glog.V(5).Infof("MockRoutes.Delete(%v, %v) = %v", ctx, key, err) + return err + } + } + if !key.Valid() { + return fmt.Errorf("invalid GCE key (%+v)", key) + } + + m.Lock.Lock() + defer m.Lock.Unlock() + + if err, ok := m.DeleteError[*key]; ok { + glog.V(5).Infof("MockRoutes.Delete(%v, %v) = %v", ctx, key, err) + return err + } + if _, ok := m.Objects[*key]; !ok { + err := &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("MockRoutes %v not found", key), + } + glog.V(5).Infof("MockRoutes.Delete(%v, %v) = %v", ctx, key, err) + return err + } + + delete(m.Objects, *key) + glog.V(5).Infof("MockRoutes.Delete(%v, %v) = nil", ctx, key) + return nil +} + +// Obj wraps the object for use in the mock. +func (m *MockRoutes) Obj(o *ga.Route) *MockRoutesObj { + return &MockRoutesObj{o} +} + +// GCERoutes is a simplifying adapter for the GCE Routes. +type GCERoutes struct { + s *Service +} + +// Get the Route named by key. +func (g *GCERoutes) Get(ctx context.Context, key *meta.Key) (*ga.Route, error) { + glog.V(5).Infof("GCERoutes.Get(%v, %v): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCERoutes.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + return nil, fmt.Errorf("invalid GCE key (%#v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Routes") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Get", + Version: meta.Version("ga"), + Service: "Routes", + } + glog.V(5).Infof("GCERoutes.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCERoutes.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + return nil, err + } + call := g.s.GA.Routes.Get(projectID, key.Name) + call.Context(ctx) + v, err := call.Do() + glog.V(4).Infof("GCERoutes.Get(%v, %v) = %+v, %v", ctx, key, v, err) + return v, err +} + +// List all Route objects. +func (g *GCERoutes) List(ctx context.Context, fl *filter.F) ([]*ga.Route, error) { + glog.V(5).Infof("GCERoutes.List(%v, %v) called", ctx, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Routes") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "List", + Version: meta.Version("ga"), + Service: "Routes", + } + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + return nil, err + } + glog.V(5).Infof("GCERoutes.List(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) + call := g.s.GA.Routes.List(projectID) + if fl != filter.None { + call.Filter(fl.String()) + } + var all []*ga.Route + f := func(l *ga.RouteList) error { + glog.V(5).Infof("GCERoutes.List(%v, ..., %v): page %+v", ctx, fl, l) + all = append(all, l.Items...) + return nil + } + if err := call.Pages(ctx, f); err != nil { + glog.V(4).Infof("GCERoutes.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + return nil, err + } + + if glog.V(4) { + glog.V(4).Infof("GCERoutes.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + } else if glog.V(5) { + var asStr []string + for _, o := range all { + asStr = append(asStr, fmt.Sprintf("%+v", o)) + } + glog.V(5).Infof("GCERoutes.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + } + + return all, nil +} + +// Insert Route with key of value obj. +func (g *GCERoutes) Insert(ctx context.Context, key *meta.Key, obj *ga.Route) error { + glog.V(5).Infof("GCERoutes.Insert(%v, %v, %+v): called", ctx, key, obj) + if !key.Valid() { + glog.V(2).Infof("GCERoutes.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Routes") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Insert", + Version: meta.Version("ga"), + Service: "Routes", + } + glog.V(5).Infof("GCERoutes.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCERoutes.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + obj.Name = key.Name + call := g.s.GA.Routes.Insert(projectID, obj) + call.Context(ctx) + + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCERoutes.Insert(%v, %v, ...) = %+v", ctx, key, err) + return err + } + + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCERoutes.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + return err +} + +// Delete the Route referenced by key. +func (g *GCERoutes) Delete(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCERoutes.Delete(%v, %v): called", ctx, key) + if !key.Valid() { + glog.V(2).Infof("GCERoutes.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Routes") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Delete", + Version: meta.Version("ga"), + Service: "Routes", + } + glog.V(5).Infof("GCERoutes.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCERoutes.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.GA.Routes.Delete(projectID, key.Name) + + call.Context(ctx) + + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCERoutes.Delete(%v, %v) = %v", ctx, key, err) + return err + } + + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCERoutes.Delete(%v, %v) = %v", ctx, key, err) + return err +} + +// BetaSecurityPolicies is an interface that allows for mocking of SecurityPolicies. +type BetaSecurityPolicies interface { + Get(ctx context.Context, key *meta.Key) (*beta.SecurityPolicy, error) + List(ctx context.Context, fl *filter.F) ([]*beta.SecurityPolicy, error) + Insert(ctx context.Context, key *meta.Key, obj *beta.SecurityPolicy) error + Delete(ctx context.Context, key *meta.Key) error + AddRule(context.Context, *meta.Key, *beta.SecurityPolicyRule) error + GetRule(context.Context, *meta.Key) (*beta.SecurityPolicyRule, error) + Patch(context.Context, *meta.Key, *beta.SecurityPolicy) error + PatchRule(context.Context, *meta.Key, *beta.SecurityPolicyRule) error + RemoveRule(context.Context, *meta.Key) error +} + +// NewMockBetaSecurityPolicies returns a new mock for SecurityPolicies. +func NewMockBetaSecurityPolicies(pr ProjectRouter, objs map[meta.Key]*MockSecurityPoliciesObj) *MockBetaSecurityPolicies { + mock := &MockBetaSecurityPolicies{ + ProjectRouter: pr, + + Objects: objs, + GetError: map[meta.Key]error{}, + InsertError: map[meta.Key]error{}, + DeleteError: map[meta.Key]error{}, + } + return mock +} + +// MockBetaSecurityPolicies is the mock for SecurityPolicies. +type MockBetaSecurityPolicies struct { + Lock sync.Mutex + + ProjectRouter ProjectRouter + + // Objects maintained by the mock. + Objects map[meta.Key]*MockSecurityPoliciesObj + + // If an entry exists for the given key and operation, then the error + // will be returned instead of the operation. + GetError map[meta.Key]error + ListError *error + InsertError map[meta.Key]error + DeleteError map[meta.Key]error + + // xxxHook allow you to intercept the standard processing of the mock in + // order to add your own logic. Return (true, _, _) to prevent the normal + // execution flow of the mock. Return (false, nil, nil) to continue with + // normal mock behavior/ after the hook function executes. + GetHook func(ctx context.Context, key *meta.Key, m *MockBetaSecurityPolicies) (bool, *beta.SecurityPolicy, error) + ListHook func(ctx context.Context, fl *filter.F, m *MockBetaSecurityPolicies) (bool, []*beta.SecurityPolicy, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *beta.SecurityPolicy, m *MockBetaSecurityPolicies) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockBetaSecurityPolicies) (bool, error) + AddRuleHook func(context.Context, *meta.Key, *beta.SecurityPolicyRule, *MockBetaSecurityPolicies) error + GetRuleHook func(context.Context, *meta.Key, *MockBetaSecurityPolicies) (*beta.SecurityPolicyRule, error) + PatchHook func(context.Context, *meta.Key, *beta.SecurityPolicy, *MockBetaSecurityPolicies) error + PatchRuleHook func(context.Context, *meta.Key, *beta.SecurityPolicyRule, *MockBetaSecurityPolicies) error + RemoveRuleHook func(context.Context, *meta.Key, *MockBetaSecurityPolicies) error + + // X is extra state that can be used as part of the mock. Generated code + // will not use this field. + X interface{} +} + +// Get returns the object from the mock. +func (m *MockBetaSecurityPolicies) Get(ctx context.Context, key *meta.Key) (*beta.SecurityPolicy, error) { + if m.GetHook != nil { + if intercept, obj, err := m.GetHook(ctx, key, m); intercept { + glog.V(5).Infof("MockBetaSecurityPolicies.Get(%v, %s) = %+v, %v", ctx, key, obj, err) + return obj, err + } + } + if !key.Valid() { + return nil, fmt.Errorf("invalid GCE key (%+v)", key) + } + + m.Lock.Lock() + defer m.Lock.Unlock() + + if err, ok := m.GetError[*key]; ok { + glog.V(5).Infof("MockBetaSecurityPolicies.Get(%v, %s) = nil, %v", ctx, key, err) + return nil, err + } + if obj, ok := m.Objects[*key]; ok { + typedObj := obj.ToBeta() + glog.V(5).Infof("MockBetaSecurityPolicies.Get(%v, %s) = %+v, nil", ctx, key, typedObj) return typedObj, nil } err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockRoutes %v not found", key), + Message: fmt.Sprintf("MockBetaSecurityPolicies %v not found", key), } - glog.V(5).Infof("MockRoutes.Get(%v, %s) = nil, %v", ctx, key, err) + glog.V(5).Infof("MockBetaSecurityPolicies.Get(%v, %s) = nil, %v", ctx, key, err) return nil, err } // List all of the objects in the mock. -func (m *MockRoutes) List(ctx context.Context, fl *filter.F) ([]*ga.Route, error) { +func (m *MockBetaSecurityPolicies) List(ctx context.Context, fl *filter.F) ([]*beta.SecurityPolicy, error) { if m.ListHook != nil { if intercept, objs, err := m.ListHook(ctx, fl, m); intercept { - glog.V(5).Infof("MockRoutes.List(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) + glog.V(5).Infof("MockBetaSecurityPolicies.List(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) return objs, err } } @@ -10813,28 +11404,28 @@ func (m *MockRoutes) List(ctx context.Context, fl *filter.F) ([]*ga.Route, error if m.ListError != nil { err := *m.ListError - glog.V(5).Infof("MockRoutes.List(%v, %v) = nil, %v", ctx, fl, err) + glog.V(5).Infof("MockBetaSecurityPolicies.List(%v, %v) = nil, %v", ctx, fl, err) return nil, *m.ListError } - var objs []*ga.Route + var objs []*beta.SecurityPolicy for _, obj := range m.Objects { - if !fl.Match(obj.ToGA()) { + if !fl.Match(obj.ToBeta()) { continue } - objs = append(objs, obj.ToGA()) + objs = append(objs, obj.ToBeta()) } - glog.V(5).Infof("MockRoutes.List(%v, %v) = [%v items], nil", ctx, fl, len(objs)) + glog.V(5).Infof("MockBetaSecurityPolicies.List(%v, %v) = [%v items], nil", ctx, fl, len(objs)) return objs, nil } // Insert is a mock for inserting/creating a new object. -func (m *MockRoutes) Insert(ctx context.Context, key *meta.Key, obj *ga.Route) error { +func (m *MockBetaSecurityPolicies) Insert(ctx context.Context, key *meta.Key, obj *beta.SecurityPolicy) error { if m.InsertHook != nil { if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - glog.V(5).Infof("MockRoutes.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaSecurityPolicies.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } } @@ -10846,32 +11437,32 @@ func (m *MockRoutes) Insert(ctx context.Context, key *meta.Key, obj *ga.Route) e defer m.Lock.Unlock() if err, ok := m.InsertError[*key]; ok { - glog.V(5).Infof("MockRoutes.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaSecurityPolicies.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } if _, ok := m.Objects[*key]; ok { err := &googleapi.Error{ Code: http.StatusConflict, - Message: fmt.Sprintf("MockRoutes %v exists", key), + Message: fmt.Sprintf("MockBetaSecurityPolicies %v exists", key), } - glog.V(5).Infof("MockRoutes.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + glog.V(5).Infof("MockBetaSecurityPolicies.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) return err } obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "ga", "routes") - obj.SelfLink = SelfLink(meta.VersionGA, projectID, "routes", key) + projectID := m.ProjectRouter.ProjectID(ctx, "beta", "securityPolicies") + obj.SelfLink = SelfLink(meta.VersionBeta, projectID, "securityPolicies", key) - m.Objects[*key] = &MockRoutesObj{obj} - glog.V(5).Infof("MockRoutes.Insert(%v, %v, %+v) = nil", ctx, key, obj) + m.Objects[*key] = &MockSecurityPoliciesObj{obj} + glog.V(5).Infof("MockBetaSecurityPolicies.Insert(%v, %v, %+v) = nil", ctx, key, obj) return nil } // Delete is a mock for deleting the object. -func (m *MockRoutes) Delete(ctx context.Context, key *meta.Key) error { +func (m *MockBetaSecurityPolicies) Delete(ctx context.Context, key *meta.Key) error { if m.DeleteHook != nil { if intercept, err := m.DeleteHook(ctx, key, m); intercept { - glog.V(5).Infof("MockRoutes.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaSecurityPolicies.Delete(%v, %v) = %v", ctx, key, err) return err } } @@ -10883,167 +11474,367 @@ func (m *MockRoutes) Delete(ctx context.Context, key *meta.Key) error { defer m.Lock.Unlock() if err, ok := m.DeleteError[*key]; ok { - glog.V(5).Infof("MockRoutes.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaSecurityPolicies.Delete(%v, %v) = %v", ctx, key, err) return err } if _, ok := m.Objects[*key]; !ok { err := &googleapi.Error{ Code: http.StatusNotFound, - Message: fmt.Sprintf("MockRoutes %v not found", key), + Message: fmt.Sprintf("MockBetaSecurityPolicies %v not found", key), } - glog.V(5).Infof("MockRoutes.Delete(%v, %v) = %v", ctx, key, err) + glog.V(5).Infof("MockBetaSecurityPolicies.Delete(%v, %v) = %v", ctx, key, err) return err } delete(m.Objects, *key) - glog.V(5).Infof("MockRoutes.Delete(%v, %v) = nil", ctx, key) + glog.V(5).Infof("MockBetaSecurityPolicies.Delete(%v, %v) = nil", ctx, key) return nil } // Obj wraps the object for use in the mock. -func (m *MockRoutes) Obj(o *ga.Route) *MockRoutesObj { - return &MockRoutesObj{o} +func (m *MockBetaSecurityPolicies) Obj(o *beta.SecurityPolicy) *MockSecurityPoliciesObj { + return &MockSecurityPoliciesObj{o} } -// GCERoutes is a simplifying adapter for the GCE Routes. -type GCERoutes struct { +// AddRule is a mock for the corresponding method. +func (m *MockBetaSecurityPolicies) AddRule(ctx context.Context, key *meta.Key, arg0 *beta.SecurityPolicyRule) error { + if m.AddRuleHook != nil { + return m.AddRuleHook(ctx, key, arg0, m) + } + return nil +} + +// GetRule is a mock for the corresponding method. +func (m *MockBetaSecurityPolicies) GetRule(ctx context.Context, key *meta.Key) (*beta.SecurityPolicyRule, error) { + if m.GetRuleHook != nil { + return m.GetRuleHook(ctx, key, m) + } + return nil, fmt.Errorf("GetRuleHook must be set") +} + +// Patch is a mock for the corresponding method. +func (m *MockBetaSecurityPolicies) Patch(ctx context.Context, key *meta.Key, arg0 *beta.SecurityPolicy) error { + if m.PatchHook != nil { + return m.PatchHook(ctx, key, arg0, m) + } + return nil +} + +// PatchRule is a mock for the corresponding method. +func (m *MockBetaSecurityPolicies) PatchRule(ctx context.Context, key *meta.Key, arg0 *beta.SecurityPolicyRule) error { + if m.PatchRuleHook != nil { + return m.PatchRuleHook(ctx, key, arg0, m) + } + return nil +} + +// RemoveRule is a mock for the corresponding method. +func (m *MockBetaSecurityPolicies) RemoveRule(ctx context.Context, key *meta.Key) error { + if m.RemoveRuleHook != nil { + return m.RemoveRuleHook(ctx, key, m) + } + return nil +} + +// GCEBetaSecurityPolicies is a simplifying adapter for the GCE SecurityPolicies. +type GCEBetaSecurityPolicies struct { s *Service } -// Get the Route named by key. -func (g *GCERoutes) Get(ctx context.Context, key *meta.Key) (*ga.Route, error) { - glog.V(5).Infof("GCERoutes.Get(%v, %v): called", ctx, key) +// Get the SecurityPolicy named by key. +func (g *GCEBetaSecurityPolicies) Get(ctx context.Context, key *meta.Key) (*beta.SecurityPolicy, error) { + glog.V(5).Infof("GCEBetaSecurityPolicies.Get(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCERoutes.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaSecurityPolicies.Get(%v, %v): key is invalid (%#v)", ctx, key, key) return nil, fmt.Errorf("invalid GCE key (%#v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Routes") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "SecurityPolicies") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Get", - Version: meta.Version("ga"), - Service: "Routes", + Version: meta.Version("beta"), + Service: "SecurityPolicies", } - glog.V(5).Infof("GCERoutes.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaSecurityPolicies.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCERoutes.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaSecurityPolicies.Get(%v, %v): RateLimiter error: %v", ctx, key, err) return nil, err } - call := g.s.GA.Routes.Get(projectID, key.Name) + call := g.s.Beta.SecurityPolicies.Get(projectID, key.Name) call.Context(ctx) v, err := call.Do() - glog.V(4).Infof("GCERoutes.Get(%v, %v) = %+v, %v", ctx, key, v, err) + glog.V(4).Infof("GCEBetaSecurityPolicies.Get(%v, %v) = %+v, %v", ctx, key, v, err) return v, err } -// List all Route objects. -func (g *GCERoutes) List(ctx context.Context, fl *filter.F) ([]*ga.Route, error) { - glog.V(5).Infof("GCERoutes.List(%v, %v) called", ctx, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Routes") +// List all SecurityPolicy objects. +func (g *GCEBetaSecurityPolicies) List(ctx context.Context, fl *filter.F) ([]*beta.SecurityPolicy, error) { + glog.V(5).Infof("GCEBetaSecurityPolicies.List(%v, %v) called", ctx, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "SecurityPolicies") rk := &RateLimitKey{ ProjectID: projectID, Operation: "List", - Version: meta.Version("ga"), - Service: "Routes", + Version: meta.Version("beta"), + Service: "SecurityPolicies", } if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { return nil, err } - glog.V(5).Infof("GCERoutes.List(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) - call := g.s.GA.Routes.List(projectID) + glog.V(5).Infof("GCEBetaSecurityPolicies.List(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) + call := g.s.Beta.SecurityPolicies.List(projectID) if fl != filter.None { call.Filter(fl.String()) } - var all []*ga.Route - f := func(l *ga.RouteList) error { - glog.V(5).Infof("GCERoutes.List(%v, ..., %v): page %+v", ctx, fl, l) + var all []*beta.SecurityPolicy + f := func(l *beta.SecurityPolicyList) error { + glog.V(5).Infof("GCEBetaSecurityPolicies.List(%v, ..., %v): page %+v", ctx, fl, l) all = append(all, l.Items...) return nil } if err := call.Pages(ctx, f); err != nil { - glog.V(4).Infof("GCERoutes.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + glog.V(4).Infof("GCEBetaSecurityPolicies.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) return nil, err } if glog.V(4) { - glog.V(4).Infof("GCERoutes.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + glog.V(4).Infof("GCEBetaSecurityPolicies.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) } else if glog.V(5) { var asStr []string for _, o := range all { asStr = append(asStr, fmt.Sprintf("%+v", o)) } - glog.V(5).Infof("GCERoutes.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + glog.V(5).Infof("GCEBetaSecurityPolicies.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) } return all, nil } -// Insert Route with key of value obj. -func (g *GCERoutes) Insert(ctx context.Context, key *meta.Key, obj *ga.Route) error { - glog.V(5).Infof("GCERoutes.Insert(%v, %v, %+v): called", ctx, key, obj) +// Insert SecurityPolicy with key of value obj. +func (g *GCEBetaSecurityPolicies) Insert(ctx context.Context, key *meta.Key, obj *beta.SecurityPolicy) error { + glog.V(5).Infof("GCEBetaSecurityPolicies.Insert(%v, %v, %+v): called", ctx, key, obj) if !key.Valid() { - glog.V(2).Infof("GCERoutes.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaSecurityPolicies.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Routes") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "SecurityPolicies") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Insert", - Version: meta.Version("ga"), - Service: "Routes", + Version: meta.Version("beta"), + Service: "SecurityPolicies", } - glog.V(5).Infof("GCERoutes.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaSecurityPolicies.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCERoutes.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaSecurityPolicies.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) return err } obj.Name = key.Name - call := g.s.GA.Routes.Insert(projectID, obj) + call := g.s.Beta.SecurityPolicies.Insert(projectID, obj) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCERoutes.Insert(%v, %v, ...) = %+v", ctx, key, err) + glog.V(4).Infof("GCEBetaSecurityPolicies.Insert(%v, %v, ...) = %+v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCERoutes.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + glog.V(4).Infof("GCEBetaSecurityPolicies.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) return err } -// Delete the Route referenced by key. -func (g *GCERoutes) Delete(ctx context.Context, key *meta.Key) error { - glog.V(5).Infof("GCERoutes.Delete(%v, %v): called", ctx, key) +// Delete the SecurityPolicy referenced by key. +func (g *GCEBetaSecurityPolicies) Delete(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCEBetaSecurityPolicies.Delete(%v, %v): called", ctx, key) if !key.Valid() { - glog.V(2).Infof("GCERoutes.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + glog.V(2).Infof("GCEBetaSecurityPolicies.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) return fmt.Errorf("invalid GCE key (%+v)", key) } - projectID := g.s.ProjectRouter.ProjectID(ctx, "ga", "Routes") + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "SecurityPolicies") rk := &RateLimitKey{ ProjectID: projectID, Operation: "Delete", - Version: meta.Version("ga"), - Service: "Routes", + Version: meta.Version("beta"), + Service: "SecurityPolicies", } - glog.V(5).Infof("GCERoutes.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + glog.V(5).Infof("GCEBetaSecurityPolicies.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - glog.V(4).Infof("GCERoutes.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + glog.V(4).Infof("GCEBetaSecurityPolicies.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) return err } - call := g.s.GA.Routes.Delete(projectID, key.Name) + call := g.s.Beta.SecurityPolicies.Delete(projectID, key.Name) call.Context(ctx) op, err := call.Do() if err != nil { - glog.V(4).Infof("GCERoutes.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEBetaSecurityPolicies.Delete(%v, %v) = %v", ctx, key, err) return err } err = g.s.WaitForCompletion(ctx, op) - glog.V(4).Infof("GCERoutes.Delete(%v, %v) = %v", ctx, key, err) + glog.V(4).Infof("GCEBetaSecurityPolicies.Delete(%v, %v) = %v", ctx, key, err) + return err +} + +// AddRule is a method on GCEBetaSecurityPolicies. +func (g *GCEBetaSecurityPolicies) AddRule(ctx context.Context, key *meta.Key, arg0 *beta.SecurityPolicyRule) error { + glog.V(5).Infof("GCEBetaSecurityPolicies.AddRule(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEBetaSecurityPolicies.AddRule(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "SecurityPolicies") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "AddRule", + Version: meta.Version("beta"), + Service: "SecurityPolicies", + } + glog.V(5).Infof("GCEBetaSecurityPolicies.AddRule(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEBetaSecurityPolicies.AddRule(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Beta.SecurityPolicies.AddRule(projectID, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEBetaSecurityPolicies.AddRule(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEBetaSecurityPolicies.AddRule(%v, %v, ...) = %+v", ctx, key, err) + return err +} + +// GetRule is a method on GCEBetaSecurityPolicies. +func (g *GCEBetaSecurityPolicies) GetRule(ctx context.Context, key *meta.Key) (*beta.SecurityPolicyRule, error) { + glog.V(5).Infof("GCEBetaSecurityPolicies.GetRule(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEBetaSecurityPolicies.GetRule(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return nil, fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "SecurityPolicies") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "GetRule", + Version: meta.Version("beta"), + Service: "SecurityPolicies", + } + glog.V(5).Infof("GCEBetaSecurityPolicies.GetRule(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEBetaSecurityPolicies.GetRule(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return nil, err + } + call := g.s.Beta.SecurityPolicies.GetRule(projectID, key.Name) + call.Context(ctx) + v, err := call.Do() + glog.V(4).Infof("GCEBetaSecurityPolicies.GetRule(%v, %v, ...) = %+v, %v", ctx, key, v, err) + return v, err +} + +// Patch is a method on GCEBetaSecurityPolicies. +func (g *GCEBetaSecurityPolicies) Patch(ctx context.Context, key *meta.Key, arg0 *beta.SecurityPolicy) error { + glog.V(5).Infof("GCEBetaSecurityPolicies.Patch(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEBetaSecurityPolicies.Patch(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "SecurityPolicies") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Patch", + Version: meta.Version("beta"), + Service: "SecurityPolicies", + } + glog.V(5).Infof("GCEBetaSecurityPolicies.Patch(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEBetaSecurityPolicies.Patch(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Beta.SecurityPolicies.Patch(projectID, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEBetaSecurityPolicies.Patch(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEBetaSecurityPolicies.Patch(%v, %v, ...) = %+v", ctx, key, err) + return err +} + +// PatchRule is a method on GCEBetaSecurityPolicies. +func (g *GCEBetaSecurityPolicies) PatchRule(ctx context.Context, key *meta.Key, arg0 *beta.SecurityPolicyRule) error { + glog.V(5).Infof("GCEBetaSecurityPolicies.PatchRule(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEBetaSecurityPolicies.PatchRule(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "SecurityPolicies") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "PatchRule", + Version: meta.Version("beta"), + Service: "SecurityPolicies", + } + glog.V(5).Infof("GCEBetaSecurityPolicies.PatchRule(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEBetaSecurityPolicies.PatchRule(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Beta.SecurityPolicies.PatchRule(projectID, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEBetaSecurityPolicies.PatchRule(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEBetaSecurityPolicies.PatchRule(%v, %v, ...) = %+v", ctx, key, err) + return err +} + +// RemoveRule is a method on GCEBetaSecurityPolicies. +func (g *GCEBetaSecurityPolicies) RemoveRule(ctx context.Context, key *meta.Key) error { + glog.V(5).Infof("GCEBetaSecurityPolicies.RemoveRule(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + glog.V(2).Infof("GCEBetaSecurityPolicies.RemoveRule(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "SecurityPolicies") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "RemoveRule", + Version: meta.Version("beta"), + Service: "SecurityPolicies", + } + glog.V(5).Infof("GCEBetaSecurityPolicies.RemoveRule(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + glog.V(4).Infof("GCEBetaSecurityPolicies.RemoveRule(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Beta.SecurityPolicies.RemoveRule(projectID, key.Name) + call.Context(ctx) + op, err := call.Do() + if err != nil { + glog.V(4).Infof("GCEBetaSecurityPolicies.RemoveRule(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + glog.V(4).Infof("GCEBetaSecurityPolicies.RemoveRule(%v, %v, ...) = %+v", ctx, key, err) return err } @@ -13152,3 +13943,153 @@ func (g *GCEZones) List(ctx context.Context, fl *filter.F) ([]*ga.Zone, error) { return all, nil } + +// NewAddressesResourceID creates a ResourceID for the Addresses resource. +func NewAddressesResourceID(project, region, name string) *ResourceID { + key := meta.RegionalKey(name, region) + return &ResourceID{project, "addresses", key} +} + +// NewBackendServicesResourceID creates a ResourceID for the BackendServices resource. +func NewBackendServicesResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "backendServices", key} +} + +// NewDisksResourceID creates a ResourceID for the Disks resource. +func NewDisksResourceID(project, zone, name string) *ResourceID { + key := meta.ZonalKey(name, zone) + return &ResourceID{project, "disks", key} +} + +// NewFirewallsResourceID creates a ResourceID for the Firewalls resource. +func NewFirewallsResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "firewalls", key} +} + +// NewForwardingRulesResourceID creates a ResourceID for the ForwardingRules resource. +func NewForwardingRulesResourceID(project, region, name string) *ResourceID { + key := meta.RegionalKey(name, region) + return &ResourceID{project, "forwardingRules", key} +} + +// NewGlobalAddressesResourceID creates a ResourceID for the GlobalAddresses resource. +func NewGlobalAddressesResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "addresses", key} +} + +// NewGlobalForwardingRulesResourceID creates a ResourceID for the GlobalForwardingRules resource. +func NewGlobalForwardingRulesResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "forwardingRules", key} +} + +// NewHealthChecksResourceID creates a ResourceID for the HealthChecks resource. +func NewHealthChecksResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "healthChecks", key} +} + +// NewHttpHealthChecksResourceID creates a ResourceID for the HttpHealthChecks resource. +func NewHttpHealthChecksResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "httpHealthChecks", key} +} + +// NewHttpsHealthChecksResourceID creates a ResourceID for the HttpsHealthChecks resource. +func NewHttpsHealthChecksResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "httpsHealthChecks", key} +} + +// NewInstanceGroupsResourceID creates a ResourceID for the InstanceGroups resource. +func NewInstanceGroupsResourceID(project, zone, name string) *ResourceID { + key := meta.ZonalKey(name, zone) + return &ResourceID{project, "instanceGroups", key} +} + +// NewInstancesResourceID creates a ResourceID for the Instances resource. +func NewInstancesResourceID(project, zone, name string) *ResourceID { + key := meta.ZonalKey(name, zone) + return &ResourceID{project, "instances", key} +} + +// NewNetworkEndpointGroupsResourceID creates a ResourceID for the NetworkEndpointGroups resource. +func NewNetworkEndpointGroupsResourceID(project, zone, name string) *ResourceID { + key := meta.ZonalKey(name, zone) + return &ResourceID{project, "networkEndpointGroups", key} +} + +// NewProjectsResourceID creates a ResourceID for the Projects resource. +func NewProjectsResourceID(project string) *ResourceID { + var key *meta.Key + return &ResourceID{project, "projects", key} +} + +// NewRegionBackendServicesResourceID creates a ResourceID for the RegionBackendServices resource. +func NewRegionBackendServicesResourceID(project, region, name string) *ResourceID { + key := meta.RegionalKey(name, region) + return &ResourceID{project, "backendServices", key} +} + +// NewRegionDisksResourceID creates a ResourceID for the RegionDisks resource. +func NewRegionDisksResourceID(project, region, name string) *ResourceID { + key := meta.RegionalKey(name, region) + return &ResourceID{project, "disks", key} +} + +// NewRegionsResourceID creates a ResourceID for the Regions resource. +func NewRegionsResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "regions", key} +} + +// NewRoutesResourceID creates a ResourceID for the Routes resource. +func NewRoutesResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "routes", key} +} + +// NewSecurityPoliciesResourceID creates a ResourceID for the SecurityPolicies resource. +func NewSecurityPoliciesResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "securityPolicies", key} +} + +// NewSslCertificatesResourceID creates a ResourceID for the SslCertificates resource. +func NewSslCertificatesResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "sslCertificates", key} +} + +// NewTargetHttpProxiesResourceID creates a ResourceID for the TargetHttpProxies resource. +func NewTargetHttpProxiesResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "targetHttpProxies", key} +} + +// NewTargetHttpsProxiesResourceID creates a ResourceID for the TargetHttpsProxies resource. +func NewTargetHttpsProxiesResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "targetHttpsProxies", key} +} + +// NewTargetPoolsResourceID creates a ResourceID for the TargetPools resource. +func NewTargetPoolsResourceID(project, region, name string) *ResourceID { + key := meta.RegionalKey(name, region) + return &ResourceID{project, "targetPools", key} +} + +// NewUrlMapsResourceID creates a ResourceID for the UrlMaps resource. +func NewUrlMapsResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "urlMaps", key} +} + +// NewZonesResourceID creates a ResourceID for the Zones resource. +func NewZonesResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) + return &ResourceID{project, "zones", key} +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen/main.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen/main.go index 07aa0eb30..47aeabe9d 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen/main.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen/main.go @@ -28,7 +28,6 @@ import ( "log" "os" "os/exec" - "sort" "text/template" "time" @@ -986,6 +985,38 @@ func (g *{{.GCEWrapType}}) {{.FcnArgs}} { } } +// genTypes generates the type wrappers. +func genResourceIDs(wr io.Writer) { + const text = ` +// New{{.Service}}ResourceID creates a ResourceID for the {{.Service}} resource. +{{- if .KeyIsProject}} +func New{{.Service}}ResourceID(project string) *ResourceID { + var key *meta.Key +{{- else}} +{{- if .KeyIsGlobal}} +func New{{.Service}}ResourceID(project, name string) *ResourceID { + key := meta.GlobalKey(name) +{{- end}} +{{- if .KeyIsRegional}} +func New{{.Service}}ResourceID(project, region, name string) *ResourceID { + key := meta.RegionalKey(name, region) +{{- end}} +{{- if .KeyIsZonal}} +func New{{.Service}}ResourceID(project, zone, name string) *ResourceID { + key := meta.ZonalKey(name, zone) +{{- end -}} +{{end}} + return &ResourceID{project, "{{.Resource}}", key} +} +` + tmpl := template.Must(template.New("resourceIDs").Parse(text)) + for _, sg := range meta.SortedServicesGroups { + if err := tmpl.Execute(wr, sg.ServiceInfo()); err != nil { + panic(err) + } + } +} + func genUnitTestHeader(wr io.Writer) { const text = `/* Copyright {{.Year}} The Kubernetes Authors. @@ -1238,20 +1269,86 @@ func Test{{.Service}}Group(t *testing.T) { } ` tmpl := template.Must(template.New("unittest").Parse(text)) - // Sort keys so the output will be stable. - var keys []string - for k := range meta.AllServicesByGroup { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { - s := meta.AllServicesByGroup[k] - if err := tmpl.Execute(wr, s); err != nil { + for _, sg := range meta.SortedServicesGroups { + if err := tmpl.Execute(wr, sg); err != nil { panic(err) } } } +func genUnitTestResourceIDConversion(wr io.Writer) { + const text = ` +func TestResourceIDConversion(t *testing.T) { + t.Parallel() + + for _, id := range []*ResourceID{ + {{- range .Groups}} + {{- with .ServiceInfo}} + {{- if .KeyIsProject}} + New{{.Service}}ResourceID("my-{{.Resource}}-resource"), + {{- else}} + {{- if .KeyIsGlobal}} + New{{.Service}}ResourceID("some-project", "my-{{.Resource}}-resource"), + {{- end}} + {{- if .KeyIsRegional}} + New{{.Service}}ResourceID("some-project", "us-central1", "my-{{.Resource}}-resource"), + {{- end}} + {{- if .KeyIsZonal}} + New{{.Service}}ResourceID("some-project", "us-east1-b", "my-{{.Resource}}-resource"), + {{- end -}} + {{end -}} + {{end -}} + {{end}} + } { + t.Run(id.Resource, func(t *testing.T) { + // Test conversion to and from full URL. + fullURL := id.SelfLink(meta.VersionGA) + parsedID, err := ParseResourceURL(fullURL) + if err != nil { + t.Errorf("ParseResourceURL(%s) = _, %v, want nil", fullURL, err) + } + if !reflect.DeepEqual(id, parsedID) { + t.Errorf("SelfLink(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, fullURL, parsedID) + } + + // Test conversion to and from relative resource name. + relativeName := id.RelativeResourceName() + parsedID, err = ParseResourceURL(relativeName) + if err != nil { + t.Errorf("ParseResourceURL(%s) = _, %v, want nil", relativeName, err) + } + if !reflect.DeepEqual(id, parsedID) { + t.Errorf("RelativeResourceName(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, relativeName, parsedID) + } + + // Do not test ResourcePath for projects. + if id.Resource == "projects" { + return + } + + // Test conversion to and from resource path. + resourcePath := id.ResourcePath() + parsedID, err = ParseResourceURL(resourcePath) + if err != nil { + t.Errorf("ParseResourceURL(%s) = _, %v, want nil", resourcePath, err) + } + id.ProjectID = "" + if !reflect.DeepEqual(id, parsedID) { + t.Errorf("ResourcePath(%+v) -> ParseResourceURL(%s) = %+v, want %+v", id, resourcePath, parsedID, id) + } + }) + } +} +` + data := struct { + Groups []*meta.ServiceGroup + }{meta.SortedServicesGroups} + tmpl := template.Must(template.New("unittest-resourceIDs").Parse(text)) + if err := tmpl.Execute(wr, data); err != nil { + panic(err) + } +} + func main() { flag.Parse() @@ -1262,9 +1359,11 @@ func main() { genHeader(out) genStubs(out) genTypes(out) + genResourceIDs(out) case "test": genUnitTestHeader(out) genUnitTestServices(out) + genUnitTestResourceIDConversion(out) default: log.Fatalf("Invalid -mode: %q", flags.mode) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen_test.go index 10d6f2aee..bbdeaff70 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen_test.go @@ -179,6 +179,8 @@ func TestBackendServicesGroup(t *testing.T) { var key *meta.Key keyAlpha := meta.GlobalKey("key-alpha") key = keyAlpha + keyBeta := meta.GlobalKey("key-beta") + key = keyBeta keyGA := meta.GlobalKey("key-ga") key = keyGA // Ignore unused variables. @@ -188,6 +190,9 @@ func TestBackendServicesGroup(t *testing.T) { if _, err := mock.AlphaBackendServices().Get(ctx, key); err == nil { t.Errorf("AlphaBackendServices().Get(%v, %v) = _, nil; want error", ctx, key) } + if _, err := mock.BetaBackendServices().Get(ctx, key); err == nil { + t.Errorf("BetaBackendServices().Get(%v, %v) = _, nil; want error", ctx, key) + } if _, err := mock.BackendServices().Get(ctx, key); err == nil { t.Errorf("BackendServices().Get(%v, %v) = _, nil; want error", ctx, key) } @@ -199,6 +204,12 @@ func TestBackendServicesGroup(t *testing.T) { t.Errorf("AlphaBackendServices().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) } } + { + obj := &beta.BackendService{} + if err := mock.BetaBackendServices().Insert(ctx, keyBeta, obj); err != nil { + t.Errorf("BetaBackendServices().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) + } + } { obj := &ga.BackendService{} if err := mock.BackendServices().Insert(ctx, keyGA, obj); err != nil { @@ -210,15 +221,20 @@ func TestBackendServicesGroup(t *testing.T) { if obj, err := mock.AlphaBackendServices().Get(ctx, key); err != nil { t.Errorf("AlphaBackendServices().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) } + if obj, err := mock.BetaBackendServices().Get(ctx, key); err != nil { + t.Errorf("BetaBackendServices().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) + } if obj, err := mock.BackendServices().Get(ctx, key); err != nil { t.Errorf("BackendServices().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) } // List. mock.MockAlphaBackendServices.Objects[*keyAlpha] = mock.MockAlphaBackendServices.Obj(&alpha.BackendService{Name: keyAlpha.Name}) + mock.MockBetaBackendServices.Objects[*keyBeta] = mock.MockBetaBackendServices.Obj(&beta.BackendService{Name: keyBeta.Name}) mock.MockBackendServices.Objects[*keyGA] = mock.MockBackendServices.Obj(&ga.BackendService{Name: keyGA.Name}) want := map[string]bool{ "key-alpha": true, + "key-beta": true, "key-ga": true, } _ = want // ignore unused variables. @@ -236,6 +252,20 @@ func TestBackendServicesGroup(t *testing.T) { } } } + { + objs, err := mock.BetaBackendServices().List(ctx, filter.None) + if err != nil { + t.Errorf("BetaBackendServices().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) + } else { + got := map[string]bool{} + for _, obj := range objs { + got[obj.Name] = true + } + if !reflect.DeepEqual(got, want) { + t.Errorf("AlphaBackendServices().List(); got %+v, want %+v", got, want) + } + } + } { objs, err := mock.BackendServices().List(ctx, filter.None) if err != nil { @@ -255,6 +285,9 @@ func TestBackendServicesGroup(t *testing.T) { if err := mock.AlphaBackendServices().Delete(ctx, keyAlpha); err != nil { t.Errorf("AlphaBackendServices().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) } + if err := mock.BetaBackendServices().Delete(ctx, keyBeta); err != nil { + t.Errorf("BetaBackendServices().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) + } if err := mock.BackendServices().Delete(ctx, keyGA); err != nil { t.Errorf("BackendServices().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) } @@ -263,6 +296,9 @@ func TestBackendServicesGroup(t *testing.T) { if err := mock.AlphaBackendServices().Delete(ctx, keyAlpha); err == nil { t.Errorf("AlphaBackendServices().Delete(%v, %v) = nil; want error", ctx, keyAlpha) } + if err := mock.BetaBackendServices().Delete(ctx, keyBeta); err == nil { + t.Errorf("BetaBackendServices().Delete(%v, %v) = nil; want error", ctx, keyBeta) + } if err := mock.BackendServices().Delete(ctx, keyGA); err == nil { t.Errorf("BackendServices().Delete(%v, %v) = nil; want error", ctx, keyGA) } @@ -276,28 +312,17 @@ func TestDisksGroup(t *testing.T) { mock := NewMockGCE(pr) var key *meta.Key - keyAlpha := meta.ZonalKey("key-alpha", "location") - key = keyAlpha keyGA := meta.ZonalKey("key-ga", "location") key = keyGA // Ignore unused variables. _, _, _ = ctx, mock, key // Get not found. - if _, err := mock.AlphaDisks().Get(ctx, key); err == nil { - t.Errorf("AlphaDisks().Get(%v, %v) = _, nil; want error", ctx, key) - } if _, err := mock.Disks().Get(ctx, key); err == nil { t.Errorf("Disks().Get(%v, %v) = _, nil; want error", ctx, key) } // Insert. - { - obj := &alpha.Disk{} - if err := mock.AlphaDisks().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaDisks().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } { obj := &ga.Disk{} if err := mock.Disks().Insert(ctx, keyGA, obj); err != nil { @@ -306,35 +331,16 @@ func TestDisksGroup(t *testing.T) { } // Get across versions. - if obj, err := mock.AlphaDisks().Get(ctx, key); err != nil { - t.Errorf("AlphaDisks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } if obj, err := mock.Disks().Get(ctx, key); err != nil { t.Errorf("Disks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) } // List. - mock.MockAlphaDisks.Objects[*keyAlpha] = mock.MockAlphaDisks.Obj(&alpha.Disk{Name: keyAlpha.Name}) mock.MockDisks.Objects[*keyGA] = mock.MockDisks.Obj(&ga.Disk{Name: keyGA.Name}) want := map[string]bool{ - "key-alpha": true, - "key-ga": true, + "key-ga": true, } _ = want // ignore unused variables. - { - objs, err := mock.AlphaDisks().List(ctx, location, filter.None) - if err != nil { - t.Errorf("AlphaDisks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaDisks().List(); got %+v, want %+v", got, want) - } - } - } { objs, err := mock.Disks().List(ctx, location, filter.None) if err != nil { @@ -351,17 +357,11 @@ func TestDisksGroup(t *testing.T) { } // Delete across versions. - if err := mock.AlphaDisks().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaDisks().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } if err := mock.Disks().Delete(ctx, keyGA); err != nil { t.Errorf("Disks().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) } // Delete not found. - if err := mock.AlphaDisks().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaDisks().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } if err := mock.Disks().Delete(ctx, keyGA); err == nil { t.Errorf("Disks().Delete(%v, %v) = nil; want error", ctx, keyGA) } @@ -1279,39 +1279,39 @@ func TestRegionDisksGroup(t *testing.T) { mock := NewMockGCE(pr) var key *meta.Key - keyAlpha := meta.RegionalKey("key-alpha", "location") - key = keyAlpha + keyBeta := meta.RegionalKey("key-beta", "location") + key = keyBeta // Ignore unused variables. _, _, _ = ctx, mock, key // Get not found. - if _, err := mock.AlphaRegionDisks().Get(ctx, key); err == nil { - t.Errorf("AlphaRegionDisks().Get(%v, %v) = _, nil; want error", ctx, key) + if _, err := mock.BetaRegionDisks().Get(ctx, key); err == nil { + t.Errorf("BetaRegionDisks().Get(%v, %v) = _, nil; want error", ctx, key) } // Insert. { - obj := &alpha.Disk{} - if err := mock.AlphaRegionDisks().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaRegionDisks().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) + obj := &beta.Disk{} + if err := mock.BetaRegionDisks().Insert(ctx, keyBeta, obj); err != nil { + t.Errorf("BetaRegionDisks().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) } } // Get across versions. - if obj, err := mock.AlphaRegionDisks().Get(ctx, key); err != nil { - t.Errorf("AlphaRegionDisks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) + if obj, err := mock.BetaRegionDisks().Get(ctx, key); err != nil { + t.Errorf("BetaRegionDisks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) } // List. - mock.MockAlphaRegionDisks.Objects[*keyAlpha] = mock.MockAlphaRegionDisks.Obj(&alpha.Disk{Name: keyAlpha.Name}) + mock.MockBetaRegionDisks.Objects[*keyBeta] = mock.MockBetaRegionDisks.Obj(&beta.Disk{Name: keyBeta.Name}) want := map[string]bool{ - "key-alpha": true, + "key-beta": true, } _ = want // ignore unused variables. { - objs, err := mock.AlphaRegionDisks().List(ctx, location, filter.None) + objs, err := mock.BetaRegionDisks().List(ctx, location, filter.None) if err != nil { - t.Errorf("AlphaRegionDisks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) + t.Errorf("BetaRegionDisks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) } else { got := map[string]bool{} for _, obj := range objs { @@ -1324,13 +1324,13 @@ func TestRegionDisksGroup(t *testing.T) { } // Delete across versions. - if err := mock.AlphaRegionDisks().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaRegionDisks().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) + if err := mock.BetaRegionDisks().Delete(ctx, keyBeta); err != nil { + t.Errorf("BetaRegionDisks().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) } // Delete not found. - if err := mock.AlphaRegionDisks().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaRegionDisks().Delete(%v, %v) = nil; want error", ctx, keyAlpha) + if err := mock.BetaRegionDisks().Delete(ctx, keyBeta); err == nil { + t.Errorf("BetaRegionDisks().Delete(%v, %v) = nil; want error", ctx, keyBeta) } } @@ -1445,6 +1445,69 @@ func TestRoutesGroup(t *testing.T) { } } +func TestSecurityPoliciesGroup(t *testing.T) { + t.Parallel() + + ctx := context.Background() + pr := &SingleProjectRouter{"mock-project"} + mock := NewMockGCE(pr) + + var key *meta.Key + keyBeta := meta.GlobalKey("key-beta") + key = keyBeta + // Ignore unused variables. + _, _, _ = ctx, mock, key + + // Get not found. + if _, err := mock.BetaSecurityPolicies().Get(ctx, key); err == nil { + t.Errorf("BetaSecurityPolicies().Get(%v, %v) = _, nil; want error", ctx, key) + } + + // Insert. + { + obj := &beta.SecurityPolicy{} + if err := mock.BetaSecurityPolicies().Insert(ctx, keyBeta, obj); err != nil { + t.Errorf("BetaSecurityPolicies().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) + } + } + + // Get across versions. + if obj, err := mock.BetaSecurityPolicies().Get(ctx, key); err != nil { + t.Errorf("BetaSecurityPolicies().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) + } + + // List. + mock.MockBetaSecurityPolicies.Objects[*keyBeta] = mock.MockBetaSecurityPolicies.Obj(&beta.SecurityPolicy{Name: keyBeta.Name}) + want := map[string]bool{ + "key-beta": true, + } + _ = want // ignore unused variables. + { + objs, err := mock.BetaSecurityPolicies().List(ctx, filter.None) + if err != nil { + t.Errorf("BetaSecurityPolicies().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) + } else { + got := map[string]bool{} + for _, obj := range objs { + got[obj.Name] = true + } + if !reflect.DeepEqual(got, want) { + t.Errorf("AlphaSecurityPolicies().List(); got %+v, want %+v", got, want) + } + } + } + + // Delete across versions. + if err := mock.BetaSecurityPolicies().Delete(ctx, keyBeta); err != nil { + t.Errorf("BetaSecurityPolicies().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) + } + + // Delete not found. + if err := mock.BetaSecurityPolicies().Delete(ctx, keyBeta); err == nil { + t.Errorf("BetaSecurityPolicies().Delete(%v, %v) = nil; want error", ctx, keyBeta) + } +} + func TestSslCertificatesGroup(t *testing.T) { t.Parallel() @@ -1807,3 +1870,73 @@ func TestZonesGroup(t *testing.T) { // Delete not found. } + +func TestResourceIDConversion(t *testing.T) { + t.Parallel() + + for _, id := range []*ResourceID{ + NewAddressesResourceID("some-project", "us-central1", "my-addresses-resource"), + NewBackendServicesResourceID("some-project", "my-backendServices-resource"), + NewDisksResourceID("some-project", "us-east1-b", "my-disks-resource"), + NewFirewallsResourceID("some-project", "my-firewalls-resource"), + NewForwardingRulesResourceID("some-project", "us-central1", "my-forwardingRules-resource"), + NewGlobalAddressesResourceID("some-project", "my-addresses-resource"), + NewGlobalForwardingRulesResourceID("some-project", "my-forwardingRules-resource"), + NewHealthChecksResourceID("some-project", "my-healthChecks-resource"), + NewHttpHealthChecksResourceID("some-project", "my-httpHealthChecks-resource"), + NewHttpsHealthChecksResourceID("some-project", "my-httpsHealthChecks-resource"), + NewInstanceGroupsResourceID("some-project", "us-east1-b", "my-instanceGroups-resource"), + NewInstancesResourceID("some-project", "us-east1-b", "my-instances-resource"), + NewNetworkEndpointGroupsResourceID("some-project", "us-east1-b", "my-networkEndpointGroups-resource"), + NewProjectsResourceID("my-projects-resource"), + NewRegionBackendServicesResourceID("some-project", "us-central1", "my-backendServices-resource"), + NewRegionDisksResourceID("some-project", "us-central1", "my-disks-resource"), + NewRegionsResourceID("some-project", "my-regions-resource"), + NewRoutesResourceID("some-project", "my-routes-resource"), + NewSecurityPoliciesResourceID("some-project", "my-securityPolicies-resource"), + NewSslCertificatesResourceID("some-project", "my-sslCertificates-resource"), + NewTargetHttpProxiesResourceID("some-project", "my-targetHttpProxies-resource"), + NewTargetHttpsProxiesResourceID("some-project", "my-targetHttpsProxies-resource"), + NewTargetPoolsResourceID("some-project", "us-central1", "my-targetPools-resource"), + NewUrlMapsResourceID("some-project", "my-urlMaps-resource"), + NewZonesResourceID("some-project", "my-zones-resource"), + } { + t.Run(id.Resource, func(t *testing.T) { + // Test conversion to and from full URL. + fullURL := id.SelfLink(meta.VersionGA) + parsedID, err := ParseResourceURL(fullURL) + if err != nil { + t.Errorf("ParseResourceURL(%s) = _, %v, want nil", fullURL, err) + } + if !reflect.DeepEqual(id, parsedID) { + t.Errorf("SelfLink(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, fullURL, parsedID) + } + + // Test conversion to and from relative resource name. + relativeName := id.RelativeResourceName() + parsedID, err = ParseResourceURL(relativeName) + if err != nil { + t.Errorf("ParseResourceURL(%s) = _, %v, want nil", relativeName, err) + } + if !reflect.DeepEqual(id, parsedID) { + t.Errorf("RelativeResourceName(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, relativeName, parsedID) + } + + // Do not test ResourcePath for projects. + if id.Resource == "projects" { + return + } + + // Test conversion to and from resource path. + resourcePath := id.ResourcePath() + parsedID, err = ParseResourceURL(resourcePath) + if err != nil { + t.Errorf("ParseResourceURL(%s) = _, %v, want nil", resourcePath, err) + } + id.ProjectID = "" + if !reflect.DeepEqual(id, parsedID) { + t.Errorf("ResourcePath(%+v) -> ParseResourceURL(%s) = %+v, want %+v", id, resourcePath, parsedID, id) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/meta.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/meta.go index 852248beb..e9ff33d43 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/meta.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/meta.go @@ -103,17 +103,32 @@ var AllServices = []*ServiceInfo{ serviceType: reflect.TypeOf(&ga.BackendServicesService{}), additionalMethods: []string{ "GetHealth", + "Patch", "Update", }, }, { - Object: "BackendService", - Service: "BackendServices", - Resource: "backendServices", - version: VersionAlpha, - keyType: Global, - serviceType: reflect.TypeOf(&alpha.BackendServicesService{}), - additionalMethods: []string{"Update"}, + Object: "BackendService", + Service: "BackendServices", + Resource: "backendServices", + version: VersionBeta, + keyType: Global, + serviceType: reflect.TypeOf(&beta.BackendServicesService{}), + additionalMethods: []string{ + "SetSecurityPolicy", + }, + }, + { + Object: "BackendService", + Service: "BackendServices", + Resource: "backendServices", + version: VersionAlpha, + keyType: Global, + serviceType: reflect.TypeOf(&alpha.BackendServicesService{}), + additionalMethods: []string{ + "Update", + "SetSecurityPolicy", + }, }, { Object: "BackendService", @@ -145,22 +160,20 @@ var AllServices = []*ServiceInfo{ Resource: "disks", keyType: Zonal, serviceType: reflect.TypeOf(&ga.DisksService{}), - }, - { - Object: "Disk", - Service: "Disks", - Resource: "disks", - version: VersionAlpha, - keyType: Zonal, - serviceType: reflect.TypeOf(&alpha.DisksService{}), + additionalMethods: []string{ + "Resize", + }, }, { Object: "Disk", Service: "RegionDisks", Resource: "disks", - version: VersionAlpha, + version: VersionBeta, keyType: Regional, - serviceType: reflect.TypeOf(&alpha.DisksService{}), + serviceType: reflect.TypeOf(&beta.RegionDisksService{}), + additionalMethods: []string{ + "Resize", + }, }, { Object: "Firewall", @@ -326,6 +339,21 @@ var AllServices = []*ServiceInfo{ keyType: Global, serviceType: reflect.TypeOf(&ga.RoutesService{}), }, + { + Object: "SecurityPolicy", + Service: "SecurityPolicies", + Resource: "securityPolicies", + version: VersionBeta, + keyType: Global, + serviceType: reflect.TypeOf(&beta.SecurityPoliciesService{}), + additionalMethods: []string{ + "AddRule", + "GetRule", + "Patch", + "PatchRule", + "RemoveRule", + }, + }, { Object: "SslCertificate", Service: "SslCertificates", diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/service.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/service.go index b2ba91c8e..c18de2a59 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/service.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/service.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "reflect" + "sort" ) // ServiceInfo defines the entry for a Service that code will be generated for. @@ -159,6 +160,13 @@ func (i *ServiceInfo) KeyIsZonal() bool { return i.keyType == Zonal } +// KeyIsProject is true if the key represents the project resource. +func (i *ServiceInfo) KeyIsProject() bool { + // Projects are a special resource for ResourceId because there is no 'key' value. This func + // is used by the generator to not accept a key parameter. + return i.Service == "Projects" +} + // MakeKey returns the call used to create the appropriate key type. func (i *ServiceInfo) MakeKey(name, location string) string { switch i.keyType { @@ -220,15 +228,20 @@ type ServiceGroup struct { GA *ServiceInfo } -// Service returns any ServiceInfo object belonging to the ServiceGroup. +// Service returns any ServiceInfo string belonging to the ServiceGroup. func (sg *ServiceGroup) Service() string { + return sg.ServiceInfo().Service +} + +// ServiceInfo returns any ServiceInfo object belonging to the ServiceGroup. +func (sg *ServiceGroup) ServiceInfo() *ServiceInfo { switch { case sg.GA != nil: - return sg.GA.Service + return sg.GA case sg.Alpha != nil: - return sg.Alpha.Service + return sg.Alpha case sg.Beta != nil: - return sg.Beta.Service + return sg.Beta default: panic(errors.New("service group is empty")) } @@ -272,6 +285,16 @@ func groupServices(services []*ServiceInfo) map[string]*ServiceGroup { // AllServicesByGroup is a map of service name to ServicesGroup. var AllServicesByGroup map[string]*ServiceGroup +// SortedServicesGroups is a slice of Servicegroup sorted by Service name. +var SortedServicesGroups []*ServiceGroup + func init() { AllServicesByGroup = groupServices(AllServices) + + for _, sg := range AllServicesByGroup { + SortedServicesGroups = append(SortedServicesGroups, sg) + } + sort.Slice(SortedServicesGroups, func(i, j int) bool { + return SortedServicesGroups[i].Service() < SortedServicesGroups[j].Service() + }) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/BUILD b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/BUILD index bceb2e847..e6e359278 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/BUILD @@ -7,6 +7,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/cloudprovider/providers/gce/cloud:go_default_library", + "//pkg/cloudprovider/providers/gce/cloud/filter:go_default_library", "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", "//vendor/google.golang.org/api/compute/v0.alpha:go_default_library", "//vendor/google.golang.org/api/compute/v0.beta:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/mock.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/mock.go index 06ff480d4..6a28c9f8e 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/mock.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/mock.go @@ -28,15 +28,24 @@ import ( "encoding/json" "fmt" "net/http" + "sync" alpha "google.golang.org/api/compute/v0.alpha" beta "google.golang.org/api/compute/v0.beta" ga "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + cloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) +var ( + // InUseError is a shared variable with error code StatusBadRequest for error verification. + InUseError = &googleapi.Error{Code: http.StatusBadRequest, Message: "It's being used by god."} + // InternalServerError is shared variable with error code StatusInternalServerError for error verification. + InternalServerError = &googleapi.Error{Code: http.StatusInternalServerError} +) + // gceObject is an abstraction of all GCE API object in go client type gceObject interface { MarshalJSON() ([]byte, error) @@ -85,7 +94,7 @@ func RemoveInstanceHook(ctx context.Context, key *meta.Key, req *ga.TargetPoolsR func convertAndInsertAlphaForwardingRule(key *meta.Key, obj gceObject, mRules map[meta.Key]*cloud.MockForwardingRulesObj, version meta.Version, projectID string) (bool, error) { if !key.Valid() { - return false, fmt.Errorf("invalid GCE key (%+v)", key) + return true, fmt.Errorf("invalid GCE key (%+v)", key) } if _, ok := mRules[*key]; ok { @@ -93,16 +102,16 @@ func convertAndInsertAlphaForwardingRule(key *meta.Key, obj gceObject, mRules ma Code: http.StatusConflict, Message: fmt.Sprintf("MockForwardingRule %v exists", key), } - return false, err + return true, err } enc, err := obj.MarshalJSON() if err != nil { - return false, err + return true, err } var fwdRule alpha.ForwardingRule if err := json.Unmarshal(enc, &fwdRule); err != nil { - return false, err + return true, err } // Set the default values for the Alpha fields. if fwdRule.NetworkTier == "" { @@ -121,28 +130,39 @@ func convertAndInsertAlphaForwardingRule(key *meta.Key, obj gceObject, mRules ma // InsertFwdRuleHook mocks inserting a ForwardingRule. ForwardingRules are // expected to default to Premium tier if no NetworkTier is specified. func InsertFwdRuleHook(ctx context.Context, key *meta.Key, obj *ga.ForwardingRule, m *cloud.MockForwardingRules) (bool, error) { + m.Lock.Lock() + defer m.Lock.Unlock() + projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionGA, "forwardingRules") return convertAndInsertAlphaForwardingRule(key, obj, m.Objects, meta.VersionGA, projectID) } // InsertBetaFwdRuleHook mocks inserting a BetaForwardingRule. func InsertBetaFwdRuleHook(ctx context.Context, key *meta.Key, obj *beta.ForwardingRule, m *cloud.MockForwardingRules) (bool, error) { + m.Lock.Lock() + defer m.Lock.Unlock() + projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionBeta, "forwardingRules") return convertAndInsertAlphaForwardingRule(key, obj, m.Objects, meta.VersionBeta, projectID) } // InsertAlphaFwdRuleHook mocks inserting an AlphaForwardingRule. func InsertAlphaFwdRuleHook(ctx context.Context, key *meta.Key, obj *alpha.ForwardingRule, m *cloud.MockForwardingRules) (bool, error) { + m.Lock.Lock() + defer m.Lock.Unlock() + projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionAlpha, "forwardingRules") return convertAndInsertAlphaForwardingRule(key, obj, m.Objects, meta.VersionAlpha, projectID) } -// Used to assign Addresses with no IP a unique IP address -var ipCounter = 1 +// AddressAttributes maps from Address key to a map of Instances +type AddressAttributes struct { + IPCounter int // Used to assign Addresses with no IP a unique IP address +} -func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta.Key]*cloud.MockAddressesObj, version meta.Version, projectID string) (bool, error) { +func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta.Key]*cloud.MockAddressesObj, version meta.Version, projectID string, addressAttrs AddressAttributes) (bool, error) { if !key.Valid() { - return false, fmt.Errorf("invalid GCE key (%+v)", key) + return true, fmt.Errorf("invalid GCE key (%+v)", key) } if _, ok := mAddrs[*key]; ok { @@ -150,16 +170,16 @@ func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta. Code: http.StatusConflict, Message: fmt.Sprintf("MockAddresses %v exists", key), } - return false, err + return true, err } enc, err := obj.MarshalJSON() if err != nil { - return false, err + return true, err } var addr alpha.Address if err := json.Unmarshal(enc, &addr); err != nil { - return false, err + return true, err } // Set default address type if not present. @@ -184,7 +204,7 @@ func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta. errorCode = http.StatusBadRequest } - return false, &googleapi.Error{Code: errorCode, Message: msg} + return true, &googleapi.Error{Code: errorCode, Message: msg} } } @@ -195,8 +215,8 @@ func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta. } if addr.Address == "" { - addr.Address = fmt.Sprintf("1.2.3.%d", ipCounter) - ipCounter++ + addr.Address = fmt.Sprintf("1.2.3.%d", addressAttrs.IPCounter) + addressAttrs.IPCounter++ } // Set the default values for the Alpha fields. @@ -210,19 +230,323 @@ func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta. // InsertAddressHook mocks inserting an Address. func InsertAddressHook(ctx context.Context, key *meta.Key, obj *ga.Address, m *cloud.MockAddresses) (bool, error) { + m.Lock.Lock() + defer m.Lock.Unlock() + projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionGA, "addresses") - return convertAndInsertAlphaAddress(key, obj, m.Objects, meta.VersionGA, projectID) + return convertAndInsertAlphaAddress(key, obj, m.Objects, meta.VersionGA, projectID, m.X.(AddressAttributes)) } // InsertBetaAddressHook mocks inserting a BetaAddress. func InsertBetaAddressHook(ctx context.Context, key *meta.Key, obj *beta.Address, m *cloud.MockAddresses) (bool, error) { + m.Lock.Lock() + defer m.Lock.Unlock() + projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionBeta, "addresses") - return convertAndInsertAlphaAddress(key, obj, m.Objects, meta.VersionBeta, projectID) + return convertAndInsertAlphaAddress(key, obj, m.Objects, meta.VersionBeta, projectID, m.X.(AddressAttributes)) } // InsertAlphaAddressHook mocks inserting an Address. Addresses are expected to // default to Premium tier if no NetworkTier is specified. func InsertAlphaAddressHook(ctx context.Context, key *meta.Key, obj *alpha.Address, m *cloud.MockAlphaAddresses) (bool, error) { + m.Lock.Lock() + defer m.Lock.Unlock() + projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionBeta, "addresses") - return convertAndInsertAlphaAddress(key, obj, m.Objects, meta.VersionAlpha, projectID) + return convertAndInsertAlphaAddress(key, obj, m.Objects, meta.VersionAlpha, projectID, m.X.(AddressAttributes)) +} + +// InstanceGroupAttributes maps from InstanceGroup key to a map of Instances +type InstanceGroupAttributes struct { + InstanceMap map[meta.Key]map[string]*ga.InstanceWithNamedPorts + Lock *sync.Mutex +} + +// AddInstances adds a list of Instances passed by InstanceReference +func (igAttrs *InstanceGroupAttributes) AddInstances(key *meta.Key, instanceRefs []*ga.InstanceReference) error { + igAttrs.Lock.Lock() + defer igAttrs.Lock.Unlock() + + instancesWithNamedPorts, ok := igAttrs.InstanceMap[*key] + if !ok { + instancesWithNamedPorts = make(map[string]*ga.InstanceWithNamedPorts) + } + + for _, instance := range instanceRefs { + iWithPort := &ga.InstanceWithNamedPorts{ + Instance: instance.Instance, + } + + instancesWithNamedPorts[instance.Instance] = iWithPort + } + + igAttrs.InstanceMap[*key] = instancesWithNamedPorts + return nil +} + +// RemoveInstances removes a list of Instances passed by InstanceReference +func (igAttrs *InstanceGroupAttributes) RemoveInstances(key *meta.Key, instanceRefs []*ga.InstanceReference) error { + igAttrs.Lock.Lock() + defer igAttrs.Lock.Unlock() + + instancesWithNamedPorts, ok := igAttrs.InstanceMap[*key] + if !ok { + instancesWithNamedPorts = make(map[string]*ga.InstanceWithNamedPorts) + } + + for _, instanceToRemove := range instanceRefs { + if _, ok := instancesWithNamedPorts[instanceToRemove.Instance]; ok { + delete(instancesWithNamedPorts, instanceToRemove.Instance) + } else { + return &googleapi.Error{ + Code: http.StatusBadRequest, + Message: fmt.Sprintf("%s is not a member of %s", instanceToRemove.Instance, key.String()), + } + } + } + + igAttrs.InstanceMap[*key] = instancesWithNamedPorts + return nil +} + +// List gets a list of InstanceWithNamedPorts +func (igAttrs *InstanceGroupAttributes) List(key *meta.Key) []*ga.InstanceWithNamedPorts { + igAttrs.Lock.Lock() + defer igAttrs.Lock.Unlock() + + instancesWithNamedPorts, ok := igAttrs.InstanceMap[*key] + if !ok { + instancesWithNamedPorts = make(map[string]*ga.InstanceWithNamedPorts) + } + + var instanceList []*ga.InstanceWithNamedPorts + for _, val := range instancesWithNamedPorts { + instanceList = append(instanceList, val) + } + + return instanceList +} + +// AddInstancesHook mocks adding instances from an InstanceGroup +func AddInstancesHook(ctx context.Context, key *meta.Key, req *ga.InstanceGroupsAddInstancesRequest, m *cloud.MockInstanceGroups) error { + _, err := m.Get(ctx, key) + if err != nil { + return &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("Key: %s was not found in InstanceGroups", key.String()), + } + } + + var attrs InstanceGroupAttributes + attrs = m.X.(InstanceGroupAttributes) + attrs.AddInstances(key, req.Instances) + m.X = attrs + return nil +} + +// ListInstancesHook mocks listing instances from an InstanceGroup +func ListInstancesHook(ctx context.Context, key *meta.Key, req *ga.InstanceGroupsListInstancesRequest, filter *filter.F, m *cloud.MockInstanceGroups) ([]*ga.InstanceWithNamedPorts, error) { + _, err := m.Get(ctx, key) + if err != nil { + return nil, &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("Key: %s was not found in InstanceGroups", key.String()), + } + } + + var attrs InstanceGroupAttributes + attrs = m.X.(InstanceGroupAttributes) + instances := attrs.List(key) + + return instances, nil +} + +// RemoveInstancesHook mocks removing instances from an InstanceGroup +func RemoveInstancesHook(ctx context.Context, key *meta.Key, req *ga.InstanceGroupsRemoveInstancesRequest, m *cloud.MockInstanceGroups) error { + _, err := m.Get(ctx, key) + if err != nil { + return &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("Key: %s was not found in InstanceGroups", key.String()), + } + } + + var attrs InstanceGroupAttributes + attrs = m.X.(InstanceGroupAttributes) + attrs.RemoveInstances(key, req.Instances) + m.X = attrs + return nil +} + +// UpdateFirewallHook defines the hook for updating a Firewall. It replaces the +// object with the same key in the mock with the updated object. +func UpdateFirewallHook(ctx context.Context, key *meta.Key, obj *ga.Firewall, m *cloud.MockFirewalls) error { + _, err := m.Get(ctx, key) + if err != nil { + return &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("Key: %s was not found in Firewalls", key.String()), + } + } + + obj.Name = key.Name + projectID := m.ProjectRouter.ProjectID(ctx, "ga", "firewalls") + obj.SelfLink = cloud.SelfLink(meta.VersionGA, projectID, "firewalls", key) + + m.Objects[*key] = &cloud.MockFirewallsObj{Obj: obj} + return nil +} + +// UpdateHealthCheckHook defines the hook for updating a HealthCheck. It +// replaces the object with the same key in the mock with the updated object. +func UpdateHealthCheckHook(ctx context.Context, key *meta.Key, obj *ga.HealthCheck, m *cloud.MockHealthChecks) error { + _, err := m.Get(ctx, key) + if err != nil { + return &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("Key: %s was not found in HealthChecks", key.String()), + } + } + + obj.Name = key.Name + projectID := m.ProjectRouter.ProjectID(ctx, "ga", "healthChecks") + obj.SelfLink = cloud.SelfLink(meta.VersionGA, projectID, "healthChecks", key) + + m.Objects[*key] = &cloud.MockHealthChecksObj{Obj: obj} + return nil +} + +// UpdateRegionBackendServiceHook defines the hook for updating a Region +// BackendsService. It replaces the object with the same key in the mock with +// the updated object. +func UpdateRegionBackendServiceHook(ctx context.Context, key *meta.Key, obj *ga.BackendService, m *cloud.MockRegionBackendServices) error { + _, err := m.Get(ctx, key) + if err != nil { + return &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("Key: %s was not found in RegionBackendServices", key.String()), + } + } + + obj.Name = key.Name + projectID := m.ProjectRouter.ProjectID(ctx, "ga", "backendServices") + obj.SelfLink = cloud.SelfLink(meta.VersionGA, projectID, "backendServices", key) + + m.Objects[*key] = &cloud.MockRegionBackendServicesObj{Obj: obj} + return nil +} + +// InsertFirewallsUnauthorizedErrHook mocks firewall insertion. A forbidden error will be thrown as return. +func InsertFirewallsUnauthorizedErrHook(ctx context.Context, key *meta.Key, obj *ga.Firewall, m *cloud.MockFirewalls) (bool, error) { + return true, &googleapi.Error{Code: http.StatusForbidden} +} + +// UpdateFirewallsUnauthorizedErrHook mocks firewall updating. A forbidden error will be thrown as return. +func UpdateFirewallsUnauthorizedErrHook(ctx context.Context, key *meta.Key, obj *ga.Firewall, m *cloud.MockFirewalls) error { + return &googleapi.Error{Code: http.StatusForbidden} +} + +// DeleteFirewallsUnauthorizedErrHook mocks firewall deletion. A forbidden error will be thrown as return. +func DeleteFirewallsUnauthorizedErrHook(ctx context.Context, key *meta.Key, m *cloud.MockFirewalls) (bool, error) { + return true, &googleapi.Error{Code: http.StatusForbidden} +} + +// GetFirewallsUnauthorizedErrHook mocks firewall information retrival. A forbidden error will be thrown as return. +func GetFirewallsUnauthorizedErrHook(ctx context.Context, key *meta.Key, m *cloud.MockFirewalls) (bool, *ga.Firewall, error) { + return true, nil, &googleapi.Error{Code: http.StatusForbidden} +} + +// GetTargetPoolInternalErrHook mocks getting target pool. It returns a internal server error. +func GetTargetPoolInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockTargetPools) (bool, *ga.TargetPool, error) { + return true, nil, InternalServerError +} + +// GetForwardingRulesInternalErrHook mocks getting forwarding rules and returns an internal server error. +func GetForwardingRulesInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockForwardingRules) (bool, *ga.ForwardingRule, error) { + return true, nil, InternalServerError +} + +// GetAddressesInternalErrHook mocks getting network address and returns an internal server error. +func GetAddressesInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockAddresses) (bool, *ga.Address, error) { + return true, nil, InternalServerError +} + +// GetHTTPHealthChecksInternalErrHook mocks getting http health check and returns an internal server error. +func GetHTTPHealthChecksInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockHttpHealthChecks) (bool, *ga.HttpHealthCheck, error) { + return true, nil, InternalServerError +} + +// InsertTargetPoolsInternalErrHook mocks getting target pool and returns an internal server error. +func InsertTargetPoolsInternalErrHook(ctx context.Context, key *meta.Key, obj *ga.TargetPool, m *cloud.MockTargetPools) (bool, error) { + return true, InternalServerError +} + +// InsertForwardingRulesInternalErrHook mocks getting forwarding rule and returns an internal server error. +func InsertForwardingRulesInternalErrHook(ctx context.Context, key *meta.Key, obj *ga.ForwardingRule, m *cloud.MockForwardingRules) (bool, error) { + return true, InternalServerError +} + +// DeleteAddressesNotFoundErrHook mocks deleting network address and returns a not found error. +func DeleteAddressesNotFoundErrHook(ctx context.Context, key *meta.Key, m *cloud.MockAddresses) (bool, error) { + return true, &googleapi.Error{Code: http.StatusNotFound} +} + +// DeleteAddressesInternalErrHook mocks deleting address and returns an internal server error. +func DeleteAddressesInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockAddresses) (bool, error) { + return true, InternalServerError +} + +// GetRegionBackendServicesErrHook mocks getting region backend service and returns an internal server error. +func GetRegionBackendServicesErrHook(ctx context.Context, key *meta.Key, m *cloud.MockRegionBackendServices) (bool, *ga.BackendService, error) { + return true, nil, InternalServerError +} + +// UpdateRegionBackendServicesErrHook mocks updating a reegion backend service and returns an internal server error. +func UpdateRegionBackendServicesErrHook(ctx context.Context, key *meta.Key, svc *ga.BackendService, m *cloud.MockRegionBackendServices) error { + return InternalServerError +} + +// DeleteRegionBackendServicesErrHook mocks deleting region backend service and returns an internal server error. +func DeleteRegionBackendServicesErrHook(ctx context.Context, key *meta.Key, m *cloud.MockRegionBackendServices) (bool, error) { + return true, InternalServerError +} + +// DeleteRegionBackendServicesInUseErrHook mocks deleting region backend service and returns an InUseError. +func DeleteRegionBackendServicesInUseErrHook(ctx context.Context, key *meta.Key, m *cloud.MockRegionBackendServices) (bool, error) { + return true, InUseError +} + +// GetInstanceGroupInternalErrHook mocks getting instance group and returns an internal server error. +func GetInstanceGroupInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockInstanceGroups) (bool, *ga.InstanceGroup, error) { + return true, nil, InternalServerError +} + +// GetHealthChecksInternalErrHook mocks getting health check and returns an internal server erorr. +func GetHealthChecksInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockHealthChecks) (bool, *ga.HealthCheck, error) { + return true, nil, InternalServerError +} + +// DeleteHealthChecksInternalErrHook mocks deleting health check and returns an internal server error. +func DeleteHealthChecksInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockHealthChecks) (bool, error) { + return true, InternalServerError +} + +// DeleteHealthChecksInuseErrHook mocks deleting health check and returns an in use error. +func DeleteHealthChecksInuseErrHook(ctx context.Context, key *meta.Key, m *cloud.MockHealthChecks) (bool, error) { + return true, InUseError +} + +// DeleteForwardingRuleErrHook mocks deleting forwarding rule and returns an internal server error. +func DeleteForwardingRuleErrHook(ctx context.Context, key *meta.Key, m *cloud.MockForwardingRules) (bool, error) { + return true, InternalServerError +} + +// ListZonesInternalErrHook mocks listing zone and returns an internal server error. +func ListZonesInternalErrHook(ctx context.Context, fl *filter.F, m *cloud.MockZones) (bool, []*ga.Zone, error) { + return true, []*ga.Zone{}, InternalServerError +} + +// DeleteInstanceGroupInternalErrHook mocks deleting instance group and returns an internal server error. +func DeleteInstanceGroupInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockInstanceGroups) (bool, error) { + return true, InternalServerError } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/op.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/op.go index 1bd2e0c48..2933fe223 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/op.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/op.go @@ -25,14 +25,22 @@ import ( alpha "google.golang.org/api/compute/v0.alpha" beta "google.golang.org/api/compute/v0.beta" ga "google.golang.org/api/compute/v1" + "google.golang.org/api/googleapi" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) +const ( + operationStatusDone = "DONE" +) + // operation is a GCE operation that can be watied on. type operation interface { // isDone queries GCE for the done status. This call can block. isDone(ctx context.Context) (bool, error) + // error returns the resulting error of the operation. This may be nil if the operations + // was successful. + error() error // rateLimitKey returns the rate limit key to use for the given operation. // This rate limit will govern how fast the server will be polled for // operation completion status. @@ -43,6 +51,7 @@ type gaOperation struct { s *Service projectID string key *meta.Key + err error } func (o *gaOperation) String() string { @@ -71,7 +80,15 @@ func (o *gaOperation) isDone(ctx context.Context) (bool, error) { if err != nil { return false, err } - return op != nil && op.Status == "DONE", nil + if op == nil || op.Status != operationStatusDone { + return false, nil + } + + if op.Error != nil && len(op.Error.Errors) > 0 && op.Error.Errors[0] != nil { + e := op.Error.Errors[0] + o.err = &googleapi.Error{Code: int(op.HttpErrorStatusCode), Message: fmt.Sprintf("%v - %v", e.Code, e.Message)} + } + return true, nil } func (o *gaOperation) rateLimitKey() *RateLimitKey { @@ -83,10 +100,15 @@ func (o *gaOperation) rateLimitKey() *RateLimitKey { } } +func (o *gaOperation) error() error { + return o.err +} + type alphaOperation struct { s *Service projectID string key *meta.Key + err error } func (o *alphaOperation) String() string { @@ -115,7 +137,15 @@ func (o *alphaOperation) isDone(ctx context.Context) (bool, error) { if err != nil { return false, err } - return op != nil && op.Status == "DONE", nil + if op == nil || op.Status != operationStatusDone { + return false, nil + } + + if op.Error != nil && len(op.Error.Errors) > 0 && op.Error.Errors[0] != nil { + e := op.Error.Errors[0] + o.err = &googleapi.Error{Code: int(op.HttpErrorStatusCode), Message: fmt.Sprintf("%v - %v", e.Code, e.Message)} + } + return true, nil } func (o *alphaOperation) rateLimitKey() *RateLimitKey { @@ -127,10 +157,15 @@ func (o *alphaOperation) rateLimitKey() *RateLimitKey { } } +func (o *alphaOperation) error() error { + return o.err +} + type betaOperation struct { s *Service projectID string key *meta.Key + err error } func (o *betaOperation) String() string { @@ -159,7 +194,15 @@ func (o *betaOperation) isDone(ctx context.Context) (bool, error) { if err != nil { return false, err } - return op != nil && op.Status == "DONE", nil + if op == nil || op.Status != operationStatusDone { + return false, nil + } + + if op.Error != nil && len(op.Error.Errors) > 0 && op.Error.Errors[0] != nil { + e := op.Error.Errors[0] + o.err = &googleapi.Error{Code: int(op.HttpErrorStatusCode), Message: fmt.Sprintf("%v - %v", e.Code, e.Message)} + } + return true, nil } func (o *betaOperation) rateLimitKey() *RateLimitKey { @@ -170,3 +213,7 @@ func (o *betaOperation) rateLimitKey() *RateLimitKey { Version: meta.VersionBeta, } } + +func (o *betaOperation) error() error { + return o.err +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/ratelimit.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/ratelimit.go index e38b8f7de..ca1278a00 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/ratelimit.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/ratelimit.go @@ -47,22 +47,60 @@ type RateLimiter interface { Accept(ctx context.Context, key *RateLimitKey) error } +// acceptor is an object which blocks within Accept until a call is allowed to run. +// Accept is a behavior of the flowcontrol.RateLimiter interface. +type acceptor interface { + // Accept blocks until a call is allowed to run. + Accept() +} + +// AcceptRateLimiter wraps an Acceptor with RateLimiter parameters. +type AcceptRateLimiter struct { + // Acceptor is the underlying rate limiter. + Acceptor acceptor +} + +// Accept wraps an Acceptor and blocks on Accept or context.Done(). Key is ignored. +func (rl *AcceptRateLimiter) Accept(ctx context.Context, key *RateLimitKey) error { + ch := make(chan struct{}) + go func() { + rl.Acceptor.Accept() + close(ch) + }() + select { + case <-ch: + break + case <-ctx.Done(): + return ctx.Err() + } + return nil +} + // NopRateLimiter is a rate limiter that performs no rate limiting. type NopRateLimiter struct { } -// Accept the operation to be rate limited. +// Accept everything immediately. func (*NopRateLimiter) Accept(ctx context.Context, key *RateLimitKey) error { - // Rate limit polling of the Operation status to avoid hammering GCE - // for the status of an operation. - const pollTime = time.Duration(1) * time.Second - if key.Operation == "Get" && key.Service == "Operations" { - select { - case <-time.NewTimer(pollTime).C: - break - case <-ctx.Done(): - return ctx.Err() - } - } return nil } + +// MinimumRateLimiter wraps a RateLimiter and will only call its Accept until the minimum +// duration has been met or the context is cancelled. +type MinimumRateLimiter struct { + // RateLimiter is the underlying ratelimiter which is called after the mininum time is reacehd. + RateLimiter RateLimiter + // Minimum is the minimum wait time before the underlying ratelimiter is called. + Minimum time.Duration +} + +// Accept blocks on the minimum duration and context. Once the minimum duration is met, +// the func is blocked on the underlying ratelimiter. +func (m *MinimumRateLimiter) Accept(ctx context.Context, key *RateLimitKey) error { + select { + case <-time.After(m.Minimum): + return m.RateLimiter.Accept(ctx, key) + case <-ctx.Done(): + return ctx.Err() + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/ratelimit_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/ratelimit_test.go new file mode 100644 index 000000000..4bb4512e1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/ratelimit_test.go @@ -0,0 +1,80 @@ +/* +Copyright 2018 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 cloud + +import ( + "context" + "testing" + "time" +) + +type FakeAcceptor struct{ accept func() } + +func (f *FakeAcceptor) Accept() { + f.accept() +} + +func TestAcceptRateLimiter(t *testing.T) { + fa := &FakeAcceptor{accept: func() {}} + arl := &AcceptRateLimiter{fa} + err := arl.Accept(context.Background(), nil) + if err != nil { + t.Errorf("AcceptRateLimiter.Accept() = %v, want nil", err) + } + + // Use context that has been cancelled and expect a context error returned. + ctxCancelled, cancelled := context.WithCancel(context.Background()) + cancelled() + // Verify context is cancelled by now. + <-ctxCancelled.Done() + + fa.accept = func() { time.Sleep(1 * time.Second) } + err = arl.Accept(ctxCancelled, nil) + if err != ctxCancelled.Err() { + t.Errorf("AcceptRateLimiter.Accept() = %v, want %v", err, ctxCancelled.Err()) + } +} + +func TestMinimumRateLimiter(t *testing.T) { + fa := &FakeAcceptor{accept: func() {}} + arl := &AcceptRateLimiter{fa} + var called bool + fa.accept = func() { called = true } + m := &MinimumRateLimiter{RateLimiter: arl, Minimum: 10 * time.Millisecond} + + err := m.Accept(context.Background(), nil) + if err != nil { + t.Errorf("MinimumRateLimiter.Accept = %v, want nil", err) + } + if !called { + t.Errorf("`called` = false, want true") + } + + // Use context that has been cancelled and expect a context error returned. + ctxCancelled, cancelled := context.WithCancel(context.Background()) + cancelled() + // Verify context is cancelled by now. + <-ctxCancelled.Done() + called = false + err = m.Accept(ctxCancelled, nil) + if err != ctxCancelled.Err() { + t.Errorf("AcceptRateLimiter.Accept() = %v, want %v", err, ctxCancelled.Err()) + } + if called { + t.Errorf("`called` = true, want false") + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/service.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/service.go index 99ed7d226..2f332dfff 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/service.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/service.go @@ -45,19 +45,19 @@ func (s *Service) wrapOperation(anyOp interface{}) (operation, error) { if err != nil { return nil, err } - return &gaOperation{s, r.ProjectID, r.Key}, nil + return &gaOperation{s: s, projectID: r.ProjectID, key: r.Key}, nil case *alpha.Operation: r, err := ParseResourceURL(o.SelfLink) if err != nil { return nil, err } - return &alphaOperation{s, r.ProjectID, r.Key}, nil + return &alphaOperation{s: s, projectID: r.ProjectID, key: r.Key}, nil case *beta.Operation: r, err := ParseResourceURL(o.SelfLink) if err != nil { return nil, err } - return &betaOperation{s, r.ProjectID, r.Key}, nil + return &betaOperation{s: s, projectID: r.ProjectID, key: r.Key}, nil default: return nil, fmt.Errorf("invalid type %T", anyOp) } @@ -72,14 +72,39 @@ func (s *Service) WaitForCompletion(ctx context.Context, genericOp interface{}) glog.Errorf("wrapOperation(%+v) error: %v", genericOp, err) return err } - for done, err := op.isDone(ctx); !done; done, err = op.isDone(ctx) { - if err != nil { - glog.V(4).Infof("op.isDone(%v) error; op = %v, err = %v", ctx, op, err) - return err + + return s.pollOperation(ctx, op) +} + +// pollOperation calls operations.isDone until the function comes back true or context is Done. +// If an error occurs retrieving the operation, the loop will continue until the context is done. +// This is to prevent a transient error from bubbling up to controller-level logic. +func (s *Service) pollOperation(ctx context.Context, op operation) error { + var pollCount int + for { + // Check if context has been cancelled. Note that ctx.Done() must be checked before + // returning ctx.Err(). + select { + case <-ctx.Done(): + glog.V(5).Infof("op.pollOperation(%v, %v) not completed, poll count = %d, ctx.Err = %v", ctx, op, pollCount, ctx.Err()) + return ctx.Err() + default: + // ctx is not canceled, continue immediately } - glog.V(5).Infof("op.isDone(%v) waiting; op = %v", ctx, op) + + pollCount++ + glog.V(5).Infof("op.isDone(%v) waiting; op = %v, poll count = %d", ctx, op, pollCount) s.RateLimiter.Accept(ctx, op.rateLimitKey()) + done, err := op.isDone(ctx) + if err != nil { + glog.V(5).Infof("op.isDone(%v) error; op = %v, poll count = %d, err = %v, retrying", ctx, op, pollCount, err) + } + + if done { + break + } } - glog.V(5).Infof("op.isDone(%v) complete; op = %v", ctx, op) - return nil + + glog.V(5).Infof("op.isDone(%v) complete; op = %v, poll count = %d, op.err = %v", ctx, op, pollCount, op.error()) + return op.error() } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/service_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/service_test.go new file mode 100644 index 000000000..fc6fbb51d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/service_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2018 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 cloud + +import ( + "context" + "fmt" + "testing" +) + +func TestPollOperation(t *testing.T) { + const totalAttempts = 10 + var attempts int + fo := &fakeOperation{isDoneFunc: func(ctx context.Context) (bool, error) { + attempts++ + if attempts < totalAttempts { + return false, nil + } + return true, nil + }} + s := Service{RateLimiter: &NopRateLimiter{}} + // Check that pollOperation will retry the operation multiple times. + err := s.pollOperation(context.Background(), fo) + if err != nil { + t.Errorf("pollOperation() = %v, want nil", err) + } + if attempts != totalAttempts { + t.Errorf("`attempts` = %d, want %d", attempts, totalAttempts) + } + + // Check that the operation's error is returned. + fo.err = fmt.Errorf("test operation failed") + err = s.pollOperation(context.Background(), fo) + if err != fo.err { + t.Errorf("pollOperation() = %v, want %v", err, fo.err) + } + fo.err = nil + + fo.isDoneFunc = func(ctx context.Context) (bool, error) { + return false, nil + } + // Use context that has been cancelled and expect a context error returned. + ctxCancelled, cancelled := context.WithCancel(context.Background()) + cancelled() + // Verify context is cancelled by now. + <-ctxCancelled.Done() + // Check that pollOperation returns because the context is cancelled. + err = s.pollOperation(ctxCancelled, fo) + if err == nil { + t.Errorf("pollOperation() = nil, want: %v", ctxCancelled.Err()) + } +} + +type fakeOperation struct { + isDoneFunc func(ctx context.Context) (bool, error) + err error + rateKey *RateLimitKey +} + +func (f *fakeOperation) isDone(ctx context.Context) (bool, error) { + return f.isDoneFunc(ctx) +} + +func (f *fakeOperation) error() error { + return f.err +} + +func (f *fakeOperation) rateLimitKey() *RateLimitKey { + return f.rateKey +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils.go index fb258866f..0affadc96 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils.go @@ -25,9 +25,9 @@ import ( ) const ( - gaPrefix = "https://www.googleapis.com/compute/v1/" - alphaPrefix = "https://www.googleapis.com/compute/alpha/" - betaPrefix = "https://www.googleapis.com/compute/beta/" + gaPrefix = "https://www.googleapis.com/compute/v1" + alphaPrefix = "https://www.googleapis.com/compute/alpha" + betaPrefix = "https://www.googleapis.com/compute/beta" ) // ResourceID identifies a GCE resource as parsed from compute resource URL. @@ -51,8 +51,27 @@ func (r *ResourceID) Equal(other *ResourceID) bool { return false } +// RelativeResourceName returns the relative resource name string +// representing this ResourceID. +func (r *ResourceID) RelativeResourceName() string { + return RelativeResourceName(r.ProjectID, r.Resource, r.Key) +} + +// ResourcePath returns the resource path representing this ResourceID. +func (r *ResourceID) ResourcePath() string { + return ResourcePath(r.Resource, r.Key) +} + +func (r *ResourceID) SelfLink(ver meta.Version) string { + return SelfLink(ver, r.ProjectID, r.Resource, r.Key) +} + // ParseResourceURL parses resource URLs of the following formats: // +// global// +// regions/// +// zones/// +// projects/ // projects//global// // projects//regions/// // projects//zones/// @@ -62,64 +81,63 @@ func (r *ResourceID) Equal(other *ResourceID) bool { func ParseResourceURL(url string) (*ResourceID, error) { errNotValid := fmt.Errorf("%q is not a valid resource URL", url) - // Remove the prefix up to ...projects/ + // Trim prefix off URL leaving "projects/..." projectsIndex := strings.Index(url, "/projects/") if projectsIndex >= 0 { url = url[projectsIndex+1:] } parts := strings.Split(url, "/") - if len(parts) < 2 || parts[0] != "projects" { + if len(parts) < 2 || len(parts) > 6 { return nil, errNotValid } - ret := &ResourceID{ProjectID: parts[1]} - if len(parts) == 2 { + ret := &ResourceID{} + scopedName := parts + if parts[0] == "projects" { ret.Resource = "projects" - return ret, nil - } - - if len(parts) < 4 { - return nil, errNotValid - } + ret.ProjectID = parts[1] + scopedName = parts[2:] - if len(parts) == 4 { - switch parts[2] { - case "regions": - ret.Resource = "regions" - ret.Key = meta.GlobalKey(parts[3]) + if len(scopedName) == 0 { return ret, nil - case "zones": - ret.Resource = "zones" - ret.Key = meta.GlobalKey(parts[3]) - return ret, nil - default: - return nil, errNotValid } } - switch parts[2] { + switch scopedName[0] { case "global": - if len(parts) != 5 { + if len(scopedName) != 3 { return nil, errNotValid } - ret.Resource = parts[3] - ret.Key = meta.GlobalKey(parts[4]) + ret.Resource = scopedName[1] + ret.Key = meta.GlobalKey(scopedName[2]) return ret, nil case "regions": - if len(parts) != 6 { + switch len(scopedName) { + case 2: + ret.Resource = "regions" + ret.Key = meta.GlobalKey(scopedName[1]) + return ret, nil + case 4: + ret.Resource = scopedName[2] + ret.Key = meta.RegionalKey(scopedName[3], scopedName[1]) + return ret, nil + default: return nil, errNotValid } - ret.Resource = parts[4] - ret.Key = meta.RegionalKey(parts[5], parts[3]) - return ret, nil case "zones": - if len(parts) != 6 { + switch len(scopedName) { + case 2: + ret.Resource = "zones" + ret.Key = meta.GlobalKey(scopedName[1]) + return ret, nil + case 4: + ret.Resource = scopedName[2] + ret.Key = meta.ZonalKey(scopedName[3], scopedName[1]) + return ret, nil + default: return nil, errNotValid } - ret.Resource = parts[4] - ret.Key = meta.ZonalKey(parts[5], parts[3]) - return ret, nil } return nil, errNotValid } @@ -132,6 +150,38 @@ func copyViaJSON(dest, src interface{}) error { return json.Unmarshal(bytes, dest) } +// ResourcePath returns the path starting from the location. +// Example: regions/us-central1/subnetworks/my-subnet +func ResourcePath(resource string, key *meta.Key) string { + switch resource { + case "zones", "regions": + return fmt.Sprintf("%s/%s", resource, key.Name) + case "projects": + return "invalid-resource" + } + + switch key.Type() { + case meta.Zonal: + return fmt.Sprintf("zones/%s/%s/%s", key.Zone, resource, key.Name) + case meta.Regional: + return fmt.Sprintf("regions/%s/%s/%s", key.Region, resource, key.Name) + case meta.Global: + return fmt.Sprintf("global/%s/%s", resource, key.Name) + } + return "invalid-key-type" +} + +// RelativeResourceName returns the path starting from project. +// Example: projects/my-project/regions/us-central1/subnetworks/my-subnet +func RelativeResourceName(project, resource string, key *meta.Key) string { + switch resource { + case "projects": + return fmt.Sprintf("projects/%s", project) + default: + return fmt.Sprintf("projects/%s/%s", project, ResourcePath(resource, key)) + } +} + // SelfLink returns the self link URL for the given object. func SelfLink(ver meta.Version, project, resource string, key *meta.Key) string { var prefix string @@ -146,13 +196,6 @@ func SelfLink(ver meta.Version, project, resource string, key *meta.Key) string prefix = "invalid-prefix" } - switch key.Type() { - case meta.Zonal: - return fmt.Sprintf("%sprojects/%s/zones/%s/%s/%s", prefix, project, key.Zone, resource, key.Name) - case meta.Regional: - return fmt.Sprintf("%sprojects/%s/regions/%s/%s/%s", prefix, project, key.Region, resource, key.Name) - case meta.Global: - return fmt.Sprintf("%sprojects/%s/%s/%s", prefix, project, resource, key.Name) - } - return "invalid-self-link" + return fmt.Sprintf("%s/%s", prefix, RelativeResourceName(project, resource, key)) + } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils_test.go index 9d2ee0451..0565638cc 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils_test.go @@ -23,6 +23,54 @@ import ( "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) +func TestEqualResourceID(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + a *ResourceID + b *ResourceID + }{ + { + a: &ResourceID{"some-gce-project", "projects", nil}, + b: &ResourceID{"some-gce-project", "projects", nil}, + }, + { + a: &ResourceID{"", "networks", meta.GlobalKey("my-net")}, + b: &ResourceID{"", "networks", meta.GlobalKey("my-net")}, + }, + { + a: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")}, + b: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")}, + }, + } { + if !tc.a.Equal(tc.b) { + t.Errorf("%v.Equal(%v) = false, want true", tc.a, tc.b) + } + } + + for _, tc := range []struct { + a *ResourceID + b *ResourceID + }{ + { + a: &ResourceID{"some-gce-project", "projects", nil}, + b: &ResourceID{"some-other-project", "projects", nil}, + }, + { + a: &ResourceID{"some-gce-project", "projects", nil}, + b: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")}, + }, + { + a: &ResourceID{"some-gce-project", "networks", meta.GlobalKey("us-central1")}, + b: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")}, + }, + } { + if tc.a.Equal(tc.b) { + t.Errorf("%v.Equal(%v) = true, want false", tc.a, tc.b) + } + } +} + func TestParseResourceURL(t *testing.T) { t.Parallel() @@ -90,6 +138,18 @@ func TestParseResourceURL(t *testing.T) { "projects/some-gce-project/zones/us-central1-c/instances/instance-1", &ResourceID{"some-gce-project", "instances", meta.ZonalKey("instance-1", "us-central1-c")}, }, + { + "global/networks/my-network", + &ResourceID{"", "networks", meta.GlobalKey("my-network")}, + }, + { + "regions/us-central1/subnetworks/my-subnet", + &ResourceID{"", "subnetworks", meta.RegionalKey("my-subnet", "us-central1")}, + }, + { + "zones/us-central1-c/instances/instance-1", + &ResourceID{"", "instances", meta.ZonalKey("instance-1", "us-central1-c")}, + }, } { r, err := ParseResourceURL(tc.in) if err != nil { @@ -112,7 +172,9 @@ func TestParseResourceURL(t *testing.T) { "/a/b/c/d/e/f", "https://www.googleapis.com/compute/v1/projects/some-gce-project/global", "projects/some-gce-project/global", + "projects/some-gce-project/global/foo", "projects/some-gce-project/global/foo/bar/baz", + "projects/some-gce-project/regions/us-central1/res", "projects/some-gce-project/zones/us-central1-c/res", "projects/some-gce-project/zones/us-central1-c/res/name/extra", } { @@ -198,7 +260,28 @@ func TestSelfLink(t *testing.T) { "proj4", "urlMaps", meta.GlobalKey("key3"), - "https://www.googleapis.com/compute/v1/projects/proj4/urlMaps/key3", + "https://www.googleapis.com/compute/v1/projects/proj4/global/urlMaps/key3", + }, + { + meta.VersionGA, + "proj4", + "projects", + nil, + "https://www.googleapis.com/compute/v1/projects/proj4", + }, + { + meta.VersionGA, + "proj4", + "regions", + meta.GlobalKey("us-central1"), + "https://www.googleapis.com/compute/v1/projects/proj4/regions/us-central1", + }, + { + meta.VersionGA, + "proj4", + "zones", + meta.GlobalKey("us-central1-a"), + "https://www.googleapis.com/compute/v1/projects/proj4/zones/us-central1-a", }, } { if link := SelfLink(tc.ver, tc.project, tc.resource, tc.key); link != tc.want { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce.go index 4698c52b0..c2defec38 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce.go @@ -68,7 +68,7 @@ const ( // AffinityTypeClientIPProto - affinity based on Client IP and port. gceAffinityTypeClientIPProto = "CLIENT_IP_PROTO" - operationPollInterval = 3 * time.Second + operationPollInterval = time.Second // Creating Route in very large clusters, may take more than half an hour. operationPollTimeoutDuration = time.Hour @@ -152,6 +152,9 @@ type GCECloud struct { // New code generated interface to the GCE compute library. c cloud.Cloud + + // Keep a reference of this around so we can inject a new cloud.RateLimiter implementation. + s *cloud.Service } // TODO: replace gcfg with json @@ -269,9 +272,7 @@ func generateCloudConfig(configFile *ConfigFile) (cloudConfig *CloudConfig, err // By default, fetch token from GCE metadata server cloudConfig.TokenSource = google.ComputeTokenSource("") cloudConfig.UseMetadataServer = true - - featureMap := make(map[string]bool) - cloudConfig.AlphaFeatureGate = &AlphaFeatureGate{featureMap} + cloudConfig.AlphaFeatureGate = NewAlphaFeatureGate([]string{}) if configFile != nil { if configFile.Global.ApiEndpoint != "" { cloudConfig.ApiEndpoint = configFile.Global.ApiEndpoint @@ -289,19 +290,7 @@ func generateCloudConfig(configFile *ConfigFile) (cloudConfig *CloudConfig, err cloudConfig.NodeTags = configFile.Global.NodeTags cloudConfig.NodeInstancePrefix = configFile.Global.NodeInstancePrefix - - alphaFeatureGate, err := NewAlphaFeatureGate(configFile.Global.AlphaFeatures) - if err != nil { - glog.Errorf("Encountered error for creating alpha feature gate: %v", err) - } - cloudConfig.AlphaFeatureGate = alphaFeatureGate - } else { - // initialize AlphaFeatureGate when no AlphaFeatures are configured. - alphaFeatureGate, err := NewAlphaFeatureGate([]string{}) - if err != nil { - glog.Errorf("Encountered error for initializing alpha feature gate: %v", err) - } - cloudConfig.AlphaFeatureGate = alphaFeatureGate + cloudConfig.AlphaFeatureGate = NewAlphaFeatureGate(configFile.Global.AlphaFeatures) } // retrieve projectID and zone @@ -495,7 +484,7 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) { glog.Infof("managing multiple zones: %v", config.ManagedZones) } - operationPollRateLimiter := flowcontrol.NewTokenBucketRateLimiter(10, 100) // 10 qps, 100 bucket size. + operationPollRateLimiter := flowcontrol.NewTokenBucketRateLimiter(5, 5) // 5 qps, 5 burst. gce := &GCECloud{ service: service, @@ -522,17 +511,27 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) { } gce.manager = &gceServiceManager{gce} - gce.c = cloud.NewGCE(&cloud.Service{ + gce.s = &cloud.Service{ GA: service, Alpha: serviceAlpha, Beta: serviceBeta, ProjectRouter: &gceProjectRouter{gce}, RateLimiter: &gceRateLimiter{gce}, - }) + } + gce.c = cloud.NewGCE(gce.s) return gce, nil } +// SetRateLimiter adds a custom cloud.RateLimiter implementation. +// WARNING: Calling this could have unexpected behavior if you have in-flight +// requests. It is best to use this immediately after creating a GCECloud. +func (g *GCECloud) SetRateLimiter(rl cloud.RateLimiter) { + if rl != nil { + g.s.RateLimiter = rl + } +} + // determineSubnetURL queries for all subnetworks in a region for a given network and returns // the URL of the subnetwork which exists in the auto-subnet range. func determineSubnetURL(service *compute.Service, networkProjectID, networkName, region string) (string, error) { @@ -592,7 +591,7 @@ func (gce *GCECloud) Initialize(clientBuilder controller.ControllerClientBuilder if gce.OnXPN() { gce.eventBroadcaster = record.NewBroadcaster() - gce.eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(gce.client.CoreV1().RESTClient()).Events("")}) + gce.eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: gce.client.CoreV1().Events("")}) gce.eventRecorder = gce.eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "gce-cloudprovider"}) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager_test.go index 3c7d60dc5..3b7409c6c 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager_test.go @@ -26,95 +26,104 @@ import ( ) const testSvcName = "my-service" -const testRegion = "us-central1" const testSubnet = "/projects/x/testRegions/us-central1/testSubnetworks/customsub" const testLBName = "a111111111111111" +var vals = DefaultTestClusterValues() + // TestAddressManagerNoRequestedIP tests the typical case of passing in no requested IP func TestAddressManagerNoRequestedIP(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "" - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal)) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + testHoldAddress(t, mgr, svc, testLBName, vals.Region, targetIP, string(cloud.SchemeInternal)) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerBasic tests the typical case of reserving and unreserving an address. func TestAddressManagerBasic(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "1.1.1.1" - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal)) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + testHoldAddress(t, mgr, svc, testLBName, vals.Region, targetIP, string(cloud.SchemeInternal)) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerOrphaned tests the case where the address exists with the IP being equal // to the requested address (forwarding rule or loadbalancer IP). func TestAddressManagerOrphaned(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "1.1.1.1" addr := &compute.Address{Name: testLBName, Address: targetIP, AddressType: string(cloud.SchemeInternal)} - err := svc.ReserveRegionAddress(addr, testRegion) + err = svc.ReserveRegionAddress(addr, vals.Region) require.NoError(t, err) - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal)) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + testHoldAddress(t, mgr, svc, testLBName, vals.Region, targetIP, string(cloud.SchemeInternal)) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerOutdatedOrphan tests the case where an address exists but points to // an IP other than the forwarding rule or loadbalancer IP. func TestAddressManagerOutdatedOrphan(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) previousAddress := "1.1.0.0" targetIP := "1.1.1.1" addr := &compute.Address{Name: testLBName, Address: previousAddress, AddressType: string(cloud.SchemeExternal)} - err := svc.ReserveRegionAddress(addr, testRegion) + err = svc.ReserveRegionAddress(addr, vals.Region) require.NoError(t, err) - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal)) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + testHoldAddress(t, mgr, svc, testLBName, vals.Region, targetIP, string(cloud.SchemeInternal)) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerExternallyOwned tests the case where the address exists but isn't // owned by the controller. func TestAddressManagerExternallyOwned(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "1.1.1.1" addr := &compute.Address{Name: "my-important-address", Address: targetIP, AddressType: string(cloud.SchemeInternal)} - err := svc.ReserveRegionAddress(addr, testRegion) + err = svc.ReserveRegionAddress(addr, vals.Region) require.NoError(t, err) - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) ipToUse, err := mgr.HoldAddress() require.NoError(t, err) assert.NotEmpty(t, ipToUse) - _, err = svc.GetRegionAddress(testLBName, testRegion) + ad, err := svc.GetRegionAddress(testLBName, vals.Region) assert.True(t, isNotFound(err)) + require.Nil(t, ad) - testReleaseAddress(t, mgr, svc, testLBName, testRegion) + testReleaseAddress(t, mgr, svc, testLBName, vals.Region) } // TestAddressManagerExternallyOwned tests the case where the address exists but isn't // owned by the controller. However, this address has the wrong type. func TestAddressManagerBadExternallyOwned(t *testing.T) { - svc := NewFakeCloudAddressService() + svc, err := fakeGCECloud(vals) + require.NoError(t, err) targetIP := "1.1.1.1" addr := &compute.Address{Name: "my-important-address", Address: targetIP, AddressType: string(cloud.SchemeExternal)} - err := svc.ReserveRegionAddress(addr, testRegion) + err = svc.ReserveRegionAddress(addr, vals.Region) require.NoError(t, err) - mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal) - _, err = mgr.HoldAddress() - assert.NotNil(t, err) + mgr := newAddressManager(svc, testSvcName, vals.Region, testSubnet, testLBName, targetIP, cloud.SchemeInternal) + ad, err := mgr.HoldAddress() + assert.NotNil(t, err) // FIXME + require.Equal(t, ad, "") } func testHoldAddress(t *testing.T, mgr *addressManager, svc CloudAddressService, name, region, targetIP, scheme string) { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses.go index 37e2f5e9a..2bf3e20b0 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses.go @@ -17,7 +17,6 @@ limitations under the License. package gce import ( - "context" "fmt" "github.com/golang/glog" @@ -44,72 +43,105 @@ func newAddressMetricContextWithVersion(request, region, version string) *metric // ipAddress is specified, it must belong to the current project, eg: an // ephemeral IP associated with a global forwarding rule. func (gce *GCECloud) ReserveGlobalAddress(addr *compute.Address) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("reserve", "") - return mc.Observe(gce.c.GlobalAddresses().Insert(context.Background(), meta.GlobalKey(addr.Name), addr)) + return mc.Observe(gce.c.GlobalAddresses().Insert(ctx, meta.GlobalKey(addr.Name), addr)) } // DeleteGlobalAddress deletes a global address by name. func (gce *GCECloud) DeleteGlobalAddress(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("delete", "") - return mc.Observe(gce.c.GlobalAddresses().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.GlobalAddresses().Delete(ctx, meta.GlobalKey(name))) } // GetGlobalAddress returns the global address by name. func (gce *GCECloud) GetGlobalAddress(name string) (*compute.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("get", "") - v, err := gce.c.GlobalAddresses().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.GlobalAddresses().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // ReserveRegionAddress creates a region address func (gce *GCECloud) ReserveRegionAddress(addr *compute.Address, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("reserve", region) - return mc.Observe(gce.c.Addresses().Insert(context.Background(), meta.RegionalKey(addr.Name, region), addr)) + return mc.Observe(gce.c.Addresses().Insert(ctx, meta.RegionalKey(addr.Name, region), addr)) } // ReserveAlphaRegionAddress creates an Alpha, regional address. func (gce *GCECloud) ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("reserve", region) - return mc.Observe(gce.c.AlphaAddresses().Insert(context.Background(), meta.RegionalKey(addr.Name, region), addr)) + return mc.Observe(gce.c.AlphaAddresses().Insert(ctx, meta.RegionalKey(addr.Name, region), addr)) } // ReserveBetaRegionAddress creates a beta region address func (gce *GCECloud) ReserveBetaRegionAddress(addr *computebeta.Address, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("reserve", region) - return mc.Observe(gce.c.BetaAddresses().Insert(context.Background(), meta.RegionalKey(addr.Name, region), addr)) + return mc.Observe(gce.c.BetaAddresses().Insert(ctx, meta.RegionalKey(addr.Name, region), addr)) } // DeleteRegionAddress deletes a region address by name. func (gce *GCECloud) DeleteRegionAddress(name, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("delete", region) - return mc.Observe(gce.c.Addresses().Delete(context.Background(), meta.RegionalKey(name, region))) + return mc.Observe(gce.c.Addresses().Delete(ctx, meta.RegionalKey(name, region))) } // GetRegionAddress returns the region address by name func (gce *GCECloud) GetRegionAddress(name, region string) (*compute.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("get", region) - v, err := gce.c.Addresses().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.Addresses().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // GetAlphaRegionAddress returns the Alpha, regional address by name. func (gce *GCECloud) GetAlphaRegionAddress(name, region string) (*computealpha.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("get", region) - v, err := gce.c.AlphaAddresses().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.AlphaAddresses().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // GetBetaRegionAddress returns the beta region address by name func (gce *GCECloud) GetBetaRegionAddress(name, region string) (*computebeta.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("get", region) - v, err := gce.c.BetaAddresses().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.BetaAddresses().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // GetRegionAddressByIP returns the regional address matching the given IP address. func (gce *GCECloud) GetRegionAddressByIP(region, ipAddress string) (*compute.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("list", region) - addrs, err := gce.c.Addresses().List(context.Background(), region, filter.Regexp("address", ipAddress)) + addrs, err := gce.c.Addresses().List(ctx, region, filter.Regexp("address", ipAddress)) mc.Observe(err) if err != nil { @@ -129,8 +161,11 @@ func (gce *GCECloud) GetRegionAddressByIP(region, ipAddress string) (*compute.Ad // GetBetaRegionAddressByIP returns the beta regional address matching the given IP address. func (gce *GCECloud) GetBetaRegionAddressByIP(region, ipAddress string) (*computebeta.Address, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newAddressMetricContext("list", region) - addrs, err := gce.c.BetaAddresses().List(context.Background(), region, filter.Regexp("address", ipAddress)) + addrs, err := gce.c.BetaAddresses().List(ctx, region, filter.Regexp("address", ipAddress)) mc.Observe(err) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go deleted file mode 100644 index 75dfa571c..000000000 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go +++ /dev/null @@ -1,239 +0,0 @@ -/* -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 gce - -import ( - "bytes" - "encoding/json" - "fmt" - "net/http" - - computealpha "google.golang.org/api/compute/v0.alpha" - computebeta "google.golang.org/api/compute/v0.beta" - compute "google.golang.org/api/compute/v1" - - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" -) - -// test - -type FakeCloudAddressService struct { - count int - // reservedAddrs tracks usage of IP addresses - // Key is the IP address as a string - reservedAddrs map[string]bool - // addrsByRegionAndName - // Outer key is for region string; inner key is for address name. - addrsByRegionAndName map[string]map[string]*computealpha.Address -} - -// FakeCloudAddressService Implements CloudAddressService -var _ CloudAddressService = &FakeCloudAddressService{} - -func NewFakeCloudAddressService() *FakeCloudAddressService { - return &FakeCloudAddressService{ - reservedAddrs: make(map[string]bool), - addrsByRegionAndName: make(map[string]map[string]*computealpha.Address), - } -} - -// SetRegionalAddresses sets the addresses of there region. This is used for -// setting the test environment. -func (cas *FakeCloudAddressService) SetRegionalAddresses(region string, addrs []*computealpha.Address) { - // Reset addresses in the region. - cas.addrsByRegionAndName[region] = make(map[string]*computealpha.Address) - - for _, addr := range addrs { - cas.reservedAddrs[addr.Address] = true - cas.addrsByRegionAndName[region][addr.Name] = addr - } -} - -func (cas *FakeCloudAddressService) ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error { - if addr.Address == "" { - addr.Address = fmt.Sprintf("1.2.3.%d", cas.count) - cas.count++ - } - - if addr.AddressType == "" { - addr.AddressType = string(cloud.SchemeExternal) - } - - if cas.reservedAddrs[addr.Address] { - msg := "IP in use" - // When the IP is already in use, this call returns an error code based - // on the type (internal vs external) of the address. This is to be - // consistent with actual GCE API. - switch cloud.LbScheme(addr.AddressType) { - case cloud.SchemeExternal: - return makeGoogleAPIError(http.StatusBadRequest, msg) - default: - return makeGoogleAPIError(http.StatusConflict, msg) - } - } - - if _, exists := cas.addrsByRegionAndName[region]; !exists { - cas.addrsByRegionAndName[region] = make(map[string]*computealpha.Address) - } - - if _, exists := cas.addrsByRegionAndName[region][addr.Name]; exists { - return makeGoogleAPIError(http.StatusConflict, "name in use") - } - - cas.addrsByRegionAndName[region][addr.Name] = addr - cas.reservedAddrs[addr.Address] = true - return nil -} - -func (cas *FakeCloudAddressService) ReserveBetaRegionAddress(addr *computebeta.Address, region string) error { - alphaAddr := convertToAlphaAddress(addr) - return cas.ReserveAlphaRegionAddress(alphaAddr, region) -} - -func (cas *FakeCloudAddressService) ReserveRegionAddress(addr *compute.Address, region string) error { - alphaAddr := convertToAlphaAddress(addr) - return cas.ReserveAlphaRegionAddress(alphaAddr, region) -} - -func (cas *FakeCloudAddressService) GetAlphaRegionAddress(name, region string) (*computealpha.Address, error) { - if _, exists := cas.addrsByRegionAndName[region]; !exists { - return nil, makeGoogleAPINotFoundError("") - } - - if addr, exists := cas.addrsByRegionAndName[region][name]; !exists { - return nil, makeGoogleAPINotFoundError("") - } else { - return addr, nil - } -} - -func (cas *FakeCloudAddressService) GetBetaRegionAddress(name, region string) (*computebeta.Address, error) { - addr, err := cas.GetAlphaRegionAddress(name, region) - if addr != nil { - return convertToBetaAddress(addr), err - } - return nil, err -} - -func (cas *FakeCloudAddressService) GetRegionAddress(name, region string) (*compute.Address, error) { - addr, err := cas.GetAlphaRegionAddress(name, region) - if addr != nil { - return convertToV1Address(addr), err - } - return nil, err -} - -func (cas *FakeCloudAddressService) DeleteRegionAddress(name, region string) error { - if _, exists := cas.addrsByRegionAndName[region]; !exists { - return makeGoogleAPINotFoundError("") - } - - addr, exists := cas.addrsByRegionAndName[region][name] - if !exists { - return makeGoogleAPINotFoundError("") - } - - delete(cas.reservedAddrs, addr.Address) - delete(cas.addrsByRegionAndName[region], name) - return nil -} - -func (cas *FakeCloudAddressService) GetAlphaRegionAddressByIP(region, ipAddress string) (*computealpha.Address, error) { - if _, exists := cas.addrsByRegionAndName[region]; !exists { - return nil, makeGoogleAPINotFoundError("") - } - - for _, addr := range cas.addrsByRegionAndName[region] { - if addr.Address == ipAddress { - return addr, nil - } - } - return nil, makeGoogleAPINotFoundError("") -} - -func (cas *FakeCloudAddressService) GetBetaRegionAddressByIP(name, region string) (*computebeta.Address, error) { - addr, err := cas.GetAlphaRegionAddressByIP(name, region) - if addr != nil { - return convertToBetaAddress(addr), nil - } - return nil, err -} - -func (cas *FakeCloudAddressService) GetRegionAddressByIP(name, region string) (*compute.Address, error) { - addr, err := cas.GetAlphaRegionAddressByIP(name, region) - if addr != nil { - return convertToV1Address(addr), nil - } - return nil, err -} - -func (cas *FakeCloudAddressService) getNetworkTierFromAddress(name, region string) (string, error) { - addr, err := cas.GetAlphaRegionAddress(name, region) - if err != nil { - return "", err - } - return addr.NetworkTier, nil -} - -func convertToV1Address(object gceObject) *compute.Address { - enc, err := object.MarshalJSON() - if err != nil { - panic(fmt.Sprintf("Failed to encode to json: %v", err)) - } - var addr compute.Address - if err := json.Unmarshal(enc, &addr); err != nil { - panic(fmt.Sprintf("Failed to convert GCE apiObject %v to v1 address: %v", object, err)) - } - return &addr -} - -func convertToAlphaAddress(object gceObject) *computealpha.Address { - enc, err := object.MarshalJSON() - if err != nil { - panic(fmt.Sprintf("Failed to encode to json: %v", err)) - } - var addr computealpha.Address - if err := json.Unmarshal(enc, &addr); err != nil { - panic(fmt.Sprintf("Failed to convert GCE apiObject %v to alpha address: %v", object, err)) - } - // Set the default values for the Alpha fields. - addr.NetworkTier = cloud.NetworkTierDefault.ToGCEValue() - return &addr -} - -func convertToBetaAddress(object gceObject) *computebeta.Address { - enc, err := object.MarshalJSON() - if err != nil { - panic(fmt.Sprintf("Failed to encode to json: %v", err)) - } - var addr computebeta.Address - if err := json.Unmarshal(enc, &addr); err != nil { - panic(fmt.Sprintf("Failed to convert GCE apiObject %v to beta address: %v", object, err)) - } - return &addr -} - -func (cas *FakeCloudAddressService) String() string { - var b bytes.Buffer - for region, regAddresses := range cas.addrsByRegionAndName { - b.WriteString(fmt.Sprintf("%v:\n", region)) - for name, addr := range regAddresses { - b.WriteString(fmt.Sprintf(" %v: %v\n", name, addr.Address)) - } - } - return b.String() -} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_alpha.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_alpha.go index 6e2272527..884b822cb 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_alpha.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_alpha.go @@ -18,8 +18,6 @@ package gce import ( "fmt" - - utilerrors "k8s.io/apimachinery/pkg/util/errors" ) const ( @@ -32,12 +30,6 @@ const ( AlphaFeatureNetworkEndpointGroup = "NetworkEndpointGroup" ) -// All known alpha features -var knownAlphaFeatures = map[string]bool{ - AlphaFeatureNetworkTiers: true, - AlphaFeatureNetworkEndpointGroup: true, -} - type AlphaFeatureGate struct { features map[string]bool } @@ -46,17 +38,12 @@ func (af *AlphaFeatureGate) Enabled(key string) bool { return af.features[key] } -func NewAlphaFeatureGate(features []string) (*AlphaFeatureGate, error) { - errList := []error{} +func NewAlphaFeatureGate(features []string) *AlphaFeatureGate { featureMap := make(map[string]bool) for _, name := range features { - if _, ok := knownAlphaFeatures[name]; !ok { - errList = append(errList, fmt.Errorf("alpha feature %q is not supported.", name)) - } else { - featureMap[name] = true - } + featureMap[name] = true } - return &AlphaFeatureGate{featureMap}, utilerrors.NewAggregate(errList) + return &AlphaFeatureGate{featureMap} } func (gce *GCECloud) alphaFeatureEnabled(feature string) error { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_backendservice.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_backendservice.go index 66bd4d59e..4b330a49e 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_backendservice.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_backendservice.go @@ -17,11 +17,11 @@ limitations under the License. package gce import ( - "context" - computealpha "google.golang.org/api/compute/v0.alpha" + computebeta "google.golang.org/api/compute/v0.beta" compute "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -36,54 +36,88 @@ func newBackendServiceMetricContextWithVersion(request, region, version string) // GetGlobalBackendService retrieves a backend by name. func (gce *GCECloud) GetGlobalBackendService(name string) (*compute.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("get", "") - v, err := gce.c.BackendServices().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.BackendServices().Get(ctx, meta.GlobalKey(name)) + return v, mc.Observe(err) +} + +// GetBetaGlobalBackendService retrieves beta backend by name. +func (gce *GCECloud) GetBetaGlobalBackendService(name string) (*computebeta.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newBackendServiceMetricContextWithVersion("get", "", computeBetaVersion) + v, err := gce.c.BetaBackendServices().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // GetAlphaGlobalBackendService retrieves alpha backend by name. func (gce *GCECloud) GetAlphaGlobalBackendService(name string) (*computealpha.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContextWithVersion("get", "", computeAlphaVersion) - v, err := gce.c.AlphaBackendServices().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.AlphaBackendServices().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // UpdateGlobalBackendService applies the given BackendService as an update to // an existing service. func (gce *GCECloud) UpdateGlobalBackendService(bg *compute.BackendService) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("update", "") - return mc.Observe(gce.c.BackendServices().Update(context.Background(), meta.GlobalKey(bg.Name), bg)) + return mc.Observe(gce.c.BackendServices().Update(ctx, meta.GlobalKey(bg.Name), bg)) } // UpdateAlphaGlobalBackendService applies the given alpha BackendService as an // update to an existing service. func (gce *GCECloud) UpdateAlphaGlobalBackendService(bg *computealpha.BackendService) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("update", "") - return mc.Observe(gce.c.AlphaBackendServices().Update(context.Background(), meta.GlobalKey(bg.Name), bg)) + return mc.Observe(gce.c.AlphaBackendServices().Update(ctx, meta.GlobalKey(bg.Name), bg)) } // DeleteGlobalBackendService deletes the given BackendService by name. func (gce *GCECloud) DeleteGlobalBackendService(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("delete", "") - return mc.Observe(gce.c.BackendServices().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.BackendServices().Delete(ctx, meta.GlobalKey(name))) } // CreateGlobalBackendService creates the given BackendService. func (gce *GCECloud) CreateGlobalBackendService(bg *compute.BackendService) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("create", "") - return mc.Observe(gce.c.BackendServices().Insert(context.Background(), meta.GlobalKey(bg.Name), bg)) + return mc.Observe(gce.c.BackendServices().Insert(ctx, meta.GlobalKey(bg.Name), bg)) } // CreateAlphaGlobalBackendService creates the given alpha BackendService. func (gce *GCECloud) CreateAlphaGlobalBackendService(bg *computealpha.BackendService) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("create", "") - return mc.Observe(gce.c.AlphaBackendServices().Insert(context.Background(), meta.GlobalKey(bg.Name), bg)) + return mc.Observe(gce.c.AlphaBackendServices().Insert(ctx, meta.GlobalKey(bg.Name), bg)) } // ListGlobalBackendServices lists all backend services in the project. func (gce *GCECloud) ListGlobalBackendServices() ([]*compute.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("list", "") - v, err := gce.c.BackendServices().List(context.Background(), filter.None) + v, err := gce.c.BackendServices().List(ctx, filter.None) return v, mc.Observe(err) } @@ -91,42 +125,60 @@ func (gce *GCECloud) ListGlobalBackendServices() ([]*compute.BackendService, err // identified by the given name, in the given instanceGroup. The // instanceGroupLink is the fully qualified self link of an instance group. func (gce *GCECloud) GetGlobalBackendServiceHealth(name string, instanceGroupLink string) (*compute.BackendServiceGroupHealth, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("get_health", "") groupRef := &compute.ResourceGroupReference{Group: instanceGroupLink} - v, err := gce.c.BackendServices().GetHealth(context.Background(), meta.GlobalKey(name), groupRef) + v, err := gce.c.BackendServices().GetHealth(ctx, meta.GlobalKey(name), groupRef) return v, mc.Observe(err) } // GetRegionBackendService retrieves a backend by name. func (gce *GCECloud) GetRegionBackendService(name, region string) (*compute.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("get", region) - v, err := gce.c.RegionBackendServices().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.RegionBackendServices().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // UpdateRegionBackendService applies the given BackendService as an update to // an existing service. func (gce *GCECloud) UpdateRegionBackendService(bg *compute.BackendService, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("update", region) - return mc.Observe(gce.c.RegionBackendServices().Update(context.Background(), meta.RegionalKey(bg.Name, region), bg)) + return mc.Observe(gce.c.RegionBackendServices().Update(ctx, meta.RegionalKey(bg.Name, region), bg)) } // DeleteRegionBackendService deletes the given BackendService by name. func (gce *GCECloud) DeleteRegionBackendService(name, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("delete", region) - return mc.Observe(gce.c.RegionBackendServices().Delete(context.Background(), meta.RegionalKey(name, region))) + return mc.Observe(gce.c.RegionBackendServices().Delete(ctx, meta.RegionalKey(name, region))) } // CreateRegionBackendService creates the given BackendService. func (gce *GCECloud) CreateRegionBackendService(bg *compute.BackendService, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("create", region) - return mc.Observe(gce.c.RegionBackendServices().Insert(context.Background(), meta.RegionalKey(bg.Name, region), bg)) + return mc.Observe(gce.c.RegionBackendServices().Insert(ctx, meta.RegionalKey(bg.Name, region), bg)) } // ListRegionBackendServices lists all backend services in the project. func (gce *GCECloud) ListRegionBackendServices(region string) ([]*compute.BackendService, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("list", region) - v, err := gce.c.RegionBackendServices().List(context.Background(), region, filter.None) + v, err := gce.c.RegionBackendServices().List(ctx, region, filter.None) return v, mc.Observe(err) } @@ -134,8 +186,31 @@ func (gce *GCECloud) ListRegionBackendServices(region string) ([]*compute.Backen // identified by the given name, in the given instanceGroup. The // instanceGroupLink is the fully qualified self link of an instance group. func (gce *GCECloud) GetRegionalBackendServiceHealth(name, region string, instanceGroupLink string) (*compute.BackendServiceGroupHealth, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newBackendServiceMetricContext("get_health", region) ref := &compute.ResourceGroupReference{Group: instanceGroupLink} - v, err := gce.c.RegionBackendServices().GetHealth(context.Background(), meta.RegionalKey(name, region), ref) + v, err := gce.c.RegionBackendServices().GetHealth(ctx, meta.RegionalKey(name, region), ref) return v, mc.Observe(err) } + +// SetSecurityPolicyForBetaGlobalBackendService sets the given +// SecurityPolicyReference for the BackendService identified by the given name. +func (gce *GCECloud) SetSecurityPolicyForBetaGlobalBackendService(backendServiceName string, securityPolicyReference *computebeta.SecurityPolicyReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newBackendServiceMetricContextWithVersion("set_security_policy", "", computeBetaVersion) + return mc.Observe(gce.c.BetaBackendServices().SetSecurityPolicy(ctx, meta.GlobalKey(backendServiceName), securityPolicyReference)) +} + +// SetSecurityPolicyForAlphaGlobalBackendService sets the given +// SecurityPolicyReference for the BackendService identified by the given name. +func (gce *GCECloud) SetSecurityPolicyForAlphaGlobalBackendService(backendServiceName string, securityPolicyReference *computealpha.SecurityPolicyReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newBackendServiceMetricContextWithVersion("set_security_policy", "", computeAlphaVersion) + return mc.Observe(gce.c.AlphaBackendServices().SetSecurityPolicy(ctx, meta.GlobalKey(backendServiceName), securityPolicyReference)) +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_cert.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_cert.go index f91ce879e..3b6614f81 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_cert.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_cert.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - compute "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -31,15 +30,21 @@ func newCertMetricContext(request string) *metricContext { // GetSslCertificate returns the SslCertificate by name. func (gce *GCECloud) GetSslCertificate(name string) (*compute.SslCertificate, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newCertMetricContext("get") - v, err := gce.c.SslCertificates().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.SslCertificates().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateSslCertificate creates and returns a SslCertificate. func (gce *GCECloud) CreateSslCertificate(sslCerts *compute.SslCertificate) (*compute.SslCertificate, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newCertMetricContext("create") - err := gce.c.SslCertificates().Insert(context.Background(), meta.GlobalKey(sslCerts.Name), sslCerts) + err := gce.c.SslCertificates().Insert(ctx, meta.GlobalKey(sslCerts.Name), sslCerts) if err != nil { return nil, mc.Observe(err) } @@ -48,13 +53,19 @@ func (gce *GCECloud) CreateSslCertificate(sslCerts *compute.SslCertificate) (*co // DeleteSslCertificate deletes the SslCertificate by name. func (gce *GCECloud) DeleteSslCertificate(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newCertMetricContext("delete") - return mc.Observe(gce.c.SslCertificates().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.SslCertificates().Delete(ctx, meta.GlobalKey(name))) } // ListSslCertificates lists all SslCertificates in the project. func (gce *GCECloud) ListSslCertificates() ([]*compute.SslCertificate, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newCertMetricContext("list") - v, err := gce.c.SslCertificates().List(context.Background(), filter.None) + v, err := gce.c.SslCertificates().List(ctx, filter.None) return v, mc.Observe(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks.go index 18b1c0809..a62106a61 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks.go @@ -38,6 +38,8 @@ import ( compute "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" "k8s.io/kubernetes/pkg/features" ) @@ -65,7 +67,7 @@ type diskServiceManager interface { sizeGb int64, tagsStr string, diskType string, - zone string) (gceObject, error) + zone string) error // Creates a new regional persistent disk on GCE with the given disk spec. CreateRegionalDiskOnCloudProvider( @@ -73,41 +75,35 @@ type diskServiceManager interface { sizeGb int64, tagsStr string, diskType string, - zones sets.String) (gceObject, error) + zones sets.String) error // Deletes the persistent disk from GCE with the given diskName. - DeleteDiskOnCloudProvider(zone string, disk string) (gceObject, error) + DeleteDiskOnCloudProvider(zone string, disk string) error // Deletes the regional persistent disk from GCE with the given diskName. - DeleteRegionalDiskOnCloudProvider(diskName string) (gceObject, error) + DeleteRegionalDiskOnCloudProvider(diskName string) error // Attach a persistent disk on GCE with the given disk spec to the specified instance. AttachDiskOnCloudProvider( disk *GCEDisk, readWrite string, instanceZone string, - instanceName string) (gceObject, error) + instanceName string) error // Detach a persistent disk on GCE with the given disk spec from the specified instance. DetachDiskOnCloudProvider( instanceZone string, instanceName string, - devicePath string) (gceObject, error) + devicePath string) error - ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) (gceObject, error) - RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) (gceObject, error) + ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) error + RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) error // Gets the persistent disk from GCE with the given diskName. GetDiskFromCloudProvider(zone string, diskName string) (*GCEDisk, error) // Gets the regional persistent disk from GCE with the given diskName. GetRegionalDiskFromCloudProvider(diskName string) (*GCEDisk, error) - - // Waits until GCE reports the given operation in the given zone as done. - WaitForZoneOp(op gceObject, zone string, mc *metricContext) error - - // Waits until GCE reports the given operation in the given region is done. - WaitForRegionalOp(op gceObject, mc *metricContext) error } type gceServiceManager struct { @@ -121,11 +117,11 @@ func (manager *gceServiceManager) CreateDiskOnCloudProvider( sizeGb int64, tagsStr string, diskType string, - zone string) (gceObject, error) { + zone string) error { diskTypeURI, err := manager.getDiskTypeURI( manager.gce.region /* diskRegion */, singleZone{zone}, diskType, false /* useBetaAPI */) if err != nil { - return nil, err + return err } diskToCreateV1 := &compute.Disk{ @@ -134,8 +130,10 @@ func (manager *gceServiceManager) CreateDiskOnCloudProvider( Description: tagsStr, Type: diskTypeURI, } - return manager.gce.service.Disks.Insert( - manager.gce.projectID, zone, diskToCreateV1).Do() + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Disks().Insert(ctx, meta.ZonalKey(name, zone), diskToCreateV1) } func (manager *gceServiceManager) CreateRegionalDiskOnCloudProvider( @@ -143,42 +141,44 @@ func (manager *gceServiceManager) CreateRegionalDiskOnCloudProvider( sizeGb int64, tagsStr string, diskType string, - replicaZones sets.String) (gceObject, error) { + replicaZones sets.String) error { - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - diskTypeURI, err := manager.getDiskTypeURI( - manager.gce.region /* diskRegion */, multiZone{replicaZones}, diskType, true /* useBetaAPI */) - if err != nil { - return nil, err - } - fullyQualifiedReplicaZones := []string{} - for _, replicaZone := range replicaZones.UnsortedList() { - fullyQualifiedReplicaZones = append( - fullyQualifiedReplicaZones, manager.getReplicaZoneURI(replicaZone, true)) - } + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + } - diskToCreateBeta := &computebeta.Disk{ - Name: name, - SizeGb: sizeGb, - Description: tagsStr, - Type: diskTypeURI, - ReplicaZones: fullyQualifiedReplicaZones, - } - return manager.gce.serviceBeta.RegionDisks.Insert( - manager.gce.projectID, manager.gce.region, diskToCreateBeta).Do() + diskTypeURI, err := manager.getDiskTypeURI( + manager.gce.region /* diskRegion */, multiZone{replicaZones}, diskType, true /* useBetaAPI */) + if err != nil { + return err + } + fullyQualifiedReplicaZones := []string{} + for _, replicaZone := range replicaZones.UnsortedList() { + fullyQualifiedReplicaZones = append( + fullyQualifiedReplicaZones, manager.getReplicaZoneURI(replicaZone, true)) } - return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + diskToCreateBeta := &computebeta.Disk{ + Name: name, + SizeGb: sizeGb, + Description: tagsStr, + Type: diskTypeURI, + ReplicaZones: fullyQualifiedReplicaZones, + } + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.BetaRegionDisks().Insert(ctx, meta.RegionalKey(name, manager.gce.region), diskToCreateBeta) } func (manager *gceServiceManager) AttachDiskOnCloudProvider( disk *GCEDisk, readWrite string, instanceZone string, - instanceName string) (gceObject, error) { + instanceName string) error { source, err := manager.getDiskSourceURI(disk) if err != nil { - return nil, err + return err } attachedDiskV1 := &compute.AttachedDisk{ @@ -188,16 +188,19 @@ func (manager *gceServiceManager) AttachDiskOnCloudProvider( Source: source, Type: diskTypePersistent, } - return manager.gce.service.Instances.AttachDisk( - manager.gce.projectID, instanceZone, instanceName, attachedDiskV1).Do() + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Instances().AttachDisk(ctx, meta.ZonalKey(instanceName, instanceZone), attachedDiskV1) } func (manager *gceServiceManager) DetachDiskOnCloudProvider( instanceZone string, instanceName string, - devicePath string) (gceObject, error) { - return manager.gce.service.Instances.DetachDisk( - manager.gce.projectID, instanceZone, instanceName, devicePath).Do() + devicePath string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Instances().DetachDisk(ctx, meta.ZonalKey(instanceName, instanceZone), devicePath) } func (manager *gceServiceManager) GetDiskFromCloudProvider( @@ -211,8 +214,9 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider( return nil, fmt.Errorf("Can not fetch disk. Zone is specified (%q). But disk name is empty.", zone) } - diskStable, err := manager.gce.service.Disks.Get( - manager.gce.projectID, zone, diskName).Do() + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + diskStable, err := manager.gce.c.Disks().Get(ctx, meta.ZonalKey(diskName, zone)) if err != nil { return nil, err } @@ -240,56 +244,50 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider( func (manager *gceServiceManager) GetRegionalDiskFromCloudProvider( diskName string) (*GCEDisk, error) { - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - diskBeta, err := manager.gce.serviceBeta.RegionDisks.Get( - manager.gce.projectID, manager.gce.region, diskName).Do() - if err != nil { - return nil, err - } + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + } - zones := sets.NewString() - for _, zoneURI := range diskBeta.ReplicaZones { - zones.Insert(lastComponent(zoneURI)) - } + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + diskBeta, err := manager.gce.c.BetaRegionDisks().Get(ctx, meta.RegionalKey(diskName, manager.gce.region)) + if err != nil { + return nil, err + } - return &GCEDisk{ - ZoneInfo: multiZone{zones}, - Region: lastComponent(diskBeta.Region), - Name: diskBeta.Name, - Kind: diskBeta.Kind, - Type: diskBeta.Type, - SizeGb: diskBeta.SizeGb, - }, nil + zones := sets.NewString() + for _, zoneURI := range diskBeta.ReplicaZones { + zones.Insert(lastComponent(zoneURI)) } - return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + return &GCEDisk{ + ZoneInfo: multiZone{zones}, + Region: lastComponent(diskBeta.Region), + Name: diskBeta.Name, + Kind: diskBeta.Kind, + Type: diskBeta.Type, + SizeGb: diskBeta.SizeGb, + }, nil } func (manager *gceServiceManager) DeleteDiskOnCloudProvider( zone string, - diskName string) (gceObject, error) { - return manager.gce.service.Disks.Delete( - manager.gce.projectID, zone, diskName).Do() + diskName string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Disks().Delete(ctx, meta.ZonalKey(diskName, zone)) } func (manager *gceServiceManager) DeleteRegionalDiskOnCloudProvider( - diskName string) (gceObject, error) { - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - return manager.gce.serviceBeta.RegionDisks.Delete( - manager.gce.projectID, manager.gce.region, diskName).Do() - } - - return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) -} + diskName string) error { -func (manager *gceServiceManager) WaitForZoneOp( - op gceObject, zone string, mc *metricContext) error { - return manager.gce.waitForZoneOp(op, zone, mc) -} + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + } -func (manager *gceServiceManager) WaitForRegionalOp( - op gceObject, mc *metricContext) error { - return manager.gce.waitForRegionOp(op, manager.gce.region, mc) + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.BetaRegionDisks().Delete(ctx, meta.RegionalKey(diskName, manager.gce.region)) } func (manager *gceServiceManager) getDiskSourceURI(disk *GCEDisk) (string, error) { @@ -411,21 +409,28 @@ func (manager *gceServiceManager) getRegionFromZone(zoneInfo zoneType) (string, return region, nil } -func (manager *gceServiceManager) ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) (gceObject, error) { +func (manager *gceServiceManager) ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) error { resizeServiceRequest := &compute.DisksResizeRequest{ SizeGb: sizeGb, } - return manager.gce.service.Disks.Resize(manager.gce.projectID, zone, disk.Name, resizeServiceRequest).Do() + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.Disks().Resize(ctx, meta.ZonalKey(disk.Name, zone), resizeServiceRequest) } -func (manager *gceServiceManager) RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) (gceObject, error) { - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - resizeServiceRequest := &computebeta.RegionDisksResizeRequest{ - SizeGb: sizeGb, - } - return manager.gce.serviceBeta.RegionDisks.Resize(manager.gce.projectID, disk.Region, disk.Name, resizeServiceRequest).Do() +func (manager *gceServiceManager) RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) error { + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + } + + resizeServiceRequest := &computebeta.RegionDisksResizeRequest{ + SizeGb: sizeGb, } - return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk) + + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return manager.gce.c.BetaRegionDisks().Resize(ctx, meta.RegionalKey(disk.Name, disk.Region), resizeServiceRequest) } // Disks is interface for manipulation with GCE PDs. @@ -535,14 +540,10 @@ func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOn if regional && utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { disk, err = gce.getRegionalDiskByName(diskName) if err != nil { - glog.V(5).Infof("Could not find regional PD named %q to Attach. Will look for a zonal PD", diskName) - err = nil - } else { - mc = newDiskMetricContextRegional("attach", gce.region) + return err } - } - - if disk == nil { + mc = newDiskMetricContextRegional("attach", gce.region) + } else { disk, err = gce.getDiskByName(diskName, instance.Zone) if err != nil { return err @@ -555,14 +556,7 @@ func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOn readWrite = "READ_ONLY" } - attachOp, err := gce.manager.AttachDiskOnCloudProvider( - disk, readWrite, instance.Zone, instance.Name) - - if err != nil { - return mc.Observe(err) - } - - return gce.manager.WaitForZoneOp(attachOp, instance.Zone, mc) + return mc.Observe(gce.manager.AttachDiskOnCloudProvider(disk, readWrite, instance.Zone, instance.Name)) } func (gce *GCECloud) DetachDisk(devicePath string, nodeName types.NodeName) error { @@ -582,12 +576,7 @@ func (gce *GCECloud) DetachDisk(devicePath string, nodeName types.NodeName) erro } mc := newDiskMetricContextZonal("detach", gce.region, inst.Zone) - detachOp, err := gce.manager.DetachDiskOnCloudProvider(inst.Zone, inst.Name, devicePath) - if err != nil { - return mc.Observe(err) - } - - return gce.manager.WaitForZoneOp(detachOp, inst.Zone, mc) + return mc.Observe(gce.manager.DetachDiskOnCloudProvider(inst.Zone, inst.Name, devicePath)) } func (gce *GCECloud) DiskIsAttached(diskName string, nodeName types.NodeName) (bool, error) { @@ -675,17 +664,10 @@ func (gce *GCECloud) CreateDisk( mc := newDiskMetricContextZonal("create", gce.region, zone) - createOp, err := gce.manager.CreateDiskOnCloudProvider( + err = gce.manager.CreateDiskOnCloudProvider( name, sizeGb, tagsStr, diskType, zone) - if isGCEError(err, "alreadyExists") { - glog.Warningf("GCE PD %q already exists, reusing", name) - return nil - } else if err != nil { - return mc.Observe(err) - } - - err = gce.manager.WaitForZoneOp(createOp, zone, mc) + mc.Observe(err) if isGCEError(err, "alreadyExists") { glog.Warningf("GCE PD %q already exists, reusing", name) return nil @@ -723,17 +705,10 @@ func (gce *GCECloud) CreateRegionalDisk( mc := newDiskMetricContextRegional("create", gce.region) - createOp, err := gce.manager.CreateRegionalDiskOnCloudProvider( + err = gce.manager.CreateRegionalDiskOnCloudProvider( name, sizeGb, tagsStr, diskType, replicaZones) - if isGCEError(err, "alreadyExists") { - glog.Warningf("GCE PD %q already exists, reusing", name) - return nil - } else if err != nil { - return mc.Observe(err) - } - - err = gce.manager.WaitForRegionalOp(createOp, mc) + mc.Observe(err) if isGCEError(err, "alreadyExists") { glog.Warningf("GCE PD %q already exists, reusing", name) return nil @@ -772,12 +747,12 @@ func (gce *GCECloud) ResizeDisk(diskToResize string, oldSize resource.Quantity, } requestBytes := newSize.Value() - // GCE resizes in chunks of GBs (not GiB) - requestGB := volumeutil.RoundUpSize(requestBytes, 1000*1000*1000) - newSizeQuant := resource.MustParse(fmt.Sprintf("%dG", requestGB)) + // GCE resizes in chunks of GiBs + requestGIB := volumeutil.RoundUpSize(requestBytes, volumeutil.GIB) + newSizeQuant := resource.MustParse(fmt.Sprintf("%dGi", requestGIB)) // If disk is already of size equal or greater than requested size, we simply return - if disk.SizeGb >= requestGB { + if disk.SizeGb >= requestGIB { return newSizeQuant, nil } @@ -786,31 +761,26 @@ func (gce *GCECloud) ResizeDisk(diskToResize string, oldSize resource.Quantity, switch zoneInfo := disk.ZoneInfo.(type) { case singleZone: mc = newDiskMetricContextZonal("resize", disk.Region, zoneInfo.zone) - resizeOp, err := gce.manager.ResizeDiskOnCloudProvider(disk, requestGB, zoneInfo.zone) + err := gce.manager.ResizeDiskOnCloudProvider(disk, requestGIB, zoneInfo.zone) if err != nil { return oldSize, mc.Observe(err) + } else { + return newSizeQuant, mc.Observe(err) } - waitErr := gce.manager.WaitForZoneOp(resizeOp, zoneInfo.zone, mc) - if waitErr != nil { - return oldSize, waitErr - } - return newSizeQuant, nil case multiZone: - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - mc = newDiskMetricContextRegional("resize", disk.Region) - resizeOp, err := gce.manager.RegionalResizeDiskOnCloudProvider(disk, requestGB) + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return oldSize, fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo) + } - if err != nil { - return oldSize, mc.Observe(err) - } - waitErr := gce.manager.WaitForRegionalOp(resizeOp, mc) - if waitErr != nil { - return oldSize, waitErr - } - return newSizeQuant, nil + mc = newDiskMetricContextRegional("resize", disk.Region) + err := gce.manager.RegionalResizeDiskOnCloudProvider(disk, requestGIB) + + if err != nil { + return oldSize, mc.Observe(err) + } else { + return newSizeQuant, mc.Observe(err) } - return oldSize, fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo) case nil: return oldSize, fmt.Errorf("PD has nil ZoneInfo: %v", disk) default: @@ -1026,21 +996,14 @@ func (gce *GCECloud) doDeleteDisk(diskToDelete string) error { switch zoneInfo := disk.ZoneInfo.(type) { case singleZone: mc = newDiskMetricContextZonal("delete", disk.Region, zoneInfo.zone) - deleteOp, err := gce.manager.DeleteDiskOnCloudProvider(zoneInfo.zone, disk.Name) - if err != nil { - return mc.Observe(err) - } - return gce.manager.WaitForZoneOp(deleteOp, zoneInfo.zone, mc) + return mc.Observe(gce.manager.DeleteDiskOnCloudProvider(zoneInfo.zone, disk.Name)) case multiZone: - if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { - mc = newDiskMetricContextRegional("delete", disk.Region) - deleteOp, err := gce.manager.DeleteRegionalDiskOnCloudProvider(disk.Name) - if err != nil { - return mc.Observe(err) - } - return gce.manager.WaitForRegionalOp(deleteOp, mc) + if !utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) { + return fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo) } - return fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo) + + mc = newDiskMetricContextRegional("delete", disk.Region) + return mc.Observe(gce.manager.DeleteRegionalDiskOnCloudProvider(disk.Name)) case nil: return fmt.Errorf("PD has nil ZoneInfo: %v", disk) default: diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks_test.go index 1a0b1240c..5cc6f5f58 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks_test.go @@ -39,10 +39,7 @@ func TestCreateDisk_Basic(t *testing.T) { gceRegion := "fake-region" zonesWithNodes := []string{"zone1"} fakeManager := newFakeManager(gceProjectId, gceRegion) - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: []string{"zone1"}, @@ -73,9 +70,6 @@ func TestCreateDisk_Basic(t *testing.T) { if !fakeManager.createDiskCalled { t.Error("Never called GCE disk create.") } - if !fakeManager.doesOpMatch { - t.Error("Ops used in WaitForZoneOp does not match what's returned by CreateDisk.") - } // Partial check of equality between disk description sent to GCE and parameters of method. diskToCreate := fakeManager.diskToCreateStable @@ -130,9 +124,6 @@ func TestCreateRegionalDisk_Basic(t *testing.T) { if !fakeManager.createDiskCalled { t.Error("Never called GCE disk create.") } - if !fakeManager.doesOpMatch { - t.Error("Ops used in WaitForZoneOp does not match what's returned by CreateDisk.") - } // Partial check of equality between disk description sent to GCE and parameters of method. diskToCreate := fakeManager.diskToCreateStable @@ -157,10 +148,7 @@ func TestCreateDisk_DiskAlreadyExists(t *testing.T) { gceRegion := "fake-region" zonesWithNodes := []string{"zone1"} fakeManager := newFakeManager(gceProjectId, gceRegion) - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -171,7 +159,7 @@ func TestCreateDisk_DiskAlreadyExists(t *testing.T) { // Inject disk AlreadyExists error. alreadyExistsError := googleapi.ErrorItem{Reason: "alreadyExists"} - fakeManager.waitForOpError = &googleapi.Error{ + fakeManager.opError = &googleapi.Error{ Errors: []googleapi.ErrorItem{alreadyExistsError}, } @@ -266,10 +254,7 @@ func TestCreateDisk_MultiZone(t *testing.T) { gceRegion := "fake-region" zonesWithNodes := []string{"zone1", "zone2", "zone3"} fakeManager := newFakeManager(gceProjectId, gceRegion) - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -298,10 +283,7 @@ func TestDeleteDisk_Basic(t *testing.T) { gceRegion := "fake-region" zonesWithNodes := []string{"zone1"} fakeManager := newFakeManager(gceProjectId, gceRegion) - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -326,9 +308,6 @@ func TestDeleteDisk_Basic(t *testing.T) { if !fakeManager.deleteDiskCalled { t.Error("Never called GCE disk delete.") } - if !fakeManager.doesOpMatch { - t.Error("Ops used in WaitForZoneOp does not match what's returned by DeleteDisk.") - } } @@ -338,10 +317,7 @@ func TestDeleteDisk_NotFound(t *testing.T) { gceRegion := "fake-region" zonesWithNodes := []string{"zone1"} fakeManager := newFakeManager(gceProjectId, gceRegion) - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -366,10 +342,7 @@ func TestDeleteDisk_ResourceBeingUsed(t *testing.T) { gceRegion := "fake-region" zonesWithNodes := []string{"zone1"} fakeManager := newFakeManager(gceProjectId, gceRegion) - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -400,10 +373,7 @@ func TestDeleteDisk_SameDiskMultiZone(t *testing.T) { gceRegion := "fake-region" zonesWithNodes := []string{"zone1", "zone2", "zone3"} fakeManager := newFakeManager(gceProjectId, gceRegion) - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -437,10 +407,7 @@ func TestDeleteDisk_DiffDiskMultiZone(t *testing.T) { gceRegion := "fake-region" zonesWithNodes := []string{"zone1"} fakeManager := newFakeManager(gceProjectId, gceRegion) - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -478,10 +445,7 @@ func TestGetAutoLabelsForPD_Basic(t *testing.T) { diskName := "disk" diskType := DiskTypeSSD const sizeGb int64 = 128 - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -518,10 +482,7 @@ func TestGetAutoLabelsForPD_NoZone(t *testing.T) { diskName := "disk" diskType := DiskTypeStandard const sizeGb int64 = 128 - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -576,10 +537,7 @@ func TestGetAutoLabelsForPD_DiskNotFoundAndNoZone(t *testing.T) { zonesWithNodes := []string{} fakeManager := newFakeManager(gceProjectId, gceRegion) diskName := "disk" - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -608,10 +566,7 @@ func TestGetAutoLabelsForPD_DupDisk(t *testing.T) { zone := "us-west1-b" const sizeGb int64 = 128 - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -649,10 +604,7 @@ func TestGetAutoLabelsForPD_DupDiskNoZone(t *testing.T) { diskType := DiskTypeStandard const sizeGb int64 = 128 - alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{}) - if featureGateErr != nil { - t.Error(featureGateErr) - } + alphaFeatureGate := NewAlphaFeatureGate([]string{}) gce := GCECloud{ manager: fakeManager, managedZones: zonesWithNodes, @@ -683,16 +635,12 @@ const ( type FakeServiceManager struct { // Common fields shared among tests - targetAPI targetClientAPI - gceProjectID string - gceRegion string - opAlpha *computealpha.Operation // Mocks an operation returned by GCE API calls - opBeta *computebeta.Operation // Mocks an operation returned by GCE API calls - opStable *compute.Operation // Mocks an operation returned by GCE API calls - doesOpMatch bool - zonalDisks map[string]string // zone: diskName - regionalDisks map[string]sets.String // diskName: zones - waitForOpError error // Error to be returned by WaitForZoneOp or WaitForRegionalOp + targetAPI targetClientAPI + gceProjectID string + gceRegion string + zonalDisks map[string]string // zone: diskName + regionalDisks map[string]sets.String // diskName: zones + opError error // Fields for TestCreateDisk createDiskCalled bool @@ -723,12 +671,11 @@ func (manager *FakeServiceManager) CreateDiskOnCloudProvider( sizeGb int64, tagsStr string, diskType string, - zone string) (gceObject, error) { + zone string) error { manager.createDiskCalled = true switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} diskTypeURI := gceComputeAPIEndpoint + "projects/" + fmt.Sprintf(diskTypeURITemplateSingleZone, manager.gceProjectID, zone, diskType) diskToCreateV1 := &compute.Disk{ Name: name, @@ -738,9 +685,8 @@ func (manager *FakeServiceManager) CreateDiskOnCloudProvider( } manager.diskToCreateStable = diskToCreateV1 manager.zonalDisks[zone] = diskToCreateV1.Name - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} diskTypeURI := gceComputeAPIEndpoint + "projects/" + fmt.Sprintf(diskTypeURITemplateSingleZone, manager.gceProjectID, zone, diskType) diskToCreateBeta := &computebeta.Disk{ Name: name, @@ -750,9 +696,8 @@ func (manager *FakeServiceManager) CreateDiskOnCloudProvider( } manager.diskToCreateBeta = diskToCreateBeta manager.zonalDisks[zone] = diskToCreateBeta.Name - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} diskTypeURI := gceComputeAPIEndpointBeta + "projects/" + fmt.Sprintf(diskTypeURITemplateSingleZone, manager.gceProjectID, zone, diskType) diskToCreateAlpha := &computealpha.Disk{ Name: name, @@ -762,9 +707,9 @@ func (manager *FakeServiceManager) CreateDiskOnCloudProvider( } manager.diskToCreateAlpha = diskToCreateAlpha manager.zonalDisks[zone] = diskToCreateAlpha.Name - return manager.opAlpha, nil + return nil default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } @@ -777,13 +722,12 @@ func (manager *FakeServiceManager) CreateRegionalDiskOnCloudProvider( sizeGb int64, tagsStr string, diskType string, - zones sets.String) (gceObject, error) { + zones sets.String) error { manager.createDiskCalled = true diskTypeURI := gceComputeAPIEndpointBeta + "projects/" + fmt.Sprintf(diskTypeURITemplateRegional, manager.gceProjectID, manager.gceRegion, diskType) switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} diskToCreateV1 := &compute.Disk{ Name: name, SizeGb: sizeGb, @@ -792,13 +736,13 @@ func (manager *FakeServiceManager) CreateRegionalDiskOnCloudProvider( } manager.diskToCreateStable = diskToCreateV1 manager.regionalDisks[diskToCreateV1.Name] = zones - return manager.opStable, nil + return nil case targetBeta: - return nil, fmt.Errorf("RegionalDisk CreateDisk op not supported in beta.") + return fmt.Errorf("RegionalDisk CreateDisk op not supported in beta.") case targetAlpha: - return nil, fmt.Errorf("RegionalDisk CreateDisk op not supported in alpha.") + return fmt.Errorf("RegionalDisk CreateDisk op not supported in alpha.") default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } @@ -806,39 +750,33 @@ func (manager *FakeServiceManager) AttachDiskOnCloudProvider( disk *GCEDisk, readWrite string, instanceZone string, - instanceName string) (gceObject, error) { + instanceName string) error { switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} - return manager.opAlpha, nil + return nil default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } func (manager *FakeServiceManager) DetachDiskOnCloudProvider( instanceZone string, instanceName string, - devicePath string) (gceObject, error) { + devicePath string) error { switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} - return manager.opAlpha, nil + return nil default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } @@ -895,13 +833,13 @@ func (manager *FakeServiceManager) GetRegionalDiskFromCloudProvider( func (manager *FakeServiceManager) ResizeDiskOnCloudProvider( disk *GCEDisk, size int64, - zone string) (gceObject, error) { + zone string) error { panic("Not implmented") } func (manager *FakeServiceManager) RegionalResizeDiskOnCloudProvider( disk *GCEDisk, - size int64) (gceObject, error) { + size int64) error { panic("Not implemented") } @@ -910,89 +848,39 @@ func (manager *FakeServiceManager) RegionalResizeDiskOnCloudProvider( */ func (manager *FakeServiceManager) DeleteDiskOnCloudProvider( zone string, - disk string) (gceObject, error) { + disk string) error { manager.deleteDiskCalled = true delete(manager.zonalDisks, zone) switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} - return manager.opAlpha, nil + return nil default: - return nil, fmt.Errorf("unexpected type: %T", t) + return fmt.Errorf("unexpected type: %T", t) } } func (manager *FakeServiceManager) DeleteRegionalDiskOnCloudProvider( - disk string) (gceObject, error) { + disk string) error { manager.deleteDiskCalled = true delete(manager.regionalDisks, disk) switch t := manager.targetAPI; t { case targetStable: - manager.opStable = &compute.Operation{} - return manager.opStable, nil + return nil case targetBeta: - manager.opBeta = &computebeta.Operation{} - return manager.opBeta, nil + return nil case targetAlpha: - manager.opAlpha = &computealpha.Operation{} - return manager.opAlpha, nil - default: - return nil, fmt.Errorf("unexpected type: %T", t) - } -} - -func (manager *FakeServiceManager) WaitForZoneOp( - op gceObject, - zone string, - mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - if op.(*computealpha.Operation) == manager.opAlpha { - manager.doesOpMatch = true - } - case *computebeta.Operation: - if op.(*computebeta.Operation) == manager.opBeta { - manager.doesOpMatch = true - } - case *compute.Operation: - if op.(*compute.Operation) == manager.opStable { - manager.doesOpMatch = true - } - default: - return fmt.Errorf("unexpected type: %T", v) - } - return manager.waitForOpError -} - -func (manager *FakeServiceManager) WaitForRegionalOp( - op gceObject, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - if op.(*computealpha.Operation) == manager.opAlpha { - manager.doesOpMatch = true - } - case *computebeta.Operation: - if op.(*computebeta.Operation) == manager.opBeta { - manager.doesOpMatch = true - } - case *compute.Operation: - if op.(*compute.Operation) == manager.opStable { - manager.doesOpMatch = true - } + return nil default: - return fmt.Errorf("unexpected type: %T", v) + return fmt.Errorf("unexpected type: %T", t) } - return manager.waitForOpError } func createNodeZones(zones []string) map[string]sets.String { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_firewall.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_firewall.go index 88db0ebd3..e138df874 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_firewall.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_firewall.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - compute "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -30,25 +29,37 @@ func newFirewallMetricContext(request string) *metricContext { // GetFirewall returns the Firewall by name. func (gce *GCECloud) GetFirewall(name string) (*compute.Firewall, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newFirewallMetricContext("get") - v, err := gce.c.Firewalls().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.Firewalls().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateFirewall creates the passed firewall func (gce *GCECloud) CreateFirewall(f *compute.Firewall) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newFirewallMetricContext("create") - return mc.Observe(gce.c.Firewalls().Insert(context.Background(), meta.GlobalKey(f.Name), f)) + return mc.Observe(gce.c.Firewalls().Insert(ctx, meta.GlobalKey(f.Name), f)) } // DeleteFirewall deletes the given firewall rule. func (gce *GCECloud) DeleteFirewall(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newFirewallMetricContext("delete") - return mc.Observe(gce.c.Firewalls().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.Firewalls().Delete(ctx, meta.GlobalKey(name))) } // UpdateFirewall applies the given firewall as an update to an existing service. func (gce *GCECloud) UpdateFirewall(f *compute.Firewall) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newFirewallMetricContext("update") - return mc.Observe(gce.c.Firewalls().Update(context.Background(), meta.GlobalKey(f.Name), f)) + return mc.Observe(gce.c.Firewalls().Update(ctx, meta.GlobalKey(f.Name), f)) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule.go index 9fe0da9f7..b40652c98 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule.go @@ -17,8 +17,6 @@ limitations under the License. package gce import ( - "context" - computealpha "google.golang.org/api/compute/v0.alpha" compute "google.golang.org/api/compute/v1" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" @@ -35,84 +33,120 @@ func newForwardingRuleMetricContextWithVersion(request, region, version string) // CreateGlobalForwardingRule creates the passed GlobalForwardingRule func (gce *GCECloud) CreateGlobalForwardingRule(rule *compute.ForwardingRule) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("create", "") - return mc.Observe(gce.c.GlobalForwardingRules().Insert(context.Background(), meta.GlobalKey(rule.Name), rule)) + return mc.Observe(gce.c.GlobalForwardingRules().Insert(ctx, meta.GlobalKey(rule.Name), rule)) } // SetProxyForGlobalForwardingRule links the given TargetHttp(s)Proxy with the given GlobalForwardingRule. // targetProxyLink is the SelfLink of a TargetHttp(s)Proxy. func (gce *GCECloud) SetProxyForGlobalForwardingRule(forwardingRuleName, targetProxyLink string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("set_proxy", "") target := &compute.TargetReference{Target: targetProxyLink} - return mc.Observe(gce.c.GlobalForwardingRules().SetTarget(context.Background(), meta.GlobalKey(forwardingRuleName), target)) + return mc.Observe(gce.c.GlobalForwardingRules().SetTarget(ctx, meta.GlobalKey(forwardingRuleName), target)) } // DeleteGlobalForwardingRule deletes the GlobalForwardingRule by name. func (gce *GCECloud) DeleteGlobalForwardingRule(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("delete", "") - return mc.Observe(gce.c.GlobalForwardingRules().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.GlobalForwardingRules().Delete(ctx, meta.GlobalKey(name))) } // GetGlobalForwardingRule returns the GlobalForwardingRule by name. func (gce *GCECloud) GetGlobalForwardingRule(name string) (*compute.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("get", "") - v, err := gce.c.GlobalForwardingRules().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.GlobalForwardingRules().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // ListGlobalForwardingRules lists all GlobalForwardingRules in the project. func (gce *GCECloud) ListGlobalForwardingRules() ([]*compute.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("list", "") - v, err := gce.c.GlobalForwardingRules().List(context.Background(), filter.None) + v, err := gce.c.GlobalForwardingRules().List(ctx, filter.None) return v, mc.Observe(err) } // GetRegionForwardingRule returns the RegionalForwardingRule by name & region. func (gce *GCECloud) GetRegionForwardingRule(name, region string) (*compute.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("get", region) - v, err := gce.c.ForwardingRules().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.ForwardingRules().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // GetAlphaRegionForwardingRule returns the Alpha forwarding rule by name & region. func (gce *GCECloud) GetAlphaRegionForwardingRule(name, region string) (*computealpha.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContextWithVersion("get", region, computeAlphaVersion) - v, err := gce.c.AlphaForwardingRules().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.AlphaForwardingRules().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // ListRegionForwardingRules lists all RegionalForwardingRules in the project & region. func (gce *GCECloud) ListRegionForwardingRules(region string) ([]*compute.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("list", region) - v, err := gce.c.ForwardingRules().List(context.Background(), region, filter.None) + v, err := gce.c.ForwardingRules().List(ctx, region, filter.None) return v, mc.Observe(err) } // ListAlphaRegionForwardingRules lists all RegionalForwardingRules in the project & region. func (gce *GCECloud) ListAlphaRegionForwardingRules(region string) ([]*computealpha.ForwardingRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContextWithVersion("list", region, computeAlphaVersion) - v, err := gce.c.AlphaForwardingRules().List(context.Background(), region, filter.None) + v, err := gce.c.AlphaForwardingRules().List(ctx, region, filter.None) return v, mc.Observe(err) } // CreateRegionForwardingRule creates and returns a // RegionalForwardingRule that points to the given BackendService func (gce *GCECloud) CreateRegionForwardingRule(rule *compute.ForwardingRule, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("create", region) - return mc.Observe(gce.c.ForwardingRules().Insert(context.Background(), meta.RegionalKey(rule.Name, region), rule)) + return mc.Observe(gce.c.ForwardingRules().Insert(ctx, meta.RegionalKey(rule.Name, region), rule)) } // CreateAlphaRegionForwardingRule creates and returns an Alpha // forwarding fule in the given region. func (gce *GCECloud) CreateAlphaRegionForwardingRule(rule *computealpha.ForwardingRule, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContextWithVersion("create", region, computeAlphaVersion) - return mc.Observe(gce.c.AlphaForwardingRules().Insert(context.Background(), meta.RegionalKey(rule.Name, region), rule)) + return mc.Observe(gce.c.AlphaForwardingRules().Insert(ctx, meta.RegionalKey(rule.Name, region), rule)) } // DeleteRegionForwardingRule deletes the RegionalForwardingRule by name & region. func (gce *GCECloud) DeleteRegionForwardingRule(name, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newForwardingRuleMetricContext("delete", region) - return mc.Observe(gce.c.ForwardingRules().Delete(context.Background(), meta.RegionalKey(name, region))) + return mc.Observe(gce.c.ForwardingRules().Delete(ctx, meta.RegionalKey(name, region))) } // TODO(#51665): retire this function once Network Tiers becomes Beta in GCP. diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_healthchecks.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_healthchecks.go index e4c0829e1..937ba2950 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_healthchecks.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_healthchecks.go @@ -17,14 +17,13 @@ limitations under the License. package gce import ( - "context" - "github.com/golang/glog" computealpha "google.golang.org/api/compute/v0.alpha" compute "google.golang.org/api/compute/v1" "k8s.io/api/core/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" "k8s.io/kubernetes/pkg/master/ports" @@ -58,33 +57,48 @@ func newHealthcheckMetricContextWithVersion(request, version string) *metricCont // GetHttpHealthCheck returns the given HttpHealthCheck by name. func (gce *GCECloud) GetHttpHealthCheck(name string) (*compute.HttpHealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("get_legacy") - v, err := gce.c.HttpHealthChecks().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.HttpHealthChecks().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // UpdateHttpHealthCheck applies the given HttpHealthCheck as an update. func (gce *GCECloud) UpdateHttpHealthCheck(hc *compute.HttpHealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("update_legacy") - return mc.Observe(gce.c.HttpHealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HttpHealthChecks().Update(ctx, meta.GlobalKey(hc.Name), hc)) } // DeleteHttpHealthCheck deletes the given HttpHealthCheck by name. func (gce *GCECloud) DeleteHttpHealthCheck(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("delete_legacy") - return mc.Observe(gce.c.HttpHealthChecks().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.HttpHealthChecks().Delete(ctx, meta.GlobalKey(name))) } // CreateHttpHealthCheck creates the given HttpHealthCheck. func (gce *GCECloud) CreateHttpHealthCheck(hc *compute.HttpHealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("create_legacy") - return mc.Observe(gce.c.HttpHealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HttpHealthChecks().Insert(ctx, meta.GlobalKey(hc.Name), hc)) } // ListHttpHealthChecks lists all HttpHealthChecks in the project. func (gce *GCECloud) ListHttpHealthChecks() ([]*compute.HttpHealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("list_legacy") - v, err := gce.c.HttpHealthChecks().List(context.Background(), filter.None) + v, err := gce.c.HttpHealthChecks().List(ctx, filter.None) return v, mc.Observe(err) } @@ -92,33 +106,48 @@ func (gce *GCECloud) ListHttpHealthChecks() ([]*compute.HttpHealthCheck, error) // GetHttpsHealthCheck returns the given HttpsHealthCheck by name. func (gce *GCECloud) GetHttpsHealthCheck(name string) (*compute.HttpsHealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("get_legacy") - v, err := gce.c.HttpsHealthChecks().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.HttpsHealthChecks().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // UpdateHttpsHealthCheck applies the given HttpsHealthCheck as an update. func (gce *GCECloud) UpdateHttpsHealthCheck(hc *compute.HttpsHealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("update_legacy") - return mc.Observe(gce.c.HttpsHealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HttpsHealthChecks().Update(ctx, meta.GlobalKey(hc.Name), hc)) } // DeleteHttpsHealthCheck deletes the given HttpsHealthCheck by name. func (gce *GCECloud) DeleteHttpsHealthCheck(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("delete_legacy") - return mc.Observe(gce.c.HttpsHealthChecks().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.HttpsHealthChecks().Delete(ctx, meta.GlobalKey(name))) } // CreateHttpsHealthCheck creates the given HttpsHealthCheck. func (gce *GCECloud) CreateHttpsHealthCheck(hc *compute.HttpsHealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("create_legacy") - return mc.Observe(gce.c.HttpsHealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HttpsHealthChecks().Insert(ctx, meta.GlobalKey(hc.Name), hc)) } // ListHttpsHealthChecks lists all HttpsHealthChecks in the project. func (gce *GCECloud) ListHttpsHealthChecks() ([]*compute.HttpsHealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("list_legacy") - v, err := gce.c.HttpsHealthChecks().List(context.Background(), filter.None) + v, err := gce.c.HttpsHealthChecks().List(ctx, filter.None) return v, mc.Observe(err) } @@ -126,52 +155,76 @@ func (gce *GCECloud) ListHttpsHealthChecks() ([]*compute.HttpsHealthCheck, error // GetHealthCheck returns the given HealthCheck by name. func (gce *GCECloud) GetHealthCheck(name string) (*compute.HealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("get") - v, err := gce.c.HealthChecks().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.HealthChecks().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // GetAlphaHealthCheck returns the given alpha HealthCheck by name. func (gce *GCECloud) GetAlphaHealthCheck(name string) (*computealpha.HealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContextWithVersion("get", computeAlphaVersion) - v, err := gce.c.AlphaHealthChecks().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.AlphaHealthChecks().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // UpdateHealthCheck applies the given HealthCheck as an update. func (gce *GCECloud) UpdateHealthCheck(hc *compute.HealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("update") - return mc.Observe(gce.c.HealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HealthChecks().Update(ctx, meta.GlobalKey(hc.Name), hc)) } // UpdateAlphaHealthCheck applies the given alpha HealthCheck as an update. func (gce *GCECloud) UpdateAlphaHealthCheck(hc *computealpha.HealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContextWithVersion("update", computeAlphaVersion) - return mc.Observe(gce.c.AlphaHealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.AlphaHealthChecks().Update(ctx, meta.GlobalKey(hc.Name), hc)) } // DeleteHealthCheck deletes the given HealthCheck by name. func (gce *GCECloud) DeleteHealthCheck(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("delete") - return mc.Observe(gce.c.HealthChecks().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.HealthChecks().Delete(ctx, meta.GlobalKey(name))) } // CreateHealthCheck creates the given HealthCheck. func (gce *GCECloud) CreateHealthCheck(hc *compute.HealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("create") - return mc.Observe(gce.c.HealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.HealthChecks().Insert(ctx, meta.GlobalKey(hc.Name), hc)) } // CreateAlphaHealthCheck creates the given alpha HealthCheck. func (gce *GCECloud) CreateAlphaHealthCheck(hc *computealpha.HealthCheck) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContextWithVersion("create", computeAlphaVersion) - return mc.Observe(gce.c.AlphaHealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc)) + return mc.Observe(gce.c.AlphaHealthChecks().Insert(ctx, meta.GlobalKey(hc.Name), hc)) } // ListHealthChecks lists all HealthCheck in the project. func (gce *GCECloud) ListHealthChecks() ([]*compute.HealthCheck, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newHealthcheckMetricContext("list") - v, err := gce.c.HealthChecks().List(context.Background(), filter.None) + v, err := gce.c.HealthChecks().List(ctx, filter.None) return v, mc.Observe(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instancegroup.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instancegroup.go index 84b9724bf..13b2c51e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instancegroup.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instancegroup.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - compute "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -32,36 +31,51 @@ func newInstanceGroupMetricContext(request string, zone string) *metricContext { // CreateInstanceGroup creates an instance group with the given // instances. It is the callers responsibility to add named ports. func (gce *GCECloud) CreateInstanceGroup(ig *compute.InstanceGroup, zone string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("create", zone) - return mc.Observe(gce.c.InstanceGroups().Insert(context.Background(), meta.ZonalKey(ig.Name, zone), ig)) + return mc.Observe(gce.c.InstanceGroups().Insert(ctx, meta.ZonalKey(ig.Name, zone), ig)) } // DeleteInstanceGroup deletes an instance group. func (gce *GCECloud) DeleteInstanceGroup(name string, zone string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("delete", zone) - return mc.Observe(gce.c.InstanceGroups().Delete(context.Background(), meta.ZonalKey(name, zone))) + return mc.Observe(gce.c.InstanceGroups().Delete(ctx, meta.ZonalKey(name, zone))) } // ListInstanceGroups lists all InstanceGroups in the project and // zone. func (gce *GCECloud) ListInstanceGroups(zone string) ([]*compute.InstanceGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("list", zone) - v, err := gce.c.InstanceGroups().List(context.Background(), zone, filter.None) + v, err := gce.c.InstanceGroups().List(ctx, zone, filter.None) return v, mc.Observe(err) } // ListInstancesInInstanceGroup lists all the instances in a given // instance group and state. func (gce *GCECloud) ListInstancesInInstanceGroup(name string, zone string, state string) ([]*compute.InstanceWithNamedPorts, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("list_instances", zone) req := &compute.InstanceGroupsListInstancesRequest{InstanceState: state} - v, err := gce.c.InstanceGroups().ListInstances(context.Background(), meta.ZonalKey(name, zone), req, filter.None) + v, err := gce.c.InstanceGroups().ListInstances(ctx, meta.ZonalKey(name, zone), req, filter.None) return v, mc.Observe(err) } // AddInstancesToInstanceGroup adds the given instances to the given // instance group. func (gce *GCECloud) AddInstancesToInstanceGroup(name string, zone string, instanceRefs []*compute.InstanceReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("add_instances", zone) // TODO: should cull operation above this layer. if len(instanceRefs) == 0 { @@ -70,12 +84,15 @@ func (gce *GCECloud) AddInstancesToInstanceGroup(name string, zone string, insta req := &compute.InstanceGroupsAddInstancesRequest{ Instances: instanceRefs, } - return mc.Observe(gce.c.InstanceGroups().AddInstances(context.Background(), meta.ZonalKey(name, zone), req)) + return mc.Observe(gce.c.InstanceGroups().AddInstances(ctx, meta.ZonalKey(name, zone), req)) } // RemoveInstancesFromInstanceGroup removes the given instances from // the instance group. func (gce *GCECloud) RemoveInstancesFromInstanceGroup(name string, zone string, instanceRefs []*compute.InstanceReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("remove_instances", zone) // TODO: should cull operation above this layer. if len(instanceRefs) == 0 { @@ -84,19 +101,25 @@ func (gce *GCECloud) RemoveInstancesFromInstanceGroup(name string, zone string, req := &compute.InstanceGroupsRemoveInstancesRequest{ Instances: instanceRefs, } - return mc.Observe(gce.c.InstanceGroups().RemoveInstances(context.Background(), meta.ZonalKey(name, zone), req)) + return mc.Observe(gce.c.InstanceGroups().RemoveInstances(ctx, meta.ZonalKey(name, zone), req)) } // SetNamedPortsOfInstanceGroup sets the list of named ports on a given instance group func (gce *GCECloud) SetNamedPortsOfInstanceGroup(igName, zone string, namedPorts []*compute.NamedPort) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("set_namedports", zone) req := &compute.InstanceGroupsSetNamedPortsRequest{NamedPorts: namedPorts} - return mc.Observe(gce.c.InstanceGroups().SetNamedPorts(context.Background(), meta.ZonalKey(igName, zone), req)) + return mc.Observe(gce.c.InstanceGroups().SetNamedPorts(ctx, meta.ZonalKey(igName, zone), req)) } // GetInstanceGroup returns an instance group by name. func (gce *GCECloud) GetInstanceGroup(name string, zone string) (*compute.InstanceGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstanceGroupMetricContext("get", zone) - v, err := gce.c.InstanceGroups().Get(context.Background(), meta.ZonalKey(name, zone)) + v, err := gce.c.InstanceGroups().Get(ctx, meta.ZonalKey(name, zone)) return v, mc.Observe(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instances.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instances.go index aa31f5e3a..0d4dc6314 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instances.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instances.go @@ -21,7 +21,6 @@ import ( "fmt" "net" "net/http" - "strconv" "strings" "time" @@ -35,6 +34,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" @@ -100,12 +100,15 @@ func (gce *GCECloud) NodeAddresses(_ context.Context, _ types.NodeName) ([]v1.No // NodeAddressesByProviderID will not be called from the node that is requesting this ID. // i.e. metadata service and other local methods cannot be used here func (gce *GCECloud) NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + _, zone, name, err := splitProviderID(providerID) if err != nil { return []v1.NodeAddress{}, err } - instance, err := gce.c.Instances().Get(context.Background(), meta.ZonalKey(canonicalizeInstanceName(name), zone)) + instance, err := gce.c.Instances().Get(ctx, meta.ZonalKey(canonicalizeInstanceName(name), zone)) if err != nil { return []v1.NodeAddress{}, fmt.Errorf("error while querying for providerID %q: %v", providerID, err) } @@ -142,6 +145,11 @@ func (gce *GCECloud) instanceByProviderID(providerID string) (*gceInstance, erro return instance, nil } +// InstanceShutdownByProviderID returns true if the instance is in safe state to detach volumes +func (gce *GCECloud) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, cloudprovider.NotImplemented +} + // InstanceTypeByProviderID returns the cloudprovider instance type of the node // with the specified unique providerID This method will not be called from the // node that is requesting this ID. i.e. metadata service and other local @@ -155,27 +163,6 @@ func (gce *GCECloud) InstanceTypeByProviderID(ctx context.Context, providerID st return instance.Type, nil } -// ExternalID returns the cloud provider ID of the node with the specified NodeName (deprecated). -func (gce *GCECloud) ExternalID(ctx context.Context, nodeName types.NodeName) (string, error) { - instanceName := mapNodeNameToInstanceName(nodeName) - if gce.useMetadataServer { - // Use metadata, if possible, to fetch ID. See issue #12000 - if gce.isCurrentInstance(instanceName) { - externalInstanceID, err := getCurrentExternalIDViaMetadata() - if err == nil { - return externalInstanceID, nil - } - } - } - - // Fallback to GCE API call if metadata server fails to retrieve ID - inst, err := gce.getInstanceByName(instanceName) - if err != nil { - return "", err - } - return strconv.FormatUint(inst.ID, 10), nil -} - // InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. func (gce *GCECloud) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) { @@ -229,8 +216,11 @@ func (gce *GCECloud) InstanceType(ctx context.Context, nodeName types.NodeName) } func (gce *GCECloud) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + return wait.Poll(2*time.Second, 30*time.Second, func() (bool, error) { - project, err := gce.c.Projects().Get(context.Background(), gce.projectID) + project, err := gce.c.Projects().Get(ctx, gce.projectID) if err != nil { glog.Errorf("Could not get project: %v", err) return false, nil @@ -261,7 +251,7 @@ func (gce *GCECloud) AddSSHKeyToAllInstances(ctx context.Context, user string, k } mc := newInstancesMetricContext("add_ssh_key", "") - err = gce.c.Projects().SetCommonInstanceMetadata(context.Background(), gce.projectID, project.CommonInstanceMetadata) + err = gce.c.Projects().SetCommonInstanceMetadata(ctx, gce.projectID, project.CommonInstanceMetadata) mc.Observe(err) if err != nil { @@ -301,9 +291,12 @@ func (gce *GCECloud) GetAllCurrentZones() (sets.String, error) { // // TODO: this should be removed from the cloud provider. func (gce *GCECloud) GetAllZonesFromCloudProvider() (sets.String, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + zones := sets.NewString() for _, zone := range gce.managedZones { - instances, err := gce.c.Instances().List(context.Background(), zone, filter.None) + instances, err := gce.c.Instances().List(ctx, zone, filter.None) if err != nil { return sets.NewString(), err } @@ -316,15 +309,21 @@ func (gce *GCECloud) GetAllZonesFromCloudProvider() (sets.String, error) { // InsertInstance creates a new instance on GCP func (gce *GCECloud) InsertInstance(project string, zone string, i *compute.Instance) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newInstancesMetricContext("create", zone) - return mc.Observe(gce.c.Instances().Insert(context.Background(), meta.ZonalKey(i.Name, zone), i)) + return mc.Observe(gce.c.Instances().Insert(ctx, meta.ZonalKey(i.Name, zone), i)) } // ListInstanceNames returns a string of instance names separated by spaces. // This method should only be used for e2e testing. // TODO: remove this method. func (gce *GCECloud) ListInstanceNames(project, zone string) (string, error) { - l, err := gce.c.Instances().List(context.Background(), zone, filter.None) + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + l, err := gce.c.Instances().List(ctx, zone, filter.None) if err != nil { return "", err } @@ -337,7 +336,10 @@ func (gce *GCECloud) ListInstanceNames(project, zone string) (string, error) { // DeleteInstance deletes an instance specified by project, zone, and name func (gce *GCECloud) DeleteInstance(project, zone, name string) error { - return gce.c.Instances().Delete(context.Background(), meta.ZonalKey(name, zone)) + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + return gce.c.Instances().Delete(ctx, meta.ZonalKey(name, zone)) } // Implementation of Instances.CurrentNodeName @@ -349,6 +351,9 @@ func (gce *GCECloud) CurrentNodeName(ctx context.Context, hostname string) (type // `node` for allocation to pods. Returns a list of the form // "/". func (gce *GCECloud) AliasRanges(nodeName types.NodeName) (cidrs []string, err error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + var instance *gceInstance instance, err = gce.getInstanceByName(mapNodeNameToInstanceName(nodeName)) if err != nil { @@ -356,7 +361,7 @@ func (gce *GCECloud) AliasRanges(nodeName types.NodeName) (cidrs []string, err e } var res *computebeta.Instance - res, err = gce.c.BetaInstances().Get(context.Background(), meta.ZonalKey(instance.Name, lastComponent(instance.Zone))) + res, err = gce.c.BetaInstances().Get(ctx, meta.ZonalKey(instance.Name, lastComponent(instance.Zone))) if err != nil { return } @@ -372,12 +377,14 @@ func (gce *GCECloud) AliasRanges(nodeName types.NodeName) (cidrs []string, err e // AddAliasToInstance adds an alias to the given instance from the named // secondary range. func (gce *GCECloud) AddAliasToInstance(nodeName types.NodeName, alias *net.IPNet) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() v1instance, err := gce.getInstanceByName(mapNodeNameToInstanceName(nodeName)) if err != nil { return err } - instance, err := gce.c.BetaInstances().Get(context.Background(), meta.ZonalKey(v1instance.Name, lastComponent(v1instance.Zone))) + instance, err := gce.c.BetaInstances().Get(ctx, meta.ZonalKey(v1instance.Name, lastComponent(v1instance.Zone))) if err != nil { return err } @@ -400,13 +407,16 @@ func (gce *GCECloud) AddAliasToInstance(nodeName types.NodeName, alias *net.IPNe }) mc := newInstancesMetricContext("add_alias", v1instance.Zone) - err = gce.c.BetaInstances().UpdateNetworkInterface(context.Background(), meta.ZonalKey(instance.Name, lastComponent(instance.Zone)), iface.Name, iface) + err = gce.c.BetaInstances().UpdateNetworkInterface(ctx, meta.ZonalKey(instance.Name, lastComponent(instance.Zone)), iface.Name, iface) return mc.Observe(err) } // Gets the named instances, returning cloudprovider.InstanceNotFound if any // instance is not found func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + found := map[string]*gceInstance{} remaining := len(names) @@ -424,7 +434,7 @@ func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error) if remaining == 0 { break } - instances, err := gce.c.Instances().List(context.Background(), zone, filter.Regexp("name", nodeInstancePrefix+".*")) + instances, err := gce.c.Instances().List(ctx, zone, filter.Regexp("name", nodeInstancePrefix+".*")) if err != nil { return nil, err } @@ -488,9 +498,12 @@ func (gce *GCECloud) getInstanceByName(name string) (*gceInstance, error) { } func (gce *GCECloud) getInstanceFromProjectInZoneByName(project, zone, name string) (*gceInstance, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + name = canonicalizeInstanceName(name) mc := newInstancesMetricContext("get", zone) - res, err := gce.c.Instances().Get(context.Background(), meta.ZonalKey(name, zone)) + res, err := gce.c.Instances().Get(ctx, meta.ZonalKey(name, zone)) mc.Observe(err) if err != nil { return nil, err @@ -516,14 +529,6 @@ func getInstanceIDViaMetadata() (string, error) { return parts[0], nil } -func getCurrentExternalIDViaMetadata() (string, error) { - externalID, err := metadata.Get("instance/id") - if err != nil { - return "", fmt.Errorf("couldn't get external ID: %v", err) - } - return externalID, nil -} - func getCurrentMachineTypeViaMetadata() (string, error) { mType, err := metadata.Get("instance/machine-type") if err != nil { @@ -557,6 +562,9 @@ func (gce *GCECloud) isCurrentInstance(instanceID string) bool { // format of the host names in the cluster. Only use it as a fallback if // gce.nodeTags is unspecified func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + // TODO: We could store the tags in gceInstance, so we could have already fetched it hostNamesByZone := make(map[string]map[string]bool) // map of zones -> map of names -> bool (for easy lookup) nodeInstancePrefix := gce.nodeInstancePrefix @@ -581,7 +589,7 @@ func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) { filt = filter.Regexp("name", nodeInstancePrefix+".*") } for zone, hostNames := range hostNamesByZone { - instances, err := gce.c.Instances().List(context.Background(), zone, filt) + instances, err := gce.c.Instances().List(ctx, zone, filt) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go index 587de3524..ac53fa015 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go @@ -17,8 +17,9 @@ limitations under the License. package gce import ( + "context" "fmt" - "net/http" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -26,104 +27,48 @@ import ( computealpha "google.golang.org/api/compute/v0.alpha" compute "google.golang.org/api/compute/v1" + ga "google.golang.org/api/compute/v1" "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock" - kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + netsets "k8s.io/kubernetes/pkg/util/net/sets" ) -const ( - projectID = "test-project" - region = "us-central1" - zoneName = "us-central1-b" - nodeName = "test-node-1" - clusterName = "Test Cluster Name" - clusterID = "test-cluster-id" - serviceName = "" -) - -var apiService = &v1.Service{ - Spec: v1.ServiceSpec{ - SessionAffinity: v1.ServiceAffinityClientIP, - Type: v1.ServiceTypeClusterIP, - Ports: []v1.ServicePort{{Protocol: v1.ProtocolTCP, Port: int32(123)}}, - }, -} - -type fakeRoundTripper struct{} - -func (*fakeRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { - return nil, fmt.Errorf("err: test used fake http client") -} - -func fakeGCECloud() (*GCECloud, error) { - c := &http.Client{Transport: &fakeRoundTripper{}} - - service, err := compute.New(c) - if err != nil { - return nil, err - } - - // Used in disk unit tests - fakeManager := newFakeManager(projectID, region) - zonesWithNodes := createNodeZones([]string{zoneName}) - - alphaFeatureGate, err := NewAlphaFeatureGate([]string{}) - if err != nil { - return nil, err - } - - gce := &GCECloud{ - region: region, - service: service, - manager: fakeManager, - managedZones: []string{zoneName}, - projectID: projectID, - networkProjectID: projectID, - AlphaFeatureGate: alphaFeatureGate, - nodeZones: zonesWithNodes, - nodeInformerSynced: func() bool { return true }, - } - - cloud := cloud.NewMockGCE(&gceProjectRouter{gce}) - cloud.MockTargetPools.AddInstanceHook = mock.AddInstanceHook - cloud.MockTargetPools.RemoveInstanceHook = mock.RemoveInstanceHook - cloud.MockForwardingRules.InsertHook = mock.InsertFwdRuleHook - cloud.MockAddresses.InsertHook = mock.InsertAddressHook - cloud.MockAlphaAddresses.InsertHook = mock.InsertAlphaAddressHook - - gce.c = cloud - - return gce, nil -} - func TestEnsureStaticIP(t *testing.T) { - gce, err := fakeGCECloud() + t.Parallel() + + gce, err := fakeGCECloud(DefaultTestClusterValues()) require.NoError(t, err) ipName := "some-static-ip" + serviceName := "some-service" // First ensure call - ip, existed, err := ensureStaticIP(gce, ipName, serviceName, region, "", cloud.NetworkTierDefault) + ip, existed, err := ensureStaticIP(gce, ipName, serviceName, gce.region, "", cloud.NetworkTierDefault) if err != nil || existed { - t.Fatalf(`ensureStaticIP(%v, %v, %v, %v, "") = %v, %v, %v; want valid ip, false, nil`, gce, ipName, serviceName, region, ip, existed, err) + t.Fatalf(`ensureStaticIP(%v, %v, %v, %v, "") = %v, %v, %v; want valid ip, false, nil`, gce, ipName, serviceName, gce.region, ip, existed, err) } // Second ensure call var ipPrime string - ipPrime, existed, err = ensureStaticIP(gce, ipName, serviceName, region, ip, cloud.NetworkTierDefault) + ipPrime, existed, err = ensureStaticIP(gce, ipName, serviceName, gce.region, ip, cloud.NetworkTierDefault) if err != nil || !existed || ip != ipPrime { - t.Fatalf(`ensureStaticIP(%v, %v, %v, %v, %v) = %v, %v, %v; want %v, true, nil`, gce, ipName, serviceName, region, ip, ipPrime, existed, err, ip) + t.Fatalf(`ensureStaticIP(%v, %v, %v, %v, %v) = %v, %v, %v; want %v, true, nil`, gce, ipName, serviceName, gce.region, ip, ipPrime, existed, err, ip) } } func TestEnsureStaticIPWithTier(t *testing.T) { - s, err := fakeGCECloud() + t.Parallel() + + s, err := fakeGCECloud(DefaultTestClusterValues()) require.NoError(t, err) + serviceName := "some-service" + for desc, tc := range map[string]struct { name string netTier cloud.NetworkTier @@ -141,13 +86,13 @@ func TestEnsureStaticIPWithTier(t *testing.T) { }, } { t.Run(desc, func(t *testing.T) { - ip, existed, err := ensureStaticIP(s, tc.name, serviceName, region, "", tc.netTier) + ip, existed, err := ensureStaticIP(s, tc.name, serviceName, s.region, "", tc.netTier) assert.NoError(t, err) assert.False(t, existed) assert.NotEqual(t, ip, "") // Get the Address from the fake address service and verify that the tier // is set correctly. - alphaAddr, err := s.GetAlphaRegionAddress(tc.name, region) + alphaAddr, err := s.GetAlphaRegionAddress(tc.name, s.region) require.NoError(t, err) assert.Equal(t, tc.expected, alphaAddr.NetworkTier) }) @@ -155,6 +100,8 @@ func TestEnsureStaticIPWithTier(t *testing.T) { } func TestVerifyRequestedIP(t *testing.T) { + t.Parallel() + lbRef := "test-lb" for desc, tc := range map[string]struct { @@ -196,13 +143,13 @@ func TestVerifyRequestedIP(t *testing.T) { }, } { t.Run(desc, func(t *testing.T) { - s, err := fakeGCECloud() + s, err := fakeGCECloud(DefaultTestClusterValues()) require.NoError(t, err) for _, addr := range tc.addrList { - s.ReserveAlphaRegionAddress(addr, region) + s.ReserveAlphaRegionAddress(addr, s.region) } - isUserOwnedIP, err := verifyUserRequestedIP(s, region, tc.requestedIP, tc.fwdRuleIP, lbRef, tc.netTier) + isUserOwnedIP, err := verifyUserRequestedIP(s, s.region, tc.requestedIP, tc.fwdRuleIP, lbRef, tc.netTier) assert.Equal(t, tc.expectErr, err != nil, fmt.Sprintf("err: %v", err)) assert.Equal(t, tc.expectUserOwned, isUserOwnedIP) }) @@ -210,10 +157,14 @@ func TestVerifyRequestedIP(t *testing.T) { } func TestCreateForwardingRuleWithTier(t *testing.T) { + t.Parallel() + // Common variables among the tests. ports := []v1.ServicePort{{Name: "foo", Protocol: v1.ProtocolTCP, Port: int32(123)}} target := "test-target-pool" - svcName := "foo-svc" + vals := DefaultTestClusterValues() + serviceName := "foo-svc" + baseLinkUrl := "https://www.googleapis.com/compute/%v/projects/%v/regions/%v/forwardingRules/%v" for desc, tc := range map[string]struct { @@ -230,7 +181,7 @@ func TestCreateForwardingRuleWithTier(t *testing.T) { PortRange: "123-123", Target: target, NetworkTier: "PREMIUM", - SelfLink: fmt.Sprintf(baseLinkUrl, "v1", projectID, region, "lb-1"), + SelfLink: fmt.Sprintf(baseLinkUrl, "v1", vals.ProjectID, vals.Region, "lb-1"), }, }, "Standard tier": { @@ -243,21 +194,21 @@ func TestCreateForwardingRuleWithTier(t *testing.T) { PortRange: "123-123", Target: target, NetworkTier: "STANDARD", - SelfLink: fmt.Sprintf(baseLinkUrl, "alpha", projectID, region, "lb-2"), + SelfLink: fmt.Sprintf(baseLinkUrl, "alpha", vals.ProjectID, vals.Region, "lb-2"), }, }, } { t.Run(desc, func(t *testing.T) { - s, err := fakeGCECloud() + s, err := fakeGCECloud(vals) require.NoError(t, err) lbName := tc.expectedRule.Name ipAddr := tc.expectedRule.IPAddress - err = createForwardingRule(s, lbName, svcName, region, ipAddr, target, ports, tc.netTier) + err = createForwardingRule(s, lbName, serviceName, s.region, ipAddr, target, ports, tc.netTier) assert.NoError(t, err) - alphaRule, err := s.GetAlphaRegionForwardingRule(lbName, region) + alphaRule, err := s.GetAlphaRegionForwardingRule(lbName, s.region) assert.NoError(t, err) assert.Equal(t, tc.expectedRule, alphaRule) }) @@ -265,9 +216,11 @@ func TestCreateForwardingRuleWithTier(t *testing.T) { } func TestDeleteAddressWithWrongTier(t *testing.T) { + t.Parallel() + lbRef := "test-lb" - s, err := fakeGCECloud() + s, err := fakeGCECloud(DefaultTestClusterValues()) require.NoError(t, err) // Enable the cloud.NetworkTiers feature @@ -304,17 +257,17 @@ func TestDeleteAddressWithWrongTier(t *testing.T) { } { t.Run(desc, func(t *testing.T) { for _, addr := range tc.addrList { - s.ReserveAlphaRegionAddress(addr, region) + s.ReserveAlphaRegionAddress(addr, s.region) } // Sanity check to ensure we inject the right address. - _, err = s.GetRegionAddress(tc.addrName, region) + _, err = s.GetRegionAddress(tc.addrName, s.region) require.NoError(t, err) - err = deleteAddressWithWrongTier(s, region, tc.addrName, lbRef, tc.netTier) + err = deleteAddressWithWrongTier(s, s.region, tc.addrName, lbRef, tc.netTier) assert.NoError(t, err) // Check whether the address still exists. - _, err = s.GetRegionAddress(tc.addrName, region) + _, err = s.GetRegionAddress(tc.addrName, s.region) if tc.expectDelete { assert.True(t, isNotFound(err)) } else { @@ -324,56 +277,8 @@ func TestDeleteAddressWithWrongTier(t *testing.T) { } } -func createAndInsertNodes(gce *GCECloud, nodeNames []string) ([]*v1.Node, error) { - nodes := []*v1.Node{} - - for _, name := range nodeNames { - // Inserting the same node name twice causes an error - here we check if - // the instance exists already before insertion. - // TestUpdateExternalLoadBalancer inserts a new node, and relies on an older - // node to already have been inserted. - instance, _ := gce.getInstanceByName(name) - - if instance == nil { - err := gce.InsertInstance( - projectID, - zoneName, - &compute.Instance{ - Name: name, - Tags: &compute.Tags{ - Items: []string{name}, - }, - }, - ) - if err != nil { - return nodes, err - } - } - - nodes = append( - nodes, - &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Labels: map[string]string{ - kubeletapis.LabelHostname: name, - }, - }, - Status: v1.NodeStatus{ - NodeInfo: v1.NodeSystemInfo{ - KubeProxyVersion: "v1.7.2", - }, - }, - }, - ) - - } - - return nodes, nil -} - -func createExternalLoadBalancer(gce *GCECloud) (*v1.LoadBalancerStatus, error) { - nodes, err := createAndInsertNodes(gce, []string{nodeName}) +func createExternalLoadBalancer(gce *GCECloud, svc *v1.Service, nodeNames []string, clusterName, clusterID, zoneName string) (*v1.LoadBalancerStatus, error) { + nodes, err := createAndInsertNodes(gce, nodeNames, zoneName) if err != nil { return nil, err } @@ -381,174 +286,133 @@ func createExternalLoadBalancer(gce *GCECloud) (*v1.LoadBalancerStatus, error) { return gce.ensureExternalLoadBalancer( clusterName, clusterID, - apiService, + svc, nil, nodes, ) } func TestEnsureExternalLoadBalancer(t *testing.T) { - gce, err := fakeGCECloud() - require.NoError(t, err) - - status, err := createExternalLoadBalancer(gce) - assert.NoError(t, err) - assert.NotEmpty(t, status.Ingress) - - lbName := cloudprovider.GetLoadBalancerName(apiService) - hcName := MakeNodesHealthCheckName(clusterID) - - // Check that Firewalls are created for the LoadBalancer and the HealthCheck - fwNames := []string{ - MakeFirewallName(lbName), - MakeHealthCheckFirewallName(clusterID, hcName, true), - } + t.Parallel() - for _, fwName := range fwNames { - firewall, err := gce.GetFirewall(fwName) - require.NoError(t, err) - assert.Equal(t, []string{nodeName}, firewall.TargetTags) - assert.NotEmpty(t, firewall.SourceRanges) - } + vals := DefaultTestClusterValues() + nodeNames := []string{"test-node-1"} - // Check that TargetPool is Created - pool, err := gce.GetTargetPool(lbName, region) + gce, err := fakeGCECloud(vals) require.NoError(t, err) - assert.Equal(t, lbName, pool.Name) - assert.NotEmpty(t, pool.HealthChecks) - assert.Equal(t, 1, len(pool.Instances)) - // Check that HealthCheck is created - healthcheck, err := gce.GetHttpHealthCheck(hcName) - require.NoError(t, err) - assert.Equal(t, hcName, healthcheck.Name) + svc := fakeLoadbalancerService("") + status, err := createExternalLoadBalancer(gce, svc, nodeNames, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) + assert.NotEmpty(t, status.Ingress) - // Check that ForwardingRule is created - fwdRule, err := gce.GetRegionForwardingRule(lbName, region) - require.NoError(t, err) - assert.Equal(t, lbName, fwdRule.Name) - assert.Equal(t, "TCP", fwdRule.IPProtocol) - assert.Equal(t, "123-123", fwdRule.PortRange) + assertExternalLbResources(t, gce, svc, vals, nodeNames) } func TestUpdateExternalLoadBalancer(t *testing.T) { - gce, err := fakeGCECloud() + t.Parallel() + + vals := DefaultTestClusterValues() + nodeName := "test-node-1" + + gce, err := fakeGCECloud((DefaultTestClusterValues())) require.NoError(t, err) - _, err = createExternalLoadBalancer(gce) + svc := fakeLoadbalancerService("") + _, err = createExternalLoadBalancer(gce, svc, []string{nodeName}, vals.ClusterName, vals.ClusterID, vals.ZoneName) assert.NoError(t, err) newNodeName := "test-node-2" - newNodes, err := createAndInsertNodes(gce, []string{nodeName, newNodeName}) + newNodes, err := createAndInsertNodes(gce, []string{nodeName, newNodeName}, vals.ZoneName) assert.NoError(t, err) // Add the new node, then check that it is properly added to the TargetPool - err = gce.updateExternalLoadBalancer(clusterName, apiService, newNodes) + err = gce.updateExternalLoadBalancer("", svc, newNodes) assert.NoError(t, err) - lbName := cloudprovider.GetLoadBalancerName(apiService) + lbName := cloudprovider.GetLoadBalancerName(svc) - pool, err := gce.GetTargetPool(lbName, region) + pool, err := gce.GetTargetPool(lbName, gce.region) require.NoError(t, err) // TODO: when testify is updated to v1.2.0+, use ElementsMatch instead assert.Contains( t, pool.Instances, - fmt.Sprintf("/zones/%s/instances/%s", zoneName, nodeName), + fmt.Sprintf("/zones/%s/instances/%s", vals.ZoneName, nodeName), ) assert.Contains( t, pool.Instances, - fmt.Sprintf("/zones/%s/instances/%s", zoneName, newNodeName), + fmt.Sprintf("/zones/%s/instances/%s", vals.ZoneName, newNodeName), ) - newNodes, err = createAndInsertNodes(gce, []string{nodeName}) + newNodes, err = createAndInsertNodes(gce, []string{nodeName}, vals.ZoneName) assert.NoError(t, err) // Remove the new node by calling updateExternalLoadBalancer with a list // only containing the old node, and test that the TargetPool no longer // contains the new node. - err = gce.updateExternalLoadBalancer(clusterName, apiService, newNodes) + err = gce.updateExternalLoadBalancer(vals.ClusterName, svc, newNodes) assert.NoError(t, err) - pool, err = gce.GetTargetPool(lbName, region) + pool, err = gce.GetTargetPool(lbName, gce.region) require.NoError(t, err) assert.Equal( t, - []string{fmt.Sprintf("/zones/%s/instances/%s", zoneName, nodeName)}, + []string{fmt.Sprintf("/zones/%s/instances/%s", vals.ZoneName, nodeName)}, pool.Instances, ) } func TestEnsureExternalLoadBalancerDeleted(t *testing.T) { - gce, err := fakeGCECloud() + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) require.NoError(t, err) - _, err = createExternalLoadBalancer(gce) + svc := fakeLoadbalancerService("") + _, err = createExternalLoadBalancer(gce, svc, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) assert.NoError(t, err) - err = gce.ensureExternalLoadBalancerDeleted(clusterName, clusterID, apiService) + err = gce.ensureExternalLoadBalancerDeleted(vals.ClusterName, vals.ClusterID, svc) assert.NoError(t, err) - lbName := cloudprovider.GetLoadBalancerName(apiService) - hcName := MakeNodesHealthCheckName(clusterID) - - // Check that Firewalls are deleted for the LoadBalancer and the HealthCheck - fwNames := []string{ - MakeFirewallName(lbName), - MakeHealthCheckFirewallName(clusterID, hcName, true), - } - - for _, fwName := range fwNames { - firewall, err := gce.GetFirewall(fwName) - require.Error(t, err) - assert.Nil(t, firewall) - } - - // Check that TargetPool is deleted - pool, err := gce.GetTargetPool(lbName, region) - require.Error(t, err) - assert.Nil(t, pool) - - // Check that HealthCheck is deleted - healthcheck, err := gce.GetHttpHealthCheck(hcName) - require.Error(t, err) - assert.Nil(t, healthcheck) - - // Check forwarding rule is deleted - fwdRule, err := gce.GetRegionForwardingRule(lbName, region) - require.Error(t, err) - assert.Nil(t, fwdRule) + assertExternalLbResourcesDeleted(t, gce, svc, vals, true) } func TestLoadBalancerWrongTierResourceDeletion(t *testing.T) { - gce, err := fakeGCECloud() + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) require.NoError(t, err) // Enable the cloud.NetworkTiers feature gce.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true - apiService.Annotations = map[string]string{NetworkTierAnnotationKey: "Premium"} + svc := fakeLoadbalancerService("") + svc.Annotations = map[string]string{NetworkTierAnnotationKey: "Premium"} // cloud.NetworkTier defaults to Premium - desiredTier, err := gce.getServiceNetworkTier(apiService) + desiredTier, err := gce.getServiceNetworkTier(svc) require.NoError(t, err) assert.Equal(t, cloud.NetworkTierPremium, desiredTier) - lbName := cloudprovider.GetLoadBalancerName(apiService) - serviceName := types.NamespacedName{Namespace: apiService.Namespace, Name: apiService.Name} + lbName := cloudprovider.GetLoadBalancerName(svc) + serviceName := types.NamespacedName{Namespace: svc.Namespace, Name: svc.Name} // create ForwardingRule and Address with the wrong tier err = createForwardingRule( gce, lbName, serviceName.String(), - region, + gce.region, "", gce.targetPoolURL(lbName), - apiService.Spec.Ports, + svc.Spec.Ports, cloud.NetworkTierStandard, ) require.NoError(t, err) @@ -559,18 +423,613 @@ func TestLoadBalancerWrongTierResourceDeletion(t *testing.T) { NetworkTier: cloud.NetworkTierStandard.ToGCEValue(), } - err = gce.ReserveAlphaRegionAddress(addressObj, region) + err = gce.ReserveAlphaRegionAddress(addressObj, gce.region) require.NoError(t, err) - _, err = createExternalLoadBalancer(gce) + _, err = createExternalLoadBalancer(gce, svc, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) require.NoError(t, err) // Expect forwarding rule tier to not be Standard - tier, err := gce.getNetworkTierFromForwardingRule(lbName, region) + tier, err := gce.getNetworkTierFromForwardingRule(lbName, gce.region) assert.NoError(t, err) assert.Equal(t, cloud.NetworkTierDefault.ToGCEValue(), tier) // Expect address to be deleted - _, err = gce.GetRegionAddress(lbName, region) + _, err = gce.GetRegionAddress(lbName, gce.region) assert.True(t, isNotFound(err)) } + +func TestEnsureExternalLoadBalancerFailsIfInvalidNetworkTier(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + nodeNames := []string{"test-node-1"} + + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + require.NoError(t, err) + + // Enable the cloud.NetworkTiers feature + gce.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true + svc := fakeLoadbalancerService("") + svc.Annotations = map[string]string{NetworkTierAnnotationKey: wrongTier} + + _, err = gce.ensureExternalLoadBalancer(vals.ClusterName, vals.ClusterID, svc, nil, nodes) + require.Error(t, err) + assert.EqualError(t, err, errStrUnsupportedTier) +} + +func TestEnsureExternalLoadBalancerFailsWithNoNodes(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + svc := fakeLoadbalancerService("") + _, err = gce.ensureExternalLoadBalancer(vals.ClusterName, vals.ClusterID, svc, nil, []*v1.Node{}) + require.Error(t, err) + assert.EqualError(t, err, errStrLbNoHosts) +} + +func TestForwardingRuleNeedsUpdate(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + status, err := createExternalLoadBalancer(gce, fakeLoadbalancerService(""), []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + require.NotNil(t, status) + require.NoError(t, err) + + svc := fakeLoadbalancerService("") + lbName := cloudprovider.GetLoadBalancerName(svc) + ipAddr := status.Ingress[0].IP + + lbIP := svc.Spec.LoadBalancerIP + wrongPorts := []v1.ServicePort{svc.Spec.Ports[0]} + wrongPorts[0].Port = wrongPorts[0].Port + 1 + + wrongProtocolPorts := []v1.ServicePort{svc.Spec.Ports[0]} + wrongProtocolPorts[0].Protocol = v1.ProtocolUDP + + for desc, tc := range map[string]struct { + lbIP string + ports []v1.ServicePort + exists bool + needsUpdate bool + expectIpAddr string + expectError bool + }{ + "When the loadBalancerIP does not equal the FwdRule IP address.": { + lbIP: "1.2.3.4", + ports: svc.Spec.Ports, + exists: true, + needsUpdate: true, + expectIpAddr: ipAddr, + expectError: false, + }, + "When loadBalancerPortRange returns an error.": { + lbIP: lbIP, + ports: []v1.ServicePort{}, + exists: true, + needsUpdate: false, + expectIpAddr: "", + expectError: true, + }, + "When portRange not equals to the forwardingRule port range.": { + lbIP: lbIP, + ports: wrongPorts, + exists: true, + needsUpdate: true, + expectIpAddr: ipAddr, + expectError: false, + }, + "When the ports protocol does not equal the ForwardingRuel IP Protocol.": { + lbIP: lbIP, + ports: wrongProtocolPorts, + exists: true, + needsUpdate: true, + expectIpAddr: ipAddr, + expectError: false, + }, + "When basic workflow.": { + lbIP: lbIP, + ports: svc.Spec.Ports, + exists: true, + needsUpdate: false, + expectIpAddr: ipAddr, + expectError: false, + }, + } { + t.Run(desc, func(t *testing.T) { + exists, needsUpdate, ipAddress, err := gce.forwardingRuleNeedsUpdate(lbName, vals.Region, tc.lbIP, tc.ports) + assert.Equal(t, tc.exists, exists, "'exists' didn't return as expected "+desc) + assert.Equal(t, tc.needsUpdate, needsUpdate, "'needsUpdate' didn't return as expected "+desc) + assert.Equal(t, tc.expectIpAddr, ipAddress, "'ipAddress' didn't return as expected "+desc) + if tc.expectError { + assert.Error(t, err, "Should returns an error "+desc) + } else { + assert.NoError(t, err, "Should not returns an error "+desc) + } + }) + } +} + +func TestTargetPoolNeedsRecreation(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + svc := fakeLoadbalancerService("") + serviceName := svc.ObjectMeta.Name + lbName := cloudprovider.GetLoadBalancerName(svc) + nodes, err := createAndInsertNodes(gce, []string{"test-node-1"}, vals.ZoneName) + require.NoError(t, err) + hostNames := nodeNames(nodes) + hosts, err := gce.getInstancesByNames(hostNames) + + var instances []string + for _, host := range hosts { + instances = append(instances, host.makeComparableHostPath()) + } + pool := &compute.TargetPool{ + Name: lbName, + Description: fmt.Sprintf(`{"kubernetes.io/service-name":"%s"}`, serviceName), + Instances: instances, + SessionAffinity: translateAffinityType(v1.ServiceAffinityNone), + } + err = gce.CreateTargetPool(pool, vals.Region) + require.NoError(t, err) + + c := gce.c.(*cloud.MockGCE) + c.MockTargetPools.GetHook = mock.GetTargetPoolInternalErrHook + exists, needsRecreation, err := gce.targetPoolNeedsRecreation(lbName, vals.Region, v1.ServiceAffinityNone) + assert.True(t, exists) + assert.False(t, needsRecreation) + require.NotNil(t, err) + assert.True(t, strings.HasPrefix(err.Error(), errPrefixGetTargetPool)) + c.MockTargetPools.GetHook = nil + + exists, needsRecreation, err = gce.targetPoolNeedsRecreation(lbName, vals.Region, v1.ServiceAffinityClientIP) + assert.True(t, exists) + assert.True(t, needsRecreation) + assert.NoError(t, err) + + exists, needsRecreation, err = gce.targetPoolNeedsRecreation(lbName, vals.Region, v1.ServiceAffinityNone) + assert.True(t, exists) + assert.False(t, needsRecreation) + assert.NoError(t, err) +} + +func TestFirewallNeedsUpdate(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + svc := fakeLoadbalancerService("") + status, err := createExternalLoadBalancer(gce, svc, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + require.NotNil(t, status) + require.NoError(t, err) + svcName := "/" + svc.ObjectMeta.Name + region := vals.Region + + ipAddr := status.Ingress[0].IP + lbName := cloudprovider.GetLoadBalancerName(svc) + + ipnet, err := netsets.ParseIPNets("0.0.0.0/0") + require.NoError(t, err) + + wrongIpnet, err := netsets.ParseIPNets("1.0.0.0/10") + require.NoError(t, err) + + fw, err := gce.GetFirewall(MakeFirewallName(lbName)) + require.NoError(t, err) + + for desc, tc := range map[string]struct { + lbName string + ipAddr string + ports []v1.ServicePort + ipnet netsets.IPNet + fwIPProtocol string + getHook func(context.Context, *meta.Key, *cloud.MockFirewalls) (bool, *ga.Firewall, error) + sourceRange string + exists bool + needsUpdate bool + hasErr bool + }{ + "When response is a Non-400 HTTP error.": { + lbName: lbName, + ipAddr: ipAddr, + ports: svc.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: mock.GetFirewallsUnauthorizedErrHook, + sourceRange: fw.SourceRanges[0], + exists: false, + needsUpdate: false, + hasErr: true, + }, + "When given a wrong description.": { + lbName: lbName, + ipAddr: "", + ports: svc.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When IPProtocol doesn't match.": { + lbName: lbName, + ipAddr: ipAddr, + ports: svc.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "usps", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When the ports don't match.": { + lbName: lbName, + ipAddr: ipAddr, + ports: []v1.ServicePort{{Protocol: v1.ProtocolTCP, Port: int32(666)}}, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When parseIPNets returns an error.": { + lbName: lbName, + ipAddr: ipAddr, + ports: svc.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: "badSourceRange", + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When the source ranges are not equal.": { + lbName: lbName, + ipAddr: ipAddr, + ports: svc.Spec.Ports, + ipnet: wrongIpnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When basic flow without exceptions.": { + lbName: lbName, + ipAddr: ipAddr, + ports: svc.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: false, + hasErr: false, + }, + } { + t.Run(desc, func(t *testing.T) { + fw, err = gce.GetFirewall(MakeFirewallName(tc.lbName)) + fw.Allowed[0].IPProtocol = tc.fwIPProtocol + fw, err = gce.GetFirewall(MakeFirewallName(tc.lbName)) + require.Equal(t, fw.Allowed[0].IPProtocol, tc.fwIPProtocol) + + trueSourceRange := fw.SourceRanges[0] + fw.SourceRanges[0] = tc.sourceRange + fw, err = gce.GetFirewall(MakeFirewallName(lbName)) + require.Equal(t, fw.SourceRanges[0], tc.sourceRange) + + c := gce.c.(*cloud.MockGCE) + c.MockFirewalls.GetHook = tc.getHook + + exists, needsUpdate, err := gce.firewallNeedsUpdate( + tc.lbName, + svcName, + region, + tc.ipAddr, + tc.ports, + tc.ipnet) + + assert.Equal(t, tc.exists, exists, "'exists' didn't return as expected "+desc) + assert.Equal(t, tc.needsUpdate, needsUpdate, "'needsUpdate' didn't return as expected "+desc) + if tc.hasErr { + assert.Error(t, err, "Should returns an error "+desc) + } else { + assert.NoError(t, err, "Should not returns an error "+desc) + } + + c.MockFirewalls.GetHook = nil + + fw.Allowed[0].IPProtocol = "tcp" + fw.SourceRanges[0] = trueSourceRange + fw, err = gce.GetFirewall(MakeFirewallName(tc.lbName)) + require.Equal(t, fw.Allowed[0].IPProtocol, "tcp") + require.Equal(t, fw.SourceRanges[0], trueSourceRange) + + }) + } +} + +func TestDeleteWrongNetworkTieredResourcesSucceedsWhenNotFound(t *testing.T) { + t.Parallel() + + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + gce.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true + assert.Nil(t, gce.deleteWrongNetworkTieredResources("Wrong_LB_Name", "", cloud.NetworkTier(""))) +} + +func TestEnsureTargetPoolAndHealthCheck(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + nodes, err := createAndInsertNodes(gce, []string{"test-node-1"}, vals.ZoneName) + require.NoError(t, err) + svc := fakeLoadbalancerService("") + status, err := gce.ensureExternalLoadBalancer( + vals.ClusterName, + vals.ClusterID, + svc, + nil, + nodes, + ) + require.NotNil(t, status) + require.NoError(t, err) + + hostNames := nodeNames(nodes) + hosts, err := gce.getInstancesByNames(hostNames) + clusterID := vals.ClusterID + + ipAddr := status.Ingress[0].IP + lbName := cloudprovider.GetLoadBalancerName(svc) + region := vals.Region + + hcToCreate := makeHttpHealthCheck(MakeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort()) + hcToDelete := makeHttpHealthCheck(MakeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort()) + + // Apply a tag on the target pool. By verifying the change of the tag, target pool update can be ensured. + tag := "A Tag" + pool, err := gce.GetTargetPool(lbName, region) + pool.CreationTimestamp = tag + pool, err = gce.GetTargetPool(lbName, region) + require.Equal(t, tag, pool.CreationTimestamp) + err = gce.ensureTargetPoolAndHealthCheck(true, true, svc, lbName, clusterID, ipAddr, hosts, hcToCreate, hcToDelete) + assert.NoError(t, err) + pool, err = gce.GetTargetPool(lbName, region) + assert.NotEqual(t, pool.CreationTimestamp, tag) + + pool, err = gce.GetTargetPool(lbName, region) + assert.Equal(t, 1, len(pool.Instances)) + var manyNodeName [maxTargetPoolCreateInstances + 1]string + for i := 0; i < maxTargetPoolCreateInstances+1; i += 1 { + manyNodeName[i] = fmt.Sprintf("testnode_%d", i) + } + manyNodes, err := createAndInsertNodes(gce, manyNodeName[:], vals.ZoneName) + require.NoError(t, err) + manyHostNames := nodeNames(manyNodes) + manyHosts, err := gce.getInstancesByNames(manyHostNames) + err = gce.ensureTargetPoolAndHealthCheck(true, true, svc, lbName, clusterID, ipAddr, manyHosts, hcToCreate, hcToDelete) + assert.NoError(t, err) + + pool, err = gce.GetTargetPool(lbName, region) + assert.Equal(t, maxTargetPoolCreateInstances+1, len(pool.Instances)) + + err = gce.ensureTargetPoolAndHealthCheck(true, false, svc, lbName, clusterID, ipAddr, hosts, hcToCreate, hcToDelete) + assert.NoError(t, err) + pool, err = gce.GetTargetPool(lbName, region) + assert.Equal(t, 1, len(pool.Instances)) +} + +func TestCreateAndUpdateFirewallSucceedsOnXPN(t *testing.T) { + t.Parallel() + + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + vals := DefaultTestClusterValues() + + c := gce.c.(*cloud.MockGCE) + c.MockFirewalls.InsertHook = mock.InsertFirewallsUnauthorizedErrHook + c.MockFirewalls.UpdateHook = mock.UpdateFirewallsUnauthorizedErrHook + gce.onXPN = true + require.True(t, gce.OnXPN()) + + recorder := record.NewFakeRecorder(1024) + gce.eventRecorder = recorder + + svc := fakeLoadbalancerService("") + nodes, err := createAndInsertNodes(gce, []string{"test-node-1"}, vals.ZoneName) + require.NoError(t, err) + hostNames := nodeNames(nodes) + hosts, err := gce.getInstancesByNames(hostNames) + require.NoError(t, err) + ipnet, err := netsets.ParseIPNets("10.0.0.0/20") + require.NoError(t, err) + gce.createFirewall( + svc, + cloudprovider.GetLoadBalancerName(svc), + gce.region, + "A sad little firewall", + ipnet, + svc.Spec.Ports, + hosts) + require.Nil(t, err) + + msg := fmt.Sprintf("%s %s %s", v1.EventTypeNormal, eventReasonManualChange, eventMsgFirewallChange) + checkEvent(t, recorder, msg, true) + + gce.updateFirewall( + svc, + cloudprovider.GetLoadBalancerName(svc), + gce.region, + "A sad little firewall", + ipnet, + svc.Spec.Ports, + hosts) + require.Nil(t, err) + + msg = fmt.Sprintf("%s %s %s", v1.EventTypeNormal, eventReasonManualChange, eventMsgFirewallChange) + checkEvent(t, recorder, msg, true) +} + +func TestEnsureExternalLoadBalancerDeletedSucceedsOnXPN(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + _, err = createExternalLoadBalancer(gce, fakeLoadbalancerService(""), []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + require.NoError(t, err) + + c := gce.c.(*cloud.MockGCE) + c.MockFirewalls.DeleteHook = mock.DeleteFirewallsUnauthorizedErrHook + gce.onXPN = true + require.True(t, gce.OnXPN()) + + recorder := record.NewFakeRecorder(1024) + gce.eventRecorder = recorder + + svc := fakeLoadbalancerService("") + err = gce.ensureExternalLoadBalancerDeleted(vals.ClusterName, vals.ClusterID, svc) + require.NoError(t, err) + + msg := fmt.Sprintf("%s %s %s", v1.EventTypeNormal, eventReasonManualChange, eventMsgFirewallChange) + checkEvent(t, recorder, msg, true) +} + +type EnsureELBParams struct { + clusterName string + clusterID string + service *v1.Service + existingFwdRule *compute.ForwardingRule + nodes []*v1.Node +} + +// newEnsureELBParams is the constructor of EnsureELBParams. +func newEnsureELBParams(nodes []*v1.Node, svc *v1.Service) *EnsureELBParams { + vals := DefaultTestClusterValues() + return &EnsureELBParams{ + vals.ClusterName, + vals.ClusterID, + svc, + nil, + nodes, + } +} + +// TestEnsureExternalLoadBalancerErrors tests the function +// ensureExternalLoadBalancer, making sure the system won't panic when +// exceptions raised by gce. +func TestEnsureExternalLoadBalancerErrors(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + var params *EnsureELBParams + + for desc, tc := range map[string]struct { + adjustParams func(*EnsureELBParams) + injectMock func(*cloud.MockGCE) + }{ + "No hosts provided": { + adjustParams: func(params *EnsureELBParams) { + params.nodes = []*v1.Node{} + }, + }, + "Invalid node provided": { + adjustParams: func(params *EnsureELBParams) { + params.nodes = []*v1.Node{{}} + }, + }, + "Get forwarding rules failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockForwardingRules.GetHook = mock.GetForwardingRulesInternalErrHook + }, + }, + "Get addresses failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockAddresses.GetHook = mock.GetAddressesInternalErrHook + }, + }, + "Bad load balancer source range provided": { + adjustParams: func(params *EnsureELBParams) { + params.service.Spec.LoadBalancerSourceRanges = []string{"BadSourceRange"} + }, + }, + "Get firewall failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockFirewalls.GetHook = mock.GetFirewallsUnauthorizedErrHook + }, + }, + "Create firewall failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockFirewalls.InsertHook = mock.InsertFirewallsUnauthorizedErrHook + }, + }, + "Get target pool failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockTargetPools.GetHook = mock.GetTargetPoolInternalErrHook + }, + }, + "Get HTTP health checks failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockHttpHealthChecks.GetHook = mock.GetHTTPHealthChecksInternalErrHook + }, + }, + "Create target pools failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockTargetPools.InsertHook = mock.InsertTargetPoolsInternalErrHook + }, + }, + "Create forwarding rules failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockForwardingRules.InsertHook = mock.InsertForwardingRulesInternalErrHook + }, + }, + } { + t.Run(desc, func(t *testing.T) { + gce, err := fakeGCECloud(DefaultTestClusterValues()) + nodes, err := createAndInsertNodes(gce, []string{"test-node-1"}, vals.ZoneName) + require.NoError(t, err) + svc := fakeLoadbalancerService("") + params = newEnsureELBParams(nodes, svc) + if tc.adjustParams != nil { + tc.adjustParams(params) + } + if tc.injectMock != nil { + tc.injectMock(gce.c.(*cloud.MockGCE)) + } + status, err := gce.ensureExternalLoadBalancer( + params.clusterName, + params.clusterID, + params.service, + params.existingFwdRule, + params.nodes, + ) + assert.Error(t, err, "Should return an error when "+desc) + assert.Nil(t, status, "Should not return a status when "+desc) + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go index 432bb19d7..ab4fc9657 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go @@ -578,8 +578,7 @@ func shareBackendService(svc *v1.Service) bool { return GetLoadBalancerAnnotationBackendShare(svc) && !v1_service.RequestsOnlyLocalTraffic(svc) } -func backendsFromGroupLinks(igLinks []string) []*compute.Backend { - var backends []*compute.Backend +func backendsFromGroupLinks(igLinks []string) (backends []*compute.Backend) { for _, igLink := range igLinks { backends = append(backends, &compute.Backend{ Group: igLink, diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal_test.go new file mode 100644 index 000000000..d24148f20 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal_test.go @@ -0,0 +1,739 @@ +/* +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 gce + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + compute "google.golang.org/api/compute/v1" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + v1_service "k8s.io/kubernetes/pkg/api/v1/service" + "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock" +) + +func createInternalLoadBalancer(gce *GCECloud, svc *v1.Service, existingFwdRule *compute.ForwardingRule, nodeNames []string, clusterName, clusterID, zoneName string) (*v1.LoadBalancerStatus, error) { + nodes, err := createAndInsertNodes(gce, nodeNames, zoneName) + if err != nil { + return nil, err + } + + return gce.ensureInternalLoadBalancer( + clusterName, + clusterID, + svc, + existingFwdRule, + nodes, + ) +} + +func TestEnsureInternalBackendServiceUpdates(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + nodeNames := []string{"test-node-1"} + + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + svc := fakeLoadbalancerService(string(LBTypeInternal)) + lbName := cloudprovider.GetLoadBalancerName(svc) + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + igName := makeInstanceGroupName(vals.ClusterID) + igLinks, err := gce.ensureInternalInstanceGroups(igName, nodes) + require.NoError(t, err) + + sharedBackend := shareBackendService(svc) + bsName := makeBackendServiceName(lbName, vals.ClusterID, sharedBackend, cloud.SchemeInternal, "TCP", svc.Spec.SessionAffinity) + err = gce.ensureInternalBackendService(bsName, "description", svc.Spec.SessionAffinity, cloud.SchemeInternal, "TCP", igLinks, "") + require.NoError(t, err) + + // Update the Internal Backend Service with a new ServiceAffinity + err = gce.ensureInternalBackendService(bsName, "description", v1.ServiceAffinityNone, cloud.SchemeInternal, "TCP", igLinks, "") + require.NoError(t, err) + + bs, err := gce.GetRegionBackendService(bsName, gce.region) + assert.NoError(t, err) + assert.Equal(t, bs.SessionAffinity, strings.ToUpper(string(v1.ServiceAffinityNone))) +} + +func TestEnsureInternalBackendServiceGroups(t *testing.T) { + t.Parallel() + + for desc, tc := range map[string]struct { + mockModifier func(*cloud.MockGCE) + }{ + "Basic workflow": {}, + "GetRegionBackendService failed": { + mockModifier: func(c *cloud.MockGCE) { + c.MockRegionBackendServices.GetHook = mock.GetRegionBackendServicesErrHook + }, + }, + "UpdateRegionBackendServices failed": { + mockModifier: func(c *cloud.MockGCE) { + c.MockRegionBackendServices.UpdateHook = mock.UpdateRegionBackendServicesErrHook + }, + }, + } { + t.Run(desc, func(t *testing.T) { + vals := DefaultTestClusterValues() + nodeNames := []string{"test-node-1"} + + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + svc := fakeLoadbalancerService(string(LBTypeInternal)) + lbName := cloudprovider.GetLoadBalancerName(svc) + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + igName := makeInstanceGroupName(vals.ClusterID) + igLinks, err := gce.ensureInternalInstanceGroups(igName, nodes) + require.NoError(t, err) + + sharedBackend := shareBackendService(svc) + bsName := makeBackendServiceName(lbName, vals.ClusterID, sharedBackend, cloud.SchemeInternal, "TCP", svc.Spec.SessionAffinity) + + err = gce.ensureInternalBackendService(bsName, "description", svc.Spec.SessionAffinity, cloud.SchemeInternal, "TCP", igLinks, "") + require.NoError(t, err) + + // Update the BackendService with new InstanceGroups + if tc.mockModifier != nil { + tc.mockModifier(gce.c.(*cloud.MockGCE)) + } + newIGLinks := []string{"new-test-ig-1", "new-test-ig-2"} + err = gce.ensureInternalBackendServiceGroups(bsName, newIGLinks) + if tc.mockModifier != nil { + assert.Error(t, err) + return + } + assert.NoError(t, err) + + bs, err := gce.GetRegionBackendService(bsName, gce.region) + assert.NoError(t, err) + + // Check that the Backends reflect the new InstanceGroups + backends := backendsFromGroupLinks(newIGLinks) + assert.Equal(t, bs.Backends, backends) + }) + } +} + +func TestEnsureInternalLoadBalancer(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + nodeNames := []string{"test-node-1"} + + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + svc := fakeLoadbalancerService(string(LBTypeInternal)) + status, err := createInternalLoadBalancer(gce, svc, nil, nodeNames, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) + assert.NotEmpty(t, status.Ingress) + assertInternalLbResources(t, gce, svc, vals, nodeNames) +} + +func TestEnsureInternalLoadBalancerWithExistingResources(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + nodeNames := []string{"test-node-1"} + + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + svc := fakeLoadbalancerService(string(LBTypeInternal)) + + // Create the expected resources necessary for an Internal Load Balancer + nm := types.NamespacedName{Name: svc.Name, Namespace: svc.Namespace} + lbName := cloudprovider.GetLoadBalancerName(svc) + + sharedHealthCheck := !v1_service.RequestsOnlyLocalTraffic(svc) + hcName := makeHealthCheckName(lbName, vals.ClusterID, sharedHealthCheck) + hcPath, hcPort := GetNodesHealthCheckPath(), GetNodesHealthCheckPort() + existingHC := newInternalLBHealthCheck(hcName, nm, sharedHealthCheck, hcPath, hcPort) + err = gce.CreateHealthCheck(existingHC) + require.NoError(t, err) + + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + igName := makeInstanceGroupName(vals.ClusterID) + igLinks, err := gce.ensureInternalInstanceGroups(igName, nodes) + require.NoError(t, err) + + sharedBackend := shareBackendService(svc) + bsDescription := makeBackendServiceDescription(nm, sharedBackend) + bsName := makeBackendServiceName(lbName, vals.ClusterID, sharedBackend, cloud.SchemeInternal, "TCP", svc.Spec.SessionAffinity) + err = gce.ensureInternalBackendService(bsName, bsDescription, svc.Spec.SessionAffinity, cloud.SchemeInternal, "TCP", igLinks, existingHC.SelfLink) + require.NoError(t, err) + + _, err = createInternalLoadBalancer(gce, svc, nil, nodeNames, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) +} + +func TestEnsureInternalLoadBalancerClearPreviousResources(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + svc := fakeLoadbalancerService(string(LBTypeInternal)) + lbName := cloudprovider.GetLoadBalancerName(svc) + + // Create a ForwardingRule that's missing an IP address + existingFwdRule := &compute.ForwardingRule{ + Name: lbName, + IPAddress: "", + Ports: []string{"123"}, + IPProtocol: "TCP", + LoadBalancingScheme: string(cloud.SchemeInternal), + } + gce.CreateRegionForwardingRule(existingFwdRule, gce.region) + + // Create a Firewall that's missing a Description + existingFirewall := &compute.Firewall{ + Name: lbName, + Network: gce.networkURL, + Allowed: []*compute.FirewallAllowed{ + { + IPProtocol: "tcp", + Ports: []string{"123"}, + }, + }, + } + gce.CreateFirewall(existingFirewall) + + sharedHealthCheck := !v1_service.RequestsOnlyLocalTraffic(svc) + hcName := makeHealthCheckName(lbName, vals.ClusterID, sharedHealthCheck) + hcPath, hcPort := GetNodesHealthCheckPath(), GetNodesHealthCheckPort() + nm := types.NamespacedName{Name: svc.Name, Namespace: svc.Namespace} + + // Create a healthcheck with an incorrect threshold + existingHC := newInternalLBHealthCheck(hcName, nm, sharedHealthCheck, hcPath, hcPort) + existingHC.HealthyThreshold = gceHcHealthyThreshold * 10 + gce.CreateHealthCheck(existingHC) + + // Create a backend Service that's missing Description and Backends + sharedBackend := shareBackendService(svc) + backendServiceName := makeBackendServiceName(lbName, vals.ClusterID, sharedBackend, cloud.SchemeInternal, "TCP", svc.Spec.SessionAffinity) + existingBS := &compute.BackendService{ + Name: lbName, + Protocol: "TCP", + HealthChecks: []string{existingHC.SelfLink}, + SessionAffinity: translateAffinityType(svc.Spec.SessionAffinity), + LoadBalancingScheme: string(cloud.SchemeInternal), + } + + gce.CreateRegionBackendService(existingBS, gce.region) + existingFwdRule.BackendService = existingBS.Name + + _, err = createInternalLoadBalancer(gce, svc, existingFwdRule, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) + + // Expect new resources with the correct attributes to be created + rule, _ := gce.GetRegionForwardingRule(lbName, gce.region) + assert.NotEqual(t, existingFwdRule, rule) + + firewall, err := gce.GetFirewall(lbName) + require.NoError(t, err) + assert.NotEqual(t, firewall, existingFirewall) + + healthcheck, err := gce.GetHealthCheck(hcName) + require.NoError(t, err) + assert.NotEqual(t, healthcheck, existingHC) + + bs, err := gce.GetRegionBackendService(backendServiceName, gce.region) + require.NoError(t, err) + assert.NotEqual(t, bs, existingBS) +} + +func TestUpdateInternalLoadBalancerBackendServices(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + nodeName := "test-node-1" + + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + svc := fakeLoadbalancerService(string(LBTypeInternal)) + _, err = createInternalLoadBalancer(gce, svc, nil, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) + + // BackendService exists prior to updateInternalLoadBalancer call, but has + // incorrect (missing) attributes. + // ensureInternalBackendServiceGroups is called and creates the correct + // BackendService + lbName := cloudprovider.GetLoadBalancerName(svc) + sharedBackend := shareBackendService(svc) + backendServiceName := makeBackendServiceName(lbName, vals.ClusterID, sharedBackend, cloud.SchemeInternal, "TCP", svc.Spec.SessionAffinity) + existingBS := &compute.BackendService{ + Name: backendServiceName, + Protocol: "TCP", + SessionAffinity: translateAffinityType(svc.Spec.SessionAffinity), + LoadBalancingScheme: string(cloud.SchemeInternal), + } + + gce.CreateRegionBackendService(existingBS, gce.region) + + nodes, err := createAndInsertNodes(gce, []string{nodeName}, vals.ZoneName) + require.NoError(t, err) + + err = gce.updateInternalLoadBalancer(vals.ClusterName, vals.ClusterID, svc, nodes) + assert.NoError(t, err) + + bs, err := gce.GetRegionBackendService(backendServiceName, gce.region) + require.NoError(t, err) + + // Check that the new BackendService has the correct attributes + url_base := fmt.Sprintf("https://www.googleapis.com/compute/v1/projects/%s", vals.ProjectID) + + assert.NotEqual(t, existingBS, bs) + assert.Equal( + t, + bs.SelfLink, + fmt.Sprintf("%s/regions/%s/backendServices/%s", url_base, vals.Region, bs.Name), + ) + assert.Equal(t, bs.Description, `{"kubernetes.io/service-name":"/"}`) + assert.Equal( + t, + bs.HealthChecks, + []string{fmt.Sprintf("%s/global/healthChecks/k8s-%s-node", url_base, vals.ClusterID)}, + ) +} + +func TestUpdateInternalLoadBalancerNodes(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + node1Name := []string{"test-node-1"} + + svc := fakeLoadbalancerService(string(LBTypeInternal)) + nodes, err := createAndInsertNodes(gce, node1Name, vals.ZoneName) + require.NoError(t, err) + + _, err = gce.ensureInternalLoadBalancer(vals.ClusterName, vals.ClusterID, svc, nil, nodes) + assert.NoError(t, err) + + // Replace the node in initial zone; add new node in a new zone. + node2Name, node3Name := "test-node-2", "test-node-3" + newNodesZoneA, err := createAndInsertNodes(gce, []string{node2Name}, vals.ZoneName) + require.NoError(t, err) + newNodesZoneB, err := createAndInsertNodes(gce, []string{node3Name}, vals.SecondaryZoneName) + require.NoError(t, err) + + nodes = append(newNodesZoneA, newNodesZoneB...) + err = gce.updateInternalLoadBalancer(vals.ClusterName, vals.ClusterID, svc, nodes) + assert.NoError(t, err) + + lbName := cloudprovider.GetLoadBalancerName(svc) + sharedBackend := shareBackendService(svc) + backendServiceName := makeBackendServiceName(lbName, vals.ClusterID, sharedBackend, cloud.SchemeInternal, "TCP", svc.Spec.SessionAffinity) + bs, err := gce.GetRegionBackendService(backendServiceName, gce.region) + require.NoError(t, err) + assert.Equal(t, 2, len(bs.Backends), "Want two backends referencing two instances groups") + + for _, zone := range []string{vals.ZoneName, vals.SecondaryZoneName} { + var found bool + for _, be := range bs.Backends { + if strings.Contains(be.Group, zone) { + found = true + break + } + } + assert.True(t, found, "Expected list of backends to have zone %q", zone) + } + + // Expect initial zone to have test-node-2 + igName := makeInstanceGroupName(vals.ClusterID) + instances, err := gce.ListInstancesInInstanceGroup(igName, vals.ZoneName, "ALL") + require.NoError(t, err) + assert.Equal(t, 1, len(instances)) + assert.Contains( + t, + instances[0].Instance, + fmt.Sprintf("projects/%s/zones/%s/instances/%s", vals.ProjectID, vals.ZoneName, node2Name), + ) + + // Expect initial zone to have test-node-3 + instances, err = gce.ListInstancesInInstanceGroup(igName, vals.SecondaryZoneName, "ALL") + require.NoError(t, err) + assert.Equal(t, 1, len(instances)) + assert.Contains( + t, + instances[0].Instance, + fmt.Sprintf("projects/%s/zones/%s/instances/%s", vals.ProjectID, vals.SecondaryZoneName, node3Name), + ) +} + +func TestEnsureInternalLoadBalancerDeleted(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + svc := fakeLoadbalancerService(string(LBTypeInternal)) + _, err = createInternalLoadBalancer(gce, svc, nil, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) + + err = gce.ensureInternalLoadBalancerDeleted(vals.ClusterName, vals.ClusterID, svc) + assert.NoError(t, err) + + assertInternalLbResourcesDeleted(t, gce, svc, vals, true) +} + +func TestEnsureInternalLoadBalancerDeletedTwiceDoesNotError(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + svc := fakeLoadbalancerService(string(LBTypeInternal)) + + _, err = createInternalLoadBalancer(gce, svc, nil, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) + + err = gce.ensureInternalLoadBalancerDeleted(vals.ClusterName, vals.ClusterID, svc) + assert.NoError(t, err) + + // Deleting the loadbalancer and resources again should not cause an error. + err = gce.ensureInternalLoadBalancerDeleted(vals.ClusterName, vals.ClusterID, svc) + assert.NoError(t, err) + assertInternalLbResourcesDeleted(t, gce, svc, vals, true) +} + +func TestEnsureInternalLoadBalancerWithSpecialHealthCheck(t *testing.T) { + vals := DefaultTestClusterValues() + nodeName := "test-node-1" + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + healthCheckNodePort := int32(10101) + svc := fakeLoadbalancerService(string(LBTypeInternal)) + svc.Spec.HealthCheckNodePort = healthCheckNodePort + svc.Spec.Type = v1.ServiceTypeLoadBalancer + svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal + + status, err := createInternalLoadBalancer(gce, svc, nil, []string{nodeName}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) + assert.NotEmpty(t, status.Ingress) + + loadBalancerName := cloudprovider.GetLoadBalancerName(svc) + hc, err := gce.GetHealthCheck(loadBalancerName) + assert.NoError(t, err) + assert.NotNil(t, hc) + assert.Equal(t, int64(healthCheckNodePort), hc.HttpHealthCheck.Port) +} + +func TestClearPreviousInternalResources(t *testing.T) { + // Configure testing environment. + vals := DefaultTestClusterValues() + svc := fakeLoadbalancerService(string(LBTypeInternal)) + loadBalancerName := cloudprovider.GetLoadBalancerName(svc) + nm := types.NamespacedName{Name: svc.Name, Namespace: svc.Namespace} + gce, err := fakeGCECloud(vals) + c := gce.c.(*cloud.MockGCE) + require.NoError(t, err) + + hc_1, err := gce.ensureInternalHealthCheck("hc_1", nm, false, "healthz", 12345) + require.NoError(t, err) + + hc_2, err := gce.ensureInternalHealthCheck("hc_2", nm, false, "healthz", 12346) + require.NoError(t, err) + + err = gce.ensureInternalBackendService(svc.ObjectMeta.Name, "", svc.Spec.SessionAffinity, cloud.SchemeInternal, v1.ProtocolTCP, []string{}, "") + require.NoError(t, err) + backendSvc, err := gce.GetRegionBackendService(svc.ObjectMeta.Name, gce.region) + backendSvc.HealthChecks = []string{hc_1.SelfLink, hc_2.SelfLink} + + c.MockRegionBackendServices.DeleteHook = mock.DeleteRegionBackendServicesErrHook + c.MockHealthChecks.DeleteHook = mock.DeleteHealthChecksInternalErrHook + gce.clearPreviousInternalResources(svc, loadBalancerName, backendSvc, "expectedBSName", "expectedHCName") + + backendSvc, err = gce.GetRegionBackendService(svc.ObjectMeta.Name, gce.region) + assert.NoError(t, err) + assert.NotNil(t, backendSvc, "BackendService should not be deleted when api is mocked out.") + hc_1, err = gce.GetHealthCheck("hc_1") + assert.NoError(t, err) + assert.NotNil(t, hc_1, "HealthCheck should not be deleted when there are more than one healthcheck attached.") + hc_2, err = gce.GetHealthCheck("hc_2") + assert.NoError(t, err) + assert.NotNil(t, hc_2, "HealthCheck should not be deleted when there are more than one healthcheck attached.") + + c.MockRegionBackendServices.DeleteHook = mock.DeleteRegionBackendServicesInUseErrHook + backendSvc.HealthChecks = []string{hc_1.SelfLink} + gce.clearPreviousInternalResources(svc, loadBalancerName, backendSvc, "expectedBSName", "expectedHCName") + + hc_1, err = gce.GetHealthCheck("hc_1") + assert.NoError(t, err) + assert.NotNil(t, hc_1, "HealthCheck should not be deleted when api is mocked out.") + + c.MockHealthChecks.DeleteHook = mock.DeleteHealthChecksInuseErrHook + gce.clearPreviousInternalResources(svc, loadBalancerName, backendSvc, "expectedBSName", "expectedHCName") + + hc_1, err = gce.GetHealthCheck("hc_1") + assert.NoError(t, err) + assert.NotNil(t, hc_1, "HealthCheck should not be deleted when api is mocked out.") + + c.MockRegionBackendServices.DeleteHook = nil + c.MockHealthChecks.DeleteHook = nil + gce.clearPreviousInternalResources(svc, loadBalancerName, backendSvc, "expectedBSName", "expectedHCName") + + backendSvc, err = gce.GetRegionBackendService(svc.ObjectMeta.Name, gce.region) + assert.Error(t, err) + assert.Nil(t, backendSvc, "BackendService should be deleted.") + hc_1, err = gce.GetHealthCheck("hc_1") + assert.Error(t, err) + assert.Nil(t, hc_1, "HealthCheck should be deleted.") +} + +func TestEnsureInternalFirewallSucceedsOnXPN(t *testing.T) { + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + vals := DefaultTestClusterValues() + svc := fakeLoadbalancerService(string(LBTypeInternal)) + fwName := cloudprovider.GetLoadBalancerName(svc) + + c := gce.c.(*cloud.MockGCE) + c.MockFirewalls.InsertHook = mock.InsertFirewallsUnauthorizedErrHook + c.MockFirewalls.UpdateHook = mock.UpdateFirewallsUnauthorizedErrHook + gce.onXPN = true + require.True(t, gce.OnXPN()) + + recorder := record.NewFakeRecorder(1024) + gce.eventRecorder = recorder + + nodes, err := createAndInsertNodes(gce, []string{"test-node-1"}, vals.ZoneName) + require.NoError(t, err) + sourceRange := []string{"10.0.0.0/20"} + gce.ensureInternalFirewall( + svc, + fwName, + "A sad little firewall", + sourceRange, + []string{"123"}, + v1.ProtocolTCP, + nodes) + require.Nil(t, err, "Should success when XPN is on.") + + checkEvent(t, recorder, FilewallChangeMsg, true) + + // Create a firewall. + c.MockFirewalls.InsertHook = nil + c.MockFirewalls.UpdateHook = nil + gce.onXPN = false + + gce.ensureInternalFirewall( + svc, + fwName, + "A sad little firewall", + sourceRange, + []string{"123"}, + v1.ProtocolTCP, + nodes) + require.Nil(t, err) + existingFirewall, err := gce.GetFirewall(fwName) + require.Nil(t, err) + require.NotNil(t, existingFirewall) + + gce.onXPN = true + c.MockFirewalls.InsertHook = mock.InsertFirewallsUnauthorizedErrHook + c.MockFirewalls.UpdateHook = mock.UpdateFirewallsUnauthorizedErrHook + + // Try to update the firewall just created. + gce.ensureInternalFirewall( + svc, + fwName, + "A happy little firewall", + sourceRange, + []string{"123"}, + v1.ProtocolTCP, + nodes) + require.Nil(t, err, "Should success when XPN is on.") + + checkEvent(t, recorder, FilewallChangeMsg, true) +} + +func TestEnsureLoadBalancerDeletedSucceedsOnXPN(t *testing.T) { + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + c := gce.c.(*cloud.MockGCE) + recorder := record.NewFakeRecorder(1024) + gce.eventRecorder = recorder + require.NoError(t, err) + + _, err = createInternalLoadBalancer(gce, fakeLoadbalancerService(string(LBTypeInternal)), nil, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) + + c.MockFirewalls.DeleteHook = mock.DeleteFirewallsUnauthorizedErrHook + gce.onXPN = true + + err = gce.ensureInternalLoadBalancerDeleted(vals.ClusterName, vals.ClusterID, fakeLoadbalancerService(string(LBTypeInternal))) + assert.NoError(t, err) + checkEvent(t, recorder, FilewallChangeMsg, true) +} + +func TestEnsureInternalInstanceGroupsDeleted(t *testing.T) { + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + c := gce.c.(*cloud.MockGCE) + recorder := record.NewFakeRecorder(1024) + gce.eventRecorder = recorder + require.NoError(t, err) + + igName := makeInstanceGroupName(vals.ClusterID) + + svc := fakeLoadbalancerService(string(LBTypeInternal)) + _, err = createInternalLoadBalancer(gce, svc, nil, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + assert.NoError(t, err) + + c.MockZones.ListHook = mock.ListZonesInternalErrHook + + err = gce.ensureInternalLoadBalancerDeleted(igName, vals.ClusterID, svc) + assert.Error(t, err, mock.InternalServerError) + ig, err := gce.GetInstanceGroup(igName, vals.ZoneName) + assert.NoError(t, err) + assert.NotNil(t, ig) + + c.MockZones.ListHook = nil + c.MockInstanceGroups.DeleteHook = mock.DeleteInstanceGroupInternalErrHook + + err = gce.ensureInternalInstanceGroupsDeleted(igName) + assert.Error(t, err, mock.InternalServerError) + ig, err = gce.GetInstanceGroup(igName, vals.ZoneName) + assert.NoError(t, err) + assert.NotNil(t, ig) + + c.MockInstanceGroups.DeleteHook = nil + err = gce.ensureInternalInstanceGroupsDeleted(igName) + assert.NoError(t, err) + ig, err = gce.GetInstanceGroup(igName, vals.ZoneName) + assert.Error(t, err) + assert.Nil(t, ig) +} + +type EnsureILBParams struct { + clusterName string + clusterID string + service *v1.Service + existingFwdRule *compute.ForwardingRule + nodes []*v1.Node +} + +// newEnsureILBParams is the constructor of EnsureILBParams. +func newEnsureILBParams(nodes []*v1.Node) *EnsureILBParams { + vals := DefaultTestClusterValues() + return &EnsureILBParams{ + vals.ClusterName, + vals.ClusterID, + fakeLoadbalancerService(string(LBTypeInternal)), + nil, + nodes, + } +} + +// TestEnsureInternalLoadBalancerErrors tests the function +// ensureInternalLoadBalancer, making sure the system won't panic when +// exceptions raised by gce. +func TestEnsureInternalLoadBalancerErrors(t *testing.T) { + vals := DefaultTestClusterValues() + var params *EnsureILBParams + + for desc, tc := range map[string]struct { + adjustParams func(*EnsureILBParams) + injectMock func(*cloud.MockGCE) + }{ + "Create internal instance groups failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockInstanceGroups.GetHook = mock.GetInstanceGroupInternalErrHook + }, + }, + "Invalid existing forwarding rules given": { + adjustParams: func(params *EnsureILBParams) { + params.existingFwdRule = &compute.ForwardingRule{BackendService: "badBackendService"} + }, + injectMock: func(c *cloud.MockGCE) { + c.MockRegionBackendServices.GetHook = mock.GetRegionBackendServicesErrHook + }, + }, + "EnsureInternalBackendService failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockRegionBackendServices.GetHook = mock.GetRegionBackendServicesErrHook + }, + }, + "Create internal health check failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockHealthChecks.GetHook = mock.GetHealthChecksInternalErrHook + }, + }, + "Create firewall failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockFirewalls.InsertHook = mock.InsertFirewallsUnauthorizedErrHook + }, + }, + "Create region forwarding rule failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockForwardingRules.InsertHook = mock.InsertForwardingRulesInternalErrHook + }, + }, + "Get region forwarding rule failed": { + injectMock: func(c *cloud.MockGCE) { + c.MockForwardingRules.GetHook = mock.GetForwardingRulesInternalErrHook + }, + }, + "Delete region forwarding rule failed": { + adjustParams: func(params *EnsureILBParams) { + params.existingFwdRule = &compute.ForwardingRule{BackendService: "badBackendService"} + }, + injectMock: func(c *cloud.MockGCE) { + c.MockForwardingRules.DeleteHook = mock.DeleteForwardingRuleErrHook + }, + }, + } { + t.Run(desc, func(t *testing.T) { + gce, err := fakeGCECloud(DefaultTestClusterValues()) + nodes, err := createAndInsertNodes(gce, []string{"test-node-1"}, vals.ZoneName) + require.NoError(t, err) + params = newEnsureILBParams(nodes) + if tc.adjustParams != nil { + tc.adjustParams(params) + } + if tc.injectMock != nil { + tc.injectMock(gce.c.(*cloud.MockGCE)) + } + status, err := gce.ensureInternalLoadBalancer( + params.clusterName, + params.clusterID, + params.service, + params.existingFwdRule, + params.nodes, + ) + assert.Error(t, err, "Should return an error when "+desc) + assert.Nil(t, status, "Should not return a status when "+desc) + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_test.go new file mode 100644 index 000000000..7d7224892 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_test.go @@ -0,0 +1,171 @@ +/* +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 gce + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetLoadBalancer(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + apiService := fakeLoadbalancerService("") + + // When a loadbalancer has not been created + status, found, err := gce.GetLoadBalancer(context.Background(), vals.ClusterName, apiService) + assert.Nil(t, status) + assert.False(t, found) + assert.Nil(t, err) + + nodeNames := []string{"test-node-1"} + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + require.NoError(t, err) + expectedStatus, err := gce.EnsureLoadBalancer(context.Background(), vals.ClusterName, apiService, nodes) + require.NoError(t, err) + + status, found, err = gce.GetLoadBalancer(context.Background(), vals.ClusterName, apiService) + assert.Equal(t, expectedStatus, status) + assert.True(t, found) + assert.Nil(t, err) +} + +func TestEnsureLoadBalancerCreatesExternalLb(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + nodeNames := []string{"test-node-1"} + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + require.NoError(t, err) + + apiService := fakeLoadbalancerService("") + status, err := gce.EnsureLoadBalancer(context.Background(), vals.ClusterName, apiService, nodes) + assert.NoError(t, err) + assert.NotEmpty(t, status.Ingress) + assertExternalLbResources(t, gce, apiService, vals, nodeNames) +} + +func TestEnsureLoadBalancerCreatesInternalLb(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + nodeNames := []string{"test-node-1"} + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + require.NoError(t, err) + + apiService := fakeLoadbalancerService(string(LBTypeInternal)) + status, err := gce.EnsureLoadBalancer(context.Background(), vals.ClusterName, apiService, nodes) + assert.NoError(t, err) + assert.NotEmpty(t, status.Ingress) + assertInternalLbResources(t, gce, apiService, vals, nodeNames) +} + +func TestEnsureLoadBalancerDeletesExistingInternalLb(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + nodeNames := []string{"test-node-1"} + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + require.NoError(t, err) + + apiService := fakeLoadbalancerService("") + createInternalLoadBalancer(gce, apiService, nil, nodeNames, vals.ClusterName, vals.ClusterID, vals.ZoneName) + + status, err := gce.EnsureLoadBalancer(context.Background(), vals.ClusterName, apiService, nodes) + assert.NoError(t, err) + assert.NotEmpty(t, status.Ingress) + + assertExternalLbResources(t, gce, apiService, vals, nodeNames) + assertInternalLbResourcesDeleted(t, gce, apiService, vals, false) +} + +func TestEnsureLoadBalancerDeletesExistingExternalLb(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + nodeNames := []string{"test-node-1"} + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + require.NoError(t, err) + + apiService := fakeLoadbalancerService("") + createExternalLoadBalancer(gce, apiService, nodeNames, vals.ClusterName, vals.ClusterID, vals.ZoneName) + + apiService = fakeLoadbalancerService(string(LBTypeInternal)) + status, err := gce.EnsureLoadBalancer(context.Background(), vals.ClusterName, apiService, nodes) + assert.NoError(t, err) + assert.NotEmpty(t, status.Ingress) + + assertInternalLbResources(t, gce, apiService, vals, nodeNames) + assertExternalLbResourcesDeleted(t, gce, apiService, vals, false) +} + +func TestEnsureLoadBalancerDeletedDeletesExternalLb(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + nodeNames := []string{"test-node-1"} + _, err = createAndInsertNodes(gce, nodeNames, vals.ZoneName) + require.NoError(t, err) + + apiService := fakeLoadbalancerService("") + createExternalLoadBalancer(gce, apiService, nodeNames, vals.ClusterName, vals.ClusterID, vals.ZoneName) + + err = gce.EnsureLoadBalancerDeleted(context.Background(), vals.ClusterName, apiService) + assert.NoError(t, err) + assertExternalLbResourcesDeleted(t, gce, apiService, vals, true) +} + +func TestEnsureLoadBalancerDeletedDeletesInternalLb(t *testing.T) { + t.Parallel() + + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(vals) + require.NoError(t, err) + + nodeNames := []string{"test-node-1"} + _, err = createAndInsertNodes(gce, nodeNames, vals.ZoneName) + require.NoError(t, err) + + apiService := fakeLoadbalancerService(string(LBTypeInternal)) + createInternalLoadBalancer(gce, apiService, nil, nodeNames, vals.ClusterName, vals.ClusterID, vals.ZoneName) + + err = gce.EnsureLoadBalancerDeleted(context.Background(), vals.ClusterName, apiService) + assert.NoError(t, err) + assertInternalLbResourcesDeleted(t, gce, apiService, vals, true) +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go new file mode 100644 index 000000000..7a5dbc715 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go @@ -0,0 +1,403 @@ +/* +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. +*/ + +// This file contains shared functions and variables to set up for tests for +// ExternalLoadBalancer and InternalLoadBalancers. It currently cannot live in a +// separate package from GCE because then it would cause a circular import. + +package gce + +import ( + "fmt" + "net/http" + "strings" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + compute "google.golang.org/api/compute/v1" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + v1_service "k8s.io/kubernetes/pkg/api/v1/service" + "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock" + kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" +) + +// TODO(yankaiz): Create shared error types for both test/non-test codes. +const ( + eventReasonManualChange = "LoadBalancerManualChange" + eventMsgFirewallChange = "Firewall change required by network admin" + errPrefixGetTargetPool = "error getting load balancer's target pool:" + errStrLbNoHosts = "Cannot EnsureLoadBalancer() with no hosts" + wrongTier = "SupremeLuxury" + errStrUnsupportedTier = "unsupported network tier: \"" + wrongTier + "\"" +) + +type TestClusterValues struct { + ProjectID string + Region string + ZoneName string + SecondaryZoneName string + ClusterID string + ClusterName string +} + +func DefaultTestClusterValues() TestClusterValues { + return TestClusterValues{ + ProjectID: "test-project", + Region: "us-central1", + ZoneName: "us-central1-b", + SecondaryZoneName: "us-central1-c", + ClusterID: "test-cluster-id", + ClusterName: "Test Cluster Name", + } +} + +func fakeLoadbalancerService(lbType string) *v1.Service { + return &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "", + Annotations: map[string]string{ServiceAnnotationLoadBalancerType: lbType}, + }, + Spec: v1.ServiceSpec{ + SessionAffinity: v1.ServiceAffinityClientIP, + Type: v1.ServiceTypeLoadBalancer, + Ports: []v1.ServicePort{{Protocol: v1.ProtocolTCP, Port: int32(123)}}, + }, + } +} + +var ( + FilewallChangeMsg = fmt.Sprintf("%s %s %s", v1.EventTypeNormal, eventReasonManualChange, eventMsgFirewallChange) +) + +type fakeRoundTripper struct{} + +func (*fakeRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { + return nil, fmt.Errorf("err: test used fake http client") +} + +func fakeGCECloud(vals TestClusterValues) (*GCECloud, error) { + client := &http.Client{Transport: &fakeRoundTripper{}} + + service, err := compute.New(client) + if err != nil { + return nil, err + } + + // Used in disk unit tests + fakeManager := newFakeManager(vals.ProjectID, vals.Region) + zonesWithNodes := createNodeZones([]string{vals.ZoneName}) + + alphaFeatureGate := NewAlphaFeatureGate([]string{}) + if err != nil { + return nil, err + } + + gce := &GCECloud{ + region: vals.Region, + service: service, + manager: fakeManager, + managedZones: []string{vals.ZoneName}, + projectID: vals.ProjectID, + networkProjectID: vals.ProjectID, + AlphaFeatureGate: alphaFeatureGate, + nodeZones: zonesWithNodes, + nodeInformerSynced: func() bool { return true }, + ClusterID: fakeClusterID(vals.ClusterID), + } + + c := cloud.NewMockGCE(&gceProjectRouter{gce}) + c.MockTargetPools.AddInstanceHook = mock.AddInstanceHook + c.MockTargetPools.RemoveInstanceHook = mock.RemoveInstanceHook + c.MockForwardingRules.InsertHook = mock.InsertFwdRuleHook + c.MockAddresses.InsertHook = mock.InsertAddressHook + c.MockAlphaAddresses.InsertHook = mock.InsertAlphaAddressHook + c.MockAlphaAddresses.X = mock.AddressAttributes{} + c.MockAddresses.X = mock.AddressAttributes{} + + c.MockInstanceGroups.X = mock.InstanceGroupAttributes{ + InstanceMap: make(map[meta.Key]map[string]*compute.InstanceWithNamedPorts), + Lock: &sync.Mutex{}, + } + c.MockInstanceGroups.AddInstancesHook = mock.AddInstancesHook + c.MockInstanceGroups.RemoveInstancesHook = mock.RemoveInstancesHook + c.MockInstanceGroups.ListInstancesHook = mock.ListInstancesHook + + c.MockRegionBackendServices.UpdateHook = mock.UpdateRegionBackendServiceHook + c.MockHealthChecks.UpdateHook = mock.UpdateHealthCheckHook + c.MockFirewalls.UpdateHook = mock.UpdateFirewallHook + + keyGA := meta.GlobalKey("key-ga") + c.MockZones.Objects[*keyGA] = &cloud.MockZonesObj{ + Obj: &compute.Zone{Name: vals.ZoneName, Region: gce.getRegionLink(vals.Region)}, + } + + gce.c = c + + return gce, nil +} + +func createAndInsertNodes(gce *GCECloud, nodeNames []string, zoneName string) ([]*v1.Node, error) { + nodes := []*v1.Node{} + + for _, name := range nodeNames { + // Inserting the same node name twice causes an error - here we check if + // the instance exists already before insertion. + // TestUpdateExternalLoadBalancer inserts a new node, and relies on an older + // node to already have been inserted. + instance, _ := gce.getInstanceByName(name) + + if instance == nil { + err := gce.InsertInstance( + gce.ProjectID(), + zoneName, + &compute.Instance{ + Name: name, + Tags: &compute.Tags{ + Items: []string{name}, + }, + }, + ) + if err != nil { + return nodes, err + } + } + + nodes = append( + nodes, + &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + kubeletapis.LabelHostname: name, + kubeletapis.LabelZoneFailureDomain: zoneName, + }, + }, + Status: v1.NodeStatus{ + NodeInfo: v1.NodeSystemInfo{ + KubeProxyVersion: "v1.7.2", + }, + }, + }, + ) + + } + + return nodes, nil +} + +// Stubs ClusterID so that ClusterID.getOrInitialize() does not require calling +// gce.Initialize() +func fakeClusterID(clusterID string) ClusterID { + return ClusterID{ + clusterID: &clusterID, + store: cache.NewStore(func(obj interface{}) (string, error) { + return "", nil + }), + } +} + +func assertExternalLbResources(t *testing.T, gce *GCECloud, apiService *v1.Service, vals TestClusterValues, nodeNames []string) { + lbName := cloudprovider.GetLoadBalancerName(apiService) + hcName := MakeNodesHealthCheckName(vals.ClusterID) + + // Check that Firewalls are created for the LoadBalancer and the HealthCheck + fwNames := []string{ + MakeFirewallName(lbName), // Firewalls for external LBs are prefixed with k8s-fw- + MakeHealthCheckFirewallName(vals.ClusterID, hcName, true), + } + + for _, fwName := range fwNames { + firewall, err := gce.GetFirewall(fwName) + require.NoError(t, err) + assert.Equal(t, nodeNames, firewall.TargetTags) + assert.NotEmpty(t, firewall.SourceRanges) + } + + // Check that TargetPool is Created + pool, err := gce.GetTargetPool(lbName, gce.region) + require.NoError(t, err) + assert.Equal(t, lbName, pool.Name) + assert.NotEmpty(t, pool.HealthChecks) + assert.Equal(t, 1, len(pool.Instances)) + + // Check that HealthCheck is created + healthcheck, err := gce.GetHttpHealthCheck(hcName) + require.NoError(t, err) + assert.Equal(t, hcName, healthcheck.Name) + + // Check that ForwardingRule is created + fwdRule, err := gce.GetRegionForwardingRule(lbName, gce.region) + require.NoError(t, err) + assert.Equal(t, lbName, fwdRule.Name) + assert.Equal(t, "TCP", fwdRule.IPProtocol) + assert.Equal(t, "123-123", fwdRule.PortRange) +} + +func assertExternalLbResourcesDeleted(t *testing.T, gce *GCECloud, apiService *v1.Service, vals TestClusterValues, firewallsDeleted bool) { + lbName := cloudprovider.GetLoadBalancerName(apiService) + hcName := MakeNodesHealthCheckName(vals.ClusterID) + + if firewallsDeleted { + // Check that Firewalls are deleted for the LoadBalancer and the HealthCheck + fwNames := []string{ + MakeFirewallName(lbName), + MakeHealthCheckFirewallName(vals.ClusterID, hcName, true), + } + + for _, fwName := range fwNames { + firewall, err := gce.GetFirewall(fwName) + require.Error(t, err) + assert.Nil(t, firewall) + } + + // Check forwarding rule is deleted + fwdRule, err := gce.GetRegionForwardingRule(lbName, gce.region) + require.Error(t, err) + assert.Nil(t, fwdRule) + } + + // Check that TargetPool is deleted + pool, err := gce.GetTargetPool(lbName, gce.region) + require.Error(t, err) + assert.Nil(t, pool) + + // Check that HealthCheck is deleted + healthcheck, err := gce.GetHttpHealthCheck(hcName) + require.Error(t, err) + assert.Nil(t, healthcheck) + +} + +func assertInternalLbResources(t *testing.T, gce *GCECloud, apiService *v1.Service, vals TestClusterValues, nodeNames []string) { + lbName := cloudprovider.GetLoadBalancerName(apiService) + + // Check that Instance Group is created + igName := makeInstanceGroupName(vals.ClusterID) + ig, err := gce.GetInstanceGroup(igName, vals.ZoneName) + assert.NoError(t, err) + assert.Equal(t, igName, ig.Name) + + // Check that Firewalls are created for the LoadBalancer and the HealthCheck + fwNames := []string{ + lbName, // Firewalls for internal LBs are named the same name as the loadbalancer. + makeHealthCheckFirewallName(lbName, vals.ClusterID, true), + } + + for _, fwName := range fwNames { + firewall, err := gce.GetFirewall(fwName) + require.NoError(t, err) + assert.Equal(t, nodeNames, firewall.TargetTags) + assert.NotEmpty(t, firewall.SourceRanges) + } + + // Check that HealthCheck is created + sharedHealthCheck := !v1_service.RequestsOnlyLocalTraffic(apiService) + hcName := makeHealthCheckName(lbName, vals.ClusterID, sharedHealthCheck) + healthcheck, err := gce.GetHealthCheck(hcName) + require.NoError(t, err) + assert.Equal(t, hcName, healthcheck.Name) + + // Check that BackendService exists + sharedBackend := shareBackendService(apiService) + backendServiceName := makeBackendServiceName(lbName, vals.ClusterID, sharedBackend, cloud.SchemeInternal, "TCP", apiService.Spec.SessionAffinity) + backendServiceLink := gce.getBackendServiceLink(backendServiceName) + + bs, err := gce.GetRegionBackendService(backendServiceName, gce.region) + require.NoError(t, err) + assert.Equal(t, "TCP", bs.Protocol) + assert.Equal( + t, + []string{healthcheck.SelfLink}, + bs.HealthChecks, + ) + + // Check that ForwardingRule is created + fwdRule, err := gce.GetRegionForwardingRule(lbName, gce.region) + require.NoError(t, err) + assert.Equal(t, lbName, fwdRule.Name) + assert.Equal(t, "TCP", fwdRule.IPProtocol) + assert.Equal(t, backendServiceLink, fwdRule.BackendService) + // if no Subnetwork specified, defaults to the GCE NetworkURL + assert.Equal(t, gce.NetworkURL(), fwdRule.Subnetwork) +} + +func assertInternalLbResourcesDeleted(t *testing.T, gce *GCECloud, apiService *v1.Service, vals TestClusterValues, firewallsDeleted bool) { + lbName := cloudprovider.GetLoadBalancerName(apiService) + sharedHealthCheck := !v1_service.RequestsOnlyLocalTraffic(apiService) + hcName := makeHealthCheckName(lbName, vals.ClusterID, sharedHealthCheck) + + // ensureExternalLoadBalancer and ensureInternalLoadBalancer both create + // Firewalls with the same name. + if firewallsDeleted { + // Check that Firewalls are deleted for the LoadBalancer and the HealthCheck + fwNames := []string{ + MakeFirewallName(lbName), + MakeHealthCheckFirewallName(vals.ClusterID, hcName, true), + } + + for _, fwName := range fwNames { + firewall, err := gce.GetFirewall(fwName) + require.Error(t, err) + assert.Nil(t, firewall) + } + + // Check forwarding rule is deleted + fwdRule, err := gce.GetRegionForwardingRule(lbName, gce.region) + require.Error(t, err) + assert.Nil(t, fwdRule) + } + + // Check that Instance Group is deleted + igName := makeInstanceGroupName(vals.ClusterID) + ig, err := gce.GetInstanceGroup(igName, vals.ZoneName) + assert.Error(t, err) + assert.Nil(t, ig) + + // Check that HealthCheck is deleted + healthcheck, err := gce.GetHealthCheck(hcName) + require.Error(t, err) + assert.Nil(t, healthcheck) +} + +func checkEvent(t *testing.T, recorder *record.FakeRecorder, expected string, shouldMatch bool) bool { + select { + case received := <-recorder.Events: + if strings.HasPrefix(received, expected) != shouldMatch { + t.Errorf(received) + if shouldMatch { + t.Errorf("Should receive message \"%v\" but got \"%v\".", expected, received) + } else { + t.Errorf("Unexpected event \"%v\".", received) + } + } + return false + case <-time.After(2 * time.Second): + if shouldMatch { + t.Errorf("Should receive message \"%v\" but got timed out.", expected) + } + return true + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go index f0e3fb538..efa4dcf4b 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go @@ -17,12 +17,12 @@ limitations under the License. package gce import ( - "context" "fmt" "strings" computealpha "google.golang.org/api/compute/v0.alpha" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -37,31 +37,40 @@ func newNetworkEndpointGroupMetricContext(request string, zone string) *metricCo } func (gce *GCECloud) GetNetworkEndpointGroup(name string, zone string) (*computealpha.NetworkEndpointGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("get", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return nil, mc.Observe(err) } - v, err := gce.c.AlphaNetworkEndpointGroups().Get(context.Background(), meta.ZonalKey(name, zone)) + v, err := gce.c.AlphaNetworkEndpointGroups().Get(ctx, meta.ZonalKey(name, zone)) return v, mc.Observe(err) } func (gce *GCECloud) ListNetworkEndpointGroup(zone string) ([]*computealpha.NetworkEndpointGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("list", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return nil, mc.Observe(err) } - negs, err := gce.c.AlphaNetworkEndpointGroups().List(context.Background(), zone, filter.None) + negs, err := gce.c.AlphaNetworkEndpointGroups().List(ctx, zone, filter.None) return negs, mc.Observe(err) } // AggregatedListNetworkEndpointGroup returns a map of zone -> endpoint group. func (gce *GCECloud) AggregatedListNetworkEndpointGroup() (map[string][]*computealpha.NetworkEndpointGroup, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("aggregated_list", "") if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return nil, mc.Observe(err) } // TODO: filter for the region the cluster is in. - all, err := gce.c.AlphaNetworkEndpointGroups().AggregatedList(context.Background(), filter.None) + all, err := gce.c.AlphaNetworkEndpointGroups().AggregatedList(ctx, filter.None) if err != nil { return nil, mc.Observe(err) } @@ -79,22 +88,31 @@ func (gce *GCECloud) AggregatedListNetworkEndpointGroup() (map[string][]*compute } func (gce *GCECloud) CreateNetworkEndpointGroup(neg *computealpha.NetworkEndpointGroup, zone string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return err } mc := newNetworkEndpointGroupMetricContext("create", zone) - return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Insert(context.Background(), meta.ZonalKey(neg.Name, zone), neg)) + return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Insert(ctx, meta.ZonalKey(neg.Name, zone), neg)) } func (gce *GCECloud) DeleteNetworkEndpointGroup(name string, zone string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return err } mc := newNetworkEndpointGroupMetricContext("delete", zone) - return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Delete(context.Background(), meta.ZonalKey(name, zone))) + return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Delete(ctx, meta.ZonalKey(name, zone))) } func (gce *GCECloud) AttachNetworkEndpoints(name, zone string, endpoints []*computealpha.NetworkEndpoint) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("attach", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return mc.Observe(err) @@ -102,10 +120,13 @@ func (gce *GCECloud) AttachNetworkEndpoints(name, zone string, endpoints []*comp req := &computealpha.NetworkEndpointGroupsAttachEndpointsRequest{ NetworkEndpoints: endpoints, } - return mc.Observe(gce.c.AlphaNetworkEndpointGroups().AttachNetworkEndpoints(context.Background(), meta.ZonalKey(name, zone), req)) + return mc.Observe(gce.c.AlphaNetworkEndpointGroups().AttachNetworkEndpoints(ctx, meta.ZonalKey(name, zone), req)) } func (gce *GCECloud) DetachNetworkEndpoints(name, zone string, endpoints []*computealpha.NetworkEndpoint) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("detach", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return mc.Observe(err) @@ -113,10 +134,13 @@ func (gce *GCECloud) DetachNetworkEndpoints(name, zone string, endpoints []*comp req := &computealpha.NetworkEndpointGroupsDetachEndpointsRequest{ NetworkEndpoints: endpoints, } - return mc.Observe(gce.c.AlphaNetworkEndpointGroups().DetachNetworkEndpoints(context.Background(), meta.ZonalKey(name, zone), req)) + return mc.Observe(gce.c.AlphaNetworkEndpointGroups().DetachNetworkEndpoints(ctx, meta.ZonalKey(name, zone), req)) } func (gce *GCECloud) ListNetworkEndpoints(name, zone string, showHealthStatus bool) ([]*computealpha.NetworkEndpointWithHealthStatus, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newNetworkEndpointGroupMetricContext("list_networkendpoints", zone) if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil { return nil, mc.Observe(err) @@ -128,6 +152,6 @@ func (gce *GCECloud) ListNetworkEndpoints(name, zone string, showHealthStatus bo req := &computealpha.NetworkEndpointGroupsListEndpointsRequest{ HealthStatus: healthStatus, } - l, err := gce.c.AlphaNetworkEndpointGroups().ListNetworkEndpoints(context.Background(), meta.ZonalKey(name, zone), req, filter.None) + l, err := gce.c.AlphaNetworkEndpointGroups().ListNetworkEndpoints(ctx, meta.ZonalKey(name, zone), req, filter.None) return l, mc.Observe(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_op.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_op.go deleted file mode 100644 index b354d79ce..000000000 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_op.go +++ /dev/null @@ -1,180 +0,0 @@ -/* -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 gce - -import ( - "encoding/json" - "fmt" - "time" - - "k8s.io/apimachinery/pkg/util/wait" - - "github.com/golang/glog" - computealpha "google.golang.org/api/compute/v0.alpha" - computebeta "google.golang.org/api/compute/v0.beta" - computev1 "google.golang.org/api/compute/v1" - "google.golang.org/api/googleapi" -) - -func (gce *GCECloud) waitForOp(op *computev1.Operation, getOperation func(operationName string) (*computev1.Operation, error), mc *metricContext) error { - if op == nil { - return mc.Observe(fmt.Errorf("operation must not be nil")) - } - - if opIsDone(op) { - return getErrorFromOp(op) - } - - opStart := time.Now() - opName := op.Name - - return wait.Poll(operationPollInterval, operationPollTimeoutDuration, func() (bool, error) { - start := time.Now() - gce.operationPollRateLimiter.Accept() - duration := time.Now().Sub(start) - if duration > 5*time.Second { - glog.V(2).Infof("pollOperation: throttled %v for %v", duration, opName) - } - pollOp, err := getOperation(opName) - if err != nil { - glog.Warningf("GCE poll operation %s failed: pollOp: [%v] err: [%v] getErrorFromOp: [%v]", - opName, pollOp, err, getErrorFromOp(pollOp)) - } - - done := opIsDone(pollOp) - if done { - duration := time.Now().Sub(opStart) - if duration > 1*time.Minute { - // Log the JSON. It's cleaner than the %v structure. - enc, err := pollOp.MarshalJSON() - if err != nil { - glog.Warningf("waitForOperation: long operation (%v): %v (failed to encode to JSON: %v)", - duration, pollOp, err) - } else { - glog.V(2).Infof("waitForOperation: long operation (%v): %v", - duration, string(enc)) - } - } - } - - return done, mc.Observe(getErrorFromOp(pollOp)) - }) -} - -func opIsDone(op *computev1.Operation) bool { - return op != nil && op.Status == "DONE" -} - -func getErrorFromOp(op *computev1.Operation) error { - if op != nil && op.Error != nil && len(op.Error.Errors) > 0 { - err := &googleapi.Error{ - Code: int(op.HttpErrorStatusCode), - Message: op.Error.Errors[0].Message, - } - glog.Errorf("GCE operation failed: %v", err) - return err - } - - return nil -} - -func (gce *GCECloud) waitForGlobalOp(op gceObject, mc *metricContext) error { - return gce.waitForGlobalOpInProject(op, gce.ProjectID(), mc) -} - -func (gce *GCECloud) waitForRegionOp(op gceObject, region string, mc *metricContext) error { - return gce.waitForRegionOpInProject(op, gce.ProjectID(), region, mc) -} - -func (gce *GCECloud) waitForZoneOp(op gceObject, zone string, mc *metricContext) error { - return gce.waitForZoneOpInProject(op, gce.ProjectID(), zone, mc) -} - -func (gce *GCECloud) waitForGlobalOpInProject(op gceObject, projectID string, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceAlpha.GlobalOperations.Get(projectID, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computebeta.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceBeta.GlobalOperations.Get(projectID, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computev1.Operation: - return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { - return gce.service.GlobalOperations.Get(projectID, operationName).Do() - }, mc) - default: - return fmt.Errorf("unexpected type: %T", v) - } -} - -func (gce *GCECloud) waitForRegionOpInProject(op gceObject, projectID, region string, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceAlpha.RegionOperations.Get(projectID, region, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computebeta.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceBeta.RegionOperations.Get(projectID, region, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computev1.Operation: - return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { - return gce.service.RegionOperations.Get(projectID, region, operationName).Do() - }, mc) - default: - return fmt.Errorf("unexpected type: %T", v) - } -} - -func (gce *GCECloud) waitForZoneOpInProject(op gceObject, projectID, zone string, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceAlpha.ZoneOperations.Get(projectID, zone, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computebeta.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceBeta.ZoneOperations.Get(projectID, zone, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computev1.Operation: - return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { - return gce.service.ZoneOperations.Get(projectID, zone, operationName).Do() - }, mc) - default: - return fmt.Errorf("unexpected type: %T", v) - } -} - -func convertToV1Operation(object gceObject) *computev1.Operation { - enc, err := object.MarshalJSON() - if err != nil { - panic(fmt.Sprintf("Failed to encode to json: %v", err)) - } - var op computev1.Operation - if err := json.Unmarshal(enc, &op); err != nil { - panic(fmt.Sprintf("Failed to convert GCE apiObject %v to v1 operation: %v", object, err)) - } - return &op -} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_routes.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_routes.go index 4a7cea5b3..624b581cb 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_routes.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_routes.go @@ -27,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -37,10 +38,13 @@ func newRoutesMetricContext(request string) *metricContext { // ListRoutes in the cloud environment. func (gce *GCECloud) ListRoutes(ctx context.Context, clusterName string) ([]*cloudprovider.Route, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newRoutesMetricContext("list") prefix := truncateClusterName(clusterName) f := filter.Regexp("name", prefix+"-.*").AndRegexp("network", gce.NetworkURL()).AndRegexp("description", k8sNodeRouteTag) - routes, err := gce.c.Routes().List(context.Background(), f) + routes, err := gce.c.Routes().List(ctx, f) if err != nil { return nil, mc.Observe(err) } @@ -60,6 +64,9 @@ func (gce *GCECloud) ListRoutes(ctx context.Context, clusterName string) ([]*clo // CreateRoute in the cloud environment. func (gce *GCECloud) CreateRoute(ctx context.Context, clusterName string, nameHint string, route *cloudprovider.Route) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newRoutesMetricContext("create") targetInstance, err := gce.getInstanceByName(mapNodeNameToInstanceName(route.TargetNode)) @@ -74,7 +81,7 @@ func (gce *GCECloud) CreateRoute(ctx context.Context, clusterName string, nameHi Priority: 1000, Description: k8sNodeRouteTag, } - err = gce.c.Routes().Insert(context.Background(), meta.GlobalKey(cr.Name), cr) + err = gce.c.Routes().Insert(ctx, meta.GlobalKey(cr.Name), cr) if isHTTPErrorCode(err, http.StatusConflict) { glog.Infof("Route %q already exists.", cr.Name) err = nil @@ -84,8 +91,11 @@ func (gce *GCECloud) CreateRoute(ctx context.Context, clusterName string, nameHi // DeleteRoute from the cloud environment. func (gce *GCECloud) DeleteRoute(ctx context.Context, clusterName string, route *cloudprovider.Route) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newRoutesMetricContext("delete") - return mc.Observe(gce.c.Routes().Delete(context.Background(), meta.GlobalKey(route.Name))) + return mc.Observe(gce.c.Routes().Delete(ctx, meta.GlobalKey(route.Name))) } func truncateClusterName(clusterName string) string { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_securitypolicy.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_securitypolicy.go new file mode 100644 index 000000000..293946590 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_securitypolicy.go @@ -0,0 +1,116 @@ +/* +Copyright 2018 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 gce + +import ( + computebeta "google.golang.org/api/compute/v0.beta" + + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" +) + +func newSecurityPolicyMetricContextWithVersion(request, version string) *metricContext { + return newGenericMetricContext("securitypolicy", request, "", unusedMetricLabel, version) +} + +// GetBetaSecurityPolicy retrieves a security policy. +func (gce *GCECloud) GetBetaSecurityPolicy(name string) (*computebeta.SecurityPolicy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newSecurityPolicyMetricContextWithVersion("get", computeBetaVersion) + v, err := gce.c.BetaSecurityPolicies().Get(ctx, meta.GlobalKey(name)) + return v, mc.Observe(err) +} + +// ListBetaSecurityPolicy lists all security policies in the project. +func (gce *GCECloud) ListBetaSecurityPolicy() ([]*computebeta.SecurityPolicy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newSecurityPolicyMetricContextWithVersion("list", computeBetaVersion) + v, err := gce.c.BetaSecurityPolicies().List(ctx, filter.None) + return v, mc.Observe(err) +} + +// CreateBetaSecurityPolicy creates the given security policy. +func (gce *GCECloud) CreateBetaSecurityPolicy(sp *computebeta.SecurityPolicy) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newSecurityPolicyMetricContextWithVersion("create", computeBetaVersion) + return mc.Observe(gce.c.BetaSecurityPolicies().Insert(ctx, meta.GlobalKey(sp.Name), sp)) +} + +// DeleteBetaSecurityPolicy deletes the given security policy. +func (gce *GCECloud) DeleteBetaSecurityPolicy(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newSecurityPolicyMetricContextWithVersion("delete", computeBetaVersion) + return mc.Observe(gce.c.BetaSecurityPolicies().Delete(ctx, meta.GlobalKey(name))) +} + +// PatchBetaSecurityPolicy applies the given security policy as a +// patch to an existing security policy. +func (gce *GCECloud) PatchBetaSecurityPolicy(sp *computebeta.SecurityPolicy) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newSecurityPolicyMetricContextWithVersion("patch", computeBetaVersion) + return mc.Observe(gce.c.BetaSecurityPolicies().Patch(ctx, meta.GlobalKey(sp.Name), sp)) +} + +// GetRuleForBetaSecurityPolicy gets rule from a security policy. +func (gce *GCECloud) GetRuleForBetaSecurityPolicy(name string) (*computebeta.SecurityPolicyRule, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newSecurityPolicyMetricContextWithVersion("get_rule", computeBetaVersion) + v, err := gce.c.BetaSecurityPolicies().GetRule(ctx, meta.GlobalKey(name)) + return v, mc.Observe(err) +} + +// AddRuletoBetaSecurityPolicy adds the given security policy rule to +// a security policy. +func (gce *GCECloud) AddRuletoBetaSecurityPolicy(name string, spr *computebeta.SecurityPolicyRule) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newSecurityPolicyMetricContextWithVersion("add_rule", computeBetaVersion) + return mc.Observe(gce.c.BetaSecurityPolicies().AddRule(ctx, meta.GlobalKey(name), spr)) +} + +// PatchRuleForBetaSecurityPolicy patches the given security policy +// rule to a security policy. +func (gce *GCECloud) PatchRuleForBetaSecurityPolicy(name string, spr *computebeta.SecurityPolicyRule) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newSecurityPolicyMetricContextWithVersion("patch_rule", computeBetaVersion) + return mc.Observe(gce.c.BetaSecurityPolicies().PatchRule(ctx, meta.GlobalKey(name), spr)) +} + +// RemoveRuleFromBetaSecurityPolicy removes rule from a security policy. +func (gce *GCECloud) RemoveRuleFromBetaSecurityPolicy(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + + mc := newSecurityPolicyMetricContextWithVersion("remove_rule", computeBetaVersion) + return mc.Observe(gce.c.BetaSecurityPolicies().RemoveRule(ctx, meta.GlobalKey(name))) +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetpool.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetpool.go index 8fd3b3704..8c1127e74 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetpool.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetpool.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - compute "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -30,37 +29,52 @@ func newTargetPoolMetricContext(request, region string) *metricContext { // GetTargetPool returns the TargetPool by name. func (gce *GCECloud) GetTargetPool(name, region string) (*compute.TargetPool, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetPoolMetricContext("get", region) - v, err := gce.c.TargetPools().Get(context.Background(), meta.RegionalKey(name, region)) + v, err := gce.c.TargetPools().Get(ctx, meta.RegionalKey(name, region)) return v, mc.Observe(err) } // CreateTargetPool creates the passed TargetPool func (gce *GCECloud) CreateTargetPool(tp *compute.TargetPool, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetPoolMetricContext("create", region) - return mc.Observe(gce.c.TargetPools().Insert(context.Background(), meta.RegionalKey(tp.Name, region), tp)) + return mc.Observe(gce.c.TargetPools().Insert(ctx, meta.RegionalKey(tp.Name, region), tp)) } // DeleteTargetPool deletes TargetPool by name. func (gce *GCECloud) DeleteTargetPool(name, region string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetPoolMetricContext("delete", region) - return mc.Observe(gce.c.TargetPools().Delete(context.Background(), meta.RegionalKey(name, region))) + return mc.Observe(gce.c.TargetPools().Delete(ctx, meta.RegionalKey(name, region))) } // AddInstancesToTargetPool adds instances by link to the TargetPool func (gce *GCECloud) AddInstancesToTargetPool(name, region string, instanceRefs []*compute.InstanceReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + req := &compute.TargetPoolsAddInstanceRequest{ Instances: instanceRefs, } mc := newTargetPoolMetricContext("add_instances", region) - return mc.Observe(gce.c.TargetPools().AddInstance(context.Background(), meta.RegionalKey(name, region), req)) + return mc.Observe(gce.c.TargetPools().AddInstance(ctx, meta.RegionalKey(name, region), req)) } // RemoveInstancesFromTargetPool removes instances by link to the TargetPool func (gce *GCECloud) RemoveInstancesFromTargetPool(name, region string, instanceRefs []*compute.InstanceReference) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + req := &compute.TargetPoolsRemoveInstanceRequest{ Instances: instanceRefs, } mc := newTargetPoolMetricContext("remove_instances", region) - return mc.Observe(gce.c.TargetPools().RemoveInstance(context.Background(), meta.RegionalKey(name, region), req)) + return mc.Observe(gce.c.TargetPools().RemoveInstance(ctx, meta.RegionalKey(name, region), req)) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetproxy.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetproxy.go index 47a9626fe..f266d13e6 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetproxy.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetproxy.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - compute "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -31,34 +30,49 @@ func newTargetProxyMetricContext(request string) *metricContext { // GetTargetHttpProxy returns the UrlMap by name. func (gce *GCECloud) GetTargetHttpProxy(name string) (*compute.TargetHttpProxy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("get") - v, err := gce.c.TargetHttpProxies().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.TargetHttpProxies().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateTargetHttpProxy creates a TargetHttpProxy func (gce *GCECloud) CreateTargetHttpProxy(proxy *compute.TargetHttpProxy) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("create") - return mc.Observe(gce.c.TargetHttpProxies().Insert(context.Background(), meta.GlobalKey(proxy.Name), proxy)) + return mc.Observe(gce.c.TargetHttpProxies().Insert(ctx, meta.GlobalKey(proxy.Name), proxy)) } // SetUrlMapForTargetHttpProxy sets the given UrlMap for the given TargetHttpProxy. func (gce *GCECloud) SetUrlMapForTargetHttpProxy(proxy *compute.TargetHttpProxy, urlMap *compute.UrlMap) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + ref := &compute.UrlMapReference{UrlMap: urlMap.SelfLink} mc := newTargetProxyMetricContext("set_url_map") - return mc.Observe(gce.c.TargetHttpProxies().SetUrlMap(context.Background(), meta.GlobalKey(proxy.Name), ref)) + return mc.Observe(gce.c.TargetHttpProxies().SetUrlMap(ctx, meta.GlobalKey(proxy.Name), ref)) } // DeleteTargetHttpProxy deletes the TargetHttpProxy by name. func (gce *GCECloud) DeleteTargetHttpProxy(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("delete") - return mc.Observe(gce.c.TargetHttpProxies().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.TargetHttpProxies().Delete(ctx, meta.GlobalKey(name))) } // ListTargetHttpProxies lists all TargetHttpProxies in the project. func (gce *GCECloud) ListTargetHttpProxies() ([]*compute.TargetHttpProxy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("list") - v, err := gce.c.TargetHttpProxies().List(context.Background(), filter.None) + v, err := gce.c.TargetHttpProxies().List(ctx, filter.None) return v, mc.Observe(err) } @@ -66,42 +80,60 @@ func (gce *GCECloud) ListTargetHttpProxies() ([]*compute.TargetHttpProxy, error) // GetTargetHttpsProxy returns the UrlMap by name. func (gce *GCECloud) GetTargetHttpsProxy(name string) (*compute.TargetHttpsProxy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("get") - v, err := gce.c.TargetHttpsProxies().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.TargetHttpsProxies().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateTargetHttpsProxy creates a TargetHttpsProxy func (gce *GCECloud) CreateTargetHttpsProxy(proxy *compute.TargetHttpsProxy) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("create") - return mc.Observe(gce.c.TargetHttpsProxies().Insert(context.Background(), meta.GlobalKey(proxy.Name), proxy)) + return mc.Observe(gce.c.TargetHttpsProxies().Insert(ctx, meta.GlobalKey(proxy.Name), proxy)) } // SetUrlMapForTargetHttpsProxy sets the given UrlMap for the given TargetHttpsProxy. func (gce *GCECloud) SetUrlMapForTargetHttpsProxy(proxy *compute.TargetHttpsProxy, urlMap *compute.UrlMap) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("set_url_map") ref := &compute.UrlMapReference{UrlMap: urlMap.SelfLink} - return mc.Observe(gce.c.TargetHttpsProxies().SetUrlMap(context.Background(), meta.GlobalKey(proxy.Name), ref)) + return mc.Observe(gce.c.TargetHttpsProxies().SetUrlMap(ctx, meta.GlobalKey(proxy.Name), ref)) } // SetSslCertificateForTargetHttpsProxy sets the given SslCertificate for the given TargetHttpsProxy. -func (gce *GCECloud) SetSslCertificateForTargetHttpsProxy(proxy *compute.TargetHttpsProxy, sslCert *compute.SslCertificate) error { +func (gce *GCECloud) SetSslCertificateForTargetHttpsProxy(proxy *compute.TargetHttpsProxy, sslCertURLs []string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("set_ssl_cert") req := &compute.TargetHttpsProxiesSetSslCertificatesRequest{ - SslCertificates: []string{sslCert.SelfLink}, + SslCertificates: sslCertURLs, } - return mc.Observe(gce.c.TargetHttpsProxies().SetSslCertificates(context.Background(), meta.GlobalKey(proxy.Name), req)) + return mc.Observe(gce.c.TargetHttpsProxies().SetSslCertificates(ctx, meta.GlobalKey(proxy.Name), req)) } // DeleteTargetHttpsProxy deletes the TargetHttpsProxy by name. func (gce *GCECloud) DeleteTargetHttpsProxy(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("delete") - return mc.Observe(gce.c.TargetHttpsProxies().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.TargetHttpsProxies().Delete(ctx, meta.GlobalKey(name))) } // ListTargetHttpsProxies lists all TargetHttpsProxies in the project. func (gce *GCECloud) ListTargetHttpsProxies() ([]*compute.TargetHttpsProxy, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newTargetProxyMetricContext("list") - v, err := gce.c.TargetHttpsProxies().List(context.Background(), filter.None) + v, err := gce.c.TargetHttpsProxies().List(ctx, filter.None) return v, mc.Observe(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_test.go index a36027627..9747dfea5 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_test.go @@ -18,16 +18,12 @@ package gce import ( "context" - "encoding/json" "reflect" "strings" "testing" "golang.org/x/oauth2/google" - computealpha "google.golang.org/api/compute/v0.alpha" - computebeta "google.golang.org/api/compute/v0.beta" - computev1 "google.golang.org/api/compute/v1" "k8s.io/kubernetes/pkg/cloudprovider" ) @@ -480,102 +476,40 @@ func TestGenerateCloudConfigs(t *testing.T) { } } -func TestConvertToV1Operation(t *testing.T) { - v1Op := getTestOperation() - enc, _ := v1Op.MarshalJSON() - var op interface{} - var alphaOp computealpha.Operation - var betaOp computebeta.Operation - - if err := json.Unmarshal(enc, &alphaOp); err != nil { - t.Errorf("Failed to unmarshal operation: %v", err) - } - - if err := json.Unmarshal(enc, &betaOp); err != nil { - t.Errorf("Failed to unmarshal operation: %v", err) - } - - op = convertToV1Operation(&alphaOp) - if _, ok := op.(*computev1.Operation); ok { - if !reflect.DeepEqual(op, v1Op) { - t.Errorf("Failed to maintain consistency across conversion") - } - } else { - t.Errorf("Expect output to be type v1 operation, but got %v", op) - } - - op = convertToV1Operation(&betaOp) - if _, ok := op.(*computev1.Operation); ok { - if !reflect.DeepEqual(op, v1Op) { - t.Errorf("Failed to maintain consistency across conversion") - } - } else { - t.Errorf("Expect output to be type v1 operation, but got %v", op) - } -} - -func getTestOperation() *computev1.Operation { - return &computev1.Operation{ - Name: "test", - Description: "test", - Id: uint64(12345), - Error: &computev1.OperationError{ - Errors: []*computev1.OperationErrorErrors{ - { - Code: "555", - Message: "error", - }, - }, - }, - } -} - func TestNewAlphaFeatureGate(t *testing.T) { - knownAlphaFeatures["foo"] = true - knownAlphaFeatures["bar"] = true - testCases := []struct { alphaFeatures []string expectEnabled []string expectDisabled []string - expectError bool }{ // enable foo bar { alphaFeatures: []string{"foo", "bar"}, expectEnabled: []string{"foo", "bar"}, expectDisabled: []string{"aaa"}, - expectError: false, }, // no alpha feature { alphaFeatures: []string{}, expectEnabled: []string{}, expectDisabled: []string{"foo", "bar"}, - expectError: false, }, // unsupported alpha feature { alphaFeatures: []string{"aaa", "foo"}, - expectError: true, expectEnabled: []string{"foo"}, - expectDisabled: []string{"aaa"}, + expectDisabled: []string{}, }, // enable foo { alphaFeatures: []string{"foo"}, expectEnabled: []string{"foo"}, expectDisabled: []string{"bar"}, - expectError: false, }, } for _, tc := range testCases { - featureGate, err := NewAlphaFeatureGate(tc.alphaFeatures) - - if (tc.expectError && err == nil) || (!tc.expectError && err != nil) { - t.Errorf("Expect error to be %v, but got error %v", tc.expectError, err) - } + featureGate := NewAlphaFeatureGate(tc.alphaFeatures) for _, key := range tc.expectEnabled { if !featureGate.Enabled(key) { @@ -588,8 +522,6 @@ func TestNewAlphaFeatureGate(t *testing.T) { } } } - delete(knownAlphaFeatures, "foo") - delete(knownAlphaFeatures, "bar") } func TestGetRegionInURL(t *testing.T) { diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_tpu.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_tpu.go index fe71e57ab..0a78f62cb 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_tpu.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_tpu.go @@ -25,7 +25,7 @@ import ( "github.com/golang/glog" "google.golang.org/api/googleapi" - tpuapi "google.golang.org/api/tpu/v1alpha1" + tpuapi "google.golang.org/api/tpu/v1" "k8s.io/apimachinery/pkg/util/wait" ) @@ -38,16 +38,14 @@ func newTPUService(client *http.Client) (*tpuService, error) { return nil, err } return &tpuService{ - nodesService: tpuapi.NewProjectsLocationsNodesService(s), - operationsService: tpuapi.NewProjectsLocationsOperationsService(s), + projects: tpuapi.NewProjectsService(s), }, nil } // tpuService encapsulates the TPU services on nodes and the operations on the // nodes. type tpuService struct { - nodesService *tpuapi.ProjectsLocationsNodesService - operationsService *tpuapi.ProjectsLocationsOperationsService + projects *tpuapi.ProjectsService } // CreateTPU creates the Cloud TPU node with the specified name in the @@ -59,13 +57,13 @@ func (gce *GCECloud) CreateTPU(ctx context.Context, name, zone string, node *tpu var op *tpuapi.Operation parent := getTPUParentName(gce.projectID, zone) - op, err = gce.tpuService.nodesService.Create(parent, node).NodeId(name).Do() + op, err = gce.tpuService.projects.Locations.Nodes.Create(parent, node).NodeId(name).Do() if err != nil { return nil, err } glog.V(2).Infof("Creating Cloud TPU %q in zone %q with operation %q", name, zone, op.Name) - op, err = gce.waitForTPUOp(30*time.Second, 10*time.Minute, op) + op, err = gce.waitForTPUOp(ctx, op) if err != nil { return nil, err } @@ -92,13 +90,13 @@ func (gce *GCECloud) DeleteTPU(ctx context.Context, name, zone string) error { var op *tpuapi.Operation name = getTPUName(gce.projectID, zone, name) - op, err = gce.tpuService.nodesService.Delete(name).Do() + op, err = gce.tpuService.projects.Locations.Nodes.Delete(name).Do() if err != nil { return err } glog.V(2).Infof("Deleting Cloud TPU %q in zone %q with operation %q", name, zone, op.Name) - op, err = gce.waitForTPUOp(30*time.Second, 10*time.Minute, op) + op, err = gce.waitForTPUOp(ctx, op) if err != nil { return err } @@ -114,7 +112,7 @@ func (gce *GCECloud) GetTPU(ctx context.Context, name, zone string) (*tpuapi.Nod mc := newTPUMetricContext("get", zone) name = getTPUName(gce.projectID, zone, name) - node, err := gce.tpuService.nodesService.Get(name).Do() + node, err := gce.tpuService.projects.Locations.Nodes.Get(name).Do() if err != nil { return nil, mc.Observe(err) } @@ -126,17 +124,36 @@ func (gce *GCECloud) ListTPUs(ctx context.Context, zone string) ([]*tpuapi.Node, mc := newTPUMetricContext("list", zone) parent := getTPUParentName(gce.projectID, zone) - response, err := gce.tpuService.nodesService.List(parent).Do() + response, err := gce.tpuService.projects.Locations.Nodes.List(parent).Do() if err != nil { return nil, mc.Observe(err) } return response.Nodes, mc.Observe(nil) } -// waitForTPUOp checks whether the op is done every interval before the timeout -// occurs. -func (gce *GCECloud) waitForTPUOp(interval, timeout time.Duration, op *tpuapi.Operation) (*tpuapi.Operation, error) { - if err := wait.PollImmediate(interval, timeout, func() (bool, error) { +// ListLocations returns the zones where Cloud TPUs are available. +func (gce *GCECloud) ListLocations(ctx context.Context) ([]*tpuapi.Location, error) { + mc := newTPUMetricContext("list_locations", "") + parent := getTPUProjectURL(gce.projectID) + response, err := gce.tpuService.projects.Locations.List(parent).Do() + if err != nil { + return nil, mc.Observe(err) + } + return response.Locations, mc.Observe(nil) +} + +// waitForTPUOp checks whether the op is done every 30 seconds before the ctx +// is cancelled. +func (gce *GCECloud) waitForTPUOp(ctx context.Context, op *tpuapi.Operation) (*tpuapi.Operation, error) { + if err := wait.PollInfinite(30*time.Second, func() (bool, error) { + // Check if context has been cancelled. + select { + case <-ctx.Done(): + glog.V(3).Infof("Context for operation %q has been cancelled: %s", op.Name, ctx.Err()) + return true, ctx.Err() + default: + } + glog.V(3).Infof("Waiting for operation %q to complete...", op.Name) start := time.Now() @@ -147,7 +164,7 @@ func (gce *GCECloud) waitForTPUOp(interval, timeout time.Duration, op *tpuapi.Op } var err error - op, err = gce.tpuService.operationsService.Get(op.Name).Do() + op, err = gce.tpuService.projects.Locations.Operations.Get(op.Name).Do() if err != nil { return true, err } @@ -165,7 +182,7 @@ func (gce *GCECloud) waitForTPUOp(interval, timeout time.Duration, op *tpuapi.Op // newTPUMetricContext returns a new metricContext used for recording metrics // of Cloud TPU API calls. func newTPUMetricContext(request, zone string) *metricContext { - return newGenericMetricContext("tpus", request, unusedMetricLabel, zone, "alpha") + return newGenericMetricContext("tpus", request, unusedMetricLabel, zone, "v1") } // getErrorFromTPUOp returns the error in the failed op, or nil if the op @@ -180,6 +197,10 @@ func getErrorFromTPUOp(op *tpuapi.Operation) error { return nil } +func getTPUProjectURL(project string) string { + return fmt.Sprintf("projects/%s", project) +} + func getTPUParentName(project, zone string) string { return fmt.Sprintf("projects/%s/locations/%s", project, zone) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_urlmap.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_urlmap.go index 54ceccbf5..b0e60093c 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_urlmap.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_urlmap.go @@ -17,10 +17,9 @@ limitations under the License. package gce import ( - "context" - compute "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) @@ -31,32 +30,47 @@ func newUrlMapMetricContext(request string) *metricContext { // GetUrlMap returns the UrlMap by name. func (gce *GCECloud) GetUrlMap(name string) (*compute.UrlMap, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("get") - v, err := gce.c.UrlMaps().Get(context.Background(), meta.GlobalKey(name)) + v, err := gce.c.UrlMaps().Get(ctx, meta.GlobalKey(name)) return v, mc.Observe(err) } // CreateUrlMap creates a url map func (gce *GCECloud) CreateUrlMap(urlMap *compute.UrlMap) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("create") - return mc.Observe(gce.c.UrlMaps().Insert(context.Background(), meta.GlobalKey(urlMap.Name), urlMap)) + return mc.Observe(gce.c.UrlMaps().Insert(ctx, meta.GlobalKey(urlMap.Name), urlMap)) } // UpdateUrlMap applies the given UrlMap as an update func (gce *GCECloud) UpdateUrlMap(urlMap *compute.UrlMap) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("update") - return mc.Observe(gce.c.UrlMaps().Update(context.Background(), meta.GlobalKey(urlMap.Name), urlMap)) + return mc.Observe(gce.c.UrlMaps().Update(ctx, meta.GlobalKey(urlMap.Name), urlMap)) } // DeleteUrlMap deletes a url map by name. func (gce *GCECloud) DeleteUrlMap(name string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("delete") - return mc.Observe(gce.c.UrlMaps().Delete(context.Background(), meta.GlobalKey(name))) + return mc.Observe(gce.c.UrlMaps().Delete(ctx, meta.GlobalKey(name))) } // ListUrlMaps lists all UrlMaps in the project. func (gce *GCECloud) ListUrlMaps() ([]*compute.UrlMap, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newUrlMapMetricContext("list") - v, err := gce.c.UrlMaps().List(context.Background(), filter.None) + v, err := gce.c.UrlMaps().List(ctx, filter.None) return v, mc.Observe(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_zones.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_zones.go index 6c745e34c..503ca348f 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_zones.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_zones.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" ) @@ -72,8 +73,11 @@ func (gce *GCECloud) GetZoneByNodeName(ctx context.Context, nodeName types.NodeN // ListZonesInRegion returns all zones in a GCP region func (gce *GCECloud) ListZonesInRegion(region string) ([]*compute.Zone, error) { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := newZonesMetricContext("list", region) - list, err := gce.c.Zones().List(context.Background(), filter.Regexp("region", gce.getRegionLink(region))) + list, err := gce.c.Zones().List(ctx, filter.Regexp("region", gce.getRegionLink(region))) if err != nil { return nil, mc.Observe(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/support.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/support.go index 42903af45..7861e08ac 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/support.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/support.go @@ -50,17 +50,26 @@ type gceRateLimiter struct { // operations. func (l *gceRateLimiter) Accept(ctx context.Context, key *cloud.RateLimitKey) error { if key.Operation == "Get" && key.Service == "Operations" { - ch := make(chan struct{}) - go func() { - l.gce.operationPollRateLimiter.Accept() - close(ch) - }() - select { - case <-ch: - break - case <-ctx.Done(): - return ctx.Err() + // Wait a minimum amount of time regardless of rate limiter. + rl := &cloud.MinimumRateLimiter{ + // Convert flowcontrol.RateLimiter into cloud.RateLimiter + RateLimiter: &cloud.AcceptRateLimiter{ + Acceptor: l.gce.operationPollRateLimiter, + }, + Minimum: operationPollInterval, } + return rl.Accept(ctx, key) } return nil } + +// CreateGCECloudWithCloud is a helper function to create an instance of GCECloud with the +// given Cloud interface implementation. Typical usage is to use cloud.NewMockGCE to get a +// handle to a mock Cloud instance and then use that for testing. +func CreateGCECloudWithCloud(config *CloudConfig, c cloud.Cloud) (*GCECloud, error) { + gceCloud, err := CreateGCECloud(config) + if err == nil { + gceCloud.c = c + } + return gceCloud, err +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack.go index c69df4dd1..5f2e6925c 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack.go @@ -415,13 +415,10 @@ func foreachServer(client *gophercloud.ServiceClient, opts servers.ListOptsBuild return err } -func getServerByName(client *gophercloud.ServiceClient, name types.NodeName, showOnlyActive bool) (*servers.Server, error) { +func getServerByName(client *gophercloud.ServiceClient, name types.NodeName) (*servers.Server, error) { opts := servers.ListOpts{ Name: fmt.Sprintf("^%s$", regexp.QuoteMeta(mapNodeNameToServerName(name))), } - if showOnlyActive { - opts.Status = "ACTIVE" - } pager := servers.List(client, opts) @@ -504,7 +501,7 @@ func nodeAddresses(srv *servers.Server) ([]v1.NodeAddress, error) { } func getAddressesByName(client *gophercloud.ServiceClient, name types.NodeName) ([]v1.NodeAddress, error) { - srv, err := getServerByName(client, name, true) + srv, err := getServerByName(client, name) if err != nil { return nil, err } @@ -675,7 +672,7 @@ func (os *OpenStack) GetZoneByNodeName(ctx context.Context, nodeName types.NodeN return cloudprovider.Zone{}, err } - srv, err := getServerByName(compute, nodeName, true) + srv, err := getServerByName(compute, nodeName) if err != nil { if err == ErrNotFound { return cloudprovider.Zone{}, cloudprovider.InstanceNotFound diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_instances.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_instances.go index 826770a3a..638b78508 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_instances.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_instances.go @@ -106,18 +106,6 @@ func (i *Instances) NodeAddressesByProviderID(ctx context.Context, providerID st return addresses, nil } -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (i *Instances) ExternalID(ctx context.Context, name types.NodeName) (string, error) { - srv, err := getServerByName(i.compute, name, true) - if err != nil { - if err == ErrNotFound { - return "", cloudprovider.InstanceNotFound - } - return "", err - } - return srv.ID, nil -} - // InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. func (i *Instances) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) { @@ -142,6 +130,11 @@ func (i *Instances) InstanceExistsByProviderID(ctx context.Context, providerID s return true, nil } +// InstanceShutdownByProviderID returns true if the instances is in safe state to detach volumes +func (i *Instances) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, cloudprovider.NotImplemented +} + // InstanceID returns the kubelet's cloud provider ID. func (os *OpenStack) InstanceID() (string, error) { if len(os.localInstanceID) == 0 { @@ -156,7 +149,7 @@ func (os *OpenStack) InstanceID() (string, error) { // InstanceID returns the cloud provider ID of the specified instance. func (i *Instances) InstanceID(ctx context.Context, name types.NodeName) (string, error) { - srv, err := getServerByName(i.compute, name, true) + srv, err := getServerByName(i.compute, name) if err != nil { if err == ErrNotFound { return "", cloudprovider.InstanceNotFound @@ -189,7 +182,7 @@ func (i *Instances) InstanceTypeByProviderID(ctx context.Context, providerID str // InstanceType returns the type of the specified instance. func (i *Instances) InstanceType(ctx context.Context, name types.NodeName) (string, error) { - srv, err := getServerByName(i.compute, name, true) + srv, err := getServerByName(i.compute, name) if err != nil { return "", err diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go index 1d894db22..f0dad3d55 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go @@ -70,6 +70,7 @@ const ( errorStatus = "ERROR" ServiceAnnotationLoadBalancerFloatingNetworkID = "loadbalancer.openstack.org/floating-network-id" + ServiceAnnotationLoadBalancerSubnetID = "loadbalancer.openstack.org/subnet-id" // ServiceAnnotationLoadBalancerInternal is the annotation used on the service // to indicate that we want an internal loadbalancer service. @@ -367,7 +368,7 @@ func waitLoadbalancerDeleted(client *gophercloud.ServiceClient, loadbalancerID s err := wait.ExponentialBackoff(backoff, func() (bool, error) { _, err := loadbalancers.Get(client, loadbalancerID).Extract() if err != nil { - if err == ErrNotFound { + if isNotFound(err) { return true, nil } return false, err @@ -486,21 +487,27 @@ func (lbaas *LbaasV2) GetLoadBalancer(ctx context.Context, clusterName string, s // The LB needs to be configured with instance addresses on the same // subnet as the LB (aka opts.SubnetID). Currently we're just -// guessing that the node's InternalIP is the right address - and that -// should be sufficient for all "normal" cases. +// guessing that the node's InternalIP is the right address. +// In case no InternalIP can be found, ExternalIP is tried. +// If neither InternalIP nor ExternalIP can be found an error is +// returned. func nodeAddressForLB(node *v1.Node) (string, error) { addrs := node.Status.Addresses if len(addrs) == 0 { return "", ErrNoAddressFound } - for _, addr := range addrs { - if addr.Type == v1.NodeInternalIP { - return addr.Address, nil + allowedAddrTypes := []v1.NodeAddressType{v1.NodeInternalIP, v1.NodeExternalIP} + + for _, allowedAddrType := range allowedAddrTypes { + for _, addr := range addrs { + if addr.Type == allowedAddrType { + return addr.Address, nil + } } } - return addrs[0].Address, nil + return "", ErrNoAddressFound } //getStringFromServiceAnnotation searches a given v1.Service for a specific annotationKey and either returns the annotation's value or a specified defaultSetting @@ -547,14 +554,14 @@ func getSubnetIDForLB(compute *gophercloud.ServiceClient, node v1.Node) (string, } // getNodeSecurityGroupIDForLB lists node-security-groups for specific nodes -func getNodeSecurityGroupIDForLB(compute *gophercloud.ServiceClient, nodes []*v1.Node) ([]string, error) { - nodeSecurityGroupIDs := sets.NewString() +func getNodeSecurityGroupIDForLB(compute *gophercloud.ServiceClient, network *gophercloud.ServiceClient, nodes []*v1.Node) ([]string, error) { + secGroupNames := sets.NewString() for _, node := range nodes { nodeName := types.NodeName(node.Name) - srv, err := getServerByName(compute, nodeName, true) + srv, err := getServerByName(compute, nodeName) if err != nil { - return nodeSecurityGroupIDs.List(), err + return []string{}, err } // use the first node-security-groups @@ -562,11 +569,19 @@ func getNodeSecurityGroupIDForLB(compute *gophercloud.ServiceClient, nodes []*v1 // case 1: node1:SG1 node2:SG2 return SG1,SG2 // case 2: node1:SG1,SG2 node2:SG3,SG4 return SG1,SG3 // case 3: node1:SG1,SG2 node2:SG2,SG3 return SG1,SG2 - securityGroupName := srv.SecurityGroups[0]["name"] - nodeSecurityGroupIDs.Insert(securityGroupName.(string)) + secGroupNames.Insert(srv.SecurityGroups[0]["name"].(string)) } - return nodeSecurityGroupIDs.List(), nil + secGroupIDs := make([]string, secGroupNames.Len()) + for i, name := range secGroupNames.List() { + secGroupID, err := groups.IDFromName(network, name) + if err != nil { + return []string{}, err + } + secGroupIDs[i] = secGroupID + } + + return secGroupIDs, nil } // isSecurityGroupNotFound return true while 'err' is object of gophercloud.ErrResourceNotFound @@ -643,6 +658,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(ctx context.Context, clusterName string return nil, fmt.Errorf("there are no available nodes for LoadBalancer service %s/%s", apiService.Namespace, apiService.Name) } + lbaas.opts.SubnetID = getStringFromServiceAnnotation(apiService, ServiceAnnotationLoadBalancerSubnetID, lbaas.opts.SubnetID) if len(lbaas.opts.SubnetID) == 0 { // Get SubnetID automatically. // The LB needs to be configured with instance addresses on the same subnet, so get SubnetID by one node. @@ -815,6 +831,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(ctx context.Context, clusterName string if !memberExists(members, addr, int(port.NodePort)) { glog.V(4).Infof("Creating member for pool %s", pool.ID) _, err := v2pools.CreateMember(lbaas.lb, pool.ID, v2pools.CreateMemberOpts{ + Name: fmt.Sprintf("member_%s_%d_%s", name, portIndex, node.Name), ProtocolPort: int(port.NodePort), Address: addr, SubnetID: lbaas.opts.SubnetID, @@ -852,6 +869,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(ctx context.Context, clusterName string if monitorID == "" && lbaas.opts.CreateMonitor { glog.V(4).Infof("Creating monitor for pool %s", pool.ID) monitor, err := v2monitors.Create(lbaas.lb, v2monitors.CreateOpts{ + Name: fmt.Sprintf("monitor_%s_%d", name, portIndex), PoolID: pool.ID, Type: string(port.Protocol), Delay: int(lbaas.opts.MonitorDelay.Duration.Seconds()), @@ -987,7 +1005,7 @@ func (lbaas *LbaasV2) ensureSecurityGroup(clusterName string, apiService *v1.Ser // find node-security-group for service var err error if len(lbaas.opts.NodeSecurityGroupIDs) == 0 { - lbaas.opts.NodeSecurityGroupIDs, err = getNodeSecurityGroupIDForLB(lbaas.compute, nodes) + lbaas.opts.NodeSecurityGroupIDs, err = getNodeSecurityGroupIDForLB(lbaas.compute, lbaas.network, nodes) if err != nil { return fmt.Errorf("failed to find node-security-group for loadbalancer service %s/%s: %v", apiService.Namespace, apiService.Name, err) } @@ -1158,6 +1176,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(ctx context.Context, clusterName string loadBalancerName := cloudprovider.GetLoadBalancerName(service) glog.V(4).Infof("UpdateLoadBalancer(%v, %v, %v)", clusterName, loadBalancerName, nodes) + lbaas.opts.SubnetID = getStringFromServiceAnnotation(service, ServiceAnnotationLoadBalancerSubnetID, lbaas.opts.SubnetID) if len(lbaas.opts.SubnetID) == 0 && len(nodes) > 0 { // Get SubnetID automatically. // The LB needs to be configured with instance addresses on the same subnet, so get SubnetID by one node. @@ -1211,17 +1230,17 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(ctx context.Context, clusterName string } // Compose Set of member (addresses) that _should_ exist - addrs := map[string]empty{} + addrs := make(map[string]*v1.Node) for _, node := range nodes { addr, err := nodeAddressForLB(node) if err != nil { return err } - addrs[addr] = empty{} + addrs[addr] = node } // Check for adding/removing members associated with each port - for _, port := range ports { + for portIndex, port := range ports { // Get listener associated with this port listener, ok := lbListeners[portKey{ Protocol: toListenersProtocol(port.Protocol), @@ -1248,12 +1267,13 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(ctx context.Context, clusterName string } // Add any new members for this port - for addr := range addrs { + for addr, node := range addrs { if _, ok := members[addr]; ok && members[addr].ProtocolPort == int(port.NodePort) { // Already exists, do not create member continue } _, err := v2pools.CreateMember(lbaas.lb, pool.ID, v2pools.CreateMemberOpts{ + Name: fmt.Sprintf("member_%s_%d_%s", loadbalancer.Name, portIndex, node.Name), Address: addr, ProtocolPort: int(port.NodePort), SubnetID: lbaas.opts.SubnetID, @@ -1299,7 +1319,7 @@ func (lbaas *LbaasV2) updateSecurityGroup(clusterName string, apiService *v1.Ser originalNodeSecurityGroupIDs := lbaas.opts.NodeSecurityGroupIDs var err error - lbaas.opts.NodeSecurityGroupIDs, err = getNodeSecurityGroupIDForLB(lbaas.compute, nodes) + lbaas.opts.NodeSecurityGroupIDs, err = getNodeSecurityGroupIDForLB(lbaas.compute, lbaas.network, nodes) if err != nil { return fmt.Errorf("failed to find node-security-group for loadbalancer service %s/%s: %v", apiService.Namespace, apiService.Name, err) } @@ -1424,18 +1444,6 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(ctx context.Context, clusterName } } - // get all members associated with each poolIDs - var memberIDs []string - for _, pool := range poolIDs { - membersList, err := getMembersByPoolID(lbaas.lb, pool) - if err != nil && !isNotFound(err) { - return fmt.Errorf("error getting pool members %s: %v", pool, err) - } - for _, member := range membersList { - memberIDs = append(memberIDs, member.ID) - } - } - // delete all monitors for _, monitorID := range monitorIDs { err := v2monitors.Delete(lbaas.lb, monitorID).ExtractErr() @@ -1450,9 +1458,14 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(ctx context.Context, clusterName // delete all members and pools for _, poolID := range poolIDs { + // get members for current pool + membersList, err := getMembersByPoolID(lbaas.lb, poolID) + if err != nil && !isNotFound(err) { + return fmt.Errorf("error getting pool members %s: %v", poolID, err) + } // delete all members for this pool - for _, memberID := range memberIDs { - err := v2pools.DeleteMember(lbaas.lb, poolID, memberID).ExtractErr() + for _, member := range membersList { + err := v2pools.DeleteMember(lbaas.lb, poolID, member.ID).ExtractErr() if err != nil && !isNotFound(err) { return err } @@ -1463,7 +1476,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(ctx context.Context, clusterName } // delete pool - err := v2pools.Delete(lbaas.lb, poolID).ExtractErr() + err = v2pools.Delete(lbaas.lb, poolID).ExtractErr() if err != nil && !isNotFound(err) { return err } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_routes.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_routes.go index 4b0b8047a..3f41c7339 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_routes.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_routes.go @@ -83,9 +83,12 @@ func (r *Routes) ListRoutes(ctx context.Context, clusterName string) ([]*cloudpr var routes []*cloudprovider.Route for _, item := range router.Routes { nodeName, foundNode := nodeNamesByAddr[item.NextHop] + if !foundNode { + nodeName = types.NodeName(item.NextHop) + } route := cloudprovider.Route{ Name: item.DestinationCIDR, - TargetNode: nodeName, //empty if NextHop is unknown + TargetNode: nodeName, //contains the nexthop address if node was not found Blackhole: !foundNode, DestinationCIDR: item.DestinationCIDR, } @@ -225,10 +228,16 @@ func (r *Routes) DeleteRoute(ctx context.Context, clusterName string, route *clo ip, _, _ := net.ParseCIDR(route.DestinationCIDR) isCIDRv6 := ip.To4() == nil - addr, err := getAddressByName(r.compute, route.TargetNode, isCIDRv6) - if err != nil { - return err + var addr string + + // Blackhole routes are orphaned and have no counterpart in OpenStack + if !route.Blackhole { + var err error + addr, err = getAddressByName(r.compute, route.TargetNode, isCIDRv6) + if err != nil { + return err + } } router, err := routers.Get(r.network, r.opts.RouterID).Extract() @@ -239,7 +248,7 @@ func (r *Routes) DeleteRoute(ctx context.Context, clusterName string, route *clo routes := router.Routes index := -1 for i, item := range routes { - if item.DestinationCIDR == route.DestinationCIDR && item.NextHop == addr { + if item.DestinationCIDR == route.DestinationCIDR && (item.NextHop == addr || route.Blackhole && item.NextHop == string(route.TargetNode)) { index = i break } @@ -255,7 +264,8 @@ func (r *Routes) DeleteRoute(ctx context.Context, clusterName string, route *clo routes = routes[:len(routes)-1] unwind, err := updateRoutes(r.network, router, routes) - if err != nil { + // If this was a blackhole route we are done, there are no ports to update + if err != nil || route.Blackhole { return err } defer onFailure.call(unwind) @@ -297,7 +307,7 @@ func (r *Routes) DeleteRoute(ctx context.Context, clusterName string, route *clo } func getPortIDByIP(compute *gophercloud.ServiceClient, targetNode types.NodeName, ipAddress string) (string, error) { - srv, err := getServerByName(compute, targetNode, true) + srv, err := getServerByName(compute, targetNode) if err != nil { return "", err } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_test.go index f577a5305..40855e24a 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_test.go @@ -88,6 +88,11 @@ func TestReadConfig(t *testing.T) { t.Errorf("Should fail when no config is provided: %s", err) } + // Since we are setting env vars, we need to reset old + // values for other tests to succeed. + env := clearEnviron(t) + defer resetEnviron(t, env) + os.Setenv("OS_PASSWORD", "mypass") defer os.Unsetenv("OS_PASSWORD") @@ -681,3 +686,24 @@ func TestToAuth3Options(t *testing.T) { t.Errorf("DomainName %s != %s", ao.DomainName, cfg.Global.DomainName) } } + +func clearEnviron(t *testing.T) []string { + env := os.Environ() + for _, pair := range env { + if strings.HasPrefix(pair, "OS_") { + i := strings.Index(pair, "=") + 1 + os.Unsetenv(pair[:i-1]) + } + } + return env +} +func resetEnviron(t *testing.T, items []string) { + for _, pair := range items { + if strings.HasPrefix(pair, "OS_") { + i := strings.Index(pair, "=") + 1 + if err := os.Setenv(pair[:i-1], pair[i:]); err != nil { + t.Errorf("Setenv(%q, %q) failed during reset: %v", pair[:i-1], pair[i:], err) + } + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_volumes.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_volumes.go index 37c71c36f..f50a23119 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_volumes.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_volumes.go @@ -310,7 +310,8 @@ func (os *OpenStack) OperationPending(diskName string) (bool, string, error) { } volumeStatus := volume.Status if volumeStatus == volumeErrorStatus { - return false, volumeStatus, nil + err = fmt.Errorf("status of volume %s is %s", diskName, volumeStatus) + return false, volumeStatus, err } if volumeStatus == volumeAvailableStatus || volumeStatus == volumeInUseStatus || volumeStatus == volumeDeletedStatus { return false, volume.Status, nil @@ -622,7 +623,7 @@ func (os *OpenStack) DiskIsAttachedByName(nodeName types.NodeName, volumeID stri if err != nil { return false, "", err } - srv, err := getServerByName(cClient, nodeName, false) + srv, err := getServerByName(cClient, nodeName) if err != nil { if err == ErrNotFound { // instance not found anymore in cloudprovider, assume that cinder is detached @@ -659,7 +660,7 @@ func (os *OpenStack) DisksAreAttachedByName(nodeName types.NodeName, volumeIDs [ if err != nil { return attached, err } - srv, err := getServerByName(cClient, nodeName, false) + srv, err := getServerByName(cClient, nodeName) if err != nil { if err == ErrNotFound { // instance not found anymore, mark all volumes as detached diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt.go index 708358eec..686ba8e25 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt.go @@ -196,22 +196,17 @@ func mapNodeNameToInstanceName(nodeName types.NodeName) string { return string(nodeName) } -// ExternalID returns the cloud provider ID of the specified node with the specified NodeName (deprecated). -func (v *OVirtCloud) ExternalID(ctx context.Context, nodeName types.NodeName) (string, error) { - name := mapNodeNameToInstanceName(nodeName) - instance, err := v.fetchInstance(name) - if err != nil { - return "", err - } - return instance.UUID, nil -} - // InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. func (v *OVirtCloud) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) { return false, cloudprovider.NotImplemented } +// InstanceShutdownByProviderID returns true if the instance is in safe state to detach volumes +func (v *OVirtCloud) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, cloudprovider.NotImplemented +} + // InstanceID returns the cloud provider ID of the node with the specified NodeName. func (v *OVirtCloud) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) { name := mapNodeNameToInstanceName(nodeName) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/photon/photon.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/photon/photon.go index 424b6f91a..9411c15f2 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/photon/photon.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/photon/photon.go @@ -454,29 +454,17 @@ func getInstanceID(pc *PCCloud, name string) (string, error) { return vmID, err } -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (pc *PCCloud) ExternalID(ctx context.Context, nodeName k8stypes.NodeName) (string, error) { - name := string(nodeName) - if name == pc.localK8sHostname { - return pc.localInstanceID, nil - } else { - // We assume only master need to get InstanceID of a node other than itself - ID, err := getInstanceID(pc, name) - if err != nil { - glog.Errorf("Photon Cloud Provider: getInstanceID failed for ExternalID. Error[%v]", err) - return ID, err - } else { - return ID, nil - } - } -} - // InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. func (pc *PCCloud) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) { return false, cloudprovider.NotImplemented } +// InstanceShutdownByProviderID returns true if the instance is in safe state to detach volumes +func (pc *PCCloud) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, cloudprovider.NotImplemented +} + // InstanceID returns the cloud provider ID of the specified instance. func (pc *PCCloud) InstanceID(ctx context.Context, nodeName k8stypes.NodeName) (string, error) { name := string(nodeName) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/photon/photon_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/photon/photon_test.go index 6f13f479e..f798f1cc2 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/photon/photon_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/photon/photon_test.go @@ -133,22 +133,7 @@ func TestInstances(t *testing.T) { t.Fatalf("Instances() returned false") } - externalId, err := i.ExternalID(context.TODO(), NodeName) - if err != nil { - t.Fatalf("Instances.ExternalID(%s) failed: %s", testVM, err) - } - t.Logf("Found ExternalID(%s) = %s\n", testVM, externalId) - nonExistingVM := types.NodeName(rand.String(15)) - externalId, err = i.ExternalID(context.TODO(), nonExistingVM) - if err == cloudprovider.InstanceNotFound { - t.Logf("VM %s was not found as expected\n", nonExistingVM) - } else if err == nil { - t.Fatalf("Instances.ExternalID did not fail as expected, VM %s was found", nonExistingVM) - } else { - t.Fatalf("Instances.ExternalID did not fail as expected, err: %v", err) - } - instanceId, err := i.InstanceID(context.TODO(), NodeName) if err != nil { t.Fatalf("Instances.InstanceID(%s) failed: %s", testVM, err) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/BUILD b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/BUILD index f8ebf6270..4c6b27a03 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/BUILD @@ -9,6 +9,7 @@ load( go_library( name = "go_default_library", srcs = [ + "credentialmanager.go", "nodemanager.go", "vsphere.go", "vsphere_util.go", @@ -24,25 +25,38 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/vmware/govmomi/vim25:go_default_library", "//vendor/github.com/vmware/govmomi/vim25/mo:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/gopkg.in/gcfg.v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/listers/core/v1:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", ], ) go_test( name = "go_default_test", - srcs = ["vsphere_test.go"], + srcs = [ + "credentialmanager_test.go", + "vsphere_test.go", + ], embed = [":go_default_library"], deps = [ "//pkg/cloudprovider:go_default_library", "//pkg/cloudprovider/providers/vsphere/vclib:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", + "//pkg/controller:go_default_library", + "//vendor/github.com/vmware/govmomi/lookup/simulator:go_default_library", + "//vendor/github.com/vmware/govmomi/simulator:go_default_library", + "//vendor/github.com/vmware/govmomi/simulator/vpx:go_default_library", + "//vendor/github.com/vmware/govmomi/sts/simulator:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/rand:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/credentialmanager.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/credentialmanager.go new file mode 100644 index 000000000..95862a8a5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/credentialmanager.go @@ -0,0 +1,164 @@ +/* +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 vsphere + +import ( + "errors" + "fmt" + "github.com/golang/glog" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/client-go/listers/core/v1" + "net/http" + "strings" + "sync" +) + +// Error Messages +const ( + CredentialsNotFoundErrMsg = "Credentials not found" + CredentialMissingErrMsg = "Username/Password is missing" + UnknownSecretKeyErrMsg = "Unknown secret key" +) + +// Error constants +var ( + ErrCredentialsNotFound = errors.New(CredentialsNotFoundErrMsg) + ErrCredentialMissing = errors.New(CredentialMissingErrMsg) + ErrUnknownSecretKey = errors.New(UnknownSecretKeyErrMsg) +) + +type SecretCache struct { + cacheLock sync.Mutex + VirtualCenter map[string]*Credential + Secret *corev1.Secret +} + +type Credential struct { + User string `gcfg:"user"` + Password string `gcfg:"password"` +} + +type SecretCredentialManager struct { + SecretName string + SecretNamespace string + SecretLister v1.SecretLister + Cache *SecretCache +} + +// GetCredential returns credentials for the given vCenter Server. +// GetCredential returns error if Secret is not added. +// GetCredential return error is the secret doesn't contain any credentials. +func (secretCredentialManager *SecretCredentialManager) GetCredential(server string) (*Credential, error) { + err := secretCredentialManager.updateCredentialsMap() + if err != nil { + statusErr, ok := err.(*apierrors.StatusError) + if (ok && statusErr.ErrStatus.Code != http.StatusNotFound) || !ok { + return nil, err + } + // Handle secrets deletion by finding credentials from cache + glog.Warningf("secret %q not found in namespace %q", secretCredentialManager.SecretName, secretCredentialManager.SecretNamespace) + } + + credential, found := secretCredentialManager.Cache.GetCredential(server) + if !found { + glog.Errorf("credentials not found for server %q", server) + return nil, ErrCredentialsNotFound + } + return &credential, nil +} + +func (secretCredentialManager *SecretCredentialManager) updateCredentialsMap() error { + if secretCredentialManager.SecretLister == nil { + return fmt.Errorf("SecretLister is not initialized") + } + secret, err := secretCredentialManager.SecretLister.Secrets(secretCredentialManager.SecretNamespace).Get(secretCredentialManager.SecretName) + if err != nil { + glog.Errorf("Cannot get secret %s in namespace %s. error: %q", secretCredentialManager.SecretName, secretCredentialManager.SecretNamespace, err) + return err + } + cacheSecret := secretCredentialManager.Cache.GetSecret() + if cacheSecret != nil && + cacheSecret.GetResourceVersion() == secret.GetResourceVersion() { + glog.V(4).Infof("VCP SecretCredentialManager: Secret %q will not be updated in cache. Since, secrets have same resource version %q", secretCredentialManager.SecretName, cacheSecret.GetResourceVersion()) + return nil + } + secretCredentialManager.Cache.UpdateSecret(secret) + return secretCredentialManager.Cache.parseSecret() +} + +func (cache *SecretCache) GetSecret() *corev1.Secret { + cache.cacheLock.Lock() + defer cache.cacheLock.Unlock() + return cache.Secret +} + +func (cache *SecretCache) UpdateSecret(secret *corev1.Secret) { + cache.cacheLock.Lock() + defer cache.cacheLock.Unlock() + cache.Secret = secret +} + +func (cache *SecretCache) GetCredential(server string) (Credential, bool) { + cache.cacheLock.Lock() + defer cache.cacheLock.Unlock() + credential, found := cache.VirtualCenter[server] + if !found { + return Credential{}, found + } + return *credential, found +} + +func (cache *SecretCache) parseSecret() error { + cache.cacheLock.Lock() + defer cache.cacheLock.Unlock() + return parseConfig(cache.Secret.Data, cache.VirtualCenter) +} + +// parseConfig returns vCenter ip/fdqn mapping to its credentials viz. Username and Password. +func parseConfig(data map[string][]byte, config map[string]*Credential) error { + if len(data) == 0 { + return ErrCredentialMissing + } + for credentialKey, credentialValue := range data { + credentialKey = strings.ToLower(credentialKey) + vcServer := "" + if strings.HasSuffix(credentialKey, "password") { + vcServer = strings.Split(credentialKey, ".password")[0] + if _, ok := config[vcServer]; !ok { + config[vcServer] = &Credential{} + } + config[vcServer].Password = string(credentialValue) + } else if strings.HasSuffix(credentialKey, "username") { + vcServer = strings.Split(credentialKey, ".username")[0] + if _, ok := config[vcServer]; !ok { + config[vcServer] = &Credential{} + } + config[vcServer].User = string(credentialValue) + } else { + glog.Errorf("Unknown secret key %s", credentialKey) + return ErrUnknownSecretKey + } + } + for vcServer, credential := range config { + if credential.User == "" || credential.Password == "" { + glog.Errorf("Username/Password is missing for server %s", vcServer) + return ErrCredentialMissing + } + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/credentialmanager_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/credentialmanager_test.go new file mode 100644 index 000000000..4bef4001f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/credentialmanager_test.go @@ -0,0 +1,338 @@ +/* +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 vsphere + +import ( + "reflect" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/pkg/controller" +) + +func TestSecretCredentialManager_GetCredential(t *testing.T) { + var ( + userKey = "username" + passwordKey = "password" + testUser = "user" + testPassword = "password" + testServer = "0.0.0.0" + testServer2 = "0.0.1.1" + testUserServer2 = "user1" + testPasswordServer2 = "password1" + testIncorrectServer = "1.1.1.1" + ) + var ( + secretName = "vsconf" + secretNamespace = "kube-system" + ) + var ( + addSecretOp = "ADD_SECRET_OP" + getCredentialsOp = "GET_CREDENTIAL_OP" + deleteSecretOp = "DELETE_SECRET_OP" + ) + type GetCredentialsTest struct { + server string + username string + password string + err error + } + type OpSecretTest struct { + secret *corev1.Secret + } + type testEnv struct { + testName string + ops []string + expectedValues []interface{} + } + + client := &fake.Clientset{} + metaObj := metav1.ObjectMeta{ + Name: secretName, + Namespace: secretNamespace, + } + + defaultSecret := &corev1.Secret{ + ObjectMeta: metaObj, + Data: map[string][]byte{ + testServer + "." + userKey: []byte(testUser), + testServer + "." + passwordKey: []byte(testPassword), + }, + } + + multiVCSecret := &corev1.Secret{ + ObjectMeta: metaObj, + Data: map[string][]byte{ + testServer + "." + userKey: []byte(testUser), + testServer + "." + passwordKey: []byte(testPassword), + testServer2 + "." + userKey: []byte(testUserServer2), + testServer2 + "." + passwordKey: []byte(testPasswordServer2), + }, + } + + emptySecret := &corev1.Secret{ + ObjectMeta: metaObj, + Data: map[string][]byte{}, + } + + tests := []testEnv{ + { + testName: "Deleting secret should give the credentials from cache", + ops: []string{addSecretOp, getCredentialsOp, deleteSecretOp, getCredentialsOp}, + expectedValues: []interface{}{ + OpSecretTest{ + secret: defaultSecret, + }, + GetCredentialsTest{ + username: testUser, + password: testPassword, + server: testServer, + }, + OpSecretTest{ + secret: defaultSecret, + }, + GetCredentialsTest{ + username: testUser, + password: testPassword, + server: testServer, + }, + }, + }, + { + testName: "Add secret and get credentials", + ops: []string{addSecretOp, getCredentialsOp}, + expectedValues: []interface{}{ + OpSecretTest{ + secret: defaultSecret, + }, + GetCredentialsTest{ + username: testUser, + password: testPassword, + server: testServer, + }, + }, + }, + { + testName: "Getcredentials should fail by not adding at secret at first time", + ops: []string{getCredentialsOp}, + expectedValues: []interface{}{ + GetCredentialsTest{ + username: testUser, + password: testPassword, + server: testServer, + err: ErrCredentialsNotFound, + }, + }, + }, + { + testName: "GetCredential should fail to get credentials from empty secrets", + ops: []string{addSecretOp, getCredentialsOp}, + expectedValues: []interface{}{ + OpSecretTest{ + secret: emptySecret, + }, + GetCredentialsTest{ + server: testServer, + err: ErrCredentialMissing, + }, + }, + }, + { + testName: "GetCredential should fail to get credentials for invalid server", + ops: []string{addSecretOp, getCredentialsOp}, + expectedValues: []interface{}{ + OpSecretTest{ + secret: defaultSecret, + }, + GetCredentialsTest{ + server: testIncorrectServer, + err: ErrCredentialsNotFound, + }, + }, + }, + { + testName: "GetCredential for multi-vc", + ops: []string{addSecretOp, getCredentialsOp}, + expectedValues: []interface{}{ + OpSecretTest{ + secret: multiVCSecret, + }, + GetCredentialsTest{ + server: testServer2, + username: testUserServer2, + password: testPasswordServer2, + }, + }, + }, + } + + informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc()) + secretInformer := informerFactory.Core().V1().Secrets() + secretCredentialManager := &SecretCredentialManager{ + SecretName: secretName, + SecretNamespace: secretNamespace, + SecretLister: secretInformer.Lister(), + Cache: &SecretCache{ + VirtualCenter: make(map[string]*Credential), + }, + } + cleanupSecretCredentialManager := func() { + secretCredentialManager.Cache.Secret = nil + for key := range secretCredentialManager.Cache.VirtualCenter { + delete(secretCredentialManager.Cache.VirtualCenter, key) + } + secrets, err := secretCredentialManager.SecretLister.List(labels.Everything()) + if err != nil { + t.Fatal("Failed to get all secrets from sharedInformer. error: ", err) + } + for _, secret := range secrets { + secretInformer.Informer().GetIndexer().Delete(secret) + } + } + + for _, test := range tests { + t.Logf("Executing Testcase: %s", test.testName) + for ntest, op := range test.ops { + switch op { + case addSecretOp: + expected := test.expectedValues[ntest].(OpSecretTest) + t.Logf("Adding secret: %s", expected.secret) + err := secretInformer.Informer().GetIndexer().Add(expected.secret) + if err != nil { + t.Fatalf("Failed to add secret to internal cache: %v", err) + } + case getCredentialsOp: + expected := test.expectedValues[ntest].(GetCredentialsTest) + credential, err := secretCredentialManager.GetCredential(expected.server) + t.Logf("Retrieving credentials for server %s", expected.server) + if err != expected.err { + t.Fatalf("Fail to get credentials with error: %v", err) + } + if expected.err == nil { + if expected.username != credential.User || + expected.password != credential.Password { + t.Fatalf("Received credentials %v "+ + "are different than actual credential user:%s password:%s", credential, expected.username, + expected.password) + } + } + case deleteSecretOp: + expected := test.expectedValues[ntest].(OpSecretTest) + t.Logf("Deleting secret: %s", expected.secret) + err := secretInformer.Informer().GetIndexer().Delete(expected.secret) + if err != nil { + t.Fatalf("Failed to delete secret to internal cache: %v", err) + } + } + } + cleanupSecretCredentialManager() + } +} + +func TestParseSecretConfig(t *testing.T) { + var ( + testUsername = "Admin" + testPassword = "Password" + testIP = "10.20.30.40" + ) + var testcases = []struct { + testName string + data map[string][]byte + config map[string]*Credential + expectedError error + }{ + { + testName: "Valid username and password", + data: map[string][]byte{ + "10.20.30.40.username": []byte(testUsername), + "10.20.30.40.password": []byte(testPassword), + }, + config: map[string]*Credential{ + testIP: { + User: testUsername, + Password: testPassword, + }, + }, + expectedError: nil, + }, + { + testName: "Invalid username key with valid password key", + data: map[string][]byte{ + "10.20.30.40.usernam": []byte(testUsername), + "10.20.30.40.password": []byte(testPassword), + }, + config: nil, + expectedError: ErrUnknownSecretKey, + }, + { + testName: "Missing username", + data: map[string][]byte{ + "10.20.30.40.password": []byte(testPassword), + }, + config: map[string]*Credential{ + testIP: { + Password: testPassword, + }, + }, + expectedError: ErrCredentialMissing, + }, + { + testName: "Missing password", + data: map[string][]byte{ + "10.20.30.40.username": []byte(testUsername), + }, + config: map[string]*Credential{ + testIP: { + User: testUsername, + }, + }, + expectedError: ErrCredentialMissing, + }, + { + testName: "IP with unknown key", + data: map[string][]byte{ + "10.20.30.40": []byte(testUsername), + }, + config: nil, + expectedError: ErrUnknownSecretKey, + }, + } + + resultConfig := make(map[string]*Credential) + cleanupResultConfig := func(config map[string]*Credential) { + for k := range config { + delete(config, k) + } + } + + for _, testcase := range testcases { + err := parseConfig(testcase.data, resultConfig) + t.Logf("Executing Testcase: %s", testcase.testName) + if err != testcase.expectedError { + t.Fatalf("Parsing Secret failed for data %+v: %s", testcase.data, err) + } + if testcase.config != nil && !reflect.DeepEqual(testcase.config, resultConfig) { + t.Fatalf("Parsing Secret failed for data %+v expected config %+v and actual config %+v", + testcase.data, resultConfig, testcase.config) + } + cleanupResultConfig(resultConfig) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/nodemanager.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/nodemanager.go index ecdb57570..8b3fe4165 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/nodemanager.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/nodemanager.go @@ -17,12 +17,12 @@ limitations under the License. package vsphere import ( + "context" "fmt" "strings" "sync" "github.com/golang/glog" - "golang.org/x/net/context" "k8s.io/api/core/v1" k8stypes "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib" @@ -45,10 +45,13 @@ type NodeManager struct { nodeInfoMap map[string]*NodeInfo // Maps node name to node structure registeredNodes map[string]*v1.Node + //CredentialsManager + credentialManager *SecretCredentialManager // Mutexes - registeredNodesLock sync.RWMutex - nodeInfoLock sync.RWMutex + registeredNodesLock sync.RWMutex + nodeInfoLock sync.RWMutex + credentialManagerLock sync.Mutex } type NodeDetails struct { @@ -119,7 +122,7 @@ func (nm *NodeManager) DiscoverNode(node *v1.Node) error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - err := vsi.conn.Connect(ctx) + err := nm.vcConnect(ctx, vsi) if err != nil { glog.V(4).Info("Discovering node error vc:", err) setGlobalErr(err) @@ -297,30 +300,17 @@ func (nm *NodeManager) GetNodeInfo(nodeName k8stypes.NodeName) (NodeInfo, error) // // This method is a getter but it can cause side-effect of updating NodeInfo objects. func (nm *NodeManager) GetNodeDetails() ([]NodeDetails, error) { - nm.nodeInfoLock.RLock() - defer nm.nodeInfoLock.RUnlock() + nm.registeredNodesLock.Lock() + defer nm.registeredNodesLock.Unlock() var nodeDetails []NodeDetails - vsphereSessionRefreshMap := make(map[string]bool) - - for nodeName, nodeInfo := range nm.nodeInfoMap { - var n *NodeInfo - var err error - if vsphereSessionRefreshMap[nodeInfo.vcServer] { - // vSphere connection already refreshed. Just refresh VM and Datacenter. - glog.V(4).Infof("Renewing NodeInfo %+v for node %q. No new connection needed.", nodeInfo, nodeName) - n, err = nm.renewNodeInfo(nodeInfo, false) - } else { - // Refresh vSphere connection, VM and Datacenter. - glog.V(4).Infof("Renewing NodeInfo %+v for node %q with new vSphere connection.", nodeInfo, nodeName) - n, err = nm.renewNodeInfo(nodeInfo, true) - vsphereSessionRefreshMap[nodeInfo.vcServer] = true - } + + for nodeName, nodeObj := range nm.registeredNodes { + nodeInfo, err := nm.GetNodeInfoWithNodeObject(nodeObj) if err != nil { return nil, err } - nm.nodeInfoMap[nodeName] = n glog.V(4).Infof("Updated NodeInfo %q for node %q.", nodeInfo, nodeName) - nodeDetails = append(nodeDetails, NodeDetails{nodeName, n.vm, n.vmUUID}) + nodeDetails = append(nodeDetails, NodeDetails{nodeName, nodeInfo.vm, nodeInfo.vmUUID}) } return nodeDetails, nil } @@ -355,13 +345,18 @@ func (nm *NodeManager) renewNodeInfo(nodeInfo *NodeInfo, reconnect bool) (*NodeI return nil, err } if reconnect { - err := vsphereInstance.conn.Connect(ctx) + err := nm.vcConnect(ctx, vsphereInstance) if err != nil { return nil, err } } - vm := nodeInfo.vm.RenewVM(vsphereInstance.conn.GoVmomiClient) - return &NodeInfo{vm: &vm, dataCenter: vm.Datacenter, vcServer: nodeInfo.vcServer}, nil + vm := nodeInfo.vm.RenewVM(vsphereInstance.conn.Client) + return &NodeInfo{ + vm: &vm, + dataCenter: vm.Datacenter, + vcServer: nodeInfo.vcServer, + vmUUID: nodeInfo.vmUUID, + }, nil } func (nodeInfo *NodeInfo) VM() *vclib.VirtualMachine { @@ -370,3 +365,82 @@ func (nodeInfo *NodeInfo) VM() *vclib.VirtualMachine { } return nodeInfo.vm } + +// vcConnect connects to vCenter with existing credentials +// If credentials are invalid: +// 1. It will fetch credentials from credentialManager +// 2. Update the credentials +// 3. Connects again to vCenter with fetched credentials +func (nm *NodeManager) vcConnect(ctx context.Context, vsphereInstance *VSphereInstance) error { + err := vsphereInstance.conn.Connect(ctx) + if err == nil { + return nil + } + + credentialManager := nm.CredentialManager() + if !vclib.IsInvalidCredentialsError(err) || credentialManager == nil { + glog.Errorf("Cannot connect to vCenter with err: %v", err) + return err + } + + glog.V(4).Infof("Invalid credentials. Cannot connect to server %q. "+ + "Fetching credentials from secrets.", vsphereInstance.conn.Hostname) + + // Get latest credentials from SecretCredentialManager + credentials, err := credentialManager.GetCredential(vsphereInstance.conn.Hostname) + if err != nil { + glog.Errorf("Failed to get credentials from Secret Credential Manager with err: %v", err) + return err + } + vsphereInstance.conn.UpdateCredentials(credentials.User, credentials.Password) + return vsphereInstance.conn.Connect(ctx) +} + +// GetNodeInfoWithNodeObject returns a NodeInfo which datacenter, vm and vc server ip address. +// This method returns an error if it is unable find node VCs and DCs listed in vSphere.conf +// NodeInfo returned may not be updated to reflect current VM location. +// +// This method is a getter but it can cause side-effect of updating NodeInfo object. +func (nm *NodeManager) GetNodeInfoWithNodeObject(node *v1.Node) (NodeInfo, error) { + nodeName := node.Name + getNodeInfo := func(nodeName string) *NodeInfo { + nm.nodeInfoLock.RLock() + nodeInfo := nm.nodeInfoMap[nodeName] + nm.nodeInfoLock.RUnlock() + return nodeInfo + } + nodeInfo := getNodeInfo(nodeName) + var err error + if nodeInfo == nil { + // Rediscover node if no NodeInfo found. + glog.V(4).Infof("No VM found for node %q. Initiating rediscovery.", nodeName) + err = nm.DiscoverNode(node) + if err != nil { + glog.Errorf("Error %q node info for node %q not found", err, nodeName) + return NodeInfo{}, err + } + nodeInfo = getNodeInfo(nodeName) + } else { + // Renew the found NodeInfo to avoid stale vSphere connection. + glog.V(4).Infof("Renewing NodeInfo %+v for node %q", nodeInfo, nodeName) + nodeInfo, err = nm.renewNodeInfo(nodeInfo, true) + if err != nil { + glog.Errorf("Error %q occurred while renewing NodeInfo for %q", err, nodeName) + return NodeInfo{}, err + } + nm.addNodeInfo(nodeName, nodeInfo) + } + return *nodeInfo, nil +} + +func (nm *NodeManager) CredentialManager() *SecretCredentialManager { + nm.credentialManagerLock.Lock() + defer nm.credentialManagerLock.Unlock() + return nm.credentialManager +} + +func (nm *NodeManager) UpdateCredentialManager(credentialManager *SecretCredentialManager) { + nm.credentialManagerLock.Lock() + defer nm.credentialManagerLock.Unlock() + nm.credentialManager = credentialManager +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/BUILD b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/BUILD index f1a11cecb..9bb59c3ab 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/BUILD @@ -26,18 +26,17 @@ go_library( deps = [ "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", - "//vendor/github.com/vmware/govmomi:go_default_library", "//vendor/github.com/vmware/govmomi/find:go_default_library", "//vendor/github.com/vmware/govmomi/object:go_default_library", "//vendor/github.com/vmware/govmomi/pbm:go_default_library", "//vendor/github.com/vmware/govmomi/pbm/types:go_default_library", "//vendor/github.com/vmware/govmomi/property:go_default_library", "//vendor/github.com/vmware/govmomi/session:go_default_library", + "//vendor/github.com/vmware/govmomi/sts:go_default_library", "//vendor/github.com/vmware/govmomi/vim25:go_default_library", "//vendor/github.com/vmware/govmomi/vim25/mo:go_default_library", "//vendor/github.com/vmware/govmomi/vim25/soap:go_default_library", "//vendor/github.com/vmware/govmomi/vim25/types:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", ], ) @@ -63,6 +62,7 @@ go_test( "datacenter_test.go", "datastore_test.go", "folder_test.go", + "utils_test.go", "virtualmachine_test.go", ], embed = [":go_default_library"], diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/connection.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/connection.go index d42a091f1..91f0e8a96 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/connection.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/connection.go @@ -17,49 +17,53 @@ limitations under the License. package vclib import ( - "fmt" + "context" + "crypto/tls" + "encoding/pem" + "net" neturl "net/url" "sync" "github.com/golang/glog" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/session" + "github.com/vmware/govmomi/sts" "github.com/vmware/govmomi/vim25" - "golang.org/x/net/context" + "github.com/vmware/govmomi/vim25/soap" ) // VSphereConnection contains information for connecting to vCenter type VSphereConnection struct { - GoVmomiClient *govmomi.Client + Client *vim25.Client Username string Password string Hostname string Port string Insecure bool RoundTripperCount uint + credentialsLock sync.Mutex } var ( clientLock sync.Mutex ) -// Connect makes connection to vCenter and sets VSphereConnection.GoVmomiClient. -// If connection.GoVmomiClient is already set, it obtains the existing user session. -// if user session is not valid, connection.GoVmomiClient will be set to the new client. +// Connect makes connection to vCenter and sets VSphereConnection.Client. +// If connection.Client is already set, it obtains the existing user session. +// if user session is not valid, connection.Client will be set to the new client. func (connection *VSphereConnection) Connect(ctx context.Context) error { var err error clientLock.Lock() defer clientLock.Unlock() - if connection.GoVmomiClient == nil { - connection.GoVmomiClient, err = connection.NewClient(ctx) + if connection.Client == nil { + connection.Client, err = connection.NewClient(ctx) if err != nil { glog.Errorf("Failed to create govmomi client. err: %+v", err) return err } return nil } - m := session.NewManager(connection.GoVmomiClient.Client) + m := session.NewManager(connection.Client) userSession, err := m.UserSession(ctx) if err != nil { glog.Errorf("Error while obtaining user session. err: %+v", err) @@ -69,8 +73,8 @@ func (connection *VSphereConnection) Connect(ctx context.Context) error { return nil } glog.Warningf("Creating new client session since the existing session is not valid or not authenticated") - connection.GoVmomiClient.Logout(ctx) - connection.GoVmomiClient, err = connection.NewClient(ctx) + + connection.Client, err = connection.NewClient(ctx) if err != nil { glog.Errorf("Failed to create govmomi client. err: %+v", err) return err @@ -78,22 +82,96 @@ func (connection *VSphereConnection) Connect(ctx context.Context) error { return nil } +// login calls SessionManager.LoginByToken if certificate and private key are configured, +// otherwise calls SessionManager.Login with user and password. +func (connection *VSphereConnection) login(ctx context.Context, client *vim25.Client) error { + m := session.NewManager(client) + connection.credentialsLock.Lock() + defer connection.credentialsLock.Unlock() + + // TODO: Add separate fields for certificate and private-key. + // For now we can leave the config structs and validation as-is and + // decide to use LoginByToken if the username value is PEM encoded. + b, _ := pem.Decode([]byte(connection.Username)) + if b == nil { + glog.V(3).Infof("SessionManager.Login with username '%s'", connection.Username) + return m.Login(ctx, neturl.UserPassword(connection.Username, connection.Password)) + } + + glog.V(3).Infof("SessionManager.LoginByToken with certificate '%s'", connection.Username) + + cert, err := tls.X509KeyPair([]byte(connection.Username), []byte(connection.Password)) + if err != nil { + glog.Errorf("Failed to load X509 key pair. err: %+v", err) + return err + } + + tokens, err := sts.NewClient(ctx, client) + if err != nil { + glog.Errorf("Failed to create STS client. err: %+v", err) + return err + } + + req := sts.TokenRequest{ + Certificate: &cert, + } + + signer, err := tokens.Issue(ctx, req) + if err != nil { + glog.Errorf("Failed to issue SAML token. err: %+v", err) + return err + } + + header := soap.Header{Security: signer} + + return m.LoginByToken(client.WithHeader(ctx, header)) +} + +// Logout calls SessionManager.Logout for the given connection. +func (connection *VSphereConnection) Logout(ctx context.Context) { + m := session.NewManager(connection.Client) + if err := m.Logout(ctx); err != nil { + glog.Errorf("Logout failed: %s", err) + } +} + // NewClient creates a new govmomi client for the VSphereConnection obj -func (connection *VSphereConnection) NewClient(ctx context.Context) (*govmomi.Client, error) { - url, err := neturl.Parse(fmt.Sprintf("https://%s:%s/sdk", connection.Hostname, connection.Port)) +func (connection *VSphereConnection) NewClient(ctx context.Context) (*vim25.Client, error) { + url, err := soap.ParseURL(net.JoinHostPort(connection.Hostname, connection.Port)) if err != nil { glog.Errorf("Failed to parse URL: %s. err: %+v", url, err) return nil, err } - url.User = neturl.UserPassword(connection.Username, connection.Password) - client, err := govmomi.NewClient(ctx, url, connection.Insecure) + + sc := soap.NewClient(url, connection.Insecure) + client, err := vim25.NewClient(ctx, sc) if err != nil { glog.Errorf("Failed to create new client. err: %+v", err) return nil, err } + err = connection.login(ctx, client) + if err != nil { + return nil, err + } + if glog.V(3) { + s, err := session.NewManager(client).UserSession(ctx) + if err == nil { + glog.Infof("New session ID for '%s' = %s", s.UserName, s.Key) + } + } + if connection.RoundTripperCount == 0 { connection.RoundTripperCount = RoundTripperDefaultCount } client.RoundTripper = vim25.Retry(client.RoundTripper, vim25.TemporaryNetworkError(int(connection.RoundTripperCount))) return client, nil } + +// UpdateCredentials updates username and password. +// Note: Updated username and password will be used when there is no session active +func (connection *VSphereConnection) UpdateCredentials(username string, password string) { + connection.credentialsLock.Lock() + defer connection.credentialsLock.Unlock() + connection.Username = username + connection.Password = password +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/constants.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/constants.go index 451d92411..522f308b8 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/constants.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/constants.go @@ -53,7 +53,8 @@ const ( // Test Constants const ( - testDefaultDatacenter = "DC0" - testDefaultDatastore = "LocalDS_0" + TestDefaultDatacenter = "DC0" + TestDefaultDatastore = "LocalDS_0" + TestDefaultNetwork = "VM Network" testNameNotFound = "enoent" ) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datacenter.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datacenter.go index 8b0a10e9a..96107a4a3 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datacenter.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datacenter.go @@ -17,6 +17,7 @@ limitations under the License. package vclib import ( + "context" "errors" "fmt" "path/filepath" @@ -28,7 +29,6 @@ import ( "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" ) // Datacenter extends the govmomi Datacenter object @@ -39,7 +39,7 @@ type Datacenter struct { // GetDatacenter returns the DataCenter Object for the given datacenterPath // If datacenter is located in a folder, include full path to datacenter else just provide the datacenter name func GetDatacenter(ctx context.Context, connection *VSphereConnection, datacenterPath string) (*Datacenter, error) { - finder := find.NewFinder(connection.GoVmomiClient.Client, true) + finder := find.NewFinder(connection.Client, false) datacenter, err := finder.Datacenter(ctx, datacenterPath) if err != nil { glog.Errorf("Failed to find the datacenter: %s. err: %+v", datacenterPath, err) @@ -52,7 +52,7 @@ func GetDatacenter(ctx context.Context, connection *VSphereConnection, datacente // GetAllDatacenter returns all the DataCenter Objects func GetAllDatacenter(ctx context.Context, connection *VSphereConnection) ([]*Datacenter, error) { var dc []*Datacenter - finder := find.NewFinder(connection.GoVmomiClient.Client, true) + finder := find.NewFinder(connection.Client, false) datacenters, err := finder.DatacenterList(ctx, "*") if err != nil { glog.Errorf("Failed to find the datacenter. err: %+v", err) @@ -155,20 +155,16 @@ func (dc *Datacenter) GetDatastoreByName(ctx context.Context, name string) (*Dat } // GetResourcePool gets the resource pool for the given path -func (dc *Datacenter) GetResourcePool(ctx context.Context, computePath string) (*object.ResourcePool, error) { +func (dc *Datacenter) GetResourcePool(ctx context.Context, resourcePoolPath string) (*object.ResourcePool, error) { finder := getFinder(dc) - var computeResource *object.ComputeResource + var resourcePool *object.ResourcePool var err error - if computePath == "" { - computeResource, err = finder.DefaultComputeResource(ctx) - } else { - computeResource, err = finder.ComputeResource(ctx, computePath) - } + resourcePool, err = finder.ResourcePoolOrDefault(ctx, resourcePoolPath) if err != nil { - glog.Errorf("Failed to get the ResourcePool for computePath '%s'. err: %+v", computePath, err) + glog.Errorf("Failed to get the ResourcePool for path '%s'. err: %+v", resourcePoolPath, err) return nil, err } - return computeResource.ResourcePool(ctx) + return resourcePool, nil } // GetFolderByPath gets the Folder Object from the given folder path diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datacenter_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datacenter_test.go index 284a3edaf..ad7e13921 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datacenter_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datacenter_test.go @@ -47,14 +47,14 @@ func TestDatacenter(t *testing.T) { t.Fatal(err) } - vc := &VSphereConnection{GoVmomiClient: c} + vc := &VSphereConnection{Client: c.Client} _, err = GetDatacenter(ctx, vc, testNameNotFound) if err == nil { t.Error("expected error") } - dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter) + dc, err := GetDatacenter(ctx, vc, TestDefaultDatacenter) if err != nil { t.Error(err) } @@ -74,7 +74,7 @@ func TestDatacenter(t *testing.T) { t.Error("expected error") } - vm, err := dc.GetVMByPath(ctx, testDefaultDatacenter+"/vm/"+avm.Name) + vm, err := dc.GetVMByPath(ctx, TestDefaultDatacenter+"/vm/"+avm.Name) if err != nil { t.Error(err) } @@ -103,7 +103,7 @@ func TestDatacenter(t *testing.T) { t.Error("expected error") } - ds, err := dc.GetDatastoreByName(ctx, testDefaultDatastore) + ds, err := dc.GetDatastoreByName(ctx, TestDefaultDatastore) if err != nil { t.Error(err) } @@ -113,7 +113,7 @@ func TestDatacenter(t *testing.T) { t.Error("expected error") } - _, err = dc.GetFolderByPath(ctx, testDefaultDatacenter+"/vm") + _, err = dc.GetFolderByPath(ctx, TestDefaultDatacenter+"/vm") if err != nil { t.Error(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datastore.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datastore.go index 8fba424bb..8d21789f9 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datastore.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datastore.go @@ -17,14 +17,15 @@ limitations under the License. package vclib import ( + "context" "fmt" + "github.com/golang/glog" "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" ) // Datastore extends the govmomi Datastore object diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datastore_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datastore_test.go index 4300e4d6f..6c6e888cb 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datastore_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/datastore_test.go @@ -45,9 +45,9 @@ func TestDatastore(t *testing.T) { t.Fatal(err) } - vc := &VSphereConnection{GoVmomiClient: c} + vc := &VSphereConnection{Client: c.Client} - dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter) + dc, err := GetDatacenter(ctx, vc, TestDefaultDatacenter) if err != nil { t.Error(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/BUILD b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/BUILD index 6a888195e..377202f4c 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/BUILD @@ -18,7 +18,6 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/vmware/govmomi/object:go_default_library", "//vendor/github.com/vmware/govmomi/vim25/types:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/vdm.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/vdm.go index 3e6d9b2ec..a643241bd 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/vdm.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/vdm.go @@ -17,10 +17,9 @@ limitations under the License. package diskmanagers import ( + "context" "time" - "golang.org/x/net/context" - "github.com/golang/glog" "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/types" diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/virtualdisk.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/virtualdisk.go index 533f49ece..fe905cc79 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/virtualdisk.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/virtualdisk.go @@ -17,10 +17,10 @@ limitations under the License. package diskmanagers import ( + "context" "fmt" "github.com/golang/glog" - "golang.org/x/net/context" "k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib" ) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/vmdm.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/vmdm.go index 6942dffb7..1979d5725 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/vmdm.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/diskmanagers/vmdm.go @@ -17,6 +17,7 @@ limitations under the License. package diskmanagers import ( + "context" "fmt" "hash/fnv" "strings" @@ -24,7 +25,6 @@ import ( "github.com/golang/glog" "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" "k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib" ) diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/folder.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/folder.go index 35294b5d4..4e66de88d 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/folder.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/folder.go @@ -17,9 +17,10 @@ limitations under the License. package vclib import ( + "context" + "github.com/golang/glog" "github.com/vmware/govmomi/object" - "golang.org/x/net/context" ) // Folder extends the govmomi Folder object diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/folder_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/folder_test.go index 315d008dc..be570d80d 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/folder_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/folder_test.go @@ -47,9 +47,9 @@ func TestFolder(t *testing.T) { t.Fatal(err) } - vc := &VSphereConnection{GoVmomiClient: c} + vc := &VSphereConnection{Client: c.Client} - dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter) + dc, err := GetDatacenter(ctx, vc, TestDefaultDatacenter) if err != nil { t.Error(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/pbm.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/pbm.go index 5ec83c62b..0a494f7d7 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/pbm.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/pbm.go @@ -17,11 +17,11 @@ limitations under the License. package vclib import ( + "context" "fmt" "github.com/golang/glog" "github.com/vmware/govmomi/pbm" - "golang.org/x/net/context" pbmtypes "github.com/vmware/govmomi/pbm/types" "github.com/vmware/govmomi/vim25" diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/utils.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/utils.go index d449e5fe9..36ea8d6c6 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/utils.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/utils.go @@ -46,7 +46,7 @@ func IsNotFound(err error) bool { } func getFinder(dc *Datacenter) *find.Finder { - finder := find.NewFinder(dc.Client(), true) + finder := find.NewFinder(dc.Client(), false) finder.SetDatacenter(dc.Datacenter) return finder } @@ -172,6 +172,15 @@ func IsManagedObjectNotFoundError(err error) bool { return isManagedObjectNotFoundError } +// IsInvalidCredentialsError returns true if error is of type InvalidLogin +func IsInvalidCredentialsError(err error) bool { + isInvalidCredentialsError := false + if soap.IsSoapFault(err) { + _, isInvalidCredentialsError = soap.ToSoapFault(err).VimFault().(types.InvalidLogin) + } + return isInvalidCredentialsError +} + // VerifyVolumePathsForVM verifies if the volume paths (volPaths) are attached to VM. func VerifyVolumePathsForVM(vmMo mo.VirtualMachine, volPaths []string, nodeName string, nodeVolumeMap map[string]map[string]bool) { // Verify if the volume paths are present on the VM backing virtual disk devices diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/utils_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/utils_test.go new file mode 100644 index 000000000..436055cf1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/utils_test.go @@ -0,0 +1,71 @@ +/* +Copyright 2018 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 vclib + +import ( + "context" + "testing" + + "github.com/vmware/govmomi" + "github.com/vmware/govmomi/simulator" +) + +func TestUtils(t *testing.T) { + ctx := context.Background() + + model := simulator.VPX() + // Child folder "F0" will be created under the root folder and datacenter folders, + // and all resources are created within the "F0" child folders. + model.Folder = 1 + + defer model.Remove() + err := model.Create() + if err != nil { + t.Fatal(err) + } + + s := model.Service.NewServer() + defer s.Close() + + c, err := govmomi.NewClient(ctx, s.URL, true) + if err != nil { + t.Fatal(err) + } + + vc := &VSphereConnection{Client: c.Client} + + dc, err := GetDatacenter(ctx, vc, TestDefaultDatacenter) + if err != nil { + t.Error(err) + } + + finder := getFinder(dc) + datastores, err := finder.DatastoreList(ctx, "*") + if err != nil { + t.Fatal(err) + } + + count := model.Count() + if count.Datastore != len(datastores) { + t.Errorf("got %d Datastores, expected: %d", len(datastores), count.Datastore) + } + + _, err = finder.Datastore(ctx, testNameNotFound) + if !IsNotFound(err) { + t.Errorf("unexpected error: %s", err) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/virtualmachine.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/virtualmachine.go index 679d827ad..01654b3d1 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/virtualmachine.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/virtualmachine.go @@ -23,9 +23,9 @@ import ( "time" "github.com/golang/glog" - "github.com/vmware/govmomi" "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" ) @@ -403,8 +403,8 @@ func (vm *VirtualMachine) deleteController(ctx context.Context, controllerDevice } // RenewVM renews this virtual machine with new client connection. -func (vm *VirtualMachine) RenewVM(client *govmomi.Client) VirtualMachine { - dc := Datacenter{Datacenter: object.NewDatacenter(client.Client, vm.Datacenter.Reference())} - newVM := object.NewVirtualMachine(client.Client, vm.VirtualMachine.Reference()) +func (vm *VirtualMachine) RenewVM(client *vim25.Client) VirtualMachine { + dc := Datacenter{Datacenter: object.NewDatacenter(client, vm.Datacenter.Reference())} + newVM := object.NewVirtualMachine(client, vm.VirtualMachine.Reference()) return VirtualMachine{VirtualMachine: newVM, Datacenter: &dc} } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/virtualmachine_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/virtualmachine_test.go index 0b38fd1be..ca2ef9665 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/virtualmachine_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib/virtualmachine_test.go @@ -43,9 +43,9 @@ func TestVirtualMachine(t *testing.T) { t.Fatal(err) } - vc := &VSphereConnection{GoVmomiClient: c} + vc := &VSphereConnection{Client: c.Client} - dc, err := GetDatacenter(ctx, vc, testDefaultDatacenter) + dc, err := GetDatacenter(ctx, vc, TestDefaultDatacenter) if err != nil { t.Error(err) } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vsphere.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vsphere.go index 2eb7523bd..27b0d8444 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vsphere.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vsphere.go @@ -17,6 +17,7 @@ limitations under the License. package vsphere import ( + "context" "errors" "fmt" "io" @@ -32,7 +33,6 @@ import ( "gopkg.in/gcfg.v1" "github.com/golang/glog" - "golang.org/x/net/context" "k8s.io/api/core/v1" k8stypes "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/informers" @@ -61,6 +61,18 @@ var datastoreFolderIDMap = make(map[string]map[string]string) var cleanUpRoutineInitLock sync.Mutex var cleanUpDummyVMLock sync.RWMutex +// Error Messages +const ( + MissingUsernameErrMsg = "Username is missing" + MissingPasswordErrMsg = "Password is missing" +) + +// Error constants +var ( + ErrUsernameMissing = errors.New(MissingUsernameErrMsg) + ErrPasswordMissing = errors.New(MissingPasswordErrMsg) +) + // VSphere is an implementation of cloud provider Interface for VSphere. type VSphere struct { cfg *VSphereConfig @@ -68,8 +80,9 @@ type VSphere struct { // Maps the VSphere IP address to VSphereInstance vsphereInstanceMap map[string]*VSphereInstance // Responsible for managing discovery of k8s node, their location etc. - nodeManager *NodeManager - vmUUID string + nodeManager *NodeManager + vmUUID string + isSecretInfoProvided bool } // Represents a vSphere instance where one or more kubernetes nodes are running. @@ -131,6 +144,10 @@ type VSphereConfig struct { // Combining the WorkingDir and VMName can form a unique InstanceID. // When vm-name is set, no username/password is required on worker nodes. VMName string `gcfg:"vm-name"` + // Name of the secret were vCenter credentials are present. + SecretName string `gcfg:"secret-name"` + // Secret Namespace where secret will be present that has vCenter credentials. + SecretNamespace string `gcfg:"secret-namespace"` } VirtualCenter map[string]*VirtualCenterConfig @@ -217,6 +234,18 @@ func (vs *VSphere) SetInformers(informerFactory informers.SharedInformerFactory) return } + if vs.isSecretInfoProvided { + secretCredentialManager := &SecretCredentialManager{ + SecretName: vs.cfg.Global.SecretName, + SecretNamespace: vs.cfg.Global.SecretNamespace, + SecretLister: informerFactory.Core().V1().Secrets().Lister(), + Cache: &SecretCache{ + VirtualCenter: make(map[string]*Credential), + }, + } + vs.nodeManager.UpdateCredentialManager(secretCredentialManager) + } + // Only on controller node it is required to register listeners. // Register callbacks for node updates glog.V(4).Infof("Setting up node informers for vSphere Cloud Provider") @@ -226,6 +255,7 @@ func (vs *VSphere) SetInformers(informerFactory informers.SharedInformerFactory) DeleteFunc: vs.NodeDeleted, }) glog.V(4).Infof("Node informers in vSphere cloud provider initialized") + } // Creates new worker node interface and returns @@ -247,19 +277,40 @@ func newWorkerNode() (*VSphere, error) { func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance, error) { vsphereInstanceMap := make(map[string]*VSphereInstance) + isSecretInfoProvided := true + + if cfg.Global.SecretName == "" || cfg.Global.SecretNamespace == "" { + glog.Warningf("SecretName and/or SecretNamespace is not provided. " + + "VCP will use username and password from config file") + isSecretInfoProvided = false + } + + if isSecretInfoProvided { + if cfg.Global.User != "" { + glog.Warning("Global.User and Secret info provided. VCP will use secret to get credentials") + cfg.Global.User = "" + } + if cfg.Global.Password != "" { + glog.Warning("Global.Password and Secret info provided. VCP will use secret to get credentials") + cfg.Global.Password = "" + } + } // Check if the vsphere.conf is in old format. In this // format the cfg.VirtualCenter will be nil or empty. if cfg.VirtualCenter == nil || len(cfg.VirtualCenter) == 0 { glog.V(4).Infof("Config is not per virtual center and is in old format.") - if cfg.Global.User == "" { - glog.Error("Global.User is empty!") - return nil, errors.New("Global.User is empty!") - } - if cfg.Global.Password == "" { - glog.Error("Global.Password is empty!") - return nil, errors.New("Global.Password is empty!") + if !isSecretInfoProvided { + if cfg.Global.User == "" { + glog.Error("Global.User is empty!") + return nil, ErrUsernameMissing + } + if cfg.Global.Password == "" { + glog.Error("Global.Password is empty!") + return nil, ErrPasswordMissing + } } + if cfg.Global.WorkingDir == "" { glog.Error("Global.WorkingDir is empty!") return nil, errors.New("Global.WorkingDir is empty!") @@ -285,6 +336,8 @@ func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance RoundTripperCount: cfg.Global.RoundTripperCount, } + // Note: If secrets info is provided username and password will be populated + // once secret is created. vSphereConn := vclib.VSphereConnection{ Username: vcConfig.User, Password: vcConfig.Password, @@ -305,31 +358,44 @@ func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance glog.Error(msg) return nil, errors.New(msg) } + for vcServer, vcConfig := range cfg.VirtualCenter { glog.V(4).Infof("Initializing vc server %s", vcServer) if vcServer == "" { glog.Error("vsphere.conf does not have the VirtualCenter IP address specified") return nil, errors.New("vsphere.conf does not have the VirtualCenter IP address specified") } - if vcConfig.User == "" { - vcConfig.User = cfg.Global.User - } - if vcConfig.Password == "" { - vcConfig.Password = cfg.Global.Password - } - if vcConfig.User == "" { - msg := fmt.Sprintf("vcConfig.User is empty for vc %s!", vcServer) - glog.Error(msg) - return nil, errors.New(msg) - } - if vcConfig.Password == "" { - msg := fmt.Sprintf("vcConfig.Password is empty for vc %s!", vcServer) - glog.Error(msg) - return nil, errors.New(msg) + + if !isSecretInfoProvided { + if vcConfig.User == "" { + vcConfig.User = cfg.Global.User + if vcConfig.User == "" { + glog.Errorf("vcConfig.User is empty for vc %s!", vcServer) + return nil, ErrUsernameMissing + } + } + if vcConfig.Password == "" { + vcConfig.Password = cfg.Global.Password + if vcConfig.Password == "" { + glog.Errorf("vcConfig.Password is empty for vc %s!", vcServer) + return nil, ErrPasswordMissing + } + } + } else { + if vcConfig.User != "" { + glog.Warningf("vcConfig.User for server %s and Secret info provided. VCP will use secret to get credentials", vcServer) + vcConfig.User = "" + } + if vcConfig.Password != "" { + glog.Warningf("vcConfig.Password for server %s and Secret info provided. VCP will use secret to get credentials", vcServer) + vcConfig.Password = "" + } } + if vcConfig.VCenterPort == "" { vcConfig.VCenterPort = cfg.Global.VCenterPort } + if vcConfig.Datacenters == "" { if cfg.Global.Datacenters != "" { vcConfig.Datacenters = cfg.Global.Datacenters @@ -342,6 +408,8 @@ func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance vcConfig.RoundTripperCount = cfg.Global.RoundTripperCount } + // Note: If secrets info is provided username and password will be populated + // once secret is created. vSphereConn := vclib.VSphereConnection{ Username: vcConfig.User, Password: vcConfig.Password, @@ -360,9 +428,35 @@ func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance return vsphereInstanceMap, nil } -// Creates new Contreoller node interface and returns +// getVMUUID allows tests to override GetVMUUID +var getVMUUID = GetVMUUID + +// Creates new Controller node interface and returns func newControllerNode(cfg VSphereConfig) (*VSphere, error) { - var err error + vs, err := buildVSphereFromConfig(cfg) + if err != nil { + return nil, err + } + vs.hostName, err = os.Hostname() + if err != nil { + glog.Errorf("Failed to get hostname. err: %+v", err) + return nil, err + } + vs.vmUUID, err = getVMUUID() + if err != nil { + glog.Errorf("Failed to get uuid. err: %+v", err) + return nil, err + } + runtime.SetFinalizer(vs, logout) + return vs, nil +} + +// Initializes vSphere from vSphere CloudProvider Configuration +func buildVSphereFromConfig(cfg VSphereConfig) (*VSphere, error) { + isSecretInfoProvided := false + if cfg.Global.SecretName != "" && cfg.Global.SecretNamespace != "" { + isSecretInfoProvided = true + } if cfg.Disk.SCSIControllerType == "" { cfg.Disk.SCSIControllerType = vclib.PVSCSIControllerType @@ -391,27 +485,16 @@ func newControllerNode(cfg VSphereConfig) (*VSphere, error) { nodeInfoMap: make(map[string]*NodeInfo), registeredNodes: make(map[string]*v1.Node), }, - cfg: &cfg, - } - - vs.hostName, err = os.Hostname() - if err != nil { - glog.Errorf("Failed to get hostname. err: %+v", err) - return nil, err - } - vs.vmUUID, err = GetVMUUID() - if err != nil { - glog.Errorf("Failed to get uuid. err: %+v", err) - return nil, err + isSecretInfoProvided: isSecretInfoProvided, + cfg: &cfg, } - runtime.SetFinalizer(&vs, logout) return &vs, nil } func logout(vs *VSphere) { for _, vsphereIns := range vs.vsphereInstanceMap { - if vsphereIns.conn.GoVmomiClient != nil { - vsphereIns.conn.GoVmomiClient.Logout(context.TODO()) + if vsphereIns.conn.Client != nil { + vsphereIns.conn.Logout(context.TODO()) } } @@ -477,7 +560,7 @@ func (vs *VSphere) getVSphereInstanceForServer(vcServer string, ctx context.Cont return nil, errors.New(fmt.Sprintf("Cannot find node %q in vsphere configuration map", vcServer)) } // Ensure client is logged in and session is valid - err := vsphereIns.conn.Connect(ctx) + err := vs.nodeManager.vcConnect(ctx, vsphereIns) if err != nil { glog.Errorf("failed connecting to vcServer %q with error %+v", vcServer, err) return nil, err @@ -516,7 +599,7 @@ func (vs *VSphere) NodeAddresses(ctx context.Context, nodeName k8stypes.NodeName return nil, err } // Ensure client is logged in and session is valid - err = vsi.conn.Connect(ctx) + err = vs.nodeManager.vcConnect(ctx, vsi) if err != nil { return nil, err } @@ -577,11 +660,6 @@ func convertToK8sType(vmName string) k8stypes.NodeName { return k8stypes.NodeName(vmName) } -// ExternalID returns the cloud provider ID of the node with the specified Name (deprecated). -func (vs *VSphere) ExternalID(ctx context.Context, nodeName k8stypes.NodeName) (string, error) { - return vs.InstanceID(ctx, nodeName) -} - // InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. func (vs *VSphere) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) { @@ -610,6 +688,11 @@ func (vs *VSphere) InstanceExistsByProviderID(ctx context.Context, providerID st return false, err } +// InstanceShutdownByProviderID returns true if the instance is in safe state to detach volumes +func (vs *VSphere) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, cloudprovider.NotImplemented +} + // InstanceID returns the cloud provider ID of the node with the specified Name. func (vs *VSphere) InstanceID(ctx context.Context, nodeName k8stypes.NodeName) (string, error) { @@ -631,7 +714,7 @@ func (vs *VSphere) InstanceID(ctx context.Context, nodeName k8stypes.NodeName) ( return "", err } // Ensure client is logged in and session is valid - err = vsi.conn.Connect(ctx) + err = vs.nodeManager.vcConnect(ctx, vsi) if err != nil { return "", err } @@ -722,7 +805,7 @@ func (vs *VSphere) AttachDisk(vmDiskPath string, storagePolicyName string, nodeN return "", err } // Ensure client is logged in and session is valid - err = vsi.conn.Connect(ctx) + err = vs.nodeManager.vcConnect(ctx, vsi) if err != nil { return "", err } @@ -789,7 +872,7 @@ func (vs *VSphere) DetachDisk(volPath string, nodeName k8stypes.NodeName) error return err } // Ensure client is logged in and session is valid - err = vsi.conn.Connect(ctx) + err = vs.nodeManager.vcConnect(ctx, vsi) if err != nil { return err } @@ -844,7 +927,7 @@ func (vs *VSphere) DiskIsAttached(volPath string, nodeName k8stypes.NodeName) (b return false, err } // Ensure client is logged in and session is valid - err = vsi.conn.Connect(ctx) + err = vs.nodeManager.vcConnect(ctx, vsi) if err != nil { return false, err } diff --git a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vsphere_test.go b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vsphere_test.go index 86a0c4026..0533405b1 100644 --- a/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vsphere_test.go +++ b/vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vsphere_test.go @@ -17,19 +17,49 @@ limitations under the License. package vsphere import ( + "context" + "crypto/tls" "log" "os" "strconv" "strings" "testing" - "golang.org/x/net/context" + lookup "github.com/vmware/govmomi/lookup/simulator" + "github.com/vmware/govmomi/simulator" + "github.com/vmware/govmomi/simulator/vpx" + sts "github.com/vmware/govmomi/sts/simulator" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere/vclib" ) +// localhostCert was generated from crypto/tls/generate_cert.go with the following command: +// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h +var localhostCert = `-----BEGIN CERTIFICATE----- +MIIBjzCCATmgAwIBAgIRAKpi2WmTcFrVjxrl5n5YDUEwDQYJKoZIhvcNAQELBQAw +EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2 +MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC +QQC9fEbRszP3t14Gr4oahV7zFObBI4TfA5i7YnlMXeLinb7MnvT4bkfOJzE6zktn +59zP7UiHs3l4YOuqrjiwM413AgMBAAGjaDBmMA4GA1UdDwEB/wQEAwICpDATBgNV +HSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MC4GA1UdEQQnMCWCC2V4 +YW1wbGUuY29thwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUA +A0EAUsVE6KMnza/ZbodLlyeMzdo7EM/5nb5ywyOxgIOCf0OOLHsPS9ueGLQX9HEG +//yjTXuhNcUugExIjM/AIwAZPQ== +-----END CERTIFICATE-----` + +// localhostKey is the private key for localhostCert. +var localhostKey = `-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBAL18RtGzM/e3XgavihqFXvMU5sEjhN8DmLtieUxd4uKdvsye9Phu +R84nMTrOS2fn3M/tSIezeXhg66quOLAzjXcCAwEAAQJBAKcRxH9wuglYLBdI/0OT +BLzfWPZCEw1vZmMR2FF1Fm8nkNOVDPleeVGTWoOEcYYlQbpTmkGSxJ6ya+hqRi6x +goECIQDx3+X49fwpL6B5qpJIJMyZBSCuMhH4B7JevhGGFENi3wIhAMiNJN5Q3UkL +IuSvv03kaPR5XVQ99/UeEetUgGvBcABpAiBJSBzVITIVCGkGc7d+RCf49KTCIklv +bGWObufAR8Ni4QIgWpILjW8dkGg8GOUZ0zaNA6Nvt6TIv2UWGJ4v5PoV98kCIQDx +rIiZs5QbKdycsv9gQJzwQAogC8o04X3Zz3dsoX+h4A== +-----END RSA PRIVATE KEY-----` + func configFromEnv() (cfg VSphereConfig, ok bool) { var InsecureFlag bool var err error @@ -59,6 +89,61 @@ func configFromEnv() (cfg VSphereConfig, ok bool) { return } +// configFromSim starts a vcsim instance and returns config for use against the vcsim instance. +func configFromSim() (VSphereConfig, func()) { + var cfg VSphereConfig + model := simulator.VPX() + + err := model.Create() + if err != nil { + log.Fatal(err) + } + + model.Service.TLS = new(tls.Config) + s := model.Service.NewServer() + + // STS simulator + path, handler := sts.New(s.URL, vpx.Setting) + model.Service.ServeMux.Handle(path, handler) + + // Lookup Service simulator + model.Service.RegisterSDK(lookup.New()) + + cfg.Global.InsecureFlag = true + cfg.Global.VCenterIP = s.URL.Hostname() + cfg.Global.VCenterPort = s.URL.Port() + cfg.Global.User = s.URL.User.Username() + cfg.Global.Password, _ = s.URL.User.Password() + cfg.Global.Datacenter = vclib.TestDefaultDatacenter + cfg.Network.PublicNetwork = vclib.TestDefaultNetwork + cfg.Global.DefaultDatastore = vclib.TestDefaultDatastore + cfg.Disk.SCSIControllerType = os.Getenv("VSPHERE_SCSICONTROLLER_TYPE") + cfg.Global.WorkingDir = os.Getenv("VSPHERE_WORKING_DIR") + cfg.Global.VMName = os.Getenv("VSPHERE_VM_NAME") + + if cfg.Global.WorkingDir == "" { + cfg.Global.WorkingDir = "vm" // top-level Datacenter.VmFolder + } + + uuid := simulator.Map.Any("VirtualMachine").(*simulator.VirtualMachine).Config.Uuid + getVMUUID = func() (string, error) { return uuid, nil } + + return cfg, func() { + getVMUUID = GetVMUUID + s.Close() + model.Remove() + } +} + +// configFromEnvOrSim returns config from configFromEnv if set, otherwise returns configFromSim. +func configFromEnvOrSim() (VSphereConfig, func()) { + cfg, ok := configFromEnv() + if ok { + return cfg, func() {} + } + return configFromSim() +} + func TestReadConfig(t *testing.T) { _, err := readConfig(nil) if err == nil { @@ -110,10 +195,8 @@ func TestNewVSphere(t *testing.T) { } func TestVSphereLogin(t *testing.T) { - cfg, ok := configFromEnv() - if !ok { - t.Skipf("No config found in environment") - } + cfg, cleanup := configFromEnvOrSim() + defer cleanup() // Create vSphere configuration object vs, err := newControllerNode(cfg) @@ -126,8 +209,37 @@ func TestVSphereLogin(t *testing.T) { defer cancel() // Create vSphere client - var vcInstance *VSphereInstance - if vcInstance, ok = vs.vsphereInstanceMap[cfg.Global.VCenterIP]; !ok { + vcInstance, ok := vs.vsphereInstanceMap[cfg.Global.VCenterIP] + if !ok { + t.Fatalf("Couldn't get vSphere instance: %s", cfg.Global.VCenterIP) + } + + err = vcInstance.conn.Connect(ctx) + if err != nil { + t.Errorf("Failed to connect to vSphere: %s", err) + } + vcInstance.conn.Logout(ctx) +} + +func TestVSphereLoginByToken(t *testing.T) { + cfg, cleanup := configFromSim() + defer cleanup() + + // Configure for SAML token auth + cfg.Global.User = localhostCert + cfg.Global.Password = localhostKey + + // Create vSphere configuration object + vs, err := newControllerNode(cfg) + if err != nil { + t.Fatalf("Failed to construct/authenticate vSphere: %s", err) + } + + ctx := context.Background() + + // Create vSphere client + vcInstance, ok := vs.vsphereInstanceMap[cfg.Global.VCenterIP] + if !ok { t.Fatalf("Couldn't get vSphere instance: %s", cfg.Global.VCenterIP) } @@ -135,7 +247,7 @@ func TestVSphereLogin(t *testing.T) { if err != nil { t.Errorf("Failed to connect to vSphere: %s", err) } - defer vcInstance.conn.GoVmomiClient.Logout(ctx) + vcInstance.conn.Logout(ctx) } func TestZones(t *testing.T) { @@ -174,22 +286,7 @@ func TestInstances(t *testing.T) { t.Fatalf("CurrentNodeName() failed: %s", err) } - externalID, err := i.ExternalID(context.TODO(), nodeName) - if err != nil { - t.Fatalf("Instances.ExternalID(%s) failed: %s", nodeName, err) - } - t.Logf("Found ExternalID(%s) = %s\n", nodeName, externalID) - nonExistingVM := types.NodeName(rand.String(15)) - externalID, err = i.ExternalID(context.TODO(), nonExistingVM) - if err == cloudprovider.InstanceNotFound { - t.Logf("VM %s was not found as expected\n", nonExistingVM) - } else if err == nil { - t.Fatalf("Instances.ExternalID did not fail as expected, VM %s was found", nonExistingVM) - } else { - t.Fatalf("Instances.ExternalID did not fail as expected, err: %v", err) - } - instanceID, err := i.InstanceID(context.TODO(), nodeName) if err != nil { t.Fatalf("Instances.InstanceID(%s) failed: %s", nodeName, err) @@ -255,3 +352,221 @@ func TestVolumes(t *testing.T) { // t.Fatalf("Cannot delete VMDK volume %s: %v", volPath, err) // } } + +func TestSecretVSphereConfig(t *testing.T) { + var vs *VSphere + var ( + username = "user" + password = "password" + ) + var testcases = []struct { + testName string + conf string + expectedIsSecretProvided bool + expectedUsername string + expectedPassword string + expectedError error + }{ + { + testName: "Username and password with old configuration", + conf: `[Global] + server = 0.0.0.0 + user = user + password = password + datacenter = us-west + working-dir = kubernetes + `, + expectedUsername: username, + expectedPassword: password, + expectedError: nil, + }, + { + testName: "SecretName and SecretNamespace in old configuration", + conf: `[Global] + server = 0.0.0.0 + datacenter = us-west + secret-name = "vccreds" + secret-namespace = "kube-system" + working-dir = kubernetes + `, + expectedIsSecretProvided: true, + expectedError: nil, + }, + { + testName: "SecretName and SecretNamespace with Username and Password in old configuration", + conf: `[Global] + server = 0.0.0.0 + user = user + password = password + datacenter = us-west + secret-name = "vccreds" + secret-namespace = "kube-system" + working-dir = kubernetes + `, + expectedIsSecretProvided: true, + expectedError: nil, + }, + { + testName: "SecretName and SecretNamespace with Username missing in old configuration", + conf: `[Global] + server = 0.0.0.0 + password = password + datacenter = us-west + secret-name = "vccreds" + secret-namespace = "kube-system" + working-dir = kubernetes + `, + expectedIsSecretProvided: true, + expectedError: nil, + }, + { + testName: "SecretNamespace missing with Username and Password in old configuration", + conf: `[Global] + server = 0.0.0.0 + user = user + password = password + datacenter = us-west + secret-name = "vccreds" + working-dir = kubernetes + `, + expectedUsername: username, + expectedPassword: password, + expectedError: nil, + }, + { + testName: "SecretNamespace and Username missing in old configuration", + conf: `[Global] + server = 0.0.0.0 + password = password + datacenter = us-west + secret-name = "vccreds" + working-dir = kubernetes + `, + expectedError: ErrUsernameMissing, + }, + { + testName: "SecretNamespace and Password missing in old configuration", + conf: `[Global] + server = 0.0.0.0 + user = user + datacenter = us-west + secret-name = "vccreds" + working-dir = kubernetes + `, + expectedError: ErrPasswordMissing, + }, + { + testName: "SecretNamespace, Username and Password missing in old configuration", + conf: `[Global] + server = 0.0.0.0 + datacenter = us-west + secret-name = "vccreds" + working-dir = kubernetes + `, + expectedError: ErrUsernameMissing, + }, + { + testName: "Username and password with new configuration but username and password in global section", + conf: `[Global] + user = user + password = password + datacenter = us-west + [VirtualCenter "0.0.0.0"] + [Workspace] + server = 0.0.0.0 + datacenter = us-west + folder = kubernetes + `, + expectedUsername: username, + expectedPassword: password, + expectedError: nil, + }, + { + testName: "Username and password with new configuration, username and password in virtualcenter section", + conf: `[Global] + server = 0.0.0.0 + port = 443 + insecure-flag = true + datacenter = us-west + [VirtualCenter "0.0.0.0"] + user = user + password = password + [Workspace] + server = 0.0.0.0 + datacenter = us-west + folder = kubernetes + `, + expectedUsername: username, + expectedPassword: password, + expectedError: nil, + }, + { + testName: "SecretName and SecretNamespace with new configuration", + conf: `[Global] + server = 0.0.0.0 + secret-name = "vccreds" + secret-namespace = "kube-system" + datacenter = us-west + [VirtualCenter "0.0.0.0"] + [Workspace] + server = 0.0.0.0 + datacenter = us-west + folder = kubernetes + `, + expectedIsSecretProvided: true, + expectedError: nil, + }, + { + testName: "SecretName and SecretNamespace with Username missing in new configuration", + conf: `[Global] + server = 0.0.0.0 + port = 443 + insecure-flag = true + datacenter = us-west + secret-name = "vccreds" + secret-namespace = "kube-system" + [VirtualCenter "0.0.0.0"] + password = password + [Workspace] + server = 0.0.0.0 + datacenter = us-west + folder = kubernetes + `, + expectedIsSecretProvided: true, + expectedError: nil, + }, + } + + for _, testcase := range testcases { + t.Logf("Executing Testcase: %s", testcase.testName) + cfg, err := readConfig(strings.NewReader(testcase.conf)) + if err != nil { + t.Fatalf("Should succeed when a valid config is provided: %s", err) + } + vs, err = buildVSphereFromConfig(cfg) + if err != testcase.expectedError { + t.Fatalf("Should succeed when a valid config is provided: %s", err) + } + if err != nil { + continue + } + if vs.isSecretInfoProvided != testcase.expectedIsSecretProvided { + t.Fatalf("SecretName and SecretNamespace was expected in config %s. error: %s", + testcase.conf, err) + } + if !testcase.expectedIsSecretProvided { + for _, vsInstance := range vs.vsphereInstanceMap { + if vsInstance.conn.Username != testcase.expectedUsername { + t.Fatalf("Expected username %s doesn't match actual username %s in config %s. error: %s", + testcase.expectedUsername, vsInstance.conn.Username, testcase.conf, err) + } + if vsInstance.conn.Password != testcase.expectedPassword { + t.Fatalf("Expected password %s doesn't match actual password %s in config %s. error: %s", + testcase.expectedPassword, vsInstance.conn.Password, testcase.conf, err) + } + + } + } + + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/BUILD index a63a13123..d2d5ed451 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/BUILD @@ -14,14 +14,13 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/apis/core/install: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/apps/v1: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/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", @@ -56,6 +55,7 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/core/install:go_default_library", "//pkg/apis/core/validation:go_default_library", + "//pkg/scheduler/algorithm:go_default_library", "//pkg/serviceaccount:go_default_library", "//pkg/util/hash:go_default_library", "//pkg/util/taints:go_default_library", @@ -64,7 +64,6 @@ go_library( "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/authentication/v1: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/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/bootstrap/tokencleaner.go b/vendor/k8s.io/kubernetes/pkg/controller/bootstrap/tokencleaner.go index d39582b2f..c9fb2c148 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/bootstrap/tokencleaner.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/bootstrap/tokencleaner.go @@ -161,7 +161,7 @@ func (tc *TokenCleaner) processNextWorkItem() bool { func (tc *TokenCleaner) syncFunc(key string) error { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing secret %q (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing secret %q (%v)", key, time.Since(startTime)) }() namespace, name, err := cache.SplitMetaNamespaceKey(key) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/certificates/OWNERS b/vendor/k8s.io/kubernetes/pkg/controller/certificates/OWNERS index 4516fdf5b..e77a57187 100755 --- a/vendor/k8s.io/kubernetes/pkg/controller/certificates/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/controller/certificates/OWNERS @@ -1,3 +1,4 @@ reviewers: - deads2k - mikedanese +- awly diff --git a/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/BUILD index e54a14223..874a6ddf3 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/BUILD @@ -28,10 +28,8 @@ go_library( deps = [ "//pkg/apis/certificates/v1beta1:go_default_library", "//pkg/controller/certificates:go_default_library", - "//pkg/features:go_default_library", "//vendor/k8s.io/api/authorization/v1beta1:go_default_library", "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/informers/certificates/v1beta1:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/sarapprove.go b/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/sarapprove.go index 3aa6be1ce..e5ca32f86 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/sarapprove.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/sarapprove.go @@ -25,12 +25,10 @@ import ( authorization "k8s.io/api/authorization/v1beta1" capi "k8s.io/api/certificates/v1beta1" - utilfeature "k8s.io/apiserver/pkg/util/feature" certificatesinformers "k8s.io/client-go/informers/certificates/v1beta1" clientset "k8s.io/client-go/kubernetes" k8s_certificates_v1beta1 "k8s.io/kubernetes/pkg/apis/certificates/v1beta1" "k8s.io/kubernetes/pkg/controller/certificates" - "k8s.io/kubernetes/pkg/features" ) type csrRecognizer struct { @@ -69,13 +67,6 @@ func recognizers() []csrRecognizer { successMessage: "Auto approving kubelet client certificate after SubjectAccessReview.", }, } - if utilfeature.DefaultFeatureGate.Enabled(features.RotateKubeletServerCertificate) { - recognizers = append(recognizers, csrRecognizer{ - recognize: isSelfNodeServerCert, - permission: authorization.ResourceAttributes{Group: "certificates.k8s.io", Resource: "certificatesigningrequests", Verb: "create", Subresource: "selfnodeserver"}, - successMessage: "Auto approving self kubelet server certificate after SubjectAccessReview.", - }) - } return recognizers } @@ -201,28 +192,3 @@ func isSelfNodeClientCert(csr *capi.CertificateSigningRequest, x509cr *x509.Cert } return true } - -var kubeletServerUsages = []capi.KeyUsage{ - capi.UsageKeyEncipherment, - capi.UsageDigitalSignature, - capi.UsageServerAuth, -} - -func isSelfNodeServerCert(csr *capi.CertificateSigningRequest, x509cr *x509.CertificateRequest) bool { - if !reflect.DeepEqual([]string{"system:nodes"}, x509cr.Subject.Organization) { - return false - } - if len(x509cr.DNSNames) == 0 || len(x509cr.IPAddresses) == 0 { - return false - } - if !hasExactUsages(csr, kubeletServerUsages) { - return false - } - if !strings.HasPrefix(x509cr.Subject.CommonName, "system:node:") { - return false - } - if csr.Spec.Username != x509cr.Subject.CommonName { - return false - } - return true -} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/sarapprove_test.go b/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/sarapprove_test.go index f17b9cebe..40dcc316d 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/sarapprove_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/certificates/approver/sarapprove_test.go @@ -187,77 +187,6 @@ func TestHandle(t *testing.T) { } } -func TestSelfNodeServerCertRecognizer(t *testing.T) { - defaultCSR := csrBuilder{ - cn: "system:node:foo", - orgs: []string{"system:nodes"}, - requestor: "system:node:foo", - usages: []capi.KeyUsage{ - capi.UsageKeyEncipherment, - capi.UsageDigitalSignature, - capi.UsageServerAuth, - }, - dns: []string{"node"}, - ips: []net.IP{net.ParseIP("192.168.0.1")}, - } - - testCases := []struct { - description string - csrBuilder csrBuilder - expectedOutcome bool - }{ - { - description: "Success - all requirements met", - csrBuilder: defaultCSR, - expectedOutcome: true, - }, - { - description: "No organization", - csrBuilder: func(b csrBuilder) csrBuilder { - b.orgs = []string{} - return b - }(defaultCSR), - expectedOutcome: false, - }, - { - description: "Wrong organization", - csrBuilder: func(b csrBuilder) csrBuilder { - b.orgs = append(b.orgs, "new-org") - return b - }(defaultCSR), - expectedOutcome: false, - }, - { - description: "Wrong usages", - csrBuilder: func(b csrBuilder) csrBuilder { - b.usages = []capi.KeyUsage{} - return b - }(defaultCSR), - expectedOutcome: false, - }, - { - description: "Wrong common name", - csrBuilder: func(b csrBuilder) csrBuilder { - b.cn = "wrong-common-name" - return b - }(defaultCSR), - expectedOutcome: false, - }, - } - for _, tc := range testCases { - t.Run(tc.description, func(t *testing.T) { - csr := makeFancyTestCsr(tc.csrBuilder) - x509cr, err := k8s_certificates_v1beta1.ParseCSR(csr) - if err != nil { - t.Errorf("unexpected err: %v", err) - } - if isSelfNodeServerCert(csr, x509cr) != tc.expectedOutcome { - t.Errorf("expected recognized to be %v", tc.expectedOutcome) - } - }) - } -} - func TestRecognizers(t *testing.T) { goodCases := []func(b *csrBuilder){ func(b *csrBuilder) { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/certificates/certificate_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/certificates/certificate_controller.go index 23e9f342e..088faf50e 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/certificates/certificate_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/certificates/certificate_controller.go @@ -58,7 +58,7 @@ func NewCertificateController( // Send events to the apiserver eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) cc := &CertificateController{ kubeClient: kubeClient, @@ -169,7 +169,7 @@ func (cc *CertificateController) enqueueCertificateRequest(obj interface{}) { func (cc *CertificateController) syncFunc(key string) error { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing certificate request %q (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing certificate request %q (%v)", key, time.Since(startTime)) }() csr, err := cc.csrLister.Get(key) if errors.IsNotFound(err) { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/cloud/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/cloud/BUILD index cb35dda14..d6ba3f1e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/cloud/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/cloud/BUILD @@ -17,6 +17,7 @@ go_library( "//pkg/api/v1/node:go_default_library", "//pkg/cloudprovider:go_default_library", "//pkg/controller:go_default_library", + "//pkg/controller/util/node:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/util/node:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/cloud/OWNERS b/vendor/k8s.io/kubernetes/pkg/controller/cloud/OWNERS index 5a58eee8c..85347d439 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/cloud/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/controller/cloud/OWNERS @@ -2,7 +2,9 @@ approvers: - thockin - luxas - wlan0 +- andrewsykim reviewers: - thockin - luxas - wlan0 +- andrewsykim diff --git a/vendor/k8s.io/kubernetes/pkg/controller/cloud/node_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/cloud/node_controller.go index de20921bc..9655feee7 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/cloud/node_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/cloud/node_controller.go @@ -18,6 +18,7 @@ package cloud import ( "context" + "errors" "fmt" "time" @@ -37,6 +38,8 @@ import ( clientretry "k8s.io/client-go/util/retry" nodeutilv1 "k8s.io/kubernetes/pkg/api/v1/node" "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/controller" + nodectrlutil "k8s.io/kubernetes/pkg/controller/util/node" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/scheduler/algorithm" nodeutil "k8s.io/kubernetes/pkg/util/node" @@ -84,7 +87,7 @@ func NewCloudNodeController( eventBroadcaster.StartLogging(glog.Infof) if kubeClient != nil { glog.V(0).Infof("Sending events to api server.") - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) } else { glog.V(0).Infof("No api server defined - no events will be sent to API server.") } @@ -110,7 +113,7 @@ func NewCloudNodeController( // This controller deletes a node if kubelet is not reporting // and the node is gone from the cloud provider. -func (cnc *CloudNodeController) Run() { +func (cnc *CloudNodeController) Run(stopCh <-chan struct{}) { defer utilruntime.HandleCrash() // The following loops run communicate with the APIServer with a worst case complexity @@ -118,10 +121,10 @@ func (cnc *CloudNodeController) Run() { // very infrequently. DO NOT MODIFY this to perform frequent operations. // Start a loop to periodically update the node addresses obtained from the cloud - go wait.Until(cnc.UpdateNodeStatus, cnc.nodeStatusUpdateFrequency, wait.NeverStop) + go wait.Until(cnc.UpdateNodeStatus, cnc.nodeStatusUpdateFrequency, stopCh) // Start a loop to periodically check if any nodes have been deleted from cloudprovider - go wait.Until(cnc.MonitorNode, cnc.nodeMonitorPeriod, wait.NeverStop) + go wait.Until(cnc.MonitorNode, cnc.nodeMonitorPeriod, stopCh) } // UpdateNodeStatus updates the node status, such as node addresses @@ -152,7 +155,7 @@ func (cnc *CloudNodeController) updateNodeAddress(node *v1.Node, instances cloud return } // Node that isn't present according to the cloud provider shouldn't have its address updated - exists, err := ensureNodeExistsByProviderIDOrExternalID(instances, node) + exists, err := ensureNodeExistsByProviderID(instances, node) if err != nil { // Continue to update node address when not sure the node is not exists glog.Errorf("%v", err) @@ -166,6 +169,12 @@ func (cnc *CloudNodeController) updateNodeAddress(node *v1.Node, instances cloud glog.Errorf("%v", err) return } + + if len(nodeAddresses) == 0 { + glog.V(5).Infof("Skipping node address update for node %q since cloud provider did not return any", node.Name) + return + } + // Check if a hostname address exists in the cloud provided addresses hostnameExists := false for i := range nodeAddresses { @@ -189,7 +198,6 @@ func (cnc *CloudNodeController) updateNodeAddress(node *v1.Node, instances cloud glog.Errorf("Specified Node IP not found in cloudprovider") return } - nodeAddresses = []v1.NodeAddress{*nodeIP} } newNode := node.DeepCopy() newNode.Status.Addresses = nodeAddresses @@ -243,9 +251,27 @@ func (cnc *CloudNodeController) MonitorNode() { // from the cloud provider. If node cannot be found in cloudprovider, then delete the node immediately if currentReadyCondition != nil { if currentReadyCondition.Status != v1.ConditionTrue { + // we need to check this first to get taint working in similar in all cloudproviders + // current problem is that shutdown nodes are not working in similar way ie. all cloudproviders + // does not delete node from kubernetes cluster when instance it is shutdown see issue #46442 + shutdown, err := nodectrlutil.ShutdownInCloudProvider(context.TODO(), cnc.cloud, node) + if err != nil { + glog.Errorf("Error getting data for node %s from cloud: %v", node.Name, err) + } + + if shutdown && err == nil { + // if node is shutdown add shutdown taint + err = controller.AddOrUpdateTaintOnNode(cnc.kubeClient, node.Name, controller.ShutdownTaint) + if err != nil { + glog.Errorf("Error patching node taints: %v", err) + } + // Continue checking the remaining nodes since the current one is shutdown. + continue + } + // Check with the cloud provider to see if the node still exists. If it // doesn't, delete the node immediately. - exists, err := ensureNodeExistsByProviderIDOrExternalID(instances, node) + exists, err := ensureNodeExistsByProviderID(instances, node) if err != nil { glog.Errorf("Error getting data for node %s from cloud: %v", node.Name, err) continue @@ -275,6 +301,12 @@ func (cnc *CloudNodeController) MonitorNode() { } }(node.Name) + } else { + // if taint exist remove taint + err = controller.RemoveTaintOffNode(cnc.kubeClient, node.Name, node, controller.ShutdownTaint) + if err != nil { + glog.Errorf("Error patching node taints: %v", err) + } } } } @@ -324,21 +356,18 @@ func (cnc *CloudNodeController) AddCloudNode(obj interface{}) { nodeAddresses, err := getNodeAddressesByProviderIDOrName(instances, curNode) if err != nil { - glog.Errorf("%v", err) - return nil + return err } // If user provided an IP address, ensure that IP address is found // in the cloud provider before removing the taint on the node if nodeIP, ok := ensureNodeProvidedIPExists(curNode, nodeAddresses); ok { if nodeIP == nil { - glog.Errorf("failed to get specified nodeIP in cloudprovider") - return nil + return errors.New("failed to find kubelet node IP from cloud provider") } } if instanceType, err := getInstanceTypeByProviderIDOrName(instances, curNode); err != nil { - glog.Errorf("%v", err) return err } else if instanceType != "" { glog.V(2).Infof("Adding node label from cloud provider: %s=%s", kubeletapis.LabelInstanceType, instanceType) @@ -412,23 +441,27 @@ func excludeTaintFromList(taints []v1.Taint, toExclude v1.Taint) []v1.Taint { return newTaints } -// ensureNodeExistsByProviderIDOrExternalID first checks if the instance exists by the provider id and then by calling external id with node name -func ensureNodeExistsByProviderIDOrExternalID(instances cloudprovider.Instances, node *v1.Node) (bool, error) { - exists, err := instances.InstanceExistsByProviderID(context.TODO(), node.Spec.ProviderID) - if err != nil { - providerIDErr := err - _, err = instances.ExternalID(context.TODO(), types.NodeName(node.Name)) - if err == nil { - return true, nil +// ensureNodeExistsByProviderID checks if the instance exists by the provider id, +// If provider id in spec is empty it calls instanceId with node name to get provider id +func ensureNodeExistsByProviderID(instances cloudprovider.Instances, node *v1.Node) (bool, error) { + providerID := node.Spec.ProviderID + if providerID == "" { + var err error + providerID, err = instances.InstanceID(context.TODO(), types.NodeName(node.Name)) + if err != nil { + if err == cloudprovider.InstanceNotFound { + return false, nil + } + return false, err } - if err == cloudprovider.InstanceNotFound { + + if providerID == "" { + glog.Warningf("Cannot find valid providerID for node name %q, assuming non existence", node.Name) return false, nil } - - return false, fmt.Errorf("InstanceExistsByProviderID: Error fetching by providerID: %v Error fetching by NodeName: %v", providerIDErr, err) } - return exists, nil + return instances.InstanceExistsByProviderID(context.TODO(), providerID) } func getNodeAddressesByProviderIDOrName(instances cloudprovider.Instances, node *v1.Node) ([]v1.NodeAddress, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/cloud/node_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/cloud/node_controller_test.go index a8faf8352..ee25f12f7 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/cloud/node_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/cloud/node_controller_test.go @@ -41,13 +41,14 @@ import ( "github.com/stretchr/testify/assert" ) -func TestEnsureNodeExistsByProviderIDOrNodeName(t *testing.T) { +func TestEnsureNodeExistsByProviderID(t *testing.T) { testCases := []struct { testName string node *v1.Node expectedCalls []string - existsByNodeName bool + expectedNodeExists bool + hasInstanceID bool existsByProviderID bool nodeNameErr error providerIDErr error @@ -56,9 +57,10 @@ func TestEnsureNodeExistsByProviderIDOrNodeName(t *testing.T) { testName: "node exists by provider id", existsByProviderID: true, providerIDErr: nil, - existsByNodeName: false, + hasInstanceID: true, nodeNameErr: errors.New("unimplemented"), expectedCalls: []string{"instance-exists-by-provider-id"}, + expectedNodeExists: true, node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: "node0", @@ -72,9 +74,10 @@ func TestEnsureNodeExistsByProviderIDOrNodeName(t *testing.T) { testName: "does not exist by provider id", existsByProviderID: false, providerIDErr: nil, - existsByNodeName: false, + hasInstanceID: true, nodeNameErr: errors.New("unimplemented"), expectedCalls: []string{"instance-exists-by-provider-id"}, + expectedNodeExists: false, node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: "node0", @@ -85,28 +88,41 @@ func TestEnsureNodeExistsByProviderIDOrNodeName(t *testing.T) { }, }, { - testName: "node exists by node name", - existsByProviderID: false, - providerIDErr: errors.New("unimplemented"), - existsByNodeName: true, + testName: "exists by instance id", + existsByProviderID: true, + providerIDErr: nil, + hasInstanceID: true, nodeNameErr: nil, - expectedCalls: []string{"instance-exists-by-provider-id", "external-id"}, + expectedCalls: []string{"instance-id", "instance-exists-by-provider-id"}, + expectedNodeExists: true, node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: "node0", }, - Spec: v1.NodeSpec{ - ProviderID: "node0", + }, + }, + { + testName: "does not exist by no instance id", + existsByProviderID: true, + providerIDErr: nil, + hasInstanceID: false, + nodeNameErr: cloudprovider.InstanceNotFound, + expectedCalls: []string{"instance-id"}, + expectedNodeExists: false, + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", }, }, }, { - testName: "does not exist by node name", + testName: "provider id returns error", existsByProviderID: false, providerIDErr: errors.New("unimplemented"), - existsByNodeName: false, + hasInstanceID: true, nodeNameErr: cloudprovider.InstanceNotFound, - expectedCalls: []string{"instance-exists-by-provider-id", "external-id"}, + expectedCalls: []string{"instance-exists-by-provider-id"}, + expectedNodeExists: false, node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: "node0", @@ -121,28 +137,137 @@ func TestEnsureNodeExistsByProviderIDOrNodeName(t *testing.T) { for _, tc := range testCases { t.Run(tc.testName, func(t *testing.T) { fc := &fakecloud.FakeCloud{ - Exists: tc.existsByNodeName, ExistsByProviderID: tc.existsByProviderID, Err: tc.nodeNameErr, ErrByProviderID: tc.providerIDErr, } + if tc.hasInstanceID { + fc.ExtID = map[types.NodeName]string{ + types.NodeName(tc.node.Name): "provider-id://a", + } + } + instances, _ := fc.Instances() - exists, err := ensureNodeExistsByProviderIDOrExternalID(instances, tc.node) - assert.NoError(t, err) + exists, err := ensureNodeExistsByProviderID(instances, tc.node) + assert.Equal(t, err, tc.providerIDErr) + assert.EqualValues(t, tc.expectedCalls, fc.Calls, "expected cloud provider methods `%v` to be called but `%v` was called ", tc.expectedCalls, fc.Calls) - assert.False(t, tc.existsByProviderID && tc.existsByProviderID != exists, - "expected exist by provider id to be `%t` but got `%t`", + assert.Equal(t, tc.expectedNodeExists, exists, + "expected exists to be `%t` but got `%t`", tc.existsByProviderID, exists) + }) + } + +} + +func TestNodeShutdown(t *testing.T) { + + testCases := []struct { + testName string + node *v1.Node + existsByProviderID bool + shutdown bool + }{ + { + testName: "node shutdowned add taint", + existsByProviderID: true, + shutdown: true, + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Spec: v1.NodeSpec{ + ProviderID: "node0", + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionUnknown, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + { + testName: "node started after shutdown remove taint", + existsByProviderID: true, + shutdown: false, + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Spec: v1.NodeSpec{ + ProviderID: "node0", + Taints: []v1.Taint{ + { + Key: algorithm.TaintNodeShutdown, + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionTrue, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.testName, func(t *testing.T) { + fc := &fakecloud.FakeCloud{ + ExistsByProviderID: tc.existsByProviderID, + NodeShutdown: tc.shutdown, + } + fnh := &testutil.FakeNodeHandler{ + Existing: []*v1.Node{tc.node}, + Clientset: fake.NewSimpleClientset(), + PatchWaitChan: make(chan struct{}), + } + + factory := informers.NewSharedInformerFactory(fnh, controller.NoResyncPeriodFunc()) - assert.False(t, tc.existsByNodeName && tc.existsByNodeName != exists, - "expected exist by node name to be `%t` but got `%t`", tc.existsByNodeName, exists) + eventBroadcaster := record.NewBroadcaster() + cloudNodeController := &CloudNodeController{ + kubeClient: fnh, + nodeInformer: factory.Core().V1().Nodes(), + cloud: fc, + nodeMonitorPeriod: 1 * time.Second, + recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), + nodeStatusUpdateFrequency: 1 * time.Second, + } + eventBroadcaster.StartLogging(glog.Infof) + + cloudNodeController.Run(wait.NeverStop) + + select { + case <-fnh.PatchWaitChan: + case <-time.After(1 * time.Second): + t.Errorf("Timed out waiting %v for node to be updated", wait.ForeverTestTimeout) + } + + assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated") + if tc.shutdown { + assert.Equal(t, 1, len(fnh.UpdatedNodes[0].Spec.Taints), "Node Taint was not added") + assert.Equal(t, "node.cloudprovider.kubernetes.io/shutdown", fnh.UpdatedNodes[0].Spec.Taints[0].Key, "Node Taint key is not correct") + } else { + assert.Equal(t, 0, len(fnh.UpdatedNodes[0].Spec.Taints), "Node Taint was not removed after node is back in ready state") + } - assert.False(t, !tc.existsByNodeName && !tc.existsByProviderID && exists, - "node is not supposed to exist") }) } @@ -226,7 +351,7 @@ func TestNodeDeleted(t *testing.T) { } eventBroadcaster.StartLogging(glog.Infof) - cloudNodeController.Run() + cloudNodeController.Run(wait.NeverStop) select { case <-fnh.DeleteWaitChan: @@ -643,7 +768,7 @@ func TestNodeAddresses(t *testing.T) { }, } - cloudNodeController.Run() + cloudNodeController.Run(wait.NeverStop) <-time.After(2 * time.Second) @@ -745,15 +870,15 @@ func TestNodeProvidedIPAddresses(t *testing.T) { assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated") assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated") - assert.Equal(t, 1, len(fnh.UpdatedNodes[0].Status.Addresses), "Node status unexpectedly updated") + assert.Equal(t, 3, len(fnh.UpdatedNodes[0].Status.Addresses), "Node status unexpectedly updated") - cloudNodeController.Run() + cloudNodeController.Run(wait.NeverStop) <-time.After(2 * time.Second) updatedNodes := fnh.GetUpdatedNodesCopy() - assert.Equal(t, 1, len(updatedNodes[0].Status.Addresses), 1, "Node Addresses not correctly updated") + assert.Equal(t, 3, len(updatedNodes[0].Status.Addresses), "Node Addresses not correctly updated") assert.Equal(t, "10.0.0.1", updatedNodes[0].Status.Addresses[0].Address, "Node Addresses not correctly updated") } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go b/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go index 21d7aa302..6cf2ac189 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go @@ -23,7 +23,6 @@ import ( "github.com/golang/glog" apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -301,18 +300,18 @@ func NewReplicaSetControllerRefManager( // If the error is nil, either the reconciliation succeeded, or no // reconciliation was necessary. The list of ReplicaSets that you now own is // returned. -func (m *ReplicaSetControllerRefManager) ClaimReplicaSets(sets []*extensions.ReplicaSet) ([]*extensions.ReplicaSet, error) { - var claimed []*extensions.ReplicaSet +func (m *ReplicaSetControllerRefManager) ClaimReplicaSets(sets []*apps.ReplicaSet) ([]*apps.ReplicaSet, error) { + var claimed []*apps.ReplicaSet var errlist []error match := func(obj metav1.Object) bool { return m.Selector.Matches(labels.Set(obj.GetLabels())) } adopt := func(obj metav1.Object) error { - return m.AdoptReplicaSet(obj.(*extensions.ReplicaSet)) + return m.AdoptReplicaSet(obj.(*apps.ReplicaSet)) } release := func(obj metav1.Object) error { - return m.ReleaseReplicaSet(obj.(*extensions.ReplicaSet)) + return m.ReleaseReplicaSet(obj.(*apps.ReplicaSet)) } for _, rs := range sets { @@ -330,7 +329,7 @@ func (m *ReplicaSetControllerRefManager) ClaimReplicaSets(sets []*extensions.Rep // AdoptReplicaSet sends a patch to take control of the ReplicaSet. It returns // the error if the patching fails. -func (m *ReplicaSetControllerRefManager) AdoptReplicaSet(rs *extensions.ReplicaSet) error { +func (m *ReplicaSetControllerRefManager) AdoptReplicaSet(rs *apps.ReplicaSet) error { if err := m.CanAdopt(); err != nil { return fmt.Errorf("can't adopt ReplicaSet %v/%v (%v): %v", rs.Namespace, rs.Name, rs.UID, err) } @@ -345,7 +344,7 @@ func (m *ReplicaSetControllerRefManager) AdoptReplicaSet(rs *extensions.ReplicaS // ReleaseReplicaSet sends a patch to free the ReplicaSet from the control of the Deployment controller. // It returns the error if the patching fails. 404 and 422 errors are ignored. -func (m *ReplicaSetControllerRefManager) ReleaseReplicaSet(replicaSet *extensions.ReplicaSet) error { +func (m *ReplicaSetControllerRefManager) ReleaseReplicaSet(replicaSet *apps.ReplicaSet) error { glog.V(2).Infof("patching ReplicaSet %s_%s to remove its controllerRef to %s/%s:%s", replicaSet.Namespace, replicaSet.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.Controller.GetName()) deleteOwnerRefPatch := fmt.Sprintf(`{"metadata":{"ownerReferences":[{"$patch":"delete","uid":"%s"}],"uid":"%s"}}`, m.Controller.GetUID(), replicaSet.UID) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager_test.go b/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager_test.go index 4e6acb7cf..fe8781764 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager_test.go @@ -20,8 +20,8 @@ import ( "reflect" "testing" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" @@ -52,7 +52,7 @@ func newPod(podName string, label map[string]string, owner metav1.Object) *v1.Po }, } if owner != nil { - pod.OwnerReferences = []metav1.OwnerReference{*metav1.NewControllerRef(owner, v1beta1.SchemeGroupVersion.WithKind("Fake"))} + pod.OwnerReferences = []metav1.OwnerReference{*metav1.NewControllerRef(owner, apps.SchemeGroupVersion.WithKind("Fake"))} } return pod } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go b/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go index d7d755ebf..fb00a7567 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go @@ -25,8 +25,8 @@ import ( "sync/atomic" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -45,6 +45,7 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" _ "k8s.io/kubernetes/pkg/apis/core/install" "k8s.io/kubernetes/pkg/apis/core/validation" + "k8s.io/kubernetes/pkg/scheduler/algorithm" hashutil "k8s.io/kubernetes/pkg/util/hash" taintutils "k8s.io/kubernetes/pkg/util/taints" @@ -86,6 +87,11 @@ var UpdateTaintBackoff = wait.Backoff{ Jitter: 1.0, } +var ShutdownTaint = &v1.Taint{ + Key: algorithm.TaintNodeShutdown, + Effect: v1.TaintEffectNoSchedule, +} + var ( KeyFunc = cache.DeletionHandlingMetaNamespaceKeyFunc ) @@ -812,18 +818,18 @@ func IsPodActive(p *v1.Pod) bool { } // FilterActiveReplicaSets returns replica sets that have (or at least ought to have) pods. -func FilterActiveReplicaSets(replicaSets []*extensions.ReplicaSet) []*extensions.ReplicaSet { - activeFilter := func(rs *extensions.ReplicaSet) bool { +func FilterActiveReplicaSets(replicaSets []*apps.ReplicaSet) []*apps.ReplicaSet { + activeFilter := func(rs *apps.ReplicaSet) bool { return rs != nil && *(rs.Spec.Replicas) > 0 } return FilterReplicaSets(replicaSets, activeFilter) } -type filterRS func(rs *extensions.ReplicaSet) bool +type filterRS func(rs *apps.ReplicaSet) bool // FilterReplicaSets returns replica sets that are filtered by filterFn (all returned ones should match filterFn). -func FilterReplicaSets(RSes []*extensions.ReplicaSet, filterFn filterRS) []*extensions.ReplicaSet { - var filtered []*extensions.ReplicaSet +func FilterReplicaSets(RSes []*apps.ReplicaSet, filterFn filterRS) []*apps.ReplicaSet { + var filtered []*apps.ReplicaSet for i := range RSes { if filterFn(RSes[i]) { filtered = append(filtered, RSes[i]) @@ -853,7 +859,7 @@ func (o ControllersByCreationTimestamp) Less(i, j int) bool { } // ReplicaSetsByCreationTimestamp sorts a list of ReplicaSet by creation timestamp, using their names as a tie breaker. -type ReplicaSetsByCreationTimestamp []*extensions.ReplicaSet +type ReplicaSetsByCreationTimestamp []*apps.ReplicaSet func (o ReplicaSetsByCreationTimestamp) Len() int { return len(o) } func (o ReplicaSetsByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } @@ -866,7 +872,7 @@ func (o ReplicaSetsByCreationTimestamp) Less(i, j int) bool { // ReplicaSetsBySizeOlder sorts a list of ReplicaSet by size in descending order, using their creation timestamp or name as a tie breaker. // By using the creation timestamp, this sorts from old to new replica sets. -type ReplicaSetsBySizeOlder []*extensions.ReplicaSet +type ReplicaSetsBySizeOlder []*apps.ReplicaSet func (o ReplicaSetsBySizeOlder) Len() int { return len(o) } func (o ReplicaSetsBySizeOlder) Swap(i, j int) { o[i], o[j] = o[j], o[i] } @@ -879,7 +885,7 @@ func (o ReplicaSetsBySizeOlder) Less(i, j int) bool { // ReplicaSetsBySizeNewer sorts a list of ReplicaSet by size in descending order, using their creation timestamp or name as a tie breaker. // By using the creation timestamp, this sorts from new to old replica sets. -type ReplicaSetsBySizeNewer []*extensions.ReplicaSet +type ReplicaSetsBySizeNewer []*apps.ReplicaSet func (o ReplicaSetsBySizeNewer) Len() int { return len(o) } func (o ReplicaSetsBySizeNewer) Swap(i, j int) { o[i], o[j] = o[j], o[i] } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils_test.go b/vendor/k8s.io/kubernetes/pkg/controller/controller_utils_test.go index f3599ba6d..857b8b46f 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/controller_utils_test.go @@ -27,11 +27,12 @@ import ( "testing" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/clock" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" @@ -41,7 +42,6 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" utiltesting "k8s.io/client-go/util/testing" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" _ "k8s.io/kubernetes/pkg/apis/core/install" "k8s.io/kubernetes/pkg/controller/testutil" @@ -62,7 +62,7 @@ func NewFakeControllerExpectationsLookup(ttl time.Duration) (*ControllerExpectat func newReplicationController(replicas int) *v1.ReplicationController { rc := &v1.ReplicationController{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: "foobar", @@ -122,16 +122,16 @@ func newPodList(store cache.Store, count int, status v1.PodPhase, rc *v1.Replica } } -func newReplicaSet(name string, replicas int) *extensions.ReplicaSet { - return &extensions.ReplicaSet{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, +func newReplicaSet(name string, replicas int) *apps.ReplicaSet { + return &apps.ReplicaSet{ + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: name, Namespace: metav1.NamespaceDefault, ResourceVersion: "18", }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: func() *int32 { i := int32(replicas); return &i }(), Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, Template: v1.PodTemplateSpec{ @@ -286,7 +286,7 @@ func TestCreatePods(t *testing.T) { } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) podControl := RealPodControl{ KubeClient: clientset, @@ -417,7 +417,7 @@ func TestSortingActivePods(t *testing.T) { } func TestActiveReplicaSetsFiltering(t *testing.T) { - var replicaSets []*extensions.ReplicaSet + var replicaSets []*apps.ReplicaSet replicaSets = append(replicaSets, newReplicaSet("zero", 0)) replicaSets = append(replicaSets, nil) replicaSets = append(replicaSets, newReplicaSet("foo", 1)) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/cronjob/cronjob_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/cronjob/cronjob_controller.go index 5d4d7dc3d..34dfca3fc 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/cronjob/cronjob_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/cronjob/cronjob_controller.go @@ -69,8 +69,7 @@ type CronJobController struct { func NewCronJobController(kubeClient clientset.Interface) (*CronJobController, error) { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - // TODO: remove the wrapper when every clients have moved to use the clientset. - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { if err := metrics.RegisterMetricAndTrackRateLimiterUsage("cronjob_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter()); err != nil { @@ -89,14 +88,6 @@ func NewCronJobController(kubeClient clientset.Interface) (*CronJobController, e return jm, nil } -func NewCronJobControllerFromClient(kubeClient clientset.Interface) (*CronJobController, error) { - jm, err := NewCronJobController(kubeClient) - if err != nil { - return nil, err - } - return jm, nil -} - // Run the main goroutine responsible for watching and syncing jobs. func (jm *CronJobController) Run(stopCh <-chan struct{}) { defer utilruntime.HandleCrash() @@ -281,9 +272,8 @@ func syncOne(sj *batchv1beta1.CronJob, js []batchv1.Job, now time.Time, jc jobCo } if tooLate { glog.V(4).Infof("Missed starting window for %s", nameForLog) - // TODO: generate an event for a miss. Use a warning level event because it indicates a - // problem with the controller (restart or long queue), and is not expected by user either. - // Since we don't set LastScheduleTime when not scheduling, we are going to keep noticing + recorder.Eventf(sj, v1.EventTypeWarning, "MissSchedule", "Missed scheduled time to start a job: %s", scheduledTime.Format(time.RFC1123Z)) + // TODO: Since we don't set LastScheduleTime when not scheduling, we are going to keep noticing // the miss every cycle. In order to avoid sending multiple events, and to avoid processing // the sj again and again, we could set a Status.LastMissedTime when we notice a miss. // Then, when we call getRecentUnmetScheduleTimes, we can take max(creationTimestamp, diff --git a/vendor/k8s.io/kubernetes/pkg/controller/cronjob/utils.go b/vendor/k8s.io/kubernetes/pkg/controller/cronjob/utils.go index d3286d99c..53db1d8e0 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/cronjob/utils.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/cronjob/utils.go @@ -89,24 +89,6 @@ func groupJobsByParent(js []batchv1.Job) map[types.UID][]batchv1.Job { return jobsBySj } -// getNextStartTimeAfter gets the latest scheduled start time that is less than "now", or an error. -func getNextStartTimeAfter(schedule string, now time.Time) (time.Time, error) { - // Using robfig/cron for cron scheduled parsing and next runtime - // computation. Not using the entire library because: - // - I want to detect when we missed a runtime due to being down. - // - How do I set the time such that I can detect the last known runtime? - // - I guess the functions could launch a go-routine to start the job and - // then return. - // How to handle concurrency control. - // How to detect changes to schedules or deleted schedules and then - // update the jobs? - sched, err := cron.Parse(schedule) - if err != nil { - return time.Unix(0, 0), fmt.Errorf("Unparseable schedule: %s : %s", schedule, err) - } - return sched.Next(now), nil -} - // getRecentUnmetScheduleTimes gets a slice of times (from oldest to latest) that have passed when a Job should have started but did not. // // If there are too many (>100) unstarted times, just give up and return an empty slice. @@ -171,9 +153,6 @@ func getRecentUnmetScheduleTimes(sj batchv1beta1.CronJob, now time.Time) ([]time // getJobFromTemplate makes a Job from a CronJob func getJobFromTemplate(sj *batchv1beta1.CronJob, scheduledTime time.Time) (*batchv1.Job, error) { - // TODO: consider adding the following labels: - // nominal-start-time=$RFC_3339_DATE_OF_INTENDED_START -- for user convenience - // scheduled-job-name=$SJ_NAME -- for user convenience labels := copyLabels(&sj.Spec.JobTemplate) annotations := copyAnnotations(&sj.Spec.JobTemplate) // We want job names for a given nominal start time to have a deterministic name to avoid the same job being created twice diff --git a/vendor/k8s.io/kubernetes/pkg/controller/daemon/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/daemon/BUILD index 81c11c383..a456c978b 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/daemon/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/daemon/BUILD @@ -23,7 +23,7 @@ go_library( "//pkg/kubelet/types:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/util/labels:go_default_library", "//pkg/util/metrics:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -33,6 +33,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller.go index a640f1acd..92cdb15b9 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller.go @@ -30,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" @@ -55,7 +56,7 @@ import ( kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/util/metrics" ) @@ -112,6 +113,8 @@ type DaemonSetsController struct { historyStoreSynced cache.InformerSynced // podLister get list/get pods from the shared informers's store podLister corelisters.PodLister + // podNodeIndex indexes pods by their nodeName + podNodeIndex cache.Indexer // podStoreSynced returns true if the pod store has been synced at least once. // Added as a member to the struct to allow injection for testing. podStoreSynced cache.InformerSynced @@ -134,8 +137,7 @@ type DaemonSetsController struct { func NewDaemonSetsController(daemonSetInformer appsinformers.DaemonSetInformer, historyInformer appsinformers.ControllerRevisionInformer, podInformer coreinformers.PodInformer, nodeInformer coreinformers.NodeInformer, kubeClient clientset.Interface) (*DaemonSetsController, error) { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - // TODO: remove the wrapper when every clients have moved to use the clientset. - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { if err := metrics.RegisterMetricAndTrackRateLimiterUsage("daemon_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter()); err != nil { @@ -191,6 +193,12 @@ func NewDaemonSetsController(daemonSetInformer appsinformers.DaemonSetInformer, DeleteFunc: dsc.deletePod, }) dsc.podLister = podInformer.Lister() + + // This custom indexer will index pods based on their NodeName which will decrease the amount of pods we need to get in simulate() call. + podInformer.Informer().GetIndexer().AddIndexers(cache.Indexers{ + "nodeName": indexByPodNodeName, + }) + dsc.podNodeIndex = podInformer.Informer().GetIndexer() dsc.podStoreSynced = podInformer.Informer().HasSynced nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -207,6 +215,18 @@ func NewDaemonSetsController(daemonSetInformer appsinformers.DaemonSetInformer, return dsc, nil } +func indexByPodNodeName(obj interface{}) ([]string, error) { + pod, ok := obj.(*v1.Pod) + if !ok { + return []string{}, nil + } + // We are only interested in active pods with nodeName set + if len(pod.Spec.NodeName) == 0 || pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed { + return []string{}, nil + } + return []string{pod.Spec.NodeName}, nil +} + func (dsc *DaemonSetsController) deleteDaemonset(obj interface{}) { ds, ok := obj.(*apps.DaemonSet) if !ok { @@ -763,7 +783,7 @@ func (dsc *DaemonSetsController) getDaemonPods(ds *apps.DaemonSet) ([]*v1.Pod, e return cm.ClaimPods(pods) } -// getNodesToDaemonPods returns a map from nodes to daemon pods (corresponding to ds) running on the nodes. +// getNodesToDaemonPods returns a map from nodes to daemon pods (corresponding to ds) created for the nodes. // This also reconciles ControllerRef by adopting/orphaning. // Note that returned Pods are pointers to objects in the cache. // If you want to modify one, you need to deep-copy it first. @@ -775,9 +795,16 @@ func (dsc *DaemonSetsController) getNodesToDaemonPods(ds *apps.DaemonSet) (map[s // Group Pods by Node name. nodeToDaemonPods := make(map[string][]*v1.Pod) for _, pod := range claimedPods { - nodeName := pod.Spec.NodeName + nodeName, err := util.GetTargetNodeName(pod) + if err != nil { + glog.Warningf("Failed to get target node name of Pod %v/%v in DaemonSet %v/%v", + pod.Namespace, pod.Name, ds.Namespace, ds.Name) + continue + } + nodeToDaemonPods[nodeName] = append(nodeToDaemonPods[nodeName], pod) } + return nodeToDaemonPods, nil } @@ -802,12 +829,76 @@ func (dsc *DaemonSetsController) resolveControllerRef(namespace string, controll return ds } +// podsShouldBeOnNode figures out the DaemonSet pods to be created and deleted on the given node: +// - nodesNeedingDaemonPods: the pods need to start on the node +// - podsToDelete: the Pods need to be deleted on the node +// - failedPodsObserved: the number of failed pods on node +// - err: unexpected error +func (dsc *DaemonSetsController) podsShouldBeOnNode( + node *v1.Node, + nodeToDaemonPods map[string][]*v1.Pod, + ds *apps.DaemonSet, +) (nodesNeedingDaemonPods, podsToDelete []string, failedPodsObserved int, err error) { + + wantToRun, shouldSchedule, shouldContinueRunning, err := dsc.nodeShouldRunDaemonPod(node, ds) + if err != nil { + return + } + + daemonPods, exists := nodeToDaemonPods[node.Name] + dsKey, _ := cache.MetaNamespaceKeyFunc(ds) + dsc.removeSuspendedDaemonPods(node.Name, dsKey) + + switch { + case wantToRun && !shouldSchedule: + // If daemon pod is supposed to run, but can not be scheduled, add to suspended list. + dsc.addSuspendedDaemonPods(node.Name, dsKey) + case shouldSchedule && !exists: + // If daemon pod is supposed to be running on node, but isn't, create daemon pod. + nodesNeedingDaemonPods = append(nodesNeedingDaemonPods, node.Name) + case shouldContinueRunning: + // If a daemon pod failed, delete it + // If there's non-daemon pods left on this node, we will create it in the next sync loop + var daemonPodsRunning []*v1.Pod + for _, pod := range daemonPods { + if pod.DeletionTimestamp != nil { + continue + } + if pod.Status.Phase == v1.PodFailed { + msg := fmt.Sprintf("Found failed daemon pod %s/%s on node %s, will try to kill it", pod.Namespace, pod.Name, node.Name) + glog.V(2).Infof(msg) + // Emit an event so that it's discoverable to users. + dsc.eventRecorder.Eventf(ds, v1.EventTypeWarning, FailedDaemonPodReason, msg) + podsToDelete = append(podsToDelete, pod.Name) + failedPodsObserved++ + } else { + daemonPodsRunning = append(daemonPodsRunning, pod) + } + } + // If daemon pod is supposed to be running on node, but more than 1 daemon pod is running, delete the excess daemon pods. + // Sort the daemon pods by creation time, so the oldest is preserved. + if len(daemonPodsRunning) > 1 { + sort.Sort(podByCreationTimestampAndPhase(daemonPodsRunning)) + for i := 1; i < len(daemonPodsRunning); i++ { + podsToDelete = append(podsToDelete, daemonPodsRunning[i].Name) + } + } + case !shouldContinueRunning && exists: + // If daemon pod isn't supposed to run on node, but it is, delete all daemon pods on node. + for _, pod := range daemonPods { + podsToDelete = append(podsToDelete, pod.Name) + } + } + + return nodesNeedingDaemonPods, podsToDelete, failedPodsObserved, nil +} + // manage manages the scheduling and running of Pods of ds on nodes. // After figuring out which nodes should run a Pod of ds but not yet running one and // which nodes should not run a Pod of ds but currently running one, it calls function // syncNodes with a list of pods to remove and a list of nodes to run a Pod of ds. func (dsc *DaemonSetsController) manage(ds *apps.DaemonSet, hash string) error { - // Find out which nodes are running the daemon pods controlled by ds. + // Find out the pods which are created for the nodes by DaemonSet. nodeToDaemonPods, err := dsc.getNodesToDaemonPods(ds) if err != nil { return fmt.Errorf("couldn't get node to daemon pod mapping for daemon set %q: %v", ds.Name, err) @@ -822,55 +913,16 @@ func (dsc *DaemonSetsController) manage(ds *apps.DaemonSet, hash string) error { var nodesNeedingDaemonPods, podsToDelete []string var failedPodsObserved int for _, node := range nodeList { - wantToRun, shouldSchedule, shouldContinueRunning, err := dsc.nodeShouldRunDaemonPod(node, ds) + nodesNeedingDaemonPodsOnNode, podsToDeleteOnNode, failedPodsObservedOnNode, err := dsc.podsShouldBeOnNode( + node, nodeToDaemonPods, ds) + if err != nil { continue } - daemonPods, exists := nodeToDaemonPods[node.Name] - dsKey, _ := cache.MetaNamespaceKeyFunc(ds) - dsc.removeSuspendedDaemonPods(node.Name, dsKey) - - switch { - case wantToRun && !shouldSchedule: - // If daemon pod is supposed to run, but can not be scheduled, add to suspended list. - dsc.addSuspendedDaemonPods(node.Name, dsKey) - case shouldSchedule && !exists: - // If daemon pod is supposed to be running on node, but isn't, create daemon pod. - nodesNeedingDaemonPods = append(nodesNeedingDaemonPods, node.Name) - case shouldContinueRunning: - // If a daemon pod failed, delete it - // If there's non-daemon pods left on this node, we will create it in the next sync loop - var daemonPodsRunning []*v1.Pod - for _, pod := range daemonPods { - if pod.DeletionTimestamp != nil { - continue - } - if pod.Status.Phase == v1.PodFailed { - msg := fmt.Sprintf("Found failed daemon pod %s/%s on node %s, will try to kill it", pod.Namespace, pod.Name, node.Name) - glog.V(2).Infof(msg) - // Emit an event so that it's discoverable to users. - dsc.eventRecorder.Eventf(ds, v1.EventTypeWarning, FailedDaemonPodReason, msg) - podsToDelete = append(podsToDelete, pod.Name) - failedPodsObserved++ - } else { - daemonPodsRunning = append(daemonPodsRunning, pod) - } - } - // If daemon pod is supposed to be running on node, but more than 1 daemon pod is running, delete the excess daemon pods. - // Sort the daemon pods by creation time, so the oldest is preserved. - if len(daemonPodsRunning) > 1 { - sort.Sort(podByCreationTimestamp(daemonPodsRunning)) - for i := 1; i < len(daemonPodsRunning); i++ { - podsToDelete = append(podsToDelete, daemonPodsRunning[i].Name) - } - } - case !shouldContinueRunning && exists: - // If daemon pod isn't supposed to run on node, but it is, delete all daemon pods on node. - for _, pod := range daemonPods { - podsToDelete = append(podsToDelete, pod.Name) - } - } + nodesNeedingDaemonPods = append(nodesNeedingDaemonPods, nodesNeedingDaemonPodsOnNode...) + podsToDelete = append(podsToDelete, podsToDeleteOnNode...) + failedPodsObserved += failedPodsObservedOnNode } // Label new pods using the hash label value of the current history when creating them @@ -938,9 +990,12 @@ func (dsc *DaemonSetsController) syncNodes(ds *apps.DaemonSet, podsToDelete, nod podTemplate := &template - if false /*disabled for 1.10*/ && utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { + if utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { podTemplate = template.DeepCopy() - podTemplate.Spec.Affinity = util.ReplaceDaemonSetPodHostnameNodeAffinity( + // The pod's NodeAffinity will be updated to make sure the Pod is bound + // to the target node by default scheduler. It is safe to do so because there + // should be no conflicting node affinity with the target node. + podTemplate.Spec.Affinity = util.ReplaceDaemonSetPodNodeNameNodeAffinity( podTemplate.Spec.Affinity, nodesNeedingDaemonPods[ix]) podTemplate.Spec.Tolerations = util.AppendNoScheduleTolerationIfNotExist(podTemplate.Spec.Tolerations) @@ -1074,7 +1129,7 @@ func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *apps.DaemonSet, hash currentNumberScheduled++ // Sort the daemon pods by creation time, so that the oldest is first. daemonPods, _ := nodeToDaemonPods[node.Name] - sort.Sort(podByCreationTimestamp(daemonPods)) + sort.Sort(podByCreationTimestampAndPhase(daemonPods)) pod := daemonPods[0] if podutil.IsPodReady(pod) { numberReady++ @@ -1111,7 +1166,7 @@ func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *apps.DaemonSet, hash func (dsc *DaemonSetsController) syncDaemonSet(key string) error { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing daemon set %q (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing daemon set %q (%v)", key, time.Since(startTime)) }() namespace, name, err := cache.SplitMetaNamespaceKey(key) @@ -1142,6 +1197,18 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error { return fmt.Errorf("couldn't get key for object %#v: %v", ds, err) } + // If the DaemonSet is being deleted (either by foreground deletion or + // orphan deletion), we cannot be sure if the DaemonSet history objects + // it owned still exist -- those history objects can either be deleted + // or orphaned. Garbage collector doesn't guarantee that it will delete + // DaemonSet pods before deleting DaemonSet history objects, because + // DaemonSet history doesn't own DaemonSet pods. We cannot reliably + // calculate the status of a DaemonSet being deleted. Therefore, return + // here without updating status for the DaemonSet being deleted. + if ds.DeletionTimestamp != nil { + return nil + } + // Construct histories of the DaemonSet, and get the hash of current history cur, old, err := dsc.constructHistory(ds) if err != nil { @@ -1149,7 +1216,7 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error { } hash := cur.Labels[apps.DefaultDaemonSetUniqueLabelKey] - if ds.DeletionTimestamp != nil || !dsc.expectations.SatisfiedExpectations(dsKey) { + if !dsc.expectations.SatisfiedExpectations(dsKey) { // Only update status. return dsc.updateDaemonSetStatus(ds, hash) } @@ -1225,30 +1292,27 @@ func (dsc *DaemonSetsController) simulate(newPod *v1.Pod, node *v1.Node, ds *app }) } - pods := []*v1.Pod{} - - podList, err := dsc.podLister.List(labels.Everything()) + objects, err := dsc.podNodeIndex.ByIndex("nodeName", node.Name) if err != nil { return nil, nil, err } - for _, pod := range podList { - if pod.Spec.NodeName != node.Name { - continue - } - if pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed { + + nodeInfo := schedulercache.NewNodeInfo() + nodeInfo.SetNode(node) + + for _, obj := range objects { + // Ignore pods that belong to the daemonset when taking into account whether a daemonset should bind to a node. + // TODO: replace this with metav1.IsControlledBy() in 1.12 + pod, ok := obj.(*v1.Pod) + if !ok { continue } - // ignore pods that belong to the daemonset when taking into account whether - // a daemonset should bind to a node. - if metav1.IsControlledBy(pod, ds) { + if isControlledByDaemonSet(pod, ds.GetUID()) { continue } - pods = append(pods, pod) + nodeInfo.AddPod(pod) } - nodeInfo := schedulercache.NewNodeInfo(pods...) - nodeInfo.SetNode(node) - _, reasons, err := Predicates(newPod, nodeInfo) return reasons, nodeInfo, err } @@ -1390,7 +1454,7 @@ func Predicates(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo) (bool, []algorit var predicateFails []algorithm.PredicateFailureReason // If ScheduleDaemonSetPods is enabled, only check nodeSelector and nodeAffinity. - if false /*disabled for 1.10*/ && utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { + if utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { fit, reasons, err := nodeSelectionPredicates(pod, nil, nodeInfo) if err != nil { return false, predicateFails, err @@ -1442,14 +1506,32 @@ func (o byCreationTimestamp) Less(i, j int) bool { return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp) } -type podByCreationTimestamp []*v1.Pod +type podByCreationTimestampAndPhase []*v1.Pod + +func (o podByCreationTimestampAndPhase) Len() int { return len(o) } +func (o podByCreationTimestampAndPhase) Swap(i, j int) { o[i], o[j] = o[j], o[i] } -func (o podByCreationTimestamp) Len() int { return len(o) } -func (o podByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } +func (o podByCreationTimestampAndPhase) Less(i, j int) bool { + // Scheduled Pod first + if len(o[i].Spec.NodeName) != 0 && len(o[j].Spec.NodeName) == 0 { + return true + } + + if len(o[i].Spec.NodeName) == 0 && len(o[j].Spec.NodeName) != 0 { + return false + } -func (o podByCreationTimestamp) Less(i, j int) bool { if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) { return o[i].Name < o[j].Name } return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp) } + +func isControlledByDaemonSet(p *v1.Pod, uuid types.UID) bool { + for _, ref := range p.OwnerReferences { + if ref.Controller != nil && *ref.Controller && ref.UID == uuid { + return true + } + } + return false +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller_test.go index 4dbcbf57c..679402594 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller_test.go @@ -147,7 +147,7 @@ func updateStrategies() []*apps.DaemonSetUpdateStrategy { func newNode(name string, label map[string]string) *v1.Node { return &v1.Node{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: label, @@ -197,7 +197,7 @@ func newPod(podName string, nodeName string, label map[string]string, ds *apps.D } pod := &v1.Pod{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ GenerateName: podName, Labels: newLabels, @@ -1953,6 +1953,7 @@ func TestNodeShouldRunDaemonPod(t *testing.T) { for _, p := range c.podsOnNode { manager.podStore.Add(p) p.Spec.NodeName = "test-node" + manager.podNodeIndex.Add(p) } c.ds.Spec.UpdateStrategy = *strategy wantToRun, shouldSchedule, shouldContinueRunning, err := manager.nodeShouldRunDaemonPod(node, c.ds) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/BUILD index 9a64e9a62..3d92cbd88 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/BUILD @@ -14,7 +14,6 @@ go_library( "//pkg/api/v1/pod:go_default_library", "//pkg/apis/core/v1/helper:go_default_library", "//pkg/features:go_default_library", - "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", @@ -45,9 +44,12 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/api/testapi:go_default_library", + "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", + "//pkg/scheduler/algorithm: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/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/daemonset_util.go b/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/daemonset_util.go index e39f1620f..ffb7033bd 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/daemonset_util.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/daemonset_util.go @@ -29,7 +29,6 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/features" - kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/scheduler/algorithm" ) @@ -136,19 +135,20 @@ func SplitByAvailablePods(minReadySeconds int32, pods []*v1.Pod) ([]*v1.Pod, []* return availablePods, unavailablePods } -// ReplaceDaemonSetPodHostnameNodeAffinity replaces the 'kubernetes.io/hostname' NodeAffinity term with -// the given "nodeName" in the "affinity" terms. -func ReplaceDaemonSetPodHostnameNodeAffinity(affinity *v1.Affinity, nodename string) *v1.Affinity { +// ReplaceDaemonSetPodNodeNameNodeAffinity replaces the RequiredDuringSchedulingIgnoredDuringExecution +// NodeAffinity of the given affinity with a new NodeAffinity that selects the given nodeName. +// Note that this function assumes that no NodeAffinity conflicts with the selected nodeName. +func ReplaceDaemonSetPodNodeNameNodeAffinity(affinity *v1.Affinity, nodename string) *v1.Affinity { + nodeSelReq := v1.NodeSelectorRequirement{ + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{nodename}, + } + nodeSelector := &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: kubeletapis.LabelHostname, - Operator: v1.NodeSelectorOpIn, - Values: []string{nodename}, - }, - }, + MatchFields: []v1.NodeSelectorRequirement{nodeSelReq}, }, }, } @@ -175,28 +175,12 @@ func ReplaceDaemonSetPodHostnameNodeAffinity(affinity *v1.Affinity, nodename str return affinity } - nodeSelectorTerms := []v1.NodeSelectorTerm{} - - // Removes hostname node selector, as only the target hostname will take effect. - for _, term := range nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { - exps := []v1.NodeSelectorRequirement{} - for _, exp := range term.MatchExpressions { - if exp.Key != kubeletapis.LabelHostname { - exps = append(exps, exp) - } - } - - if len(exps) > 0 { - term.MatchExpressions = exps - nodeSelectorTerms = append(nodeSelectorTerms, term) - } - } - - // Adds target hostname NodeAffinity term. - nodeSelectorTerms = append(nodeSelectorTerms, nodeSelector.NodeSelectorTerms[0]) - // Replace node selector with the new one. - nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = nodeSelectorTerms + nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{nodeSelReq}, + }, + } return affinity } @@ -225,3 +209,42 @@ func AppendNoScheduleTolerationIfNotExist(tolerations []v1.Toleration) []v1.Tole return tolerations } + +// GetTargetNodeName get the target node name of DaemonSet pods. If `.spec.NodeName` is not empty (nil), +// return `.spec.NodeName`; otherwise, retrieve node name of pending pods from NodeAffinity. Return error +// if failed to retrieve node name from `.spec.NodeName` and NodeAffinity. +func GetTargetNodeName(pod *v1.Pod) (string, error) { + if len(pod.Spec.NodeName) != 0 { + return pod.Spec.NodeName, nil + } + + // If ScheduleDaemonSetPods was enabled before, retrieve node name of unscheduled pods from NodeAffinity + if pod.Spec.Affinity == nil || + pod.Spec.Affinity.NodeAffinity == nil || + pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil { + return "", fmt.Errorf("no spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution for pod %s/%s", + pod.Namespace, pod.Name) + } + + terms := pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms + if len(terms) < 1 { + return "", fmt.Errorf("no nodeSelectorTerms in requiredDuringSchedulingIgnoredDuringExecution of pod %s/%s", + pod.Namespace, pod.Name) + } + + for _, term := range terms { + for _, exp := range term.MatchFields { + if exp.Key == algorithm.NodeFieldSelectorKeyNodeName && + exp.Operator == v1.NodeSelectorOpIn { + if len(exp.Values) != 1 { + return "", fmt.Errorf("the matchFields value of '%s' is not unique for pod %s/%s", + algorithm.NodeFieldSelectorKeyNodeName, pod.Namespace, pod.Name) + } + + return exp.Values[0], nil + } + } + } + + return "", fmt.Errorf("no node name found for pod %s/%s", pod.Namespace, pod.Name) +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/daemonset_util_test.go b/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/daemonset_util_test.go index cf23be401..5ed8d9990 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/daemonset_util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/daemon/util/daemonset_util_test.go @@ -24,8 +24,11 @@ import ( "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/features" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + "k8s.io/kubernetes/pkg/scheduler/algorithm" ) func newPod(podName string, nodeName string, label map[string]string) *v1.Pod { @@ -171,7 +174,7 @@ func int64Ptr(i int) *int64 { return &li } -func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { +func TestReplaceDaemonSetPodNodeNameNodeAffinity(t *testing.T) { tests := []struct { affinity *v1.Affinity hostname string @@ -181,6 +184,25 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { affinity: nil, hostname: "host_1", expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + affinity: &v1.Affinity{ NodeAffinity: &v1.NodeAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ @@ -197,6 +219,24 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { }, }, }, + hostname: "host_1", + expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, }, { affinity: &v1.Affinity{ @@ -235,9 +275,9 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { - MatchExpressions: []v1.NodeSelectorRequirement{ + MatchFields: []v1.NodeSelectorRequirement{ { - Key: kubeletapis.LabelHostname, + Key: algorithm.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"host_1"}, }, @@ -254,11 +294,11 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { - MatchExpressions: []v1.NodeSelectorRequirement{ + MatchFields: []v1.NodeSelectorRequirement{ { - Key: "not-host-label", + Key: algorithm.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, - Values: []string{"label_value_1", "label_value_2"}, + Values: []string{"host_1", "host_2"}, }, }, }, @@ -272,18 +312,30 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { - MatchExpressions: []v1.NodeSelectorRequirement{ + MatchFields: []v1.NodeSelectorRequirement{ { - Key: "not-host-label", + Key: algorithm.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, - Values: []string{"label_value_1", "label_value_2"}, + Values: []string{"host_1"}, }, }, }, + }, + }, + }, + }, + }, + { + affinity: nil, + hostname: "host_1", + expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ { - MatchExpressions: []v1.NodeSelectorRequirement{ + MatchFields: []v1.NodeSelectorRequirement{ { - Key: kubeletapis.LabelHostname, + Key: algorithm.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"host_1"}, }, @@ -302,9 +354,18 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { { MatchExpressions: []v1.NodeSelectorRequirement{ { - Key: kubeletapis.LabelHostname, + Key: "hostname", Operator: v1.NodeSelectorOpIn, - Values: []string{"host_1", "host_2"}, + Values: []string{"host_1"}, + }, + }, + }, + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_2"}, }, }, }, @@ -318,9 +379,86 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { - MatchExpressions: []v1.NodeSelectorRequirement{ + MatchFields: []v1.NodeSelectorRequirement{ { - Key: kubeletapis.LabelHostname, + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpNotIn, + Values: []string{"host_2"}, + }, + }, + }, + }, + }, + }, + }, + hostname: "host_1", + expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"host_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + // NOTE: Only `metadata.name` is valid key in `MatchFields` in 1.11; + // added this case for compatibility: the feature works as normal + // when new Keys introduced. + Key: "metadata.foo", + Operator: v1.NodeSelectorOpIn, + Values: []string{"bar"}, + }, + }, + }, + }, + }, + }, + }, + hostname: "host_1", + expected: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"host_1"}, }, @@ -333,10 +471,129 @@ func TestReplaceDaemonSetPodHostnameNodeAffinity(t *testing.T) { }, } - for _, test := range tests { - got := ReplaceDaemonSetPodHostnameNodeAffinity(test.affinity, test.hostname) + for i, test := range tests { + got := ReplaceDaemonSetPodNodeNameNodeAffinity(test.affinity, test.hostname) if !reflect.DeepEqual(test.expected, got) { - t.Errorf("Failed to append NodeAffinity, got: %v, expected: %v", got, test.expected) + t.Errorf("Failed to append NodeAffinity in case %d, got: %v, expected: %v", + i, got, test.expected) + } + } +} + +func forEachFeatureGate(t *testing.T, tf func(t *testing.T), gates ...utilfeature.Feature) { + for _, fg := range gates { + func() { + enabled := utilfeature.DefaultFeatureGate.Enabled(fg) + defer func() { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=%t", fg, enabled)) + }() + + for _, f := range []bool{true, false} { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=%t", fg, f)) + t.Run(fmt.Sprintf("%v (%t)", fg, f), tf) + } + }() + } +} + +func TestGetTargetNodeName(t *testing.T) { + testFun := func(t *testing.T) { + tests := []struct { + pod *v1.Pod + nodeName string + expectedErr bool + }{ + { + pod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "default", + }, + Spec: v1.PodSpec{ + NodeName: "node-1", + }, + }, + nodeName: "node-1", + }, + { + pod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod2", + Namespace: "default", + }, + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node-1"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + nodeName: "node-1", + }, + { + pod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod3", + Namespace: "default", + }, + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node-1", "node-2"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectedErr: true, + }, + { + pod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod4", + Namespace: "default", + }, + Spec: v1.PodSpec{}, + }, + expectedErr: true, + }, + } + + for _, test := range tests { + got, err := GetTargetNodeName(test.pod) + if test.expectedErr != (err != nil) { + t.Errorf("Unexpected error, expectedErr: %v, err: %v", test.expectedErr, err) + } else if !test.expectedErr { + if test.nodeName != got { + t.Errorf("Failed to get target node name, got: %v, expected: %v", got, test.nodeName) + } + } } } + + forEachFeatureGate(t, testFun, features.ScheduleDaemonSetPods) } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/deployment/BUILD index 5754aad46..05339b466 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/BUILD @@ -23,23 +23,23 @@ go_library( "//pkg/util/labels:go_default_library", "//pkg/util/metrics:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/rand:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/client-go/informers/apps/v1:go_default_library", "//vendor/k8s.io/client-go/informers/core/v1:go_default_library", - "//vendor/k8s.io/client-go/informers/extensions/v1beta1: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/apps/v1:go_default_library", "//vendor/k8s.io/client-go/listers/core/v1:go_default_library", - "//vendor/k8s.io/client-go/listers/extensions/v1beta1: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/util/integer:go_default_library", @@ -58,7 +58,6 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/apps/install:go_default_library", "//pkg/apis/authentication/install:go_default_library", "//pkg/apis/authorization/install:go_default_library", @@ -66,13 +65,13 @@ go_test( "//pkg/apis/batch/install:go_default_library", "//pkg/apis/certificates/install:go_default_library", "//pkg/apis/core/install:go_default_library", - "//pkg/apis/extensions/install:go_default_library", "//pkg/apis/policy/install:go_default_library", "//pkg/apis/rbac/install:go_default_library", "//pkg/apis/settings/install:go_default_library", "//pkg/apis/storage/install:go_default_library", "//pkg/controller:go_default_library", "//pkg/controller/deployment/util:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller.go index 0b3461f30..8b14efddb 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller.go @@ -27,21 +27,21 @@ import ( "github.com/golang/glog" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" + appsinformers "k8s.io/client-go/informers/apps/v1" coreinformers "k8s.io/client-go/informers/core/v1" - extensionsinformers "k8s.io/client-go/informers/extensions/v1beta1" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" v1core "k8s.io/client-go/kubernetes/typed/core/v1" + appslisters "k8s.io/client-go/listers/apps/v1" corelisters "k8s.io/client-go/listers/core/v1" - extensionslisters "k8s.io/client-go/listers/extensions/v1beta1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" @@ -60,7 +60,7 @@ const ( ) // controllerKind contains the schema.GroupVersionKind for this controller type. -var controllerKind = extensions.SchemeGroupVersion.WithKind("Deployment") +var controllerKind = apps.SchemeGroupVersion.WithKind("Deployment") // DeploymentController is responsible for synchronizing Deployment objects stored // in the system with actual running replica sets and pods. @@ -73,12 +73,12 @@ type DeploymentController struct { // To allow injection of syncDeployment for testing. syncHandler func(dKey string) error // used for unit testing - enqueueDeployment func(deployment *extensions.Deployment) + enqueueDeployment func(deployment *apps.Deployment) // dLister can list/get deployments from the shared informer's store - dLister extensionslisters.DeploymentLister + dLister appslisters.DeploymentLister // rsLister can list/get replica sets from the shared informer's store - rsLister extensionslisters.ReplicaSetLister + rsLister appslisters.ReplicaSetLister // podLister can list/get pods from the shared informer's store podLister corelisters.PodLister @@ -97,11 +97,10 @@ type DeploymentController struct { } // NewDeploymentController creates a new DeploymentController. -func NewDeploymentController(dInformer extensionsinformers.DeploymentInformer, rsInformer extensionsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, client clientset.Interface) (*DeploymentController, error) { +func NewDeploymentController(dInformer appsinformers.DeploymentInformer, rsInformer appsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, client clientset.Interface) (*DeploymentController, error) { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - // TODO: remove the wrapper when every clients have moved to use the clientset. - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(client.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: client.CoreV1().Events("")}) if client != nil && client.CoreV1().RESTClient().GetRateLimiter() != nil { if err := metrics.RegisterMetricAndTrackRateLimiterUsage("deployment_controller", client.CoreV1().RESTClient().GetRateLimiter()); err != nil { @@ -165,27 +164,27 @@ func (dc *DeploymentController) Run(workers int, stopCh <-chan struct{}) { } func (dc *DeploymentController) addDeployment(obj interface{}) { - d := obj.(*extensions.Deployment) + d := obj.(*apps.Deployment) glog.V(4).Infof("Adding deployment %s", d.Name) dc.enqueueDeployment(d) } func (dc *DeploymentController) updateDeployment(old, cur interface{}) { - oldD := old.(*extensions.Deployment) - curD := cur.(*extensions.Deployment) + oldD := old.(*apps.Deployment) + curD := cur.(*apps.Deployment) glog.V(4).Infof("Updating deployment %s", oldD.Name) dc.enqueueDeployment(curD) } func (dc *DeploymentController) deleteDeployment(obj interface{}) { - d, ok := obj.(*extensions.Deployment) + d, ok := obj.(*apps.Deployment) if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { utilruntime.HandleError(fmt.Errorf("Couldn't get object from tombstone %#v", obj)) return } - d, ok = tombstone.Obj.(*extensions.Deployment) + d, ok = tombstone.Obj.(*apps.Deployment) if !ok { utilruntime.HandleError(fmt.Errorf("Tombstone contained object that is not a Deployment %#v", obj)) return @@ -197,7 +196,7 @@ func (dc *DeploymentController) deleteDeployment(obj interface{}) { // addReplicaSet enqueues the deployment that manages a ReplicaSet when the ReplicaSet is created. func (dc *DeploymentController) addReplicaSet(obj interface{}) { - rs := obj.(*extensions.ReplicaSet) + rs := obj.(*apps.ReplicaSet) if rs.DeletionTimestamp != nil { // On a restart of the controller manager, it's possible for an object to @@ -231,7 +230,7 @@ func (dc *DeploymentController) addReplicaSet(obj interface{}) { // getDeploymentsForReplicaSet returns a list of Deployments that potentially // match a ReplicaSet. -func (dc *DeploymentController) getDeploymentsForReplicaSet(rs *extensions.ReplicaSet) []*extensions.Deployment { +func (dc *DeploymentController) getDeploymentsForReplicaSet(rs *apps.ReplicaSet) []*apps.Deployment { deployments, err := dc.dLister.GetDeploymentsForReplicaSet(rs) if err != nil || len(deployments) == 0 { return nil @@ -251,11 +250,11 @@ func (dc *DeploymentController) getDeploymentsForReplicaSet(rs *extensions.Repli // updateReplicaSet figures out what deployment(s) manage a ReplicaSet when the ReplicaSet // is updated and wake them up. If the anything of the ReplicaSets have changed, we need to -// awaken both the old and new deployments. old and cur must be *extensions.ReplicaSet +// awaken both the old and new deployments. old and cur must be *apps.ReplicaSet // types. func (dc *DeploymentController) updateReplicaSet(old, cur interface{}) { - curRS := cur.(*extensions.ReplicaSet) - oldRS := old.(*extensions.ReplicaSet) + curRS := cur.(*apps.ReplicaSet) + oldRS := old.(*apps.ReplicaSet) if curRS.ResourceVersion == oldRS.ResourceVersion { // Periodic resync will send update events for all known replica sets. // Two different versions of the same replica set will always have different RVs. @@ -299,10 +298,10 @@ func (dc *DeploymentController) updateReplicaSet(old, cur interface{}) { } // deleteReplicaSet enqueues the deployment that manages a ReplicaSet when -// the ReplicaSet is deleted. obj could be an *extensions.ReplicaSet, or +// the ReplicaSet is deleted. obj could be an *apps.ReplicaSet, or // a DeletionFinalStateUnknown marker item. func (dc *DeploymentController) deleteReplicaSet(obj interface{}) { - rs, ok := obj.(*extensions.ReplicaSet) + rs, ok := obj.(*apps.ReplicaSet) // When a delete is dropped, the relist will notice a pod in the store not // in the list, leading to the insertion of a tombstone object which contains @@ -314,7 +313,7 @@ func (dc *DeploymentController) deleteReplicaSet(obj interface{}) { utilruntime.HandleError(fmt.Errorf("Couldn't get object from tombstone %#v", obj)) return } - rs, ok = tombstone.Obj.(*extensions.ReplicaSet) + rs, ok = tombstone.Obj.(*apps.ReplicaSet) if !ok { utilruntime.HandleError(fmt.Errorf("Tombstone contained object that is not a ReplicaSet %#v", obj)) return @@ -355,9 +354,9 @@ func (dc *DeploymentController) deletePod(obj interface{}) { } } glog.V(4).Infof("Pod %s deleted.", pod.Name) - if d := dc.getDeploymentForPod(pod); d != nil && d.Spec.Strategy.Type == extensions.RecreateDeploymentStrategyType { + if d := dc.getDeploymentForPod(pod); d != nil && d.Spec.Strategy.Type == apps.RecreateDeploymentStrategyType { // Sync if this Deployment now has no more Pods. - rsList, err := util.ListReplicaSets(d, util.RsListFromClient(dc.client.ExtensionsV1beta1())) + rsList, err := util.ListReplicaSets(d, util.RsListFromClient(dc.client.AppsV1())) if err != nil { return } @@ -375,7 +374,7 @@ func (dc *DeploymentController) deletePod(obj interface{}) { } } -func (dc *DeploymentController) enqueue(deployment *extensions.Deployment) { +func (dc *DeploymentController) enqueue(deployment *apps.Deployment) { key, err := controller.KeyFunc(deployment) if err != nil { utilruntime.HandleError(fmt.Errorf("Couldn't get key for object %#v: %v", deployment, err)) @@ -385,7 +384,7 @@ func (dc *DeploymentController) enqueue(deployment *extensions.Deployment) { dc.queue.Add(key) } -func (dc *DeploymentController) enqueueRateLimited(deployment *extensions.Deployment) { +func (dc *DeploymentController) enqueueRateLimited(deployment *apps.Deployment) { key, err := controller.KeyFunc(deployment) if err != nil { utilruntime.HandleError(fmt.Errorf("Couldn't get key for object %#v: %v", deployment, err)) @@ -396,7 +395,7 @@ func (dc *DeploymentController) enqueueRateLimited(deployment *extensions.Deploy } // enqueueAfter will enqueue a deployment after the provided amount of time. -func (dc *DeploymentController) enqueueAfter(deployment *extensions.Deployment, after time.Duration) { +func (dc *DeploymentController) enqueueAfter(deployment *apps.Deployment, after time.Duration) { key, err := controller.KeyFunc(deployment) if err != nil { utilruntime.HandleError(fmt.Errorf("Couldn't get key for object %#v: %v", deployment, err)) @@ -407,16 +406,16 @@ func (dc *DeploymentController) enqueueAfter(deployment *extensions.Deployment, } // getDeploymentForPod returns the deployment managing the given Pod. -func (dc *DeploymentController) getDeploymentForPod(pod *v1.Pod) *extensions.Deployment { +func (dc *DeploymentController) getDeploymentForPod(pod *v1.Pod) *apps.Deployment { // Find the owning replica set - var rs *extensions.ReplicaSet + var rs *apps.ReplicaSet var err error controllerRef := metav1.GetControllerOf(pod) if controllerRef == nil { // No controller owns this Pod. return nil } - if controllerRef.Kind != extensions.SchemeGroupVersion.WithKind("ReplicaSet").Kind { + if controllerRef.Kind != apps.SchemeGroupVersion.WithKind("ReplicaSet").Kind { // Not a pod owned by a replica set. return nil } @@ -437,7 +436,7 @@ func (dc *DeploymentController) getDeploymentForPod(pod *v1.Pod) *extensions.Dep // resolveControllerRef returns the controller referenced by a ControllerRef, // or nil if the ControllerRef could not be resolved to a matching controller // of the correct Kind. -func (dc *DeploymentController) resolveControllerRef(namespace string, controllerRef *metav1.OwnerReference) *extensions.Deployment { +func (dc *DeploymentController) resolveControllerRef(namespace string, controllerRef *metav1.OwnerReference) *apps.Deployment { // We can't look up by UID, so look up by Name and then verify UID. // Don't even try to look up by Name if it's the wrong Kind. if controllerRef.Kind != controllerKind.Kind { @@ -495,7 +494,7 @@ func (dc *DeploymentController) handleErr(err error, key interface{}) { // getReplicaSetsForDeployment uses ControllerRefManager to reconcile // ControllerRef by adopting and orphaning. // It returns the list of ReplicaSets that this Deployment should manage. -func (dc *DeploymentController) getReplicaSetsForDeployment(d *extensions.Deployment) ([]*extensions.ReplicaSet, error) { +func (dc *DeploymentController) getReplicaSetsForDeployment(d *apps.Deployment) ([]*apps.ReplicaSet, error) { // List all ReplicaSets to find those we own but that no longer match our // selector. They will be orphaned by ClaimReplicaSets(). rsList, err := dc.rsLister.ReplicaSets(d.Namespace).List(labels.Everything()) @@ -509,7 +508,7 @@ func (dc *DeploymentController) getReplicaSetsForDeployment(d *extensions.Deploy // If any adoptions are attempted, we should first recheck for deletion with // an uncached quorum read sometime after listing ReplicaSets (see #42639). canAdoptFunc := controller.RecheckDeletionTimestamp(func() (metav1.Object, error) { - fresh, err := dc.client.ExtensionsV1beta1().Deployments(d.Namespace).Get(d.Name, metav1.GetOptions{}) + fresh, err := dc.client.AppsV1().Deployments(d.Namespace).Get(d.Name, metav1.GetOptions{}) if err != nil { return nil, err } @@ -526,7 +525,7 @@ func (dc *DeploymentController) getReplicaSetsForDeployment(d *extensions.Deploy // // It returns a map from ReplicaSet UID to a list of Pods controlled by that RS, // according to the Pod's ControllerRef. -func (dc *DeploymentController) getPodMapForDeployment(d *extensions.Deployment, rsList []*extensions.ReplicaSet) (map[types.UID]*v1.PodList, error) { +func (dc *DeploymentController) getPodMapForDeployment(d *apps.Deployment, rsList []*apps.ReplicaSet) (map[types.UID]*v1.PodList, error) { // Get all Pods that potentially belong to this Deployment. selector, err := metav1.LabelSelectorAsSelector(d.Spec.Selector) if err != nil { @@ -587,7 +586,7 @@ func (dc *DeploymentController) syncDeployment(key string) error { dc.eventRecorder.Eventf(d, v1.EventTypeWarning, "SelectingAll", "This deployment is selecting all pods. A non-empty selector is required.") if d.Status.ObservedGeneration < d.Generation { d.Status.ObservedGeneration = d.Generation - dc.client.ExtensionsV1beta1().Deployments(d.Namespace).UpdateStatus(d) + dc.client.AppsV1().Deployments(d.Namespace).UpdateStatus(d) } return nil } @@ -626,7 +625,7 @@ func (dc *DeploymentController) syncDeployment(key string) error { // rollback is not re-entrant in case the underlying replica sets are updated with a new // revision so we should ensure that we won't proceed to update replica sets until we // make sure that the deployment has cleaned up its rollback spec in subsequent enqueues. - if d.Spec.RollbackTo != nil { + if getRollbackTo(d) != nil { return dc.rollback(d, rsList, podMap) } @@ -639,9 +638,9 @@ func (dc *DeploymentController) syncDeployment(key string) error { } switch d.Spec.Strategy.Type { - case extensions.RecreateDeploymentStrategyType: + case apps.RecreateDeploymentStrategyType: return dc.rolloutRecreate(d, rsList, podMap) - case extensions.RollingUpdateDeploymentStrategyType: + case apps.RollingUpdateDeploymentStrategyType: return dc.rolloutRolling(d, rsList, podMap) } return fmt.Errorf("unexpected deployment strategy type: %s", d.Spec.Strategy.Type) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller_test.go index 7b4ed1432..6b289fe0d 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller_test.go @@ -20,6 +20,7 @@ import ( "strconv" "testing" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,7 +32,6 @@ import ( "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/api/legacyscheme" _ "k8s.io/kubernetes/pkg/apis/apps/install" _ "k8s.io/kubernetes/pkg/apis/authentication/install" _ "k8s.io/kubernetes/pkg/apis/authorization/install" @@ -39,7 +39,6 @@ import ( _ "k8s.io/kubernetes/pkg/apis/batch/install" _ "k8s.io/kubernetes/pkg/apis/certificates/install" _ "k8s.io/kubernetes/pkg/apis/core/install" - _ "k8s.io/kubernetes/pkg/apis/extensions/install" _ "k8s.io/kubernetes/pkg/apis/policy/install" _ "k8s.io/kubernetes/pkg/apis/rbac/install" _ "k8s.io/kubernetes/pkg/apis/settings/install" @@ -53,14 +52,14 @@ var ( noTimestamp = metav1.Time{} ) -func rs(name string, replicas int, selector map[string]string, timestamp metav1.Time) *extensions.ReplicaSet { - return &extensions.ReplicaSet{ +func rs(name string, replicas int, selector map[string]string, timestamp metav1.Time) *apps.ReplicaSet { + return &apps.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ Name: name, CreationTimestamp: timestamp, Namespace: metav1.NamespaceDefault, }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: func() *int32 { i := int32(replicas); return &i }(), Selector: &metav1.LabelSelector{MatchLabels: selector}, Template: v1.PodTemplateSpec{}, @@ -68,27 +67,27 @@ func rs(name string, replicas int, selector map[string]string, timestamp metav1. } } -func newRSWithStatus(name string, specReplicas, statusReplicas int, selector map[string]string) *extensions.ReplicaSet { +func newRSWithStatus(name string, specReplicas, statusReplicas int, selector map[string]string) *apps.ReplicaSet { rs := rs(name, specReplicas, selector, noTimestamp) - rs.Status = extensions.ReplicaSetStatus{ + rs.Status = apps.ReplicaSetStatus{ Replicas: int32(statusReplicas), } return rs } -func newDeployment(name string, replicas int, revisionHistoryLimit *int32, maxSurge, maxUnavailable *intstr.IntOrString, selector map[string]string) *extensions.Deployment { - d := extensions.Deployment{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(extensions.GroupName).GroupVersion.String()}, +func newDeployment(name string, replicas int, revisionHistoryLimit *int32, maxSurge, maxUnavailable *intstr.IntOrString, selector map[string]string) *apps.Deployment { + d := apps.Deployment{ + TypeMeta: metav1.TypeMeta{APIVersion: "apps/v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: name, Namespace: metav1.NamespaceDefault, Annotations: make(map[string]string), }, - Spec: extensions.DeploymentSpec{ - Strategy: extensions.DeploymentStrategy{ - Type: extensions.RollingUpdateDeploymentStrategyType, - RollingUpdate: &extensions.RollingUpdateDeployment{ + Spec: apps.DeploymentSpec{ + Strategy: apps.DeploymentStrategy{ + Type: apps.RollingUpdateDeploymentStrategyType, + RollingUpdate: &apps.RollingUpdateDeployment{ MaxUnavailable: func() *intstr.IntOrString { i := intstr.FromInt(0); return &i }(), MaxSurge: func() *intstr.IntOrString { i := intstr.FromInt(0); return &i }(), }, @@ -119,8 +118,8 @@ func newDeployment(name string, replicas int, revisionHistoryLimit *int32, maxSu return &d } -func newReplicaSet(d *extensions.Deployment, name string, replicas int) *extensions.ReplicaSet { - return &extensions.ReplicaSet{ +func newReplicaSet(d *apps.Deployment, name string, replicas int) *apps.ReplicaSet { + return &apps.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ Name: name, UID: uuid.NewUUID(), @@ -128,7 +127,7 @@ func newReplicaSet(d *extensions.Deployment, name string, replicas int) *extensi Labels: d.Spec.Selector.MatchLabels, OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(d, controllerKind)}, }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Selector: d.Spec.Selector, Replicas: func() *int32 { i := int32(replicas); return &i }(), Template: d.Spec.Template, @@ -136,7 +135,7 @@ func newReplicaSet(d *extensions.Deployment, name string, replicas int) *extensi } } -func getKey(d *extensions.Deployment, t *testing.T) string { +func getKey(d *apps.Deployment, t *testing.T) string { if key, err := controller.KeyFunc(d); err != nil { t.Errorf("Unexpected error getting key for deployment %v: %v", d.Name, err) return "" @@ -150,8 +149,8 @@ type fixture struct { client *fake.Clientset // Objects to put in the store. - dLister []*extensions.Deployment - rsLister []*extensions.ReplicaSet + dLister []*apps.Deployment + rsLister []*apps.ReplicaSet podLister []*v1.Pod // Actions expected to happen on the client. Objects from here are also @@ -160,23 +159,23 @@ type fixture struct { objects []runtime.Object } -func (f *fixture) expectGetDeploymentAction(d *extensions.Deployment) { +func (f *fixture) expectGetDeploymentAction(d *apps.Deployment) { action := core.NewGetAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d.Name) f.actions = append(f.actions, action) } -func (f *fixture) expectUpdateDeploymentStatusAction(d *extensions.Deployment) { +func (f *fixture) expectUpdateDeploymentStatusAction(d *apps.Deployment) { action := core.NewUpdateAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d) action.Subresource = "status" f.actions = append(f.actions, action) } -func (f *fixture) expectUpdateDeploymentAction(d *extensions.Deployment) { +func (f *fixture) expectUpdateDeploymentAction(d *apps.Deployment) { action := core.NewUpdateAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d) f.actions = append(f.actions, action) } -func (f *fixture) expectCreateRSAction(rs *extensions.ReplicaSet) { +func (f *fixture) expectCreateRSAction(rs *apps.ReplicaSet) { f.actions = append(f.actions, core.NewCreateAction(schema.GroupVersionResource{Resource: "replicasets"}, rs.Namespace, rs)) } @@ -190,7 +189,7 @@ func newFixture(t *testing.T) *fixture { func (f *fixture) newController() (*DeploymentController, informers.SharedInformerFactory, error) { f.client = fake.NewSimpleClientset(f.objects...) informers := informers.NewSharedInformerFactory(f.client, controller.NoResyncPeriodFunc()) - c, err := NewDeploymentController(informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().ReplicaSets(), informers.Core().V1().Pods(), f.client) + c, err := NewDeploymentController(informers.Apps().V1().Deployments(), informers.Apps().V1().ReplicaSets(), informers.Core().V1().Pods(), f.client) if err != nil { return nil, nil, err } @@ -199,10 +198,10 @@ func (f *fixture) newController() (*DeploymentController, informers.SharedInform c.rsListerSynced = alwaysReady c.podListerSynced = alwaysReady for _, d := range f.dLister { - informers.Extensions().V1beta1().Deployments().Informer().GetIndexer().Add(d) + informers.Apps().V1().Deployments().Informer().GetIndexer().Add(d) } for _, rs := range f.rsLister { - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs) } for _, pod := range f.podLister { informers.Core().V1().Pods().Informer().GetIndexer().Add(pod) @@ -345,20 +344,19 @@ func TestReentrantRollback(t *testing.T) { f := newFixture(t) d := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) - - d.Spec.RollbackTo = &extensions.RollbackConfig{Revision: 0} d.Annotations = map[string]string{util.RevisionAnnotation: "2"} + setRollbackTo(d, &extensions.RollbackConfig{Revision: 0}) f.dLister = append(f.dLister, d) rs1 := newReplicaSet(d, "deploymentrs-old", 0) rs1.Annotations = map[string]string{util.RevisionAnnotation: "1"} one := int64(1) rs1.Spec.Template.Spec.TerminationGracePeriodSeconds = &one - rs1.Spec.Selector.MatchLabels[extensions.DefaultDeploymentUniqueLabelKey] = "hash" + rs1.Spec.Selector.MatchLabels[apps.DefaultDeploymentUniqueLabelKey] = "hash" rs2 := newReplicaSet(d, "deploymentrs-new", 1) rs2.Annotations = map[string]string{util.RevisionAnnotation: "2"} - rs2.Spec.Selector.MatchLabels[extensions.DefaultDeploymentUniqueLabelKey] = "hash" + rs2.Spec.Selector.MatchLabels[apps.DefaultDeploymentUniqueLabelKey] = "hash" f.rsLister = append(f.rsLister, rs1, rs2) f.objects = append(f.objects, d, rs1, rs2) @@ -376,7 +374,7 @@ func TestPodDeletionEnqueuesRecreateDeployment(t *testing.T) { f := newFixture(t) foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) - foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType + foo.Spec.Strategy.Type = apps.RecreateDeploymentStrategyType rs := newReplicaSet(foo, "foo-1", 1) pod := generatePodFromRS(rs) @@ -389,7 +387,7 @@ func TestPodDeletionEnqueuesRecreateDeployment(t *testing.T) { t.Fatalf("error creating Deployment controller: %v", err) } enqueued := false - c.enqueueDeployment = func(d *extensions.Deployment) { + c.enqueueDeployment = func(d *apps.Deployment) { if d.Name == "foo" { enqueued = true } @@ -409,7 +407,7 @@ func TestPodDeletionDoesntEnqueueRecreateDeployment(t *testing.T) { f := newFixture(t) foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) - foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType + foo.Spec.Strategy.Type = apps.RecreateDeploymentStrategyType rs1 := newReplicaSet(foo, "foo-1", 1) rs2 := newReplicaSet(foo, "foo-1", 1) pod1 := generatePodFromRS(rs1) @@ -425,7 +423,7 @@ func TestPodDeletionDoesntEnqueueRecreateDeployment(t *testing.T) { t.Fatalf("error creating Deployment controller: %v", err) } enqueued := false - c.enqueueDeployment = func(d *extensions.Deployment) { + c.enqueueDeployment = func(d *apps.Deployment) { if d.Name == "foo" { enqueued = true } @@ -446,7 +444,7 @@ func TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment(t *testi f := newFixture(t) foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) - foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType + foo.Spec.Strategy.Type = apps.RecreateDeploymentStrategyType rs1 := newReplicaSet(foo, "foo-1", 1) rs2 := newReplicaSet(foo, "foo-2", 2) rs2.OwnerReferences = nil @@ -461,7 +459,7 @@ func TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment(t *testi t.Fatalf("error creating Deployment controller: %v", err) } enqueued := false - c.enqueueDeployment = func(d *extensions.Deployment) { + c.enqueueDeployment = func(d *apps.Deployment) { if d.Name == "foo" { enqueued = true } @@ -482,7 +480,7 @@ func TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment(t f := newFixture(t) foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) - foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType + foo.Spec.Strategy.Type = apps.RecreateDeploymentStrategyType rs1 := newReplicaSet(foo, "foo-1", 1) rs2 := newReplicaSet(foo, "foo-2", 2) rs2.OwnerReferences = nil @@ -500,7 +498,7 @@ func TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment(t t.Fatalf("error creating Deployment controller: %v", err) } enqueued := false - c.enqueueDeployment = func(d *extensions.Deployment) { + c.enqueueDeployment = func(d *apps.Deployment) { if d.Name == "foo" { enqueued = true } @@ -973,7 +971,7 @@ func bumpResourceVersion(obj metav1.Object) { } // generatePodFromRS creates a pod, with the input ReplicaSet's selector and its template -func generatePodFromRS(rs *extensions.ReplicaSet) *v1.Pod { +func generatePodFromRS(rs *apps.ReplicaSet) *v1.Pod { trueVar := true return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/progress.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/progress.go index 1cd25ed1f..cfe35ebab 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/progress.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/progress.go @@ -23,8 +23,8 @@ import ( "github.com/golang/glog" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/kubernetes/pkg/controller/deployment/util" ) @@ -32,18 +32,18 @@ import ( // cases this helper will run that cannot be prevented from the scaling detection, // for example a resync of the deployment after it was scaled up. In those cases, // we shouldn't try to estimate any progress. -func (dc *DeploymentController) syncRolloutStatus(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, d *extensions.Deployment) error { +func (dc *DeploymentController) syncRolloutStatus(allRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, d *apps.Deployment) error { newStatus := calculateStatus(allRSs, newRS, d) // If there is no progressDeadlineSeconds set, remove any Progressing condition. if d.Spec.ProgressDeadlineSeconds == nil { - util.RemoveDeploymentCondition(&newStatus, extensions.DeploymentProgressing) + util.RemoveDeploymentCondition(&newStatus, apps.DeploymentProgressing) } // If there is only one replica set that is active then that means we are not running // a new rollout and this is a resync where we don't need to estimate any progress. // In such a case, we should simply not estimate any progress for this deployment. - currentCond := util.GetDeploymentCondition(d.Status, extensions.DeploymentProgressing) + currentCond := util.GetDeploymentCondition(d.Status, apps.DeploymentProgressing) isCompleteDeployment := newStatus.Replicas == newStatus.UpdatedReplicas && currentCond != nil && currentCond.Reason == util.NewRSAvailableReason // Check for progress only if there is a progress deadline set and the latest rollout // hasn't completed yet. @@ -56,7 +56,7 @@ func (dc *DeploymentController) syncRolloutStatus(allRSs []*extensions.ReplicaSe if newRS != nil { msg = fmt.Sprintf("ReplicaSet %q has successfully progressed.", newRS.Name) } - condition := util.NewDeploymentCondition(extensions.DeploymentProgressing, v1.ConditionTrue, util.NewRSAvailableReason, msg) + condition := util.NewDeploymentCondition(apps.DeploymentProgressing, v1.ConditionTrue, util.NewRSAvailableReason, msg) util.SetDeploymentCondition(&newStatus, *condition) case util.DeploymentProgressing(d, &newStatus): @@ -66,7 +66,7 @@ func (dc *DeploymentController) syncRolloutStatus(allRSs []*extensions.ReplicaSe if newRS != nil { msg = fmt.Sprintf("ReplicaSet %q is progressing.", newRS.Name) } - condition := util.NewDeploymentCondition(extensions.DeploymentProgressing, v1.ConditionTrue, util.ReplicaSetUpdatedReason, msg) + condition := util.NewDeploymentCondition(apps.DeploymentProgressing, v1.ConditionTrue, util.ReplicaSetUpdatedReason, msg) // Update the current Progressing condition or add a new one if it doesn't exist. // If a Progressing condition with status=true already exists, we should update // everything but lastTransitionTime. SetDeploymentCondition already does that but @@ -78,7 +78,7 @@ func (dc *DeploymentController) syncRolloutStatus(allRSs []*extensions.ReplicaSe if currentCond.Status == v1.ConditionTrue { condition.LastTransitionTime = currentCond.LastTransitionTime } - util.RemoveDeploymentCondition(&newStatus, extensions.DeploymentProgressing) + util.RemoveDeploymentCondition(&newStatus, apps.DeploymentProgressing) } util.SetDeploymentCondition(&newStatus, *condition) @@ -89,7 +89,7 @@ func (dc *DeploymentController) syncRolloutStatus(allRSs []*extensions.ReplicaSe if newRS != nil { msg = fmt.Sprintf("ReplicaSet %q has timed out progressing.", newRS.Name) } - condition := util.NewDeploymentCondition(extensions.DeploymentProgressing, v1.ConditionFalse, util.TimedOutReason, msg) + condition := util.NewDeploymentCondition(apps.DeploymentProgressing, v1.ConditionFalse, util.TimedOutReason, msg) util.SetDeploymentCondition(&newStatus, *condition) } } @@ -100,7 +100,7 @@ func (dc *DeploymentController) syncRolloutStatus(allRSs []*extensions.ReplicaSe // There will be only one ReplicaFailure condition on the replica set. util.SetDeploymentCondition(&newStatus, replicaFailureCond[0]) } else { - util.RemoveDeploymentCondition(&newStatus, extensions.DeploymentReplicaFailure) + util.RemoveDeploymentCondition(&newStatus, apps.DeploymentReplicaFailure) } // Do not update if there is nothing new to add. @@ -112,17 +112,17 @@ func (dc *DeploymentController) syncRolloutStatus(allRSs []*extensions.ReplicaSe newDeployment := d newDeployment.Status = newStatus - _, err := dc.client.ExtensionsV1beta1().Deployments(newDeployment.Namespace).UpdateStatus(newDeployment) + _, err := dc.client.AppsV1().Deployments(newDeployment.Namespace).UpdateStatus(newDeployment) return err } // getReplicaFailures will convert replica failure conditions from replica sets // to deployment conditions. -func (dc *DeploymentController) getReplicaFailures(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet) []extensions.DeploymentCondition { - var conditions []extensions.DeploymentCondition +func (dc *DeploymentController) getReplicaFailures(allRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet) []apps.DeploymentCondition { + var conditions []apps.DeploymentCondition if newRS != nil { for _, c := range newRS.Status.Conditions { - if c.Type != extensions.ReplicaSetReplicaFailure { + if c.Type != apps.ReplicaSetReplicaFailure { continue } conditions = append(conditions, util.ReplicaSetToDeploymentCondition(c)) @@ -141,7 +141,7 @@ func (dc *DeploymentController) getReplicaFailures(allRSs []*extensions.ReplicaS } for _, c := range rs.Status.Conditions { - if c.Type != extensions.ReplicaSetReplicaFailure { + if c.Type != apps.ReplicaSetReplicaFailure { continue } conditions = append(conditions, util.ReplicaSetToDeploymentCondition(c)) @@ -156,8 +156,8 @@ var nowFn = func() time.Time { return time.Now() } // requeueStuckDeployment checks whether the provided deployment needs to be synced for a progress // check. It returns the time after the deployment will be requeued for the progress check, 0 if it // will be requeued now, or -1 if it does not need to be requeued. -func (dc *DeploymentController) requeueStuckDeployment(d *extensions.Deployment, newStatus extensions.DeploymentStatus) time.Duration { - currentCond := util.GetDeploymentCondition(d.Status, extensions.DeploymentProgressing) +func (dc *DeploymentController) requeueStuckDeployment(d *apps.Deployment, newStatus apps.DeploymentStatus) time.Duration { + currentCond := util.GetDeploymentCondition(d.Status, apps.DeploymentProgressing) // Can't estimate progress if there is no deadline in the spec or progressing condition in the current status. if d.Spec.ProgressDeadlineSeconds == nil || currentCond == nil { return time.Duration(-1) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/progress_test.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/progress_test.go index 978b21469..da0aa2d67 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/progress_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/progress_test.go @@ -20,16 +20,16 @@ import ( "testing" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/util/workqueue" "k8s.io/kubernetes/pkg/controller/deployment/util" ) -func newDeploymentStatus(replicas, updatedReplicas, availableReplicas int32) extensions.DeploymentStatus { - return extensions.DeploymentStatus{ +func newDeploymentStatus(replicas, updatedReplicas, availableReplicas int32) apps.DeploymentStatus { + return apps.DeploymentStatus{ Replicas: replicas, UpdatedReplicas: updatedReplicas, AvailableReplicas: availableReplicas, @@ -37,16 +37,16 @@ func newDeploymentStatus(replicas, updatedReplicas, availableReplicas int32) ext } // assumes the retuned deployment is always observed - not needed to be tested here. -func currentDeployment(pds *int32, replicas, statusReplicas, updatedReplicas, availableReplicas int32, conditions []extensions.DeploymentCondition) *extensions.Deployment { - d := &extensions.Deployment{ +func currentDeployment(pds *int32, replicas, statusReplicas, updatedReplicas, availableReplicas int32, conditions []apps.DeploymentCondition) *apps.Deployment { + d := &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "progress-test", }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ ProgressDeadlineSeconds: pds, Replicas: &replicas, - Strategy: extensions.DeploymentStrategy{ - Type: extensions.RecreateDeploymentStrategyType, + Strategy: apps.DeploymentStrategy{ + Type: apps.RecreateDeploymentStrategyType, }, }, Status: newDeploymentStatus(statusReplicas, updatedReplicas, availableReplicas), @@ -56,9 +56,9 @@ func currentDeployment(pds *int32, replicas, statusReplicas, updatedReplicas, av } // helper to create RS with given availableReplicas -func newRSWithAvailable(name string, specReplicas, statusReplicas, availableReplicas int) *extensions.ReplicaSet { +func newRSWithAvailable(name string, specReplicas, statusReplicas, availableReplicas int) *apps.ReplicaSet { rs := rs(name, specReplicas, nil, metav1.Time{}) - rs.Status = extensions.ReplicaSetStatus{ + rs.Status = apps.ReplicaSetStatus{ Replicas: int32(statusReplicas), AvailableReplicas: int32(availableReplicas), } @@ -67,16 +67,16 @@ func newRSWithAvailable(name string, specReplicas, statusReplicas, availableRepl func TestRequeueStuckDeployment(t *testing.T) { pds := int32(60) - failed := []extensions.DeploymentCondition{ + failed := []apps.DeploymentCondition{ { - Type: extensions.DeploymentProgressing, + Type: apps.DeploymentProgressing, Status: v1.ConditionFalse, Reason: util.TimedOutReason, }, } - stuck := []extensions.DeploymentCondition{ + stuck := []apps.DeploymentCondition{ { - Type: extensions.DeploymentProgressing, + Type: apps.DeploymentProgressing, Status: v1.ConditionTrue, LastUpdateTime: metav1.Date(2017, 2, 15, 18, 49, 00, 00, time.UTC), }, @@ -84,8 +84,8 @@ func TestRequeueStuckDeployment(t *testing.T) { tests := []struct { name string - d *extensions.Deployment - status extensions.DeploymentStatus + d *apps.Deployment + status apps.DeploymentStatus nowFn func() time.Time expected time.Duration }{ @@ -178,20 +178,20 @@ func TestRequeueStuckDeployment(t *testing.T) { func TestSyncRolloutStatus(t *testing.T) { pds := int32(60) testTime := metav1.Date(2017, 2, 15, 18, 49, 00, 00, time.UTC) - failedTimedOut := extensions.DeploymentCondition{ - Type: extensions.DeploymentProgressing, + failedTimedOut := apps.DeploymentCondition{ + Type: apps.DeploymentProgressing, Status: v1.ConditionFalse, Reason: util.TimedOutReason, } - newRSAvailable := extensions.DeploymentCondition{ - Type: extensions.DeploymentProgressing, + newRSAvailable := apps.DeploymentCondition{ + Type: apps.DeploymentProgressing, Status: v1.ConditionTrue, Reason: util.NewRSAvailableReason, LastUpdateTime: testTime, LastTransitionTime: testTime, } - replicaSetUpdated := extensions.DeploymentCondition{ - Type: extensions.DeploymentProgressing, + replicaSetUpdated := apps.DeploymentCondition{ + Type: apps.DeploymentProgressing, Status: v1.ConditionTrue, Reason: util.ReplicaSetUpdatedReason, LastUpdateTime: testTime, @@ -200,10 +200,10 @@ func TestSyncRolloutStatus(t *testing.T) { tests := []struct { name string - d *extensions.Deployment - allRSs []*extensions.ReplicaSet - newRS *extensions.ReplicaSet - conditionType extensions.DeploymentConditionType + d *apps.Deployment + allRSs []*apps.ReplicaSet + newRS *apps.ReplicaSet + conditionType apps.DeploymentConditionType conditionStatus v1.ConditionStatus conditionReason string lastUpdate metav1.Time @@ -211,15 +211,15 @@ func TestSyncRolloutStatus(t *testing.T) { }{ { name: "General: remove Progressing condition and do not estimate progress if deployment has no Progress Deadline", - d: currentDeployment(nil, 3, 2, 2, 2, []extensions.DeploymentCondition{replicaSetUpdated}), - allRSs: []*extensions.ReplicaSet{newRSWithAvailable("bar", 0, 1, 1)}, + d: currentDeployment(nil, 3, 2, 2, 2, []apps.DeploymentCondition{replicaSetUpdated}), + allRSs: []*apps.ReplicaSet{newRSWithAvailable("bar", 0, 1, 1)}, newRS: newRSWithAvailable("foo", 3, 2, 2), }, { name: "General: do not estimate progress of deployment with only one active ReplicaSet", - d: currentDeployment(&pds, 3, 3, 3, 3, []extensions.DeploymentCondition{newRSAvailable}), - allRSs: []*extensions.ReplicaSet{newRSWithAvailable("bar", 3, 3, 3)}, - conditionType: extensions.DeploymentProgressing, + d: currentDeployment(&pds, 3, 3, 3, 3, []apps.DeploymentCondition{newRSAvailable}), + allRSs: []*apps.ReplicaSet{newRSWithAvailable("bar", 3, 3, 3)}, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionTrue, conditionReason: util.NewRSAvailableReason, lastUpdate: testTime, @@ -227,83 +227,83 @@ func TestSyncRolloutStatus(t *testing.T) { }, { name: "DeploymentProgressing: dont update lastTransitionTime if deployment already has Progressing=True", - d: currentDeployment(&pds, 3, 2, 2, 2, []extensions.DeploymentCondition{replicaSetUpdated}), - allRSs: []*extensions.ReplicaSet{newRSWithAvailable("bar", 0, 1, 1)}, + d: currentDeployment(&pds, 3, 2, 2, 2, []apps.DeploymentCondition{replicaSetUpdated}), + allRSs: []*apps.ReplicaSet{newRSWithAvailable("bar", 0, 1, 1)}, newRS: newRSWithAvailable("foo", 3, 2, 2), - conditionType: extensions.DeploymentProgressing, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionTrue, conditionReason: util.ReplicaSetUpdatedReason, lastTransition: testTime, }, { name: "DeploymentProgressing: update everything if deployment has Progressing=False", - d: currentDeployment(&pds, 3, 2, 2, 2, []extensions.DeploymentCondition{failedTimedOut}), - allRSs: []*extensions.ReplicaSet{newRSWithAvailable("bar", 0, 1, 1)}, + d: currentDeployment(&pds, 3, 2, 2, 2, []apps.DeploymentCondition{failedTimedOut}), + allRSs: []*apps.ReplicaSet{newRSWithAvailable("bar", 0, 1, 1)}, newRS: newRSWithAvailable("foo", 3, 2, 2), - conditionType: extensions.DeploymentProgressing, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionTrue, conditionReason: util.ReplicaSetUpdatedReason, }, { name: "DeploymentProgressing: create Progressing condition if it does not exist", - d: currentDeployment(&pds, 3, 2, 2, 2, []extensions.DeploymentCondition{}), - allRSs: []*extensions.ReplicaSet{newRSWithAvailable("bar", 0, 1, 1)}, + d: currentDeployment(&pds, 3, 2, 2, 2, []apps.DeploymentCondition{}), + allRSs: []*apps.ReplicaSet{newRSWithAvailable("bar", 0, 1, 1)}, newRS: newRSWithAvailable("foo", 3, 2, 2), - conditionType: extensions.DeploymentProgressing, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionTrue, conditionReason: util.ReplicaSetUpdatedReason, }, { name: "DeploymentComplete: dont update lastTransitionTime if deployment already has Progressing=True", - d: currentDeployment(&pds, 3, 3, 3, 3, []extensions.DeploymentCondition{replicaSetUpdated}), - allRSs: []*extensions.ReplicaSet{}, + d: currentDeployment(&pds, 3, 3, 3, 3, []apps.DeploymentCondition{replicaSetUpdated}), + allRSs: []*apps.ReplicaSet{}, newRS: newRSWithAvailable("foo", 3, 3, 3), - conditionType: extensions.DeploymentProgressing, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionTrue, conditionReason: util.NewRSAvailableReason, lastTransition: testTime, }, { name: "DeploymentComplete: update everything if deployment has Progressing=False", - d: currentDeployment(&pds, 3, 3, 3, 3, []extensions.DeploymentCondition{failedTimedOut}), - allRSs: []*extensions.ReplicaSet{}, + d: currentDeployment(&pds, 3, 3, 3, 3, []apps.DeploymentCondition{failedTimedOut}), + allRSs: []*apps.ReplicaSet{}, newRS: newRSWithAvailable("foo", 3, 3, 3), - conditionType: extensions.DeploymentProgressing, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionTrue, conditionReason: util.NewRSAvailableReason, }, { name: "DeploymentComplete: create Progressing condition if it does not exist", - d: currentDeployment(&pds, 3, 3, 3, 3, []extensions.DeploymentCondition{}), - allRSs: []*extensions.ReplicaSet{}, + d: currentDeployment(&pds, 3, 3, 3, 3, []apps.DeploymentCondition{}), + allRSs: []*apps.ReplicaSet{}, newRS: newRSWithAvailable("foo", 3, 3, 3), - conditionType: extensions.DeploymentProgressing, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionTrue, conditionReason: util.NewRSAvailableReason, }, { name: "DeploymentComplete: defend against NPE when newRS=nil", - d: currentDeployment(&pds, 0, 3, 3, 3, []extensions.DeploymentCondition{replicaSetUpdated}), - allRSs: []*extensions.ReplicaSet{newRSWithAvailable("foo", 0, 0, 0)}, - conditionType: extensions.DeploymentProgressing, + d: currentDeployment(&pds, 0, 3, 3, 3, []apps.DeploymentCondition{replicaSetUpdated}), + allRSs: []*apps.ReplicaSet{newRSWithAvailable("foo", 0, 0, 0)}, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionTrue, conditionReason: util.NewRSAvailableReason, }, { name: "DeploymentTimedOut: update status if rollout exceeds Progress Deadline", - d: currentDeployment(&pds, 3, 2, 2, 2, []extensions.DeploymentCondition{replicaSetUpdated}), - allRSs: []*extensions.ReplicaSet{}, + d: currentDeployment(&pds, 3, 2, 2, 2, []apps.DeploymentCondition{replicaSetUpdated}), + allRSs: []*apps.ReplicaSet{}, newRS: newRSWithAvailable("foo", 3, 2, 2), - conditionType: extensions.DeploymentProgressing, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionFalse, conditionReason: util.TimedOutReason, }, { name: "DeploymentTimedOut: do not update status if deployment has existing timedOut condition", - d: currentDeployment(&pds, 3, 2, 2, 2, []extensions.DeploymentCondition{failedTimedOut}), - allRSs: []*extensions.ReplicaSet{}, + d: currentDeployment(&pds, 3, 2, 2, 2, []apps.DeploymentCondition{failedTimedOut}), + allRSs: []*apps.ReplicaSet{}, newRS: newRSWithAvailable("foo", 3, 2, 2), - conditionType: extensions.DeploymentProgressing, + conditionType: apps.DeploymentProgressing, conditionStatus: v1.ConditionFalse, conditionReason: util.TimedOutReason, lastUpdate: testTime, diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/recreate.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/recreate.go index b6f01ef54..04403978d 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/recreate.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/recreate.go @@ -17,15 +17,15 @@ limitations under the License. package deployment import ( + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/deployment/util" ) // rolloutRecreate implements the logic for recreating a replica set. -func (dc *DeploymentController) rolloutRecreate(d *extensions.Deployment, rsList []*extensions.ReplicaSet, podMap map[types.UID]*v1.PodList) error { +func (dc *DeploymentController) rolloutRecreate(d *apps.Deployment, rsList []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList) error { // Don't create a new RS if not already existed, so that we avoid scaling up before scaling down. newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(d, rsList, podMap, false) if err != nil { @@ -74,7 +74,7 @@ func (dc *DeploymentController) rolloutRecreate(d *extensions.Deployment, rsList } // scaleDownOldReplicaSetsForRecreate scales down old replica sets when deployment strategy is "Recreate". -func (dc *DeploymentController) scaleDownOldReplicaSetsForRecreate(oldRSs []*extensions.ReplicaSet, deployment *extensions.Deployment) (bool, error) { +func (dc *DeploymentController) scaleDownOldReplicaSetsForRecreate(oldRSs []*apps.ReplicaSet, deployment *apps.Deployment) (bool, error) { scaled := false for i := range oldRSs { rs := oldRSs[i] @@ -95,7 +95,7 @@ func (dc *DeploymentController) scaleDownOldReplicaSetsForRecreate(oldRSs []*ext } // oldPodsRunning returns whether there are old pods running or any of the old ReplicaSets thinks that it runs pods. -func oldPodsRunning(newRS *extensions.ReplicaSet, oldRSs []*extensions.ReplicaSet, podMap map[types.UID]*v1.PodList) bool { +func oldPodsRunning(newRS *apps.ReplicaSet, oldRSs []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList) bool { if oldPods := util.GetActualReplicaCountForReplicaSets(oldRSs); oldPods > 0 { return true } @@ -123,7 +123,7 @@ func oldPodsRunning(newRS *extensions.ReplicaSet, oldRSs []*extensions.ReplicaSe } // scaleUpNewReplicaSetForRecreate scales up new replica set when deployment strategy is "Recreate". -func (dc *DeploymentController) scaleUpNewReplicaSetForRecreate(newRS *extensions.ReplicaSet, deployment *extensions.Deployment) (bool, error) { +func (dc *DeploymentController) scaleUpNewReplicaSetForRecreate(newRS *apps.ReplicaSet, deployment *apps.Deployment) (bool, error) { scaled, _, err := dc.scaleReplicaSetAndRecordEvent(newRS, *(deployment.Spec.Replicas), deployment) return scaled, err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/recreate_test.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/recreate_test.go index d81435c75..dc9d3b04a 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/recreate_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/recreate_test.go @@ -20,8 +20,8 @@ import ( "fmt" "testing" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/informers" @@ -33,7 +33,7 @@ import ( func TestScaleDownOldReplicaSets(t *testing.T) { tests := []struct { oldRSSizes []int - d *extensions.Deployment + d *apps.Deployment }{ { oldRSSizes: []int{3}, @@ -45,7 +45,7 @@ func TestScaleDownOldReplicaSets(t *testing.T) { t.Logf("running scenario %d", i) test := tests[i] - var oldRSs []*extensions.ReplicaSet + var oldRSs []*apps.ReplicaSet var expected []runtime.Object for n, size := range test.oldRSSizes { @@ -58,14 +58,14 @@ func TestScaleDownOldReplicaSets(t *testing.T) { rsCopy.Spec.Replicas = &zero expected = append(expected, rsCopy) - if *(oldRSs[n].Spec.Replicas) == *(expected[n].(*extensions.ReplicaSet).Spec.Replicas) { + if *(oldRSs[n].Spec.Replicas) == *(expected[n].(*apps.ReplicaSet).Spec.Replicas) { t.Errorf("broken test - original and expected RS have the same size") } } kc := fake.NewSimpleClientset(expected...) informers := informers.NewSharedInformerFactory(kc, controller.NoResyncPeriodFunc()) - c, err := NewDeploymentController(informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().ReplicaSets(), informers.Core().V1().Pods(), kc) + c, err := NewDeploymentController(informers.Apps().V1().Deployments(), informers.Apps().V1().ReplicaSets(), informers.Core().V1().Pods(), kc) if err != nil { t.Fatalf("error creating Deployment controller: %v", err) } @@ -86,8 +86,8 @@ func TestOldPodsRunning(t *testing.T) { tests := []struct { name string - newRS *extensions.ReplicaSet - oldRSs []*extensions.ReplicaSet + newRS *apps.ReplicaSet + oldRSs []*apps.ReplicaSet podMap map[types.UID]*v1.PodList hasOldPodsRunning bool @@ -98,23 +98,23 @@ func TestOldPodsRunning(t *testing.T) { }, { name: "old RSs with running pods", - oldRSs: []*extensions.ReplicaSet{rsWithUID("some-uid"), rsWithUID("other-uid")}, + oldRSs: []*apps.ReplicaSet{rsWithUID("some-uid"), rsWithUID("other-uid")}, podMap: podMapWithUIDs([]string{"some-uid", "other-uid"}), hasOldPodsRunning: true, }, { name: "old RSs without pods but with non-zero status replicas", - oldRSs: []*extensions.ReplicaSet{newRSWithStatus("rs-1", 0, 1, nil)}, + oldRSs: []*apps.ReplicaSet{newRSWithStatus("rs-1", 0, 1, nil)}, hasOldPodsRunning: true, }, { name: "old RSs without pods or non-zero status replicas", - oldRSs: []*extensions.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, + oldRSs: []*apps.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, hasOldPodsRunning: false, }, { name: "old RSs with zero status replicas but pods in terminal state are present", - oldRSs: []*extensions.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, + oldRSs: []*apps.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, podMap: map[types.UID]*v1.PodList{ "uid-1": { Items: []v1.Pod{ @@ -135,7 +135,7 @@ func TestOldPodsRunning(t *testing.T) { }, { name: "old RSs with zero status replicas but pod in unknown phase present", - oldRSs: []*extensions.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, + oldRSs: []*apps.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, podMap: map[types.UID]*v1.PodList{ "uid-1": { Items: []v1.Pod{ @@ -151,7 +151,7 @@ func TestOldPodsRunning(t *testing.T) { }, { name: "old RSs with zero status replicas with pending pod present", - oldRSs: []*extensions.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, + oldRSs: []*apps.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, podMap: map[types.UID]*v1.PodList{ "uid-1": { Items: []v1.Pod{ @@ -167,7 +167,7 @@ func TestOldPodsRunning(t *testing.T) { }, { name: "old RSs with zero status replicas with running pod present", - oldRSs: []*extensions.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, + oldRSs: []*apps.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, podMap: map[types.UID]*v1.PodList{ "uid-1": { Items: []v1.Pod{ @@ -183,7 +183,7 @@ func TestOldPodsRunning(t *testing.T) { }, { name: "old RSs with zero status replicas but pods in terminal state and pending are present", - oldRSs: []*extensions.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, + oldRSs: []*apps.ReplicaSet{newRSWithStatus("rs-1", 0, 0, nil)}, podMap: map[types.UID]*v1.PodList{ "uid-1": { Items: []v1.Pod{ @@ -225,7 +225,7 @@ func TestOldPodsRunning(t *testing.T) { } } -func rsWithUID(uid string) *extensions.ReplicaSet { +func rsWithUID(uid string) *apps.ReplicaSet { d := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) rs := newReplicaSet(d, fmt.Sprintf("foo-%s", uid), 0) rs.UID = types.UID(uid) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/rollback.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/rollback.go index 826185afc..97e3b3027 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/rollback.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/rollback.go @@ -18,9 +18,11 @@ package deployment import ( "fmt" + "strconv" "github.com/golang/glog" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/types" @@ -28,17 +30,17 @@ import ( ) // rollback the deployment to the specified revision. In any case cleanup the rollback spec. -func (dc *DeploymentController) rollback(d *extensions.Deployment, rsList []*extensions.ReplicaSet, podMap map[types.UID]*v1.PodList) error { +func (dc *DeploymentController) rollback(d *apps.Deployment, rsList []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList) error { newRS, allOldRSs, err := dc.getAllReplicaSetsAndSyncRevision(d, rsList, podMap, true) if err != nil { return err } allRSs := append(allOldRSs, newRS) - toRevision := &d.Spec.RollbackTo.Revision + rollbackTo := getRollbackTo(d) // If rollback revision is 0, rollback to the last revision - if *toRevision == 0 { - if *toRevision = deploymentutil.LastRevision(allRSs); *toRevision == 0 { + if rollbackTo.Revision == 0 { + if rollbackTo.Revision = deploymentutil.LastRevision(allRSs); rollbackTo.Revision == 0 { // If we still can't find the last revision, gives up rollback dc.emitRollbackWarningEvent(d, deploymentutil.RollbackRevisionNotFound, "Unable to find last revision.") // Gives up rollback @@ -51,14 +53,14 @@ func (dc *DeploymentController) rollback(d *extensions.Deployment, rsList []*ext glog.V(4).Infof("Unable to extract revision from deployment's replica set %q: %v", rs.Name, err) continue } - if v == *toRevision { + if v == rollbackTo.Revision { glog.V(4).Infof("Found replica set %q with desired revision %d", rs.Name, v) // rollback by copying podTemplate.Spec from the replica set // revision number will be incremented during the next getAllReplicaSetsAndSyncRevision call // no-op if the spec matches current deployment's podTemplate.Spec performedRollback, err := dc.rollbackToTemplate(d, rs) if performedRollback && err == nil { - dc.emitRollbackNormalEvent(d, fmt.Sprintf("Rolled back deployment %q to revision %d", d.Name, *toRevision)) + dc.emitRollbackNormalEvent(d, fmt.Sprintf("Rolled back deployment %q to revision %d", d.Name, rollbackTo.Revision)) } return err } @@ -71,7 +73,7 @@ func (dc *DeploymentController) rollback(d *extensions.Deployment, rsList []*ext // rollbackToTemplate compares the templates of the provided deployment and replica set and // updates the deployment with the replica set template in case they are different. It also // cleans up the rollback spec so subsequent requeues of the deployment won't end up in here. -func (dc *DeploymentController) rollbackToTemplate(d *extensions.Deployment, rs *extensions.ReplicaSet) (bool, error) { +func (dc *DeploymentController) rollbackToTemplate(d *apps.Deployment, rs *apps.ReplicaSet) (bool, error) { performedRollback := false if !deploymentutil.EqualIgnoreHash(&d.Spec.Template, &rs.Spec.Template) { glog.V(4).Infof("Rolling back deployment %q to template spec %+v", d.Name, rs.Spec.Template.Spec) @@ -98,20 +100,49 @@ func (dc *DeploymentController) rollbackToTemplate(d *extensions.Deployment, rs return performedRollback, dc.updateDeploymentAndClearRollbackTo(d) } -func (dc *DeploymentController) emitRollbackWarningEvent(d *extensions.Deployment, reason, message string) { +func (dc *DeploymentController) emitRollbackWarningEvent(d *apps.Deployment, reason, message string) { dc.eventRecorder.Eventf(d, v1.EventTypeWarning, reason, message) } -func (dc *DeploymentController) emitRollbackNormalEvent(d *extensions.Deployment, message string) { +func (dc *DeploymentController) emitRollbackNormalEvent(d *apps.Deployment, message string) { dc.eventRecorder.Eventf(d, v1.EventTypeNormal, deploymentutil.RollbackDone, message) } // updateDeploymentAndClearRollbackTo sets .spec.rollbackTo to nil and update the input deployment // It is assumed that the caller will have updated the deployment template appropriately (in case // we want to rollback). -func (dc *DeploymentController) updateDeploymentAndClearRollbackTo(d *extensions.Deployment) error { +func (dc *DeploymentController) updateDeploymentAndClearRollbackTo(d *apps.Deployment) error { glog.V(4).Infof("Cleans up rollbackTo of deployment %q", d.Name) - d.Spec.RollbackTo = nil - _, err := dc.client.ExtensionsV1beta1().Deployments(d.Namespace).Update(d) + setRollbackTo(d, nil) + _, err := dc.client.AppsV1().Deployments(d.Namespace).Update(d) return err } + +// TODO: Remove this when extensions/v1beta1 and apps/v1beta1 Deployment are dropped. +func getRollbackTo(d *apps.Deployment) *extensions.RollbackConfig { + // Extract the annotation used for round-tripping the deprecated RollbackTo field. + revision := d.Annotations[apps.DeprecatedRollbackTo] + if revision == "" { + return nil + } + revision64, err := strconv.ParseInt(revision, 10, 64) + if err != nil { + // If it's invalid, ignore it. + return nil + } + return &extensions.RollbackConfig{ + Revision: revision64, + } +} + +// TODO: Remove this when extensions/v1beta1 and apps/v1beta1 Deployment are dropped. +func setRollbackTo(d *apps.Deployment, rollbackTo *extensions.RollbackConfig) { + if rollbackTo == nil { + delete(d.Annotations, apps.DeprecatedRollbackTo) + return + } + if d.Annotations == nil { + d.Annotations = make(map[string]string) + } + d.Annotations[apps.DeprecatedRollbackTo] = strconv.FormatInt(rollbackTo.Revision, 10) +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/rolling.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/rolling.go index 598928366..132981fa3 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/rolling.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/rolling.go @@ -21,8 +21,8 @@ import ( "sort" "github.com/golang/glog" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/integer" "k8s.io/kubernetes/pkg/controller" @@ -30,7 +30,7 @@ import ( ) // rolloutRolling implements the logic for rolling a new replica set. -func (dc *DeploymentController) rolloutRolling(d *extensions.Deployment, rsList []*extensions.ReplicaSet, podMap map[types.UID]*v1.PodList) error { +func (dc *DeploymentController) rolloutRolling(d *apps.Deployment, rsList []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList) error { newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(d, rsList, podMap, true) if err != nil { return err @@ -67,7 +67,7 @@ func (dc *DeploymentController) rolloutRolling(d *extensions.Deployment, rsList return dc.syncRolloutStatus(allRSs, newRS, d) } -func (dc *DeploymentController) reconcileNewReplicaSet(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, deployment *extensions.Deployment) (bool, error) { +func (dc *DeploymentController) reconcileNewReplicaSet(allRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, deployment *apps.Deployment) (bool, error) { if *(newRS.Spec.Replicas) == *(deployment.Spec.Replicas) { // Scaling not required. return false, nil @@ -85,7 +85,7 @@ func (dc *DeploymentController) reconcileNewReplicaSet(allRSs []*extensions.Repl return scaled, err } -func (dc *DeploymentController) reconcileOldReplicaSets(allRSs []*extensions.ReplicaSet, oldRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, deployment *extensions.Deployment) (bool, error) { +func (dc *DeploymentController) reconcileOldReplicaSets(allRSs []*apps.ReplicaSet, oldRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, deployment *apps.Deployment) (bool, error) { oldPodsCount := deploymentutil.GetReplicaCountForReplicaSets(oldRSs) if oldPodsCount == 0 { // Can't scale down further @@ -154,7 +154,7 @@ func (dc *DeploymentController) reconcileOldReplicaSets(allRSs []*extensions.Rep } // cleanupUnhealthyReplicas will scale down old replica sets with unhealthy replicas, so that all unhealthy replicas will be deleted. -func (dc *DeploymentController) cleanupUnhealthyReplicas(oldRSs []*extensions.ReplicaSet, deployment *extensions.Deployment, maxCleanupCount int32) ([]*extensions.ReplicaSet, int32, error) { +func (dc *DeploymentController) cleanupUnhealthyReplicas(oldRSs []*apps.ReplicaSet, deployment *apps.Deployment, maxCleanupCount int32) ([]*apps.ReplicaSet, int32, error) { sort.Sort(controller.ReplicaSetsByCreationTimestamp(oldRSs)) // Safely scale down all old replica sets with unhealthy replicas. Replica set will sort the pods in the order // such that not-ready < ready, unscheduled < scheduled, and pending < running. This ensures that unhealthy replicas will @@ -191,7 +191,7 @@ func (dc *DeploymentController) cleanupUnhealthyReplicas(oldRSs []*extensions.Re // scaleDownOldReplicaSetsForRollingUpdate scales down old replica sets when deployment strategy is "RollingUpdate". // Need check maxUnavailable to ensure availability -func (dc *DeploymentController) scaleDownOldReplicaSetsForRollingUpdate(allRSs []*extensions.ReplicaSet, oldRSs []*extensions.ReplicaSet, deployment *extensions.Deployment) (int32, error) { +func (dc *DeploymentController) scaleDownOldReplicaSetsForRollingUpdate(allRSs []*apps.ReplicaSet, oldRSs []*apps.ReplicaSet, deployment *apps.Deployment) (int32, error) { maxUnavailable := deploymentutil.MaxUnavailable(*deployment) // Check if we can scale down. diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/rolling_test.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/rolling_test.go index 5f870e40b..b0feb42b4 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/rolling_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/rolling_test.go @@ -19,7 +19,7 @@ package deployment import ( "testing" - extensions "k8s.io/api/extensions/v1beta1" + apps "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" @@ -82,7 +82,7 @@ func TestDeploymentController_reconcileNewReplicaSet(t *testing.T) { t.Logf("executing scenario %d", i) newRS := rs("foo-v2", test.newReplicas, nil, noTimestamp) oldRS := rs("foo-v2", test.oldReplicas, nil, noTimestamp) - allRSs := []*extensions.ReplicaSet{newRS, oldRS} + allRSs := []*apps.ReplicaSet{newRS, oldRS} maxUnavailable := intstr.FromInt(0) deployment := newDeployment("foo", test.deploymentReplicas, nil, &test.maxSurge, &maxUnavailable, map[string]string{"foo": "bar"}) fake := fake.Clientset{} @@ -109,7 +109,7 @@ func TestDeploymentController_reconcileNewReplicaSet(t *testing.T) { t.Errorf("expected 1 action during scale, got: %v", fake.Actions()) continue } - updated := fake.Actions()[0].(core.UpdateAction).GetObject().(*extensions.ReplicaSet) + updated := fake.Actions()[0].(core.UpdateAction).GetObject().(*apps.ReplicaSet) if e, a := test.expectedNewReplicas, int(*(updated.Spec.Replicas)); e != a { t.Errorf("expected update to %d replicas, got %d", e, a) } @@ -187,8 +187,8 @@ func TestDeploymentController_reconcileOldReplicaSets(t *testing.T) { newRS.Status.AvailableReplicas = int32(test.readyPodsFromNewRS) oldRS := rs("foo-old", test.oldReplicas, oldSelector, noTimestamp) oldRS.Status.AvailableReplicas = int32(test.readyPodsFromOldRS) - oldRSs := []*extensions.ReplicaSet{oldRS} - allRSs := []*extensions.ReplicaSet{oldRS, newRS} + oldRSs := []*apps.ReplicaSet{oldRS} + allRSs := []*apps.ReplicaSet{oldRS, newRS} maxSurge := intstr.FromInt(0) deployment := newDeployment("foo", test.deploymentReplicas, nil, &maxSurge, &test.maxUnavailable, newSelector) fakeClientset := fake.Clientset{} @@ -255,7 +255,7 @@ func TestDeploymentController_cleanupUnhealthyReplicas(t *testing.T) { t.Logf("executing scenario %d", i) oldRS := rs("foo-v2", test.oldReplicas, nil, noTimestamp) oldRS.Status.AvailableReplicas = int32(test.readyPods) - oldRSs := []*extensions.ReplicaSet{oldRS} + oldRSs := []*apps.ReplicaSet{oldRS} maxSurge := intstr.FromInt(2) maxUnavailable := intstr.FromInt(2) deployment := newDeployment("foo", 10, nil, &maxSurge, &maxUnavailable, nil) @@ -330,8 +330,8 @@ func TestDeploymentController_scaleDownOldReplicaSetsForRollingUpdate(t *testing t.Logf("executing scenario %d", i) oldRS := rs("foo-v2", test.oldReplicas, nil, noTimestamp) oldRS.Status.AvailableReplicas = int32(test.readyPods) - allRSs := []*extensions.ReplicaSet{oldRS} - oldRSs := []*extensions.ReplicaSet{oldRS} + allRSs := []*apps.ReplicaSet{oldRS} + oldRSs := []*apps.ReplicaSet{oldRS} maxSurge := intstr.FromInt(0) deployment := newDeployment("foo", test.deploymentReplicas, nil, &maxSurge, &test.maxUnavailable, map[string]string{"foo": "bar"}) fakeClientset := fake.Clientset{} @@ -371,7 +371,7 @@ func TestDeploymentController_scaleDownOldReplicaSetsForRollingUpdate(t *testing t.Errorf("expected an update action") continue } - updated := updateAction.GetObject().(*extensions.ReplicaSet) + updated := updateAction.GetObject().(*apps.ReplicaSet) if e, a := test.expectedOldReplicas, int(*(updated.Spec.Replicas)); e != a { t.Errorf("expected update to %d replicas, got %d", e, a) } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/sync.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/sync.go index cfd147b50..9ddb6d453 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/sync.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/sync.go @@ -23,12 +23,11 @@ import ( "strconv" "github.com/golang/glog" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/kubernetes/pkg/controller" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" @@ -36,7 +35,7 @@ import ( ) // syncStatusOnly only updates Deployments Status and doesn't take any mutating actions. -func (dc *DeploymentController) syncStatusOnly(d *extensions.Deployment, rsList []*extensions.ReplicaSet, podMap map[types.UID]*v1.PodList) error { +func (dc *DeploymentController) syncStatusOnly(d *apps.Deployment, rsList []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList) error { newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(d, rsList, podMap, false) if err != nil { return err @@ -48,7 +47,7 @@ func (dc *DeploymentController) syncStatusOnly(d *extensions.Deployment, rsList // sync is responsible for reconciling deployments on scaling events or when they // are paused. -func (dc *DeploymentController) sync(d *extensions.Deployment, rsList []*extensions.ReplicaSet, podMap map[types.UID]*v1.PodList) error { +func (dc *DeploymentController) sync(d *apps.Deployment, rsList []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList) error { newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(d, rsList, podMap, false) if err != nil { return err @@ -60,7 +59,7 @@ func (dc *DeploymentController) sync(d *extensions.Deployment, rsList []*extensi } // Clean up the deployment when it's paused and no rollback is in flight. - if d.Spec.Paused && d.Spec.RollbackTo == nil { + if d.Spec.Paused && getRollbackTo(d) == nil { if err := dc.cleanupDeployment(oldRSs, d); err != nil { return err } @@ -73,11 +72,11 @@ func (dc *DeploymentController) sync(d *extensions.Deployment, rsList []*extensi // checkPausedConditions checks if the given deployment is paused or not and adds an appropriate condition. // These conditions are needed so that we won't accidentally report lack of progress for resumed deployments // that were paused for longer than progressDeadlineSeconds. -func (dc *DeploymentController) checkPausedConditions(d *extensions.Deployment) error { +func (dc *DeploymentController) checkPausedConditions(d *apps.Deployment) error { if d.Spec.ProgressDeadlineSeconds == nil { return nil } - cond := deploymentutil.GetDeploymentCondition(d.Status, extensions.DeploymentProgressing) + cond := deploymentutil.GetDeploymentCondition(d.Status, apps.DeploymentProgressing) if cond != nil && cond.Reason == deploymentutil.TimedOutReason { // If we have reported lack of progress, do not overwrite it with a paused condition. return nil @@ -86,11 +85,11 @@ func (dc *DeploymentController) checkPausedConditions(d *extensions.Deployment) needsUpdate := false if d.Spec.Paused && !pausedCondExists { - condition := deploymentutil.NewDeploymentCondition(extensions.DeploymentProgressing, v1.ConditionUnknown, deploymentutil.PausedDeployReason, "Deployment is paused") + condition := deploymentutil.NewDeploymentCondition(apps.DeploymentProgressing, v1.ConditionUnknown, deploymentutil.PausedDeployReason, "Deployment is paused") deploymentutil.SetDeploymentCondition(&d.Status, *condition) needsUpdate = true } else if !d.Spec.Paused && pausedCondExists { - condition := deploymentutil.NewDeploymentCondition(extensions.DeploymentProgressing, v1.ConditionUnknown, deploymentutil.ResumedDeployReason, "Deployment is resumed") + condition := deploymentutil.NewDeploymentCondition(apps.DeploymentProgressing, v1.ConditionUnknown, deploymentutil.ResumedDeployReason, "Deployment is resumed") deploymentutil.SetDeploymentCondition(&d.Status, *condition) needsUpdate = true } @@ -100,7 +99,7 @@ func (dc *DeploymentController) checkPausedConditions(d *extensions.Deployment) } var err error - d, err = dc.client.ExtensionsV1beta1().Deployments(d.Namespace).UpdateStatus(d) + d, err = dc.client.AppsV1().Deployments(d.Namespace).UpdateStatus(d) return err } @@ -116,12 +115,7 @@ func (dc *DeploymentController) checkPausedConditions(d *extensions.Deployment) // // Note that currently the deployment controller is using caches to avoid querying the server for reads. // This may lead to stale reads of replica sets, thus incorrect deployment status. -func (dc *DeploymentController) getAllReplicaSetsAndSyncRevision(d *extensions.Deployment, rsList []*extensions.ReplicaSet, podMap map[types.UID]*v1.PodList, createIfNotExisted bool) (*extensions.ReplicaSet, []*extensions.ReplicaSet, error) { - // List the deployment's RSes & Pods and apply pod-template-hash info to deployment's adopted RSes/Pods - rsList, err := dc.rsAndPodsWithHashKeySynced(d, rsList, podMap) - if err != nil { - return nil, nil, fmt.Errorf("error labeling replica sets and pods with pod-template-hash: %v", err) - } +func (dc *DeploymentController) getAllReplicaSetsAndSyncRevision(d *apps.Deployment, rsList []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList, createIfNotExisted bool) (*apps.ReplicaSet, []*apps.ReplicaSet, error) { _, allOldRSs := deploymentutil.FindOldReplicaSets(d, rsList) // Get new replica set with the updated revision number @@ -133,105 +127,12 @@ func (dc *DeploymentController) getAllReplicaSetsAndSyncRevision(d *extensions.D return newRS, allOldRSs, nil } -// rsAndPodsWithHashKeySynced returns the RSes and pods the given deployment -// targets, with pod-template-hash information synced. -// -// rsList should come from getReplicaSetsForDeployment(d). -// podMap should come from getPodMapForDeployment(d, rsList). -func (dc *DeploymentController) rsAndPodsWithHashKeySynced(d *extensions.Deployment, rsList []*extensions.ReplicaSet, podMap map[types.UID]*v1.PodList) ([]*extensions.ReplicaSet, error) { - var syncedRSList []*extensions.ReplicaSet - for _, rs := range rsList { - // Add pod-template-hash information if it's not in the RS. - // Otherwise, new RS produced by Deployment will overlap with pre-existing ones - // that aren't constrained by the pod-template-hash. - syncedRS, err := dc.addHashKeyToRSAndPods(rs, podMap[rs.UID], d.Status.CollisionCount) - if err != nil { - return nil, err - } - syncedRSList = append(syncedRSList, syncedRS) - } - return syncedRSList, nil -} - -// addHashKeyToRSAndPods adds pod-template-hash information to the given rs, if it's not already there, with the following steps: -// 1. Add hash label to the rs's pod template, and make sure the controller sees this update so that no orphaned pods will be created -// 2. Add hash label to all pods this rs owns, wait until replicaset controller reports rs.Status.FullyLabeledReplicas equal to the desired number of replicas -// 3. Add hash label to the rs's label and selector -func (dc *DeploymentController) addHashKeyToRSAndPods(rs *extensions.ReplicaSet, podList *v1.PodList, collisionCount *int32) (*extensions.ReplicaSet, error) { - // If the rs already has the new hash label in its selector, it's done syncing - if labelsutil.SelectorHasLabel(rs.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey) { - return rs, nil - } - hash, err := deploymentutil.GetReplicaSetHash(rs, collisionCount) - if err != nil { - return nil, err - } - // 1. Add hash template label to the rs. This ensures that any newly created pods will have the new label. - updatedRS, err := deploymentutil.UpdateRSWithRetries(dc.client.ExtensionsV1beta1().ReplicaSets(rs.Namespace), dc.rsLister, rs.Namespace, rs.Name, - func(updated *extensions.ReplicaSet) error { - // Precondition: the RS doesn't contain the new hash in its pod template label. - if updated.Spec.Template.Labels[extensions.DefaultDeploymentUniqueLabelKey] == hash { - return utilerrors.ErrPreconditionViolated - } - updated.Spec.Template.Labels = labelsutil.AddLabel(updated.Spec.Template.Labels, extensions.DefaultDeploymentUniqueLabelKey, hash) - return nil - }) - if err != nil { - return nil, fmt.Errorf("error updating replica set %s/%s pod template label with template hash: %v", rs.Namespace, rs.Name, err) - } - // Make sure rs pod template is updated so that it won't create pods without the new label (orphaned pods). - if updatedRS.Generation > updatedRS.Status.ObservedGeneration { - // TODO: Revisit if we really need to wait here as opposed to returning and - // potentially unblocking this worker (can wait up to 1min before timing out). - if err = deploymentutil.WaitForReplicaSetUpdated(dc.rsLister, updatedRS.Generation, updatedRS.Namespace, updatedRS.Name); err != nil { - return nil, fmt.Errorf("error waiting for replica set %s/%s to be observed by controller: %v", updatedRS.Namespace, updatedRS.Name, err) - } - glog.V(4).Infof("Observed the update of replica set %s/%s's pod template with hash %s.", rs.Namespace, rs.Name, hash) - } - - // 2. Update all pods managed by the rs to have the new hash label, so they will be correctly adopted. - if err := deploymentutil.LabelPodsWithHash(podList, dc.client, dc.podLister, rs.Namespace, rs.Name, hash); err != nil { - return nil, fmt.Errorf("error in adding template hash label %s to pods %+v: %s", hash, podList, err) - } - - // We need to wait for the replicaset controller to observe the pods being - // labeled with pod template hash. Because previously we've called - // WaitForReplicaSetUpdated, the replicaset controller should have dropped - // FullyLabeledReplicas to 0 already, we only need to wait it to increase - // back to the number of replicas in the spec. - // TODO: Revisit if we really need to wait here as opposed to returning and - // potentially unblocking this worker (can wait up to 1min before timing out). - if err := deploymentutil.WaitForPodsHashPopulated(dc.rsLister, updatedRS.Generation, updatedRS.Namespace, updatedRS.Name); err != nil { - return nil, fmt.Errorf("Replica set %s/%s: error waiting for replicaset controller to observe pods being labeled with template hash: %v", updatedRS.Namespace, updatedRS.Name, err) - } - - // 3. Update rs label and selector to include the new hash label - // Copy the old selector, so that we can scrub out any orphaned pods - updatedRS, err = deploymentutil.UpdateRSWithRetries(dc.client.ExtensionsV1beta1().ReplicaSets(rs.Namespace), dc.rsLister, rs.Namespace, rs.Name, func(updated *extensions.ReplicaSet) error { - // Precondition: the RS doesn't contain the new hash in its label and selector. - if updated.Labels[extensions.DefaultDeploymentUniqueLabelKey] == hash && updated.Spec.Selector.MatchLabels[extensions.DefaultDeploymentUniqueLabelKey] == hash { - return utilerrors.ErrPreconditionViolated - } - updated.Labels = labelsutil.AddLabel(updated.Labels, extensions.DefaultDeploymentUniqueLabelKey, hash) - updated.Spec.Selector = labelsutil.AddLabelToSelector(updated.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey, hash) - return nil - }) - // If the RS isn't actually updated, that's okay, we'll retry in the - // next sync loop since its selector isn't updated yet. - if err != nil { - return nil, fmt.Errorf("error updating ReplicaSet %s/%s label and selector with template hash: %v", updatedRS.Namespace, updatedRS.Name, err) - } - - // TODO: look for orphaned pods and label them in the background somewhere else periodically - return updatedRS, nil -} - // Returns a replica set that matches the intent of the given deployment. Returns nil if the new replica set doesn't exist yet. // 1. Get existing new RS (the RS that the given deployment targets, whose pod template is the same as deployment's). // 2. If there's existing new RS, update its revision number if it's smaller than (maxOldRevision + 1), where maxOldRevision is the max revision number among all old RSes. // 3. If there's no existing new RS and createIfNotExisted is true, create one with appropriate revision number (maxOldRevision + 1) and replicas. // Note that the pod-template-hash will be added to adopted RSes and pods. -func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsList, oldRSs []*extensions.ReplicaSet, createIfNotExisted bool) (*extensions.ReplicaSet, error) { +func (dc *DeploymentController) getNewReplicaSet(d *apps.Deployment, rsList, oldRSs []*apps.ReplicaSet, createIfNotExisted bool) (*apps.ReplicaSet, error) { existingNewRS := deploymentutil.FindNewReplicaSet(d, rsList) // Calculate the max revision number among all old RSes @@ -251,7 +152,7 @@ func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsLis minReadySecondsNeedsUpdate := rsCopy.Spec.MinReadySeconds != d.Spec.MinReadySeconds if annotationsUpdated || minReadySecondsNeedsUpdate { rsCopy.Spec.MinReadySeconds = d.Spec.MinReadySeconds - return dc.client.ExtensionsV1beta1().ReplicaSets(rsCopy.ObjectMeta.Namespace).Update(rsCopy) + return dc.client.AppsV1().ReplicaSets(rsCopy.ObjectMeta.Namespace).Update(rsCopy) } // Should use the revision in existingNewRS's annotation, since it set by before @@ -259,17 +160,17 @@ func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsLis // If no other Progressing condition has been recorded and we need to estimate the progress // of this deployment then it is likely that old users started caring about progress. In that // case we need to take into account the first time we noticed their new replica set. - cond := deploymentutil.GetDeploymentCondition(d.Status, extensions.DeploymentProgressing) + cond := deploymentutil.GetDeploymentCondition(d.Status, apps.DeploymentProgressing) if d.Spec.ProgressDeadlineSeconds != nil && cond == nil { msg := fmt.Sprintf("Found new replica set %q", rsCopy.Name) - condition := deploymentutil.NewDeploymentCondition(extensions.DeploymentProgressing, v1.ConditionTrue, deploymentutil.FoundNewRSReason, msg) + condition := deploymentutil.NewDeploymentCondition(apps.DeploymentProgressing, v1.ConditionTrue, deploymentutil.FoundNewRSReason, msg) deploymentutil.SetDeploymentCondition(&d.Status, *condition) needsUpdate = true } if needsUpdate { var err error - if d, err = dc.client.ExtensionsV1beta1().Deployments(d.Namespace).UpdateStatus(d); err != nil { + if d, err = dc.client.AppsV1().Deployments(d.Namespace).UpdateStatus(d); err != nil { return nil, err } } @@ -283,19 +184,20 @@ func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsLis // new ReplicaSet does not exist, create one. newRSTemplate := *d.Spec.Template.DeepCopy() podTemplateSpecHash := fmt.Sprintf("%d", controller.ComputeHash(&newRSTemplate, d.Status.CollisionCount)) - newRSTemplate.Labels = labelsutil.CloneAndAddLabel(d.Spec.Template.Labels, extensions.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash) + newRSTemplate.Labels = labelsutil.CloneAndAddLabel(d.Spec.Template.Labels, apps.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash) // Add podTemplateHash label to selector. - newRSSelector := labelsutil.CloneSelectorAndAddLabel(d.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash) + newRSSelector := labelsutil.CloneSelectorAndAddLabel(d.Spec.Selector, apps.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash) // Create new ReplicaSet - newRS := extensions.ReplicaSet{ + newRS := apps.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ // Make the name deterministic, to ensure idempotence Name: d.Name + "-" + rand.SafeEncodeString(podTemplateSpecHash), Namespace: d.Namespace, OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(d, controllerKind)}, + Labels: newRSTemplate.Labels, }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: new(int32), MinReadySeconds: d.Spec.MinReadySeconds, Selector: newRSSelector, @@ -315,7 +217,7 @@ func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsLis // hash collisions. If there is any other error, we need to report it in the status of // the Deployment. alreadyExists := false - createdRS, err := dc.client.ExtensionsV1beta1().ReplicaSets(d.Namespace).Create(&newRS) + createdRS, err := dc.client.AppsV1().ReplicaSets(d.Namespace).Create(&newRS) switch { // We may end up hitting this due to a slow cache or a fast resync of the Deployment. case errors.IsAlreadyExists(err): @@ -347,7 +249,7 @@ func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsLis *d.Status.CollisionCount++ // Update the collisionCount for the Deployment and let it requeue by returning the original // error. - _, dErr := dc.client.ExtensionsV1beta1().Deployments(d.Namespace).UpdateStatus(d) + _, dErr := dc.client.AppsV1().Deployments(d.Namespace).UpdateStatus(d) if dErr == nil { glog.V(2).Infof("Found a hash collision for deployment %q - bumping collisionCount (%d->%d) to resolve it", d.Name, preCollisionCount, *d.Status.CollisionCount) } @@ -355,12 +257,12 @@ func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsLis case err != nil: msg := fmt.Sprintf("Failed to create new replica set %q: %v", newRS.Name, err) if d.Spec.ProgressDeadlineSeconds != nil { - cond := deploymentutil.NewDeploymentCondition(extensions.DeploymentProgressing, v1.ConditionFalse, deploymentutil.FailedRSCreateReason, msg) + cond := deploymentutil.NewDeploymentCondition(apps.DeploymentProgressing, v1.ConditionFalse, deploymentutil.FailedRSCreateReason, msg) deploymentutil.SetDeploymentCondition(&d.Status, *cond) // We don't really care about this error at this point, since we have a bigger issue to report. // TODO: Identify which errors are permanent and switch DeploymentIsFailed to take into account // these reasons as well. Related issue: https://github.com/kubernetes/kubernetes/issues/18568 - _, _ = dc.client.ExtensionsV1beta1().Deployments(d.Namespace).UpdateStatus(d) + _, _ = dc.client.AppsV1().Deployments(d.Namespace).UpdateStatus(d) } dc.eventRecorder.Eventf(d, v1.EventTypeWarning, deploymentutil.FailedRSCreateReason, msg) return nil, err @@ -372,12 +274,12 @@ func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsLis needsUpdate := deploymentutil.SetDeploymentRevision(d, newRevision) if !alreadyExists && d.Spec.ProgressDeadlineSeconds != nil { msg := fmt.Sprintf("Created new replica set %q", createdRS.Name) - condition := deploymentutil.NewDeploymentCondition(extensions.DeploymentProgressing, v1.ConditionTrue, deploymentutil.NewReplicaSetReason, msg) + condition := deploymentutil.NewDeploymentCondition(apps.DeploymentProgressing, v1.ConditionTrue, deploymentutil.NewReplicaSetReason, msg) deploymentutil.SetDeploymentCondition(&d.Status, *condition) needsUpdate = true } if needsUpdate { - _, err = dc.client.ExtensionsV1beta1().Deployments(d.Namespace).UpdateStatus(d) + _, err = dc.client.AppsV1().Deployments(d.Namespace).UpdateStatus(d) } return createdRS, err } @@ -387,7 +289,7 @@ func (dc *DeploymentController) getNewReplicaSet(d *extensions.Deployment, rsLis // have the effect of hastening the rollout progress, which could produce a higher proportion of unavailable // replicas in the event of a problem with the rolled out template. Should run only on scaling events or // when a deployment is paused and not during the normal rollout process. -func (dc *DeploymentController) scale(deployment *extensions.Deployment, newRS *extensions.ReplicaSet, oldRSs []*extensions.ReplicaSet) error { +func (dc *DeploymentController) scale(deployment *apps.Deployment, newRS *apps.ReplicaSet, oldRSs []*apps.ReplicaSet) error { // If there is only one active replica set then we should scale that up to the full count of the // deployment. If there is no active replica set, then we should scale up the newest replica set. if activeOrLatest := deploymentutil.FindActiveOrLatest(newRS, oldRSs); activeOrLatest != nil { @@ -485,7 +387,7 @@ func (dc *DeploymentController) scale(deployment *extensions.Deployment, newRS * return nil } -func (dc *DeploymentController) scaleReplicaSetAndRecordEvent(rs *extensions.ReplicaSet, newScale int32, deployment *extensions.Deployment) (bool, *extensions.ReplicaSet, error) { +func (dc *DeploymentController) scaleReplicaSetAndRecordEvent(rs *apps.ReplicaSet, newScale int32, deployment *apps.Deployment) (bool, *apps.ReplicaSet, error) { // No need to scale if *(rs.Spec.Replicas) == newScale { return false, rs, nil @@ -500,20 +402,19 @@ func (dc *DeploymentController) scaleReplicaSetAndRecordEvent(rs *extensions.Rep return scaled, newRS, err } -func (dc *DeploymentController) scaleReplicaSet(rs *extensions.ReplicaSet, newScale int32, deployment *extensions.Deployment, scalingOperation string) (bool, *extensions.ReplicaSet, error) { - rsCopy := rs.DeepCopy() +func (dc *DeploymentController) scaleReplicaSet(rs *apps.ReplicaSet, newScale int32, deployment *apps.Deployment, scalingOperation string) (bool, *apps.ReplicaSet, error) { + + sizeNeedsUpdate := *(rs.Spec.Replicas) != newScale - sizeNeedsUpdate := *(rsCopy.Spec.Replicas) != newScale - // TODO: Do not mutate the replica set here, instead simply compare the annotation and if they mismatch - // call SetReplicasAnnotations inside the following if clause. Then we can also move the deep-copy from - // above inside the if too. - annotationsNeedUpdate := deploymentutil.SetReplicasAnnotations(rsCopy, *(deployment.Spec.Replicas), *(deployment.Spec.Replicas)+deploymentutil.MaxSurge(*deployment)) + annotationsNeedUpdate := deploymentutil.ReplicasAnnotationsNeedUpdate(rs, *(deployment.Spec.Replicas), *(deployment.Spec.Replicas)+deploymentutil.MaxSurge(*deployment)) scaled := false var err error if sizeNeedsUpdate || annotationsNeedUpdate { + rsCopy := rs.DeepCopy() *(rsCopy.Spec.Replicas) = newScale - rs, err = dc.client.ExtensionsV1beta1().ReplicaSets(rsCopy.Namespace).Update(rsCopy) + deploymentutil.SetReplicasAnnotations(rsCopy, *(deployment.Spec.Replicas), *(deployment.Spec.Replicas)+deploymentutil.MaxSurge(*deployment)) + rs, err = dc.client.AppsV1().ReplicaSets(rsCopy.Namespace).Update(rsCopy) if err == nil && sizeNeedsUpdate { scaled = true dc.eventRecorder.Eventf(deployment, v1.EventTypeNormal, "ScalingReplicaSet", "Scaled %s replica set %s to %d", scalingOperation, rs.Name, newScale) @@ -525,13 +426,13 @@ func (dc *DeploymentController) scaleReplicaSet(rs *extensions.ReplicaSet, newSc // cleanupDeployment is responsible for cleaning up a deployment ie. retains all but the latest N old replica sets // where N=d.Spec.RevisionHistoryLimit. Old replica sets are older versions of the podtemplate of a deployment kept // around by default 1) for historical reasons and 2) for the ability to rollback a deployment. -func (dc *DeploymentController) cleanupDeployment(oldRSs []*extensions.ReplicaSet, deployment *extensions.Deployment) error { +func (dc *DeploymentController) cleanupDeployment(oldRSs []*apps.ReplicaSet, deployment *apps.Deployment) error { if deployment.Spec.RevisionHistoryLimit == nil { return nil } // Avoid deleting replica set with deletion timestamp set - aliveFilter := func(rs *extensions.ReplicaSet) bool { + aliveFilter := func(rs *apps.ReplicaSet) bool { return rs != nil && rs.ObjectMeta.DeletionTimestamp == nil } cleanableRSes := controller.FilterReplicaSets(oldRSs, aliveFilter) @@ -551,7 +452,7 @@ func (dc *DeploymentController) cleanupDeployment(oldRSs []*extensions.ReplicaSe continue } glog.V(4).Infof("Trying to cleanup replica set %q for deployment %q", rs.Name, deployment.Name) - if err := dc.client.ExtensionsV1beta1().ReplicaSets(rs.Namespace).Delete(rs.Name, nil); err != nil && !errors.IsNotFound(err) { + if err := dc.client.AppsV1().ReplicaSets(rs.Namespace).Delete(rs.Name, nil); err != nil && !errors.IsNotFound(err) { // Return error instead of aggregating and continuing DELETEs on the theory // that we may be overloading the api server. return err @@ -562,7 +463,7 @@ func (dc *DeploymentController) cleanupDeployment(oldRSs []*extensions.ReplicaSe } // syncDeploymentStatus checks if the status is up-to-date and sync it if necessary -func (dc *DeploymentController) syncDeploymentStatus(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, d *extensions.Deployment) error { +func (dc *DeploymentController) syncDeploymentStatus(allRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, d *apps.Deployment) error { newStatus := calculateStatus(allRSs, newRS, d) if reflect.DeepEqual(d.Status, newStatus) { @@ -571,12 +472,12 @@ func (dc *DeploymentController) syncDeploymentStatus(allRSs []*extensions.Replic newDeployment := d newDeployment.Status = newStatus - _, err := dc.client.ExtensionsV1beta1().Deployments(newDeployment.Namespace).UpdateStatus(newDeployment) + _, err := dc.client.AppsV1().Deployments(newDeployment.Namespace).UpdateStatus(newDeployment) return err } // calculateStatus calculates the latest status for the provided deployment by looking into the provided replica sets. -func calculateStatus(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, deployment *extensions.Deployment) extensions.DeploymentStatus { +func calculateStatus(allRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, deployment *apps.Deployment) apps.DeploymentStatus { availableReplicas := deploymentutil.GetAvailableReplicaCountForReplicaSets(allRSs) totalReplicas := deploymentutil.GetReplicaCountForReplicaSets(allRSs) unavailableReplicas := totalReplicas - availableReplicas @@ -586,11 +487,11 @@ func calculateStatus(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaS unavailableReplicas = 0 } - status := extensions.DeploymentStatus{ + status := apps.DeploymentStatus{ // TODO: Ensure that if we start retrying status updates, we won't pick up a new Generation value. ObservedGeneration: deployment.Generation, Replicas: deploymentutil.GetActualReplicaCountForReplicaSets(allRSs), - UpdatedReplicas: deploymentutil.GetActualReplicaCountForReplicaSets([]*extensions.ReplicaSet{newRS}), + UpdatedReplicas: deploymentutil.GetActualReplicaCountForReplicaSets([]*apps.ReplicaSet{newRS}), ReadyReplicas: deploymentutil.GetReadyReplicaCountForReplicaSets(allRSs), AvailableReplicas: availableReplicas, UnavailableReplicas: unavailableReplicas, @@ -604,10 +505,10 @@ func calculateStatus(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaS } if availableReplicas >= *(deployment.Spec.Replicas)-deploymentutil.MaxUnavailable(*deployment) { - minAvailability := deploymentutil.NewDeploymentCondition(extensions.DeploymentAvailable, v1.ConditionTrue, deploymentutil.MinimumReplicasAvailable, "Deployment has minimum availability.") + minAvailability := deploymentutil.NewDeploymentCondition(apps.DeploymentAvailable, v1.ConditionTrue, deploymentutil.MinimumReplicasAvailable, "Deployment has minimum availability.") deploymentutil.SetDeploymentCondition(&status, *minAvailability) } else { - noMinAvailability := deploymentutil.NewDeploymentCondition(extensions.DeploymentAvailable, v1.ConditionFalse, deploymentutil.MinimumReplicasUnavailable, "Deployment does not have minimum availability.") + noMinAvailability := deploymentutil.NewDeploymentCondition(apps.DeploymentAvailable, v1.ConditionFalse, deploymentutil.MinimumReplicasUnavailable, "Deployment does not have minimum availability.") deploymentutil.SetDeploymentCondition(&status, *noMinAvailability) } @@ -619,7 +520,7 @@ func calculateStatus(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaS // // rsList should come from getReplicaSetsForDeployment(d). // podMap should come from getPodMapForDeployment(d, rsList). -func (dc *DeploymentController) isScalingEvent(d *extensions.Deployment, rsList []*extensions.ReplicaSet, podMap map[types.UID]*v1.PodList) (bool, error) { +func (dc *DeploymentController) isScalingEvent(d *apps.Deployment, rsList []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList) (bool, error) { newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(d, rsList, podMap, false) if err != nil { return false, err diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/sync_test.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/sync_test.go index 6f5cc96b3..4cd4c0ab2 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/sync_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/sync_test.go @@ -20,7 +20,7 @@ import ( "testing" "time" - extensions "k8s.io/api/extensions/v1beta1" + apps "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/informers" @@ -41,7 +41,7 @@ func TestScale(t *testing.T) { oldTimestamp := metav1.Date(2016, 5, 20, 1, 0, 0, 0, time.UTC) olderTimestamp := metav1.Date(2016, 5, 20, 0, 0, 0, 0, time.UTC) - var updatedTemplate = func(replicas int) *extensions.Deployment { + var updatedTemplate = func(replicas int) *apps.Deployment { d := newDeployment("foo", replicas, nil, nil, nil, map[string]string{"foo": "bar"}) d.Spec.Template.Labels["another"] = "label" return d @@ -49,14 +49,14 @@ func TestScale(t *testing.T) { tests := []struct { name string - deployment *extensions.Deployment - oldDeployment *extensions.Deployment + deployment *apps.Deployment + oldDeployment *apps.Deployment - newRS *extensions.ReplicaSet - oldRSs []*extensions.ReplicaSet + newRS *apps.ReplicaSet + oldRSs []*apps.ReplicaSet - expectedNew *extensions.ReplicaSet - expectedOld []*extensions.ReplicaSet + expectedNew *apps.ReplicaSet + expectedOld []*apps.ReplicaSet wasntUpdated map[string]bool desiredReplicasAnnotations map[string]int32 @@ -67,10 +67,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 10, nil, nil, nil, nil), newRS: rs("foo-v1", 10, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{}, + oldRSs: []*apps.ReplicaSet{}, expectedNew: rs("foo-v1", 12, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{}, + expectedOld: []*apps.ReplicaSet{}, }, { name: "normal scaling event: 10 -> 5", @@ -78,10 +78,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 10, nil, nil, nil, nil), newRS: rs("foo-v1", 10, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{}, + oldRSs: []*apps.ReplicaSet{}, expectedNew: rs("foo-v1", 5, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{}, + expectedOld: []*apps.ReplicaSet{}, }, { name: "proportional scaling: 5 -> 10", @@ -89,10 +89,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 5, nil, nil, nil, nil), newRS: rs("foo-v2", 2, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v1", 3, nil, oldTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v1", 3, nil, oldTimestamp)}, expectedNew: rs("foo-v2", 4, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v1", 6, nil, oldTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v1", 6, nil, oldTimestamp)}, }, { name: "proportional scaling: 5 -> 3", @@ -100,10 +100,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 5, nil, nil, nil, nil), newRS: rs("foo-v2", 2, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v1", 3, nil, oldTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v1", 3, nil, oldTimestamp)}, expectedNew: rs("foo-v2", 1, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v1", 2, nil, oldTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v1", 2, nil, oldTimestamp)}, }, { name: "proportional scaling: 9 -> 4", @@ -111,10 +111,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 9, nil, nil, nil, nil), newRS: rs("foo-v2", 8, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v1", 1, nil, oldTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v1", 1, nil, oldTimestamp)}, expectedNew: rs("foo-v2", 4, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v1", 0, nil, oldTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v1", 0, nil, oldTimestamp)}, }, { name: "proportional scaling: 7 -> 10", @@ -122,10 +122,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 7, nil, nil, nil, nil), newRS: rs("foo-v3", 2, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v2", 3, nil, oldTimestamp), rs("foo-v1", 2, nil, olderTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v2", 3, nil, oldTimestamp), rs("foo-v1", 2, nil, olderTimestamp)}, expectedNew: rs("foo-v3", 3, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v2", 4, nil, oldTimestamp), rs("foo-v1", 3, nil, olderTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v2", 4, nil, oldTimestamp), rs("foo-v1", 3, nil, olderTimestamp)}, }, { name: "proportional scaling: 13 -> 8", @@ -133,10 +133,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 13, nil, nil, nil, nil), newRS: rs("foo-v3", 2, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v2", 8, nil, oldTimestamp), rs("foo-v1", 3, nil, olderTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v2", 8, nil, oldTimestamp), rs("foo-v1", 3, nil, olderTimestamp)}, expectedNew: rs("foo-v3", 1, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v2", 5, nil, oldTimestamp), rs("foo-v1", 2, nil, olderTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v2", 5, nil, oldTimestamp), rs("foo-v1", 2, nil, olderTimestamp)}, }, // Scales up the new replica set. { @@ -145,10 +145,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 3, nil, nil, nil, nil), newRS: rs("foo-v3", 1, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, expectedNew: rs("foo-v3", 2, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, }, // Scales down the older replica set. { @@ -157,10 +157,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 3, nil, nil, nil, nil), newRS: rs("foo-v3", 1, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, expectedNew: rs("foo-v3", 1, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 0, nil, olderTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 0, nil, olderTimestamp)}, }, // Scales up the latest replica set first. { @@ -169,10 +169,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 4, nil, nil, nil, nil), newRS: nil, - oldRSs: []*extensions.ReplicaSet{rs("foo-v2", 2, nil, oldTimestamp), rs("foo-v1", 2, nil, olderTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v2", 2, nil, oldTimestamp), rs("foo-v1", 2, nil, olderTimestamp)}, expectedNew: nil, - expectedOld: []*extensions.ReplicaSet{rs("foo-v2", 3, nil, oldTimestamp), rs("foo-v1", 2, nil, olderTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v2", 3, nil, oldTimestamp), rs("foo-v1", 2, nil, olderTimestamp)}, }, // Scales down to zero { @@ -181,10 +181,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 6, nil, nil, nil, nil), newRS: rs("foo-v3", 3, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v2", 2, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v2", 2, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, expectedNew: rs("foo-v3", 0, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v2", 0, nil, oldTimestamp), rs("foo-v1", 0, nil, olderTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v2", 0, nil, oldTimestamp), rs("foo-v1", 0, nil, olderTimestamp)}, }, // Scales up from zero { @@ -193,10 +193,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 6, nil, nil, nil, nil), newRS: rs("foo-v3", 0, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v2", 0, nil, oldTimestamp), rs("foo-v1", 0, nil, olderTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v2", 0, nil, oldTimestamp), rs("foo-v1", 0, nil, olderTimestamp)}, expectedNew: rs("foo-v3", 6, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v2", 0, nil, oldTimestamp), rs("foo-v1", 0, nil, olderTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v2", 0, nil, oldTimestamp), rs("foo-v1", 0, nil, olderTimestamp)}, wasntUpdated: map[string]bool{"foo-v2": true, "foo-v1": true}, }, // Scenario: deployment.spec.replicas == 3 ( foo-v1.spec.replicas == foo-v2.spec.replicas == foo-v3.spec.replicas == 1 ) @@ -208,10 +208,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 5, nil, nil, nil, nil), newRS: rs("foo-v3", 2, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v2", 1, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, expectedNew: rs("foo-v3", 2, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v2", 2, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v2", 2, nil, oldTimestamp), rs("foo-v1", 1, nil, olderTimestamp)}, wasntUpdated: map[string]bool{"foo-v3": true, "foo-v1": true}, desiredReplicasAnnotations: map[string]int32{"foo-v2": int32(3)}, @@ -222,10 +222,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 10, nil, intOrStrP(2), nil, nil), newRS: rs("foo-v2", 6, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v1", 6, nil, oldTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v1", 6, nil, oldTimestamp)}, expectedNew: rs("foo-v2", 11, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v1", 11, nil, oldTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v1", 11, nil, oldTimestamp)}, }, { name: "change both surge and size", @@ -233,10 +233,10 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 10, nil, intOrStrP(3), nil, nil), newRS: rs("foo-v2", 5, nil, newTimestamp), - oldRSs: []*extensions.ReplicaSet{rs("foo-v1", 8, nil, oldTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v1", 8, nil, oldTimestamp)}, expectedNew: rs("foo-v2", 22, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v1", 34, nil, oldTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v1", 34, nil, oldTimestamp)}, }, { name: "change both size and template", @@ -244,25 +244,25 @@ func TestScale(t *testing.T) { oldDeployment: newDeployment("foo", 10, nil, nil, nil, map[string]string{"foo": "bar"}), newRS: nil, - oldRSs: []*extensions.ReplicaSet{rs("foo-v2", 7, nil, newTimestamp), rs("foo-v1", 3, nil, oldTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v2", 7, nil, newTimestamp), rs("foo-v1", 3, nil, oldTimestamp)}, expectedNew: nil, - expectedOld: []*extensions.ReplicaSet{rs("foo-v2", 10, nil, newTimestamp), rs("foo-v1", 4, nil, oldTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v2", 10, nil, newTimestamp), rs("foo-v1", 4, nil, oldTimestamp)}, }, { name: "saturated but broken new replica set does not affect old pods", deployment: newDeployment("foo", 2, nil, intOrStrP(1), intOrStrP(1), nil), oldDeployment: newDeployment("foo", 2, nil, intOrStrP(1), intOrStrP(1), nil), - newRS: func() *extensions.ReplicaSet { + newRS: func() *apps.ReplicaSet { rs := rs("foo-v2", 2, nil, newTimestamp) rs.Status.AvailableReplicas = 0 return rs }(), - oldRSs: []*extensions.ReplicaSet{rs("foo-v1", 1, nil, oldTimestamp)}, + oldRSs: []*apps.ReplicaSet{rs("foo-v1", 1, nil, oldTimestamp)}, expectedNew: rs("foo-v2", 2, nil, newTimestamp), - expectedOld: []*extensions.ReplicaSet{rs("foo-v1", 1, nil, oldTimestamp)}, + expectedOld: []*apps.ReplicaSet{rs("foo-v1", 1, nil, oldTimestamp)}, }, } @@ -313,7 +313,7 @@ func TestScale(t *testing.T) { } // Get all the UPDATE actions and update nameToSize with all the updated sizes. for _, action := range fake.Actions() { - rs := action.(testclient.UpdateAction).GetObject().(*extensions.ReplicaSet) + rs := action.(testclient.UpdateAction).GetObject().(*apps.ReplicaSet) if !test.wasntUpdated[rs.Name] { nameToSize[rs.Name] = *(rs.Spec.Replicas) } @@ -345,12 +345,12 @@ func TestDeploymentController_cleanupDeployment(t *testing.T) { alreadyDeleted.DeletionTimestamp = &now tests := []struct { - oldRSs []*extensions.ReplicaSet + oldRSs []*apps.ReplicaSet revisionHistoryLimit int32 expectedDeletions int }{ { - oldRSs: []*extensions.ReplicaSet{ + oldRSs: []*apps.ReplicaSet{ newRSWithStatus("foo-1", 0, 0, selector), newRSWithStatus("foo-2", 0, 0, selector), newRSWithStatus("foo-3", 0, 0, selector), @@ -360,7 +360,7 @@ func TestDeploymentController_cleanupDeployment(t *testing.T) { }, { // Only delete the replica set with Spec.Replicas = Status.Replicas = 0. - oldRSs: []*extensions.ReplicaSet{ + oldRSs: []*apps.ReplicaSet{ newRSWithStatus("foo-1", 0, 0, selector), newRSWithStatus("foo-2", 0, 1, selector), newRSWithStatus("foo-3", 1, 0, selector), @@ -371,7 +371,7 @@ func TestDeploymentController_cleanupDeployment(t *testing.T) { }, { - oldRSs: []*extensions.ReplicaSet{ + oldRSs: []*apps.ReplicaSet{ newRSWithStatus("foo-1", 0, 0, selector), newRSWithStatus("foo-2", 0, 0, selector), }, @@ -379,7 +379,7 @@ func TestDeploymentController_cleanupDeployment(t *testing.T) { expectedDeletions: 2, }, { - oldRSs: []*extensions.ReplicaSet{ + oldRSs: []*apps.ReplicaSet{ newRSWithStatus("foo-1", 1, 1, selector), newRSWithStatus("foo-2", 1, 1, selector), }, @@ -387,7 +387,7 @@ func TestDeploymentController_cleanupDeployment(t *testing.T) { expectedDeletions: 0, }, { - oldRSs: []*extensions.ReplicaSet{ + oldRSs: []*apps.ReplicaSet{ alreadyDeleted, }, revisionHistoryLimit: 0, @@ -401,7 +401,7 @@ func TestDeploymentController_cleanupDeployment(t *testing.T) { fake := &fake.Clientset{} informers := informers.NewSharedInformerFactory(fake, controller.NoResyncPeriodFunc()) - controller, err := NewDeploymentController(informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().ReplicaSets(), informers.Core().V1().Pods(), fake) + controller, err := NewDeploymentController(informers.Apps().V1().Deployments(), informers.Apps().V1().ReplicaSets(), informers.Core().V1().Pods(), fake) if err != nil { t.Fatalf("error creating Deployment controller: %v", err) } @@ -411,7 +411,7 @@ func TestDeploymentController_cleanupDeployment(t *testing.T) { controller.rsListerSynced = alwaysReady controller.podListerSynced = alwaysReady for _, rs := range test.oldRSs { - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs) } stopCh := make(chan struct{}) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/BUILD index 58890da63..e3bd84401 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/BUILD @@ -19,8 +19,8 @@ go_library( "//pkg/controller:go_default_library", "//pkg/util/labels:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/apis/meta/v1:go_default_library", @@ -29,11 +29,10 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", + "//vendor/k8s.io/client-go/listers/apps/v1:go_default_library", "//vendor/k8s.io/client-go/listers/core/v1:go_default_library", - "//vendor/k8s.io/client-go/listers/extensions/v1beta1:go_default_library", "//vendor/k8s.io/client-go/util/integer:go_default_library", "//vendor/k8s.io/client-go/util/retry:go_default_library", ], @@ -49,8 +48,8 @@ go_test( deps = [ "//pkg/controller:go_default_library", "//pkg/util/hash:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/deployment_util.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/deployment_util.go index 763b8debd..a435e5eac 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/deployment_util.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/deployment_util.go @@ -25,20 +25,16 @@ import ( "github.com/golang/glog" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/errors" intstrutil "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" - clientset "k8s.io/client-go/kubernetes" - extensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" - corelisters "k8s.io/client-go/listers/core/v1" - extensionslisters "k8s.io/client-go/listers/extensions/v1beta1" + appsclient "k8s.io/client-go/kubernetes/typed/apps/v1" "k8s.io/client-go/util/integer" internalextensions "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/controller" @@ -102,8 +98,8 @@ const ( ) // NewDeploymentCondition creates a new deployment condition. -func NewDeploymentCondition(condType extensions.DeploymentConditionType, status v1.ConditionStatus, reason, message string) *extensions.DeploymentCondition { - return &extensions.DeploymentCondition{ +func NewDeploymentCondition(condType apps.DeploymentConditionType, status v1.ConditionStatus, reason, message string) *apps.DeploymentCondition { + return &apps.DeploymentCondition{ Type: condType, Status: status, LastUpdateTime: metav1.Now(), @@ -114,7 +110,7 @@ func NewDeploymentCondition(condType extensions.DeploymentConditionType, status } // GetDeploymentCondition returns the condition with the provided type. -func GetDeploymentCondition(status extensions.DeploymentStatus, condType extensions.DeploymentConditionType) *extensions.DeploymentCondition { +func GetDeploymentCondition(status apps.DeploymentStatus, condType apps.DeploymentConditionType) *apps.DeploymentCondition { for i := range status.Conditions { c := status.Conditions[i] if c.Type == condType { @@ -126,7 +122,7 @@ func GetDeploymentCondition(status extensions.DeploymentStatus, condType extensi // SetDeploymentCondition updates the deployment to include the provided condition. If the condition that // we are about to add already exists and has the same status and reason then we are not going to update. -func SetDeploymentCondition(status *extensions.DeploymentStatus, condition extensions.DeploymentCondition) { +func SetDeploymentCondition(status *apps.DeploymentStatus, condition apps.DeploymentCondition) { currentCond := GetDeploymentCondition(*status, condition.Type) if currentCond != nil && currentCond.Status == condition.Status && currentCond.Reason == condition.Reason { return @@ -140,13 +136,13 @@ func SetDeploymentCondition(status *extensions.DeploymentStatus, condition exten } // RemoveDeploymentCondition removes the deployment condition with the provided type. -func RemoveDeploymentCondition(status *extensions.DeploymentStatus, condType extensions.DeploymentConditionType) { +func RemoveDeploymentCondition(status *apps.DeploymentStatus, condType apps.DeploymentConditionType) { status.Conditions = filterOutCondition(status.Conditions, condType) } // filterOutCondition returns a new slice of deployment conditions without conditions with the provided type. -func filterOutCondition(conditions []extensions.DeploymentCondition, condType extensions.DeploymentConditionType) []extensions.DeploymentCondition { - var newConditions []extensions.DeploymentCondition +func filterOutCondition(conditions []apps.DeploymentCondition, condType apps.DeploymentConditionType) []apps.DeploymentCondition { + var newConditions []apps.DeploymentCondition for _, c := range conditions { if c.Type == condType { continue @@ -158,9 +154,9 @@ func filterOutCondition(conditions []extensions.DeploymentCondition, condType ex // ReplicaSetToDeploymentCondition converts a replica set condition into a deployment condition. // Useful for promoting replica set failure conditions into deployments. -func ReplicaSetToDeploymentCondition(cond extensions.ReplicaSetCondition) extensions.DeploymentCondition { - return extensions.DeploymentCondition{ - Type: extensions.DeploymentConditionType(cond.Type), +func ReplicaSetToDeploymentCondition(cond apps.ReplicaSetCondition) apps.DeploymentCondition { + return apps.DeploymentCondition{ + Type: apps.DeploymentConditionType(cond.Type), Status: cond.Status, LastTransitionTime: cond.LastTransitionTime, LastUpdateTime: cond.LastTransitionTime, @@ -170,7 +166,7 @@ func ReplicaSetToDeploymentCondition(cond extensions.ReplicaSetCondition) extens } // SetDeploymentRevision updates the revision for a deployment. -func SetDeploymentRevision(deployment *extensions.Deployment, revision string) bool { +func SetDeploymentRevision(deployment *apps.Deployment, revision string) bool { updated := false if deployment.Annotations == nil { @@ -185,7 +181,7 @@ func SetDeploymentRevision(deployment *extensions.Deployment, revision string) b } // MaxRevision finds the highest revision in the replica sets -func MaxRevision(allRSs []*extensions.ReplicaSet) int64 { +func MaxRevision(allRSs []*apps.ReplicaSet) int64 { max := int64(0) for _, rs := range allRSs { if v, err := Revision(rs); err != nil { @@ -199,7 +195,7 @@ func MaxRevision(allRSs []*extensions.ReplicaSet) int64 { } // LastRevision finds the second max revision number in all replica sets (the last revision) -func LastRevision(allRSs []*extensions.ReplicaSet) int64 { +func LastRevision(allRSs []*apps.ReplicaSet) int64 { max, secMax := int64(0), int64(0) for _, rs := range allRSs { if v, err := Revision(rs); err != nil { @@ -230,7 +226,7 @@ func Revision(obj runtime.Object) (int64, error) { // SetNewReplicaSetAnnotations sets new replica set's annotations appropriately by updating its revision and // copying required deployment annotations to it; it returns true if replica set's annotation is changed. -func SetNewReplicaSetAnnotations(deployment *extensions.Deployment, newRS *extensions.ReplicaSet, newRevision string, exists bool) bool { +func SetNewReplicaSetAnnotations(deployment *apps.Deployment, newRS *apps.ReplicaSet, newRevision string, exists bool) bool { // First, copy deployment's annotations (except for apply and revision annotations) annotationChanged := copyDeploymentAnnotationsToReplicaSet(deployment, newRS) // Then, update replica set's revision annotation @@ -287,6 +283,7 @@ var annotationsToSkip = map[string]bool{ RevisionHistoryAnnotation: true, DesiredReplicasAnnotation: true, MaxReplicasAnnotation: true, + apps.DeprecatedRollbackTo: true, } // skipCopyAnnotation returns true if we should skip copying the annotation with the given annotation key @@ -299,7 +296,7 @@ func skipCopyAnnotation(key string) bool { // copyDeploymentAnnotationsToReplicaSet copies deployment's annotations to replica set's annotations, // and returns true if replica set's annotation is changed. // Note that apply and revision annotations are not copied. -func copyDeploymentAnnotationsToReplicaSet(deployment *extensions.Deployment, rs *extensions.ReplicaSet) bool { +func copyDeploymentAnnotationsToReplicaSet(deployment *apps.Deployment, rs *apps.ReplicaSet) bool { rsAnnotationsChanged := false if rs.Annotations == nil { rs.Annotations = make(map[string]string) @@ -320,7 +317,7 @@ func copyDeploymentAnnotationsToReplicaSet(deployment *extensions.Deployment, rs // SetDeploymentAnnotationsTo sets deployment's annotations as given RS's annotations. // This action should be done if and only if the deployment is rolling back to this rs. // Note that apply and revision annotations are not changed. -func SetDeploymentAnnotationsTo(deployment *extensions.Deployment, rollbackToRS *extensions.ReplicaSet) { +func SetDeploymentAnnotationsTo(deployment *apps.Deployment, rollbackToRS *apps.ReplicaSet) { deployment.Annotations = getSkippedAnnotations(deployment.Annotations) for k, v := range rollbackToRS.Annotations { if !skipCopyAnnotation(k) { @@ -341,7 +338,7 @@ func getSkippedAnnotations(annotations map[string]string) map[string]string { // FindActiveOrLatest returns the only active or the latest replica set in case there is at most one active // replica set. If there are more active replica sets, then we should proportionally scale them. -func FindActiveOrLatest(newRS *extensions.ReplicaSet, oldRSs []*extensions.ReplicaSet) *extensions.ReplicaSet { +func FindActiveOrLatest(newRS *apps.ReplicaSet, oldRSs []*apps.ReplicaSet) *apps.ReplicaSet { if newRS == nil && len(oldRSs) == 0 { return nil } @@ -364,15 +361,15 @@ func FindActiveOrLatest(newRS *extensions.ReplicaSet, oldRSs []*extensions.Repli } // GetDesiredReplicasAnnotation returns the number of desired replicas -func GetDesiredReplicasAnnotation(rs *extensions.ReplicaSet) (int32, bool) { +func GetDesiredReplicasAnnotation(rs *apps.ReplicaSet) (int32, bool) { return getIntFromAnnotation(rs, DesiredReplicasAnnotation) } -func getMaxReplicasAnnotation(rs *extensions.ReplicaSet) (int32, bool) { +func getMaxReplicasAnnotation(rs *apps.ReplicaSet) (int32, bool) { return getIntFromAnnotation(rs, MaxReplicasAnnotation) } -func getIntFromAnnotation(rs *extensions.ReplicaSet, annotationKey string) (int32, bool) { +func getIntFromAnnotation(rs *apps.ReplicaSet, annotationKey string) (int32, bool) { annotationValue, ok := rs.Annotations[annotationKey] if !ok { return int32(0), false @@ -386,7 +383,7 @@ func getIntFromAnnotation(rs *extensions.ReplicaSet, annotationKey string) (int3 } // SetReplicasAnnotations sets the desiredReplicas and maxReplicas into the annotations -func SetReplicasAnnotations(rs *extensions.ReplicaSet, desiredReplicas, maxReplicas int32) bool { +func SetReplicasAnnotations(rs *apps.ReplicaSet, desiredReplicas, maxReplicas int32) bool { updated := false if rs.Annotations == nil { rs.Annotations = make(map[string]string) @@ -404,8 +401,24 @@ func SetReplicasAnnotations(rs *extensions.ReplicaSet, desiredReplicas, maxRepli return updated } +// AnnotationsNeedUpdate return true if ReplicasAnnotations need to be updated +func ReplicasAnnotationsNeedUpdate(rs *apps.ReplicaSet, desiredReplicas, maxReplicas int32) bool { + if rs.Annotations == nil { + return true + } + desiredString := fmt.Sprintf("%d", desiredReplicas) + if hasString := rs.Annotations[DesiredReplicasAnnotation]; hasString != desiredString { + return true + } + maxString := fmt.Sprintf("%d", maxReplicas) + if hasString := rs.Annotations[MaxReplicasAnnotation]; hasString != maxString { + return true + } + return false +} + // MaxUnavailable returns the maximum unavailable pods a rolling deployment can take. -func MaxUnavailable(deployment extensions.Deployment) int32 { +func MaxUnavailable(deployment apps.Deployment) int32 { if !IsRollingUpdate(&deployment) || *(deployment.Spec.Replicas) == 0 { return int32(0) } @@ -418,7 +431,7 @@ func MaxUnavailable(deployment extensions.Deployment) int32 { } // MinAvailable returns the minimum available pods of a given deployment -func MinAvailable(deployment *extensions.Deployment) int32 { +func MinAvailable(deployment *apps.Deployment) int32 { if !IsRollingUpdate(deployment) { return int32(0) } @@ -426,7 +439,7 @@ func MinAvailable(deployment *extensions.Deployment) int32 { } // MaxSurge returns the maximum surge pods a rolling deployment can take. -func MaxSurge(deployment extensions.Deployment) int32 { +func MaxSurge(deployment apps.Deployment) int32 { if !IsRollingUpdate(&deployment) { return int32(0) } @@ -438,7 +451,7 @@ func MaxSurge(deployment extensions.Deployment) int32 { // GetProportion will estimate the proportion for the provided replica set using 1. the current size // of the parent deployment, 2. the replica count that needs be added on the replica sets of the // deployment, and 3. the total replicas added in the replica sets of the deployment so far. -func GetProportion(rs *extensions.ReplicaSet, d extensions.Deployment, deploymentReplicasToAdd, deploymentReplicasAdded int32) int32 { +func GetProportion(rs *apps.ReplicaSet, d apps.Deployment, deploymentReplicasToAdd, deploymentReplicasAdded int32) int32 { if rs == nil || *(rs.Spec.Replicas) == 0 || deploymentReplicasToAdd == 0 || deploymentReplicasToAdd == deploymentReplicasAdded { return int32(0) } @@ -460,7 +473,7 @@ func GetProportion(rs *extensions.ReplicaSet, d extensions.Deployment, deploymen // getReplicaSetFraction estimates the fraction of replicas a replica set can have in // 1. a scaling event during a rollout or 2. when scaling a paused deployment. -func getReplicaSetFraction(rs extensions.ReplicaSet, d extensions.Deployment) int32 { +func getReplicaSetFraction(rs apps.ReplicaSet, d apps.Deployment) int32 { // If we are scaling down to zero then the fraction of this replica set is its whole size (negative) if *(d.Spec.Replicas) == int32(0) { return -*(rs.Spec.Replicas) @@ -485,7 +498,7 @@ func getReplicaSetFraction(rs extensions.ReplicaSet, d extensions.Deployment) in // GetAllReplicaSets returns the old and new replica sets targeted by the given Deployment. It gets PodList and ReplicaSetList from client interface. // Note that the first set of old replica sets doesn't include the ones with no pods, and the second set of old replica sets include all old replica sets. // The third returned value is the new replica set, and it may be nil if it doesn't exist yet. -func GetAllReplicaSets(deployment *extensions.Deployment, c extensionsv1beta1.ExtensionsV1beta1Interface) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, *extensions.ReplicaSet, error) { +func GetAllReplicaSets(deployment *apps.Deployment, c appsclient.AppsV1Interface) ([]*apps.ReplicaSet, []*apps.ReplicaSet, *apps.ReplicaSet, error) { rsList, err := ListReplicaSets(deployment, RsListFromClient(c)) if err != nil { return nil, nil, nil, err @@ -497,7 +510,7 @@ func GetAllReplicaSets(deployment *extensions.Deployment, c extensionsv1beta1.Ex // GetOldReplicaSets returns the old replica sets targeted by the given Deployment; get PodList and ReplicaSetList from client interface. // Note that the first set of old replica sets doesn't include the ones with no pods, and the second set of old replica sets include all old replica sets. -func GetOldReplicaSets(deployment *extensions.Deployment, c extensionsv1beta1.ExtensionsV1beta1Interface) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, error) { +func GetOldReplicaSets(deployment *apps.Deployment, c appsclient.AppsV1Interface) ([]*apps.ReplicaSet, []*apps.ReplicaSet, error) { rsList, err := ListReplicaSets(deployment, RsListFromClient(c)) if err != nil { return nil, nil, err @@ -508,7 +521,7 @@ func GetOldReplicaSets(deployment *extensions.Deployment, c extensionsv1beta1.Ex // GetNewReplicaSet returns a replica set that matches the intent of the given deployment; get ReplicaSetList from client interface. // Returns nil if the new replica set doesn't exist yet. -func GetNewReplicaSet(deployment *extensions.Deployment, c extensionsv1beta1.ExtensionsV1beta1Interface) (*extensions.ReplicaSet, error) { +func GetNewReplicaSet(deployment *apps.Deployment, c appsclient.AppsV1Interface) (*apps.ReplicaSet, error) { rsList, err := ListReplicaSets(deployment, RsListFromClient(c)) if err != nil { return nil, err @@ -517,13 +530,13 @@ func GetNewReplicaSet(deployment *extensions.Deployment, c extensionsv1beta1.Ext } // RsListFromClient returns an rsListFunc that wraps the given client. -func RsListFromClient(c extensionsv1beta1.ExtensionsV1beta1Interface) RsListFunc { - return func(namespace string, options metav1.ListOptions) ([]*extensions.ReplicaSet, error) { +func RsListFromClient(c appsclient.AppsV1Interface) RsListFunc { + return func(namespace string, options metav1.ListOptions) ([]*apps.ReplicaSet, error) { rsList, err := c.ReplicaSets(namespace).List(options) if err != nil { return nil, err } - var ret []*extensions.ReplicaSet + var ret []*apps.ReplicaSet for i := range rsList.Items { ret = append(ret, &rsList.Items[i]) } @@ -532,14 +545,14 @@ func RsListFromClient(c extensionsv1beta1.ExtensionsV1beta1Interface) RsListFunc } // TODO: switch this to full namespacers -type RsListFunc func(string, metav1.ListOptions) ([]*extensions.ReplicaSet, error) +type RsListFunc func(string, metav1.ListOptions) ([]*apps.ReplicaSet, error) type podListFunc func(string, metav1.ListOptions) (*v1.PodList, error) // ListReplicaSets returns a slice of RSes the given deployment targets. // Note that this does NOT attempt to reconcile ControllerRef (adopt/orphan), // because only the controller itself should do that. // However, it does filter out anything whose ControllerRef doesn't match. -func ListReplicaSets(deployment *extensions.Deployment, getRSList RsListFunc) ([]*extensions.ReplicaSet, error) { +func ListReplicaSets(deployment *apps.Deployment, getRSList RsListFunc) ([]*apps.ReplicaSet, error) { // TODO: Right now we list replica sets by their labels. We should list them by selector, i.e. the replica set's selector // should be a superset of the deployment's selector, see https://github.com/kubernetes/kubernetes/issues/19830. namespace := deployment.Namespace @@ -553,7 +566,7 @@ func ListReplicaSets(deployment *extensions.Deployment, getRSList RsListFunc) ([ return nil, err } // Only include those whose ControllerRef matches the Deployment. - owned := make([]*extensions.ReplicaSet, 0, len(all)) + owned := make([]*apps.ReplicaSet, 0, len(all)) for _, rs := range all { if metav1.IsControlledBy(rs, deployment) { owned = append(owned, rs) @@ -591,7 +604,7 @@ func ListReplicaSetsInternal(deployment *internalextensions.Deployment, getRSLis // Note that this does NOT attempt to reconcile ControllerRef (adopt/orphan), // because only the controller itself should do that. // However, it does filter out anything whose ControllerRef doesn't match. -func ListPods(deployment *extensions.Deployment, rsList []*extensions.ReplicaSet, getPodList podListFunc) (*v1.PodList, error) { +func ListPods(deployment *apps.Deployment, rsList []*apps.ReplicaSet, getPodList podListFunc) (*v1.PodList, error) { namespace := deployment.Namespace selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector) if err != nil { @@ -620,30 +633,21 @@ func ListPods(deployment *extensions.Deployment, rsList []*extensions.ReplicaSet } // EqualIgnoreHash returns true if two given podTemplateSpec are equal, ignoring the diff in value of Labels[pod-template-hash] -// We ignore pod-template-hash because the hash result would be different upon podTemplateSpec API changes -// (e.g. the addition of a new field will cause the hash code to change) -// Note that we assume input podTemplateSpecs contain non-empty labels +// We ignore pod-template-hash because: +// 1. The hash result would be different upon podTemplateSpec API changes +// (e.g. the addition of a new field will cause the hash code to change) +// 2. The deployment template won't have hash labels func EqualIgnoreHash(template1, template2 *v1.PodTemplateSpec) bool { t1Copy := template1.DeepCopy() t2Copy := template2.DeepCopy() - // First, compare template.Labels (ignoring hash) - labels1, labels2 := t1Copy.Labels, t2Copy.Labels - if len(labels1) > len(labels2) { - labels1, labels2 = labels2, labels1 - } - // We make sure len(labels2) >= len(labels1) - for k, v := range labels2 { - if labels1[k] != v && k != extensions.DefaultDeploymentUniqueLabelKey { - return false - } - } - // Then, compare the templates without comparing their labels - t1Copy.Labels, t2Copy.Labels = nil, nil + // Remove hash labels from template.Labels before comparing + delete(t1Copy.Labels, apps.DefaultDeploymentUniqueLabelKey) + delete(t2Copy.Labels, apps.DefaultDeploymentUniqueLabelKey) return apiequality.Semantic.DeepEqual(t1Copy, t2Copy) } // FindNewReplicaSet returns the new RS this given deployment targets (the one with the same pod template). -func FindNewReplicaSet(deployment *extensions.Deployment, rsList []*extensions.ReplicaSet) *extensions.ReplicaSet { +func FindNewReplicaSet(deployment *apps.Deployment, rsList []*apps.ReplicaSet) *apps.ReplicaSet { sort.Sort(controller.ReplicaSetsByCreationTimestamp(rsList)) for i := range rsList { if EqualIgnoreHash(&rsList[i].Spec.Template, &deployment.Spec.Template) { @@ -660,9 +664,9 @@ func FindNewReplicaSet(deployment *extensions.Deployment, rsList []*extensions.R // FindOldReplicaSets returns the old replica sets targeted by the given Deployment, with the given slice of RSes. // Note that the first set of old replica sets doesn't include the ones with no pods, and the second set of old replica sets include all old replica sets. -func FindOldReplicaSets(deployment *extensions.Deployment, rsList []*extensions.ReplicaSet) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet) { - var requiredRSs []*extensions.ReplicaSet - var allRSs []*extensions.ReplicaSet +func FindOldReplicaSets(deployment *apps.Deployment, rsList []*apps.ReplicaSet) ([]*apps.ReplicaSet, []*apps.ReplicaSet) { + var requiredRSs []*apps.ReplicaSet + var allRSs []*apps.ReplicaSet newRS := FindNewReplicaSet(deployment, rsList) for _, rs := range rsList { // Filter out new replica set @@ -677,68 +681,18 @@ func FindOldReplicaSets(deployment *extensions.Deployment, rsList []*extensions. return requiredRSs, allRSs } -// WaitForReplicaSetUpdated polls the replica set until it is updated. -func WaitForReplicaSetUpdated(c extensionslisters.ReplicaSetLister, desiredGeneration int64, namespace, name string) error { - return wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) { - rs, err := c.ReplicaSets(namespace).Get(name) - if err != nil { - return false, err - } - return rs.Status.ObservedGeneration >= desiredGeneration, nil - }) -} - -// WaitForPodsHashPopulated polls the replica set until updated and fully labeled. -func WaitForPodsHashPopulated(c extensionslisters.ReplicaSetLister, desiredGeneration int64, namespace, name string) error { - return wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) { - rs, err := c.ReplicaSets(namespace).Get(name) - if err != nil { - return false, err - } - return rs.Status.ObservedGeneration >= desiredGeneration && - rs.Status.FullyLabeledReplicas == *(rs.Spec.Replicas), nil - }) -} - -// LabelPodsWithHash labels all pods in the given podList with the new hash label. -func LabelPodsWithHash(podList *v1.PodList, c clientset.Interface, podLister corelisters.PodLister, namespace, name, hash string) error { - for _, pod := range podList.Items { - // Ignore inactive Pods. - if !controller.IsPodActive(&pod) { - continue - } - // Only label the pod that doesn't already have the new hash - if pod.Labels[extensions.DefaultDeploymentUniqueLabelKey] != hash { - _, err := UpdatePodWithRetries(c.CoreV1().Pods(namespace), podLister, pod.Namespace, pod.Name, - func(podToUpdate *v1.Pod) error { - // Precondition: the pod doesn't contain the new hash in its label. - if podToUpdate.Labels[extensions.DefaultDeploymentUniqueLabelKey] == hash { - return errors.ErrPreconditionViolated - } - podToUpdate.Labels = labelsutil.AddLabel(podToUpdate.Labels, extensions.DefaultDeploymentUniqueLabelKey, hash) - return nil - }) - if err != nil { - return fmt.Errorf("error in adding template hash label %s to pod %q: %v", hash, pod.Name, err) - } - glog.V(4).Infof("Labeled pod %s/%s of ReplicaSet %s/%s with hash %s.", pod.Namespace, pod.Name, namespace, name, hash) - } - } - return nil -} - // SetFromReplicaSetTemplate sets the desired PodTemplateSpec from a replica set template to the given deployment. -func SetFromReplicaSetTemplate(deployment *extensions.Deployment, template v1.PodTemplateSpec) *extensions.Deployment { +func SetFromReplicaSetTemplate(deployment *apps.Deployment, template v1.PodTemplateSpec) *apps.Deployment { deployment.Spec.Template.ObjectMeta = template.ObjectMeta deployment.Spec.Template.Spec = template.Spec deployment.Spec.Template.ObjectMeta.Labels = labelsutil.CloneAndRemoveLabel( deployment.Spec.Template.ObjectMeta.Labels, - extensions.DefaultDeploymentUniqueLabelKey) + apps.DefaultDeploymentUniqueLabelKey) return deployment } // GetReplicaCountForReplicaSets returns the sum of Replicas of the given replica sets. -func GetReplicaCountForReplicaSets(replicaSets []*extensions.ReplicaSet) int32 { +func GetReplicaCountForReplicaSets(replicaSets []*apps.ReplicaSet) int32 { totalReplicas := int32(0) for _, rs := range replicaSets { if rs != nil { @@ -749,7 +703,7 @@ func GetReplicaCountForReplicaSets(replicaSets []*extensions.ReplicaSet) int32 { } // GetActualReplicaCountForReplicaSets returns the sum of actual replicas of the given replica sets. -func GetActualReplicaCountForReplicaSets(replicaSets []*extensions.ReplicaSet) int32 { +func GetActualReplicaCountForReplicaSets(replicaSets []*apps.ReplicaSet) int32 { totalActualReplicas := int32(0) for _, rs := range replicaSets { if rs != nil { @@ -760,7 +714,7 @@ func GetActualReplicaCountForReplicaSets(replicaSets []*extensions.ReplicaSet) i } // GetReadyReplicaCountForReplicaSets returns the number of ready pods corresponding to the given replica sets. -func GetReadyReplicaCountForReplicaSets(replicaSets []*extensions.ReplicaSet) int32 { +func GetReadyReplicaCountForReplicaSets(replicaSets []*apps.ReplicaSet) int32 { totalReadyReplicas := int32(0) for _, rs := range replicaSets { if rs != nil { @@ -771,7 +725,7 @@ func GetReadyReplicaCountForReplicaSets(replicaSets []*extensions.ReplicaSet) in } // GetAvailableReplicaCountForReplicaSets returns the number of available pods corresponding to the given replica sets. -func GetAvailableReplicaCountForReplicaSets(replicaSets []*extensions.ReplicaSet) int32 { +func GetAvailableReplicaCountForReplicaSets(replicaSets []*apps.ReplicaSet) int32 { totalAvailableReplicas := int32(0) for _, rs := range replicaSets { if rs != nil { @@ -782,13 +736,13 @@ func GetAvailableReplicaCountForReplicaSets(replicaSets []*extensions.ReplicaSet } // IsRollingUpdate returns true if the strategy type is a rolling update. -func IsRollingUpdate(deployment *extensions.Deployment) bool { - return deployment.Spec.Strategy.Type == extensions.RollingUpdateDeploymentStrategyType +func IsRollingUpdate(deployment *apps.Deployment) bool { + return deployment.Spec.Strategy.Type == apps.RollingUpdateDeploymentStrategyType } // DeploymentComplete considers a deployment to be complete once all of its desired replicas // are updated and available, and no old pods are running. -func DeploymentComplete(deployment *extensions.Deployment, newStatus *extensions.DeploymentStatus) bool { +func DeploymentComplete(deployment *apps.Deployment, newStatus *apps.DeploymentStatus) bool { return newStatus.UpdatedReplicas == *(deployment.Spec.Replicas) && newStatus.Replicas == *(deployment.Spec.Replicas) && newStatus.AvailableReplicas == *(deployment.Spec.Replicas) && @@ -799,7 +753,7 @@ func DeploymentComplete(deployment *extensions.Deployment, newStatus *extensions // current with the new status of the deployment that the controller is observing. More specifically, // when new pods are scaled up or become ready or available, or old pods are scaled down, then we // consider the deployment is progressing. -func DeploymentProgressing(deployment *extensions.Deployment, newStatus *extensions.DeploymentStatus) bool { +func DeploymentProgressing(deployment *apps.Deployment, newStatus *apps.DeploymentStatus) bool { oldStatus := deployment.Status // Old replicas that need to be scaled down @@ -818,7 +772,7 @@ var nowFn = func() time.Time { return time.Now() } // DeploymentTimedOut considers a deployment to have timed out once its condition that reports progress // is older than progressDeadlineSeconds or a Progressing condition with a TimedOutReason reason already // exists. -func DeploymentTimedOut(deployment *extensions.Deployment, newStatus *extensions.DeploymentStatus) bool { +func DeploymentTimedOut(deployment *apps.Deployment, newStatus *apps.DeploymentStatus) bool { if deployment.Spec.ProgressDeadlineSeconds == nil { return false } @@ -826,7 +780,7 @@ func DeploymentTimedOut(deployment *extensions.Deployment, newStatus *extensions // Look for the Progressing condition. If it doesn't exist, we have no base to estimate progress. // If it's already set with a TimedOutReason reason, we have already timed out, no need to check // again. - condition := GetDeploymentCondition(*newStatus, extensions.DeploymentProgressing) + condition := GetDeploymentCondition(*newStatus, apps.DeploymentProgressing) if condition == nil { return false } @@ -864,9 +818,9 @@ func DeploymentTimedOut(deployment *extensions.Deployment, newStatus *extensions // When one of the followings is true, we're rolling out the deployment; otherwise, we're scaling it. // 1) The new RS is saturated: newRS's replicas == deployment's replicas // 2) Max number of pods allowed is reached: deployment's replicas + maxSurge == all RSs' replicas -func NewRSNewReplicas(deployment *extensions.Deployment, allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet) (int32, error) { +func NewRSNewReplicas(deployment *apps.Deployment, allRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet) (int32, error) { switch deployment.Spec.Strategy.Type { - case extensions.RollingUpdateDeploymentStrategyType: + case apps.RollingUpdateDeploymentStrategyType: // Check if we can scale up. maxSurge, err := intstrutil.GetValueFromIntOrPercent(deployment.Spec.Strategy.RollingUpdate.MaxSurge, int(*(deployment.Spec.Replicas)), true) if err != nil { @@ -884,7 +838,7 @@ func NewRSNewReplicas(deployment *extensions.Deployment, allRSs []*extensions.Re // Do not exceed the number of desired replicas. scaleUpCount = int32(integer.IntMin(int(scaleUpCount), int(*(deployment.Spec.Replicas)-*(newRS.Spec.Replicas)))) return *(newRS.Spec.Replicas) + scaleUpCount, nil - case extensions.RecreateDeploymentStrategyType: + case apps.RecreateDeploymentStrategyType: return *(deployment.Spec.Replicas), nil default: return 0, fmt.Errorf("deployment type %v isn't supported", deployment.Spec.Strategy.Type) @@ -895,7 +849,7 @@ func NewRSNewReplicas(deployment *extensions.Deployment, allRSs []*extensions.Re // Both the deployment and the replica set have to believe this replica set can own all of the desired // replicas in the deployment and the annotation helps in achieving that. All pods of the ReplicaSet // need to be available. -func IsSaturated(deployment *extensions.Deployment, rs *extensions.ReplicaSet) bool { +func IsSaturated(deployment *apps.Deployment, rs *apps.ReplicaSet) bool { if rs == nil { return false } @@ -911,7 +865,7 @@ func IsSaturated(deployment *extensions.Deployment, rs *extensions.ReplicaSet) b // WaitForObservedDeployment polls for deployment to be updated so that deployment.Status.ObservedGeneration >= desiredGeneration. // Returns error if polling timesout. -func WaitForObservedDeployment(getDeploymentFunc func() (*extensions.Deployment, error), desiredGeneration int64, interval, timeout time.Duration) error { +func WaitForObservedDeployment(getDeploymentFunc func() (*apps.Deployment, error), desiredGeneration int64, interval, timeout time.Duration) error { // TODO: This should take clientset.Interface when all code is updated to use clientset. Keeping it this way allows the function to be used by callers who have client.Interface. return wait.PollImmediate(interval, timeout, func() (bool, error) { deployment, err := getDeploymentFunc() diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/deployment_util_test.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/deployment_util_test.go index c8ce876df..1d90e848d 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/deployment_util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/deployment_util_test.go @@ -25,8 +25,8 @@ import ( "testing" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -53,7 +53,7 @@ func addListPodsReactor(fakeClient *fake.Clientset, obj runtime.Object) *fake.Cl } func addGetRSReactor(fakeClient *fake.Clientset, obj runtime.Object) *fake.Clientset { - rsList, ok := obj.(*extensions.ReplicaSetList) + rsList, ok := obj.(*apps.ReplicaSetList) fakeClient.AddReactor("get", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) { name := action.(core.GetAction).GetName() if ok { @@ -71,7 +71,7 @@ func addGetRSReactor(fakeClient *fake.Clientset, obj runtime.Object) *fake.Clien func addUpdateRSReactor(fakeClient *fake.Clientset) *fake.Clientset { fakeClient.AddReactor("update", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) { - obj := action.(core.UpdateAction).GetObject().(*extensions.ReplicaSet) + obj := action.(core.UpdateAction).GetObject().(*apps.ReplicaSet) return true, obj, nil }) return fakeClient @@ -85,13 +85,13 @@ func addUpdatePodsReactor(fakeClient *fake.Clientset) *fake.Clientset { return fakeClient } -func generateRSWithLabel(labels map[string]string, image string) extensions.ReplicaSet { - return extensions.ReplicaSet{ +func generateRSWithLabel(labels map[string]string, image string) apps.ReplicaSet { + return apps.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ Name: names.SimpleNameGenerator.GenerateName("replicaset"), Labels: labels, }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: func(i int32) *int32 { return &i }(1), Selector: &metav1.LabelSelector{MatchLabels: labels}, Template: v1.PodTemplateSpec{ @@ -113,10 +113,10 @@ func generateRSWithLabel(labels map[string]string, image string) extensions.Repl } } -func newDControllerRef(d *extensions.Deployment) *metav1.OwnerReference { +func newDControllerRef(d *apps.Deployment) *metav1.OwnerReference { isController := true return &metav1.OwnerReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "Deployment", Name: d.GetName(), UID: d.GetUID(), @@ -125,16 +125,16 @@ func newDControllerRef(d *extensions.Deployment) *metav1.OwnerReference { } // generateRS creates a replica set, with the input deployment's template as its template -func generateRS(deployment extensions.Deployment) extensions.ReplicaSet { +func generateRS(deployment apps.Deployment) apps.ReplicaSet { template := deployment.Spec.Template.DeepCopy() - return extensions.ReplicaSet{ + return apps.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ UID: randomUID(), Name: names.SimpleNameGenerator.GenerateName("replicaset"), Labels: template.Labels, OwnerReferences: []metav1.OwnerReference{*newDControllerRef(&deployment)}, }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: new(int32), Template: *template, Selector: &metav1.LabelSelector{MatchLabels: template.Labels}, @@ -147,15 +147,15 @@ func randomUID() types.UID { } // generateDeployment creates a deployment, with the input image as its template -func generateDeployment(image string) extensions.Deployment { +func generateDeployment(image string) apps.Deployment { podLabels := map[string]string{"name": image} terminationSec := int64(30) - return extensions.Deployment{ + return apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: image, Annotations: make(map[string]string), }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: func(i int32) *int32 { return &i }(1), Selector: &metav1.LabelSelector{MatchLabels: podLabels}, Template: v1.PodTemplateSpec{ @@ -188,14 +188,14 @@ func TestGetNewRS(t *testing.T) { tests := []struct { Name string objs []runtime.Object - expected *extensions.ReplicaSet + expected *apps.ReplicaSet }{ { "No new ReplicaSet", []runtime.Object{ &v1.PodList{}, - &extensions.ReplicaSetList{ - Items: []extensions.ReplicaSet{ + &apps.ReplicaSetList{ + Items: []apps.ReplicaSet{ generateRS(generateDeployment("foo")), generateRS(generateDeployment("bar")), }, @@ -207,8 +207,8 @@ func TestGetNewRS(t *testing.T) { "Has new ReplicaSet", []runtime.Object{ &v1.PodList{}, - &extensions.ReplicaSetList{ - Items: []extensions.ReplicaSet{ + &apps.ReplicaSetList{ + Items: []apps.ReplicaSet{ generateRS(generateDeployment("foo")), generateRS(generateDeployment("bar")), generateRS(generateDeployment("abc")), @@ -228,7 +228,7 @@ func TestGetNewRS(t *testing.T) { fakeClient = addListRSReactor(fakeClient, test.objs[1]) fakeClient = addUpdatePodsReactor(fakeClient) fakeClient = addUpdateRSReactor(fakeClient) - rs, err := GetNewReplicaSet(&newDeployment, fakeClient.ExtensionsV1beta1()) + rs, err := GetNewReplicaSet(&newDeployment, fakeClient.AppsV1()) if err != nil { t.Errorf("In test case %s, got unexpected error %v", test.Name, err) } @@ -262,13 +262,13 @@ func TestGetOldRSs(t *testing.T) { tests := []struct { Name string objs []runtime.Object - expected []*extensions.ReplicaSet + expected []*apps.ReplicaSet }{ { "No old ReplicaSets", []runtime.Object{ - &extensions.ReplicaSetList{ - Items: []extensions.ReplicaSet{ + &apps.ReplicaSetList{ + Items: []apps.ReplicaSet{ generateRS(generateDeployment("foo")), newRS, generateRS(generateDeployment("bar")), @@ -280,8 +280,8 @@ func TestGetOldRSs(t *testing.T) { { "Has old ReplicaSet", []runtime.Object{ - &extensions.ReplicaSetList{ - Items: []extensions.ReplicaSet{ + &apps.ReplicaSetList{ + Items: []apps.ReplicaSet{ oldRS2, oldRS, existedRS, @@ -291,7 +291,7 @@ func TestGetOldRSs(t *testing.T) { }, }, }, - []*extensions.ReplicaSet{&oldRS, &oldRS2}, + []*apps.ReplicaSet{&oldRS, &oldRS2}, }, } @@ -301,7 +301,7 @@ func TestGetOldRSs(t *testing.T) { fakeClient = addListRSReactor(fakeClient, test.objs[0]) fakeClient = addGetRSReactor(fakeClient, test.objs[0]) fakeClient = addUpdateRSReactor(fakeClient) - _, rss, err := GetOldReplicaSets(&newDeployment, fakeClient.ExtensionsV1beta1()) + _, rss, err := GetOldReplicaSets(&newDeployment, fakeClient.AppsV1()) if err != nil { t.Errorf("In test case %s, got unexpected error %v", test.Name, err) } @@ -340,44 +340,56 @@ func TestEqualIgnoreHash(t *testing.T) { }{ { "Same spec, same labels", - generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), - generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), true, }, { "Same spec, only pod-template-hash label value is different", - generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), - generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-2", "something": "else"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-2", "something": "else"}), true, }, { "Same spec, the former doesn't have pod-template-hash label", generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{"something": "else"}), - generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-2", "something": "else"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-2", "something": "else"}), true, }, + { + "Same spec, the label is different, the former doesn't have pod-template-hash label, same number of labels", + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{"something": "else"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-2"}), + false, + }, + { + "Same spec, the label is different, the latter doesn't have pod-template-hash label, same number of labels", + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-1"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{"something": "else"}), + false, + }, { "Same spec, the label is different, and the pod-template-hash label value is the same", - generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1"}), - generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-1"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), false, }, { "Different spec, same labels", - generatePodTemplateSpec("foo", "foo-node", map[string]string{"former": "value"}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), - generatePodTemplateSpec("foo", "foo-node", map[string]string{"latter": "value"}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{"former": "value"}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), + generatePodTemplateSpec("foo", "foo-node", map[string]string{"latter": "value"}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), false, }, { "Different spec, different pod-template-hash label value", - generatePodTemplateSpec("foo-1", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), - generatePodTemplateSpec("foo-2", "foo-node", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-2", "something": "else"}), + generatePodTemplateSpec("foo-1", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-1", "something": "else"}), + generatePodTemplateSpec("foo-2", "foo-node", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-2", "something": "else"}), false, }, { "Different spec, the former doesn't have pod-template-hash label", generatePodTemplateSpec("foo-1", "foo-node-1", map[string]string{}, map[string]string{"something": "else"}), - generatePodTemplateSpec("foo-2", "foo-node-2", map[string]string{}, map[string]string{extensions.DefaultDeploymentUniqueLabelKey: "value-2", "something": "else"}), + generatePodTemplateSpec("foo-2", "foo-node-2", map[string]string{}, map[string]string{apps.DefaultDeploymentUniqueLabelKey: "value-2", "something": "else"}), false, }, { @@ -419,11 +431,11 @@ func TestFindNewReplicaSet(t *testing.T) { deployment := generateDeployment("nginx") newRS := generateRS(deployment) - newRS.Labels[extensions.DefaultDeploymentUniqueLabelKey] = "hash" + newRS.Labels[apps.DefaultDeploymentUniqueLabelKey] = "hash" newRS.CreationTimestamp = later newRSDup := generateRS(deployment) - newRSDup.Labels[extensions.DefaultDeploymentUniqueLabelKey] = "different-hash" + newRSDup.Labels[apps.DefaultDeploymentUniqueLabelKey] = "different-hash" newRSDup.CreationTimestamp = now oldDeployment := generateDeployment("nginx") @@ -433,26 +445,26 @@ func TestFindNewReplicaSet(t *testing.T) { tests := []struct { Name string - deployment extensions.Deployment - rsList []*extensions.ReplicaSet - expected *extensions.ReplicaSet + deployment apps.Deployment + rsList []*apps.ReplicaSet + expected *apps.ReplicaSet }{ { Name: "Get new ReplicaSet with the same template as Deployment spec but different pod-template-hash value", deployment: deployment, - rsList: []*extensions.ReplicaSet{&newRS, &oldRS}, + rsList: []*apps.ReplicaSet{&newRS, &oldRS}, expected: &newRS, }, { Name: "Get the oldest new ReplicaSet when there are more than one ReplicaSet with the same template", deployment: deployment, - rsList: []*extensions.ReplicaSet{&newRS, &oldRS, &newRSDup}, + rsList: []*apps.ReplicaSet{&newRS, &oldRS, &newRSDup}, expected: &newRSDup, }, { Name: "Get nil new ReplicaSet", deployment: deployment, - rsList: []*extensions.ReplicaSet{&oldRS}, + rsList: []*apps.ReplicaSet{&oldRS}, expected: nil, }, } @@ -474,11 +486,11 @@ func TestFindOldReplicaSets(t *testing.T) { deployment := generateDeployment("nginx") newRS := generateRS(deployment) *(newRS.Spec.Replicas) = 1 - newRS.Labels[extensions.DefaultDeploymentUniqueLabelKey] = "hash" + newRS.Labels[apps.DefaultDeploymentUniqueLabelKey] = "hash" newRS.CreationTimestamp = later newRSDup := generateRS(deployment) - newRSDup.Labels[extensions.DefaultDeploymentUniqueLabelKey] = "different-hash" + newRSDup.Labels[apps.DefaultDeploymentUniqueLabelKey] = "different-hash" newRSDup.CreationTimestamp = now oldDeployment := generateDeployment("nginx") @@ -489,37 +501,37 @@ func TestFindOldReplicaSets(t *testing.T) { tests := []struct { Name string - deployment extensions.Deployment - rsList []*extensions.ReplicaSet + deployment apps.Deployment + rsList []*apps.ReplicaSet podList *v1.PodList - expected []*extensions.ReplicaSet - expectedRequire []*extensions.ReplicaSet + expected []*apps.ReplicaSet + expectedRequire []*apps.ReplicaSet }{ { Name: "Get old ReplicaSets", deployment: deployment, - rsList: []*extensions.ReplicaSet{&newRS, &oldRS}, - expected: []*extensions.ReplicaSet{&oldRS}, + rsList: []*apps.ReplicaSet{&newRS, &oldRS}, + expected: []*apps.ReplicaSet{&oldRS}, expectedRequire: nil, }, { Name: "Get old ReplicaSets with no new ReplicaSet", deployment: deployment, - rsList: []*extensions.ReplicaSet{&oldRS}, - expected: []*extensions.ReplicaSet{&oldRS}, + rsList: []*apps.ReplicaSet{&oldRS}, + expected: []*apps.ReplicaSet{&oldRS}, expectedRequire: nil, }, { Name: "Get old ReplicaSets with two new ReplicaSets, only the oldest new ReplicaSet is seen as new ReplicaSet", deployment: deployment, - rsList: []*extensions.ReplicaSet{&oldRS, &newRS, &newRSDup}, - expected: []*extensions.ReplicaSet{&oldRS, &newRS}, - expectedRequire: []*extensions.ReplicaSet{&newRS}, + rsList: []*apps.ReplicaSet{&oldRS, &newRS, &newRSDup}, + expected: []*apps.ReplicaSet{&oldRS, &newRS}, + expectedRequire: []*apps.ReplicaSet{&newRS}, }, { Name: "Get empty old ReplicaSets", deployment: deployment, - rsList: []*extensions.ReplicaSet{&newRS}, + rsList: []*apps.ReplicaSet{&newRS}, expected: nil, expectedRequire: nil, }, @@ -542,7 +554,7 @@ func TestFindOldReplicaSets(t *testing.T) { } // equal compares the equality of two ReplicaSet slices regardless of their ordering -func equal(rss1, rss2 []*extensions.ReplicaSet) bool { +func equal(rss1, rss2 []*apps.ReplicaSet) bool { if reflect.DeepEqual(rss1, rss2) { return true } @@ -571,19 +583,19 @@ func TestGetReplicaCountForReplicaSets(t *testing.T) { tests := []struct { Name string - sets []*extensions.ReplicaSet + sets []*apps.ReplicaSet expectedCount int32 expectedActual int32 }{ { "1:2 Replicas", - []*extensions.ReplicaSet{&rs1}, + []*apps.ReplicaSet{&rs1}, 1, 2, }, { "3:5 Replicas", - []*extensions.ReplicaSet{&rs1, &rs2}, + []*apps.ReplicaSet{&rs1, &rs2}, 3, 5, }, @@ -667,7 +679,7 @@ func TestResolveFenceposts(t *testing.T) { func TestNewRSNewReplicas(t *testing.T) { tests := []struct { Name string - strategyType extensions.DeploymentStrategyType + strategyType apps.DeploymentStrategyType depReplicas int32 newRSReplicas int32 maxSurge int @@ -675,17 +687,17 @@ func TestNewRSNewReplicas(t *testing.T) { }{ { "can not scale up - to newRSReplicas", - extensions.RollingUpdateDeploymentStrategyType, + apps.RollingUpdateDeploymentStrategyType, 1, 5, 1, 5, }, { "scale up - to depReplicas", - extensions.RollingUpdateDeploymentStrategyType, + apps.RollingUpdateDeploymentStrategyType, 6, 2, 10, 6, }, { "recreate - to depReplicas", - extensions.RecreateDeploymentStrategyType, + apps.RecreateDeploymentStrategyType, 3, 1, 1, 3, }, } @@ -697,8 +709,8 @@ func TestNewRSNewReplicas(t *testing.T) { for _, test := range tests { t.Run(test.Name, func(t *testing.T) { *(newDeployment.Spec.Replicas) = test.depReplicas - newDeployment.Spec.Strategy = extensions.DeploymentStrategy{Type: test.strategyType} - newDeployment.Spec.Strategy.RollingUpdate = &extensions.RollingUpdateDeployment{ + newDeployment.Spec.Strategy = apps.DeploymentStrategy{Type: test.strategyType} + newDeployment.Spec.Strategy.RollingUpdate = &apps.RollingUpdateDeployment{ MaxUnavailable: func(i int) *intstr.IntOrString { x := intstr.FromInt(i) return &x @@ -709,7 +721,7 @@ func TestNewRSNewReplicas(t *testing.T) { }(test.maxSurge), } *(newRC.Spec.Replicas) = test.newRSReplicas - rs, err := NewRSNewReplicas(&newDeployment, []*extensions.ReplicaSet{&rs5}, &newRC) + rs, err := NewRSNewReplicas(&newDeployment, []*apps.ReplicaSet{&rs5}, &newRC) if err != nil { t.Errorf("In test case %s, got unexpected error %v", test.Name, err) } @@ -721,33 +733,33 @@ func TestNewRSNewReplicas(t *testing.T) { } var ( - condProgressing = func() extensions.DeploymentCondition { - return extensions.DeploymentCondition{ - Type: extensions.DeploymentProgressing, + condProgressing = func() apps.DeploymentCondition { + return apps.DeploymentCondition{ + Type: apps.DeploymentProgressing, Status: v1.ConditionFalse, Reason: "ForSomeReason", } } - condProgressing2 = func() extensions.DeploymentCondition { - return extensions.DeploymentCondition{ - Type: extensions.DeploymentProgressing, + condProgressing2 = func() apps.DeploymentCondition { + return apps.DeploymentCondition{ + Type: apps.DeploymentProgressing, Status: v1.ConditionTrue, Reason: "BecauseItIs", } } - condAvailable = func() extensions.DeploymentCondition { - return extensions.DeploymentCondition{ - Type: extensions.DeploymentAvailable, + condAvailable = func() apps.DeploymentCondition { + return apps.DeploymentCondition{ + Type: apps.DeploymentAvailable, Status: v1.ConditionTrue, Reason: "AwesomeController", } } - status = func() *extensions.DeploymentStatus { - return &extensions.DeploymentStatus{ - Conditions: []extensions.DeploymentCondition{condProgressing(), condAvailable()}, + status = func() *apps.DeploymentStatus { + return &apps.DeploymentStatus{ + Conditions: []apps.DeploymentCondition{condProgressing(), condAvailable()}, } } ) @@ -758,8 +770,8 @@ func TestGetCondition(t *testing.T) { tests := []struct { name string - status extensions.DeploymentStatus - condType extensions.DeploymentConditionType + status apps.DeploymentStatus + condType apps.DeploymentConditionType expected bool }{ @@ -767,7 +779,7 @@ func TestGetCondition(t *testing.T) { name: "condition exists", status: *exampleStatus, - condType: extensions.DeploymentAvailable, + condType: apps.DeploymentAvailable, expected: true, }, @@ -775,7 +787,7 @@ func TestGetCondition(t *testing.T) { name: "condition does not exist", status: *exampleStatus, - condType: extensions.DeploymentReplicaFailure, + condType: apps.DeploymentReplicaFailure, expected: false, }, @@ -796,23 +808,23 @@ func TestSetCondition(t *testing.T) { tests := []struct { name string - status *extensions.DeploymentStatus - cond extensions.DeploymentCondition + status *apps.DeploymentStatus + cond apps.DeploymentCondition - expectedStatus *extensions.DeploymentStatus + expectedStatus *apps.DeploymentStatus }{ { name: "set for the first time", - status: &extensions.DeploymentStatus{}, + status: &apps.DeploymentStatus{}, cond: condAvailable(), - expectedStatus: &extensions.DeploymentStatus{Conditions: []extensions.DeploymentCondition{condAvailable()}}, + expectedStatus: &apps.DeploymentStatus{Conditions: []apps.DeploymentCondition{condAvailable()}}, }, { name: "simple set", - status: &extensions.DeploymentStatus{Conditions: []extensions.DeploymentCondition{condProgressing()}}, + status: &apps.DeploymentStatus{Conditions: []apps.DeploymentCondition{condProgressing()}}, cond: condAvailable(), expectedStatus: status(), @@ -820,10 +832,10 @@ func TestSetCondition(t *testing.T) { { name: "overwrite", - status: &extensions.DeploymentStatus{Conditions: []extensions.DeploymentCondition{condProgressing()}}, + status: &apps.DeploymentStatus{Conditions: []apps.DeploymentCondition{condProgressing()}}, cond: condProgressing2(), - expectedStatus: &extensions.DeploymentStatus{Conditions: []extensions.DeploymentCondition{condProgressing2()}}, + expectedStatus: &apps.DeploymentStatus{Conditions: []apps.DeploymentCondition{condProgressing2()}}, }, } @@ -841,32 +853,32 @@ func TestRemoveCondition(t *testing.T) { tests := []struct { name string - status *extensions.DeploymentStatus - condType extensions.DeploymentConditionType + status *apps.DeploymentStatus + condType apps.DeploymentConditionType - expectedStatus *extensions.DeploymentStatus + expectedStatus *apps.DeploymentStatus }{ { name: "remove from empty status", - status: &extensions.DeploymentStatus{}, - condType: extensions.DeploymentProgressing, + status: &apps.DeploymentStatus{}, + condType: apps.DeploymentProgressing, - expectedStatus: &extensions.DeploymentStatus{}, + expectedStatus: &apps.DeploymentStatus{}, }, { name: "simple remove", - status: &extensions.DeploymentStatus{Conditions: []extensions.DeploymentCondition{condProgressing()}}, - condType: extensions.DeploymentProgressing, + status: &apps.DeploymentStatus{Conditions: []apps.DeploymentCondition{condProgressing()}}, + condType: apps.DeploymentProgressing, - expectedStatus: &extensions.DeploymentStatus{}, + expectedStatus: &apps.DeploymentStatus{}, }, { name: "doesn't remove anything", status: status(), - condType: extensions.DeploymentReplicaFailure, + condType: apps.DeploymentReplicaFailure, expectedStatus: status(), }, @@ -883,19 +895,19 @@ func TestRemoveCondition(t *testing.T) { } func TestDeploymentComplete(t *testing.T) { - deployment := func(desired, current, updated, available, maxUnavailable, maxSurge int32) *extensions.Deployment { - return &extensions.Deployment{ - Spec: extensions.DeploymentSpec{ + deployment := func(desired, current, updated, available, maxUnavailable, maxSurge int32) *apps.Deployment { + return &apps.Deployment{ + Spec: apps.DeploymentSpec{ Replicas: &desired, - Strategy: extensions.DeploymentStrategy{ - RollingUpdate: &extensions.RollingUpdateDeployment{ + Strategy: apps.DeploymentStrategy{ + RollingUpdate: &apps.RollingUpdateDeployment{ MaxUnavailable: func(i int) *intstr.IntOrString { x := intstr.FromInt(i); return &x }(int(maxUnavailable)), MaxSurge: func(i int) *intstr.IntOrString { x := intstr.FromInt(i); return &x }(int(maxSurge)), }, - Type: extensions.RollingUpdateDeploymentStrategyType, + Type: apps.RollingUpdateDeploymentStrategyType, }, }, - Status: extensions.DeploymentStatus{ + Status: apps.DeploymentStatus{ Replicas: current, UpdatedReplicas: updated, AvailableReplicas: available, @@ -906,7 +918,7 @@ func TestDeploymentComplete(t *testing.T) { tests := []struct { name string - d *extensions.Deployment + d *apps.Deployment expected bool }{ @@ -960,9 +972,9 @@ func TestDeploymentComplete(t *testing.T) { } func TestDeploymentProgressing(t *testing.T) { - deployment := func(current, updated, ready, available int32) *extensions.Deployment { - return &extensions.Deployment{ - Status: extensions.DeploymentStatus{ + deployment := func(current, updated, ready, available int32) *apps.Deployment { + return &apps.Deployment{ + Status: apps.DeploymentStatus{ Replicas: current, UpdatedReplicas: updated, ReadyReplicas: ready, @@ -970,8 +982,8 @@ func TestDeploymentProgressing(t *testing.T) { }, } } - newStatus := func(current, updated, ready, available int32) extensions.DeploymentStatus { - return extensions.DeploymentStatus{ + newStatus := func(current, updated, ready, available int32) apps.DeploymentStatus { + return apps.DeploymentStatus{ Replicas: current, UpdatedReplicas: updated, ReadyReplicas: ready, @@ -982,8 +994,8 @@ func TestDeploymentProgressing(t *testing.T) { tests := []struct { name string - d *extensions.Deployment - newStatus extensions.DeploymentStatus + d *apps.Deployment + newStatus apps.DeploymentStatus expected bool }{ @@ -1063,13 +1075,13 @@ func TestDeploymentTimedOut(t *testing.T) { timeFn := func(min, sec int) time.Time { return time.Date(2016, 1, 1, 0, min, sec, 0, time.UTC) } - deployment := func(condType extensions.DeploymentConditionType, status v1.ConditionStatus, reason string, pds *int32, from time.Time) extensions.Deployment { - return extensions.Deployment{ - Spec: extensions.DeploymentSpec{ + deployment := func(condType apps.DeploymentConditionType, status v1.ConditionStatus, reason string, pds *int32, from time.Time) apps.Deployment { + return apps.Deployment{ + Spec: apps.DeploymentSpec{ ProgressDeadlineSeconds: pds, }, - Status: extensions.DeploymentStatus{ - Conditions: []extensions.DeploymentCondition{ + Status: apps.DeploymentStatus{ + Conditions: []apps.DeploymentCondition{ { Type: condType, Status: status, @@ -1084,7 +1096,7 @@ func TestDeploymentTimedOut(t *testing.T) { tests := []struct { name string - d extensions.Deployment + d apps.Deployment nowFn func() time.Time expected bool @@ -1092,28 +1104,28 @@ func TestDeploymentTimedOut(t *testing.T) { { name: "no progressDeadlineSeconds specified - no timeout", - d: deployment(extensions.DeploymentProgressing, v1.ConditionTrue, "", null, timeFn(1, 9)), + d: deployment(apps.DeploymentProgressing, v1.ConditionTrue, "", null, timeFn(1, 9)), nowFn: func() time.Time { return timeFn(1, 20) }, expected: false, }, { name: "progressDeadlineSeconds: 10s, now - started => 00:01:20 - 00:01:09 => 11s", - d: deployment(extensions.DeploymentProgressing, v1.ConditionTrue, "", &ten, timeFn(1, 9)), + d: deployment(apps.DeploymentProgressing, v1.ConditionTrue, "", &ten, timeFn(1, 9)), nowFn: func() time.Time { return timeFn(1, 20) }, expected: true, }, { name: "progressDeadlineSeconds: 10s, now - started => 00:01:20 - 00:01:11 => 9s", - d: deployment(extensions.DeploymentProgressing, v1.ConditionTrue, "", &ten, timeFn(1, 11)), + d: deployment(apps.DeploymentProgressing, v1.ConditionTrue, "", &ten, timeFn(1, 11)), nowFn: func() time.Time { return timeFn(1, 20) }, expected: false, }, { name: "previous status was a complete deployment", - d: deployment(extensions.DeploymentProgressing, v1.ConditionTrue, NewRSAvailableReason, nil, time.Time{}), + d: deployment(apps.DeploymentProgressing, v1.ConditionTrue, NewRSAvailableReason, nil, time.Time{}), expected: false, }, } @@ -1129,23 +1141,23 @@ func TestDeploymentTimedOut(t *testing.T) { } func TestMaxUnavailable(t *testing.T) { - deployment := func(replicas int32, maxUnavailable intstr.IntOrString) extensions.Deployment { - return extensions.Deployment{ - Spec: extensions.DeploymentSpec{ + deployment := func(replicas int32, maxUnavailable intstr.IntOrString) apps.Deployment { + return apps.Deployment{ + Spec: apps.DeploymentSpec{ Replicas: func(i int32) *int32 { return &i }(replicas), - Strategy: extensions.DeploymentStrategy{ - RollingUpdate: &extensions.RollingUpdateDeployment{ + Strategy: apps.DeploymentStrategy{ + RollingUpdate: &apps.RollingUpdateDeployment{ MaxSurge: func(i int) *intstr.IntOrString { x := intstr.FromInt(i); return &x }(int(1)), MaxUnavailable: &maxUnavailable, }, - Type: extensions.RollingUpdateDeploymentStrategyType, + Type: apps.RollingUpdateDeploymentStrategyType, }, }, } } tests := []struct { name string - deployment extensions.Deployment + deployment apps.Deployment expected int32 }{ { @@ -1170,10 +1182,10 @@ func TestMaxUnavailable(t *testing.T) { }, { name: "maxUnavailable with Recreate deployment strategy", - deployment: extensions.Deployment{ - Spec: extensions.DeploymentSpec{ - Strategy: extensions.DeploymentStrategy{ - Type: extensions.RecreateDeploymentStrategyType, + deployment: apps.Deployment{ + Spec: apps.DeploymentSpec{ + Strategy: apps.DeploymentStrategy{ + Type: apps.RecreateDeploymentStrategyType, }, }, }, @@ -1265,3 +1277,77 @@ func TestAnnotationUtils(t *testing.T) { }) //Tear Down } + +func TestReplicasAnnotationsNeedUpdate(t *testing.T) { + + desiredReplicas := fmt.Sprintf("%d", int32(10)) + maxReplicas := fmt.Sprintf("%d", int32(20)) + + tests := []struct { + name string + replicaSet *apps.ReplicaSet + expected bool + }{ + { + name: "test Annotations nil", + replicaSet: &apps.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, + Spec: apps.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + expected: true, + }, + { + name: "test desiredReplicas update", + replicaSet: &apps.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "hello", + Namespace: "test", + Annotations: map[string]string{DesiredReplicasAnnotation: "8", MaxReplicasAnnotation: maxReplicas}, + }, + Spec: apps.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + expected: true, + }, + { + name: "test maxReplicas update", + replicaSet: &apps.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "hello", + Namespace: "test", + Annotations: map[string]string{DesiredReplicasAnnotation: desiredReplicas, MaxReplicasAnnotation: "16"}, + }, + Spec: apps.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + expected: true, + }, + { + name: "test needn't update", + replicaSet: &apps.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "hello", + Namespace: "test", + Annotations: map[string]string{DesiredReplicasAnnotation: desiredReplicas, MaxReplicasAnnotation: maxReplicas}, + }, + Spec: apps.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + expected: false, + }, + } + + for i, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := ReplicasAnnotationsNeedUpdate(test.replicaSet, 10, 20) + if result != test.expected { + t.Errorf("case[%d]:%s Expected %v, Got: %v", i, test.name, test.expected, result) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/replicaset_util.go b/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/replicaset_util.go index a0db8242e..bf05a5927 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/replicaset_util.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/deployment/util/replicaset_util.go @@ -17,27 +17,23 @@ limitations under the License. package util import ( - "fmt" - "github.com/golang/glog" - extensions "k8s.io/api/extensions/v1beta1" + apps "k8s.io/api/apps/v1" errorsutil "k8s.io/apimachinery/pkg/util/errors" - unversionedextensions "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" - extensionslisters "k8s.io/client-go/listers/extensions/v1beta1" + appsclient "k8s.io/client-go/kubernetes/typed/apps/v1" + appslisters "k8s.io/client-go/listers/apps/v1" "k8s.io/client-go/util/retry" - "k8s.io/kubernetes/pkg/controller" - labelsutil "k8s.io/kubernetes/pkg/util/labels" ) // TODO: use client library instead when it starts to support update retries // see https://github.com/kubernetes/kubernetes/issues/21479 -type updateRSFunc func(rs *extensions.ReplicaSet) error +type updateRSFunc func(rs *apps.ReplicaSet) error // UpdateRSWithRetries updates a RS with given applyUpdate function. Note that RS not found error is ignored. // The returned bool value can be used to tell if the RS is actually updated. -func UpdateRSWithRetries(rsClient unversionedextensions.ReplicaSetInterface, rsLister extensionslisters.ReplicaSetLister, namespace, name string, applyUpdate updateRSFunc) (*extensions.ReplicaSet, error) { - var rs *extensions.ReplicaSet +func UpdateRSWithRetries(rsClient appsclient.ReplicaSetInterface, rsLister appslisters.ReplicaSetLister, namespace, name string, applyUpdate updateRSFunc) (*apps.ReplicaSet, error) { + var rs *apps.ReplicaSet retryErr := retry.RetryOnConflict(retry.DefaultBackoff, func() error { var err error @@ -62,10 +58,3 @@ func UpdateRSWithRetries(rsClient unversionedextensions.ReplicaSetInterface, rsL return rs, retryErr } - -// GetReplicaSetHash returns the pod template hash of a ReplicaSet's pod template space -func GetReplicaSetHash(rs *extensions.ReplicaSet, uniquifier *int32) (string, error) { - rsTemplate := rs.Spec.Template.DeepCopy() - rsTemplate.Labels = labelsutil.CloneAndRemoveLabel(rsTemplate.Labels, extensions.DefaultDeploymentUniqueLabelKey) - return fmt.Sprintf("%d", controller.ComputeHash(rsTemplate, uniquifier)), nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/disruption/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/disruption/BUILD index f210ecb10..f3224e1f9 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/disruption/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/disruption/BUILD @@ -47,7 +47,6 @@ go_test( srcs = ["disruption_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core/install:go_default_library", "//pkg/controller:go_default_library", "//vendor/github.com/Azure/go-autorest/autorest/to:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/disruption/disruption.go b/vendor/k8s.io/kubernetes/pkg/controller/disruption/disruption.go index 6ec9663fd..b6ae484a8 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/disruption/disruption.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/disruption/disruption.go @@ -294,7 +294,7 @@ func (dc *DisruptionController) Run(stopCh <-chan struct{}) { if dc.kubeClient != nil { glog.Infof("Sending events to api server.") - dc.broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(dc.kubeClient.CoreV1().RESTClient()).Events("")}) + dc.broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: dc.kubeClient.CoreV1().Events("")}) } else { glog.Infof("No api server defined - no events will be sent to API server.") } @@ -471,7 +471,7 @@ func (dc *DisruptionController) processNextRecheckWorkItem() bool { func (dc *DisruptionController) sync(key string) error { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing PodDisruptionBudget %q (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing PodDisruptionBudget %q (%v)", key, time.Since(startTime)) }() namespace, name, err := cache.SplitMetaNamespaceKey(key) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/disruption/disruption_test.go b/vendor/k8s.io/kubernetes/pkg/controller/disruption/disruption_test.go index b64a7a10c..734266977 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/disruption/disruption_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/disruption/disruption_test.go @@ -33,7 +33,6 @@ import ( "k8s.io/client-go/informers" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" - "k8s.io/kubernetes/pkg/api/legacyscheme" _ "k8s.io/kubernetes/pkg/apis/core/install" "k8s.io/kubernetes/pkg/controller" @@ -142,7 +141,7 @@ func newSelFooBar() *metav1.LabelSelector { func newMinAvailablePodDisruptionBudget(t *testing.T, minAvailable intstr.IntOrString) (*policy.PodDisruptionBudget, string) { pdb := &policy.PodDisruptionBudget{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: "foobar", @@ -165,7 +164,7 @@ func newMinAvailablePodDisruptionBudget(t *testing.T, minAvailable intstr.IntOrS func newMaxUnavailablePodDisruptionBudget(t *testing.T, maxUnavailable intstr.IntOrString) (*policy.PodDisruptionBudget, string) { pdb := &policy.PodDisruptionBudget{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: "foobar", @@ -210,7 +209,7 @@ func updatePodOwnerToSs(t *testing.T, pod *v1.Pod, ss *apps.StatefulSet) { func newPod(t *testing.T, name string) (*v1.Pod, string) { pod := &v1.Pod{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Annotations: make(map[string]string), @@ -237,7 +236,7 @@ func newPod(t *testing.T, name string) (*v1.Pod, string) { func newReplicationController(t *testing.T, size int32) (*v1.ReplicationController, string) { rc := &v1.ReplicationController{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: "foobar", @@ -261,7 +260,7 @@ func newReplicationController(t *testing.T, size int32) (*v1.ReplicationControll func newDeployment(t *testing.T, size int32) (*extensions.Deployment, string) { d := &extensions.Deployment{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: "foobar", @@ -285,7 +284,7 @@ func newDeployment(t *testing.T, size int32) (*extensions.Deployment, string) { func newReplicaSet(t *testing.T, size int32) (*extensions.ReplicaSet, string) { rs := &extensions.ReplicaSet{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: "foobar", @@ -309,7 +308,7 @@ func newReplicaSet(t *testing.T, size int32) (*extensions.ReplicaSet, string) { func newStatefulSet(t *testing.T, size int32) (*apps.StatefulSet, string) { ss := &apps.StatefulSet{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: "foobar", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/endpoint/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/endpoint/BUILD index 27e74d323..c5c899e80 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/endpoint/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/endpoint/BUILD @@ -42,7 +42,6 @@ go_test( srcs = ["endpoints_controller_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/v1/endpoints:go_default_library", "//pkg/apis/core:go_default_library", @@ -50,6 +49,7 @@ go_test( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/endpoint/OWNERS b/vendor/k8s.io/kubernetes/pkg/controller/endpoint/OWNERS index d830b4e1b..14351bb3a 100755 --- a/vendor/k8s.io/kubernetes/pkg/controller/endpoint/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/controller/endpoint/OWNERS @@ -1,5 +1,10 @@ +approvers: +- bowei +- MrHohn +- thockin +- matchstick reviewers: -- bowei +- bowei - MrHohn - thockin - matchstick diff --git a/vendor/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller.go index a0ae0e4e8..dbce2630f 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller.go @@ -64,7 +64,7 @@ const ( // containers in the pod and marks it "Running", till the kubelet stops all // containers and deletes the pod from the apiserver. // This field is deprecated. v1.Service.PublishNotReadyAddresses will replace it - // subsequent releases. + // subsequent releases. It will be removed no sooner than 1.13. TolerateUnreadyEndpointsAnnotation = "service.alpha.kubernetes.io/tolerate-unready-endpoints" ) @@ -372,7 +372,7 @@ func (e *EndpointController) handleErr(err error, key interface{}) { } if e.queue.NumRequeues(key) < maxRetries { - glog.V(2).Infof("Error syncing endpoints for service %q: %v", key, err) + glog.V(2).Infof("Error syncing endpoints for service %q, retrying. Error: %v", key, err) e.queue.AddRateLimited(key) return } @@ -385,7 +385,7 @@ func (e *EndpointController) handleErr(err error, key interface{}) { func (e *EndpointController) syncService(key string) error { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing service %q endpoints. (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing service %q endpoints. (%v)", key, time.Since(startTime)) }() namespace, name, err := cache.SplitMetaNamespaceKey(key) @@ -420,7 +420,8 @@ func (e *EndpointController) syncService(key string) error { return err } - var tolerateUnreadyEndpoints bool + // If the user specified the older (deprecated) annotation, we have to respect it. + tolerateUnreadyEndpoints := service.Spec.PublishNotReadyAddresses if v, ok := service.Annotations[TolerateUnreadyEndpointsAnnotation]; ok { b, err := strconv.ParseBool(v) if err == nil { @@ -454,8 +455,8 @@ func (e *EndpointController) syncService(key string) error { // Allow headless service not to have ports. if len(service.Spec.Ports) == 0 { if service.Spec.ClusterIP == api.ClusterIPNone { - epp := v1.EndpointPort{Port: 0, Protocol: v1.ProtocolTCP} - subsets, totalReadyEps, totalNotReadyEps = addEndpointSubset(subsets, pod, epa, epp, tolerateUnreadyEndpoints) + subsets, totalReadyEps, totalNotReadyEps = addEndpointSubset(subsets, pod, epa, nil, tolerateUnreadyEndpoints) + // No need to repack subsets for headless service without ports. } } else { for i := range service.Spec.Ports { @@ -470,14 +471,14 @@ func (e *EndpointController) syncService(key string) error { } var readyEps, notReadyEps int - epp := v1.EndpointPort{Name: portName, Port: int32(portNum), Protocol: portProto} + epp := &v1.EndpointPort{Name: portName, Port: int32(portNum), Protocol: portProto} subsets, readyEps, notReadyEps = addEndpointSubset(subsets, pod, epa, epp, tolerateUnreadyEndpoints) totalReadyEps = totalReadyEps + readyEps totalNotReadyEps = totalNotReadyEps + notReadyEps } + subsets = endpoints.RepackSubsets(subsets) } } - subsets = endpoints.RepackSubsets(subsets) // See if there's actually an update here. currentEndpoints, err := e.endpointsLister.Endpoints(service.Namespace).Get(service.Name) @@ -561,20 +562,24 @@ func (e *EndpointController) checkLeftoverEndpoints() { } func addEndpointSubset(subsets []v1.EndpointSubset, pod *v1.Pod, epa v1.EndpointAddress, - epp v1.EndpointPort, tolerateUnreadyEndpoints bool) ([]v1.EndpointSubset, int, int) { + epp *v1.EndpointPort, tolerateUnreadyEndpoints bool) ([]v1.EndpointSubset, int, int) { var readyEps int = 0 var notReadyEps int = 0 + ports := []v1.EndpointPort{} + if epp != nil { + ports = append(ports, *epp) + } if tolerateUnreadyEndpoints || podutil.IsPodReady(pod) { subsets = append(subsets, v1.EndpointSubset{ Addresses: []v1.EndpointAddress{epa}, - Ports: []v1.EndpointPort{epp}, + Ports: ports, }) readyEps++ } else if shouldPodBeInEndpoints(pod) { glog.V(5).Infof("Pod is out of service: %s/%s", pod.Namespace, pod.Name) subsets = append(subsets, v1.EndpointSubset{ NotReadyAddresses: []v1.EndpointAddress{epa}, - Ports: []v1.EndpointPort{epp}, + Ports: ports, }) notReadyEps++ } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller_test.go index 49e786d9c..0f9f2d319 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" @@ -34,7 +35,6 @@ import ( restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" utiltesting "k8s.io/client-go/util/testing" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" endptspkg "k8s.io/kubernetes/pkg/api/v1/endpoints" api "k8s.io/kubernetes/pkg/apis/core" @@ -48,7 +48,7 @@ var emptyNodeName string func addPods(store cache.Store, namespace string, nPods int, nPorts int, nNotReady int) { for i := 0; i < nPods+nNotReady; i++ { p := &v1.Pod{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: fmt.Sprintf("pod%d", i), @@ -81,7 +81,7 @@ func addPods(store cache.Store, namespace string, nPods int, nPorts int, nNotRea func addNotReadyPodsWithSpecifiedRestartPolicyAndPhase(store cache.Store, namespace string, nPods int, nPorts int, restartPolicy v1.RestartPolicy, podPhase v1.PodPhase) { for i := 0; i < nPods; i++ { p := &v1.Pod{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: fmt.Sprintf("pod%d", i), @@ -110,11 +110,6 @@ func addNotReadyPodsWithSpecifiedRestartPolicyAndPhase(store cache.Store, namesp } } -type serverResponse struct { - statusCode int - obj interface{} -} - func makeTestServer(t *testing.T, namespace string) (*httptest.Server, *utiltesting.FakeHandler) { fakeEndpointsHandler := utiltesting.FakeHandler{ StatusCode: http.StatusOK, @@ -138,7 +133,7 @@ type endpointController struct { } func newController(url string) *endpointController { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: url, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: url, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc()) endpoints := NewEndpointController(informerFactory.Core().V1().Pods(), informerFactory.Core().V1().Services(), informerFactory.Core().V1().Endpoints(), client) @@ -753,7 +748,7 @@ func TestSyncEndpointsHeadlessService(t *testing.T) { }, Subsets: []v1.EndpointSubset{{ Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", NodeName: &emptyNodeName, TargetRef: &v1.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, - Ports: []v1.EndpointPort{{Port: 0, Protocol: "TCP"}}, + Ports: []v1.EndpointPort{}, }}, }) endpointsHandler.ValidateRequestCount(t, 1) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/BUILD index 1ef247e24..37f439ed7 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/BUILD @@ -54,13 +54,12 @@ go_test( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core/install:go_default_library", - "//pkg/controller/garbagecollector/metaonly:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/garbagecollector.go b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/garbagecollector.go index 93a96c20f..644949eca 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/garbagecollector.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/garbagecollector.go @@ -32,6 +32,7 @@ import ( "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" @@ -59,10 +60,8 @@ const ResourceResyncTime time.Duration = 0 // ensures that the garbage collector operates with a graph that is at least as // up to date as the notification is sent. type GarbageCollector struct { - restMapper resettableRESTMapper - // clientPool uses the regular dynamicCodec. We need it to update - // finalizers. It can be removed if we support patching finalizers. - clientPool dynamic.ClientPool + restMapper resettableRESTMapper + dynamicClient dynamic.Interface // garbage collector attempts to delete the items in attemptToDelete queue when the time is ripe. attemptToDelete workqueue.RateLimitingInterface // garbage collector attempts to orphan the dependents of the items in the attemptToOrphan queue, then deletes the items. @@ -76,8 +75,7 @@ type GarbageCollector struct { } func NewGarbageCollector( - metaOnlyClientPool dynamic.ClientPool, - clientPool dynamic.ClientPool, + dynamicClient dynamic.Interface, mapper resettableRESTMapper, deletableResources map[schema.GroupVersionResource]struct{}, ignoredResources map[schema.GroupResource]struct{}, @@ -88,17 +86,17 @@ func NewGarbageCollector( attemptToOrphan := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "garbage_collector_attempt_to_orphan") absentOwnerCache := NewUIDCache(500) gc := &GarbageCollector{ - clientPool: clientPool, + dynamicClient: dynamicClient, restMapper: mapper, attemptToDelete: attemptToDelete, attemptToOrphan: attemptToOrphan, absentOwnerCache: absentOwnerCache, } gb := &GraphBuilder{ - metaOnlyClientPool: metaOnlyClientPool, - informersStarted: informersStarted, - restMapper: mapper, - graphChanges: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "garbage_collector_graph_changes"), + dynamicClient: dynamicClient, + informersStarted: informersStarted, + restMapper: mapper, + graphChanges: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "garbage_collector_graph_changes"), uidToNode: &concurrentUIDToNode{ uidToNode: make(map[types.UID]*node), }, @@ -173,10 +171,8 @@ func (gc *GarbageCollector) Sync(discoveryClient discovery.ServerResourcesInterf newResources := GetDeletableResources(discoveryClient) // This can occur if there is an internal error in GetDeletableResources. - // If the gc attempts to sync with 0 resources it will block forever. - // TODO: Implement a more complete solution for the garbage collector hanging. if len(newResources) == 0 { - glog.V(5).Infof("no resources reported by discovery, skipping garbage collector sync") + glog.V(2).Infof("no resources reported by discovery, skipping garbage collector sync") return } @@ -186,39 +182,61 @@ func (gc *GarbageCollector) Sync(discoveryClient discovery.ServerResourcesInterf return } - // Something has changed, time to sync. - glog.V(2).Infof("syncing garbage collector with updated resources from discovery: %v", newResources) - // Ensure workers are paused to avoid processing events before informers // have resynced. gc.workerLock.Lock() defer gc.workerLock.Unlock() - // Resetting the REST mapper will also invalidate the underlying discovery - // client. This is a leaky abstraction and assumes behavior about the REST - // mapper, but we'll deal with it for now. - gc.restMapper.Reset() - - // Perform the monitor resync and wait for controllers to report cache sync. - // - // NOTE: It's possible that newResources will diverge from the resources - // discovered by restMapper during the call to Reset, since they are - // distinct discovery clients invalidated at different times. For example, - // newResources may contain resources not returned in the restMapper's - // discovery call if the resources appeared in-between the calls. In that - // case, the restMapper will fail to map some of newResources until the next - // sync period. - if err := gc.resyncMonitors(newResources); err != nil { - utilruntime.HandleError(fmt.Errorf("failed to sync resource monitors: %v", err)) - return - } - // TODO: WaitForCacheSync can block forever during normal operation. Could - // pass a timeout channel, but we have to consider the implications of - // un-pausing the GC with a partially synced graph builder. - if !controller.WaitForCacheSync("garbage collector", stopCh, gc.dependencyGraphBuilder.IsSynced) { - utilruntime.HandleError(fmt.Errorf("timed out waiting for dependency graph builder sync during GC sync")) - return - } + // Once we get here, we should not unpause workers until we've successfully synced + attempt := 0 + wait.PollImmediateUntil(100*time.Millisecond, func() (bool, error) { + attempt++ + + // On a reattempt, check if available resources have changed + if attempt > 1 { + newResources = GetDeletableResources(discoveryClient) + if len(newResources) == 0 { + glog.V(2).Infof("no resources reported by discovery (attempt %d)", attempt) + return false, nil + } + } + + glog.V(2).Infof("syncing garbage collector with updated resources from discovery (attempt %d): %s", attempt, printDiff(oldResources, newResources)) + + // Resetting the REST mapper will also invalidate the underlying discovery + // client. This is a leaky abstraction and assumes behavior about the REST + // mapper, but we'll deal with it for now. + gc.restMapper.Reset() + glog.V(4).Infof("reset restmapper") + + // Perform the monitor resync and wait for controllers to report cache sync. + // + // NOTE: It's possible that newResources will diverge from the resources + // discovered by restMapper during the call to Reset, since they are + // distinct discovery clients invalidated at different times. For example, + // newResources may contain resources not returned in the restMapper's + // discovery call if the resources appeared in-between the calls. In that + // case, the restMapper will fail to map some of newResources until the next + // attempt. + if err := gc.resyncMonitors(newResources); err != nil { + utilruntime.HandleError(fmt.Errorf("failed to sync resource monitors (attempt %d): %v", attempt, err)) + return false, nil + } + glog.V(4).Infof("resynced monitors") + + // wait for caches to fill for a while (our sync period) before attempting to rediscover resources and retry syncing. + // this protects us from deadlocks where available resources changed and one of our informer caches will never fill. + // informers keep attempting to sync in the background, so retrying doesn't interrupt them. + // the call to resyncMonitors on the reattempt will no-op for resources that still exist. + // note that workers stay paused until we successfully resync. + if !controller.WaitForCacheSync("garbage collector", waitForStopOrTimeout(stopCh, period), gc.dependencyGraphBuilder.IsSynced) { + utilruntime.HandleError(fmt.Errorf("timed out waiting for dependency graph builder sync during GC sync (attempt %d)", attempt)) + return false, nil + } + + // success, break out of the loop + return true, nil + }, stopCh) // Finally, keep track of our new state. Do this after all preceding steps // have succeeded to ensure we'll retry on subsequent syncs if an error @@ -228,6 +246,36 @@ func (gc *GarbageCollector) Sync(discoveryClient discovery.ServerResourcesInterf }, period, stopCh) } +// printDiff returns a human-readable summary of what resources were added and removed +func printDiff(oldResources, newResources map[schema.GroupVersionResource]struct{}) string { + removed := sets.NewString() + for oldResource := range oldResources { + if _, ok := newResources[oldResource]; !ok { + removed.Insert(fmt.Sprintf("%+v", oldResource)) + } + } + added := sets.NewString() + for newResource := range newResources { + if _, ok := oldResources[newResource]; !ok { + added.Insert(fmt.Sprintf("%+v", newResource)) + } + } + return fmt.Sprintf("added: %v, removed: %v", added.List(), removed.List()) +} + +// waitForStopOrTimeout returns a stop channel that closes when the provided stop channel closes or when the specified timeout is reached +func waitForStopOrTimeout(stopCh <-chan struct{}, timeout time.Duration) <-chan struct{} { + stopChWithTimeout := make(chan struct{}) + go func() { + select { + case <-stopCh: + case <-time.After(timeout): + } + close(stopChWithTimeout) + }() + return stopChWithTimeout +} + func (gc *GarbageCollector) IsSynced() bool { return gc.dependencyGraphBuilder.IsSynced() } @@ -291,19 +339,15 @@ func (gc *GarbageCollector) isDangling(reference metav1.OwnerReference, item *no // ii) should update the object to remove such references. This is to // prevent objects having references to an old resource from being // deleted during a cluster upgrade. - fqKind := schema.FromAPIVersionAndKind(reference.APIVersion, reference.Kind) - client, err := gc.clientPool.ClientForGroupVersionKind(fqKind) - if err != nil { - return false, nil, err - } - resource, err := gc.apiResource(reference.APIVersion, reference.Kind) + resource, namespaced, err := gc.apiResource(reference.APIVersion, reference.Kind) if err != nil { return false, nil, err } + // TODO: It's only necessary to talk to the API server if the owner node // is a "virtual" node. The local graph could lag behind the real // status, but in practice, the difference is small. - owner, err = client.Resource(resource, item.identity.Namespace).Get(reference.Name, metav1.GetOptions{}) + owner, err = gc.dynamicClient.Resource(resource).Namespace(resourceDefaultNamespace(namespaced, item.identity.Namespace)).Get(reference.Name, metav1.GetOptions{}) switch { case errors.IsNotFound(err): gc.absentOwnerCache.Add(reference.UID) @@ -424,8 +468,11 @@ func (gc *GarbageCollector) attemptToDeleteItem(item *node) error { // waitingForDependentsDeletion needs to be deleted from the // ownerReferences, otherwise the referenced objects will be stuck with // the FinalizerDeletingDependents and never get deleted. - patch := deleteOwnerRefPatch(item.identity.UID, append(ownerRefsToUIDs(dangling), ownerRefsToUIDs(waitingForDependentsDeletion)...)...) - _, err = gc.patchObject(item.identity, patch) + ownerUIDs := append(ownerRefsToUIDs(dangling), ownerRefsToUIDs(waitingForDependentsDeletion)...) + patch := deleteOwnerRefStrategicMergePatch(item.identity.UID, ownerUIDs...) + _, err = gc.patch(item, patch, func(n *node) ([]byte, error) { + return gc.deleteOwnerRefJSONMergePatch(n, ownerUIDs...) + }) return err case len(waitingForDependentsDeletion) != 0 && item.dependentsLength() != 0: deps := item.getDependents() @@ -437,11 +484,11 @@ func (gc *GarbageCollector) attemptToDeleteItem(item *node) error { // there are multiple workers run attemptToDeleteItem in // parallel, the circle detection can fail in a race condition. glog.V(2).Infof("processing object %s, some of its owners and its dependent [%s] have FinalizerDeletingDependents, to prevent potential cycle, its ownerReferences are going to be modified to be non-blocking, then the object is going to be deleted with Foreground", item.identity, dep.identity) - patch, err := item.patchToUnblockOwnerReferences() + patch, err := item.unblockOwnerReferencesStrategicMergePatch() if err != nil { return err } - if _, err := gc.patchObject(item.identity, patch); err != nil { + if _, err := gc.patch(item, patch, gc.unblockOwnerReferencesJSONMergePatch); err != nil { return err } break @@ -501,8 +548,10 @@ func (gc *GarbageCollector) orphanDependents(owner objectReference, dependents [ go func(dependent *node) { defer wg.Done() // the dependent.identity.UID is used as precondition - patch := deleteOwnerRefPatch(dependent.identity.UID, owner.UID) - _, err := gc.patchObject(dependent.identity, patch) + patch := deleteOwnerRefStrategicMergePatch(dependent.identity.UID, owner.UID) + _, err := gc.patch(dependent, patch, func(n *node) ([]byte, error) { + return gc.deleteOwnerRefJSONMergePatch(n, owner.UID) + }) // note that if the target ownerReference doesn't exist in the // dependent, strategic merge patch will NOT return an error. if err != nil && !errors.IsNotFound(err) { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/garbagecollector_test.go b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/garbagecollector_test.go index 33c6b4665..60aab9ff1 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/garbagecollector_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/garbagecollector_test.go @@ -32,9 +32,9 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/sets" @@ -47,7 +47,6 @@ import ( restclient "k8s.io/client-go/rest" "k8s.io/client-go/util/workqueue" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly" ) type testRESTMapper struct { @@ -58,12 +57,13 @@ func (_ *testRESTMapper) Reset() {} func TestGarbageCollectorConstruction(t *testing.T) { config := &restclient.Config{} - config.ContentConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: metaonly.NewMetadataCodecFactory()} - tweakableRM := meta.NewDefaultRESTMapper(nil, nil) - rm := &testRESTMapper{meta.MultiRESTMapper{tweakableRM, legacyscheme.Registry.RESTMapper()}} - metaOnlyClientPool := dynamic.NewClientPool(config, rm, dynamic.LegacyAPIPathResolverFunc) - config.ContentConfig.NegotiatedSerializer = nil - clientPool := dynamic.NewClientPool(config, rm, dynamic.LegacyAPIPathResolverFunc) + tweakableRM := meta.NewDefaultRESTMapper(nil) + rm := &testRESTMapper{meta.MultiRESTMapper{tweakableRM, testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme)}} + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + podResource := map[schema.GroupVersionResource]struct{}{ {Version: "v1", Resource: "pods"}: {}, } @@ -78,7 +78,7 @@ func TestGarbageCollectorConstruction(t *testing.T) { // construction will not fail. alwaysStarted := make(chan struct{}) close(alwaysStarted) - gc, err := NewGarbageCollector(metaOnlyClientPool, clientPool, rm, twoResources, map[schema.GroupResource]struct{}{}, sharedInformers, alwaysStarted) + gc, err := NewGarbageCollector(dynamicClient, rm, twoResources, map[schema.GroupResource]struct{}{}, sharedInformers, alwaysStarted) if err != nil { t.Fatal(err) } @@ -189,16 +189,17 @@ type garbageCollector struct { } func setupGC(t *testing.T, config *restclient.Config) garbageCollector { - config.ContentConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: metaonly.NewMetadataCodecFactory()} - metaOnlyClientPool := dynamic.NewClientPool(config, legacyscheme.Registry.RESTMapper(), dynamic.LegacyAPIPathResolverFunc) - config.ContentConfig.NegotiatedSerializer = nil - clientPool := dynamic.NewClientPool(config, legacyscheme.Registry.RESTMapper(), dynamic.LegacyAPIPathResolverFunc) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + podResource := map[schema.GroupVersionResource]struct{}{{Version: "v1", Resource: "pods"}: {}} client := fake.NewSimpleClientset() sharedInformers := informers.NewSharedInformerFactory(client, 0) alwaysStarted := make(chan struct{}) close(alwaysStarted) - gc, err := NewGarbageCollector(metaOnlyClientPool, clientPool, &testRESTMapper{legacyscheme.Registry.RESTMapper()}, podResource, ignoredResources, sharedInformers, alwaysStarted) + gc, err := NewGarbageCollector(dynamicClient, &testRESTMapper{testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme)}, podResource, ignoredResources, sharedInformers, alwaysStarted) if err != nil { t.Fatal(err) } @@ -433,13 +434,13 @@ func TestGCListWatcher(t *testing.T) { testHandler := &fakeActionHandler{} srv, clientConfig := testServerAndClientConfig(testHandler.ServeHTTP) defer srv.Close() - clientPool := dynamic.NewClientPool(clientConfig, legacyscheme.Registry.RESTMapper(), dynamic.LegacyAPIPathResolverFunc) podResource := schema.GroupVersionResource{Version: "v1", Resource: "pods"} - client, err := clientPool.ClientForGroupVersionResource(podResource) + dynamicClient, err := dynamic.NewForConfig(clientConfig) if err != nil { t.Fatal(err) } - lw := listWatcher(client, podResource) + + lw := listWatcher(dynamicClient, podResource) lw.DisableChunking = true if _, err := lw.Watch(metav1.ListOptions{ResourceVersion: "1"}); err != nil { t.Fatal(err) @@ -592,7 +593,7 @@ func TestDeleteOwnerRefPatch(t *testing.T) { }, }, } - patch := deleteOwnerRefPatch("100", "2", "3") + patch := deleteOwnerRefStrategicMergePatch("100", "2", "3") patched, err := strategicpatch.StrategicMergePatch(originalData, patch, v1.Pod{}) if err != nil { t.Fatal(err) @@ -637,7 +638,7 @@ func TestUnblockOwnerReference(t *testing.T) { n := node{ owners: accessor.GetOwnerReferences(), } - patch, err := n.patchToUnblockOwnerReferences() + patch, err := n.unblockOwnerReferencesStrategicMergePatch() if err != nil { t.Fatal(err) } @@ -686,9 +687,13 @@ func TestOrphanDependentsFailure(t *testing.T) { }, } err := gc.orphanDependents(objectReference{}, dependents) - expected := `the server reported a conflict (patch pods pod)` + expected := `the server reported a conflict` if err == nil || !strings.Contains(err.Error(), expected) { - t.Errorf("expected error contains text %s, got %v", expected, err) + if err != nil { + t.Errorf("expected error contains text %q, got %q", expected, err.Error()) + } else { + t.Errorf("expected error contains text %q, got nil", expected) + } } } @@ -795,6 +800,15 @@ func TestGarbageCollectorSync(t *testing.T) { }, }, } + unsyncableServerResources := []*metav1.APIResourceList{ + { + GroupVersion: "v1", + APIResources: []metav1.APIResource{ + {Name: "pods", Namespaced: true, Kind: "Pod", Verbs: metav1.Verbs{"delete", "list", "watch"}}, + {Name: "secrets", Namespaced: true, Kind: "Secret", Verbs: metav1.Verbs{"delete", "list", "watch"}}, + }, + }, + } fakeDiscoveryClient := &fakeServerResources{ PreferredResources: serverResources, Error: nil, @@ -808,6 +822,10 @@ func TestGarbageCollectorSync(t *testing.T) { 200, []byte("{}"), }, + "GET" + "/api/v1/secrets": { + 404, + []byte("{}"), + }, }, } srv, clientConfig := testServerAndClientConfig(testHandler.ServeHTTP) @@ -818,16 +836,19 @@ func TestGarbageCollectorSync(t *testing.T) { t.Fatal(err) } - rm := &testRESTMapper{legacyscheme.Registry.RESTMapper()} - metaOnlyClientPool := dynamic.NewClientPool(clientConfig, rm, dynamic.LegacyAPIPathResolverFunc) - clientPool := dynamic.NewClientPool(clientConfig, rm, dynamic.LegacyAPIPathResolverFunc) + rm := &testRESTMapper{testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme)} + dynamicClient, err := dynamic.NewForConfig(clientConfig) + if err != nil { + t.Fatal(err) + } + podResource := map[schema.GroupVersionResource]struct{}{ {Group: "", Version: "v1", Resource: "pods"}: {}, } sharedInformers := informers.NewSharedInformerFactory(client, 0) alwaysStarted := make(chan struct{}) close(alwaysStarted) - gc, err := NewGarbageCollector(metaOnlyClientPool, clientPool, rm, podResource, map[schema.GroupResource]struct{}{}, sharedInformers, alwaysStarted) + gc, err := NewGarbageCollector(dynamicClient, rm, podResource, map[schema.GroupResource]struct{}{}, sharedInformers, alwaysStarted) if err != nil { t.Fatal(err) } @@ -841,7 +862,7 @@ func TestGarbageCollectorSync(t *testing.T) { fmt.Printf("Test output") time.Sleep(1 * time.Second) - err = expectSyncNotBlocked(fakeDiscoveryClient) + err = expectSyncNotBlocked(fakeDiscoveryClient, &gc.workerLock) if err != nil { t.Fatalf("Expected garbagecollector.Sync to be running but it is blocked: %v", err) } @@ -857,13 +878,29 @@ func TestGarbageCollectorSync(t *testing.T) { fakeDiscoveryClient.setPreferredResources(serverResources) fakeDiscoveryClient.setError(nil) - err = expectSyncNotBlocked(fakeDiscoveryClient) + err = expectSyncNotBlocked(fakeDiscoveryClient, &gc.workerLock) + if err != nil { + t.Fatalf("Expected garbagecollector.Sync to still be running but it is blocked: %v", err) + } + + // Simulate the discovery client returning a resource the restmapper can resolve, but will not sync caches + fakeDiscoveryClient.setPreferredResources(unsyncableServerResources) + fakeDiscoveryClient.setError(nil) + + // Wait until sync discovers the change + time.Sleep(1 * time.Second) + + // Put the resources back to normal and ensure garbage collector sync recovers + fakeDiscoveryClient.setPreferredResources(serverResources) + fakeDiscoveryClient.setError(nil) + + err = expectSyncNotBlocked(fakeDiscoveryClient, &gc.workerLock) if err != nil { t.Fatalf("Expected garbagecollector.Sync to still be running but it is blocked: %v", err) } } -func expectSyncNotBlocked(fakeDiscoveryClient *fakeServerResources) error { +func expectSyncNotBlocked(fakeDiscoveryClient *fakeServerResources, workerLock *sync.RWMutex) error { before := fakeDiscoveryClient.getInterfaceUsedCount() t := 1 * time.Second time.Sleep(t) @@ -871,7 +908,19 @@ func expectSyncNotBlocked(fakeDiscoveryClient *fakeServerResources) error { if before == after { return fmt.Errorf("discoveryClient.ServerPreferredResources() called %d times over %v", after-before, t) } - return nil + + workerLockAcquired := make(chan struct{}) + go func() { + workerLock.Lock() + workerLock.Unlock() + close(workerLockAcquired) + }() + select { + case <-workerLockAcquired: + return nil + case <-time.After(t): + return fmt.Errorf("workerLock blocked for at least %v", t) + } } type fakeServerResources struct { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/graph_builder.go b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/graph_builder.go index 190938b0a..e8c94effc 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/graph_builder.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/graph_builder.go @@ -78,7 +78,7 @@ type GraphBuilder struct { // each monitor list/watches a resource, the results are funneled to the // dependencyGraphBuilder monitors monitors - monitorLock sync.Mutex + monitorLock sync.RWMutex // informersStarted is closed after after all of the controllers have been initialized and are running. // After that it is safe to start them here, before that it is not. informersStarted <-chan struct{} @@ -91,9 +91,7 @@ type GraphBuilder struct { // it is protected by monitorLock. running bool - // metaOnlyClientPool uses a special codec, which removes fields except for - // apiVersion, kind, and metadata during decoding. - metaOnlyClientPool dynamic.ClientPool + dynamicClient dynamic.Interface // monitors are the producer of the graphChanges queue, graphBuilder alters // the in-memory graph according to the changes. graphChanges workqueue.RateLimitingInterface @@ -113,6 +111,7 @@ type GraphBuilder struct { // monitor runs a Controller with a local stop channel. type monitor struct { controller cache.Controller + store cache.Store // stopCh stops Controller. If stopCh is nil, the monitor is considered to be // not yet started. @@ -130,29 +129,17 @@ type monitors map[schema.GroupVersionResource]*monitor func listWatcher(client dynamic.Interface, resource schema.GroupVersionResource) *cache.ListWatch { return &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { - // APIResource.Kind is not used by the dynamic client, so - // leave it empty. We want to list this resource in all - // namespaces if it's namespace scoped, so leave - // APIResource.Namespaced as false is all right. - apiResource := metav1.APIResource{Name: resource.Resource} - return client.ParameterCodec(dynamic.VersionedParameterEncoderWithV1Fallback). - Resource(&apiResource, metav1.NamespaceAll). - List(options) + // We want to list this resource in all namespaces if it's namespace scoped, so not passing namespace is ok. + return client.Resource(resource).List(options) }, WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { - // APIResource.Kind is not used by the dynamic client, so - // leave it empty. We want to list this resource in all - // namespaces if it's namespace scoped, so leave - // APIResource.Namespaced as false is all right. - apiResource := metav1.APIResource{Name: resource.Resource} - return client.ParameterCodec(dynamic.VersionedParameterEncoderWithV1Fallback). - Resource(&apiResource, metav1.NamespaceAll). - Watch(options) + // We want to list this resource in all namespaces if it's namespace scoped, so not passing namespace is ok. + return client.Resource(resource).Watch(options) }, } } -func (gb *GraphBuilder) controllerFor(resource schema.GroupVersionResource, kind schema.GroupVersionKind) (cache.Controller, error) { +func (gb *GraphBuilder) controllerFor(resource schema.GroupVersionResource, kind schema.GroupVersionKind) (cache.Controller, cache.Store, error) { handlers := cache.ResourceEventHandlerFuncs{ // add the event to the dependencyGraphBuilder's graphChanges. AddFunc: func(obj interface{}) { @@ -192,25 +179,21 @@ func (gb *GraphBuilder) controllerFor(resource schema.GroupVersionResource, kind glog.V(4).Infof("using a shared informer for resource %q, kind %q", resource.String(), kind.String()) // need to clone because it's from a shared cache shared.Informer().AddEventHandlerWithResyncPeriod(handlers, ResourceResyncTime) - return shared.Informer().GetController(), nil + return shared.Informer().GetController(), shared.Informer().GetStore(), nil } else { glog.V(4).Infof("unable to use a shared informer for resource %q, kind %q: %v", resource.String(), kind.String(), err) } // TODO: consider store in one storage. glog.V(5).Infof("create storage for resource %s", resource) - client, err := gb.metaOnlyClientPool.ClientForGroupVersionKind(kind) - if err != nil { - return nil, err - } - _, monitor := cache.NewInformer( - listWatcher(client, resource), + store, monitor := cache.NewInformer( + listWatcher(gb.dynamicClient, resource), nil, ResourceResyncTime, // don't need to clone because it's not from shared cache handlers, ) - return monitor, nil + return monitor, store, nil } // syncMonitors rebuilds the monitor set according to the supplied resources, @@ -246,12 +229,12 @@ func (gb *GraphBuilder) syncMonitors(resources map[schema.GroupVersionResource]s errs = append(errs, fmt.Errorf("couldn't look up resource %q: %v", resource, err)) continue } - c, err := gb.controllerFor(resource, kind) + c, s, err := gb.controllerFor(resource, kind) if err != nil { errs = append(errs, fmt.Errorf("couldn't start monitor for resource %q: %v", resource, err)) continue } - current[resource] = &monitor{controller: c} + current[resource] = &monitor{store: s, controller: c} added++ } gb.monitors = current @@ -306,11 +289,13 @@ func (gb *GraphBuilder) IsSynced() bool { defer gb.monitorLock.Unlock() if len(gb.monitors) == 0 { + glog.V(4).Info("garbage controller monitor not synced: no monitors") return false } - for _, monitor := range gb.monitors { + for resource, monitor := range gb.monitors { if !monitor.controller.HasSynced() { + glog.V(4).Infof("garbage controller monitor not yet synced: %+v", resource) return false } } @@ -361,8 +346,6 @@ var ignoredResources = map[schema.GroupResource]struct{}{ {Group: "authorization.k8s.io", Resource: "selfsubjectaccessreviews"}: {}, {Group: "authorization.k8s.io", Resource: "localsubjectaccessreviews"}: {}, {Group: "authorization.k8s.io", Resource: "selfsubjectrulesreviews"}: {}, - {Group: "apiregistration.k8s.io", Resource: "apiservices"}: {}, - {Group: "apiextensions.k8s.io", Resource: "customresourcedefinitions"}: {}, } // DefaultIgnoredResources returns the default set of resources that the garbage collector controller diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/BUILD index d20f61e88..671a5e2b8 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/BUILD @@ -3,38 +3,18 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", - "go_test", ) go_library( name = "go_default_library", srcs = [ - "metaonly.go", "types.go", "zz_generated.deepcopy.go", ], importpath = "k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly", deps = [ - "//pkg/api/legacyscheme:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["metaonly_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/apis/core/install:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/metaonly.go b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/metaonly.go deleted file mode 100644 index aec98ba33..000000000 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/metaonly.go +++ /dev/null @@ -1,66 +0,0 @@ -/* -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 metaonly - -import ( - "fmt" - "strings" - - 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" - "k8s.io/kubernetes/pkg/api/legacyscheme" -) - -type metaOnlyJSONScheme struct{} - -// This function can be extended to mapping different gvk to different MetadataOnlyObject, -// which embedded with different version of ObjectMeta. Currently the system -// only supports metav1.ObjectMeta. -func gvkToMetadataOnlyObject(gvk schema.GroupVersionKind) runtime.Object { - if strings.HasSuffix(gvk.Kind, "List") { - return &MetadataOnlyObjectList{} - } else { - return &MetadataOnlyObject{} - } -} - -func NewMetadataCodecFactory() serializer.CodecFactory { - // populating another scheme from legacyscheme.Scheme, registering every kind with - // MetadataOnlyObject (or MetadataOnlyObjectList). - scheme := runtime.NewScheme() - allTypes := legacyscheme.Scheme.AllKnownTypes() - for kind := range allTypes { - if kind.Version == runtime.APIVersionInternal { - continue - } - if kind == metav1.Unversioned.WithKind("Status") { - // this is added below as unversioned - continue - } - metaOnlyObject := gvkToMetadataOnlyObject(kind) - scheme.AddKnownTypeWithName(kind, metaOnlyObject) - } - scheme.AddUnversionedTypes(metav1.Unversioned, &metav1.Status{}) - return serializer.NewCodecFactory(scheme) -} - -// String converts a MetadataOnlyObject to a human-readable string. -func (metaOnly MetadataOnlyObject) String() string { - return fmt.Sprintf("%s/%s, name: %s, DeletionTimestamp:%v", metaOnly.TypeMeta.APIVersion, metaOnly.TypeMeta.Kind, metaOnly.ObjectMeta.Name, metaOnly.ObjectMeta.DeletionTimestamp) -} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/metaonly_test.go b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/metaonly_test.go deleted file mode 100644 index 2bdf9c879..000000000 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/metaonly_test.go +++ /dev/null @@ -1,164 +0,0 @@ -/* -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 metaonly - -import ( - "encoding/json" - "reflect" - "testing" - - "k8s.io/api/core/v1" - "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/apimachinery/pkg/runtime/serializer" - _ "k8s.io/kubernetes/pkg/apis/core/install" -) - -func getPod() *v1.Pod { - return &v1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "pod", - OwnerReferences: []metav1.OwnerReference{ - {UID: "1234"}, - }, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "fake-name", - Image: "fakeimage", - }, - }, - }, - } -} - -func getPodJson(t *testing.T) []byte { - data, err := json.Marshal(getPod()) - if err != nil { - t.Fatal(err) - } - return data -} - -func getPodListJson(t *testing.T) []byte { - data, err := json.Marshal(&v1.PodList{ - TypeMeta: metav1.TypeMeta{ - Kind: "PodList", - APIVersion: "v1", - }, - Items: []v1.Pod{ - *getPod(), - *getPod(), - }, - }) - if err != nil { - t.Fatal(err) - } - return data -} - -func verfiyMetadata(description string, t *testing.T, in *MetadataOnlyObject) { - pod := getPod() - if e, a := pod.ObjectMeta, in.ObjectMeta; !reflect.DeepEqual(e, a) { - t.Errorf("%s: expected %#v, got %#v", description, e, a) - } -} - -func TestDecodeToMetadataOnlyObject(t *testing.T) { - data := getPodJson(t) - cf := serializer.DirectCodecFactory{CodecFactory: NewMetadataCodecFactory()} - info, ok := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON) - if !ok { - t.Fatalf("expected to get a JSON serializer") - } - codec := cf.DecoderToVersion(info.Serializer, schema.GroupVersion{Group: "SOMEGROUP", Version: "SOMEVERSION"}) - // decode with into - into := &MetadataOnlyObject{} - ret, _, err := codec.Decode(data, nil, into) - if err != nil { - t.Fatal(err) - } - metaOnly, ok := ret.(*MetadataOnlyObject) - if !ok { - t.Fatalf("expected ret to be *runtime.MetadataOnlyObject") - } - verfiyMetadata("check returned metaonly with into", t, metaOnly) - verfiyMetadata("check into", t, into) - // decode without into - ret, _, err = codec.Decode(data, nil, nil) - if err != nil { - t.Fatal(err) - } - metaOnly, ok = ret.(*MetadataOnlyObject) - if !ok { - t.Fatalf("expected ret to be *runtime.MetadataOnlyObject") - } - verfiyMetadata("check returned metaonly without into", t, metaOnly) -} - -func verifyListMetadata(t *testing.T, metaOnlyList *MetadataOnlyObjectList) { - items, err := meta.ExtractList(metaOnlyList) - if err != nil { - t.Fatal(err) - } - for _, item := range items { - metaOnly, ok := item.(*MetadataOnlyObject) - if !ok { - t.Fatalf("expected item to be *MetadataOnlyObject") - } - verfiyMetadata("check list", t, metaOnly) - } -} - -func TestDecodeToMetadataOnlyObjectList(t *testing.T) { - data := getPodListJson(t) - cf := serializer.DirectCodecFactory{CodecFactory: NewMetadataCodecFactory()} - info, ok := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON) - if !ok { - t.Fatalf("expected to get a JSON serializer") - } - codec := cf.DecoderToVersion(info.Serializer, schema.GroupVersion{Group: "SOMEGROUP", Version: "SOMEVERSION"}) - // decode with into - into := &MetadataOnlyObjectList{} - ret, _, err := codec.Decode(data, nil, into) - if err != nil { - t.Fatal(err) - } - metaOnlyList, ok := ret.(*MetadataOnlyObjectList) - if !ok { - t.Fatalf("expected ret to be *runtime.UnstructuredList") - } - verifyListMetadata(t, metaOnlyList) - verifyListMetadata(t, into) - // decode without into - ret, _, err = codec.Decode(data, nil, nil) - if err != nil { - t.Fatal(err) - } - metaOnlyList, ok = ret.(*MetadataOnlyObjectList) - if !ok { - t.Fatalf("expected ret to be *runtime.UnstructuredList") - } - verifyListMetadata(t, metaOnlyList) -} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/zz_generated.deepcopy.go index 5fd2559b0..3763cb5b0 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/operations.go b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/operations.go index 4fd59ad18..9f0145869 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/operations.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/operations.go @@ -30,76 +30,58 @@ import ( "k8s.io/client-go/util/retry" ) +// cluster scoped resources don't have namespaces. Default to the item's namespace, but clear it for cluster scoped resources +func resourceDefaultNamespace(namespaced bool, defaultNamespace string) string { + if namespaced { + return defaultNamespace + } + return "" +} + // apiResource consults the REST mapper to translate an tuple to a unversioned.APIResource struct. -func (gc *GarbageCollector) apiResource(apiVersion, kind string) (*metav1.APIResource, error) { +func (gc *GarbageCollector) apiResource(apiVersion, kind string) (schema.GroupVersionResource, bool, error) { fqKind := schema.FromAPIVersionAndKind(apiVersion, kind) mapping, err := gc.restMapper.RESTMapping(fqKind.GroupKind(), fqKind.Version) if err != nil { - return nil, newRESTMappingError(kind, apiVersion) - } - glog.V(5).Infof("map kind %s, version %s to resource %s", kind, apiVersion, mapping.Resource) - resource := metav1.APIResource{ - Name: mapping.Resource, - Namespaced: mapping.Scope == meta.RESTScopeNamespace, - Kind: kind, + return schema.GroupVersionResource{}, false, newRESTMappingError(kind, apiVersion) } - return &resource, nil + return mapping.Resource, mapping.Scope == meta.RESTScopeNamespace, nil } func (gc *GarbageCollector) deleteObject(item objectReference, policy *metav1.DeletionPropagation) error { - fqKind := schema.FromAPIVersionAndKind(item.APIVersion, item.Kind) - client, err := gc.clientPool.ClientForGroupVersionKind(fqKind) - if err != nil { - return err - } - resource, err := gc.apiResource(item.APIVersion, item.Kind) + resource, namespaced, err := gc.apiResource(item.APIVersion, item.Kind) if err != nil { return err } uid := item.UID preconditions := metav1.Preconditions{UID: &uid} deleteOptions := metav1.DeleteOptions{Preconditions: &preconditions, PropagationPolicy: policy} - return client.Resource(resource, item.Namespace).Delete(item.Name, &deleteOptions) + return gc.dynamicClient.Resource(resource).Namespace(resourceDefaultNamespace(namespaced, item.Namespace)).Delete(item.Name, &deleteOptions) } func (gc *GarbageCollector) getObject(item objectReference) (*unstructured.Unstructured, error) { - fqKind := schema.FromAPIVersionAndKind(item.APIVersion, item.Kind) - client, err := gc.clientPool.ClientForGroupVersionKind(fqKind) - if err != nil { - return nil, err - } - resource, err := gc.apiResource(item.APIVersion, item.Kind) + resource, namespaced, err := gc.apiResource(item.APIVersion, item.Kind) if err != nil { return nil, err } - return client.Resource(resource, item.Namespace).Get(item.Name, metav1.GetOptions{}) + return gc.dynamicClient.Resource(resource).Namespace(resourceDefaultNamespace(namespaced, item.Namespace)).Get(item.Name, metav1.GetOptions{}) } func (gc *GarbageCollector) updateObject(item objectReference, obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - fqKind := schema.FromAPIVersionAndKind(item.APIVersion, item.Kind) - client, err := gc.clientPool.ClientForGroupVersionKind(fqKind) - if err != nil { - return nil, err - } - resource, err := gc.apiResource(item.APIVersion, item.Kind) + resource, namespaced, err := gc.apiResource(item.APIVersion, item.Kind) if err != nil { return nil, err } - return client.Resource(resource, item.Namespace).Update(obj) + return gc.dynamicClient.Resource(resource).Namespace(resourceDefaultNamespace(namespaced, item.Namespace)).Update(obj) } -func (gc *GarbageCollector) patchObject(item objectReference, patch []byte) (*unstructured.Unstructured, error) { - fqKind := schema.FromAPIVersionAndKind(item.APIVersion, item.Kind) - client, err := gc.clientPool.ClientForGroupVersionKind(fqKind) - if err != nil { - return nil, err - } - resource, err := gc.apiResource(item.APIVersion, item.Kind) +func (gc *GarbageCollector) patchObject(item objectReference, patch []byte, pt types.PatchType) (*unstructured.Unstructured, error) { + resource, namespaced, err := gc.apiResource(item.APIVersion, item.Kind) if err != nil { return nil, err } - return client.Resource(resource, item.Namespace).Patch(item.Name, types.StrategicMergePatchType, patch) + return gc.dynamicClient.Resource(resource).Namespace(resourceDefaultNamespace(namespaced, item.Namespace)).Patch(item.Name, pt, patch) } // TODO: Using Patch when strategicmerge supports deleting an entry from a diff --git a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/patch.go b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/patch.go index 8f8f9fb75..b0169adea 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/patch.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/garbagecollector/patch.go @@ -21,12 +21,16 @@ import ( "fmt" "strings" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly" ) -func deleteOwnerRefPatch(dependentUID types.UID, ownerUIDs ...types.UID) []byte { +func deleteOwnerRefStrategicMergePatch(dependentUID types.UID, ownerUIDs ...types.UID) []byte { var pieces []string for _, ownerUID := range ownerUIDs { pieces = append(pieces, fmt.Sprintf(`{"$patch":"delete","uid":"%s"}`, ownerUID)) @@ -35,9 +39,97 @@ func deleteOwnerRefPatch(dependentUID types.UID, ownerUIDs ...types.UID) []byte return []byte(patch) } -// generate a patch that unsets the BlockOwnerDeletion field of all +// getMetadata tries getting object metadata from local cache, and sends GET request to apiserver when +// local cache is not available or not latest. +func (gc *GarbageCollector) getMetadata(apiVersion, kind, namespace, name string) (metav1.Object, error) { + apiResource, _, err := gc.apiResource(apiVersion, kind) + if err != nil { + return nil, err + } + gc.dependencyGraphBuilder.monitorLock.RLock() + defer gc.dependencyGraphBuilder.monitorLock.RUnlock() + m, ok := gc.dependencyGraphBuilder.monitors[apiResource] + if !ok || m == nil { + // If local cache doesn't exist for mapping.Resource, send a GET request to API server + return gc.dynamicClient.Resource(apiResource).Namespace(namespace).Get(name, metav1.GetOptions{}) + } + key := name + if len(namespace) != 0 { + key = namespace + "/" + name + } + raw, exist, err := m.store.GetByKey(key) + if err != nil { + return nil, err + } + if !exist { + // If local cache doesn't contain the object, send a GET request to API server + return gc.dynamicClient.Resource(apiResource).Namespace(namespace).Get(name, metav1.GetOptions{}) + } + obj, ok := raw.(runtime.Object) + if !ok { + return nil, fmt.Errorf("expect a runtime.Object, got %v", raw) + } + return meta.Accessor(obj) +} + +type objectForPatch struct { + ObjectMetaForPatch `json:"metadata"` +} + +type ObjectMetaForPatch struct { + ResourceVersion string `json:"resourceVersion"` + OwnerReferences []metav1.OwnerReference `json:"ownerReferences"` +} + +// jsonMergePatchFunc defines the interface for functions that construct json merge patches that manipulate +// owner reference array. +type jsonMergePatchFunc func(*node) ([]byte, error) + +// patch tries strategic merge patch on item first, and if SMP is not supported, it fallbacks to JSON merge +// patch. +func (gc *GarbageCollector) patch(item *node, smp []byte, jmp jsonMergePatchFunc) (*unstructured.Unstructured, error) { + smpResult, err := gc.patchObject(item.identity, smp, types.StrategicMergePatchType) + if err == nil { + return smpResult, nil + } + if !errors.IsUnsupportedMediaType(err) { + return nil, err + } + // StrategicMergePatch is not supported, use JSON merge patch instead + patch, err := jmp(item) + if err != nil { + return nil, err + } + return gc.patchObject(item.identity, patch, types.MergePatchType) +} + +// Returns JSON merge patch that removes the ownerReferences matching ownerUIDs. +func (gc *GarbageCollector) deleteOwnerRefJSONMergePatch(item *node, ownerUIDs ...types.UID) ([]byte, error) { + accessor, err := gc.getMetadata(item.identity.APIVersion, item.identity.Kind, item.identity.Namespace, item.identity.Name) + if err != nil { + return nil, err + } + expectedObjectMeta := ObjectMetaForPatch{} + expectedObjectMeta.ResourceVersion = accessor.GetResourceVersion() + refs := accessor.GetOwnerReferences() + for _, ref := range refs { + var skip bool + for _, ownerUID := range ownerUIDs { + if ref.UID == ownerUID { + skip = true + break + } + } + if !skip { + expectedObjectMeta.OwnerReferences = append(expectedObjectMeta.OwnerReferences, ref) + } + } + return json.Marshal(objectForPatch{expectedObjectMeta}) +} + +// Generate a patch that unsets the BlockOwnerDeletion field of all // ownerReferences of node. -func (n *node) patchToUnblockOwnerReferences() ([]byte, error) { +func (n *node) unblockOwnerReferencesStrategicMergePatch() ([]byte, error) { var dummy metaonly.MetadataOnlyObject var blockingRefs []metav1.OwnerReference falseVar := false @@ -52,3 +144,22 @@ func (n *node) patchToUnblockOwnerReferences() ([]byte, error) { dummy.ObjectMeta.UID = n.identity.UID return json.Marshal(dummy) } + +// Generate a JSON merge patch that unsets the BlockOwnerDeletion field of all +// ownerReferences of node. +func (gc *GarbageCollector) unblockOwnerReferencesJSONMergePatch(n *node) ([]byte, error) { + accessor, err := gc.getMetadata(n.identity.APIVersion, n.identity.Kind, n.identity.Namespace, n.identity.Name) + if err != nil { + return nil, err + } + expectedObjectMeta := ObjectMetaForPatch{} + expectedObjectMeta.ResourceVersion = accessor.GetResourceVersion() + var expectedOwners []metav1.OwnerReference + falseVar := false + for _, owner := range n.owners { + owner.BlockOwnerDeletion = &falseVar + expectedOwners = append(expectedOwners, owner) + } + expectedObjectMeta.OwnerReferences = expectedOwners + return json.Marshal(objectForPatch{expectedObjectMeta}) +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/history/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/history/BUILD index 9824a0b9d..e326d484f 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/history/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/history/BUILD @@ -11,6 +11,7 @@ go_test( srcs = ["controller_history_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/controller:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/history/controller_history_test.go b/vendor/k8s.io/kubernetes/pkg/controller/history/controller_history_test.go index 455d6b673..169a5b110 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/history/controller_history_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/history/controller_history_test.go @@ -27,6 +27,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/controller" @@ -966,7 +967,7 @@ func TestRealHistory_AdoptControllerRevision(t *testing.T) { if err != nil { return true, nil, err } - patched, err := testapi.Apps.Converter().ConvertToVersion(obj, apps.SchemeGroupVersion) + patched, err := legacyscheme.Scheme.ConvertToVersion(obj, apps.SchemeGroupVersion) if err != nil { return true, nil, err } @@ -1217,7 +1218,7 @@ func TestRealHistory_ReleaseControllerRevision(t *testing.T) { if err != nil { return true, nil, err } - patched, err := testapi.Apps.Converter().ConvertToVersion(obj, apps.SchemeGroupVersion) + patched, err := legacyscheme.Scheme.ConvertToVersion(obj, apps.SchemeGroupVersion) if err != nil { return true, nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/job/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/job/BUILD index 94dfcfa51..1658a1deb 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/job/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/job/BUILD @@ -47,13 +47,13 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core/install:go_default_library", "//pkg/controller:go_default_library", "//vendor/k8s.io/api/batch/v1: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/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/rand:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller.go index 366eacc46..7578653d3 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller.go @@ -48,6 +48,8 @@ import ( "github.com/golang/glog" ) +const statusUpdateRetries = 3 + // controllerKind contains the schema.GroupVersionKind for this controller type. var controllerKind = batch.SchemeGroupVersion.WithKind("Job") @@ -90,8 +92,7 @@ type JobController struct { func NewJobController(podInformer coreinformers.PodInformer, jobInformer batchinformers.JobInformer, kubeClient clientset.Interface) *JobController { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - // TODO: remove the wrapper when every clients have moved to use the clientset. - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("job_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter()) @@ -357,10 +358,10 @@ func (jm *JobController) enqueueController(obj interface{}, immediate bool) { return } - if immediate { - jm.queue.Forget(key) + backoff := time.Duration(0) + if !immediate { + backoff = getBackoff(jm.queue, key) } - backoff := getBackoff(jm.queue, key) // TODO: Handle overlapping controllers better. Either disallow them at admission time or // deterministically avoid syncing controllers that fight over pods. Currently, we only @@ -435,7 +436,7 @@ func (jm *JobController) getPodsForJob(j *batch.Job) ([]*v1.Pod, error) { func (jm *JobController) syncJob(key string) (bool, error) { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing job %q (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing job %q (%v)", key, time.Since(startTime)) }() ns, name, err := cache.SplitMetaNamespaceKey(key) @@ -496,12 +497,18 @@ func (jm *JobController) syncJob(key string) (bool, error) { var failureMessage string jobHaveNewFailure := failed > job.Status.Failed - - // check if the number of failed jobs increased since the last syncJob - if jobHaveNewFailure && (int32(previousRetry)+1 > *job.Spec.BackoffLimit) { + // new failures happen when status does not reflect the failures and active + // is different than parallelism, otherwise the previous controller loop + // failed updating status so even if we pick up failure it is not a new one + exceedsBackoffLimit := jobHaveNewFailure && (active != *job.Spec.Parallelism) && + (int32(previousRetry)+1 > *job.Spec.BackoffLimit) + + if exceedsBackoffLimit || pastBackoffLimitOnFailure(&job, pods) { + // check if the number of pod restart exceeds backoff (for restart OnFailure only) + // OR if the number of failed jobs increased since the last syncJob jobFailed = true failureReason = "BackoffLimitExceeded" - failureMessage = "Job has reach the specified backoff limit" + failureMessage = "Job has reached the specified backoff limit" } else if pastActiveDeadline(&job) { jobFailed = true failureReason = "DeadlineExceeded" @@ -615,6 +622,30 @@ func (jm *JobController) deleteJobPods(job *batch.Job, pods []*v1.Pod, errCh cha wait.Wait() } +// pastBackoffLimitOnFailure checks if container restartCounts sum exceeds BackoffLimit +// this method applies only to pods with restartPolicy == OnFailure +func pastBackoffLimitOnFailure(job *batch.Job, pods []*v1.Pod) bool { + if job.Spec.Template.Spec.RestartPolicy != v1.RestartPolicyOnFailure { + return false + } + result := int32(0) + for i := range pods { + po := pods[i] + if po.Status.Phase != v1.PodRunning { + continue + } + for j := range po.Status.InitContainerStatuses { + stat := po.Status.InitContainerStatuses[j] + result += stat.RestartCount + } + for j := range po.Status.ContainerStatuses { + stat := po.Status.ContainerStatuses[j] + result += stat.RestartCount + } + } + return result >= *job.Spec.BackoffLimit +} + // pastActiveDeadline checks if job has ActiveDeadlineSeconds field set and if it is exceeded. func pastActiveDeadline(job *batch.Job) bool { if job.Spec.ActiveDeadlineSeconds == nil || job.Status.StartTime == nil { @@ -788,7 +819,20 @@ func (jm *JobController) manageJob(activePods []*v1.Pod, succeeded int32, job *b } func (jm *JobController) updateJobStatus(job *batch.Job) error { - _, err := jm.kubeClient.BatchV1().Jobs(job.Namespace).UpdateStatus(job) + jobClient := jm.kubeClient.BatchV1().Jobs(job.Namespace) + var err error + for i := 0; i <= statusUpdateRetries; i = i + 1 { + var newJob *batch.Job + newJob, err = jobClient.Get(job.Name, metav1.GetOptions{}) + if err != nil { + break + } + newJob.Status = job.Status + if _, err = jobClient.UpdateStatus(newJob); err == nil { + break + } + } + return err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller_test.go index e176961c6..b0533c963 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" @@ -37,7 +38,6 @@ import ( core "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" - "k8s.io/kubernetes/pkg/api/legacyscheme" _ "k8s.io/kubernetes/pkg/apis/core/install" "k8s.io/kubernetes/pkg/controller" ) @@ -269,7 +269,7 @@ func TestControllerSyncJob(t *testing.T) { nil, true, 0, 0, 0, 0, 10, 0, 10, 0, 0, nil, "", }, - "to many job sync failure": { + "too many job failures": { 2, 5, 0, true, 0, nil, true, 0, 0, 0, 1, 0, 0, 0, 0, 1, &jobConditionFailed, "BackoffLimitExceeded", @@ -278,7 +278,7 @@ func TestControllerSyncJob(t *testing.T) { for name, tc := range testCases { // job manager setup - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) fakePodControl := controller.FakePodControl{Err: tc.podControllerError, CreateLimit: tc.podLimit} manager.podControl = &fakePodControl @@ -412,14 +412,14 @@ func TestSyncJobPastDeadline(t *testing.T) { }, "activeDeadlineSeconds with backofflimit reach": { 1, 1, 1, 10, 0, - 1, 0, 2, - true, 1, 0, 0, 3, "BackoffLimitExceeded", + 0, 0, 1, + true, 0, 0, 0, 1, "BackoffLimitExceeded", }, } for name, tc := range testCases { // job manager setup - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) fakePodControl := controller.FakePodControl{} manager.podControl = &fakePodControl @@ -485,7 +485,7 @@ func getCondition(job *batch.Job, condition batch.JobConditionType, reason strin } func TestSyncPastDeadlineJobFinished(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) fakePodControl := controller.FakePodControl{} manager.podControl = &fakePodControl @@ -523,7 +523,7 @@ func TestSyncPastDeadlineJobFinished(t *testing.T) { } func TestSyncJobComplete(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) fakePodControl := controller.FakePodControl{} manager.podControl = &fakePodControl @@ -551,7 +551,7 @@ func TestSyncJobComplete(t *testing.T) { } func TestSyncJobDeleted(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) manager, _ := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) fakePodControl := controller.FakePodControl{} manager.podControl = &fakePodControl @@ -575,7 +575,7 @@ func TestSyncJobDeleted(t *testing.T) { } func TestSyncJobUpdateRequeue(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) DefaultJobBackOff = time.Duration(0) // overwrite the default value for testing manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) fakePodControl := controller.FakePodControl{} @@ -605,7 +605,7 @@ func TestSyncJobUpdateRequeue(t *testing.T) { } func TestJobPodLookup(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) manager.podStoreSynced = alwaysReady manager.jobStoreSynced = alwaysReady @@ -687,7 +687,7 @@ func TestJobPodLookup(t *testing.T) { } func TestGetPodsForJob(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -823,7 +823,7 @@ func TestGetPodsForJobNoAdoptIfBeingDeletedRace(t *testing.T) { } func TestGetPodsForJobRelease(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -852,7 +852,7 @@ func TestGetPodsForJobRelease(t *testing.T) { } func TestAddPod(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -897,7 +897,7 @@ func TestAddPod(t *testing.T) { } func TestAddPodOrphan(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -925,7 +925,7 @@ func TestAddPodOrphan(t *testing.T) { } func TestUpdatePod(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -974,7 +974,7 @@ func TestUpdatePod(t *testing.T) { } func TestUpdatePodOrphanWithNewLabels(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -1001,7 +1001,7 @@ func TestUpdatePodOrphanWithNewLabels(t *testing.T) { } func TestUpdatePodChangeControllerRef(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -1027,7 +1027,7 @@ func TestUpdatePodChangeControllerRef(t *testing.T) { } func TestUpdatePodRelease(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -1053,7 +1053,7 @@ func TestUpdatePodRelease(t *testing.T) { } func TestDeletePod(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -1098,7 +1098,7 @@ func TestDeletePod(t *testing.T) { } func TestDeletePodOrphan(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) jm, informer := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) jm.podStoreSynced = alwaysReady jm.jobStoreSynced = alwaysReady @@ -1138,7 +1138,7 @@ func (fe FakeJobExpectations) SatisfiedExpectations(controllerKey string) bool { // TestSyncJobExpectations tests that a pod cannot sneak in between counting active pods // and checking expectations. func TestSyncJobExpectations(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) fakePodControl := controller.FakePodControl{} manager.podControl = &fakePodControl @@ -1299,7 +1299,7 @@ func TestJobBackoffReset(t *testing.T) { } for name, tc := range testCases { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) DefaultJobBackOff = time.Duration(0) // overwrite the default value for testing manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) fakePodControl := controller.FakePodControl{} @@ -1350,7 +1350,9 @@ type fakeRateLimitingQueue struct { } func (f *fakeRateLimitingQueue) AddRateLimited(item interface{}) {} -func (f *fakeRateLimitingQueue) Forget(item interface{}) {} +func (f *fakeRateLimitingQueue) Forget(item interface{}) { + f.requeues = 0 +} func (f *fakeRateLimitingQueue) NumRequeues(item interface{}) int { return f.requeues } @@ -1386,7 +1388,7 @@ func TestJobBackoff(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) fakePodControl := controller.FakePodControl{} manager.podControl = &fakePodControl @@ -1406,3 +1408,92 @@ func TestJobBackoff(t *testing.T) { }) } } + +func TestJobBackoffForOnFailure(t *testing.T) { + jobConditionFailed := batch.JobFailed + + testCases := map[string]struct { + // job setup + parallelism int32 + completions int32 + backoffLimit int32 + + // pod setup + jobKeyForget bool + restartCounts []int32 + + // expectations + expectedActive int32 + expectedSucceeded int32 + expectedFailed int32 + expectedCondition *batch.JobConditionType + expectedConditionReason string + }{ + "too many job failures - single pod": { + 1, 5, 2, + true, []int32{2}, + 0, 0, 1, &jobConditionFailed, "BackoffLimitExceeded", + }, + "too many job failures - multiple pods": { + 2, 5, 2, + true, []int32{1, 1}, + 0, 0, 2, &jobConditionFailed, "BackoffLimitExceeded", + }, + "not enough failures": { + 2, 5, 3, + true, []int32{1, 1}, + 2, 0, 0, nil, "", + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + // job manager setup + clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) + manager, sharedInformerFactory := newJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) + fakePodControl := controller.FakePodControl{} + manager.podControl = &fakePodControl + manager.podStoreSynced = alwaysReady + manager.jobStoreSynced = alwaysReady + var actual *batch.Job + manager.updateHandler = func(job *batch.Job) error { + actual = job + return nil + } + + // job & pods setup + job := newJob(tc.parallelism, tc.completions, tc.backoffLimit) + job.Spec.Template.Spec.RestartPolicy = v1.RestartPolicyOnFailure + sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job) + podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer() + for i, pod := range newPodList(int32(len(tc.restartCounts)), v1.PodRunning, job) { + pod.Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: tc.restartCounts[i]}} + podIndexer.Add(&pod) + } + + // run + forget, err := manager.syncJob(getKey(job, t)) + + if err != nil { + t.Errorf("unexpected error syncing job. Got %#v", err) + } + if forget != tc.jobKeyForget { + t.Errorf("unexpected forget value. Expected %v, saw %v\n", tc.jobKeyForget, forget) + } + // validate status + if actual.Status.Active != tc.expectedActive { + t.Errorf("unexpected number of active pods. Expected %d, saw %d\n", tc.expectedActive, actual.Status.Active) + } + if actual.Status.Succeeded != tc.expectedSucceeded { + t.Errorf("unexpected number of succeeded pods. Expected %d, saw %d\n", tc.expectedSucceeded, actual.Status.Succeeded) + } + if actual.Status.Failed != tc.expectedFailed { + t.Errorf("unexpected number of failed pods. Expected %d, saw %d\n", tc.expectedFailed, actual.Status.Failed) + } + // validate conditions + if tc.expectedCondition != nil && !getCondition(actual, *tc.expectedCondition, tc.expectedConditionReason) { + t.Errorf("expected completion condition. Got %#v", actual.Status.Conditions) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/BUILD index 672e19936..4e42d161d 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/BUILD @@ -31,7 +31,6 @@ go_test( srcs = ["namespaced_resources_deleter_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/namespaced_resources_deleter.go b/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/namespaced_resources_deleter.go index a89aec5ac..62e09392f 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/namespaced_resources_deleter.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/namespaced_resources_deleter.go @@ -43,13 +43,13 @@ type NamespacedResourcesDeleterInterface interface { } func NewNamespacedResourcesDeleter(nsClient v1clientset.NamespaceInterface, - clientPool dynamic.ClientPool, podsGetter v1clientset.PodsGetter, + dynamicClient dynamic.Interface, podsGetter v1clientset.PodsGetter, discoverResourcesFn func() ([]*metav1.APIResourceList, error), finalizerToken v1.FinalizerName, deleteNamespaceWhenDone bool) NamespacedResourcesDeleterInterface { d := &namespacedResourcesDeleter{ - nsClient: nsClient, - clientPool: clientPool, - podsGetter: podsGetter, + nsClient: nsClient, + dynamicClient: dynamicClient, + podsGetter: podsGetter, opCache: &operationNotSupportedCache{ m: make(map[operationKey]bool), }, @@ -68,7 +68,7 @@ type namespacedResourcesDeleter struct { // Client to manipulate the namespace. nsClient v1clientset.NamespaceInterface // Dynamic client to list and delete all namespaced resources. - clientPool dynamic.ClientPool + dynamicClient dynamic.Interface // Interface to get PodInterface. podsGetter v1clientset.PodsGetter // Cache of what operations are not supported on each group version resource. @@ -328,9 +328,7 @@ func (d *namespacedResourcesDeleter) finalizeNamespace(namespace *v1.Namespace) // deleteCollection is a helper function that will delete the collection of resources // it returns true if the operation was supported on the server. // it returns an error if the operation was supported on the server but was unable to complete. -func (d *namespacedResourcesDeleter) deleteCollection( - dynamicClient dynamic.Interface, gvr schema.GroupVersionResource, - namespace string) (bool, error) { +func (d *namespacedResourcesDeleter) deleteCollection(gvr schema.GroupVersionResource, namespace string) (bool, error) { glog.V(5).Infof("namespace controller - deleteCollection - namespace: %s, gvr: %v", namespace, gvr) key := operationKey{operation: operationDeleteCollection, gvr: gvr} @@ -339,14 +337,12 @@ func (d *namespacedResourcesDeleter) deleteCollection( return false, nil } - apiResource := metav1.APIResource{Name: gvr.Resource, Namespaced: true} - // namespace controller does not want the garbage collector to insert the orphan finalizer since it calls // resource deletions generically. it will ensure all resources in the namespace are purged prior to releasing // namespace itself. background := metav1.DeletePropagationBackground opts := &metav1.DeleteOptions{PropagationPolicy: &background} - err := dynamicClient.Resource(&apiResource, namespace).DeleteCollection(opts, metav1.ListOptions{}) + err := d.dynamicClient.Resource(gvr).Namespace(namespace).DeleteCollection(opts, metav1.ListOptions{}) if err == nil { return true, nil @@ -373,8 +369,7 @@ func (d *namespacedResourcesDeleter) deleteCollection( // the list of items in the collection (if found) // a boolean if the operation is supported // an error if the operation is supported but could not be completed. -func (d *namespacedResourcesDeleter) listCollection( - dynamicClient dynamic.Interface, gvr schema.GroupVersionResource, namespace string) (*unstructured.UnstructuredList, bool, error) { +func (d *namespacedResourcesDeleter) listCollection(gvr schema.GroupVersionResource, namespace string) (*unstructured.UnstructuredList, bool, error) { glog.V(5).Infof("namespace controller - listCollection - namespace: %s, gvr: %v", namespace, gvr) key := operationKey{operation: operationList, gvr: gvr} @@ -383,13 +378,8 @@ func (d *namespacedResourcesDeleter) listCollection( return nil, false, nil } - apiResource := metav1.APIResource{Name: gvr.Resource, Namespaced: true} - obj, err := dynamicClient.Resource(&apiResource, namespace).List(metav1.ListOptions{IncludeUninitialized: true}) + unstructuredList, err := d.dynamicClient.Resource(gvr).Namespace(namespace).List(metav1.ListOptions{IncludeUninitialized: true}) if err == nil { - unstructuredList, ok := obj.(*unstructured.UnstructuredList) - if !ok { - return nil, false, fmt.Errorf("resource: %s, expected *unstructured.UnstructuredList, got %#v", apiResource.Name, obj) - } return unstructuredList, true, nil } @@ -409,22 +399,20 @@ func (d *namespacedResourcesDeleter) listCollection( } // deleteEachItem is a helper function that will list the collection of resources and delete each item 1 by 1. -func (d *namespacedResourcesDeleter) deleteEachItem( - dynamicClient dynamic.Interface, gvr schema.GroupVersionResource, namespace string) error { +func (d *namespacedResourcesDeleter) deleteEachItem(gvr schema.GroupVersionResource, namespace string) error { glog.V(5).Infof("namespace controller - deleteEachItem - namespace: %s, gvr: %v", namespace, gvr) - unstructuredList, listSupported, err := d.listCollection(dynamicClient, gvr, namespace) + unstructuredList, listSupported, err := d.listCollection(gvr, namespace) if err != nil { return err } if !listSupported { return nil } - apiResource := metav1.APIResource{Name: gvr.Resource, Namespaced: true} for _, item := range unstructuredList.Items { background := metav1.DeletePropagationBackground opts := &metav1.DeleteOptions{PropagationPolicy: &background} - if err = dynamicClient.Resource(&apiResource, namespace).Delete(item.GetName(), opts); err != nil && !errors.IsNotFound(err) && !errors.IsMethodNotSupported(err) { + if err = d.dynamicClient.Resource(gvr).Namespace(namespace).Delete(item.GetName(), opts); err != nil && !errors.IsNotFound(err) && !errors.IsMethodNotSupported(err) { return err } } @@ -447,22 +435,15 @@ func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource( } glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - estimate - namespace: %s, gvr: %v, estimate: %v", namespace, gvr, estimate) - // get a client for this group version... - dynamicClient, err := d.clientPool.ClientForGroupVersionResource(gvr) - if err != nil { - glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - unable to get client - namespace: %s, gvr: %v, err: %v", namespace, gvr, err) - return estimate, err - } - // first try to delete the entire collection - deleteCollectionSupported, err := d.deleteCollection(dynamicClient, gvr, namespace) + deleteCollectionSupported, err := d.deleteCollection(gvr, namespace) if err != nil { return estimate, err } // delete collection was not supported, so we list and delete each item... if !deleteCollectionSupported { - err = d.deleteEachItem(dynamicClient, gvr, namespace) + err = d.deleteEachItem(gvr, namespace) if err != nil { return estimate, err } @@ -471,7 +452,7 @@ func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource( // verify there are no more remaining items // it is not an error condition for there to be remaining items if local estimate is non-zero glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - checking for no more items in namespace: %s, gvr: %v", namespace, gvr) - unstructuredList, listSupported, err := d.listCollection(dynamicClient, gvr, namespace) + unstructuredList, listSupported, err := d.listCollection(gvr, namespace) if err != nil { glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - error verifying no items in namespace: %s, gvr: %v, err: %v", namespace, gvr, err) return estimate, err @@ -497,8 +478,7 @@ func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource( // deleteAllContent will use the dynamic client to delete each resource identified in groupVersionResources. // It returns an estimate of the time remaining before the remaining resources are deleted. // If estimate > 0, not all resources are guaranteed to be gone. -func (d *namespacedResourcesDeleter) deleteAllContent( - namespace string, namespaceDeletedAt metav1.Time) (int64, error) { +func (d *namespacedResourcesDeleter) deleteAllContent(namespace string, namespaceDeletedAt metav1.Time) (int64, error) { estimate := int64(0) glog.V(4).Infof("namespace controller - deleteAllContent - namespace: %s", namespace) resources, err := d.discoverResourcesFn() diff --git a/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/namespaced_resources_deleter_test.go b/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/namespaced_resources_deleter_test.go index d20cb4b10..5a3563375 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/namespaced_resources_deleter_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/namespace/deletion/namespaced_resources_deleter_test.go @@ -36,7 +36,6 @@ import ( "k8s.io/client-go/kubernetes/fake" restclient "k8s.io/client-go/rest" core "k8s.io/client-go/testing" - "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" ) @@ -173,14 +172,16 @@ func testSyncNamespaceThatIsTerminating(t *testing.T, versions *metav1.APIVersio defer srv.Close() mockClient := fake.NewSimpleClientset(testInput.testNamespace) - clientPool := dynamic.NewClientPool(clientConfig, legacyscheme.Registry.RESTMapper(), dynamic.LegacyAPIPathResolverFunc) + dynamicClient, err := dynamic.NewForConfig(clientConfig) + if err != nil { + t.Fatal(err) + } fn := func() ([]*metav1.APIResourceList, error) { return resources, nil } - d := NewNamespacedResourcesDeleter(mockClient.Core().Namespaces(), clientPool, mockClient.Core(), fn, v1.FinalizerKubernetes, true) - err := d.Delete(testInput.testNamespace.Name) - if err != nil { + d := NewNamespacedResourcesDeleter(mockClient.Core().Namespaces(), dynamicClient, mockClient.Core(), fn, v1.FinalizerKubernetes, true) + if err := d.Delete(testInput.testNamespace.Name); err != nil { t.Errorf("scenario %s - Unexpected error when synching namespace %v", scenario, err) } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller.go index 32a0bb33f..3164d290b 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller.go @@ -63,7 +63,7 @@ type NamespaceController struct { // NewNamespaceController creates a new NamespaceController func NewNamespaceController( kubeClient clientset.Interface, - clientPool dynamic.ClientPool, + dynamicClient dynamic.Interface, discoverResourcesFn func() ([]*metav1.APIResourceList, error), namespaceInformer coreinformers.NamespaceInformer, resyncPeriod time.Duration, @@ -72,7 +72,7 @@ func NewNamespaceController( // create the controller so we can inject the enqueue function namespaceController := &NamespaceController{ queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespace"), - namespacedResourcesDeleter: deletion.NewNamespacedResourcesDeleter(kubeClient.CoreV1().Namespaces(), clientPool, kubeClient.CoreV1(), discoverResourcesFn, finalizerToken, true), + namespacedResourcesDeleter: deletion.NewNamespacedResourcesDeleter(kubeClient.CoreV1().Namespaces(), dynamicClient, kubeClient.CoreV1(), discoverResourcesFn, finalizerToken, true), } if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { @@ -163,7 +163,7 @@ func (nm *NamespaceController) worker() { func (nm *NamespaceController) syncNamespaceFromKey(key string) (err error) { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing namespace %q (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing namespace %q (%v)", key, time.Since(startTime)) }() namespace, err := nm.lister.Get(key) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/BUILD index 653fb14f1..603a43fde 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/BUILD @@ -49,7 +49,9 @@ go_library( "//pkg/controller/nodeipam/ipam/cidrset:go_default_library", "//pkg/controller/nodeipam/ipam/sync:go_default_library", "//pkg/controller/util/node:go_default_library", + "//pkg/scheduler/algorithm:go_default_library", "//pkg/util/node:go_default_library", + "//pkg/util/taints:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/adapter.go b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/adapter.go index 6a5d9e480..c393a6f75 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/adapter.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/adapter.go @@ -52,7 +52,7 @@ func newAdapter(k8s clientset.Interface, cloud *gce.GCECloud) *adapter { ret.recorder = broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloudCIDRAllocator"}) glog.V(0).Infof("Sending events to api server.") broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{ - Interface: v1core.New(k8s.CoreV1().RESTClient()).Events(""), + Interface: k8s.CoreV1().Events(""), }) return ret diff --git a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/cloud_cidr_allocator.go b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/cloud_cidr_allocator.go index c45c5acec..087e04a39 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/cloud_cidr_allocator.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/cloud_cidr_allocator.go @@ -42,7 +42,9 @@ import ( "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" "k8s.io/kubernetes/pkg/controller" nodeutil "k8s.io/kubernetes/pkg/controller/util/node" + "k8s.io/kubernetes/pkg/scheduler/algorithm" utilnode "k8s.io/kubernetes/pkg/util/node" + utiltaints "k8s.io/kubernetes/pkg/util/taints" ) // nodeProcessingInfo tracks information related to current nodes in processing @@ -88,7 +90,7 @@ func NewCloudCIDRAllocator(client clientset.Interface, cloud cloudprovider.Inter recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cidrAllocator"}) eventBroadcaster.StartLogging(glog.Infof) glog.V(0).Infof("Sending events to api server.") - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(client.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: client.CoreV1().Events("")}) gceCloud, ok := cloud.(*gce.GCECloud) if !ok { @@ -114,8 +116,9 @@ func NewCloudCIDRAllocator(client clientset.Interface, cloud cloudprovider.Inter } // Even if PodCIDR is assigned, but NetworkUnavailable condition is // set to true, we need to process the node to set the condition. + networkUnavailableTaint := &v1.Taint{Key: algorithm.TaintNodeNetworkUnavailable, Effect: v1.TaintEffectNoSchedule} _, cond := v1node.GetNodeCondition(&newNode.Status, v1.NodeNetworkUnavailable) - if cond == nil || cond.Status != v1.ConditionFalse { + if cond == nil || cond.Status != v1.ConditionFalse || utiltaints.TaintExists(newNode.Spec.Taints, networkUnavailableTaint) { return ca.AllocateOrOccupyCIDR(newNode) } return nil diff --git a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/range_allocator.go b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/range_allocator.go index 241bc2f1b..de3e27a55 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/range_allocator.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/range_allocator.go @@ -76,7 +76,7 @@ func NewCIDRRangeAllocator(client clientset.Interface, nodeInformer informers.No recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cidrAllocator"}) eventBroadcaster.StartLogging(glog.Infof) glog.V(0).Infof("Sending events to api server.") - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(client.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: client.CoreV1().Events("")}) set, err := cidrset.NewCIDRSet(clusterCIDR, subNetMaskSize) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/node_ipam_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/node_ipam_controller.go index e66cd776b..94f8e2ca8 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/node_ipam_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/nodeipam/node_ipam_controller.go @@ -99,7 +99,7 @@ func NewNodeIpamController( glog.V(0).Infof("Sending events to api server.") eventBroadcaster.StartRecordingToSink( &v1core.EventSinkImpl{ - Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events(""), + Interface: kubeClient.CoreV1().Events(""), }) if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/node_lifecycle_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/node_lifecycle_controller.go index 5337f715f..81774d196 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/node_lifecycle_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/node_lifecycle_controller.go @@ -22,6 +22,7 @@ limitations under the License. package nodelifecycle import ( + "context" "fmt" "sync" "time" @@ -107,8 +108,6 @@ const ( ) const ( - // The amount of time the nodecontroller polls on the list nodes endpoint. - apiserverStartupGracePeriod = 10 * time.Minute // The amount of time the nodecontroller should sleep between retrying NodeStatus updates retrySleepTime = 20 * time.Millisecond ) @@ -153,9 +152,10 @@ type Controller struct { daemonSetStore extensionslisters.DaemonSetLister daemonSetInformerSynced cache.InformerSynced - nodeLister corelisters.NodeLister - nodeInformerSynced cache.InformerSynced - nodeExistsInCloudProvider func(types.NodeName) (bool, error) + nodeLister corelisters.NodeLister + nodeInformerSynced cache.InformerSynced + nodeExistsInCloudProvider func(types.NodeName) (bool, error) + nodeShutdownInCloudProvider func(context.Context, *v1.Node) (bool, error) recorder record.EventRecorder @@ -241,6 +241,9 @@ func NewNodeLifecycleController(podInformer coreinformers.PodInformer, nodeExistsInCloudProvider: func(nodeName types.NodeName) (bool, error) { return nodeutil.ExistsInCloudProvider(cloud, nodeName) }, + nodeShutdownInCloudProvider: func(ctx context.Context, node *v1.Node) (bool, error) { + return nodeutil.ShutdownInCloudProvider(ctx, cloud, node) + }, recorder: recorder, nodeMonitorPeriod: nodeMonitorPeriod, nodeStartupGracePeriod: nodeStartupGracePeriod, @@ -669,6 +672,11 @@ func (nc *Controller) monitorNodeStatus() error { glog.V(2).Infof("Node %s is ready again, cancelled pod eviction", node.Name) } } + // remove shutdown taint this is needed always depending do we use taintbased or not + err := nc.markNodeAsNotShutdown(node) + if err != nil { + glog.Errorf("Failed to remove taints from node %v. Will retry in next iteration.", node.Name) + } } // Report node event. @@ -682,6 +690,19 @@ func (nc *Controller) monitorNodeStatus() error { // Check with the cloud provider to see if the node still exists. If it // doesn't, delete the node immediately. if currentReadyCondition.Status != v1.ConditionTrue && nc.cloud != nil { + // check is node shutdowned, if yes do not deleted it. Instead add taint + shutdown, err := nc.nodeShutdownInCloudProvider(context.TODO(), node) + if err != nil { + glog.Errorf("Error determining if node %v shutdown in cloud: %v", node.Name, err) + } + // node shutdown + if shutdown && err == nil { + err = controller.AddOrUpdateTaintOnNode(nc.kubeClient, node.Name, controller.ShutdownTaint) + if err != nil { + glog.Errorf("Error patching node taints: %v", err) + } + continue + } exists, err := nc.nodeExistsInCloudProvider(types.NodeName(node.Name)) if err != nil { glog.Errorf("Error determining if node %v exists in cloud: %v", node.Name, err) @@ -1056,6 +1077,8 @@ func (nc *Controller) ReducedQPSFunc(nodeNum int) float32 { // addPodEvictorForNewZone checks if new zone appeared, and if so add new evictor. func (nc *Controller) addPodEvictorForNewZone(node *v1.Node) { + nc.evictorLock.Lock() + defer nc.evictorLock.Unlock() zone := utilnode.GetZoneKey(node) if _, found := nc.zoneStates[zone]; !found { nc.zoneStates[zone] = stateInitial @@ -1118,6 +1141,17 @@ func (nc *Controller) markNodeAsReachable(node *v1.Node) (bool, error) { return nc.zoneNoExecuteTainter[utilnode.GetZoneKey(node)].Remove(node.Name), nil } +func (nc *Controller) markNodeAsNotShutdown(node *v1.Node) error { + nc.evictorLock.Lock() + defer nc.evictorLock.Unlock() + err := controller.RemoveTaintOffNode(nc.kubeClient, node.Name, node, controller.ShutdownTaint) + if err != nil { + glog.Errorf("Failed to remove taint from node %v: %v", node.Name, err) + return err + } + return nil +} + // ComputeZoneState returns a slice of NodeReadyConditions for all Nodes in a given zone. // The zone is considered: // - fullyDisrupted if there're no Ready Nodes, diff --git a/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/node_lifecycle_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/node_lifecycle_controller_test.go index 365f31dc9..35f37e2ba 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/node_lifecycle_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/node_lifecycle_controller_test.go @@ -17,6 +17,7 @@ limitations under the License. package nodelifecycle import ( + "context" "strings" "testing" "time" @@ -1360,6 +1361,118 @@ func TestMonitorNodeStatusEvictPodsWithDisruption(t *testing.T) { } } +func TestCloudProviderNodeShutdown(t *testing.T) { + + testCases := []struct { + testName string + node *v1.Node + shutdown bool + }{ + { + testName: "node shutdowned add taint", + shutdown: true, + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Spec: v1.NodeSpec{ + ProviderID: "node0", + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionUnknown, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + { + testName: "node started after shutdown remove taint", + shutdown: false, + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Spec: v1.NodeSpec{ + ProviderID: "node0", + Taints: []v1.Taint{ + { + Key: algorithm.TaintNodeShutdown, + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionTrue, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.testName, func(t *testing.T) { + fnh := &testutil.FakeNodeHandler{ + Existing: []*v1.Node{tc.node}, + Clientset: fake.NewSimpleClientset(), + } + nodeController, _ := newNodeLifecycleControllerFromClient( + nil, + fnh, + 10*time.Minute, + testRateLimiterQPS, + testRateLimiterQPS, + testLargeClusterThreshold, + testUnhealthyThreshold, + testNodeMonitorGracePeriod, + testNodeStartupGracePeriod, + testNodeMonitorPeriod, + false) + nodeController.cloud = &fakecloud.FakeCloud{} + nodeController.now = func() metav1.Time { return metav1.Date(2016, 1, 1, 12, 0, 0, 0, time.UTC) } + nodeController.recorder = testutil.NewFakeRecorder() + nodeController.nodeShutdownInCloudProvider = func(ctx context.Context, node *v1.Node) (bool, error) { + return tc.shutdown, nil + } + + if err := nodeController.syncNodeStore(fnh); err != nil { + t.Errorf("unexpected error: %v", err) + } + if err := nodeController.monitorNodeStatus(); err != nil { + t.Errorf("unexpected error: %v", err) + } + + if len(fnh.UpdatedNodes) != 1 { + t.Errorf("Node was not updated") + } + if tc.shutdown { + if len(fnh.UpdatedNodes[0].Spec.Taints) != 1 { + t.Errorf("Node Taint was not added") + } + if fnh.UpdatedNodes[0].Spec.Taints[0].Key != "node.cloudprovider.kubernetes.io/shutdown" { + t.Errorf("Node Taint key is not correct") + } + } else { + if len(fnh.UpdatedNodes[0].Spec.Taints) != 0 { + t.Errorf("Node Taint was not removed after node is back in ready state") + } + } + }) + } + +} + // TestCloudProviderNoRateLimit tests that monitorNodes() immediately deletes // pods and the node when kubelet has not reported, and the cloudprovider says // the node is gone. @@ -1404,6 +1517,9 @@ func TestCloudProviderNoRateLimit(t *testing.T) { nodeController.nodeExistsInCloudProvider = func(nodeName types.NodeName) (bool, error) { return false, nil } + nodeController.nodeShutdownInCloudProvider = func(ctx context.Context, node *v1.Node) (bool, error) { + return false, nil + } // monitorNodeStatus should allow this node to be immediately deleted if err := nodeController.syncNodeStore(fnh); err != nil { t.Errorf("unexpected error: %v", err) @@ -1543,9 +1659,6 @@ func TestMonitorNodeStatusUpdateStatus(t *testing.T) { v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"), }, }, - Spec: v1.NodeSpec{ - ExternalID: "node0", - }, }, }, Clientset: fake.NewSimpleClientset(&v1.PodList{Items: []v1.Pod{*testutil.NewPod("pod0", "node0")}}), @@ -1620,9 +1733,6 @@ func TestMonitorNodeStatusUpdateStatus(t *testing.T) { v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"), }, }, - Spec: v1.NodeSpec{ - ExternalID: "node0", - }, }, }, }, @@ -1651,9 +1761,6 @@ func TestMonitorNodeStatusUpdateStatus(t *testing.T) { v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"), }, }, - Spec: v1.NodeSpec{ - ExternalID: "node0", - }, }, }, Clientset: fake.NewSimpleClientset(&v1.PodList{Items: []v1.Pod{*testutil.NewPod("pod0", "node0")}}), @@ -1755,9 +1862,6 @@ func TestMonitorNodeStatusMarkPodsNotReady(t *testing.T) { v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"), }, }, - Spec: v1.NodeSpec{ - ExternalID: "node0", - }, }, }, Clientset: fake.NewSimpleClientset(&v1.PodList{Items: []v1.Pod{*testutil.NewPod("pod0", "node0")}}), @@ -1789,9 +1893,6 @@ func TestMonitorNodeStatusMarkPodsNotReady(t *testing.T) { v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"), }, }, - Spec: v1.NodeSpec{ - ExternalID: "node0", - }, }, }, Clientset: fake.NewSimpleClientset(&v1.PodList{Items: []v1.Pod{*testutil.NewPod("pod0", "node0")}}), @@ -2208,9 +2309,6 @@ func TestNodeEventGeneration(t *testing.T) { UID: "1234567890", CreationTimestamp: metav1.Date(2015, 8, 10, 0, 0, 0, 0, time.UTC), }, - Spec: v1.NodeSpec{ - ExternalID: "node0", - }, Status: v1.NodeStatus{ Conditions: []v1.NodeCondition{ { @@ -2242,6 +2340,9 @@ func TestNodeEventGeneration(t *testing.T) { nodeController.nodeExistsInCloudProvider = func(nodeName types.NodeName) (bool, error) { return false, nil } + nodeController.nodeShutdownInCloudProvider = func(ctx context.Context, node *v1.Node) (bool, error) { + return false, nil + } nodeController.now = func() metav1.Time { return fakeNow } fakeRecorder := testutil.NewFakeRecorder() nodeController.recorder = fakeRecorder diff --git a/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler/taint_manager.go b/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler/taint_manager.go index a71fa8fc7..d90d8c1b9 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler/taint_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler/taint_manager.go @@ -18,22 +18,23 @@ package scheduler import ( "fmt" - "k8s.io/api/core/v1" - clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/apis/core/helper" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" + "hash/fnv" + "io" + "sync" + "time" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" - "sync" - "time" - + clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" v1core "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" + "k8s.io/kubernetes/pkg/apis/core/helper" + v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "github.com/golang/glog" ) @@ -59,6 +60,32 @@ type podUpdateItem struct { newTolerations []v1.Toleration } +func (n *nodeUpdateItem) name() string { + if n.newNode != nil { + return n.newNode.ObjectMeta.Name + } + if n.oldNode != nil { + return n.oldNode.ObjectMeta.Name + } + return "" +} + +func (p *podUpdateItem) nodeName() string { + if p.newPod != nil { + return p.newPod.Spec.NodeName + } + if p.oldPod != nil { + return p.oldPod.Spec.NodeName + } + return "" +} + +func hash(val string, max int) int { + hasher := fnv.New32a() + io.WriteString(hasher, val) + return int(hasher.Sum32() % uint32(max)) +} + // NoExecuteTaintManager listens to Taint/Toleration changes and is responsible for removing Pods // from Nodes tainted with NoExecute Taints. type NoExecuteTaintManager struct { @@ -70,8 +97,8 @@ type NoExecuteTaintManager struct { taintedNodesLock sync.Mutex taintedNodes map[string][]v1.Taint - nodeUpdateChannel chan *nodeUpdateItem - podUpdateChannel chan *podUpdateItem + nodeUpdateChannels []chan *nodeUpdateItem + podUpdateChannels []chan *podUpdateItem nodeUpdateQueue workqueue.Interface podUpdateQueue workqueue.Interface @@ -155,17 +182,15 @@ func NewNoExecuteTaintManager(c clientset.Interface) *NoExecuteTaintManager { eventBroadcaster.StartLogging(glog.Infof) if c != nil { glog.V(0).Infof("Sending events to api server.") - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(c.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: c.CoreV1().Events("")}) } else { glog.Fatalf("kubeClient is nil when starting NodeController") } tm := &NoExecuteTaintManager{ - client: c, - recorder: recorder, - taintedNodes: make(map[string][]v1.Taint), - nodeUpdateChannel: make(chan *nodeUpdateItem, nodeUpdateChannelSize), - podUpdateChannel: make(chan *podUpdateItem, podUpdateChannelSize), + client: c, + recorder: recorder, + taintedNodes: make(map[string][]v1.Taint), nodeUpdateQueue: workqueue.New(), podUpdateQueue: workqueue.New(), @@ -178,6 +203,15 @@ func NewNoExecuteTaintManager(c clientset.Interface) *NoExecuteTaintManager { // Run starts NoExecuteTaintManager which will run in loop until `stopCh` is closed. func (tc *NoExecuteTaintManager) Run(stopCh <-chan struct{}) { glog.V(0).Infof("Starting NoExecuteTaintManager") + + // TODO: Figure out a reasonable number of workers and propagate the + // number of workers up making it a paramater of Run() function. + workers := 8 + for i := 0; i < workers; i++ { + tc.nodeUpdateChannels = append(tc.nodeUpdateChannels, make(chan *nodeUpdateItem, nodeUpdateChannelSize)) + tc.podUpdateChannels = append(tc.podUpdateChannels, make(chan *podUpdateItem, podUpdateChannelSize)) + } + // Functions that are responsible for taking work items out of the workqueues and putting them // into channels. go func(stopCh <-chan struct{}) { @@ -187,11 +221,14 @@ func (tc *NoExecuteTaintManager) Run(stopCh <-chan struct{}) { break } nodeUpdate := item.(*nodeUpdateItem) + hash := hash(nodeUpdate.name(), workers) select { case <-stopCh: + tc.nodeUpdateQueue.Done(item) break - case tc.nodeUpdateChannel <- nodeUpdate: + case tc.nodeUpdateChannels[hash] <- nodeUpdate: } + tc.nodeUpdateQueue.Done(item) } }(stopCh) @@ -202,14 +239,28 @@ func (tc *NoExecuteTaintManager) Run(stopCh <-chan struct{}) { break } podUpdate := item.(*podUpdateItem) + hash := hash(podUpdate.nodeName(), workers) select { case <-stopCh: + tc.podUpdateQueue.Done(item) break - case tc.podUpdateChannel <- podUpdate: + case tc.podUpdateChannels[hash] <- podUpdate: } + tc.podUpdateQueue.Done(item) } }(stopCh) + wg := sync.WaitGroup{} + wg.Add(workers) + for i := 0; i < workers; i++ { + go tc.worker(i, wg.Done, stopCh) + } + wg.Wait() +} + +func (tc *NoExecuteTaintManager) worker(worker int, done func(), stopCh <-chan struct{}) { + defer done() + // When processing events we want to prioritize Node updates over Pod updates, // as NodeUpdates that interest NoExecuteTaintManager should be handled as soon as possible - // we don't want user (or system) to wait until PodUpdate queue is drained before it can @@ -217,15 +268,15 @@ func (tc *NoExecuteTaintManager) Run(stopCh <-chan struct{}) { for { select { case <-stopCh: - break - case nodeUpdate := <-tc.nodeUpdateChannel: + return + case nodeUpdate := <-tc.nodeUpdateChannels[worker]: tc.handleNodeUpdate(nodeUpdate) - case podUpdate := <-tc.podUpdateChannel: + case podUpdate := <-tc.podUpdateChannels[worker]: // If we found a Pod update we need to empty Node queue first. priority: for { select { - case nodeUpdate := <-tc.nodeUpdateChannel: + case nodeUpdate := <-tc.nodeUpdateChannels[worker]: tc.handleNodeUpdate(nodeUpdate) default: break priority diff --git a/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler/timed_workers_test.go b/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler/timed_workers_test.go index e07c6daee..9489fd184 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler/timed_workers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler/timed_workers_test.go @@ -61,7 +61,7 @@ func TestExecuteDelayed(t *testing.T) { return nil }) now := time.Now() - then := now.Add(3 * time.Second) + then := now.Add(10 * time.Second) queue.AddWork(NewWorkArgs("1", "1"), now, then) queue.AddWork(NewWorkArgs("2", "2"), now, then) queue.AddWork(NewWorkArgs("3", "3"), now, then) @@ -89,7 +89,7 @@ func TestCancel(t *testing.T) { return nil }) now := time.Now() - then := now.Add(3 * time.Second) + then := now.Add(10 * time.Second) queue.AddWork(NewWorkArgs("1", "1"), now, then) queue.AddWork(NewWorkArgs("2", "2"), now, then) queue.AddWork(NewWorkArgs("3", "3"), now, then) @@ -119,7 +119,7 @@ func TestCancelAndReadd(t *testing.T) { return nil }) now := time.Now() - then := now.Add(3 * time.Second) + then := now.Add(10 * time.Second) queue.AddWork(NewWorkArgs("1", "1"), now, then) queue.AddWork(NewWorkArgs("2", "2"), now, then) queue.AddWork(NewWorkArgs("3", "3"), now, then) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/BUILD index 7313619df..5e9ec7ffa 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/BUILD @@ -69,6 +69,7 @@ go_test( "//vendor/k8s.io/api/autoscaling/v1:go_default_library", "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper: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/labels:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal.go b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal.go index 737ceb9bb..2ca40458d 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal.go @@ -91,7 +91,6 @@ func NewHorizontalController( ) *HorizontalController { broadcaster := record.NewBroadcaster() broadcaster.StartLogging(glog.Infof) - // TODO: remove the wrapper when every clients have moved to use the clientset. broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: evtNamespacer.Events("")}) recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "horizontal-pod-autoscaler"}) @@ -223,7 +222,7 @@ func (a *HorizontalController) computeReplicasForMetrics(hpa *autoscalingv2.Hori switch metricSpec.Type { case autoscalingv2.ObjectMetricSourceType: - replicaCountProposal, utilizationProposal, timestampProposal, err = a.replicaCalc.GetObjectMetricReplicas(currentReplicas, metricSpec.Object.TargetValue.MilliValue(), metricSpec.Object.MetricName, hpa.Namespace, &metricSpec.Object.Target) + replicaCountProposal, utilizationProposal, timestampProposal, err = a.replicaCalc.GetObjectMetricReplicas(currentReplicas, metricSpec.Object.TargetValue.MilliValue(), metricSpec.Object.MetricName, hpa.Namespace, &metricSpec.Object.Target, selector) if err != nil { a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetObjectMetric", err.Error()) setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetObjectMetric", "the HPA was unable to compute the replica count: %v", err) @@ -317,7 +316,7 @@ func (a *HorizontalController) computeReplicasForMetrics(hpa *autoscalingv2.Hori }, } } else if metricSpec.External.TargetValue != nil { - replicaCountProposal, utilizationProposal, timestampProposal, err = a.replicaCalc.GetExternalMetricReplicas(currentReplicas, metricSpec.External.TargetValue.MilliValue(), metricSpec.External.MetricName, hpa.Namespace, metricSpec.External.MetricSelector) + replicaCountProposal, utilizationProposal, timestampProposal, err = a.replicaCalc.GetExternalMetricReplicas(currentReplicas, metricSpec.External.TargetValue.MilliValue(), metricSpec.External.MetricName, hpa.Namespace, metricSpec.External.MetricSelector, selector) if err != nil { a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetExternalMetric", err.Error()) setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetExternalMetric", "the HPA was unable to compute the replica count: %v", err) @@ -621,7 +620,7 @@ func (a *HorizontalController) shouldScale(hpa *autoscalingv2.HorizontalPodAutos func (a *HorizontalController) scaleForResourceMappings(namespace, name string, mappings []*apimeta.RESTMapping) (*autoscalingv1.Scale, schema.GroupResource, error) { var firstErr error for i, mapping := range mappings { - targetGR := mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource).GroupResource() + targetGR := mapping.Resource.GroupResource() scale, err := a.scaleNamespacer.Scales(namespace).Get(targetGR, name) if err == nil { return scale, targetGR, nil diff --git a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal_test.go b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal_test.go index 2d74a8aef..86f9d7144 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal_test.go @@ -27,6 +27,7 @@ import ( autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv2 "k8s.io/api/autoscaling/v2beta1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -124,6 +125,7 @@ type testCase struct { testClient *fake.Clientset testMetricsClient *metricsfake.Clientset testCMClient *cmfake.FakeCustomMetricsClient + testEMClient *emfake.FakeExternalMetricsClient testScaleClient *scalefake.FakeScaleClient } @@ -246,16 +248,32 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa defer tc.Unlock() obj := &v1.PodList{} - for i := 0; i < len(tc.reportedCPURequests); i++ { + + specifiedCPURequests := tc.reportedCPURequests != nil + + numPodsToCreate := int(tc.initialReplicas) + if specifiedCPURequests { + numPodsToCreate = len(tc.reportedCPURequests) + } + + for i := 0; i < numPodsToCreate; i++ { podReadiness := v1.ConditionTrue if tc.reportedPodReadiness != nil { podReadiness = tc.reportedPodReadiness[i] } + podPhase := v1.PodRunning if tc.reportedPodPhase != nil { podPhase = tc.reportedPodPhase[i] } + podName := fmt.Sprintf("%s-%d", podNamePrefix, i) + + reportedCPURequest := resource.MustParse("1.0") + if specifiedCPURequests { + reportedCPURequest = tc.reportedCPURequests[i] + } + pod := v1.Pod{ Status: v1.PodStatus{ Phase: podPhase, @@ -273,12 +291,13 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa "name": podNamePrefix, }, }, + Spec: v1.PodSpec{ Containers: []v1.Container{ { Resources: v1.ResourceRequirements{ Requests: v1.ResourceList{ - v1.ResourceCPU: tc.reportedCPURequests[i], + v1.ResourceCPU: reportedCPURequest, }, }, }, @@ -493,7 +512,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa } name := getForAction.GetName() - mapper := legacyscheme.Registry.RESTMapper() + mapper := testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme) metrics := &cmapi.MetricValueList{} var matchedTarget *autoscalingv2.MetricSpec for i, target := range tc.metricsTarget { @@ -504,7 +523,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa t.Logf("unable to get mapping for %s: %v", gk.String(), err) continue } - groupResource := schema.GroupResource{Group: mapping.GroupVersionKind.Group, Resource: mapping.Resource} + groupResource := mapping.Resource.GroupResource() if getForAction.GetResource().Resource == groupResource.String() { matchedTarget = &tc.metricsTarget[i] @@ -582,6 +601,9 @@ func (tc *testCase) setupController(t *testing.T) (*HorizontalController, inform if tc.testCMClient != nil { testCMClient = tc.testCMClient } + if tc.testEMClient != nil { + testEMClient = tc.testEMClient + } if tc.testScaleClient != nil { testScaleClient = tc.testScaleClient } @@ -628,7 +650,7 @@ func (tc *testCase) setupController(t *testing.T) (*HorizontalController, inform eventClient.Core(), testScaleClient, testClient.Autoscaling(), - legacyscheme.Registry.RESTMapper(), + testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme), replicaCalc, informerFactory.Autoscaling().V1().HorizontalPodAutoscalers(), controller.NoResyncPeriodFunc(), @@ -1348,13 +1370,14 @@ func TestEmptyMetrics(t *testing.T) { func TestEmptyCPURequest(t *testing.T) { tc := testCase{ - minReplicas: 1, - maxReplicas: 5, - initialReplicas: 1, - desiredReplicas: 1, - CPUTarget: 100, - reportedLevels: []uint64{200}, - useMetricsAPI: true, + minReplicas: 1, + maxReplicas: 5, + initialReplicas: 1, + desiredReplicas: 1, + CPUTarget: 100, + reportedLevels: []uint64{200}, + reportedCPURequests: []resource.Quantity{}, + useMetricsAPI: true, expectedConditions: []autoscalingv1.HorizontalPodAutoscalerCondition{ {Type: autoscalingv1.AbleToScale, Status: v1.ConditionTrue, Reason: "SucceededGetScale"}, {Type: autoscalingv1.ScalingActive, Status: v1.ConditionFalse, Reason: "FailedGetResourceMetric"}, @@ -1568,6 +1591,16 @@ func TestConditionFailedGetMetrics(t *testing.T) { }, }, }, + "FailedGetExternalMetric": { + { + Type: autoscalingv2.ExternalMetricSourceType, + External: &autoscalingv2.ExternalMetricSource{ + MetricSelector: &metav1.LabelSelector{}, + MetricName: "qps", + TargetValue: resource.NewMilliQuantity(300, resource.DecimalSI), + }, + }, + }, } for reason, specs := range metricsTargets { @@ -1581,9 +1614,10 @@ func TestConditionFailedGetMetrics(t *testing.T) { reportedCPURequests: []resource.Quantity{resource.MustParse("0.1"), resource.MustParse("0.1"), resource.MustParse("0.1")}, useMetricsAPI: true, } - _, testMetricsClient, testCMClient, _, _ := tc.prepareTestClient(t) + _, testMetricsClient, testCMClient, testEMClient, _ := tc.prepareTestClient(t) tc.testMetricsClient = testMetricsClient tc.testCMClient = testCMClient + tc.testEMClient = testEMClient testMetricsClient.PrependReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, &metricsapi.PodMetricsList{}, fmt.Errorf("something went wrong") @@ -1591,6 +1625,9 @@ func TestConditionFailedGetMetrics(t *testing.T) { testCMClient.PrependReactor("get", "*", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, &cmapi.MetricValueList{}, fmt.Errorf("something went wrong") }) + testEMClient.PrependReactor("list", "*", func(action core.Action) (handled bool, ret runtime.Object, err error) { + return true, &emapi.ExternalMetricValueList{}, fmt.Errorf("something went wrong") + }) tc.expectedConditions = []autoscalingv1.HorizontalPodAutoscalerCondition{ {Type: autoscalingv1.AbleToScale, Status: v1.ConditionTrue, Reason: "SucceededGetScale"}, diff --git a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/legacy_horizontal_test.go b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/legacy_horizontal_test.go index 1254634d5..b6ffc18c3 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/legacy_horizontal_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/legacy_horizontal_test.go @@ -30,6 +30,7 @@ import ( autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv2 "k8s.io/api/autoscaling/v2beta1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -497,7 +498,7 @@ func (tc *legacyTestCase) runTest(t *testing.T) { eventClient.Core(), testScaleClient, testClient.Autoscaling(), - legacyscheme.Registry.RESTMapper(), + testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme), replicaCalc, informerFactory.Autoscaling().V1().HorizontalPodAutoscalers(), controller.NoResyncPeriodFunc(), @@ -524,7 +525,7 @@ func (tc *legacyTestCase) runTest(t *testing.T) { tc.verifyResults(t) } -func LegacyTestScaleUp(t *testing.T) { +func TestLegacyScaleUp(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -539,7 +540,7 @@ func LegacyTestScaleUp(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleUpUnreadyLessScale(t *testing.T) { +func TestLegacyScaleUpUnreadyLessScale(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -556,7 +557,7 @@ func LegacyTestScaleUpUnreadyLessScale(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleUpUnreadyNoScale(t *testing.T) { +func TestLegacyScaleUpUnreadyNoScale(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -573,7 +574,7 @@ func LegacyTestScaleUpUnreadyNoScale(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleUpDeployment(t *testing.T) { +func TestLegacyScaleUpDeployment(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -593,7 +594,7 @@ func LegacyTestScaleUpDeployment(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleUpReplicaSet(t *testing.T) { +func TestLegacyScaleUpReplicaSet(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -613,7 +614,7 @@ func LegacyTestScaleUpReplicaSet(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleUpCM(t *testing.T) { +func TestLegacyScaleUpCM(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -635,7 +636,7 @@ func LegacyTestScaleUpCM(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleUpCMUnreadyLessScale(t *testing.T) { +func TestLegacyScaleUpCMUnreadyLessScale(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -658,7 +659,7 @@ func LegacyTestScaleUpCMUnreadyLessScale(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleUpCMUnreadyNoScaleWouldScaleDown(t *testing.T) { +func TestLegacyScaleUpCMUnreadyNoScaleWouldScaleDown(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -681,7 +682,7 @@ func LegacyTestScaleUpCMUnreadyNoScaleWouldScaleDown(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleDown(t *testing.T) { +func TestLegacyScaleDown(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -696,7 +697,7 @@ func LegacyTestScaleDown(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleDownCM(t *testing.T) { +func TestLegacyScaleDownCM(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -718,7 +719,7 @@ func LegacyTestScaleDownCM(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleDownIgnoresUnreadyPods(t *testing.T) { +func TestLegacyScaleDownIgnoresUnreadyPods(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -840,7 +841,7 @@ func LegacyTestMaxReplicas(t *testing.T) { tc.runTest(t) } -func LegacyTestSuperfluousMetrics(t *testing.T) { +func TestLegacySuperfluousMetrics(t *testing.T) { tc := legacyTestCase{ minReplicas: 2, maxReplicas: 6, @@ -1022,7 +1023,7 @@ func LegacyTestComputedToleranceAlgImplementation(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleUpRCImmediately(t *testing.T) { +func TestLegacyScaleUpRCImmediately(t *testing.T) { time := metav1.Time{Time: time.Now()} tc := legacyTestCase{ minReplicas: 2, @@ -1038,7 +1039,7 @@ func LegacyTestScaleUpRCImmediately(t *testing.T) { tc.runTest(t) } -func LegacyTestScaleDownRCImmediately(t *testing.T) { +func TestLegacyScaleDownRCImmediately(t *testing.T) { time := metav1.Time{Time: time.Now()} tc := legacyTestCase{ minReplicas: 2, diff --git a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/legacy_replica_calculator_test.go b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/legacy_replica_calculator_test.go index 85cc30d35..7f3e872a5 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/legacy_replica_calculator_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/legacy_replica_calculator_test.go @@ -227,7 +227,7 @@ func (tc *legacyReplicaCalcTestCase) runTest(t *testing.T) { } } -func LegacyTestReplicaCalcDisjointResourcesMetrics(t *testing.T) { +func TestLegacyReplicaCalcDisjointResourcesMetrics(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 1, expectedError: fmt.Errorf("no metrics returned matched known pods"), @@ -243,7 +243,7 @@ func LegacyTestReplicaCalcDisjointResourcesMetrics(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcScaleUp(t *testing.T) { +func TestLegacyReplicaCalcScaleUp(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 5, @@ -260,7 +260,7 @@ func LegacyTestReplicaCalcScaleUp(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcScaleUpUnreadyLessScale(t *testing.T) { +func TestLegacyReplicaCalcScaleUpUnreadyLessScale(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 4, @@ -278,7 +278,7 @@ func LegacyTestReplicaCalcScaleUpUnreadyLessScale(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcScaleUpUnreadyNoScale(t *testing.T) { +func TestLegacyReplicaCalcScaleUpUnreadyNoScale(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 3, @@ -296,7 +296,7 @@ func LegacyTestReplicaCalcScaleUpUnreadyNoScale(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcScaleUpCM(t *testing.T) { +func TestLegacyReplicaCalcScaleUpCM(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 4, @@ -310,7 +310,7 @@ func LegacyTestReplicaCalcScaleUpCM(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcScaleUpCMUnreadyLessScale(t *testing.T) { +func TestLegacyReplicaCalcScaleUpCMUnreadyLessScale(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 4, @@ -325,7 +325,7 @@ func LegacyTestReplicaCalcScaleUpCMUnreadyLessScale(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcScaleUpCMUnreadyNoScaleWouldScaleDown(t *testing.T) { +func TestLegacyReplicaCalcScaleUpCMUnreadyNoScaleWouldScaleDown(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 3, @@ -340,7 +340,7 @@ func LegacyTestReplicaCalcScaleUpCMUnreadyNoScaleWouldScaleDown(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcScaleDown(t *testing.T) { +func TestLegacyReplicaCalcScaleDown(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 5, expectedReplicas: 3, @@ -357,7 +357,7 @@ func LegacyTestReplicaCalcScaleDown(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcScaleDownCM(t *testing.T) { +func TestLegacyReplicaCalcScaleDownCM(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 5, expectedReplicas: 3, @@ -371,7 +371,7 @@ func LegacyTestReplicaCalcScaleDownCM(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcScaleDownIgnoresUnreadyPods(t *testing.T) { +func TestLegacyReplicaCalcScaleDownIgnoresUnreadyPods(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 5, expectedReplicas: 2, @@ -389,7 +389,7 @@ func LegacyTestReplicaCalcScaleDownIgnoresUnreadyPods(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcTolerance(t *testing.T) { +func TestLegacyReplicaCalcTolerance(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 3, @@ -406,7 +406,7 @@ func LegacyTestReplicaCalcTolerance(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcToleranceCM(t *testing.T) { +func TestLegacyReplicaCalcToleranceCM(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 3, @@ -420,7 +420,7 @@ func LegacyTestReplicaCalcToleranceCM(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcSuperfluousMetrics(t *testing.T) { +func TestLegacyReplicaCalcSuperfluousMetrics(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 4, expectedReplicas: 24, @@ -436,7 +436,7 @@ func LegacyTestReplicaCalcSuperfluousMetrics(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcMissingMetrics(t *testing.T) { +func TestLegacyReplicaCalcMissingMetrics(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 4, expectedReplicas: 3, @@ -453,7 +453,7 @@ func LegacyTestReplicaCalcMissingMetrics(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcEmptyMetrics(t *testing.T) { +func TestLegacyReplicaCalcEmptyMetrics(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 4, expectedError: fmt.Errorf("unable to get metrics for resource cpu: no metrics returned from heapster"), @@ -468,7 +468,7 @@ func LegacyTestReplicaCalcEmptyMetrics(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcEmptyCPURequest(t *testing.T) { +func TestLegacyReplicaCalcEmptyCPURequest(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 1, expectedError: fmt.Errorf("missing request for"), @@ -483,7 +483,7 @@ func LegacyTestReplicaCalcEmptyCPURequest(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcMissingMetricsNoChangeEq(t *testing.T) { +func TestLegacyReplicaCalcMissingMetricsNoChangeEq(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 2, expectedReplicas: 2, @@ -500,7 +500,7 @@ func LegacyTestReplicaCalcMissingMetricsNoChangeEq(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcMissingMetricsNoChangeGt(t *testing.T) { +func TestLegacyReplicaCalcMissingMetricsNoChangeGt(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 2, expectedReplicas: 2, @@ -517,7 +517,7 @@ func LegacyTestReplicaCalcMissingMetricsNoChangeGt(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcMissingMetricsNoChangeLt(t *testing.T) { +func TestLegacyReplicaCalcMissingMetricsNoChangeLt(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 2, expectedReplicas: 2, @@ -534,7 +534,7 @@ func LegacyTestReplicaCalcMissingMetricsNoChangeLt(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcMissingMetricsUnreadyNoChange(t *testing.T) { +func TestLegacyReplicaCalcMissingMetricsUnreadyNoChange(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 3, @@ -552,7 +552,7 @@ func LegacyTestReplicaCalcMissingMetricsUnreadyNoChange(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcMissingMetricsUnreadyScaleUp(t *testing.T) { +func TestLegacyReplicaCalcMissingMetricsUnreadyScaleUp(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 3, expectedReplicas: 4, @@ -570,7 +570,7 @@ func LegacyTestReplicaCalcMissingMetricsUnreadyScaleUp(t *testing.T) { tc.runTest(t) } -func LegacyTestReplicaCalcMissingMetricsUnreadyScaleDown(t *testing.T) { +func TestLegacyReplicaCalcMissingMetricsUnreadyScaleDown(t *testing.T) { tc := legacyReplicaCalcTestCase{ currentReplicas: 4, expectedReplicas: 3, @@ -591,7 +591,7 @@ func LegacyTestReplicaCalcMissingMetricsUnreadyScaleDown(t *testing.T) { // TestComputedToleranceAlgImplementation is a regression test which // back-calculates a minimal percentage for downscaling based on a small percentage // increase in pod utilization which is calibrated against the tolerance value. -func LegacyTestReplicaCalcComputedToleranceAlgImplementation(t *testing.T) { +func TestLegacyReplicaCalcComputedToleranceAlgImplementation(t *testing.T) { startPods := int32(10) // 150 mCPU per pod. diff --git a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/BUILD index 7dd3d7acc..92f686e88 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/BUILD @@ -47,6 +47,7 @@ go_test( "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper: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/labels:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go index 26977f832..2558e2320 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go @@ -23,6 +23,7 @@ import ( autoscalingapi "k8s.io/api/autoscaling/v2beta1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -153,14 +154,14 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie return true, &metrics, nil } else { name := getForAction.GetName() - mapper := legacyscheme.Registry.RESTMapper() + mapper := testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme) assert.NotNil(t, tc.singleObject, "should have only requested a single-object metric when we asked for metrics for a single object") gk := schema.FromAPIVersionAndKind(tc.singleObject.APIVersion, tc.singleObject.Kind).GroupKind() mapping, err := mapper.RESTMapping(gk) if err != nil { return true, nil, fmt.Errorf("unable to get mapping for %s: %v", gk.String(), err) } - groupResource := schema.GroupResource{Group: mapping.GroupVersionKind.Group, Resource: mapping.Resource} + groupResource := mapping.Resource.GroupResource() assert.Equal(t, groupResource.String(), getForAction.GetResource().Resource, "should have requested metrics for the resource matching the GroupKind passed in") assert.Equal(t, tc.singleObject.Name, name, "should have requested metrics for the object matching the name passed in") diff --git a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/replica_calculator.go b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/replica_calculator.go index a7a54677c..7dc26f9a7 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/replica_calculator.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/replica_calculator.go @@ -276,7 +276,7 @@ func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMet // GetObjectMetricReplicas calculates the desired replica count based on a target metric utilization (as a milli-value) // for the given object in the given namespace, and the current replica count. -func (c *ReplicaCalculator) GetObjectMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference) (replicaCount int32, utilization int64, timestamp time.Time, err error) { +func (c *ReplicaCalculator) GetObjectMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, selector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) { utilization, timestamp, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef) if err != nil { return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v on %s %s/%s", metricName, objectRef.Kind, namespace, objectRef.Name, err) @@ -287,48 +287,85 @@ func (c *ReplicaCalculator) GetObjectMetricReplicas(currentReplicas int32, targe // return the current replicas if the change would be too small return currentReplicas, utilization, timestamp, nil } - replicaCount = int32(math.Ceil(usageRatio * float64(currentReplicas))) + + readyPodCount, err := c.getReadyPodsCount(namespace, selector) + + if err != nil { + return 0, 0, time.Time{}, fmt.Errorf("unable to calculate ready pods: %s", err) + } + + replicaCount = int32(math.Ceil(usageRatio * float64(readyPodCount))) return replicaCount, utilization, timestamp, nil } +// @TODO(mattjmcnaughton) Many different functions in this module use variations +// of this function. Make this function generic, so we don't repeat the same +// logic in multiple places. +func (c *ReplicaCalculator) getReadyPodsCount(namespace string, selector labels.Selector) (int64, error) { + podList, err := c.podsGetter.Pods(namespace).List(metav1.ListOptions{LabelSelector: selector.String()}) + if err != nil { + return 0, fmt.Errorf("unable to get pods while calculating replica count: %v", err) + } + + if len(podList.Items) == 0 { + return 0, fmt.Errorf("no pods returned by selector while calculating replica count") + } + + readyPodCount := 0 + + for _, pod := range podList.Items { + if pod.Status.Phase == v1.PodRunning && podutil.IsPodReady(&pod) { + readyPodCount++ + } + } + + return int64(readyPodCount), nil +} + // GetExternalMetricReplicas calculates the desired replica count based on a // target metric value (as a milli-value) for the external metric in the given // namespace, and the current replica count. -func (c *ReplicaCalculator) GetExternalMetricReplicas(currentReplicas int32, targetUtilization int64, metricName, namespace string, selector *metav1.LabelSelector) (replicaCount int32, utilization int64, timestamp time.Time, err error) { - labelSelector, err := metav1.LabelSelectorAsSelector(selector) +func (c *ReplicaCalculator) GetExternalMetricReplicas(currentReplicas int32, targetUtilization int64, metricName, namespace string, metricSelector *metav1.LabelSelector, podSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) { + metricLabelSelector, err := metav1.LabelSelectorAsSelector(metricSelector) if err != nil { return 0, 0, time.Time{}, err } - metrics, timestamp, err := c.metricsClient.GetExternalMetric(metricName, namespace, labelSelector) + metrics, timestamp, err := c.metricsClient.GetExternalMetric(metricName, namespace, metricLabelSelector) if err != nil { - return 0, 0, time.Time{}, fmt.Errorf("unable to get external metric %s/%s/%+v: %s", namespace, metricName, selector, err) + return 0, 0, time.Time{}, fmt.Errorf("unable to get external metric %s/%s/%+v: %s", namespace, metricName, metricSelector, err) } utilization = 0 for _, val := range metrics { utilization = utilization + val } + readyPodCount, err := c.getReadyPodsCount(namespace, podSelector) + + if err != nil { + return 0, 0, time.Time{}, fmt.Errorf("unable to calculate ready pods: %s", err) + } + usageRatio := float64(utilization) / float64(targetUtilization) if math.Abs(1.0-usageRatio) <= c.tolerance { // return the current replicas if the change would be too small return currentReplicas, utilization, timestamp, nil } - return int32(math.Ceil(usageRatio * float64(currentReplicas))), utilization, timestamp, nil + return int32(math.Ceil(usageRatio * float64(readyPodCount))), utilization, timestamp, nil } // GetExternalPerPodMetricReplicas calculates the desired replica count based on a // target metric value per pod (as a milli-value) for the external metric in the // given namespace, and the current replica count. -func (c *ReplicaCalculator) GetExternalPerPodMetricReplicas(currentReplicas int32, targetUtilizationPerPod int64, metricName, namespace string, selector *metav1.LabelSelector) (replicaCount int32, utilization int64, timestamp time.Time, err error) { - labelSelector, err := metav1.LabelSelectorAsSelector(selector) +func (c *ReplicaCalculator) GetExternalPerPodMetricReplicas(currentReplicas int32, targetUtilizationPerPod int64, metricName, namespace string, metricSelector *metav1.LabelSelector) (replicaCount int32, utilization int64, timestamp time.Time, err error) { + metricLabelSelector, err := metav1.LabelSelectorAsSelector(metricSelector) if err != nil { return 0, 0, time.Time{}, err } - metrics, timestamp, err := c.metricsClient.GetExternalMetric(metricName, namespace, labelSelector) + metrics, timestamp, err := c.metricsClient.GetExternalMetric(metricName, namespace, metricLabelSelector) if err != nil { - return 0, 0, time.Time{}, fmt.Errorf("unable to get external metric %s/%s/%+v: %s", namespace, metricName, selector, err) + return 0, 0, time.Time{}, fmt.Errorf("unable to get external metric %s/%s/%+v: %s", namespace, metricName, metricSelector, err) } utilization = 0 for _, val := range metrics { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/replica_calculator_test.go b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/replica_calculator_test.go index 2c5f8250d..21af497a3 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/replica_calculator_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/podautoscaler/replica_calculator_test.go @@ -24,6 +24,7 @@ import ( autoscalingv2 "k8s.io/api/autoscaling/v2beta1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -221,7 +222,7 @@ func (tc *replicaCalcTestCase) prepareTestClient(t *testing.T) (*fake.Clientset, return true, &metrics, nil } name := getForAction.GetName() - mapper := legacyscheme.Registry.RESTMapper() + mapper := testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme) metrics := &cmapi.MetricValueList{} assert.NotNil(t, tc.metric.singleObject, "should have only requested a single-object metric when calling GetObjectMetricReplicas") gk := schema.FromAPIVersionAndKind(tc.metric.singleObject.APIVersion, tc.metric.singleObject.Kind).GroupKind() @@ -229,7 +230,7 @@ func (tc *replicaCalcTestCase) prepareTestClient(t *testing.T) (*fake.Clientset, if err != nil { return true, nil, fmt.Errorf("unable to get mapping for %s: %v", gk.String(), err) } - groupResource := schema.GroupResource{Group: mapping.GroupVersionKind.Group, Resource: mapping.Resource} + groupResource := mapping.Resource.GroupResource() assert.Equal(t, groupResource.String(), getForAction.GetResource().Resource, "should have requested metrics for the resource matching the GroupKind passed in") assert.Equal(t, tc.metric.singleObject.Name, name, "should have requested metrics for the object matching the name passed in") @@ -323,10 +324,10 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) { var outTimestamp time.Time var err error if tc.metric.singleObject != nil { - outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetObjectMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.singleObject) + outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetObjectMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.singleObject, selector) } else if tc.metric.selector != nil { if tc.metric.targetUtilization > 0 { - outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.selector) + outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.selector, selector) } else if tc.metric.perPodTargetUtilization > 0 { outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUtilization, tc.metric.name, testNamespace, tc.metric.selector) } @@ -497,6 +498,26 @@ func TestReplicaCalcScaleUpCMObject(t *testing.T) { tc.runTest(t) } +func TestReplicaCalcScaleUpCMObjectIgnoresUnreadyPods(t *testing.T) { + tc := replicaCalcTestCase{ + currentReplicas: 3, + expectedReplicas: 5, // If we did not ignore unready pods, we'd expect 15 replicas. + podReadiness: []v1.ConditionStatus{v1.ConditionFalse, v1.ConditionTrue, v1.ConditionFalse}, + metric: &metricInfo{ + name: "qps", + levels: []int64{50000}, + targetUtilization: 10000, + expectedUtilization: 50000, + singleObject: &autoscalingv2.CrossVersionObjectReference{ + Kind: "Deployment", + APIVersion: "extensions/v1beta1", + Name: "some-deployment", + }, + }, + } + tc.runTest(t) +} + func TestReplicaCalcScaleUpCMExternal(t *testing.T) { tc := replicaCalcTestCase{ currentReplicas: 1, @@ -512,6 +533,22 @@ func TestReplicaCalcScaleUpCMExternal(t *testing.T) { tc.runTest(t) } +func TestReplicaCalcScaleUpCMExternalIgnoresUnreadyPods(t *testing.T) { + tc := replicaCalcTestCase{ + currentReplicas: 3, + expectedReplicas: 2, // Would expect 6 if we didn't ignore unready pods + podReadiness: []v1.ConditionStatus{v1.ConditionFalse, v1.ConditionTrue, v1.ConditionFalse}, + metric: &metricInfo{ + name: "qps", + levels: []int64{8600}, + targetUtilization: 4400, + expectedUtilization: 8600, + selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}}, + }, + } + tc.runTest(t) +} + func TestReplicaCalcScaleUpCMExternalNoLabels(t *testing.T) { tc := replicaCalcTestCase{ currentReplicas: 1, diff --git a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/BUILD index 20a82ccf3..55ea64b3d 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/BUILD @@ -19,22 +19,22 @@ go_library( "//pkg/controller:go_default_library", "//pkg/util/metrics:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/client-go/informers/apps/v1:go_default_library", "//vendor/k8s.io/client-go/informers/core/v1:go_default_library", - "//vendor/k8s.io/client-go/informers/extensions/v1beta1: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/apps/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", + "//vendor/k8s.io/client-go/listers/apps/v1:go_default_library", "//vendor/k8s.io/client-go/listers/core/v1:go_default_library", - "//vendor/k8s.io/client-go/listers/extensions/v1beta1: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/util/integer:go_default_library", @@ -50,14 +50,14 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/controller:go_default_library", "//pkg/securitycontext:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/apis/meta/v1: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/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go index 7c7ee2b77..f87439806 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go @@ -36,21 +36,21 @@ import ( "time" "github.com/golang/glog" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" + appsinformers "k8s.io/client-go/informers/apps/v1" coreinformers "k8s.io/client-go/informers/core/v1" - extensionsinformers "k8s.io/client-go/informers/extensions/v1beta1" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" v1core "k8s.io/client-go/kubernetes/typed/core/v1" + appslisters "k8s.io/client-go/listers/apps/v1" corelisters "k8s.io/client-go/listers/core/v1" - extensionslisters "k8s.io/client-go/listers/extensions/v1beta1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/integer" @@ -90,7 +90,7 @@ type ReplicaSetController struct { expectations *controller.UIDTrackingControllerExpectations // A store of ReplicaSets, populated by the shared informer passed to NewReplicaSetController - rsLister extensionslisters.ReplicaSetLister + rsLister appslisters.ReplicaSetLister // rsListerSynced returns true if the pod store has been synced at least once. // Added as a member to the struct to allow injection for testing. rsListerSynced cache.InformerSynced @@ -106,12 +106,12 @@ type ReplicaSetController struct { } // NewReplicaSetController configures a replica set controller with the specified event recorder -func NewReplicaSetController(rsInformer extensionsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, kubeClient clientset.Interface, burstReplicas int) *ReplicaSetController { +func NewReplicaSetController(rsInformer appsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, kubeClient clientset.Interface, burstReplicas int) *ReplicaSetController { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) return NewBaseController(rsInformer, podInformer, kubeClient, burstReplicas, - extensions.SchemeGroupVersion.WithKind("ReplicaSet"), + apps.SchemeGroupVersion.WithKind("ReplicaSet"), "replicaset_controller", "replicaset", controller.RealPodControl{ @@ -123,7 +123,7 @@ func NewReplicaSetController(rsInformer extensionsinformers.ReplicaSetInformer, // NewBaseController is the implementation of NewReplicaSetController with additional injected // parameters so that it can also serve as the implementation of NewReplicationController. -func NewBaseController(rsInformer extensionsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, kubeClient clientset.Interface, burstReplicas int, +func NewBaseController(rsInformer appsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, kubeClient clientset.Interface, burstReplicas int, gvk schema.GroupVersionKind, metricOwnerName, queueName string, podControl controller.PodControlInterface) *ReplicaSetController { if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage(metricOwnerName, kubeClient.CoreV1().RESTClient().GetRateLimiter()) @@ -194,7 +194,7 @@ func (rsc *ReplicaSetController) Run(workers int, stopCh <-chan struct{}) { } // getPodReplicaSets returns a list of ReplicaSets matching the given pod. -func (rsc *ReplicaSetController) getPodReplicaSets(pod *v1.Pod) []*extensions.ReplicaSet { +func (rsc *ReplicaSetController) getPodReplicaSets(pod *v1.Pod) []*apps.ReplicaSet { rss, err := rsc.rsLister.GetPodReplicaSets(pod) if err != nil { return nil @@ -210,7 +210,7 @@ func (rsc *ReplicaSetController) getPodReplicaSets(pod *v1.Pod) []*extensions.Re // resolveControllerRef returns the controller referenced by a ControllerRef, // or nil if the ControllerRef could not be resolved to a matching controller // of the correct Kind. -func (rsc *ReplicaSetController) resolveControllerRef(namespace string, controllerRef *metav1.OwnerReference) *extensions.ReplicaSet { +func (rsc *ReplicaSetController) resolveControllerRef(namespace string, controllerRef *metav1.OwnerReference) *apps.ReplicaSet { // We can't look up by UID, so look up by Name and then verify UID. // Don't even try to look up by Name if it's the wrong Kind. if controllerRef.Kind != rsc.Kind { @@ -230,8 +230,8 @@ func (rsc *ReplicaSetController) resolveControllerRef(namespace string, controll // callback when RS is updated func (rsc *ReplicaSetController) updateRS(old, cur interface{}) { - oldRS := old.(*extensions.ReplicaSet) - curRS := cur.(*extensions.ReplicaSet) + oldRS := old.(*apps.ReplicaSet) + curRS := cur.(*apps.ReplicaSet) // You might imagine that we only really need to enqueue the // replica set when Spec changes, but it is safer to sync any @@ -407,7 +407,7 @@ func (rsc *ReplicaSetController) deletePod(obj interface{}) { rsc.enqueueReplicaSet(rs) } -// obj could be an *extensions.ReplicaSet, or a DeletionFinalStateUnknown marker item. +// obj could be an *apps.ReplicaSet, or a DeletionFinalStateUnknown marker item. func (rsc *ReplicaSetController) enqueueReplicaSet(obj interface{}) { key, err := controller.KeyFunc(obj) if err != nil { @@ -417,7 +417,7 @@ func (rsc *ReplicaSetController) enqueueReplicaSet(obj interface{}) { rsc.queue.Add(key) } -// obj could be an *extensions.ReplicaSet, or a DeletionFinalStateUnknown marker item. +// obj could be an *apps.ReplicaSet, or a DeletionFinalStateUnknown marker item. func (rsc *ReplicaSetController) enqueueReplicaSetAfter(obj interface{}, after time.Duration) { key, err := controller.KeyFunc(obj) if err != nil { @@ -456,7 +456,7 @@ func (rsc *ReplicaSetController) processNextWorkItem() bool { // manageReplicas checks and updates replicas for the given ReplicaSet. // Does NOT modify . // It will requeue the replica set in case of an error while creating/deleting pods. -func (rsc *ReplicaSetController) manageReplicas(filteredPods []*v1.Pod, rs *extensions.ReplicaSet) error { +func (rsc *ReplicaSetController) manageReplicas(filteredPods []*v1.Pod, rs *apps.ReplicaSet) error { diff := len(filteredPods) - int(*(rs.Spec.Replicas)) rsKey, err := controller.KeyFunc(rs) if err != nil { @@ -626,7 +626,7 @@ func (rsc *ReplicaSetController) syncReplicaSet(key string) error { newStatus := calculateStatus(rs, filteredPods, manageReplicasErr) // Always updates status as pods come up or die. - updatedRS, err := updateReplicaSetStatus(rsc.kubeClient.ExtensionsV1beta1().ReplicaSets(rs.Namespace), rs, newStatus) + updatedRS, err := updateReplicaSetStatus(rsc.kubeClient.AppsV1().ReplicaSets(rs.Namespace), rs, newStatus) if err != nil { // Multiple things could lead to this update failing. Requeuing the replica set ensures // Returning an error causes a requeue without forcing a hotloop @@ -641,11 +641,11 @@ func (rsc *ReplicaSetController) syncReplicaSet(key string) error { return manageReplicasErr } -func (rsc *ReplicaSetController) claimPods(rs *extensions.ReplicaSet, selector labels.Selector, filteredPods []*v1.Pod) ([]*v1.Pod, error) { +func (rsc *ReplicaSetController) claimPods(rs *apps.ReplicaSet, selector labels.Selector, filteredPods []*v1.Pod) ([]*v1.Pod, error) { // If any adoptions are attempted, we should first recheck for deletion with // an uncached quorum read sometime after listing Pods (see #42639). canAdoptFunc := controller.RecheckDeletionTimestamp(func() (metav1.Object, error) { - fresh, err := rsc.kubeClient.ExtensionsV1beta1().ReplicaSets(rs.Namespace).Get(rs.Name, metav1.GetOptions{}) + fresh, err := rsc.kubeClient.AppsV1().ReplicaSets(rs.Namespace).Get(rs.Name, metav1.GetOptions{}) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_test.go b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_test.go index 6dc135676..34235fc7a 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_test.go @@ -28,11 +28,12 @@ import ( "testing" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" @@ -45,7 +46,6 @@ import ( "k8s.io/client-go/tools/cache" utiltesting "k8s.io/client-go/util/testing" "k8s.io/client-go/util/workqueue" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/securitycontext" ) @@ -54,7 +54,7 @@ func testNewReplicaSetControllerFromClient(client clientset.Interface, stopCh ch informers := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc()) ret := NewReplicaSetController( - informers.Extensions().V1beta1().ReplicaSets(), + informers.Apps().V1().ReplicaSets(), informers.Core().V1().Pods(), client, burstReplicas, @@ -78,7 +78,7 @@ func skipListerFunc(verb string, url url.URL) bool { var alwaysReady = func() bool { return true } -func getKey(rs *extensions.ReplicaSet, t *testing.T) string { +func getKey(rs *apps.ReplicaSet, t *testing.T) string { if key, err := controller.KeyFunc(rs); err != nil { t.Errorf("Unexpected error getting key for ReplicaSet %v: %v", rs.Name, err) return "" @@ -87,16 +87,16 @@ func getKey(rs *extensions.ReplicaSet, t *testing.T) string { } } -func newReplicaSet(replicas int, selectorMap map[string]string) *extensions.ReplicaSet { - rs := &extensions.ReplicaSet{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, +func newReplicaSet(replicas int, selectorMap map[string]string) *apps.ReplicaSet { + rs := &apps.ReplicaSet{ + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), Name: "foobar", Namespace: metav1.NamespaceDefault, ResourceVersion: "18", }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: func() *int32 { i := int32(replicas); return &i }(), Selector: &metav1.LabelSelector{MatchLabels: selectorMap}, Template: v1.PodTemplateSpec{ @@ -128,7 +128,7 @@ func newReplicaSet(replicas int, selectorMap map[string]string) *extensions.Repl } // create a pod with the given phase for the given rs (same selectors and namespace) -func newPod(name string, rs *extensions.ReplicaSet, status v1.PodPhase, lastTransitionTime *metav1.Time, properlyOwned bool) *v1.Pod { +func newPod(name string, rs *apps.ReplicaSet, status v1.PodPhase, lastTransitionTime *metav1.Time, properlyOwned bool) *v1.Pod { var conditions []v1.PodCondition if status == v1.PodRunning { condition := v1.PodCondition{Type: v1.PodReady, Status: v1.ConditionTrue} @@ -154,7 +154,7 @@ func newPod(name string, rs *extensions.ReplicaSet, status v1.PodPhase, lastTran } // create count pods with the given phase for the given ReplicaSet (same selectors and namespace), and add them to the store. -func newPodList(store cache.Store, count int, status v1.PodPhase, labelMap map[string]string, rs *extensions.ReplicaSet, name string) *v1.PodList { +func newPodList(store cache.Store, count int, status v1.PodPhase, labelMap map[string]string, rs *apps.ReplicaSet, name string) *v1.PodList { pods := []v1.Pod{} var trueVar = true controllerReference := metav1.OwnerReference{UID: rs.UID, APIVersion: "v1beta1", Kind: "ReplicaSet", Name: rs.Name, Controller: &trueVar} @@ -203,7 +203,7 @@ func validateSyncReplicaSet(t *testing.T, fakePodControl *controller.FakePodCont } func TestSyncReplicaSetDoesNothing(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) fakePodControl := controller.FakePodControl{} stopCh := make(chan struct{}) defer close(stopCh) @@ -212,7 +212,7 @@ func TestSyncReplicaSetDoesNothing(t *testing.T) { // 2 running pods, a controller with 2 replicas, sync is a no-op labelMap := map[string]string{"foo": "bar"} rsSpec := newReplicaSet(2, labelMap) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) newPodList(informers.Core().V1().Pods().Informer().GetIndexer(), 2, v1.PodRunning, labelMap, rsSpec, "pod") manager.podControl = &fakePodControl @@ -221,7 +221,7 @@ func TestSyncReplicaSetDoesNothing(t *testing.T) { } func TestDeleteFinalStateUnknown(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) fakePodControl := controller.FakePodControl{} stopCh := make(chan struct{}) defer close(stopCh) @@ -238,7 +238,7 @@ func TestDeleteFinalStateUnknown(t *testing.T) { // the controller matching the selectors of the deleted pod into the work queue. labelMap := map[string]string{"foo": "bar"} rsSpec := newReplicaSet(1, labelMap) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) pods := newPodList(nil, 1, v1.PodRunning, labelMap, rsSpec, "pod") manager.deletePod(cache.DeletedFinalStateUnknown{Key: "foo", Obj: &pods.Items[0]}) @@ -268,7 +268,7 @@ func TestSyncReplicaSetCreateFailures(t *testing.T) { defer close(stopCh) manager, informers := testNewReplicaSetControllerFromClient(client, stopCh, BurstReplicas) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs) manager.podControl = &fakePodControl manager.syncReplicaSet(getKey(rs, t)) @@ -292,7 +292,7 @@ func TestSyncReplicaSetDormancy(t *testing.T) { } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) fakePodControl := controller.FakePodControl{} stopCh := make(chan struct{}) @@ -303,7 +303,7 @@ func TestSyncReplicaSetDormancy(t *testing.T) { labelMap := map[string]string{"foo": "bar"} rsSpec := newReplicaSet(2, labelMap) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) newPodList(informers.Core().V1().Pods().Informer().GetIndexer(), 1, v1.PodRunning, labelMap, rsSpec, "pod") // Creates a replica and sets expectations @@ -353,25 +353,25 @@ func TestSyncReplicaSetDormancy(t *testing.T) { func TestPodControllerLookup(t *testing.T) { stopCh := make(chan struct{}) defer close(stopCh) - manager, informers := testNewReplicaSetControllerFromClient(clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}), stopCh, BurstReplicas) + manager, informers := testNewReplicaSetControllerFromClient(clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}), stopCh, BurstReplicas) testCases := []struct { - inRSs []*extensions.ReplicaSet + inRSs []*apps.ReplicaSet pod *v1.Pod outRSName string }{ // pods without labels don't match any ReplicaSets { - inRSs: []*extensions.ReplicaSet{ + inRSs: []*apps.ReplicaSet{ {ObjectMeta: metav1.ObjectMeta{Name: "basic"}}}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo1", Namespace: metav1.NamespaceAll}}, outRSName: "", }, // Matching labels, not namespace { - inRSs: []*extensions.ReplicaSet{ + inRSs: []*apps.ReplicaSet{ { ObjectMeta: metav1.ObjectMeta{Name: "foo"}, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, }, }, @@ -383,10 +383,10 @@ func TestPodControllerLookup(t *testing.T) { }, // Matching ns and labels returns the key to the ReplicaSet, not the ReplicaSet name { - inRSs: []*extensions.ReplicaSet{ + inRSs: []*apps.ReplicaSet{ { ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "ns"}, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, }, }, @@ -399,7 +399,7 @@ func TestPodControllerLookup(t *testing.T) { } for _, c := range testCases { for _, r := range c.inRSs { - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(r) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(r) } if rss := manager.getPodReplicaSets(c.pod); rss != nil { if len(rss) != 1 { @@ -424,25 +424,25 @@ func TestWatchControllers(t *testing.T) { defer close(stopCh) informers := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc()) manager := NewReplicaSetController( - informers.Extensions().V1beta1().ReplicaSets(), + informers.Apps().V1().ReplicaSets(), informers.Core().V1().Pods(), client, BurstReplicas, ) informers.Start(stopCh) - var testRSSpec extensions.ReplicaSet + var testRSSpec apps.ReplicaSet received := make(chan string) // The update sent through the fakeWatcher should make its way into the workqueue, // and eventually into the syncHandler. The handler validates the received controller // and closes the received channel to indicate that the test can finish. manager.syncHandler = func(key string) error { - obj, exists, err := informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().GetByKey(key) + obj, exists, err := informers.Apps().V1().ReplicaSets().Informer().GetIndexer().GetByKey(key) if !exists || err != nil { t.Errorf("Expected to find replica set under key %v", key) } - rsSpec := *obj.(*extensions.ReplicaSet) + rsSpec := *obj.(*apps.ReplicaSet) if !apiequality.Semantic.DeepDerivative(rsSpec, testRSSpec) { t.Errorf("Expected %#v, but got %#v", testRSSpec, rsSpec) } @@ -477,7 +477,7 @@ func TestWatchPods(t *testing.T) { // Put one ReplicaSet into the shared informer labelMap := map[string]string{"foo": "bar"} testRSSpec := newReplicaSet(1, labelMap) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(testRSSpec) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(testRSSpec) received := make(chan string) // The pod update sent through the fakeWatcher should figure out the managing ReplicaSet and @@ -540,12 +540,12 @@ func TestUpdatePods(t *testing.T) { // Put 2 ReplicaSets and one pod into the informers labelMap1 := map[string]string{"foo": "bar"} testRSSpec1 := newReplicaSet(1, labelMap1) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(testRSSpec1) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(testRSSpec1) testRSSpec2 := *testRSSpec1 labelMap2 := map[string]string{"bar": "foo"} testRSSpec2.Spec.Selector = &metav1.LabelSelector{MatchLabels: labelMap2} testRSSpec2.Name = "barfoo" - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(&testRSSpec2) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(&testRSSpec2) isController := true controllerRef1 := metav1.OwnerReference{UID: testRSSpec1.UID, APIVersion: "v1", Kind: "ReplicaSet", Name: testRSSpec1.Name, Controller: &isController} @@ -656,8 +656,8 @@ func TestControllerUpdateRequeue(t *testing.T) { defer close(stopCh) manager, informers := testNewReplicaSetControllerFromClient(client, stopCh, BurstReplicas) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) - rs.Status = extensions.ReplicaSetStatus{Replicas: 2} + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs) + rs.Status = apps.ReplicaSetStatus{Replicas: 2} newPodList(informers.Core().V1().Pods().Informer().GetIndexer(), 1, v1.PodRunning, labelMap, rs, "pod") fakePodControl := controller.FakePodControl{} @@ -678,11 +678,11 @@ func TestControllerUpdateStatusWithFailure(t *testing.T) { fakeClient := &fake.Clientset{} fakeClient.AddReactor("get", "replicasets", func(action core.Action) (bool, runtime.Object, error) { return true, rs, nil }) fakeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { - return true, &extensions.ReplicaSet{}, fmt.Errorf("Fake error") + return true, &apps.ReplicaSet{}, fmt.Errorf("Fake error") }) - fakeRSClient := fakeClient.Extensions().ReplicaSets("default") + fakeRSClient := fakeClient.Apps().ReplicaSets("default") numReplicas := int32(10) - newStatus := extensions.ReplicaSetStatus{Replicas: numReplicas} + newStatus := apps.ReplicaSetStatus{Replicas: numReplicas} updateReplicaSetStatus(fakeRSClient, rs, newStatus) updates, gets := 0, 0 for _, a := range fakeClient.Actions() { @@ -702,7 +702,7 @@ func TestControllerUpdateStatusWithFailure(t *testing.T) { updates++ // Confirm that the update has the right status.Replicas even though the Get // returned a ReplicaSet with replicas=1. - if c, ok := action.GetObject().(*extensions.ReplicaSet); !ok { + if c, ok := action.GetObject().(*apps.ReplicaSet); !ok { t.Errorf("Expected a ReplicaSet as the argument to update, got %T", c) } else if c.Status.Replicas != numReplicas { t.Errorf("Expected update for ReplicaSet to contain replicas %v, got %v instead", @@ -729,7 +729,7 @@ func doTestControllerBurstReplicas(t *testing.T, burstReplicas, numReplicas int) manager, informers := testNewReplicaSetControllerFromClient(client, stopCh, burstReplicas) manager.podControl = &fakePodControl - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) expectedPods := int32(0) pods := newPodList(nil, numReplicas, v1.PodPending, labelMap, rsSpec, "pod") @@ -743,7 +743,7 @@ func doTestControllerBurstReplicas(t *testing.T, burstReplicas, numReplicas int) for _, replicas := range []int32{int32(numReplicas), 0} { *(rsSpec.Spec.Replicas) = replicas - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) for i := 0; i < numReplicas; i += burstReplicas { manager.syncReplicaSet(getKey(rsSpec, t)) @@ -881,7 +881,7 @@ func (fe FakeRSExpectations) SatisfiedExpectations(controllerKey string) bool { // TestRSSyncExpectations tests that a pod cannot sneak in between counting active pods // and checking expectations. func TestRSSyncExpectations(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) fakePodControl := controller.FakePodControl{} stopCh := make(chan struct{}) defer close(stopCh) @@ -890,7 +890,7 @@ func TestRSSyncExpectations(t *testing.T) { labelMap := map[string]string{"foo": "bar"} rsSpec := newReplicaSet(2, labelMap) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rsSpec) pods := newPodList(nil, 2, v1.PodPending, labelMap, rsSpec, "pod") informers.Core().V1().Pods().Informer().GetIndexer().Add(&pods.Items[0]) postExpectationsPod := pods.Items[1] @@ -914,7 +914,7 @@ func TestDeleteControllerAndExpectations(t *testing.T) { defer close(stopCh) manager, informers := testNewReplicaSetControllerFromClient(client, stopCh, 10) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs) fakePodControl := controller.FakePodControl{} manager.podControl = &fakePodControl @@ -936,7 +936,7 @@ func TestDeleteControllerAndExpectations(t *testing.T) { if !exists || err != nil { t.Errorf("No expectations found for ReplicaSet") } - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Delete(rs) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Delete(rs) manager.syncReplicaSet(getKey(rs, t)) if _, exists, err = manager.expectations.GetExpectations(rsKey); exists { @@ -951,10 +951,10 @@ func TestDeleteControllerAndExpectations(t *testing.T) { } // shuffle returns a new shuffled list of container controllers. -func shuffle(controllers []*extensions.ReplicaSet) []*extensions.ReplicaSet { +func shuffle(controllers []*apps.ReplicaSet) []*apps.ReplicaSet { numControllers := len(controllers) randIndexes := rand.Perm(numControllers) - shuffled := make([]*extensions.ReplicaSet, numControllers) + shuffled := make([]*apps.ReplicaSet, numControllers) for i := 0; i < numControllers; i++ { shuffled[i] = controllers[randIndexes[i]] } @@ -962,7 +962,7 @@ func shuffle(controllers []*extensions.ReplicaSet) []*extensions.ReplicaSet { } func TestOverlappingRSs(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) labelMap := map[string]string{"foo": "bar"} stopCh := make(chan struct{}) @@ -974,7 +974,7 @@ func TestOverlappingRSs(t *testing.T) { // All use the same CreationTimestamp since ControllerRef should be able // to handle that. timestamp := metav1.Date(2014, time.December, 0, 0, 0, 0, 0, time.Local) - var controllers []*extensions.ReplicaSet + var controllers []*apps.ReplicaSet for j := 1; j < 10; j++ { rsSpec := newReplicaSet(1, labelMap) rsSpec.CreationTimestamp = timestamp @@ -983,7 +983,7 @@ func TestOverlappingRSs(t *testing.T) { } shuffledControllers := shuffle(controllers) for j := range shuffledControllers { - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(shuffledControllers[j]) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(shuffledControllers[j]) } // Add a pod with a ControllerRef and make sure only the corresponding // ReplicaSet is synced. Pick a RS in the middle since the old code used to @@ -1005,14 +1005,14 @@ func TestOverlappingRSs(t *testing.T) { } func TestDeletionTimestamp(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) labelMap := map[string]string{"foo": "bar"} stopCh := make(chan struct{}) defer close(stopCh) manager, informers := testNewReplicaSetControllerFromClient(c, stopCh, 10) rs := newReplicaSet(1, labelMap) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs) rsKey, err := controller.KeyFunc(rs) if err != nil { t.Errorf("Couldn't get key for object %#v: %v", rs, err) @@ -1116,7 +1116,7 @@ func TestDoNotPatchPodWithOtherControlRef(t *testing.T) { stopCh := make(chan struct{}) defer close(stopCh) manager, fakePodControl, informers := setupManagerWithGCEnabled(stopCh, rs) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs) var trueVar = true otherControllerReference := metav1.OwnerReference{UID: uuid.NewUUID(), APIVersion: "v1beta1", Kind: "ReplicaSet", Name: "AnotherRS", Controller: &trueVar} // add to podLister a matching Pod controlled by another controller. Expect no patch. @@ -1137,7 +1137,7 @@ func TestPatchPodFails(t *testing.T) { stopCh := make(chan struct{}) defer close(stopCh) manager, fakePodControl, informers := setupManagerWithGCEnabled(stopCh, rs) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs) // add to podLister two matching pods. Expect two patches to take control // them. informers.Core().V1().Pods().Informer().GetIndexer().Add(newPod("pod1", rs, v1.PodRunning, nil, false)) @@ -1169,7 +1169,7 @@ func TestDoNotAdoptOrCreateIfBeingDeleted(t *testing.T) { stopCh := make(chan struct{}) defer close(stopCh) manager, fakePodControl, informers := setupManagerWithGCEnabled(stopCh, rs) - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs) pod1 := newPod("pod1", rs, v1.PodRunning, nil, false) informers.Core().V1().Pods().Informer().GetIndexer().Add(pod1) @@ -1193,7 +1193,7 @@ func TestDoNotAdoptOrCreateIfBeingDeletedRace(t *testing.T) { // Lister (cache) says it's NOT deleted. rs2 := *rs rs2.DeletionTimestamp = nil - informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(&rs2) + informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(&rs2) // Recheck occurs if a matching orphan is present. pod1 := newPod("pod1", rs, v1.PodRunning, nil, false) @@ -1209,35 +1209,35 @@ func TestDoNotAdoptOrCreateIfBeingDeletedRace(t *testing.T) { } var ( - imagePullBackOff extensions.ReplicaSetConditionType = "ImagePullBackOff" + imagePullBackOff apps.ReplicaSetConditionType = "ImagePullBackOff" - condImagePullBackOff = func() extensions.ReplicaSetCondition { - return extensions.ReplicaSetCondition{ + condImagePullBackOff = func() apps.ReplicaSetCondition { + return apps.ReplicaSetCondition{ Type: imagePullBackOff, Status: v1.ConditionTrue, Reason: "NonExistentImage", } } - condReplicaFailure = func() extensions.ReplicaSetCondition { - return extensions.ReplicaSetCondition{ - Type: extensions.ReplicaSetReplicaFailure, + condReplicaFailure = func() apps.ReplicaSetCondition { + return apps.ReplicaSetCondition{ + Type: apps.ReplicaSetReplicaFailure, Status: v1.ConditionTrue, Reason: "OtherFailure", } } - condReplicaFailure2 = func() extensions.ReplicaSetCondition { - return extensions.ReplicaSetCondition{ - Type: extensions.ReplicaSetReplicaFailure, + condReplicaFailure2 = func() apps.ReplicaSetCondition { + return apps.ReplicaSetCondition{ + Type: apps.ReplicaSetReplicaFailure, Status: v1.ConditionTrue, Reason: "AnotherFailure", } } - status = func() *extensions.ReplicaSetStatus { - return &extensions.ReplicaSetStatus{ - Conditions: []extensions.ReplicaSetCondition{condReplicaFailure()}, + status = func() *apps.ReplicaSetStatus { + return &apps.ReplicaSetStatus{ + Conditions: []apps.ReplicaSetCondition{condReplicaFailure()}, } } ) @@ -1248,8 +1248,8 @@ func TestGetCondition(t *testing.T) { tests := []struct { name string - status extensions.ReplicaSetStatus - condType extensions.ReplicaSetConditionType + status apps.ReplicaSetStatus + condType apps.ReplicaSetConditionType condStatus v1.ConditionStatus condReason string @@ -1259,7 +1259,7 @@ func TestGetCondition(t *testing.T) { name: "condition exists", status: *exampleStatus, - condType: extensions.ReplicaSetReplicaFailure, + condType: apps.ReplicaSetReplicaFailure, expected: true, }, @@ -1286,34 +1286,34 @@ func TestSetCondition(t *testing.T) { tests := []struct { name string - status *extensions.ReplicaSetStatus - cond extensions.ReplicaSetCondition + status *apps.ReplicaSetStatus + cond apps.ReplicaSetCondition - expectedStatus *extensions.ReplicaSetStatus + expectedStatus *apps.ReplicaSetStatus }{ { name: "set for the first time", - status: &extensions.ReplicaSetStatus{}, + status: &apps.ReplicaSetStatus{}, cond: condReplicaFailure(), - expectedStatus: &extensions.ReplicaSetStatus{Conditions: []extensions.ReplicaSetCondition{condReplicaFailure()}}, + expectedStatus: &apps.ReplicaSetStatus{Conditions: []apps.ReplicaSetCondition{condReplicaFailure()}}, }, { name: "simple set", - status: &extensions.ReplicaSetStatus{Conditions: []extensions.ReplicaSetCondition{condImagePullBackOff()}}, + status: &apps.ReplicaSetStatus{Conditions: []apps.ReplicaSetCondition{condImagePullBackOff()}}, cond: condReplicaFailure(), - expectedStatus: &extensions.ReplicaSetStatus{Conditions: []extensions.ReplicaSetCondition{condImagePullBackOff(), condReplicaFailure()}}, + expectedStatus: &apps.ReplicaSetStatus{Conditions: []apps.ReplicaSetCondition{condImagePullBackOff(), condReplicaFailure()}}, }, { name: "overwrite", - status: &extensions.ReplicaSetStatus{Conditions: []extensions.ReplicaSetCondition{condReplicaFailure()}}, + status: &apps.ReplicaSetStatus{Conditions: []apps.ReplicaSetCondition{condReplicaFailure()}}, cond: condReplicaFailure2(), - expectedStatus: &extensions.ReplicaSetStatus{Conditions: []extensions.ReplicaSetCondition{condReplicaFailure2()}}, + expectedStatus: &apps.ReplicaSetStatus{Conditions: []apps.ReplicaSetCondition{condReplicaFailure2()}}, }, } @@ -1329,26 +1329,26 @@ func TestRemoveCondition(t *testing.T) { tests := []struct { name string - status *extensions.ReplicaSetStatus - condType extensions.ReplicaSetConditionType + status *apps.ReplicaSetStatus + condType apps.ReplicaSetConditionType - expectedStatus *extensions.ReplicaSetStatus + expectedStatus *apps.ReplicaSetStatus }{ { name: "remove from empty status", - status: &extensions.ReplicaSetStatus{}, - condType: extensions.ReplicaSetReplicaFailure, + status: &apps.ReplicaSetStatus{}, + condType: apps.ReplicaSetReplicaFailure, - expectedStatus: &extensions.ReplicaSetStatus{}, + expectedStatus: &apps.ReplicaSetStatus{}, }, { name: "simple remove", - status: &extensions.ReplicaSetStatus{Conditions: []extensions.ReplicaSetCondition{condReplicaFailure()}}, - condType: extensions.ReplicaSetReplicaFailure, + status: &apps.ReplicaSetStatus{Conditions: []apps.ReplicaSetCondition{condReplicaFailure()}}, + condType: apps.ReplicaSetReplicaFailure, - expectedStatus: &extensions.ReplicaSetStatus{}, + expectedStatus: &apps.ReplicaSetStatus{}, }, { name: "doesn't remove anything", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils.go b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils.go index ad628da95..de915e522 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils.go @@ -24,16 +24,16 @@ import ( "github.com/golang/glog" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - unversionedextensions "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" + appsclient "k8s.io/client-go/kubernetes/typed/apps/v1" podutil "k8s.io/kubernetes/pkg/api/v1/pod" ) // updateReplicaSetStatus attempts to update the Status.Replicas of the given ReplicaSet, with a single GET/PUT retry. -func updateReplicaSetStatus(c unversionedextensions.ReplicaSetInterface, rs *extensions.ReplicaSet, newStatus extensions.ReplicaSetStatus) (*extensions.ReplicaSet, error) { +func updateReplicaSetStatus(c appsclient.ReplicaSetInterface, rs *apps.ReplicaSet, newStatus apps.ReplicaSetStatus) (*apps.ReplicaSet, error) { // This is the steady state. It happens when the ReplicaSet doesn't have any expectations, since // we do a periodic relist every 30s. If the generations differ but the replicas are // the same, a caller might've resized to the same replica count. @@ -53,7 +53,7 @@ func updateReplicaSetStatus(c unversionedextensions.ReplicaSetInterface, rs *ext newStatus.ObservedGeneration = rs.Generation var getErr, updateErr error - var updatedRS *extensions.ReplicaSet + var updatedRS *apps.ReplicaSet for i, rs := 0, rs; ; i++ { glog.V(4).Infof(fmt.Sprintf("Updating status for %v: %s/%s, ", rs.Kind, rs.Namespace, rs.Name) + fmt.Sprintf("replicas %d->%d (need %d), ", rs.Status.Replicas, newStatus.Replicas, *(rs.Spec.Replicas)) + @@ -82,7 +82,7 @@ func updateReplicaSetStatus(c unversionedextensions.ReplicaSetInterface, rs *ext return nil, updateErr } -func calculateStatus(rs *extensions.ReplicaSet, filteredPods []*v1.Pod, manageReplicasErr error) extensions.ReplicaSetStatus { +func calculateStatus(rs *apps.ReplicaSet, filteredPods []*v1.Pod, manageReplicasErr error) apps.ReplicaSetStatus { newStatus := rs.Status // Count the number of pods that have labels matching the labels of the pod // template of the replica set, the matching pods may have more @@ -105,7 +105,7 @@ func calculateStatus(rs *extensions.ReplicaSet, filteredPods []*v1.Pod, manageRe } } - failureCond := GetCondition(rs.Status, extensions.ReplicaSetReplicaFailure) + failureCond := GetCondition(rs.Status, apps.ReplicaSetReplicaFailure) if manageReplicasErr != nil && failureCond == nil { var reason string if diff := len(filteredPods) - int(*(rs.Spec.Replicas)); diff < 0 { @@ -113,10 +113,10 @@ func calculateStatus(rs *extensions.ReplicaSet, filteredPods []*v1.Pod, manageRe } else if diff > 0 { reason = "FailedDelete" } - cond := NewReplicaSetCondition(extensions.ReplicaSetReplicaFailure, v1.ConditionTrue, reason, manageReplicasErr.Error()) + cond := NewReplicaSetCondition(apps.ReplicaSetReplicaFailure, v1.ConditionTrue, reason, manageReplicasErr.Error()) SetCondition(&newStatus, cond) } else if manageReplicasErr == nil && failureCond != nil { - RemoveCondition(&newStatus, extensions.ReplicaSetReplicaFailure) + RemoveCondition(&newStatus, apps.ReplicaSetReplicaFailure) } newStatus.Replicas = int32(len(filteredPods)) @@ -127,8 +127,8 @@ func calculateStatus(rs *extensions.ReplicaSet, filteredPods []*v1.Pod, manageRe } // NewReplicaSetCondition creates a new replicaset condition. -func NewReplicaSetCondition(condType extensions.ReplicaSetConditionType, status v1.ConditionStatus, reason, msg string) extensions.ReplicaSetCondition { - return extensions.ReplicaSetCondition{ +func NewReplicaSetCondition(condType apps.ReplicaSetConditionType, status v1.ConditionStatus, reason, msg string) apps.ReplicaSetCondition { + return apps.ReplicaSetCondition{ Type: condType, Status: status, LastTransitionTime: metav1.Now(), @@ -138,7 +138,7 @@ func NewReplicaSetCondition(condType extensions.ReplicaSetConditionType, status } // GetCondition returns a replicaset condition with the provided type if it exists. -func GetCondition(status extensions.ReplicaSetStatus, condType extensions.ReplicaSetConditionType) *extensions.ReplicaSetCondition { +func GetCondition(status apps.ReplicaSetStatus, condType apps.ReplicaSetConditionType) *apps.ReplicaSetCondition { for _, c := range status.Conditions { if c.Type == condType { return &c @@ -149,7 +149,7 @@ func GetCondition(status extensions.ReplicaSetStatus, condType extensions.Replic // SetCondition adds/replaces the given condition in the replicaset status. If the condition that we // are about to add already exists and has the same status and reason then we are not going to update. -func SetCondition(status *extensions.ReplicaSetStatus, condition extensions.ReplicaSetCondition) { +func SetCondition(status *apps.ReplicaSetStatus, condition apps.ReplicaSetCondition) { currentCond := GetCondition(*status, condition.Type) if currentCond != nil && currentCond.Status == condition.Status && currentCond.Reason == condition.Reason { return @@ -159,13 +159,13 @@ func SetCondition(status *extensions.ReplicaSetStatus, condition extensions.Repl } // RemoveCondition removes the condition with the provided type from the replicaset status. -func RemoveCondition(status *extensions.ReplicaSetStatus, condType extensions.ReplicaSetConditionType) { +func RemoveCondition(status *apps.ReplicaSetStatus, condType apps.ReplicaSetConditionType) { status.Conditions = filterOutCondition(status.Conditions, condType) } // filterOutCondition returns a new slice of replicaset conditions without conditions with the provided type. -func filterOutCondition(conditions []extensions.ReplicaSetCondition, condType extensions.ReplicaSetConditionType) []extensions.ReplicaSetCondition { - var newConditions []extensions.ReplicaSetCondition +func filterOutCondition(conditions []apps.ReplicaSetCondition, condType apps.ReplicaSetConditionType) []apps.ReplicaSetCondition { + var newConditions []apps.ReplicaSetCondition for _, c := range conditions { if c.Type == condType { continue diff --git a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils_test.go b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils_test.go index fbde4d0b4..6f65315e7 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils_test.go @@ -23,8 +23,8 @@ import ( "reflect" "testing" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" ) func TestCalculateStatus(t *testing.T) { @@ -38,9 +38,9 @@ func TestCalculateStatus(t *testing.T) { rsStatusTests := []struct { name string - replicaset *extensions.ReplicaSet + replicaset *apps.ReplicaSet filteredPods []*v1.Pod - expectedReplicaSetStatus extensions.ReplicaSetStatus + expectedReplicaSetStatus apps.ReplicaSetStatus }{ { "1 fully labelled pod", @@ -48,7 +48,7 @@ func TestCalculateStatus(t *testing.T) { []*v1.Pod{ newPod("pod1", fullyLabelledRS, v1.PodRunning, nil, true), }, - extensions.ReplicaSetStatus{ + apps.ReplicaSetStatus{ Replicas: 1, FullyLabeledReplicas: 1, ReadyReplicas: 1, @@ -61,7 +61,7 @@ func TestCalculateStatus(t *testing.T) { []*v1.Pod{ newPod("pod1", notFullyLabelledRS, v1.PodRunning, nil, true), }, - extensions.ReplicaSetStatus{ + apps.ReplicaSetStatus{ Replicas: 1, FullyLabeledReplicas: 0, ReadyReplicas: 1, @@ -75,7 +75,7 @@ func TestCalculateStatus(t *testing.T) { newPod("pod1", fullyLabelledRS, v1.PodRunning, nil, true), newPod("pod2", fullyLabelledRS, v1.PodRunning, nil, true), }, - extensions.ReplicaSetStatus{ + apps.ReplicaSetStatus{ Replicas: 2, FullyLabeledReplicas: 2, ReadyReplicas: 2, @@ -89,7 +89,7 @@ func TestCalculateStatus(t *testing.T) { newPod("pod1", notFullyLabelledRS, v1.PodRunning, nil, true), newPod("pod2", notFullyLabelledRS, v1.PodRunning, nil, true), }, - extensions.ReplicaSetStatus{ + apps.ReplicaSetStatus{ Replicas: 2, FullyLabeledReplicas: 0, ReadyReplicas: 2, @@ -103,7 +103,7 @@ func TestCalculateStatus(t *testing.T) { newPod("pod1", notFullyLabelledRS, v1.PodRunning, nil, true), newPod("pod2", fullyLabelledRS, v1.PodRunning, nil, true), }, - extensions.ReplicaSetStatus{ + apps.ReplicaSetStatus{ Replicas: 2, FullyLabeledReplicas: 1, ReadyReplicas: 2, @@ -116,7 +116,7 @@ func TestCalculateStatus(t *testing.T) { []*v1.Pod{ newPod("pod1", fullyLabelledRS, v1.PodPending, nil, true), }, - extensions.ReplicaSetStatus{ + apps.ReplicaSetStatus{ Replicas: 1, FullyLabeledReplicas: 1, ReadyReplicas: 0, @@ -129,7 +129,7 @@ func TestCalculateStatus(t *testing.T) { []*v1.Pod{ newPod("pod1", longMinReadySecondsRS, v1.PodRunning, nil, true), }, - extensions.ReplicaSetStatus{ + apps.ReplicaSetStatus{ Replicas: 1, FullyLabeledReplicas: 1, ReadyReplicas: 1, @@ -150,19 +150,19 @@ func TestCalculateStatusConditions(t *testing.T) { labelMap := map[string]string{"name": "foo"} rs := newReplicaSet(2, labelMap) replicaFailureRS := newReplicaSet(10, labelMap) - replicaFailureRS.Status.Conditions = []extensions.ReplicaSetCondition{ + replicaFailureRS.Status.Conditions = []apps.ReplicaSetCondition{ { - Type: extensions.ReplicaSetReplicaFailure, + Type: apps.ReplicaSetReplicaFailure, Status: v1.ConditionTrue, }, } rsStatusConditionTests := []struct { name string - replicaset *extensions.ReplicaSet + replicaset *apps.ReplicaSet filteredPods []*v1.Pod manageReplicasErr error - expectedReplicaSetConditions []extensions.ReplicaSetCondition + expectedReplicaSetConditions []apps.ReplicaSetCondition }{ { @@ -172,9 +172,9 @@ func TestCalculateStatusConditions(t *testing.T) { newPod("pod1", rs, v1.PodRunning, nil, true), }, fmt.Errorf("fake manageReplicasErr"), - []extensions.ReplicaSetCondition{ + []apps.ReplicaSetCondition{ { - Type: extensions.ReplicaSetReplicaFailure, + Type: apps.ReplicaSetReplicaFailure, Status: v1.ConditionTrue, Reason: "FailedCreate", Message: "fake manageReplicasErr", @@ -190,9 +190,9 @@ func TestCalculateStatusConditions(t *testing.T) { newPod("pod3", rs, v1.PodRunning, nil, true), }, fmt.Errorf("fake manageReplicasErr"), - []extensions.ReplicaSetCondition{ + []apps.ReplicaSetCondition{ { - Type: extensions.ReplicaSetReplicaFailure, + Type: apps.ReplicaSetReplicaFailure, Status: v1.ConditionTrue, Reason: "FailedDelete", Message: "fake manageReplicasErr", @@ -215,9 +215,9 @@ func TestCalculateStatusConditions(t *testing.T) { newPod("pod1", replicaFailureRS, v1.PodRunning, nil, true), }, fmt.Errorf("fake manageReplicasErr"), - []extensions.ReplicaSetCondition{ + []apps.ReplicaSetCondition{ { - Type: extensions.ReplicaSetReplicaFailure, + Type: apps.ReplicaSetReplicaFailure, Status: v1.ConditionTrue, }, }, diff --git a/vendor/k8s.io/kubernetes/pkg/controller/replication/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/replication/BUILD index c3f4b3978..a382e2b96 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/replication/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/replication/BUILD @@ -16,14 +16,14 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/controller/replication", deps = [ + "//pkg/apis/apps/v1:go_default_library", "//pkg/apis/core/v1:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/apis/extensions/v1beta1:go_default_library", "//pkg/controller:go_default_library", "//pkg/controller/replicaset:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", @@ -34,11 +34,9 @@ go_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/apps/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", + "//vendor/k8s.io/client-go/listers/apps/v1:go_default_library", "//vendor/k8s.io/client-go/listers/core/v1:go_default_library", - "//vendor/k8s.io/client-go/listers/extensions/v1beta1:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/tools/record:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/controller/replication/conversion.go b/vendor/k8s.io/kubernetes/pkg/controller/replication/conversion.go index 044c1b240..ff7f4b6f7 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/replication/conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/replication/conversion.go @@ -26,8 +26,8 @@ import ( "fmt" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensionsv1beta1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" @@ -36,16 +36,14 @@ import ( "k8s.io/apimachinery/pkg/watch" coreinformers "k8s.io/client-go/informers/core/v1" clientset "k8s.io/client-go/kubernetes" - appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" - appsv1beta2 "k8s.io/client-go/kubernetes/typed/apps/v1beta2" + appsv1client "k8s.io/client-go/kubernetes/typed/apps/v1" v1client "k8s.io/client-go/kubernetes/typed/core/v1" - extensionsv1beta1client "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" + appslisters "k8s.io/client-go/listers/apps/v1" v1listers "k8s.io/client-go/listers/core/v1" - extensionslisters "k8s.io/client-go/listers/extensions/v1beta1" "k8s.io/client-go/tools/cache" + appsconversion "k8s.io/kubernetes/pkg/apis/apps/v1" apiv1 "k8s.io/kubernetes/pkg/apis/core/v1" "k8s.io/kubernetes/pkg/apis/extensions" - extensionsinternalv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" "k8s.io/kubernetes/pkg/controller" ) @@ -59,7 +57,7 @@ func (i informerAdapter) Informer() cache.SharedIndexInformer { return conversionInformer{i.rcInformer.Informer()} } -func (i informerAdapter) Lister() extensionslisters.ReplicaSetLister { +func (i informerAdapter) Lister() appslisters.ReplicaSetLister { return conversionLister{i.rcInformer.Lister()} } @@ -79,7 +77,7 @@ type conversionLister struct { rcLister v1listers.ReplicationControllerLister } -func (l conversionLister) List(selector labels.Selector) ([]*extensionsv1beta1.ReplicaSet, error) { +func (l conversionLister) List(selector labels.Selector) ([]*apps.ReplicaSet, error) { rcList, err := l.rcLister.List(selector) if err != nil { return nil, err @@ -87,11 +85,11 @@ func (l conversionLister) List(selector labels.Selector) ([]*extensionsv1beta1.R return convertSlice(rcList) } -func (l conversionLister) ReplicaSets(namespace string) extensionslisters.ReplicaSetNamespaceLister { +func (l conversionLister) ReplicaSets(namespace string) appslisters.ReplicaSetNamespaceLister { return conversionNamespaceLister{l.rcLister.ReplicationControllers(namespace)} } -func (l conversionLister) GetPodReplicaSets(pod *v1.Pod) ([]*extensionsv1beta1.ReplicaSet, error) { +func (l conversionLister) GetPodReplicaSets(pod *v1.Pod) ([]*apps.ReplicaSet, error) { rcList, err := l.rcLister.GetPodControllers(pod) if err != nil { return nil, err @@ -103,7 +101,7 @@ type conversionNamespaceLister struct { rcLister v1listers.ReplicationControllerNamespaceLister } -func (l conversionNamespaceLister) List(selector labels.Selector) ([]*extensionsv1beta1.ReplicaSet, error) { +func (l conversionNamespaceLister) List(selector labels.Selector) ([]*apps.ReplicaSet, error) { rcList, err := l.rcLister.List(selector) if err != nil { return nil, err @@ -111,7 +109,7 @@ func (l conversionNamespaceLister) List(selector labels.Selector) ([]*extensions return convertSlice(rcList) } -func (l conversionNamespaceLister) Get(name string) (*extensionsv1beta1.ReplicaSet, error) { +func (l conversionNamespaceLister) Get(name string) (*apps.ReplicaSet, error) { rc, err := l.rcLister.Get(name) if err != nil { return nil, err @@ -182,58 +180,20 @@ type clientsetAdapter struct { clientset.Interface } -func (c clientsetAdapter) ExtensionsV1beta1() extensionsv1beta1client.ExtensionsV1beta1Interface { - return conversionExtensionsClient{c.Interface, c.Interface.ExtensionsV1beta1()} -} - -func (c clientsetAdapter) Extensions() extensionsv1beta1client.ExtensionsV1beta1Interface { - return conversionExtensionsClient{c.Interface, c.Interface.ExtensionsV1beta1()} -} - -func (c clientsetAdapter) AppsV1beta2() appsv1beta2.AppsV1beta2Interface { - return conversionAppsV1beta2Client{c.Interface, c.Interface.AppsV1beta2()} -} - -func (c clientsetAdapter) AppsV1() appsv1.AppsV1Interface { +func (c clientsetAdapter) AppsV1() appsv1client.AppsV1Interface { return conversionAppsV1Client{c.Interface, c.Interface.AppsV1()} } -func (c clientsetAdapter) Apps() appsv1.AppsV1Interface { +func (c clientsetAdapter) Apps() appsv1client.AppsV1Interface { return conversionAppsV1Client{c.Interface, c.Interface.AppsV1()} } -type conversionAppsV1beta2Client struct { - clientset clientset.Interface - appsv1beta2.AppsV1beta2Interface -} - -func (c conversionAppsV1beta2Client) ReplicaSets(namespace string) appsv1beta2.ReplicaSetInterface { - // TODO(enisoc): This will force RC integration tests to fail if anyone tries to update - // ReplicaSetController to use apps/v1beta2 without updating this conversion adapter. - // Please change conversionClient to use the new RS version instead of extensions/v1beta1, - // and then return a conversionClient here. - panic("need to update RC/RS conversionClient for apps/v1beta2") -} - type conversionAppsV1Client struct { clientset clientset.Interface - appsv1.AppsV1Interface -} - -func (c conversionAppsV1Client) ReplicaSets(namespace string) appsv1.ReplicaSetInterface { - // TODO(enisoc): This will force RC integration tests to fail if anyone tries to update - // ReplicaSetController to use apps/v1 without updating this conversion adapter. - // Please change conversionClient to use the new RS version instead of extensions/v1beta1, - // and then return a conversionClient here. - panic("need to update RC/RS conversionClient for apps/v1") -} - -type conversionExtensionsClient struct { - clientset clientset.Interface - extensionsv1beta1client.ExtensionsV1beta1Interface + appsv1client.AppsV1Interface } -func (c conversionExtensionsClient) ReplicaSets(namespace string) extensionsv1beta1client.ReplicaSetInterface { +func (c conversionAppsV1Client) ReplicaSets(namespace string) appsv1client.ReplicaSetInterface { return conversionClient{c.clientset.CoreV1().ReplicationControllers(namespace)} } @@ -241,19 +201,19 @@ type conversionClient struct { v1client.ReplicationControllerInterface } -func (c conversionClient) Create(rs *extensionsv1beta1.ReplicaSet) (*extensionsv1beta1.ReplicaSet, error) { +func (c conversionClient) Create(rs *apps.ReplicaSet) (*apps.ReplicaSet, error) { return convertCall(c.ReplicationControllerInterface.Create, rs) } -func (c conversionClient) Update(rs *extensionsv1beta1.ReplicaSet) (*extensionsv1beta1.ReplicaSet, error) { +func (c conversionClient) Update(rs *apps.ReplicaSet) (*apps.ReplicaSet, error) { return convertCall(c.ReplicationControllerInterface.Update, rs) } -func (c conversionClient) UpdateStatus(rs *extensionsv1beta1.ReplicaSet) (*extensionsv1beta1.ReplicaSet, error) { +func (c conversionClient) UpdateStatus(rs *apps.ReplicaSet) (*apps.ReplicaSet, error) { return convertCall(c.ReplicationControllerInterface.UpdateStatus, rs) } -func (c conversionClient) Get(name string, options metav1.GetOptions) (*extensionsv1beta1.ReplicaSet, error) { +func (c conversionClient) Get(name string, options metav1.GetOptions) (*apps.ReplicaSet, error) { rc, err := c.ReplicationControllerInterface.Get(name, options) if err != nil { return nil, err @@ -261,7 +221,7 @@ func (c conversionClient) Get(name string, options metav1.GetOptions) (*extensio return convertRCtoRS(rc, nil) } -func (c conversionClient) List(opts metav1.ListOptions) (*extensionsv1beta1.ReplicaSetList, error) { +func (c conversionClient) List(opts metav1.ListOptions) (*apps.ReplicaSetList, error) { rcList, err := c.ReplicationControllerInterface.List(opts) if err != nil { return nil, err @@ -274,13 +234,13 @@ func (c conversionClient) Watch(opts metav1.ListOptions) (watch.Interface, error return nil, errors.New("Watch() is not implemented for conversionClient") } -func (c conversionClient) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *extensionsv1beta1.ReplicaSet, err error) { +func (c conversionClient) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *apps.ReplicaSet, err error) { // This is not used by RSC. return nil, errors.New("Patch() is not implemented for conversionClient") } -func convertSlice(rcList []*v1.ReplicationController) ([]*extensionsv1beta1.ReplicaSet, error) { - rsList := make([]*extensionsv1beta1.ReplicaSet, 0, len(rcList)) +func convertSlice(rcList []*v1.ReplicationController) ([]*apps.ReplicaSet, error) { + rsList := make([]*apps.ReplicaSet, 0, len(rcList)) for _, rc := range rcList { rs, err := convertRCtoRS(rc, nil) if err != nil { @@ -291,8 +251,8 @@ func convertSlice(rcList []*v1.ReplicationController) ([]*extensionsv1beta1.Repl return rsList, nil } -func convertList(rcList *v1.ReplicationControllerList) (*extensionsv1beta1.ReplicaSetList, error) { - rsList := &extensionsv1beta1.ReplicaSetList{Items: make([]extensionsv1beta1.ReplicaSet, len(rcList.Items))} +func convertList(rcList *v1.ReplicationControllerList) (*apps.ReplicaSetList, error) { + rsList := &apps.ReplicaSetList{Items: make([]apps.ReplicaSet, len(rcList.Items))} for i := range rcList.Items { rc := &rcList.Items[i] _, err := convertRCtoRS(rc, &rsList.Items[i]) @@ -303,7 +263,7 @@ func convertList(rcList *v1.ReplicationControllerList) (*extensionsv1beta1.Repli return rsList, nil } -func convertCall(fn func(*v1.ReplicationController) (*v1.ReplicationController, error), rs *extensionsv1beta1.ReplicaSet) (*extensionsv1beta1.ReplicaSet, error) { +func convertCall(fn func(*v1.ReplicationController) (*v1.ReplicationController, error), rs *apps.ReplicaSet) (*apps.ReplicaSet, error) { rc, err := convertRStoRC(rs) if err != nil { return nil, err @@ -315,23 +275,23 @@ func convertCall(fn func(*v1.ReplicationController) (*v1.ReplicationController, return convertRCtoRS(result, nil) } -func convertRCtoRS(rc *v1.ReplicationController, out *extensionsv1beta1.ReplicaSet) (*extensionsv1beta1.ReplicaSet, error) { +func convertRCtoRS(rc *v1.ReplicationController, out *apps.ReplicaSet) (*apps.ReplicaSet, error) { var rsInternal extensions.ReplicaSet if err := apiv1.Convert_v1_ReplicationController_to_extensions_ReplicaSet(rc, &rsInternal, nil); err != nil { return nil, fmt.Errorf("can't convert ReplicationController %v/%v to ReplicaSet: %v", rc.Namespace, rc.Name, err) } if out == nil { - out = new(extensionsv1beta1.ReplicaSet) + out = new(apps.ReplicaSet) } - if err := extensionsinternalv1beta1.Convert_extensions_ReplicaSet_To_v1beta1_ReplicaSet(&rsInternal, out, nil); err != nil { + if err := appsconversion.Convert_extensions_ReplicaSet_To_v1_ReplicaSet(&rsInternal, out, nil); err != nil { return nil, fmt.Errorf("can't convert ReplicaSet (converted from ReplicationController %v/%v) from internal to extensions/v1beta1: %v", rc.Namespace, rc.Name, err) } return out, nil } -func convertRStoRC(rs *extensionsv1beta1.ReplicaSet) (*v1.ReplicationController, error) { +func convertRStoRC(rs *apps.ReplicaSet) (*v1.ReplicationController, error) { var rsInternal extensions.ReplicaSet - if err := extensionsinternalv1beta1.Convert_v1beta1_ReplicaSet_To_extensions_ReplicaSet(rs, &rsInternal, nil); err != nil { + if err := appsconversion.Convert_v1_ReplicaSet_To_extensions_ReplicaSet(rs, &rsInternal, nil); err != nil { return nil, fmt.Errorf("can't convert ReplicaSet (converting to ReplicationController %v/%v) from extensions/v1beta1 to internal: %v", rs.Namespace, rs.Name, err) } var rc v1.ReplicationController @@ -356,7 +316,7 @@ func (pc podControlAdapter) CreatePodsOnNode(nodeName, namespace string, templat } func (pc podControlAdapter) CreatePodsWithControllerRef(namespace string, template *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error { - rc, err := convertRStoRC(object.(*extensionsv1beta1.ReplicaSet)) + rc, err := convertRStoRC(object.(*apps.ReplicaSet)) if err != nil { return err } @@ -364,7 +324,7 @@ func (pc podControlAdapter) CreatePodsWithControllerRef(namespace string, templa } func (pc podControlAdapter) DeletePod(namespace string, podID string, object runtime.Object) error { - rc, err := convertRStoRC(object.(*extensionsv1beta1.ReplicaSet)) + rc, err := convertRStoRC(object.(*apps.ReplicaSet)) if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/replication/replication_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/replication/replication_controller.go index b181db0f3..4b6ac5f4a 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/replication/replication_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/replication/replication_controller.go @@ -52,7 +52,7 @@ type ReplicationManager struct { func NewReplicationManager(podInformer coreinformers.PodInformer, rcInformer coreinformers.ReplicationControllerInformer, kubeClient clientset.Interface, burstReplicas int) *ReplicationManager { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) return &ReplicationManager{ *replicaset.NewBaseController(informerAdapter{rcInformer}, podInformer, clientsetAdapter{kubeClient}, burstReplicas, v1.SchemeGroupVersion.WithKind("ReplicationController"), diff --git a/vendor/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller.go index 71cf8310e..2b46d45ed 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller.go @@ -161,11 +161,14 @@ func NewResourceQuotaController(options *ResourceQuotaControllerOptions) (*Resou rq.quotaMonitor = qm - // do initial quota monitor setup + // do initial quota monitor setup. If we have a discovery failure here, it's ok. We'll discover more resources when a later sync happens. resources, err := GetQuotableResources(options.DiscoveryFunc) - if err != nil { + if discovery.IsGroupDiscoveryFailedError(err) { + utilruntime.HandleError(fmt.Errorf("initial discovery check failure, continuing and counting on future sync update: %v", err)) + } else if err != nil { return nil, err } + if err = qm.SyncMonitors(resources); err != nil { utilruntime.HandleError(fmt.Errorf("initial monitor sync has error: %v", err)) } @@ -297,7 +300,7 @@ func (rq *ResourceQuotaController) Run(workers int, stopCh <-chan struct{}) { func (rq *ResourceQuotaController) syncResourceQuotaFromKey(key string) (err error) { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing resource quota %q (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing resource quota %q (%v)", key, time.Since(startTime)) }() namespace, name, err := cache.SplitMetaNamespaceKey(key) @@ -337,7 +340,7 @@ func (rq *ResourceQuotaController) syncResourceQuota(v1ResourceQuota *v1.Resourc } hardLimits := quota.Add(api.ResourceList{}, resourceQuota.Spec.Hard) - newUsage, err := quota.CalculateUsage(resourceQuota.Namespace, resourceQuota.Spec.Scopes, hardLimits, rq.registry) + newUsage, err := quota.CalculateUsage(resourceQuota.Namespace, resourceQuota.Spec.Scopes, hardLimits, rq.registry, resourceQuota.Spec.ScopeSelector) if err != nil { return err } @@ -425,7 +428,16 @@ func (rq *ResourceQuotaController) Sync(discoveryFunc NamespacedResourcesFunc, p newResources, err := GetQuotableResources(discoveryFunc) if err != nil { utilruntime.HandleError(err) - return + + if discovery.IsGroupDiscoveryFailedError(err) && len(newResources) > 0 { + // In partial discovery cases, don't remove any existing informers, just add new ones + for k, v := range oldResources { + newResources[k] = v + } + } else { + // short circuit in non-discovery error cases or if discovery returned zero resources + return + } } // Decide whether discovery has reported a change. @@ -470,15 +482,18 @@ func (rq *ResourceQuotaController) resyncMonitors(resources map[schema.GroupVers // GetQuotableResources returns all resources that the quota system should recognize. // It requires a resource supports the following verbs: 'create','list','delete' +// This function may return both results and an error. If that happens, it means that the discovery calls were only +// partially successful. A decision about whether to proceed or not is left to the caller. func GetQuotableResources(discoveryFunc NamespacedResourcesFunc) (map[schema.GroupVersionResource]struct{}, error) { - possibleResources, err := discoveryFunc() - if err != nil { - return nil, fmt.Errorf("failed to discover resources: %v", err) + possibleResources, discoveryErr := discoveryFunc() + if discoveryErr != nil && len(possibleResources) == 0 { + return nil, fmt.Errorf("failed to discover resources: %v", discoveryErr) } quotableResources := discovery.FilteredBy(discovery.SupportsAllVerbs{Verbs: []string{"create", "list", "watch", "delete"}}, possibleResources) quotableGroupVersionResources, err := discovery.GroupVersionResources(quotableResources) if err != nil { return nil, fmt.Errorf("Failed to parse resources: %v", err) } - return quotableGroupVersionResources, nil + // return the original discovery error (if any) in addition to the list + return quotableGroupVersionResources, discoveryErr } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/route/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/route/BUILD index fe0e240fe..3bb653bdb 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/route/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/route/BUILD @@ -21,7 +21,6 @@ go_library( "//pkg/util/node:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", @@ -34,6 +33,7 @@ go_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/util/retry:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/route/route_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/route/route_controller.go index dd51fb06d..08fb9145e 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/route/route_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/route/route_controller.go @@ -24,8 +24,8 @@ import ( "time" "github.com/golang/glog" + "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" @@ -38,6 +38,7 @@ import ( corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" + clientretry "k8s.io/client-go/util/retry" v1node "k8s.io/kubernetes/pkg/api/v1/node" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/controller" @@ -49,12 +50,14 @@ const ( // Maximal number of concurrent CreateRoute API calls. // TODO: This should be per-provider. maxConcurrentRouteCreations int = 200 - // Maximum number of retries of route creations. - maxRetries int = 5 - // Maximum number of retries of node status update. - updateNodeStatusMaxRetries int = 3 ) +var updateNetworkConditionBackoff = wait.Backoff{ + Steps: 5, // Maximum number of retries. + Duration: 100 * time.Millisecond, + Jitter: 1.0, +} + type RouteController struct { routes cloudprovider.Routes kubeClient clientset.Interface @@ -104,7 +107,7 @@ func (rc *RouteController) Run(stopCh <-chan struct{}, syncPeriod time.Duration) } if rc.broadcaster != nil { - rc.broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(rc.kubeClient.CoreV1().RESTClient()).Events("")}) + rc.broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: rc.kubeClient.CoreV1().Events("")}) } // TODO: If we do just the full Resync every 5 minutes (default value) @@ -165,18 +168,18 @@ func (rc *RouteController) reconcile(nodes []*v1.Node, routes []*cloudprovider.R wg.Add(1) go func(nodeName types.NodeName, nameHint string, route *cloudprovider.Route) { defer wg.Done() - for i := 0; i < maxRetries; i++ { + err := clientretry.RetryOnConflict(updateNetworkConditionBackoff, func() error { startTime := time.Now() // Ensure that we don't have more than maxConcurrentRouteCreations // CreateRoute calls in flight. rateLimiter <- struct{}{} - glog.Infof("Creating route for node %s %s with hint %s, throttled %v", nodeName, route.DestinationCIDR, nameHint, time.Now().Sub(startTime)) + glog.Infof("Creating route for node %s %s with hint %s, throttled %v", nodeName, route.DestinationCIDR, nameHint, time.Since(startTime)) err := rc.routes.CreateRoute(context.TODO(), rc.clusterName, nameHint, route) <-rateLimiter rc.updateNetworkingCondition(nodeName, err == nil) if err != nil { - msg := fmt.Sprintf("Could not create route %s %s for node %s after %v: %v", nameHint, route.DestinationCIDR, nodeName, time.Now().Sub(startTime), err) + msg := fmt.Sprintf("Could not create route %s %s for node %s after %v: %v", nameHint, route.DestinationCIDR, nodeName, time.Since(startTime), err) if rc.recorder != nil { rc.recorder.Eventf( &v1.ObjectReference{ @@ -186,12 +189,14 @@ func (rc *RouteController) reconcile(nodes []*v1.Node, routes []*cloudprovider.R Namespace: "", }, v1.EventTypeWarning, "FailedToCreateRoute", msg) } - glog.Error(msg) - - } else { - glog.Infof("Created route for node %s %s with hint %s after %v", nodeName, route.DestinationCIDR, nameHint, time.Now().Sub(startTime)) - return + glog.V(4).Infof(msg) + return err } + glog.Infof("Created route for node %s %s with hint %s after %v", nodeName, route.DestinationCIDR, nameHint, time.Now().Sub(startTime)) + return nil + }) + if err != nil { + glog.Errorf("Could not create route %s %s for node %s: %v", nameHint, route.DestinationCIDR, nodeName, err) } }(nodeName, nameHint, route) } else { @@ -210,14 +215,13 @@ func (rc *RouteController) reconcile(nodes []*v1.Node, routes []*cloudprovider.R wg.Add(1) // Delete the route. go func(route *cloudprovider.Route, startTime time.Time) { + defer wg.Done() glog.Infof("Deleting route %s %s", route.Name, route.DestinationCIDR) if err := rc.routes.DeleteRoute(context.TODO(), rc.clusterName, route); err != nil { - glog.Errorf("Could not delete route %s %s after %v: %v", route.Name, route.DestinationCIDR, time.Now().Sub(startTime), err) + glog.Errorf("Could not delete route %s %s after %v: %v", route.Name, route.DestinationCIDR, time.Since(startTime), err) } else { - glog.Infof("Deleted route %s %s after %v", route.Name, route.DestinationCIDR, time.Now().Sub(startTime)) + glog.Infof("Deleted route %s %s after %v", route.Name, route.DestinationCIDR, time.Since(startTime)) } - wg.Done() - }(route, time.Now()) } } @@ -227,8 +231,8 @@ func (rc *RouteController) reconcile(nodes []*v1.Node, routes []*cloudprovider.R } func (rc *RouteController) updateNetworkingCondition(nodeName types.NodeName, routeCreated bool) error { - var err error - for i := 0; i < updateNodeStatusMaxRetries; i++ { + err := clientretry.RetryOnConflict(updateNetworkConditionBackoff, func() error { + var err error // Patch could also fail, even though the chance is very slim. So we still do // patch in the retry loop. currentTime := metav1.Now() @@ -249,16 +253,16 @@ func (rc *RouteController) updateNetworkingCondition(nodeName types.NodeName, ro LastTransitionTime: currentTime, }) } - if err == nil { - return nil - } - if !errors.IsConflict(err) { - glog.Errorf("Error updating node %s: %v", nodeName, err) - return err + if err != nil { + glog.V(4).Infof("Error updating node %s, retrying: %v", nodeName, err) } - glog.V(4).Infof("Error updating node %s, retrying: %v", nodeName, err) + return err + }) + + if err != nil { + glog.Errorf("Error updating node %s: %v", nodeName, err) } - glog.Errorf("Error updating node %s: %v", nodeName, err) + return err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/service/service_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/service/service_controller.go index 69e129958..61f92d02a 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/service/service_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/service/service_controller.go @@ -111,7 +111,7 @@ func New( ) (*ServiceController, error) { broadcaster := record.NewBroadcaster() broadcaster.StartLogging(glog.Infof) - broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "service-controller"}) if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/service/service_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/service/service_controller_test.go index 78839d0de..266929c28 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/service/service_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/service/service_controller_test.go @@ -247,9 +247,8 @@ func TestUpdateNodesInExternalLoadBalancer(t *testing.T) { controller, cloud, _ := newController() var services []*v1.Service - for _, service := range item.services { - services = append(services, service) - } + services = append(services, item.services...) + if err := controller.updateLoadBalancerHosts(services, nodes); err != nil { t.Errorf("unexpected error: %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller.go index e0c41b82f..4d0f53bb0 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller.go @@ -183,7 +183,7 @@ func (c *ServiceAccountsController) processNextWorkItem() bool { func (c *ServiceAccountsController) syncNamespace(key string) error { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing namespace %q (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing namespace %q (%v)", key, time.Since(startTime)) }() ns, err := c.nsLister.Get(key) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller_test.go index 969f8a17c..e7007f72e 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller_test.go @@ -29,11 +29,6 @@ import ( "k8s.io/kubernetes/pkg/controller" ) -type serverResponse struct { - statusCode int - obj interface{} -} - func TestServiceAccountCreation(t *testing.T) { ns := metav1.NamespaceDefault diff --git a/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller_test.go index ca6a14f23..cf0c4f854 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller_test.go @@ -474,7 +474,7 @@ func TestTokenCreation(t *testing.T) { AddedSecret: serviceAccountTokenSecretWithNamespaceData([]byte("custom")), ExpectedActions: []core.Action{ - // no update is performed... the custom namespace is preserved + // no update is performed... the custom namespace is preserved }, }, @@ -539,7 +539,7 @@ func TestTokenCreation(t *testing.T) { UpdatedSecret: serviceAccountTokenSecretWithNamespaceData([]byte("custom")), ExpectedActions: []core.Action{ - // no update is performed... the custom namespace is preserved + // no update is performed... the custom namespace is preserved }, }, diff --git a/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set.go b/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set.go index 1890fb271..2e197c9da 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set.go @@ -87,7 +87,7 @@ func NewStatefulSetController( ) *StatefulSetController { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "statefulset-controller"}) ssc := &StatefulSetController{ @@ -415,7 +415,7 @@ func (ssc *StatefulSetController) worker() { func (ssc *StatefulSetController) sync(key string) error { startTime := time.Now() defer func() { - glog.V(4).Infof("Finished syncing statefulset %q (%v)", key, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished syncing statefulset %q (%v)", key, time.Since(startTime)) }() namespace, name, err := cache.SplitMetaNamespaceKey(key) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set_test.go b/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set_test.go index 3893753d1..7d9a7cc16 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set_test.go @@ -496,7 +496,6 @@ func TestStatefulSetControllerGetStatefulSetsForPod(t *testing.T) { func TestGetPodsForStatefulSetAdopt(t *testing.T) { set := newStatefulSet(5) - ssc, spc := newFakeStatefulSetController(set) pod1 := newStatefulSetPod(set, 1) // pod2 is an orphan with matching labels and name. pod2 := newStatefulSetPod(set, 2) @@ -510,6 +509,8 @@ func TestGetPodsForStatefulSetAdopt(t *testing.T) { pod4.OwnerReferences = nil pod4.Name = "x" + pod4.Name + ssc, spc := newFakeStatefulSetController(set, pod1, pod2, pod3, pod4) + spc.podsIndexer.Add(pod1) spc.podsIndexer.Add(pod2) spc.podsIndexer.Add(pod3) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/testutil/test_utils.go b/vendor/k8s.io/kubernetes/pkg/controller/testutil/test_utils.go index 1ecada1f6..021191910 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/testutil/test_utils.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/testutil/test_utils.go @@ -67,6 +67,7 @@ type FakeNodeHandler struct { // Synchronization lock sync.Mutex DeleteWaitChan chan struct{} + PatchWaitChan chan struct{} } // FakeLegacyHandler is a fake implemtation of CoreV1Interface. @@ -270,6 +271,9 @@ func (m *FakeNodeHandler) Patch(name string, pt types.PatchType, data []byte, su m.lock.Lock() defer func() { m.RequestCount++ + if m.PatchWaitChan != nil { + m.PatchWaitChan <- struct{}{} + } m.lock.Unlock() }() var nodeCopy v1.Node @@ -361,6 +365,11 @@ func (f *FakeRecorder) Eventf(obj runtime.Object, eventtype, reason, messageFmt func (f *FakeRecorder) PastEventf(obj runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) { } +// AnnotatedEventf emits a fake formatted event to the fake recorder +func (f *FakeRecorder) AnnotatedEventf(obj runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + f.Eventf(obj, eventtype, reason, messageFmt, args) +} + func (f *FakeRecorder) generateEvent(obj runtime.Object, timestamp metav1.Time, eventtype, reason, message string) { f.Lock() defer f.Unlock() @@ -421,9 +430,6 @@ func NewFakeRecorder() *FakeRecorder { func NewNode(name string) *v1.Node { return &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: name}, - Spec: v1.NodeSpec{ - ExternalID: name, - }, Status: v1.NodeStatus{ Capacity: v1.ResourceList{ v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"), diff --git a/vendor/k8s.io/kubernetes/pkg/controller/util/node/controller_utils.go b/vendor/k8s.io/kubernetes/pkg/controller/util/node/controller_utils.go index b2c0ec23c..36fbddda0 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/util/node/controller_utils.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/util/node/controller_utils.go @@ -178,7 +178,7 @@ func ExistsInCloudProvider(cloud cloudprovider.Interface, nodeName types.NodeNam if !ok { return false, fmt.Errorf("%v", ErrCloudInstance) } - if _, err := instances.ExternalID(context.TODO(), nodeName); err != nil { + if _, err := instances.InstanceID(context.TODO(), nodeName); err != nil { if err == cloudprovider.InstanceNotFound { return false, nil } @@ -187,6 +187,20 @@ func ExistsInCloudProvider(cloud cloudprovider.Interface, nodeName types.NodeNam return true, nil } +// ShutdownInCloudProvider returns true if the node is shutdowned in +// cloud provider. +func ShutdownInCloudProvider(ctx context.Context, cloud cloudprovider.Interface, node *v1.Node) (bool, error) { + instances, ok := cloud.Instances() + if !ok { + return false, fmt.Errorf("%v", ErrCloudInstance) + } + shutdown, err := instances.InstanceShutdownByProviderID(ctx, node.Spec.ProviderID) + if err == cloudprovider.NotImplemented { + return false, nil + } + return shutdown, err +} + // RecordNodeEvent records a event related to a node. func RecordNodeEvent(recorder record.EventRecorder, nodeName, nodeUID, eventtype, reason, event string) { ref := &v1.ObjectReference{ diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/BUILD index 4d5908494..da1b3e24b 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/BUILD @@ -25,10 +25,13 @@ go_library( "//pkg/volume/util/operationexecutor:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/informers/core/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", @@ -36,6 +39,7 @@ go_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/util/workqueue:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/attach_detach_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/attach_detach_controller.go index b719ffaaa..7390af95c 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/attach_detach_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/attach_detach_controller.go @@ -24,10 +24,13 @@ import ( "time" "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" coreinformers "k8s.io/client-go/informers/core/v1" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" @@ -35,6 +38,7 @@ import ( corelisters "k8s.io/client-go/listers/core/v1" kcache "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache" @@ -124,9 +128,11 @@ func NewAttachDetachController( pvsSynced: pvInformer.Informer().HasSynced, podLister: podInformer.Lister(), podsSynced: podInformer.Informer().HasSynced, + podIndexer: podInformer.Informer().GetIndexer(), nodeLister: nodeInformer.Lister(), nodesSynced: nodeInformer.Informer().HasSynced, cloud: cloud, + pvcQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "pvcs"), } if err := adc.volumePluginMgr.InitPlugins(plugins, prober, adc); err != nil { @@ -135,7 +141,7 @@ func NewAttachDetachController( eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "attachdetach-controller"}) blkutil := volumepathhandler.NewBlockVolumePathHandler() @@ -178,15 +184,54 @@ func NewAttachDetachController( DeleteFunc: adc.podDelete, }) + // This custom indexer will index pods by its PVC keys. Then we don't need + // to iterate all pods every time to find pods which reference given PVC. + adc.podIndexer.AddIndexers(kcache.Indexers{ + pvcKeyIndex: indexByPVCKey, + }) + nodeInformer.Informer().AddEventHandler(kcache.ResourceEventHandlerFuncs{ AddFunc: adc.nodeAdd, UpdateFunc: adc.nodeUpdate, DeleteFunc: adc.nodeDelete, }) + pvcInformer.Informer().AddEventHandler(kcache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + adc.enqueuePVC(obj) + }, + UpdateFunc: func(old, new interface{}) { + adc.enqueuePVC(new) + }, + }) + return adc, nil } +const ( + pvcKeyIndex string = "pvcKey" +) + +// indexByPVCKey returns PVC keys for given pod. Note that the index is only +// used for attaching, so we are only interested in active pods with nodeName +// set. +func indexByPVCKey(obj interface{}) ([]string, error) { + pod, ok := obj.(*v1.Pod) + if !ok { + return []string{}, nil + } + if len(pod.Spec.NodeName) == 0 || volumeutil.IsPodTerminated(pod, pod.Status) { + return []string{}, nil + } + keys := []string{} + for _, podVolume := range pod.Spec.Volumes { + if pvcSource := podVolume.VolumeSource.PersistentVolumeClaim; pvcSource != nil { + keys = append(keys, fmt.Sprintf("%s/%s", pod.Namespace, pvcSource.ClaimName)) + } + } + return keys, nil +} + type attachDetachController struct { // kubeClient is the kube API client used by volumehost to communicate with // the API server. @@ -206,6 +251,7 @@ type attachDetachController struct { podLister corelisters.PodLister podsSynced kcache.InformerSynced + podIndexer kcache.Indexer nodeLister corelisters.NodeLister nodesSynced kcache.InformerSynced @@ -250,10 +296,14 @@ type attachDetachController struct { // recorder is used to record events in the API server recorder record.EventRecorder + + // pvcQueue is used to queue pvc objects + pvcQueue workqueue.RateLimitingInterface } func (adc *attachDetachController) Run(stopCh <-chan struct{}) { defer runtime.HandleCrash() + defer adc.pvcQueue.ShutDown() glog.Infof("Starting attach detach controller") defer glog.Infof("Shutting down attach detach controller") @@ -272,6 +322,7 @@ func (adc *attachDetachController) Run(stopCh <-chan struct{}) { } go adc.reconciler.Run(stopCh) go adc.desiredStateOfWorldPopulator.Run(stopCh) + go wait.Until(adc.pvcWorker, time.Second, stopCh) <-stopCh } @@ -484,6 +535,83 @@ func (adc *attachDetachController) nodeDelete(obj interface{}) { adc.processVolumesInUse(nodeName, node.Status.VolumesInUse) } +func (adc *attachDetachController) enqueuePVC(obj interface{}) { + key, err := kcache.DeletionHandlingMetaNamespaceKeyFunc(obj) + if err != nil { + runtime.HandleError(fmt.Errorf("Couldn't get key for object %+v: %v", obj, err)) + return + } + adc.pvcQueue.Add(key) +} + +// pvcWorker processes items from pvcQueue +func (adc *attachDetachController) pvcWorker() { + for adc.processNextItem() { + } +} + +func (adc *attachDetachController) processNextItem() bool { + keyObj, shutdown := adc.pvcQueue.Get() + if shutdown { + return false + } + defer adc.pvcQueue.Done(keyObj) + + if err := adc.syncPVCByKey(keyObj.(string)); err != nil { + // Rather than wait for a full resync, re-add the key to the + // queue to be processed. + adc.pvcQueue.AddRateLimited(keyObj) + runtime.HandleError(fmt.Errorf("Failed to sync pvc %q, will retry again: %v", keyObj.(string), err)) + return true + } + + // Finally, if no error occurs we Forget this item so it does not + // get queued again until another change happens. + adc.pvcQueue.Forget(keyObj) + return true +} + +func (adc *attachDetachController) syncPVCByKey(key string) error { + glog.V(5).Infof("syncPVCByKey[%s]", key) + namespace, name, err := kcache.SplitMetaNamespaceKey(key) + if err != nil { + glog.V(4).Infof("error getting namespace & name of pvc %q to get pvc from informer: %v", key, err) + return nil + } + pvc, err := adc.pvcLister.PersistentVolumeClaims(namespace).Get(name) + if apierrors.IsNotFound(err) { + glog.V(4).Infof("error getting pvc %q from informer: %v", key, err) + return nil + } + if err != nil { + return err + } + + if pvc.Status.Phase != v1.ClaimBound || pvc.Spec.VolumeName == "" { + // Skip unbound PVCs. + return nil + } + + objs, err := adc.podIndexer.ByIndex(pvcKeyIndex, key) + if err != nil { + return err + } + for _, obj := range objs { + pod, ok := obj.(*v1.Pod) + if !ok { + continue + } + volumeActionFlag := util.DetermineVolumeAction( + pod, + adc.desiredStateOfWorld, + true /* default volume action */) + + util.ProcessPodVolumes(pod, volumeActionFlag, /* addVolumes */ + adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister) + } + return nil +} + // processVolumesInUse processes the list of volumes marked as "in-use" // according to the specified Node's Status.VolumesInUse and updates the // corresponding volume in the actual state of the world to indicate that it is @@ -522,6 +650,10 @@ func (adc *attachDetachController) GetVolumeDevicePluginDir(podUID string) strin return "" } +func (adc *attachDetachController) GetPodsDir() string { + return "" +} + func (adc *attachDetachController) GetPodVolumeDir(podUID types.UID, pluginName, volumeName string) string { return "" } @@ -582,6 +714,12 @@ func (adc *attachDetachController) GetConfigMapFunc() func(namespace, name strin } } +func (adc *attachDetachController) GetServiceAccountTokenFunc() func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return nil, fmt.Errorf("GetServiceAccountToken unsupported in attachDetachController") + } +} + func (adc *attachDetachController) GetExec(pluginName string) mount.Exec { return mount.NewOsExec() } @@ -607,3 +745,7 @@ func (adc *attachDetachController) GetNodeLabels() (map[string]string, error) { func (adc *attachDetachController) GetNodeName() types.NodeName { return "" } + +func (adc *attachDetachController) GetEventRecorder() record.EventRecorder { + return adc.recorder +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/populator/desired_state_of_world_populator_test.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/populator/desired_state_of_world_populator_test.go index 9e07d29c6..275f6d290 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/populator/desired_state_of_world_populator_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/populator/desired_state_of_world_populator_test.go @@ -68,7 +68,7 @@ func TestFindAndAddActivePods_FindAndRemoveDeletedPods(t *testing.T) { podName := util.GetUniquePodName(pod) - generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].Name + generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].GCEPersistentDisk.PDName pvcLister := fakeInformerFactory.Core().V1().PersistentVolumeClaims().Lister() pvLister := fakeInformerFactory.Core().V1().PersistentVolumes().Lister() diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/reconciler/reconciler.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/reconciler/reconciler.go index 47c690f83..5c57b2093 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/reconciler/reconciler.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/reconciler/reconciler.go @@ -257,13 +257,17 @@ func (rc *reconciler) attachDesiredVolumes() { for _, volumeToAttach := range rc.desiredStateOfWorld.GetVolumesToAttach() { if rc.actualStateOfWorld.VolumeNodeExists(volumeToAttach.VolumeName, volumeToAttach.NodeName) { // Volume/Node exists, touch it to reset detachRequestedTime - glog.V(5).Infof(volumeToAttach.GenerateMsgDetailed("Volume attached--touching", "")) + if glog.V(5) { + glog.Infof(volumeToAttach.GenerateMsgDetailed("Volume attached--touching", "")) + } rc.actualStateOfWorld.ResetDetachRequestTime(volumeToAttach.VolumeName, volumeToAttach.NodeName) continue } // Don't even try to start an operation if there is already one running if rc.attacherDetacher.IsOperationPending(volumeToAttach.VolumeName, "") { - glog.V(10).Infof("Operation for volume %q is already running. Can't start attach for %q", volumeToAttach.VolumeName, volumeToAttach.NodeName) + if glog.V(10) { + glog.Infof("Operation for volume %q is already running. Can't start attach for %q", volumeToAttach.VolumeName, volumeToAttach.NodeName) + } continue } @@ -279,7 +283,9 @@ func (rc *reconciler) attachDesiredVolumes() { } // Volume/Node doesn't exist, spawn a goroutine to attach it - glog.V(5).Infof(volumeToAttach.GenerateMsgDetailed("Starting attacherDetacher.AttachVolume", "")) + if glog.V(5) { + glog.Infof(volumeToAttach.GenerateMsgDetailed("Starting attacherDetacher.AttachVolume", "")) + } err := rc.attacherDetacher.AttachVolume(volumeToAttach.VolumeToAttach, rc.actualStateOfWorld) if err == nil { glog.Infof(volumeToAttach.GenerateMsgDetailed("attacherDetacher.AttachVolume started", "")) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing/testvolumespec.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing/testvolumespec.go index 06aad75f7..d72fbe4e6 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing/testvolumespec.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing/testvolumespec.go @@ -153,7 +153,6 @@ func CreateTestClient() *fake.Clientset { }, }, }, - Spec: v1.NodeSpec{ExternalID: string(nodeName)}, } obj.Items = append(obj.Items, node) } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/expand/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/volume/expand/BUILD index 5a067da6a..69c110142 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/expand/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/expand/BUILD @@ -25,6 +25,7 @@ go_library( "//pkg/volume/util/operationexecutor:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/expand/expand_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/expand/expand_controller.go index e41785f34..9a8e8d379 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/expand/expand_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/expand/expand_controller.go @@ -26,6 +26,7 @@ import ( "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/runtime" @@ -116,7 +117,7 @@ func NewExpandController( eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "volume_expand"}) blkutil := volumepathhandler.NewBlockVolumePathHandler() @@ -227,6 +228,10 @@ func (expc *expandController) GetVolumeDevicePluginDir(pluginName string) string return "" } +func (expc *expandController) GetPodsDir() string { + return "" +} + func (expc *expandController) GetPodVolumeDir(podUID types.UID, pluginName string, volumeName string) string { return "" } @@ -291,6 +296,12 @@ func (expc *expandController) GetConfigMapFunc() func(namespace, name string) (* } } +func (expc *expandController) GetServiceAccountTokenFunc() func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return nil, fmt.Errorf("GetServiceAccountToken unsupported in expandController") + } +} + func (expc *expandController) GetNodeLabels() (map[string]string, error) { return nil, fmt.Errorf("GetNodeLabels unsupported in expandController") } @@ -298,3 +309,7 @@ func (expc *expandController) GetNodeLabels() (map[string]string, error) { func (expc *expandController) GetNodeName() types.NodeName { return "" } + +func (expc *expandController) GetEventRecorder() record.EventRecorder { + return expc.recorder +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/BUILD b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/BUILD index 5367ef78f..ec57338d7 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/BUILD @@ -34,6 +34,7 @@ go_library( "//pkg/volume/util:go_default_library", "//pkg/volume/util/recyclerclient:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/OWNERS b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/OWNERS index f081b1b9d..1a69ba7d8 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/OWNERS @@ -2,3 +2,4 @@ approvers: - jsafrane - saad-ali - thockin +- msau42 # for volume scheduling diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/binder_test.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/binder_test.go index 0f51b47f0..d91156281 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/binder_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/binder_test.go @@ -723,7 +723,7 @@ func TestSyncAlphaBlockVolume(t *testing.T) { }, { // failed syncVolume do not bind when pvc is prebound to pv with mismatching volumeModes - "14-8-1 - do not bind when pv is prebound to pvc with mismatching volumeModes", + "14-8-1 - do not bind when pvc is prebound to pv with mismatching volumeModes", withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-8-1", "10Gi", "", "claim14-8-1", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty)), withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-8-1", "10Gi", "", "claim14-8-1", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty)), withClaimVolumeMode(&modeFile, newClaimArray("claim14-8-1", "uid14-8-1", "10Gi", "", v1.ClaimPending, nil)), @@ -767,6 +767,44 @@ func TestSyncAlphaBlockVolume(t *testing.T) { withClaimVolumeMode(&modeFile, newClaimArray("claim14-12", "uid14-12", "10Gi", "volume14-12", v1.ClaimBound, nil, annBoundByController, annBindCompleted)), noevents, noerrors, testSyncClaim, }, + { + // syncVolume output warning when pv is prebound to pvc with mismatching volumeMode + "14-13 - output warning when pv is prebound to pvc with different volumeModes", + withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-13", "10Gi", "uid14-13", "claim14-13", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController)), + withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-13", "10Gi", "uid14-13", "claim14-13", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController)), + withClaimVolumeMode(&modeBlock, newClaimArray("claim14-13", "uid14-13", "10Gi", "", v1.ClaimPending, nil)), + withClaimVolumeMode(&modeBlock, newClaimArray("claim14-13", "uid14-13", "10Gi", "", v1.ClaimPending, nil)), + []string{"Warning VolumeMismatch"}, + noerrors, testSyncVolume, + }, + { + // syncVolume output warning when pv is prebound to pvc with mismatching volumeMode + "14-13-1 - output warning when pv is prebound to pvc with different volumeModes", + withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-13-1", "10Gi", "uid14-13-1", "claim14-13-1", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController)), + withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-13-1", "10Gi", "uid14-13-1", "claim14-13-1", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController)), + withClaimVolumeMode(&modeFile, newClaimArray("claim14-13-1", "uid14-13-1", "10Gi", "", v1.ClaimPending, nil)), + withClaimVolumeMode(&modeFile, newClaimArray("claim14-13-1", "uid14-13-1", "10Gi", "", v1.ClaimPending, nil)), + []string{"Warning VolumeMismatch"}, + noerrors, testSyncVolume, + }, + { + // syncVolume waits for synClaim without warning when pv is prebound to pvc with matching volumeMode block + "14-14 - wait for synClaim without warning when pv is prebound to pvc with matching volumeModes block", + withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-14", "10Gi", "uid14-14", "claim14-14", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController)), + withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-14", "10Gi", "uid14-14", "claim14-14", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController)), + withClaimVolumeMode(&modeBlock, newClaimArray("claim14-14", "uid14-14", "10Gi", "", v1.ClaimPending, nil)), + withClaimVolumeMode(&modeBlock, newClaimArray("claim14-14", "uid14-14", "10Gi", "", v1.ClaimPending, nil)), + noevents, noerrors, testSyncVolume, + }, + { + // syncVolume waits for synClaim without warning when pv is prebound to pvc with matching volumeMode file + "14-14-1 - wait for synClaim without warning when pv is prebound to pvc with matching volumeModes file", + withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-14-1", "10Gi", "uid14-14-1", "claim14-14-1", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController)), + withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-14-1", "10Gi", "uid14-14-1", "claim14-14-1", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty, annBoundByController)), + withClaimVolumeMode(&modeFile, newClaimArray("claim14-14-1", "uid14-14-1", "10Gi", "", v1.ClaimPending, nil)), + withClaimVolumeMode(&modeFile, newClaimArray("claim14-14-1", "uid14-14-1", "10Gi", "", v1.ClaimPending, nil)), + noevents, noerrors, testSyncVolume, + }, } err := utilfeature.DefaultFeatureGate.Set("BlockVolume=true") diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/framework_test.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/framework_test.go index 5197f053c..13e36c25d 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/framework_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/framework_test.go @@ -612,6 +612,7 @@ func newTestController(kubeClient clientset.Interface, informerFactory informers ClaimInformer: informerFactory.Core().V1().PersistentVolumeClaims(), ClassInformer: informerFactory.Storage().V1().StorageClasses(), PodInformer: informerFactory.Core().V1().Pods(), + NodeInformer: informerFactory.Core().V1().Nodes(), EventRecorder: record.NewFakeRecorder(1000), EnableDynamicProvisioning: enableDynamicProvisioning, } @@ -1192,7 +1193,7 @@ func (plugin *mockVolumePlugin) NewProvisioner(options vol.VolumeOptions) (vol.P } } -func (plugin *mockVolumePlugin) Provision() (*v1.PersistentVolume, error) { +func (plugin *mockVolumePlugin) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if len(plugin.provisionCalls) <= plugin.provisionCallCounter { return nil, fmt.Errorf("Mock plugin error: unexpected provisioner call %d", plugin.provisionCallCounter) } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller.go index c245fb15b..732f1024b 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller.go @@ -122,6 +122,8 @@ const annBindCompleted = "pv.kubernetes.io/bind-completed" // the binding (PV->PVC or PVC->PV) was installed by the controller. The // absence of this annotation means the binding was done by the user (i.e. // pre-bound). Value of this annotation does not matter. +// External PV binders must bind PV the same way as PV controller, otherwise PV +// controller may not handle it correctly. const annBoundByController = "pv.kubernetes.io/bound-by-controller" // This annotation is added to a PV that has been dynamically provisioned by @@ -135,6 +137,14 @@ const annDynamicallyProvisioned = "pv.kubernetes.io/provisioned-by" // a volume for this PVC. const annStorageProvisioner = "volume.beta.kubernetes.io/storage-provisioner" +// This annotation is added to a PVC that has been triggered by scheduler to +// be dynamically provisioned. Its value is the name of the selected node. +const annSelectedNode = "volume.alpha.kubernetes.io/selected-node" + +// If the provisioner name in a storage class is set to "kubernetes.io/no-provisioner", +// then dynamic provisioning is not supported by the storage. +const notSupportedProvisioner = "kubernetes.io/no-provisioner" + // CloudVolumeCreatedForClaimNamespaceTag is a name of a tag attached to a real volume in cloud (e.g. AWS EBS or GCE PD) // with namespace of a persistent volume claim used to create this volume. const CloudVolumeCreatedForClaimNamespaceTag = "kubernetes.io/created-for/pvc/namespace" @@ -166,6 +176,8 @@ type PersistentVolumeController struct { classListerSynced cache.InformerSynced podLister corelisters.PodLister podListerSynced cache.InformerSynced + NodeLister corelisters.NodeLister + NodeListerSynced cache.InformerSynced kubeClient clientset.Interface eventRecorder record.EventRecorder @@ -277,6 +289,16 @@ func (ctrl *PersistentVolumeController) shouldDelayBinding(claim *v1.PersistentV return false, nil } + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + // When feature DynamicProvisioningScheduling enabled, + // Scheduler signal to the PV controller to start dynamic + // provisioning by setting the "annSelectedNode" annotation + // in the PVC + if _, ok := claim.Annotations[annSelectedNode]; ok { + return false, nil + } + } + className := v1helper.GetPersistentVolumeClaimClass(claim) if className == "" { return false, nil @@ -291,8 +313,6 @@ func (ctrl *PersistentVolumeController) shouldDelayBinding(claim *v1.PersistentV return false, fmt.Errorf("VolumeBindingMode not set for StorageClass %q", className) } - // TODO: add check to handle dynamic provisioning later - return *class.VolumeBindingMode == storage.VolumeBindingWaitForFirstConsumer, nil } @@ -320,7 +340,6 @@ func (ctrl *PersistentVolumeController) syncUnboundClaim(claim *v1.PersistentVol // OBSERVATION: pvc is "Pending", will retry switch { case delayBinding: - // TODO: Skip dynamic provisioning for now ctrl.eventRecorder.Event(claim, v1.EventTypeNormal, events.WaitForFirstConsumer, "waiting for first consumer to be created before binding") case v1helper.GetPersistentVolumeClaimClass(claim) != "": if err = ctrl.provisionClaim(claim); err != nil { @@ -527,6 +546,30 @@ func (ctrl *PersistentVolumeController) syncVolume(volume *v1.PersistentVolume) if err != nil { return err } + if !found && metav1.HasAnnotation(volume.ObjectMeta, annBoundByController) { + // If PV is bound by external PV binder (e.g. kube-scheduler), it's + // possible on heavy load that corresponding PVC is not synced to + // controller local cache yet. So we need to double-check PVC in + // 1) informer cache + // 2) apiserver if not found in informer cache + // to make sure we will not reclaim a PV wrongly. + // Note that only non-released and non-failed volumes will be + // updated to Released state when PVC does not eixst. + if volume.Status.Phase != v1.VolumeReleased && volume.Status.Phase != v1.VolumeFailed { + obj, err = ctrl.claimLister.PersistentVolumeClaims(volume.Spec.ClaimRef.Namespace).Get(volume.Spec.ClaimRef.Name) + if err != nil && !apierrs.IsNotFound(err) { + return err + } + found = !apierrs.IsNotFound(err) + if !found { + obj, err = ctrl.kubeClient.CoreV1().PersistentVolumeClaims(volume.Spec.ClaimRef.Namespace).Get(volume.Spec.ClaimRef.Name, metav1.GetOptions{}) + if err != nil && !apierrs.IsNotFound(err) { + return err + } + found = !apierrs.IsNotFound(err) + } + } + } if !found { glog.V(4).Infof("synchronizing PersistentVolume[%s]: claim %s not found", volume.Name, claimrefToClaimKey(volume.Spec.ClaimRef)) // Fall through with claim = nil @@ -571,6 +614,17 @@ func (ctrl *PersistentVolumeController) syncVolume(volume *v1.PersistentVolume) } return nil } else if claim.Spec.VolumeName == "" { + if isMisMatch, err := checkVolumeModeMisMatches(&claim.Spec, &volume.Spec); err != nil || isMisMatch { + // Binding for the volume won't be called in syncUnboundClaim, + // because findBestMatchForClaim won't return the volume due to volumeMode mismatch. + volumeMsg := fmt.Sprintf("Cannot bind PersistentVolume to requested PersistentVolumeClaim %q due to incompatible volumeMode.", claim.Name) + ctrl.eventRecorder.Event(volume, v1.EventTypeWarning, events.VolumeMismatch, volumeMsg) + claimMsg := fmt.Sprintf("Cannot bind PersistentVolume %q to requested PersistentVolumeClaim due to incompatible volumeMode.", volume.Name) + ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.VolumeMismatch, claimMsg) + // Skipping syncClaim + return nil + } + if metav1.HasAnnotation(volume.ObjectMeta, annBoundByController) { // The binding is not completed; let PVC sync handle it glog.V(4).Infof("synchronizing PersistentVolume[%s]: volume not bound yet, waiting for syncClaim to fix it", volume.Name) @@ -1045,12 +1099,7 @@ func (ctrl *PersistentVolumeController) reclaimVolume(volume *v1.PersistentVolum // doRerecycleVolumeOperationcycleVolume recycles a volume. This method is // running in standalone goroutine and already has all necessary locks. -func (ctrl *PersistentVolumeController) recycleVolumeOperation(arg interface{}) { - volume, ok := arg.(*v1.PersistentVolume) - if !ok { - glog.Errorf("Cannot convert recycleVolumeOperation argument to volume, got %#v", arg) - return - } +func (ctrl *PersistentVolumeController) recycleVolumeOperation(volume *v1.PersistentVolume) { glog.V(4).Infof("recycleVolumeOperation [%s] started", volume.Name) // This method may have been waiting for a volume lock for some time. @@ -1134,13 +1183,7 @@ func (ctrl *PersistentVolumeController) recycleVolumeOperation(arg interface{}) // deleteVolumeOperation deletes a volume. This method is running in standalone // goroutine and already has all necessary locks. -func (ctrl *PersistentVolumeController) deleteVolumeOperation(arg interface{}) error { - volume, ok := arg.(*v1.PersistentVolume) - if !ok { - glog.Errorf("Cannot convert deleteVolumeOperation argument to volume, got %#v", arg) - return nil - } - +func (ctrl *PersistentVolumeController) deleteVolumeOperation(volume *v1.PersistentVolume) error { glog.V(4).Infof("deleteVolumeOperation [%s] started", volume.Name) // This method may have been waiting for a volume lock for some time. @@ -1331,13 +1374,7 @@ func (ctrl *PersistentVolumeController) provisionClaim(claim *v1.PersistentVolum // provisionClaimOperation provisions a volume. This method is running in // standalone goroutine and already has all necessary locks. -func (ctrl *PersistentVolumeController) provisionClaimOperation(claimObj interface{}) { - claim, ok := claimObj.(*v1.PersistentVolumeClaim) - if !ok { - glog.Errorf("Cannot convert provisionClaimOperation argument to claim, got %#v", claimObj) - return - } - +func (ctrl *PersistentVolumeController) provisionClaimOperation(claim *v1.PersistentVolumeClaim) { claimClass := v1helper.GetPersistentVolumeClaimClass(claim) glog.V(4).Infof("provisionClaimOperation [%s] started, class: %q", claimToClaimKey(claim), claimClass) @@ -1425,10 +1462,30 @@ func (ctrl *PersistentVolumeController) provisionClaimOperation(claimObj interfa return } + var selectedNode *v1.Node = nil + var allowedTopologies []v1.TopologySelectorTerm = nil + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + if nodeName, ok := claim.Annotations[annSelectedNode]; ok { + selectedNode, err = ctrl.NodeLister.Get(nodeName) + if err != nil { + strerr := fmt.Sprintf("Failed to get target node: %v", err) + glog.V(3).Infof("unexpected error getting target node %q for claim %q: %v", nodeName, claimToClaimKey(claim), err) + ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr) + return + } + } + allowedTopologies = storageClass.AllowedTopologies + } + opComplete := util.OperationCompleteHook(plugin.GetPluginName(), "volume_provision") - volume, err = provisioner.Provision() + volume, err = provisioner.Provision(selectedNode, allowedTopologies) opComplete(&err) if err != nil { + // Other places of failure have nothing to do with DynamicProvisioningScheduling, + // so just let controller retry in the next sync. We'll only call func + // rescheduleProvisioning here when the underlying provisioning actually failed. + ctrl.rescheduleProvisioning(claim) + strerr := fmt.Sprintf("Failed to provision volume with StorageClass %q: %v", storageClass.Name, err) glog.V(2).Infof("failed to provision volume for claim %q with StorageClass %q: %v", claimToClaimKey(claim), storageClass.Name, err) ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr) @@ -1519,6 +1576,29 @@ func (ctrl *PersistentVolumeController) provisionClaimOperation(claimObj interfa } } +// rescheduleProvisioning signal back to the scheduler to retry dynamic provisioning +// by removing the annSelectedNode annotation +func (ctrl *PersistentVolumeController) rescheduleProvisioning(claim *v1.PersistentVolumeClaim) { + if _, ok := claim.Annotations[annSelectedNode]; !ok { + // Provisioning not triggered by the scheduler, skip + return + } + + // The claim from method args can be pointing to watcher cache. We must not + // modify these, therefore create a copy. + newClaim := claim.DeepCopy() + delete(newClaim.Annotations, annSelectedNode) + // Try to update the PVC object + if _, err := ctrl.kubeClient.CoreV1().PersistentVolumeClaims(newClaim.Namespace).Update(newClaim); err != nil { + glog.V(4).Infof("Failed to delete annotation 'annSelectedNode' for PersistentVolumeClaim %q: %v", claimToClaimKey(newClaim), err) + return + } + if _, err := ctrl.storeClaimUpdate(newClaim); err != nil { + // We will get an "claim updated" event soon, this is not a big error + glog.V(4).Infof("Updating PersistentVolumeClaim %q: cannot update internal cache: %v", claimToClaimKey(newClaim), err) + } +} + // getProvisionedVolumeNameForClaim returns PV.Name for the provisioned volume. // The name must be unique. func (ctrl *PersistentVolumeController) getProvisionedVolumeNameForClaim(claim *v1.PersistentVolumeClaim) string { diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller_base.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller_base.go index 1b745ef93..40e788248 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller_base.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller_base.go @@ -63,6 +63,7 @@ type ControllerParameters struct { ClaimInformer coreinformers.PersistentVolumeClaimInformer ClassInformer storageinformers.StorageClassInformer PodInformer coreinformers.PodInformer + NodeInformer coreinformers.NodeInformer EventRecorder record.EventRecorder EnableDynamicProvisioning bool } @@ -73,7 +74,7 @@ func NewController(p ControllerParameters) (*PersistentVolumeController, error) if eventRecorder == nil { broadcaster := record.NewBroadcaster() broadcaster.StartLogging(glog.Infof) - broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(p.KubeClient.CoreV1().RESTClient()).Events("")}) + broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: p.KubeClient.CoreV1().Events("")}) eventRecorder = broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "persistentvolume-controller"}) } @@ -122,6 +123,8 @@ func NewController(p ControllerParameters) (*PersistentVolumeController, error) controller.classListerSynced = p.ClassInformer.Informer().HasSynced controller.podLister = p.PodInformer.Lister() controller.podListerSynced = p.PodInformer.Informer().HasSynced + controller.NodeLister = p.NodeInformer.Lister() + controller.NodeListerSynced = p.NodeInformer.Informer().HasSynced return controller, nil } @@ -268,7 +271,7 @@ func (ctrl *PersistentVolumeController) Run(stopCh <-chan struct{}) { glog.Infof("Starting persistent volume controller") defer glog.Infof("Shutting down persistent volume controller") - if !controller.WaitForCacheSync("persistent volume", stopCh, ctrl.volumeListerSynced, ctrl.claimListerSynced, ctrl.classListerSynced, ctrl.podListerSynced) { + if !controller.WaitForCacheSync("persistent volume", stopCh, ctrl.volumeListerSynced, ctrl.claimListerSynced, ctrl.classListerSynced, ctrl.podListerSynced, ctrl.NodeListerSynced) { return } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller_test.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller_test.go index 5454fe26e..48b7c1d98 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/pv_controller_test.go @@ -312,8 +312,8 @@ func TestDelayBinding(t *testing.T) { } } - // When feature gate is disabled, should always be delayed - name := "feature-disabled" + // When volumeScheduling feature gate is disabled, should always be delayed + name := "volumeScheduling-feature-disabled" shouldDelay, err := ctrl.shouldDelayBinding(makePVCClass(&classWaitMode)) if err != nil { t.Errorf("Test %q returned error: %v", name, err) @@ -322,7 +322,7 @@ func TestDelayBinding(t *testing.T) { t.Errorf("Test %q returned true, expected false", name) } - // Enable feature gate + // Enable volumeScheduling feature gate utilfeature.DefaultFeatureGate.Set("VolumeScheduling=true") defer utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false") @@ -338,4 +338,43 @@ func TestDelayBinding(t *testing.T) { t.Errorf("Test %q returned unexpected %v", name, test.shouldDelay) } } + + // When dynamicProvisioningScheduling feature gate is disabled, should be delayed, + // even if the pvc has selectedNode annotation. + provisionedClaim := makePVCClass(&classWaitMode) + provisionedClaim.Annotations = map[string]string{annSelectedNode: "node-name"} + name = "dynamicProvisioningScheduling-feature-disabled" + shouldDelay, err = ctrl.shouldDelayBinding(provisionedClaim) + if err != nil { + t.Errorf("Test %q returned error: %v", name, err) + } + if !shouldDelay { + t.Errorf("Test %q returned false, expected true", name) + } + + // Enable DynamicProvisioningScheduling feature gate + utilfeature.DefaultFeatureGate.Set("DynamicProvisioningScheduling=true") + defer utilfeature.DefaultFeatureGate.Set("DynamicProvisioningScheduling=false") + + // When the pvc does not have selectedNode annotation, should be delayed, + // even if dynamicProvisioningScheduling feature gate is enabled. + name = "dynamicProvisioningScheduling-feature-enabled, selectedNode-annotation-not-set" + shouldDelay, err = ctrl.shouldDelayBinding(makePVCClass(&classWaitMode)) + if err != nil { + t.Errorf("Test %q returned error: %v", name, err) + } + if !shouldDelay { + t.Errorf("Test %q returned false, expected true", name) + } + + // Should not be delayed when dynamicProvisioningScheduling feature gate is enabled, + // and the pvc has selectedNode annotation. + name = "dynamicProvisioningScheduling-feature-enabled, selectedNode-annotation-set" + shouldDelay, err = ctrl.shouldDelayBinding(provisionedClaim) + if err != nil { + t.Errorf("Test %q returned error: %v", name, err) + } + if shouldDelay { + t.Errorf("Test %q returned true, expected false", name) + } } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_assume_cache.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_assume_cache.go index c5217be0e..b04b402bf 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_assume_cache.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_assume_cache.go @@ -158,8 +158,30 @@ func (c *assumeCache) add(obj interface{}) { c.mutex.Lock() defer c.mutex.Unlock() + if objInfo, _ := c.getObjInfo(name); objInfo != nil { + newVersion, err := c.getObjVersion(name, obj) + if err != nil { + glog.Errorf("add: couldn't get object version: %v", err) + return + } + + storedVersion, err := c.getObjVersion(name, objInfo.latestObj) + if err != nil { + glog.Errorf("add: couldn't get stored object version: %v", err) + return + } + + // Only update object if version is newer. + // This is so we don't override assumed objects due to informer resync. + if newVersion <= storedVersion { + glog.V(10).Infof("Skip adding %v %v to assume cache because version %v is not newer than %v", c.description, name, newVersion, storedVersion) + return + } + } + objInfo := &objInfo{name: name, latestObj: obj, apiObj: obj} c.store.Update(objInfo) + glog.V(10).Infof("Adding %v %v to assume cache: %+v ", c.description, name, obj) } func (c *assumeCache) update(oldObj interface{}, newObj interface{}) { @@ -349,3 +371,34 @@ func (c *pvAssumeCache) ListPVs(storageClassName string) []*v1.PersistentVolume } return pvs } + +// PVCAssumeCache is a AssumeCache for PersistentVolumeClaim objects +type PVCAssumeCache interface { + AssumeCache + + // GetPVC returns the PVC from the cache with the same + // namespace and the same name of the specified pod. + // pvcKey is the result of MetaNamespaceKeyFunc on PVC obj + GetPVC(pvcKey string) (*v1.PersistentVolumeClaim, error) +} + +type pvcAssumeCache struct { + *assumeCache +} + +func NewPVCAssumeCache(informer cache.SharedIndexInformer) PVCAssumeCache { + return &pvcAssumeCache{assumeCache: NewAssumeCache(informer, "v1.PersistentVolumeClaim", "namespace", cache.MetaNamespaceIndexFunc)} +} + +func (c *pvcAssumeCache) GetPVC(pvcKey string) (*v1.PersistentVolumeClaim, error) { + obj, err := c.Get(pvcKey) + if err != nil { + return nil, err + } + + pvc, ok := obj.(*v1.PersistentVolumeClaim) + if !ok { + return nil, &errWrongType{"v1.PersistentVolumeClaim", obj} + } + return pvc, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_assume_cache_test.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_assume_cache_test.go index 2664e4c41..c6c0f1f0c 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_assume_cache_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_assume_cache_test.go @@ -36,6 +36,33 @@ func makePV(name, version, storageClass string) *v1.PersistentVolume { } } +func verifyListPVs(t *testing.T, cache PVAssumeCache, expectedPVs map[string]*v1.PersistentVolume, storageClassName string) { + pvList := cache.ListPVs(storageClassName) + if len(pvList) != len(expectedPVs) { + t.Errorf("ListPVs() returned %v PVs, expected %v", len(pvList), len(expectedPVs)) + } + for _, pv := range pvList { + expectedPV, ok := expectedPVs[pv.Name] + if !ok { + t.Errorf("ListPVs() returned unexpected PV %q", pv.Name) + } + if expectedPV != pv { + t.Errorf("ListPVs() returned PV %p, expected %p", pv, expectedPV) + } + } +} + +func verifyPV(cache PVAssumeCache, name string, expectedPV *v1.PersistentVolume) error { + pv, err := cache.GetPV(name) + if err != nil { + return err + } + if pv != expectedPV { + return fmt.Errorf("GetPV() returned %p, expected %p", pv, expectedPV) + } + return nil +} + func TestAssumePV(t *testing.T) { scenarios := map[string]struct { oldPV *v1.PersistentVolume @@ -88,7 +115,7 @@ func TestAssumePV(t *testing.T) { // Add oldPV to cache internal_cache.add(scenario.oldPV) - if err := getPV(cache, scenario.oldPV.Name, scenario.oldPV); err != nil { + if err := verifyPV(cache, scenario.oldPV.Name, scenario.oldPV); err != nil { t.Errorf("Failed to GetPV() after initial update: %v", err) continue } @@ -107,7 +134,7 @@ func TestAssumePV(t *testing.T) { if !scenario.shouldSucceed { expectedPV = scenario.oldPV } - if err := getPV(cache, scenario.oldPV.Name, expectedPV); err != nil { + if err := verifyPV(cache, scenario.oldPV.Name, expectedPV); err != nil { t.Errorf("Failed to GetPV() after initial update: %v", err) } } @@ -128,13 +155,13 @@ func TestRestorePV(t *testing.T) { // Add oldPV to cache internal_cache.add(oldPV) - if err := getPV(cache, oldPV.Name, oldPV); err != nil { + if err := verifyPV(cache, oldPV.Name, oldPV); err != nil { t.Fatalf("Failed to GetPV() after initial update: %v", err) } // Restore PV cache.Restore(oldPV.Name) - if err := getPV(cache, oldPV.Name, oldPV); err != nil { + if err := verifyPV(cache, oldPV.Name, oldPV); err != nil { t.Fatalf("Failed to GetPV() after iniital restore: %v", err) } @@ -142,13 +169,13 @@ func TestRestorePV(t *testing.T) { if err := cache.Assume(newPV); err != nil { t.Fatalf("Assume() returned error %v", err) } - if err := getPV(cache, oldPV.Name, newPV); err != nil { + if err := verifyPV(cache, oldPV.Name, newPV); err != nil { t.Fatalf("Failed to GetPV() after Assume: %v", err) } // Restore PV cache.Restore(oldPV.Name) - if err := getPV(cache, oldPV.Name, oldPV); err != nil { + if err := verifyPV(cache, oldPV.Name, oldPV); err != nil { t.Fatalf("Failed to GetPV() after restore: %v", err) } } @@ -243,29 +270,203 @@ func TestPVCacheWithStorageClasses(t *testing.T) { verifyListPVs(t, cache, pvs2, "class2") } -func verifyListPVs(t *testing.T, cache PVAssumeCache, expectedPVs map[string]*v1.PersistentVolume, storageClassName string) { - pvList := cache.ListPVs(storageClassName) - if len(pvList) != len(expectedPVs) { - t.Errorf("ListPVs() returned %v PVs, expected %v", len(pvList), len(expectedPVs)) +func TestAssumeUpdatePVCache(t *testing.T) { + cache := NewPVAssumeCache(nil) + internal_cache, ok := cache.(*pvAssumeCache) + if !ok { + t.Fatalf("Failed to get internal cache") } - for _, pv := range pvList { - expectedPV, ok := expectedPVs[pv.Name] - if !ok { - t.Errorf("ListPVs() returned unexpected PV %q", pv.Name) - } - if expectedPV != pv { - t.Errorf("ListPVs() returned PV %p, expected %p", pv, expectedPV) - } + + pvName := "test-pv0" + + // Add a PV + pv := makePV(pvName, "1", "") + internal_cache.add(pv) + if err := verifyPV(cache, pvName, pv); err != nil { + t.Fatalf("failed to get PV: %v", err) + } + + // Assume PV + newPV := pv.DeepCopy() + newPV.Spec.ClaimRef = &v1.ObjectReference{Name: "test-claim"} + if err := cache.Assume(newPV); err != nil { + t.Fatalf("failed to assume PV: %v", err) + } + if err := verifyPV(cache, pvName, newPV); err != nil { + t.Fatalf("failed to get PV after assume: %v", err) + } + + // Add old PV + internal_cache.add(pv) + if err := verifyPV(cache, pvName, newPV); err != nil { + t.Fatalf("failed to get PV after old PV added: %v", err) } } -func getPV(cache PVAssumeCache, name string, expectedPV *v1.PersistentVolume) error { - pv, err := cache.GetPV(name) +func makeClaim(name, version, namespace string) *v1.PersistentVolumeClaim { + return &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + ResourceVersion: version, + Annotations: map[string]string{}, + }, + } +} + +func verifyPVC(cache PVCAssumeCache, pvcKey string, expectedPVC *v1.PersistentVolumeClaim) error { + pvc, err := cache.GetPVC(pvcKey) if err != nil { return err } - if pv != expectedPV { - return fmt.Errorf("GetPV() returned %p, expected %p", pv, expectedPV) + if pvc != expectedPVC { + return fmt.Errorf("GetPVC() returned %p, expected %p", pvc, expectedPVC) } return nil } + +func TestAssumePVC(t *testing.T) { + scenarios := map[string]struct { + oldPVC *v1.PersistentVolumeClaim + newPVC *v1.PersistentVolumeClaim + shouldSucceed bool + }{ + "success-same-version": { + oldPVC: makeClaim("pvc1", "5", "ns1"), + newPVC: makeClaim("pvc1", "5", "ns1"), + shouldSucceed: true, + }, + "success-new-higher-version": { + oldPVC: makeClaim("pvc1", "5", "ns1"), + newPVC: makeClaim("pvc1", "6", "ns1"), + shouldSucceed: true, + }, + "fail-old-not-found": { + oldPVC: makeClaim("pvc2", "5", "ns1"), + newPVC: makeClaim("pvc1", "5", "ns1"), + shouldSucceed: false, + }, + "fail-new-lower-version": { + oldPVC: makeClaim("pvc1", "5", "ns1"), + newPVC: makeClaim("pvc1", "4", "ns1"), + shouldSucceed: false, + }, + "fail-new-bad-version": { + oldPVC: makeClaim("pvc1", "5", "ns1"), + newPVC: makeClaim("pvc1", "a", "ns1"), + shouldSucceed: false, + }, + "fail-old-bad-version": { + oldPVC: makeClaim("pvc1", "a", "ns1"), + newPVC: makeClaim("pvc1", "5", "ns1"), + shouldSucceed: false, + }, + } + + for name, scenario := range scenarios { + cache := NewPVCAssumeCache(nil) + internal_cache, ok := cache.(*pvcAssumeCache) + if !ok { + t.Fatalf("Failed to get internal cache") + } + + // Add oldPVC to cache + internal_cache.add(scenario.oldPVC) + if err := verifyPVC(cache, getPVCName(scenario.oldPVC), scenario.oldPVC); err != nil { + t.Errorf("Failed to GetPVC() after initial update: %v", err) + continue + } + + // Assume newPVC + err := cache.Assume(scenario.newPVC) + if scenario.shouldSucceed && err != nil { + t.Errorf("Test %q failed: Assume() returned error %v", name, err) + } + if !scenario.shouldSucceed && err == nil { + t.Errorf("Test %q failed: Assume() returned success but expected error", name) + } + + // Check that GetPVC returns correct PVC + expectedPV := scenario.newPVC + if !scenario.shouldSucceed { + expectedPV = scenario.oldPVC + } + if err := verifyPVC(cache, getPVCName(scenario.oldPVC), expectedPV); err != nil { + t.Errorf("Failed to GetPVC() after initial update: %v", err) + } + } +} + +func TestRestorePVC(t *testing.T) { + cache := NewPVCAssumeCache(nil) + internal_cache, ok := cache.(*pvcAssumeCache) + if !ok { + t.Fatalf("Failed to get internal cache") + } + + oldPVC := makeClaim("pvc1", "5", "ns1") + newPVC := makeClaim("pvc1", "5", "ns1") + + // Restore PVC that doesn't exist + cache.Restore("nothing") + + // Add oldPVC to cache + internal_cache.add(oldPVC) + if err := verifyPVC(cache, getPVCName(oldPVC), oldPVC); err != nil { + t.Fatalf("Failed to GetPVC() after initial update: %v", err) + } + + // Restore PVC + cache.Restore(getPVCName(oldPVC)) + if err := verifyPVC(cache, getPVCName(oldPVC), oldPVC); err != nil { + t.Fatalf("Failed to GetPVC() after iniital restore: %v", err) + } + + // Assume newPVC + if err := cache.Assume(newPVC); err != nil { + t.Fatalf("Assume() returned error %v", err) + } + if err := verifyPVC(cache, getPVCName(oldPVC), newPVC); err != nil { + t.Fatalf("Failed to GetPVC() after Assume: %v", err) + } + + // Restore PVC + cache.Restore(getPVCName(oldPVC)) + if err := verifyPVC(cache, getPVCName(oldPVC), oldPVC); err != nil { + t.Fatalf("Failed to GetPVC() after restore: %v", err) + } +} + +func TestAssumeUpdatePVCCache(t *testing.T) { + cache := NewPVCAssumeCache(nil) + internal_cache, ok := cache.(*pvcAssumeCache) + if !ok { + t.Fatalf("Failed to get internal cache") + } + + pvcName := "test-pvc0" + pvcNamespace := "test-ns" + + // Add a PVC + pvc := makeClaim(pvcName, "1", pvcNamespace) + internal_cache.add(pvc) + if err := verifyPVC(cache, getPVCName(pvc), pvc); err != nil { + t.Fatalf("failed to get PVC: %v", err) + } + + // Assume PVC + newPVC := pvc.DeepCopy() + newPVC.Annotations["volume.alpha.kubernetes.io/selected-node"] = "test-node" + if err := cache.Assume(newPVC); err != nil { + t.Fatalf("failed to assume PVC: %v", err) + } + if err := verifyPVC(cache, getPVCName(pvc), newPVC); err != nil { + t.Fatalf("failed to get PVC after assume: %v", err) + } + + // Add old PVC + internal_cache.add(pvc) + if err := verifyPVC(cache, getPVCName(pvc), newPVC); err != nil { + t.Fatalf("failed to get PVC after old PVC added: %v", err) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder.go index b342e7f46..bec90c1b8 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder.go @@ -24,10 +24,13 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + utilfeature "k8s.io/apiserver/pkg/util/feature" coreinformers "k8s.io/client-go/informers/core/v1" storageinformers "k8s.io/client-go/informers/storage/v1" clientset "k8s.io/client-go/kubernetes" - corelisters "k8s.io/client-go/listers/core/v1" + v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" + "k8s.io/kubernetes/pkg/features" volumeutil "k8s.io/kubernetes/pkg/volume/util" ) @@ -58,24 +61,30 @@ type SchedulerVolumeBinder interface { // If a PVC is bound, it checks if the PV's NodeAffinity matches the Node. // Otherwise, it tries to find an available PV to bind to the PVC. // - // It returns true if there are matching PVs that can satisfy all of the Pod's PVCs, and returns true - // if bound volumes satisfy the PV NodeAffinity. + // It returns true if all of the Pod's PVCs have matching PVs or can be dynamic provisioned, + // and returns true if bound volumes satisfy the PV NodeAffinity. // // This function is called by the volume binding scheduler predicate and can be called in parallel FindPodVolumes(pod *v1.Pod, node *v1.Node) (unboundVolumesSatisified, boundVolumesSatisfied bool, err error) - // AssumePodVolumes will take the PV matches for unbound PVCs and update the PV cache assuming + // AssumePodVolumes will: + // 1. Take the PV matches for unbound PVCs and update the PV cache assuming // that the PV is prebound to the PVC. + // 2. Take the PVCs that need provisioning and update the PVC cache with related + // annotations set. // - // It returns true if all volumes are fully bound, and returns true if any volume binding API operation needs - // to be done afterwards. + // It returns true if all volumes are fully bound, and returns true if any volume binding/provisioning + // API operation needs to be done afterwards. // // This function will modify assumedPod with the node name. // This function is called serially. AssumePodVolumes(assumedPod *v1.Pod, nodeName string) (allFullyBound bool, bindingRequired bool, err error) - // BindPodVolumes will initiate the volume binding by making the API call to prebind the PV + // BindPodVolumes will: + // 1. Initiate the volume binding by making the API call to prebind the PV // to its matching PVC. + // 2. Trigger the volume provisioning by making the API call to set related + // annotations on the PVC // // This function can be called in parallel. BindPodVolumes(assumedPod *v1.Pod) error @@ -87,8 +96,7 @@ type SchedulerVolumeBinder interface { type volumeBinder struct { ctrl *PersistentVolumeController - // TODO: Need AssumeCache for PVC for dynamic provisioning - pvcCache corelisters.PersistentVolumeClaimLister + pvcCache PVCAssumeCache pvCache PVAssumeCache // Stores binding decisions that were made in FindPodVolumes for use in AssumePodVolumes. @@ -111,7 +119,7 @@ func NewVolumeBinder( b := &volumeBinder{ ctrl: ctrl, - pvcCache: pvcInformer.Lister(), + pvcCache: NewPVCAssumeCache(pvcInformer.Informer()), pvCache: NewPVAssumeCache(pvInformer.Informer()), podBindingCache: NewPodBindingCache(), } @@ -123,7 +131,7 @@ func (b *volumeBinder) GetBindingsCache() PodBindingCache { return b.podBindingCache } -// FindPodVolumes caches the matching PVs per node in podBindingCache +// FindPodVolumes caches the matching PVs and PVCs to provision per node in podBindingCache func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, node *v1.Node) (unboundVolumesSatisfied, boundVolumesSatisfied bool, err error) { podName := getPodName(pod) @@ -135,8 +143,8 @@ func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, node *v1.Node) (unboundVolume boundVolumesSatisfied = true // The pod's volumes need to be processed in one call to avoid the race condition where - // volumes can get bound in between calls. - boundClaims, unboundClaims, unboundClaimsImmediate, err := b.getPodVolumes(pod) + // volumes can get bound/provisioned in between calls. + boundClaims, claimsToBind, unboundClaimsImmediate, err := b.getPodVolumes(pod) if err != nil { return false, false, err } @@ -154,37 +162,51 @@ func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, node *v1.Node) (unboundVolume } } - // Find PVs for unbound volumes - if len(unboundClaims) > 0 { - unboundVolumesSatisfied, err = b.findMatchingVolumes(pod, unboundClaims, node) + if len(claimsToBind) > 0 { + var claimsToProvision []*v1.PersistentVolumeClaim + unboundVolumesSatisfied, claimsToProvision, err = b.findMatchingVolumes(pod, claimsToBind, node) if err != nil { return false, false, err } + + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + // Try to provision for unbound volumes + if !unboundVolumesSatisfied { + unboundVolumesSatisfied, err = b.checkVolumeProvisions(pod, claimsToProvision, node) + if err != nil { + return false, false, err + } + } + } } return unboundVolumesSatisfied, boundVolumesSatisfied, nil } -// AssumePodVolumes will take the cached matching PVs in podBindingCache for the chosen node -// and update the pvCache with the new prebound PV. It will update podBindingCache again -// with the PVs that need an API update. +// AssumePodVolumes will take the cached matching PVs and PVCs to provision +// in podBindingCache for the chosen node, and: +// 1. Update the pvCache with the new prebound PV. +// 2. Update the pvcCache with the new PVCs with annotations set +// It will update podBindingCache again with the PVs and PVCs that need an API update. func (b *volumeBinder) AssumePodVolumes(assumedPod *v1.Pod, nodeName string) (allFullyBound, bindingRequired bool, err error) { podName := getPodName(assumedPod) glog.V(4).Infof("AssumePodVolumes for pod %q, node %q", podName, nodeName) if allBound := b.arePodVolumesBound(assumedPod); allBound { - glog.V(4).Infof("AssumePodVolumes: all PVCs bound and nothing to do") + glog.V(4).Infof("AssumePodVolumes for pod %q, node %q: all PVCs bound and nothing to do", podName, nodeName) return true, false, nil } assumedPod.Spec.NodeName = nodeName + // Assume PV claimsToBind := b.podBindingCache.GetBindings(assumedPod, nodeName) newBindings := []*bindingInfo{} for _, binding := range claimsToBind { newPV, dirty, err := b.ctrl.getBindVolumeToClaim(binding.pv, binding.pvc) - glog.V(5).Infof("AssumePodVolumes: getBindVolumeToClaim for PV %q, PVC %q. newPV %p, dirty %v, err: %v", + glog.V(5).Infof("AssumePodVolumes: getBindVolumeToClaim for pod %q, PV %q, PVC %q. newPV %p, dirty %v, err: %v", + podName, binding.pv.Name, binding.pvc.Name, newPV, @@ -205,30 +227,71 @@ func (b *volumeBinder) AssumePodVolumes(assumedPod *v1.Pod, nodeName string) (al } } - if len(newBindings) == 0 { - // Don't update cached bindings if no API updates are needed. This can happen if we - // previously updated the PV object and are waiting for the PV controller to finish binding. - glog.V(4).Infof("AssumePodVolumes: PVs already assumed") - return false, false, nil + // Don't update cached bindings if no API updates are needed. This can happen if we + // previously updated the PV object and are waiting for the PV controller to finish binding. + if len(newBindings) != 0 { + bindingRequired = true + b.podBindingCache.UpdateBindings(assumedPod, nodeName, newBindings) + } + + // Assume PVCs + claimsToProvision := b.podBindingCache.GetProvisionedPVCs(assumedPod, nodeName) + + newProvisionedPVCs := []*v1.PersistentVolumeClaim{} + for _, claim := range claimsToProvision { + // The claims from method args can be pointing to watcher cache. We must not + // modify these, therefore create a copy. + claimClone := claim.DeepCopy() + metav1.SetMetaDataAnnotation(&claimClone.ObjectMeta, annSelectedNode, nodeName) + err = b.pvcCache.Assume(claimClone) + if err != nil { + b.revertAssumedPVs(newBindings) + b.revertAssumedPVCs(newProvisionedPVCs) + return + } + + newProvisionedPVCs = append(newProvisionedPVCs, claimClone) + } + + if len(newProvisionedPVCs) != 0 { + bindingRequired = true + b.podBindingCache.UpdateProvisionedPVCs(assumedPod, nodeName, newProvisionedPVCs) } - b.podBindingCache.UpdateBindings(assumedPod, nodeName, newBindings) - return false, true, nil + return } -// BindPodVolumes gets the cached bindings in podBindingCache and makes the API update for those PVs. +// BindPodVolumes gets the cached bindings and PVCs to provision in podBindingCache +// and makes the API update for those PVs/PVCs. func (b *volumeBinder) BindPodVolumes(assumedPod *v1.Pod) error { - glog.V(4).Infof("BindPodVolumes for pod %q", getPodName(assumedPod)) + podName := getPodName(assumedPod) + glog.V(4).Infof("BindPodVolumes for pod %q", podName) bindings := b.podBindingCache.GetBindings(assumedPod, assumedPod.Spec.NodeName) + claimsToProvision := b.podBindingCache.GetProvisionedPVCs(assumedPod, assumedPod.Spec.NodeName) // Do the actual prebinding. Let the PV controller take care of the rest // There is no API rollback if the actual binding fails for i, bindingInfo := range bindings { + glog.V(5).Infof("BindPodVolumes: Pod %q, binding PV %q to PVC %q", podName, bindingInfo.pv.Name, bindingInfo.pvc.Name) _, err := b.ctrl.updateBindVolumeToClaim(bindingInfo.pv, bindingInfo.pvc, false) if err != nil { // only revert assumed cached updates for volumes we haven't successfully bound b.revertAssumedPVs(bindings[i:]) + // Revert all of the assumed cached updates for claims, + // since no actual API update will be done + b.revertAssumedPVCs(claimsToProvision) + return err + } + } + + // Update claims objects to trigger volume provisioning. Let the PV controller take care of the rest + // PV controller is expect to signal back by removing related annotations if actual provisioning fails + for i, claim := range claimsToProvision { + if _, err := b.ctrl.kubeClient.CoreV1().PersistentVolumeClaims(claim.Namespace).Update(claim); err != nil { + glog.V(4).Infof("updating PersistentVolumeClaim[%s] failed: %v", getPVCName(claim), err) + // only revert assumed cached updates for claims we haven't successfully updated + b.revertAssumedPVCs(claimsToProvision[i:]) return err } } @@ -250,7 +313,13 @@ func (b *volumeBinder) isVolumeBound(namespace string, vol *v1.Volume, checkFull } pvcName := vol.PersistentVolumeClaim.ClaimName - pvc, err := b.pvcCache.PersistentVolumeClaims(namespace).Get(pvcName) + claim := &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: namespace, + }, + } + pvc, err := b.pvcCache.GetPVC(getPVCName(claim)) if err != nil || pvc == nil { return false, nil, fmt.Errorf("error getting PVC %q: %v", pvcName, err) } @@ -335,16 +404,22 @@ func (b *volumeBinder) checkBoundClaims(claims []*v1.PersistentVolumeClaim, node glog.V(5).Infof("PersistentVolume %q, Node %q matches for Pod %q", pvName, node.Name, podName) } - glog.V(4).Infof("All volumes for Pod %q match with Node %q", podName, node.Name) + glog.V(4).Infof("All bound volumes for Pod %q match with Node %q", podName, node.Name) return true, nil } -func (b *volumeBinder) findMatchingVolumes(pod *v1.Pod, claimsToBind []*bindingInfo, node *v1.Node) (foundMatches bool, err error) { +// findMatchingVolumes tries to find matching volumes for given claims, +// and return unbound claims for further provision. +func (b *volumeBinder) findMatchingVolumes(pod *v1.Pod, claimsToBind []*bindingInfo, node *v1.Node) (foundMatches bool, unboundClaims []*v1.PersistentVolumeClaim, err error) { + podName := getPodName(pod) // Sort all the claims by increasing size request to get the smallest fits sort.Sort(byPVCSize(claimsToBind)) chosenPVs := map[string]*v1.PersistentVolume{} + foundMatches = true + matchedClaims := []*bindingInfo{} + for _, bindingInfo := range claimsToBind { // Get storage class name from each PVC storageClassName := "" @@ -357,20 +432,72 @@ func (b *volumeBinder) findMatchingVolumes(pod *v1.Pod, claimsToBind []*bindingI // Find a matching PV bindingInfo.pv, err = findMatchingVolume(bindingInfo.pvc, allPVs, node, chosenPVs, true) if err != nil { - return false, err + return false, nil, err } if bindingInfo.pv == nil { - glog.V(4).Infof("No matching volumes for PVC %q on node %q", getPVCName(bindingInfo.pvc), node.Name) - return false, nil + glog.V(4).Infof("No matching volumes for Pod %q, PVC %q on node %q", podName, getPVCName(bindingInfo.pvc), node.Name) + unboundClaims = append(unboundClaims, bindingInfo.pvc) + foundMatches = false + continue } // matching PV needs to be excluded so we don't select it again chosenPVs[bindingInfo.pv.Name] = bindingInfo.pv + matchedClaims = append(matchedClaims, bindingInfo) + glog.V(5).Infof("Found matching PV %q for PVC %q on node %q for pod %q", bindingInfo.pv.Name, getPVCName(bindingInfo.pvc), node.Name, podName) } // Mark cache with all the matches for each PVC for this node - b.podBindingCache.UpdateBindings(pod, node.Name, claimsToBind) - glog.V(4).Infof("Found matching volumes on node %q", node.Name) + if len(matchedClaims) > 0 { + b.podBindingCache.UpdateBindings(pod, node.Name, matchedClaims) + } + + if foundMatches { + glog.V(4).Infof("Found matching volumes for pod %q on node %q", podName, node.Name) + } + + return +} + +// checkVolumeProvisions checks given unbound claims (the claims have gone through func +// findMatchingVolumes, and do not have matching volumes for binding), and return true +// if all of the claims are eligible for dynamic provision. +func (b *volumeBinder) checkVolumeProvisions(pod *v1.Pod, claimsToProvision []*v1.PersistentVolumeClaim, node *v1.Node) (provisionSatisfied bool, err error) { + podName := getPodName(pod) + provisionedClaims := []*v1.PersistentVolumeClaim{} + + for _, claim := range claimsToProvision { + className := v1helper.GetPersistentVolumeClaimClass(claim) + if className == "" { + return false, fmt.Errorf("no class for claim %q", getPVCName(claim)) + } + + class, err := b.ctrl.classLister.Get(className) + if err != nil { + return false, fmt.Errorf("failed to find storage class %q", className) + } + provisioner := class.Provisioner + if provisioner == "" || provisioner == notSupportedProvisioner { + glog.V(4).Infof("storage class %q of claim %q does not support dynamic provisioning", className, getPVCName(claim)) + return false, nil + } + + // Check if the node can satisfy the topology requirement in the class + if !v1helper.MatchTopologySelectorTerms(class.AllowedTopologies, labels.Set(node.Labels)) { + glog.V(4).Infof("Node %q cannot satisfy provisioning topology requirements of claim %q", node.Name, getPVCName(claim)) + return false, nil + } + + // TODO: Check if capacity of the node domain in the storage class + // can satisfy resource requirement of given claim + + provisionedClaims = append(provisionedClaims, claim) + + } + glog.V(4).Infof("Provisioning for claims of pod %q that has no matching volumes on node %q ...", podName, node.Name) + + // Mark cache with all the PVCs that need provisioning for this node + b.podBindingCache.UpdateProvisionedPVCs(pod, node.Name, provisionedClaims) return true, nil } @@ -381,6 +508,12 @@ func (b *volumeBinder) revertAssumedPVs(bindings []*bindingInfo) { } } +func (b *volumeBinder) revertAssumedPVCs(claims []*v1.PersistentVolumeClaim) { + for _, claim := range claims { + b.pvcCache.Restore(getPVCName(claim)) + } +} + type bindingInfo struct { // Claim that needs to be bound pvc *v1.PersistentVolumeClaim diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_cache.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_cache.go index 8a0a77960..c52301179 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_cache.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_cache.go @@ -30,27 +30,41 @@ type PodBindingCache interface { // pod and node. UpdateBindings(pod *v1.Pod, node string, bindings []*bindingInfo) - // DeleteBindings will remove all cached bindings for the given pod. - DeleteBindings(pod *v1.Pod) - // GetBindings will return the cached bindings for the given pod and node. GetBindings(pod *v1.Pod, node string) []*bindingInfo + + // UpdateProvisionedPVCs will update the cache with the given provisioning decisions + // for the pod and node. + UpdateProvisionedPVCs(pod *v1.Pod, node string, provisionings []*v1.PersistentVolumeClaim) + + // GetProvisionedPVCs will return the cached provisioning decisions for the given pod and node. + GetProvisionedPVCs(pod *v1.Pod, node string) []*v1.PersistentVolumeClaim + + // DeleteBindings will remove all cached bindings and provisionings for the given pod. + // TODO: separate the func if it is needed to delete bindings/provisionings individually + DeleteBindings(pod *v1.Pod) } type podBindingCache struct { mutex sync.Mutex // Key = pod name - // Value = nodeBindings - bindings map[string]nodeBindings + // Value = nodeDecisions + bindingDecisions map[string]nodeDecisions } // Key = nodeName -// Value = array of bindingInfo -type nodeBindings map[string][]*bindingInfo +// Value = bindings & provisioned PVCs of the node +type nodeDecisions map[string]nodeDecision + +// A decision includes bindingInfo and provisioned PVCs of the node +type nodeDecision struct { + bindings []*bindingInfo + provisionings []*v1.PersistentVolumeClaim +} func NewPodBindingCache() PodBindingCache { - return &podBindingCache{bindings: map[string]nodeBindings{}} + return &podBindingCache{bindingDecisions: map[string]nodeDecisions{}} } func (c *podBindingCache) DeleteBindings(pod *v1.Pod) { @@ -58,7 +72,7 @@ func (c *podBindingCache) DeleteBindings(pod *v1.Pod) { defer c.mutex.Unlock() podName := getPodName(pod) - delete(c.bindings, podName) + delete(c.bindingDecisions, podName) } func (c *podBindingCache) UpdateBindings(pod *v1.Pod, node string, bindings []*bindingInfo) { @@ -66,12 +80,20 @@ func (c *podBindingCache) UpdateBindings(pod *v1.Pod, node string, bindings []*b defer c.mutex.Unlock() podName := getPodName(pod) - nodeBinding, ok := c.bindings[podName] + decisions, ok := c.bindingDecisions[podName] + if !ok { + decisions = nodeDecisions{} + c.bindingDecisions[podName] = decisions + } + decision, ok := decisions[node] if !ok { - nodeBinding = nodeBindings{} - c.bindings[podName] = nodeBinding + decision = nodeDecision{ + bindings: bindings, + } + } else { + decision.bindings = bindings } - nodeBinding[node] = bindings + decisions[node] = decision } func (c *podBindingCache) GetBindings(pod *v1.Pod, node string) []*bindingInfo { @@ -79,9 +101,50 @@ func (c *podBindingCache) GetBindings(pod *v1.Pod, node string) []*bindingInfo { defer c.mutex.Unlock() podName := getPodName(pod) - nodeBindings, ok := c.bindings[podName] + decisions, ok := c.bindingDecisions[podName] + if !ok { + return nil + } + decision, ok := decisions[node] + if !ok { + return nil + } + return decision.bindings +} + +func (c *podBindingCache) UpdateProvisionedPVCs(pod *v1.Pod, node string, pvcs []*v1.PersistentVolumeClaim) { + c.mutex.Lock() + defer c.mutex.Unlock() + + podName := getPodName(pod) + decisions, ok := c.bindingDecisions[podName] + if !ok { + decisions = nodeDecisions{} + c.bindingDecisions[podName] = decisions + } + decision, ok := decisions[node] + if !ok { + decision = nodeDecision{ + provisionings: pvcs, + } + } else { + decision.provisionings = pvcs + } + decisions[node] = decision +} + +func (c *podBindingCache) GetProvisionedPVCs(pod *v1.Pod, node string) []*v1.PersistentVolumeClaim { + c.mutex.Lock() + defer c.mutex.Unlock() + + podName := getPodName(pod) + decisions, ok := c.bindingDecisions[podName] + if !ok { + return nil + } + decision, ok := decisions[node] if !ok { return nil } - return nodeBindings[node] + return decision.provisionings } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_cache_test.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_cache_test.go index d39d823c2..65086274c 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_cache_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_cache_test.go @@ -26,32 +26,37 @@ import ( func TestUpdateGetBindings(t *testing.T) { scenarios := map[string]struct { - updateBindings []*bindingInfo - updatePod string - updateNode string - - getBindings []*bindingInfo - getPod string - getNode string + updateBindings []*bindingInfo + updateProvisionings []*v1.PersistentVolumeClaim + updatePod string + updateNode string + + getBindings []*bindingInfo + getProvisionings []*v1.PersistentVolumeClaim + getPod string + getNode string }{ "no-pod": { getPod: "pod1", getNode: "node1", }, "no-node": { - updatePod: "pod1", - updateNode: "node1", - updateBindings: []*bindingInfo{}, - getPod: "pod1", - getNode: "node2", + updatePod: "pod1", + updateNode: "node1", + updateBindings: []*bindingInfo{}, + updateProvisionings: []*v1.PersistentVolumeClaim{}, + getPod: "pod1", + getNode: "node2", }, "binding-exists": { - updatePod: "pod1", - updateNode: "node1", - updateBindings: []*bindingInfo{{pvc: &v1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{Name: "pvc1"}}}}, - getPod: "pod1", - getNode: "node1", - getBindings: []*bindingInfo{{pvc: &v1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{Name: "pvc1"}}}}, + updatePod: "pod1", + updateNode: "node1", + updateBindings: []*bindingInfo{{pvc: &v1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{Name: "pvc1"}}}}, + updateProvisionings: []*v1.PersistentVolumeClaim{{ObjectMeta: metav1.ObjectMeta{Name: "pvc2"}}}, + getPod: "pod1", + getNode: "node1", + getBindings: []*bindingInfo{{pvc: &v1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{Name: "pvc1"}}}}, + getProvisionings: []*v1.PersistentVolumeClaim{{ObjectMeta: metav1.ObjectMeta{Name: "pvc2"}}}, }, } @@ -61,6 +66,7 @@ func TestUpdateGetBindings(t *testing.T) { // Perform updates updatePod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: scenario.updatePod, Namespace: "ns"}} cache.UpdateBindings(updatePod, scenario.updateNode, scenario.updateBindings) + cache.UpdateProvisionedPVCs(updatePod, scenario.updateNode, scenario.updateProvisionings) // Verify updated bindings bindings := cache.GetBindings(updatePod, scenario.updateNode) @@ -68,45 +74,71 @@ func TestUpdateGetBindings(t *testing.T) { t.Errorf("Test %v failed: returned bindings after update different. Got %+v, expected %+v", name, bindings, scenario.updateBindings) } + // Verify updated provisionings + provisionings := cache.GetProvisionedPVCs(updatePod, scenario.updateNode) + if !reflect.DeepEqual(provisionings, scenario.updateProvisionings) { + t.Errorf("Test %v failed: returned provisionings after update different. Got %+v, expected %+v", name, provisionings, scenario.updateProvisionings) + } + // Get bindings getPod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: scenario.getPod, Namespace: "ns"}} bindings = cache.GetBindings(getPod, scenario.getNode) if !reflect.DeepEqual(bindings, scenario.getBindings) { t.Errorf("Test %v failed: unexpected bindings returned. Got %+v, expected %+v", name, bindings, scenario.updateBindings) } + + // Get provisionings + provisionings = cache.GetProvisionedPVCs(getPod, scenario.getNode) + if !reflect.DeepEqual(provisionings, scenario.getProvisionings) { + t.Errorf("Test %v failed: unexpected bindings returned. Got %+v, expected %+v", name, provisionings, scenario.getProvisionings) + } } } func TestDeleteBindings(t *testing.T) { initialBindings := []*bindingInfo{{pvc: &v1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{Name: "pvc1"}}}} + initialProvisionings := []*v1.PersistentVolumeClaim{{ObjectMeta: metav1.ObjectMeta{Name: "pvc2"}}} cache := NewPodBindingCache() pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Namespace: "ns"}} - // Get nil bindings + // Get nil bindings and provisionings bindings := cache.GetBindings(pod, "node1") if bindings != nil { t.Errorf("Test failed: expected initial nil bindings, got %+v", bindings) } + provisionings := cache.GetProvisionedPVCs(pod, "node1") + if provisionings != nil { + t.Errorf("Test failed: expected initial nil provisionings, got %+v", provisionings) + } // Delete nothing cache.DeleteBindings(pod) // Perform updates cache.UpdateBindings(pod, "node1", initialBindings) + cache.UpdateProvisionedPVCs(pod, "node1", initialProvisionings) - // Get bindings + // Get bindings and provisionings bindings = cache.GetBindings(pod, "node1") if !reflect.DeepEqual(bindings, initialBindings) { t.Errorf("Test failed: expected bindings %+v, got %+v", initialBindings, bindings) } + provisionings = cache.GetProvisionedPVCs(pod, "node1") + if !reflect.DeepEqual(provisionings, initialProvisionings) { + t.Errorf("Test failed: expected provisionings %+v, got %+v", initialProvisionings, provisionings) + } // Delete cache.DeleteBindings(pod) - // Get bindings + // Get bindings and provisionings bindings = cache.GetBindings(pod, "node1") if bindings != nil { t.Errorf("Test failed: expected nil bindings, got %+v", bindings) } + provisionings = cache.GetProvisionedPVCs(pod, "node1") + if provisionings != nil { + t.Errorf("Test failed: expected nil provisionings, got %+v", provisionings) + } } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_test.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_test.go index 5464607cc..e1e49d0e3 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_test.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/scheduler_binder_test.go @@ -33,24 +33,29 @@ import ( "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" - "k8s.io/client-go/tools/cache" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/controller" ) var ( - unboundPVC = makeTestPVC("unbound-pvc", "1G", pvcUnbound, "", &waitClass) - unboundPVC2 = makeTestPVC("unbound-pvc2", "5G", pvcUnbound, "", &waitClass) - preboundPVC = makeTestPVC("prebound-pvc", "1G", pvcPrebound, "pv-node1a", &waitClass) - boundPVC = makeTestPVC("bound-pvc", "1G", pvcBound, "pv-bound", &waitClass) - boundPVC2 = makeTestPVC("bound-pvc2", "1G", pvcBound, "pv-bound2", &waitClass) - badPVC = makeBadPVC() - immediateUnboundPVC = makeTestPVC("immediate-unbound-pvc", "1G", pvcUnbound, "", &immediateClass) - immediateBoundPVC = makeTestPVC("immediate-bound-pvc", "1G", pvcBound, "pv-bound-immediate", &immediateClass) + unboundPVC = makeTestPVC("unbound-pvc", "1G", pvcUnbound, "", "1", &waitClass) + unboundPVC2 = makeTestPVC("unbound-pvc2", "5G", pvcUnbound, "", "1", &waitClass) + preboundPVC = makeTestPVC("prebound-pvc", "1G", pvcPrebound, "pv-node1a", "1", &waitClass) + boundPVC = makeTestPVC("bound-pvc", "1G", pvcBound, "pv-bound", "1", &waitClass) + boundPVC2 = makeTestPVC("bound-pvc2", "1G", pvcBound, "pv-bound2", "1", &waitClass) + badPVC = makeBadPVC() + immediateUnboundPVC = makeTestPVC("immediate-unbound-pvc", "1G", pvcUnbound, "", "1", &immediateClass) + immediateBoundPVC = makeTestPVC("immediate-bound-pvc", "1G", pvcBound, "pv-bound-immediate", "1", &immediateClass) + provisionedPVC = makeTestPVC("provisioned-pvc", "1Gi", pvcUnbound, "", "1", &waitClass) + provisionedPVC2 = makeTestPVC("provisioned-pvc2", "1Gi", pvcUnbound, "", "1", &waitClass) + provisionedPVCHigherVersion = makeTestPVC("provisioned-pvc2", "1Gi", pvcUnbound, "", "2", &waitClass) + noProvisionerPVC = makeTestPVC("no-provisioner-pvc", "1Gi", pvcUnbound, "", "1", &provisionNotSupportClass) + topoMismatchPVC = makeTestPVC("topo-mismatch-pvc", "1Gi", pvcUnbound, "", "1", &topoMismatchClass) pvNoNode = makeTestPV("pv-no-node", "", "1G", "1", nil, waitClass) pvNode1a = makeTestPV("pv-node1a", "node1", "5G", "1", nil, waitClass) pvNode1b = makeTestPV("pv-node1b", "node1", "10G", "1", nil, waitClass) + pvNode1c = makeTestPV("pv-node1b", "node1", "5G", "1", nil, waitClass) pvNode2 = makeTestPV("pv-node2", "node2", "1G", "1", nil, waitClass) pvPrebound = makeTestPV("pv-prebound", "node1", "1G", "1", unboundPVC, waitClass) pvBound = makeTestPV("pv-bound", "node1", "1G", "1", boundPVC, waitClass) @@ -67,10 +72,13 @@ var ( binding1aBound = makeBinding(unboundPVC, pvNode1aBound) binding1bBound = makeBinding(unboundPVC2, pvNode1bBound) - waitClass = "waitClass" - immediateClass = "immediateClass" + waitClass = "waitClass" + immediateClass = "immediateClass" + provisionNotSupportClass = "provisionNotSupportedClass" + topoMismatchClass = "topoMismatchClass" - nodeLabelKey = "nodeKey" + nodeLabelKey = "nodeKey" + nodeLabelValue = "node1" ) type testEnv struct { @@ -79,7 +87,7 @@ type testEnv struct { binder SchedulerVolumeBinder internalBinder *volumeBinder internalPVCache *pvAssumeCache - internalPVCCache cache.Indexer + internalPVCCache *pvcAssumeCache } func newTestBinder(t *testing.T) *testEnv { @@ -105,6 +113,17 @@ func newTestBinder(t *testing.T) *testEnv { Name: waitClass, }, VolumeBindingMode: &waitMode, + Provisioner: "test-provisioner", + AllowedTopologies: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ + { + Key: nodeLabelKey, + Values: []string{nodeLabelValue, "reference-value"}, + }, + }, + }, + }, }, { ObjectMeta: metav1.ObjectMeta{ @@ -112,6 +131,30 @@ func newTestBinder(t *testing.T) *testEnv { }, VolumeBindingMode: &immediateMode, }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: provisionNotSupportClass, + }, + VolumeBindingMode: &waitMode, + Provisioner: "kubernetes.io/no-provisioner", + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: topoMismatchClass, + }, + VolumeBindingMode: &waitMode, + Provisioner: "test-provisioner", + AllowedTopologies: []v1.TopologySelectorTerm{ + { + MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ + { + Key: nodeLabelKey, + Values: []string{"reference-value"}, + }, + }, + }, + }, + }, } for _, class := range classes { if err := classInformer.Informer().GetIndexer().Add(class); err != nil { @@ -131,22 +174,31 @@ func newTestBinder(t *testing.T) *testEnv { t.Fatalf("Failed to convert to internal PV cache") } + pvcCache := internalBinder.pvcCache + internalPVCCache, ok := pvcCache.(*pvcAssumeCache) + if !ok { + t.Fatalf("Failed to convert to internal PVC cache") + } + return &testEnv{ client: client, reactor: reactor, binder: binder, internalBinder: internalBinder, internalPVCache: internalPVCache, - internalPVCCache: pvcInformer.Informer().GetIndexer(), + internalPVCCache: internalPVCCache, } } -func (env *testEnv) initClaims(t *testing.T, pvcs []*v1.PersistentVolumeClaim) { - for _, pvc := range pvcs { - err := env.internalPVCCache.Add(pvc) - if err != nil { - t.Fatalf("Failed to add PVC %q to internal cache: %v", pvc.Name, err) +func (env *testEnv) initClaims(cachedPVCs []*v1.PersistentVolumeClaim, apiPVCs []*v1.PersistentVolumeClaim) { + internalPVCCache := env.internalPVCCache + for _, pvc := range cachedPVCs { + internalPVCCache.add(pvc) + if apiPVCs == nil { + env.reactor.claims[pvc.Name] = pvc } + } + for _, pvc := range apiPVCs { env.reactor.claims[pvc.Name] = pvc } } @@ -165,7 +217,7 @@ func (env *testEnv) initVolumes(cachedPVs []*v1.PersistentVolume, apiPVs []*v1.P } -func (env *testEnv) assumeVolumes(t *testing.T, name, node string, pod *v1.Pod, bindings []*bindingInfo) { +func (env *testEnv) assumeVolumes(t *testing.T, name, node string, pod *v1.Pod, bindings []*bindingInfo, provisionings []*v1.PersistentVolumeClaim) { pvCache := env.internalBinder.pvCache for _, binding := range bindings { if err := pvCache.Assume(binding.pv); err != nil { @@ -174,23 +226,46 @@ func (env *testEnv) assumeVolumes(t *testing.T, name, node string, pod *v1.Pod, } env.internalBinder.podBindingCache.UpdateBindings(pod, node, bindings) + + pvcCache := env.internalBinder.pvcCache + for _, pvc := range provisionings { + if err := pvcCache.Assume(pvc); err != nil { + t.Fatalf("Failed to setup test %q: error: %v", name, err) + } + } + + env.internalBinder.podBindingCache.UpdateProvisionedPVCs(pod, node, provisionings) } -func (env *testEnv) initPodCache(pod *v1.Pod, node string, bindings []*bindingInfo) { +func (env *testEnv) initPodCache(pod *v1.Pod, node string, bindings []*bindingInfo, provisionings []*v1.PersistentVolumeClaim) { cache := env.internalBinder.podBindingCache cache.UpdateBindings(pod, node, bindings) + + cache.UpdateProvisionedPVCs(pod, node, provisionings) } -func (env *testEnv) validatePodCache(t *testing.T, name, node string, pod *v1.Pod, expectedBindings []*bindingInfo) { +func (env *testEnv) validatePodCache(t *testing.T, name, node string, pod *v1.Pod, expectedBindings []*bindingInfo, expectedProvisionings []*v1.PersistentVolumeClaim) { cache := env.internalBinder.podBindingCache bindings := cache.GetBindings(pod, node) if !reflect.DeepEqual(expectedBindings, bindings) { t.Errorf("Test %q failed: Expected bindings %+v, got %+v", name, expectedBindings, bindings) } + + provisionedClaims := cache.GetProvisionedPVCs(pod, node) + + if !reflect.DeepEqual(expectedProvisionings, provisionedClaims) { + t.Errorf("Test %q failed: Expected provisionings %+v, got %+v", name, expectedProvisionings, provisionedClaims) + } + +} + +func (env *testEnv) getPodBindings(t *testing.T, name, node string, pod *v1.Pod) []*bindingInfo { + cache := env.internalBinder.podBindingCache + return cache.GetBindings(pod, node) } -func (env *testEnv) validateAssume(t *testing.T, name string, pod *v1.Pod, bindings []*bindingInfo) { +func (env *testEnv) validateAssume(t *testing.T, name string, pod *v1.Pod, bindings []*bindingInfo, provisionings []*v1.PersistentVolumeClaim) { // TODO: Check binding cache // Check pv cache @@ -212,9 +287,23 @@ func (env *testEnv) validateAssume(t *testing.T, name string, pod *v1.Pod, bindi t.Errorf("Test %q failed: expected PV.ClaimRef.Namespace %q, got %q", name, b.pvc.Namespace, pv.Spec.ClaimRef.Namespace) } } + + // Check pvc cache + pvcCache := env.internalBinder.pvcCache + for _, p := range provisionings { + pvcKey := getPVCName(p) + pvc, err := pvcCache.GetPVC(pvcKey) + if err != nil { + t.Errorf("Test %q failed: GetPVC %q returned error: %v", name, pvcKey, err) + continue + } + if pvc.Annotations[annSelectedNode] != nodeLabelValue { + t.Errorf("Test %q failed: expected annSelectedNode of pvc %q to be %q, but got %q", name, pvcKey, nodeLabelValue, pvc.Annotations[annSelectedNode]) + } + } } -func (env *testEnv) validateFailedAssume(t *testing.T, name string, pod *v1.Pod, bindings []*bindingInfo) { +func (env *testEnv) validateFailedAssume(t *testing.T, name string, pod *v1.Pod, bindings []*bindingInfo, provisionings []*v1.PersistentVolumeClaim) { // All PVs have been unmodified in cache pvCache := env.internalBinder.pvCache for _, b := range bindings { @@ -224,6 +313,20 @@ func (env *testEnv) validateFailedAssume(t *testing.T, name string, pod *v1.Pod, t.Errorf("Test %q failed: PV %q was modified in cache", name, b.pv.Name) } } + + // Check pvc cache + pvcCache := env.internalBinder.pvcCache + for _, p := range provisionings { + pvcKey := getPVCName(p) + pvc, err := pvcCache.GetPVC(pvcKey) + if err != nil { + t.Errorf("Test %q failed: GetPVC %q returned error: %v", name, pvcKey, err) + continue + } + if pvc.Annotations[annSelectedNode] != "" { + t.Errorf("Test %q failed: expected annSelectedNode of pvc %q empty, but got %q", name, pvcKey, pvc.Annotations[annSelectedNode]) + } + } } func (env *testEnv) validateBind( @@ -251,20 +354,46 @@ func (env *testEnv) validateBind( } } +func (env *testEnv) validateProvision( + t *testing.T, + name string, + pod *v1.Pod, + expectedPVCs []*v1.PersistentVolumeClaim, + expectedAPIPVCs []*v1.PersistentVolumeClaim) { + + // Check pvc cache + pvcCache := env.internalBinder.pvcCache + for _, pvc := range expectedPVCs { + cachedPVC, err := pvcCache.GetPVC(getPVCName(pvc)) + if err != nil { + t.Errorf("Test %q failed: GetPVC %q returned error: %v", name, getPVCName(pvc), err) + } + if !reflect.DeepEqual(cachedPVC, pvc) { + t.Errorf("Test %q failed: cached PVC check failed [A-expected, B-got]:\n%s", name, diff.ObjectDiff(pvc, cachedPVC)) + } + } + + // Check reactor for API updates + if err := env.reactor.checkClaims(expectedAPIPVCs); err != nil { + t.Errorf("Test %q failed: API reactor validation failed: %v", name, err) + } +} + const ( pvcUnbound = iota pvcPrebound pvcBound ) -func makeTestPVC(name, size string, pvcBoundState int, pvName string, className *string) *v1.PersistentVolumeClaim { +func makeTestPVC(name, size string, pvcBoundState int, pvName, resourceVersion string, className *string) *v1.PersistentVolumeClaim { pvc := &v1.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: "testns", UID: types.UID("pvc-uid"), - ResourceVersion: "1", + ResourceVersion: resourceVersion, SelfLink: testapi.Default.SelfLink("pvc", name), + Annotations: map[string]string{}, }, Spec: v1.PersistentVolumeClaimSpec{ Resources: v1.ResourceRequirements{ @@ -383,12 +512,15 @@ func makeBinding(pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) *bindin return &bindingInfo{pvc: pvc, pv: pv} } -func makeStringPtr(str string) *string { - s := fmt.Sprintf("%v", str) - return &s +func addProvisionAnn(pvc *v1.PersistentVolumeClaim) *v1.PersistentVolumeClaim { + res := pvc.DeepCopy() + // Add provision related annotations + res.Annotations[annSelectedNode] = nodeLabelValue + + return res } -func TestFindPodVolumes(t *testing.T) { +func TestFindPodVolumesWithoutProvisioning(t *testing.T) { scenarios := map[string]struct { // Inputs pvs []*v1.PersistentVolume @@ -469,10 +601,11 @@ func TestFindPodVolumes(t *testing.T) { expectedBound: true, }, "two-unbound-pvcs,partial-match": { - podPVCs: []*v1.PersistentVolumeClaim{unboundPVC, unboundPVC2}, - pvs: []*v1.PersistentVolume{pvNode1a}, - expectedUnbound: false, - expectedBound: true, + podPVCs: []*v1.PersistentVolumeClaim{unboundPVC, unboundPVC2}, + pvs: []*v1.PersistentVolume{pvNode1a}, + expectedBindings: []*bindingInfo{binding1a}, + expectedUnbound: false, + expectedBound: true, }, "one-bound,one-unbound": { podPVCs: []*v1.PersistentVolumeClaim{unboundPVC, boundPVC}, @@ -551,7 +684,121 @@ func TestFindPodVolumes(t *testing.T) { if scenario.cachePVCs == nil { scenario.cachePVCs = scenario.podPVCs } - testEnv.initClaims(t, scenario.cachePVCs) + testEnv.initClaims(scenario.cachePVCs, scenario.cachePVCs) + + // b. Generate pod with given claims + if scenario.pod == nil { + scenario.pod = makePod(scenario.podPVCs) + } + + // Execute + unboundSatisfied, boundSatisfied, err := testEnv.binder.FindPodVolumes(scenario.pod, testNode) + + // Validate + if !scenario.shouldFail && err != nil { + t.Errorf("Test %q failed: returned error: %v", name, err) + } + if scenario.shouldFail && err == nil { + t.Errorf("Test %q failed: returned success but expected error", name) + } + if boundSatisfied != scenario.expectedBound { + t.Errorf("Test %q failed: expected boundSatsified %v, got %v", name, scenario.expectedBound, boundSatisfied) + } + if unboundSatisfied != scenario.expectedUnbound { + t.Errorf("Test %q failed: expected unboundSatsified %v, got %v", name, scenario.expectedUnbound, unboundSatisfied) + } + testEnv.validatePodCache(t, name, testNode.Name, scenario.pod, scenario.expectedBindings, nil) + } +} + +func TestFindPodVolumesWithProvisioning(t *testing.T) { + scenarios := map[string]struct { + // Inputs + pvs []*v1.PersistentVolume + podPVCs []*v1.PersistentVolumeClaim + // If nil, use pod PVCs + cachePVCs []*v1.PersistentVolumeClaim + // If nil, makePod with podPVCs + pod *v1.Pod + + // Expected podBindingCache fields + expectedBindings []*bindingInfo + expectedProvisions []*v1.PersistentVolumeClaim + + // Expected return values + expectedUnbound bool + expectedBound bool + shouldFail bool + }{ + "one-provisioned": { + podPVCs: []*v1.PersistentVolumeClaim{provisionedPVC}, + expectedProvisions: []*v1.PersistentVolumeClaim{provisionedPVC}, + expectedUnbound: true, + expectedBound: true, + }, + "two-unbound-pvcs,one-matched,one-provisioned": { + podPVCs: []*v1.PersistentVolumeClaim{unboundPVC, provisionedPVC}, + pvs: []*v1.PersistentVolume{pvNode1a}, + expectedBindings: []*bindingInfo{binding1a}, + expectedProvisions: []*v1.PersistentVolumeClaim{provisionedPVC}, + expectedUnbound: true, + expectedBound: true, + }, + "one-bound,one-provisioned": { + podPVCs: []*v1.PersistentVolumeClaim{boundPVC, provisionedPVC}, + pvs: []*v1.PersistentVolume{pvBound}, + expectedProvisions: []*v1.PersistentVolumeClaim{provisionedPVC}, + expectedUnbound: true, + expectedBound: true, + }, + "immediate-unbound-pvc": { + podPVCs: []*v1.PersistentVolumeClaim{immediateUnboundPVC}, + expectedUnbound: false, + expectedBound: false, + shouldFail: true, + }, + "one-immediate-bound,one-provisioned": { + podPVCs: []*v1.PersistentVolumeClaim{immediateBoundPVC, provisionedPVC}, + pvs: []*v1.PersistentVolume{pvBoundImmediate}, + expectedProvisions: []*v1.PersistentVolumeClaim{provisionedPVC}, + expectedUnbound: true, + expectedBound: true, + }, + "invalid-provisioner": { + podPVCs: []*v1.PersistentVolumeClaim{noProvisionerPVC}, + expectedUnbound: false, + expectedBound: true, + }, + "volume-topology-unsatisfied": { + podPVCs: []*v1.PersistentVolumeClaim{topoMismatchPVC}, + expectedUnbound: false, + expectedBound: true, + }, + } + + // Set VolumeScheduling and DynamicProvisioningScheduling feature gate + utilfeature.DefaultFeatureGate.Set("VolumeScheduling=true,DynamicProvisioningScheduling=true") + defer utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false,DynamicProvisioningScheduling=false") + + testNode := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node1", + Labels: map[string]string{ + nodeLabelKey: "node1", + }, + }, + } + + for name, scenario := range scenarios { + // Setup + testEnv := newTestBinder(t) + testEnv.initVolumes(scenario.pvs, scenario.pvs) + + // a. Init pvc cache + if scenario.cachePVCs == nil { + scenario.cachePVCs = scenario.podPVCs + } + testEnv.initClaims(scenario.cachePVCs, scenario.cachePVCs) // b. Generate pod with given claims if scenario.pod == nil { @@ -574,16 +821,17 @@ func TestFindPodVolumes(t *testing.T) { if unboundSatisfied != scenario.expectedUnbound { t.Errorf("Test %q failed: expected unboundSatsified %v, got %v", name, scenario.expectedUnbound, unboundSatisfied) } - testEnv.validatePodCache(t, name, testNode.Name, scenario.pod, scenario.expectedBindings) + testEnv.validatePodCache(t, name, testNode.Name, scenario.pod, scenario.expectedBindings, scenario.expectedProvisions) } } func TestAssumePodVolumes(t *testing.T) { scenarios := map[string]struct { // Inputs - podPVCs []*v1.PersistentVolumeClaim - pvs []*v1.PersistentVolume - bindings []*bindingInfo + podPVCs []*v1.PersistentVolumeClaim + pvs []*v1.PersistentVolume + bindings []*bindingInfo + provisionedPVCs []*v1.PersistentVolumeClaim // Expected return values shouldFail bool @@ -635,6 +883,21 @@ func TestAssumePodVolumes(t *testing.T) { shouldFail: true, expectedBindingRequired: true, }, + "one-binding, one-pvc-provisioned": { + podPVCs: []*v1.PersistentVolumeClaim{unboundPVC, provisionedPVC}, + bindings: []*bindingInfo{binding1a}, + pvs: []*v1.PersistentVolume{pvNode1a}, + provisionedPVCs: []*v1.PersistentVolumeClaim{provisionedPVC}, + expectedBindingRequired: true, + }, + "one-binding, one-provision-tmpupdate-failed": { + podPVCs: []*v1.PersistentVolumeClaim{unboundPVC, provisionedPVCHigherVersion}, + bindings: []*bindingInfo{binding1a}, + pvs: []*v1.PersistentVolume{pvNode1a}, + provisionedPVCs: []*v1.PersistentVolumeClaim{provisionedPVC2}, + shouldFail: true, + expectedBindingRequired: true, + }, } for name, scenario := range scenarios { @@ -642,9 +905,9 @@ func TestAssumePodVolumes(t *testing.T) { // Setup testEnv := newTestBinder(t) - testEnv.initClaims(t, scenario.podPVCs) + testEnv.initClaims(scenario.podPVCs, scenario.podPVCs) pod := makePod(scenario.podPVCs) - testEnv.initPodCache(pod, "node1", scenario.bindings) + testEnv.initPodCache(pod, "node1", scenario.bindings, scenario.provisionedPVCs) testEnv.initVolumes(scenario.pvs, scenario.pvs) // Execute @@ -667,9 +930,9 @@ func TestAssumePodVolumes(t *testing.T) { scenario.expectedBindings = scenario.bindings } if scenario.shouldFail { - testEnv.validateFailedAssume(t, name, pod, scenario.expectedBindings) + testEnv.validateFailedAssume(t, name, pod, scenario.expectedBindings, scenario.provisionedPVCs) } else { - testEnv.validateAssume(t, name, pod, scenario.expectedBindings) + testEnv.validateAssume(t, name, pod, scenario.expectedBindings, scenario.provisionedPVCs) } } } @@ -682,11 +945,20 @@ func TestBindPodVolumes(t *testing.T) { // if nil, use cachedPVs apiPVs []*v1.PersistentVolume + provisionedPVCs []*v1.PersistentVolumeClaim + cachedPVCs []*v1.PersistentVolumeClaim + // if nil, use cachedPVCs + apiPVCs []*v1.PersistentVolumeClaim + // Expected return values shouldFail bool expectedPVs []*v1.PersistentVolume // if nil, use expectedPVs expectedAPIPVs []*v1.PersistentVolume + + expectedPVCs []*v1.PersistentVolumeClaim + // if nil, use expectedPVCs + expectedAPIPVCs []*v1.PersistentVolumeClaim }{ "all-bound": {}, "not-fully-bound": { @@ -710,6 +982,30 @@ func TestBindPodVolumes(t *testing.T) { expectedAPIPVs: []*v1.PersistentVolume{pvNode1aBound, pvNode1bBoundHigherVersion}, shouldFail: true, }, + "one-provisioned-pvc": { + provisionedPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVC)}, + cachedPVCs: []*v1.PersistentVolumeClaim{provisionedPVC}, + expectedPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVC)}, + }, + "provision-api-update-failed": { + provisionedPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVC), addProvisionAnn(provisionedPVC2)}, + cachedPVCs: []*v1.PersistentVolumeClaim{provisionedPVC, provisionedPVC2}, + apiPVCs: []*v1.PersistentVolumeClaim{provisionedPVC, provisionedPVCHigherVersion}, + expectedPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVC), provisionedPVC2}, + expectedAPIPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVC), provisionedPVCHigherVersion}, + shouldFail: true, + }, + "bingding-succeed, provision-api-update-failed": { + bindings: []*bindingInfo{binding1aBound}, + cachedPVs: []*v1.PersistentVolume{pvNode1a}, + expectedPVs: []*v1.PersistentVolume{pvNode1aBound}, + provisionedPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVC), addProvisionAnn(provisionedPVC2)}, + cachedPVCs: []*v1.PersistentVolumeClaim{provisionedPVC, provisionedPVC2}, + apiPVCs: []*v1.PersistentVolumeClaim{provisionedPVC, provisionedPVCHigherVersion}, + expectedPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVC), provisionedPVC2}, + expectedAPIPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVC), provisionedPVCHigherVersion}, + shouldFail: true, + }, } for name, scenario := range scenarios { glog.V(5).Infof("Running test case %q", name) @@ -720,8 +1016,12 @@ func TestBindPodVolumes(t *testing.T) { if scenario.apiPVs == nil { scenario.apiPVs = scenario.cachedPVs } + if scenario.apiPVCs == nil { + scenario.apiPVCs = scenario.cachedPVCs + } testEnv.initVolumes(scenario.cachedPVs, scenario.apiPVs) - testEnv.assumeVolumes(t, name, "node1", pod, scenario.bindings) + testEnv.initClaims(scenario.cachedPVCs, scenario.apiPVCs) + testEnv.assumeVolumes(t, name, "node1", pod, scenario.bindings, scenario.provisionedPVCs) // Execute err := testEnv.binder.BindPodVolumes(pod) @@ -736,6 +1036,76 @@ func TestBindPodVolumes(t *testing.T) { if scenario.expectedAPIPVs == nil { scenario.expectedAPIPVs = scenario.expectedPVs } + if scenario.expectedAPIPVCs == nil { + scenario.expectedAPIPVCs = scenario.expectedPVCs + } testEnv.validateBind(t, name, pod, scenario.expectedPVs, scenario.expectedAPIPVs) + testEnv.validateProvision(t, name, pod, scenario.expectedPVCs, scenario.expectedAPIPVCs) + } +} + +func TestFindAssumeVolumes(t *testing.T) { + // Set feature gate + utilfeature.DefaultFeatureGate.Set("VolumeScheduling=true") + defer utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false") + + // Test case + podPVCs := []*v1.PersistentVolumeClaim{unboundPVC} + pvs := []*v1.PersistentVolume{pvNode2, pvNode1a, pvNode1c} + + // Setup + testEnv := newTestBinder(t) + testEnv.initVolumes(pvs, pvs) + testEnv.initClaims(podPVCs, podPVCs) + pod := makePod(podPVCs) + + testNode := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node1", + Labels: map[string]string{ + nodeLabelKey: "node1", + }, + }, + } + + // Execute + // 1. Find matching PVs + unboundSatisfied, _, err := testEnv.binder.FindPodVolumes(pod, testNode) + if err != nil { + t.Errorf("Test failed: FindPodVolumes returned error: %v", err) + } + if !unboundSatisfied { + t.Errorf("Test failed: couldn't find PVs for all PVCs") + } + expectedBindings := testEnv.getPodBindings(t, "before-assume", testNode.Name, pod) + + // 2. Assume matches + allBound, bindingRequired, err := testEnv.binder.AssumePodVolumes(pod, testNode.Name) + if err != nil { + t.Errorf("Test failed: AssumePodVolumes returned error: %v", err) + } + if allBound { + t.Errorf("Test failed: detected unbound volumes as bound") + } + if !bindingRequired { + t.Errorf("Test failed: binding not required") + } + testEnv.validateAssume(t, "assume", pod, expectedBindings, nil) + // After assume, claimref should be set on pv + expectedBindings = testEnv.getPodBindings(t, "after-assume", testNode.Name, pod) + + // 3. Find matching PVs again + // This should always return the original chosen pv + // Run this many times in case sorting returns different orders for the two PVs. + t.Logf("Testing FindPodVolumes after Assume") + for i := 0; i < 50; i++ { + unboundSatisfied, _, err := testEnv.binder.FindPodVolumes(pod, testNode) + if err != nil { + t.Errorf("Test failed: FindPodVolumes returned error: %v", err) + } + if !unboundSatisfied { + t.Errorf("Test failed: couldn't find PVs for all PVCs") + } + testEnv.validatePodCache(t, "after-assume", testNode.Name, pod, expectedBindings, nil) } } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/volume_host.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/volume_host.go index 27d45629e..7fa54790c 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/volume_host.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/persistentvolume/volume_host.go @@ -20,9 +20,11 @@ import ( "fmt" "net" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" @@ -41,6 +43,10 @@ func (ctrl *PersistentVolumeController) GetVolumeDevicePluginDir(pluginName stri return "" } +func (ctrl *PersistentVolumeController) GetPodsDir() string { + return "" +} + func (ctrl *PersistentVolumeController) GetPodVolumeDir(podUID types.UID, pluginName string, volumeName string) string { return "" } @@ -89,18 +95,24 @@ func (ctrl *PersistentVolumeController) GetNodeAllocatable() (v1.ResourceList, e return v1.ResourceList{}, nil } -func (adc *PersistentVolumeController) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) { +func (ctrl *PersistentVolumeController) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) { return func(_, _ string) (*v1.Secret, error) { return nil, fmt.Errorf("GetSecret unsupported in PersistentVolumeController") } } -func (adc *PersistentVolumeController) GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error) { +func (ctrl *PersistentVolumeController) GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error) { return func(_, _ string) (*v1.ConfigMap, error) { return nil, fmt.Errorf("GetConfigMap unsupported in PersistentVolumeController") } } +func (ctrl *PersistentVolumeController) GetServiceAccountTokenFunc() func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return func(_, _ string, _ *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return nil, fmt.Errorf("GetServiceAccountToken unsupported in PersistentVolumeController") + } +} + func (adc *PersistentVolumeController) GetExec(pluginName string) mount.Exec { return mount.NewOsExec() } @@ -112,3 +124,7 @@ func (ctrl *PersistentVolumeController) GetNodeLabels() (map[string]string, erro func (ctrl *PersistentVolumeController) GetNodeName() types.NodeName { return "" } + +func (ctrl *PersistentVolumeController) GetEventRecorder() record.EventRecorder { + return ctrl.eventRecorder +} diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/pvcprotection/pvc_protection_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/pvcprotection/pvc_protection_controller.go index 90b178496..8ff28cf64 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/pvcprotection/pvc_protection_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/pvcprotection/pvc_protection_controller.go @@ -54,7 +54,7 @@ type Controller struct { storageObjectInUseProtectionEnabled bool } -// NewPVCProtectionController returns a new *{VCProtectionController. +// NewPVCProtectionController returns a new instance of PVCProtectionController. func NewPVCProtectionController(pvcInformer coreinformers.PersistentVolumeClaimInformer, podInformer coreinformers.PodInformer, cl clientset.Interface, storageObjectInUseProtectionFeatureEnabled bool) *Controller { e := &Controller{ client: cl, @@ -145,7 +145,7 @@ func (c *Controller) processPVC(pvcNamespace, pvcName string) error { glog.V(4).Infof("Processing PVC %s/%s", pvcNamespace, pvcName) startTime := time.Now() defer func() { - glog.V(4).Infof("Finished processing PVC %s/%s (%v)", pvcNamespace, pvcName, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished processing PVC %s/%s (%v)", pvcNamespace, pvcName, time.Since(startTime)) }() pvc, err := c.pvcLister.PersistentVolumeClaims(pvcNamespace).Get(pvcName) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/pvprotection/pv_protection_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/pvprotection/pv_protection_controller.go index 93ce14b1b..2f70a7621 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/volume/pvprotection/pv_protection_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/pvprotection/pv_protection_controller.go @@ -123,7 +123,7 @@ func (c *Controller) processPV(pvName string) error { glog.V(4).Infof("Processing PV %s", pvName) startTime := time.Now() defer func() { - glog.V(4).Infof("Finished processing PV %s (%v)", pvName, time.Now().Sub(startTime)) + glog.V(4).Infof("Finished processing PV %s (%v)", pvName, time.Since(startTime)) }() pv, err := c.pvLister.Get(pvName) diff --git a/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/BUILD b/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/BUILD index a52c99dbc..5d1c3800d 100644 --- a/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/BUILD @@ -16,7 +16,7 @@ go_library( deps = [ "//pkg/cloudprovider/providers/azure/auth:go_default_library", "//pkg/credentialprovider:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/containerregistry:go_default_library", + "//vendor/github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry:go_default_library", "//vendor/github.com/Azure/go-autorest/autorest:go_default_library", "//vendor/github.com/Azure/go-autorest/autorest/adal:go_default_library", "//vendor/github.com/Azure/go-autorest/autorest/azure:go_default_library", @@ -32,7 +32,7 @@ go_test( srcs = ["azure_credentials_test.go"], embed = [":go_default_library"], deps = [ - "//vendor/github.com/Azure/azure-sdk-for-go/arm/containerregistry:go_default_library", + "//vendor/github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry:go_default_library", "//vendor/github.com/Azure/go-autorest/autorest/to:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/azure_credentials.go b/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/azure_credentials.go index 486128dc0..ffeab5ea5 100644 --- a/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/azure_credentials.go +++ b/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/azure_credentials.go @@ -17,18 +17,20 @@ limitations under the License. package azure import ( + "context" "io" "io/ioutil" "os" "time" - "github.com/Azure/azure-sdk-for-go/arm/containerregistry" + "github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry" "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/adal" "github.com/Azure/go-autorest/autorest/azure" "github.com/ghodss/yaml" "github.com/golang/glog" "github.com/spf13/pflag" + "k8s.io/kubernetes/pkg/cloudprovider/providers/azure/auth" "k8s.io/kubernetes/pkg/credentialprovider" ) @@ -38,6 +40,8 @@ var flagConfigFile = pflag.String("azure-container-registry-config", "", const dummyRegistryEmail = "name@contoso.com" +var containerRegistryUrls = []string{"*.azurecr.io", "*.azurecr.cn", "*.azurecr.de", "*.azurecr.us"} + // init registers the various means by which credentials may // be resolved on Azure. func init() { @@ -48,9 +52,46 @@ func init() { }) } +func getContextWithCancel() (context.Context, context.CancelFunc) { + return context.WithCancel(context.Background()) +} + // RegistriesClient is a testable interface for the ACR client List operation. type RegistriesClient interface { - List() (containerregistry.RegistryListResult, error) + List(ctx context.Context) ([]containerregistry.Registry, error) +} + +// azRegistriesClient implements RegistriesClient. +type azRegistriesClient struct { + client containerregistry.RegistriesClient +} + +func newAzRegistriesClient(subscriptionID, endpoint string, token *adal.ServicePrincipalToken) *azRegistriesClient { + registryClient := containerregistry.NewRegistriesClient(subscriptionID) + registryClient.BaseURI = endpoint + registryClient.Authorizer = autorest.NewBearerAuthorizer(token) + + return &azRegistriesClient{ + client: registryClient, + } +} + +func (az *azRegistriesClient) List(ctx context.Context) ([]containerregistry.Registry, error) { + iterator, err := az.client.ListComplete(ctx) + if err != nil { + return nil, err + } + + result := make([]containerregistry.Registry, 0) + for ; iterator.NotDone(); err = iterator.Next() { + if err != nil { + return nil, err + } + + result = append(result, iterator.Value()) + } + + return result, nil } // NewACRProvider parses the specified configFile and returns a DockerConfigProvider @@ -128,42 +169,42 @@ func (a *acrProvider) Enabled() bool { return false } - registryClient := containerregistry.NewRegistriesClient(a.config.SubscriptionID) - registryClient.BaseURI = a.environment.ResourceManagerEndpoint - registryClient.Authorizer = autorest.NewBearerAuthorizer(a.servicePrincipalToken) - a.registryClient = registryClient - + a.registryClient = newAzRegistriesClient(a.config.SubscriptionID, a.environment.ResourceManagerEndpoint, a.servicePrincipalToken) return true } func (a *acrProvider) Provide() credentialprovider.DockerConfig { cfg := credentialprovider.DockerConfig{} + ctx, cancel := getContextWithCancel() + defer cancel() + + if a.config.UseManagedIdentityExtension { + glog.V(4).Infof("listing registries") + result, err := a.registryClient.List(ctx) + if err != nil { + glog.Errorf("Failed to list registries: %v", err) + return cfg + } - glog.V(4).Infof("listing registries") - res, err := a.registryClient.List() - if err != nil { - glog.Errorf("Failed to list registries: %v", err) - return cfg - } - - for ix := range *res.Value { - loginServer := getLoginServer((*res.Value)[ix]) - var cred *credentialprovider.DockerConfigEntry - - if a.config.UseManagedIdentityExtension { - cred, err = getACRDockerEntryFromARMToken(a, loginServer) + for ix := range result { + loginServer := getLoginServer(result[ix]) + glog.V(2).Infof("loginServer: %s", loginServer) + cred, err := getACRDockerEntryFromARMToken(a, loginServer) if err != nil { continue } - } else { - cred = &credentialprovider.DockerConfigEntry{ + cfg[loginServer] = *cred + } + } else { + // Add our entry for each of the supported container registry URLs + for _, url := range containerRegistryUrls { + cred := &credentialprovider.DockerConfigEntry{ Username: a.config.AADClientID, Password: a.config.AADClientSecret, Email: dummyRegistryEmail, } + cfg[url] = *cred } - - cfg[loginServer] = *cred } return cfg } diff --git a/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/azure_credentials_test.go b/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/azure_credentials_test.go index 9d966fe6b..d0201f0a4 100644 --- a/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/azure_credentials_test.go +++ b/vendor/k8s.io/kubernetes/pkg/credentialprovider/azure/azure_credentials_test.go @@ -18,17 +18,18 @@ package azure import ( "bytes" + "context" "testing" - "github.com/Azure/azure-sdk-for-go/arm/containerregistry" + "github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry" "github.com/Azure/go-autorest/autorest/to" ) type fakeClient struct { - results containerregistry.RegistryListResult + results []containerregistry.Registry } -func (f *fakeClient) List() (containerregistry.RegistryListResult, error) { +func (f *fakeClient) List(ctx context.Context) ([]containerregistry.Registry, error) { return f.results, nil } @@ -38,25 +39,29 @@ func Test(t *testing.T) { "aadClientId": "foo", "aadClientSecret": "bar" }` - result := containerregistry.RegistryListResult{ - Value: &[]containerregistry.Registry{ - { - Name: to.StringPtr("foo"), - RegistryProperties: &containerregistry.RegistryProperties{ - LoginServer: to.StringPtr("foo-microsoft.azurecr.io"), - }, + result := []containerregistry.Registry{ + { + Name: to.StringPtr("foo"), + RegistryProperties: &containerregistry.RegistryProperties{ + LoginServer: to.StringPtr("*.azurecr.io"), }, - { - Name: to.StringPtr("bar"), - RegistryProperties: &containerregistry.RegistryProperties{ - LoginServer: to.StringPtr("bar-microsoft.azurecr.io"), - }, + }, + { + Name: to.StringPtr("bar"), + RegistryProperties: &containerregistry.RegistryProperties{ + LoginServer: to.StringPtr("*.azurecr.cn"), + }, + }, + { + Name: to.StringPtr("baz"), + RegistryProperties: &containerregistry.RegistryProperties{ + LoginServer: to.StringPtr("*.azurecr.de"), }, - { - Name: to.StringPtr("baz"), - RegistryProperties: &containerregistry.RegistryProperties{ - LoginServer: to.StringPtr("baz-microsoft.azurecr.io"), - }, + }, + { + Name: to.StringPtr("bus"), + RegistryProperties: &containerregistry.RegistryProperties{ + LoginServer: to.StringPtr("*.azurecr.us"), }, }, } @@ -71,8 +76,8 @@ func Test(t *testing.T) { creds := provider.Provide() - if len(creds) != len(*result.Value) { - t.Errorf("Unexpected list: %v, expected length %d", creds, len(*result.Value)) + if len(creds) != len(result) { + t.Errorf("Unexpected list: %v, expected length %d", creds, len(result)) } for _, cred := range creds { if cred.Username != "foo" { @@ -82,7 +87,7 @@ func Test(t *testing.T) { t.Errorf("expected 'bar' for password, saw: %v", cred.Username) } } - for _, val := range *result.Value { + for _, val := range result { registryName := getLoginServer(val) if _, found := creds[registryName]; !found { t.Errorf("Missing expected registry: %s", registryName) diff --git a/vendor/k8s.io/kubernetes/pkg/features/OWNERS b/vendor/k8s.io/kubernetes/pkg/features/OWNERS new file mode 100644 index 000000000..fe7b0144e --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/features/OWNERS @@ -0,0 +1,2 @@ +approvers: +- feature-approvers diff --git a/vendor/k8s.io/kubernetes/pkg/features/kube_features.go b/vendor/k8s.io/kubernetes/pkg/features/kube_features.go index dd8f24c28..855ede106 100644 --- a/vendor/k8s.io/kubernetes/pkg/features/kube_features.go +++ b/vendor/k8s.io/kubernetes/pkg/features/kube_features.go @@ -35,6 +35,7 @@ const ( // owner: @mtaufen // alpha: v1.4 + // beta: v1.11 DynamicKubeletConfig utilfeature.Feature = "DynamicKubeletConfig" // owner: @pweil- @@ -53,16 +54,6 @@ const ( // Note: This feature is not supported for `BestEffort` pods. ExperimentalCriticalPodAnnotation utilfeature.Feature = "ExperimentalCriticalPodAnnotation" - // owner: @vishh - // alpha: v1.6 - // - // This is deprecated and will be removed in v1.11. Use DevicePlugins instead. - // - // Enables support for GPUs as a schedulable resource. - // Only Nvidia GPUs are supported as of v1.6. - // Works only with Docker Container Runtime. - Accelerators utilfeature.Feature = "Accelerators" - // owner: @jiayingz // beta: v1.10 // @@ -76,7 +67,7 @@ const ( // to take advantage of NoExecute Taints and Tolerations. TaintBasedEvictions utilfeature.Feature = "TaintBasedEvictions" - // owner: @jcbsmpsn + // owner: @mikedanese // alpha: v1.7 // // Gets a server certificate for the kubelet from the Certificate Signing @@ -84,8 +75,8 @@ const ( // certificate as expiration approaches. RotateKubeletServerCertificate utilfeature.Feature = "RotateKubeletServerCertificate" - // owner: @jcbsmpsn - // alpha: v1.7 + // owner: @mikedanese + // beta: v1.8 // // Automatically renews the client certificate used for communicating with // the API server as the certificate approaches expiration. @@ -104,10 +95,15 @@ const ( LocalStorageCapacityIsolation utilfeature.Feature = "LocalStorageCapacityIsolation" // owner: @gnufied - // alpha: v1.8 + // beta: v1.11 // Ability to Expand persistent volumes ExpandPersistentVolumes utilfeature.Feature = "ExpandPersistentVolumes" + // owner: @mlmhl + // alpha: v1.11 + // Ability to expand persistent volumes' file system without unmounting volumes. + ExpandInUsePersistentVolumes utilfeature.Feature = "ExpandInUsePersistentVolumes" + // owner: @verb // alpha: v1.10 // @@ -145,6 +141,13 @@ const ( // Enable mount propagation of volumes. MountPropagation utilfeature.Feature = "MountPropagation" + // owner: @sjenning + // alpha: v1.11 + // + // Allows resource reservations at the QoS level preventing pods at lower QoS levels from + // bursting into resources requested at higher QoS levels (memory only for now) + QOSReserved utilfeature.Feature = "QOSReserved" + // owner: @ConnorDoyle // alpha: v1.8 // @@ -157,6 +160,12 @@ const ( // Enable pods to consume pre-allocated huge pages of varying page sizes HugePages utilfeature.Feature = "HugePages" + // owner: @sjenning + // beta: v1.11 + // + // Enable pods to set sysctls on a pod + Sysctls utilfeature.Feature = "Sysctls" + // owner @brendandburns // alpha: v1.9 // @@ -202,7 +211,7 @@ const ( BlockVolume utilfeature.Feature = "BlockVolume" // owner: @pospispa - // beta: v1.10 + // GA: v1.11 // // Postpone deletion of a PV or a PVC when they are being used StorageObjectInUseProtection utilfeature.Feature = "StorageObjectInUseProtection" @@ -214,7 +223,7 @@ const ( ResourceLimitsPriorityFunction utilfeature.Feature = "ResourceLimitsPriorityFunction" // owner: @m1093782566 - // beta: v1.9 + // GA: v1.11 // // Implement IPVS-based in-cluster service load balancing SupportIPVSProxyMode utilfeature.Feature = "SupportIPVSProxyMode" @@ -250,8 +259,14 @@ const ( // Implement TokenRequest endpoint on service account resources. TokenRequest utilfeature.Feature = "TokenRequest" + // owner: @mikedanese + // alpha: v1.11 + // + // Enable ServiceAccountTokenVolumeProjection support in ProjectedVolumes. + TokenRequestProjection utilfeature.Feature = "TokenRequestProjection" + // owner: @Random-Liu - // alpha: v1.10 + // beta: v1.11 // // Enable container log rotation for cri container runtime CRIContainerLogRotation utilfeature.Feature = "CRIContainerLogRotation" @@ -274,6 +289,60 @@ const ( // Allow mounting a subpath of a volume in a container // Do not remove this feature gate even though it's GA VolumeSubpath utilfeature.Feature = "VolumeSubpath" + + // owner: @gnufied + // alpha : v1.11 + // + // Add support for volume plugins to report node specific + // volume limits + AttachVolumeLimit utilfeature.Feature = "AttachVolumeLimit" + + // owner: @ravig + // alpha: v1.11 + // + // Include volume count on node to be considered for balanced resource allocation while scheduling. + // A node which has closer cpu,memory utilization and volume count is favoured by scheduler + // while making decisions. + BalanceAttachedNodeVolumes utilfeature.Feature = "BalanceAttachedNodeVolumes" + + // owner @freehan + // beta: v1.11 + // + // Support Pod Ready++ + PodReadinessGates utilfeature.Feature = "PodReadinessGates" + + // owner: @lichuqiang + // alpha: v1.11 + // + // Extend the default scheduler to be aware of volume topology and handle PV provisioning + DynamicProvisioningScheduling utilfeature.Feature = "DynamicProvisioningScheduling" + + // owner: @kevtaylor + // alpha: v1.11 + // + // Allow subpath environment variable substitution + // Only applicable if the VolumeSubpath feature is also enabled + VolumeSubpathEnvExpansion utilfeature.Feature = "VolumeSubpathEnvExpansion" + + // owner: @vikaschoudhary16 + // alpha: v1.11 + // + // + // Enable probe based plugin watcher utility for discovering Kubelet plugins + KubeletPluginsWatcher utilfeature.Feature = "KubeletPluginsWatcher" + + // owner: @vikaschoudhary16 + // alpha: v1.11 + // + // + // Enable resource quota scope selectors + ResourceQuotaScopeSelectors utilfeature.Feature = "ResourceQuotaScopeSelectors" + + // owner: @vladimirvivien + // alpha: v1.11 + // + // Enables CSI to use raw block storage volumes + CSIBlockVolume utilfeature.Feature = "CSIBlockVolume" ) func init() { @@ -285,10 +354,9 @@ func init() { // available throughout Kubernetes binaries. var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureSpec{ AppArmor: {Default: true, PreRelease: utilfeature.Beta}, - DynamicKubeletConfig: {Default: false, PreRelease: utilfeature.Alpha}, + DynamicKubeletConfig: {Default: true, PreRelease: utilfeature.Beta}, ExperimentalHostUserNamespaceDefaultingGate: {Default: false, PreRelease: utilfeature.Beta}, ExperimentalCriticalPodAnnotation: {Default: false, PreRelease: utilfeature.Alpha}, - Accelerators: {Default: false, PreRelease: utilfeature.Alpha}, DevicePlugins: {Default: true, PreRelease: utilfeature.Beta}, TaintBasedEvictions: {Default: false, PreRelease: utilfeature.Alpha}, RotateKubeletServerCertificate: {Default: false, PreRelease: utilfeature.Alpha}, @@ -296,13 +364,17 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS PersistentLocalVolumes: {Default: true, PreRelease: utilfeature.Beta}, LocalStorageCapacityIsolation: {Default: true, PreRelease: utilfeature.Beta}, HugePages: {Default: true, PreRelease: utilfeature.Beta}, + Sysctls: {Default: true, PreRelease: utilfeature.Beta}, DebugContainers: {Default: false, PreRelease: utilfeature.Alpha}, PodShareProcessNamespace: {Default: false, PreRelease: utilfeature.Alpha}, - PodPriority: {Default: false, PreRelease: utilfeature.Alpha}, + PodPriority: {Default: true, PreRelease: utilfeature.Beta}, EnableEquivalenceClassCache: {Default: false, PreRelease: utilfeature.Alpha}, TaintNodesByCondition: {Default: false, PreRelease: utilfeature.Alpha}, MountPropagation: {Default: true, PreRelease: utilfeature.Beta}, - ExpandPersistentVolumes: {Default: false, PreRelease: utilfeature.Alpha}, + QOSReserved: {Default: false, PreRelease: utilfeature.Alpha}, + ExpandPersistentVolumes: {Default: true, PreRelease: utilfeature.Beta}, + ExpandInUsePersistentVolumes: {Default: false, PreRelease: utilfeature.Alpha}, + AttachVolumeLimit: {Default: false, PreRelease: utilfeature.Alpha}, CPUManager: {Default: true, PreRelease: utilfeature.Beta}, ServiceNodeExclusion: {Default: false, PreRelease: utilfeature.Alpha}, MountContainers: {Default: false, PreRelease: utilfeature.Alpha}, @@ -310,17 +382,25 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS CSIPersistentVolume: {Default: true, PreRelease: utilfeature.Beta}, CustomPodDNS: {Default: true, PreRelease: utilfeature.Beta}, BlockVolume: {Default: false, PreRelease: utilfeature.Alpha}, - StorageObjectInUseProtection: {Default: true, PreRelease: utilfeature.Beta}, + StorageObjectInUseProtection: {Default: true, PreRelease: utilfeature.GA}, ResourceLimitsPriorityFunction: {Default: false, PreRelease: utilfeature.Alpha}, - SupportIPVSProxyMode: {Default: true, PreRelease: utilfeature.Beta}, + SupportIPVSProxyMode: {Default: true, PreRelease: utilfeature.GA}, SupportPodPidsLimit: {Default: false, PreRelease: utilfeature.Alpha}, HyperVContainer: {Default: false, PreRelease: utilfeature.Alpha}, ScheduleDaemonSetPods: {Default: false, PreRelease: utilfeature.Alpha}, TokenRequest: {Default: false, PreRelease: utilfeature.Alpha}, - CRIContainerLogRotation: {Default: false, PreRelease: utilfeature.Alpha}, + TokenRequestProjection: {Default: false, PreRelease: utilfeature.Alpha}, + CRIContainerLogRotation: {Default: true, PreRelease: utilfeature.Beta}, GCERegionalPersistentDisk: {Default: true, PreRelease: utilfeature.Beta}, RunAsGroup: {Default: false, PreRelease: utilfeature.Alpha}, VolumeSubpath: {Default: true, PreRelease: utilfeature.GA}, + BalanceAttachedNodeVolumes: {Default: false, PreRelease: utilfeature.Alpha}, + DynamicProvisioningScheduling: {Default: false, PreRelease: utilfeature.Alpha}, + PodReadinessGates: {Default: false, PreRelease: utilfeature.Beta}, + VolumeSubpathEnvExpansion: {Default: false, PreRelease: utilfeature.Alpha}, + KubeletPluginsWatcher: {Default: false, PreRelease: utilfeature.Alpha}, + ResourceQuotaScopeSelectors: {Default: false, PreRelease: utilfeature.Alpha}, + CSIBlockVolume: {Default: false, PreRelease: utilfeature.Alpha}, // inherited features from generic apiserver, relisted here to get a conflict if it is changed // unintentionally on either side: @@ -333,7 +413,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS // inherited features from apiextensions-apiserver, relisted here to get a conflict if it is changed // unintentionally on either side: apiextensionsfeatures.CustomResourceValidation: {Default: true, PreRelease: utilfeature.Beta}, - apiextensionsfeatures.CustomResourceSubresources: {Default: false, PreRelease: utilfeature.Alpha}, + apiextensionsfeatures.CustomResourceSubresources: {Default: true, PreRelease: utilfeature.Beta}, // features that enable backwards compatibility but are scheduled to be removed ServiceProxyAllowExternalIPs: {Default: false, PreRelease: utilfeature.Deprecated}, diff --git a/vendor/k8s.io/kubernetes/pkg/fieldpath/BUILD b/vendor/k8s.io/kubernetes/pkg/fieldpath/BUILD index b3cde577f..859d5b388 100644 --- a/vendor/k8s.io/kubernetes/pkg/fieldpath/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/fieldpath/BUILD @@ -15,6 +15,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/fieldpath", deps = [ "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/fieldpath/fieldpath.go b/vendor/k8s.io/kubernetes/pkg/fieldpath/fieldpath.go index 437541458..b997751ec 100644 --- a/vendor/k8s.io/kubernetes/pkg/fieldpath/fieldpath.go +++ b/vendor/k8s.io/kubernetes/pkg/fieldpath/fieldpath.go @@ -21,13 +21,19 @@ import ( "strings" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" ) // FormatMap formats map[string]string to a string. func FormatMap(m map[string]string) (fmtStr string) { - for key, value := range m { - fmtStr += fmt.Sprintf("%v=%q\n", key, value) + // output with keys in sorted order to provide stable output + keys := sets.NewString() + for key := range m { + keys.Insert(key) + } + for _, key := range keys.List() { + fmtStr += fmt.Sprintf("%v=%q\n", key, m[key]) } fmtStr = strings.TrimSuffix(fmtStr, "\n") diff --git a/vendor/k8s.io/kubernetes/pkg/generated/BUILD b/vendor/k8s.io/kubernetes/pkg/generated/BUILD index a5ffe28c1..35ecbd7de 100644 --- a/vendor/k8s.io/kubernetes/pkg/generated/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/generated/BUILD @@ -4,6 +4,18 @@ load( "@io_bazel_rules_go//go:def.bzl", "go_library", ) +load("//build:bindata.bzl", "go_bindata") + +# IMPORTANT: if you make any changes here, you must also update hack/generate-bindata.sh. +go_bindata( + name = "bindata", + srcs = [ + "//translations:all-srcs", + ], + outs = ["bindata.go"], + compress = False, + include_metadata = False, +) go_library( name = "go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/generated/bindata.go b/vendor/k8s.io/kubernetes/pkg/generated/bindata.go index 2ec40346b..cd88df9df 100644 --- a/vendor/k8s.io/kubernetes/pkg/generated/bindata.go +++ b/vendor/k8s.io/kubernetes/pkg/generated/bindata.go @@ -15,6 +15,8 @@ // translations/kubectl/it_IT/LC_MESSAGES/k8s.po // translations/kubectl/ja_JP/LC_MESSAGES/k8s.mo // translations/kubectl/ja_JP/LC_MESSAGES/k8s.po +// translations/kubectl/ko_KR/LC_MESSAGES/k8s.mo +// translations/kubectl/ko_KR/LC_MESSAGES/k8s.po // translations/kubectl/template.pot // translations/kubectl/zh_CN/LC_MESSAGES/k8s.mo // translations/kubectl/zh_CN/LC_MESSAGES/k8s.po @@ -13651,7 +13653,7 @@ msgstr "Imposta il current-context in un file kubeconfig" #: pkg/kubectl/cmd/describe.go:86 msgid "Show details of a specific resource or group of resources" -msgstr "Mostra i dettagli di una specifiche risorsa o un gruppo di risorse" +msgstr "Mostra i dettagli di una specifica risorsa o un gruppo di risorse" #: pkg/kubectl/cmd/rollout/rollout_status.go:58 msgid "Show the status of the rollout" @@ -14018,6 +14020,129 @@ func translationsKubectlJa_jpLc_messagesK8sPo() (*asset, error) { return a, nil } +var _translationsKubectlKo_krLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\x11\x00\x00\x00\x1c\x00\x00\x00\xa4\x00\x00\x00\x17\x00\x00\x00,\x01\x00\x00\x00\x00\x00\x00\x88\x01\x00\x008\x00\x00\x00\x89\x01\x00\x000\x00\x00\x00\xc2\x01\x00\x000\x00\x00\x00\xf3\x01\x00\x00\x1d\x00\x00\x00$\x02\x00\x00*\x00\x00\x00B\x02\x00\x00A\x00\x00\x00m\x02\x00\x00\x1c\x00\x00\x00\xaf\x02\x00\x00\x17\x00\x00\x00\xcc\x02\x00\x00\"\x00\x00\x00\xe4\x02\x00\x00\"\x00\x00\x00\a\x03\x00\x00\x1f\x00\x00\x00*\x03\x00\x00-\x00\x00\x00J\x03\x00\x00-\x00\x00\x00x\x03\x00\x00/\x00\x00\x00\xa6\x03\x00\x00$\x00\x00\x00\xd6\x03\x00\x00\xc5\x00\x00\x00\xfb\x03\x00\x00\x9f\x01\x00\x00\xc1\x04\x00\x00H\x00\x00\x00a\x06\x00\x00:\x00\x00\x00\xaa\x06\x00\x00:\x00\x00\x00\xe5\x06\x00\x004\x00\x00\x00 \a\x00\x007\x00\x00\x00U\a\x00\x00Q\x00\x00\x00\x8d\a\x00\x00&\x00\x00\x00\xdf\a\x00\x00$\x00\x00\x00\x06\b\x00\x007\x00\x00\x00+\b\x00\x007\x00\x00\x00c\b\x00\x004\x00\x00\x00\x9b\b\x00\x004\x00\x00\x00\xd0\b\x00\x00>\x00\x00\x00\x05\t\x00\x00;\x00\x00\x00D\t\x00\x000\x00\x00\x00\x80\t\x00\x00l\x00\x00\x00\xb1\t\x00\x00\x01\x00\x00\x00\n\x00\x00\x00\v\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\t\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\f\x00\x00\x00\x05\x00\x00\x00\r\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00Apply a configuration to a resource by filename or stdin\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Describe one or many contexts\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Displays the current-context\x00Modify kubeconfig files\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Unsets an individual value in a kubeconfig file\x00Update the annotations on a resource\x00watch is only supported on individual resources and resource collections - %d resources were found\x00watch is only supported on individual resources and resource collections - %d resources were found\x00Project-Id-Version: gettext-go-examples-hello\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2013-12-12 20:03+0000\nPO-Revision-Date: 2018-04-03 06:05+0900\nLast-Translator: Ian Y. Choi \nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 2.0.6\nX-Poedit-SourceCharset: UTF-8\nLanguage-Team: \nPlural-Forms: nplurals=1; plural=0;\nLanguage: ko_KR\n\x00\uad6c\uc131\uc744 \ud30c\uc77c \uc774\ub984 \ub610\ub294 stdin\uc5d0 \uc758\ud55c \uc790\uc6d0\uc5d0 \uc801\uc6a9\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \uc9c0\uc815\ub41c \ud074\ub7ec\uc2a4\ud130\ub97c \uc0ad\uc81c\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \uc9c0\uc815\ub41c \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc0ad\uc81c\ud569\ub2c8\ub2e4\x00\ud558\ub098 \ub610\ub294 \uc5ec\ub7ec \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc124\uba85\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0 \uc815\uc758\ub41c \ud074\ub7ec\uc2a4\ud130\ub97c \ud45c\uc2dc\ud569\ub2c8\ub2e4\x00\ubcd1\ud569\ub41c kubeconfig \uc124\uc815 \ub610\ub294 \uc9c0\uc815\ub41c kubeconfig \ud30c\uc77c\uc744 \ud45c\uc2dc\ud569\ub2c8\ub2e4\x00\ud604\uc7ac-\ucee8\ud14d\uc2a4\ud2b8\ub97c \ud45c\uc2dc\ud569\ub2c8\ub2e4\x00kubeconfig \ud30c\uc77c\uc744 \uc218\uc815\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \ud074\ub7ec\uc2a4\ud130 \ud56d\ubaa9\uc744 \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \ucee8\ud14d\uc2a4\ud2b8 \ud56d\ubaa9\uc744 \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \uc0ac\uc6a9\uc790 \ud56d\ubaa9\uc744 \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig \ud30c\uc77c\uc5d0\uc11c \ub2e8\uc77c\uac12\uc744 \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig \ud30c\uc77c\uc5d0\uc11c \ud604\uc7ac-\ucee8\ud14d\uc2a4\ud2b8\ub97c \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig \ud30c\uc77c\uc5d0\uc11c \ub2e8\uc77c\uac12 \uc124\uc815\uc744 \ud574\uc81c\ud569\ub2c8\ub2e4\x00\uc790\uc6d0\uc5d0 \ub300\ud55c \uc8fc\uc11d\uc744 \uc5c5\ub370\uc774\ud2b8\ud569\ub2c8\ub2e4\x00watch\ub294 \ub2e8\uc77c \ub9ac\uc18c\uc2a4\uc640 \ub9ac\uc18c\uc2a4 \ubaa8\uc74c\ub9cc\uc744 \uc9c0\uc6d0\ud569\ub2c8\ub2e4 - %d \uac1c \uc790\uc6d0\uc744 \ubc1c\uacac\ud558\uc600\uc2b5\ub2c8\ub2e4\x00") + +func translationsKubectlKo_krLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlKo_krLc_messagesK8sMo, nil +} + +func translationsKubectlKo_krLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlKo_krLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/ko_KR/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlKo_krLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2017 +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR ianyrchoi@gmail.com, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-12 20:03+0000\n" +"PO-Revision-Date: 2018-04-03 06:05+0900\n" +"Last-Translator: Ian Y. Choi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.6\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Language-Team: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Language: ko_KR\n" + +# https://github.com/kubernetes/kubernetes/blob/masterpkg/kubectl/cmd/apply.go#L98 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "구성을 파일 이름 또는 stdin에 의한 자원에 적용합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_cluster.go#L38 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "kubeconfig에서 지정된 클러스터를 삭제합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_context.go#L38 +msgid "Delete the specified context from the kubeconfig" +msgstr "kubeconfig에서 지정된 컨텍스트를 삭제합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62 +msgid "Describe one or many contexts" +msgstr "하나 또는 여러 컨텍스트를 설명합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40 +msgid "Display clusters defined in the kubeconfig" +msgstr "kubeconfig에 정의된 클러스터를 표시합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "병합된 kubeconfig 설정 또는 지정된 kubeconfig 파일을 표시합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48 +msgid "Displays the current-context" +msgstr "현재-컨텍스트를 표시합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39 +msgid "Modify kubeconfig files" +msgstr "kubeconfig 파일을 수정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67 +msgid "Sets a cluster entry in kubeconfig" +msgstr "kubeconfig에서 클러스터 항목을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57 +msgid "Sets a context entry in kubeconfig" +msgstr "kubeconfig에서 컨텍스트 항목을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103 +msgid "Sets a user entry in kubeconfig" +msgstr "kubeconfig에서 사용자 항목을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/set.go#L59 +msgid "Sets an individual value in a kubeconfig file" +msgstr "kubeconfig 파일에서 단일값을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48 +msgid "Sets the current-context in a kubeconfig file" +msgstr "kubeconfig 파일에서 현재-컨텍스트를 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/unset.go#L47 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "kubeconfig 파일에서 단일값 설정을 해제합니다" + +msgid "Update the annotations on a resource" +msgstr "자원에 대한 주석을 업데이트합니다" + +msgid "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgid_plural "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgstr[0] "" +"watch는 단일 리소스와 리소스 모음만을 지원합니다 - %d 개 자원을 발견하였습" +"니다" +`) + +func translationsKubectlKo_krLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlKo_krLc_messagesK8sPo, nil +} + +func translationsKubectlKo_krLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlKo_krLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/ko_KR/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + var _translationsKubectlTemplatePot = []byte(`# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. @@ -16241,7 +16366,7 @@ msgid "" "\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" msgstr "" "\n" -"\t\t # 如果你还没有一个 .dockercfg 文件, 你可以创建一个 dockercfg 的 secret 直接使用:\n" +"\t\t # 如果你还没有一个 .dockercfg 文件, 你可以直接使用下面的命令创建一个 dockercfg 的 secret:\n" "\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" #: pkg/kubectl/cmd/top_node.go:65 @@ -19315,6 +19440,8 @@ var _bindata = map[string]func() (*asset, error){ "translations/kubectl/it_IT/LC_MESSAGES/k8s.po": translationsKubectlIt_itLc_messagesK8sPo, "translations/kubectl/ja_JP/LC_MESSAGES/k8s.mo": translationsKubectlJa_jpLc_messagesK8sMo, "translations/kubectl/ja_JP/LC_MESSAGES/k8s.po": translationsKubectlJa_jpLc_messagesK8sPo, + "translations/kubectl/ko_KR/LC_MESSAGES/k8s.mo": translationsKubectlKo_krLc_messagesK8sMo, + "translations/kubectl/ko_KR/LC_MESSAGES/k8s.po": translationsKubectlKo_krLc_messagesK8sPo, "translations/kubectl/template.pot": translationsKubectlTemplatePot, "translations/kubectl/zh_CN/LC_MESSAGES/k8s.mo": translationsKubectlZh_cnLc_messagesK8sMo, "translations/kubectl/zh_CN/LC_MESSAGES/k8s.po": translationsKubectlZh_cnLc_messagesK8sPo, @@ -19408,6 +19535,12 @@ var _bintree = &bintree{nil, map[string]*bintree{ "k8s.po": {translationsKubectlJa_jpLc_messagesK8sPo, map[string]*bintree{}}, }}, }}, + "ko_KR": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlKo_krLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlKo_krLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, "template.pot": {translationsKubectlTemplatePot, map[string]*bintree{}}, "zh_CN": {nil, map[string]*bintree{ "LC_MESSAGES": {nil, map[string]*bintree{ diff --git a/vendor/k8s.io/kubernetes/pkg/generated/openapi/BUILD b/vendor/k8s.io/kubernetes/pkg/generated/openapi/BUILD index 444088c8a..99b5a64b7 100644 --- a/vendor/k8s.io/kubernetes/pkg/generated/openapi/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/generated/openapi/BUILD @@ -47,6 +47,7 @@ openapi_library( "k8s.io/api/rbac/v1alpha1", "k8s.io/api/rbac/v1beta1", "k8s.io/api/scheduling/v1alpha1", + "k8s.io/api/scheduling/v1beta1", "k8s.io/api/settings/v1alpha1", "k8s.io/api/storage/v1", "k8s.io/api/storage/v1alpha1", @@ -64,6 +65,7 @@ openapi_library( "k8s.io/apiserver/pkg/apis/example/v1", "k8s.io/apiserver/pkg/apis/example2/v1", "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", + "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", "k8s.io/client-go/pkg/version", "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1", "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1", diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authenticator/config.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authenticator/config.go index 05c4c377a..e86228b7a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authenticator/config.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authenticator/config.go @@ -59,6 +59,7 @@ type AuthenticatorConfig struct { OIDCGroupsClaim string OIDCGroupsPrefix string OIDCSigningAlgs []string + OIDCRequiredClaims map[string]string ServiceAccountKeyFiles []string ServiceAccountLookup bool ServiceAccountIssuer string @@ -82,7 +83,6 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe var authenticators []authenticator.Request var tokenAuthenticators []authenticator.Token securityDefinitions := spec.SecurityDefinitions{} - hasBasicAuth := false // front-proxy, BasicAuth methods, local first, then remote // Add the front proxy authenticator if requested @@ -100,13 +100,20 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe authenticators = append(authenticators, requestHeaderAuthenticator) } + // basic auth if len(config.BasicAuthFile) > 0 { basicAuth, err := newAuthenticatorFromBasicAuthFile(config.BasicAuthFile) if err != nil { return nil, nil, err } authenticators = append(authenticators, basicAuth) - hasBasicAuth = true + + securityDefinitions["HTTPBasic"] = &spec.SecurityScheme{ + SecuritySchemeProps: spec.SecuritySchemeProps{ + Type: "basic", + Description: "HTTP Basic authentication", + }, + } } // X509 methods @@ -153,7 +160,7 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe // simply returns an error, the OpenID Connect plugin may query the provider to // update the keys, causing performance hits. if len(config.OIDCIssuerURL) > 0 && len(config.OIDCClientID) > 0 { - oidcAuth, err := newAuthenticatorFromOIDCIssuerURL(config.OIDCIssuerURL, config.OIDCClientID, config.OIDCCAFile, config.OIDCUsernameClaim, config.OIDCUsernamePrefix, config.OIDCGroupsClaim, config.OIDCGroupsPrefix, config.OIDCSigningAlgs) + oidcAuth, err := newAuthenticatorFromOIDCIssuerURL(config.OIDCIssuerURL, config.OIDCClientID, config.OIDCCAFile, config.OIDCUsernameClaim, config.OIDCUsernamePrefix, config.OIDCGroupsClaim, config.OIDCGroupsPrefix, config.OIDCSigningAlgs, config.OIDCRequiredClaims) if err != nil { return nil, nil, err } @@ -167,15 +174,6 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe tokenAuthenticators = append(tokenAuthenticators, webhookTokenAuth) } - if hasBasicAuth { - securityDefinitions["HTTPBasic"] = &spec.SecurityScheme{ - SecuritySchemeProps: spec.SecuritySchemeProps{ - Type: "basic", - Description: "HTTP Basic authentication", - }, - } - } - if len(tokenAuthenticators) > 0 { // Union the token authenticators tokenAuth := tokenunion.New(tokenAuthenticators...) @@ -198,10 +196,6 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe if config.Anonymous { return anonymous.NewAuthenticator(), &securityDefinitions, nil } - } - - switch len(authenticators) { - case 0: return nil, &securityDefinitions, nil } @@ -245,7 +239,7 @@ func newAuthenticatorFromTokenFile(tokenAuthFile string) (authenticator.Token, e } // newAuthenticatorFromOIDCIssuerURL returns an authenticator.Token or an error. -func newAuthenticatorFromOIDCIssuerURL(issuerURL, clientID, caFile, usernameClaim, usernamePrefix, groupsClaim, groupsPrefix string, signingAlgs []string) (authenticator.Token, error) { +func newAuthenticatorFromOIDCIssuerURL(issuerURL, clientID, caFile, usernameClaim, usernamePrefix, groupsClaim, groupsPrefix string, signingAlgs []string, requiredClaims map[string]string) (authenticator.Token, error) { const noUsernamePrefix = "-" if usernamePrefix == "" && usernameClaim != "email" { @@ -270,6 +264,7 @@ func newAuthenticatorFromOIDCIssuerURL(issuerURL, clientID, caFile, usernameClai GroupsClaim: groupsClaim, GroupsPrefix: groupsPrefix, SupportedSigningAlgs: signingAlgs, + RequiredClaims: requiredClaims, }) if err != nil { return nil, err diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/BUILD b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/BUILD index 59bd54a40..de78b616f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/BUILD @@ -3,17 +3,6 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["config_test.go"], - data = [ - "//pkg/auth/authorizer/abac:example_policy", - ], - embed = [":go_default_library"], - deps = ["//pkg/kubeapiserver/authorizer/modes:go_default_library"], ) go_library( diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/config.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/config.go index 30661bc14..a72ba5ee6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/config.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/config.go @@ -17,7 +17,6 @@ limitations under the License. package authorizer import ( - "errors" "fmt" "time" @@ -60,26 +59,22 @@ type AuthorizationConfig struct { // based on the authorizationMode or an error. func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleResolver, error) { if len(config.AuthorizationModes) == 0 { - return nil, nil, errors.New("At least one authorization mode should be passed") + return nil, nil, fmt.Errorf("at least one authorization mode must be passed") } var ( authorizers []authorizer.Authorizer ruleResolvers []authorizer.RuleResolver ) - authorizerMap := make(map[string]bool) for _, authorizationMode := range config.AuthorizationModes { - if authorizerMap[authorizationMode] { - return nil, nil, fmt.Errorf("Authorization mode %s specified more than once", authorizationMode) - } - - // Keep cases in sync with constant list above. + // Keep cases in sync with constant list in k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes/modes.go. switch authorizationMode { case modes.ModeNode: graph := node.NewGraph() node.AddGraphEventHandlers( graph, + config.InformerFactory.Core().InternalVersion().Nodes(), config.InformerFactory.Core().InternalVersion().Pods(), config.InformerFactory.Core().InternalVersion().PersistentVolumes(), config.VersionedInformerFactory.Storage().V1beta1().VolumeAttachments(), @@ -96,9 +91,6 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR authorizers = append(authorizers, alwaysDenyAuthorizer) ruleResolvers = append(ruleResolvers, alwaysDenyAuthorizer) case modes.ModeABAC: - if config.PolicyFile == "" { - return nil, nil, errors.New("ABAC's authorization policy file not passed") - } abacAuthorizer, err := abac.NewFromFile(config.PolicyFile) if err != nil { return nil, nil, err @@ -106,9 +98,6 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR authorizers = append(authorizers, abacAuthorizer) ruleResolvers = append(ruleResolvers, abacAuthorizer) case modes.ModeWebhook: - if config.WebhookConfigFile == "" { - return nil, nil, errors.New("Webhook's configuration file not passed") - } webhookAuthorizer, err := webhook.New(config.WebhookConfigFile, config.WebhookCacheAuthorizedTTL, config.WebhookCacheUnauthorizedTTL) @@ -119,24 +108,16 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR ruleResolvers = append(ruleResolvers, webhookAuthorizer) case modes.ModeRBAC: rbacAuthorizer := rbac.New( - &rbac.RoleGetter{Lister: config.InformerFactory.Rbac().InternalVersion().Roles().Lister()}, - &rbac.RoleBindingLister{Lister: config.InformerFactory.Rbac().InternalVersion().RoleBindings().Lister()}, - &rbac.ClusterRoleGetter{Lister: config.InformerFactory.Rbac().InternalVersion().ClusterRoles().Lister()}, - &rbac.ClusterRoleBindingLister{Lister: config.InformerFactory.Rbac().InternalVersion().ClusterRoleBindings().Lister()}, + &rbac.RoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().Roles().Lister()}, + &rbac.RoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().RoleBindings().Lister()}, + &rbac.ClusterRoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().ClusterRoles().Lister()}, + &rbac.ClusterRoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().ClusterRoleBindings().Lister()}, ) authorizers = append(authorizers, rbacAuthorizer) ruleResolvers = append(ruleResolvers, rbacAuthorizer) default: - return nil, nil, fmt.Errorf("Unknown authorization mode %s specified", authorizationMode) + return nil, nil, fmt.Errorf("unknown authorization mode %s specified", authorizationMode) } - authorizerMap[authorizationMode] = true - } - - if !authorizerMap[modes.ModeABAC] && config.PolicyFile != "" { - return nil, nil, errors.New("Cannot specify --authorization-policy-file without mode ABAC") - } - if !authorizerMap[modes.ModeWebhook] && config.WebhookConfigFile != "" { - return nil, nil, errors.New("Cannot specify --authorization-webhook-config-file without mode Webhook") } return union.New(authorizers...), union.NewRuleResolvers(ruleResolvers...), nil diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/config_test.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/config_test.go deleted file mode 100644 index 42cee9889..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/authorizer/config_test.go +++ /dev/null @@ -1,101 +0,0 @@ -/* -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 authorizer - -import ( - "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" - "testing" -) - -// New has multiple return possibilities. This test -// validates that errors are returned only when proper. -func TestNew(t *testing.T) { - examplePolicyFile := "../../auth/authorizer/abac/example_policy_file.jsonl" - - tests := []struct { - config AuthorizationConfig - wantErr bool - msg string - }{ - { - // Unknown modes should return errors - config: AuthorizationConfig{AuthorizationModes: []string{"DoesNotExist"}}, - wantErr: true, - msg: "using a fake mode should have returned an error", - }, - { - // ModeAlwaysAllow and ModeAlwaysDeny should return without authorizationPolicyFile - // but error if one is given - config: AuthorizationConfig{AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny}}, - msg: "returned an error for valid config", - }, - { - // ModeABAC requires a policy file - config: AuthorizationConfig{AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC}}, - wantErr: true, - msg: "specifying ABAC with no policy file should return an error", - }, - { - // ModeABAC should not error if a valid policy path is provided - config: AuthorizationConfig{ - AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC}, - PolicyFile: examplePolicyFile, - }, - msg: "errored while using a valid policy file", - }, - { - - // Authorization Policy file cannot be used without ModeABAC - config: AuthorizationConfig{ - AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny}, - PolicyFile: examplePolicyFile, - }, - wantErr: true, - msg: "should have errored when Authorization Policy File is used without ModeABAC", - }, - { - // At least one authorizationMode is necessary - config: AuthorizationConfig{PolicyFile: examplePolicyFile}, - wantErr: true, - msg: "should have errored when no authorization modes are passed", - }, - { - // ModeWebhook requires at minimum a target. - config: AuthorizationConfig{AuthorizationModes: []string{modes.ModeWebhook}}, - wantErr: true, - msg: "should have errored when config was empty with ModeWebhook", - }, - { - // Cannot provide webhook flags without ModeWebhook - config: AuthorizationConfig{ - AuthorizationModes: []string{modes.ModeAlwaysAllow}, - WebhookConfigFile: "authz_webhook_config.yml", - }, - wantErr: true, - msg: "should have errored when Webhook config file is used without ModeWebhook", - }, - } - - for _, tt := range tests { - _, _, err := tt.config.New() - if tt.wantErr && (err == nil) { - t.Errorf("New %s", tt.msg) - } else if !tt.wantErr && (err != nil) { - t.Errorf("New %s: %v", tt.msg, err) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/default_storage_factory_builder.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/default_storage_factory_builder.go index 9b09d9141..b7a1c73ed 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/default_storage_factory_builder.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/default_storage_factory_builder.go @@ -26,7 +26,6 @@ import ( // SpecialDefaultResourcePrefixes are prefixes compiled into Kubernetes. var SpecialDefaultResourcePrefixes = map[schema.GroupResource]string{ - {Group: "", Resource: "replicationControllers"}: "controllers", {Group: "", Resource: "replicationcontrollers"}: "controllers", {Group: "", Resource: "endpoints"}: "services/endpoints", {Group: "", Resource: "nodes"}: "minions", diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/BUILD b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/BUILD index b4fae4a15..03577d1d7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/BUILD @@ -23,6 +23,7 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library", "//pkg/cloudprovider/providers:go_default_library", + "//pkg/features:go_default_library", "//pkg/kubeapiserver/authenticator:go_default_library", "//pkg/kubeapiserver/authorizer:go_default_library", "//pkg/kubeapiserver/authorizer/modes:go_default_library", @@ -37,13 +38,10 @@ go_library( "//plugin/pkg/admission/extendedresourcetoleration:go_default_library", "//plugin/pkg/admission/gc:go_default_library", "//plugin/pkg/admission/imagepolicy:go_default_library", - "//plugin/pkg/admission/initialresources:go_default_library", "//plugin/pkg/admission/limitranger:go_default_library", "//plugin/pkg/admission/namespace/autoprovision:go_default_library", "//plugin/pkg/admission/namespace/exists:go_default_library", "//plugin/pkg/admission/noderestriction:go_default_library", - "//plugin/pkg/admission/persistentvolume/label:go_default_library", - "//plugin/pkg/admission/persistentvolume/resize:go_default_library", "//plugin/pkg/admission/podnodeselector:go_default_library", "//plugin/pkg/admission/podpreset:go_default_library", "//plugin/pkg/admission/podtolerationrestriction:go_default_library", @@ -52,6 +50,8 @@ go_library( "//plugin/pkg/admission/security/podsecuritypolicy:go_default_library", "//plugin/pkg/admission/securitycontext/scdeny:go_default_library", "//plugin/pkg/admission/serviceaccount:go_default_library", + "//plugin/pkg/admission/storage/persistentvolume/label:go_default_library", + "//plugin/pkg/admission/storage/persistentvolume/resize:go_default_library", "//plugin/pkg/admission/storage/storageclass/setdefault:go_default_library", "//plugin/pkg/admission/storage/storageobjectinuseprotection:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -68,6 +68,8 @@ go_library( "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], @@ -90,8 +92,12 @@ go_test( name = "go_default_test", srcs = [ "admission_test.go", + "authorization_test.go", "storage_versions_test.go", ], embed = [":go_default_library"], - deps = ["//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library"], + deps = [ + "//pkg/kubeapiserver/authorizer/modes:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authentication.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authentication.go index 1a71fb177..8b794de8a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authentication.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authentication.go @@ -25,8 +25,10 @@ import ( "github.com/golang/glog" "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/util/sets" genericapiserver "k8s.io/apiserver/pkg/server" genericoptions "k8s.io/apiserver/pkg/server/options" + "k8s.io/apiserver/pkg/util/flag" "k8s.io/kubernetes/pkg/kubeapiserver/authenticator" authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" ) @@ -63,6 +65,7 @@ type OIDCAuthenticationOptions struct { GroupsClaim string GroupsPrefix string SigningAlgs []string + RequiredClaims map[string]string } type PasswordFileAuthenticationOptions struct { @@ -222,6 +225,11 @@ func (s *BuiltInAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { "Comma-separated list of allowed JOSE asymmetric signing algorithms. JWTs with a "+ "'alg' header value not in this list will be rejected. "+ "Values are defined by RFC 7518 https://tools.ietf.org/html/rfc7518#section-3.1.") + + fs.Var(flag.NewMapStringStringNoSplit(&s.OIDC.RequiredClaims), "oidc-required-claim", ""+ + "A key=value pair that describes a required claim in the ID Token. "+ + "If set, the claim is verified to be present in the ID Token with a matching value. "+ + "Repeat this flag to specify multiple claims.") } if s.PasswordFile != nil { @@ -297,6 +305,7 @@ func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.Au ret.OIDCUsernameClaim = s.OIDC.UsernameClaim ret.OIDCUsernamePrefix = s.OIDC.UsernamePrefix ret.OIDCSigningAlgs = s.OIDC.SigningAlgs + ret.OIDCRequiredClaims = s.OIDC.RequiredClaims } if s.PasswordFile != nil { @@ -365,17 +374,8 @@ func (o *BuiltInAuthenticationOptions) ApplyAuthorization(authorization *BuiltIn // authorization ModeAlwaysAllow cannot be combined with AnonymousAuth. // in such a case the AnonymousAuth is stomped to false and you get a message - if o.Anonymous.Allow { - found := false - for _, mode := range strings.Split(authorization.Mode, ",") { - if mode == authzmodes.ModeAlwaysAllow { - found = true - break - } - } - if found { - glog.Warningf("AnonymousAuth is not allowed with the AllowAll authorizer. Resetting AnonymousAuth to false. You should use a different authorizer") - o.Anonymous.Allow = false - } + if o.Anonymous.Allow && sets.NewString(authorization.Modes...).Has(authzmodes.ModeAlwaysAllow) { + glog.Warningf("AnonymousAuth is not allowed with the AlwaysAllow authorizer. Resetting AnonymousAuth to false. You should use a different authorizer") + o.Anonymous.Allow = false } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authorization.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authorization.go index 88c04e7e1..dd483c5e4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authorization.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authorization.go @@ -17,11 +17,13 @@ limitations under the License. package options import ( + "fmt" "strings" "time" "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/util/sets" versionedinformers "k8s.io/client-go/informers" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/kubeapiserver/authorizer" @@ -29,7 +31,7 @@ import ( ) type BuiltInAuthorizationOptions struct { - Mode string + Modes []string PolicyFile string WebhookConfigFile string WebhookCacheAuthorizedTTL time.Duration @@ -38,19 +40,57 @@ type BuiltInAuthorizationOptions struct { func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions { return &BuiltInAuthorizationOptions{ - Mode: authzmodes.ModeAlwaysAllow, + Modes: []string{authzmodes.ModeAlwaysAllow}, WebhookCacheAuthorizedTTL: 5 * time.Minute, WebhookCacheUnauthorizedTTL: 30 * time.Second, } } func (s *BuiltInAuthorizationOptions) Validate() []error { + if s == nil { + return nil + } allErrors := []error{} + + if len(s.Modes) == 0 { + allErrors = append(allErrors, fmt.Errorf("at least one authorization-mode must be passed")) + } + + allowedModes := sets.NewString(authzmodes.AuthorizationModeChoices...) + modes := sets.NewString(s.Modes...) + for _, mode := range s.Modes { + if !allowedModes.Has(mode) { + allErrors = append(allErrors, fmt.Errorf("authorization-mode %q is not a valid mode", mode)) + } + if mode == authzmodes.ModeABAC { + if s.PolicyFile == "" { + allErrors = append(allErrors, fmt.Errorf("authorization-mode ABAC's authorization policy file not passed")) + } + } + if mode == authzmodes.ModeWebhook { + if s.WebhookConfigFile == "" { + allErrors = append(allErrors, fmt.Errorf("authorization-mode Webhook's authorization config file not passed")) + } + } + } + + if s.PolicyFile != "" && !modes.Has(authzmodes.ModeABAC) { + allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-policy-file without mode ABAC")) + } + + if s.WebhookConfigFile != "" && !modes.Has(authzmodes.ModeWebhook) { + allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-webhook-config-file without mode Webhook")) + } + + if len(s.Modes) != len(modes.List()) { + allErrors = append(allErrors, fmt.Errorf("authorization-mode %q has mode specified more than once", s.Modes)) + } + return allErrors } func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&s.Mode, "authorization-mode", s.Mode, ""+ + fs.StringSliceVar(&s.Modes, "authorization-mode", s.Modes, ""+ "Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "+ strings.Join(authzmodes.AuthorizationModeChoices, ",")+".") @@ -68,25 +108,11 @@ func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) { fs.DurationVar(&s.WebhookCacheUnauthorizedTTL, "authorization-webhook-cache-unauthorized-ttl", s.WebhookCacheUnauthorizedTTL, "The duration to cache 'unauthorized' responses from the webhook authorizer.") - - fs.String("authorization-rbac-super-user", "", ""+ - "If specified, a username which avoids RBAC authorization checks and role binding "+ - "privilege escalation checks, to be used with --authorization-mode=RBAC.") - fs.MarkDeprecated("authorization-rbac-super-user", "Removed during alpha to beta. The 'system:masters' group has privileged access.") - -} - -func (s *BuiltInAuthorizationOptions) Modes() []string { - modes := []string{} - if len(s.Mode) > 0 { - modes = strings.Split(s.Mode, ",") - } - return modes } func (s *BuiltInAuthorizationOptions) ToAuthorizationConfig(informerFactory informers.SharedInformerFactory, versionedInformerFactory versionedinformers.SharedInformerFactory) authorizer.AuthorizationConfig { return authorizer.AuthorizationConfig{ - AuthorizationModes: s.Modes(), + AuthorizationModes: s.Modes, PolicyFile: s.PolicyFile, WebhookConfigFile: s.WebhookConfigFile, WebhookCacheAuthorizedTTL: s.WebhookCacheAuthorizedTTL, diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authorization_test.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authorization_test.go new file mode 100644 index 000000000..4794de700 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/authorization_test.go @@ -0,0 +1,104 @@ +/* +Copyright 2018 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 options + +import ( + "testing" + + "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" +) + +func TestAuthzValidate(t *testing.T) { + examplePolicyFile := "../../auth/authorizer/abac/example_policy_file.jsonl" + + testCases := []struct { + name string + modes []string + policyFile string + webhookConfigFile string + expectErr bool + }{ + { + name: "Unknown modes should return errors", + modes: []string{"DoesNotExist"}, + expectErr: true, + }, + { + name: "At least one authorizationMode is necessary", + modes: []string{}, + expectErr: true, + }, + { + name: "ModeAlwaysAllow and ModeAlwaysDeny should return without authorizationPolicyFile", + modes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny}, + expectErr: false, + }, + { + name: "ModeABAC requires a policy file", + modes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC}, + expectErr: true, + }, + { + name: "Authorization Policy file cannot be used without ModeABAC", + modes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny}, + policyFile: examplePolicyFile, + webhookConfigFile: "", + expectErr: true, + }, + { + name: "ModeABAC should not error if a valid policy path is provided", + modes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC}, + policyFile: examplePolicyFile, + webhookConfigFile: "", + expectErr: false, + }, + { + name: "ModeWebhook requires a config file", + modes: []string{modes.ModeWebhook}, + expectErr: true, + }, + { + name: "Cannot provide webhook config file without ModeWebhook", + modes: []string{modes.ModeAlwaysAllow}, + webhookConfigFile: "authz_webhook_config.yaml", + expectErr: true, + }, + { + name: "ModeWebhook should not error if a valid config file is provided", + modes: []string{modes.ModeWebhook}, + webhookConfigFile: "authz_webhook_config.yaml", + expectErr: false, + }, + } + + for _, testcase := range testCases { + t.Run(testcase.name, func(t *testing.T) { + options := NewBuiltInAuthorizationOptions() + options.Modes = testcase.modes + options.WebhookConfigFile = testcase.webhookConfigFile + options.PolicyFile = testcase.policyFile + + errs := options.Validate() + if len(errs) > 0 && !testcase.expectErr { + t.Errorf("got unexpected err %v", errs) + } + if testcase.expectErr && len(errs) == 0 { + t.Errorf("should return an error") + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/plugins.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/plugins.go index 75095b20d..abcb5b467 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/plugins.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/plugins.go @@ -34,13 +34,10 @@ import ( "k8s.io/kubernetes/plugin/pkg/admission/extendedresourcetoleration" "k8s.io/kubernetes/plugin/pkg/admission/gc" "k8s.io/kubernetes/plugin/pkg/admission/imagepolicy" - "k8s.io/kubernetes/plugin/pkg/admission/initialresources" "k8s.io/kubernetes/plugin/pkg/admission/limitranger" "k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision" "k8s.io/kubernetes/plugin/pkg/admission/namespace/exists" "k8s.io/kubernetes/plugin/pkg/admission/noderestriction" - "k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label" - "k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize" "k8s.io/kubernetes/plugin/pkg/admission/podnodeselector" "k8s.io/kubernetes/plugin/pkg/admission/podpreset" "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction" @@ -49,6 +46,8 @@ import ( "k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy" "k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny" "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount" + "k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label" + "k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize" "k8s.io/kubernetes/plugin/pkg/admission/storage/storageclass/setdefault" "k8s.io/kubernetes/plugin/pkg/admission/storage/storageobjectinuseprotection" @@ -58,6 +57,8 @@ import ( "k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle" mutatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating" validatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/validating" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" ) // AllOrderedPlugins is the list of all the plugins in order. @@ -68,7 +69,6 @@ var AllOrderedPlugins = []string{ exists.PluginName, // NamespaceExists scdeny.PluginName, // SecurityContextDeny antiaffinity.PluginName, // LimitPodHardAntiAffinityTopology - initialresources.PluginName, // InitialResources podpreset.PluginName, // PodPreset limitranger.PluginName, // LimitRanger serviceaccount.PluginName, // ServiceAccount @@ -109,7 +109,6 @@ func RegisterAllAdmissionPlugins(plugins *admission.Plugins) { extendedresourcetoleration.Register(plugins) gc.Register(plugins) imagepolicy.Register(plugins) - initialresources.Register(plugins) limitranger.Register(plugins) autoprovision.Register(plugins) exists.Register(plugins) @@ -134,13 +133,17 @@ func DefaultOffAdmissionPlugins() sets.String { lifecycle.PluginName, //NamespaceLifecycle limitranger.PluginName, //LimitRanger serviceaccount.PluginName, //ServiceAccount - label.PluginName, //PersistentVolumeLabel setdefault.PluginName, //DefaultStorageClass + resize.PluginName, //PersistentVolumeClaimResize defaulttolerationseconds.PluginName, //DefaultTolerationSeconds mutatingwebhook.PluginName, //MutatingAdmissionWebhook validatingwebhook.PluginName, //ValidatingAdmissionWebhook resourcequota.PluginName, //ResourceQuota ) + if utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) { + defaultOnPlugins.Insert(podpriority.PluginName) //PodPriority + } + return sets.NewString(AllOrderedPlugins...).Difference(defaultOnPlugins) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/serving.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/serving.go index d2339ed07..388bc614b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/serving.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/serving.go @@ -81,7 +81,7 @@ func NewInsecureServingOptions() *InsecureServingOptions { } } -func (s InsecureServingOptions) Validate(portArg string) []error { +func (s InsecureServingOptions) Validate() []error { errors := []error{} if s.BindPort < 0 || s.BindPort > 65535 { diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/storage_versions.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/storage_versions.go index bac872560..714cc70af 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/storage_versions.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/options/storage_versions.go @@ -22,6 +22,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubernetes/pkg/api/legacyscheme" + "sort" + "github.com/spf13/pflag" ) @@ -40,8 +42,8 @@ type StorageSerializationOptions struct { func NewStorageSerializationOptions() *StorageSerializationOptions { return &StorageSerializationOptions{ - DefaultStorageVersions: legacyscheme.Registry.AllPreferredGroupVersions(), - StorageVersions: legacyscheme.Registry.AllPreferredGroupVersions(), + DefaultStorageVersions: ToPreferredVersionString(legacyscheme.Scheme.PreferredVersionAllGroups()), + StorageVersions: ToPreferredVersionString(legacyscheme.Scheme.PreferredVersionAllGroups()), } } @@ -95,20 +97,25 @@ func mergeGroupVersionIntoMap(gvList string, dest map[string]schema.GroupVersion func (s *StorageSerializationOptions) AddFlags(fs *pflag.FlagSet) { // Note: the weird ""+ in below lines seems to be the only way to get gofmt to // arrange these text blocks sensibly. Grrr. - - deprecatedStorageVersion := "" - fs.StringVar(&deprecatedStorageVersion, "storage-version", deprecatedStorageVersion, - "DEPRECATED: the version to store the legacy v1 resources with. Defaults to server preferred.") - fs.MarkDeprecated("storage-version", "--storage-version is deprecated and will be removed when the v1 API "+ - "is retired. Setting this has no effect. See --storage-versions instead.") - fs.StringVar(&s.StorageVersions, "storage-versions", s.StorageVersions, ""+ "The per-group version to store resources in. "+ "Specified in the format \"group1/version1,group2/version2,...\". "+ "In the case where objects are moved from one group to the other, "+ "you may specify the format \"group1=group2/v1beta1,group3/v1beta1,...\". "+ "You only need to pass the groups you wish to change from the defaults. "+ - "It defaults to a list of preferred versions of all registered groups, "+ - "which is derived from the KUBE_API_VERSIONS environment variable.") + "It defaults to a list of preferred versions of all known groups.") } + +// ToPreferredVersionString returns the preferred versions of all registered +// groups in the form of "group1/version1,group2/version2,...". This is compatible +// with the flag format +func ToPreferredVersionString(versions []schema.GroupVersion) string { + var defaults []string + for _, version := range versions { + defaults = append(defaults, version.String()) + } + // sorting provides stable output for help. + sort.Strings(defaults) + return strings.Join(defaults, ",") +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/server/BUILD b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/server/BUILD index 2c7cf9a24..824a693a3 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/server/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/server/BUILD @@ -13,7 +13,6 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/filters:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/features:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/server/insecure_handler.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/server/insecure_handler.go index c3a3921f5..600f028b8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/server/insecure_handler.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/server/insecure_handler.go @@ -25,7 +25,6 @@ import ( "k8s.io/apiserver/pkg/authentication/user" genericapifilters "k8s.io/apiserver/pkg/endpoints/filters" - apirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/server" genericfilters "k8s.io/apiserver/pkg/server/filters" @@ -41,17 +40,16 @@ import ( func BuildInsecureHandlerChain(apiHandler http.Handler, c *server.Config) http.Handler { handler := apiHandler if utilfeature.DefaultFeatureGate.Enabled(features.AdvancedAuditing) { - handler = genericapifilters.WithAudit(handler, c.RequestContextMapper, c.AuditBackend, c.AuditPolicyChecker, c.LongRunningFunc) + handler = genericapifilters.WithAudit(handler, c.AuditBackend, c.AuditPolicyChecker, c.LongRunningFunc) } else { - handler = genericapifilters.WithLegacyAudit(handler, c.RequestContextMapper, c.LegacyAuditWriter) + handler = genericapifilters.WithLegacyAudit(handler, c.LegacyAuditWriter) } - handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, insecureSuperuser{}, nil) + handler = genericapifilters.WithAuthentication(handler, insecureSuperuser{}, nil) handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true") - handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc, c.RequestTimeout) - handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.RequestContextMapper, c.LongRunningFunc) - handler = genericfilters.WithWaitGroup(handler, c.RequestContextMapper, c.LongRunningFunc, c.HandlerChainWaitGroup) - handler = genericapifilters.WithRequestInfo(handler, server.NewRequestInfoResolver(c), c.RequestContextMapper) - handler = apirequest.WithRequestContext(handler, c.RequestContextMapper) + handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.LongRunningFunc, c.RequestTimeout) + handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.LongRunningFunc) + handler = genericfilters.WithWaitGroup(handler, c.LongRunningFunc, c.HandlerChainWaitGroup) + handler = genericapifilters.WithRequestInfo(handler, server.NewRequestInfoResolver(c)) handler = genericfilters.WithPanicRecovery(handler) return handler diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/.import-restrictions b/vendor/k8s.io/kubernetes/pkg/kubectl/.import-restrictions index 6d8fdf7cb..8dc23442f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/.import-restrictions +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/.import-restrictions @@ -121,7 +121,7 @@ "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates", "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util", "k8s.io/kubernetes/pkg/scheduler/api", - "k8s.io/kubernetes/pkg/scheduler/schedulercache", + "k8s.io/kubernetes/pkg/scheduler/cache", "k8s.io/kubernetes/pkg/scheduler/util", "k8s.io/kubernetes/pkg/scheduler/volumebinder", "k8s.io/kubernetes/pkg/security/apparmor", diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/BUILD index 7fe68ccde..9701a1ad2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/BUILD @@ -12,7 +12,6 @@ go_test( "autoscale_test.go", "clusterrolebinding_test.go", "configmap_test.go", - "delete_test.go", "deployment_test.go", "env_file_test.go", "generate_test.go", @@ -21,7 +20,6 @@ go_test( "pdb_test.go", "priorityclass_test.go", "quota_test.go", - "resource_filter_test.go", "rolebinding_test.go", "rollback_test.go", "rolling_updater_test.go", @@ -34,28 +32,21 @@ go_test( "service_basic_test.go", "service_test.go", "serviceaccount_test.go", - "sorting_printer_test.go", + "sorter_test.go", ], embed = [":go_default_library"], deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", - "//pkg/apis/apps:go_default_library", - "//pkg/apis/batch:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset/fake:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/apps/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library", "//pkg/kubectl/util:go_default_library", - "//pkg/printers:go_default_library", + "//pkg/util/pointer:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", "//vendor/k8s.io/api/autoscaling/v1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/api/batch/v1beta1:go_default_library", @@ -74,18 +65,13 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - "//vendor/k8s.io/client-go/discovery/fake:go_default_library", - "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest/fake:go_default_library", "//vendor/k8s.io/client-go/scale:go_default_library", + "//vendor/k8s.io/client-go/scale/fake:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", "//vendor/k8s.io/client-go/util/testing:go_default_library", ], @@ -96,23 +82,19 @@ go_library( srcs = [ "apply.go", "autoscale.go", - "bash_comp_utils.go", "clusterrolebinding.go", "conditions.go", "configmap.go", - "delete.go", "deployment.go", "doc.go", "env_file.go", "generate.go", "history.go", "interfaces.go", - "kubectl.go", "namespace.go", "pdb.go", "priorityclass.go", "quota.go", - "resource_filter.go", "rolebinding.go", "rollback.go", "rolling_updater.go", @@ -125,7 +107,7 @@ go_library( "service.go", "service_basic.go", "serviceaccount.go", - "sorting_printer.go", + "sorter.go", ], importpath = "k8s.io/kubernetes/pkg/kubectl", deps = [ @@ -133,21 +115,15 @@ go_library( "//pkg/api/pod:go_default_library", "//pkg/api/v1/pod:go_default_library", "//pkg/apis/apps:go_default_library", - "//pkg/apis/batch:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/v1:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/apps/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library", - "//pkg/controller/daemon:go_default_library", "//pkg/controller/deployment/util:go_default_library", - "//pkg/controller/statefulset:go_default_library", "//pkg/credentialprovider:go_default_library", "//pkg/kubectl/apps:go_default_library", - "//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/util:go_default_library", "//pkg/kubectl/util/hash:go_default_library", "//pkg/kubectl/util/slice:go_default_library", @@ -182,14 +158,11 @@ go_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/util/strategicpatch:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/scale:go_default_library", "//vendor/k8s.io/client-go/util/integer:go_default_library", @@ -212,13 +185,13 @@ filegroup( ":package-srcs", "//pkg/kubectl/apply:all-srcs", "//pkg/kubectl/apps:all-srcs", - "//pkg/kubectl/categories:all-srcs", "//pkg/kubectl/cmd:all-srcs", "//pkg/kubectl/explain:all-srcs", + "//pkg/kubectl/genericclioptions:all-srcs", "//pkg/kubectl/metricsutil:all-srcs", "//pkg/kubectl/plugins:all-srcs", + "//pkg/kubectl/polymorphichelpers:all-srcs", "//pkg/kubectl/proxy:all-srcs", - "//pkg/kubectl/resource:all-srcs", "//pkg/kubectl/scheme:all-srcs", "//pkg/kubectl/util:all-srcs", "//pkg/kubectl/validation:all-srcs", diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply.go index 1e8f79cae..3c82aee80 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply.go @@ -20,13 +20,14 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/kubectl/resource" ) +var metadataAccessor = meta.NewAccessor() + // GetOriginalConfiguration retrieves the original configuration of the object // from the annotation, or nil if no annotation was found. -func GetOriginalConfiguration(mapping *meta.RESTMapping, obj runtime.Object) ([]byte, error) { - annots, err := mapping.MetadataAccessor.Annotations(obj) +func GetOriginalConfiguration(obj runtime.Object) ([]byte, error) { + annots, err := metadataAccessor.Annotations(obj) if err != nil { return nil, err } @@ -45,13 +46,12 @@ func GetOriginalConfiguration(mapping *meta.RESTMapping, obj runtime.Object) ([] // SetOriginalConfiguration sets the original configuration of the object // as the annotation on the object for later use in computing a three way patch. -func SetOriginalConfiguration(info *resource.Info, original []byte) error { +func setOriginalConfiguration(obj runtime.Object, original []byte) error { if len(original) < 1 { return nil } - accessor := info.Mapping.MetadataAccessor - annots, err := accessor.Annotations(info.Object) + annots, err := metadataAccessor.Annotations(obj) if err != nil { return err } @@ -61,22 +61,21 @@ func SetOriginalConfiguration(info *resource.Info, original []byte) error { } annots[v1.LastAppliedConfigAnnotation] = string(original) - return info.Mapping.MetadataAccessor.SetAnnotations(info.Object, annots) + return metadataAccessor.SetAnnotations(obj, annots) } // GetModifiedConfiguration retrieves the modified configuration of the object. // If annotate is true, it embeds the result as an annotation in the modified // configuration. If an object was read from the command input, it will use that // version of the object. Otherwise, it will use the version from the server. -func GetModifiedConfiguration(info *resource.Info, annotate bool, codec runtime.Encoder) ([]byte, error) { +func GetModifiedConfiguration(obj runtime.Object, annotate bool, codec runtime.Encoder) ([]byte, error) { // First serialize the object without the annotation to prevent recursion, // then add that serialization to it as the annotation and serialize it again. var modified []byte // Otherwise, use the server side version of the object. - accessor := info.Mapping.MetadataAccessor // Get the current annotations from the object. - annots, err := accessor.Annotations(info.Object) + annots, err := metadataAccessor.Annotations(obj) if err != nil { return nil, err } @@ -87,22 +86,22 @@ func GetModifiedConfiguration(info *resource.Info, annotate bool, codec runtime. original := annots[v1.LastAppliedConfigAnnotation] delete(annots, v1.LastAppliedConfigAnnotation) - if err := accessor.SetAnnotations(info.Object, annots); err != nil { + if err := metadataAccessor.SetAnnotations(obj, annots); err != nil { return nil, err } - modified, err = runtime.Encode(codec, info.Object) + modified, err = runtime.Encode(codec, obj) if err != nil { return nil, err } if annotate { annots[v1.LastAppliedConfigAnnotation] = string(modified) - if err := info.Mapping.MetadataAccessor.SetAnnotations(info.Object, annots); err != nil { + if err := metadataAccessor.SetAnnotations(obj, annots); err != nil { return nil, err } - modified, err = runtime.Encode(codec, info.Object) + modified, err = runtime.Encode(codec, obj) if err != nil { return nil, err } @@ -110,7 +109,7 @@ func GetModifiedConfiguration(info *resource.Info, annotate bool, codec runtime. // Restore the object to its original condition. annots[v1.LastAppliedConfigAnnotation] = original - if err := info.Mapping.MetadataAccessor.SetAnnotations(info.Object, annots); err != nil { + if err := metadataAccessor.SetAnnotations(obj, annots); err != nil { return nil, err } @@ -119,28 +118,28 @@ func GetModifiedConfiguration(info *resource.Info, annotate bool, codec runtime. // UpdateApplyAnnotation calls CreateApplyAnnotation if the last applied // configuration annotation is already present. Otherwise, it does nothing. -func UpdateApplyAnnotation(info *resource.Info, codec runtime.Encoder) error { - if original, err := GetOriginalConfiguration(info.Mapping, info.Object); err != nil || len(original) <= 0 { +func UpdateApplyAnnotation(obj runtime.Object, codec runtime.Encoder) error { + if original, err := GetOriginalConfiguration(obj); err != nil || len(original) <= 0 { return err } - return CreateApplyAnnotation(info, codec) + return CreateApplyAnnotation(obj, codec) } // CreateApplyAnnotation gets the modified configuration of the object, // without embedding it again, and then sets it on the object as the annotation. -func CreateApplyAnnotation(info *resource.Info, codec runtime.Encoder) error { - modified, err := GetModifiedConfiguration(info, false, codec) +func CreateApplyAnnotation(obj runtime.Object, codec runtime.Encoder) error { + modified, err := GetModifiedConfiguration(obj, false, codec) if err != nil { return err } - return SetOriginalConfiguration(info, modified) + return setOriginalConfiguration(obj, modified) } // Create the annotation used by kubectl apply only when createAnnotation is true // Otherwise, only update the annotation when it already exists -func CreateOrUpdateAnnotation(createAnnotation bool, info *resource.Info, codec runtime.Encoder) error { +func CreateOrUpdateAnnotation(createAnnotation bool, obj runtime.Object, codec runtime.Encoder) error { if createAnnotation { - return CreateApplyAnnotation(info, codec) + return CreateApplyAnnotation(obj, codec) } - return UpdateApplyAnnotation(info, codec) + return UpdateApplyAnnotation(obj, codec) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/BUILD index 02443472b..419388c1d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/BUILD @@ -6,6 +6,7 @@ go_library( "doc.go", "element.go", "empty_element.go", + "error.go", "list_element.go", "map_element.go", "primitive_element.go", diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/element.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/element.go index 0b55b109b..8e7e14800 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/element.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/element.go @@ -45,7 +45,7 @@ type Element interface { GetRecorded() interface{} // HasLocal returns true if the field was explicitly - // present in the recorded source. This is to differentiate between + // present in the local source. This is to differentiate between // undefined and set to null HasLocal() bool @@ -88,7 +88,7 @@ type FieldMetaImpl struct { // Type is the openapi type of the field - "list", "primitive", "map" Type string - // Name contains of the field + // Name contains name of the field Name string } @@ -276,8 +276,7 @@ func (s *CombinedMapSlice) UpsertRecorded(key MergeKeys, l interface{}) error { if err != nil { return err } - item.recorded = l - item.recordedSet = true + item.SetRecorded(l) return nil } @@ -289,8 +288,7 @@ func (s *CombinedMapSlice) UpsertLocal(key MergeKeys, l interface{}) error { if err != nil { return err } - item.local = l - item.localSet = true + item.SetLocal(l) return nil } @@ -302,8 +300,7 @@ func (s *CombinedMapSlice) UpsertRemote(key MergeKeys, l interface{}) error { if err != nil { return err } - item.remote = l - item.remoteSet = true + item.SetRemote(l) return nil } @@ -359,13 +356,13 @@ func (b *RawElementData) SetRecorded(value interface{}) { b.recordedSet = true } -// SetLocal sets the recorded value +// SetLocal sets the local value func (b *RawElementData) SetLocal(value interface{}) { b.local = value b.localSet = true } -// SetRemote sets the recorded value +// SetRemote sets the remote value func (b *RawElementData) SetRemote(value interface{}) { b.remote = value b.remoteSet = true @@ -419,3 +416,8 @@ func (e HasElementData) HasLocal() bool { func (e HasElementData) HasRemote() bool { return e.remoteSet } + +// ConflictDetector defines the capability to detect conflict. An element can examine remote/recorded value to detect conflict. +type ConflictDetector interface { + HasConflict() error +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/error.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/error.go new file mode 100644 index 000000000..2e7a3d499 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/error.go @@ -0,0 +1,37 @@ +/* +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 apply + +import "fmt" + +// ConflictError represents a conflict error occurred during the merge operation. +type ConflictError struct { + element Element +} + +// NewConflictError returns a ConflictError with detailed conflict information in element +func NewConflictError(e PrimitiveElement) *ConflictError { + return &ConflictError{ + element: e, + } +} + +// Error implements error +func (c *ConflictError) Error() string { + return fmt.Sprintf("conflict detected, recorded value (%+v) and remote value (%+v)", + c.element.GetRecorded(), c.element.GetRemote()) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/list_element.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/list_element.go index 86be39ed1..b271d3882 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/list_element.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/list_element.go @@ -65,3 +65,17 @@ func sliceCast(i interface{}) []interface{} { } return i.([]interface{}) } + +// HasConflict returns ConflictError if fields in recorded and remote of ListElement conflict +func (e ListElement) HasConflict() error { + for _, item := range e.Values { + if item, ok := item.(ConflictDetector); ok { + if err := item.HasConflict(); err != nil { + return err + } + } + } + return nil +} + +var _ ConflictDetector = &ListElement{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/map_element.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/map_element.go index 9fcd4e86b..c24ac4019 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/map_element.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/map_element.go @@ -70,3 +70,17 @@ func mapCast(i interface{}) map[string]interface{} { } return i.(map[string]interface{}) } + +// HasConflict returns ConflictError if some elements in map conflict. +func (e MapElement) HasConflict() error { + for _, item := range e.GetValues() { + if item, ok := item.(ConflictDetector); ok { + if err := item.HasConflict(); err != nil { + return err + } + } + } + return nil +} + +var _ ConflictDetector = &MapElement{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/parse/util.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/parse/util.go index ce7adddab..676ab7d3d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/parse/util.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/parse/util.go @@ -104,7 +104,7 @@ func getFieldMeta(s proto.Schema, name string) (apply.FieldMetaImpl, error) { if e, found := ext["x-kubernetes-patch-strategy"]; found { strategy, ok := e.(string) if !ok { - return apply.FieldMetaImpl{}, fmt.Errorf("Expected string for x-kubernetes-patch-strategy by got %T", s) + return apply.FieldMetaImpl{}, fmt.Errorf("Expected string for x-kubernetes-patch-strategy by got %T", e) } // Take the first strategy if there are substrategies. diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/primitive_element.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/primitive_element.go index 847ee1a29..cc80c7b03 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/primitive_element.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/primitive_element.go @@ -16,6 +16,8 @@ limitations under the License. package apply +import "reflect" + // PrimitiveElement contains the recorded, local and remote values for a field // of type primitive type PrimitiveElement struct { @@ -32,3 +34,21 @@ func (e PrimitiveElement) Merge(v Strategy) (Result, error) { } var _ Element = &PrimitiveElement{} + +// HasConflict returns ConflictError if primitive element has conflict field. +// Conflicts happen when either of the following conditions: +// 1. A field is specified in both recorded and remote values, but does not match. +// 2. A field is specified in recorded values, but missing in remote values. +func (e PrimitiveElement) HasConflict() error { + if e.HasRecorded() && e.HasRemote() { + if !reflect.DeepEqual(e.GetRecorded(), e.GetRemote()) { + return NewConflictError(e) + } + } + if e.HasRecorded() && !e.HasRemote() { + return NewConflictError(e) + } + return nil +} + +var _ ConflictDetector = &PrimitiveElement{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/BUILD index 2013ea7c2..d9652e356 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/BUILD @@ -18,6 +18,7 @@ go_library( go_test( name = "go_default_xtest", srcs = [ + "merge_conflict_test.go", "merge_map_list_test.go", "merge_map_test.go", "merge_primitive_list_test.go", diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_conflict_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_conflict_test.go new file mode 100644 index 000000000..73ca6ca72 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_conflict_test.go @@ -0,0 +1,206 @@ +/* +Copyright 2018 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 strategy_test + +import ( + . "github.com/onsi/ginkgo" + + "k8s.io/kubernetes/pkg/kubectl/apply/strategy" +) + +var _ = Describe("Comparing fields of remote and recorded ", func() { + Context("Test conflict in map fields of remote and recorded", func() { + It("If conflicts found, expected return error", func() { + recorded := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + foo1: "key1" +`) + local := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + foo2: "baz2-1" +`) + remote := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + foo1: "baz1-0" +`) + + expect := hasConflict + // map fields have conflict : recorded {foo1 : "key1"}, remote {foo1 : "baz1-0"} + runConflictTest(strategy.Create(strategy.Options{FailOnConflict: true}), recorded, local, remote, expect) + }) + }) + + Context("Test conflict in list fields of remote and recorded ", func() { + It("If conflicts found, expected return false", func() { + recorded := create(` +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + finalizers: + - "a" + - "b" + - "d" +`) + local := create(` +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + finalizers: + - "a" + - "b" +`) + remote := create(` +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + finalizers: + - "a" + - "b" + - "c" +`) + expect := hasConflict + // primatie lists have conflicts: recorded [a, b, d], remote [a, b, c] + runConflictTest(strategy.Create(strategy.Options{FailOnConflict: true}), recorded, local, remote, expect) + }) + }) + + Context("Test conflict in Map-List fields of remote and recorded ", func() { + It("should leave the item", func() { + recorded := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + template: + spec: + containers: + - name: item1 + image: image1 +`) + local := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + template: + spec: + containers: + - name: item2 + image: image2 +`) + remote := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + template: + spec: + containers: + - name: item1 + image: image3 +`) + expect := hasConflict + // map list has conflict : recorded {containers: [ {name: item1, image: image1} ]} , remote {containers: [ {name: item1, image: image3} ]} + runConflictTest(strategy.Create(strategy.Options{FailOnConflict: true}), recorded, local, remote, expect) + }) + }) + + Context("Test conflicts in nested map field", func() { + It("If conflicts found, expected return error", func() { + recorded := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + foo1: + name: "key1" +`) + local := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + foo1: + name: "baz1-0" +`) + remote := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + foo1: + name: "baz1-1" +`) + expect := hasConflict + // nested map has conflict : recorded {foo1: {name: "key1"}}, remote {foo1: {name : "baz1-1"}} + runConflictTest(strategy.Create(strategy.Options{FailOnConflict: true}), recorded, local, remote, expect) + }) + }) + + Context("Test conflicts in complicated map, list", func() { + It("Should catch conflict in key-value in map element", func() { + recorded := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + template: + spec: + containers: + - name: container + ports: + - containerPort: 8080 + protocol: TCP + hostPort: 2020 + - containerPort: 8080 + protocol: UDP + hostPort: 2022 +`) + local := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + template: + spec: + containers: + - name: container + ports: + - containerPort: 8080 + protocol: TCP + hostPort: 2020 +`) + remote := create(` +apiVersion: apps/v1beta1 +kind: Deployment +spec: + template: + spec: + containers: + - name: container + ports: + - containerPort: 8080 + protocol: TCP + hostPort: 2020 + - containerPort: 8080 + protocol: UDP + hostPort: 2022 + hostIP: "127.0.0.1" +`) + expect := noConflict + runConflictTest(strategy.Create(strategy.Options{FailOnConflict: true}), recorded, local, remote, expect) + }) + }) +}) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_visitor.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_visitor.go index 94a9d701f..5a1b1a003 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_visitor.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_visitor.go @@ -41,7 +41,10 @@ func (v mergeStrategy) MergeList(e apply.ListElement) (apply.Result, error) { if result, done := v.doAddOrDelete(e); done { return result, nil } - + // Detect conflict in ListElement + if err := v.doConflictDetect(e); err != nil { + return apply.Result{}, err + } // Merge each item in the list and append it to the list merged := []interface{}{} for _, value := range e.Values { @@ -76,7 +79,10 @@ func (v mergeStrategy) MergeMap(e apply.MapElement) (apply.Result, error) { if result, done := v.doAddOrDelete(e); done { return result, nil } - + // Detect conflict in MapElement + if err := v.doConflictDetect(e); err != nil { + return apply.Result{}, err + } return v.doMergeMap(e.GetValues()) } @@ -86,7 +92,10 @@ func (v mergeStrategy) MergeType(e apply.TypeElement) (apply.Result, error) { if result, done := v.doAddOrDelete(e); done { return result, nil } - + // Detect conflict in TypeElement + if err := v.doConflictDetect(e); err != nil { + return apply.Result{}, err + } return v.doMergeMap(e.GetValues()) } @@ -145,4 +154,9 @@ func (v mergeStrategy) MergeEmpty(diff apply.EmptyElement) (apply.Result, error) return apply.Result{Operation: apply.SET}, nil } +// doConflictDetect returns error if element has conflict +func (v mergeStrategy) doConflictDetect(e apply.Element) error { + return v.strategic.doConflictDetect(e) +} + var _ apply.Strategy = &mergeStrategy{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_visitor.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_visitor.go index 5bf2f55d1..047d53ff1 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_visitor.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_visitor.go @@ -65,11 +65,13 @@ func (v replaceStrategy) MergeEmpty(e apply.EmptyElement) (apply.Result, error) // replace returns the local value if specified, otherwise it returns the remote value // this works regardless of the approach func (v replaceStrategy) doReplace(e apply.Element) (apply.Result, error) { - // TODO: Check for conflicts + if result, done := v.doAddOrDelete(e); done { return result, nil } - + if err := v.doConflictDetect(e); err != nil { + return apply.Result{}, err + } if e.HasLocal() { // Specified locally, set the local value return apply.Result{Operation: apply.SET, MergedResult: e.GetLocal()}, nil @@ -97,4 +99,9 @@ func (v replaceStrategy) doAddOrDelete(e apply.Element) (apply.Result, bool) { return apply.Result{}, false } +// doConflictDetect returns error if element has conflict +func (v replaceStrategy) doConflictDetect(e apply.Element) error { + return v.strategic.doConflictDetect(e) +} + var _ apply.Strategy = &replaceStrategy{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/strategic_visitor.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/strategic_visitor.go index eae1f9230..8c2d592b0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/strategic_visitor.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/strategic_visitor.go @@ -96,4 +96,14 @@ func (v delegatingStrategy) MergeEmpty(diff apply.EmptyElement) (apply.Result, e return v.merge.MergeEmpty(diff) } +// doConflictDetect detects conflicts in element when option enabled, return error if conflict happened. +func (v delegatingStrategy) doConflictDetect(e apply.Element) error { + if v.options.FailOnConflict { + if e, ok := e.(apply.ConflictDetector); ok { + return e.HasConflict() + } + } + return nil +} + var _ apply.Strategy = &delegatingStrategy{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/test_swagger.json b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/test_swagger.json index 2bdd12657..57f69314d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/test_swagger.json +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/test_swagger.json @@ -81,7 +81,7 @@ "spec": { "description": "Specification of the desired behavior of the Deployment.", "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentSpec" - }, + } }, "x-kubernetes-group-version-kind": [ { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/utils_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/utils_test.go index 1ca687bac..9a958b78f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/utils_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/utils_test.go @@ -32,6 +32,11 @@ import ( tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" ) +const ( + hasConflict = true + noConflict = false +) + var fakeResources = tst.NewFakeResources(filepath.Join("..", "..", "..", "..", "api", "openapi-spec", "swagger.json")) // run parses the openapi and runs the tests @@ -64,3 +69,17 @@ func create(config string) map[string]interface{} { return result } + +func runConflictTest(instance apply.Strategy, recorded, local, remote map[string]interface{}, isConflict bool) { + parseFactory := parse.Factory{Resources: fakeResources} + parsed, err := parseFactory.CreateElement(recorded, local, remote) + Expect(err).Should(Not(HaveOccurred())) + + merged, err := parsed.Merge(instance) + if isConflict { + Expect(err).Should(HaveOccurred()) + } else { + Expect(err).ShouldNot(HaveOccurred()) + Expect(merged.Operation).Should(Equal(apply.SET)) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/type_element.go b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/type_element.go index 0462123fb..2528db87d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/apply/type_element.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/apply/type_element.go @@ -40,4 +40,17 @@ func (e TypeElement) GetValues() map[string]Element { return e.Values } +// HasConflict returns ConflictError if some elements in type conflict. +func (e TypeElement) HasConflict() error { + for _, item := range e.GetValues() { + if item, ok := item.(ConflictDetector); ok { + if err := item.HasConflict(); err != nil { + return err + } + } + } + return nil +} + var _ Element = &TypeElement{} +var _ ConflictDetector = &TypeElement{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/autoscale_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/autoscale_test.go index 86b6c1eab..918ee8354 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/autoscale_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/autoscale_test.go @@ -22,6 +22,7 @@ import ( autoscalingv1 "k8s.io/api/autoscaling/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilpointer "k8s.io/kubernetes/pkg/util/pointer" ) func TestHPAGenerate(t *testing.T) { @@ -51,14 +52,14 @@ func TestHPAGenerate(t *testing.T) { Name: "foo", }, Spec: autoscalingv1.HorizontalPodAutoscalerSpec{ - TargetCPUUtilizationPercentage: newInt32(80), + TargetCPUUtilizationPercentage: utilpointer.Int32Ptr(80), ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{ Kind: "kind", Name: "name", APIVersion: "apiVersion", }, MaxReplicas: int32(10), - MinReplicas: newInt32(1), + MinReplicas: utilpointer.Int32Ptr(1), }, }, expectErr: false, @@ -125,8 +126,3 @@ func TestHPAGenerate(t *testing.T) { } } } - -func newInt32(value int) *int32 { - v := int32(value) - return &v -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/bash_comp_utils.go b/vendor/k8s.io/kubernetes/pkg/kubectl/bash_comp_utils.go deleted file mode 100644 index 346200276..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/bash_comp_utils.go +++ /dev/null @@ -1,36 +0,0 @@ -/* -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. -*/ - -// A set of common functions needed by cmd/kubectl and pkg/kubectl packages. - -package kubectl - -import ( - "strings" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl/resource" -) - -func AddJsonFilenameFlag(cmd *cobra.Command, value *[]string, usage string) { - cmd.Flags().StringSliceVarP(value, "filename", "f", *value, usage) - annotations := make([]string, 0, len(resource.FileExtensions)) - for _, ext := range resource.FileExtensions { - annotations = append(annotations, strings.TrimLeft(ext, ".")) - } - cmd.Flags().SetAnnotation("filename", cobra.BashCompFilenameExt, annotations) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/categories/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/categories/BUILD deleted file mode 100644 index 2a7d7588e..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/categories/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["categories.go"], - importpath = "k8s.io/kubernetes/pkg/kubectl/categories", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["categories_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/rest/fake:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/categories/categories.go b/vendor/k8s.io/kubernetes/pkg/kubectl/categories/categories.go deleted file mode 100644 index 29bcc5d39..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/categories/categories.go +++ /dev/null @@ -1,192 +0,0 @@ -/* -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 categories - -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/discovery" -) - -// CategoryExpander maps category strings to GroupResouces. -// Categories are classification or 'tag' of a group of resources. -type CategoryExpander interface { - Expand(category string) ([]schema.GroupResource, bool) -} - -// SimpleCategoryExpander implements CategoryExpander interface -// using a static mapping of categories to GroupResource mapping. -type SimpleCategoryExpander struct { - Expansions map[string][]schema.GroupResource -} - -func (e SimpleCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) { - ret, ok := e.Expansions[category] - return ret, ok -} - -// discoveryCategoryExpander struct lets a REST Client wrapper (discoveryClient) to retrieve list of APIResourceList, -// and then convert to fallbackExpander -type discoveryCategoryExpander struct { - fallbackExpander CategoryExpander - discoveryClient discovery.DiscoveryInterface -} - -// NewDiscoveryCategoryExpander returns a category expander that makes use of the "categories" fields from -// the API, found through the discovery client. In case of any error or no category found (which likely -// means we're at a cluster prior to categories support, fallback to the expander provided. -func NewDiscoveryCategoryExpander(fallbackExpander CategoryExpander, client discovery.DiscoveryInterface) (discoveryCategoryExpander, error) { - if client == nil { - panic("Please provide discovery client to shortcut expander") - } - return discoveryCategoryExpander{fallbackExpander: fallbackExpander, discoveryClient: client}, nil -} - -func (e discoveryCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) { - // Get all supported resources for groups and versions from server, if no resource found, fallback anyway. - apiResourceLists, _ := e.discoveryClient.ServerResources() - if len(apiResourceLists) == 0 { - return e.fallbackExpander.Expand(category) - } - - discoveredExpansions := map[string][]schema.GroupResource{} - - for _, apiResourceList := range apiResourceLists { - gv, err := schema.ParseGroupVersion(apiResourceList.GroupVersion) - if err != nil { - return e.fallbackExpander.Expand(category) - } - // Collect GroupVersions by categories - for _, apiResource := range apiResourceList.APIResources { - if categories := apiResource.Categories; len(categories) > 0 { - for _, category := range categories { - groupResource := schema.GroupResource{ - Group: gv.Group, - Resource: apiResource.Name, - } - discoveredExpansions[category] = append(discoveredExpansions[category], groupResource) - } - } - } - } - - if len(discoveredExpansions) == 0 { - // We don't know if the server really don't have any resource with categories, - // or we're on a cluster version prior to categories support. Anyways, fallback. - return e.fallbackExpander.Expand(category) - } - - ret, ok := discoveredExpansions[category] - return ret, ok -} - -// discoveryFilteredExpander expands the given CategoryExpander (delegate) to filter group and resource returned from server -type discoveryFilteredExpander struct { - delegate CategoryExpander - - discoveryClient discovery.DiscoveryInterface -} - -// NewDiscoveryFilteredExpander returns a category expander that filters the returned groupresources -// by what the server has available -func NewDiscoveryFilteredExpander(delegate CategoryExpander, client discovery.DiscoveryInterface) (discoveryFilteredExpander, error) { - if client == nil { - panic("Please provide discovery client to shortcut expander") - } - return discoveryFilteredExpander{delegate: delegate, discoveryClient: client}, nil -} - -func (e discoveryFilteredExpander) Expand(category string) ([]schema.GroupResource, bool) { - delegateExpansion, ok := e.delegate.Expand(category) - - // Check if we have access to server resources - apiResources, err := e.discoveryClient.ServerResources() - if err != nil { - return delegateExpansion, ok - } - - availableResources, err := discovery.GroupVersionResources(apiResources) - if err != nil { - return delegateExpansion, ok - } - - available := []schema.GroupResource{} - for _, requestedResource := range delegateExpansion { - for availableResource := range availableResources { - if requestedResource.Group == availableResource.Group && - requestedResource.Resource == availableResource.Resource { - available = append(available, requestedResource) - break - } - } - } - - return available, ok -} - -// UnionCategoryExpander implements CategoryExpander interface. -// It maps given category string to union of expansions returned by all the CategoryExpanders in the list. -type UnionCategoryExpander []CategoryExpander - -func (u UnionCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) { - ret := []schema.GroupResource{} - ok := false - - // Expand the category for each CategoryExpander in the list and merge/combine the results. - for _, expansion := range u { - curr, currOk := expansion.Expand(category) - - for _, currGR := range curr { - found := false - for _, existing := range ret { - if existing == currGR { - found = true - break - } - } - if !found { - ret = append(ret, currGR) - } - } - ok = ok || currOk - } - - return ret, ok -} - -// legacyUserResources are the resource names that apply to the primary, user facing resources used by -// client tools. They are in deletion-first order - dependent resources should be last. -// Should remain exported in order to expose a current list of resources to downstream -// composition that wants to build on the concept of 'all' for their CLIs. -var legacyUserResources = []schema.GroupResource{ - {Group: "", Resource: "pods"}, - {Group: "", Resource: "replicationcontrollers"}, - {Group: "", Resource: "services"}, - {Group: "apps", Resource: "statefulsets"}, - {Group: "autoscaling", Resource: "horizontalpodautoscalers"}, - {Group: "batch", Resource: "jobs"}, - {Group: "batch", Resource: "cronjobs"}, - {Group: "extensions", Resource: "daemonsets"}, - {Group: "extensions", Resource: "deployments"}, - {Group: "extensions", Resource: "replicasets"}, -} - -// LegacyCategoryExpander is the old hardcoded expansion -var LegacyCategoryExpander CategoryExpander = SimpleCategoryExpander{ - Expansions: map[string][]schema.GroupResource{ - "all": legacyUserResources, - }, -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/categories/categories_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/categories/categories_test.go deleted file mode 100644 index 5344bad22..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/categories/categories_test.go +++ /dev/null @@ -1,186 +0,0 @@ -/* -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 categories - -import ( - "reflect" - "testing" - - "github.com/googleapis/gnostic/OpenAPIv2" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/version" - "k8s.io/client-go/discovery" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" -) - -func TestCategoryExpansion(t *testing.T) { - tests := []struct { - name string - arg string - - expected []schema.GroupResource - expectedOk bool - }{ - { - name: "no-replacement", - arg: "service", - expected: nil, - }, - { - name: "all-replacement", - arg: "all", - expected: []schema.GroupResource{ - {Resource: "pods"}, - {Resource: "replicationcontrollers"}, - {Resource: "services"}, - {Resource: "statefulsets", Group: "apps"}, - {Resource: "horizontalpodautoscalers", Group: "autoscaling"}, - {Resource: "jobs", Group: "batch"}, - {Resource: "cronjobs", Group: "batch"}, - {Resource: "daemonsets", Group: "extensions"}, - {Resource: "deployments", Group: "extensions"}, - {Resource: "replicasets", Group: "extensions"}, - }, - expectedOk: true, - }, - } - - for _, test := range tests { - actual, actualOk := LegacyCategoryExpander.Expand(test.arg) - if e, a := test.expected, actual; !reflect.DeepEqual(e, a) { - t.Errorf("%s: expected %s, got %s", test.name, e, a) - } - if e, a := test.expectedOk, actualOk; e != a { - t.Errorf("%s: expected %v, got %v", test.name, e, a) - } - } -} - -func TestDiscoveryCategoryExpander(t *testing.T) { - tests := []struct { - category string - serverResponse []*metav1.APIResourceList - expected []schema.GroupResource - }{ - { - category: "all", - serverResponse: []*metav1.APIResourceList{ - { - GroupVersion: "batch/v1", - APIResources: []metav1.APIResource{ - { - Name: "jobs", - ShortNames: []string{"jz"}, - Categories: []string{"all"}, - }, - }, - }, - }, - expected: []schema.GroupResource{ - { - Group: "batch", - Resource: "jobs", - }, - }, - }, - { - category: "all", - serverResponse: []*metav1.APIResourceList{ - { - GroupVersion: "batch/v1", - APIResources: []metav1.APIResource{ - { - Name: "jobs", - ShortNames: []string{"jz"}, - }, - }, - }, - }, - }, - { - category: "targaryens", - serverResponse: []*metav1.APIResourceList{ - { - GroupVersion: "batch/v1", - APIResources: []metav1.APIResource{ - { - Name: "jobs", - ShortNames: []string{"jz"}, - Categories: []string{"all"}, - }, - }, - }, - }, - }, - } - - dc := &fakeDiscoveryClient{} - for _, test := range tests { - dc.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { - return test.serverResponse, nil - } - expander, err := NewDiscoveryCategoryExpander(SimpleCategoryExpander{}, dc) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - expanded, _ := expander.Expand(test.category) - if !reflect.DeepEqual(expanded, test.expected) { - t.Errorf("expected %v, got %v", test.expected, expanded) - } - } - -} - -type fakeDiscoveryClient struct { - serverResourcesHandler func() ([]*metav1.APIResourceList, error) -} - -var _ discovery.DiscoveryInterface = &fakeDiscoveryClient{} - -func (c *fakeDiscoveryClient) RESTClient() restclient.Interface { - return &fake.RESTClient{} -} - -func (c *fakeDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { - return nil, nil -} - -func (c *fakeDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - return &metav1.APIResourceList{}, nil -} - -func (c *fakeDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { - return c.serverResourcesHandler() -} - -func (c *fakeDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - return nil, nil -} - -func (c *fakeDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { - return nil, nil -} - -func (c *fakeDiscoveryClient) ServerVersion() (*version.Info, error) { - return &version.Info{}, nil -} - -func (c *fakeDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { - return &openapi_v2.Document{}, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/BUILD index 45707367c..0eac87025 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/BUILD @@ -9,6 +9,7 @@ go_library( srcs = [ "alpha.go", "annotate.go", + "apiresources.go", "apiversions.go", "apply.go", "apply_edit_last_applied.go", @@ -23,22 +24,8 @@ go_library( "completion.go", "convert.go", "cp.go", - "create.go", - "create_clusterrole.go", - "create_clusterrolebinding.go", - "create_configmap.go", - "create_deployment.go", - "create_job.go", - "create_namespace.go", - "create_pdb.go", - "create_priorityclass.go", - "create_quota.go", - "create_role.go", - "create_rolebinding.go", - "create_secret.go", - "create_service.go", - "create_serviceaccount.go", "delete.go", + "delete_flags.go", "describe.go", "diff.go", "drain.go", @@ -74,30 +61,37 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", + "//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", "//pkg/kubectl:go_default_library", "//pkg/kubectl/apply/parse:go_default_library", "//pkg/kubectl/apply/strategy:go_default_library", "//pkg/kubectl/cmd/auth:go_default_library", "//pkg/kubectl/cmd/config:go_default_library", - "//pkg/kubectl/cmd/resource:go_default_library", + "//pkg/kubectl/cmd/create:go_default_library", + "//pkg/kubectl/cmd/get:go_default_library", "//pkg/kubectl/cmd/rollout:go_default_library", + "//pkg/kubectl/cmd/scalejob:go_default_library", "//pkg/kubectl/cmd/set:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util/editor:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library", + "//pkg/kubectl/cmd/wait:go_default_library", "//pkg/kubectl/explain:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/metricsutil:go_default_library", "//pkg/kubectl/plugins:go_default_library", + "//pkg/kubectl/polymorphichelpers:go_default_library", "//pkg/kubectl/proxy:go_default_library", - "//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/util:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", "//pkg/kubectl/util/term:go_default_library", + "//pkg/kubectl/validation:go_default_library", "//pkg/printers:go_default_library", - "//pkg/printers/internalversion:go_default_library", "//pkg/util/interrupt:go_default_library", "//pkg/util/taints:go_default_library", "//pkg/version:go_default_library", @@ -111,16 +105,15 @@ go_library( "//vendor/github.com/renstrom/dedent:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", + "//vendor/k8s.io/api/autoscaling/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme: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/runtime:go_default_library", @@ -134,6 +127,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", @@ -141,11 +135,13 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", + "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/scale:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/k8s.io/client-go/tools/portforward:go_default_library", "//vendor/k8s.io/client-go/tools/remotecommand:go_default_library", @@ -165,24 +161,10 @@ go_test( "apply_test.go", "attach_test.go", "clusterinfo_dump_test.go", + "cmd_printing_test.go", "cmd_test.go", "convert_test.go", "cp_test.go", - "create_clusterrole_test.go", - "create_clusterrolebinding_test.go", - "create_configmap_test.go", - "create_deployment_test.go", - "create_job_test.go", - "create_namespace_test.go", - "create_pdb_test.go", - "create_priorityclass_test.go", - "create_quota_test.go", - "create_role_test.go", - "create_rolebinding_test.go", - "create_secret_test.go", - "create_service_test.go", - "create_serviceaccount_test.go", - "create_test.go", "delete_test.go", "describe_test.go", "diff_test.go", @@ -206,7 +188,6 @@ go_test( data = [ "testdata", "//api/openapi-spec:swagger-spec", - "//examples:config", "//test/e2e/testing-manifests:all-srcs", "//test/fixtures", ], @@ -218,29 +199,25 @@ go_test( "//pkg/apis/batch:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/kubectl:go_default_library", - "//pkg/kubectl/cmd/resource:go_default_library", + "//pkg/client/clientset_generated/internalclientset:go_default_library", + "//pkg/kubectl/cmd/create:go_default_library", "//pkg/kubectl/cmd/testing:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/plugins:go_default_library", - "//pkg/kubectl/resource:go_default_library", + "//pkg/kubectl/polymorphichelpers:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", "//pkg/kubectl/util/term:go_default_library", "//pkg/printers:go_default_library", - "//pkg/util/strings:go_default_library", "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", - "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/gopkg.in/yaml.v2:go_default_library", - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/api/rbac/v1:go_default_library", - "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -256,8 +233,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch/testing:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/client-go/dynamic:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", + "//vendor/k8s.io/client-go/dynamic/fake:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest/fake:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", @@ -281,13 +257,16 @@ filegroup( ":package-srcs", "//pkg/kubectl/cmd/auth:all-srcs", "//pkg/kubectl/cmd/config:all-srcs", - "//pkg/kubectl/cmd/resource:all-srcs", + "//pkg/kubectl/cmd/create:all-srcs", + "//pkg/kubectl/cmd/get:all-srcs", "//pkg/kubectl/cmd/rollout:all-srcs", + "//pkg/kubectl/cmd/scalejob:all-srcs", "//pkg/kubectl/cmd/set:all-srcs", "//pkg/kubectl/cmd/templates:all-srcs", "//pkg/kubectl/cmd/testdata/edit:all-srcs", "//pkg/kubectl/cmd/testing:all-srcs", "//pkg/kubectl/cmd/util:all-srcs", + "//pkg/kubectl/cmd/wait:all-srcs", ], tags = ["automanaged"], visibility = [ diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/alpha.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/alpha.go index afbe7347d..bd7f34e66 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/alpha.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/alpha.go @@ -17,17 +17,16 @@ limitations under the License. package cmd import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) // NewCmdAlpha creates a command that acts as an alternate root command for features in alpha -func NewCmdAlpha(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command { +func NewCmdAlpha(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "alpha", Short: i18n.T("Commands for features in alpha"), @@ -37,7 +36,7 @@ func NewCmdAlpha(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Com // Alpha commands should be added here. As features graduate from alpha they should move // from here to the CommandGroups defined by NewKubeletCommand() in cmd.go. //cmd.AddCommand(NewCmdDebug(f, in, out, err)) - cmd.AddCommand(NewCmdDiff(f, out, err)) + cmd.AddCommand(NewCmdDiff(f, streams)) // NewKubeletCommand() will hide the alpha command if it has no subcommands. Overriding // the help function ensures a reasonable message if someone types the hidden command anyway. diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/annotate.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/annotate.go index fcd04f267..7df91f9b7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/annotate.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/annotate.go @@ -34,32 +34,44 @@ import ( "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) // AnnotateOptions have the data required to perform the annotate operation type AnnotateOptions struct { + PrintFlags *genericclioptions.PrintFlags + PrintObj printers.ResourcePrinterFunc + // Filename options resource.FilenameOptions + RecordFlags *genericclioptions.RecordFlags // Common user flags - overwrite bool - local bool - dryrun bool - all bool - resourceVersion string - selector string - outputFormat string - recordChangeCause bool + overwrite bool + local bool + dryrun bool + all bool + resourceVersion string + selector string + fieldSelector string + outputFormat string // results of arg parsing - resources []string - newAnnotations map[string]string - removeAnnotations []string - - // Common share fields - out io.Writer + resources []string + newAnnotations map[string]string + removeAnnotations []string + Recorder genericclioptions.Recorder + namespace string + enforceNamespace bool + builder *resource.Builder + unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) + includeUninitialized bool + + genericclioptions.IOStreams } var ( @@ -69,7 +81,7 @@ var ( All Kubernetes objects support the ability to store additional data with the object as annotations. Annotations are key/value pairs that can be larger than labels and include arbitrary string values such as structured JSON. Tools and system extensions may use - annotations to store their own data. + annotations to store their own data. Attempting to set an annotation that already exists will fail unless --overwrite is set. If --resource-version is specified and does not match the current resource version on @@ -97,50 +109,81 @@ var ( kubectl annotate pods foo description-`)) ) -func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &AnnotateOptions{} - validArgs := cmdutil.ValidArgList(f) +func NewAnnotateOptions(ioStreams genericclioptions.IOStreams) *AnnotateOptions { + return &AnnotateOptions{ + PrintFlags: genericclioptions.NewPrintFlags("annotated").WithTypeSetter(scheme.Scheme), + + RecordFlags: genericclioptions.NewRecordFlags(), + Recorder: genericclioptions.NoopRecorder{}, + IOStreams: ioStreams, + } +} + +func NewCmdAnnotate(parent string, f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewAnnotateOptions(ioStreams) cmd := &cobra.Command{ Use: "annotate [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]", DisableFlagsInUseLine: true, Short: i18n.T("Update the annotations on a resource"), - Long: annotateLong + "\n\n" + cmdutil.ValidResourceTypeList(f), + Long: annotateLong + "\n\n" + cmdutil.SuggestApiResources(parent), Example: annotateExample, Run: func(cmd *cobra.Command, args []string) { - if err := options.Complete(out, cmd, args); err != nil { - cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err)) - } - if err := options.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err)) - } - cmdutil.CheckErr(options.RunAnnotate(f, cmd)) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunAnnotate()) }, - ValidArgs: validArgs, - ArgAliases: kubectl.ResourceAliases(validArgs), } - cmdutil.AddPrinterFlags(cmd) + + // bind flag structs + o.RecordFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) - cmd.Flags().BoolVar(&options.overwrite, "overwrite", options.overwrite, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.") - cmd.Flags().BoolVar(&options.local, "local", options.local, "If true, annotation will NOT contact api-server but run locally.") - cmd.Flags().StringVarP(&options.selector, "selector", "l", options.selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).") - cmd.Flags().BoolVar(&options.all, "all", options.all, "Select all resources, including uninitialized ones, in the namespace of the specified resource types.") - cmd.Flags().StringVar(&options.resourceVersion, "resource-version", options.resourceVersion, i18n.T("If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")) + cmd.Flags().BoolVar(&o.overwrite, "overwrite", o.overwrite, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.") + cmd.Flags().BoolVar(&o.local, "local", o.local, "If true, annotation will NOT contact api-server but run locally.") + cmd.Flags().StringVarP(&o.selector, "selector", "l", o.selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).") + cmd.Flags().StringVar(&o.fieldSelector, "field-selector", o.fieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") + cmd.Flags().BoolVar(&o.all, "all", o.all, "Select all resources, including uninitialized ones, in the namespace of the specified resource types.") + cmd.Flags().StringVar(&o.resourceVersion, "resource-version", o.resourceVersion, i18n.T("If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")) usage := "identifying the resource to update the annotation" - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) cmdutil.AddDryRunFlag(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) return cmd } // Complete adapts from the command line args and factory to the data required. -func (o *AnnotateOptions) Complete(out io.Writer, cmd *cobra.Command, args []string) (err error) { - o.out = out +func (o *AnnotateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + o.outputFormat = cmdutil.GetFlagString(cmd, "output") o.dryrun = cmdutil.GetDryRunFlag(cmd) - o.recordChangeCause = cmdutil.GetRecordFlag(cmd) + + if o.dryrun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObj = func(obj runtime.Object, out io.Writer) error { + return printer.PrintObj(obj, out) + } + + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + o.includeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, false) + o.builder = f.NewBuilder() + o.unstructuredClientForMapping = f.UnstructuredClientForMapping // retrieves resource and annotation args from args // also checks args to verify that all resources are specified before annotations @@ -150,7 +193,11 @@ func (o *AnnotateOptions) Complete(out io.Writer, cmd *cobra.Command, args []str } o.resources = resources o.newAnnotations, o.removeAnnotations, err = parseAnnotations(annotationArgs) - return err + if err != nil { + return err + } + + return nil } // Validate checks to the AnnotateOptions to see if there is sufficient information run the command. @@ -158,6 +205,9 @@ func (o AnnotateOptions) Validate() error { if o.all && len(o.selector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") } + if o.all && len(o.fieldSelector) > 0 { + return fmt.Errorf("cannot set --all and --field-selector at the same time") + } if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { return fmt.Errorf("one or more resources must be specified as or /") } @@ -168,26 +218,19 @@ func (o AnnotateOptions) Validate() error { } // RunAnnotate does the work -func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) error { - namespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - changeCause := f.Command(cmd, false) - - includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) - b := f.NewBuilder(). +func (o AnnotateOptions) RunAnnotate() error { + b := o.builder. Unstructured(). LocalParam(o.local). ContinueOnError(). - NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &o.FilenameOptions). - IncludeUninitialized(includeUninitialized). + NamespaceParam(o.namespace).DefaultNamespace(). + FilenameParam(o.enforceNamespace, &o.FilenameOptions). + IncludeUninitialized(o.includeUninitialized). Flatten() if !o.local { b = b.LabelSelectorParam(o.selector). + FieldSelectorParam(o.fieldSelector). ResourceTypeOrNameArgs(o.all, o.resources...). Latest() } @@ -214,12 +257,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro } var outputObj runtime.Object - var obj runtime.Object - - obj, err = info.Mapping.ConvertToVersion(info.Object, info.Mapping.GroupVersionKind.GroupVersion()) - if err != nil { - return err - } + obj := info.Object if o.dryrun || o.local { if err := o.updateAnnotations(obj); err != nil { @@ -232,9 +270,8 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro if err != nil { return err } - // If we should record change-cause, add it to new annotations - if cmdutil.ContainsChangeCause(info) || o.recordChangeCause { - o.newAnnotations[kubectl.ChangeCauseAnnotation] = changeCause + if err := o.Recorder.Record(info.Object); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } if err := o.updateAnnotations(obj); err != nil { return err @@ -250,7 +287,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro } mapping := info.ResourceMapping() - client, err := f.UnstructuredClientForMapping(mapping) + client, err := o.unstructuredClientForMapping(mapping) if err != nil { return err } @@ -266,11 +303,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro } } - if len(o.outputFormat) > 0 { - return cmdutil.PrintObject(cmd, outputObj, o.out) - } - cmdutil.PrintSuccess(false, o.out, info.Object, o.dryrun, "annotated") - return nil + return o.PrintObj(outputObj, o.Out) }) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/annotate_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/annotate_test.go index 409070e26..172eb2330 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/annotate_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/annotate_test.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "bytes" "net/http" "reflect" "strings" @@ -30,6 +29,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -418,21 +418,20 @@ func TestAnnotateErrors(t *testing.T) { for k, testCase := range testCases { t.Run(k, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - cmd.SetOutput(buf) + iostreams, _, bufOut, bufErr := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate("kubectl", tf, iostreams) + cmd.SetOutput(bufOut) for k, v := range testCase.flags { cmd.Flags().Set(k, v) } - options := &AnnotateOptions{} - err := options.Complete(buf, cmd, testCase.args) + options := NewAnnotateOptions(iostreams) + err := options.Complete(tf, cmd, testCase.args) if err == nil { err = options.Validate() } @@ -440,8 +439,11 @@ func TestAnnotateErrors(t *testing.T) { t.Errorf("%s: unexpected error: %v", k, err) return } - if buf.Len() > 0 { - t.Errorf("buffer should be empty: %s", string(buf.Bytes())) + if bufOut.Len() > 0 { + t.Errorf("buffer should be empty: %s", string(bufOut.Bytes())) + } + if bufErr.Len() > 0 { + t.Errorf("buffer should be empty: %s", string(bufErr.Bytes())) } }) } @@ -450,10 +452,10 @@ func TestAnnotateErrors(t *testing.T) { func TestAnnotateObject(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"}, @@ -482,21 +484,20 @@ func TestAnnotateObject(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - cmd.SetOutput(buf) - options := &AnnotateOptions{} + iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate("kubectl", tf, iostreams) + cmd.SetOutput(bufOut) + options := NewAnnotateOptions(iostreams) args := []string{"pods/foo", "a=b", "c-"} - if err := options.Complete(buf, cmd, args); err != nil { + if err := options.Complete(tf, cmd, args); err != nil { t.Fatalf("unexpected error: %v", err) } if err := options.Validate(); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(tf, cmd); err != nil { + if err := options.RunAnnotate(); err != nil { t.Fatalf("unexpected error: %v", err) } } @@ -504,10 +505,10 @@ func TestAnnotateObject(t *testing.T) { func TestAnnotateObjectFromFile(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"}, @@ -536,28 +537,27 @@ func TestAnnotateObjectFromFile(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - cmd.SetOutput(buf) - options := &AnnotateOptions{} + iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate("kubectl", tf, iostreams) + cmd.SetOutput(bufOut) + options := NewAnnotateOptions(iostreams) options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} args := []string{"a=b", "c-"} - if err := options.Complete(buf, cmd, args); err != nil { + if err := options.Complete(tf, cmd, args); err != nil { t.Fatalf("unexpected error: %v", err) } if err := options.Validate(); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(tf, cmd); err != nil { + if err := options.RunAnnotate(); err != nil { t.Fatalf("unexpected error: %v", err) } } func TestAnnotateLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -568,21 +568,21 @@ func TestAnnotateLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - options := &AnnotateOptions{local: true} + iostreams, _, _, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate("kubectl", tf, iostreams) + options := NewAnnotateOptions(iostreams) + options.local = true options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} args := []string{"a=b"} - if err := options.Complete(buf, cmd, args); err != nil { + if err := options.Complete(tf, cmd, args); err != nil { t.Fatalf("unexpected error: %v", err) } if err := options.Validate(); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(tf, cmd); err != nil { + if err := options.RunAnnotate(); err != nil { t.Fatalf("unexpected error: %v", err) } } @@ -590,10 +590,10 @@ func TestAnnotateLocal(t *testing.T) { func TestAnnotateMultipleObjects(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"}, NegotiatedSerializer: unstructuredSerializer, @@ -623,21 +623,21 @@ func TestAnnotateMultipleObjects(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - cmd.SetOutput(buf) - options := &AnnotateOptions{all: true} + iostreams, _, _, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate("kubectl", tf, iostreams) + cmd.SetOutput(iostreams.Out) + options := NewAnnotateOptions(iostreams) + options.all = true args := []string{"pods", "a=b", "c-"} - if err := options.Complete(buf, cmd, args); err != nil { + if err := options.Complete(tf, cmd, args); err != nil { t.Fatalf("unexpected error: %v", err) } if err := options.Validate(); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(tf, cmd); err != nil { + if err := options.RunAnnotate(); err != nil { t.Fatalf("unexpected error: %v", err) } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiresources.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiresources.go new file mode 100644 index 000000000..982bbb02f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiresources.go @@ -0,0 +1,229 @@ +/* +Copyright 2018 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 cmd + +import ( + "fmt" + "io" + "sort" + "strings" + + "github.com/spf13/cobra" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/printers" +) + +var ( + apiresourcesExample = templates.Examples(` + # Print the supported API Resources + kubectl api-resources + + # Print the supported API Resources with more information + kubectl api-resources -o wide + + # Print the supported namespaced resources + kubectl api-resources --namespaced=true + + # Print the supported non-namespaced resources + kubectl api-resources --namespaced=false + + # Print the supported API Resources with specific APIGroup + kubectl api-resources --api-group=extensions`) +) + +// ApiResourcesOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of +// referencing the cmd.Flags() +type ApiResourcesOptions struct { + Output string + APIGroup string + Namespaced bool + Verbs []string + NoHeaders bool + Cached bool + + genericclioptions.IOStreams +} + +// groupResource contains the APIGroup and APIResource +type groupResource struct { + APIGroup string + APIResource metav1.APIResource +} + +func NewAPIResourceOptions(ioStreams genericclioptions.IOStreams) *ApiResourcesOptions { + return &ApiResourcesOptions{ + IOStreams: ioStreams, + Namespaced: true, + } +} + +func NewCmdApiResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewAPIResourceOptions(ioStreams) + + cmd := &cobra.Command{ + Use: "api-resources", + Short: "Print the supported API resources on the server", + Long: "Print the supported API resources on the server", + Example: apiresourcesExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(o.Validate(cmd)) + cmdutil.CheckErr(o.RunApiResources(cmd, f)) + }, + } + + cmd.Flags().BoolVar(&o.NoHeaders, "no-headers", o.NoHeaders, "When using the default or custom-column output format, don't print headers (default print headers).") + cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, "Output format. One of: wide|name.") + + cmd.Flags().StringVar(&o.APIGroup, "api-group", o.APIGroup, "Limit to resources in the specified API group.") + cmd.Flags().BoolVar(&o.Namespaced, "namespaced", o.Namespaced, "If false, non-namespaced resources will be returned, otherwise returning namespaced resources by default.") + cmd.Flags().StringSliceVar(&o.Verbs, "verbs", o.Verbs, "Limit to resources that support the specified verbs.") + cmd.Flags().BoolVar(&o.Cached, "cached", o.Cached, "Use the cached list of resources if available.") + return cmd +} + +func (o *ApiResourcesOptions) Validate(cmd *cobra.Command) error { + supportedOutputTypes := sets.NewString("", "wide", "name") + if !supportedOutputTypes.Has(o.Output) { + return fmt.Errorf("--output %v is not available", o.Output) + } + return nil +} + +func (o *ApiResourcesOptions) RunApiResources(cmd *cobra.Command, f cmdutil.Factory) error { + w := printers.GetNewTabWriter(o.Out) + defer w.Flush() + + discoveryclient, err := f.ToDiscoveryClient() + if err != nil { + return err + } + + if !o.Cached { + // Always request fresh data from the server + discoveryclient.Invalidate() + } + + lists, err := discoveryclient.ServerPreferredResources() + if err != nil { + return err + } + + resources := []groupResource{} + + groupChanged := cmd.Flags().Changed("api-group") + nsChanged := cmd.Flags().Changed("namespaced") + + for _, list := range lists { + if len(list.APIResources) == 0 { + continue + } + gv, err := schema.ParseGroupVersion(list.GroupVersion) + if err != nil { + continue + } + for _, resource := range list.APIResources { + if len(resource.Verbs) == 0 { + continue + } + // filter apiGroup + if groupChanged && o.APIGroup != gv.Group { + continue + } + // filter namespaced + if nsChanged && o.Namespaced != resource.Namespaced { + continue + } + // filter to resources that support the specified verbs + if len(o.Verbs) > 0 && !sets.NewString(resource.Verbs...).HasAll(o.Verbs...) { + continue + } + resources = append(resources, groupResource{ + APIGroup: gv.Group, + APIResource: resource, + }) + } + } + + if o.NoHeaders == false && o.Output != "name" { + if err = printContextHeaders(w, o.Output); err != nil { + return err + } + } + + sort.Stable(sortableGroupResource(resources)) + for _, r := range resources { + switch o.Output { + case "name": + name := r.APIResource.Name + if len(r.APIGroup) > 0 { + name += "." + r.APIGroup + } + if _, err := fmt.Fprintf(w, "%s\n", name); err != nil { + return err + } + case "wide": + if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%s\t%v\n", + r.APIResource.Name, + strings.Join(r.APIResource.ShortNames, ","), + r.APIGroup, + r.APIResource.Namespaced, + r.APIResource.Kind, + r.APIResource.Verbs); err != nil { + return err + } + case "": + if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%s\n", + r.APIResource.Name, + strings.Join(r.APIResource.ShortNames, ","), + r.APIGroup, + r.APIResource.Namespaced, + r.APIResource.Kind); err != nil { + return err + } + } + } + return nil +} + +func printContextHeaders(out io.Writer, output string) error { + columnNames := []string{"NAME", "SHORTNAMES", "APIGROUP", "NAMESPACED", "KIND"} + if output == "wide" { + columnNames = append(columnNames, "VERBS") + } + _, err := fmt.Fprintf(out, "%s\n", strings.Join(columnNames, "\t")) + return err +} + +type sortableGroupResource []groupResource + +func (s sortableGroupResource) Len() int { return len(s) } +func (s sortableGroupResource) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s sortableGroupResource) Less(i, j int) bool { + ret := strings.Compare(s[i].APIGroup, s[j].APIGroup) + if ret > 0 { + return false + } else if ret == 0 { + return strings.Compare(s[i].APIResource.Name, s[j].APIResource.Name) < 0 + } + return true +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiversions.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiversions.go index 39d84ab11..516bbfcc2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiversions.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiversions.go @@ -18,14 +18,15 @@ package cmd import ( "fmt" - "io" "sort" "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/discovery" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -35,37 +36,54 @@ var ( kubectl api-versions`)) ) -func NewCmdApiVersions(f cmdutil.Factory, out io.Writer) *cobra.Command { +type ApiVersionsOptions struct { + discoveryClient discovery.CachedDiscoveryInterface + + genericclioptions.IOStreams +} + +func NewApiVersionsOptions(ioStreams genericclioptions.IOStreams) *ApiVersionsOptions { + return &ApiVersionsOptions{ + IOStreams: ioStreams, + } +} + +func NewCmdApiVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewApiVersionsOptions(ioStreams) cmd := &cobra.Command{ Use: "api-versions", Short: "Print the supported API versions on the server, in the form of \"group/version\"", Long: "Print the supported API versions on the server, in the form of \"group/version\"", Example: apiversionsExample, Run: func(cmd *cobra.Command, args []string) { - err := RunApiVersions(f, out) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f)) + cmdutil.CheckErr(o.RunApiVersions()) }, } return cmd } -func RunApiVersions(f cmdutil.Factory, w io.Writer) error { - discoveryclient, err := f.DiscoveryClient() +func (o *ApiVersionsOptions) Complete(f cmdutil.Factory) error { + var err error + o.discoveryClient, err = f.ToDiscoveryClient() if err != nil { return err } + return nil +} +func (o *ApiVersionsOptions) RunApiVersions() error { // Always request fresh data from the server - discoveryclient.Invalidate() + o.discoveryClient.Invalidate() - groupList, err := discoveryclient.ServerGroups() + groupList, err := o.discoveryClient.ServerGroups() if err != nil { return fmt.Errorf("Couldn't get available api versions from server: %v\n", err) } apiVersions := metav1.ExtractGroupVersions(groupList) sort.Strings(apiVersions) for _, v := range apiVersions { - fmt.Fprintln(w, v) + fmt.Fprintln(o.Out, v) } return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply.go index 71486bdac..976915a45 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply.go @@ -26,9 +26,11 @@ import ( "github.com/jonboulle/clockwork" "github.com/spf13/cobra" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" @@ -37,29 +39,52 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/dynamic" oapi "k8s.io/kube-openapi/pkg/util/proto" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "k8s.io/kubernetes/pkg/kubectl/validation" ) type ApplyOptions struct { - FilenameOptions resource.FilenameOptions - Selector string - Force bool - Prune bool - Cascade bool - GracePeriod int - PruneResources []pruneResource - Timeout time.Duration - cmdBaseName string - all bool + RecordFlags *genericclioptions.RecordFlags + Recorder genericclioptions.Recorder + + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) + + DeleteFlags *DeleteFlags + DeleteOptions *DeleteOptions + + Selector string + DryRun bool + Prune bool + PruneResources []pruneResource + cmdBaseName string + All bool + Overwrite bool + OpenApiPatch bool + PruneWhitelist []string + ShouldIncludeUninitialized bool + + Validator validation.Schema + Builder *resource.Builder + Mapper meta.RESTMapper + DynamicClient dynamic.Interface + OpenAPISchema openapi.Resources + + Namespace string + EnforceNamespace bool + + genericclioptions.IOStreams } const ( @@ -98,12 +123,27 @@ var ( warningNoLastAppliedConfigAnnotation = "Warning: %[1]s apply should be used on resource created by either %[1]s create --save-config or %[1]s apply\n" ) -func NewCmdApply(baseName string, f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - var options ApplyOptions +func NewApplyOptions(ioStreams genericclioptions.IOStreams) *ApplyOptions { + return &ApplyOptions{ + RecordFlags: genericclioptions.NewRecordFlags(), + DeleteFlags: NewDeleteFlags("that contains the configuration to apply"), + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme), + + Overwrite: true, + OpenApiPatch: true, + + Recorder: genericclioptions.NoopRecorder{}, + + IOStreams: ioStreams, + } +} + +func NewCmdApply(baseName string, f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewApplyOptions(ioStreams) // Store baseName for use in printing warnings / messages involving the base command name. // This is useful for downstream command that wrap this one. - options.cmdBaseName = baseName + o.cmdBaseName = baseName cmd := &cobra.Command{ Use: "apply -f FILENAME", @@ -112,40 +152,85 @@ func NewCmdApply(baseName string, f cmdutil.Factory, out, errOut io.Writer) *cob Long: applyLong, Example: applyExample, Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(o.Complete(f, cmd)) cmdutil.CheckErr(validateArgs(cmd, args)) - cmdutil.CheckErr(validatePruneAll(options.Prune, options.all, options.Selector)) - cmdutil.CheckErr(RunApply(f, cmd, out, errOut, &options)) + cmdutil.CheckErr(validatePruneAll(o.Prune, o.All, o.Selector)) + cmdutil.CheckErr(o.Run()) }, } - usage := "that contains the configuration to apply" - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) + // bind flag structs + o.DeleteFlags.AddFlags(cmd) + o.RecordFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) + cmd.MarkFlagRequired("filename") - cmd.Flags().Bool("overwrite", true, "Automatically resolve conflicts between the modified and live configuration by using values from the modified configuration") - cmd.Flags().BoolVar(&options.Prune, "prune", false, "Automatically delete resource objects, including the uninitialized ones, that do not appear in the configs and are created by either apply or create --save-config. Should be used with either -l or --all.") - cmd.Flags().BoolVar(&options.Cascade, "cascade", true, "Only relevant during a prune or a force apply. If true, cascade the deletion of the resources managed by pruned or deleted resources (e.g. Pods created by a ReplicationController).") - cmd.Flags().IntVar(&options.GracePeriod, "grace-period", -1, "Only relevant during a prune or a force apply. Period of time in seconds given to pruned or deleted resources to terminate gracefully. Ignored if negative.") - cmd.Flags().BoolVar(&options.Force, "force", false, fmt.Sprintf("Delete and re-create the specified resource, when PATCH encounters conflict and has retried for %d times.", maxPatchRetry)) - cmd.Flags().DurationVar(&options.Timeout, "timeout", 0, "Only relevant during a force apply. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object. Any other values should contain a corresponding time unit (e.g. 1s, 2m, 3h).") + cmd.Flags().BoolVar(&o.Overwrite, "overwrite", o.Overwrite, "Automatically resolve conflicts between the modified and live configuration by using values from the modified configuration") + cmd.Flags().BoolVar(&o.Prune, "prune", o.Prune, "Automatically delete resource objects, including the uninitialized ones, that do not appear in the configs and are created by either apply or create --save-config. Should be used with either -l or --all.") cmdutil.AddValidateFlags(cmd) - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().BoolVar(&options.all, "all", options.all, "Select all resources in the namespace of the specified resource types.") - cmd.Flags().StringArray("prune-whitelist", []string{}, "Overwrite the default whitelist with for --prune") - cmd.Flags().Bool("openapi-patch", true, "If true, use openapi to calculate diff when the openapi presents and the resource can be found in the openapi spec. Otherwise, fall back to use baked-in types.") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&o.All, "all", o.All, "Select all resources in the namespace of the specified resource types.") + cmd.Flags().StringArrayVar(&o.PruneWhitelist, "prune-whitelist", o.PruneWhitelist, "Overwrite the default whitelist with for --prune") + cmd.Flags().BoolVar(&o.OpenApiPatch, "openapi-patch", o.OpenApiPatch, "If true, use openapi to calculate diff when the openapi presents and the resource can be found in the openapi spec. Otherwise, fall back to use baked-in types.") cmdutil.AddDryRunFlag(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) cmdutil.AddIncludeUninitializedFlag(cmd) // apply subcommands - cmd.AddCommand(NewCmdApplyViewLastApplied(f, out, errOut)) - cmd.AddCommand(NewCmdApplySetLastApplied(f, out, errOut)) - cmd.AddCommand(NewCmdApplyEditLastApplied(f, out, errOut)) + cmd.AddCommand(NewCmdApplyViewLastApplied(f, ioStreams)) + cmd.AddCommand(NewCmdApplySetLastApplied(f, ioStreams)) + cmd.AddCommand(NewCmdApplyEditLastApplied(f, ioStreams)) return cmd } +func (o *ApplyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { + o.DryRun = cmdutil.GetDryRunFlag(cmd) + + // allow for a success message operation to be specified at print time + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + + return o.PrintFlags.ToPrinter() + } + + var err error + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + + dynamicClient, err := f.DynamicClient() + if err != nil { + return err + } + o.DeleteOptions = o.DeleteFlags.ToOptions(dynamicClient, o.IOStreams) + o.ShouldIncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, o.Prune) + + o.OpenAPISchema, _ = f.OpenAPISchema() + o.Validator, err = f.Validator(cmdutil.GetFlagBool(cmd, "validate")) + o.Builder = f.NewBuilder() + o.Mapper, err = f.ToRESTMapper() + if err != nil { + return err + } + + o.DynamicClient, err = f.DynamicClient() + if err != nil { + return err + } + + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + + return nil +} + func validateArgs(cmd *cobra.Command, args []string) error { if len(args) != 0 { return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args) @@ -194,60 +279,44 @@ func parsePruneResources(mapper meta.RESTMapper, gvks []string) ([]pruneResource return pruneResources, nil } -func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, options *ApplyOptions) error { - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) - if err != nil { - return err - } - +func (o *ApplyOptions) Run() error { var openapiSchema openapi.Resources - if cmdutil.GetFlagBool(cmd, "openapi-patch") { - openapiSchema, err = f.OpenAPISchema() - if err != nil { - openapiSchema = nil - } - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err + if o.OpenApiPatch { + openapiSchema = o.OpenAPISchema } // include the uninitialized objects by default if --prune is true // unless explicitly set --include-uninitialized=false - includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, options.Prune) - r := f.NewBuilder(). + r := o.Builder. Unstructured(). - Schema(schema). + Schema(o.Validator). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &options.FilenameOptions). - LabelSelectorParam(options.Selector). - IncludeUninitialized(includeUninitialized). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.EnforceNamespace, &o.DeleteOptions.FilenameOptions). + LabelSelectorParam(o.Selector). + IncludeUninitialized(o.ShouldIncludeUninitialized). Flatten(). Do() if err := r.Err(); err != nil { return err } - if options.Prune { - options.PruneResources, err = parsePruneResources(r.Mapper().RESTMapper, cmdutil.GetFlagStringArray(cmd, "prune-whitelist")) + var err error + if o.Prune { + o.PruneResources, err = parsePruneResources(o.Mapper, o.PruneWhitelist) if err != nil { return err } } - dryRun := cmdutil.GetDryRunFlag(cmd) - output := cmdutil.GetFlagString(cmd, "output") + output := *o.PrintFlags.OutputFormat shortOutput := output == "name" - encoder := scheme.DefaultJSONEncoder() - deserializer := scheme.Codecs.UniversalDeserializer() - mapper := r.Mapper().RESTMapper - visitedUids := sets.NewString() visitedNamespaces := sets.NewString() + var objs []runtime.Object + count := 0 err = r.Visit(func(info *resource.Info, err error) error { if err != nil { @@ -258,145 +327,185 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti visitedNamespaces.Insert(info.Namespace) } - // Add change-cause annotation to resource info if it should be recorded - if cmdutil.ShouldRecord(cmd, info) { - recordInObj := info.Object - if err := cmdutil.RecordChangeCause(recordInObj, f.Command(cmd, false)); err != nil { - glog.V(4).Infof("error recording current command: %v", err) - } + if err := o.Recorder.Record(info.Object); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } // Get the modified configuration of the object. Embed the result // as an annotation in the modified configuration, so that it will appear // in the patch sent to the server. - modified, err := kubectl.GetModifiedConfiguration(info, true, encoder) + modified, err := kubectl.GetModifiedConfiguration(info.Object, true, unstructured.UnstructuredJSONScheme) if err != nil { - return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving modified configuration from:\n%v\nfor:", info), info.Source, err) + return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving modified configuration from:\n%s\nfor:", info.String()), info.Source, err) } + // Print object only if output format other than "name" is specified + printObject := len(output) > 0 && !shortOutput + if err := info.Get(); err != nil { if !errors.IsNotFound(err) { - return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) + return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%s\nfrom server for:", info.String()), info.Source, err) } // Create the resource if it doesn't exist // First, update the annotation used by kubectl apply - if err := kubectl.CreateApplyAnnotation(info, encoder); err != nil { + if err := kubectl.CreateApplyAnnotation(info.Object, unstructured.UnstructuredJSONScheme); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } - if !dryRun { + if !o.DryRun { // Then create the resource and skip the three-way merge - if err := createAndRefresh(info); err != nil { + obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object) + if err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } - if uid, err := info.Mapping.UID(info.Object); err != nil { + info.Refresh(obj, true) + metadata, err := meta.Accessor(info.Object) + if err != nil { return err - } else { - visitedUids.Insert(string(uid)) } + visitedUids.Insert(string(metadata.GetUID())) } count++ - if len(output) > 0 && !shortOutput { - return cmdutil.PrintObject(cmd, info.Object, out) + + if printObject { + objs = append(objs, info.Object) + return nil } - cmdutil.PrintSuccess(shortOutput, out, info.Object, dryRun, "created") - return nil + + printer, err := o.ToPrinter("created") + if err != nil { + return err + } + return printer.PrintObj(info.Object, o.Out) } - if !dryRun { - annotationMap, err := info.Mapping.MetadataAccessor.Annotations(info.Object) + if !o.DryRun { + metadata, err := meta.Accessor(info.Object) if err != nil { return err } + + annotationMap := metadata.GetAnnotations() if _, ok := annotationMap[api.LastAppliedConfigAnnotation]; !ok { - fmt.Fprintf(errOut, warningNoLastAppliedConfigAnnotation, options.cmdBaseName) + fmt.Fprintf(o.ErrOut, warningNoLastAppliedConfigAnnotation, o.cmdBaseName) } - overwrite := cmdutil.GetFlagBool(cmd, "overwrite") + helper := resource.NewHelper(info.Client, info.Mapping) patcher := &patcher{ - encoder: encoder, - decoder: deserializer, mapping: info.Mapping, helper: helper, - clientFunc: f.UnstructuredClientForMapping, - clientsetFunc: f.ClientSet, - overwrite: overwrite, + dynamicClient: o.DynamicClient, + overwrite: o.Overwrite, backOff: clockwork.NewRealClock(), - force: options.Force, - cascade: options.Cascade, - timeout: options.Timeout, - gracePeriod: options.GracePeriod, + force: o.DeleteOptions.ForceDeletion, + cascade: o.DeleteOptions.Cascade, + timeout: o.DeleteOptions.Timeout, + gracePeriod: o.DeleteOptions.GracePeriod, openapiSchema: openapiSchema, } - patchBytes, patchedObject, err := patcher.patch(info.Object, modified, info.Source, info.Namespace, info.Name, errOut) + patchBytes, patchedObject, err := patcher.patch(info.Object, modified, info.Source, info.Namespace, info.Name, o.ErrOut) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patchBytes, info), info.Source, err) } info.Refresh(patchedObject, true) - if uid, err := info.Mapping.UID(info.Object); err != nil { - return err - } else { - visitedUids.Insert(string(uid)) - } + visitedUids.Insert(string(metadata.GetUID())) - if string(patchBytes) == "{}" { + if string(patchBytes) == "{}" && !printObject { count++ - cmdutil.PrintSuccess(shortOutput, out, info.Object, false, "unchanged") - return nil + + printer, err := o.ToPrinter("unchanged") + if err != nil { + return err + } + return printer.PrintObj(info.Object, o.Out) } } count++ - if len(output) > 0 && !shortOutput { - return cmdutil.PrintObject(cmd, info.Object, out) + + if printObject { + objs = append(objs, info.Object) + return nil } - cmdutil.PrintSuccess(shortOutput, out, info.Object, dryRun, "configured") - return nil - }) + printer, err := o.ToPrinter("configured") + if err != nil { + return err + } + return printer.PrintObj(info.Object, o.Out) + }) if err != nil { return err } + if count == 0 { return fmt.Errorf("no objects passed to apply") } - if !options.Prune { + // print objects + if len(objs) > 0 { + printer, err := o.ToPrinter("") + if err != nil { + return err + } + + objToPrint := objs[0] + if len(objs) > 1 { + list := &v1.List{ + TypeMeta: metav1.TypeMeta{ + Kind: "List", + APIVersion: "v1", + }, + ListMeta: metav1.ListMeta{}, + } + if err := meta.SetList(list, objs); err != nil { + return err + } + + objToPrint = list + } + if err := printer.PrintObj(objToPrint, o.Out); err != nil { + return err + } + } + + if !o.Prune { return nil } p := pruner{ - mapper: mapper, - clientFunc: f.UnstructuredClientForMapping, - clientsetFunc: f.ClientSet, + mapper: o.Mapper, + dynamicClient: o.DynamicClient, - labelSelector: options.Selector, + labelSelector: o.Selector, visitedUids: visitedUids, - cascade: options.Cascade, - dryRun: dryRun, - gracePeriod: options.GracePeriod, + cascade: o.DeleteOptions.Cascade, + dryRun: o.DryRun, + gracePeriod: o.DeleteOptions.GracePeriod, + + toPrinter: o.ToPrinter, - out: out, + out: o.Out, } - namespacedRESTMappings, nonNamespacedRESTMappings, err := getRESTMappings(mapper, &(options.PruneResources)) + namespacedRESTMappings, nonNamespacedRESTMappings, err := getRESTMappings(o.Mapper, &(o.PruneResources)) if err != nil { return fmt.Errorf("error retrieving RESTMappings to prune: %v", err) } for n := range visitedNamespaces { for _, m := range namespacedRESTMappings { - if err := p.prune(f, n, m, shortOutput, includeUninitialized); err != nil { + if err := p.prune(n, m, o.ShouldIncludeUninitialized); err != nil { return fmt.Errorf("error pruning namespaced object %v: %v", m.GroupVersionKind, err) } } } for _, m := range nonNamespacedRESTMappings { - if err := p.prune(f, metav1.NamespaceNone, m, shortOutput, includeUninitialized); err != nil { + if err := p.prune(metav1.NamespaceNone, m, o.ShouldIncludeUninitialized); err != nil { return fmt.Errorf("error pruning nonNamespaced object %v: %v", m.GroupVersionKind, err) } } @@ -430,6 +539,7 @@ func getRESTMappings(mapper meta.RESTMapper, pruneResources *[]pruneResource) (n {"", "v1", "Secret", true}, {"", "v1", "Service", true}, {"batch", "v1", "Job", true}, + {"batch", "v1beta1", "CronJob", true}, {"extensions", "v1beta1", "DaemonSet", true}, {"extensions", "v1beta1", "Deployment", true}, {"extensions", "v1beta1", "Ingress", true}, @@ -456,8 +566,7 @@ func getRESTMappings(mapper meta.RESTMapper, pruneResources *[]pruneResource) (n type pruner struct { mapper meta.RESTMapper - clientFunc resource.ClientMapperFunc - clientsetFunc func() (internalclientset.Interface, error) + dynamicClient dynamic.Interface visitedUids sets.String labelSelector string @@ -467,117 +576,83 @@ type pruner struct { dryRun bool gracePeriod int + toPrinter func(string) (printers.ResourcePrinter, error) + out io.Writer } -func (p *pruner) prune(f cmdutil.Factory, namespace string, mapping *meta.RESTMapping, shortOutput, includeUninitialized bool) error { - c, err := p.clientFunc(mapping) - if err != nil { - return err - } - - objList, err := resource.NewHelper(c, mapping).List( - namespace, - mapping.GroupVersionKind.Version, - false, - &metav1.ListOptions{ +func (p *pruner) prune(namespace string, mapping *meta.RESTMapping, includeUninitialized bool) error { + objList, err := p.dynamicClient.Resource(mapping.Resource). + Namespace(namespace). + List(metav1.ListOptions{ LabelSelector: p.labelSelector, FieldSelector: p.fieldSelector, IncludeUninitialized: includeUninitialized, - }, - ) + }) if err != nil { return err } + objs, err := meta.ExtractList(objList) if err != nil { return err } for _, obj := range objs { - annots, err := mapping.MetadataAccessor.Annotations(obj) + metadata, err := meta.Accessor(obj) if err != nil { return err } + annots := metadata.GetAnnotations() if _, ok := annots[api.LastAppliedConfigAnnotation]; !ok { // don't prune resources not created with apply continue } - uid, err := mapping.UID(obj) - if err != nil { - return err - } + uid := metadata.GetUID() if p.visitedUids.Has(string(uid)) { continue } - - name, err := mapping.Name(obj) - if err != nil { - return err - } + name := metadata.GetName() if !p.dryRun { if err := p.delete(namespace, name, mapping); err != nil { return err } } - cmdutil.PrintSuccess(shortOutput, p.out, obj, p.dryRun, "pruned") + + printer, err := p.toPrinter("pruned") + if err != nil { + return err + } + printer.PrintObj(obj, p.out) } return nil } func (p *pruner) delete(namespace, name string, mapping *meta.RESTMapping) error { - c, err := p.clientFunc(mapping) - if err != nil { - return err - } - - return runDelete(namespace, name, mapping, c, nil, p.cascade, p.gracePeriod, p.clientsetFunc) + return runDelete(namespace, name, mapping, p.dynamicClient, p.cascade, p.gracePeriod) } -func runDelete(namespace, name string, mapping *meta.RESTMapping, c resource.RESTClient, helper *resource.Helper, cascade bool, gracePeriod int, clientsetFunc func() (internalclientset.Interface, error)) error { - if !cascade { - if helper == nil { - helper = resource.NewHelper(c, mapping) - } - return helper.Delete(namespace, name) - } - cs, err := clientsetFunc() - if err != nil { - return err - } - r, err := kubectl.ReaperFor(mapping.GroupVersionKind.GroupKind(), cs) - if err != nil { - if _, ok := err.(*kubectl.NoSuchReaperError); !ok { - return err - } - return resource.NewHelper(c, mapping).Delete(namespace, name) - } - var options *metav1.DeleteOptions +func runDelete(namespace, name string, mapping *meta.RESTMapping, c dynamic.Interface, cascade bool, gracePeriod int) error { + options := &metav1.DeleteOptions{} if gracePeriod >= 0 { options = metav1.NewDeleteOptions(int64(gracePeriod)) } - if err := r.Stop(namespace, name, 2*time.Minute, options); err != nil { - return err + policy := metav1.DeletePropagationForeground + if !cascade { + policy = metav1.DeletePropagationOrphan } - return nil + options.PropagationPolicy = &policy + return c.Resource(mapping.Resource).Namespace(namespace).Delete(name, options) } func (p *patcher) delete(namespace, name string) error { - c, err := p.clientFunc(p.mapping) - if err != nil { - return err - } - return runDelete(namespace, name, p.mapping, c, p.helper, p.cascade, p.gracePeriod, p.clientsetFunc) + return runDelete(namespace, name, p.mapping, p.dynamicClient, p.cascade, p.gracePeriod) } type patcher struct { - encoder runtime.Encoder - decoder runtime.Decoder - mapping *meta.RESTMapping helper *resource.Helper - clientFunc resource.ClientMapperFunc - clientsetFunc func() (internalclientset.Interface, error) + dynamicClient dynamic.Interface overwrite bool backOff clockwork.Clock @@ -592,13 +667,13 @@ type patcher struct { func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, namespace, name string, errOut io.Writer) ([]byte, runtime.Object, error) { // Serialize the current configuration of the object from the server. - current, err := runtime.Encode(p.encoder, obj) + current, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) if err != nil { return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf("serializing current configuration from:\n%v\nfor:", obj), source, err) } // Retrieve the original configuration of the object from the annotation. - original, err := kubectl.GetOriginalConfiguration(p.mapping, obj) + original, err := kubectl.GetOriginalConfiguration(obj) if err != nil { return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf("retrieving original configuration from:\n%v\nfor:", obj), source, err) } @@ -685,20 +760,19 @@ func (p *patcher) patch(current runtime.Object, modified []byte, source, namespa } func (p *patcher) deleteAndCreate(original runtime.Object, modified []byte, namespace, name string) ([]byte, runtime.Object, error) { - err := p.delete(namespace, name) - if err != nil { + if err := p.delete(namespace, name); err != nil { return modified, nil, err } - err = wait.PollImmediate(kubectl.Interval, p.timeout, func() (bool, error) { + // TODO: use wait + if err := wait.PollImmediate(1*time.Second, p.timeout, func() (bool, error) { if _, err := p.helper.Get(namespace, name, false); !errors.IsNotFound(err) { return false, err } return true, nil - }) - if err != nil { + }); err != nil { return modified, nil, err } - versionedObject, _, err := p.decoder.Decode(modified, nil, nil) + versionedObject, _, err := unstructured.UnstructuredJSONScheme.Decode(modified, nil, nil) if err != nil { return modified, nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_edit_last_applied.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_edit_last_applied.go index 5fd5dd199..e4700989c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_edit_last_applied.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_edit_last_applied.go @@ -17,15 +17,12 @@ limitations under the License. package cmd import ( - "io" - "runtime" - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) var ( @@ -58,11 +55,8 @@ var ( kubectl apply edit-last-applied -f deploy.yaml -o json`) ) -func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - options := &editor.EditOptions{ - EditMode: editor.ApplyEditMode, - } - validArgs := cmdutil.ValidArgList(f) +func NewCmdApplyEditLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := editor.NewEditOptions(editor.ApplyEditMode, ioStreams) cmd := &cobra.Command{ Use: "edit-last-applied (RESOURCE/NAME | -f FILENAME)", @@ -71,24 +65,23 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra Long: applyEditLastAppliedLong, Example: applyEditLastAppliedExample, Run: func(cmd *cobra.Command, args []string) { - options.ChangeCause = f.Command(cmd, false) - if err := options.Complete(f, out, errOut, args, cmd); err != nil { + if err := o.Complete(f, args, cmd); err != nil { cmdutil.CheckErr(err) } - if err := options.Run(); err != nil { + if err := o.Run(); err != nil { cmdutil.CheckErr(err) } }, - ValidArgs: validArgs, - ArgAliases: kubectl.ResourceAliases(validArgs), } + // bind flag structs + o.RecordFlags.AddFlags(cmd) + usage := "to use to edit the resource" - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) - cmd.Flags().StringVarP(&options.Output, "output", "o", "yaml", "Output format. One of: yaml|json.") - cmd.Flags().BoolVar(&options.WindowsLineEndings, "windows-line-endings", runtime.GOOS == "windows", + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, "Output format. One of: yaml|json.") + cmd.Flags().BoolVar(&o.WindowsLineEndings, "windows-line-endings", o.WindowsLineEndings, "Defaults to the line ending native to your platform.") - cmdutil.AddRecordVarFlag(cmd, &options.Record) cmdutil.AddIncludeUninitializedFlag(cmd) return cmd diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_set_last_applied.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_set_last_applied.go index 5a0c565b5..809515d24 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_set_last_applied.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_set_last_applied.go @@ -18,44 +18,44 @@ package cmd import ( "bytes" - "encoding/json" "fmt" - "io" - "github.com/ghodss/yaml" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - apijson "k8s.io/apimachinery/pkg/util/json" - api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) type SetLastAppliedOptions struct { - FilenameOptions resource.FilenameOptions - Selector string - InfoList []*resource.Info - Mapper meta.RESTMapper - Typer runtime.ObjectTyper - Namespace string - EnforceNamespace bool - DryRun bool - ShortOutput bool CreateAnnotation bool - Output string - PatchBufferList []PatchBuffer - Factory cmdutil.Factory - Out io.Writer - ErrOut io.Writer + + PrintFlags *genericclioptions.PrintFlags + PrintObj printers.ResourcePrinterFunc + + FilenameOptions resource.FilenameOptions + + infoList []*resource.Info + namespace string + enforceNamespace bool + dryRun bool + shortOutput bool + output string + patchBufferList []PatchBuffer + builder *resource.Builder + unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) + + genericclioptions.IOStreams } type PatchBuffer struct { @@ -81,8 +81,15 @@ var ( `)) ) -func NewCmdApplySetLastApplied(f cmdutil.Factory, out, err io.Writer) *cobra.Command { - options := &SetLastAppliedOptions{Out: out, ErrOut: err} +func NewSetLastAppliedOptions(ioStreams genericclioptions.IOStreams) *SetLastAppliedOptions { + return &SetLastAppliedOptions{ + PrintFlags: genericclioptions.NewPrintFlags("configured").WithTypeSetter(scheme.Scheme), + IOStreams: ioStreams, + } +} + +func NewCmdApplySetLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewSetLastAppliedOptions(ioStreams) cmd := &cobra.Command{ Use: "set-last-applied -f FILENAME", DisableFlagsInUseLine: true, @@ -90,42 +97,55 @@ func NewCmdApplySetLastApplied(f cmdutil.Factory, out, err io.Writer) *cobra.Com Long: applySetLastAppliedLong, Example: applySetLastAppliedExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd)) - cmdutil.CheckErr(options.Validate(f, cmd)) - cmdutil.CheckErr(options.RunSetLastApplied(f, cmd)) + cmdutil.CheckErr(o.Complete(f, cmd)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunSetLastApplied()) }, } + o.PrintFlags.AddFlags(cmd) + cmdutil.AddDryRunFlag(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().BoolVar(&options.CreateAnnotation, "create-annotation", false, "Will create 'last-applied-configuration' annotations if current objects doesn't have one") - usage := "that contains the last-applied-configuration annotations" - kubectl.AddJsonFilenameFlag(cmd, &options.FilenameOptions.Filenames, "Filename, directory, or URL to files "+usage) + cmd.Flags().BoolVar(&o.CreateAnnotation, "create-annotation", o.CreateAnnotation, "Will create 'last-applied-configuration' annotations if current objects doesn't have one") + cmdutil.AddJsonFilenameFlag(cmd.Flags(), &o.FilenameOptions.Filenames, "Filename, directory, or URL to files that contains the last-applied-configuration annotations") return cmd } func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { - o.DryRun = cmdutil.GetDryRunFlag(cmd) - o.Output = cmdutil.GetFlagString(cmd, "output") - o.ShortOutput = o.Output == "name" + o.dryRun = cmdutil.GetDryRunFlag(cmd) + o.output = cmdutil.GetFlagString(cmd, "output") + o.shortOutput = o.output == "name" var err error - o.Mapper, o.Typer = f.Object() + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } + o.builder = f.NewBuilder() + o.unstructuredClientForMapping = f.UnstructuredClientForMapping + + if o.dryRun { + // TODO(juanvallejo): This can be cleaned up even further by creating + // a PrintFlags struct that binds the --dry-run flag, and whose + // ToPrinter method returns a printer that understands how to print + // this success message. + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObj = printer.PrintObj - o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() - return err + return nil } -func (o *SetLastAppliedOptions) Validate(f cmdutil.Factory, cmd *cobra.Command) error { - r := f.NewBuilder(). +func (o *SetLastAppliedOptions) Validate() error { + r := o.builder. Unstructured(). - NamespaceParam(o.Namespace).DefaultNamespace(). - FilenameParam(o.EnforceNamespace, &o.FilenameOptions). + NamespaceParam(o.namespace).DefaultNamespace(). + FilenameParam(o.enforceNamespace, &o.FilenameOptions). Flatten(). Do() @@ -133,7 +153,7 @@ func (o *SetLastAppliedOptions) Validate(f cmdutil.Factory, cmd *cobra.Command) if err != nil { return err } - patchBuf, diffBuf, patchType, err := editor.GetApplyPatch(info.Object, scheme.DefaultJSONEncoder()) + patchBuf, diffBuf, patchType, err := editor.GetApplyPatch(info.Object.(runtime.Unstructured)) if err != nil { return err } @@ -143,22 +163,22 @@ func (o *SetLastAppliedOptions) Validate(f cmdutil.Factory, cmd *cobra.Command) if errors.IsNotFound(err) { return err } else { - return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) + return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%s\nfrom server for:", info.String()), info.Source, err) } } - originalBuf, err := kubectl.GetOriginalConfiguration(info.Mapping, info.Object) + originalBuf, err := kubectl.GetOriginalConfiguration(info.Object) if err != nil { - return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) + return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%s\nfrom server for:", info.String()), info.Source, err) } if originalBuf == nil && !o.CreateAnnotation { - return cmdutil.UsageErrorf(cmd, "no last-applied-configuration annotation found on resource: %s, to create the annotation, run the command with --create-annotation", info.Name) + return fmt.Errorf("no last-applied-configuration annotation found on resource: %s, to create the annotation, run the command with --create-annotation", info.Name) } //only add to PatchBufferList when changed if !bytes.Equal(cmdutil.StripComments(originalBuf), cmdutil.StripComments(diffBuf)) { p := PatchBuffer{Patch: patchBuf, PatchType: patchType} - o.PatchBufferList = append(o.PatchBufferList, p) - o.InfoList = append(o.InfoList, info) + o.patchBufferList = append(o.patchBufferList, p) + o.infoList = append(o.infoList, info) } else { fmt.Fprintf(o.Out, "set-last-applied %s: no changes required.\n", info.Name) } @@ -168,68 +188,26 @@ func (o *SetLastAppliedOptions) Validate(f cmdutil.Factory, cmd *cobra.Command) return err } -func (o *SetLastAppliedOptions) RunSetLastApplied(f cmdutil.Factory, cmd *cobra.Command) error { - for i, patch := range o.PatchBufferList { - info := o.InfoList[i] - if !o.DryRun { +func (o *SetLastAppliedOptions) RunSetLastApplied() error { + for i, patch := range o.patchBufferList { + info := o.infoList[i] + finalObj := info.Object + + if !o.dryRun { mapping := info.ResourceMapping() - client, err := f.UnstructuredClientForMapping(mapping) + client, err := o.unstructuredClientForMapping(mapping) if err != nil { return err } helper := resource.NewHelper(client, mapping) - patchedObj, err := helper.Patch(o.Namespace, info.Name, patch.PatchType, patch.Patch) - if err != nil { - return err - } - - if len(o.Output) > 0 && !o.ShortOutput { - info.Refresh(patchedObj, false) - return cmdutil.PrintObject(cmd, info.Object, o.Out) - } - cmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, o.DryRun, "configured") - - } else { - err := o.formatPrinter(o.Output, patch.Patch, o.Out) + finalObj, err = helper.Patch(o.namespace, info.Name, patch.PatchType, patch.Patch) if err != nil { return err } - cmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, o.DryRun, "configured") } - } - return nil -} - -func (o *SetLastAppliedOptions) formatPrinter(output string, buf []byte, w io.Writer) error { - yamlOutput, err := yaml.JSONToYAML(buf) - if err != nil { - return err - } - switch output { - case "json": - jsonBuffer := &bytes.Buffer{} - err = json.Indent(jsonBuffer, buf, "", " ") - if err != nil { + if err := o.PrintObj(finalObj, o.Out); err != nil { return err } - fmt.Fprintf(w, "%s\n", jsonBuffer.String()) - case "yaml": - fmt.Fprintf(w, "%s\n", string(yamlOutput)) } return nil } - -func (o *SetLastAppliedOptions) getPatch(info *resource.Info) ([]byte, []byte, error) { - objMap := map[string]map[string]map[string]string{} - metadataMap := map[string]map[string]string{} - annotationsMap := map[string]string{} - localFile, err := runtime.Encode(scheme.DefaultJSONEncoder(), info.Object) - if err != nil { - return nil, localFile, err - } - annotationsMap[api.LastAppliedConfigAnnotation] = string(localFile) - metadataMap["annotations"] = annotationsMap - objMap["metadata"] = metadataMap - jsonString, err := apijson.Marshal(objMap) - return jsonString, localFile, err -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_test.go index aa4919769..81f746421 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_test.go @@ -31,14 +31,17 @@ import ( "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" kubeerr "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" sptest "k8s.io/apimachinery/pkg/util/strategicpatch/testing" + dynamicfakeclient "k8s.io/client-go/dynamic/fake" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" + clienttesting "k8s.io/client-go/testing" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" api "k8s.io/kubernetes/pkg/apis/core" @@ -46,6 +49,7 @@ import ( cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -65,13 +69,10 @@ var ( ) func TestApplyExtraArgsFail(t *testing.T) { - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - f := cmdtesting.NewTestFactory() defer f.Cleanup() - c := NewCmdApply("kubectl", f, buf, errBuf) + c := NewCmdApply("kubectl", f, genericclioptions.NewTestIOStreamsDiscard()) if validateApplyArgs(c, []string{"rc"}) == nil { t.Fatalf("unexpected non-error") } @@ -85,6 +86,7 @@ func validateApplyArgs(cmd *cobra.Command, args []string) error { } const ( + filenameCM = "../../../test/fixtures/pkg/kubectl/cmd/apply/cm.yaml" filenameRC = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc.yaml" filenameRCArgs = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-args.yaml" filenameRCLastAppliedArgs = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-lastapplied-args.yaml" @@ -101,6 +103,21 @@ const ( filenameWidgetServerside = "../../../test/fixtures/pkg/kubectl/cmd/apply/widget-serverside.yaml" ) +func readConfigMapList(t *testing.T, filename string) []byte { + data := readBytesFromFile(t, filename) + cmList := corev1.ConfigMapList{} + if err := runtime.DecodeInto(testapi.Default.Codec(), data, &cmList); err != nil { + t.Fatal(err) + } + + cmListBytes, err := runtime.Encode(testapi.Default.Codec(), &cmList) + if err != nil { + t.Fatal(err) + } + + return cmListBytes +} + func readBytesFromFile(t *testing.T, filename string) []byte { file, err := os.Open(filename) if err != nil { @@ -174,7 +191,7 @@ func annotateRuntimeObject(t *testing.T, originalObj, currentObj runtime.Object, originalLabels := originalAccessor.GetLabels() originalLabels["DELETE_ME"] = "DELETE_ME" originalAccessor.SetLabels(originalLabels) - original, err := runtime.Encode(testapi.Default.Codec(), originalObj) + original, err := runtime.Encode(unstructured.JSONFallbackEncoder{Encoder: testapi.Default.Codec()}, originalObj) if err != nil { t.Fatal(err) } @@ -190,7 +207,7 @@ func annotateRuntimeObject(t *testing.T, originalObj, currentObj runtime.Object, } currentAnnotations[api.LastAppliedConfigAnnotation] = string(original) currentAccessor.SetAnnotations(currentAnnotations) - current, err := runtime.Encode(testapi.Default.Codec(), currentObj) + current, err := runtime.Encode(unstructured.JSONFallbackEncoder{Encoder: testapi.Default.Codec()}, currentObj) if err != nil { t.Fatal(err) } @@ -251,6 +268,46 @@ func walkMapPath(t *testing.T, start map[string]interface{}, path []string) map[ return finish } +func TestRunApplyPrintsValidObjectList(t *testing.T) { + initTestErrorHandler(t) + cmBytes := readConfigMapList(t, filenameCM) + pathCM := "/namespaces/test/configmaps" + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case strings.HasPrefix(p, pathCM) && m != "GET": + pod := ioutil.NopCloser(bytes.NewReader(cmBytes)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: pod}, nil + case strings.HasPrefix(p, pathCM) && m != "PATCH": + pod := ioutil.NopCloser(bytes.NewReader(cmBytes)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: pod}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + tf.ClientConfigVal = defaultClientConfig() + + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) + cmd.Flags().Set("filename", filenameCM) + cmd.Flags().Set("output", "json") + cmd.Flags().Set("dry-run", "true") + cmd.Run(cmd, []string{}) + + // ensure that returned list can be unmarshaled back into a configmap list + cmList := corev1.List{} + if err := runtime.DecodeInto(testapi.Default.Codec(), buf.Bytes(), &cmList); err != nil { + t.Fatal(err) + } +} + func TestRunApplyViewLastApplied(t *testing.T) { _, rcBytesWithConfig := readReplicationController(t, filenameRCLASTAPPLIED) _, rcBytesWithArgs := readReplicationController(t, filenameRCLastAppliedArgs) @@ -299,7 +356,7 @@ func TestRunApplyViewLastApplied(t *testing.T) { expectedErr: "error: Unexpected -o output mode: wide, the flag 'output' must be one of yaml|json\nSee 'view-last-applied -h' for help and examples.", expectedOut: "", selector: "", - args: []string{"rc", "test-rc"}, + args: []string{"replicationcontroller", "test-rc"}, respBytes: rcBytesWithConfig, }, { @@ -309,7 +366,7 @@ func TestRunApplyViewLastApplied(t *testing.T) { expectedErr: "", expectedOut: "test: 1234\n", selector: "name=test-rc", - args: []string{"rc"}, + args: []string{"replicationcontroller"}, respBytes: rcBytesWithConfig, }, { @@ -319,7 +376,7 @@ func TestRunApplyViewLastApplied(t *testing.T) { expectedErr: "error: no last-applied-configuration annotation found on resource: test-rc", expectedOut: "", selector: "", - args: []string{"rc", "test-rc"}, + args: []string{"replicationcontroller", "test-rc"}, respBytes: rcBytes, }, { @@ -329,16 +386,16 @@ func TestRunApplyViewLastApplied(t *testing.T) { expectedErr: "Error from server (NotFound): the server could not find the requested resource (get replicationcontrollers no-match)", expectedOut: "", selector: "", - args: []string{"rc", "no-match"}, + args: []string{"replicationcontroller", "no-match"}, respBytes: nil, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: "v1"}, @@ -361,9 +418,7 @@ func TestRunApplyViewLastApplied(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) cmdutil.BehaviorOnFatal(func(str string, code int) { if str != test.expectedErr { @@ -371,7 +426,8 @@ func TestRunApplyViewLastApplied(t *testing.T) { } }) - cmd := NewCmdApplyViewLastApplied(tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApplyViewLastApplied(tf, ioStreams) if test.filePath != "" { cmd.Flags().Set("filename", test.filePath) } @@ -395,7 +451,7 @@ func TestApplyObjectWithoutAnnotation(t *testing.T) { nameRC, rcBytes := readReplicationController(t, filenameRC) pathRC := "/namespaces/test/replicationcontrollers/" + nameRC - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -414,12 +470,10 @@ func TestApplyObjectWithoutAnnotation(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -442,7 +496,7 @@ func TestApplyObject(t *testing.T) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply when a local object is specified", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -463,11 +517,10 @@ func TestApplyObject(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + tf.ClientConfigVal = defaultClientConfig() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -507,7 +560,7 @@ func TestApplyObjectOutput(t *testing.T) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply returns correct output", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -528,11 +581,10 @@ func TestApplyObjectOutput(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + tf.ClientConfigVal = defaultClientConfig() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "yaml") cmd.Run(cmd, []string{}) @@ -560,7 +612,7 @@ func TestApplyRetry(t *testing.T) { firstPatch := true retry := false getCount := 0 - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -590,11 +642,10 @@ func TestApplyRetry(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + tf.ClientConfigVal = defaultClientConfig() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -620,7 +671,7 @@ func TestApplyNonExistObject(t *testing.T) { pathRC := "/namespaces/test/replicationcontrollers" pathNameRC := pathRC + "/" + nameRC - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -640,11 +691,10 @@ func TestApplyNonExistObject(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + tf.ClientConfigVal = defaultClientConfig() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -666,7 +716,7 @@ func TestApplyEmptyPatch(t *testing.T) { var body []byte - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -693,13 +743,11 @@ func TestApplyEmptyPatch(t *testing.T) { } }), } - tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() // 1. apply non exist object - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -713,10 +761,8 @@ func TestApplyEmptyPatch(t *testing.T) { } // 2. test apply already exist object, will not send empty patch request - buf = bytes.NewBuffer([]byte{}) - errBuf = bytes.NewBuffer([]byte{}) - - cmd = NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, _ = genericclioptions.NewTestIOStreams() + cmd = NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -743,7 +789,7 @@ func testApplyMultipleObjects(t *testing.T, asList bool) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply on multiple objects", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -771,11 +817,10 @@ func testApplyMultipleObjects(t *testing.T, asList bool) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + tf.ClientConfigVal = defaultClientConfig() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) if asList { cmd.Flags().Set("filename", filenameRCSVC) } else { @@ -830,7 +875,7 @@ func TestApplyNULLPreservation(t *testing.T) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply preserves NULL fields", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -872,11 +917,10 @@ func TestApplyNULLPreservation(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + tf.ClientConfigVal = defaultClientConfig() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameDeployObjClientside) cmd.Flags().Set("output", "name") @@ -906,7 +950,7 @@ func TestUnstructuredApply(t *testing.T) { for _, fn := range testingOpenAPISchemaFns { t.Run("test apply works correctly with unstructured objects", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -939,11 +983,10 @@ func TestUnstructuredApply(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + tf.ClientConfigVal = defaultClientConfig() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameWidgetClientside) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -967,17 +1010,15 @@ func TestUnstructuredIdempotentApply(t *testing.T) { initTestErrorHandler(t) serversideObject := readUnstructuredFromFile(t, filenameWidgetServerside) - serversideData, err := runtime.Encode(testapi.Default.Codec(), serversideObject) + serversideData, err := runtime.Encode(unstructured.JSONFallbackEncoder{Encoder: testapi.Default.Codec()}, serversideObject) if err != nil { t.Fatal(err) } path := "/namespaces/test/widgets/widget" - verifiedPatch := false - for _, fn := range testingOpenAPISchemaFns { t.Run("test repeated apply operations on an unstructured object", func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -991,41 +1032,15 @@ func TestUnstructuredIdempotentApply(t *testing.T) { Header: defaultHeader(), Body: body}, nil case p == path && m == "PATCH": - // In idempotent updates, kubectl sends a logically empty - // request body with the PATCH request. - // Should look like this: - // Request Body: {"metadata":{"annotations":{}}} + // In idempotent updates, kubectl will resolve to an empty patch and not send anything to the server + // Thus, if we reach this branch, kubectl is unnecessarily sending a patch. patch, err := ioutil.ReadAll(req.Body) if err != nil { t.Fatal(err) } - - contentType := req.Header.Get("Content-Type") - if contentType != "application/merge-patch+json" { - t.Fatalf("Unexpected Content-Type: %s", contentType) - } - - patchMap := map[string]interface{}{} - if err := json.Unmarshal(patch, &patchMap); err != nil { - t.Fatal(err) - } - if len(patchMap) != 1 { - t.Fatalf("Unexpected Patch. Has more than 1 entry. path: %s", patch) - } - - annotationsMap := walkMapPath(t, patchMap, []string{"metadata", "annotations"}) - if len(annotationsMap) != 0 { - t.Fatalf("Unexpected Patch. Found unexpected annotation: %s", patch) - } - - verifiedPatch = true - - body := ioutil.NopCloser(bytes.NewReader(serversideData)) - return &http.Response{ - StatusCode: 200, - Header: defaultHeader(), - Body: body}, nil + t.Fatalf("Unexpected Patch: %s", patch) + return nil, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil @@ -1033,11 +1048,10 @@ func TestUnstructuredIdempotentApply(t *testing.T) { }), } tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + tf.ClientConfigVal = defaultClientConfig() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameWidgetClientside) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -1049,9 +1063,6 @@ func TestUnstructuredIdempotentApply(t *testing.T) { if errBuf.String() != "" { t.Fatalf("unexpected error output: %s", errBuf.String()) } - if !verifiedPatch { - t.Fatal("No server-side patch call detected") - } }) } } @@ -1087,7 +1098,7 @@ func TestRunApplySetLastApplied(t *testing.T) { { name: "set for the annotation does not exist on the live object", filePath: filenameRCNoAnnotation, - expectedErr: "error: no last-applied-configuration annotation found on resource: no-annotation, to create the annotation, run the command with --create-annotation\nSee 'set-last-applied -h' for help and examples.", + expectedErr: "error: no last-applied-configuration annotation found on resource: no-annotation, to create the annotation, run the command with --create-annotation", expectedOut: "", output: "name", }, @@ -1108,10 +1119,10 @@ func TestRunApplySetLastApplied(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: "v1"}, @@ -1138,9 +1149,7 @@ func TestRunApplySetLastApplied(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) cmdutil.BehaviorOnFatal(func(str string, code int) { if str != test.expectedErr { @@ -1148,7 +1157,8 @@ func TestRunApplySetLastApplied(t *testing.T) { } }) - cmd := NewCmdApplySetLastApplied(tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApplySetLastApplied(tf, ioStreams) cmd.Flags().Set("filename", test.filePath) cmd.Flags().Set("output", test.output) cmd.Run(cmd, []string{}) @@ -1186,16 +1196,16 @@ func checkPatchString(t *testing.T, req *http.Request) { func TestForceApply(t *testing.T) { initTestErrorHandler(t) + scheme := runtime.NewScheme() nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC) pathRC := "/namespaces/test/replicationcontrollers/" + nameRC pathRCList := "/namespaces/test/replicationcontrollers" expected := map[string]int{ - "getOk": 10, + "getOk": 6, "getNotFound": 1, - "getList": 1, + "getList": 0, "patch": 6, "delete": 1, - "put": 1, "post": 1, } @@ -1204,9 +1214,10 @@ func TestForceApply(t *testing.T) { deleted := false isScaledDownToZero := false counts := map[string]int{} - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() + tf.ClientConfigVal = defaultClientConfig() tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { @@ -1256,10 +1267,6 @@ func TestForceApply(t *testing.T) { } t.Fatalf("unexpected request: %#v after %v tries\n%#v", req.URL, counts["patch"], req) return nil, nil - case strings.HasSuffix(p, pathRC) && m == "DELETE": - counts["delete"]++ - deleted = true - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte{}))}, nil case strings.HasSuffix(p, pathRC) && m == "PUT": counts["put"]++ bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) @@ -1277,14 +1284,24 @@ func TestForceApply(t *testing.T) { } }), } + fakeDynamicClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeDynamicClient.PrependReactor("delete", "replicationcontrollers", func(action clienttesting.Action) (bool, runtime.Object, error) { + if deleteAction, ok := action.(clienttesting.DeleteAction); ok { + if deleteAction.GetName() == nameRC { + counts["delete"]++ + deleted = true + return true, nil, nil + } + } + return false, nil, nil + }) + tf.FakeDynamicClient = fakeDynamicClient tf.OpenAPISchemaFunc = fn tf.Client = tf.UnstructuredClient tf.ClientConfigVal = &restclient.Config{} - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Flags().Set("force", "true") diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_view_last_applied.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_view_last_applied.go index b0ebb1af8..5fa5cd12c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_view_last_applied.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply_view_last_applied.go @@ -20,14 +20,14 @@ import ( "bytes" "encoding/json" "fmt" - "io" "github.com/ghodss/yaml" "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -38,8 +38,8 @@ type ViewLastAppliedOptions struct { OutputFormat string All bool Factory cmdutil.Factory - Out io.Writer - ErrOut io.Writer + + genericclioptions.IOStreams } var ( @@ -57,8 +57,17 @@ var ( kubectl apply view-last-applied -f deploy.yaml -o json`)) ) -func NewCmdApplyViewLastApplied(f cmdutil.Factory, out, err io.Writer) *cobra.Command { - options := &ViewLastAppliedOptions{Out: out, ErrOut: err} +func NewViewLastAppliedOptions(ioStreams genericclioptions.IOStreams) *ViewLastAppliedOptions { + return &ViewLastAppliedOptions{ + OutputFormat: "yaml", + + IOStreams: ioStreams, + } +} + +func NewCmdApplyViewLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := NewViewLastAppliedOptions(ioStreams) + cmd := &cobra.Command{ Use: "view-last-applied (TYPE [NAME | -l label] | TYPE/NAME | -f FILENAME)", DisableFlagsInUseLine: true, @@ -66,24 +75,23 @@ func NewCmdApplyViewLastApplied(f cmdutil.Factory, out, err io.Writer) *cobra.Co Long: applyViewLastAppliedLong, Example: applyViewLastAppliedExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.ValidateOutputArgs(cmd)) - cmdutil.CheckErr(options.Complete(f, args)) + cmdutil.CheckErr(options.Complete(cmd, f, args)) cmdutil.CheckErr(options.Validate(cmd)) - cmdutil.CheckErr(options.RunApplyViewLastApplied()) + cmdutil.CheckErr(options.RunApplyViewLastApplied(cmd)) }, } - cmd.Flags().StringP("output", "o", "", "Output format. Must be one of yaml|json") - cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources in the namespace of the specified resource types") + cmd.Flags().StringVarP(&options.OutputFormat, "output", "o", options.OutputFormat, "Output format. Must be one of yaml|json") + cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&options.All, "all", options.All, "Select all resources in the namespace of the specified resource types") usage := "that contains the last-applied-configuration annotations" cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) return cmd } -func (o *ViewLastAppliedOptions) Complete(f cmdutil.Factory, args []string) error { - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() +func (o *ViewLastAppliedOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string) error { + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -108,7 +116,7 @@ func (o *ViewLastAppliedOptions) Complete(f cmdutil.Factory, args []string) erro return err } - configString, err := kubectl.GetOriginalConfiguration(info.Mapping, info.Object) + configString, err := kubectl.GetOriginalConfiguration(info.Object) if err != nil { return err } @@ -130,7 +138,7 @@ func (o *ViewLastAppliedOptions) Validate(cmd *cobra.Command) error { return nil } -func (o *ViewLastAppliedOptions) RunApplyViewLastApplied() error { +func (o *ViewLastAppliedOptions) RunApplyViewLastApplied(cmd *cobra.Command) error { for _, str := range o.LastAppliedConfigurationList { switch o.OutputFormat { case "json": @@ -146,23 +154,13 @@ func (o *ViewLastAppliedOptions) RunApplyViewLastApplied() error { return err } fmt.Fprint(o.Out, string(yamlOutput)) + default: + return cmdutil.UsageErrorf( + cmd, + "Unexpected -o output mode: %s, the flag 'output' must be one of yaml|json", + o.OutputFormat) } } return nil } - -func (o *ViewLastAppliedOptions) ValidateOutputArgs(cmd *cobra.Command) error { - format := cmdutil.GetFlagString(cmd, "output") - switch format { - case "json": - o.OutputFormat = "json" - return nil - // If flag -o is not specified, use yaml as default - case "yaml", "": - o.OutputFormat = "yaml" - return nil - default: - return cmdutil.UsageErrorf(cmd, "Unexpected -o output mode: %s, the flag 'output' must be one of yaml|json", format) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/attach.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/attach.go index e35c56844..88ff4f7d4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/attach.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/attach.go @@ -35,6 +35,8 @@ import ( coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -60,12 +62,10 @@ const ( defaultPodLogsTimeout = 20 * time.Second ) -func NewCmdAttach(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command { - options := &AttachOptions{ +func NewCmdAttach(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := &AttachOptions{ StreamOptions: StreamOptions{ - In: cmdIn, - Out: cmdOut, - Err: cmdErr, + IOStreams: streams, }, Attach: &DefaultRemoteAttach{}, @@ -77,15 +77,15 @@ func NewCmdAttach(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) Long: "Attach to a process that is already running inside an existing container.", Example: attachExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.Run()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.Run()) }, } cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodAttachTimeout) - cmd.Flags().StringVarP(&options.ContainerName, "container", "c", "", "Container name. If omitted, the first container in the pod will be chosen") - cmd.Flags().BoolVarP(&options.Stdin, "stdin", "i", false, "Pass stdin to the container") - cmd.Flags().BoolVarP(&options.TTY, "tty", "t", false, "Stdin is a TTY") + cmd.Flags().StringVarP(&o.ContainerName, "container", "c", o.ContainerName, "Container name. If omitted, the first container in the pod will be chosen") + cmd.Flags().BoolVarP(&o.Stdin, "stdin", "i", o.Stdin, "Pass stdin to the container") + cmd.Flags().BoolVarP(&o.TTY, "tty", "t", o.TTY, "Stdin is a TTY") return cmd } @@ -135,7 +135,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [ return cmdutil.UsageErrorf(cmd, "expected POD, TYPE/NAME, or TYPE NAME, (at most 2 arguments) saw %d: %v", len(argsIn), argsIn) } - namespace, _, err := f.DefaultNamespace() + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -146,7 +146,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [ } builder := f.NewBuilder(). - Internal(). + WithScheme(legacyscheme.Scheme). NamespaceParam(namespace).DefaultNamespace() switch len(argsIn) { @@ -161,7 +161,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [ return err } - attachablePod, err := f.AttachablePodForObject(obj, p.GetPodTimeout) + attachablePod, err := polymorphichelpers.AttachablePodForObjectFn(f, obj, p.GetPodTimeout) if err != nil { return err } @@ -178,7 +178,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [ p.SuggestedCmdUsage = fmt.Sprintf("Use '%s describe pod/%s -n %s' to see all of the containers in this pod.", fullCmdName, p.PodName, p.Namespace) } - config, err := f.ClientConfig() + config, err := f.ToRESTConfig() if err != nil { return err } @@ -188,6 +188,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [ if err != nil { return err } + p.PodClient = clientset.Core() if p.CommandName == "" { @@ -203,7 +204,7 @@ func (p *AttachOptions) Validate() error { if len(p.PodName) == 0 { allErrs = append(allErrs, errors.New("pod name must be specified")) } - if p.Out == nil || p.Err == nil { + if p.Out == nil || p.ErrOut == nil { allErrs = append(allErrs, errors.New("both output and error output must be provided")) } if p.Attach == nil || p.PodClient == nil || p.Config == nil { @@ -236,8 +237,8 @@ func (p *AttachOptions) Run() error { } if p.TTY && !containerToAttach.TTY { p.TTY = false - if p.Err != nil { - fmt.Fprintf(p.Err, "Unable to use a TTY - container %s did not allocate one\n", containerToAttach.Name) + if p.ErrOut != nil { + fmt.Fprintf(p.ErrOut, "Unable to use a TTY - container %s did not allocate one\n", containerToAttach.Name) } } else if !p.TTY && containerToAttach.TTY { // the container was launched with a TTY, so we have to force a TTY here, otherwise you'll get @@ -249,7 +250,7 @@ func (p *AttachOptions) Run() error { t := p.setupTTY() // save p.Err so we can print the command prompt message below - stderr := p.Err + stderr := p.ErrOut var sizeQueue remotecommand.TerminalSizeQueue if t.Raw { @@ -266,7 +267,7 @@ func (p *AttachOptions) Run() error { // unset p.Err if it was previously set because both stdout and stderr go over p.Out when tty is // true - p.Err = nil + p.ErrOut = nil } fn := func() error { @@ -284,11 +285,11 @@ func (p *AttachOptions) Run() error { Container: containerToAttach.Name, Stdin: p.Stdin, Stdout: p.Out != nil, - Stderr: p.Err != nil, + Stderr: p.ErrOut != nil, TTY: t.Raw, }, legacyscheme.ParameterCodec) - return p.Attach.Attach("POST", req.URL(), p.Config, p.In, p.Out, p.Err, t.Raw, sizeQueue) + return p.Attach.Attach("POST", req.URL(), p.Config, p.In, p.Out, p.ErrOut, t.Raw, sizeQueue) } if !p.Quiet && stderr != nil { @@ -322,8 +323,8 @@ func (p *AttachOptions) containerToAttachTo(pod *api.Pod) (*api.Container, error } if len(p.SuggestedCmdUsage) > 0 { - fmt.Fprintf(p.Err, "Defaulting container name to %s.\n", pod.Spec.Containers[0].Name) - fmt.Fprintf(p.Err, "%s\n", p.SuggestedCmdUsage) + fmt.Fprintf(p.ErrOut, "Defaulting container name to %s.\n", pod.Spec.Containers[0].Name) + fmt.Fprintf(p.ErrOut, "%s\n", p.SuggestedCmdUsage) } glog.V(4).Infof("defaulting container name to %s", pod.Spec.Containers[0].Name) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/attach_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/attach_test.go index d5294ea2e..007df0dcc 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/attach_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/attach_test.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "bytes" "fmt" "io" "net/http" @@ -38,6 +37,7 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -140,14 +140,14 @@ func TestPodAndContainerAttach(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, NegotiatedSerializer: ns, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { if test.obj != nil { @@ -156,7 +156,6 @@ func TestPodAndContainerAttach(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() cmd := &cobra.Command{} @@ -184,7 +183,7 @@ func TestPodAndContainerAttach(t *testing.T) { } func TestAttach(t *testing.T) { - version := legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.Version + version := "v1" tests := []struct { name, version, podPath, fetchPodPath, attachPath, container string pod *api.Pod @@ -224,14 +223,14 @@ func TestAttach(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, NegotiatedSerializer: ns, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { @@ -242,17 +241,12 @@ func TestAttach(t *testing.T) { body := objBody(codec, test.pod) return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil default: - // Ensures no GET is performed when deleting by name t.Errorf("%s: unexpected request: %s %#v\n%#v", p, req.Method, req.URL, req) return nil, fmt.Errorf("unexpected request") } }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}} - bufOut := bytes.NewBuffer([]byte{}) - bufErr := bytes.NewBuffer([]byte{}) - bufIn := bytes.NewBuffer([]byte{}) remoteAttach := &fakeRemoteAttach{} if test.remoteAttachErr { remoteAttach.err = fmt.Errorf("attach error") @@ -260,9 +254,7 @@ func TestAttach(t *testing.T) { params := &AttachOptions{ StreamOptions: StreamOptions{ ContainerName: test.container, - In: bufIn, - Out: bufOut, - Err: bufErr, + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), }, Attach: remoteAttach, GetPodTimeout: 1000, @@ -299,7 +291,7 @@ func TestAttach(t *testing.T) { } func TestAttachWarnings(t *testing.T) { - version := legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.Version + version := "v1" tests := []struct { name, container, version, podPath, fetchPodPath, expectedErr string pod *api.Pod @@ -318,14 +310,14 @@ func TestAttachWarnings(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, NegotiatedSerializer: ns, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { @@ -341,18 +333,13 @@ func TestAttachWarnings(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}} - bufOut := bytes.NewBuffer([]byte{}) - bufErr := bytes.NewBuffer([]byte{}) - bufIn := bytes.NewBuffer([]byte{}) + streams, _, _, bufErr := genericclioptions.NewTestIOStreams() ex := &fakeRemoteAttach{} params := &AttachOptions{ StreamOptions: StreamOptions{ ContainerName: test.container, - In: bufIn, - Out: bufOut, - Err: bufErr, + IOStreams: streams, Stdin: test.stdin, TTY: test.tty, }, diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/BUILD index 5aa487c49..1734481f9 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/BUILD @@ -17,18 +17,21 @@ go_library( ], deps = [ "//pkg/apis/authorization:go_default_library", - "//pkg/apis/rbac:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/kubectl/resource:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//pkg/kubectl/scheme:go_default_library", "//pkg/registry/rbac/reconciliation:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/auth.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/auth.go index eb70d3005..b48fe56a7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/auth.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/auth.go @@ -17,24 +17,23 @@ limitations under the License. package auth import ( - "io" - "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ) -func NewCmdAuth(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { +func NewCmdAuth(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { // Parent command to which all subcommands are added. cmds := &cobra.Command{ Use: "auth", Short: "Inspect authorization", Long: `Inspect authorization`, - Run: cmdutil.DefaultSubCommandRun(errOut), + Run: cmdutil.DefaultSubCommandRun(streams.ErrOut), } - cmds.AddCommand(NewCmdCanI(f, out, errOut)) - cmds.AddCommand(NewCmdReconcile(f, out, errOut)) + cmds.AddCommand(NewCmdCanI(f, streams)) + cmds.AddCommand(NewCmdReconcile(f, streams)) return cmds } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/cani.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/cani.go index 7484cab18..118f0876d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/cani.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/cani.go @@ -19,12 +19,12 @@ package auth import ( "errors" "fmt" - "io" "io/ioutil" "os" "strings" "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime/schema" @@ -48,8 +48,7 @@ type CanIOptions struct { Subresource string ResourceName string - Out io.Writer - Err io.Writer + genericclioptions.IOStreams } var ( @@ -81,10 +80,9 @@ var ( kubectl auth can-i get /logs/`) ) -func NewCmdCanI(f cmdutil.Factory, out, err io.Writer) *cobra.Command { +func NewCmdCanI(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := &CanIOptions{ - Out: out, - Err: err, + IOStreams: streams, } cmd := &cobra.Command{ @@ -99,7 +97,7 @@ func NewCmdCanI(f cmdutil.Factory, out, err io.Writer) *cobra.Command { allowed, err := o.RunAccessCheck() if err == nil { - if o.Quiet && !allowed { + if !allowed { os.Exit(1) } } @@ -110,7 +108,7 @@ func NewCmdCanI(f cmdutil.Factory, out, err io.Writer) *cobra.Command { cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If true, check the specified action in all namespaces.") cmd.Flags().BoolVarP(&o.Quiet, "quiet", "q", o.Quiet, "If true, suppress output and just return the exit code.") - cmd.Flags().StringVar(&o.Subresource, "subresource", "", "SubResource such as pod/log or deployment/scale") + cmd.Flags().StringVar(&o.Subresource, "subresource", o.Subresource, "SubResource such as pod/log or deployment/scale") return cmd } @@ -127,7 +125,10 @@ func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error { break } resourceTokens := strings.SplitN(args[1], "/", 2) - restMapper, _ := f.Object() + restMapper, err := f.ToRESTMapper() + if err != nil { + return err + } o.Resource = o.resourceFor(restMapper, resourceTokens[0]) if len(resourceTokens) > 1 { o.ResourceName = resourceTokens[1] @@ -145,7 +146,7 @@ func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error { o.Namespace = "" if !o.AllNamespaces { - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -229,9 +230,9 @@ func (o *CanIOptions) resourceFor(mapper meta.RESTMapper, resourceArg string) sc gvr, err = mapper.ResourceFor(groupResource.WithVersion("")) if err != nil { if len(groupResource.Group) == 0 { - fmt.Fprintf(o.Err, "Warning: the server doesn't have a resource type '%s'\n", groupResource.Resource) + fmt.Fprintf(o.ErrOut, "Warning: the server doesn't have a resource type '%s'\n", groupResource.Resource) } else { - fmt.Fprintf(o.Err, "Warning: the server doesn't have a resource type '%s' in group '%s'\n", groupResource.Resource, groupResource.Group) + fmt.Fprintf(o.ErrOut, "Warning: the server doesn't have a resource type '%s' in group '%s'\n", groupResource.Resource, groupResource.Group) } return schema.GroupVersionResource{Resource: resourceArg} } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/cani_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/cani_test.go index eb3cf9c5d..8ce36cdd6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/cani_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/cani_test.go @@ -119,9 +119,9 @@ func TestRunAccessCheck(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { test.o.Out = ioutil.Discard - test.o.Err = ioutil.Discard + test.o.ErrOut = ioutil.Discard - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -157,7 +157,6 @@ func TestRunAccessCheck(t *testing.T) { test.serverErr }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}} if err := test.o.Complete(tf, test.args); err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/reconcile.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/reconcile.go index debd2787a..3346812de 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/reconcile.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/auth/reconcile.go @@ -18,31 +18,36 @@ package auth import ( "errors" - "io" "github.com/golang/glog" "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/apis/rbac" - internalcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - internalrbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + rbacv1 "k8s.io/api/rbac/v1" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/registry/rbac/reconciliation" ) // ReconcileOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type ReconcileOptions struct { + PrintFlags *genericclioptions.PrintFlags + FilenameOptions *resource.FilenameOptions + DryRun bool + Visitor resource.Visitor - RBACClient internalrbacclient.RbacInterface - NamespaceClient internalcoreclient.NamespaceInterface + RBACClient rbacv1client.RbacV1Interface + NamespaceClient corev1client.CoreV1Interface - Print func(*resource.Info) error + PrintObject printers.ResourcePrinterFunc - Out io.Writer - Err io.Writer + genericclioptions.IOStreams } var ( @@ -56,12 +61,16 @@ var ( kubectl auth reconcile -f my-rbac-rules.yaml`) ) -func NewCmdReconcile(f cmdutil.Factory, out, err io.Writer) *cobra.Command { - fileOptions := &resource.FilenameOptions{} - o := &ReconcileOptions{ - Out: out, - Err: err, +func NewReconcileOptions(ioStreams genericclioptions.IOStreams) *ReconcileOptions { + return &ReconcileOptions{ + FilenameOptions: &resource.FilenameOptions{}, + PrintFlags: genericclioptions.NewPrintFlags("reconciled").WithTypeSetter(scheme.Scheme), + IOStreams: ioStreams, } +} + +func NewCmdReconcile(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewReconcileOptions(streams) cmd := &cobra.Command{ Use: "reconcile -f FILENAME", @@ -70,35 +79,36 @@ func NewCmdReconcile(f cmdutil.Factory, out, err io.Writer) *cobra.Command { Long: reconcileLong, Example: reconcileExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(o.Complete(cmd, f, args, fileOptions)) + cmdutil.CheckErr(o.Complete(cmd, f, args)) cmdutil.CheckErr(o.Validate()) cmdutil.CheckErr(o.RunReconcile()) }, } - cmdutil.AddPrinterFlags(cmd) - usage := "identifying the resource to reconcile." - cmdutil.AddFilenameOptionFlags(cmd, fileOptions, usage) + o.PrintFlags.AddFlags(cmd) + + cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, "identifying the resource to reconcile.") + cmd.Flags().BoolVar(&o.DryRun, "dry-run", o.DryRun, "If true, display results but do not submit changes") cmd.MarkFlagRequired("filename") return cmd } -func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string, options *resource.FilenameOptions) error { +func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string) error { if len(args) > 0 { return errors.New("no arguments are allowed") } - namespace, enforceNamespace, err := f.DefaultNamespace() + namespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } r := f.NewBuilder(). - Internal(). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options). + FilenameParam(enforceNamespace, o.FilenameOptions). Flatten(). Do() @@ -107,24 +117,28 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args } o.Visitor = r - client, err := f.ClientSet() + clientConfig, err := f.ToRESTConfig() + if err != nil { + return err + } + o.RBACClient, err = rbacv1client.NewForConfig(clientConfig) + if err != nil { + return err + } + o.NamespaceClient, err = corev1client.NewForConfig(clientConfig) if err != nil { return err } - o.RBACClient = client.Rbac() - o.NamespaceClient = client.Core().Namespaces() - dryRun := false - output := cmdutil.GetFlagString(cmd, "output") - shortOutput := output == "name" - o.Print = func(info *resource.Info) error { - if len(output) > 0 && !shortOutput { - return cmdutil.PrintObject(cmd, info.Object, o.Out) - } - cmdutil.PrintSuccess(shortOutput, o.Out, info.Object, dryRun, "reconciled") - return nil + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err } + o.PrintObject = printer.PrintObj return nil } @@ -138,13 +152,13 @@ func (o *ReconcileOptions) Validate() error { if o.NamespaceClient == nil { return errors.New("ReconcileOptions.NamespaceClient must be set") } - if o.Print == nil { + if o.PrintObject == nil { return errors.New("ReconcileOptions.Print must be set") } if o.Out == nil { return errors.New("ReconcileOptions.Out must be set") } - if o.Err == nil { + if o.ErrOut == nil { return errors.New("ReconcileOptions.Err must be set") } return nil @@ -156,18 +170,14 @@ func (o *ReconcileOptions) RunReconcile() error { return err } - // shallowInfoCopy this is used to later twiddle the Object for printing - // we really need more straightforward printing options - shallowInfoCopy := *info - switch t := info.Object.(type) { - case *rbac.Role: + case *rbacv1.Role: reconcileOptions := reconciliation.ReconcileRoleOptions{ - Confirm: true, + Confirm: !o.DryRun, RemoveExtraPermissions: false, Role: reconciliation.RoleRuleOwner{Role: t}, Client: reconciliation.RoleModifier{ - NamespaceClient: o.NamespaceClient, + NamespaceClient: o.NamespaceClient.Namespaces(), Client: o.RBACClient, }, } @@ -175,12 +185,11 @@ func (o *ReconcileOptions) RunReconcile() error { if err != nil { return err } - shallowInfoCopy.Object = result.Role.GetObject() - o.Print(&shallowInfoCopy) + o.PrintObject(result.Role.GetObject(), o.Out) - case *rbac.ClusterRole: + case *rbacv1.ClusterRole: reconcileOptions := reconciliation.ReconcileRoleOptions{ - Confirm: true, + Confirm: !o.DryRun, RemoveExtraPermissions: false, Role: reconciliation.ClusterRoleRuleOwner{ClusterRole: t}, Client: reconciliation.ClusterRoleModifier{ @@ -191,29 +200,27 @@ func (o *ReconcileOptions) RunReconcile() error { if err != nil { return err } - shallowInfoCopy.Object = result.Role.GetObject() - o.Print(&shallowInfoCopy) + o.PrintObject(result.Role.GetObject(), o.Out) - case *rbac.RoleBinding: + case *rbacv1.RoleBinding: reconcileOptions := reconciliation.ReconcileRoleBindingOptions{ - Confirm: true, + Confirm: !o.DryRun, RemoveExtraSubjects: false, RoleBinding: reconciliation.RoleBindingAdapter{RoleBinding: t}, Client: reconciliation.RoleBindingClientAdapter{ Client: o.RBACClient, - NamespaceClient: o.NamespaceClient, + NamespaceClient: o.NamespaceClient.Namespaces(), }, } result, err := reconcileOptions.Run() if err != nil { return err } - shallowInfoCopy.Object = result.RoleBinding.GetObject() - o.Print(&shallowInfoCopy) + o.PrintObject(result.RoleBinding.GetObject(), o.Out) - case *rbac.ClusterRoleBinding: + case *rbacv1.ClusterRoleBinding: reconcileOptions := reconciliation.ReconcileRoleBindingOptions{ - Confirm: true, + Confirm: !o.DryRun, RemoveExtraSubjects: false, RoleBinding: reconciliation.ClusterRoleBindingAdapter{ClusterRoleBinding: t}, Client: reconciliation.ClusterRoleBindingClientAdapter{ @@ -224,8 +231,7 @@ func (o *ReconcileOptions) RunReconcile() error { if err != nil { return err } - shallowInfoCopy.Object = result.RoleBinding.GetObject() - o.Print(&shallowInfoCopy) + o.PrintObject(result.RoleBinding.GetObject(), o.Out) default: glog.V(1).Infof("skipping %#v", info.Object.GetObjectKind()) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/autoscale.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/autoscale.go index 2f4e52020..e2fc58998 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/autoscale.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/autoscale.go @@ -18,16 +18,23 @@ package cmd import ( "fmt" - "io" - utilerrors "k8s.io/apimachinery/pkg/util/errors" + "github.com/golang/glog" + "github.com/spf13/cobra" + + autoscalingv1 "k8s.io/api/autoscaling/v1" + "k8s.io/apimachinery/pkg/api/meta" + autoscalingv1client "k8s.io/client-go/kubernetes/typed/autoscaling/v1" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" - - "github.com/spf13/cobra" ) var ( @@ -45,11 +52,50 @@ var ( kubectl autoscale rc foo --max=5 --cpu-percent=80`)) ) -func NewCmdAutoscale(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &resource.FilenameOptions{} +type AutoscaleOptions struct { + FilenameOptions *resource.FilenameOptions + + RecordFlags *genericclioptions.RecordFlags + Recorder genericclioptions.Recorder + + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) + + Name string + Generator string + Min int32 + Max int32 + CpuPercent int32 + + createAnnotation bool + args []string + enforceNamespace bool + namespace string + dryRun bool + builder *resource.Builder + canBeAutoscaled polymorphichelpers.CanBeAutoscaledFunc + generatorFunc func(string, *meta.RESTMapping) (kubectl.StructuredGenerator, error) + + HPAClient autoscalingv1client.HorizontalPodAutoscalersGetter + + genericclioptions.IOStreams +} + +func NewAutoscaleOptions(ioStreams genericclioptions.IOStreams) *AutoscaleOptions { + return &AutoscaleOptions{ + PrintFlags: genericclioptions.NewPrintFlags("autoscaled").WithTypeSetter(scheme.Scheme), + FilenameOptions: &resource.FilenameOptions{}, + RecordFlags: genericclioptions.NewRecordFlags(), + Recorder: genericclioptions.NoopRecorder{}, + + IOStreams: ioStreams, + } +} + +func NewCmdAutoscale(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewAutoscaleOptions(ioStreams) validArgs := []string{"deployment", "replicaset", "replicationcontroller"} - argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ Use: "autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS] --max=MAXPODS [--cpu-percent=CPU]", @@ -58,78 +104,122 @@ func NewCmdAutoscale(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: autoscaleLong, Example: autoscaleExample, Run: func(cmd *cobra.Command, args []string) { - err := RunAutoscale(f, out, cmd, args, options) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.Run()) }, - ValidArgs: validArgs, - ArgAliases: argAliases, + ValidArgs: validArgs, } - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().String("generator", cmdutil.HorizontalPodAutoscalerV1GeneratorName, i18n.T("The name of the API generator to use. Currently there is only 1 generator.")) - cmd.Flags().Int32("min", -1, "The lower limit for the number of pods that can be set by the autoscaler. If it's not specified or negative, the server will apply a default value.") - cmd.Flags().Int32("max", -1, "The upper limit for the number of pods that can be set by the autoscaler. Required.") + + // bind flag structs + o.RecordFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) + + cmd.Flags().StringVar(&o.Generator, "generator", cmdutil.HorizontalPodAutoscalerV1GeneratorName, i18n.T("The name of the API generator to use. Currently there is only 1 generator.")) + cmd.Flags().Int32Var(&o.Min, "min", -1, "The lower limit for the number of pods that can be set by the autoscaler. If it's not specified or negative, the server will apply a default value.") + cmd.Flags().Int32Var(&o.Max, "max", -1, "The upper limit for the number of pods that can be set by the autoscaler. Required.") cmd.MarkFlagRequired("max") - cmd.Flags().Int32("cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, a default autoscaling policy will be used.")) - cmd.Flags().String("name", "", i18n.T("The name for the newly created object. If not specified, the name of the input resource will be used.")) + cmd.Flags().Int32Var(&o.CpuPercent, "cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, a default autoscaling policy will be used.")) + cmd.Flags().StringVar(&o.Name, "name", "", i18n.T("The name for the newly created object. If not specified, the name of the input resource will be used.")) cmdutil.AddDryRunFlag(cmd) - usage := "identifying the resource to autoscale." - cmdutil.AddFilenameOptionFlags(cmd, options, usage) + cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, "identifying the resource to autoscale.") cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) return cmd } -func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { - namespace, enforceNamespace, err := f.DefaultNamespace() +func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run") + o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag) + o.builder = f.NewBuilder() + o.canBeAutoscaled = polymorphichelpers.CanBeAutoscaledFn + o.args = args + o.RecordFlags.Complete(cmd) + + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + + kubeClient, err := f.KubernetesClientSet() if err != nil { return err } + o.HPAClient = kubeClient.AutoscalingV1() + + // get the generator + o.generatorFunc = func(name string, mapping *meta.RESTMapping) (kubectl.StructuredGenerator, error) { + switch o.Generator { + case cmdutil.HorizontalPodAutoscalerV1GeneratorName: + return &kubectl.HorizontalPodAutoscalerGeneratorV1{ + Name: name, + MinReplicas: o.Min, + MaxReplicas: o.Max, + CPUPercent: o.CpuPercent, + ScaleRefName: name, + ScaleRefKind: mapping.GroupVersionKind.Kind, + ScaleRefApiVersion: mapping.GroupVersionKind.GroupVersion().String(), + }, nil + default: + return nil, cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", o.Generator) + } + } - // validate flags - if err := validateFlags(cmd); err != nil { + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { return err } - r := f.NewBuilder(). - Internal(). + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + if o.dryRun { + o.PrintFlags.Complete("%s (dry run)") + } + + return o.PrintFlags.ToPrinter() + } + + return nil +} + +func (o *AutoscaleOptions) Validate() error { + if o.Max < 1 { + return fmt.Errorf("--max=MAXPODS is required and must be at least 1, max: %d", o.Max) + } + if o.Max < o.Min { + return fmt.Errorf("--max=MAXPODS must be larger or equal to --min=MINPODS, max: %d, min: %d", o.Max, o.Min) + } + + return nil +} + +func (o *AutoscaleOptions) Run() error { + r := o.builder. + WithScheme(legacyscheme.Scheme). ContinueOnError(). - NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options). - ResourceTypeOrNameArgs(false, args...). + NamespaceParam(o.namespace).DefaultNamespace(). + FilenameParam(o.enforceNamespace, o.FilenameOptions). + ResourceTypeOrNameArgs(false, o.args...). Flatten(). Do() - err = r.Err() - if err != nil { + if err := r.Err(); err != nil { return err } count := 0 - err = r.Visit(func(info *resource.Info, err error) error { + err := r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } mapping := info.ResourceMapping() - if err := f.CanBeAutoscaled(mapping.GroupVersionKind.GroupKind()); err != nil { + if err := o.canBeAutoscaled(mapping.GroupVersionKind.GroupKind()); err != nil { return err } - // get the generator - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.HorizontalPodAutoscalerV1GeneratorName: - generator = &kubectl.HorizontalPodAutoscalerGeneratorV1{ - Name: info.Name, - MinReplicas: cmdutil.GetFlagInt32(cmd, "min"), - MaxReplicas: cmdutil.GetFlagInt32(cmd, "max"), - CPUPercent: cmdutil.GetFlagInt32(cmd, "cpu-percent"), - ScaleRefName: info.Name, - ScaleRefKind: mapping.GroupVersionKind.Kind, - ScaleRefApiVersion: mapping.GroupVersionKind.GroupVersion().String(), - } - default: - return errUnsupportedGenerator(cmd, generatorName) + generator, err := o.generatorFunc(info.Name, mapping) + if err != nil { + return err } // Generate new object @@ -137,44 +227,40 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s if err != nil { return err } - - mapper, typer := f.Object() - resourceMapper := &resource.Mapper{ - ObjectTyper: typer, - RESTMapper: mapper, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - Decoder: cmdutil.InternalVersionDecoder(), + hpa, ok := object.(*autoscalingv1.HorizontalPodAutoscaler) + if !ok { + return fmt.Errorf("generator made %T, not autoscalingv1.HorizontalPodAutoscaler", object) } - hpa, err := resourceMapper.InfoForObject(object, nil) - if err != nil { - return err + + if err := o.Recorder.Record(hpa); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } - if cmdutil.ShouldRecord(cmd, hpa) { - if err := cmdutil.RecordChangeCause(hpa.Object, f.Command(cmd, false)); err != nil { + + if o.dryRun { + count++ + + printer, err := o.ToPrinter("created") + if err != nil { return err } - object = hpa.Object - } - if cmdutil.GetDryRunFlag(cmd) { - return cmdutil.PrintObject(cmd, object, out) + return printer.PrintObj(hpa, o.Out) } - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), hpa, cmdutil.InternalVersionJSONEncoder()); err != nil { + if err := kubectl.CreateOrUpdateAnnotation(o.createAnnotation, hpa, cmdutil.InternalVersionJSONEncoder()); err != nil { return err } - object, err = resource.NewHelper(hpa.Client, hpa.Mapping).Create(namespace, false, object) + actualHPA, err := o.HPAClient.HorizontalPodAutoscalers(o.namespace).Create(hpa) if err != nil { return err } count++ - if len(cmdutil.GetFlagString(cmd, "output")) > 0 { - return cmdutil.PrintObject(cmd, object, out) + printer, err := o.ToPrinter("autoscaled") + if err != nil { + return err } - - cmdutil.PrintSuccess(false, out, info.Object, cmdutil.GetDryRunFlag(cmd), "autoscaled") - return nil + return printer.PrintObj(actualHPA, o.Out) }) if err != nil { return err @@ -184,15 +270,3 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s } return nil } - -func validateFlags(cmd *cobra.Command) error { - errs := []error{} - max, min := cmdutil.GetFlagInt32(cmd, "max"), cmdutil.GetFlagInt32(cmd, "min") - if max < 1 { - errs = append(errs, fmt.Errorf("--max=MAXPODS is required and must be at least 1, max: %d", max)) - } - if max < min { - errs = append(errs, fmt.Errorf("--max=MAXPODS must be larger or equal to --min=MINPODS, max: %d, min: %d", max, min)) - } - return utilerrors.NewAggregate(errs) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/certificates.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/certificates.go index f3f335c3e..36c0ff693 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/certificates.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/certificates.go @@ -20,17 +20,24 @@ import ( "fmt" "io" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/certificates" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "github.com/spf13/cobra" ) -func NewCmdCertificate(f cmdutil.Factory, out io.Writer) *cobra.Command { +func NewCmdCertificate(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "certificate SUBCOMMAND", DisableFlagsInUseLine: true, @@ -41,33 +48,61 @@ func NewCmdCertificate(f cmdutil.Factory, out io.Writer) *cobra.Command { }, } - cmd.AddCommand(NewCmdCertificateApprove(f, out)) - cmd.AddCommand(NewCmdCertificateDeny(f, out)) + cmd.AddCommand(NewCmdCertificateApprove(f, ioStreams)) + cmd.AddCommand(NewCmdCertificateDeny(f, ioStreams)) return cmd } type CertificateOptions struct { resource.FilenameOptions + + PrintFlags *genericclioptions.PrintFlags + PrintObj printers.ResourcePrinterFunc + csrNames []string outputStyle string + + clientSet internalclientset.Interface + builder *resource.Builder + + genericclioptions.IOStreams } -func (options *CertificateOptions) Complete(cmd *cobra.Command, args []string) error { - options.csrNames = args - options.outputStyle = cmdutil.GetFlagString(cmd, "output") +func (o *CertificateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + o.csrNames = args + o.outputStyle = cmdutil.GetFlagString(cmd, "output") + + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + + o.PrintObj = func(obj runtime.Object, out io.Writer) error { + return printer.PrintObj(obj, out) + } + + o.builder = f.NewBuilder() + o.clientSet, err = f.ClientSet() + if err != nil { + return err + } + return nil } -func (options *CertificateOptions) Validate() error { - if len(options.csrNames) < 1 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { +func (o *CertificateOptions) Validate() error { + if len(o.csrNames) < 1 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { return fmt.Errorf("one or more CSRs must be specified as or -f ") } return nil } -func NewCmdCertificateApprove(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := CertificateOptions{} +func NewCmdCertificateApprove(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := CertificateOptions{ + PrintFlags: genericclioptions.NewPrintFlags("approved").WithTypeSetter(scheme.Scheme), + IOStreams: ioStreams, + } cmd := &cobra.Command{ Use: "approve (-f FILENAME | NAME)", DisableFlagsInUseLine: true, @@ -85,19 +120,22 @@ func NewCmdCertificateApprove(f cmdutil.Factory, out io.Writer) *cobra.Command { signed certificate can do. `), Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(cmd, args)) + cmdutil.CheckErr(options.Complete(f, cmd, args)) cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.RunCertificateApprove(f, out)) + cmdutil.CheckErr(options.RunCertificateApprove(cmdutil.GetFlagBool(cmd, "force"))) }, } - cmdutil.AddOutputFlagsForMutation(cmd) + + options.PrintFlags.AddFlags(cmd) + + cmd.Flags().Bool("force", false, "Update the CSR even if it is already approved.") cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to update") return cmd } -func (options *CertificateOptions) RunCertificateApprove(f cmdutil.Factory, out io.Writer) error { - return options.modifyCertificateCondition(f, out, func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, string) { +func (o *CertificateOptions) RunCertificateApprove(force bool) error { + return o.modifyCertificateCondition(o.builder, o.clientSet, force, func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, bool) { var alreadyApproved bool for _, c := range csr.Status.Conditions { if c.Type == certificates.CertificateApproved { @@ -105,7 +143,7 @@ func (options *CertificateOptions) RunCertificateApprove(f cmdutil.Factory, out } } if alreadyApproved { - return csr, "approved" + return csr, true } csr.Status.Conditions = append(csr.Status.Conditions, certificates.CertificateSigningRequestCondition{ Type: certificates.CertificateApproved, @@ -113,12 +151,15 @@ func (options *CertificateOptions) RunCertificateApprove(f cmdutil.Factory, out Message: "This CSR was approved by kubectl certificate approve.", LastUpdateTime: metav1.Now(), }) - return csr, "approved" + return csr, false }) } -func NewCmdCertificateDeny(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := CertificateOptions{} +func NewCmdCertificateDeny(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := CertificateOptions{ + PrintFlags: genericclioptions.NewPrintFlags("denied").WithTypeSetter(scheme.Scheme), + IOStreams: ioStreams, + } cmd := &cobra.Command{ Use: "deny (-f FILENAME | NAME)", DisableFlagsInUseLine: true, @@ -131,19 +172,22 @@ func NewCmdCertificateDeny(f cmdutil.Factory, out io.Writer) *cobra.Command { not to issue a certificate to the requestor. `), Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(cmd, args)) + cmdutil.CheckErr(options.Complete(f, cmd, args)) cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.RunCertificateDeny(f, out)) + cmdutil.CheckErr(options.RunCertificateDeny(cmdutil.GetFlagBool(cmd, "force"))) }, } - cmdutil.AddOutputFlagsForMutation(cmd) + + options.PrintFlags.AddFlags(cmd) + + cmd.Flags().Bool("force", false, "Update the CSR even if it is already denied.") cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to update") return cmd } -func (options *CertificateOptions) RunCertificateDeny(f cmdutil.Factory, out io.Writer) error { - return options.modifyCertificateCondition(f, out, func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, string) { +func (o *CertificateOptions) RunCertificateDeny(force bool) error { + return o.modifyCertificateCondition(o.builder, o.clientSet, force, func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, bool) { var alreadyDenied bool for _, c := range csr.Status.Conditions { if c.Type == certificates.CertificateDenied { @@ -151,7 +195,7 @@ func (options *CertificateOptions) RunCertificateDeny(f cmdutil.Factory, out io. } } if alreadyDenied { - return csr, "denied" + return csr, true } csr.Status.Conditions = append(csr.Status.Conditions, certificates.CertificateSigningRequestCondition{ Type: certificates.CertificateDenied, @@ -159,18 +203,14 @@ func (options *CertificateOptions) RunCertificateDeny(f cmdutil.Factory, out io. Message: "This CSR was approved by kubectl certificate deny.", LastUpdateTime: metav1.Now(), }) - return csr, "denied" + return csr, false }) } -func (options *CertificateOptions) modifyCertificateCondition(f cmdutil.Factory, out io.Writer, modify func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, string)) error { +func (options *CertificateOptions) modifyCertificateCondition(builder *resource.Builder, clientSet internalclientset.Interface, force bool, modify func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, bool)) error { var found int - c, err := f.ClientSet() - if err != nil { - return err - } - r := f.NewBuilder(). - Internal(). + r := builder. + WithScheme(legacyscheme.Scheme). ContinueOnError(). FilenameParam(false, &options.FilenameOptions). ResourceNames("certificatesigningrequest", options.csrNames...). @@ -178,24 +218,35 @@ func (options *CertificateOptions) modifyCertificateCondition(f cmdutil.Factory, Flatten(). Latest(). Do() - err = r.Visit(func(info *resource.Info, err error) error { + err := r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } - csr := info.Object.(*certificates.CertificateSigningRequest) - csr, verb := modify(csr) - csr, err = c.Certificates(). - CertificateSigningRequests(). - UpdateApproval(csr) - if err != nil { - return err + for i := 0; ; i++ { + csr := info.Object.(*certificates.CertificateSigningRequest) + csr, hasCondition := modify(csr) + if !hasCondition || force { + csr, err = clientSet.Certificates(). + CertificateSigningRequests(). + UpdateApproval(csr) + if errors.IsConflict(err) && i < 10 { + if err := info.Get(); err != nil { + return err + } + continue + } + if err != nil { + return err + } + } + break } found++ - cmdutil.PrintSuccess(options.outputStyle == "name", out, info.Object, false, verb) - return nil + + return options.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), options.Out) }) if found == 0 { - fmt.Fprintf(out, "No resources found\n") + fmt.Fprintf(options.Out, "No resources found\n") } return err } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo.go index 2e2b7a8b9..655dda9d4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo.go @@ -23,10 +23,13 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilnet "k8s.io/apimachinery/pkg/util/net" + restclient "k8s.io/client-go/rest" + "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ct "github.com/daviddengcn/go-colortext" @@ -43,42 +46,62 @@ var ( kubectl cluster-info`)) ) -func NewCmdClusterInfo(f cmdutil.Factory, out io.Writer) *cobra.Command { +type ClusterInfoOptions struct { + genericclioptions.IOStreams + + Namespace string + + Builder *resource.Builder + Client *restclient.Config +} + +func NewCmdClusterInfo(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := &ClusterInfoOptions{ + IOStreams: ioStreams, + } + cmd := &cobra.Command{ Use: "cluster-info", Short: i18n.T("Display cluster info"), Long: longDescr, Example: clusterinfoExample, Run: func(cmd *cobra.Command, args []string) { - err := RunClusterInfo(f, out, cmd) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd)) + cmdutil.CheckErr(o.Run()) }, } - cmdutil.AddInclude3rdPartyFlags(cmd) - cmd.AddCommand(NewCmdClusterInfoDump(f, out)) + cmd.AddCommand(NewCmdClusterInfoDump(f, ioStreams)) return cmd } -func RunClusterInfo(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { - client, err := f.ClientConfig() +func (o *ClusterInfoOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { + var err error + o.Client, err = f.ToRESTConfig() if err != nil { return err } - printService(out, "Kubernetes master", client.Host) cmdNamespace := cmdutil.GetFlagString(cmd, "namespace") if cmdNamespace == "" { cmdNamespace = metav1.NamespaceSystem } + o.Namespace = cmdNamespace + + o.Builder = f.NewBuilder() + return nil +} + +func (o *ClusterInfoOptions) Run() error { + printService(o.Out, "Kubernetes master", o.Client.Host) // TODO use generalized labels once they are implemented (#341) - b := f.NewBuilder(). - Internal(). - NamespaceParam(cmdNamespace).DefaultNamespace(). + b := o.Builder. + WithScheme(legacyscheme.Scheme). + NamespaceParam(o.Namespace).DefaultNamespace(). LabelSelectorParam("kubernetes.io/cluster-service=true"). ResourceTypeOrNameArgs(false, []string{"services"}...). Latest() - err = b.Do().Visit(func(r *resource.Info, err error) error { + err := b.Do().Visit(func(r *resource.Info, err error) error { if err != nil { return err } @@ -110,10 +133,10 @@ func RunClusterInfo(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error name = utilnet.JoinSchemeNamePort(scheme, service.ObjectMeta.Name, port.Name) } - if len(client.GroupVersion.Group) == 0 { - link = client.Host + "/api/" + client.GroupVersion.Version + "/namespaces/" + service.ObjectMeta.Namespace + "/services/" + name + "/proxy" + if len(o.Client.GroupVersion.Group) == 0 { + link = o.Client.Host + "/api/" + o.Client.GroupVersion.Version + "/namespaces/" + service.ObjectMeta.Namespace + "/services/" + name + "/proxy" } else { - link = client.Host + "/api/" + client.GroupVersion.Group + "/" + client.GroupVersion.Version + "/namespaces/" + service.ObjectMeta.Namespace + "/services/" + name + "/proxy" + link = o.Client.Host + "/api/" + o.Client.GroupVersion.Group + "/" + o.Client.GroupVersion.Version + "/namespaces/" + service.ObjectMeta.Namespace + "/services/" + name + "/proxy" } } @@ -121,11 +144,11 @@ func RunClusterInfo(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error if len(name) == 0 { name = service.ObjectMeta.Name } - printService(out, name, link) + printService(o.Out, name, link) } return nil }) - out.Write([]byte("\nTo further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\n")) + o.Out.Write([]byte("\nTo further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\n")) return err // TODO consider printing more information about cluster diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo_dump.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo_dump.go index 511bba5d9..516a5e9cf 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo_dump.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo_dump.go @@ -21,31 +21,66 @@ import ( "io" "os" "path" + "time" "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + appsv1client "k8s.io/client-go/kubernetes/typed/apps/v1" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" - "k8s.io/kubernetes/pkg/printers" ) +type ClusterInfoDumpOptions struct { + PrintFlags *genericclioptions.PrintFlags + PrintObj printers.ResourcePrinterFunc + + OutputDir string + AllNamespaces bool + Namespaces []string + + Timeout time.Duration + AppsClient appsv1client.AppsV1Interface + CoreClient corev1client.CoreV1Interface + Namespace string + RESTClientGetter genericclioptions.RESTClientGetter + LogsForObject polymorphichelpers.LogsForObjectFunc + + genericclioptions.IOStreams +} + // NewCmdCreateSecret groups subcommands to create various types of secrets -func NewCmdClusterInfoDump(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdClusterInfoDump(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := &ClusterInfoDumpOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithTypeSetter(scheme.Scheme).WithDefaultOutput("json"), + + IOStreams: ioStreams, + } + cmd := &cobra.Command{ Use: "dump", Short: i18n.T("Dump lots of relevant info for debugging and diagnosis"), Long: dumpLong, Example: dumpExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(dumpClusterInfo(f, cmd, cmdOut)) + cmdutil.CheckErr(o.Complete(f, cmd)) + cmdutil.CheckErr(o.Run()) }, } - cmd.Flags().String("output-directory", "", i18n.T("Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory")) - cmd.Flags().StringSlice("namespaces", []string{}, "A comma separated list of namespaces to dump.") - cmd.Flags().Bool("all-namespaces", false, "If true, dump all namespaces. If true, --namespaces is ignored.") + + o.PrintFlags.AddFlags(cmd) + + cmd.Flags().StringVar(&o.OutputDir, "output-directory", o.OutputDir, i18n.T("Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory")) + cmd.Flags().StringSliceVar(&o.Namespaces, "namespaces", o.Namespaces, "A comma separated list of namespaces to dump.") + cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If true, dump all namespaces. If true, --namespaces is ignored.") cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodLogsTimeout) return cmd } @@ -74,8 +109,7 @@ var ( kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state`)) ) -func setupOutputWriter(cmd *cobra.Command, defaultWriter io.Writer, filename string) io.Writer { - dir := cmdutil.GetFlagString(cmd, "output-directory") +func setupOutputWriter(dir string, defaultWriter io.Writer, filename string) io.Writer { if len(dir) == 0 || dir == "-" { return defaultWriter } @@ -88,31 +122,58 @@ func setupOutputWriter(cmd *cobra.Command, defaultWriter io.Writer, filename str return file } -func dumpClusterInfo(f cmdutil.Factory, cmd *cobra.Command, out io.Writer) error { - timeout, err := cmdutil.GetPodRunningTimeoutFlag(cmd) +func (o *ClusterInfoDumpOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { + printer, err := o.PrintFlags.ToPrinter() if err != nil { - return cmdutil.UsageErrorf(cmd, err.Error()) + return err } - clientset, err := f.ClientSet() + o.PrintObj = printer.PrintObj + + config, err := f.ToRESTConfig() if err != nil { return err } - printer := &printers.JSONPrinter{} + o.CoreClient, err = corev1client.NewForConfig(config) + if err != nil { + return err + } - nodes, err := clientset.Core().Nodes().List(metav1.ListOptions{}) + o.AppsClient, err = appsv1client.NewForConfig(config) if err != nil { return err } - if err := printer.PrintObj(nodes, setupOutputWriter(cmd, out, "nodes.json")); err != nil { + o.Timeout, err = cmdutil.GetPodRunningTimeoutFlag(cmd) + if err != nil { + return err + } + + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + // TODO this should eventually just be the completed kubeconfigflag struct + o.RESTClientGetter = f + o.LogsForObject = polymorphichelpers.LogsForObjectFn + + return nil +} + +func (o *ClusterInfoDumpOptions) Run() error { + nodes, err := o.CoreClient.Nodes().List(metav1.ListOptions{}) + if err != nil { + return err + } + + if err := o.PrintObj(nodes, setupOutputWriter(o.OutputDir, o.Out, "nodes.json")); err != nil { return err } var namespaces []string - if cmdutil.GetFlagBool(cmd, "all-namespaces") { - namespaceList, err := clientset.Core().Namespaces().List(metav1.ListOptions{}) + if o.AllNamespaces { + namespaceList, err := o.CoreClient.Namespaces().List(metav1.ListOptions{}) if err != nil { return err } @@ -120,83 +181,78 @@ func dumpClusterInfo(f cmdutil.Factory, cmd *cobra.Command, out io.Writer) error namespaces = append(namespaces, namespaceList.Items[ix].Name) } } else { - namespaces = cmdutil.GetFlagStringSlice(cmd, "namespaces") - if len(namespaces) == 0 { - cmdNamespace, _, err := f.DefaultNamespace() - if err != nil { - return err - } + if len(o.Namespaces) == 0 { namespaces = []string{ metav1.NamespaceSystem, - cmdNamespace, + o.Namespace, } } } for _, namespace := range namespaces { // TODO: this is repetitive in the extreme. Use reflection or // something to make this a for loop. - events, err := clientset.Core().Events(namespace).List(metav1.ListOptions{}) + events, err := o.CoreClient.Events(namespace).List(metav1.ListOptions{}) if err != nil { return err } - if err := printer.PrintObj(events, setupOutputWriter(cmd, out, path.Join(namespace, "events.json"))); err != nil { + if err := o.PrintObj(events, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "events.json"))); err != nil { return err } - rcs, err := clientset.Core().ReplicationControllers(namespace).List(metav1.ListOptions{}) + rcs, err := o.CoreClient.ReplicationControllers(namespace).List(metav1.ListOptions{}) if err != nil { return err } - if err := printer.PrintObj(rcs, setupOutputWriter(cmd, out, path.Join(namespace, "replication-controllers.json"))); err != nil { + if err := o.PrintObj(rcs, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "replication-controllers.json"))); err != nil { return err } - svcs, err := clientset.Core().Services(namespace).List(metav1.ListOptions{}) + svcs, err := o.CoreClient.Services(namespace).List(metav1.ListOptions{}) if err != nil { return err } - if err := printer.PrintObj(svcs, setupOutputWriter(cmd, out, path.Join(namespace, "services.json"))); err != nil { + if err := o.PrintObj(svcs, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "services.json"))); err != nil { return err } - sets, err := clientset.Extensions().DaemonSets(namespace).List(metav1.ListOptions{}) + sets, err := o.AppsClient.DaemonSets(namespace).List(metav1.ListOptions{}) if err != nil { return err } - if err := printer.PrintObj(sets, setupOutputWriter(cmd, out, path.Join(namespace, "daemonsets.json"))); err != nil { + if err := o.PrintObj(sets, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "daemonsets.json"))); err != nil { return err } - deps, err := clientset.Extensions().Deployments(namespace).List(metav1.ListOptions{}) + deps, err := o.AppsClient.Deployments(namespace).List(metav1.ListOptions{}) if err != nil { return err } - if err := printer.PrintObj(deps, setupOutputWriter(cmd, out, path.Join(namespace, "deployments.json"))); err != nil { + if err := o.PrintObj(deps, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "deployments.json"))); err != nil { return err } - rps, err := clientset.Extensions().ReplicaSets(namespace).List(metav1.ListOptions{}) + rps, err := o.AppsClient.ReplicaSets(namespace).List(metav1.ListOptions{}) if err != nil { return err } - if err := printer.PrintObj(rps, setupOutputWriter(cmd, out, path.Join(namespace, "replicasets.json"))); err != nil { + if err := o.PrintObj(rps, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "replicasets.json"))); err != nil { return err } - pods, err := clientset.Core().Pods(namespace).List(metav1.ListOptions{}) + pods, err := o.CoreClient.Pods(namespace).List(metav1.ListOptions{}) if err != nil { return err } - if err := printer.PrintObj(pods, setupOutputWriter(cmd, out, path.Join(namespace, "pods.json"))); err != nil { + if err := o.PrintObj(pods, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "pods.json"))); err != nil { return err } - printContainer := func(writer io.Writer, container api.Container, pod *api.Pod) { + printContainer := func(writer io.Writer, container corev1.Container, pod *corev1.Pod) { writer.Write([]byte(fmt.Sprintf("==== START logs for container %s of pod %s/%s ====\n", container.Name, pod.Namespace, pod.Name))) defer writer.Write([]byte(fmt.Sprintf("==== END logs for container %s of pod %s/%s ====\n", container.Name, pod.Namespace, pod.Name))) - request, err := f.LogsForObject(pod, &api.PodLogOptions{Container: container.Name}, timeout) + request, err := o.LogsForObject(o.RESTClientGetter, pod, &api.PodLogOptions{Container: container.Name}, timeout) if err != nil { // Print error and return. writer.Write([]byte(fmt.Sprintf("Create log request error: %s\n", err.Error()))) @@ -215,19 +271,20 @@ func dumpClusterInfo(f cmdutil.Factory, cmd *cobra.Command, out io.Writer) error for ix := range pods.Items { pod := &pods.Items[ix] containers := pod.Spec.Containers - writer := setupOutputWriter(cmd, out, path.Join(namespace, pod.Name, "logs.txt")) + writer := setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, pod.Name, "logs.txt")) for i := range containers { printContainer(writer, containers[i], pod) } } } - dir := cmdutil.GetFlagString(cmd, "output-directory") - if len(dir) == 0 { - dir = "standard output" + + dest := o.OutputDir + if len(dest) == 0 { + dest = "standard output" } - if dir != "-" { - fmt.Fprintf(out, "Cluster info dumped to %s\n", dir) + if dest != "-" { + fmt.Fprintf(o.Out, "Cluster info dumped to %s\n", dest) } return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo_dump_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo_dump_test.go index f4a1a1145..c600ef29f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo_dump_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo_dump_test.go @@ -17,27 +17,25 @@ limitations under the License. package cmd import ( - "bytes" "io/ioutil" "os" "path" "testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestSetupOutputWriterNoOp(t *testing.T) { tests := []string{"", "-"} for _, test := range tests { - out := &bytes.Buffer{} + _, _, buf, _ := genericclioptions.NewTestIOStreams() f := cmdtesting.NewTestFactory() defer f.Cleanup() - cmd := NewCmdClusterInfoDump(f, os.Stdout) - cmd.Flag("output-directory").Value.Set(test) - writer := setupOutputWriter(cmd, out, "/some/file/that/should/be/ignored") - if writer != out { - t.Errorf("expected: %v, saw: %v", out, writer) + writer := setupOutputWriter(test, buf, "/some/file/that/should/be/ignored") + if writer != buf { + t.Errorf("expected: %v, saw: %v", buf, writer) } } } @@ -51,15 +49,13 @@ func TestSetupOutputWriterFile(t *testing.T) { fullPath := path.Join(dir, file) defer os.RemoveAll(dir) - out := &bytes.Buffer{} + _, _, buf, _ := genericclioptions.NewTestIOStreams() f := cmdtesting.NewTestFactory() defer f.Cleanup() - cmd := NewCmdClusterInfoDump(f, os.Stdout) - cmd.Flag("output-directory").Value.Set(dir) - writer := setupOutputWriter(cmd, out, file) - if writer == out { - t.Errorf("expected: %v, saw: %v", out, writer) + writer := setupOutputWriter(dir, buf, file) + if writer == buf { + t.Errorf("expected: %v, saw: %v", buf, writer) } output := "some data here" writer.Write([]byte(output)) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go index 3bdd843b9..025ba0459 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go @@ -17,22 +17,27 @@ limitations under the License. package cmd import ( + "flag" "fmt" "io" "os" - "k8s.io/apiserver/pkg/util/flag" + "k8s.io/apimachinery/pkg/api/meta" + utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/client-go/tools/clientcmd" "k8s.io/kubernetes/pkg/kubectl/cmd/auth" cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config" - "k8s.io/kubernetes/pkg/kubectl/cmd/resource" + "k8s.io/kubernetes/pkg/kubectl/cmd/create" + "k8s.io/kubernetes/pkg/kubectl/cmd/get" "k8s.io/kubernetes/pkg/kubectl/cmd/rollout" "k8s.io/kubernetes/pkg/kubectl/cmd/set" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/cmd/wait" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) const ( @@ -57,9 +62,6 @@ __kubectl_override_flags() ;; esac done - if [ "${w}" == "--all-namespaces" ]; then - namespace="--all-namespaces" - fi done for var in "${__kubectl_override_flag_list[@]##*-}"; do if eval "test -n \"\$${var}\""; then @@ -93,20 +95,27 @@ __kubectl_parse_config() fi } +# $1 is the name of resource (required) +# $2 is template string for kubectl get (optional) __kubectl_parse_get() { local template - template="{{ range .items }}{{ .metadata.name }} {{ end }}" + template="${2:-"{{ range .items }}{{ .metadata.name }} {{ end }}"}" local kubectl_out if kubectl_out=$(kubectl get $(__kubectl_override_flags) -o template --template="${template}" "$1" 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) ) + COMPREPLY+=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) ) fi } __kubectl_get_resource() { if [[ ${#nouns[@]} -eq 0 ]]; then - return 1 + local kubectl_out + if kubectl_out=$(kubectl api-resources $(__kubectl_override_flags) -o name --cached --request-timeout=5s --verbs=get 2>/dev/null); then + COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) ) + return 0 + fi + return 1 fi __kubectl_parse_get "${nouns[${#nouns[@]} -1]}" } @@ -140,7 +149,7 @@ __kubectl_get_resource_clusterrole() __kubectl_get_containers() { local template - template="{{ range .spec.containers }}{{ .name }} {{ end }}" + template="{{ range .spec.initContainers }}{{ .name }} {{end}}{{ range .spec.containers }}{{ .name }} {{ end }}" __kubectl_debug "${FUNCNAME} nouns are ${nouns[*]}" local len="${#nouns[@]}" @@ -165,10 +174,41 @@ __kubectl_require_pod_and_container() return 0 } +__kubectl_cp() +{ + if [[ $(type -t compopt) = "builtin" ]]; then + compopt -o nospace + fi + + case "$cur" in + /*|[.~]*) # looks like a path + return + ;; + *:*) # TODO: complete remote files in the pod + return + ;; + */*) # complete / + local template namespace kubectl_out + template="{{ range .items }}{{ .metadata.namespace }}/{{ .metadata.name }}: {{ end }}" + namespace="${cur%%/*}" + if kubectl_out=( $(kubectl get $(__kubectl_override_flags) --namespace "${namespace}" -o template --template="${template}" pods 2>/dev/null) ); then + COMPREPLY=( $(compgen -W "${kubectl_out[*]}" -- "${cur}") ) + fi + return + ;; + *) # complete namespaces, pods, and filedirs + __kubectl_parse_get "namespace" "{{ range .items }}{{ .metadata.name }}/ {{ end }}" + __kubectl_parse_get "pod" "{{ range .items }}{{ .metadata.name }}: {{ end }}" + _filedir + ;; + esac +} + __custom_func() { case ${last_command} in kubectl_get | kubectl_describe | kubectl_delete | kubectl_label | kubectl_edit | kubectl_patch |\ - kubectl_annotate | kubectl_expose | kubectl_scale | kubectl_autoscale | kubectl_taint | kubectl_rollout_*) + kubectl_annotate | kubectl_expose | kubectl_scale | kubectl_autoscale | kubectl_taint | kubectl_rollout_* |\ + kubectl_apply_edit-last-applied | kubectl_apply_view-last-applied) __kubectl_get_resource return ;; @@ -196,6 +236,10 @@ __custom_func() { __kubectl_config_get_clusters return ;; + kubectl_cp) + __kubectl_cp + return + ;; *) ;; esac @@ -213,11 +257,11 @@ var ( ) func NewDefaultKubectlCommand() *cobra.Command { - return NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr) + return NewKubectlCommand(os.Stdin, os.Stdout, os.Stderr) } // NewKubectlCommand creates the `kubectl` command and its nested children. -func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command { +func NewKubectlCommand(in io.Reader, out, err io.Writer) *cobra.Command { // Parent command to which all subcommands are added. cmds := &cobra.Command{ Use: "kubectl", @@ -231,8 +275,21 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob BashCompletionFunction: bashCompletionFunc, } - f.BindFlags(cmds.PersistentFlags()) - f.BindExternalFlags(cmds.PersistentFlags()) + flags := cmds.PersistentFlags() + flags.SetNormalizeFunc(utilflag.WarnWordSepNormalizeFunc) // Warn for "_" flags + + // Normalize all flags that are coming from other packages or pre-configurations + // a.k.a. change all "_" to "-". e.g. glog package + flags.SetNormalizeFunc(utilflag.WordSepNormalizeFunc) + + kubeConfigFlags := genericclioptions.NewConfigFlags() + kubeConfigFlags.AddFlags(flags) + matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags) + matchVersionKubeConfigFlags.AddFlags(cmds.PersistentFlags()) + + cmds.PersistentFlags().AddGoFlagSet(flag.CommandLine) + + f := cmdutil.NewFactory(matchVersionKubeConfigFlags) // Sending in 'nil' for the getLanguageFn() results in using // the LANG environment variable. @@ -242,77 +299,80 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob i18n.LoadTranslations("kubectl", nil) // From this point and forward we get warnings on flags that contain "_" separators - cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc) + cmds.SetGlobalNormalizationFunc(utilflag.WarnWordSepNormalizeFunc) + + ioStreams := genericclioptions.IOStreams{In: in, Out: out, ErrOut: err} groups := templates.CommandGroups{ { Message: "Basic Commands (Beginner):", Commands: []*cobra.Command{ - NewCmdCreate(f, out, err), - NewCmdExposeService(f, out), - NewCmdRun(f, in, out, err), - set.NewCmdSet(f, in, out, err), - deprecatedAlias("run-container", NewCmdRun(f, in, out, err)), + create.NewCmdCreate(f, ioStreams), + NewCmdExposeService(f, ioStreams), + NewCmdRun(f, ioStreams), + set.NewCmdSet(f, ioStreams), + deprecatedAlias("run-container", NewCmdRun(f, ioStreams)), }, }, { Message: "Basic Commands (Intermediate):", Commands: []*cobra.Command{ - resource.NewCmdGet(f, out, err), - NewCmdExplain(f, out, err), - NewCmdEdit(f, out, err), - NewCmdDelete(f, out, err), + NewCmdExplain("kubectl", f, ioStreams), + get.NewCmdGet("kubectl", f, ioStreams), + NewCmdEdit(f, ioStreams), + NewCmdDelete(f, ioStreams), }, }, { Message: "Deploy Commands:", Commands: []*cobra.Command{ - rollout.NewCmdRollout(f, out, err), - NewCmdRollingUpdate(f, out), - NewCmdScale(f, out, err), - NewCmdAutoscale(f, out), + rollout.NewCmdRollout(f, ioStreams), + NewCmdRollingUpdate(f, ioStreams), + NewCmdScale(f, ioStreams), + NewCmdAutoscale(f, ioStreams), }, }, { Message: "Cluster Management Commands:", Commands: []*cobra.Command{ - NewCmdCertificate(f, out), - NewCmdClusterInfo(f, out), - NewCmdTop(f, out, err), - NewCmdCordon(f, out), - NewCmdUncordon(f, out), - NewCmdDrain(f, out, err), - NewCmdTaint(f, out), + NewCmdCertificate(f, ioStreams), + NewCmdClusterInfo(f, ioStreams), + NewCmdTop(f, ioStreams), + NewCmdCordon(f, ioStreams), + NewCmdUncordon(f, ioStreams), + NewCmdDrain(f, ioStreams), + NewCmdTaint(f, ioStreams), }, }, { Message: "Troubleshooting and Debugging Commands:", Commands: []*cobra.Command{ - NewCmdDescribe(f, out, err), - NewCmdLogs(f, out, err), - NewCmdAttach(f, in, out, err), - NewCmdExec(f, in, out, err), - NewCmdPortForward(f, out, err), - NewCmdProxy(f, out), - NewCmdCp(f, out, err), - auth.NewCmdAuth(f, out, err), + NewCmdDescribe("kubectl", f, ioStreams), + NewCmdLogs(f, ioStreams), + NewCmdAttach(f, ioStreams), + NewCmdExec(f, ioStreams), + NewCmdPortForward(f, ioStreams), + NewCmdProxy(f, ioStreams), + NewCmdCp(f, ioStreams), + auth.NewCmdAuth(f, ioStreams), }, }, { Message: "Advanced Commands:", Commands: []*cobra.Command{ - NewCmdApply("kubectl", f, out, err), - NewCmdPatch(f, out), - NewCmdReplace(f, out), - NewCmdConvert(f, out), + NewCmdApply("kubectl", f, ioStreams), + NewCmdPatch(f, ioStreams), + NewCmdReplace(f, ioStreams), + wait.NewCmdWait(f, ioStreams), + NewCmdConvert(f, ioStreams), }, }, { Message: "Settings Commands:", Commands: []*cobra.Command{ - NewCmdLabel(f, out), - NewCmdAnnotate(f, out), - NewCmdCompletion(out, ""), + NewCmdLabel(f, ioStreams), + NewCmdAnnotate("kubectl", f, ioStreams), + NewCmdCompletion(ioStreams.Out, ""), }, }, } @@ -321,7 +381,7 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob filters := []string{"options"} // Hide the "alpha" subcommand if there are no alpha commands in this build. - alpha := NewCmdAlpha(f, in, out, err) + alpha := NewCmdAlpha(f, ioStreams) if !alpha.HasSubCommands() { filters = append(filters, alpha.Name()) } @@ -341,11 +401,12 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob } cmds.AddCommand(alpha) - cmds.AddCommand(cmdconfig.NewCmdConfig(f, clientcmd.NewDefaultPathOptions(), out, err)) - cmds.AddCommand(NewCmdPlugin(f, in, out, err)) - cmds.AddCommand(NewCmdVersion(f, out)) - cmds.AddCommand(NewCmdApiVersions(f, out)) - cmds.AddCommand(NewCmdOptions(out)) + cmds.AddCommand(cmdconfig.NewCmdConfig(f, clientcmd.NewDefaultPathOptions(), ioStreams)) + cmds.AddCommand(NewCmdPlugin(f, ioStreams)) + cmds.AddCommand(NewCmdVersion(f, ioStreams)) + cmds.AddCommand(NewCmdApiVersions(f, ioStreams)) + cmds.AddCommand(NewCmdApiResources(f, ioStreams)) + cmds.AddCommand(NewCmdOptions(ioStreams.Out)) return cmds } @@ -372,3 +433,5 @@ func deprecatedAlias(deprecatedVersion string, cmd *cobra.Command) *cobra.Comman cmd.Hidden = true return cmd } + +var metadataAccessor = meta.NewAccessor() diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_printing_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_printing_test.go new file mode 100644 index 000000000..10df477aa --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_printing_test.go @@ -0,0 +1,234 @@ +/* +Copyright 2018 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 cmd + +import ( + "bytes" + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + genericprinters "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/scheme" + "k8s.io/kubernetes/pkg/printers" +) + +func TestIllegalPackageSourceCheckerThroughPrintFlags(t *testing.T) { + testCases := []struct { + name string + expectInternalObjErr bool + output string + obj runtime.Object + expectedOutput string + }{ + { + name: "success printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + obj: internalPod(), + }, + { + name: "success printer: object containing package path with no forbidden prefix returns no error", + expectInternalObjErr: false, + obj: externalPod(), + output: "", + expectedOutput: "pod/foo succeeded\n", + }, + { + name: "name printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + output: "name", + obj: internalPod(), + }, + { + name: "json printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + output: "json", + obj: internalPod(), + }, + { + name: "json printer: object containing package path with no forbidden prefix returns no error", + expectInternalObjErr: false, + obj: externalPod(), + output: "json", + }, + { + name: "yaml printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + output: "yaml", + obj: internalPod(), + }, + { + name: "yaml printer: object containing package path with no forbidden prefix returns no error", + expectInternalObjErr: false, + obj: externalPod(), + output: "yaml", + }, + } + + for _, tc := range testCases { + printFlags := genericclioptions.NewPrintFlags("succeeded").WithTypeSetter(scheme.Scheme) + printFlags.OutputFormat = &tc.output + + printer, err := printFlags.ToPrinter() + if err != nil { + t.Fatalf("unexpected error %v", err) + } + + output := bytes.NewBuffer([]byte{}) + + err = printer.PrintObj(tc.obj, output) + if err != nil { + if !tc.expectInternalObjErr { + t.Fatalf("unexpected error %v", err) + } + + if !genericprinters.IsInternalObjectError(err) { + t.Fatalf("unexpected error - expecting internal object printer error, got %q", err) + } + continue + } + + if tc.expectInternalObjErr { + t.Fatalf("expected internal object printer error, but got no error") + } + + if len(tc.expectedOutput) == 0 { + continue + } + + if tc.expectedOutput != output.String() { + t.Fatalf("unexpected output: expecting %q, got %q", tc.expectedOutput, output.String()) + } + } +} + +func TestIllegalPackageSourceCheckerDirectlyThroughPrinters(t *testing.T) { + jsonPathPrinter, err := genericprinters.NewJSONPathPrinter("{ .metadata.name }") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + goTemplatePrinter, err := genericprinters.NewGoTemplatePrinter([]byte("{{ .metadata.name }}")) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + customColumns, err := printers.NewCustomColumnsPrinterFromSpec("NAME:.metadata.name", scheme.Codecs.UniversalDecoder(), true) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + testCases := []struct { + name string + expectInternalObjErr bool + printer genericprinters.ResourcePrinter + obj runtime.Object + expectedOutput string + }{ + { + name: "json printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + printer: &genericprinters.JSONPrinter{}, + obj: internalPod(), + }, + { + name: "yaml printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + printer: &genericprinters.YAMLPrinter{}, + obj: internalPod(), + }, + { + name: "jsonpath printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + printer: jsonPathPrinter, + obj: internalPod(), + }, + { + name: "go-template printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + printer: goTemplatePrinter, + obj: internalPod(), + }, + { + name: "go-template printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + printer: goTemplatePrinter, + obj: internalPod(), + }, + { + name: "custom-columns printer: object containing package path beginning with forbidden prefix is rejected", + expectInternalObjErr: true, + printer: customColumns, + obj: internalPod(), + }, + } + + for _, tc := range testCases { + output := bytes.NewBuffer([]byte{}) + + err := tc.printer.PrintObj(tc.obj, output) + if err != nil { + if !tc.expectInternalObjErr { + t.Fatalf("unexpected error %v", err) + } + + if !genericprinters.IsInternalObjectError(err) { + t.Fatalf("unexpected error - expecting internal object printer error, got %q", err) + } + continue + } + + if tc.expectInternalObjErr { + t.Fatalf("expected internal object printer error, but got no error") + } + + if len(tc.expectedOutput) == 0 { + continue + } + + if tc.expectedOutput != output.String() { + t.Fatalf("unexpected output: expecting %q, got %q", tc.expectedOutput, output.String()) + } + } +} + +func internalPod() *api.Pod { + return &api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: "bar", + }, + }, + }, + Status: api.PodStatus{ + Phase: api.PodRunning, + }, + } +} + +func externalPod() *v1.Pod { + return &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_test.go index b694aa640..8ae9c6054 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_test.go @@ -19,7 +19,6 @@ package cmd import ( "bytes" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -35,17 +34,11 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/kubectl/cmd/resource" - cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/scheme" - "k8s.io/kubernetes/pkg/printers" - "k8s.io/kubernetes/pkg/util/strings" ) // This init should be removed after switching this command and its tests to user external types. @@ -122,44 +115,6 @@ func testData() (*api.PodList, *api.ServiceList, *api.ReplicationControllerList) return pods, svc, rc } -type testPrinter struct { - Objects []runtime.Object - Err error - GenericPrinter bool -} - -func (t *testPrinter) PrintObj(obj runtime.Object, out io.Writer) error { - t.Objects = append(t.Objects, obj) - fmt.Fprintf(out, "%#v", obj) - return t.Err -} - -// TODO: implement HandledResources() -func (t *testPrinter) HandledResources() []string { - return []string{} -} - -func (t *testPrinter) AfterPrint(output io.Writer, res string) error { - return nil -} - -func (t *testPrinter) IsGeneric() bool { - return t.GenericPrinter -} - -type testDescriber struct { - Name, Namespace string - Settings printers.DescriberSettings - Output string - Err error -} - -func (t *testDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (output string, err error) { - t.Namespace, t.Name = namespace, name - t.Settings = describerSettings - return t.Output, t.Err -} - func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser { return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj)))) } @@ -176,192 +131,6 @@ func stringBody(body string) io.ReadCloser { return ioutil.NopCloser(bytes.NewReader([]byte(body))) } -func Example_printMultiContainersReplicationControllerWithWide() { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: nil, - } - cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) - ctrl := &api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar"}, - CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"foo": "bar"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - }, - { - Name: "foo2", - Image: "someimage2", - }, - }, - }, - }, - }, - Status: api.ReplicationControllerStatus{ - Replicas: 1, - }, - } - cmd.Flags().Set("output", "wide") - err := cmdutil.PrintObject(cmd, ctrl, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR - // foo 1 1 0 10y foo,foo2 someimage,someimage2 foo=bar -} - -func Example_printReplicationController() { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: nil, - } - cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) - ctrl := &api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar"}, - CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"foo": "bar"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - }, - { - Name: "foo2", - Image: "someimage", - }, - }, - }, - }, - }, - Status: api.ReplicationControllerStatus{ - Replicas: 1, - }, - } - err := cmdutil.PrintObject(cmd, ctrl, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME DESIRED CURRENT READY AGE - // foo 1 1 0 10y -} - -func Example_printPodWithWideFormat() { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: nil, - } - nodeName := "kubernetes-node-abcd" - cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) - pod := &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test1", - CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.PodSpec{ - Containers: make([]api.Container, 2), - NodeName: nodeName, - }, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - PodIP: "10.1.1.3", - }, - } - cmd.Flags().Set("output", "wide") - err := cmdutil.PrintObject(cmd, pod, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME READY STATUS RESTARTS AGE IP NODE - // test1 1/2 podPhase 6 10y 10.1.1.3 kubernetes-node-abcd -} - -func Example_printPodWithShowLabels() { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: nil, - } - nodeName := "kubernetes-node-abcd" - cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) - pod := &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test1", - CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)}, - Labels: map[string]string{ - "l1": "key", - "l2": "value", - }, - }, - Spec: api.PodSpec{ - Containers: make([]api.Container, 2), - NodeName: nodeName, - }, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - } - cmd.Flags().Set("show-labels", "true") - err := cmdutil.PrintObject(cmd, pod, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME READY STATUS RESTARTS AGE LABELS - // test1 1/2 podPhase 6 10y l1=key,l2=value -} - func newAllPhasePodList() *api.PodList { nodeName := "kubernetes-node-abcd" return &api.PodList{ @@ -454,144 +223,9 @@ func newAllPhasePodList() *api.PodList { } } -func Example_printPodShowTerminated() { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: nil, - } - cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) - podList := newAllPhasePodList() - // filter pods - filterFuncs := tf.DefaultResourceFilterFunc() - filterOpts := cmdutil.ExtractCmdPrintOptions(cmd, false) - _, filteredPodList, errs := cmdutil.FilterResourceList(podList, filterFuncs, filterOpts) - if errs != nil { - fmt.Printf("Unexpected filter error: %v\n", errs) - } - printer, err := cmdutil.PrinterForOptions(cmdutil.ExtractCmdPrintOptions(cmd, false)) - if err != nil { - fmt.Printf("Unexpected printer get error: %v\n", errs) - } - for _, pod := range filteredPodList { - err := printer.PrintObj(pod, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - } - // Output: - // NAME READY STATUS RESTARTS AGE - // test1 1/2 Pending 6 10y - // test2 1/2 Running 6 10y - // test3 1/2 Succeeded 6 10y - // test4 1/2 Failed 6 10y - // test5 1/2 Unknown 6 10y -} - -func Example_printPodShowAll() { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: nil, - } - cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) - podList := newAllPhasePodList() - err := cmdutil.PrintObject(cmd, podList, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME READY STATUS RESTARTS AGE - // test1 1/2 Pending 6 10y - // test2 1/2 Running 6 10y - // test3 1/2 Succeeded 6 10y - // test4 1/2 Failed 6 10y - // test5 1/2 Unknown 6 10y -} - -func Example_printServiceWithLabels() { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: nil, - } - cmd := resource.NewCmdGet(tf, os.Stdout, os.Stderr) - svc := &api.ServiceList{ - Items: []api.Service{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "svc1", - Namespace: "ns1", - CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)}, - Labels: map[string]string{ - "l1": "value", - }, - }, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - {Protocol: "UDP", Port: 53}, - {Protocol: "TCP", Port: 53}, - }, - Selector: map[string]string{ - "s": "magic", - }, - ClusterIP: "10.1.1.1", - Type: api.ServiceTypeClusterIP, - }, - Status: api.ServiceStatus{}, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "svc2", - Namespace: "ns2", - CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)}, - Labels: map[string]string{ - "l1": "dolla-bill-yall", - }, - }, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - {Protocol: "TCP", Port: 80}, - {Protocol: "TCP", Port: 8080}, - }, - Selector: map[string]string{ - "s": "kazam", - }, - ClusterIP: "10.1.1.2", - Type: api.ServiceTypeClusterIP, - }, - Status: api.ServiceStatus{}, - }}, - } - ld := strings.NewLineDelimiter(os.Stdout, "|") - defer ld.Flush() - cmd.Flags().Set("label-columns", "l1") - err := cmdutil.PrintObject(cmd, svc, ld) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // |NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE L1| - // |svc1 ClusterIP 10.1.1.1 53/UDP,53/TCP 10y value| - // |svc2 ClusterIP 10.1.1.2 80/TCP,8080/TCP 10y dolla-bill-yall| - // || -} - func TestNormalizationFuncGlobalExistence(t *testing.T) { // This test can be safely deleted when we will not support multiple flag formats - root := NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr) + root := NewKubectlCommand(os.Stdin, os.Stdout, os.Stderr) if root.Parent() != nil { t.Fatal("We expect the root command to be returned") diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/BUILD index ba56eab4b..60238dc8a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/BUILD @@ -28,8 +28,10 @@ go_library( "//build/visible_to:pkg_kubectl_cmd_config_CONSUMERS", ], deps = [ + "//pkg/api/legacyscheme:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", "//pkg/printers:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", @@ -64,6 +66,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/config.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/config.go index 7984eb5e1..dbfa53efb 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/config.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/config.go @@ -18,7 +18,6 @@ package config import ( "fmt" - "io" "path" "strconv" @@ -27,11 +26,12 @@ import ( "k8s.io/client-go/tools/clientcmd" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) // NewCmdConfig creates a command object for the "config" action, and adds all child commands to it. -func NewCmdConfig(f cmdutil.Factory, pathOptions *clientcmd.PathOptions, out, errOut io.Writer) *cobra.Command { +func NewCmdConfig(f cmdutil.Factory, pathOptions *clientcmd.PathOptions, streams genericclioptions.IOStreams) *cobra.Command { if len(pathOptions.ExplicitFileFlag) == 0 { pathOptions.ExplicitFileFlag = clientcmd.RecommendedConfigPathFlag } @@ -48,25 +48,26 @@ func NewCmdConfig(f cmdutil.Factory, pathOptions *clientcmd.PathOptions, out, er 1. If the --` + pathOptions.ExplicitFileFlag + ` flag is set, then only that file is loaded. The flag may only be set once and no merging takes place. 2. If $` + pathOptions.EnvVar + ` environment variable is set, then it is used a list of paths (normal path delimitting rules for your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the last file in the list. 3. Otherwise, ` + path.Join("${HOME}", pathOptions.GlobalFileSubpath) + ` is used and no merging takes place.`), - Run: cmdutil.DefaultSubCommandRun(errOut), + Run: cmdutil.DefaultSubCommandRun(streams.ErrOut), } // file paths are common to all sub commands cmd.PersistentFlags().StringVar(&pathOptions.LoadingRules.ExplicitPath, pathOptions.ExplicitFileFlag, pathOptions.LoadingRules.ExplicitPath, "use a particular kubeconfig file") - cmd.AddCommand(NewCmdConfigView(f, out, errOut, pathOptions)) - cmd.AddCommand(NewCmdConfigSetCluster(out, pathOptions)) - cmd.AddCommand(NewCmdConfigSetAuthInfo(out, pathOptions)) - cmd.AddCommand(NewCmdConfigSetContext(out, pathOptions)) - cmd.AddCommand(NewCmdConfigSet(out, pathOptions)) - cmd.AddCommand(NewCmdConfigUnset(out, pathOptions)) - cmd.AddCommand(NewCmdConfigCurrentContext(out, pathOptions)) - cmd.AddCommand(NewCmdConfigUseContext(out, pathOptions)) - cmd.AddCommand(NewCmdConfigGetContexts(out, pathOptions)) - cmd.AddCommand(NewCmdConfigGetClusters(out, pathOptions)) - cmd.AddCommand(NewCmdConfigDeleteCluster(out, pathOptions)) - cmd.AddCommand(NewCmdConfigDeleteContext(out, errOut, pathOptions)) - cmd.AddCommand(NewCmdConfigRenameContext(out, pathOptions)) + // TODO(juanvallejo): update all subcommands to work with genericclioptions.IOStreams + cmd.AddCommand(NewCmdConfigView(f, streams, pathOptions)) + cmd.AddCommand(NewCmdConfigSetCluster(streams.Out, pathOptions)) + cmd.AddCommand(NewCmdConfigSetAuthInfo(streams.Out, pathOptions)) + cmd.AddCommand(NewCmdConfigSetContext(streams.Out, pathOptions)) + cmd.AddCommand(NewCmdConfigSet(streams.Out, pathOptions)) + cmd.AddCommand(NewCmdConfigUnset(streams.Out, pathOptions)) + cmd.AddCommand(NewCmdConfigCurrentContext(streams.Out, pathOptions)) + cmd.AddCommand(NewCmdConfigUseContext(streams.Out, pathOptions)) + cmd.AddCommand(NewCmdConfigGetContexts(streams, pathOptions)) + cmd.AddCommand(NewCmdConfigGetClusters(streams.Out, pathOptions)) + cmd.AddCommand(NewCmdConfigDeleteCluster(streams.Out, pathOptions)) + cmd.AddCommand(NewCmdConfigDeleteContext(streams.Out, streams.ErrOut, pathOptions)) + cmd.AddCommand(NewCmdConfigRenameContext(streams.Out, pathOptions)) return cmd } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/config_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/config_test.go index 2fc800027..fcf381f4e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/config_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/config_test.go @@ -17,7 +17,6 @@ limitations under the License. package config import ( - "bytes" "fmt" "io/ioutil" "os" @@ -31,6 +30,7 @@ import ( "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func newRedFederalCowHammerConfig() clientcmdapi.Config { @@ -863,15 +863,14 @@ func testConfigCommand(args []string, startingConfig clientcmdapi.Config, t *tes argsToUse = append(argsToUse, "--kubeconfig="+fakeKubeFile.Name()) argsToUse = append(argsToUse, args...) - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdConfig(cmdutil.NewFactory(nil), clientcmd.NewDefaultPathOptions(), buf, buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdConfig(cmdutil.NewFactory(genericclioptions.NewTestConfigFlags()), clientcmd.NewDefaultPathOptions(), streams) + // "context" is a global flag, inherited from base kubectl command in the real world + cmd.PersistentFlags().String("context", "", "The name of the kubeconfig context to use") cmd.SetArgs(argsToUse) cmd.Execute() - // outBytes, _ := ioutil.ReadFile(fakeKubeFile.Name()) config := clientcmd.GetConfigFromFileOrDie(fakeKubeFile.Name()) - return buf.String(), *config } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_authinfo_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_authinfo_test.go index 16cd95910..2b7fd1edd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_authinfo_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_authinfo_test.go @@ -142,7 +142,7 @@ func TestCreateAuthInfoOptions(t *testing.T) { }, { flags: []string{ - // No name for authinfo provided. + // No name for authinfo provided. }, wantCompleteErr: true, }, diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/get_contexts.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/get_contexts.go index b392bdb39..791db8030 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/get_contexts.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/get_contexts.go @@ -31,6 +31,7 @@ import ( clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/printers" ) @@ -41,7 +42,8 @@ type GetContextsOptions struct { nameOnly bool showHeaders bool contextNames []string - out io.Writer + + genericclioptions.IOStreams } var ( @@ -57,8 +59,12 @@ var ( // NewCmdConfigGetContexts creates a command object for the "get-contexts" action, which // retrieves one or more contexts from a kubeconfig. -func NewCmdConfigGetContexts(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { - options := &GetContextsOptions{configAccess: configAccess} +func NewCmdConfigGetContexts(streams genericclioptions.IOStreams, configAccess clientcmd.ConfigAccess) *cobra.Command { + options := &GetContextsOptions{ + configAccess: configAccess, + + IOStreams: streams, + } cmd := &cobra.Command{ Use: "get-contexts [(-o|--output=)name)]", @@ -74,22 +80,22 @@ func NewCmdConfigGetContexts(out io.Writer, configAccess clientcmd.ConfigAccess) cmdutil.CheckErr(fmt.Errorf("output must be one of '' or 'name': %v", outputFormat)) } if !supportedOutputTypes.Has(outputFormat) { - fmt.Fprintf(out, "--output %v is not available in kubectl config get-contexts; resetting to default output format\n", outputFormat) + fmt.Fprintf(options.Out, "--output %v is not available in kubectl config get-contexts; resetting to default output format\n", outputFormat) cmd.Flags().Set("output", "") } - cmdutil.CheckErr(options.Complete(cmd, args, out)) + cmdutil.CheckErr(options.Complete(cmd, args)) cmdutil.CheckErr(options.RunGetContexts()) }, } - cmdutil.AddOutputFlags(cmd) - cmdutil.AddNoHeadersFlags(cmd) + + cmd.Flags().Bool("no-headers", false, "When using the default or custom-column output format, don't print headers (default print headers).") + cmd.Flags().StringP("output", "o", "", "Output format. One of: name") return cmd } // Complete assigns GetContextsOptions from the args. -func (o *GetContextsOptions) Complete(cmd *cobra.Command, args []string, out io.Writer) error { +func (o *GetContextsOptions) Complete(cmd *cobra.Command, args []string) error { o.contextNames = args - o.out = out o.nameOnly = false if cmdutil.GetFlagString(cmd, "output") == "name" { o.nameOnly = true @@ -109,9 +115,9 @@ func (o GetContextsOptions) RunGetContexts() error { return err } - out, found := o.out.(*tabwriter.Writer) + out, found := o.Out.(*tabwriter.Writer) if !found { - out = printers.GetNewTabWriter(o.out) + out = printers.GetNewTabWriter(o.Out) defer out.Flush() } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/get_contexts_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/get_contexts_test.go index d21c4470a..fe16f0766 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/get_contexts_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/get_contexts_test.go @@ -17,13 +17,13 @@ limitations under the License. package config import ( - "bytes" "io/ioutil" "os" "testing" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) type getContextsTest struct { @@ -157,11 +157,11 @@ func (test getContextsTest) run(t *testing.T) { pathOptions := clientcmd.NewDefaultPathOptions() pathOptions.GlobalFile = fakeKubeFile.Name() pathOptions.EnvVar = "" - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() options := GetContextsOptions{ configAccess: pathOptions, } - cmd := NewCmdConfigGetContexts(buf, options.configAccess) + cmd := NewCmdConfigGetContexts(streams, options.configAccess) if test.nameOnly { cmd.Flags().Set("output", "name") } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/set.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/set.go index 4374b74b2..184a987fc 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/set.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/set.go @@ -33,11 +33,6 @@ import ( "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) -const ( - cannotHaveStepsAfterError = "Cannot have steps after %v. %v are remaining" - additionStepRequiredUnlessUnsettingError = "Must have additional steps after %v unless you are unsetting it" -) - type setOptions struct { configAccess clientcmd.ConfigAccess propertyName string diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/view.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/view.go index 703f4a033..476aab340 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/view.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/view.go @@ -18,8 +18,6 @@ package config import ( "errors" - "fmt" - "io" "github.com/spf13/cobra" @@ -27,18 +25,28 @@ import ( "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/tools/clientcmd/api/latest" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/printers" ) type ViewOptions struct { + PrintFlags *genericclioptions.PrintFlags + PrintObject printers.ResourcePrinterFunc + ConfigAccess clientcmd.ConfigAccess Merge flag.Tristate Flatten bool Minify bool RawByteData bool + + Context string + OutputFormat string + + genericclioptions.IOStreams } var ( @@ -48,17 +56,25 @@ var ( You can use --output jsonpath={...} to extract specific values using a jsonpath expression.`) view_example = templates.Examples(` - # Show Merged kubeconfig settings. + # Show merged kubeconfig settings. kubectl config view + # Show merged kubeconfig settings and raw certificate data. + kubectl config view --raw + # Get the password for the e2e user kubectl config view -o jsonpath='{.users[?(@.name == "e2e")].user.password}'`) + + defaultOutputFormat = "yaml" ) -func NewCmdConfigView(f cmdutil.Factory, out, errOut io.Writer, ConfigAccess clientcmd.ConfigAccess) *cobra.Command { - options := &ViewOptions{ConfigAccess: ConfigAccess} - // Default to yaml - defaultOutputFormat := "yaml" +func NewCmdConfigView(f cmdutil.Factory, streams genericclioptions.IOStreams, ConfigAccess clientcmd.ConfigAccess) *cobra.Command { + o := &ViewOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithTypeSetter(legacyscheme.Scheme).WithDefaultOutput("yaml"), + ConfigAccess: ConfigAccess, + + IOStreams: streams, + } cmd := &cobra.Command{ Use: "view", @@ -66,46 +82,58 @@ func NewCmdConfigView(f cmdutil.Factory, out, errOut io.Writer, ConfigAccess cli Long: view_long, Example: view_example, Run: func(cmd *cobra.Command, args []string) { - options.Complete() - outputFormat := cmdutil.GetFlagString(cmd, "output") - if outputFormat == "wide" { - fmt.Fprintf(errOut, "--output wide is not available in kubectl config view; reset to default output format (%s)\n\n", defaultOutputFormat) - // TODO: once printing is abstracted, this should be handled at flag declaration time - cmd.Flags().Set("output", defaultOutputFormat) - } - if outputFormat == "" { - fmt.Fprintf(errOut, "Reset to default output format (%s) as --output is empty\n", defaultOutputFormat) - // TODO: once printing is abstracted, this should be handled at flag declaration time - cmd.Flags().Set("output", defaultOutputFormat) - } - - printOpts := cmdutil.ExtractCmdPrintOptions(cmd, false) - printer, err := cmdutil.PrinterForOptions(printOpts) - cmdutil.CheckErr(err) - - cmdutil.CheckErr(options.Run(out, printer)) + cmdutil.CheckErr(o.Complete(cmd)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.Run()) }, } - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().Set("output", defaultOutputFormat) + o.PrintFlags.AddFlags(cmd) - options.Merge.Default(true) - mergeFlag := cmd.Flags().VarPF(&options.Merge, "merge", "", "Merge the full hierarchy of kubeconfig files") + o.Merge.Default(true) + mergeFlag := cmd.Flags().VarPF(&o.Merge, "merge", "", "Merge the full hierarchy of kubeconfig files") mergeFlag.NoOptDefVal = "true" - cmd.Flags().BoolVar(&options.RawByteData, "raw", false, "Display raw byte data") - cmd.Flags().BoolVar(&options.Flatten, "flatten", false, "Flatten the resulting kubeconfig file into self-contained output (useful for creating portable kubeconfig files)") - cmd.Flags().BoolVar(&options.Minify, "minify", false, "Remove all information not used by current-context from the output") + cmd.Flags().BoolVar(&o.RawByteData, "raw", o.RawByteData, "Display raw byte data") + cmd.Flags().BoolVar(&o.Flatten, "flatten", o.Flatten, "Flatten the resulting kubeconfig file into self-contained output (useful for creating portable kubeconfig files)") + cmd.Flags().BoolVar(&o.Minify, "minify", o.Minify, "Remove all information not used by current-context from the output") return cmd } -func (o ViewOptions) Run(out io.Writer, printer printers.ResourcePrinter) error { +func (o *ViewOptions) Complete(cmd *cobra.Command) error { + if o.ConfigAccess.IsExplicitFile() { + if !o.Merge.Provided() { + o.Merge.Set("false") + } + } + + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObject = printer.PrintObj + o.Context = cmdutil.GetFlagString(cmd, "context") + + return nil +} + +func (o ViewOptions) Validate() error { + if !o.Merge.Value() && !o.ConfigAccess.IsExplicitFile() { + return errors.New("if merge==false a precise file must to specified") + } + + return nil +} + +func (o ViewOptions) Run() error { config, err := o.loadConfig() if err != nil { return err } if o.Minify { + if len(o.Context) > 0 { + config.CurrentContext = o.Context + } if err := clientcmdapi.MinifyConfig(config); err != nil { return err } @@ -124,22 +152,7 @@ func (o ViewOptions) Run(out io.Writer, printer printers.ResourcePrinter) error return err } - err = printer.PrintObj(convertedObj, out) - if err != nil { - return err - } - - return nil -} - -func (o *ViewOptions) Complete() bool { - if o.ConfigAccess.IsExplicitFile() { - if !o.Merge.Provided() { - o.Merge.Set("false") - } - } - - return true + return o.PrintObject(convertedObj, o.Out) } func (o ViewOptions) loadConfig() (*clientcmdapi.Config, error) { @@ -152,14 +165,6 @@ func (o ViewOptions) loadConfig() (*clientcmdapi.Config, error) { return config, err } -func (o ViewOptions) Validate() error { - if !o.Merge.Value() && !o.ConfigAccess.IsExplicitFile() { - return errors.New("if merge==false a precise file must to specified") - } - - return nil -} - // getStartingConfig returns the Config object built from the sources specified by the options, the filename read (only if it was a single file), and an error if something goes wrong func (o *ViewOptions) getStartingConfig() (*clientcmdapi.Config, error) { switch { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/view_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/view_test.go index 873e5f079..936f1d9cd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/view_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/config/view_test.go @@ -17,7 +17,6 @@ limitations under the License. package config import ( - "bytes" "io/ioutil" "os" "testing" @@ -25,6 +24,7 @@ import ( "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) type viewClusterTest struct { @@ -43,19 +43,19 @@ func TestViewCluster(t *testing.T) { "my-cluster": {Server: "https://192.168.0.1:3434"}, }, Contexts: map[string]*clientcmdapi.Context{ - "minikube": {AuthInfo: "minikube", Cluster: "minikube"}, - "my-cluser": {AuthInfo: "mu-cluster", Cluster: "my-cluster"}, + "minikube": {AuthInfo: "minikube", Cluster: "minikube"}, + "my-cluster": {AuthInfo: "mu-cluster", Cluster: "my-cluster"}, }, CurrentContext: "minikube", AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "minikube": {Token: "minikube-token"}, - "my-cluser": {Token: "minikube-token"}, + "minikube": {Token: "minikube-token"}, + "mu-cluster": {Token: "minikube-token"}, }, } + test := viewClusterTest{ description: "Testing for kubectl config view", config: conf, - flags: []string{}, expected: `apiVersion: v1 clusters: - cluster: @@ -72,7 +72,7 @@ contexts: - context: cluster: my-cluster user: mu-cluster - name: my-cluser + name: my-cluster current-context: minikube kind: Config preferences: {} @@ -80,10 +80,13 @@ users: - name: minikube user: token: minikube-token -- name: my-cluser +- name: mu-cluster user: - token: minikube-token` + "\n"} + token: minikube-token` + "\n", + } + test.run(t) + } func TestViewClusterMinify(t *testing.T) { @@ -95,20 +98,27 @@ func TestViewClusterMinify(t *testing.T) { "my-cluster": {Server: "https://192.168.0.1:3434"}, }, Contexts: map[string]*clientcmdapi.Context{ - "minikube": {AuthInfo: "minikube", Cluster: "minikube"}, - "my-cluser": {AuthInfo: "mu-cluster", Cluster: "my-cluster"}, + "minikube": {AuthInfo: "minikube", Cluster: "minikube"}, + "my-cluster": {AuthInfo: "mu-cluster", Cluster: "my-cluster"}, }, CurrentContext: "minikube", AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "minikube": {Token: "minikube-token"}, - "my-cluser": {Token: "minikube-token"}, + "minikube": {Token: "minikube-token"}, + "mu-cluster": {Token: "minikube-token"}, }, } - test := viewClusterTest{ - description: "Testing for kubectl config view --minify=true", - config: conf, - flags: []string{"--minify=true"}, - expected: `apiVersion: v1 + + testCases := []struct { + description string + config clientcmdapi.Config + flags []string + expected string + }{ + { + description: "Testing for kubectl config view --minify=true", + config: conf, + flags: []string{"--minify=true"}, + expected: `apiVersion: v1 clusters: - cluster: server: https://192.168.99.100:8443 @@ -124,8 +134,41 @@ preferences: {} users: - name: minikube user: - token: minikube-token` + "\n"} - test.run(t) + token: minikube-token` + "\n", + }, + { + description: "Testing for kubectl config view --minify=true --context=my-cluster", + config: conf, + flags: []string{"--minify=true", "--context=my-cluster"}, + expected: `apiVersion: v1 +clusters: +- cluster: + server: https://192.168.0.1:3434 + name: my-cluster +contexts: +- context: + cluster: my-cluster + user: mu-cluster + name: my-cluster +current-context: my-cluster +kind: Config +preferences: {} +users: +- name: mu-cluster + user: + token: minikube-token` + "\n", + }, + } + + for _, test := range testCases { + cmdTest := viewClusterTest{ + description: test.description, + config: test.config, + flags: test.flags, + expected: test.expected, + } + cmdTest.run(t) + } } func (test viewClusterTest) run(t *testing.T) { @@ -141,10 +184,12 @@ func (test viewClusterTest) run(t *testing.T) { pathOptions := clientcmd.NewDefaultPathOptions() pathOptions.GlobalFile = fakeKubeFile.Name() pathOptions.EnvVar = "" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdConfigView(cmdutil.NewFactory(nil), buf, errBuf, pathOptions) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdConfigView(cmdutil.NewFactory(genericclioptions.NewTestConfigFlags()), streams, pathOptions) + // "context" is a global flag, inherited from base kubectl command in the real world + cmd.Flags().String("context", "", "The name of the kubeconfig context to use") cmd.Flags().Parse(test.flags) + if err := cmd.Execute(); err != nil { t.Fatalf("unexpected error executing command: %v,kubectl config view flags: %v", err, test.flags) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/convert.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/convert.go index 3a094b917..c22c2990d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/convert.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/convert.go @@ -18,7 +18,6 @@ package cmd import ( "fmt" - "io" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" @@ -27,9 +26,10 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" - "k8s.io/kubernetes/pkg/printers" "github.com/golang/glog" "github.com/spf13/cobra" @@ -61,8 +61,8 @@ var ( // NewCmdConvert creates a command object for the generic "convert" action, which // translates the config file into a given version. -func NewCmdConvert(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ConvertOptions{} +func NewCmdConvert(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := NewConvertOptions(ioStreams) cmd := &cobra.Command{ Use: "convert -f FILENAME", @@ -71,37 +71,44 @@ func NewCmdConvert(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: convert_long, Example: convert_example, Run: func(cmd *cobra.Command, args []string) { - err := options.Complete(f, out, cmd) - cmdutil.CheckErr(err) - err = options.RunConvert() - cmdutil.CheckErr(err) + cmdutil.CheckErr(options.Complete(f, cmd)) + cmdutil.CheckErr(options.RunConvert()) }, } + options.PrintFlags.AddFlags(cmd) + usage := "to need to get converted." cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmd.MarkFlagRequired("filename") cmdutil.AddValidateFlags(cmd) - cmdutil.AddNonDeprecatedPrinterFlags(cmd) - cmd.Flags().BoolVar(&options.local, "local", true, "If true, convert will NOT try to contact api-server but run locally.") + cmd.Flags().BoolVar(&options.local, "local", options.local, "If true, convert will NOT try to contact api-server but run locally.") cmd.Flags().String("output-version", "", i18n.T("Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)")) - cmdutil.AddInclude3rdPartyFlags(cmd) return cmd } // ConvertOptions have the data required to perform the convert operation type ConvertOptions struct { + PrintFlags *genericclioptions.PrintFlags + PrintObj printers.ResourcePrinterFunc + resource.FilenameOptions builder *resource.Builder local bool - out io.Writer - printer printers.ResourcePrinter - + genericclioptions.IOStreams specifiedOutputVersion schema.GroupVersion } +func NewConvertOptions(ioStreams genericclioptions.IOStreams) *ConvertOptions { + return &ConvertOptions{ + PrintFlags: genericclioptions.NewPrintFlags("converted").WithTypeSetter(scheme.Scheme).WithDefaultOutput("yaml"), + local: true, + IOStreams: ioStreams, + } +} + // outputVersion returns the preferred output version for generic content (JSON, YAML, or templates) // defaultVersion is never mutated. Nil simply allows clean passing in common usage from client.Config func outputVersion(cmd *cobra.Command) (schema.GroupVersion, error) { @@ -114,7 +121,7 @@ func outputVersion(cmd *cobra.Command) (schema.GroupVersion, error) { } // Complete collects information required to run Convert command from command line. -func (o *ConvertOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) (err error) { +func (o *ConvertOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) (err error) { o.specifiedOutputVersion, err = outputVersion(cmd) if err != nil { return err @@ -122,7 +129,7 @@ func (o *ConvertOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.C // build the builder o.builder = f.NewBuilder(). - Internal(). + WithScheme(scheme.Scheme). LocalParam(o.local) if !o.local { schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) @@ -132,7 +139,7 @@ func (o *ConvertOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.C o.builder.Schema(schema) } - cmdNamespace, _, err := f.DefaultNamespace() + cmdNamespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -142,20 +149,12 @@ func (o *ConvertOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.C Flatten() // build the printer - o.out = out - outputFormat := cmdutil.GetFlagString(cmd, "output") - templateFile := cmdutil.GetFlagString(cmd, "template") - if len(outputFormat) == 0 { - if len(templateFile) == 0 { - outputFormat = "yaml" - } else { - outputFormat = "template" - } - // TODO: once printing is abstracted, this should be handled at flag declaration time - cmd.Flags().Set("output", outputFormat) + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err } - o.printer, err = cmdutil.PrinterForOptions(cmdutil.ExtractCmdPrintOptions(cmd, false)) - return err + o.PrintObj = printer.PrintObj + return nil } // RunConvert implements the generic Convert command @@ -182,18 +181,14 @@ func (o *ConvertOptions) RunConvert() error { } if meta.IsListType(objects) { - _, items, err := cmdutil.FilterResourceList(objects, nil, nil) - if err != nil { - return err - } - filteredObj, err := objectListToVersionedObject(items, o.specifiedOutputVersion) + obj, err := objectListToVersionedObject([]runtime.Object{objects}, o.specifiedOutputVersion) if err != nil { return err } - return o.printer.PrintObj(filteredObj, o.out) + return o.PrintObj(obj, o.Out) } - return o.printer.PrintObj(objects, o.out) + return o.PrintObj(objects, o.Out) } // objectListToVersionedObject receives a list of api objects and a group version @@ -204,7 +199,7 @@ func objectListToVersionedObject(objects []runtime.Object, specifiedOutputVersio if !specifiedOutputVersion.Empty() { targetVersions = append(targetVersions, specifiedOutputVersion) } - targetVersions = append(targetVersions, scheme.Registry.GroupOrDie(api.GroupName).GroupVersion) + targetVersions = append(targetVersions, schema.GroupVersion{Group: "", Version: "v1"}) converted, err := tryConvert(scheme.Scheme, objectList, targetVersions...) if err != nil { return nil, err @@ -231,7 +226,7 @@ func asVersionedObject(infos []*resource.Info, forceList bool, specifiedOutputVe if !specifiedOutputVersion.Empty() { targetVersions = append(targetVersions, specifiedOutputVersion) } - targetVersions = append(targetVersions, scheme.Registry.GroupOrDie(api.GroupName).GroupVersion) + targetVersions = append(targetVersions, schema.GroupVersion{Group: "", Version: "v1"}) converted, err := tryConvert(scheme.Scheme, object, targetVersions...) if err != nil { @@ -280,14 +275,14 @@ func asVersionedObjects(infos []*resource.Info, specifiedOutputVersion schema.Gr gvks, _, err := scheme.Scheme.ObjectKinds(info.Object) if err == nil { for _, gvk := range gvks { - for _, version := range scheme.Registry.EnabledVersionsForGroup(gvk.Group) { + for _, version := range scheme.Scheme.PrioritizedVersionsForGroup(gvk.Group) { targetVersions = append(targetVersions, version) } } } } - converted, err := tryConvert(info.Mapping.ObjectConvertor, info.Object, targetVersions...) + converted, err := tryConvert(scheme.Scheme, info.Object, targetVersions...) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/convert_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/convert_test.go index 5b7474ef6..8f3e8cf85 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/convert_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/convert_test.go @@ -20,10 +20,12 @@ import ( "bytes" "fmt" "net/http" + "strings" "testing" "k8s.io/client-go/rest/fake" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) type testcase struct { @@ -34,7 +36,6 @@ type testcase struct { } type checkField struct { - template string expected string } @@ -46,8 +47,7 @@ func TestConvertObject(t *testing.T) { outputVersion: "extensions/v1beta1", fields: []checkField{ { - template: "{{.apiVersion}}", - expected: "extensions/v1beta1", + expected: "apiVersion: extensions/v1beta1", }, }, }, @@ -57,8 +57,7 @@ func TestConvertObject(t *testing.T) { outputVersion: "apps/v1beta2", fields: []checkField{ { - template: "{{.apiVersion}}", - expected: "apps/v1beta2", + expected: "apiVersion: apps/v1beta2", }, }, }, @@ -68,16 +67,13 @@ func TestConvertObject(t *testing.T) { outputVersion: "autoscaling/v2beta1", fields: []checkField{ { - template: "{{.apiVersion}}", - expected: "autoscaling/v2beta1", + expected: "apiVersion: autoscaling/v2beta1", }, { - template: "{{(index .spec.metrics 0).resource.name}}", - expected: "cpu", + expected: "name: cpu", }, { - template: "{{(index .spec.metrics 0).resource.targetAverageUtilization}}", - expected: "50", + expected: "targetAverageUtilization: 50", }, }, }, @@ -87,12 +83,10 @@ func TestConvertObject(t *testing.T) { outputVersion: "autoscaling/v1", fields: []checkField{ { - template: "{{.apiVersion}}", - expected: "autoscaling/v1", + expected: "apiVersion: autoscaling/v1", }, { - template: "{{.spec.targetCPUUtilizationPercentage}}", - expected: "50", + expected: "targetCPUUtilizationPercentage: 50", }, }, }, @@ -101,7 +95,7 @@ func TestConvertObject(t *testing.T) { for _, tc := range testcases { for _, field := range tc.fields { t.Run(fmt.Sprintf("%s %s", tc.name, field), func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -110,16 +104,15 @@ func TestConvertObject(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdConvert(tf, buf) + cmd := NewCmdConvert(tf, genericclioptions.IOStreams{Out: buf, ErrOut: buf}) cmd.Flags().Set("filename", tc.file) cmd.Flags().Set("output-version", tc.outputVersion) cmd.Flags().Set("local", "true") - cmd.Flags().Set("output", "go-template="+field.template) + cmd.Flags().Set("output", "yaml") cmd.Run(cmd, []string{}) - if buf.String() != field.expected { + if !strings.Contains(buf.String(), field.expected) { t.Errorf("unexpected output when converting %s to %q, expected: %q, but got %q", tc.file, tc.outputVersion, field.expected, buf.String()) } }) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cp.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cp.go index 602be6d0a..2c67fee7c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cp.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cp.go @@ -18,7 +18,6 @@ package cmd import ( "archive/tar" - "bytes" "errors" "fmt" "io" @@ -28,10 +27,15 @@ import ( "path/filepath" "strings" + restclient "k8s.io/client-go/rest" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "bytes" + "github.com/renstrom/dedent" "github.com/spf13/cobra" ) @@ -61,8 +65,26 @@ var ( /file/path for a local file`) ) +type CopyOptions struct { + Container string + Namespace string + + ClientConfig *restclient.Config + Clientset internalclientset.Interface + + genericclioptions.IOStreams +} + +func NewCopyOptions(ioStreams genericclioptions.IOStreams) *CopyOptions { + return &CopyOptions{ + IOStreams: ioStreams, + } +} + // NewCmdCp creates a new Copy command. -func NewCmdCp(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command { +func NewCmdCp(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewCopyOptions(ioStreams) + cmd := &cobra.Command{ Use: "cp ", DisableFlagsInUseLine: true, @@ -70,10 +92,11 @@ func NewCmdCp(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command { Long: "Copy files and directories to and from containers.", Example: cpExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(runCopy(f, cmd, cmdOut, cmdErr, args)) + cmdutil.CheckErr(o.Complete(f, cmd)) + cmdutil.CheckErr(o.Run(args)) }, } - cmd.Flags().StringP("container", "c", "", "Container name. If omitted, the first container in the pod will be chosen") + cmd.Flags().StringVarP(&o.Container, "container", "c", o.Container, "Container name. If omitted, the first container in the pod will be chosen") return cmd } @@ -90,39 +113,60 @@ var ( ) func extractFileSpec(arg string) (fileSpec, error) { - pieces := strings.Split(arg, ":") - if len(pieces) == 1 { + if i := strings.Index(arg, ":"); i == -1 { return fileSpec{File: arg}, nil + } else if i > 0 { + file := arg[i+1:] + pod := arg[:i] + pieces := strings.Split(pod, "/") + if len(pieces) == 1 { + return fileSpec{ + PodName: pieces[0], + File: file, + }, nil + } + if len(pieces) == 2 { + return fileSpec{ + PodNamespace: pieces[0], + PodName: pieces[1], + File: file, + }, nil + } } - if len(pieces) != 2 { - // FIXME Kubernetes can't copy files that contain a ':' - // character. - return fileSpec{}, errFileSpecDoesntMatchFormat - } - file := pieces[1] - pieces = strings.Split(pieces[0], "/") - if len(pieces) == 1 { - return fileSpec{ - PodName: pieces[0], - File: file, - }, nil + return fileSpec{}, errFileSpecDoesntMatchFormat +} + +func (o *CopyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { + var err error + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err } - if len(pieces) == 2 { - return fileSpec{ - PodNamespace: pieces[0], - PodName: pieces[1], - File: file, - }, nil + + o.Clientset, err = f.ClientSet() + if err != nil { + return err } - return fileSpec{}, errFileSpecDoesntMatchFormat + o.ClientConfig, err = f.ToRESTConfig() + if err != nil { + return err + } + return nil } -func runCopy(f cmdutil.Factory, cmd *cobra.Command, out, cmderr io.Writer, args []string) error { +func (o *CopyOptions) Validate(cmd *cobra.Command, args []string) error { if len(args) != 2 { return cmdutil.UsageErrorf(cmd, cpUsageStr) } + return nil +} + +func (o *CopyOptions) Run(args []string) error { + if len(args) < 2 { + return fmt.Errorf("source and destination are required") + } srcSpec, err := extractFileSpec(args[0]) if err != nil { return err @@ -131,24 +175,34 @@ func runCopy(f cmdutil.Factory, cmd *cobra.Command, out, cmderr io.Writer, args if err != nil { return err } + + if len(srcSpec.PodName) != 0 && len(destSpec.PodName) != 0 { + if _, err := os.Stat(args[0]); err == nil { + return o.copyToPod(fileSpec{File: args[0]}, destSpec) + } + return fmt.Errorf("src doesn't exist in local filesystem") + } + if len(srcSpec.PodName) != 0 { - return copyFromPod(f, cmd, cmderr, srcSpec, destSpec) + return o.copyFromPod(srcSpec, destSpec) } if len(destSpec.PodName) != 0 { - return copyToPod(f, cmd, out, cmderr, srcSpec, destSpec) + return o.copyToPod(srcSpec, destSpec) } - return cmdutil.UsageErrorf(cmd, "One of src or dest must be a remote file specification") + return fmt.Errorf("one of src or dest must be a remote file specification") } // checkDestinationIsDir receives a destination fileSpec and // determines if the provided destination path exists on the // pod. If the destination path does not exist or is _not_ a // directory, an error is returned with the exit code received. -func checkDestinationIsDir(dest fileSpec, f cmdutil.Factory, cmd *cobra.Command) error { +func (o *CopyOptions) checkDestinationIsDir(dest fileSpec) error { options := &ExecOptions{ StreamOptions: StreamOptions{ - Out: bytes.NewBuffer([]byte{}), - Err: bytes.NewBuffer([]byte{}), + IOStreams: genericclioptions.IOStreams{ + Out: bytes.NewBuffer([]byte{}), + ErrOut: bytes.NewBuffer([]byte{}), + }, Namespace: dest.PodNamespace, PodName: dest.PodName, @@ -158,21 +212,21 @@ func checkDestinationIsDir(dest fileSpec, f cmdutil.Factory, cmd *cobra.Command) Executor: &DefaultRemoteExecutor{}, } - return execute(f, cmd, options) + return o.execute(options) } -func copyToPod(f cmdutil.Factory, cmd *cobra.Command, stdout, stderr io.Writer, src, dest fileSpec) error { - if len(src.File) == 0 { +func (o *CopyOptions) copyToPod(src, dest fileSpec) error { + if len(src.File) == 0 || len(dest.File) == 0 { return errFileCannotBeEmpty } reader, writer := io.Pipe() // strip trailing slash (if any) - if strings.HasSuffix(string(dest.File[len(dest.File)-1]), "/") { + if dest.File != "/" && strings.HasSuffix(string(dest.File[len(dest.File)-1]), "/") { dest.File = dest.File[:len(dest.File)-1] } - if err := checkDestinationIsDir(dest, f, cmd); err == nil { + if err := o.checkDestinationIsDir(dest); err == nil { // If no error, dest.File was found to be a directory. // Copy specified src into it dest.File = dest.File + "/" + path.Base(src.File) @@ -193,9 +247,11 @@ func copyToPod(f cmdutil.Factory, cmd *cobra.Command, stdout, stderr io.Writer, options := &ExecOptions{ StreamOptions: StreamOptions{ - In: reader, - Out: stdout, - Err: stderr, + IOStreams: genericclioptions.IOStreams{ + In: reader, + Out: o.Out, + ErrOut: o.ErrOut, + }, Stdin: true, Namespace: dest.PodNamespace, @@ -205,20 +261,22 @@ func copyToPod(f cmdutil.Factory, cmd *cobra.Command, stdout, stderr io.Writer, Command: cmdArr, Executor: &DefaultRemoteExecutor{}, } - return execute(f, cmd, options) + return o.execute(options) } -func copyFromPod(f cmdutil.Factory, cmd *cobra.Command, cmderr io.Writer, src, dest fileSpec) error { - if len(src.File) == 0 { +func (o *CopyOptions) copyFromPod(src, dest fileSpec) error { + if len(src.File) == 0 || len(dest.File) == 0 { return errFileCannotBeEmpty } reader, outStream := io.Pipe() options := &ExecOptions{ StreamOptions: StreamOptions{ - In: nil, - Out: outStream, - Err: cmderr, + IOStreams: genericclioptions.IOStreams{ + In: nil, + Out: outStream, + ErrOut: o.Out, + }, Namespace: src.PodNamespace, PodName: src.PodName, @@ -231,13 +289,26 @@ func copyFromPod(f cmdutil.Factory, cmd *cobra.Command, cmderr io.Writer, src, d go func() { defer outStream.Close() - execute(f, cmd, options) + o.execute(options) }() prefix := getPrefix(src.File) prefix = path.Clean(prefix) + // remove extraneous path shortcuts - these could occur if a path contained extra "../" + // and attempted to navigate beyond "/" in a remote filesystem + prefix = stripPathShortcuts(prefix) return untarAll(reader, dest.File, prefix) } +// stripPathShortcuts removes any leading or trailing "../" from a given path +func stripPathShortcuts(p string) string { + newPath := path.Clean(p) + if len(newPath) > 0 && string(newPath[0]) == "/" { + return newPath[1:] + } + + return newPath +} + func makeTar(srcPath, destPath string, writer io.Writer) error { // TODO: use compression here? tarWriter := tar.NewWriter(writer) @@ -389,31 +460,17 @@ func getPrefix(file string) string { return strings.TrimLeft(file, "/") } -func execute(f cmdutil.Factory, cmd *cobra.Command, options *ExecOptions) error { +func (o *CopyOptions) execute(options *ExecOptions) error { if len(options.Namespace) == 0 { - namespace, _, err := f.DefaultNamespace() - if err != nil { - return err - } - options.Namespace = namespace - } - - container := cmdutil.GetFlagString(cmd, "container") - if len(container) > 0 { - options.ContainerName = container + options.Namespace = o.Namespace } - config, err := f.ClientConfig() - if err != nil { - return err + if len(o.Container) > 0 { + options.ContainerName = o.Container } - options.Config = config - clientset, err := f.ClientSet() - if err != nil { - return err - } - options.PodClient = clientset.Core() + options.Config = o.ClientConfig + options.PodClient = o.Clientset.Core() if err := options.Validate(); err != nil { return err diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cp_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cp_test.go index 1c0481295..a01747e80 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cp_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cp_test.go @@ -21,12 +21,23 @@ import ( "bytes" "io" "io/ioutil" + "net/http" "os" "os/exec" "path" "path/filepath" "strings" "testing" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" + cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/scheme" ) type FileType int @@ -60,9 +71,18 @@ func TestExtractFileSpec(t *testing.T) { expectedFile: "/some/file", }, { - spec: "some:bad:spec", + spec: ":file:not:exist:in:local:filesystem", + expectErr: true, + }, + { + spec: "namespace/pod/invalid:/some/file", expectErr: true, }, + { + spec: "pod:/some/filenamewith:in", + expectedPod: "pod", + expectedFile: "/some/filenamewith:in", + }, } for _, test := range tests { spec, err := extractFileSpec(test.spec) @@ -497,3 +517,105 @@ func TestClean(t *testing.T) { } } } + +func TestCopyToPod(t *testing.T) { + tf := cmdtesting.NewTestFactory().WithNamespace("test") + ns := legacyscheme.Codecs + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.Client = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + responsePod := &v1.Pod{} + return &http.Response{StatusCode: http.StatusNotFound, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, responsePod))))}, nil + }), + } + + tf.ClientConfigVal = defaultClientConfig() + ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() + + cmd := NewCmdCp(tf, ioStreams) + + srcFile, err := ioutil.TempDir("", "test") + if err != nil { + t.Errorf("unexpected error: %v", err) + t.FailNow() + } + defer os.RemoveAll(srcFile) + + tests := map[string]struct { + dest string + expectedErr bool + }{ + "copy to directory": { + dest: "/tmp/", + expectedErr: false, + }, + "copy to root": { + dest: "/", + expectedErr: false, + }, + "copy to empty file name": { + dest: "", + expectedErr: true, + }, + } + + for name, test := range tests { + opts := NewCopyOptions(ioStreams) + src := fileSpec{ + File: srcFile, + } + dest := fileSpec{ + PodNamespace: "pod-ns", + PodName: "pod-name", + File: test.dest, + } + opts.Complete(tf, cmd) + t.Run(name, func(t *testing.T) { + err = opts.copyToPod(src, dest) + //If error is NotFound error , it indicates that the + //request has been sent correctly. + //Treat this as no error. + if test.expectedErr && errors.IsNotFound(err) { + t.Errorf("expected error but didn't get one") + } + if !test.expectedErr && !errors.IsNotFound(err) { + t.Errorf("unexpected error: %v", err) + } + }) + } +} + +func TestValidate(t *testing.T) { + tests := []struct { + name string + args []string + expectedErr bool + }{ + { + name: "Validate Succeed", + args: []string{"1", "2"}, + expectedErr: false, + }, + { + name: "Validate Fail", + args: []string{"1", "2", "3"}, + expectedErr: true, + }, + } + tf := cmdtesting.NewTestFactory() + ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() + opts := NewCopyOptions(ioStreams) + cmd := NewCmdCp(tf, ioStreams) + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := opts.Validate(cmd, test.args) + if (err != nil) != test.expectedErr { + t.Errorf("expected error: %v, saw: %v, error: %v", test.expectedErr, err != nil, err) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create.go deleted file mode 100644 index 6784fef85..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create.go +++ /dev/null @@ -1,362 +0,0 @@ -/* -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 cmd - -import ( - "fmt" - "io" - "os" - "runtime" - "strings" - - "github.com/spf13/cobra" - - "net/url" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" -) - -type CreateOptions struct { - FilenameOptions resource.FilenameOptions - Selector string - EditBeforeCreate bool - Raw string - Out io.Writer - ErrOut io.Writer -} - -var ( - createLong = templates.LongDesc(i18n.T(` - Create a resource from a file or from stdin. - - JSON and YAML formats are accepted.`)) - - createExample = templates.Examples(i18n.T(` - # Create a pod using the data in pod.json. - kubectl create -f ./pod.json - - # Create a pod based on the JSON passed into stdin. - cat pod.json | kubectl create -f - - - # Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data. - kubectl create -f docker-registry.yaml --edit --output-version=v1 -o json`)) -) - -func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - options := &CreateOptions{ - Out: out, - ErrOut: errOut, - } - - cmd := &cobra.Command{ - Use: "create -f FILENAME", - DisableFlagsInUseLine: true, - Short: i18n.T("Create a resource from a file or from stdin."), - Long: createLong, - Example: createExample, - Run: func(cmd *cobra.Command, args []string) { - if cmdutil.IsFilenameSliceEmpty(options.FilenameOptions.Filenames) { - defaultRunFunc := cmdutil.DefaultSubCommandRun(errOut) - defaultRunFunc(cmd, args) - return - } - cmdutil.CheckErr(options.ValidateArgs(cmd, args)) - cmdutil.CheckErr(options.RunCreate(f, cmd)) - }, - } - - usage := "to use to create the resource" - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) - cmd.MarkFlagRequired("filename") - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().BoolVar(&options.EditBeforeCreate, "edit", false, "Edit the API resource before creating") - cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows", - "Only relevant if --edit=true. Defaults to the line ending native to your platform.") - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddDryRunFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().StringVar(&options.Raw, "raw", options.Raw, "Raw URI to POST to the server. Uses the transport specified by the kubeconfig file.") - - // create subcommands - cmd.AddCommand(NewCmdCreateNamespace(f, out)) - cmd.AddCommand(NewCmdCreateQuota(f, out)) - cmd.AddCommand(NewCmdCreateSecret(f, out, errOut)) - cmd.AddCommand(NewCmdCreateConfigMap(f, out)) - cmd.AddCommand(NewCmdCreateServiceAccount(f, out)) - cmd.AddCommand(NewCmdCreateService(f, out, errOut)) - cmd.AddCommand(NewCmdCreateDeployment(f, out, errOut)) - cmd.AddCommand(NewCmdCreateClusterRole(f, out)) - cmd.AddCommand(NewCmdCreateClusterRoleBinding(f, out)) - cmd.AddCommand(NewCmdCreateRole(f, out)) - cmd.AddCommand(NewCmdCreateRoleBinding(f, out)) - cmd.AddCommand(NewCmdCreatePodDisruptionBudget(f, out)) - cmd.AddCommand(NewCmdCreatePriorityClass(f, out)) - cmd.AddCommand(NewCmdCreateJob(f, out)) - return cmd -} - -func (o *CreateOptions) ValidateArgs(cmd *cobra.Command, args []string) error { - if len(args) != 0 { - return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args) - } - if len(o.Raw) > 0 { - if o.EditBeforeCreate { - return cmdutil.UsageErrorf(cmd, "--raw and --edit are mutually exclusive") - } - if len(o.FilenameOptions.Filenames) != 1 { - return cmdutil.UsageErrorf(cmd, "--raw can only use a single local file or stdin") - } - if strings.Index(o.FilenameOptions.Filenames[0], "http://") == 0 || strings.Index(o.FilenameOptions.Filenames[0], "https://") == 0 { - return cmdutil.UsageErrorf(cmd, "--raw cannot read from a url") - } - if o.FilenameOptions.Recursive { - return cmdutil.UsageErrorf(cmd, "--raw and --recursive are mutually exclusive") - } - if len(o.Selector) > 0 { - return cmdutil.UsageErrorf(cmd, "--raw and --selector (-l) are mutually exclusive") - } - if len(cmdutil.GetFlagString(cmd, "output")) > 0 { - return cmdutil.UsageErrorf(cmd, "--raw and --output are mutually exclusive") - } - if _, err := url.ParseRequestURI(o.Raw); err != nil { - return cmdutil.UsageErrorf(cmd, "--raw must be a valid URL path: %v", err) - } - } - - return nil -} - -func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error { - // raw only makes sense for a single file resource multiple objects aren't likely to do what you want. - // the validator enforces this, so - if len(o.Raw) > 0 { - return o.raw(f) - } - - if o.EditBeforeCreate { - return RunEditOnCreate(f, o.Out, o.ErrOut, cmd, &o.FilenameOptions) - } - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) - if err != nil { - return err - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - r := f.NewBuilder(). - Unstructured(). - Schema(schema). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &o.FilenameOptions). - LabelSelectorParam(o.Selector). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - dryRun := cmdutil.GetDryRunFlag(cmd) - output := cmdutil.GetFlagString(cmd, "output") - - count := 0 - err = r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, cmdutil.InternalVersionJSONEncoder()); err != nil { - return cmdutil.AddSourceToErr("creating", info.Source, err) - } - - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command(cmd, false)); err != nil { - return cmdutil.AddSourceToErr("creating", info.Source, err) - } - } - - if !dryRun { - if err := createAndRefresh(info); err != nil { - return cmdutil.AddSourceToErr("creating", info.Source, err) - } - } - - count++ - - shortOutput := output == "name" - if len(output) > 0 && !shortOutput { - return cmdutil.PrintObject(cmd, info.Object, o.Out) - } - - cmdutil.PrintSuccess(shortOutput, o.Out, info.Object, dryRun, "created") - return nil - }) - if err != nil { - return err - } - if count == 0 { - return fmt.Errorf("no objects passed to create") - } - return nil -} - -// raw makes a simple HTTP request to the provided path on the server using the default -// credentials. -func (o *CreateOptions) raw(f cmdutil.Factory) error { - restClient, err := f.RESTClient() - if err != nil { - return err - } - - var data io.ReadCloser - if o.FilenameOptions.Filenames[0] == "-" { - data = os.Stdin - } else { - data, err = os.Open(o.FilenameOptions.Filenames[0]) - if err != nil { - return err - } - } - // TODO post content with stream. Right now it ignores body content - bytes, err := restClient.Post().RequestURI(o.Raw).Body(data).DoRaw() - if err != nil { - return err - } - - fmt.Fprintf(o.Out, "%v", string(bytes)) - return nil -} - -func RunEditOnCreate(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, options *resource.FilenameOptions) error { - editOptions := &editor.EditOptions{ - EditMode: editor.EditBeforeCreateMode, - FilenameOptions: *options, - ValidateOptions: cmdutil.ValidateOptions{ - EnableValidation: cmdutil.GetFlagBool(cmd, "validate"), - }, - Output: cmdutil.GetFlagString(cmd, "output"), - WindowsLineEndings: cmdutil.GetFlagBool(cmd, "windows-line-endings"), - ApplyAnnotation: cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), - Record: cmdutil.GetFlagBool(cmd, "record"), - ChangeCause: f.Command(cmd, false), - Include3rdParty: cmdutil.GetFlagBool(cmd, "include-extended-apis"), - } - err := editOptions.Complete(f, out, errOut, []string{}, cmd) - if err != nil { - return err - } - return editOptions.Run() -} - -// createAndRefresh creates an object from input info and refreshes info with that object -func createAndRefresh(info *resource.Info) error { - obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object) - if err != nil { - return err - } - info.Refresh(obj, true) - return nil -} - -// NameFromCommandArgs is a utility function for commands that assume the first argument is a resource name -func NameFromCommandArgs(cmd *cobra.Command, args []string) (string, error) { - if len(args) != 1 { - return "", cmdutil.UsageErrorf(cmd, "exactly one NAME is required, got %d", len(args)) - } - return args[0], nil -} - -// CreateSubcommandOptions is an options struct to support create subcommands -type CreateSubcommandOptions struct { - // Name of resource being created - Name string - // StructuredGenerator is the resource generator for the object being created - StructuredGenerator kubectl.StructuredGenerator - // DryRun is true if the command should be simulated but not run against the server - DryRun bool - OutputFormat string -} - -// RunCreateSubcommand executes a create subcommand using the specified options -func RunCreateSubcommand(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *CreateSubcommandOptions) error { - namespace, nsOverriden, err := f.DefaultNamespace() - if err != nil { - return err - } - obj, err := options.StructuredGenerator.StructuredGenerate() - if err != nil { - return err - } - mapper, typer := f.Object() - gvks, _, err := typer.ObjectKinds(obj) - if err != nil { - return err - } - gvk := gvks[0] - mapping, err := mapper.RESTMapping(schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version) - if err != nil { - return err - } - client, err := f.ClientForMapping(mapping) - if err != nil { - return err - } - resourceMapper := &resource.Mapper{ - ObjectTyper: typer, - RESTMapper: mapper, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - } - info, err := resourceMapper.InfoForObject(obj, nil) - if err != nil { - return err - } - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, cmdutil.InternalVersionJSONEncoder()); err != nil { - return err - } - obj = info.Object - - if !options.DryRun { - obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) - if err != nil { - return err - } - } else { - if meta, err := meta.Accessor(obj); err == nil && nsOverriden { - meta.SetNamespace(namespace) - } - } - - if useShortOutput := options.OutputFormat == "name"; useShortOutput || len(options.OutputFormat) == 0 { - cmdutil.PrintSuccess(useShortOutput, out, info.Object, options.DryRun, "created") - return nil - } - - return cmdutil.PrintObject(cmd, obj, out) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/BUILD new file mode 100644 index 000000000..7f67fa4cc --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/BUILD @@ -0,0 +1,117 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "create.go", + "create_clusterrole.go", + "create_clusterrolebinding.go", + "create_configmap.go", + "create_deployment.go", + "create_job.go", + "create_namespace.go", + "create_pdb.go", + "create_priorityclass.go", + "create_quota.go", + "create_role.go", + "create_rolebinding.go", + "create_secret.go", + "create_service.go", + "create_serviceaccount.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/create", + visibility = ["//build/visible_to:pkg_kubectl_cmd_create_CONSUMERS"], + deps = [ + "//pkg/api/legacyscheme:go_default_library", + "//pkg/kubectl:go_default_library", + "//pkg/kubectl/cmd/templates:go_default_library", + "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/cmd/util/editor:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//pkg/kubectl/scheme:go_default_library", + "//pkg/kubectl/util/i18n:go_default_library", + "//pkg/printers:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/k8s.io/api/batch/v1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/util/sets:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", + "//vendor/k8s.io/client-go/dynamic:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/batch/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "create_clusterrole_test.go", + "create_clusterrolebinding_test.go", + "create_configmap_test.go", + "create_deployment_test.go", + "create_job_test.go", + "create_namespace_test.go", + "create_pdb_test.go", + "create_priorityclass_test.go", + "create_quota_test.go", + "create_role_test.go", + "create_rolebinding_test.go", + "create_secret_test.go", + "create_service_test.go", + "create_serviceaccount_test.go", + "create_test.go", + ], + data = [ + "//test/e2e/testing-manifests:all-srcs", + ], + embed = [":go_default_library"], + deps = [ + "//pkg/api/legacyscheme:go_default_library", + "//pkg/api/testing:go_default_library", + "//pkg/apis/core:go_default_library", + "//pkg/kubectl:go_default_library", + "//pkg/kubectl/cmd/testing:go_default_library", + "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//pkg/kubectl/scheme:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/k8s.io/api/batch/v1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/util/diff:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/rest/fake:go_default_library", + "//vendor/k8s.io/client-go/testing:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create.go new file mode 100644 index 000000000..a6bb8b03b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create.go @@ -0,0 +1,451 @@ +/* +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 create + +import ( + "fmt" + "io" + "net/url" + "os" + "runtime" + "strings" + + "github.com/golang/glog" + "github.com/spf13/cobra" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + kruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "k8s.io/kubernetes/pkg/printers" +) + +type CreateOptions struct { + PrintFlags *genericclioptions.PrintFlags + RecordFlags *genericclioptions.RecordFlags + + DryRun bool + + FilenameOptions resource.FilenameOptions + Selector string + EditBeforeCreate bool + Raw string + + Recorder genericclioptions.Recorder + PrintObj func(obj kruntime.Object) error + + genericclioptions.IOStreams +} + +var ( + createLong = templates.LongDesc(i18n.T(` + Create a resource from a file or from stdin. + + JSON and YAML formats are accepted.`)) + + createExample = templates.Examples(i18n.T(` + # Create a pod using the data in pod.json. + kubectl create -f ./pod.json + + # Create a pod based on the JSON passed into stdin. + cat pod.json | kubectl create -f - + + # Edit the data in docker-registry.yaml in JSON then create the resource using the edited data. + kubectl create -f docker-registry.yaml --edit -o json`)) +) + +func NewCreateOptions(ioStreams genericclioptions.IOStreams) *CreateOptions { + return &CreateOptions{ + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), + RecordFlags: genericclioptions.NewRecordFlags(), + + Recorder: genericclioptions.NoopRecorder{}, + + IOStreams: ioStreams, + } +} + +func NewCmdCreate(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewCreateOptions(ioStreams) + + cmd := &cobra.Command{ + Use: "create -f FILENAME", + DisableFlagsInUseLine: true, + Short: i18n.T("Create a resource from a file or from stdin."), + Long: createLong, + Example: createExample, + Run: func(cmd *cobra.Command, args []string) { + if cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) { + defaultRunFunc := cmdutil.DefaultSubCommandRun(ioStreams.ErrOut) + defaultRunFunc(cmd, args) + return + } + cmdutil.CheckErr(o.Complete(f, cmd)) + cmdutil.CheckErr(o.ValidateArgs(cmd, args)) + cmdutil.CheckErr(o.RunCreate(f, cmd)) + }, + } + + // bind flag structs + o.RecordFlags.AddFlags(cmd) + + usage := "to use to create the resource" + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.MarkFlagRequired("filename") + cmdutil.AddValidateFlags(cmd) + cmd.Flags().BoolVar(&o.EditBeforeCreate, "edit", o.EditBeforeCreate, "Edit the API resource before creating") + cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows", + "Only relevant if --edit=true. Defaults to the line ending native to your platform.") + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddDryRunFlag(cmd) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().StringVar(&o.Raw, "raw", o.Raw, "Raw URI to POST to the server. Uses the transport specified by the kubeconfig file.") + + o.PrintFlags.AddFlags(cmd) + + // create subcommands + cmd.AddCommand(NewCmdCreateNamespace(f, ioStreams)) + cmd.AddCommand(NewCmdCreateQuota(f, ioStreams)) + cmd.AddCommand(NewCmdCreateSecret(f, ioStreams)) + cmd.AddCommand(NewCmdCreateConfigMap(f, ioStreams)) + cmd.AddCommand(NewCmdCreateServiceAccount(f, ioStreams)) + cmd.AddCommand(NewCmdCreateService(f, ioStreams)) + cmd.AddCommand(NewCmdCreateDeployment(f, ioStreams)) + cmd.AddCommand(NewCmdCreateClusterRole(f, ioStreams)) + cmd.AddCommand(NewCmdCreateClusterRoleBinding(f, ioStreams)) + cmd.AddCommand(NewCmdCreateRole(f, ioStreams)) + cmd.AddCommand(NewCmdCreateRoleBinding(f, ioStreams)) + cmd.AddCommand(NewCmdCreatePodDisruptionBudget(f, ioStreams)) + cmd.AddCommand(NewCmdCreatePriorityClass(f, ioStreams)) + cmd.AddCommand(NewCmdCreateJob(f, ioStreams)) + return cmd +} + +func (o *CreateOptions) ValidateArgs(cmd *cobra.Command, args []string) error { + if len(args) != 0 { + return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args) + } + if len(o.Raw) > 0 { + if o.EditBeforeCreate { + return cmdutil.UsageErrorf(cmd, "--raw and --edit are mutually exclusive") + } + if len(o.FilenameOptions.Filenames) != 1 { + return cmdutil.UsageErrorf(cmd, "--raw can only use a single local file or stdin") + } + if strings.Index(o.FilenameOptions.Filenames[0], "http://") == 0 || strings.Index(o.FilenameOptions.Filenames[0], "https://") == 0 { + return cmdutil.UsageErrorf(cmd, "--raw cannot read from a url") + } + if o.FilenameOptions.Recursive { + return cmdutil.UsageErrorf(cmd, "--raw and --recursive are mutually exclusive") + } + if len(o.Selector) > 0 { + return cmdutil.UsageErrorf(cmd, "--raw and --selector (-l) are mutually exclusive") + } + if len(cmdutil.GetFlagString(cmd, "output")) > 0 { + return cmdutil.UsageErrorf(cmd, "--raw and --output are mutually exclusive") + } + if _, err := url.ParseRequestURI(o.Raw); err != nil { + return cmdutil.UsageErrorf(cmd, "--raw must be a valid URL path: %v", err) + } + } + + return nil +} + +func (o *CreateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { + var err error + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + + o.DryRun = cmdutil.GetDryRunFlag(cmd) + + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + + o.PrintObj = func(obj kruntime.Object) error { + return printer.PrintObj(obj, o.Out) + } + + return nil +} + +func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error { + // raw only makes sense for a single file resource multiple objects aren't likely to do what you want. + // the validator enforces this, so + if len(o.Raw) > 0 { + return o.raw(f) + } + + if o.EditBeforeCreate { + return RunEditOnCreate(f, o.RecordFlags, o.IOStreams, cmd, &o.FilenameOptions) + } + schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) + if err != nil { + return err + } + + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + + r := f.NewBuilder(). + Unstructured(). + Schema(schema). + ContinueOnError(). + NamespaceParam(cmdNamespace).DefaultNamespace(). + FilenameParam(enforceNamespace, &o.FilenameOptions). + LabelSelectorParam(o.Selector). + Flatten(). + Do() + err = r.Err() + if err != nil { + return err + } + + count := 0 + err = r.Visit(func(info *resource.Info, err error) error { + if err != nil { + return err + } + if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info.Object, cmdutil.InternalVersionJSONEncoder()); err != nil { + return cmdutil.AddSourceToErr("creating", info.Source, err) + } + + if err := o.Recorder.Record(info.Object); err != nil { + glog.V(4).Infof("error recording current command: %v", err) + } + + if !o.DryRun { + if err := createAndRefresh(info); err != nil { + return cmdutil.AddSourceToErr("creating", info.Source, err) + } + } + + count++ + + return o.PrintObj(info.Object) + }) + if err != nil { + return err + } + if count == 0 { + return fmt.Errorf("no objects passed to create") + } + return nil +} + +// raw makes a simple HTTP request to the provided path on the server using the default +// credentials. +func (o *CreateOptions) raw(f cmdutil.Factory) error { + restClient, err := f.RESTClient() + if err != nil { + return err + } + + var data io.ReadCloser + if o.FilenameOptions.Filenames[0] == "-" { + data = os.Stdin + } else { + data, err = os.Open(o.FilenameOptions.Filenames[0]) + if err != nil { + return err + } + } + // TODO post content with stream. Right now it ignores body content + result := restClient.Post().RequestURI(o.Raw).Body(data).Do() + if err := result.Error(); err != nil { + return err + } + body, err := result.Raw() + if err != nil { + return err + } + + fmt.Fprintf(o.Out, "%v", string(body)) + return nil +} + +func RunEditOnCreate(f cmdutil.Factory, recordFlags *genericclioptions.RecordFlags, ioStreams genericclioptions.IOStreams, cmd *cobra.Command, options *resource.FilenameOptions) error { + editOptions := editor.NewEditOptions(editor.EditBeforeCreateMode, ioStreams) + editOptions.FilenameOptions = *options + editOptions.ValidateOptions = cmdutil.ValidateOptions{ + EnableValidation: cmdutil.GetFlagBool(cmd, "validate"), + } + editOptions.Output = cmdutil.GetFlagString(cmd, "output") + editOptions.ApplyAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag) + editOptions.RecordFlags = recordFlags + + err := editOptions.Complete(f, []string{}, cmd) + if err != nil { + return err + } + return editOptions.Run() +} + +// createAndRefresh creates an object from input info and refreshes info with that object +func createAndRefresh(info *resource.Info) error { + obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object) + if err != nil { + return err + } + info.Refresh(obj, true) + return nil +} + +// NameFromCommandArgs is a utility function for commands that assume the first argument is a resource name +func NameFromCommandArgs(cmd *cobra.Command, args []string) (string, error) { + if len(args) != 1 { + return "", cmdutil.UsageErrorf(cmd, "exactly one NAME is required, got %d", len(args)) + } + return args[0], nil +} + +// CreateSubcommandOptions is an options struct to support create subcommands +type CreateSubcommandOptions struct { + // PrintFlags holds options necessary for obtaining a printer + PrintFlags *genericclioptions.PrintFlags + // Name of resource being created + Name string + // StructuredGenerator is the resource generator for the object being created + StructuredGenerator kubectl.StructuredGenerator + // DryRun is true if the command should be simulated but not run against the server + DryRun bool + CreateAnnotation bool + + Namespace string + EnforceNamespace bool + + Mapper meta.RESTMapper + DynamicClient dynamic.Interface + + PrintObj printers.ResourcePrinterFunc + + genericclioptions.IOStreams +} + +func NewCreateSubcommandOptions(ioStreams genericclioptions.IOStreams) *CreateSubcommandOptions { + return &CreateSubcommandOptions{ + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), + IOStreams: ioStreams, + } +} + +func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string, generator kubectl.StructuredGenerator) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + o.Name = name + o.StructuredGenerator = generator + o.DryRun = cmdutil.GetDryRunFlag(cmd) + o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag) + + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + + o.PrintObj = func(obj kruntime.Object, out io.Writer) error { + return printer.PrintObj(obj, out) + } + + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + + o.DynamicClient, err = f.DynamicClient() + if err != nil { + return err + } + + o.Mapper, err = f.ToRESTMapper() + if err != nil { + return err + } + + return nil +} + +// RunCreateSubcommand executes a create subcommand using the specified options +func (o *CreateSubcommandOptions) Run() error { + obj, err := o.StructuredGenerator.StructuredGenerate() + if err != nil { + return err + } + if !o.DryRun { + // create subcommands have compiled knowledge of things they create, so type them directly + gvks, _, err := legacyscheme.Scheme.ObjectKinds(obj) + if err != nil { + return err + } + gvk := gvks[0] + mapping, err := o.Mapper.RESTMapping(schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version) + if err != nil { + return err + } + + if err := kubectl.CreateOrUpdateAnnotation(o.CreateAnnotation, obj, cmdutil.InternalVersionJSONEncoder()); err != nil { + return err + } + + asUnstructured := &unstructured.Unstructured{} + + if err := legacyscheme.Scheme.Convert(obj, asUnstructured, nil); err != nil { + return err + } + if mapping.Scope.Name() == meta.RESTScopeNameRoot { + o.Namespace = "" + } + actualObject, err := o.DynamicClient.Resource(mapping.Resource).Namespace(o.Namespace).Create(asUnstructured) + if err != nil { + return err + } + + // ensure we pass a versioned object to the printer + obj = actualObject + } else { + if meta, err := meta.Accessor(obj); err == nil && o.EnforceNamespace { + meta.SetNamespace(o.Namespace) + } + } + + return o.PrintObj(obj, o.Out) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrole.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrole.go new file mode 100644 index 000000000..4f3002549 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrole.go @@ -0,0 +1,206 @@ +/* +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 create + +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" + + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilflag "k8s.io/apiserver/pkg/util/flag" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" +) + +var ( + clusterRoleLong = templates.LongDesc(i18n.T(` + Create a ClusterRole.`)) + + clusterRoleExample = templates.Examples(i18n.T(` + # Create a ClusterRole named "pod-reader" that allows user to perform "get", "watch" and "list" on pods + kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods + + # Create a ClusterRole named "pod-reader" with ResourceName specified + kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod + + # Create a ClusterRole named "foo" with API Group specified + kubectl create clusterrole foo --verb=get,list,watch --resource=rs.extensions + + # Create a ClusterRole named "foo" with SubResource specified + kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status + + # Create a ClusterRole name "foo" with NonResourceURL specified + kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/* + + # Create a ClusterRole name "monitoring" with AggregationRule specified + kubectl create clusterrole monitoring --aggregation-rule="rbac.example.com/aggregate-to-monitoring=true"`)) + + // Valid nonResource verb list for validation. + validNonResourceVerbs = []string{"*", "get", "post", "put", "delete", "patch", "head", "options"} +) + +type CreateClusterRoleOptions struct { + *CreateRoleOptions + NonResourceURLs []string + AggregationRule map[string]string +} + +// ClusterRole is a command to ease creating ClusterRoles. +func NewCmdCreateClusterRole(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + c := &CreateClusterRoleOptions{ + CreateRoleOptions: NewCreateRoleOptions(ioStreams), + AggregationRule: map[string]string{}, + } + cmd := &cobra.Command{ + Use: "clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]", + DisableFlagsInUseLine: true, + Short: clusterRoleLong, + Long: clusterRoleLong, + Example: clusterRoleExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(c.Complete(f, cmd, args)) + cmdutil.CheckErr(c.Validate()) + cmdutil.CheckErr(c.RunCreateRole()) + }, + } + + c.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddDryRunFlag(cmd) + cmd.Flags().StringSliceVar(&c.Verbs, "verb", c.Verbs, "Verb that applies to the resources contained in the rule") + cmd.Flags().StringSliceVar(&c.NonResourceURLs, "non-resource-url", c.NonResourceURLs, "A partial url that user should have access to.") + cmd.Flags().StringSlice("resource", []string{}, "Resource that the rule applies to") + cmd.Flags().StringArrayVar(&c.ResourceNames, "resource-name", c.ResourceNames, "Resource in the white list that the rule applies to, repeat this flag for multiple items") + cmd.Flags().Var(utilflag.NewMapStringString(&c.AggregationRule), "aggregation-rule", "An aggregation label selector for combining ClusterRoles.") + + return cmd +} + +func (c *CreateClusterRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + // Remove duplicate nonResourceURLs + nonResourceURLs := []string{} + for _, n := range c.NonResourceURLs { + if !arrayContains(nonResourceURLs, n) { + nonResourceURLs = append(nonResourceURLs, n) + } + } + c.NonResourceURLs = nonResourceURLs + + return c.CreateRoleOptions.Complete(f, cmd, args) +} + +func (c *CreateClusterRoleOptions) Validate() error { + if c.Name == "" { + return fmt.Errorf("name must be specified") + } + + if len(c.AggregationRule) > 0 { + if len(c.NonResourceURLs) > 0 || len(c.Verbs) > 0 || len(c.Resources) > 0 || len(c.ResourceNames) > 0 { + return fmt.Errorf("aggregation rule must be specified without nonResourceURLs, verbs, resources or resourceNames") + } + return nil + } + + // validate verbs. + if len(c.Verbs) == 0 { + return fmt.Errorf("at least one verb must be specified") + } + + if len(c.Resources) == 0 && len(c.NonResourceURLs) == 0 { + return fmt.Errorf("one of resource or nonResourceURL must be specified") + } + + // validate resources + if len(c.Resources) > 0 { + for _, v := range c.Verbs { + if !arrayContains(validResourceVerbs, v) { + return fmt.Errorf("invalid verb: '%s'", v) + } + } + if err := c.validateResource(); err != nil { + return err + } + } + + //validate non-resource-url + if len(c.NonResourceURLs) > 0 { + for _, v := range c.Verbs { + if !arrayContains(validNonResourceVerbs, v) { + return fmt.Errorf("invalid verb: '%s' for nonResourceURL", v) + } + } + + for _, nonResourceURL := range c.NonResourceURLs { + if nonResourceURL == "*" { + continue + } + + if nonResourceURL == "" || !strings.HasPrefix(nonResourceURL, "/") { + return fmt.Errorf("nonResourceURL should start with /") + } + + if strings.ContainsRune(nonResourceURL[:len(nonResourceURL)-1], '*') { + return fmt.Errorf("nonResourceURL only supports wildcard matches when '*' is at the end") + } + } + } + + return nil + +} + +func (c *CreateClusterRoleOptions) RunCreateRole() error { + clusterRole := &rbacv1.ClusterRole{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: rbacv1.SchemeGroupVersion.String(), Kind: "ClusterRole"}, + } + clusterRole.Name = c.Name + + var err error + if len(c.AggregationRule) == 0 { + rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames, c.NonResourceURLs) + if err != nil { + return err + } + clusterRole.Rules = rules + } else { + clusterRole.AggregationRule = &rbacv1.AggregationRule{ + ClusterRoleSelectors: []metav1.LabelSelector{ + { + MatchLabels: c.AggregationRule, + }, + }, + } + } + + // Create ClusterRole. + if !c.DryRun { + clusterRole, err = c.Client.ClusterRoles().Create(clusterRole) + if err != nil { + return err + } + } + + return c.PrintObj(clusterRole) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrole_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrole_test.go similarity index 80% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrole_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrole_test.go index 6f2db36f1..647c08657 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrole_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrole_test.go @@ -14,28 +14,31 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "bytes" "testing" rbac "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestCreateClusterRole(t *testing.T) { clusterRoleName := "my-cluster-role" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() @@ -44,6 +47,7 @@ func TestCreateClusterRole(t *testing.T) { resources string nonResourceURL string resourceNames string + aggregationRule string expectedClusterRole *rbac.ClusterRole }{ "test-duplicate-resources": { @@ -127,16 +131,36 @@ func TestCreateClusterRole(t *testing.T) { }, }, }, + "test-aggregation-rules": { + aggregationRule: "foo1=foo2,foo3=foo4", + expectedClusterRole: &rbac.ClusterRole{ + TypeMeta: v1.TypeMeta{APIVersion: "rbac.authorization.k8s.io/v1", Kind: "ClusterRole"}, + ObjectMeta: v1.ObjectMeta{ + Name: clusterRoleName, + }, + AggregationRule: &rbac.AggregationRule{ + ClusterRoleSelectors: []metav1.LabelSelector{ + { + MatchLabels: map[string]string{ + "foo1": "foo2", + "foo3": "foo4", + }, + }, + }, + }, + }, + }, } for name, test := range tests { - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateClusterRole(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateClusterRole(tf, ioStreams) cmd.Flags().Set("dry-run", "true") cmd.Flags().Set("output", "yaml") cmd.Flags().Set("verb", test.verbs) cmd.Flags().Set("resource", test.resources) cmd.Flags().Set("non-resource-url", test.nonResourceURL) + cmd.Flags().Set("aggregation-rule", test.aggregationRule) if test.resourceNames != "" { cmd.Flags().Set("resource-name", test.resourceNames) } @@ -153,11 +177,9 @@ func TestCreateClusterRole(t *testing.T) { } func TestClusterRoleValidate(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" - tests := map[string]struct { clusterRoleOptions *CreateClusterRoleOptions expectErr bool @@ -430,12 +452,60 @@ func TestClusterRoleValidate(t *testing.T) { }, expectErr: false, }, + "test-aggregation-rule-with-verb": { + clusterRoleOptions: &CreateClusterRoleOptions{ + CreateRoleOptions: &CreateRoleOptions{ + Name: "my-clusterrole", + Verbs: []string{"get"}, + }, + AggregationRule: map[string]string{"foo-key": "foo-vlue"}, + }, + expectErr: true, + }, + "test-aggregation-rule-with-resource": { + clusterRoleOptions: &CreateClusterRoleOptions{ + CreateRoleOptions: &CreateRoleOptions{ + Name: "my-clusterrole", + Resources: []ResourceOptions{ + { + Resource: "replicasets", + SubResource: "scale", + }, + }, + }, + AggregationRule: map[string]string{"foo-key": "foo-vlue"}, + }, + expectErr: true, + }, + "test-aggregation-rule-with-no-resource-url": { + clusterRoleOptions: &CreateClusterRoleOptions{ + CreateRoleOptions: &CreateRoleOptions{ + Name: "my-clusterrole", + }, + NonResourceURLs: []string{"/logs/"}, + AggregationRule: map[string]string{"foo-key": "foo-vlue"}, + }, + expectErr: true, + }, + "test-aggregation-rule": { + clusterRoleOptions: &CreateClusterRoleOptions{ + CreateRoleOptions: &CreateRoleOptions{ + Name: "my-clusterrole", + }, + AggregationRule: map[string]string{"foo-key": "foo-vlue"}, + }, + expectErr: false, + }, } for name, test := range tests { t.Run(name, func(t *testing.T) { - test.clusterRoleOptions.Mapper, _ = tf.Object() - err := test.clusterRoleOptions.Validate() + var err error + test.clusterRoleOptions.Mapper, err = tf.ToRESTMapper() + if err != nil { + t.Fatal(err) + } + err = test.clusterRoleOptions.Validate() if test.expectErr && err == nil { t.Errorf("%s: expect error happens, but validate passes.", name) } @@ -445,3 +515,14 @@ func TestClusterRoleValidate(t *testing.T) { }) } } + +func defaultClientConfig() *restclient.Config { + return &restclient.Config{ + APIPath: "/api", + ContentConfig: restclient.ContentConfig{ + NegotiatedSerializer: scheme.Codecs, + ContentType: runtime.ContentTypeJSON, + GroupVersion: &schema.GroupVersion{Version: "v1"}, + }, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrolebinding.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrolebinding.go similarity index 79% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrolebinding.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrolebinding.go index c7ce180c3..d07992390 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrolebinding.go @@ -14,16 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -36,8 +35,16 @@ var ( kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1`)) ) +type ClusterRoleBindingOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + // ClusterRoleBinding is a command to ease creating ClusterRoleBindings. -func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &ClusterRoleBindingOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + cmd := &cobra.Command{ Use: "clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", DisableFlagsInUseLine: true, @@ -45,13 +52,15 @@ func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra. Long: clusterRoleBindingLong, Example: clusterRoleBindingExample, Run: func(cmd *cobra.Command, args []string) { - err := CreateClusterRoleBinding(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) }, } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) cmdutil.AddGeneratorFlags(cmd, cmdutil.ClusterRoleBindingV1GeneratorName) cmd.Flags().String("clusterrole", "", i18n.T("ClusterRole this ClusterRoleBinding should reference")) cmd.MarkFlagCustom("clusterrole", "__kubectl_get_resource_clusterrole") @@ -61,12 +70,12 @@ func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra. return cmd } -// CreateClusterRoleBinding is the implementation of the create clusterrolebinding command. -func CreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { +func (o *ClusterRoleBindingOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { return err } + var generator kubectl.StructuredGenerator switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { case cmdutil.ClusterRoleBindingV1GeneratorName: @@ -80,10 +89,11 @@ func CreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Co default: return errUnsupportedGenerator(cmd, generatorName) } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateClusterRoleBinding is the implementation of the create clusterrolebinding command. +func (o *ClusterRoleBindingOpts) Run() error { + return o.CreateSubcommandOptions.Run() } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrolebinding_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go similarity index 92% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrolebinding_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go index 762edac82..69f1559aa 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrolebinding_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( "bytes" @@ -32,6 +32,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestCreateClusterRoleBinding(t *testing.T) { @@ -67,7 +68,7 @@ func TestCreateClusterRoleBinding(t *testing.T) { }, } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -76,7 +77,6 @@ func TestCreateClusterRoleBinding(t *testing.T) { encoder := ns.EncoderForVersion(info.Serializer, groupVersion) decoder := ns.DecoderToVersion(info.Serializer, groupVersion) - tf.Namespace = "test" tf.Client = &ClusterRoleBindingRESTClient{ RESTClient: &fake.RESTClient{ NegotiatedSerializer: ns, @@ -111,8 +111,8 @@ func TestCreateClusterRoleBinding(t *testing.T) { } expectedOutput := "clusterrolebinding.rbac.authorization.k8s.io/" + expectBinding.Name + "\n" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateClusterRoleBinding(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateClusterRoleBinding(tf, ioStreams) cmd.Flags().Set("clusterrole", "fake-clusterrole") cmd.Flags().Set("user", "fake-user") cmd.Flags().Set("group", "fake-group") @@ -145,3 +145,9 @@ func (c *ClusterRoleBindingRESTClient) Post() *restclient.Request { } return restclient.NewRequest(c, "POST", &url.URL{Host: "localhost"}, c.VersionedAPIPath, config, serializers, nil, nil, 0) } + +func defaultHeader() http.Header { + header := http.Header{} + header.Set("Content-Type", runtime.ContentTypeJSON) + return header +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_configmap.go similarity index 85% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_configmap.go index cb80b83e9..8abaa314f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_configmap.go @@ -14,16 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -57,8 +56,16 @@ var ( kubectl create configmap my-config --from-env-file=path/to/bar.env`)) ) +type ConfigMapOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + // ConfigMap is a command to ease creating ConfigMaps. -func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateConfigMap(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &ConfigMapOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + cmd := &cobra.Command{ Use: "configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", DisableFlagsInUseLine: true, @@ -67,13 +74,15 @@ func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { Long: configMapLong, Example: configMapExample, Run: func(cmd *cobra.Command, args []string) { - err := CreateConfigMap(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) }, } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) cmdutil.AddGeneratorFlags(cmd, cmdutil.ConfigMapV1GeneratorName) cmd.Flags().StringSlice("from-file", []string{}, "Key file can be specified using its file path, in which case file basename will be used as configmap key, or optionally with a key and file path, in which case the given key will be used. Specifying a directory will iterate each named file in the directory whose basename is a valid configmap key.") cmd.Flags().StringArray("from-literal", []string{}, "Specify a key and literal value to insert in configmap (i.e. mykey=somevalue)") @@ -82,12 +91,12 @@ func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { return cmd } -// CreateConfigMap is the implementation of the create configmap command. -func CreateConfigMap(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { +func (o *ConfigMapOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { return err } + var generator kubectl.StructuredGenerator switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { case cmdutil.ConfigMapV1GeneratorName: @@ -101,10 +110,11 @@ func CreateConfigMap(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, ar default: return errUnsupportedGenerator(cmd, generatorName) } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateConfigMap is the implementation of the create configmap command. +func (o *ConfigMapOpts) Run() error { + return o.CreateSubcommandOptions.Run() } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_configmap_test.go similarity index 77% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_configmap_test.go index a0d5bdaec..8ee9501bc 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_configmap_test.go @@ -14,28 +14,32 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( "bytes" + "io" + "io/ioutil" "net/http" "testing" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestCreateConfigMap(t *testing.T) { configMap := &v1.ConfigMap{} configMap.Name = "my-configmap" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -51,9 +55,8 @@ func TestCreateConfigMap(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateConfigMap(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateConfigMap(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{configMap.Name}) expectedOutput := "configmap/" + configMap.Name + "\n" @@ -61,3 +64,7 @@ func TestCreateConfigMap(t *testing.T) { t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) } } + +func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser { + return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj)))) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_deployment.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_deployment.go new file mode 100644 index 000000000..13ec3235d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_deployment.go @@ -0,0 +1,155 @@ +/* +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 create + +import ( + "github.com/spf13/cobra" + + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" +) + +var ( + deploymentLong = templates.LongDesc(i18n.T(` + Create a deployment with the specified name.`)) + + deploymentExample = templates.Examples(i18n.T(` + # Create a new deployment named my-dep that runs the busybox image. + kubectl create deployment my-dep --image=busybox`)) +) + +type DeploymentOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateDeployment is a macro command to create a new deployment. +// This command is better known to users as `kubectl create deployment`. +// Note that this command overlaps significantly with the `kubectl run` command. +func NewCmdCreateDeployment(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &DeploymentOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "deployment NAME --image=image [--dry-run]", + DisableFlagsInUseLine: true, + Aliases: []string{"deploy"}, + Short: i18n.T("Create a deployment with the specified name."), + Long: deploymentLong, + Example: deploymentExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, "") + cmd.Flags().StringSlice("image", []string{}, "Image name to run.") + cmd.MarkFlagRequired("image") + return cmd +} + +// generatorFromName returns the appropriate StructuredGenerator based on the +// generatorName. If the generatorName is unrecognized, then return (nil, +// false). +func generatorFromName( + generatorName string, + imageNames []string, + deploymentName string, +) (kubectl.StructuredGenerator, bool) { + + switch generatorName { + case cmdutil.DeploymentBasicAppsV1GeneratorName: + generator := &kubectl.DeploymentBasicAppsGeneratorV1{ + BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ + Name: deploymentName, + Images: imageNames, + }, + } + return generator, true + + case cmdutil.DeploymentBasicAppsV1Beta1GeneratorName: + generator := &kubectl.DeploymentBasicAppsGeneratorV1Beta1{ + BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ + Name: deploymentName, + Images: imageNames, + }, + } + return generator, true + + case cmdutil.DeploymentBasicV1Beta1GeneratorName: + generator := &kubectl.DeploymentBasicGeneratorV1{ + BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ + Name: deploymentName, + Images: imageNames, + }, + } + return generator, true + } + + return nil, false +} + +func (o *DeploymentOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + clientset, err := f.ClientSet() + if err != nil { + return err + } + + generatorName := cmdutil.GetFlagString(cmd, "generator") + + if len(generatorName) == 0 { + generatorName = cmdutil.DeploymentBasicAppsV1GeneratorName + generatorNameTemp, err := cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), o.CreateSubcommandOptions.ErrOut) + if err != nil { + return err + } + if generatorNameTemp != generatorName { + cmdutil.Warning(o.CreateSubcommandOptions.ErrOut, generatorName, generatorNameTemp) + } else { + generatorName = generatorNameTemp + } + } + + imageNames := cmdutil.GetFlagStringSlice(cmd, "image") + generator, ok := generatorFromName(generatorName, imageNames, name) + if !ok { + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// createDeployment +// 1. Reads user config values from Cobra. +// 2. Sets up the correct Generator object. +// 3. Calls RunCreateSubcommand. +func (o *DeploymentOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_deployment_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_deployment_test.go new file mode 100644 index 000000000..1df3066eb --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_deployment_test.go @@ -0,0 +1,156 @@ +/* +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 create + +import ( + "bytes" + "io/ioutil" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/kubectl" + cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +func Test_generatorFromName(t *testing.T) { + const ( + nonsenseName = "not-a-real-generator-name" + basicName = cmdutil.DeploymentBasicV1Beta1GeneratorName + basicAppsV1Beta1Name = cmdutil.DeploymentBasicAppsV1Beta1GeneratorName + basicAppsV1Name = cmdutil.DeploymentBasicAppsV1GeneratorName + deploymentName = "deployment-name" + ) + imageNames := []string{"image-1", "image-2"} + + generator, ok := generatorFromName(nonsenseName, imageNames, deploymentName) + assert.Nil(t, generator) + assert.False(t, ok) + + generator, ok = generatorFromName(basicName, imageNames, deploymentName) + assert.True(t, ok) + + { + expectedGenerator := &kubectl.DeploymentBasicGeneratorV1{ + BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ + Name: deploymentName, + Images: imageNames, + }, + } + assert.Equal(t, expectedGenerator, generator) + } + + generator, ok = generatorFromName(basicAppsV1Beta1Name, imageNames, deploymentName) + assert.True(t, ok) + + { + expectedGenerator := &kubectl.DeploymentBasicAppsGeneratorV1Beta1{ + BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ + Name: deploymentName, + Images: imageNames, + }, + } + assert.Equal(t, expectedGenerator, generator) + } + + generator, ok = generatorFromName(basicAppsV1Name, imageNames, deploymentName) + assert.True(t, ok) + + { + expectedGenerator := &kubectl.DeploymentBasicAppsGeneratorV1{ + BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ + Name: deploymentName, + Images: imageNames, + }, + } + assert.Equal(t, expectedGenerator, generator) + } +} + +func TestCreateDeployment(t *testing.T) { + depName := "jonny-dep" + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + + ns := legacyscheme.Codecs + fakeDiscovery := "{\"kind\":\"APIResourceList\",\"apiVersion\":\"v1\",\"groupVersion\":\"apps/v1\",\"resources\":[{\"name\":\"deployments\",\"singularName\":\"\",\"namespaced\":true,\"kind\":\"Deployment\",\"verbs\":[\"create\",\"delete\",\"deletecollection\",\"get\",\"list\",\"patch\",\"update\",\"watch\"],\"shortNames\":[\"deploy\"],\"categories\":[\"all\"]}]}" + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte(fakeDiscovery))), + }, nil + }), + } + tf.ClientConfigVal = &restclient.Config{} + + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateDeployment(tf, ioStreams) + cmd.Flags().Set("dry-run", "true") + cmd.Flags().Set("output", "name") + cmd.Flags().Set("image", "hollywood/jonny.depp:v2") + cmd.Run(cmd, []string{depName}) + expectedOutput := "deployment.apps/" + depName + "\n" + if buf.String() != expectedOutput { + t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) + } +} + +func TestCreateDeploymentNoImage(t *testing.T) { + depName := "jonny-dep" + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + + ns := legacyscheme.Codecs + fakeDiscovery := "{\"kind\":\"APIResourceList\",\"apiVersion\":\"v1\",\"groupVersion\":\"apps/v1\",\"resources\":[{\"name\":\"deployments\",\"singularName\":\"\",\"namespaced\":true,\"kind\":\"Deployment\",\"verbs\":[\"create\",\"delete\",\"deletecollection\",\"get\",\"list\",\"patch\",\"update\",\"watch\"],\"shortNames\":[\"deploy\"],\"categories\":[\"all\"]}]}" + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte(fakeDiscovery))), + }, nil + }), + } + tf.ClientConfigVal = &restclient.Config{} + + ioStreams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdCreateDeployment(tf, ioStreams) + cmd.Flags().Set("output", "name") + options := &DeploymentOpts{ + CreateSubcommandOptions: &CreateSubcommandOptions{ + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), + DryRun: true, + IOStreams: ioStreams, + }, + } + + err := options.Complete(tf, cmd, []string{depName}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + err = options.Run() + assert.Error(t, err, "at least one image must be specified") +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_job.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_job.go new file mode 100644 index 000000000..1e92754de --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_job.go @@ -0,0 +1,186 @@ +/* +Copyright 2018 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 create + +import ( + "fmt" + + "github.com/spf13/cobra" + + batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + clientbatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" +) + +var ( + jobLong = templates.LongDesc(i18n.T(` + Create a job with the specified name.`)) + + jobExample = templates.Examples(i18n.T(` + # Create a job from a CronJob named "a-cronjob" + kubectl create job test-job --from=cronjob/a-cronjob`)) +) + +type CreateJobOptions struct { + PrintFlags *genericclioptions.PrintFlags + + PrintObj func(obj runtime.Object) error + + Name string + From string + + Namespace string + OutputFormat string + Client clientbatchv1.BatchV1Interface + DryRun bool + Builder *resource.Builder + Cmd *cobra.Command + + genericclioptions.IOStreams +} + +func NewCreateJobOptions(ioStreams genericclioptions.IOStreams) *CreateJobOptions { + return &CreateJobOptions{ + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), + IOStreams: ioStreams, + } +} + +// NewCmdCreateJob is a command to ease creating Jobs from CronJobs. +func NewCmdCreateJob(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewCreateJobOptions(ioStreams) + + cmd := &cobra.Command{ + Use: "job NAME [--from=CRONJOB]", + Short: jobLong, + Long: jobLong, + Example: jobExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.RunCreateJob()) + }, + } + + o.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddDryRunFlag(cmd) + cmd.Flags().StringVar(&o.From, "from", o.From, "The name of the resource to create a Job from (only cronjob is supported).") + + return cmd +} + +func (o *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) (err error) { + if len(args) == 0 { + return cmdutil.UsageErrorf(cmd, "NAME is required") + } + o.Name = args[0] + + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + + clientset, err := f.KubernetesClientSet() + if err != nil { + return err + } + o.Client = clientset.BatchV1() + o.Builder = f.NewBuilder() + o.DryRun = cmdutil.GetDryRunFlag(cmd) + o.Cmd = cmd + o.OutputFormat = cmdutil.GetFlagString(cmd, "output") + + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + + o.PrintObj = func(obj runtime.Object) error { + return printer.PrintObj(obj, o.Out) + } + + return nil +} + +func (o *CreateJobOptions) RunCreateJob() error { + infos, err := o.Builder. + Unstructured(). + NamespaceParam(o.Namespace).DefaultNamespace(). + ResourceTypeOrNameArgs(false, o.From). + Flatten(). + Latest(). + Do(). + Infos() + if err != nil { + return err + } + if len(infos) != 1 { + return fmt.Errorf("from must be an existing cronjob") + } + + uncastVersionedObj, err := scheme.Scheme.ConvertToVersion(infos[0].Object, batchv1beta1.SchemeGroupVersion) + if err != nil { + return fmt.Errorf("from must be an existing cronjob: %v", err) + } + cronJob, ok := uncastVersionedObj.(*batchv1beta1.CronJob) + if !ok { + return fmt.Errorf("from must be an existing cronjob") + } + + return o.createJob(cronJob) +} + +func (o *CreateJobOptions) createJob(cronJob *batchv1beta1.CronJob) error { + annotations := make(map[string]string) + annotations["cronjob.kubernetes.io/instantiate"] = "manual" + for k, v := range cronJob.Spec.JobTemplate.Annotations { + annotations[k] = v + } + job := &batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: o.Name, + Namespace: o.Namespace, + Annotations: annotations, + Labels: cronJob.Spec.JobTemplate.Labels, + }, + Spec: cronJob.Spec.JobTemplate.Spec, + } + + if !o.DryRun { + var err error + job, err = o.Client.Jobs(o.Namespace).Create(job) + if err != nil { + return fmt.Errorf("failed to create job: %v", err) + } + } + + return o.PrintObj(job) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_job_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_job_test.go similarity index 85% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_job_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_job_test.go index 2e6989dc8..d866c8e83 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_job_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_job_test.go @@ -14,10 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "bytes" "testing" batchv1 "k8s.io/api/batch/v1" @@ -27,7 +26,9 @@ import ( "k8s.io/apimachinery/pkg/runtime" fake "k8s.io/client-go/kubernetes/fake" clienttesting "k8s.io/client-go/testing" + "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestCreateJobFromCronJob(t *testing.T) { @@ -84,13 +85,24 @@ func TestCreateJobFromCronJob(t *testing.T) { f := cmdtesting.NewTestFactory() defer f.Cleanup() - buf := bytes.NewBuffer([]byte{}) + printFlags := genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme) + + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmdOptions := &CreateJobOptions{ - Name: testJobName, - Namespace: testNamespaceName, - Client: clientset.BatchV1(), - Out: buf, - Cmd: NewCmdCreateJob(f, buf), + PrintFlags: printFlags, + Name: testJobName, + Namespace: testNamespaceName, + Client: clientset.BatchV1(), + Cmd: NewCmdCreateJob(f, ioStreams), + PrintObj: func(obj runtime.Object) error { + p, err := printFlags.ToPrinter() + if err != nil { + return err + } + + return p.PrintObj(obj, buf) + }, + IOStreams: ioStreams, } err := cmdOptions.createJob(cronJob) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_namespace.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_namespace.go new file mode 100644 index 000000000..3ab1a26d4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_namespace.go @@ -0,0 +1,90 @@ +/* +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 create + +import ( + "github.com/spf13/cobra" + + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" +) + +var ( + namespaceLong = templates.LongDesc(i18n.T(` + Create a namespace with the specified name.`)) + + namespaceExample = templates.Examples(i18n.T(` + # Create a new namespace named my-namespace + kubectl create namespace my-namespace`)) +) + +type NamespaceOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateNamespace is a macro command to create a new namespace +func NewCmdCreateNamespace(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &NamespaceOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "namespace NAME [--dry-run]", + DisableFlagsInUseLine: true, + Aliases: []string{"ns"}, + Short: i18n.T("Create a namespace with the specified name"), + Long: namespaceLong, + Example: namespaceExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.NamespaceV1GeneratorName) + + return cmd +} + +func (o *NamespaceOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.NamespaceV1GeneratorName: + generator = &kubectl.NamespaceGeneratorV1{Name: name} + default: + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateNamespace implements the behavior to run the create namespace command +func (o *NamespaceOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_namespace_test.go similarity index 87% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_namespace_test.go index c743ce7cf..8bfd9bd2f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_namespace_test.go @@ -14,10 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "bytes" "net/http" "testing" @@ -26,6 +25,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -35,7 +35,7 @@ func TestCreateNamespace(t *testing.T) { tf := cmdtesting.NewTestFactory() defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -51,8 +51,8 @@ func TestCreateNamespace(t *testing.T) { } }), } - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateNamespace(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateNamespace(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{namespaceObject.Name}) expectedOutput := "namespace/" + namespaceObject.Name + "\n" diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_pdb.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_pdb.go similarity index 81% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_pdb.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_pdb.go index 83232cafb..c8027a142 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_pdb.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_pdb.go @@ -14,16 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -41,8 +40,16 @@ var ( kubectl create pdb my-pdb --selector=app=nginx --min-available=50%`)) ) +type PodDisruptionBudgetOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + // NewCmdCreatePodDisruptionBudget is a macro command to create a new pod disruption budget. -func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &PodDisruptionBudgetOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + cmd := &cobra.Command{ Use: "poddisruptionbudget NAME --selector=SELECTOR --min-available=N [--dry-run]", DisableFlagsInUseLine: true, @@ -51,14 +58,15 @@ func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra Long: pdbLong, Example: pdbExample, Run: func(cmd *cobra.Command, args []string) { - err := CreatePodDisruptionBudget(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) }, } + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) cmdutil.AddGeneratorFlags(cmd, cmdutil.PodDisruptionBudgetV2GeneratorName) cmd.Flags().String("min-available", "", i18n.T("The minimum number or percentage of available pods this budget requires.")) @@ -67,12 +75,12 @@ func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra return cmd } -// CreatePodDisruptionBudget implements the behavior to run the create pdb command. -func CreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { +func (o *PodDisruptionBudgetOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { return err } + var generator kubectl.StructuredGenerator switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { case cmdutil.PodDisruptionBudgetV1GeneratorName: @@ -91,10 +99,11 @@ func CreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.C default: return errUnsupportedGenerator(cmd, generatorName) } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreatePodDisruptionBudget implements the behavior to run the create pdb command. +func (o *PodDisruptionBudgetOpts) Run() error { + return o.CreateSubcommandOptions.Run() } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_pdb_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_pdb_test.go new file mode 100644 index 000000000..42e7652c0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_pdb_test.go @@ -0,0 +1,85 @@ +/* +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 create + +import ( + "bytes" + "io/ioutil" + "net/http" + "testing" + + "k8s.io/apimachinery/pkg/runtime/schema" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" + cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +func TestCreatePdb(t *testing.T) { + pdbName := "my-pdb" + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + + ns := legacyscheme.Codecs + + tf.Client = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Group: "policy", Version: "v1beta1"}, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(&bytes.Buffer{}), + }, nil + }), + } + tf.ClientConfigVal = &restclient.Config{} + + outputFormat := "name" + + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreatePodDisruptionBudget(tf, ioStreams) + cmd.Flags().Set("min-available", "1") + cmd.Flags().Set("selector", "app=rails") + cmd.Flags().Set("dry-run", "true") + cmd.Flags().Set("output", outputFormat) + + printFlags := genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme) + printFlags.OutputFormat = &outputFormat + + options := &PodDisruptionBudgetOpts{ + CreateSubcommandOptions: &CreateSubcommandOptions{ + PrintFlags: printFlags, + Name: pdbName, + IOStreams: ioStreams, + }, + } + err := options.Complete(tf, cmd, []string{pdbName}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + err = options.Run() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expectedOutput := "poddisruptionbudget.policy/" + pdbName + "\n" + if buf.String() != expectedOutput { + t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_priorityclass.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_priorityclass.go similarity index 79% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_priorityclass.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_priorityclass.go index a01b50921..58abe3180 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_priorityclass.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_priorityclass.go @@ -14,16 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -39,8 +38,16 @@ var ( kubectl create priorityclass default-priority --value=1000 --global-default=true --description="default priority"`)) ) +type PriorityClassOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + // NewCmdCreatePriorityClass is a macro command to create a new priorityClass. -func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreatePriorityClass(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &PriorityClassOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + cmd := &cobra.Command{ Use: "priorityclass NAME --value=VALUE --global-default=BOOL [--dry-run]", DisableFlagsInUseLine: true, @@ -49,13 +56,15 @@ func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comma Long: pcLong, Example: pcExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(CreatePriorityClass(f, cmdOut, cmd, args)) + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) }, } + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) cmdutil.AddGeneratorFlags(cmd, cmdutil.PriorityClassV1Alpha1GeneratorName) cmd.Flags().Int32("value", 0, i18n.T("the value of this priority class.")) @@ -64,12 +73,12 @@ func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Comma return cmd } -// CreatePriorityClass implements the behavior to run the create priorityClass command. -func CreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { +func (o *PriorityClassOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { return err } + var generator kubectl.StructuredGenerator switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { case cmdutil.PriorityClassV1Alpha1GeneratorName: @@ -82,10 +91,11 @@ func CreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command default: return errUnsupportedGenerator(cmd, generatorName) } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreatePriorityClass implements the behavior to run the create priorityClass command. +func (o *PriorityClassOpts) Run() error { + return o.CreateSubcommandOptions.Run() } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_priorityclass_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_priorityclass_test.go new file mode 100644 index 000000000..b25aaa7a2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_priorityclass_test.go @@ -0,0 +1,86 @@ +/* +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 create + +import ( + "bytes" + "io/ioutil" + "net/http" + "testing" + + "k8s.io/apimachinery/pkg/runtime/schema" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" + cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +func TestCreatePriorityClass(t *testing.T) { + pcName := "my-pc" + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + ns := legacyscheme.Codecs + + tf.Client = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Group: "scheduling.k8s.io", Version: "v1beta1"}, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(&bytes.Buffer{}), + }, nil + }), + } + tf.ClientConfigVal = &restclient.Config{} + + outputFormat := "name" + + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreatePriorityClass(tf, ioStreams) + cmd.Flags().Set("value", "1000") + cmd.Flags().Set("global-default", "true") + cmd.Flags().Set("description", "my priority") + cmd.Flags().Set("dry-run", "true") + cmd.Flags().Set("output", outputFormat) + + printFlags := genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme) + printFlags.OutputFormat = &outputFormat + + options := &PriorityClassOpts{ + CreateSubcommandOptions: &CreateSubcommandOptions{ + PrintFlags: printFlags, + Name: pcName, + IOStreams: ioStreams, + }, + } + err := options.Complete(tf, cmd, []string{pcName}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + err = options.Run() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expectedOutput := "priorityclass.scheduling.k8s.io/" + pcName + "\n" + if buf.String() != expectedOutput { + t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_quota.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_quota.go similarity index 79% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_quota.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_quota.go index d66d68a94..015c96431 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_quota.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_quota.go @@ -14,16 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -39,8 +38,16 @@ var ( kubectl create quota best-effort --hard=pods=100 --scopes=BestEffort`)) ) +type QuotaOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + // NewCmdCreateQuota is a macro command to create a new quota -func NewCmdCreateQuota(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateQuota(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &QuotaOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + cmd := &cobra.Command{ Use: "quota NAME [--hard=key1=value1,key2=value2] [--scopes=Scope1,Scope2] [--dry-run=bool]", DisableFlagsInUseLine: true, @@ -49,26 +56,27 @@ func NewCmdCreateQuota(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { Long: quotaLong, Example: quotaExample, Run: func(cmd *cobra.Command, args []string) { - err := CreateQuota(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) }, } + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) cmdutil.AddGeneratorFlags(cmd, cmdutil.ResourceQuotaV1GeneratorName) cmd.Flags().String("hard", "", i18n.T("A comma-delimited set of resource=quantity pairs that define a hard limit.")) cmd.Flags().String("scopes", "", i18n.T("A comma-delimited set of quota scopes that must all match each object tracked by the quota.")) return cmd } -// CreateQuota implements the behavior to run the create quota command -func CreateQuota(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { +func (o *QuotaOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { return err } + var generator kubectl.StructuredGenerator switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { case cmdutil.ResourceQuotaV1GeneratorName: @@ -80,10 +88,11 @@ func CreateQuota(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args [ default: return errUnsupportedGenerator(cmd, generatorName) } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateQuota implements the behavior to run the create quota command +func (o *QuotaOpts) Run() error { + return o.CreateSubcommandOptions.Run() } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_quota_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_quota_test.go new file mode 100644 index 000000000..c780beafe --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_quota_test.go @@ -0,0 +1,68 @@ +/* +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 create + +import ( + "testing" + + "k8s.io/api/core/v1" + cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +func TestCreateQuota(t *testing.T) { + resourceQuotaObject := &v1.ResourceQuota{} + resourceQuotaObject.Name = "my-quota" + + tests := map[string]struct { + flags []string + expectedOutput string + }{ + "single resource": { + flags: []string{"--hard=cpu=1"}, + expectedOutput: "resourcequota/" + resourceQuotaObject.Name + "\n", + }, + "single resource with a scope": { + flags: []string{"--hard=cpu=1", "--scopes=BestEffort"}, + expectedOutput: "resourcequota/" + resourceQuotaObject.Name + "\n", + }, + "multiple resources": { + flags: []string{"--hard=cpu=1,pods=42", "--scopes=BestEffort"}, + expectedOutput: "resourcequota/" + resourceQuotaObject.Name + "\n", + }, + "single resource with multiple scopes": { + flags: []string{"--hard=cpu=1", "--scopes=BestEffort,NotTerminating"}, + expectedOutput: "resourcequota/" + resourceQuotaObject.Name + "\n", + }, + } + for name, test := range tests { + t.Run(name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateQuota(tf, ioStreams) + cmd.Flags().Parse(test.flags) + cmd.Flags().Set("output", "name") + cmd.Run(cmd, []string{resourceQuotaObject.Name}) + + if buf.String() != test.expectedOutput { + t.Errorf("%s: expected output: %s, but got: %s", name, test.expectedOutput, buf.String()) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_role.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_role.go new file mode 100644 index 000000000..764f2ed15 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_role.go @@ -0,0 +1,378 @@ +/* +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 create + +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" + + rbacv1 "k8s.io/api/rbac/v1" + "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/apimachinery/pkg/util/sets" + clientgorbacv1 "k8s.io/client-go/kubernetes/typed/rbac/v1" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" +) + +var ( + roleLong = templates.LongDesc(i18n.T(` + Create a role with single rule.`)) + + roleExample = templates.Examples(i18n.T(` + # Create a Role named "pod-reader" that allows user to perform "get", "watch" and "list" on pods + kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods + + # Create a Role named "pod-reader" with ResourceName specified + kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod + + # Create a Role named "foo" with API Group specified + kubectl create role foo --verb=get,list,watch --resource=rs.extensions + + # Create a Role named "foo" with SubResource specified + kubectl create role foo --verb=get,list,watch --resource=pods,pods/status`)) + + // Valid resource verb list for validation. + validResourceVerbs = []string{"*", "get", "delete", "list", "create", "update", "patch", "watch", "proxy", "deletecollection", "use", "bind", "impersonate"} + + // Specialized verbs and GroupResources + specialVerbs = map[string][]schema.GroupResource{ + "use": { + { + Group: "extensions", + Resource: "podsecuritypolicies", + }, + }, + "bind": { + { + Group: "rbac.authorization.k8s.io", + Resource: "roles", + }, + { + Group: "rbac.authorization.k8s.io", + Resource: "clusterroles", + }, + }, + "impersonate": { + { + Group: "", + Resource: "users", + }, + { + Group: "", + Resource: "serviceaccounts", + }, + { + Group: "", + Resource: "groups", + }, + { + Group: "authentication.k8s.io", + Resource: "userextras", + }, + }, + } +) + +type ResourceOptions struct { + Group string + Resource string + SubResource string +} + +type CreateRoleOptions struct { + PrintFlags *genericclioptions.PrintFlags + + Name string + Verbs []string + Resources []ResourceOptions + ResourceNames []string + + DryRun bool + OutputFormat string + Namespace string + Client clientgorbacv1.RbacV1Interface + Mapper meta.RESTMapper + PrintObj func(obj runtime.Object) error + + genericclioptions.IOStreams +} + +func NewCreateRoleOptions(ioStreams genericclioptions.IOStreams) *CreateRoleOptions { + return &CreateRoleOptions{ + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), + + IOStreams: ioStreams, + } +} + +// Role is a command to ease creating Roles. +func NewCmdCreateRole(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewCreateRoleOptions(ioStreams) + + cmd := &cobra.Command{ + Use: "role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]", + DisableFlagsInUseLine: true, + Short: roleLong, + Long: roleLong, + Example: roleExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunCreateRole()) + }, + } + + o.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddDryRunFlag(cmd) + cmd.Flags().StringSliceVar(&o.Verbs, "verb", o.Verbs, "Verb that applies to the resources contained in the rule") + cmd.Flags().StringSlice("resource", []string{}, "Resource that the rule applies to") + cmd.Flags().StringArrayVar(&o.ResourceNames, "resource-name", o.ResourceNames, "Resource in the white list that the rule applies to, repeat this flag for multiple items") + + return cmd +} + +func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + o.Name = name + + // Remove duplicate verbs. + verbs := []string{} + for _, v := range o.Verbs { + // VerbAll respresents all kinds of verbs. + if v == "*" { + verbs = []string{"*"} + break + } + if !arrayContains(verbs, v) { + verbs = append(verbs, v) + } + } + o.Verbs = verbs + + // Support resource.group pattern. If no API Group specified, use "" as core API Group. + // e.g. --resource=pods,deployments.extensions + resources := cmdutil.GetFlagStringSlice(cmd, "resource") + for _, r := range resources { + sections := strings.SplitN(r, "/", 2) + + resource := &ResourceOptions{} + if len(sections) == 2 { + resource.SubResource = sections[1] + } + + parts := strings.SplitN(sections[0], ".", 2) + if len(parts) == 2 { + resource.Group = parts[1] + } + resource.Resource = parts[0] + + o.Resources = append(o.Resources, *resource) + } + + // Remove duplicate resource names. + resourceNames := []string{} + for _, n := range o.ResourceNames { + if !arrayContains(resourceNames, n) { + resourceNames = append(resourceNames, n) + } + } + o.ResourceNames = resourceNames + + // Complete other options for Run. + o.Mapper, err = f.ToRESTMapper() + if err != nil { + return err + } + + o.DryRun = cmdutil.GetDryRunFlag(cmd) + o.OutputFormat = cmdutil.GetFlagString(cmd, "output") + + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObj = func(obj runtime.Object) error { + return printer.PrintObj(obj, o.Out) + } + + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + + clientset, err := f.KubernetesClientSet() + if err != nil { + return err + } + o.Client = clientset.RbacV1() + + return nil +} + +func (o *CreateRoleOptions) Validate() error { + if o.Name == "" { + return fmt.Errorf("name must be specified") + } + + // validate verbs. + if len(o.Verbs) == 0 { + return fmt.Errorf("at least one verb must be specified") + } + + for _, v := range o.Verbs { + if !arrayContains(validResourceVerbs, v) { + return fmt.Errorf("invalid verb: '%s'", v) + } + } + + // validate resources. + if len(o.Resources) == 0 { + return fmt.Errorf("at least one resource must be specified") + } + + return o.validateResource() +} + +func (o *CreateRoleOptions) validateResource() error { + for _, r := range o.Resources { + if len(r.Resource) == 0 { + return fmt.Errorf("resource must be specified if apiGroup/subresource specified") + } + + resource := schema.GroupVersionResource{Resource: r.Resource, Group: r.Group} + groupVersionResource, err := o.Mapper.ResourceFor(schema.GroupVersionResource{Resource: r.Resource, Group: r.Group}) + if err == nil { + resource = groupVersionResource + } + + for _, v := range o.Verbs { + if groupResources, ok := specialVerbs[v]; ok { + match := false + for _, extra := range groupResources { + if resource.Resource == extra.Resource && resource.Group == extra.Group { + match = true + err = nil + break + } + } + if !match { + return fmt.Errorf("can not perform '%s' on '%s' in group '%s'", v, resource.Resource, resource.Group) + } + } + } + + if err != nil { + return err + } + } + return nil +} + +func (o *CreateRoleOptions) RunCreateRole() error { + role := &rbacv1.Role{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: rbacv1.SchemeGroupVersion.String(), Kind: "Role"}, + } + role.Name = o.Name + rules, err := generateResourcePolicyRules(o.Mapper, o.Verbs, o.Resources, o.ResourceNames, []string{}) + if err != nil { + return err + } + role.Rules = rules + + // Create role. + if !o.DryRun { + role, err = o.Client.Roles(o.Namespace).Create(role) + if err != nil { + return err + } + } + + return o.PrintObj(role) +} + +func arrayContains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} + +func generateResourcePolicyRules(mapper meta.RESTMapper, verbs []string, resources []ResourceOptions, resourceNames []string, nonResourceURLs []string) ([]rbacv1.PolicyRule, error) { + // groupResourceMapping is a apigroup-resource map. The key of this map is api group, while the value + // is a string array of resources under this api group. + // E.g. groupResourceMapping = {"extensions": ["replicasets", "deployments"], "batch":["jobs"]} + groupResourceMapping := map[string][]string{} + + // This loop does the following work: + // 1. Constructs groupResourceMapping based on input resources. + // 2. Prevents pointing to non-existent resources. + // 3. Transfers resource short name to long name. E.g. rs.extensions is transferred to replicasets.extensions + for _, r := range resources { + resource := schema.GroupVersionResource{Resource: r.Resource, Group: r.Group} + groupVersionResource, err := mapper.ResourceFor(schema.GroupVersionResource{Resource: r.Resource, Group: r.Group}) + if err == nil { + resource = groupVersionResource + } + + if len(r.SubResource) > 0 { + resource.Resource = resource.Resource + "/" + r.SubResource + } + if !arrayContains(groupResourceMapping[resource.Group], resource.Resource) { + groupResourceMapping[resource.Group] = append(groupResourceMapping[resource.Group], resource.Resource) + } + } + + // Create separate rule for each of the api group. + rules := []rbacv1.PolicyRule{} + for _, g := range sets.StringKeySet(groupResourceMapping).List() { + rule := rbacv1.PolicyRule{} + rule.Verbs = verbs + rule.Resources = groupResourceMapping[g] + rule.APIGroups = []string{g} + rule.ResourceNames = resourceNames + rules = append(rules, rule) + } + + if len(nonResourceURLs) > 0 { + rule := rbacv1.PolicyRule{} + rule.Verbs = verbs + rule.NonResourceURLs = nonResourceURLs + rules = append(rules, rule) + } + + return rules, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_role_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_role_test.go similarity index 90% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_role_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_role_test.go index 5ed22e043..506e30333 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_role_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_role_test.go @@ -14,10 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "bytes" "reflect" "testing" @@ -29,15 +28,15 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestCreateRole(t *testing.T) { roleName := "my-role" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() @@ -129,8 +128,8 @@ func TestCreateRole(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateRole(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateRole(tf, ioStreams) cmd.Flags().Set("dry-run", "true") cmd.Flags().Set("output", "yaml") cmd.Flags().Set("verb", test.verbs) @@ -152,11 +151,9 @@ func TestCreateRole(t *testing.T) { } func TestValidate(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" - tests := map[string]struct { roleOptions *CreateRoleOptions expectErr bool @@ -339,8 +336,12 @@ func TestValidate(t *testing.T) { } for name, test := range tests { - test.roleOptions.Mapper, _ = tf.Object() - err := test.roleOptions.Validate() + var err error + test.roleOptions.Mapper, err = tf.ToRESTMapper() + if err != nil { + t.Fatal(err) + } + err = test.roleOptions.Validate() if test.expectErr && err == nil { t.Errorf("%s: expect error happens but validate passes.", name) } @@ -353,15 +354,13 @@ func TestValidate(t *testing.T) { func TestComplete(t *testing.T) { roleName := "my-role" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateRole(tf, buf) + cmd := NewCmdCreateRole(tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("resource", "pods,deployments.extensions") tests := map[string]struct { @@ -371,14 +370,17 @@ func TestComplete(t *testing.T) { expectErr bool }{ "test-missing-name": { - params: []string{}, - roleOptions: &CreateRoleOptions{}, - expectErr: true, + params: []string{}, + roleOptions: &CreateRoleOptions{ + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), + }, + expectErr: true, }, "test-duplicate-verbs": { params: []string{roleName}, roleOptions: &CreateRoleOptions{ - Name: roleName, + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), + Name: roleName, Verbs: []string{ "get", "watch", @@ -410,7 +412,8 @@ func TestComplete(t *testing.T) { "test-verball": { params: []string{roleName}, roleOptions: &CreateRoleOptions{ - Name: roleName, + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), + Name: roleName, Verbs: []string{ "get", "watch", @@ -438,6 +441,7 @@ func TestComplete(t *testing.T) { "test-duplicate-resourcenames": { params: []string{roleName}, roleOptions: &CreateRoleOptions{ + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), Name: roleName, Verbs: []string{"*"}, ResourceNames: []string{"foo", "foo"}, @@ -462,6 +466,7 @@ func TestComplete(t *testing.T) { "test-valid-complete-case": { params: []string{roleName}, roleOptions: &CreateRoleOptions{ + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(legacyscheme.Scheme), Name: roleName, Verbs: []string{"*"}, ResourceNames: []string{"foo"}, diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_rolebinding.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_rolebinding.go similarity index 79% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_rolebinding.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_rolebinding.go index 49eca5706..67566df41 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_rolebinding.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_rolebinding.go @@ -14,16 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -36,8 +35,16 @@ var ( kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1`)) ) +type RoleBindingOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + // RoleBinding is a command to ease creating RoleBindings. -func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateRoleBinding(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &RoleBindingOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + cmd := &cobra.Command{ Use: "rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", DisableFlagsInUseLine: true, @@ -45,13 +52,15 @@ func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command Long: roleBindingLong, Example: roleBindingExample, Run: func(cmd *cobra.Command, args []string) { - err := CreateRoleBinding(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) }, } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) cmdutil.AddGeneratorFlags(cmd, cmdutil.RoleBindingV1GeneratorName) cmd.Flags().String("clusterrole", "", i18n.T("ClusterRole this RoleBinding should reference")) cmd.Flags().String("role", "", i18n.T("Role this RoleBinding should reference")) @@ -61,11 +70,12 @@ func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command return cmd } -func CreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { +func (o *RoleBindingOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { return err } + var generator kubectl.StructuredGenerator switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { case cmdutil.RoleBindingV1GeneratorName: @@ -80,10 +90,10 @@ func CreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, default: return errUnsupportedGenerator(cmd, generatorName) } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +func (o *RoleBindingOpts) Run() error { + return o.CreateSubcommandOptions.Run() } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_rolebinding_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_rolebinding_test.go similarity index 95% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_rolebinding_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_rolebinding_test.go index d227857eb..f9cb82518 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_rolebinding_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_rolebinding_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( "bytes" @@ -32,6 +32,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) var groupVersion = schema.GroupVersion{Group: "rbac.authorization.k8s.io", Version: "v1"} @@ -69,7 +70,7 @@ func TestCreateRoleBinding(t *testing.T) { }, } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -78,7 +79,6 @@ func TestCreateRoleBinding(t *testing.T) { encoder := ns.EncoderForVersion(info.Serializer, groupVersion) decoder := ns.DecoderToVersion(info.Serializer, groupVersion) - tf.Namespace = "test" tf.Client = &RoleBindingRESTClient{ RESTClient: &fake.RESTClient{ NegotiatedSerializer: ns, @@ -112,8 +112,7 @@ func TestCreateRoleBinding(t *testing.T) { }, } - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateRoleBinding(tf, buf) + cmd := NewCmdCreateRoleBinding(tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("role", "fake-role") cmd.Flags().Set("user", "fake-user") cmd.Flags().Set("group", "fake-group") diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_secret.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_secret.go new file mode 100644 index 000000000..700e15bb1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_secret.go @@ -0,0 +1,315 @@ +/* +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 create + +import ( + "github.com/spf13/cobra" + + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" +) + +// NewCmdCreateSecret groups subcommands to create various types of secrets +func NewCmdCreateSecret(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + cmd := &cobra.Command{ + Use: "secret", + Short: i18n.T("Create a secret using specified subcommand"), + Long: "Create a secret using specified subcommand.", + Run: cmdutil.DefaultSubCommandRun(ioStreams.ErrOut), + } + cmd.AddCommand(NewCmdCreateSecretDockerRegistry(f, ioStreams)) + cmd.AddCommand(NewCmdCreateSecretTLS(f, ioStreams)) + cmd.AddCommand(NewCmdCreateSecretGeneric(f, ioStreams)) + + return cmd +} + +var ( + secretLong = templates.LongDesc(i18n.T(` + Create a secret based on a file, directory, or specified literal value. + + A single secret may package one or more key/value pairs. + + When creating a secret based on a file, the key will default to the basename of the file, and the value will + default to the file content. If the basename is an invalid key or you wish to chose your own, you may specify + an alternate key. + + When creating a secret based on a directory, each file whose basename is a valid key in the directory will be + packaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories, + symlinks, devices, pipes, etc).`)) + + secretExample = templates.Examples(i18n.T(` + # Create a new secret named my-secret with keys for each file in folder bar + kubectl create secret generic my-secret --from-file=path/to/bar + + # Create a new secret named my-secret with specified keys instead of names on disk + kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub + + # Create a new secret named my-secret with key1=supersecret and key2=topsecret + kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret + + # Create a new secret named my-secret using a combination of a file and a literal + kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-literal=passphrase=topsecret + + # Create a new secret named my-secret from an env file + kubectl create secret generic my-secret --from-env-file=path/to/bar.env`)) +) + +type SecretGenericOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateSecretGeneric is a command to create generic secrets from files, directories, or literal values +func NewCmdCreateSecretGeneric(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &SecretGenericOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", + DisableFlagsInUseLine: true, + Short: i18n.T("Create a secret from a local file, directory or literal value"), + Long: secretLong, + Example: secretExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretV1GeneratorName) + cmd.Flags().StringSlice("from-file", []string{}, "Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.") + cmd.Flags().StringArray("from-literal", []string{}, "Specify a key and literal value to insert in secret (i.e. mykey=somevalue)") + cmd.Flags().String("from-env-file", "", "Specify the path to a file to read lines of key=val pairs to create a secret (i.e. a Docker .env file).") + cmd.Flags().String("type", "", i18n.T("The type of secret to create")) + cmd.Flags().Bool("append-hash", false, "Append a hash of the secret to its name.") + return cmd +} + +func (o *SecretGenericOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.SecretV1GeneratorName: + generator = &kubectl.SecretGeneratorV1{ + Name: name, + Type: cmdutil.GetFlagString(cmd, "type"), + FileSources: cmdutil.GetFlagStringSlice(cmd, "from-file"), + LiteralSources: cmdutil.GetFlagStringArray(cmd, "from-literal"), + EnvFileSource: cmdutil.GetFlagString(cmd, "from-env-file"), + AppendHash: cmdutil.GetFlagBool(cmd, "append-hash"), + } + default: + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateSecretGeneric is the implementation of the create secret generic command +func (o *SecretGenericOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} + +var ( + secretForDockerRegistryLong = templates.LongDesc(i18n.T(` + Create a new secret for use with Docker registries. + + Dockercfg secrets are used to authenticate against Docker registries. + + When using the Docker command line to push images, you can authenticate to a given registry by running: + '$ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'. + + That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to + authenticate to the registry. The email address is optional. + + When creating applications, you may have a Docker registry that requires authentication. In order for the + nodes to pull images on your behalf, they have to have the credentials. You can provide this information + by creating a dockercfg secret and attaching it to your service account.`)) + + secretForDockerRegistryExample = templates.Examples(i18n.T(` + # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using: + kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL`)) +) + +type SecretDockerRegistryOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries +func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &SecretDockerRegistryOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-literal=key1=value1] [--dry-run]", + DisableFlagsInUseLine: true, + Short: i18n.T("Create a secret for use with a Docker registry"), + Long: secretForDockerRegistryLong, + Example: secretForDockerRegistryExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForDockerRegistryV1GeneratorName) + cmd.Flags().String("docker-username", "", i18n.T("Username for Docker registry authentication")) + cmd.MarkFlagRequired("docker-username") + cmd.Flags().String("docker-password", "", i18n.T("Password for Docker registry authentication")) + cmd.MarkFlagRequired("docker-password") + cmd.Flags().String("docker-email", "", i18n.T("Email for Docker registry")) + cmd.Flags().String("docker-server", "https://index.docker.io/v1/", i18n.T("Server location for Docker registry")) + cmd.Flags().Bool("append-hash", false, "Append a hash of the secret to its name.") + cmd.Flags().StringSlice("from-file", []string{}, "Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.") + + return cmd +} + +func (o *SecretDockerRegistryOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + fromFileFlag := cmdutil.GetFlagStringSlice(cmd, "from-file") + if len(fromFileFlag) == 0 { + requiredFlags := []string{"docker-username", "docker-password", "docker-server"} + for _, requiredFlag := range requiredFlags { + if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 { + return cmdutil.UsageErrorf(cmd, "flag %s is required", requiredFlag) + } + } + } + + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.SecretForDockerRegistryV1GeneratorName: + generator = &kubectl.SecretForDockerRegistryGeneratorV1{ + Name: name, + Username: cmdutil.GetFlagString(cmd, "docker-username"), + Email: cmdutil.GetFlagString(cmd, "docker-email"), + Password: cmdutil.GetFlagString(cmd, "docker-password"), + Server: cmdutil.GetFlagString(cmd, "docker-server"), + AppendHash: cmdutil.GetFlagBool(cmd, "append-hash"), + FileSources: cmdutil.GetFlagStringSlice(cmd, "from-file"), + } + default: + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateSecretDockerRegistry is the implementation of the create secret docker-registry command +func (o *SecretDockerRegistryOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} + +var ( + secretForTLSLong = templates.LongDesc(i18n.T(` + Create a TLS secret from the given public/private key pair. + + The public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match + the given private key.`)) + + secretForTLSExample = templates.Examples(i18n.T(` + # Create a new TLS secret named tls-secret with the given key pair: + kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key`)) +) + +type SecretTLSOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateSecretTLS is a macro command for creating secrets to work with Docker registries +func NewCmdCreateSecretTLS(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &SecretTLSOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run]", + DisableFlagsInUseLine: true, + Short: i18n.T("Create a TLS secret"), + Long: secretForTLSLong, + Example: secretForTLSExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForTLSV1GeneratorName) + cmd.Flags().String("cert", "", i18n.T("Path to PEM encoded public key certificate.")) + cmd.Flags().String("key", "", i18n.T("Path to private key associated with given certificate.")) + cmd.Flags().Bool("append-hash", false, "Append a hash of the secret to its name.") + return cmd +} + +func (o *SecretTLSOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + requiredFlags := []string{"cert", "key"} + for _, requiredFlag := range requiredFlags { + if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 { + return cmdutil.UsageErrorf(cmd, "flag %s is required", requiredFlag) + } + } + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.SecretForTLSV1GeneratorName: + generator = &kubectl.SecretForTLSGeneratorV1{ + Name: name, + Key: cmdutil.GetFlagString(cmd, "key"), + Cert: cmdutil.GetFlagString(cmd, "cert"), + AppendHash: cmdutil.GetFlagBool(cmd, "append-hash"), + } + default: + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateSecretTLS is the implementation of the create secret tls command +func (o *SecretTLSOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_secret_test.go similarity index 83% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_secret_test.go index 1e3f73979..6bdf44759 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_secret_test.go @@ -14,10 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "bytes" "net/http" "testing" @@ -26,6 +25,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -37,10 +37,10 @@ func TestCreateSecretGeneric(t *testing.T) { }, } secretObject.Name = "my-secret" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -56,9 +56,8 @@ func TestCreateSecretGeneric(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateSecretGeneric(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateSecretGeneric(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Flags().Set("from-literal", "password=includes,comma") cmd.Flags().Set("from-literal", "username=test_user") @@ -72,8 +71,8 @@ func TestCreateSecretGeneric(t *testing.T) { func TestCreateSecretDockerRegistry(t *testing.T) { secretObject := &v1.Secret{} secretObject.Name = "my-secret" - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + tf := cmdtesting.NewTestFactory().WithNamespace("test") + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -89,9 +88,8 @@ func TestCreateSecretDockerRegistry(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateSecretDockerRegistry(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateSecretDockerRegistry(tf, ioStreams) cmd.Flags().Set("docker-username", "test-user") cmd.Flags().Set("docker-password", "test-pass") cmd.Flags().Set("docker-email", "test-email") diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_service.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_service.go new file mode 100644 index 000000000..e645138d2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_service.go @@ -0,0 +1,333 @@ +/* +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 create + +import ( + "github.com/spf13/cobra" + + "k8s.io/api/core/v1" + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" +) + +// NewCmdCreateService is a macro command to create a new service +func NewCmdCreateService(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + cmd := &cobra.Command{ + Use: "service", + Aliases: []string{"svc"}, + Short: i18n.T("Create a service using specified subcommand."), + Long: "Create a service using specified subcommand.", + Run: cmdutil.DefaultSubCommandRun(ioStreams.ErrOut), + } + cmd.AddCommand(NewCmdCreateServiceClusterIP(f, ioStreams)) + cmd.AddCommand(NewCmdCreateServiceNodePort(f, ioStreams)) + cmd.AddCommand(NewCmdCreateServiceLoadBalancer(f, ioStreams)) + cmd.AddCommand(NewCmdCreateServiceExternalName(f, ioStreams)) + + return cmd +} + +var ( + serviceClusterIPLong = templates.LongDesc(i18n.T(` + Create a ClusterIP service with the specified name.`)) + + serviceClusterIPExample = templates.Examples(i18n.T(` + # Create a new ClusterIP service named my-cs + kubectl create service clusterip my-cs --tcp=5678:8080 + + # Create a new ClusterIP service named my-cs (in headless mode) + kubectl create service clusterip my-cs --clusterip="None"`)) +) + +func addPortFlags(cmd *cobra.Command) { + cmd.Flags().StringSlice("tcp", []string{}, "Port pairs can be specified as ':'.") +} + +type ServiceClusterIPOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateServiceClusterIP is a command to create a ClusterIP service +func NewCmdCreateServiceClusterIP(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &ServiceClusterIPOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "clusterip NAME [--tcp=:] [--dry-run]", + DisableFlagsInUseLine: true, + Short: i18n.T("Create a ClusterIP service."), + Long: serviceClusterIPLong, + Example: serviceClusterIPExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceClusterIPGeneratorV1Name) + addPortFlags(cmd) + cmd.Flags().String("clusterip", "", i18n.T("Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).")) + return cmd +} + +func errUnsupportedGenerator(cmd *cobra.Command, generatorName string) error { + return cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", generatorName) +} + +func (o *ServiceClusterIPOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.ServiceClusterIPGeneratorV1Name: + generator = &kubectl.ServiceCommonGeneratorV1{ + Name: name, + TCP: cmdutil.GetFlagStringSlice(cmd, "tcp"), + Type: v1.ServiceTypeClusterIP, + ClusterIP: cmdutil.GetFlagString(cmd, "clusterip"), + } + default: + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateServiceClusterIP is the implementation of the create service clusterip command +func (o *ServiceClusterIPOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} + +var ( + serviceNodePortLong = templates.LongDesc(i18n.T(` + Create a NodePort service with the specified name.`)) + + serviceNodePortExample = templates.Examples(i18n.T(` + # Create a new NodePort service named my-ns + kubectl create service nodeport my-ns --tcp=5678:8080`)) +) + +type ServiceNodePortOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateServiceNodePort is a macro command for creating a NodePort service +func NewCmdCreateServiceNodePort(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &ServiceNodePortOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "nodeport NAME [--tcp=port:targetPort] [--dry-run]", + DisableFlagsInUseLine: true, + Short: i18n.T("Create a NodePort service."), + Long: serviceNodePortLong, + Example: serviceNodePortExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceNodePortGeneratorV1Name) + cmd.Flags().Int("node-port", 0, "Port used to expose the service on each node in a cluster.") + addPortFlags(cmd) + return cmd +} + +func (o *ServiceNodePortOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.ServiceNodePortGeneratorV1Name: + generator = &kubectl.ServiceCommonGeneratorV1{ + Name: name, + TCP: cmdutil.GetFlagStringSlice(cmd, "tcp"), + Type: v1.ServiceTypeNodePort, + ClusterIP: "", + NodePort: cmdutil.GetFlagInt(cmd, "node-port"), + } + default: + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateServiceNodePort is the implementation of the create service nodeport command +func (o *ServiceNodePortOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} + +var ( + serviceLoadBalancerLong = templates.LongDesc(i18n.T(` + Create a LoadBalancer service with the specified name.`)) + + serviceLoadBalancerExample = templates.Examples(i18n.T(` + # Create a new LoadBalancer service named my-lbs + kubectl create service loadbalancer my-lbs --tcp=5678:8080`)) +) + +type ServiceLoadBalancerOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateServiceLoadBalancer is a macro command for creating a LoadBalancer service +func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &ServiceLoadBalancerOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "loadbalancer NAME [--tcp=port:targetPort] [--dry-run]", + DisableFlagsInUseLine: true, + Short: i18n.T("Create a LoadBalancer service."), + Long: serviceLoadBalancerLong, + Example: serviceLoadBalancerExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceLoadBalancerGeneratorV1Name) + addPortFlags(cmd) + return cmd +} + +func (o *ServiceLoadBalancerOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.ServiceLoadBalancerGeneratorV1Name: + generator = &kubectl.ServiceCommonGeneratorV1{ + Name: name, + TCP: cmdutil.GetFlagStringSlice(cmd, "tcp"), + Type: v1.ServiceTypeLoadBalancer, + ClusterIP: "", + } + default: + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateServiceLoadBalancer is the implementation of the create service loadbalancer command +func (o *ServiceLoadBalancerOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} + +var ( + serviceExternalNameLong = templates.LongDesc(i18n.T(` + Create an ExternalName service with the specified name. + + ExternalName service references to an external DNS address instead of + only pods, which will allow application authors to reference services + that exist off platform, on other clusters, or locally.`)) + + serviceExternalNameExample = templates.Examples(i18n.T(` + # Create a new ExternalName service named my-ns + kubectl create service externalname my-ns --external-name bar.com`)) +) + +type ServiceExternalNameOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateServiceExternalName is a macro command for creating an ExternalName service +func NewCmdCreateServiceExternalName(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &ServiceExternalNameOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "externalname NAME --external-name external.name [--dry-run]", + DisableFlagsInUseLine: true, + Short: i18n.T("Create an ExternalName service."), + Long: serviceExternalNameLong, + Example: serviceExternalNameExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceExternalNameGeneratorV1Name) + addPortFlags(cmd) + cmd.Flags().String("external-name", "", i18n.T("External name of service")) + cmd.MarkFlagRequired("external-name") + return cmd +} + +func (o *ServiceExternalNameOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.ServiceExternalNameGeneratorV1Name: + generator = &kubectl.ServiceCommonGeneratorV1{ + Name: name, + Type: v1.ServiceTypeExternalName, + ExternalName: cmdutil.GetFlagString(cmd, "external-name"), + ClusterIP: "", + } + default: + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateExternalNameService is the implementation of the create service externalname command +func (o *ServiceExternalNameOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_service_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_service_test.go similarity index 81% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_service_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_service_test.go index 9abd224da..eb6229222 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_service_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_service_test.go @@ -14,10 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "bytes" "net/http" "testing" @@ -26,16 +25,17 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestCreateService(t *testing.T) { service := &v1.Service{} service.Name = "my-service" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) negSer := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -51,9 +51,8 @@ func TestCreateService(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateServiceClusterIP(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateServiceClusterIP(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Flags().Set("tcp", "8080:8000") cmd.Run(cmd, []string{service.Name}) @@ -66,10 +65,10 @@ func TestCreateService(t *testing.T) { func TestCreateServiceNodePort(t *testing.T) { service := &v1.Service{} service.Name = "my-node-port-service" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) negSer := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -85,9 +84,8 @@ func TestCreateServiceNodePort(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateServiceNodePort(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateServiceNodePort(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Flags().Set("tcp", "30000:8000") cmd.Run(cmd, []string{service.Name}) @@ -100,10 +98,10 @@ func TestCreateServiceNodePort(t *testing.T) { func TestCreateServiceExternalName(t *testing.T) { service := &v1.Service{} service.Name = "my-external-name-service" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) negSer := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -119,9 +117,8 @@ func TestCreateServiceExternalName(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateServiceExternalName(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateServiceExternalName(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Flags().Set("external-name", "name") cmd.Run(cmd, []string{service.Name}) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_serviceaccount.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_serviceaccount.go new file mode 100644 index 000000000..0399f8307 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_serviceaccount.go @@ -0,0 +1,89 @@ +/* +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 create + +import ( + "github.com/spf13/cobra" + + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" +) + +var ( + serviceAccountLong = templates.LongDesc(i18n.T(` + Create a service account with the specified name.`)) + + serviceAccountExample = templates.Examples(i18n.T(` + # Create a new service account named my-service-account + kubectl create serviceaccount my-service-account`)) +) + +type ServiceAccountOpts struct { + CreateSubcommandOptions *CreateSubcommandOptions +} + +// NewCmdCreateServiceAccount is a macro command to create a new service account +func NewCmdCreateServiceAccount(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &ServiceAccountOpts{ + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), + } + + cmd := &cobra.Command{ + Use: "serviceaccount NAME [--dry-run]", + DisableFlagsInUseLine: true, + Aliases: []string{"sa"}, + Short: i18n.T("Create a service account with the specified name"), + Long: serviceAccountLong, + Example: serviceAccountExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(f, cmd, args)) + cmdutil.CheckErr(options.Run()) + }, + } + + options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceAccountV1GeneratorName) + return cmd +} + +func (o *ServiceAccountOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.ServiceAccountV1GeneratorName: + generator = &kubectl.ServiceAccountGeneratorV1{Name: name} + default: + return errUnsupportedGenerator(cmd, generatorName) + } + + return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) +} + +// CreateServiceAccount implements the behavior to run the create service account command +func (o *ServiceAccountOpts) Run() error { + return o.CreateSubcommandOptions.Run() +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_serviceaccount_test.go similarity index 84% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_serviceaccount_test.go index 7997ea721..06f9e3564 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_serviceaccount_test.go @@ -14,10 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package create import ( - "bytes" "net/http" "testing" @@ -26,16 +25,17 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestCreateServiceAccount(t *testing.T) { serviceAccountObject := &v1.ServiceAccount{} serviceAccountObject.Name = "my-service-account" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -51,9 +51,8 @@ func TestCreateServiceAccount(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateServiceAccount(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateServiceAccount(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{serviceAccountObject.Name}) expectedOutput := "serviceaccount/" + serviceAccountObject.Name + "\n" diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_test.go new file mode 100644 index 000000000..dba513d8b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create/create_test.go @@ -0,0 +1,210 @@ +/* +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 create + +import ( + "net/http" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" + apitesting "k8s.io/kubernetes/pkg/api/testing" + api "k8s.io/kubernetes/pkg/apis/core" + cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" +) + +func TestExtraArgsFail(t *testing.T) { + initTestErrorHandler(t) + + f := cmdtesting.NewTestFactory() + defer f.Cleanup() + + c := NewCmdCreate(f, genericclioptions.NewTestIOStreamsDiscard()) + options := CreateOptions{} + if options.ValidateArgs(c, []string{"rc"}) == nil { + t.Errorf("unexpected non-error") + } +} + +func TestCreateObject(t *testing.T) { + initTestErrorHandler(t) + _, _, rc := testData() + rc.Items[0].Name = "redis-master-controller" + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Version: "v1"}, + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: + return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreate(tf, ioStreams) + cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") + cmd.Flags().Set("output", "name") + cmd.Run(cmd, []string{}) + + // uses the name from the file, not the response + if buf.String() != "replicationcontroller/redis-master-controller\n" { + t.Errorf("unexpected output: %s", buf.String()) + } +} + +func TestCreateMultipleObject(t *testing.T) { + initTestErrorHandler(t) + _, svc, rc := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Version: "v1"}, + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == "/namespaces/test/services" && m == http.MethodPost: + return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil + case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: + return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreate(tf, ioStreams) + cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") + cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml") + cmd.Flags().Set("output", "name") + cmd.Run(cmd, []string{}) + + // Names should come from the REST response, NOT the files + if buf.String() != "replicationcontroller/rc1\nservice/baz\n" { + t.Errorf("unexpected output: %s", buf.String()) + } +} + +func TestCreateDirectory(t *testing.T) { + initTestErrorHandler(t) + _, _, rc := testData() + rc.Items[0].Name = "name" + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Version: "v1"}, + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: + return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreate(tf, ioStreams) + cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy") + cmd.Flags().Set("output", "name") + cmd.Run(cmd, []string{}) + + if buf.String() != "replicationcontroller/name\nreplicationcontroller/name\nreplicationcontroller/name\n" { + t.Errorf("unexpected output: %s", buf.String()) + } +} + +var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer + +func initTestErrorHandler(t *testing.T) { + cmdutil.BehaviorOnFatal(func(str string, code int) { + t.Errorf("Error running command (exit code %d): %s", code, str) + }) +} + +func testData() (*api.PodList, *api.ServiceList, *api.ReplicationControllerList) { + pods := &api.PodList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "15", + }, + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, + Spec: apitesting.DeepEqualSafePodSpec(), + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"}, + Spec: apitesting.DeepEqualSafePodSpec(), + }, + }, + } + svc := &api.ServiceList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "16", + }, + Items: []api.Service{ + { + ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, + Spec: api.ServiceSpec{ + SessionAffinity: "None", + Type: api.ServiceTypeClusterIP, + }, + }, + }, + } + rc := &api.ReplicationControllerList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "17", + }, + Items: []api.ReplicationController{ + { + ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: "test", ResourceVersion: "18"}, + Spec: api.ReplicationControllerSpec{ + Replicas: 1, + }, + }, + }, + } + return pods, svc, rc +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrole.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrole.go deleted file mode 100644 index 2b1c5440f..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_clusterrole.go +++ /dev/null @@ -1,181 +0,0 @@ -/* -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 cmd - -import ( - "fmt" - "io" - "strings" - - "github.com/spf13/cobra" - - rbacv1 "k8s.io/api/rbac/v1" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" -) - -var ( - clusterRoleLong = templates.LongDesc(i18n.T(` - Create a ClusterRole.`)) - - clusterRoleExample = templates.Examples(i18n.T(` - # Create a ClusterRole named "pod-reader" that allows user to perform "get", "watch" and "list" on pods - kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods - - # Create a ClusterRole named "pod-reader" with ResourceName specified - kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod --resource-name=anotherpod - - # Create a ClusterRole named "foo" with API Group specified - kubectl create clusterrole foo --verb=get,list,watch --resource=rs.extensions - - # Create a ClusterRole named "foo" with SubResource specified - kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status - - # Create a ClusterRole name "foo" with NonResourceURL specified - kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*`)) - - // Valid nonResource verb list for validation. - validNonResourceVerbs = []string{"*", "get", "post", "put", "delete", "patch", "head", "options"} -) - -type CreateClusterRoleOptions struct { - *CreateRoleOptions - NonResourceURLs []string -} - -// ClusterRole is a command to ease creating ClusterRoles. -func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - c := &CreateClusterRoleOptions{ - CreateRoleOptions: &CreateRoleOptions{ - Out: cmdOut, - }, - } - cmd := &cobra.Command{ - Use: "clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]", - DisableFlagsInUseLine: true, - Short: clusterRoleLong, - Long: clusterRoleLong, - Example: clusterRoleExample, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(c.Complete(f, cmd, args)) - cmdutil.CheckErr(c.Validate()) - cmdutil.CheckErr(c.RunCreateRole()) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddDryRunFlag(cmd) - cmd.Flags().StringSliceVar(&c.Verbs, "verb", []string{}, "Verb that applies to the resources contained in the rule") - cmd.Flags().StringSliceVar(&c.NonResourceURLs, "non-resource-url", []string{}, "A partial url that user should have access to.") - cmd.Flags().StringSlice("resource", []string{}, "Resource that the rule applies to") - cmd.Flags().StringArrayVar(&c.ResourceNames, "resource-name", []string{}, "Resource in the white list that the rule applies to, repeat this flag for multiple items") - - return cmd -} - -func (c *CreateClusterRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - // Remove duplicate nonResourceURLs - nonResourceURLs := []string{} - for _, n := range c.NonResourceURLs { - if !arrayContains(nonResourceURLs, n) { - nonResourceURLs = append(nonResourceURLs, n) - } - } - c.NonResourceURLs = nonResourceURLs - - return c.CreateRoleOptions.Complete(f, cmd, args) -} - -func (c *CreateClusterRoleOptions) Validate() error { - if c.Name == "" { - return fmt.Errorf("name must be specified") - } - - // validate verbs. - if len(c.Verbs) == 0 { - return fmt.Errorf("at least one verb must be specified") - } - - if len(c.Resources) == 0 && len(c.NonResourceURLs) == 0 { - return fmt.Errorf("one of resource or nonResourceURL must be specified") - } - - // validate resources - if len(c.Resources) > 0 { - for _, v := range c.Verbs { - if !arrayContains(validResourceVerbs, v) { - return fmt.Errorf("invalid verb: '%s'", v) - } - } - if err := c.validateResource(); err != nil { - return err - } - } - - //validate non-resource-url - if len(c.NonResourceURLs) > 0 { - for _, v := range c.Verbs { - if !arrayContains(validNonResourceVerbs, v) { - return fmt.Errorf("invalid verb: '%s' for nonResourceURL", v) - } - } - - for _, nonResourceURL := range c.NonResourceURLs { - if nonResourceURL == "*" { - continue - } - - if nonResourceURL == "" || !strings.HasPrefix(nonResourceURL, "/") { - return fmt.Errorf("nonResourceURL should start with /") - } - - if strings.ContainsRune(nonResourceURL[:len(nonResourceURL)-1], '*') { - return fmt.Errorf("nonResourceURL only supports wildcard matches when '*' is at the end") - } - } - } - - return nil - -} - -func (c *CreateClusterRoleOptions) RunCreateRole() error { - clusterRole := &rbacv1.ClusterRole{} - clusterRole.Name = c.Name - rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames, c.NonResourceURLs) - if err != nil { - return err - } - clusterRole.Rules = rules - - // Create ClusterRole. - if !c.DryRun { - _, err = c.Client.ClusterRoles().Create(clusterRole) - if err != nil { - return err - } - } - - if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 { - cmdutil.PrintSuccess(useShortOutput, c.Out, clusterRole, c.DryRun, "created") - return nil - } - - return c.PrintObject(clusterRole) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_deployment.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_deployment.go deleted file mode 100644 index cde03d1b7..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_deployment.go +++ /dev/null @@ -1,134 +0,0 @@ -/* -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 cmd - -import ( - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" -) - -var ( - deploymentLong = templates.LongDesc(i18n.T(` - Create a deployment with the specified name.`)) - - deploymentExample = templates.Examples(i18n.T(` - # Create a new deployment named my-dep that runs the busybox image. - kubectl create deployment my-dep --image=busybox`)) -) - -// NewCmdCreateDeployment is a macro command to create a new deployment. -// This command is better known to users as `kubectl create deployment`. -// Note that this command overlaps significantly with the `kubectl run` command. -func NewCmdCreateDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "deployment NAME --image=image [--dry-run]", - DisableFlagsInUseLine: true, - Aliases: []string{"deploy"}, - Short: i18n.T("Create a deployment with the specified name."), - Long: deploymentLong, - Example: deploymentExample, - Run: func(cmd *cobra.Command, args []string) { - err := createDeployment(f, cmdOut, cmdErr, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.DeploymentBasicV1Beta1GeneratorName) - cmd.Flags().StringSlice("image", []string{}, "Image name to run.") - cmd.MarkFlagRequired("image") - return cmd -} - -// generatorFromName returns the appropriate StructuredGenerator based on the -// generatorName. If the generatorName is unrecognized, then return (nil, -// false). -func generatorFromName( - generatorName string, - imageNames []string, - deploymentName string, -) (kubectl.StructuredGenerator, bool) { - - switch generatorName { - case cmdutil.DeploymentBasicAppsV1Beta1GeneratorName: - generator := &kubectl.DeploymentBasicAppsGeneratorV1{ - BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ - Name: deploymentName, - Images: imageNames, - }, - } - return generator, true - - case cmdutil.DeploymentBasicV1Beta1GeneratorName: - generator := &kubectl.DeploymentBasicGeneratorV1{ - BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ - Name: deploymentName, - Images: imageNames, - }, - } - return generator, true - } - - return nil, false -} - -// createDeployment -// 1. Reads user config values from Cobra. -// 2. Sets up the correct Generator object. -// 3. Calls RunCreateSubcommand. -func createDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer, - cmd *cobra.Command, args []string) error { - - deploymentName, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - - clientset, err := f.ClientSet() - if err != nil { - return err - } - - generatorName := cmdutil.GetFlagString(cmd, "generator") - - // It is possible we have to modify the user-provided generator name if - // the server does not have support for the requested generator. - generatorName, err = cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), cmdErr) - if err != nil { - return err - } - - imageNames := cmdutil.GetFlagStringSlice(cmd, "image") - generator, ok := generatorFromName(generatorName, imageNames, deploymentName) - if !ok { - return errUnsupportedGenerator(cmd, generatorName) - } - - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: deploymentName, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_deployment_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_deployment_test.go deleted file mode 100644 index 26b7c414c..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_deployment_test.go +++ /dev/null @@ -1,131 +0,0 @@ -/* -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 cmd - -import ( - "bytes" - "io/ioutil" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/kubectl" - cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -func Test_generatorFromName(t *testing.T) { - const ( - nonsenseName = "not-a-real-generator-name" - basicName = cmdutil.DeploymentBasicV1Beta1GeneratorName - basicAppsName = cmdutil.DeploymentBasicAppsV1Beta1GeneratorName - deploymentName = "deployment-name" - ) - imageNames := []string{"image-1", "image-2"} - - generator, ok := generatorFromName(nonsenseName, imageNames, deploymentName) - assert.Nil(t, generator) - assert.False(t, ok) - - generator, ok = generatorFromName(basicName, imageNames, deploymentName) - assert.True(t, ok) - - { - expectedGenerator := &kubectl.DeploymentBasicGeneratorV1{ - BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ - Name: deploymentName, - Images: imageNames, - }, - } - assert.Equal(t, expectedGenerator, generator) - } - - generator, ok = generatorFromName(basicAppsName, imageNames, deploymentName) - assert.True(t, ok) - - { - expectedGenerator := &kubectl.DeploymentBasicAppsGeneratorV1{ - BaseDeploymentGenerator: kubectl.BaseDeploymentGenerator{ - Name: deploymentName, - Images: imageNames, - }, - } - assert.Equal(t, expectedGenerator, generator) - } -} - -func TestCreateDeployment(t *testing.T) { - depName := "jonny-dep" - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(bytes.NewBuffer([]byte("{}"))), - }, nil - }), - } - tf.ClientConfigVal = &restclient.Config{} - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdCreateDeployment(tf, buf, buf) - cmd.Flags().Set("dry-run", "true") - cmd.Flags().Set("output", "name") - cmd.Flags().Set("image", "hollywood/jonny.depp:v2") - cmd.Run(cmd, []string{depName}) - expectedOutput := "deployment.extensions/" + depName + "\n" - if buf.String() != expectedOutput { - t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) - } -} - -func TestCreateDeploymentNoImage(t *testing.T) { - depName := "jonny-dep" - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(&bytes.Buffer{}), - }, nil - }), - } - tf.ClientConfigVal = &restclient.Config{} - tf.Namespace = "test" - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateDeployment(tf, buf, buf) - cmd.Flags().Set("dry-run", "true") - cmd.Flags().Set("output", "name") - err := createDeployment(tf, buf, buf, cmd, []string{depName}) - assert.Error(t, err, "at least one image must be specified") -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_job.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_job.go deleted file mode 100644 index 382ca5c34..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_job.go +++ /dev/null @@ -1,146 +0,0 @@ -/* -Copyright 2018 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 cmd - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - - batchv1 "k8s.io/api/batch/v1" - batchv1beta1 "k8s.io/api/batch/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - clientbatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" -) - -var ( - jobLong = templates.LongDesc(i18n.T(` - Create a job with the specified name.`)) - - jobExample = templates.Examples(i18n.T(` - # Create a job from a CronJob named "a-cronjob" - kubectl create job --from=cronjob/a-cronjob`)) -) - -type CreateJobOptions struct { - Name string - From string - - Namespace string - Client clientbatchv1.BatchV1Interface - Out io.Writer - DryRun bool - Builder *resource.Builder - Cmd *cobra.Command -} - -// NewCmdCreateJob is a command to ease creating Jobs from CronJobs. -func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - c := &CreateJobOptions{ - Out: cmdOut, - } - cmd := &cobra.Command{ - Use: "job NAME [--from-cronjob=CRONJOB]", - Short: jobLong, - Long: jobLong, - Example: jobExample, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(c.Complete(f, cmd, args)) - cmdutil.CheckErr(c.RunCreateJob()) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().String("from", "", "The name of the resource to create a Job from (only cronjob is supported).") - - return cmd -} - -func (c *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) (err error) { - if len(args) == 0 { - return cmdutil.UsageErrorf(cmd, "NAME is required") - } - c.Name = args[0] - - c.From = cmdutil.GetFlagString(cmd, "from") - c.Namespace, _, err = f.DefaultNamespace() - if err != nil { - return err - } - - clientset, err := f.KubernetesClientSet() - if err != nil { - return err - } - c.Client = clientset.BatchV1() - c.Builder = f.NewBuilder() - c.Cmd = cmd - - return nil -} - -func (c *CreateJobOptions) RunCreateJob() error { - infos, err := c.Builder. - Unstructured(). - NamespaceParam(c.Namespace).DefaultNamespace(). - ResourceTypeOrNameArgs(false, c.From). - Flatten(). - Latest(). - Do(). - Infos() - if err != nil { - return err - } - if len(infos) != 1 { - return fmt.Errorf("from must be an existing cronjob") - } - cronJob, ok := infos[0].AsVersioned().(*batchv1beta1.CronJob) - if !ok { - return fmt.Errorf("from must be an existing cronjob") - } - - return c.createJob(cronJob) -} - -func (c *CreateJobOptions) createJob(cronJob *batchv1beta1.CronJob) error { - annotations := make(map[string]string) - annotations["cronjob.kubernetes.io/instantiate"] = "manual" - for k, v := range cronJob.Spec.JobTemplate.Annotations { - annotations[k] = v - } - jobToCreate := &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: c.Name, - Namespace: c.Namespace, - Annotations: annotations, - Labels: cronJob.Spec.JobTemplate.Labels, - }, - Spec: cronJob.Spec.JobTemplate.Spec, - } - - job, err := c.Client.Jobs(c.Namespace).Create(jobToCreate) - if err != nil { - return fmt.Errorf("failed to create job: %v", err) - } - return cmdutil.PrintObject(c.Cmd, job, c.Out) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace.go deleted file mode 100644 index 7a0f2ec32..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace.go +++ /dev/null @@ -1,80 +0,0 @@ -/* -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 cmd - -import ( - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" -) - -var ( - namespaceLong = templates.LongDesc(i18n.T(` - Create a namespace with the specified name.`)) - - namespaceExample = templates.Examples(i18n.T(` - # Create a new namespace named my-namespace - kubectl create namespace my-namespace`)) -) - -// NewCmdCreateNamespace is a macro command to create a new namespace -func NewCmdCreateNamespace(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "namespace NAME [--dry-run]", - DisableFlagsInUseLine: true, - Aliases: []string{"ns"}, - Short: i18n.T("Create a namespace with the specified name"), - Long: namespaceLong, - Example: namespaceExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateNamespace(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.NamespaceV1GeneratorName) - - return cmd -} - -// CreateNamespace implements the behavior to run the create namespace command -func CreateNamespace(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.NamespaceV1GeneratorName: - generator = &kubectl.NamespaceGeneratorV1{Name: name} - default: - return errUnsupportedGenerator(cmd, generatorName) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_pdb_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_pdb_test.go deleted file mode 100644 index 2fb0956a4..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_pdb_test.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -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 cmd - -import ( - "bytes" - "io/ioutil" - "net/http" - "testing" - - "k8s.io/apimachinery/pkg/runtime/schema" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" - cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" -) - -func TestCreatePdb(t *testing.T) { - pdbName := "my-pdb" - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Group: "policy", Version: "v1beta1"}, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(&bytes.Buffer{}), - }, nil - }), - } - tf.ClientConfigVal = &restclient.Config{} - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdCreatePodDisruptionBudget(tf, buf) - cmd.Flags().Set("min-available", "1") - cmd.Flags().Set("selector", "app=rails") - cmd.Flags().Set("dry-run", "true") - cmd.Flags().Set("output", "name") - CreatePodDisruptionBudget(tf, buf, cmd, []string{pdbName}) - expectedOutput := "poddisruptionbudget.policy/" + pdbName + "\n" - if buf.String() != expectedOutput { - t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_priorityclass_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_priorityclass_test.go deleted file mode 100644 index 92f51774a..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_priorityclass_test.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -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 cmd - -import ( - "bytes" - "io/ioutil" - "net/http" - "testing" - - "k8s.io/apimachinery/pkg/runtime/schema" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" - cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" -) - -func TestCreatePriorityClass(t *testing.T) { - pcName := "my-pc" - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Group: "scheduling.k8s.io", Version: "v1alpha1"}, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(&bytes.Buffer{}), - }, nil - }), - } - tf.ClientConfigVal = &restclient.Config{} - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdCreatePriorityClass(tf, buf) - cmd.Flags().Set("value", "1000") - cmd.Flags().Set("global-default", "true") - cmd.Flags().Set("description", "my priority") - cmd.Flags().Set("dry-run", "true") - cmd.Flags().Set("output", "name") - CreatePriorityClass(tf, buf, cmd, []string{pcName}) - expectedOutput := "priorityclass.scheduling.k8s.io/" + pcName + "\n" - if buf.String() != expectedOutput { - t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_quota_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_quota_test.go deleted file mode 100644 index 618ff3617..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_quota_test.go +++ /dev/null @@ -1,88 +0,0 @@ -/* -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 cmd - -import ( - "bytes" - "net/http" - "testing" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" - cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - "k8s.io/kubernetes/pkg/kubectl/scheme" -) - -func TestCreateQuota(t *testing.T) { - resourceQuotaObject := &v1.ResourceQuota{} - resourceQuotaObject.Name = "my-quota" - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/resourcequotas" && m == "POST": - return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, resourceQuotaObject)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - - tests := map[string]struct { - flags []string - expectedOutput string - }{ - "single resource": { - flags: []string{"--hard=cpu=1"}, - expectedOutput: "resourcequota/" + resourceQuotaObject.Name + "\n", - }, - "single resource with a scope": { - flags: []string{"--hard=cpu=1", "--scopes=BestEffort"}, - expectedOutput: "resourcequota/" + resourceQuotaObject.Name + "\n", - }, - "multiple resources": { - flags: []string{"--hard=cpu=1,pods=42", "--scopes=BestEffort"}, - expectedOutput: "resourcequota/" + resourceQuotaObject.Name + "\n", - }, - "single resource with multiple scopes": { - flags: []string{"--hard=cpu=1", "--scopes=BestEffort,NotTerminating"}, - expectedOutput: "resourcequota/" + resourceQuotaObject.Name + "\n", - }, - } - for name, test := range tests { - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateQuota(tf, buf) - cmd.Flags().Parse(test.flags) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{resourceQuotaObject.Name}) - - if buf.String() != test.expectedOutput { - t.Errorf("%s: expected output: %s, but got: %s", name, test.expectedOutput, buf.String()) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_role.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_role.go deleted file mode 100644 index 2191fc742..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_role.go +++ /dev/null @@ -1,356 +0,0 @@ -/* -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 cmd - -import ( - "fmt" - "io" - "strings" - - "github.com/spf13/cobra" - - rbacv1 "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/sets" - clientgorbacv1 "k8s.io/client-go/kubernetes/typed/rbac/v1" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" -) - -var ( - roleLong = templates.LongDesc(i18n.T(` - Create a role with single rule.`)) - - roleExample = templates.Examples(i18n.T(` - # Create a Role named "pod-reader" that allows user to perform "get", "watch" and "list" on pods - kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods - - # Create a Role named "pod-reader" with ResourceName specified - kubectl create role pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod --resource-name=anotherpod - - # Create a Role named "foo" with API Group specified - kubectl create role foo --verb=get,list,watch --resource=rs.extensions - - # Create a Role named "foo" with SubResource specified - kubectl create role foo --verb=get,list,watch --resource=pods,pods/status`)) - - // Valid resource verb list for validation. - validResourceVerbs = []string{"*", "get", "delete", "list", "create", "update", "patch", "watch", "proxy", "deletecollection", "use", "bind", "impersonate"} - - // Specialized verbs and GroupResources - specialVerbs = map[string][]schema.GroupResource{ - "use": { - { - Group: "extensions", - Resource: "podsecuritypolicies", - }, - }, - "bind": { - { - Group: "rbac.authorization.k8s.io", - Resource: "roles", - }, - { - Group: "rbac.authorization.k8s.io", - Resource: "clusterroles", - }, - }, - "impersonate": { - { - Group: "", - Resource: "users", - }, - { - Group: "", - Resource: "serviceaccounts", - }, - { - Group: "", - Resource: "groups", - }, - { - Group: "authentication.k8s.io", - Resource: "userextras", - }, - }, - } -) - -type ResourceOptions struct { - Group string - Resource string - SubResource string -} - -type CreateRoleOptions struct { - Name string - Verbs []string - Resources []ResourceOptions - ResourceNames []string - - DryRun bool - OutputFormat string - Namespace string - Client clientgorbacv1.RbacV1Interface - Mapper meta.RESTMapper - Out io.Writer - PrintObject func(obj runtime.Object) error -} - -// Role is a command to ease creating Roles. -func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - c := &CreateRoleOptions{ - Out: cmdOut, - } - cmd := &cobra.Command{ - Use: "role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]", - DisableFlagsInUseLine: true, - Short: roleLong, - Long: roleLong, - Example: roleExample, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(c.Complete(f, cmd, args)) - cmdutil.CheckErr(c.Validate()) - cmdutil.CheckErr(c.RunCreateRole()) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddDryRunFlag(cmd) - cmd.Flags().StringSliceVar(&c.Verbs, "verb", []string{}, "Verb that applies to the resources contained in the rule") - cmd.Flags().StringSlice("resource", []string{}, "Resource that the rule applies to") - cmd.Flags().StringArrayVar(&c.ResourceNames, "resource-name", []string{}, "Resource in the white list that the rule applies to, repeat this flag for multiple items") - - return cmd -} - -func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - c.Name = name - - // Remove duplicate verbs. - verbs := []string{} - for _, v := range c.Verbs { - // VerbAll respresents all kinds of verbs. - if v == "*" { - verbs = []string{"*"} - break - } - if !arrayContains(verbs, v) { - verbs = append(verbs, v) - } - } - c.Verbs = verbs - - // Support resource.group pattern. If no API Group specified, use "" as core API Group. - // e.g. --resource=pods,deployments.extensions - resources := cmdutil.GetFlagStringSlice(cmd, "resource") - for _, r := range resources { - sections := strings.SplitN(r, "/", 2) - - resource := &ResourceOptions{} - if len(sections) == 2 { - resource.SubResource = sections[1] - } - - parts := strings.SplitN(sections[0], ".", 2) - if len(parts) == 2 { - resource.Group = parts[1] - } - resource.Resource = parts[0] - - c.Resources = append(c.Resources, *resource) - } - - // Remove duplicate resource names. - resourceNames := []string{} - for _, n := range c.ResourceNames { - if !arrayContains(resourceNames, n) { - resourceNames = append(resourceNames, n) - } - } - c.ResourceNames = resourceNames - - // Complete other options for Run. - c.Mapper, _ = f.Object() - - c.DryRun = cmdutil.GetDryRunFlag(cmd) - c.OutputFormat = cmdutil.GetFlagString(cmd, "output") - - c.Namespace, _, err = f.DefaultNamespace() - if err != nil { - return err - } - - c.PrintObject = func(obj runtime.Object) error { - return cmdutil.PrintObject(cmd, obj, c.Out) - } - - clientset, err := f.KubernetesClientSet() - if err != nil { - return err - } - c.Client = clientset.RbacV1() - - return nil -} - -func (c *CreateRoleOptions) Validate() error { - if c.Name == "" { - return fmt.Errorf("name must be specified") - } - - // validate verbs. - if len(c.Verbs) == 0 { - return fmt.Errorf("at least one verb must be specified") - } - - for _, v := range c.Verbs { - if !arrayContains(validResourceVerbs, v) { - return fmt.Errorf("invalid verb: '%s'", v) - } - } - - // validate resources. - if len(c.Resources) == 0 { - return fmt.Errorf("at least one resource must be specified") - } - - return c.validateResource() -} - -func (c *CreateRoleOptions) validateResource() error { - for _, r := range c.Resources { - if len(r.Resource) == 0 { - return fmt.Errorf("resource must be specified if apiGroup/subresource specified") - } - - resource := schema.GroupVersionResource{Resource: r.Resource, Group: r.Group} - groupVersionResource, err := c.Mapper.ResourceFor(schema.GroupVersionResource{Resource: r.Resource, Group: r.Group}) - if err == nil { - resource = groupVersionResource - } - - for _, v := range c.Verbs { - if groupResources, ok := specialVerbs[v]; ok { - match := false - for _, extra := range groupResources { - if resource.Resource == extra.Resource && resource.Group == extra.Group { - match = true - err = nil - break - } - } - if !match { - return fmt.Errorf("can not perform '%s' on '%s' in group '%s'", v, resource.Resource, resource.Group) - } - } - } - - if err != nil { - return err - } - } - return nil -} - -func (c *CreateRoleOptions) RunCreateRole() error { - role := &rbacv1.Role{} - role.Name = c.Name - rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames, []string{}) - if err != nil { - return err - } - role.Rules = rules - - // Create role. - if !c.DryRun { - _, err = c.Client.Roles(c.Namespace).Create(role) - if err != nil { - return err - } - } - - if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 { - cmdutil.PrintSuccess(useShortOutput, c.Out, role, c.DryRun, "created") - return nil - } - - return c.PrintObject(role) -} - -func arrayContains(s []string, e string) bool { - for _, a := range s { - if a == e { - return true - } - } - return false -} - -func generateResourcePolicyRules(mapper meta.RESTMapper, verbs []string, resources []ResourceOptions, resourceNames []string, nonResourceURLs []string) ([]rbacv1.PolicyRule, error) { - // groupResourceMapping is a apigroup-resource map. The key of this map is api group, while the value - // is a string array of resources under this api group. - // E.g. groupResourceMapping = {"extensions": ["replicasets", "deployments"], "batch":["jobs"]} - groupResourceMapping := map[string][]string{} - - // This loop does the following work: - // 1. Constructs groupResourceMapping based on input resources. - // 2. Prevents pointing to non-existent resources. - // 3. Transfers resource short name to long name. E.g. rs.extensions is transferred to replicasets.extensions - for _, r := range resources { - resource := schema.GroupVersionResource{Resource: r.Resource, Group: r.Group} - groupVersionResource, err := mapper.ResourceFor(schema.GroupVersionResource{Resource: r.Resource, Group: r.Group}) - if err == nil { - resource = groupVersionResource - } - - if len(r.SubResource) > 0 { - resource.Resource = resource.Resource + "/" + r.SubResource - } - if !arrayContains(groupResourceMapping[resource.Group], resource.Resource) { - groupResourceMapping[resource.Group] = append(groupResourceMapping[resource.Group], resource.Resource) - } - } - - // Create separate rule for each of the api group. - rules := []rbacv1.PolicyRule{} - for _, g := range sets.StringKeySet(groupResourceMapping).List() { - rule := rbacv1.PolicyRule{} - rule.Verbs = verbs - rule.Resources = groupResourceMapping[g] - rule.APIGroups = []string{g} - rule.ResourceNames = resourceNames - rules = append(rules, rule) - } - - if len(nonResourceURLs) > 0 { - rule := rbacv1.PolicyRule{} - rule.Verbs = verbs - rule.NonResourceURLs = nonResourceURLs - rules = append(rules, rule) - } - - return rules, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret.go deleted file mode 100644 index 7cfa13d46..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret.go +++ /dev/null @@ -1,278 +0,0 @@ -/* -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 cmd - -import ( - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" -) - -// NewCmdCreateSecret groups subcommands to create various types of secrets -func NewCmdCreateSecret(f cmdutil.Factory, cmdOut, errOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "secret", - Short: i18n.T("Create a secret using specified subcommand"), - Long: "Create a secret using specified subcommand.", - Run: cmdutil.DefaultSubCommandRun(errOut), - } - cmd.AddCommand(NewCmdCreateSecretDockerRegistry(f, cmdOut)) - cmd.AddCommand(NewCmdCreateSecretTLS(f, cmdOut)) - cmd.AddCommand(NewCmdCreateSecretGeneric(f, cmdOut)) - - return cmd -} - -var ( - secretLong = templates.LongDesc(i18n.T(` - Create a secret based on a file, directory, or specified literal value. - - A single secret may package one or more key/value pairs. - - When creating a secret based on a file, the key will default to the basename of the file, and the value will - default to the file content. If the basename is an invalid key or you wish to chose your own, you may specify - an alternate key. - - When creating a secret based on a directory, each file whose basename is a valid key in the directory will be - packaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories, - symlinks, devices, pipes, etc).`)) - - secretExample = templates.Examples(i18n.T(` - # Create a new secret named my-secret with keys for each file in folder bar - kubectl create secret generic my-secret --from-file=path/to/bar - - # Create a new secret named my-secret with specified keys instead of names on disk - kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub - - # Create a new secret named my-secret with key1=supersecret and key2=topsecret - kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret - - # Create a new secret named my-secret using a combination of a file and a literal - kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-literal=passphrase=topsecret - - # Create a new secret named my-secret from an env file - kubectl create secret generic my-secret --from-env-file=path/to/bar.env`)) -) - -// NewCmdCreateSecretGeneric is a command to create generic secrets from files, directories, or literal values -func NewCmdCreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", - DisableFlagsInUseLine: true, - Short: i18n.T("Create a secret from a local file, directory or literal value"), - Long: secretLong, - Example: secretExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateSecretGeneric(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretV1GeneratorName) - cmd.Flags().StringSlice("from-file", []string{}, "Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.") - cmd.Flags().StringArray("from-literal", []string{}, "Specify a key and literal value to insert in secret (i.e. mykey=somevalue)") - cmd.Flags().String("from-env-file", "", "Specify the path to a file to read lines of key=val pairs to create a secret (i.e. a Docker .env file).") - cmd.Flags().String("type", "", i18n.T("The type of secret to create")) - cmd.Flags().Bool("append-hash", false, "Append a hash of the secret to its name.") - return cmd -} - -// CreateSecretGeneric is the implementation of the create secret generic command -func CreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.SecretV1GeneratorName: - generator = &kubectl.SecretGeneratorV1{ - Name: name, - Type: cmdutil.GetFlagString(cmd, "type"), - FileSources: cmdutil.GetFlagStringSlice(cmd, "from-file"), - LiteralSources: cmdutil.GetFlagStringArray(cmd, "from-literal"), - EnvFileSource: cmdutil.GetFlagString(cmd, "from-env-file"), - AppendHash: cmdutil.GetFlagBool(cmd, "append-hash"), - } - default: - return errUnsupportedGenerator(cmd, generatorName) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} - -var ( - secretForDockerRegistryLong = templates.LongDesc(i18n.T(` - Create a new secret for use with Docker registries. - - Dockercfg secrets are used to authenticate against Docker registries. - - When using the Docker command line to push images, you can authenticate to a given registry by running: - '$ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'. - - That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to - authenticate to the registry. The email address is optional. - - When creating applications, you may have a Docker registry that requires authentication. In order for the - nodes to pull images on your behalf, they have to have the credentials. You can provide this information - by creating a dockercfg secret and attaching it to your service account.`)) - - secretForDockerRegistryExample = templates.Examples(i18n.T(` - # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using: - kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL`)) -) - -// NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries -func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-literal=key1=value1] [--dry-run]", - DisableFlagsInUseLine: true, - Short: i18n.T("Create a secret for use with a Docker registry"), - Long: secretForDockerRegistryLong, - Example: secretForDockerRegistryExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateSecretDockerRegistry(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForDockerRegistryV1GeneratorName) - cmd.Flags().String("docker-username", "", i18n.T("Username for Docker registry authentication")) - cmd.MarkFlagRequired("docker-username") - cmd.Flags().String("docker-password", "", i18n.T("Password for Docker registry authentication")) - cmd.MarkFlagRequired("docker-password") - cmd.Flags().String("docker-email", "", i18n.T("Email for Docker registry")) - cmd.Flags().String("docker-server", "https://index.docker.io/v1/", i18n.T("Server location for Docker registry")) - cmd.Flags().Bool("append-hash", false, "Append a hash of the secret to its name.") - - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -// CreateSecretDockerRegistry is the implementation of the create secret docker-registry command -func CreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - requiredFlags := []string{"docker-username", "docker-password", "docker-email", "docker-server"} - for _, requiredFlag := range requiredFlags { - if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 { - return cmdutil.UsageErrorf(cmd, "flag %s is required", requiredFlag) - } - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.SecretForDockerRegistryV1GeneratorName: - generator = &kubectl.SecretForDockerRegistryGeneratorV1{ - Name: name, - Username: cmdutil.GetFlagString(cmd, "docker-username"), - Email: cmdutil.GetFlagString(cmd, "docker-email"), - Password: cmdutil.GetFlagString(cmd, "docker-password"), - Server: cmdutil.GetFlagString(cmd, "docker-server"), - AppendHash: cmdutil.GetFlagBool(cmd, "append-hash"), - } - default: - return errUnsupportedGenerator(cmd, generatorName) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} - -var ( - secretForTLSLong = templates.LongDesc(i18n.T(` - Create a TLS secret from the given public/private key pair. - - The public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match - the given private key.`)) - - secretForTLSExample = templates.Examples(i18n.T(` - # Create a new TLS secret named tls-secret with the given key pair: - kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key`)) -) - -// NewCmdCreateSecretTLS is a macro command for creating secrets to work with Docker registries -func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run]", - DisableFlagsInUseLine: true, - Short: i18n.T("Create a TLS secret"), - Long: secretForTLSLong, - Example: secretForTLSExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateSecretTLS(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForTLSV1GeneratorName) - cmd.Flags().String("cert", "", i18n.T("Path to PEM encoded public key certificate.")) - cmd.Flags().String("key", "", i18n.T("Path to private key associated with given certificate.")) - cmd.Flags().Bool("append-hash", false, "Append a hash of the secret to its name.") - return cmd -} - -// CreateSecretTLS is the implementation of the create secret tls command -func CreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - requiredFlags := []string{"cert", "key"} - for _, requiredFlag := range requiredFlags { - if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 { - return cmdutil.UsageErrorf(cmd, "flag %s is required", requiredFlag) - } - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.SecretForTLSV1GeneratorName: - generator = &kubectl.SecretForTLSGeneratorV1{ - Name: name, - Key: cmdutil.GetFlagString(cmd, "key"), - Cert: cmdutil.GetFlagString(cmd, "cert"), - AppendHash: cmdutil.GetFlagBool(cmd, "append-hash"), - } - default: - return errUnsupportedGenerator(cmd, generatorName) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_service.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_service.go deleted file mode 100644 index 72437b350..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_service.go +++ /dev/null @@ -1,290 +0,0 @@ -/* -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 cmd - -import ( - "io" - - "github.com/spf13/cobra" - - "k8s.io/api/core/v1" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" -) - -// NewCmdCreateService is a macro command to create a new service -func NewCmdCreateService(f cmdutil.Factory, cmdOut, errOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "service", - Aliases: []string{"svc"}, - Short: i18n.T("Create a service using specified subcommand."), - Long: "Create a service using specified subcommand.", - Run: cmdutil.DefaultSubCommandRun(errOut), - } - cmd.AddCommand(NewCmdCreateServiceClusterIP(f, cmdOut)) - cmd.AddCommand(NewCmdCreateServiceNodePort(f, cmdOut)) - cmd.AddCommand(NewCmdCreateServiceLoadBalancer(f, cmdOut)) - cmd.AddCommand(NewCmdCreateServiceExternalName(f, cmdOut)) - - return cmd -} - -var ( - serviceClusterIPLong = templates.LongDesc(i18n.T(` - Create a ClusterIP service with the specified name.`)) - - serviceClusterIPExample = templates.Examples(i18n.T(` - # Create a new ClusterIP service named my-cs - kubectl create service clusterip my-cs --tcp=5678:8080 - - # Create a new ClusterIP service named my-cs (in headless mode) - kubectl create service clusterip my-cs --clusterip="None"`)) -) - -func addPortFlags(cmd *cobra.Command) { - cmd.Flags().StringSlice("tcp", []string{}, "Port pairs can be specified as ':'.") -} - -// NewCmdCreateServiceClusterIP is a command to create a ClusterIP service -func NewCmdCreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "clusterip NAME [--tcp=:] [--dry-run]", - DisableFlagsInUseLine: true, - Short: i18n.T("Create a ClusterIP service."), - Long: serviceClusterIPLong, - Example: serviceClusterIPExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateServiceClusterIP(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceClusterIPGeneratorV1Name) - addPortFlags(cmd) - cmd.Flags().String("clusterip", "", i18n.T("Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).")) - return cmd -} - -func errUnsupportedGenerator(cmd *cobra.Command, generatorName string) error { - return cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", generatorName) -} - -// CreateServiceClusterIP is the implementation of the create service clusterip command -func CreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.ServiceClusterIPGeneratorV1Name: - generator = &kubectl.ServiceCommonGeneratorV1{ - Name: name, - TCP: cmdutil.GetFlagStringSlice(cmd, "tcp"), - Type: v1.ServiceTypeClusterIP, - ClusterIP: cmdutil.GetFlagString(cmd, "clusterip"), - } - default: - return errUnsupportedGenerator(cmd, generatorName) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} - -var ( - serviceNodePortLong = templates.LongDesc(i18n.T(` - Create a NodePort service with the specified name.`)) - - serviceNodePortExample = templates.Examples(i18n.T(` - # Create a new NodePort service named my-ns - kubectl create service nodeport my-ns --tcp=5678:8080`)) -) - -// NewCmdCreateServiceNodePort is a macro command for creating a NodePort service -func NewCmdCreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "nodeport NAME [--tcp=port:targetPort] [--dry-run]", - DisableFlagsInUseLine: true, - Short: i18n.T("Create a NodePort service."), - Long: serviceNodePortLong, - Example: serviceNodePortExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateServiceNodePort(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceNodePortGeneratorV1Name) - cmd.Flags().Int("node-port", 0, "Port used to expose the service on each node in a cluster.") - addPortFlags(cmd) - return cmd -} - -// CreateServiceNodePort is the implementation of the create service nodeport command -func CreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.ServiceNodePortGeneratorV1Name: - generator = &kubectl.ServiceCommonGeneratorV1{ - Name: name, - TCP: cmdutil.GetFlagStringSlice(cmd, "tcp"), - Type: v1.ServiceTypeNodePort, - ClusterIP: "", - NodePort: cmdutil.GetFlagInt(cmd, "node-port"), - } - default: - return errUnsupportedGenerator(cmd, generatorName) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} - -var ( - serviceLoadBalancerLong = templates.LongDesc(i18n.T(` - Create a LoadBalancer service with the specified name.`)) - - serviceLoadBalancerExample = templates.Examples(i18n.T(` - # Create a new LoadBalancer service named my-lbs - kubectl create service loadbalancer my-lbs --tcp=5678:8080`)) -) - -// NewCmdCreateServiceLoadBalancer is a macro command for creating a LoadBalancer service -func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "loadbalancer NAME [--tcp=port:targetPort] [--dry-run]", - DisableFlagsInUseLine: true, - Short: i18n.T("Create a LoadBalancer service."), - Long: serviceLoadBalancerLong, - Example: serviceLoadBalancerExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateServiceLoadBalancer(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceLoadBalancerGeneratorV1Name) - addPortFlags(cmd) - return cmd -} - -// CreateServiceLoadBalancer is the implementation of the create service loadbalancer command -func CreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.ServiceLoadBalancerGeneratorV1Name: - generator = &kubectl.ServiceCommonGeneratorV1{ - Name: name, - TCP: cmdutil.GetFlagStringSlice(cmd, "tcp"), - Type: v1.ServiceTypeLoadBalancer, - ClusterIP: "", - } - default: - return errUnsupportedGenerator(cmd, generatorName) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} - -var ( - serviceExternalNameLong = templates.LongDesc(i18n.T(` - Create an ExternalName service with the specified name. - - ExternalName service references to an external DNS address instead of - only pods, which will allow application authors to reference services - that exist off platform, on other clusters, or locally.`)) - - serviceExternalNameExample = templates.Examples(i18n.T(` - # Create a new ExternalName service named my-ns - kubectl create service externalname my-ns --external-name bar.com`)) -) - -// NewCmdCreateServiceExternalName is a macro command for creating an ExternalName service -func NewCmdCreateServiceExternalName(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "externalname NAME --external-name external.name [--dry-run]", - DisableFlagsInUseLine: true, - Short: i18n.T("Create an ExternalName service."), - Long: serviceExternalNameLong, - Example: serviceExternalNameExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateExternalNameService(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceExternalNameGeneratorV1Name) - addPortFlags(cmd) - cmd.Flags().String("external-name", "", i18n.T("External name of service")) - cmd.MarkFlagRequired("external-name") - return cmd -} - -// CreateExternalNameService is the implementation of the create service externalname command -func CreateExternalNameService(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.ServiceExternalNameGeneratorV1Name: - generator = &kubectl.ServiceCommonGeneratorV1{ - Name: name, - Type: v1.ServiceTypeExternalName, - ExternalName: cmdutil.GetFlagString(cmd, "external-name"), - ClusterIP: "", - } - default: - return errUnsupportedGenerator(cmd, generatorName) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount.go deleted file mode 100644 index c4302c64c..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount.go +++ /dev/null @@ -1,80 +0,0 @@ -/* -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 cmd - -import ( - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" -) - -var ( - serviceAccountLong = templates.LongDesc(i18n.T(` - Create a service account with the specified name.`)) - - serviceAccountExample = templates.Examples(i18n.T(` - # Create a new service account named my-service-account - kubectl create serviceaccount my-service-account`)) -) - -// NewCmdCreateServiceAccount is a macro command to create a new service account -func NewCmdCreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "serviceaccount NAME [--dry-run]", - DisableFlagsInUseLine: true, - Aliases: []string{"sa"}, - Short: i18n.T("Create a service account with the specified name"), - Long: serviceAccountLong, - Example: serviceAccountExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateServiceAccount(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceAccountV1GeneratorName) - return cmd -} - -// CreateServiceAccount implements the behavior to run the create service account command -func CreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.ServiceAccountV1GeneratorName: - generator = &kubectl.ServiceAccountGeneratorV1{Name: name} - default: - return errUnsupportedGenerator(cmd, generatorName) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetDryRunFlag(cmd), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_test.go deleted file mode 100644 index 9b160374f..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/create_test.go +++ /dev/null @@ -1,159 +0,0 @@ -/* -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 cmd - -import ( - "bytes" - "net/http" - "testing" - - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" - cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - "k8s.io/kubernetes/pkg/kubectl/scheme" -) - -func TestExtraArgsFail(t *testing.T) { - initTestErrorHandler(t) - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - f := cmdtesting.NewTestFactory() - defer f.Cleanup() - - c := NewCmdCreate(f, buf, errBuf) - options := CreateOptions{} - if options.ValidateArgs(c, []string{"rc"}) == nil { - t.Errorf("unexpected non-error") - } -} - -func TestCreateObject(t *testing.T) { - initTestErrorHandler(t) - _, _, rc := testData() - rc.Items[0].Name = "redis-master-controller" - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: - return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdCreate(tf, buf, errBuf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - // uses the name from the file, not the response - if buf.String() != "replicationcontroller/redis-master-controller\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestCreateMultipleObject(t *testing.T) { - initTestErrorHandler(t) - _, svc, rc := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/services" && m == http.MethodPost: - return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil - case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: - return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdCreate(tf, buf, errBuf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - // Names should come from the REST response, NOT the files - if buf.String() != "replicationcontroller/rc1\nservice/baz\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestCreateDirectory(t *testing.T) { - initTestErrorHandler(t) - _, _, rc := testData() - rc.Items[0].Name = "name" - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: - return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdCreate(tf, buf, errBuf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/name\nreplicationcontroller/name\nreplicationcontroller/name\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete.go index 86f8869ab..8a085585a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete.go @@ -18,20 +18,28 @@ package cmd import ( "fmt" - "io" "strings" "time" + "github.com/golang/glog" "github.com/spf13/cobra" + appsv1 "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/client-go/dynamic" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + kubectlwait "k8s.io/kubernetes/pkg/kubectl/cmd/wait" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -90,7 +98,8 @@ var ( type DeleteOptions struct { resource.FilenameOptions - Selector string + LabelSelector string + FieldSelector string DeleteAll bool IgnoreNotFound bool Cascade bool @@ -101,20 +110,17 @@ type DeleteOptions struct { GracePeriod int Timeout time.Duration - Include3rdParty bool - Output string + Output string - Mapper meta.RESTMapper - Result *resource.Result + DynamicClient dynamic.Interface + Mapper meta.RESTMapper + Result *resource.Result - f cmdutil.Factory - Out io.Writer - ErrOut io.Writer + genericclioptions.IOStreams } -func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - options := &DeleteOptions{Include3rdParty: true} - validArgs := cmdutil.ValidArgList(f) +func NewCmdDelete(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + deleteFlags := NewDeleteCommandFlags("containing the resource to delete.") cmd := &cobra.Command{ Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", @@ -123,50 +129,52 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { Long: delete_long, Example: delete_example, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - if err := options.Complete(f, out, errOut, args, cmd); err != nil { - cmdutil.CheckErr(err) - } - if err := options.Validate(cmd); err != nil { - cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error())) - } - if err := options.RunDelete(); err != nil { - cmdutil.CheckErr(err) - } + o := deleteFlags.ToOptions(nil, streams) + cmdutil.CheckErr(o.Complete(f, args, cmd)) + cmdutil.CheckErr(o.Validate(cmd)) + cmdutil.CheckErr(o.RunDelete()) }, SuggestFor: []string{"rm"}, - ValidArgs: validArgs, - ArgAliases: kubectl.ResourceAliases(validArgs), - } - usage := "containing the resource to delete." - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) - cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones.") - cmd.Flags().BoolVar(&options.DeleteAll, "all", options.DeleteAll, "Delete all resources, including uninitialized ones, in the namespace of the specified resource types.") - cmd.Flags().BoolVar(&options.IgnoreNotFound, "ignore-not-found", false, "Treat \"resource not found\" as a successful delete. Defaults to \"true\" when --all is specified.") - cmd.Flags().BoolVar(&options.Cascade, "cascade", true, "If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.") - cmd.Flags().IntVar(&options.GracePeriod, "grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.") - cmd.Flags().BoolVar(&options.DeleteNow, "now", false, "If true, resources are signaled for immediate shutdown (same as --grace-period=1).") - cmd.Flags().BoolVar(&options.ForceDeletion, "force", false, "Immediate deletion of some resources may result in inconsistency or data loss and requires confirmation.") - cmd.Flags().DurationVar(&options.Timeout, "timeout", 0, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object") - cmdutil.AddOutputVarFlagsForMutation(cmd, &options.Output) - cmdutil.AddInclude3rdPartyVarFlags(cmd, &options.Include3rdParty) + } + + deleteFlags.AddFlags(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } -func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string, cmd *cobra.Command) error { - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() +func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Command) error { + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } + if o.DeleteAll || len(o.LabelSelector) > 0 || len(o.FieldSelector) > 0 { + if f := cmd.Flags().Lookup("ignore-not-found"); f != nil && !f.Changed { + // If the user didn't explicitly set the option, default to ignoring NotFound errors when used with --all, -l, or --field-selector + o.IgnoreNotFound = true + } + } + if o.DeleteNow { + if o.GracePeriod != -1 { + return fmt.Errorf("--now and --grace-period cannot be specified together") + } + o.GracePeriod = 1 + } + if o.GracePeriod == 0 && !o.ForceDeletion { + // To preserve backwards compatibility, but prevent accidental data loss, we convert --grace-period=0 + // into --grace-period=1. Users may provide --force to bypass this conversion. + o.GracePeriod = 1 + } + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) r := f.NewBuilder(). Unstructured(). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). - LabelSelectorParam(o.Selector). + LabelSelectorParam(o.LabelSelector). + FieldSelectorParam(o.FieldSelector). IncludeUninitialized(includeUninitialized). SelectAllParam(o.DeleteAll). ResourceTypeOrNameArgs(false, args...).RequireObject(false). @@ -177,151 +185,211 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args return err } o.Result = r - o.Mapper = r.Mapper().RESTMapper - o.f = f - // Set up writer - o.Out = out - o.ErrOut = errOut + o.Mapper, err = f.ToRESTMapper() + if err != nil { + return err + } + + o.DynamicClient, err = f.DynamicClient() + if err != nil { + return err + } return nil } func (o *DeleteOptions) Validate(cmd *cobra.Command) error { - if o.DeleteAll && len(o.Selector) > 0 { + if o.Output != "" && o.Output != "name" { + return cmdutil.UsageErrorf(cmd, "Unexpected -o output mode: %v. We only support '-o name'.", o.Output) + } + + if o.DeleteAll && len(o.LabelSelector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") } - if o.DeleteAll { - f := cmd.Flags().Lookup("ignore-not-found") - // The flag should never be missing - if f == nil { - return fmt.Errorf("missing --ignore-not-found flag") - } - // If the user didn't explicitly set the option, default to ignoring NotFound errors when used with --all - if !f.Changed { - o.IgnoreNotFound = true - } + if o.DeleteAll && len(o.FieldSelector) > 0 { + return fmt.Errorf("cannot set --all and --field-selector at the same time") } - if o.DeleteNow { - if o.GracePeriod != -1 { - return fmt.Errorf("--now and --grace-period cannot be specified together") - } - o.GracePeriod = 1 + + if o.GracePeriod == 0 && !o.ForceDeletion && !o.WaitForDeletion { + // With the explicit --wait flag we need extra validation for backward compatibility + return fmt.Errorf("--grace-period=0 must have either --force specified, or --wait to be set to true") } - if o.GracePeriod == 0 { - if o.ForceDeletion { - fmt.Fprintf(o.ErrOut, "warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n") - } else { - // To preserve backwards compatibility, but prevent accidental data loss, we convert --grace-period=0 - // into --grace-period=1 and wait until the object is successfully deleted. Users may provide --force - // to bypass this wait. - o.WaitForDeletion = true - o.GracePeriod = 1 - } + + switch { + case o.GracePeriod == 0 && o.ForceDeletion: + fmt.Fprintf(o.ErrOut, "warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n") + case o.ForceDeletion: + fmt.Fprintf(o.ErrOut, "warning: --force is ignored because --grace-period is not 0.\n") } return nil } func (o *DeleteOptions) RunDelete() error { - shortOutput := o.Output == "name" - // By default use a reaper to delete all related resources. - if o.Cascade { - return ReapResult(o.Result, o.f, o.Out, true, o.IgnoreNotFound, o.Timeout, o.GracePeriod, o.WaitForDeletion, shortOutput, false) - } - return DeleteResult(o.Result, o.Out, o.IgnoreNotFound, o.GracePeriod, shortOutput) + return o.DeleteResult(o.Result) } -func ReapResult(r *resource.Result, f cmdutil.Factory, out io.Writer, isDefaultDelete, ignoreNotFound bool, timeout time.Duration, gracePeriod int, waitForDeletion, shortOutput bool, quiet bool) error { +func (o *DeleteOptions) DeleteResult(r *resource.Result) error { found := 0 - if ignoreNotFound { + if o.IgnoreNotFound { r = r.IgnoreErrors(errors.IsNotFound) } + deletedInfos := []*resource.Info{} + uidMap := kubectlwait.UIDMap{} err := r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } + deletedInfos = append(deletedInfos, info) found++ - reaper, err := f.Reaper(info.Mapping) - if err != nil { - // If there is no reaper for this resources and the user didn't explicitly ask for stop. - if kubectl.IsNoSuchReaperError(err) && isDefaultDelete { - // No client side reaper found. Let the server do cascading deletion. - return cascadingDeleteResource(info, out, shortOutput) - } - return cmdutil.AddSourceToErr("reaping", info.Source, err) + + options := &metav1.DeleteOptions{} + if o.GracePeriod >= 0 { + options = metav1.NewDeleteOptions(int64(o.GracePeriod)) + } + policy := metav1.DeletePropagationBackground + if !o.Cascade { + policy = metav1.DeletePropagationOrphan } - var options *metav1.DeleteOptions - if gracePeriod >= 0 { - options = metav1.NewDeleteOptions(int64(gracePeriod)) + options.PropagationPolicy = &policy + + response, err := o.deleteResource(info, options) + if err != nil { + return err } - if err := reaper.Stop(info.Namespace, info.Name, timeout, options); err != nil { - return cmdutil.AddSourceToErr("stopping", info.Source, err) + resourceLocation := kubectlwait.ResourceLocation{ + GroupResource: info.Mapping.Resource.GroupResource(), + Namespace: info.Namespace, + Name: info.Name, } - if waitForDeletion { - if err := waitForObjectDeletion(info, timeout); err != nil { - return cmdutil.AddSourceToErr("stopping", info.Source, err) - } + if status, ok := response.(*metav1.Status); ok && status.Details != nil { + uidMap[resourceLocation] = status.Details.UID + return nil } - if !quiet { - printDeletion(info, out, shortOutput) + responseMetadata, err := meta.Accessor(response) + if err != nil { + // we don't have UID, but we didn't fail the delete, next best thing is just skipping the UID + glog.V(1).Info(err) + return nil } + uidMap[resourceLocation] = responseMetadata.GetUID() + return nil }) if err != nil { return err } if found == 0 { - fmt.Fprintf(out, "No resources found\n") + fmt.Fprintf(o.Out, "No resources found\n") + return nil + } + if !o.WaitForDeletion { + return nil + } + // if we don't have a dynamic client, we don't want to wait. Eventually when delete is cleaned up, this will likely + // drop out. + if o.DynamicClient == nil { + return nil } - return nil -} -func DeleteResult(r *resource.Result, out io.Writer, ignoreNotFound bool, gracePeriod int, shortOutput bool) error { - found := 0 - if ignoreNotFound { - r = r.IgnoreErrors(errors.IsNotFound) + effectiveTimeout := o.Timeout + if effectiveTimeout == 0 { + // if we requested to wait forever, set it to a week. + effectiveTimeout = 168 * time.Hour } - err := r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - found++ + waitOptions := kubectlwait.WaitOptions{ + ResourceFinder: genericclioptions.ResourceFinderForResult(resource.InfoListVisitor(deletedInfos)), + UIDMap: uidMap, + DynamicClient: o.DynamicClient, + Timeout: effectiveTimeout, + + Printer: printers.NewDiscardingPrinter(), + ConditionFn: kubectlwait.IsDeleted, + IOStreams: o.IOStreams, + } + err = waitOptions.RunWait() + if errors.IsForbidden(err) || errors.IsMethodNotSupported(err) { + // if we're forbidden from waiting, we shouldn't fail. + // if the resource doesn't support a verb we need, we shouldn't fail. + glog.V(1).Info(err) + return nil + } + return err +} - // if we're here, it means that cascade=false (not the default), so we should orphan as requested - orphan := true - options := &metav1.DeleteOptions{} - if gracePeriod >= 0 { - options = metav1.NewDeleteOptions(int64(gracePeriod)) +func (o *DeleteOptions) deleteResource(info *resource.Info, deleteOptions *metav1.DeleteOptions) (runtime.Object, error) { + // TODO: Remove this in or after 1.12 release. + // Server version >= 1.11 no longer needs this hack. + mapping := info.ResourceMapping() + if (mapping.Resource.GroupResource() == (schema.GroupResource{Group: "extensions", Resource: "daemonsets"}) || + mapping.Resource.GroupResource() == (schema.GroupResource{Group: "apps", Resource: "daemonsets"})) && + (deleteOptions.PropagationPolicy != nil && *deleteOptions.PropagationPolicy != metav1.DeletePropagationOrphan) { + if err := updateDaemonSet(info.Namespace, info.Name, o.DynamicClient); err != nil { + return nil, err } - options.OrphanDependents = &orphan - return deleteResource(info, out, shortOutput, options) - }) + } + + deleteResponse, err := resource.NewHelper(info.Client, info.Mapping).DeleteWithOptions(info.Namespace, info.Name, deleteOptions) + if err != nil { + return nil, cmdutil.AddSourceToErr("deleting", info.Source, err) + } + + o.PrintObj(info) + return deleteResponse, nil +} + +// TODO: Remove this in or after 1.12 release. +// Server version >= 1.11 no longer needs this hack. +func updateDaemonSet(namespace, name string, dynamicClient dynamic.Interface) error { + dsClient := dynamicClient.Resource(schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"}).Namespace(namespace) + obj, err := dsClient.Get(name, metav1.GetOptions{}) if err != nil { return err } - if found == 0 { - fmt.Fprintf(out, "No resources found\n") + ds := &appsv1.DaemonSet{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, ds); err != nil { + return err } - return nil -} -func cascadingDeleteResource(info *resource.Info, out io.Writer, shortOutput bool) error { - falseVar := false - deleteOptions := &metav1.DeleteOptions{OrphanDependents: &falseVar} - return deleteResource(info, out, shortOutput, deleteOptions) -} + // We set the nodeSelector to a random label. This label is nearly guaranteed + // to not be set on any node so the DameonSetController will start deleting + // daemon pods. Once it's done deleting the daemon pods, it's safe to delete + // the DaemonSet. + ds.Spec.Template.Spec.NodeSelector = map[string]string{ + string(uuid.NewUUID()): string(uuid.NewUUID()), + } + // force update to avoid version conflict + ds.ResourceVersion = "" -func deleteResource(info *resource.Info, out io.Writer, shortOutput bool, deleteOptions *metav1.DeleteOptions) error { - if err := resource.NewHelper(info.Client, info.Mapping).DeleteWithOptions(info.Namespace, info.Name, deleteOptions); err != nil { - return cmdutil.AddSourceToErr("deleting", info.Source, err) + out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(ds) + if err != nil { + return err } + if _, err = dsClient.Update(&unstructured.Unstructured{Object: out}); err != nil { + return err + } + + // Wait for the daemon set controller to kill all the daemon pods. + if err := wait.Poll(1*time.Second, 5*time.Minute, func() (bool, error) { + updatedObj, err := dsClient.Get(name, metav1.GetOptions{}) + if err != nil { + return false, nil + } + updatedDS := &appsv1.DaemonSet{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(updatedObj.Object, ds); err != nil { + return false, nil + } - printDeletion(info, out, shortOutput) + return updatedDS.Status.CurrentNumberScheduled+updatedDS.Status.NumberMisscheduled == 0, nil + }); err != nil { + return err + } return nil } -// deletion printing is special because they don't have an object to print. This logic mirrors PrintSuccess -func printDeletion(info *resource.Info, out io.Writer, shortOutput bool) { +// deletion printing is special because we do not have an object to print. +// This mirrors name printer behavior +func (o *DeleteOptions) PrintObj(info *resource.Info) { operation := "deleted" groupKind := info.Mapping.GroupVersionKind kindString := fmt.Sprintf("%s.%s", strings.ToLower(groupKind.Kind), groupKind.Group) @@ -329,33 +397,16 @@ func printDeletion(info *resource.Info, out io.Writer, shortOutput bool) { kindString = strings.ToLower(groupKind.Kind) } - if shortOutput { + if o.GracePeriod == 0 { + operation = "force deleted" + } + + if o.Output == "name" { // -o name: prints resource/name - fmt.Fprintf(out, "%s/%s\n", kindString, info.Name) + fmt.Fprintf(o.Out, "%s/%s\n", kindString, info.Name) return } // understandable output by default - fmt.Fprintf(out, "%s \"%s\" %s\n", kindString, info.Name, operation) -} - -// objectDeletionWaitInterval is the interval to wait between checks for deletion. -var objectDeletionWaitInterval = time.Second - -// waitForObjectDeletion refreshes the object, waiting until it is deleted, a timeout is reached, or -// an error is encountered. It checks once a second. -func waitForObjectDeletion(info *resource.Info, timeout time.Duration) error { - copied := *info - info = &copied - // TODO: refactor Reaper so that we can pass the "wait" option into it, and then check for UID change. - return wait.PollImmediate(objectDeletionWaitInterval, timeout, func() (bool, error) { - switch err := info.Get(); { - case err == nil: - return false, nil - case errors.IsNotFound(err): - return true, nil - default: - return false, err - } - }) + fmt.Fprintf(o.Out, "%s \"%s\" %s\n", kindString, info.Name, operation) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete_flags.go new file mode 100644 index 000000000..c98d1fce0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete_flags.go @@ -0,0 +1,193 @@ +/* +Copyright 2018 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 cmd + +import ( + "time" + + "github.com/spf13/cobra" + + "k8s.io/client-go/dynamic" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +// PrintFlags composes common printer flag structs +// used for commands requiring deletion logic. +type DeleteFlags struct { + FileNameFlags *genericclioptions.FileNameFlags + LabelSelector *string + FieldSelector *string + + All *bool + Cascade *bool + Force *bool + GracePeriod *int + IgnoreNotFound *bool + Now *bool + Timeout *time.Duration + Wait *bool + Output *string +} + +func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams genericclioptions.IOStreams) *DeleteOptions { + options := &DeleteOptions{ + DynamicClient: dynamicClient, + IOStreams: streams, + } + + // add filename options + if f.FileNameFlags != nil { + options.FilenameOptions = f.FileNameFlags.ToOptions() + } + if f.LabelSelector != nil { + options.LabelSelector = *f.LabelSelector + } + if f.FieldSelector != nil { + options.FieldSelector = *f.FieldSelector + } + + // add output format + if f.Output != nil { + options.Output = *f.Output + } + + if f.All != nil { + options.DeleteAll = *f.All + } + if f.Cascade != nil { + options.Cascade = *f.Cascade + } + if f.Force != nil { + options.ForceDeletion = *f.Force + } + if f.GracePeriod != nil { + options.GracePeriod = *f.GracePeriod + } + if f.IgnoreNotFound != nil { + options.IgnoreNotFound = *f.IgnoreNotFound + } + if f.Now != nil { + options.DeleteNow = *f.Now + } + if f.Timeout != nil { + options.Timeout = *f.Timeout + } + if f.Wait != nil { + options.WaitForDeletion = *f.Wait + } + + return options +} + +func (f *DeleteFlags) AddFlags(cmd *cobra.Command) { + f.FileNameFlags.AddFlags(cmd.Flags()) + if f.LabelSelector != nil { + cmd.Flags().StringVarP(f.LabelSelector, "selector", "l", *f.LabelSelector, "Selector (label query) to filter on, not including uninitialized ones.") + } + if f.FieldSelector != nil { + cmd.Flags().StringVarP(f.FieldSelector, "field-selector", "", *f.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") + } + if f.All != nil { + cmd.Flags().BoolVar(f.All, "all", *f.All, "Delete all resources, including uninitialized ones, in the namespace of the specified resource types.") + } + if f.Force != nil { + cmd.Flags().BoolVar(f.Force, "force", *f.Force, "Only used when grace-period=0. If true, immediately remove resources from API and bypass graceful deletion. Note that immediate deletion of some resources may result in inconsistency or data loss and requires confirmation.") + } + if f.Cascade != nil { + cmd.Flags().BoolVar(f.Cascade, "cascade", *f.Cascade, "If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.") + } + if f.Now != nil { + cmd.Flags().BoolVar(f.Now, "now", *f.Now, "If true, resources are signaled for immediate shutdown (same as --grace-period=1).") + } + if f.GracePeriod != nil { + cmd.Flags().IntVar(f.GracePeriod, "grace-period", *f.GracePeriod, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative. Set to 1 for immediate shutdown. Can only be set to 0 when --force is true (force deletion).") + } + if f.Timeout != nil { + cmd.Flags().DurationVar(f.Timeout, "timeout", *f.Timeout, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object") + } + if f.IgnoreNotFound != nil { + cmd.Flags().BoolVar(f.IgnoreNotFound, "ignore-not-found", *f.IgnoreNotFound, "Treat \"resource not found\" as a successful delete. Defaults to \"true\" when --all is specified.") + } + if f.Wait != nil { + cmd.Flags().BoolVar(f.Wait, "wait", *f.Wait, "If true, wait for resources to be gone before returning. This waits for finalizers.") + } + if f.Output != nil { + cmd.Flags().StringVarP(f.Output, "output", "o", *f.Output, "Output mode. Use \"-o name\" for shorter output (resource/name).") + } +} + +// NewDeleteCommandFlags provides default flags and values for use with the "delete" command +func NewDeleteCommandFlags(usage string) *DeleteFlags { + cascade := true + gracePeriod := -1 + + // setup command defaults + all := false + force := false + ignoreNotFound := false + now := false + output := "" + labelSelector := "" + fieldSelector := "" + timeout := time.Duration(0) + wait := true + + filenames := []string{} + recursive := false + + return &DeleteFlags{ + FileNameFlags: &genericclioptions.FileNameFlags{Usage: usage, Filenames: &filenames, Recursive: &recursive}, + LabelSelector: &labelSelector, + FieldSelector: &fieldSelector, + + Cascade: &cascade, + GracePeriod: &gracePeriod, + + All: &all, + Force: &force, + IgnoreNotFound: &ignoreNotFound, + Now: &now, + Timeout: &timeout, + Wait: &wait, + Output: &output, + } +} + +// NewDeleteFlags provides default flags and values for use in commands outside of "delete" +func NewDeleteFlags(usage string) *DeleteFlags { + cascade := true + gracePeriod := -1 + + force := false + timeout := time.Duration(0) + wait := false + + filenames := []string{} + recursive := false + + return &DeleteFlags{ + FileNameFlags: &genericclioptions.FileNameFlags{Usage: usage, Filenames: &filenames, Recursive: &recursive}, + + Cascade: &cascade, + GracePeriod: &gracePeriod, + + // add non-defaults + Force: &force, + Timeout: &timeout, + Wait: &wait, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete_test.go index cd937864b..8c8f1bc79 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/delete_test.go @@ -17,49 +17,45 @@ limitations under the License. package cmd import ( - "bytes" "encoding/json" "io" "io/ioutil" "net/http" "strings" "testing" - "time" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/dynamic" "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/kubectl" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" ) -var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer +var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer -var fakecmd = &cobra.Command{ - Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", - DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - }, +func fakecmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", + DisableFlagsInUseLine: true, + Run: func(cmd *cobra.Command, args []string) {}, + } + return cmd } func TestDeleteObjectByTuple(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -81,10 +77,9 @@ func TestDeleteObjectByTuple(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - cmd := NewCmdDelete(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdDelete(tf, streams) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") @@ -94,8 +89,8 @@ func TestDeleteObjectByTuple(t *testing.T) { } // Test cascading delete of object without client-side reaper doesn't make GET requests - buf, errBuf = bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - cmd = NewCmdDelete(tf, buf, errBuf) + streams, _, buf, _ = genericclioptions.NewTestIOStreams() + cmd = NewCmdDelete(tf, streams) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{"secrets/mysecret"}) @@ -104,17 +99,17 @@ func TestDeleteObjectByTuple(t *testing.T) { } } -func hasExpectedOrphanDependents(body io.ReadCloser, expectedOrphanDependents *bool) bool { - if body == nil || expectedOrphanDependents == nil { - return body == nil && expectedOrphanDependents == nil +func hasExpectedPropagationPolicy(body io.ReadCloser, policy *metav1.DeletionPropagation) bool { + if body == nil || policy == nil { + return body == nil && policy == nil } var parsedBody metav1.DeleteOptions rawBody, _ := ioutil.ReadAll(body) json.Unmarshal(rawBody, &parsedBody) - if parsedBody.OrphanDependents == nil { + if parsedBody.PropagationPolicy == nil { return false } - return *expectedOrphanDependents == *parsedBody.OrphanDependents + return *policy == *parsedBody.PropagationPolicy } // Tests that DeleteOptions.OrphanDependents is appropriately set while deleting objects. @@ -122,18 +117,18 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) - var expectedOrphanDependents *bool + var policy *metav1.DeletionPropagation tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { switch p, m, b := req.URL.Path, req.Method, req.Body; { - case p == "/namespaces/test/secrets/mysecret" && m == "DELETE" && hasExpectedOrphanDependents(b, expectedOrphanDependents): + case p == "/namespaces/test/secrets/mysecret" && m == "DELETE" && hasExpectedPropagationPolicy(b, policy): return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil default: @@ -141,13 +136,12 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) { } }), } - tf.Namespace = "test" - // DeleteOptions.OrphanDependents should be false, when cascade is true (default). - falseVar := false - expectedOrphanDependents = &falseVar - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - cmd := NewCmdDelete(tf, buf, errBuf) + // DeleteOptions.PropagationPolicy should be Background, when cascade is true (default). + backgroundPolicy := metav1.DeletePropagationBackground + policy = &backgroundPolicy + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdDelete(tf, streams) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{"secrets/mysecret"}) @@ -156,10 +150,10 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) { } // Test that delete options should be set to orphan when cascade is false. - trueVar := true - expectedOrphanDependents = &trueVar - buf, errBuf = bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - cmd = NewCmdDelete(tf, buf, errBuf) + orphanPolicy := metav1.DeletePropagationOrphan + policy = &orphanPolicy + streams, _, buf, _ = genericclioptions.NewTestIOStreams() + cmd = NewCmdDelete(tf, streams) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") @@ -174,10 +168,10 @@ func TestDeleteNamedObject(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -199,10 +193,9 @@ func TestDeleteNamedObject(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - cmd := NewCmdDelete(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdDelete(tf, streams) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") @@ -212,8 +205,8 @@ func TestDeleteNamedObject(t *testing.T) { } // Test cascading delete of object without client-side reaper doesn't make GET requests - buf, errBuf = bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - cmd = NewCmdDelete(tf, buf, errBuf) + streams, _, buf, _ = genericclioptions.NewTestIOStreams() + cmd = NewCmdDelete(tf, streams) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") @@ -227,10 +220,10 @@ func TestDeleteObject(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -244,11 +237,10 @@ func TestDeleteObject(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - cmd := NewCmdDelete(tf, buf, errBuf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdDelete(tf, streams) + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -259,39 +251,15 @@ func TestDeleteObject(t *testing.T) { } } -type fakeReaper struct { - namespace, name string - timeout time.Duration - deleteOptions *metav1.DeleteOptions - err error -} - -func (r *fakeReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error { - r.namespace, r.name = namespace, name - r.timeout = timeout - r.deleteOptions = gracePeriod - return r.err -} - -type fakeReaperFactory struct { - cmdutil.Factory - reaper kubectl.Reaper -} - -func (f *fakeReaperFactory) Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, error) { - return f.reaper, nil -} - func TestDeleteObjectGraceZero(t *testing.T) { initTestErrorHandler(t) pods, _, _ := testData() - objectDeletionWaitInterval = time.Millisecond count := 0 - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -316,12 +284,9 @@ func TestDeleteObjectGraceZero(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - reaper := &fakeReaper{} - fake := &fakeReaperFactory{Factory: tf, reaper: reaper} - cmd := NewCmdDelete(fake, buf, errBuf) + streams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdDelete(tf, streams) cmd.Flags().Set("output", "name") cmd.Flags().Set("grace-period", "0") cmd.Run(cmd, []string{"pods/nginx"}) @@ -330,17 +295,14 @@ func TestDeleteObjectGraceZero(t *testing.T) { if buf.String() != "pod/nginx\n" { t.Errorf("unexpected output: %s\n---\n%s", buf.String(), errBuf.String()) } - if reaper.deleteOptions == nil || reaper.deleteOptions.GracePeriodSeconds == nil || *reaper.deleteOptions.GracePeriodSeconds != 1 { - t.Errorf("unexpected reaper options: %#v", reaper) - } - if count != 4 { + if count != 0 { t.Errorf("unexpected calls to GET: %d", count) } } func TestDeleteObjectNotFound(t *testing.T) { initTestErrorHandler(t) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -355,18 +317,17 @@ func TestDeleteObjectNotFound(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) options := &DeleteOptions{ FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}, + Filenames: []string{"../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml"}, }, GracePeriod: -1, Cascade: false, Output: "name", + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), } - err := options.Complete(tf, buf, errBuf, []string{}, fakecmd) + err := options.Complete(tf, []string{}, fakecmd()) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -378,7 +339,7 @@ func TestDeleteObjectNotFound(t *testing.T) { func TestDeleteObjectIgnoreNotFound(t *testing.T) { initTestErrorHandler(t) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -393,11 +354,10 @@ func TestDeleteObjectIgnoreNotFound(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdDelete(tf, buf, errBuf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") + cmd := NewCmdDelete(tf, streams) + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("ignore-not-found", "true") cmd.Flags().Set("output", "name") @@ -415,10 +375,10 @@ func TestDeleteAllNotFound(t *testing.T) { svc.Items = append(svc.Items, api.Service{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}) notFoundError := &errors.NewNotFound(api.Resource("services"), "foo").ErrStatus - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -436,8 +396,6 @@ func TestDeleteAllNotFound(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) // Make sure we can explicitly choose to fail on NotFound errors, even with --all options := &DeleteOptions{ @@ -447,8 +405,9 @@ func TestDeleteAllNotFound(t *testing.T) { DeleteAll: true, IgnoreNotFound: false, Output: "name", + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), } - err := options.Complete(tf, buf, errBuf, []string{"services"}, fakecmd) + err := options.Complete(tf, []string{"services"}, fakecmd()) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -462,10 +421,10 @@ func TestDeleteAllIgnoreNotFound(t *testing.T) { initTestErrorHandler(t) _, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) // Add an item to the list which will result in a 404 on delete svc.Items = append(svc.Items, api.Service{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}) @@ -487,10 +446,9 @@ func TestDeleteAllIgnoreNotFound(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdDelete(tf, buf, errBuf) + cmd := NewCmdDelete(tf, streams) cmd.Flags().Set("all", "true") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") @@ -505,10 +463,10 @@ func TestDeleteMultipleObject(t *testing.T) { initTestErrorHandler(t) _, svc, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -524,12 +482,11 @@ func TestDeleteMultipleObject(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdDelete(tf, buf, errBuf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") + cmd := NewCmdDelete(tf, streams) + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -543,10 +500,10 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { initTestErrorHandler(t) _, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -562,18 +519,18 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() options := &DeleteOptions{ FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml", "../../../examples/guestbook/frontend-service.yaml"}, + Filenames: []string{"../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml"}, }, GracePeriod: -1, Cascade: false, Output: "name", + IOStreams: streams, } - err := options.Complete(tf, buf, errBuf, []string{}, fakecmd) + err := options.Complete(tf, []string{}, fakecmd()) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -590,10 +547,10 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) { initTestErrorHandler(t) _, svc, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -614,10 +571,9 @@ func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdDelete(tf, buf, errBuf) + cmd := NewCmdDelete(tf, streams) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") @@ -631,10 +587,10 @@ func TestDeleteDirectory(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -648,11 +604,10 @@ func TestDeleteDirectory(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdDelete(tf, buf, errBuf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy") + cmd := NewCmdDelete(tf, streams) + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -666,10 +621,10 @@ func TestDeleteMultipleSelector(t *testing.T) { initTestErrorHandler(t) pods, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -695,10 +650,9 @@ func TestDeleteMultipleSelector(t *testing.T) { } }), } - tf.Namespace = "test" - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdDelete(tf, buf, errBuf) + cmd := NewCmdDelete(tf, streams) cmd.Flags().Set("selector", "a=b") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") @@ -735,21 +689,20 @@ func TestResourceErrors(t *testing.T) { for k, testCase := range testCases { t.Run(k, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - + streams, _, buf, _ := genericclioptions.NewTestIOStreams() options := &DeleteOptions{ FilenameOptions: resource.FilenameOptions{}, GracePeriod: -1, Cascade: false, Output: "name", + IOStreams: streams, } - err := options.Complete(tf, buf, errBuf, testCase.args, fakecmd) + err := options.Complete(tf, testCase.args, fakecmd()) if !testCase.errFn(err) { t.Errorf("%s: unexpected error: %v", k, err) return diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/describe.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/describe.go index f1b75ccd0..3a0feafdd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/describe.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/describe.go @@ -18,21 +18,20 @@ package cmd import ( "fmt" - "io" "strings" "github.com/spf13/cobra" apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/printers" - printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" ) var ( @@ -69,67 +68,103 @@ var ( kubectl describe pods frontend`)) ) -func NewCmdDescribe(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { - options := &resource.FilenameOptions{} - describerSettings := &printers.DescriberSettings{} +type DescribeOptions struct { + CmdParent string + Selector string + Namespace string - // TODO: this should come from the factory, and may need to be loaded from the server, and so is probably - // going to have to be removed - validArgs := printersinternal.DescribableResources() - argAliases := kubectl.ResourceAliases(validArgs) + Describer func(*meta.RESTMapping) (printers.Describer, error) + NewBuilder func() *resource.Builder + + BuilderArgs []string + + EnforceNamespace bool + AllNamespaces bool + IncludeUninitialized bool + + DescriberSettings *printers.DescriberSettings + FilenameOptions *resource.FilenameOptions + + genericclioptions.IOStreams +} + +func NewCmdDescribe(parent string, f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := &DescribeOptions{ + FilenameOptions: &resource.FilenameOptions{}, + DescriberSettings: &printers.DescriberSettings{ + ShowEvents: true, + }, + + CmdParent: parent, + + IOStreams: streams, + } cmd := &cobra.Command{ Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)", DisableFlagsInUseLine: true, Short: i18n.T("Show details of a specific resource or group of resources"), - Long: describeLong + "\n\n" + cmdutil.ValidResourceTypeList(f), + Long: describeLong + "\n\n" + cmdutil.SuggestApiResources(parent), Example: describeExample, Run: func(cmd *cobra.Command, args []string) { - err := RunDescribe(f, out, cmdErr, cmd, args, options, describerSettings) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Run()) }, - ValidArgs: validArgs, - ArgAliases: argAliases, } usage := "containing the resource to describe" - cmdutil.AddFilenameOptionFlags(cmd, options, usage) - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") - cmd.Flags().BoolVar(&describerSettings.ShowEvents, "show-events", true, "If true, display events related to the described object.") - cmdutil.AddInclude3rdPartyFlags(cmd) + cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + cmd.Flags().BoolVar(&o.DescriberSettings.ShowEvents, "show-events", o.DescriberSettings.ShowEvents, "If true, display events related to the described object.") cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } -func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions, describerSettings *printers.DescriberSettings) error { - selector := cmdutil.GetFlagString(cmd, "selector") - allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces") - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() +func (o *DescribeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - if allNamespaces { - enforceNamespace = false + + if o.AllNamespaces { + o.EnforceNamespace = false + } + + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) { + return fmt.Errorf("You must specify the type of resource to describe. %s\n", cmdutil.SuggestApiResources(o.CmdParent)) } - if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { - fmt.Fprint(cmdErr, "You must specify the type of resource to describe. ", cmdutil.ValidResourceTypeList(f)) - return cmdutil.UsageErrorf(cmd, "Required resource not specified.") + + o.BuilderArgs = args + + o.Describer = func(mapping *meta.RESTMapping) (printers.Describer, error) { + return cmdutil.DescriberFn(f, mapping) } + o.NewBuilder = f.NewBuilder + // include the uninitialized objects by default // unless user explicitly set --include-uninitialized=false - includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, true) - r := f.NewBuilder(). + o.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, true) + return nil +} + +func (o *DescribeOptions) Validate(args []string) error { + return nil +} + +func (o *DescribeOptions) Run() error { + r := o.NewBuilder(). Unstructured(). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). - FilenameParam(enforceNamespace, options). - LabelSelectorParam(selector). - IncludeUninitialized(includeUninitialized). - ResourceTypeOrNameArgs(true, args...). + NamespaceParam(o.Namespace).DefaultNamespace().AllNamespaces(o.AllNamespaces). + FilenameParam(o.EnforceNamespace, o.FilenameOptions). + LabelSelectorParam(o.Selector). + IncludeUninitialized(o.IncludeUninitialized). + ResourceTypeOrNameArgs(true, o.BuilderArgs...). Flatten(). Do() - err = r.Err() + err := r.Err() if err != nil { return err } @@ -137,8 +172,8 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a allErrs := []error{} infos, err := r.Infos() if err != nil { - if apierrors.IsNotFound(err) && len(args) == 2 { - return DescribeMatchingResources(f, cmdNamespace, args[0], args[1], describerSettings, out, err) + if apierrors.IsNotFound(err) && len(o.BuilderArgs) == 2 { + return o.DescribeMatchingResources(err, o.BuilderArgs[0], o.BuilderArgs[1]) } allErrs = append(allErrs, err) } @@ -147,7 +182,7 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a first := true for _, info := range infos { mapping := info.ResourceMapping() - describer, err := f.Describer(mapping) + describer, err := o.Describer(mapping) if err != nil { if errs.Has(err.Error()) { continue @@ -156,7 +191,7 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a errs.Insert(err.Error()) continue } - s, err := describer.Describe(info.Namespace, info.Name, *describerSettings) + s, err := describer.Describe(info.Namespace, info.Name, *o.DescriberSettings) if err != nil { if errs.Has(err.Error()) { continue @@ -167,20 +202,20 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a } if first { first = false - fmt.Fprint(out, s) + fmt.Fprint(o.Out, s) } else { - fmt.Fprintf(out, "\n\n%s", s) + fmt.Fprintf(o.Out, "\n\n%s", s) } } return utilerrors.NewAggregate(allErrs) } -func DescribeMatchingResources(f cmdutil.Factory, namespace, rsrc, prefix string, describerSettings *printers.DescriberSettings, out io.Writer, originalError error) error { - r := f.NewBuilder(). +func (o *DescribeOptions) DescribeMatchingResources(originalError error, resource, prefix string) error { + r := o.NewBuilder(). Unstructured(). - NamespaceParam(namespace).DefaultNamespace(). - ResourceTypeOrNameArgs(true, rsrc). + NamespaceParam(o.Namespace).DefaultNamespace(). + ResourceTypeOrNameArgs(true, resource). SingleResourceType(). Flatten(). Do() @@ -188,7 +223,7 @@ func DescribeMatchingResources(f cmdutil.Factory, namespace, rsrc, prefix string if err != nil { return err } - describer, err := f.Describer(mapping) + describer, err := o.Describer(mapping) if err != nil { return err } @@ -201,11 +236,11 @@ func DescribeMatchingResources(f cmdutil.Factory, namespace, rsrc, prefix string info := infos[ix] if strings.HasPrefix(info.Name, prefix) { isFound = true - s, err := describer.Describe(info.Namespace, info.Name, *describerSettings) + s, err := describer.Describe(info.Namespace, info.Name, *o.DescriberSettings) if err != nil { return err } - fmt.Fprintf(out, "%s\n", s) + fmt.Fprintf(o.Out, "%s\n", s) } } if !isFound { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/describe_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/describe_test.go index 6e029f3d6..daac115ed 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/describe_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/describe_test.go @@ -17,33 +17,42 @@ limitations under the License. package cmd import ( - "bytes" "fmt" "net/http" "strings" "testing" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" + "k8s.io/kubernetes/pkg/printers" ) // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. func TestDescribeUnknownSchemaObject(t *testing.T) { d := &testDescriber{Output: "test output"} - tf := cmdtesting.NewTestFactory() + oldFn := cmdutil.DescriberFn + defer func() { + cmdutil.DescriberFn = oldFn + }() + cmdutil.DescriberFn = d.describerFor + + tf := cmdtesting.NewTestFactory().WithNamespace("non-default") defer tf.Cleanup() _, _, codec := cmdtesting.NewExternalScheme() - tf.DescriberVal = d + tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalType("", "", "foo"))}, } - tf.Namespace = "non-default" - buf := bytes.NewBuffer([]byte{}) - buferr := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(tf, buf, buferr) + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + + cmd := NewCmdDescribe("kubectl", tf, streams) cmd.Run(cmd, []string{"type", "foo"}) if d.Name != "foo" || d.Namespace != "" { @@ -58,19 +67,25 @@ func TestDescribeUnknownSchemaObject(t *testing.T) { // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. func TestDescribeUnknownNamespacedSchemaObject(t *testing.T) { d := &testDescriber{Output: "test output"} + oldFn := cmdutil.DescriberFn + defer func() { + cmdutil.DescriberFn = oldFn + }() + cmdutil.DescriberFn = d.describerFor + tf := cmdtesting.NewTestFactory() defer tf.Cleanup() _, _, codec := cmdtesting.NewExternalScheme() - tf.DescriberVal = d tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalNamespacedType("", "", "foo", "non-default"))}, } - tf.Namespace = "non-default" - buf := bytes.NewBuffer([]byte{}) - buferr := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(tf, buf, buferr) + tf.WithNamespace("non-default") + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + + cmd := NewCmdDescribe("kubectl", tf, streams) cmd.Run(cmd, []string{"namespacedtype", "foo"}) if d.Name != "foo" || d.Namespace != "non-default" { @@ -83,13 +98,18 @@ func TestDescribeUnknownNamespacedSchemaObject(t *testing.T) { } func TestDescribeObject(t *testing.T) { + d := &testDescriber{Output: "test output"} + oldFn := cmdutil.DescriberFn + defer func() { + cmdutil.DescriberFn = oldFn + }() + cmdutil.DescriberFn = d.describerFor + _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) - d := &testDescriber{Output: "test output"} - tf.DescriberVal = d tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { @@ -102,11 +122,11 @@ func TestDescribeObject(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - buferr := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(tf, buf, buferr) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + + cmd := NewCmdDescribe("kubectl", tf, streams) + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Run(cmd, []string{}) if d.Name != "redis-master" || d.Namespace != "test" { @@ -119,22 +139,26 @@ func TestDescribeObject(t *testing.T) { } func TestDescribeListObjects(t *testing.T) { + d := &testDescriber{Output: "test output"} + oldFn := cmdutil.DescriberFn + defer func() { + cmdutil.DescriberFn = oldFn + }() + cmdutil.DescriberFn = d.describerFor + pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) - d := &testDescriber{Output: "test output"} - tf.DescriberVal = d tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - buferr := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(tf, buf, buferr) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + + cmd := NewCmdDescribe("kubectl", tf, streams) cmd.Run(cmd, []string{"pods"}) if buf.String() != fmt.Sprintf("%s\n\n%s", d.Output, d.Output) { t.Errorf("unexpected output: %s", buf.String()) @@ -142,22 +166,24 @@ func TestDescribeListObjects(t *testing.T) { } func TestDescribeObjectShowEvents(t *testing.T) { + d := &testDescriber{Output: "test output"} + oldFn := cmdutil.DescriberFn + defer func() { + cmdutil.DescriberFn = oldFn + }() + cmdutil.DescriberFn = d.describerFor + pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) - d := &testDescriber{Output: "test output"} - tf.DescriberVal = d tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - buferr := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(tf, buf, buferr) + cmd := NewCmdDescribe("kubectl", tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("show-events", "true") cmd.Run(cmd, []string{"pods"}) if d.Settings.ShowEvents != true { @@ -166,22 +192,24 @@ func TestDescribeObjectShowEvents(t *testing.T) { } func TestDescribeObjectSkipEvents(t *testing.T) { + d := &testDescriber{Output: "test output"} + oldFn := cmdutil.DescriberFn + defer func() { + cmdutil.DescriberFn = oldFn + }() + cmdutil.DescriberFn = d.describerFor + pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) - d := &testDescriber{Output: "test output"} - tf.DescriberVal = d tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - buferr := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(tf, buf, buferr) + cmd := NewCmdDescribe("kubectl", tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("show-events", "false") cmd.Run(cmd, []string{"pods"}) if d.Settings.ShowEvents != false { @@ -193,9 +221,9 @@ func TestDescribeHelpMessage(t *testing.T) { tf := cmdtesting.NewTestFactory() defer tf.Cleanup() - buf := bytes.NewBuffer([]byte{}) - buferr := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(tf, buf, buferr) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + + cmd := NewCmdDescribe("kubectl", tf, streams) cmd.SetArgs([]string{"-h"}) cmd.SetOutput(buf) _, err := cmd.ExecuteC() @@ -216,3 +244,19 @@ func TestDescribeHelpMessage(t *testing.T) { t.Errorf("Expected not to contain: \n %v\nGot:\n %v\n", unexpected, got) } } + +type testDescriber struct { + Name, Namespace string + Settings printers.DescriberSettings + Output string + Err error +} + +func (t *testDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (output string, err error) { + t.Namespace, t.Name = namespace, name + t.Settings = describerSettings + return t.Output, t.Err +} +func (t *testDescriber) describerFor(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (printers.Describer, error) { + return t, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/diff.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/diff.go index 490db667c..d4cda1261 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/diff.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/diff.go @@ -26,15 +26,18 @@ import ( "github.com/ghodss/yaml" "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/dynamic" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl/apply/parse" "k8s.io/kubernetes/pkg/kubectl/apply/strategy" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/utils/exec" ) @@ -101,12 +104,11 @@ func parseDiffArguments(args []string) (string, string, error) { return from, to, nil } -func NewCmdDiff(f cmdutil.Factory, stdout, stderr io.Writer) *cobra.Command { +func NewCmdDiff(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { var options DiffOptions diff := DiffProgram{ - Exec: exec.New(), - Stdout: stdout, - Stderr: stderr, + Exec: exec.New(), + IOStreams: streams, } cmd := &cobra.Command{ Use: "diff -f FILENAME", @@ -132,9 +134,8 @@ func NewCmdDiff(f cmdutil.Factory, stdout, stderr io.Writer) *cobra.Command { // KUBERNETES_EXTERNAL_DIFF environment variable will be used a diff // program. By default, `diff(1)` will be used. type DiffProgram struct { - Exec exec.Interface - Stdout io.Writer - Stderr io.Writer + Exec exec.Interface + genericclioptions.IOStreams } func (d *DiffProgram) getCommand(args ...string) exec.Cmd { @@ -147,8 +148,8 @@ func (d *DiffProgram) getCommand(args ...string) exec.Cmd { } cmd := d.Exec.Command(diff, args...) - cmd.SetStdout(d.Stdout) - cmd.SetStderr(d.Stderr) + cmd.SetStdout(d.Out) + cmd.SetStderr(d.ErrOut) return cmd } @@ -264,6 +265,7 @@ type Object interface { // InfoObject is an implementation of the Object interface. It gets all // the information from the Info object. type InfoObject struct { + Remote runtime.Unstructured Info *resource.Info Encoder runtime.Encoder Parser *parse.Factory @@ -289,14 +291,10 @@ func (obj InfoObject) Local() (map[string]interface{}, error) { } func (obj InfoObject) Live() (map[string]interface{}, error) { - if obj.Info.Object == nil { + if obj.Remote == nil { return nil, nil // Object doesn't exist on cluster. } - data, err := runtime.Encode(obj.Encoder, obj.Info.Object) - if err != nil { - return nil, err - } - return obj.toMap(data) + return obj.Remote.UnstructuredContent(), nil } func (obj InfoObject) Merged() (map[string]interface{}, error) { @@ -328,10 +326,10 @@ func (obj InfoObject) Merged() (map[string]interface{}, error) { } func (obj InfoObject) Last() (map[string]interface{}, error) { - if obj.Info.Object == nil { + if obj.Remote == nil { return nil, nil // No object is live, return empty } - accessor, err := meta.Accessor(obj.Info.Object) + accessor, err := meta.Accessor(obj.Remote) if err != nil { return nil, err } @@ -391,6 +389,50 @@ func (d *Differ) TearDown() { d.To.Dir.Delete() // Ignore error } +type Downloader struct { + mapper meta.RESTMapper + dclient dynamic.Interface + ns string +} + +func NewDownloader(f cmdutil.Factory) (*Downloader, error) { + var err error + var d Downloader + + d.mapper, err = f.ToRESTMapper() + if err != nil { + return nil, err + } + d.dclient, err = f.DynamicClient() + if err != nil { + return nil, err + } + d.ns, _, _ = f.ToRawKubeConfigLoader().Namespace() + + return &d, nil +} + +func (d *Downloader) Download(info *resource.Info) (*unstructured.Unstructured, error) { + gvk := info.Object.GetObjectKind().GroupVersionKind() + mapping, err := d.mapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, err + } + + var resource dynamic.ResourceInterface + switch mapping.Scope.Name() { + case meta.RESTScopeNameNamespace: + if info.Namespace == "" { + info.Namespace = d.ns + } + resource = d.dclient.Resource(mapping.Resource).Namespace(info.Namespace) + case meta.RESTScopeNameRoot: + resource = d.dclient.Resource(mapping.Resource) + } + + return resource.Get(info.Name, metav1.GetOptions{}) +} + // RunDiff uses the factory to parse file arguments, find the version to // diff, and find each Info object for each files, and runs against the // differ. @@ -409,7 +451,7 @@ func RunDiff(f cmdutil.Factory, diff *DiffProgram, options *DiffOptions, from, t printer := Printer{} - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -418,25 +460,26 @@ func RunDiff(f cmdutil.Factory, diff *DiffProgram, options *DiffOptions, from, t Unstructured(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &options.FilenameOptions). + Local(). Flatten(). Do() if err := r.Err(); err != nil { return err } + dl, err := NewDownloader(f) + if err != nil { + return err + } + err = r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } - if err := info.Get(); err != nil { - if !errors.IsNotFound(err) { - return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) - } - info.Object = nil - } - + remote, _ := dl.Download(info) obj := InfoObject{ + Remote: remote, Info: info, Parser: parser, Encoder: cmdutil.InternalVersionJSONEncoder(), diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/diff_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/diff_test.go index 4400023ff..302e69e5a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/diff_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/diff_test.go @@ -25,6 +25,7 @@ import ( "strings" "testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/utils/exec" ) @@ -137,11 +138,10 @@ func TestArguments(t *testing.T) { func TestDiffProgram(t *testing.T) { os.Setenv("KUBERNETES_EXTERNAL_DIFF", "echo") - stdout := bytes.Buffer{} + streams, _, stdout, _ := genericclioptions.NewTestIOStreams() diff := DiffProgram{ - Stdout: &stdout, - Stderr: &bytes.Buffer{}, - Exec: exec.New(), + IOStreams: streams, + Exec: exec.New(), } err := diff.Run("one", "two") if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/drain.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/drain.go index 235089c62..8c0baf5b5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/drain.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/drain.go @@ -19,7 +19,6 @@ package cmd import ( "errors" "fmt" - "io" "math" "strings" "time" @@ -30,7 +29,6 @@ import ( corev1 "k8s.io/api/core/v1" policyv1beta1 "k8s.io/api/policy/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" @@ -43,17 +41,24 @@ import ( "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) type DrainOptions struct { + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinterFunc, error) + + Namespace string client kubernetes.Interface restClient *restclient.RESTClient - Factory cmdutil.Factory Force bool DryRun bool GracePeriodSeconds int @@ -63,11 +68,10 @@ type DrainOptions struct { DeleteLocalData bool Selector string PodSelector string - mapper meta.RESTMapper nodeInfos []*resource.Info - Out io.Writer - ErrOut io.Writer typer runtime.ObjectTyper + + genericclioptions.IOStreams } // Takes a pod and returns a bool indicating whether or not to operate on the @@ -101,8 +105,12 @@ var ( kubectl cordon foo`)) ) -func NewCmdCordon(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &DrainOptions{Factory: f, Out: out} +func NewCmdCordon(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &DrainOptions{ + PrintFlags: genericclioptions.NewPrintFlags("cordoned").WithTypeSetter(scheme.Scheme), + + IOStreams: ioStreams, + } cmd := &cobra.Command{ Use: "cordon NODE", @@ -111,7 +119,7 @@ func NewCmdCordon(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: cordon_long, Example: cordon_example, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.SetupDrain(cmd, args)) + cmdutil.CheckErr(options.Complete(f, cmd, args)) cmdutil.CheckErr(options.RunCordonOrUncordon(true)) }, } @@ -129,8 +137,11 @@ var ( $ kubectl uncordon foo`)) ) -func NewCmdUncordon(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &DrainOptions{Factory: f, Out: out} +func NewCmdUncordon(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := &DrainOptions{ + PrintFlags: genericclioptions.NewPrintFlags("uncordoned").WithTypeSetter(scheme.Scheme), + IOStreams: ioStreams, + } cmd := &cobra.Command{ Use: "uncordon NODE", @@ -139,7 +150,7 @@ func NewCmdUncordon(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: uncordon_long, Example: uncordon_example, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.SetupDrain(cmd, args)) + cmdutil.CheckErr(options.Complete(f, cmd, args)) cmdutil.CheckErr(options.RunCordonOrUncordon(false)) }, } @@ -182,8 +193,18 @@ var ( $ kubectl drain foo --grace-period=900`)) ) -func NewCmdDrain(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - options := &DrainOptions{Factory: f, Out: out, ErrOut: errOut, backOff: clockwork.NewRealClock()} +func NewDrainOptions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *DrainOptions { + return &DrainOptions{ + PrintFlags: genericclioptions.NewPrintFlags("drained").WithTypeSetter(scheme.Scheme), + + IOStreams: ioStreams, + backOff: clockwork.NewRealClock(), + GracePeriodSeconds: -1, + } +} + +func NewCmdDrain(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := NewDrainOptions(f, ioStreams) cmd := &cobra.Command{ Use: "drain NODE", @@ -192,15 +213,15 @@ func NewCmdDrain(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { Long: drain_long, Example: drain_example, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.SetupDrain(cmd, args)) + cmdutil.CheckErr(options.Complete(f, cmd, args)) cmdutil.CheckErr(options.RunDrain()) }, } - cmd.Flags().BoolVar(&options.Force, "force", false, "Continue even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet.") - cmd.Flags().BoolVar(&options.IgnoreDaemonsets, "ignore-daemonsets", false, "Ignore DaemonSet-managed pods.") - cmd.Flags().BoolVar(&options.DeleteLocalData, "delete-local-data", false, "Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained).") - cmd.Flags().IntVar(&options.GracePeriodSeconds, "grace-period", -1, "Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used.") - cmd.Flags().DurationVar(&options.Timeout, "timeout", 0, "The length of time to wait before giving up, zero means infinite") + cmd.Flags().BoolVar(&options.Force, "force", options.Force, "Continue even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet.") + cmd.Flags().BoolVar(&options.IgnoreDaemonsets, "ignore-daemonsets", options.IgnoreDaemonsets, "Ignore DaemonSet-managed pods.") + cmd.Flags().BoolVar(&options.DeleteLocalData, "delete-local-data", options.DeleteLocalData, "Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained).") + cmd.Flags().IntVar(&options.GracePeriodSeconds, "grace-period", options.GracePeriodSeconds, "Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used.") + cmd.Flags().DurationVar(&options.Timeout, "timeout", options.Timeout, "The length of time to wait before giving up, zero means infinite") cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on") cmd.Flags().StringVarP(&options.PodSelector, "pod-selector", "", options.PodSelector, "Label selector to filter pods on the node") @@ -208,11 +229,10 @@ func NewCmdDrain(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { return cmd } -// SetupDrain populates some fields from the factory, grabs command line +// Complete populates some fields from the factory, grabs command line // arguments and looks up the node using Builder -func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error { +func (o *DrainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { var err error - o.Selector = cmdutil.GetFlagString(cmd, "selector") if len(args) == 0 && !cmd.Flags().Changed("selector") { return cmdutil.UsageErrorf(cmd, fmt.Sprintf("USAGE: %s [flags]", cmd.Use)) @@ -226,7 +246,7 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error { o.DryRun = cmdutil.GetDryRunFlag(cmd) - if o.client, err = o.Factory.KubernetesClientSet(); err != nil { + if o.client, err = f.KubernetesClientSet(); err != nil { return err } @@ -236,21 +256,35 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error { } } - o.restClient, err = o.Factory.RESTClient() + o.restClient, err = f.RESTClient() if err != nil { return err } o.nodeInfos = []*resource.Info{} - cmdNamespace, _, err := o.Factory.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - builder := o.Factory.NewBuilder(). - Internal(). - NamespaceParam(cmdNamespace).DefaultNamespace(). + o.ToPrinter = func(operation string) (printers.ResourcePrinterFunc, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return nil, err + } + + return printer.PrintObj, nil + } + + builder := f.NewBuilder(). + WithScheme(legacyscheme.Scheme). + NamespaceParam(o.Namespace).DefaultNamespace(). ResourceNames("nodes", args...). SingleResourceType(). Flatten() @@ -270,7 +304,7 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error { if err != nil { return err } - if info.Mapping.Resource != "nodes" { + if info.Mapping.Resource.GroupResource() != (schema.GroupResource{Group: "", Resource: "nodes"}) { return fmt.Errorf("error: expected resource of type node, got %q", info.Mapping.Resource) } @@ -285,6 +319,11 @@ func (o *DrainOptions) RunDrain() error { return err } + printObj, err := o.ToPrinter("drained") + if err != nil { + return err + } + drainedNodes := sets.NewString() var fatal error @@ -295,7 +334,7 @@ func (o *DrainOptions) RunDrain() error { } if err == nil || o.DryRun { drainedNodes.Insert(info.Name) - cmdutil.PrintSuccess(false, o.Out, info.Object, o.DryRun, "drained") + printObj(info.Object, o.Out) } else { fmt.Fprintf(o.ErrOut, "error: unable to drain node %q, aborting command...\n\n", info.Name) remainingNodes := []string{} @@ -554,7 +593,7 @@ func (o *DrainOptions) evictPods(pods []corev1.Pod, policyGroupVersion string, g } } podArray := []corev1.Pod{pod} - _, err = o.waitForDelete(podArray, kubectl.Interval, time.Duration(math.MaxInt64), true, getPodFn) + _, err = o.waitForDelete(podArray, 1*time.Second, time.Duration(math.MaxInt64), true, getPodFn) if err == nil { doneCh <- true } else { @@ -600,7 +639,7 @@ func (o *DrainOptions) deletePods(pods []corev1.Pod, getPodFn func(namespace, na return err } } - _, err := o.waitForDelete(pods, kubectl.Interval, globalTimeout, false, getPodFn) + _, err := o.waitForDelete(pods, 1*time.Second, globalTimeout, false, getPodFn) return err } @@ -611,12 +650,17 @@ func (o *DrainOptions) waitForDelete(pods []corev1.Pod, interval, timeout time.D } else { verbStr = "deleted" } - err := wait.PollImmediate(interval, timeout, func() (bool, error) { + printObj, err := o.ToPrinter(verbStr) + if err != nil { + return pods, err + } + + err = wait.PollImmediate(interval, timeout, func() (bool, error) { pendingPods := []corev1.Pod{} for i, pod := range pods { p, err := getPodFn(pod.Namespace, pod.Name) if apierrors.IsNotFound(err) || (p != nil && p.ObjectMeta.UID != pod.ObjectMeta.UID) { - cmdutil.PrintSuccess(false, o.Out, &pod, false, verbStr) + printObj(&pod, o.Out) continue } else if err != nil { return false, err @@ -668,11 +712,6 @@ func SupportEviction(clientset kubernetes.Interface) (string, error) { // RunCordonOrUncordon runs either Cordon or Uncordon. The desired value for // "Unschedulable" is passed as the first arg. func (o *DrainOptions) RunCordonOrUncordon(desired bool) error { - cmdNamespace, _, err := o.Factory.DefaultNamespace() - if err != nil { - return err - } - cordonOrUncordon := "cordon" if !desired { cordonOrUncordon = "un" + cordonOrUncordon @@ -680,7 +719,7 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error { for _, nodeInfo := range o.nodeInfos { if nodeInfo.Mapping.GroupVersionKind.Kind == "Node" { - obj, err := nodeInfo.Mapping.ConvertToVersion(nodeInfo.Object, nodeInfo.Mapping.GroupVersionKind.GroupVersion()) + obj, err := legacyscheme.Scheme.ConvertToVersion(nodeInfo.Object, nodeInfo.Mapping.GroupVersionKind.GroupVersion()) if err != nil { fmt.Printf("error: unable to %s node %q: %v", cordonOrUncordon, nodeInfo.Name, err) continue @@ -697,7 +736,12 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error { } unsched := node.Spec.Unschedulable if unsched == desired { - cmdutil.PrintSuccess(false, o.Out, nodeInfo.Object, o.DryRun, already(desired)) + printObj, err := o.ToPrinter(already(desired)) + if err != nil { + fmt.Printf("error: %v", err) + continue + } + printObj(cmdutil.AsDefaultVersionedOrOriginal(nodeInfo.Object, nodeInfo.Mapping), o.Out) } else { if !o.DryRun { helper := resource.NewHelper(o.restClient, nodeInfo.Mapping) @@ -712,16 +756,26 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error { fmt.Printf("error: unable to %s node %q: %v", cordonOrUncordon, nodeInfo.Name, err) continue } - _, err = helper.Patch(cmdNamespace, nodeInfo.Name, types.StrategicMergePatchType, patchBytes) + _, err = helper.Patch(o.Namespace, nodeInfo.Name, types.StrategicMergePatchType, patchBytes) if err != nil { fmt.Printf("error: unable to %s node %q: %v", cordonOrUncordon, nodeInfo.Name, err) continue } } - cmdutil.PrintSuccess(false, o.Out, nodeInfo.Object, o.DryRun, changed(desired)) + printObj, err := o.ToPrinter(changed(desired)) + if err != nil { + fmt.Fprintf(o.ErrOut, "%v", err) + continue + } + printObj(cmdutil.AsDefaultVersionedOrOriginal(nodeInfo.Object, nodeInfo.Mapping), o.Out) } } else { - cmdutil.PrintSuccess(false, o.Out, nodeInfo.Object, o.DryRun, "skipped") + printObj, err := o.ToPrinter("skipped") + if err != nil { + fmt.Fprintf(o.ErrOut, "%v", err) + continue + } + printObj(cmdutil.AsDefaultVersionedOrOriginal(nodeInfo.Object, nodeInfo.Mapping), o.Out) } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/drain_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/drain_test.go index f06a60053..6b602ed87 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/drain_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/drain_test.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "bytes" "errors" "fmt" "io" @@ -32,6 +31,7 @@ import ( "time" "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" corev1 "k8s.io/api/core/v1" policyv1beta1 "k8s.io/api/policy/v1beta1" @@ -50,6 +50,7 @@ import ( "k8s.io/kubernetes/pkg/apis/extensions" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -70,9 +71,6 @@ func TestMain(m *testing.M) { Name: "node", CreationTimestamp: metav1.Time{Time: time.Now()}, }, - Spec: corev1.NodeSpec{ - ExternalID: "node", - }, Status: corev1.NodeStatus{}, } @@ -87,7 +85,7 @@ func TestCordon(t *testing.T) { description string node *corev1.Node expected *corev1.Node - cmd func(cmdutil.Factory, io.Writer) *cobra.Command + cmd func(cmdutil.Factory, genericclioptions.IOStreams) *cobra.Command arg string expectFatal bool }{ @@ -154,13 +152,13 @@ func TestCordon(t *testing.T) { tf := cmdtesting.NewTestFactory() defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs new_node := &corev1.Node{} updated := false tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, NegotiatedSerializer: ns, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { m := &MyReq{req} @@ -199,8 +197,8 @@ func TestCordon(t *testing.T) { } tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := test.cmd(tf, buf) + ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() + cmd := test.cmd(tf, ioStreams) saw_fatal := false func() { @@ -608,11 +606,11 @@ func TestDrain(t *testing.T) { tf := cmdtesting.NewTestFactory() defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, NegotiatedSerializer: ns, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { m := &MyReq{req} @@ -709,9 +707,8 @@ func TestDrain(t *testing.T) { } tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdDrain(tf, buf, errBuf) + ioStreams, _, _, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdDrain(tf, ioStreams) saw_fatal := false fatal_msg := "" @@ -836,9 +833,17 @@ func TestDeletePods(t *testing.T) { tf := cmdtesting.NewTestFactory() defer tf.Cleanup() - o := DrainOptions{Factory: tf} - o.mapper, _ = tf.Object() + o := DrainOptions{ + PrintFlags: genericclioptions.NewPrintFlags("drained").WithTypeSetter(scheme.Scheme), + } o.Out = os.Stdout + + o.ToPrinter = func(operation string) (printers.ResourcePrinterFunc, error) { + return func(obj runtime.Object, out io.Writer) error { + return nil + }, nil + } + _, pods := createPods(false) pendingPods, err := o.waitForDelete(pods, test.interval, test.timeout, false, test.getPodFn) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/edit.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/edit.go index 212ce13b9..4789082b0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/edit.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/edit.go @@ -18,15 +18,13 @@ package cmd import ( "fmt" - "io" - "runtime" "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -69,13 +67,9 @@ var ( kubectl edit deployment/mydeployment -o yaml --save-config`)) ) -func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - options := &editor.EditOptions{ - EditMode: editor.NormalEditMode, - ValidateOptions: cmdutil.ValidateOptions{EnableValidation: true}, - Include3rdParty: true, - } - validArgs := cmdutil.ValidArgList(f) +func NewCmdEdit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := editor.NewEditOptions(editor.NormalEditMode, ioStreams) + o.ValidateOptions = cmdutil.ValidateOptions{EnableValidation: true} cmd := &cobra.Command{ Use: "edit (RESOURCE/NAME | -f FILENAME)", @@ -84,29 +78,27 @@ func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { Long: editLong, Example: fmt.Sprintf(editExample), Run: func(cmd *cobra.Command, args []string) { - options.ChangeCause = f.Command(cmd, false) - if err := options.Complete(f, out, errOut, args, cmd); err != nil { + if err := o.Complete(f, args, cmd); err != nil { cmdutil.CheckErr(err) } - if err := options.Run(); err != nil { + if err := o.Run(); err != nil { cmdutil.CheckErr(err) } }, - ValidArgs: validArgs, - ArgAliases: kubectl.ResourceAliases(validArgs), } - usage := "to use to edit the resource" - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) - cmdutil.AddValidateOptionFlags(cmd, &options.ValidateOptions) - cmd.Flags().StringVarP(&options.Output, "output", "o", "yaml", "Output format. One of: yaml|json.") - cmd.Flags().BoolVarP(&options.OutputPatch, "output-patch", "", false, "Output the patch if the resource is edited.") - cmd.Flags().BoolVar(&options.WindowsLineEndings, "windows-line-endings", runtime.GOOS == "windows", + // bind flag structs + o.RecordFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) + + usage := "to use to edit the resource" + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmdutil.AddValidateOptionFlags(cmd, &o.ValidateOptions) + cmd.Flags().BoolVarP(&o.OutputPatch, "output-patch", "", o.OutputPatch, "Output the patch if the resource is edited.") + cmd.Flags().BoolVar(&o.WindowsLineEndings, "windows-line-endings", o.WindowsLineEndings, "Defaults to the line ending native to your platform.") - cmdutil.AddApplyAnnotationVarFlags(cmd, &options.ApplyAnnotation) - cmdutil.AddRecordVarFlag(cmd, &options.Record) - cmdutil.AddInclude3rdPartyVarFlags(cmd, &options.Include3rdParty) + cmdutil.AddApplyAnnotationVarFlags(cmd, &o.ApplyAnnotation) cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/edit_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/edit_test.go index fddc0c7e4..6820d64e7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/edit_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/edit_test.go @@ -32,13 +32,15 @@ import ( yaml "gopkg.in/yaml.v2" - "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/kubectl/cmd/create" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" ) type EditTestCase struct { @@ -209,12 +211,12 @@ func TestEdit(t *testing.T) { tf := cmdtesting.NewTestFactory() defer tf.Cleanup() - tf.UnstructuredClientForMappingFunc = func(mapping *meta.RESTMapping) (resource.RESTClient, error) { + tf.UnstructuredClientForMappingFunc = func(gv schema.GroupVersion) (resource.RESTClient, error) { versionedAPIPath := "" - if mapping.GroupVersionKind.Group == "" { - versionedAPIPath = "/api/" + mapping.GroupVersionKind.Version + if gv.Group == "" { + versionedAPIPath = "/api/" + gv.Version } else { - versionedAPIPath = "/apis/" + mapping.GroupVersionKind.Group + "/" + mapping.GroupVersionKind.Version + versionedAPIPath = "/apis/" + gv.Group + "/" + gv.Version } return &fake.RESTClient{ VersionedAPIPath: versionedAPIPath, @@ -222,24 +224,19 @@ func TestEdit(t *testing.T) { Client: fake.CreateHTTPClient(reqResp), }, nil } - - if len(testcase.Namespace) > 0 { - tf.Namespace = testcase.Namespace - } + tf.WithNamespace(testcase.Namespace) tf.ClientConfigVal = defaultClientConfig() - tf.CommandVal = "edit test cmd invocation" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() var cmd *cobra.Command switch testcase.Mode { case "edit": - cmd = NewCmdEdit(tf, buf, errBuf) + cmd = NewCmdEdit(tf, ioStreams) case "create": - cmd = NewCmdCreate(tf, buf, errBuf) + cmd = create.NewCmdCreate(tf, ioStreams) cmd.Flags().Set("edit", "true") case "edit-last-applied": - cmd = NewCmdApplyEditLastApplied(tf, buf, errBuf) + cmd = NewCmdApplyEditLastApplied(tf, ioStreams) default: t.Fatalf("%s: unexpected mode %s", name, testcase.Mode) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/exec.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/exec.go index 671d66f47..5290b0fd2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/exec.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/exec.go @@ -32,6 +32,7 @@ import ( coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/term" "k8s.io/kubernetes/pkg/util/interrupt" @@ -62,12 +63,10 @@ const ( execUsageStr = "expected 'exec POD_NAME COMMAND [ARG1] [ARG2] ... [ARGN]'.\nPOD_NAME and COMMAND are required arguments for the exec command" ) -func NewCmdExec(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command { +func NewCmdExec(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { options := &ExecOptions{ StreamOptions: StreamOptions{ - In: cmdIn, - Out: cmdOut, - Err: cmdErr, + IOStreams: streams, }, Executor: &DefaultRemoteExecutor{}, @@ -85,11 +84,11 @@ func NewCmdExec(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c cmdutil.CheckErr(options.Run()) }, } - cmd.Flags().StringVarP(&options.PodName, "pod", "p", "", "Pod name") + cmd.Flags().StringVarP(&options.PodName, "pod", "p", options.PodName, "Pod name") // TODO support UID - cmd.Flags().StringVarP(&options.ContainerName, "container", "c", "", "Container name. If omitted, the first container in the pod will be chosen") - cmd.Flags().BoolVarP(&options.Stdin, "stdin", "i", false, "Pass stdin to the container") - cmd.Flags().BoolVarP(&options.TTY, "tty", "t", false, "Stdin is a TTY") + cmd.Flags().StringVarP(&options.ContainerName, "container", "c", options.ContainerName, "Container name. If omitted, the first container in the pod will be chosen") + cmd.Flags().BoolVarP(&options.Stdin, "stdin", "i", options.Stdin, "Pass stdin to the container") + cmd.Flags().BoolVarP(&options.TTY, "tty", "t", options.TTY, "Stdin is a TTY") return cmd } @@ -125,9 +124,8 @@ type StreamOptions struct { Quiet bool // InterruptParent, if set, is used to handle interrupts while attached InterruptParent *interrupt.Handler - In io.Reader - Out io.Writer - Err io.Writer + + genericclioptions.IOStreams // for testing overrideStreams func() (io.ReadCloser, io.Writer, io.Writer) @@ -155,7 +153,7 @@ func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []s return cmdutil.UsageErrorf(cmd, execUsageStr) } if len(p.PodName) != 0 { - printDeprecationWarning(p.Err, "exec POD_NAME", "-p POD_NAME") + printDeprecationWarning(p.ErrOut, "exec POD_NAME", "-p POD_NAME") if len(argsIn) < 1 { return cmdutil.UsageErrorf(cmd, execUsageStr) } @@ -168,7 +166,7 @@ func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []s } } - namespace, _, err := f.DefaultNamespace() + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -182,7 +180,7 @@ func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []s p.SuggestedCmdUsage = fmt.Sprintf("Use '%s describe pod/%s -n %s' to see all of the containers in this pod.", p.FullCmdName, p.PodName, p.Namespace) } - config, err := f.ClientConfig() + config, err := f.ToRESTConfig() if err != nil { return err } @@ -205,7 +203,7 @@ func (p *ExecOptions) Validate() error { if len(p.Command) == 0 { return fmt.Errorf("you must specify at least one command for the container") } - if p.Out == nil || p.Err == nil { + if p.Out == nil || p.ErrOut == nil { return fmt.Errorf("both output and error output must be provided") } if p.Executor == nil || p.PodClient == nil || p.Config == nil { @@ -240,8 +238,8 @@ func (o *StreamOptions) setupTTY() term.TTY { if !o.isTerminalIn(t) { o.TTY = false - if o.Err != nil { - fmt.Fprintln(o.Err, "Unable to use a TTY - input is not a terminal or the right kind of file") + if o.ErrOut != nil { + fmt.Fprintln(o.ErrOut, "Unable to use a TTY - input is not a terminal or the right kind of file") } return t @@ -284,7 +282,7 @@ func (p *ExecOptions) Run() error { if len(p.SuggestedCmdUsage) > 0 { usageString = fmt.Sprintf("%s\n%s", usageString, p.SuggestedCmdUsage) } - fmt.Fprintf(p.Err, "%s\n", usageString) + fmt.Fprintf(p.ErrOut, "%s\n", usageString) } containerName = pod.Spec.Containers[0].Name } @@ -299,7 +297,7 @@ func (p *ExecOptions) Run() error { // unset p.Err if it was previously set because both stdout and stderr go over p.Out when tty is // true - p.Err = nil + p.ErrOut = nil } fn := func() error { @@ -320,11 +318,11 @@ func (p *ExecOptions) Run() error { Command: p.Command, Stdin: p.Stdin, Stdout: p.Out != nil, - Stderr: p.Err != nil, + Stderr: p.ErrOut != nil, TTY: t.Raw, }, legacyscheme.ParameterCodec) - return p.Executor.Execute("POST", req.URL(), p.Config, p.In, p.Out, p.Err, t.Raw, sizeQueue) + return p.Executor.Execute("POST", req.URL(), p.Config, p.In, p.Out, p.ErrOut, t.Raw, sizeQueue) } if err := t.Safe(fn); err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/exec_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/exec_test.go index c80daabc0..187c6ff8f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/exec_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/exec_test.go @@ -36,6 +36,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/term" ) @@ -131,7 +132,7 @@ func TestPodAndContainer(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() ns := legacyscheme.Codecs @@ -140,12 +141,11 @@ func TestPodAndContainer(t *testing.T) { NegotiatedSerializer: ns, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() cmd := &cobra.Command{} options := test.p - options.Err = bytes.NewBuffer([]byte{}) + options.ErrOut = bytes.NewBuffer([]byte{}) err := options.Complete(tf, cmd, test.args, test.argsLenAtDash) if test.expectError && err == nil { t.Errorf("%s: unexpected non-error", test.name) @@ -192,10 +192,10 @@ func TestExec(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -206,17 +206,12 @@ func TestExec(t *testing.T) { body := objBody(codec, test.pod) return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil default: - // Ensures no GET is performed when deleting by name t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) return nil, fmt.Errorf("unexpected request") } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - bufOut := bytes.NewBuffer([]byte{}) - bufErr := bytes.NewBuffer([]byte{}) - bufIn := bytes.NewBuffer([]byte{}) ex := &fakeRemoteExecutor{} if test.execErr { ex.execErr = fmt.Errorf("exec error") @@ -225,9 +220,7 @@ func TestExec(t *testing.T) { StreamOptions: StreamOptions{ PodName: "foo", ContainerName: "bar", - In: bufIn, - Out: bufOut, - Err: bufErr, + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), }, Executor: ex, } @@ -278,16 +271,14 @@ func execPod() *api.Pod { } func TestSetupTTY(t *testing.T) { - stderr := &bytes.Buffer{} + streams, _, _, stderr := genericclioptions.NewTestIOStreams() // test 1 - don't attach stdin o := &StreamOptions{ // InterruptParent: , - Stdin: false, - In: &bytes.Buffer{}, - Out: &bytes.Buffer{}, - Err: stderr, - TTY: true, + Stdin: false, + IOStreams: streams, + TTY: true, } tty := o.setupTTY() @@ -335,7 +326,7 @@ func TestSetupTTY(t *testing.T) { // test 3 - request a TTY, but stdin is not a terminal o.Stdin = true o.In = &bytes.Buffer{} - o.Err = stderr + o.ErrOut = stderr o.TTY = true tty = o.setupTTY() diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/explain.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/explain.go index 15463a945..d85c240cf 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/explain.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/explain.go @@ -18,14 +18,16 @@ package cmd import ( "fmt" - "io" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" "k8s.io/kubernetes/pkg/kubectl/explain" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -49,43 +51,79 @@ var ( kubectl explain pods.spec.containers`)) ) +type ExplainOptions struct { + genericclioptions.IOStreams + + CmdParent string + ApiVersion string + Recursive bool + + Mapper meta.RESTMapper + Schema openapi.Resources +} + +func NewExplainOptions(parent string, streams genericclioptions.IOStreams) *ExplainOptions { + return &ExplainOptions{ + IOStreams: streams, + CmdParent: parent, + } +} + // NewCmdExplain returns a cobra command for swagger docs -func NewCmdExplain(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { +func NewCmdExplain(parent string, f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewExplainOptions(parent, streams) + cmd := &cobra.Command{ Use: "explain RESOURCE", DisableFlagsInUseLine: true, Short: i18n.T("Documentation of resources"), - Long: explainLong + "\n\n" + cmdutil.ValidResourceTypeList(f), + Long: explainLong + "\n\n" + cmdutil.SuggestApiResources(parent), Example: explainExamples, Run: func(cmd *cobra.Command, args []string) { - err := RunExplain(f, out, cmdErr, cmd, args) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd)) + cmdutil.CheckErr(o.Validate(args)) + cmdutil.CheckErr(o.Run(args)) }, } - cmd.Flags().Bool("recursive", false, "Print the fields of fields (Currently only 1 level deep)") - cmd.Flags().String("api-version", "", "Get different explanations for particular API version") - cmdutil.AddInclude3rdPartyFlags(cmd) + cmd.Flags().BoolVar(&o.Recursive, "recursive", o.Recursive, "Print the fields of fields (Currently only 1 level deep)") + cmd.Flags().StringVar(&o.ApiVersion, "api-version", o.ApiVersion, "Get different explanations for particular API version") return cmd } -// RunExplain executes the appropriate steps to print a model's documentation -func RunExplain(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string) error { +func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { + var err error + o.Mapper, err = f.ToRESTMapper() + if err != nil { + return err + } + + o.Schema, err = f.OpenAPISchema() + if err != nil { + return err + } + return nil +} + +func (o *ExplainOptions) Validate(args []string) error { if len(args) == 0 { - fmt.Fprintf(cmdErr, "You must specify the type of resource to explain. %s\n", cmdutil.ValidResourceTypeList(f)) - return cmdutil.UsageErrorf(cmd, "Required resource not specified.") + return fmt.Errorf("You must specify the type of resource to explain. %s\n", cmdutil.SuggestApiResources(o.CmdParent)) } if len(args) > 1 { - return cmdutil.UsageErrorf(cmd, "We accept only this format: explain RESOURCE") + return fmt.Errorf("We accept only this format: explain RESOURCE\n") } - recursive := cmdutil.GetFlagBool(cmd, "recursive") - apiVersionString := cmdutil.GetFlagString(cmd, "api-version") + return nil +} + +// Run executes the appropriate steps to print a model's documentation +func (o *ExplainOptions) Run(args []string) error { + recursive := o.Recursive + apiVersionString := o.ApiVersion - mapper, _ := f.Object() // TODO: After we figured out the new syntax to separate group and resource, allow // the users to use it in explain (kubectl explain ). // Refer to issue #16039 for why we do this. Refer to PR #15808 that used "/" syntax. - inModel, fieldsPath, err := explain.SplitAndParseResourceRequest(args[0], mapper) + inModel, fieldsPath, err := explain.SplitAndParseResourceRequest(args[0], o.Mapper) if err != nil { return err } @@ -94,10 +132,10 @@ func RunExplain(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, ar fullySpecifiedGVR, groupResource := schema.ParseResourceArg(inModel) gvk := schema.GroupVersionKind{} if fullySpecifiedGVR != nil { - gvk, _ = mapper.KindFor(*fullySpecifiedGVR) + gvk, _ = o.Mapper.KindFor(*fullySpecifiedGVR) } if gvk.Empty() { - gvk, err = mapper.KindFor(groupResource.WithVersion("")) + gvk, err = o.Mapper.KindFor(groupResource.WithVersion("")) if err != nil { return err } @@ -111,15 +149,10 @@ func RunExplain(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, ar gvk = apiVersion.WithKind(gvk.Kind) } - resources, err := f.OpenAPISchema() - if err != nil { - return err - } - - schema := resources.LookupResource(gvk) + schema := o.Schema.LookupResource(gvk) if schema == nil { return fmt.Errorf("Couldn't find resource for %q", gvk) } - return explain.PrintModelDescription(fieldsPath, out, schema, gvk, recursive) + return explain.PrintModelDescription(fieldsPath, o.Out, schema, gvk, recursive) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/expose.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/expose.go index c511215ad..f0e309eb7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/expose.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/expose.go @@ -17,18 +17,27 @@ limitations under the License. package cmd import ( - "io" "regexp" "strings" + "github.com/golang/glog" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation" + "k8s.io/client-go/dynamic" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -72,8 +81,44 @@ var ( kubectl expose deployment nginx --port=80 --target-port=8000`)) ) -func NewCmdExposeService(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &resource.FilenameOptions{} +type ExposeServiceOptions struct { + FilenameOptions resource.FilenameOptions + RecordFlags *genericclioptions.RecordFlags + PrintFlags *genericclioptions.PrintFlags + PrintObj printers.ResourcePrinterFunc + + DryRun bool + EnforceNamespace bool + + Generators func(string) map[string]kubectl.Generator + CanBeExposed polymorphichelpers.CanBeExposedFunc + ClientForMapping func(*meta.RESTMapping) (resource.RESTClient, error) + MapBasedSelectorForObject func(runtime.Object) (string, error) + PortsForObject polymorphichelpers.PortsForObjectFunc + ProtocolsForObject func(runtime.Object) (map[string]string, error) + + Namespace string + Mapper meta.RESTMapper + + DynamicClient dynamic.Interface + Builder *resource.Builder + + Recorder genericclioptions.Recorder + genericclioptions.IOStreams +} + +func NewExposeServiceOptions(ioStreams genericclioptions.IOStreams) *ExposeServiceOptions { + return &ExposeServiceOptions{ + RecordFlags: genericclioptions.NewRecordFlags(), + PrintFlags: genericclioptions.NewPrintFlags("exposed").WithTypeSetter(scheme.Scheme), + + Recorder: genericclioptions.NoopRecorder{}, + IOStreams: ioStreams, + } +} + +func NewCmdExposeService(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewExposeServiceOptions(streams) validArgs := []string{} resources := regexp.MustCompile(`\s*,`).Split(exposeResources, -1) @@ -88,13 +133,15 @@ func NewCmdExposeService(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: exposeLong, Example: exposeExample, Run: func(cmd *cobra.Command, args []string) { - err := RunExpose(f, out, cmd, args, options) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd)) + cmdutil.CheckErr(o.RunExpose(cmd, args)) }, - ValidArgs: validArgs, - ArgAliases: kubectl.ResourceAliases(validArgs), + ValidArgs: validArgs, } - cmdutil.AddPrinterFlags(cmd) + + o.RecordFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) + cmd.Flags().String("generator", "service/v2", i18n.T("The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.")) cmd.Flags().String("protocol", "", i18n.T("The network protocol for the service to be created. Default is 'TCP'.")) cmd.Flags().String("port", "", i18n.T("The port that the service should serve on. Copied from the resource being exposed, if unspecified")) @@ -112,36 +159,73 @@ func NewCmdExposeService(f cmdutil.Factory, out io.Writer) *cobra.Command { cmd.Flags().String("cluster-ip", "", i18n.T("ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.")) usage := "identifying the resource to expose a service" - cmdutil.AddFilenameOptionFlags(cmd, options, usage) + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) cmdutil.AddDryRunFlag(cmd) cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) return cmd } -func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { - namespace, enforceNamespace, err := f.DefaultNamespace() +func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { + o.DryRun = cmdutil.GetDryRunFlag(cmd) + + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObj = printer.PrintObj + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + + o.DynamicClient, err = f.DynamicClient() + if err != nil { + return err + } + + o.Generators = cmdutil.GeneratorFn + o.Builder = f.NewBuilder() + o.CanBeExposed = polymorphichelpers.CanBeExposedFn + o.ClientForMapping = f.ClientForMapping + o.MapBasedSelectorForObject = polymorphichelpers.MapBasedSelectorForObjectFn + o.ProtocolsForObject = polymorphichelpers.ProtocolsForObjectFn + o.PortsForObject = polymorphichelpers.PortsForObjectFn + + o.Mapper, err = f.ToRESTMapper() + if err != nil { + return err + } + + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - mapper, typer := f.Object() - r := f.NewBuilder(). - Internal(). + return err +} + +func (o *ExposeServiceOptions) RunExpose(cmd *cobra.Command, args []string) error { + r := o.Builder. + WithScheme(legacyscheme.Scheme). ContinueOnError(). - NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.EnforceNamespace, &o.FilenameOptions). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() - err = r.Err() + err := r.Err() if err != nil { return cmdutil.UsageErrorf(cmd, err.Error()) } // Get the generator, setup and validate all required parameters generatorName := cmdutil.GetFlagString(cmd, "generator") - generators := f.Generators("expose") + generators := o.Generators("expose") generator, found := generators[generatorName] if !found { return cmdutil.UsageErrorf(cmd, "generator %q not found.", generatorName) @@ -154,7 +238,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri } mapping := info.ResourceMapping() - if err := f.CanBeExposed(mapping.GroupVersionKind.GroupKind()); err != nil { + if err := o.CanBeExposed(mapping.GroupVersionKind.GroupKind()); err != nil { return err } @@ -168,7 +252,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri // For objects that need a pod selector, derive it from the exposed object in case a user // didn't explicitly specify one via --selector if s, found := params["selector"]; found && kubectl.IsZero(s) { - s, err := f.MapBasedSelectorForObject(info.Object) + s, err := o.MapBasedSelectorForObject(info.Object) if err != nil { return cmdutil.UsageErrorf(cmd, "couldn't retrieve selectors via --selector flag or introspection: %v", err) } @@ -180,7 +264,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri // For objects that need a port, derive it from the exposed object in case a user // didn't explicitly specify one via --port if port, found := params["port"]; found && kubectl.IsZero(port) { - ports, err := f.PortsForObject(info.Object) + ports, err := o.PortsForObject(info.Object) if err != nil { return cmdutil.UsageErrorf(cmd, "couldn't find port via --port flag or introspection: %v", err) } @@ -199,7 +283,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri // Always try to derive protocols from the exposed object, may use // different protocols for different ports. if _, found := params["protocol"]; found { - protocolsMap, err := f.ProtocolsForObject(info.Object) + protocolsMap, err := o.ProtocolsForObject(info.Object) if err != nil { return cmdutil.UsageErrorf(cmd, "couldn't find protocol via introspection: %v", err) } @@ -209,7 +293,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri } if kubectl.IsZero(params["labels"]) { - labels, err := f.LabelsForObject(info.Object) + labels, err := meta.NewAccessor().Labels(info.Object) if err != nil { return err } @@ -237,45 +321,36 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri } } - resourceMapper := &resource.Mapper{ - ObjectTyper: typer, - RESTMapper: mapper, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - Decoder: cmdutil.InternalVersionDecoder(), + if err := o.Recorder.Record(object); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } - info, err = resourceMapper.InfoForObject(object, nil) - if err != nil { + + if o.DryRun { + return o.PrintObj(object, o.Out) + } + if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), object, cmdutil.InternalVersionJSONEncoder()); err != nil { return err } - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(object, f.Command(cmd, false)); err != nil { - return err - } + + asUnstructured := &unstructured.Unstructured{} + if err := legacyscheme.Scheme.Convert(object, asUnstructured, nil); err != nil { + return err } - info.Refresh(object, true) - if cmdutil.GetDryRunFlag(cmd) { - if len(cmdutil.GetFlagString(cmd, "output")) > 0 { - return cmdutil.PrintObject(cmd, object, out) - } - cmdutil.PrintSuccess(false, out, info.Object, true, "exposed") - return nil + gvks, _, err := unstructuredscheme.NewUnstructuredObjectTyper().ObjectKinds(asUnstructured) + if err != nil { + return err } - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, cmdutil.InternalVersionJSONEncoder()); err != nil { + objMapping, err := o.Mapper.RESTMapping(gvks[0].GroupKind(), gvks[0].Version) + if err != nil { return err } - // Serialize the object with the annotation applied. - object, err = resource.NewHelper(info.Client, info.Mapping).Create(namespace, false, object) + actualObject, err := o.DynamicClient.Resource(objMapping.Resource).Namespace(o.Namespace).Create(asUnstructured) if err != nil { return err } - if len(cmdutil.GetFlagString(cmd, "output")) > 0 { - return cmdutil.PrintObject(cmd, object, out) - } - - cmdutil.PrintSuccess(false, out, info.Object, false, "exposed") - return nil + return o.PrintObj(actualObject, o.Out) }) if err != nil { return err diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/expose_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/expose_test.go index 7097d6794..7c4fa01e9 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/expose_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/expose_test.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "bytes" "fmt" "net/http" "strings" @@ -31,6 +30,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -79,7 +79,7 @@ func TestRunExposeService(t *testing.T) { Selector: map[string]string{"app": "go"}, }, }, - expected: "service \"foo\" exposed", + expected: "service/foo exposed", status: 200, }, { @@ -110,7 +110,7 @@ func TestRunExposeService(t *testing.T) { Selector: map[string]string{"func": "stream"}, }, }, - expected: "service \"foo\" exposed", + expected: "service/foo exposed", status: 200, }, { @@ -142,7 +142,7 @@ func TestRunExposeService(t *testing.T) { Selector: map[string]string{"run": "this"}, }, }, - expected: "service \"mayor\" exposed", + expected: "service/mayor exposed", status: 200, }, { @@ -237,7 +237,7 @@ func TestRunExposeService(t *testing.T) { ClusterIP: "10.10.10.10", }, }, - expected: "service \"foo\" exposed", + expected: "service /foo exposed", status: 200, }, { @@ -269,7 +269,7 @@ func TestRunExposeService(t *testing.T) { ClusterIP: api.ClusterIPNone, }, }, - expected: "service \"foo\" exposed", + expected: "service/foo exposed", status: 200, }, { @@ -295,7 +295,7 @@ func TestRunExposeService(t *testing.T) { ClusterIP: api.ClusterIPNone, }, }, - expected: "service \"foo\" exposed", + expected: "service/foo exposed", status: 200, }, { @@ -312,7 +312,7 @@ func TestRunExposeService(t *testing.T) { Selector: map[string]string{"app": "go"}, }, }, - flags: map[string]string{"filename": "../../../examples/guestbook/redis-master-service.yaml", "selector": "func=stream", "protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test", "dry-run": "true"}, + flags: map[string]string{"filename": "../../../test/e2e/testing-manifests/guestbook/redis-master-service.yaml", "selector": "func=stream", "protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test", "dry-run": "true"}, output: &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Labels: map[string]string{"svc": "test"}}, Spec: api.ServiceSpec{ @@ -353,7 +353,7 @@ func TestRunExposeService(t *testing.T) { Selector: map[string]string{"svc": "frompod"}, }, }, - expected: "service \"a-name-that-is-toooo-big-for-a-service-because-it-can-only-hand\" exposed", + expected: "service/a-name-that-is-toooo-big-for-a-service-because-it-can-only-hand exposed", status: 200, }, { @@ -467,10 +467,10 @@ func TestRunExposeService(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace(test.ns) defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -480,18 +480,15 @@ func TestRunExposeService(t *testing.T) { switch p, m := req.URL.Path, req.Method; { case p == test.calls[m] && m == "GET": return &http.Response{StatusCode: test.status, Header: defaultHeader(), Body: objBody(codec, test.input)}, nil - case p == test.calls[m] && m == "POST": - return &http.Response{StatusCode: test.status, Header: defaultHeader(), Body: objBody(codec, test.output)}, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } }), } - tf.Namespace = test.ns - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdExposeService(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdExposeService(tf, ioStreams) cmd.SetOutput(buf) for flag, value := range test.flags { cmd.Flags().Set(flag, value) @@ -500,7 +497,7 @@ func TestRunExposeService(t *testing.T) { out := buf.String() if _, ok := test.flags["dry-run"]; ok { - test.expected = fmt.Sprintf("service %q exposed (dry run)", test.flags["name"]) + test.expected = fmt.Sprintf("service/%s exposed (dry run)", test.flags["name"]) } if !strings.Contains(out, test.expected) { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/BUILD new file mode 100644 index 000000000..37aded20c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/BUILD @@ -0,0 +1,93 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + srcs = [ + "get.go", + "get_flags.go", + "humanreadable_flags.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/get", + visibility = ["//visibility:public"], + deps = [ + "//pkg/api/legacyscheme:go_default_library", + "//pkg/apis/core:go_default_library", + "//pkg/kubectl:go_default_library", + "//pkg/kubectl/cmd/templates:go_default_library", + "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/cmd/util/openapi:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//pkg/kubectl/scheme:go_default_library", + "//pkg/kubectl/util/i18n:go_default_library", + "//pkg/printers:go_default_library", + "//pkg/printers/internalversion:go_default_library", + "//pkg/util/interrupt:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1: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/util/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "get_test.go", + "humanreadable_flags_test.go", + ], + data = [ + "//api/openapi-spec:swagger-spec", + "//test/e2e/testing-manifests:all-srcs", + "//test/fixtures", + ], + embed = [":go_default_library"], + deps = [ + "//pkg/api/legacyscheme:go_default_library", + "//pkg/api/testing:go_default_library", + "//pkg/apis/core:go_default_library", + "//pkg/apis/core/v1:go_default_library", + "//pkg/kubectl/cmd/testing:go_default_library", + "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/cmd/util/openapi:go_default_library", + "//pkg/kubectl/cmd/util/openapi/testing:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//pkg/kubectl/scheme:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/json:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/rest/fake:go_default_library", + "//vendor/k8s.io/client-go/rest/watch:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/get.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/get.go new file mode 100644 index 000000000..02cd2bfe1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/get.go @@ -0,0 +1,756 @@ +/* +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 get + +import ( + "encoding/json" + "fmt" + "io" + "net/url" + + "github.com/golang/glog" + "github.com/spf13/cobra" + + kapierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/rest" + "k8s.io/kubernetes/pkg/api/legacyscheme" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "k8s.io/kubernetes/pkg/printers" + "k8s.io/kubernetes/pkg/util/interrupt" +) + +// GetOptions contains the input to the get command. +type GetOptions struct { + PrintFlags *PrintFlags + ToPrinter func(*meta.RESTMapping, bool) (printers.ResourcePrinterFunc, error) + IsHumanReadablePrinter bool + PrintWithOpenAPICols bool + + CmdParent string + + resource.FilenameOptions + + Raw string + Watch bool + WatchOnly bool + ChunkSize int64 + + LabelSelector string + FieldSelector string + AllNamespaces bool + Namespace string + ExplicitNamespace bool + + ServerPrint bool + + NoHeaders bool + Sort bool + IgnoreNotFound bool + Export bool + + IncludeUninitialized bool + + genericclioptions.IOStreams +} + +var ( + getLong = templates.LongDesc(` + Display one or many resources + + Prints a table of the most important information about the specified resources. + You can filter the list using a label selector and the --selector flag. If the + desired resource type is namespaced you will only see results in your current + namespace unless you pass --all-namespaces. + + Uninitialized objects are not shown unless --include-uninitialized is passed. + + By specifying the output as 'template' and providing a Go template as the value + of the --template flag, you can filter the attributes of the fetched resources.`) + + getExample = templates.Examples(i18n.T(` + # List all pods in ps output format. + kubectl get pods + + # List all pods in ps output format with more information (such as node name). + kubectl get pods -o wide + + # List a single replication controller with specified NAME in ps output format. + kubectl get replicationcontroller web + + # List deployments in JSON output format, in the "v1" version of the "apps" API group: + kubectl get deployments.v1.apps -o json + + # List a single pod in JSON output format. + kubectl get -o json pod web-pod-13je7 + + # List a pod identified by type and name specified in "pod.yaml" in JSON output format. + kubectl get -f pod.yaml -o json + + # Return only the phase value of the specified pod. + kubectl get -o template pod/web-pod-13je7 --template={{.status.phase}} + + # List all replication controllers and services together in ps output format. + kubectl get rc,services + + # List one or more resources by their type and names. + kubectl get rc/web service/frontend pods/web-pod-13je7`)) +) + +const ( + useOpenAPIPrintColumnFlagLabel = "use-openapi-print-columns" + useServerPrintColumns = "server-print" +) + +// NewGetOptions returns a GetOptions with default chunk size 500. +func NewGetOptions(parent string, streams genericclioptions.IOStreams) *GetOptions { + return &GetOptions{ + PrintFlags: NewGetPrintFlags(), + CmdParent: parent, + + IOStreams: streams, + ChunkSize: 500, + ServerPrint: true, + } +} + +// NewCmdGet creates a command object for the generic "get" action, which +// retrieves one or more resources from a server. +func NewCmdGet(parent string, f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewGetOptions(parent, streams) + + cmd := &cobra.Command{ + Use: "get [(-o|--output=)json|yaml|wide|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE[.VERSION][.GROUP] [NAME | -l label] | TYPE[.VERSION][.GROUP]/NAME ...) [flags]", + DisableFlagsInUseLine: true, + Short: i18n.T("Display one or many resources"), + Long: getLong + "\n\n" + cmdutil.SuggestApiResources(parent), + Example: getExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate(cmd)) + cmdutil.CheckErr(o.Run(f, cmd, args)) + }, + SuggestFor: []string{"list", "ps"}, + } + + o.PrintFlags.AddFlags(cmd) + + cmd.Flags().StringVar(&o.Raw, "raw", o.Raw, "Raw URI to request from the server. Uses the transport specified by the kubeconfig file.") + cmd.Flags().BoolVarP(&o.Watch, "watch", "w", o.Watch, "After listing/getting the requested object, watch for changes. Uninitialized objects are excluded if no object name is provided.") + cmd.Flags().BoolVar(&o.WatchOnly, "watch-only", o.WatchOnly, "Watch for changes to the requested object(s), without listing/getting first.") + cmd.Flags().Int64Var(&o.ChunkSize, "chunk-size", o.ChunkSize, "Return large lists in chunks rather than all at once. Pass 0 to disable. This flag is beta and may change in the future.") + cmd.Flags().BoolVar(&o.IgnoreNotFound, "ignore-not-found", o.IgnoreNotFound, "If the requested object does not exist the command will return exit code 0.") + cmd.Flags().StringVarP(&o.LabelSelector, "selector", "l", o.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().StringVar(&o.FieldSelector, "field-selector", o.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") + cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + cmdutil.AddIncludeUninitializedFlag(cmd) + addOpenAPIPrintColumnFlags(cmd, o) + addServerPrintColumnFlags(cmd, o) + cmd.Flags().BoolVar(&o.Export, "export", o.Export, "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information.") + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to get from a server.") + return cmd +} + +// Complete takes the command arguments and factory and infers any remaining options. +func (o *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + if len(o.Raw) > 0 { + if len(args) > 0 { + return fmt.Errorf("arguments may not be passed when --raw is specified") + } + return nil + } + + var err error + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + if o.AllNamespaces { + o.ExplicitNamespace = false + } + + isSorting, err := cmd.Flags().GetString("sort-by") + if err != nil { + return err + } + o.Sort = len(isSorting) > 0 + + o.NoHeaders = cmdutil.GetFlagBool(cmd, "no-headers") + + // TODO (soltysh): currently we don't support sorting and custom columns + // with server side print. So in these cases force the old behavior. + outputOption := cmd.Flags().Lookup("output").Value.String() + if o.Sort && outputOption == "custom-columns" { + o.ServerPrint = false + } + + templateArg := "" + if o.PrintFlags.TemplateFlags != nil && o.PrintFlags.TemplateFlags.TemplateArgument != nil { + templateArg = *o.PrintFlags.TemplateFlags.TemplateArgument + } + + // human readable printers have special conversion rules, so we determine if we're using one. + if (len(*o.PrintFlags.OutputFormat) == 0 && len(templateArg) == 0) || *o.PrintFlags.OutputFormat == "wide" { + o.IsHumanReadablePrinter = true + } + + o.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, false) + + if resource.MultipleTypesRequested(args) { + o.PrintFlags.EnsureWithKind() + } + o.ToPrinter = func(mapping *meta.RESTMapping, withNamespace bool) (printers.ResourcePrinterFunc, error) { + // make a new copy of current flags / opts before mutating + printFlags := o.PrintFlags.Copy() + + if mapping != nil { + if !cmdSpecifiesOutputFmt(cmd) && o.PrintWithOpenAPICols { + if apiSchema, err := f.OpenAPISchema(); err == nil { + printFlags.UseOpenAPIColumns(apiSchema, mapping) + } + } + printFlags.SetKind(mapping.GroupVersionKind.GroupKind()) + } + if withNamespace { + printFlags.EnsureWithNamespace() + } + + printer, err := printFlags.ToPrinter() + if err != nil { + return nil, err + } + + printer = maybeWrapSortingPrinter(printer, isSorting) + return printer.PrintObj, nil + } + + switch { + case o.Watch || o.WatchOnly: + // include uninitialized objects when watching on a single object + // unless explicitly set --include-uninitialized=false + o.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, len(args) == 2) + default: + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { + fmt.Fprintf(o.ErrOut, "You must specify the type of resource to get. %s\n\n", cmdutil.SuggestApiResources(o.CmdParent)) + fullCmdName := cmd.Parent().CommandPath() + usageString := "Required resource not specified." + if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") { + usageString = fmt.Sprintf("%s\nUse \"%s explain \" for a detailed description of that resource (e.g. %[2]s explain pods).", usageString, fullCmdName) + } + + return cmdutil.UsageErrorf(cmd, usageString) + } + } + return nil +} + +// Validate checks the set of flags provided by the user. +func (o *GetOptions) Validate(cmd *cobra.Command) error { + if len(o.Raw) > 0 { + if o.Watch || o.WatchOnly || len(o.LabelSelector) > 0 || o.Export { + return fmt.Errorf("--raw may not be specified with other flags that filter the server request or alter the output") + } + if len(cmdutil.GetFlagString(cmd, "output")) > 0 { + return cmdutil.UsageErrorf(cmd, "--raw and --output are mutually exclusive") + } + if _, err := url.ParseRequestURI(o.Raw); err != nil { + return cmdutil.UsageErrorf(cmd, "--raw must be a valid URL path: %v", err) + } + } + if cmdutil.GetFlagBool(cmd, "show-labels") { + outputOption := cmd.Flags().Lookup("output").Value.String() + if outputOption != "" && outputOption != "wide" { + return fmt.Errorf("--show-labels option cannot be used with %s printer", outputOption) + } + } + return nil +} + +// Run performs the get operation. +// TODO: remove the need to pass these arguments, like other commands. +func (o *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + if len(o.Raw) > 0 { + return o.raw(f) + } + if o.Watch || o.WatchOnly { + return o.watch(f, cmd, args) + } + + r := f.NewBuilder(). + Unstructured(). + NamespaceParam(o.Namespace).DefaultNamespace().AllNamespaces(o.AllNamespaces). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + LabelSelectorParam(o.LabelSelector). + FieldSelectorParam(o.FieldSelector). + ExportParam(o.Export). + RequestChunksOf(o.ChunkSize). + IncludeUninitialized(o.IncludeUninitialized). + ResourceTypeOrNameArgs(true, args...). + ContinueOnError(). + Latest(). + Flatten(). + TransformRequests(func(req *rest.Request) { + // We need full objects if printing with openapi columns + if o.PrintWithOpenAPICols { + return + } + if o.ServerPrint && o.IsHumanReadablePrinter && !o.Sort { + group := metav1beta1.GroupName + version := metav1beta1.SchemeGroupVersion.Version + + tableParam := fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", version, group) + req.SetHeader("Accept", tableParam) + } + }). + Do() + + if o.IgnoreNotFound { + r.IgnoreErrors(kapierrors.IsNotFound) + } + if err := r.Err(); err != nil { + return err + } + + if !o.IsHumanReadablePrinter { + return o.printGeneric(r) + } + + allErrs := []error{} + errs := sets.NewString() + infos, err := r.Infos() + if err != nil { + allErrs = append(allErrs, err) + } + + objs := make([]runtime.Object, len(infos)) + for ix := range infos { + if o.ServerPrint { + table, err := o.decodeIntoTable(infos[ix].Object) + if err == nil { + infos[ix].Object = table + } else { + // if we are unable to decode server response into a v1beta1.Table, + // fallback to client-side printing with whatever info the server returned. + glog.V(2).Infof("Unable to decode server response into a Table. Falling back to hardcoded types: %v", err) + } + } + + objs[ix] = infos[ix].Object + } + + sorting, err := cmd.Flags().GetString("sort-by") + if err != nil { + return err + } + var sorter *kubectl.RuntimeSort + if o.Sort && len(objs) > 1 { + // TODO: questionable + if sorter, err = kubectl.SortObjects(cmdutil.InternalVersionDecoder(), objs, sorting); err != nil { + return err + } + } + + var printer printers.ResourcePrinter + var lastMapping *meta.RESTMapping + nonEmptyObjCount := 0 + w := printers.GetNewTabWriter(o.Out) + for ix := range objs { + var mapping *meta.RESTMapping + var info *resource.Info + if sorter != nil { + info = infos[sorter.OriginalPosition(ix)] + mapping = info.Mapping + } else { + info = infos[ix] + mapping = info.Mapping + } + + // if dealing with a table that has no rows, skip remaining steps + // and avoid printing an unnecessary newline + if table, isTable := info.Object.(*metav1beta1.Table); isTable { + if len(table.Rows) == 0 { + continue + } + } + + nonEmptyObjCount++ + + printWithNamespace := o.AllNamespaces + if mapping != nil && mapping.Scope.Name() == meta.RESTScopeNameRoot { + printWithNamespace = false + } + + if shouldGetNewPrinterForMapping(printer, lastMapping, mapping) { + w.Flush() + + // TODO: this doesn't belong here + // add linebreak between resource groups (if there is more than one) + // skip linebreak above first resource group + if lastMapping != nil && !o.NoHeaders { + fmt.Fprintln(o.ErrOut) + } + + printer, err = o.ToPrinter(mapping, printWithNamespace) + if err != nil { + if !errs.Has(err.Error()) { + errs.Insert(err.Error()) + allErrs = append(allErrs, err) + } + continue + } + + lastMapping = mapping + } + + // ensure a versioned object is passed to the custom-columns printer + // if we are using OpenAPI columns to print + if o.PrintWithOpenAPICols { + printer.PrintObj(info.Object, w) + continue + } + + internalObj, err := legacyscheme.Scheme.ConvertToVersion(info.Object, info.Mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion()) + if err != nil { + // if there's an error, try to print what you have (mirrors old behavior). + glog.V(1).Info(err) + printer.PrintObj(info.Object, w) + } else { + printer.PrintObj(internalObj, w) + } + } + w.Flush() + if nonEmptyObjCount == 0 && !o.IgnoreNotFound { + fmt.Fprintln(o.ErrOut, "No resources found.") + } + return utilerrors.NewAggregate(allErrs) +} + +// raw makes a simple HTTP request to the provided path on the server using the default +// credentials. +func (o *GetOptions) raw(f cmdutil.Factory) error { + restClient, err := f.RESTClient() + if err != nil { + return err + } + + stream, err := restClient.Get().RequestURI(o.Raw).Stream() + if err != nil { + return err + } + defer stream.Close() + + _, err = io.Copy(o.Out, stream) + if err != nil && err != io.EOF { + return err + } + return nil +} + +// watch starts a client-side watch of one or more resources. +// TODO: remove the need for arguments here. +func (o *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + r := f.NewBuilder(). + Unstructured(). + NamespaceParam(o.Namespace).DefaultNamespace().AllNamespaces(o.AllNamespaces). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + LabelSelectorParam(o.LabelSelector). + FieldSelectorParam(o.FieldSelector). + ExportParam(o.Export). + RequestChunksOf(o.ChunkSize). + IncludeUninitialized(o.IncludeUninitialized). + ResourceTypeOrNameArgs(true, args...). + SingleResourceType(). + Latest(). + Do() + if err := r.Err(); err != nil { + return err + } + infos, err := r.Infos() + if err != nil { + return err + } + if len(infos) > 1 { + gvk := infos[0].Mapping.GroupVersionKind + uniqueGVKs := 1 + + // If requesting a resource count greater than a request's --chunk-size, + // we will end up making multiple requests to the server, with each + // request producing its own "Info" object. Although overall we are + // dealing with a single resource type, we will end up with multiple + // infos returned by the builder. To handle this case, only fail if we + // have at least one info with a different GVK than the others. + for _, info := range infos { + if info.Mapping.GroupVersionKind != gvk { + uniqueGVKs++ + } + } + + if uniqueGVKs > 1 { + return i18n.Errorf("watch is only supported on individual resources and resource collections - %d resources were found", uniqueGVKs) + } + } + + info := infos[0] + mapping := info.ResourceMapping() + printer, err := o.ToPrinter(mapping, o.AllNamespaces) + if err != nil { + return err + } + obj, err := r.Object() + if err != nil { + return err + } + + // watching from resourceVersion 0, starts the watch at ~now and + // will return an initial watch event. Starting form ~now, rather + // the rv of the object will insure that we start the watch from + // inside the watch window, which the rv of the object might not be. + rv := "0" + isList := meta.IsListType(obj) + if isList { + // the resourceVersion of list objects is ~now but won't return + // an initial watch event + rv, err = meta.NewAccessor().ResourceVersion(obj) + if err != nil { + return err + } + } + + // print the current object + if !o.WatchOnly { + var objsToPrint []runtime.Object + writer := printers.GetNewTabWriter(o.Out) + + if isList { + objsToPrint, _ = meta.ExtractList(obj) + } else { + objsToPrint = append(objsToPrint, obj) + } + for _, objToPrint := range objsToPrint { + if o.IsHumanReadablePrinter { + // printing always takes the internal version, but the watch event uses externals + internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion() + objToPrint = attemptToConvertToInternal(objToPrint, legacyscheme.Scheme, internalGV) + } + if err := printer.PrintObj(objToPrint, writer); err != nil { + return fmt.Errorf("unable to output the provided object: %v", err) + } + } + writer.Flush() + } + + // print watched changes + w, err := r.Watch(rv) + if err != nil { + return err + } + + first := true + intr := interrupt.New(nil, w.Stop) + intr.Run(func() error { + _, err := watch.Until(0, w, func(e watch.Event) (bool, error) { + if !isList && first { + // drop the initial watch event in the single resource case + first = false + return false, nil + } + + // printing always takes the internal version, but the watch event uses externals + // TODO fix printing to use server-side or be version agnostic + internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion() + if err := printer.PrintObj(attemptToConvertToInternal(e.Object, legacyscheme.Scheme, internalGV), o.Out); err != nil { + return false, err + } + return false, nil + }) + return err + }) + return nil +} + +// attemptToConvertToInternal tries to convert to an internal type, but returns the original if it can't +func attemptToConvertToInternal(obj runtime.Object, converter runtime.ObjectConvertor, targetVersion schema.GroupVersion) runtime.Object { + internalObject, err := converter.ConvertToVersion(obj, targetVersion) + if err != nil { + glog.V(1).Infof("Unable to convert %T to %v: err", obj, targetVersion, err) + return obj + } + return internalObject +} + +func (o *GetOptions) decodeIntoTable(obj runtime.Object) (runtime.Object, error) { + if obj.GetObjectKind().GroupVersionKind().Kind != "Table" { + return nil, fmt.Errorf("attempt to decode non-Table object into a v1beta1.Table") + } + + unstr, ok := obj.(*unstructured.Unstructured) + if !ok { + return nil, fmt.Errorf("attempt to decode non-Unstructured object") + } + table := &metav1beta1.Table{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstr.Object, table); err != nil { + return nil, err + } + + for i := range table.Rows { + row := &table.Rows[i] + if row.Object.Raw == nil || row.Object.Object != nil { + continue + } + converted, err := runtime.Decode(unstructured.UnstructuredJSONScheme, row.Object.Raw) + if err != nil { + return nil, err + } + row.Object.Object = converted + } + + return table, nil +} + +func (o *GetOptions) printGeneric(r *resource.Result) error { + // we flattened the data from the builder, so we have individual items, but now we'd like to either: + // 1. if there is more than one item, combine them all into a single list + // 2. if there is a single item and that item is a list, leave it as its specific list + // 3. if there is a single item and it is not a list, leave it as a single item + var errs []error + singleItemImplied := false + infos, err := r.IntoSingleItemImplied(&singleItemImplied).Infos() + if err != nil { + if singleItemImplied { + return err + } + errs = append(errs, err) + } + + if len(infos) == 0 && o.IgnoreNotFound { + return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) + } + + printer, err := o.ToPrinter(nil, false) + if err != nil { + return err + } + + var obj runtime.Object + if !singleItemImplied || len(infos) > 1 { + // we have more than one item, so coerce all items into a list. + // we don't want an *unstructured.Unstructured list yet, as we + // may be dealing with non-unstructured objects. Compose all items + // into an api.List, and then decode using an unstructured scheme. + list := api.List{ + TypeMeta: metav1.TypeMeta{ + Kind: "List", + APIVersion: "v1", + }, + ListMeta: metav1.ListMeta{}, + } + for _, info := range infos { + list.Items = append(list.Items, info.Object) + } + + listData, err := json.Marshal(list) + if err != nil { + return err + } + + converted, err := runtime.Decode(unstructured.UnstructuredJSONScheme, listData) + if err != nil { + return err + } + + obj = converted + } else { + obj = infos[0].Object + } + + isList := meta.IsListType(obj) + if isList { + items, err := meta.ExtractList(obj) + if err != nil { + return err + } + + // take the items and create a new list for display + list := &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "kind": "List", + "apiVersion": "v1", + "metadata": map[string]interface{}{}, + }, + } + if listMeta, err := meta.ListAccessor(obj); err == nil { + list.Object["metadata"] = map[string]interface{}{ + "selfLink": listMeta.GetSelfLink(), + "resourceVersion": listMeta.GetResourceVersion(), + } + } + + for _, item := range items { + list.Items = append(list.Items, *item.(*unstructured.Unstructured)) + } + if err := printer.PrintObj(list, o.Out); err != nil { + errs = append(errs, err) + } + return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) + } + + if printErr := printer.PrintObj(obj, o.Out); printErr != nil { + errs = append(errs, printErr) + } + + return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) +} + +func addOpenAPIPrintColumnFlags(cmd *cobra.Command, opt *GetOptions) { + cmd.Flags().BoolVar(&opt.PrintWithOpenAPICols, useOpenAPIPrintColumnFlagLabel, opt.PrintWithOpenAPICols, "If true, use x-kubernetes-print-column metadata (if present) from the OpenAPI schema for displaying a resource.") +} + +func addServerPrintColumnFlags(cmd *cobra.Command, opt *GetOptions) { + cmd.Flags().BoolVar(&opt.ServerPrint, useServerPrintColumns, opt.ServerPrint, "If true, have the server return the appropriate table output. Supports extension APIs and CRDs.") +} + +func shouldGetNewPrinterForMapping(printer printers.ResourcePrinter, lastMapping, mapping *meta.RESTMapping) bool { + return printer == nil || lastMapping == nil || mapping == nil || mapping.Resource != lastMapping.Resource +} + +func cmdSpecifiesOutputFmt(cmd *cobra.Command) bool { + return cmdutil.GetFlagString(cmd, "output") != "" +} + +func maybeWrapSortingPrinter(printer printers.ResourcePrinter, sortBy string) printers.ResourcePrinter { + if len(sortBy) != 0 { + return &kubectl.SortingPrinter{ + Delegate: printer, + SortField: fmt.Sprintf("%s", sortBy), + } + } + return printer +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/get_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/get_flags.go new file mode 100644 index 000000000..bc05ac05c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/get_flags.go @@ -0,0 +1,190 @@ +/* +Copyright 2018 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 get + +import ( + "strings" + + "github.com/spf13/cobra" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/printers" +) + +// PrintFlags composes common printer flag structs +// used in the Get command. +type PrintFlags struct { + JSONYamlPrintFlags *genericclioptions.JSONYamlPrintFlags + NamePrintFlags *genericclioptions.NamePrintFlags + CustomColumnsFlags *printers.CustomColumnsPrintFlags + HumanReadableFlags *HumanPrintFlags + TemplateFlags *genericclioptions.KubeTemplatePrintFlags + + NoHeaders *bool + OutputFormat *string +} + +// SetKind sets the Kind option of humanreadable flags +func (f *PrintFlags) SetKind(kind schema.GroupKind) { + f.HumanReadableFlags.SetKind(kind) +} + +// EnsureWithNamespace ensures that humanreadable flags return +// a printer capable of printing with a "namespace" column. +func (f *PrintFlags) EnsureWithNamespace() error { + return f.HumanReadableFlags.EnsureWithNamespace() +} + +// EnsureWithKind ensures that humanreadable flags return +// a printer capable of including resource kinds. +func (f *PrintFlags) EnsureWithKind() error { + return f.HumanReadableFlags.EnsureWithKind() +} + +// Copy returns a copy of PrintFlags for mutation +func (f *PrintFlags) Copy() PrintFlags { + printFlags := *f + return printFlags +} + +func (f *PrintFlags) AllowedFormats() []string { + formats := f.JSONYamlPrintFlags.AllowedFormats() + formats = append(formats, f.NamePrintFlags.AllowedFormats()...) + formats = append(formats, f.TemplateFlags.AllowedFormats()...) + formats = append(formats, f.CustomColumnsFlags.AllowedFormats()...) + formats = append(formats, f.HumanReadableFlags.AllowedFormats()...) + return formats +} + +// UseOpenAPIColumns modifies the output format, as well as the +// "allowMissingKeys" option for template printers, to values +// defined in the OpenAPI schema of a resource. +func (f *PrintFlags) UseOpenAPIColumns(api openapi.Resources, mapping *meta.RESTMapping) error { + // Found openapi metadata for this resource + schema := api.LookupResource(mapping.GroupVersionKind) + if schema == nil { + // Schema not found, return empty columns + return nil + } + + columns, found := openapi.GetPrintColumns(schema.GetExtensions()) + if !found { + // Extension not found, return empty columns + return nil + } + + parts := strings.SplitN(columns, "=", 2) + if len(parts) < 2 { + return nil + } + + allowMissingKeys := true + f.OutputFormat = &parts[0] + f.TemplateFlags.TemplateArgument = &parts[1] + f.TemplateFlags.AllowMissingKeys = &allowMissingKeys + return nil +} + +// ToPrinter attempts to find a composed set of PrintFlags suitable for +// returning a printer based on current flag values. +func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) { + outputFormat := "" + if f.OutputFormat != nil { + outputFormat = *f.OutputFormat + } + + noHeaders := false + if f.NoHeaders != nil { + noHeaders = *f.NoHeaders + } + f.HumanReadableFlags.NoHeaders = noHeaders + f.CustomColumnsFlags.NoHeaders = noHeaders + + // for "get.go" we want to support a --template argument given, even when no --output format is provided + if f.TemplateFlags.TemplateArgument != nil && len(*f.TemplateFlags.TemplateArgument) > 0 && len(outputFormat) == 0 { + outputFormat = "go-template" + } + + if p, err := f.TemplateFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + if f.TemplateFlags.TemplateArgument != nil { + f.CustomColumnsFlags.TemplateArgument = *f.TemplateFlags.TemplateArgument + } + + if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + if p, err := f.HumanReadableFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + if p, err := f.CustomColumnsFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to humanreadable and template printing. +func (f *PrintFlags) AddFlags(cmd *cobra.Command) { + f.JSONYamlPrintFlags.AddFlags(cmd) + f.NamePrintFlags.AddFlags(cmd) + f.TemplateFlags.AddFlags(cmd) + f.HumanReadableFlags.AddFlags(cmd) + f.CustomColumnsFlags.AddFlags(cmd) + + if f.OutputFormat != nil { + cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, "Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].") + } + if f.NoHeaders != nil { + cmd.Flags().BoolVar(f.NoHeaders, "no-headers", *f.NoHeaders, "When using the default or custom-column output format, don't print headers (default print headers).") + } + + // TODO(juanvallejo): This is deprecated - remove + cmd.Flags().BoolP("show-all", "a", true, "When printing, show all resources (default show all pods including terminated one.)") + cmd.Flags().MarkDeprecated("show-all", "will be removed in an upcoming release") +} + +// NewGetPrintFlags returns flags associated with humanreadable, +// template, and "name" printing, with default values set. +func NewGetPrintFlags() *PrintFlags { + outputFormat := "" + noHeaders := false + + return &PrintFlags{ + OutputFormat: &outputFormat, + NoHeaders: &noHeaders, + + JSONYamlPrintFlags: genericclioptions.NewJSONYamlPrintFlags(), + NamePrintFlags: genericclioptions.NewNamePrintFlags(""), + TemplateFlags: genericclioptions.NewKubeTemplatePrintFlags(), + + HumanReadableFlags: NewHumanPrintFlags(), + CustomColumnsFlags: printers.NewCustomColumnsPrintFlags(), + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/get_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/get_test.go new file mode 100644 index 000000000..a6ab89904 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/get_test.go @@ -0,0 +1,1235 @@ +/* +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 get + +import ( + "bytes" + encjson "encoding/json" + "io" + "io/ioutil" + "net/http" + "path/filepath" + "reflect" + "strings" + "testing" + + api "k8s.io/api/core/v1" + 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/json" + "k8s.io/apimachinery/pkg/runtime/serializer/streaming" + "k8s.io/apimachinery/pkg/watch" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" + restclientwatch "k8s.io/client-go/rest/watch" + "k8s.io/kube-openapi/pkg/util/proto" + apitesting "k8s.io/kubernetes/pkg/api/testing" + "k8s.io/kubernetes/pkg/apis/core/v1" + + "k8s.io/apimachinery/pkg/util/diff" + "k8s.io/kubernetes/pkg/api/legacyscheme" + cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" + openapitesting "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" +) + +var openapiSchemaPath = filepath.Join("..", "..", "..", "..", "api", "openapi-spec", "swagger.json") + +// This init should be removed after switching this command and its tests to user external types. +func init() { + api.AddToScheme(scheme.Scheme) + scheme.Scheme.AddConversionFuncs(v1.Convert_core_PodSpec_To_v1_PodSpec) + scheme.Scheme.AddConversionFuncs(v1.Convert_v1_PodSecurityContext_To_core_PodSecurityContext) +} + +var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer + +func defaultHeader() http.Header { + header := http.Header{} + header.Set("Content-Type", runtime.ContentTypeJSON) + return header +} + +func defaultClientConfig() *restclient.Config { + return &restclient.Config{ + APIPath: "/api", + ContentConfig: restclient.ContentConfig{ + NegotiatedSerializer: scheme.Codecs, + ContentType: runtime.ContentTypeJSON, + GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}, + }, + } +} + +func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser { + return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj)))) +} + +func stringBody(body string) io.ReadCloser { + return ioutil.NopCloser(bytes.NewReader([]byte(body))) +} + +func initTestErrorHandler(t *testing.T) { + cmdutil.BehaviorOnFatal(func(str string, code int) { + t.Errorf("Error running command (exit code %d): %s", code, str) + }) +} + +func testData() (*api.PodList, *api.ServiceList, *api.ReplicationControllerList) { + pods := &api.PodList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "15", + }, + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"}, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + }, + } + svc := &api.ServiceList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "16", + }, + Items: []api.Service{ + { + ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, + Spec: api.ServiceSpec{ + SessionAffinity: "None", + Type: api.ServiceTypeClusterIP, + }, + }, + }, + } + + one := int32(1) + rc := &api.ReplicationControllerList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "17", + }, + Items: []api.ReplicationController{ + { + ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: "test", ResourceVersion: "18"}, + Spec: api.ReplicationControllerSpec{ + Replicas: &one, + }, + }, + }, + } + return pods, svc, rc +} + +func testComponentStatusData() *api.ComponentStatusList { + good := api.ComponentStatus{ + Conditions: []api.ComponentCondition{ + {Type: api.ComponentHealthy, Status: api.ConditionTrue, Message: "ok"}, + }, + ObjectMeta: metav1.ObjectMeta{Name: "servergood"}, + } + + bad := api.ComponentStatus{ + Conditions: []api.ComponentCondition{ + {Type: api.ComponentHealthy, Status: api.ConditionFalse, Message: "", Error: "bad status: 500"}, + }, + ObjectMeta: metav1.ObjectMeta{Name: "serverbad"}, + } + + unknown := api.ComponentStatus{ + Conditions: []api.ComponentCondition{ + {Type: api.ComponentHealthy, Status: api.ConditionUnknown, Message: "", Error: "fizzbuzz error"}, + }, + ObjectMeta: metav1.ObjectMeta{Name: "serverunknown"}, + } + + return &api.ComponentStatusList{ + Items: []api.ComponentStatus{good, bad, unknown}, + } +} + +// Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. +func TestGetUnknownSchemaObject(t *testing.T) { + t.Skip("This test is completely broken. The first thing it does is add the object to the scheme!") + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + _, _, codec := cmdtesting.NewExternalScheme() + tf.OpenAPISchemaFunc = openapitesting.CreateOpenAPISchemaFunc(openapiSchemaPath) + + obj := &cmdtesting.ExternalType{ + Kind: "Type", + APIVersion: "apitest/unlikelyversion", + Name: "foo", + } + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{ + StatusCode: 200, Header: defaultHeader(), + Body: objBody(codec, obj), + }, + } + tf.ClientConfigVal = defaultClientConfig() + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Run(cmd, []string{"type", "foo"}) + + expected := []runtime.Object{cmdtesting.NewInternalType("", "", "foo")} + actual := []runtime.Object{} + if len(actual) != len(expected) { + t.Fatalf("expected: %#v, but actual: %#v", expected, actual) + } + t.Logf("actual: %#v", actual[0]) + for i, obj := range actual { + expectedJSON := runtime.EncodeOrDie(codec, expected[i]) + expectedMap := map[string]interface{}{} + if err := encjson.Unmarshal([]byte(expectedJSON), &expectedMap); err != nil { + t.Fatal(err) + } + + actualJSON := runtime.EncodeOrDie(codec, obj) + actualMap := map[string]interface{}{} + if err := encjson.Unmarshal([]byte(actualJSON), &actualMap); err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(expectedMap, actualMap) { + t.Errorf("expectedMap: %#v, but actualMap: %#v", expectedMap, actualMap) + } + } +} + +// Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. +func TestGetSchemaObject(t *testing.T) { + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(schema.GroupVersion{Version: "v1"}) + t.Logf("%v", string(runtime.EncodeOrDie(codec, &api.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}))) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &api.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})}, + } + tf.ClientConfigVal = defaultClientConfig() + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.Run(cmd, []string{"replicationcontrollers", "foo"}) + + if !strings.Contains(buf.String(), "foo") { + t.Errorf("unexpected output: %s", buf.String()) + } +} + +func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) { + pods, _, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + // overide the openAPISchema function to return custom output + // for Pod type. + tf.OpenAPISchemaFunc = testOpenAPISchemaData + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Flags().Set(useOpenAPIPrintColumnFlagLabel, "true") + cmd.Run(cmd, []string{"pods", "foo"}) + + expected := `NAME RSRC +foo 10 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +type FakeResources struct { + resources map[schema.GroupVersionKind]proto.Schema +} + +func (f FakeResources) LookupResource(s schema.GroupVersionKind) proto.Schema { + return f.resources[s] +} + +var _ openapi.Resources = &FakeResources{} + +func testOpenAPISchemaData() (openapi.Resources, error) { + return &FakeResources{ + resources: map[schema.GroupVersionKind]proto.Schema{ + { + Version: "v1", + Kind: "Pod", + }: &proto.Primitive{ + BaseSchema: proto.BaseSchema{ + Extensions: map[string]interface{}{ + "x-kubernetes-print-columns": "custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion", + }, + }, + }, + }, + }, nil +} + +func TestGetObjects(t *testing.T) { + pods, _, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Run(cmd, []string{"pods", "foo"}) + + expected := `NAME READY STATUS RESTARTS AGE +foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetObjectsShowKind(t *testing.T) { + pods, _, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Flags().Set("show-kind", "true") + cmd.Run(cmd, []string{"pods", "foo"}) + + expected := `NAME READY STATUS RESTARTS AGE +pod/foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetObjectsShowLabels(t *testing.T) { + pods, _, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Flags().Set("show-labels", "true") + cmd.Run(cmd, []string{"pods", "foo"}) + + expected := `NAME READY STATUS RESTARTS AGE LABELS +foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetObjectIgnoreNotFound(t *testing.T) { + initTestErrorHandler(t) + + ns := &api.NamespaceList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "1", + }, + Items: []api.Namespace{ + { + ObjectMeta: metav1.ObjectMeta{Name: "testns", Namespace: "test", ResourceVersion: "11"}, + Spec: api.NamespaceSpec{}, + }, + }, + } + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == "/namespaces/test/pods/nonexistentpod" && m == "GET": + return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: stringBody("")}, nil + case p == "/api/v1/namespaces/test" && m == "GET": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &ns.Items[0])}, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Flags().Set("ignore-not-found", "true") + cmd.Flags().Set("output", "yaml") + cmd.Run(cmd, []string{"pods", "nonexistentpod"}) + + if buf.String() != "" { + t.Errorf("unexpected output: %s", buf.String()) + } +} + +func TestGetSortedObjects(t *testing.T) { + pods := &api.PodList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "15", + }, + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"}, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"}, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"}, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + }, + } + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, + } + tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: "v1"}}} + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + // sorting with metedata.name + cmd.Flags().Set("sort-by", ".metadata.name") + cmd.Run(cmd, []string{"pods"}) + + expected := `NAME READY STATUS RESTARTS AGE +a 0/0 0 +b 0/0 0 +c 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetObjectsIdentifiedByFile(t *testing.T) { + pods, _, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml") + cmd.Run(cmd, []string{}) + + expected := `NAME READY STATUS RESTARTS AGE +foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetListObjects(t *testing.T) { + pods, _, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Run(cmd, []string{"pods"}) + + expected := `NAME READY STATUS RESTARTS AGE +foo 0/0 0 +bar 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetListComponentStatus(t *testing.T) { + statuses := testComponentStatusData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, statuses)}, + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Run(cmd, []string{"componentstatuses"}) + + expected := `NAME STATUS MESSAGE ERROR +servergood Healthy ok +serverbad Unhealthy bad status: 500 +serverunknown Unhealthy fizzbuzz error +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetMixedGenericObjects(t *testing.T) { + initTestErrorHandler(t) + + // ensure that a runtime.Object without + // an ObjectMeta field is handled properly + structuredObj := &metav1.Status{ + TypeMeta: metav1.TypeMeta{ + Kind: "Status", + APIVersion: "v1", + }, + Status: "Success", + Message: "", + Reason: "", + Code: 0, + } + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch req.URL.Path { + case "/namespaces/test/pods": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, structuredObj)}, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + tf.ClientConfigVal = defaultClientConfig() + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Flags().Set("output", "json") + cmd.Run(cmd, []string{"pods"}) + + expected := `{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "kind": "Status", + "metadata": {}, + "status": "Success" + } + ], + "kind": "List", + "metadata": { + "resourceVersion": "", + "selfLink": "" + } +} +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetMultipleTypeObjects(t *testing.T) { + pods, svc, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch req.URL.Path { + case "/namespaces/test/pods": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil + case "/namespaces/test/services": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + cmd.Run(cmd, []string{"pods,services"}) + + expected := `NAME READY STATUS RESTARTS AGE +pod/foo 0/0 0 +pod/bar 0/0 0 +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/baz ClusterIP +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetMultipleTypeObjectsAsList(t *testing.T) { + pods, svc, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch req.URL.Path { + case "/namespaces/test/pods": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil + case "/namespaces/test/services": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + tf.ClientConfigVal = defaultClientConfig() + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Flags().Set("output", "json") + cmd.Run(cmd, []string{"pods,services"}) + + expected := `{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "creationTimestamp": null, + "name": "foo", + "namespace": "test", + "resourceVersion": "10" + }, + "spec": { + "containers": null, + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + }, + "status": {} + }, + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "creationTimestamp": null, + "name": "bar", + "namespace": "test", + "resourceVersion": "11" + }, + "spec": { + "containers": null, + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + }, + "status": {} + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "creationTimestamp": null, + "name": "baz", + "namespace": "test", + "resourceVersion": "12" + }, + "spec": { + "sessionAffinity": "None", + "type": "ClusterIP" + }, + "status": { + "loadBalancer": {} + } + } + ], + "kind": "List", + "metadata": { + "resourceVersion": "", + "selfLink": "" + } +} +` + if e, a := expected, buf.String(); e != a { + t.Errorf("did not match: %v", diff.StringDiff(e, a)) + } +} + +func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) { + pods, svc, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" { + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + } + switch req.URL.Path { + case "/namespaces/test/pods": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil + case "/namespaces/test/services": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Flags().Set("selector", "a=b") + cmd.Run(cmd, []string{"pods,services"}) + + expected := `NAME READY STATUS RESTARTS AGE +pod/foo 0/0 0 +pod/bar 0/0 0 +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/baz ClusterIP +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) { + pods, svc, _ := testData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" { + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + } + switch req.URL.Path { + case "/namespaces/test/pods": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil + case "/namespaces/test/services": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Flags().Set("field-selector", "a=b") + cmd.Run(cmd, []string{"pods,services"}) + + expected := `NAME READY STATUS RESTARTS AGE +pod/foo 0/0 0 +pod/bar 0/0 0 +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/baz ClusterIP +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { + _, svc, _ := testData() + node := &api.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }, + } + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch req.URL.Path { + case "/nodes/foo": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, node)}, nil + case "/namespaces/test/services/bar": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Run(cmd, []string{"services/bar", "node/foo"}) + + expected := `NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/baz ClusterIP +NAME STATUS ROLES AGE VERSION +node/foo Unknown +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func watchTestData() ([]api.Pod, []watch.Event) { + pods := []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + Namespace: "test", + ResourceVersion: "9", + }, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "test", + ResourceVersion: "10", + }, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + } + events := []watch.Event{ + // current state events + { + Type: watch.Added, + Object: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + Namespace: "test", + ResourceVersion: "9", + }, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + }, + { + Type: watch.Added, + Object: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "test", + ResourceVersion: "10", + }, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + }, + // resource events + { + Type: watch.Modified, + Object: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "test", + ResourceVersion: "11", + }, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + }, + { + Type: watch.Deleted, + Object: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "test", + ResourceVersion: "12", + }, + Spec: apitesting.V1DeepEqualSafePodSpec(), + }, + }, + } + return pods, events +} + +func TestWatchLabelSelector(t *testing.T) { + pods, events := watchTestData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + podList := &api.PodList{ + Items: pods, + ListMeta: metav1.ListMeta{ + ResourceVersion: "10", + }, + } + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" { + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + } + switch req.URL.Path { + case "/namespaces/test/pods": + if req.URL.Query().Get("watch") == "true" { + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Flags().Set("watch", "true") + cmd.Flags().Set("selector", "a=b") + cmd.Run(cmd, []string{"pods"}) + + expected := `NAME READY STATUS RESTARTS AGE +bar 0/0 0 +foo 0/0 0 +foo 0/0 0 +foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestWatchFieldSelector(t *testing.T) { + pods, events := watchTestData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + podList := &api.PodList{ + Items: pods, + ListMeta: metav1.ListMeta{ + ResourceVersion: "10", + }, + } + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" { + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + } + switch req.URL.Path { + case "/namespaces/test/pods": + if req.URL.Query().Get("watch") == "true" { + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Flags().Set("watch", "true") + cmd.Flags().Set("field-selector", "a=b") + cmd.Run(cmd, []string{"pods"}) + + expected := `NAME READY STATUS RESTARTS AGE +bar 0/0 0 +foo 0/0 0 +foo 0/0 0 +foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestWatchResource(t *testing.T) { + pods, events := watchTestData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch req.URL.Path { + case "/namespaces/test/pods/foo": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil + case "/namespaces/test/pods": + if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" { + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil + } + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Flags().Set("watch", "true") + cmd.Run(cmd, []string{"pods", "foo"}) + + expected := `NAME READY STATUS RESTARTS AGE +foo 0/0 0 +foo 0/0 0 +foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestWatchResourceIdentifiedByFile(t *testing.T) { + pods, events := watchTestData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch req.URL.Path { + case "/namespaces/test/replicationcontrollers/cassandra": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil + case "/namespaces/test/replicationcontrollers": + if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=cassandra" { + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil + } + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Flags().Set("watch", "true") + cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml") + cmd.Run(cmd, []string{}) + + expected := `NAME READY STATUS RESTARTS AGE +foo 0/0 0 +foo 0/0 0 +foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestWatchOnlyResource(t *testing.T) { + pods, events := watchTestData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch req.URL.Path { + case "/namespaces/test/pods/foo": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil + case "/namespaces/test/pods": + if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" { + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil + } + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Flags().Set("watch-only", "true") + cmd.Run(cmd, []string{"pods", "foo"}) + + expected := `NAME READY STATUS RESTARTS AGE +foo 0/0 0 +foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func TestWatchOnlyList(t *testing.T) { + pods, events := watchTestData() + + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + podList := &api.PodList{ + Items: pods, + ListMeta: metav1.ListMeta{ + ResourceVersion: "10", + }, + } + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch req.URL.Path { + case "/namespaces/test/pods": + if req.URL.Query().Get("watch") == "true" { + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil + default: + t.Fatalf("request url: %#v,and request: %#v", req.URL, req) + return nil, nil + } + }), + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet("kubectl", tf, streams) + cmd.SetOutput(buf) + + cmd.Flags().Set("watch-only", "true") + cmd.Run(cmd, []string{"pods"}) + + expected := `NAME READY STATUS RESTARTS AGE +foo 0/0 0 +foo 0/0 0 +` + if e, a := expected, buf.String(); e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + +func watchBody(codec runtime.Codec, events []watch.Event) io.ReadCloser { + buf := bytes.NewBuffer([]byte{}) + enc := restclientwatch.NewEncoder(streaming.NewEncoder(buf, codec), codec) + for i := range events { + enc.Encode(&events[i]) + } + return json.Framer.NewFrameReader(ioutil.NopCloser(buf)) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/humanreadable_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/humanreadable_flags.go new file mode 100644 index 000000000..28b0e8f8b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/humanreadable_flags.go @@ -0,0 +1,144 @@ +/* +Copyright 2018 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 get + +import ( + "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kubernetes/pkg/kubectl/scheme" + "k8s.io/kubernetes/pkg/printers" + printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" +) + +// HumanPrintFlags provides default flags necessary for printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type HumanPrintFlags struct { + ShowKind *bool + ShowLabels *bool + SortBy *string + ColumnLabels *[]string + + // get.go-specific values + NoHeaders bool + + Kind schema.GroupKind + AbsoluteTimestamps bool + WithNamespace bool +} + +// SetKind sets the Kind option +func (f *HumanPrintFlags) SetKind(kind schema.GroupKind) { + f.Kind = kind +} + +// EnsureWithKind sets the "Showkind" humanreadable option to true. +func (f *HumanPrintFlags) EnsureWithKind() error { + showKind := true + f.ShowKind = &showKind + return nil +} + +// EnsureWithNamespace sets the "WithNamespace" humanreadable option to true. +func (f *HumanPrintFlags) EnsureWithNamespace() error { + f.WithNamespace = true + return nil +} + +func (f *HumanPrintFlags) AllowedFormats() []string { + return []string{"wide"} +} + +// ToPrinter receives an outputFormat and returns a printer capable of +// handling human-readable output. +func (f *HumanPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) { + if len(outputFormat) > 0 && outputFormat != "wide" { + return nil, genericclioptions.NoCompatiblePrinterError{Options: f, AllowedFormats: f.AllowedFormats()} + } + + decoder := scheme.Codecs.UniversalDecoder() + + showKind := false + if f.ShowKind != nil { + showKind = *f.ShowKind + } + + showLabels := false + if f.ShowLabels != nil { + showLabels = *f.ShowLabels + } + + columnLabels := []string{} + if f.ColumnLabels != nil { + columnLabels = *f.ColumnLabels + } + + p := printers.NewHumanReadablePrinter(decoder, printers.PrintOptions{ + Kind: f.Kind, + WithKind: showKind, + NoHeaders: f.NoHeaders, + Wide: outputFormat == "wide", + WithNamespace: f.WithNamespace, + ColumnLabels: columnLabels, + ShowLabels: showLabels, + }) + printersinternal.AddHandlers(p) + + // TODO(juanvallejo): handle sorting here + + return p, nil +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to human-readable printing to it +func (f *HumanPrintFlags) AddFlags(c *cobra.Command) { + if f.ShowLabels != nil { + c.Flags().BoolVar(f.ShowLabels, "show-labels", *f.ShowLabels, "When printing, show all labels as the last column (default hide labels column)") + } + if f.SortBy != nil { + c.Flags().StringVar(f.SortBy, "sort-by", *f.SortBy, "If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.") + } + if f.ColumnLabels != nil { + c.Flags().StringSliceVarP(f.ColumnLabels, "label-columns", "L", *f.ColumnLabels, "Accepts a comma separated list of labels that are going to be presented as columns. Names are case-sensitive. You can also use multiple flag options like -L label1 -L label2...") + } + if f.ShowKind != nil { + c.Flags().BoolVar(f.ShowKind, "show-kind", *f.ShowKind, "If present, list the resource type for the requested object(s).") + } +} + +// NewHumanPrintFlags returns flags associated with +// human-readable printing, with default values set. +func NewHumanPrintFlags() *HumanPrintFlags { + showLabels := false + sortBy := "" + showKind := false + columnLabels := []string{} + + return &HumanPrintFlags{ + NoHeaders: false, + WithNamespace: false, + AbsoluteTimestamps: false, + ColumnLabels: &columnLabels, + + Kind: schema.GroupKind{}, + ShowLabels: &showLabels, + SortBy: &sortBy, + ShowKind: &showKind, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/humanreadable_flags_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/humanreadable_flags_test.go new file mode 100644 index 000000000..875b0c166 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/get/humanreadable_flags_test.go @@ -0,0 +1,156 @@ +/* +Copyright 2018 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 get + +import ( + "bytes" + "regexp" + "strings" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) { + testObject := &api.Pod{ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Labels: map[string]string{ + "l1": "value", + }, + }} + + testCases := []struct { + name string + showKind bool + showLabels bool + + // TODO(juanvallejo): test sorting once it's moved to the HumanReadablePrinter + sortBy string + columnLabels []string + + noHeaders bool + withNamespace bool + + outputFormat string + + expectedError string + expectedOutput string + expectNoMatch bool + }{ + { + name: "empty output format matches a humanreadable printer", + expectedOutput: "NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\nfoo\\ +0/0\\ +0\\ +\n", + }, + { + name: "\"wide\" output format prints", + outputFormat: "wide", + expectedOutput: "NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\\ +IP\\ +NODE\\ +NOMINATED NODE\nfoo\\ +0/0\\ +0\\ +\\ +\\ +\\ +\n", + }, + { + name: "no-headers prints output with no headers", + noHeaders: true, + expectedOutput: "foo\\ +0/0\\ +0\\ +\n", + }, + { + name: "no-headers and a \"wide\" output format prints output with no headers and additional columns", + outputFormat: "wide", + noHeaders: true, + expectedOutput: "foo\\ +0/0\\ +0\\ +\\ +\\ +\\ +\n", + }, + { + name: "show-kind displays the resource's kind, even when printing a single type of resource", + showKind: true, + expectedOutput: "NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\npod/foo\\ +0/0\\ +0\\ +\n", + }, + { + name: "label-columns prints specified label values in new column", + columnLabels: []string{"l1"}, + expectedOutput: "NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\\ +L1\nfoo\\ +0/0\\ +0\\ +\\ +value\n", + }, + { + name: "withNamespace displays an additional NAMESPACE column", + withNamespace: true, + expectedOutput: "NAMESPACE\\ +NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\n\\ +foo\\ +0/0\\ +0\\ +\n", + }, + { + name: "no printer is matched on an invalid outputFormat", + outputFormat: "invalid", + expectNoMatch: true, + }, + { + name: "printer should not match on any other format supported by another printer", + outputFormat: "go-template", + expectNoMatch: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + printFlags := HumanPrintFlags{ + ShowKind: &tc.showKind, + ShowLabels: &tc.showLabels, + SortBy: &tc.sortBy, + ColumnLabels: &tc.columnLabels, + + NoHeaders: tc.noHeaders, + WithNamespace: tc.withNamespace, + } + + if tc.showKind { + printFlags.Kind = schema.GroupKind{Kind: "pod"} + } + + p, err := printFlags.ToPrinter(tc.outputFormat) + if tc.expectNoMatch { + if !genericclioptions.IsNoCompatiblePrinterError(err) { + t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) + } + return + } + if genericclioptions.IsNoCompatiblePrinterError(err) { + t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) + } + + if len(tc.expectedError) > 0 { + if err == nil || !strings.Contains(err.Error(), tc.expectedError) { + t.Errorf("expecting error %q, got %v", tc.expectedError, err) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + out := bytes.NewBuffer([]byte{}) + err = p.PrintObj(testObject, out) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + match, err := regexp.Match(tc.expectedOutput, out.Bytes()) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !match { + t.Errorf("unexpected output: expecting %q, got %q", tc.expectedOutput, out.String()) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/label.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/label.go index 7784f9f6f..f89024770 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/label.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/label.go @@ -18,7 +18,6 @@ package cmd import ( "fmt" - "io" "reflect" "strings" @@ -28,16 +27,19 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/validation" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -45,6 +47,10 @@ import ( type LabelOptions struct { // Filename options resource.FilenameOptions + RecordFlags *genericclioptions.RecordFlags + + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) // Common user flags overwrite bool @@ -54,6 +60,7 @@ type LabelOptions struct { all bool resourceVersion string selector string + fieldSelector string outputFormat string // results of arg parsing @@ -61,8 +68,16 @@ type LabelOptions struct { newLabels map[string]string removeLabels []string + Recorder genericclioptions.Recorder + + namespace string + enforceNamespace bool + includeUninitialized bool + builder *resource.Builder + unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) + // Common shared fields - out io.Writer + genericclioptions.IOStreams } var ( @@ -95,9 +110,19 @@ var ( kubectl label pods foo bar-`)) ) -func NewCmdLabel(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &LabelOptions{} - validArgs := cmdutil.ValidArgList(f) +func NewLabelOptions(ioStreams genericclioptions.IOStreams) *LabelOptions { + return &LabelOptions{ + RecordFlags: genericclioptions.NewRecordFlags(), + Recorder: genericclioptions.NoopRecorder{}, + + PrintFlags: genericclioptions.NewPrintFlags("labeled").WithTypeSetter(scheme.Scheme), + + IOStreams: ioStreams, + } +} + +func NewCmdLabel(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewLabelOptions(ioStreams) cmd := &cobra.Command{ Use: "label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]", @@ -106,40 +131,52 @@ func NewCmdLabel(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: fmt.Sprintf(labelLong, validation.LabelValueMaxLength), Example: labelExample, Run: func(cmd *cobra.Command, args []string) { - if err := options.Complete(out, cmd, args); err != nil { - cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error())) - } - if err := options.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error())) - } - cmdutil.CheckErr(options.RunLabel(f, cmd)) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunLabel()) }, - ValidArgs: validArgs, - ArgAliases: kubectl.ResourceAliases(validArgs), } - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().BoolVar(&options.overwrite, "overwrite", options.overwrite, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.") - cmd.Flags().BoolVar(&options.list, "list", options.list, "If true, display the labels for a given resource.") - cmd.Flags().BoolVar(&options.local, "local", options.local, "If true, label will NOT contact api-server but run locally.") - cmd.Flags().StringVarP(&options.selector, "selector", "l", options.selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).") - cmd.Flags().BoolVar(&options.all, "all", options.all, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") - cmd.Flags().StringVar(&options.resourceVersion, "resource-version", options.resourceVersion, i18n.T("If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")) + + o.RecordFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) + + cmd.Flags().BoolVar(&o.overwrite, "overwrite", o.overwrite, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.") + cmd.Flags().BoolVar(&o.list, "list", o.list, "If true, display the labels for a given resource.") + cmd.Flags().BoolVar(&o.local, "local", o.local, "If true, label will NOT contact api-server but run locally.") + cmd.Flags().StringVarP(&o.selector, "selector", "l", o.selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).") + cmd.Flags().StringVar(&o.fieldSelector, "field-selector", o.fieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") + cmd.Flags().BoolVar(&o.all, "all", o.all, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") + cmd.Flags().StringVar(&o.resourceVersion, "resource-version", o.resourceVersion, i18n.T("If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")) usage := "identifying the resource to update the labels" - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) cmdutil.AddDryRunFlag(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } // Complete adapts from the command line args and factory to the data required. -func (o *LabelOptions) Complete(out io.Writer, cmd *cobra.Command, args []string) (err error) { - o.out = out +func (o *LabelOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + o.outputFormat = cmdutil.GetFlagString(cmd, "output") o.dryrun = cmdutil.GetDryRunFlag(cmd) + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + if o.dryrun { + o.PrintFlags.Complete("%s (dry run)") + } + + return o.PrintFlags.ToPrinter() + } + resources, labelArgs, err := cmdutil.GetResourcesAndPairs(args, "label") if err != nil { return err @@ -148,10 +185,18 @@ func (o *LabelOptions) Complete(out io.Writer, cmd *cobra.Command, args []string o.newLabels, o.removeLabels, err = parseLabels(labelArgs) if o.list && len(o.outputFormat) > 0 { - return cmdutil.UsageErrorf(cmd, "--list and --output may not be specified together") + return fmt.Errorf("--list and --output may not be specified together") + } + + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err } + o.includeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, false) + o.builder = f.NewBuilder() + o.unstructuredClientForMapping = f.UnstructuredClientForMapping - return err + return nil } // Validate checks to the LabelOptions to see if there is sufficient information run the command. @@ -159,6 +204,9 @@ func (o *LabelOptions) Validate() error { if o.all && len(o.selector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") } + if o.all && len(o.fieldSelector) > 0 { + return fmt.Errorf("cannot set --all and --field-selector at the same time") + } if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) { return fmt.Errorf("one or more resources must be specified as or /") } @@ -169,26 +217,19 @@ func (o *LabelOptions) Validate() error { } // RunLabel does the work -func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error { - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - changeCause := f.Command(cmd, false) - - includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) - b := f.NewBuilder(). +func (o *LabelOptions) RunLabel() error { + b := o.builder. Unstructured(). LocalParam(o.local). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &o.FilenameOptions). - IncludeUninitialized(includeUninitialized). + NamespaceParam(o.namespace).DefaultNamespace(). + FilenameParam(o.enforceNamespace, &o.FilenameOptions). + IncludeUninitialized(o.includeUninitialized). Flatten() if !o.local { b = b.LabelSelectorParam(o.selector). + FieldSelectorParam(o.fieldSelector). ResourceTypeOrNameArgs(o.all, o.resources...). Latest() } @@ -232,17 +273,15 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error { } for _, label := range o.removeLabels { if _, ok := accessor.GetLabels()[label]; !ok { - fmt.Fprintf(o.out, "label %q not found.\n", label) + fmt.Fprintf(o.Out, "label %q not found.\n", label) } } if err := labelFunc(obj, o.overwrite, o.resourceVersion, o.newLabels, o.removeLabels); err != nil { return err } - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(obj, changeCause); err != nil { - return err - } + if err := o.Recorder.Record(obj); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } newData, err := json.Marshal(obj) if err != nil { @@ -258,7 +297,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error { } mapping := info.ResourceMapping() - client, err := f.UnstructuredClientForMapping(mapping) + client, err := o.unstructuredClientForMapping(mapping) if err != nil { return err } @@ -280,17 +319,27 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error { return err } + indent := "" + if !one { + indent = " " + gvks, _, err := unstructuredscheme.NewUnstructuredObjectTyper().ObjectKinds(info.Object) + if err != nil { + return err + } + fmt.Fprintf(o.ErrOut, "Listing labels for %s.%s/%s:\n", gvks[0].Kind, gvks[0].Group, info.Name) + } for k, v := range accessor.GetLabels() { - fmt.Fprintf(o.out, "%s=%s\n", k, v) + fmt.Fprintf(o.Out, "%s%s=%s\n", indent, k, v) } return nil } - if len(o.outputFormat) > 0 { - return cmdutil.PrintObject(cmd, outputObj, o.out) + printer, err := o.ToPrinter(dataChangeMsg) + if err != nil { + return err } - cmdutil.PrintSuccess(false, o.out, info.Object, o.dryrun, dataChangeMsg) + printer.PrintObj(info.Object, o.Out) return nil }) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/label_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/label_test.go index 96fe2ffd4..f0264645e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/label_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/label_test.go @@ -29,7 +29,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -322,26 +322,26 @@ func TestLabelErrors(t *testing.T) { for k, testCase := range testCases { t.Run(k, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() + ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLabel(tf, buf) + cmd := NewCmdLabel(tf, ioStreams) cmd.SetOutput(buf) for k, v := range testCase.flags { cmd.Flags().Set(k, v) } - opts := LabelOptions{} - err := opts.Complete(buf, cmd, testCase.args) + opts := NewLabelOptions(ioStreams) + err := opts.Complete(tf, cmd, testCase.args) if err == nil { err = opts.Validate() } if err == nil { - err = opts.RunLabel(tf, cmd) + err = opts.RunLabel() } if !testCase.errFn(err) { t.Errorf("%s: unexpected error: %v", k, err) @@ -356,10 +356,10 @@ func TestLabelErrors(t *testing.T) { func TestLabelForResourceFromFile(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -387,19 +387,18 @@ func TestLabelForResourceFromFile(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLabel(tf, buf) - opts := LabelOptions{FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}} - err := opts.Complete(buf, cmd, []string{"a=b"}) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdLabel(tf, ioStreams) + opts := NewLabelOptions(ioStreams) + opts.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} + err := opts.Complete(tf, cmd, []string{"a=b"}) if err == nil { err = opts.Validate() } if err == nil { - err = opts.RunLabel(tf, cmd) + err = opts.RunLabel() } if err != nil { t.Fatalf("unexpected error: %v", err) @@ -410,7 +409,7 @@ func TestLabelForResourceFromFile(t *testing.T) { } func TestLabelLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.UnstructuredClient = &fake.RESTClient{ @@ -420,20 +419,19 @@ func TestLabelLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLabel(tf, buf) - opts := LabelOptions{FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, - local: true} - err := opts.Complete(buf, cmd, []string{"a=b"}) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdLabel(tf, ioStreams) + opts := NewLabelOptions(ioStreams) + opts.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} + opts.local = true + err := opts.Complete(tf, cmd, []string{"a=b"}) if err == nil { err = opts.Validate() } if err == nil { - err = opts.RunLabel(tf, cmd) + err = opts.RunLabel() } if err != nil { t.Fatalf("unexpected error: %v", err) @@ -445,10 +443,10 @@ func TestLabelLocal(t *testing.T) { func TestLabelMultipleObjects(t *testing.T) { pods, _, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -478,18 +476,18 @@ func TestLabelMultipleObjects(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLabel(tf, buf) - opts := LabelOptions{all: true} - err := opts.Complete(buf, cmd, []string{"pods", "a=b"}) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + opts := NewLabelOptions(ioStreams) + opts.all = true + cmd := NewCmdLabel(tf, ioStreams) + err := opts.Complete(tf, cmd, []string{"pods", "a=b"}) if err == nil { err = opts.Validate() } if err == nil { - err = opts.RunLabel(tf, cmd) + err = opts.RunLabel() } if err != nil { t.Fatalf("unexpected error: %v", err) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/logs.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/logs.go index d6d965c38..9b5e55cf5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/logs.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/logs.go @@ -18,20 +18,22 @@ package cmd import ( "errors" + "fmt" "io" - "math" "os" "time" "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - restclient "k8s.io/client-go/rest" + "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/util" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -41,8 +43,11 @@ var ( # Return snapshot logs from pod nginx with only one container kubectl logs nginx - # Return snapshot logs for the pods defined by label app=nginx - kubectl logs -lapp=nginx + # Return snapshot logs from pod nginx with multi containers + kubectl logs nginx --all-containers=true + + # Return snapshot logs from all containers in pods defined by label app=nginx + kubectl logs -lapp=nginx --all-containers=true # Return snapshot of previous terminated ruby container logs from pod web-1 kubectl logs -p -c ruby web-1 @@ -70,24 +75,30 @@ const ( ) type LogsOptions struct { - Namespace string - ResourceArg string - Options runtime.Object + Namespace string + ResourceArg string + AllContainers bool + Options runtime.Object - Mapper meta.RESTMapper - Typer runtime.ObjectTyper - Decoder runtime.Decoder + Object runtime.Object + GetPodTimeout time.Duration + RESTClientGetter genericclioptions.RESTClientGetter + LogsForObject polymorphichelpers.LogsForObjectFunc - Object runtime.Object - GetPodTimeout time.Duration - LogsForObject func(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) + genericclioptions.IOStreams +} - Out io.Writer +func NewLogsOptions(streams genericclioptions.IOStreams, allContainers bool) *LogsOptions { + return &LogsOptions{ + IOStreams: streams, + AllContainers: allContainers, + } } // NewCmdLogs creates a new pod logs command -func NewCmdLogs(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - o := &LogsOptions{} +func NewCmdLogs(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewLogsOptions(streams, false) + cmd := &cobra.Command{ Use: "logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]", DisableFlagsInUseLine: true, @@ -96,16 +107,17 @@ func NewCmdLogs(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { Example: logsExample, PreRun: func(cmd *cobra.Command, args []string) { if len(os.Args) > 1 && os.Args[1] == "log" { - printDeprecationWarning(errOut, "logs", "log") + printDeprecationWarning(o.ErrOut, "logs", "log") } }, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(o.Complete(f, out, cmd, args)) + cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) cmdutil.CheckErr(o.RunLogs()) }, Aliases: []string{"log"}, } + cmd.Flags().BoolVar(&o.AllContainers, "all-containers", o.AllContainers, "Get all containers's logs in the pod(s).") cmd.Flags().BoolP("follow", "f", false, "Specify if the logs should be streamed.") cmd.Flags().Bool("timestamps", false, "Include timestamps on each line in the log output") cmd.Flags().Int64("limit-bytes", 0, "Maximum bytes of logs to return. Defaults to no limit.") @@ -116,13 +128,12 @@ func NewCmdLogs(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { cmd.Flags().StringP("container", "c", "", "Print the logs of this container") cmd.Flags().Bool("interactive", false, "If true, prompt the user for input when required.") cmd.Flags().MarkDeprecated("interactive", "This flag is no longer respected and there is no replacement.") - cmdutil.AddInclude3rdPartyFlags(cmd) cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodLogsTimeout) cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.") return cmd } -func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { +func (o *LogsOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { containerName := cmdutil.GetFlagString(cmd, "container") selector := cmdutil.GetFlagString(cmd, "selector") switch len(args) { @@ -145,7 +156,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm return cmdutil.UsageErrorf(cmd, "%s", logsUsageStr) } var err error - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -172,7 +183,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm } if sinceSeconds := cmdutil.GetFlagDuration(cmd, "since"); sinceSeconds != 0 { // round up to the nearest second - sec := int64(math.Ceil(float64(sinceSeconds) / float64(time.Second))) + sec := int64(sinceSeconds.Round(time.Second).Seconds()) logOptions.SinceSeconds = &sec } o.GetPodTimeout, err = cmdutil.GetPodRunningTimeoutFlag(cmd) @@ -180,8 +191,8 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm return err } o.Options = logOptions - o.LogsForObject = f.LogsForObject - o.Out = out + o.RESTClientGetter = f + o.LogsForObject = polymorphichelpers.LogsForObjectFn if len(selector) != 0 { if logOptions.Follow { @@ -194,7 +205,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm if o.Object == nil { builder := f.NewBuilder(). - Internal(). + WithScheme(legacyscheme.Scheme). NamespaceParam(o.Namespace).DefaultNamespace(). SingleResourceType() if o.ResourceArg != "" { @@ -221,6 +232,9 @@ func (o LogsOptions) Validate() error { if !ok { return errors.New("unexpected logs options object") } + if o.AllContainers && len(logsOptions.Container) > 0 { + return fmt.Errorf("--all-containers=true should not be specified with container name %s", logsOptions.Container) + } if errs := validation.ValidatePodLogOptions(logsOptions); len(errs) > 0 { return errs.ToAggregate() } @@ -233,18 +247,42 @@ func (o LogsOptions) RunLogs() error { switch t := o.Object.(type) { case *api.PodList: for _, p := range t.Items { - if err := o.getLogs(&p); err != nil { + if err := o.getPodLogs(&p); err != nil { return err } } return nil + case *api.Pod: + return o.getPodLogs(t) default: return o.getLogs(o.Object) } } +// getPodLogs checks whether o.AllContainers is set to true. +// If so, it retrives all containers' log in the pod. +func (o LogsOptions) getPodLogs(pod *api.Pod) error { + if !o.AllContainers { + return o.getLogs(pod) + } + + for _, c := range pod.Spec.InitContainers { + o.Options.(*api.PodLogOptions).Container = c.Name + if err := o.getLogs(pod); err != nil { + return err + } + } + for _, c := range pod.Spec.Containers { + o.Options.(*api.PodLogOptions).Container = c.Name + if err := o.getLogs(pod); err != nil { + return err + } + } + return nil +} + func (o LogsOptions) getLogs(obj runtime.Object) error { - req, err := o.LogsForObject(obj, o.Options, o.GetPodTimeout) + req, err := o.LogsForObject(o.RESTClientGetter, obj, o.Options, o.GetPodTimeout) if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/logs_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/logs_test.go index 9476a76be..7b8243253 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/logs_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/logs_test.go @@ -18,19 +18,27 @@ package cmd import ( "bytes" + "errors" "io/ioutil" "net/http" - "os" "strings" "testing" + "time" "github.com/spf13/cobra" + "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -50,10 +58,10 @@ func TestLog(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { logContent := "test log content" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -67,17 +75,25 @@ func TestLog(t *testing.T) { body := ioutil.NopCloser(bytes.NewBufferString(logContent)) return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil default: - // Ensures no GET is performed when deleting by name t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) return nil, nil } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + oldLogFn := polymorphichelpers.LogsForObjectFn + defer func() { + polymorphichelpers.LogsForObjectFn = oldLogFn + }() + clientset, err := tf.ClientSet() + if err != nil { + t.Fatal(err) + } + polymorphichelpers.LogsForObjectFn = logTestMock{client: clientset}.logsForObject - cmd := NewCmdLogs(tf, buf, buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + + cmd := NewCmdLogs(tf, streams) cmd.Flags().Set("namespace", "test") cmd.Run(cmd, []string{"foo"}) @@ -106,48 +122,60 @@ func testPod() *api.Pod { func TestValidateLogFlags(t *testing.T) { f := cmdtesting.NewTestFactory() defer f.Cleanup() + f.WithNamespace("") tests := []struct { name string flags map[string]string + args []string expected string }{ { name: "since & since-time", flags: map[string]string{"since": "1h", "since-time": "2006-01-02T15:04:05Z"}, + args: []string{"foo"}, expected: "at most one of `sinceTime` or `sinceSeconds` may be specified", }, { name: "negative since-time", flags: map[string]string{"since": "-1s"}, + args: []string{"foo"}, expected: "must be greater than 0", }, { name: "negative limit-bytes", flags: map[string]string{"limit-bytes": "-100"}, + args: []string{"foo"}, expected: "must be greater than 0", }, { name: "negative tail", flags: map[string]string{"tail": "-100"}, + args: []string{"foo"}, expected: "must be greater than or equal to 0", }, + { + name: "container name combined with --all-containers", + flags: map[string]string{"all-containers": "true"}, + args: []string{"my-pod", "my-container"}, + expected: "--all-containers=true should not be specified with container", + }, } for _, test := range tests { - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLogs(f, buf, buf) + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdLogs(f, streams) out := "" for flag, value := range test.flags { cmd.Flags().Set(flag, value) } // checkErr breaks tests in case of errors, plus we just // need to check errors returned by the command validation - o := &LogsOptions{} + o := NewLogsOptions(streams, test.flags["all-containers"] == "true") cmd.Run = func(cmd *cobra.Command, args []string) { - o.Complete(f, os.Stdout, cmd, args) + o.Complete(f, cmd, args) out = o.Validate().Error() } - cmd.Run(cmd, []string{"foo"}) + cmd.Run(cmd, test.args) if !strings.Contains(out, test.expected) { t.Errorf("%s: expected to find:\n\t%s\nfound:\n\t%s\n", test.name, test.expected, out) @@ -195,8 +223,7 @@ func TestLogComplete(t *testing.T) { }, } for _, test := range tests { - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLogs(f, buf, buf) + cmd := NewCmdLogs(f, genericclioptions.NewTestIOStreamsDiscard()) var err error out := "" for flag, value := range test.flags { @@ -204,11 +231,28 @@ func TestLogComplete(t *testing.T) { } // checkErr breaks tests in case of errors, plus we just // need to check errors returned by the command validation - o := &LogsOptions{} - err = o.Complete(f, os.Stdout, cmd, test.args) + o := NewLogsOptions(genericclioptions.NewTestIOStreamsDiscard(), false) + err = o.Complete(f, cmd, test.args) out = err.Error() if !strings.Contains(out, test.expected) { t.Errorf("%s: expected to find:\n\t%s\nfound:\n\t%s\n", test.name, test.expected, out) } } } + +type logTestMock struct { + client internalclientset.Interface +} + +func (m logTestMock) logsForObject(restClientGetter genericclioptions.RESTClientGetter, object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) { + switch t := object.(type) { + case *api.Pod: + opts, ok := options.(*api.PodLogOptions) + if !ok { + return nil, errors.New("provided options object is not a PodLogOptions") + } + return m.client.Core().Pods(t.Namespace).GetLogs(t.Name, opts), nil + default: + return nil, fmt.Errorf("cannot get the logs from %T", object) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/patch.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/patch.go index fd0b3adeb..14fa2c6a5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/patch.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/patch.go @@ -18,7 +18,6 @@ package cmd import ( "fmt" - "io" "reflect" "strings" @@ -26,18 +25,19 @@ import ( "github.com/golang/glog" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -49,9 +49,24 @@ var patchTypes = map[string]types.PatchType{"json": types.JSONPatchType, "merge" type PatchOptions struct { resource.FilenameOptions - Local bool + RecordFlags *genericclioptions.RecordFlags + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) + Recorder genericclioptions.Recorder - OutputFormat string + Local bool + PatchType string + Patch string + + namespace string + enforceNamespace bool + dryRun bool + outputFormat string + args []string + builder *resource.Builder + unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) + + genericclioptions.IOStreams } var ( @@ -79,9 +94,17 @@ var ( kubectl patch pod valid-pod --type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'`)) ) -func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &PatchOptions{} - validArgs := cmdutil.ValidArgList(f) +func NewPatchOptions(ioStreams genericclioptions.IOStreams) *PatchOptions { + return &PatchOptions{ + RecordFlags: genericclioptions.NewRecordFlags(), + Recorder: genericclioptions.NoopRecorder{}, + PrintFlags: genericclioptions.NewPrintFlags("patched").WithTypeSetter(scheme.Scheme), + IOStreams: ioStreams, + } +} + +func NewCmdPatch(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewPatchOptions(ioStreams) cmd := &cobra.Command{ Use: "patch (-f FILENAME | TYPE NAME) -p PATCH", @@ -90,65 +113,89 @@ func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: patchLong, Example: patchExample, Run: func(cmd *cobra.Command, args []string) { - options.OutputFormat = cmdutil.GetFlagString(cmd, "output") - err := RunPatch(f, out, cmd, args, options) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunPatch()) }, - ValidArgs: validArgs, - ArgAliases: kubectl.ResourceAliases(validArgs), } - cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.") - cmd.MarkFlagRequired("patch") - cmd.Flags().String("type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List())) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - usage := "identifying the resource to update" - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) + o.RecordFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) - cmd.Flags().BoolVar(&options.Local, "local", options.Local, "If true, patch will operate on the content of the file, not the server-side resource.") + cmd.Flags().StringVarP(&o.Patch, "patch", "p", "", "The patch to be applied to the resource JSON file.") + cmd.MarkFlagRequired("patch") + cmd.Flags().StringVar(&o.PatchType, "type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List())) + cmdutil.AddDryRunFlag(cmd) + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to update") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, patch will operate on the content of the file, not the server-side resource.") return cmd } -func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *PatchOptions) error { - switch { - case options.Local && len(args) != 0: - return fmt.Errorf("cannot specify --local and server resources") +func (o *PatchOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + + o.outputFormat = cmdutil.GetFlagString(cmd, "output") + o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run") + + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + if o.dryRun { + o.PrintFlags.Complete("%s (dry run)") + } + + return o.PrintFlags.ToPrinter() } - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } + o.args = args + o.builder = f.NewBuilder() + o.unstructuredClientForMapping = f.UnstructuredClientForMapping - patchType := types.StrategicMergePatchType - patchTypeString := strings.ToLower(cmdutil.GetFlagString(cmd, "type")) - if len(patchTypeString) != 0 { - ok := false - patchType, ok = patchTypes[patchTypeString] - if !ok { - return cmdutil.UsageErrorf(cmd, "--type must be one of %v, not %q", - sets.StringKeySet(patchTypes).List(), patchTypeString) + return nil +} + +func (o *PatchOptions) Validate() error { + if o.Local && len(o.args) != 0 { + return fmt.Errorf("cannot specify --local and server resources") + } + if len(o.Patch) == 0 { + return fmt.Errorf("must specify -p to patch") + } + if len(o.PatchType) != 0 { + if _, ok := patchTypes[strings.ToLower(o.PatchType)]; !ok { + return fmt.Errorf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), o.PatchType) } } - patch := cmdutil.GetFlagString(cmd, "patch") - if len(patch) == 0 { - return cmdutil.UsageErrorf(cmd, "Must specify -p to patch") + return nil +} + +func (o *PatchOptions) RunPatch() error { + patchType := types.StrategicMergePatchType + if len(o.PatchType) != 0 { + patchType = patchTypes[strings.ToLower(o.PatchType)] } - patchBytes, err := yaml.ToJSON([]byte(patch)) + + patchBytes, err := yaml.ToJSON([]byte(o.Patch)) if err != nil { - return fmt.Errorf("unable to parse %q: %v", patch, err) + return fmt.Errorf("unable to parse %q: %v", o.Patch, err) } - r := f.NewBuilder(). + r := o.builder. Unstructured(). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &options.FilenameOptions). - ResourceTypeOrNameArgs(false, args...). + NamespaceParam(o.namespace).DefaultNamespace(). + FilenameParam(o.enforceNamespace, &o.FilenameOptions). + ResourceTypeOrNameArgs(false, o.args...). Flatten(). Do() err = r.Err() @@ -163,56 +210,42 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin } name, namespace := info.Name, info.Namespace mapping := info.ResourceMapping() - client, err := f.UnstructuredClientForMapping(mapping) + client, err := o.unstructuredClientForMapping(mapping) if err != nil { return err } - if !options.Local { - dataChangedMsg := "not patched" - didPatch := false + if !o.Local && !o.dryRun { helper := resource.NewHelper(client, mapping) patchedObj, err := helper.Patch(namespace, name, patchType, patchBytes) if err != nil { return err } - // Record the change as a second patch to avoid trying to merge with a user's patch data - if cmdutil.ShouldRecord(cmd, info) { - // Copy the resource info and update with the result of applying the user's patch - infoCopy := *info - infoCopy.Object = patchedObj - if patch, patchType, err := cmdutil.ChangeResourcePatch(&infoCopy, f.Command(cmd, true)); err == nil { - if recordedObj, err := helper.Patch(info.Namespace, info.Name, patchType, patch); err != nil { - glog.V(4).Infof("error recording reason: %v", err) - } else { - patchedObj = recordedObj - } + + didPatch := !reflect.DeepEqual(info.Object, patchedObj) + + // if the recorder makes a change, compute and create another patch + if mergePatch, err := o.Recorder.MakeRecordMergePatch(patchedObj); err != nil { + glog.V(4).Infof("error recording current command: %v", err) + } else if len(mergePatch) > 0 { + if recordedObj, err := helper.Patch(info.Namespace, info.Name, types.MergePatchType, mergePatch); err != nil { + glog.V(4).Infof("error recording reason: %v", err) + } else { + patchedObj = recordedObj } } count++ - oldData, err := json.Marshal(info.Object) - if err != nil { - return err - } - newData, err := json.Marshal(patchedObj) - if err != nil { - return err - } - if !reflect.DeepEqual(oldData, newData) { - didPatch = true - dataChangedMsg = "patched" - } - // After computing whether we changed data, refresh the resource info with the resulting object if err := info.Refresh(patchedObj, true); err != nil { return err } - if len(options.OutputFormat) > 0 && options.OutputFormat != "name" { - return cmdutil.PrintObject(cmd, info.Object, out) + printer, err := o.ToPrinter(patchOperation(didPatch)) + if err != nil { + return err } - cmdutil.PrintSuccess(options.OutputFormat == "name", out, info.Object, false, dataChangedMsg) + printer.PrintObj(info.Object, o.Out) // if object was not successfully patched, exit with error code 1 if !didPatch { @@ -239,14 +272,23 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin return err } + didPatch := !reflect.DeepEqual(info.Object, targetObj) + // TODO: if we ever want to go generic, this allows a clean -o yaml without trying to print columns or anything // rawExtension := &runtime.Unknown{ // Raw: originalPatchedObjJS, // } - if err := info.Refresh(targetObj, true); err != nil { + if didPatch { + if err := info.Refresh(targetObj, true); err != nil { + return err + } + } + + printer, err := o.ToPrinter(patchOperation(didPatch)) + if err != nil { return err } - return cmdutil.PrintObject(cmd, info.Object, out) + return printer.PrintObj(info.Object, o.Out) }) if err != nil { return err @@ -282,3 +324,10 @@ func getPatchedJSON(patchType types.PatchType, originalJS, patchJS []byte, gvk s return nil, fmt.Errorf("unknown Content-Type header for patch: %v", patchType) } } + +func patchOperation(didPatch bool) string { + if didPatch { + return "patched" + } + return "not patched" +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/patch_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/patch_test.go index 6d9757eb5..9a6ee38ca 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/patch_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/patch_test.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "bytes" "net/http" "strings" "testing" @@ -25,16 +24,17 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestPatchObject(t *testing.T) { _, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -55,10 +55,9 @@ func TestPatchObject(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) + stream, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdPatch(tf, buf) + cmd := NewCmdPatch(tf, stream) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`) cmd.Flags().Set("output", "name") @@ -73,10 +72,10 @@ func TestPatchObject(t *testing.T) { func TestPatchObjectFromFile(t *testing.T) { _, svc, _ := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -90,14 +89,13 @@ func TestPatchObjectFromFile(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) + stream, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdPatch(tf, buf) + cmd := NewCmdPatch(tf, stream) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`) cmd.Flags().Set("output", "name") - cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml") cmd.Run(cmd, []string{}) // uses the name from the response @@ -111,10 +109,10 @@ func TestPatchNoop(t *testing.T) { getObject := &svc.Items[0] patchObject := &svc.Items[0] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -130,7 +128,6 @@ func TestPatchNoop(t *testing.T) { } }), } - tf.Namespace = "test" // Patched { @@ -139,12 +136,12 @@ func TestPatchNoop(t *testing.T) { patchObject.Annotations = map[string]string{} } patchObject.Annotations["foo"] = "bar" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdPatch(tf, buf) + stream, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdPatch(tf, stream) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("patch", `{"metadata":{"annotations":{"foo":"bar"}}}`) cmd.Run(cmd, []string{"services", "frontend"}) - if buf.String() != "service \"baz\" patched\n" { + if buf.String() != "service/baz patched\n" { t.Errorf("unexpected output: %s", buf.String()) } } @@ -159,10 +156,10 @@ func TestPatchObjectFromFileOutput(t *testing.T) { } svcCopy.Labels["post-patch"] = "post-patch-value" - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -178,14 +175,13 @@ func TestPatchObjectFromFileOutput(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) + stream, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdPatch(tf, buf) + cmd := NewCmdPatch(tf, stream) cmd.Flags().Set("namespace", "test") cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`) cmd.Flags().Set("output", "yaml") - cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml") cmd.Run(cmd, []string{}) t.Log(buf.String()) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/plugin.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/plugin.go index d34e78733..feb352531 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/plugin.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/plugin.go @@ -18,7 +18,6 @@ package cmd import ( "fmt" - "io" "os" "os/exec" "syscall" @@ -28,6 +27,7 @@ import ( "github.com/spf13/pflag" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/plugins" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -42,9 +42,9 @@ var ( ) // NewCmdPlugin creates the command that is the top-level for plugin commands. -func NewCmdPlugin(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command { +func NewCmdPlugin(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { // Loads plugins and create commands for each plugin identified - loadedPlugins, loadErr := f.PluginLoader().Load() + loadedPlugins, loadErr := pluginLoader().Load() if loadErr != nil { glog.V(1).Infof("Unable to load plugins: %v", loadErr) } @@ -58,14 +58,14 @@ func NewCmdPlugin(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Co if len(loadedPlugins) == 0 { cmdutil.CheckErr(fmt.Errorf("no plugins installed.")) } - cmdutil.DefaultSubCommandRun(err)(cmd, args) + cmdutil.DefaultSubCommandRun(streams.ErrOut)(cmd, args) }, } if len(loadedPlugins) > 0 { - pluginRunner := f.PluginRunner() + pluginRunner := pluginRunner() for _, p := range loadedPlugins { - cmd.AddCommand(NewCmdForPlugin(f, p, pluginRunner, in, out, err)) + cmd.AddCommand(NewCmdForPlugin(f, p, pluginRunner, streams)) } } @@ -73,7 +73,7 @@ func NewCmdPlugin(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Co } // NewCmdForPlugin creates a command capable of running the provided plugin. -func NewCmdForPlugin(f cmdutil.Factory, plugin *plugins.Plugin, runner plugins.PluginRunner, in io.Reader, out, errout io.Writer) *cobra.Command { +func NewCmdForPlugin(f cmdutil.Factory, plugin *plugins.Plugin, runner plugins.PluginRunner, streams genericclioptions.IOStreams) *cobra.Command { if !plugin.IsValid() { return nil } @@ -85,7 +85,7 @@ func NewCmdForPlugin(f cmdutil.Factory, plugin *plugins.Plugin, runner plugins.P Example: templates.Examples(plugin.Example), Run: func(cmd *cobra.Command, args []string) { if len(plugin.Command) == 0 { - cmdutil.DefaultSubCommandRun(errout)(cmd, args) + cmdutil.DefaultSubCommandRun(streams.ErrOut)(cmd, args) return } @@ -104,9 +104,7 @@ func NewCmdForPlugin(f cmdutil.Factory, plugin *plugins.Plugin, runner plugins.P } runningContext := plugins.RunningContext{ - In: in, - Out: out, - ErrOut: errout, + IOStreams: streams, Args: args, EnvProvider: envProvider, WorkingDir: plugin.Dir, @@ -117,7 +115,7 @@ func NewCmdForPlugin(f cmdutil.Factory, plugin *plugins.Plugin, runner plugins.P // check for (and exit with) the correct exit code // from a failed plugin command execution if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { - fmt.Fprintf(errout, "error: %v\n", err) + fmt.Fprintf(streams.ErrOut, "error: %v\n", err) os.Exit(status.ExitStatus()) } } @@ -132,7 +130,7 @@ func NewCmdForPlugin(f cmdutil.Factory, plugin *plugins.Plugin, runner plugins.P } for _, childPlugin := range plugin.Tree { - cmd.AddCommand(NewCmdForPlugin(f, childPlugin, runner, in, out, errout)) + cmd.AddCommand(NewCmdForPlugin(f, childPlugin, runner, streams)) } return cmd @@ -160,7 +158,7 @@ type factoryAttrsPluginEnvProvider struct { } func (p *factoryAttrsPluginEnvProvider) Env() (plugins.EnvList, error) { - cmdNamespace, _, err := p.factory.DefaultNamespace() + cmdNamespace, _, err := p.factory.ToRawKubeConfigLoader().Namespace() if err != nil { return plugins.EnvList{}, err } @@ -168,3 +166,22 @@ func (p *factoryAttrsPluginEnvProvider) Env() (plugins.EnvList, error) { plugins.Env{N: "KUBECTL_PLUGINS_CURRENT_NAMESPACE", V: cmdNamespace}, }, nil } + +// pluginLoader loads plugins from a path set by the KUBECTL_PLUGINS_PATH env var. +// If this env var is not set, it defaults to +// "~/.kube/plugins", plus +// "./kubectl/plugins" directory under the "data dir" directory specified by the XDG +// system directory structure spec for the given platform. +func pluginLoader() plugins.PluginLoader { + if len(os.Getenv("KUBECTL_PLUGINS_PATH")) > 0 { + return plugins.KubectlPluginsPathPluginLoader() + } + return plugins.TolerantMultiPluginLoader{ + plugins.XDGDataDirsPluginLoader(), + plugins.UserDirPluginLoader(), + } +} + +func pluginRunner() plugins.PluginRunner { + return &plugins.ExecPluginRunner{} +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/plugin_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/plugin_test.go index 205b26674..c47646dd8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/plugin_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/plugin_test.go @@ -17,12 +17,12 @@ limitations under the License. package cmd import ( - "bytes" "fmt" "testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/plugins" ) @@ -81,9 +81,7 @@ func TestPluginCmd(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - inBuf := bytes.NewBuffer([]byte{}) - outBuf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + streams, _, outBuf, errBuf := genericclioptions.NewTestIOStreams() cmdutil.BehaviorOnFatal(func(str string, code int) { errBuf.Write([]byte(str)) @@ -96,7 +94,7 @@ func TestPluginCmd(t *testing.T) { f := cmdtesting.NewTestFactory() defer f.Cleanup() - cmd := NewCmdForPlugin(f, test.plugin, runner, inBuf, outBuf, errBuf) + cmd := NewCmdForPlugin(f, test.plugin, runner, streams) if cmd == nil { if !test.expectedNilCmd { t.Fatalf("%s: command was unexpectedly not registered", test.name) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/portforward.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/portforward.go index 9dc690d33..3baa3bee0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/portforward.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/portforward.go @@ -18,7 +18,6 @@ package cmd import ( "fmt" - "io" "net/http" "net/url" "os" @@ -33,10 +32,13 @@ import ( restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/portforward" "k8s.io/client-go/transport/spdy" + "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/util" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -83,11 +85,10 @@ const ( defaultPodPortForwardWaitTimeout = 60 * time.Second ) -func NewCmdPortForward(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command { +func NewCmdPortForward(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { opts := &PortForwardOptions{ PortForwarder: &defaultPortForwarder{ - cmdOut: cmdOut, - cmdErr: cmdErr, + IOStreams: streams, }, } cmd := &cobra.Command{ @@ -118,7 +119,7 @@ type portForwarder interface { } type defaultPortForwarder struct { - cmdOut, cmdErr io.Writer + genericclioptions.IOStreams } func (f *defaultPortForwarder) ForwardPorts(method string, url *url.URL, opts PortForwardOptions) error { @@ -127,7 +128,7 @@ func (f *defaultPortForwarder) ForwardPorts(method string, url *url.URL, opts Po return err } dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, method, url) - fw, err := portforward.New(dialer, opts.Ports, opts.StopChannel, opts.ReadyChannel, f.cmdOut, f.cmdErr) + fw, err := portforward.New(dialer, opts.Ports, opts.StopChannel, opts.ReadyChannel, f.Out, f.ErrOut) if err != nil { return err } @@ -173,13 +174,13 @@ func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg return cmdutil.UsageErrorf(cmd, "TYPE/NAME and list of ports are required for port-forward") } - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } builder := f.NewBuilder(). - Internal(). + WithScheme(legacyscheme.Scheme). ContinueOnError(). NamespaceParam(o.Namespace).DefaultNamespace() @@ -196,7 +197,7 @@ func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg return err } - forwardablePod, err := f.AttachablePodForObject(obj, getPodTimeout) + forwardablePod, err := polymorphichelpers.AttachablePodForObjectFn(f, obj, getPodTimeout) if err != nil { return err } @@ -218,9 +219,10 @@ func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg if err != nil { return err } + o.PodClient = clientset.Core() - o.Config, err = f.ClientConfig() + o.Config, err = f.ToRESTConfig() if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/portforward_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/portforward_test.go index a4ba152e2..c2ddde7fa 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/portforward_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/portforward_test.go @@ -20,7 +20,6 @@ import ( "fmt" "net/http" "net/url" - "os" "reflect" "testing" @@ -32,6 +31,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -73,10 +73,10 @@ func testPortForward(t *testing.T, flags map[string]string, args []string) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { var err error - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -89,13 +89,11 @@ func testPortForward(t *testing.T, flags map[string]string, args []string) { body := objBody(codec, test.pod) return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil default: - // Ensures no GET is performed when deleting by name t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) return nil, nil } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() ff := &fakePortForwarder{} if test.pfErr { @@ -103,7 +101,7 @@ func testPortForward(t *testing.T, flags map[string]string, args []string) { } opts := &PortForwardOptions{} - cmd := NewCmdPortForward(tf, os.Stdout, os.Stderr) + cmd := NewCmdPortForward(tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Run = func(cmd *cobra.Command, args []string) { if err = opts.Complete(tf, cmd, args); err != nil { return diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/proxy.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/proxy.go index 027dfbf1e..592912416 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/proxy.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/proxy.go @@ -28,6 +28,7 @@ import ( "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/proxy" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -69,7 +70,7 @@ var ( kubectl proxy --api-prefix=/k8s-api`)) ) -func NewCmdProxy(f cmdutil.Factory, out io.Writer) *cobra.Command { +func NewCmdProxy(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix]", DisableFlagsInUseLine: true, @@ -77,7 +78,7 @@ func NewCmdProxy(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: proxyLong, Example: proxyExample, Run: func(cmd *cobra.Command, args []string) { - err := RunProxy(f, out, cmd) + err := RunProxy(f, streams.Out, cmd) cmdutil.CheckErr(err) }, } @@ -104,7 +105,7 @@ func RunProxy(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { return errors.New("Don't specify both --unix-socket and --port") } - clientConfig, err := f.ClientConfig() + clientConfig, err := f.ToRESTConfig() if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/replace.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/replace.go index 3616ecc12..d44f7625c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/replace.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/replace.go @@ -18,21 +18,25 @@ package cmd import ( "fmt" - "io" "io/ioutil" "os" "path/filepath" + "time" "github.com/spf13/cobra" "github.com/golang/glog" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "k8s.io/kubernetes/pkg/kubectl/validation" ) var ( @@ -60,8 +64,41 @@ var ( kubectl replace --force -f ./pod.json`)) ) -func NewCmdReplace(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &resource.FilenameOptions{} +type ReplaceOptions struct { + PrintFlags *genericclioptions.PrintFlags + DeleteFlags *DeleteFlags + RecordFlags *genericclioptions.RecordFlags + + DeleteOptions *DeleteOptions + + PrintObj func(obj runtime.Object) error + + createAnnotation bool + validate bool + + Schema validation.Schema + Builder func() *resource.Builder + BuilderArgs []string + + Namespace string + EnforceNamespace bool + + Recorder genericclioptions.Recorder + + genericclioptions.IOStreams +} + +func NewReplaceOptions(streams genericclioptions.IOStreams) *ReplaceOptions { + return &ReplaceOptions{ + PrintFlags: genericclioptions.NewPrintFlags("replaced"), + DeleteFlags: NewDeleteFlags("to use to replace the resource."), + + IOStreams: streams, + } +} + +func NewCmdReplace(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewReplaceOptions(streams) cmd := &cobra.Command{ Use: "replace -f FILENAME", @@ -70,62 +107,106 @@ func NewCmdReplace(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: replaceLong, Example: replaceExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - err := RunReplace(f, out, cmd, args, options) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate(cmd)) + cmdutil.CheckErr(o.Run()) }, } - usage := "to use to replace the resource." - cmdutil.AddFilenameOptionFlags(cmd, options, usage) + + o.PrintFlags.AddFlags(cmd) + o.DeleteFlags.AddFlags(cmd) + o.RecordFlags.AddFlags(cmd) + cmd.MarkFlagRequired("filename") - cmd.Flags().Bool("force", false, "Delete and re-create the specified resource") - cmd.Flags().Bool("cascade", false, "Only relevant during a force replace. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController).") - cmd.Flags().Int("grace-period", -1, "Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative.") - cmd.Flags().Duration("timeout", 0, "Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object. Any other values should contain a corresponding time unit (e.g. 1s, 2m, 3h).") cmdutil.AddValidateFlags(cmd) - cmdutil.AddOutputFlagsForMutation(cmd) cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) return cmd } -func RunReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) +func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() if err != nil { return err } - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + o.validate = cmdutil.GetFlagBool(cmd, "validate") + o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag) + + printer, err := o.PrintFlags.ToPrinter() if err != nil { return err } + o.PrintObj = func(obj runtime.Object) error { + return printer.PrintObj(obj, o.Out) + } - force := cmdutil.GetFlagBool(cmd, "force") - if cmdutil.IsFilenameSliceEmpty(options.Filenames) { - return cmdutil.UsageErrorf(cmd, "Must specify --filename to replace") + dynamicClient, err := f.DynamicClient() + if err != nil { + return err + } + deleteOpts := o.DeleteFlags.ToOptions(dynamicClient, o.IOStreams) + + //Replace will create a resource if it doesn't exist already, so ignore not found error + deleteOpts.IgnoreNotFound = true + if o.PrintFlags.OutputFormat != nil { + deleteOpts.Output = *o.PrintFlags.OutputFormat + } + if deleteOpts.GracePeriod == 0 { + // To preserve backwards compatibility, but prevent accidental data loss, we convert --grace-period=0 + // into --grace-period=1 and wait until the object is successfully deleted. + deleteOpts.GracePeriod = 1 + deleteOpts.WaitForDeletion = true } + o.DeleteOptions = deleteOpts - shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" - if force { - return forceReplace(f, out, cmd, args, shortOutput, options) + schema, err := f.Validator(o.validate) + if err != nil { + return err } - if cmdutil.GetFlagInt(cmd, "grace-period") >= 0 { + o.Schema = schema + o.Builder = f.NewBuilder + o.BuilderArgs = args + + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + + return nil +} + +func (o *ReplaceOptions) Validate(cmd *cobra.Command) error { + if o.DeleteOptions.GracePeriod >= 0 && !o.DeleteOptions.ForceDeletion { return fmt.Errorf("--grace-period must have --force specified") } - if cmdutil.GetFlagDuration(cmd, "timeout") != 0 { + if o.DeleteOptions.Timeout != 0 && !o.DeleteOptions.ForceDeletion { return fmt.Errorf("--timeout must have --force specified") } - r := f.NewBuilder(). + if cmdutil.IsFilenameSliceEmpty(o.DeleteOptions.FilenameOptions.Filenames) { + return cmdutil.UsageErrorf(cmd, "Must specify --filename to replace") + } + + return nil +} + +func (o *ReplaceOptions) Run() error { + if o.DeleteOptions.ForceDeletion { + return o.forceReplace() + } + + r := o.Builder(). Unstructured(). - Schema(schema). + Schema(o.Schema). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.EnforceNamespace, &o.DeleteOptions.FilenameOptions). Flatten(). Do() if err := r.Err(); err != nil { @@ -137,14 +218,12 @@ func RunReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str return err } - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, cmdutil.InternalVersionJSONEncoder()); err != nil { + if err := kubectl.CreateOrUpdateAnnotation(o.createAnnotation, info.Object, cmdutil.InternalVersionJSONEncoder()); err != nil { return cmdutil.AddSourceToErr("replacing", info.Source, err) } - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command(cmd, false)); err != nil { - return cmdutil.AddSourceToErr("replacing", info.Source, err) - } + if err := o.Recorder.Record(info.Object); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } // Serialize the object with the annotation applied. @@ -154,23 +233,12 @@ func RunReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str } info.Refresh(obj, true) - cmdutil.PrintSuccess(shortOutput, out, info.Object, false, "replaced") - return nil + return o.PrintObj(info.Object) }) } -func forceReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *resource.FilenameOptions) error { - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) - if err != nil { - return err - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - for i, filename := range options.Filenames { +func (o *ReplaceOptions) forceReplace() error { + for i, filename := range o.DeleteOptions.FilenameOptions.Filenames { if filename == "-" { tempDir, err := ioutil.TempDir("", "kubectl_replace_") if err != nil { @@ -182,53 +250,36 @@ func forceReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s if err != nil { return err } - options.Filenames[i] = tempFilename + o.DeleteOptions.FilenameOptions.Filenames[i] = tempFilename } } - r := f.NewBuilder(). + r := o.Builder(). Unstructured(). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options). - ResourceTypeOrNameArgs(false, args...).RequireObject(false). + NamespaceParam(o.Namespace).DefaultNamespace(). + ResourceTypeOrNameArgs(false, o.BuilderArgs...).RequireObject(false). + FilenameParam(o.EnforceNamespace, &o.DeleteOptions.FilenameOptions). Flatten(). Do() if err := r.Err(); err != nil { return err } - //Replace will create a resource if it doesn't exist already, so ignore not found error - ignoreNotFound := true - timeout := cmdutil.GetFlagDuration(cmd, "timeout") - gracePeriod := cmdutil.GetFlagInt(cmd, "grace-period") - waitForDeletion := false - if gracePeriod == 0 { - // To preserve backwards compatibility, but prevent accidental data loss, we convert --grace-period=0 - // into --grace-period=1 and wait until the object is successfully deleted. - gracePeriod = 1 - waitForDeletion = true - } - // By default use a reaper to delete all related resources. - if cmdutil.GetFlagBool(cmd, "cascade") { - glog.Warningf("\"cascade\" is set, kubectl will delete and re-create all resources managed by this resource (e.g. Pods created by a ReplicationController). Consider using \"kubectl rolling-update\" if you want to update a ReplicationController together with its Pods.") - err = ReapResult(r, f, out, cmdutil.GetFlagBool(cmd, "cascade"), ignoreNotFound, timeout, gracePeriod, waitForDeletion, shortOutput, false) - } else { - err = DeleteResult(r, out, ignoreNotFound, gracePeriod, shortOutput) - } - if err != nil { + if err := o.DeleteOptions.DeleteResult(r); err != nil { return err } + timeout := o.DeleteOptions.Timeout if timeout == 0 { - timeout = kubectl.Timeout + timeout = 5 * time.Minute } - err = r.Visit(func(info *resource.Info, err error) error { + err := r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } - return wait.PollImmediate(kubectl.Interval, timeout, func() (bool, error) { + return wait.PollImmediate(1*time.Second, timeout, func() (bool, error) { if err := info.Get(); !errors.IsNotFound(err) { return false, err } @@ -239,12 +290,12 @@ func forceReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s return err } - r = f.NewBuilder(). + r = o.Builder(). Unstructured(). - Schema(schema). + Schema(o.Schema). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.EnforceNamespace, &o.DeleteOptions.FilenameOptions). Flatten(). Do() err = r.Err() @@ -258,14 +309,12 @@ func forceReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s return err } - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, cmdutil.InternalVersionJSONEncoder()); err != nil { + if err := kubectl.CreateOrUpdateAnnotation(o.createAnnotation, info.Object, cmdutil.InternalVersionJSONEncoder()); err != nil { return err } - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command(cmd, false)); err != nil { - return cmdutil.AddSourceToErr("replacing", info.Source, err) - } + if err := o.Recorder.Record(info.Object); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object) @@ -275,8 +324,7 @@ func forceReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s count++ info.Refresh(obj, true) - cmdutil.PrintSuccess(shortOutput, out, info.Object, false, "replaced") - return nil + return o.PrintObj(info.Object) }) if err != nil { return err diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/replace_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/replace_test.go index e3604da01..13e69d907 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/replace_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/replace_test.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "bytes" "net/http" "strings" "testing" @@ -26,15 +25,16 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestReplaceObject(t *testing.T) { _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) deleted := false tf.UnstructuredClient = &fake.RESTClient{ @@ -62,11 +62,10 @@ func TestReplaceObject(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdReplace(tf, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") + cmd := NewCmdReplace(tf, streams) + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -89,9 +88,9 @@ func TestReplaceObject(t *testing.T) { func TestReplaceMultipleObject(t *testing.T) { _, svc, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) redisMasterDeleted := false frontendDeleted := false @@ -133,12 +132,11 @@ func TestReplaceMultipleObject(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdReplace(tf, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") + cmd := NewCmdReplace(tf, streams) + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -160,9 +158,9 @@ func TestReplaceMultipleObject(t *testing.T) { func TestReplaceDirectory(t *testing.T) { _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) created := map[string]bool{} tf.UnstructuredClient = &fake.RESTClient{ @@ -191,11 +189,10 @@ func TestReplaceDirectory(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdReplace(tf, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy") + cmd := NewCmdReplace(tf, streams) + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy") cmd.Flags().Set("namespace", "test") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -218,9 +215,9 @@ func TestReplaceDirectory(t *testing.T) { func TestForceReplaceObjectNotFound(t *testing.T) { _, _, rc := testData() - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -238,11 +235,10 @@ func TestForceReplaceObjectNotFound(t *testing.T) { } }), } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdReplace(tf, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") + cmd := NewCmdReplace(tf, streams) + cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("force", "true") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/resource/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/resource/BUILD deleted file mode 100644 index 0f65660c2..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/resource/BUILD +++ /dev/null @@ -1,83 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["get.go"], - importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/resource", - visibility = ["//visibility:public"], - deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/kubectl:go_default_library", - "//pkg/kubectl/cmd/templates:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/kubectl/cmd/util/openapi:go_default_library", - "//pkg/kubectl/resource:go_default_library", - "//pkg/kubectl/util/i18n:go_default_library", - "//pkg/printers:go_default_library", - "//pkg/util/interrupt:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/spf13/cobra:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1: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/util/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["get_test.go"], - data = [ - "//api/openapi-spec:swagger-spec", - "//examples:config", - "//test/e2e/testing-manifests:all-srcs", - "//test/fixtures", - ], - embed = [":go_default_library"], - deps = [ - "//pkg/api/legacyscheme:go_default_library", - "//pkg/api/testapi:go_default_library", - "//pkg/api/testing:go_default_library", - "//pkg/apis/core:go_default_library", - "//pkg/apis/core/v1:go_default_library", - "//pkg/kubectl/cmd/testing:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/kubectl/cmd/util/openapi:go_default_library", - "//pkg/kubectl/cmd/util/openapi/testing:go_default_library", - "//pkg/kubectl/scheme:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/json:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/dynamic:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/rest/fake:go_default_library", - "//vendor/k8s.io/client-go/rest/watch:go_default_library", - "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/resource/get.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/resource/get.go deleted file mode 100644 index 9785ddb2b..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/resource/get.go +++ /dev/null @@ -1,796 +0,0 @@ -/* -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 resource - -import ( - "encoding/json" - "fmt" - "io" - "strings" - - "github.com/golang/glog" - "github.com/spf13/cobra" - - "net/url" - - kapierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/rest" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/kubectl/util/i18n" - "k8s.io/kubernetes/pkg/printers" - "k8s.io/kubernetes/pkg/util/interrupt" -) - -// GetOptions contains the input to the get command. -type GetOptions struct { - Out, ErrOut io.Writer - - resource.FilenameOptions - - Raw string - Watch bool - WatchOnly bool - ChunkSize int64 - - LabelSelector string - FieldSelector string - AllNamespaces bool - Namespace string - ExplicitNamespace bool - - ServerPrint bool - - Sort bool - IgnoreNotFound bool - ShowKind bool - LabelColumns []string - Export bool - - IncludeUninitialized bool -} - -var ( - getLong = templates.LongDesc(` - Display one or many resources - - Prints a table of the most important information about the specified resources. - You can filter the list using a label selector and the --selector flag. If the - desired resource type is namespaced you will only see results in your current - namespace unless you pass --all-namespaces. - - Uninitialized objects are not shown unless --include-uninitialized is passed. - - By specifying the output as 'template' and providing a Go template as the value - of the --template flag, you can filter the attributes of the fetched resources.`) - - getExample = templates.Examples(i18n.T(` - # List all pods in ps output format. - kubectl get pods - - # List all pods in ps output format with more information (such as node name). - kubectl get pods -o wide - - # List a single replication controller with specified NAME in ps output format. - kubectl get replicationcontroller web - - # List a single pod in JSON output format. - kubectl get -o json pod web-pod-13je7 - - # List a pod identified by type and name specified in "pod.yaml" in JSON output format. - kubectl get -f pod.yaml -o json - - # Return only the phase value of the specified pod. - kubectl get -o template pod/web-pod-13je7 --template={{.status.phase}} - - # List all replication controllers and services together in ps output format. - kubectl get rc,services - - # List one or more resources by their type and names. - kubectl get rc/web service/frontend pods/web-pod-13je7 - - # List all resources with different types. - kubectl get all`)) -) - -const ( - useOpenAPIPrintColumnFlagLabel = "use-openapi-print-columns" - useServerPrintColumns = "experimental-server-print" -) - -// NewCmdGet creates a command object for the generic "get" action, which -// retrieves one or more resources from a server. -func NewCmdGet(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { - options := &GetOptions{ - Out: out, - ErrOut: errOut, - } - validArgs := cmdutil.ValidArgList(f) - - cmd := &cobra.Command{ - Use: "get [(-o|--output=)json|yaml|wide|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE [NAME | -l label] | TYPE/NAME ...) [flags]", - DisableFlagsInUseLine: true, - Short: i18n.T("Display one or many resources"), - Long: getLong + "\n\n" + cmdutil.ValidResourceTypeList(f), - Example: getExample, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Validate(cmd)) - cmdutil.CheckErr(options.Run(f, cmd, args)) - }, - SuggestFor: []string{"list", "ps"}, - ValidArgs: validArgs, - ArgAliases: kubectl.ResourceAliases(validArgs), - } - - cmd.Flags().StringVar(&options.Raw, "raw", options.Raw, "Raw URI to request from the server. Uses the transport specified by the kubeconfig file.") - cmd.Flags().BoolVarP(&options.Watch, "watch", "w", options.Watch, "After listing/getting the requested object, watch for changes. Uninitialized objects are excluded if no object name is provided.") - cmd.Flags().BoolVar(&options.WatchOnly, "watch-only", options.WatchOnly, "Watch for changes to the requested object(s), without listing/getting first.") - cmd.Flags().Int64Var(&options.ChunkSize, "chunk-size", 500, "Return large lists in chunks rather than all at once. Pass 0 to disable. This flag is beta and may change in the future.") - cmd.Flags().BoolVar(&options.IgnoreNotFound, "ignore-not-found", options.IgnoreNotFound, "If the requested object does not exist the command will return exit code 0.") - cmd.Flags().StringVarP(&options.LabelSelector, "selector", "l", options.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().StringVar(&options.FieldSelector, "field-selector", options.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") - cmd.Flags().BoolVar(&options.AllNamespaces, "all-namespaces", options.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") - cmdutil.AddIncludeUninitializedFlag(cmd) - cmdutil.AddPrinterFlags(cmd) - addOpenAPIPrintColumnFlags(cmd) - addServerPrintColumnFlags(cmd) - cmd.Flags().BoolVar(&options.ShowKind, "show-kind", options.ShowKind, "If present, list the resource type for the requested object(s).") - cmd.Flags().StringSliceVarP(&options.LabelColumns, "label-columns", "L", options.LabelColumns, "Accepts a comma separated list of labels that are going to be presented as columns. Names are case-sensitive. You can also use multiple flag options like -L label1 -L label2...") - cmd.Flags().BoolVar(&options.Export, "export", options.Export, "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information.") - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to get from a server.") - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -// Complete takes the command arguments and factory and infers any remaining options. -func (options *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - if len(options.Raw) > 0 { - if len(args) > 0 { - return fmt.Errorf("arguments may not be passed when --raw is specified") - } - return nil - } - - options.ServerPrint = cmdutil.GetFlagBool(cmd, useServerPrintColumns) - - var err error - options.Namespace, options.ExplicitNamespace, err = f.DefaultNamespace() - if err != nil { - return err - } - if options.AllNamespaces { - options.ExplicitNamespace = false - } - - isSorting, err := cmd.Flags().GetString("sort-by") - if err != nil { - return err - } - options.Sort = len(isSorting) > 0 - - options.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, false) - - switch { - case options.Watch || options.WatchOnly: - // include uninitialized objects when watching on a single object - // unless explicitly set --include-uninitialized=false - options.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, len(args) == 2) - default: - if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { - fmt.Fprint(options.ErrOut, "You must specify the type of resource to get. ", cmdutil.ValidResourceTypeList(f)) - fullCmdName := cmd.Parent().CommandPath() - usageString := "Required resource not specified." - if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") { - usageString = fmt.Sprintf("%s\nUse \"%s explain \" for a detailed description of that resource (e.g. %[2]s explain pods).", usageString, fullCmdName) - } - - return cmdutil.UsageErrorf(cmd, usageString) - } - } - return nil -} - -// Validate checks the set of flags provided by the user. -func (options *GetOptions) Validate(cmd *cobra.Command) error { - if len(options.Raw) > 0 { - if options.Watch || options.WatchOnly || len(options.LabelSelector) > 0 || options.Export { - return fmt.Errorf("--raw may not be specified with other flags that filter the server request or alter the output") - } - if len(cmdutil.GetFlagString(cmd, "output")) > 0 { - return cmdutil.UsageErrorf(cmd, "--raw and --output are mutually exclusive") - } - if _, err := url.ParseRequestURI(options.Raw); err != nil { - return cmdutil.UsageErrorf(cmd, "--raw must be a valid URL path: %v", err) - } - } - if cmdutil.GetFlagBool(cmd, "show-labels") { - outputOption := cmd.Flags().Lookup("output").Value.String() - if outputOption != "" && outputOption != "wide" { - return fmt.Errorf("--show-labels option cannot be used with %s printer", outputOption) - } - } - return nil -} - -// Run performs the get operation. -// TODO: remove the need to pass these arguments, like other commands. -func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - if len(options.Raw) > 0 { - return options.raw(f) - } - if options.Watch || options.WatchOnly { - return options.watch(f, cmd, args) - } - - printOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces) - printer, err := cmdutil.PrinterForOptions(printOpts) - if err != nil { - return err - } - - r := f.NewBuilder(). - Unstructured(). - NamespaceParam(options.Namespace).DefaultNamespace().AllNamespaces(options.AllNamespaces). - FilenameParam(options.ExplicitNamespace, &options.FilenameOptions). - LabelSelectorParam(options.LabelSelector). - FieldSelectorParam(options.FieldSelector). - ExportParam(options.Export). - RequestChunksOf(options.ChunkSize). - IncludeUninitialized(options.IncludeUninitialized). - ResourceTypeOrNameArgs(true, args...). - ContinueOnError(). - Latest(). - Flatten(). - TransformRequests(func(req *rest.Request) { - if options.ServerPrint && !printer.IsGeneric() && !options.Sort { - group := metav1beta1.GroupName - version := metav1beta1.SchemeGroupVersion.Version - - tableParam := fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", version, group) - req.SetHeader("Accept", tableParam) - } - }). - Do() - - if options.IgnoreNotFound { - r.IgnoreErrors(kapierrors.IsNotFound) - } - if err := r.Err(); err != nil { - return err - } - - filterOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces) - filterFuncs := f.DefaultResourceFilterFunc() - if r.TargetsSingleItems() { - filterFuncs = nil - } - - if printer.IsGeneric() { - return options.printGeneric(printer, r, filterFuncs, filterOpts) - } - - allErrs := []error{} - errs := sets.NewString() - infos, err := r.Infos() - if err != nil { - allErrs = append(allErrs, err) - } - - objs := make([]runtime.Object, len(infos)) - for ix := range infos { - if options.ServerPrint { - table, err := options.decodeIntoTable(cmdutil.InternalVersionJSONEncoder(), infos[ix].Object) - if err == nil { - infos[ix].Object = table - } else { - // if we are unable to decode server response into a v1beta1.Table, - // fallback to client-side printing with whatever info the server returned. - glog.V(2).Infof("Unable to decode server response into a Table. Falling back to hardcoded types: %v", err) - } - } - - objs[ix] = infos[ix].Object - } - - sorting, err := cmd.Flags().GetString("sort-by") - if err != nil { - return err - } - var sorter *kubectl.RuntimeSort - if options.Sort && len(objs) > 1 { - // TODO: questionable - if sorter, err = kubectl.SortObjects(cmdutil.InternalVersionDecoder(), objs, sorting); err != nil { - return err - } - } - - // use the default printer for each object - printer = nil - var lastMapping *meta.RESTMapping - w := printers.GetNewTabWriter(options.Out) - - useOpenAPIPrintColumns := cmdutil.GetFlagBool(cmd, useOpenAPIPrintColumnFlagLabel) - - showKind := options.ShowKind || resource.MultipleTypesRequested(args) || cmdutil.MustPrintWithKinds(objs, infos, sorter) - - filteredResourceCount := 0 - noHeaders := cmdutil.GetFlagBool(cmd, "no-headers") - for ix := range objs { - var mapping *meta.RESTMapping - var original runtime.Object - var info *resource.Info - if sorter != nil { - info = infos[sorter.OriginalPosition(ix)] - mapping = info.Mapping - original = info.Object - } else { - info = infos[ix] - mapping = info.Mapping - original = info.Object - } - - // if dealing with a table that has no rows, skip remaining steps - // and avoid printing an unnecessary newline - if table, isTable := info.Object.(*metav1beta1.Table); isTable { - if len(table.Rows) == 0 { - continue - } - } - - if shouldGetNewPrinterForMapping(printer, lastMapping, mapping) { - if printer != nil { - w.Flush() - } - - printWithNamespace := options.AllNamespaces - if mapping != nil && mapping.Scope.Name() == meta.RESTScopeNameRoot { - printWithNamespace = false - } - - printOpts := cmdutil.ExtractCmdPrintOptions(cmd, printWithNamespace) - // if cmd does not specify output format and useOpenAPIPrintColumnFlagLabel flag is true, - // then get the default output options for this mapping from OpenAPI schema. - if !cmdSpecifiesOutputFmt(cmd) && useOpenAPIPrintColumns { - updatePrintOptionsForOpenAPI(f, mapping, printOpts) - } - - if showKind && mapping != nil { - printOpts.WithKind = true - printOpts.Kind = mapping.GroupVersionKind.GroupKind() - } - - printer, err = cmdutil.PrinterForOptions(printOpts) - if err != nil { - if !errs.Has(err.Error()) { - errs.Insert(err.Error()) - allErrs = append(allErrs, err) - } - continue - } - - // TODO: this doesn't belong here - // add linebreak between resource groups (if there is more than one) - // skip linebreak above first resource group - if lastMapping != nil && !noHeaders { - fmt.Fprintf(options.ErrOut, "%s\n", "") - } - - lastMapping = mapping - } - - typedObj := info.AsInternal() - - // filter objects if filter has been defined for current object - if isFiltered, err := filterFuncs.Filter(typedObj, filterOpts); isFiltered { - if err == nil { - filteredResourceCount++ - continue - } - if !errs.Has(err.Error()) { - errs.Insert(err.Error()) - allErrs = append(allErrs, err) - } - } - - objToPrint := typedObj - if printer.IsGeneric() { - // use raw object as received from the builder when using generic - // printer instead of decodedObj - objToPrint = original - } - if err := printer.PrintObj(objToPrint, w); err != nil { - if !errs.Has(err.Error()) { - errs.Insert(err.Error()) - allErrs = append(allErrs, err) - } - continue - } - } - w.Flush() - nonEmptyObjCount := 0 - for _, obj := range objs { - if table, ok := obj.(*metav1beta1.Table); ok { - // exclude any Table objects with empty rows from our total object count - if len(table.Rows) == 0 { - continue - } - } - - nonEmptyObjCount++ - } - - cmdutil.PrintFilterCount(options.ErrOut, nonEmptyObjCount, filteredResourceCount, len(allErrs), filterOpts, options.IgnoreNotFound) - return utilerrors.NewAggregate(allErrs) -} - -// raw makes a simple HTTP request to the provided path on the server using the default -// credentials. -func (options *GetOptions) raw(f cmdutil.Factory) error { - restClient, err := f.RESTClient() - if err != nil { - return err - } - - stream, err := restClient.Get().RequestURI(options.Raw).Stream() - if err != nil { - return err - } - defer stream.Close() - - _, err = io.Copy(options.Out, stream) - if err != nil && err != io.EOF { - return err - } - return nil -} - -// watch starts a client-side watch of one or more resources. -// TODO: remove the need for arguments here. -func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - r := f.NewBuilder(). - Unstructured(). - NamespaceParam(options.Namespace).DefaultNamespace().AllNamespaces(options.AllNamespaces). - FilenameParam(options.ExplicitNamespace, &options.FilenameOptions). - LabelSelectorParam(options.LabelSelector). - FieldSelectorParam(options.FieldSelector). - ExportParam(options.Export). - RequestChunksOf(options.ChunkSize). - IncludeUninitialized(options.IncludeUninitialized). - ResourceTypeOrNameArgs(true, args...). - SingleResourceType(). - Latest(). - Do() - if err := r.Err(); err != nil { - return err - } - infos, err := r.Infos() - if err != nil { - return err - } - if len(infos) > 1 { - gvk := infos[0].Mapping.GroupVersionKind - uniqueGVKs := 1 - - // If requesting a resource count greater than a request's --chunk-size, - // we will end up making multiple requests to the server, with each - // request producing its own "Info" object. Although overall we are - // dealing with a single resource type, we will end up with multiple - // infos returned by the builder. To handle this case, only fail if we - // have at least one info with a different GVK than the others. - for _, info := range infos { - if info.Mapping.GroupVersionKind != gvk { - uniqueGVKs++ - } - } - - if uniqueGVKs > 1 { - return i18n.Errorf("watch is only supported on individual resources and resource collections - %d resources were found", uniqueGVKs) - } - } - - filterOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces) - filterFuncs := f.DefaultResourceFilterFunc() - if r.TargetsSingleItems() { - filterFuncs = nil - } - - info := infos[0] - mapping := info.ResourceMapping() - printOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces) - printer, err := cmdutil.PrinterForOptions(printOpts) - if err != nil { - return err - } - obj, err := r.Object() - if err != nil { - return err - } - - // watching from resourceVersion 0, starts the watch at ~now and - // will return an initial watch event. Starting form ~now, rather - // the rv of the object will insure that we start the watch from - // inside the watch window, which the rv of the object might not be. - rv := "0" - isList := meta.IsListType(obj) - if isList { - // the resourceVersion of list objects is ~now but won't return - // an initial watch event - rv, err = mapping.MetadataAccessor.ResourceVersion(obj) - if err != nil { - return err - } - } - - // print the current object - if !options.WatchOnly { - var objsToPrint []runtime.Object - writer := printers.GetNewTabWriter(options.Out) - - if isList { - objsToPrint, _ = meta.ExtractList(obj) - } else { - objsToPrint = append(objsToPrint, obj) - } - for _, objToPrint := range objsToPrint { - if isFiltered, err := filterFuncs.Filter(objToPrint, filterOpts); !isFiltered { - if err != nil { - glog.V(2).Infof("Unable to filter resource: %v", err) - continue - } - - // printing always takes the internal version, but the watch event uses externals - // TODO fix printing to use server-side or be version agnostic - internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion() - if err := printer.PrintObj(attemptToConvertToInternal(objToPrint, mapping, internalGV), writer); err != nil { - return fmt.Errorf("unable to output the provided object: %v", err) - } - } - } - writer.Flush() - } - - // print watched changes - w, err := r.Watch(rv) - if err != nil { - return err - } - - first := true - intr := interrupt.New(nil, w.Stop) - intr.Run(func() error { - _, err := watch.Until(0, w, func(e watch.Event) (bool, error) { - if !isList && first { - // drop the initial watch event in the single resource case - first = false - return false, nil - } - - if isFiltered, err := filterFuncs.Filter(e.Object, filterOpts); !isFiltered { - if err != nil { - glog.V(2).Infof("Unable to filter resource: %v", err) - return false, nil - } - - // printing always takes the internal version, but the watch event uses externals - // TODO fix printing to use server-side or be version agnostic - internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion() - if err := printer.PrintObj(attemptToConvertToInternal(e.Object, mapping, internalGV), options.Out); err != nil { - return false, err - } - } - return false, nil - }) - return err - }) - return nil -} - -// attemptToConvertToInternal tries to convert to an internal type, but returns the original if it can't -func attemptToConvertToInternal(obj runtime.Object, converter runtime.ObjectConvertor, targetVersion schema.GroupVersion) runtime.Object { - internalObject, err := converter.ConvertToVersion(obj, targetVersion) - if err != nil { - glog.V(1).Infof("Unable to convert %T to %v: err", obj, targetVersion, err) - return obj - } - return internalObject -} - -func (options *GetOptions) decodeIntoTable(encoder runtime.Encoder, obj runtime.Object) (runtime.Object, error) { - if obj.GetObjectKind().GroupVersionKind().Kind != "Table" { - return nil, fmt.Errorf("attempt to decode non-Table object into a v1beta1.Table") - } - - b, err := runtime.Encode(encoder, obj) - if err != nil { - return nil, err - } - - table := &metav1beta1.Table{} - err = json.Unmarshal(b, table) - if err != nil { - return nil, err - } - - return table, nil -} - -func (options *GetOptions) printGeneric(printer printers.ResourcePrinter, r *resource.Result, filterFuncs kubectl.Filters, filterOpts *printers.PrintOptions) error { - // we flattened the data from the builder, so we have individual items, but now we'd like to either: - // 1. if there is more than one item, combine them all into a single list - // 2. if there is a single item and that item is a list, leave it as its specific list - // 3. if there is a single item and it is not a list, leave it as a single item - var errs []error - singleItemImplied := false - infos, err := r.IntoSingleItemImplied(&singleItemImplied).Infos() - if err != nil { - if singleItemImplied { - return err - } - errs = append(errs, err) - } - - if len(infos) == 0 && options.IgnoreNotFound { - return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) - } - - var obj runtime.Object - if !singleItemImplied || len(infos) > 1 { - // we have more than one item, so coerce all items into a list. - // we don't want an *unstructured.Unstructured list yet, as we - // may be dealing with non-unstructured objects. Compose all items - // into an api.List, and then decode using an unstructured scheme. - list := api.List{ - TypeMeta: metav1.TypeMeta{ - Kind: "List", - APIVersion: "v1", - }, - ListMeta: metav1.ListMeta{}, - } - for _, info := range infos { - list.Items = append(list.Items, info.Object) - } - - listData, err := json.Marshal(list) - if err != nil { - return err - } - - converted, err := runtime.Decode(unstructured.UnstructuredJSONScheme, listData) - if err != nil { - return err - } - - obj = converted - } else { - obj = infos[0].Object - } - - isList := meta.IsListType(obj) - if isList { - _, items, err := cmdutil.FilterResourceList(obj, filterFuncs, filterOpts) - if err != nil { - return err - } - - // take the filtered items and create a new list for display - list := &unstructured.UnstructuredList{ - Object: map[string]interface{}{ - "kind": "List", - "apiVersion": "v1", - "metadata": map[string]interface{}{}, - }, - } - if listMeta, err := meta.ListAccessor(obj); err == nil { - list.Object["metadata"] = map[string]interface{}{ - "selfLink": listMeta.GetSelfLink(), - "resourceVersion": listMeta.GetResourceVersion(), - } - } - - for _, item := range items { - list.Items = append(list.Items, *item.(*unstructured.Unstructured)) - } - if err := printer.PrintObj(list, options.Out); err != nil { - errs = append(errs, err) - } - return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) - } - - if isFiltered, err := filterFuncs.Filter(obj, filterOpts); !isFiltered { - if err != nil { - glog.V(2).Infof("Unable to filter resource: %v", err) - } else if err := printer.PrintObj(obj, options.Out); err != nil { - errs = append(errs, err) - } - } - - return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) -} - -func addOpenAPIPrintColumnFlags(cmd *cobra.Command) { - cmd.Flags().Bool(useOpenAPIPrintColumnFlagLabel, true, "If true, use x-kubernetes-print-column metadata (if present) from the OpenAPI schema for displaying a resource.") -} - -func addServerPrintColumnFlags(cmd *cobra.Command) { - cmd.Flags().Bool(useServerPrintColumns, false, "If true, have the server return the appropriate table output. Supports extension APIs and CRD. Experimental.") -} - -func shouldGetNewPrinterForMapping(printer printers.ResourcePrinter, lastMapping, mapping *meta.RESTMapping) bool { - return printer == nil || lastMapping == nil || mapping == nil || mapping.Resource != lastMapping.Resource -} - -func cmdSpecifiesOutputFmt(cmd *cobra.Command) bool { - return cmdutil.GetFlagString(cmd, "output") != "" -} - -// outputOptsForMappingFromOpenAPI looks for the output format metatadata in the -// openapi schema and modifies the passed print options for the mapping if found. -func updatePrintOptionsForOpenAPI(f cmdutil.Factory, mapping *meta.RESTMapping, printOpts *printers.PrintOptions) bool { - - // user has not specified any output format, check if OpenAPI has - // default specification to print this resource type - api, err := f.OpenAPISchema() - if err != nil { - // Error getting schema - return false - } - // Found openapi metadata for this resource - schema := api.LookupResource(mapping.GroupVersionKind) - if schema == nil { - // Schema not found, return empty columns - return false - } - - columns, found := openapi.GetPrintColumns(schema.GetExtensions()) - if !found { - // Extension not found, return empty columns - return false - } - - return outputOptsFromStr(columns, printOpts) -} - -// outputOptsFromStr parses the print-column metadata and generates printer.OutputOptions object. -func outputOptsFromStr(columnStr string, printOpts *printers.PrintOptions) bool { - if columnStr == "" { - return false - } - parts := strings.SplitN(columnStr, "=", 2) - if len(parts) < 2 { - return false - } - - printOpts.OutputFormatType = parts[0] - printOpts.OutputFormatArgument = parts[1] - printOpts.AllowMissingKeys = true - - return true -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/resource/get_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/resource/get_test.go deleted file mode 100644 index 5192fb5ce..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/resource/get_test.go +++ /dev/null @@ -1,1402 +0,0 @@ -/* -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 resource - -import ( - "bytes" - encjson "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "path/filepath" - "reflect" - "strings" - "testing" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer/json" - "k8s.io/apimachinery/pkg/runtime/serializer/streaming" - "k8s.io/apimachinery/pkg/util/diff" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" - restclientwatch "k8s.io/client-go/rest/watch" - "k8s.io/kube-openapi/pkg/util/proto" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/v1" - - "k8s.io/kubernetes/pkg/api/legacyscheme" - cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - openapitesting "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" - "k8s.io/kubernetes/pkg/kubectl/scheme" -) - -var openapiSchemaPath = filepath.Join("..", "..", "..", "..", "api", "openapi-spec", "swagger.json") - -// This init should be removed after switching this command and its tests to user external types. -func init() { - api.AddToScheme(scheme.Scheme) - scheme.Scheme.AddConversionFuncs(v1.Convert_core_PodSpec_To_v1_PodSpec) - scheme.Scheme.AddConversionFuncs(v1.Convert_v1_PodSecurityContext_To_core_PodSecurityContext) -} - -var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer - -func defaultHeader() http.Header { - header := http.Header{} - header.Set("Content-Type", runtime.ContentTypeJSON) - return header -} - -func defaultClientConfig() *restclient.Config { - return &restclient.Config{ - APIPath: "/api", - ContentConfig: restclient.ContentConfig{ - NegotiatedSerializer: scheme.Codecs, - ContentType: runtime.ContentTypeJSON, - GroupVersion: &scheme.Registry.GroupOrDie(api.GroupName).GroupVersion, - }, - } -} - -type testPrinter struct { - Objects []runtime.Object - Err error - GenericPrinter bool -} - -func (t *testPrinter) PrintObj(obj runtime.Object, out io.Writer) error { - t.Objects = append(t.Objects, obj) - fmt.Fprintf(out, "%#v", obj) - return t.Err -} - -// TODO: implement HandledResources() -func (t *testPrinter) HandledResources() []string { - return []string{} -} - -func (t *testPrinter) AfterPrint(output io.Writer, res string) error { - return nil -} - -func (t *testPrinter) IsGeneric() bool { - return t.GenericPrinter -} - -func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj)))) -} - -func stringBody(body string) io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader([]byte(body))) -} - -func initTestErrorHandler(t *testing.T) { - cmdutil.BehaviorOnFatal(func(str string, code int) { - t.Errorf("Error running command (exit code %d): %s", code, str) - }) -} - -func testData() (*api.PodList, *api.ServiceList, *api.ReplicationControllerList) { - pods := &api.PodList{ - ListMeta: metav1.ListMeta{ - ResourceVersion: "15", - }, - Items: []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - svc := &api.ServiceList{ - ListMeta: metav1.ListMeta{ - ResourceVersion: "16", - }, - Items: []api.Service{ - { - ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.ServiceSpec{ - SessionAffinity: "None", - Type: api.ServiceTypeClusterIP, - }, - }, - }, - } - rc := &api.ReplicationControllerList{ - ListMeta: metav1.ListMeta{ - ResourceVersion: "17", - }, - Items: []api.ReplicationController{ - { - ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: "test", ResourceVersion: "18"}, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - }, - }, - }, - } - return pods, svc, rc -} - -func testComponentStatusData() *api.ComponentStatusList { - good := api.ComponentStatus{ - Conditions: []api.ComponentCondition{ - {Type: api.ComponentHealthy, Status: api.ConditionTrue, Message: "ok"}, - }, - ObjectMeta: metav1.ObjectMeta{Name: "servergood"}, - } - - bad := api.ComponentStatus{ - Conditions: []api.ComponentCondition{ - {Type: api.ComponentHealthy, Status: api.ConditionFalse, Message: "", Error: "bad status: 500"}, - }, - ObjectMeta: metav1.ObjectMeta{Name: "serverbad"}, - } - - unknown := api.ComponentStatus{ - Conditions: []api.ComponentCondition{ - {Type: api.ComponentHealthy, Status: api.ConditionUnknown, Message: "", Error: "fizzbuzz error"}, - }, - ObjectMeta: metav1.ObjectMeta{Name: "serverunknown"}, - } - - return &api.ComponentStatusList{ - Items: []api.ComponentStatus{good, bad, unknown}, - } -} - -// Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. -func TestGetUnknownSchemaObject(t *testing.T) { - t.Skip("This test is completely broken. The first thing it does is add the object to the scheme!") - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - _, _, codec := cmdtesting.NewExternalScheme() - tf.OpenAPISchemaFunc = openapitesting.CreateOpenAPISchemaFunc(openapiSchemaPath) - - obj := &cmdtesting.ExternalType{ - Kind: "Type", - APIVersion: "apitest/unlikelyversion", - Name: "foo", - } - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{ - StatusCode: 200, Header: defaultHeader(), - Body: objBody(codec, obj), - }, - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() - - mapper, _ := tf.Object() - m, err := mapper.RESTMapping(schema.GroupKind{Group: "apitest", Kind: "Type"}) - if err != nil { - t.Fatal(err) - } - convertedObj, err := m.ConvertToVersion(&unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": "Type", - "apiVersion": "apitest/unlikelyversion", - "name": "foo", - }, - }, schema.GroupVersion{Group: "apitest", Version: "unlikelyversion"}) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(convertedObj, obj) { - t.Fatalf("unexpected conversion of unstructured object to structured: %s", diff.ObjectReflectDiff(convertedObj, obj)) - } - - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"type", "foo"}) - - expected := []runtime.Object{cmdtesting.NewInternalType("", "", "foo")} - actual := []runtime.Object{} - //actual := tf.Printer.(*testPrinter).Objects - if len(actual) != len(expected) { - t.Fatalf("expected: %#v, but actual: %#v", expected, actual) - } - t.Logf("actual: %#v", actual[0]) - for i, obj := range actual { - expectedJSON := runtime.EncodeOrDie(codec, expected[i]) - expectedMap := map[string]interface{}{} - if err := encjson.Unmarshal([]byte(expectedJSON), &expectedMap); err != nil { - t.Fatal(err) - } - - actualJSON := runtime.EncodeOrDie(codec, obj) - actualMap := map[string]interface{}{} - if err := encjson.Unmarshal([]byte(actualJSON), &actualMap); err != nil { - t.Fatal(err) - } - - if !reflect.DeepEqual(expectedMap, actualMap) { - t.Errorf("expectedMap: %#v, but actualMap: %#v", expectedMap, actualMap) - } - } -} - -// Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. -func TestGetSchemaObject(t *testing.T) { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := testapi.Default.Codec() - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &api.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})}, - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.Run(cmd, []string{"replicationcontrollers", "foo"}) - - if !strings.Contains(buf.String(), "foo") { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) { - pods, _, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - // overide the openAPISchema function to return custom output - // for Pod type. - tf.OpenAPISchemaFunc = testOpenAPISchemaData - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Flags().Set(useOpenAPIPrintColumnFlagLabel, "true") - cmd.Run(cmd, []string{"pods", "foo"}) - - expected := `NAME RSRC -foo 10 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -type FakeResources struct { - resources map[schema.GroupVersionKind]proto.Schema -} - -func (f FakeResources) LookupResource(s schema.GroupVersionKind) proto.Schema { - return f.resources[s] -} - -var _ openapi.Resources = &FakeResources{} - -func testOpenAPISchemaData() (openapi.Resources, error) { - return &FakeResources{ - resources: map[schema.GroupVersionKind]proto.Schema{ - { - Version: "v1", - Kind: "Pod", - }: &proto.Primitive{ - BaseSchema: proto.BaseSchema{ - Extensions: map[string]interface{}{ - "x-kubernetes-print-columns": "custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion", - }, - }, - }, - }, - }, nil -} - -func TestGetObjects(t *testing.T) { - pods, _, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"pods", "foo"}) - - expected := `NAME READY STATUS RESTARTS AGE -foo 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetObjectsFiltered(t *testing.T) { - initTestErrorHandler(t) - - pods, _, _ := testData() - pods.Items[0].Status.Phase = api.PodFailed - first := &pods.Items[0] - - testCases := []struct { - args []string - resp runtime.Object - flags map[string]string - expect string - }{ - {args: []string{"pods", "foo"}, resp: first, flags: map[string]string{"show-all": "true"}, - expect: "NAME READY STATUS RESTARTS AGE\nfoo 0/0 Failed 0 \n"}, - - {args: []string{"pods", "foo"}, flags: map[string]string{"show-all": "false"}, resp: first, - expect: "NAME READY STATUS RESTARTS AGE\nfoo 0/0 Failed 0 \n"}, - - {args: []string{"pods"}, flags: map[string]string{"show-all": "true"}, resp: pods, - expect: "NAME READY STATUS RESTARTS AGE\nfoo 0/0 Failed 0 \nbar 0/0 0 \n"}, - - {args: []string{"pods/foo"}, resp: first, flags: map[string]string{"show-all": "false"}, - expect: "NAME READY STATUS RESTARTS AGE\nfoo 0/0 Failed 0 \n"}, - - {args: []string{"pods"}, flags: map[string]string{"show-all": "false", "output": "name"}, resp: pods, - expect: "pod/foo\npod/bar\n"}, - - {args: []string{}, flags: map[string]string{"show-all": "false", "filename": "../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}, resp: pods, - expect: "NAME READY STATUS RESTARTS AGE\nfoo 0/0 Failed 0 \nbar 0/0 0 \n"}, - - {args: []string{"pods"}, resp: pods, flags: map[string]string{"show-all": "false"}, - expect: "NAME READY STATUS RESTARTS AGE\nbar 0/0 0 \n"}, - - {args: []string{"pods"}, flags: map[string]string{"show-all": "true", "output": "name"}, resp: pods, - expect: "pod/foo\npod/bar\n"}, - - {args: []string{"pods"}, flags: map[string]string{"show-all": "false"}, resp: pods, - expect: "NAME READY STATUS RESTARTS AGE\nbar 0/0 0 \n"}, - } - - for i, test := range testCases { - t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, test.resp)}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - for k, v := range test.flags { - cmd.Flags().Lookup(k).Value.Set(v) - } - cmd.Run(cmd, test.args) - - if e, a := test.expect, buf.String(); e != a { - t.Errorf("expected %q, got %q", e, a) - } - }) - } -} - -func TestGetObjectIgnoreNotFound(t *testing.T) { - initTestErrorHandler(t) - - ns := &api.NamespaceList{ - ListMeta: metav1.ListMeta{ - ResourceVersion: "1", - }, - Items: []api.Namespace{ - { - ObjectMeta: metav1.ObjectMeta{Name: "testns", Namespace: "test", ResourceVersion: "11"}, - Spec: api.NamespaceSpec{}, - }, - }, - } - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/pods/nonexistentpod" && m == "GET": - return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: stringBody("")}, nil - case p == "/api/v1/namespaces/test" && m == "GET": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &ns.Items[0])}, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Flags().Set("ignore-not-found", "true") - cmd.Flags().Set("output", "yaml") - cmd.Run(cmd, []string{"pods", "nonexistentpod"}) - - if buf.String() != "" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestGetSortedObjects(t *testing.T) { - pods := &api.PodList{ - ListMeta: metav1.ListMeta{ - ResourceVersion: "15", - }, - Items: []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, - } - tf.Namespace = "test" - tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: "v1"}}} - - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - // sorting with metedata.name - cmd.Flags().Set("sort-by", ".metadata.name") - cmd.Run(cmd, []string{"pods"}) - - expected := `NAME READY STATUS RESTARTS AGE -a 0/0 0 -b 0/0 0 -c 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetObjectsIdentifiedByFile(t *testing.T) { - pods, _, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml") - cmd.Run(cmd, []string{}) - - expected := `NAME READY STATUS RESTARTS AGE -foo 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetListObjects(t *testing.T) { - pods, _, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"pods"}) - - expected := `NAME READY STATUS RESTARTS AGE -foo 0/0 0 -bar 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetAllListObjects(t *testing.T) { - pods, _, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Flags().Set("show-all", "true") - cmd.Run(cmd, []string{"pods"}) - - expected := `NAME READY STATUS RESTARTS AGE -foo 0/0 0 -bar 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetListComponentStatus(t *testing.T) { - statuses := testComponentStatusData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, statuses)}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"componentstatuses"}) - - expected := `NAME STATUS MESSAGE ERROR -servergood Healthy ok -serverbad Unhealthy bad status: 500 -serverunknown Unhealthy fizzbuzz error -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetMixedGenericObjects(t *testing.T) { - initTestErrorHandler(t) - - // ensure that a runtime.Object without - // an ObjectMeta field is handled properly - structuredObj := &metav1.Status{ - TypeMeta: metav1.TypeMeta{ - Kind: "Status", - APIVersion: "v1", - }, - Status: "Success", - Message: "", - Reason: "", - Code: 0, - } - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, structuredObj)}, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Flags().Set("output", "json") - cmd.Run(cmd, []string{"pods"}) - - expected := `{ - "apiVersion": "v1", - "items": [ - { - "apiVersion": "v1", - "kind": "Status", - "metadata": {}, - "status": "Success" - } - ], - "kind": "List", - "metadata": { - "resourceVersion": "", - "selfLink": "" - } -} -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetMultipleTypeObjects(t *testing.T) { - pods, svc, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil - case "/namespaces/test/services": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"pods,services"}) - - expected := `NAME READY STATUS RESTARTS AGE -pod/foo 0/0 0 -pod/bar 0/0 0 -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/baz ClusterIP -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetMultipleTypeObjectsAsList(t *testing.T) { - pods, svc, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil - case "/namespaces/test/services": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Flags().Set("output", "json") - cmd.Run(cmd, []string{"pods,services"}) - - expected := `{ - "apiVersion": "v1", - "items": [ - { - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "creationTimestamp": null, - "name": "foo", - "namespace": "test", - "resourceVersion": "10" - }, - "spec": { - "containers": null, - "dnsPolicy": "ClusterFirst", - "restartPolicy": "Always", - "schedulerName": "default-scheduler", - "securityContext": {}, - "terminationGracePeriodSeconds": 30 - }, - "status": {} - }, - { - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "creationTimestamp": null, - "name": "bar", - "namespace": "test", - "resourceVersion": "11" - }, - "spec": { - "containers": null, - "dnsPolicy": "ClusterFirst", - "restartPolicy": "Always", - "schedulerName": "default-scheduler", - "securityContext": {}, - "terminationGracePeriodSeconds": 30 - }, - "status": {} - }, - { - "apiVersion": "v1", - "kind": "Service", - "metadata": { - "creationTimestamp": null, - "name": "baz", - "namespace": "test", - "resourceVersion": "12" - }, - "spec": { - "sessionAffinity": "None", - "type": "ClusterIP" - }, - "status": { - "loadBalancer": {} - } - } - ], - "kind": "List", - "metadata": { - "resourceVersion": "", - "selfLink": "" - } -} -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) { - pods, svc, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" { - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - } - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil - case "/namespaces/test/services": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Flags().Set("selector", "a=b") - cmd.Run(cmd, []string{"pods,services"}) - - expected := `NAME READY STATUS RESTARTS AGE -pod/foo 0/0 0 -pod/bar 0/0 0 -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/baz ClusterIP -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) { - pods, svc, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" { - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - } - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil - case "/namespaces/test/services": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Flags().Set("field-selector", "a=b") - cmd.Run(cmd, []string{"pods,services"}) - - expected := `NAME READY STATUS RESTARTS AGE -pod/foo 0/0 0 -pod/bar 0/0 0 -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/baz ClusterIP -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { - _, svc, _ := testData() - node := &api.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - ExternalID: "ext", - }, - } - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/nodes/foo": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, node)}, nil - case "/namespaces/test/services/bar": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Run(cmd, []string{"services/bar", "node/foo"}) - - expected := `NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/baz ClusterIP -NAME STATUS ROLES AGE VERSION -node/foo Unknown -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetByFormatForcesFlag(t *testing.T) { - pods, _, _ := testData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - cmd.Flags().Lookup("output").Value.Set("yaml") - cmd.Flags().Set("show-all", "false") - cmd.Run(cmd, []string{"pods"}) - - showAllFlag, _ := cmd.Flags().GetBool("show-all") - if showAllFlag { - t.Error("expected showAll to not be true when getting resource") - } -} - -func watchTestData() ([]api.Pod, []watch.Event) { - pods := []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "bar", - Namespace: "test", - ResourceVersion: "9", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "test", - ResourceVersion: "10", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - } - events := []watch.Event{ - // current state events - { - Type: watch.Added, - Object: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "bar", - Namespace: "test", - ResourceVersion: "9", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - { - Type: watch.Added, - Object: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "test", - ResourceVersion: "10", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - // resource events - { - Type: watch.Modified, - Object: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "test", - ResourceVersion: "11", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - { - Type: watch.Deleted, - Object: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "test", - ResourceVersion: "12", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - return pods, events -} - -func TestWatchLabelSelector(t *testing.T) { - pods, events := watchTestData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - podList := &api.PodList{ - Items: pods, - ListMeta: metav1.ListMeta{ - ResourceVersion: "10", - }, - } - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" { - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - } - switch req.URL.Path { - case "/namespaces/test/pods": - if req.URL.Query().Get("watch") == "true" { - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil - } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch", "true") - cmd.Flags().Set("selector", "a=b") - cmd.Run(cmd, []string{"pods"}) - - expected := `NAME READY STATUS RESTARTS AGE -bar 0/0 0 -foo 0/0 0 -foo 0/0 0 -foo 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestWatchFieldSelector(t *testing.T) { - pods, events := watchTestData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - podList := &api.PodList{ - Items: pods, - ListMeta: metav1.ListMeta{ - ResourceVersion: "10", - }, - } - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" { - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - } - switch req.URL.Path { - case "/namespaces/test/pods": - if req.URL.Query().Get("watch") == "true" { - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil - } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch", "true") - cmd.Flags().Set("field-selector", "a=b") - cmd.Run(cmd, []string{"pods"}) - - expected := `NAME READY STATUS RESTARTS AGE -bar 0/0 0 -foo 0/0 0 -foo 0/0 0 -foo 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestWatchResource(t *testing.T) { - pods, events := watchTestData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil - case "/namespaces/test/pods": - if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" { - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil - } - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch", "true") - cmd.Run(cmd, []string{"pods", "foo"}) - - expected := `NAME READY STATUS RESTARTS AGE -foo 0/0 0 -foo 0/0 0 -foo 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestWatchResourceIdentifiedByFile(t *testing.T) { - pods, events := watchTestData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/replicationcontrollers/cassandra": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil - case "/namespaces/test/replicationcontrollers": - if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=cassandra" { - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil - } - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch", "true") - cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml") - cmd.Run(cmd, []string{}) - - expected := `NAME READY STATUS RESTARTS AGE -foo 0/0 0 -foo 0/0 0 -foo 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestWatchOnlyResource(t *testing.T) { - pods, events := watchTestData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil - case "/namespaces/test/pods": - if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" { - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil - } - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch-only", "true") - cmd.Run(cmd, []string{"pods", "foo"}) - - expected := `NAME READY STATUS RESTARTS AGE -foo 0/0 0 -foo 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestWatchOnlyList(t *testing.T) { - pods, events := watchTestData() - - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - - podList := &api.PodList{ - Items: pods, - ListMeta: metav1.ListMeta{ - ResourceVersion: "10", - }, - } - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods": - if req.URL.Query().Get("watch") == "true" { - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil - } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil - default: - t.Fatalf("request url: %#v,and request: %#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch-only", "true") - cmd.Run(cmd, []string{"pods"}) - - expected := `NAME READY STATUS RESTARTS AGE -foo 0/0 0 -foo 0/0 0 -` - if e, a := expected, buf.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func watchBody(codec runtime.Codec, events []watch.Event) io.ReadCloser { - buf := bytes.NewBuffer([]byte{}) - enc := restclientwatch.NewEncoder(streaming.NewEncoder(buf, codec), codec) - for i := range events { - enc.Encode(&events[i]) - } - return json.Framer.NewFrameReader(ioutil.NopCloser(buf)) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate.go index 029adb8aa..c304fdcaa 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate.go @@ -19,11 +19,9 @@ package cmd import ( "bytes" "fmt" - "io" "time" "github.com/golang/glog" - "github.com/spf13/cobra" "k8s.io/api/core/v1" @@ -31,14 +29,20 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/intstr" + scaleclient "k8s.io/client-go/scale" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util" "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "k8s.io/kubernetes/pkg/kubectl/validation" ) var ( @@ -75,34 +79,85 @@ var ( pollInterval, _ = time.ParseDuration("3s") ) -func NewCmdRollingUpdate(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &resource.FilenameOptions{} +type RollingUpdateOptions struct { + FilenameOptions *resource.FilenameOptions + + OldName string + KeepOldName bool + + DeploymentKey string + Image string + Container string + PullPolicy string + Rollback bool + Period time.Duration + Timeout time.Duration + Interval time.Duration + DryRun bool + OutputFormat string + Namespace string + EnforceNamespace bool + + ScaleClient scaleclient.ScalesGetter + ClientSet internalclientset.Interface + Builder *resource.Builder + + ShouldValidate bool + Validator func(bool) (validation.Schema, error) + + FindNewName func(*api.ReplicationController) string + + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) + + genericclioptions.IOStreams +} + +func NewRollingUpdateOptions(streams genericclioptions.IOStreams) *RollingUpdateOptions { + return &RollingUpdateOptions{ + PrintFlags: genericclioptions.NewPrintFlags("rolling updated").WithTypeSetter(scheme.Scheme), + FilenameOptions: &resource.FilenameOptions{}, + DeploymentKey: "deployment", + Timeout: timeout, + Interval: pollInterval, + Period: updatePeriod, + + IOStreams: streams, + } +} + +func NewCmdRollingUpdate(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewRollingUpdateOptions(ioStreams) cmd := &cobra.Command{ Use: "rolling-update OLD_CONTROLLER_NAME ([NEW_CONTROLLER_NAME] --image=NEW_CONTAINER_IMAGE | -f NEW_CONTROLLER_SPEC)", DisableFlagsInUseLine: true, - Short: i18n.T("Perform a rolling update of the given ReplicationController"), - Long: rollingUpdateLong, - Example: rollingUpdateExample, + Short: "Perform a rolling update. This command is deprecated, use rollout instead.", + Long: rollingUpdateLong, + Example: rollingUpdateExample, + Deprecated: `use "rollout" instead`, + Hidden: true, Run: func(cmd *cobra.Command, args []string) { - err := RunRollingUpdate(f, out, cmd, args, options) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate(cmd, args)) + cmdutil.CheckErr(o.Run()) }, } - cmd.Flags().Duration("update-period", updatePeriod, `Time to wait between updating pods. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) - cmd.Flags().Duration("poll-interval", pollInterval, `Time delay between polling for replication controller status after the update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) - cmd.Flags().Duration("timeout", timeout, `Max time to wait for a replication controller to update before giving up. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) + + o.PrintFlags.AddFlags(cmd) + + cmd.Flags().DurationVar(&o.Period, "update-period", o.Period, `Time to wait between updating pods. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) + cmd.Flags().DurationVar(&o.Interval, "poll-interval", o.Interval, `Time delay between polling for replication controller status after the update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) + cmd.Flags().DurationVar(&o.Timeout, "timeout", o.Timeout, `Max time to wait for a replication controller to update before giving up. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) usage := "Filename or URL to file to use to create the new replication controller." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmd.Flags().String("image", "", i18n.T("Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f")) - cmd.Flags().String("deployment-label-key", "deployment", i18n.T("The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise")) - cmd.Flags().String("container", "", i18n.T("Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod")) - cmd.Flags().String("image-pull-policy", "", i18n.T("Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.")) - cmd.Flags().Bool("rollback", false, "If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout") + cmdutil.AddJsonFilenameFlag(cmd.Flags(), &o.FilenameOptions.Filenames, usage) + cmd.Flags().StringVar(&o.Image, "image", o.Image, i18n.T("Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f")) + cmd.Flags().StringVar(&o.DeploymentKey, "deployment-label-key", o.DeploymentKey, i18n.T("The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise")) + cmd.Flags().StringVar(&o.Container, "container", o.Container, i18n.T("Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod")) + cmd.Flags().StringVar(&o.PullPolicy, "image-pull-policy", o.PullPolicy, i18n.T("Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.")) + cmd.Flags().BoolVar(&o.Rollback, "rollback", o.Rollback, "If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout") cmdutil.AddDryRunFlag(cmd) cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) return cmd } @@ -139,69 +194,89 @@ func validateArguments(cmd *cobra.Command, filenames, args []string) error { return utilerrors.NewAggregate(errors) } -func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { - err := validateArguments(cmd, options.Filenames, args) - if err != nil { - return err +func (o *RollingUpdateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + if len(args) > 0 { + o.OldName = args[0] + } + o.DryRun = cmdutil.GetDryRunFlag(cmd) + o.OutputFormat = cmdutil.GetFlagString(cmd, "output") + o.KeepOldName = len(args) == 1 + o.ShouldValidate = cmdutil.GetFlagBool(cmd, "validate") + + o.Validator = f.Validator + o.FindNewName = func(obj *api.ReplicationController) string { + return findNewName(args, obj) } - deploymentKey := cmdutil.GetFlagString(cmd, "deployment-label-key") - filename := "" - image := cmdutil.GetFlagString(cmd, "image") - pullPolicy := cmdutil.GetFlagString(cmd, "image-pull-policy") - oldName := args[0] - rollback := cmdutil.GetFlagBool(cmd, "rollback") - period := cmdutil.GetFlagDuration(cmd, "update-period") - interval := cmdutil.GetFlagDuration(cmd, "poll-interval") - timeout := cmdutil.GetFlagDuration(cmd, "timeout") - dryrun := cmdutil.GetDryRunFlag(cmd) - outputFormat := cmdutil.GetFlagString(cmd, "output") - container := cmdutil.GetFlagString(cmd, "container") - - if len(options.Filenames) > 0 { - filename = options.Filenames[0] + var err error + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err } - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + o.ScaleClient, err = cmdutil.ScaleClientFn(f) if err != nil { return err } - clientset, err := f.ClientSet() + o.ClientSet, err = f.ClientSet() if err != nil { return err } - coreClient := clientset.Core() + + o.Builder = f.NewBuilder() + + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + + return o.PrintFlags.ToPrinter() + } + return nil +} + +func (o *RollingUpdateOptions) Validate(cmd *cobra.Command, args []string) error { + return validateArguments(cmd, o.FilenameOptions.Filenames, args) +} + +func (o *RollingUpdateOptions) Run() error { + filename := "" + if len(o.FilenameOptions.Filenames) > 0 { + filename = o.FilenameOptions.Filenames[0] + } + + coreClient := o.ClientSet.Core() var newRc *api.ReplicationController // fetch rc - oldRc, err := coreClient.ReplicationControllers(cmdNamespace).Get(oldName, metav1.GetOptions{}) + oldRc, err := coreClient.ReplicationControllers(o.Namespace).Get(o.OldName, metav1.GetOptions{}) if err != nil { - if !errors.IsNotFound(err) || len(image) == 0 || len(args) > 1 { + if !errors.IsNotFound(err) || len(o.Image) == 0 || !o.KeepOldName { return err } // We're in the middle of a rename, look for an RC with a source annotation of oldName - newRc, err := kubectl.FindSourceController(coreClient, cmdNamespace, oldName) + newRc, err := kubectl.FindSourceController(coreClient, o.Namespace, o.OldName) if err != nil { return err } - return kubectl.Rename(coreClient, newRc, oldName) + return kubectl.Rename(coreClient, newRc, o.OldName) } - var keepOldName bool var replicasDefaulted bool if len(filename) != 0 { - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) + schema, err := o.Validator(o.ShouldValidate) if err != nil { return err } - request := f.NewBuilder(). + request := o.Builder. Unstructured(). Schema(schema). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &resource.FilenameOptions{Recursive: false, Filenames: []string{filename}}). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.EnforceNamespace, &resource.FilenameOptions{Recursive: false, Filenames: []string{filename}}). Flatten(). Do() infos, err := request.Infos() @@ -210,52 +285,61 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args } // Handle filename input from stdin. if len(infos) > 1 { - return cmdutil.UsageErrorf(cmd, "%s specifies multiple items", filename) + return fmt.Errorf("%s specifies multiple items", filename) } if len(infos) == 0 { - return cmdutil.UsageErrorf(cmd, "please make sure %s exists and is not empty", filename) + return fmt.Errorf("please make sure %s exists and is not empty", filename) } - switch t := infos[0].AsVersioned().(type) { + uncastVersionedObj, err := legacyscheme.Scheme.ConvertToVersion(infos[0].Object, v1.SchemeGroupVersion) + if err != nil { + glog.V(4).Infof("Object %T is not a ReplicationController", infos[0].Object) + return fmt.Errorf("%s contains a %v not a ReplicationController", filename, infos[0].Object.GetObjectKind().GroupVersionKind()) + } + switch t := uncastVersionedObj.(type) { case *v1.ReplicationController: replicasDefaulted = t.Spec.Replicas == nil - newRc, _ = infos[0].AsInternal().(*api.ReplicationController) + + // previous code ignored the error. Seem like it's very unlikely to fail, so ok for now. + uncastObj, err := legacyscheme.Scheme.ConvertToVersion(uncastVersionedObj, api.SchemeGroupVersion) + if err == nil { + newRc, _ = uncastObj.(*api.ReplicationController) + } } if newRc == nil { glog.V(4).Infof("Object %T is not a ReplicationController", infos[0].Object) - return cmdutil.UsageErrorf(cmd, "%s contains a %v not a ReplicationController", filename, infos[0].Object.GetObjectKind().GroupVersionKind()) + return fmt.Errorf("%s contains a %v not a ReplicationController", filename, infos[0].Object.GetObjectKind().GroupVersionKind()) } } // If the --image option is specified, we need to create a new rc with at least one different selector // than the old rc. This selector is the hash of the rc, with a suffix to provide uniqueness for // same-image updates. - if len(image) != 0 { + if len(o.Image) != 0 { codec := legacyscheme.Codecs.LegacyCodec(v1.SchemeGroupVersion) - keepOldName = len(args) == 1 - newName := findNewName(args, oldRc) - if newRc, err = kubectl.LoadExistingNextReplicationController(coreClient, cmdNamespace, newName); err != nil { + newName := o.FindNewName(oldRc) + if newRc, err = kubectl.LoadExistingNextReplicationController(coreClient, o.Namespace, newName); err != nil { return err } if newRc != nil { - if inProgressImage := newRc.Spec.Template.Spec.Containers[0].Image; inProgressImage != image { - return cmdutil.UsageErrorf(cmd, "Found existing in-progress update to image (%s).\nEither continue in-progress update with --image=%s or rollback with --rollback", inProgressImage, inProgressImage) + if inProgressImage := newRc.Spec.Template.Spec.Containers[0].Image; inProgressImage != o.Image { + return fmt.Errorf("Found existing in-progress update to image (%s).\nEither continue in-progress update with --image=%s or rollback with --rollback", inProgressImage, inProgressImage) } - fmt.Fprintf(out, "Found existing update in progress (%s), resuming.\n", newRc.Name) + fmt.Fprintf(o.Out, "Found existing update in progress (%s), resuming.\n", newRc.Name) } else { config := &kubectl.NewControllerConfig{ - Namespace: cmdNamespace, - OldName: oldName, + Namespace: o.Namespace, + OldName: o.OldName, NewName: newName, - Image: image, - Container: container, - DeploymentKey: deploymentKey, + Image: o.Image, + Container: o.Container, + DeploymentKey: o.DeploymentKey, } - if oldRc.Spec.Template.Spec.Containers[0].Image == image { - if len(pullPolicy) == 0 { - return cmdutil.UsageErrorf(cmd, "--image-pull-policy (Always|Never|IfNotPresent) must be provided when --image is the same as existing container image") + if oldRc.Spec.Template.Spec.Containers[0].Image == o.Image { + if len(o.PullPolicy) == 0 { + return fmt.Errorf("--image-pull-policy (Always|Never|IfNotPresent) must be provided when --image is the same as existing container image") } - config.PullPolicy = api.PullPolicy(pullPolicy) + config.PullPolicy = api.PullPolicy(o.PullPolicy) } newRc, err = kubectl.CreateNewControllerFromCurrentController(coreClient, codec, config) if err != nil { @@ -270,30 +354,29 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args } // If new image is same as old, the hash may not be distinct, so add a suffix. oldHash += "-orig" - oldRc, err = kubectl.UpdateExistingReplicationController(coreClient, coreClient, oldRc, cmdNamespace, newRc.Name, deploymentKey, oldHash, out) + oldRc, err = kubectl.UpdateExistingReplicationController(coreClient, coreClient, oldRc, o.Namespace, newRc.Name, o.DeploymentKey, oldHash, o.Out) if err != nil { return err } } - if rollback { - keepOldName = len(args) == 1 - newName := findNewName(args, oldRc) - if newRc, err = kubectl.LoadExistingNextReplicationController(coreClient, cmdNamespace, newName); err != nil { + if o.Rollback { + newName := o.FindNewName(oldRc) + if newRc, err = kubectl.LoadExistingNextReplicationController(coreClient, o.Namespace, newName); err != nil { return err } if newRc == nil { - return cmdutil.UsageErrorf(cmd, "Could not find %s to rollback.\n", newName) + return fmt.Errorf("Could not find %s to rollback.\n", newName) } } - if oldName == newRc.Name { - return cmdutil.UsageErrorf(cmd, "%s cannot have the same name as the existing ReplicationController %s", - filename, oldName) + if o.OldName == newRc.Name { + return fmt.Errorf("%s cannot have the same name as the existing ReplicationController %s", + filename, o.OldName) } - updater := kubectl.NewRollingUpdater(newRc.Namespace, coreClient, coreClient) + updater := kubectl.NewRollingUpdater(newRc.Namespace, coreClient, coreClient, o.ScaleClient) // To successfully pull off a rolling update the new and old rc have to differ // by at least one selector. Every new pod should have the selector and every @@ -306,46 +389,51 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args } } if !hasLabel { - return cmdutil.UsageErrorf(cmd, "%s must specify a matching key with non-equal value in Selector for %s", - filename, oldName) + return fmt.Errorf("%s must specify a matching key with non-equal value in Selector for %s", + filename, o.OldName) } // TODO: handle scales during rolling update if replicasDefaulted { newRc.Spec.Replicas = oldRc.Spec.Replicas } - if dryrun { + + if o.DryRun { oldRcData := &bytes.Buffer{} newRcData := &bytes.Buffer{} - if outputFormat == "" { + if o.OutputFormat == "" { oldRcData.WriteString(oldRc.Name) newRcData.WriteString(newRc.Name) } else { - if err := cmdutil.PrintObject(cmd, oldRc, oldRcData); err != nil { + printer, err := o.ToPrinter("rolling updated") + if err != nil { return err } - if err := cmdutil.PrintObject(cmd, newRc, newRcData); err != nil { + if err := printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(oldRc, nil), oldRcData); err != nil { + return err + } + if err := printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(newRc, nil), newRcData); err != nil { return err } } - fmt.Fprintf(out, "Rolling from:\n%s\nTo:\n%s\n", string(oldRcData.Bytes()), string(newRcData.Bytes())) + fmt.Fprintf(o.Out, "Rolling from:\n%s\nTo:\n%s\n", string(oldRcData.Bytes()), string(newRcData.Bytes())) return nil } updateCleanupPolicy := kubectl.DeleteRollingUpdateCleanupPolicy - if keepOldName { + if o.KeepOldName { updateCleanupPolicy = kubectl.RenameRollingUpdateCleanupPolicy } config := &kubectl.RollingUpdaterConfig{ - Out: out, + Out: o.Out, OldRc: oldRc, NewRc: newRc, - UpdatePeriod: period, - Interval: interval, + UpdatePeriod: o.Period, + Interval: o.Interval, Timeout: timeout, CleanupPolicy: updateCleanupPolicy, MaxUnavailable: intstr.FromInt(0), MaxSurge: intstr.FromInt(1), } - if rollback { + if o.Rollback { err = kubectl.AbortRollingUpdate(config) if err != nil { return err @@ -358,20 +446,21 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args } message := "rolling updated" - if keepOldName { - newRc.Name = oldName + if o.KeepOldName { + newRc.Name = o.OldName } else { message = fmt.Sprintf("rolling updated to %q", newRc.Name) } - newRc, err = coreClient.ReplicationControllers(cmdNamespace).Get(newRc.Name, metav1.GetOptions{}) + newRc, err = coreClient.ReplicationControllers(o.Namespace).Get(newRc.Name, metav1.GetOptions{}) if err != nil { return err } - if outputFormat != "" { - return cmdutil.PrintObject(cmd, newRc, out) + + printer, err := o.ToPrinter(message) + if err != nil { + return err } - cmdutil.PrintSuccess(false, out, newRc, dryrun, message) - return nil + return printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(newRc, nil), o.Out) } func findNewName(args []string, oldRc *api.ReplicationController) string { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate_test.go index 4e452dbb6..3d1507463 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate_test.go @@ -17,10 +17,10 @@ limitations under the License. package cmd import ( - "bytes" "testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestValidateArgs(t *testing.T) { @@ -74,8 +74,7 @@ func TestValidateArgs(t *testing.T) { }, } for _, test := range tests { - out := &bytes.Buffer{} - cmd := NewCmdRollingUpdate(f, out) + cmd := NewCmdRollingUpdate(f, genericclioptions.NewTestIOStreamsDiscard()) if test.flags != nil { for key, val := range test.flags { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/BUILD index dbcdca014..652bc084f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/BUILD @@ -1,6 +1,7 @@ load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( @@ -18,17 +19,21 @@ go_library( "//build/visible_to:pkg_kubectl_cmd_rollout_CONSUMERS", ], deps = [ + "//pkg/api/legacyscheme:go_default_library", "//pkg/kubectl:go_default_library", "//pkg/kubectl/cmd/set:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/kubectl/resource:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//pkg/kubectl/polymorphichelpers:go_default_library", + "//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", "//pkg/util/interrupt:go_default_library", "//vendor/github.com/renstrom/dedent:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", @@ -49,3 +54,20 @@ filegroup( "//build/visible_to:pkg_kubectl_cmd_rollout_CONSUMERS", ], ) + +go_test( + name = "go_default_test", + srcs = ["rollout_pause_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/api/legacyscheme:go_default_library", + "//pkg/apis/extensions:go_default_library", + "//pkg/kubectl/cmd/testing:go_default_library", + "//pkg/kubectl/genericclioptions: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/types:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/rest/fake:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout.go index 941b585c1..d7d03e266 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout.go @@ -17,12 +17,12 @@ limitations under the License. package rollout import ( - "io" - "github.com/renstrom/dedent" "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -46,22 +46,21 @@ var ( `) ) -func NewCmdRollout(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - +func NewCmdRollout(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "rollout SUBCOMMAND", DisableFlagsInUseLine: true, Short: i18n.T("Manage the rollout of a resource"), Long: rollout_long, Example: rollout_example, - Run: cmdutil.DefaultSubCommandRun(errOut), + Run: cmdutil.DefaultSubCommandRun(streams.Out), } // subcommands - cmd.AddCommand(NewCmdRolloutHistory(f, out)) - cmd.AddCommand(NewCmdRolloutPause(f, out)) - cmd.AddCommand(NewCmdRolloutResume(f, out)) - cmd.AddCommand(NewCmdRolloutUndo(f, out)) - cmd.AddCommand(NewCmdRolloutStatus(f, out)) + cmd.AddCommand(NewCmdRolloutHistory(f, streams.Out)) + cmd.AddCommand(NewCmdRolloutPause(f, streams)) + cmd.AddCommand(NewCmdRolloutResume(f, streams)) + cmd.AddCommand(NewCmdRolloutUndo(f, streams.Out)) + cmd.AddCommand(NewCmdRolloutStatus(f, streams)) return cmd } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_history.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_history.go index fb6ccbe90..b438bc30d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_history.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_history.go @@ -20,10 +20,11 @@ import ( "fmt" "io" - "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "github.com/spf13/cobra" @@ -45,7 +46,6 @@ func NewCmdRolloutHistory(f cmdutil.Factory, out io.Writer) *cobra.Command { options := &resource.FilenameOptions{} validArgs := []string{"deployment", "daemonset", "statefulset"} - argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ Use: "history (TYPE NAME | TYPE/NAME) [flags]", @@ -56,8 +56,7 @@ func NewCmdRolloutHistory(f cmdutil.Factory, out io.Writer) *cobra.Command { Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(RunHistory(f, cmd, out, args, options)) }, - ValidArgs: validArgs, - ArgAliases: argAliases, + ValidArgs: validArgs, } cmd.Flags().Int64("revision", 0, "See the details, including podTemplate of the revision specified") @@ -75,13 +74,13 @@ func RunHistory(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []str return fmt.Errorf("revision must be a positive integer: %v", revision) } - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } r := f.NewBuilder(). - Internal(). + WithScheme(legacyscheme.Scheme). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(true, args...). @@ -99,7 +98,7 @@ func RunHistory(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []str return err } mapping := info.ResourceMapping() - historyViewer, err := f.HistoryViewer(mapping) + historyViewer, err := polymorphichelpers.HistoryViewerFn(f, mapping) if err != nil { return err } @@ -108,7 +107,7 @@ func RunHistory(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []str return err } - header := fmt.Sprintf("%s %q", mapping.Resource, info.Name) + header := fmt.Sprintf("%s %q", mapping.Resource.Resource, info.Name) if revision > 0 { header = fmt.Sprintf("%s with revision #%d", header, revision) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause.go index 933b76868..7ab8a8519 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause.go @@ -18,19 +18,20 @@ package rollout import ( "fmt" - "io" "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl/cmd/set" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -38,13 +39,13 @@ import ( // referencing the cmd.Flags() type PauseConfig struct { resource.FilenameOptions + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) - Pauser func(info *resource.Info) ([]byte, error) - Mapper meta.RESTMapper - Typer runtime.ObjectTyper + Pauser polymorphichelpers.ObjectPauserFunc Infos []*resource.Info - Out io.Writer + genericclioptions.IOStreams } var ( @@ -62,11 +63,13 @@ var ( kubectl rollout pause deployment/nginx`) ) -func NewCmdRolloutPause(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &PauseConfig{} +func NewCmdRolloutPause(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := &PauseConfig{ + PrintFlags: genericclioptions.NewPrintFlags("paused").WithTypeSetter(scheme.Scheme), + IOStreams: streams, + } validArgs := []string{"deployment"} - argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ Use: "pause RESOURCE", @@ -76,42 +79,38 @@ func NewCmdRolloutPause(f cmdutil.Factory, out io.Writer) *cobra.Command { Example: pause_example, Run: func(cmd *cobra.Command, args []string) { allErrs := []error{} - err := options.CompletePause(f, cmd, out, args) + err := o.CompletePause(f, cmd, args) if err != nil { allErrs = append(allErrs, err) } - err = options.RunPause() + err = o.RunPause() if err != nil { allErrs = append(allErrs, err) } cmdutil.CheckErr(utilerrors.Flatten(utilerrors.NewAggregate(allErrs))) }, - ValidArgs: validArgs, - ArgAliases: argAliases, + ValidArgs: validArgs, } usage := "identifying the resource to get from a server." - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) return cmd } -func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { +func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, args []string) error { if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } - o.Mapper, o.Typer = f.Object() - - o.Pauser = f.Pauser - o.Out = out + o.Pauser = polymorphichelpers.ObjectPauserFn - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } r := f.NewBuilder(). - Internal(). + WithScheme(legacyscheme.Scheme). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). ResourceTypeOrNameArgs(true, args...). @@ -124,6 +123,11 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out i return err } + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + return o.PrintFlags.ToPrinter() + } + o.Infos, err = r.Infos() if err != nil { return err @@ -133,15 +137,26 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out i func (o PauseConfig) RunPause() error { allErrs := []error{} - for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), o.Pauser) { + for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), set.PatchFn(o.Pauser)) { info := patch.Info if patch.Err != nil { - allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", info.Mapping.Resource, info.Name, patch.Err)) + resourceString := info.Mapping.Resource.Resource + if len(info.Mapping.Resource.Group) > 0 { + resourceString = resourceString + "." + info.Mapping.Resource.Group + } + allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", resourceString, info.Name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - cmdutil.PrintSuccess(false, o.Out, info.Object, false, "already paused") + printer, err := o.ToPrinter("already paused") + if err != nil { + allErrs = append(allErrs, err) + continue + } + if err = printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out); err != nil { + allErrs = append(allErrs, err) + } continue } @@ -152,7 +167,14 @@ func (o PauseConfig) RunPause() error { } info.Refresh(obj, true) - cmdutil.PrintSuccess(false, o.Out, info.Object, false, "paused") + printer, err := o.ToPrinter("paused") + if err != nil { + allErrs = append(allErrs, err) + continue + } + if err = printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out); err != nil { + allErrs = append(allErrs, err) + } } return utilerrors.NewAggregate(allErrs) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause_test.go new file mode 100644 index 000000000..965a52163 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause_test.go @@ -0,0 +1,121 @@ +/* +Copyright 2018 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 rollout + +import ( + "bytes" + "io/ioutil" + "net/http" + "net/url" + "testing" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" + extensions "k8s.io/kubernetes/pkg/apis/extensions" + cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +var rolloutPauseGroupVersionEncoder = schema.GroupVersion{Group: "extensions", Version: "v1beta1"} +var rolloutPauseGroupVersionDecoder = schema.GroupVersion{Group: "extensions", Version: runtime.APIVersionInternal} + +func TestRolloutPause(t *testing.T) { + deploymentName := "deployment/nginx-deployment" + ns := legacyscheme.Codecs + tf := cmdtesting.NewTestFactory().WithNamespace("test") + + info, _ := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), runtime.ContentTypeJSON) + encoder := ns.EncoderForVersion(info.Serializer, rolloutPauseGroupVersionEncoder) + tf.Client = &RolloutPauseRESTClient{ + RESTClient: &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == "/namespaces/test/deployments/nginx-deployment" && (m == "GET" || m == "PATCH"): + responseDeployment := &extensions.Deployment{} + responseDeployment.Name = deploymentName + body := ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, responseDeployment)))) + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: body}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + }, + } + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdRolloutPause(tf, streams) + + cmd.Run(cmd, []string{deploymentName}) + expectedOutput := "deployment.extensions/" + deploymentName + " paused\n" + if buf.String() != expectedOutput { + t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) + } +} + +type RolloutPauseRESTClient struct { + *fake.RESTClient +} + +func (c *RolloutPauseRESTClient) Get() *restclient.Request { + config := restclient.ContentConfig{ + ContentType: runtime.ContentTypeJSON, + GroupVersion: &rolloutPauseGroupVersionEncoder, + NegotiatedSerializer: c.NegotiatedSerializer, + } + + info, _ := runtime.SerializerInfoForMediaType(c.NegotiatedSerializer.SupportedMediaTypes(), runtime.ContentTypeJSON) + serializers := restclient.Serializers{ + Encoder: c.NegotiatedSerializer.EncoderForVersion(info.Serializer, rolloutPauseGroupVersionEncoder), + Decoder: c.NegotiatedSerializer.DecoderToVersion(info.Serializer, rolloutPauseGroupVersionDecoder), + } + if info.StreamSerializer != nil { + serializers.StreamingSerializer = info.StreamSerializer.Serializer + serializers.Framer = info.StreamSerializer.Framer + } + return restclient.NewRequest(c, "GET", &url.URL{Host: "localhost"}, c.VersionedAPIPath, config, serializers, nil, nil, 0) +} + +func (c *RolloutPauseRESTClient) Patch(pt types.PatchType) *restclient.Request { + config := restclient.ContentConfig{ + ContentType: runtime.ContentTypeJSON, + GroupVersion: &rolloutPauseGroupVersionEncoder, + NegotiatedSerializer: c.NegotiatedSerializer, + } + + info, _ := runtime.SerializerInfoForMediaType(c.NegotiatedSerializer.SupportedMediaTypes(), runtime.ContentTypeJSON) + serializers := restclient.Serializers{ + Encoder: c.NegotiatedSerializer.EncoderForVersion(info.Serializer, rolloutPauseGroupVersionEncoder), + Decoder: c.NegotiatedSerializer.DecoderToVersion(info.Serializer, rolloutPauseGroupVersionDecoder), + } + if info.StreamSerializer != nil { + serializers.StreamingSerializer = info.StreamSerializer.Serializer + serializers.Framer = info.StreamSerializer.Framer + } + return restclient.NewRequest(c, "PATCH", &url.URL{Host: "localhost"}, c.VersionedAPIPath, config, serializers, nil, nil, 0) +} + +func defaultHeader() http.Header { + header := http.Header{} + header.Set("Content-Type", runtime.ContentTypeJSON) + return header +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_resume.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_resume.go index a57829223..aca0534f8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_resume.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_resume.go @@ -18,19 +18,20 @@ package rollout import ( "fmt" - "io" "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl/cmd/set" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -38,13 +39,13 @@ import ( // referencing the cmd.Flags() type ResumeConfig struct { resource.FilenameOptions + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) - Resumer func(object *resource.Info) ([]byte, error) - Mapper meta.RESTMapper - Typer runtime.ObjectTyper + Resumer polymorphichelpers.ObjectResumerFunc Infos []*resource.Info - Out io.Writer + genericclioptions.IOStreams } var ( @@ -60,11 +61,13 @@ var ( kubectl rollout resume deployment/nginx`) ) -func NewCmdRolloutResume(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ResumeConfig{} +func NewCmdRolloutResume(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := &ResumeConfig{ + PrintFlags: genericclioptions.NewPrintFlags("resumed").WithTypeSetter(scheme.Scheme), + IOStreams: streams, + } validArgs := []string{"deployment"} - argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ Use: "resume RESOURCE", @@ -74,42 +77,43 @@ func NewCmdRolloutResume(f cmdutil.Factory, out io.Writer) *cobra.Command { Example: resume_example, Run: func(cmd *cobra.Command, args []string) { allErrs := []error{} - err := options.CompleteResume(f, cmd, out, args) + err := o.CompleteResume(f, cmd, args) if err != nil { allErrs = append(allErrs, err) } - err = options.RunResume() + err = o.RunResume() if err != nil { allErrs = append(allErrs, err) } cmdutil.CheckErr(utilerrors.Flatten(utilerrors.NewAggregate(allErrs))) }, - ValidArgs: validArgs, - ArgAliases: argAliases, + ValidArgs: validArgs, } usage := "identifying the resource to get from a server." - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) return cmd } -func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { +func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, args []string) error { if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } - o.Mapper, o.Typer = f.Object() - - o.Resumer = f.Resumer - o.Out = out + o.Resumer = polymorphichelpers.ObjectResumerFn - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + return o.PrintFlags.ToPrinter() + } + r := f.NewBuilder(). - Internal(). + WithScheme(legacyscheme.Scheme). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). ResourceTypeOrNameArgs(true, args...). @@ -137,17 +141,27 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, out func (o ResumeConfig) RunResume() error { allErrs := []error{} - for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), o.Resumer) { + for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), set.PatchFn(o.Resumer)) { info := patch.Info if patch.Err != nil { - allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", info.Mapping.Resource, info.Name, patch.Err)) + resourceString := info.Mapping.Resource.Resource + if len(info.Mapping.Resource.Group) > 0 { + resourceString = resourceString + "." + info.Mapping.Resource.Group + } + allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", resourceString, info.Name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - cmdutil.PrintSuccess(false, o.Out, info.Object, false, "already resumed") - continue + printer, err := o.ToPrinter("already resumed") + if err != nil { + allErrs = append(allErrs, err) + continue + } + if err = printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out); err != nil { + allErrs = append(allErrs, err) + } } obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) @@ -157,7 +171,14 @@ func (o ResumeConfig) RunResume() error { } info.Refresh(obj, true) - cmdutil.PrintSuccess(false, o.Out, info.Object, false, "resumed") + printer, err := o.ToPrinter("resumed") + if err != nil { + allErrs = append(allErrs, err) + continue + } + if err = printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out); err != nil { + allErrs = append(allErrs, err) + } } return utilerrors.NewAggregate(allErrs) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_status.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_status.go index 224d240ba..e705bd8d1 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_status.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_status.go @@ -18,17 +18,20 @@ package rollout import ( "fmt" - "io" + "github.com/spf13/cobra" + + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/watch" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/util/interrupt" - - "github.com/spf13/cobra" ) var ( @@ -47,11 +50,34 @@ var ( kubectl rollout status deployment/nginx`) ) -func NewCmdRolloutStatus(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &resource.FilenameOptions{} +type RolloutStatusOptions struct { + FilenameOptions *resource.FilenameOptions + genericclioptions.IOStreams + + Namespace string + EnforceNamespace bool + BuilderArgs []string + + Watch bool + Revision int64 + + StatusViewer func(*meta.RESTMapping) (kubectl.StatusViewer, error) + + Builder *resource.Builder +} + +func NewRolloutStatusOptions(streams genericclioptions.IOStreams) *RolloutStatusOptions { + return &RolloutStatusOptions{ + FilenameOptions: &resource.FilenameOptions{}, + IOStreams: streams, + Watch: true, + } +} + +func NewCmdRolloutStatus(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewRolloutStatusOptions(streams) validArgs := []string{"deployment", "daemonset", "statefulset"} - argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ Use: "status (TYPE NAME | TYPE/NAME) [flags]", @@ -60,38 +86,53 @@ func NewCmdRolloutStatus(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: status_long, Example: status_example, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(RunStatus(f, cmd, out, args, options)) + cmdutil.CheckErr(o.Complete(f, args)) + cmdutil.CheckErr(o.Validate(cmd, args)) + cmdutil.CheckErr(o.Run()) }, - ValidArgs: validArgs, - ArgAliases: argAliases, + ValidArgs: validArgs, } usage := "identifying the resource to get from a server." - cmdutil.AddFilenameOptionFlags(cmd, options, usage) - cmd.Flags().BoolP("watch", "w", true, "Watch the status of the rollout until it's done.") - cmd.Flags().Int64("revision", 0, "Pin to a specific revision for showing its status. Defaults to 0 (last revision).") + cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, usage) + cmd.Flags().BoolVarP(&o.Watch, "watch", "w", o.Watch, "Watch the status of the rollout until it's done.") + cmd.Flags().Int64Var(&o.Revision, "revision", o.Revision, "Pin to a specific revision for showing its status. Defaults to 0 (last revision).") return cmd } -func RunStatus(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *resource.FilenameOptions) error { - if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { - return cmdutil.UsageErrorf(cmd, "Required resource not specified.") - } +func (o *RolloutStatusOptions) Complete(f cmdutil.Factory, args []string) error { + o.Builder = f.NewBuilder() - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + var err error + o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - r := f.NewBuilder(). - Internal(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options). - ResourceTypeOrNameArgs(true, args...). + o.BuilderArgs = args + o.StatusViewer = func(mapping *meta.RESTMapping) (kubectl.StatusViewer, error) { + return polymorphichelpers.StatusViewerFn(f, mapping) + } + return nil +} + +func (o *RolloutStatusOptions) Validate(cmd *cobra.Command, args []string) error { + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) { + return cmdutil.UsageErrorf(cmd, "Required resource not specified.") + } + return nil +} + +func (o *RolloutStatusOptions) Run() error { + r := o.Builder. + WithScheme(legacyscheme.Scheme). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.EnforceNamespace, o.FilenameOptions). + ResourceTypeOrNameArgs(true, o.BuilderArgs...). SingleResourceType(). Latest(). Do() - err = r.Err() + err := r.Err() if err != nil { return err } @@ -110,17 +151,17 @@ func RunStatus(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []stri if err != nil { return err } - rv, err := mapping.MetadataAccessor.ResourceVersion(obj) + rv, err := meta.NewAccessor().ResourceVersion(obj) if err != nil { return err } - statusViewer, err := f.StatusViewer(mapping) + statusViewer, err := o.StatusViewer(mapping) if err != nil { return err } - revision := cmdutil.GetFlagInt64(cmd, "revision") + revision := o.Revision if revision < 0 { return fmt.Errorf("revision must be a positive integer: %v", revision) } @@ -130,12 +171,12 @@ func RunStatus(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []stri if err != nil { return err } - fmt.Fprintf(out, "%s", status) + fmt.Fprintf(o.Out, "%s", status) if done { return nil } - shouldWatch := cmdutil.GetFlagBool(cmd, "watch") + shouldWatch := o.Watch if !shouldWatch { return nil } @@ -155,7 +196,7 @@ func RunStatus(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []stri if err != nil { return false, err } - fmt.Fprintf(out, "%s", status) + fmt.Fprintf(o.Out, "%s", status) // Quit waiting if the rollout is done if done { return true, nil diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_undo.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_undo.go index c69251e6c..f2840eebe 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_undo.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_undo.go @@ -19,16 +19,19 @@ package rollout import ( "io" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" + "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" - - "github.com/spf13/cobra" ) // UndoOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of @@ -36,9 +39,10 @@ import ( type UndoOptions struct { resource.FilenameOptions + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) + Rollbackers []kubectl.Rollbacker - Mapper meta.RESTMapper - Typer runtime.ObjectTyper Infos []*resource.Info ToRevision int64 DryRun bool @@ -62,10 +66,12 @@ var ( ) func NewCmdRolloutUndo(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &UndoOptions{} + o := &UndoOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithTypeSetter(scheme.Scheme), + ToRevision: int64(0), + } validArgs := []string{"deployment", "daemonset", "statefulset"} - argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ Use: "undo (TYPE NAME | TYPE/NAME) [flags]", @@ -75,23 +81,22 @@ func NewCmdRolloutUndo(f cmdutil.Factory, out io.Writer) *cobra.Command { Example: undo_example, Run: func(cmd *cobra.Command, args []string) { allErrs := []error{} - err := options.CompleteUndo(f, cmd, out, args) + err := o.CompleteUndo(f, cmd, out, args) if err != nil { allErrs = append(allErrs, err) } - err = options.RunUndo() + err = o.RunUndo() if err != nil { allErrs = append(allErrs, err) } cmdutil.CheckErr(utilerrors.Flatten(utilerrors.NewAggregate(allErrs))) }, - ValidArgs: validArgs, - ArgAliases: argAliases, + ValidArgs: validArgs, } - cmd.Flags().Int64("to-revision", 0, "The revision to rollback to. Default to 0 (last revision).") + cmd.Flags().Int64Var(&o.ToRevision, "to-revision", o.ToRevision, "The revision to rollback to. Default to 0 (last revision).") usage := "identifying the resource to get from a server." - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) cmdutil.AddDryRunFlag(cmd) return cmd } @@ -101,18 +106,24 @@ func (o *UndoOptions) CompleteUndo(f cmdutil.Factory, cmd *cobra.Command, out io return cmdutil.UsageErrorf(cmd, "Required resource not specified.") } - o.ToRevision = cmdutil.GetFlagInt64(cmd, "to-revision") - o.Mapper, o.Typer = f.Object() o.Out = out o.DryRun = cmdutil.GetDryRunFlag(cmd) - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + return o.PrintFlags.ToPrinter() + } + r := f.NewBuilder(). - Internal(). + WithScheme(legacyscheme.Scheme). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). ResourceTypeOrNameArgs(true, args...). @@ -129,7 +140,7 @@ func (o *UndoOptions) CompleteUndo(f cmdutil.Factory, cmd *cobra.Command, out io if err != nil { return err } - rollbacker, err := f.Rollbacker(info.ResourceMapping()) + rollbacker, err := polymorphichelpers.RollbackerFn(f, info.ResourceMapping()) if err != nil { return err } @@ -148,7 +159,12 @@ func (o *UndoOptions) RunUndo() error { allErrs = append(allErrs, cmdutil.AddSourceToErr("undoing", info.Source, err)) continue } - cmdutil.PrintSuccess(false, o.Out, info.Object, false, result) + printer, err := o.ToPrinter(result) + if err != nil { + allErrs = append(allErrs, err) + continue + } + printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out) } return utilerrors.NewAggregate(allErrs) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/run.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/run.go index 7baf95c3f..7157b72c8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/run.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/run.go @@ -23,21 +23,25 @@ import ( "github.com/docker/distribution/reference" "github.com/spf13/cobra" - batchv1 "k8s.io/api/batch/v1" - batchv1beta1 "k8s.io/api/batch/v1beta1" - extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + "k8s.io/client-go/dynamic" + + "github.com/golang/glog" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/watch" + "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/util/interrupt" uexec "k8s.io/utils/exec" @@ -89,11 +93,52 @@ var ( type RunObject struct { Object runtime.Object - Kind string Mapping *meta.RESTMapping } -func NewCmdRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command { +type RunOptions struct { + PrintFlags *genericclioptions.PrintFlags + DeleteFlags *DeleteFlags + DeleteOptions *DeleteOptions + RecordFlags *genericclioptions.RecordFlags + + DryRun bool + + PrintObj func(runtime.Object) error + Recorder genericclioptions.Recorder + + DynamicClient dynamic.Interface + + ArgsLenAtDash int + Attach bool + Expose bool + Generator string + Image string + Interactive bool + LeaveStdinOpen bool + Port string + Quiet bool + Schedule string + TTY bool + + genericclioptions.IOStreams +} + +func NewRunOptions(streams genericclioptions.IOStreams) *RunOptions { + return &RunOptions{ + PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme), + DeleteFlags: NewDeleteFlags("to use to replace the resource."), + RecordFlags: genericclioptions.NewRecordFlags(), + + Recorder: genericclioptions.NoopRecorder{}, + + IOStreams: streams, + } +} + +func NewCmdRun(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewRunOptions(streams) + cmd := &cobra.Command{ Use: "run NAME --image=image [--env=\"key=value\"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...]", DisableFlagsInUseLine: true, @@ -101,24 +146,25 @@ func NewCmdRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *co Long: runLong, Example: runExample, Run: func(cmd *cobra.Command, args []string) { - argsLenAtDash := cmd.ArgsLenAtDash() - err := RunRun(f, cmdIn, cmdOut, cmdErr, cmd, args, argsLenAtDash) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd)) + cmdutil.CheckErr(o.Run(f, cmd, args)) }, } - cmdutil.AddPrinterFlags(cmd) - addRunFlags(cmd) + + o.DeleteFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) + o.RecordFlags.AddFlags(cmd) + + addRunFlags(cmd, o) cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodAttachTimeout) return cmd } -func addRunFlags(cmd *cobra.Command) { +func addRunFlags(cmd *cobra.Command, opt *RunOptions) { cmdutil.AddDryRunFlag(cmd) - cmd.Flags().String("generator", "", i18n.T("The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.")) - cmd.Flags().String("image", "", i18n.T("The image for the container to run.")) + cmd.Flags().StringVar(&opt.Generator, "generator", opt.Generator, i18n.T("The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.")) + cmd.Flags().StringVar(&opt.Image, "image", opt.Image, i18n.T("The image for the container to run.")) cmd.MarkFlagRequired("image") cmd.Flags().String("image-pull-policy", "", i18n.T("The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server")) cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.") @@ -126,27 +172,70 @@ func addRunFlags(cmd *cobra.Command) { cmd.Flags().String("overrides", "", i18n.T("An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.")) cmd.Flags().StringArray("env", []string{}, "Environment variables to set in the container") cmd.Flags().String("serviceaccount", "", "Service account to set in the pod spec") - cmd.Flags().String("port", "", i18n.T("The port that this container exposes. If --expose is true, this is also the port used by the service that is created.")) + cmd.Flags().StringVar(&opt.Port, "port", opt.Port, i18n.T("The port that this container exposes. If --expose is true, this is also the port used by the service that is created.")) cmd.Flags().Int("hostport", -1, "The host port mapping for the container port. To demonstrate a single-machine container.") cmd.Flags().StringP("labels", "l", "", "Comma separated labels to apply to the pod(s). Will override previous values.") - cmd.Flags().BoolP("stdin", "i", false, "Keep stdin open on the container(s) in the pod, even if nothing is attached.") - cmd.Flags().BoolP("tty", "t", false, "Allocated a TTY for each container in the pod.") - cmd.Flags().Bool("attach", false, "If true, wait for the Pod to start running, and then attach to the Pod as if 'kubectl attach ...' were called. Default false, unless '-i/--stdin' is set, in which case the default is true. With '--restart=Never' the exit code of the container process is returned.") - cmd.Flags().Bool("leave-stdin-open", false, "If the pod is started in interactive mode or with stdin, leave stdin open after the first attach completes. By default, stdin will be closed after the first attach completes.") + cmd.Flags().BoolVarP(&opt.Interactive, "stdin", "i", opt.Interactive, "Keep stdin open on the container(s) in the pod, even if nothing is attached.") + cmd.Flags().BoolVarP(&opt.TTY, "tty", "t", opt.TTY, "Allocated a TTY for each container in the pod.") + cmd.Flags().BoolVar(&opt.Attach, "attach", opt.Attach, "If true, wait for the Pod to start running, and then attach to the Pod as if 'kubectl attach ...' were called. Default false, unless '-i/--stdin' is set, in which case the default is true. With '--restart=Never' the exit code of the container process is returned.") + cmd.Flags().BoolVar(&opt.LeaveStdinOpen, "leave-stdin-open", opt.LeaveStdinOpen, "If the pod is started in interactive mode or with stdin, leave stdin open after the first attach completes. By default, stdin will be closed after the first attach completes.") cmd.Flags().String("restart", "Always", i18n.T("The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created, if set to 'OnFailure' a job is created, if set to 'Never', a regular pod is created. For the latter two --replicas must be 1. Default 'Always', for CronJobs `Never`.")) cmd.Flags().Bool("command", false, "If true and extra arguments are present, use them as the 'command' field in the container, rather than the 'args' field which is the default.") cmd.Flags().String("requests", "", i18n.T("The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.")) cmd.Flags().String("limits", "", i18n.T("The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.")) - cmd.Flags().Bool("expose", false, "If true, a public, external service is created for the container(s) which are run") + cmd.Flags().BoolVar(&opt.Expose, "expose", opt.Expose, "If true, a public, external service is created for the container(s) which are run") cmd.Flags().String("service-generator", "service/v2", i18n.T("The name of the generator to use for creating a service. Only used if --expose is true")) cmd.Flags().String("service-overrides", "", i18n.T("An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.")) - cmd.Flags().Bool("quiet", false, "If true, suppress prompt messages.") - cmd.Flags().String("schedule", "", i18n.T("A schedule in the Cron format the job should be run with.")) + cmd.Flags().BoolVar(&opt.Quiet, "quiet", opt.Quiet, "If true, suppress prompt messages.") + cmd.Flags().StringVar(&opt.Schedule, "schedule", opt.Schedule, i18n.T("A schedule in the Cron format the job should be run with.")) } -func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string, argsLenAtDash int) error { +func (o *RunOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { + var err error + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + + o.DynamicClient, err = f.DynamicClient() + if err != nil { + return err + } + + o.ArgsLenAtDash = cmd.ArgsLenAtDash() + o.DryRun = cmdutil.GetFlagBool(cmd, "dry-run") + + attachFlag := cmd.Flags().Lookup("attach") + if !attachFlag.Changed && o.Interactive { + o.Attach = true + } + + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObj = func(obj runtime.Object) error { + return printer.PrintObj(obj, o.Out) + } + + deleteOpts := o.DeleteFlags.ToOptions(o.DynamicClient, o.IOStreams) + deleteOpts.IgnoreNotFound = true + deleteOpts.WaitForDeletion = false + deleteOpts.GracePeriod = -1 + + o.DeleteOptions = deleteOpts + + return nil +} + +func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) error { // Let kubectl run follow rules for `--`, see #13004 issue - if len(args) == 0 || argsLenAtDash == 0 { + if len(args) == 0 || o.ArgsLenAtDash == 0 { return cmdutil.UsageErrorf(cmd, "NAME is required for run") } @@ -156,7 +245,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c } // validate image name - imageName := cmdutil.GetFlagString(cmd, "image") + imageName := o.Image if imageName == "" { return fmt.Errorf("--image is required") } @@ -165,24 +254,22 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c return fmt.Errorf("Invalid image name %q: %v", imageName, reference.ErrReferenceInvalidFormat) } - interactive := cmdutil.GetFlagBool(cmd, "stdin") - tty := cmdutil.GetFlagBool(cmd, "tty") - if tty && !interactive { + if o.TTY && !o.Interactive { return cmdutil.UsageErrorf(cmd, "-i/--stdin is required for containers with -t/--tty=true") } replicas := cmdutil.GetFlagInt(cmd, "replicas") - if interactive && replicas != 1 { + if o.Interactive && replicas != 1 { return cmdutil.UsageErrorf(cmd, "-i/--stdin requires that replicas is 1, found %d", replicas) } - if cmdutil.GetFlagBool(cmd, "expose") && len(cmdutil.GetFlagString(cmd, "port")) == 0 { + if o.Expose && len(o.Port) == 0 { return cmdutil.UsageErrorf(cmd, "--port must be set when exposing a service") } - namespace, _, err := f.DefaultNamespace() + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - restartPolicy, err := getRestartPolicy(cmd, interactive) + restartPolicy, err := getRestartPolicy(cmd, o.Interactive) if err != nil { return err } @@ -190,19 +277,12 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c return cmdutil.UsageErrorf(cmd, "--restart=%s requires that --replicas=1, found %d", restartPolicy, replicas) } - attachFlag := cmd.Flags().Lookup("attach") - attach := cmdutil.GetFlagBool(cmd, "attach") - - if !attachFlag.Changed && interactive { - attach = true - } - remove := cmdutil.GetFlagBool(cmd, "rm") - if !attach && remove { + if !o.Attach && remove { return cmdutil.UsageErrorf(cmd, "--rm should only be used for attached containers") } - if attach && cmdutil.GetDryRunFlag(cmd) { + if o.Attach && o.DryRun { return cmdutil.UsageErrorf(cmd, "--dry-run can't be used with attached containers options (--attach, --stdin, or --tty)") } @@ -215,54 +295,33 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c return err } - generatorName := cmdutil.GetFlagString(cmd, "generator") - schedule := cmdutil.GetFlagString(cmd, "schedule") - if len(schedule) != 0 && len(generatorName) == 0 { - hasResource, err := cmdutil.HasResource(clientset.Discovery(), batchv1beta1.SchemeGroupVersion.WithResource("cronjobs")) - if err != nil { - return err - } - if hasResource { - generatorName = cmdutil.CronJobV1Beta1GeneratorName - } else { - generatorName = cmdutil.CronJobV2Alpha1GeneratorName - } + generatorName := o.Generator + if len(o.Schedule) != 0 && len(generatorName) == 0 { + generatorName = cmdutil.CronJobV1Beta1GeneratorName } if len(generatorName) == 0 { switch restartPolicy { case api.RestartPolicyAlways: - // TODO: we need to deprecate this along with extensions/v1beta1.Deployments - // in favor of the new generator for apps/v1beta1.Deployments - hasResource, err := cmdutil.HasResource(clientset.Discovery(), extensionsv1beta1.SchemeGroupVersion.WithResource("deployments")) - if err != nil { - return err - } - if hasResource { - generatorName = cmdutil.DeploymentV1Beta1GeneratorName - } else { - generatorName = cmdutil.RunV1GeneratorName - } + generatorName = cmdutil.DeploymentAppsV1Beta1GeneratorName case api.RestartPolicyOnFailure: - hasResource, err := cmdutil.HasResource(clientset.Discovery(), batchv1.SchemeGroupVersion.WithResource("jobs")) - if err != nil { - return err - } - if hasResource { - generatorName = cmdutil.JobV1GeneratorName - } else { - generatorName = cmdutil.RunPodV1GeneratorName - } + generatorName = cmdutil.JobV1GeneratorName case api.RestartPolicyNever: generatorName = cmdutil.RunPodV1GeneratorName } - } - generatorName, err = cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), cmdErr) - if err != nil { - return err + // Falling back because the generator was not provided and the default one could be unavailable. + generatorNameTemp, err := cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), o.ErrOut) + if err != nil { + return err + } + if generatorNameTemp != generatorName { + cmdutil.Warning(o.ErrOut, generatorName, generatorNameTemp) + } else { + generatorName = generatorNameTemp + } } - generators := f.Generators("run") + generators := cmdutil.GeneratorFn("run") generator, found := generators[generatorName] if !found { return cmdutil.UsageErrorf(cmd, "generator %q not found", generatorName) @@ -277,19 +336,19 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c params["env"] = cmdutil.GetFlagStringArray(cmd, "env") var createdObjects = []*RunObject{} - runObject, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace) + runObject, err := o.createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace) if err != nil { return err } else { createdObjects = append(createdObjects, runObject) } allErrs := []error{} - if cmdutil.GetFlagBool(cmd, "expose") { + if o.Expose { serviceGenerator := cmdutil.GetFlagString(cmd, "service-generator") if len(serviceGenerator) == 0 { return cmdutil.UsageErrorf(cmd, "No service generator specified") } - serviceRunObject, err := generateService(f, cmd, args, serviceGenerator, params, namespace, cmdOut) + serviceRunObject, err := o.generateService(f, cmd, serviceGenerator, params, namespace) if err != nil { allErrs = append(allErrs, err) } else { @@ -297,23 +356,24 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c } } - if attach { - quiet := cmdutil.GetFlagBool(cmd, "quiet") + if o.Attach { + if remove { + defer o.removeCreatedObjects(f, createdObjects) + } + opts := &AttachOptions{ StreamOptions: StreamOptions{ - In: cmdIn, - Out: cmdOut, - Err: cmdErr, - Stdin: interactive, - TTY: tty, - Quiet: quiet, + IOStreams: o.IOStreams, + Stdin: o.Interactive, + TTY: o.TTY, + Quiet: o.Quiet, }, GetPodTimeout: timeout, CommandName: cmd.Parent().CommandPath() + " attach", Attach: &DefaultRemoteAttach{}, } - config, err := f.ClientConfig() + config, err := f.ToRESTConfig() if err != nil { return err } @@ -325,7 +385,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c } opts.PodClient = clientset.Core() - attachablePod, err := f.AttachablePodForObject(runObject.Object, opts.GetPodTimeout) + attachablePod, err := polymorphichelpers.AttachablePodForObjectFn(f, runObject.Object, opts.GetPodTimeout) if err != nil { return err } @@ -335,7 +395,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c } var pod *api.Pod - leaveStdinOpen := cmdutil.GetFlagBool(cmd, "leave-stdin-open") + leaveStdinOpen := o.LeaveStdinOpen waitForExitCode := !leaveStdinOpen && restartPolicy == api.RestartPolicyNever if waitForExitCode { pod, err = waitForPod(clientset.Core(), attachablePod.Namespace, attachablePod.Name, kubectl.PodCompleted) @@ -344,37 +404,6 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c } } - if remove { - for _, obj := range createdObjects { - namespace, err = obj.Mapping.MetadataAccessor.Namespace(obj.Object) - if err != nil { - return err - } - var name string - name, err = obj.Mapping.MetadataAccessor.Name(obj.Object) - if err != nil { - return err - } - r := f.NewBuilder(). - Internal(). - ContinueOnError(). - NamespaceParam(namespace).DefaultNamespace(). - ResourceNames(obj.Mapping.Resource, name). - Flatten(). - Do() - // Note: we pass in "true" for the "quiet" parameter because - // ReadResult will only print one thing based on the "quiet" - // flag, and that's the "pod xxx deleted" message. If they - // asked for us to remove the pod (via --rm) then telling them - // its been deleted is unnecessary since that's what they asked - // for. We should only print something if the "rm" fails. - err = ReapResult(r, f, cmdOut, true, true, 0, -1, false, false, true) - if err != nil { - return err - } - } - } - // after removal is done, return successfully if we are not interested in the exit code if !waitForExitCode { return nil @@ -403,16 +432,40 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c } if runObject != nil { - outputFormat := cmdutil.GetFlagString(cmd, "output") - if outputFormat != "" || cmdutil.GetDryRunFlag(cmd) { - return cmdutil.PrintObject(cmd, runObject.Object, cmdOut) + if err := o.PrintObj(runObject.Object); err != nil { + return err } - cmdutil.PrintSuccess(false, cmdOut, runObject.Object, cmdutil.GetDryRunFlag(cmd), "created") } return utilerrors.NewAggregate(allErrs) } +func (o *RunOptions) removeCreatedObjects(f cmdutil.Factory, createdObjects []*RunObject) error { + for _, obj := range createdObjects { + namespace, err := metadataAccessor.Namespace(obj.Object) + if err != nil { + return err + } + var name string + name, err = metadataAccessor.Name(obj.Object) + if err != nil { + return err + } + r := f.NewBuilder(). + WithScheme(legacyscheme.Scheme). + ContinueOnError(). + NamespaceParam(namespace).DefaultNamespace(). + ResourceNames(obj.Mapping.Resource.Resource+"."+obj.Mapping.Resource.Group, name). + Flatten(). + Do() + if err := o.DeleteOptions.DeleteResult(r); err != nil { + return err + } + } + + return nil +} + // waitForPod watches the given pod until the exitCondition is true func waitForPod(podClient coreclient.PodsGetter, ns, name string, exitCondition watch.ConditionFunc) (*api.Pod, error) { w, err := podClient.Pods(ns).Watch(metav1.SingleObject(metav1.ObjectMeta{Name: name})) @@ -455,7 +508,7 @@ func handleAttachPod(f cmdutil.Factory, podClient coreclient.PodsGetter, ns, nam opts.Namespace = ns // TODO: opts.Run sets opts.Err to nil, we need to find a better way - stderr := opts.Err + stderr := opts.ErrOut if err := opts.Run(); err != nil { fmt.Fprintf(stderr, "Error attaching, falling back to logs: %v\n", err) return logOpts(f, pod, opts) @@ -464,13 +517,13 @@ func handleAttachPod(f cmdutil.Factory, podClient coreclient.PodsGetter, ns, nam } // logOpts logs output from opts to the pods log. -func logOpts(f cmdutil.Factory, pod *api.Pod, opts *AttachOptions) error { +func logOpts(restClientGetter genericclioptions.RESTClientGetter, pod *api.Pod, opts *AttachOptions) error { ctrName, err := opts.GetContainerName(pod) if err != nil { return err } - req, err := f.LogsForObject(pod, &api.PodLogOptions{Container: ctrName}, opts.GetPodTimeout) + req, err := polymorphichelpers.LogsForObjectFn(restClientGetter, pod, &api.PodLogOptions{Container: ctrName}, opts.GetPodTimeout) if err != nil { return err } @@ -519,8 +572,8 @@ func verifyImagePullPolicy(cmd *cobra.Command) error { return cmdutil.UsageErrorf(cmd, "invalid image pull policy: %s", pullPolicy) } -func generateService(f cmdutil.Factory, cmd *cobra.Command, args []string, serviceGenerator string, paramsIn map[string]interface{}, namespace string, out io.Writer) (*RunObject, error) { - generators := f.Generators("expose") +func (o *RunOptions) generateService(f cmdutil.Factory, cmd *cobra.Command, serviceGenerator string, paramsIn map[string]interface{}, namespace string) (*RunObject, error) { + generators := cmdutil.GeneratorFn("expose") generator, found := generators[serviceGenerator] if !found { return nil, fmt.Errorf("missing service generator: %s", serviceGenerator) @@ -549,27 +602,23 @@ func generateService(f cmdutil.Factory, cmd *cobra.Command, args []string, servi params["default-name"] = name } - runObject, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "service-overrides"), namespace) + runObject, err := o.createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "service-overrides"), namespace) if err != nil { return nil, err } - if cmdutil.GetFlagString(cmd, "output") != "" || cmdutil.GetDryRunFlag(cmd) { - err := cmdutil.PrintObject(cmd, runObject.Object, out) - if err != nil { - return nil, err - } - if cmdutil.GetFlagString(cmd, "output") == "yaml" { - fmt.Fprintln(out, "---") - } - return runObject, nil + if err := o.PrintObj(runObject.Object); err != nil { + return nil, err + } + // separate yaml objects + if o.PrintFlags.OutputFormat != nil && *o.PrintFlags.OutputFormat == "yaml" { + fmt.Fprintln(o.Out, "---") } - cmdutil.PrintSuccess(false, out, runObject.Object, cmdutil.GetDryRunFlag(cmd), "created") return runObject, nil } -func createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command, generator kubectl.Generator, names []kubectl.GeneratorParam, params map[string]interface{}, overrides, namespace string) (*RunObject, error) { +func (o *RunOptions) createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command, generator kubectl.Generator, names []kubectl.GeneratorParam, params map[string]interface{}, overrides, namespace string) (*RunObject, error) { err := kubectl.ValidateParams(names, params) if err != nil { return nil, err @@ -581,63 +630,50 @@ func createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command, generator kube return nil, err } - mapper, typer := f.Object() - groupVersionKinds, _, err := typer.ObjectKinds(obj) + mapper, err := f.ToRESTMapper() + if err != nil { + return nil, err + } + // run has compiled knowledge of the thing is is creating + gvks, _, err := scheme.Scheme.ObjectKinds(obj) + if err != nil { + return nil, err + } + mapping, err := mapper.RESTMapping(gvks[0].GroupKind(), gvks[0].Version) if err != nil { return nil, err } - groupVersionKind := groupVersionKinds[0] if len(overrides) > 0 { - codec := runtime.NewCodec(cmdutil.InternalVersionJSONEncoder(), cmdutil.InternalVersionDecoder()) + codec := runtime.NewCodec(scheme.DefaultJSONEncoder(), scheme.Codecs.UniversalDecoder(scheme.Scheme.PrioritizedVersionsAllGroups()...)) obj, err = cmdutil.Merge(codec, obj, overrides) if err != nil { return nil, err } } - mapping, err := mapper.RESTMapping(groupVersionKind.GroupKind(), groupVersionKind.Version) - if err != nil { - return nil, err - } - client, err := f.ClientForMapping(mapping) - if err != nil { - return nil, err + if err := o.Recorder.Record(obj); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } - annotations, err := mapping.MetadataAccessor.Annotations(obj) - if err != nil { - return nil, err - } - if cmdutil.GetRecordFlag(cmd) || len(annotations[kubectl.ChangeCauseAnnotation]) > 0 { - if err := cmdutil.RecordChangeCause(obj, f.Command(cmd, false)); err != nil { + actualObj := obj + if !o.DryRun { + if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), obj, scheme.DefaultJSONEncoder()); err != nil { return nil, err } - } - if !cmdutil.GetDryRunFlag(cmd) { - resourceMapper := &resource.Mapper{ - ObjectTyper: typer, - RESTMapper: mapper, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - Decoder: cmdutil.InternalVersionDecoder(), - } - info, err := resourceMapper.InfoForObject(obj, nil) + client, err := f.ClientForMapping(mapping) if err != nil { return nil, err } - - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, cmdutil.InternalVersionJSONEncoder()); err != nil { - return nil, err - } - - obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) + actualObj, err = resource.NewHelper(client, mapping).Create(namespace, false, obj) if err != nil { return nil, err } } + actualObj = cmdutil.AsDefaultVersionedOrOriginal(actualObj, mapping) + return &RunObject{ - Object: obj, - Kind: groupVersionKind.Kind, + Object: actualObj, Mapping: mapping, }, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/run_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/run_test.go index 88d1dbbdc..3ffd79f1c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/run_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/run_test.go @@ -39,6 +39,7 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -169,10 +170,10 @@ func TestRunArgsFollowDashRules(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -188,12 +189,39 @@ func TestRunArgsFollowDashRules(t *testing.T) { }, nil }), } - tf.Namespace = "test" + tf.ClientConfigVal = &restclient.Config{} - cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) + + cmd := NewCmdRun(tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("image", "nginx") cmd.Flags().Set("generator", "run/v1") - err := RunRun(tf, os.Stdin, os.Stdout, os.Stderr, cmd, test.args, test.argsLenAtDash) + + printFlags := genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme) + printer, err := printFlags.ToPrinter() + if err != nil { + t.Errorf("unexpected error: %v", err) + return + } + + deleteFlags := NewDeleteFlags("to use to replace the resource.") + opts := &RunOptions{ + PrintFlags: printFlags, + DeleteOptions: deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard()), + + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), + + Image: "nginx", + Generator: "run/v1", + + PrintObj: func(obj runtime.Object) error { + return printer.PrintObj(obj, os.Stdout) + }, + Recorder: genericclioptions.NoopRecorder{}, + + ArgsLenAtDash: test.argsLenAtDash, + } + + err = opts.Run(tf, cmd, test.args) if test.expectError && err == nil { t.Errorf("unexpected non-error (%s)", test.name) } @@ -301,7 +329,7 @@ func TestGenerateService(t *testing.T) { tf := cmdtesting.NewTestFactory() defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.ClientConfigVal = defaultClientConfig() @@ -330,21 +358,42 @@ func TestGenerateService(t *testing.T) { } return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil default: - // Ensures no GET is performed when deleting by name t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) return nil, fmt.Errorf("unexpected request") } }), } + + printFlags := genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme) + printer, err := printFlags.ToPrinter() + if err != nil { + t.Errorf("unexpected error: %v", err) + return + } + + ioStreams, _, buff, _ := genericclioptions.NewTestIOStreams() + deleteFlags := NewDeleteFlags("to use to replace the resource.") + opts := &RunOptions{ + PrintFlags: printFlags, + DeleteOptions: deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard()), + + IOStreams: ioStreams, + + Port: test.port, + Recorder: genericclioptions.NoopRecorder{}, + + PrintObj: func(obj runtime.Object) error { + return printer.PrintObj(obj, buff) + }, + } + cmd := &cobra.Command{} cmd.Flags().Bool(cmdutil.ApplyAnnotationsFlag, false, "") cmd.Flags().Bool("record", false, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.") - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - addRunFlags(cmd) + addRunFlags(cmd, opts) if !test.expectPOST { - cmd.Flags().Set("dry-run", "true") + opts.DryRun = true } if len(test.port) > 0 { @@ -352,8 +401,7 @@ func TestGenerateService(t *testing.T) { test.params["port"] = test.port } - buff := &bytes.Buffer{} - _, err := generateService(tf, cmd, test.args, test.serviceGenerator, test.params, "namespace", buff) + _, err = opts.generateService(tf, cmd, test.serviceGenerator, test.params, "namespace") if test.expectErr { if err == nil { t.Error("unexpected non-error") @@ -456,7 +504,7 @@ func TestRunValidations(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() _, _, codec := cmdtesting.NewExternalScheme() @@ -464,17 +512,19 @@ func TestRunValidations(t *testing.T) { NegotiatedSerializer: scheme.Codecs, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalType("", "", ""))}, } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - inBuf := bytes.NewReader([]byte{}) - outBuf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdRun(tf, inBuf, outBuf, errBuf) + streams, _, _, bufErr := genericclioptions.NewTestIOStreams() + cmd := NewCmdRun(tf, streams) for flagName, flagValue := range test.flags { cmd.Flags().Set(flagName, flagValue) } - err := RunRun(tf, inBuf, outBuf, errBuf, cmd, test.args, cmd.ArgsLenAtDash()) + cmd.Run(cmd, test.args) + + var err error + if bufErr.Len() > 0 { + err = fmt.Errorf("%v", bufErr.String()) + } if err != nil && len(test.expectedErr) > 0 { if !strings.Contains(err.Error(), test.expectedErr) { t.Errorf("unexpected error: %v", err) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scale.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scale.go index c7d42f022..a883456dd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scale.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scale.go @@ -18,14 +18,23 @@ package cmd import ( "fmt" - "io" + "time" + "github.com/golang/glog" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + batchclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion" "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/cmd/scalejob" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -56,12 +65,48 @@ var ( kubectl scale --replicas=3 statefulset/web`)) ) +type ScaleOptions struct { + FilenameOptions resource.FilenameOptions + RecordFlags *genericclioptions.RecordFlags + PrintFlags *genericclioptions.PrintFlags + PrintObj printers.ResourcePrinterFunc + + Selector string + All bool + Replicas int + ResourceVersion string + CurrentReplicas int + Timeout time.Duration + + Recorder genericclioptions.Recorder + builder *resource.Builder + namespace string + enforceNamespace bool + args []string + shortOutput bool + clientSet internalclientset.Interface + scaler kubectl.Scaler + unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) + parent string + + genericclioptions.IOStreams +} + +func NewScaleOptions(ioStreams genericclioptions.IOStreams) *ScaleOptions { + return &ScaleOptions{ + PrintFlags: genericclioptions.NewPrintFlags("scaled"), + RecordFlags: genericclioptions.NewRecordFlags(), + CurrentReplicas: -1, + Recorder: genericclioptions.NoopRecorder{}, + IOStreams: ioStreams, + } +} + // NewCmdScale returns a cobra command with the appropriate configuration and flags to run scale -func NewCmdScale(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - options := &resource.FilenameOptions{} +func NewCmdScale(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewScaleOptions(ioStreams) - validArgs := []string{"deployment", "replicaset", "replicationcontroller", "job", "statefulset"} - argAliases := kubectl.ResourceAliases(validArgs) + validArgs := []string{"deployment", "replicaset", "replicationcontroller", "statefulset"} cmd := &cobra.Command{ Use: "scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)", @@ -70,58 +115,81 @@ func NewCmdScale(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { Long: scaleLong, Example: scaleExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" - err := RunScale(f, out, errOut, cmd, args, shortOutput, options) - cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate(cmd)) + cmdutil.CheckErr(o.RunScale()) }, - ValidArgs: validArgs, - ArgAliases: argAliases, - } - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().Bool("all", false, "Select all resources in the namespace of the specified resource types") - cmd.Flags().String("resource-version", "", i18n.T("Precondition for resource version. Requires that the current resource version match this value in order to scale.")) - cmd.Flags().Int("current-replicas", -1, "Precondition for current size. Requires that the current size of the resource match this value in order to scale.") - cmd.Flags().Int("replicas", -1, "The new desired number of replicas. Required.") - cmd.MarkFlagRequired("replicas") - cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a scale operation, zero means don't wait. Any other values should contain a corresponding time unit (e.g. 1s, 2m, 3h).") - cmdutil.AddOutputFlagsForMutation(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) + ValidArgs: validArgs, + } + + o.RecordFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) - usage := "identifying the resource to set a new size" - cmdutil.AddFilenameOptionFlags(cmd, options, usage) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&o.All, "all", o.All, "Select all resources in the namespace of the specified resource types") + cmd.Flags().StringVar(&o.ResourceVersion, "resource-version", o.ResourceVersion, i18n.T("Precondition for resource version. Requires that the current resource version match this value in order to scale.")) + cmd.Flags().IntVar(&o.CurrentReplicas, "current-replicas", o.CurrentReplicas, "Precondition for current size. Requires that the current size of the resource match this value in order to scale.") + cmd.Flags().IntVar(&o.Replicas, "replicas", o.Replicas, "The new desired number of replicas. Required.") + cmd.MarkFlagRequired("replicas") + cmd.Flags().DurationVar(&o.Timeout, "timeout", 0, "The length of time to wait before giving up on a scale operation, zero means don't wait. Any other values should contain a corresponding time unit (e.g. 1s, 2m, 3h).") + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to set a new size") return cmd } -// RunScale executes the scaling -func RunScale(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *resource.FilenameOptions) error { - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() +func (o *ScaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() if err != nil { return err } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObj = printer.PrintObj - count := cmdutil.GetFlagInt(cmd, "replicas") - if count < 0 { - return cmdutil.UsageErrorf(cmd, "The --replicas=COUNT flag is required, and COUNT must be greater than or equal to 0") + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + o.builder = f.NewBuilder() + o.args = args + o.shortOutput = cmdutil.GetFlagString(cmd, "output") == "name" + o.clientSet, err = f.ClientSet() + if err != nil { + return err + } + o.scaler, err = scaler(f) + if err != nil { + return err + } + o.unstructuredClientForMapping = f.UnstructuredClientForMapping + o.parent = cmd.Parent().Name() + + return nil +} + +func (o *ScaleOptions) Validate(cmd *cobra.Command) error { + if o.Replicas < 0 { + return fmt.Errorf("The --replicas=COUNT flag is required, and COUNT must be greater than or equal to 0") } - selector := cmdutil.GetFlagString(cmd, "selector") - all := cmdutil.GetFlagBool(cmd, "all") + return nil +} - r := f.NewBuilder(). +// RunScale executes the scaling +func (o *ScaleOptions) RunScale() error { + r := o.builder. Unstructured(). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options). - ResourceTypeOrNameArgs(all, args...). + NamespaceParam(o.namespace).DefaultNamespace(). + FilenameParam(o.enforceNamespace, &o.FilenameOptions). + ResourceTypeOrNameArgs(o.All, o.args...). Flatten(). - LabelSelectorParam(selector). + LabelSelectorParam(o.Selector). Do() - err = r.Err() - if resource.IsUsageError(err) { - return cmdutil.UsageErrorf(cmd, "%v", err) - } + err := r.Err() if err != nil { return err } @@ -134,11 +202,18 @@ func RunScale(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args return nil }) - resourceVersion := cmdutil.GetFlagString(cmd, "resource-version") - if len(resourceVersion) != 0 && len(infos) > 1 { + if len(o.ResourceVersion) != 0 && len(infos) > 1 { return fmt.Errorf("cannot use --resource-version with multiple resources") } + precondition := &kubectl.ScalePrecondition{Size: o.CurrentReplicas, ResourceVersion: o.ResourceVersion} + retry := kubectl.NewRetryParams(1*time.Second, 5*time.Minute) + + var waitForReplicas *kubectl.RetryParams + if o.Timeout != 0 { + waitForReplicas = kubectl.NewRetryParams(1*time.Second, timeout) + } + counter := 0 err = r.Visit(func(info *resource.Info, err error) error { if err != nil { @@ -146,46 +221,36 @@ func RunScale(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args } mapping := info.ResourceMapping() - if mapping.Resource == "jobs" { - fmt.Fprintf(errOut, "%s scale job is DEPRECATED and will be removed in a future version.\n", cmd.Parent().Name()) - } - - scaler, err := f.Scaler(mapping) - if err != nil { - return err - } - - currentSize := cmdutil.GetFlagInt(cmd, "current-replicas") - precondition := &kubectl.ScalePrecondition{Size: currentSize, ResourceVersion: resourceVersion} - retry := kubectl.NewRetryParams(kubectl.Interval, kubectl.Timeout) + if mapping.Resource.GroupResource() == (schema.GroupResource{Group: "batch", Resource: "jobs"}) { + // go down the legacy jobs path. This can be removed in 3.14 For now, contain it. + fmt.Fprintf(o.ErrOut, "%s scale job is DEPRECATED and will be removed in a future version.\n", o.parent) - var waitForReplicas *kubectl.RetryParams - if timeout := cmdutil.GetFlagDuration(cmd, "timeout"); timeout != 0 { - waitForReplicas = kubectl.NewRetryParams(kubectl.Interval, timeout) - } + if err := ScaleJob(info, o.clientSet.Batch(), uint(o.Replicas), precondition, retry, waitForReplicas); err != nil { + return err + } - if err := scaler.Scale(info.Namespace, info.Name, uint(count), precondition, retry, waitForReplicas); err != nil { - return err - } - if cmdutil.ShouldRecord(cmd, info) { - patchBytes, patchType, err := cmdutil.ChangeResourcePatch(info, f.Command(cmd, true)) - if err != nil { + } else { + if err := o.scaler.Scale(info.Namespace, info.Name, uint(o.Replicas), precondition, retry, waitForReplicas, mapping.Resource.GroupResource()); err != nil { return err } - mapping := info.ResourceMapping() - client, err := f.UnstructuredClientForMapping(mapping) + } + + // if the recorder makes a change, compute and create another patch + if mergePatch, err := o.Recorder.MakeRecordMergePatch(info.Object); err != nil { + glog.V(4).Infof("error recording current command: %v", err) + } else if len(mergePatch) > 0 { + client, err := o.unstructuredClientForMapping(mapping) if err != nil { return err } helper := resource.NewHelper(client, mapping) - _, err = helper.Patch(info.Namespace, info.Name, patchType, patchBytes) - if err != nil { - return err + if _, err := helper.Patch(info.Namespace, info.Name, types.MergePatchType, mergePatch); err != nil { + glog.V(4).Infof("error recording reason: %v", err) } } + counter++ - cmdutil.PrintSuccess(shortOutput, out, info.Object, false, "scaled") - return nil + return o.PrintObj(info.Object, o.Out) }) if err != nil { return err @@ -195,3 +260,32 @@ func RunScale(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args } return nil } + +func ScaleJob(info *resource.Info, jobsClient batchclient.JobsGetter, count uint, preconditions *kubectl.ScalePrecondition, retry, waitForReplicas *kubectl.RetryParams) error { + scaler := scalejob.JobPsuedoScaler{ + JobsClient: jobsClient, + } + var jobPreconditions *scalejob.ScalePrecondition + if preconditions != nil { + jobPreconditions = &scalejob.ScalePrecondition{Size: preconditions.Size, ResourceVersion: preconditions.ResourceVersion} + } + var jobRetry *scalejob.RetryParams + if retry != nil { + jobRetry = &scalejob.RetryParams{Interval: retry.Interval, Timeout: retry.Timeout} + } + var jobWaitForReplicas *scalejob.RetryParams + if waitForReplicas != nil { + jobWaitForReplicas = &scalejob.RetryParams{Interval: waitForReplicas.Interval, Timeout: waitForReplicas.Timeout} + } + + return scaler.Scale(info.Namespace, info.Name, count, jobPreconditions, jobRetry, jobWaitForReplicas) +} + +func scaler(f cmdutil.Factory) (kubectl.Scaler, error) { + scalesGetter, err := cmdutil.ScaleClientFn(f) + if err != nil { + return nil, err + } + + return kubectl.NewScaler(scalesGetter), nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/BUILD new file mode 100644 index 000000000..f95519c78 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/BUILD @@ -0,0 +1,47 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "scalejob.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/scalejob", + visibility = ["//visibility:public"], + deps = [ + "//pkg/apis/batch:go_default_library", + "//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["scalejob_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/apis/batch:go_default_library", + "//pkg/apis/core:go_default_library", + "//pkg/client/clientset_generated/internalclientset/fake:go_default_library", + "//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/client-go/testing:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/doc.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/doc.go new file mode 100644 index 000000000..589fa1a64 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2018 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 scalejob is deprecated This package contains deprecated functions used to "scale" jobs in a way inconsistent with normal scaling rules +package scalejob diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/scalejob.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/scalejob.go new file mode 100644 index 000000000..687c7b48a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/scalejob.go @@ -0,0 +1,162 @@ +/* +Copyright 2018 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 scalejob + +import ( + "fmt" + "strconv" + "time" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/pkg/apis/batch" + + batchclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion" +) + +// ScalePrecondition is a deprecated precondition +type ScalePrecondition struct { + Size int + ResourceVersion string +} + +// RetryParams is a deprecated retry struct +type RetryParams struct { + Interval, Timeout time.Duration +} + +// PreconditionError is a deprecated error +type PreconditionError struct { + Precondition string + ExpectedValue string + ActualValue string +} + +func (pe PreconditionError) Error() string { + return fmt.Sprintf("Expected %s to be %s, was %s", pe.Precondition, pe.ExpectedValue, pe.ActualValue) +} + +// ScaleCondition is a closure around Scale that facilitates retries via util.wait +func scaleCondition(r *JobPsuedoScaler, precondition *ScalePrecondition, namespace, name string, count uint, updatedResourceVersion *string) wait.ConditionFunc { + return func() (bool, error) { + rv, err := r.ScaleSimple(namespace, name, precondition, count) + if updatedResourceVersion != nil { + *updatedResourceVersion = rv + } + // Retry only on update conflicts. + if errors.IsConflict(err) { + return false, nil + } + if err != nil { + return false, err + } + return true, nil + } +} + +// JobPsuedoScaler is a deprecated scale-similar thing that doesn't obey scale semantics +type JobPsuedoScaler struct { + JobsClient batchclient.JobsGetter +} + +// ScaleSimple is responsible for updating job's parallelism. It returns the +// resourceVersion of the job if the update is successful. +func (scaler *JobPsuedoScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (string, error) { + job, err := scaler.JobsClient.Jobs(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + return "", err + } + if preconditions != nil { + if err := validateJob(job, preconditions); err != nil { + return "", err + } + } + parallelism := int32(newSize) + job.Spec.Parallelism = ¶llelism + updatedJob, err := scaler.JobsClient.Jobs(namespace).Update(job) + if err != nil { + return "", err + } + return updatedJob.ObjectMeta.ResourceVersion, nil +} + +// Scale updates a Job to a new size, with optional precondition check (if preconditions is not nil), +// optional retries (if retry is not nil), and then optionally waits for parallelism to reach desired +// number, which can be less than requested based on job's current progress. +func (scaler *JobPsuedoScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error { + if preconditions == nil { + preconditions = &ScalePrecondition{-1, ""} + } + if retry == nil { + // Make it try only once, immediately + retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond} + } + cond := scaleCondition(scaler, preconditions, namespace, name, newSize, nil) + if err := wait.PollImmediate(retry.Interval, retry.Timeout, cond); err != nil { + return err + } + if waitForReplicas != nil { + job, err := scaler.JobsClient.Jobs(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + return err + } + err = wait.PollImmediate(waitForReplicas.Interval, waitForReplicas.Timeout, jobHasDesiredParallelism(scaler.JobsClient, job)) + if err == wait.ErrWaitTimeout { + return fmt.Errorf("timed out waiting for %q to be synced", name) + } + return err + } + return nil +} + +// JobHasDesiredParallelism returns a condition that will be true if the desired parallelism count +// for a job equals the current active counts or is less by an appropriate successful/unsuccessful count. +func jobHasDesiredParallelism(jobClient batchclient.JobsGetter, job *batch.Job) wait.ConditionFunc { + return func() (bool, error) { + job, err := jobClient.Jobs(job.Namespace).Get(job.Name, metav1.GetOptions{}) + if err != nil { + return false, err + } + + // desired parallelism can be either the exact number, in which case return immediately + if job.Status.Active == *job.Spec.Parallelism { + return true, nil + } + if job.Spec.Completions == nil { + // A job without specified completions needs to wait for Active to reach Parallelism. + return false, nil + } + + // otherwise count successful + progress := *job.Spec.Completions - job.Status.Active - job.Status.Succeeded + return progress <= 0, nil + } +} + +func validateJob(job *batch.Job, precondition *ScalePrecondition) error { + if precondition.Size != -1 && job.Spec.Parallelism == nil { + return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), "nil"} + } + if precondition.Size != -1 && int(*job.Spec.Parallelism) != precondition.Size { + return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), strconv.Itoa(int(*job.Spec.Parallelism))} + } + if len(precondition.ResourceVersion) != 0 && job.ResourceVersion != precondition.ResourceVersion { + return PreconditionError{"resource version", precondition.ResourceVersion, job.ResourceVersion} + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/scalejob_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/scalejob_test.go new file mode 100644 index 000000000..d8a22f88e --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/scalejob/scalejob_test.go @@ -0,0 +1,292 @@ +/* +Copyright 2018 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 scalejob + +import ( + "errors" + "testing" + + kerrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + testcore "k8s.io/client-go/testing" + "k8s.io/kubernetes/pkg/apis/batch" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" + batchclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion" +) + +type errorJobs struct { + batchclient.JobInterface + conflict bool + invalid bool +} + +func (c *errorJobs) Update(job *batch.Job) (*batch.Job, error) { + switch { + case c.invalid: + return nil, kerrors.NewInvalid(api.Kind(job.Kind), job.Name, nil) + case c.conflict: + return nil, kerrors.NewConflict(api.Resource(job.Kind), job.Name, nil) + } + return nil, errors.New("Job update failure") +} + +func (c *errorJobs) Get(name string, options metav1.GetOptions) (*batch.Job, error) { + zero := int32(0) + return &batch.Job{ + Spec: batch.JobSpec{ + Parallelism: &zero, + }, + }, nil +} + +type errorJobClient struct { + batchclient.JobsGetter + conflict bool + invalid bool +} + +func (c *errorJobClient) Jobs(namespace string) batchclient.JobInterface { + return &errorJobs{ + JobInterface: c.JobsGetter.Jobs(namespace), + conflict: c.conflict, + invalid: c.invalid, + } +} + +func TestJobScaleRetry(t *testing.T) { + fake := &errorJobClient{JobsGetter: fake.NewSimpleClientset().Batch(), conflict: true} + scaler := &JobPsuedoScaler{JobsClient: fake} + preconditions := ScalePrecondition{-1, ""} + count := uint(3) + name := "foo" + namespace := "default" + + scaleFunc := scaleCondition(scaler, &preconditions, namespace, name, count, nil) + pass, err := scaleFunc() + if pass != false { + t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) + } + if err != nil { + t.Errorf("Did not expect an error on update failure, got %v", err) + } + preconditions = ScalePrecondition{3, ""} + scaleFunc = scaleCondition(scaler, &preconditions, namespace, name, count, nil) + pass, err = scaleFunc() + if err == nil { + t.Error("Expected error on precondition failure") + } +} + +func job() *batch.Job { + return &batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: metav1.NamespaceDefault, + Name: "foo", + }, + } +} + +func TestJobScale(t *testing.T) { + fakeClientset := fake.NewSimpleClientset(job()) + scaler := &JobPsuedoScaler{JobsClient: fakeClientset.Batch()} + preconditions := ScalePrecondition{-1, ""} + count := uint(3) + name := "foo" + scaler.Scale("default", name, count, &preconditions, nil, nil) + + actions := fakeClientset.Actions() + if len(actions) != 2 { + t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions) + } + if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != batch.Resource("jobs") || action.GetName() != name { + t.Errorf("unexpected action: %v, expected get-job %s", actions[0], name) + } + if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != batch.Resource("jobs") || *action.GetObject().(*batch.Job).Spec.Parallelism != int32(count) { + t.Errorf("unexpected action %v, expected update-job with parallelism = %d", actions[1], count) + } +} + +func TestJobScaleInvalid(t *testing.T) { + fake := &errorJobClient{JobsGetter: fake.NewSimpleClientset().Batch(), invalid: true} + scaler := &JobPsuedoScaler{JobsClient: fake} + preconditions := ScalePrecondition{-1, ""} + count := uint(3) + name := "foo" + namespace := "default" + + scaleFunc := scaleCondition(scaler, &preconditions, namespace, name, count, nil) + pass, err := scaleFunc() + if pass { + t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) + } + if err == nil { + t.Errorf("Expected error on invalid update failure, got %v", err) + } +} + +func TestJobScaleFailsPreconditions(t *testing.T) { + ten := int32(10) + fake := fake.NewSimpleClientset(&batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: metav1.NamespaceDefault, + Name: "foo", + }, + Spec: batch.JobSpec{ + Parallelism: &ten, + }, + }) + scaler := &JobPsuedoScaler{JobsClient: fake.Batch()} + preconditions := ScalePrecondition{2, ""} + count := uint(3) + name := "foo" + scaler.Scale("default", name, count, &preconditions, nil, nil) + + actions := fake.Actions() + if len(actions) != 1 { + t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions) + } + if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != batch.Resource("jobs") || action.GetName() != name { + t.Errorf("unexpected action: %v, expected get-job %s", actions[0], name) + } +} + +func TestValidateJob(t *testing.T) { + zero, ten, twenty := int32(0), int32(10), int32(20) + tests := []struct { + preconditions ScalePrecondition + job batch.Job + expectError bool + test string + }{ + { + preconditions: ScalePrecondition{-1, ""}, + expectError: false, + test: "defaults", + }, + { + preconditions: ScalePrecondition{-1, ""}, + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "foo", + }, + Spec: batch.JobSpec{ + Parallelism: &ten, + }, + }, + expectError: false, + test: "defaults 2", + }, + { + preconditions: ScalePrecondition{0, ""}, + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "foo", + }, + Spec: batch.JobSpec{ + Parallelism: &zero, + }, + }, + expectError: false, + test: "size matches", + }, + { + preconditions: ScalePrecondition{-1, "foo"}, + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "foo", + }, + Spec: batch.JobSpec{ + Parallelism: &ten, + }, + }, + expectError: false, + test: "resource version matches", + }, + { + preconditions: ScalePrecondition{10, "foo"}, + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "foo", + }, + Spec: batch.JobSpec{ + Parallelism: &ten, + }, + }, + expectError: false, + test: "both match", + }, + { + preconditions: ScalePrecondition{10, "foo"}, + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "foo", + }, + Spec: batch.JobSpec{ + Parallelism: &twenty, + }, + }, + expectError: true, + test: "size different", + }, + { + preconditions: ScalePrecondition{10, "foo"}, + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "foo", + }, + }, + expectError: true, + test: "parallelism nil", + }, + { + preconditions: ScalePrecondition{10, "foo"}, + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "bar", + }, + Spec: batch.JobSpec{ + Parallelism: &ten, + }, + }, + expectError: true, + test: "version different", + }, + { + preconditions: ScalePrecondition{10, "foo"}, + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "bar", + }, + Spec: batch.JobSpec{ + Parallelism: &twenty, + }, + }, + expectError: true, + test: "both different", + }, + } + for _, test := range tests { + err := validateJob(&test.job, &test.preconditions) + if err != nil && !test.expectError { + t.Errorf("unexpected error: %v (%s)", err, test.test) + } + if err == nil && test.expectError { + t.Errorf("expected an error: %v (%s)", err, test.test) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/BUILD index e3af3fd55..ba61c44cb 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/BUILD @@ -21,13 +21,19 @@ go_library( deps = [ "//pkg/apis/rbac:go_default_library", "//pkg/kubectl:go_default_library", + "//pkg/kubectl/cmd/set/env:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/kubectl/cmd/util/env:go_default_library", - "//pkg/kubectl/resource:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//pkg/kubectl/polymorphichelpers:go_default_library", + "//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -53,18 +59,17 @@ go_test( "set_test.go", ], data = [ - "//examples:config", "//test/e2e/testing-manifests:all-srcs", "//test/fixtures", ], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", - "//pkg/apis/rbac:go_default_library", "//pkg/kubectl/cmd/testing:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/kubectl/resource:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", @@ -74,9 +79,11 @@ go_test( "//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest/fake:go_default_library", ], @@ -90,7 +97,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/kubectl/cmd/set/env:all-srcs", + ], tags = ["automanaged"], visibility = [ "//build/visible_to:pkg_kubectl_cmd_set_CONSUMERS", diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/BUILD new file mode 100644 index 000000000..97fb91a20 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/BUILD @@ -0,0 +1,41 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "env_parse.go", + "env_resolve.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/set/env", + visibility = ["//visibility:public"], + deps = [ + "//pkg/api/v1/resource:go_default_library", + "//pkg/fieldpath:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["env_parse_test.go"], + embed = [":go_default_library"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/doc.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/doc.go new file mode 100644 index 000000000..25e4c04a7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/doc.go @@ -0,0 +1,18 @@ +/* +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 env provides functions to incorporate environment variables into set env. +package env diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_parse.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/env_parse.go similarity index 91% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_parse.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/env_parse.go index 1d1686af6..5e2e52908 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_parse.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/env_parse.go @@ -20,7 +20,6 @@ import ( "bufio" "fmt" "io" - "os" "regexp" "strings" @@ -28,24 +27,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" ) -// Env returns an environment variable if not nil, or a default value. -func Env(key string, defaultValue string) string { - val := os.Getenv(key) - if len(val) == 0 { - return defaultValue - } - return val -} - -// GetEnv returns an environment value if not nil, and an ok boolean. -func GetEnv(key string) (string, bool) { - val := os.Getenv(key) - if len(val) == 0 { - return "", false - } - return val, true -} - var argumentEnvironment = regexp.MustCompile("(?ms)^(.+)\\=(.*)$") var validArgumentEnvironment = regexp.MustCompile("(?ms)^(\\w+)\\=(.*)$") diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_parse_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/env_parse_test.go similarity index 76% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_parse_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/env_parse_test.go index 32be9833c..5cff84a18 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_parse_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/env_parse_test.go @@ -19,36 +19,9 @@ package env import ( "fmt" "io" - "os" "strings" ) -func ExampleEnv_defaultValue() { - fmt.Println(Env("TESTENVVAR", "default")) - // Output: default -} - -func ExampleEnv_variableExists() { - os.Setenv("TESTENVVAR", "test value") - defer os.Unsetenv("TESTENVVAR") - fmt.Println(Env("TESTENVVAR", "default")) - // Output: test value -} - -func ExampleGetEnv_variableExists() { - os.Setenv("THISVAREXISTS", "value") - defer os.Unsetenv("THISVAREXISTS") - fmt.Println(GetEnv("THISVAREXISTS")) - // Output: - // value true -} - -func ExampleGetEnv_variableDoesNotExist() { - fmt.Println(GetEnv("THISVARDOESNOTEXIST")) - // Output: - // false -} - func ExampleIsEnvironmentArgument_true() { test := "returns=true" fmt.Println(IsEnvironmentArgument(test)) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_resolve.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/env_resolve.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_resolve.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/env/env_resolve.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/helper.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/helper.go index 5d6bed200..42b1bb8a9 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/helper.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/helper.go @@ -27,7 +27,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/strategicpatch" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" ) // selectContainers allows one or more containers to be matched against a string or wildcard @@ -118,16 +118,16 @@ type Patch struct { Patch []byte } -// patchFn is a function type that accepts an info object and returns a byte slice. -// Implementations of patchFn should update the object and return it encoded. -type patchFn func(*resource.Info) ([]byte, error) +// PatchFn is a function type that accepts an info object and returns a byte slice. +// Implementations of PatchFn should update the object and return it encoded. +type PatchFn func(runtime.Object) ([]byte, error) // CalculatePatch calls the mutation function on the provided info object, and generates a strategic merge patch for // the changes in the object. Encoder must be able to encode the info into the appropriate destination type. // This function returns whether the mutation function made any change in the original object. -func CalculatePatch(patch *Patch, encoder runtime.Encoder, mutateFn patchFn) bool { +func CalculatePatch(patch *Patch, encoder runtime.Encoder, mutateFn PatchFn) bool { patch.Before, patch.Err = runtime.Encode(encoder, patch.Info.Object) - patch.After, patch.Err = mutateFn(patch.Info) + patch.After, patch.Err = mutateFn(patch.Info.Object) if patch.Err != nil { return true } @@ -141,7 +141,7 @@ func CalculatePatch(patch *Patch, encoder runtime.Encoder, mutateFn patchFn) boo // CalculatePatches calculates patches on each provided info object. If the provided mutateFn // makes no change in an object, the object is not included in the final list of patches. -func CalculatePatches(infos []*resource.Info, encoder runtime.Encoder, mutateFn patchFn) []*Patch { +func CalculatePatches(infos []*resource.Info, encoder runtime.Encoder, mutateFn PatchFn) []*Patch { var patches []*Patch for _, info := range infos { patch := &Patch{Info: info} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set.go index dfc69c104..f0864fc33 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set.go @@ -17,11 +17,10 @@ limitations under the License. package set import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -32,22 +31,22 @@ var ( These commands help you make changes to existing application resources.`) ) -func NewCmdSet(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command { +func NewCmdSet(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "set SUBCOMMAND", DisableFlagsInUseLine: true, Short: i18n.T("Set specific features on objects"), Long: set_long, - Run: cmdutil.DefaultSubCommandRun(err), + Run: cmdutil.DefaultSubCommandRun(streams.ErrOut), } // add subcommands - cmd.AddCommand(NewCmdImage(f, out, err)) - cmd.AddCommand(NewCmdResources(f, out, err)) - cmd.AddCommand(NewCmdSelector(f, out)) - cmd.AddCommand(NewCmdSubject(f, out, err)) - cmd.AddCommand(NewCmdServiceAccount(f, out, err)) - cmd.AddCommand(NewCmdEnv(f, in, out, err)) + cmd.AddCommand(NewCmdImage(f, streams)) + cmd.AddCommand(NewCmdResources(f, streams)) + cmd.AddCommand(NewCmdSelector(f, streams)) + cmd.AddCommand(NewCmdSubject(f, streams)) + cmd.AddCommand(NewCmdServiceAccount(f, streams)) + cmd.AddCommand(NewCmdEnv(f, streams)) return cmd } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_env.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_env.go index 6cbaf21f0..f1e6c0cc6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_env.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_env.go @@ -19,22 +19,26 @@ package set import ( "errors" "fmt" - "io" "regexp" "sort" "strings" "github.com/spf13/cobra" + "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/client-go/kubernetes" + envutil "k8s.io/kubernetes/pkg/kubectl/cmd/set/env" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - envutil "k8s.io/kubernetes/pkg/kubectl/cmd/util/env" - "k8s.io/kubernetes/pkg/kubectl/resource" - - utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" ) var ( @@ -58,7 +62,7 @@ var ( ` + envResources) envExample = templates.Examples(` - # Update deployment 'registry' with a new environment variable + # Update deployment 'registry' with a new environment variable kubectl set env deployment/registry STORAGE_DIR=/local # List the environment variables defined on a deployments 'sample-build' @@ -79,6 +83,9 @@ var ( # Import environment from a config map with a prefix kubectl set env --from=configmap/myconfigmap --prefix=MYSQL_ deployment/myapp + # Import specific keys from a config map + kubectl set env --keys=my-example-key --from=configmap/myconfigmap deployment/myapp + # Remove the environment variable ENV from container 'c1' in all deployment configs kubectl set env deployments --all --containers="c1" ENV- @@ -91,45 +98,52 @@ var ( ) type EnvOptions struct { - Out io.Writer - Err io.Writer - In io.Reader - + PrintFlags *genericclioptions.PrintFlags resource.FilenameOptions - EnvParams []string - EnvArgs []string - Resources []string - - All bool - Resolve bool - List bool - ShortOutput bool - Local bool - Overwrite bool - DryRun bool - - ResourceVersion string + + EnvParams []string + All bool + Resolve bool + List bool + Local bool + Overwrite bool ContainerSelector string Selector string - Output string From string Prefix string + Keys []string - Builder *resource.Builder - Infos []*resource.Info + PrintObj printers.ResourcePrinterFunc - Cmd *cobra.Command + envArgs []string + resources []string + output string + dryRun bool + builder func() *resource.Builder + updatePodSpecForObject polymorphichelpers.UpdatePodSpecForObjectFunc + namespace string + enforceNamespace bool + clientset *kubernetes.Clientset - UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) + genericclioptions.IOStreams } -// NewCmdEnv implements the OpenShift cli env command -func NewCmdEnv(f cmdutil.Factory, in io.Reader, out, errout io.Writer) *cobra.Command { - options := &EnvOptions{ - Out: out, - Err: errout, - In: in, +// NewEnvOptions returns an EnvOptions indicating all containers in the selected +// pod templates are selected by default and allowing environment to be overwritten +func NewEnvOptions(streams genericclioptions.IOStreams) *EnvOptions { + return &EnvOptions{ + PrintFlags: genericclioptions.NewPrintFlags("env updated").WithTypeSetter(scheme.Scheme), + + ContainerSelector: "*", + Overwrite: true, + + IOStreams: streams, } +} + +// NewCmdEnv implements the OpenShift cli env command +func NewCmdEnv(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewEnvOptions(streams) cmd := &cobra.Command{ Use: "env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N", DisableFlagsInUseLine: true, @@ -137,26 +151,28 @@ func NewCmdEnv(f cmdutil.Factory, in io.Reader, out, errout io.Writer) *cobra.Co Long: envLong, Example: fmt.Sprintf(envExample), Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.RunEnv(f)) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunEnv()) }, } usage := "the resource to update the env" - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) - cmd.Flags().StringVarP(&options.ContainerSelector, "containers", "c", "*", "The names of containers in the selected pod templates to change - may use wildcards") - cmd.Flags().StringP("from", "", "", "The name of a resource from which to inject environment variables") - cmd.Flags().StringP("prefix", "", "", "Prefix to append to variable names") - cmd.Flags().StringArrayVarP(&options.EnvParams, "env", "e", options.EnvParams, "Specify a key-value pair for an environment variable to set into each container.") - cmd.Flags().BoolVar(&options.List, "list", options.List, "If true, display the environment and any changes in the standard format. this flag will removed when we have kubectl view env.") - cmd.Flags().BoolVar(&options.Resolve, "resolve", options.Resolve, "If true, show secret or configmap references when listing variables") - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on") - cmd.Flags().BoolVar(&options.Local, "local", options.Local, "If true, set env will NOT contact api-server but run locally.") - cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all resources in the namespace of the specified resource types") - cmd.Flags().BoolVar(&options.Overwrite, "overwrite", true, "If true, allow environment to be overwritten, otherwise reject updates that overwrite existing environment.") + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.ContainerSelector, "containers", "c", o.ContainerSelector, "The names of containers in the selected pod templates to change - may use wildcards") + cmd.Flags().StringVarP(&o.From, "from", "", "", "The name of a resource from which to inject environment variables") + cmd.Flags().StringVarP(&o.Prefix, "prefix", "", "", "Prefix to append to variable names") + cmd.Flags().StringArrayVarP(&o.EnvParams, "env", "e", o.EnvParams, "Specify a key-value pair for an environment variable to set into each container.") + cmd.Flags().StringSliceVarP(&o.Keys, "keys", "", o.Keys, "Comma-separated list of keys to import from specified resource") + cmd.Flags().BoolVar(&o.List, "list", o.List, "If true, display the environment and any changes in the standard format. this flag will removed when we have kubectl view env.") + cmd.Flags().BoolVar(&o.Resolve, "resolve", o.Resolve, "If true, show secret or configmap references when listing variables") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set env will NOT contact api-server but run locally.") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all resources in the namespace of the specified resource types") + cmd.Flags().BoolVar(&o.Overwrite, "overwrite", o.Overwrite, "If true, allow environment to be overwritten, otherwise reject updates that overwrite existing environment.") + + o.PrintFlags.AddFlags(cmd) cmdutil.AddDryRunFlag(cmd) - cmdutil.AddPrinterFlags(cmd) - return cmd } @@ -173,71 +189,86 @@ func keyToEnvName(key string) string { return strings.ToUpper(validEnvNameRegexp.ReplaceAllString(key, "_")) } +func contains(key string, keyList []string) bool { + if len(keyList) == 0 { + return true + } + + for _, k := range keyList { + if k == key { + return true + } + } + return false +} + func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { if o.All && len(o.Selector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") } - resources, envArgs, ok := envutil.SplitEnvironmentFromResources(args) + ok := false + o.resources, o.envArgs, ok = envutil.SplitEnvironmentFromResources(args) if !ok { - return cmdutil.UsageErrorf(o.Cmd, "all resources must be specified before environment changes: %s", strings.Join(args, " ")) + return fmt.Errorf("all resources must be specified before environment changes: %s", strings.Join(args, " ")) } - if len(o.Filenames) == 0 && len(resources) < 1 { - return cmdutil.UsageErrorf(cmd, "one or more resources must be specified as or /") + + o.updatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn + o.output = cmdutil.GetFlagString(cmd, "output") + o.dryRun = cmdutil.GetDryRunFlag(cmd) + + if o.dryRun { + // TODO(juanvallejo): This can be cleaned up even further by creating + // a PrintFlags struct that binds the --dry-run flag, and whose + // ToPrinter method returns a printer that understands how to print + // this success message. + o.PrintFlags.Complete("%s (dry run)") } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObj = printer.PrintObj - o.UpdatePodSpecForObject = f.UpdatePodSpecForObject - o.ContainerSelector = cmdutil.GetFlagString(cmd, "containers") - o.List = cmdutil.GetFlagBool(cmd, "list") - o.Resolve = cmdutil.GetFlagBool(cmd, "resolve") - o.Selector = cmdutil.GetFlagString(cmd, "selector") - o.All = cmdutil.GetFlagBool(cmd, "all") - o.Overwrite = cmdutil.GetFlagBool(cmd, "overwrite") - o.Output = cmdutil.GetFlagString(cmd, "output") - o.From = cmdutil.GetFlagString(cmd, "from") - o.Prefix = cmdutil.GetFlagString(cmd, "prefix") - o.DryRun = cmdutil.GetDryRunFlag(cmd) - - o.EnvArgs = envArgs - o.Resources = resources - o.Cmd = cmd - - o.ShortOutput = cmdutil.GetFlagString(cmd, "output") == "name" - - if o.List && len(o.Output) > 0 { - return cmdutil.UsageErrorf(o.Cmd, "--list and --output may not be specified together") + o.clientset, err = f.KubernetesClientSet() + if err != nil { + return err } + o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + o.builder = f.NewBuilder return nil } -// RunEnv contains all the necessary functionality for the OpenShift cli env command -func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { - var kubeClient *kubernetes.Clientset - if o.List { - client, err := f.KubernetesClientSet() - if err != nil { - return err - } - kubeClient = client +func (o *EnvOptions) Validate() error { + if len(o.Filenames) == 0 && len(o.resources) < 1 { + return fmt.Errorf("one or more resources must be specified as or /") } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err + if o.List && len(o.output) > 0 { + return fmt.Errorf("--list and --output may not be specified together") } + if len(o.Keys) > 0 && len(o.From) == 0 { + return fmt.Errorf("when specifying --keys, a configmap or secret must be provided with --from") + } + return nil +} - env, remove, err := envutil.ParseEnv(append(o.EnvParams, o.EnvArgs...), o.In) +// RunEnv contains all the necessary functionality for the OpenShift cli env command +func (o *EnvOptions) RunEnv() error { + env, remove, err := envutil.ParseEnv(append(o.EnvParams, o.envArgs...), o.In) if err != nil { return err } if len(o.From) != 0 { - b := f.NewBuilder(). - Internal(). + b := o.builder(). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). LocalParam(o.Local). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &o.FilenameOptions). + NamespaceParam(o.namespace).DefaultNamespace(). + FilenameParam(o.enforceNamespace, &o.FilenameOptions). Flatten() if !o.Local { @@ -253,40 +284,40 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { } for _, info := range infos { - versionedObject, err := info.Mapping.ConvertToVersion(info.Object, info.Mapping.GroupVersionKind.GroupVersion()) - if err != nil { - return err - } - switch from := versionedObject.(type) { + switch from := info.Object.(type) { case *v1.Secret: for key := range from.Data { - envVar := v1.EnvVar{ - Name: keyToEnvName(key), - ValueFrom: &v1.EnvVarSource{ - SecretKeyRef: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: from.Name, + if contains(key, o.Keys) { + envVar := v1.EnvVar{ + Name: keyToEnvName(key), + ValueFrom: &v1.EnvVarSource{ + SecretKeyRef: &v1.SecretKeySelector{ + LocalObjectReference: v1.LocalObjectReference{ + Name: from.Name, + }, + Key: key, }, - Key: key, }, - }, + } + env = append(env, envVar) } - env = append(env, envVar) } case *v1.ConfigMap: for key := range from.Data { - envVar := v1.EnvVar{ - Name: keyToEnvName(key), - ValueFrom: &v1.EnvVarSource{ - ConfigMapKeyRef: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: from.Name, + if contains(key, o.Keys) { + envVar := v1.EnvVar{ + Name: keyToEnvName(key), + ValueFrom: &v1.EnvVarSource{ + ConfigMapKeyRef: &v1.ConfigMapKeySelector{ + LocalObjectReference: v1.LocalObjectReference{ + Name: from.Name, + }, + Key: key, }, - Key: key, }, - }, + } + env = append(env, envVar) } - env = append(env, envVar) } default: return fmt.Errorf("unsupported resource specified in --from") @@ -300,31 +331,71 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { } } - b := f.NewBuilder(). - Internal(). + b := o.builder(). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). LocalParam(o.Local). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &o.FilenameOptions). + NamespaceParam(o.namespace).DefaultNamespace(). + FilenameParam(o.enforceNamespace, &o.FilenameOptions). Flatten() if !o.Local { b.LabelSelectorParam(o.Selector). - ResourceTypeOrNameArgs(o.All, o.Resources...). + ResourceTypeOrNameArgs(o.All, o.resources...). Latest() } - o.Infos, err = b.Do().Infos() + infos, err := b.Do().Infos() if err != nil { return err } - patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { - info.Object = info.AsVersioned() - _, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error { + patches := CalculatePatches(infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) { + _, err := o.updatePodSpecForObject(obj, func(spec *v1.PodSpec) error { resolutionErrorsEncountered := false containers, _ := selectContainers(spec.Containers, o.ContainerSelector) + objName, err := meta.NewAccessor().Name(obj) + if err != nil { + return err + } + + gvks, _, err := scheme.Scheme.ObjectKinds(obj) + if err != nil { + return err + } + objKind := obj.GetObjectKind().GroupVersionKind().Kind + if len(objKind) == 0 { + for _, gvk := range gvks { + if len(gvk.Kind) == 0 { + continue + } + if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal { + continue + } + + objKind = gvk.Kind + break + } + } + if len(containers) == 0 { - fmt.Fprintf(o.Err, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, o.ContainerSelector) + if gvks, _, err := scheme.Scheme.ObjectKinds(obj); err == nil { + objKind := obj.GetObjectKind().GroupVersionKind().Kind + if len(objKind) == 0 { + for _, gvk := range gvks { + if len(gvk.Kind) == 0 { + continue + } + if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal { + continue + } + + objKind = gvk.Kind + break + } + } + + fmt.Fprintf(o.ErrOut, "warning: %s/%s does not have any containers matching %q\n", objKind, objName, o.ContainerSelector) + } return nil } for _, c := range containers { @@ -339,7 +410,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { resolveErrors := map[string][]string{} store := envutil.NewResourceStore() - fmt.Fprintf(o.Out, "# %s %s, container %s\n", info.Mapping.Resource, info.Name, c.Name) + fmt.Fprintf(o.Out, "# %s %s, container %s\n", objKind, objName, c.Name) for _, env := range c.Env { // Print the simple value if env.ValueFrom == nil { @@ -353,7 +424,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { continue } - value, err := envutil.GetEnvVarRefValue(kubeClient, cmdNamespace, store, env.ValueFrom, info.Object, c) + value, err := envutil.GetEnvVarRefValue(o.clientset, o.namespace, store, env.ValueFrom, obj, c) // Print the resolved value if err == nil { fmt.Fprintf(o.Out, "%s=%s\n", env.Name, value) @@ -375,7 +446,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { } sort.Strings(errs) for _, err := range errs { - fmt.Fprintln(o.Err, err) + fmt.Fprintln(o.ErrOut, err) } } } @@ -386,7 +457,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { }) if err == nil { - return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), info.Object) + return runtime.Encode(scheme.DefaultJSONEncoder(), obj) } return nil, err }) @@ -409,34 +480,28 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { continue } - if o.Local || o.DryRun { - if err := cmdutil.PrintObject(o.Cmd, patch.Info.AsVersioned(), o.Out); err != nil { - return err + if o.Local || o.dryRun { + if err := o.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) } continue } - obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { allErrs = append(allErrs, fmt.Errorf("failed to patch env update to pod template: %v\n", err)) continue } - info.Refresh(obj, true) // make sure arguments to set or replace environment variables are set // before returning a successful message - if len(env) == 0 && len(o.EnvArgs) == 0 { + if len(env) == 0 && len(o.envArgs) == 0 { return fmt.Errorf("at least one environment variable must be provided") } - if len(o.Output) > 0 { - if err := cmdutil.PrintObject(o.Cmd, info.AsVersioned(), o.Out); err != nil { - return err - } - continue + if err := o.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) } - - cmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, false, "env updated") } return utilerrors.NewAggregate(allErrs) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_env_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_env_test.go index 22c429a27..f3d7c3338 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_env_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_env_test.go @@ -17,11 +17,9 @@ limitations under the License. package set import ( - "bytes" "fmt" "io/ioutil" "net/http" - "os" "path" "strings" "testing" @@ -36,47 +34,47 @@ import ( 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" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestSetEnvLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} + outputFormat := "name" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdEnv(tf, os.Stdin, buf, buf) - cmd.SetOutput(buf) - cmd.Flags().Set("output", "name") - cmd.Flags().Set("local", "true") - - opts := EnvOptions{FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, - Out: buf, - Local: true} - err := opts.Complete(tf, cmd, []string{"env=prod"}) - if err == nil { - err = opts.RunEnv(tf) + streams, _, buf, bufErr := genericclioptions.NewTestIOStreams() + opts := NewEnvOptions(streams) + opts.PrintFlags = genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme) + opts.FilenameOptions = resource.FilenameOptions{ + Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}, } - if err != nil { - t.Fatalf("unexpected error: %v", err) + opts.Local = true + + err := opts.Complete(tf, NewCmdEnv(tf, streams), []string{"env=prod"}) + assert.NoError(t, err) + err = opts.Validate() + assert.NoError(t, err) + err = opts.RunEnv() + assert.NoError(t, err) + if bufErr.Len() > 0 { + t.Errorf("unexpected error: %s", string(bufErr.String())) } if !strings.Contains(buf.String(), "replicationcontroller/cassandra") { t.Errorf("did not set env: %s", buf.String()) @@ -84,40 +82,37 @@ func TestSetEnvLocal(t *testing.T) { } func TestSetMultiResourcesEnvLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - ns := legacyscheme.Codecs - tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdEnv(tf, os.Stdin, buf, buf) - cmd.SetOutput(buf) - cmd.Flags().Set("output", "name") - cmd.Flags().Set("local", "true") - - opts := EnvOptions{FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, - Out: buf, - Local: true} - err := opts.Complete(tf, cmd, []string{"env=prod"}) - if err == nil { - err = opts.RunEnv(tf) - } - if err != nil { - t.Fatalf("unexpected error: %v", err) + outputFormat := "name" + streams, _, buf, bufErr := genericclioptions.NewTestIOStreams() + opts := NewEnvOptions(streams) + opts.PrintFlags = genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme) + opts.FilenameOptions = resource.FilenameOptions{ + Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}, } + opts.Local = true + err := opts.Complete(tf, NewCmdEnv(tf, streams), []string{"env=prod"}) + assert.NoError(t, err) + err = opts.Validate() + assert.NoError(t, err) + err = opts.RunEnv() + assert.NoError(t, err) + if bufErr.Len() > 0 { + t.Errorf("unexpected error: %s", string(bufErr.String())) + } expectedOut := "replicationcontroller/first-rc\nreplicationcontroller/second-rc\n" if buf.String() != expectedOut { t.Errorf("expected out:\n%s\nbut got:\n%s", expectedOut, buf.String()) @@ -450,20 +445,18 @@ func TestSetEnvRemote(t *testing.T) { t.Run(input.name, func(t *testing.T) { groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") + tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} defer tf.Cleanup() - codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) - ns := legacyscheme.Codecs - tf.Namespace = "test" tf.Client = &fake.RESTClient{ GroupVersion: groupVersion, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", "test", input.args[1]) switch p, m := req.URL.Path, req.Method; { case p == resourcePath && m == http.MethodGet: - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil case p == resourcePath && m == http.MethodPatch: stream, err := req.GetBody() if err != nil { @@ -474,7 +467,7 @@ func TestSetEnvRemote(t *testing.T) { return nil, err } assert.Contains(t, string(bytes), `"value":`+`"`+"prod"+`"`, fmt.Sprintf("env not updated for %#v", input.object)) - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil default: t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req) return nil, fmt.Errorf("unexpected request") @@ -482,16 +475,162 @@ func TestSetEnvRemote(t *testing.T) { }), VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), } - out := new(bytes.Buffer) - cmd := NewCmdEnv(tf, out, out, out) - cmd.SetOutput(out) - cmd.Flags().Set("output", "yaml") - opts := EnvOptions{ - Out: out, - Local: false} - err := opts.Complete(tf, cmd, input.args) + + outputFormat := "yaml" + streams := genericclioptions.NewTestIOStreamsDiscard() + opts := NewEnvOptions(streams) + opts.PrintFlags = genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme) + opts.Local = false + opts.IOStreams = streams + err := opts.Complete(tf, NewCmdEnv(tf, streams), input.args) + assert.NoError(t, err) + err = opts.RunEnv() + assert.NoError(t, err) + }) + } +} + +func TestSetEnvFromResource(t *testing.T) { + mockConfigMap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{Name: "testconfigmap"}, + Data: map[string]string{ + "env": "prod", + "test-key": "testValue", + "test-key-two": "testValueTwo", + }, + } + + mockSecret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "testsecret"}, + Data: map[string][]byte{ + "env": []byte("prod"), + "test-key": []byte("testValue"), + "test-key-two": []byte("testValueTwo"), + }, + } + + inputs := []struct { + name string + args []string + from string + keys []string + assertIncludes []string + assertExcludes []string + }{ + { + name: "test from configmap", + args: []string{"deployment", "nginx"}, + from: "configmap/testconfigmap", + keys: []string{}, + assertIncludes: []string{ + `{"name":"ENV","valueFrom":{"configMapKeyRef":{"key":"env","name":"testconfigmap"}}}`, + `{"name":"TEST_KEY","valueFrom":{"configMapKeyRef":{"key":"test-key","name":"testconfigmap"}}}`, + `{"name":"TEST_KEY_TWO","valueFrom":{"configMapKeyRef":{"key":"test-key-two","name":"testconfigmap"}}}`, + }, + assertExcludes: []string{}, + }, + { + name: "test from secret", + args: []string{"deployment", "nginx"}, + from: "secret/testsecret", + keys: []string{}, + assertIncludes: []string{ + `{"name":"ENV","valueFrom":{"secretKeyRef":{"key":"env","name":"testsecret"}}}`, + `{"name":"TEST_KEY","valueFrom":{"secretKeyRef":{"key":"test-key","name":"testsecret"}}}`, + `{"name":"TEST_KEY_TWO","valueFrom":{"secretKeyRef":{"key":"test-key-two","name":"testsecret"}}}`, + }, + assertExcludes: []string{}, + }, + { + name: "test from configmap with keys", + args: []string{"deployment", "nginx"}, + from: "configmap/testconfigmap", + keys: []string{"env", "test-key-two"}, + assertIncludes: []string{ + `{"name":"ENV","valueFrom":{"configMapKeyRef":{"key":"env","name":"testconfigmap"}}}`, + `{"name":"TEST_KEY_TWO","valueFrom":{"configMapKeyRef":{"key":"test-key-two","name":"testconfigmap"}}}`, + }, + assertExcludes: []string{`{"name":"TEST_KEY","valueFrom":{"configMapKeyRef":{"key":"test-key","name":"testconfigmap"}}}`}, + }, + { + name: "test from secret with keys", + args: []string{"deployment", "nginx"}, + from: "secret/testsecret", + keys: []string{"env", "test-key-two"}, + assertIncludes: []string{ + `{"name":"ENV","valueFrom":{"secretKeyRef":{"key":"env","name":"testsecret"}}}`, + `{"name":"TEST_KEY_TWO","valueFrom":{"secretKeyRef":{"key":"test-key-two","name":"testsecret"}}}`, + }, + assertExcludes: []string{`{"name":"TEST_KEY","valueFrom":{"secretKeyRef":{"key":"test-key","name":"testsecret"}}}`}, + }, + } + + for _, input := range inputs { + mockDeployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, + Spec: appsv1.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "nginx", + Image: "nginx", + }, + }, + }, + }, + }, + } + t.Run(input.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory().WithNamespace("test") + defer tf.Cleanup() + + tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} + tf.Client = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == "/namespaces/test/configmaps/testconfigmap" && m == http.MethodGet: + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(mockConfigMap)}, nil + case p == "/namespaces/test/secrets/testsecret" && m == http.MethodGet: + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(mockSecret)}, nil + case p == "/namespaces/test/deployments/nginx" && m == http.MethodGet: + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(mockDeployment)}, nil + case p == "/namespaces/test/deployments/nginx" && m == http.MethodPatch: + stream, err := req.GetBody() + if err != nil { + return nil, err + } + bytes, err := ioutil.ReadAll(stream) + if err != nil { + return nil, err + } + for _, include := range input.assertIncludes { + assert.Contains(t, string(bytes), include) + } + for _, exclude := range input.assertExcludes { + assert.NotContains(t, string(bytes), exclude) + } + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(mockDeployment)}, nil + default: + t.Errorf("%s: unexpected request: %#v\n%#v", input.name, req.URL, req) + return nil, nil + } + }), + } + + outputFormat := "yaml" + streams := genericclioptions.NewTestIOStreamsDiscard() + opts := NewEnvOptions(streams) + opts.From = input.from + opts.Keys = input.keys + opts.PrintFlags = genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme) + opts.Local = false + opts.IOStreams = streams + err := opts.Complete(tf, NewCmdEnv(tf, streams), input.args) assert.NoError(t, err) - err = opts.RunEnv(tf) + err = opts.RunEnv() assert.NoError(t, err) }) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_image.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_image.go index 7d9ac6a8e..7efa5f2d1 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_image.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_image.go @@ -18,41 +18,48 @@ package set import ( "fmt" - "io" + "github.com/golang/glog" "github.com/spf13/cobra" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) // ImageOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() -type ImageOptions struct { +type SetImageOptions struct { resource.FilenameOptions + PrintFlags *genericclioptions.PrintFlags + RecordFlags *genericclioptions.RecordFlags + Infos []*resource.Info Selector string - Out io.Writer - Err io.Writer DryRun bool - ShortOutput bool All bool - Record bool Output string - ChangeCause string Local bool - Cmd *cobra.Command - ResolveImage func(in string) (string, error) + ResolveImage ImageResolver + + PrintObj printers.ResourcePrinterFunc + Recorder genericclioptions.Recorder - UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) + UpdatePodSpecForObject polymorphichelpers.UpdatePodSpecForObjectFunc Resources []string ContainerImages map[string]string + + genericclioptions.IOStreams } var ( @@ -79,11 +86,19 @@ var ( kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml`) ) -func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command { - options := &ImageOptions{ - Out: out, - Err: err, +func NewImageOptions(streams genericclioptions.IOStreams) *SetImageOptions { + return &SetImageOptions{ + PrintFlags: genericclioptions.NewPrintFlags("image updated").WithTypeSetter(scheme.Scheme), + RecordFlags: genericclioptions.NewRecordFlags(), + + Recorder: genericclioptions.NoopRecorder{}, + + IOStreams: streams, } +} + +func NewCmdImage(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewImageOptions(streams) cmd := &cobra.Command{ Use: "image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N", @@ -92,35 +107,50 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command { Long: image_long, Example: image_example, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.Run()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.Run()) }, } - cmdutil.AddPrinterFlags(cmd) + o.PrintFlags.AddFlags(cmd) + o.RecordFlags.AddFlags(cmd) + usage := "identifying the resource to get from a server." - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) - cmd.Flags().BoolVar(&options.All, "all", options.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") - cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().BoolVar(&options.Local, "local", options.Local, "If true, set image will NOT contact api-server but run locally.") - cmdutil.AddRecordFlag(cmd) + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().BoolVar(&o.All, "all", o.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set image will NOT contact api-server but run locally.") cmdutil.AddDryRunFlag(cmd) cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } -func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - o.UpdatePodSpecForObject = f.UpdatePodSpecForObject - o.ShortOutput = cmdutil.GetFlagString(cmd, "output") == "name" - o.Record = cmdutil.GetRecordFlag(cmd) - o.ChangeCause = f.Command(cmd, false) +func (o *SetImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + + o.UpdatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn o.DryRun = cmdutil.GetDryRunFlag(cmd) o.Output = cmdutil.GetFlagString(cmd, "output") - o.ResolveImage = f.ResolveImage - o.Cmd = cmd + o.ResolveImage = resolveImageFunc + + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + + o.PrintObj = printer.PrintObj - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -132,7 +162,7 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) builder := f.NewBuilder(). - Internal(). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). LocalParam(o.Local). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). @@ -161,7 +191,7 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st return nil } -func (o *ImageOptions) Validate() error { +func (o *SetImageOptions) Validate() error { errors := []error{} if o.All && len(o.Selector) > 0 { errors = append(errors, fmt.Errorf("cannot set --all and --selector at the same time")) @@ -177,13 +207,12 @@ func (o *ImageOptions) Validate() error { return utilerrors.NewAggregate(errors) } -func (o *ImageOptions) Run() error { +func (o *SetImageOptions) Run() error { allErrs := []error{} - patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { + patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) { transformed := false - info.Object = info.AsVersioned() - _, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error { + _, err := o.UpdatePodSpecForObject(obj, func(spec *v1.PodSpec) error { for name, image := range o.ContainerImages { var ( containerFound bool @@ -219,10 +248,18 @@ func (o *ImageOptions) Run() error { } return nil }) - if transformed && err == nil { - return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), info.Object) + if err != nil { + return nil, err } - return nil, err + if !transformed { + return nil, nil + } + // record this change (for rollout history) + if err := o.Recorder.Record(obj); err != nil { + glog.V(4).Infof("error recording current command: %v", err) + } + + return runtime.Encode(scheme.DefaultJSONEncoder(), obj) }) for _, patch := range patches { @@ -238,38 +275,22 @@ func (o *ImageOptions) Run() error { } if o.Local || o.DryRun { - if err := cmdutil.PrintObject(o.Cmd, patch.Info.AsVersioned(), o.Out); err != nil { - return err + if err := o.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) } continue } // patch the change - obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { allErrs = append(allErrs, fmt.Errorf("failed to patch image update to pod template: %v\n", err)) continue } - info.Refresh(obj, true) - - // record this change (for rollout history) - if o.Record || cmdutil.ContainsChangeCause(info) { - if patch, patchType, err := cmdutil.ChangeResourcePatch(info, o.ChangeCause); err == nil { - if obj, err = resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, patchType, patch); err != nil { - fmt.Fprintf(o.Err, "WARNING: changes to %s/%s can't be recorded: %v\n", info.Mapping.Resource, info.Name, err) - } - } - } - info.Refresh(obj, true) - - if len(o.Output) > 0 { - if err := cmdutil.PrintObject(o.Cmd, info.AsVersioned(), o.Out); err != nil { - return err - } - continue + if err := o.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) } - cmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, o.DryRun, "image updated") } return utilerrors.NewAggregate(allErrs) } @@ -289,3 +310,13 @@ func hasWildcardKey(containerImages map[string]string) bool { _, ok := containerImages["*"] return ok } + +// ImageResolver is a func that receives an image name, and +// resolves it to an appropriate / compatible image name. +// Adds flexibility for future image resolving methods. +type ImageResolver func(in string) (string, error) + +// implements ImageResolver +func resolveImageFunc(in string) (string, error) { + return in, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_image_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_image_test.go index 5c5cf3588..bf731f066 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_image_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_image_test.go @@ -17,7 +17,6 @@ limitations under the License. package set import ( - "bytes" "fmt" "io/ioutil" "net/http" @@ -26,6 +25,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + appsv1 "k8s.io/api/apps/v1" appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta2 "k8s.io/api/apps/v1beta2" @@ -35,42 +35,45 @@ import ( 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" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestImageLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - ns := legacyscheme.Codecs - tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdImage(tf, buf, buf) + outputFormat := "name" + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdImage(tf, streams) cmd.SetOutput(buf) - cmd.Flags().Set("output", "name") + cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") - opts := ImageOptions{FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, - Out: buf, - Local: true} + opts := SetImageOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + FilenameOptions: resource.FilenameOptions{ + Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, + Local: true, + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{"cassandra=thingy"}) if err == nil { err = opts.Validate() @@ -87,20 +90,23 @@ func TestImageLocal(t *testing.T) { } func TestSetImageValidation(t *testing.T) { + printFlags := genericclioptions.NewPrintFlags("").WithTypeSetter(scheme.Scheme) + testCases := []struct { name string - imageOptions *ImageOptions + imageOptions *SetImageOptions expectErr string }{ { name: "test resource < 1 and filenames empty", - imageOptions: &ImageOptions{}, + imageOptions: &SetImageOptions{PrintFlags: printFlags}, expectErr: "[one or more resources must be specified as or /, at least one image update is required]", }, { name: "test containerImages < 1", - imageOptions: &ImageOptions{ - Resources: []string{"a", "b", "c"}, + imageOptions: &SetImageOptions{ + PrintFlags: printFlags, + Resources: []string{"a", "b", "c"}, FilenameOptions: resource.FilenameOptions{ Filenames: []string{"testFile"}, @@ -110,8 +116,9 @@ func TestSetImageValidation(t *testing.T) { }, { name: "test containerImages > 1 and all containers are already specified by *", - imageOptions: &ImageOptions{ - Resources: []string{"a", "b", "c"}, + imageOptions: &SetImageOptions{ + PrintFlags: printFlags, + Resources: []string{"a", "b", "c"}, FilenameOptions: resource.FilenameOptions{ Filenames: []string{"testFile"}, }, @@ -124,8 +131,9 @@ func TestSetImageValidation(t *testing.T) { }, { name: "success case", - imageOptions: &ImageOptions{ - Resources: []string{"a", "b", "c"}, + imageOptions: &SetImageOptions{ + PrintFlags: printFlags, + Resources: []string{"a", "b", "c"}, FilenameOptions: resource.FilenameOptions{ Filenames: []string{"testFile"}, }, @@ -150,32 +158,34 @@ func TestSetImageValidation(t *testing.T) { } func TestSetMultiResourcesImageLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - ns := legacyscheme.Codecs - tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdImage(tf, buf, buf) + outputFormat := "name" + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdImage(tf, streams) cmd.SetOutput(buf) - cmd.Flags().Set("output", "name") + cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") - opts := ImageOptions{FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, - Out: buf, - Local: true} + opts := SetImageOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + FilenameOptions: resource.FilenameOptions{ + Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, + Local: true, + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{"*=thingy"}) if err == nil { err = opts.Validate() @@ -520,20 +530,17 @@ func TestSetImageRemote(t *testing.T) { t.Run(input.name, func(t *testing.T) { groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) - ns := legacyscheme.Codecs - tf.Namespace = "test" tf.Client = &fake.RESTClient{ GroupVersion: groupVersion, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", "test", input.args[1]) switch p, m := req.URL.Path, req.Method; { case p == resourcePath && m == http.MethodGet: - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil case p == resourcePath && m == http.MethodPatch: stream, err := req.GetBody() if err != nil { @@ -544,7 +551,7 @@ func TestSetImageRemote(t *testing.T) { return nil, err } assert.Contains(t, string(bytes), `"image":`+`"`+"thingy"+`"`, fmt.Sprintf("image not updated for %#v", input.object)) - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil default: t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req) return nil, fmt.Errorf("unexpected request") @@ -552,13 +559,18 @@ func TestSetImageRemote(t *testing.T) { }), VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), } - out := new(bytes.Buffer) - cmd := NewCmdImage(tf, out, out) - cmd.SetOutput(out) - cmd.Flags().Set("output", "yaml") - opts := ImageOptions{ - Out: out, - Local: false} + + outputFormat := "yaml" + + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdImage(tf, streams) + cmd.Flags().Set("output", outputFormat) + opts := SetImageOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + + Local: false, + IOStreams: streams, + } err := opts.Complete(tf, cmd, input.args) assert.NoError(t, err) err = opts.Run() diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_resources.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_resources.go index e696dac06..e773bb813 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_resources.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_resources.go @@ -18,19 +18,22 @@ package set import ( "fmt" - "io" - "strings" + "github.com/golang/glog" "github.com/spf13/cobra" - "k8s.io/api/core/v1" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -58,85 +61,113 @@ var ( // ResourcesOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags -type ResourcesOptions struct { +type SetResourcesOptions struct { resource.FilenameOptions + PrintFlags *genericclioptions.PrintFlags + RecordFlags *genericclioptions.RecordFlags + Infos []*resource.Info - Out io.Writer - Err io.Writer Selector string ContainerSelector string Output string All bool - Record bool - ChangeCause string Local bool - Cmd *cobra.Command + + DryRun bool + + PrintObj printers.ResourcePrinterFunc + Recorder genericclioptions.Recorder Limits string Requests string ResourceRequirements v1.ResourceRequirements - UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) + UpdatePodSpecForObject polymorphichelpers.UpdatePodSpecForObjectFunc Resources []string + + genericclioptions.IOStreams } -func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { - options := &ResourcesOptions{ - Out: out, - Err: errOut, - } +// NewResourcesOptions returns a ResourcesOptions indicating all containers in the selected +// pod templates are selected by default. +func NewResourcesOptions(streams genericclioptions.IOStreams) *SetResourcesOptions { + return &SetResourcesOptions{ + PrintFlags: genericclioptions.NewPrintFlags("resource requirements updated").WithTypeSetter(scheme.Scheme), + RecordFlags: genericclioptions.NewRecordFlags(), + + Recorder: genericclioptions.NoopRecorder{}, + + ContainerSelector: "*", - resourceTypesWithPodTemplate := []string{} - for _, resource := range f.SuggestedPodTemplateResources() { - resourceTypesWithPodTemplate = append(resourceTypesWithPodTemplate, resource.Resource) + IOStreams: streams, } +} + +func NewCmdResources(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewResourcesOptions(streams) cmd := &cobra.Command{ Use: "resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --requests=REQUESTS]", DisableFlagsInUseLine: true, Short: i18n.T("Update resource requests/limits on objects with pod templates"), - Long: fmt.Sprintf(resources_long, strings.Join(resourceTypesWithPodTemplate, ", ")), + Long: fmt.Sprintf(resources_long, cmdutil.SuggestApiResources("kubectl")), Example: resources_example, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.Run()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.Run()) }, } - cmdutil.AddPrinterFlags(cmd) + o.PrintFlags.AddFlags(cmd) + o.RecordFlags.AddFlags(cmd) + //usage := "Filename, directory, or URL to a file identifying the resource to get from the server" //kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) usage := "identifying the resource to get from a server." - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) - cmd.Flags().BoolVar(&options.All, "all", options.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") - cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones,supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().StringVarP(&options.ContainerSelector, "containers", "c", "*", "The names of containers in the selected pod templates to change, all containers are selected by default - may use wildcards") - cmd.Flags().BoolVar(&options.Local, "local", options.Local, "If true, set resources will NOT contact api-server but run locally.") + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().BoolVar(&o.All, "all", o.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, not including uninitialized ones,supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().StringVarP(&o.ContainerSelector, "containers", "c", o.ContainerSelector, "The names of containers in the selected pod templates to change, all containers are selected by default - may use wildcards") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set resources will NOT contact api-server but run locally.") cmdutil.AddDryRunFlag(cmd) - cmdutil.AddRecordFlag(cmd) cmdutil.AddIncludeUninitializedFlag(cmd) - cmd.Flags().StringVar(&options.Limits, "limits", options.Limits, "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.") - cmd.Flags().StringVar(&options.Requests, "requests", options.Requests, "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.") + cmd.Flags().StringVar(&o.Limits, "limits", o.Limits, "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.") + cmd.Flags().StringVar(&o.Requests, "requests", o.Requests, "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.") return cmd } -func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - o.UpdatePodSpecForObject = f.UpdatePodSpecForObject +func (o *SetResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + + o.UpdatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn o.Output = cmdutil.GetFlagString(cmd, "output") - o.Record = cmdutil.GetRecordFlag(cmd) - o.ChangeCause = f.Command(cmd, false) - o.Cmd = cmd + o.DryRun = cmdutil.GetDryRunFlag(cmd) + + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObj = printer.PrintObj - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) builder := f.NewBuilder(). - Internal(). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). LocalParam(o.Local). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). @@ -166,7 +197,7 @@ func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args return nil } -func (o *ResourcesOptions) Validate() error { +func (o *SetResourcesOptions) Validate() error { var err error if o.All && len(o.Selector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") @@ -183,12 +214,11 @@ func (o *ResourcesOptions) Validate() error { return nil } -func (o *ResourcesOptions) Run() error { +func (o *SetResourcesOptions) Run() error { allErrs := []error{} - patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { + patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) { transformed := false - info.Object = info.AsVersioned() - _, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error { + _, err := o.UpdatePodSpecForObject(obj, func(spec *v1.PodSpec) error { containers, _ := selectContainers(spec.Containers, o.ContainerSelector) if len(containers) != 0 { for i := range containers { @@ -212,10 +242,18 @@ func (o *ResourcesOptions) Run() error { } return nil }) - if transformed && err == nil { - return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), info.Object) + if err != nil { + return nil, err + } + if !transformed { + return nil, nil } - return nil, err + // record this change (for rollout history) + if err := o.Recorder.Record(obj); err != nil { + glog.V(4).Infof("error recording current command: %v", err) + } + + return runtime.Encode(scheme.DefaultJSONEncoder(), obj) }) for _, patch := range patches { @@ -231,38 +269,22 @@ func (o *ResourcesOptions) Run() error { continue } - if o.Local || cmdutil.GetDryRunFlag(o.Cmd) { - if err := cmdutil.PrintObject(o.Cmd, patch.Info.AsVersioned(), o.Out); err != nil { - return err + if o.Local || o.DryRun { + if err := o.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) } continue } - obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { allErrs = append(allErrs, fmt.Errorf("failed to patch limit update to pod template %v\n", err)) continue } - info.Refresh(obj, true) - - //record this change (for rollout history) - if o.Record || cmdutil.ContainsChangeCause(info) { - if err := cmdutil.RecordChangeCause(obj, o.ChangeCause); err == nil { - if obj, err = resource.NewHelper(info.Client, info.Mapping).Replace(info.Namespace, info.Name, false, obj); err != nil { - allErrs = append(allErrs, fmt.Errorf("changes to %s/%s can't be recorded: %v\n", info.Mapping.Resource, info.Name, err)) - } - } - } - info.Refresh(obj, true) - shortOutput := o.Output == "name" - if len(o.Output) > 0 && !shortOutput { - if err := cmdutil.PrintObject(o.Cmd, info.AsVersioned(), o.Out); err != nil { - return err - } - continue + if err := o.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) } - cmdutil.PrintSuccess(shortOutput, o.Out, info.Object, false, "resource requirements updated") } return utilerrors.NewAggregate(allErrs) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_resources_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_resources_test.go index 2685fb0a3..9d286278f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_resources_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_resources_test.go @@ -17,7 +17,6 @@ limitations under the License. package set import ( - "bytes" "fmt" "io/ioutil" "net/http" @@ -35,44 +34,48 @@ import ( 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" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestResourcesLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdResources(tf, buf, buf) + outputFormat := "name" + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdResources(tf, streams) cmd.SetOutput(buf) - cmd.Flags().Set("output", "name") + cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") - opts := ResourcesOptions{FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, - Out: buf, + opts := SetResourcesOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + FilenameOptions: resource.FilenameOptions{ + Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, Local: true, Limits: "cpu=200m,memory=512Mi", Requests: "cpu=200m,memory=512Mi", - ContainerSelector: "*"} + ContainerSelector: "*", + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{}) if err == nil { @@ -90,34 +93,37 @@ func TestResourcesLocal(t *testing.T) { } func TestSetMultiResourcesLimitsLocal(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdResources(tf, buf, buf) + outputFormat := "name" + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdResources(tf, streams) cmd.SetOutput(buf) - cmd.Flags().Set("output", "name") + cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") - opts := ResourcesOptions{FilenameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, - Out: buf, + opts := SetResourcesOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + FilenameOptions: resource.FilenameOptions{ + Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, Local: true, Limits: "cpu=200m,memory=512Mi", Requests: "cpu=200m,memory=512Mi", - ContainerSelector: "*"} + ContainerSelector: "*", + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{}) if err == nil { @@ -447,19 +453,17 @@ func TestSetResourcesRemote(t *testing.T) { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) - ns := legacyscheme.Codecs - tf.Namespace = "test" + tf.Client = &fake.RESTClient{ GroupVersion: groupVersion, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", "test", input.args[1]) switch p, m := req.URL.Path, req.Method; { case p == resourcePath && m == http.MethodGet: - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil case p == resourcePath && m == http.MethodPatch: stream, err := req.GetBody() if err != nil { @@ -470,7 +474,7 @@ func TestSetResourcesRemote(t *testing.T) { return nil, err } assert.Contains(t, string(bytes), "200m", fmt.Sprintf("resources not updated for %#v", input.object)) - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil default: t.Errorf("%s: unexpected request: %s %#v\n%#v", "resources", req.Method, req.URL, req) return nil, fmt.Errorf("unexpected request") @@ -478,14 +482,19 @@ func TestSetResourcesRemote(t *testing.T) { }), VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), } - buf := new(bytes.Buffer) - cmd := NewCmdResources(tf, buf, buf) - cmd.SetOutput(buf) - cmd.Flags().Set("output", "yaml") - opts := ResourcesOptions{ - Out: buf, + + outputFormat := "yaml" + + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdResources(tf, streams) + cmd.Flags().Set("output", outputFormat) + opts := SetResourcesOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + Limits: "cpu=200m,memory=512Mi", - ContainerSelector: "*"} + ContainerSelector: "*", + IOStreams: streams, + } err := opts.Complete(tf, cmd, input.args) if err == nil { err = opts.Validate() diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_selector.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_selector.go index 820916223..70199c376 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_selector.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_selector.go @@ -18,42 +18,45 @@ package set import ( "fmt" - "io" + "github.com/golang/glog" "github.com/spf13/cobra" + "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) // SelectorOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() -type SelectorOptions struct { - fileOptions resource.FilenameOptions - - local bool - dryrun bool - all bool - record bool - changeCause string - output string - +type SetSelectorOptions struct { + // Bound + ResourceBuilderFlags *genericclioptions.ResourceBuilderFlags + PrintFlags *genericclioptions.PrintFlags + RecordFlags *genericclioptions.RecordFlags + dryrun bool + + // set by args resources []string selector *metav1.LabelSelector - out io.Writer - PrintObject func(obj runtime.Object) error - ClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) + // computed + WriteToServer bool + PrintObj printers.ResourcePrinterFunc + Recorder genericclioptions.Recorder + ResourceFinder genericclioptions.ResourceFinder - builder *resource.Builder - mapper meta.RESTMapper + // set at initialization + genericclioptions.IOStreams } var ( @@ -70,11 +73,26 @@ var ( kubectl create deployment my-dep -o yaml --dry-run | kubectl label --local -f - environment=qa -o yaml | kubectl create -f -`) ) -// NewCmdSelector is the "set selector" command. -func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &SelectorOptions{ - out: out, +func NewSelectorOptions(streams genericclioptions.IOStreams) *SetSelectorOptions { + return &SetSelectorOptions{ + ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags(). + WithScheme(scheme.Scheme). + WithAll(false). + WithLocal(false). + WithUninitialized(false). + WithLatest(), + PrintFlags: genericclioptions.NewPrintFlags("selector updated").WithTypeSetter(scheme.Scheme), + RecordFlags: genericclioptions.NewRecordFlags(), + + Recorder: genericclioptions.NoopRecorder{}, + + IOStreams: streams, } +} + +// NewCmdSelector is the "set selector" command. +func NewCmdSelector(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewSelectorOptions(streams) cmd := &cobra.Command{ Use: "selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version]", @@ -83,83 +101,56 @@ func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: fmt.Sprintf(selectorLong, validation.LabelValueMaxLength), Example: selectorExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.RunSelector()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunSelector()) }, } - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().Bool("all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") - cmd.Flags().Bool("local", false, "If true, set selector will NOT contact api-server but run locally.") + + o.ResourceBuilderFlags.AddFlags(cmd.Flags()) + o.PrintFlags.AddFlags(cmd) + o.RecordFlags.AddFlags(cmd) + cmd.Flags().String("resource-version", "", "If non-empty, the selectors update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") - usage := "the resource to update the selectors" - cmdutil.AddFilenameOptionFlags(cmd, &options.fileOptions, usage) cmdutil.AddDryRunFlag(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } // Complete assigns the SelectorOptions from args. -func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - o.local = cmdutil.GetFlagBool(cmd, "local") - o.all = cmdutil.GetFlagBool(cmd, "all") - o.record = cmdutil.GetRecordFlag(cmd) - o.dryrun = cmdutil.GetDryRunFlag(cmd) - o.output = cmdutil.GetFlagString(cmd, "output") +func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() if err != nil { return err } - o.changeCause = f.Command(cmd, false) - mapper, _ := f.Object() - o.mapper = mapper + o.dryrun = cmdutil.GetDryRunFlag(cmd) o.resources, o.selector, err = getResourcesAndSelector(args) if err != nil { return err } - includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) - o.builder = f.NewBuilder(). - Internal(). - LocalParam(o.local). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &o.fileOptions). - IncludeUninitialized(includeUninitialized). - Flatten() - - if !o.local { - o.builder. - ResourceTypeOrNameArgs(o.all, o.resources...). - Latest() - } else { - // if a --local flag was provided, and a resource was specified in the form - // /, fail immediately as --local cannot query the api server - // for the specified resource. - if len(o.resources) > 0 { - return resource.LocalResourceError - } - } + o.ResourceFinder = o.ResourceBuilderFlags.ToBuilder(f, o.resources) + o.WriteToServer = !(*o.ResourceBuilderFlags.Local || o.dryrun) - o.PrintObject = func(obj runtime.Object) error { - return cmdutil.PrintObject(cmd, obj, o.out) + if o.dryrun { + o.PrintFlags.Complete("%s (dry run)") } - o.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) { - return f.ClientForMapping(mapping) + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err } + o.PrintObj = printer.PrintObj + return err } // Validate basic inputs -func (o *SelectorOptions) Validate() error { - if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.fileOptions.Filenames) { - return fmt.Errorf("one or more resources must be specified as or /") - } +func (o *SetSelectorOptions) Validate() error { if o.selector == nil { return fmt.Errorf("one selector is required") } @@ -167,54 +158,38 @@ func (o *SelectorOptions) Validate() error { } // RunSelector executes the command. -func (o *SelectorOptions) RunSelector() error { - r := o.builder.Do() - err := r.Err() - if err != nil { - return err - } +func (o *SetSelectorOptions) RunSelector() error { + r := o.ResourceFinder.Do() return r.Visit(func(info *resource.Info, err error) error { patch := &Patch{Info: info} - CalculatePatch(patch, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { - versioned := info.AsVersioned() - patch.Info.Object = versioned + CalculatePatch(patch, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) { selectErr := updateSelectorForObject(info.Object, *o.selector) + if selectErr != nil { + return nil, selectErr + } - if selectErr == nil { - return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), info.Object) + // record this change (for rollout history) + if err := o.Recorder.Record(patch.Info.Object); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } - return nil, selectErr + + return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object) }) if patch.Err != nil { return patch.Err } - if o.local || o.dryrun { - return o.PrintObject(info.Object) + if !o.WriteToServer { + return o.PrintObj(info.Object, o.Out) } - patched, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { return err } - if o.record || cmdutil.ContainsChangeCause(info) { - if err := cmdutil.RecordChangeCause(patched, o.changeCause); err == nil { - if patched, err = resource.NewHelper(info.Client, info.Mapping).Replace(info.Namespace, info.Name, false, patched); err != nil { - return fmt.Errorf("changes to %s/%s can't be recorded: %v\n", info.Mapping.Resource, info.Name, err) - } - } - } - - info.Refresh(patched, true) - - shortOutput := o.output == "name" - if len(o.output) > 0 && !shortOutput { - return o.PrintObject(patched) - } - cmdutil.PrintSuccess(shortOutput, o.out, info.Object, o.dryrun, "selector updated") - return nil + return o.PrintObj(actual, o.Out) }) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_selector_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_selector_test.go index 15dba1a94..e1924f32c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_selector_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_selector_test.go @@ -17,8 +17,6 @@ limitations under the License. package set import ( - "bytes" - "net/http" "reflect" "strings" "testing" @@ -29,11 +27,9 @@ import ( extensionsv1beta1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" - cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" ) func TestUpdateSelectorForObjectTypes(t *testing.T) { @@ -316,30 +312,30 @@ func TestGetResourcesAndSelector(t *testing.T) { } func TestSelectorTest(t *testing.T) { - tf := cmdtesting.NewTestFactory() - defer tf.Cleanup() - - ns := legacyscheme.Codecs - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: ""}, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) - return nil, nil - }), + info := &resource.Info{ + Object: &v1.Service{ + TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Service"}, + ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "cassandra"}, + }, } - tf.Namespace = "test" - tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdSelector(tf, buf) - cmd.SetOutput(buf) - cmd.Flags().Set("output", "name") - cmd.Flags().Set("local", "true") - cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/service.yaml") + labelToSet, err := metav1.ParseToLabelSelector("environment=qa") + if err != nil { + t.Fatal(err) + } - cmd.Run(cmd, []string{"environment=qa"}) + iostreams, _, buf, _ := genericclioptions.NewTestIOStreams() + o := &SetSelectorOptions{ + selector: labelToSet, + ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(info), + Recorder: genericclioptions.NoopRecorder{}, + PrintObj: (&printers.NamePrinter{}).PrintObj, + IOStreams: iostreams, + } + if err := o.RunSelector(); err != nil { + t.Fatal(err) + } if !strings.Contains(buf.String(), "service/cassandra") { t.Errorf("did not set selector: %s", buf.String()) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_serviceaccount.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_serviceaccount.go index 1bcc1cfb5..6faf72780 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_serviceaccount.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_serviceaccount.go @@ -19,8 +19,8 @@ package set import ( "errors" "fmt" - "io" + "github.com/golang/glog" "github.com/spf13/cobra" "k8s.io/api/core/v1" @@ -29,7 +29,11 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -53,29 +57,40 @@ var ( ) // serviceAccountConfig encapsulates the data required to perform the operation. -type serviceAccountConfig struct { +type SetServiceAccountOptions struct { + PrintFlags *genericclioptions.PrintFlags + RecordFlags *genericclioptions.RecordFlags + fileNameOptions resource.FilenameOptions - out io.Writer - err io.Writer dryRun bool - cmd *cobra.Command shortOutput bool all bool - record bool output string - changeCause string local bool - updatePodSpecForObject func(runtime.Object, func(*v1.PodSpec) error) (bool, error) + updatePodSpecForObject polymorphichelpers.UpdatePodSpecForObjectFunc infos []*resource.Info serviceAccountName string + + PrintObj printers.ResourcePrinterFunc + Recorder genericclioptions.Recorder + + genericclioptions.IOStreams } -// NewCmdServiceAccount returns the "set serviceaccount" command. -func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command { - saConfig := &serviceAccountConfig{ - out: out, - err: err, +func NewSetServiceAccountOptions(streams genericclioptions.IOStreams) *SetServiceAccountOptions { + return &SetServiceAccountOptions{ + PrintFlags: genericclioptions.NewPrintFlags("serviceaccount updated").WithTypeSetter(scheme.Scheme), + RecordFlags: genericclioptions.NewRecordFlags(), + + Recorder: genericclioptions.NoopRecorder{}, + + IOStreams: streams, } +} + +// NewCmdServiceAccount returns the "set serviceaccount" command. +func NewCmdServiceAccount(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewSetServiceAccountOptions(streams) cmd := &cobra.Command{ Use: "serviceaccount (-f FILENAME | TYPE NAME) SERVICE_ACCOUNT", @@ -85,55 +100,70 @@ func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command Long: serviceaccountLong, Example: serviceaccountExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(saConfig.Complete(f, cmd, args)) - cmdutil.CheckErr(saConfig.Run()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Run()) }, } - cmdutil.AddPrinterFlags(cmd) + + o.PrintFlags.AddFlags(cmd) + o.RecordFlags.AddFlags(cmd) usage := "identifying the resource to get from a server." - cmdutil.AddFilenameOptionFlags(cmd, &saConfig.fileNameOptions, usage) - cmd.Flags().BoolVar(&saConfig.all, "all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") - cmd.Flags().BoolVar(&saConfig.local, "local", false, "If true, set serviceaccount will NOT contact api-server but run locally.") - cmdutil.AddRecordFlag(cmd) + cmdutil.AddFilenameOptionFlags(cmd, &o.fileNameOptions, usage) + cmd.Flags().BoolVar(&o.all, "all", o.all, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") + cmd.Flags().BoolVar(&o.local, "local", o.local, "If true, set serviceaccount will NOT contact api-server but run locally.") cmdutil.AddDryRunFlag(cmd) cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } // Complete configures serviceAccountConfig from command line args. -func (saConfig *serviceAccountConfig) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - saConfig.shortOutput = cmdutil.GetFlagString(cmd, "output") == "name" - saConfig.record = cmdutil.GetRecordFlag(cmd) - saConfig.changeCause = f.Command(cmd, false) - saConfig.dryRun = cmdutil.GetDryRunFlag(cmd) - saConfig.output = cmdutil.GetFlagString(cmd, "output") - saConfig.updatePodSpecForObject = f.UpdatePodSpecForObject - saConfig.cmd = cmd - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() +func (o *SetServiceAccountOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + + o.shortOutput = cmdutil.GetFlagString(cmd, "output") == "name" + o.dryRun = cmdutil.GetDryRunFlag(cmd) + o.output = cmdutil.GetFlagString(cmd, "output") + o.updatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn + + if o.dryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err + } + o.PrintObj = printer.PrintObj + + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } if len(args) == 0 { return errors.New("serviceaccount is required") } - saConfig.serviceAccountName = args[len(args)-1] + o.serviceAccountName = args[len(args)-1] resources := args[:len(args)-1] includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) builder := f.NewBuilder(). - Internal(). - LocalParam(saConfig.local). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). + LocalParam(o.local). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, &saConfig.fileNameOptions). + FilenameParam(enforceNamespace, &o.fileNameOptions). IncludeUninitialized(includeUninitialized). Flatten() - if !saConfig.local { - builder.ResourceTypeOrNameArgs(saConfig.all, resources...). + if !o.local { + builder.ResourceTypeOrNameArgs(o.all, resources...). Latest() } - saConfig.infos, err = builder.Do().Infos() + o.infos, err = builder.Do().Infos() if err != nil { return err } @@ -141,49 +171,46 @@ func (saConfig *serviceAccountConfig) Complete(f cmdutil.Factory, cmd *cobra.Com } // Run creates and applies the patch either locally or calling apiserver. -func (saConfig *serviceAccountConfig) Run() error { +func (o *SetServiceAccountOptions) Run() error { patchErrs := []error{} - patchFn := func(info *resource.Info) ([]byte, error) { - info.Object = info.AsVersioned() - saConfig.updatePodSpecForObject(info.Object, func(podSpec *v1.PodSpec) error { - podSpec.ServiceAccountName = saConfig.serviceAccountName + patchFn := func(obj runtime.Object) ([]byte, error) { + _, err := o.updatePodSpecForObject(obj, func(podSpec *v1.PodSpec) error { + podSpec.ServiceAccountName = o.serviceAccountName return nil }) - return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), info.Object) + if err != nil { + return nil, err + } + // record this change (for rollout history) + if err := o.Recorder.Record(obj); err != nil { + glog.V(4).Infof("error recording current command: %v", err) + } + + return runtime.Encode(scheme.DefaultJSONEncoder(), obj) } - patches := CalculatePatches(saConfig.infos, cmdutil.InternalVersionJSONEncoder(), patchFn) + + patches := CalculatePatches(o.infos, scheme.DefaultJSONEncoder(), patchFn) for _, patch := range patches { info := patch.Info if patch.Err != nil { patchErrs = append(patchErrs, fmt.Errorf("error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err)) continue } - if saConfig.local || saConfig.dryRun { - if err := cmdutil.PrintObject(saConfig.cmd, patch.Info.AsVersioned(), saConfig.out); err != nil { - return err + if o.local || o.dryRun { + if err := o.PrintObj(info.Object, o.Out); err != nil { + patchErrs = append(patchErrs, err) } continue } - patched, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { patchErrs = append(patchErrs, fmt.Errorf("failed to patch ServiceAccountName %v", err)) continue } - info.Refresh(patched, true) - if saConfig.record || cmdutil.ContainsChangeCause(info) { - if patch, patchType, err := cmdutil.ChangeResourcePatch(info, saConfig.changeCause); err == nil { - if patched, err = resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, patchType, patch); err != nil { - fmt.Fprintf(saConfig.err, "WARNING: changes to %s/%s can't be recorded: %v\n", info.Mapping.Resource, info.Name, err) - } - } - } - if len(saConfig.output) > 0 { - if err := cmdutil.PrintObject(saConfig.cmd, info.AsVersioned(), saConfig.out); err != nil { - return err - } - continue + + if err := o.PrintObj(actual, o.Out); err != nil { + patchErrs = append(patchErrs, err) } - cmdutil.PrintSuccess(saConfig.shortOutput, saConfig.out, info.Object, saConfig.dryRun, "serviceaccount updated") } return utilerrors.NewAggregate(patchErrs) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_serviceaccount_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_serviceaccount_test.go index 90bf81b87..7239bf1c5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_serviceaccount_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_serviceaccount_test.go @@ -35,12 +35,13 @@ import ( 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" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -67,7 +68,7 @@ func TestSetServiceAccountLocal(t *testing.T) { for i, input := range inputs { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -77,52 +78,58 @@ func TestSetServiceAccountLocal(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" - out := new(bytes.Buffer) - cmd := NewCmdServiceAccount(tf, out, out) - cmd.SetOutput(out) - cmd.Flags().Set("output", "yaml") + + outputFormat := "yaml" + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdServiceAccount(tf, streams) + cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") testapi.Default = testapi.Groups[input.apiGroup] - saConfig := serviceAccountConfig{fileNameOptions: resource.FilenameOptions{ - Filenames: []string{input.yaml}}, - out: out, - local: true} + saConfig := SetServiceAccountOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + fileNameOptions: resource.FilenameOptions{ + Filenames: []string{input.yaml}}, + local: true, + IOStreams: streams, + } err := saConfig.Complete(tf, cmd, []string{serviceAccount}) assert.NoError(t, err) err = saConfig.Run() assert.NoError(t, err) - assert.Contains(t, out.String(), "serviceAccountName: "+serviceAccount, fmt.Sprintf("serviceaccount not updated for %s", input.yaml)) + assert.Contains(t, buf.String(), "serviceAccountName: "+serviceAccount, fmt.Sprintf("serviceaccount not updated for %s", input.yaml)) }) } } func TestSetServiceAccountMultiLocal(t *testing.T) { testapi.Default = testapi.Groups[""] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) return nil, nil }), } - tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdServiceAccount(tf, buf, buf) - cmd.SetOutput(buf) - cmd.Flags().Set("output", "name") + outputFormat := "name" + + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdServiceAccount(tf, streams) + cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") - opts := serviceAccountConfig{fileNameOptions: resource.FilenameOptions{ - Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, - out: buf, - local: true} + opts := SetServiceAccountOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + fileNameOptions: resource.FilenameOptions{ + Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, + local: true, + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{serviceAccount}) if err == nil { @@ -317,20 +324,17 @@ func TestSetServiceAccountRemote(t *testing.T) { t.Run(input.apiPrefix, func(t *testing.T) { groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) - ns := legacyscheme.Codecs - tf.Namespace = "test" tf.Client = &fake.RESTClient{ GroupVersion: groupVersion, - NegotiatedSerializer: ns, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", "test", input.args[1]) switch p, m := req.URL.Path, req.Method; { case p == resourcePath && m == http.MethodGet: - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil case p == resourcePath && m == http.MethodPatch: stream, err := req.GetBody() if err != nil { @@ -341,7 +345,7 @@ func TestSetServiceAccountRemote(t *testing.T) { return nil, err } assert.Contains(t, string(bytes), `"serviceAccountName":`+`"`+serviceAccount+`"`, fmt.Sprintf("serviceaccount not updated for %#v", input.object)) - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil default: t.Errorf("%s: unexpected request: %s %#v\n%#v", "serviceaccount", req.Method, req.URL, req) return nil, fmt.Errorf("unexpected request") @@ -349,13 +353,18 @@ func TestSetServiceAccountRemote(t *testing.T) { }), VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), } - out := new(bytes.Buffer) - cmd := NewCmdServiceAccount(tf, out, out) - cmd.SetOutput(out) - cmd.Flags().Set("output", "yaml") - saConfig := serviceAccountConfig{ - out: out, - local: false} + + outputFormat := "yaml" + + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdServiceAccount(tf, streams) + cmd.Flags().Set("output", outputFormat) + saConfig := SetServiceAccountOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + + local: false, + IOStreams: streams, + } err := saConfig.Complete(tf, cmd, input.args) assert.NoError(t, err) err = saConfig.Run() @@ -375,7 +384,7 @@ func TestServiceAccountValidation(t *testing.T) { } for _, input := range inputs { t.Run(input.name, func(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() tf.Client = &fake.RESTClient{ @@ -385,20 +394,24 @@ func TestServiceAccountValidation(t *testing.T) { return nil, nil }), } - tf.Namespace = "test" - out := bytes.NewBuffer([]byte{}) - cmd := NewCmdServiceAccount(tf, out, out) - cmd.SetOutput(out) - saConfig := &serviceAccountConfig{} + outputFormat := "" + + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdServiceAccount(tf, streams) + + saConfig := &SetServiceAccountOptions{ + PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme), + IOStreams: streams, + } err := saConfig.Complete(tf, cmd, input.args) assert.EqualError(t, err, input.errorString) }) } } -func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser { - return bytesBody([]byte(runtime.EncodeOrDie(codec, obj))) +func objBody(obj runtime.Object) io.ReadCloser { + return bytesBody([]byte(runtime.EncodeOrDie(scheme.DefaultJSONEncoder(), obj))) } func defaultHeader() http.Header { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_subject.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_subject.go index 350db8ef0..4b395b31d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_subject.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_subject.go @@ -18,11 +18,11 @@ package set import ( "fmt" - "io" "strings" "github.com/spf13/cobra" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -30,7 +30,10 @@ import ( "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -49,16 +52,16 @@ var ( kubectl create rolebinding admin --role=admin --user=admin -o yaml --dry-run | kubectl set subject --local -f - --user=foo -o yaml`) ) -type updateSubjects func(existings []rbac.Subject, targets []rbac.Subject) (bool, []rbac.Subject) +type updateSubjects func(existings []rbacv1.Subject, targets []rbacv1.Subject) (bool, []rbacv1.Subject) // SubjectOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags type SubjectOptions struct { + PrintFlags *genericclioptions.PrintFlags + resource.FilenameOptions Infos []*resource.Info - Out io.Writer - Err io.Writer Selector string ContainerSelector string Output string @@ -70,15 +73,23 @@ type SubjectOptions struct { Groups []string ServiceAccounts []string - PrintObject func(obj runtime.Object, out io.Writer) error + namespace string + + PrintObj printers.ResourcePrinterFunc + + genericclioptions.IOStreams } -func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { - options := &SubjectOptions{ - Out: out, - Err: errOut, +func NewSubjectOptions(streams genericclioptions.IOStreams) *SubjectOptions { + return &SubjectOptions{ + PrintFlags: genericclioptions.NewPrintFlags("subjects updated").WithTypeSetter(scheme.Scheme), + + IOStreams: streams, } +} +func NewCmdSubject(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewSubjectOptions(streams) cmd := &cobra.Command{ Use: "subject (-f FILENAME | TYPE NAME) [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", DisableFlagsInUseLine: true, @@ -86,22 +97,22 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co Long: subject_long, Example: subject_example, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.Run(f, addSubjects)) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.Run(addSubjects)) }, } - cmdutil.AddPrinterFlags(cmd) - usage := "the resource to update the subjects" - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) - cmd.Flags().BoolVar(&options.All, "all", options.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") - cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().BoolVar(&options.Local, "local", options.Local, "If true, set subject will NOT contact api-server but run locally.") + o.PrintFlags.AddFlags(cmd) + + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "the resource to update the subjects") + cmd.Flags().BoolVar(&o.All, "all", o.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set subject will NOT contact api-server but run locally.") cmdutil.AddDryRunFlag(cmd) - cmd.Flags().StringArrayVar(&options.Users, "user", []string{}, "Usernames to bind to the role") - cmd.Flags().StringArrayVar(&options.Groups, "group", []string{}, "Groups to bind to the role") - cmd.Flags().StringArrayVar(&options.ServiceAccounts, "serviceaccount", []string{}, "Service accounts to bind to the role") + cmd.Flags().StringArrayVar(&o.Users, "user", o.Users, "Usernames to bind to the role") + cmd.Flags().StringArrayVar(&o.Groups, "group", o.Groups, "Groups to bind to the role") + cmd.Flags().StringArrayVar(&o.ServiceAccounts, "serviceaccount", o.ServiceAccounts, "Service accounts to bind to the role") cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } @@ -109,21 +120,28 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { o.Output = cmdutil.GetFlagString(cmd, "output") o.DryRun = cmdutil.GetDryRunFlag(cmd) - o.PrintObject = func(obj runtime.Object, out io.Writer) error { - return cmdutil.PrintObject(cmd, obj, out) + + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + printer, err := o.PrintFlags.ToPrinter() + if err != nil { + return err } + o.PrintObj = printer.PrintObj - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + var enforceNamespace bool + o.namespace, enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) builder := f.NewBuilder(). - Internal(). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). LocalParam(o.Local). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). + NamespaceParam(o.namespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). IncludeUninitialized(includeUninitialized). Flatten() @@ -175,12 +193,11 @@ func (o *SubjectOptions) Validate() error { return nil } -func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error { - var err error - patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { - subjects := []rbac.Subject{} +func (o *SubjectOptions) Run(fn updateSubjects) error { + patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) { + subjects := []rbacv1.Subject{} for _, user := range sets.NewString(o.Users...).List() { - subject := rbac.Subject{ + subject := rbacv1.Subject{ Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: user, @@ -188,7 +205,7 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error { subjects = append(subjects, subject) } for _, group := range sets.NewString(o.Groups...).List() { - subject := rbac.Subject{ + subject := rbacv1.Subject{ Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: group, @@ -200,12 +217,9 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error { namespace := tokens[0] name := tokens[1] if len(namespace) == 0 { - namespace, _, err = f.DefaultNamespace() - if err != nil { - return nil, err - } + namespace = o.namespace } - subject := rbac.Subject{ + subject := rbacv1.Subject{ Kind: rbac.ServiceAccountKind, Namespace: namespace, Name: name, @@ -213,10 +227,10 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error { subjects = append(subjects, subject) } - transformed, err := updateSubjectForObject(info.Object, subjects, fn) + transformed, err := updateSubjectForObject(obj, subjects, fn) if transformed && err == nil { // TODO: switch UpdatePodSpecForObject to work on v1.PodSpec - return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), info.AsVersioned()) + return runtime.Encode(scheme.DefaultJSONEncoder(), obj) } return nil, err }) @@ -236,36 +250,33 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error { } if o.Local || o.DryRun { - if err := o.PrintObject(info.Object, o.Out); err != nil { - return err + if err := o.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) } continue } - obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { allErrs = append(allErrs, fmt.Errorf("failed to patch subjects to rolebinding: %v\n", err)) continue } - info.Refresh(obj, true) - shortOutput := o.Output == "name" - if len(o.Output) > 0 && !shortOutput { - return o.PrintObject(info.AsVersioned(), o.Out) + if err := o.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) } - cmdutil.PrintSuccess(shortOutput, o.Out, info.Object, false, "subjects updated") } return utilerrors.NewAggregate(allErrs) } //Note: the obj mutates in the function -func updateSubjectForObject(obj runtime.Object, subjects []rbac.Subject, fn updateSubjects) (bool, error) { +func updateSubjectForObject(obj runtime.Object, subjects []rbacv1.Subject, fn updateSubjects) (bool, error) { switch t := obj.(type) { - case *rbac.RoleBinding: + case *rbacv1.RoleBinding: transformed, result := fn(t.Subjects, subjects) t.Subjects = result return transformed, nil - case *rbac.ClusterRoleBinding: + case *rbacv1.ClusterRoleBinding: transformed, result := fn(t.Subjects, subjects) t.Subjects = result return transformed, nil @@ -274,7 +285,7 @@ func updateSubjectForObject(obj runtime.Object, subjects []rbac.Subject, fn upda } } -func addSubjects(existings []rbac.Subject, targets []rbac.Subject) (bool, []rbac.Subject) { +func addSubjects(existings []rbacv1.Subject, targets []rbacv1.Subject) (bool, []rbacv1.Subject) { transformed := false updated := existings for _, item := range targets { @@ -286,7 +297,7 @@ func addSubjects(existings []rbac.Subject, targets []rbac.Subject) (bool, []rbac return transformed, updated } -func contain(slice []rbac.Subject, item rbac.Subject) bool { +func contain(slice []rbacv1.Subject, item rbacv1.Subject) bool { for _, v := range slice { if v == item { return true diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_subject_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_subject_test.go index 8b205095e..33fd75cd7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_subject_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_subject_test.go @@ -20,19 +20,17 @@ import ( "reflect" "testing" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/apis/rbac" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" ) func TestValidate(t *testing.T) { - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - tf.Namespace = "test" - tests := map[string]struct { options *SubjectOptions expectErr bool @@ -65,11 +63,11 @@ func TestValidate(t *testing.T) { options: &SubjectOptions{ Infos: []*resource.Info{ { - Object: &rbac.ClusterRoleBinding{ + Object: &rbacv1.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: "clusterrolebinding", }, - RoleRef: rbac.RoleRef{ + RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole", Name: "role", @@ -87,12 +85,12 @@ func TestValidate(t *testing.T) { options: &SubjectOptions{ Infos: []*resource.Info{ { - Object: &rbac.RoleBinding{ + Object: &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: "rolebinding", Namespace: "one", }, - RoleRef: rbac.RoleRef{ + RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole", Name: "role", @@ -123,13 +121,13 @@ func TestUpdateSubjectForObject(t *testing.T) { tests := []struct { Name string obj runtime.Object - subjects []rbac.Subject - expected []rbac.Subject + subjects []rbacv1.Subject + expected []rbacv1.Subject wantErr bool }{ { Name: "invalid object type", - obj: &rbac.Role{ + obj: &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ Name: "role", Namespace: "one", @@ -139,12 +137,12 @@ func TestUpdateSubjectForObject(t *testing.T) { }, { Name: "add resource with users in rolebinding", - obj: &rbac.RoleBinding{ + obj: &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: "rolebinding", Namespace: "one", }, - Subjects: []rbac.Subject{ + Subjects: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "User", @@ -152,7 +150,7 @@ func TestUpdateSubjectForObject(t *testing.T) { }, }, }, - subjects: []rbac.Subject{ + subjects: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "User", @@ -164,7 +162,7 @@ func TestUpdateSubjectForObject(t *testing.T) { Name: "b", }, }, - expected: []rbac.Subject{ + expected: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "User", @@ -180,12 +178,12 @@ func TestUpdateSubjectForObject(t *testing.T) { }, { Name: "add resource with groups in rolebinding", - obj: &rbac.RoleBinding{ + obj: &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: "rolebinding", Namespace: "one", }, - Subjects: []rbac.Subject{ + Subjects: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "Group", @@ -193,7 +191,7 @@ func TestUpdateSubjectForObject(t *testing.T) { }, }, }, - subjects: []rbac.Subject{ + subjects: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "Group", @@ -205,7 +203,7 @@ func TestUpdateSubjectForObject(t *testing.T) { Name: "b", }, }, - expected: []rbac.Subject{ + expected: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "Group", @@ -221,12 +219,12 @@ func TestUpdateSubjectForObject(t *testing.T) { }, { Name: "add resource with serviceaccounts in rolebinding", - obj: &rbac.RoleBinding{ + obj: &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: "rolebinding", Namespace: "one", }, - Subjects: []rbac.Subject{ + Subjects: []rbacv1.Subject{ { Kind: "ServiceAccount", Namespace: "one", @@ -234,7 +232,7 @@ func TestUpdateSubjectForObject(t *testing.T) { }, }, }, - subjects: []rbac.Subject{ + subjects: []rbacv1.Subject{ { Kind: "ServiceAccount", Namespace: "one", @@ -246,7 +244,7 @@ func TestUpdateSubjectForObject(t *testing.T) { Name: "b", }, }, - expected: []rbac.Subject{ + expected: []rbacv1.Subject{ { Kind: "ServiceAccount", Namespace: "one", @@ -262,11 +260,11 @@ func TestUpdateSubjectForObject(t *testing.T) { }, { Name: "add resource with serviceaccounts in clusterrolebinding", - obj: &rbac.ClusterRoleBinding{ + obj: &rbacv1.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: "clusterrolebinding", }, - Subjects: []rbac.Subject{ + Subjects: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "User", @@ -279,14 +277,14 @@ func TestUpdateSubjectForObject(t *testing.T) { }, }, }, - subjects: []rbac.Subject{ + subjects: []rbacv1.Subject{ { Kind: "ServiceAccount", Namespace: "one", Name: "a", }, }, - expected: []rbac.Subject{ + expected: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "User", @@ -312,11 +310,11 @@ func TestUpdateSubjectForObject(t *testing.T) { } want := tt.expected - var got []rbac.Subject + var got []rbacv1.Subject switch t := tt.obj.(type) { - case *rbac.RoleBinding: + case *rbacv1.RoleBinding: got = t.Subjects - case *rbac.ClusterRoleBinding: + case *rbacv1.ClusterRoleBinding: got = t.Subjects } if !reflect.DeepEqual(got, want) { @@ -330,14 +328,14 @@ func TestUpdateSubjectForObject(t *testing.T) { func TestAddSubject(t *testing.T) { tests := []struct { Name string - existing []rbac.Subject - subjects []rbac.Subject - expected []rbac.Subject + existing []rbacv1.Subject + subjects []rbacv1.Subject + expected []rbacv1.Subject wantChange bool }{ { Name: "add resource with users", - existing: []rbac.Subject{ + existing: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "User", @@ -349,14 +347,14 @@ func TestAddSubject(t *testing.T) { Name: "b", }, }, - subjects: []rbac.Subject{ + subjects: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "User", Name: "a", }, }, - expected: []rbac.Subject{ + expected: []rbacv1.Subject{ { APIGroup: "rbac.authorization.k8s.io", Kind: "User", @@ -372,7 +370,7 @@ func TestAddSubject(t *testing.T) { }, { Name: "add resource with serviceaccounts", - existing: []rbac.Subject{ + existing: []rbacv1.Subject{ { Kind: "ServiceAccount", Namespace: "one", @@ -384,14 +382,14 @@ func TestAddSubject(t *testing.T) { Name: "b", }, }, - subjects: []rbac.Subject{ + subjects: []rbacv1.Subject{ { Kind: "ServiceAccount", Namespace: "two", Name: "a", }, }, - expected: []rbac.Subject{ + expected: []rbacv1.Subject{ { Kind: "ServiceAccount", Namespace: "one", @@ -413,7 +411,7 @@ func TestAddSubject(t *testing.T) { } for _, tt := range tests { changed := false - got := []rbac.Subject{} + got := []rbacv1.Subject{} if changed, got = addSubjects(tt.existing, tt.subjects); (changed != false) != tt.wantChange { t.Errorf("%q. addSubjects() changed = %v, wantChange = %v", tt.Name, changed, tt.wantChange) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_test.go index 1c7b42db0..70fd92f7e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/set/set_test.go @@ -17,20 +17,17 @@ limitations under the License. package set import ( - "bytes" "testing" "github.com/spf13/cobra" clientcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "os" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestLocalAndDryRunFlags(t *testing.T) { - out := &bytes.Buffer{} - errout := &bytes.Buffer{} - f := clientcmdutil.NewFactory(nil) - setCmd := NewCmdSet(f, os.Stdin, out, errout) + f := clientcmdutil.NewFactory(genericclioptions.NewTestConfigFlags()) + setCmd := NewCmdSet(f, genericclioptions.NewTestIOStreamsDiscard()) ensureLocalAndDryRunFlagsOnChildren(t, setCmd, "") } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/taint.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/taint.go index e48d301d9..45b6ab0e7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/taint.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/taint.go @@ -17,29 +17,35 @@ limitations under the License. package cmd import ( + "encoding/json" "fmt" - "io" "strings" - "encoding/json" - "github.com/golang/glog" "github.com/spf13/cobra" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/util/validation" - "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" taintutils "k8s.io/kubernetes/pkg/util/taints" ) // TaintOptions have the data required to perform the taint operation type TaintOptions struct { + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) + resources []string taintsToAdd []v1.Taint taintsToRemove []v1.Taint @@ -47,9 +53,10 @@ type TaintOptions struct { selector string overwrite bool all bool - f cmdutil.Factory - out io.Writer - cmd *cobra.Command + + ClientForMapping func(*meta.RESTMapping) (resource.RESTClient, error) + + genericclioptions.IOStreams } var ( @@ -78,11 +85,13 @@ var ( kubectl taint node -l myLabel=X dedicated=foo:PreferNoSchedule`)) ) -func NewCmdTaint(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &TaintOptions{} +func NewCmdTaint(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + options := &TaintOptions{ + PrintFlags: genericclioptions.NewPrintFlags("tainted").WithTypeSetter(scheme.Scheme), + IOStreams: streams, + } validArgs := []string{"node"} - argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ Use: "taint NODE NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_N", @@ -91,7 +100,7 @@ func NewCmdTaint(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: fmt.Sprintf(taintLong, validation.DNS1123SubdomainMaxLength, validation.LabelValueMaxLength), Example: taintExample, Run: func(cmd *cobra.Command, args []string) { - if err := options.Complete(f, out, cmd, args); err != nil { + if err := options.Complete(f, cmd, args); err != nil { cmdutil.CheckErr(err) } if err := options.Validate(); err != nil { @@ -101,13 +110,12 @@ func NewCmdTaint(f cmdutil.Factory, out io.Writer) *cobra.Command { cmdutil.CheckErr(err) } }, - ValidArgs: validArgs, - ArgAliases: argAliases, + ValidArgs: validArgs, } - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) + options.PrintFlags.AddFlags(cmd) + + cmdutil.AddValidateFlags(cmd) cmd.Flags().StringVarP(&options.selector, "selector", "l", options.selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().BoolVar(&options.overwrite, "overwrite", options.overwrite, "If true, allow taints to be overwritten, otherwise reject taint updates that overwrite existing taints.") cmd.Flags().BoolVar(&options.all, "all", options.all, "Select all nodes in the cluster") @@ -115,8 +123,8 @@ func NewCmdTaint(f cmdutil.Factory, out io.Writer) *cobra.Command { } // Complete adapts from the command line args and factory to the data required. -func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) { - namespace, _, err := f.DefaultNamespace() +func (o *TaintOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) (err error) { + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -140,6 +148,11 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Com } } + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + return o.PrintFlags.ToPrinter() + } + if len(o.resources) < 1 { return fmt.Errorf("one or more resources must be specified as ") } @@ -151,7 +164,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Com return cmdutil.UsageErrorf(cmd, err.Error()) } o.builder = f.NewBuilder(). - Internal(). + WithScheme(legacyscheme.Scheme). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace() if o.selector != "" { @@ -166,9 +179,8 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Com o.builder = o.builder.LabelSelectorParam(o.selector). Flatten(). Latest() - o.f = f - o.out = out - o.cmd = cmd + + o.ClientForMapping = f.ClientForMapping return nil } @@ -192,7 +204,7 @@ func (o TaintOptions) validateFlags() error { // Validate checks to the TaintOptions to see if there is sufficient information run the command. func (o TaintOptions) Validate() error { resourceType := strings.ToLower(o.resources[0]) - validResources, isValidResource := append(kubectl.ResourceAliases([]string{"node"}), "node"), false + validResources, isValidResource := []string{"node", "nodes"}, false for _, validResource := range validResources { if resourceType == validResource { isValidResource = true @@ -234,9 +246,10 @@ func (o TaintOptions) RunTaint() error { return err } - obj, err := info.Mapping.ConvertToVersion(info.Object, info.Mapping.GroupVersionKind.GroupVersion()) + obj, err := legacyscheme.Scheme.ConvertToVersion(info.Object, v1.SchemeGroupVersion) if err != nil { - return err + glog.V(1).Info(err) + return fmt.Errorf("object was not a node.v1.: %T", info.Object) } name, namespace := info.Name, info.Namespace oldData, err := json.Marshal(obj) @@ -258,7 +271,7 @@ func (o TaintOptions) RunTaint() error { } mapping := info.ResourceMapping() - client, err := o.f.ClientForMapping(mapping) + client, err := o.ClientForMapping(mapping) if err != nil { return err } @@ -273,14 +286,13 @@ func (o TaintOptions) RunTaint() error { if err != nil { return err } + outputObj = cmdutil.AsDefaultVersionedOrOriginal(outputObj, mapping) - outputFormat := cmdutil.GetFlagString(o.cmd, "output") - if outputFormat != "" { - return cmdutil.PrintObject(o.cmd, outputObj, o.out) + printer, err := o.ToPrinter(operation) + if err != nil { + return err } - - cmdutil.PrintSuccess(false, o.out, info.Object, false, operation) - return nil + return printer.PrintObj(outputObj, o.Out) }) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/taint_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/taint_test.go index 5fb814edb..bf5ec3b77 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/taint_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/taint_test.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "bytes" "io/ioutil" "net/http" "reflect" @@ -32,6 +31,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -45,8 +45,7 @@ func generateNodeAndTaintedNode(oldTaints []v1.Taint, newTaints []v1.Taint) (*v1 CreationTimestamp: metav1.Time{Time: time.Now()}, }, Spec: v1.NodeSpec{ - ExternalID: "node-name", - Taints: oldTaints, + Taints: oldTaints, }, Status: v1.NodeStatus{}, } @@ -243,7 +242,7 @@ func TestTaint(t *testing.T) { tf := cmdtesting.NewTestFactory() defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -303,8 +302,7 @@ func TestTaint(t *testing.T) { } tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdTaint(tf, buf) + cmd := NewCmdTaint(tf, genericclioptions.NewTestIOStreamsDiscard()) saw_fatal := false func() { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/templates/templater.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/templates/templater.go index 27b76dc42..0892f0403 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/templates/templater.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/templates/templater.go @@ -145,7 +145,7 @@ func (t *templater) cmdGroupsString(c *cobra.Command) string { for _, cmdGroup := range t.cmdGroups(c, c.Commands()) { cmds := []string{cmdGroup.Message} for _, cmd := range cmdGroup.Commands { - if cmd.Runnable() { + if cmd.IsAvailableCommand() { cmds = append(cmds, " "+rpad(cmd.Name(), cmd.NamePadding())+" "+cmd.Short) } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/record_editor.sh b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/record_editor.sh index 0a7d4c376..a2ba2d6fb 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/record_editor.sh +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/record_editor.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/record_testcase.sh b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/record_testcase.sh index 9a51c351c..1181912dc 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/record_testcase.sh +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/record_testcase.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/test_editor.sh b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/test_editor.sh index 268a8078c..387e255d0 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/test_editor.sh +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/test_editor.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-list-fail/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-list-fail/test.yaml index 56b93abd6..e1e80d5d1 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-list-fail/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-list-fail/test.yaml @@ -5,8 +5,8 @@ args: - service/svc1 namespace: "myproject" expectedStdout: -- configmap "cm1" edited -- service "svc1" edited +- configmap/cm1 edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-list/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-list/test.yaml index ef9f5588d..9236dc984 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-list/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-list/test.yaml @@ -5,8 +5,8 @@ args: - service/svc1 namespace: "myproject" expectedStdout: -- configmap "cm1" edited -- service "svc1" edited +- configmap/cm1 edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-syntax-error/2.original b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-syntax-error/2.original index d17734396..601ea3bda 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-syntax-error/2.original +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-syntax-error/2.original @@ -1,7 +1,7 @@ # Please edit the 'last-applied-configuration' annotations below. # Lines beginning with a '#' will be ignored, and an empty file will abort the edit. # -# The edited file had a syntax error: error converting YAML to JSON: yaml: line 12: could not find expected ':' +# The edited file had a syntax error: error parsing edited-file: error converting YAML to JSON: yaml: line 12: could not find expected ':' # kind: Service metadata: diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-syntax-error/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-syntax-error/test.yaml index f500dc65e..df1a5db83 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-syntax-error/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied-syntax-error/test.yaml @@ -4,7 +4,7 @@ args: - service/svc1 namespace: myproject expectedStdout: -- "service \"svc1\" edited" +- "service/svc1 edited" expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied/test.yaml index a284da093..73d8fd98b 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-apply-edit-last-applied/test.yaml @@ -6,7 +6,7 @@ args: outputFormat: yaml namespace: myproject expectedStdout: -- service "svc1" edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-create-list-error/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-create-list-error/test.yaml index 5663b94d9..e0bfe91f6 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-create-list-error/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-create-list-error/test.yaml @@ -3,7 +3,7 @@ mode: create filename: "svc.yaml" namespace: "edit-test" expectedStdout: -- "service \"svc1\" created" +- "service/svc1 created" expectedStderr: - "\"svc2\" is invalid" expectedExitCode: 1 diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-create-list/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-create-list/test.yaml index 0b75c7ffe..a3198e791 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-create-list/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-create-list/test.yaml @@ -3,8 +3,8 @@ mode: create filename: "svc.yaml" namespace: "edit-test" expectedStdout: -- service "svc1" created -- service "svc2" created +- service/svc1 created +- service/svc2 created expectedExitCode: 0 steps: - type: edit diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-edit-error-reedit/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-edit-error-reedit/test.yaml index 8ead26707..0cc3a3705 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-edit-error-reedit/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-edit-error-reedit/test.yaml @@ -5,7 +5,7 @@ args: - svc1 namespace: edit-test expectedStdout: -- service "svc1" edited +- service/svc1 edited expectedStderr: - "error: services \"svc1\" is invalid" expectedExitCode: 0 diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/test.yaml index 0b0f92f97..1a6e13c50 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/test.yaml @@ -11,7 +11,7 @@ outputPatch: "true" namespace: edit-test expectedStdout: - 'Patch: {"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":\"2017-02-27T19:40:53Z\",\"labels\":{\"app\":\"svc1\",\"new-label\":\"new-value\"},\"name\":\"svc1\",\"namespace\":\"edit-test\",\"resourceVersion\":\"670\",\"selfLink\":\"/api/v1/namespaces/edit-test/services/svc1\",\"uid\":\"a6c11186-fd24-11e6-b53c-480fcf4a5275\"},\"spec\":{\"clusterIP\":\"10.0.0.204\",\"ports\":[{\"name\":\"80\",\"port\":80,\"protocol\":\"TCP\",\"targetPort\":80}],\"selector\":{\"app\":\"svc1\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}\n"},"labels":{"new-label":"new-value"}}}' -- service "svc1" edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-errors/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-errors/test.yaml index 03f6ca904..a55cff618 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-errors/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-errors/test.yaml @@ -4,8 +4,8 @@ args: - configmaps,services namespace: "edit-test" expectedStdout: -- configmap "cm1" edited -- service "svc1" edited +- configmap/cm1 edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/3.request b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/3.request index c609f20a9..ba542f24b 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/3.request +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/3.request @@ -1,10 +1,5 @@ { "data": { "new-data3": "newivalue" - }, - "metadata": { - "annotations": { - "kubernetes.io/change-cause": "edit test cmd invocation" - } } } \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/4.request b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/4.request index 3520e4699..572a71819 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/4.request +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/4.request @@ -1,8 +1,5 @@ { "metadata": { - "annotations": { - "kubernetes.io/change-cause": "edit test cmd invocation" - }, "labels": { "new-label2": "foo2" } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/test.yaml index 1ee9e35fa..c4fd1ae17 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list-record/test.yaml @@ -5,8 +5,8 @@ args: - service/svc1 namespace: "edit-test" expectedStdout: -- configmap "cm1" edited -- service "svc1" edited +- configmap/cm1 edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list/test.yaml index 1ee9e35fa..c4fd1ae17 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-list/test.yaml @@ -5,8 +5,8 @@ args: - service/svc1 namespace: "edit-test" expectedStdout: -- configmap "cm1" edited -- service "svc1" edited +- configmap/cm1 edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-not-update-annotation/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-not-update-annotation/test.yaml index 01315f66c..a78dc296a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-not-update-annotation/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-not-update-annotation/test.yaml @@ -9,7 +9,7 @@ args: saveConfig: "false" namespace: edit-test expectedStdout: -- service "svc1" edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-schemaless-list/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-schemaless-list/test.yaml index 3aa57d07f..726e74735 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-schemaless-list/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-schemaless-list/test.yaml @@ -6,9 +6,9 @@ args: - bars/test2 namespace: default expectedStdout: -- "service \"kubernetes\" edited" -- "bar.company.com \"test\" edited" -- "bar.company.com \"test2\" edited" +- "service/kubernetes edited" +- "bar.company.com/test edited" +- "bar.company.com/test2 edited" expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-single-service/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-single-service/test.yaml index 5b48baa96..f1f66de23 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-single-service/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-single-service/test.yaml @@ -8,7 +8,7 @@ args: - svc1 namespace: edit-test expectedStdout: -- service "svc1" edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-syntax-error/2.original b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-syntax-error/2.original index 85da34d23..a229c98f0 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-syntax-error/2.original +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-syntax-error/2.original @@ -2,7 +2,7 @@ # and an empty file will abort the edit. If an error occurs while saving this file will be # reopened with the relevant failures. # -# The edited file had a syntax error: error converting YAML to JSON: yaml: line 17: could not find expected ':' +# The edited file had a syntax error: error parsing edited-file: error converting YAML to JSON: yaml: line 17: could not find expected ':' # apiVersion: v1 kind: Service diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-syntax-error/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-syntax-error/test.yaml index a37c25139..636557139 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-syntax-error/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-syntax-error/test.yaml @@ -4,7 +4,7 @@ args: - service/kubernetes namespace: default expectedStdout: -- "service \"kubernetes\" edited" +- "service/kubernetes edited" expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-unknown-field-known-group-kind/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-unknown-field-known-group-kind/test.yaml index fc099fcae..5b119e611 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-unknown-field-known-group-kind/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-unknown-field-known-group-kind/test.yaml @@ -4,7 +4,7 @@ args: - storageclasses.v1beta1.storage.k8s.io/foo namespace: default expectedStdout: -- "storageclass.storage.k8s.io \"foo\" edited" +- "storageclass.storage.k8s.io/foo edited" expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-unknown-version-known-group-kind/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-unknown-version-known-group-kind/test.yaml index cfc8dccf3..b0c78e05c 100755 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-unknown-version-known-group-kind/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-unknown-version-known-group-kind/test.yaml @@ -4,7 +4,7 @@ args: - storageclasses.v0.storage.k8s.io/foo namespace: default expectedStdout: -- "storageclass.storage.k8s.io \"foo\" edited" +- "storageclass.storage.k8s.io/foo edited" expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-update-annotation/test.yaml b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-update-annotation/test.yaml index 928c10642..1e01c8369 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-update-annotation/test.yaml +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testdata/edit/testcase-update-annotation/test.yaml @@ -9,7 +9,7 @@ args: saveConfig: "true" namespace: edit-test expectedStdout: -- service "svc1" edited +- service/svc1 edited expectedExitCode: 0 steps: - type: request diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/BUILD index 23f686de7..e6b59fa7f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/BUILD @@ -1,7 +1,4 @@ -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) +load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", @@ -10,33 +7,31 @@ go_library( "zz_generated.deepcopy.go", ], importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/testing", - visibility = [ - "//build/visible_to:pkg_kubectl_cmd_testing_CONSUMERS", - ], + visibility = ["//build/visible_to:pkg_kubectl_cmd_testing_CONSUMERS"], deps = [ "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/kubectl:go_default_library", - "//pkg/kubectl/categories:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/cmd/util/openapi/testing:go_default_library", - "//pkg/kubectl/resource:go_default_library", - "//pkg/kubectl/scheme:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/validation:go_default_library", - "//pkg/printers:go_default_library", - "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", + "//vendor/k8s.io/client-go/dynamic:go_default_library", + "//vendor/k8s.io/client-go/dynamic/fake:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest/fake:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", + "//vendor/k8s.io/client-go/scale:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", ], @@ -46,13 +41,12 @@ filegroup( name = "package-srcs", srcs = glob(["**"]), tags = ["automanaged"], + visibility = ["//build/visible_to:pkg_kubectl_cmd_testing_CONSUMERS"], ) filegroup( name = "all-srcs", srcs = [":package-srcs"], tags = ["automanaged"], - visibility = [ - "//build/visible_to:pkg_kubectl_cmd_testing_CONSUMERS", - ], + visibility = ["//build/visible_to:pkg_kubectl_cmd_testing_CONSUMERS"], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/fake.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/fake.go index 751165d2e..12d876626 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/fake.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/fake.go @@ -25,32 +25,31 @@ import ( "path/filepath" "time" - "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/client-go/discovery" + "k8s.io/client-go/dynamic" + fakedynamic "k8s.io/client-go/dynamic/fake" "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" + "k8s.io/client-go/restmapper" + scaleclient "k8s.io/client-go/scale" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/kubernetes/pkg/api/legacyscheme" - api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/categories" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" openapitesting "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/kubectl/scheme" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/validation" - "k8s.io/kubernetes/pkg/printers" ) // +k8s:deepcopy-gen=true @@ -178,7 +177,7 @@ func versionErrIfFalse(b bool) error { return versionErr } -var ValidVersion = legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.Version +var ValidVersion = "v1" var InternalGV = schema.GroupVersion{Group: "apitest", Version: runtime.APIVersionInternal} var UnlikelyGV = schema.GroupVersion{Group: "apitest", Version: "unlikelyversion"} var ValidVersionGV = schema.GroupVersion{Group: "apitest", Version: ValidVersion} @@ -202,12 +201,7 @@ func AddToScheme(scheme *runtime.Scheme) (meta.RESTMapper, runtime.Codec) { codecs := serializer.NewCodecFactory(scheme) codec := codecs.LegacyCodec(UnlikelyGV) - mapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{UnlikelyGV, ValidVersionGV}, func(version schema.GroupVersion) (*meta.VersionInterfaces, error) { - return &meta.VersionInterfaces{ - ObjectConvertor: scheme, - MetadataAccessor: meta.NewAccessor(), - }, versionErrIfFalse(version == ValidVersionGV || version == UnlikelyGV) - }) + mapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{UnlikelyGV, ValidVersionGV}) for _, gv := range []schema.GroupVersion{UnlikelyGV, ValidVersionGV} { for kind := range scheme.KnownTypes(gv) { gvk := gv.WithKind(kind) @@ -238,71 +232,70 @@ func (d *fakeCachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList type TestFactory struct { cmdutil.Factory + kubeConfigFlags *genericclioptions.TestConfigFlags + Client kubectl.RESTClient + ScaleGetter scaleclient.ScalesGetter UnstructuredClient kubectl.RESTClient - DescriberVal printers.Describer - Namespace string ClientConfigVal *restclient.Config - CommandVal string + FakeDynamicClient *fakedynamic.FakeDynamicClient tempConfigFile *os.File - UnstructuredClientForMappingFunc func(mapping *meta.RESTMapping) (resource.RESTClient, error) + UnstructuredClientForMappingFunc resource.FakeClientFunc OpenAPISchemaFunc func() (openapi.Resources, error) } func NewTestFactory() *TestFactory { // specify an optionalClientConfig to explicitly use in testing // to avoid polluting an existing user config. - config, configFile := defaultFakeClientConfig() - return &TestFactory{ - Factory: cmdutil.NewFactory(config), - tempConfigFile: configFile, - } -} - -func (f *TestFactory) Cleanup() { - if f.tempConfigFile == nil { - return - } - - os.Remove(f.tempConfigFile.Name()) -} - -func defaultFakeClientConfig() (clientcmd.ClientConfig, *os.File) { - loadingRules, tmpFile, err := newDefaultFakeClientConfigLoadingRules() + tmpFile, err := ioutil.TempFile("", "cmdtests_temp") if err != nil { panic(fmt.Sprintf("unable to create a fake client config: %v", err)) } + loadingRules := &clientcmd.ClientConfigLoadingRules{ + Precedence: []string{tmpFile.Name()}, + MigrationRules: map[string]string{}, + } + overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmdapi.Cluster{Server: "http://localhost:8080"}} fallbackReader := bytes.NewBuffer([]byte{}) - clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, fallbackReader) - return clientConfig, tmpFile -} -func newDefaultFakeClientConfigLoadingRules() (*clientcmd.ClientConfigLoadingRules, *os.File, error) { - tmpFile, err := ioutil.TempFile("", "cmdtests_temp") + configFlags := genericclioptions.NewTestConfigFlags(). + WithClientConfig(clientConfig). + WithRESTMapper(testRESTMapper()) + + restConfig, err := clientConfig.ClientConfig() if err != nil { - return nil, nil, err + panic(fmt.Sprintf("unable to create a fake restclient config: %v", err)) } - return &clientcmd.ClientConfigLoadingRules{ - Precedence: []string{tmpFile.Name()}, - MigrationRules: map[string]string{}, - }, tmpFile, nil + return &TestFactory{ + Factory: cmdutil.NewFactory(configFlags), + kubeConfigFlags: configFlags, + FakeDynamicClient: fakedynamic.NewSimpleDynamicClient(legacyscheme.Scheme), + tempConfigFile: tmpFile, + + ClientConfigVal: restConfig, + } } -func (f *TestFactory) CategoryExpander() categories.CategoryExpander { - return categories.LegacyCategoryExpander +func (f *TestFactory) WithNamespace(ns string) *TestFactory { + f.kubeConfigFlags.WithNamespace(ns) + return f } -func (f *TestFactory) ClientConfig() (*restclient.Config, error) { - return f.ClientConfigVal, nil +func (f *TestFactory) Cleanup() { + if f.tempConfigFile == nil { + return + } + + os.Remove(f.tempConfigFile.Name()) } -func (f *TestFactory) BareClientConfig() (*restclient.Config, error) { +func (f *TestFactory) ToRESTConfig() (*restclient.Config, error) { return f.ClientConfigVal, nil } @@ -312,23 +305,15 @@ func (f *TestFactory) ClientForMapping(mapping *meta.RESTMapping) (resource.REST func (f *TestFactory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { if f.UnstructuredClientForMappingFunc != nil { - return f.UnstructuredClientForMappingFunc(mapping) + return f.UnstructuredClientForMappingFunc(mapping.GroupVersionKind.GroupVersion()) } return f.UnstructuredClient, nil } -func (f *TestFactory) Describer(*meta.RESTMapping) (printers.Describer, error) { - return f.DescriberVal, nil -} - func (f *TestFactory) Validator(validate bool) (validation.Schema, error) { return validation.NullSchema{}, nil } -func (f *TestFactory) DefaultNamespace() (string, bool, error) { - return f.Namespace, false, nil -} - func (f *TestFactory) OpenAPISchema() (openapi.Resources, error) { if f.OpenAPISchemaFunc != nil { return f.OpenAPISchemaFunc() @@ -336,28 +321,22 @@ func (f *TestFactory) OpenAPISchema() (openapi.Resources, error) { return openapitesting.EmptyResources{}, nil } -func (f *TestFactory) Command(*cobra.Command, bool) string { - return f.CommandVal -} - func (f *TestFactory) NewBuilder() *resource.Builder { - mapper, typer := f.Object() - - return resource.NewBuilder( - &resource.Mapper{ - RESTMapper: mapper, - ObjectTyper: typer, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - Decoder: cmdutil.InternalVersionDecoder(), - }, - &resource.Mapper{ - RESTMapper: mapper, - ObjectTyper: typer, - ClientMapper: resource.ClientMapperFunc(f.UnstructuredClientForMapping), - Decoder: unstructured.UnstructuredJSONScheme, + mapper, err := f.ToRESTMapper() + + return resource.NewFakeBuilder( + func(version schema.GroupVersion) (resource.RESTClient, error) { + if f.UnstructuredClientForMappingFunc != nil { + return f.UnstructuredClientForMappingFunc(version) + } + if f.UnstructuredClient != nil { + return f.UnstructuredClient, nil + } + return f.Client, nil }, - f.CategoryExpander(), - ) + mapper, + resource.FakeCategoryExpander, + ).AddError(err) } func (f *TestFactory) KubernetesClientSet() (*kubernetes.Clientset, error) { @@ -407,6 +386,13 @@ func (f *TestFactory) ClientSet() (internalclientset.Interface, error) { return clientset, nil } +func (f *TestFactory) DynamicClient() (dynamic.Interface, error) { + if f.FakeDynamicClient != nil { + return f.FakeDynamicClient, nil + } + return f.Factory.DynamicClient() +} + func (f *TestFactory) RESTClient() (*restclient.RESTClient, error) { // Swap out the HTTP client out of the client with the fake's version. fakeClient := f.Client.(*fake.RESTClient) @@ -420,71 +406,40 @@ func (f *TestFactory) RESTClient() (*restclient.RESTClient, error) { func (f *TestFactory) DiscoveryClient() (discovery.CachedDiscoveryInterface, error) { fakeClient := f.Client.(*fake.RESTClient) - discoveryClient := discovery.NewDiscoveryClientForConfigOrDie(f.ClientConfigVal) - discoveryClient.RESTClient().(*restclient.RESTClient).Client = fakeClient.Client cacheDir := filepath.Join("", ".kube", "cache", "discovery") - return cmdutil.NewCachedDiscoveryClient(discoveryClient, cacheDir, time.Duration(10*time.Minute)), nil -} + cachedClient, err := discovery.NewCachedDiscoveryClientForConfig(f.ClientConfigVal, cacheDir, "", time.Duration(10*time.Minute)) + if err != nil { + return nil, err + } + cachedClient.RESTClient().(*restclient.RESTClient).Client = fakeClient.Client -func (f *TestFactory) ClientSetForVersion(requiredVersion *schema.GroupVersion) (internalclientset.Interface, error) { - return f.ClientSet() + return cachedClient, nil } -func (f *TestFactory) Object() (meta.RESTMapper, runtime.ObjectTyper) { +func testRESTMapper() meta.RESTMapper { groupResources := testDynamicResources() - mapper := discovery.NewRESTMapper( - groupResources, - meta.InterfacesForUnstructuredConversion(func(version schema.GroupVersion) (*meta.VersionInterfaces, error) { - switch version { - // provide typed objects for these two versions - case ValidVersionGV, UnlikelyGV: - return &meta.VersionInterfaces{ - ObjectConvertor: scheme.Scheme, - MetadataAccessor: meta.NewAccessor(), - }, nil - // otherwise fall back to the legacy scheme - default: - return legacyscheme.Registry.InterfacesFor(version) - } - }), - ) + mapper := restmapper.NewDiscoveryRESTMapper(groupResources) // for backwards compatibility with existing tests, allow rest mappings from the scheme to show up // TODO: make this opt-in? mapper = meta.FirstHitRESTMapper{ MultiRESTMapper: meta.MultiRESTMapper{ mapper, - legacyscheme.Registry.RESTMapper(), + testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme), }, } - // TODO: should probably be the external scheme - typer := discovery.NewUnstructuredObjectTyper(groupResources, legacyscheme.Scheme) fakeDs := &fakeCachedDiscoveryClient{} - expander := cmdutil.NewShortcutExpander(mapper, fakeDs) - return expander, typer + expander := restmapper.NewShortcutExpander(mapper, fakeDs) + return expander } -func (f *TestFactory) LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) { - c, err := f.ClientSet() - if err != nil { - panic(err) - } - - switch t := object.(type) { - case *api.Pod: - opts, ok := options.(*api.PodLogOptions) - if !ok { - return nil, errors.New("provided options object is not a PodLogOptions") - } - return c.Core().Pods(f.Namespace).GetLogs(t.Name, opts), nil - default: - return nil, fmt.Errorf("cannot get the logs from %T", object) - } +func (f *TestFactory) ScaleClient() (scaleclient.ScalesGetter, error) { + return f.ScaleGetter, nil } -func testDynamicResources() []*discovery.APIGroupResources { - return []*discovery.APIGroupResources{ +func testDynamicResources() []*restmapper.APIGroupResources { + return []*restmapper.APIGroupResources{ { Group: metav1.APIGroup{ Versions: []metav1.GroupVersionForDiscovery{ diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/zz_generated.deepcopy.go index 03fe349f0..4c20a5aa6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/testing/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top.go index 608c0ae7c..c8abeee22 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top.go @@ -17,8 +17,6 @@ limitations under the License. package cmd import ( - "io" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/util/i18n" @@ -26,6 +24,7 @@ import ( "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) var ( @@ -40,17 +39,17 @@ var ( This command requires Heapster to be correctly configured and working on the server. `)) ) -func NewCmdTop(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { +func NewCmdTop(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "top", Short: i18n.T("Display Resource (CPU/Memory/Storage) usage."), Long: topLong, - Run: cmdutil.DefaultSubCommandRun(errOut), + Run: cmdutil.DefaultSubCommandRun(streams.ErrOut), } // create subcommands - cmd.AddCommand(NewCmdTopNode(f, nil, out)) - cmd.AddCommand(NewCmdTopPod(f, nil, out)) + cmd.AddCommand(NewCmdTopNode(f, nil, streams)) + cmd.AddCommand(NewCmdTopPod(f, nil, streams)) return cmd } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_node.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_node.go index 624be6633..5922e78fa 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_node.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_node.go @@ -18,7 +18,6 @@ package cmd import ( "errors" - "io" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -29,6 +28,7 @@ import ( corev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/metricsutil" "k8s.io/kubernetes/pkg/kubectl/util/i18n" metricsapi "k8s.io/metrics/pkg/apis/metrics" @@ -46,6 +46,8 @@ type TopNodeOptions struct { Printer *metricsutil.TopCmdPrinter DiscoveryClient discovery.DiscoveryInterface MetricsClient metricsclientset.Interface + + genericclioptions.IOStreams } type HeapsterTopOptions struct { @@ -89,9 +91,11 @@ var ( kubectl top node NODE_NAME`)) ) -func NewCmdTopNode(f cmdutil.Factory, options *TopNodeOptions, out io.Writer) *cobra.Command { - if options == nil { - options = &TopNodeOptions{} +func NewCmdTopNode(f cmdutil.Factory, o *TopNodeOptions, streams genericclioptions.IOStreams) *cobra.Command { + if o == nil { + o = &TopNodeOptions{ + IOStreams: streams, + } } cmd := &cobra.Command{ @@ -101,24 +105,24 @@ func NewCmdTopNode(f cmdutil.Factory, options *TopNodeOptions, out io.Writer) *c Long: topNodeLong, Example: topNodeExample, Run: func(cmd *cobra.Command, args []string) { - if err := options.Complete(f, cmd, args, out); err != nil { + if err := o.Complete(f, cmd, args); err != nil { cmdutil.CheckErr(err) } - if err := options.Validate(); err != nil { + if err := o.Validate(); err != nil { cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err)) } - if err := options.RunTopNode(); err != nil { + if err := o.RunTopNode(); err != nil { cmdutil.CheckErr(err) } }, Aliases: []string{"nodes", "no"}, } - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - options.HeapsterOptions.Bind(cmd.Flags()) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + o.HeapsterOptions.Bind(cmd.Flags()) return cmd } -func (o *TopNodeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer) error { +func (o *TopNodeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { if len(args) == 1 { o.ResourceName = args[0] } else if len(args) > 1 { @@ -132,7 +136,7 @@ func (o *TopNodeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] o.DiscoveryClient = clientset.DiscoveryClient - config, err := f.ClientConfig() + config, err := f.ToRESTConfig() if err != nil { return err } @@ -144,7 +148,7 @@ func (o *TopNodeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] o.NodeClient = clientset.CoreV1() o.Client = metricsutil.NewHeapsterMetricsClient(clientset.CoreV1(), o.HeapsterOptions.Namespace, o.HeapsterOptions.Scheme, o.HeapsterOptions.Service, o.HeapsterOptions.Port) - o.Printer = metricsutil.NewTopCmdPrinter(out) + o.Printer = metricsutil.NewTopCmdPrinter(o.Out) return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_node_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_node_test.go index 13c7af7f8..ab387fbfc 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_node_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_node_test.go @@ -32,6 +32,7 @@ import ( core "k8s.io/client-go/testing" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" metricsv1alpha1api "k8s.io/metrics/pkg/apis/metrics/v1alpha1" metricsv1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1" @@ -49,10 +50,10 @@ func TestTopNodeAllMetrics(t *testing.T) { expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -77,11 +78,10 @@ func TestTopNodeAllMetrics(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdTopNode(tf, nil, buf) + cmd := NewCmdTopNode(tf, nil, streams) cmd.Run(cmd, []string{}) // Check the presence of node names in the output. @@ -102,10 +102,10 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) { expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", customBaseMetricsAddress, metricsApiVersion) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -130,9 +130,8 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() opts := &TopNodeOptions{ HeapsterOptions: HeapsterTopOptions{ @@ -140,8 +139,9 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) { Scheme: "https", Service: "custom-heapster-service", }, + IOStreams: streams, } - cmd := NewCmdTopNode(tf, opts, buf) + cmd := NewCmdTopNode(tf, opts, streams) cmd.Run(cmd, []string{}) // Check the presence of node names in the output. @@ -165,10 +165,10 @@ func TestTopNodeWithNameMetrics(t *testing.T) { expectedPath := fmt.Sprintf("%s/%s/nodes/%s", baseMetricsAddress, metricsApiVersion, expectedMetrics.Name) expectedNodePath := fmt.Sprintf("/%s/%s/nodes/%s", apiPrefix, apiVersion, expectedMetrics.Name) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -193,11 +193,10 @@ func TestTopNodeWithNameMetrics(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdTopNode(tf, nil, buf) + cmd := NewCmdTopNode(tf, nil, streams) cmd.Run(cmd, []string{expectedMetrics.Name}) // Check the presence of node names in the output. @@ -232,10 +231,10 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { expectedQuery := fmt.Sprintf("labelSelector=%s", url.QueryEscape(label)) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -260,11 +259,10 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { } }), } - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdTopNode(tf, nil, buf) + cmd := NewCmdTopNode(tf, nil, streams) cmd.Flags().Set("selector", label) cmd.Run(cmd, []string{}) @@ -287,10 +285,10 @@ func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) { expectedMetrics, nodes := testNodeV1beta1MetricsData() expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -313,16 +311,17 @@ func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) { fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, expectedMetrics, nil }) - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdTopNode(tf, nil, buf) + cmd := NewCmdTopNode(tf, nil, streams) // TODO in the long run, we want to test most of our commands like this. Wire the options struct with specific mocks // TODO then check the particular Run functionality and harvest results from fake clients - cmdOptions := &TopNodeOptions{} - if err := cmdOptions.Complete(tf, cmd, []string{}, buf); err != nil { + cmdOptions := &TopNodeOptions{ + IOStreams: streams, + } + if err := cmdOptions.Complete(tf, cmd, []string{}); err != nil { t.Fatal(err) } cmdOptions.MetricsClient = fakemetricsClientset @@ -353,10 +352,10 @@ func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) { } expectedNodePath := fmt.Sprintf("/%s/%s/nodes/%s", apiPrefix, apiVersion, expectedMetrics.Name) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -379,16 +378,17 @@ func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) { fakemetricsClientset.AddReactor("get", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, &expectedMetrics, nil }) - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdTopNode(tf, nil, buf) + cmd := NewCmdTopNode(tf, nil, streams) // TODO in the long run, we want to test most of our commands like this. Wire the options struct with specific mocks // TODO then check the particular Run functionality and harvest results from fake clients - cmdOptions := &TopNodeOptions{} - if err := cmdOptions.Complete(tf, cmd, []string{expectedMetrics.Name}, buf); err != nil { + cmdOptions := &TopNodeOptions{ + IOStreams: streams, + } + if err := cmdOptions.Complete(tf, cmd, []string{expectedMetrics.Name}); err != nil { t.Fatal(err) } cmdOptions.MetricsClient = fakemetricsClientset @@ -429,10 +429,10 @@ func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) { label := "key=value" expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace("test") defer tf.Cleanup() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -456,17 +456,18 @@ func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) { fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, expectedMetrics, nil }) - tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdTopNode(tf, nil, buf) + cmd := NewCmdTopNode(tf, nil, streams) cmd.Flags().Set("selector", label) // TODO in the long run, we want to test most of our commands like this. Wire the options struct with specific mocks // TODO then check the particular Run functionality and harvest results from fake clients - cmdOptions := &TopNodeOptions{} - if err := cmdOptions.Complete(tf, cmd, []string{}, buf); err != nil { + cmdOptions := &TopNodeOptions{ + IOStreams: streams, + } + if err := cmdOptions.Complete(tf, cmd, []string{}); err != nil { t.Fatal(err) } cmdOptions.MetricsClient = fakemetricsClientset diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_pod.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_pod.go index 71bd8df2c..b63dde44e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_pod.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_pod.go @@ -19,7 +19,6 @@ package cmd import ( "errors" "fmt" - "io" "time" "k8s.io/api/core/v1" @@ -37,6 +36,7 @@ import ( "github.com/golang/glog" "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) type TopPodOptions struct { @@ -51,6 +51,8 @@ type TopPodOptions struct { Printer *metricsutil.TopCmdPrinter DiscoveryClient discovery.DiscoveryInterface MetricsClient metricsclientset.Interface + + genericclioptions.IOStreams } const metricsCreationDelay = 2 * time.Minute @@ -78,9 +80,11 @@ var ( kubectl top pod -l name=myLabel`)) ) -func NewCmdTopPod(f cmdutil.Factory, options *TopPodOptions, out io.Writer) *cobra.Command { - if options == nil { - options = &TopPodOptions{} +func NewCmdTopPod(f cmdutil.Factory, o *TopPodOptions, streams genericclioptions.IOStreams) *cobra.Command { + if o == nil { + o = &TopPodOptions{ + IOStreams: streams, + } } cmd := &cobra.Command{ @@ -90,26 +94,26 @@ func NewCmdTopPod(f cmdutil.Factory, options *TopPodOptions, out io.Writer) *cob Long: topPodLong, Example: topPodExample, Run: func(cmd *cobra.Command, args []string) { - if err := options.Complete(f, cmd, args, out); err != nil { + if err := o.Complete(f, cmd, args); err != nil { cmdutil.CheckErr(err) } - if err := options.Validate(); err != nil { + if err := o.Validate(); err != nil { cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err)) } - if err := options.RunTopPod(); err != nil { + if err := o.RunTopPod(); err != nil { cmdutil.CheckErr(err) } }, Aliases: []string{"pods", "po"}, } - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().BoolVar(&options.PrintContainers, "containers", options.PrintContainers, "If present, print usage of containers within a pod.") - cmd.Flags().BoolVar(&options.AllNamespaces, "all-namespaces", options.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") - options.HeapsterOptions.Bind(cmd.Flags()) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&o.PrintContainers, "containers", o.PrintContainers, "If present, print usage of containers within a pod.") + cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + o.HeapsterOptions.Bind(cmd.Flags()) return cmd } -func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer) error { +func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { var err error if len(args) == 1 { o.ResourceName = args[0] @@ -117,7 +121,7 @@ func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } - o.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -127,7 +131,7 @@ func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s } o.DiscoveryClient = clientset.DiscoveryClient - config, err := f.ClientConfig() + config, err := f.ToRESTConfig() if err != nil { return err } @@ -139,7 +143,7 @@ func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s o.PodClient = clientset.CoreV1() o.Client = metricsutil.NewHeapsterMetricsClient(clientset.CoreV1(), o.HeapsterOptions.Namespace, o.HeapsterOptions.Scheme, o.HeapsterOptions.Service, o.HeapsterOptions.Port) - o.Printer = metricsutil.NewTopCmdPrinter(out) + o.Printer = metricsutil.NewTopCmdPrinter(o.Out) return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_pod_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_pod_test.go index ac5f78aa3..1cba8d692 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_pod_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_pod_test.go @@ -37,6 +37,7 @@ import ( core "k8s.io/client-go/testing" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" metricsv1alpha1api "k8s.io/metrics/pkg/apis/metrics/v1alpha1" metricsv1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1" metricsfake "k8s.io/metrics/pkg/client/clientset_generated/clientset/fake" @@ -163,7 +164,7 @@ func TestTopPod(t *testing.T) { } } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace(testNS) defer tf.Cleanup() ns := legacyscheme.Codecs @@ -189,11 +190,10 @@ func TestTopPod(t *testing.T) { } }), } - tf.Namespace = testNS tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdTopPod(tf, nil, buf) + cmd := NewCmdTopPod(tf, nil, streams) for name, value := range testCase.flags { cmd.Flags().Set(name, value) } @@ -308,7 +308,7 @@ func TestTopPodWithMetricsServer(t *testing.T) { }) } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace(testNS) defer tf.Cleanup() ns := legacyscheme.Codecs @@ -328,21 +328,21 @@ func TestTopPodWithMetricsServer(t *testing.T) { } }), } - tf.Namespace = testNS tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() - cmd := NewCmdTopPod(tf, nil, buf) + cmd := NewCmdTopPod(tf, nil, streams) var cmdOptions *TopPodOptions if testCase.options != nil { cmdOptions = testCase.options } else { cmdOptions = &TopPodOptions{} } + cmdOptions.IOStreams = streams // TODO in the long run, we want to test most of our commands like this. Wire the options struct with specific mocks // TODO then check the particular Run functionality and harvest results from fake clients. We probably end up skipping the factory altogether. - if err := cmdOptions.Complete(tf, cmd, testCase.args, buf); err != nil { + if err := cmdOptions.Complete(tf, cmd, testCase.args); err != nil { t.Fatal(err) } cmdOptions.MetricsClient = fakemetricsClientset @@ -506,7 +506,7 @@ func TestTopPodCustomDefaults(t *testing.T) { } } - tf := cmdtesting.NewTestFactory() + tf := cmdtesting.NewTestFactory().WithNamespace(testNS) defer tf.Cleanup() ns := legacyscheme.Codecs @@ -532,9 +532,8 @@ func TestTopPodCustomDefaults(t *testing.T) { } }), } - tf.Namespace = testNS tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() opts := &TopPodOptions{ HeapsterOptions: HeapsterTopOptions{ @@ -543,8 +542,9 @@ func TestTopPodCustomDefaults(t *testing.T) { Service: "custom-heapster-service", }, DiscoveryClient: &fakeDiscovery{}, + IOStreams: streams, } - cmd := NewCmdTopPod(tf, opts, buf) + cmd := NewCmdTopPod(tf, opts, streams) for name, value := range testCase.flags { cmd.Flags().Set(name, value) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_test.go index 0090782fc..2ad63d06b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/top_test.go @@ -29,6 +29,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" metricsv1alpha1api "k8s.io/metrics/pkg/apis/metrics/v1alpha1" metricsv1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1" ) @@ -46,9 +47,7 @@ func TestTopSubcommandsExist(t *testing.T) { f := cmdtesting.NewTestFactory() defer f.Cleanup() - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdTop(f, buf, buf) + cmd := NewCmdTop(f, genericclioptions.NewTestIOStreamsDiscard()) if !cmd.HasSubCommands() { t.Error("top command should have subcommands") } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/BUILD index 5abbe5b5b..7ed95e505 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/BUILD @@ -1,141 +1,76 @@ -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "cached_discovery.go", - "clientcache.go", + "conversion.go", "factory.go", - "factory_builder.go", "factory_client_access.go", - "factory_object_mapping.go", + "generator.go", "helpers.go", + "kubectl_match_version.go", "printing.go", - "shortcut_restmapper.go", ], importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util", - visibility = [ - "//build/visible_to:pkg_kubectl_cmd_util_CONSUMERS", - ], + visibility = ["//build/visible_to:pkg_kubectl_cmd_util_CONSUMERS"], deps = [ "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/apps:go_default_library", - "//pkg/apis/batch:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/core/v1:go_default_library", - "//pkg/apis/extensions:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", - "//pkg/controller:go_default_library", "//pkg/kubectl:go_default_library", - "//pkg/kubectl/categories:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/cmd/util/openapi/validation:go_default_library", - "//pkg/kubectl/plugins:go_default_library", - "//pkg/kubectl/resource:go_default_library", - "//pkg/kubectl/scheme:go_default_library", - "//pkg/kubectl/util/transport:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/validation:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", "//pkg/version:go_default_library", "//vendor/github.com/evanphx/json-patch:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/api/apps/v1beta2:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v2alpha1: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/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels: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/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors: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/util/strategicpatch:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/scale:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - "//vendor/k8s.io/client-go/util/homedir:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], ) go_test( name = "go_default_test", - srcs = [ - "cached_discovery_test.go", - "factory_object_mapping_test.go", - "factory_test.go", - "helpers_test.go", - "shortcut_restmapper_test.go", - ], - data = [ - "//api/swagger-spec", - ], + srcs = ["helpers_test.go"], embed = [":go_default_library"], - visibility = [ - "//build/visible_to:COMMON_testing", - ], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", - "//pkg/apis/apps:go_default_library", - "//pkg/apis/batch:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", - "//pkg/client/clientset_generated/internalclientset:go_default_library", - "//pkg/client/clientset_generated/internalclientset/fake:go_default_library", - "//pkg/controller:go_default_library", - "//pkg/kubectl:go_default_library", - "//pkg/kubectl/categories:go_default_library", - "//pkg/kubectl/resource:go_default_library", - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", - "//vendor/github.com/stretchr/testify/assert: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/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels: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/util/diff:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/rest/fake:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], ) @@ -144,6 +79,7 @@ filegroup( name = "package-srcs", srcs = glob(["**"]), tags = ["automanaged"], + visibility = ["//visibility:private"], ) filegroup( @@ -151,8 +87,6 @@ filegroup( srcs = [ ":package-srcs", "//pkg/kubectl/cmd/util/editor:all-srcs", - "//pkg/kubectl/cmd/util/env:all-srcs", - "//pkg/kubectl/cmd/util/jsonmerge:all-srcs", "//pkg/kubectl/cmd/util/openapi:all-srcs", "//pkg/kubectl/cmd/util/sanity:all-srcs", ], diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/cached_discovery.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/cached_discovery.go deleted file mode 100644 index 0224ebbe9..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/cached_discovery.go +++ /dev/null @@ -1,263 +0,0 @@ -/* -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 util - -import ( - "errors" - "io/ioutil" - "os" - "path/filepath" - "sync" - "time" - - "github.com/golang/glog" - "github.com/googleapis/gnostic/OpenAPIv2" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/version" - "k8s.io/client-go/discovery" - restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/kubectl/scheme" -) - -// CachedDiscoveryClient implements the functions that discovery server-supported API groups, -// versions and resources. -type CachedDiscoveryClient struct { - delegate discovery.DiscoveryInterface - - // cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well. - cacheDirectory string - - // ttl is how long the cache should be considered valid - ttl time.Duration - - // mutex protects the variables below - mutex sync.Mutex - - // ourFiles are all filenames of cache files created by this process - ourFiles map[string]struct{} - // invalidated is true if all cache files should be ignored that are not ours (e.g. after Invalidate() was called) - invalidated bool - // fresh is true if all used cache files were ours - fresh bool -} - -var _ discovery.CachedDiscoveryInterface = &CachedDiscoveryClient{} - -// ServerResourcesForGroupVersion returns the supported resources for a group and version. -func (d *CachedDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - filename := filepath.Join(d.cacheDirectory, groupVersion, "serverresources.json") - cachedBytes, err := d.getCachedFile(filename) - // don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback. - if err == nil { - cachedResources := &metav1.APIResourceList{} - if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedResources); err == nil { - glog.V(10).Infof("returning cached discovery info from %v", filename) - return cachedResources, nil - } - } - - liveResources, err := d.delegate.ServerResourcesForGroupVersion(groupVersion) - if err != nil { - glog.V(3).Infof("skipped caching discovery info due to %v", err) - return liveResources, err - } - if liveResources == nil || len(liveResources.APIResources) == 0 { - glog.V(3).Infof("skipped caching discovery info, no resources found") - return liveResources, err - } - - if err := d.writeCachedFile(filename, liveResources); err != nil { - glog.V(3).Infof("failed to write cache to %v due to %v", filename, err) - } - - return liveResources, nil -} - -// ServerResources returns the supported resources for all groups and versions. -func (d *CachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { - apiGroups, err := d.ServerGroups() - if err != nil { - return nil, err - } - groupVersions := metav1.ExtractGroupVersions(apiGroups) - result := []*metav1.APIResourceList{} - for _, groupVersion := range groupVersions { - resources, err := d.ServerResourcesForGroupVersion(groupVersion) - if err != nil { - return nil, err - } - result = append(result, resources) - } - return result, nil -} - -func (d *CachedDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { - filename := filepath.Join(d.cacheDirectory, "servergroups.json") - cachedBytes, err := d.getCachedFile(filename) - // don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback. - if err == nil { - cachedGroups := &metav1.APIGroupList{} - if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedGroups); err == nil { - glog.V(10).Infof("returning cached discovery info from %v", filename) - return cachedGroups, nil - } - } - - liveGroups, err := d.delegate.ServerGroups() - if err != nil { - glog.V(3).Infof("skipped caching discovery info due to %v", err) - return liveGroups, err - } - if liveGroups == nil || len(liveGroups.Groups) == 0 { - glog.V(3).Infof("skipped caching discovery info, no groups found") - return liveGroups, err - } - - if err := d.writeCachedFile(filename, liveGroups); err != nil { - glog.V(3).Infof("failed to write cache to %v due to %v", filename, err) - } - - return liveGroups, nil -} - -func (d *CachedDiscoveryClient) getCachedFile(filename string) ([]byte, error) { - // after invalidation ignore cache files not created by this process - d.mutex.Lock() - _, ourFile := d.ourFiles[filename] - if d.invalidated && !ourFile { - d.mutex.Unlock() - return nil, errors.New("cache invalidated") - } - d.mutex.Unlock() - - file, err := os.Open(filename) - if err != nil { - return nil, err - } - defer file.Close() - - fileInfo, err := file.Stat() - if err != nil { - return nil, err - } - - if time.Now().After(fileInfo.ModTime().Add(d.ttl)) { - return nil, errors.New("cache expired") - } - - // the cache is present and its valid. Try to read and use it. - cachedBytes, err := ioutil.ReadAll(file) - if err != nil { - return nil, err - } - - d.mutex.Lock() - defer d.mutex.Unlock() - d.fresh = d.fresh && ourFile - - return cachedBytes, nil -} - -func (d *CachedDiscoveryClient) writeCachedFile(filename string, obj runtime.Object) error { - if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil { - return err - } - - bytes, err := runtime.Encode(scheme.Codecs.LegacyCodec(), obj) - if err != nil { - return err - } - - f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)+".") - if err != nil { - return err - } - defer os.Remove(f.Name()) - _, err = f.Write(bytes) - if err != nil { - return err - } - - err = os.Chmod(f.Name(), 0755) - if err != nil { - return err - } - - name := f.Name() - err = f.Close() - if err != nil { - return err - } - - // atomic rename - d.mutex.Lock() - defer d.mutex.Unlock() - err = os.Rename(name, filename) - if err == nil { - d.ourFiles[filename] = struct{}{} - } - return err -} - -func (d *CachedDiscoveryClient) RESTClient() restclient.Interface { - return d.delegate.RESTClient() -} - -func (d *CachedDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - return d.delegate.ServerPreferredResources() -} - -func (d *CachedDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { - return d.delegate.ServerPreferredNamespacedResources() -} - -func (d *CachedDiscoveryClient) ServerVersion() (*version.Info, error) { - return d.delegate.ServerVersion() -} - -func (d *CachedDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { - return d.delegate.OpenAPISchema() -} - -func (d *CachedDiscoveryClient) Fresh() bool { - d.mutex.Lock() - defer d.mutex.Unlock() - - return d.fresh -} - -func (d *CachedDiscoveryClient) Invalidate() { - d.mutex.Lock() - defer d.mutex.Unlock() - - d.ourFiles = map[string]struct{}{} - d.fresh = true - d.invalidated = true -} - -// NewCachedDiscoveryClient creates a new DiscoveryClient. cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well. -func NewCachedDiscoveryClient(delegate discovery.DiscoveryInterface, cacheDirectory string, ttl time.Duration) *CachedDiscoveryClient { - return &CachedDiscoveryClient{ - delegate: delegate, - cacheDirectory: cacheDirectory, - ttl: ttl, - ourFiles: map[string]struct{}{}, - fresh: true, - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/cached_discovery_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/cached_discovery_test.go deleted file mode 100644 index 46cbc9c38..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/cached_discovery_test.go +++ /dev/null @@ -1,170 +0,0 @@ -/* -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 util - -import ( - "io/ioutil" - "os" - "testing" - "time" - - "github.com/googleapis/gnostic/OpenAPIv2" - "github.com/stretchr/testify/assert" - - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/version" - "k8s.io/client-go/discovery" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" -) - -func TestCachedDiscoveryClient_Fresh(t *testing.T) { - assert := assert.New(t) - - d, err := ioutil.TempDir("", "") - assert.NoError(err) - defer os.RemoveAll(d) - - c := fakeDiscoveryClient{} - cdc := NewCachedDiscoveryClient(&c, d, 60*time.Second) - assert.True(cdc.Fresh(), "should be fresh after creation") - - cdc.ServerGroups() - assert.True(cdc.Fresh(), "should be fresh after groups call without cache") - assert.Equal(c.groupCalls, 1) - - cdc.ServerGroups() - assert.True(cdc.Fresh(), "should be fresh after another groups call") - assert.Equal(c.groupCalls, 1) - - cdc.ServerResources() - assert.True(cdc.Fresh(), "should be fresh after resources call") - assert.Equal(c.resourceCalls, 1) - - cdc.ServerResources() - assert.True(cdc.Fresh(), "should be fresh after another resources call") - assert.Equal(c.resourceCalls, 1) - - cdc = NewCachedDiscoveryClient(&c, d, 60*time.Second) - cdc.ServerGroups() - assert.False(cdc.Fresh(), "should NOT be fresh after recreation with existing groups cache") - assert.Equal(c.groupCalls, 1) - - cdc.ServerResources() - assert.False(cdc.Fresh(), "should NOT be fresh after recreation with existing resources cache") - assert.Equal(c.resourceCalls, 1) - - cdc.Invalidate() - assert.True(cdc.Fresh(), "should be fresh after cache invalidation") - - cdc.ServerResources() - assert.True(cdc.Fresh(), "should ignore existing resources cache after invalidation") - assert.Equal(c.resourceCalls, 2) -} - -func TestNewCachedDiscoveryClient_TTL(t *testing.T) { - assert := assert.New(t) - - d, err := ioutil.TempDir("", "") - assert.NoError(err) - defer os.RemoveAll(d) - - c := fakeDiscoveryClient{} - cdc := NewCachedDiscoveryClient(&c, d, 1*time.Nanosecond) - cdc.ServerGroups() - assert.Equal(c.groupCalls, 1) - - time.Sleep(1 * time.Second) - - cdc.ServerGroups() - assert.Equal(c.groupCalls, 2) -} - -type fakeDiscoveryClient struct { - groupCalls int - resourceCalls int - versionCalls int - openAPICalls int - - serverResourcesHandler func() ([]*metav1.APIResourceList, error) -} - -var _ discovery.DiscoveryInterface = &fakeDiscoveryClient{} - -func (c *fakeDiscoveryClient) RESTClient() restclient.Interface { - return &fake.RESTClient{} -} - -func (c *fakeDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { - c.groupCalls = c.groupCalls + 1 - return &metav1.APIGroupList{ - Groups: []metav1.APIGroup{ - { - Name: "a", - Versions: []metav1.GroupVersionForDiscovery{ - { - GroupVersion: "a/v1", - Version: "v1", - }, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{ - GroupVersion: "a/v1", - Version: "v1", - }, - }, - }, - }, nil -} - -func (c *fakeDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - c.resourceCalls = c.resourceCalls + 1 - if groupVersion == "a/v1" { - return &metav1.APIResourceList{APIResources: []metav1.APIResource{{Name: "widgets", Kind: "Widget"}}}, nil - } - - return nil, errors.NewNotFound(schema.GroupResource{}, "") -} - -func (c *fakeDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { - c.resourceCalls = c.resourceCalls + 1 - if c.serverResourcesHandler != nil { - return c.serverResourcesHandler() - } - return []*metav1.APIResourceList{}, nil -} - -func (c *fakeDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - c.resourceCalls = c.resourceCalls + 1 - return nil, nil -} - -func (c *fakeDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { - c.resourceCalls = c.resourceCalls + 1 - return nil, nil -} - -func (c *fakeDiscoveryClient) ServerVersion() (*version.Info, error) { - c.versionCalls = c.versionCalls + 1 - return &version.Info{}, nil -} - -func (c *fakeDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { - c.openAPICalls = c.openAPICalls + 1 - return &openapi_v2.Document{}, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/clientcache.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/clientcache.go deleted file mode 100644 index 4019f0fbc..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/clientcache.go +++ /dev/null @@ -1,226 +0,0 @@ -/* -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 ( - "sync" - - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/discovery" - "k8s.io/client-go/kubernetes" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/version" -) - -func NewClientCache(loader clientcmd.ClientConfig, discoveryClientFactory DiscoveryClientFactory) *ClientCache { - return &ClientCache{ - clientsets: make(map[schema.GroupVersion]internalclientset.Interface), - configs: make(map[schema.GroupVersion]*restclient.Config), - loader: loader, - discoveryClientFactory: discoveryClientFactory, - } -} - -// ClientCache caches previously loaded clients for reuse, and ensures MatchServerVersion -// is invoked only once -type ClientCache struct { - loader clientcmd.ClientConfig - clientsets map[schema.GroupVersion]internalclientset.Interface - configs map[schema.GroupVersion]*restclient.Config - - // noVersionConfig provides a cached config for the case of no required version specified - noVersionConfig *restclient.Config - - matchVersion bool - - lock sync.Mutex - defaultConfig *restclient.Config - // discoveryClientFactory comes as a factory method so that we can defer resolution until after - // argument evaluation - discoveryClientFactory DiscoveryClientFactory - discoveryClient discovery.DiscoveryInterface - - kubernetesClientCache kubernetesClientCache -} - -// kubernetesClientCache creates a new kubernetes.Clientset one time -// and then returns the result for all future requests -type kubernetesClientCache struct { - // once makes sure the client is only initialized once - once sync.Once - // client is the cached client value - client *kubernetes.Clientset - // err is the cached error value - err error -} - -// KubernetesClientSetForVersion returns a new kubernetes.Clientset. It will cache the value -// the first time it is called and return the cached value on subsequent calls. -// If an error is encountered the first time KubernetesClientSetForVersion is called, -// the error will be cached. -func (c *ClientCache) KubernetesClientSetForVersion(requiredVersion *schema.GroupVersion) (*kubernetes.Clientset, error) { - c.kubernetesClientCache.once.Do(func() { - config, err := c.ClientConfigForVersion(requiredVersion) - if err != nil { - c.kubernetesClientCache.err = err - return - } - c.kubernetesClientCache.client, c.kubernetesClientCache.err = kubernetes.NewForConfig(config) - }) - return c.kubernetesClientCache.client, c.kubernetesClientCache.err -} - -// also looks up the discovery client. We can't do this during init because the flags won't have been set -// because this is constructed pre-command execution before the command tree is -// even set up. Requires the lock to already be acquired -func (c *ClientCache) getDefaultConfig() (restclient.Config, discovery.DiscoveryInterface, error) { - if c.defaultConfig != nil && c.discoveryClient != nil { - return *c.defaultConfig, c.discoveryClient, nil - } - - config, err := c.loader.ClientConfig() - if err != nil { - return restclient.Config{}, nil, err - } - discoveryClient, err := c.discoveryClientFactory.DiscoveryClient() - if err != nil { - return restclient.Config{}, nil, err - } - if c.matchVersion { - if err := discovery.MatchesServerVersion(version.Get(), discoveryClient); err != nil { - return restclient.Config{}, nil, err - } - } - - c.defaultConfig = config - c.discoveryClient = discoveryClient - return *c.defaultConfig, c.discoveryClient, nil -} - -// ClientConfigForVersion returns the correct config for a server -func (c *ClientCache) ClientConfigForVersion(requiredVersion *schema.GroupVersion) (*restclient.Config, error) { - c.lock.Lock() - defer c.lock.Unlock() - - return c.clientConfigForVersion(requiredVersion) -} - -// clientConfigForVersion returns the correct config for a server -func (c *ClientCache) clientConfigForVersion(requiredVersion *schema.GroupVersion) (*restclient.Config, error) { - // only lookup in the cache if the requiredVersion is set - if requiredVersion != nil { - if config, ok := c.configs[*requiredVersion]; ok { - return copyConfig(config), nil - } - } else if c.noVersionConfig != nil { - return copyConfig(c.noVersionConfig), nil - } - - // this returns a shallow copy to work with - config, discoveryClient, err := c.getDefaultConfig() - if err != nil { - return nil, err - } - - if requiredVersion != nil { - if err := discovery.ServerSupportsVersion(discoveryClient, *requiredVersion); err != nil { - return nil, err - } - config.GroupVersion = requiredVersion - } else { - // TODO remove this hack. This is allowing the GetOptions to be serialized. - config.GroupVersion = &schema.GroupVersion{Group: "", Version: "v1"} - } - - // TODO this isn't what we want. Each clientset should be setting defaults as it sees fit. - setKubernetesDefaults(&config) - - if requiredVersion != nil { - c.configs[*requiredVersion] = copyConfig(&config) - } else { - c.noVersionConfig = copyConfig(&config) - } - - // `version` does not necessarily equal `config.Version`. However, we know that we call this method again with - // `config.Version`, we should get the config we've just built. - c.configs[*config.GroupVersion] = copyConfig(&config) - - return copyConfig(&config), nil -} - -// setKubernetesDefaults sets default values on the provided client config for accessing the -// Kubernetes API or returns an error if any of the defaults are impossible or invalid. -func setKubernetesDefaults(config *restclient.Config) error { - if config.APIPath == "" { - config.APIPath = "/api" - } - // TODO chase down uses and tolerate nil - if config.GroupVersion == nil { - config.GroupVersion = &schema.GroupVersion{} - } - if config.NegotiatedSerializer == nil { - config.NegotiatedSerializer = legacyscheme.Codecs - } - return restclient.SetKubernetesDefaults(config) -} - -func copyConfig(in *restclient.Config) *restclient.Config { - configCopy := *in - copyGroupVersion := *configCopy.GroupVersion - configCopy.GroupVersion = ©GroupVersion - return &configCopy -} - -// ClientSetForVersion initializes or reuses a clientset for the specified version, or returns an -// error if that is not possible -func (c *ClientCache) ClientSetForVersion(requiredVersion *schema.GroupVersion) (internalclientset.Interface, error) { - c.lock.Lock() - defer c.lock.Unlock() - - if requiredVersion != nil { - if clientset, ok := c.clientsets[*requiredVersion]; ok { - return clientset, nil - } - } - config, err := c.clientConfigForVersion(requiredVersion) - if err != nil { - return nil, err - } - - clientset, err := internalclientset.NewForConfig(config) - if err != nil { - return nil, err - } - c.clientsets[*config.GroupVersion] = clientset - - // `version` does not necessarily equal `config.Version`. However, we know that if we call this method again with - // `version`, we should get a client based on the same config we just found. There's no guarantee that a client - // is copiable, so create a new client and save it in the cache. - if requiredVersion != nil { - configCopy := *config - clientset, err := internalclientset.NewForConfig(&configCopy) - if err != nil { - return nil, err - } - c.clientsets[*requiredVersion] = clientset - } - - return clientset, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/conversion.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/conversion.go new file mode 100644 index 000000000..98b02ee71 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/conversion.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 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 ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kubernetes/pkg/api/legacyscheme" +) + +// AsDefaultVersionedOrOriginal returns the object as a Go object in the external form if possible (matching the +// group version kind of the mapping if provided, a best guess based on serialization if not provided, or obj if it cannot be converted. +// TODO update call sites to specify the scheme they want on their builder. +func AsDefaultVersionedOrOriginal(obj runtime.Object, mapping *meta.RESTMapping) runtime.Object { + converter := runtime.ObjectConvertor(legacyscheme.Scheme) + groupVersioner := runtime.GroupVersioner(schema.GroupVersions(legacyscheme.Scheme.PrioritizedVersionsAllGroups())) + if mapping != nil { + groupVersioner = mapping.GroupVersionKind.GroupVersion() + } + + if obj, err := converter.ConvertToVersion(obj, groupVersioner); err == nil { + return obj + } + return obj +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/BUILD index 1533b35a4..379bdcc5c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/BUILD @@ -18,11 +18,12 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/kubectl:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", - "//pkg/kubectl/resource:go_default_library", + "//pkg/kubectl/cmd/util/editor/crlf:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/scheme:go_default_library", - "//pkg/kubectl/util/crlf:go_default_library", "//pkg/kubectl/util/term:go_default_library", - "//pkg/printers:go_default_library", "//vendor/github.com/evanphx/json-patch:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", @@ -41,7 +42,10 @@ go_library( go_test( name = "go_default_test", - srcs = ["editor_test.go"], + srcs = [ + "editoptions_test.go", + "editor_test.go", + ], embed = [":go_default_library"], ) @@ -53,7 +57,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/kubectl/cmd/util/editor/crlf:all-srcs", + ], tags = ["automanaged"], visibility = [ "//build/visible_to:pkg_kubectl_cmd_util_editor_CONSUMERS", diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf/BUILD new file mode 100644 index 000000000..ebf46c7e2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf/BUILD @@ -0,0 +1,25 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["crlf.go"], + importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf", +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/crlf.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf/crlf.go similarity index 98% rename from vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/crlf.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf/crlf.go index c08fe6f31..524a81f3e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/crlf.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf/crlf.go @@ -51,7 +51,7 @@ func (w crlfWriter) Write(b []byte) (n int, err error) { } return written + n, err } - written += 1 + written++ i = next + 1 } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editoptions.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editoptions.go index b7ae830d2..f2d2920b9 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editoptions.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editoptions.go @@ -25,6 +25,7 @@ import ( "os" "path/filepath" "reflect" + goruntime "runtime" "strings" "github.com/evanphx/json-patch" @@ -44,15 +45,20 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" - "k8s.io/kubernetes/pkg/kubectl/util/crlf" - "k8s.io/kubernetes/pkg/printers" ) // EditOptions contains all the options for running edit cli command. type EditOptions struct { resource.FilenameOptions + RecordFlags *genericclioptions.RecordFlags + + PrintFlags *genericclioptions.PrintFlags + ToPrinter func(string) (printers.ResourcePrinter, error) Output string OutputPatch bool @@ -60,25 +66,39 @@ type EditOptions struct { cmdutil.ValidateOptions - ResourceMapper *resource.Mapper OriginalResult *resource.Result EditMode EditMode CmdNamespace string ApplyAnnotation bool - Record bool ChangeCause string - Include3rdParty bool - Out io.Writer - ErrOut io.Writer + genericclioptions.IOStreams + Recorder genericclioptions.Recorder f cmdutil.Factory editPrinterOptions *editPrinterOptions updatedResultGetter func(data []byte) *resource.Result } +func NewEditOptions(editMode EditMode, ioStreams genericclioptions.IOStreams) *EditOptions { + return &EditOptions{ + RecordFlags: genericclioptions.NewRecordFlags(), + + EditMode: editMode, + + PrintFlags: genericclioptions.NewPrintFlags("edited").WithTypeSetter(scheme.Scheme), + + WindowsLineEndings: goruntime.GOOS == "windows", + + Recorder: genericclioptions.NoopRecorder{}, + + IOStreams: ioStreams, + Output: "yaml", + } +} + type editPrinterOptions struct { printer printers.ResourcePrinter ext string @@ -86,7 +106,15 @@ type editPrinterOptions struct { } // Complete completes all the required options -func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string, cmd *cobra.Command) error { +func (o *EditOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Command) error { + var err error + + o.RecordFlags.Complete(cmd) + o.Recorder, err = o.RecordFlags.ToRecorder() + if err != nil { + return err + } + if o.EditMode != NormalEditMode && o.EditMode != EditBeforeCreateMode && o.EditMode != ApplyEditMode { return fmt.Errorf("unsupported edit mode %q", o.EditMode) } @@ -101,7 +129,7 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args [] return fmt.Errorf("the edit mode doesn't support output the patch") } - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -135,13 +163,14 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args [] Do() } + o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { + o.PrintFlags.NamePrintFlags.Operation = operation + return o.PrintFlags.ToPrinter() + } + o.CmdNamespace = cmdNamespace o.f = f - // Set up writer - o.Out = out - o.ErrOut = errOut - return nil } @@ -151,7 +180,7 @@ func (o *EditOptions) Validate() error { } func (o *EditOptions) Run() error { - edit := NewDefaultEditor(o.f.EditorEnvs()) + edit := NewDefaultEditor(editorEnvs()) // editFn is invoked for each edit session (once with a list for normal edit, once for each individual resource in a edit-on-create invocation) editFn := func(infos []*resource.Info) error { var ( @@ -342,7 +371,7 @@ func (o *EditOptions) Run() error { } var annotationInfos []*resource.Info for i := range infos { - data, err := kubectl.GetOriginalConfiguration(infos[i].Mapping, infos[i].Object) + data, err := kubectl.GetOriginalConfiguration(infos[i].Object) if err != nil { return err } @@ -392,25 +421,34 @@ func (o *EditOptions) visitToApplyEditPatch(originalInfos []*resource.Info, patc return fmt.Errorf("no original object found for %#v", info.Object) } - originalJS, err := encodeToJson(cmdutil.InternalVersionJSONEncoder(), originalInfo.Object) + originalJS, err := encodeToJson(originalInfo.Object.(runtime.Unstructured)) if err != nil { return err } - editedJS, err := encodeToJson(cmdutil.InternalVersionJSONEncoder(), info.Object) + editedJS, err := encodeToJson(info.Object.(runtime.Unstructured)) if err != nil { return err } if reflect.DeepEqual(originalJS, editedJS) { - cmdutil.PrintSuccess(false, o.Out, info.Object, false, "skipped") + printer, err := o.ToPrinter("skipped") + if err != nil { + return err + } + printer.PrintObj(info.Object, o.Out) return nil } else { err := o.annotationPatch(info) if err != nil { return err } - cmdutil.PrintSuccess(false, o.Out, info.Object, false, "edited") + + printer, err := o.ToPrinter("edited") + if err != nil { + return err + } + printer.PrintObj(info.Object, o.Out) return nil } }) @@ -418,7 +456,7 @@ func (o *EditOptions) visitToApplyEditPatch(originalInfos []*resource.Info, patc } func (o *EditOptions) annotationPatch(update *resource.Info) error { - patch, _, patchType, err := GetApplyPatch(update.Object, cmdutil.InternalVersionJSONEncoder()) + patch, _, patchType, err := GetApplyPatch(update.Object.(runtime.Unstructured)) if err != nil { return err } @@ -435,8 +473,8 @@ func (o *EditOptions) annotationPatch(update *resource.Info) error { return nil } -func GetApplyPatch(obj runtime.Object, codec runtime.Encoder) ([]byte, []byte, types.PatchType, error) { - beforeJSON, err := encodeToJson(codec, obj) +func GetApplyPatch(obj runtime.Unstructured) ([]byte, []byte, types.PatchType, error) { + beforeJSON, err := encodeToJson(obj) if err != nil { return nil, []byte(""), types.MergePatchType, err } @@ -451,7 +489,7 @@ func GetApplyPatch(obj runtime.Object, codec runtime.Encoder) ([]byte, []byte, t } annotations[api.LastAppliedConfigAnnotation] = string(beforeJSON) accessor.SetAnnotations(objCopy, annotations) - afterJSON, err := encodeToJson(codec, objCopy) + afterJSON, err := encodeToJson(objCopy.(runtime.Unstructured)) if err != nil { return nil, beforeJSON, types.MergePatchType, err } @@ -459,8 +497,8 @@ func GetApplyPatch(obj runtime.Object, codec runtime.Encoder) ([]byte, []byte, t return patch, beforeJSON, types.MergePatchType, err } -func encodeToJson(codec runtime.Encoder, obj runtime.Object) ([]byte, error) { - serialization, err := runtime.Encode(codec, obj) +func encodeToJson(obj runtime.Unstructured) ([]byte, error) { + serialization, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) if err != nil { return nil, err } @@ -517,19 +555,23 @@ func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor return fmt.Errorf("no original object found for %#v", info.Object) } - originalJS, err := encodeToJson(cmdutil.InternalVersionJSONEncoder(), originalInfo.Object) + originalJS, err := encodeToJson(originalInfo.Object.(runtime.Unstructured)) if err != nil { return err } - editedJS, err := encodeToJson(cmdutil.InternalVersionJSONEncoder(), info.Object) + editedJS, err := encodeToJson(info.Object.(runtime.Unstructured)) if err != nil { return err } if reflect.DeepEqual(originalJS, editedJS) { // no edit, so just skip it. - cmdutil.PrintSuccess(false, o.Out, info.Object, false, "skipped") + printer, err := o.ToPrinter("skipped") + if err != nil { + return err + } + printer.PrintObj(info.Object, o.Out) return nil } @@ -583,7 +625,11 @@ func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor return nil } info.Refresh(patched, true) - cmdutil.PrintSuccess(false, o.Out, info.Object, false, "edited") + printer, err := o.ToPrinter("edited") + if err != nil { + return err + } + printer.PrintObj(info.Object, o.Out) return nil }) return err @@ -594,7 +640,11 @@ func (o *EditOptions) visitToCreate(createVisitor resource.Visitor) error { if err := resource.CreateAndRefresh(info); err != nil { return err } - cmdutil.PrintSuccess(false, o.Out, info.Object, false, "created") + printer, err := o.ToPrinter("created") + if err != nil { + return err + } + printer.PrintObj(info.Object, o.Out) return nil }) return err @@ -605,14 +655,12 @@ func (o *EditOptions) visitAnnotation(annotationVisitor resource.Visitor) error err := annotationVisitor.Visit(func(info *resource.Info, incomingErr error) error { // put configuration annotation in "updates" if o.ApplyAnnotation { - if err := kubectl.CreateOrUpdateAnnotation(true, info, cmdutil.InternalVersionJSONEncoder()); err != nil { + if err := kubectl.CreateOrUpdateAnnotation(true, info.Object, cmdutil.InternalVersionJSONEncoder()); err != nil { return err } } - if o.Record || cmdutil.ContainsChangeCause(info) { - if err := cmdutil.RecordChangeCause(info.Object, o.ChangeCause); err != nil { - return err - } + if err := o.Recorder.Record(info.Object); err != nil { + glog.V(4).Infof("error recording current command: %v", err) } return nil @@ -657,12 +705,12 @@ func (h *editHeader) writeTo(w io.Writer, editMode EditMode) error { for _, r := range h.reasons { if len(r.other) > 0 { - fmt.Fprintf(w, "# %s:\n", r.head) + fmt.Fprintf(w, "# %s:\n", hashOnLineBreak(r.head)) } else { - fmt.Fprintf(w, "# %s\n", r.head) + fmt.Fprintf(w, "# %s\n", hashOnLineBreak(r.head)) } for _, o := range r.other { - fmt.Fprintf(w, "# * %s\n", o) + fmt.Fprintf(w, "# * %s\n", hashOnLineBreak(o)) } fmt.Fprintln(w, "#") } @@ -685,11 +733,16 @@ type editResults struct { } func (r *editResults) addError(err error, info *resource.Info) string { + resourceString := info.Mapping.Resource.Resource + if len(info.Mapping.Resource.Group) > 0 { + resourceString = resourceString + "." + info.Mapping.Resource.Group + } + switch { case apierrors.IsInvalid(err): r.edit = append(r.edit, info) reason := editReason{ - head: fmt.Sprintf("%s %q was not valid", info.Mapping.Resource, info.Name), + head: fmt.Sprintf("%s %q was not valid", resourceString, info.Name), } if err, ok := err.(apierrors.APIStatus); ok { if details := err.Status().Details; details != nil { @@ -699,13 +752,13 @@ func (r *editResults) addError(err error, info *resource.Info) string { } } r.header.reasons = append(r.header.reasons, reason) - return fmt.Sprintf("error: %s %q is invalid", info.Mapping.Resource, info.Name) + return fmt.Sprintf("error: %s %q is invalid", resourceString, info.Name) case apierrors.IsNotFound(err): r.notfound++ - return fmt.Sprintf("error: %s %q could not be found on the server", info.Mapping.Resource, info.Name) + return fmt.Sprintf("error: %s %q could not be found on the server", resourceString, info.Name) default: r.retryable++ - return fmt.Sprintf("error: %s %q could not be patched: %v", info.Mapping.Resource, info.Name, err) + return fmt.Sprintf("error: %s %q could not be patched: %v", resourceString, info.Name, err) } } @@ -738,3 +791,26 @@ func hasLines(r io.Reader) (bool, error) { } return false, nil } + +// hashOnLineBreak returns a string built from the provided string by inserting any necessary '#' +// characters after '\n' characters, indicating a comment. +func hashOnLineBreak(s string) string { + r := "" + for i, ch := range s { + j := i + 1 + if j < len(s) && ch == '\n' && s[j] != '#' { + r += "\n# " + } else { + r += string(ch) + } + } + return r +} + +// editorEnvs returns an ordered list of env vars to check for editor preferences. +func editorEnvs() []string { + return []string{ + "KUBE_EDITOR", + "EDITOR", + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editoptions_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editoptions_test.go new file mode 100644 index 000000000..69a30583c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editoptions_test.go @@ -0,0 +1,51 @@ +/* +Copyright 2018 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 editor + +import ( + "testing" +) + +func TestHashOnLineBreak(t *testing.T) { + tests := []struct { + original string + expected string + }{ + { + original: "", + expected: "", + }, + { + original: "\n", + expected: "\n", + }, + { + original: "a\na\na\n", + expected: "a\n# a\n# a\n", + }, + { + original: "a\n\n\na\n\n", + expected: "a\n# \n# \n# a\n# \n", + }, + } + for _, test := range tests { + r := hashOnLineBreak(test.original) + if r != test.expected { + t.Errorf("expected: %s, saw: %s", test.expected, r) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/BUILD deleted file mode 100644 index ecdf11acb..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "env_parse.go", - "env_resolve.go", - ], - importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/env", - visibility = ["//visibility:public"], - deps = [ - "//pkg/api/v1/resource:go_default_library", - "//pkg/fieldpath:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) - -go_test( - name = "go_default_test", - srcs = ["env_parse_test.go"], - embed = [":go_default_library"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/doc.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/doc.go deleted file mode 100644 index 39adb0adf..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -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 env provides functions to incorporate environment variables into kubectl commands. -package env // import "k8s.io/kubernetes/pkg/kubectl/cmd/util/env" diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go index 3cb44ab4d..3a0fc5d97 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go @@ -17,44 +17,15 @@ limitations under the License. package util import ( - "fmt" - "sort" - "strconv" - "strings" - "time" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" - - "k8s.io/api/core/v1" "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/apimachinery/pkg/watch" - "k8s.io/client-go/discovery" + "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - api "k8s.io/kubernetes/pkg/apis/core" - apiv1 "k8s.io/kubernetes/pkg/apis/core/v1" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/categories" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - "k8s.io/kubernetes/pkg/kubectl/plugins" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/validation" - "k8s.io/kubernetes/pkg/printers" -) - -const ( - FlagMatchBinaryVersion = "match-server-version" -) - -var ( - FlagHTTPCacheDir = "cache-dir" ) // Factory provides abstractions that allow the Kubectl command to be extended across multiple types @@ -68,270 +39,32 @@ var ( // TODO: pass the various interfaces on the factory directly into the command constructors (so the // commands are decoupled from the factory). type Factory interface { - ClientAccessFactory - ObjectMappingFactory - BuilderFactory -} - -type DiscoveryClientFactory interface { - // Returns a discovery client - DiscoveryClient() (discovery.CachedDiscoveryInterface, error) - - // BindFlags adds any discovery flags that are common to all kubectl sub commands. - BindFlags(flags *pflag.FlagSet) -} - -// ClientAccessFactory holds the first level of factory methods. -// Generally provides discovery, negotiation, and no-dep calls. -// TODO The polymorphic calls probably deserve their own interface. -type ClientAccessFactory interface { - // Returns a discovery client - DiscoveryClient() (discovery.CachedDiscoveryInterface, error) + genericclioptions.RESTClientGetter // ClientSet gives you back an internal, generated clientset ClientSet() (internalclientset.Interface, error) + // DynamicClient returns a dynamic client ready for use + DynamicClient() (dynamic.Interface, error) + // KubernetesClientSet gives you back an external clientset KubernetesClientSet() (*kubernetes.Clientset, error) // Returns a RESTClient for accessing Kubernetes resources or an error. RESTClient() (*restclient.RESTClient, error) - // Returns a client.Config for accessing the Kubernetes server. - ClientConfig() (*restclient.Config, error) - // BareClientConfig returns a client.Config that has NOT been negotiated. It's - // just directions to the server. People use this to build RESTMappers on top of - BareClientConfig() (*restclient.Config, error) - - // UpdatePodSpecForObject will call the provided function on the pod spec this object supports, - // return false if no pod spec is supported, or return an error. - UpdatePodSpecForObject(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) - // MapBasedSelectorForObject returns the map-based selector associated with the provided object. If a - // new set-based selector is provided, an error is returned if the selector cannot be converted to a - // map-based selector - MapBasedSelectorForObject(object runtime.Object) (string, error) - // PortsForObject returns the ports associated with the provided object - PortsForObject(object runtime.Object) ([]string, error) - // ProtocolsForObject returns the mapping associated with the provided object - ProtocolsForObject(object runtime.Object) (map[string]string, error) - // LabelsForObject returns the labels associated with the provided object - LabelsForObject(object runtime.Object) (map[string]string, error) - - // Returns internal flagset - FlagSet() *pflag.FlagSet - // Command will stringify and return all environment arguments ie. a command run by a client - // using the factory. - Command(cmd *cobra.Command, showSecrets bool) string - // BindFlags adds any flags that are common to all kubectl sub commands. - BindFlags(flags *pflag.FlagSet) - // BindExternalFlags adds any flags defined by external projects (not part of pflags) - BindExternalFlags(flags *pflag.FlagSet) - - // DefaultResourceFilterFunc returns a collection of FilterFuncs suitable for filtering specific resource types. - DefaultResourceFilterFunc() kubectl.Filters - - // SuggestedPodTemplateResources returns a list of resource types that declare a pod template - SuggestedPodTemplateResources() []schema.GroupResource - - // Pauser marks the object in the info as paused. Currently supported only for Deployments. - // Returns the patched object in bytes and any error that occurred during the encoding or - // in case the object is already paused. - Pauser(info *resource.Info) ([]byte, error) - // Resumer resumes a paused object inside the info. Currently supported only for Deployments. - // Returns the patched object in bytes and any error that occurred during the encoding or - // in case the object is already resumed. - Resumer(info *resource.Info) ([]byte, error) - - // ResolveImage resolves the image names. For kubernetes this function is just - // passthrough but it allows to perform more sophisticated image name resolving for - // third-party vendors. - ResolveImage(imageName string) (string, error) - - // Returns the default namespace to use in cases where no - // other namespace is specified and whether the namespace was - // overridden. - DefaultNamespace() (string, bool, error) - // Generators returns the generators for the provided command - Generators(cmdName string) map[string]kubectl.Generator - // Check whether the kind of resources could be exposed - CanBeExposed(kind schema.GroupKind) error - // Check whether the kind of resources could be autoscaled - CanBeAutoscaled(kind schema.GroupKind) error - - // EditorEnvs returns a group of environment variables that the edit command - // can range over in order to determine if the user has specified an editor - // of their choice. - EditorEnvs() []string -} + // NewBuilder returns an object that assists in loading objects from both disk and the server + // and which implements the common patterns for CLI interactions with generic resources. + NewBuilder() *resource.Builder -// ObjectMappingFactory holds the second level of factory methods. These functions depend upon ClientAccessFactory methods. -// Generally they provide object typing and functions that build requests based on the negotiated clients. -type ObjectMappingFactory interface { - // Returns interfaces for dealing with arbitrary runtime.Objects. - Object() (meta.RESTMapper, runtime.ObjectTyper) - // Returns interface for expanding categories like `all`. - CategoryExpander() categories.CategoryExpander // Returns a RESTClient for working with the specified RESTMapping or an error. This is intended // for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer. ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) // Returns a RESTClient for working with Unstructured objects. UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) - // Returns a Describer for displaying the specified RESTMapping type or an error. - Describer(mapping *meta.RESTMapping) (printers.Describer, error) - - // LogsForObject returns a request for the logs associated with the provided object - LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) - // Returns a Scaler for changing the size of the specified RESTMapping type or an error - Scaler(mapping *meta.RESTMapping) (kubectl.Scaler, error) - // Returns a Reaper for gracefully shutting down resources. - Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, error) - // Returns a HistoryViewer for viewing change history - HistoryViewer(mapping *meta.RESTMapping) (kubectl.HistoryViewer, error) - // Returns a Rollbacker for changing the rollback version of the specified RESTMapping type or an error - Rollbacker(mapping *meta.RESTMapping) (kubectl.Rollbacker, error) - // Returns a StatusViewer for printing rollout status. - StatusViewer(mapping *meta.RESTMapping) (kubectl.StatusViewer, error) - - // AttachablePodForObject returns the pod to which to attach given an object. - AttachablePodForObject(object runtime.Object, timeout time.Duration) (*api.Pod, error) - - // ApproximatePodTemplateForObject returns a pod template object for the provided source. - // It may return both an error and a object. It attempt to return the best possible template - // available at the current time. - ApproximatePodTemplateForObject(runtime.Object) (*api.PodTemplateSpec, error) // Returns a schema that can validate objects stored on disk. Validator(validate bool) (validation.Schema, error) // OpenAPISchema returns the schema openapi schema definition OpenAPISchema() (openapi.Resources, error) } - -// BuilderFactory holds the third level of factory methods. These functions depend upon ObjectMappingFactory and ClientAccessFactory methods. -// Generally they depend upon client mapper functions -type BuilderFactory interface { - // NewBuilder returns an object that assists in loading objects from both disk and the server - // and which implements the common patterns for CLI interactions with generic resources. - NewBuilder() *resource.Builder - // PluginLoader provides the implementation to be used to load cli plugins. - PluginLoader() plugins.PluginLoader - // PluginRunner provides the implementation to be used to run cli plugins. - PluginRunner() plugins.PluginRunner -} - -type factory struct { - ClientAccessFactory - ObjectMappingFactory - BuilderFactory -} - -// NewFactory creates a factory with the default Kubernetes resources defined -// if optionalClientConfig is nil, then flags will be bound to a new clientcmd.ClientConfig. -// if optionalClientConfig is not nil, then this factory will make use of it. -func NewFactory(optionalClientConfig clientcmd.ClientConfig) Factory { - clientAccessFactory := NewClientAccessFactory(optionalClientConfig) - objectMappingFactory := NewObjectMappingFactory(clientAccessFactory) - builderFactory := NewBuilderFactory(clientAccessFactory, objectMappingFactory) - - return &factory{ - ClientAccessFactory: clientAccessFactory, - ObjectMappingFactory: objectMappingFactory, - BuilderFactory: builderFactory, - } -} - -// GetFirstPod returns a pod matching the namespace and label selector -// and the number of all pods that match the label selector. -func GetFirstPod(client coreclient.PodsGetter, namespace string, selector string, timeout time.Duration, sortBy func([]*v1.Pod) sort.Interface) (*api.Pod, int, error) { - options := metav1.ListOptions{LabelSelector: selector} - - podList, err := client.Pods(namespace).List(options) - if err != nil { - return nil, 0, err - } - pods := []*v1.Pod{} - for i := range podList.Items { - pod := podList.Items[i] - externalPod := &v1.Pod{} - apiv1.Convert_core_Pod_To_v1_Pod(&pod, externalPod, nil) - pods = append(pods, externalPod) - } - if len(pods) > 0 { - sort.Sort(sortBy(pods)) - internalPod := &api.Pod{} - apiv1.Convert_v1_Pod_To_core_Pod(pods[0], internalPod, nil) - return internalPod, len(podList.Items), nil - } - - // Watch until we observe a pod - options.ResourceVersion = podList.ResourceVersion - w, err := client.Pods(namespace).Watch(options) - if err != nil { - return nil, 0, err - } - defer w.Stop() - - condition := func(event watch.Event) (bool, error) { - return event.Type == watch.Added || event.Type == watch.Modified, nil - } - event, err := watch.Until(timeout, w, condition) - if err != nil { - return nil, 0, err - } - pod, ok := event.Object.(*api.Pod) - if !ok { - return nil, 0, fmt.Errorf("%#v is not a pod event", event) - } - return pod, 1, nil -} - -func makePortsString(ports []api.ServicePort, useNodePort bool) string { - pieces := make([]string, len(ports)) - for ix := range ports { - var port int32 - if useNodePort { - port = ports[ix].NodePort - } else { - port = ports[ix].Port - } - pieces[ix] = fmt.Sprintf("%s:%d", strings.ToLower(string(ports[ix].Protocol)), port) - } - return strings.Join(pieces, ",") -} - -func getPorts(spec api.PodSpec) []string { - result := []string{} - for _, container := range spec.Containers { - for _, port := range container.Ports { - result = append(result, strconv.Itoa(int(port.ContainerPort))) - } - } - return result -} - -func getProtocols(spec api.PodSpec) map[string]string { - result := make(map[string]string) - for _, container := range spec.Containers { - for _, port := range container.Ports { - result[strconv.Itoa(int(port.ContainerPort))] = string(port.Protocol) - } - } - return result -} - -// Extracts the ports exposed by a service from the given service spec. -func getServicePorts(spec api.ServiceSpec) []string { - result := []string{} - for _, servicePort := range spec.Ports { - result = append(result, strconv.Itoa(int(servicePort.Port))) - } - return result -} - -// Extracts the protocols exposed by a service from the given service spec. -func getServiceProtocols(spec api.ServiceSpec) map[string]string { - result := make(map[string]string) - for _, servicePort := range spec.Ports { - result[strconv.Itoa(int(servicePort.Port))] = string(servicePort.Protocol) - } - return result -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_builder.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_builder.go deleted file mode 100644 index 98407d179..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_builder.go +++ /dev/null @@ -1,86 +0,0 @@ -/* -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. -*/ - -// this file contains factories with no other dependencies - -package util - -import ( - "os" - - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/kubernetes/pkg/kubectl/plugins" - "k8s.io/kubernetes/pkg/kubectl/resource" -) - -type ring2Factory struct { - clientAccessFactory ClientAccessFactory - objectMappingFactory ObjectMappingFactory -} - -func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFactory ObjectMappingFactory) BuilderFactory { - f := &ring2Factory{ - clientAccessFactory: clientAccessFactory, - objectMappingFactory: objectMappingFactory, - } - - return f -} - -// NewBuilder returns a new resource builder for structured api objects. -func (f *ring2Factory) NewBuilder() *resource.Builder { - clientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping) - mapper, typer := f.objectMappingFactory.Object() - - unstructuredClientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.UnstructuredClientForMapping) - - categoryExpander := f.objectMappingFactory.CategoryExpander() - - return resource.NewBuilder( - &resource.Mapper{ - RESTMapper: mapper, - ObjectTyper: typer, - ClientMapper: clientMapperFunc, - Decoder: InternalVersionDecoder(), - }, - &resource.Mapper{ - RESTMapper: mapper, - ObjectTyper: typer, - ClientMapper: unstructuredClientMapperFunc, - Decoder: unstructured.UnstructuredJSONScheme, - }, - categoryExpander, - ) -} - -// PluginLoader loads plugins from a path set by the KUBECTL_PLUGINS_PATH env var. -// If this env var is not set, it defaults to -// "~/.kube/plugins", plus -// "./kubectl/plugins" directory under the "data dir" directory specified by the XDG -// system directory structure spec for the given platform. -func (f *ring2Factory) PluginLoader() plugins.PluginLoader { - if len(os.Getenv("KUBECTL_PLUGINS_PATH")) > 0 { - return plugins.KubectlPluginsPathPluginLoader() - } - return plugins.TolerantMultiPluginLoader{ - plugins.XDGDataDirsPluginLoader(), - plugins.UserDirPluginLoader(), - } -} - -func (f *ring2Factory) PluginRunner() plugins.PluginRunner { - return &plugins.ExecPluginRunner{} -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_client_access.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_client_access.go index 4ca247309..43b4a1a9b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_client_access.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_client_access.go @@ -19,645 +19,173 @@ limitations under the License. package util import ( - "errors" - "flag" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "regexp" - "strings" - "time" - - "k8s.io/api/core/v1" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" - - appsv1 "k8s.io/api/apps/v1" - appsv1beta1 "k8s.io/api/apps/v1beta1" - appsv1beta2 "k8s.io/api/apps/v1beta2" - batchv1 "k8s.io/api/batch/v1" - batchv1beta1 "k8s.io/api/batch/v1beta1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" - extensionsv1beta1 "k8s.io/api/extensions/v1beta1" - apierrors "k8s.io/apimachinery/pkg/api/errors" + "sync" + "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/client-go/discovery" + "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/util/homedir" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/apis/apps" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/kubectl/util/transport" + "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" + openapivalidation "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + "k8s.io/kubernetes/pkg/kubectl/validation" ) -type ring0Factory struct { - flags *pflag.FlagSet - clientConfig clientcmd.ClientConfig - discoveryFactory DiscoveryClientFactory - clientCache *ClientCache -} - -func NewClientAccessFactory(optionalClientConfig clientcmd.ClientConfig) ClientAccessFactory { - flags := pflag.NewFlagSet("", pflag.ContinueOnError) - - clientConfig := optionalClientConfig - if optionalClientConfig == nil { - clientConfig = DefaultClientConfig(flags) - } - - return NewClientAccessFactoryFromDiscovery(flags, clientConfig, &discoveryFactory{clientConfig: clientConfig}) -} - -// NewClientAccessFactoryFromDiscovery allows an external caller to substitute a different discoveryFactory -// Which allows for the client cache to be built in ring0, but still rely on a custom discovery client -func NewClientAccessFactoryFromDiscovery(flags *pflag.FlagSet, clientConfig clientcmd.ClientConfig, discoveryFactory DiscoveryClientFactory) ClientAccessFactory { - flags.SetNormalizeFunc(utilflag.WarnWordSepNormalizeFunc) // Warn for "_" flags - - clientCache := NewClientCache(clientConfig, discoveryFactory) +type factoryImpl struct { + clientGetter genericclioptions.RESTClientGetter - f := &ring0Factory{ - flags: flags, - clientConfig: clientConfig, - discoveryFactory: discoveryFactory, - clientCache: clientCache, - } - - return f + // openAPIGetter loads and caches openapi specs + openAPIGetter openAPIGetter } -type discoveryFactory struct { - clientConfig clientcmd.ClientConfig - cacheDir string +type openAPIGetter struct { + once sync.Once + getter openapi.Getter } -func (f *discoveryFactory) DiscoveryClient() (discovery.CachedDiscoveryInterface, error) { - cfg, err := f.clientConfig.ClientConfig() - if err != nil { - return nil, err - } - - if f.cacheDir != "" { - wt := cfg.WrapTransport - cfg.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { - if wt != nil { - rt = wt(rt) - } - return transport.NewCacheRoundTripper(f.cacheDir, rt) - } +func NewFactory(clientGetter genericclioptions.RESTClientGetter) Factory { + if clientGetter == nil { + panic("attempt to instantiate client_access_factory with nil clientGetter") } - discoveryClient, err := discovery.NewDiscoveryClientForConfig(cfg) - if err != nil { - return nil, err + f := &factoryImpl{ + clientGetter: clientGetter, } - cacheDir := computeDiscoverCacheDir(filepath.Join(homedir.HomeDir(), ".kube", "cache", "discovery"), cfg.Host) - return NewCachedDiscoveryClient(discoveryClient, cacheDir, time.Duration(10*time.Minute)), nil -} - -func (f *discoveryFactory) BindFlags(flags *pflag.FlagSet) { - defaultCacheDir := filepath.Join(homedir.HomeDir(), ".kube", "http-cache") - flags.StringVar(&f.cacheDir, FlagHTTPCacheDir, defaultCacheDir, "Default HTTP cache directory") -} -// DefaultClientConfig creates a clientcmd.ClientConfig with the following hierarchy: -// 1. Use the kubeconfig builder. The number of merges and overrides here gets a little crazy. Stay with me. -// 1. Merge the kubeconfig itself. This is done with the following hierarchy rules: -// 1. CommandLineLocation - this parsed from the command line, so it must be late bound. If you specify this, -// then no other kubeconfig files are merged. This file must exist. -// 2. If $KUBECONFIG is set, then it is treated as a list of files that should be merged. -// 3. HomeDirectoryLocation -// Empty filenames are ignored. Files with non-deserializable content produced errors. -// The first file to set a particular value or map key wins and the value or map key is never changed. -// This means that the first file to set CurrentContext will have its context preserved. It also means -// that if two files specify a "red-user", only values from the first file's red-user are used. Even -// non-conflicting entries from the second file's "red-user" are discarded. -// 2. Determine the context to use based on the first hit in this chain -// 1. command line argument - again, parsed from the command line, so it must be late bound -// 2. CurrentContext from the merged kubeconfig file -// 3. Empty is allowed at this stage -// 3. Determine the cluster info and auth info to use. At this point, we may or may not have a context. They -// are built based on the first hit in this chain. (run it twice, once for auth, once for cluster) -// 1. command line argument -// 2. If context is present, then use the context value -// 3. Empty is allowed -// 4. Determine the actual cluster info to use. At this point, we may or may not have a cluster info. Build -// each piece of the cluster info based on the chain: -// 1. command line argument -// 2. If cluster info is present and a value for the attribute is present, use it. -// 3. If you don't have a server location, bail. -// 5. Auth info is build using the same rules as cluster info, EXCEPT that you can only have one authentication -// technique per auth info. The following conditions result in an error: -// 1. If there are two conflicting techniques specified from the command line, fail. -// 2. If the command line does not specify one, and the auth info has conflicting techniques, fail. -// 3. If the command line specifies one and the auth info specifies another, honor the command line technique. -// 2. Use default values and potentially prompt for auth information -// -// However, if it appears that we're running in a kubernetes cluster -// container environment, then run with the auth info kubernetes mounted for -// us. Specifically: -// The env vars KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT are -// set, and the file /var/run/secrets/kubernetes.io/serviceaccount/token -// exists and is not a directory. -func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig { - loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() - // use the standard defaults for this client command - // DEPRECATED: remove and replace with something more accurate - loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig - - flags.StringVar(&loadingRules.ExplicitPath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.") - - overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults} - - flagNames := clientcmd.RecommendedConfigOverrideFlags("") - // short flagnames are disabled by default. These are here for compatibility with existing scripts - flagNames.ClusterOverrideFlags.APIServer.ShortName = "s" - - clientcmd.BindOverrideFlags(overrides, flags, flagNames) - clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin) - - return clientConfig + return f } -func (f *ring0Factory) DiscoveryClient() (discovery.CachedDiscoveryInterface, error) { - return f.discoveryFactory.DiscoveryClient() +func (f *factoryImpl) ToRESTConfig() (*restclient.Config, error) { + return f.clientGetter.ToRESTConfig() } -func (f *ring0Factory) KubernetesClientSet() (*kubernetes.Clientset, error) { - return f.clientCache.KubernetesClientSetForVersion(nil) +func (f *factoryImpl) ToRESTMapper() (meta.RESTMapper, error) { + return f.clientGetter.ToRESTMapper() } -func (f *ring0Factory) ClientSet() (internalclientset.Interface, error) { - return f.clientCache.ClientSetForVersion(nil) +func (f *factoryImpl) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + return f.clientGetter.ToDiscoveryClient() } -func (f *ring0Factory) ClientConfig() (*restclient.Config, error) { - return f.clientCache.ClientConfigForVersion(nil) -} -func (f *ring0Factory) BareClientConfig() (*restclient.Config, error) { - return f.clientConfig.ClientConfig() +func (f *factoryImpl) ToRawKubeConfigLoader() clientcmd.ClientConfig { + return f.clientGetter.ToRawKubeConfigLoader() } -func (f *ring0Factory) RESTClient() (*restclient.RESTClient, error) { - clientConfig, err := f.clientCache.ClientConfigForVersion(nil) +func (f *factoryImpl) KubernetesClientSet() (*kubernetes.Clientset, error) { + clientConfig, err := f.ToRESTConfig() if err != nil { return nil, err } - return restclient.RESTClientFor(clientConfig) + return kubernetes.NewForConfig(clientConfig) } -func (f *ring0Factory) UpdatePodSpecForObject(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) { - // TODO: replace with a swagger schema based approach (identify pod template via schema introspection) - switch t := obj.(type) { - case *v1.Pod: - return true, fn(&t.Spec) - // ReplicationController - case *v1.ReplicationController: - if t.Spec.Template == nil { - t.Spec.Template = &v1.PodTemplateSpec{} - } - return true, fn(&t.Spec.Template.Spec) - // Deployment - case *extensionsv1beta1.Deployment: - return true, fn(&t.Spec.Template.Spec) - case *appsv1beta1.Deployment: - return true, fn(&t.Spec.Template.Spec) - case *appsv1beta2.Deployment: - return true, fn(&t.Spec.Template.Spec) - case *appsv1.Deployment: - return true, fn(&t.Spec.Template.Spec) - // DaemonSet - case *extensionsv1beta1.DaemonSet: - return true, fn(&t.Spec.Template.Spec) - case *appsv1beta2.DaemonSet: - return true, fn(&t.Spec.Template.Spec) - case *appsv1.DaemonSet: - return true, fn(&t.Spec.Template.Spec) - // ReplicaSet - case *extensionsv1beta1.ReplicaSet: - return true, fn(&t.Spec.Template.Spec) - case *appsv1beta2.ReplicaSet: - return true, fn(&t.Spec.Template.Spec) - case *appsv1.ReplicaSet: - return true, fn(&t.Spec.Template.Spec) - // StatefulSet - case *appsv1beta1.StatefulSet: - return true, fn(&t.Spec.Template.Spec) - case *appsv1beta2.StatefulSet: - return true, fn(&t.Spec.Template.Spec) - case *appsv1.StatefulSet: - return true, fn(&t.Spec.Template.Spec) - // Job - case *batchv1.Job: - return true, fn(&t.Spec.Template.Spec) - // CronJob - case *batchv1beta1.CronJob: - return true, fn(&t.Spec.JobTemplate.Spec.Template.Spec) - case *batchv2alpha1.CronJob: - return true, fn(&t.Spec.JobTemplate.Spec.Template.Spec) - default: - return false, fmt.Errorf("the object is not a pod or does not have a pod template") +func (f *factoryImpl) ClientSet() (internalclientset.Interface, error) { + clientConfig, err := f.ToRESTConfig() + if err != nil { + return nil, err } + return internalclientset.NewForConfig(clientConfig) } -func (f *ring0Factory) MapBasedSelectorForObject(object runtime.Object) (string, error) { - // TODO: replace with a swagger schema based approach (identify pod selector via schema introspection) - switch t := object.(type) { - case *api.ReplicationController: - return kubectl.MakeLabels(t.Spec.Selector), nil - case *api.Pod: - if len(t.Labels) == 0 { - return "", fmt.Errorf("the pod has no labels and cannot be exposed") - } - return kubectl.MakeLabels(t.Labels), nil - case *api.Service: - if t.Spec.Selector == nil { - return "", fmt.Errorf("the service has no pod selector set") - } - return kubectl.MakeLabels(t.Spec.Selector), nil - case *extensions.Deployment: - // TODO(madhusudancs): Make this smarter by admitting MatchExpressions with Equals - // operator, DoubleEquals operator and In operator with only one element in the set. - if len(t.Spec.Selector.MatchExpressions) > 0 { - return "", fmt.Errorf("couldn't convert expressions - \"%+v\" to map-based selector format", t.Spec.Selector.MatchExpressions) - } - return kubectl.MakeLabels(t.Spec.Selector.MatchLabels), nil - case *extensions.ReplicaSet: - // TODO(madhusudancs): Make this smarter by admitting MatchExpressions with Equals - // operator, DoubleEquals operator and In operator with only one element in the set. - if len(t.Spec.Selector.MatchExpressions) > 0 { - return "", fmt.Errorf("couldn't convert expressions - \"%+v\" to map-based selector format", t.Spec.Selector.MatchExpressions) - } - return kubectl.MakeLabels(t.Spec.Selector.MatchLabels), nil - default: - return "", fmt.Errorf("cannot extract pod selector from %T", object) +func (f *factoryImpl) DynamicClient() (dynamic.Interface, error) { + clientConfig, err := f.ToRESTConfig() + if err != nil { + return nil, err } + return dynamic.NewForConfig(clientConfig) } -func (f *ring0Factory) PortsForObject(object runtime.Object) ([]string, error) { - // TODO: replace with a swagger schema based approach (identify pod selector via schema introspection) - switch t := object.(type) { - case *api.ReplicationController: - return getPorts(t.Spec.Template.Spec), nil - case *api.Pod: - return getPorts(t.Spec), nil - case *api.Service: - return getServicePorts(t.Spec), nil - case *extensions.Deployment: - return getPorts(t.Spec.Template.Spec), nil - case *extensions.ReplicaSet: - return getPorts(t.Spec.Template.Spec), nil - default: - return nil, fmt.Errorf("cannot extract ports from %T", object) - } +// NewBuilder returns a new resource builder for structured api objects. +func (f *factoryImpl) NewBuilder() *resource.Builder { + return resource.NewBuilder(f.clientGetter) } -func (f *ring0Factory) ProtocolsForObject(object runtime.Object) (map[string]string, error) { - // TODO: replace with a swagger schema based approach (identify pod selector via schema introspection) - switch t := object.(type) { - case *api.ReplicationController: - return getProtocols(t.Spec.Template.Spec), nil - case *api.Pod: - return getProtocols(t.Spec), nil - case *api.Service: - return getServiceProtocols(t.Spec), nil - case *extensions.Deployment: - return getProtocols(t.Spec.Template.Spec), nil - case *extensions.ReplicaSet: - return getProtocols(t.Spec.Template.Spec), nil - default: - return nil, fmt.Errorf("cannot extract protocols from %T", object) +func (f *factoryImpl) RESTClient() (*restclient.RESTClient, error) { + clientConfig, err := f.ToRESTConfig() + if err != nil { + return nil, err } + setKubernetesDefaults(clientConfig) + return restclient.RESTClientFor(clientConfig) } -func (f *ring0Factory) LabelsForObject(object runtime.Object) (map[string]string, error) { - return meta.NewAccessor().Labels(object) -} - -func (f *ring0Factory) FlagSet() *pflag.FlagSet { - return f.flags -} - -// Set showSecrets false to filter out stuff like secrets. -func (f *ring0Factory) Command(cmd *cobra.Command, showSecrets bool) string { - if len(os.Args) == 0 { - return "" - } - - flags := "" - parseFunc := func(flag *pflag.Flag, value string) error { - flags = flags + " --" + flag.Name - if set, ok := flag.Annotations["classified"]; showSecrets || !ok || len(set) == 0 { - flags = flags + "=" + value - } else { - flags = flags + "=CLASSIFIED" - } - return nil - } - var err error - err = cmd.Flags().ParseAll(os.Args[1:], parseFunc) - if err != nil || !cmd.Flags().Parsed() { - return "" - } - - args := "" - if arguments := cmd.Flags().Args(); len(arguments) > 0 { - args = " " + strings.Join(arguments, " ") +func (f *factoryImpl) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { + cfg, err := f.clientGetter.ToRESTConfig() + if err != nil { + return nil, err } - - base := filepath.Base(os.Args[0]) - return base + args + flags -} - -func (f *ring0Factory) BindFlags(flags *pflag.FlagSet) { - // Merge factory's flags - flags.AddFlagSet(f.flags) - - // Globally persistent flags across all subcommands. - // TODO Change flag names to consts to allow safer lookup from subcommands. - // TODO Add a verbose flag that turns on glog logging. Probably need a way - // to do that automatically for every subcommand. - flags.BoolVar(&f.clientCache.matchVersion, FlagMatchBinaryVersion, false, "Require server version to match client version") - - f.discoveryFactory.BindFlags(flags) - - // Normalize all flags that are coming from other packages or pre-configurations - // a.k.a. change all "_" to "-". e.g. glog package - flags.SetNormalizeFunc(utilflag.WordSepNormalizeFunc) -} - -func (f *ring0Factory) BindExternalFlags(flags *pflag.FlagSet) { - // any flags defined by external projects (not part of pflags) - flags.AddGoFlagSet(flag.CommandLine) -} - -func (f *ring0Factory) DefaultResourceFilterFunc() kubectl.Filters { - return kubectl.NewResourceFilter() -} - -func (f *ring0Factory) SuggestedPodTemplateResources() []schema.GroupResource { - return []schema.GroupResource{ - {Resource: "replicationcontroller"}, - {Resource: "deployment"}, - {Resource: "daemonset"}, - {Resource: "job"}, - {Resource: "replicaset"}, + if err := setKubernetesDefaults(cfg); err != nil { + return nil, err } -} - -func (f *ring0Factory) Pauser(info *resource.Info) ([]byte, error) { - switch obj := info.Object.(type) { - case *extensions.Deployment: - if obj.Spec.Paused { - return nil, errors.New("is already paused") - } - obj.Spec.Paused = true - return runtime.Encode(InternalVersionJSONEncoder(), info.Object) + gvk := mapping.GroupVersionKind + switch gvk.Group { + case api.GroupName: + cfg.APIPath = "/api" default: - return nil, fmt.Errorf("pausing is not supported") + cfg.APIPath = "/apis" } + gv := gvk.GroupVersion() + cfg.GroupVersion = &gv + return restclient.RESTClientFor(cfg) } -func (f *ring0Factory) ResolveImage(name string) (string, error) { - return name, nil -} - -func (f *ring0Factory) Resumer(info *resource.Info) ([]byte, error) { - switch obj := info.Object.(type) { - case *extensions.Deployment: - if !obj.Spec.Paused { - return nil, errors.New("is not paused") - } - obj.Spec.Paused = false - return runtime.Encode(InternalVersionJSONEncoder(), info.Object) - default: - return nil, fmt.Errorf("resuming is not supported") +func (f *factoryImpl) UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { + cfg, err := f.clientGetter.ToRESTConfig() + if err != nil { + return nil, err } -} - -func (f *ring0Factory) DefaultNamespace() (string, bool, error) { - return f.clientConfig.Namespace() -} - -const ( - // TODO(sig-cli): Enforce consistent naming for generators here. - // See discussion in https://github.com/kubernetes/kubernetes/issues/46237 - // before you add any more. - RunV1GeneratorName = "run/v1" - RunPodV1GeneratorName = "run-pod/v1" - ServiceV1GeneratorName = "service/v1" - ServiceV2GeneratorName = "service/v2" - ServiceNodePortGeneratorV1Name = "service-nodeport/v1" - ServiceClusterIPGeneratorV1Name = "service-clusterip/v1" - ServiceLoadBalancerGeneratorV1Name = "service-loadbalancer/v1" - ServiceExternalNameGeneratorV1Name = "service-externalname/v1" - ServiceAccountV1GeneratorName = "serviceaccount/v1" - HorizontalPodAutoscalerV1GeneratorName = "horizontalpodautoscaler/v1" - DeploymentV1Beta1GeneratorName = "deployment/v1beta1" - DeploymentAppsV1Beta1GeneratorName = "deployment/apps.v1beta1" - DeploymentBasicV1Beta1GeneratorName = "deployment-basic/v1beta1" - DeploymentBasicAppsV1Beta1GeneratorName = "deployment-basic/apps.v1beta1" - JobV1GeneratorName = "job/v1" - CronJobV2Alpha1GeneratorName = "cronjob/v2alpha1" - CronJobV1Beta1GeneratorName = "cronjob/v1beta1" - NamespaceV1GeneratorName = "namespace/v1" - ResourceQuotaV1GeneratorName = "resourcequotas/v1" - SecretV1GeneratorName = "secret/v1" - SecretForDockerRegistryV1GeneratorName = "secret-for-docker-registry/v1" - SecretForTLSV1GeneratorName = "secret-for-tls/v1" - ConfigMapV1GeneratorName = "configmap/v1" - ClusterRoleBindingV1GeneratorName = "clusterrolebinding.rbac.authorization.k8s.io/v1alpha1" - RoleBindingV1GeneratorName = "rolebinding.rbac.authorization.k8s.io/v1alpha1" - ClusterV1Beta1GeneratorName = "cluster/v1beta1" - PodDisruptionBudgetV1GeneratorName = "poddisruptionbudget/v1beta1" - PodDisruptionBudgetV2GeneratorName = "poddisruptionbudget/v1beta1/v2" - PriorityClassV1Alpha1GeneratorName = "priorityclass/v1alpha1" -) - -// DefaultGenerators returns the set of default generators for use in Factory instances -func DefaultGenerators(cmdName string) map[string]kubectl.Generator { - var generator map[string]kubectl.Generator - switch cmdName { - case "expose": - generator = map[string]kubectl.Generator{ - ServiceV1GeneratorName: kubectl.ServiceGeneratorV1{}, - ServiceV2GeneratorName: kubectl.ServiceGeneratorV2{}, - } - case "service-clusterip": - generator = map[string]kubectl.Generator{ - ServiceClusterIPGeneratorV1Name: kubectl.ServiceClusterIPGeneratorV1{}, - } - case "service-nodeport": - generator = map[string]kubectl.Generator{ - ServiceNodePortGeneratorV1Name: kubectl.ServiceNodePortGeneratorV1{}, - } - case "service-loadbalancer": - generator = map[string]kubectl.Generator{ - ServiceLoadBalancerGeneratorV1Name: kubectl.ServiceLoadBalancerGeneratorV1{}, - } - case "deployment": - // Create Deployment has only StructuredGenerators and no - // param-based Generators. - // The StructuredGenerators are as follows (as of 2017-07-17): - // DeploymentBasicV1Beta1GeneratorName -> kubectl.DeploymentBasicGeneratorV1 - // DeploymentBasicAppsV1Beta1GeneratorName -> kubectl.DeploymentBasicAppsGeneratorV1 - generator = map[string]kubectl.Generator{} - case "run": - generator = map[string]kubectl.Generator{ - RunV1GeneratorName: kubectl.BasicReplicationController{}, - RunPodV1GeneratorName: kubectl.BasicPod{}, - DeploymentV1Beta1GeneratorName: kubectl.DeploymentV1Beta1{}, - DeploymentAppsV1Beta1GeneratorName: kubectl.DeploymentAppsV1Beta1{}, - JobV1GeneratorName: kubectl.JobV1{}, - CronJobV2Alpha1GeneratorName: kubectl.CronJobV2Alpha1{}, - CronJobV1Beta1GeneratorName: kubectl.CronJobV1Beta1{}, - } - case "namespace": - generator = map[string]kubectl.Generator{ - NamespaceV1GeneratorName: kubectl.NamespaceGeneratorV1{}, - } - case "quota": - generator = map[string]kubectl.Generator{ - ResourceQuotaV1GeneratorName: kubectl.ResourceQuotaGeneratorV1{}, - } - case "secret": - generator = map[string]kubectl.Generator{ - SecretV1GeneratorName: kubectl.SecretGeneratorV1{}, - } - case "secret-for-docker-registry": - generator = map[string]kubectl.Generator{ - SecretForDockerRegistryV1GeneratorName: kubectl.SecretForDockerRegistryGeneratorV1{}, - } - case "secret-for-tls": - generator = map[string]kubectl.Generator{ - SecretForTLSV1GeneratorName: kubectl.SecretForTLSGeneratorV1{}, - } + if err := restclient.SetKubernetesDefaults(cfg); err != nil { + return nil, err } - - return generator -} - -// fallbackGeneratorNameIfNecessary returns the name of the old generator -// if server does not support new generator. Otherwise, the -// generator string is returned unchanged. -// -// If the generator name is changed, print a warning message to let the user -// know. -func FallbackGeneratorNameIfNecessary( - generatorName string, - discoveryClient discovery.DiscoveryInterface, - cmdErr io.Writer, -) (string, error) { - switch generatorName { - case DeploymentBasicAppsV1Beta1GeneratorName: - hasResource, err := HasResource(discoveryClient, appsv1beta1.SchemeGroupVersion.WithResource("deployments")) - if err != nil { - return "", err - } - if !hasResource { - warning(cmdErr, DeploymentBasicAppsV1Beta1GeneratorName, DeploymentBasicV1Beta1GeneratorName) - return DeploymentBasicV1Beta1GeneratorName, nil - } - case CronJobV2Alpha1GeneratorName: - hasResource, err := HasResource(discoveryClient, batchv2alpha1.SchemeGroupVersion.WithResource("cronjobs")) - if err != nil { - return "", err - } - if !hasResource { - warning(cmdErr, CronJobV2Alpha1GeneratorName, JobV1GeneratorName) - return JobV1GeneratorName, nil - } + cfg.APIPath = "/apis" + if mapping.GroupVersionKind.Group == api.GroupName { + cfg.APIPath = "/api" } - return generatorName, nil -} - -func warning(cmdErr io.Writer, newGeneratorName, oldGeneratorName string) { - fmt.Fprintf(cmdErr, "WARNING: New deployments generator %q specified, "+ - "but it isn't available. "+ - "Falling back to %q.\n", - newGeneratorName, - oldGeneratorName, - ) + gv := mapping.GroupVersionKind.GroupVersion() + cfg.ContentConfig = resource.UnstructuredPlusDefaultContentConfig() + cfg.GroupVersion = &gv + return restclient.RESTClientFor(cfg) } -func HasResource(client discovery.DiscoveryInterface, resource schema.GroupVersionResource) (bool, error) { - resources, err := client.ServerResourcesForGroupVersion(resource.GroupVersion().String()) - if apierrors.IsNotFound(err) { - // entire group is missing - return false, nil +func (f *factoryImpl) Validator(validate bool) (validation.Schema, error) { + if !validate { + return validation.NullSchema{}, nil } + + resources, err := f.OpenAPISchema() if err != nil { - // other errors error - return false, fmt.Errorf("failed to discover supported resources: %v", err) - } - for _, serverResource := range resources.APIResources { - if serverResource.Name == resource.Resource { - return true, nil - } + return nil, err } - return false, nil -} - -func Contains(resourcesList []*metav1.APIResourceList, resource schema.GroupVersionResource) bool { - resources := discovery.FilteredBy(discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool { - return resource.GroupVersion().String() == gv && resource.Resource == r.Name - }), resourcesList) - return len(resources) != 0 -} - -func (f *ring0Factory) Generators(cmdName string) map[string]kubectl.Generator { - return DefaultGenerators(cmdName) -} -func (f *ring0Factory) CanBeExposed(kind schema.GroupKind) error { - switch kind { - case api.Kind("ReplicationController"), api.Kind("Service"), api.Kind("Pod"), - extensions.Kind("Deployment"), apps.Kind("Deployment"), extensions.Kind("ReplicaSet"), apps.Kind("ReplicaSet"): - // nothing to do here - default: - return fmt.Errorf("cannot expose a %s", kind) - } - return nil + return validation.ConjunctiveSchema{ + openapivalidation.NewSchemaValidation(resources), + validation.NoDoubleKeySchema{}, + }, nil } -func (f *ring0Factory) CanBeAutoscaled(kind schema.GroupKind) error { - switch kind { - case api.Kind("ReplicationController"), extensions.Kind("ReplicaSet"), - extensions.Kind("Deployment"), apps.Kind("Deployment"), apps.Kind("ReplicaSet"): - // nothing to do here - default: - return fmt.Errorf("cannot autoscale a %v", kind) +// OpenAPISchema returns metadata and structural information about Kubernetes object definitions. +func (f *factoryImpl) OpenAPISchema() (openapi.Resources, error) { + discovery, err := f.clientGetter.ToDiscoveryClient() + if err != nil { + return nil, err } - return nil -} - -func (f *ring0Factory) EditorEnvs() []string { - return []string{"KUBE_EDITOR", "EDITOR"} -} - -// overlyCautiousIllegalFileCharacters matches characters that *might* not be supported. Windows is really restrictive, so this is really restrictive -var overlyCautiousIllegalFileCharacters = regexp.MustCompile(`[^(\w/\.)]`) -// computeDiscoverCacheDir takes the parentDir and the host and comes up with a "usually non-colliding" name. -func computeDiscoverCacheDir(parentDir, host string) string { - // strip the optional scheme from host if its there: - schemelessHost := strings.Replace(strings.Replace(host, "https://", "", 1), "http://", "", 1) - // now do a simple collapse of non-AZ09 characters. Collisions are possible but unlikely. Even if we do collide the problem is short lived - safeHost := overlyCautiousIllegalFileCharacters.ReplaceAllString(schemelessHost, "_") + // Lazily initialize the OpenAPIGetter once + f.openAPIGetter.once.Do(func() { + // Create the caching OpenAPIGetter + f.openAPIGetter.getter = openapi.NewOpenAPIGetter(discovery) + }) - return filepath.Join(parentDir, safeHost) + // Delegate to the OpenAPIGetter + return f.openAPIGetter.getter.Get() } // this method exists to help us find the points still relying on internal types. @@ -666,5 +194,6 @@ func InternalVersionDecoder() runtime.Decoder { } func InternalVersionJSONEncoder() runtime.Encoder { - return legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...) + encoder := legacyscheme.Codecs.LegacyCodec(legacyscheme.Scheme.PrioritizedVersionsAllGroups()...) + return unstructured.JSONFallbackEncoder{Encoder: encoder} } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping.go deleted file mode 100644 index 835fe7992..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping.go +++ /dev/null @@ -1,451 +0,0 @@ -/* -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. -*/ - -// this file contains factories with no other dependencies - -package util - -import ( - "errors" - "fmt" - "os" - "reflect" - "sort" - "sync" - "time" - - "github.com/golang/glog" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/discovery" - "k8s.io/client-go/dynamic" - restclient "k8s.io/client-go/rest" - scaleclient "k8s.io/client-go/scale" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/apis/batch" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/categories" - "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - openapivalidation "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/kubectl/validation" - "k8s.io/kubernetes/pkg/printers" - printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" -) - -type ring1Factory struct { - clientAccessFactory ClientAccessFactory - - // openAPIGetter loads and caches openapi specs - openAPIGetter openAPIGetter -} - -type openAPIGetter struct { - once sync.Once - getter openapi.Getter -} - -func NewObjectMappingFactory(clientAccessFactory ClientAccessFactory) ObjectMappingFactory { - f := &ring1Factory{ - clientAccessFactory: clientAccessFactory, - } - return f -} - -// objectLoader attempts to perform discovery against the server, and will fall back to -// the built in mapper if necessary. It supports unstructured objects either way, since -// the underlying Scheme supports Unstructured. The mapper will return converters that can -// convert versioned types to unstructured and back. -func (f *ring1Factory) objectLoader() (meta.RESTMapper, runtime.ObjectTyper, error) { - discoveryClient, err := f.clientAccessFactory.DiscoveryClient() - if err != nil { - glog.V(3).Infof("Unable to get a discovery client to find server resources, falling back to hardcoded types: %v", err) - return legacyscheme.Registry.RESTMapper(), legacyscheme.Scheme, nil - } - - groupResources, err := discovery.GetAPIGroupResources(discoveryClient) - if err != nil && !discoveryClient.Fresh() { - discoveryClient.Invalidate() - groupResources, err = discovery.GetAPIGroupResources(discoveryClient) - } - if err != nil { - glog.V(3).Infof("Unable to retrieve API resources, falling back to hardcoded types: %v", err) - return legacyscheme.Registry.RESTMapper(), legacyscheme.Scheme, nil - } - - // allow conversion between typed and unstructured objects - interfaces := meta.InterfacesForUnstructuredConversion(legacyscheme.Registry.InterfacesFor) - mapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient, meta.VersionInterfacesFunc(interfaces)) - // TODO: should this also indicate it recognizes typed objects? - typer := discovery.NewUnstructuredObjectTyper(groupResources, legacyscheme.Scheme) - expander := NewShortcutExpander(mapper, discoveryClient) - return expander, typer, err -} - -func (f *ring1Factory) Object() (meta.RESTMapper, runtime.ObjectTyper) { - return meta.NewLazyObjectLoader(f.objectLoader) -} - -func (f *ring1Factory) CategoryExpander() categories.CategoryExpander { - legacyExpander := categories.LegacyCategoryExpander - - discoveryClient, err := f.clientAccessFactory.DiscoveryClient() - if err == nil { - // fallback is the legacy expander wrapped with discovery based filtering - fallbackExpander, err := categories.NewDiscoveryFilteredExpander(legacyExpander, discoveryClient) - CheckErr(err) - - // by default use the expander that discovers based on "categories" field from the API - discoveryCategoryExpander, err := categories.NewDiscoveryCategoryExpander(fallbackExpander, discoveryClient) - CheckErr(err) - - return discoveryCategoryExpander - } - - return legacyExpander -} - -func (f *ring1Factory) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { - cfg, err := f.clientAccessFactory.ClientConfig() - if err != nil { - return nil, err - } - if err := setKubernetesDefaults(cfg); err != nil { - return nil, err - } - gvk := mapping.GroupVersionKind - switch gvk.Group { - case api.GroupName: - cfg.APIPath = "/api" - default: - cfg.APIPath = "/apis" - } - gv := gvk.GroupVersion() - cfg.GroupVersion = &gv - return restclient.RESTClientFor(cfg) -} - -func (f *ring1Factory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { - cfg, err := f.clientAccessFactory.BareClientConfig() - if err != nil { - return nil, err - } - if err := restclient.SetKubernetesDefaults(cfg); err != nil { - return nil, err - } - cfg.APIPath = "/apis" - if mapping.GroupVersionKind.Group == api.GroupName { - cfg.APIPath = "/api" - } - gv := mapping.GroupVersionKind.GroupVersion() - cfg.ContentConfig = dynamic.ContentConfig() - cfg.GroupVersion = &gv - return restclient.RESTClientFor(cfg) -} - -func (f *ring1Factory) Describer(mapping *meta.RESTMapping) (printers.Describer, error) { - clientset, err := f.clientAccessFactory.ClientSet() - if err != nil { - // if we can't make a client for this group/version, go generic if possible - if genericDescriber, genericErr := genericDescriber(f.clientAccessFactory, mapping); genericErr == nil { - return genericDescriber, nil - } - // otherwise return the original error - return nil, err - } - - // try to get a describer - if describer, ok := printersinternal.DescriberFor(mapping.GroupVersionKind.GroupKind(), clientset); ok { - return describer, nil - } - // if this is a kind we don't have a describer for yet, go generic if possible - if genericDescriber, genericErr := genericDescriber(f.clientAccessFactory, mapping); genericErr == nil { - return genericDescriber, nil - } - // otherwise return an unregistered error - return nil, fmt.Errorf("no description has been implemented for %s", mapping.GroupVersionKind.String()) -} - -// helper function to make a generic describer, or return an error -func genericDescriber(clientAccessFactory ClientAccessFactory, mapping *meta.RESTMapping) (printers.Describer, error) { - clientConfig, err := clientAccessFactory.ClientConfig() - if err != nil { - return nil, err - } - - clientConfigCopy := *clientConfig - clientConfigCopy.APIPath = dynamic.LegacyAPIPathResolverFunc(mapping.GroupVersionKind) - gv := mapping.GroupVersionKind.GroupVersion() - clientConfigCopy.GroupVersion = &gv - - // used to fetch the resource - dynamicClient, err := dynamic.NewClient(&clientConfigCopy) - if err != nil { - return nil, err - } - - // used to get events for the resource - clientSet, err := clientAccessFactory.ClientSet() - if err != nil { - return nil, err - } - eventsClient := clientSet.Core() - - return printersinternal.GenericDescriberFor(mapping, dynamicClient, eventsClient), nil -} - -func (f *ring1Factory) LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) { - clientset, err := f.clientAccessFactory.ClientSet() - if err != nil { - return nil, err - } - opts, ok := options.(*api.PodLogOptions) - if !ok { - return nil, errors.New("provided options object is not a PodLogOptions") - } - - var selector labels.Selector - var namespace string - switch t := object.(type) { - case *api.Pod: - return clientset.Core().Pods(t.Namespace).GetLogs(t.Name, opts), nil - - case *api.ReplicationController: - namespace = t.Namespace - selector = labels.SelectorFromSet(t.Spec.Selector) - - case *extensions.ReplicaSet: - namespace = t.Namespace - selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) - if err != nil { - return nil, fmt.Errorf("invalid label selector: %v", err) - } - - case *extensions.Deployment: - namespace = t.Namespace - selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) - if err != nil { - return nil, fmt.Errorf("invalid label selector: %v", err) - } - - case *batch.Job: - namespace = t.Namespace - selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) - if err != nil { - return nil, fmt.Errorf("invalid label selector: %v", err) - } - - case *apps.StatefulSet: - namespace = t.Namespace - selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) - if err != nil { - return nil, fmt.Errorf("invalid label selector: %v", err) - } - - default: - return nil, fmt.Errorf("cannot get the logs from %T", object) - } - - sortBy := func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) } - pod, numPods, err := GetFirstPod(clientset.Core(), namespace, selector.String(), timeout, sortBy) - if err != nil { - return nil, err - } - if numPods > 1 { - fmt.Fprintf(os.Stderr, "Found %v pods, using pod/%v\n", numPods, pod.Name) - } - return clientset.Core().Pods(pod.Namespace).GetLogs(pod.Name, opts), nil -} - -func (f *ring1Factory) Scaler(mapping *meta.RESTMapping) (kubectl.Scaler, error) { - clientset, err := f.clientAccessFactory.ClientSet() - if err != nil { - return nil, err - } - - // create scales getter - // TODO(p0lyn0mial): put scalesGetter to a factory - discoClient, err := f.clientAccessFactory.DiscoveryClient() - if err != nil { - return nil, err - } - restClient, err := f.clientAccessFactory.RESTClient() - if err != nil { - return nil, err - } - mapper, _ := f.Object() - resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient) - scalesGetter := scaleclient.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver) - gvk := mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource) - - return kubectl.ScalerFor(mapping.GroupVersionKind.GroupKind(), clientset.Batch(), scalesGetter, gvk.GroupResource()), nil -} - -func (f *ring1Factory) Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, error) { - clientset, clientsetErr := f.clientAccessFactory.ClientSet() - reaper, reaperErr := kubectl.ReaperFor(mapping.GroupVersionKind.GroupKind(), clientset) - - if kubectl.IsNoSuchReaperError(reaperErr) { - return nil, reaperErr - } - if clientsetErr != nil { - return nil, clientsetErr - } - return reaper, reaperErr -} - -func (f *ring1Factory) HistoryViewer(mapping *meta.RESTMapping) (kubectl.HistoryViewer, error) { - external, err := f.clientAccessFactory.KubernetesClientSet() - if err != nil { - return nil, err - } - return kubectl.HistoryViewerFor(mapping.GroupVersionKind.GroupKind(), external) -} - -func (f *ring1Factory) Rollbacker(mapping *meta.RESTMapping) (kubectl.Rollbacker, error) { - external, err := f.clientAccessFactory.KubernetesClientSet() - if err != nil { - return nil, err - } - return kubectl.RollbackerFor(mapping.GroupVersionKind.GroupKind(), external) -} - -func (f *ring1Factory) StatusViewer(mapping *meta.RESTMapping) (kubectl.StatusViewer, error) { - clientset, err := f.clientAccessFactory.KubernetesClientSet() - if err != nil { - return nil, err - } - return kubectl.StatusViewerFor(mapping.GroupVersionKind.GroupKind(), clientset) -} - -func (f *ring1Factory) ApproximatePodTemplateForObject(object runtime.Object) (*api.PodTemplateSpec, error) { - switch t := object.(type) { - case *api.Pod: - return &api.PodTemplateSpec{ - ObjectMeta: t.ObjectMeta, - Spec: t.Spec, - }, nil - case *api.ReplicationController: - return t.Spec.Template, nil - case *extensions.ReplicaSet: - return &t.Spec.Template, nil - case *extensions.DaemonSet: - return &t.Spec.Template, nil - case *extensions.Deployment: - return &t.Spec.Template, nil - case *batch.Job: - return &t.Spec.Template, nil - } - - return nil, fmt.Errorf("unable to extract pod template from type %v", reflect.TypeOf(object)) -} - -func (f *ring1Factory) AttachablePodForObject(object runtime.Object, timeout time.Duration) (*api.Pod, error) { - clientset, err := f.clientAccessFactory.ClientSet() - if err != nil { - return nil, err - } - var selector labels.Selector - var namespace string - switch t := object.(type) { - case *extensions.ReplicaSet: - namespace = t.Namespace - selector = labels.SelectorFromSet(t.Spec.Selector.MatchLabels) - - case *api.ReplicationController: - namespace = t.Namespace - selector = labels.SelectorFromSet(t.Spec.Selector) - - case *apps.StatefulSet: - namespace = t.Namespace - selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) - if err != nil { - return nil, fmt.Errorf("invalid label selector: %v", err) - } - - case *extensions.Deployment: - namespace = t.Namespace - selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) - if err != nil { - return nil, fmt.Errorf("invalid label selector: %v", err) - } - - case *batch.Job: - namespace = t.Namespace - selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) - if err != nil { - return nil, fmt.Errorf("invalid label selector: %v", err) - } - - case *api.Service: - namespace = t.Namespace - if t.Spec.Selector == nil || len(t.Spec.Selector) == 0 { - return nil, fmt.Errorf("invalid service '%s': Service is defined without a selector", t.Name) - } - selector = labels.SelectorFromSet(t.Spec.Selector) - - case *api.Pod: - return t, nil - - default: - return nil, fmt.Errorf("cannot attach to %T: not implemented", object) - } - - sortBy := func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) } - pod, _, err := GetFirstPod(clientset.Core(), namespace, selector.String(), timeout, sortBy) - return pod, err -} - -func (f *ring1Factory) Validator(validate bool) (validation.Schema, error) { - if !validate { - return validation.NullSchema{}, nil - } - - resources, err := f.OpenAPISchema() - if err != nil { - return nil, err - } - - return validation.ConjunctiveSchema{ - openapivalidation.NewSchemaValidation(resources), - validation.NoDoubleKeySchema{}, - }, nil -} - -// OpenAPISchema returns metadata and structural information about Kubernetes object definitions. -func (f *ring1Factory) OpenAPISchema() (openapi.Resources, error) { - discovery, err := f.clientAccessFactory.DiscoveryClient() - if err != nil { - return nil, err - } - - // Lazily initialize the OpenAPIGetter once - f.openAPIGetter.once.Do(func() { - // Create the caching OpenAPIGetter - f.openAPIGetter.getter = openapi.NewOpenAPIGetter(discovery) - }) - - // Delegate to the OpenAPIGetter - return f.openAPIGetter.getter.Get() -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping_test.go deleted file mode 100644 index c2e763f16..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping_test.go +++ /dev/null @@ -1,194 +0,0 @@ -/* -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 util - -import ( - "reflect" - "testing" - "time" - - 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" - testclient "k8s.io/client-go/testing" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/apis/batch" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" -) - -type fakeClientAccessFactory struct { - ClientAccessFactory - - fakeClientset *fake.Clientset -} - -func (f *fakeClientAccessFactory) ClientSet() (internalclientset.Interface, error) { - return f.fakeClientset, nil -} - -func newFakeClientAccessFactory(objs []runtime.Object) *fakeClientAccessFactory { - return &fakeClientAccessFactory{ - fakeClientset: fake.NewSimpleClientset(objs...), - } -} - -var ( - podsResource = schema.GroupVersionResource{Resource: "pods"} - podsKind = schema.GroupVersionKind{Kind: "Pod"} -) - -func TestLogsForObject(t *testing.T) { - tests := []struct { - name string - obj runtime.Object - opts *api.PodLogOptions - pods []runtime.Object - actions []testclient.Action - }{ - { - name: "pod logs", - obj: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, - }, - pods: []runtime.Object{testPod()}, - actions: []testclient.Action{ - getLogsAction("test", nil), - }, - }, - { - name: "replication controller logs", - obj: &api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{"foo": "bar"}, - }, - }, - pods: []runtime.Object{testPod()}, - actions: []testclient.Action{ - testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), - getLogsAction("test", nil), - }, - }, - { - name: "replica set logs", - obj: &extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, - Spec: extensions.ReplicaSetSpec{ - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - pods: []runtime.Object{testPod()}, - actions: []testclient.Action{ - testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), - getLogsAction("test", nil), - }, - }, - { - name: "deployment logs", - obj: &extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, - Spec: extensions.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - pods: []runtime.Object{testPod()}, - actions: []testclient.Action{ - testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), - getLogsAction("test", nil), - }, - }, - { - name: "job logs", - obj: &batch.Job{ - ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, - Spec: batch.JobSpec{ - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - pods: []runtime.Object{testPod()}, - actions: []testclient.Action{ - testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), - getLogsAction("test", nil), - }, - }, - { - name: "stateful set logs", - obj: &apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, - Spec: apps.StatefulSetSpec{ - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - pods: []runtime.Object{testPod()}, - actions: []testclient.Action{ - testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), - getLogsAction("test", nil), - }, - }, - } - - for _, test := range tests { - caf := newFakeClientAccessFactory(test.pods) - omf := NewObjectMappingFactory(caf) - _, err := omf.LogsForObject(test.obj, test.opts, 20*time.Second) - if err != nil { - t.Errorf("%s: unexpected error: %v", test.name, err) - continue - } - for i := range test.actions { - if len(caf.fakeClientset.Actions()) < i { - t.Errorf("%s: action %d does not exists in actual actions: %#v", - test.name, i, caf.fakeClientset.Actions()) - continue - } - got := caf.fakeClientset.Actions()[i] - want := test.actions[i] - if !reflect.DeepEqual(got, want) { - t.Errorf("%s: unexpected action: %s", test.name, diff.ObjectDiff(got, want)) - } - } - } -} - -func testPod() runtime.Object { - return &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "test", - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "c1"}}, - }, - } -} - -func getLogsAction(namespace string, opts *api.PodLogOptions) testclient.Action { - action := testclient.GenericActionImpl{} - action.Verb = "get" - action.Namespace = namespace - action.Resource = podsResource - action.Subresource = "logs" - action.Value = opts - return action -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_test.go deleted file mode 100644 index e86298fc6..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_test.go +++ /dev/null @@ -1,524 +0,0 @@ -/* -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 ( - "fmt" - "sort" - "strings" - "testing" - "time" - - "k8s.io/api/core/v1" - apiequality "k8s.io/apimachinery/pkg/api/equality" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/apiserver/pkg/util/flag" - manualfake "k8s.io/client-go/rest/fake" - testcore "k8s.io/client-go/testing" - "k8s.io/client-go/tools/clientcmd" - clientcmdapi "k8s.io/client-go/tools/clientcmd/api" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/api/testapi" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/categories" - "k8s.io/kubernetes/pkg/kubectl/resource" -) - -func TestNewFactoryDefaultFlagBindings(t *testing.T) { - factory := NewFactory(nil) - - if !factory.FlagSet().HasFlags() { - t.Errorf("Expected flags, but didn't get any") - } -} - -func TestNewFactoryNoFlagBindings(t *testing.T) { - clientConfig := clientcmd.NewDefaultClientConfig(*clientcmdapi.NewConfig(), &clientcmd.ConfigOverrides{}) - factory := NewFactory(clientConfig) - - if factory.FlagSet().HasFlags() { - t.Errorf("Expected zero flags, but got %v", factory.FlagSet()) - } -} - -func TestPortsForObject(t *testing.T) { - f := NewFactory(nil) - - pod := &api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Ports: []api.ContainerPort{ - { - ContainerPort: 101, - }, - }, - }, - }, - }, - } - - expected := sets.NewString("101") - ports, err := f.PortsForObject(pod) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - got := sets.NewString(ports...) - - if !expected.Equal(got) { - t.Fatalf("Ports mismatch! Expected %v, got %v", expected, got) - } -} - -func TestProtocolsForObject(t *testing.T) { - f := NewFactory(nil) - - pod := &api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Ports: []api.ContainerPort{ - { - ContainerPort: 101, - Protocol: api.ProtocolTCP, - }, - { - ContainerPort: 102, - Protocol: api.ProtocolUDP, - }, - }, - }, - }, - }, - } - - expected := sets.NewString("101/TCP", "102/UDP") - protocolsMap, err := f.ProtocolsForObject(pod) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - protocolsString := kubectl.MakeProtocols(protocolsMap) - protocolsStrings := strings.Split(protocolsString, ",") - got := sets.NewString(protocolsStrings...) - - if !expected.Equal(got) { - t.Fatalf("Protocols mismatch! Expected %v, got %v", expected, got) - } -} - -func TestLabelsForObject(t *testing.T) { - f := NewFactory(nil) - - tests := []struct { - name string - object runtime.Object - expected string - err error - }{ - { - name: "successful re-use of labels", - object: &api.Service{ - ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", Labels: map[string]string{"svc": "test"}}, - TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: "v1"}, - }, - expected: "svc=test", - err: nil, - }, - { - name: "empty labels", - object: &api.Service{ - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", Labels: map[string]string{}}, - TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: "v1"}, - }, - expected: "", - err: nil, - }, - { - name: "nil labels", - object: &api.Service{ - ObjectMeta: metav1.ObjectMeta{Name: "zen", Namespace: "test", Labels: nil}, - TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: "v1"}, - }, - expected: "", - err: nil, - }, - } - - for _, test := range tests { - gotLabels, err := f.LabelsForObject(test.object) - if err != test.err { - t.Fatalf("%s: Error mismatch: Expected %v, got %v", test.name, test.err, err) - } - got := kubectl.MakeLabels(gotLabels) - if test.expected != got { - t.Fatalf("%s: Labels mismatch! Expected %s, got %s", test.name, test.expected, got) - } - - } -} - -func TestCanBeExposed(t *testing.T) { - factory := NewFactory(nil) - tests := []struct { - kind schema.GroupKind - expectErr bool - }{ - { - kind: api.Kind("ReplicationController"), - expectErr: false, - }, - { - kind: api.Kind("Node"), - expectErr: true, - }, - } - - for _, test := range tests { - err := factory.CanBeExposed(test.kind) - if test.expectErr && err == nil { - t.Error("unexpected non-error") - } - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - } -} - -func TestFlagUnderscoreRenaming(t *testing.T) { - factory := NewFactory(nil) - - factory.FlagSet().SetNormalizeFunc(flag.WordSepNormalizeFunc) - factory.FlagSet().Bool("valid_flag", false, "bool value") - - // In case of failure of this test check this PR: spf13/pflag#23 - if factory.FlagSet().Lookup("valid_flag").Name != "valid-flag" { - t.Fatalf("Expected flag name to be valid-flag, got %s", factory.FlagSet().Lookup("valid_flag").Name) - } -} - -func newPodList(count, isUnready, isUnhealthy int, labels map[string]string) *api.PodList { - pods := []api.Pod{} - for i := 0; i < count; i++ { - newPod := api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("pod-%d", i+1), - Namespace: metav1.NamespaceDefault, - CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, i, 0, time.UTC), - Labels: labels, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - } - pods = append(pods, newPod) - } - if isUnready > -1 && isUnready < count { - pods[isUnready].Status.Conditions[0].Status = api.ConditionFalse - } - if isUnhealthy > -1 && isUnhealthy < count { - pods[isUnhealthy].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 5}} - } - return &api.PodList{ - Items: pods, - } -} - -func TestGetFirstPod(t *testing.T) { - labelSet := map[string]string{"test": "selector"} - tests := []struct { - name string - - podList *api.PodList - watching []watch.Event - sortBy func([]*v1.Pod) sort.Interface - - expected *api.Pod - expectedNum int - expectedErr bool - }{ - { - name: "kubectl logs - two ready pods", - podList: newPodList(2, -1, -1, labelSet), - sortBy: func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) }, - expected: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-1", - Namespace: metav1.NamespaceDefault, - CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - }, - expectedNum: 2, - }, - { - name: "kubectl logs - one unhealthy, one healthy", - podList: newPodList(2, -1, 1, labelSet), - sortBy: func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) }, - expected: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-2", - Namespace: metav1.NamespaceDefault, - CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 1, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - ContainerStatuses: []api.ContainerStatus{{RestartCount: 5}}, - }, - }, - expectedNum: 2, - }, - { - name: "kubectl attach - two ready pods", - podList: newPodList(2, -1, -1, labelSet), - sortBy: func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) }, - expected: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-1", - Namespace: metav1.NamespaceDefault, - CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - }, - expectedNum: 2, - }, - { - name: "kubectl attach - wait for ready pod", - podList: newPodList(1, 1, -1, labelSet), - watching: []watch.Event{ - { - Type: watch.Modified, - Object: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-1", - Namespace: metav1.NamespaceDefault, - CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - }, - }, - }, - sortBy: func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) }, - expected: &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-1", - Namespace: metav1.NamespaceDefault, - CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - }, - expectedNum: 1, - }, - } - - for i := range tests { - test := tests[i] - fake := fake.NewSimpleClientset(test.podList) - if len(test.watching) > 0 { - watcher := watch.NewFake() - for _, event := range test.watching { - switch event.Type { - case watch.Added: - go watcher.Add(event.Object) - case watch.Modified: - go watcher.Modify(event.Object) - } - } - fake.PrependWatchReactor("pods", testcore.DefaultWatchReactor(watcher, nil)) - } - selector := labels.Set(labelSet).AsSelector() - - pod, numPods, err := GetFirstPod(fake.Core(), metav1.NamespaceDefault, selector.String(), 1*time.Minute, test.sortBy) - pod.Spec.SecurityContext = nil - if !test.expectedErr && err != nil { - t.Errorf("%s: unexpected error: %v", test.name, err) - continue - } - if test.expectedErr && err == nil { - t.Errorf("%s: expected an error", test.name) - continue - } - if test.expectedNum != numPods { - t.Errorf("%s: expected %d pods, got %d", test.name, test.expectedNum, numPods) - continue - } - if !apiequality.Semantic.DeepEqual(test.expected, pod) { - t.Errorf("%s:\nexpected pod:\n%#v\ngot:\n%#v\n\n", test.name, test.expected, pod) - } - } -} - -func TestMakePortsString(t *testing.T) { - tests := []struct { - ports []api.ServicePort - useNodePort bool - expectedOutput string - }{ - {ports: nil, expectedOutput: ""}, - {ports: []api.ServicePort{}, expectedOutput: ""}, - {ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - }, - expectedOutput: "tcp:80", - }, - {ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - { - Port: 8080, - Protocol: "UDP", - }, - { - Port: 9000, - Protocol: "TCP", - }, - }, - expectedOutput: "tcp:80,udp:8080,tcp:9000", - }, - {ports: []api.ServicePort{ - { - Port: 80, - NodePort: 9090, - Protocol: "TCP", - }, - { - Port: 8080, - NodePort: 80, - Protocol: "UDP", - }, - }, - useNodePort: true, - expectedOutput: "tcp:9090,udp:80", - }, - } - for _, test := range tests { - output := makePortsString(test.ports, test.useNodePort) - if output != test.expectedOutput { - t.Errorf("expected: %s, saw: %s.", test.expectedOutput, output) - } - } -} - -func fakeClient() resource.ClientMapper { - return resource.ClientMapperFunc(func(*meta.RESTMapping) (resource.RESTClient, error) { - return &manualfake.RESTClient{}, nil - }) -} - -func TestDiscoveryReplaceAliases(t *testing.T) { - tests := []struct { - name string - arg string - expected string - }{ - { - name: "no-replacement", - arg: "service", - expected: "service", - }, - { - name: "all-replacement", - arg: "all", - expected: "pods,replicationcontrollers,services,statefulsets.apps,horizontalpodautoscalers.autoscaling,jobs.batch,cronjobs.batch,daemonsets.extensions,deployments.extensions,replicasets.extensions", - }, - { - name: "alias-in-comma-separated-arg", - arg: "all,secrets", - expected: "pods,replicationcontrollers,services,statefulsets.apps,horizontalpodautoscalers.autoscaling,jobs.batch,cronjobs.batch,daemonsets.extensions,deployments.extensions,replicasets.extensions,secrets", - }, - } - - ds := &fakeDiscoveryClient{} - mapper := NewShortcutExpander(testapi.Default.RESTMapper(), ds) - b := resource.NewBuilder( - &resource.Mapper{ - RESTMapper: mapper, - ObjectTyper: legacyscheme.Scheme, - ClientMapper: fakeClient(), - Decoder: testapi.Default.Codec(), - }, - nil, - categories.LegacyCategoryExpander, - ) - - for _, test := range tests { - replaced := b.ReplaceAliases(test.arg) - if replaced != test.expected { - t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, replaced) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/generator.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/generator.go new file mode 100644 index 000000000..7d02669be --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/generator.go @@ -0,0 +1,237 @@ +/* +Copyright 2018 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 ( + "fmt" + "io" + + appsv1 "k8s.io/api/apps/v1" + appsv1beta1 "k8s.io/api/apps/v1beta1" + batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" + batchv2alpha1 "k8s.io/api/batch/v2alpha1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" + "k8s.io/kubernetes/pkg/kubectl" +) + +const ( + // TODO(sig-cli): Enforce consistent naming for generators here. + // See discussion in https://github.com/kubernetes/kubernetes/issues/46237 + // before you add any more. + RunV1GeneratorName = "run/v1" + RunPodV1GeneratorName = "run-pod/v1" + ServiceV1GeneratorName = "service/v1" + ServiceV2GeneratorName = "service/v2" + ServiceNodePortGeneratorV1Name = "service-nodeport/v1" + ServiceClusterIPGeneratorV1Name = "service-clusterip/v1" + ServiceLoadBalancerGeneratorV1Name = "service-loadbalancer/v1" + ServiceExternalNameGeneratorV1Name = "service-externalname/v1" + ServiceAccountV1GeneratorName = "serviceaccount/v1" + HorizontalPodAutoscalerV1GeneratorName = "horizontalpodautoscaler/v1" + DeploymentV1Beta1GeneratorName = "deployment/v1beta1" + DeploymentAppsV1Beta1GeneratorName = "deployment/apps.v1beta1" + DeploymentBasicV1Beta1GeneratorName = "deployment-basic/v1beta1" + DeploymentBasicAppsV1Beta1GeneratorName = "deployment-basic/apps.v1beta1" + DeploymentBasicAppsV1GeneratorName = "deployment-basic/apps.v1" + JobV1GeneratorName = "job/v1" + CronJobV2Alpha1GeneratorName = "cronjob/v2alpha1" + CronJobV1Beta1GeneratorName = "cronjob/v1beta1" + NamespaceV1GeneratorName = "namespace/v1" + ResourceQuotaV1GeneratorName = "resourcequotas/v1" + SecretV1GeneratorName = "secret/v1" + SecretForDockerRegistryV1GeneratorName = "secret-for-docker-registry/v1" + SecretForTLSV1GeneratorName = "secret-for-tls/v1" + ConfigMapV1GeneratorName = "configmap/v1" + ClusterRoleBindingV1GeneratorName = "clusterrolebinding.rbac.authorization.k8s.io/v1alpha1" + RoleBindingV1GeneratorName = "rolebinding.rbac.authorization.k8s.io/v1alpha1" + PodDisruptionBudgetV1GeneratorName = "poddisruptionbudget/v1beta1" + PodDisruptionBudgetV2GeneratorName = "poddisruptionbudget/v1beta1/v2" + PriorityClassV1Alpha1GeneratorName = "priorityclass/v1alpha1" +) + +// GeneratorFunc returns the generators for the provided command +type GeneratorFunc func(cmdName string) map[string]kubectl.Generator + +// GeneratorFn gives a way to easily override the function for unit testing if needed +var GeneratorFn GeneratorFunc = defaultGenerators + +// defaultGenerators returns the set of default generators for use in Factory instances +func defaultGenerators(cmdName string) map[string]kubectl.Generator { + var generator map[string]kubectl.Generator + switch cmdName { + case "expose": + generator = map[string]kubectl.Generator{ + ServiceV1GeneratorName: kubectl.ServiceGeneratorV1{}, + ServiceV2GeneratorName: kubectl.ServiceGeneratorV2{}, + } + case "service-clusterip": + generator = map[string]kubectl.Generator{ + ServiceClusterIPGeneratorV1Name: kubectl.ServiceClusterIPGeneratorV1{}, + } + case "service-nodeport": + generator = map[string]kubectl.Generator{ + ServiceNodePortGeneratorV1Name: kubectl.ServiceNodePortGeneratorV1{}, + } + case "service-loadbalancer": + generator = map[string]kubectl.Generator{ + ServiceLoadBalancerGeneratorV1Name: kubectl.ServiceLoadBalancerGeneratorV1{}, + } + case "deployment": + // Create Deployment has only StructuredGenerators and no + // param-based Generators. + // The StructuredGenerators are as follows (as of 2018-03-16): + // DeploymentBasicV1Beta1GeneratorName -> kubectl.DeploymentBasicGeneratorV1 + // DeploymentBasicAppsV1Beta1GeneratorName -> kubectl.DeploymentBasicAppsGeneratorV1Beta1 + // DeploymentBasicAppsV1GeneratorName -> kubectl.DeploymentBasicAppsGeneratorV1 + generator = map[string]kubectl.Generator{} + case "run": + generator = map[string]kubectl.Generator{ + RunV1GeneratorName: kubectl.BasicReplicationController{}, + RunPodV1GeneratorName: kubectl.BasicPod{}, + DeploymentV1Beta1GeneratorName: kubectl.DeploymentV1Beta1{}, + DeploymentAppsV1Beta1GeneratorName: kubectl.DeploymentAppsV1Beta1{}, + JobV1GeneratorName: kubectl.JobV1{}, + CronJobV2Alpha1GeneratorName: kubectl.CronJobV2Alpha1{}, + CronJobV1Beta1GeneratorName: kubectl.CronJobV1Beta1{}, + } + case "namespace": + generator = map[string]kubectl.Generator{ + NamespaceV1GeneratorName: kubectl.NamespaceGeneratorV1{}, + } + case "quota": + generator = map[string]kubectl.Generator{ + ResourceQuotaV1GeneratorName: kubectl.ResourceQuotaGeneratorV1{}, + } + case "secret": + generator = map[string]kubectl.Generator{ + SecretV1GeneratorName: kubectl.SecretGeneratorV1{}, + } + case "secret-for-docker-registry": + generator = map[string]kubectl.Generator{ + SecretForDockerRegistryV1GeneratorName: kubectl.SecretForDockerRegistryGeneratorV1{}, + } + case "secret-for-tls": + generator = map[string]kubectl.Generator{ + SecretForTLSV1GeneratorName: kubectl.SecretForTLSGeneratorV1{}, + } + } + + return generator +} + +// FallbackGeneratorNameIfNecessary returns the name of the old generator +// if server does not support new generator. Otherwise, the +// generator string is returned unchanged. +// +// If the generator name is changed, print a warning message to let the user +// know. +func FallbackGeneratorNameIfNecessary( + generatorName string, + discoveryClient discovery.DiscoveryInterface, + cmdErr io.Writer, +) (string, error) { + switch generatorName { + case DeploymentAppsV1Beta1GeneratorName: + hasResource, err := HasResource(discoveryClient, appsv1beta1.SchemeGroupVersion.WithResource("deployments")) + if err != nil { + return "", err + } + if !hasResource { + return FallbackGeneratorNameIfNecessary(DeploymentV1Beta1GeneratorName, discoveryClient, cmdErr) + } + case DeploymentV1Beta1GeneratorName: + hasResource, err := HasResource(discoveryClient, extensionsv1beta1.SchemeGroupVersion.WithResource("deployments")) + if err != nil { + return "", err + } + if !hasResource { + return RunV1GeneratorName, nil + } + case DeploymentBasicAppsV1GeneratorName: + hasResource, err := HasResource(discoveryClient, appsv1.SchemeGroupVersion.WithResource("deployments")) + if err != nil { + return "", err + } + if !hasResource { + return FallbackGeneratorNameIfNecessary(DeploymentBasicAppsV1Beta1GeneratorName, discoveryClient, cmdErr) + } + case DeploymentBasicAppsV1Beta1GeneratorName: + hasResource, err := HasResource(discoveryClient, appsv1beta1.SchemeGroupVersion.WithResource("deployments")) + if err != nil { + return "", err + } + if !hasResource { + return DeploymentBasicV1Beta1GeneratorName, nil + } + case JobV1GeneratorName: + hasResource, err := HasResource(discoveryClient, batchv1.SchemeGroupVersion.WithResource("jobs")) + if err != nil { + return "", err + } + if !hasResource { + return RunPodV1GeneratorName, nil + } + case CronJobV1Beta1GeneratorName: + hasResource, err := HasResource(discoveryClient, batchv1beta1.SchemeGroupVersion.WithResource("cronjobs")) + if err != nil { + return "", err + } + if !hasResource { + return FallbackGeneratorNameIfNecessary(CronJobV2Alpha1GeneratorName, discoveryClient, cmdErr) + } + case CronJobV2Alpha1GeneratorName: + hasResource, err := HasResource(discoveryClient, batchv2alpha1.SchemeGroupVersion.WithResource("cronjobs")) + if err != nil { + return "", err + } + if !hasResource { + return JobV1GeneratorName, nil + } + } + return generatorName, nil +} + +func HasResource(client discovery.DiscoveryInterface, resource schema.GroupVersionResource) (bool, error) { + resources, err := client.ServerResourcesForGroupVersion(resource.GroupVersion().String()) + if apierrors.IsNotFound(err) { + // entire group is missing + return false, nil + } + if err != nil { + // other errors error + return false, fmt.Errorf("failed to discover supported resources: %v", err) + } + for _, serverResource := range resources.APIResources { + if serverResource.Name == resource.Resource { + return true, nil + } + } + return false, nil +} + +func Warning(cmdErr io.Writer, newGeneratorName, oldGeneratorName string) { + fmt.Fprintf(cmdErr, "WARNING: New generator %q specified, "+ + "but it isn't available. "+ + "Falling back to %q.\n", + newGeneratorName, + oldGeneratorName, + ) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers.go index 5a5409c5f..aa2224652 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers.go @@ -21,7 +21,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net/url" "os" "strings" @@ -30,23 +29,24 @@ import ( "github.com/evanphx/json-patch" "github.com/golang/glog" "github.com/spf13/cobra" + "github.com/spf13/pflag" kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + "k8s.io/client-go/scale" "k8s.io/client-go/tools/clientcmd" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/printers" + printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" utilexec "k8s.io/utils/exec" ) @@ -300,16 +300,6 @@ func IsFilenameSliceEmpty(filenames []string) bool { return len(filenames) == 0 } -// Whether this cmd need watching objects. -func isWatch(cmd *cobra.Command) bool { - if w, err := cmd.Flags().GetBool("watch"); err == nil && w { - return true - } - - wo, err := cmd.Flags().GetBool("watch-only") - return err == nil && wo -} - func GetFlagString(cmd *cobra.Command, flag string) string { s, err := cmd.Flags().GetString(flag) if err != nil { @@ -336,15 +326,6 @@ func GetFlagStringArray(cmd *cobra.Command, flag string) []string { return s } -// GetWideFlag is used to determine if "-o wide" is used -func GetWideFlag(cmd *cobra.Command) bool { - f := cmd.Flags().Lookup("output") - if f != nil && f.Value != nil && f.Value.String() == "wide" { - return true - } - return false -} - func GetFlagBool(cmd *cobra.Command, flag string) bool { b, err := cmd.Flags().GetBool(flag) if err != nil { @@ -405,10 +386,19 @@ func AddValidateOptionFlags(cmd *cobra.Command, options *ValidateOptions) { } func AddFilenameOptionFlags(cmd *cobra.Command, options *resource.FilenameOptions, usage string) { - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, "Filename, directory, or URL to files "+usage) + AddJsonFilenameFlag(cmd.Flags(), &options.Filenames, "Filename, directory, or URL to files "+usage) cmd.Flags().BoolVarP(&options.Recursive, "recursive", "R", options.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") } +func AddJsonFilenameFlag(flags *pflag.FlagSet, value *[]string, usage string) { + flags.StringSliceVarP(value, "filename", "f", *value, usage) + annotations := make([]string, 0, len(resource.FileExtensions)) + for _, ext := range resource.FileExtensions { + annotations = append(annotations, strings.TrimLeft(ext, ".")) + } + flags.SetAnnotation("filename", cobra.BashCompFilenameExt, annotations) +} + // AddDryRunFlag adds dry-run flag to a command. Usually used by mutations. func AddDryRunFlag(cmd *cobra.Command) { cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.") @@ -441,19 +431,6 @@ type ValidateOptions struct { EnableValidation bool } -func ReadConfigDataFromReader(reader io.Reader, source string) ([]byte, error) { - data, err := ioutil.ReadAll(reader) - if err != nil { - return nil, err - } - - if len(data) == 0 { - return nil, fmt.Errorf("Read from %s but no data found", source) - } - - return data, nil -} - // Merge requires JSON serialization // TODO: merge assumes JSON serialization, and does not properly abstract API retrieval func Merge(codec runtime.Codec, dst runtime.Object, fragment string) (runtime.Object, error) { @@ -499,112 +476,10 @@ func DumpReaderToFile(reader io.Reader, filename string) error { return nil } -// UpdateObject updates resource object with updateFn -func UpdateObject(info *resource.Info, codec runtime.Codec, updateFn func(runtime.Object) error) (runtime.Object, error) { - helper := resource.NewHelper(info.Client, info.Mapping) - - if err := updateFn(info.Object); err != nil { - return nil, err - } - - // Update the annotation used by kubectl apply - if err := kubectl.UpdateApplyAnnotation(info, codec); err != nil { - return nil, err - } - - if _, err := helper.Replace(info.Namespace, info.Name, true, info.Object); err != nil { - return nil, err - } - - return info.Object, nil -} - -func AddRecordFlag(cmd *cobra.Command) { - cmd.Flags().Bool("record", false, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.") -} - -func AddRecordVarFlag(cmd *cobra.Command, record *bool) { - cmd.Flags().BoolVar(record, "record", *record, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.") -} - -func GetRecordFlag(cmd *cobra.Command) bool { - return GetFlagBool(cmd, "record") -} - func GetDryRunFlag(cmd *cobra.Command) bool { return GetFlagBool(cmd, "dry-run") } -// RecordChangeCause annotate change-cause to input runtime object. -func RecordChangeCause(obj runtime.Object, changeCause string) error { - accessor, err := meta.Accessor(obj) - if err != nil { - return err - } - annotations := accessor.GetAnnotations() - if annotations == nil { - annotations = make(map[string]string) - } - annotations[kubectl.ChangeCauseAnnotation] = changeCause - accessor.SetAnnotations(annotations) - return nil -} - -// ChangeResourcePatch creates a patch between the origin input resource info -// and the annotated with change-cause input resource info. -func ChangeResourcePatch(info *resource.Info, changeCause string) ([]byte, types.PatchType, error) { - // Get a versioned object - obj, err := info.Mapping.ConvertToVersion(info.Object, info.Mapping.GroupVersionKind.GroupVersion()) - if err != nil { - return nil, types.StrategicMergePatchType, err - } - - oldData, err := json.Marshal(obj) - if err != nil { - return nil, types.StrategicMergePatchType, err - } - if err := RecordChangeCause(obj, changeCause); err != nil { - return nil, types.StrategicMergePatchType, err - } - newData, err := json.Marshal(obj) - if err != nil { - return nil, types.StrategicMergePatchType, err - } - - switch obj := obj.(type) { - case *unstructured.Unstructured: - patch, err := jsonpatch.CreateMergePatch(oldData, newData) - return patch, types.MergePatchType, err - default: - patch, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj) - return patch, types.StrategicMergePatchType, err - } -} - -// ContainsChangeCause checks if input resource info contains change-cause annotation. -func ContainsChangeCause(info *resource.Info) bool { - annotations, err := info.Mapping.MetadataAccessor.Annotations(info.Object) - if err != nil { - return false - } - return len(annotations[kubectl.ChangeCauseAnnotation]) > 0 -} - -// ShouldRecord checks if we should record current change cause -func ShouldRecord(cmd *cobra.Command, info *resource.Info) bool { - return GetRecordFlag(cmd) || (ContainsChangeCause(info) && !cmd.Flags().Changed("record")) -} - -func AddInclude3rdPartyFlags(cmd *cobra.Command) { - cmd.Flags().Bool("include-extended-apis", true, "If true, include definitions of new APIs via calls to the API server. [default true]") - cmd.Flags().MarkDeprecated("include-extended-apis", "No longer required.") -} - -func AddInclude3rdPartyVarFlags(cmd *cobra.Command, include3rdParty *bool) { - cmd.Flags().BoolVar(include3rdParty, "include-extended-apis", *include3rdParty, "If true, include definitions of new APIs via calls to the API server. [default true]") - cmd.Flags().MarkDeprecated("include-extended-apis", "No longer required.") -} - // GetResourcesAndPairs retrieves resources and "KEY=VALUE or KEY-" pair args from given args func GetResourcesAndPairs(args []string, pairType string) (resources []string, pairArgs []string, err error) { foundPair := false @@ -664,81 +539,6 @@ func ParsePairs(pairArgs []string, pairType string, supportRemove bool) (newPair return } -// MustPrintWithKinds determines if printer is dealing -// with multiple resource kinds, in which case it will -// return true, indicating resource kind will be -// included as part of printer output -func MustPrintWithKinds(objs []runtime.Object, infos []*resource.Info, sorter *kubectl.RuntimeSort) bool { - var lastMap *meta.RESTMapping - - for ix := range objs { - var mapping *meta.RESTMapping - if sorter != nil { - mapping = infos[sorter.OriginalPosition(ix)].Mapping - } else { - mapping = infos[ix].Mapping - } - - // display "kind" only if we have mixed resources - if lastMap != nil && mapping.Resource != lastMap.Resource { - return true - } - lastMap = mapping - } - - return false -} - -// FilterResourceList receives a list of runtime objects. -// If any objects are filtered, that number is returned along with a modified list. -func FilterResourceList(obj runtime.Object, filterFuncs kubectl.Filters, filterOpts *printers.PrintOptions) (int, []runtime.Object, error) { - items, err := meta.ExtractList(obj) - if err != nil { - return 0, []runtime.Object{obj}, utilerrors.NewAggregate([]error{err}) - } - if errs := runtime.DecodeList(items, legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme); len(errs) > 0 { - return 0, []runtime.Object{obj}, utilerrors.NewAggregate(errs) - } - - filterCount := 0 - list := make([]runtime.Object, 0, len(items)) - for _, obj := range items { - if isFiltered, err := filterFuncs.Filter(obj, filterOpts); !isFiltered { - if err != nil { - glog.V(2).Infof("Unable to filter resource: %v", err) - continue - } - list = append(list, obj) - } else if isFiltered { - filterCount++ - } - } - return filterCount, list, nil -} - -// PrintFilterCount displays informational messages based on the number of resources found, hidden, or -// config flags shown. -func PrintFilterCount(out io.Writer, found, hidden, errors int, options *printers.PrintOptions, ignoreNotFound bool) { - switch { - case errors > 0 || ignoreNotFound: - // print nothing - case found <= hidden: - if found == 0 { - fmt.Fprintln(out, "No resources found.") - } else { - fmt.Fprintln(out, "No resources found, use --show-all to see completed objects.") - } - case hidden > 0 && !options.ShowAll && !options.NoHeaders: - if glog.V(2) { - if hidden > 1 { - fmt.Fprintf(out, "info: %d objects not shown, use --show-all to see completed objects.\n", hidden) - } else { - fmt.Fprintf(out, "info: 1 object not shown, use --show-all to see completed objects.\n") - } - } - } -} - // IsSiblingCommandExists receives a pointer to a cobra command and a target string. // Returns true if the target string is found in the list of sibling commands. func IsSiblingCommandExists(cmd *cobra.Command, targetCmdName string) bool { @@ -769,22 +569,6 @@ func RequireNoArguments(c *cobra.Command, args []string) { } } -// OutputsRawFormat determines if a command's output format is machine parsable -// or returns false if it is human readable (name, wide, etc.) -func OutputsRawFormat(cmd *cobra.Command) bool { - output := GetFlagString(cmd, "output") - if output == "json" || - output == "yaml" || - output == "go-template" || - output == "go-template-file" || - output == "jsonpath" || - output == "jsonpath-file" { - return true - } - - return false -} - // StripComments will transform a YAML file into JSON, thus dropping any comments // in it. Note that if the given file has a syntax error, the transformation will // fail and we will manually drop all comments from the file. @@ -834,3 +618,82 @@ func ShouldIncludeUninitialized(cmd *cobra.Command, includeUninitialized bool) b } return shouldIncludeUninitialized } + +// DescriberFunc gives a way to display the specified RESTMapping type +type DescriberFunc func(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (printers.Describer, error) + +// DescriberFn gives a way to easily override the function for unit testing if needed +var DescriberFn DescriberFunc = describer + +// Returns a Describer for displaying the specified RESTMapping type or an error. +func describer(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (printers.Describer, error) { + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + // try to get a describer + if describer, ok := printersinternal.DescriberFor(mapping.GroupVersionKind.GroupKind(), clientConfig); ok { + return describer, nil + } + // if this is a kind we don't have a describer for yet, go generic if possible + if genericDescriber, genericErr := genericDescriber(restClientGetter, mapping); genericErr == nil { + return genericDescriber, nil + } + // otherwise return an unregistered error + return nil, fmt.Errorf("no description has been implemented for %s", mapping.GroupVersionKind.String()) +} + +// helper function to make a generic describer, or return an error +func genericDescriber(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (printers.Describer, error) { + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + + // used to fetch the resource + dynamicClient, err := dynamic.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + + // used to get events for the resource + clientSet, err := internalclientset.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + + eventsClient := clientSet.Core() + return printersinternal.GenericDescriberFor(mapping, dynamicClient, eventsClient), nil +} + +// ScaleClientFunc provides a ScalesGetter +type ScaleClientFunc func(genericclioptions.RESTClientGetter) (scale.ScalesGetter, error) + +// ScaleClientFn gives a way to easily override the function for unit testing if needed. +var ScaleClientFn ScaleClientFunc = scaleClient + +// scaleClient gives you back scale getter +func scaleClient(restClientGetter genericclioptions.RESTClientGetter) (scale.ScalesGetter, error) { + discoveryClient, err := restClientGetter.ToDiscoveryClient() + if err != nil { + return nil, err + } + + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + + setKubernetesDefaults(clientConfig) + restClient, err := rest.RESTClientFor(clientConfig) + if err != nil { + return nil, err + } + resolver := scale.NewDiscoveryScaleKindResolver(discoveryClient) + mapper, err := restClientGetter.ToRESTMapper() + if err != nil { + return nil, err + } + + return scale.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver), nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers_test.go index db3d09ae3..65c8fde20 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers_test.go @@ -19,7 +19,6 @@ package util import ( "fmt" "io/ioutil" - "net/http" "os" "strings" "syscall" @@ -32,7 +31,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" @@ -53,7 +51,7 @@ func TestMerge(t *testing.T) { Name: "foo", }, }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s" }`, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String()), + fragment: fmt.Sprintf(`{ "apiVersion": "%s" }`, "v1"), expected: &api.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -81,7 +79,7 @@ func TestMerge(t *testing.T) { }, }, }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "containers": [ { "name": "c1", "image": "green-image" } ] } }`, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String()), + fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "containers": [ { "name": "c1", "image": "green-image" } ] } }`, schema.GroupVersion{Group:"", Version: "v1"}.String()), expected: &api.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -106,7 +104,7 @@ func TestMerge(t *testing.T) { Name: "foo", }, }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "volumes": [ {"name": "v1"}, {"name": "v2"} ] } }`, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String()), + fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "volumes": [ {"name": "v1"}, {"name": "v2"} ] } }`, "v1"), expected: &api.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -145,7 +143,7 @@ func TestMerge(t *testing.T) { obj: &api.Service{ Spec: api.ServiceSpec{}, }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "ports": [ { "port": 0 } ] } }`, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String()), + fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "ports": [ { "port": 0 } ] } }`, "v1"), expected: &api.Service{ Spec: api.ServiceSpec{ SessionAffinity: "None", @@ -167,7 +165,7 @@ func TestMerge(t *testing.T) { }, }, }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "selector": { "version": "v2" } } }`, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String()), + fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "selector": { "version": "v2" } } }`, "v1"), expected: &api.Service{ Spec: api.ServiceSpec{ SessionAffinity: "None", @@ -195,19 +193,6 @@ func TestMerge(t *testing.T) { } } -type fileHandler struct { - data []byte -} - -func (f *fileHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) { - if req.URL.Path == "/error" { - res.WriteHeader(http.StatusNotFound) - return - } - res.WriteHeader(http.StatusOK) - res.Write(f.data) -} - type checkErrTestCase struct { err error expectedErr string diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge/BUILD deleted file mode 100644 index 08551294b..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["jsonmerge.go"], - importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge", - visibility = ["//visibility:public"], - deps = [ - "//vendor/github.com/evanphx/json-patch:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = [ - "//build/visible_to:pkg_kubectl_cmd_util_jsonmerge_CONSUMERS", - ], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge/jsonmerge.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge/jsonmerge.go deleted file mode 100644 index beebc7f05..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge/jsonmerge.go +++ /dev/null @@ -1,193 +0,0 @@ -/* -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 jsonmerge - -import ( - "encoding/json" - "fmt" - - "github.com/evanphx/json-patch" - "github.com/golang/glog" - - "k8s.io/apimachinery/pkg/util/mergepatch" - "k8s.io/apimachinery/pkg/util/yaml" -) - -// Delta represents a change between two JSON documents. -type Delta struct { - original []byte - edit []byte - - preconditions []PreconditionFunc -} - -// PreconditionFunc is a test to verify that an incompatible change -// has occurred before an Apply can be successful. -type PreconditionFunc func(interface{}) (hold bool, message string) - -// AddPreconditions adds precondition checks to a change which must -// be satisfied before an Apply is considered successful. If a -// precondition returns false, the Apply is failed with -// ErrPreconditionFailed. -func (d *Delta) AddPreconditions(fns ...PreconditionFunc) { - d.preconditions = append(d.preconditions, fns...) -} - -// RequireKeyUnchanged creates a precondition function that fails -// if the provided key is present in the diff (indicating its value -// has changed). -func RequireKeyUnchanged(key string) PreconditionFunc { - return func(diff interface{}) (bool, string) { - m, ok := diff.(map[string]interface{}) - if !ok { - return true, "" - } - // the presence of key in a diff means that its value has been changed, therefore - // we should fail the precondition. - _, ok = m[key] - if ok { - return false, key + " should not be changed\n" - } else { - return true, "" - } - } -} - -// RequireMetadataKeyUnchanged creates a precondition function that fails -// if the metadata.key is present in the diff (indicating its value -// has changed). -func RequireMetadataKeyUnchanged(key string) PreconditionFunc { - return func(diff interface{}) (bool, string) { - m, ok := diff.(map[string]interface{}) - if !ok { - return true, "" - } - m1, ok := m["metadata"] - if !ok { - return true, "" - } - m2, ok := m1.(map[string]interface{}) - if !ok { - return true, "" - } - _, ok = m2[key] - if ok { - return false, "metadata." + key + " should not be changed\n" - } else { - return true, "" - } - } -} - -// TestPreconditions test if preconditions hold given the edit -func TestPreconditionsHold(edit []byte, preconditions []PreconditionFunc) (bool, string) { - diff := make(map[string]interface{}) - if err := json.Unmarshal(edit, &diff); err != nil { - return false, err.Error() - } - for _, fn := range preconditions { - if hold, msg := fn(diff); !hold { - return false, msg - } - } - return true, "" -} - -// NewDelta accepts two JSON or YAML documents and calculates the difference -// between them. It returns a Delta object which can be used to resolve -// conflicts against a third version with a common parent, or an error -// if either document is in error. -func NewDelta(from, to []byte) (*Delta, error) { - d := &Delta{} - before, err := yaml.ToJSON(from) - if err != nil { - return nil, err - } - after, err := yaml.ToJSON(to) - if err != nil { - return nil, err - } - diff, err := jsonpatch.CreateMergePatch(before, after) - if err != nil { - return nil, err - } - glog.V(6).Infof("Patch created from:\n%s\n%s\n%s", string(before), string(after), string(diff)) - d.original = before - d.edit = diff - return d, nil -} - -// Apply attempts to apply the changes described by Delta onto latest, -// returning an error if the changes cannot be applied cleanly. -// IsConflicting will be true if the changes overlap, otherwise a -// generic error will be returned. -func (d *Delta) Apply(latest []byte) ([]byte, error) { - base, err := yaml.ToJSON(latest) - if err != nil { - return nil, err - } - changes, err := jsonpatch.CreateMergePatch(d.original, base) - if err != nil { - return nil, err - } - diff1 := make(map[string]interface{}) - if err := json.Unmarshal(d.edit, &diff1); err != nil { - return nil, err - } - diff2 := make(map[string]interface{}) - if err := json.Unmarshal(changes, &diff2); err != nil { - return nil, err - } - for _, fn := range d.preconditions { - hold1, _ := fn(diff1) - hold2, _ := fn(diff2) - if !hold1 || !hold2 { - return nil, ErrPreconditionFailed - } - } - - glog.V(6).Infof("Testing for conflict between:\n%s\n%s", string(d.edit), string(changes)) - hasConflicts, err := mergepatch.HasConflicts(diff1, diff2) - if err != nil { - return nil, err - } - if hasConflicts { - return nil, ErrConflict - } - - return jsonpatch.MergePatch(base, d.edit) -} - -// IsConflicting returns true if the provided error indicates a -// conflict exists between the original changes and the applied -// changes. -func IsConflicting(err error) bool { - return err == ErrConflict -} - -// IsPreconditionFailed returns true if the provided error indicates -// a Delta precondition did not succeed. -func IsPreconditionFailed(err error) bool { - return err == ErrPreconditionFailed -} - -var ErrPreconditionFailed = fmt.Errorf("a precondition failed") -var ErrConflict = fmt.Errorf("changes are in conflict") - -func (d *Delta) Edit() []byte { - return d.edit -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/kubectl_match_version.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/kubectl_match_version.go new file mode 100644 index 000000000..c5c121a79 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/kubectl_match_version.go @@ -0,0 +1,126 @@ +/* +Copyright 2018 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 ( + "sync" + + "github.com/spf13/pflag" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/version" +) + +const ( + flagMatchBinaryVersion = "match-server-version" +) + +// MatchVersionFlags is for setting the "match server version" function. +type MatchVersionFlags struct { + Delegate genericclioptions.RESTClientGetter + + RequireMatchedServerVersion bool + checkServerVersion sync.Once + matchesServerVersionErr error +} + +var _ genericclioptions.RESTClientGetter = &MatchVersionFlags{} + +func (f *MatchVersionFlags) checkMatchingServerVersion() error { + f.checkServerVersion.Do(func() { + if !f.RequireMatchedServerVersion { + return + } + discoveryClient, err := f.Delegate.ToDiscoveryClient() + if err != nil { + f.matchesServerVersionErr = err + return + } + f.matchesServerVersionErr = discovery.MatchesServerVersion(version.Get(), discoveryClient) + }) + + return f.matchesServerVersionErr +} + +// ToRESTConfig implements RESTClientGetter. +// Returns a REST client configuration based on a provided path +// to a .kubeconfig file, loading rules, and config flag overrides. +// Expects the AddFlags method to have been called. +func (f *MatchVersionFlags) ToRESTConfig() (*rest.Config, error) { + if err := f.checkMatchingServerVersion(); err != nil { + return nil, err + } + clientConfig, err := f.Delegate.ToRESTConfig() + if err != nil { + return nil, err + } + // TODO we should not have to do this. It smacks of something going wrong. + setKubernetesDefaults(clientConfig) + return clientConfig, nil +} + +func (f *MatchVersionFlags) ToRawKubeConfigLoader() clientcmd.ClientConfig { + return f.Delegate.ToRawKubeConfigLoader() +} + +func (f *MatchVersionFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + if err := f.checkMatchingServerVersion(); err != nil { + return nil, err + } + return f.Delegate.ToDiscoveryClient() +} + +// RESTMapper returns a mapper. +func (f *MatchVersionFlags) ToRESTMapper() (meta.RESTMapper, error) { + if err := f.checkMatchingServerVersion(); err != nil { + return nil, err + } + return f.Delegate.ToRESTMapper() +} + +func (f *MatchVersionFlags) AddFlags(flags *pflag.FlagSet) { + flags.BoolVar(&f.RequireMatchedServerVersion, flagMatchBinaryVersion, f.RequireMatchedServerVersion, "Require server version to match client version") +} + +func NewMatchVersionFlags(delegate genericclioptions.RESTClientGetter) *MatchVersionFlags { + return &MatchVersionFlags{ + Delegate: delegate, + } +} + +// setKubernetesDefaults sets default values on the provided client config for accessing the +// Kubernetes API or returns an error if any of the defaults are impossible or invalid. +// TODO this isn't what we want. Each clientset should be setting defaults as it sees fit. +func setKubernetesDefaults(config *rest.Config) error { + // TODO remove this hack. This is allowing the GetOptions to be serialized. + config.GroupVersion = &schema.GroupVersion{Group: "", Version: "v1"} + + if config.APIPath == "" { + config.APIPath = "/api" + } + if config.NegotiatedSerializer == nil { + config.NegotiatedSerializer = legacyscheme.Codecs + } + return rest.SetKubernetesDefaults(config) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/BUILD index bb6b3e240..22f8f9c73 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/BUILD @@ -35,13 +35,14 @@ go_test( data = ["//api/openapi-spec:swagger-spec"], deps = [ ":go_default_library", - "//pkg/kubectl/cmd/util/openapi/testing:go_default_library", + "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/ginkgo/config:go_default_library", "//vendor/github.com/onsi/ginkgo/types:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi_getter_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi_getter_test.go index 004d27e1b..9239fe2bc 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi_getter_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi_getter_test.go @@ -19,27 +19,36 @@ package openapi_test import ( "fmt" + openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" ) +// FakeCounter returns a "null" document and the specified error. It +// also counts how many times the OpenAPISchema method has been called. +type FakeCounter struct { + Calls int + Err error +} + +func (f *FakeCounter) OpenAPISchema() (*openapi_v2.Document, error) { + f.Calls = f.Calls + 1 + return nil, f.Err +} + var _ = Describe("Getting the Resources", func() { - var client *tst.FakeClient - var expectedData openapi.Resources + var client FakeCounter var instance openapi.Getter + var expectedData openapi.Resources BeforeEach(func() { - client = tst.NewFakeClient(&fakeSchema) - d, err := fakeSchema.OpenAPISchema() + client = FakeCounter{} + instance = openapi.NewOpenAPIGetter(&client) + var err error + expectedData, err = openapi.NewOpenAPIData(nil) Expect(err).To(BeNil()) - - expectedData, err = openapi.NewOpenAPIData(d) - Expect(err).To(BeNil()) - - instance = openapi.NewOpenAPIGetter(client) }) Context("when the server returns a successful result", func() { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi_test.go index 5ee7302f1..d996a5338 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi_test.go @@ -24,11 +24,11 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kube-openapi/pkg/util/proto" + "k8s.io/kube-openapi/pkg/util/proto/testing" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" ) -var fakeSchema = tst.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")} +var fakeSchema = testing.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")} var _ = Describe("Reading apps/v1beta1/Deployment from openAPIData", func() { var resources openapi.Resources diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing/BUILD index 26a7b3467..ce6ffc739 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing/BUILD @@ -11,11 +11,9 @@ go_library( importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing", deps = [ "//pkg/kubectl/cmd/util/openapi:go_default_library", - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", - "//vendor/github.com/googleapis/gnostic/compiler:go_default_library", - "//vendor/gopkg.in/yaml.v2:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing/openapi.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing/openapi.go index 1ccf47c25..e59e6d3d3 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing/openapi.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing/openapi.go @@ -17,86 +17,17 @@ limitations under the License. package testing import ( - "io/ioutil" - "os" - "sync" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kube-openapi/pkg/util/proto" + "k8s.io/kube-openapi/pkg/util/proto/testing" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - - yaml "gopkg.in/yaml.v2" - - "github.com/googleapis/gnostic/OpenAPIv2" - "github.com/googleapis/gnostic/compiler" ) -// Fake opens and returns a openapi swagger from a file Path. It will -// parse only once and then return the same copy everytime. -type Fake struct { - Path string - - once sync.Once - document *openapi_v2.Document - err error -} - -// OpenAPISchema returns the openapi document and a potential error. -func (f *Fake) OpenAPISchema() (*openapi_v2.Document, error) { - f.once.Do(func() { - _, err := os.Stat(f.Path) - if err != nil { - f.err = err - return - } - spec, err := ioutil.ReadFile(f.Path) - if err != nil { - f.err = err - return - } - var info yaml.MapSlice - err = yaml.Unmarshal(spec, &info) - if err != nil { - f.err = err - return - } - f.document, f.err = openapi_v2.NewDocument(info, compiler.NewContext("$root", nil)) - }) - return f.document, f.err -} - -// FakeClient implements a dummy OpenAPISchemaInterface that uses the -// fake OpenAPI schema given as a parameter, and count the number of -// call to the function. -type FakeClient struct { - Calls int - Err error - - fake *Fake -} - -// NewFakeClient creates a new FakeClient from the given Fake. -func NewFakeClient(f *Fake) *FakeClient { - return &FakeClient{fake: f} -} - -// OpenAPISchema returns a OpenAPI Document as returned by the fake, but -// it also counts the number of calls. -func (f *FakeClient) OpenAPISchema() (*openapi_v2.Document, error) { - f.Calls = f.Calls + 1 - - if f.Err != nil { - return nil, f.Err - } - - return f.fake.OpenAPISchema() -} - // FakeResources is a wrapper to directly load the openapi schema from a // file, and get the schema for given GVK. This is only for test since // it's assuming that the file is there and everything will go fine. type FakeResources struct { - fake Fake + fake testing.Fake } var _ openapi.Resources = &FakeResources{} @@ -104,7 +35,7 @@ var _ openapi.Resources = &FakeResources{} // NewFakeResources creates a new FakeResources. func NewFakeResources(path string) *FakeResources { return &FakeResources{ - fake: Fake{Path: path}, + fake: testing.Fake{Path: path}, } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/BUILD index b1fa6fb0a..1d1ebb302 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/BUILD @@ -31,12 +31,12 @@ go_test( deps = [ "//pkg/api/testapi:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library", - "//pkg/kubectl/cmd/util/openapi/testing:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/ginkgo/config:go_default_library", "//vendor/github.com/onsi/ginkgo/types:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library", "//vendor/k8s.io/kube-openapi/pkg/util/proto/validation:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/validation.go index 80239e022..0ac30d5f0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/validation.go @@ -18,7 +18,6 @@ package validation import ( "errors" - "strings" "k8s.io/apimachinery/pkg/runtime/schema" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -54,7 +53,7 @@ func (v *SchemaValidation) ValidateBytes(data []byte) error { return utilerrors.NewAggregate(errs) } - if strings.HasSuffix(gvk.Kind, "List") { + if (gvk == schema.GroupVersionKind{Version: "v1", Kind: "List"}) { return utilerrors.NewAggregate(v.validateList(obj)) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/validation_test.go index c038682a3..2fb8b528e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/validation_test.go @@ -25,12 +25,12 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kube-openapi/pkg/util/proto/validation" // This dependency is needed to register API types. + "k8s.io/kube-openapi/pkg/util/proto/testing" _ "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" - tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" ) -var fakeSchema = tst.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")} +var fakeSchema = testing.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")} var _ = Describe("resource validation using OpenAPI Schema", func() { var validator *SchemaValidation @@ -394,4 +394,16 @@ items: `)) Expect(err.Error()).To(Equal("[kind not set, apiVersion not set]")) }) + + It("is fine with crd resource with List as a suffix kind name, which may not be a list of resources", func() { + err := validator.ValidateBytes([]byte(` +apiVersion: fake.com/v1 +kind: FakeList +metadata: + name: fake +spec: + foo: bar +`)) + Expect(err).To(BeNil()) + }) }) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/printing.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/printing.go index fa33f25a3..dab4792c1 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/printing.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/printing.go @@ -18,280 +18,12 @@ package util import ( "fmt" - "io" - "strings" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" - kubectlscheme "k8s.io/kubernetes/pkg/kubectl/scheme" - "k8s.io/kubernetes/pkg/printers" - printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" - - "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/kubernetes/pkg/api/legacyscheme" ) -// AddPrinterFlags adds printing related flags to a command (e.g. output format, no headers, template path) -func AddPrinterFlags(cmd *cobra.Command) { - AddNonDeprecatedPrinterFlags(cmd) - - cmd.Flags().String("output-version", "", "DEPRECATED: To use a specific API version, fully-qualify the resource, version, and group (for example: 'jobs.v1.batch/myjob').") - cmd.Flags().MarkDeprecated("output-version", "The resource is used exactly as fetched from the API. To get a specific API version, fully-qualify the resource, version, and group (for example: 'jobs.v1.batch/myjob').") - cmd.Flags().MarkHidden("output-version") -} - -// AddNonDeprecatedPrinterFlags supports the conversion case which must logically have output-version. Once output-version -// is completely removed, this function can go away. -func AddNonDeprecatedPrinterFlags(cmd *cobra.Command) { - AddOutputFlags(cmd) - AddNoHeadersFlags(cmd) - cmd.Flags().Bool("show-labels", false, "When printing, show all labels as the last column (default hide labels column)") - cmd.Flags().String("template", "", "Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].") - cmd.MarkFlagFilename("template") - cmd.Flags().String("sort-by", "", "If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.") - cmd.Flags().BoolP("show-all", "a", true, "When printing, show all resources (default show all pods including terminated one.)") - cmd.Flags().MarkDeprecated("show-all", "will be removed in an upcoming release") -} - -// AddOutputFlagsForMutation adds output related flags to a command. Used by mutations only. -func AddOutputFlagsForMutation(cmd *cobra.Command) { - cmd.Flags().StringP("output", "o", "", "Output mode. Use \"-o name\" for shorter output (resource/name).") -} - -// AddOutputVarFlagsForMutation adds output related flags to a command. Used by mutations only. -func AddOutputVarFlagsForMutation(cmd *cobra.Command, output *string) { - cmd.Flags().StringVarP(output, "output", "o", *output, "Output mode. Use \"-o name\" for shorter output (resource/name).") -} - -// AddOutputFlags adds output related flags to a command. -func AddOutputFlags(cmd *cobra.Command) { - cmd.Flags().StringP("output", "o", "", "Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].") - cmd.Flags().Bool("allow-missing-template-keys", true, "If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.") -} - -// AddNoHeadersFlags adds no-headers flags to a command. -func AddNoHeadersFlags(cmd *cobra.Command) { - cmd.Flags().Bool("no-headers", false, "When using the default or custom-column output format, don't print headers (default print headers).") -} - -// ValidateOutputArgs validates -o flag args for mutations -func ValidateOutputArgs(cmd *cobra.Command) error { - outputMode := GetFlagString(cmd, "output") - if outputMode != "" && outputMode != "name" { - return UsageErrorf(cmd, "Unexpected -o output mode: %v. We only support '-o name'.", outputMode) - } - return nil -} - -// PrintSuccess prints a success message and can do a "-o name" as "shortOutput" -// TODO this should really just be a printer. It's got just about the exact same signature. -func PrintSuccess(shortOutput bool, out io.Writer, obj runtime.Object, dryRun bool, operation string) { - dryRunMsg := "" - if dryRun { - dryRunMsg = " (dry run)" - } - - // match name printer format - name := "" - if acc, err := meta.Accessor(obj); err == nil { - if n := acc.GetName(); len(n) > 0 { - name = n - } - } - - // legacy scheme to be sure we work ok with internal types. - // TODO internal types aren't supposed to exist here - groupKind := printers.GetObjectGroupKind(obj, legacyscheme.Scheme) - kindString := fmt.Sprintf("%s.%s", strings.ToLower(groupKind.Kind), groupKind.Group) - if len(groupKind.Group) == 0 { - kindString = strings.ToLower(groupKind.Kind) - } - - if shortOutput { - // -o name: prints resource/name - fmt.Fprintf(out, "%s/%s\n", kindString, name) - return - } - - // understandable output by default - fmt.Fprintf(out, "%s \"%s\" %s%s\n", kindString, name, operation, dryRunMsg) -} - -// PrintObject prints a single object based on the default command options -// TODO this should go away once commands can embed the PrintOptions instead -func PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error { - printer, err := PrinterForOptions(ExtractCmdPrintOptions(cmd, false)) - if err != nil { - return err - } - return printer.PrintObj(obj, out) -} - -// PrinterForOptions returns the printer for the outputOptions (if given) or -// returns the default printer for the command. -// TODO this should become a function on the PrintOptions struct -func PrinterForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) { - // TODO: used by the custom column implementation and the name implementation, break this dependency - decoders := []runtime.Decoder{kubectlscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme} - encoder := kubectlscheme.Codecs.LegacyCodec(kubectlscheme.Registry.EnabledVersions()...) - - printer, err := printers.GetStandardPrinter(kubectlscheme.Scheme, encoder, decoders, *options) - if err != nil { - return nil, err - } - - // we try to convert to HumanReadablePrinter, if return ok, it must be no generic - // we execute AddHandlers() here before maybeWrapSortingPrinter so that we don't - // need to convert to delegatePrinter again then invoke AddHandlers() - // TODO this looks highly questionable. human readable printers are baked into code. This can just live in the definition of the handler itself - // TODO or be registered there - if humanReadablePrinter, ok := printer.(printers.PrintHandler); ok { - printersinternal.AddHandlers(humanReadablePrinter) - } - - printer = maybeWrapSortingPrinter(printer, *options) - - // wrap the printer in a versioning printer that understands when to convert and when not to convert - printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, legacyscheme.Scheme, kubectlscheme.Versions...) - - return printer, nil -} - -// ExtractCmdPrintOptions parses printer specific commandline args and -// returns a PrintOptions object. -// Requires that printer flags have been added to cmd (see AddPrinterFlags) -func ExtractCmdPrintOptions(cmd *cobra.Command, withNamespace bool) *printers.PrintOptions { - flags := cmd.Flags() - - columnLabel, err := flags.GetStringSlice("label-columns") - if err != nil { - columnLabel = []string{} - } - - options := &printers.PrintOptions{ - NoHeaders: GetFlagBool(cmd, "no-headers"), - Wide: GetWideFlag(cmd), - ShowAll: GetFlagBool(cmd, "show-all"), - ShowLabels: GetFlagBool(cmd, "show-labels"), - AbsoluteTimestamps: isWatch(cmd), - ColumnLabels: columnLabel, - WithNamespace: withNamespace, - } - - var outputFormat string - if flags.Lookup("output") != nil { - outputFormat = GetFlagString(cmd, "output") - } - - if flags.Lookup("sort-by") != nil { - options.SortBy = GetFlagString(cmd, "sort-by") - } - - // templates are logically optional for specifying a format. - // TODO once https://github.com/kubernetes/kubernetes/issues/12668 is fixed, this should fall back to GetFlagString - var templateFile string - if flag := flags.Lookup("template"); flag != nil { - if flag.Value.Type() == "string" { - templateFile = GetFlagString(cmd, "template") - } - } - if len(outputFormat) == 0 && len(templateFile) != 0 { - outputFormat = "template" - } - - templateFormats := []string{ - "go-template=", "go-template-file=", "jsonpath=", "jsonpath-file=", "custom-columns=", "custom-columns-file=", - } - for _, format := range templateFormats { - if strings.HasPrefix(outputFormat, format) { - templateFile = outputFormat[len(format):] - outputFormat = format[:len(format)-1] - } - } - - // this function may be invoked by a command that did not call AddPrinterFlags first, so we need - // to be safe about how we access the allow-missing-template-keys flag - if flags.Lookup("allow-missing-template-keys") != nil { - options.AllowMissingKeys = GetFlagBool(cmd, "allow-missing-template-keys") - } - - options.OutputFormatType = outputFormat - options.OutputFormatArgument = templateFile - - return options -} - -func maybeWrapSortingPrinter(printer printers.ResourcePrinter, printOpts printers.PrintOptions) printers.ResourcePrinter { - if len(printOpts.SortBy) != 0 { - return &kubectl.SortingPrinter{ - Delegate: printer, - SortField: fmt.Sprintf("{%s}", printOpts.SortBy), - } - } - return printer -} - -// ValidResourceTypeList returns a multi-line string containing the valid resources. May -// be called before the factory is initialized. -// TODO: This function implementation should be replaced with a real implementation from the -// discovery service. -func ValidResourceTypeList(f ClientAccessFactory) string { - // TODO: Should attempt to use the cached discovery list or fallback to a static list - // that is calculated from code compiled into the factory. - return templates.LongDesc(`Valid resource types include: - - * all - * certificatesigningrequests (aka 'csr') - * clusterrolebindings - * clusterroles - * componentstatuses (aka 'cs') - * configmaps (aka 'cm') - * controllerrevisions - * cronjobs - * customresourcedefinition (aka 'crd') - * daemonsets (aka 'ds') - * deployments (aka 'deploy') - * endpoints (aka 'ep') - * events (aka 'ev') - * horizontalpodautoscalers (aka 'hpa') - * ingresses (aka 'ing') - * jobs - * limitranges (aka 'limits') - * namespaces (aka 'ns') - * networkpolicies (aka 'netpol') - * nodes (aka 'no') - * persistentvolumeclaims (aka 'pvc') - * persistentvolumes (aka 'pv') - * poddisruptionbudgets (aka 'pdb') - * podpreset - * pods (aka 'po') - * podsecuritypolicies (aka 'psp') - * podtemplates - * replicasets (aka 'rs') - * replicationcontrollers (aka 'rc') - * resourcequotas (aka 'quota') - * rolebindings - * roles - * secrets - * serviceaccounts (aka 'sa') - * services (aka 'svc') - * statefulsets (aka 'sts') - * storageclasses (aka 'sc') - - `) -} - -// Retrieve a list of handled resources from printer as valid args -// TODO: This function implementation should be replaced with a real implementation from the discovery service. -func ValidArgList(f ClientAccessFactory) []string { - validArgs := []string{} - - humanReadablePrinter := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}) - printersinternal.AddHandlers(humanReadablePrinter) - validArgs = humanReadablePrinter.HandledResources() - - return validArgs +// SuggestApiResources returns a suggestion to use the "api-resources" command +// to retrieve a supported list of resources +func SuggestApiResources(parent string) string { + return templates.LongDesc(fmt.Sprintf("Use \"%s api-resources\" for a complete list of supported resources.", parent)) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper.go deleted file mode 100644 index 2ef8ce02b..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper.go +++ /dev/null @@ -1,160 +0,0 @@ -/* -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 util - -import ( - "strings" - - "github.com/golang/glog" - - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/discovery" - "k8s.io/kubernetes/pkg/kubectl" -) - -// shortcutExpander is a RESTMapper that can be used for Kubernetes resources. It expands the resource first, then invokes the wrapped -type shortcutExpander struct { - RESTMapper meta.RESTMapper - - discoveryClient discovery.DiscoveryInterface -} - -var _ meta.RESTMapper = &shortcutExpander{} - -func NewShortcutExpander(delegate meta.RESTMapper, client discovery.DiscoveryInterface) shortcutExpander { - return shortcutExpander{RESTMapper: delegate, discoveryClient: client} -} - -func (e shortcutExpander) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { - return e.RESTMapper.KindFor(e.expandResourceShortcut(resource)) -} - -func (e shortcutExpander) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { - return e.RESTMapper.KindsFor(e.expandResourceShortcut(resource)) -} - -func (e shortcutExpander) ResourcesFor(resource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { - return e.RESTMapper.ResourcesFor(e.expandResourceShortcut(resource)) -} - -func (e shortcutExpander) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) { - return e.RESTMapper.ResourceFor(e.expandResourceShortcut(resource)) -} - -func (e shortcutExpander) ResourceSingularizer(resource string) (string, error) { - return e.RESTMapper.ResourceSingularizer(e.expandResourceShortcut(schema.GroupVersionResource{Resource: resource}).Resource) -} - -func (e shortcutExpander) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { - return e.RESTMapper.RESTMapping(gk, versions...) -} - -func (e shortcutExpander) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) { - return e.RESTMapper.RESTMappings(gk, versions...) -} - -// getShortcutMappings returns a set of tuples which holds short names for resources. -// First the list of potential resources will be taken from the API server. -// Next we will append the hardcoded list of resources - to be backward compatible with old servers. -// NOTE that the list is ordered by group priority. -func (e shortcutExpander) getShortcutMappings() ([]*metav1.APIResourceList, []kubectl.ResourceShortcuts, error) { - res := []kubectl.ResourceShortcuts{} - // get server resources - // This can return an error *and* the results it was able to find. We don't need to fail on the error. - apiResList, err := e.discoveryClient.ServerResources() - if err != nil { - glog.V(1).Infof("Error loading discovery information: %v", err) - } - for _, apiResources := range apiResList { - gv, err := schema.ParseGroupVersion(apiResources.GroupVersion) - if err != nil { - glog.V(1).Infof("Unable to parse groupversion = %s due to = %s", apiResources.GroupVersion, err.Error()) - continue - } - for _, apiRes := range apiResources.APIResources { - for _, shortName := range apiRes.ShortNames { - rs := kubectl.ResourceShortcuts{ - ShortForm: schema.GroupResource{Group: gv.Group, Resource: shortName}, - LongForm: schema.GroupResource{Group: gv.Group, Resource: apiRes.Name}, - } - res = append(res, rs) - } - } - } - - // append hardcoded short forms at the end of the list - res = append(res, kubectl.ResourcesShortcutStatic...) - return apiResList, res, nil -} - -// expandResourceShortcut will return the expanded version of resource -// (something that a pkg/api/meta.RESTMapper can understand), if it is -// indeed a shortcut. If no match has been found, we will match on group prefixing. -// Lastly we will return resource unmodified. -func (e shortcutExpander) expandResourceShortcut(resource schema.GroupVersionResource) schema.GroupVersionResource { - // get the shortcut mappings and return on first match. - if allResources, shortcutResources, err := e.getShortcutMappings(); err == nil { - // avoid expanding if there's an exact match to a full resource name - for _, apiResources := range allResources { - gv, err := schema.ParseGroupVersion(apiResources.GroupVersion) - if err != nil { - continue - } - if len(resource.Group) != 0 && resource.Group != gv.Group { - continue - } - for _, apiRes := range apiResources.APIResources { - if resource.Resource == apiRes.Name { - return resource - } - if resource.Resource == apiRes.SingularName { - return resource - } - } - } - - for _, item := range shortcutResources { - if len(resource.Group) != 0 && resource.Group != item.ShortForm.Group { - continue - } - if resource.Resource == item.ShortForm.Resource { - resource.Resource = item.LongForm.Resource - resource.Group = item.LongForm.Group - return resource - } - } - - // we didn't find exact match so match on group prefixing. This allows autoscal to match autoscaling - if len(resource.Group) == 0 { - return resource - } - for _, item := range shortcutResources { - if !strings.HasPrefix(item.ShortForm.Group, resource.Group) { - continue - } - if resource.Resource == item.ShortForm.Resource { - resource.Resource = item.LongForm.Resource - resource.Group = item.LongForm.Group - return resource - } - } - } - - return resource -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper_test.go deleted file mode 100644 index 941ac63d9..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper_test.go +++ /dev/null @@ -1,195 +0,0 @@ -/* -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 util - -import ( - "testing" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/pkg/api/testapi" -) - -func TestReplaceAliases(t *testing.T) { - tests := []struct { - name string - arg string - expected schema.GroupVersionResource - srvRes []*metav1.APIResourceList - }{ - { - name: "rc-resolves-to-replicationcontrollers", - arg: "rc", - expected: schema.GroupVersionResource{Resource: "replicationcontrollers"}, - srvRes: []*metav1.APIResourceList{}, - }, - { - name: "storageclasses-no-replacement", - arg: "storageclasses", - expected: schema.GroupVersionResource{Resource: "storageclasses"}, - srvRes: []*metav1.APIResourceList{}, - }, - { - name: "hpa-priority", - arg: "hpa", - expected: schema.GroupVersionResource{Resource: "superhorizontalpodautoscalers", Group: "autoscaling"}, - srvRes: []*metav1.APIResourceList{ - { - GroupVersion: "autoscaling/v1", - APIResources: []metav1.APIResource{ - { - Name: "superhorizontalpodautoscalers", - ShortNames: []string{"hpa"}, - }, - }, - }, - { - GroupVersion: "autoscaling/v1", - APIResources: []metav1.APIResource{ - { - Name: "horizontalpodautoscalers", - ShortNames: []string{"hpa"}, - }, - }, - }, - }, - }, - { - name: "resource-override", - arg: "dpl", - expected: schema.GroupVersionResource{Resource: "deployments", Group: "foo"}, - srvRes: []*metav1.APIResourceList{ - { - GroupVersion: "foo/v1", - APIResources: []metav1.APIResource{ - { - Name: "deployments", - ShortNames: []string{"dpl"}, - }, - }, - }, - { - GroupVersion: "extension/v1beta1", - APIResources: []metav1.APIResource{ - { - Name: "deployments", - ShortNames: []string{"deploy"}, - }, - }, - }, - }, - }, - { - name: "resource-match-preferred", - arg: "pods", - expected: schema.GroupVersionResource{Resource: "pods", Group: ""}, - srvRes: []*metav1.APIResourceList{ - { - GroupVersion: "v1", - APIResources: []metav1.APIResource{{Name: "pods", SingularName: "pod"}}, - }, - { - GroupVersion: "acme.com/v1", - APIResources: []metav1.APIResource{{Name: "poddlers", ShortNames: []string{"pods", "pod"}}}, - }, - }, - }, - { - name: "resource-match-singular-preferred", - arg: "pod", - expected: schema.GroupVersionResource{Resource: "pod", Group: ""}, - srvRes: []*metav1.APIResourceList{ - { - GroupVersion: "v1", - APIResources: []metav1.APIResource{{Name: "pods", SingularName: "pod"}}, - }, - { - GroupVersion: "acme.com/v1", - APIResources: []metav1.APIResource{{Name: "poddlers", ShortNames: []string{"pods", "pod"}}}, - }, - }, - }, - } - - ds := &fakeDiscoveryClient{} - mapper := NewShortcutExpander(testapi.Default.RESTMapper(), ds) - - for _, test := range tests { - ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { - return test.srvRes, nil - } - actual := mapper.expandResourceShortcut(schema.GroupVersionResource{Resource: test.arg}) - if actual != test.expected { - t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, actual) - } - } -} - -func TestKindFor(t *testing.T) { - tests := []struct { - in schema.GroupVersionResource - expected schema.GroupVersionKind - srvRes []*metav1.APIResourceList - }{ - { - in: schema.GroupVersionResource{Group: "storage.k8s.io", Version: "", Resource: "sc"}, - expected: schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1", Kind: "StorageClass"}, - srvRes: []*metav1.APIResourceList{ - { - GroupVersion: "storage.k8s.io/v1", - APIResources: []metav1.APIResource{ - { - Name: "storageclasses", - ShortNames: []string{"sc"}, - }, - }, - }, - }, - }, - { - in: schema.GroupVersionResource{Group: "", Version: "", Resource: "sc"}, - expected: schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1", Kind: "StorageClass"}, - srvRes: []*metav1.APIResourceList{ - { - GroupVersion: "storage.k8s.io/v1", - APIResources: []metav1.APIResource{ - { - Name: "storageclasses", - ShortNames: []string{"sc"}, - }, - }, - }, - }, - }, - } - - ds := &fakeDiscoveryClient{} - mapper := NewShortcutExpander(testapi.Default.RESTMapper(), ds) - - for i, test := range tests { - ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { - return test.srvRes, nil - } - ret, err := mapper.KindFor(test.in) - if err != nil { - t.Errorf("%d: unexpected error returned %s", i, err.Error()) - } - if ret != test.expected { - t.Errorf("%d: unexpected data returned %#v, expected %#v", i, ret, test.expected) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/version.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/version.go index 53c6deccb..d5f6030c2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/version.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/version.go @@ -20,14 +20,15 @@ import ( "encoding/json" "errors" "fmt" - "io" "github.com/ghodss/yaml" "github.com/spf13/cobra" apimachineryversion "k8s.io/apimachinery/pkg/version" + "k8s.io/client-go/discovery" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/version" ) @@ -37,52 +38,67 @@ type Version struct { ServerVersion *apimachineryversion.Info `json:"serverVersion,omitempty" yaml:"serverVersion,omitempty"` } -// VersionOptions: describe the options available to users of the "kubectl -// version" command. -type VersionOptions struct { - clientOnly bool - short bool - output string -} - var ( versionExample = templates.Examples(i18n.T(` # Print the client and server versions for the current context kubectl version`)) ) -func NewCmdVersion(f cmdutil.Factory, out io.Writer) *cobra.Command { +type VersionOptions struct { + ClientOnly bool + Short bool + Output string + + discoveryClient discovery.CachedDiscoveryInterface + + genericclioptions.IOStreams +} + +func NewVersionOptions(ioStreams genericclioptions.IOStreams) *VersionOptions { + return &VersionOptions{ + IOStreams: ioStreams, + } + +} + +func NewCmdVersion(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewVersionOptions(ioStreams) cmd := &cobra.Command{ Use: "version", Short: i18n.T("Print the client and server version information"), Long: "Print the client and server version information for the current context", Example: versionExample, Run: func(cmd *cobra.Command, args []string) { - options := new(VersionOptions) - cmdutil.CheckErr(options.Complete(cmd)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.Run(f, out)) + cmdutil.CheckErr(o.Complete(f, cmd)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.Run()) }, } - cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).") - cmd.Flags().BoolP("short", "", false, "Print just the version number.") - cmd.Flags().StringP("output", "o", "", "One of 'yaml' or 'json'.") + cmd.Flags().BoolVarP(&o.ClientOnly, "client", "c", o.ClientOnly, "Client version only (no server required).") + cmd.Flags().BoolVarP(&o.Short, "short", "", o.Short, "Print just the version number.") + cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, "One of 'yaml' or 'json'.") cmd.Flags().MarkShorthandDeprecated("client", "please use --client instead.") return cmd } -func retrieveServerVersion(f cmdutil.Factory) (*apimachineryversion.Info, error) { - discoveryClient, err := f.DiscoveryClient() +func (o *VersionOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { + var err error + o.discoveryClient, err = f.ToDiscoveryClient() if err != nil { - return nil, err + return err } + return nil +} - // Always request fresh data from the server - discoveryClient.Invalidate() - return discoveryClient.ServerVersion() +func (o *VersionOptions) Validate() error { + if o.Output != "" && o.Output != "yaml" && o.Output != "json" { + return errors.New(`--output must be 'yaml' or 'json'`) + } + + return nil } -func (o *VersionOptions) Run(f cmdutil.Factory, out io.Writer) error { +func (o *VersionOptions) Run() error { var ( serverVersion *apimachineryversion.Info serverErr error @@ -92,22 +108,24 @@ func (o *VersionOptions) Run(f cmdutil.Factory, out io.Writer) error { clientVersion := version.Get() versionInfo.ClientVersion = &clientVersion - if !o.clientOnly { - serverVersion, serverErr = retrieveServerVersion(f) + if !o.ClientOnly { + // Always request fresh data from the server + o.discoveryClient.Invalidate() + serverVersion, serverErr = o.discoveryClient.ServerVersion() versionInfo.ServerVersion = serverVersion } - switch o.output { + switch o.Output { case "": - if o.short { - fmt.Fprintf(out, "Client Version: %s\n", clientVersion.GitVersion) + if o.Short { + fmt.Fprintf(o.Out, "Client Version: %s\n", clientVersion.GitVersion) if serverVersion != nil { - fmt.Fprintf(out, "Server Version: %s\n", serverVersion.GitVersion) + fmt.Fprintf(o.Out, "Server Version: %s\n", serverVersion.GitVersion) } } else { - fmt.Fprintf(out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion)) + fmt.Fprintf(o.Out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion)) if serverVersion != nil { - fmt.Fprintf(out, "Server Version: %s\n", fmt.Sprintf("%#v", *serverVersion)) + fmt.Fprintf(o.Out, "Server Version: %s\n", fmt.Sprintf("%#v", *serverVersion)) } } case "yaml": @@ -115,33 +133,18 @@ func (o *VersionOptions) Run(f cmdutil.Factory, out io.Writer) error { if err != nil { return err } - fmt.Fprintln(out, string(marshalled)) + fmt.Fprintln(o.Out, string(marshalled)) case "json": marshalled, err := json.MarshalIndent(&versionInfo, "", " ") if err != nil { return err } - fmt.Fprintln(out, string(marshalled)) + fmt.Fprintln(o.Out, string(marshalled)) default: // There is a bug in the program if we hit this case. // However, we follow a policy of never panicking. - return fmt.Errorf("VersionOptions were not validated: --output=%q should have been rejected", o.output) + return fmt.Errorf("VersionOptions were not validated: --output=%q should have been rejected", o.Output) } return serverErr } - -func (o *VersionOptions) Complete(cmd *cobra.Command) error { - o.clientOnly = cmdutil.GetFlagBool(cmd, "client") - o.short = cmdutil.GetFlagBool(cmd, "short") - o.output = cmdutil.GetFlagString(cmd, "output") - return nil -} - -func (o *VersionOptions) Validate() error { - if o.output != "" && o.output != "yaml" && o.output != "json" { - return errors.New(`--output must be 'yaml' or 'json'`) - } - - return nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/wait/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/wait/BUILD new file mode 100644 index 000000000..0ad4eb467 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/wait/BUILD @@ -0,0 +1,59 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["wait.go"], + importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/wait", + visibility = ["//visibility:public"], + deps = [ + "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/dynamic:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["wait_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//vendor/github.com/davecgh/go-spew/spew:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/dynamic/fake:go_default_library", + "//vendor/k8s.io/client-go/testing:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/wait/wait.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/wait/wait.go new file mode 100644 index 000000000..1c6e886b8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/wait/wait.go @@ -0,0 +1,347 @@ +/* +Copyright 2018 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 wait + +import ( + "fmt" + "strings" + "time" + + "github.com/spf13/cobra" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/dynamic" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" +) + +// WaitFlags directly reflect the information that CLI is gathering via flags. They will be converted to Options, which +// reflect the runtime requirements for the command. This structure reduces the transformation to wiring and makes +// the logic itself easy to unit test +type WaitFlags struct { + RESTClientGetter genericclioptions.RESTClientGetter + PrintFlags *genericclioptions.PrintFlags + ResourceBuilderFlags *genericclioptions.ResourceBuilderFlags + + Timeout time.Duration + ForCondition string + + genericclioptions.IOStreams +} + +// NewWaitFlags returns a default WaitFlags +func NewWaitFlags(restClientGetter genericclioptions.RESTClientGetter, streams genericclioptions.IOStreams) *WaitFlags { + return &WaitFlags{ + RESTClientGetter: restClientGetter, + PrintFlags: genericclioptions.NewPrintFlags("condition met"), + ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags(). + WithLabelSelector(""). + WithAllNamespaces(false). + WithLatest(), + + Timeout: 30 * time.Second, + + IOStreams: streams, + } +} + +// NewCmdWait returns a cobra command for waiting +func NewCmdWait(restClientGetter genericclioptions.RESTClientGetter, streams genericclioptions.IOStreams) *cobra.Command { + flags := NewWaitFlags(restClientGetter, streams) + + cmd := &cobra.Command{ + Use: "wait resource.group/name [--for=delete|--for condition=available]", + DisableFlagsInUseLine: true, + Short: "Experimental: Wait for one condition on one or many resources", + Run: func(cmd *cobra.Command, args []string) { + o, err := flags.ToOptions(args) + cmdutil.CheckErr(err) + err = o.RunWait() + cmdutil.CheckErr(err) + }, + SuggestFor: []string{"list", "ps"}, + } + + flags.AddFlags(cmd) + + return cmd +} + +// AddFlags registers flags for a cli +func (flags *WaitFlags) AddFlags(cmd *cobra.Command) { + flags.PrintFlags.AddFlags(cmd) + flags.ResourceBuilderFlags.AddFlags(cmd.Flags()) + + cmd.Flags().DurationVar(&flags.Timeout, "timeout", flags.Timeout, "The length of time to wait before giving up. Zero means check once and don't wait, negative means wait for a week.") + cmd.Flags().StringVar(&flags.ForCondition, "for", flags.ForCondition, "The condition to wait on: [delete|condition=condition-name].") +} + +// ToOptions converts from CLI inputs to runtime inputs +func (flags *WaitFlags) ToOptions(args []string) (*WaitOptions, error) { + printer, err := flags.PrintFlags.ToPrinter() + if err != nil { + return nil, err + } + builder := flags.ResourceBuilderFlags.ToBuilder(flags.RESTClientGetter, args) + clientConfig, err := flags.RESTClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + dynamicClient, err := dynamic.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + conditionFn, err := conditionFuncFor(flags.ForCondition) + if err != nil { + return nil, err + } + + effectiveTimeout := flags.Timeout + if effectiveTimeout < 0 { + effectiveTimeout = 168 * time.Hour + } + + o := &WaitOptions{ + ResourceFinder: builder, + DynamicClient: dynamicClient, + Timeout: effectiveTimeout, + + Printer: printer, + ConditionFn: conditionFn, + IOStreams: flags.IOStreams, + } + + return o, nil +} + +func conditionFuncFor(condition string) (ConditionFunc, error) { + if strings.ToLower(condition) == "delete" { + return IsDeleted, nil + } + if strings.HasPrefix(condition, "condition=") { + conditionName := condition[len("condition="):] + return ConditionalWait{ + conditionName: conditionName, + // TODO allow specifying a false + conditionStatus: "true", + }.IsConditionMet, nil + } + + return nil, fmt.Errorf("unrecognized condition: %q", condition) +} + +type ResourceLocation struct { + GroupResource schema.GroupResource + Namespace string + Name string +} + +type UIDMap map[ResourceLocation]types.UID + +// WaitOptions is a set of options that allows you to wait. This is the object reflects the runtime needs of a wait +// command, making the logic itself easy to unit test with our existing mocks. +type WaitOptions struct { + ResourceFinder genericclioptions.ResourceFinder + // UIDMap maps a resource location to a UID. It is optional, but ConditionFuncs may choose to use it to make the result + // more reliable. For instance, delete can look for UID consistency during delegated calls. + UIDMap UIDMap + DynamicClient dynamic.Interface + Timeout time.Duration + + Printer printers.ResourcePrinter + ConditionFn ConditionFunc + genericclioptions.IOStreams +} + +// ConditionFunc is the interface for providing condition checks +type ConditionFunc func(info *resource.Info, o *WaitOptions) (finalObject runtime.Object, done bool, err error) + +// RunWait runs the waiting logic +func (o *WaitOptions) RunWait() error { + return o.ResourceFinder.Do().Visit(func(info *resource.Info, err error) error { + if err != nil { + return err + } + + finalObject, success, err := o.ConditionFn(info, o) + if success { + o.Printer.PrintObj(finalObject, o.Out) + return nil + } + if err == nil { + return fmt.Errorf("%v unsatisified for unknown reason", finalObject) + } + return err + }) +} + +// IsDeleted is a condition func for waiting for something to be deleted +func IsDeleted(info *resource.Info, o *WaitOptions) (runtime.Object, bool, error) { + endTime := time.Now().Add(o.Timeout) + for { + gottenObj, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Get(info.Name, metav1.GetOptions{}) + if errors.IsNotFound(err) { + return info.Object, true, nil + } + if err != nil { + // TODO this could do something slightly fancier if we wish + return info.Object, false, err + } + resourceLocation := ResourceLocation{ + GroupResource: info.Mapping.Resource.GroupResource(), + Namespace: gottenObj.GetNamespace(), + Name: gottenObj.GetName(), + } + if uid, ok := o.UIDMap[resourceLocation]; ok { + if gottenObj.GetUID() != uid { + return gottenObj, true, nil + } + } + + watchOptions := metav1.ListOptions{} + watchOptions.FieldSelector = "metadata.name=" + info.Name + watchOptions.ResourceVersion = gottenObj.GetResourceVersion() + objWatch, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Watch(watchOptions) + if err != nil { + return gottenObj, false, err + } + + timeout := endTime.Sub(time.Now()) + if timeout < 0 { + // we're out of time + return gottenObj, false, wait.ErrWaitTimeout + } + watchEvent, err := watch.Until(o.Timeout, objWatch, isDeleted) + switch { + case err == nil: + return watchEvent.Object, true, nil + case err == watch.ErrWatchClosed: + continue + case err == wait.ErrWaitTimeout: + if watchEvent != nil { + return watchEvent.Object, false, wait.ErrWaitTimeout + } + return gottenObj, false, wait.ErrWaitTimeout + default: + return gottenObj, false, err + } + } +} + +func isDeleted(event watch.Event) (bool, error) { + return event.Type == watch.Deleted, nil +} + +// ConditionalWait hold information to check an API status condition +type ConditionalWait struct { + conditionName string + conditionStatus string +} + +// IsConditionMet is a conditionfunc for waiting on an API condition to be met +func (w ConditionalWait) IsConditionMet(info *resource.Info, o *WaitOptions) (runtime.Object, bool, error) { + endTime := time.Now().Add(o.Timeout) + for { + resourceVersion := "" + gottenObj, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Get(info.Name, metav1.GetOptions{}) + switch { + case errors.IsNotFound(err): + resourceVersion = "0" + case err != nil: + return info.Object, false, err + default: + conditionMet, err := w.checkCondition(gottenObj) + if conditionMet { + return gottenObj, true, nil + } + if err != nil { + return gottenObj, false, err + } + resourceVersion = gottenObj.GetResourceVersion() + } + + watchOptions := metav1.ListOptions{} + watchOptions.FieldSelector = "metadata.name=" + info.Name + watchOptions.ResourceVersion = resourceVersion + objWatch, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Watch(watchOptions) + if err != nil { + return gottenObj, false, err + } + + timeout := endTime.Sub(time.Now()) + if timeout < 0 { + // we're out of time + return gottenObj, false, wait.ErrWaitTimeout + } + watchEvent, err := watch.Until(o.Timeout, objWatch, w.isConditionMet) + switch { + case err == nil: + return watchEvent.Object, true, nil + case err == watch.ErrWatchClosed: + continue + case err == wait.ErrWaitTimeout: + if watchEvent != nil { + return watchEvent.Object, false, wait.ErrWaitTimeout + } + return gottenObj, false, wait.ErrWaitTimeout + default: + return gottenObj, false, err + } + } +} + +func (w ConditionalWait) checkCondition(obj *unstructured.Unstructured) (bool, error) { + conditions, found, err := unstructured.NestedSlice(obj.Object, "status", "conditions") + if err != nil { + return false, err + } + if !found { + return false, nil + } + for _, conditionUncast := range conditions { + condition := conditionUncast.(map[string]interface{}) + name, found, err := unstructured.NestedString(condition, "type") + if !found || err != nil || strings.ToLower(name) != strings.ToLower(w.conditionName) { + continue + } + status, found, err := unstructured.NestedString(condition, "status") + if !found || err != nil { + continue + } + return strings.ToLower(status) == strings.ToLower(w.conditionStatus), nil + } + + return false, nil +} + +func (w ConditionalWait) isConditionMet(event watch.Event) (bool, error) { + if event.Type == watch.Deleted { + // this will chain back out, result in another get and an return false back up the chain + return false, nil + } + obj := event.Object.(*unstructured.Unstructured) + return w.checkCondition(obj) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/wait/wait_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/wait/wait_test.go new file mode 100644 index 000000000..06fbc859b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/wait/wait_test.go @@ -0,0 +1,527 @@ +/* +Copyright 2018 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 wait + +import ( + "testing" + + "time" + + "strings" + + "github.com/davecgh/go-spew/spew" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/watch" + dynamicfakeclient "k8s.io/client-go/dynamic/fake" + clienttesting "k8s.io/client-go/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" +) + +func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": apiVersion, + "kind": kind, + "metadata": map[string]interface{}{ + "namespace": namespace, + "name": name, + "uid": "some-UID-value", + }, + }, + } +} + +func addCondition(in *unstructured.Unstructured, name, status string) *unstructured.Unstructured { + conditions, _, _ := unstructured.NestedSlice(in.Object, "status", "conditions") + conditions = append(conditions, map[string]interface{}{ + "type": name, + "status": status, + }) + unstructured.SetNestedSlice(in.Object, conditions, "status", "conditions") + return in +} + +func TestWaitForDeletion(t *testing.T) { + scheme := runtime.NewScheme() + + tests := []struct { + name string + info *resource.Info + fakeClient func() *dynamicfakeclient.FakeDynamicClient + timeout time.Duration + uidMap UIDMap + + expectedErr string + validateActions func(t *testing.T, actions []clienttesting.Action) + }{ + { + name: "missing on get", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + return dynamicfakeclient.NewSimpleDynamicClient(scheme) + }, + timeout: 10 * time.Second, + + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 1 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + }, + }, + { + name: "uid conflict on get", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + return true, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), nil + }) + count := 0 + fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) { + if count == 0 { + count++ + fakeWatch := watch.NewRaceFreeFake() + go func() { + time.Sleep(100 * time.Millisecond) + fakeWatch.Stop() + }() + return true, fakeWatch, nil + } + fakeWatch := watch.NewRaceFreeFake() + return true, fakeWatch, nil + }) + return fakeClient + }, + timeout: 10 * time.Second, + uidMap: UIDMap{ + ResourceLocation{Namespace: "ns-foo", Name: "name-foo"}: types.UID("some-UID-value"), + ResourceLocation{GroupResource: schema.GroupResource{Group: "group", Resource: "theresource"}, Namespace: "ns-foo", Name: "name-foo"}: types.UID("some-nonmatching-UID-value"), + }, + + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 1 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + }, + }, + { + name: "times out", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + return true, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), nil + }) + return fakeClient + }, + timeout: 1 * time.Second, + + expectedErr: wait.ErrWaitTimeout.Error(), + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 2 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + if !actions[1].Matches("watch", "theresource") { + t.Error(spew.Sdump(actions)) + } + }, + }, + { + name: "handles watch close out", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + return true, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), nil + }) + count := 0 + fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) { + if count == 0 { + count++ + fakeWatch := watch.NewRaceFreeFake() + go func() { + time.Sleep(100 * time.Millisecond) + fakeWatch.Stop() + }() + return true, fakeWatch, nil + } + fakeWatch := watch.NewRaceFreeFake() + return true, fakeWatch, nil + }) + return fakeClient + }, + timeout: 3 * time.Second, + + expectedErr: wait.ErrWaitTimeout.Error(), + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 4 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + if !actions[1].Matches("watch", "theresource") { + t.Error(spew.Sdump(actions)) + } + if !actions[2].Matches("get", "theresource") || actions[2].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + if !actions[3].Matches("watch", "theresource") { + t.Error(spew.Sdump(actions)) + } + }, + }, + { + name: "handles watch delete", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + return true, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), nil + }) + fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) { + fakeWatch := watch.NewRaceFreeFake() + fakeWatch.Action(watch.Deleted, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")) + return true, fakeWatch, nil + }) + return fakeClient + }, + timeout: 10 * time.Second, + + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 2 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + if !actions[1].Matches("watch", "theresource") { + t.Error(spew.Sdump(actions)) + } + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + fakeClient := test.fakeClient() + o := &WaitOptions{ + ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(test.info), + UIDMap: test.uidMap, + DynamicClient: fakeClient, + Timeout: test.timeout, + + Printer: printers.NewDiscardingPrinter(), + ConditionFn: IsDeleted, + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), + } + err := o.RunWait() + switch { + case err == nil && len(test.expectedErr) == 0: + case err != nil && len(test.expectedErr) == 0: + t.Fatal(err) + case err == nil && len(test.expectedErr) != 0: + t.Fatalf("missing: %q", test.expectedErr) + case err != nil && len(test.expectedErr) != 0: + if !strings.Contains(err.Error(), test.expectedErr) { + t.Fatalf("expected %q, got %q", test.expectedErr, err.Error()) + } + } + + test.validateActions(t, fakeClient.Actions()) + }) + } +} + +func TestWaitForCondition(t *testing.T) { + scheme := runtime.NewScheme() + + tests := []struct { + name string + info *resource.Info + fakeClient func() *dynamicfakeclient.FakeDynamicClient + timeout time.Duration + + expectedErr string + validateActions func(t *testing.T, actions []clienttesting.Action) + }{ + { + name: "present on get", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + return true, addCondition( + newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), + "the-condition", "status-value", + ), nil + }) + return fakeClient + }, + timeout: 10 * time.Second, + + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 1 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + }, + }, + { + name: "times out", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + return true, addCondition( + newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), + "some-other-condition", "status-value", + ), nil + }) + return fakeClient + }, + timeout: 1 * time.Second, + + expectedErr: wait.ErrWaitTimeout.Error(), + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 2 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + if !actions[1].Matches("watch", "theresource") { + t.Error(spew.Sdump(actions)) + } + }, + }, + { + name: "handles watch close out", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + return true, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), nil + }) + count := 0 + fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) { + if count == 0 { + count++ + fakeWatch := watch.NewRaceFreeFake() + go func() { + time.Sleep(100 * time.Millisecond) + fakeWatch.Stop() + }() + return true, fakeWatch, nil + } + fakeWatch := watch.NewRaceFreeFake() + return true, fakeWatch, nil + }) + return fakeClient + }, + timeout: 3 * time.Second, + + expectedErr: wait.ErrWaitTimeout.Error(), + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 4 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + if !actions[1].Matches("watch", "theresource") { + t.Error(spew.Sdump(actions)) + } + if !actions[2].Matches("get", "theresource") || actions[2].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + if !actions[3].Matches("watch", "theresource") { + t.Error(spew.Sdump(actions)) + } + }, + }, + { + name: "handles watch condition change", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) { + return true, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), nil + }) + fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) { + fakeWatch := watch.NewRaceFreeFake() + fakeWatch.Action(watch.Modified, addCondition( + newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), + "the-condition", "status-value", + )) + return true, fakeWatch, nil + }) + return fakeClient + }, + timeout: 10 * time.Second, + + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 2 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + if !actions[1].Matches("watch", "theresource") { + t.Error(spew.Sdump(actions)) + } + }, + }, + { + name: "handles watch created", + info: &resource.Info{ + Mapping: &meta.RESTMapping{ + Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"}, + }, + Name: "name-foo", + Namespace: "ns-foo", + }, + fakeClient: func() *dynamicfakeclient.FakeDynamicClient { + fakeClient := dynamicfakeclient.NewSimpleDynamicClient(scheme) + fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) { + fakeWatch := watch.NewRaceFreeFake() + fakeWatch.Action(watch.Added, addCondition( + newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), + "the-condition", "status-value", + )) + return true, fakeWatch, nil + }) + return fakeClient + }, + timeout: 10 * time.Second, + + validateActions: func(t *testing.T, actions []clienttesting.Action) { + if len(actions) != 2 { + t.Fatal(spew.Sdump(actions)) + } + if !actions[0].Matches("get", "theresource") || actions[0].(clienttesting.GetAction).GetName() != "name-foo" { + t.Error(spew.Sdump(actions)) + } + if !actions[1].Matches("watch", "theresource") { + t.Error(spew.Sdump(actions)) + } + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + fakeClient := test.fakeClient() + o := &WaitOptions{ + ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(test.info), + DynamicClient: fakeClient, + Timeout: test.timeout, + + Printer: printers.NewDiscardingPrinter(), + ConditionFn: ConditionalWait{conditionName: "the-condition", conditionStatus: "status-value"}.IsConditionMet, + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), + } + err := o.RunWait() + switch { + case err == nil && len(test.expectedErr) == 0: + case err != nil && len(test.expectedErr) == 0: + t.Fatal(err) + case err == nil && len(test.expectedErr) != 0: + t.Fatalf("missing: %q", test.expectedErr) + case err != nil && len(test.expectedErr) != 0: + if !strings.Contains(err.Error(), test.expectedErr) { + t.Fatalf("expected %q, got %q", test.expectedErr, err.Error()) + } + } + + test.validateActions(t, fakeClient.Actions()) + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/conditions.go b/vendor/k8s.io/kubernetes/pkg/kubectl/conditions.go index 666b248f4..771ccbc4f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/conditions.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/conditions.go @@ -26,11 +26,9 @@ import ( "k8s.io/apimachinery/pkg/watch" "k8s.io/kubernetes/pkg/api/pod" "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/apis/batch" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/extensions" appsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion" - batchclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion" coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion" ) @@ -99,30 +97,6 @@ func StatefulSetHasDesiredReplicas(ssClient appsclient.StatefulSetsGetter, ss *a } } -// JobHasDesiredParallelism returns a condition that will be true if the desired parallelism count -// for a job equals the current active counts or is less by an appropriate successful/unsuccessful count. -func JobHasDesiredParallelism(jobClient batchclient.JobsGetter, job *batch.Job) wait.ConditionFunc { - return func() (bool, error) { - job, err := jobClient.Jobs(job.Namespace).Get(job.Name, metav1.GetOptions{}) - if err != nil { - return false, err - } - - // desired parallelism can be either the exact number, in which case return immediately - if job.Status.Active == *job.Spec.Parallelism { - return true, nil - } - if job.Spec.Completions == nil { - // A job without specified completions needs to wait for Active to reach Parallelism. - return false, nil - } - - // otherwise count successful - progress := *job.Spec.Completions - job.Status.Active - job.Status.Succeeded - return progress == 0, nil - } -} - // DeploymentHasDesiredReplicas returns a condition that will be true if and only if // the desired replica count for a deployment equals its updated replicas count. // (non-terminated pods that have the desired template spec). diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/delete.go b/vendor/k8s.io/kubernetes/pkg/kubectl/delete.go deleted file mode 100644 index 2c8e32676..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/delete.go +++ /dev/null @@ -1,487 +0,0 @@ -/* -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 kubectl - -import ( - "fmt" - "strings" - "time" - - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime/schema" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/apis/batch" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - appsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion" - batchclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion" - coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion" - deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" -) - -const ( - Interval = time.Second * 1 - Timeout = time.Minute * 5 -) - -// A Reaper terminates an object as gracefully as possible. -type Reaper interface { - // Stop a given object within a namespace. timeout is how long we'll - // wait for the termination to be successful. gracePeriod is time given - // to an API object for it to delete itself cleanly (e.g., pod - // shutdown). It may or may not be supported by the API object. - Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error -} - -type NoSuchReaperError struct { - kind schema.GroupKind -} - -func (n *NoSuchReaperError) Error() string { - return fmt.Sprintf("no reaper has been implemented for %v", n.kind) -} - -func IsNoSuchReaperError(err error) bool { - _, ok := err.(*NoSuchReaperError) - return ok -} - -func ReaperFor(kind schema.GroupKind, c internalclientset.Interface) (Reaper, error) { - switch kind { - case api.Kind("ReplicationController"): - return &ReplicationControllerReaper{c.Core(), Interval, Timeout}, nil - - case extensions.Kind("ReplicaSet"), apps.Kind("ReplicaSet"): - return &ReplicaSetReaper{c.Extensions(), Interval, Timeout}, nil - - case extensions.Kind("DaemonSet"), apps.Kind("DaemonSet"): - return &DaemonSetReaper{c.Extensions(), Interval, Timeout}, nil - - case api.Kind("Pod"): - return &PodReaper{c.Core()}, nil - - case batch.Kind("Job"): - return &JobReaper{c.Batch(), c.Core(), Interval, Timeout}, nil - - case apps.Kind("StatefulSet"): - return &StatefulSetReaper{c.Apps(), c.Core(), Interval, Timeout}, nil - - case extensions.Kind("Deployment"), apps.Kind("Deployment"): - return &DeploymentReaper{c.Extensions(), c.Extensions(), Interval, Timeout}, nil - - } - return nil, &NoSuchReaperError{kind} -} - -func ReaperForReplicationController(rcClient coreclient.ReplicationControllersGetter, timeout time.Duration) (Reaper, error) { - return &ReplicationControllerReaper{rcClient, Interval, timeout}, nil -} - -type ReplicationControllerReaper struct { - client coreclient.ReplicationControllersGetter - pollInterval, timeout time.Duration -} -type ReplicaSetReaper struct { - client extensionsclient.ReplicaSetsGetter - pollInterval, timeout time.Duration -} -type DaemonSetReaper struct { - client extensionsclient.DaemonSetsGetter - pollInterval, timeout time.Duration -} -type JobReaper struct { - client batchclient.JobsGetter - podClient coreclient.PodsGetter - pollInterval, timeout time.Duration -} -type DeploymentReaper struct { - dClient extensionsclient.DeploymentsGetter - rsClient extensionsclient.ReplicaSetsGetter - pollInterval, timeout time.Duration -} -type PodReaper struct { - client coreclient.PodsGetter -} -type StatefulSetReaper struct { - client appsclient.StatefulSetsGetter - podClient coreclient.PodsGetter - pollInterval, timeout time.Duration -} - -// getOverlappingControllers finds rcs that this controller overlaps, as well as rcs overlapping this controller. -func getOverlappingControllers(rcClient coreclient.ReplicationControllerInterface, rc *api.ReplicationController) ([]api.ReplicationController, error) { - rcs, err := rcClient.List(metav1.ListOptions{}) - if err != nil { - return nil, fmt.Errorf("error getting replication controllers: %v", err) - } - var matchingRCs []api.ReplicationController - rcLabels := labels.Set(rc.Spec.Selector) - for _, controller := range rcs.Items { - newRCLabels := labels.Set(controller.Spec.Selector) - if labels.SelectorFromSet(newRCLabels).Matches(rcLabels) || labels.SelectorFromSet(rcLabels).Matches(newRCLabels) { - matchingRCs = append(matchingRCs, controller) - } - } - return matchingRCs, nil -} - -func (reaper *ReplicationControllerReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error { - rc := reaper.client.ReplicationControllers(namespace) - scaler := &ReplicationControllerScaler{reaper.client} - ctrl, err := rc.Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - if timeout == 0 { - timeout = Timeout + time.Duration(10*ctrl.Spec.Replicas)*time.Second - } - - // The rc manager will try and detect all matching rcs for a pod's labels, - // and only sync the oldest one. This means if we have a pod with labels - // [(k1: v1), (k2: v2)] and two rcs: rc1 with selector [(k1=v1)], and rc2 with selector [(k1=v1),(k2=v2)], - // the rc manager will sync the older of the two rcs. - // - // If there are rcs with a superset of labels, eg: - // deleting: (k1=v1), superset: (k2=v2, k1=v1) - // - It isn't safe to delete the rc because there could be a pod with labels - // (k1=v1) that isn't managed by the superset rc. We can't scale it down - // either, because there could be a pod (k2=v2, k1=v1) that it deletes - // causing a fight with the superset rc. - // If there are rcs with a subset of labels, eg: - // deleting: (k2=v2, k1=v1), subset: (k1=v1), superset: (k2=v2, k1=v1, k3=v3) - // - Even if it's safe to delete this rc without a scale down because all it's pods - // are being controlled by the subset rc the code returns an error. - - // In theory, creating overlapping controllers is user error, so the loop below - // tries to account for this logic only in the common case, where we end up - // with multiple rcs that have an exact match on selectors. - - overlappingCtrls, err := getOverlappingControllers(rc, ctrl) - if err != nil { - return fmt.Errorf("error getting replication controllers: %v", err) - } - exactMatchRCs := []api.ReplicationController{} - overlapRCs := []string{} - for _, overlappingRC := range overlappingCtrls { - if len(overlappingRC.Spec.Selector) == len(ctrl.Spec.Selector) { - exactMatchRCs = append(exactMatchRCs, overlappingRC) - } else { - overlapRCs = append(overlapRCs, overlappingRC.Name) - } - } - if len(overlapRCs) > 0 { - return fmt.Errorf( - "Detected overlapping controllers for rc %v: %v, please manage deletion individually with --cascade=false.", - ctrl.Name, strings.Join(overlapRCs, ",")) - } - if len(exactMatchRCs) == 1 { - // No overlapping controllers. - retry := NewRetryParams(reaper.pollInterval, reaper.timeout) - waitForReplicas := NewRetryParams(reaper.pollInterval, timeout) - if err = scaler.Scale(namespace, name, 0, nil, retry, waitForReplicas); err != nil { - return err - } - } - falseVar := false - deleteOptions := &metav1.DeleteOptions{OrphanDependents: &falseVar} - return rc.Delete(name, deleteOptions) -} - -// TODO(madhusudancs): Implement it when controllerRef is implemented - https://github.com/kubernetes/kubernetes/issues/2210 -// getOverlappingReplicaSets finds ReplicaSets that this ReplicaSet overlaps, as well as ReplicaSets overlapping this ReplicaSet. -func getOverlappingReplicaSets(c extensionsclient.ReplicaSetInterface, rs *extensions.ReplicaSet) ([]extensions.ReplicaSet, []extensions.ReplicaSet, error) { - var overlappingRSs, exactMatchRSs []extensions.ReplicaSet - return overlappingRSs, exactMatchRSs, nil -} - -func (reaper *ReplicaSetReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error { - rsc := reaper.client.ReplicaSets(namespace) - scaler := &ReplicaSetScaler{reaper.client} - rs, err := rsc.Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - if timeout == 0 { - timeout = Timeout + time.Duration(10*rs.Spec.Replicas)*time.Second - } - - // The ReplicaSet controller will try and detect all matching ReplicaSets - // for a pod's labels, and only sync the oldest one. This means if we have - // a pod with labels [(k1: v1), (k2: v2)] and two ReplicaSets: rs1 with - // selector [(k1=v1)], and rs2 with selector [(k1=v1),(k2=v2)], the - // ReplicaSet controller will sync the older of the two ReplicaSets. - // - // If there are ReplicaSets with a superset of labels, eg: - // deleting: (k1=v1), superset: (k2=v2, k1=v1) - // - It isn't safe to delete the ReplicaSet because there could be a pod - // with labels (k1=v1) that isn't managed by the superset ReplicaSet. - // We can't scale it down either, because there could be a pod - // (k2=v2, k1=v1) that it deletes causing a fight with the superset - // ReplicaSet. - // If there are ReplicaSets with a subset of labels, eg: - // deleting: (k2=v2, k1=v1), subset: (k1=v1), superset: (k2=v2, k1=v1, k3=v3) - // - Even if it's safe to delete this ReplicaSet without a scale down because - // all it's pods are being controlled by the subset ReplicaSet the code - // returns an error. - - // In theory, creating overlapping ReplicaSets is user error, so the loop below - // tries to account for this logic only in the common case, where we end up - // with multiple ReplicaSets that have an exact match on selectors. - - // TODO(madhusudancs): Re-evaluate again when controllerRef is implemented - - // https://github.com/kubernetes/kubernetes/issues/2210 - overlappingRSs, exactMatchRSs, err := getOverlappingReplicaSets(rsc, rs) - if err != nil { - return fmt.Errorf("error getting ReplicaSets: %v", err) - } - - if len(overlappingRSs) > 0 { - var names []string - for _, overlappingRS := range overlappingRSs { - names = append(names, overlappingRS.Name) - } - return fmt.Errorf( - "Detected overlapping ReplicaSets for ReplicaSet %v: %v, please manage deletion individually with --cascade=false.", - rs.Name, strings.Join(names, ",")) - } - if len(exactMatchRSs) == 0 { - // No overlapping ReplicaSets. - retry := NewRetryParams(reaper.pollInterval, reaper.timeout) - waitForReplicas := NewRetryParams(reaper.pollInterval, timeout) - if err = scaler.Scale(namespace, name, 0, nil, retry, waitForReplicas); err != nil { - return err - } - } - - falseVar := false - deleteOptions := &metav1.DeleteOptions{OrphanDependents: &falseVar} - return rsc.Delete(name, deleteOptions) -} - -func (reaper *DaemonSetReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error { - ds, err := reaper.client.DaemonSets(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - - // We set the nodeSelector to a random label. This label is nearly guaranteed - // to not be set on any node so the DameonSetController will start deleting - // daemon pods. Once it's done deleting the daemon pods, it's safe to delete - // the DaemonSet. - ds.Spec.Template.Spec.NodeSelector = map[string]string{ - string(uuid.NewUUID()): string(uuid.NewUUID()), - } - // force update to avoid version conflict - ds.ResourceVersion = "" - - if ds, err = reaper.client.DaemonSets(namespace).Update(ds); err != nil { - return err - } - - // Wait for the daemon set controller to kill all the daemon pods. - if err := wait.Poll(reaper.pollInterval, reaper.timeout, func() (bool, error) { - updatedDS, err := reaper.client.DaemonSets(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return false, nil - } - - return updatedDS.Status.CurrentNumberScheduled+updatedDS.Status.NumberMisscheduled == 0, nil - }); err != nil { - return err - } - - falseVar := false - deleteOptions := &metav1.DeleteOptions{OrphanDependents: &falseVar} - return reaper.client.DaemonSets(namespace).Delete(name, deleteOptions) -} - -func (reaper *StatefulSetReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error { - statefulsets := reaper.client.StatefulSets(namespace) - scaler := &StatefulSetScaler{reaper.client} - ss, err := statefulsets.Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - - if timeout == 0 { - numReplicas := ss.Spec.Replicas - // See discussion of this behavior here: - // https://github.com/kubernetes/kubernetes/pull/46468#discussion_r118589512 - timeout = Timeout + time.Duration(10*numReplicas)*time.Second - } - - retry := NewRetryParams(reaper.pollInterval, reaper.timeout) - waitForStatefulSet := NewRetryParams(reaper.pollInterval, timeout) - if err = scaler.Scale(namespace, name, 0, nil, retry, waitForStatefulSet); err != nil { - return err - } - - // TODO: Cleanup volumes? We don't want to accidentally delete volumes from - // stop, so just leave this up to the statefulset. - falseVar := false - deleteOptions := &metav1.DeleteOptions{OrphanDependents: &falseVar} - return statefulsets.Delete(name, deleteOptions) -} - -func (reaper *JobReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error { - jobs := reaper.client.Jobs(namespace) - pods := reaper.podClient.Pods(namespace) - scaler := ScalerFor(schema.GroupKind{Group: batch.GroupName, Kind: "Job"}, reaper.client, nil, schema.GroupResource{}) - job, err := jobs.Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - if timeout == 0 { - // we will never have more active pods than job.Spec.Parallelism - parallelism := *job.Spec.Parallelism - timeout = Timeout + time.Duration(10*parallelism)*time.Second - } - - // TODO: handle overlapping jobs - retry := NewRetryParams(reaper.pollInterval, reaper.timeout) - waitForJobs := NewRetryParams(reaper.pollInterval, timeout) - if err = scaler.Scale(namespace, name, 0, nil, retry, waitForJobs); err != nil { - return err - } - // at this point only dead pods are left, that should be removed - selector, _ := metav1.LabelSelectorAsSelector(job.Spec.Selector) - options := metav1.ListOptions{LabelSelector: selector.String()} - podList, err := pods.List(options) - if err != nil { - return err - } - errList := []error{} - for _, pod := range podList.Items { - if err := pods.Delete(pod.Name, gracePeriod); err != nil { - // ignores the error when the pod isn't found - if !errors.IsNotFound(err) { - errList = append(errList, err) - } - } - } - if len(errList) > 0 { - return utilerrors.NewAggregate(errList) - } - // once we have all the pods removed we can safely remove the job itself. - falseVar := false - deleteOptions := &metav1.DeleteOptions{OrphanDependents: &falseVar} - return jobs.Delete(name, deleteOptions) -} - -func (reaper *DeploymentReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error { - deployments := reaper.dClient.Deployments(namespace) - rsReaper := &ReplicaSetReaper{reaper.rsClient, reaper.pollInterval, reaper.timeout} - - deployment, err := reaper.updateDeploymentWithRetries(namespace, name, func(d *extensions.Deployment) { - // set deployment's history and scale to 0 - // TODO replace with patch when available: https://github.com/kubernetes/kubernetes/issues/20527 - rhl := int32(0) - d.Spec.RevisionHistoryLimit = &rhl - d.Spec.Replicas = 0 - d.Spec.Paused = true - }) - if err != nil { - return err - } - if deployment.Initializers != nil { - var falseVar = false - nonOrphanOption := metav1.DeleteOptions{OrphanDependents: &falseVar} - return deployments.Delete(name, &nonOrphanOption) - } - - // Use observedGeneration to determine if the deployment controller noticed the pause. - if err := deploymentutil.WaitForObservedDeploymentInternal(func() (*extensions.Deployment, error) { - return deployments.Get(name, metav1.GetOptions{}) - }, deployment.Generation, 1*time.Second, 1*time.Minute); err != nil { - return err - } - - // Stop all replica sets belonging to this Deployment. - rss, err := deploymentutil.ListReplicaSetsInternal(deployment, - func(namespace string, options metav1.ListOptions) ([]*extensions.ReplicaSet, error) { - rsList, err := reaper.rsClient.ReplicaSets(namespace).List(options) - if err != nil { - return nil, err - } - rss := make([]*extensions.ReplicaSet, 0, len(rsList.Items)) - for i := range rsList.Items { - rss = append(rss, &rsList.Items[i]) - } - return rss, nil - }) - if err != nil { - return err - } - - errList := []error{} - for _, rs := range rss { - if err := rsReaper.Stop(rs.Namespace, rs.Name, timeout, gracePeriod); err != nil { - scaleGetErr, ok := err.(ScaleError) - if errors.IsNotFound(err) || (ok && errors.IsNotFound(scaleGetErr.ActualError)) { - continue - } - errList = append(errList, err) - } - } - if len(errList) > 0 { - return utilerrors.NewAggregate(errList) - } - - // Delete deployment at the end. - // Note: We delete deployment at the end so that if removing RSs fails, we at least have the deployment to retry. - var falseVar = false - nonOrphanOption := metav1.DeleteOptions{OrphanDependents: &falseVar} - return deployments.Delete(name, &nonOrphanOption) -} - -type updateDeploymentFunc func(d *extensions.Deployment) - -func (reaper *DeploymentReaper) updateDeploymentWithRetries(namespace, name string, applyUpdate updateDeploymentFunc) (deployment *extensions.Deployment, err error) { - deployments := reaper.dClient.Deployments(namespace) - err = wait.Poll(10*time.Millisecond, 1*time.Minute, func() (bool, error) { - if deployment, err = deployments.Get(name, metav1.GetOptions{}); err != nil { - return false, err - } - // Apply the update, then attempt to push it to the apiserver. - applyUpdate(deployment) - if deployment, err = deployments.Update(deployment); err == nil { - return true, nil - } - // Retry only on update conflict. - if errors.IsConflict(err) { - return false, nil - } - return false, err - }) - return deployment, err -} - -func (reaper *PodReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error { - pods := reaper.client.Pods(namespace) - _, err := pods.Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - return pods.Delete(name, gracePeriod) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/delete_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/delete_test.go deleted file mode 100644 index 38fb1e041..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/delete_test.go +++ /dev/null @@ -1,704 +0,0 @@ -/* -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 kubectl - -import ( - "fmt" - "reflect" - "strings" - "testing" - "time" - - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/apimachinery/pkg/watch" - testcore "k8s.io/client-go/testing" - "k8s.io/kubernetes/pkg/apis/batch" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" -) - -func TestReplicationControllerStop(t *testing.T) { - name := "foo" - ns := "default" - tests := []struct { - Name string - Objs []runtime.Object - StopError error - ExpectedActions []string - }{ - { - Name: "OnlyOneRC", - Objs: []runtime.Object{ - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get", "list", "get", "update", "get", "get", "delete"}, - }, - { - Name: "NoOverlapping", - Objs: []runtime.Object{ - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "baz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k3": "v3"}}, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get", "list", "get", "update", "get", "get", "delete"}, - }, - { - Name: "OverlappingError", - Objs: []runtime.Object{ - - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "baz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1", "k2": "v2"}}, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - StopError: fmt.Errorf("Detected overlapping controllers for rc foo: baz, please manage deletion individually with --cascade=false."), - ExpectedActions: []string{"get", "list"}, - }, - - { - Name: "OverlappingButSafeDelete", - Objs: []runtime.Object{ - - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "baz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1", "k2": "v2", "k3": "v3"}}, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "zaz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1", "k2": "v2"}}, - }, - }, - }, - }, - - StopError: fmt.Errorf("Detected overlapping controllers for rc foo: baz,zaz, please manage deletion individually with --cascade=false."), - ExpectedActions: []string{"get", "list"}, - }, - - { - Name: "TwoExactMatchRCs", - Objs: []runtime.Object{ - - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "zaz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - - StopError: nil, - ExpectedActions: []string{"get", "list", "delete"}, - }, - } - - for _, test := range tests { - copiedForWatch := test.Objs[0].DeepCopyObject() - fake := fake.NewSimpleClientset(test.Objs...) - fakeWatch := watch.NewFake() - fake.PrependWatchReactor("replicationcontrollers", testcore.DefaultWatchReactor(fakeWatch, nil)) - - go func() { - fakeWatch.Add(copiedForWatch) - }() - - reaper := ReplicationControllerReaper{fake.Core(), time.Millisecond, time.Millisecond} - err := reaper.Stop(ns, name, 0, nil) - if !reflect.DeepEqual(err, test.StopError) { - t.Errorf("%s unexpected error: %v", test.Name, err) - continue - } - - actions := fake.Actions() - if len(actions) != len(test.ExpectedActions) { - t.Errorf("%s unexpected actions: %v, expected %d actions got %d", test.Name, actions, len(test.ExpectedActions), len(actions)) - continue - } - for i, verb := range test.ExpectedActions { - if actions[i].GetResource().GroupResource() != api.Resource("replicationcontrollers") { - t.Errorf("%s unexpected action: %+v, expected %s-replicationController", test.Name, actions[i], verb) - } - if actions[i].GetVerb() != verb { - t.Errorf("%s unexpected action: %+v, expected %s-replicationController", test.Name, actions[i], verb) - } - } - } -} - -func TestReplicaSetStop(t *testing.T) { - name := "foo" - ns := "default" - tests := []struct { - Name string - Objs []runtime.Object - StopError error - ExpectedActions []string - }{ - { - Name: "OnlyOneRS", - Objs: []runtime.Object{ - &extensions.ReplicaSetList{ // LIST - Items: []extensions.ReplicaSet{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get", "get", "update", "get", "get", "delete"}, - }, - { - Name: "NoOverlapping", - Objs: []runtime.Object{ - &extensions.ReplicaSetList{ // LIST - Items: []extensions.ReplicaSet{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "baz", - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"k3": "v3"}}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get", "get", "update", "get", "get", "delete"}, - }, - // TODO: Implement tests for overlapping replica sets, similar to replication controllers, - // when the overlapping checks are implemented for replica sets. - } - - for _, test := range tests { - fake := fake.NewSimpleClientset(test.Objs...) - reaper := ReplicaSetReaper{fake.Extensions(), time.Millisecond, time.Millisecond} - err := reaper.Stop(ns, name, 0, nil) - if !reflect.DeepEqual(err, test.StopError) { - t.Errorf("%s unexpected error: %v", test.Name, err) - continue - } - - actions := fake.Actions() - if len(actions) != len(test.ExpectedActions) { - t.Errorf("%s unexpected actions: %v, expected %d actions got %d", test.Name, actions, len(test.ExpectedActions), len(actions)) - continue - } - for i, verb := range test.ExpectedActions { - if actions[i].GetResource().GroupResource() != extensions.Resource("replicasets") { - t.Errorf("%s unexpected action: %+v, expected %s-replicaSet", test.Name, actions[i], verb) - } - if actions[i].GetVerb() != verb { - t.Errorf("%s unexpected action: %+v, expected %s-replicaSet", test.Name, actions[i], verb) - } - } - } -} - -func TestJobStop(t *testing.T) { - name := "foo" - ns := "default" - zero := int32(0) - tests := []struct { - Name string - Objs []runtime.Object - StopError error - ExpectedActions []string - }{ - { - Name: "OnlyOneJob", - Objs: []runtime.Object{ - &batch.JobList{ // LIST - Items: []batch.Job{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: batch.JobSpec{ - Parallelism: &zero, - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"k1": "v1"}, - }, - }, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get:jobs", "get:jobs", "update:jobs", - "get:jobs", "get:jobs", "list:pods", "delete:jobs"}, - }, - { - Name: "JobWithDeadPods", - Objs: []runtime.Object{ - &batch.JobList{ // LIST - Items: []batch.Job{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: batch.JobSpec{ - Parallelism: &zero, - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"k1": "v1"}, - }, - }, - }, - }, - }, - &api.PodList{ // LIST - Items: []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pod1", - Namespace: ns, - Labels: map[string]string{"k1": "v1"}, - }, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get:jobs", "get:jobs", "update:jobs", - "get:jobs", "get:jobs", "list:pods", "delete:pods", "delete:jobs"}, - }, - } - - for _, test := range tests { - fake := fake.NewSimpleClientset(test.Objs...) - reaper := JobReaper{fake.Batch(), fake.Core(), time.Millisecond, time.Millisecond} - err := reaper.Stop(ns, name, 0, nil) - if !reflect.DeepEqual(err, test.StopError) { - t.Errorf("%s unexpected error: %v", test.Name, err) - continue - } - - actions := fake.Actions() - if len(actions) != len(test.ExpectedActions) { - t.Errorf("%s unexpected actions: %v, expected %d actions got %d", test.Name, actions, len(test.ExpectedActions), len(actions)) - continue - } - for i, expAction := range test.ExpectedActions { - action := strings.Split(expAction, ":") - if actions[i].GetVerb() != action[0] { - t.Errorf("%s unexpected verb: %+v, expected %s", test.Name, actions[i], expAction) - } - if actions[i].GetResource().Resource != action[1] { - t.Errorf("%s unexpected resource: %+v, expected %s", test.Name, actions[i], expAction) - } - } - } -} - -func TestDeploymentStop(t *testing.T) { - name := "foo" - ns := "default" - deployment := extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - UID: uuid.NewUUID(), - Namespace: ns, - }, - Spec: extensions.DeploymentSpec{ - Replicas: 0, - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - Status: extensions.DeploymentStatus{ - Replicas: 0, - }, - } - trueVar := true - tests := []struct { - Name string - Objs []runtime.Object - StopError error - ExpectedActions []string - }{ - { - Name: "SimpleDeployment", - Objs: []runtime.Object{ - &extensions.Deployment{ // GET - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.DeploymentSpec{ - Replicas: 0, - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - Status: extensions.DeploymentStatus{ - Replicas: 0, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get:deployments", "update:deployments", - "get:deployments", "list:replicasets", "delete:deployments"}, - }, - { - Name: "Deployment with single replicaset", - Objs: []runtime.Object{ - &deployment, // GET - &extensions.ReplicaSetList{ // LIST - Items: []extensions.ReplicaSet{ - // ReplicaSet owned by this Deployment. - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - Labels: map[string]string{"k1": "v1"}, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: extensions.SchemeGroupVersion.String(), - Kind: "Deployment", - Name: deployment.Name, - UID: deployment.UID, - Controller: &trueVar, - }, - }, - }, - Spec: extensions.ReplicaSetSpec{}, - }, - // ReplicaSet owned by something else (should be ignored). - { - ObjectMeta: metav1.ObjectMeta{ - Name: "rs2", - Namespace: ns, - Labels: map[string]string{"k1": "v1"}, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: extensions.SchemeGroupVersion.String(), - Kind: "Deployment", - Name: "somethingelse", - UID: uuid.NewUUID(), - Controller: &trueVar, - }, - }, - }, - Spec: extensions.ReplicaSetSpec{}, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get:deployments", "update:deployments", - "get:deployments", "list:replicasets", "get:replicasets", - "get:replicasets", "update:replicasets", "get:replicasets", - "get:replicasets", "delete:replicasets", "delete:deployments"}, - }, - } - - for _, test := range tests { - fake := fake.NewSimpleClientset(test.Objs...) - reaper := DeploymentReaper{fake.Extensions(), fake.Extensions(), time.Millisecond, time.Millisecond} - err := reaper.Stop(ns, name, 0, nil) - if !reflect.DeepEqual(err, test.StopError) { - t.Errorf("%s unexpected error: %v", test.Name, err) - continue - } - - actions := fake.Actions() - if len(actions) != len(test.ExpectedActions) { - t.Errorf("%s unexpected actions: %v, expected %d actions got %d", test.Name, actions, len(test.ExpectedActions), len(actions)) - continue - } - for i, expAction := range test.ExpectedActions { - action := strings.Split(expAction, ":") - if actions[i].GetVerb() != action[0] { - t.Errorf("%s unexpected verb: %+v, expected %s", test.Name, actions[i], expAction) - } - if actions[i].GetResource().Resource != action[1] { - t.Errorf("%s unexpected resource: %+v, expected %s", test.Name, actions[i], expAction) - } - if len(action) == 3 && actions[i].GetSubresource() != action[2] { - t.Errorf("%s unexpected subresource: %+v, expected %s", test.Name, actions[i], expAction) - } - } - } -} - -type noSuchPod struct { - coreclient.PodInterface -} - -func (c *noSuchPod) Get(name string, options metav1.GetOptions) (*api.Pod, error) { - return nil, fmt.Errorf("%s does not exist", name) -} - -type noDeletePod struct { - coreclient.PodInterface -} - -func (c *noDeletePod) Delete(name string, o *metav1.DeleteOptions) error { - return fmt.Errorf("I'm afraid I can't do that, Dave") -} - -type reaperFake struct { - *fake.Clientset - noSuchPod, noDeletePod bool -} - -func (c *reaperFake) Core() coreclient.CoreInterface { - return &reaperCoreFake{c.Clientset.Core(), c.noSuchPod, c.noDeletePod} -} - -type reaperCoreFake struct { - coreclient.CoreInterface - noSuchPod, noDeletePod bool -} - -func (c *reaperCoreFake) Pods(namespace string) coreclient.PodInterface { - pods := c.CoreInterface.Pods(namespace) - if c.noSuchPod { - return &noSuchPod{pods} - } - if c.noDeletePod { - return &noDeletePod{pods} - } - return pods -} - -func newPod() *api.Pod { - return &api.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"}} -} - -func TestSimpleStop(t *testing.T) { - tests := []struct { - fake *reaperFake - kind schema.GroupKind - actions []testcore.Action - expectError bool - test string - }{ - { - fake: &reaperFake{ - Clientset: fake.NewSimpleClientset(newPod()), - }, - kind: api.Kind("Pod"), - actions: []testcore.Action{ - testcore.NewGetAction(api.Resource("pods").WithVersion(""), metav1.NamespaceDefault, "foo"), - testcore.NewDeleteAction(api.Resource("pods").WithVersion(""), metav1.NamespaceDefault, "foo"), - }, - expectError: false, - test: "stop pod succeeds", - }, - { - fake: &reaperFake{ - Clientset: fake.NewSimpleClientset(), - noSuchPod: true, - }, - kind: api.Kind("Pod"), - actions: []testcore.Action{}, - expectError: true, - test: "stop pod fails, no pod", - }, - { - fake: &reaperFake{ - Clientset: fake.NewSimpleClientset(newPod()), - noDeletePod: true, - }, - kind: api.Kind("Pod"), - actions: []testcore.Action{ - testcore.NewGetAction(api.Resource("pods").WithVersion(""), metav1.NamespaceDefault, "foo"), - }, - expectError: true, - test: "stop pod fails, can't delete", - }, - } - for _, test := range tests { - fake := test.fake - reaper, err := ReaperFor(test.kind, fake) - if err != nil { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - err = reaper.Stop("default", "foo", 0, nil) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - if err == nil { - if test.expectError { - t.Errorf("unexpected non-error: %v (%s)", err, test.test) - } - } - actions := fake.Actions() - if len(test.actions) != len(actions) { - t.Errorf("unexpected actions: %v; expected %v (%s)", actions, test.actions, test.test) - } - for i, action := range actions { - testAction := test.actions[i] - if action != testAction { - t.Errorf("unexpected action: %#v; expected %v (%s)", action, testAction, test.test) - } - } - } -} - -func TestDeploymentNotFoundError(t *testing.T) { - name := "foo" - ns := "default" - deployment := &extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.DeploymentSpec{ - Replicas: 0, - Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - Status: extensions.DeploymentStatus{ - Replicas: 0, - }, - } - - fake := fake.NewSimpleClientset( - deployment, - &extensions.ReplicaSetList{Items: []extensions.ReplicaSet{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{}, - }, - }, - }, - ) - fake.AddReactor("get", "replicasets", func(action testcore.Action) (handled bool, ret runtime.Object, err error) { - return true, nil, ScaleError{ActualError: errors.NewNotFound(api.Resource("replicaset"), "doesn't-matter")} - }) - - reaper := DeploymentReaper{fake.Extensions(), fake.Extensions(), time.Millisecond, time.Millisecond} - if err := reaper.Stop(ns, name, 0, nil); err != nil { - t.Fatalf("unexpected error: %#v", err) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/deployment.go b/vendor/k8s.io/kubernetes/pkg/kubectl/deployment.go index 76a4f1f44..9686d200d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/deployment.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/deployment.go @@ -20,6 +20,7 @@ import ( "fmt" "strings" + appsv1 "k8s.io/api/apps/v1" appsv1beta1 "k8s.io/api/apps/v1beta1" "k8s.io/api/core/v1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" @@ -28,7 +29,7 @@ import ( ) // BaseDeploymentGenerator: implement the common functionality of -// DeploymentBasicGeneratorV1 and DeploymentBasicAppsGeneratorV1. To reduce +// DeploymentBasicGeneratorV1, DeploymentBasicAppsGeneratorV1Beta1 and DeploymentBasicAppsGeneratorV1. To reduce // confusion, it's best to keep this struct in the same file as those // generators. type BaseDeploymentGenerator struct { @@ -78,7 +79,8 @@ func buildPodSpec(images []string) v1.PodSpec { // Remove any tag or hash if strings.Contains(name, ":") { name = strings.Split(name, ":")[0] - } else if strings.Contains(name, "@") { + } + if strings.Contains(name, "@") { name = strings.Split(name, "@")[0] } podSpec.Containers = append(podSpec.Containers, v1.Container{Name: name, Image: imageString}) @@ -116,7 +118,37 @@ func (s *DeploymentBasicGeneratorV1) StructuredGenerate() (runtime.Object, error }, err } -// DeploymentBasicAppsGeneratorV1 supports stable generation of a deployment under apps/v1beta1 endpoint +// DeploymentBasicAppsGeneratorV1Beta1 supports stable generation of a deployment under apps/v1beta1 endpoint +type DeploymentBasicAppsGeneratorV1Beta1 struct { + BaseDeploymentGenerator +} + +// Ensure it supports the generator pattern that uses parameters specified during construction +var _ StructuredGenerator = &DeploymentBasicAppsGeneratorV1Beta1{} + +// StructuredGenerate outputs a deployment object using the configured fields +func (s *DeploymentBasicAppsGeneratorV1Beta1) StructuredGenerate() (runtime.Object, error) { + podSpec, labels, selector, err := s.structuredGenerate() + one := int32(1) + return &appsv1beta1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: s.Name, + Labels: labels, + }, + Spec: appsv1beta1.DeploymentSpec{ + Replicas: &one, + Selector: &selector, + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: labels, + }, + Spec: podSpec, + }, + }, + }, err +} + +// DeploymentBasicAppsGeneratorV1 supports stable generation of a deployment under apps/v1 endpoint type DeploymentBasicAppsGeneratorV1 struct { BaseDeploymentGenerator } @@ -128,12 +160,12 @@ var _ StructuredGenerator = &DeploymentBasicAppsGeneratorV1{} func (s *DeploymentBasicAppsGeneratorV1) StructuredGenerate() (runtime.Object, error) { podSpec, labels, selector, err := s.structuredGenerate() one := int32(1) - return &appsv1beta1.Deployment{ + return &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: s.Name, Labels: labels, }, - Spec: appsv1beta1.DeploymentSpec{ + Spec: appsv1.DeploymentSpec{ Replicas: &one, Selector: &selector, Template: v1.PodTemplateSpec{ diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/deployment_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/deployment_test.go index 25569424b..5388e6cd8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/deployment_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/deployment_test.go @@ -20,8 +20,8 @@ import ( "reflect" "testing" + appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensionsv1beta1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -31,19 +31,19 @@ func TestDeploymentBasicGenerate(t *testing.T) { name string deploymentName string images []string - expected *extensionsv1beta1.Deployment + expected *appsv1.Deployment expectErr bool }{ { name: "deployment name and images ok", deploymentName: "images-name-ok", - images: []string{"nn/image1", "registry/nn/image2", "nn/image3:tag", "nn/image4@digest"}, - expected: &extensionsv1beta1.Deployment{ + images: []string{"nn/image1", "registry/nn/image2", "nn/image3:tag", "nn/image4@digest", "nn/image5@sha256:digest"}, + expected: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "images-name-ok", Labels: map[string]string{"app": "images-name-ok"}, }, - Spec: extensionsv1beta1.DeploymentSpec{ + Spec: appsv1.DeploymentSpec{ Replicas: &one, Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"app": "images-name-ok"}, @@ -58,6 +58,7 @@ func TestDeploymentBasicGenerate(t *testing.T) { {Name: "image2", Image: "registry/nn/image2"}, {Name: "image3", Image: "nn/image3:tag"}, {Name: "image4", Image: "nn/image4@digest"}, + {Name: "image5", Image: "nn/image5@sha256:digest"}, }, }, }, @@ -82,7 +83,7 @@ func TestDeploymentBasicGenerate(t *testing.T) { }, } for _, test := range tests { - generator := &DeploymentBasicGeneratorV1{ + generator := &DeploymentBasicAppsGeneratorV1{ BaseDeploymentGenerator{ Name: test.deploymentName, Images: test.images, @@ -95,8 +96,8 @@ func TestDeploymentBasicGenerate(t *testing.T) { if test.expectErr && err != nil { continue } - if !reflect.DeepEqual(obj.(*extensionsv1beta1.Deployment), test.expected) { - t.Errorf("test: %v\nexpected:\n%#v\nsaw:\n%#v", test.name, test.expected, obj.(*extensionsv1beta1.Deployment)) + if !reflect.DeepEqual(obj.(*appsv1.Deployment), test.expected) { + t.Errorf("test: %v\nexpected:\n%#v\nsaw:\n%#v", test.name, test.expected, obj.(*appsv1.Deployment)) } } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/explain/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/explain/BUILD index fa8aed924..5cbccb40b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/explain/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/explain/BUILD @@ -51,6 +51,7 @@ go_test( deps = [ "//pkg/kubectl/cmd/util/openapi/testing:go_default_library", "//pkg/kubectl/scheme:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/explain/explain_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/explain/explain_test.go index 46317bfd3..2c8c35888 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/explain/explain_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/explain/explain_test.go @@ -20,6 +20,7 @@ import ( "reflect" "testing" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -56,7 +57,7 @@ func TestSplitAndParseResourceRequest(t *testing.T) { }, } - mapper := scheme.Registry.RESTMapper(scheme.Versions...) + mapper := testrestmapper.TestOnlyStaticRESTMapper(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...) for _, test := range tests { gotInResource, gotFieldsPath, err := SplitAndParseResourceRequest(test.inresource, mapper) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/explain/formatter.go b/vendor/k8s.io/kubernetes/pkg/kubectl/explain/formatter.go index ab9c53e9e..04bdb0464 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/explain/formatter.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/explain/formatter.go @@ -48,7 +48,11 @@ func (f *Formatter) Write(str string, a ...interface{}) error { for i := 0; i < f.IndentLevel; i++ { indent = indent + " " } - _, err := io.WriteString(f.Writer, indent+fmt.Sprintf(str, a...)+"\n") + + if len(a) > 0 { + str = fmt.Sprintf(str, a...) + } + _, err := io.WriteString(f.Writer, indent+str+"\n") return err } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/BUILD new file mode 100644 index 000000000..538fad85a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/BUILD @@ -0,0 +1,72 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "builder_flags.go", + "builder_flags_fake.go", + "config_flags.go", + "config_flags_fake.go", + "doc.go", + "filename_flags.go", + "io_options.go", + "json_yaml_flags.go", + "jsonpath_flags.go", + "kube_template_flags.go", + "name_flags.go", + "print_flags.go", + "record_flags.go", + "template_flags.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubectl/genericclioptions", + visibility = ["//visibility:public"], + deps = [ + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/genericclioptions/resource:go_default_library", + "//vendor/github.com/evanphx/json-patch:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", + "//vendor/k8s.io/client-go/discovery:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", + "//vendor/k8s.io/client-go/util/homedir:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/kubectl/genericclioptions/printers:all-srcs", + "//pkg/kubectl/genericclioptions/resource:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = [ + "json_yaml_flags_test.go", + "jsonpath_flags_test.go", + "name_flags_test.go", + "template_flags_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/builder_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/builder_flags.go new file mode 100644 index 000000000..43ca43b3b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/builder_flags.go @@ -0,0 +1,233 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" +) + +// ResourceBuilderFlags are flags for finding resources +// TODO(juanvallejo): wire --local flag from commands through +type ResourceBuilderFlags struct { + FileNameFlags *FileNameFlags + + LabelSelector *string + FieldSelector *string + AllNamespaces *bool + All *bool + Local *bool + IncludeUninitialized *bool + + Scheme *runtime.Scheme + Latest bool + StopOnFirstError bool +} + +// NewResourceBuilderFlags returns a default ResourceBuilderFlags +func NewResourceBuilderFlags() *ResourceBuilderFlags { + filenames := []string{} + + return &ResourceBuilderFlags{ + FileNameFlags: &FileNameFlags{ + Usage: "identifying the resource.", + Filenames: &filenames, + Recursive: boolPtr(true), + }, + } +} + +func (o *ResourceBuilderFlags) WithFile(recurse bool, files ...string) *ResourceBuilderFlags { + o.FileNameFlags = &FileNameFlags{ + Usage: "identifying the resource.", + Filenames: &files, + Recursive: boolPtr(recurse), + } + + return o +} + +func (o *ResourceBuilderFlags) WithLabelSelector(selector string) *ResourceBuilderFlags { + o.LabelSelector = &selector + return o +} + +func (o *ResourceBuilderFlags) WithFieldSelector(selector string) *ResourceBuilderFlags { + o.FieldSelector = &selector + return o +} + +func (o *ResourceBuilderFlags) WithAllNamespaces(defaultVal bool) *ResourceBuilderFlags { + o.AllNamespaces = &defaultVal + return o +} + +func (o *ResourceBuilderFlags) WithAll(defaultVal bool) *ResourceBuilderFlags { + o.All = &defaultVal + return o +} + +func (o *ResourceBuilderFlags) WithLocal(defaultVal bool) *ResourceBuilderFlags { + o.Local = &defaultVal + return o +} + +// WithUninitialized is using an alpha feature and may be dropped +func (o *ResourceBuilderFlags) WithUninitialized(defaultVal bool) *ResourceBuilderFlags { + o.IncludeUninitialized = &defaultVal + return o +} + +func (o *ResourceBuilderFlags) WithScheme(scheme *runtime.Scheme) *ResourceBuilderFlags { + o.Scheme = scheme + return o +} + +func (o *ResourceBuilderFlags) WithLatest() *ResourceBuilderFlags { + o.Latest = true + return o +} + +func (o *ResourceBuilderFlags) StopOnError() *ResourceBuilderFlags { + o.StopOnFirstError = true + return o +} + +// AddFlags registers flags for finding resources +func (o *ResourceBuilderFlags) AddFlags(flagset *pflag.FlagSet) { + o.FileNameFlags.AddFlags(flagset) + + if o.LabelSelector != nil { + flagset.StringVarP(o.LabelSelector, "selector", "l", *o.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + } + if o.FieldSelector != nil { + flagset.StringVar(o.FieldSelector, "field-selector", *o.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") + } + if o.AllNamespaces != nil { + flagset.BoolVar(o.AllNamespaces, "all-namespaces", *o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + } + if o.All != nil { + flagset.BoolVar(o.All, "all", *o.All, "Select all resources in the namespace of the specified resource types") + } + if o.Local != nil { + flagset.BoolVar(o.Local, "local", *o.Local, "If true, annotation will NOT contact api-server but run locally.") + } + if o.IncludeUninitialized != nil { + flagset.BoolVar(o.IncludeUninitialized, "include-uninitialized", *o.IncludeUninitialized, `If true, the kubectl command applies to uninitialized objects. If explicitly set to false, this flag overrides other flags that make the kubectl commands apply to uninitialized objects, e.g., "--all". Objects with empty metadata.initializers are regarded as initialized.`) + } +} + +// ToBuilder gives you back a resource finder to visit resources that are located +func (o *ResourceBuilderFlags) ToBuilder(restClientGetter RESTClientGetter, resources []string) ResourceFinder { + namespace, enforceNamespace, namespaceErr := restClientGetter.ToRawKubeConfigLoader().Namespace() + + builder := resource.NewBuilder(restClientGetter). + NamespaceParam(namespace).DefaultNamespace() + + if o.Scheme != nil { + builder.WithScheme(o.Scheme, o.Scheme.PrioritizedVersionsAllGroups()...) + } else { + builder.Unstructured() + } + + if o.FileNameFlags != nil { + opts := o.FileNameFlags.ToOptions() + builder.FilenameParam(enforceNamespace, &opts) + } + + if o.Local == nil || !*o.Local { + // resource type/name tuples only work non-local + if o.All != nil { + builder.ResourceTypeOrNameArgs(*o.All, resources...) + } else { + builder.ResourceTypeOrNameArgs(false, resources...) + } + // label selectors only work non-local (for now) + if o.LabelSelector != nil { + builder.LabelSelectorParam(*o.LabelSelector) + } + // field selectors only work non-local (forever) + if o.FieldSelector != nil { + builder.FieldSelectorParam(*o.FieldSelector) + } + // latest only works non-local (forever) + if o.Latest { + builder.Latest() + } + + } else { + builder.Local() + + if len(resources) > 0 { + builder.AddError(resource.LocalResourceError) + } + } + + if o.IncludeUninitialized != nil { + builder.IncludeUninitialized(*o.IncludeUninitialized) + } + + if !o.StopOnFirstError { + builder.ContinueOnError() + } + + return &ResourceFindBuilderWrapper{ + builder: builder. + Flatten(). // I think we're going to recommend this everywhere + AddError(namespaceErr), + } +} + +// ResourceFindBuilderWrapper wraps a builder in an interface +type ResourceFindBuilderWrapper struct { + builder *resource.Builder +} + +// Do finds you resources to check +func (b *ResourceFindBuilderWrapper) Do() resource.Visitor { + return b.builder.Do() +} + +// ResourceFinder allows mocking the resource builder +// TODO resource builders needs to become more interfacey +type ResourceFinder interface { + Do() resource.Visitor +} + +// ResourceFinderFunc is a handy way to make a ResourceFinder +type ResourceFinderFunc func() resource.Visitor + +// Do implements ResourceFinder +func (fn ResourceFinderFunc) Do() resource.Visitor { + return fn() +} + +// ResourceFinderForResult skins a visitor for re-use as a ResourceFinder +func ResourceFinderForResult(result resource.Visitor) ResourceFinder { + return ResourceFinderFunc(func() resource.Visitor { + return result + }) +} + +func strPtr(val string) *string { + return &val +} + +func boolPtr(val bool) *bool { + return &val +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/builder_flags_fake.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/builder_flags_fake.go new file mode 100644 index 000000000..de968d8e5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/builder_flags_fake.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" +) + +// NewSimpleResourceFinder builds a super simple ResourceFinder that just iterates over the objects you provided +func NewSimpleFakeResourceFinder(infos ...*resource.Info) ResourceFinder { + return &fakeResourceFinder{ + Infos: infos, + } +} + +type fakeResourceFinder struct { + Infos []*resource.Info +} + +// Do implements the interface +func (f *fakeResourceFinder) Do() resource.Visitor { + return &fakeResourceResult{ + Infos: f.Infos, + } +} + +type fakeResourceResult struct { + Infos []*resource.Info +} + +// Visit just iterates over info +func (r *fakeResourceResult) Visit(fn resource.VisitorFunc) error { + for _, info := range r.Infos { + err := fn(info, nil) + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/config_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/config_flags.go new file mode 100644 index 000000000..e32e1eee7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/config_flags.go @@ -0,0 +1,326 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "github.com/spf13/pflag" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/util/homedir" +) + +const ( + flagClusterName = "cluster" + flagAuthInfoName = "user" + flagContext = "context" + flagNamespace = "namespace" + flagAPIServer = "server" + flagInsecure = "insecure-skip-tls-verify" + flagCertFile = "client-certificate" + flagKeyFile = "client-key" + flagCAFile = "certificate-authority" + flagBearerToken = "token" + flagImpersonate = "as" + flagImpersonateGroup = "as-group" + flagUsername = "username" + flagPassword = "password" + flagTimeout = "request-timeout" + flagHTTPCacheDir = "cache-dir" +) + +var defaultCacheDir = filepath.Join(homedir.HomeDir(), ".kube", "http-cache") + +// RESTClientGetter is an interface that the ConfigFlags describe to provide an easier way to mock for commands +// and eliminate the direct coupling to a struct type. Users may wish to duplicate this type in their own packages +// as per the golang type overlapping. +type RESTClientGetter interface { + // ToRESTConfig returns restconfig + ToRESTConfig() (*rest.Config, error) + // ToDiscoveryClient returns discovery client + ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) + // ToRESTMapper returns a restmapper + ToRESTMapper() (meta.RESTMapper, error) + // ToRawKubeConfigLoader return kubeconfig loader as-is + ToRawKubeConfigLoader() clientcmd.ClientConfig +} + +var _ RESTClientGetter = &ConfigFlags{} + +// ConfigFlags composes the set of values necessary +// for obtaining a REST client config +type ConfigFlags struct { + CacheDir *string + KubeConfig *string + + // config flags + ClusterName *string + AuthInfoName *string + Context *string + Namespace *string + APIServer *string + Insecure *bool + CertFile *string + KeyFile *string + CAFile *string + BearerToken *string + Impersonate *string + ImpersonateGroup *[]string + Username *string + Password *string + Timeout *string +} + +// ToRESTConfig implements RESTClientGetter. +// Returns a REST client configuration based on a provided path +// to a .kubeconfig file, loading rules, and config flag overrides. +// Expects the AddFlags method to have been called. +func (f *ConfigFlags) ToRESTConfig() (*rest.Config, error) { + return f.ToRawKubeConfigLoader().ClientConfig() +} + +// ToRawKubeConfigLoader binds config flag values to config overrides +// Returns an interactive clientConfig if the password flag is enabled, +// or a non-interactive clientConfig otherwise. +func (f *ConfigFlags) ToRawKubeConfigLoader() clientcmd.ClientConfig { + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + // use the standard defaults for this client command + // DEPRECATED: remove and replace with something more accurate + loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig + + if f.KubeConfig != nil { + loadingRules.ExplicitPath = *f.KubeConfig + } + + overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults} + + // bind auth info flag values to overrides + if f.CertFile != nil { + overrides.AuthInfo.ClientCertificate = *f.CertFile + } + if f.KeyFile != nil { + overrides.AuthInfo.ClientKey = *f.KeyFile + } + if f.BearerToken != nil { + overrides.AuthInfo.Token = *f.BearerToken + } + if f.Impersonate != nil { + overrides.AuthInfo.Impersonate = *f.Impersonate + } + if f.ImpersonateGroup != nil { + overrides.AuthInfo.ImpersonateGroups = *f.ImpersonateGroup + } + if f.Username != nil { + overrides.AuthInfo.Username = *f.Username + } + if f.Password != nil { + overrides.AuthInfo.Password = *f.Password + } + + // bind cluster flags + if f.APIServer != nil { + overrides.ClusterInfo.Server = *f.APIServer + } + if f.CAFile != nil { + overrides.ClusterInfo.CertificateAuthority = *f.CAFile + } + if f.Insecure != nil { + overrides.ClusterInfo.InsecureSkipTLSVerify = *f.Insecure + } + + // bind context flags + if f.Context != nil { + overrides.CurrentContext = *f.Context + } + if f.ClusterName != nil { + overrides.Context.Cluster = *f.ClusterName + } + if f.AuthInfoName != nil { + overrides.Context.AuthInfo = *f.AuthInfoName + } + if f.Namespace != nil { + overrides.Context.Namespace = *f.Namespace + } + + if f.Timeout != nil { + overrides.Timeout = *f.Timeout + } + + var clientConfig clientcmd.ClientConfig + + // we only have an interactive prompt when a password is allowed + if f.Password == nil { + clientConfig = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides) + } else { + clientConfig = clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin) + } + + return clientConfig +} + +// ToDiscoveryClient implements RESTClientGetter. +// Expects the AddFlags method to have been called. +// Returns a CachedDiscoveryInterface using a computed RESTConfig. +func (f *ConfigFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + config, err := f.ToRESTConfig() + if err != nil { + return nil, err + } + + // The more groups you have, the more discovery requests you need to make. + // given 25 groups (our groups + a few custom resources) with one-ish version each, discovery needs to make 50 requests + // double it just so we don't end up here again for a while. This config is only used for discovery. + config.Burst = 100 + + // retrieve a user-provided value for the "cache-dir" + // defaulting to ~/.kube/http-cache if no user-value is given. + httpCacheDir := defaultCacheDir + if f.CacheDir != nil { + httpCacheDir = *f.CacheDir + } + + discoveryCacheDir := computeDiscoverCacheDir(filepath.Join(homedir.HomeDir(), ".kube", "cache", "discovery"), config.Host) + return discovery.NewCachedDiscoveryClientForConfig(config, discoveryCacheDir, httpCacheDir, time.Duration(10*time.Minute)) +} + +// ToRESTMapper returns a mapper. +func (f *ConfigFlags) ToRESTMapper() (meta.RESTMapper, error) { + discoveryClient, err := f.ToDiscoveryClient() + if err != nil { + return nil, err + } + + mapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) + expander := restmapper.NewShortcutExpander(mapper, discoveryClient) + return expander, nil +} + +// AddFlags binds client configuration flags to a given flagset +func (f *ConfigFlags) AddFlags(flags *pflag.FlagSet) { + if f.KubeConfig != nil { + flags.StringVar(f.KubeConfig, "kubeconfig", *f.KubeConfig, "Path to the kubeconfig file to use for CLI requests.") + } + if f.CacheDir != nil { + flags.StringVar(f.CacheDir, flagHTTPCacheDir, *f.CacheDir, "Default HTTP cache directory") + } + + // add config options + if f.CertFile != nil { + flags.StringVar(f.CertFile, flagCertFile, *f.CertFile, "Path to a client certificate file for TLS") + } + if f.KeyFile != nil { + flags.StringVar(f.KeyFile, flagKeyFile, *f.KeyFile, "Path to a client key file for TLS") + } + if f.BearerToken != nil { + flags.StringVar(f.BearerToken, flagBearerToken, *f.BearerToken, "Bearer token for authentication to the API server") + } + if f.Impersonate != nil { + flags.StringVar(f.Impersonate, flagImpersonate, *f.Impersonate, "Username to impersonate for the operation") + } + if f.ImpersonateGroup != nil { + flags.StringArrayVar(f.ImpersonateGroup, flagImpersonateGroup, *f.ImpersonateGroup, "Group to impersonate for the operation, this flag can be repeated to specify multiple groups.") + } + if f.Username != nil { + flags.StringVar(f.Username, flagUsername, *f.Username, "Username for basic authentication to the API server") + } + if f.Password != nil { + flags.StringVar(f.Password, flagPassword, *f.Password, "Password for basic authentication to the API server") + } + if f.ClusterName != nil { + flags.StringVar(f.ClusterName, flagClusterName, *f.ClusterName, "The name of the kubeconfig cluster to use") + } + if f.AuthInfoName != nil { + flags.StringVar(f.AuthInfoName, flagAuthInfoName, *f.AuthInfoName, "The name of the kubeconfig user to use") + } + if f.Namespace != nil { + flags.StringVarP(f.Namespace, flagNamespace, "n", *f.Namespace, "If present, the namespace scope for this CLI request") + } + if f.Context != nil { + flags.StringVar(f.Context, flagContext, *f.Context, "The name of the kubeconfig context to use") + } + + if f.APIServer != nil { + flags.StringVarP(f.APIServer, flagAPIServer, "s", *f.APIServer, "The address and port of the Kubernetes API server") + } + if f.Insecure != nil { + flags.BoolVar(f.Insecure, flagInsecure, *f.Insecure, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure") + } + if f.CAFile != nil { + flags.StringVar(f.CAFile, flagCAFile, *f.CAFile, "Path to a cert file for the certificate authority") + } + if f.Timeout != nil { + flags.StringVar(f.Timeout, flagTimeout, *f.Timeout, "The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests.") + } + +} + +// WithDeprecatedPasswordFlag enables the username and password config flags +func (f *ConfigFlags) WithDeprecatedPasswordFlag() *ConfigFlags { + f.Username = stringptr("") + f.Password = stringptr("") + return f +} + +// NewConfigFlags returns ConfigFlags with default values set +func NewConfigFlags() *ConfigFlags { + impersonateGroup := []string{} + insecure := false + + return &ConfigFlags{ + Insecure: &insecure, + Timeout: stringptr("0"), + KubeConfig: stringptr(""), + + CacheDir: stringptr(defaultCacheDir), + ClusterName: stringptr(""), + AuthInfoName: stringptr(""), + Context: stringptr(""), + Namespace: stringptr(""), + APIServer: stringptr(""), + CertFile: stringptr(""), + KeyFile: stringptr(""), + CAFile: stringptr(""), + BearerToken: stringptr(""), + Impersonate: stringptr(""), + ImpersonateGroup: &impersonateGroup, + } +} + +func stringptr(val string) *string { + return &val +} + +// overlyCautiousIllegalFileCharacters matches characters that *might* not be supported. Windows is really restrictive, so this is really restrictive +var overlyCautiousIllegalFileCharacters = regexp.MustCompile(`[^(\w/\.)]`) + +// computeDiscoverCacheDir takes the parentDir and the host and comes up with a "usually non-colliding" name. +func computeDiscoverCacheDir(parentDir, host string) string { + // strip the optional scheme from host if its there: + schemelessHost := strings.Replace(strings.Replace(host, "https://", "", 1), "http://", "", 1) + // now do a simple collapse of non-AZ09 characters. Collisions are possible but unlikely. Even if we do collide the problem is short lived + safeHost := overlyCautiousIllegalFileCharacters.ReplaceAllString(schemelessHost, "_") + return filepath.Join(parentDir, safeHost) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/config_flags_fake.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/config_flags_fake.go new file mode 100644 index 000000000..64e9a6883 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/config_flags_fake.go @@ -0,0 +1,110 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +type TestConfigFlags struct { + clientConfig clientcmd.ClientConfig + discoveryClient discovery.CachedDiscoveryInterface + restMapper meta.RESTMapper +} + +func (f *TestConfigFlags) ToRawKubeConfigLoader() clientcmd.ClientConfig { + if f.clientConfig == nil { + panic("attempt to obtain a test RawKubeConfigLoader with no clientConfig specified") + } + return f.clientConfig +} + +func (f *TestConfigFlags) ToRESTConfig() (*rest.Config, error) { + return f.ToRawKubeConfigLoader().ClientConfig() +} + +func (f *TestConfigFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + return f.discoveryClient, nil +} + +func (f *TestConfigFlags) ToRESTMapper() (meta.RESTMapper, error) { + if f.restMapper != nil { + return f.restMapper, nil + } + if f.discoveryClient != nil { + mapper := restmapper.NewDeferredDiscoveryRESTMapper(f.discoveryClient) + expander := restmapper.NewShortcutExpander(mapper, f.discoveryClient) + return expander, nil + } + return nil, fmt.Errorf("no restmapper") +} + +func (f *TestConfigFlags) WithClientConfig(clientConfig clientcmd.ClientConfig) *TestConfigFlags { + f.clientConfig = clientConfig + return f +} + +func (f *TestConfigFlags) WithRESTMapper(mapper meta.RESTMapper) *TestConfigFlags { + f.restMapper = mapper + return f +} + +func (f *TestConfigFlags) WithDiscoveryClient(c discovery.CachedDiscoveryInterface) *TestConfigFlags { + f.discoveryClient = c + return f +} + +func (f *TestConfigFlags) WithNamespace(ns string) *TestConfigFlags { + if f.clientConfig == nil { + panic("attempt to obtain a test RawKubeConfigLoader with no clientConfig specified") + } + f.clientConfig = &namespacedClientConfig{ + delegate: f.clientConfig, + namespace: ns, + } + return f +} + +func NewTestConfigFlags() *TestConfigFlags { + return &TestConfigFlags{} +} + +type namespacedClientConfig struct { + delegate clientcmd.ClientConfig + namespace string +} + +func (c *namespacedClientConfig) Namespace() (string, bool, error) { + return c.namespace, false, nil +} + +func (c *namespacedClientConfig) RawConfig() (clientcmdapi.Config, error) { + return c.delegate.RawConfig() +} +func (c *namespacedClientConfig) ClientConfig() (*rest.Config, error) { + return c.delegate.ClientConfig() +} +func (c *namespacedClientConfig) ConfigAccess() clientcmd.ConfigAccess { + return c.delegate.ConfigAccess() +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/doc.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/doc.go new file mode 100644 index 000000000..2bf32d256 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2018 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 genericclioptions contains flags which can be added to you command, bound, completed, and produce +// useful helper functions. Nothing in this package can depend on kube/kube +package genericclioptions diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/filename_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/filename_flags.go new file mode 100644 index 000000000..9fc0b6070 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/filename_flags.go @@ -0,0 +1,71 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "strings" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" +) + +// Usage of this struct by itself is discouraged. +// These flags are composed by ResourceBuilderFlags +// which should be used instead. +type FileNameFlags struct { + Usage string + + Filenames *[]string + Recursive *bool +} + +func (o *FileNameFlags) ToOptions() resource.FilenameOptions { + options := resource.FilenameOptions{} + + if o == nil { + return options + } + + if o.Recursive != nil { + options.Recursive = *o.Recursive + } + if o.Filenames != nil { + options.Filenames = *o.Filenames + } + + return options +} + +func (o *FileNameFlags) AddFlags(flags *pflag.FlagSet) { + if o == nil { + return + } + + if o.Recursive != nil { + flags.BoolVarP(o.Recursive, "recursive", "R", *o.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") + } + if o.Filenames != nil { + flags.StringSliceVarP(o.Filenames, "filename", "f", *o.Filenames, o.Usage) + annotations := make([]string, 0, len(resource.FileExtensions)) + for _, ext := range resource.FileExtensions { + annotations = append(annotations, strings.TrimLeft(ext, ".")) + } + flags.SetAnnotation("filename", cobra.BashCompFilenameExt, annotations) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/io_options.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/io_options.go new file mode 100644 index 000000000..4fc3a77b0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/io_options.go @@ -0,0 +1,57 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "bytes" + "io" + "io/ioutil" +) + +// IOStreams provides the standard names for iostreams. This is useful for embedding and for unit testing. +// Inconsistent and different names make it hard to read and review code +type IOStreams struct { + // In think, os.Stdin + In io.Reader + // Out think, os.Stdout + Out io.Writer + // ErrOut think, os.Stderr + ErrOut io.Writer +} + +// NewTestIOStreams returns a valid IOStreams and in, out, errout buffers for unit tests +func NewTestIOStreams() (IOStreams, *bytes.Buffer, *bytes.Buffer, *bytes.Buffer) { + in := &bytes.Buffer{} + out := &bytes.Buffer{} + errOut := &bytes.Buffer{} + + return IOStreams{ + In: in, + Out: out, + ErrOut: errOut, + }, in, out, errOut +} + +// NewTestIOStreamsDiscard returns a valid IOStreams that just discards +func NewTestIOStreamsDiscard() IOStreams { + in := &bytes.Buffer{} + return IOStreams{ + In: in, + Out: ioutil.Discard, + ErrOut: ioutil.Discard, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/json_yaml_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/json_yaml_flags.go new file mode 100644 index 000000000..8205f5191 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/json_yaml_flags.go @@ -0,0 +1,65 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "strings" + + "github.com/spf13/cobra" + + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" +) + +func (f *JSONYamlPrintFlags) AllowedFormats() []string { + return []string{"json", "yaml"} +} + +// JSONYamlPrintFlags provides default flags necessary for json/yaml printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type JSONYamlPrintFlags struct { +} + +// ToPrinter receives an outputFormat and returns a printer capable of +// handling --output=(yaml|json) printing. +// Returns false if the specified outputFormat does not match a supported format. +// Supported Format types can be found in pkg/printers/printers.go +func (f *JSONYamlPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) { + var printer printers.ResourcePrinter + + outputFormat = strings.ToLower(outputFormat) + switch outputFormat { + case "json": + printer = &printers.JSONPrinter{} + case "yaml": + printer = &printers.YAMLPrinter{} + default: + return nil, NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} + } + + return printer, nil +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to JSON or Yaml printing to it +func (f *JSONYamlPrintFlags) AddFlags(c *cobra.Command) {} + +// NewJSONYamlPrintFlags returns flags associated with +// yaml or json printing, with default values set. +func NewJSONYamlPrintFlags() *JSONYamlPrintFlags { + return &JSONYamlPrintFlags{} +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/json_yaml_flags_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/json_yaml_flags_test.go new file mode 100644 index 000000000..7ab5b7f1d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/json_yaml_flags_test.go @@ -0,0 +1,91 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "bytes" + "strings" + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestPrinterSupportsExpectedJSONYamlFormats(t *testing.T) { + testObject := &v1.Pod{ + TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"}, + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + } + + testCases := []struct { + name string + outputFormat string + expectedOutput string + expectNoMatch bool + }{ + { + name: "json output format matches a json printer", + outputFormat: "json", + expectedOutput: "\"name\": \"foo\"", + }, + { + name: "yaml output format matches a yaml printer", + outputFormat: "yaml", + expectedOutput: "name: foo", + }, + { + name: "output format for another printer does not match a json/yaml printer", + outputFormat: "jsonpath", + expectNoMatch: true, + }, + { + name: "invalid output format results in no match", + outputFormat: "invalid", + expectNoMatch: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + printFlags := JSONYamlPrintFlags{} + + p, err := printFlags.ToPrinter(tc.outputFormat) + if tc.expectNoMatch { + if !IsNoCompatiblePrinterError(err) { + t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) + } + return + } + if IsNoCompatiblePrinterError(err) { + t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + out := bytes.NewBuffer([]byte{}) + err = p.PrintObj(testObject, out) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if !strings.Contains(out.String(), tc.expectedOutput) { + t.Errorf("unexpected output: expecting %q, got %q", tc.expectedOutput, out.String()) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/jsonpath_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/jsonpath_flags.go new file mode 100644 index 000000000..c495fcd8b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/jsonpath_flags.go @@ -0,0 +1,128 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "fmt" + "io/ioutil" + "strings" + + "github.com/spf13/cobra" + + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" +) + +// templates are logically optional for specifying a format. +// this allows a user to specify a template format value +// as --output=jsonpath= +var jsonFormats = map[string]bool{ + "jsonpath": true, + "jsonpath-file": true, +} + +// JSONPathPrintFlags provides default flags necessary for template printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type JSONPathPrintFlags struct { + // indicates if it is OK to ignore missing keys for rendering + // an output template. + AllowMissingKeys *bool + TemplateArgument *string +} + +func (f *JSONPathPrintFlags) AllowedFormats() []string { + formats := make([]string, 0, len(jsonFormats)) + for format := range jsonFormats { + formats = append(formats, format) + } + return formats +} + +// ToPrinter receives an templateFormat and returns a printer capable of +// handling --template format printing. +// Returns false if the specified templateFormat does not match a template format. +func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (printers.ResourcePrinter, error) { + if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 { + return nil, NoCompatiblePrinterError{Options: f, OutputFormat: &templateFormat} + } + + templateValue := "" + + if f.TemplateArgument == nil || len(*f.TemplateArgument) == 0 { + for format := range jsonFormats { + format = format + "=" + if strings.HasPrefix(templateFormat, format) { + templateValue = templateFormat[len(format):] + templateFormat = format[:len(format)-1] + break + } + } + } else { + templateValue = *f.TemplateArgument + } + + if _, supportedFormat := jsonFormats[templateFormat]; !supportedFormat { + return nil, NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()} + } + + if len(templateValue) == 0 { + return nil, fmt.Errorf("template format specified but no template given") + } + + if templateFormat == "jsonpath-file" { + data, err := ioutil.ReadFile(templateValue) + if err != nil { + return nil, fmt.Errorf("error reading --template %s, %v\n", templateValue, err) + } + + templateValue = string(data) + } + + p, err := printers.NewJSONPathPrinter(templateValue) + if err != nil { + return nil, fmt.Errorf("error parsing jsonpath %s, %v\n", templateValue, err) + } + + allowMissingKeys := true + if f.AllowMissingKeys != nil { + allowMissingKeys = *f.AllowMissingKeys + } + + p.AllowMissingKeys(allowMissingKeys) + return p, nil +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to template printing to it +func (f *JSONPathPrintFlags) AddFlags(c *cobra.Command) { + if f.TemplateArgument != nil { + c.Flags().StringVar(f.TemplateArgument, "template", *f.TemplateArgument, "Template string or path to template file to use when --output=jsonpath, --output=jsonpath-file.") + c.MarkFlagFilename("template") + } + if f.AllowMissingKeys != nil { + c.Flags().BoolVar(f.AllowMissingKeys, "allow-missing-template-keys", *f.AllowMissingKeys, "If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.") + } +} + +// NewJSONPathPrintFlags returns flags associated with +// --template printing, with default values set. +func NewJSONPathPrintFlags(templateValue string, allowMissingKeys bool) *JSONPathPrintFlags { + return &JSONPathPrintFlags{ + TemplateArgument: &templateValue, + AllowMissingKeys: &allowMissingKeys, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/jsonpath_flags_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/jsonpath_flags_test.go new file mode 100644 index 000000000..bf0c087bc --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/jsonpath_flags_test.go @@ -0,0 +1,211 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "strings" + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestPrinterSupportsExpectedJSONPathFormats(t *testing.T) { + testObject := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + + jsonpathFile, err := ioutil.TempFile("", "printers_jsonpath_flags") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + defer func(tempFile *os.File) { + tempFile.Close() + os.Remove(tempFile.Name()) + }(jsonpathFile) + + fmt.Fprintf(jsonpathFile, "{ .metadata.name }\n") + + testCases := []struct { + name string + outputFormat string + templateArg string + expectedError string + expectedParseError string + expectedOutput string + expectNoMatch bool + }{ + { + name: "valid output format also containing the jsonpath argument succeeds", + outputFormat: "jsonpath={ .metadata.name }", + expectedOutput: "foo", + }, + { + name: "valid output format and no --template argument results in an error", + outputFormat: "jsonpath", + expectedError: "template format specified but no template given", + }, + { + name: "valid output format and --template argument succeeds", + outputFormat: "jsonpath", + templateArg: "{ .metadata.name }", + expectedOutput: "foo", + }, + { + name: "jsonpath template file should match, and successfully return correct value", + outputFormat: "jsonpath-file", + templateArg: jsonpathFile.Name(), + expectedOutput: "foo", + }, + { + name: "valid output format and invalid --template argument results in a parsing from the printer", + outputFormat: "jsonpath", + templateArg: "{invalid}", + expectedParseError: "unrecognized identifier invalid", + }, + { + name: "no printer is matched on an invalid outputFormat", + outputFormat: "invalid", + expectNoMatch: true, + }, + { + name: "jsonpath printer should not match on any other format supported by another printer", + outputFormat: "go-template", + expectNoMatch: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + templateArg := &tc.templateArg + if len(tc.templateArg) == 0 { + templateArg = nil + } + + printFlags := JSONPathPrintFlags{ + TemplateArgument: templateArg, + } + + p, err := printFlags.ToPrinter(tc.outputFormat) + if tc.expectNoMatch { + if !IsNoCompatiblePrinterError(err) { + t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) + } + return + } + if IsNoCompatiblePrinterError(err) { + t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) + } + + if len(tc.expectedError) > 0 { + if err == nil || !strings.Contains(err.Error(), tc.expectedError) { + t.Errorf("expecting error %q, got %v", tc.expectedError, err) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + out := bytes.NewBuffer([]byte{}) + err = p.PrintObj(testObject, out) + if len(tc.expectedParseError) > 0 { + if err == nil || !strings.Contains(err.Error(), tc.expectedParseError) { + t.Errorf("expecting error %q, got %v", tc.expectedError, err) + } + return + } + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if !strings.Contains(out.String(), tc.expectedOutput) { + t.Errorf("unexpected output: expecting %q, got %q", tc.expectedOutput, out.String()) + } + }) + } +} + +func TestJSONPathPrinterDefaultsAllowMissingKeysToTrue(t *testing.T) { + testObject := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + + allowMissingKeys := false + + testCases := []struct { + name string + templateArg string + expectedOutput string + expectedError string + allowMissingKeys *bool + }{ + { + name: "existing field does not error and returns expected value", + templateArg: "{ .metadata.name }", + expectedOutput: "foo", + allowMissingKeys: &allowMissingKeys, + }, + { + name: "missing field does not error and returns an empty string since missing keys are allowed by default", + templateArg: "{ .metadata.missing }", + expectedOutput: "", + allowMissingKeys: nil, + }, + { + name: "missing field returns expected error if field is missing and allowMissingKeys is explicitly set to false", + templateArg: "{ .metadata.missing }", + expectedError: "error executing jsonpath", + allowMissingKeys: &allowMissingKeys, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + printFlags := JSONPathPrintFlags{ + TemplateArgument: &tc.templateArg, + AllowMissingKeys: tc.allowMissingKeys, + } + + outputFormat := "jsonpath" + p, err := printFlags.ToPrinter(outputFormat) + if IsNoCompatiblePrinterError(err) { + t.Fatalf("expected to match template printer for output format %q", outputFormat) + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + out := bytes.NewBuffer([]byte{}) + err = p.PrintObj(testObject, out) + + if len(tc.expectedError) > 0 { + if err == nil || !strings.Contains(err.Error(), tc.expectedError) { + t.Errorf("expecting error %q, got %v", tc.expectedError, err) + } + return + } + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if len(out.String()) != len(tc.expectedOutput) { + t.Errorf("unexpected output: expecting %q, got %q", tc.expectedOutput, out.String()) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/kube_template_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/kube_template_flags.go new file mode 100644 index 000000000..b44a1b038 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/kube_template_flags.go @@ -0,0 +1,88 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" +) + +// KubeTemplatePrintFlags composes print flags that provide both a JSONPath and a go-template printer. +// This is necessary if dealing with cases that require support both both printers, since both sets of flags +// require overlapping flags. +type KubeTemplatePrintFlags struct { + GoTemplatePrintFlags *GoTemplatePrintFlags + JSONPathPrintFlags *JSONPathPrintFlags + + AllowMissingKeys *bool + TemplateArgument *string +} + +func (f *KubeTemplatePrintFlags) AllowedFormats() []string { + if f == nil { + return []string{} + } + return append(f.GoTemplatePrintFlags.AllowedFormats(), f.JSONPathPrintFlags.AllowedFormats()...) +} + +func (f *KubeTemplatePrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) { + if f == nil { + return nil, NoCompatiblePrinterError{} + } + + if p, err := f.JSONPathPrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) { + return p, err + } + return f.GoTemplatePrintFlags.ToPrinter(outputFormat) +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to template printing to it +func (f *KubeTemplatePrintFlags) AddFlags(c *cobra.Command) { + if f == nil { + return + } + + if f.TemplateArgument != nil { + c.Flags().StringVar(f.TemplateArgument, "template", *f.TemplateArgument, "Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].") + c.MarkFlagFilename("template") + } + if f.AllowMissingKeys != nil { + c.Flags().BoolVar(f.AllowMissingKeys, "allow-missing-template-keys", *f.AllowMissingKeys, "If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.") + } +} + +// NewKubeTemplatePrintFlags returns flags associated with +// --template printing, with default values set. +func NewKubeTemplatePrintFlags() *KubeTemplatePrintFlags { + allowMissingKeysPtr := true + templateArgPtr := "" + + return &KubeTemplatePrintFlags{ + GoTemplatePrintFlags: &GoTemplatePrintFlags{ + TemplateArgument: &templateArgPtr, + AllowMissingKeys: &allowMissingKeysPtr, + }, + JSONPathPrintFlags: &JSONPathPrintFlags{ + TemplateArgument: &templateArgPtr, + AllowMissingKeys: &allowMissingKeysPtr, + }, + + TemplateArgument: &templateArgPtr, + AllowMissingKeys: &allowMissingKeysPtr, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/name_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/name_flags.go new file mode 100644 index 000000000..13c714554 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/name_flags.go @@ -0,0 +1,78 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" + + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" +) + +// NamePrintFlags provides default flags necessary for printing +// a resource's fully-qualified Kind.group/name, or a successful +// message about that resource if an Operation is provided. +type NamePrintFlags struct { + // Operation describes the name of the action that + // took place on an object, to be included in the + // finalized "successful" message. + Operation string +} + +func (f *NamePrintFlags) Complete(successTemplate string) error { + f.Operation = fmt.Sprintf(successTemplate, f.Operation) + return nil +} + +func (f *NamePrintFlags) AllowedFormats() []string { + return []string{"name"} +} + +// ToPrinter receives an outputFormat and returns a printer capable of +// handling --output=name printing. +// Returns false if the specified outputFormat does not match a supported format. +// Supported format types can be found in pkg/printers/printers.go +func (f *NamePrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) { + namePrinter := &printers.NamePrinter{ + Operation: f.Operation, + } + + outputFormat = strings.ToLower(outputFormat) + switch outputFormat { + case "name": + namePrinter.ShortOutput = true + fallthrough + case "": + return namePrinter, nil + default: + return nil, NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} + } +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to name printing to it +func (f *NamePrintFlags) AddFlags(c *cobra.Command) {} + +// NewNamePrintFlags returns flags associated with +// --name printing, with default values set. +func NewNamePrintFlags(operation string) *NamePrintFlags { + return &NamePrintFlags{ + Operation: operation, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/name_flags_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/name_flags_test.go new file mode 100644 index 000000000..6f64fad94 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/name_flags_test.go @@ -0,0 +1,116 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "bytes" + "strings" + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestNamePrinterSupportsExpectedFormats(t *testing.T) { + testObject := &v1.Pod{ + TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"}, + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + } + + testCases := []struct { + name string + outputFormat string + operation string + dryRun bool + expectedError string + expectedOutput string + expectNoMatch bool + }{ + { + name: "valid \"name\" output format with no operation prints resource name", + outputFormat: "name", + expectedOutput: "pod/foo", + }, + { + name: "valid \"name\" output format and an operation results in a short-output (non success printer) message", + outputFormat: "name", + operation: "patched", + expectedOutput: "pod/foo", + }, + { + name: "operation and no valid \"name\" output does not match a printer", + operation: "patched", + outputFormat: "invalid", + dryRun: true, + expectNoMatch: true, + }, + { + name: "operation and empty output still matches name printer", + expectedOutput: "pod/foo patched", + operation: "patched", + }, + { + name: "no printer is matched on an invalid outputFormat", + outputFormat: "invalid", + expectNoMatch: true, + }, + { + name: "printer should not match on any other format supported by another printer", + outputFormat: "go-template", + expectNoMatch: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + printFlags := NamePrintFlags{ + Operation: tc.operation, + } + + p, err := printFlags.ToPrinter(tc.outputFormat) + if tc.expectNoMatch { + if !IsNoCompatiblePrinterError(err) { + t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) + } + return + } + if IsNoCompatiblePrinterError(err) { + t.Fatalf("expected to match name printer for output format %q", tc.outputFormat) + } + + if len(tc.expectedError) > 0 { + if err == nil || !strings.Contains(err.Error(), tc.expectedError) { + t.Errorf("expecting error %q, got %v", tc.expectedError, err) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + out := bytes.NewBuffer([]byte{}) + err = p.PrintObj(testObject, out) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if !strings.Contains(out.String(), tc.expectedOutput) { + t.Errorf("unexpected output: expecting %q, got %q", tc.expectedOutput, out.String()) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/print_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/print_flags.go new file mode 100644 index 000000000..1292d633c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/print_flags.go @@ -0,0 +1,158 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "fmt" + "sort" + "strings" + + "github.com/spf13/cobra" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" +) + +type NoCompatiblePrinterError struct { + OutputFormat *string + AllowedFormats []string + Options interface{} +} + +func (e NoCompatiblePrinterError) Error() string { + output := "" + if e.OutputFormat != nil { + output = *e.OutputFormat + } + + sort.Strings(e.AllowedFormats) + return fmt.Sprintf("unable to match a printer suitable for the output format %q, allowed formats are: %s", output, strings.Join(e.AllowedFormats, ",")) +} + +func IsNoCompatiblePrinterError(err error) bool { + if err == nil { + return false + } + + _, ok := err.(NoCompatiblePrinterError) + return ok +} + +// PrintFlags composes common printer flag structs +// used across all commands, and provides a method +// of retrieving a known printer based on flag values provided. +type PrintFlags struct { + JSONYamlPrintFlags *JSONYamlPrintFlags + NamePrintFlags *NamePrintFlags + TemplatePrinterFlags *KubeTemplatePrintFlags + + TypeSetterPrinter *printers.TypeSetterPrinter + + OutputFormat *string + + // OutputFlagSpecified indicates whether the user specifically requested a certain kind of output. + // Using this function allows a sophisticated caller to change the flag binding logic if they so desire. + OutputFlagSpecified func() bool +} + +func (f *PrintFlags) Complete(successTemplate string) error { + return f.NamePrintFlags.Complete(successTemplate) +} + +func (f *PrintFlags) AllowedFormats() []string { + ret := []string{} + ret = append(ret, f.JSONYamlPrintFlags.AllowedFormats()...) + ret = append(ret, f.NamePrintFlags.AllowedFormats()...) + ret = append(ret, f.TemplatePrinterFlags.AllowedFormats()...) + return ret +} + +func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) { + outputFormat := "" + if f.OutputFormat != nil { + outputFormat = *f.OutputFormat + } + // For backwards compatibility we want to support a --template argument given, even when no --output format is provided. + // If no explicit output format has been provided via the --output flag, fallback + // to honoring the --template argument. + templateFlagSpecified := f.TemplatePrinterFlags != nil && + f.TemplatePrinterFlags.TemplateArgument != nil && + len(*f.TemplatePrinterFlags.TemplateArgument) > 0 + outputFlagSpecified := f.OutputFlagSpecified != nil && f.OutputFlagSpecified() + if templateFlagSpecified && !outputFlagSpecified { + outputFormat = "go-template" + } + + if f.JSONYamlPrintFlags != nil { + if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) { + return f.TypeSetterPrinter.WrapToPrinter(p, err) + } + } + + if f.NamePrintFlags != nil { + if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) { + return f.TypeSetterPrinter.WrapToPrinter(p, err) + } + } + + if f.TemplatePrinterFlags != nil { + if p, err := f.TemplatePrinterFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) { + return f.TypeSetterPrinter.WrapToPrinter(p, err) + } + } + + return nil, NoCompatiblePrinterError{OutputFormat: f.OutputFormat, AllowedFormats: f.AllowedFormats()} +} + +func (f *PrintFlags) AddFlags(cmd *cobra.Command) { + f.JSONYamlPrintFlags.AddFlags(cmd) + f.NamePrintFlags.AddFlags(cmd) + f.TemplatePrinterFlags.AddFlags(cmd) + + if f.OutputFormat != nil { + cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, fmt.Sprintf("Output format. One of: %s.", strings.Join(f.AllowedFormats(), "|"))) + if f.OutputFlagSpecified == nil { + f.OutputFlagSpecified = func() bool { + return cmd.Flag("output").Changed + } + } + } +} + +// WithDefaultOutput sets a default output format if one is not provided through a flag value +func (f *PrintFlags) WithDefaultOutput(output string) *PrintFlags { + f.OutputFormat = &output + return f +} + +// WithTypeSetter sets a wrapper than will surround the returned printer with a printer to type resources +func (f *PrintFlags) WithTypeSetter(scheme *runtime.Scheme) *PrintFlags { + f.TypeSetterPrinter = printers.NewTypeSetter(scheme) + return f +} + +func NewPrintFlags(operation string) *PrintFlags { + outputFormat := "" + + return &PrintFlags{ + OutputFormat: &outputFormat, + + JSONYamlPrintFlags: NewJSONYamlPrintFlags(), + NamePrintFlags: NewNamePrintFlags(operation), + TemplatePrinterFlags: NewKubeTemplatePrintFlags(), + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/BUILD new file mode 100644 index 000000000..6357f99a5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/BUILD @@ -0,0 +1,52 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "discard.go", + "interface.go", + "json.go", + "jsonpath.go", + "name.go", + "sourcechecker.go", + "template.go", + "typesetter.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/client-go/util/jsonpath:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "sourcechecker_test.go", + "template_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/discard.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/discard.go new file mode 100644 index 000000000..cd934976d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/discard.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 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 printers + +import ( + "io" + + "k8s.io/apimachinery/pkg/runtime" +) + +// NewDiscardingPrinter is a printer that discards all objects +func NewDiscardingPrinter() ResourcePrinterFunc { + return ResourcePrinterFunc(func(runtime.Object, io.Writer) error { + return nil + }) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/interface.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/interface.go new file mode 100644 index 000000000..b59a935fc --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/interface.go @@ -0,0 +1,37 @@ +/* +Copyright 2018 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 printers + +import ( + "io" + + "k8s.io/apimachinery/pkg/runtime" +) + +// ResourcePrinterFunc is a function that can print objects +type ResourcePrinterFunc func(runtime.Object, io.Writer) error + +// PrintObj implements ResourcePrinter +func (fn ResourcePrinterFunc) PrintObj(obj runtime.Object, w io.Writer) error { + return fn(obj, w) +} + +// ResourcePrinter is an interface that knows how to print runtime objects. +type ResourcePrinter interface { + // Print receives a runtime object, formats it and prints it to a writer. + PrintObj(runtime.Object, io.Writer) error +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/json.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/json.go new file mode 100644 index 000000000..1df9a8646 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/json.go @@ -0,0 +1,105 @@ +/* +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 printers + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "reflect" + + "k8s.io/apimachinery/pkg/runtime" + + "github.com/ghodss/yaml" +) + +// JSONPrinter is an implementation of ResourcePrinter which outputs an object as JSON. +type JSONPrinter struct{} + +// PrintObj is an implementation of ResourcePrinter.PrintObj which simply writes the object to the Writer. +func (p *JSONPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + switch obj := obj.(type) { + case *runtime.Unknown: + var buf bytes.Buffer + err := json.Indent(&buf, obj.Raw, "", " ") + if err != nil { + return err + } + buf.WriteRune('\n') + _, err = buf.WriteTo(w) + return err + } + + if obj.GetObjectKind().GroupVersionKind().Empty() { + return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type") + } + + data, err := json.MarshalIndent(obj, "", " ") + if err != nil { + return err + } + data = append(data, '\n') + _, err = w.Write(data) + return err +} + +// YAMLPrinter is an implementation of ResourcePrinter which outputs an object as YAML. +// The input object is assumed to be in the internal version of an API and is converted +// to the given version first. +type YAMLPrinter struct { + version string + converter runtime.ObjectConvertor +} + +// PrintObj prints the data as YAML. +func (p *YAMLPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + switch obj := obj.(type) { + case *runtime.Unknown: + data, err := yaml.JSONToYAML(obj.Raw) + if err != nil { + return err + } + _, err = w.Write(data) + return err + } + + if obj.GetObjectKind().GroupVersionKind().Empty() { + return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type") + } + + output, err := yaml.Marshal(obj) + if err != nil { + return err + } + _, err = fmt.Fprint(w, string(output)) + return err +} diff --git a/vendor/k8s.io/kubernetes/pkg/printers/jsonpath.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/jsonpath.go similarity index 89% rename from vendor/k8s.io/kubernetes/pkg/printers/jsonpath.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/jsonpath.go index f1739dcd6..76ebb1563 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/jsonpath.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/jsonpath.go @@ -107,15 +107,21 @@ func NewJSONPathPrinter(tmpl string) (*JSONPathPrinter, error) { if err := j.Parse(tmpl); err != nil { return nil, err } - return &JSONPathPrinter{tmpl, j}, nil -} - -func (j *JSONPathPrinter) AfterPrint(w io.Writer, res string) error { - return nil + return &JSONPathPrinter{ + rawTemplate: tmpl, + JSONPath: j, + }, nil } // PrintObj formats the obj with the JSONPath Template. func (j *JSONPathPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + var queryObj interface{} = obj if meta.IsListType(obj) { data, err := json.Marshal(obj) @@ -150,12 +156,3 @@ func (j *JSONPathPrinter) PrintObj(obj runtime.Object, w io.Writer) error { } return nil } - -// TODO: implement HandledResources() -func (p *JSONPathPrinter) HandledResources() []string { - return []string{} -} - -func (p *JSONPathPrinter) IsGeneric() bool { - return true -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/name.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/name.go new file mode 100644 index 000000000..d04c5c6bb --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/name.go @@ -0,0 +1,124 @@ +/* +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 printers + +import ( + "fmt" + "io" + "reflect" + "strings" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// NamePrinter is an implementation of ResourcePrinter which outputs "resource/name" pair of an object. +type NamePrinter struct { + // ShortOutput indicates whether an operation should be + // printed along side the "resource/name" pair for an object. + ShortOutput bool + // Operation describes the name of the action that + // took place on an object, to be included in the + // finalized "successful" message. + Operation string +} + +// PrintObj is an implementation of ResourcePrinter.PrintObj which decodes the object +// and print "resource/name" pair. If the object is a List, print all items in it. +func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + // we need an actual value in order to retrieve the package path for an object. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + if meta.IsListType(obj) { + // we allow unstructured lists for now because they always contain the GVK information. We should chase down + // callers and stop them from passing unflattened lists + // TODO chase the caller that is setting this and remove it. + if _, ok := obj.(*unstructured.UnstructuredList); !ok { + return fmt.Errorf("list types are not supported by name printing: %T", obj) + } + + items, err := meta.ExtractList(obj) + if err != nil { + return err + } + for _, obj := range items { + if err := p.PrintObj(obj, w); err != nil { + return err + } + } + return nil + } + + if obj.GetObjectKind().GroupVersionKind().Empty() { + return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type") + } + + name := "" + if acc, err := meta.Accessor(obj); err == nil { + if n := acc.GetName(); len(n) > 0 { + name = n + } + } + + return printObj(w, name, p.Operation, p.ShortOutput, GetObjectGroupKind(obj)) +} + +func GetObjectGroupKind(obj runtime.Object) schema.GroupKind { + if obj == nil { + return schema.GroupKind{Kind: ""} + } + groupVersionKind := obj.GetObjectKind().GroupVersionKind() + if len(groupVersionKind.Kind) > 0 { + return groupVersionKind.GroupKind() + } + + if uns, ok := obj.(*unstructured.Unstructured); ok { + if len(uns.GroupVersionKind().Kind) > 0 { + return uns.GroupVersionKind().GroupKind() + } + } + + return schema.GroupKind{Kind: ""} +} + +func printObj(w io.Writer, name string, operation string, shortOutput bool, groupKind schema.GroupKind) error { + if len(groupKind.Kind) == 0 { + return fmt.Errorf("missing kind for resource with name %v", name) + } + + if len(operation) > 0 { + operation = " " + operation + } + + if shortOutput { + operation = "" + } + + if len(groupKind.Group) == 0 { + fmt.Fprintf(w, "%s/%s%s\n", strings.ToLower(groupKind.Kind), name, operation) + return nil + } + + fmt.Fprintf(w, "%s.%s/%s%s\n", strings.ToLower(groupKind.Kind), groupKind.Group, name, operation) + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/sourcechecker.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/sourcechecker.go new file mode 100644 index 000000000..11d672cc9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/sourcechecker.go @@ -0,0 +1,60 @@ +/* +Copyright 2018 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 printers + +import ( + "strings" +) + +var ( + InternalObjectPrinterErr = "a versioned object must be passed to a printer" + + // disallowedPackagePrefixes contains regular expression templates + // for object package paths that are not allowed by printers. + disallowedPackagePrefixes = []string{ + "k8s.io/kubernetes/pkg/apis/", + } +) + +var InternalObjectPreventer = &illegalPackageSourceChecker{disallowedPackagePrefixes} + +func IsInternalObjectError(err error) bool { + if err == nil { + return false + } + + return err.Error() == InternalObjectPrinterErr +} + +// illegalPackageSourceChecker compares a given +// object's package path, and determines if the +// object originates from a disallowed source. +type illegalPackageSourceChecker struct { + // disallowedPrefixes is a slice of disallowed package path + // prefixes for a given runtime.Object that we are printing. + disallowedPrefixes []string +} + +func (c *illegalPackageSourceChecker) IsForbidden(pkgPath string) bool { + for _, forbiddenPrefix := range c.disallowedPrefixes { + if strings.HasPrefix(pkgPath, forbiddenPrefix) { + return true + } + } + + return false +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/sourcechecker_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/sourcechecker_test.go new file mode 100644 index 000000000..704fafb1f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/sourcechecker_test.go @@ -0,0 +1,66 @@ +/* +Copyright 2018 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 printers + +import ( + "testing" +) + +func TestIllegalPackageSourceChecker(t *testing.T) { + disallowedPrefixes := []string{ + "foo/bar", + "k8s.io/foo/bar/vendor/k8s.io/baz/buz", + "bar/foo/baz", + } + + testCases := []struct { + name string + pkgPath string + shouldBeAllowed bool + }{ + { + name: "package path beginning with forbidden prefix is rejected", + pkgPath: "foo/bar/baz/buz", + shouldBeAllowed: false, + }, + { + name: "package path not fully matching forbidden prefix is allowed", + pkgPath: "bar/foo", + shouldBeAllowed: true, + }, + { + name: "package path containing forbidden prefix (not as prefix) is allowed", + pkgPath: "k8s.io/bar/foo/baz/etc", + shouldBeAllowed: true, + }, + } + + checker := &illegalPackageSourceChecker{disallowedPrefixes} + + for _, tc := range testCases { + if checker.IsForbidden(tc.pkgPath) { + if tc.shouldBeAllowed { + t.Fatalf("expected package path %q to have been allowed", tc.pkgPath) + } + continue + } + + if !tc.shouldBeAllowed { + t.Fatalf("expected package path %q to have been rejected", tc.pkgPath) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/template.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/template.go new file mode 100644 index 000000000..5dd807dad --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/template.go @@ -0,0 +1,118 @@ +/* +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 printers + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io" + "reflect" + "text/template" + + "k8s.io/apimachinery/pkg/runtime" +) + +// GoTemplatePrinter is an implementation of ResourcePrinter which formats data with a Go Template. +type GoTemplatePrinter struct { + rawTemplate string + template *template.Template +} + +func NewGoTemplatePrinter(tmpl []byte) (*GoTemplatePrinter, error) { + t, err := template.New("output"). + Funcs(template.FuncMap{ + "exists": exists, + "base64decode": base64decode, + }). + Parse(string(tmpl)) + if err != nil { + return nil, err + } + return &GoTemplatePrinter{ + rawTemplate: string(tmpl), + template: t, + }, nil +} + +// AllowMissingKeys tells the template engine if missing keys are allowed. +func (p *GoTemplatePrinter) AllowMissingKeys(allow bool) { + if allow { + p.template.Option("missingkey=default") + } else { + p.template.Option("missingkey=error") + } +} + +// PrintObj formats the obj with the Go Template. +func (p *GoTemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error { + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + var data []byte + var err error + data, err = json.Marshal(obj) + if err != nil { + return err + } + + out := map[string]interface{}{} + if err := json.Unmarshal(data, &out); err != nil { + return err + } + if err = p.safeExecute(w, out); err != nil { + // It is way easier to debug this stuff when it shows up in + // stdout instead of just stdin. So in addition to returning + // a nice error, also print useful stuff with the writer. + fmt.Fprintf(w, "Error executing template: %v. Printing more information for debugging the template:\n", err) + fmt.Fprintf(w, "\ttemplate was:\n\t\t%v\n", p.rawTemplate) + fmt.Fprintf(w, "\traw data was:\n\t\t%v\n", string(data)) + fmt.Fprintf(w, "\tobject given to template engine was:\n\t\t%+v\n\n", out) + return fmt.Errorf("error executing template %q: %v", p.rawTemplate, err) + } + return nil +} + +// safeExecute tries to execute the template, but catches panics and returns an error +// should the template engine panic. +func (p *GoTemplatePrinter) safeExecute(w io.Writer, obj interface{}) error { + var panicErr error + // Sorry for the double anonymous function. There's probably a clever way + // to do this that has the defer'd func setting the value to be returned, but + // that would be even less obvious. + retErr := func() error { + defer func() { + if x := recover(); x != nil { + panicErr = fmt.Errorf("caught panic: %+v", x) + } + }() + return p.template.Execute(w, obj) + }() + if panicErr != nil { + return panicErr + } + return retErr +} + +func base64decode(v string) (string, error) { + data, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return "", fmt.Errorf("base64 decode failed: %v", err) + } + return string(data), nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/template_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/template_test.go new file mode 100644 index 000000000..25841aa4d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/template_test.go @@ -0,0 +1,102 @@ +/* +Copyright 2018 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 printers + +import ( + "bytes" + "strings" + "testing" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +func TestTemplate(t *testing.T) { + testCase := []struct { + name string + template string + obj runtime.Object + expectOut string + expectErr func(error) (string, bool) + }{ + { + name: "support base64 decoding of secret data", + template: "{{ .data.username | base64decode }}", + obj: &v1.Secret{ + Data: map[string][]byte{ + "username": []byte("hunter"), + }, + }, + expectOut: "hunter", + }, + { + name: "test error path for base64 decoding", + template: "{{ .data.username | base64decode }}", + obj: &badlyMarshaledSecret{}, + expectErr: func(err error) (string, bool) { + matched := strings.Contains(err.Error(), "base64 decode") + return "a base64 decode error", matched + }, + }, + } + for _, test := range testCase { + t.Run(test.name, func(t *testing.T) { + buffer := &bytes.Buffer{} + + p, err := NewGoTemplatePrinter([]byte(test.template)) + if err != nil { + if test.expectErr == nil { + t.Errorf("[%s]expected success but got:\n %v\n", test.name, err) + return + } + if expected, ok := test.expectErr(err); !ok { + t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", test.name, expected, err) + } + return + } + + err = p.PrintObj(test.obj, buffer) + if err != nil { + if test.expectErr == nil { + t.Errorf("[%s]expected success but got:\n %v\n", test.name, err) + return + } + if expected, ok := test.expectErr(err); !ok { + t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", test.name, expected, err) + } + return + } + + if test.expectErr != nil { + t.Errorf("[%s]expect:\n error\n but got:\n no error\n", test.name) + return + } + + if test.expectOut != buffer.String() { + t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", test.name, test.expectOut, buffer.String()) + } + }) + } +} + +type badlyMarshaledSecret struct { + v1.Secret +} + +func (a badlyMarshaledSecret) MarshalJSON() ([]byte, error) { + return []byte(`{"apiVersion":"v1","data":{"username":"--THIS IS NOT BASE64--"},"kind":"Secret"}`), nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/typesetter.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/typesetter.go new file mode 100644 index 000000000..8d2d9b56e --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers/typesetter.go @@ -0,0 +1,95 @@ +/* +Copyright 2018 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 printers + +import ( + "fmt" + "io" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// TypeSetterPrinter is an implementation of ResourcePrinter wraps another printer with types set on the objects +type TypeSetterPrinter struct { + Delegate ResourcePrinter + + Typer runtime.ObjectTyper +} + +// NewTypeSetter constructs a wrapping printer with required params +func NewTypeSetter(typer runtime.ObjectTyper) *TypeSetterPrinter { + return &TypeSetterPrinter{Typer: typer} +} + +// PrintObj is an implementation of ResourcePrinter.PrintObj which sets type information on the obj for the duration +// of printing. It is NOT threadsafe. +func (p *TypeSetterPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + if obj == nil { + return p.Delegate.PrintObj(obj, w) + } + if !obj.GetObjectKind().GroupVersionKind().Empty() { + return p.Delegate.PrintObj(obj, w) + } + + // we were empty coming in, make sure we're empty going out. This makes the call thread-unsafe + defer func() { + obj.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{}) + }() + + gvks, _, err := p.Typer.ObjectKinds(obj) + if err != nil { + // printers wrapped by us expect to find the type information present + return fmt.Errorf("missing apiVersion or kind and cannot assign it; %v", err) + } + + for _, gvk := range gvks { + if len(gvk.Kind) == 0 { + continue + } + if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal { + continue + } + obj.GetObjectKind().SetGroupVersionKind(gvk) + break + } + + return p.Delegate.PrintObj(obj, w) +} + +// ToPrinter returns a printer (not threadsafe!) that has been wrapped +func (p *TypeSetterPrinter) ToPrinter(delegate ResourcePrinter) ResourcePrinter { + if p == nil { + return delegate + } + + p.Delegate = delegate + return p +} + +// WrapToPrinter wraps the common ToPrinter method +func (p *TypeSetterPrinter) WrapToPrinter(delegate ResourcePrinter, err error) (ResourcePrinter, error) { + if err != nil { + return delegate, err + } + if p == nil { + return delegate, nil + } + + p.Delegate = delegate + return p, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/record_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/record_flags.go new file mode 100644 index 000000000..faf250d53 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/record_flags.go @@ -0,0 +1,199 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "os" + "path/filepath" + "strings" + + "github.com/evanphx/json-patch" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/json" +) + +// ChangeCauseAnnotation is the annotation indicating a guess at "why" something was changed +const ChangeCauseAnnotation = "kubernetes.io/change-cause" + +// RecordFlags contains all flags associated with the "--record" operation +type RecordFlags struct { + // Record indicates the state of the recording flag. It is a pointer so a caller can opt out or rebind + Record *bool + + changeCause string +} + +// ToRecorder returns a ChangeCause recorder if --record=false was not +// explicitly given by the user +func (f *RecordFlags) ToRecorder() (Recorder, error) { + if f == nil { + return NoopRecorder{}, nil + } + + shouldRecord := false + if f.Record != nil { + shouldRecord = *f.Record + } + + // if flag was explicitly set to false by the user, + // do not record + if !shouldRecord { + return NoopRecorder{}, nil + } + + return &ChangeCauseRecorder{ + changeCause: f.changeCause, + }, nil +} + +// Complete is called before the command is run, but after it is invoked to finish the state of the struct before use. +func (f *RecordFlags) Complete(cmd *cobra.Command) error { + if f == nil { + return nil + } + + f.changeCause = parseCommandArguments(cmd) + return nil +} + +func (f *RecordFlags) CompleteWithChangeCause(cause string) error { + if f == nil { + return nil + } + + f.changeCause = cause + return nil +} + +// AddFlags binds the requested flags to the provided flagset +// TODO have this only take a flagset +func (f *RecordFlags) AddFlags(cmd *cobra.Command) { + if f == nil { + return + } + + if f.Record != nil { + cmd.Flags().BoolVar(f.Record, "record", *f.Record, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.") + } +} + +// NewRecordFlags provides a RecordFlags with reasonable default values set for use +func NewRecordFlags() *RecordFlags { + record := false + + return &RecordFlags{ + Record: &record, + } +} + +// Recorder is used to record why a runtime.Object was changed in an annotation. +type Recorder interface { + // Record records why a runtime.Object was changed in an annotation. + Record(runtime.Object) error + MakeRecordMergePatch(runtime.Object) ([]byte, error) +} + +// NoopRecorder does nothing. It is a "do nothing" that can be returned so code doesn't switch on it. +type NoopRecorder struct{} + +// Record implements Recorder +func (r NoopRecorder) Record(obj runtime.Object) error { + return nil +} + +// MakeRecordMergePatch implements Recorder +func (r NoopRecorder) MakeRecordMergePatch(obj runtime.Object) ([]byte, error) { + return nil, nil +} + +// ChangeCauseRecorder annotates a "change-cause" to an input runtime object +type ChangeCauseRecorder struct { + changeCause string +} + +// Record annotates a "change-cause" to a given info if either "shouldRecord" is true, +// or the resource info previously contained a "change-cause" annotation. +func (r *ChangeCauseRecorder) Record(obj runtime.Object) error { + accessor, err := meta.Accessor(obj) + if err != nil { + return err + } + annotations := accessor.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string) + } + annotations[ChangeCauseAnnotation] = r.changeCause + accessor.SetAnnotations(annotations) + return nil +} + +// MakeRecordMergePatch produces a merge patch for updating the recording annotation. +func (r *ChangeCauseRecorder) MakeRecordMergePatch(obj runtime.Object) ([]byte, error) { + // copy so we don't mess with the original + objCopy := obj.DeepCopyObject() + if err := r.Record(objCopy); err != nil { + return nil, err + } + + oldData, err := json.Marshal(obj) + if err != nil { + return nil, err + } + newData, err := json.Marshal(objCopy) + if err != nil { + return nil, err + } + + return jsonpatch.CreateMergePatch(oldData, newData) +} + +// parseCommandArguments will stringify and return all environment arguments ie. a command run by a client +// using the factory. +// Set showSecrets false to filter out stuff like secrets. +func parseCommandArguments(cmd *cobra.Command) string { + if len(os.Args) == 0 { + return "" + } + + flags := "" + parseFunc := func(flag *pflag.Flag, value string) error { + flags = flags + " --" + flag.Name + if set, ok := flag.Annotations["classified"]; !ok || len(set) == 0 { + flags = flags + "=" + value + } else { + flags = flags + "=CLASSIFIED" + } + return nil + } + var err error + err = cmd.Flags().ParseAll(os.Args[1:], parseFunc) + if err != nil || !cmd.Flags().Parsed() { + return "" + } + + args := "" + if arguments := cmd.Flags().Args(); len(arguments) > 0 { + args = " " + strings.Join(arguments, " ") + } + + base := filepath.Base(os.Args[0]) + return base + args + flags +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/BUILD new file mode 100644 index 000000000..e2fb1a892 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/BUILD @@ -0,0 +1,95 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "builder.go", + "client.go", + "doc.go", + "fake.go", + "helper.go", + "interfaces.go", + "mapper.go", + "result.go", + "scheme.go", + "selector.go", + "visitor.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource", + visibility = ["//visibility:public"], + deps = [ + "//vendor/golang.org/x/text/encoding/unicode:go_default_library", + "//vendor/golang.org/x/text/transform:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme: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/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/discovery:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "builder_test.go", + "helper_test.go", + "visitor_test.go", + ], + data = [ + "//test/e2e/testing-manifests:all-srcs", + "//test/fixtures", + ], + embed = [":go_default_library"], + deps = [ + "//vendor/github.com/davecgh/go-spew/spew:go_default_library", + "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/github.com/stretchr/testify/assert: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/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper: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/labels: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:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/rest/fake:go_default_library", + "//vendor/k8s.io/client-go/rest/watch:go_default_library", + "//vendor/k8s.io/client-go/util/testing:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/builder.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/builder.go similarity index 84% rename from vendor/k8s.io/kubernetes/pkg/kubectl/resource/builder.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/builder.go index 5c48c44fc..09e21827f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/builder.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/builder.go @@ -26,12 +26,15 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/kubernetes/pkg/kubectl/categories" - "k8s.io/kubernetes/pkg/kubectl/validation" + "k8s.io/client-go/restmapper" ) var FileExtensions = []string{".json", ".yaml", ".yml"} @@ -43,12 +46,25 @@ const defaultHttpGetAttempts int = 3 // from the command line and converting them to a list of resources to iterate // over using the Visitor interface. type Builder struct { - categoryExpander categories.CategoryExpander + categoryExpander restmapper.CategoryExpander // mapper is set explicitly by resource builders - mapper *Mapper - internal *Mapper - unstructured *Mapper + mapper *mapper + + // clientConfigFn is a function to produce a client, *if* you need one + clientConfigFn ClientConfigFunc + + restMapper meta.RESTMapper + + // objectTyper is statically determinant per-command invocation based on your internal or unstructured choice + // it does not ever need to rely upon discovery. + objectTyper runtime.ObjectTyper + + // codecFactory describes which codecs you want to use + negotiatedSerializer runtime.NegotiatedSerializer + + // local indicates that we cannot make server calls + local bool errs []error @@ -86,7 +102,10 @@ type Builder struct { export bool - schema validation.Schema + schema ContentValidator + + // fakeClientFn is used for testing + fakeClientFn FakeClientFunc } var missingResourceError = fmt.Errorf(`You must provide one or more resources by argument or filename. @@ -119,23 +138,55 @@ type resourceTuple struct { Name string } +type FakeClientFunc func(version schema.GroupVersion) (RESTClient, error) + +func NewFakeBuilder(fakeClientFn FakeClientFunc, restMapper meta.RESTMapper, categoryExpander restmapper.CategoryExpander) *Builder { + ret := newBuilder(nil, restMapper, categoryExpander) + ret.fakeClientFn = fakeClientFn + return ret +} + // NewBuilder creates a builder that operates on generic objects. At least one of // internal or unstructured must be specified. // TODO: Add versioned client (although versioned is still lossy) -func NewBuilder(internal, unstructured *Mapper, categoryExpander categories.CategoryExpander) *Builder { +// TODO remove internal and unstructured mapper and instead have them set the negotiated serializer for use in the client +func newBuilder(clientConfigFn ClientConfigFunc, restMapper meta.RESTMapper, categoryExpander restmapper.CategoryExpander) *Builder { return &Builder{ - internal: internal, - unstructured: unstructured, + clientConfigFn: clientConfigFn, + restMapper: restMapper, categoryExpander: categoryExpander, requireObject: true, } } -func (b *Builder) Schema(schema validation.Schema) *Builder { +func NewBuilder(restClientGetter RESTClientGetter) *Builder { + restMapper, mapperErr := restClientGetter.ToRESTMapper() + discoveryClient, discoveryErr := restClientGetter.ToDiscoveryClient() + var categoryExpander restmapper.CategoryExpander + if discoveryErr == nil { + categoryExpander = restmapper.NewDiscoveryCategoryExpander(discoveryClient) + } + + return newBuilder( + restClientGetter.ToRESTConfig, + restMapper, + categoryExpander, + ).AddError(mapperErr).AddError(discoveryErr) +} + +func (b *Builder) Schema(schema ContentValidator) *Builder { b.schema = schema return b } +func (b *Builder) AddError(err error) *Builder { + if err == nil { + return b + } + b.errs = append(b.errs, err) + return b +} + // FilenameParam groups input in two categories: URLs and files (files, directories, STDIN) // If enforceNamespace is false, namespaces in the specs will be allowed to // override the default namespace. If it is true, namespaces that don't match @@ -177,33 +228,45 @@ func (b *Builder) FilenameParam(enforceNamespace bool, filenameOptions *Filename // reads and then writes an object. Use this mode in preference to Internal unless you // are working with Go types directly. func (b *Builder) Unstructured() *Builder { - if b.unstructured == nil { - b.errs = append(b.errs, fmt.Errorf("no unstructured mapper provided")) - return b - } if b.mapper != nil { b.errs = append(b.errs, fmt.Errorf("another mapper was already selected, cannot use unstructured types")) return b } - b.mapper = b.unstructured + b.objectTyper = unstructuredscheme.NewUnstructuredObjectTyper() + b.mapper = &mapper{ + localFn: b.isLocal, + restMapper: b.restMapper, + clientFn: b.getClient, + decoder: unstructured.UnstructuredJSONScheme, + } + return b } -// Internal updates the builder so that it will convert objects off the wire -// into the internal form if necessary. Using internal types is lossy - fields added -// to the server will not be seen by the client code and may result in failure. Only -// use this mode when working offline, or when generating patches to send to the server. -// Use Unstructured if you are reading an object and performing a POST or PUT. -func (b *Builder) Internal() *Builder { - if b.internal == nil { - b.errs = append(b.errs, fmt.Errorf("no internal mapper provided")) - return b - } +// WithScheme uses the scheme to manage typing, conversion (optional), and decoding. If decodingVersions +// is empty, then you can end up with internal types. You have been warned. +func (b *Builder) WithScheme(scheme *runtime.Scheme, decodingVersions ...schema.GroupVersion) *Builder { if b.mapper != nil { b.errs = append(b.errs, fmt.Errorf("another mapper was already selected, cannot use internal types")) return b } - b.mapper = b.internal + b.objectTyper = scheme + codecFactory := serializer.NewCodecFactory(scheme) + negotiatedSerializer := runtime.NegotiatedSerializer(codecFactory) + // if you specified versions, you're specifying a desire for external types, which you don't want to round-trip through + // internal types + if len(decodingVersions) > 0 { + negotiatedSerializer = &serializer.DirectCodecFactory{CodecFactory: codecFactory} + } + b.negotiatedSerializer = negotiatedSerializer + + b.mapper = &mapper{ + localFn: b.isLocal, + restMapper: b.restMapper, + clientFn: b.getClient, + decoder: codecFactory.UniversalDecoder(decodingVersions...), + } + return b } @@ -217,14 +280,16 @@ func (b *Builder) LocalParam(local bool) *Builder { // Local will avoid asking the server for results. func (b *Builder) Local() *Builder { - mapper := *b.mapper - mapper.ClientMapper = DisabledClientForMapping{ClientMapper: mapper.ClientMapper} - b.mapper = &mapper + b.local = true return b } +func (b *Builder) isLocal() bool { + return b.local +} + // Mapper returns a copy of the current mapper. -func (b *Builder) Mapper() *Mapper { +func (b *Builder) Mapper() *mapper { mapper := *b.mapper return &mapper } @@ -287,6 +352,9 @@ func (b *Builder) Path(recursive bool, paths ...string) *Builder { b.paths = append(b.paths, visitors...) } + if len(b.paths) == 0 && len(b.errs) == 0 { + b.errs = append(b.errs, fmt.Errorf("error reading %v: recognized file extensions are %v", paths, FileExtensions)) + } return b } @@ -487,6 +555,9 @@ func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string func (b *Builder) ReplaceAliases(input string) string { replaced := []string{} for _, arg := range strings.Split(input, ",") { + if b.categoryExpander == nil { + continue + } if resources, ok := b.categoryExpander.Expand(arg); ok { asStrings := []string{} for _, resource := range resources { @@ -605,13 +676,13 @@ func (b *Builder) mappingFor(resourceOrKindArg string) (*meta.RESTMapping, error fullySpecifiedGVR, groupResource := schema.ParseResourceArg(resourceOrKindArg) gvk := schema.GroupVersionKind{} if fullySpecifiedGVR != nil { - gvk, _ = b.mapper.KindFor(*fullySpecifiedGVR) + gvk, _ = b.mapper.restMapper.KindFor(*fullySpecifiedGVR) } if gvk.Empty() { - gvk, _ = b.mapper.KindFor(groupResource.WithVersion("")) + gvk, _ = b.mapper.restMapper.KindFor(groupResource.WithVersion("")) } if !gvk.Empty() { - return b.mapper.RESTMapping(gvk.GroupKind(), gvk.Version) + return b.mapper.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version) } fullySpecifiedGVK, groupKind := schema.ParseKindArg(resourceOrKindArg) @@ -621,16 +692,21 @@ func (b *Builder) mappingFor(resourceOrKindArg string) (*meta.RESTMapping, error } if !fullySpecifiedGVK.Empty() { - if mapping, err := b.mapper.RESTMapping(fullySpecifiedGVK.GroupKind(), fullySpecifiedGVK.Version); err == nil { + if mapping, err := b.mapper.restMapper.RESTMapping(fullySpecifiedGVK.GroupKind(), fullySpecifiedGVK.Version); err == nil { return mapping, nil } } - mapping, err := b.mapper.RESTMapping(groupKind, gvk.Version) + mapping, err := b.mapper.restMapper.RESTMapping(groupKind, gvk.Version) if err != nil { // if we error out here, it is because we could not match a resource or a kind // for the given argument. To maintain consistency with previous behavior, // announce that a resource type could not be found. + // if the error is a URL error, then we had trouble doing discovery, so we should return the original + // error since it may help a user diagnose what is actually wrong + if _, ok := err.(*url.Error); ok { + return nil, err + } return nil, fmt.Errorf("the server doesn't have a resource type %q", groupResource.Resource) } @@ -661,7 +737,7 @@ func (b *Builder) resourceMappings() ([]*meta.RESTMapping, error) { func (b *Builder) resourceTupleMappings() (map[string]*meta.RESTMapping, error) { mappings := make(map[string]*meta.RESTMapping) - canonical := make(map[string]struct{}) + canonical := make(map[schema.GroupVersionResource]struct{}) for _, r := range b.resourceTuples { if _, ok := mappings[r.Resource]; ok { continue @@ -671,7 +747,6 @@ func (b *Builder) resourceTupleMappings() (map[string]*meta.RESTMapping, error) return nil, err } - mappings[mapping.Resource] = mapping mappings[r.Resource] = mapping canonical[mapping.Resource] = struct{}{} } @@ -747,12 +822,11 @@ func (b *Builder) visitBySelector() *Result { visitors := []Visitor{} for _, mapping := range mappings { - client, err := b.mapper.ClientForMapping(mapping) + client, err := b.getClient(mapping.GroupVersionKind.GroupVersion()) if err != nil { result.err = err return result } - client = NewClientWithOptions(client, b.requestTransforms...) selectorNamespace := b.namespace if mapping.Scope.Name() != meta.RESTScopeNameNamespace { selectorNamespace = "" @@ -768,6 +842,28 @@ func (b *Builder) visitBySelector() *Result { return result } +func (b *Builder) getClient(gv schema.GroupVersion) (RESTClient, error) { + var ( + client RESTClient + err error + ) + + switch { + case b.fakeClientFn != nil: + client, err = b.fakeClientFn(gv) + case b.negotiatedSerializer != nil: + client, err = b.clientConfigFn.clientForGroupVersion(gv, b.negotiatedSerializer) + default: + client, err = b.clientConfigFn.unstructuredClientForGroupVersion(gv) + } + + if err != nil { + return nil, err + } + + return NewClientWithOptions(client, b.requestTransforms...), nil +} + func (b *Builder) visitByResource() *Result { // if b.singleItemImplied is false, this could be by default, so double-check length // of resourceTuples to determine if in fact it is singleItemImplied or not @@ -793,16 +889,15 @@ func (b *Builder) visitByResource() *Result { } clients := make(map[string]RESTClient) for _, mapping := range mappings { - s := fmt.Sprintf("%s/%s", mapping.GroupVersionKind.GroupVersion().String(), mapping.Resource) + s := fmt.Sprintf("%s/%s", mapping.GroupVersionKind.GroupVersion().String(), mapping.Resource.Resource) if _, ok := clients[s]; ok { continue } - client, err := b.mapper.ClientForMapping(mapping) + client, err := b.getClient(mapping.GroupVersionKind.GroupVersion()) if err != nil { result.err = err return result } - client = NewClientWithOptions(client, b.requestTransforms...) clients[s] = client } @@ -812,7 +907,7 @@ func (b *Builder) visitByResource() *Result { if !ok { return result.withError(fmt.Errorf("resource %q is not recognized: %v", tuple.Resource, mappings)) } - s := fmt.Sprintf("%s/%s", mapping.GroupVersionKind.GroupVersion().String(), mapping.Resource) + s := fmt.Sprintf("%s/%s", mapping.GroupVersionKind.GroupVersion().String(), mapping.Resource.Resource) client, ok := clients[s] if !ok { return result.withError(fmt.Errorf("could not find a client for resource %q", tuple.Resource)) @@ -875,7 +970,7 @@ func (b *Builder) visitByName() *Result { } mapping := mappings[0] - client, err := b.mapper.ClientForMapping(mapping) + client, err := b.getClient(mapping.GroupVersionKind.GroupVersion()) if err != nil { result.err = err return result @@ -933,12 +1028,12 @@ func (b *Builder) visitByPaths() *Result { visitors = VisitorList(b.paths) } + if b.flatten { + visitors = NewFlattenListVisitor(visitors, b.objectTyper, b.mapper) + } + // only items from disk can be refetched if b.latest { - // must flatten lists prior to fetching - if b.flatten { - visitors = NewFlattenListVisitor(visitors, b.mapper) - } // must set namespace prior to fetching if b.defaultNamespace { visitors = NewDecoratedVisitor(visitors, SetNamespace(b.namespace)) @@ -968,7 +1063,7 @@ func (b *Builder) Do() *Result { return r } if b.flatten { - r.visitor = NewFlattenListVisitor(r.visitor, b.mapper) + r.visitor = NewFlattenListVisitor(r.visitor, b.objectTyper, b.mapper) } helpers := []VisitorFunc{} if b.defaultNamespace { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/builder_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/builder_test.go similarity index 90% rename from vendor/k8s.io/kubernetes/pkg/kubectl/resource/builder_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/builder_test.go index 90c4f6be7..ecf12529a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/builder_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/builder_test.go @@ -29,11 +29,12 @@ import ( "strings" "testing" + "github.com/davecgh/go-spew/spew" "github.com/ghodss/yaml" - "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -46,15 +47,16 @@ import ( "k8s.io/client-go/rest/fake" restclientwatch "k8s.io/client-go/rest/watch" utiltesting "k8s.io/client-go/util/testing" - "k8s.io/kubernetes/pkg/kubectl/categories" - "k8s.io/kubernetes/pkg/kubectl/scheme" + + // TODO we need to remove this linkage and create our own scheme + "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes/scheme" ) var ( corev1GV = schema.GroupVersion{Version: "v1"} corev1Codec = scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(corev1GV), scheme.Codecs.UniversalDecoder(corev1GV), corev1GV, corev1GV) metaAccessor = meta.NewAccessor() - restmapper = scheme.Registry.RESTMapper() ) func stringBody(body string) io.ReadCloser { @@ -71,14 +73,14 @@ func watchBody(events ...watch.Event) string { return buf.String() } -func fakeClient() ClientMapper { - return ClientMapperFunc(func(*meta.RESTMapping) (RESTClient, error) { +func fakeClient() FakeClientFunc { + return func(version schema.GroupVersion) (RESTClient, error) { return &fake.RESTClient{}, nil - }) + } } -func fakeClientWith(testName string, t *testing.T, data map[string]string) ClientMapper { - return ClientMapperFunc(func(*meta.RESTMapping) (RESTClient, error) { +func fakeClientWith(testName string, t *testing.T, data map[string]string) FakeClientFunc { + return func(version schema.GroupVersion) (RESTClient, error) { return &fake.RESTClient{ GroupVersion: corev1GV, NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, @@ -101,7 +103,7 @@ func fakeClientWith(testName string, t *testing.T, data map[string]string) Clien }, nil }), }, nil - }) + } } func testData() (*v1.PodList, *v1.ServiceList) { @@ -267,22 +269,14 @@ func newDefaultBuilder() *Builder { return newDefaultBuilderWith(fakeClient()) } -func newDefaultBuilderWith(client ClientMapper) *Builder { - return NewBuilder( - &Mapper{ - RESTMapper: restmapper, - ObjectTyper: scheme.Scheme, - ClientMapper: client, - Decoder: corev1Codec, - }, - nil, - categories.LegacyCategoryExpander, - ).Internal() +func newDefaultBuilderWith(fakeClientFn FakeClientFunc) *Builder { + return NewFakeBuilder(fakeClientFn, testrestmapper.TestOnlyStaticRESTMapper(scheme.Scheme), FakeCategoryExpander). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...) } func TestPathBuilderAndVersionedObjectNotDefaulted(t *testing.T) { b := newDefaultBuilder(). - FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../test/fixtures/pkg/kubectl/builder/kitten-rc.yaml"}}) + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../../test/fixtures/pkg/kubectl/builder/kitten-rc.yaml"}}) test := &testVisitor{} singleItemImplied := false @@ -296,7 +290,8 @@ func TestPathBuilderAndVersionedObjectNotDefaulted(t *testing.T) { if info.Name != "update-demo-kitten" || info.Namespace != "" || info.Object == nil { t.Errorf("unexpected info: %#v", info) } - obj := info.AsVersioned() + + obj := info.Object version, ok := obj.(*v1.ReplicationController) // versioned object does not have defaulting applied if obj == nil || !ok || version.Spec.Replicas != nil { @@ -375,9 +370,9 @@ func TestPathBuilderWithMultiple(t *testing.T) { directory string expectedNames []string }{ - {"pod", &v1.Pod{}, false, "../../../examples/pod", []string{"nginx"}}, + {"pod", &v1.Pod{}, false, "../../../../test/e2e/testing-manifests/pod", []string{"nginx"}}, {"recursive-pod", &v1.Pod{}, true, fmt.Sprintf("%s/recursive/pod", tmpDir), []string{"busybox0", "busybox1"}}, - {"rc", &v1.ReplicationController{}, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml", []string{"redis-master"}}, + {"rc", &v1.ReplicationController{}, false, "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml", []string{"redis-master"}}, {"recursive-rc", &v1.ReplicationController{}, true, fmt.Sprintf("%s/recursive/rc", tmpDir), []string{"busybox0", "busybox1"}}, {"hardlink", &v1.Pod{}, false, fmt.Sprintf("%s/inode/hardlink/busybox-link.json", tmpDir), []string{"busybox0"}}, {"hardlink", &v1.Pod{}, true, fmt.Sprintf("%s/inode/hardlink/busybox-link.json", tmpDir), []string{"busybox0"}}, @@ -402,11 +397,11 @@ func TestPathBuilderWithMultiple(t *testing.T) { switch test.object.(type) { case *v1.Pod: if _, ok := v.Object.(*v1.Pod); !ok || v.Name != test.expectedNames[i] || v.Namespace != "test" { - t.Errorf("unexpected info: %#v", v) + t.Errorf("unexpected info: %v", spew.Sdump(v.Object)) } case *v1.ReplicationController: if _, ok := v.Object.(*v1.ReplicationController); !ok || v.Name != test.expectedNames[i] || v.Namespace != "test" { - t.Errorf("unexpected info: %#v", v) + t.Errorf("unexpected info: %v", spew.Sdump(v.Object)) } } } @@ -459,7 +454,7 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) { func TestDirectoryBuilder(t *testing.T) { b := newDefaultBuilder(). - FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy"}}). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../../test/e2e/testing-manifests/guestbook/legacy"}}). NamespaceParam("test").DefaultNamespace() test := &testVisitor{} @@ -562,6 +557,39 @@ func TestURLBuilderRequireNamespace(t *testing.T) { } } +func TestReplaceAliases(t *testing.T) { + tests := []struct { + name string + arg string + expected string + }{ + { + name: "no-replacement", + arg: "service", + expected: "service", + }, + { + name: "all-replacement", + arg: "all", + expected: "pods,replicationcontrollers,services,statefulsets.apps,horizontalpodautoscalers.autoscaling,jobs.batch,cronjobs.batch,daemonsets.extensions,deployments.extensions,replicasets.extensions", + }, + { + name: "alias-in-comma-separated-arg", + arg: "all,secrets", + expected: "pods,replicationcontrollers,services,statefulsets.apps,horizontalpodautoscalers.autoscaling,jobs.batch,cronjobs.batch,daemonsets.extensions,deployments.extensions,replicasets.extensions,secrets", + }, + } + + b := newDefaultBuilder() + + for _, test := range tests { + replaced := b.ReplaceAliases(test.arg) + if replaced != test.expected { + t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, replaced) + } + } +} + func TestResourceByName(t *testing.T) { pods, _ := testData() b := newDefaultBuilderWith(fakeClientWith("", t, map[string]string{ @@ -589,7 +617,7 @@ func TestResourceByName(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.Resource != "pods" { + if mapping.Resource != (schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}) { t.Errorf("unexpected resource mapping: %#v", mapping) } } @@ -627,22 +655,50 @@ func TestMultipleResourceByTheSameName(t *testing.T) { } func TestRequestModifier(t *testing.T) { - var got *rest.Request - b := newDefaultBuilderWith(fakeClientWith("test", t, nil)). - NamespaceParam("foo"). - TransformRequests(func(req *rest.Request) { - got = req - }). - ResourceNames("", "services/baz"). - RequireObject(false) - - i, err := b.Do().Infos() - if err != nil { - t.Fatal(err) - } - req := i[0].Client.Get() - if got != req { - t.Fatalf("request was not received by modifier: %#v", req) + for _, tc := range []struct { + name string + f func(t *testing.T, got **rest.Request) *Builder + }{ + { + name: "simple", + f: func(t *testing.T, got **rest.Request) *Builder { + return newDefaultBuilderWith(fakeClientWith(t.Name(), t, nil)). + NamespaceParam("foo"). + TransformRequests(func(req *rest.Request) { + *got = req + }). + ResourceNames("", "services/baz"). + RequireObject(false) + }, + }, + { + name: "flatten", + f: func(t *testing.T, got **rest.Request) *Builder { + pods, _ := testData() + return newDefaultBuilderWith(fakeClientWith(t.Name(), t, map[string]string{ + "/namespaces/foo/pods": runtime.EncodeOrDie(corev1Codec, pods), + })). + NamespaceParam("foo"). + TransformRequests(func(req *rest.Request) { + *got = req + }). + ResourceTypeOrNameArgs(true, "pods"). + Flatten() + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + var got *rest.Request + b := tc.f(t, &got) + i, err := b.Do().Infos() + if err != nil { + t.Fatal(err) + } + req := i[0].Client.Get() + if got != req { + t.Fatalf("request was not received by modifier: %#v", req) + } + }) } } @@ -721,7 +777,7 @@ func TestResourceByNameWithoutRequireObject(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.GroupVersionKind.Kind != "Pod" || mapping.Resource != "pods" { + if mapping.GroupVersionKind.Kind != "Pod" || mapping.Resource != (schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}) { t.Errorf("unexpected resource mapping: %#v", mapping) } } @@ -748,7 +804,7 @@ func TestResourceByNameAndEmptySelector(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.Resource != "pods" { + if mapping.Resource != (schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}) { t.Errorf("unexpected resource mapping: %#v", mapping) } } @@ -1029,7 +1085,7 @@ func TestContinueOnErrorVisitor(t *testing.T) { func TestSingleItemImpliedObject(t *testing.T) { obj, err := newDefaultBuilder(). NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml"}}). Flatten(). Do().Object() @@ -1049,7 +1105,7 @@ func TestSingleItemImpliedObject(t *testing.T) { func TestSingleItemImpliedObjectNoExtension(t *testing.T) { obj, err := newDefaultBuilder(). NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/pod"}}). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../../test/e2e/testing-manifests/pod"}}). Flatten(). Do().Object() @@ -1067,7 +1123,7 @@ func TestSingleItemImpliedObjectNoExtension(t *testing.T) { } func TestSingleItemImpliedRootScopedObject(t *testing.T) { - node := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "test"}, Spec: v1.NodeSpec{ExternalID: "test"}} + node := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "test"}} r := streamTestObject(node) infos, err := newDefaultBuilder(). NamespaceParam("test").DefaultNamespace(). @@ -1119,7 +1175,7 @@ func TestListObject(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.Resource != "pods" { + if mapping.Resource != (schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}) { t.Errorf("unexpected resource mapping: %#v", mapping) } } @@ -1160,7 +1216,7 @@ func TestWatch(t *testing.T) { }), })). NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/redis-master-service.yaml"}}).Flatten(). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../../test/e2e/testing-manifests/guestbook/redis-master-service.yaml"}}).Flatten(). Do().Watch("12") if err != nil { @@ -1187,8 +1243,8 @@ func TestWatch(t *testing.T) { func TestWatchMultipleError(t *testing.T) { _, err := newDefaultBuilder(). NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).Flatten(). - FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).Flatten(). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml"}}).Flatten(). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml"}}).Flatten(). Do().Watch("") if err == nil { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/client.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/client.go new file mode 100644 index 000000000..46380207f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/client.go @@ -0,0 +1,58 @@ +/* +Copyright 2018 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 resource + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/rest" +) + +// TODO require negotiatedSerializer. leaving it optional lets us plumb current behavior and deal with the difference after major plumbing is complete +func (clientConfigFn ClientConfigFunc) clientForGroupVersion(gv schema.GroupVersion, negotiatedSerializer runtime.NegotiatedSerializer) (RESTClient, error) { + cfg, err := clientConfigFn() + if err != nil { + return nil, err + } + if negotiatedSerializer != nil { + cfg.ContentConfig.NegotiatedSerializer = negotiatedSerializer + } + cfg.GroupVersion = &gv + if len(gv.Group) == 0 { + cfg.APIPath = "/api" + } else { + cfg.APIPath = "/apis" + } + + return rest.RESTClientFor(cfg) +} + +func (clientConfigFn ClientConfigFunc) unstructuredClientForGroupVersion(gv schema.GroupVersion) (RESTClient, error) { + cfg, err := clientConfigFn() + if err != nil { + return nil, err + } + cfg.ContentConfig = UnstructuredPlusDefaultContentConfig() + cfg.GroupVersion = &gv + if len(gv.Group) == 0 { + cfg.APIPath = "/api" + } else { + cfg.APIPath = "/apis" + } + + return rest.RESTClientFor(cfg) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/doc.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/doc.go new file mode 100644 index 000000000..a0e22e7cf --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/doc.go @@ -0,0 +1,24 @@ +/* +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 resource assists clients in dealing with RESTful objects that match the +// Kubernetes API conventions. The Helper object provides simple CRUD operations +// on resources. The Visitor interface makes it easy to deal with multiple resources +// in bulk for retrieval and operation. The Builder object simplifies converting +// standard command line arguments and parameters into a Visitor that can iterate +// over all of the identified resources, whether on the server or on the local +// filesystem. +package resource diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/fake.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/fake.go new file mode 100644 index 000000000..276c343e2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/fake.go @@ -0,0 +1,40 @@ +/* +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 resource + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/restmapper" +) + +// FakeCategoryExpander is for testing only +var FakeCategoryExpander restmapper.CategoryExpander = restmapper.SimpleCategoryExpander{ + Expansions: map[string][]schema.GroupResource{ + "all": { + {Group: "", Resource: "pods"}, + {Group: "", Resource: "replicationcontrollers"}, + {Group: "", Resource: "services"}, + {Group: "apps", Resource: "statefulsets"}, + {Group: "autoscaling", Resource: "horizontalpodautoscalers"}, + {Group: "batch", Resource: "jobs"}, + {Group: "batch", Resource: "cronjobs"}, + {Group: "extensions", Resource: "daemonsets"}, + {Group: "extensions", Resource: "deployments"}, + {Group: "extensions", Resource: "replicasets"}, + }, + }, +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/helper.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/helper.go similarity index 89% rename from vendor/k8s.io/kubernetes/pkg/kubectl/resource/helper.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/helper.go index e5ca36221..52a4057e0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/helper.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/helper.go @@ -27,6 +27,8 @@ import ( "k8s.io/apimachinery/pkg/watch" ) +var metadataAccessor = meta.NewAccessor() + // Helper provides methods for retrieving or mutating a RESTful // resource. type Helper struct { @@ -34,9 +36,6 @@ type Helper struct { Resource string // A RESTClient capable of mutating this resource. RESTClient RESTClient - // An interface for reading or writing the resource version of this - // type. - Versioner runtime.ResourceVersioner // True if the resource type is scoped to namespaces NamespaceScoped bool } @@ -44,9 +43,8 @@ type Helper struct { // NewHelper creates a Helper from a ResourceMapping func NewHelper(client RESTClient, mapping *meta.RESTMapping) *Helper { return &Helper{ - Resource: mapping.Resource, + Resource: mapping.Resource.Resource, RESTClient: client, - Versioner: mapping.MetadataAccessor, NamespaceScoped: mapping.Scope.Name() == meta.RESTScopeNameNamespace, } } @@ -96,30 +94,30 @@ func (m *Helper) WatchSingle(namespace, name, resourceVersion string) (watch.Int Watch() } -func (m *Helper) Delete(namespace, name string) error { +func (m *Helper) Delete(namespace, name string) (runtime.Object, error) { return m.DeleteWithOptions(namespace, name, nil) } -func (m *Helper) DeleteWithOptions(namespace, name string, options *metav1.DeleteOptions) error { +func (m *Helper) DeleteWithOptions(namespace, name string, options *metav1.DeleteOptions) (runtime.Object, error) { return m.RESTClient.Delete(). NamespaceIfScoped(namespace, m.NamespaceScoped). Resource(m.Resource). Name(name). Body(options). Do(). - Error() + Get() } func (m *Helper) Create(namespace string, modify bool, obj runtime.Object) (runtime.Object, error) { if modify { // Attempt to version the object based on client logic. - version, err := m.Versioner.ResourceVersion(obj) + version, err := metadataAccessor.ResourceVersion(obj) if err != nil { // We don't know how to clear the version on this object, so send it to the server as is return m.createResource(m.RESTClient, m.Resource, namespace, obj) } if version != "" { - if err := m.Versioner.SetResourceVersion(obj, ""); err != nil { + if err := metadataAccessor.SetResourceVersion(obj, ""); err != nil { return nil, err } } @@ -145,7 +143,7 @@ func (m *Helper) Replace(namespace, name string, overwrite bool, obj runtime.Obj c := m.RESTClient // Attempt to version the object based on client logic. - version, err := m.Versioner.ResourceVersion(obj) + version, err := metadataAccessor.ResourceVersion(obj) if err != nil { // We don't know how to version this object, so send it to the server as is return m.replaceResource(c, m.Resource, namespace, name, obj) @@ -157,11 +155,11 @@ func (m *Helper) Replace(namespace, name string, overwrite bool, obj runtime.Obj // The object does not exist, but we want it to be created return m.replaceResource(c, m.Resource, namespace, name, obj) } - serverVersion, err := m.Versioner.ResourceVersion(serverObj) + serverVersion, err := metadataAccessor.ResourceVersion(serverObj) if err != nil { return nil, err } - if err := m.Versioner.SetResourceVersion(obj, serverVersion); err != nil { + if err := metadataAccessor.SetResourceVersion(obj, serverVersion); err != nil { return nil, err } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/helper_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/helper_test.go similarity index 99% rename from vendor/k8s.io/kubernetes/pkg/kubectl/resource/helper_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/helper_test.go index 96a2d7789..5f8a6e3e8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/helper_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/helper_test.go @@ -26,13 +26,15 @@ import ( "strings" "testing" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest/fake" + + // TODO we need to remove this linkage and create our own scheme + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes/scheme" ) func objBody(obj runtime.Object) io.ReadCloser { @@ -122,7 +124,7 @@ func TestHelperDelete(t *testing.T) { RESTClient: client, NamespaceScoped: true, } - err := modifier.Delete("bar", "foo") + _, err := modifier.Delete("bar", "foo") if (err != nil) != test.Err { t.Errorf("unexpected error: %t %v", test.Err, err) } @@ -211,7 +213,6 @@ func TestHelperCreate(t *testing.T) { } modifier := &Helper{ RESTClient: client, - Versioner: metaAccessor, NamespaceScoped: true, } _, err := modifier.Create("bar", test.Modify, test.Object) @@ -568,7 +569,6 @@ func TestHelperReplace(t *testing.T) { } modifier := &Helper{ RESTClient: client, - Versioner: metaAccessor, NamespaceScoped: test.NamespaceScoped, } _, err := modifier.Replace(test.Namespace, "foo", test.Overwrite, test.Object) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/interfaces.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/interfaces.go new file mode 100644 index 000000000..508d4d6b5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/interfaces.go @@ -0,0 +1,100 @@ +/* +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 resource + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" +) + +type RESTClientGetter interface { + ToRESTConfig() (*rest.Config, error) + ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) + ToRESTMapper() (meta.RESTMapper, error) +} + +type ClientConfigFunc func() (*rest.Config, error) + +// RESTClient is a client helper for dealing with RESTful resources +// in a generic way. +type RESTClient interface { + Get() *rest.Request + Post() *rest.Request + Patch(types.PatchType) *rest.Request + Delete() *rest.Request + Put() *rest.Request +} + +// RequestTransform is a function that is given a chance to modify the outgoing request. +type RequestTransform func(*rest.Request) + +// NewClientWithOptions wraps the provided RESTClient and invokes each transform on each +// newly created request. +func NewClientWithOptions(c RESTClient, transforms ...RequestTransform) RESTClient { + if len(transforms) == 0 { + return c + } + return &clientOptions{c: c, transforms: transforms} +} + +type clientOptions struct { + c RESTClient + transforms []RequestTransform +} + +func (c *clientOptions) modify(req *rest.Request) *rest.Request { + for _, transform := range c.transforms { + transform(req) + } + return req +} + +func (c *clientOptions) Get() *rest.Request { + return c.modify(c.c.Get()) +} + +func (c *clientOptions) Post() *rest.Request { + return c.modify(c.c.Post()) +} +func (c *clientOptions) Patch(t types.PatchType) *rest.Request { + return c.modify(c.c.Patch(t)) +} +func (c *clientOptions) Delete() *rest.Request { + return c.modify(c.c.Delete()) +} +func (c *clientOptions) Put() *rest.Request { + return c.modify(c.c.Put()) +} + +// ContentValidator is an interface that knows how to validate an API object serialized to a byte array. +type ContentValidator interface { + ValidateBytes(data []byte) error +} + +// Visitor lets clients walk a list of resources. +type Visitor interface { + Visit(VisitorFunc) error +} + +// VisitorFunc implements the Visitor interface for a matching function. +// If there was a problem walking a list of resources, the incoming error +// will describe the problem and the function can decide how to handle that error. +// A nil returned indicates to accept an error to continue loops even when errors happen. +// This is useful for ignoring certain kinds of errors or aggregating errors in some way. +type VisitorFunc func(*Info, error) error diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/mapper.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/mapper.go new file mode 100644 index 000000000..0453e5423 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/mapper.go @@ -0,0 +1,154 @@ +/* +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 resource + +import ( + "fmt" + "reflect" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// Mapper is a convenience struct for holding references to the interfaces +// needed to create Info for arbitrary objects. +type mapper struct { + // localFn indicates the call can't make server requests + localFn func() bool + + restMapper meta.RESTMapper + clientFn func(version schema.GroupVersion) (RESTClient, error) + decoder runtime.Decoder +} + +// InfoForData creates an Info object for the given data. An error is returned +// if any of the decoding or client lookup steps fail. Name and namespace will be +// set into Info if the mapping's MetadataAccessor can retrieve them. +func (m *mapper) infoForData(data []byte, source string) (*Info, error) { + obj, gvk, err := m.decoder.Decode(data, nil, nil) + if err != nil { + return nil, fmt.Errorf("unable to decode %q: %v", source, err) + } + + name, _ := metadataAccessor.Name(obj) + namespace, _ := metadataAccessor.Namespace(obj) + resourceVersion, _ := metadataAccessor.ResourceVersion(obj) + + ret := &Info{ + Source: source, + Namespace: namespace, + Name: name, + ResourceVersion: resourceVersion, + + Object: obj, + } + + if m.localFn == nil || !m.localFn() { + mapping, err := m.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, fmt.Errorf("unable to recognize %q: %v", source, err) + } + ret.Mapping = mapping + + client, err := m.clientFn(gvk.GroupVersion()) + if err != nil { + return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err) + } + ret.Client = client + } + + return ret, nil +} + +// InfoForObject creates an Info object for the given Object. An error is returned +// if the object cannot be introspected. Name and namespace will be set into Info +// if the mapping's MetadataAccessor can retrieve them. +func (m *mapper) infoForObject(obj runtime.Object, typer runtime.ObjectTyper, preferredGVKs []schema.GroupVersionKind) (*Info, error) { + groupVersionKinds, _, err := typer.ObjectKinds(obj) + if err != nil { + return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err) + } + + gvk := groupVersionKinds[0] + if len(groupVersionKinds) > 1 && len(preferredGVKs) > 0 { + gvk = preferredObjectKind(groupVersionKinds, preferredGVKs) + } + + name, _ := metadataAccessor.Name(obj) + namespace, _ := metadataAccessor.Namespace(obj) + resourceVersion, _ := metadataAccessor.ResourceVersion(obj) + ret := &Info{ + Namespace: namespace, + Name: name, + ResourceVersion: resourceVersion, + + Object: obj, + } + + if m.localFn == nil || !m.localFn() { + mapping, err := m.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, fmt.Errorf("unable to recognize %v", err) + } + ret.Mapping = mapping + + client, err := m.clientFn(gvk.GroupVersion()) + if err != nil { + return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err) + } + ret.Client = client + } + + return ret, nil +} + +// preferredObjectKind picks the possibility that most closely matches the priority list in this order: +// GroupVersionKind matches (exact match) +// GroupKind matches +// Group matches +func preferredObjectKind(possibilities []schema.GroupVersionKind, preferences []schema.GroupVersionKind) schema.GroupVersionKind { + // Exact match + for _, priority := range preferences { + for _, possibility := range possibilities { + if possibility == priority { + return possibility + } + } + } + + // GroupKind match + for _, priority := range preferences { + for _, possibility := range possibilities { + if possibility.GroupKind() == priority.GroupKind() { + return possibility + } + } + } + + // Group match + for _, priority := range preferences { + for _, possibility := range possibilities { + if possibility.Group == priority.Group { + return possibility + } + } + } + + // Just pick the first + return possibilities[0] +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/result.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/result.go similarity index 97% rename from vendor/k8s.io/kubernetes/pkg/kubectl/resource/result.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/result.go index 611471ca7..b8722afe6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/result.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/result.go @@ -24,6 +24,7 @@ import ( "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" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/watch" @@ -41,7 +42,7 @@ type Result struct { singleItemImplied bool targetsSingleItems bool - mapper *Mapper + mapper *mapper ignoreErrors []utilerrors.Matcher // populated by a call to Infos @@ -76,7 +77,7 @@ func (r *Result) IgnoreErrors(fns ...ErrMatchFunc) *Result { } // Mapper returns a copy of the builder's mapper. -func (r *Result) Mapper() *Mapper { +func (r *Result) Mapper() *mapper { return r.mapper } @@ -196,7 +197,7 @@ func (r *Result) ResourceMapping() (*meta.RESTMapping, error) { if r.err != nil { return nil, r.err } - mappings := map[string]*meta.RESTMapping{} + mappings := map[schema.GroupVersionResource]*meta.RESTMapping{} for i := range r.sources { m, ok := r.sources[i].(ResourceMapping) if !ok { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/scheme.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/scheme.go new file mode 100644 index 000000000..fef6edfc1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/scheme.go @@ -0,0 +1,79 @@ +/* +Copyright 2018 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 resource + +import ( + "encoding/json" + "io" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" +) + +// dynamicCodec is a codec that wraps the standard unstructured codec +// with special handling for Status objects. +// Deprecated only used by test code and its wrong +type dynamicCodec struct{} + +func (dynamicCodec) Decode(data []byte, gvk *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { + obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(data, gvk, obj) + if err != nil { + return nil, nil, err + } + + if _, ok := obj.(*metav1.Status); !ok && strings.ToLower(gvk.Kind) == "status" { + obj = &metav1.Status{} + err := json.Unmarshal(data, obj) + if err != nil { + return nil, nil, err + } + } + + return obj, gvk, nil +} + +func (dynamicCodec) Encode(obj runtime.Object, w io.Writer) error { + return unstructured.UnstructuredJSONScheme.Encode(obj, w) +} + +// ContentConfig returns a rest.ContentConfig for dynamic types. It includes enough codecs to act as a "normal" +// serializer for the rest.client with options, status and the like. +func UnstructuredPlusDefaultContentConfig() rest.ContentConfig { + var jsonInfo runtime.SerializerInfo + // TODO: scheme.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need + // to talk to a kubernetes server + for _, info := range scheme.Codecs.SupportedMediaTypes() { + if info.MediaType == runtime.ContentTypeJSON { + jsonInfo = info + break + } + } + + jsonInfo.Serializer = dynamicCodec{} + jsonInfo.PrettySerializer = nil + return rest.ContentConfig{ + AcceptContentTypes: runtime.ContentTypeJSON, + ContentType: runtime.ContentTypeJSON, + NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo), + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/selector.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/selector.go similarity index 96% rename from vendor/k8s.io/kubernetes/pkg/kubectl/resource/selector.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/selector.go index 66e13ad08..f36508bd4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/selector.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/selector.go @@ -88,9 +88,8 @@ func (r *Selector) Visit(fn VisitorFunc) error { } return err } - accessor := r.Mapping.MetadataAccessor - resourceVersion, _ := accessor.ResourceVersion(list) - nextContinueToken, _ := accessor.Continue(list) + resourceVersion, _ := metadataAccessor.ResourceVersion(list) + nextContinueToken, _ := metadataAccessor.Continue(list) info := &Info{ Client: r.Client, Mapping: r.Mapping, diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/visitor.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/visitor.go similarity index 82% rename from vendor/k8s.io/kubernetes/pkg/kubectl/resource/visitor.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/visitor.go index 554fa4a66..e83d02aa4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/visitor.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/visitor.go @@ -32,14 +32,12 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/watch" - "k8s.io/kubernetes/pkg/kubectl/validation" ) const ( @@ -47,18 +45,6 @@ const ( stopValidateMessage = "if you choose to ignore these errors, turn validation off with --validate=false" ) -// Visitor lets clients walk a list of resources. -type Visitor interface { - Visit(VisitorFunc) error -} - -// VisitorFunc implements the Visitor interface for a matching function. -// If there was a problem walking a list of resources, the incoming error -// will describe the problem and the function can decide how to handle that error. -// A nil returned indicates to accept an error to continue loops even when errors happen. -// This is useful for ignoring certain kinds of errors or aggregating errors in some way. -type VisitorFunc func(*Info, error) error - // Watchable describes a resource that can be watched for changes that occur on the server, // beginning after the provided resource version. type Watchable interface { @@ -74,10 +60,11 @@ type ResourceMapping interface { // Info contains temporary info to execute a REST call, or show the results // of an already completed REST call. type Info struct { + // Client will only be present if this builder was not local Client RESTClient - // Mapping may be nil if the object has no available metadata, but is still parseable - // from disk. + // Mapping will only be present if this builder was not local Mapping *meta.RESTMapping + // Namespace will be set if the object is namespaced and has a specified value. Namespace string Name string @@ -118,7 +105,7 @@ func (i *Info) Get() (err error) { return err } i.Object = obj - i.ResourceVersion, _ = i.Mapping.MetadataAccessor.ResourceVersion(obj) + i.ResourceVersion, _ = metadataAccessor.ResourceVersion(obj) return nil } @@ -126,7 +113,7 @@ func (i *Info) Get() (err error) { // the Object will be updated even if name, namespace, or resourceVersion // attributes cannot be loaded from the object. func (i *Info) Refresh(obj runtime.Object, ignoreError bool) error { - name, err := i.Mapping.MetadataAccessor.Name(obj) + name, err := metadataAccessor.Name(obj) if err != nil { if !ignoreError { return err @@ -134,7 +121,7 @@ func (i *Info) Refresh(obj runtime.Object, ignoreError bool) error { } else { i.Name = name } - namespace, err := i.Mapping.MetadataAccessor.Namespace(obj) + namespace, err := metadataAccessor.Namespace(obj) if err != nil { if !ignoreError { return err @@ -142,7 +129,7 @@ func (i *Info) Refresh(obj runtime.Object, ignoreError bool) error { } else { i.Namespace = namespace } - version, err := i.Mapping.MetadataAccessor.ResourceVersion(obj) + version, err := metadataAccessor.ResourceVersion(obj) if err != nil { if !ignoreError { return err @@ -154,6 +141,17 @@ func (i *Info) Refresh(obj runtime.Object, ignoreError bool) error { return nil } +// String returns the general purpose string representation +func (i *Info) String() string { + basicInfo := fmt.Sprintf("Name: %q, Namespace: %q\nObject: %+q", i.Name, i.Namespace, i.Object) + if i.Mapping != nil { + mappingInfo := fmt.Sprintf("Resource: %q, GroupVersionKind: %q", i.Mapping.Resource.String(), + i.Mapping.GroupVersionKind.String()) + return fmt.Sprint(mappingInfo, "\n", basicInfo) + } + return basicInfo +} + // Namespaced returns true if the object belongs to a namespace func (i *Info) Namespaced() bool { return i.Mapping != nil && i.Mapping.Scope.Name() == meta.RESTScopeNameNamespace @@ -169,61 +167,6 @@ func (i *Info) ResourceMapping() *meta.RESTMapping { return i.Mapping } -// Internal attempts to convert the provided object to an internal type or returns an error. -func (i *Info) Internal() (runtime.Object, error) { - return i.Mapping.ConvertToVersion(i.Object, i.Mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion()) -} - -// AsInternal returns the object in internal form if possible, or i.Object if it cannot be -// converted. -func (i *Info) AsInternal() runtime.Object { - if obj, err := i.Internal(); err == nil { - return obj - } - return i.Object -} - -// Versioned returns the object as a Go type in the mapping's version or returns an error. -func (i *Info) Versioned() (runtime.Object, error) { - return i.Mapping.ConvertToVersion(i.Object, i.Mapping.GroupVersionKind.GroupVersion()) -} - -// AsVersioned returns the object as a Go object in the external form if possible (matching the -// group version kind of the mapping, or i.Object if it cannot be converted. -func (i *Info) AsVersioned() runtime.Object { - if obj, err := i.Versioned(); err == nil { - return obj - } - return i.Object -} - -// Unstructured returns the current object in unstructured form (as a runtime.Unstructured) -func (i *Info) Unstructured() (runtime.Unstructured, error) { - switch t := i.Object.(type) { - case runtime.Unstructured: - return t, nil - case *runtime.Unknown: - gvk := i.Mapping.GroupVersionKind - out, _, err := unstructured.UnstructuredJSONScheme.Decode(t.Raw, &gvk, nil) - return out.(runtime.Unstructured), err - default: - out := &unstructured.Unstructured{} - if err := i.Mapping.Convert(i.Object, out, nil); err != nil { - return nil, err - } - return out, nil - } -} - -// AsUnstructured returns the object as a Go object in external form as a runtime.Unstructured -// (map of JSON equivalent values) or as i.Object if it cannot be converted. -func (i *Info) AsUnstructured() runtime.Object { - if out, err := i.Unstructured(); err == nil { - return out - } - return i.Object -} - // VisitorList implements Visit for the sub visitors it contains. The first error // returned from a child Visitor will terminate iteration. type VisitorList []Visitor @@ -263,7 +206,7 @@ func (l EagerVisitorList) Visit(fn VisitorFunc) error { return utilerrors.NewAggregate(errs) } -func ValidateSchema(data []byte, schema validation.Schema) error { +func ValidateSchema(data []byte, schema ContentValidator) error { if schema == nil { return nil } @@ -414,18 +357,19 @@ func (v ContinueOnErrorVisitor) Visit(fn VisitorFunc) error { // the visit. // TODO: allow errors to be aggregated? type FlattenListVisitor struct { - Visitor - *Mapper + visitor Visitor + typer runtime.ObjectTyper + mapper *mapper } // NewFlattenListVisitor creates a visitor that will expand list style runtime.Objects // into individual items and then visit them individually. -func NewFlattenListVisitor(v Visitor, mapper *Mapper) Visitor { - return FlattenListVisitor{v, mapper} +func NewFlattenListVisitor(v Visitor, typer runtime.ObjectTyper, mapper *mapper) Visitor { + return FlattenListVisitor{v, typer, mapper} } func (v FlattenListVisitor) Visit(fn VisitorFunc) error { - return v.Visitor.Visit(func(info *Info, err error) error { + return v.visitor.Visit(func(info *Info, err error) error { if err != nil { return err } @@ -436,7 +380,7 @@ func (v FlattenListVisitor) Visit(fn VisitorFunc) error { if err != nil { return fn(info, nil) } - if errs := runtime.DecodeList(items, v.Mapper.Decoder); len(errs) > 0 { + if errs := runtime.DecodeList(items, v.mapper.decoder); len(errs) > 0 { return utilerrors.NewAggregate(errs) } @@ -447,7 +391,7 @@ func (v FlattenListVisitor) Visit(fn VisitorFunc) error { } for i := range items { - item, err := v.InfoForObject(items[i], preferredGVKs) + item, err := v.mapper.infoForObject(items[i], v.typer, preferredGVKs) if err != nil { return err } @@ -476,7 +420,7 @@ func ignoreFile(path string, extensions []string) bool { } // FileVisitorForSTDIN return a special FileVisitor just for STDIN -func FileVisitorForSTDIN(mapper *Mapper, schema validation.Schema) Visitor { +func FileVisitorForSTDIN(mapper *mapper, schema ContentValidator) Visitor { return &FileVisitor{ Path: constSTDINstr, StreamVisitor: NewStreamVisitor(nil, mapper, constSTDINstr, schema), @@ -486,7 +430,7 @@ func FileVisitorForSTDIN(mapper *Mapper, schema validation.Schema) Visitor { // ExpandPathsToFileVisitors will return a slice of FileVisitors that will handle files from the provided path. // After FileVisitors open the files, they will pass an io.Reader to a StreamVisitor to do the reading. (stdin // is also taken care of). Paths argument also accepts a single file, and will return a single visitor -func ExpandPathsToFileVisitors(mapper *Mapper, paths string, recursive bool, extensions []string, schema validation.Schema) ([]Visitor, error) { +func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, extensions []string, schema ContentValidator) ([]Visitor, error) { var visitors []Visitor err := filepath.Walk(paths, func(path string, fi os.FileInfo, err error) error { if err != nil { @@ -553,17 +497,17 @@ func (v *FileVisitor) Visit(fn VisitorFunc) error { // a stream decoder method on runtime.Codec to properly handle this. type StreamVisitor struct { io.Reader - *Mapper + *mapper Source string - Schema validation.Schema + Schema ContentValidator } // NewStreamVisitor is a helper function that is useful when we want to change the fields of the struct but keep calls the same. -func NewStreamVisitor(r io.Reader, mapper *Mapper, source string, schema validation.Schema) *StreamVisitor { +func NewStreamVisitor(r io.Reader, mapper *mapper, source string, schema ContentValidator) *StreamVisitor { return &StreamVisitor{ Reader: r, - Mapper: mapper, + mapper: mapper, Source: source, Schema: schema, } @@ -578,7 +522,7 @@ func (v *StreamVisitor) Visit(fn VisitorFunc) error { if err == io.EOF { return nil } - return err + return fmt.Errorf("error parsing %s: %v", v.Source, err) } // TODO: This needs to be able to handle object in other encodings and schemas. ext.Raw = bytes.TrimSpace(ext.Raw) @@ -588,7 +532,7 @@ func (v *StreamVisitor) Visit(fn VisitorFunc) error { if err := ValidateSchema(ext.Raw, v.Schema); err != nil { return fmt.Errorf("error validating %q: %v", v.Source, err) } - info, err := v.InfoForData(ext.Raw, v.Source) + info, err := v.infoForData(ext.Raw, v.Source) if err != nil { if fnErr := fn(info, err); fnErr != nil { return fnErr @@ -606,7 +550,7 @@ func UpdateObjectNamespace(info *Info, err error) error { return err } if info.Object != nil { - return info.Mapping.MetadataAccessor.SetNamespace(info.Object, info.Namespace) + return metadataAccessor.SetNamespace(info.Object, info.Namespace) } return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/visitor_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/visitor_test.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubectl/resource/visitor_test.go rename to vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource/visitor_test.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/template_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/template_flags.go new file mode 100644 index 000000000..f090f0976 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/template_flags.go @@ -0,0 +1,132 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "fmt" + "io/ioutil" + "strings" + + "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" +) + +// templates are logically optional for specifying a format. +// this allows a user to specify a template format value +// as --output=go-template= +var templateFormats = map[string]bool{ + "template": true, + "go-template": true, + "go-template-file": true, + "templatefile": true, +} + +// GoTemplatePrintFlags provides default flags necessary for template printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type GoTemplatePrintFlags struct { + // indicates if it is OK to ignore missing keys for rendering + // an output template. + AllowMissingKeys *bool + TemplateArgument *string +} + +func (f *GoTemplatePrintFlags) AllowedFormats() []string { + formats := make([]string, 0, len(templateFormats)) + for format := range templateFormats { + formats = append(formats, format) + } + return formats +} + +// ToPrinter receives an templateFormat and returns a printer capable of +// handling --template format printing. +// Returns false if the specified templateFormat does not match a template format. +func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (printers.ResourcePrinter, error) { + if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 { + return nil, NoCompatiblePrinterError{Options: f, OutputFormat: &templateFormat} + } + + templateValue := "" + + if f.TemplateArgument == nil || len(*f.TemplateArgument) == 0 { + for format := range templateFormats { + format = format + "=" + if strings.HasPrefix(templateFormat, format) { + templateValue = templateFormat[len(format):] + templateFormat = format[:len(format)-1] + break + } + } + } else { + templateValue = *f.TemplateArgument + } + + if _, supportedFormat := templateFormats[templateFormat]; !supportedFormat { + return nil, NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()} + } + + if len(templateValue) == 0 { + return nil, fmt.Errorf("template format specified but no template given") + } + + if templateFormat == "templatefile" || templateFormat == "go-template-file" { + data, err := ioutil.ReadFile(templateValue) + if err != nil { + return nil, fmt.Errorf("error reading --template %s, %v\n", templateValue, err) + } + + templateValue = string(data) + } + + p, err := printers.NewGoTemplatePrinter([]byte(templateValue)) + if err != nil { + return nil, fmt.Errorf("error parsing template %s, %v\n", templateValue, err) + } + + allowMissingKeys := true + if f.AllowMissingKeys != nil { + allowMissingKeys = *f.AllowMissingKeys + } + + p.AllowMissingKeys(allowMissingKeys) + return p, nil +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to template printing to it +func (f *GoTemplatePrintFlags) AddFlags(c *cobra.Command) { + if f.TemplateArgument != nil { + c.Flags().StringVar(f.TemplateArgument, "template", *f.TemplateArgument, "Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].") + c.MarkFlagFilename("template") + } + if f.AllowMissingKeys != nil { + c.Flags().BoolVar(f.AllowMissingKeys, "allow-missing-template-keys", *f.AllowMissingKeys, "If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.") + } +} + +// NewGoTemplatePrintFlags returns flags associated with +// --template printing, with default values set. +func NewGoTemplatePrintFlags() *GoTemplatePrintFlags { + allowMissingKeysPtr := true + templateValuePtr := "" + + return &GoTemplatePrintFlags{ + TemplateArgument: &templateValuePtr, + AllowMissingKeys: &allowMissingKeysPtr, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/template_flags_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/template_flags_test.go new file mode 100644 index 000000000..e1f5ae60e --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/template_flags_test.go @@ -0,0 +1,205 @@ +/* +Copyright 2018 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 genericclioptions + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "strings" + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestPrinterSupportsExpectedTemplateFormats(t *testing.T) { + testObject := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + + templateFile, err := ioutil.TempFile("", "printers_jsonpath_flags") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + defer func(tempFile *os.File) { + tempFile.Close() + os.Remove(tempFile.Name()) + }(templateFile) + + fmt.Fprintf(templateFile, "{{ .metadata.name }}") + + testCases := []struct { + name string + outputFormat string + templateArg string + expectedError string + expectedParseError string + expectedOutput string + expectNoMatch bool + }{ + { + name: "valid output format also containing the template argument succeeds", + outputFormat: "go-template={{ .metadata.name }}", + expectedOutput: "foo", + }, + { + name: "valid output format and no template argument results in an error", + outputFormat: "template", + expectedError: "template format specified but no template given", + }, + { + name: "valid output format and template argument succeeds", + outputFormat: "go-template", + templateArg: "{{ .metadata.name }}", + expectedOutput: "foo", + }, + { + name: "Go-template file should match, and successfully return correct value", + outputFormat: "go-template-file", + templateArg: templateFile.Name(), + expectedOutput: "foo", + }, + { + name: "valid output format and invalid template argument results in the templateArg contents as the output", + outputFormat: "go-template", + templateArg: "invalid", + expectedOutput: "invalid", + }, + { + name: "no printer is matched on an invalid outputFormat", + outputFormat: "invalid", + expectNoMatch: true, + }, + { + name: "go-template printer should not match on any other format supported by another printer", + outputFormat: "jsonpath", + expectNoMatch: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + templateArg := &tc.templateArg + if len(tc.templateArg) == 0 { + templateArg = nil + } + + printFlags := GoTemplatePrintFlags{ + TemplateArgument: templateArg, + } + + p, err := printFlags.ToPrinter(tc.outputFormat) + if tc.expectNoMatch { + if !IsNoCompatiblePrinterError(err) { + t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) + } + return + } + if IsNoCompatiblePrinterError(err) { + t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) + } + + if len(tc.expectedError) > 0 { + if err == nil || !strings.Contains(err.Error(), tc.expectedError) { + t.Errorf("expecting error %q, got %v", tc.expectedError, err) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + out := bytes.NewBuffer([]byte{}) + err = p.PrintObj(testObject, out) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if len(out.String()) != len(tc.expectedOutput) { + t.Errorf("unexpected output: expecting %q, got %q", tc.expectedOutput, out.String()) + } + }) + } +} + +func TestTemplatePrinterDefaultsAllowMissingKeysToTrue(t *testing.T) { + testObject := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + + allowMissingKeys := false + + testCases := []struct { + name string + templateArg string + expectedOutput string + expectedError string + allowMissingKeys *bool + }{ + { + name: "existing field does not error and returns expected value", + templateArg: "{{ .metadata.name }}", + expectedOutput: "foo", + allowMissingKeys: &allowMissingKeys, + }, + { + name: "missing field does not error and returns no value since missing keys are allowed by default", + templateArg: "{{ .metadata.missing }}", + expectedOutput: "", + allowMissingKeys: nil, + }, + { + name: "missing field returns expected error if field is missing and allowMissingKeys is explicitly set to false", + templateArg: "{{ .metadata.missing }}", + expectedError: "error executing template", + allowMissingKeys: &allowMissingKeys, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + printFlags := GoTemplatePrintFlags{ + TemplateArgument: &tc.templateArg, + AllowMissingKeys: tc.allowMissingKeys, + } + + outputFormat := "template" + p, err := printFlags.ToPrinter(outputFormat) + if IsNoCompatiblePrinterError(err) { + t.Fatalf("expected to match template printer for output format %q", outputFormat) + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + out := bytes.NewBuffer([]byte{}) + err = p.PrintObj(testObject, out) + + if len(tc.expectedError) > 0 { + if err == nil || !strings.Contains(err.Error(), tc.expectedError) { + t.Errorf("expecting error %q, got %v", tc.expectedError, err) + } + return + } + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if len(out.String()) != len(tc.expectedOutput) { + t.Errorf("unexpected output: expecting %q, got %q", tc.expectedOutput, out.String()) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/history.go b/vendor/k8s.io/kubernetes/pkg/kubectl/history.go index 9344e194a..4fcd4e526 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/history.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/history.go @@ -102,12 +102,12 @@ type DeploymentHistoryViewer struct { // ViewHistory returns a revision-to-replicaset map as the revision history of a deployment // TODO: this should be a describer func (h *DeploymentHistoryViewer) ViewHistory(namespace, name string, revision int64) (string, error) { - versionedExtensionsClient := h.c.ExtensionsV1beta1() - deployment, err := versionedExtensionsClient.Deployments(namespace).Get(name, metav1.GetOptions{}) + versionedAppsClient := h.c.AppsV1() + deployment, err := versionedAppsClient.Deployments(namespace).Get(name, metav1.GetOptions{}) if err != nil { return "", fmt.Errorf("failed to retrieve deployment %s: %v", name, err) } - _, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, versionedExtensionsClient) + _, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, versionedAppsClient) if err != nil { return "", fmt.Errorf("failed to retrieve replica sets from deployment %s: %v", name, err) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/kubectl.go b/vendor/k8s.io/kubernetes/pkg/kubectl/kubectl.go deleted file mode 100644 index f13cbc66c..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/kubectl.go +++ /dev/null @@ -1,183 +0,0 @@ -/* -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. -*/ - -// A set of common functions needed by cmd/kubectl and pkg/kubectl packages. -package kubectl - -import ( - "strings" - - "k8s.io/apimachinery/pkg/runtime/schema" -) - -type NamespaceInfo struct { - Namespace string -} - -// ResourceShortcuts represents a structure that holds the information how to -// transition from resource's shortcut to its full name. -type ResourceShortcuts struct { - ShortForm schema.GroupResource - LongForm schema.GroupResource -} - -// ResourcesShortcutStatic is the list of short names to their expanded names. -// Note that the list is ordered by group. -var ResourcesShortcutStatic = []ResourceShortcuts{ - // If you add an entry here, please also take a look at pkg/kubectl/cmd/cmd.go - // and add an entry to valid_resources when appropriate. - { - ShortForm: schema.GroupResource{Resource: "cm"}, - LongForm: schema.GroupResource{Resource: "configmaps"}, - }, - { - ShortForm: schema.GroupResource{Resource: "cs"}, - LongForm: schema.GroupResource{Resource: "componentstatuses"}, - }, - { - ShortForm: schema.GroupResource{Resource: "ep"}, - LongForm: schema.GroupResource{Resource: "endpoints"}, - }, - { - ShortForm: schema.GroupResource{Resource: "ev"}, - LongForm: schema.GroupResource{Resource: "events"}, - }, - { - ShortForm: schema.GroupResource{Resource: "limits"}, - LongForm: schema.GroupResource{Resource: "limitranges"}, - }, - { - ShortForm: schema.GroupResource{Resource: "no"}, - LongForm: schema.GroupResource{Resource: "nodes"}, - }, - { - ShortForm: schema.GroupResource{Resource: "ns"}, - LongForm: schema.GroupResource{Resource: "namespaces"}, - }, - { - ShortForm: schema.GroupResource{Resource: "po"}, - LongForm: schema.GroupResource{Resource: "pods"}, - }, - { - ShortForm: schema.GroupResource{Resource: "pvc"}, - LongForm: schema.GroupResource{Resource: "persistentvolumeclaims"}, - }, - { - ShortForm: schema.GroupResource{Resource: "pv"}, - LongForm: schema.GroupResource{Resource: "persistentvolumes"}, - }, - { - ShortForm: schema.GroupResource{Resource: "quota"}, - LongForm: schema.GroupResource{Resource: "resourcequotas"}, - }, - { - ShortForm: schema.GroupResource{Resource: "rc"}, - LongForm: schema.GroupResource{Resource: "replicationcontrollers"}, - }, - { - ShortForm: schema.GroupResource{Resource: "rs"}, - LongForm: schema.GroupResource{Resource: "replicasets"}, - }, - { - ShortForm: schema.GroupResource{Resource: "sa"}, - LongForm: schema.GroupResource{Resource: "serviceaccounts"}, - }, - { - ShortForm: schema.GroupResource{Resource: "svc"}, - LongForm: schema.GroupResource{Resource: "services"}, - }, - { - ShortForm: schema.GroupResource{Group: "autoscaling", Resource: "hpa"}, - LongForm: schema.GroupResource{Group: "autoscaling", Resource: "horizontalpodautoscalers"}, - }, - { - ShortForm: schema.GroupResource{Group: "certificates.k8s.io", Resource: "csr"}, - LongForm: schema.GroupResource{Group: "certificates.k8s.io", Resource: "certificatesigningrequests"}, - }, - { - ShortForm: schema.GroupResource{Group: "policy", Resource: "pdb"}, - LongForm: schema.GroupResource{Group: "policy", Resource: "poddisruptionbudgets"}, - }, - { - ShortForm: schema.GroupResource{Group: "extensions", Resource: "deploy"}, - LongForm: schema.GroupResource{Group: "extensions", Resource: "deployments"}, - }, - { - ShortForm: schema.GroupResource{Group: "extensions", Resource: "ds"}, - LongForm: schema.GroupResource{Group: "extensions", Resource: "daemonsets"}, - }, - { - ShortForm: schema.GroupResource{Group: "extensions", Resource: "hpa"}, - LongForm: schema.GroupResource{Group: "extensions", Resource: "horizontalpodautoscalers"}, - }, - { - ShortForm: schema.GroupResource{Group: "extensions", Resource: "ing"}, - LongForm: schema.GroupResource{Group: "extensions", Resource: "ingresses"}, - }, - { - ShortForm: schema.GroupResource{Group: "extensions", Resource: "netpol"}, - LongForm: schema.GroupResource{Group: "extensions", Resource: "networkpolicies"}, - }, - { - ShortForm: schema.GroupResource{Group: "extensions", Resource: "psp"}, - LongForm: schema.GroupResource{Group: "extensions", Resource: "podSecurityPolicies"}, - }, -} - -// ResourceShortFormFor looks up for a short form of resource names. -// TODO: Change the signature of this function so that it can -// make use of ResourceShortcuts. -func ResourceShortFormFor(resource string) (string, bool) { - var alias string - exists := false - for _, item := range ResourcesShortcutStatic { - if item.LongForm.Resource == resource { - alias = item.ShortForm.Resource - exists = true - break - } - } - return alias, exists -} - -// ResourceAliases returns the resource shortcuts and plural forms for the given resources. -func ResourceAliases(rs []string) []string { - as := make([]string, 0, len(rs)) - plurals := make(map[string]struct{}, len(rs)) - for _, r := range rs { - var plural string - switch { - case r == "endpoints": - plural = r // exception. "endpoint" does not exist. Why? - case strings.HasSuffix(r, "y"): - plural = r[0:len(r)-1] + "ies" - case strings.HasSuffix(r, "s"): - plural = r + "es" - default: - plural = r + "s" - } - as = append(as, plural) - - plurals[plural] = struct{}{} - } - - for _, item := range ResourcesShortcutStatic { - if _, found := plurals[item.LongForm.Resource]; found { - as = append(as, item.ShortForm.Resource) - } - } - return as -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/BUILD index e2f32b7d6..ac8b4f73f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/BUILD @@ -16,6 +16,7 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/kubectl/plugins", deps = [ + "//pkg/kubectl/genericclioptions:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", @@ -45,5 +46,8 @@ go_test( "runner_test.go", ], embed = [":go_default_library"], - deps = ["//vendor/github.com/spf13/pflag:go_default_library"], + deps = [ + "//pkg/kubectl/genericclioptions:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/runner.go b/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/runner.go index b30472193..eff195564 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/runner.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/runner.go @@ -17,12 +17,12 @@ limitations under the License. package plugins import ( - "io" "os" "os/exec" "strings" "github.com/golang/glog" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) // PluginRunner is capable of running a plugin in a given running context. @@ -34,9 +34,7 @@ type PluginRunner interface { // in, out, and err streams, arguments and environment passed to it, and the // working directory. type RunningContext struct { - In io.Reader - Out io.Writer - ErrOut io.Writer + genericclioptions.IOStreams Args []string EnvProvider EnvProvider WorkingDir string diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/runner_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/runner_test.go index c91ad2fb1..ae3781487 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/runner_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/plugins/runner_test.go @@ -17,9 +17,10 @@ limitations under the License. package plugins import ( - "bytes" "os" "testing" + + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestExecRunner(t *testing.T) { @@ -50,7 +51,7 @@ func TestExecRunner(t *testing.T) { defer os.Unsetenv("KUBECTL_PLUGINS_TEST") for _, test := range tests { - outBuf := bytes.NewBuffer([]byte{}) + streams, _, outBuf, _ := genericclioptions.NewTestIOStreams() plugin := &Plugin{ Description: Description{ @@ -61,7 +62,7 @@ func TestExecRunner(t *testing.T) { } ctx := RunningContext{ - Out: outBuf, + IOStreams: streams, WorkingDir: ".", EnvProvider: &EmptyEnvProvider{}, } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/BUILD new file mode 100644 index 000000000..08132fceb --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/BUILD @@ -0,0 +1,97 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "attachablepodforobject.go", + "canbeautoscaled.go", + "canbeexposed.go", + "helpers.go", + "historyviewer.go", + "interface.go", + "logsforobject.go", + "mapbasedselectorforobject.go", + "objectpauser.go", + "objectresumer.go", + "portsforobject.go", + "protocolsforobject.go", + "rollbacker.go", + "statusviewer.go", + "updatepodspec.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers", + visibility = ["//visibility:public"], + deps = [ + "//pkg/api/legacyscheme:go_default_library", + "//pkg/apis/apps:go_default_library", + "//pkg/apis/batch:go_default_library", + "//pkg/apis/core:go_default_library", + "//pkg/apis/core/v1:go_default_library", + "//pkg/apis/extensions:go_default_library", + "//pkg/client/clientset_generated/internalclientset:go_default_library", + "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", + "//pkg/controller:go_default_library", + "//pkg/kubectl:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", + "//vendor/k8s.io/api/apps/v1beta1:go_default_library", + "//vendor/k8s.io/api/apps/v1beta2:go_default_library", + "//vendor/k8s.io/api/batch/v1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", + "//vendor/k8s.io/api/batch/v2alpha1: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/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels: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/watch:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "canbeexposed_test.go", + "helpers_test.go", + "logsforobject_test.go", + "portsforobject_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//pkg/apis/apps:go_default_library", + "//pkg/apis/batch:go_default_library", + "//pkg/apis/core:go_default_library", + "//pkg/apis/extensions:go_default_library", + "//pkg/client/clientset_generated/internalclientset/fake:go_default_library", + "//pkg/controller: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/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels: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/util/diff:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/testing:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/attachablepodforobject.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/attachablepodforobject.go new file mode 100644 index 000000000..5e8b7f185 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/attachablepodforobject.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "fmt" + "sort" + "time" + + "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + api "k8s.io/kubernetes/pkg/apis/core" + apiv1 "k8s.io/kubernetes/pkg/apis/core/v1" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + "k8s.io/kubernetes/pkg/controller" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +// attachablePodForObject returns the pod to which to attach given an object. +func attachablePodForObject(restClientGetter genericclioptions.RESTClientGetter, object runtime.Object, timeout time.Duration) (*api.Pod, error) { + switch t := object.(type) { + case *api.Pod: + return t, nil + case *corev1.Pod: + internalPod := &api.Pod{} + err := apiv1.Convert_v1_Pod_To_core_Pod(t, internalPod, nil) + return internalPod, err + + } + + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + clientset, err := internalclientset.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + + namespace, selector, err := SelectorsForObject(object) + if err != nil { + return nil, fmt.Errorf("cannot attach to %T: %v", object, err) + } + sortBy := func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) } + pod, _, err := GetFirstPod(clientset.Core(), namespace, selector.String(), timeout, sortBy) + return pod, err +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/canbeautoscaled.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/canbeautoscaled.go new file mode 100644 index 000000000..6009f2b57 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/canbeautoscaled.go @@ -0,0 +1,37 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kubernetes/pkg/apis/apps" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +func canBeAutoscaled(kind schema.GroupKind) error { + switch kind { + case api.Kind("ReplicationController"), extensions.Kind("ReplicaSet"), + extensions.Kind("Deployment"), apps.Kind("Deployment"), apps.Kind("ReplicaSet"): + // nothing to do here + default: + return fmt.Errorf("cannot autoscale a %v", kind) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/canbeexposed.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/canbeexposed.go new file mode 100644 index 000000000..af4463fe9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/canbeexposed.go @@ -0,0 +1,38 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kubernetes/pkg/apis/apps" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +// Check whether the kind of resources could be exposed +func canBeExposed(kind schema.GroupKind) error { + switch kind { + case api.Kind("ReplicationController"), api.Kind("Service"), api.Kind("Pod"), + extensions.Kind("Deployment"), apps.Kind("Deployment"), extensions.Kind("ReplicaSet"), apps.Kind("ReplicaSet"): + // nothing to do here + default: + return fmt.Errorf("cannot expose a %s", kind) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/canbeexposed_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/canbeexposed_test.go new file mode 100644 index 000000000..b9e8d492d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/canbeexposed_test.go @@ -0,0 +1,50 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "testing" + + "k8s.io/apimachinery/pkg/runtime/schema" + api "k8s.io/kubernetes/pkg/apis/core" +) + +func TestCanBeExposed(t *testing.T) { + tests := []struct { + kind schema.GroupKind + expectErr bool + }{ + { + kind: api.Kind("ReplicationController"), + expectErr: false, + }, + { + kind: api.Kind("Node"), + expectErr: true, + }, + } + + for _, test := range tests { + err := canBeExposed(test.kind) + if test.expectErr && err == nil { + t.Error("unexpected non-error") + } + if !test.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/helpers.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/helpers.go new file mode 100644 index 000000000..5d9f0c333 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/helpers.go @@ -0,0 +1,235 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "fmt" + "sort" + "time" + + appsv1 "k8s.io/api/apps/v1" + appsv1beta1 "k8s.io/api/apps/v1beta1" + appsv1beta2 "k8s.io/api/apps/v1beta2" + batchv1 "k8s.io/api/batch/v1" + "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/kubernetes/pkg/apis/apps" + "k8s.io/kubernetes/pkg/apis/batch" + api "k8s.io/kubernetes/pkg/apis/core" + apiv1 "k8s.io/kubernetes/pkg/apis/core/v1" + "k8s.io/kubernetes/pkg/apis/extensions" + coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" +) + +// GetFirstPod returns a pod matching the namespace and label selector +// and the number of all pods that match the label selector. +func GetFirstPod(client coreclient.PodsGetter, namespace string, selector string, timeout time.Duration, sortBy func([]*v1.Pod) sort.Interface) (*api.Pod, int, error) { + options := metav1.ListOptions{LabelSelector: selector} + + podList, err := client.Pods(namespace).List(options) + if err != nil { + return nil, 0, err + } + pods := []*v1.Pod{} + for i := range podList.Items { + pod := podList.Items[i] + externalPod := &v1.Pod{} + apiv1.Convert_core_Pod_To_v1_Pod(&pod, externalPod, nil) + pods = append(pods, externalPod) + } + if len(pods) > 0 { + sort.Sort(sortBy(pods)) + internalPod := &api.Pod{} + apiv1.Convert_v1_Pod_To_core_Pod(pods[0], internalPod, nil) + return internalPod, len(podList.Items), nil + } + + // Watch until we observe a pod + options.ResourceVersion = podList.ResourceVersion + w, err := client.Pods(namespace).Watch(options) + if err != nil { + return nil, 0, err + } + defer w.Stop() + + condition := func(event watch.Event) (bool, error) { + return event.Type == watch.Added || event.Type == watch.Modified, nil + } + event, err := watch.Until(timeout, w, condition) + if err != nil { + return nil, 0, err + } + pod, ok := event.Object.(*api.Pod) + if !ok { + return nil, 0, fmt.Errorf("%#v is not a pod event", event) + } + return pod, 1, nil +} + +// SelectorsForObject returns the pod label selector for a given object +func SelectorsForObject(object runtime.Object) (namespace string, selector labels.Selector, err error) { + switch t := object.(type) { + case *extensions.ReplicaSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *extensionsv1beta1.ReplicaSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1.ReplicaSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1beta2.ReplicaSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + + case *api.ReplicationController: + namespace = t.Namespace + selector = labels.SelectorFromSet(t.Spec.Selector) + case *corev1.ReplicationController: + namespace = t.Namespace + selector = labels.SelectorFromSet(t.Spec.Selector) + + case *apps.StatefulSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1.StatefulSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1beta1.StatefulSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1beta2.StatefulSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + + case *extensions.DaemonSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *extensionsv1beta1.DaemonSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1.DaemonSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1beta2.DaemonSet: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + + case *extensions.Deployment: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *extensionsv1beta1.Deployment: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1.Deployment: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1beta1.Deployment: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *appsv1beta2.Deployment: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + + case *batch.Job: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + case *batchv1.Job: + namespace = t.Namespace + selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return "", nil, fmt.Errorf("invalid label selector: %v", err) + } + + case *api.Service: + namespace = t.Namespace + if t.Spec.Selector == nil || len(t.Spec.Selector) == 0 { + return "", nil, fmt.Errorf("invalid service '%s': Service is defined without a selector", t.Name) + } + selector = labels.SelectorFromSet(t.Spec.Selector) + case *corev1.Service: + namespace = t.Namespace + if t.Spec.Selector == nil || len(t.Spec.Selector) == 0 { + return "", nil, fmt.Errorf("invalid service '%s': Service is defined without a selector", t.Name) + } + selector = labels.SelectorFromSet(t.Spec.Selector) + + default: + return "", nil, fmt.Errorf("selector for %T not implemented", object) + } + + return namespace, selector, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/helpers_test.go new file mode 100644 index 000000000..98a06d5f4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/helpers_test.go @@ -0,0 +1,229 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "fmt" + "sort" + "testing" + "time" + + "k8s.io/api/core/v1" + + apiequality "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/watch" + testcore "k8s.io/client-go/testing" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" + "k8s.io/kubernetes/pkg/controller" +) + +func TestGetFirstPod(t *testing.T) { + labelSet := map[string]string{"test": "selector"} + tests := []struct { + name string + + podList *api.PodList + watching []watch.Event + sortBy func([]*v1.Pod) sort.Interface + + expected *api.Pod + expectedNum int + expectedErr bool + }{ + { + name: "kubectl logs - two ready pods", + podList: newPodList(2, -1, -1, labelSet), + sortBy: func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) }, + expected: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: metav1.NamespaceDefault, + CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), + Labels: map[string]string{"test": "selector"}, + }, + Status: api.PodStatus{ + Conditions: []api.PodCondition{ + { + Status: api.ConditionTrue, + Type: api.PodReady, + }, + }, + }, + }, + expectedNum: 2, + }, + { + name: "kubectl logs - one unhealthy, one healthy", + podList: newPodList(2, -1, 1, labelSet), + sortBy: func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) }, + expected: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-2", + Namespace: metav1.NamespaceDefault, + CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 1, 0, time.UTC), + Labels: map[string]string{"test": "selector"}, + }, + Status: api.PodStatus{ + Conditions: []api.PodCondition{ + { + Status: api.ConditionTrue, + Type: api.PodReady, + }, + }, + ContainerStatuses: []api.ContainerStatus{{RestartCount: 5}}, + }, + }, + expectedNum: 2, + }, + { + name: "kubectl attach - two ready pods", + podList: newPodList(2, -1, -1, labelSet), + sortBy: func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) }, + expected: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: metav1.NamespaceDefault, + CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), + Labels: map[string]string{"test": "selector"}, + }, + Status: api.PodStatus{ + Conditions: []api.PodCondition{ + { + Status: api.ConditionTrue, + Type: api.PodReady, + }, + }, + }, + }, + expectedNum: 2, + }, + { + name: "kubectl attach - wait for ready pod", + podList: newPodList(1, 1, -1, labelSet), + watching: []watch.Event{ + { + Type: watch.Modified, + Object: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: metav1.NamespaceDefault, + CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), + Labels: map[string]string{"test": "selector"}, + }, + Status: api.PodStatus{ + Conditions: []api.PodCondition{ + { + Status: api.ConditionTrue, + Type: api.PodReady, + }, + }, + }, + }, + }, + }, + sortBy: func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) }, + expected: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: metav1.NamespaceDefault, + CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), + Labels: map[string]string{"test": "selector"}, + }, + Status: api.PodStatus{ + Conditions: []api.PodCondition{ + { + Status: api.ConditionTrue, + Type: api.PodReady, + }, + }, + }, + }, + expectedNum: 1, + }, + } + + for i := range tests { + test := tests[i] + fake := fake.NewSimpleClientset(test.podList) + if len(test.watching) > 0 { + watcher := watch.NewFake() + for _, event := range test.watching { + switch event.Type { + case watch.Added: + go watcher.Add(event.Object) + case watch.Modified: + go watcher.Modify(event.Object) + } + } + fake.PrependWatchReactor("pods", testcore.DefaultWatchReactor(watcher, nil)) + } + selector := labels.Set(labelSet).AsSelector() + + pod, numPods, err := GetFirstPod(fake.Core(), metav1.NamespaceDefault, selector.String(), 1*time.Minute, test.sortBy) + pod.Spec.SecurityContext = nil + if !test.expectedErr && err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + continue + } + if test.expectedErr && err == nil { + t.Errorf("%s: expected an error", test.name) + continue + } + if test.expectedNum != numPods { + t.Errorf("%s: expected %d pods, got %d", test.name, test.expectedNum, numPods) + continue + } + if !apiequality.Semantic.DeepEqual(test.expected, pod) { + t.Errorf("%s:\nexpected pod:\n%#v\ngot:\n%#v\n\n", test.name, test.expected, pod) + } + } +} + +func newPodList(count, isUnready, isUnhealthy int, labels map[string]string) *api.PodList { + pods := []api.Pod{} + for i := 0; i < count; i++ { + newPod := api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("pod-%d", i+1), + Namespace: metav1.NamespaceDefault, + CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, i, 0, time.UTC), + Labels: labels, + }, + Status: api.PodStatus{ + Conditions: []api.PodCondition{ + { + Status: api.ConditionTrue, + Type: api.PodReady, + }, + }, + }, + } + pods = append(pods, newPod) + } + if isUnready > -1 && isUnready < count { + pods[isUnready].Status.Conditions[0].Status = api.ConditionFalse + } + if isUnhealthy > -1 && isUnhealthy < count { + pods[isUnhealthy].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 5}} + } + return &api.PodList{ + Items: pods, + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/historyviewer.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/historyviewer.go new file mode 100644 index 000000000..b2742d843 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/historyviewer.go @@ -0,0 +1,38 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +// historyViewer Returns a HistoryViewer for viewing change history +func historyViewer(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (kubectl.HistoryViewer, error) { + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + + external, err := kubernetes.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + return kubectl.HistoryViewerFor(mapping.GroupVersionKind.GroupKind(), external) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/interface.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/interface.go new file mode 100644 index 000000000..06f40df60 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/interface.go @@ -0,0 +1,115 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "time" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/rest" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +// LogsForObjectFunc is a function type that can tell you how to get logs for a runtime.object +type LogsForObjectFunc func(restClientGetter genericclioptions.RESTClientGetter, object, options runtime.Object, timeout time.Duration) (*rest.Request, error) + +// LogsForObjectFn gives a way to easily override the function for unit testing if needed. +var LogsForObjectFn LogsForObjectFunc = logsForObject + +// AttachableLogsForObjectFunc is a function type that can tell you how to get the pod for which to attach a given object +type AttachableLogsForObjectFunc func(restClientGetter genericclioptions.RESTClientGetter, object runtime.Object, timeout time.Duration) (*api.Pod, error) + +// AttachablePodForObjectFn gives a way to easily override the function for unit testing if needed. +var AttachablePodForObjectFn AttachableLogsForObjectFunc = attachablePodForObject + +// HistoryViewerFunc is a function type that can tell you how to view change history +type HistoryViewerFunc func(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (kubectl.HistoryViewer, error) + +// HistoryViewerFn gives a way to easily override the function for unit testing if needed +var HistoryViewerFn HistoryViewerFunc = historyViewer + +// StatusViewerFunc is a function type that can tell you how to print rollout status +type StatusViewerFunc func(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (kubectl.StatusViewer, error) + +// StatusViewerFn gives a way to easily override the function for unit testing if needed +var StatusViewerFn StatusViewerFunc = statusViewer + +// UpdatePodSpecForObjectFunc will call the provided function on the pod spec this object supports, +// return false if no pod spec is supported, or return an error. +type UpdatePodSpecForObjectFunc func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) + +// UpdatePodSpecForObjectFn gives a way to easily override the function for unit testing if needed +var UpdatePodSpecForObjectFn UpdatePodSpecForObjectFunc = updatePodSpecForObject + +// MapBasedSelectorForObjectFunc will call the provided function on mapping the baesd selector for object, +// return "" if object is not supported, or return an error. +type MapBasedSelectorForObjectFunc func(object runtime.Object) (string, error) + +// MapBasedSelectorForObjectFn gives a way to easily override the function for unit testing if needed +var MapBasedSelectorForObjectFn MapBasedSelectorForObjectFunc = mapBasedSelectorForObject + +// ProtocolsForObjectFunc will call the provided function on the protocols for the object, +// return nil-map if no protocols for the object, or return an error. +type ProtocolsForObjectFunc func(object runtime.Object) (map[string]string, error) + +// ProtocolsForObjectFn gives a way to easily override the function for unit testing if needed +var ProtocolsForObjectFn ProtocolsForObjectFunc = protocolsForObject + +// PortsForObjectFunc returns the ports associated with the provided object +type PortsForObjectFunc func(object runtime.Object) ([]string, error) + +// PortsForObjectFn gives a way to easily override the function for unit testing if needed +var PortsForObjectFn PortsForObjectFunc = portsForObject + +// CanBeAutoscaledFunc checks whether the kind of resources could be autoscaled +type CanBeAutoscaledFunc func(kind schema.GroupKind) error + +// CanBeAutoscaledFn gives a way to easily override the function for unit testing if needed +var CanBeAutoscaledFn CanBeAutoscaledFunc = canBeAutoscaled + +// CanBeExposedFunc is a function type that can tell you whether a given GroupKind is capable of being exposed +type CanBeExposedFunc func(kind schema.GroupKind) error + +// CanBeExposedFn gives a way to easily override the function for unit testing if needed +var CanBeExposedFn CanBeExposedFunc = canBeExposed + +// ObjectPauserFunc is a function type that marks the object in a given info as paused. +type ObjectPauserFunc func(runtime.Object) ([]byte, error) + +// ObjectPauserFn gives a way to easily override the function for unit testing if needed. +// Returns the patched object in bytes and any error that occurred during the encoding or +// in case the object is already paused. +var ObjectPauserFn ObjectPauserFunc = defaultObjectPauser + +// ObjectResumerFunc is a function type that marks the object in a given info as resumed. +type ObjectResumerFunc func(runtime.Object) ([]byte, error) + +// ObjectResumerFn gives a way to easily override the function for unit testing if needed. +// Returns the patched object in bytes and any error that occurred during the encoding or +// in case the object is already resumed. +var ObjectResumerFn ObjectResumerFunc = defaultObjectResumer + +// RollbackerFunc gives a way to change the rollback version of the specified RESTMapping type +type RollbackerFunc func(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (kubectl.Rollbacker, error) + +// RollbackerFn gives a way to easily override the function for unit testing if needed +var RollbackerFn RollbackerFunc = rollbacker diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/logsforobject.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/logsforobject.go new file mode 100644 index 000000000..f5a517a1b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/logsforobject.go @@ -0,0 +1,75 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "errors" + "fmt" + "os" + "sort" + "time" + + "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" + coreinternal "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + "k8s.io/kubernetes/pkg/controller" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +func logsForObject(restClientGetter genericclioptions.RESTClientGetter, object, options runtime.Object, timeout time.Duration) (*rest.Request, error) { + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + clientset, err := internalclientset.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + return logsForObjectWithClient(clientset, object, options, timeout) +} + +// this is split for easy test-ability +func logsForObjectWithClient(clientset internalclientset.Interface, object, options runtime.Object, timeout time.Duration) (*rest.Request, error) { + opts, ok := options.(*coreinternal.PodLogOptions) + if !ok { + return nil, errors.New("provided options object is not a PodLogOptions") + } + + switch t := object.(type) { + case *coreinternal.Pod: + return clientset.Core().Pods(t.Namespace).GetLogs(t.Name, opts), nil + case *corev1.Pod: + return clientset.Core().Pods(t.Namespace).GetLogs(t.Name, opts), nil + } + + namespace, selector, err := SelectorsForObject(object) + if err != nil { + return nil, fmt.Errorf("cannot get the logs from %T: %v", object, err) + } + sortBy := func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) } + pod, numPods, err := GetFirstPod(clientset.Core(), namespace, selector.String(), timeout, sortBy) + if err != nil { + return nil, err + } + if numPods > 1 { + fmt.Fprintf(os.Stderr, "Found %v pods, using pod/%v\n", numPods, pod.Name) + } + return clientset.Core().Pods(pod.Namespace).GetLogs(pod.Name, opts), nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/logsforobject_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/logsforobject_test.go new file mode 100644 index 000000000..6ed87d910 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/logsforobject_test.go @@ -0,0 +1,176 @@ +/* +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 polymorphichelpers + +import ( + "reflect" + "testing" + "time" + + 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" + testclient "k8s.io/client-go/testing" + "k8s.io/kubernetes/pkg/apis/apps" + "k8s.io/kubernetes/pkg/apis/batch" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" +) + +var ( + podsResource = schema.GroupVersionResource{Resource: "pods"} + podsKind = schema.GroupVersionKind{Kind: "Pod"} +) + +func TestLogsForObject(t *testing.T) { + tests := []struct { + name string + obj runtime.Object + opts *api.PodLogOptions + pods []runtime.Object + actions []testclient.Action + }{ + { + name: "pod logs", + obj: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, + }, + pods: []runtime.Object{testPod()}, + actions: []testclient.Action{ + getLogsAction("test", nil), + }, + }, + { + name: "replication controller logs", + obj: &api.ReplicationController{ + ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, + Spec: api.ReplicationControllerSpec{ + Selector: map[string]string{"foo": "bar"}, + }, + }, + pods: []runtime.Object{testPod()}, + actions: []testclient.Action{ + testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), + getLogsAction("test", nil), + }, + }, + { + name: "replica set logs", + obj: &extensions.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, + Spec: extensions.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + pods: []runtime.Object{testPod()}, + actions: []testclient.Action{ + testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), + getLogsAction("test", nil), + }, + }, + { + name: "deployment logs", + obj: &extensions.Deployment{ + ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, + Spec: extensions.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + pods: []runtime.Object{testPod()}, + actions: []testclient.Action{ + testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), + getLogsAction("test", nil), + }, + }, + { + name: "job logs", + obj: &batch.Job{ + ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, + Spec: batch.JobSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + pods: []runtime.Object{testPod()}, + actions: []testclient.Action{ + testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), + getLogsAction("test", nil), + }, + }, + { + name: "stateful set logs", + obj: &apps.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"}, + Spec: apps.StatefulSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + pods: []runtime.Object{testPod()}, + actions: []testclient.Action{ + testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}), + getLogsAction("test", nil), + }, + }, + } + + for _, test := range tests { + fakeClientset := fake.NewSimpleClientset(test.pods...) + _, err := logsForObjectWithClient(fakeClientset, test.obj, test.opts, 20*time.Second) + if err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + continue + } + for i := range test.actions { + if len(fakeClientset.Actions()) < i { + t.Errorf("%s: action %d does not exists in actual actions: %#v", + test.name, i, fakeClientset.Actions()) + continue + } + got := fakeClientset.Actions()[i] + want := test.actions[i] + if !reflect.DeepEqual(got, want) { + t.Errorf("%s: unexpected action: %s", test.name, diff.ObjectDiff(got, want)) + } + } + } +} + +func testPod() runtime.Object { + return &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "test", + Labels: map[string]string{"foo": "bar"}, + }, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyAlways, + DNSPolicy: api.DNSClusterFirst, + Containers: []api.Container{{Name: "c1"}}, + }, + } +} + +func getLogsAction(namespace string, opts *api.PodLogOptions) testclient.Action { + action := testclient.GenericActionImpl{} + action.Verb = "get" + action.Namespace = namespace + action.Resource = podsResource + action.Subresource = "logs" + action.Value = opts + return action +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject.go new file mode 100644 index 000000000..dd12941ba --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject.go @@ -0,0 +1,63 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/kubectl" +) + +// mapBasedSelectorForObject returns the map-based selector associated with the provided object. If a +// new set-based selector is provided, an error is returned if the selector cannot be converted to a +// map-based selector +func mapBasedSelectorForObject(object runtime.Object) (string, error) { + // TODO: replace with a swagger schema based approach (identify pod selector via schema introspection) + switch t := object.(type) { + case *api.ReplicationController: + return kubectl.MakeLabels(t.Spec.Selector), nil + case *api.Pod: + if len(t.Labels) == 0 { + return "", fmt.Errorf("the pod has no labels and cannot be exposed") + } + return kubectl.MakeLabels(t.Labels), nil + case *api.Service: + if t.Spec.Selector == nil { + return "", fmt.Errorf("the service has no pod selector set") + } + return kubectl.MakeLabels(t.Spec.Selector), nil + case *extensions.Deployment: + // TODO(madhusudancs): Make this smarter by admitting MatchExpressions with Equals + // operator, DoubleEquals operator and In operator with only one element in the set. + if len(t.Spec.Selector.MatchExpressions) > 0 { + return "", fmt.Errorf("couldn't convert expressions - \"%+v\" to map-based selector format", t.Spec.Selector.MatchExpressions) + } + return kubectl.MakeLabels(t.Spec.Selector.MatchLabels), nil + case *extensions.ReplicaSet: + // TODO(madhusudancs): Make this smarter by admitting MatchExpressions with Equals + // operator, DoubleEquals operator and In operator with only one element in the set. + if len(t.Spec.Selector.MatchExpressions) > 0 { + return "", fmt.Errorf("couldn't convert expressions - \"%+v\" to map-based selector format", t.Spec.Selector.MatchExpressions) + } + return kubectl.MakeLabels(t.Spec.Selector.MatchLabels), nil + default: + return "", fmt.Errorf("cannot extract pod selector from %T", object) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/objectpauser.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/objectpauser.go new file mode 100644 index 000000000..f6fbde558 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/objectpauser.go @@ -0,0 +1,46 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "errors" + "fmt" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +// Currently only supports Deployments. +func defaultObjectPauser(obj runtime.Object) ([]byte, error) { + switch obj := obj.(type) { + case *extensions.Deployment: + if obj.Spec.Paused { + return nil, errors.New("is already paused") + } + obj.Spec.Paused = true + return runtime.Encode(internalVersionJSONEncoder(), obj) + default: + return nil, fmt.Errorf("pausing is not supported") + } +} + +func internalVersionJSONEncoder() runtime.Encoder { + encoder := legacyscheme.Codecs.LegacyCodec(legacyscheme.Scheme.PrioritizedVersionsAllGroups()...) + return unstructured.JSONFallbackEncoder{Encoder: encoder} +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/objectresumer.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/objectresumer.go new file mode 100644 index 000000000..84d8dff91 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/objectresumer.go @@ -0,0 +1,38 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "errors" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +func defaultObjectResumer(obj runtime.Object) ([]byte, error) { + switch obj := obj.(type) { + case *extensions.Deployment: + if !obj.Spec.Paused { + return nil, errors.New("is not paused") + } + obj.Spec.Paused = false + return runtime.Encode(internalVersionJSONEncoder(), obj) + default: + return nil, fmt.Errorf("resuming is not supported") + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/portsforobject.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/portsforobject.go new file mode 100644 index 000000000..48318d30a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/portsforobject.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "fmt" + "strconv" + + "k8s.io/apimachinery/pkg/runtime" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +func portsForObject(object runtime.Object) ([]string, error) { + switch t := object.(type) { + case *api.ReplicationController: + return getPorts(t.Spec.Template.Spec), nil + case *api.Pod: + return getPorts(t.Spec), nil + case *api.Service: + return getServicePorts(t.Spec), nil + case *extensions.Deployment: + return getPorts(t.Spec.Template.Spec), nil + case *extensions.ReplicaSet: + return getPorts(t.Spec.Template.Spec), nil + default: + return nil, fmt.Errorf("cannot extract ports from %T", object) + } +} + +func getPorts(spec api.PodSpec) []string { + result := []string{} + for _, container := range spec.Containers { + for _, port := range container.Ports { + result = append(result, strconv.Itoa(int(port.ContainerPort))) + } + } + return result +} + +// Extracts the ports exposed by a service from the given service spec. +func getServicePorts(spec api.ServiceSpec) []string { + result := []string{} + for _, servicePort := range spec.Ports { + result = append(result, strconv.Itoa(int(servicePort.Port))) + } + return result +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/portsforobject_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/portsforobject_test.go new file mode 100644 index 000000000..3bd05b1f8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/portsforobject_test.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" + api "k8s.io/kubernetes/pkg/apis/core" +) + +func TestPortsForObject(t *testing.T) { + pod := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Ports: []api.ContainerPort{ + { + ContainerPort: 101, + }, + }, + }, + }, + }, + } + + expected := sets.NewString("101") + ports, err := portsForObject(pod) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + got := sets.NewString(ports...) + + if !expected.Equal(got) { + t.Fatalf("Ports mismatch! Expected %v, got %v", expected, got) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/protocolsforobject.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/protocolsforobject.go new file mode 100644 index 000000000..de6d23d2a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/protocolsforobject.go @@ -0,0 +1,63 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "fmt" + "strconv" + + "k8s.io/apimachinery/pkg/runtime" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +func protocolsForObject(object runtime.Object) (map[string]string, error) { + // TODO: replace with a swagger schema based approach (identify pod selector via schema introspection) + switch t := object.(type) { + case *api.ReplicationController: + return getProtocols(t.Spec.Template.Spec), nil + case *api.Pod: + return getProtocols(t.Spec), nil + case *api.Service: + return getServiceProtocols(t.Spec), nil + case *extensions.Deployment: + return getProtocols(t.Spec.Template.Spec), nil + case *extensions.ReplicaSet: + return getProtocols(t.Spec.Template.Spec), nil + default: + return nil, fmt.Errorf("cannot extract protocols from %T", object) + } +} + +func getProtocols(spec api.PodSpec) map[string]string { + result := make(map[string]string) + for _, container := range spec.Containers { + for _, port := range container.Ports { + result[strconv.Itoa(int(port.ContainerPort))] = string(port.Protocol) + } + } + return result +} + +// Extracts the protocols exposed by a service from the given service spec. +func getServiceProtocols(spec api.ServiceSpec) map[string]string { + result := make(map[string]string) + for _, servicePort := range spec.Ports { + result[strconv.Itoa(int(servicePort.Port))] = string(servicePort.Protocol) + } + return result +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/rollbacker.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/rollbacker.go new file mode 100644 index 000000000..f57f475c6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/rollbacker.go @@ -0,0 +1,38 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +// Returns a Rollbacker for changing the rollback version of the specified RESTMapping type or an error +func rollbacker(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (kubectl.Rollbacker, error) { + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + external, err := kubernetes.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + + return kubectl.RollbackerFor(mapping.GroupVersionKind.GroupKind(), external) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/statusviewer.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/statusviewer.go new file mode 100644 index 000000000..043d1e31c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/statusviewer.go @@ -0,0 +1,37 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +// statusViewer returns a StatusViewer for printing rollout status. +func statusViewer(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (kubectl.StatusViewer, error) { + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + clientset, err := kubernetes.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + return kubectl.StatusViewerFor(mapping.GroupVersionKind.GroupKind(), clientset) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/updatepodspec.go b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/updatepodspec.go new file mode 100644 index 000000000..404486382 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/polymorphichelpers/updatepodspec.go @@ -0,0 +1,91 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "fmt" + + appsv1 "k8s.io/api/apps/v1" + appsv1beta1 "k8s.io/api/apps/v1beta1" + appsv1beta2 "k8s.io/api/apps/v1beta2" + batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" + batchv2alpha1 "k8s.io/api/batch/v2alpha1" + "k8s.io/api/core/v1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + "k8s.io/apimachinery/pkg/runtime" +) + +func updatePodSpecForObject(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) { + switch t := obj.(type) { + case *v1.Pod: + return true, fn(&t.Spec) + // ReplicationController + case *v1.ReplicationController: + if t.Spec.Template == nil { + t.Spec.Template = &v1.PodTemplateSpec{} + } + return true, fn(&t.Spec.Template.Spec) + + // Deployment + case *extensionsv1beta1.Deployment: + return true, fn(&t.Spec.Template.Spec) + case *appsv1beta1.Deployment: + return true, fn(&t.Spec.Template.Spec) + case *appsv1beta2.Deployment: + return true, fn(&t.Spec.Template.Spec) + case *appsv1.Deployment: + return true, fn(&t.Spec.Template.Spec) + + // DaemonSet + case *extensionsv1beta1.DaemonSet: + return true, fn(&t.Spec.Template.Spec) + case *appsv1beta2.DaemonSet: + return true, fn(&t.Spec.Template.Spec) + case *appsv1.DaemonSet: + return true, fn(&t.Spec.Template.Spec) + + // ReplicaSet + case *extensionsv1beta1.ReplicaSet: + return true, fn(&t.Spec.Template.Spec) + case *appsv1beta2.ReplicaSet: + return true, fn(&t.Spec.Template.Spec) + case *appsv1.ReplicaSet: + return true, fn(&t.Spec.Template.Spec) + + // StatefulSet + case *appsv1beta1.StatefulSet: + return true, fn(&t.Spec.Template.Spec) + case *appsv1beta2.StatefulSet: + return true, fn(&t.Spec.Template.Spec) + case *appsv1.StatefulSet: + return true, fn(&t.Spec.Template.Spec) + + // Job + case *batchv1.Job: + return true, fn(&t.Spec.Template.Spec) + + // CronJob + case *batchv1beta1.CronJob: + return true, fn(&t.Spec.JobTemplate.Spec.Template.Spec) + case *batchv2alpha1.CronJob: + return true, fn(&t.Spec.JobTemplate.Spec.Template.Spec) + + default: + return false, fmt.Errorf("the object is not a pod or does not have a pod template: %T", t) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/resource/BUILD deleted file mode 100644 index fc5d02053..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/BUILD +++ /dev/null @@ -1,96 +0,0 @@ -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "builder.go", - "doc.go", - "helper.go", - "interfaces.go", - "mapper.go", - "result.go", - "selector.go", - "visitor.go", - ], - importpath = "k8s.io/kubernetes/pkg/kubectl/resource", - visibility = [ - "//build/visible_to:pkg_kubectl_resource_CONSUMERS", - ], - deps = [ - "//pkg/kubectl/categories:go_default_library", - "//pkg/kubectl/validation:go_default_library", - "//vendor/golang.org/x/text/encoding/unicode:go_default_library", - "//vendor/golang.org/x/text/transform:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured: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/runtime:go_default_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/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "builder_test.go", - "helper_test.go", - "visitor_test.go", - ], - data = [ - "//examples:config", - "//test/fixtures", - ], - embed = [":go_default_library"], - deps = [ - "//pkg/kubectl/categories:go_default_library", - "//pkg/kubectl/scheme:go_default_library", - "//vendor/github.com/ghodss/yaml:go_default_library", - "//vendor/github.com/stretchr/testify/assert: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/meta: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/labels: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:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/rest/fake:go_default_library", - "//vendor/k8s.io/client-go/rest/watch:go_default_library", - "//vendor/k8s.io/client-go/util/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = [ - "//build/visible_to:pkg_kubectl_resource_CONSUMERS", - ], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/doc.go b/vendor/k8s.io/kubernetes/pkg/kubectl/resource/doc.go deleted file mode 100644 index 94944dfe3..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -/* -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 resource assists clients in dealing with RESTful objects that match the -// Kubernetes API conventions. The Helper object provides simple CRUD operations -// on resources. The Visitor interface makes it easy to deal with multiple resources -// in bulk for retrieval and operation. The Builder object simplifies converting -// standard command line arguments and parameters into a Visitor that can iterate -// over all of the identified resources, whether on the server or on the local -// filesystem. -package resource // import "k8s.io/kubernetes/pkg/kubectl/resource" diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/interfaces.go b/vendor/k8s.io/kubernetes/pkg/kubectl/resource/interfaces.go deleted file mode 100644 index 8b75d41db..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/interfaces.go +++ /dev/null @@ -1,84 +0,0 @@ -/* -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 resource - -import ( - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/types" - client "k8s.io/client-go/rest" -) - -// RESTClient is a client helper for dealing with RESTful resources -// in a generic way. -type RESTClient interface { - Get() *client.Request - Post() *client.Request - Patch(types.PatchType) *client.Request - Delete() *client.Request - Put() *client.Request -} - -// ClientMapper abstracts retrieving a Client for mapped objects. -type ClientMapper interface { - ClientForMapping(mapping *meta.RESTMapping) (RESTClient, error) -} - -// ClientMapperFunc implements ClientMapper for a function -type ClientMapperFunc func(mapping *meta.RESTMapping) (RESTClient, error) - -// ClientForMapping implements ClientMapper -func (f ClientMapperFunc) ClientForMapping(mapping *meta.RESTMapping) (RESTClient, error) { - return f(mapping) -} - -// RequestTransform is a function that is given a chance to modify the outgoing request. -type RequestTransform func(*client.Request) - -// NewClientWithOptions wraps the provided RESTClient and invokes each transform on each -// newly created request. -func NewClientWithOptions(c RESTClient, transforms ...RequestTransform) RESTClient { - return &clientOptions{c: c, transforms: transforms} -} - -type clientOptions struct { - c RESTClient - transforms []RequestTransform -} - -func (c *clientOptions) modify(req *client.Request) *client.Request { - for _, transform := range c.transforms { - transform(req) - } - return req -} - -func (c *clientOptions) Get() *client.Request { - return c.modify(c.c.Get()) -} - -func (c *clientOptions) Post() *client.Request { - return c.modify(c.c.Post()) -} -func (c *clientOptions) Patch(t types.PatchType) *client.Request { - return c.modify(c.c.Patch(t)) -} -func (c *clientOptions) Delete() *client.Request { - return c.modify(c.c.Delete()) -} -func (c *clientOptions) Put() *client.Request { - return c.modify(c.c.Put()) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/mapper.go b/vendor/k8s.io/kubernetes/pkg/kubectl/resource/mapper.go deleted file mode 100644 index 673973680..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource/mapper.go +++ /dev/null @@ -1,237 +0,0 @@ -/* -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 resource - -import ( - "fmt" - "reflect" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// Mapper is a convenience struct for holding references to the interfaces -// needed to create Info for arbitrary objects. -type Mapper struct { - runtime.ObjectTyper - meta.RESTMapper - ClientMapper - runtime.Decoder -} - -// AcceptUnrecognizedObjects will return a mapper that will tolerate objects -// that are not recognized by the RESTMapper, returning mappings that can -// perform minimal transformation. Allows working in disconnected mode, or with -// objects that the server does not recognize. Returned resource.Info objects -// may have empty resource fields and nil clients. -func (m *Mapper) AcceptUnrecognizedObjects() *Mapper { - copied := *m - copied.RESTMapper = NewRelaxedRESTMapper(m.RESTMapper) - copied.ClientMapper = NewRelaxedClientMapper(m.ClientMapper) - return &copied -} - -// InfoForData creates an Info object for the given data. An error is returned -// if any of the decoding or client lookup steps fail. Name and namespace will be -// set into Info if the mapping's MetadataAccessor can retrieve them. -func (m *Mapper) InfoForData(data []byte, source string) (*Info, error) { - obj, gvk, err := m.Decode(data, nil, nil) - if err != nil { - return nil, fmt.Errorf("unable to decode %q: %v", source, err) - } - - mapping, err := m.RESTMapping(gvk.GroupKind(), gvk.Version) - if err != nil { - return nil, fmt.Errorf("unable to recognize %q: %v", source, err) - } - - client, err := m.ClientForMapping(mapping) - if err != nil { - return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err) - } - - name, _ := mapping.MetadataAccessor.Name(obj) - namespace, _ := mapping.MetadataAccessor.Namespace(obj) - resourceVersion, _ := mapping.MetadataAccessor.ResourceVersion(obj) - - return &Info{ - Client: client, - Mapping: mapping, - - Source: source, - Namespace: namespace, - Name: name, - ResourceVersion: resourceVersion, - - Object: obj, - }, nil -} - -// InfoForObject creates an Info object for the given Object. An error is returned -// if the object cannot be introspected. Name and namespace will be set into Info -// if the mapping's MetadataAccessor can retrieve them. -func (m *Mapper) InfoForObject(obj runtime.Object, preferredGVKs []schema.GroupVersionKind) (*Info, error) { - groupVersionKinds, _, err := m.ObjectKinds(obj) - if err != nil { - return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err) - } - - groupVersionKind := groupVersionKinds[0] - if len(groupVersionKinds) > 1 && len(preferredGVKs) > 0 { - groupVersionKind = preferredObjectKind(groupVersionKinds, preferredGVKs) - } - - mapping, err := m.RESTMapping(groupVersionKind.GroupKind(), groupVersionKind.Version) - if err != nil { - return nil, fmt.Errorf("unable to recognize %v: %v", groupVersionKind, err) - } - - client, err := m.ClientForMapping(mapping) - if err != nil { - return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err) - } - name, _ := mapping.MetadataAccessor.Name(obj) - namespace, _ := mapping.MetadataAccessor.Namespace(obj) - resourceVersion, _ := mapping.MetadataAccessor.ResourceVersion(obj) - return &Info{ - Client: client, - Mapping: mapping, - - Namespace: namespace, - Name: name, - ResourceVersion: resourceVersion, - - Object: obj, - }, nil -} - -// preferredObjectKind picks the possibility that most closely matches the priority list in this order: -// GroupVersionKind matches (exact match) -// GroupKind matches -// Group matches -func preferredObjectKind(possibilities []schema.GroupVersionKind, preferences []schema.GroupVersionKind) schema.GroupVersionKind { - // Exact match - for _, priority := range preferences { - for _, possibility := range possibilities { - if possibility == priority { - return possibility - } - } - } - - // GroupKind match - for _, priority := range preferences { - for _, possibility := range possibilities { - if possibility.GroupKind() == priority.GroupKind() { - return possibility - } - } - } - - // Group match - for _, priority := range preferences { - for _, possibility := range possibilities { - if possibility.Group == priority.Group { - return possibility - } - } - } - - // Just pick the first - return possibilities[0] -} - -// DisabledClientForMapping allows callers to avoid allowing remote calls when handling -// resources. -type DisabledClientForMapping struct { - ClientMapper -} - -func (f DisabledClientForMapping) ClientForMapping(mapping *meta.RESTMapping) (RESTClient, error) { - return nil, nil -} - -// NewRelaxedClientMapper will return a nil mapping if the object is not a recognized resource. -func NewRelaxedClientMapper(mapper ClientMapper) ClientMapper { - return relaxedClientMapper{mapper} -} - -type relaxedClientMapper struct { - ClientMapper -} - -func (f relaxedClientMapper) ClientForMapping(mapping *meta.RESTMapping) (RESTClient, error) { - if len(mapping.Resource) == 0 { - return nil, nil - } - return f.ClientMapper.ClientForMapping(mapping) -} - -// NewRelaxedRESTMapper returns a RESTMapper that will tolerate mappings that don't exist in provided -// RESTMapper, returning a mapping that is a best effort against the current server. This allows objects -// that the server does not recognize to still be loaded. -func NewRelaxedRESTMapper(mapper meta.RESTMapper) meta.RESTMapper { - return relaxedMapper{mapper} -} - -type relaxedMapper struct { - meta.RESTMapper -} - -func (m relaxedMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { - mapping, err := m.RESTMapper.RESTMapping(gk, versions...) - if err != nil && meta.IsNoMatchError(err) && len(versions) > 0 { - return &meta.RESTMapping{ - GroupVersionKind: gk.WithVersion(versions[0]), - MetadataAccessor: meta.NewAccessor(), - Scope: meta.RESTScopeRoot, - ObjectConvertor: identityConvertor{}, - }, nil - } - return mapping, err -} -func (m relaxedMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) { - mappings, err := m.RESTMapper.RESTMappings(gk, versions...) - if err != nil && meta.IsNoMatchError(err) && len(versions) > 0 { - return []*meta.RESTMapping{ - { - GroupVersionKind: gk.WithVersion(versions[0]), - MetadataAccessor: meta.NewAccessor(), - Scope: meta.RESTScopeRoot, - ObjectConvertor: identityConvertor{}, - }, - }, nil - } - return mappings, err -} - -type identityConvertor struct{} - -var _ runtime.ObjectConvertor = identityConvertor{} - -func (c identityConvertor) Convert(in interface{}, out interface{}, context interface{}) error { - return fmt.Errorf("unable to convert objects across pointers") -} - -func (c identityConvertor) ConvertToVersion(in runtime.Object, gv runtime.GroupVersioner) (out runtime.Object, err error) { - return in, nil -} - -func (c identityConvertor) ConvertFieldLabel(version string, kind string, label string, value string) (string, string, error) { - return "", "", fmt.Errorf("unable to convert field labels") -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource_filter.go b/vendor/k8s.io/kubernetes/pkg/kubectl/resource_filter.go deleted file mode 100644 index b873748f6..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource_filter.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -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 kubectl - -import ( - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/printers" -) - -// FilterFunc is a function that knows how to filter a specific resource kind. -// It receives a generic runtime.Object which must be type-checked by the function. -// Returns a boolean value true if a resource is filtered, or false otherwise. -type FilterFunc func(runtime.Object, printers.PrintOptions) bool - -// Filters is a collection of filter funcs -type Filters []FilterFunc - -func NewResourceFilter() Filters { - return []FilterFunc{ - filterPods, - } -} - -// filterPods returns true if a pod should be skipped. -// If show-all is true, the pod will be never be skipped (return false); -// otherwise, skip terminated pod. -func filterPods(obj runtime.Object, options printers.PrintOptions) bool { - if options.ShowAll { - return false - } - - switch p := obj.(type) { - case *v1.Pod: - return p.Status.Phase == v1.PodSucceeded || p.Status.Phase == v1.PodFailed - case *api.Pod: - return p.Status.Phase == api.PodSucceeded || p.Status.Phase == api.PodFailed - } - return false -} - -// Filter loops through a collection of FilterFuncs until it finds one that can filter the given resource -func (f Filters) Filter(obj runtime.Object, opts *printers.PrintOptions) (bool, error) { - for _, filter := range f { - if ok := filter(obj, *opts); ok { - return true, nil - } - } - return false, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/resource_filter_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/resource_filter_test.go deleted file mode 100644 index 7c3335bdf..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/resource_filter_test.go +++ /dev/null @@ -1,76 +0,0 @@ -/* -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 kubectl - -import ( - "testing" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/printers" -) - -func TestResourceFilter(t *testing.T) { - tests := []struct { - name string - hide bool - object runtime.Object - }{ - {"v1.Pod pending", false, &v1.Pod{Status: v1.PodStatus{Phase: v1.PodPending}}}, - {"v1.Pod running", false, &v1.Pod{Status: v1.PodStatus{Phase: v1.PodRunning}}}, - {"v1.Pod succeeded", true, &v1.Pod{Status: v1.PodStatus{Phase: v1.PodSucceeded}}}, - {"v1.Pod failed", true, &v1.Pod{Status: v1.PodStatus{Phase: v1.PodFailed}}}, - {"v1.Pod evicted", true, &v1.Pod{Status: v1.PodStatus{Phase: v1.PodFailed, Reason: "Evicted"}}}, - {"v1.Pod unknown", false, &v1.Pod{Status: v1.PodStatus{Phase: v1.PodUnknown}}}, - - {"api.Pod pending", false, &api.Pod{Status: api.PodStatus{Phase: api.PodPending}}}, - {"api.Pod running", false, &api.Pod{Status: api.PodStatus{Phase: api.PodRunning}}}, - {"api.Pod succeeded", true, &api.Pod{Status: api.PodStatus{Phase: api.PodSucceeded}}}, - {"api.Pod failed", true, &api.Pod{Status: api.PodStatus{Phase: api.PodFailed}}}, - {"api.Pod evicted", true, &api.Pod{Status: api.PodStatus{Phase: api.PodFailed, Reason: "Evicted"}}}, - {"api.Pod unknown", false, &api.Pod{Status: api.PodStatus{Phase: api.PodUnknown}}}, - } - - filters := NewResourceFilter() - - options := &printers.PrintOptions{ - ShowAll: false, - } - for _, test := range tests { - got, err := filters.Filter(test.object, options) - if err != nil { - t.Errorf("%v: unexpected error: %v", test.name, err) - continue - } - if want := test.hide; got != want { - t.Errorf("%v: got %v, want %v", test.name, got, want) - } - } - - options.ShowAll = true - for _, test := range tests { - got, err := filters.Filter(test.object, options) - if err != nil { - t.Errorf("%v: unexpected error: %v", test.name, err) - continue - } - if want := false; got != want { - t.Errorf("%v (ShowAll): got %v, want %v", test.name, got, want) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/rollback.go b/vendor/k8s.io/kubernetes/pkg/kubectl/rollback.go index 10ede4b53..2d984d0d6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/rollback.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/rollback.go @@ -26,24 +26,25 @@ import ( appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extv1beta1 "k8s.io/api/extensions/v1beta1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" "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/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/json" + "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" apiv1 "k8s.io/kubernetes/pkg/apis/core/v1" "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/controller/daemon" - deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" - "k8s.io/kubernetes/pkg/controller/statefulset" kapps "k8s.io/kubernetes/pkg/kubectl/apps" sliceutil "k8s.io/kubernetes/pkg/kubectl/util/slice" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" + // kubectl should not be taking dependencies on logic in the controllers + deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" ) const ( @@ -114,10 +115,10 @@ func (r *DeploymentRollbacker) Rollback(obj runtime.Object, updatedAnnotations m if d.Spec.Paused { return "", fmt.Errorf("you cannot rollback a paused deployment; resume it first with 'kubectl rollout resume deployment/%s' and try again", d.Name) } - deploymentRollback := &extv1beta1.DeploymentRollback{ + deploymentRollback := &extensionsv1beta1.DeploymentRollback{ Name: d.Name, UpdatedAnnotations: updatedAnnotations, - RollbackTo: extv1beta1.RollbackConfig{ + RollbackTo: extensionsv1beta1.RollbackConfig{ Revision: toRevision, }, } @@ -183,12 +184,12 @@ func isRollbackEvent(e *api.Event) (bool, string) { } func simpleDryRun(deployment *extensions.Deployment, c kubernetes.Interface, toRevision int64) (string, error) { - externalDeployment := &extv1beta1.Deployment{} + externalDeployment := &appsv1.Deployment{} if err := legacyscheme.Scheme.Convert(deployment, externalDeployment, nil); err != nil { return "", fmt.Errorf("failed to convert deployment, %v", err) } - _, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(externalDeployment, c.ExtensionsV1beta1()) + _, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(externalDeployment, c.AppsV1()) if err != nil { return "", fmt.Errorf("failed to retrieve replica sets from deployment %s: %v", deployment.Name, err) } @@ -278,7 +279,7 @@ func (r *DaemonSetRollbacker) Rollback(obj runtime.Object, updatedAnnotations ma } // Skip if the revision already matches current DaemonSet - done, err := daemon.Match(ds, toHistory) + done, err := daemonSetMatch(ds, toHistory) if err != nil { return "", err } @@ -294,6 +295,42 @@ func (r *DaemonSetRollbacker) Rollback(obj runtime.Object, updatedAnnotations ma return rollbackSuccess, nil } +// daemonMatch check if the given DaemonSet's template matches the template stored in the given history. +func daemonSetMatch(ds *appsv1.DaemonSet, history *appsv1.ControllerRevision) (bool, error) { + patch, err := getDaemonSetPatch(ds) + if err != nil { + return false, err + } + return bytes.Equal(patch, history.Data.Raw), nil +} + +// getPatch returns a strategic merge patch that can be applied to restore a Daemonset to a +// previous version. If the returned error is nil the patch is valid. The current state that we save is just the +// PodSpecTemplate. We can modify this later to encompass more state (or less) and remain compatible with previously +// recorded patches. +func getDaemonSetPatch(ds *appsv1.DaemonSet) ([]byte, error) { + dsBytes, err := json.Marshal(ds) + if err != nil { + return nil, err + } + var raw map[string]interface{} + err = json.Unmarshal(dsBytes, &raw) + if err != nil { + return nil, err + } + objCopy := make(map[string]interface{}) + specCopy := make(map[string]interface{}) + + // Create a patch of the DaemonSet that replaces spec.template + spec := raw["spec"].(map[string]interface{}) + template := spec["template"].(map[string]interface{}) + specCopy["template"] = template + template["$patch"] = "replace" + objCopy["spec"] = specCopy + patch, err := json.Marshal(objCopy) + return patch, err +} + type StatefulSetRollbacker struct { c kubernetes.Interface } @@ -321,7 +358,7 @@ func (r *StatefulSetRollbacker) Rollback(obj runtime.Object, updatedAnnotations } if dryRun { - appliedSS, err := statefulset.ApplyRevision(sts, toHistory) + appliedSS, err := applyRevision(sts, toHistory) if err != nil { return "", err } @@ -329,7 +366,7 @@ func (r *StatefulSetRollbacker) Rollback(obj runtime.Object, updatedAnnotations } // Skip if the revision already matches current StatefulSet - done, err := statefulset.Match(sts, toHistory) + done, err := statefulsetMatch(sts, toHistory) if err != nil { return "", err } @@ -345,6 +382,54 @@ func (r *StatefulSetRollbacker) Rollback(obj runtime.Object, updatedAnnotations return rollbackSuccess, nil } +var appsCodec = legacyscheme.Codecs.LegacyCodec(appsv1.SchemeGroupVersion) + +// applyRevision returns a new StatefulSet constructed by restoring the state in revision to set. If the returned error +// is nil, the returned StatefulSet is valid. +func applyRevision(set *appsv1.StatefulSet, revision *appsv1.ControllerRevision) (*appsv1.StatefulSet, error) { + clone := set.DeepCopy() + patched, err := strategicpatch.StrategicMergePatch([]byte(runtime.EncodeOrDie(appsCodec, clone)), revision.Data.Raw, clone) + if err != nil { + return nil, err + } + err = json.Unmarshal(patched, clone) + if err != nil { + return nil, err + } + return clone, nil +} + +// statefulsetMatch check if the given StatefulSet's template matches the template stored in the given history. +func statefulsetMatch(ss *appsv1.StatefulSet, history *appsv1.ControllerRevision) (bool, error) { + patch, err := getStatefulSetPatch(ss) + if err != nil { + return false, err + } + return bytes.Equal(patch, history.Data.Raw), nil +} + +// getStatefulSetPatch returns a strategic merge patch that can be applied to restore a StatefulSet to a +// previous version. If the returned error is nil the patch is valid. The current state that we save is just the +// PodSpecTemplate. We can modify this later to encompass more state (or less) and remain compatible with previously +// recorded patches. +func getStatefulSetPatch(set *appsv1.StatefulSet) ([]byte, error) { + str, err := runtime.Encode(appsCodec, set) + if err != nil { + return nil, err + } + var raw map[string]interface{} + json.Unmarshal([]byte(str), &raw) + objCopy := make(map[string]interface{}) + specCopy := make(map[string]interface{}) + spec := raw["spec"].(map[string]interface{}) + template := spec["template"].(map[string]interface{}) + specCopy["template"] = template + template["$patch"] = "replace" + objCopy["spec"] = specCopy + patch, err := json.Marshal(objCopy) + return patch, err +} + // findHistory returns a controllerrevision of a specific revision from the given controllerrevisions. // It returns nil if no such controllerrevision exists. // If toRevision is 0, the last previously used history is returned. diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/rolling_updater.go b/vendor/k8s.io/kubernetes/pkg/kubectl/rolling_updater.go index 3d640184c..d0a885986 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/rolling_updater.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/rolling_updater.go @@ -28,8 +28,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" + scaleclient "k8s.io/client-go/scale" "k8s.io/client-go/util/integer" "k8s.io/client-go/util/retry" podutil "k8s.io/kubernetes/pkg/api/v1/pod" @@ -114,8 +116,9 @@ const ( // RollingUpdater provides methods for updating replicated pods in a predictable, // fault-tolerant way. type RollingUpdater struct { - rcClient coreclient.ReplicationControllersGetter - podClient coreclient.PodsGetter + rcClient coreclient.ReplicationControllersGetter + podClient coreclient.PodsGetter + scaleClient scaleclient.ScalesGetter // Namespace for resources ns string // scaleAndWait scales a controller and returns its updated state. @@ -132,11 +135,12 @@ type RollingUpdater struct { } // NewRollingUpdater creates a RollingUpdater from a client. -func NewRollingUpdater(namespace string, rcClient coreclient.ReplicationControllersGetter, podClient coreclient.PodsGetter) *RollingUpdater { +func NewRollingUpdater(namespace string, rcClient coreclient.ReplicationControllersGetter, podClient coreclient.PodsGetter, sc scaleclient.ScalesGetter) *RollingUpdater { updater := &RollingUpdater{ - rcClient: rcClient, - podClient: podClient, - ns: namespace, + rcClient: rcClient, + podClient: podClient, + scaleClient: sc, + ns: namespace, } // Inject real implementations. updater.scaleAndWait = updater.scaleAndWaitWithScaler @@ -396,8 +400,8 @@ func (r *RollingUpdater) scaleDown(newRc, oldRc *api.ReplicationController, desi // scalerScaleAndWait scales a controller using a Scaler and a real client. func (r *RollingUpdater) scaleAndWaitWithScaler(rc *api.ReplicationController, retry *RetryParams, wait *RetryParams) (*api.ReplicationController, error) { - scaler := &ReplicationControllerScaler{r.rcClient} - if err := scaler.Scale(rc.Namespace, rc.Name, uint(rc.Spec.Replicas), &ScalePrecondition{-1, ""}, retry, wait); err != nil { + scaler := NewScaler(r.scaleClient) + if err := scaler.Scale(rc.Namespace, rc.Name, uint(rc.Spec.Replicas), &ScalePrecondition{-1, ""}, retry, wait, schema.GroupResource{Resource: "replicationcontrollers"}); err != nil { return nil, err } return r.rcClient.ReplicationControllers(rc.Namespace).Get(rc.Name, metav1.GetOptions{}) @@ -545,8 +549,8 @@ func Rename(c coreclient.ReplicationControllersGetter, rc *api.ReplicationContro rc.Name = newName rc.ResourceVersion = "" // First delete the oldName RC and orphan its pods. - trueVar := true - err := c.ReplicationControllers(rc.Namespace).Delete(oldName, &metav1.DeleteOptions{OrphanDependents: &trueVar}) + policy := metav1.DeletePropagationOrphan + err := c.ReplicationControllers(rc.Namespace).Delete(oldName, &metav1.DeleteOptions{PropagationPolicy: &policy}) if err != nil && !errors.IsNotFound(err) { return err } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/rolling_updater_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/rolling_updater_test.go index 3620ed071..68c535bab 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/rolling_updater_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/rolling_updater_test.go @@ -1468,8 +1468,8 @@ func TestUpdateRcWithRetries(t *testing.T) { {StatusCode: 200, Header: header, Body: objBody(codec, rc)}, } fakeClient := &manualfake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, - NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, + NegotiatedSerializer: legacyscheme.Codecs, Client: manualfake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == testapi.Default.ResourcePath("replicationcontrollers", "default", "rc") && m == "PUT": @@ -1495,7 +1495,7 @@ func TestUpdateRcWithRetries(t *testing.T) { } }), } - clientConfig := &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion}} + clientConfig := &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}} restClient, _ := restclient.RESTClientFor(clientConfig) restClient.Client = fakeClient.Client clientset := internalclientset.New(restClient) @@ -1561,8 +1561,8 @@ func TestAddDeploymentHash(t *testing.T) { seen := sets.String{} updatedRc := false fakeClient := &manualfake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, - NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, + NegotiatedSerializer: legacyscheme.Codecs, Client: manualfake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { header := http.Header{} header.Set("Content-Type", runtime.ContentTypeJSON) @@ -1596,7 +1596,7 @@ func TestAddDeploymentHash(t *testing.T) { } }), } - clientConfig := &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion}} + clientConfig := &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}} restClient, _ := restclient.RESTClientFor(clientConfig) restClient.Client = fakeClient.Client clientset := internalclientset.New(restClient) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/rollout_status.go b/vendor/k8s.io/kubernetes/pkg/kubectl/rollout_status.go index 24fcdf568..714d364fd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/rollout_status.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/rollout_status.go @@ -19,12 +19,12 @@ package kubectl import ( "fmt" + appsv1 "k8s.io/api/apps/v1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" - clientappsv1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1" - clientextensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" + clientappsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" "k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/controller/deployment/util" ) @@ -38,28 +38,28 @@ type StatusViewer interface { func StatusViewerFor(kind schema.GroupKind, c kubernetes.Interface) (StatusViewer, error) { switch kind { case extensionsv1beta1.SchemeGroupVersion.WithKind("Deployment").GroupKind(), apps.Kind("Deployment"): - return &DeploymentStatusViewer{c.ExtensionsV1beta1()}, nil + return &DeploymentStatusViewer{c.AppsV1()}, nil case extensionsv1beta1.SchemeGroupVersion.WithKind("DaemonSet").GroupKind(), apps.Kind("DaemonSet"): - return &DaemonSetStatusViewer{c.ExtensionsV1beta1()}, nil + return &DaemonSetStatusViewer{c.AppsV1()}, nil case apps.Kind("StatefulSet"): - return &StatefulSetStatusViewer{c.AppsV1beta1()}, nil + return &StatefulSetStatusViewer{c.AppsV1()}, nil } return nil, fmt.Errorf("no status viewer has been implemented for %v", kind) } // DeploymentStatusViewer implements the StatusViewer interface. type DeploymentStatusViewer struct { - c clientextensionsv1beta1.DeploymentsGetter + c clientappsv1.DeploymentsGetter } // DaemonSetStatusViewer implements the StatusViewer interface. type DaemonSetStatusViewer struct { - c clientextensionsv1beta1.DaemonSetsGetter + c clientappsv1.DaemonSetsGetter } // StatefulSetStatusViewer implements the StatusViewer interface. type StatefulSetStatusViewer struct { - c clientappsv1beta1.StatefulSetsGetter + c clientappsv1.StatefulSetsGetter } // Status returns a message describing deployment status, and a bool value indicating if the status is considered done. @@ -78,18 +78,18 @@ func (s *DeploymentStatusViewer) Status(namespace, name string, revision int64) } } if deployment.Generation <= deployment.Status.ObservedGeneration { - cond := util.GetDeploymentCondition(deployment.Status, extensionsv1beta1.DeploymentProgressing) + cond := util.GetDeploymentCondition(deployment.Status, appsv1.DeploymentProgressing) if cond != nil && cond.Reason == util.TimedOutReason { return "", false, fmt.Errorf("deployment %q exceeded its progress deadline", name) } if deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas { - return fmt.Sprintf("Waiting for rollout to finish: %d out of %d new replicas have been updated...\n", deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas), false, nil + return fmt.Sprintf("Waiting for deployment %q rollout to finish: %d out of %d new replicas have been updated...\n", name, deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas), false, nil } if deployment.Status.Replicas > deployment.Status.UpdatedReplicas { - return fmt.Sprintf("Waiting for rollout to finish: %d old replicas are pending termination...\n", deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false, nil + return fmt.Sprintf("Waiting for deployment %q rollout to finish: %d old replicas are pending termination...\n", name, deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false, nil } if deployment.Status.AvailableReplicas < deployment.Status.UpdatedReplicas { - return fmt.Sprintf("Waiting for rollout to finish: %d of %d updated replicas are available...\n", deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas), false, nil + return fmt.Sprintf("Waiting for deployment %q rollout to finish: %d of %d updated replicas are available...\n", name, deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas), false, nil } return fmt.Sprintf("deployment %q successfully rolled out\n", name), true, nil } @@ -104,15 +104,15 @@ func (s *DaemonSetStatusViewer) Status(namespace, name string, revision int64) ( if err != nil { return "", false, err } - if daemon.Spec.UpdateStrategy.Type != extensionsv1beta1.RollingUpdateDaemonSetStrategyType { + if daemon.Spec.UpdateStrategy.Type != appsv1.RollingUpdateDaemonSetStrategyType { return "", true, fmt.Errorf("Status is available only for RollingUpdate strategy type") } if daemon.Generation <= daemon.Status.ObservedGeneration { if daemon.Status.UpdatedNumberScheduled < daemon.Status.DesiredNumberScheduled { - return fmt.Sprintf("Waiting for rollout to finish: %d out of %d new pods have been updated...\n", daemon.Status.UpdatedNumberScheduled, daemon.Status.DesiredNumberScheduled), false, nil + return fmt.Sprintf("Waiting for daemon set %q rollout to finish: %d out of %d new pods have been updated...\n", name, daemon.Status.UpdatedNumberScheduled, daemon.Status.DesiredNumberScheduled), false, nil } if daemon.Status.NumberAvailable < daemon.Status.DesiredNumberScheduled { - return fmt.Sprintf("Waiting for rollout to finish: %d of %d updated pods are available...\n", daemon.Status.NumberAvailable, daemon.Status.DesiredNumberScheduled), false, nil + return fmt.Sprintf("Waiting for daemon set %q rollout to finish: %d of %d updated pods are available...\n", name, daemon.Status.NumberAvailable, daemon.Status.DesiredNumberScheduled), false, nil } return fmt.Sprintf("daemon set %q successfully rolled out\n", name), true, nil } @@ -128,7 +128,7 @@ func (s *StatefulSetStatusViewer) Status(namespace, name string, revision int64) if sts.Spec.UpdateStrategy.Type == apps.OnDeleteStatefulSetStrategyType { return "", true, fmt.Errorf("%s updateStrategy does not have a Status`", apps.OnDeleteStatefulSetStrategyType) } - if sts.Status.ObservedGeneration == nil || sts.Generation > *sts.Status.ObservedGeneration { + if sts.Status.ObservedGeneration == 0 || sts.Generation > sts.Status.ObservedGeneration { return "Waiting for statefulset spec update to be observed...\n", false, nil } if sts.Spec.Replicas != nil && sts.Status.ReadyReplicas < *sts.Spec.Replicas { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/rollout_status_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/rollout_status_test.go index 38fd2348f..ae346f116 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/rollout_status_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/rollout_status_test.go @@ -20,9 +20,8 @@ import ( "fmt" "testing" - apps "k8s.io/api/apps/v1beta1" + apps "k8s.io/api/apps/v1" api "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" ) @@ -31,14 +30,14 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { tests := []struct { generation int64 specReplicas int32 - status extensions.DeploymentStatus + status apps.DeploymentStatus msg string done bool }{ { generation: 0, specReplicas: 1, - status: extensions.DeploymentStatus{ + status: apps.DeploymentStatus{ ObservedGeneration: 1, Replicas: 1, UpdatedReplicas: 0, @@ -46,13 +45,13 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { UnavailableReplicas: 0, }, - msg: "Waiting for rollout to finish: 0 out of 1 new replicas have been updated...\n", + msg: "Waiting for deployment \"foo\" rollout to finish: 0 out of 1 new replicas have been updated...\n", done: false, }, { generation: 1, specReplicas: 1, - status: extensions.DeploymentStatus{ + status: apps.DeploymentStatus{ ObservedGeneration: 1, Replicas: 2, UpdatedReplicas: 1, @@ -60,13 +59,13 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { UnavailableReplicas: 0, }, - msg: "Waiting for rollout to finish: 1 old replicas are pending termination...\n", + msg: "Waiting for deployment \"foo\" rollout to finish: 1 old replicas are pending termination...\n", done: false, }, { generation: 1, specReplicas: 2, - status: extensions.DeploymentStatus{ + status: apps.DeploymentStatus{ ObservedGeneration: 1, Replicas: 2, UpdatedReplicas: 2, @@ -74,13 +73,13 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { UnavailableReplicas: 1, }, - msg: "Waiting for rollout to finish: 1 of 2 updated replicas are available...\n", + msg: "Waiting for deployment \"foo\" rollout to finish: 1 of 2 updated replicas are available...\n", done: false, }, { generation: 1, specReplicas: 2, - status: extensions.DeploymentStatus{ + status: apps.DeploymentStatus{ ObservedGeneration: 1, Replicas: 2, UpdatedReplicas: 2, @@ -94,7 +93,7 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { { generation: 2, specReplicas: 2, - status: extensions.DeploymentStatus{ + status: apps.DeploymentStatus{ ObservedGeneration: 1, Replicas: 2, UpdatedReplicas: 2, @@ -108,19 +107,19 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { } for _, test := range tests { - d := &extensions.Deployment{ + d := &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ Namespace: "bar", Name: "foo", UID: "8764ae47-9092-11e4-8393-42010af018ff", Generation: test.generation, }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: &test.specReplicas, }, Status: test.status, } - client := fake.NewSimpleClientset(d).Extensions() + client := fake.NewSimpleClientset(d).Apps() dsv := &DeploymentStatusViewer{c: client} msg, done, err := dsv.Status("bar", "foo", 0) if err != nil { @@ -143,37 +142,37 @@ func TestDeploymentStatusViewerStatus(t *testing.T) { func TestDaemonSetStatusViewerStatus(t *testing.T) { tests := []struct { generation int64 - status extensions.DaemonSetStatus + status apps.DaemonSetStatus msg string done bool }{ { generation: 0, - status: extensions.DaemonSetStatus{ + status: apps.DaemonSetStatus{ ObservedGeneration: 1, UpdatedNumberScheduled: 0, DesiredNumberScheduled: 1, NumberAvailable: 0, }, - msg: "Waiting for rollout to finish: 0 out of 1 new pods have been updated...\n", + msg: "Waiting for daemon set \"foo\" rollout to finish: 0 out of 1 new pods have been updated...\n", done: false, }, { generation: 1, - status: extensions.DaemonSetStatus{ + status: apps.DaemonSetStatus{ ObservedGeneration: 1, UpdatedNumberScheduled: 2, DesiredNumberScheduled: 2, NumberAvailable: 1, }, - msg: "Waiting for rollout to finish: 1 of 2 updated pods are available...\n", + msg: "Waiting for daemon set \"foo\" rollout to finish: 1 of 2 updated pods are available...\n", done: false, }, { generation: 1, - status: extensions.DaemonSetStatus{ + status: apps.DaemonSetStatus{ ObservedGeneration: 1, UpdatedNumberScheduled: 2, DesiredNumberScheduled: 2, @@ -185,7 +184,7 @@ func TestDaemonSetStatusViewerStatus(t *testing.T) { }, { generation: 2, - status: extensions.DaemonSetStatus{ + status: apps.DaemonSetStatus{ ObservedGeneration: 1, UpdatedNumberScheduled: 2, DesiredNumberScheduled: 2, @@ -200,21 +199,21 @@ func TestDaemonSetStatusViewerStatus(t *testing.T) { for i := range tests { test := tests[i] t.Logf("testing scenario %d", i) - d := &extensions.DaemonSet{ + d := &apps.DaemonSet{ ObjectMeta: metav1.ObjectMeta{ Namespace: "bar", Name: "foo", UID: "8764ae47-9092-11e4-8393-42010af018ff", Generation: test.generation, }, - Spec: extensions.DaemonSetSpec{ - UpdateStrategy: extensions.DaemonSetUpdateStrategy{ - Type: extensions.RollingUpdateDaemonSetStrategyType, + Spec: apps.DaemonSetSpec{ + UpdateStrategy: apps.DaemonSetUpdateStrategy{ + Type: apps.RollingUpdateDaemonSetStrategyType, }, }, Status: test.status, } - client := fake.NewSimpleClientset(d).Extensions() + client := fake.NewSimpleClientset(d).Apps() dsv := &DaemonSetStatusViewer{c: client} msg, done, err := dsv.Status("bar", "foo", 0) if err != nil { @@ -249,14 +248,11 @@ func TestStatefulSetStatusViewerStatus(t *testing.T) { generation: 1, strategy: apps.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType}, status: apps.StatefulSetStatus{ - ObservedGeneration: func() *int64 { - generation := int64(1) - return &generation - }(), - Replicas: 0, - ReadyReplicas: 1, - CurrentReplicas: 0, - UpdatedReplicas: 0, + ObservedGeneration: 1, + Replicas: 0, + ReadyReplicas: 1, + CurrentReplicas: 0, + UpdatedReplicas: 0, }, msg: "", @@ -268,14 +264,11 @@ func TestStatefulSetStatusViewerStatus(t *testing.T) { generation: 2, strategy: apps.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType}, status: apps.StatefulSetStatus{ - ObservedGeneration: func() *int64 { - generation := int64(1) - return &generation - }(), - Replicas: 3, - ReadyReplicas: 3, - CurrentReplicas: 3, - UpdatedReplicas: 0, + ObservedGeneration: 1, + Replicas: 3, + ReadyReplicas: 3, + CurrentReplicas: 3, + UpdatedReplicas: 0, }, msg: "Waiting for statefulset spec update to be observed...\n", @@ -287,14 +280,11 @@ func TestStatefulSetStatusViewerStatus(t *testing.T) { generation: 1, strategy: apps.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType}, status: apps.StatefulSetStatus{ - ObservedGeneration: func() *int64 { - generation := int64(2) - return &generation - }(), - Replicas: 3, - ReadyReplicas: 2, - CurrentReplicas: 3, - UpdatedReplicas: 0, + ObservedGeneration: 2, + Replicas: 3, + ReadyReplicas: 2, + CurrentReplicas: 3, + UpdatedReplicas: 0, }, msg: fmt.Sprintf("Waiting for %d pods to be ready...\n", 1), @@ -310,14 +300,11 @@ func TestStatefulSetStatusViewerStatus(t *testing.T) { return &apps.RollingUpdateStatefulSetStrategy{Partition: &partition} }()}, status: apps.StatefulSetStatus{ - ObservedGeneration: func() *int64 { - generation := int64(2) - return &generation - }(), - Replicas: 3, - ReadyReplicas: 3, - CurrentReplicas: 2, - UpdatedReplicas: 1, + ObservedGeneration: 2, + Replicas: 3, + ReadyReplicas: 3, + CurrentReplicas: 2, + UpdatedReplicas: 1, }, msg: fmt.Sprintf("partitioned roll out complete: %d new pods have been updated...\n", 1), @@ -333,14 +320,11 @@ func TestStatefulSetStatusViewerStatus(t *testing.T) { return &apps.RollingUpdateStatefulSetStrategy{Partition: &partition} }()}, status: apps.StatefulSetStatus{ - ObservedGeneration: func() *int64 { - generation := int64(2) - return &generation - }(), - Replicas: 3, - ReadyReplicas: 3, - CurrentReplicas: 3, - UpdatedReplicas: 0, + ObservedGeneration: 2, + Replicas: 3, + ReadyReplicas: 3, + CurrentReplicas: 3, + UpdatedReplicas: 0, }, msg: fmt.Sprintf("Waiting for partitioned roll out to finish: %d out of %d new pods have been updated...\n", 0, 1), @@ -352,16 +336,13 @@ func TestStatefulSetStatusViewerStatus(t *testing.T) { generation: 1, strategy: apps.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType}, status: apps.StatefulSetStatus{ - ObservedGeneration: func() *int64 { - generation := int64(2) - return &generation - }(), - Replicas: 3, - ReadyReplicas: 3, - CurrentReplicas: 3, - UpdatedReplicas: 3, - CurrentRevision: "foo", - UpdateRevision: "foo", + ObservedGeneration: 2, + Replicas: 3, + ReadyReplicas: 3, + CurrentReplicas: 3, + UpdatedReplicas: 3, + CurrentRevision: "foo", + UpdateRevision: "foo", }, msg: fmt.Sprintf("statefulset rolling update complete %d pods at revision %s...\n", 3, "foo"), @@ -375,7 +356,7 @@ func TestStatefulSetStatusViewerStatus(t *testing.T) { s.Status = test.status s.Spec.UpdateStrategy = test.strategy s.Generation = test.generation - client := fake.NewSimpleClientset(s).AppsV1beta1() + client := fake.NewSimpleClientset(s).AppsV1() dsv := &StatefulSetStatusViewer{c: client} msg, done, err := dsv.Status(s.Namespace, s.Name, 0) if test.err && err == nil { @@ -394,19 +375,19 @@ func TestStatefulSetStatusViewerStatus(t *testing.T) { } func TestDaemonSetStatusViewerStatusWithWrongUpdateStrategyType(t *testing.T) { - d := &extensions.DaemonSet{ + d := &apps.DaemonSet{ ObjectMeta: metav1.ObjectMeta{ Namespace: "bar", Name: "foo", UID: "8764ae47-9092-11e4-8393-42010af018ff", }, - Spec: extensions.DaemonSetSpec{ - UpdateStrategy: extensions.DaemonSetUpdateStrategy{ - Type: extensions.OnDeleteDaemonSetStrategyType, + Spec: apps.DaemonSetSpec{ + UpdateStrategy: apps.DaemonSetUpdateStrategy{ + Type: apps.OnDeleteDaemonSetStrategyType, }, }, } - client := fake.NewSimpleClientset(d).Extensions() + client := fake.NewSimpleClientset(d).Apps() dsv := &DaemonSetStatusViewer{c: client} msg, done, err := dsv.Status("bar", "foo", 0) errMsg := "Status is available only for RollingUpdate strategy type" diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/run.go b/vendor/k8s.io/kubernetes/pkg/kubectl/run.go index e78bfd4c3..554996b62 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/run.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/run.go @@ -233,7 +233,7 @@ func getName(params map[string]string) (string, error) { if !found || len(name) == 0 { name, found = params["default-name"] if !found || len(name) == 0 { - return "", fmt.Errorf("'name' is a required parameter.") + return "", fmt.Errorf("'name' is a required parameter") } } return name, nil diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/scale.go b/vendor/k8s.io/kubernetes/pkg/kubectl/scale.go index 99e4b365d..f1d46b7a1 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/scale.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/scale.go @@ -23,19 +23,10 @@ import ( autoscalingapi "k8s.io/api/autoscaling/v1" "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/apis/batch" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" scaleclient "k8s.io/client-go/scale" - appsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion" - batchclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion" - coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion" ) // TODO: Figure out if we should be waiting on initializers in the Scale() functions below. @@ -46,23 +37,15 @@ type Scaler interface { // retries in the event of resource version mismatch (if retry is not nil), // and optionally waits until the status of the resource matches newSize (if wait is not nil) // TODO: Make the implementation of this watch-based (#56075) once #31345 is fixed. - Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, wait *RetryParams) error + Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, wait *RetryParams, gr schema.GroupResource) error // ScaleSimple does a simple one-shot attempt at scaling - not useful on its own, but // a necessary building block for Scale - ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (updatedResourceVersion string, err error) + ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint, gr schema.GroupResource) (updatedResourceVersion string, err error) } -// ScalerFor gets a scaler for a given resource -func ScalerFor(kind schema.GroupKind, jobsClient batchclient.JobsGetter, scalesGetter scaleclient.ScalesGetter, gr schema.GroupResource) Scaler { - // it seems like jobs dont't follow "normal" scale semantics. - // For example it is not clear whether HPA could make use of it or not. - // For more details see: https://github.com/kubernetes/kubernetes/pull/58468 - switch kind { - case batch.Kind("Job"): - return &jobScaler{jobsClient} // Either kind of job can be scaled with Batch interface. - default: - return &genericScaler{scalesGetter, gr} - } +// NewScaler get a scaler for a given resource +func NewScaler(scalesGetter scaleclient.ScalesGetter) Scaler { + return &genericScaler{scalesGetter} } // ScalePrecondition describes a condition that must be true for the scale to take place @@ -86,30 +69,6 @@ func (pe PreconditionError) Error() string { return fmt.Sprintf("Expected %s to be %s, was %s", pe.Precondition, pe.ExpectedValue, pe.ActualValue) } -type ScaleErrorType int - -const ( - ScaleGetFailure ScaleErrorType = iota - ScaleUpdateFailure - ScaleUpdateConflictFailure -) - -// A ScaleError is returned when a scale request passes -// preconditions but fails to actually scale the controller. -type ScaleError struct { - FailureType ScaleErrorType - ResourceVersion string - ActualError error -} - -func (c ScaleError) Error() string { - msg := fmt.Sprintf("Scaling the resource failed with: %v", c.ActualError) - if len(c.ResourceVersion) > 0 { - msg += fmt.Sprintf("; Current resource version %s", c.ResourceVersion) - } - return msg -} - // RetryParams encapsulates the retry parameters used by kubectl's scaler. type RetryParams struct { Interval, Timeout time.Duration @@ -120,381 +79,25 @@ func NewRetryParams(interval, timeout time.Duration) *RetryParams { } // ScaleCondition is a closure around Scale that facilitates retries via util.wait -func ScaleCondition(r Scaler, precondition *ScalePrecondition, namespace, name string, count uint, updatedResourceVersion *string) wait.ConditionFunc { +func ScaleCondition(r Scaler, precondition *ScalePrecondition, namespace, name string, count uint, updatedResourceVersion *string, gr schema.GroupResource) wait.ConditionFunc { return func() (bool, error) { - rv, err := r.ScaleSimple(namespace, name, precondition, count) + rv, err := r.ScaleSimple(namespace, name, precondition, count, gr) if updatedResourceVersion != nil { *updatedResourceVersion = rv } - switch e, _ := err.(ScaleError); err.(type) { - case nil: - return true, nil - case ScaleError: - // Retry only on update conflicts. - if e.FailureType == ScaleUpdateConflictFailure { - return false, nil - } - } - return false, err - } -} - -// ValidateStatefulSet ensures that the preconditions match. Returns nil if they are valid, an error otherwise. -func (precondition *ScalePrecondition) ValidateStatefulSet(ps *apps.StatefulSet) error { - if precondition.Size != -1 && int(ps.Spec.Replicas) != precondition.Size { - return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(int(ps.Spec.Replicas))} - } - if len(precondition.ResourceVersion) != 0 && ps.ResourceVersion != precondition.ResourceVersion { - return PreconditionError{"resource version", precondition.ResourceVersion, ps.ResourceVersion} - } - return nil -} - -// ValidateReplicationController ensures that the preconditions match. Returns nil if they are valid, an error otherwise -func (precondition *ScalePrecondition) ValidateReplicationController(controller *api.ReplicationController) error { - if precondition.Size != -1 && int(controller.Spec.Replicas) != precondition.Size { - return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(int(controller.Spec.Replicas))} - } - if len(precondition.ResourceVersion) != 0 && controller.ResourceVersion != precondition.ResourceVersion { - return PreconditionError{"resource version", precondition.ResourceVersion, controller.ResourceVersion} - } - return nil -} - -// TODO(p0lyn0mial): remove ReplicationControllerScaler -type ReplicationControllerScaler struct { - c coreclient.ReplicationControllersGetter -} - -// ScaleSimple does a simple one-shot attempt at scaling. It returns the -// resourceVersion of the replication controller if the update is successful. -func (scaler *ReplicationControllerScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (string, error) { - controller, err := scaler.c.ReplicationControllers(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return "", ScaleError{ScaleGetFailure, "", err} - } - if preconditions != nil { - if err := preconditions.ValidateReplicationController(controller); err != nil { - return "", err - } - } - controller.Spec.Replicas = int32(newSize) - updatedRC, err := scaler.c.ReplicationControllers(namespace).Update(controller) - if err != nil { + // Retry only on update conflicts. if errors.IsConflict(err) { - return "", ScaleError{ScaleUpdateConflictFailure, controller.ResourceVersion, err} + return false, nil } - return "", ScaleError{ScaleUpdateFailure, controller.ResourceVersion, err} - } - return updatedRC.ObjectMeta.ResourceVersion, nil -} - -// Scale updates a ReplicationController to a new size, with optional precondition check (if preconditions is not nil), -// optional retries (if retry is not nil), and then optionally waits for it's replica count to reach the new value -// (if wait is not nil). -func (scaler *ReplicationControllerScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error { - if preconditions == nil { - preconditions = &ScalePrecondition{-1, ""} - } - if retry == nil { - // Make it try only once, immediately - retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond} - } - cond := ScaleCondition(scaler, preconditions, namespace, name, newSize, nil) - if err := wait.PollImmediate(retry.Interval, retry.Timeout, cond); err != nil { - return err - } - if waitForReplicas != nil { - rc, err := scaler.c.ReplicationControllers(namespace).Get(name, metav1.GetOptions{}) if err != nil { - return err - } - if rc.Initializers != nil { - return nil - } - err = wait.PollImmediate(waitForReplicas.Interval, waitForReplicas.Timeout, ControllerHasDesiredReplicas(scaler.c, rc)) - if err == wait.ErrWaitTimeout { - return fmt.Errorf("timed out waiting for %q to be synced", name) - } - return err - } - return nil -} - -// ValidateReplicaSet ensures that the preconditions match. Returns nil if they are valid, an error otherwise -func (precondition *ScalePrecondition) ValidateReplicaSet(replicaSet *extensions.ReplicaSet) error { - if precondition.Size != -1 && int(replicaSet.Spec.Replicas) != precondition.Size { - return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(int(replicaSet.Spec.Replicas))} - } - if len(precondition.ResourceVersion) != 0 && replicaSet.ResourceVersion != precondition.ResourceVersion { - return PreconditionError{"resource version", precondition.ResourceVersion, replicaSet.ResourceVersion} - } - return nil -} - -// TODO(p0lyn0mial): remove ReplicaSetScaler -type ReplicaSetScaler struct { - c extensionsclient.ReplicaSetsGetter -} - -// ScaleSimple does a simple one-shot attempt at scaling. It returns the -// resourceVersion of the replicaset if the update is successful. -func (scaler *ReplicaSetScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (string, error) { - rs, err := scaler.c.ReplicaSets(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return "", ScaleError{ScaleGetFailure, "", err} - } - if preconditions != nil { - if err := preconditions.ValidateReplicaSet(rs); err != nil { - return "", err - } - } - rs.Spec.Replicas = int32(newSize) - updatedRS, err := scaler.c.ReplicaSets(namespace).Update(rs) - if err != nil { - if errors.IsConflict(err) { - return "", ScaleError{ScaleUpdateConflictFailure, rs.ResourceVersion, err} - } - return "", ScaleError{ScaleUpdateFailure, rs.ResourceVersion, err} - } - return updatedRS.ObjectMeta.ResourceVersion, nil -} - -// Scale updates a ReplicaSet to a new size, with optional precondition check (if preconditions is -// not nil), optional retries (if retry is not nil), and then optionally waits for it's replica -// count to reach the new value (if wait is not nil). -func (scaler *ReplicaSetScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error { - if preconditions == nil { - preconditions = &ScalePrecondition{-1, ""} - } - if retry == nil { - // Make it try only once, immediately - retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond} - } - cond := ScaleCondition(scaler, preconditions, namespace, name, newSize, nil) - if err := wait.PollImmediate(retry.Interval, retry.Timeout, cond); err != nil { - return err - } - if waitForReplicas != nil { - rs, err := scaler.c.ReplicaSets(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - if rs.Initializers != nil { - return nil - } - err = wait.PollImmediate(waitForReplicas.Interval, waitForReplicas.Timeout, ReplicaSetHasDesiredReplicas(scaler.c, rs)) - - if err == wait.ErrWaitTimeout { - return fmt.Errorf("timed out waiting for %q to be synced", name) - } - return err - } - return nil -} - -// ValidateJob ensures that the preconditions match. Returns nil if they are valid, an error otherwise. -func (precondition *ScalePrecondition) ValidateJob(job *batch.Job) error { - if precondition.Size != -1 && job.Spec.Parallelism == nil { - return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), "nil"} - } - if precondition.Size != -1 && int(*job.Spec.Parallelism) != precondition.Size { - return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), strconv.Itoa(int(*job.Spec.Parallelism))} - } - if len(precondition.ResourceVersion) != 0 && job.ResourceVersion != precondition.ResourceVersion { - return PreconditionError{"resource version", precondition.ResourceVersion, job.ResourceVersion} - } - return nil -} - -// TODO(p0lyn0mial): remove StatefulSetsGetter -type StatefulSetScaler struct { - c appsclient.StatefulSetsGetter -} - -// ScaleSimple does a simple one-shot attempt at scaling. It returns the -// resourceVersion of the statefulset if the update is successful. -func (scaler *StatefulSetScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (string, error) { - ss, err := scaler.c.StatefulSets(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return "", ScaleError{ScaleGetFailure, "", err} - } - if preconditions != nil { - if err := preconditions.ValidateStatefulSet(ss); err != nil { - return "", err - } - } - ss.Spec.Replicas = int32(newSize) - updatedStatefulSet, err := scaler.c.StatefulSets(namespace).Update(ss) - if err != nil { - if errors.IsConflict(err) { - return "", ScaleError{ScaleUpdateConflictFailure, ss.ResourceVersion, err} - } - return "", ScaleError{ScaleUpdateFailure, ss.ResourceVersion, err} - } - return updatedStatefulSet.ResourceVersion, nil -} - -func (scaler *StatefulSetScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error { - if preconditions == nil { - preconditions = &ScalePrecondition{-1, ""} - } - if retry == nil { - // Make it try only once, immediately - retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond} - } - cond := ScaleCondition(scaler, preconditions, namespace, name, newSize, nil) - if err := wait.PollImmediate(retry.Interval, retry.Timeout, cond); err != nil { - return err - } - if waitForReplicas != nil { - job, err := scaler.c.StatefulSets(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - if job.Initializers != nil { - return nil - } - err = wait.PollImmediate(waitForReplicas.Interval, waitForReplicas.Timeout, StatefulSetHasDesiredReplicas(scaler.c, job)) - if err == wait.ErrWaitTimeout { - return fmt.Errorf("timed out waiting for %q to be synced", name) - } - return err - } - return nil -} - -type jobScaler struct { - c batchclient.JobsGetter -} - -// ScaleSimple is responsible for updating job's parallelism. It returns the -// resourceVersion of the job if the update is successful. -func (scaler *jobScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (string, error) { - job, err := scaler.c.Jobs(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return "", ScaleError{ScaleGetFailure, "", err} - } - if preconditions != nil { - if err := preconditions.ValidateJob(job); err != nil { - return "", err - } - } - parallelism := int32(newSize) - job.Spec.Parallelism = ¶llelism - updatedJob, err := scaler.c.Jobs(namespace).Update(job) - if err != nil { - if errors.IsConflict(err) { - return "", ScaleError{ScaleUpdateConflictFailure, job.ResourceVersion, err} - } - return "", ScaleError{ScaleUpdateFailure, job.ResourceVersion, err} - } - return updatedJob.ObjectMeta.ResourceVersion, nil -} - -// Scale updates a Job to a new size, with optional precondition check (if preconditions is not nil), -// optional retries (if retry is not nil), and then optionally waits for parallelism to reach desired -// number, which can be less than requested based on job's current progress. -func (scaler *jobScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error { - if preconditions == nil { - preconditions = &ScalePrecondition{-1, ""} - } - if retry == nil { - // Make it try only once, immediately - retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond} - } - cond := ScaleCondition(scaler, preconditions, namespace, name, newSize, nil) - if err := wait.PollImmediate(retry.Interval, retry.Timeout, cond); err != nil { - return err - } - if waitForReplicas != nil { - job, err := scaler.c.Jobs(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - err = wait.PollImmediate(waitForReplicas.Interval, waitForReplicas.Timeout, JobHasDesiredParallelism(scaler.c, job)) - if err == wait.ErrWaitTimeout { - return fmt.Errorf("timed out waiting for %q to be synced", name) - } - return err - } - return nil -} - -// ValidateDeployment ensures that the preconditions match. Returns nil if they are valid, an error otherwise. -func (precondition *ScalePrecondition) ValidateDeployment(deployment *extensions.Deployment) error { - if precondition.Size != -1 && int(deployment.Spec.Replicas) != precondition.Size { - return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(int(deployment.Spec.Replicas))} - } - if len(precondition.ResourceVersion) != 0 && deployment.ResourceVersion != precondition.ResourceVersion { - return PreconditionError{"resource version", precondition.ResourceVersion, deployment.ResourceVersion} - } - return nil -} - -// TODO(p0lyn0mial): remove DeploymentScaler -type DeploymentScaler struct { - c extensionsclient.DeploymentsGetter -} - -// ScaleSimple is responsible for updating a deployment's desired replicas -// count. It returns the resourceVersion of the deployment if the update is -// successful. -func (scaler *DeploymentScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (string, error) { - deployment, err := scaler.c.Deployments(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return "", ScaleError{ScaleGetFailure, "", err} - } - if preconditions != nil { - if err := preconditions.ValidateDeployment(deployment); err != nil { - return "", err - } - } - - // TODO(madhusudancs): Fix this when Scale group issues are resolved (see issue #18528). - // For now I'm falling back to regular Deployment update operation. - deployment.Spec.Replicas = int32(newSize) - updatedDeployment, err := scaler.c.Deployments(namespace).Update(deployment) - if err != nil { - if errors.IsConflict(err) { - return "", ScaleError{ScaleUpdateConflictFailure, deployment.ResourceVersion, err} - } - return "", ScaleError{ScaleUpdateFailure, deployment.ResourceVersion, err} - } - return updatedDeployment.ObjectMeta.ResourceVersion, nil -} - -// Scale updates a deployment to a new size, with optional precondition check (if preconditions is not nil), -// optional retries (if retry is not nil), and then optionally waits for the status to reach desired count. -func (scaler *DeploymentScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error { - if preconditions == nil { - preconditions = &ScalePrecondition{-1, ""} - } - if retry == nil { - // Make it try only once, immediately - retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond} - } - cond := ScaleCondition(scaler, preconditions, namespace, name, newSize, nil) - if err := wait.PollImmediate(retry.Interval, retry.Timeout, cond); err != nil { - return err - } - if waitForReplicas != nil { - deployment, err := scaler.c.Deployments(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - err = wait.PollImmediate(waitForReplicas.Interval, waitForReplicas.Timeout, DeploymentHasDesiredReplicas(scaler.c, deployment)) - if err == wait.ErrWaitTimeout { - return fmt.Errorf("timed out waiting for %q to be synced", name) + return false, err } - return err + return true, nil } - return nil } // validateGeneric ensures that the preconditions match. Returns nil if they are valid, otherwise an error -// TODO(p0lyn0mial): when the work on GenericScaler is done, rename validateGeneric to validate -func (precondition *ScalePrecondition) validateGeneric(scale *autoscalingapi.Scale) error { +func (precondition *ScalePrecondition) validate(scale *autoscalingapi.Scale) error { if precondition.Size != -1 && int(scale.Spec.Replicas) != precondition.Size { return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(int(scale.Spec.Replicas))} } @@ -507,37 +110,33 @@ func (precondition *ScalePrecondition) validateGeneric(scale *autoscalingapi.Sca // genericScaler can update scales for resources in a particular namespace type genericScaler struct { scaleNamespacer scaleclient.ScalesGetter - targetGR schema.GroupResource } var _ Scaler = &genericScaler{} // ScaleSimple updates a scale of a given resource. It returns the resourceVersion of the scale if the update was successful. -func (s *genericScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (updatedResourceVersion string, err error) { - scale, err := s.scaleNamespacer.Scales(namespace).Get(s.targetGR, name) +func (s *genericScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint, gr schema.GroupResource) (updatedResourceVersion string, err error) { + scale, err := s.scaleNamespacer.Scales(namespace).Get(gr, name) if err != nil { - return "", ScaleError{ScaleGetFailure, "", err} + return "", err } if preconditions != nil { - if err := preconditions.validateGeneric(scale); err != nil { + if err := preconditions.validate(scale); err != nil { return "", err } } scale.Spec.Replicas = int32(newSize) - updatedScale, err := s.scaleNamespacer.Scales(namespace).Update(s.targetGR, scale) + updatedScale, err := s.scaleNamespacer.Scales(namespace).Update(gr, scale) if err != nil { - if errors.IsConflict(err) { - return "", ScaleError{ScaleUpdateConflictFailure, scale.ResourceVersion, err} - } - return "", ScaleError{ScaleUpdateFailure, scale.ResourceVersion, err} + return "", err } return updatedScale.ResourceVersion, nil } // Scale updates a scale of a given resource to a new size, with optional precondition check (if preconditions is not nil), // optional retries (if retry is not nil), and then optionally waits for the status to reach desired count. -func (s *genericScaler) Scale(namespace, resourceName string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error { +func (s *genericScaler) Scale(namespace, resourceName string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams, gr schema.GroupResource) error { if preconditions == nil { preconditions = &ScalePrecondition{-1, ""} } @@ -545,19 +144,12 @@ func (s *genericScaler) Scale(namespace, resourceName string, newSize uint, prec // make it try only once, immediately retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond} } - cond := ScaleCondition(s, preconditions, namespace, resourceName, newSize, nil) + cond := ScaleCondition(s, preconditions, namespace, resourceName, newSize, nil, gr) if err := wait.PollImmediate(retry.Interval, retry.Timeout, cond); err != nil { return err } if waitForReplicas != nil { - err := wait.PollImmediate( - waitForReplicas.Interval, - waitForReplicas.Timeout, - scaleHasDesiredReplicas(s.scaleNamespacer, s.targetGR, resourceName, namespace, int32(newSize))) - if err == wait.ErrWaitTimeout { - return fmt.Errorf("timed out waiting for %q to be synced", resourceName) - } - return err + return WaitForScaleHasDesiredReplicas(s.scaleNamespacer, gr, resourceName, namespace, newSize, waitForReplicas) } return nil } @@ -578,3 +170,19 @@ func scaleHasDesiredReplicas(sClient scaleclient.ScalesGetter, gr schema.GroupRe desiredReplicas == actualScale.Status.Replicas, nil } } + +// WaitForScaleHasDesiredReplicas waits until condition scaleHasDesiredReplicas is satisfied +// or returns error when timeout happens +func WaitForScaleHasDesiredReplicas(sClient scaleclient.ScalesGetter, gr schema.GroupResource, resourceName string, namespace string, newSize uint, waitForReplicas *RetryParams) error { + if waitForReplicas == nil { + return fmt.Errorf("waitForReplicas parameter cannot be nil!") + } + err := wait.PollImmediate( + waitForReplicas.Interval, + waitForReplicas.Timeout, + scaleHasDesiredReplicas(sClient, gr, resourceName, namespace, int32(newSize))) + if err == wait.ErrWaitTimeout { + return fmt.Errorf("timed out waiting for %q to be synced", resourceName) + } + return err +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/scale_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/scale_test.go index 65bf4beb8..2e79ce7da 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/scale_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/scale_test.go @@ -17,79 +17,34 @@ limitations under the License. package kubectl import ( - "bytes" - "encoding/json" - "errors" "fmt" - "io" - "io/ioutil" - "net/http" "testing" "time" - appsv1beta2 "k8s.io/api/apps/v1beta2" + autoscalingv1 "k8s.io/api/autoscaling/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" - apimeta "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/apimachinery/pkg/runtime/serializer" - "k8s.io/client-go/discovery" - fakedisco "k8s.io/client-go/discovery/fake" - "k8s.io/client-go/dynamic" - fakerest "k8s.io/client-go/rest/fake" "k8s.io/client-go/scale" + fakescale "k8s.io/client-go/scale/fake" testcore "k8s.io/client-go/testing" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/apis/batch" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - appsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion" - batchclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion" - coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion" ) -type ErrorReplicationControllers struct { - coreclient.ReplicationControllerInterface - conflict bool - invalid bool -} - -func (c *ErrorReplicationControllers) Update(controller *api.ReplicationController) (*api.ReplicationController, error) { - switch { - case c.invalid: - return nil, kerrors.NewInvalid(api.Kind(controller.Kind), controller.Name, nil) - case c.conflict: - return nil, kerrors.NewConflict(api.Resource(controller.Kind), controller.Name, nil) - } - return nil, errors.New("Replication controller update failure") -} - -type ErrorReplicationControllerClient struct { - *fake.Clientset - conflict bool - invalid bool -} - -func (c *ErrorReplicationControllerClient) ReplicationControllers(namespace string) coreclient.ReplicationControllerInterface { - return &ErrorReplicationControllers{ - ReplicationControllerInterface: c.Clientset.Core().ReplicationControllers(namespace), - conflict: c.conflict, - invalid: c.invalid, - } -} - func TestReplicationControllerScaleRetry(t *testing.T) { - fake := &ErrorReplicationControllerClient{Clientset: fake.NewSimpleClientset(oldRc(0, 0)), conflict: true} - scaler := ReplicationControllerScaler{fake} + verbsOnError := map[string]*kerrors.StatusError{ + "update": kerrors.NewConflict(api.Resource("Status"), "foo", nil), + } + scaleClientExpectedAction := []string{"get", "update", "get"} + scaleClient := createFakeScaleClient("replicationcontrollers", "foo-v1", 2, verbsOnError) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{-1, ""} count := uint(3) name := "foo-v1" namespace := metav1.NamespaceDefault - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count, nil) + scaleFunc := ScaleCondition(scaler, &preconditions, namespace, name, count, nil, schema.GroupResource{Group: "", Resource: "replicationcontrollers"}) pass, err := scaleFunc() if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -98,499 +53,111 @@ func TestReplicationControllerScaleRetry(t *testing.T) { t.Errorf("Did not expect an error on update conflict failure, got %v", err) } preconditions = ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(&scaler, &preconditions, namespace, name, count, nil) + scaleFunc = ScaleCondition(scaler, &preconditions, namespace, name, count, nil, schema.GroupResource{Group: "", Resource: "replicationcontrollers"}) pass, err = scaleFunc() if err == nil { t.Errorf("Expected error on precondition failure") } + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) + } + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } + } } func TestReplicationControllerScaleInvalid(t *testing.T) { - fake := &ErrorReplicationControllerClient{Clientset: fake.NewSimpleClientset(oldRc(0, 0)), invalid: true} - scaler := ReplicationControllerScaler{fake} + verbsOnError := map[string]*kerrors.StatusError{ + "update": kerrors.NewInvalid(api.Kind("Status"), "foo", nil), + } + scaleClientExpectedAction := []string{"get", "update"} + scaleClient := createFakeScaleClient("replicationcontrollers", "foo-v1", 1, verbsOnError) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{-1, ""} count := uint(3) name := "foo-v1" namespace := "default" - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count, nil) + scaleFunc := ScaleCondition(scaler, &preconditions, namespace, name, count, nil, schema.GroupResource{Group: "", Resource: "replicationcontrollers"}) pass, err := scaleFunc() if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) } - e, ok := err.(ScaleError) - if err == nil || !ok || e.FailureType != ScaleUpdateFailure { + if err == nil { t.Errorf("Expected error on invalid update failure, got %v", err) } -} - -func TestReplicationControllerScale(t *testing.T) { - fake := fake.NewSimpleClientset(oldRc(0, 0)) - scaler := ReplicationControllerScaler{fake.Core()} - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo-v1" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 2 { - t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions) - } - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != api.Resource("replicationcontrollers") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name) - } - if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != api.Resource("replicationcontrollers") || action.GetObject().(*api.ReplicationController).Spec.Replicas != int32(count) { - t.Errorf("unexpected action %v, expected update-replicationController with replicas = %d", actions[1], count) - } -} - -func TestReplicationControllerScaleFailsPreconditions(t *testing.T) { - fake := fake.NewSimpleClientset(&api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"}, - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }) - scaler := ReplicationControllerScaler{fake.Core()} - preconditions := ScalePrecondition{2, ""} - count := uint(3) - name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 1 { - t.Errorf("unexpected actions: %v, expected 1 action (get)", actions) - } - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != api.Resource("replicationcontrollers") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name) - } -} - -func TestValidateReplicationController(t *testing.T) { - tests := []struct { - preconditions ScalePrecondition - controller api.ReplicationController - expectError bool - test string - }{ - { - preconditions: ScalePrecondition{-1, ""}, - expectError: false, - test: "defaults", - }, - { - preconditions: ScalePrecondition{-1, ""}, - controller: api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }, - expectError: false, - test: "defaults 2", - }, - { - preconditions: ScalePrecondition{0, ""}, - controller: api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - }, - }, - expectError: false, - test: "size matches", - }, - { - preconditions: ScalePrecondition{-1, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }, - expectError: false, - test: "resource version matches", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }, - expectError: false, - test: "both match", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 20, - }, - }, - expectError: true, - test: "size different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }, - expectError: true, - test: "version different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 20, - }, - }, - expectError: true, - test: "both different", - }, + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) } - for _, test := range tests { - err := test.preconditions.ValidateReplicationController(&test.controller) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - if err == nil && test.expectError { - t.Errorf("expected an error: %v (%s)", err, test.test) + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) } } } -type errorJobs struct { - batchclient.JobInterface - conflict bool - invalid bool -} - -func (c *errorJobs) Update(job *batch.Job) (*batch.Job, error) { - switch { - case c.invalid: - return nil, kerrors.NewInvalid(api.Kind(job.Kind), job.Name, nil) - case c.conflict: - return nil, kerrors.NewConflict(api.Resource(job.Kind), job.Name, nil) - } - return nil, errors.New("Job update failure") -} - -func (c *errorJobs) Get(name string, options metav1.GetOptions) (*batch.Job, error) { - zero := int32(0) - return &batch.Job{ - Spec: batch.JobSpec{ - Parallelism: &zero, - }, - }, nil -} - -type errorJobClient struct { - batchclient.JobsGetter - conflict bool - invalid bool -} - -func (c *errorJobClient) Jobs(namespace string) batchclient.JobInterface { - return &errorJobs{ - JobInterface: c.JobsGetter.Jobs(namespace), - conflict: c.conflict, - invalid: c.invalid, - } -} - -func TestJobScaleRetry(t *testing.T) { - fake := &errorJobClient{JobsGetter: fake.NewSimpleClientset().Batch(), conflict: true} - scaler := ScalerFor(schema.GroupKind{Group: batch.GroupName, Kind: "Job"}, fake, nil, schema.GroupResource{}) +func TestReplicationControllerScale(t *testing.T) { + scaleClientExpectedAction := []string{"get", "update"} + scaleClient := createFakeScaleClient("replicationcontrollers", "foo-v1", 2, nil) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{-1, ""} count := uint(3) - name := "foo" - namespace := "default" + name := "foo-v1" + err := scaler.Scale("default", name, count, &preconditions, nil, nil, schema.GroupResource{Group: "", Resource: "replicationcontrollers"}) - scaleFunc := ScaleCondition(scaler, &preconditions, namespace, name, count, nil) - pass, err := scaleFunc() - if pass != false { - t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) - } if err != nil { - t.Errorf("Did not expect an error on update failure, got %v", err) - } - preconditions = ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(scaler, &preconditions, namespace, name, count, nil) - pass, err = scaleFunc() - if err == nil { - t.Error("Expected error on precondition failure") - } -} - -func job() *batch.Job { - return &batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: "foo", - }, - } -} - -func TestJobScale(t *testing.T) { - fakeClientset := fake.NewSimpleClientset(job()) - scaler := ScalerFor(schema.GroupKind{Group: batch.GroupName, Kind: "Job"}, fakeClientset.Batch(), nil, schema.GroupResource{}) - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fakeClientset.Actions() - if len(actions) != 2 { - t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions) + t.Fatalf("unexpected error occurred = %v while scaling the resource", err) } - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != batch.Resource("jobs") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-job %s", actions[0], name) + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) } - if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != batch.Resource("jobs") || *action.GetObject().(*batch.Job).Spec.Parallelism != int32(count) { - t.Errorf("unexpected action %v, expected update-job with parallelism = %d", actions[1], count) - } -} - -func TestJobScaleInvalid(t *testing.T) { - fake := &errorJobClient{JobsGetter: fake.NewSimpleClientset().Batch(), invalid: true} - scaler := ScalerFor(schema.GroupKind{Group: batch.GroupName, Kind: "Job"}, fake, nil, schema.GroupResource{}) - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - namespace := "default" - - scaleFunc := ScaleCondition(scaler, &preconditions, namespace, name, count, nil) - pass, err := scaleFunc() - if pass { - t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) - } - e, ok := err.(ScaleError) - if err == nil || !ok || e.FailureType != ScaleUpdateFailure { - t.Errorf("Expected error on invalid update failure, got %v", err) + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } } } -func TestJobScaleFailsPreconditions(t *testing.T) { - ten := int32(10) - fake := fake.NewSimpleClientset(&batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }) - scaler := ScalerFor(schema.GroupKind{Group: batch.GroupName, Kind: "Job"}, fake.Batch(), nil, schema.GroupResource{}) +func TestReplicationControllerScaleFailsPreconditions(t *testing.T) { + scaleClientExpectedAction := []string{"get"} + scaleClient := createFakeScaleClient("replicationcontrollers", "foo", 10, nil) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{2, ""} count := uint(3) name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 1 { - t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions) - } - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != batch.Resource("jobs") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-job %s", actions[0], name) + err := scaler.Scale("default", name, count, &preconditions, nil, nil, schema.GroupResource{Group: "", Resource: "replicationcontrollers"}) + if err == nil { + t.Fatal("expected to get an error but none was returned") } -} - -func TestValidateJob(t *testing.T) { - zero, ten, twenty := int32(0), int32(10), int32(20) - tests := []struct { - preconditions ScalePrecondition - job batch.Job - expectError bool - test string - }{ - { - preconditions: ScalePrecondition{-1, ""}, - expectError: false, - test: "defaults", - }, - { - preconditions: ScalePrecondition{-1, ""}, - job: batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }, - expectError: false, - test: "defaults 2", - }, - { - preconditions: ScalePrecondition{0, ""}, - job: batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &zero, - }, - }, - expectError: false, - test: "size matches", - }, - { - preconditions: ScalePrecondition{-1, "foo"}, - job: batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }, - expectError: false, - test: "resource version matches", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }, - expectError: false, - test: "both match", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &twenty, - }, - }, - expectError: true, - test: "size different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - }, - expectError: true, - test: "parallelism nil", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }, - expectError: true, - test: "version different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: batch.JobSpec{ - Parallelism: &twenty, - }, - }, - expectError: true, - test: "both different", - }, + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) } - for _, test := range tests { - err := test.preconditions.ValidateJob(&test.job) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) } - if err == nil && test.expectError { - t.Errorf("expected an error: %v (%s)", err, test.test) - } - } -} - -type ErrorDeployments struct { - extensionsclient.DeploymentInterface - conflict bool - invalid bool -} - -func (c *ErrorDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) { - switch { - case c.invalid: - return nil, kerrors.NewInvalid(api.Kind(deployment.Kind), deployment.Name, nil) - case c.conflict: - return nil, kerrors.NewConflict(api.Resource(deployment.Kind), deployment.Name, nil) - } - return nil, errors.New("deployment update failure") -} - -func (c *ErrorDeployments) Get(name string, options metav1.GetOptions) (*extensions.Deployment, error) { - return &extensions.Deployment{ - Spec: extensions.DeploymentSpec{ - Replicas: 0, - }, - }, nil -} - -type ErrorDeploymentClient struct { - extensionsclient.DeploymentsGetter - conflict bool - invalid bool -} - -func (c *ErrorDeploymentClient) Deployments(namespace string) extensionsclient.DeploymentInterface { - return &ErrorDeployments{ - DeploymentInterface: c.DeploymentsGetter.Deployments(namespace), - invalid: c.invalid, - conflict: c.conflict, } } func TestDeploymentScaleRetry(t *testing.T) { - fake := &ErrorDeploymentClient{DeploymentsGetter: fake.NewSimpleClientset().Extensions(), conflict: true} - scaler := &DeploymentScaler{fake} + verbsOnError := map[string]*kerrors.StatusError{ + "update": kerrors.NewConflict(api.Resource("Status"), "foo", nil), + } + scaleClientExpectedAction := []string{"get", "update", "get"} + scaleClient := createFakeScaleClient("deployments", "foo", 2, verbsOnError) + scaler := NewScaler(scaleClient) preconditions := &ScalePrecondition{-1, ""} count := uint(3) name := "foo" namespace := "default" - scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count, nil) + scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count, nil, schema.GroupResource{Group: "apps", Resource: "deployments"}) pass, err := scaleFunc() if pass != false { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -599,289 +166,132 @@ func TestDeploymentScaleRetry(t *testing.T) { t.Errorf("Did not expect an error on update failure, got %v", err) } preconditions = &ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil) + scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil, schema.GroupResource{Group: "apps", Resource: "deployments"}) pass, err = scaleFunc() if err == nil { t.Error("Expected error on precondition failure") } -} - -func deployment() *extensions.Deployment { - return &extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: "foo", - }, + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) + } + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } } } func TestDeploymentScale(t *testing.T) { - fake := fake.NewSimpleClientset(deployment()) - scaler := DeploymentScaler{fake.Extensions()} + scaleClientExpectedAction := []string{"get", "update"} + scaleClient := createFakeScaleClient("deployments", "foo", 2, nil) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{-1, ""} count := uint(3) name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 2 { - t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions) + err := scaler.Scale("default", name, count, &preconditions, nil, nil, schema.GroupResource{Group: "apps", Resource: "deployments"}) + if err != nil { + t.Fatal(err) } - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != extensions.Resource("deployments") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-deployment %s", actions[0], name) + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) } - if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != extensions.Resource("deployments") || action.GetObject().(*extensions.Deployment).Spec.Replicas != int32(count) { - t.Errorf("unexpected action %v, expected update-deployment with replicas = %d", actions[1], count) + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } } } func TestDeploymentScaleInvalid(t *testing.T) { - fake := &ErrorDeploymentClient{DeploymentsGetter: fake.NewSimpleClientset().Extensions(), invalid: true} - scaler := DeploymentScaler{fake} + scaleClientExpectedAction := []string{"get", "update"} + verbsOnError := map[string]*kerrors.StatusError{ + "update": kerrors.NewInvalid(api.Kind("Status"), "foo", nil), + } + scaleClient := createFakeScaleClient("deployments", "foo", 2, verbsOnError) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{-1, ""} count := uint(3) name := "foo" namespace := "default" - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count, nil) + scaleFunc := ScaleCondition(scaler, &preconditions, namespace, name, count, nil, schema.GroupResource{Group: "apps", Resource: "deployments"}) pass, err := scaleFunc() if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) } - e, ok := err.(ScaleError) - if err == nil || !ok || e.FailureType != ScaleUpdateFailure { + if err == nil { t.Errorf("Expected error on invalid update failure, got %v", err) } + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) + } + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } + } } func TestDeploymentScaleFailsPreconditions(t *testing.T) { - fake := fake.NewSimpleClientset(&extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: 10, - }, - }) - scaler := DeploymentScaler{fake.Extensions()} + scaleClientExpectedAction := []string{"get"} + scaleClient := createFakeScaleClient("deployments", "foo", 10, nil) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{2, ""} count := uint(3) name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 1 { - t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions) - } - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != extensions.Resource("deployments") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-deployment %s", actions[0], name) + err := scaler.Scale("default", name, count, &preconditions, nil, nil, schema.GroupResource{Group: "apps", Resource: "deployments"}) + if err == nil { + t.Fatal("exptected to get an error but none was returned") } -} - -func TestValidateDeployment(t *testing.T) { - zero, ten, twenty := int32(0), int32(10), int32(20) - tests := []struct { - preconditions ScalePrecondition - deployment extensions.Deployment - expectError bool - test string - }{ - { - preconditions: ScalePrecondition{-1, ""}, - expectError: false, - test: "defaults", - }, - { - preconditions: ScalePrecondition{-1, ""}, - deployment: extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "defaults 2", - }, - { - preconditions: ScalePrecondition{0, ""}, - deployment: extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: zero, - }, - }, - expectError: false, - test: "size matches", - }, - { - preconditions: ScalePrecondition{-1, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "resource version matches", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "both match", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: twenty, - }, - }, - expectError: true, - test: "size different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - }, - expectError: true, - test: "no replicas", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: extensions.DeploymentSpec{ - Replicas: ten, - }, - }, - expectError: true, - test: "version different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: extensions.DeploymentSpec{ - Replicas: twenty, - }, - }, - expectError: true, - test: "both different", - }, + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) } - for _, test := range tests { - err := test.preconditions.ValidateDeployment(&test.deployment) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) } - if err == nil && test.expectError { - t.Errorf("expected an error: %v (%s)", err, test.test) - } - } -} - -type ErrorStatefulSets struct { - appsclient.StatefulSetInterface - conflict bool - invalid bool -} - -func (c *ErrorStatefulSets) Update(statefulSet *apps.StatefulSet) (*apps.StatefulSet, error) { - switch { - case c.invalid: - return nil, kerrors.NewInvalid(api.Kind(statefulSet.Kind), statefulSet.Name, nil) - case c.conflict: - return nil, kerrors.NewConflict(api.Resource(statefulSet.Kind), statefulSet.Name, nil) - } - return nil, errors.New("statefulSet update failure") -} - -func (c *ErrorStatefulSets) Get(name string, options metav1.GetOptions) (*apps.StatefulSet, error) { - return &apps.StatefulSet{ - Spec: apps.StatefulSetSpec{ - Replicas: 0, - }, - }, nil -} - -type ErrorStatefulSetClient struct { - appsclient.StatefulSetsGetter - conflict bool - invalid bool -} - -func (c *ErrorStatefulSetClient) StatefulSets(namespace string) appsclient.StatefulSetInterface { - return &ErrorStatefulSets{ - StatefulSetInterface: c.StatefulSetsGetter.StatefulSets(namespace), - invalid: c.invalid, - conflict: c.conflict, - } -} - -func statefulSet() *apps.StatefulSet { - return &apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: "foo", - }, } } func TestStatefulSetScale(t *testing.T) { - fake := fake.NewSimpleClientset(statefulSet()) - scaler := StatefulSetScaler{fake.Apps()} + scaleClientExpectedAction := []string{"get", "update"} + scaleClient := createFakeScaleClient("statefulsets", "foo", 2, nil) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{-1, ""} count := uint(3) name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 2 { - t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions) + err := scaler.Scale("default", name, count, &preconditions, nil, nil, schema.GroupResource{Group: "apps", Resource: "statefullset"}) + if err != nil { + t.Fatal(err) } - - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != apps.Resource("statefulsets") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-statefulsets %s", actions[0], name) + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) } - if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != apps.Resource("statefulsets") || action.GetObject().(*apps.StatefulSet).Spec.Replicas != int32(count) { - t.Errorf("unexpected action %v, expected update-statefulset with replicas = %d", actions[1], count) + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } } } func TestStatefulSetScaleRetry(t *testing.T) { - fake := &ErrorStatefulSetClient{StatefulSetsGetter: fake.NewSimpleClientset().Apps(), conflict: true} - scaler := &StatefulSetScaler{fake} + scaleClientExpectedAction := []string{"get", "update", "get"} + verbsOnError := map[string]*kerrors.StatusError{ + "update": kerrors.NewConflict(api.Resource("Status"), "foo", nil), + } + scaleClient := createFakeScaleClient("statefulsets", "foo", 2, verbsOnError) + scaler := NewScaler(scaleClient) preconditions := &ScalePrecondition{-1, ""} count := uint(3) name := "foo" namespace := "default" - scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count, nil) + scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count, nil, schema.GroupResource{Group: "apps", Resource: "statefulsets"}) pass, err := scaleFunc() if pass != false { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -890,259 +300,110 @@ func TestStatefulSetScaleRetry(t *testing.T) { t.Errorf("Did not expect an error on update failure, got %v", err) } preconditions = &ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil) + scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil, schema.GroupResource{Group: "apps", Resource: "statefulsets"}) pass, err = scaleFunc() if err == nil { t.Error("Expected error on precondition failure") } + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) + } + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } + } } func TestStatefulSetScaleInvalid(t *testing.T) { - fake := &ErrorStatefulSetClient{StatefulSetsGetter: fake.NewSimpleClientset().Apps(), invalid: true} - scaler := StatefulSetScaler{fake} + scaleClientExpectedAction := []string{"get", "update"} + verbsOnError := map[string]*kerrors.StatusError{ + "update": kerrors.NewInvalid(api.Kind("Status"), "foo", nil), + } + scaleClient := createFakeScaleClient("statefulsets", "foo", 2, verbsOnError) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{-1, ""} count := uint(3) name := "foo" namespace := "default" - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count, nil) + scaleFunc := ScaleCondition(scaler, &preconditions, namespace, name, count, nil, schema.GroupResource{Group: "apps", Resource: "statefulsets"}) pass, err := scaleFunc() if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) } - e, ok := err.(ScaleError) - if err == nil || !ok || e.FailureType != ScaleUpdateFailure { + if err == nil { t.Errorf("Expected error on invalid update failure, got %v", err) } + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) + } + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } + } } func TestStatefulSetScaleFailsPreconditions(t *testing.T) { - fake := fake.NewSimpleClientset(&apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: "foo", - }, - Spec: apps.StatefulSetSpec{ - Replicas: 10, - }, - }) - scaler := StatefulSetScaler{fake.Apps()} + scaleClientExpectedAction := []string{"get"} + scaleClient := createFakeScaleClient("statefulsets", "foo", 10, nil) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{2, ""} count := uint(3) name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 1 { - t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions) - } - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != apps.Resource("statefulsets") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-statefulset %s", actions[0], name) + err := scaler.Scale("default", name, count, &preconditions, nil, nil, schema.GroupResource{Group: "apps", Resource: "statefulsets"}) + if err == nil { + t.Fatal("expected to get an error but none was returned") } -} - -func TestValidateStatefulSet(t *testing.T) { - zero, ten, twenty := int32(0), int32(10), int32(20) - tests := []struct { - preconditions ScalePrecondition - statefulset apps.StatefulSet - expectError bool - test string - }{ - { - preconditions: ScalePrecondition{-1, ""}, - expectError: false, - test: "defaults", - }, - { - preconditions: ScalePrecondition{-1, ""}, - statefulset: apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: apps.StatefulSetSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "defaults 2", - }, - { - preconditions: ScalePrecondition{0, ""}, - statefulset: apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: apps.StatefulSetSpec{ - Replicas: zero, - }, - }, - expectError: false, - test: "size matches", - }, - { - preconditions: ScalePrecondition{-1, "foo"}, - statefulset: apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: apps.StatefulSetSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "resource version matches", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - statefulset: apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: apps.StatefulSetSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "both match", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - statefulset: apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: apps.StatefulSetSpec{ - Replicas: twenty, - }, - }, - expectError: true, - test: "size different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - statefulset: apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - }, - expectError: true, - test: "no replicas", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - statefulset: apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: apps.StatefulSetSpec{ - Replicas: ten, - }, - }, - expectError: true, - test: "version different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - statefulset: apps.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: apps.StatefulSetSpec{ - Replicas: twenty, - }, - }, - expectError: true, - test: "both different", - }, + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) } - for _, test := range tests { - err := test.preconditions.ValidateStatefulSet(&test.statefulset) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - if err == nil && test.expectError { - t.Errorf("expected an error: %v (%s)", err, test.test) + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) } } } -type ErrorReplicaSets struct { - extensionsclient.ReplicaSetInterface - conflict bool - invalid bool -} - -func (c *ErrorReplicaSets) Update(replicaSets *extensions.ReplicaSet) (*extensions.ReplicaSet, error) { - switch { - case c.invalid: - return nil, kerrors.NewInvalid(api.Kind(replicaSets.Kind), replicaSets.Name, nil) - case c.conflict: - return nil, kerrors.NewConflict(api.Resource(replicaSets.Kind), replicaSets.Name, nil) - } - return nil, errors.New("replicaSets update failure") -} - -func (c *ErrorReplicaSets) Get(name string, options metav1.GetOptions) (*extensions.ReplicaSet, error) { - return &extensions.ReplicaSet{ - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - }, - }, nil -} - -type ErrorReplicaSetClient struct { - extensionsclient.ReplicaSetsGetter - conflict bool - invalid bool -} - -func (c *ErrorReplicaSetClient) ReplicaSets(namespace string) extensionsclient.ReplicaSetInterface { - return &ErrorReplicaSets{ - ReplicaSetInterface: c.ReplicaSetsGetter.ReplicaSets(namespace), - invalid: c.invalid, - conflict: c.conflict, - } -} - -func replicaSet() *extensions.ReplicaSet { - return &extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: "foo", - }, - } -} - func TestReplicaSetScale(t *testing.T) { - fake := fake.NewSimpleClientset(replicaSet()) - scaler := ReplicaSetScaler{fake.Extensions()} + scaleClientExpectedAction := []string{"get", "update"} + scaleClient := createFakeScaleClient("replicasets", "foo", 10, nil) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{-1, ""} count := uint(3) name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 2 { - t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions) + err := scaler.Scale("default", name, count, &preconditions, nil, nil, schema.GroupResource{Group: "extensions", Resource: "replicasets"}) + if err != nil { + t.Fatal(err) } - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != extensions.Resource("replicasets") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-replicationSet %s", actions[0], name) + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) } - if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != extensions.Resource("replicasets") || action.GetObject().(*extensions.ReplicaSet).Spec.Replicas != int32(count) { - t.Errorf("unexpected action %v, expected update-replicaSet with replicas = %d", actions[1], count) + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } } } func TestReplicaSetScaleRetry(t *testing.T) { - fake := &ErrorReplicaSetClient{ReplicaSetsGetter: fake.NewSimpleClientset().Extensions(), conflict: true} - scaler := &ReplicaSetScaler{fake} + verbsOnError := map[string]*kerrors.StatusError{ + "update": kerrors.NewConflict(api.Resource("Status"), "foo", nil), + } + scaleClientExpectedAction := []string{"get", "update", "get"} + scaleClient := createFakeScaleClient("replicasets", "foo", 2, verbsOnError) + scaler := NewScaler(scaleClient) preconditions := &ScalePrecondition{-1, ""} count := uint(3) name := "foo" namespace := "default" - scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count, nil) + scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count, nil, schema.GroupResource{Group: "extensions", Resource: "replicasets"}) pass, err := scaleFunc() if pass != false { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -1151,179 +412,71 @@ func TestReplicaSetScaleRetry(t *testing.T) { t.Errorf("Did not expect an error on update failure, got %v", err) } preconditions = &ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil) + scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil, schema.GroupResource{Group: "extensions", Resource: "replicasets"}) pass, err = scaleFunc() if err == nil { t.Error("Expected error on precondition failure") } + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) + } + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } + } } func TestReplicaSetScaleInvalid(t *testing.T) { - fake := &ErrorReplicaSetClient{ReplicaSetsGetter: fake.NewSimpleClientset().Extensions(), invalid: true} - scaler := ReplicaSetScaler{fake} + verbsOnError := map[string]*kerrors.StatusError{ + "update": kerrors.NewInvalid(api.Kind("Status"), "foo", nil), + } + scaleClientExpectedAction := []string{"get", "update"} + scaleClient := createFakeScaleClient("replicasets", "foo", 2, verbsOnError) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{-1, ""} count := uint(3) name := "foo" namespace := "default" - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count, nil) + scaleFunc := ScaleCondition(scaler, &preconditions, namespace, name, count, nil, schema.GroupResource{Group: "extensions", Resource: "replicasets"}) pass, err := scaleFunc() if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) } - e, ok := err.(ScaleError) - if err == nil || !ok || e.FailureType != ScaleUpdateFailure { + if err == nil { t.Errorf("Expected error on invalid update failure, got %v", err) } + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) + } + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) + } + } } func TestReplicaSetsGetterFailsPreconditions(t *testing.T) { - fake := fake.NewSimpleClientset(&extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: "foo", - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 10, - }, - }) - scaler := ReplicaSetScaler{fake.Extensions()} + scaleClientExpectedAction := []string{"get"} + scaleClient := createFakeScaleClient("replicasets", "foo", 10, nil) + scaler := NewScaler(scaleClient) preconditions := ScalePrecondition{2, ""} count := uint(3) name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 1 { - t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions) - } - if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != extensions.Resource("replicasets") || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-replicaSets %s", actions[0], name) + err := scaler.Scale("default", name, count, &preconditions, nil, nil, schema.GroupResource{Group: "extensions", Resource: "replicasets"}) + if err == nil { + t.Fatal("expected to get an error but non was returned") } -} - -func TestValidateReplicaSets(t *testing.T) { - zero, ten, twenty := int32(0), int32(10), int32(20) - tests := []struct { - preconditions ScalePrecondition - replicaSets extensions.ReplicaSet - expectError bool - test string - }{ - { - preconditions: ScalePrecondition{-1, ""}, - expectError: false, - test: "defaults", - }, - { - preconditions: ScalePrecondition{-1, ""}, - replicaSets: extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "defaults 2", - }, - { - preconditions: ScalePrecondition{0, ""}, - replicaSets: extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: zero, - }, - }, - expectError: false, - test: "size matches", - }, - { - preconditions: ScalePrecondition{-1, "foo"}, - replicaSets: extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "resource version matches", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - replicaSets: extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "both match", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - replicaSets: extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: twenty, - }, - }, - expectError: true, - test: "size different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - replicaSets: extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "foo", - }, - }, - expectError: true, - test: "no replicas", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - replicaSets: extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: ten, - }, - }, - expectError: true, - test: "version different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - replicaSets: extensions.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: twenty, - }, - }, - expectError: true, - test: "both different", - }, + actions := scaleClient.Actions() + if len(actions) != len(scaleClientExpectedAction) { + t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) } - for _, test := range tests { - err := test.preconditions.ValidateReplicaSet(&test.replicaSets) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - if err == nil && test.expectError { - t.Errorf("expected an error: %v (%s)", err, test.test) + for i, verb := range scaleClientExpectedAction { + if actions[i].GetVerb() != verb { + t.Errorf("unexpected action: %+v, expected %s", actions[i].GetVerb(), verb) } } } @@ -1331,36 +484,7 @@ func TestValidateReplicaSets(t *testing.T) { // TestGenericScaleSimple exercises GenericScaler.ScaleSimple method func TestGenericScaleSimple(t *testing.T) { // test data - discoveryResources := []*metav1.APIResourceList{ - { - GroupVersion: appsv1beta2.SchemeGroupVersion.String(), - APIResources: []metav1.APIResource{ - {Name: "deployments", Namespaced: true, Kind: "Deployment"}, - {Name: "deployments/scale", Namespaced: true, Kind: "Scale", Group: "apps", Version: "v1beta2"}, - }, - }, - } - appsV1beta2Scale := &appsv1beta2.Scale{ - TypeMeta: metav1.TypeMeta{ - Kind: "Scale", - APIVersion: appsv1beta2.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "abc", - }, - Spec: appsv1beta2.ScaleSpec{Replicas: 10}, - Status: appsv1beta2.ScaleStatus{ - Replicas: 10, - }, - } - pathsResources := map[string]runtime.Object{ - "/apis/apps/v1beta2/namespaces/default/deployments/abc/scale": appsV1beta2Scale, - } - - scaleClient, err := fakeScaleClient(discoveryResources, pathsResources) - if err != nil { - t.Fatal(err) - } + scaleClient := createFakeScaleClient("deployments", "abc", 10, nil) // test scenarios scenarios := []struct { @@ -1377,16 +501,16 @@ func TestGenericScaleSimple(t *testing.T) { name: "scale up the \"abc\" deployment", precondition: ScalePrecondition{10, ""}, newSize: 20, - targetGR: schema.GroupResource{Group: "apps", Resource: "deployment"}, + targetGR: schema.GroupResource{Group: "apps", Resource: "deployments"}, resName: "abc", scaleGetter: scaleClient, }, // scenario 2: scale down the "abc" deployment { - name: "scale down the \"abs\" deplyment", + name: "scale down the \"abs\" deployment", precondition: ScalePrecondition{20, ""}, newSize: 5, - targetGR: schema.GroupResource{Group: "apps", Resource: "deployment"}, + targetGR: schema.GroupResource{Group: "apps", Resource: "deployments"}, resName: "abc", scaleGetter: scaleClient, }, @@ -1396,7 +520,7 @@ func TestGenericScaleSimple(t *testing.T) { name: "precondition error, expected size is 1", precondition: ScalePrecondition{1, ""}, newSize: 5, - targetGR: schema.GroupResource{Group: "apps", Resource: "deployment"}, + targetGR: schema.GroupResource{Group: "apps", Resource: "deployments"}, resName: "abc", scaleGetter: scaleClient, expectError: true, @@ -1406,7 +530,7 @@ func TestGenericScaleSimple(t *testing.T) { name: "precondition is not validated when the size is set to -1", precondition: ScalePrecondition{-1, ""}, newSize: 5, - targetGR: schema.GroupResource{Group: "apps", Resource: "deployment"}, + targetGR: schema.GroupResource{Group: "apps", Resource: "deployments"}, resName: "abc", scaleGetter: scaleClient, }, @@ -1415,7 +539,7 @@ func TestGenericScaleSimple(t *testing.T) { name: "precondition error, resource version mismatch", precondition: ScalePrecondition{5, "v1"}, newSize: 5, - targetGR: schema.GroupResource{Group: "apps", Resource: "deployment"}, + targetGR: schema.GroupResource{Group: "apps", Resource: "deployments"}, resName: "abc", scaleGetter: scaleClient, expectError: true, @@ -1425,9 +549,9 @@ func TestGenericScaleSimple(t *testing.T) { // act for index, scenario := range scenarios { t.Run(fmt.Sprintf("running scenario %d: %s", index+1, scenario.name), func(t *testing.T) { - target := ScalerFor(schema.GroupKind{}, nil, scenario.scaleGetter, scenario.targetGR) + target := NewScaler(scenario.scaleGetter) - resVersion, err := target.ScaleSimple("default", scenario.resName, &scenario.precondition, uint(scenario.newSize)) + resVersion, err := target.ScaleSimple("default", scenario.resName, &scenario.precondition, uint(scenario.newSize), scenario.targetGR) if scenario.expectError && err == nil { t.Fatal("expected an error but was not returned") @@ -1445,36 +569,7 @@ func TestGenericScaleSimple(t *testing.T) { // TestGenericScale exercises GenericScaler.Scale method func TestGenericScale(t *testing.T) { // test data - discoveryResources := []*metav1.APIResourceList{ - { - GroupVersion: appsv1beta2.SchemeGroupVersion.String(), - APIResources: []metav1.APIResource{ - {Name: "deployments", Namespaced: true, Kind: "Deployment"}, - {Name: "deployments/scale", Namespaced: true, Kind: "Scale", Group: "apps", Version: "v1beta2"}, - }, - }, - } - appsV1beta2Scale := &appsv1beta2.Scale{ - TypeMeta: metav1.TypeMeta{ - Kind: "Scale", - APIVersion: appsv1beta2.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "abc", - }, - Spec: appsv1beta2.ScaleSpec{Replicas: 10}, - Status: appsv1beta2.ScaleStatus{ - Replicas: 10, - }, - } - pathsResources := map[string]runtime.Object{ - "/apis/apps/v1beta2/namespaces/default/deployments/abc/scale": appsV1beta2Scale, - } - - scaleClient, err := fakeScaleClient(discoveryResources, pathsResources) - if err != nil { - t.Fatal(err) - } + scaleClient := createFakeScaleClient("deployments", "abc", 10, nil) // test scenarios scenarios := []struct { @@ -1492,16 +587,16 @@ func TestGenericScale(t *testing.T) { name: "scale up the \"abc\" deployment", precondition: ScalePrecondition{10, ""}, newSize: 20, - targetGR: schema.GroupResource{Group: "apps", Resource: "deployment"}, + targetGR: schema.GroupResource{Group: "apps", Resource: "deployments"}, resName: "abc", scaleGetter: scaleClient, }, - // scenario 2: a resource name cannot be empty + //scenario 2: a resource name cannot be empty { name: "a resource name cannot be empty", precondition: ScalePrecondition{10, ""}, newSize: 20, - targetGR: schema.GroupResource{Group: "apps", Resource: "deployment"}, + targetGR: schema.GroupResource{Group: "apps", Resource: "deployments"}, resName: "", scaleGetter: scaleClient, expectError: true, @@ -1511,7 +606,7 @@ func TestGenericScale(t *testing.T) { name: "wait for replicas error due to status.Replicas != spec.Replicas", precondition: ScalePrecondition{10, ""}, newSize: 20, - targetGR: schema.GroupResource{Group: "apps", Resource: "deployment"}, + targetGR: schema.GroupResource{Group: "apps", Resource: "deployments"}, resName: "abc", scaleGetter: scaleClient, waitForReplicas: &RetryParams{time.Duration(5 * time.Second), time.Duration(5 * time.Second)}, @@ -1520,11 +615,11 @@ func TestGenericScale(t *testing.T) { } // act - for index, scenario := range scenarios { - t.Run(fmt.Sprintf("running scenario %d: %s", index+1, scenario.name), func(t *testing.T) { - target := ScalerFor(schema.GroupKind{}, nil, scenario.scaleGetter, scenario.targetGR) + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + target := NewScaler(scenario.scaleGetter) - err := target.Scale("default", scenario.resName, uint(scenario.newSize), &scenario.precondition, nil, scenario.waitForReplicas) + err := target.Scale("default", scenario.resName, uint(scenario.newSize), &scenario.precondition, nil, scenario.waitForReplicas, scenario.targetGR) if scenario.expectError && err == nil { t.Fatal("expected an error but was not returned") @@ -1536,74 +631,53 @@ func TestGenericScale(t *testing.T) { } } -func fakeScaleClient(discoveryResources []*metav1.APIResourceList, pathsResources map[string]runtime.Object) (scale.ScalesGetter, error) { - fakeDiscoveryClient := &fakedisco.FakeDiscovery{Fake: &testcore.Fake{}} - fakeDiscoveryClient.Resources = discoveryResources - restMapperRes, err := discovery.GetAPIGroupResources(fakeDiscoveryClient) - if err != nil { - return nil, err - } - restMapper := discovery.NewRESTMapper(restMapperRes, apimeta.InterfacesForUnstructured) - codecs := serializer.NewCodecFactory(scale.NewScaleConverter().Scheme()) - fakeReqHandler := func(req *http.Request) (*http.Response, error) { - path := req.URL.Path - scale, isScalePath := pathsResources[path] - if !isScalePath { - return nil, fmt.Errorf("unexpected request for URL %q with method %q", req.URL.String(), req.Method) +func createFakeScaleClient(resource string, resourceName string, replicas int, errorsOnVerb map[string]*kerrors.StatusError) *fakescale.FakeScaleClient { + shouldReturnAnError := func(verb string) (*kerrors.StatusError, bool) { + if anError, anErrorExists := errorsOnVerb[verb]; anErrorExists { + return anError, true } - - switch req.Method { - case "GET": - res, err := json.Marshal(scale) - if err != nil { - return nil, err - } - return &http.Response{StatusCode: 200, Header: defaultHeaders(), Body: bytesBody(res)}, nil - case "PUT": - decoder := codecs.UniversalDeserializer() - body, err := ioutil.ReadAll(req.Body) - if err != nil { - return nil, err - } - newScale, newScaleGVK, err := decoder.Decode(body, nil, nil) - if err != nil { - return nil, fmt.Errorf("unexpected request body: %v", err) - } - if *newScaleGVK != scale.GetObjectKind().GroupVersionKind() { - return nil, fmt.Errorf("unexpected scale API version %s (expected %s)", newScaleGVK.String(), scale.GetObjectKind().GroupVersionKind().String()) - } - res, err := json.Marshal(newScale) - if err != nil { - return nil, err - } - - pathsResources[path] = newScale - return &http.Response{StatusCode: 200, Header: defaultHeaders(), Body: bytesBody(res)}, nil - default: - return nil, fmt.Errorf("unexpected request for URL %q with method %q", req.URL.String(), req.Method) + return &kerrors.StatusError{}, false + } + newReplicas := int32(replicas) + scaleClient := &fakescale.FakeScaleClient{} + scaleClient.AddReactor("get", resource, func(rawAction testcore.Action) (handled bool, ret runtime.Object, err error) { + action := rawAction.(testcore.GetAction) + if action.GetName() != resourceName { + return true, nil, fmt.Errorf("expected = %s, got = %s", resourceName, action.GetName()) } - } - - fakeClient := &fakerest.RESTClient{ - Client: fakerest.CreateHTTPClient(fakeReqHandler), - NegotiatedSerializer: serializer.DirectCodecFactory{ - CodecFactory: serializer.NewCodecFactory(scale.NewScaleConverter().Scheme()), - }, - GroupVersion: schema.GroupVersion{}, - VersionedAPIPath: "/not/a/real/path", - } - - resolver := scale.NewDiscoveryScaleKindResolver(fakeDiscoveryClient) - client := scale.New(fakeClient, restMapper, dynamic.LegacyAPIPathResolverFunc, resolver) - return client, nil -} - -func bytesBody(bodyBytes []byte) io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader(bodyBytes)) -} - -func defaultHeaders() http.Header { - header := http.Header{} - header.Set("Content-Type", runtime.ContentTypeJSON) - return header + if anError, should := shouldReturnAnError("get"); should { + return true, nil, anError + } + obj := &autoscalingv1.Scale{ + ObjectMeta: metav1.ObjectMeta{ + Name: action.GetName(), + Namespace: action.GetNamespace(), + }, + Spec: autoscalingv1.ScaleSpec{ + Replicas: newReplicas, + }, + } + return true, obj, nil + }) + scaleClient.AddReactor("update", resource, func(rawAction testcore.Action) (handled bool, ret runtime.Object, err error) { + action := rawAction.(testcore.UpdateAction) + obj := action.GetObject().(*autoscalingv1.Scale) + if obj.Name != resourceName { + return true, nil, fmt.Errorf("expected = %s, got = %s", resourceName, obj.Name) + } + if anError, should := shouldReturnAnError("update"); should { + return true, nil, anError + } + newReplicas = obj.Spec.Replicas + return true, &autoscalingv1.Scale{ + ObjectMeta: metav1.ObjectMeta{ + Name: obj.Name, + Namespace: action.GetNamespace(), + }, + Spec: autoscalingv1.ScaleSpec{ + Replicas: newReplicas, + }, + }, nil + }) + return scaleClient } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/BUILD index cdd933340..8d1f602f4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/BUILD @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -11,6 +11,7 @@ go_library( deps = [ "//vendor/k8s.io/api/admission/v1beta1:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", + "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/apps/v1beta2:go_default_library", @@ -36,13 +37,12 @@ go_library( "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/api/storage/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", ], ) @@ -60,3 +60,17 @@ filegroup( tags = ["automanaged"], visibility = ["//visibility:public"], ) + +go_test( + name = "go_default_test", + srcs = ["sparse_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/batch/v1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/install.go b/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/install.go index 95838f557..b756689b3 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/install.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/install.go @@ -19,6 +19,7 @@ package scheme import ( admissionv1alpha1 "k8s.io/api/admission/v1beta1" admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1" + admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" appsv1 "k8s.io/api/apps/v1" appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta2 "k8s.io/api/apps/v1beta2" @@ -44,10 +45,9 @@ import ( settingsv1alpha1 "k8s.io/api/settings/v1alpha1" storagev1 "k8s.io/api/storage/v1" storagev1beta1 "k8s.io/api/storage/v1beta1" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/kubernetes/scheme" ) @@ -56,266 +56,24 @@ import ( // but does NOT register the internal types. func init() { // Register external types for Scheme - v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) scheme.AddToScheme(Scheme) - // Register external types for Registry - Versions = append(Versions, corev1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: corev1.GroupName, - VersionPreferenceOrder: []string{corev1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString( - "Node", - "Namespace", - "PersistentVolume", - "ComponentStatus", - ), - IgnoredKinds: sets.NewString( - "ListOptions", - "DeleteOptions", - "Status", - "PodLogOptions", - "PodExecOptions", - "PodAttachOptions", - "PodPortForwardOptions", - "PodProxyOptions", - "NodeProxyOptions", - "ServiceProxyOptions", - ), - }, - announced.VersionToSchemeFunc{ - corev1.SchemeGroupVersion.Version: corev1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, admissionv1alpha1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: admissionv1alpha1.GroupName, - VersionPreferenceOrder: []string{admissionv1alpha1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("AdmissionReview"), - }, - announced.VersionToSchemeFunc{ - admissionv1alpha1.SchemeGroupVersion.Version: admissionv1alpha1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, admissionregistrationv1alpha1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: admissionregistrationv1alpha1.GroupName, - RootScopedKinds: sets.NewString("InitializerConfiguration", "ValidatingWebhookConfiguration", "MutatingWebhookConfiguration"), - VersionPreferenceOrder: []string{admissionregistrationv1alpha1.SchemeGroupVersion.Version}, - }, - announced.VersionToSchemeFunc{ - admissionregistrationv1alpha1.SchemeGroupVersion.Version: admissionregistrationv1alpha1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, appsv1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion, appsv1beta1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: appsv1.GroupName, - VersionPreferenceOrder: []string{appsv1beta1.SchemeGroupVersion.Version, appsv1beta2.SchemeGroupVersion.Version, appsv1.SchemeGroupVersion.Version}, - }, - announced.VersionToSchemeFunc{ - appsv1beta1.SchemeGroupVersion.Version: appsv1beta1.AddToScheme, - appsv1beta2.SchemeGroupVersion.Version: appsv1beta2.AddToScheme, - appsv1.SchemeGroupVersion.Version: appsv1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, authenticationv1.SchemeGroupVersion, authenticationv1beta1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: authenticationv1beta1.GroupName, - VersionPreferenceOrder: []string{authenticationv1.SchemeGroupVersion.Version, authenticationv1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("TokenReview"), - }, - announced.VersionToSchemeFunc{ - authenticationv1beta1.SchemeGroupVersion.Version: authenticationv1beta1.AddToScheme, - authenticationv1.SchemeGroupVersion.Version: authenticationv1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, authorizationv1.SchemeGroupVersion, authorizationv1beta1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: authorizationv1.GroupName, - VersionPreferenceOrder: []string{authorizationv1.SchemeGroupVersion.Version, authorizationv1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("SubjectAccessReview", "SelfSubjectAccessReview", "SelfSubjectRulesReview"), - }, - announced.VersionToSchemeFunc{ - authorizationv1beta1.SchemeGroupVersion.Version: authorizationv1beta1.AddToScheme, - authorizationv1.SchemeGroupVersion.Version: authorizationv1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, autoscalingv1.SchemeGroupVersion, autoscalingv2beta1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: autoscalingv1.GroupName, - VersionPreferenceOrder: []string{autoscalingv1.SchemeGroupVersion.Version, autoscalingv2beta1.SchemeGroupVersion.Version}, - }, - announced.VersionToSchemeFunc{ - autoscalingv1.SchemeGroupVersion.Version: autoscalingv1.AddToScheme, - autoscalingv2beta1.SchemeGroupVersion.Version: autoscalingv2beta1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, batchv1.SchemeGroupVersion, batchv1beta1.SchemeGroupVersion, batchv2alpha1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: batchv1.GroupName, - VersionPreferenceOrder: []string{batchv1.SchemeGroupVersion.Version, batchv1beta1.SchemeGroupVersion.Version, batchv2alpha1.SchemeGroupVersion.Version}, - }, - announced.VersionToSchemeFunc{ - batchv1.SchemeGroupVersion.Version: batchv1.AddToScheme, - batchv1beta1.SchemeGroupVersion.Version: batchv1beta1.AddToScheme, - batchv2alpha1.SchemeGroupVersion.Version: batchv2alpha1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, certificatesv1beta1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: certificatesv1beta1.GroupName, - VersionPreferenceOrder: []string{certificatesv1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("CertificateSigningRequest"), - }, - announced.VersionToSchemeFunc{ - certificatesv1beta1.SchemeGroupVersion.Version: certificatesv1beta1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, extensionsv1beta1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: extensionsv1beta1.GroupName, - VersionPreferenceOrder: []string{extensionsv1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("PodSecurityPolicy"), - }, - announced.VersionToSchemeFunc{ - extensionsv1beta1.SchemeGroupVersion.Version: extensionsv1beta1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, imagepolicyv1alpha1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: imagepolicyv1alpha1.GroupName, - VersionPreferenceOrder: []string{imagepolicyv1alpha1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("ImageReview"), - }, - announced.VersionToSchemeFunc{ - imagepolicyv1alpha1.SchemeGroupVersion.Version: imagepolicyv1alpha1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, networkingv1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: networkingv1.GroupName, - VersionPreferenceOrder: []string{networkingv1.SchemeGroupVersion.Version}, - }, - announced.VersionToSchemeFunc{ - networkingv1.SchemeGroupVersion.Version: networkingv1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, policyv1beta1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: policyv1beta1.GroupName, - VersionPreferenceOrder: []string{policyv1beta1.SchemeGroupVersion.Version}, - }, - announced.VersionToSchemeFunc{ - policyv1beta1.SchemeGroupVersion.Version: policyv1beta1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, rbacv1.SchemeGroupVersion, rbacv1beta1.SchemeGroupVersion, rbacv1alpha1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: rbacv1.GroupName, - VersionPreferenceOrder: []string{rbacv1.SchemeGroupVersion.Version, rbacv1beta1.SchemeGroupVersion.Version, rbacv1alpha1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("ClusterRole", "ClusterRoleBinding"), - }, - announced.VersionToSchemeFunc{ - rbacv1.SchemeGroupVersion.Version: rbacv1.AddToScheme, - rbacv1beta1.SchemeGroupVersion.Version: rbacv1beta1.AddToScheme, - rbacv1alpha1.SchemeGroupVersion.Version: rbacv1alpha1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, schedulingv1alpha1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: schedulingv1alpha1.GroupName, - VersionPreferenceOrder: []string{schedulingv1alpha1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("PriorityClass"), - }, - announced.VersionToSchemeFunc{ - schedulingv1alpha1.SchemeGroupVersion.Version: schedulingv1alpha1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, settingsv1alpha1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: settingsv1alpha1.GroupName, - VersionPreferenceOrder: []string{settingsv1alpha1.SchemeGroupVersion.Version}, - }, - announced.VersionToSchemeFunc{ - settingsv1alpha1.SchemeGroupVersion.Version: settingsv1alpha1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } - - Versions = append(Versions, storagev1.SchemeGroupVersion, storagev1beta1.SchemeGroupVersion) - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: storagev1.GroupName, - VersionPreferenceOrder: []string{storagev1.SchemeGroupVersion.Version, storagev1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("StorageClass"), - }, - announced.VersionToSchemeFunc{ - storagev1.SchemeGroupVersion.Version: storagev1.AddToScheme, - storagev1beta1.SchemeGroupVersion.Version: storagev1beta1.AddToScheme, - }, - ).Announce(GroupFactoryRegistry).RegisterAndEnable(Registry, Scheme); err != nil { - panic(err) - } + utilruntime.Must(Scheme.SetVersionPriority(corev1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(admissionv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(admissionregistrationv1beta1.SchemeGroupVersion, admissionregistrationv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(appsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion, appsv1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(authenticationv1.SchemeGroupVersion, authenticationv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(authorizationv1.SchemeGroupVersion, authorizationv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(autoscalingv1.SchemeGroupVersion, autoscalingv2beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(batchv1.SchemeGroupVersion, batchv1beta1.SchemeGroupVersion, batchv2alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(certificatesv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(extensionsv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(imagepolicyv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(networkingv1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(policyv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(rbacv1.SchemeGroupVersion, rbacv1beta1.SchemeGroupVersion, rbacv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(schedulingv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(settingsv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(storagev1.SchemeGroupVersion, storagev1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/scheme.go b/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/scheme.go index d2e7ca978..880b115b1 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/scheme.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/scheme.go @@ -17,38 +17,20 @@ limitations under the License. package scheme import ( - "os" - - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" ) // All kubectl code should eventually switch to use this Registry and Scheme instead of the global ones. -// GroupFactoryRegistry is the APIGroupFactoryRegistry (overlaps a bit with Registry, see comments in package for details) -var GroupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - -// Registry is an instance of an API registry. -var Registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) - // Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. var Scheme = runtime.NewScheme() // Codecs provides access to encoding and decoding for the scheme var Codecs = serializer.NewCodecFactory(Scheme) -// ParameterCodec handles versioning of objects that are converted to query parameters. -var ParameterCodec = runtime.NewParameterCodec(Scheme) - -// Versions is a list of group versions in order of preferred serialization. This used to be discovered dynamically, -// from the server for use in the client, but that gives conflicting lists of non-existent versions. This only needs to -// live until we stop attempting to perform any conversion client-side and is only valid for items existent in our scheme. -var Versions = []schema.GroupVersion{} - // DefaultJSONEncoder returns a default encoder for our scheme func DefaultJSONEncoder() runtime.Encoder { - return Codecs.LegacyCodec(Versions...) + return unstructured.JSONFallbackEncoder{Encoder: Codecs.LegacyCodec(Scheme.PrioritizedVersionsAllGroups()...)} } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/sparse_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/sparse_test.go new file mode 100644 index 000000000..b0d4201ec --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/scheme/sparse_test.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 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 scheme + +import ( + "testing" + + "k8s.io/api/batch/v1" + "k8s.io/api/batch/v1beta1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/diff" +) + +func TestCronJob(t *testing.T) { + src := &v1beta1.CronJob{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + + encoder := Codecs.LegacyCodec(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion) + cronjobBytes, err := runtime.Encode(encoder, src) + if err != nil { + t.Fatal(err) + } + t.Log(string(cronjobBytes)) + t.Log(Scheme.PrioritizedVersionsAllGroups()) + + decoder := Codecs.UniversalDecoder(Scheme.PrioritizedVersionsAllGroups()...) + + uncastDst, err := runtime.Decode(decoder, cronjobBytes) + if err != nil { + t.Fatal(err) + } + + // clear typemeta + uncastDst.(*v1beta1.CronJob).TypeMeta = metav1.TypeMeta{} + + if !equality.Semantic.DeepEqual(src, uncastDst) { + t.Fatal(diff.ObjectDiff(src, uncastDst)) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/secret.go b/vendor/k8s.io/kubernetes/pkg/kubectl/secret.go index 04c5ced23..9a0ff5281 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/secret.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/secret.go @@ -130,6 +130,7 @@ func (s SecretGeneratorV1) StructuredGenerate() (runtime.Object, error) { return nil, err } secret := &v1.Secret{} + secret.SetGroupVersionKind(v1.SchemeGroupVersion.WithKind("Secret")) secret.Name = s.Name secret.Data = map[string][]byte{} if len(s.Type) > 0 { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/secret_for_docker_registry.go b/vendor/k8s.io/kubernetes/pkg/kubectl/secret_for_docker_registry.go index cad90cfe1..da95e6d45 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/secret_for_docker_registry.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/secret_for_docker_registry.go @@ -30,6 +30,8 @@ import ( type SecretForDockerRegistryGeneratorV1 struct { // Name of secret (required) Name string + // FileSources to derive the secret from (optional) + FileSources []string // Username for registry (required) Username string // Email for registry (optional) @@ -85,15 +87,22 @@ func (s SecretForDockerRegistryGeneratorV1) StructuredGenerate() (runtime.Object if err := s.validate(); err != nil { return nil, err } - dockercfgJsonContent, err := handleDockerCfgJsonContent(s.Username, s.Password, s.Email, s.Server) - if err != nil { - return nil, err - } secret := &v1.Secret{} secret.Name = s.Name secret.Type = v1.SecretTypeDockerConfigJson secret.Data = map[string][]byte{} - secret.Data[v1.DockerConfigJsonKey] = dockercfgJsonContent + if len(s.FileSources) > 0 { + if err := handleFromFileSources(secret, s.FileSources); err != nil { + return nil, err + } + } + if len(s.FileSources) == 0 { + dockercfgJsonContent, err := handleDockerCfgJsonContent(s.Username, s.Password, s.Email, s.Server) + if err != nil { + return nil, err + } + secret.Data[v1.DockerConfigJsonKey] = dockercfgJsonContent + } if s.AppendHash { h, err := hash.SecretHash(secret) if err != nil { @@ -108,6 +117,7 @@ func (s SecretForDockerRegistryGeneratorV1) StructuredGenerate() (runtime.Object func (s SecretForDockerRegistryGeneratorV1) ParamNames() []GeneratorParam { return []GeneratorParam{ {"name", true}, + {"from-file", false}, {"docker-username", true}, {"docker-email", false}, {"docker-password", true}, @@ -121,14 +131,17 @@ func (s SecretForDockerRegistryGeneratorV1) validate() error { if len(s.Name) == 0 { return fmt.Errorf("name must be specified") } - if len(s.Username) == 0 { - return fmt.Errorf("username must be specified") - } - if len(s.Password) == 0 { - return fmt.Errorf("password must be specified") - } - if len(s.Server) == 0 { - return fmt.Errorf("server must be specified") + + if len(s.FileSources) == 0 { + if len(s.Username) == 0 { + return fmt.Errorf("username must be specified") + } + if len(s.Password) == 0 { + return fmt.Errorf("password must be specified") + } + if len(s.Server) == 0 { + return fmt.Errorf("server must be specified") + } } return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/secret_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/secret_test.go index 15f3db0b4..43dd411a2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/secret_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/secret_test.go @@ -37,6 +37,8 @@ func TestSecretGenerate(t *testing.T) { "name": "foo", }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, @@ -50,6 +52,8 @@ func TestSecretGenerate(t *testing.T) { "append-hash": true, }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "foo-949tdgdkgg", }, @@ -63,6 +67,8 @@ func TestSecretGenerate(t *testing.T) { "type": "my-type", }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, @@ -78,6 +84,8 @@ func TestSecretGenerate(t *testing.T) { "append-hash": true, }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "foo-dg474f9t76", }, @@ -92,6 +100,8 @@ func TestSecretGenerate(t *testing.T) { "from-literal": []string{"key1=value1", "key2=value2"}, }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, @@ -109,6 +119,8 @@ func TestSecretGenerate(t *testing.T) { "append-hash": true, }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "foo-tf72c228m4", }, @@ -146,6 +158,8 @@ func TestSecretGenerate(t *testing.T) { "from-literal": []string{"key1==value1"}, }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, @@ -162,6 +176,8 @@ func TestSecretGenerate(t *testing.T) { "append-hash": true, }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "foo-fdcc8tkhh5", }, @@ -178,6 +194,8 @@ func TestSecretGenerate(t *testing.T) { "from-env-file": "file.env", }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "valid_env", }, @@ -196,6 +214,8 @@ func TestSecretGenerate(t *testing.T) { "append-hash": true, }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "valid_env-bkb2m2965h", }, @@ -217,6 +237,8 @@ func TestSecretGenerate(t *testing.T) { "from-env-file": "file.env", }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "getenv", }, @@ -239,6 +261,8 @@ func TestSecretGenerate(t *testing.T) { "append-hash": true, }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "getenv-m7kg2khdb4", }, @@ -272,6 +296,8 @@ func TestSecretGenerate(t *testing.T) { "from-env-file": "file.env", }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "with_spaces", }, @@ -289,6 +315,8 @@ func TestSecretGenerate(t *testing.T) { "append-hash": true, }, expected: &v1.Secret{ + // this is ok because we know exactly how we want to be serialized + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{ Name: "with_spaces-4488d5b57d", }, diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/service_basic_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/service_basic_test.go index c7f9ff717..b1c89921b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/service_basic_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/service_basic_test.go @@ -18,6 +18,7 @@ package kubectl import ( "reflect" + "strings" "testing" "k8s.io/api/core/v1" @@ -152,3 +153,169 @@ func TestServiceBasicGenerate(t *testing.T) { } } } + +func TestParsePorts(t *testing.T) { + tests := []struct { + portString string + expectPort int32 + expectTargetPort intstr.IntOrString + expectErr string + }{ + { + portString: "3232", + expectPort: 3232, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 3232}, + }, + { + portString: "1:65535", + expectPort: 1, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 65535}, + }, + { + portString: "-5:1234", + expectPort: 0, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 0}, + expectErr: "must be between 1 and 65535, inclusive", + }, + { + portString: "5:65536", + expectPort: 0, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 0}, + expectErr: "must be between 1 and 65535, inclusive", + }, + { + portString: "test-5:443", + expectPort: 0, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 0}, + expectErr: "invalid syntax", + }, + { + portString: "5:test-443", + expectPort: 5, + expectTargetPort: intstr.IntOrString{Type: intstr.String, StrVal: "test-443"}, + }, + { + portString: "5:test*443", + expectPort: 0, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 0}, + expectErr: "must contain only alpha-numeric characters (a-z, 0-9), and hyphens (-)", + }, + { + portString: "5:", + expectPort: 0, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 0}, + expectErr: "must contain at least one letter or number (a-z, 0-9)", + }, + { + portString: "5:test--443", + expectPort: 0, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 0}, + expectErr: "must not contain consecutive hyphens", + }, + { + portString: "5:test443-", + expectPort: 0, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 0}, + expectErr: "must not begin or end with a hyphen", + }, + { + portString: "3232:1234:4567", + expectPort: 3232, + expectTargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 1234}, + }, + } + + for _, test := range tests { + t.Run(test.portString, func(t *testing.T) { + port, targetPort, err := parsePorts(test.portString) + if len(test.expectErr) != 0 { + if !strings.Contains(err.Error(), test.expectErr) { + t.Errorf("parse ports string: %s. Expected err: %s, Got err: %v.", test.portString, test.expectErr, err) + } + } + if !reflect.DeepEqual(targetPort, test.expectTargetPort) || port != test.expectPort { + t.Errorf("parse ports string: %s. Expected port:%d, targetPort:%v, Got port:%d, targetPort:%v.", test.portString, test.expectPort, test.expectTargetPort, port, targetPort) + } + }) + } +} + +func TestValidateServiceCommonGeneratorV1(t *testing.T) { + tests := []struct { + name string + s ServiceCommonGeneratorV1 + expectErr string + }{ + { + name: "validate-ok", + s: ServiceCommonGeneratorV1{ + Name: "validate-ok", + Type: v1.ServiceTypeClusterIP, + TCP: []string{"123", "234:1234"}, + ClusterIP: "", + }, + }, + { + name: "Name-none", + s: ServiceCommonGeneratorV1{ + Type: v1.ServiceTypeClusterIP, + TCP: []string{"123", "234:1234"}, + ClusterIP: "", + }, + expectErr: "name must be specified", + }, + { + name: "Type-none", + s: ServiceCommonGeneratorV1{ + Name: "validate-ok", + TCP: []string{"123", "234:1234"}, + ClusterIP: "", + }, + expectErr: "type must be specified", + }, + { + name: "invalid-ClusterIPNone", + s: ServiceCommonGeneratorV1{ + Name: "validate-ok", + Type: v1.ServiceTypeNodePort, + TCP: []string{"123", "234:1234"}, + ClusterIP: v1.ClusterIPNone, + }, + expectErr: "ClusterIP=None can only be used with ClusterIP service type", + }, + { + name: "TCP-none", + s: ServiceCommonGeneratorV1{ + Name: "validate-ok", + Type: v1.ServiceTypeClusterIP, + ClusterIP: "", + }, + expectErr: "at least one tcp port specifier must be provided", + }, + { + name: "invalid-ExternalName", + s: ServiceCommonGeneratorV1{ + Name: "validate-ok", + Type: v1.ServiceTypeExternalName, + TCP: []string{"123", "234:1234"}, + ClusterIP: "", + ExternalName: "@oi:test", + }, + expectErr: "invalid service external name", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := test.s.validate() + if err != nil { + if !strings.Contains(err.Error(), test.expectErr) { + t.Errorf("validate:%s Expected err: %s, Got err: %v", test.name, test.expectErr, err) + } + } + if err == nil && len(test.expectErr) != 0 { + t.Errorf("validate:%s Expected success, Got err: %v", test.name, err) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/sorter.go b/vendor/k8s.io/kubernetes/pkg/kubectl/sorter.go new file mode 100644 index 000000000..8c7566a56 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/sorter.go @@ -0,0 +1,318 @@ +/* +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 kubectl + +import ( + "fmt" + "io" + "reflect" + "sort" + + "github.com/golang/glog" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/util/integer" + "k8s.io/client-go/util/jsonpath" + "k8s.io/kubernetes/pkg/printers" + + "vbom.ml/util/sortorder" +) + +// Sorting printer sorts list types before delegating to another printer. +// Non-list types are simply passed through +type SortingPrinter struct { + SortField string + Delegate printers.ResourcePrinter + Decoder runtime.Decoder +} + +func (s *SortingPrinter) PrintObj(obj runtime.Object, out io.Writer) error { + if !meta.IsListType(obj) { + return s.Delegate.PrintObj(obj, out) + } + + if err := s.sortObj(obj); err != nil { + return err + } + return s.Delegate.PrintObj(obj, out) +} + +func (s *SortingPrinter) sortObj(obj runtime.Object) error { + objs, err := meta.ExtractList(obj) + if err != nil { + return err + } + if len(objs) == 0 { + return nil + } + + sorter, err := SortObjects(s.Decoder, objs, s.SortField) + if err != nil { + return err + } + + switch list := obj.(type) { + case *v1.List: + outputList := make([]runtime.RawExtension, len(objs)) + for ix := range objs { + outputList[ix] = list.Items[sorter.OriginalPosition(ix)] + } + list.Items = outputList + return nil + } + return meta.SetList(obj, objs) +} + +func SortObjects(decoder runtime.Decoder, objs []runtime.Object, fieldInput string) (*RuntimeSort, error) { + for ix := range objs { + item := objs[ix] + switch u := item.(type) { + case *runtime.Unknown: + var err error + // decode runtime.Unknown to runtime.Unstructured for sorting. + // we don't actually want the internal versions of known types. + if objs[ix], _, err = decoder.Decode(u.Raw, nil, &unstructured.Unstructured{}); err != nil { + return nil, err + } + } + } + + field, err := printers.RelaxedJSONPathExpression(fieldInput) + if err != nil { + return nil, err + } + + parser := jsonpath.New("sorting").AllowMissingKeys(true) + if err := parser.Parse(field); err != nil { + return nil, err + } + + // We don't do any model validation here, so we traverse all objects to be sorted + // and, if the field is valid to at least one of them, we consider it to be a + // valid field; otherwise error out. + // Note that this requires empty fields to be considered later, when sorting. + var fieldFoundOnce bool + for _, obj := range objs { + var values [][]reflect.Value + if unstructured, ok := obj.(*unstructured.Unstructured); ok { + values, err = parser.FindResults(unstructured.Object) + } else { + values, err = parser.FindResults(reflect.ValueOf(obj).Elem().Interface()) + } + if err != nil { + return nil, err + } + if len(values) > 0 && len(values[0]) > 0 { + fieldFoundOnce = true + break + } + } + if !fieldFoundOnce { + return nil, fmt.Errorf("couldn't find any field with path %q in the list of objects", field) + } + + sorter := NewRuntimeSort(field, objs) + sort.Sort(sorter) + return sorter, nil +} + +// RuntimeSort is an implementation of the golang sort interface that knows how to sort +// lists of runtime.Object +type RuntimeSort struct { + field string + objs []runtime.Object + origPosition []int +} + +func NewRuntimeSort(field string, objs []runtime.Object) *RuntimeSort { + sorter := &RuntimeSort{field: field, objs: objs, origPosition: make([]int, len(objs))} + for ix := range objs { + sorter.origPosition[ix] = ix + } + return sorter +} + +func (r *RuntimeSort) Len() int { + return len(r.objs) +} + +func (r *RuntimeSort) Swap(i, j int) { + r.objs[i], r.objs[j] = r.objs[j], r.objs[i] + r.origPosition[i], r.origPosition[j] = r.origPosition[j], r.origPosition[i] +} + +func isLess(i, j reflect.Value) (bool, error) { + switch i.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return i.Int() < j.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return i.Uint() < j.Uint(), nil + case reflect.Float32, reflect.Float64: + return i.Float() < j.Float(), nil + case reflect.String: + return sortorder.NaturalLess(i.String(), j.String()), nil + case reflect.Ptr: + return isLess(i.Elem(), j.Elem()) + case reflect.Struct: + // sort metav1.Time + in := i.Interface() + if t, ok := in.(metav1.Time); ok { + time := j.Interface().(metav1.Time) + return t.Before(&time), nil + } + // fallback to the fields comparison + for idx := 0; idx < i.NumField(); idx++ { + less, err := isLess(i.Field(idx), j.Field(idx)) + if err != nil || !less { + return less, err + } + } + return true, nil + case reflect.Array, reflect.Slice: + // note: the length of i and j may be different + for idx := 0; idx < integer.IntMin(i.Len(), j.Len()); idx++ { + less, err := isLess(i.Index(idx), j.Index(idx)) + if err != nil || !less { + return less, err + } + } + return true, nil + + case reflect.Interface: + switch itype := i.Interface().(type) { + case uint8: + if jtype, ok := j.Interface().(uint8); ok { + return itype < jtype, nil + } + case uint16: + if jtype, ok := j.Interface().(uint16); ok { + return itype < jtype, nil + } + case uint32: + if jtype, ok := j.Interface().(uint32); ok { + return itype < jtype, nil + } + case uint64: + if jtype, ok := j.Interface().(uint64); ok { + return itype < jtype, nil + } + case int8: + if jtype, ok := j.Interface().(int8); ok { + return itype < jtype, nil + } + case int16: + if jtype, ok := j.Interface().(int16); ok { + return itype < jtype, nil + } + case int32: + if jtype, ok := j.Interface().(int32); ok { + return itype < jtype, nil + } + case int64: + if jtype, ok := j.Interface().(int64); ok { + return itype < jtype, nil + } + case uint: + if jtype, ok := j.Interface().(uint); ok { + return itype < jtype, nil + } + case int: + if jtype, ok := j.Interface().(int); ok { + return itype < jtype, nil + } + case float32: + if jtype, ok := j.Interface().(float32); ok { + return itype < jtype, nil + } + case float64: + if jtype, ok := j.Interface().(float64); ok { + return itype < jtype, nil + } + case string: + if jtype, ok := j.Interface().(string); ok { + return sortorder.NaturalLess(itype, jtype), nil + } + default: + return false, fmt.Errorf("unsortable type: %T", itype) + } + return false, fmt.Errorf("unsortable interface: %v", i.Kind()) + + default: + return false, fmt.Errorf("unsortable type: %v", i.Kind()) + } +} + +func (r *RuntimeSort) Less(i, j int) bool { + iObj := r.objs[i] + jObj := r.objs[j] + + var iValues [][]reflect.Value + var jValues [][]reflect.Value + var err error + + parser := jsonpath.New("sorting").AllowMissingKeys(true) + err = parser.Parse(r.field) + if err != nil { + panic(err) + } + + if unstructured, ok := iObj.(*unstructured.Unstructured); ok { + iValues, err = parser.FindResults(unstructured.Object) + } else { + iValues, err = parser.FindResults(reflect.ValueOf(iObj).Elem().Interface()) + } + if err != nil { + glog.Fatalf("Failed to get i values for %#v using %s (%#v)", iObj, r.field, err) + } + + if unstructured, ok := jObj.(*unstructured.Unstructured); ok { + jValues, err = parser.FindResults(unstructured.Object) + } else { + jValues, err = parser.FindResults(reflect.ValueOf(jObj).Elem().Interface()) + } + if err != nil { + glog.Fatalf("Failed to get j values for %#v using %s (%v)", jObj, r.field, err) + } + + if len(iValues) == 0 || len(iValues[0]) == 0 { + return true + } + if len(jValues) == 0 || len(jValues[0]) == 0 { + return false + } + iField := iValues[0][0] + jField := jValues[0][0] + + less, err := isLess(iField, jField) + if err != nil { + glog.Fatalf("Field %s in %T is an unsortable type: %s, err: %v", r.field, iObj, iField.Kind().String(), err) + } + return less +} + +// Returns the starting (original) position of a particular index. e.g. If OriginalPosition(0) returns 5 than the +// the item currently at position 0 was at position 5 in the original unsorted array. +func (r *RuntimeSort) OriginalPosition(ix int) int { + if ix < 0 || ix > len(r.origPosition) { + return -1 + } + return r.origPosition[ix] +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/sorter_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/sorter_test.go new file mode 100644 index 000000000..7c2e5ee0a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/sorter_test.go @@ -0,0 +1,475 @@ +/* +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 kubectl + +import ( + "reflect" + "strings" + "testing" + + api "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/api/legacyscheme" +) + +func encodeOrDie(obj runtime.Object) []byte { + data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(api.SchemeGroupVersion), obj) + if err != nil { + panic(err.Error()) + } + return data +} + +func TestSortingPrinter(t *testing.T) { + intPtr := func(val int32) *int32 { return &val } + + a := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a", + }, + } + + b := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "b", + }, + } + + c := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "c", + }, + } + + tests := []struct { + obj runtime.Object + sort runtime.Object + field string + name string + expectedErr string + }{ + { + name: "in-order-already", + obj: &api.PodList{ + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "a", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "b", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "c", + }, + }, + }, + }, + sort: &api.PodList{ + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "a", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "b", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "c", + }, + }, + }, + }, + field: "{.metadata.name}", + }, + { + name: "reverse-order", + obj: &api.PodList{ + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "b", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "c", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "a", + }, + }, + }, + }, + sort: &api.PodList{ + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "a", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "b", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "c", + }, + }, + }, + }, + field: "{.metadata.name}", + }, + { + name: "random-order-timestamp", + obj: &api.PodList{ + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + CreationTimestamp: metav1.Unix(300, 0), + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + CreationTimestamp: metav1.Unix(100, 0), + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + CreationTimestamp: metav1.Unix(200, 0), + }, + }, + }, + }, + sort: &api.PodList{ + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + CreationTimestamp: metav1.Unix(100, 0), + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + CreationTimestamp: metav1.Unix(200, 0), + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + CreationTimestamp: metav1.Unix(300, 0), + }, + }, + }, + }, + field: "{.metadata.creationTimestamp}", + }, + { + name: "random-order-numbers", + obj: &api.ReplicationControllerList{ + Items: []api.ReplicationController{ + { + Spec: api.ReplicationControllerSpec{ + Replicas: intPtr(5), + }, + }, + { + Spec: api.ReplicationControllerSpec{ + Replicas: intPtr(1), + }, + }, + { + Spec: api.ReplicationControllerSpec{ + Replicas: intPtr(9), + }, + }, + }, + }, + sort: &api.ReplicationControllerList{ + Items: []api.ReplicationController{ + { + Spec: api.ReplicationControllerSpec{ + Replicas: intPtr(1), + }, + }, + { + Spec: api.ReplicationControllerSpec{ + Replicas: intPtr(5), + }, + }, + { + Spec: api.ReplicationControllerSpec{ + Replicas: intPtr(9), + }, + }, + }, + }, + field: "{.spec.replicas}", + }, + { + name: "v1.List in order", + obj: &api.List{ + Items: []runtime.RawExtension{ + {Raw: encodeOrDie(a)}, + {Raw: encodeOrDie(b)}, + {Raw: encodeOrDie(c)}, + }, + }, + sort: &api.List{ + Items: []runtime.RawExtension{ + {Raw: encodeOrDie(a)}, + {Raw: encodeOrDie(b)}, + {Raw: encodeOrDie(c)}, + }, + }, + field: "{.metadata.name}", + }, + { + name: "v1.List in reverse", + obj: &api.List{ + Items: []runtime.RawExtension{ + {Raw: encodeOrDie(c)}, + {Raw: encodeOrDie(b)}, + {Raw: encodeOrDie(a)}, + }, + }, + sort: &api.List{ + Items: []runtime.RawExtension{ + {Raw: encodeOrDie(a)}, + {Raw: encodeOrDie(b)}, + {Raw: encodeOrDie(c)}, + }, + }, + field: "{.metadata.name}", + }, + { + name: "some-missing-fields", + obj: &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "kind": "List", + "apiVersion": "v1", + }, + Items: []unstructured.Unstructured{ + { + Object: map[string]interface{}{ + "kind": "ReplicationController", + "apiVersion": "v1", + "status": map[string]interface{}{ + "availableReplicas": 2, + }, + }, + }, + { + Object: map[string]interface{}{ + "kind": "ReplicationController", + "apiVersion": "v1", + "status": map[string]interface{}{}, + }, + }, + { + Object: map[string]interface{}{ + "kind": "ReplicationController", + "apiVersion": "v1", + "status": map[string]interface{}{ + "availableReplicas": 1, + }, + }, + }, + }, + }, + sort: &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "kind": "List", + "apiVersion": "v1", + }, + Items: []unstructured.Unstructured{ + { + Object: map[string]interface{}{ + "kind": "ReplicationController", + "apiVersion": "v1", + "status": map[string]interface{}{}, + }, + }, + { + Object: map[string]interface{}{ + "kind": "ReplicationController", + "apiVersion": "v1", + "status": map[string]interface{}{ + "availableReplicas": 1, + }, + }, + }, + { + Object: map[string]interface{}{ + "kind": "ReplicationController", + "apiVersion": "v1", + "status": map[string]interface{}{ + "availableReplicas": 2, + }, + }, + }, + }, + }, + field: "{.status.availableReplicas}", + }, + { + name: "all-missing-fields", + obj: &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "kind": "List", + "apiVersion": "v1", + }, + Items: []unstructured.Unstructured{ + { + Object: map[string]interface{}{ + "kind": "ReplicationController", + "apiVersion": "v1", + "status": map[string]interface{}{ + "replicas": 0, + }, + }, + }, + { + Object: map[string]interface{}{ + "kind": "ReplicationController", + "apiVersion": "v1", + "status": map[string]interface{}{ + "replicas": 0, + }, + }, + }, + }, + }, + field: "{.status.availableReplicas}", + expectedErr: "couldn't find any field with path \"{.status.availableReplicas}\" in the list of objects", + }, + { + name: "model-invalid-fields", + obj: &api.ReplicationControllerList{ + Items: []api.ReplicationController{ + { + Status: api.ReplicationControllerStatus{}, + }, + { + Status: api.ReplicationControllerStatus{}, + }, + { + Status: api.ReplicationControllerStatus{}, + }, + }, + }, + field: "{.invalid}", + expectedErr: "couldn't find any field with path \"{.invalid}\" in the list of objects", + }, + } + for _, test := range tests { + sort := &SortingPrinter{SortField: test.field, Decoder: legacyscheme.Codecs.UniversalDecoder()} + err := sort.sortObj(test.obj) + if err != nil { + if len(test.expectedErr) > 0 { + if strings.Contains(err.Error(), test.expectedErr) { + continue + } + t.Fatalf("%s: expected error containing: %q, got: \"%v\"", test.name, test.expectedErr, err) + } + t.Fatalf("%s: unexpected error: %v", test.name, err) + } + if len(test.expectedErr) > 0 { + t.Fatalf("%s: expected error containing: %q, got none", test.name, test.expectedErr) + } + if !reflect.DeepEqual(test.obj, test.sort) { + t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v", test.name, test.sort, test.obj) + } + } +} + +func TestRuntimeSortLess(t *testing.T) { + var testobj runtime.Object + + testobj = &api.PodList{ + Items: []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "b", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "c", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "a", + }, + }, + }, + } + + testobjs, err := meta.ExtractList(testobj) + if err != nil { + t.Fatalf("ExtractList testobj got unexpected error: %v", err) + } + + testfield := "{.metadata.name}" + testruntimeSort := NewRuntimeSort(testfield, testobjs) + tests := []struct { + name string + runtimeSort *RuntimeSort + i int + j int + expectResult bool + expectErr bool + }{ + { + name: "test less true", + runtimeSort: testruntimeSort, + i: 0, + j: 1, + expectResult: true, + }, + { + name: "test less false", + runtimeSort: testruntimeSort, + i: 1, + j: 2, + expectResult: false, + }, + } + + for i, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := test.runtimeSort.Less(test.i, test.j) + if result != test.expectResult { + t.Errorf("case[%d]:%s Expected result: %v, Got result: %v", i, test.name, test.expectResult, result) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/sorting_printer.go b/vendor/k8s.io/kubernetes/pkg/kubectl/sorting_printer.go deleted file mode 100644 index f1330e358..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/sorting_printer.go +++ /dev/null @@ -1,328 +0,0 @@ -/* -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 kubectl - -import ( - "fmt" - "io" - "reflect" - "sort" - - "github.com/golang/glog" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/util/integer" - "k8s.io/client-go/util/jsonpath" - "k8s.io/kubernetes/pkg/printers" - - "vbom.ml/util/sortorder" -) - -// Sorting printer sorts list types before delegating to another printer. -// Non-list types are simply passed through -type SortingPrinter struct { - SortField string - Delegate printers.ResourcePrinter - Decoder runtime.Decoder -} - -func (s *SortingPrinter) AfterPrint(w io.Writer, res string) error { - return nil -} - -func (s *SortingPrinter) PrintObj(obj runtime.Object, out io.Writer) error { - if !meta.IsListType(obj) { - return s.Delegate.PrintObj(obj, out) - } - - if err := s.sortObj(obj); err != nil { - return err - } - return s.Delegate.PrintObj(obj, out) -} - -// TODO: implement HandledResources() -func (s *SortingPrinter) HandledResources() []string { - return []string{} -} - -func (s *SortingPrinter) IsGeneric() bool { - return s.Delegate.IsGeneric() -} - -func (s *SortingPrinter) sortObj(obj runtime.Object) error { - objs, err := meta.ExtractList(obj) - if err != nil { - return err - } - if len(objs) == 0 { - return nil - } - - sorter, err := SortObjects(s.Decoder, objs, s.SortField) - if err != nil { - return err - } - - switch list := obj.(type) { - case *v1.List: - outputList := make([]runtime.RawExtension, len(objs)) - for ix := range objs { - outputList[ix] = list.Items[sorter.OriginalPosition(ix)] - } - list.Items = outputList - return nil - } - return meta.SetList(obj, objs) -} - -func SortObjects(decoder runtime.Decoder, objs []runtime.Object, fieldInput string) (*RuntimeSort, error) { - for ix := range objs { - item := objs[ix] - switch u := item.(type) { - case *runtime.Unknown: - var err error - // decode runtime.Unknown to runtime.Unstructured for sorting. - // we don't actually want the internal versions of known types. - if objs[ix], _, err = decoder.Decode(u.Raw, nil, &unstructured.Unstructured{}); err != nil { - return nil, err - } - } - } - - field, err := printers.RelaxedJSONPathExpression(fieldInput) - if err != nil { - return nil, err - } - - parser := jsonpath.New("sorting").AllowMissingKeys(true) - if err := parser.Parse(field); err != nil { - return nil, err - } - - // We don't do any model validation here, so we traverse all objects to be sorted - // and, if the field is valid to at least one of them, we consider it to be a - // valid field; otherwise error out. - // Note that this requires empty fields to be considered later, when sorting. - var fieldFoundOnce bool - for _, obj := range objs { - var values [][]reflect.Value - if unstructured, ok := obj.(*unstructured.Unstructured); ok { - values, err = parser.FindResults(unstructured.Object) - } else { - values, err = parser.FindResults(reflect.ValueOf(obj).Elem().Interface()) - } - if err != nil { - return nil, err - } - if len(values) > 0 && len(values[0]) > 0 { - fieldFoundOnce = true - break - } - } - if !fieldFoundOnce { - return nil, fmt.Errorf("couldn't find any field with path %q in the list of objects", field) - } - - sorter := NewRuntimeSort(field, objs) - sort.Sort(sorter) - return sorter, nil -} - -// RuntimeSort is an implementation of the golang sort interface that knows how to sort -// lists of runtime.Object -type RuntimeSort struct { - field string - objs []runtime.Object - origPosition []int -} - -func NewRuntimeSort(field string, objs []runtime.Object) *RuntimeSort { - sorter := &RuntimeSort{field: field, objs: objs, origPosition: make([]int, len(objs))} - for ix := range objs { - sorter.origPosition[ix] = ix - } - return sorter -} - -func (r *RuntimeSort) Len() int { - return len(r.objs) -} - -func (r *RuntimeSort) Swap(i, j int) { - r.objs[i], r.objs[j] = r.objs[j], r.objs[i] - r.origPosition[i], r.origPosition[j] = r.origPosition[j], r.origPosition[i] -} - -func isLess(i, j reflect.Value) (bool, error) { - switch i.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return i.Int() < j.Int(), nil - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return i.Uint() < j.Uint(), nil - case reflect.Float32, reflect.Float64: - return i.Float() < j.Float(), nil - case reflect.String: - return sortorder.NaturalLess(i.String(), j.String()), nil - case reflect.Ptr: - return isLess(i.Elem(), j.Elem()) - case reflect.Struct: - // sort metav1.Time - in := i.Interface() - if t, ok := in.(metav1.Time); ok { - time := j.Interface().(metav1.Time) - return t.Before(&time), nil - } - // fallback to the fields comparison - for idx := 0; idx < i.NumField(); idx++ { - less, err := isLess(i.Field(idx), j.Field(idx)) - if err != nil || !less { - return less, err - } - } - return true, nil - case reflect.Array, reflect.Slice: - // note: the length of i and j may be different - for idx := 0; idx < integer.IntMin(i.Len(), j.Len()); idx++ { - less, err := isLess(i.Index(idx), j.Index(idx)) - if err != nil || !less { - return less, err - } - } - return true, nil - - case reflect.Interface: - switch itype := i.Interface().(type) { - case uint8: - if jtype, ok := j.Interface().(uint8); ok { - return itype < jtype, nil - } - case uint16: - if jtype, ok := j.Interface().(uint16); ok { - return itype < jtype, nil - } - case uint32: - if jtype, ok := j.Interface().(uint32); ok { - return itype < jtype, nil - } - case uint64: - if jtype, ok := j.Interface().(uint64); ok { - return itype < jtype, nil - } - case int8: - if jtype, ok := j.Interface().(int8); ok { - return itype < jtype, nil - } - case int16: - if jtype, ok := j.Interface().(int16); ok { - return itype < jtype, nil - } - case int32: - if jtype, ok := j.Interface().(int32); ok { - return itype < jtype, nil - } - case int64: - if jtype, ok := j.Interface().(int64); ok { - return itype < jtype, nil - } - case uint: - if jtype, ok := j.Interface().(uint); ok { - return itype < jtype, nil - } - case int: - if jtype, ok := j.Interface().(int); ok { - return itype < jtype, nil - } - case float32: - if jtype, ok := j.Interface().(float32); ok { - return itype < jtype, nil - } - case float64: - if jtype, ok := j.Interface().(float64); ok { - return itype < jtype, nil - } - case string: - if jtype, ok := j.Interface().(string); ok { - return sortorder.NaturalLess(itype, jtype), nil - } - default: - return false, fmt.Errorf("unsortable type: %T", itype) - } - return false, fmt.Errorf("unsortable interface: %v", i.Kind()) - - default: - return false, fmt.Errorf("unsortable type: %v", i.Kind()) - } -} - -func (r *RuntimeSort) Less(i, j int) bool { - iObj := r.objs[i] - jObj := r.objs[j] - - parser := jsonpath.New("sorting").AllowMissingKeys(true) - parser.Parse(r.field) - - var iValues [][]reflect.Value - var jValues [][]reflect.Value - var err error - - if unstructured, ok := iObj.(*unstructured.Unstructured); ok { - iValues, err = parser.FindResults(unstructured.Object) - } else { - iValues, err = parser.FindResults(reflect.ValueOf(iObj).Elem().Interface()) - } - if err != nil { - glog.Fatalf("Failed to get i values for %#v using %s (%#v)", iObj, r.field, err) - } - - if unstructured, ok := jObj.(*unstructured.Unstructured); ok { - jValues, err = parser.FindResults(unstructured.Object) - } else { - jValues, err = parser.FindResults(reflect.ValueOf(jObj).Elem().Interface()) - } - if err != nil { - glog.Fatalf("Failed to get j values for %#v using %s (%v)", jObj, r.field, err) - } - - if len(iValues) == 0 || len(iValues[0]) == 0 { - return true - } - if len(jValues) == 0 || len(jValues[0]) == 0 { - return false - } - iField := iValues[0][0] - jField := jValues[0][0] - - less, err := isLess(iField, jField) - if err != nil { - glog.Fatalf("Field %s in %T is an unsortable type: %s, err: %v", r.field, iObj, iField.Kind().String(), err) - } - return less -} - -// Returns the starting (original) position of a particular index. e.g. If OriginalPosition(0) returns 5 than the -// the item currently at position 0 was at position 5 in the original unsorted array. -func (r *RuntimeSort) OriginalPosition(ix int) int { - if ix < 0 || ix > len(r.origPosition) { - return -1 - } - return r.origPosition[ix] -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/sorting_printer_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/sorting_printer_test.go deleted file mode 100644 index 7f6b0ad5c..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/sorting_printer_test.go +++ /dev/null @@ -1,410 +0,0 @@ -/* -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 kubectl - -import ( - "reflect" - "strings" - "testing" - - api "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/api/legacyscheme" -) - -func encodeOrDie(obj runtime.Object) []byte { - data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(api.SchemeGroupVersion), obj) - if err != nil { - panic(err.Error()) - } - return data -} - -func TestSortingPrinter(t *testing.T) { - intPtr := func(val int32) *int32 { return &val } - - a := &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "a", - }, - } - - b := &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "b", - }, - } - - c := &api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "c", - }, - } - - tests := []struct { - obj runtime.Object - sort runtime.Object - field string - name string - expectedErr string - }{ - { - name: "in-order-already", - obj: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "a", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "b", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "c", - }, - }, - }, - }, - sort: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "a", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "b", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "c", - }, - }, - }, - }, - field: "{.metadata.name}", - }, - { - name: "reverse-order", - obj: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "b", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "c", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "a", - }, - }, - }, - }, - sort: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "a", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "b", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "c", - }, - }, - }, - }, - field: "{.metadata.name}", - }, - { - name: "random-order-timestamp", - obj: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{ - CreationTimestamp: metav1.Unix(300, 0), - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - CreationTimestamp: metav1.Unix(100, 0), - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - CreationTimestamp: metav1.Unix(200, 0), - }, - }, - }, - }, - sort: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: metav1.ObjectMeta{ - CreationTimestamp: metav1.Unix(100, 0), - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - CreationTimestamp: metav1.Unix(200, 0), - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - CreationTimestamp: metav1.Unix(300, 0), - }, - }, - }, - }, - field: "{.metadata.creationTimestamp}", - }, - { - name: "random-order-numbers", - obj: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(5), - }, - }, - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(1), - }, - }, - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(9), - }, - }, - }, - }, - sort: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(1), - }, - }, - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(5), - }, - }, - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(9), - }, - }, - }, - }, - field: "{.spec.replicas}", - }, - { - name: "v1.List in order", - obj: &api.List{ - Items: []runtime.RawExtension{ - {Raw: encodeOrDie(a)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(c)}, - }, - }, - sort: &api.List{ - Items: []runtime.RawExtension{ - {Raw: encodeOrDie(a)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(c)}, - }, - }, - field: "{.metadata.name}", - }, - { - name: "v1.List in reverse", - obj: &api.List{ - Items: []runtime.RawExtension{ - {Raw: encodeOrDie(c)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(a)}, - }, - }, - sort: &api.List{ - Items: []runtime.RawExtension{ - {Raw: encodeOrDie(a)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(c)}, - }, - }, - field: "{.metadata.name}", - }, - { - name: "some-missing-fields", - obj: &unstructured.UnstructuredList{ - Object: map[string]interface{}{ - "kind": "List", - "apiVersion": "v1", - }, - Items: []unstructured.Unstructured{ - { - Object: map[string]interface{}{ - "kind": "ReplicationController", - "apiVersion": "v1", - "status": map[string]interface{}{ - "availableReplicas": 2, - }, - }, - }, - { - Object: map[string]interface{}{ - "kind": "ReplicationController", - "apiVersion": "v1", - "status": map[string]interface{}{}, - }, - }, - { - Object: map[string]interface{}{ - "kind": "ReplicationController", - "apiVersion": "v1", - "status": map[string]interface{}{ - "availableReplicas": 1, - }, - }, - }, - }, - }, - sort: &unstructured.UnstructuredList{ - Object: map[string]interface{}{ - "kind": "List", - "apiVersion": "v1", - }, - Items: []unstructured.Unstructured{ - { - Object: map[string]interface{}{ - "kind": "ReplicationController", - "apiVersion": "v1", - "status": map[string]interface{}{}, - }, - }, - { - Object: map[string]interface{}{ - "kind": "ReplicationController", - "apiVersion": "v1", - "status": map[string]interface{}{ - "availableReplicas": 1, - }, - }, - }, - { - Object: map[string]interface{}{ - "kind": "ReplicationController", - "apiVersion": "v1", - "status": map[string]interface{}{ - "availableReplicas": 2, - }, - }, - }, - }, - }, - field: "{.status.availableReplicas}", - }, - { - name: "all-missing-fields", - obj: &unstructured.UnstructuredList{ - Object: map[string]interface{}{ - "kind": "List", - "apiVersion": "v1", - }, - Items: []unstructured.Unstructured{ - { - Object: map[string]interface{}{ - "kind": "ReplicationController", - "apiVersion": "v1", - "status": map[string]interface{}{ - "replicas": 0, - }, - }, - }, - { - Object: map[string]interface{}{ - "kind": "ReplicationController", - "apiVersion": "v1", - "status": map[string]interface{}{ - "replicas": 0, - }, - }, - }, - }, - }, - field: "{.status.availableReplicas}", - expectedErr: "couldn't find any field with path \"{.status.availableReplicas}\" in the list of objects", - }, - { - name: "model-invalid-fields", - obj: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ - { - Status: api.ReplicationControllerStatus{}, - }, - { - Status: api.ReplicationControllerStatus{}, - }, - { - Status: api.ReplicationControllerStatus{}, - }, - }, - }, - field: "{.invalid}", - expectedErr: "couldn't find any field with path \"{.invalid}\" in the list of objects", - }, - } - for _, test := range tests { - sort := &SortingPrinter{SortField: test.field, Decoder: legacyscheme.Codecs.UniversalDecoder()} - err := sort.sortObj(test.obj) - if err != nil { - if len(test.expectedErr) > 0 { - if strings.Contains(err.Error(), test.expectedErr) { - continue - } - t.Fatalf("%s: expected error containing: %q, got: \"%v\"", test.name, test.expectedErr, err) - } - t.Fatalf("%s: unexpected error: %v", test.name, err) - } - if len(test.expectedErr) > 0 { - t.Fatalf("%s: expected error containing: %q, got none", test.name, test.expectedErr) - } - if !reflect.DeepEqual(test.obj, test.sort) { - t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v", test.name, test.sort, test.obj) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/util/BUILD index 16c098d19..73dfd3a19 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/util/BUILD @@ -98,13 +98,11 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//pkg/kubectl/util/crlf:all-srcs", "//pkg/kubectl/util/hash:all-srcs", "//pkg/kubectl/util/i18n:all-srcs", "//pkg/kubectl/util/logs:all-srcs", "//pkg/kubectl/util/slice:all-srcs", "//pkg/kubectl/util/term:all-srcs", - "//pkg/kubectl/util/transport:all-srcs", ], tags = ["automanaged"], visibility = ["//build/visible_to:pkg_kubectl_util_CONSUMERS"], diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/BUILD deleted file mode 100644 index fad331874..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["crlf.go"], - importpath = "k8s.io/kubernetes/pkg/kubectl/util/crlf", -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash.go b/vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash.go index d7afaab7d..de0036245 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash.go @@ -56,7 +56,11 @@ func SecretHash(sec *v1.Secret) (string, error) { // Data, Kind, and Name are taken into account. func encodeConfigMap(cm *v1.ConfigMap) (string, error) { // json.Marshal sorts the keys in a stable order in the encoding - data, err := json.Marshal(map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data}) + m := map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data} + if len(cm.BinaryData) > 0 { + m["binaryData"] = cm.BinaryData + } + data, err := json.Marshal(m) if err != nil { return "", err } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash_test.go index b9a168a23..f527a98a2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash_test.go @@ -32,11 +32,19 @@ func TestConfigMapHash(t *testing.T) { err string }{ // empty map - {"empty data", &v1.ConfigMap{Data: map[string]string{}}, "42745tchd9", ""}, + {"empty data", &v1.ConfigMap{Data: map[string]string{}, BinaryData: map[string][]byte{}}, "42745tchd9", ""}, // one key {"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, "9g67k2htb6", ""}, // three keys (tests sorting order) {"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, "f5h7t85m9b", ""}, + // empty binary data map + {"empty binary data", &v1.ConfigMap{BinaryData: map[string][]byte{}}, "dk855m5d49", ""}, + // one key with binary data + {"one key with binary data", &v1.ConfigMap{BinaryData: map[string][]byte{"one": []byte("")}}, "mk79584b8c", ""}, + // three keys with binary data (tests sorting order) + {"three keys with binary data", &v1.ConfigMap{BinaryData: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, "t458mc6db2", ""}, + // two keys, one with string and another with binary data + {"two keys with one each", &v1.ConfigMap{Data: map[string]string{"one": ""}, BinaryData: map[string][]byte{"two": []byte("")}}, "698h7c7t9m", ""}, } for _, c := range cases { @@ -89,6 +97,14 @@ func TestEncodeConfigMap(t *testing.T) { {"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, `{"data":{"one":""},"kind":"ConfigMap","name":""}`, ""}, // three keys (tests sorting order) {"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, `{"data":{"one":"","three":"3","two":"2"},"kind":"ConfigMap","name":""}`, ""}, + // empty binary map + {"empty data", &v1.ConfigMap{BinaryData: map[string][]byte{}}, `{"data":null,"kind":"ConfigMap","name":""}`, ""}, + // one key with binary data + {"one key", &v1.ConfigMap{BinaryData: map[string][]byte{"one": []byte("")}}, `{"binaryData":{"one":""},"data":null,"kind":"ConfigMap","name":""}`, ""}, + // three keys with binary data (tests sorting order) + {"three keys", &v1.ConfigMap{BinaryData: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, `{"binaryData":{"one":"","three":"Mw==","two":"Mg=="},"data":null,"kind":"ConfigMap","name":""}`, ""}, + // two keys, one string and one binary values + {"two keys with one each", &v1.ConfigMap{Data: map[string]string{"one": ""}, BinaryData: map[string][]byte{"two": []byte("")}}, `{"binaryData":{"two":""},"data":{"one":""},"kind":"ConfigMap","name":""}`, ""}, } for _, c := range cases { s, err := encodeConfigMap(c.cm) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n.go b/vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n.go index 3cafc67c2..e287eab97 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n.go @@ -40,6 +40,7 @@ var knownTranslations = map[string][]string{ "zh_TW", "it_IT", "de_DE", + "ko_KR", }, // only used for unit tests. "test": { diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/logs.go b/vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/logs.go index 392bbc0fb..eae42f795 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/logs.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/logs.go @@ -46,7 +46,7 @@ func (writer GlogWriter) Write(data []byte) (n int, err error) { func InitLogs() { log.SetOutput(GlogWriter{}) log.SetFlags(0) - // The default glog flush interval is 30 seconds, which is frighteningly long. + // The default glog flush interval is 5 seconds. go wait.Until(glog.Flush, *logFlushFreq, wait.NeverStop) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/transport/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/util/transport/BUILD deleted file mode 100644 index c077a903c..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/transport/BUILD +++ /dev/null @@ -1,33 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["round_tripper.go"], - importpath = "k8s.io/kubernetes/pkg/kubectl/util/transport", - visibility = ["//visibility:public"], - deps = [ - "//vendor/github.com/gregjones/httpcache:go_default_library", - "//vendor/github.com/gregjones/httpcache/diskcache:go_default_library", - "//vendor/github.com/peterbourgon/diskv:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["round_tripper_test.go"], - embed = [":go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/transport/round_tripper.go b/vendor/k8s.io/kubernetes/pkg/kubectl/util/transport/round_tripper.go deleted file mode 100644 index 82e3e502e..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/transport/round_tripper.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -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 transport provides a round tripper capable of caching HTTP responses. -package transport - -import ( - "net/http" - "path/filepath" - - "github.com/gregjones/httpcache" - "github.com/gregjones/httpcache/diskcache" - "github.com/peterbourgon/diskv" -) - -type cacheRoundTripper struct { - rt *httpcache.Transport -} - -// NewCacheRoundTripper creates a roundtripper that reads the ETag on -// response headers and send the If-None-Match header on subsequent -// corresponding requests. -func NewCacheRoundTripper(cacheDir string, rt http.RoundTripper) http.RoundTripper { - d := diskv.New(diskv.Options{ - BasePath: cacheDir, - TempDir: filepath.Join(cacheDir, ".diskv-temp"), - }) - t := httpcache.NewTransport(diskcache.NewWithDiskv(d)) - t.Transport = rt - - return &cacheRoundTripper{rt: t} -} - -func (rt *cacheRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - return rt.rt.RoundTrip(req) -} - -func (rt *cacheRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt.Transport } diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/transport/round_tripper_test.go b/vendor/k8s.io/kubernetes/pkg/kubectl/util/transport/round_tripper_test.go deleted file mode 100644 index e68e8e372..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/transport/round_tripper_test.go +++ /dev/null @@ -1,95 +0,0 @@ -/* -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 transport - -import ( - "bytes" - "io/ioutil" - "net/http" - "net/url" - "os" - "testing" -) - -// copied from k8s.io/client-go/transport/round_trippers_test.go -type testRoundTripper struct { - Request *http.Request - Response *http.Response - Err error -} - -func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - rt.Request = req - return rt.Response, rt.Err -} - -func TestCacheRoundTripper(t *testing.T) { - rt := &testRoundTripper{} - cacheDir, err := ioutil.TempDir("", "cache-rt") - defer os.RemoveAll(cacheDir) - if err != nil { - t.Fatal(err) - } - cache := NewCacheRoundTripper(cacheDir, rt) - - // First call, caches the response - req := &http.Request{ - Method: http.MethodGet, - URL: &url.URL{Host: "localhost"}, - } - rt.Response = &http.Response{ - Header: http.Header{"ETag": []string{`"123456"`}}, - Body: ioutil.NopCloser(bytes.NewReader([]byte("Content"))), - StatusCode: http.StatusOK, - } - resp, err := cache.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - content, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - if string(content) != "Content" { - t.Errorf(`Expected Body to be "Content", got %q`, string(content)) - } - - // Second call, returns cached response - req = &http.Request{ - Method: http.MethodGet, - URL: &url.URL{Host: "localhost"}, - } - rt.Response = &http.Response{ - StatusCode: http.StatusNotModified, - Body: ioutil.NopCloser(bytes.NewReader([]byte("Other Content"))), - } - - resp, err = cache.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - - // Read body and make sure we have the initial content - content, err = ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - t.Fatal(err) - } - if string(content) != "Content" { - t.Errorf("Invalid content read from cache %q", string(content)) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/util/util.go b/vendor/k8s.io/kubernetes/pkg/kubectl/util/util.go index fd1bf1364..41427780c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/util/util.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/util/util.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "path" + "path/filepath" "strings" "time" @@ -60,7 +61,7 @@ func ParseFileSource(source string) (keyName, filePath string, err error) { numSeparators := strings.Count(source, "=") switch { case numSeparators == 0: - return path.Base(source), source, nil + return path.Base(filepath.ToSlash(source)), source, nil case numSeparators == 1 && strings.HasPrefix(source, "="): return "", "", fmt.Errorf("key name for file path %v missing.", strings.TrimPrefix(source, "=")) case numSeparators == 1 && strings.HasSuffix(source, "="): diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/BUILD index f0230fbb1..d6c52d725 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/BUILD @@ -46,6 +46,7 @@ go_library( "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/cadvisor:go_default_library", "//pkg/kubelet/certificate:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/config:go_default_library", "//pkg/kubelet/configmap:go_default_library", @@ -55,8 +56,6 @@ go_library( "//pkg/kubelet/envvars:go_default_library", "//pkg/kubelet/events:go_default_library", "//pkg/kubelet/eviction:go_default_library", - "//pkg/kubelet/gpu:go_default_library", - "//pkg/kubelet/gpu/nvidia:go_default_library", "//pkg/kubelet/images:go_default_library", "//pkg/kubelet/kubeletconfig:go_default_library", "//pkg/kubelet/kuberuntime:go_default_library", @@ -65,7 +64,6 @@ go_library( "//pkg/kubelet/metrics:go_default_library", "//pkg/kubelet/metrics/collectors:go_default_library", "//pkg/kubelet/mountpod:go_default_library", - "//pkg/kubelet/network:go_default_library", "//pkg/kubelet/network/dns:go_default_library", "//pkg/kubelet/pleg:go_default_library", "//pkg/kubelet/pod:go_default_library", @@ -73,7 +71,6 @@ go_library( "//pkg/kubelet/prober:go_default_library", "//pkg/kubelet/prober/results:go_default_library", "//pkg/kubelet/remote:go_default_library", - "//pkg/kubelet/rkt:go_default_library", "//pkg/kubelet/secret:go_default_library", "//pkg/kubelet/server:go_default_library", "//pkg/kubelet/server/portforward:go_default_library", @@ -83,15 +80,19 @@ go_library( "//pkg/kubelet/stats:go_default_library", "//pkg/kubelet/status:go_default_library", "//pkg/kubelet/sysctl:go_default_library", + "//pkg/kubelet/token:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util:go_default_library", "//pkg/kubelet/util/format:go_default_library", + "//pkg/kubelet/util/manager:go_default_library", + "//pkg/kubelet/util/pluginwatcher:go_default_library", "//pkg/kubelet/util/queue:go_default_library", "//pkg/kubelet/util/sliceutils:go_default_library", "//pkg/kubelet/volumemanager:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/security/apparmor:go_default_library", + "//pkg/security/podsecuritypolicy/sysctl:go_default_library", "//pkg/securitycontext:go_default_library", "//pkg/util/dbus:go_default_library", "//pkg/util/file:go_default_library", @@ -103,6 +104,7 @@ go_library( "//pkg/util/removeall:go_default_library", "//pkg/version:go_default_library", "//pkg/volume:go_default_library", + "//pkg/volume/csi:go_default_library", "//pkg/volume/util:go_default_library", "//pkg/volume/util/types:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library", @@ -113,6 +115,7 @@ go_library( "//vendor/github.com/google/cadvisor/events:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/google/cadvisor/info/v2:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -133,7 +136,6 @@ go_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", @@ -165,13 +167,11 @@ go_test( }), embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core/install:go_default_library", "//pkg/capabilities:go_default_library", "//pkg/cloudprovider/providers/fake:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", - "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/cadvisor/testing:go_default_library", "//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/config:go_default_library", @@ -179,12 +179,9 @@ go_test( "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/container/testing:go_default_library", "//pkg/kubelet/eviction:go_default_library", - "//pkg/kubelet/gpu:go_default_library", "//pkg/kubelet/images:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/logs:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/testing:go_default_library", "//pkg/kubelet/pleg:go_default_library", "//pkg/kubelet/pod:go_default_library", "//pkg/kubelet/pod/testing:go_default_library", @@ -197,14 +194,18 @@ go_test( "//pkg/kubelet/stats:go_default_library", "//pkg/kubelet/status:go_default_library", "//pkg/kubelet/status/testing:go_default_library", + "//pkg/kubelet/token:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/queue:go_default_library", "//pkg/kubelet/util/sliceutils:go_default_library", "//pkg/kubelet/volumemanager:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/version:go_default_library", "//pkg/volume:go_default_library", + "//pkg/volume/aws_ebs:go_default_library", + "//pkg/volume/azure_dd:go_default_library", + "//pkg/volume/gce_pd:go_default_library", "//pkg/volume/host_path:go_default_library", "//pkg/volume/testing:go_default_library", "//pkg/volume/util:go_default_library", @@ -254,6 +255,7 @@ filegroup( "//pkg/kubelet/cadvisor:all-srcs", "//pkg/kubelet/certificate:all-srcs", "//pkg/kubelet/checkpoint:all-srcs", + "//pkg/kubelet/checkpointmanager:all-srcs", "//pkg/kubelet/client:all-srcs", "//pkg/kubelet/cm:all-srcs", "//pkg/kubelet/config:all-srcs", @@ -264,7 +266,6 @@ filegroup( "//pkg/kubelet/envvars:all-srcs", "//pkg/kubelet/events:all-srcs", "//pkg/kubelet/eviction:all-srcs", - "//pkg/kubelet/gpu:all-srcs", "//pkg/kubelet/images:all-srcs", "//pkg/kubelet/kubeletconfig:all-srcs", "//pkg/kubelet/kuberuntime:all-srcs", @@ -280,12 +281,12 @@ filegroup( "//pkg/kubelet/prober:all-srcs", "//pkg/kubelet/qos:all-srcs", "//pkg/kubelet/remote:all-srcs", - "//pkg/kubelet/rkt:all-srcs", "//pkg/kubelet/secret:all-srcs", "//pkg/kubelet/server:all-srcs", "//pkg/kubelet/stats:all-srcs", "//pkg/kubelet/status:all-srcs", "//pkg/kubelet/sysctl:all-srcs", + "//pkg/kubelet/token:all-srcs", "//pkg/kubelet/types:all-srcs", "//pkg/kubelet/util:all-srcs", "//pkg/kubelet/volumemanager:all-srcs", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/BUILD index 47cb8184c..2a22e4812 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/BUILD @@ -41,6 +41,7 @@ filegroup( "//pkg/kubelet/apis/deviceplugin/v1alpha:all-srcs", "//pkg/kubelet/apis/deviceplugin/v1beta1:all-srcs", "//pkg/kubelet/apis/kubeletconfig:all-srcs", + "//pkg/kubelet/apis/pluginregistration/v1alpha1:all-srcs", "//pkg/kubelet/apis/stats/v1alpha1:all-srcs", ], tags = ["automanaged"], diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go index 82e5a5e5e..c17a8e0da 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -60,6 +60,7 @@ limitations under the License. Capability LinuxContainerSecurityContext LinuxContainerConfig + WindowsContainerSecurityContext WindowsContainerConfig WindowsContainerResources ContainerMetadata @@ -434,7 +435,9 @@ func (m *PortMapping) GetHostIp() string { type Mount struct { // Path of the mount within the container. ContainerPath string `protobuf:"bytes,1,opt,name=container_path,json=containerPath,proto3" json:"container_path,omitempty"` - // Path of the mount on the host. + // Path of the mount on the host. If the hostPath doesn't exist, then runtimes + // should report error. If the hostpath is a symbolic link, runtimes should + // follow the symlink and mount the real destination to container. HostPath string `protobuf:"bytes,2,opt,name=host_path,json=hostPath,proto3" json:"host_path,omitempty"` // If set, the mount is read-only. Readonly bool `protobuf:"varint,3,opt,name=readonly,proto3" json:"readonly,omitempty"` @@ -555,7 +558,8 @@ type LinuxSandboxSecurityContext struct { SelinuxOptions *SELinuxOption `protobuf:"bytes,2,opt,name=selinux_options,json=selinuxOptions" json:"selinux_options,omitempty"` // UID to run sandbox processes as, when applicable. RunAsUser *Int64Value `protobuf:"bytes,3,opt,name=run_as_user,json=runAsUser" json:"run_as_user,omitempty"` - // GID to run sandbox processes as, when applicable. + // GID to run sandbox processes as, when applicable. run_as_group should only + // be specified when run_as_user is specified; otherwise, the runtime MUST error. RunAsGroup *Int64Value `protobuf:"bytes,8,opt,name=run_as_group,json=runAsGroup" json:"run_as_group,omitempty"` // If set, the root filesystem of the sandbox is read-only. ReadonlyRootfs bool `protobuf:"varint,4,opt,name=readonly_rootfs,json=readonlyRootfs,proto3" json:"readonly_rootfs,omitempty"` @@ -569,7 +573,7 @@ type LinuxSandboxSecurityContext struct { // privileged containers are expected to be run. Privileged bool `protobuf:"varint,6,opt,name=privileged,proto3" json:"privileged,omitempty"` // Seccomp profile for the sandbox, candidate values are: - // * docker/default: the default profile for the docker container runtime + // * runtime/default: the default profile for the container runtime // * unconfined: unconfined profile, ie, no seccomp sandboxing // * localhost/: the profile installed on the node. // is the full path of the profile. @@ -741,7 +745,7 @@ type PodSandboxConfig struct { // structured logs, systemd-journald journal files, gRPC trace files, etc. // E.g., // PodSandboxConfig.LogDirectory = `/var/log/pods//` - // ContainerConfig.LogPath = `containerName_Instance#.log` + // ContainerConfig.LogPath = `containerName/Instance#.log` // // WARNING: Log management and how kubelet should interface with the // container logs are under active discussion in @@ -1463,8 +1467,9 @@ type LinuxContainerSecurityContext struct { // UID to run the container process as. Only one of run_as_user and // run_as_username can be specified at a time. RunAsUser *Int64Value `protobuf:"bytes,5,opt,name=run_as_user,json=runAsUser" json:"run_as_user,omitempty"` - // GID to run the container process as. Only one of run_as_group and - // run_as_groupname can be specified at a time. + // GID to run the container process as. run_as_group should only be specified + // when run_as_user or run_as_username is specified; otherwise, the runtime + // MUST error. RunAsGroup *Int64Value `protobuf:"bytes,12,opt,name=run_as_group,json=runAsGroup" json:"run_as_group,omitempty"` // User name to run the container process as. If specified, the user MUST // exist in the container image (i.e. in the /etc/passwd inside the image), @@ -1483,7 +1488,7 @@ type LinuxContainerSecurityContext struct { // http://wiki.apparmor.net/index.php/AppArmor_Core_Policy_Reference ApparmorProfile string `protobuf:"bytes,9,opt,name=apparmor_profile,json=apparmorProfile,proto3" json:"apparmor_profile,omitempty"` // Seccomp profile for the container, candidate values are: - // * docker/default: the default profile for the docker container runtime + // * runtime/default: the default profile for the container runtime // * unconfined: unconfined profile, ie, no seccomp sandboxing // * localhost/: the profile installed on the node. // is the full path of the profile. @@ -1611,16 +1616,39 @@ func (m *LinuxContainerConfig) GetSecurityContext() *LinuxContainerSecurityConte return nil } +// WindowsContainerSecurityContext holds windows security configuration that will be applied to a container. +type WindowsContainerSecurityContext struct { + // User name to run the container process as. If specified, the user MUST + // exist in the container image and be resolved there by the runtime; + // otherwise, the runtime MUST return error. + RunAsUsername string `protobuf:"bytes,1,opt,name=run_as_username,json=runAsUsername,proto3" json:"run_as_username,omitempty"` +} + +func (m *WindowsContainerSecurityContext) Reset() { *m = WindowsContainerSecurityContext{} } +func (*WindowsContainerSecurityContext) ProtoMessage() {} +func (*WindowsContainerSecurityContext) Descriptor() ([]byte, []int) { + return fileDescriptorApi, []int{35} +} + +func (m *WindowsContainerSecurityContext) GetRunAsUsername() string { + if m != nil { + return m.RunAsUsername + } + return "" +} + // WindowsContainerConfig contains platform-specific configuration for // Windows-based containers. type WindowsContainerConfig struct { // Resources specification for the container. Resources *WindowsContainerResources `protobuf:"bytes,1,opt,name=resources" json:"resources,omitempty"` + // WindowsContainerSecurityContext configuration for the container. + SecurityContext *WindowsContainerSecurityContext `protobuf:"bytes,2,opt,name=security_context,json=securityContext" json:"security_context,omitempty"` } func (m *WindowsContainerConfig) Reset() { *m = WindowsContainerConfig{} } func (*WindowsContainerConfig) ProtoMessage() {} -func (*WindowsContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{35} } +func (*WindowsContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{36} } func (m *WindowsContainerConfig) GetResources() *WindowsContainerResources { if m != nil { @@ -1629,6 +1657,13 @@ func (m *WindowsContainerConfig) GetResources() *WindowsContainerResources { return nil } +func (m *WindowsContainerConfig) GetSecurityContext() *WindowsContainerSecurityContext { + if m != nil { + return m.SecurityContext + } + return nil +} + // WindowsContainerResources specifies Windows specific configuration for // resources. type WindowsContainerResources struct { @@ -1644,7 +1679,7 @@ type WindowsContainerResources struct { func (m *WindowsContainerResources) Reset() { *m = WindowsContainerResources{} } func (*WindowsContainerResources) ProtoMessage() {} -func (*WindowsContainerResources) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{36} } +func (*WindowsContainerResources) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{37} } func (m *WindowsContainerResources) GetCpuShares() int64 { if m != nil { @@ -1688,7 +1723,7 @@ type ContainerMetadata struct { func (m *ContainerMetadata) Reset() { *m = ContainerMetadata{} } func (*ContainerMetadata) ProtoMessage() {} -func (*ContainerMetadata) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{37} } +func (*ContainerMetadata) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{38} } func (m *ContainerMetadata) GetName() string { if m != nil { @@ -1719,7 +1754,7 @@ type Device struct { func (m *Device) Reset() { *m = Device{} } func (*Device) ProtoMessage() {} -func (*Device) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{38} } +func (*Device) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{39} } func (m *Device) GetContainerPath() string { if m != nil { @@ -1786,7 +1821,7 @@ type ContainerConfig struct { // the log (STDOUT and STDERR) on the host. // E.g., // PodSandboxConfig.LogDirectory = `/var/log/pods//` - // ContainerConfig.LogPath = `containerName_Instance#.log` + // ContainerConfig.LogPath = `containerName/Instance#.log` // // WARNING: Log management and how kubelet should interface with the // container logs are under active discussion in @@ -1808,7 +1843,7 @@ type ContainerConfig struct { func (m *ContainerConfig) Reset() { *m = ContainerConfig{} } func (*ContainerConfig) ProtoMessage() {} -func (*ContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{39} } +func (*ContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{40} } func (m *ContainerConfig) GetMetadata() *ContainerMetadata { if m != nil { @@ -1936,7 +1971,7 @@ type CreateContainerRequest struct { func (m *CreateContainerRequest) Reset() { *m = CreateContainerRequest{} } func (*CreateContainerRequest) ProtoMessage() {} -func (*CreateContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{40} } +func (*CreateContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{41} } func (m *CreateContainerRequest) GetPodSandboxId() string { if m != nil { @@ -1966,7 +2001,7 @@ type CreateContainerResponse struct { func (m *CreateContainerResponse) Reset() { *m = CreateContainerResponse{} } func (*CreateContainerResponse) ProtoMessage() {} -func (*CreateContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{41} } +func (*CreateContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{42} } func (m *CreateContainerResponse) GetContainerId() string { if m != nil { @@ -1982,7 +2017,7 @@ type StartContainerRequest struct { func (m *StartContainerRequest) Reset() { *m = StartContainerRequest{} } func (*StartContainerRequest) ProtoMessage() {} -func (*StartContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{42} } +func (*StartContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{43} } func (m *StartContainerRequest) GetContainerId() string { if m != nil { @@ -1996,7 +2031,7 @@ type StartContainerResponse struct { func (m *StartContainerResponse) Reset() { *m = StartContainerResponse{} } func (*StartContainerResponse) ProtoMessage() {} -func (*StartContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{43} } +func (*StartContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{44} } type StopContainerRequest struct { // ID of the container to stop. @@ -2008,7 +2043,7 @@ type StopContainerRequest struct { func (m *StopContainerRequest) Reset() { *m = StopContainerRequest{} } func (*StopContainerRequest) ProtoMessage() {} -func (*StopContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{44} } +func (*StopContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{45} } func (m *StopContainerRequest) GetContainerId() string { if m != nil { @@ -2029,7 +2064,7 @@ type StopContainerResponse struct { func (m *StopContainerResponse) Reset() { *m = StopContainerResponse{} } func (*StopContainerResponse) ProtoMessage() {} -func (*StopContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{45} } +func (*StopContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{46} } type RemoveContainerRequest struct { // ID of the container to remove. @@ -2038,7 +2073,7 @@ type RemoveContainerRequest struct { func (m *RemoveContainerRequest) Reset() { *m = RemoveContainerRequest{} } func (*RemoveContainerRequest) ProtoMessage() {} -func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{46} } +func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{47} } func (m *RemoveContainerRequest) GetContainerId() string { if m != nil { @@ -2052,7 +2087,7 @@ type RemoveContainerResponse struct { func (m *RemoveContainerResponse) Reset() { *m = RemoveContainerResponse{} } func (*RemoveContainerResponse) ProtoMessage() {} -func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{47} } +func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{48} } // ContainerStateValue is the wrapper of ContainerState. type ContainerStateValue struct { @@ -2062,7 +2097,7 @@ type ContainerStateValue struct { func (m *ContainerStateValue) Reset() { *m = ContainerStateValue{} } func (*ContainerStateValue) ProtoMessage() {} -func (*ContainerStateValue) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{48} } +func (*ContainerStateValue) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{49} } func (m *ContainerStateValue) GetState() ContainerState { if m != nil { @@ -2088,7 +2123,7 @@ type ContainerFilter struct { func (m *ContainerFilter) Reset() { *m = ContainerFilter{} } func (*ContainerFilter) ProtoMessage() {} -func (*ContainerFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{49} } +func (*ContainerFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{50} } func (m *ContainerFilter) GetId() string { if m != nil { @@ -2124,7 +2159,7 @@ type ListContainersRequest struct { func (m *ListContainersRequest) Reset() { *m = ListContainersRequest{} } func (*ListContainersRequest) ProtoMessage() {} -func (*ListContainersRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{50} } +func (*ListContainersRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{51} } func (m *ListContainersRequest) GetFilter() *ContainerFilter { if m != nil { @@ -2163,7 +2198,7 @@ type Container struct { func (m *Container) Reset() { *m = Container{} } func (*Container) ProtoMessage() {} -func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{51} } +func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{52} } func (m *Container) GetId() string { if m != nil { @@ -2235,7 +2270,7 @@ type ListContainersResponse struct { func (m *ListContainersResponse) Reset() { *m = ListContainersResponse{} } func (*ListContainersResponse) ProtoMessage() {} -func (*ListContainersResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{52} } +func (*ListContainersResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{53} } func (m *ListContainersResponse) GetContainers() []*Container { if m != nil { @@ -2253,7 +2288,7 @@ type ContainerStatusRequest struct { func (m *ContainerStatusRequest) Reset() { *m = ContainerStatusRequest{} } func (*ContainerStatusRequest) ProtoMessage() {} -func (*ContainerStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{53} } +func (*ContainerStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{54} } func (m *ContainerStatusRequest) GetContainerId() string { if m != nil { @@ -2310,7 +2345,7 @@ type ContainerStatus struct { func (m *ContainerStatus) Reset() { *m = ContainerStatus{} } func (*ContainerStatus) ProtoMessage() {} -func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{54} } +func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{55} } func (m *ContainerStatus) GetId() string { if m != nil { @@ -2429,7 +2464,7 @@ type ContainerStatusResponse struct { func (m *ContainerStatusResponse) Reset() { *m = ContainerStatusResponse{} } func (*ContainerStatusResponse) ProtoMessage() {} -func (*ContainerStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{55} } +func (*ContainerStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{56} } func (m *ContainerStatusResponse) GetStatus() *ContainerStatus { if m != nil { @@ -2455,7 +2490,7 @@ type UpdateContainerResourcesRequest struct { func (m *UpdateContainerResourcesRequest) Reset() { *m = UpdateContainerResourcesRequest{} } func (*UpdateContainerResourcesRequest) ProtoMessage() {} func (*UpdateContainerResourcesRequest) Descriptor() ([]byte, []int) { - return fileDescriptorApi, []int{56} + return fileDescriptorApi, []int{57} } func (m *UpdateContainerResourcesRequest) GetContainerId() string { @@ -2478,7 +2513,7 @@ type UpdateContainerResourcesResponse struct { func (m *UpdateContainerResourcesResponse) Reset() { *m = UpdateContainerResourcesResponse{} } func (*UpdateContainerResourcesResponse) ProtoMessage() {} func (*UpdateContainerResourcesResponse) Descriptor() ([]byte, []int) { - return fileDescriptorApi, []int{57} + return fileDescriptorApi, []int{58} } type ExecSyncRequest struct { @@ -2492,7 +2527,7 @@ type ExecSyncRequest struct { func (m *ExecSyncRequest) Reset() { *m = ExecSyncRequest{} } func (*ExecSyncRequest) ProtoMessage() {} -func (*ExecSyncRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{58} } +func (*ExecSyncRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{59} } func (m *ExecSyncRequest) GetContainerId() string { if m != nil { @@ -2526,7 +2561,7 @@ type ExecSyncResponse struct { func (m *ExecSyncResponse) Reset() { *m = ExecSyncResponse{} } func (*ExecSyncResponse) ProtoMessage() {} -func (*ExecSyncResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{59} } +func (*ExecSyncResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{60} } func (m *ExecSyncResponse) GetStdout() []byte { if m != nil { @@ -2572,7 +2607,7 @@ type ExecRequest struct { func (m *ExecRequest) Reset() { *m = ExecRequest{} } func (*ExecRequest) ProtoMessage() {} -func (*ExecRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{60} } +func (*ExecRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{61} } func (m *ExecRequest) GetContainerId() string { if m != nil { @@ -2623,7 +2658,7 @@ type ExecResponse struct { func (m *ExecResponse) Reset() { *m = ExecResponse{} } func (*ExecResponse) ProtoMessage() {} -func (*ExecResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{61} } +func (*ExecResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{62} } func (m *ExecResponse) GetUrl() string { if m != nil { @@ -2654,7 +2689,7 @@ type AttachRequest struct { func (m *AttachRequest) Reset() { *m = AttachRequest{} } func (*AttachRequest) ProtoMessage() {} -func (*AttachRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{62} } +func (*AttachRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{63} } func (m *AttachRequest) GetContainerId() string { if m != nil { @@ -2698,7 +2733,7 @@ type AttachResponse struct { func (m *AttachResponse) Reset() { *m = AttachResponse{} } func (*AttachResponse) ProtoMessage() {} -func (*AttachResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{63} } +func (*AttachResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{64} } func (m *AttachResponse) GetUrl() string { if m != nil { @@ -2716,7 +2751,7 @@ type PortForwardRequest struct { func (m *PortForwardRequest) Reset() { *m = PortForwardRequest{} } func (*PortForwardRequest) ProtoMessage() {} -func (*PortForwardRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{64} } +func (*PortForwardRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{65} } func (m *PortForwardRequest) GetPodSandboxId() string { if m != nil { @@ -2739,7 +2774,7 @@ type PortForwardResponse struct { func (m *PortForwardResponse) Reset() { *m = PortForwardResponse{} } func (*PortForwardResponse) ProtoMessage() {} -func (*PortForwardResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{65} } +func (*PortForwardResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{66} } func (m *PortForwardResponse) GetUrl() string { if m != nil { @@ -2755,7 +2790,7 @@ type ImageFilter struct { func (m *ImageFilter) Reset() { *m = ImageFilter{} } func (*ImageFilter) ProtoMessage() {} -func (*ImageFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{66} } +func (*ImageFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{67} } func (m *ImageFilter) GetImage() *ImageSpec { if m != nil { @@ -2771,7 +2806,7 @@ type ListImagesRequest struct { func (m *ListImagesRequest) Reset() { *m = ListImagesRequest{} } func (*ListImagesRequest) ProtoMessage() {} -func (*ListImagesRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{67} } +func (*ListImagesRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{68} } func (m *ListImagesRequest) GetFilter() *ImageFilter { if m != nil { @@ -2801,7 +2836,7 @@ type Image struct { func (m *Image) Reset() { *m = Image{} } func (*Image) ProtoMessage() {} -func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{68} } +func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{69} } func (m *Image) GetId() string { if m != nil { @@ -2852,7 +2887,7 @@ type ListImagesResponse struct { func (m *ListImagesResponse) Reset() { *m = ListImagesResponse{} } func (*ListImagesResponse) ProtoMessage() {} -func (*ListImagesResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{69} } +func (*ListImagesResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{70} } func (m *ListImagesResponse) GetImages() []*Image { if m != nil { @@ -2870,7 +2905,7 @@ type ImageStatusRequest struct { func (m *ImageStatusRequest) Reset() { *m = ImageStatusRequest{} } func (*ImageStatusRequest) ProtoMessage() {} -func (*ImageStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{70} } +func (*ImageStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{71} } func (m *ImageStatusRequest) GetImage() *ImageSpec { if m != nil { @@ -2898,7 +2933,7 @@ type ImageStatusResponse struct { func (m *ImageStatusResponse) Reset() { *m = ImageStatusResponse{} } func (*ImageStatusResponse) ProtoMessage() {} -func (*ImageStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{71} } +func (*ImageStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{72} } func (m *ImageStatusResponse) GetImage() *Image { if m != nil { @@ -2929,7 +2964,7 @@ type AuthConfig struct { func (m *AuthConfig) Reset() { *m = AuthConfig{} } func (*AuthConfig) ProtoMessage() {} -func (*AuthConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{72} } +func (*AuthConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{73} } func (m *AuthConfig) GetUsername() string { if m != nil { @@ -2984,7 +3019,7 @@ type PullImageRequest struct { func (m *PullImageRequest) Reset() { *m = PullImageRequest{} } func (*PullImageRequest) ProtoMessage() {} -func (*PullImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{73} } +func (*PullImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{74} } func (m *PullImageRequest) GetImage() *ImageSpec { if m != nil { @@ -3015,7 +3050,7 @@ type PullImageResponse struct { func (m *PullImageResponse) Reset() { *m = PullImageResponse{} } func (*PullImageResponse) ProtoMessage() {} -func (*PullImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{74} } +func (*PullImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{75} } func (m *PullImageResponse) GetImageRef() string { if m != nil { @@ -3031,7 +3066,7 @@ type RemoveImageRequest struct { func (m *RemoveImageRequest) Reset() { *m = RemoveImageRequest{} } func (*RemoveImageRequest) ProtoMessage() {} -func (*RemoveImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{75} } +func (*RemoveImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{76} } func (m *RemoveImageRequest) GetImage() *ImageSpec { if m != nil { @@ -3045,16 +3080,17 @@ type RemoveImageResponse struct { func (m *RemoveImageResponse) Reset() { *m = RemoveImageResponse{} } func (*RemoveImageResponse) ProtoMessage() {} -func (*RemoveImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{76} } +func (*RemoveImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{77} } type NetworkConfig struct { - // CIDR to use for pod IP addresses. + // CIDR to use for pod IP addresses. If the CIDR is empty, runtimes + // should omit it. PodCidr string `protobuf:"bytes,1,opt,name=pod_cidr,json=podCidr,proto3" json:"pod_cidr,omitempty"` } func (m *NetworkConfig) Reset() { *m = NetworkConfig{} } func (*NetworkConfig) ProtoMessage() {} -func (*NetworkConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{77} } +func (*NetworkConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{78} } func (m *NetworkConfig) GetPodCidr() string { if m != nil { @@ -3069,7 +3105,7 @@ type RuntimeConfig struct { func (m *RuntimeConfig) Reset() { *m = RuntimeConfig{} } func (*RuntimeConfig) ProtoMessage() {} -func (*RuntimeConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{78} } +func (*RuntimeConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{79} } func (m *RuntimeConfig) GetNetworkConfig() *NetworkConfig { if m != nil { @@ -3084,7 +3120,7 @@ type UpdateRuntimeConfigRequest struct { func (m *UpdateRuntimeConfigRequest) Reset() { *m = UpdateRuntimeConfigRequest{} } func (*UpdateRuntimeConfigRequest) ProtoMessage() {} -func (*UpdateRuntimeConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{79} } +func (*UpdateRuntimeConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{80} } func (m *UpdateRuntimeConfigRequest) GetRuntimeConfig() *RuntimeConfig { if m != nil { @@ -3098,7 +3134,7 @@ type UpdateRuntimeConfigResponse struct { func (m *UpdateRuntimeConfigResponse) Reset() { *m = UpdateRuntimeConfigResponse{} } func (*UpdateRuntimeConfigResponse) ProtoMessage() {} -func (*UpdateRuntimeConfigResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{80} } +func (*UpdateRuntimeConfigResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{81} } // RuntimeCondition contains condition information for the runtime. // There are 2 kinds of runtime conditions: @@ -3126,7 +3162,7 @@ type RuntimeCondition struct { func (m *RuntimeCondition) Reset() { *m = RuntimeCondition{} } func (*RuntimeCondition) ProtoMessage() {} -func (*RuntimeCondition) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{81} } +func (*RuntimeCondition) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{82} } func (m *RuntimeCondition) GetType() string { if m != nil { @@ -3164,7 +3200,7 @@ type RuntimeStatus struct { func (m *RuntimeStatus) Reset() { *m = RuntimeStatus{} } func (*RuntimeStatus) ProtoMessage() {} -func (*RuntimeStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{82} } +func (*RuntimeStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{83} } func (m *RuntimeStatus) GetConditions() []*RuntimeCondition { if m != nil { @@ -3180,7 +3216,7 @@ type StatusRequest struct { func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (*StatusRequest) ProtoMessage() {} -func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{83} } +func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{84} } func (m *StatusRequest) GetVerbose() bool { if m != nil { @@ -3201,7 +3237,7 @@ type StatusResponse struct { func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (*StatusResponse) ProtoMessage() {} -func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{84} } +func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{85} } func (m *StatusResponse) GetStatus() *RuntimeStatus { if m != nil { @@ -3222,7 +3258,7 @@ type ImageFsInfoRequest struct { func (m *ImageFsInfoRequest) Reset() { *m = ImageFsInfoRequest{} } func (*ImageFsInfoRequest) ProtoMessage() {} -func (*ImageFsInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{85} } +func (*ImageFsInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{86} } // UInt64Value is the wrapper of uint64. type UInt64Value struct { @@ -3232,7 +3268,7 @@ type UInt64Value struct { func (m *UInt64Value) Reset() { *m = UInt64Value{} } func (*UInt64Value) ProtoMessage() {} -func (*UInt64Value) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{86} } +func (*UInt64Value) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{87} } func (m *UInt64Value) GetValue() uint64 { if m != nil { @@ -3249,7 +3285,7 @@ type FilesystemIdentifier struct { func (m *FilesystemIdentifier) Reset() { *m = FilesystemIdentifier{} } func (*FilesystemIdentifier) ProtoMessage() {} -func (*FilesystemIdentifier) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{87} } +func (*FilesystemIdentifier) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{88} } func (m *FilesystemIdentifier) GetMountpoint() string { if m != nil { @@ -3276,7 +3312,7 @@ type FilesystemUsage struct { func (m *FilesystemUsage) Reset() { *m = FilesystemUsage{} } func (*FilesystemUsage) ProtoMessage() {} -func (*FilesystemUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{88} } +func (*FilesystemUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{89} } func (m *FilesystemUsage) GetTimestamp() int64 { if m != nil { @@ -3313,7 +3349,7 @@ type ImageFsInfoResponse struct { func (m *ImageFsInfoResponse) Reset() { *m = ImageFsInfoResponse{} } func (*ImageFsInfoResponse) ProtoMessage() {} -func (*ImageFsInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{89} } +func (*ImageFsInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{90} } func (m *ImageFsInfoResponse) GetImageFilesystems() []*FilesystemUsage { if m != nil { @@ -3329,7 +3365,7 @@ type ContainerStatsRequest struct { func (m *ContainerStatsRequest) Reset() { *m = ContainerStatsRequest{} } func (*ContainerStatsRequest) ProtoMessage() {} -func (*ContainerStatsRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{90} } +func (*ContainerStatsRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{91} } func (m *ContainerStatsRequest) GetContainerId() string { if m != nil { @@ -3345,7 +3381,7 @@ type ContainerStatsResponse struct { func (m *ContainerStatsResponse) Reset() { *m = ContainerStatsResponse{} } func (*ContainerStatsResponse) ProtoMessage() {} -func (*ContainerStatsResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{91} } +func (*ContainerStatsResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{92} } func (m *ContainerStatsResponse) GetStats() *ContainerStats { if m != nil { @@ -3361,7 +3397,7 @@ type ListContainerStatsRequest struct { func (m *ListContainerStatsRequest) Reset() { *m = ListContainerStatsRequest{} } func (*ListContainerStatsRequest) ProtoMessage() {} -func (*ListContainerStatsRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{92} } +func (*ListContainerStatsRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{93} } func (m *ListContainerStatsRequest) GetFilter() *ContainerStatsFilter { if m != nil { @@ -3385,7 +3421,7 @@ type ContainerStatsFilter struct { func (m *ContainerStatsFilter) Reset() { *m = ContainerStatsFilter{} } func (*ContainerStatsFilter) ProtoMessage() {} -func (*ContainerStatsFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{93} } +func (*ContainerStatsFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{94} } func (m *ContainerStatsFilter) GetId() string { if m != nil { @@ -3415,7 +3451,7 @@ type ListContainerStatsResponse struct { func (m *ListContainerStatsResponse) Reset() { *m = ListContainerStatsResponse{} } func (*ListContainerStatsResponse) ProtoMessage() {} -func (*ListContainerStatsResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{94} } +func (*ListContainerStatsResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{95} } func (m *ListContainerStatsResponse) GetStats() []*ContainerStats { if m != nil { @@ -3441,7 +3477,7 @@ type ContainerAttributes struct { func (m *ContainerAttributes) Reset() { *m = ContainerAttributes{} } func (*ContainerAttributes) ProtoMessage() {} -func (*ContainerAttributes) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{95} } +func (*ContainerAttributes) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{96} } func (m *ContainerAttributes) GetId() string { if m != nil { @@ -3485,7 +3521,7 @@ type ContainerStats struct { func (m *ContainerStats) Reset() { *m = ContainerStats{} } func (*ContainerStats) ProtoMessage() {} -func (*ContainerStats) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{96} } +func (*ContainerStats) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{97} } func (m *ContainerStats) GetAttributes() *ContainerAttributes { if m != nil { @@ -3525,7 +3561,7 @@ type CpuUsage struct { func (m *CpuUsage) Reset() { *m = CpuUsage{} } func (*CpuUsage) ProtoMessage() {} -func (*CpuUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{97} } +func (*CpuUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{98} } func (m *CpuUsage) GetTimestamp() int64 { if m != nil { @@ -3551,7 +3587,7 @@ type MemoryUsage struct { func (m *MemoryUsage) Reset() { *m = MemoryUsage{} } func (*MemoryUsage) ProtoMessage() {} -func (*MemoryUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{98} } +func (*MemoryUsage) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{99} } func (m *MemoryUsage) GetTimestamp() int64 { if m != nil { @@ -3574,7 +3610,7 @@ type ReopenContainerLogRequest struct { func (m *ReopenContainerLogRequest) Reset() { *m = ReopenContainerLogRequest{} } func (*ReopenContainerLogRequest) ProtoMessage() {} -func (*ReopenContainerLogRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{99} } +func (*ReopenContainerLogRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{100} } func (m *ReopenContainerLogRequest) GetContainerId() string { if m != nil { @@ -3588,7 +3624,7 @@ type ReopenContainerLogResponse struct { func (m *ReopenContainerLogResponse) Reset() { *m = ReopenContainerLogResponse{} } func (*ReopenContainerLogResponse) ProtoMessage() {} -func (*ReopenContainerLogResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{100} } +func (*ReopenContainerLogResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{101} } func init() { proto.RegisterType((*VersionRequest)(nil), "runtime.v1alpha2.VersionRequest") @@ -3626,6 +3662,7 @@ func init() { proto.RegisterType((*Capability)(nil), "runtime.v1alpha2.Capability") proto.RegisterType((*LinuxContainerSecurityContext)(nil), "runtime.v1alpha2.LinuxContainerSecurityContext") proto.RegisterType((*LinuxContainerConfig)(nil), "runtime.v1alpha2.LinuxContainerConfig") + proto.RegisterType((*WindowsContainerSecurityContext)(nil), "runtime.v1alpha2.WindowsContainerSecurityContext") proto.RegisterType((*WindowsContainerConfig)(nil), "runtime.v1alpha2.WindowsContainerConfig") proto.RegisterType((*WindowsContainerResources)(nil), "runtime.v1alpha2.WindowsContainerResources") proto.RegisterType((*ContainerMetadata)(nil), "runtime.v1alpha2.ContainerMetadata") @@ -6325,6 +6362,30 @@ func (m *LinuxContainerConfig) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *WindowsContainerSecurityContext) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WindowsContainerSecurityContext) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.RunAsUsername) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.RunAsUsername))) + i += copy(dAtA[i:], m.RunAsUsername) + } + return i, nil +} + func (m *WindowsContainerConfig) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -6350,6 +6411,16 @@ func (m *WindowsContainerConfig) MarshalTo(dAtA []byte) (int, error) { } i += n30 } + if m.SecurityContext != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(m.SecurityContext.Size())) + n31, err := m.SecurityContext.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n31 + } return i, nil } @@ -6475,21 +6546,21 @@ func (m *ContainerConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Metadata.Size())) - n31, err := m.Metadata.MarshalTo(dAtA[i:]) + n32, err := m.Metadata.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n31 + i += n32 } if m.Image != nil { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n32, err := m.Image.MarshalTo(dAtA[i:]) + n33, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n32 + i += n33 } if len(m.Command) > 0 { for _, s := range m.Command { @@ -6637,11 +6708,11 @@ func (m *ContainerConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x7a i++ i = encodeVarintApi(dAtA, i, uint64(m.Linux.Size())) - n33, err := m.Linux.MarshalTo(dAtA[i:]) + n34, err := m.Linux.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n33 + i += n34 } if m.Windows != nil { dAtA[i] = 0x82 @@ -6649,11 +6720,11 @@ func (m *ContainerConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintApi(dAtA, i, uint64(m.Windows.Size())) - n34, err := m.Windows.MarshalTo(dAtA[i:]) + n35, err := m.Windows.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n34 + i += n35 } return i, nil } @@ -6683,21 +6754,21 @@ func (m *CreateContainerRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Config.Size())) - n35, err := m.Config.MarshalTo(dAtA[i:]) + n36, err := m.Config.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n36 } if m.SandboxConfig != nil { dAtA[i] = 0x1a i++ i = encodeVarintApi(dAtA, i, uint64(m.SandboxConfig.Size())) - n36, err := m.SandboxConfig.MarshalTo(dAtA[i:]) + n37, err := m.SandboxConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n37 } return i, nil } @@ -6905,11 +6976,11 @@ func (m *ContainerFilter) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.State.Size())) - n37, err := m.State.MarshalTo(dAtA[i:]) + n38, err := m.State.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n38 } if len(m.PodSandboxId) > 0 { dAtA[i] = 0x1a @@ -6956,11 +7027,11 @@ func (m *ListContainersRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Filter.Size())) - n38, err := m.Filter.MarshalTo(dAtA[i:]) + n39, err := m.Filter.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n39 } return i, nil } @@ -6996,21 +7067,21 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintApi(dAtA, i, uint64(m.Metadata.Size())) - n39, err := m.Metadata.MarshalTo(dAtA[i:]) + n40, err := m.Metadata.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n40 } if m.Image != nil { dAtA[i] = 0x22 i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n40, err := m.Image.MarshalTo(dAtA[i:]) + n41, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n41 } if len(m.ImageRef) > 0 { dAtA[i] = 0x2a @@ -7154,11 +7225,11 @@ func (m *ContainerStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Metadata.Size())) - n41, err := m.Metadata.MarshalTo(dAtA[i:]) + n42, err := m.Metadata.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n41 + i += n42 } if m.State != 0 { dAtA[i] = 0x18 @@ -7189,11 +7260,11 @@ func (m *ContainerStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x42 i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n42, err := m.Image.MarshalTo(dAtA[i:]) + n43, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n42 + i += n43 } if len(m.ImageRef) > 0 { dAtA[i] = 0x4a @@ -7287,11 +7358,11 @@ func (m *ContainerStatusResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Status.Size())) - n43, err := m.Status.MarshalTo(dAtA[i:]) + n44, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n43 + i += n44 } if len(m.Info) > 0 { for k := range m.Info { @@ -7338,11 +7409,11 @@ func (m *UpdateContainerResourcesRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Linux.Size())) - n44, err := m.Linux.MarshalTo(dAtA[i:]) + n45, err := m.Linux.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n44 + i += n45 } return i, nil } @@ -7657,22 +7728,22 @@ func (m *PortForwardRequest) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], m.PodSandboxId) } if len(m.Port) > 0 { - dAtA46 := make([]byte, len(m.Port)*10) - var j45 int + dAtA47 := make([]byte, len(m.Port)*10) + var j46 int for _, num1 := range m.Port { num := uint64(num1) for num >= 1<<7 { - dAtA46[j45] = uint8(uint64(num)&0x7f | 0x80) + dAtA47[j46] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j45++ + j46++ } - dAtA46[j45] = uint8(num) - j45++ + dAtA47[j46] = uint8(num) + j46++ } dAtA[i] = 0x12 i++ - i = encodeVarintApi(dAtA, i, uint64(j45)) - i += copy(dAtA[i:], dAtA46[:j45]) + i = encodeVarintApi(dAtA, i, uint64(j46)) + i += copy(dAtA[i:], dAtA47[:j46]) } return i, nil } @@ -7720,11 +7791,11 @@ func (m *ImageFilter) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n47, err := m.Image.MarshalTo(dAtA[i:]) + n48, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n47 + i += n48 } return i, nil } @@ -7748,11 +7819,11 @@ func (m *ListImagesRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Filter.Size())) - n48, err := m.Filter.MarshalTo(dAtA[i:]) + n49, err := m.Filter.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n48 + i += n49 } return i, nil } @@ -7817,11 +7888,11 @@ func (m *Image) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintApi(dAtA, i, uint64(m.Uid.Size())) - n49, err := m.Uid.MarshalTo(dAtA[i:]) + n50, err := m.Uid.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n49 + i += n50 } if len(m.Username) > 0 { dAtA[i] = 0x32 @@ -7881,11 +7952,11 @@ func (m *ImageStatusRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n50, err := m.Image.MarshalTo(dAtA[i:]) + n51, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n50 + i += n51 } if m.Verbose { dAtA[i] = 0x10 @@ -7919,11 +7990,11 @@ func (m *ImageStatusResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n51, err := m.Image.MarshalTo(dAtA[i:]) + n52, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n51 + i += n52 } if len(m.Info) > 0 { for k := range m.Info { @@ -8018,31 +8089,31 @@ func (m *PullImageRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n52, err := m.Image.MarshalTo(dAtA[i:]) + n53, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n52 + i += n53 } if m.Auth != nil { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Auth.Size())) - n53, err := m.Auth.MarshalTo(dAtA[i:]) + n54, err := m.Auth.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n53 + i += n54 } if m.SandboxConfig != nil { dAtA[i] = 0x1a i++ i = encodeVarintApi(dAtA, i, uint64(m.SandboxConfig.Size())) - n54, err := m.SandboxConfig.MarshalTo(dAtA[i:]) + n55, err := m.SandboxConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n54 + i += n55 } return i, nil } @@ -8090,11 +8161,11 @@ func (m *RemoveImageRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Image.Size())) - n55, err := m.Image.MarshalTo(dAtA[i:]) + n56, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n55 + i += n56 } return i, nil } @@ -8160,11 +8231,11 @@ func (m *RuntimeConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.NetworkConfig.Size())) - n56, err := m.NetworkConfig.MarshalTo(dAtA[i:]) + n57, err := m.NetworkConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n56 + i += n57 } return i, nil } @@ -8188,11 +8259,11 @@ func (m *UpdateRuntimeConfigRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.RuntimeConfig.Size())) - n57, err := m.RuntimeConfig.MarshalTo(dAtA[i:]) + n58, err := m.RuntimeConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n57 + i += n58 } return i, nil } @@ -8338,11 +8409,11 @@ func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Status.Size())) - n58, err := m.Status.MarshalTo(dAtA[i:]) + n59, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n58 + i += n59 } if len(m.Info) > 0 { for k := range m.Info { @@ -8453,31 +8524,31 @@ func (m *FilesystemUsage) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.FsId.Size())) - n59, err := m.FsId.MarshalTo(dAtA[i:]) + n60, err := m.FsId.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n59 + i += n60 } if m.UsedBytes != nil { dAtA[i] = 0x1a i++ i = encodeVarintApi(dAtA, i, uint64(m.UsedBytes.Size())) - n60, err := m.UsedBytes.MarshalTo(dAtA[i:]) + n61, err := m.UsedBytes.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n60 + i += n61 } if m.InodesUsed != nil { dAtA[i] = 0x22 i++ i = encodeVarintApi(dAtA, i, uint64(m.InodesUsed.Size())) - n61, err := m.InodesUsed.MarshalTo(dAtA[i:]) + n62, err := m.InodesUsed.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n61 + i += n62 } return i, nil } @@ -8555,11 +8626,11 @@ func (m *ContainerStatsResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Stats.Size())) - n62, err := m.Stats.MarshalTo(dAtA[i:]) + n63, err := m.Stats.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n62 + i += n63 } return i, nil } @@ -8583,11 +8654,11 @@ func (m *ListContainerStatsRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Filter.Size())) - n63, err := m.Filter.MarshalTo(dAtA[i:]) + n64, err := m.Filter.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n63 + i += n64 } return i, nil } @@ -8694,11 +8765,11 @@ func (m *ContainerAttributes) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Metadata.Size())) - n64, err := m.Metadata.MarshalTo(dAtA[i:]) + n65, err := m.Metadata.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n64 + i += n65 } if len(m.Labels) > 0 { for k := range m.Labels { @@ -8756,41 +8827,41 @@ func (m *ContainerStats) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintApi(dAtA, i, uint64(m.Attributes.Size())) - n65, err := m.Attributes.MarshalTo(dAtA[i:]) + n66, err := m.Attributes.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n65 + i += n66 } if m.Cpu != nil { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.Cpu.Size())) - n66, err := m.Cpu.MarshalTo(dAtA[i:]) + n67, err := m.Cpu.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n66 + i += n67 } if m.Memory != nil { dAtA[i] = 0x1a i++ i = encodeVarintApi(dAtA, i, uint64(m.Memory.Size())) - n67, err := m.Memory.MarshalTo(dAtA[i:]) + n68, err := m.Memory.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n67 + i += n68 } if m.WritableLayer != nil { dAtA[i] = 0x22 i++ i = encodeVarintApi(dAtA, i, uint64(m.WritableLayer.Size())) - n68, err := m.WritableLayer.MarshalTo(dAtA[i:]) + n69, err := m.WritableLayer.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n68 + i += n69 } return i, nil } @@ -8819,11 +8890,11 @@ func (m *CpuUsage) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.UsageCoreNanoSeconds.Size())) - n69, err := m.UsageCoreNanoSeconds.MarshalTo(dAtA[i:]) + n70, err := m.UsageCoreNanoSeconds.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n69 + i += n70 } return i, nil } @@ -8852,11 +8923,11 @@ func (m *MemoryUsage) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintApi(dAtA, i, uint64(m.WorkingSetBytes.Size())) - n70, err := m.WorkingSetBytes.MarshalTo(dAtA[i:]) + n71, err := m.WorkingSetBytes.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n70 + i += n71 } return i, nil } @@ -9589,6 +9660,16 @@ func (m *LinuxContainerConfig) Size() (n int) { return n } +func (m *WindowsContainerSecurityContext) Size() (n int) { + var l int + _ = l + l = len(m.RunAsUsername) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + func (m *WindowsContainerConfig) Size() (n int) { var l int _ = l @@ -9596,6 +9677,10 @@ func (m *WindowsContainerConfig) Size() (n int) { l = m.Resources.Size() n += 1 + l + sovApi(uint64(l)) } + if m.SecurityContext != nil { + l = m.SecurityContext.Size() + n += 1 + l + sovApi(uint64(l)) + } return n } @@ -11177,12 +11262,23 @@ func (this *LinuxContainerConfig) String() string { }, "") return s } +func (this *WindowsContainerSecurityContext) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&WindowsContainerSecurityContext{`, + `RunAsUsername:` + fmt.Sprintf("%v", this.RunAsUsername) + `,`, + `}`, + }, "") + return s +} func (this *WindowsContainerConfig) String() string { if this == nil { return "nil" } s := strings.Join([]string{`&WindowsContainerConfig{`, `Resources:` + strings.Replace(fmt.Sprintf("%v", this.Resources), "WindowsContainerResources", "WindowsContainerResources", 1) + `,`, + `SecurityContext:` + strings.Replace(fmt.Sprintf("%v", this.SecurityContext), "WindowsContainerSecurityContext", "WindowsContainerSecurityContext", 1) + `,`, `}`, }, "") return s @@ -17550,6 +17646,85 @@ func (m *LinuxContainerConfig) Unmarshal(dAtA []byte) error { } return nil } +func (m *WindowsContainerSecurityContext) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WindowsContainerSecurityContext: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WindowsContainerSecurityContext: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RunAsUsername", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RunAsUsername = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *WindowsContainerConfig) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -17612,6 +17787,39 @@ func (m *WindowsContainerConfig) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecurityContext", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SecurityContext == nil { + m.SecurityContext = &WindowsContainerSecurityContext{} + } + if err := m.SecurityContext.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipApi(dAtA[iNdEx:]) @@ -26450,294 +26658,296 @@ var ( func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } var fileDescriptorApi = []byte{ - // 4623 bytes of a gzipped FileDescriptorProto + // 4649 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5c, 0xcd, 0x6f, 0x1b, 0x49, - 0x76, 0x17, 0x49, 0x7d, 0x90, 0x8f, 0xa2, 0x44, 0x95, 0x65, 0x8b, 0xa6, 0x6d, 0x8d, 0xd5, 0x1e, + 0x76, 0x57, 0x93, 0xfa, 0x20, 0x1f, 0x45, 0x89, 0x2a, 0xcb, 0x16, 0x4d, 0xdb, 0xb2, 0xd5, 0x1e, 0x7f, 0xce, 0x58, 0x1e, 0x6b, 0x76, 0x3d, 0xb1, 0x3d, 0x6b, 0x9b, 0x96, 0x64, 0x9b, 0x59, 0x9b, - 0x52, 0x9a, 0xd2, 0x7c, 0xec, 0x2c, 0xd0, 0xdb, 0x62, 0x97, 0xa8, 0x5e, 0x93, 0x5d, 0x3d, 0xdd, + 0x52, 0x9a, 0xd2, 0x7c, 0xec, 0x0c, 0xd0, 0xdb, 0x62, 0x97, 0xa8, 0x5e, 0x93, 0x5d, 0x3d, 0xdd, 0x4d, 0xdb, 0xca, 0x21, 0x58, 0x20, 0xc8, 0x1e, 0x02, 0x04, 0xc8, 0x79, 0x8f, 0x9b, 0x43, 0x0e, - 0xb9, 0x05, 0x08, 0x72, 0xc8, 0x29, 0xc1, 0x1e, 0xf6, 0x12, 0x20, 0xa7, 0x45, 0x3e, 0x2e, 0x99, - 0x09, 0x72, 0xc9, 0x21, 0xc8, 0x1f, 0x90, 0x43, 0x50, 0x5f, 0xfd, 0xdd, 0xfc, 0xd0, 0x78, 0x77, - 0x26, 0x27, 0x75, 0xbd, 0x7a, 0xef, 0xd5, 0xab, 0xaa, 0x57, 0xaf, 0x5e, 0xfd, 0xaa, 0x28, 0x28, - 0xe9, 0xb6, 0xb9, 0x6e, 0x3b, 0xc4, 0x23, 0xa8, 0xea, 0x0c, 0x2c, 0xcf, 0xec, 0xe3, 0xf5, 0x57, - 0xb7, 0xf5, 0x9e, 0x7d, 0xa4, 0x6f, 0xd4, 0x6f, 0x76, 0x4d, 0xef, 0x68, 0x70, 0xb0, 0xde, 0x21, - 0xfd, 0x5b, 0x5d, 0xd2, 0x25, 0xb7, 0x18, 0xe3, 0xc1, 0xe0, 0x90, 0x95, 0x58, 0x81, 0x7d, 0x71, - 0x05, 0xca, 0x0d, 0x58, 0xf8, 0x04, 0x3b, 0xae, 0x49, 0x2c, 0x15, 0x7f, 0x39, 0xc0, 0xae, 0x87, - 0x6a, 0x30, 0xf7, 0x8a, 0x53, 0x6a, 0xb9, 0x8b, 0xb9, 0x6b, 0x25, 0x55, 0x16, 0x95, 0xbf, 0xcc, - 0xc1, 0xa2, 0xcf, 0xec, 0xda, 0xc4, 0x72, 0x71, 0x36, 0x37, 0x5a, 0x83, 0x79, 0x61, 0x9c, 0x66, - 0xe9, 0x7d, 0x5c, 0xcb, 0xb3, 0xea, 0xb2, 0xa0, 0xb5, 0xf4, 0x3e, 0x46, 0x57, 0x61, 0x51, 0xb2, - 0x48, 0x25, 0x05, 0xc6, 0xb5, 0x20, 0xc8, 0xa2, 0x35, 0xb4, 0x0e, 0xa7, 0x24, 0xa3, 0x6e, 0x9b, - 0x3e, 0xf3, 0x34, 0x63, 0x5e, 0x12, 0x55, 0x0d, 0xdb, 0x14, 0xfc, 0xca, 0x17, 0x50, 0xda, 0x6a, - 0xb5, 0x37, 0x89, 0x75, 0x68, 0x76, 0xa9, 0x89, 0x2e, 0x76, 0xa8, 0x4c, 0x2d, 0x77, 0xb1, 0x40, - 0x4d, 0x14, 0x45, 0x54, 0x87, 0xa2, 0x8b, 0x75, 0xa7, 0x73, 0x84, 0xdd, 0x5a, 0x9e, 0x55, 0xf9, - 0x65, 0x2a, 0x45, 0x6c, 0xcf, 0x24, 0x96, 0x5b, 0x2b, 0x70, 0x29, 0x51, 0x54, 0x7e, 0x99, 0x83, - 0xf2, 0x2e, 0x71, 0xbc, 0x17, 0xba, 0x6d, 0x9b, 0x56, 0x17, 0xdd, 0x81, 0x22, 0x1b, 0xcb, 0x0e, - 0xe9, 0xb1, 0x31, 0x58, 0xd8, 0xa8, 0xaf, 0xc7, 0xa7, 0x65, 0x7d, 0x57, 0x70, 0xa8, 0x3e, 0x2f, - 0xba, 0x0c, 0x0b, 0x1d, 0x62, 0x79, 0xba, 0x69, 0x61, 0x47, 0xb3, 0x89, 0xe3, 0xb1, 0x21, 0x9a, - 0x51, 0x2b, 0x3e, 0x95, 0xb6, 0x82, 0xce, 0x41, 0xe9, 0x88, 0xb8, 0x1e, 0xe7, 0x28, 0x30, 0x8e, - 0x22, 0x25, 0xb0, 0xca, 0x15, 0x98, 0x63, 0x95, 0xa6, 0x2d, 0x06, 0x63, 0x96, 0x16, 0x9b, 0xb6, - 0xf2, 0x9b, 0x1c, 0xcc, 0xbc, 0x20, 0x03, 0xcb, 0x8b, 0x35, 0xa3, 0x7b, 0x47, 0x62, 0xa2, 0x42, - 0xcd, 0xe8, 0xde, 0x51, 0xd0, 0x0c, 0xe5, 0xe0, 0x73, 0xc5, 0x9b, 0xa1, 0x95, 0x75, 0x28, 0x3a, - 0x58, 0x37, 0x88, 0xd5, 0x3b, 0x66, 0x26, 0x14, 0x55, 0xbf, 0x4c, 0x27, 0xd1, 0xc5, 0x3d, 0xd3, - 0x1a, 0xbc, 0xd1, 0x1c, 0xdc, 0xd3, 0x0f, 0x70, 0x8f, 0x99, 0x52, 0x54, 0x17, 0x04, 0x59, 0xe5, - 0x54, 0xb4, 0x05, 0x65, 0xdb, 0x21, 0xb6, 0xde, 0xd5, 0xe9, 0x38, 0xd6, 0x66, 0xd8, 0x50, 0x29, - 0xc9, 0xa1, 0x62, 0x66, 0xef, 0x06, 0x9c, 0x6a, 0x58, 0x4c, 0xf9, 0xeb, 0x1c, 0x2c, 0x52, 0xe7, - 0x71, 0x6d, 0xbd, 0x83, 0x77, 0xd8, 0x94, 0xa0, 0xbb, 0x30, 0x67, 0x61, 0xef, 0x35, 0x71, 0x5e, - 0x8a, 0x09, 0x78, 0x27, 0xa9, 0xd5, 0x97, 0x79, 0x41, 0x0c, 0xac, 0x4a, 0x7e, 0x74, 0x1b, 0x0a, - 0xb6, 0x69, 0xb0, 0x0e, 0x8f, 0x21, 0x46, 0x79, 0xa9, 0x88, 0x69, 0x77, 0xd8, 0x38, 0x8c, 0x23, - 0x62, 0xda, 0x1d, 0x45, 0x01, 0x68, 0x5a, 0xde, 0x9d, 0xef, 0x7d, 0xa2, 0xf7, 0x06, 0x18, 0x2d, - 0xc3, 0xcc, 0x2b, 0xfa, 0xc1, 0x8c, 0x2d, 0xa8, 0xbc, 0xa0, 0x7c, 0x55, 0x80, 0x73, 0xcf, 0xe9, - 0x78, 0xb5, 0x75, 0xcb, 0x38, 0x20, 0x6f, 0xda, 0xb8, 0x33, 0x70, 0x4c, 0xef, 0x78, 0x93, 0x58, - 0x1e, 0x7e, 0xe3, 0xa1, 0x16, 0x2c, 0x59, 0x52, 0xb3, 0x26, 0x5d, 0x93, 0x6a, 0x28, 0x6f, 0xac, - 0x0d, 0x31, 0x82, 0x0f, 0x91, 0x5a, 0xb5, 0xa2, 0x04, 0x17, 0x3d, 0x0b, 0xe6, 0x4d, 0x6a, 0xcb, - 0x33, 0x6d, 0x29, 0x5d, 0x6a, 0x6f, 0x33, 0xcb, 0x84, 0x2e, 0x39, 0xb1, 0x52, 0xd3, 0xc7, 0x40, - 0x57, 0xb5, 0xa6, 0xbb, 0xda, 0xc0, 0xc5, 0x0e, 0x1b, 0x98, 0xf2, 0xc6, 0xf9, 0xa4, 0x96, 0x60, - 0x08, 0xd4, 0x92, 0x33, 0xb0, 0x1a, 0xee, 0xbe, 0x8b, 0x1d, 0x16, 0x04, 0x84, 0x2f, 0x69, 0x0e, - 0x21, 0xde, 0xa1, 0x2b, 0xfd, 0x47, 0x92, 0x55, 0x46, 0x45, 0xb7, 0xe0, 0x94, 0x3b, 0xb0, 0xed, - 0x1e, 0xee, 0x63, 0xcb, 0xd3, 0x7b, 0x5a, 0xd7, 0x21, 0x03, 0xdb, 0xad, 0xcd, 0x5c, 0x2c, 0x5c, - 0x2b, 0xa8, 0x28, 0x5c, 0xf5, 0x94, 0xd5, 0xa0, 0x55, 0x00, 0xdb, 0x31, 0x5f, 0x99, 0x3d, 0xdc, - 0xc5, 0x46, 0x6d, 0x96, 0x29, 0x0d, 0x51, 0xd0, 0x07, 0xb0, 0xec, 0xe2, 0x4e, 0x87, 0xf4, 0x6d, - 0xcd, 0x76, 0xc8, 0xa1, 0xd9, 0xc3, 0xdc, 0xfb, 0xe7, 0x98, 0xf7, 0x23, 0x51, 0xb7, 0xcb, 0xab, - 0xd8, 0x3a, 0x78, 0xc0, 0x62, 0x1a, 0xed, 0x29, 0x6b, 0xbc, 0x56, 0x1c, 0xa3, 0xab, 0xc0, 0xba, - 0xca, 0x4c, 0x52, 0x7e, 0x99, 0x87, 0xd3, 0x6c, 0x24, 0x77, 0x89, 0x21, 0xa6, 0x59, 0x04, 0xa9, - 0x4b, 0x50, 0xe9, 0x30, 0x9d, 0x9a, 0xad, 0x3b, 0xd8, 0xf2, 0xc4, 0x22, 0x9d, 0xe7, 0xc4, 0x5d, - 0x46, 0x43, 0x9f, 0x41, 0xd5, 0x15, 0x5e, 0xa1, 0x75, 0xb8, 0x5b, 0x88, 0x39, 0xbb, 0x99, 0x34, - 0x61, 0x88, 0x2f, 0xa9, 0x8b, 0x6e, 0xc2, 0xb9, 0xe6, 0xdc, 0x63, 0xb7, 0xe3, 0xf5, 0x78, 0xb4, - 0x2b, 0x6f, 0x7c, 0x2f, 0x43, 0x61, 0xdc, 0xf0, 0xf5, 0x36, 0x17, 0xdb, 0xb6, 0x3c, 0xe7, 0x58, - 0x95, 0x4a, 0xea, 0xf7, 0x60, 0x3e, 0x5c, 0x81, 0xaa, 0x50, 0x78, 0x89, 0x8f, 0x45, 0xa7, 0xe8, - 0x67, 0xb0, 0x08, 0x78, 0xac, 0xe1, 0x85, 0x7b, 0xf9, 0xdf, 0xcb, 0x29, 0x0e, 0xa0, 0xa0, 0x95, - 0x17, 0xd8, 0xd3, 0x0d, 0xdd, 0xd3, 0x11, 0x82, 0x69, 0xb6, 0x8d, 0x70, 0x15, 0xec, 0x9b, 0x6a, - 0x1d, 0x88, 0xc5, 0x5b, 0x52, 0xe9, 0x27, 0x3a, 0x0f, 0x25, 0xdf, 0xd1, 0xc5, 0x5e, 0x12, 0x10, - 0x68, 0x4c, 0xd7, 0x3d, 0x0f, 0xf7, 0x6d, 0x8f, 0xb9, 0x58, 0x45, 0x95, 0x45, 0xe5, 0xbf, 0xa7, - 0xa1, 0x9a, 0x98, 0x93, 0x47, 0x50, 0xec, 0x8b, 0xe6, 0xc5, 0x42, 0x7b, 0x37, 0x25, 0xb0, 0x27, - 0x4c, 0x55, 0x7d, 0x29, 0x1a, 0x37, 0x69, 0x0c, 0x0d, 0xed, 0x7f, 0x7e, 0x99, 0xce, 0x78, 0x8f, - 0x74, 0x35, 0xc3, 0x74, 0x70, 0xc7, 0x23, 0xce, 0xb1, 0x30, 0x77, 0xbe, 0x47, 0xba, 0x5b, 0x92, - 0x86, 0xee, 0x01, 0x18, 0x96, 0x4b, 0x27, 0xfb, 0xd0, 0xec, 0x32, 0xa3, 0xcb, 0x1b, 0xe7, 0x92, - 0x46, 0xf8, 0x9b, 0x9d, 0x5a, 0x32, 0x2c, 0x57, 0x98, 0xff, 0x18, 0x2a, 0x74, 0xcf, 0xd0, 0xfa, - 0x7c, 0x9f, 0xe2, 0x2b, 0xa5, 0xbc, 0x71, 0x21, 0xad, 0x0f, 0xfe, 0x6e, 0xa6, 0xce, 0xdb, 0x41, - 0xc1, 0x45, 0x4f, 0x60, 0x96, 0x05, 0x6f, 0xb7, 0x36, 0xcb, 0x84, 0xd7, 0x87, 0x0d, 0x80, 0xf0, - 0x88, 0xe7, 0x4c, 0x80, 0x3b, 0x84, 0x90, 0x46, 0xfb, 0x50, 0xd6, 0x2d, 0x8b, 0x78, 0x3a, 0x0f, - 0x34, 0x73, 0x4c, 0xd9, 0x87, 0x63, 0x28, 0x6b, 0x04, 0x52, 0x5c, 0x63, 0x58, 0x0f, 0xfa, 0x01, - 0xcc, 0xb0, 0x48, 0x24, 0x16, 0xe2, 0xd5, 0x31, 0x9d, 0x56, 0xe5, 0x52, 0xf5, 0xbb, 0x50, 0x0e, - 0x19, 0x3b, 0x89, 0x93, 0xd6, 0x1f, 0x40, 0x35, 0x6e, 0xda, 0x44, 0x4e, 0xae, 0xc2, 0xb2, 0x3a, - 0xb0, 0x02, 0xc3, 0x64, 0xf6, 0x75, 0x0f, 0x66, 0xc5, 0x64, 0x73, 0x8f, 0x53, 0x46, 0x8f, 0x91, - 0x2a, 0x24, 0x94, 0x1f, 0xc0, 0xe9, 0x98, 0x4e, 0x91, 0xa4, 0xbd, 0x0b, 0x0b, 0x36, 0x31, 0x34, - 0x97, 0x93, 0x35, 0xd3, 0x90, 0xd1, 0xc5, 0xf6, 0x79, 0x9b, 0x06, 0x15, 0x6f, 0x7b, 0xc4, 0x4e, - 0xda, 0x34, 0x9e, 0x78, 0x0d, 0xce, 0xc4, 0xc5, 0x79, 0xf3, 0xca, 0x43, 0x58, 0x51, 0x71, 0x9f, - 0xbc, 0xc2, 0x27, 0x55, 0x5d, 0x87, 0x5a, 0x52, 0x81, 0x50, 0xfe, 0x39, 0xac, 0x04, 0xd4, 0xb6, - 0xa7, 0x7b, 0x03, 0x77, 0x22, 0xe5, 0x22, 0x83, 0x3d, 0x20, 0x2e, 0x9f, 0xa5, 0xa2, 0x2a, 0x8b, - 0xca, 0xf5, 0xb0, 0xea, 0x16, 0x4f, 0x18, 0x78, 0x0b, 0x68, 0x01, 0xf2, 0xa6, 0x2d, 0xd4, 0xe5, - 0x4d, 0x5b, 0x79, 0x06, 0x25, 0x7f, 0xc7, 0x45, 0xf7, 0x83, 0xd4, 0x31, 0x3f, 0xee, 0xfe, 0xec, - 0x67, 0x97, 0x7b, 0x89, 0x1d, 0x42, 0x34, 0x79, 0x1f, 0xc0, 0x8f, 0x64, 0x72, 0xe3, 0x3f, 0x37, - 0x44, 0xb1, 0x1a, 0x62, 0x57, 0xfe, 0x35, 0x12, 0xdf, 0x42, 0x9d, 0x30, 0xfc, 0x4e, 0x18, 0x91, - 0x78, 0x97, 0x3f, 0x51, 0xbc, 0xfb, 0x08, 0x66, 0x5c, 0x4f, 0xf7, 0xb0, 0x48, 0x8e, 0xd6, 0x86, - 0x89, 0x53, 0x23, 0xb0, 0xca, 0xf9, 0xd1, 0x05, 0x80, 0x8e, 0x83, 0x75, 0x0f, 0x1b, 0x9a, 0xce, - 0x83, 0x73, 0x41, 0x2d, 0x09, 0x4a, 0xc3, 0x43, 0x9b, 0x41, 0x82, 0x37, 0xc3, 0x0c, 0xbb, 0x3e, - 0x4c, 0x73, 0x64, 0xaa, 0x82, 0x54, 0xcf, 0x0f, 0x16, 0xb3, 0x63, 0x06, 0x0b, 0xa1, 0x80, 0x4b, - 0x85, 0x42, 0xe1, 0xdc, 0xe8, 0x50, 0xc8, 0x45, 0xc7, 0x09, 0x85, 0xc5, 0xd1, 0xa1, 0x50, 0x28, - 0x1b, 0x1a, 0x0a, 0xbf, 0xcd, 0x58, 0xf6, 0x2f, 0x39, 0xa8, 0x25, 0xd7, 0xa0, 0x88, 0x3d, 0xf7, - 0x60, 0xd6, 0x65, 0x94, 0x71, 0x02, 0x9a, 0x90, 0x15, 0x12, 0xe8, 0x19, 0x4c, 0x9b, 0xd6, 0x21, - 0x61, 0x67, 0xb3, 0xd4, 0x94, 0x24, 0xab, 0xd5, 0xf5, 0xa6, 0x75, 0x48, 0xf8, 0x20, 0x31, 0x0d, - 0xf5, 0x8f, 0xa0, 0xe4, 0x93, 0x26, 0xea, 0xdb, 0x0e, 0x2c, 0xc7, 0x5c, 0x96, 0xe7, 0xf0, 0xbe, - 0xa7, 0xe7, 0x26, 0xf3, 0x74, 0xe5, 0x67, 0xf9, 0xf0, 0x4a, 0x7c, 0x62, 0xf6, 0x3c, 0xec, 0x24, - 0x56, 0xe2, 0xc7, 0x52, 0x3b, 0x5f, 0x86, 0x57, 0x46, 0x6a, 0xe7, 0xa9, 0xa6, 0x58, 0x4c, 0x3f, - 0x86, 0x05, 0xe6, 0x6b, 0x9a, 0x8b, 0x7b, 0x2c, 0x8f, 0x10, 0x39, 0xdd, 0xf7, 0x87, 0xa9, 0xe1, - 0x96, 0x70, 0x8f, 0x6d, 0x0b, 0x39, 0x3e, 0x82, 0x95, 0x5e, 0x98, 0x56, 0x7f, 0x04, 0x28, 0xc9, - 0x34, 0xd1, 0x98, 0xb6, 0x69, 0x88, 0xa3, 0x07, 0xd8, 0x94, 0xcd, 0xef, 0x90, 0x99, 0x31, 0x8e, - 0xaf, 0x70, 0x83, 0x55, 0x21, 0xa1, 0xfc, 0xaa, 0x00, 0x10, 0x54, 0xfe, 0x3f, 0x8a, 0x6d, 0x8f, - 0xfc, 0xb8, 0xc2, 0xf3, 0xb3, 0x6b, 0xc3, 0x14, 0xa7, 0x46, 0x94, 0x9d, 0x68, 0x44, 0xe1, 0x99, - 0xda, 0xcd, 0xa1, 0x6a, 0xbe, 0xb3, 0xb1, 0xe4, 0x39, 0x9c, 0x89, 0xfb, 0x86, 0x08, 0x24, 0x1b, - 0x30, 0x63, 0x7a, 0xb8, 0xcf, 0x41, 0x9c, 0xd4, 0x43, 0x57, 0x48, 0x88, 0xb3, 0x2a, 0x6b, 0x50, - 0x6a, 0xf6, 0xf5, 0x2e, 0x6e, 0xdb, 0xb8, 0x43, 0x1b, 0x35, 0x69, 0x41, 0x18, 0xc2, 0x0b, 0xca, - 0x06, 0x14, 0x7f, 0x88, 0x8f, 0xf9, 0xa2, 0x1e, 0xd3, 0x50, 0xe5, 0xcf, 0xf2, 0xb0, 0xc2, 0xf6, - 0x8a, 0x4d, 0x09, 0xa1, 0xa8, 0xd8, 0x25, 0x03, 0xa7, 0x83, 0x5d, 0x36, 0xdb, 0xf6, 0x40, 0xb3, - 0xb1, 0x63, 0x12, 0x43, 0x9c, 0xf0, 0x4b, 0x1d, 0x7b, 0xb0, 0xcb, 0x08, 0xe8, 0x1c, 0xd0, 0x82, - 0xf6, 0xe5, 0x80, 0x08, 0x47, 0x2c, 0xa8, 0xc5, 0x8e, 0x3d, 0xf8, 0x03, 0x5a, 0x96, 0xb2, 0xee, - 0x91, 0xee, 0x60, 0x97, 0xf9, 0x19, 0x97, 0x6d, 0x33, 0x02, 0xba, 0x0d, 0xa7, 0xfb, 0xb8, 0x4f, - 0x9c, 0x63, 0xad, 0x67, 0xf6, 0x4d, 0x4f, 0x33, 0x2d, 0xed, 0xe0, 0xd8, 0xc3, 0xae, 0xf0, 0x29, - 0xc4, 0x2b, 0x9f, 0xd3, 0xba, 0xa6, 0xf5, 0x98, 0xd6, 0x20, 0x05, 0x2a, 0x84, 0xf4, 0x35, 0xb7, - 0x43, 0x1c, 0xac, 0xe9, 0xc6, 0x4f, 0xd9, 0xf6, 0x59, 0x50, 0xcb, 0x84, 0xf4, 0xdb, 0x94, 0xd6, - 0x30, 0x7e, 0x8a, 0xde, 0x81, 0x72, 0xc7, 0x1e, 0xb8, 0xd8, 0xd3, 0xe8, 0x1f, 0xb6, 0x3b, 0x96, - 0x54, 0xe0, 0xa4, 0x4d, 0x7b, 0xe0, 0x86, 0x18, 0xfa, 0x74, 0xfc, 0xe7, 0xc2, 0x0c, 0x2f, 0xe8, - 0x30, 0xeb, 0x50, 0x89, 0x20, 0x04, 0xf4, 0xb0, 0xc6, 0xa0, 0x00, 0x71, 0x58, 0xa3, 0xdf, 0x94, - 0xe6, 0x90, 0x9e, 0x1c, 0x49, 0xf6, 0x4d, 0x69, 0xde, 0xb1, 0x2d, 0x4f, 0x6a, 0xec, 0x9b, 0x0e, - 0x79, 0x0f, 0xbf, 0x12, 0x28, 0x52, 0x49, 0xe5, 0x05, 0xc5, 0x00, 0xd8, 0xd4, 0x6d, 0xfd, 0xc0, - 0xec, 0x99, 0xde, 0x31, 0xba, 0x0e, 0x55, 0xdd, 0x30, 0xb4, 0x8e, 0xa4, 0x98, 0x58, 0x62, 0x7b, - 0x8b, 0xba, 0x61, 0x6c, 0x86, 0xc8, 0xe8, 0x3d, 0x58, 0x32, 0x1c, 0x62, 0x47, 0x79, 0x39, 0xd8, - 0x57, 0xa5, 0x15, 0x61, 0x66, 0xe5, 0x17, 0x33, 0x70, 0x21, 0x3a, 0xb1, 0x71, 0x14, 0xe6, 0x11, - 0xcc, 0xc7, 0x5a, 0xcd, 0x40, 0x00, 0x02, 0x6b, 0xd5, 0x88, 0x44, 0x0c, 0x95, 0xc8, 0x27, 0x50, - 0x89, 0x54, 0x9c, 0xa7, 0xf0, 0x56, 0x71, 0x9e, 0xe9, 0xb7, 0x82, 0xf3, 0xcc, 0x4c, 0x86, 0xf3, - 0x5c, 0x61, 0x60, 0xaf, 0x94, 0x66, 0x47, 0x62, 0xee, 0x6a, 0x15, 0x9f, 0xc7, 0x92, 0xa0, 0x70, - 0x0c, 0x0f, 0x9a, 0x9b, 0x04, 0x0f, 0x2a, 0x66, 0xe2, 0x41, 0xd4, 0x6b, 0x6c, 0x5b, 0x77, 0xfa, - 0xc4, 0x91, 0x80, 0x4f, 0xad, 0xc4, 0x4c, 0x58, 0x94, 0x74, 0x01, 0xf6, 0x64, 0x42, 0x43, 0x90, - 0x09, 0x0d, 0x5d, 0x84, 0x79, 0x8b, 0x68, 0x16, 0x7e, 0xad, 0xd1, 0xb9, 0x74, 0x6b, 0x65, 0x3e, - 0xb1, 0x16, 0x69, 0xe1, 0xd7, 0xbb, 0x94, 0x92, 0x00, 0x8f, 0xe6, 0x27, 0x04, 0x8f, 0xfe, 0x2e, - 0x07, 0xcb, 0x51, 0xe7, 0x14, 0x07, 0xfd, 0xa7, 0x50, 0x72, 0x64, 0xfc, 0x11, 0x0e, 0x79, 0x3d, - 0x23, 0xb9, 0x4d, 0x06, 0x2c, 0x35, 0x90, 0x45, 0x3f, 0xca, 0xc4, 0x97, 0x6e, 0x8d, 0xd2, 0x37, - 0x0a, 0x61, 0x52, 0x3a, 0x70, 0xe6, 0x53, 0xd3, 0x32, 0xc8, 0x6b, 0x37, 0x6e, 0x7e, 0x33, 0x69, - 0xfe, 0x7b, 0xc9, 0xe6, 0xe2, 0xc2, 0x69, 0x1d, 0x50, 0xfe, 0x2a, 0x07, 0x67, 0x33, 0x19, 0x63, - 0xe1, 0x35, 0x17, 0x0f, 0xaf, 0x22, 0x34, 0x77, 0xc8, 0xc0, 0xf2, 0x42, 0xa1, 0x79, 0x93, 0xa1, - 0xe8, 0x3c, 0x06, 0x6a, 0x7d, 0xfd, 0x8d, 0xd9, 0x1f, 0xf4, 0x45, 0x6c, 0xa6, 0xea, 0x5e, 0x70, - 0xca, 0x09, 0x82, 0xb3, 0xd2, 0x80, 0x25, 0xdf, 0xca, 0xa1, 0x38, 0x57, 0x08, 0xb7, 0xca, 0x47, - 0x71, 0x2b, 0x0b, 0x66, 0xb7, 0xf0, 0x2b, 0xb3, 0x83, 0xdf, 0x0a, 0xcc, 0x7f, 0x11, 0xca, 0x36, - 0x76, 0xfa, 0xa6, 0xeb, 0xfa, 0x41, 0xa7, 0xa4, 0x86, 0x49, 0xca, 0x7f, 0xce, 0xc2, 0x62, 0x7c, - 0xfe, 0x1e, 0x26, 0x60, 0xb2, 0x4b, 0x29, 0xe1, 0x30, 0xde, 0xd1, 0x50, 0x66, 0x75, 0x5b, 0x6e, - 0xcc, 0xf9, 0xac, 0x43, 0xad, 0xbf, 0x89, 0x8b, 0x5d, 0x9b, 0x8e, 0x48, 0x87, 0xf4, 0xfb, 0xba, - 0x65, 0xc8, 0xdb, 0x19, 0x51, 0xa4, 0xe3, 0xa7, 0x3b, 0x5d, 0x3a, 0xec, 0x94, 0xcc, 0xbe, 0xe9, - 0xe4, 0xd1, 0x13, 0xa0, 0x69, 0x31, 0xb8, 0x8d, 0x05, 0xae, 0x92, 0x0a, 0x82, 0xb4, 0x65, 0x3a, - 0x68, 0x1d, 0xa6, 0xb1, 0xf5, 0x4a, 0xa6, 0x4e, 0x29, 0xd7, 0x37, 0x32, 0x45, 0x50, 0x19, 0x1f, - 0xba, 0x05, 0xb3, 0x7d, 0xea, 0x16, 0xf2, 0x2c, 0xb8, 0x92, 0x71, 0x8b, 0xa1, 0x0a, 0x36, 0xb4, - 0x01, 0x73, 0x06, 0x9b, 0x27, 0x79, 0xe0, 0xab, 0xa5, 0x80, 0x78, 0x8c, 0x41, 0x95, 0x8c, 0x68, - 0xdb, 0x4f, 0x0c, 0x4b, 0x59, 0x19, 0x5d, 0x6c, 0x2a, 0x52, 0xb3, 0xc3, 0xbd, 0x68, 0x76, 0x08, - 0x4c, 0xd7, 0xc6, 0x68, 0x5d, 0xc3, 0x91, 0xb7, 0xb3, 0x50, 0xec, 0x91, 0x2e, 0x77, 0xa3, 0x32, - 0xbf, 0xf8, 0xeb, 0x91, 0x2e, 0xf3, 0xa2, 0x65, 0x9a, 0x28, 0x1b, 0xa6, 0xc5, 0x02, 0x5c, 0x51, - 0xe5, 0x05, 0xba, 0xf8, 0xd8, 0x87, 0x46, 0xac, 0x0e, 0xae, 0x55, 0x58, 0x55, 0x89, 0x51, 0x76, - 0xac, 0x0e, 0x4b, 0xbd, 0x3c, 0xef, 0xb8, 0xb6, 0xc0, 0xe8, 0xf4, 0x93, 0x9e, 0x81, 0xf8, 0x71, - 0x7d, 0x31, 0xeb, 0x0c, 0x94, 0x16, 0x0c, 0xe5, 0x69, 0xfd, 0x31, 0xcc, 0xbd, 0xe6, 0x81, 0xa0, - 0x56, 0x65, 0xf2, 0xd7, 0x46, 0x87, 0x14, 0xa1, 0x41, 0x0a, 0x7e, 0x9b, 0x69, 0xf0, 0xaf, 0x72, - 0x70, 0x66, 0x93, 0x1d, 0x11, 0x42, 0x71, 0x6c, 0x12, 0x54, 0xeb, 0xae, 0x8f, 0x23, 0x66, 0x42, - 0x50, 0xf1, 0x7e, 0x0b, 0x01, 0xd4, 0x84, 0x05, 0xa9, 0x5c, 0xa8, 0x28, 0x8c, 0x0d, 0x45, 0x56, - 0xdc, 0x70, 0x51, 0xf9, 0x18, 0x56, 0x12, 0xbd, 0x10, 0xe9, 0xfc, 0x1a, 0xcc, 0x07, 0xf1, 0xca, - 0xef, 0x44, 0xd9, 0xa7, 0x35, 0x0d, 0xe5, 0x1e, 0x9c, 0x6e, 0x7b, 0xba, 0xe3, 0x25, 0x86, 0x60, - 0x0c, 0x59, 0x86, 0x46, 0x46, 0x65, 0x05, 0x60, 0xd8, 0x86, 0xe5, 0xb6, 0x47, 0xec, 0x13, 0x28, - 0xa5, 0x51, 0x87, 0xf6, 0x9f, 0x0c, 0xe4, 0xfe, 0x20, 0x8b, 0xca, 0x0a, 0xc7, 0x4e, 0x93, 0xad, - 0xdd, 0x87, 0x33, 0x1c, 0xba, 0x3c, 0x49, 0x27, 0xce, 0x4a, 0xe0, 0x34, 0xa9, 0xf7, 0x05, 0x9c, - 0x0a, 0xf6, 0xde, 0x00, 0x96, 0xb8, 0x13, 0x85, 0x25, 0x2e, 0x0e, 0x99, 0xf5, 0x08, 0x2a, 0xf1, - 0x17, 0xf9, 0x50, 0x5c, 0xcf, 0x00, 0x25, 0xee, 0x47, 0x41, 0x89, 0xcb, 0xa3, 0x74, 0x47, 0x30, - 0x89, 0xa4, 0xd7, 0x16, 0x52, 0xbc, 0xf6, 0x8b, 0x04, 0x72, 0x31, 0x9d, 0x05, 0xfd, 0xc4, 0xac, - 0xfd, 0x9d, 0x00, 0x17, 0x2a, 0x07, 0x2e, 0xfc, 0xa6, 0x7d, 0xa4, 0xf9, 0x6e, 0x0c, 0xb8, 0x58, - 0x1b, 0x69, 0xaf, 0x8f, 0x5b, 0xfc, 0xcd, 0x34, 0x94, 0xfc, 0xba, 0xc4, 0x98, 0x27, 0x87, 0x2d, - 0x9f, 0x32, 0x6c, 0xe1, 0x1d, 0xb8, 0xf0, 0x8d, 0x76, 0xe0, 0xe9, 0xb1, 0x77, 0xe0, 0x73, 0x50, - 0x62, 0x1f, 0x9a, 0x83, 0x0f, 0xc5, 0x8e, 0x5a, 0x64, 0x04, 0x15, 0x1f, 0x06, 0x6e, 0x38, 0x3b, - 0x91, 0x1b, 0xc6, 0xa0, 0x92, 0xb9, 0x38, 0x54, 0xf2, 0xd0, 0xdf, 0x11, 0xf9, 0x26, 0x7a, 0x75, - 0x88, 0xde, 0xd4, 0xbd, 0xb0, 0x15, 0xdd, 0x0b, 0xf9, 0xbe, 0xfa, 0xfe, 0x30, 0x2d, 0xdf, 0x59, - 0xa0, 0x64, 0x9f, 0x03, 0x25, 0x61, 0x5f, 0x14, 0x91, 0xf5, 0x3e, 0x80, 0x1f, 0x44, 0x24, 0x5a, - 0x72, 0x6e, 0x48, 0x1f, 0xd5, 0x10, 0x3b, 0x55, 0x1b, 0x99, 0x9a, 0xe0, 0x36, 0x65, 0xbc, 0xf8, - 0x98, 0x71, 0x95, 0xf2, 0xbf, 0x33, 0xa1, 0xf8, 0x92, 0x71, 0xfd, 0xf0, 0x30, 0x01, 0xd1, 0x4d, - 0xe8, 0xc5, 0x77, 0xa2, 0x08, 0xdd, 0x09, 0xbd, 0x2e, 0x01, 0xd0, 0xb1, 0xcc, 0x45, 0x77, 0x44, - 0x35, 0x07, 0x50, 0x4a, 0x82, 0xd2, 0x60, 0x27, 0x83, 0x43, 0xd3, 0x32, 0xdd, 0x23, 0x5e, 0x3f, - 0xcb, 0x4f, 0x06, 0x92, 0xd4, 0x60, 0x0f, 0x78, 0xf0, 0x1b, 0xd3, 0xd3, 0x3a, 0xc4, 0xc0, 0xcc, - 0xa7, 0x67, 0xd4, 0x22, 0x25, 0x6c, 0x12, 0x03, 0x07, 0x2b, 0xaf, 0x78, 0xb2, 0x95, 0x57, 0x8a, - 0xad, 0xbc, 0x33, 0x30, 0xeb, 0x60, 0xdd, 0x25, 0x96, 0x38, 0xaa, 0x8a, 0x12, 0x9d, 0x9a, 0x3e, - 0x76, 0x5d, 0xda, 0x92, 0x48, 0xd7, 0x44, 0x31, 0x94, 0x66, 0xce, 0x8f, 0x4c, 0x33, 0x87, 0x5c, - 0x6b, 0xc4, 0xd2, 0xcc, 0xca, 0xc8, 0x34, 0x73, 0x9c, 0x5b, 0x8d, 0x50, 0xa2, 0xbd, 0x30, 0x5e, - 0xa2, 0x1d, 0xce, 0x4b, 0x17, 0x23, 0x79, 0xe9, 0xb7, 0xb9, 0x58, 0x7f, 0x93, 0x83, 0x95, 0xc4, - 0xb2, 0x12, 0xcb, 0xf5, 0x6e, 0xec, 0x82, 0x64, 0x6d, 0xe4, 0x98, 0xf9, 0xf7, 0x23, 0x4f, 0x23, - 0xf7, 0x23, 0x1f, 0x8e, 0x16, 0x7c, 0xeb, 0xd7, 0x23, 0x7f, 0x92, 0x83, 0x77, 0xf6, 0x6d, 0x23, - 0x96, 0xe1, 0x89, 0x83, 0xf9, 0xf8, 0x81, 0xe3, 0xa1, 0xcc, 0xf5, 0xf3, 0x93, 0xa2, 0x17, 0x5c, - 0x4e, 0x51, 0xe0, 0x62, 0xb6, 0x19, 0x22, 0x65, 0xfa, 0x09, 0x2c, 0x6e, 0xbf, 0xc1, 0x9d, 0xf6, - 0xb1, 0xd5, 0x99, 0xc0, 0xb4, 0x2a, 0x14, 0x3a, 0x7d, 0x43, 0x20, 0x86, 0xf4, 0x33, 0x9c, 0x05, - 0x16, 0xa2, 0x59, 0xa0, 0x06, 0xd5, 0xa0, 0x05, 0x31, 0xbd, 0x67, 0xe8, 0xf4, 0x1a, 0x94, 0x99, - 0x2a, 0x9f, 0x57, 0x45, 0x49, 0xd0, 0xb1, 0xe3, 0xb0, 0x3e, 0x73, 0x3a, 0x76, 0x9c, 0x68, 0xb4, - 0x28, 0x44, 0xa3, 0x85, 0xf2, 0x8b, 0x1c, 0x94, 0x69, 0x0b, 0xdf, 0xc8, 0x7e, 0x71, 0xd4, 0x2a, - 0x04, 0x47, 0x2d, 0xff, 0xc4, 0x36, 0x1d, 0x3e, 0xb1, 0x05, 0x96, 0xcf, 0x30, 0x72, 0xd2, 0xf2, - 0x59, 0x9f, 0x8e, 0x1d, 0x47, 0xb9, 0x08, 0xf3, 0xdc, 0x36, 0xd1, 0xf3, 0x2a, 0x14, 0x06, 0x4e, - 0x4f, 0xfa, 0xd1, 0xc0, 0xe9, 0x29, 0x7f, 0x9a, 0x83, 0x4a, 0xc3, 0xf3, 0xf4, 0xce, 0xd1, 0x04, - 0x1d, 0xf0, 0x8d, 0xcb, 0x87, 0x8d, 0x4b, 0x76, 0x22, 0x30, 0x77, 0x3a, 0xc3, 0xdc, 0x99, 0x88, - 0xb9, 0x0a, 0x2c, 0x48, 0x5b, 0x32, 0x0d, 0x6e, 0x01, 0xda, 0x25, 0x8e, 0xf7, 0x84, 0x38, 0xaf, - 0x75, 0xc7, 0x98, 0xec, 0x04, 0x86, 0x60, 0x5a, 0x3c, 0xea, 0x2c, 0x5c, 0x9b, 0x51, 0xd9, 0xb7, - 0x72, 0x15, 0x4e, 0x45, 0xf4, 0x65, 0x36, 0xfc, 0x08, 0xca, 0x2c, 0xee, 0x8b, 0x54, 0xfc, 0x76, - 0xf8, 0xea, 0x62, 0xac, 0x5d, 0x42, 0xf9, 0x7d, 0x58, 0xa2, 0xf9, 0x01, 0xa3, 0xfb, 0x4b, 0xf1, - 0xfb, 0xb1, 0x3c, 0xf5, 0x42, 0x86, 0xa2, 0x58, 0x8e, 0xfa, 0xb7, 0x39, 0x98, 0x61, 0xf4, 0xc4, - 0x9e, 0x7d, 0x0e, 0x4a, 0x0e, 0xb6, 0x89, 0xe6, 0xe9, 0x5d, 0xff, 0x09, 0x2d, 0x25, 0xec, 0xe9, - 0x5d, 0x97, 0xbd, 0x00, 0xa6, 0x95, 0x86, 0xd9, 0xc5, 0xae, 0x27, 0xdf, 0xd1, 0x96, 0x29, 0x6d, - 0x8b, 0x93, 0xe8, 0x20, 0xb9, 0xe6, 0x1f, 0xf2, 0xbc, 0x73, 0x5a, 0x65, 0xdf, 0x68, 0x9d, 0xbf, - 0xea, 0x1a, 0x07, 0x5e, 0x66, 0x6f, 0xbe, 0xea, 0x50, 0x8c, 0x21, 0xca, 0x7e, 0x59, 0xd9, 0x06, - 0x14, 0x1e, 0x05, 0x31, 0xde, 0xb7, 0x60, 0x96, 0x0d, 0x92, 0xcc, 0x8e, 0x56, 0x32, 0x86, 0x41, - 0x15, 0x6c, 0x8a, 0x0e, 0x88, 0x0f, 0x70, 0x24, 0x23, 0x9a, 0x7c, 0x56, 0x86, 0x64, 0x48, 0xff, - 0x90, 0x83, 0x53, 0x91, 0x36, 0x84, 0xad, 0x37, 0xa3, 0x8d, 0x64, 0x9a, 0x2a, 0x1a, 0xd8, 0x8c, - 0x6c, 0x09, 0xb7, 0xb2, 0x4c, 0xfa, 0x2d, 0x6d, 0x07, 0xff, 0x98, 0x03, 0x68, 0x0c, 0xbc, 0x23, - 0x81, 0x0c, 0x86, 0x67, 0x26, 0x17, 0x9d, 0x19, 0x5a, 0x67, 0xeb, 0xae, 0xfb, 0x9a, 0x38, 0xf2, - 0x4c, 0xe3, 0x97, 0x19, 0x86, 0x37, 0xf0, 0x8e, 0xe4, 0xb5, 0x10, 0xfd, 0x46, 0x97, 0x61, 0x81, - 0x3f, 0xdb, 0xd6, 0x74, 0xc3, 0x70, 0xb0, 0xeb, 0x8a, 0xfb, 0xa1, 0x0a, 0xa7, 0x36, 0x38, 0x91, - 0xb2, 0x99, 0x06, 0xb6, 0x3c, 0xd3, 0x3b, 0xd6, 0x3c, 0xf2, 0x12, 0x5b, 0xe2, 0x6c, 0x52, 0x91, - 0xd4, 0x3d, 0x4a, 0xa4, 0x6c, 0x0e, 0xee, 0x9a, 0xae, 0xe7, 0x48, 0x36, 0x79, 0x17, 0x21, 0xa8, - 0x8c, 0x8d, 0x4e, 0x4a, 0x75, 0x77, 0xd0, 0xeb, 0xf1, 0x21, 0x3e, 0xf9, 0xb4, 0x7f, 0x20, 0x3a, - 0x94, 0xcf, 0xf2, 0xe9, 0x60, 0xd0, 0x44, 0x77, 0xdf, 0x22, 0x08, 0xf3, 0x01, 0x2c, 0x85, 0xfa, - 0x20, 0xdc, 0x2a, 0x92, 0x44, 0xe6, 0xa2, 0x49, 0xa4, 0xf2, 0x14, 0x10, 0xc7, 0x1d, 0xbe, 0x61, - 0xbf, 0x95, 0xd3, 0x70, 0x2a, 0xa2, 0x48, 0xec, 0xc4, 0x37, 0xa0, 0x22, 0xde, 0xe8, 0x08, 0x47, - 0x39, 0x0b, 0x45, 0x1a, 0x51, 0x3b, 0xa6, 0x21, 0xef, 0x0c, 0xe7, 0x6c, 0x62, 0x6c, 0x9a, 0x86, - 0xa3, 0x7c, 0x0a, 0x15, 0x95, 0xb7, 0x23, 0x78, 0x9f, 0xc0, 0x82, 0x78, 0xd1, 0xa3, 0x45, 0x5e, - 0xca, 0xa5, 0xbd, 0xc4, 0x0e, 0x37, 0xa2, 0x56, 0xac, 0x70, 0x51, 0x31, 0xa0, 0xce, 0x53, 0x86, - 0x88, 0x7a, 0xd9, 0xd9, 0x27, 0x20, 0x7f, 0x83, 0x30, 0xb2, 0x95, 0xa8, 0x7c, 0xc5, 0x09, 0x17, - 0x95, 0x0b, 0x70, 0x2e, 0xb5, 0x15, 0x31, 0x12, 0x36, 0x54, 0x83, 0x0a, 0xc3, 0x94, 0x97, 0xa7, - 0xec, 0x52, 0x34, 0x17, 0xba, 0x14, 0x3d, 0xe3, 0x27, 0x89, 0x79, 0xb9, 0x89, 0xb1, 0x0c, 0x30, - 0x48, 0xf7, 0x0b, 0x59, 0xe9, 0xfe, 0x74, 0x24, 0xdd, 0x57, 0xda, 0xfe, 0x78, 0x8a, 0x63, 0xd8, - 0x63, 0x76, 0x5c, 0xe4, 0x6d, 0xcb, 0x80, 0xa8, 0x0c, 0xeb, 0x25, 0x67, 0x55, 0x43, 0x52, 0xca, - 0x75, 0xa8, 0x44, 0x43, 0x63, 0x28, 0xce, 0xe5, 0x12, 0x71, 0x6e, 0x21, 0x16, 0xe2, 0x3e, 0x8a, - 0x65, 0xc0, 0xd9, 0x63, 0x1c, 0xcb, 0x7f, 0x1f, 0x44, 0x82, 0xdd, 0x8d, 0x94, 0xfb, 0xcc, 0xdf, - 0x52, 0x9c, 0x5b, 0x16, 0xfb, 0xc1, 0x13, 0x97, 0xca, 0x8b, 0x4e, 0x2b, 0x97, 0xa0, 0xbc, 0x9f, - 0xf5, 0xcc, 0x7f, 0x5a, 0xbe, 0x1d, 0xb8, 0x03, 0xcb, 0x4f, 0xcc, 0x1e, 0x76, 0x8f, 0x5d, 0x0f, - 0xf7, 0x9b, 0x2c, 0x28, 0x1d, 0x9a, 0xd8, 0x41, 0xab, 0x00, 0xec, 0x08, 0x63, 0x13, 0xd3, 0x7f, - 0xfd, 0x1d, 0xa2, 0x28, 0xff, 0x95, 0x83, 0xc5, 0x40, 0x70, 0x9f, 0x1d, 0xdd, 0xce, 0x43, 0x89, - 0xf6, 0xd7, 0xf5, 0xf4, 0xbe, 0x2d, 0xef, 0xb3, 0x7c, 0x02, 0xba, 0x0f, 0x33, 0x87, 0xae, 0x84, - 0x8c, 0x52, 0x01, 0xf4, 0x34, 0x43, 0xd4, 0xe9, 0x43, 0xb7, 0x69, 0xa0, 0x8f, 0x01, 0x06, 0x2e, - 0x36, 0xc4, 0x1d, 0x56, 0x21, 0x2b, 0x5b, 0xd8, 0x0f, 0xdf, 0xf5, 0x52, 0x01, 0xfe, 0xec, 0xe0, - 0x01, 0x94, 0x4d, 0x8b, 0x18, 0x98, 0xdd, 0xf5, 0x1a, 0x02, 0x55, 0x1a, 0x21, 0x0e, 0x5c, 0x62, - 0xdf, 0xc5, 0x86, 0x82, 0xc5, 0x5e, 0x28, 0xc7, 0x57, 0x38, 0x4a, 0x0b, 0x96, 0x78, 0xd0, 0x3a, - 0xf4, 0x0d, 0x97, 0x1e, 0xbb, 0x36, 0xac, 0x77, 0x6c, 0xb4, 0xd4, 0xaa, 0x29, 0x52, 0x1b, 0x29, - 0xaa, 0xdc, 0x83, 0xd3, 0x91, 0x13, 0xd2, 0x04, 0x47, 0x16, 0x65, 0x37, 0x06, 0x94, 0x04, 0xee, - 0x2c, 0x60, 0x08, 0xe9, 0xcd, 0xa3, 0x60, 0x08, 0x97, 0xc3, 0x10, 0xae, 0xf2, 0x05, 0x9c, 0x8d, - 0x20, 0x3a, 0x11, 0x8b, 0x1e, 0xc4, 0x32, 0xb7, 0x2b, 0xa3, 0xb4, 0xc6, 0x52, 0xb8, 0xff, 0xc9, - 0xc1, 0x72, 0x1a, 0xc3, 0x09, 0x11, 0xc7, 0x9f, 0x64, 0x3c, 0x31, 0xbb, 0x3b, 0x9e, 0x59, 0xbf, - 0x13, 0xb4, 0x76, 0x0f, 0xea, 0x69, 0xe3, 0x99, 0x9c, 0xa5, 0xc2, 0x24, 0xb3, 0xf4, 0xf3, 0x42, - 0x08, 0x79, 0x6f, 0x78, 0x9e, 0x63, 0x1e, 0x0c, 0xa8, 0xcb, 0xbf, 0x75, 0x34, 0xab, 0xe9, 0xe3, - 0x32, 0x7c, 0x68, 0x6f, 0x0f, 0x11, 0x0f, 0xec, 0x48, 0xc5, 0x66, 0x3e, 0x8b, 0x62, 0x33, 0x1c, - 0x53, 0xbf, 0x33, 0x9e, 0xbe, 0xef, 0x2c, 0x00, 0xfa, 0xf3, 0x3c, 0x2c, 0x44, 0xa7, 0x08, 0x6d, - 0x03, 0xe8, 0xbe, 0xe5, 0x62, 0xa1, 0x5c, 0x1e, 0xab, 0x9b, 0x6a, 0x48, 0x10, 0xbd, 0x0f, 0x85, - 0x8e, 0x3d, 0x10, 0xb3, 0x96, 0x72, 0x19, 0xbc, 0x69, 0x0f, 0x78, 0x44, 0xa1, 0x6c, 0xf4, 0x4c, - 0xc5, 0xef, 0xf6, 0xb3, 0xa3, 0xe4, 0x0b, 0x56, 0xcf, 0x65, 0x04, 0x33, 0x7a, 0x06, 0x0b, 0xaf, - 0x1d, 0xd3, 0xd3, 0x0f, 0x7a, 0x58, 0xeb, 0xe9, 0xc7, 0xd8, 0x11, 0x51, 0x72, 0x8c, 0x40, 0x56, - 0x91, 0x82, 0xcf, 0xa9, 0x9c, 0xf2, 0x47, 0x50, 0x94, 0x16, 0x8d, 0xd8, 0x11, 0xf6, 0x60, 0x65, - 0x40, 0xd9, 0x34, 0xf6, 0x1c, 0xcc, 0xd2, 0x2d, 0xa2, 0xb9, 0x98, 0x6e, 0xe3, 0xf2, 0xa1, 0xfa, - 0x88, 0x10, 0xbd, 0xcc, 0xa4, 0x37, 0x89, 0x83, 0x5b, 0xba, 0x45, 0xda, 0x5c, 0x54, 0x79, 0x05, - 0xe5, 0x50, 0x07, 0x47, 0x98, 0xd0, 0x84, 0x25, 0x79, 0x15, 0xef, 0x62, 0x4f, 0x6c, 0x2f, 0x63, - 0x35, 0xbe, 0x28, 0xe4, 0xda, 0xd8, 0xe3, 0xcf, 0x27, 0x1e, 0xc0, 0x59, 0x15, 0x13, 0x1b, 0x5b, - 0xfe, 0x7c, 0x3e, 0x27, 0xdd, 0x09, 0x22, 0xf8, 0x79, 0xa8, 0xa7, 0xc9, 0xf3, 0xf8, 0x70, 0xe3, - 0x3c, 0x14, 0xe5, 0x6f, 0x36, 0xd1, 0x1c, 0x14, 0xf6, 0x36, 0x77, 0xab, 0x53, 0xf4, 0x63, 0x7f, - 0x6b, 0xb7, 0x9a, 0xbb, 0xd1, 0x87, 0x6a, 0xfc, 0x67, 0x8a, 0x68, 0x05, 0x4e, 0xed, 0xaa, 0x3b, - 0xbb, 0x8d, 0xa7, 0x8d, 0xbd, 0xe6, 0x4e, 0x4b, 0xdb, 0x55, 0x9b, 0x9f, 0x34, 0xf6, 0xb6, 0xab, - 0x53, 0x68, 0x0d, 0x2e, 0x84, 0x2b, 0x9e, 0xed, 0xb4, 0xf7, 0xb4, 0xbd, 0x1d, 0x6d, 0x73, 0xa7, - 0xb5, 0xd7, 0x68, 0xb6, 0xb6, 0xd5, 0x6a, 0x0e, 0x5d, 0x80, 0xb3, 0x61, 0x96, 0xc7, 0xcd, 0xad, - 0xa6, 0xba, 0xbd, 0x49, 0xbf, 0x1b, 0xcf, 0xab, 0xf9, 0x1b, 0xb7, 0xa1, 0x12, 0xf9, 0x55, 0x21, - 0x35, 0x64, 0x77, 0x67, 0xab, 0x3a, 0x85, 0x2a, 0x50, 0x0a, 0xeb, 0x29, 0xc2, 0x74, 0x6b, 0x67, - 0x6b, 0xbb, 0x9a, 0xbf, 0x71, 0x0f, 0x16, 0x63, 0xef, 0x51, 0xd1, 0x12, 0x54, 0xda, 0x8d, 0xd6, - 0xd6, 0xe3, 0x9d, 0xcf, 0x34, 0x75, 0xbb, 0xb1, 0xf5, 0x79, 0x75, 0x0a, 0x2d, 0x43, 0x55, 0x92, - 0x5a, 0x3b, 0x7b, 0x9c, 0x9a, 0xbb, 0xf1, 0x32, 0xb6, 0xb2, 0x30, 0x3a, 0x0d, 0x4b, 0x7e, 0x33, - 0xda, 0xa6, 0xba, 0xdd, 0xd8, 0xdb, 0xa6, 0xad, 0x47, 0xc8, 0xea, 0x7e, 0xab, 0xd5, 0x6c, 0x3d, - 0xad, 0xe6, 0xa8, 0xd6, 0x80, 0xbc, 0xfd, 0x59, 0x93, 0x32, 0xe7, 0xa3, 0xcc, 0xfb, 0xad, 0x1f, - 0xb6, 0x76, 0x3e, 0x6d, 0x55, 0x0b, 0x1b, 0x7f, 0xbf, 0x04, 0x0b, 0x32, 0xbd, 0xc3, 0x0e, 0x7b, - 0xcb, 0xb2, 0x0b, 0x73, 0xf2, 0x97, 0xbf, 0x29, 0x71, 0x39, 0xfa, 0x7b, 0xe5, 0xfa, 0xda, 0x10, - 0x0e, 0x91, 0x65, 0x4f, 0xa1, 0x03, 0x96, 0xf5, 0x86, 0xde, 0x07, 0x5f, 0x49, 0xcd, 0x31, 0x13, - 0x4f, 0x92, 0xeb, 0x57, 0x47, 0xf2, 0xf9, 0x6d, 0x60, 0x9a, 0xd8, 0x86, 0x7f, 0x00, 0x83, 0xae, - 0xa6, 0x65, 0xa4, 0x29, 0xbf, 0xb0, 0xa9, 0x5f, 0x1b, 0xcd, 0xe8, 0x37, 0xf3, 0x12, 0xaa, 0xf1, - 0x1f, 0xc3, 0xa0, 0x14, 0xc0, 0x34, 0xe3, 0x17, 0x37, 0xf5, 0x1b, 0xe3, 0xb0, 0x86, 0x1b, 0x4b, - 0xfc, 0x6c, 0xe4, 0xfa, 0x38, 0xef, 0xf0, 0x33, 0x1b, 0xcb, 0x7a, 0xb2, 0xcf, 0x07, 0x30, 0xfa, - 0xf6, 0x17, 0xa5, 0xfe, 0x46, 0x23, 0xe5, 0xe5, 0x78, 0xda, 0x00, 0xa6, 0x3f, 0x23, 0x56, 0xa6, - 0xd0, 0x11, 0x2c, 0xc6, 0x1e, 0x25, 0xa0, 0x14, 0xf1, 0xf4, 0xd7, 0x17, 0xf5, 0xeb, 0x63, 0x70, - 0x46, 0x3d, 0x22, 0xfc, 0x08, 0x21, 0xdd, 0x23, 0x52, 0x9e, 0x38, 0xa4, 0x7b, 0x44, 0xea, 0x7b, - 0x06, 0xe6, 0xdc, 0x91, 0xc7, 0x07, 0x69, 0xce, 0x9d, 0xf6, 0xe4, 0xa1, 0x7e, 0x75, 0x24, 0x5f, - 0x78, 0xd0, 0x62, 0x4f, 0x11, 0xd2, 0x06, 0x2d, 0xfd, 0xa9, 0x43, 0xfd, 0xfa, 0x18, 0x9c, 0x71, - 0x2f, 0x08, 0x2e, 0x36, 0xb3, 0xbc, 0x20, 0x71, 0x0d, 0x9f, 0xe5, 0x05, 0xc9, 0x3b, 0x52, 0xe1, - 0x05, 0xb1, 0x0b, 0xc9, 0x6b, 0x63, 0x5c, 0xa0, 0x64, 0x7b, 0x41, 0xfa, 0x55, 0x8b, 0x32, 0x85, - 0xfe, 0x38, 0x07, 0xb5, 0xac, 0xcb, 0x09, 0x94, 0x92, 0xd5, 0x8d, 0xb8, 0x4f, 0xa9, 0x6f, 0x4c, - 0x22, 0xe2, 0x5b, 0xf1, 0x25, 0xa0, 0xe4, 0x6e, 0x87, 0xde, 0x4b, 0x9b, 0x99, 0x8c, 0x3d, 0xb5, - 0xfe, 0xfe, 0x78, 0xcc, 0x7e, 0x93, 0x6d, 0x28, 0xca, 0xeb, 0x10, 0x94, 0x12, 0xa5, 0x63, 0x97, - 0x31, 0x75, 0x65, 0x18, 0x8b, 0xaf, 0xf4, 0x29, 0x4c, 0x53, 0x2a, 0xba, 0x90, 0xce, 0x2d, 0x95, - 0xad, 0x66, 0x55, 0xfb, 0x8a, 0x5e, 0xc0, 0x2c, 0xc7, 0xff, 0x51, 0x0a, 0xde, 0x10, 0xb9, 0xa5, - 0xa8, 0x5f, 0xcc, 0x66, 0xf0, 0xd5, 0xfd, 0x98, 0xff, 0x53, 0x08, 0x01, 0xed, 0xa3, 0x77, 0xd3, - 0x7f, 0x65, 0x1b, 0xbd, 0x49, 0xa8, 0x5f, 0x1e, 0xc1, 0x15, 0x5e, 0x14, 0xb1, 0x5c, 0xf7, 0xea, - 0xc8, 0x03, 0x4b, 0xf6, 0xa2, 0x48, 0x3f, 0x12, 0x71, 0x27, 0x49, 0x1e, 0x99, 0xd2, 0x9c, 0x24, - 0xf3, 0xa0, 0x9a, 0xe6, 0x24, 0xd9, 0xa7, 0x30, 0x65, 0x0a, 0x79, 0x70, 0x2a, 0x05, 0x20, 0x43, - 0xef, 0x67, 0x39, 0x79, 0x1a, 0x5a, 0x57, 0xbf, 0x39, 0x26, 0x77, 0x78, 0xf2, 0xc5, 0xa2, 0x7f, - 0x27, 0x1b, 0x35, 0xca, 0x9c, 0xfc, 0xf8, 0x12, 0xdf, 0xf8, 0xb7, 0x02, 0xcc, 0x73, 0xf0, 0x53, - 0x64, 0x30, 0x9f, 0x03, 0x04, 0xf7, 0x0e, 0xe8, 0x52, 0xfa, 0x98, 0x44, 0xee, 0x66, 0xea, 0xef, - 0x0e, 0x67, 0x0a, 0x3b, 0x5a, 0x08, 0xc3, 0x4f, 0x73, 0xb4, 0xe4, 0x55, 0x45, 0x9a, 0xa3, 0xa5, - 0x5c, 0x04, 0x28, 0x53, 0xe8, 0x13, 0x28, 0xf9, 0x60, 0x31, 0x4a, 0x03, 0x9b, 0x63, 0x68, 0x78, - 0xfd, 0xd2, 0x50, 0x9e, 0xb0, 0xd5, 0x21, 0x24, 0x38, 0xcd, 0xea, 0x24, 0xe2, 0x9c, 0x66, 0x75, - 0x1a, 0x9c, 0x1c, 0x8c, 0x09, 0xc7, 0x8b, 0x32, 0xc7, 0x24, 0x02, 0xd7, 0x65, 0x8e, 0x49, 0x14, - 0x74, 0x52, 0xa6, 0x1e, 0x5f, 0xf9, 0xf5, 0x57, 0xab, 0xb9, 0x7f, 0xfe, 0x6a, 0x75, 0xea, 0x67, - 0x5f, 0xaf, 0xe6, 0x7e, 0xfd, 0xf5, 0x6a, 0xee, 0x9f, 0xbe, 0x5e, 0xcd, 0xfd, 0xfb, 0xd7, 0xab, - 0xb9, 0x3f, 0xff, 0x8f, 0xd5, 0xa9, 0x1f, 0x15, 0xa5, 0xf4, 0xc1, 0x2c, 0xfb, 0xd7, 0x2e, 0x1f, - 0xfe, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x44, 0x4e, 0x61, 0x00, 0xa0, 0x47, 0x00, 0x00, + 0xb9, 0x05, 0x08, 0x72, 0xc8, 0x69, 0x83, 0x3d, 0xec, 0x25, 0x40, 0x4e, 0x8b, 0x7c, 0x5c, 0x32, + 0x13, 0xe4, 0x92, 0x43, 0x90, 0x3f, 0x20, 0x87, 0xa0, 0xbe, 0x9a, 0xfd, 0xc9, 0x0f, 0x8f, 0x77, + 0x67, 0xf6, 0xa4, 0xae, 0xd7, 0xef, 0xbd, 0x7a, 0xf5, 0xea, 0xf5, 0xab, 0x57, 0xbf, 0x2a, 0x0a, + 0x8a, 0x86, 0x63, 0xad, 0x3b, 0x2e, 0xf1, 0x09, 0xaa, 0xb8, 0x7d, 0xdb, 0xb7, 0x7a, 0x78, 0xfd, + 0xe5, 0x2d, 0xa3, 0xeb, 0x1c, 0x19, 0x1b, 0xb5, 0x1b, 0x1d, 0xcb, 0x3f, 0xea, 0x1f, 0xac, 0xb7, + 0x49, 0xef, 0x66, 0x87, 0x74, 0xc8, 0x4d, 0xc6, 0x78, 0xd0, 0x3f, 0x64, 0x2d, 0xd6, 0x60, 0x4f, + 0x5c, 0x81, 0x7a, 0x1d, 0x16, 0x3e, 0xc6, 0xae, 0x67, 0x11, 0x5b, 0xc3, 0x5f, 0xf6, 0xb1, 0xe7, + 0xa3, 0x2a, 0xcc, 0xbd, 0xe4, 0x94, 0xaa, 0x72, 0x41, 0xb9, 0x5a, 0xd4, 0x64, 0x53, 0xfd, 0x6b, + 0x05, 0x16, 0x03, 0x66, 0xcf, 0x21, 0xb6, 0x87, 0xb3, 0xb9, 0xd1, 0x1a, 0xcc, 0x0b, 0xe3, 0x74, + 0xdb, 0xe8, 0xe1, 0x6a, 0x8e, 0xbd, 0x2e, 0x09, 0x5a, 0xd3, 0xe8, 0x61, 0x74, 0x05, 0x16, 0x25, + 0x8b, 0x54, 0x92, 0x67, 0x5c, 0x0b, 0x82, 0x2c, 0x7a, 0x43, 0xeb, 0x70, 0x42, 0x32, 0x1a, 0x8e, + 0x15, 0x30, 0x4f, 0x33, 0xe6, 0x25, 0xf1, 0xaa, 0xee, 0x58, 0x82, 0x5f, 0xfd, 0x1c, 0x8a, 0x5b, + 0xcd, 0xd6, 0x26, 0xb1, 0x0f, 0xad, 0x0e, 0x35, 0xd1, 0xc3, 0x2e, 0x95, 0xa9, 0x2a, 0x17, 0xf2, + 0xd4, 0x44, 0xd1, 0x44, 0x35, 0x28, 0x78, 0xd8, 0x70, 0xdb, 0x47, 0xd8, 0xab, 0xe6, 0xd8, 0xab, + 0xa0, 0x4d, 0xa5, 0x88, 0xe3, 0x5b, 0xc4, 0xf6, 0xaa, 0x79, 0x2e, 0x25, 0x9a, 0xea, 0x2f, 0x14, + 0x28, 0xed, 0x12, 0xd7, 0x7f, 0x6e, 0x38, 0x8e, 0x65, 0x77, 0xd0, 0x6d, 0x28, 0x30, 0x5f, 0xb6, + 0x49, 0x97, 0xf9, 0x60, 0x61, 0xa3, 0xb6, 0x1e, 0x9f, 0x96, 0xf5, 0x5d, 0xc1, 0xa1, 0x05, 0xbc, + 0xe8, 0x12, 0x2c, 0xb4, 0x89, 0xed, 0x1b, 0x96, 0x8d, 0x5d, 0xdd, 0x21, 0xae, 0xcf, 0x5c, 0x34, + 0xa3, 0x95, 0x03, 0x2a, 0xed, 0x05, 0x9d, 0x81, 0xe2, 0x11, 0xf1, 0x7c, 0xce, 0x91, 0x67, 0x1c, + 0x05, 0x4a, 0x60, 0x2f, 0x57, 0x60, 0x8e, 0xbd, 0xb4, 0x1c, 0xe1, 0x8c, 0x59, 0xda, 0x6c, 0x38, + 0xea, 0x6f, 0x14, 0x98, 0x79, 0x4e, 0xfa, 0xb6, 0x1f, 0xeb, 0xc6, 0xf0, 0x8f, 0xc4, 0x44, 0x85, + 0xba, 0x31, 0xfc, 0xa3, 0x41, 0x37, 0x94, 0x83, 0xcf, 0x15, 0xef, 0x86, 0xbe, 0xac, 0x41, 0xc1, + 0xc5, 0x86, 0x49, 0xec, 0xee, 0x31, 0x33, 0xa1, 0xa0, 0x05, 0x6d, 0x3a, 0x89, 0x1e, 0xee, 0x5a, + 0x76, 0xff, 0xb5, 0xee, 0xe2, 0xae, 0x71, 0x80, 0xbb, 0xcc, 0x94, 0x82, 0xb6, 0x20, 0xc8, 0x1a, + 0xa7, 0xa2, 0x2d, 0x28, 0x39, 0x2e, 0x71, 0x8c, 0x8e, 0x41, 0xfd, 0x58, 0x9d, 0x61, 0xae, 0x52, + 0x93, 0xae, 0x62, 0x66, 0xef, 0x0e, 0x38, 0xb5, 0xb0, 0x98, 0xfa, 0xb7, 0x0a, 0x2c, 0xd2, 0xe0, + 0xf1, 0x1c, 0xa3, 0x8d, 0x77, 0xd8, 0x94, 0xa0, 0x3b, 0x30, 0x67, 0x63, 0xff, 0x15, 0x71, 0x5f, + 0x88, 0x09, 0x38, 0x9f, 0xd4, 0x1a, 0xc8, 0x3c, 0x27, 0x26, 0xd6, 0x24, 0x3f, 0xba, 0x05, 0x79, + 0xc7, 0x32, 0xd9, 0x80, 0xc7, 0x10, 0xa3, 0xbc, 0x54, 0xc4, 0x72, 0xda, 0xcc, 0x0f, 0xe3, 0x88, + 0x58, 0x4e, 0x5b, 0x55, 0x01, 0x1a, 0xb6, 0x7f, 0xfb, 0x7b, 0x1f, 0x1b, 0xdd, 0x3e, 0x46, 0xcb, + 0x30, 0xf3, 0x92, 0x3e, 0x30, 0x63, 0xf3, 0x1a, 0x6f, 0xa8, 0x5f, 0xe5, 0xe1, 0xcc, 0x33, 0xea, + 0xaf, 0x96, 0x61, 0x9b, 0x07, 0xe4, 0x75, 0x0b, 0xb7, 0xfb, 0xae, 0xe5, 0x1f, 0x6f, 0x12, 0xdb, + 0xc7, 0xaf, 0x7d, 0xd4, 0x84, 0x25, 0x5b, 0x6a, 0xd6, 0x65, 0x68, 0x52, 0x0d, 0xa5, 0x8d, 0xb5, + 0x21, 0x46, 0x70, 0x17, 0x69, 0x15, 0x3b, 0x4a, 0xf0, 0xd0, 0xd3, 0xc1, 0xbc, 0x49, 0x6d, 0x39, + 0xa6, 0x2d, 0x65, 0x48, 0xad, 0x6d, 0x66, 0x99, 0xd0, 0x25, 0x27, 0x56, 0x6a, 0xfa, 0x08, 0xe8, + 0x57, 0xad, 0x1b, 0x9e, 0xde, 0xf7, 0xb0, 0xcb, 0x1c, 0x53, 0xda, 0x38, 0x9b, 0xd4, 0x32, 0x70, + 0x81, 0x56, 0x74, 0xfb, 0x76, 0xdd, 0xdb, 0xf7, 0xb0, 0xcb, 0x92, 0x80, 0x88, 0x25, 0xdd, 0x25, + 0xc4, 0x3f, 0xf4, 0x64, 0xfc, 0x48, 0xb2, 0xc6, 0xa8, 0xe8, 0x26, 0x9c, 0xf0, 0xfa, 0x8e, 0xd3, + 0xc5, 0x3d, 0x6c, 0xfb, 0x46, 0x57, 0xef, 0xb8, 0xa4, 0xef, 0x78, 0xd5, 0x99, 0x0b, 0xf9, 0xab, + 0x79, 0x0d, 0x85, 0x5f, 0x3d, 0x61, 0x6f, 0xd0, 0x2a, 0x80, 0xe3, 0x5a, 0x2f, 0xad, 0x2e, 0xee, + 0x60, 0xb3, 0x3a, 0xcb, 0x94, 0x86, 0x28, 0xe8, 0x7d, 0x58, 0xf6, 0x70, 0xbb, 0x4d, 0x7a, 0x8e, + 0xee, 0xb8, 0xe4, 0xd0, 0xea, 0x62, 0x1e, 0xfd, 0x73, 0x2c, 0xfa, 0x91, 0x78, 0xb7, 0xcb, 0x5f, + 0xb1, 0xef, 0xe0, 0x3e, 0xcb, 0x69, 0x74, 0xa4, 0xac, 0xf3, 0x6a, 0x61, 0x8c, 0xa1, 0x02, 0x1b, + 0x2a, 0x33, 0x49, 0xfd, 0x45, 0x0e, 0x4e, 0x32, 0x4f, 0xee, 0x12, 0x53, 0x4c, 0xb3, 0x48, 0x52, + 0x17, 0xa1, 0xdc, 0x66, 0x3a, 0x75, 0xc7, 0x70, 0xb1, 0xed, 0x8b, 0x8f, 0x74, 0x9e, 0x13, 0x77, + 0x19, 0x0d, 0x7d, 0x0a, 0x15, 0x4f, 0x44, 0x85, 0xde, 0xe6, 0x61, 0x21, 0xe6, 0xec, 0x46, 0xd2, + 0x84, 0x21, 0xb1, 0xa4, 0x2d, 0x7a, 0x89, 0xe0, 0x9a, 0xf3, 0x8e, 0xbd, 0xb6, 0xdf, 0xe5, 0xd9, + 0xae, 0xb4, 0xf1, 0xbd, 0x0c, 0x85, 0x71, 0xc3, 0xd7, 0x5b, 0x5c, 0x6c, 0xdb, 0xf6, 0xdd, 0x63, + 0x4d, 0x2a, 0xa9, 0xdd, 0x85, 0xf9, 0xf0, 0x0b, 0x54, 0x81, 0xfc, 0x0b, 0x7c, 0x2c, 0x06, 0x45, + 0x1f, 0x07, 0x1f, 0x01, 0xcf, 0x35, 0xbc, 0x71, 0x37, 0xf7, 0x07, 0x8a, 0xea, 0x02, 0x1a, 0xf4, + 0xf2, 0x1c, 0xfb, 0x86, 0x69, 0xf8, 0x06, 0x42, 0x30, 0xcd, 0x96, 0x11, 0xae, 0x82, 0x3d, 0x53, + 0xad, 0x7d, 0xf1, 0xf1, 0x16, 0x35, 0xfa, 0x88, 0xce, 0x42, 0x31, 0x08, 0x74, 0xb1, 0x96, 0x0c, + 0x08, 0x34, 0xa7, 0x1b, 0xbe, 0x8f, 0x7b, 0x8e, 0xcf, 0x42, 0xac, 0xac, 0xc9, 0xa6, 0xfa, 0x3f, + 0xd3, 0x50, 0x49, 0xcc, 0xc9, 0x43, 0x28, 0xf4, 0x44, 0xf7, 0xe2, 0x43, 0x7b, 0x27, 0x25, 0xb1, + 0x27, 0x4c, 0xd5, 0x02, 0x29, 0x9a, 0x37, 0x69, 0x0e, 0x0d, 0xad, 0x7f, 0x41, 0x9b, 0xce, 0x78, + 0x97, 0x74, 0x74, 0xd3, 0x72, 0x71, 0xdb, 0x27, 0xee, 0xb1, 0x30, 0x77, 0xbe, 0x4b, 0x3a, 0x5b, + 0x92, 0x86, 0xee, 0x02, 0x98, 0xb6, 0x47, 0x27, 0xfb, 0xd0, 0xea, 0x30, 0xa3, 0x4b, 0x1b, 0x67, + 0x92, 0x46, 0x04, 0x8b, 0x9d, 0x56, 0x34, 0x6d, 0x4f, 0x98, 0xff, 0x08, 0xca, 0x74, 0xcd, 0xd0, + 0x7b, 0x7c, 0x9d, 0xe2, 0x5f, 0x4a, 0x69, 0xe3, 0x5c, 0xda, 0x18, 0x82, 0xd5, 0x4c, 0x9b, 0x77, + 0x06, 0x0d, 0x0f, 0x3d, 0x86, 0x59, 0x96, 0xbc, 0xbd, 0xea, 0x2c, 0x13, 0x5e, 0x1f, 0xe6, 0x00, + 0x11, 0x11, 0xcf, 0x98, 0x00, 0x0f, 0x08, 0x21, 0x8d, 0xf6, 0xa1, 0x64, 0xd8, 0x36, 0xf1, 0x0d, + 0x9e, 0x68, 0xe6, 0x98, 0xb2, 0x0f, 0xc6, 0x50, 0x56, 0x1f, 0x48, 0x71, 0x8d, 0x61, 0x3d, 0xe8, + 0x07, 0x30, 0xc3, 0x32, 0x91, 0xf8, 0x10, 0xaf, 0x8c, 0x19, 0xb4, 0x1a, 0x97, 0xaa, 0xdd, 0x81, + 0x52, 0xc8, 0xd8, 0x49, 0x82, 0xb4, 0x76, 0x1f, 0x2a, 0x71, 0xd3, 0x26, 0x0a, 0x72, 0x0d, 0x96, + 0xb5, 0xbe, 0x3d, 0x30, 0x4c, 0x56, 0x5f, 0x77, 0x61, 0x56, 0x4c, 0x36, 0x8f, 0x38, 0x75, 0xb4, + 0x8f, 0x34, 0x21, 0xa1, 0xfe, 0x00, 0x4e, 0xc6, 0x74, 0x8a, 0x22, 0xed, 0x1d, 0x58, 0x70, 0x88, + 0xa9, 0x7b, 0x9c, 0xac, 0x5b, 0xa6, 0xcc, 0x2e, 0x4e, 0xc0, 0xdb, 0x30, 0xa9, 0x78, 0xcb, 0x27, + 0x4e, 0xd2, 0xa6, 0xf1, 0xc4, 0xab, 0x70, 0x2a, 0x2e, 0xce, 0xbb, 0x57, 0x1f, 0xc0, 0x8a, 0x86, + 0x7b, 0xe4, 0x25, 0x7e, 0x53, 0xd5, 0x35, 0xa8, 0x26, 0x15, 0x08, 0xe5, 0x9f, 0xc1, 0xca, 0x80, + 0xda, 0xf2, 0x0d, 0xbf, 0xef, 0x4d, 0xa4, 0x5c, 0x54, 0xb0, 0x07, 0xc4, 0xe3, 0xb3, 0x54, 0xd0, + 0x64, 0x53, 0xbd, 0x16, 0x56, 0xdd, 0xe4, 0x05, 0x03, 0xef, 0x01, 0x2d, 0x40, 0xce, 0x72, 0x84, + 0xba, 0x9c, 0xe5, 0xa8, 0x4f, 0xa1, 0x18, 0xac, 0xb8, 0xe8, 0xde, 0xa0, 0x74, 0xcc, 0x8d, 0xbb, + 0x3e, 0x07, 0xd5, 0xe5, 0x5e, 0x62, 0x85, 0x10, 0x5d, 0xde, 0x03, 0x08, 0x32, 0x99, 0x5c, 0xf8, + 0xcf, 0x0c, 0x51, 0xac, 0x85, 0xd8, 0xd5, 0x7f, 0x8b, 0xe4, 0xb7, 0xd0, 0x20, 0xcc, 0x60, 0x10, + 0x66, 0x24, 0xdf, 0xe5, 0xde, 0x28, 0xdf, 0x7d, 0x08, 0x33, 0x9e, 0x6f, 0xf8, 0x58, 0x14, 0x47, + 0x6b, 0xc3, 0xc4, 0xa9, 0x11, 0x58, 0xe3, 0xfc, 0xe8, 0x1c, 0x40, 0xdb, 0xc5, 0x86, 0x8f, 0x4d, + 0xdd, 0xe0, 0xc9, 0x39, 0xaf, 0x15, 0x05, 0xa5, 0xee, 0xa3, 0xcd, 0x41, 0x81, 0x37, 0xc3, 0x0c, + 0xbb, 0x36, 0x4c, 0x73, 0x64, 0xaa, 0x06, 0xa5, 0x5e, 0x90, 0x2c, 0x66, 0xc7, 0x4c, 0x16, 0x42, + 0x01, 0x97, 0x0a, 0xa5, 0xc2, 0xb9, 0xd1, 0xa9, 0x90, 0x8b, 0x8e, 0x93, 0x0a, 0x0b, 0xa3, 0x53, + 0xa1, 0x50, 0x36, 0x34, 0x15, 0x7e, 0x9b, 0xb9, 0xec, 0x5f, 0x15, 0xa8, 0x26, 0xbf, 0x41, 0x91, + 0x7b, 0xee, 0xc2, 0xac, 0xc7, 0x28, 0xe3, 0x24, 0x34, 0x21, 0x2b, 0x24, 0xd0, 0x53, 0x98, 0xb6, + 0xec, 0x43, 0xc2, 0xf6, 0x66, 0xa9, 0x25, 0x49, 0x56, 0xaf, 0xeb, 0x0d, 0xfb, 0x90, 0x70, 0x27, + 0x31, 0x0d, 0xb5, 0x0f, 0xa1, 0x18, 0x90, 0x26, 0x1a, 0xdb, 0x0e, 0x2c, 0xc7, 0x42, 0x96, 0xd7, + 0xf0, 0x41, 0xa4, 0x2b, 0x93, 0x45, 0xba, 0xfa, 0xd3, 0x5c, 0xf8, 0x4b, 0x7c, 0x6c, 0x75, 0x7d, + 0xec, 0x26, 0xbe, 0xc4, 0x8f, 0xa4, 0x76, 0xfe, 0x19, 0x5e, 0x1e, 0xa9, 0x9d, 0x97, 0x9a, 0xe2, + 0x63, 0xfa, 0x02, 0x16, 0x58, 0xac, 0xe9, 0x1e, 0xee, 0xb2, 0x3a, 0x42, 0xd4, 0x74, 0xdf, 0x1f, + 0xa6, 0x86, 0x5b, 0xc2, 0x23, 0xb6, 0x25, 0xe4, 0xb8, 0x07, 0xcb, 0xdd, 0x30, 0xad, 0xf6, 0x10, + 0x50, 0x92, 0x69, 0x22, 0x9f, 0xb6, 0x68, 0x8a, 0xa3, 0x1b, 0xd8, 0x94, 0xc5, 0xef, 0x90, 0x99, + 0x31, 0x4e, 0xac, 0x70, 0x83, 0x35, 0x21, 0xa1, 0xfe, 0x2a, 0x0f, 0x30, 0x78, 0xf9, 0x7b, 0x94, + 0xdb, 0x1e, 0x06, 0x79, 0x85, 0xd7, 0x67, 0x57, 0x87, 0x29, 0x4e, 0xcd, 0x28, 0x3b, 0xd1, 0x8c, + 0xc2, 0x2b, 0xb5, 0x1b, 0x43, 0xd5, 0x7c, 0x67, 0x73, 0xc9, 0x33, 0x38, 0x15, 0x8f, 0x0d, 0x91, + 0x48, 0x36, 0x60, 0xc6, 0xf2, 0x71, 0x8f, 0x83, 0x38, 0xa9, 0x9b, 0xae, 0x90, 0x10, 0x67, 0x55, + 0xd7, 0xa0, 0xd8, 0xe8, 0x19, 0x1d, 0xdc, 0x72, 0x70, 0x9b, 0x76, 0x6a, 0xd1, 0x86, 0x30, 0x84, + 0x37, 0xd4, 0x0d, 0x28, 0xfc, 0x10, 0x1f, 0xf3, 0x8f, 0x7a, 0x4c, 0x43, 0xd5, 0xbf, 0xc8, 0xc1, + 0x0a, 0x5b, 0x2b, 0x36, 0x25, 0x84, 0xa2, 0x61, 0x8f, 0xf4, 0xdd, 0x36, 0xf6, 0xd8, 0x6c, 0x3b, + 0x7d, 0xdd, 0xc1, 0xae, 0x45, 0x4c, 0xb1, 0xc3, 0x2f, 0xb6, 0x9d, 0xfe, 0x2e, 0x23, 0xa0, 0x33, + 0x40, 0x1b, 0xfa, 0x97, 0x7d, 0x22, 0x02, 0x31, 0xaf, 0x15, 0xda, 0x4e, 0xff, 0x8f, 0x68, 0x5b, + 0xca, 0x7a, 0x47, 0x86, 0x8b, 0x3d, 0x16, 0x67, 0x5c, 0xb6, 0xc5, 0x08, 0xe8, 0x16, 0x9c, 0xec, + 0xe1, 0x1e, 0x71, 0x8f, 0xf5, 0xae, 0xd5, 0xb3, 0x7c, 0xdd, 0xb2, 0xf5, 0x83, 0x63, 0x1f, 0x7b, + 0x22, 0xa6, 0x10, 0x7f, 0xf9, 0x8c, 0xbe, 0x6b, 0xd8, 0x8f, 0xe8, 0x1b, 0xa4, 0x42, 0x99, 0x90, + 0x9e, 0xee, 0xb5, 0x89, 0x8b, 0x75, 0xc3, 0xfc, 0x09, 0x5b, 0x3e, 0xf3, 0x5a, 0x89, 0x90, 0x5e, + 0x8b, 0xd2, 0xea, 0xe6, 0x4f, 0xd0, 0x79, 0x28, 0xb5, 0x9d, 0xbe, 0x87, 0x7d, 0x9d, 0xfe, 0x61, + 0xab, 0x63, 0x51, 0x03, 0x4e, 0xda, 0x74, 0xfa, 0x5e, 0x88, 0xa1, 0x47, 0xfd, 0x3f, 0x17, 0x66, + 0x78, 0x4e, 0xdd, 0x6c, 0x40, 0x39, 0x82, 0x10, 0xd0, 0xcd, 0x1a, 0x83, 0x02, 0xc4, 0x66, 0x8d, + 0x3e, 0x53, 0x9a, 0x4b, 0xba, 0xd2, 0x93, 0xec, 0x99, 0xd2, 0xfc, 0x63, 0x47, 0xee, 0xd4, 0xd8, + 0x33, 0x75, 0x79, 0x17, 0xbf, 0x14, 0x28, 0x52, 0x51, 0xe3, 0x0d, 0xd5, 0x04, 0xd8, 0x34, 0x1c, + 0xe3, 0xc0, 0xea, 0x5a, 0xfe, 0x31, 0xba, 0x06, 0x15, 0xc3, 0x34, 0xf5, 0xb6, 0xa4, 0x58, 0x58, + 0x62, 0x7b, 0x8b, 0x86, 0x69, 0x6e, 0x86, 0xc8, 0xe8, 0x5d, 0x58, 0x32, 0x5d, 0xe2, 0x44, 0x79, + 0x39, 0xd8, 0x57, 0xa1, 0x2f, 0xc2, 0xcc, 0xea, 0xcf, 0x67, 0xe0, 0x5c, 0x74, 0x62, 0xe3, 0x28, + 0xcc, 0x43, 0x98, 0x8f, 0xf5, 0x9a, 0x81, 0x00, 0x0c, 0xac, 0xd5, 0x22, 0x12, 0x31, 0x54, 0x22, + 0x97, 0x40, 0x25, 0x52, 0x71, 0x9e, 0xfc, 0x5b, 0xc5, 0x79, 0xa6, 0xdf, 0x0a, 0xce, 0x33, 0x33, + 0x19, 0xce, 0x73, 0x99, 0x81, 0xbd, 0x52, 0x9a, 0x6d, 0x89, 0x79, 0xa8, 0x95, 0x03, 0x1e, 0x5b, + 0x82, 0xc2, 0x31, 0x3c, 0x68, 0x6e, 0x12, 0x3c, 0xa8, 0x90, 0x89, 0x07, 0xd1, 0xa8, 0x71, 0x1c, + 0xc3, 0xed, 0x11, 0x57, 0x02, 0x3e, 0xd5, 0x22, 0x33, 0x61, 0x51, 0xd2, 0x05, 0xd8, 0x93, 0x09, + 0x0d, 0x41, 0x26, 0x34, 0x74, 0x01, 0xe6, 0x6d, 0xa2, 0xdb, 0xf8, 0x95, 0x4e, 0xe7, 0xd2, 0xab, + 0x96, 0xf8, 0xc4, 0xda, 0xa4, 0x89, 0x5f, 0xed, 0x52, 0x4a, 0x02, 0x3c, 0x9a, 0x9f, 0x10, 0x3c, + 0xfa, 0x07, 0x05, 0x96, 0xa3, 0xc1, 0x29, 0x36, 0xfa, 0x4f, 0xa0, 0xe8, 0xca, 0xfc, 0x23, 0x02, + 0xf2, 0x5a, 0x46, 0x71, 0x9b, 0x4c, 0x58, 0xda, 0x40, 0x16, 0xfd, 0x28, 0x13, 0x5f, 0xba, 0x39, + 0x4a, 0xdf, 0x28, 0x84, 0x49, 0x6d, 0xc0, 0xf9, 0x4f, 0x2c, 0xdb, 0x24, 0xaf, 0xbc, 0xcc, 0x6f, + 0x2b, 0x25, 0x42, 0x94, 0x94, 0x08, 0x51, 0x7f, 0xa9, 0xc0, 0xa9, 0xb8, 0x2e, 0xe1, 0x8a, 0x46, + 0xd2, 0x15, 0xef, 0x26, 0x4d, 0x8f, 0x0b, 0xa7, 0x3a, 0xe3, 0x8b, 0x4c, 0x67, 0xdc, 0x1a, 0xad, + 0x71, 0xa4, 0x3b, 0xfe, 0x46, 0x81, 0xd3, 0x99, 0x66, 0xc4, 0x16, 0x02, 0x25, 0xbe, 0x10, 0x88, + 0x45, 0xa4, 0x4d, 0xfa, 0xb6, 0x1f, 0x5a, 0x44, 0x36, 0x19, 0xde, 0xcf, 0xb3, 0xb5, 0xde, 0x33, + 0x5e, 0x5b, 0xbd, 0x7e, 0x4f, 0xac, 0x22, 0x54, 0xdd, 0x73, 0x4e, 0x79, 0x83, 0x65, 0x44, 0xad, + 0xc3, 0x52, 0x60, 0xe5, 0x50, 0x44, 0x2e, 0x84, 0xb0, 0xe5, 0xa2, 0x08, 0x9b, 0x0d, 0xb3, 0x5b, + 0xf8, 0xa5, 0xd5, 0xc6, 0x6f, 0xe5, 0x40, 0xe2, 0x02, 0x94, 0x1c, 0xec, 0xf6, 0x2c, 0xcf, 0x0b, + 0xd2, 0x63, 0x51, 0x0b, 0x93, 0xd4, 0xff, 0x9a, 0x85, 0xc5, 0x78, 0x74, 0x3c, 0x48, 0x00, 0x7a, + 0x17, 0x53, 0x12, 0x77, 0x7c, 0xa0, 0xa1, 0x1a, 0xf0, 0x96, 0x2c, 0x21, 0x72, 0x59, 0xdb, 0xef, + 0xa0, 0xdc, 0x10, 0xf5, 0x05, 0xf5, 0x48, 0x9b, 0xf4, 0x7a, 0x86, 0x6d, 0xca, 0x73, 0x24, 0xd1, + 0xa4, 0xfe, 0x33, 0xdc, 0x0e, 0x75, 0x3b, 0x25, 0xb3, 0x67, 0x3a, 0x79, 0x74, 0xaf, 0x6a, 0xd9, + 0x0c, 0x18, 0x64, 0x29, 0xb6, 0xa8, 0x81, 0x20, 0x6d, 0x59, 0x2e, 0x5a, 0x87, 0x69, 0x6c, 0xbf, + 0x94, 0x45, 0x5e, 0xca, 0x41, 0x93, 0x2c, 0x66, 0x34, 0xc6, 0x87, 0x6e, 0xc2, 0x6c, 0x8f, 0x86, + 0x85, 0xdc, 0xb5, 0xae, 0x64, 0x9c, 0xb7, 0x68, 0x82, 0x0d, 0x6d, 0xc0, 0x9c, 0xc9, 0xe6, 0x49, + 0x6e, 0x4d, 0xab, 0x29, 0x70, 0x23, 0x63, 0xd0, 0x24, 0x23, 0xda, 0x0e, 0x4a, 0xd8, 0x62, 0x56, + 0xed, 0x19, 0x9b, 0x8a, 0xd4, 0x3a, 0x76, 0x2f, 0x5a, 0xc7, 0x02, 0xd3, 0xb5, 0x31, 0x5a, 0xd7, + 0x70, 0x8c, 0xf0, 0x34, 0x14, 0xba, 0xa4, 0xc3, 0xc3, 0xa8, 0xc4, 0x8f, 0x28, 0xbb, 0xa4, 0xc3, + 0xa2, 0x68, 0x99, 0x96, 0xf4, 0xa6, 0x65, 0xb3, 0x54, 0x5c, 0xd0, 0x78, 0x83, 0x7e, 0x7c, 0xec, + 0x41, 0x27, 0x76, 0x1b, 0x57, 0xcb, 0xec, 0x55, 0x91, 0x51, 0x76, 0xec, 0x36, 0x2b, 0x12, 0x7d, + 0xff, 0xb8, 0xba, 0xc0, 0xe8, 0xf4, 0x91, 0xee, 0xd6, 0x38, 0xb0, 0xb0, 0x98, 0xb5, 0x5b, 0x4b, + 0x4b, 0xdb, 0x12, 0x57, 0x78, 0x04, 0x73, 0xaf, 0x78, 0x22, 0xa8, 0x56, 0x98, 0xfc, 0xd5, 0xd1, + 0xe9, 0x45, 0x68, 0x90, 0x82, 0xdf, 0x66, 0xc1, 0xfe, 0x2b, 0x05, 0x4e, 0x6d, 0xb2, 0xcd, 0x4c, + 0x28, 0x8f, 0x4d, 0x82, 0xbf, 0xdd, 0x09, 0x10, 0xcf, 0x4c, 0xb0, 0x2c, 0x3e, 0x6e, 0x21, 0x80, + 0x1a, 0xb0, 0x20, 0x95, 0x0b, 0x15, 0xf9, 0xb1, 0x41, 0xd3, 0xb2, 0x17, 0x6e, 0xaa, 0x1f, 0xc1, + 0x4a, 0x62, 0x14, 0x62, 0xe3, 0xb1, 0x06, 0xf3, 0x83, 0x7c, 0x15, 0x0c, 0xa2, 0x14, 0xd0, 0x1a, + 0xa6, 0x7a, 0x17, 0x4e, 0xb6, 0x7c, 0xc3, 0xf5, 0x13, 0x2e, 0x18, 0x43, 0x96, 0xe1, 0xa6, 0x51, + 0x59, 0x01, 0x6d, 0xb6, 0x60, 0xb9, 0xe5, 0x13, 0xe7, 0x0d, 0x94, 0xd2, 0xac, 0x43, 0xc7, 0x4f, + 0xfa, 0x72, 0x7d, 0x90, 0x4d, 0x75, 0x85, 0xa3, 0xbc, 0xc9, 0xde, 0xee, 0xc1, 0x29, 0x0e, 0xb2, + 0xbe, 0xc9, 0x20, 0x4e, 0x4b, 0x88, 0x37, 0xa9, 0xf7, 0x39, 0x9c, 0x18, 0x2c, 0x8b, 0x03, 0x00, + 0xe5, 0x76, 0x14, 0x40, 0xb9, 0x30, 0x64, 0xd6, 0x23, 0xf8, 0xc9, 0x5f, 0xe5, 0x42, 0x79, 0x3d, + 0x03, 0x3e, 0xb9, 0x17, 0x85, 0x4f, 0x2e, 0x8d, 0xd2, 0x1d, 0x41, 0x4f, 0x92, 0x51, 0x9b, 0x4f, + 0x89, 0xda, 0xcf, 0x13, 0x18, 0xcb, 0x74, 0x16, 0x48, 0x15, 0xb3, 0xf6, 0x77, 0x02, 0xb1, 0x68, + 0x1c, 0x62, 0x09, 0xba, 0x0e, 0x30, 0xf1, 0x3b, 0x31, 0x88, 0x65, 0x6d, 0xa4, 0xbd, 0x01, 0xc2, + 0xf2, 0x77, 0xd3, 0x50, 0x0c, 0xde, 0x25, 0x7c, 0x9e, 0x74, 0x5b, 0x2e, 0xc5, 0x6d, 0xe1, 0x15, + 0x38, 0xff, 0x8d, 0x56, 0xe0, 0xe9, 0xb1, 0x57, 0xe0, 0x33, 0x50, 0x64, 0x0f, 0xba, 0x8b, 0x0f, + 0xc5, 0x8a, 0x5a, 0x60, 0x04, 0x0d, 0x1f, 0x0e, 0xc2, 0x70, 0x76, 0xa2, 0x30, 0x8c, 0x81, 0x3a, + 0x73, 0x71, 0x50, 0xe7, 0x41, 0xb0, 0x22, 0xf2, 0x45, 0xf4, 0xca, 0x10, 0xbd, 0xa9, 0x6b, 0x61, + 0x33, 0xba, 0x16, 0xf2, 0x75, 0xf5, 0xbd, 0x61, 0x5a, 0xbe, 0xb3, 0x90, 0xce, 0x3e, 0x87, 0x74, + 0xc2, 0xb1, 0x28, 0x32, 0xeb, 0x3d, 0x80, 0x20, 0x89, 0x48, 0x5c, 0xe7, 0xcc, 0x90, 0x31, 0x6a, + 0x21, 0x76, 0xaa, 0x36, 0x32, 0x35, 0x83, 0x73, 0x9f, 0xf1, 0xf2, 0x63, 0xc6, 0xa1, 0xcf, 0xff, + 0xcd, 0x84, 0xf2, 0x4b, 0xc6, 0x41, 0xc9, 0x83, 0x04, 0x98, 0x38, 0x61, 0x14, 0xdf, 0x8e, 0x62, + 0x89, 0x6f, 0x18, 0x75, 0x09, 0x28, 0x91, 0x55, 0x2e, 0x86, 0x2b, 0x5e, 0x73, 0xa8, 0xa7, 0x28, + 0x28, 0x75, 0xb6, 0x33, 0x38, 0xb4, 0x6c, 0xcb, 0x3b, 0xe2, 0xef, 0x67, 0xf9, 0xce, 0x40, 0x92, + 0xea, 0xec, 0xaa, 0x11, 0x7e, 0x6d, 0xf9, 0x7a, 0x9b, 0x98, 0x98, 0xc5, 0xf4, 0x8c, 0x56, 0xa0, + 0x84, 0x4d, 0x62, 0xe2, 0xc1, 0x97, 0x57, 0x78, 0xb3, 0x2f, 0xaf, 0x18, 0xfb, 0xf2, 0x4e, 0xc1, + 0xac, 0x8b, 0x0d, 0x8f, 0xd8, 0x62, 0x53, 0x2d, 0x5a, 0x74, 0x6a, 0x7a, 0xd8, 0xf3, 0x68, 0x4f, + 0xa2, 0x5c, 0x13, 0xcd, 0x50, 0x99, 0x39, 0x3f, 0xb2, 0xcc, 0x1c, 0x72, 0x00, 0x13, 0x2b, 0x33, + 0xcb, 0x23, 0xcb, 0xcc, 0x71, 0xce, 0x5f, 0x42, 0x85, 0xf6, 0xc2, 0x78, 0x85, 0x76, 0xb8, 0x2e, + 0x5d, 0x8c, 0xd4, 0xa5, 0xdf, 0xe6, 0xc7, 0xfa, 0x1b, 0x05, 0x56, 0x12, 0x9f, 0x95, 0xf8, 0x5c, + 0xef, 0xc4, 0x8e, 0x72, 0xd6, 0x46, 0xfa, 0x2c, 0x38, 0xc9, 0x79, 0x12, 0x39, 0xc9, 0xf9, 0x60, + 0xb4, 0xe0, 0x5b, 0x3f, 0xc8, 0xf9, 0x33, 0x05, 0xce, 0xef, 0x3b, 0x66, 0xac, 0xc2, 0x13, 0xdb, + 0xfe, 0xf1, 0x13, 0xc7, 0x03, 0x59, 0xeb, 0xe7, 0x26, 0xc5, 0x59, 0xb8, 0x9c, 0xaa, 0xc2, 0x85, + 0x6c, 0x33, 0x44, 0xc9, 0xf4, 0x63, 0x58, 0xdc, 0x7e, 0x8d, 0xdb, 0xad, 0x63, 0xbb, 0x3d, 0x81, + 0x69, 0x15, 0xc8, 0xb7, 0x7b, 0xa6, 0xc0, 0x36, 0xe9, 0x63, 0xb8, 0x0a, 0xcc, 0x47, 0xab, 0x40, + 0x1d, 0x2a, 0x83, 0x1e, 0xc4, 0xf4, 0x9e, 0xa2, 0xd3, 0x6b, 0x52, 0x66, 0xaa, 0x7c, 0x5e, 0x13, + 0x2d, 0x41, 0xc7, 0xae, 0xcb, 0xc6, 0xcc, 0xe9, 0xd8, 0x75, 0xa3, 0xd9, 0x22, 0x1f, 0xcd, 0x16, + 0xea, 0xcf, 0x15, 0x28, 0xd1, 0x1e, 0xbe, 0x91, 0xfd, 0x62, 0xab, 0x95, 0x1f, 0x6c, 0xb5, 0x82, + 0x1d, 0xdb, 0x74, 0x78, 0xc7, 0x36, 0xb0, 0x7c, 0x86, 0x91, 0x93, 0x96, 0xcf, 0x06, 0x74, 0xec, + 0xba, 0xea, 0x05, 0x98, 0xe7, 0xb6, 0x89, 0x91, 0x57, 0x20, 0xdf, 0x77, 0xbb, 0x32, 0x8e, 0xfa, + 0x6e, 0x57, 0xfd, 0x73, 0x05, 0xca, 0x75, 0xdf, 0x37, 0xda, 0x47, 0x13, 0x0c, 0x20, 0x30, 0x2e, + 0x17, 0x36, 0x2e, 0x39, 0x88, 0x81, 0xb9, 0xd3, 0x19, 0xe6, 0xce, 0x44, 0xcc, 0x55, 0x61, 0x41, + 0xda, 0x92, 0x69, 0x70, 0x13, 0xd0, 0x2e, 0x71, 0xfd, 0xc7, 0xc4, 0x7d, 0x65, 0xb8, 0xe6, 0x64, + 0x3b, 0x30, 0x04, 0xd3, 0xe2, 0xfa, 0x69, 0xfe, 0xea, 0x8c, 0xc6, 0x9e, 0xd5, 0x2b, 0x70, 0x22, + 0xa2, 0x2f, 0xb3, 0xe3, 0x87, 0x50, 0x62, 0x79, 0x5f, 0x94, 0xe2, 0xb7, 0xc2, 0x87, 0x2c, 0x63, + 0xad, 0x12, 0xea, 0x1f, 0xc2, 0x12, 0xad, 0x0f, 0x18, 0x3d, 0xf8, 0x14, 0xbf, 0x1f, 0xab, 0x53, + 0xcf, 0x65, 0x28, 0x8a, 0xd5, 0xa8, 0x7f, 0xaf, 0xc0, 0x0c, 0xa3, 0x27, 0xd6, 0xec, 0x33, 0x50, + 0x74, 0xb1, 0x43, 0x74, 0xdf, 0xe8, 0x04, 0x97, 0x7d, 0x29, 0x61, 0xcf, 0xe8, 0x78, 0xec, 0xae, + 0x32, 0x7d, 0x69, 0x5a, 0x1d, 0xec, 0xf9, 0xf2, 0xc6, 0x6f, 0x89, 0xd2, 0xb6, 0x38, 0x89, 0x3a, + 0xc9, 0xb3, 0xfe, 0x98, 0xd7, 0x9d, 0xd3, 0x1a, 0x7b, 0x46, 0xeb, 0xfc, 0xfe, 0xd9, 0x38, 0x40, + 0x38, 0xbb, 0x9d, 0x56, 0x83, 0x42, 0x0c, 0xfb, 0x0e, 0xda, 0xea, 0x36, 0xa0, 0xb0, 0x17, 0x84, + 0xbf, 0x6f, 0xc2, 0x2c, 0x73, 0x92, 0xac, 0x8e, 0x56, 0x32, 0xdc, 0xa0, 0x09, 0x36, 0xd5, 0x00, + 0xc4, 0x1d, 0x1c, 0xa9, 0x88, 0x26, 0x9f, 0x95, 0x21, 0x15, 0xd2, 0x3f, 0x2a, 0x70, 0x22, 0xd2, + 0x87, 0xb0, 0xf5, 0x46, 0xb4, 0x93, 0x4c, 0x53, 0x45, 0x07, 0x9b, 0x91, 0x25, 0xe1, 0x66, 0x96, + 0x49, 0xbf, 0xa5, 0xe5, 0xe0, 0x9f, 0x14, 0x80, 0x7a, 0xdf, 0x3f, 0x12, 0xc8, 0x60, 0x78, 0x66, + 0x94, 0xe8, 0xcc, 0xd0, 0x77, 0x8e, 0xe1, 0x79, 0xaf, 0x88, 0x2b, 0xf7, 0x34, 0x41, 0x9b, 0x61, + 0x78, 0x7d, 0xff, 0x48, 0x1e, 0x60, 0xd1, 0x67, 0x74, 0x09, 0x16, 0xf8, 0x05, 0x73, 0xdd, 0x30, + 0x4d, 0x17, 0x7b, 0x9e, 0x38, 0xc9, 0x2a, 0x73, 0x6a, 0x9d, 0x13, 0x29, 0x9b, 0x65, 0x62, 0xdb, + 0xb7, 0xfc, 0x63, 0xdd, 0x27, 0x2f, 0xb0, 0x2d, 0xf6, 0x26, 0x65, 0x49, 0xdd, 0xa3, 0x44, 0xca, + 0xe6, 0xe2, 0x8e, 0xe5, 0xf9, 0xae, 0x64, 0x93, 0xa7, 0x26, 0x82, 0xca, 0xd8, 0xe8, 0xa4, 0x54, + 0x76, 0xfb, 0xdd, 0x2e, 0x77, 0xf1, 0x9b, 0x4f, 0xfb, 0xfb, 0x62, 0x40, 0xb9, 0xac, 0x98, 0x1e, + 0x38, 0x4d, 0x0c, 0xf7, 0x2d, 0x82, 0x30, 0xef, 0xc3, 0x52, 0x68, 0x0c, 0x22, 0xac, 0x22, 0x45, + 0xa4, 0x12, 0x2d, 0x22, 0xd5, 0x27, 0x80, 0x38, 0xee, 0xf0, 0x0d, 0xc7, 0xad, 0x9e, 0x84, 0x13, + 0x11, 0x45, 0x62, 0x25, 0xbe, 0x0e, 0x65, 0x71, 0x9b, 0x48, 0x04, 0xca, 0x69, 0x28, 0xd0, 0x8c, + 0xda, 0xb6, 0x4c, 0x79, 0xba, 0x39, 0xe7, 0x10, 0x73, 0xd3, 0x32, 0x5d, 0xf5, 0x13, 0x28, 0x6b, + 0xbc, 0x1f, 0xc1, 0xfb, 0x18, 0x16, 0xc4, 0xdd, 0x23, 0x3d, 0x72, 0xa7, 0x2f, 0xed, 0xce, 0x78, + 0xb8, 0x13, 0xad, 0x6c, 0x87, 0x9b, 0xaa, 0x09, 0x35, 0x5e, 0x32, 0x44, 0xd4, 0xcb, 0xc1, 0x3e, + 0x06, 0xf9, 0x6b, 0x89, 0x91, 0xbd, 0x44, 0xe5, 0xcb, 0x6e, 0xb8, 0xa9, 0x9e, 0x83, 0x33, 0xa9, + 0xbd, 0x08, 0x4f, 0x38, 0x50, 0x19, 0xbc, 0x30, 0x2d, 0x79, 0xcc, 0xcb, 0x8e, 0x6f, 0x95, 0xd0, + 0xf1, 0xed, 0xa9, 0xa0, 0x48, 0xcc, 0xc9, 0x45, 0x8c, 0x55, 0x80, 0x83, 0x72, 0x3f, 0x9f, 0x55, + 0xee, 0x4f, 0x47, 0xca, 0x7d, 0xb5, 0x15, 0xf8, 0x53, 0x6c, 0xc3, 0x1e, 0xb1, 0xed, 0x22, 0xef, + 0x5b, 0x26, 0x44, 0x75, 0xd8, 0x28, 0x39, 0xab, 0x16, 0x92, 0x52, 0xaf, 0x41, 0x39, 0x9a, 0x1a, + 0x43, 0x79, 0x4e, 0x49, 0xe4, 0xb9, 0x85, 0x58, 0x8a, 0xfb, 0x30, 0x56, 0x01, 0x67, 0xfb, 0x38, + 0x56, 0xff, 0xde, 0x8f, 0x24, 0xbb, 0xeb, 0x29, 0x27, 0xaf, 0xbf, 0xa5, 0x3c, 0xb7, 0x2c, 0xd6, + 0x83, 0xc7, 0x1e, 0x95, 0x17, 0x83, 0x56, 0x2f, 0x42, 0x69, 0x3f, 0xeb, 0x07, 0x09, 0xd3, 0xf2, + 0x96, 0xc3, 0x6d, 0x58, 0x7e, 0x6c, 0x75, 0xb1, 0x77, 0xec, 0xf9, 0xb8, 0xd7, 0x60, 0x49, 0xe9, + 0xd0, 0xc2, 0x2e, 0x5a, 0x05, 0x60, 0x5b, 0x18, 0x87, 0x58, 0xc1, 0x3d, 0xf5, 0x10, 0x45, 0xfd, + 0x6f, 0x05, 0x16, 0x07, 0x82, 0xfb, 0x6c, 0xeb, 0x76, 0x16, 0x8a, 0x74, 0xbc, 0x9e, 0x6f, 0xf4, + 0x1c, 0x79, 0x9e, 0x15, 0x10, 0xd0, 0x3d, 0x98, 0x39, 0xf4, 0x24, 0x64, 0x94, 0x0a, 0xa0, 0xa7, + 0x19, 0xa2, 0x4d, 0x1f, 0x7a, 0x0d, 0x13, 0x7d, 0x04, 0xd0, 0xf7, 0xb0, 0x29, 0xce, 0xb0, 0xf2, + 0x59, 0xd5, 0xc2, 0x7e, 0xf8, 0x54, 0x9a, 0x0a, 0xf0, 0x0b, 0x12, 0xf7, 0xa1, 0x64, 0xd9, 0xc4, + 0xc4, 0xec, 0xcc, 0xd1, 0x14, 0xa8, 0xd2, 0x08, 0x71, 0xe0, 0x12, 0xfb, 0x1e, 0x36, 0x55, 0x2c, + 0xd6, 0x42, 0xe9, 0x5f, 0x11, 0x28, 0x4d, 0x58, 0xe2, 0x49, 0xeb, 0x30, 0x30, 0x5c, 0x46, 0xec, + 0xda, 0xb0, 0xd1, 0x31, 0x6f, 0x69, 0x15, 0x4b, 0x94, 0x36, 0x52, 0x54, 0xbd, 0x0b, 0x27, 0x23, + 0x3b, 0xa4, 0x09, 0xb6, 0x2c, 0xea, 0x6e, 0x0c, 0x28, 0x19, 0x84, 0xb3, 0x80, 0x21, 0x64, 0x34, + 0x8f, 0x82, 0x21, 0x3c, 0x0e, 0x43, 0x78, 0xea, 0xe7, 0x70, 0x3a, 0x82, 0xe8, 0x44, 0x2c, 0xba, + 0x1f, 0xab, 0xdc, 0x2e, 0x8f, 0xd2, 0x1a, 0x2b, 0xe1, 0xfe, 0x57, 0x81, 0xe5, 0x34, 0x86, 0x37, + 0x44, 0x1c, 0x7f, 0x9c, 0x71, 0x19, 0xee, 0xce, 0x78, 0x66, 0xfd, 0x4e, 0xd0, 0xda, 0x3d, 0xa8, + 0xa5, 0xf9, 0x33, 0x39, 0x4b, 0xf9, 0x49, 0x66, 0xe9, 0x67, 0xf9, 0x10, 0xf2, 0x5e, 0xf7, 0x7d, + 0xd7, 0x3a, 0xe8, 0xd3, 0x90, 0x7f, 0xeb, 0x68, 0x56, 0x23, 0xc0, 0x65, 0xb8, 0x6b, 0x6f, 0x0d, + 0x11, 0x1f, 0xd8, 0x91, 0x8a, 0xcd, 0x7c, 0x1a, 0xc5, 0x66, 0x38, 0xa6, 0x7e, 0x7b, 0x3c, 0x7d, + 0xdf, 0x59, 0x00, 0xf4, 0x67, 0x39, 0x58, 0x88, 0x4e, 0x11, 0xda, 0x06, 0x30, 0x02, 0xcb, 0xc5, + 0x87, 0x72, 0x69, 0xac, 0x61, 0x6a, 0x21, 0x41, 0xf4, 0x1e, 0xe4, 0xdb, 0x4e, 0x5f, 0xcc, 0x5a, + 0xca, 0x61, 0xf0, 0xa6, 0xd3, 0xe7, 0x19, 0x85, 0xb2, 0xd1, 0x3d, 0x15, 0x3f, 0xdb, 0xcf, 0xce, + 0x92, 0xcf, 0xd9, 0x7b, 0x2e, 0x23, 0x98, 0xd1, 0x53, 0x58, 0x78, 0xe5, 0x5a, 0xbe, 0x71, 0xd0, + 0xc5, 0x7a, 0xd7, 0x38, 0xc6, 0xae, 0xc8, 0x92, 0x63, 0x24, 0xb2, 0xb2, 0x14, 0x7c, 0x46, 0xe5, + 0xd4, 0x3f, 0x81, 0x82, 0xb4, 0x68, 0xc4, 0x8a, 0xb0, 0x07, 0x2b, 0x7d, 0xca, 0xa6, 0xb3, 0x8b, + 0x6b, 0xb6, 0x61, 0x13, 0xdd, 0xc3, 0x74, 0x19, 0x97, 0x57, 0xea, 0x47, 0xa4, 0xe8, 0x65, 0x26, + 0xbd, 0x49, 0x5c, 0xdc, 0x34, 0x6c, 0xd2, 0xe2, 0xa2, 0xea, 0x4b, 0x28, 0x85, 0x06, 0x38, 0xc2, + 0x84, 0x06, 0x2c, 0xc9, 0xa3, 0x78, 0x0f, 0xfb, 0x62, 0x79, 0x19, 0xab, 0xf3, 0x45, 0x21, 0xd7, + 0xc2, 0x3e, 0xbf, 0x3e, 0x71, 0x1f, 0x4e, 0x6b, 0x98, 0x38, 0xd8, 0x0e, 0xe6, 0xf3, 0x19, 0xe9, + 0x4c, 0x90, 0xc1, 0xcf, 0x42, 0x2d, 0x4d, 0x9e, 0xe7, 0x87, 0xeb, 0x67, 0xa1, 0x20, 0x7f, 0x5d, + 0x8a, 0xe6, 0x20, 0xbf, 0xb7, 0xb9, 0x5b, 0x99, 0xa2, 0x0f, 0xfb, 0x5b, 0xbb, 0x15, 0xe5, 0x7a, + 0x0f, 0x2a, 0xf1, 0x1f, 0x54, 0xa2, 0x15, 0x38, 0xb1, 0xab, 0xed, 0xec, 0xd6, 0x9f, 0xd4, 0xf7, + 0x1a, 0x3b, 0x4d, 0x7d, 0x57, 0x6b, 0x7c, 0x5c, 0xdf, 0xdb, 0xae, 0x4c, 0xa1, 0x35, 0x38, 0x17, + 0x7e, 0xf1, 0x74, 0xa7, 0xb5, 0xa7, 0xef, 0xed, 0xe8, 0x9b, 0x3b, 0xcd, 0xbd, 0x7a, 0xa3, 0xb9, + 0xad, 0x55, 0x14, 0x74, 0x0e, 0x4e, 0x87, 0x59, 0x1e, 0x35, 0xb6, 0x1a, 0xda, 0xf6, 0x26, 0x7d, + 0xae, 0x3f, 0xab, 0xe4, 0xae, 0xdf, 0x82, 0x72, 0xe4, 0xf7, 0x8f, 0xd4, 0x90, 0xdd, 0x9d, 0xad, + 0xca, 0x14, 0x2a, 0x43, 0x31, 0xac, 0xa7, 0x00, 0xd3, 0xcd, 0x9d, 0xad, 0xed, 0x4a, 0xee, 0xfa, + 0x5d, 0x58, 0x8c, 0xdd, 0x9c, 0x45, 0x4b, 0x50, 0x6e, 0xd5, 0x9b, 0x5b, 0x8f, 0x76, 0x3e, 0xd5, + 0xb5, 0xed, 0xfa, 0xd6, 0x67, 0x95, 0x29, 0xb4, 0x0c, 0x15, 0x49, 0x6a, 0xee, 0xec, 0x71, 0xaa, + 0x72, 0xfd, 0x45, 0xec, 0xcb, 0xc2, 0xe8, 0x24, 0x2c, 0x05, 0xdd, 0xe8, 0x9b, 0xda, 0x76, 0x7d, + 0x6f, 0x9b, 0xf6, 0x1e, 0x21, 0x6b, 0xfb, 0xcd, 0x66, 0xa3, 0xf9, 0xa4, 0xa2, 0x50, 0xad, 0x03, + 0xf2, 0xf6, 0xa7, 0x0d, 0xca, 0x9c, 0x8b, 0x32, 0xef, 0x37, 0x7f, 0xd8, 0xdc, 0xf9, 0xa4, 0x59, + 0xc9, 0x6f, 0xfc, 0x72, 0x09, 0x16, 0x64, 0x79, 0x87, 0x5d, 0x76, 0x97, 0x65, 0x17, 0xe6, 0xe4, + 0x6f, 0x94, 0x53, 0xf2, 0x72, 0xf4, 0x97, 0xd5, 0xb5, 0xb5, 0x21, 0x1c, 0xa2, 0xca, 0x9e, 0x42, + 0x07, 0xac, 0xea, 0x0d, 0xdd, 0x64, 0xbe, 0x9c, 0x5a, 0x63, 0x26, 0x2e, 0x4f, 0xd7, 0xae, 0x8c, + 0xe4, 0x0b, 0xfa, 0xc0, 0xb4, 0xb0, 0x0d, 0xff, 0x54, 0x07, 0x5d, 0x49, 0xab, 0x48, 0x53, 0x7e, + 0x0b, 0x54, 0xbb, 0x3a, 0x9a, 0x31, 0xe8, 0xe6, 0x05, 0x54, 0xe2, 0x3f, 0xdb, 0x41, 0x29, 0x80, + 0x69, 0xc6, 0x6f, 0x83, 0x6a, 0xd7, 0xc7, 0x61, 0x0d, 0x77, 0x96, 0xf8, 0x81, 0xcb, 0xb5, 0x71, + 0x7e, 0x31, 0x90, 0xd9, 0x59, 0xd6, 0x8f, 0x0b, 0xb8, 0x03, 0xa3, 0xb7, 0x94, 0x51, 0xea, 0xaf, + 0x49, 0x52, 0xee, 0xb8, 0xa7, 0x39, 0x30, 0xfd, 0xc2, 0xb3, 0x3a, 0x85, 0x8e, 0x60, 0x31, 0x76, + 0x29, 0x01, 0xa5, 0x88, 0xa7, 0xdf, 0xbe, 0xa8, 0x5d, 0x1b, 0x83, 0x33, 0x1a, 0x11, 0xe1, 0x4b, + 0x08, 0xe9, 0x11, 0x91, 0x72, 0xc5, 0x21, 0x3d, 0x22, 0x52, 0xef, 0x33, 0xb0, 0xe0, 0x8e, 0x5c, + 0x3e, 0x48, 0x0b, 0xee, 0xb4, 0x2b, 0x0f, 0xb5, 0x2b, 0x23, 0xf9, 0xc2, 0x4e, 0x8b, 0x5d, 0x45, + 0x48, 0x73, 0x5a, 0xfa, 0x55, 0x87, 0xda, 0xb5, 0x31, 0x38, 0xe3, 0x51, 0x30, 0x38, 0xd8, 0xcc, + 0x8a, 0x82, 0xc4, 0x31, 0x7c, 0x56, 0x14, 0x24, 0xcf, 0x48, 0x45, 0x14, 0xc4, 0x0e, 0x24, 0xaf, + 0x8e, 0x71, 0x80, 0x92, 0x1d, 0x05, 0xe9, 0x47, 0x2d, 0xea, 0x14, 0xfa, 0x53, 0x05, 0xaa, 0x59, + 0x87, 0x13, 0x28, 0xa5, 0xaa, 0x1b, 0x71, 0x9e, 0x52, 0xdb, 0x98, 0x44, 0x24, 0xb0, 0xe2, 0x4b, + 0x40, 0xc9, 0xd5, 0x0e, 0xbd, 0x9b, 0x36, 0x33, 0x19, 0x6b, 0x6a, 0xed, 0xbd, 0xf1, 0x98, 0x83, + 0x2e, 0x5b, 0x50, 0x90, 0xc7, 0x21, 0x28, 0x25, 0x4b, 0xc7, 0x0e, 0x63, 0x6a, 0xea, 0x30, 0x96, + 0x40, 0xe9, 0x13, 0x98, 0xa6, 0x54, 0x74, 0x2e, 0x9d, 0x5b, 0x2a, 0x5b, 0xcd, 0x7a, 0x1d, 0x28, + 0x7a, 0x0e, 0xb3, 0x1c, 0xff, 0x47, 0x29, 0x78, 0x43, 0xe4, 0x94, 0xa2, 0x76, 0x21, 0x9b, 0x21, + 0x50, 0xf7, 0x05, 0xff, 0xf7, 0x15, 0x02, 0xda, 0x47, 0xef, 0xa4, 0xff, 0x1e, 0x38, 0x7a, 0x92, + 0x50, 0xbb, 0x34, 0x82, 0x2b, 0xfc, 0x51, 0xc4, 0x6a, 0xdd, 0x2b, 0x23, 0x37, 0x2c, 0xd9, 0x1f, + 0x45, 0xfa, 0x96, 0x88, 0x07, 0x49, 0x72, 0xcb, 0x94, 0x16, 0x24, 0x99, 0x1b, 0xd5, 0xb4, 0x20, + 0xc9, 0xde, 0x85, 0xa9, 0x53, 0xc8, 0x87, 0x13, 0x29, 0x00, 0x19, 0x7a, 0x2f, 0x2b, 0xc8, 0xd3, + 0xd0, 0xba, 0xda, 0x8d, 0x31, 0xb9, 0xc3, 0x93, 0x2f, 0x3e, 0xfa, 0xf3, 0xd9, 0xa8, 0x51, 0xe6, + 0xe4, 0xc7, 0x3f, 0xf1, 0x8d, 0x7f, 0xcf, 0xc3, 0x3c, 0x07, 0x3f, 0x45, 0x05, 0xf3, 0x19, 0xc0, + 0xe0, 0xdc, 0x01, 0x5d, 0x4c, 0xf7, 0x49, 0xe4, 0x6c, 0xa6, 0xf6, 0xce, 0x70, 0xa6, 0x70, 0xa0, + 0x85, 0x30, 0xfc, 0xb4, 0x40, 0x4b, 0x1e, 0x55, 0xa4, 0x05, 0x5a, 0xca, 0x41, 0x80, 0x3a, 0x85, + 0x3e, 0x86, 0x62, 0x00, 0x16, 0xa3, 0x34, 0xb0, 0x39, 0x86, 0x86, 0xd7, 0x2e, 0x0e, 0xe5, 0x09, + 0x5b, 0x1d, 0x42, 0x82, 0xd3, 0xac, 0x4e, 0x22, 0xce, 0x69, 0x56, 0xa7, 0xc1, 0xc9, 0x03, 0x9f, + 0x70, 0xbc, 0x28, 0xd3, 0x27, 0x11, 0xb8, 0x2e, 0xd3, 0x27, 0x51, 0xd0, 0x49, 0x9d, 0x7a, 0x74, + 0xf9, 0xd7, 0x5f, 0xad, 0x2a, 0xff, 0xf2, 0xd5, 0xea, 0xd4, 0x4f, 0xbf, 0x5e, 0x55, 0x7e, 0xfd, + 0xf5, 0xaa, 0xf2, 0xcf, 0x5f, 0xaf, 0x2a, 0xff, 0xf1, 0xf5, 0xaa, 0xf2, 0x97, 0xff, 0xb9, 0x3a, + 0xf5, 0xa3, 0x82, 0x94, 0x3e, 0x98, 0x65, 0xff, 0x84, 0xe6, 0x83, 0xff, 0x0f, 0x00, 0x00, 0xff, + 0xff, 0xb5, 0x80, 0xdd, 0xf4, 0x4a, 0x48, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto index 382f18138..ab4351374 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto @@ -171,7 +171,9 @@ enum MountPropagation { message Mount { // Path of the mount within the container. string container_path = 1; - // Path of the mount on the host. + // Path of the mount on the host. If the hostPath doesn't exist, then runtimes + // should report error. If the hostpath is a symbolic link, runtimes should + // follow the symlink and mount the real destination to container. string host_path = 2; // If set, the mount is read-only. bool readonly = 3; @@ -235,7 +237,8 @@ message LinuxSandboxSecurityContext { SELinuxOption selinux_options = 2; // UID to run sandbox processes as, when applicable. Int64Value run_as_user = 3; - // GID to run sandbox processes as, when applicable. + // GID to run sandbox processes as, when applicable. run_as_group should only + // be specified when run_as_user is specified; otherwise, the runtime MUST error. Int64Value run_as_group = 8; // If set, the root filesystem of the sandbox is read-only. bool readonly_rootfs = 4; @@ -249,7 +252,7 @@ message LinuxSandboxSecurityContext { // privileged containers are expected to be run. bool privileged = 6; // Seccomp profile for the sandbox, candidate values are: - // * docker/default: the default profile for the docker container runtime + // * runtime/default: the default profile for the container runtime // * unconfined: unconfined profile, ie, no seccomp sandboxing // * localhost/: the profile installed on the node. // is the full path of the profile. @@ -304,7 +307,7 @@ message PodSandboxConfig { // structured logs, systemd-journald journal files, gRPC trace files, etc. // E.g., // PodSandboxConfig.LogDirectory = `/var/log/pods//` - // ContainerConfig.LogPath = `containerName_Instance#.log` + // ContainerConfig.LogPath = `containerName/Instance#.log` // // WARNING: Log management and how kubelet should interface with the // container logs are under active discussion in @@ -553,8 +556,9 @@ message LinuxContainerSecurityContext { // UID to run the container process as. Only one of run_as_user and // run_as_username can be specified at a time. Int64Value run_as_user = 5; - // GID to run the container process as. Only one of run_as_group and - // run_as_groupname can be specified at a time. + // GID to run the container process as. run_as_group should only be specified + // when run_as_user or run_as_username is specified; otherwise, the runtime + // MUST error. Int64Value run_as_group = 12; // User name to run the container process as. If specified, the user MUST // exist in the container image (i.e. in the /etc/passwd inside the image), @@ -573,7 +577,7 @@ message LinuxContainerSecurityContext { // http://wiki.apparmor.net/index.php/AppArmor_Core_Policy_Reference string apparmor_profile = 9; // Seccomp profile for the container, candidate values are: - // * docker/default: the default profile for the docker container runtime + // * runtime/default: the default profile for the container runtime // * unconfined: unconfined profile, ie, no seccomp sandboxing // * localhost/: the profile installed on the node. // is the full path of the profile. @@ -593,11 +597,21 @@ message LinuxContainerConfig { LinuxContainerSecurityContext security_context = 2; } +// WindowsContainerSecurityContext holds windows security configuration that will be applied to a container. +message WindowsContainerSecurityContext { + // User name to run the container process as. If specified, the user MUST + // exist in the container image and be resolved there by the runtime; + // otherwise, the runtime MUST return error. + string run_as_username = 1; +} + // WindowsContainerConfig contains platform-specific configuration for // Windows-based containers. message WindowsContainerConfig { // Resources specification for the container. WindowsContainerResources resources = 1; + // WindowsContainerSecurityContext configuration for the container. + WindowsContainerSecurityContext security_context = 2; } // WindowsContainerResources specifies Windows specific configuration for @@ -682,7 +696,7 @@ message ContainerConfig { // the log (STDOUT and STDERR) on the host. // E.g., // PodSandboxConfig.LogDirectory = `/var/log/pods//` - // ContainerConfig.LogPath = `containerName_Instance#.log` + // ContainerConfig.LogPath = `containerName/Instance#.log` // // WARNING: Log management and how kubelet should interface with the // container logs are under active discussion in @@ -1043,7 +1057,8 @@ message RemoveImageRequest { message RemoveImageResponse {} message NetworkConfig { - // CIDR to use for pod IP addresses. + // CIDR to use for pod IP addresses. If the CIDR is empty, runtimes + // should omit it. string pod_cidr = 1; } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1alpha/api.pb.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1alpha/api.pb.go index 0735b4328..75fbbfeea 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1alpha/api.pb.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1alpha/api.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1/api.pb.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1/api.pb.go index dc6d68efd..2aeb99f3b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1/api.pb.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1/api.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/BUILD index 0aa5579dd..969efbc99 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/BUILD @@ -17,6 +17,7 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig", deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/fuzzer/fuzzer.go index 857646d07..d55d8ee9a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/fuzzer/fuzzer.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/fuzzer/fuzzer.go @@ -63,6 +63,9 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { obj.NodeStatusUpdateFrequency = metav1.Duration{Duration: 10 * time.Second} obj.CPUManagerPolicy = "none" obj.CPUManagerReconcilePeriod = obj.NodeStatusUpdateFrequency + obj.QOSReserved = map[string]string{ + "memory": "50%", + } obj.OOMScoreAdj = int32(qos.KubeletOOMScoreAdj) obj.Port = ports.KubeletPort obj.ReadOnlyPort = ports.KubeletReadOnlyPort diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/helpers_test.go index 6c8602b22..929ac0042 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/helpers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/helpers_test.go @@ -147,6 +147,7 @@ var ( "CPUCFSQuota", "CPUManagerPolicy", "CPUManagerReconcilePeriod.Duration", + "QOSReserved[*]", "CgroupDriver", "CgroupRoot", "CgroupsPerQOS", @@ -187,6 +188,8 @@ var ( "KubeReserved[*]", "KubeletCgroups", "MakeIPTablesUtilChains", + "RotateCertificates", + "ServerTLSBootstrap", "StaticPodURL", "StaticPodURLHeader[*][*]", "MaxOpenFiles", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/register.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/register.go index fd5d5de5f..886f39dec 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/register.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/register.go @@ -46,6 +46,7 @@ func addKnownTypes(scheme *runtime.Scheme) error { // TODO this will get cleaned up with the scheme types are fixed scheme.AddKnownTypes(SchemeGroupVersion, &KubeletConfiguration{}, + &SerializedNodeConfigSource{}, ) return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/types.go index b593c2c25..4b220981f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/types.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/types.go @@ -17,6 +17,7 @@ limitations under the License. package kubeletconfig import ( + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -81,6 +82,17 @@ type KubeletConfiguration struct { // TLSMinVersion is the minimum TLS version supported. // Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). TLSMinVersion string + // rotateCertificates enables client certificate rotation. The Kubelet will request a + // new certificate from the certificates.k8s.io API. This requires an approver to approve the + // certificate signing requests. The RotateKubeletClientCertificate feature + // must be enabled. + RotateCertificates bool + // serverTLSBootstrap enables server certificate bootstrap. Instead of self + // signing a serving certificate, the Kubelet will request a certificate from + // the certificates.k8s.io API. This requires an approver to approve the + // certificate signing requests. The RotateKubeletServerCertificate feature + // must be enabled. + ServerTLSBootstrap bool // authentication specifies how requests to the Kubelet's server are authenticated Authentication KubeletAuthentication // authorization specifies how requests to the Kubelet's server are authorized @@ -160,6 +172,9 @@ type KubeletConfiguration struct { // CPU Manager reconciliation period. // Requires the CPUManager feature gate to be enabled. CPUManagerReconcilePeriod metav1.Duration + // Map of QoS resource reservation percentages (memory only for now). + // Requires the QOSReserved feature gate to be enabled. + QOSReserved map[string]string // runtimeRequestTimeout is the timeout for all runtime requests except long running // requests - pull, logs, exec and attach. RuntimeRequestTimeout metav1.Duration @@ -245,7 +260,7 @@ type KubeletConfiguration struct { // Maximum number of container log files that can be present for a container. ContainerLogMaxFiles int32 - /* following flags are meant for Node Allocatable */ + /* the following fields are meant for Node Allocatable */ // A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G) pairs // that describe resources reserved for non-kubernetes components. @@ -324,3 +339,15 @@ type KubeletAnonymousAuthentication struct { // Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated. Enabled bool } + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// SerializedNodeConfigSource allows us to serialize NodeConfigSource +// This type is used internally by the Kubelet for tracking checkpointed dynamic configs. +// It exists in the kubeletconfig API group because it is classified as a versioned input to the Kubelet. +type SerializedNodeConfigSource struct { + metav1.TypeMeta + // Source is the source that we are serializing + // +optional + Source v1.NodeConfigSource +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/BUILD index e54e8b0a3..c45da80cf 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/BUILD @@ -23,6 +23,7 @@ go_library( "//pkg/kubelet/types:go_default_library", "//pkg/master/ports:go_default_library", "//pkg/util/pointer:go_default_library", + "//vendor/k8s.io/api/core/v1: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/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/register.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/register.go index 306fc55e0..4c6b2931b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/register.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/register.go @@ -45,6 +45,7 @@ func init() { func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &KubeletConfiguration{}, + &SerializedNodeConfigSource{}, ) return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/types.go index fd46f3c9d..2ec949efe 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/types.go @@ -17,6 +17,7 @@ limitations under the License. package v1beta1 import ( + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -46,68 +47,124 @@ type KubeletConfiguration struct { // staticPodPath is the path to the directory containing local (static) pods to // run, or the path to a single static pod file. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // the set of static pods specified at the new path may be different than the + // ones the Kubelet initially started with, and this may disrupt your node. // Default: "" // +optional StaticPodPath string `json:"staticPodPath,omitempty"` // syncFrequency is the max period between synchronizing running // containers and config. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening this duration may have a negative performance impact, especially + // as the number of Pods on the node increases. Alternatively, increasing this + // duration will result in longer refresh times for ConfigMaps and Secrets. // Default: "1m" // +optional SyncFrequency metav1.Duration `json:"syncFrequency,omitempty"` // fileCheckFrequency is the duration between checking config files for // new data + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening the duration will cause the Kubelet to reload local Static Pod + // configurations more frequently, which may have a negative performance impact. // Default: "20s" // +optional FileCheckFrequency metav1.Duration `json:"fileCheckFrequency,omitempty"` // httpCheckFrequency is the duration between checking http for new data + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening the duration will cause the Kubelet to poll staticPodURL more + // frequently, which may have a negative performance impact. // Default: "20s" // +optional HTTPCheckFrequency metav1.Duration `json:"httpCheckFrequency,omitempty"` // staticPodURL is the URL for accessing static pods to run + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // the set of static pods specified at the new URL may be different than the + // ones the Kubelet initially started with, and this may disrupt your node. // Default: "" // +optional StaticPodURL string `json:"staticPodURL,omitempty"` // staticPodURLHeader is a map of slices with HTTP headers to use when accessing the podURL + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt the ability to read the latest set of static pods from StaticPodURL. // Default: nil // +optional StaticPodURLHeader map[string][]string `json:"staticPodURLHeader,omitempty"` // address is the IP address for the Kubelet to serve on (set to 0.0.0.0 // for all interfaces). + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "0.0.0.0" // +optional Address string `json:"address,omitempty"` // port is the port for the Kubelet to serve on. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: 10250 // +optional Port int32 `json:"port,omitempty"` // readOnlyPort is the read-only port for the Kubelet to serve on with // no authentication/authorization. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: 0 (disabled) // +optional ReadOnlyPort int32 `json:"readOnlyPort,omitempty"` - // tlsCertFile is the file containing x509 Certificate for HTTPS. (CA cert, + // tlsCertFile is the file containing x509 Certificate for HTTPS. (CA cert, // if any, concatenated after server cert). If tlsCertFile and // tlsPrivateKeyFile are not provided, a self-signed certificate // and key are generated for the public address and saved to the directory // passed to the Kubelet's --cert-dir flag. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "" // +optional TLSCertFile string `json:"tlsCertFile,omitempty"` // tlsPrivateKeyFile is the file containing x509 private key matching tlsCertFile + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "" // +optional TLSPrivateKeyFile string `json:"tlsPrivateKeyFile,omitempty"` // TLSCipherSuites is the list of allowed cipher suites for the server. // Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: nil // +optional TLSCipherSuites []string `json:"tlsCipherSuites,omitempty"` // TLSMinVersion is the minimum TLS version supported. // Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "" // +optional TLSMinVersion string `json:"tlsMinVersion,omitempty"` + // rotateCertificates enables client certificate rotation. The Kubelet will request a + // new certificate from the certificates.k8s.io API. This requires an approver to approve the + // certificate signing requests. The RotateKubeletClientCertificate feature + // must be enabled. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it may disrupt the Kubelet's ability to authenticate with the API server + // after the current certificate expires. + // Default: false + // +optional + RotateCertificates bool `json:"rotateCertificates,omitempty"` + // serverTLSBootstrap enables server certificate bootstrap. Instead of self + // signing a serving certificate, the Kubelet will request a certificate from + // the certificates.k8s.io API. This requires an approver to approve the + // certificate signing requests. The RotateKubeletServerCertificate feature + // must be enabled. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it will stop the renewal of Kubelet server certificates, which can + // disrupt components that interact with the Kubelet server in the long term, + // due to certificate expiration. + // Default: false + // +optional + ServerTLSBootstrap bool `json:"serverTLSBootstrap,omitempty"` // authentication specifies how requests to the Kubelet's server are authenticated + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Defaults: // anonymous: // enabled: false @@ -117,6 +174,8 @@ type KubeletConfiguration struct { // +optional Authentication KubeletAuthentication `json:"authentication"` // authorization specifies how requests to the Kubelet's server are authorized + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Defaults: // mode: Webhook // webhook: @@ -126,131 +185,202 @@ type KubeletConfiguration struct { Authorization KubeletAuthorization `json:"authorization"` // registryPullQPS is the limit of registry pulls per second. // Set to 0 for no limit. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic produced + // by image pulls. // Default: 5 // +optional RegistryPullQPS *int32 `json:"registryPullQPS,omitempty"` // registryBurst is the maximum size of bursty pulls, temporarily allows // pulls to burst to this number, while still not exceeding registryPullQPS. // Only used if registryPullQPS > 0. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic produced + // by image pulls. // Default: 10 // +optional RegistryBurst int32 `json:"registryBurst,omitempty"` // eventRecordQPS is the maximum event creations per second. If 0, there // is no limit enforced. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic produced by + // event creations. // Default: 5 // +optional EventRecordQPS *int32 `json:"eventRecordQPS,omitempty"` // eventBurst is the maximum size of a burst of event creations, temporarily // allows event creations to burst to this number, while still not exceeding // eventRecordQPS. Only used if eventRecordQPS > 0. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic produced by + // event creations. // Default: 10 // +optional EventBurst int32 `json:"eventBurst,omitempty"` - // enableDebuggingHandlers enables server endpoints for log collection - // and local running of containers and commands + // enableDebuggingHandlers enables server endpoints for log access + // and local running of containers and commands, including the exec, + // attach, logs, and portforward features. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it may disrupt components that interact with the Kubelet server. // Default: true // +optional EnableDebuggingHandlers *bool `json:"enableDebuggingHandlers,omitempty"` // enableContentionProfiling enables lock contention profiling, if enableDebuggingHandlers is true. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // enabling it may carry a performance impact. // Default: false // +optional EnableContentionProfiling bool `json:"enableContentionProfiling,omitempty"` // healthzPort is the port of the localhost healthz endpoint (set to 0 to disable) + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that monitor Kubelet health. // Default: 10248 // +optional HealthzPort *int32 `json:"healthzPort,omitempty"` // healthzBindAddress is the IP address for the healthz server to serve on + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that monitor Kubelet health. // Default: "127.0.0.1" // +optional HealthzBindAddress string `json:"healthzBindAddress,omitempty"` // oomScoreAdj is The oom-score-adj value for kubelet process. Values // must be within the range [-1000, 1000]. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact the stability of nodes under memory pressure. // Default: -999 // +optional OOMScoreAdj *int32 `json:"oomScoreAdj,omitempty"` // clusterDomain is the DNS domain for this cluster. If set, kubelet will // configure all containers to search this domain in addition to the // host's search domains. + // Dynamic Kubelet Config (beta): Dynamically updating this field is not recommended, + // as it should be kept in sync with the rest of the cluster. // Default: "" // +optional ClusterDomain string `json:"clusterDomain,omitempty"` // clusterDNS is a list of IP addresses for the cluster DNS server. If set, // kubelet will configure all containers to use this for DNS resolution // instead of the host's DNS servers. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changes will only take effect on Pods created after the update. Draining + // the node is recommended before changing this field. // Default: nil // +optional ClusterDNS []string `json:"clusterDNS,omitempty"` // streamingConnectionIdleTimeout is the maximum time a streaming connection // can be idle before the connection is automatically closed. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact components that rely on infrequent updates over streaming + // connections to the Kubelet server. // Default: "4h" // +optional StreamingConnectionIdleTimeout metav1.Duration `json:"streamingConnectionIdleTimeout,omitempty"` // nodeStatusUpdateFrequency is the frequency that kubelet posts node // status to master. Note: be cautious when changing the constant, it // must work with nodeMonitorGracePeriod in nodecontroller. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact node scalability, and also that the node controller's + // nodeMonitorGracePeriod must be set to N*NodeStatusUpdateFrequency, + // where N is the number of retries before the node controller marks + // the node unhealthy. // Default: "10s" // +optional NodeStatusUpdateFrequency metav1.Duration `json:"nodeStatusUpdateFrequency,omitempty"` // imageMinimumGCAge is the minimum age for an unused image before it is // garbage collected. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay garbage collection, and may change the image overhead + // on the node. // Default: "2m" // +optional ImageMinimumGCAge metav1.Duration `json:"imageMinimumGCAge,omitempty"` // imageGCHighThresholdPercent is the percent of disk usage after which // image garbage collection is always run. The percent is calculated as // this field value out of 100. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay garbage collection, and may change the image overhead + // on the node. // Default: 85 // +optional ImageGCHighThresholdPercent *int32 `json:"imageGCHighThresholdPercent,omitempty"` // imageGCLowThresholdPercent is the percent of disk usage before which // image garbage collection is never run. Lowest disk usage to garbage // collect to. The percent is calculated as this field value out of 100. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay garbage collection, and may change the image overhead + // on the node. // Default: 80 // +optional ImageGCLowThresholdPercent *int32 `json:"imageGCLowThresholdPercent,omitempty"` // How frequently to calculate and cache volume disk usage for all pods + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening the period may carry a performance impact. // Default: "1m" // +optional VolumeStatsAggPeriod metav1.Duration `json:"volumeStatsAggPeriod,omitempty"` // kubeletCgroups is the absolute name of cgroups to isolate the kubelet in + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional KubeletCgroups string `json:"kubeletCgroups,omitempty"` // systemCgroups is absolute name of cgroups in which to place // all non-kernel processes that are not already in a container. Empty // for no container. Rolling back the flag requires a reboot. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional SystemCgroups string `json:"systemCgroups,omitempty"` // cgroupRoot is the root cgroup to use for pods. This is handled by the // container runtime on a best effort basis. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional CgroupRoot string `json:"cgroupRoot,omitempty"` // Enable QoS based Cgroup hierarchy: top level cgroups for QoS Classes // And all Burstable and BestEffort pods are brought up under their // specific top level QoS cgroup. - // +optional + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: true // +optional CgroupsPerQOS *bool `json:"cgroupsPerQOS,omitempty"` // driver that the kubelet uses to manipulate cgroups on the host (cgroupfs or systemd) - // +optional + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "cgroupfs" // +optional CgroupDriver string `json:"cgroupDriver,omitempty"` // CPUManagerPolicy is the name of the policy to use. // Requires the CPUManager feature gate to be enabled. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "none" // +optional CPUManagerPolicy string `json:"cpuManagerPolicy,omitempty"` // CPU Manager reconciliation period. // Requires the CPUManager feature gate to be enabled. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // shortening the period may carry a performance impact. // Default: "10s" // +optional CPUManagerReconcilePeriod metav1.Duration `json:"cpuManagerReconcilePeriod,omitempty"` + // qosReserved is a set of resource name to percentage pairs that specify + // the minimum percentage of a resource reserved for exclusive use by the + // guaranteed QoS tier. + // Currently supported resources: "memory" + // Requires the QOSReserved feature gate to be enabled. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. + // Default: nil + // +optional + QOSReserved map[string]string `json:"qosReserved,omitempty"` // runtimeRequestTimeout is the timeout for all runtime requests except long running // requests - pull, logs, exec and attach. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may disrupt components that interact with the Kubelet server. // Default: "2m" // +optional RuntimeRequestTimeout metav1.Duration `json:"runtimeRequestTimeout,omitempty"` @@ -263,46 +393,74 @@ type KubeletConfiguration struct { // "none": do nothing. // Generally, one must set --hairpin-mode=hairpin-veth to achieve hairpin NAT, // because promiscuous-bridge assumes the existence of a container bridge named cbr0. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may require a node reboot, depending on the network plugin. // Default: "promiscuous-bridge" // +optional HairpinMode string `json:"hairpinMode,omitempty"` // maxPods is the number of pods that can run on this Kubelet. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changes may cause Pods to fail admission on Kubelet restart, and may change + // the value reported in Node.Status.Capacity[v1.ResourcePods], thus affecting + // future scheduling decisions. Increasing this value may also decrease performance, + // as more Pods can be packed into a single node. // Default: 110 // +optional MaxPods int32 `json:"maxPods,omitempty"` // The CIDR to use for pod IP addresses, only used in standalone mode. // In cluster mode, this is obtained from the master. + // Dynamic Kubelet Config (beta): This field should always be set to the empty default. + // It should only set for standalone Kubelets, which cannot use Dynamic Kubelet Config. // Default: "" // +optional PodCIDR string `json:"podCIDR,omitempty"` // PodPidsLimit is the maximum number of pids in any pod. // Requires the SupportPodPidsLimit feature gate to be enabled. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // lowering it may prevent container processes from forking after the change. // Default: -1 // +optional PodPidsLimit *int64 `json:"podPidsLimit,omitempty"` // ResolverConfig is the resolver configuration file used as the basis // for the container DNS resolution configuration. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changes will only take effect on Pods created after the update. Draining + // the node is recommended before changing this field. // Default: "/etc/resolv.conf" // +optional ResolverConfig string `json:"resolvConf,omitempty"` // cpuCFSQuota enables CPU CFS quota enforcement for containers that // specify CPU limits. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it may reduce node stability. // Default: true // +optional CPUCFSQuota *bool `json:"cpuCFSQuota,omitempty"` // maxOpenFiles is Number of files that can be opened by Kubelet process. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact the ability of the Kubelet to interact with the node's filesystem. // Default: 1000000 // +optional MaxOpenFiles int64 `json:"maxOpenFiles,omitempty"` // contentType is contentType of requests sent to apiserver. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact the ability for the Kubelet to communicate with the API server. + // If the Kubelet loses contact with the API server due to a change to this field, + // the change cannot be reverted via dynamic Kubelet config. // Default: "application/vnd.kubernetes.protobuf" // +optional ContentType string `json:"contentType,omitempty"` // kubeAPIQPS is the QPS to use while talking with kubernetes apiserver + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic the Kubelet + // sends to the API server. // Default: 5 // +optional KubeAPIQPS *int32 `json:"kubeAPIQPS,omitempty"` // kubeAPIBurst is the burst to allow while talking with kubernetes apiserver + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact scalability by changing the amount of traffic the Kubelet + // sends to the API server. // Default: 10 // +optional KubeAPIBurst int32 `json:"kubeAPIBurst,omitempty"` @@ -310,11 +468,15 @@ type KubeletConfiguration struct { // at a time. We recommend *not* changing the default value on nodes that // run docker daemon with version < 1.9 or an Aufs storage backend. // Issue #10959 has more details. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may impact the performance of image pulls. // Default: true // +optional SerializeImagePulls *bool `json:"serializeImagePulls,omitempty"` // Map of signal names to quantities that defines hard eviction thresholds. For example: {"memory.available": "300Mi"}. // To explicitly disable, pass a 0% or 100% threshold on an arbitrary resource. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay Pod evictions. // Default: // memory.available: "100Mi" // nodefs.available: "10%" @@ -322,49 +484,83 @@ type KubeletConfiguration struct { // imagefs.available: "15%" // +optional EvictionHard map[string]string `json:"evictionHard,omitempty"` - // Map of signal names to quantities that defines soft eviction thresholds. For example: {"memory.available": "300Mi"}. + // Map of signal names to quantities that defines soft eviction thresholds. + // For example: {"memory.available": "300Mi"}. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay Pod evictions, and may change the allocatable reported + // by the node. // Default: nil // +optional EvictionSoft map[string]string `json:"evictionSoft,omitempty"` - // Map of signal names to quantities that defines grace periods for each soft eviction signal. For example: {"memory.available": "30s"}. + // Map of signal names to quantities that defines grace periods for each soft eviction signal. + // For example: {"memory.available": "30s"}. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger or delay Pod evictions. // Default: nil // +optional EvictionSoftGracePeriod map[string]string `json:"evictionSoftGracePeriod,omitempty"` // Duration for which the kubelet has to wait before transitioning out of an eviction pressure condition. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // lowering it may decrease the stability of the node when the node is overcommitted. // Default: "5m" // +optional EvictionPressureTransitionPeriod metav1.Duration `json:"evictionPressureTransitionPeriod,omitempty"` - // Maximum allowed grace period (in seconds) to use when terminating pods in response to a soft eviction threshold being met. + // Maximum allowed grace period (in seconds) to use when terminating pods in + // response to a soft eviction threshold being met. This value effectively caps + // the Pod's TerminationGracePeriodSeconds value during soft evictions. + // Note: Due to issue #64530, the behavior has a bug where this value currently just + // overrides the grace period during soft eviction, which can increase the grace + // period from what is set on the Pod. This bug will be fixed in a future release. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // lowering it decreases the amount of time Pods will have to gracefully clean + // up before being killed during a soft eviction. // Default: 0 // +optional EvictionMaxPodGracePeriod int32 `json:"evictionMaxPodGracePeriod,omitempty"` // Map of signal names to quantities that defines minimum reclaims, which describe the minimum // amount of a given resource the kubelet will reclaim when performing a pod eviction while // that resource is under pressure. For example: {"imagefs.available": "2Gi"} - // +optional + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may change how well eviction can manage resource pressure. // Default: nil // +optional EvictionMinimumReclaim map[string]string `json:"evictionMinimumReclaim,omitempty"` // podsPerCore is the maximum number of pods per core. Cannot exceed MaxPods. // If 0, this field is ignored. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changes may cause Pods to fail admission on Kubelet restart, and may change + // the value reported in Node.Status.Capacity[v1.ResourcePods], thus affecting + // future scheduling decisions. Increasing this value may also decrease performance, + // as more Pods can be packed into a single node. // Default: 0 // +optional PodsPerCore int32 `json:"podsPerCore,omitempty"` // enableControllerAttachDetach enables the Attach/Detach controller to // manage attachment/detachment of volumes scheduled to this node, and // disables kubelet from executing any attach/detach operations + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // changing which component is responsible for volume management on a live node + // may result in volumes refusing to detach if the node is not drained prior to + // the update, and if Pods are scheduled to the node before the + // volumes.kubernetes.io/controller-managed-attach-detach annotation is updated by the + // Kubelet. In general, it is safest to leave this value set the same as local config. // Default: true // +optional EnableControllerAttachDetach *bool `json:"enableControllerAttachDetach,omitempty"` // protectKernelDefaults, if true, causes the Kubelet to error if kernel // flags are not as it expects. Otherwise the Kubelet will attempt to modify // kernel flags to match its expectation. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // enabling it may cause the Kubelet to crash-loop if the Kernel is not configured as + // Kubelet expects. // Default: false // +optional ProtectKernelDefaults bool `json:"protectKernelDefaults,omitempty"` // If true, Kubelet ensures a set of iptables rules are present on host. // These rules will serve as utility rules for various components, e.g. KubeProxy. // The rules will be created based on IPTablesMasqueradeBit and IPTablesDropBit. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // disabling it will prevent the Kubelet from healing locally misconfigured iptables rules. // Default: true // +optional MakeIPTablesUtilChains *bool `json:"makeIPTablesUtilChains,omitempty"` @@ -372,39 +568,61 @@ type KubeletConfiguration struct { // Values must be within the range [0, 31]. Must be different from other mark bits. // Warning: Please match the value of the corresponding parameter in kube-proxy. // TODO: clean up IPTablesMasqueradeBit in kube-proxy + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it needs to be coordinated with other components, like kube-proxy, and the update + // will only be effective if MakeIPTablesUtilChains is enabled. // Default: 14 // +optional IPTablesMasqueradeBit *int32 `json:"iptablesMasqueradeBit,omitempty"` // iptablesDropBit is the bit of the iptables fwmark space to mark for dropping packets. // Values must be within the range [0, 31]. Must be different from other mark bits. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it needs to be coordinated with other components, like kube-proxy, and the update + // will only be effective if MakeIPTablesUtilChains is enabled. // Default: 15 // +optional IPTablesDropBit *int32 `json:"iptablesDropBit,omitempty"` // featureGates is a map of feature names to bools that enable or disable alpha/experimental // features. This field modifies piecemeal the built-in default values from // "k8s.io/kubernetes/pkg/features/kube_features.go". + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider the + // documentation for the features you are enabling or disabling. While we + // encourage feature developers to make it possible to dynamically enable + // and disable features, some changes may require node reboots, and some + // features may require careful coordination to retroactively disable. // Default: nil // +optional FeatureGates map[string]bool `json:"featureGates,omitempty"` // failSwapOn tells the Kubelet to fail to start if swap is enabled on the node. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // setting it to true will cause the Kubelet to crash-loop if swap is enabled. // Default: true // +optional FailSwapOn *bool `json:"failSwapOn,omitempty"` - // A quantity defines the maximum size of the container log file before it is rotated. For example: "5Mi" or "256Ki". + // A quantity defines the maximum size of the container log file before it is rotated. + // For example: "5Mi" or "256Ki". + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may trigger log rotation. // Default: "10Mi" // +optional ContainerLogMaxSize string `json:"containerLogMaxSize,omitempty"` // Maximum number of container log files that can be present for a container. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // lowering it may cause log files to be deleted. // Default: 5 // +optional ContainerLogMaxFiles *int32 `json:"containerLogMaxFiles,omitempty"` - /* following flags are meant for Node Allocatable */ + /* the following fields are meant for Node Allocatable */ - // A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G) pairs - // that describe resources reserved for non-kubernetes components. + // systemReserved is a set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G) + // pairs that describe resources reserved for non-kubernetes components. // Currently only cpu and memory are supported. // See http://kubernetes.io/docs/user-guide/compute-resources for more detail. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may not be possible to increase the reserved resources, because this + // requires resizing cgroups. Always look for a NodeAllocatableEnforced event + // after updating this field to ensure that the update was successful. // Default: nil // +optional SystemReserved map[string]string `json:"systemReserved,omitempty"` @@ -412,16 +630,24 @@ type KubeletConfiguration struct { // that describe resources reserved for kubernetes system components. // Currently cpu, memory and local storage for root file system are supported. // See http://kubernetes.io/docs/user-guide/compute-resources for more detail. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // it may not be possible to increase the reserved resources, because this + // requires resizing cgroups. Always look for a NodeAllocatableEnforced event + // after updating this field to ensure that the update was successful. // Default: nil // +optional KubeReserved map[string]string `json:"kubeReserved,omitempty"` // This flag helps kubelet identify absolute name of top level cgroup used to enforce `SystemReserved` compute resource reservation for OS system daemons. // Refer to [Node Allocatable](https://git.k8s.io/community/contributors/design-proposals/node/node-allocatable.md) doc for more information. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional SystemReservedCgroup string `json:"systemReservedCgroup,omitempty"` // This flag helps kubelet identify absolute name of top level cgroup used to enforce `KubeReserved` compute resource reservation for Kubernetes node system daemons. // Refer to [Node Allocatable](https://git.k8s.io/community/contributors/design-proposals/node/node-allocatable.md) doc for more information. + // Dynamic Kubelet Config (beta): This field should not be updated without a full node + // reboot. It is safest to keep this value the same as the local config. // Default: "" // +optional KubeReservedCgroup string `json:"kubeReservedCgroup,omitempty"` @@ -429,6 +655,12 @@ type KubeletConfiguration struct { // This flag accepts a list of options. Acceptable options are `none`, `pods`, `system-reserved` & `kube-reserved`. // If `none` is specified, no other options may be specified. // Refer to [Node Allocatable](https://git.k8s.io/community/contributors/design-proposals/node/node-allocatable.md) doc for more information. + // Dynamic Kubelet Config (beta): If dynamically updating this field, consider that + // removing enforcements may reduce the stability of the node. Alternatively, adding + // enforcements may reduce the stability of components which were using more than + // the reserved amount of resources; for example, enforcing kube-reserved may cause + // Kubelets to OOM if it uses more than the reserved resources, and enforcing system-reserved + // may cause system daemons to OOM if they use more than the reserved resources. // Default: ["pods"] // +optional EnforceNodeAllocatable []string `json:"enforceNodeAllocatable,omitempty"` @@ -500,3 +732,15 @@ type KubeletAnonymousAuthentication struct { // +optional Enabled *bool `json:"enabled,omitempty"` } + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// SerializedNodeConfigSource allows us to serialize v1.NodeConfigSource. +// This type is used internally by the Kubelet for tracking checkpointed dynamic configs. +// It exists in the kubeletconfig API group because it is classified as a versioned input to the Kubelet. +type SerializedNodeConfigSource struct { + metav1.TypeMeta `json:",inline"` + // Source is the source that we are serializing + // +optional + Source v1.NodeConfigSource `json:"source,omitempty" protobuf:"bytes,1,opt,name=source"` +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.conversion.go index 1a166b006..5765982b7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -51,6 +51,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kubeletconfig_KubeletWebhookAuthorization_To_v1beta1_KubeletWebhookAuthorization, Convert_v1beta1_KubeletX509Authentication_To_kubeletconfig_KubeletX509Authentication, Convert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509Authentication, + Convert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource, + Convert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource, ) } @@ -154,6 +156,8 @@ func autoConvert_v1beta1_KubeletConfiguration_To_kubeletconfig_KubeletConfigurat out.TLSPrivateKeyFile = in.TLSPrivateKeyFile out.TLSCipherSuites = *(*[]string)(unsafe.Pointer(&in.TLSCipherSuites)) out.TLSMinVersion = in.TLSMinVersion + out.RotateCertificates = in.RotateCertificates + out.ServerTLSBootstrap = in.ServerTLSBootstrap if err := Convert_v1beta1_KubeletAuthentication_To_kubeletconfig_KubeletAuthentication(&in.Authentication, &out.Authentication, s); err != nil { return err } @@ -200,6 +204,7 @@ func autoConvert_v1beta1_KubeletConfiguration_To_kubeletconfig_KubeletConfigurat out.CgroupDriver = in.CgroupDriver out.CPUManagerPolicy = in.CPUManagerPolicy out.CPUManagerReconcilePeriod = in.CPUManagerReconcilePeriod + out.QOSReserved = *(*map[string]string)(unsafe.Pointer(&in.QOSReserved)) out.RuntimeRequestTimeout = in.RuntimeRequestTimeout out.HairpinMode = in.HairpinMode out.MaxPods = in.MaxPods @@ -275,6 +280,8 @@ func autoConvert_kubeletconfig_KubeletConfiguration_To_v1beta1_KubeletConfigurat out.TLSPrivateKeyFile = in.TLSPrivateKeyFile out.TLSCipherSuites = *(*[]string)(unsafe.Pointer(&in.TLSCipherSuites)) out.TLSMinVersion = in.TLSMinVersion + out.RotateCertificates = in.RotateCertificates + out.ServerTLSBootstrap = in.ServerTLSBootstrap if err := Convert_kubeletconfig_KubeletAuthentication_To_v1beta1_KubeletAuthentication(&in.Authentication, &out.Authentication, s); err != nil { return err } @@ -321,6 +328,7 @@ func autoConvert_kubeletconfig_KubeletConfiguration_To_v1beta1_KubeletConfigurat out.CgroupDriver = in.CgroupDriver out.CPUManagerPolicy = in.CPUManagerPolicy out.CPUManagerReconcilePeriod = in.CPUManagerReconcilePeriod + out.QOSReserved = *(*map[string]string)(unsafe.Pointer(&in.QOSReserved)) out.RuntimeRequestTimeout = in.RuntimeRequestTimeout out.HairpinMode = in.HairpinMode out.MaxPods = in.MaxPods @@ -449,3 +457,23 @@ func autoConvert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509A func Convert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509Authentication(in *kubeletconfig.KubeletX509Authentication, out *KubeletX509Authentication, s conversion.Scope) error { return autoConvert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509Authentication(in, out, s) } + +func autoConvert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource(in *SerializedNodeConfigSource, out *kubeletconfig.SerializedNodeConfigSource, s conversion.Scope) error { + out.Source = in.Source + return nil +} + +// Convert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource is an autogenerated conversion function. +func Convert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource(in *SerializedNodeConfigSource, out *kubeletconfig.SerializedNodeConfigSource, s conversion.Scope) error { + return autoConvert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource(in, out, s) +} + +func autoConvert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource(in *kubeletconfig.SerializedNodeConfigSource, out *SerializedNodeConfigSource, s conversion.Scope) error { + out.Source = in.Source + return nil +} + +// Convert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource is an autogenerated conversion function. +func Convert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource(in *kubeletconfig.SerializedNodeConfigSource, out *SerializedNodeConfigSource, s conversion.Scope) error { + return autoConvert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource(in, out, s) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.deepcopy.go index 296850b3b..f7fc0a79c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -193,6 +193,13 @@ func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) { } } out.CPUManagerReconcilePeriod = in.CPUManagerReconcilePeriod + if in.QOSReserved != nil { + in, out := &in.QOSReserved, &out.QOSReserved + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } out.RuntimeRequestTimeout = in.RuntimeRequestTimeout if in.PodPidsLimit != nil { in, out := &in.PodPidsLimit, &out.PodPidsLimit @@ -419,3 +426,29 @@ func (in *KubeletX509Authentication) DeepCopy() *KubeletX509Authentication { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SerializedNodeConfigSource) DeepCopyInto(out *SerializedNodeConfigSource) { + *out = *in + out.TypeMeta = in.TypeMeta + in.Source.DeepCopyInto(&out.Source) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SerializedNodeConfigSource. +func (in *SerializedNodeConfigSource) DeepCopy() *SerializedNodeConfigSource { + if in == nil { + return nil + } + out := new(SerializedNodeConfigSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SerializedNodeConfigSource) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.defaults.go index 0d6d832b1..ab982de3a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/BUILD index 18fbe0afd..071a4b16f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/BUILD @@ -8,13 +8,52 @@ load( go_library( name = "go_default_library", - srcs = ["validation.go"], + srcs = [ + "validation.go", + ] + select({ + "@io_bazel_rules_go//go/platform:android": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:nacl": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "validation_others.go", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "validation_windows.go", + ], + "//conditions:default": [], + }), importpath = "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation", deps = [ + "//pkg/features:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation.go index 3f3e354be..4be154014 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation.go @@ -21,6 +21,8 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" utilvalidation "k8s.io/apimachinery/pkg/util/validation" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" ) @@ -29,6 +31,11 @@ import ( func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration) error { allErrors := []error{} + // Make a local copy of the global feature gates and combine it with the gates set by this configuration. + // This allows us to validate the config against the set of gates it will actually run against. + localFeatureGate := utilfeature.DefaultFeatureGate.DeepCopy() + localFeatureGate.SetFromMap(kc.FeatureGates) + if !kc.CgroupsPerQOS && len(kc.EnforceNodeAllocatable) > 0 { allErrors = append(allErrors, fmt.Errorf("invalid configuration: EnforceNodeAllocatable (--enforce-node-allocatable) is not supported unless CgroupsPerQOS (--cgroups-per-qos) feature is turned on")) } @@ -86,6 +93,12 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration) error if kc.RegistryPullQPS < 0 { allErrors = append(allErrors, fmt.Errorf("invalid configuration: RegistryPullQPS (--registry-qps) %v must not be a negative number", kc.RegistryPullQPS)) } + if kc.RotateCertificates && !localFeatureGate.Enabled(features.RotateKubeletClientCertificate) { + allErrors = append(allErrors, fmt.Errorf("invalid configuration: RotateCertificates %v requires feature gate RotateKubeletClientCertificate", kc.RotateCertificates)) + } + if kc.ServerTLSBootstrap && !localFeatureGate.Enabled(features.RotateKubeletServerCertificate) { + allErrors = append(allErrors, fmt.Errorf("invalid configuration: ServerTLSBootstrap %v requires feature gate RotateKubeletServerCertificate", kc.ServerTLSBootstrap)) + } for _, val := range kc.EnforceNodeAllocatable { switch val { case kubetypes.NodeAllocatableEnforcementKey: @@ -108,5 +121,9 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration) error allErrors = append(allErrors, fmt.Errorf("invalid configuration: option %q specified for HairpinMode (--hairpin-mode). Valid options are %q, %q or %q", kc.HairpinMode, kubeletconfig.HairpinNone, kubeletconfig.HairpinVeth, kubeletconfig.PromiscuousBridge)) } + + if err := validateKubeletOSConfiguration(kc); err != nil { + allErrors = append(allErrors, err) + } return utilerrors.NewAggregate(allErrors) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation_others.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation_others.go new file mode 100644 index 000000000..4cad82582 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation_others.go @@ -0,0 +1,28 @@ +// +build !windows + +/* +Copyright 2018 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 validation + +import ( + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" +) + +// validateKubeletOSConfiguration validates os specific kubelet configuration and returns an error if it is invalid. +func validateKubeletOSConfiguration(kc *kubeletconfig.KubeletConfiguration) error { + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation_windows.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation_windows.go new file mode 100644 index 000000000..d1a8ec1dd --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation/validation_windows.go @@ -0,0 +1,42 @@ +// +build windows + +/* +Copyright 2018 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 validation + +import ( + "fmt" + + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" +) + +// validateKubeletOSConfiguration validates os specific kubelet configuration and returns an error if it is invalid. +func validateKubeletOSConfiguration(kc *kubeletconfig.KubeletConfiguration) error { + message := "invalid configuration: %v (%v) %v is not supported on Windows" + allErrors := []error{} + + if kc.CgroupsPerQOS { + allErrors = append(allErrors, fmt.Errorf(message, "CgroupsPerQOS", "--cgroups-per-qos", kc.CgroupsPerQOS)) + } + + if len(kc.EnforceNodeAllocatable) > 0 { + allErrors = append(allErrors, fmt.Errorf(message, "EnforceNodeAllocatable", "--enforce-node-allocatable", kc.EnforceNodeAllocatable)) + } + + return utilerrors.NewAggregate(allErrors) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/zz_generated.deepcopy.go index 7c2c9e454..2a312ad84 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -112,6 +112,13 @@ func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) { out.ImageMinimumGCAge = in.ImageMinimumGCAge out.VolumeStatsAggPeriod = in.VolumeStatsAggPeriod out.CPUManagerReconcilePeriod = in.CPUManagerReconcilePeriod + if in.QOSReserved != nil { + in, out := &in.QOSReserved, &out.QOSReserved + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } out.RuntimeRequestTimeout = in.RuntimeRequestTimeout if in.EvictionHard != nil { in, out := &in.EvictionHard, &out.EvictionHard @@ -239,3 +246,29 @@ func (in *KubeletX509Authentication) DeepCopy() *KubeletX509Authentication { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SerializedNodeConfigSource) DeepCopyInto(out *SerializedNodeConfigSource) { + *out = *in + out.TypeMeta = in.TypeMeta + in.Source.DeepCopyInto(&out.Source) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SerializedNodeConfigSource. +func (in *SerializedNodeConfigSource) DeepCopy() *SerializedNodeConfigSource { + if in == nil { + return nil + } + out := new(SerializedNodeConfigSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SerializedNodeConfigSource) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/BUILD new file mode 100644 index 000000000..f51668500 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/BUILD @@ -0,0 +1,40 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "api.pb.go", + "constants.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1", + deps = [ + "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", + "//vendor/github.com/gogo/protobuf/proto:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) + +filegroup( + name = "go_default_library_protos", + srcs = ["api.proto"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/api.pb.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/api.pb.go new file mode 100644 index 000000000..96e1d571d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/api.pb.go @@ -0,0 +1,1027 @@ +/* +Copyright 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. +*/ + +// Code generated by protoc-gen-gogo. +// source: api.proto +// DO NOT EDIT! + +/* + Package pluginregistration is a generated protocol buffer package. + + It is generated from these files: + api.proto + + It has these top-level messages: + PluginInfo + RegistrationStatus + RegistrationStatusResponse + InfoRequest +*/ +package pluginregistration + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +import strings "strings" +import reflect "reflect" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +// PluginInfo is the message sent from a plugin to the Kubelet pluginwatcher for plugin registration +type PluginInfo struct { + // Type of the Plugin. CSIPlugin or DevicePlugin + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + // Plugin name that uniquely identifies the plugin for the given plugin type. + // For DevicePlugin, this is the resource name that the plugin manages and + // should follow the extended resource name convention. + // For CSI, this is the CSI driver registrar name. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Optional endpoint location. If found set by Kubelet component, + // Kubelet component will use this endpoint for specific requests. + // This allows the plugin to register using one endpoint and possibly use + // a different socket for control operations. CSI uses this model to delegate + // its registration external from the plugin. + Endpoint string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"` + // Plugin service API versions the plugin supports. + // For DevicePlugin, this maps to the deviceplugin API versions the + // plugin supports at the given socket. + // The Kubelet component communicating with the plugin should be able + // to choose any preferred version from this list, or returns an error + // if none of the listed versions is supported. + SupportedVersions []string `protobuf:"bytes,4,rep,name=supported_versions,json=supportedVersions" json:"supported_versions,omitempty"` +} + +func (m *PluginInfo) Reset() { *m = PluginInfo{} } +func (*PluginInfo) ProtoMessage() {} +func (*PluginInfo) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{0} } + +func (m *PluginInfo) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *PluginInfo) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *PluginInfo) GetEndpoint() string { + if m != nil { + return m.Endpoint + } + return "" +} + +func (m *PluginInfo) GetSupportedVersions() []string { + if m != nil { + return m.SupportedVersions + } + return nil +} + +// RegistrationStatus is the message sent from Kubelet pluginwatcher to the plugin for notification on registration status +type RegistrationStatus struct { + // True if plugin gets registered successfully at Kubelet + PluginRegistered bool `protobuf:"varint,1,opt,name=plugin_registered,json=pluginRegistered,proto3" json:"plugin_registered,omitempty"` + // Error message in case plugin fails to register, empty string otherwise + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *RegistrationStatus) Reset() { *m = RegistrationStatus{} } +func (*RegistrationStatus) ProtoMessage() {} +func (*RegistrationStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{1} } + +func (m *RegistrationStatus) GetPluginRegistered() bool { + if m != nil { + return m.PluginRegistered + } + return false +} + +func (m *RegistrationStatus) GetError() string { + if m != nil { + return m.Error + } + return "" +} + +// RegistrationStatusResponse is sent by plugin to kubelet in response to RegistrationStatus RPC +type RegistrationStatusResponse struct { +} + +func (m *RegistrationStatusResponse) Reset() { *m = RegistrationStatusResponse{} } +func (*RegistrationStatusResponse) ProtoMessage() {} +func (*RegistrationStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{2} } + +// InfoRequest is the empty request message from Kubelet +type InfoRequest struct { +} + +func (m *InfoRequest) Reset() { *m = InfoRequest{} } +func (*InfoRequest) ProtoMessage() {} +func (*InfoRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{3} } + +func init() { + proto.RegisterType((*PluginInfo)(nil), "pluginregistration.PluginInfo") + proto.RegisterType((*RegistrationStatus)(nil), "pluginregistration.RegistrationStatus") + proto.RegisterType((*RegistrationStatusResponse)(nil), "pluginregistration.RegistrationStatusResponse") + proto.RegisterType((*InfoRequest)(nil), "pluginregistration.InfoRequest") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Registration service + +type RegistrationClient interface { + GetInfo(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*PluginInfo, error) + NotifyRegistrationStatus(ctx context.Context, in *RegistrationStatus, opts ...grpc.CallOption) (*RegistrationStatusResponse, error) +} + +type registrationClient struct { + cc *grpc.ClientConn +} + +func NewRegistrationClient(cc *grpc.ClientConn) RegistrationClient { + return ®istrationClient{cc} +} + +func (c *registrationClient) GetInfo(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*PluginInfo, error) { + out := new(PluginInfo) + err := grpc.Invoke(ctx, "/pluginregistration.Registration/GetInfo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *registrationClient) NotifyRegistrationStatus(ctx context.Context, in *RegistrationStatus, opts ...grpc.CallOption) (*RegistrationStatusResponse, error) { + out := new(RegistrationStatusResponse) + err := grpc.Invoke(ctx, "/pluginregistration.Registration/NotifyRegistrationStatus", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Registration service + +type RegistrationServer interface { + GetInfo(context.Context, *InfoRequest) (*PluginInfo, error) + NotifyRegistrationStatus(context.Context, *RegistrationStatus) (*RegistrationStatusResponse, error) +} + +func RegisterRegistrationServer(s *grpc.Server, srv RegistrationServer) { + s.RegisterService(&_Registration_serviceDesc, srv) +} + +func _Registration_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistrationServer).GetInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pluginregistration.Registration/GetInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistrationServer).GetInfo(ctx, req.(*InfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Registration_NotifyRegistrationStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegistrationStatus) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistrationServer).NotifyRegistrationStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pluginregistration.Registration/NotifyRegistrationStatus", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistrationServer).NotifyRegistrationStatus(ctx, req.(*RegistrationStatus)) + } + return interceptor(ctx, in, info, handler) +} + +var _Registration_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pluginregistration.Registration", + HandlerType: (*RegistrationServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetInfo", + Handler: _Registration_GetInfo_Handler, + }, + { + MethodName: "NotifyRegistrationStatus", + Handler: _Registration_NotifyRegistrationStatus_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api.proto", +} + +func (m *PluginInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PluginInfo) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Type) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Type))) + i += copy(dAtA[i:], m.Type) + } + if len(m.Name) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + } + if len(m.Endpoint) > 0 { + dAtA[i] = 0x1a + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Endpoint))) + i += copy(dAtA[i:], m.Endpoint) + } + if len(m.SupportedVersions) > 0 { + for _, s := range m.SupportedVersions { + dAtA[i] = 0x22 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + +func (m *RegistrationStatus) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RegistrationStatus) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.PluginRegistered { + dAtA[i] = 0x8 + i++ + if m.PluginRegistered { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } + if len(m.Error) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Error))) + i += copy(dAtA[i:], m.Error) + } + return i, nil +} + +func (m *RegistrationStatusResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RegistrationStatusResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func (m *InfoRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *InfoRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func encodeFixed64Api(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Api(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintApi(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *PluginInfo) Size() (n int) { + var l int + _ = l + l = len(m.Type) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.Endpoint) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + if len(m.SupportedVersions) > 0 { + for _, s := range m.SupportedVersions { + l = len(s) + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *RegistrationStatus) Size() (n int) { + var l int + _ = l + if m.PluginRegistered { + n += 2 + } + l = len(m.Error) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *RegistrationStatusResponse) Size() (n int) { + var l int + _ = l + return n +} + +func (m *InfoRequest) Size() (n int) { + var l int + _ = l + return n +} + +func sovApi(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozApi(x uint64) (n int) { + return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *PluginInfo) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PluginInfo{`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Endpoint:` + fmt.Sprintf("%v", this.Endpoint) + `,`, + `SupportedVersions:` + fmt.Sprintf("%v", this.SupportedVersions) + `,`, + `}`, + }, "") + return s +} +func (this *RegistrationStatus) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RegistrationStatus{`, + `PluginRegistered:` + fmt.Sprintf("%v", this.PluginRegistered) + `,`, + `Error:` + fmt.Sprintf("%v", this.Error) + `,`, + `}`, + }, "") + return s +} +func (this *RegistrationStatusResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RegistrationStatusResponse{`, + `}`, + }, "") + return s +} +func (this *InfoRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&InfoRequest{`, + `}`, + }, "") + return s +} +func valueToStringApi(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *PluginInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PluginInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PluginInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Type = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Endpoint", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Endpoint = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SupportedVersions", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SupportedVersions = append(m.SupportedVersions, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RegistrationStatus) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RegistrationStatus: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RegistrationStatus: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PluginRegistered", 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.PluginRegistered = bool(v != 0) + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RegistrationStatusResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RegistrationStatusResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RegistrationStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *InfoRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: InfoRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: InfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipApi(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthApi + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipApi(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } + +var fileDescriptorApi = []byte{ + // 337 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x41, 0x4b, 0x33, 0x31, + 0x14, 0xdc, 0x7c, 0xed, 0xa7, 0xed, 0x53, 0xc1, 0x06, 0x0f, 0xcb, 0x52, 0x62, 0xd9, 0x83, 0x14, + 0xa4, 0x5b, 0xd0, 0x7f, 0xe0, 0x45, 0x04, 0x11, 0x89, 0xa0, 0xc7, 0xb2, 0xb5, 0xaf, 0x6b, 0xc0, + 0x26, 0x31, 0xc9, 0x0a, 0x3d, 0xe9, 0x4f, 0xf0, 0x67, 0xf5, 0x28, 0x9e, 0x3c, 0xda, 0xf5, 0x8f, + 0x48, 0xb3, 0x65, 0x2d, 0xb4, 0x07, 0x6f, 0x6f, 0xe6, 0x4d, 0x1e, 0x33, 0x43, 0xa0, 0x99, 0x6a, + 0x91, 0x68, 0xa3, 0x9c, 0xa2, 0x54, 0x3f, 0xe6, 0x99, 0x90, 0x06, 0x33, 0x61, 0x9d, 0x49, 0x9d, + 0x50, 0x32, 0xea, 0x65, 0xc2, 0x3d, 0xe4, 0xc3, 0xe4, 0x5e, 0x4d, 0xfa, 0x99, 0xca, 0x54, 0xdf, + 0x4b, 0x87, 0xf9, 0xd8, 0x23, 0x0f, 0xfc, 0x54, 0x9e, 0x88, 0x5f, 0x00, 0xae, 0xfd, 0x91, 0x0b, + 0x39, 0x56, 0x94, 0x42, 0xdd, 0x4d, 0x35, 0x86, 0xa4, 0x43, 0xba, 0x4d, 0xee, 0xe7, 0x05, 0x27, + 0xd3, 0x09, 0x86, 0xff, 0x4a, 0x6e, 0x31, 0xd3, 0x08, 0x1a, 0x28, 0x47, 0x5a, 0x09, 0xe9, 0xc2, + 0x9a, 0xe7, 0x2b, 0x4c, 0x7b, 0x40, 0x6d, 0xae, 0xb5, 0x32, 0x0e, 0x47, 0x83, 0x67, 0x34, 0x56, + 0x28, 0x69, 0xc3, 0x7a, 0xa7, 0xd6, 0x6d, 0xf2, 0x56, 0xb5, 0xb9, 0x5d, 0x2e, 0xe2, 0x3b, 0xa0, + 0x7c, 0xc5, 0xff, 0x8d, 0x4b, 0x5d, 0x6e, 0xe9, 0x31, 0xb4, 0xca, 0x6c, 0x83, 0x32, 0x1c, 0x1a, + 0x1c, 0x79, 0x57, 0x0d, 0xbe, 0x5f, 0x2e, 0x78, 0xc5, 0xd3, 0x03, 0xf8, 0x8f, 0xc6, 0x28, 0xb3, + 0xb4, 0x58, 0x82, 0xb8, 0x0d, 0xd1, 0xfa, 0x61, 0x8e, 0x56, 0x2b, 0x69, 0x31, 0xde, 0x83, 0x9d, + 0x45, 0x62, 0x8e, 0x4f, 0x39, 0x5a, 0x77, 0xf2, 0x41, 0x60, 0x77, 0x55, 0x4d, 0x2f, 0x61, 0xfb, + 0x1c, 0x9d, 0x2f, 0xe5, 0x30, 0x59, 0xaf, 0x39, 0x59, 0x79, 0x1c, 0xb1, 0x4d, 0x82, 0xdf, 0x56, + 0xe3, 0x80, 0x3a, 0x08, 0xaf, 0x94, 0x13, 0xe3, 0xe9, 0x86, 0xa8, 0x47, 0x9b, 0x5e, 0xaf, 0xeb, + 0xa2, 0xe4, 0x6f, 0xba, 0x2a, 0x61, 0x70, 0xd6, 0x9e, 0xcd, 0x19, 0xf9, 0x9c, 0xb3, 0xe0, 0xb5, + 0x60, 0x64, 0x56, 0x30, 0xf2, 0x5e, 0x30, 0xf2, 0x55, 0x30, 0xf2, 0xf6, 0xcd, 0x82, 0xe1, 0x96, + 0xff, 0x00, 0xa7, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe4, 0xc0, 0xe3, 0x42, 0x50, 0x02, 0x00, + 0x00, +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/api.proto b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/api.proto new file mode 100644 index 000000000..319b3f19f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/api.proto @@ -0,0 +1,60 @@ +// To regenerate api.pb.go run hack/update-generated-kubelet-plugin-registration.sh +syntax = 'proto3'; + +package pluginregistration; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +option (gogoproto.goproto_stringer_all) = false; +option (gogoproto.stringer_all) = true; +option (gogoproto.goproto_getters_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.goproto_unrecognized_all) = false; + +// PluginInfo is the message sent from a plugin to the Kubelet pluginwatcher for plugin registration +message PluginInfo { + // Type of the Plugin. CSIPlugin or DevicePlugin + string type = 1; + // Plugin name that uniquely identifies the plugin for the given plugin type. + // For DevicePlugin, this is the resource name that the plugin manages and + // should follow the extended resource name convention. + // For CSI, this is the CSI driver registrar name. + string name = 2; + // Optional endpoint location. If found set by Kubelet component, + // Kubelet component will use this endpoint for specific requests. + // This allows the plugin to register using one endpoint and possibly use + // a different socket for control operations. CSI uses this model to delegate + // its registration external from the plugin. + string endpoint = 3; + // Plugin service API versions the plugin supports. + // For DevicePlugin, this maps to the deviceplugin API versions the + // plugin supports at the given socket. + // The Kubelet component communicating with the plugin should be able + // to choose any preferred version from this list, or returns an error + // if none of the listed versions is supported. + repeated string supported_versions = 4; +} + +// RegistrationStatus is the message sent from Kubelet pluginwatcher to the plugin for notification on registration status +message RegistrationStatus { + // True if plugin gets registered successfully at Kubelet + bool plugin_registered = 1; + // Error message in case plugin fails to register, empty string otherwise + string error = 2; +} + +// RegistrationStatusResponse is sent by plugin to kubelet in response to RegistrationStatus RPC +message RegistrationStatusResponse { +} + +// InfoRequest is the empty request message from Kubelet +message InfoRequest { +} + +// Registration is the service advertised by the Plugins. +service Registration { + rpc GetInfo(InfoRequest) returns (PluginInfo) {} + rpc NotifyRegistrationStatus(RegistrationStatus) returns (RegistrationStatusResponse) {} +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/constants.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/constants.go new file mode 100644 index 000000000..cfc1b7c6d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1/constants.go @@ -0,0 +1,22 @@ +/* +Copyright 2018 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 pluginregistration + +const ( + CSIPlugin = "CSIPlugin" + DevicePlugin = "DevicePlugin" +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1/types.go index 2f7f56e4b..ecffb8bc3 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1/types.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1/types.go @@ -83,7 +83,7 @@ type RuntimeStats struct { const ( // SystemContainerKubelet is the container name for the system container tracking Kubelet usage. SystemContainerKubelet = "kubelet" - // SystemContainerRuntime is the container name for the system container tracking the runtime (e.g. docker or rkt) usage. + // SystemContainerRuntime is the container name for the system container tracking the runtime (e.g. docker) usage. SystemContainerRuntime = "runtime" // SystemContainerMisc is the container name for the system container tracking non-kubernetes processes. SystemContainerMisc = "misc" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_annotations.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_annotations.go index bc7e899ef..f1bf0620e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_annotations.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_annotations.go @@ -19,7 +19,7 @@ package apis const ( // When kubelet is started with the "external" cloud provider, then // it sets this annotation on the node to denote an ip address set from the - // cmd line flag. This ip is verified with the cloudprovider as valid by + // cmd line flag (--node-ip). This ip is verified with the cloudprovider as valid by // the cloud-controller-manager AnnotationProvidedIPAddr = "alpha.kubernetes.io/provided-node-ip" ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/cadvisor_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/cadvisor_linux.go index ffc2b0417..6418beb18 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/cadvisor_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/cadvisor_linux.go @@ -109,9 +109,10 @@ func New(address string, port uint, imageFsInfoProvider ImageFsInfoProvider, roo sysFs := sysfs.NewRealSysFs() ignoreMetrics := cadvisormetrics.MetricSet{ - cadvisormetrics.NetworkTcpUsageMetrics: struct{}{}, - cadvisormetrics.NetworkUdpUsageMetrics: struct{}{}, - cadvisormetrics.PerCpuUsageMetrics: struct{}{}, + cadvisormetrics.NetworkTcpUsageMetrics: struct{}{}, + cadvisormetrics.NetworkUdpUsageMetrics: struct{}{}, + cadvisormetrics.PerCpuUsageMetrics: struct{}{}, + cadvisormetrics.ProcessSchedulerMetrics: struct{}{}, } if !usingLegacyStats { ignoreMetrics[cadvisormetrics.DiskUsageMetrics] = struct{}{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/cadvisor_windows.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/cadvisor_windows.go index 597721cd1..eb416a141 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/cadvisor_windows.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/cadvisor_windows.go @@ -26,6 +26,7 @@ import ( ) type cadvisorClient struct { + rootPath string winStatsClient winstats.Client } @@ -34,7 +35,10 @@ var _ Interface = new(cadvisorClient) // New creates a cAdvisor and exports its API on the specified port if port > 0. func New(address string, port uint, imageFsInfoProvider ImageFsInfoProvider, rootPath string, usingLegacyStats bool) (Interface, error) { client, err := winstats.NewPerfCounterClient() - return &cadvisorClient{winStatsClient: client}, err + return &cadvisorClient{ + rootPath: rootPath, + winStatsClient: client, + }, err } func (cu *cadvisorClient) Start() error { @@ -70,7 +74,7 @@ func (cu *cadvisorClient) ImagesFsInfo() (cadvisorapiv2.FsInfo, error) { } func (cu *cadvisorClient) RootFsInfo() (cadvisorapiv2.FsInfo, error) { - return cadvisorapiv2.FsInfo{}, nil + return cu.GetDirFsInfo(cu.rootPath) } func (cu *cadvisorClient) WatchEvents(request *events.Request) (*events.EventChannel, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/helpers_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/helpers_linux.go index bff89894c..dba38022d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/helpers_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/helpers_linux.go @@ -38,8 +38,6 @@ func (i *imageFsInfoProvider) ImageFsInfoLabel() (string, error) { switch i.runtime { case types.DockerContainerRuntime: return cadvisorfs.LabelDockerImages, nil - case types.RktContainerRuntime: - return cadvisorfs.LabelRktImages, nil case types.RemoteContainerRuntime: // This is a temporary workaround to get stats for cri-o from cadvisor // and should be removed. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/util.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/util.go index e4107d5b4..16596daa9 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/util.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cadvisor/util.go @@ -75,7 +75,6 @@ func EphemeralStorageCapacityFromFsInfo(info cadvisorapi2.FsInfo) v1.ResourceLis // https://github.com/kubernetes/kubernetes/issues/51798 // UsingLegacyCadvisorStats returns true if container stats are provided by cadvisor instead of through the CRI func UsingLegacyCadvisorStats(runtime, runtimeEndpoint string) bool { - return runtime == kubetypes.RktContainerRuntime || - (runtime == kubetypes.DockerContainerRuntime && goruntime.GOOS == "linux") || + return (runtime == kubetypes.DockerContainerRuntime && goruntime.GOOS == "linux") || runtimeEndpoint == CrioSocket } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/BUILD index 23ec4341c..6910df4d9 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/BUILD @@ -26,6 +26,7 @@ go_library( "//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/util/certificate:go_default_library", + "//vendor/k8s.io/client-go/util/connrotation:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/OWNERS b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/OWNERS index 1d5fd2603..dcb32d2b8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/OWNERS @@ -1,6 +1,7 @@ reviewers: - mikedanese - liggitt +- awly approvers: - mikedanese - liggitt diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/BUILD index 74fd47647..cb21aefbc 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/BUILD @@ -30,6 +30,7 @@ go_library( "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//vendor/k8s.io/client-go/transport:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library", + "//vendor/k8s.io/client-go/util/certificate:go_default_library", "//vendor/k8s.io/client-go/util/certificate/csr:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/bootstrap.go b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/bootstrap.go index d123c0bee..350e4ed21 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/bootstrap.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/bootstrap.go @@ -32,13 +32,11 @@ import ( clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/transport" certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/certificate" "k8s.io/client-go/util/certificate/csr" ) -const ( - defaultKubeletClientCertificateFile = "kubelet-client.crt" - defaultKubeletClientKeyFile = "kubelet-client.key" -) +const tmpPrivateKeyFile = "kubelet-client.key.tmp" // LoadClientCert requests a client cert for kubelet if the kubeconfigPath file does not exist. // The kubeconfig at bootstrapPath is used to request a client certificate from the API server. @@ -66,48 +64,46 @@ func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string, return fmt.Errorf("unable to create certificates signing request client: %v", err) } - success := false - - // Get the private key. - keyPath, err := filepath.Abs(filepath.Join(certDir, defaultKubeletClientKeyFile)) - if err != nil { - return fmt.Errorf("unable to build bootstrap key path: %v", err) - } - // If we are unable to generate a CSR, we remove our key file and start fresh. - // This method is used before enabling client rotation and so we must ensure we - // can make forward progress if we crash and exit when a CSR exists but the cert - // it is signed for has expired. - defer func() { - if !success { - if err := os.Remove(keyPath); err != nil && !os.IsNotExist(err) { - glog.Warningf("Cannot clean up the key file %q: %v", keyPath, err) - } - } - }() - keyData, _, err := certutil.LoadOrGenerateKeyFile(keyPath) + store, err := certificate.NewFileStore("kubelet-client", certDir, certDir, "", "") if err != nil { - return err + return fmt.Errorf("unable to build bootstrap cert store") } - // Get the cert. - certPath, err := filepath.Abs(filepath.Join(certDir, defaultKubeletClientCertificateFile)) - if err != nil { - return fmt.Errorf("unable to build bootstrap client cert path: %v", err) - } - defer func() { - if !success { - if err := os.Remove(certPath); err != nil && !os.IsNotExist(err) { - glog.Warningf("Cannot clean up the cert file %q: %v", certPath, err) + var keyData []byte + if cert, err := store.Current(); err == nil { + if cert.PrivateKey != nil { + keyData, err = certutil.MarshalPrivateKeyToPEM(cert.PrivateKey) + if err != nil { + keyData = nil } } - }() + } + // Cache the private key in a separate file until CSR succeeds. This has to + // be a separate file because store.CurrentPath() points to a symlink + // managed by the store. + privKeyPath := filepath.Join(certDir, tmpPrivateKeyFile) + if !verifyKeyData(keyData) { + glog.V(2).Infof("No valid private key and/or certificate found, reusing existing private key or creating a new one") + // Note: always call LoadOrGenerateKeyFile so that private key is + // reused on next startup if CSR request fails. + keyData, _, err = certutil.LoadOrGenerateKeyFile(privKeyPath) + if err != nil { + return err + } + } + certData, err := csr.RequestNodeCertificate(bootstrapClient.CertificateSigningRequests(), keyData, nodeName) if err != nil { return err } - if err := certutil.WriteCert(certPath, certData); err != nil { + if _, err := store.Update(certData, keyData); err != nil { return err } + if err := os.Remove(privKeyPath); err != nil && !os.IsNotExist(err) { + glog.V(2).Infof("failed cleaning up private key file %q: %v", privKeyPath, err) + } + + pemPath := store.CurrentPath() // Get the CA data from the bootstrap client config. caFile, caData := bootstrapClientConfig.CAFile, []byte{} @@ -126,8 +122,8 @@ func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string, }}, // Define auth based on the obtained client cert. AuthInfos: map[string]*clientcmdapi.AuthInfo{"default-auth": { - ClientCertificate: certPath, - ClientKey: keyPath, + ClientCertificate: pemPath, + ClientKey: pemPath, }}, // Define a context that connects the auth info and cluster, and set it as the default Contexts: map[string]*clientcmdapi.Context{"default-context": { @@ -139,12 +135,7 @@ func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string, } // Marshal to disk - if err := clientcmd.WriteToFile(kubeconfigData, kubeconfigPath); err != nil { - return err - } - - success = true - return nil + return clientcmd.WriteToFile(kubeconfigData, kubeconfigPath) } func loadRESTClientConfig(kubeconfig string) (*restclient.Config, error) { @@ -207,3 +198,12 @@ func verifyBootstrapClientConfig(kubeconfigPath string) (bool, error) { } return true, nil } + +// verifyKeyData returns true if the provided data appears to be a valid private key. +func verifyKeyData(data []byte) bool { + if len(data) == 0 { + return false + } + _, err := certutil.ParsePrivateKeyPEM(data) + return err == nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/transport.go b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/transport.go index f980cb6eb..436bb8b4c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/transport.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/certificate/transport.go @@ -17,12 +17,10 @@ limitations under the License. package certificate import ( - "context" "crypto/tls" "fmt" "net" "net/http" - "sync" "time" "github.com/golang/glog" @@ -31,6 +29,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" restclient "k8s.io/client-go/rest" "k8s.io/client-go/util/certificate" + "k8s.io/client-go/util/connrotation" ) // UpdateTransport instruments a restconfig with a transport that dynamically uses @@ -64,80 +63,86 @@ func updateTransport(stopCh <-chan struct{}, period time.Duration, clientConfig return nil, fmt.Errorf("there is already a transport or dialer configured") } - // Custom dialer that will track all connections it creates. - t := &connTracker{ - dialer: &net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}, - conns: make(map[*closableConn]struct{}), + d := connrotation.NewDialer((&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext) + + if clientCertificateManager != nil { + if err := addCertRotation(stopCh, period, clientConfig, clientCertificateManager, exitAfter, d); err != nil { + return nil, err + } + } else { + clientConfig.Dial = d.DialContext } + return d.CloseAll, nil +} + +func addCertRotation(stopCh <-chan struct{}, period time.Duration, clientConfig *restclient.Config, clientCertificateManager certificate.Manager, exitAfter time.Duration, d *connrotation.Dialer) error { tlsConfig, err := restclient.TLSConfigFor(clientConfig) if err != nil { - return nil, fmt.Errorf("unable to configure TLS for the rest client: %v", err) + return fmt.Errorf("unable to configure TLS for the rest client: %v", err) } if tlsConfig == nil { tlsConfig = &tls.Config{} } - if clientCertificateManager != nil { - tlsConfig.Certificates = nil - tlsConfig.GetClientCertificate = func(requestInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) { - cert := clientCertificateManager.Current() - if cert == nil { - return &tls.Certificate{Certificate: nil}, nil - } - return cert, nil + tlsConfig.Certificates = nil + tlsConfig.GetClientCertificate = func(requestInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) { + cert := clientCertificateManager.Current() + if cert == nil { + return &tls.Certificate{Certificate: nil}, nil } + return cert, nil + } - lastCertAvailable := time.Now() - lastCert := clientCertificateManager.Current() - go wait.Until(func() { - curr := clientCertificateManager.Current() - - if exitAfter > 0 { - now := time.Now() - if curr == nil { - // the certificate has been deleted from disk or is otherwise corrupt - if now.After(lastCertAvailable.Add(exitAfter)) { - if clientCertificateManager.ServerHealthy() { - glog.Fatalf("It has been %s since a valid client cert was found and the server is responsive, exiting.", exitAfter) - } else { - glog.Errorf("It has been %s since a valid client cert was found, but the server is not responsive. A restart may be necessary to retrieve new initial credentials.", exitAfter) - } + lastCertAvailable := time.Now() + lastCert := clientCertificateManager.Current() + go wait.Until(func() { + curr := clientCertificateManager.Current() + + if exitAfter > 0 { + now := time.Now() + if curr == nil { + // the certificate has been deleted from disk or is otherwise corrupt + if now.After(lastCertAvailable.Add(exitAfter)) { + if clientCertificateManager.ServerHealthy() { + glog.Fatalf("It has been %s since a valid client cert was found and the server is responsive, exiting.", exitAfter) + } else { + glog.Errorf("It has been %s since a valid client cert was found, but the server is not responsive. A restart may be necessary to retrieve new initial credentials.", exitAfter) } - } else { - // the certificate is expired - if now.After(curr.Leaf.NotAfter) { - if clientCertificateManager.ServerHealthy() { - glog.Fatalf("The currently active client certificate has expired and the server is responsive, exiting.") - } else { - glog.Errorf("The currently active client certificate has expired, but the server is not responsive. A restart may be necessary to retrieve new initial credentials.") - } + } + } else { + // the certificate is expired + if now.After(curr.Leaf.NotAfter) { + if clientCertificateManager.ServerHealthy() { + glog.Fatalf("The currently active client certificate has expired and the server is responsive, exiting.") + } else { + glog.Errorf("The currently active client certificate has expired, but the server is not responsive. A restart may be necessary to retrieve new initial credentials.") } - lastCertAvailable = now } + lastCertAvailable = now } + } - if curr == nil || lastCert == curr { - // Cert hasn't been rotated. - return - } - lastCert = curr - - glog.Infof("certificate rotation detected, shutting down client connections to start using new credentials") - // The cert has been rotated. Close all existing connections to force the client - // to reperform its TLS handshake with new cert. - // - // See: https://github.com/kubernetes-incubator/bootkube/pull/663#issuecomment-318506493 - t.closeAllConns() - }, period, stopCh) - } + if curr == nil || lastCert == curr { + // Cert hasn't been rotated. + return + } + lastCert = curr + + glog.Infof("certificate rotation detected, shutting down client connections to start using new credentials") + // The cert has been rotated. Close all existing connections to force the client + // to reperform its TLS handshake with new cert. + // + // See: https://github.com/kubernetes-incubator/bootkube/pull/663#issuecomment-318506493 + d.CloseAll() + }, period, stopCh) clientConfig.Transport = utilnet.SetTransportDefaults(&http.Transport{ Proxy: http.ProxyFromEnvironment, TLSHandshakeTimeout: 10 * time.Second, TLSClientConfig: tlsConfig, MaxIdleConnsPerHost: 25, - DialContext: t.DialContext, // Use custom dialer. + DialContext: d.DialContext, }) // Zero out all existing TLS options since our new transport enforces them. @@ -149,60 +154,5 @@ func updateTransport(stopCh <-chan struct{}, period time.Duration, clientConfig clientConfig.CAFile = "" clientConfig.Insecure = false - return t.closeAllConns, nil -} - -// connTracker is a dialer that tracks all open connections it creates. -type connTracker struct { - dialer *net.Dialer - - mu sync.Mutex - conns map[*closableConn]struct{} -} - -// closeAllConns forcibly closes all tracked connections. -func (c *connTracker) closeAllConns() { - c.mu.Lock() - conns := c.conns - c.conns = make(map[*closableConn]struct{}) - c.mu.Unlock() - - for conn := range conns { - conn.Close() - } -} - -func (c *connTracker) DialContext(ctx context.Context, network, address string) (net.Conn, error) { - conn, err := c.dialer.DialContext(ctx, network, address) - if err != nil { - return nil, err - } - - closable := &closableConn{Conn: conn} - - // Start tracking the connection - c.mu.Lock() - c.conns[closable] = struct{}{} - c.mu.Unlock() - - // When the connection is closed, remove it from the map. This will - // be no-op if the connection isn't in the map, e.g. if closeAllConns() - // is called. - closable.onClose = func() { - c.mu.Lock() - delete(c.conns, closable) - c.mu.Unlock() - } - - return closable, nil -} - -type closableConn struct { - onClose func() - net.Conn -} - -func (c *closableConn) Close() error { - go c.onClose() - return c.Conn.Close() + return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/BUILD index c04d19819..0be2f14b4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/BUILD @@ -7,9 +7,8 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/apis/core:go_default_library", - "//pkg/volume/util:go_default_library", - "//vendor/github.com/dchest/safefile:go_default_library", - "//vendor/github.com/ghodss/yaml:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", + "//pkg/kubelet/checkpointmanager/checksum:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", ], @@ -21,6 +20,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint.go b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint.go index d4b30f902..e5801312d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint.go @@ -17,20 +17,15 @@ limitations under the License. package checkpoint import ( + "encoding/json" "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - "sync" - - "github.com/dchest/safefile" - "github.com/ghodss/yaml" + "github.com/golang/glog" "k8s.io/api/core/v1" "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/volume/util" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" ) const ( @@ -39,54 +34,44 @@ const ( podPrefix = "Pod" ) -// Manager is the interface used to manage checkpoints -// which involves writing resources to disk to recover -// during restart or failure scenarios. -// https://github.com/kubernetes/community/pull/1241/files -type Manager interface { - // LoadPods will load checkpointed Pods from disk - LoadPods() ([]*v1.Pod, error) - - // WritePod will serialize a Pod to disk - WritePod(pod *v1.Pod) error +type PodCheckpoint interface { + checkpointmanager.Checkpoint + GetPod() *v1.Pod +} - // Deletes the checkpoint of the given pod from disk - DeletePod(pod *v1.Pod) error +// Data to be stored as checkpoint +type Data struct { + Pod *v1.Pod + Checksum checksum.Checksum } -var instance Manager -var mutex = &sync.Mutex{} +// NewPodCheckpoint returns new pod checkpoint +func NewPodCheckpoint(pod *v1.Pod) PodCheckpoint { + return &Data{Pod: pod} +} -// fileCheckPointManager - is a checkpointer that writes contents to disk -// The type information of the resource objects are encoded in the name -type fileCheckPointManager struct { - path string +// MarshalCheckpoint returns marshalled data +func (cp *Data) MarshalCheckpoint() ([]byte, error) { + cp.Checksum = checksum.New(*cp.Pod) + return json.Marshal(*cp) } -// NewCheckpointManager will create a Manager that points to the following path -func NewCheckpointManager(path string) Manager { - // NOTE: This is a precaution; current implementation should not run - // multiple checkpoint managers. - mutex.Lock() - defer mutex.Unlock() - instance = &fileCheckPointManager{path: path} - return instance +// UnmarshalCheckpoint returns unmarshalled data +func (cp *Data) UnmarshalCheckpoint(blob []byte) error { + return json.Unmarshal(blob, cp) } -// GetInstance will return the current Manager, there should be only one. -func GetInstance() Manager { - mutex.Lock() - defer mutex.Unlock() - return instance +// VerifyChecksum verifies that passed checksum is same as calculated checksum +func (cp *Data) VerifyChecksum() error { + return cp.Checksum.Verify(*cp.Pod) } -// loadPod will load Pod Checkpoint yaml file. -func (fcp *fileCheckPointManager) loadPod(file string) (*v1.Pod, error) { - return util.LoadPodFromFile(file) +func (cp *Data) GetPod() *v1.Pod { + return cp.Pod } // checkAnnotations will validate the checkpoint annotations exist on the Pod -func (fcp *fileCheckPointManager) checkAnnotations(pod *v1.Pod) bool { +func checkAnnotations(pod *v1.Pod) bool { if podAnnotations := pod.GetAnnotations(); podAnnotations != nil { if podAnnotations[core.BootstrapCheckpointAnnotationKey] == "true" { return true @@ -95,57 +80,49 @@ func (fcp *fileCheckPointManager) checkAnnotations(pod *v1.Pod) bool { return false } -// getPodPath returns the full qualified path for the pod checkpoint -func (fcp *fileCheckPointManager) getPodPath(pod *v1.Pod) string { - return fmt.Sprintf("%v/Pod%v%v.yaml", fcp.path, delimiter, pod.GetUID()) +//getPodKey returns the full qualified path for the pod checkpoint +func getPodKey(pod *v1.Pod) string { + return fmt.Sprintf("Pod%v%v.yaml", delimiter, pod.GetUID()) } // LoadPods Loads All Checkpoints from disk -func (fcp *fileCheckPointManager) LoadPods() ([]*v1.Pod, error) { - checkpoints := make([]*v1.Pod, 0) - files, err := ioutil.ReadDir(fcp.path) +func LoadPods(cpm checkpointmanager.CheckpointManager) ([]*v1.Pod, error) { + pods := make([]*v1.Pod, 0) + + var err error + checkpointKeys := []string{} + checkpointKeys, err = cpm.ListCheckpoints() if err != nil { - return nil, err + glog.Errorf("Failed to list checkpoints: %v", err) } - for _, f := range files { - // get just the filename - _, fname := filepath.Split(f.Name()) - // Get just the Resource from "Resource_Name" - fnfields := strings.Split(fname, delimiter) - switch fnfields[0] { - case podPrefix: - pod, err := fcp.loadPod(fmt.Sprintf("%s/%s", fcp.path, f.Name())) - if err != nil { - return nil, err - } - checkpoints = append(checkpoints, pod) - default: - glog.Warningf("Unsupported checkpoint file detected %v", f) + + for _, key := range checkpointKeys { + checkpoint := NewPodCheckpoint(nil) + err := cpm.GetCheckpoint(key, checkpoint) + if err != nil { + glog.Errorf("Failed to retrieve checkpoint for pod %q: %v", key, err) + continue } + pods = append(pods, checkpoint.GetPod()) } - return checkpoints, nil + return pods, nil } -// Writes a checkpoint to a file on disk if annotation is present -func (fcp *fileCheckPointManager) WritePod(pod *v1.Pod) error { +// WritePod a checkpoint to a file on disk if annotation is present +func WritePod(cpm checkpointmanager.CheckpointManager, pod *v1.Pod) error { var err error - if fcp.checkAnnotations(pod) { - if blob, err := yaml.Marshal(pod); err == nil { - err = safefile.WriteFile(fcp.getPodPath(pod), blob, 0644) - } + if checkAnnotations(pod) { + data := NewPodCheckpoint(pod) + err = cpm.CreateCheckpoint(getPodKey(pod), data) } else { // This is to handle an edge where a pod update could remove // an annotation and the checkpoint should then be removed. - err = fcp.DeletePod(pod) + err = cpm.RemoveCheckpoint(getPodKey(pod)) } return err } -// Deletes a checkpoint from disk if present -func (fcp *fileCheckPointManager) DeletePod(pod *v1.Pod) error { - podPath := fcp.getPodPath(pod) - if err := os.Remove(podPath); !os.IsNotExist(err) { - return err - } - return nil +// DeletePod deletes a checkpoint from disk if present +func DeletePod(cpm checkpointmanager.CheckpointManager, pod *v1.Pod) error { + return cpm.RemoveCheckpoint(getPodKey(pod)) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint_test.go index 23c35c2c0..e93e61d4e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint_test.go @@ -25,6 +25,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" ) // TestWriteLoadDeletePods validates all combinations of write, load, and delete @@ -70,15 +71,18 @@ func TestWriteLoadDeletePods(t *testing.T) { } defer os.RemoveAll(dir) - cp := NewCheckpointManager(dir) + cpm, err := checkpointmanager.NewCheckpointManager(dir) + if err != nil { + t.Errorf("Failed to initialize checkpoint manager error=%v", err) + } for _, p := range testPods { // Write pods should always pass unless there is an fs error - if err := cp.WritePod(p.pod); err != nil { + if err := WritePod(cpm, p.pod); err != nil { t.Errorf("Failed to Write Pod: %v", err) } } // verify the correct written files are loaded from disk - pods, err := cp.LoadPods() + pods, err := LoadPods(cpm) if err != nil { t.Errorf("Failed to Load Pods: %v", err) } @@ -104,7 +108,7 @@ func TestWriteLoadDeletePods(t *testing.T) { } else if lpod != nil { t.Errorf("Got unexpected result for %v, should not have been loaded", pname) } - err = cp.DeletePod(p.pod) + err = DeletePod(cpm, p.pod) if err != nil { t.Errorf("Failed to delete pod %v", pname) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/BUILD new file mode 100644 index 000000000..0353c2d1c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/BUILD @@ -0,0 +1,48 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = ["checkpoint_manager.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/checkpointmanager", + deps = [ + "//pkg/kubelet/checkpointmanager/errors:go_default_library", + "//pkg/kubelet/util/store:go_default_library", + "//pkg/util/filesystem:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["checkpoint_manager_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/kubelet/checkpointmanager/checksum:go_default_library", + "//pkg/kubelet/checkpointmanager/testing:go_default_library", + "//pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/kubelet/checkpointmanager/checksum:all-srcs", + "//pkg/kubelet/checkpointmanager/errors:all-srcs", + "//pkg/kubelet/checkpointmanager/testing:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/README.md b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/README.md new file mode 100644 index 000000000..07beef130 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/README.md @@ -0,0 +1,25 @@ +## DISCLAIMER +- Sig-Node community has reached a general consensus, as a best practice, to +avoid introducing any new checkpointing support. We reached this understanding +after struggling with some hard-to-debug issues in the production environments +caused by the checkpointing. +- Any changes to the checkpointed data structure would be considered incompatible and a component should add its own handling if it needs to ensure backward compatibility of reading old-format checkpoint files. + +## Introduction +This folder contains a framework & primitives, Checkpointing Manager, which is +used by several other Kubelet submodules, `dockershim`, `devicemanager`, `pods` +and `cpumanager`, to implement checkpointing at each submodule level. As already +explained in above `Disclaimer` section, think twice before introducing any further +checkpointing in Kubelet. If still checkpointing is required, then this folder +provides the common APIs and the framework for implementing checkpointing. +Using same APIs across all the submodules will help maintaining consistency at +Kubelet level. + +Below is the history of checkpointing support in Kubelet. + +| Package | First checkpointing support merged on | PR link | +| ------- | --------------------------------------| ------- | +|kubelet/dockershim | Feb 3, 2017 | [[CRI] Implement Dockershim Checkpoint](https://github.com/kubernetes/kubernetes/pull/39903) +|devicemanager| Sep 6, 2017 | [Deviceplugin checkpoint](https://github.com/kubernetes/kubernetes/pull/51744) +| kubelet/pod | Nov 22, 2017 | [Initial basic bootstrap-checkpoint support](https://github.com/kubernetes/kubernetes/pull/50984) +|cpumanager| Oct 27, 2017 |[Add file backed state to cpu manager ](https://github.com/kubernetes/kubernetes/pull/54408) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checkpoint_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checkpoint_manager.go new file mode 100644 index 000000000..f16e96044 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checkpoint_manager.go @@ -0,0 +1,110 @@ +/* +Copyright 2018 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 checkpointmanager + +import ( + "fmt" + "sync" + + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" + utilstore "k8s.io/kubernetes/pkg/kubelet/util/store" + utilfs "k8s.io/kubernetes/pkg/util/filesystem" +) + +// Checkpoint provides the process checkpoint data +type Checkpoint interface { + MarshalCheckpoint() ([]byte, error) + UnmarshalCheckpoint(blob []byte) error + VerifyChecksum() error +} + +// CheckpointManager provides the interface to manage checkpoint +type CheckpointManager interface { + // CreateCheckpoint persists checkpoint in CheckpointStore. checkpointKey is the key for utilstore to locate checkpoint. + // For file backed utilstore, checkpointKey is the file name to write the checkpoint data. + CreateCheckpoint(checkpointKey string, checkpoint Checkpoint) error + // GetCheckpoint retrieves checkpoint from CheckpointStore. + GetCheckpoint(checkpointKey string, checkpoint Checkpoint) error + // WARNING: RemoveCheckpoint will not return error if checkpoint does not exist. + RemoveCheckpoint(checkpointKey string) error + // ListCheckpoint returns the list of existing checkpoints. + ListCheckpoints() ([]string, error) +} + +// impl is an implementation of CheckpointManager. It persists checkpoint in CheckpointStore +type impl struct { + path string + store utilstore.Store + mutex sync.Mutex +} + +// NewCheckpointManager returns a new instance of a checkpoint manager +func NewCheckpointManager(checkpointDir string) (CheckpointManager, error) { + fstore, err := utilstore.NewFileStore(checkpointDir, utilfs.DefaultFs{}) + if err != nil { + return nil, err + } + + return &impl{path: checkpointDir, store: fstore}, nil +} + +// CreateCheckpoint persists checkpoint in CheckpointStore. +func (manager *impl) CreateCheckpoint(checkpointKey string, checkpoint Checkpoint) error { + manager.mutex.Lock() + defer manager.mutex.Unlock() + blob, err := checkpoint.MarshalCheckpoint() + if err != nil { + return err + } + return manager.store.Write(checkpointKey, blob) +} + +// GetCheckpoint retrieves checkpoint from CheckpointStore. +func (manager *impl) GetCheckpoint(checkpointKey string, checkpoint Checkpoint) error { + manager.mutex.Lock() + defer manager.mutex.Unlock() + blob, err := manager.store.Read(checkpointKey) + if err != nil { + if err == utilstore.ErrKeyNotFound { + return errors.ErrCheckpointNotFound + } + return err + } + err = checkpoint.UnmarshalCheckpoint(blob) + if err == nil { + err = checkpoint.VerifyChecksum() + } + return err +} + +// RemoveCheckpoint will not return error if checkpoint does not exist. +func (manager *impl) RemoveCheckpoint(checkpointKey string) error { + manager.mutex.Lock() + defer manager.mutex.Unlock() + return manager.store.Delete(checkpointKey) +} + +// ListCheckpoints returns the list of existing checkpoints. +func (manager *impl) ListCheckpoints() ([]string, error) { + manager.mutex.Lock() + defer manager.mutex.Unlock() + keys, err := manager.store.List() + if err != nil { + return []string{}, fmt.Errorf("failed to list checkpoint store: %v", err) + } + return keys, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checkpoint_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checkpoint_manager_test.go new file mode 100644 index 000000000..6081e9048 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checkpoint_manager_test.go @@ -0,0 +1,245 @@ +/* +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 checkpointmanager + +import ( + "encoding/json" + "sort" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" + utilstore "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1" +) + +var testStore *utilstore.MemStore + +type FakeCheckpoint interface { + Checkpoint + GetData() ([]*PortMapping, bool) +} + +// Data contains all types of data that can be stored in the checkpoint. +type Data struct { + PortMappings []*PortMapping `json:"port_mappings,omitempty"` + HostNetwork bool `json:"host_network,omitempty"` +} + +type CheckpointDataV2 struct { + PortMappings []*PortMapping `json:"port_mappings,omitempty"` + HostNetwork bool `json:"host_network,omitempty"` + V2Field string `json:"v2field"` +} + +type protocol string + +// portMapping is the port mapping configurations of a sandbox. +type PortMapping struct { + // protocol of the port mapping. + Protocol *protocol + // Port number within the container. + ContainerPort *int32 + // Port number on the host. + HostPort *int32 +} + +// CheckpointData is a sample example structure to be used in test cases for checkpointing +type CheckpointData struct { + Version string + Name string + Data *Data + Checksum checksum.Checksum +} + +func newFakeCheckpointV1(name string, portMappings []*PortMapping, hostNetwork bool) FakeCheckpoint { + return &CheckpointData{ + Version: "v1", + Name: name, + Data: &Data{ + PortMappings: portMappings, + HostNetwork: hostNetwork, + }, + } +} + +func (cp *CheckpointData) MarshalCheckpoint() ([]byte, error) { + cp.Checksum = checksum.New(*cp.Data) + return json.Marshal(*cp) +} + +func (cp *CheckpointData) UnmarshalCheckpoint(blob []byte) error { + return json.Unmarshal(blob, cp) +} + +func (cp *CheckpointData) VerifyChecksum() error { + return cp.Checksum.Verify(*cp.Data) +} + +func (cp *CheckpointData) GetData() ([]*PortMapping, bool) { + return cp.Data.PortMappings, cp.Data.HostNetwork +} + +type checkpointDataV2 struct { + Version string + Name string + Data *CheckpointDataV2 + Checksum checksum.Checksum +} + +func newFakeCheckpointV2(name string, portMappings []*PortMapping, hostNetwork bool) FakeCheckpoint { + return &checkpointDataV2{ + Version: "v2", + Name: name, + Data: &CheckpointDataV2{ + PortMappings: portMappings, + HostNetwork: hostNetwork, + }, + } +} + +func newFakeCheckpointRemoteV1(name string, portMappings []*v1.PortMapping, hostNetwork bool) Checkpoint { + return &v1.CheckpointData{ + Version: "v1", + Name: name, + Data: &v1.Data{ + PortMappings: portMappings, + HostNetwork: hostNetwork, + }, + } +} + +func (cp *checkpointDataV2) MarshalCheckpoint() ([]byte, error) { + cp.Checksum = checksum.New(*cp.Data) + return json.Marshal(*cp) +} + +func (cp *checkpointDataV2) UnmarshalCheckpoint(blob []byte) error { + return json.Unmarshal(blob, cp) +} + +func (cp *checkpointDataV2) VerifyChecksum() error { + return cp.Checksum.Verify(*cp.Data) +} + +func (cp *checkpointDataV2) GetData() ([]*PortMapping, bool) { + return cp.Data.PortMappings, cp.Data.HostNetwork +} + +func newTestCheckpointManager() CheckpointManager { + return &impl{store: testStore} +} + +func TestCheckpointManager(t *testing.T) { + var err error + testStore = utilstore.NewMemStore() + manager := newTestCheckpointManager() + port80 := int32(80) + port443 := int32(443) + proto := protocol("tcp") + + portMappings := []*PortMapping{ + { + &proto, + &port80, + &port80, + }, + { + &proto, + &port443, + &port443, + }, + } + checkpoint1 := newFakeCheckpointV1("check1", portMappings, true) + + checkpoints := []struct { + checkpointKey string + checkpoint FakeCheckpoint + expectHostNetwork bool + }{ + { + "key1", + checkpoint1, + true, + }, + { + "key2", + newFakeCheckpointV1("check2", nil, false), + false, + }, + } + + for _, tc := range checkpoints { + // Test CreateCheckpoints + err = manager.CreateCheckpoint(tc.checkpointKey, tc.checkpoint) + assert.NoError(t, err) + + // Test GetCheckpoints + checkpointOut := newFakeCheckpointV1("", nil, false) + err := manager.GetCheckpoint(tc.checkpointKey, checkpointOut) + assert.NoError(t, err) + actualPortMappings, actualHostNetwork := checkpointOut.GetData() + expPortMappings, expHostNetwork := tc.checkpoint.GetData() + assert.Equal(t, actualPortMappings, expPortMappings) + assert.Equal(t, actualHostNetwork, expHostNetwork) + } + // Test it fails if tried to read V1 structure into V2, a different structure from the structure which is checkpointed + checkpointV2 := newFakeCheckpointV2("", nil, false) + err = manager.GetCheckpoint("key1", checkpointV2) + assert.EqualError(t, err, "checkpoint is corrupted") + + // Test it fails if tried to read V1 structure into the same structure but defined in another package + checkpointRemoteV1 := newFakeCheckpointRemoteV1("", nil, false) + err = manager.GetCheckpoint("key1", checkpointRemoteV1) + assert.EqualError(t, err, "checkpoint is corrupted") + + // Test it works if tried to read V1 structure using into a new V1 structure + checkpointV1 := newFakeCheckpointV1("", nil, false) + err = manager.GetCheckpoint("key1", checkpointV1) + assert.NoError(t, err) + + // Test corrupt checksum case + checkpointOut := newFakeCheckpointV1("", nil, false) + blob, err := checkpointOut.MarshalCheckpoint() + assert.NoError(t, err) + testStore.Write("key1", blob) + err = manager.GetCheckpoint("key1", checkpoint1) + assert.EqualError(t, err, "checkpoint is corrupted") + + // Test ListCheckpoints + keys, err := manager.ListCheckpoints() + assert.NoError(t, err) + sort.Strings(keys) + assert.Equal(t, keys, []string{"key1", "key2"}) + + // Test RemoveCheckpoints + err = manager.RemoveCheckpoint("key1") + assert.NoError(t, err) + // Test Remove Nonexisted Checkpoints + err = manager.RemoveCheckpoint("key1") + assert.NoError(t, err) + + // Test ListCheckpoints + keys, err = manager.ListCheckpoints() + assert.NoError(t, err) + assert.Equal(t, keys, []string{"key2"}) + + // Test Get NonExisted Checkpoint + checkpointNE := newFakeCheckpointV1("NE", nil, false) + err = manager.GetCheckpoint("key1", checkpointNE) + assert.Error(t, err) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum/BUILD new file mode 100644 index 000000000..cb86b212b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum/BUILD @@ -0,0 +1,26 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["checksum.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum", + visibility = ["//visibility:public"], + deps = [ + "//pkg/kubelet/checkpointmanager/errors:go_default_library", + "//pkg/util/hash:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum/checksum.go b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum/checksum.go new file mode 100644 index 000000000..b2a98e45b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum/checksum.go @@ -0,0 +1,46 @@ +/* +Copyright 2018 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 checksum + +import ( + "hash/fnv" + + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" + hashutil "k8s.io/kubernetes/pkg/util/hash" +) + +// Data to be stored as checkpoint +type Checksum uint64 + +// VerifyChecksum verifies that passed checksum is same as calculated checksum +func (cs Checksum) Verify(data interface{}) error { + if cs != New(data) { + return errors.ErrCorruptCheckpoint + } + return nil +} + +func New(data interface{}) Checksum { + return Checksum(getChecksum(data)) +} + +// Get returns calculated checksum of checkpoint data +func getChecksum(data interface{}) uint64 { + hash := fnv.New32a() + hashutil.DeepHashObject(hash, data) + return uint64(hash.Sum32()) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors/BUILD new file mode 100644 index 000000000..76c04fe90 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors/BUILD @@ -0,0 +1,25 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["errors.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors", +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors/errors.go b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors/errors.go new file mode 100644 index 000000000..bb445f207 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors/errors.go @@ -0,0 +1,25 @@ +/* +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 errors + +import "fmt" + +// ErrCorruptCheckpoint error is reported when checksum does not match +var ErrCorruptCheckpoint = fmt.Errorf("checkpoint is corrupted") + +// ErrCheckpointNotFound is reported when checkpoint is not found for a given key +var ErrCheckpointNotFound = fmt.Errorf("checkpoint is not found") diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/BUILD new file mode 100644 index 000000000..51c6764da --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/BUILD @@ -0,0 +1,28 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["util.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing", +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1/BUILD new file mode 100644 index 000000000..e8a30850f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["types.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1", + visibility = ["//visibility:public"], + deps = ["//pkg/kubelet/checkpointmanager/checksum:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1/types.go new file mode 100644 index 000000000..7a883d5b5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/example_checkpoint_formats/v1/types.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 ( + "encoding/json" + + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" +) + +type protocol string + +// portMapping is the port mapping configurations of a sandbox. +type PortMapping struct { + // protocol of the port mapping. + Protocol *protocol + // Port number within the container. + ContainerPort *int32 + // Port number on the host. + HostPort *int32 +} + +// CheckpointData contains all types of data that can be stored in the checkpoint. +type Data struct { + PortMappings []*PortMapping `json:"port_mappings,omitempty"` + HostNetwork bool `json:"host_network,omitempty"` +} + +// CheckpointData is a sample example structure to be used in test cases for checkpointing +type CheckpointData struct { + Version string + Name string + Data *Data + Checksum checksum.Checksum +} + +func (cp *CheckpointData) MarshalCheckpoint() ([]byte, error) { + cp.Checksum = checksum.New(*cp.Data) + return json.Marshal(*cp) +} + +func (cp *CheckpointData) UnmarshalCheckpoint(blob []byte) error { + return json.Unmarshal(blob, cp) +} + +func (cp *CheckpointData) VerifyChecksum() error { + return cp.Checksum.Verify(*cp.Data) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/util.go b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/util.go new file mode 100644 index 000000000..8ca4af1d3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/testing/util.go @@ -0,0 +1,71 @@ +/* +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 testing + +import ( + "fmt" + "sync" +) + +// MemStore is an implementation of CheckpointStore interface which stores checkpoint in memory. +type MemStore struct { + mem map[string][]byte + sync.Mutex +} + +// NewMemStore returns an instance of MemStore +func NewMemStore() *MemStore { + return &MemStore{mem: make(map[string][]byte)} +} + +// Write writes the data to the store +func (mstore *MemStore) Write(key string, data []byte) error { + mstore.Lock() + defer mstore.Unlock() + mstore.mem[key] = data + return nil +} + +// Read returns data read from store +func (mstore *MemStore) Read(key string) ([]byte, error) { + mstore.Lock() + defer mstore.Unlock() + data, ok := mstore.mem[key] + if !ok { + return nil, fmt.Errorf("checkpoint is not found") + } + return data, nil +} + +// Delete deletes data from the store +func (mstore *MemStore) Delete(key string) error { + mstore.Lock() + defer mstore.Unlock() + delete(mstore.mem, key) + return nil +} + +// List returns all the keys from the store +func (mstore *MemStore) List() ([]string, error) { + mstore.Lock() + defer mstore.Unlock() + keys := make([]string, 0) + for key := range mstore.mem { + keys = append(keys, key) + } + return keys, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/client/kubelet_client.go b/vendor/k8s.io/kubernetes/pkg/kubelet/client/kubelet_client.go index 32b0c42dd..228bab2aa 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/client/kubelet_client.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/client/kubelet_client.go @@ -74,7 +74,7 @@ func MakeTransport(config *KubeletClientConfig) (http.RoundTripper, error) { rt := http.DefaultTransport if config.Dial != nil || tlsConfig != nil { rt = utilnet.SetOldTransportDefaults(&http.Transport{ - Dial: config.Dial, + DialContext: config.Dial, TLSClientConfig: tlsConfig, }) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/BUILD index 6ecc65279..8bfdd017d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/BUILD @@ -91,7 +91,7 @@ go_library( "//pkg/kubelet/eviction/api:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/status:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -188,6 +188,7 @@ go_test( "container_manager_linux_test.go", "helpers_linux_test.go", "node_container_manager_test.go", + "pod_container_manager_linux_test.go", ], "//conditions:default": [], }), @@ -200,6 +201,7 @@ go_test( "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", ], "//conditions:default": [], }), diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux.go index 9f23817f1..6a4d65cd8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux.go @@ -53,74 +53,79 @@ const ( // which is what is expected when interacting with libcontainer var hugePageSizeList = []string{"B", "kB", "MB", "GB", "TB", "PB"} -// ConvertCgroupNameToSystemd converts the internal cgroup name to a systemd name. -// For example, the name /Burstable/pod_123-456 becomes Burstable-pod_123_456.slice -// If outputToCgroupFs is true, it expands the systemd name into the cgroupfs form. -// For example, it will return /Burstable.slice/Burstable-pod_123_456.slice in above scenario. -func ConvertCgroupNameToSystemd(cgroupName CgroupName, outputToCgroupFs bool) string { - name := string(cgroupName) - result := "" - if name != "" && name != "/" { - parts := strings.Split(name, "/") - results := []string{} - for _, part := range parts { - // ignore leading stuff - if part == "" { - continue - } - // detect if we are given a systemd style name. - // if so, we do not want to do double encoding. - if IsSystemdStyleName(part) { - part = strings.TrimSuffix(part, systemdSuffix) - separatorIndex := strings.LastIndex(part, "-") - if separatorIndex >= 0 && separatorIndex < len(part) { - part = part[separatorIndex+1:] - } - } else { - // systemd treats - as a step in the hierarchy, we convert all - to _ - part = strings.Replace(part, "-", "_", -1) - } - results = append(results, part) +var RootCgroupName = CgroupName([]string{}) + +// NewCgroupName composes a new cgroup name. +// Use RootCgroupName as base to start at the root. +// This function does some basic check for invalid characters at the name. +func NewCgroupName(base CgroupName, components ...string) CgroupName { + for _, component := range components { + // Forbit using "_" in internal names. When remapping internal + // names to systemd cgroup driver, we want to remap "-" => "_", + // so we forbid "_" so that we can always reverse the mapping. + if strings.Contains(component, "/") || strings.Contains(component, "_") { + panic(fmt.Errorf("invalid character in component [%q] of CgroupName", component)) } - // each part is appended with systemd style - - result = strings.Join(results, "-") - } else { - // root converts to - - result = "-" } - // always have a .slice suffix - if !IsSystemdStyleName(result) { - result = result + systemdSuffix + return CgroupName(append(base, components...)) +} + +func escapeSystemdCgroupName(part string) string { + return strings.Replace(part, "-", "_", -1) +} + +func unescapeSystemdCgroupName(part string) string { + return strings.Replace(part, "_", "-", -1) +} + +// cgroupName.ToSystemd converts the internal cgroup name to a systemd name. +// For example, the name {"kubepods", "burstable", "pod1234-abcd-5678-efgh"} becomes +// "/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod1234_abcd_5678_efgh.slice" +// This function always expands the systemd name into the cgroupfs form. If only +// the last part is needed, use path.Base(...) on it to discard the rest. +func (cgroupName CgroupName) ToSystemd() string { + if len(cgroupName) == 0 || (len(cgroupName) == 1 && cgroupName[0] == "") { + return "/" + } + newparts := []string{} + for _, part := range cgroupName { + part = escapeSystemdCgroupName(part) + newparts = append(newparts, part) } - // if the caller desired the result in cgroupfs format... - if outputToCgroupFs { - var err error - result, err = cgroupsystemd.ExpandSlice(result) - if err != nil { - panic(fmt.Errorf("error adapting cgroup name, input: %v, err: %v", name, err)) - } + result, err := cgroupsystemd.ExpandSlice(strings.Join(newparts, "-") + systemdSuffix) + if err != nil { + // Should never happen... + panic(fmt.Errorf("error converting cgroup name [%v] to systemd format: %v", cgroupName, err)) } return result } -// ConvertCgroupFsNameToSystemd converts an expanded cgroupfs name to its systemd name. -// For example, it will convert test.slice/test-a.slice/test-a-b.slice to become test-a-b.slice -// NOTE: this is public right now to allow its usage in dockermanager and dockershim, ideally both those -// code areas could use something from libcontainer if we get this style function upstream. -func ConvertCgroupFsNameToSystemd(cgroupfsName string) (string, error) { - // TODO: see if libcontainer systemd implementation could use something similar, and if so, move - // this function up to that library. At that time, it would most likely do validation specific to systemd - // above and beyond the simple assumption here that the base of the path encodes the hierarchy - // per systemd convention. - return path.Base(cgroupfsName), nil +func ParseSystemdToCgroupName(name string) CgroupName { + driverName := path.Base(name) + driverName = strings.TrimSuffix(driverName, systemdSuffix) + parts := strings.Split(driverName, "-") + result := []string{} + for _, part := range parts { + result = append(result, unescapeSystemdCgroupName(part)) + } + return CgroupName(result) } -func IsSystemdStyleName(name string) bool { - if strings.HasSuffix(name, systemdSuffix) { - return true +func (cgroupName CgroupName) ToCgroupfs() string { + return "/" + path.Join(cgroupName...) +} + +func ParseCgroupfsToCgroupName(name string) CgroupName { + components := strings.Split(strings.TrimPrefix(name, "/"), "/") + if len(components) == 1 && components[0] == "" { + components = []string{} } - return false + return CgroupName(components) +} + +func IsSystemdStyleName(name string) bool { + return strings.HasSuffix(name, systemdSuffix) } // libcontainerAdapter provides a simplified interface to libcontainer based on libcontainer type. @@ -156,34 +161,6 @@ func (l *libcontainerAdapter) newManager(cgroups *libcontainerconfigs.Cgroup, pa return nil, fmt.Errorf("invalid cgroup manager configuration") } -func (l *libcontainerAdapter) revertName(name string) CgroupName { - if l.cgroupManagerType != libcontainerSystemd { - return CgroupName(name) - } - return CgroupName(RevertFromSystemdToCgroupStyleName(name)) -} - -func RevertFromSystemdToCgroupStyleName(name string) string { - driverName, err := ConvertCgroupFsNameToSystemd(name) - if err != nil { - panic(err) - } - driverName = strings.TrimSuffix(driverName, systemdSuffix) - driverName = strings.Replace(driverName, "-", "/", -1) - driverName = strings.Replace(driverName, "_", "-", -1) - return driverName -} - -// adaptName converts a CgroupName identifier to a driver specific conversion value. -// if outputToCgroupFs is true, the result is returned in the cgroupfs format rather than the driver specific form. -func (l *libcontainerAdapter) adaptName(cgroupName CgroupName, outputToCgroupFs bool) string { - if l.cgroupManagerType != libcontainerSystemd { - name := string(cgroupName) - return name - } - return ConvertCgroupNameToSystemd(cgroupName, outputToCgroupFs) -} - // CgroupSubsystems holds information about the mounted cgroup subsystems type CgroupSubsystems struct { // Cgroup subsystem mounts. @@ -223,13 +200,22 @@ func NewCgroupManager(cs *CgroupSubsystems, cgroupDriver string) CgroupManager { } // Name converts the cgroup to the driver specific value in cgroupfs form. +// This always returns a valid cgroupfs path even when systemd driver is in use! func (m *cgroupManagerImpl) Name(name CgroupName) string { - return m.adapter.adaptName(name, true) + if m.adapter.cgroupManagerType == libcontainerSystemd { + return name.ToSystemd() + } else { + return name.ToCgroupfs() + } } // CgroupName converts the literal cgroupfs name on the host to an internal identifier. func (m *cgroupManagerImpl) CgroupName(name string) CgroupName { - return m.adapter.revertName(name) + if m.adapter.cgroupManagerType == libcontainerSystemd { + return ParseSystemdToCgroupName(name) + } else { + return ParseCgroupfsToCgroupName(name) + } } // buildCgroupPaths builds a path to each cgroup subsystem for the specified name. @@ -242,6 +228,22 @@ func (m *cgroupManagerImpl) buildCgroupPaths(name CgroupName) map[string]string return cgroupPaths } +// TODO(filbranden): This logic belongs in libcontainer/cgroup/systemd instead. +// It should take a libcontainerconfigs.Cgroup.Path field (rather than Name and Parent) +// and split it appropriately, using essentially the logic below. +// This was done for cgroupfs in opencontainers/runc#497 but a counterpart +// for systemd was never introduced. +func updateSystemdCgroupInfo(cgroupConfig *libcontainerconfigs.Cgroup, cgroupName CgroupName) { + dir, base := path.Split(cgroupName.ToSystemd()) + if dir == "/" { + dir = "-.slice" + } else { + dir = path.Base(dir) + } + cgroupConfig.Parent = dir + cgroupConfig.Name = base +} + // Exists checks if all subsystem cgroups already exist func (m *cgroupManagerImpl) Exists(name CgroupName) bool { // Get map of all cgroup paths on the system for the particular cgroup @@ -278,23 +280,13 @@ func (m *cgroupManagerImpl) Destroy(cgroupConfig *CgroupConfig) error { cgroupPaths := m.buildCgroupPaths(cgroupConfig.Name) - // we take the location in traditional cgroupfs format. - abstractCgroupFsName := string(cgroupConfig.Name) - abstractParent := CgroupName(path.Dir(abstractCgroupFsName)) - abstractName := CgroupName(path.Base(abstractCgroupFsName)) - - driverParent := m.adapter.adaptName(abstractParent, false) - driverName := m.adapter.adaptName(abstractName, false) - - // this is an ugly abstraction bleed, but systemd cgroup driver requires full paths... + libcontainerCgroupConfig := &libcontainerconfigs.Cgroup{} + // libcontainer consumes a different field and expects a different syntax + // depending on the cgroup driver in use, so we need this conditional here. if m.adapter.cgroupManagerType == libcontainerSystemd { - driverName = m.adapter.adaptName(cgroupConfig.Name, false) - } - - // Initialize libcontainer's cgroup config with driver specific naming. - libcontainerCgroupConfig := &libcontainerconfigs.Cgroup{ - Name: driverName, - Parent: driverParent, + updateSystemdCgroupInfo(libcontainerCgroupConfig, cgroupConfig.Name) + } else { + libcontainerCgroupConfig.Path = cgroupConfig.Name.ToCgroupfs() } manager, err := m.adapter.newManager(libcontainerCgroupConfig, cgroupPaths) @@ -418,26 +410,17 @@ func (m *cgroupManagerImpl) Update(cgroupConfig *CgroupConfig) error { cgroupPaths := m.buildCgroupPaths(cgroupConfig.Name) - // we take the location in traditional cgroupfs format. - abstractCgroupFsName := string(cgroupConfig.Name) - abstractParent := CgroupName(path.Dir(abstractCgroupFsName)) - abstractName := CgroupName(path.Base(abstractCgroupFsName)) - - driverParent := m.adapter.adaptName(abstractParent, false) - driverName := m.adapter.adaptName(abstractName, false) - - // this is an ugly abstraction bleed, but systemd cgroup driver requires full paths... - if m.adapter.cgroupManagerType == libcontainerSystemd { - driverName = m.adapter.adaptName(cgroupConfig.Name, false) - } - - // Initialize libcontainer's cgroup config libcontainerCgroupConfig := &libcontainerconfigs.Cgroup{ - Name: driverName, - Parent: driverParent, Resources: resources, Paths: cgroupPaths, } + // libcontainer consumes a different field and expects a different syntax + // depending on the cgroup driver in use, so we need this conditional here. + if m.adapter.cgroupManagerType == libcontainerSystemd { + updateSystemdCgroupInfo(libcontainerCgroupConfig, cgroupConfig.Name) + } else { + libcontainerCgroupConfig.Path = cgroupConfig.Name.ToCgroupfs() + } if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.SupportPodPidsLimit) && cgroupConfig.ResourceParameters.PodPidsLimit != nil { libcontainerCgroupConfig.PidsLimit = *cgroupConfig.ResourceParameters.PodPidsLimit @@ -456,25 +439,18 @@ func (m *cgroupManagerImpl) Create(cgroupConfig *CgroupConfig) error { metrics.CgroupManagerLatency.WithLabelValues("create").Observe(metrics.SinceInMicroseconds(start)) }() - // we take the location in traditional cgroupfs format. - abstractCgroupFsName := string(cgroupConfig.Name) - abstractParent := CgroupName(path.Dir(abstractCgroupFsName)) - abstractName := CgroupName(path.Base(abstractCgroupFsName)) - - driverParent := m.adapter.adaptName(abstractParent, false) - driverName := m.adapter.adaptName(abstractName, false) - // this is an ugly abstraction bleed, but systemd cgroup driver requires full paths... - if m.adapter.cgroupManagerType == libcontainerSystemd { - driverName = m.adapter.adaptName(cgroupConfig.Name, false) - } - resources := m.toResources(cgroupConfig.ResourceParameters) - // Initialize libcontainer's cgroup config with driver specific naming. + libcontainerCgroupConfig := &libcontainerconfigs.Cgroup{ - Name: driverName, - Parent: driverParent, Resources: resources, } + // libcontainer consumes a different field and expects a different syntax + // depending on the cgroup driver in use, so we need this conditional here. + if m.adapter.cgroupManagerType == libcontainerSystemd { + updateSystemdCgroupInfo(libcontainerCgroupConfig, cgroupConfig.Name) + } else { + libcontainerCgroupConfig.Path = cgroupConfig.Name.ToCgroupfs() + } if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.SupportPodPidsLimit) && cgroupConfig.ResourceParameters.PodPidsLimit != nil { libcontainerCgroupConfig.PidsLimit = *cgroupConfig.ResourceParameters.PodPidsLimit diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux_test.go index 9947c15da..eb71014c5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux_test.go @@ -18,119 +18,105 @@ limitations under the License. package cm -import "testing" +import ( + "path" + "testing" +) -func TestLibcontainerAdapterAdaptToSystemd(t *testing.T) { +func TestCgroupNameToSystemdBasename(t *testing.T) { testCases := []struct { - input string + input CgroupName expected string }{ { - input: "/", - expected: "-.slice", + input: RootCgroupName, + expected: "/", }, { - input: "/system.slice", + input: NewCgroupName(RootCgroupName, "system"), expected: "system.slice", }, { - input: "/system.slice/Burstable", + input: NewCgroupName(RootCgroupName, "system", "Burstable"), expected: "system-Burstable.slice", }, { - input: "/Burstable.slice/Burstable-pod_123.slice", + input: NewCgroupName(RootCgroupName, "Burstable", "pod-123"), expected: "Burstable-pod_123.slice", }, { - input: "/test.slice/test-a.slice/test-a-b.slice", + input: NewCgroupName(RootCgroupName, "test", "a", "b"), expected: "test-a-b.slice", }, { - input: "/test.slice/test-a.slice/test-a-b.slice/Burstable", + input: NewCgroupName(RootCgroupName, "test", "a", "b", "Burstable"), expected: "test-a-b-Burstable.slice", }, { - input: "/Burstable", + input: NewCgroupName(RootCgroupName, "Burstable"), expected: "Burstable.slice", }, { - input: "/Burstable/pod_123", - expected: "Burstable-pod_123.slice", - }, - { - input: "/BestEffort/pod_6c1a4e95-6bb6-11e6-bc26-28d2444e470d", + input: NewCgroupName(RootCgroupName, "BestEffort", "pod-6c1a4e95-6bb6-11e6-bc26-28d2444e470d"), expected: "BestEffort-pod_6c1a4e95_6bb6_11e6_bc26_28d2444e470d.slice", }, } for _, testCase := range testCases { - f := newLibcontainerAdapter(libcontainerSystemd) - if actual := f.adaptName(CgroupName(testCase.input), false); actual != testCase.expected { + if actual := path.Base(testCase.input.ToSystemd()); actual != testCase.expected { t.Errorf("Unexpected result, input: %v, expected: %v, actual: %v", testCase.input, testCase.expected, actual) } } } -func TestLibcontainerAdapterAdaptToSystemdAsCgroupFs(t *testing.T) { +func TestCgroupNameToSystemd(t *testing.T) { testCases := []struct { - input string + input CgroupName expected string }{ { - input: "/", + input: RootCgroupName, expected: "/", }, { - input: "/Burstable", + input: NewCgroupName(RootCgroupName, "Burstable"), expected: "/Burstable.slice", }, { - input: "/Burstable/pod_123", + input: NewCgroupName(RootCgroupName, "Burstable", "pod-123"), expected: "/Burstable.slice/Burstable-pod_123.slice", }, { - input: "/BestEffort/pod_6c1a4e95-6bb6-11e6-bc26-28d2444e470d", + input: NewCgroupName(RootCgroupName, "BestEffort", "pod-6c1a4e95-6bb6-11e6-bc26-28d2444e470d"), expected: "/BestEffort.slice/BestEffort-pod_6c1a4e95_6bb6_11e6_bc26_28d2444e470d.slice", }, { - input: "/kubepods", + input: NewCgroupName(RootCgroupName, "kubepods"), expected: "/kubepods.slice", }, } for _, testCase := range testCases { - f := newLibcontainerAdapter(libcontainerSystemd) - if actual := f.adaptName(CgroupName(testCase.input), true); actual != testCase.expected { + if actual := testCase.input.ToSystemd(); actual != testCase.expected { t.Errorf("Unexpected result, input: %v, expected: %v, actual: %v", testCase.input, testCase.expected, actual) } } } -func TestLibcontainerAdapterNotAdaptToSystemd(t *testing.T) { - cgroupfs := newLibcontainerAdapter(libcontainerCgroupfs) - otherAdatper := newLibcontainerAdapter(libcontainerCgroupManagerType("test")) - +func TestCgroupNameToCgroupfs(t *testing.T) { testCases := []struct { - input string + input CgroupName expected string }{ { - input: "/", + input: RootCgroupName, expected: "/", }, { - input: "/Burstable", + input: NewCgroupName(RootCgroupName, "Burstable"), expected: "/Burstable", }, - { - input: "", - expected: "", - }, } for _, testCase := range testCases { - if actual := cgroupfs.adaptName(CgroupName(testCase.input), true); actual != testCase.expected { - t.Errorf("Unexpected result, input: %v, expected: %v, actual: %v", testCase.input, testCase.expected, actual) - } - - if actual := otherAdatper.adaptName(CgroupName(testCase.input), true); actual != testCase.expected { + if actual := testCase.input.ToCgroupfs(); actual != testCase.expected { t.Errorf("Unexpected result, input: %v, expected: %v, actual: %v", testCase.input, testCase.expected, actual) } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_unsupported.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_unsupported.go index 34345985c..5d77ed7a4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_unsupported.go @@ -63,25 +63,35 @@ func (m *unsupportedCgroupManager) Pids(_ CgroupName) []int { } func (m *unsupportedCgroupManager) CgroupName(name string) CgroupName { - return "" + return CgroupName([]string{}) } func (m *unsupportedCgroupManager) ReduceCPULimits(cgroupName CgroupName) error { return nil } -func ConvertCgroupFsNameToSystemd(cgroupfsName string) (string, error) { - return "", nil +var RootCgroupName = CgroupName([]string{}) + +func NewCgroupName(base CgroupName, components ...string) CgroupName { + return CgroupName(append(base, components...)) } -func ConvertCgroupNameToSystemd(cgroupName CgroupName, outputToCgroupFs bool) string { +func (cgroupName CgroupName) ToSystemd() string { return "" } -func RevertFromSystemdToCgroupStyleName(name string) string { +func ParseSystemdToCgroupName(name string) CgroupName { + return nil +} + +func (cgroupName CgroupName) ToCgroupfs() string { return "" } +func ParseCgroupfsToCgroupName(name string) CgroupName { + return nil +} + func IsSystemdStyleName(name string) bool { return false } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager.go index 2a64db671..14a17396a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager.go @@ -28,7 +28,7 @@ import ( evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/status" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "fmt" "strconv" @@ -107,7 +107,7 @@ type NodeConfig struct { KubeletRootDir string ProtectKernelDefaults bool NodeAllocatableConfig - ExperimentalQOSReserved map[v1.ResourceName]int64 + QOSReserved map[v1.ResourceName]int64 ExperimentalCPUManagerPolicy string ExperimentalCPUManagerReconcilePeriod time.Duration ExperimentalPodPidsLimit int64 diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux.go index 236ac71dc..974986dea 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux.go @@ -52,7 +52,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/kubelet/status" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" utilfile "k8s.io/kubernetes/pkg/util/file" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/oom" @@ -123,7 +123,7 @@ type containerManagerImpl struct { capacity v1.ResourceList // Absolute cgroupfs path to a cgroup that Kubelet needs to place all pods under. // This path include a top level container for enforcing Node Allocatable. - cgroupRoot string + cgroupRoot CgroupName // Event recorder interface. recorder record.EventRecorder // Interface for QoS cgroup management @@ -223,7 +223,8 @@ func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.I } capacity = cadvisor.CapacityFromMachineInfo(machineInfo) - cgroupRoot := nodeConfig.CgroupRoot + // Turn CgroupRoot from a string (in cgroupfs path format) to internal CgroupName + cgroupRoot := ParseCgroupfsToCgroupName(nodeConfig.CgroupRoot) cgroupManager := NewCgroupManager(subsystems, nodeConfig.CgroupDriver) // Check if Cgroup-root actually exists on the node if nodeConfig.CgroupsPerQOS { @@ -236,13 +237,13 @@ func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.I // of note, we always use the cgroupfs driver when performing this check since // the input is provided in that format. // this is important because we do not want any name conversion to occur. - if !cgroupManager.Exists(CgroupName(cgroupRoot)) { + if !cgroupManager.Exists(cgroupRoot) { return nil, fmt.Errorf("invalid configuration: cgroup-root %q doesn't exist: %v", cgroupRoot, err) } glog.Infof("container manager verified user specified cgroup-root exists: %v", cgroupRoot) // Include the top level cgroup for enforcing node allocatable into cgroup-root. // This way, all sub modules can avoid having to understand the concept of node allocatable. - cgroupRoot = path.Join(cgroupRoot, defaultNodeAllocatableCgroupName) + cgroupRoot = NewCgroupName(cgroupRoot, defaultNodeAllocatableCgroupName) } glog.Infof("Creating Container Manager object based on Node Config: %+v", nodeConfig) @@ -305,7 +306,7 @@ func (cm *containerManagerImpl) NewPodContainerManager() PodContainerManager { } } return &podContainerManagerNoop{ - cgroupRoot: CgroupName(cm.cgroupRoot), + cgroupRoot: cm.cgroupRoot, } } @@ -503,7 +504,7 @@ func (cm *containerManagerImpl) GetNodeConfig() NodeConfig { // GetPodCgroupRoot returns the literal cgroupfs value for the cgroup containing all pods. func (cm *containerManagerImpl) GetPodCgroupRoot() string { - return cm.cgroupManager.Name(CgroupName(cm.cgroupRoot)) + return cm.cgroupManager.Name(cm.cgroupRoot) } func (cm *containerManagerImpl) GetMountedSubsystems() *CgroupSubsystems { @@ -859,21 +860,6 @@ func isKernelPid(pid int) bool { return err != nil } -// Helper for getting the docker API version. -func getDockerAPIVersion(cadvisor cadvisor.Interface) *utilversion.Version { - versions, err := cadvisor.VersionInfo() - if err != nil { - glog.Errorf("Error requesting cAdvisor VersionInfo: %v", err) - return utilversion.MustParseSemantic("0.0") - } - dockerAPIVersion, err := utilversion.ParseGeneric(versions.DockerAPIVersion) - if err != nil { - glog.Errorf("Error parsing docker version %q: %v", versions.DockerVersion, err) - return utilversion.MustParseSemantic("0.0") - } - return dockerAPIVersion -} - func (cm *containerManagerImpl) GetCapacity() v1.ResourceList { return cm.capacity } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux_test.go index 216280fba..127140e75 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux_test.go @@ -92,8 +92,8 @@ func (mi *fakeMountInterface) MakeFile(pathname string) error { return nil } -func (mi *fakeMountInterface) ExistsPath(pathname string) bool { - return true +func (mi *fakeMountInterface) ExistsPath(pathname string) (bool, error) { + return true, errors.New("not implemented") } func (mi *fakeMountInterface) PrepareSafeSubpath(subPath mount.Subpath) (newHostPath string, cleanupAction func(), err error) { @@ -108,10 +108,22 @@ func (mi *fakeMountInterface) SafeMakeDir(_, _ string, _ os.FileMode) error { return nil } +func (mi *fakeMountInterface) GetMountRefs(pathname string) ([]string, error) { + return nil, errors.New("not implemented") +} + +func (mi *fakeMountInterface) GetFSGroup(pathname string) (int64, error) { + return -1, errors.New("not implemented") +} + func (mi *fakeMountInterface) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } +func (mi *fakeMountInterface) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} + func fakeContainerMgrMountInt() mount.Interface { return &fakeMountInterface{ []mount.MountPoint{ diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_stub.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_stub.go index 261552da7..8a464adc0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_stub.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_stub.go @@ -27,7 +27,7 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/status" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) type containerManagerStub struct{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state/state_file_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state/state_file_test.go index b507884c4..edccf8799 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state/state_file_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state/state_file_test.go @@ -18,7 +18,6 @@ package state import ( "bytes" - "flag" "fmt" "io" "io/ioutil" @@ -69,9 +68,6 @@ func stderrCapture(t *testing.T, f func() State) (bytes.Buffer, State) { } func TestFileStateTryRestore(t *testing.T) { - flag.Set("alsologtostderr", "true") - flag.Parse() - testCases := []struct { description string stateFileContent string @@ -292,9 +288,6 @@ func TestFileStateTryRestorePanic(t *testing.T) { } func TestUpdateStateFile(t *testing.T) { - flag.Set("alsologtostderr", "true") - flag.Parse() - testCases := []struct { description string expErr string diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/BUILD index 051eaeef3..d2e467cca 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/BUILD @@ -15,15 +15,15 @@ go_library( deps = [ "//pkg/apis/core/v1/helper:go_default_library", "//pkg/kubelet/apis/deviceplugin/v1beta1:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", + "//pkg/kubelet/checkpointmanager/errors:go_default_library", + "//pkg/kubelet/cm/devicemanager/checkpoint:go_default_library", "//pkg/kubelet/config:go_default_library", "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/metrics:go_default_library", - "//pkg/kubelet/util/store:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", - "//pkg/util/filesystem:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -40,10 +40,9 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/kubelet/apis/deviceplugin/v1beta1:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", - "//pkg/kubelet/util/store:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", - "//pkg/util/filesystem:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -63,7 +62,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/kubelet/cm/devicemanager/checkpoint:all-srcs", + ], tags = ["automanaged"], visibility = ["//visibility:public"], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint/BUILD new file mode 100644 index 000000000..91506a71f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint/BUILD @@ -0,0 +1,26 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["checkpoint.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint", + visibility = ["//visibility:public"], + deps = [ + "//pkg/kubelet/checkpointmanager:go_default_library", + "//pkg/kubelet/checkpointmanager/checksum:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint/checkpoint.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint/checkpoint.go new file mode 100644 index 000000000..9f8cac139 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint/checkpoint.go @@ -0,0 +1,81 @@ +/* +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 checkpoint + +import ( + "encoding/json" + + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" +) + +type DeviceManagerCheckpoint interface { + checkpointmanager.Checkpoint + GetData() ([]PodDevicesEntry, map[string][]string) +} + +type PodDevicesEntry struct { + PodUID string + ContainerName string + ResourceName string + DeviceIDs []string + AllocResp []byte +} + +// checkpointData struct is used to store pod to device allocation information +// in a checkpoint file. +// TODO: add version control when we need to change checkpoint format. +type checkpointData struct { + PodDeviceEntries []PodDevicesEntry + RegisteredDevices map[string][]string +} + +type Data struct { + Data checkpointData + Checksum checksum.Checksum +} + +// NewDeviceManagerCheckpoint returns an instance of Checkpoint +func New(devEntries []PodDevicesEntry, + devices map[string][]string) DeviceManagerCheckpoint { + return &Data{ + Data: checkpointData{ + PodDeviceEntries: devEntries, + RegisteredDevices: devices, + }, + } +} + +// MarshalCheckpoint returns marshalled data +func (cp *Data) MarshalCheckpoint() ([]byte, error) { + cp.Checksum = checksum.New(cp.Data) + return json.Marshal(*cp) +} + +// UnmarshalCheckpoint returns unmarshalled data +func (cp *Data) UnmarshalCheckpoint(blob []byte) error { + return json.Unmarshal(blob, cp) +} + +// VerifyChecksum verifies that passed checksum is same as calculated checksum +func (cp *Data) VerifyChecksum() error { + return cp.Checksum.Verify(cp.Data) +} + +func (cp *Data) GetData() ([]PodDevicesEntry, map[string][]string) { + return cp.Data.PodDeviceEntries, cp.Data.RegisteredDevices +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/device_plugin_stub.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/device_plugin_stub.go index a7c3fd38b..73943039d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/device_plugin_stub.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/device_plugin_stub.go @@ -17,13 +17,14 @@ limitations under the License. package devicemanager import ( + "context" "log" "net" "os" "path" + "sync" "time" - "golang.org/x/net/context" "google.golang.org/grpc" pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" @@ -35,6 +36,7 @@ type Stub struct { socket string stop chan interface{} + wg sync.WaitGroup update chan []*pluginapi.Device server *grpc.Server @@ -70,7 +72,8 @@ func (m *Stub) SetAllocFunc(f stubAllocFunc) { m.allocFunc = f } -// Start starts the gRPC server of the device plugin +// Start starts the gRPC server of the device plugin. Can only +// be called once. func (m *Stub) Start() error { err := m.cleanup() if err != nil { @@ -82,10 +85,14 @@ func (m *Stub) Start() error { return err } + m.wg.Add(1) m.server = grpc.NewServer([]grpc.ServerOption{}...) pluginapi.RegisterDevicePluginServer(m.server, m) - go m.server.Serve(sock) + go func() { + defer m.wg.Done() + m.server.Serve(sock) + }() _, conn, err := dial(m.socket) if err != nil { return err @@ -96,18 +103,27 @@ func (m *Stub) Start() error { return nil } -// Stop stops the gRPC server +// Stop stops the gRPC server. Can be called without a prior Start +// and more than once. Not safe to be called concurrently by different +// goroutines! func (m *Stub) Stop() error { + if m.server == nil { + return nil + } m.server.Stop() - close(m.stop) + m.wg.Wait() + m.server = nil + close(m.stop) // This prevents re-starting the server. return m.cleanup() } // Register registers the device plugin for the given resourceName with Kubelet. func (m *Stub) Register(kubeletEndpoint, resourceName string, preStartContainerFlag bool) error { - conn, err := grpc.Dial(kubeletEndpoint, grpc.WithInsecure(), grpc.WithBlock(), - grpc.WithTimeout(10*time.Second), + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + conn, err := grpc.DialContext(ctx, kubeletEndpoint, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { return net.DialTimeout("unix", addr, timeout) })) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/endpoint.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/endpoint.go index 26b3952d0..069ffc220 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/endpoint.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/endpoint.go @@ -17,13 +17,13 @@ limitations under the License. package devicemanager import ( + "context" "fmt" "net" "sync" "time" "github.com/golang/glog" - "golang.org/x/net/context" "google.golang.org/grpc" pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" @@ -244,8 +244,10 @@ func (e *endpointImpl) stop() { // dial establishes the gRPC communication with the registered device plugin. https://godoc.org/google.golang.org/grpc#Dial func dial(unixSocketPath string) (pluginapi.DevicePluginClient, *grpc.ClientConn, error) { - c, err := grpc.Dial(unixSocketPath, grpc.WithInsecure(), grpc.WithBlock(), - grpc.WithTimeout(10*time.Second), + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + c, err := grpc.DialContext(ctx, unixSocketPath, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { return net.DialTimeout("unix", addr, timeout) }), diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager.go index c402e1fe3..38805ce75 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager.go @@ -17,7 +17,7 @@ limitations under the License. package devicemanager import ( - "encoding/json" + "context" "fmt" "net" "os" @@ -26,7 +26,6 @@ import ( "time" "github.com/golang/glog" - "golang.org/x/net/context" "google.golang.org/grpc" "k8s.io/api/core/v1" @@ -34,12 +33,13 @@ import ( "k8s.io/apimachinery/pkg/util/sets" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" + "k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint" "k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/metrics" - utilstore "k8s.io/kubernetes/pkg/kubelet/util/store" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" - utilfs "k8s.io/kubernetes/pkg/util/filesystem" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // ActivePodsFunc is a function that returns a list of pods to reconcile. @@ -59,6 +59,7 @@ type ManagerImpl struct { mutex sync.Mutex server *grpc.Server + wg sync.WaitGroup // activePods is a method for listing active pods on the node // so the amount of pluginResources requested by existing pods @@ -83,9 +84,9 @@ type ManagerImpl struct { allocatedDevices map[string]sets.String // podDevices contains pod to allocated device mapping. - podDevices podDevices - store utilstore.Store - pluginOpts map[string]*pluginapi.DevicePluginOptions + podDevices podDevices + pluginOpts map[string]*pluginapi.DevicePluginOptions + checkpointManager checkpointmanager.CheckpointManager } type sourcesReadyStub struct{} @@ -122,11 +123,11 @@ func newManagerImpl(socketPath string) (*ManagerImpl, error) { // Before that, initializes them to perform no-op operations. manager.activePods = func() []*v1.Pod { return []*v1.Pod{} } manager.sourcesReady = &sourcesReadyStub{} - var err error - manager.store, err = utilstore.NewFileStore(dir, utilfs.DefaultFs{}) + checkpointManager, err := checkpointmanager.NewCheckpointManager(dir) if err != nil { - return nil, fmt.Errorf("failed to initialize device plugin checkpointing store: %+v", err) + return nil, fmt.Errorf("failed to initialize checkpoint manager: %+v", err) } + manager.checkpointManager = checkpointManager return manager, nil } @@ -188,11 +189,6 @@ func (m *ManagerImpl) removeContents(dir string) error { return nil } -const ( - // kubeletDeviceManagerCheckpoint is the file name of device plugin checkpoint - kubeletDeviceManagerCheckpoint = "kubelet_internal_checkpoint" -) - // checkpointFile returns device plugin checkpoint file path. func (m *ManagerImpl) checkpointFile() string { return filepath.Join(m.socketdir, kubeletDeviceManagerCheckpoint) @@ -229,10 +225,14 @@ func (m *ManagerImpl) Start(activePods ActivePodsFunc, sourcesReady config.Sourc return err } + m.wg.Add(1) m.server = grpc.NewServer([]grpc.ServerOption{}...) pluginapi.RegisterRegistrationServer(m.server, m) - go m.server.Serve(s) + go func() { + defer m.wg.Done() + m.server.Serve(s) + }() glog.V(2).Infof("Serving device plugin registration server on %q", socketPath) @@ -318,6 +318,8 @@ func (m *ManagerImpl) Register(ctx context.Context, r *pluginapi.RegisterRequest } // Stop is the function that can stop the gRPC server. +// Can be called concurrently, more than once, and is safe to call +// without a prior Start. func (m *ManagerImpl) Stop() error { m.mutex.Lock() defer m.mutex.Unlock() @@ -325,7 +327,12 @@ func (m *ManagerImpl) Stop() error { e.stop() } + if m.server == nil { + return nil + } m.server.Stop() + m.wg.Wait() + m.server = nil return nil } @@ -460,33 +467,19 @@ func (m *ManagerImpl) GetCapacity() (v1.ResourceList, v1.ResourceList, []string) return capacity, allocatable, deletedResources.UnsortedList() } -// checkpointData struct is used to store pod to device allocation information -// and registered device information in a checkpoint file. -// TODO: add version control when we need to change checkpoint format. -type checkpointData struct { - PodDeviceEntries []podDevicesCheckpointEntry - RegisteredDevices map[string][]string -} - // Checkpoints device to container allocation information to disk. func (m *ManagerImpl) writeCheckpoint() error { m.mutex.Lock() - data := checkpointData{ - PodDeviceEntries: m.podDevices.toCheckpointData(), - RegisteredDevices: make(map[string][]string), - } + registeredDevs := make(map[string][]string) for resource, devices := range m.healthyDevices { - data.RegisteredDevices[resource] = devices.UnsortedList() + registeredDevs[resource] = devices.UnsortedList() } + data := checkpoint.New(m.podDevices.toCheckpointData(), + registeredDevs) m.mutex.Unlock() - - dataJSON, err := json.Marshal(data) - if err != nil { - return err - } - err = m.store.Write(kubeletDeviceManagerCheckpoint, dataJSON) + err := m.checkpointManager.CreateCheckpoint(kubeletDeviceManagerCheckpoint, data) if err != nil { - return fmt.Errorf("failed to write deviceplugin checkpoint file %q: %v", kubeletDeviceManagerCheckpoint, err) + return fmt.Errorf("failed to write checkpoint file %q: %v", kubeletDeviceManagerCheckpoint, err) } return nil } @@ -494,24 +487,23 @@ func (m *ManagerImpl) writeCheckpoint() error { // Reads device to container allocation information from disk, and populates // m.allocatedDevices accordingly. func (m *ManagerImpl) readCheckpoint() error { - content, err := m.store.Read(kubeletDeviceManagerCheckpoint) + registeredDevs := make(map[string][]string) + devEntries := make([]checkpoint.PodDevicesEntry, 0) + cp := checkpoint.New(devEntries, registeredDevs) + err := m.checkpointManager.GetCheckpoint(kubeletDeviceManagerCheckpoint, cp) if err != nil { - if err == utilstore.ErrKeyNotFound { + if err == errors.ErrCheckpointNotFound { + glog.Warningf("Failed to retrieve checkpoint for %q: %v", kubeletDeviceManagerCheckpoint, err) return nil } - return fmt.Errorf("failed to read checkpoint file %q: %v", kubeletDeviceManagerCheckpoint, err) - } - glog.V(4).Infof("Read checkpoint file %s\n", kubeletDeviceManagerCheckpoint) - var data checkpointData - if err := json.Unmarshal(content, &data); err != nil { - return fmt.Errorf("failed to unmarshal deviceplugin checkpoint data: %v", err) + return err } - m.mutex.Lock() defer m.mutex.Unlock() - m.podDevices.fromCheckpointData(data.PodDeviceEntries) + podDevices, registeredDevs := cp.GetData() + m.podDevices.fromCheckpointData(podDevices) m.allocatedDevices = m.podDevices.devices() - for resource := range data.RegisteredDevices { + for resource := range registeredDevs { // During start up, creates empty healthyDevices list so that the resource capacity // will stay zero till the corresponding device plugin re-registers. m.healthyDevices[resource] = sets.NewString() diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager_stub.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager_stub.go index a0f14257f..b42c1b3ea 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager_stub.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager_stub.go @@ -21,7 +21,7 @@ import ( pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" "k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/lifecycle" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // ManagerStub provides a simple stub implementation for the Device Manager. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager_test.go index b0ef2857f..d27f6b5f5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/manager_test.go @@ -17,7 +17,6 @@ limitations under the License. package devicemanager import ( - "flag" "fmt" "io/ioutil" "os" @@ -34,10 +33,9 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" "k8s.io/kubernetes/pkg/kubelet/lifecycle" - utilstore "k8s.io/kubernetes/pkg/kubelet/util/store" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" - utilfs "k8s.io/kubernetes/pkg/util/filesystem" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) const ( @@ -69,6 +67,29 @@ func TestNewManagerImplStart(t *testing.T) { defer os.RemoveAll(socketDir) m, p := setup(t, []*pluginapi.Device{}, func(n string, a, u, r []pluginapi.Device) {}, socketName, pluginSocketName) cleanup(t, m, p) + // Stop should tolerate being called more than once. + cleanup(t, m, p) +} + +func TestNewManagerImplStop(t *testing.T) { + socketDir, socketName, pluginSocketName, err := tmpSocketDir() + require.NoError(t, err) + defer os.RemoveAll(socketDir) + + m, err := newManagerImpl(socketName) + require.NoError(t, err) + // No prior Start, but that should be okay. + err = m.Stop() + require.NoError(t, err) + + devs := []*pluginapi.Device{ + {ID: "Dev1", Health: pluginapi.Healthy}, + {ID: "Dev2", Health: pluginapi.Healthy}, + } + p := NewDevicePluginStub(devs, pluginSocketName) + // Same here. + err = p.Stop() + require.NoError(t, err) } // Tests that the device plugin manager correctly handles registration and re-registration by @@ -347,20 +368,19 @@ func constructAllocResp(devices, mounts, envs map[string]string) *pluginapi.Cont func TestCheckpoint(t *testing.T) { resourceName1 := "domain1.com/resource1" resourceName2 := "domain2.com/resource2" - as := assert.New(t) tmpDir, err := ioutil.TempDir("", "checkpoint") as.Nil(err) - defer os.RemoveAll(tmpDir) + ckm, err := checkpointmanager.NewCheckpointManager(tmpDir) + as.Nil(err) testManager := &ManagerImpl{ - socketdir: tmpDir, - endpoints: make(map[string]endpoint), - healthyDevices: make(map[string]sets.String), - unhealthyDevices: make(map[string]sets.String), - allocatedDevices: make(map[string]sets.String), - podDevices: make(podDevices), + endpoints: make(map[string]endpoint), + healthyDevices: make(map[string]sets.String), + unhealthyDevices: make(map[string]sets.String), + allocatedDevices: make(map[string]sets.String), + podDevices: make(podDevices), + checkpointManager: ckm, } - testManager.store, _ = utilstore.NewFileStore("/tmp/", utilfs.DefaultFs{}) testManager.podDevices.insert("pod1", "con1", resourceName1, constructDevices([]string{"dev1", "dev2"}), @@ -479,21 +499,25 @@ func makePod(limits v1.ResourceList) *v1.Pod { } } -func getTestManager(tmpDir string, activePods ActivePodsFunc, testRes []TestResource, opts map[string]*pluginapi.DevicePluginOptions) *ManagerImpl { +func getTestManager(tmpDir string, activePods ActivePodsFunc, testRes []TestResource, opts map[string]*pluginapi.DevicePluginOptions) (*ManagerImpl, error) { monitorCallback := func(resourceName string, added, updated, deleted []pluginapi.Device) {} + ckm, err := checkpointmanager.NewCheckpointManager(tmpDir) + if err != nil { + return nil, err + } testManager := &ManagerImpl{ - socketdir: tmpDir, - callback: monitorCallback, - healthyDevices: make(map[string]sets.String), - unhealthyDevices: make(map[string]sets.String), - allocatedDevices: make(map[string]sets.String), - endpoints: make(map[string]endpoint), - pluginOpts: opts, - podDevices: make(podDevices), - activePods: activePods, - sourcesReady: &sourcesReadyStub{}, - } - testManager.store, _ = utilstore.NewFileStore("/tmp/", utilfs.DefaultFs{}) + socketdir: tmpDir, + callback: monitorCallback, + healthyDevices: make(map[string]sets.String), + unhealthyDevices: make(map[string]sets.String), + allocatedDevices: make(map[string]sets.String), + endpoints: make(map[string]endpoint), + pluginOpts: opts, + podDevices: make(podDevices), + activePods: activePods, + sourcesReady: &sourcesReadyStub{}, + checkpointManager: ckm, + } for _, res := range testRes { testManager.healthyDevices[res.resourceName] = sets.NewString() for _, dev := range res.devs { @@ -525,7 +549,7 @@ func getTestManager(tmpDir string, activePods ActivePodsFunc, testRes []TestReso } } } - return testManager + return testManager, nil } func getTestNodeInfo(allocatable v1.ResourceList) *schedulercache.NodeInfo { @@ -546,7 +570,6 @@ type TestResource struct { } func TestPodContainerDeviceAllocation(t *testing.T) { - flag.Set("alsologtostderr", fmt.Sprintf("%t", true)) res1 := TestResource{ resourceName: "domain1.com/resource1", resourceQuantity: *resource.NewQuantity(int64(2), resource.DecimalSI), @@ -569,7 +592,8 @@ func TestPodContainerDeviceAllocation(t *testing.T) { defer os.RemoveAll(tmpDir) nodeInfo := getTestNodeInfo(v1.ResourceList{}) pluginOpts := make(map[string]*pluginapi.DevicePluginOptions) - testManager := getTestManager(tmpDir, podsStub.getActivePods, testResources, pluginOpts) + testManager, err := getTestManager(tmpDir, podsStub.getActivePods, testResources, pluginOpts) + as.Nil(err) testPods := []*v1.Pod{ makePod(v1.ResourceList{ @@ -664,7 +688,8 @@ func TestInitContainerDeviceAllocation(t *testing.T) { as.Nil(err) defer os.RemoveAll(tmpDir) pluginOpts := make(map[string]*pluginapi.DevicePluginOptions) - testManager := getTestManager(tmpDir, podsStub.getActivePods, testResources, pluginOpts) + testManager, err := getTestManager(tmpDir, podsStub.getActivePods, testResources, pluginOpts) + as.Nil(err) podWithPluginResourcesInInitContainers := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -742,14 +767,18 @@ func TestSanitizeNodeAllocatable(t *testing.T) { as := assert.New(t) monitorCallback := func(resourceName string, added, updated, deleted []pluginapi.Device) {} + tmpDir, err := ioutil.TempDir("", "checkpoint") + as.Nil(err) + ckm, err := checkpointmanager.NewCheckpointManager(tmpDir) + as.Nil(err) testManager := &ManagerImpl{ - callback: monitorCallback, - healthyDevices: make(map[string]sets.String), - allocatedDevices: make(map[string]sets.String), - podDevices: make(podDevices), + callback: monitorCallback, + allocatedDevices: make(map[string]sets.String), + healthyDevices: make(map[string]sets.String), + podDevices: make(podDevices), + checkpointManager: ckm, } - testManager.store, _ = utilstore.NewFileStore("/tmp/", utilfs.DefaultFs{}) // require one of resource1 and one of resource2 testManager.allocatedDevices[resourceName1] = sets.NewString() testManager.allocatedDevices[resourceName1].Insert(devID1) @@ -796,7 +825,8 @@ func TestDevicePreStartContainer(t *testing.T) { pluginOpts := make(map[string]*pluginapi.DevicePluginOptions) pluginOpts[res1.resourceName] = &pluginapi.DevicePluginOptions{PreStartRequired: true} - testManager := getTestManager(tmpDir, podsStub.getActivePods, []TestResource{res1}, pluginOpts) + testManager, err := getTestManager(tmpDir, podsStub.getActivePods, []TestResource{res1}, pluginOpts) + as.Nil(err) ch := make(chan []string, 1) testManager.endpoints[res1.resourceName] = &MockEndpoint{ diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/pod_devices.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/pod_devices.go index eb20dc0a6..7df0e201c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/pod_devices.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/pod_devices.go @@ -21,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" + "k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" ) @@ -126,18 +127,9 @@ func (pdev podDevices) devices() map[string]sets.String { return ret } -// podDevicesCheckpointEntry is used to record to device allocation information. -type podDevicesCheckpointEntry struct { - PodUID string - ContainerName string - ResourceName string - DeviceIDs []string - AllocResp []byte -} - // Turns podDevices to checkpointData. -func (pdev podDevices) toCheckpointData() []podDevicesCheckpointEntry { - var data []podDevicesCheckpointEntry +func (pdev podDevices) toCheckpointData() []checkpoint.PodDevicesEntry { + var data []checkpoint.PodDevicesEntry for podUID, containerDevices := range pdev { for conName, resources := range containerDevices { for resource, devices := range resources { @@ -152,7 +144,12 @@ func (pdev podDevices) toCheckpointData() []podDevicesCheckpointEntry { glog.Errorf("Can't marshal allocResp for %v %v %v: %v", podUID, conName, resource, err) continue } - data = append(data, podDevicesCheckpointEntry{podUID, conName, resource, devIds, allocResp}) + data = append(data, checkpoint.PodDevicesEntry{ + PodUID: podUID, + ContainerName: conName, + ResourceName: resource, + DeviceIDs: devIds, + AllocResp: allocResp}) } } } @@ -160,7 +157,7 @@ func (pdev podDevices) toCheckpointData() []podDevicesCheckpointEntry { } // Populates podDevices from the passed in checkpointData. -func (pdev podDevices) fromCheckpointData(data []podDevicesCheckpointEntry) { +func (pdev podDevices) fromCheckpointData(data []checkpoint.PodDevicesEntry) { for _, entry := range data { glog.V(2).Infof("Get checkpoint entry: %v %v %v %v %v\n", entry.PodUID, entry.ContainerName, entry.ResourceName, entry.DeviceIDs, entry.AllocResp) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/types.go index e1d07ef5f..4e34749b6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/types.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/types.go @@ -24,7 +24,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/config" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/lifecycle" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // Manager manages all the Device Plugins running on a node. @@ -106,3 +106,6 @@ const ( // cache during this grace period to cover the time gap for the capacity change to // take effect. const endpointStopGracePeriod = time.Duration(5) * time.Minute + +// kubeletDeviceManagerCheckpoint is the file name of device plugin checkpoint +const kubeletDeviceManagerCheckpoint = "kubelet_internal_checkpoint" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_linux_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_linux_test.go index 30894e9fd..24d1b5848 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_linux_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_linux_test.go @@ -24,6 +24,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "strconv" ) // getResourceList returns a ResourceList with the @@ -230,3 +231,82 @@ func TestMilliCPUToQuota(t *testing.T) { } } } + +func TestHugePageLimits(t *testing.T) { + Mi := int64(1024 * 1024) + type inputStruct struct { + key string + input string + } + + testCases := []struct { + name string + inputs []inputStruct + expected map[int64]int64 + }{ + { + name: "no valid hugepages", + inputs: []inputStruct{ + { + key: "2Mi", + input: "128", + }, + }, + expected: map[int64]int64{}, + }, + { + name: "2Mi only", + inputs: []inputStruct{ + { + key: v1.ResourceHugePagesPrefix + "2Mi", + input: "128", + }, + }, + expected: map[int64]int64{2 * Mi: 128}, + }, + { + name: "2Mi and 4Mi", + inputs: []inputStruct{ + { + key: v1.ResourceHugePagesPrefix + "2Mi", + input: "128", + }, + { + key: v1.ResourceHugePagesPrefix + strconv.FormatInt(2*Mi, 10), + input: "256", + }, + { + key: v1.ResourceHugePagesPrefix + "4Mi", + input: "512", + }, + { + key: "4Mi", + input: "1024", + }, + }, + expected: map[int64]int64{2 * Mi: 384, 4 * Mi: 512}, + }, + } + + for _, testcase := range testCases { + t.Run(testcase.name, func(t *testing.T) { + resourceList := v1.ResourceList{} + + for _, input := range testcase.inputs { + value, err := resource.ParseQuantity(input.input) + if err != nil { + t.Fatalf("error in parsing hugepages, value: %s", input.input) + } else { + resourceList[v1.ResourceName(input.key)] = value + } + } + + resultValue := HugePageLimits(resourceList) + + if !reflect.DeepEqual(testcase.expected, resultValue) { + t.Errorf("unexpected result, expected: %v, actual: %v", testcase.expected, resultValue) + } + }) + + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/node_container_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/node_container_manager.go index 04e5acdd1..6c1e022c2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/node_container_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/node_container_manager.go @@ -39,9 +39,10 @@ const ( defaultNodeAllocatableCgroupName = "kubepods" ) +//createNodeAllocatableCgroups creates Node Allocatable Cgroup when CgroupsPerQOS flag is specified as true func (cm *containerManagerImpl) createNodeAllocatableCgroups() error { cgroupConfig := &CgroupConfig{ - Name: CgroupName(cm.cgroupRoot), + Name: cm.cgroupRoot, // The default limits for cpu shares can be very low which can lead to CPU starvation for pods. ResourceParameters: getCgroupConfig(cm.capacity), } @@ -70,7 +71,7 @@ func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error { glog.V(4).Infof("Attempting to enforce Node Allocatable with config: %+v", nc) cgroupConfig := &CgroupConfig{ - Name: CgroupName(cm.cgroupRoot), + Name: cm.cgroupRoot, ResourceParameters: getCgroupConfig(nodeAllocatable), } @@ -83,11 +84,12 @@ func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error { } // If Node Allocatable is enforced on a node that has not been drained or is updated on an existing node to a lower value, - // existing memory usage across pods might be higher that current Node Allocatable Memory Limits. + // existing memory usage across pods might be higher than current Node Allocatable Memory Limits. // Pod Evictions are expected to bring down memory usage to below Node Allocatable limits. // Until evictions happen retry cgroup updates. // Update limits on non root cgroup-root to be safe since the default limits for CPU can be too low. - if cm.cgroupRoot != "/" { + // Check if cgroupRoot is set to a non-empty value (empty would be the root container) + if len(cm.cgroupRoot) > 0 { go func() { for { err := cm.cgroupManager.Update(cgroupConfig) @@ -104,7 +106,7 @@ func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error { // Now apply kube reserved and system reserved limits if required. if nc.EnforceNodeAllocatable.Has(kubetypes.SystemReservedEnforcementKey) { glog.V(2).Infof("Enforcing System reserved on cgroup %q with limits: %+v", nc.SystemReservedCgroupName, nc.SystemReserved) - if err := enforceExistingCgroup(cm.cgroupManager, nc.SystemReservedCgroupName, nc.SystemReserved); err != nil { + if err := enforceExistingCgroup(cm.cgroupManager, ParseCgroupfsToCgroupName(nc.SystemReservedCgroupName), nc.SystemReserved); err != nil { message := fmt.Sprintf("Failed to enforce System Reserved Cgroup Limits on %q: %v", nc.SystemReservedCgroupName, err) cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message) return fmt.Errorf(message) @@ -113,7 +115,7 @@ func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error { } if nc.EnforceNodeAllocatable.Has(kubetypes.KubeReservedEnforcementKey) { glog.V(2).Infof("Enforcing kube reserved on cgroup %q with limits: %+v", nc.KubeReservedCgroupName, nc.KubeReserved) - if err := enforceExistingCgroup(cm.cgroupManager, nc.KubeReservedCgroupName, nc.KubeReserved); err != nil { + if err := enforceExistingCgroup(cm.cgroupManager, ParseCgroupfsToCgroupName(nc.KubeReservedCgroupName), nc.KubeReserved); err != nil { message := fmt.Sprintf("Failed to enforce Kube Reserved Cgroup Limits on %q: %v", nc.KubeReservedCgroupName, err) cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message) return fmt.Errorf(message) @@ -124,9 +126,9 @@ func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error { } // enforceExistingCgroup updates the limits `rl` on existing cgroup `cName` using `cgroupManager` interface. -func enforceExistingCgroup(cgroupManager CgroupManager, cName string, rl v1.ResourceList) error { +func enforceExistingCgroup(cgroupManager CgroupManager, cName CgroupName, rl v1.ResourceList) error { cgroupConfig := &CgroupConfig{ - Name: CgroupName(cName), + Name: cName, ResourceParameters: getCgroupConfig(rl), } glog.V(4).Infof("Enforcing limits on cgroup %q with %d cpu shares and %d bytes of memory", cName, cgroupConfig.ResourceParameters.CpuShares, cgroupConfig.ResourceParameters.Memory) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_linux.go index a9a873691..abe5b7397 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_linux.go @@ -104,7 +104,7 @@ func (m *podContainerManagerImpl) EnsureExists(pod *v1.Pod) error { func (m *podContainerManagerImpl) GetPodContainerName(pod *v1.Pod) (CgroupName, string) { podQOS := v1qos.GetPodQOS(pod) // Get the parent QOS container name - var parentContainer string + var parentContainer CgroupName switch podQOS { case v1.PodQOSGuaranteed: parentContainer = m.qosContainersInfo.Guaranteed @@ -116,13 +116,33 @@ func (m *podContainerManagerImpl) GetPodContainerName(pod *v1.Pod) (CgroupName, podContainer := GetPodCgroupNameSuffix(pod.UID) // Get the absolute path of the cgroup - cgroupName := (CgroupName)(path.Join(parentContainer, podContainer)) + cgroupName := NewCgroupName(parentContainer, podContainer) // Get the literal cgroupfs name cgroupfsName := m.cgroupManager.Name(cgroupName) return cgroupName, cgroupfsName } +// Kill one process ID +func (m *podContainerManagerImpl) killOnePid(pid int) error { + // os.FindProcess never returns an error on POSIX + // https://go-review.googlesource.com/c/go/+/19093 + p, _ := os.FindProcess(pid) + if err := p.Kill(); err != nil { + // If the process already exited, that's fine. + if strings.Contains(err.Error(), "process already finished") { + // Hate parsing strings, but + // vendor/github.com/opencontainers/runc/libcontainer/ + // also does this. + glog.V(3).Infof("process with pid %v no longer exists", pid) + return nil + } else { + return err + } + } + return nil +} + // Scan through the whole cgroup directory and kill all processes either // attached to the pod cgroup or to a container cgroup under the pod cgroup func (m *podContainerManagerImpl) tryKillingCgroupProcesses(podCgroup CgroupName) error { @@ -141,13 +161,8 @@ func (m *podContainerManagerImpl) tryKillingCgroupProcesses(podCgroup CgroupName } errlist = []error{} for _, pid := range pidsToKill { - p, err := os.FindProcess(pid) - if err != nil { - // Process not running anymore, do nothing - continue - } glog.V(3).Infof("Attempt to kill process with pid: %v", pid) - if err := p.Kill(); err != nil { + if err := m.killOnePid(pid); err != nil { glog.V(3).Infof("failed to kill process with pid: %v", pid) errlist = append(errlist, err) } @@ -184,12 +199,37 @@ func (m *podContainerManagerImpl) ReduceCPULimits(podCgroup CgroupName) error { return m.cgroupManager.ReduceCPULimits(podCgroup) } +// IsPodCgroup returns true if the literal cgroupfs name corresponds to a pod +func (m *podContainerManagerImpl) IsPodCgroup(cgroupfs string) (bool, types.UID) { + // convert the literal cgroupfs form to the driver specific value + cgroupName := m.cgroupManager.CgroupName(cgroupfs) + qosContainersList := [3]CgroupName{m.qosContainersInfo.BestEffort, m.qosContainersInfo.Burstable, m.qosContainersInfo.Guaranteed} + basePath := "" + for _, qosContainerName := range qosContainersList { + // a pod cgroup is a direct child of a qos node, so check if its a match + if len(cgroupName) == len(qosContainerName)+1 { + basePath = cgroupName[len(qosContainerName)] + } + } + if basePath == "" { + return false, types.UID("") + } + if !strings.HasPrefix(basePath, podCgroupNamePrefix) { + return false, types.UID("") + } + parts := strings.Split(basePath, podCgroupNamePrefix) + if len(parts) != 2 { + return false, types.UID("") + } + return true, types.UID(parts[1]) +} + // GetAllPodsFromCgroups scans through all the subsystems of pod cgroups // Get list of pods whose cgroup still exist on the cgroup mounts func (m *podContainerManagerImpl) GetAllPodsFromCgroups() (map[types.UID]CgroupName, error) { // Map for storing all the found pods on the disk foundPods := make(map[types.UID]CgroupName) - qosContainersList := [3]string{m.qosContainersInfo.BestEffort, m.qosContainersInfo.Burstable, m.qosContainersInfo.Guaranteed} + qosContainersList := [3]CgroupName{m.qosContainersInfo.BestEffort, m.qosContainersInfo.Burstable, m.qosContainersInfo.Guaranteed} // Scan through all the subsystem mounts // and through each QoS cgroup directory for each subsystem mount // If a pod cgroup exists in even a single subsystem mount @@ -197,7 +237,7 @@ func (m *podContainerManagerImpl) GetAllPodsFromCgroups() (map[types.UID]CgroupN for _, val := range m.subsystems.MountPoints { for _, qosContainerName := range qosContainersList { // get the subsystems QoS cgroup absolute name - qcConversion := m.cgroupManager.Name(CgroupName(qosContainerName)) + qcConversion := m.cgroupManager.Name(qosContainerName) qc := path.Join(val, qcConversion) dirInfo, err := ioutil.ReadDir(qc) if err != nil { @@ -219,7 +259,7 @@ func (m *podContainerManagerImpl) GetAllPodsFromCgroups() (map[types.UID]CgroupN internalPath := m.cgroupManager.CgroupName(cgroupfsPath) // we only care about base segment of the converted path since that // is what we are reading currently to know if it is a pod or not. - basePath := path.Base(string(internalPath)) + basePath := internalPath[len(internalPath)-1] if !strings.Contains(basePath, podCgroupNamePrefix) { continue } @@ -259,7 +299,7 @@ func (m *podContainerManagerNoop) EnsureExists(_ *v1.Pod) error { } func (m *podContainerManagerNoop) GetPodContainerName(_ *v1.Pod) (CgroupName, string) { - return m.cgroupRoot, string(m.cgroupRoot) + return m.cgroupRoot, m.cgroupRoot.ToCgroupfs() } func (m *podContainerManagerNoop) GetPodContainerNameForDriver(_ *v1.Pod) string { @@ -278,3 +318,7 @@ func (m *podContainerManagerNoop) ReduceCPULimits(_ CgroupName) error { func (m *podContainerManagerNoop) GetAllPodsFromCgroups() (map[types.UID]CgroupName, error) { return nil, nil } + +func (m *podContainerManagerNoop) IsPodCgroup(cgroupfs string) (bool, types.UID) { + return false, types.UID("") +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_linux_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_linux_test.go new file mode 100644 index 000000000..62c9f203a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_linux_test.go @@ -0,0 +1,125 @@ +// +build linux + +/* +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 cm + +import ( + "strings" + "testing" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" +) + +func TestIsCgroupPod(t *testing.T) { + qosContainersInfo := QOSContainersInfo{ + Guaranteed: RootCgroupName, + Burstable: NewCgroupName(RootCgroupName, strings.ToLower(string(v1.PodQOSBurstable))), + BestEffort: NewCgroupName(RootCgroupName, strings.ToLower(string(v1.PodQOSBestEffort))), + } + podUID := types.UID("123") + testCases := []struct { + input CgroupName + expectedResult bool + expectedUID types.UID + }{ + { + input: RootCgroupName, + expectedResult: false, + expectedUID: types.UID(""), + }, + { + input: NewCgroupName(qosContainersInfo.Guaranteed), + expectedResult: false, + expectedUID: types.UID(""), + }, + { + input: NewCgroupName(qosContainersInfo.Guaranteed, GetPodCgroupNameSuffix(podUID)), + expectedResult: true, + expectedUID: podUID, + }, + { + input: NewCgroupName(qosContainersInfo.Guaranteed, GetPodCgroupNameSuffix(podUID), "container.scope"), + expectedResult: false, + expectedUID: types.UID(""), + }, + { + input: NewCgroupName(qosContainersInfo.Burstable), + expectedResult: false, + expectedUID: types.UID(""), + }, + { + input: NewCgroupName(qosContainersInfo.Burstable, GetPodCgroupNameSuffix(podUID)), + expectedResult: true, + expectedUID: podUID, + }, + { + input: NewCgroupName(qosContainersInfo.Burstable, GetPodCgroupNameSuffix(podUID), "container.scope"), + expectedResult: false, + expectedUID: types.UID(""), + }, + { + input: NewCgroupName(qosContainersInfo.BestEffort), + expectedResult: false, + expectedUID: types.UID(""), + }, + { + input: NewCgroupName(qosContainersInfo.BestEffort, GetPodCgroupNameSuffix(podUID)), + expectedResult: true, + expectedUID: podUID, + }, + { + input: NewCgroupName(qosContainersInfo.BestEffort, GetPodCgroupNameSuffix(podUID), "container.scope"), + expectedResult: false, + expectedUID: types.UID(""), + }, + { + input: NewCgroupName(RootCgroupName, "system"), + expectedResult: false, + expectedUID: types.UID(""), + }, + { + input: NewCgroupName(RootCgroupName, "system", "kubelet"), + expectedResult: false, + expectedUID: types.UID(""), + }, + } + for _, cgroupDriver := range []string{"cgroupfs", "systemd"} { + pcm := &podContainerManagerImpl{ + cgroupManager: NewCgroupManager(nil, cgroupDriver), + enforceCPULimits: true, + qosContainersInfo: qosContainersInfo, + } + for _, testCase := range testCases { + // give the right cgroup structure based on driver + cgroupfs := testCase.input.ToCgroupfs() + if cgroupDriver == "systemd" { + cgroupfs = testCase.input.ToSystemd() + } + // check if this is a pod or not with the literal cgroupfs input + result, resultUID := pcm.IsPodCgroup(cgroupfs) + if result != testCase.expectedResult { + t.Errorf("Unexpected result for driver: %v, input: %v, expected: %v, actual: %v", cgroupDriver, testCase.input, testCase.expectedResult, result) + } + if resultUID != testCase.expectedUID { + t.Errorf("Unexpected result for driver: %v, input: %v, expected: %v, actual: %v", cgroupDriver, testCase.input, testCase.expectedUID, resultUID) + } + + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_stub.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_stub.go index 61923f172..26c56ec79 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_stub.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_stub.go @@ -35,7 +35,7 @@ func (m *podContainerManagerStub) EnsureExists(_ *v1.Pod) error { } func (m *podContainerManagerStub) GetPodContainerName(_ *v1.Pod) (CgroupName, string) { - return "", "" + return nil, "" } func (m *podContainerManagerStub) Destroy(_ CgroupName) error { @@ -49,3 +49,7 @@ func (m *podContainerManagerStub) ReduceCPULimits(_ CgroupName) error { func (m *podContainerManagerStub) GetAllPodsFromCgroups() (map[types.UID]CgroupName, error) { return nil, nil } + +func (m *podContainerManagerStub) IsPodCgroup(cgroupfs string) (bool, types.UID) { + return false, types.UID("") +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/qos_container_manager_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/qos_container_manager_linux.go index 0cd855999..2cfc198c3 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/qos_container_manager_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/qos_container_manager_linux.go @@ -18,7 +18,6 @@ package cm import ( "fmt" - "path" "strings" "sync" "time" @@ -60,18 +59,18 @@ type qosContainerManagerImpl struct { qosReserved map[v1.ResourceName]int64 } -func NewQOSContainerManager(subsystems *CgroupSubsystems, cgroupRoot string, nodeConfig NodeConfig, cgroupManager CgroupManager) (QOSContainerManager, error) { +func NewQOSContainerManager(subsystems *CgroupSubsystems, cgroupRoot CgroupName, nodeConfig NodeConfig, cgroupManager CgroupManager) (QOSContainerManager, error) { if !nodeConfig.CgroupsPerQOS { return &qosContainerManagerNoop{ - cgroupRoot: CgroupName(cgroupRoot), + cgroupRoot: cgroupRoot, }, nil } return &qosContainerManagerImpl{ subsystems: subsystems, cgroupManager: cgroupManager, - cgroupRoot: CgroupName(cgroupRoot), - qosReserved: nodeConfig.ExperimentalQOSReserved, + cgroupRoot: cgroupRoot, + qosReserved: nodeConfig.QOSReserved, }, nil } @@ -81,23 +80,20 @@ func (m *qosContainerManagerImpl) GetQOSContainersInfo() QOSContainersInfo { func (m *qosContainerManagerImpl) Start(getNodeAllocatable func() v1.ResourceList, activePods ActivePodsFunc) error { cm := m.cgroupManager - rootContainer := string(m.cgroupRoot) - if !cm.Exists(CgroupName(rootContainer)) { - return fmt.Errorf("root container %s doesn't exist", rootContainer) + rootContainer := m.cgroupRoot + if !cm.Exists(rootContainer) { + return fmt.Errorf("root container %v doesn't exist", rootContainer) } // Top level for Qos containers are created only for Burstable // and Best Effort classes - qosClasses := map[v1.PodQOSClass]string{ - v1.PodQOSBurstable: path.Join(rootContainer, strings.ToLower(string(v1.PodQOSBurstable))), - v1.PodQOSBestEffort: path.Join(rootContainer, strings.ToLower(string(v1.PodQOSBestEffort))), + qosClasses := map[v1.PodQOSClass]CgroupName{ + v1.PodQOSBurstable: NewCgroupName(rootContainer, strings.ToLower(string(v1.PodQOSBurstable))), + v1.PodQOSBestEffort: NewCgroupName(rootContainer, strings.ToLower(string(v1.PodQOSBestEffort))), } // Create containers for both qos classes for qosClass, containerName := range qosClasses { - // get the container's absolute name - absoluteContainerName := CgroupName(containerName) - resourceParameters := &ResourceConfig{} // the BestEffort QoS class has a statically configured minShares value if qosClass == v1.PodQOSBestEffort { @@ -107,7 +103,7 @@ func (m *qosContainerManagerImpl) Start(getNodeAllocatable func() v1.ResourceLis // containerConfig object stores the cgroup specifications containerConfig := &CgroupConfig{ - Name: absoluteContainerName, + Name: containerName, ResourceParameters: resourceParameters, } @@ -117,7 +113,7 @@ func (m *qosContainerManagerImpl) Start(getNodeAllocatable func() v1.ResourceLis } // check if it exists - if !cm.Exists(absoluteContainerName) { + if !cm.Exists(containerName) { if err := cm.Create(containerConfig); err != nil { return fmt.Errorf("failed to create top level %v QOS cgroup : %v", qosClass, err) } @@ -279,11 +275,11 @@ func (m *qosContainerManagerImpl) UpdateCgroups() error { qosConfigs := map[v1.PodQOSClass]*CgroupConfig{ v1.PodQOSBurstable: { - Name: CgroupName(m.qosContainersInfo.Burstable), + Name: m.qosContainersInfo.Burstable, ResourceParameters: &ResourceConfig{}, }, v1.PodQOSBestEffort: { - Name: CgroupName(m.qosContainersInfo.BestEffort), + Name: m.qosContainersInfo.BestEffort, ResourceParameters: &ResourceConfig{}, }, } @@ -300,31 +296,34 @@ func (m *qosContainerManagerImpl) UpdateCgroups() error { } } - for resource, percentReserve := range m.qosReserved { - switch resource { - case v1.ResourceMemory: - m.setMemoryReserve(qosConfigs, percentReserve) + if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.QOSReserved) { + for resource, percentReserve := range m.qosReserved { + switch resource { + case v1.ResourceMemory: + m.setMemoryReserve(qosConfigs, percentReserve) + } } - } - updateSuccess := true - for _, config := range qosConfigs { - err := m.cgroupManager.Update(config) - if err != nil { - updateSuccess = false + + updateSuccess := true + for _, config := range qosConfigs { + err := m.cgroupManager.Update(config) + if err != nil { + updateSuccess = false + } + } + if updateSuccess { + glog.V(4).Infof("[ContainerManager]: Updated QoS cgroup configuration") + return nil } - } - if updateSuccess { - glog.V(4).Infof("[ContainerManager]: Updated QoS cgroup configuration") - return nil - } - // If the resource can adjust the ResourceConfig to increase likelihood of - // success, call the adjustment function here. Otherwise, the Update() will - // be called again with the same values. - for resource, percentReserve := range m.qosReserved { - switch resource { - case v1.ResourceMemory: - m.retrySetMemoryReserve(qosConfigs, percentReserve) + // If the resource can adjust the ResourceConfig to increase likelihood of + // success, call the adjustment function here. Otherwise, the Update() will + // be called again with the same values. + for resource, percentReserve := range m.qosReserved { + switch resource { + case v1.ResourceMemory: + m.retrySetMemoryReserve(qosConfigs, percentReserve) + } } } @@ -336,7 +335,7 @@ func (m *qosContainerManagerImpl) UpdateCgroups() error { } } - glog.V(4).Infof("[ContainerManager]: Updated QoS cgroup configuration on retry") + glog.V(4).Infof("[ContainerManager]: Updated QoS cgroup configuration") return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/types.go index ce2cc2c82..2e60d8a8f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/types.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/types.go @@ -38,7 +38,9 @@ type ResourceConfig struct { } // CgroupName is the abstract name of a cgroup prior to any driver specific conversion. -type CgroupName string +// It is specified as a list of strings from its individual components, such as: +// {"kubepods", "burstable", "pod1234-abcd-5678-efgh"} +type CgroupName []string // CgroupConfig holds the cgroup configuration information. // This is common object which is used to specify @@ -78,7 +80,7 @@ type CgroupManager interface { Exists(name CgroupName) bool // Name returns the literal cgroupfs name on the host after any driver specific conversions. // We would expect systemd implementation to make appropriate name conversion. - // For example, if we pass /foo/bar + // For example, if we pass {"foo", "bar"} // then systemd should convert the name to something like // foo.slice/foo-bar.slice Name(name CgroupName) string @@ -94,9 +96,9 @@ type CgroupManager interface { // QOSContainersInfo stores the names of containers per qos type QOSContainersInfo struct { - Guaranteed string - BestEffort string - Burstable string + Guaranteed CgroupName + BestEffort CgroupName + Burstable CgroupName } // PodContainerManager stores and manages pod level containers @@ -122,4 +124,7 @@ type PodContainerManager interface { // GetAllPodsFromCgroups enumerates the set of pod uids to their associated cgroup based on state of cgroupfs system. GetAllPodsFromCgroups() (map[types.UID]CgroupName, error) + + // IsPodCgroup returns true if the literal cgroupfs name corresponds to a pod + IsPodCgroup(cgroupfs string) (bool, types.UID) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/config/BUILD index 3f88dbf72..6985adfdd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/BUILD @@ -58,6 +58,7 @@ go_library( "//pkg/apis/core/v1:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/kubelet/checkpoint:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/events:go_default_library", "//pkg/kubelet/types:go_default_library", @@ -80,6 +81,7 @@ go_library( ] + select({ "@io_bazel_rules_go//go/platform:linux": [ "//vendor/golang.org/x/exp/inotify:go_default_library", + "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", ], "//conditions:default": [], }), @@ -91,6 +93,7 @@ go_test( "apiserver_test.go", "common_test.go", "config_test.go", + "file_test.go", "http_test.go", ] + select({ "@io_bazel_rules_go//go/platform:linux": [ @@ -105,6 +108,8 @@ go_test( "//pkg/apis/core:go_default_library", "//pkg/apis/core/v1:go_default_library", "//pkg/apis/core/validation:go_default_library", + "//pkg/kubelet/checkpoint:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/securitycontext:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/common.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/common.go index 1f45349d0..8fb4199f8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/common.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/common.go @@ -100,7 +100,7 @@ func getSelfLink(name, namespace string) string { if len(namespace) == 0 { namespace = metav1.NamespaceDefault } - selfLink = fmt.Sprintf("/api/"+legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.Version+"/namespaces/%s/pods/%s", namespace, name) + selfLink = fmt.Sprintf("/api/v1/namespaces/%s/pods/%s", namespace, name) return selfLink } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/common_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/common_test.go index 451734918..5aa144798 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/common_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/common_test.go @@ -78,7 +78,7 @@ func TestDecodeSinglePod(t *testing.T) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, podOut, string(json)) } - for _, gv := range legacyscheme.Registry.EnabledVersionsForGroup(v1.GroupName) { + for _, gv := range legacyscheme.Scheme.PrioritizedVersionsForGroup(v1.GroupName) { info, _ := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), "application/yaml") encoder := legacyscheme.Codecs.EncoderForVersion(info.Serializer, gv) yaml, err := runtime.Encode(encoder, pod) @@ -144,7 +144,7 @@ func TestDecodePodList(t *testing.T) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", podList, &podListOut, string(json)) } - for _, gv := range legacyscheme.Registry.EnabledVersionsForGroup(v1.GroupName) { + for _, gv := range legacyscheme.Scheme.PrioritizedVersionsForGroup(v1.GroupName) { info, _ := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), "application/yaml") encoder := legacyscheme.Codecs.EncoderForVersion(info.Serializer, gv) yaml, err := runtime.Encode(encoder, podList) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/config.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/config.go index c03e32512..51c2e29c5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/config.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/config.go @@ -27,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/kubelet/checkpoint" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/events" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" @@ -64,7 +65,7 @@ type PodConfig struct { // contains the list of all configured sources sourcesLock sync.Mutex sources sets.String - checkpointManager checkpoint.Manager + checkpointManager checkpointmanager.CheckpointManager } // NewPodConfig creates an object that can merge many configuration sources into a stream @@ -112,15 +113,20 @@ func (c *PodConfig) Sync() { // Restore restores pods from the checkpoint path, *once* func (c *PodConfig) Restore(path string, updates chan<- interface{}) error { + if c.checkpointManager != nil { + return nil + } var err error - if c.checkpointManager == nil { - c.checkpointManager = checkpoint.NewCheckpointManager(path) - pods, err := c.checkpointManager.LoadPods() - if err == nil { - updates <- kubetypes.PodUpdate{Pods: pods, Op: kubetypes.RESTORE, Source: kubetypes.ApiserverSource} - } + c.checkpointManager, err = checkpointmanager.NewCheckpointManager(path) + if err != nil { + return err + } + pods, err := checkpoint.LoadPods(c.checkpointManager) + if err != nil { + return err } - return err + updates <- kubetypes.PodUpdate{Pods: pods, Op: kubetypes.RESTORE, Source: kubetypes.ApiserverSource} + return nil } // podStorage manages the current pod state at any point in time and ensures updates @@ -308,6 +314,9 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de } case kubetypes.RESTORE: glog.V(4).Infof("Restoring pods for source %s", source) + for _, value := range update.Pods { + restorePods = append(restorePods, value) + } default: glog.Warningf("Received invalid update type: %v", update) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/config_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/config_test.go index deb1f4dca..9ebf5a660 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/config_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/config_test.go @@ -17,7 +17,9 @@ limitations under the License. package config import ( + "io/ioutil" "math/rand" + "os" "reflect" "sort" "strconv" @@ -30,6 +32,9 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/tools/record" + "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/kubelet/checkpoint" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/securitycontext" ) @@ -85,6 +90,14 @@ func CreatePodUpdate(op kubetypes.PodOperation, source string, pods ...*v1.Pod) return kubetypes.PodUpdate{Pods: pods, Op: op, Source: source} } +func createPodConfigTesterByChannel(mode PodConfigNotificationMode, channelName string) (chan<- interface{}, <-chan kubetypes.PodUpdate, *PodConfig) { + eventBroadcaster := record.NewBroadcaster() + config := NewPodConfig(mode, eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "kubelet"})) + channel := config.Channel(channelName) + ch := config.Updates() + return channel, ch, config +} + func createPodConfigTester(mode PodConfigNotificationMode) (chan<- interface{}, <-chan kubetypes.PodUpdate, *PodConfig) { eventBroadcaster := record.NewBroadcaster() config := NewPodConfig(mode, eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "kubelet"})) @@ -413,3 +426,35 @@ func TestPodUpdateLabels(t *testing.T) { expectPodUpdate(t, ch, CreatePodUpdate(kubetypes.UPDATE, TestSource, pod)) } + +func TestPodRestore(t *testing.T) { + tmpDir, _ := ioutil.TempDir("", "") + defer os.RemoveAll(tmpDir) + + pod := CreateValidPod("api-server", "kube-default") + pod.Annotations = make(map[string]string, 0) + pod.Annotations["kubernetes.io/config.source"] = kubetypes.ApiserverSource + pod.Annotations[core.BootstrapCheckpointAnnotationKey] = "true" + + // Create Checkpointer + checkpointManager, err := checkpointmanager.NewCheckpointManager(tmpDir) + if err != nil { + t.Fatalf("failed to initialize checkpoint manager: %v", err) + } + if err := checkpoint.WritePod(checkpointManager, pod); err != nil { + t.Fatalf("Error writing checkpoint for pod: %v", pod.GetName()) + } + + // Restore checkpoint + channel, ch, config := createPodConfigTesterByChannel(PodConfigNotificationIncremental, kubetypes.ApiserverSource) + if err := config.Restore(tmpDir, channel); err != nil { + t.Fatalf("Restore returned error: %v", err) + } + expectPodUpdate(t, ch, CreatePodUpdate(kubetypes.RESTORE, kubetypes.ApiserverSource, pod)) + + // Verify Restore only happen once + if err := config.Restore(tmpDir, channel); err != nil { + t.Fatalf("The second restore returned error: %v", err) + } + expectNoPodUpdate(t, ch) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/file.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file.go index b96a790ec..7fbf53349 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/file.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file.go @@ -30,30 +30,46 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/tools/cache" api "k8s.io/kubernetes/pkg/apis/core" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" ) +type podEventType int + +const ( + podAdd podEventType = iota + podModify + podDelete + + eventBufferLen = 10 +) + +type watchEvent struct { + fileName string + eventType podEventType +} + type sourceFile struct { path string nodeName types.NodeName + period time.Duration store cache.Store fileKeyMapping map[string]string updates chan<- interface{} + watchEvents chan *watchEvent } func NewSourceFile(path string, nodeName types.NodeName, period time.Duration, updates chan<- interface{}) { // "golang.org/x/exp/inotify" requires a path without trailing "/" path = strings.TrimRight(path, string(os.PathSeparator)) - config := newSourceFile(path, nodeName, updates) + config := newSourceFile(path, nodeName, period, updates) glog.V(1).Infof("Watching path %q", path) - go wait.Forever(config.run, period) + config.run() } -func newSourceFile(path string, nodeName types.NodeName, updates chan<- interface{}) *sourceFile { +func newSourceFile(path string, nodeName types.NodeName, period time.Duration, updates chan<- interface{}) *sourceFile { send := func(objs []interface{}) { var pods []*v1.Pod for _, o := range objs { @@ -65,23 +81,40 @@ func newSourceFile(path string, nodeName types.NodeName, updates chan<- interfac return &sourceFile{ path: path, nodeName: nodeName, + period: period, store: store, fileKeyMapping: map[string]string{}, updates: updates, + watchEvents: make(chan *watchEvent, eventBufferLen), } } func (s *sourceFile) run() { - if err := s.watch(); err != nil { - glog.Errorf("Unable to read manifest path %q: %v", s.path, err) - } + listTicker := time.NewTicker(s.period) + + go func() { + for { + select { + case <-listTicker.C: + if err := s.listConfig(); err != nil { + glog.Errorf("Unable to read config path %q: %v", s.path, err) + } + case e := <-s.watchEvents: + if err := s.consumeWatchEvent(e); err != nil { + glog.Errorf("Unable to process watch event: %v", err) + } + } + } + }() + + s.startWatch() } func (s *sourceFile) applyDefaults(pod *api.Pod, source string) error { return applyDefaults(pod, source, true, s.nodeName) } -func (s *sourceFile) resetStoreFromPath() error { +func (s *sourceFile) listConfig() error { path := s.path statInfo, err := os.Stat(path) if err != nil { @@ -158,7 +191,7 @@ func (s *sourceFile) extractFromDir(name string) ([]*v1.Pod, error) { } func (s *sourceFile) extractFromFile(filename string) (pod *v1.Pod, err error) { - glog.V(3).Infof("Reading manifest file %q", filename) + glog.V(3).Infof("Reading config file %q", filename) defer func() { if err == nil && pod != nil { objKey, keyErr := cache.MetaNamespaceKeyFunc(pod) @@ -193,7 +226,7 @@ func (s *sourceFile) extractFromFile(filename string) (pod *v1.Pod, err error) { return pod, nil } - return pod, fmt.Errorf("%v: couldn't parse as pod(%v), please check manifest file.\n", filename, podErr) + return pod, fmt.Errorf("%v: couldn't parse as pod(%v), please check config file.\n", filename, podErr) } func (s *sourceFile) replaceStore(pods ...*v1.Pod) (err error) { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_linux.go index 315c80a68..4e6b1a5a2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_linux.go @@ -24,23 +24,49 @@ import ( "os" "path/filepath" "strings" + "time" "github.com/golang/glog" "golang.org/x/exp/inotify" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/util/flowcontrol" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" ) -type podEventType int - const ( - podAdd podEventType = iota - podModify - podDelete + retryPeriod = 1 * time.Second + maxRetryPeriod = 20 * time.Second ) -func (s *sourceFile) watch() error { +type retryableError struct { + message string +} + +func (e *retryableError) Error() string { + return e.message +} + +func (s *sourceFile) startWatch() { + backOff := flowcontrol.NewBackOff(retryPeriod, maxRetryPeriod) + backOffId := "watch" + + go wait.Forever(func() { + if backOff.IsInBackOffSinceUpdate(backOffId, time.Now()) { + return + } + + if err := s.doWatch(); err != nil { + glog.Errorf("Unable to read config path %q: %v", s.path, err) + if _, retryable := err.(*retryableError); !retryable { + backOff.Next(backOffId, time.Now()) + } + } + }, retryPeriod) +} + +func (s *sourceFile) doWatch() error { _, err := os.Stat(s.path) if err != nil { if !os.IsNotExist(err) { @@ -48,7 +74,7 @@ func (s *sourceFile) watch() error { } // Emit an update with an empty PodList to allow FileSource to be marked as seen s.updates <- kubetypes.PodUpdate{Pods: []*v1.Pod{}, Op: kubetypes.SET, Source: kubetypes.FileSource} - return fmt.Errorf("path does not exist, ignoring") + return &retryableError{"path does not exist, ignoring"} } w, err := inotify.NewWatcher() @@ -57,22 +83,16 @@ func (s *sourceFile) watch() error { } defer w.Close() - err = w.AddWatch(s.path, inotify.IN_DELETE_SELF|inotify.IN_CREATE|inotify.IN_MOVED_TO|inotify.IN_MODIFY|inotify.IN_MOVED_FROM|inotify.IN_DELETE) + err = w.AddWatch(s.path, inotify.IN_DELETE_SELF|inotify.IN_CREATE|inotify.IN_MOVED_TO|inotify.IN_MODIFY|inotify.IN_MOVED_FROM|inotify.IN_DELETE|inotify.IN_ATTRIB) if err != nil { return fmt.Errorf("unable to create inotify for path %q: %v", s.path, err) } - // Reset store with manifest files already existing when starting - if err := s.resetStoreFromPath(); err != nil { - return fmt.Errorf("unable to read manifest path %q: %v", s.path, err) - } - for { select { case event := <-w.Event: - err = s.processEvent(event) - if err != nil { - return fmt.Errorf("error while processing event (%+v): %v", event, err) + if err = s.produceWatchEvent(event); err != nil { + return fmt.Errorf("error while processing inotify event (%+v): %v", event, err) } case err = <-w.Error: return fmt.Errorf("error while watching %q: %v", s.path, err) @@ -80,7 +100,7 @@ func (s *sourceFile) watch() error { } } -func (s *sourceFile) processEvent(e *inotify.Event) error { +func (s *sourceFile) produceWatchEvent(e *inotify.Event) error { // Ignore file start with dots if strings.HasPrefix(filepath.Base(e.Name), ".") { glog.V(4).Infof("Ignored pod manifest: %s, because it starts with dots", e.Name) @@ -97,6 +117,8 @@ func (s *sourceFile) processEvent(e *inotify.Event) error { eventType = podAdd case (e.Mask & inotify.IN_MODIFY) > 0: eventType = podModify + case (e.Mask & inotify.IN_ATTRIB) > 0: + eventType = podModify case (e.Mask & inotify.IN_DELETE) > 0: eventType = podDelete case (e.Mask & inotify.IN_MOVED_FROM) > 0: @@ -108,22 +130,31 @@ func (s *sourceFile) processEvent(e *inotify.Event) error { return nil } - switch eventType { + s.watchEvents <- &watchEvent{e.Name, eventType} + return nil +} + +func (s *sourceFile) consumeWatchEvent(e *watchEvent) error { + switch e.eventType { case podAdd, podModify: - if pod, err := s.extractFromFile(e.Name); err != nil { - glog.Errorf("Can't process manifest file %q: %v", e.Name, err) + if pod, err := s.extractFromFile(e.fileName); err != nil { + return fmt.Errorf("can't process config file %q: %v", e.fileName, err) } else { return s.store.Add(pod) } case podDelete: - if objKey, keyExist := s.fileKeyMapping[e.Name]; keyExist { + if objKey, keyExist := s.fileKeyMapping[e.fileName]; keyExist { pod, podExist, err := s.store.GetByKey(objKey) if err != nil { return err } else if !podExist { return fmt.Errorf("the pod with key %s doesn't exist in cache", objKey) } else { - return s.store.Delete(pod) + if err = s.store.Delete(pod); err != nil { + return fmt.Errorf("failed to remove deleted pod from cache: %v", err) + } else { + delete(s.fileKeyMapping, e.fileName) + } } } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_linux_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_linux_test.go index c1b133977..70bc2bffa 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_linux_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_linux_test.go @@ -21,7 +21,6 @@ package config import ( "fmt" "io" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -35,7 +34,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" - utiltesting "k8s.io/client-go/util/testing" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" api "k8s.io/kubernetes/pkg/apis/core" k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1" @@ -46,8 +45,8 @@ import ( func TestExtractFromNonExistentFile(t *testing.T) { ch := make(chan interface{}, 1) - c := newSourceFile("/some/fake/file", "localhost", ch) - err := c.watch() + lw := newSourceFile("/some/fake/file", "localhost", time.Millisecond, ch) + err := lw.doWatch() if err == nil { t.Errorf("Expected error") } @@ -75,7 +74,7 @@ func TestReadPodsFromFileExistAlready(t *testing.T) { for _, testCase := range testCases { func() { - dirName, err := utiltesting.MkTmpdir("file-test") + dirName, err := mkTempDir("file-test") if err != nil { t.Fatalf("unable to create temp dir: %v", err) } @@ -107,69 +106,35 @@ func TestReadPodsFromFileExistAlready(t *testing.T) { } } -func TestReadPodsFromFileExistLater(t *testing.T) { - watchFileAdded(false, t) -} - -func TestReadPodsFromFileChanged(t *testing.T) { - watchFileChanged(false, t) -} - -func TestReadPodsFromFileInDirAdded(t *testing.T) { - watchFileAdded(true, t) -} - -func TestReadPodsFromFileInDirChanged(t *testing.T) { - watchFileChanged(true, t) -} - -func TestExtractFromBadDataFile(t *testing.T) { - dirName, err := utiltesting.MkTmpdir("file-test") - if err != nil { - t.Fatalf("unable to create temp dir: %v", err) - } - defer os.RemoveAll(dirName) - - fileName := filepath.Join(dirName, "test_pod_manifest") - err = ioutil.WriteFile(fileName, []byte{1, 2, 3}, 0555) - if err != nil { - t.Fatalf("unable to write test file %#v", err) +var ( + testCases = []struct { + watchDir bool + symlink bool + }{ + {true, true}, + {true, false}, + {false, true}, + {false, false}, } +) - ch := make(chan interface{}, 1) - c := newSourceFile(fileName, "localhost", ch) - err = c.resetStoreFromPath() - if err == nil { - t.Fatalf("expected error, got nil") +func TestWatchFileAdded(t *testing.T) { + for _, testCase := range testCases { + watchFileAdded(testCase.watchDir, testCase.symlink, t) } - expectEmptyChannel(t, ch) } -func TestExtractFromEmptyDir(t *testing.T) { - dirName, err := utiltesting.MkTmpdir("file-test") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - defer os.RemoveAll(dirName) - - ch := make(chan interface{}, 1) - c := newSourceFile(dirName, "localhost", ch) - err = c.resetStoreFromPath() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - update := (<-ch).(kubetypes.PodUpdate) - expected := CreatePodUpdate(kubetypes.SET, kubetypes.FileSource) - if !apiequality.Semantic.DeepEqual(expected, update) { - t.Fatalf("expected %#v, Got %#v", expected, update) +func TestWatchFileChanged(t *testing.T) { + for _, testCase := range testCases { + watchFileChanged(testCase.watchDir, testCase.symlink, t) } } type testCase struct { - desc string - pod runtime.Object - expected kubetypes.PodUpdate + desc string + linkedFile string + pod runtime.Object + expected kubetypes.PodUpdate } func getTestCases(hostname types.NodeName) []*testCase { @@ -234,7 +199,7 @@ func getTestCases(hostname types.NodeName) []*testCase { func (tc *testCase) writeToFile(dir, name string, t *testing.T) string { var versionedPod runtime.Object - err := testapi.Default.Converter().Convert(&tc.pod, &versionedPod, nil) + err := legacyscheme.Scheme.Convert(&tc.pod, &versionedPod, nil) if err != nil { t.Fatalf("%s: error in versioning the pod: %v", tc.desc, err) } @@ -250,19 +215,40 @@ func (tc *testCase) writeToFile(dir, name string, t *testing.T) string { return fileName } -func watchFileAdded(watchDir bool, t *testing.T) { +func createSymbolicLink(link, target, name string, t *testing.T) string { + linkName := filepath.Join(link, name) + linkedFile := filepath.Join(target, name) + + err := os.Symlink(linkedFile, linkName) + if err != nil { + t.Fatalf("unexpected error when create symbolic link: %v", err) + } + return linkName +} + +func watchFileAdded(watchDir bool, symlink bool, t *testing.T) { hostname := types.NodeName("random-test-hostname") var testCases = getTestCases(hostname) fileNamePre := "test_pod_manifest" for index, testCase := range testCases { func() { - dirName, err := utiltesting.MkTmpdir("dir-test") + dirName, err := mkTempDir("dir-test") if err != nil { t.Fatalf("unable to create temp dir: %v", err) } - defer os.RemoveAll(dirName) + defer removeAll(dirName, t) + fileName := fmt.Sprintf("%s_%d", fileNamePre, index) + var linkedDirName string + if symlink { + linkedDirName, err = mkTempDir("linked-dir-test") + if err != nil { + t.Fatalf("unable to create temp dir for linked files: %v", err) + } + defer removeAll(linkedDirName, t) + createSymbolicLink(dirName, linkedDirName, fileName, t) + } ch := make(chan interface{}) if watchDir { @@ -274,12 +260,17 @@ func watchFileAdded(watchDir bool, t *testing.T) { addFile := func() { // Add a file + if symlink { + testCase.writeToFile(linkedDirName, fileName, t) + return + } + testCase.writeToFile(dirName, fileName, t) } go addFile() - // For !watchDir: expect an update by SourceFile.resetStoreFromPath(). + // For !watchDir: expect an update by SourceFile.reloadConfig(). // For watchDir: expect at least one update from CREATE & MODIFY inotify event. // Shouldn't expect two updates from CREATE & MODIFY because CREATE doesn't guarantee file written. // In that case no update will be sent from CREATE event. @@ -288,19 +279,29 @@ func watchFileAdded(watchDir bool, t *testing.T) { } } -func watchFileChanged(watchDir bool, t *testing.T) { +func watchFileChanged(watchDir bool, symlink bool, t *testing.T) { hostname := types.NodeName("random-test-hostname") var testCases = getTestCases(hostname) fileNamePre := "test_pod_manifest" for index, testCase := range testCases { func() { - dirName, err := utiltesting.MkTmpdir("dir-test") + dirName, err := mkTempDir("dir-test") fileName := fmt.Sprintf("%s_%d", fileNamePre, index) if err != nil { t.Fatalf("unable to create temp dir: %v", err) } - defer os.RemoveAll(dirName) + defer removeAll(dirName, t) + + var linkedDirName string + if symlink { + linkedDirName, err = mkTempDir("linked-dir-test") + if err != nil { + t.Fatalf("unable to create temp dir for linked files: %v", err) + } + defer removeAll(linkedDirName, t) + createSymbolicLink(dirName, linkedDirName, fileName, t) + } var file string lock := &sync.Mutex{} @@ -308,6 +309,12 @@ func watchFileChanged(watchDir bool, t *testing.T) { func() { lock.Lock() defer lock.Unlock() + + if symlink { + file = testCase.writeToFile(linkedDirName, fileName, t) + return + } + file = testCase.writeToFile(dirName, fileName, t) }() @@ -332,7 +339,12 @@ func watchFileChanged(watchDir bool, t *testing.T) { pod.Spec.Containers[0].Name = "image2" testCase.expected.Pods[0].Spec.Containers[0].Name = "image2" - testCase.writeToFile(dirName, fileName, t) + if symlink { + file = testCase.writeToFile(linkedDirName, fileName, t) + return + } + + file = testCase.writeToFile(dirName, fileName, t) } go changeFile() @@ -370,6 +382,10 @@ func expectUpdate(t *testing.T, ch chan interface{}, testCase *testCase) { select { case got := <-ch: update := got.(kubetypes.PodUpdate) + if len(update.Pods) == 0 { + // filter out the empty updates from reading a non-existing path + continue + } for _, pod := range update.Pods { // TODO: remove the conversion when validation is performed on versioned objects. internalPod := &api.Pod{} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_test.go new file mode 100644 index 000000000..36c9f2108 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_test.go @@ -0,0 +1,84 @@ +/* +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 config + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + "time" + + apiequality "k8s.io/apimachinery/pkg/api/equality" + kubetypes "k8s.io/kubernetes/pkg/kubelet/types" +) + +func TestExtractFromBadDataFile(t *testing.T) { + dirName, err := mkTempDir("file-test") + if err != nil { + t.Fatalf("unable to create temp dir: %v", err) + } + defer removeAll(dirName, t) + + fileName := filepath.Join(dirName, "test_pod_config") + err = ioutil.WriteFile(fileName, []byte{1, 2, 3}, 0555) + if err != nil { + t.Fatalf("unable to write test file %#v", err) + } + + ch := make(chan interface{}, 1) + lw := newSourceFile(fileName, "localhost", time.Millisecond, ch) + err = lw.listConfig() + if err == nil { + t.Fatalf("expected error, got nil") + } + expectEmptyChannel(t, ch) +} + +func TestExtractFromEmptyDir(t *testing.T) { + dirName, err := mkTempDir("file-test") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + defer removeAll(dirName, t) + + ch := make(chan interface{}, 1) + lw := newSourceFile(dirName, "localhost", time.Millisecond, ch) + err = lw.listConfig() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + update, ok := (<-ch).(kubetypes.PodUpdate) + if !ok { + t.Fatalf("unexpected type: %#v", update) + } + expected := CreatePodUpdate(kubetypes.SET, kubetypes.FileSource) + if !apiequality.Semantic.DeepEqual(expected, update) { + t.Fatalf("expected %#v, got %#v", expected, update) + } +} + +func mkTempDir(prefix string) (string, error) { + return ioutil.TempDir(os.TempDir(), prefix) +} + +func removeAll(dir string, t *testing.T) { + if err := os.RemoveAll(dir); err != nil { + t.Fatalf("unable to remove dir %s: %v", dir, err) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_unsupported.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_unsupported.go index c30ede443..4bee74f54 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/file_unsupported.go @@ -19,8 +19,16 @@ limitations under the License. // Reads the pod configuration from file or a directory of files. package config -import "errors" +import ( + "fmt" -func (s *sourceFile) watch() error { - return errors.New("source file is unsupported in this build") + "github.com/golang/glog" +) + +func (s *sourceFile) startWatch() { + glog.Errorf("Watching source file is unsupported in this build") +} + +func (s *sourceFile) consumeWatchEvent(e *watchEvent) error { + return fmt.Errorf("consuming watch event is unsupported in this build") } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/flags.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/flags.go index 19d595041..771058079 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/flags.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/flags.go @@ -17,6 +17,8 @@ limitations under the License. package config import ( + "fmt" + "github.com/spf13/pflag" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -29,6 +31,15 @@ type ContainerRuntimeOptions struct { ContainerRuntime string // RuntimeCgroups that container runtime is expected to be isolated in. RuntimeCgroups string + // RedirectContainerStreaming enables container streaming redirect. + // When RedirectContainerStreaming is false, kubelet will proxy container streaming data + // between apiserver and container runtime. This approach is more secure, but the proxy + // introduces some overhead. + // When RedirectContainerStreaming is true, kubelet will return an http redirect to apiserver, + // and apiserver will access container runtime directly. This approach is more performant, + // but less secure because the connection between apiserver and container runtime is not + // authenticated. + RedirectContainerStreaming bool // Docker-specific options. @@ -67,45 +78,30 @@ type ContainerRuntimeOptions struct { // CNIBinDir is the full path of the directory in which to search for // CNI plugin binaries CNIBinDir string - - // rkt-specific options. - - // rktPath is the path of rkt binary. Leave empty to use the first rkt in $PATH. - RktPath string - // rktApiEndpoint is the endpoint of the rkt API service to communicate with. - RktAPIEndpoint string - // rktStage1Image is the image to use as stage1. Local paths and - // http/https URLs are supported. - RktStage1Image string } func (s *ContainerRuntimeOptions) AddFlags(fs *pflag.FlagSet) { + dockerOnlyWarning := "This docker-specific flag only works when container-runtime is set to docker." + // General settings. fs.StringVar(&s.ContainerRuntime, "container-runtime", s.ContainerRuntime, "The container runtime to use. Possible values: 'docker', 'remote', 'rkt (deprecated)'.") fs.StringVar(&s.RuntimeCgroups, "runtime-cgroups", s.RuntimeCgroups, "Optional absolute name of cgroups to create and run the runtime in.") + fs.BoolVar(&s.RedirectContainerStreaming, "redirect-container-streaming", s.RedirectContainerStreaming, "Enables container streaming redirect. If false, kubelet will proxy container streaming data between apiserver and container runtime; if true, kubelet will return an http redirect to apiserver, and apiserver will access container runtime directly. The proxy approach is more secure, but introduces some overhead. The redirect approach is more performant, but less secure because the connection between apiserver and container runtime may not be authenticated.") // Docker-specific settings. fs.BoolVar(&s.ExperimentalDockershim, "experimental-dockershim", s.ExperimentalDockershim, "Enable dockershim only mode. In this mode, kubelet will only start dockershim without any other functionalities. This flag only serves test purpose, please do not use it unless you are conscious of what you are doing. [default=false]") fs.MarkHidden("experimental-dockershim") fs.StringVar(&s.DockershimRootDirectory, "experimental-dockershim-root-directory", s.DockershimRootDirectory, "Path to the dockershim root directory.") fs.MarkHidden("experimental-dockershim-root-directory") - fs.BoolVar(&s.DockerDisableSharedPID, "docker-disable-shared-pid", s.DockerDisableSharedPID, "Setting this to false causes Kubernetes to create pods using a shared process namespace for containers in a pod when running with Docker 1.13.1 or higher. A future Kubernetes release will make this configurable instead in the API.") + fs.BoolVar(&s.DockerDisableSharedPID, "docker-disable-shared-pid", s.DockerDisableSharedPID, fmt.Sprintf("Setting this to false causes Kubernetes to create pods using a shared process namespace for containers in a pod when running with Docker 1.13.1 or higher. A future Kubernetes release will make this configurable instead in the API. %s", dockerOnlyWarning)) fs.MarkDeprecated("docker-disable-shared-pid", "will be removed in a future release. This option will be replaced by PID namespace sharing that is configurable per-pod using the API. See https://features.k8s.io/495") - fs.StringVar(&s.PodSandboxImage, "pod-infra-container-image", s.PodSandboxImage, "The image whose network/ipc namespaces containers in each pod will use.") - fs.StringVar(&s.DockerEndpoint, "docker-endpoint", s.DockerEndpoint, "Use this for the docker endpoint to communicate with") - fs.DurationVar(&s.ImagePullProgressDeadline.Duration, "image-pull-progress-deadline", s.ImagePullProgressDeadline.Duration, "If no pulling progress is made before this deadline, the image pulling will be cancelled.") - - // Network plugin settings. Shared by both docker and rkt. - fs.StringVar(&s.NetworkPluginName, "network-plugin", s.NetworkPluginName, " The name of the network plugin to be invoked for various events in kubelet/pod lifecycle") - fs.StringVar(&s.CNIConfDir, "cni-conf-dir", s.CNIConfDir, " The full path of the directory in which to search for CNI config files. Default: /etc/cni/net.d") - fs.StringVar(&s.CNIBinDir, "cni-bin-dir", s.CNIBinDir, " The full path of the directory in which to search for CNI plugin binaries. Default: /opt/cni/bin") - fs.Int32Var(&s.NetworkPluginMTU, "network-plugin-mtu", s.NetworkPluginMTU, " The MTU to be passed to the network plugin, to override the default. Set to 0 to use the default 1460 MTU.") - - // Rkt-specific settings. - fs.StringVar(&s.RktPath, "rkt-path", s.RktPath, "Path of rkt binary. Leave empty to use the first rkt in $PATH. Only used if --container-runtime='rkt'.") - fs.MarkDeprecated("rkt-path", "will be removed in a future version. Rktnetes has been deprecated in favor of rktlet (https://github.com/kubernetes-incubator/rktlet).") - fs.StringVar(&s.RktAPIEndpoint, "rkt-api-endpoint", s.RktAPIEndpoint, "The endpoint of the rkt API service to communicate with. Only used if --container-runtime='rkt'.") - fs.MarkDeprecated("rkt-api-endpoint", "will be removed in a future version. Rktnetes has been deprecated in favor of rktlet (https://github.com/kubernetes-incubator/rktlet).") - fs.StringVar(&s.RktStage1Image, "rkt-stage1-image", s.RktStage1Image, "image to use as stage1. Local paths and http/https URLs are supported. If empty, the 'stage1.aci' in the same directory as '--rkt-path' will be used.") - fs.MarkDeprecated("rkt-stage1-image", "will be removed in a future version. Rktnetes has been deprecated in favor of rktlet (https://github.com/kubernetes-incubator/rktlet).") + fs.StringVar(&s.PodSandboxImage, "pod-infra-container-image", s.PodSandboxImage, fmt.Sprintf("The image whose network/ipc namespaces containers in each pod will use. %s", dockerOnlyWarning)) + fs.StringVar(&s.DockerEndpoint, "docker-endpoint", s.DockerEndpoint, fmt.Sprintf("Use this for the docker endpoint to communicate with %s", dockerOnlyWarning)) + fs.DurationVar(&s.ImagePullProgressDeadline.Duration, "image-pull-progress-deadline", s.ImagePullProgressDeadline.Duration, fmt.Sprintf("If no pulling progress is made before this deadline, the image pulling will be cancelled. %s", dockerOnlyWarning)) + + // Network plugin settings for Docker. + fs.StringVar(&s.NetworkPluginName, "network-plugin", s.NetworkPluginName, fmt.Sprintf(" The name of the network plugin to be invoked for various events in kubelet/pod lifecycle. %s", dockerOnlyWarning)) + fs.StringVar(&s.CNIConfDir, "cni-conf-dir", s.CNIConfDir, fmt.Sprintf(" The full path of the directory in which to search for CNI config files. Default: /etc/cni/net.d. %s", dockerOnlyWarning)) + fs.StringVar(&s.CNIBinDir, "cni-bin-dir", s.CNIBinDir, fmt.Sprintf(" A comma-separated list of full paths of directories in which to search for CNI plugin binaries. Default: /opt/cni/bin. %s", dockerOnlyWarning)) + fs.Int32Var(&s.NetworkPluginMTU, "network-plugin-mtu", s.NetworkPluginMTU, fmt.Sprintf(" The MTU to be passed to the network plugin, to override the default. Set to 0 to use the default 1460 MTU. %s", dockerOnlyWarning)) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/config/http_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/config/http_test.go index edb25dda9..f4dff0887 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/config/http_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/config/http_test.go @@ -72,7 +72,7 @@ func TestExtractInvalidPods(t *testing.T) { { desc: "Invalid volume name", pod: &v1.Pod{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, Spec: v1.PodSpec{ Volumes: []v1.Volume{{Name: "_INVALID_"}}, }, @@ -81,7 +81,7 @@ func TestExtractInvalidPods(t *testing.T) { { desc: "Duplicate volume names", pod: &v1.Pod{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, Spec: v1.PodSpec{ Volumes: []v1.Volume{{Name: "repeated"}, {Name: "repeated"}}, }, @@ -90,7 +90,7 @@ func TestExtractInvalidPods(t *testing.T) { { desc: "Unspecified container name", pod: &v1.Pod{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, Spec: v1.PodSpec{ Containers: []v1.Container{{Name: ""}}, }, @@ -99,7 +99,7 @@ func TestExtractInvalidPods(t *testing.T) { { desc: "Invalid container name", pod: &v1.Pod{ - TypeMeta: metav1.TypeMeta{APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, Spec: v1.PodSpec{ Containers: []v1.Container{{Name: "_INVALID_"}}, }, @@ -290,7 +290,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { for _, testCase := range testCases { var versionedPods runtime.Object - err := testapi.Default.Converter().Convert(&testCase.pods, &versionedPods, nil) + err := legacyscheme.Scheme.Convert(&testCase.pods, &versionedPods, nil) if err != nil { t.Fatalf("%s: error in versioning the pods: %s", testCase.desc, err) } @@ -331,7 +331,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { func TestURLWithHeader(t *testing.T) { pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", Kind: "Pod", }, ObjectMeta: metav1.ObjectMeta{ diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/BUILD index 4762f1e9b..84d1e029d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/BUILD @@ -15,13 +15,12 @@ go_library( importpath = "k8s.io/kubernetes/pkg/kubelet/configmap", deps = [ "//pkg/api/v1/pod:go_default_library", - "//pkg/kubelet/util:go_default_library", + "//pkg/kubelet/util/manager:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apiserver/pkg/storage/etcd:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) @@ -44,13 +43,12 @@ go_test( srcs = ["configmap_manager_test.go"], embed = [":go_default_library"], deps = [ - "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//pkg/kubelet/util/manager:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager.go index 71a7ae148..91c75ddca 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager.go @@ -18,26 +18,19 @@ package configmap import ( "fmt" - "strconv" - "sync" "time" "k8s.io/api/core/v1" - storageetcd "k8s.io/apiserver/pkg/storage/etcd" clientset "k8s.io/client-go/kubernetes" podutil "k8s.io/kubernetes/pkg/api/v1/pod" - "k8s.io/kubernetes/pkg/kubelet/util" + "k8s.io/kubernetes/pkg/kubelet/util/manager" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/clock" "k8s.io/apimachinery/pkg/util/sets" ) -const ( - defaultTTL = time.Minute -) - type Manager interface { // Get configmap by configmap namespace and name. GetConfigMap(namespace, name string) (*v1.ConfigMap, error) @@ -73,191 +66,31 @@ func (s *simpleConfigMapManager) RegisterPod(pod *v1.Pod) { func (s *simpleConfigMapManager) UnregisterPod(pod *v1.Pod) { } -type GetObjectTTLFunc func() (time.Duration, bool) - -type objectKey struct { - namespace string - name string -} - -// configMapStoreItems is a single item stored in configMapStore. -type configMapStoreItem struct { - refCount int - configMap *configMapData -} - -type configMapData struct { - sync.Mutex - - configMap *v1.ConfigMap - err error - lastUpdateTime time.Time -} - -// configMapStore is a local cache of configmaps. -type configMapStore struct { - kubeClient clientset.Interface - clock clock.Clock - - lock sync.Mutex - items map[objectKey]*configMapStoreItem - - defaultTTL time.Duration - getTTL GetObjectTTLFunc -} - -func newConfigMapStore(kubeClient clientset.Interface, clock clock.Clock, getTTL GetObjectTTLFunc, ttl time.Duration) *configMapStore { - return &configMapStore{ - kubeClient: kubeClient, - clock: clock, - items: make(map[objectKey]*configMapStoreItem), - defaultTTL: ttl, - getTTL: getTTL, - } -} - -func isConfigMapOlder(newConfigMap, oldConfigMap *v1.ConfigMap) bool { - if newConfigMap == nil || oldConfigMap == nil { - return false - } - newVersion, _ := storageetcd.Versioner.ObjectResourceVersion(newConfigMap) - oldVersion, _ := storageetcd.Versioner.ObjectResourceVersion(oldConfigMap) - return newVersion < oldVersion +// configMapManager keeps a cache of all configmaps necessary +// for registered pods. Different implementation of the store +// may result in different semantics for freshness of configmaps +// (e.g. ttl-based implementation vs watch-based implementation). +type configMapManager struct { + manager manager.Manager } -func (s *configMapStore) Add(namespace, name string) { - key := objectKey{namespace: namespace, name: name} - - // Add is called from RegisterPod, thus it needs to be efficient. - // Thus Add() is only increasing refCount and generation of a given configmap. - // Then Get() is responsible for fetching if needed. - s.lock.Lock() - defer s.lock.Unlock() - item, exists := s.items[key] - if !exists { - item = &configMapStoreItem{ - refCount: 0, - configMap: &configMapData{}, - } - s.items[key] = item +func (c *configMapManager) GetConfigMap(namespace, name string) (*v1.ConfigMap, error) { + object, err := c.manager.GetObject(namespace, name) + if err != nil { + return nil, err } - - item.refCount++ - // This will trigger fetch on the next Get() operation. - item.configMap = nil -} - -func (s *configMapStore) Delete(namespace, name string) { - key := objectKey{namespace: namespace, name: name} - - s.lock.Lock() - defer s.lock.Unlock() - if item, ok := s.items[key]; ok { - item.refCount-- - if item.refCount == 0 { - delete(s.items, key) - } + if configmap, ok := object.(*v1.ConfigMap); ok { + return configmap, nil } + return nil, fmt.Errorf("unexpected object type: %v", object) } -func GetObjectTTLFromNodeFunc(getNode func() (*v1.Node, error)) GetObjectTTLFunc { - return func() (time.Duration, bool) { - node, err := getNode() - if err != nil { - return time.Duration(0), false - } - if node != nil && node.Annotations != nil { - if value, ok := node.Annotations[v1.ObjectTTLAnnotationKey]; ok { - if intValue, err := strconv.Atoi(value); err == nil { - return time.Duration(intValue) * time.Second, true - } - } - } - return time.Duration(0), false - } +func (c *configMapManager) RegisterPod(pod *v1.Pod) { + c.manager.RegisterPod(pod) } -func (s *configMapStore) isConfigMapFresh(data *configMapData) bool { - configMapTTL := s.defaultTTL - if ttl, ok := s.getTTL(); ok { - configMapTTL = ttl - } - return s.clock.Now().Before(data.lastUpdateTime.Add(configMapTTL)) -} - -func (s *configMapStore) Get(namespace, name string) (*v1.ConfigMap, error) { - key := objectKey{namespace: namespace, name: name} - - data := func() *configMapData { - s.lock.Lock() - defer s.lock.Unlock() - item, exists := s.items[key] - if !exists { - return nil - } - if item.configMap == nil { - item.configMap = &configMapData{} - } - return item.configMap - }() - if data == nil { - return nil, fmt.Errorf("configmap %q/%q not registered", namespace, name) - } - - // After updating data in configMapStore, lock the data, fetch configMap if - // needed and return data. - data.Lock() - defer data.Unlock() - if data.err != nil || !s.isConfigMapFresh(data) { - opts := metav1.GetOptions{} - if data.configMap != nil && data.err == nil { - // This is just a periodic refresh of a configmap we successfully fetched previously. - // In this case, server data from apiserver cache to reduce the load on both - // etcd and apiserver (the cache is eventually consistent). - util.FromApiserverCache(&opts) - } - configMap, err := s.kubeClient.CoreV1().ConfigMaps(namespace).Get(name, opts) - if err != nil && !apierrors.IsNotFound(err) && data.configMap == nil && data.err == nil { - // Couldn't fetch the latest configmap, but there is no cached data to return. - // Return the fetch result instead. - return configMap, err - } - if (err == nil && !isConfigMapOlder(configMap, data.configMap)) || apierrors.IsNotFound(err) { - // If the fetch succeeded with a newer version of the configmap, or if the - // configmap could not be found in the apiserver, update the cached data to - // reflect the current status. - data.configMap = configMap - data.err = err - data.lastUpdateTime = s.clock.Now() - } - } - return data.configMap, data.err -} - -// cachingConfigMapManager keeps a cache of all configmaps necessary for registered pods. -// It implements the following logic: -// - whenever a pod is created or updated, the cached versions of all its configmaps -// are invalidated -// - every GetConfigMap() call tries to fetch the value from local cache; if it is -// not there, invalidated or too old, we fetch it from apiserver and refresh the -// value in cache; otherwise it is just fetched from cache -type cachingConfigMapManager struct { - configMapStore *configMapStore - - lock sync.Mutex - registeredPods map[objectKey]*v1.Pod -} - -func NewCachingConfigMapManager(kubeClient clientset.Interface, getTTL GetObjectTTLFunc) Manager { - csm := &cachingConfigMapManager{ - configMapStore: newConfigMapStore(kubeClient, clock.RealClock{}, getTTL, defaultTTL), - registeredPods: make(map[objectKey]*v1.Pod), - } - return csm -} - -func (c *cachingConfigMapManager) GetConfigMap(namespace, name string) (*v1.ConfigMap, error) { - return c.configMapStore.Get(namespace, name) +func (c *configMapManager) UnregisterPod(pod *v1.Pod) { + c.manager.UnregisterPod(pod) } func getConfigMapNames(pod *v1.Pod) sets.String { @@ -269,39 +102,24 @@ func getConfigMapNames(pod *v1.Pod) sets.String { return result } -func (c *cachingConfigMapManager) RegisterPod(pod *v1.Pod) { - names := getConfigMapNames(pod) - c.lock.Lock() - defer c.lock.Unlock() - for name := range names { - c.configMapStore.Add(pod.Namespace, name) - } - var prev *v1.Pod - key := objectKey{namespace: pod.Namespace, name: pod.Name} - prev = c.registeredPods[key] - c.registeredPods[key] = pod - if prev != nil { - for name := range getConfigMapNames(prev) { - // On an update, the .Add() call above will have re-incremented the - // ref count of any existing items, so any configmaps that are in both - // names and prev need to have their ref counts decremented. Any that - // are only in prev need to be completely removed. This unconditional - // call takes care of both cases. - c.configMapStore.Delete(prev.Namespace, name) - } - } -} +const ( + defaultTTL = time.Minute +) -func (c *cachingConfigMapManager) UnregisterPod(pod *v1.Pod) { - var prev *v1.Pod - key := objectKey{namespace: pod.Namespace, name: pod.Name} - c.lock.Lock() - defer c.lock.Unlock() - prev = c.registeredPods[key] - delete(c.registeredPods, key) - if prev != nil { - for name := range getConfigMapNames(prev) { - c.configMapStore.Delete(prev.Namespace, name) - } +// NewCachingConfigMapManager creates a manager that keeps a cache of all configmaps +// necessary for registered pods. +// It implement the following logic: +// - whenever a pod is create or updated, the cached versions of all configmaps +// are invalidated +// - every GetObject() call tries to fetch the value from local cache; if it is +// not there, invalidated or too old, we fetch it from apiserver and refresh the +// value in cache; otherwise it is just fetched from cache +func NewCachingConfigMapManager(kubeClient clientset.Interface, getTTL manager.GetObjectTTLFunc) Manager { + getConfigMap := func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { + return kubeClient.CoreV1().ConfigMaps(namespace).Get(name, opts) + } + configMapStore := manager.NewObjectStore(getConfigMap, clock.RealClock{}, getTTL, defaultTTL) + return &configMapManager{ + manager: manager.NewCacheBasedManager(configMapStore, getConfigMapNames), } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager_test.go index d79a80b50..2b8433c0e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager_test.go @@ -18,30 +18,27 @@ package configmap import ( "fmt" - "reflect" "strings" - "sync" "testing" "time" "k8s.io/api/core/v1" - "k8s.io/client-go/kubernetes/fake" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/clock" - core "k8s.io/client-go/testing" - "github.com/stretchr/testify/assert" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/pkg/kubelet/util/manager" ) -func checkConfigMap(t *testing.T, store *configMapStore, ns, name string, shouldExist bool) { +func checkObject(t *testing.T, store manager.Store, ns, name string, shouldExist bool) { _, err := store.Get(ns, name) if shouldExist && err != nil { t.Errorf("unexpected actions: %#v", err) } - if !shouldExist && (err == nil || !strings.Contains(err.Error(), fmt.Sprintf("configmap %q/%q not registered", ns, name))) { + if !shouldExist && (err == nil || !strings.Contains(err.Error(), fmt.Sprintf("object %q/%q not registered", ns, name))) { t.Errorf("unexpected actions: %#v", err) } } @@ -50,242 +47,9 @@ func noObjectTTL() (time.Duration, bool) { return time.Duration(0), false } -func TestConfigMapStore(t *testing.T) { - fakeClient := &fake.Clientset{} - store := newConfigMapStore(fakeClient, clock.RealClock{}, noObjectTTL, 0) - store.Add("ns1", "name1") - store.Add("ns2", "name2") - store.Add("ns1", "name1") - store.Add("ns1", "name1") - store.Delete("ns1", "name1") - store.Delete("ns2", "name2") - store.Add("ns3", "name3") - - // Adds don't issue Get requests. - actions := fakeClient.Actions() - assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) - // Should issue Get request - store.Get("ns1", "name1") - // Shouldn't issue Get request, as configMap is not registered - store.Get("ns2", "name2") - // Should issue Get request - store.Get("ns3", "name3") - - actions = fakeClient.Actions() - assert.Equal(t, 2, len(actions), "unexpected actions: %#v", actions) - - for _, a := range actions { - assert.True(t, a.Matches("get", "configmaps"), "unexpected actions: %#v", a) - } - - checkConfigMap(t, store, "ns1", "name1", true) - checkConfigMap(t, store, "ns2", "name2", false) - checkConfigMap(t, store, "ns3", "name3", true) - checkConfigMap(t, store, "ns4", "name4", false) -} - -func TestConfigMapStoreDeletingConfigMap(t *testing.T) { - fakeClient := &fake.Clientset{} - store := newConfigMapStore(fakeClient, clock.RealClock{}, noObjectTTL, 0) - store.Add("ns", "name") - - result := &v1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "name", ResourceVersion: "10"}} - fakeClient.AddReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) { - return true, result, nil - }) - configMap, err := store.Get("ns", "name") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if !reflect.DeepEqual(configMap, result) { - t.Errorf("Unexpected configMap: %v", configMap) - } - - fakeClient.PrependReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) { - return true, &v1.ConfigMap{}, apierrors.NewNotFound(v1.Resource("configMap"), "name") - }) - configMap, err = store.Get("ns", "name") - if err == nil || !apierrors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } - if !reflect.DeepEqual(configMap, &v1.ConfigMap{}) { - t.Errorf("Unexpected configMap: %v", configMap) - } -} - -func TestConfigMapStoreGetAlwaysRefresh(t *testing.T) { - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Now()) - store := newConfigMapStore(fakeClient, fakeClock, noObjectTTL, 0) - - for i := 0; i < 10; i++ { - store.Add(fmt.Sprintf("ns-%d", i), fmt.Sprintf("name-%d", i)) - } - fakeClient.ClearActions() - - wg := sync.WaitGroup{} - wg.Add(100) - for i := 0; i < 100; i++ { - go func(i int) { - store.Get(fmt.Sprintf("ns-%d", i%10), fmt.Sprintf("name-%d", i%10)) - wg.Done() - }(i) - } - wg.Wait() - actions := fakeClient.Actions() - assert.Equal(t, 100, len(actions), "unexpected actions: %#v", actions) - - for _, a := range actions { - assert.True(t, a.Matches("get", "configmaps"), "unexpected actions: %#v", a) - } -} - -func TestConfigMapStoreGetNeverRefresh(t *testing.T) { - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Now()) - store := newConfigMapStore(fakeClient, fakeClock, noObjectTTL, time.Minute) - - for i := 0; i < 10; i++ { - store.Add(fmt.Sprintf("ns-%d", i), fmt.Sprintf("name-%d", i)) - } - fakeClient.ClearActions() - - wg := sync.WaitGroup{} - wg.Add(100) - for i := 0; i < 100; i++ { - go func(i int) { - store.Get(fmt.Sprintf("ns-%d", i%10), fmt.Sprintf("name-%d", i%10)) - wg.Done() - }(i) - } - wg.Wait() - actions := fakeClient.Actions() - // Only first Get, should forward the Get request. - assert.Equal(t, 10, len(actions), "unexpected actions: %#v", actions) -} - -func TestCustomTTL(t *testing.T) { - ttl := time.Duration(0) - ttlExists := false - customTTL := func() (time.Duration, bool) { - return ttl, ttlExists - } - - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Time{}) - store := newConfigMapStore(fakeClient, fakeClock, customTTL, time.Minute) - - store.Add("ns", "name") - store.Get("ns", "name") - fakeClient.ClearActions() - - // Set 0-ttl and see if that works. - ttl = time.Duration(0) - ttlExists = true - store.Get("ns", "name") - actions := fakeClient.Actions() - assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() - - // Set 5-minute ttl and see if this works. - ttl = time.Duration(5) * time.Minute - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) - // Still no effect after 4 minutes. - fakeClock.Step(4 * time.Minute) - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) - // Now it should have an effect. - fakeClock.Step(time.Minute) - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() - - // Now remove the custom ttl and see if that works. - ttlExists = false - fakeClock.Step(55 * time.Second) - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) - // Pass the minute and it should be triggered now. - fakeClock.Step(5 * time.Second) - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions) -} - -func TestParseNodeAnnotation(t *testing.T) { - testCases := []struct { - node *v1.Node - err error - exists bool - ttl time.Duration - }{ - { - node: nil, - err: fmt.Errorf("error"), - exists: false, - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - }, - }, - exists: false, - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - Annotations: map[string]string{}, - }, - }, - exists: false, - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "bad"}, - }, - }, - exists: false, - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "0"}, - }, - }, - exists: true, - ttl: time.Duration(0), - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "60"}, - }, - }, - exists: true, - ttl: time.Minute, - }, - } - for i, testCase := range testCases { - getNode := func() (*v1.Node, error) { return testCase.node, testCase.err } - ttl, exists := GetObjectTTLFromNodeFunc(getNode)() - if exists != testCase.exists { - t.Errorf("%d: incorrect parsing: %t", i, exists) - continue - } - if exists && ttl != testCase.ttl { - t.Errorf("%d: incorrect ttl: %v", i, ttl) - } +func getConfigMap(fakeClient clientset.Interface) manager.GetObjectFunc { + return func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { + return fakeClient.CoreV1().ConfigMaps(namespace).Get(name, opts) } } @@ -348,152 +112,11 @@ func podWithConfigMaps(ns, podName string, toAttach configMapsToAttach) *v1.Pod return pod } -func TestCacheInvalidation(t *testing.T) { - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Now()) - store := newConfigMapStore(fakeClient, fakeClock, noObjectTTL, time.Minute) - manager := &cachingConfigMapManager{ - configMapStore: store, - registeredPods: make(map[objectKey]*v1.Pod), - } - - // Create a pod with some configMaps. - s1 := configMapsToAttach{ - containerEnvConfigMaps: []envConfigMaps{ - {envVarNames: []string{"s1"}, envFromNames: []string{"s10"}}, - {envVarNames: []string{"s2"}}, - }, - } - manager.RegisterPod(podWithConfigMaps("ns1", "name1", s1)) - // Fetch both configMaps - this should triggger get operations. - store.Get("ns1", "s1") - store.Get("ns1", "s10") - store.Get("ns1", "s2") - actions := fakeClient.Actions() - assert.Equal(t, 3, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() - - // Update a pod with a new configMap. - s2 := configMapsToAttach{ - containerEnvConfigMaps: []envConfigMaps{ - {envVarNames: []string{"s1"}}, - {envVarNames: []string{"s2"}, envFromNames: []string{"s20"}}, - }, - volumes: []string{"s3"}, - } - manager.RegisterPod(podWithConfigMaps("ns1", "name1", s2)) - // All configMaps should be invalidated - this should trigger get operations. - store.Get("ns1", "s1") - store.Get("ns1", "s2") - store.Get("ns1", "s20") - store.Get("ns1", "s3") - actions = fakeClient.Actions() - assert.Equal(t, 4, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() - - // Create a new pod that is refencing the first three configMaps - those should - // be invalidated. - manager.RegisterPod(podWithConfigMaps("ns1", "name2", s1)) - store.Get("ns1", "s1") - store.Get("ns1", "s10") - store.Get("ns1", "s2") - store.Get("ns1", "s20") - store.Get("ns1", "s3") - actions = fakeClient.Actions() - assert.Equal(t, 3, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() -} - -func TestCacheRefcounts(t *testing.T) { - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Now()) - store := newConfigMapStore(fakeClient, fakeClock, noObjectTTL, time.Minute) - manager := &cachingConfigMapManager{ - configMapStore: store, - registeredPods: make(map[objectKey]*v1.Pod), - } - - s1 := configMapsToAttach{ - containerEnvConfigMaps: []envConfigMaps{ - {envVarNames: []string{"s1"}, envFromNames: []string{"s10"}}, - {envVarNames: []string{"s2"}}, - }, - volumes: []string{"s3"}, - } - manager.RegisterPod(podWithConfigMaps("ns1", "name1", s1)) - manager.RegisterPod(podWithConfigMaps("ns1", "name2", s1)) - s2 := configMapsToAttach{ - containerEnvConfigMaps: []envConfigMaps{ - {envVarNames: []string{"s4"}}, - {envVarNames: []string{"s5"}, envFromNames: []string{"s50"}}, - }, - } - manager.RegisterPod(podWithConfigMaps("ns1", "name2", s2)) - manager.RegisterPod(podWithConfigMaps("ns1", "name3", s2)) - manager.RegisterPod(podWithConfigMaps("ns1", "name4", s2)) - manager.UnregisterPod(podWithConfigMaps("ns1", "name3", s2)) - s3 := configMapsToAttach{ - containerEnvConfigMaps: []envConfigMaps{ - {envVarNames: []string{"s3"}, envFromNames: []string{"s30"}}, - {envVarNames: []string{"s5"}}, - }, - } - manager.RegisterPod(podWithConfigMaps("ns1", "name5", s3)) - manager.RegisterPod(podWithConfigMaps("ns1", "name6", s3)) - s4 := configMapsToAttach{ - containerEnvConfigMaps: []envConfigMaps{ - {envVarNames: []string{"s6"}}, - {envFromNames: []string{"s60"}}, - }, - } - manager.RegisterPod(podWithConfigMaps("ns1", "name7", s4)) - manager.UnregisterPod(podWithConfigMaps("ns1", "name7", s4)) - - // Also check the Add + Update + Remove scenario. - manager.RegisterPod(podWithConfigMaps("ns1", "other-name", s1)) - manager.RegisterPod(podWithConfigMaps("ns1", "other-name", s2)) - manager.UnregisterPod(podWithConfigMaps("ns1", "other-name", s2)) - - s5 := configMapsToAttach{ - containerEnvConfigMaps: []envConfigMaps{ - {envVarNames: []string{"s7"}}, - {envFromNames: []string{"s70"}}, - }, - } - - // Check the no-op update scenario - manager.RegisterPod(podWithConfigMaps("ns1", "noop-pod", s5)) - manager.RegisterPod(podWithConfigMaps("ns1", "noop-pod", s5)) - - refs := func(ns, name string) int { - store.lock.Lock() - defer store.lock.Unlock() - item, ok := store.items[objectKey{ns, name}] - if !ok { - return 0 - } - return item.refCount - } - assert.Equal(t, 1, refs("ns1", "s1")) - assert.Equal(t, 1, refs("ns1", "s10")) - assert.Equal(t, 1, refs("ns1", "s2")) - assert.Equal(t, 3, refs("ns1", "s3")) - assert.Equal(t, 2, refs("ns1", "s30")) - assert.Equal(t, 2, refs("ns1", "s4")) - assert.Equal(t, 4, refs("ns1", "s5")) - assert.Equal(t, 2, refs("ns1", "s50")) - assert.Equal(t, 0, refs("ns1", "s6")) - assert.Equal(t, 0, refs("ns1", "s60")) - assert.Equal(t, 1, refs("ns1", "s7")) - assert.Equal(t, 1, refs("ns1", "s70")) -} - -func TestCachingConfigMapManager(t *testing.T) { +func TestCacheBasedConfigMapManager(t *testing.T) { fakeClient := &fake.Clientset{} - configMapStore := newConfigMapStore(fakeClient, clock.RealClock{}, noObjectTTL, 0) - manager := &cachingConfigMapManager{ - configMapStore: configMapStore, - registeredPods: make(map[objectKey]*v1.Pod), + store := manager.NewObjectStore(getConfigMap(fakeClient), clock.RealClock{}, noObjectTTL, 0) + manager := &configMapManager{ + manager: manager.NewCacheBasedManager(store, getConfigMapNames), } // Create a pod with some configMaps. @@ -543,7 +166,7 @@ func TestCachingConfigMapManager(t *testing.T) { for _, ns := range []string{"ns1", "ns2", "ns3"} { for _, configMap := range []string{"s1", "s2", "s3", "s4", "s5", "s6", "s20", "s40", "s50"} { - checkConfigMap(t, configMapStore, ns, configMap, shouldExist(ns, configMap)) + checkObject(t, store, ns, configMap, shouldExist(ns, configMap)) } } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/container/BUILD index 1ea5866b0..287cd5013 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/container/BUILD @@ -14,49 +14,13 @@ go_library( "runtime_cache.go", "runtime_cache_fake.go", "sync_result.go", - ] + select({ - "@io_bazel_rules_go//go/platform:android": [ - "pty_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:darwin": [ - "pty_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:dragonfly": [ - "pty_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:freebsd": [ - "pty_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:linux": [ - "pty_linux.go", - ], - "@io_bazel_rules_go//go/platform:nacl": [ - "pty_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:netbsd": [ - "pty_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:openbsd": [ - "pty_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:plan9": [ - "pty_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:solaris": [ - "pty_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:windows": [ - "pty_unsupported.go", - ], - "//conditions:default": [], - }), + ], importpath = "k8s.io/kubernetes/pkg/kubelet/container", visibility = ["//visibility:public"], deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/util/format:go_default_library", - "//pkg/kubelet/util/ioutils:go_default_library", "//pkg/util/hash:go_default_library", "//pkg/volume:go_default_library", "//third_party/forked/golang/expansion:go_default_library", @@ -71,12 +35,7 @@ go_library( "//vendor/k8s.io/client-go/tools/reference:go_default_library", "//vendor/k8s.io/client-go/tools/remotecommand:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", - ] + select({ - "@io_bazel_rules_go//go/platform:linux": [ - "//vendor/github.com/kr/pty:go_default_library", - ], - "//conditions:default": [], - }), + ], ) go_test( @@ -89,7 +48,6 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core/install:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go b/vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go index 529c6dfe4..01fe7129d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go @@ -17,12 +17,9 @@ limitations under the License. package container import ( - "bytes" "fmt" - "hash/adler32" "hash/fnv" "strings" - "time" "github.com/golang/glog" @@ -33,7 +30,6 @@ import ( "k8s.io/client-go/tools/record" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" "k8s.io/kubernetes/pkg/kubelet/util/format" - "k8s.io/kubernetes/pkg/kubelet/util/ioutils" hashutil "k8s.io/kubernetes/pkg/util/hash" "k8s.io/kubernetes/third_party/forked/golang/expansion" ) @@ -100,17 +96,6 @@ func HashContainer(container *v1.Container) uint64 { return uint64(hash.Sum32()) } -// HashContainerLegacy returns the hash of the container. It is used to compare -// the running container with its desired spec. -// This is used by rktnetes and dockershim (for handling <=1.5 containers). -// TODO: Remove this function when kubernetes version is >=1.8 AND rktnetes -// update its hash function. -func HashContainerLegacy(container *v1.Container) uint64 { - hash := adler32.New() - hashutil.DeepHashObject(hash, *container) - return uint64(hash.Sum32()) -} - // EnvVarsToMap constructs a map of environment name to value from a slice // of env vars. func EnvVarsToMap(envs []EnvVar) map[string]string { @@ -145,6 +130,11 @@ func ExpandContainerCommandOnlyStatic(containerCommand []string, envs []v1.EnvVa return command } +func ExpandContainerVolumeMounts(mount v1.VolumeMount, envs []EnvVar) (expandedSubpath string) { + mapping := expansion.MappingFuncFor(EnvVarsToMap(envs)) + return expansion.Expand(mount.SubPath, mapping) +} + func ExpandContainerCommandAndArgs(container *v1.Container, envs []EnvVar) (command []string, args []string) { mapping := expansion.MappingFuncFor(EnvVarsToMap(envs)) @@ -205,6 +195,13 @@ func (irecorder *innerEventRecorder) PastEventf(object runtime.Object, timestamp } } +func (irecorder *innerEventRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + if ref, ok := irecorder.shouldRecordEvent(object); ok { + irecorder.recorder.AnnotatedEventf(ref, annotations, eventtype, reason, messageFmt, args...) + } + +} + // Pod must not be nil. func IsHostNetworkPod(pod *v1.Pod) bool { return pod.Spec.HostNetwork @@ -265,26 +262,6 @@ func FormatPod(pod *Pod) string { return fmt.Sprintf("%s_%s(%s)", pod.Name, pod.Namespace, pod.ID) } -type containerCommandRunnerWrapper struct { - DirectStreamingRuntime -} - -var _ ContainerCommandRunner = &containerCommandRunnerWrapper{} - -func DirectStreamingRunner(runtime DirectStreamingRuntime) ContainerCommandRunner { - return &containerCommandRunnerWrapper{runtime} -} - -func (r *containerCommandRunnerWrapper) RunInContainer(id ContainerID, cmd []string, timeout time.Duration) ([]byte, error) { - var buffer bytes.Buffer - output := ioutils.WriteCloserWrapper(&buffer) - err := r.ExecInContainer(id, cmd, nil, output, output, false, nil, timeout) - // Even if err is non-nil, there still may be output (e.g. the exec wrote to stdout or stderr but - // the command returned a nonzero exit code). Therefore, always return the output along with the - // error. - return buffer.Bytes(), err -} - // GetContainerSpec gets the container spec by containerName. func GetContainerSpec(pod *v1.Pod, containerName string) *v1.Container { for i, c := range pod.Spec.Containers { @@ -312,21 +289,6 @@ func HasPrivilegedContainer(pod *v1.Pod) bool { return false } -// MakeCapabilities creates string slices from Capability slices -func MakeCapabilities(capAdd []v1.Capability, capDrop []v1.Capability) ([]string, []string) { - var ( - addCaps []string - dropCaps []string - ) - for _, cap := range capAdd { - addCaps = append(addCaps, string(cap)) - } - for _, cap := range capDrop { - dropCaps = append(dropCaps, string(cap)) - } - return addCaps, dropCaps -} - // MakePortMappings creates internal port mapping from api port mapping. func MakePortMappings(container *v1.Container) (ports []PortMapping) { names := make(map[string]struct{}) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers_test.go index 14d9d6e6c..d6c2792c6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers_test.go @@ -138,6 +138,114 @@ func TestExpandCommandAndArgs(t *testing.T) { } } +func TestExpandVolumeMountsWithSubpath(t *testing.T) { + cases := []struct { + name string + container *v1.Container + envs []EnvVar + expectedSubPath string + expectedMountPath string + }{ + { + name: "subpath with no expansion", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: "foo"}}, + }, + expectedSubPath: "foo", + expectedMountPath: "", + }, + { + name: "volumes with expanded subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: "foo/$(POD_NAME)"}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "bar", + }, + }, + expectedSubPath: "foo/bar", + expectedMountPath: "", + }, + { + name: "volumes expanded with empty subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: ""}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "bar", + }, + }, + expectedSubPath: "", + expectedMountPath: "", + }, + { + name: "volumes expanded with no envs subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: "/foo/$(POD_NAME)"}}, + }, + expectedSubPath: "/foo/$(POD_NAME)", + expectedMountPath: "", + }, + { + name: "volumes expanded with leading environment variable", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{SubPath: "$(POD_NAME)/bar"}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "foo", + }, + }, + expectedSubPath: "foo/bar", + expectedMountPath: "", + }, + { + name: "volumes with volume and subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{MountPath: "/foo", SubPath: "$(POD_NAME)/bar"}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "foo", + }, + }, + expectedSubPath: "foo/bar", + expectedMountPath: "/foo", + }, + { + name: "volumes with volume and no subpath", + container: &v1.Container{ + VolumeMounts: []v1.VolumeMount{{MountPath: "/foo"}}, + }, + envs: []EnvVar{ + { + Name: "POD_NAME", + Value: "foo", + }, + }, + expectedSubPath: "", + expectedMountPath: "/foo", + }, + } + + for _, tc := range cases { + actualSubPath := ExpandContainerVolumeMounts(tc.container.VolumeMounts[0], tc.envs) + if e, a := tc.expectedSubPath, actualSubPath; !reflect.DeepEqual(e, a) { + t.Errorf("%v: unexpected subpath; expected %v, got %v", tc.name, e, a) + } + if e, a := tc.expectedMountPath, tc.container.VolumeMounts[0].MountPath; !reflect.DeepEqual(e, a) { + t.Errorf("%v: unexpected mountpath; expected %v, got %v", tc.name, e, a) + } + } + +} + func TestShouldContainerBeRestarted(t *testing.T) { pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/os.go b/vendor/k8s.io/kubernetes/pkg/kubelet/container/os.go index 6126063b3..bd27ae9f0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/os.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/container/os.go @@ -43,7 +43,7 @@ type OSInterface interface { // RealOS is used to dispatch the real system level operations. type RealOS struct{} -// MkDir will will call os.Mkdir to create a directory. +// MkdirAll will call os.MkdirAll to create a directory. func (RealOS) MkdirAll(path string, perm os.FileMode) error { return os.MkdirAll(path, perm) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_linux.go deleted file mode 100644 index 40906ce99..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_linux.go +++ /dev/null @@ -1,30 +0,0 @@ -// +build linux - -/* -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 container - -import ( - "os" - "os/exec" - - "github.com/kr/pty" -) - -func StartPty(c *exec.Cmd) (*os.File, error) { - return pty.Start(c) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_unsupported.go b/vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_unsupported.go deleted file mode 100644 index 24ea2f787..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_unsupported.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build !linux - -/* -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 container - -import ( - "os" - "os/exec" -) - -func StartPty(c *exec.Cmd) (pty *os.File, err error) { - return nil, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/ref_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/container/ref_test.go index 705f202fd..716b259ef 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/ref_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/container/ref_test.go @@ -21,7 +21,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/api/legacyscheme" _ "k8s.io/kubernetes/pkg/apis/core/install" ) @@ -68,14 +67,14 @@ func TestGenerateContainerRef(t *testing.T) { okPod = v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: "ok", Namespace: "test-ns", UID: "bar", ResourceVersion: "42", - SelfLink: "/api/" + legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String() + "/pods/foo", + SelfLink: "/api/v1/pods/foo", }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -92,7 +91,7 @@ func TestGenerateContainerRef(t *testing.T) { noSelfLinkPod.Kind = "" noSelfLinkPod.APIVersion = "" noSelfLinkPod.ObjectMeta.SelfLink = "" - defaultedSelfLinkPod.ObjectMeta.SelfLink = "/api/" + legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String() + "/pods/ok" + defaultedSelfLinkPod.ObjectMeta.SelfLink = "/api/v1/pods/ok" cases := []struct { name string @@ -109,7 +108,7 @@ func TestGenerateContainerRef(t *testing.T) { }, expected: &v1.ObjectReference{ Kind: "Pod", - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", Name: "ok", Namespace: "test-ns", UID: "bar", @@ -124,7 +123,7 @@ func TestGenerateContainerRef(t *testing.T) { container: &v1.Container{}, expected: &v1.ObjectReference{ Kind: "Pod", - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", Name: "ok", Namespace: "test-ns", UID: "bar", @@ -148,7 +147,7 @@ func TestGenerateContainerRef(t *testing.T) { }, expected: &v1.ObjectReference{ Kind: "Pod", - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", Name: "ok", Namespace: "test-ns", UID: "bar", @@ -165,7 +164,7 @@ func TestGenerateContainerRef(t *testing.T) { }, expected: &v1.ObjectReference{ Kind: "Pod", - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", Name: "ok", Namespace: "test-ns", UID: "bar", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/resize.go b/vendor/k8s.io/kubernetes/pkg/kubelet/container/resize.go index d7b75eede..34e40a95b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/resize.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/container/resize.go @@ -32,11 +32,7 @@ func HandleResizing(resize <-chan remotecommand.TerminalSize, resizeFunc func(si go func() { defer runtime.HandleCrash() - for { - size, ok := <-resize - if !ok { - return - } + for size := range resize { if size.Height < 1 || size.Width < 1 { continue } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go b/vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go index bf2af9862..70b72024c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go @@ -95,7 +95,7 @@ type Runtime interface { // it is useful when doing SIGKILL for hard eviction scenarios, or max grace period during soft eviction scenarios. KillPod(pod *v1.Pod, runningPod Pod, gracePeriodOverride *int64) error // GetPodStatus retrieves the status of the pod, including the - // information of all containers in the pod that are visble in Runtime. + // information of all containers in the pod that are visible in Runtime. GetPodStatus(uid types.UID, name, namespace string) (*PodStatus, error) // Returns the filesystem path of the pod's network namespace; if the // runtime does not handle namespace creation itself, or cannot return @@ -124,22 +124,10 @@ type Runtime interface { UpdatePodCIDR(podCIDR string) error } -// 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. - 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 - // ContainerAttach encapsulates the attaching to containers for testability - ContainerAttacher -} - -// IndirectStreamingRuntime is the interface implemented by runtimes that handle the serving of the +// StreamingRuntime is the interface implemented by runtimes that handle the serving of the // streaming calls (exec/attach/port-forward) themselves. In this case, Kubelet should redirect to // the runtime server. -type IndirectStreamingRuntime interface { +type StreamingRuntime interface { GetExec(id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) GetAttach(id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) @@ -198,7 +186,7 @@ type PodPair struct { // ContainerID is a type that identifies a container. type ContainerID struct { - // The type of the container runtime. e.g. 'docker', 'rkt'. + // The type of the container runtime. e.g. 'docker'. Type string // The identification of the container, this is comsumable by // the underlying container runtime. (Note that the container @@ -444,8 +432,6 @@ type RunContainerOptions struct { // this directory will be used to create and mount the log file to // container.TerminationMessagePath PodContainerDir string - // The parent cgroup to pass to Docker - CgroupParent string // The type of container rootfs ReadOnly bool // hostname for pod containers diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_runtime.go b/vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_runtime.go index 3019d3009..707ee1ac4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_runtime.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_runtime.go @@ -26,7 +26,6 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/tools/remotecommand" "k8s.io/client-go/util/flowcontrol" . "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/volume" @@ -59,34 +58,13 @@ type FakeRuntime struct { StatusErr error } -type FakeDirectStreamingRuntime struct { - *FakeRuntime - - // Arguments to streaming method calls. - Args struct { - // Attach / Exec args - ContainerID ContainerID - Cmd []string - Stdin io.Reader - Stdout io.WriteCloser - Stderr io.WriteCloser - TTY bool - // Port-forward args - Pod *Pod - Port int32 - Stream io.ReadWriteCloser - } -} - -var _ DirectStreamingRuntime = &FakeDirectStreamingRuntime{} - const FakeHost = "localhost:12345" -type FakeIndirectStreamingRuntime struct { +type FakeStreamingRuntime struct { *FakeRuntime } -var _ IndirectStreamingRuntime = &FakeIndirectStreamingRuntime{} +var _ StreamingRuntime = &FakeStreamingRuntime{} // FakeRuntime should implement Runtime. var _ Runtime = &FakeRuntime{} @@ -311,35 +289,6 @@ func (f *FakeRuntime) GetPodStatus(uid types.UID, name, namespace string) (*PodS return &status, f.Err } -func (f *FakeDirectStreamingRuntime) ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - f.Lock() - defer f.Unlock() - - f.CalledFunctions = append(f.CalledFunctions, "ExecInContainer") - f.Args.ContainerID = containerID - f.Args.Cmd = cmd - f.Args.Stdin = stdin - f.Args.Stdout = stdout - f.Args.Stderr = stderr - f.Args.TTY = tty - - return f.Err -} - -func (f *FakeDirectStreamingRuntime) AttachContainer(containerID ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - f.Lock() - defer f.Unlock() - - f.CalledFunctions = append(f.CalledFunctions, "AttachContainer") - f.Args.ContainerID = containerID - f.Args.Stdin = stdin - f.Args.Stdout = stdout - f.Args.Stderr = stderr - f.Args.TTY = tty - - return f.Err -} - func (f *FakeRuntime) GetContainerLogs(pod *v1.Pod, containerID ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error) { f.Lock() defer f.Unlock() @@ -394,18 +343,6 @@ func (f *FakeRuntime) RemoveImage(image ImageSpec) error { return f.Err } -func (f *FakeDirectStreamingRuntime) PortForward(pod *Pod, port int32, stream io.ReadWriteCloser) error { - f.Lock() - defer f.Unlock() - - f.CalledFunctions = append(f.CalledFunctions, "PortForward") - f.Args.Pod = pod - f.Args.Port = port - f.Args.Stream = stream - - return f.Err -} - func (f *FakeRuntime) GetNetNS(containerID ContainerID) (string, error) { f.Lock() defer f.Unlock() @@ -455,7 +392,7 @@ func (f *FakeRuntime) ImageStats() (*ImageStats, error) { return nil, f.Err } -func (f *FakeIndirectStreamingRuntime) GetExec(id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) { +func (f *FakeStreamingRuntime) GetExec(id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) { f.Lock() defer f.Unlock() @@ -463,7 +400,7 @@ func (f *FakeIndirectStreamingRuntime) GetExec(id ContainerID, cmd []string, std return &url.URL{Host: FakeHost}, f.Err } -func (f *FakeIndirectStreamingRuntime) GetAttach(id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) { +func (f *FakeStreamingRuntime) GetAttach(id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) { f.Lock() defer f.Unlock() @@ -471,7 +408,7 @@ func (f *FakeIndirectStreamingRuntime) GetAttach(id ContainerID, stdin, stdout, return &url.URL{Host: FakeHost}, f.Err } -func (f *FakeIndirectStreamingRuntime) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) { +func (f *FakeStreamingRuntime) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) { f.Lock() defer f.Unlock() diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/BUILD index 2429b5263..7ea91d854 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/BUILD @@ -82,26 +82,25 @@ go_library( "//pkg/credentialprovider:go_default_library", "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/cm:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", + "//pkg/kubelet/checkpointmanager/checksum:go_default_library", + "//pkg/kubelet/checkpointmanager/errors:go_default_library", "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/dockershim/cm:go_default_library", "//pkg/kubelet/dockershim/libdocker:go_default_library", "//pkg/kubelet/dockershim/metrics:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + "//pkg/kubelet/dockershim/network/cni:go_default_library", + "//pkg/kubelet/dockershim/network/hostport:go_default_library", + "//pkg/kubelet/dockershim/network/kubenet:go_default_library", "//pkg/kubelet/kuberuntime:go_default_library", "//pkg/kubelet/leaky:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/cni:go_default_library", - "//pkg/kubelet/network/hostport:go_default_library", - "//pkg/kubelet/network/kubenet:go_default_library", "//pkg/kubelet/qos:go_default_library", "//pkg/kubelet/server/streaming:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/cache:go_default_library", "//pkg/kubelet/util/ioutils:go_default_library", - "//pkg/kubelet/util/store:go_default_library", "//pkg/security/apparmor:go_default_library", - "//pkg/util/filesystem:go_default_library", - "//pkg/util/hash:go_default_library", "//pkg/util/parsers:go_default_library", "//vendor/github.com/armon/circbuf:go_default_library", "//vendor/github.com/blang/semver:go_default_library", @@ -112,7 +111,6 @@ go_library( "//vendor/github.com/docker/docker/pkg/jsonmessage:go_default_library", "//vendor/github.com/docker/go-connections/nat:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", @@ -150,12 +148,12 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/container/testing:go_default_library", "//pkg/kubelet/dockershim/libdocker:go_default_library", - "//pkg/kubelet/dockershim/testing:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/testing:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + "//pkg/kubelet/dockershim/network/testing:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/cache:go_default_library", "//pkg/security/apparmor:go_default_library", @@ -167,9 +165,13 @@ go_test( "//vendor/github.com/golang/mock/gomock:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", - ], + ] + select({ + "@io_bazel_rules_go//go/platform:linux": [ + "//vendor/k8s.io/api/core/v1:go_default_library", + ], + "//conditions:default": [], + }), ) filegroup( @@ -186,8 +188,8 @@ filegroup( "//pkg/kubelet/dockershim/cm:all-srcs", "//pkg/kubelet/dockershim/libdocker:all-srcs", "//pkg/kubelet/dockershim/metrics:all-srcs", + "//pkg/kubelet/dockershim/network:all-srcs", "//pkg/kubelet/dockershim/remote:all-srcs", - "//pkg/kubelet/dockershim/testing:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/convert.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/convert.go index f1c9b0e85..4f5621d24 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/convert.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/convert.go @@ -164,13 +164,14 @@ func containerToRuntimeAPISandbox(c *dockertypes.Container) (*runtimeapi.PodSand }, nil } -func checkpointToRuntimeAPISandbox(id string, checkpoint *PodSandboxCheckpoint) *runtimeapi.PodSandbox { +func checkpointToRuntimeAPISandbox(id string, checkpoint DockershimCheckpoint) *runtimeapi.PodSandbox { state := runtimeapi.PodSandboxState_SANDBOX_NOTREADY + _, name, namespace, _, _ := checkpoint.GetData() return &runtimeapi.PodSandbox{ Id: id, Metadata: &runtimeapi.PodSandboxMetadata{ - Name: checkpoint.Name, - Namespace: checkpoint.Namespace, + Name: name, + Namespace: namespace, }, State: state, } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_checkpoint.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_checkpoint.go index f47469699..8bfa1a778 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_checkpoint.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_checkpoint.go @@ -18,14 +18,9 @@ package dockershim import ( "encoding/json" - "fmt" - "hash/fnv" - "path/filepath" - - "github.com/golang/glog" - utilstore "k8s.io/kubernetes/pkg/kubelet/util/store" - utilfs "k8s.io/kubernetes/pkg/util/filesystem" - hashutil "k8s.io/kubernetes/pkg/util/hash" + + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" ) const ( @@ -36,6 +31,11 @@ const ( schemaVersion = "v1" ) +type DockershimCheckpoint interface { + checkpointmanager.Checkpoint + GetData() (string, string, string, []*PortMapping, bool) +} + type Protocol string // PortMapping is the port mapping configurations of a sandbox. @@ -65,89 +65,31 @@ type PodSandboxCheckpoint struct { // Data to checkpoint for pod sandbox. Data *CheckpointData `json:"data,omitempty"` // Checksum is calculated with fnv hash of the checkpoint object with checksum field set to be zero - CheckSum uint64 `json:"checksum"` -} - -// CheckpointHandler provides the interface to manage PodSandbox checkpoint -type CheckpointHandler interface { - // CreateCheckpoint persists sandbox checkpoint in CheckpointStore. - CreateCheckpoint(podSandboxID string, checkpoint *PodSandboxCheckpoint) error - // GetCheckpoint retrieves sandbox checkpoint from CheckpointStore. - GetCheckpoint(podSandboxID string) (*PodSandboxCheckpoint, error) - // RemoveCheckpoint removes sandbox checkpoint form CheckpointStore. - // WARNING: RemoveCheckpoint will not return error if checkpoint does not exist. - RemoveCheckpoint(podSandboxID string) error - // ListCheckpoint returns the list of existing checkpoints. - ListCheckpoints() ([]string, error) -} - -// PersistentCheckpointHandler is an implementation of CheckpointHandler. It persists checkpoint in CheckpointStore -type PersistentCheckpointHandler struct { - store utilstore.Store -} - -func NewPersistentCheckpointHandler(dockershimRootDir string) (CheckpointHandler, error) { - fstore, err := utilstore.NewFileStore(filepath.Join(dockershimRootDir, sandboxCheckpointDir), utilfs.DefaultFs{}) - if err != nil { - return nil, err - } - return &PersistentCheckpointHandler{store: fstore}, nil -} - -func (handler *PersistentCheckpointHandler) CreateCheckpoint(podSandboxID string, checkpoint *PodSandboxCheckpoint) error { - checkpoint.CheckSum = calculateChecksum(*checkpoint) - blob, err := json.Marshal(checkpoint) - if err != nil { - return err - } - return handler.store.Write(podSandboxID, blob) + Checksum checksum.Checksum `json:"checksum"` } -func (handler *PersistentCheckpointHandler) GetCheckpoint(podSandboxID string) (*PodSandboxCheckpoint, error) { - blob, err := handler.store.Read(podSandboxID) - if err != nil { - return nil, err - } - var checkpoint PodSandboxCheckpoint - //TODO: unmarhsal into a struct with just Version, check version, unmarshal into versioned type. - err = json.Unmarshal(blob, &checkpoint) - if err != nil { - glog.Errorf("Failed to unmarshal checkpoint %q, removing checkpoint. Checkpoint content: %q. ErrMsg: %v", podSandboxID, string(blob), err) - handler.RemoveCheckpoint(podSandboxID) - return nil, fmt.Errorf("failed to unmarshal checkpoint") - } - if checkpoint.CheckSum != calculateChecksum(checkpoint) { - glog.Errorf("Checksum of checkpoint %q is not valid, removing checkpoint", podSandboxID) - handler.RemoveCheckpoint(podSandboxID) - return nil, fmt.Errorf("checkpoint is corrupted") +func NewPodSandboxCheckpoint(namespace, name string, data *CheckpointData) DockershimCheckpoint { + return &PodSandboxCheckpoint{ + Version: schemaVersion, + Namespace: namespace, + Name: name, + Data: data, } - return &checkpoint, nil } -func (handler *PersistentCheckpointHandler) RemoveCheckpoint(podSandboxID string) error { - return handler.store.Delete(podSandboxID) +func (cp *PodSandboxCheckpoint) MarshalCheckpoint() ([]byte, error) { + cp.Checksum = checksum.New(*cp.Data) + return json.Marshal(*cp) } -func (handler *PersistentCheckpointHandler) ListCheckpoints() ([]string, error) { - keys, err := handler.store.List() - if err != nil { - return []string{}, fmt.Errorf("failed to list checkpoint store: %v", err) - } - return keys, nil +func (cp *PodSandboxCheckpoint) UnmarshalCheckpoint(blob []byte) error { + return json.Unmarshal(blob, cp) } -func NewPodSandboxCheckpoint(namespace, name string) *PodSandboxCheckpoint { - return &PodSandboxCheckpoint{ - Version: schemaVersion, - Namespace: namespace, - Name: name, - Data: &CheckpointData{}, - } +func (cp *PodSandboxCheckpoint) VerifyChecksum() error { + return cp.Checksum.Verify(*cp.Data) } -func calculateChecksum(checkpoint PodSandboxCheckpoint) uint64 { - checkpoint.CheckSum = 0 - hash := fnv.New32a() - hashutil.DeepHashObject(hash, checkpoint) - return uint64(hash.Sum32()) +func (cp *PodSandboxCheckpoint) GetData() (string, string, string, []*PortMapping, bool) { + return cp.Version, cp.Name, cp.Namespace, cp.Data.PortMappings, cp.Data.HostNetwork } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_checkpoint_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_checkpoint_test.go index c10b8f1e5..49f4e4d17 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_checkpoint_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_checkpoint_test.go @@ -17,86 +17,17 @@ limitations under the License. package dockershim import ( - "sort" "testing" "github.com/stretchr/testify/assert" - utilstore "k8s.io/kubernetes/pkg/kubelet/dockershim/testing" ) -func NewTestPersistentCheckpointHandler() CheckpointHandler { - return &PersistentCheckpointHandler{store: utilstore.NewMemStore()} -} - -func TestPersistentCheckpointHandler(t *testing.T) { - var err error - handler := NewTestPersistentCheckpointHandler() - port80 := int32(80) - port443 := int32(443) - proto := protocolTCP - - checkpoint1 := NewPodSandboxCheckpoint("ns1", "sandbox1") - checkpoint1.Data.PortMappings = []*PortMapping{ - { - &proto, - &port80, - &port80, - }, - { - &proto, - &port443, - &port443, - }, - } - checkpoint1.Data.HostNetwork = true - - checkpoints := []struct { - podSandboxID string - checkpoint *PodSandboxCheckpoint - expectHostNetwork bool - }{ - { - "id1", - checkpoint1, - true, - }, - { - "id2", - NewPodSandboxCheckpoint("ns2", "sandbox2"), - false, - }, - } - - for _, tc := range checkpoints { - // Test CreateCheckpoints - err = handler.CreateCheckpoint(tc.podSandboxID, tc.checkpoint) - assert.NoError(t, err) - - // Test GetCheckpoints - checkpoint, err := handler.GetCheckpoint(tc.podSandboxID) - assert.NoError(t, err) - assert.Equal(t, *checkpoint, *tc.checkpoint) - assert.Equal(t, checkpoint.Data.HostNetwork, tc.expectHostNetwork) - } - // Test ListCheckpoints - keys, err := handler.ListCheckpoints() - assert.NoError(t, err) - sort.Strings(keys) - assert.Equal(t, keys, []string{"id1", "id2"}) - - // Test RemoveCheckpoints - err = handler.RemoveCheckpoint("id1") - assert.NoError(t, err) - // Test Remove Nonexisted Checkpoints - err = handler.RemoveCheckpoint("id1") - assert.NoError(t, err) - - // Test ListCheckpoints - keys, err = handler.ListCheckpoints() - assert.NoError(t, err) - assert.Equal(t, keys, []string{"id2"}) - - // Test Get NonExisted Checkpoint - _, err = handler.GetCheckpoint("id1") - assert.Error(t, err) +func TestPodSandboxCheckpoint(t *testing.T) { + data := &CheckpointData{HostNetwork: true} + checkpoint := NewPodSandboxCheckpoint("ns1", "sandbox1", data) + version, name, namespace, _, hostNetwork := checkpoint.GetData() + assert.Equal(t, schemaVersion, version) + assert.Equal(t, "ns1", namespace) + assert.Equal(t, "sandbox1", name) + assert.Equal(t, true, hostNetwork) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_container.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_container.go index 58bb67120..6343e9be1 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_container.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_container.go @@ -17,6 +17,7 @@ limitations under the License. package dockershim import ( + "context" "fmt" "os" "path/filepath" @@ -27,7 +28,6 @@ import ( dockerfilters "github.com/docker/docker/api/types/filters" dockerstrslice "github.com/docker/docker/api/types/strslice" "github.com/golang/glog" - "golang.org/x/net/context" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_container_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_container_test.go index 640ab2d50..2e545d25c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_container_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_container_test.go @@ -17,6 +17,7 @@ limitations under the License. package dockershim import ( + "context" "fmt" "path/filepath" "strings" @@ -26,7 +27,6 @@ import ( dockertypes "github.com/docker/docker/api/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image.go index 71fe27cc2..e4c450bc8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image.go @@ -17,14 +17,15 @@ limitations under the License. package dockershim import ( + "context" "fmt" "net/http" dockertypes "github.com/docker/docker/api/types" dockerfilters "github.com/docker/docker/api/types/filters" "github.com/docker/docker/pkg/jsonmessage" - "golang.org/x/net/context" + "github.com/golang/glog" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" ) @@ -51,7 +52,7 @@ func (ds *dockerService) ListImages(_ context.Context, r *runtimeapi.ListImagesR for _, i := range images { apiImage, err := imageToRuntimeAPIImage(&i) if err != nil { - // TODO: log an error message? + glog.V(5).Infof("Failed to convert docker API image %+v to runtime API image: %v", i, err) continue } result = append(result, apiImage) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_linux.go index c823f9137..3409fa147 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_linux.go @@ -19,10 +19,9 @@ limitations under the License. package dockershim import ( + "context" "fmt" - "golang.org/x/net/context" - runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_unsupported.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_unsupported.go index 36fbd7cc6..41eed9927 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_unsupported.go @@ -19,10 +19,9 @@ limitations under the License. package dockershim import ( + "context" "fmt" - "golang.org/x/net/context" - runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_windows.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_windows.go index 703405614..38fe998be 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_windows.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_image_windows.go @@ -19,10 +19,10 @@ limitations under the License. package dockershim import ( + "context" "time" "github.com/golang/glog" - "golang.org/x/net/context" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" "k8s.io/kubernetes/pkg/kubelet/winstats" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_logs.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_logs.go index 5366c2982..76bfb4ba5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_logs.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_logs.go @@ -17,10 +17,9 @@ limitations under the License. package dockershim import ( + "context" "fmt" - "golang.org/x/net/context" - runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_sandbox.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_sandbox.go index dd150d8db..13e9c4236 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_sandbox.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_sandbox.go @@ -17,6 +17,7 @@ limitations under the License. package dockershim import ( + "context" "fmt" "os" "strings" @@ -26,10 +27,11 @@ import ( dockercontainer "github.com/docker/docker/api/types/container" dockerfilters "github.com/docker/docker/api/types/filters" "github.com/golang/glog" - "golang.org/x/net/context" utilerrors "k8s.io/apimachinery/pkg/util/errors" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" "k8s.io/kubernetes/pkg/kubelet/qos" @@ -37,7 +39,7 @@ import ( ) const ( - defaultSandboxImage = "k8s.gcr.io/pause-amd64:3.1" + defaultSandboxImage = "k8s.gcr.io/pause:3.1" // Various default sandbox resources requests/limits. defaultSandboxCPUshares int64 = 2 @@ -118,7 +120,7 @@ func (ds *dockerService) RunPodSandbox(ctx context.Context, r *runtimeapi.RunPod }(&err) // Step 3: Create Sandbox Checkpoint. - if err = ds.checkpointHandler.CreateCheckpoint(createResp.ID, constructPodSandboxCheckpoint(config)); err != nil { + if err = ds.checkpointManager.CreateCheckpoint(createResp.ID, constructPodSandboxCheckpoint(config)); err != nil { return nil, err } @@ -162,12 +164,24 @@ func (ds *dockerService) RunPodSandbox(ctx context.Context, r *runtimeapi.RunPod cID := kubecontainer.BuildContainerID(runtimeName, createResp.ID) err = ds.network.SetUpPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID, config.Annotations) if err != nil { - // TODO(random-liu): Do we need to teardown network here? - if err := ds.client.StopContainer(createResp.ID, defaultSandboxGracePeriod); err != nil { - glog.Warningf("Failed to stop sandbox container %q for pod %q: %v", createResp.ID, config.Metadata.Name, err) + errList := []error{fmt.Errorf("failed to set up sandbox container %q network for pod %q: %v", createResp.ID, config.Metadata.Name, err)} + + // Ensure network resources are cleaned up even if the plugin + // succeeded but an error happened between that success and here. + err = ds.network.TearDownPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID) + if err != nil { + errList = append(errList, fmt.Errorf("failed to clean up sandbox container %q network for pod %q: %v", createResp.ID, config.Metadata.Name, err)) + } + + err = ds.client.StopContainer(createResp.ID, defaultSandboxGracePeriod) + if err != nil { + errList = append(errList, fmt.Errorf("failed to stop sandbox container %q for pod %q: %v", createResp.ID, config.Metadata.Name, err)) } + + return resp, utilerrors.NewAggregate(errList) } - return resp, err + + return resp, nil } // StopPodSandbox stops the sandbox. If there are any running containers in the @@ -189,12 +203,19 @@ func (ds *dockerService) StopPodSandbox(ctx context.Context, r *runtimeapi.StopP name = metadata.Name hostNetwork = (networkNamespaceMode(inspectResult) == runtimeapi.NamespaceMode_NODE) } else { - checkpoint, checkpointErr := ds.checkpointHandler.GetCheckpoint(podSandboxID) + checkpoint := NewPodSandboxCheckpoint("", "", &CheckpointData{}) + checkpointErr := ds.checkpointManager.GetCheckpoint(podSandboxID, checkpoint) // Proceed if both sandbox container and checkpoint could not be found. This means that following // actions will only have sandbox ID and not have pod namespace and name information. // Return error if encounter any unexpected error. if checkpointErr != nil { + if checkpointErr != errors.ErrCheckpointNotFound { + err := ds.checkpointManager.RemoveCheckpoint(podSandboxID) + if err != nil { + glog.Errorf("Failed to delete corrupt checkpoint for sandbox %q: %v", podSandboxID, err) + } + } if libdocker.IsContainerNotFoundError(statusErr) { glog.Warningf("Both sandbox container and checkpoint for id %q could not be found. "+ "Proceed without further sandbox information.", podSandboxID) @@ -204,9 +225,7 @@ func (ds *dockerService) StopPodSandbox(ctx context.Context, r *runtimeapi.StopP fmt.Errorf("failed to get sandbox status: %v", statusErr)}) } } else { - namespace = checkpoint.Namespace - name = checkpoint.Name - hostNetwork = checkpoint.Data != nil && checkpoint.Data.HostNetwork + _, name, namespace, _, hostNetwork = checkpoint.GetData() } } @@ -237,7 +256,7 @@ func (ds *dockerService) StopPodSandbox(ctx context.Context, r *runtimeapi.StopP errList = append(errList, err) } else { // remove the checkpoint for any sandbox that is not found in the runtime - ds.checkpointHandler.RemoveCheckpoint(podSandboxID) + ds.checkpointManager.RemoveCheckpoint(podSandboxID) } } @@ -284,7 +303,7 @@ func (ds *dockerService) RemovePodSandbox(ctx context.Context, r *runtimeapi.Rem } // Remove the checkpoint of the sandbox. - if err := ds.checkpointHandler.RemoveCheckpoint(podSandboxID); err != nil { + if err := ds.checkpointManager.RemoveCheckpoint(podSandboxID); err != nil { errs = append(errs, err) } if len(errs) == 0 { @@ -465,7 +484,7 @@ func (ds *dockerService) ListPodSandbox(_ context.Context, r *runtimeapi.ListPod var err error checkpoints := []string{} if filter == nil { - checkpoints, err = ds.checkpointHandler.ListCheckpoints() + checkpoints, err = ds.checkpointManager.ListCheckpoints() if err != nil { glog.Errorf("Failed to list checkpoints: %v", err) } @@ -501,9 +520,16 @@ func (ds *dockerService) ListPodSandbox(_ context.Context, r *runtimeapi.ListPod if _, ok := sandboxIDs[id]; ok { continue } - checkpoint, err := ds.checkpointHandler.GetCheckpoint(id) + checkpoint := NewPodSandboxCheckpoint("", "", &CheckpointData{}) + err := ds.checkpointManager.GetCheckpoint(id, checkpoint) if err != nil { glog.Errorf("Failed to retrieve checkpoint for sandbox %q: %v", id, err) + if err == errors.ErrCorruptCheckpoint { + err = ds.checkpointManager.RemoveCheckpoint(id) + if err != nil { + glog.Errorf("Failed to delete corrupt checkpoint for sandbox %q: %v", id, err) + } + } continue } result = append(result, checkpointToRuntimeAPISandbox(id, checkpoint)) @@ -624,20 +650,20 @@ func ipcNamespaceMode(container *dockertypes.ContainerJSON) runtimeapi.Namespace return runtimeapi.NamespaceMode_POD } -func constructPodSandboxCheckpoint(config *runtimeapi.PodSandboxConfig) *PodSandboxCheckpoint { - checkpoint := NewPodSandboxCheckpoint(config.Metadata.Namespace, config.Metadata.Name) +func constructPodSandboxCheckpoint(config *runtimeapi.PodSandboxConfig) checkpointmanager.Checkpoint { + data := CheckpointData{} for _, pm := range config.GetPortMappings() { proto := toCheckpointProtocol(pm.Protocol) - checkpoint.Data.PortMappings = append(checkpoint.Data.PortMappings, &PortMapping{ + data.PortMappings = append(data.PortMappings, &PortMapping{ HostPort: &pm.HostPort, ContainerPort: &pm.ContainerPort, Protocol: &proto, }) } if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtimeapi.NamespaceMode_NODE { - checkpoint.Data.HostNetwork = true + data.HostNetwork = true } - return checkpoint + return NewPodSandboxCheckpoint(config.Metadata.Namespace, config.Metadata.Name, &data) } func toCheckpointProtocol(protocol runtimeapi.Protocol) Protocol { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_sandbox_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_sandbox_test.go index 609acd000..520e5091a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_sandbox_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_sandbox_test.go @@ -30,7 +30,7 @@ import ( runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - "k8s.io/kubernetes/pkg/kubelet/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" "k8s.io/kubernetes/pkg/kubelet/types" ) @@ -277,6 +277,8 @@ func TestSetUpPodFailure(t *testing.T) { cID := kubecontainer.ContainerID{Type: runtimeName, ID: libdocker.GetFakeContainerID(fmt.Sprintf("/%v", makeSandboxName(c)))} mockPlugin.EXPECT().Name().Return("mockNetworkPlugin").AnyTimes() mockPlugin.EXPECT().SetUpPod(ns, name, cID).Return(errors.New("setup pod error")).AnyTimes() + // If SetUpPod() fails, we expect TearDownPod() to immediately follow + mockPlugin.EXPECT().TearDownPod(ns, name, cID) // Assume network plugin doesn't return error, dockershim should still be able to return not ready correctly. mockPlugin.EXPECT().GetPodNetworkStatus(ns, name, cID).Return(&network.PodNetworkStatus{IP: net.IP("127.0.0.01")}, nil).AnyTimes() diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_service.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_service.go index 3c88a0e4e..8201ab941 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_service.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_service.go @@ -17,29 +17,31 @@ limitations under the License. package dockershim import ( + "context" "fmt" "net/http" + "path" + "path/filepath" "sync" "time" "github.com/blang/semver" dockertypes "github.com/docker/docker/api/types" "github.com/golang/glog" - "golang.org/x/net/context" "k8s.io/api/core/v1" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" - kubecm "k8s.io/kubernetes/pkg/kubelet/cm" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/dockershim/cm" - "k8s.io/kubernetes/pkg/kubelet/network" - "k8s.io/kubernetes/pkg/kubelet/network/cni" - "k8s.io/kubernetes/pkg/kubelet/network/hostport" - "k8s.io/kubernetes/pkg/kubelet/network/kubenet" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet" "k8s.io/kubernetes/pkg/kubelet/server/streaming" "k8s.io/kubernetes/pkg/kubelet/util/cache" - utilstore "k8s.io/kubernetes/pkg/kubelet/util/store" "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" "k8s.io/kubernetes/pkg/kubelet/dockershim/metrics" @@ -110,23 +112,19 @@ type NetworkPluginSettings struct { NonMasqueradeCIDR string // PluginName is the name of the plugin, runtime shim probes for PluginName string - // PluginBinDir is the directory in which the binaries for the plugin with - // PluginName is kept. The admin is responsible for provisioning these - // binaries before-hand. - PluginBinDir string + // PluginBinDirsString is a list of directiores delimited by commas, in + // which the binaries for the plugin with PluginName may be found. + PluginBinDirString string + // PluginBinDirs is an array of directories in which the binaries for + // the plugin with PluginName may be found. The admin is responsible for + // provisioning these binaries before-hand. + PluginBinDirs []string // PluginConfDir is the directory in which the admin places a CNI conf. // Depending on the plugin, this may be an optional field, eg: kubenet // generates its own plugin conf. PluginConfDir string // MTU is the desired MTU for network devices created by the plugin. MTU int - - // RuntimeHost is an interface that serves as a trap-door from plugin back - // into the kubelet. - // TODO: This shouldn't be required, remove once we move host ports into CNI - // and figure out bandwidth shaping. See corresponding comments above - // network.Host interface. - LegacyRuntimeHost network.LegacyHost } // namespaceGetter is a wrapper around the dockerService that implements @@ -153,7 +151,6 @@ func (p *portMappingGetter) GetPodPortMappings(containerID string) ([]*hostport. // and dockerServices which implements the rest of the network host interfaces. // The legacy host methods are slated for deletion. type dockerNetworkHost struct { - network.LegacyHost *namespaceGetter *portMappingGetter } @@ -191,12 +188,14 @@ func NewDockerClientFromConfig(config *ClientConfig) libdocker.Interface { // NOTE: Anything passed to DockerService should be eventually handled in another way when we switch to running the shim as a different process. func NewDockerService(config *ClientConfig, podSandboxImage string, streamingConfig *streaming.Config, - pluginSettings *NetworkPluginSettings, cgroupsName string, kubeCgroupDriver string, dockershimRootDir string, disableSharedPID bool) (DockerService, error) { + pluginSettings *NetworkPluginSettings, cgroupsName string, kubeCgroupDriver string, dockershimRootDir string, + disableSharedPID, startLocalStreamingServer bool) (DockerService, error) { client := NewDockerClientFromConfig(config) c := libdocker.NewInstrumentedInterface(client) - checkpointHandler, err := NewPersistentCheckpointHandler(dockershimRootDir) + + checkpointManager, err := checkpointmanager.NewCheckpointManager(filepath.Join(dockershimRootDir, sandboxCheckpointDir)) if err != nil { return nil, err } @@ -209,10 +208,11 @@ func NewDockerService(config *ClientConfig, podSandboxImage string, streamingCon client: client, execHandler: &NativeExecHandler{}, }, - containerManager: cm.NewContainerManager(cgroupsName, client), - checkpointHandler: checkpointHandler, - disableSharedPID: disableSharedPID, - networkReady: make(map[string]bool), + containerManager: cm.NewContainerManager(cgroupsName, client), + checkpointManager: checkpointManager, + disableSharedPID: disableSharedPID, + startLocalStreamingServer: startLocalStreamingServer, + networkReady: make(map[string]bool), } // check docker version compatibility. @@ -228,11 +228,20 @@ func NewDockerService(config *ClientConfig, podSandboxImage string, streamingCon return nil, err } } + + // Determine the hairpin mode. + if err := effectiveHairpinMode(pluginSettings); err != nil { + // This is a non-recoverable error. Returning it up the callstack will just + // lead to retries of the same failure, so just fail hard. + return nil, err + } + glog.Infof("Hairpin mode set to %q", pluginSettings.HairpinMode) + // dockershim currently only supports CNI plugins. - cniPlugins := cni.ProbeNetworkPlugins(pluginSettings.PluginConfDir, pluginSettings.PluginBinDir) - cniPlugins = append(cniPlugins, kubenet.NewPlugin(pluginSettings.PluginBinDir)) + pluginSettings.PluginBinDirs = cni.SplitDirs(pluginSettings.PluginBinDirString) + cniPlugins := cni.ProbeNetworkPlugins(pluginSettings.PluginConfDir, pluginSettings.PluginBinDirs) + cniPlugins = append(cniPlugins, kubenet.NewPlugin(pluginSettings.PluginBinDirs)) netHost := &dockerNetworkHost{ - pluginSettings.LegacyRuntimeHost, &namespaceGetter{ds}, &portMappingGetter{ds}, } @@ -289,7 +298,7 @@ type dockerService struct { containerManager cm.ContainerManager // cgroup driver used by Docker runtime. cgroupDriver string - checkpointHandler CheckpointHandler + checkpointManager checkpointmanager.CheckpointManager // caches the version of the runtime. // To be compatible with multiple docker versions, we need to perform // version checking for some operations. Use this cache to avoid querying @@ -300,6 +309,9 @@ type dockerService struct { // See proposals/pod-pid-namespace.md for details. // TODO: Remove once the escape hatch is no longer used (https://issues.k8s.io/41938) disableSharedPID bool + // startLocalStreamingServer indicates whether dockershim should start a + // streaming server on localhost. + startLocalStreamingServer bool } // TODO: handle context. @@ -361,17 +373,22 @@ func (ds *dockerService) GetNetNS(podSandboxID string) (string, error) { // GetPodPortMappings returns the port mappings of the given podSandbox ID. func (ds *dockerService) GetPodPortMappings(podSandboxID string) ([]*hostport.PortMapping, error) { // TODO: get portmappings from docker labels for backward compatibility - checkpoint, err := ds.checkpointHandler.GetCheckpoint(podSandboxID) + checkpoint := NewPodSandboxCheckpoint("", "", &CheckpointData{}) + err := ds.checkpointManager.GetCheckpoint(podSandboxID, checkpoint) // Return empty portMappings if checkpoint is not found if err != nil { - if err == utilstore.ErrKeyNotFound { + if err == errors.ErrCheckpointNotFound { return nil, nil } + errRem := ds.checkpointManager.RemoveCheckpoint(podSandboxID) + if errRem != nil { + glog.Errorf("Failed to delete corrupt checkpoint for sandbox %q: %v", podSandboxID, errRem) + } return nil, err } - - portMappings := make([]*hostport.PortMapping, 0, len(checkpoint.Data.PortMappings)) - for _, pm := range checkpoint.Data.PortMappings { + _, _, _, checkpointedPortMappings, _ := checkpoint.GetData() + portMappings := make([]*hostport.PortMapping, 0, len(checkpointedPortMappings)) + for _, pm := range checkpointedPortMappings { proto := toAPIProtocol(*pm.Protocol) portMappings = append(portMappings, &hostport.PortMapping{ HostPort: *pm.HostPort, @@ -385,11 +402,17 @@ func (ds *dockerService) GetPodPortMappings(podSandboxID string) ([]*hostport.Po // Start initializes and starts components in dockerService. func (ds *dockerService) Start() error { // Initialize the legacy cleanup flag. + if ds.startLocalStreamingServer { + go func() { + if err := ds.streamingServer.Start(true); err != nil { + glog.Fatalf("Streaming server stopped unexpectedly: %v", err) + } + }() + } return ds.containerManager.Start() } // Status returns the status of the runtime. -// TODO(random-liu): Set network condition accordingly here. func (ds *dockerService) Status(_ context.Context, r *runtimeapi.StatusRequest) (*runtimeapi.StatusResponse, error) { runtimeReady := &runtimeapi.RuntimeCondition{ Type: runtimeapi.RuntimeReady, @@ -424,17 +447,14 @@ func (ds *dockerService) ServeHTTP(w http.ResponseWriter, r *http.Request) { // GenerateExpectedCgroupParent returns cgroup parent in syntax expected by cgroup driver func (ds *dockerService) GenerateExpectedCgroupParent(cgroupParent string) (string, error) { - if len(cgroupParent) > 0 { + if cgroupParent != "" { // if docker uses the systemd cgroup driver, it expects *.slice style names for cgroup parent. // if we configured kubelet to use --cgroup-driver=cgroupfs, and docker is configured to use systemd driver // docker will fail to launch the container because the name we provide will not be a valid slice. // this is a very good thing. if ds.cgroupDriver == "systemd" { - systemdCgroupParent, err := kubecm.ConvertCgroupFsNameToSystemd(cgroupParent) - if err != nil { - return "", err - } - cgroupParent = systemdCgroupParent + // Pass only the last component of the cgroup path to systemd. + cgroupParent = path.Base(cgroupParent) } } glog.V(3).Infof("Setting cgroup parent to: %q", cgroupParent) @@ -506,3 +526,28 @@ func toAPIProtocol(protocol Protocol) v1.Protocol { glog.Warningf("Unknown protocol %q: defaulting to TCP", protocol) return v1.ProtocolTCP } + +// effectiveHairpinMode determines the effective hairpin mode given the +// configured mode, and whether cbr0 should be configured. +func effectiveHairpinMode(s *NetworkPluginSettings) error { + // The hairpin mode setting doesn't matter if: + // - We're not using a bridge network. This is hard to check because we might + // be using a plugin. + // - It's set to hairpin-veth for a container runtime that doesn't know how + // to set the hairpin flag on the veth's of containers. Currently the + // docker runtime is the only one that understands this. + // - It's set to "none". + if s.HairpinMode == kubeletconfig.PromiscuousBridge || s.HairpinMode == kubeletconfig.HairpinVeth { + if s.HairpinMode == kubeletconfig.PromiscuousBridge && s.PluginName != "kubenet" { + // This is not a valid combination, since promiscuous-bridge only works on kubenet. Users might be using the + // default values (from before the hairpin-mode flag existed) and we + // should keep the old behavior. + glog.Warningf("Hairpin mode set to %q but kubenet is not enabled, falling back to %q", s.HairpinMode, kubeletconfig.HairpinVeth) + s.HairpinMode = kubeletconfig.HairpinVeth + return nil + } + } else if s.HairpinMode != kubeletconfig.HairpinNone { + return fmt.Errorf("unknown value: %q", s.HairpinMode) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_service_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_service_test.go index 9bbf4cb8f..cc42ef5ca 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_service_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_service_test.go @@ -30,10 +30,11 @@ import ( "k8s.io/apimachinery/pkg/util/clock" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - "k8s.io/kubernetes/pkg/kubelet/network" - nettest "k8s.io/kubernetes/pkg/kubelet/network/testing" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" + nettest "k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing" "k8s.io/kubernetes/pkg/kubelet/util/cache" ) @@ -43,15 +44,50 @@ func newTestNetworkPlugin(t *testing.T) *nettest.MockNetworkPlugin { return nettest.NewMockNetworkPlugin(ctrl) } +type mockCheckpointManager struct { + checkpoint map[string]*PodSandboxCheckpoint +} + +func (ckm *mockCheckpointManager) CreateCheckpoint(checkpointKey string, checkpoint checkpointmanager.Checkpoint) error { + ckm.checkpoint[checkpointKey] = checkpoint.(*PodSandboxCheckpoint) + return nil +} + +func (ckm *mockCheckpointManager) GetCheckpoint(checkpointKey string, checkpoint checkpointmanager.Checkpoint) error { + *(checkpoint.(*PodSandboxCheckpoint)) = *(ckm.checkpoint[checkpointKey]) + return nil +} + +func (ckm *mockCheckpointManager) RemoveCheckpoint(checkpointKey string) error { + _, ok := ckm.checkpoint[checkpointKey] + if ok { + delete(ckm.checkpoint, "moo") + } + return nil +} + +func (ckm *mockCheckpointManager) ListCheckpoints() ([]string, error) { + var keys []string + for key := range ckm.checkpoint { + keys = append(keys, key) + } + return keys, nil +} + +func newMockCheckpointManager() checkpointmanager.CheckpointManager { + return &mockCheckpointManager{checkpoint: make(map[string]*PodSandboxCheckpoint)} +} + func newTestDockerService() (*dockerService, *libdocker.FakeDockerClient, *clock.FakeClock) { fakeClock := clock.NewFakeClock(time.Time{}) c := libdocker.NewFakeDockerClient().WithClock(fakeClock).WithVersion("1.11.2", "1.23").WithRandSource(rand.NewSource(0)) pm := network.NewPluginManager(&network.NoopNetworkPlugin{}) + ckm := newMockCheckpointManager() return &dockerService{ client: c, os: &containertest.FakeOS{}, network: pm, - checkpointHandler: NewTestPersistentCheckpointHandler(), + checkpointManager: ckm, networkReady: make(map[string]bool), }, c, fakeClock } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_linux.go index e8b54ac1d..ab3c675d8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_linux.go @@ -19,9 +19,9 @@ limitations under the License. package dockershim import ( + "context" "fmt" - "golang.org/x/net/context" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_unsupported.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_unsupported.go index 72b6409c7..6591a9e38 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_unsupported.go @@ -19,10 +19,9 @@ limitations under the License. package dockershim import ( + "context" "fmt" - "golang.org/x/net/context" - runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_windows.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_windows.go index 644dffd58..a690f883b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_windows.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_stats_windows.go @@ -19,10 +19,9 @@ limitations under the License. package dockershim import ( + "context" "time" - "golang.org/x/net/context" - runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) @@ -65,6 +64,11 @@ func (ds *dockerService) ListContainerStats(ctx context.Context, r *runtimeapi.L } func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.ContainerStats, error) { + info, err := ds.client.Info() + if err != nil { + return nil, err + } + statsJSON, err := ds.client.GetContainerStats(containerID) if err != nil { return nil, err @@ -102,6 +106,7 @@ func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.Cont }, WritableLayer: &runtimeapi.FilesystemUsage{ Timestamp: timestamp, + FsId: &runtimeapi.FilesystemIdentifier{Mountpoint: info.DockerRootDir}, UsedBytes: &runtimeapi.UInt64Value{Value: uint64(*containerJSON.SizeRw)}, }, } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_streaming.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_streaming.go index bb0a4a637..d65b97004 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_streaming.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/docker_streaming.go @@ -18,6 +18,7 @@ package dockershim import ( "bytes" + "context" "fmt" "io" "math" @@ -27,7 +28,6 @@ import ( dockertypes "github.com/docker/docker/api/types" "github.com/golang/glog" - "golang.org/x/net/context" "k8s.io/client-go/tools/remotecommand" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_linux.go index a73c241cc..5d231ea82 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_linux.go @@ -30,6 +30,7 @@ import ( "github.com/blang/semver" dockertypes "github.com/docker/docker/api/types" dockercontainer "github.com/docker/docker/api/types/container" + "k8s.io/api/core/v1" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) @@ -53,7 +54,7 @@ func getSeccompDockerOpts(seccompProfile string) ([]dockerOpt, error) { return defaultSeccompOpt, nil } - if seccompProfile == "docker/default" { + if seccompProfile == v1.SeccompProfileRuntimeDefault || seccompProfile == v1.DeprecatedSeccompProfileDockerDefault { // return nil so docker will load the default seccomp profile return nil, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_linux_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_linux_test.go index c7aa67083..2f7ddb532 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_linux_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_linux_test.go @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "k8s.io/api/core/v1" ) func TestGetSeccompSecurityOpts(t *testing.T) { @@ -44,7 +45,11 @@ func TestGetSeccompSecurityOpts(t *testing.T) { expectedOpts: []string{"seccomp=unconfined"}, }, { msg: "Seccomp default", - seccompProfile: "docker/default", + seccompProfile: v1.SeccompProfileRuntimeDefault, + expectedOpts: nil, + }, { + msg: "Seccomp deprecated default", + seccompProfile: v1.DeprecatedSeccompProfileDockerDefault, expectedOpts: nil, }} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_test.go index 1fdb185ed..7971a9297 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_test.go @@ -342,5 +342,5 @@ func TestGenerateMountBindings(t *testing.T) { } result := generateMountBindings(mounts) - assert.Equal(t, result, expectedResult) + assert.Equal(t, expectedResult, result) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_windows.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_windows.go index e614eed85..436701546 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_windows.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/helpers_windows.go @@ -76,6 +76,9 @@ func (ds *dockerService) updateCreateConfig( CPUPercent: rOpts.CpuMaximum, } } + + // Apply security context. + applyWindowsContainerSecurityContext(wc.GetSecurityContext(), createConfig.Config, createConfig.HostConfig) } applyExperimentalCreateConfig(createConfig, sandboxConfig.Annotations) @@ -83,6 +86,17 @@ func (ds *dockerService) updateCreateConfig( return nil } +// applyWindowsContainerSecurityContext updates docker container options according to security context. +func applyWindowsContainerSecurityContext(wsc *runtimeapi.WindowsContainerSecurityContext, config *dockercontainer.Config, hc *dockercontainer.HostConfig) { + if wsc == nil { + return + } + + if wsc.GetRunAsUsername() != "" { + config.User = wsc.GetRunAsUsername() + } +} + func (ds *dockerService) determinePodIPBySandboxID(sandboxID string) string { opts := dockertypes.ContainerListOptions{ All: true, @@ -115,6 +129,17 @@ func (ds *dockerService) determinePodIPBySandboxID(sandboxID string) string { // Todo: Add a kernel version check for more validation if networkMode := os.Getenv("CONTAINER_NETWORK"); networkMode == "" { + // On Windows, every container that is created in a Sandbox, needs to invoke CNI plugin again for adding the Network, + // with the shared container name as NetNS info, + // This is passed down to the platform to replicate some necessary information to the new container + + // + // This place is chosen as a hack for now, since ds.getIP would end up calling CNI's addToNetwork + // That is why addToNetwork is required to be idempotent + + // Instead of relying on this call, an explicit call to addToNetwork should be + // done immediately after ContainerCreation, in case of Windows only. TBD Issue # to handle this + if r.HostConfig.Isolation == kubeletapis.HypervIsolationValue { // Hyper-V only supports one container per Pod yet and the container will have a different // IP address from sandbox. Return the first non-sandbox container IP as POD IP. @@ -123,22 +148,16 @@ func (ds *dockerService) determinePodIPBySandboxID(sandboxID string) string { return containerIP } } else { - // Do not return any IP, so that we would continue and get the IP of the Sandbox + // Do not return any IP, so that we would continue and get the IP of the Sandbox. + // Windows 1709 and 1803 doesn't have the Namespace support, so getIP() is called + // to replicate the DNS registry key to the Workload container (IP/Gateway/MAC is + // set separately than DNS). + // TODO(feiskyer): remove this workaround after Namespace is supported in Windows RS5. ds.getIP(sandboxID, r) } } else { - // On Windows, every container that is created in a Sandbox, needs to invoke CNI plugin again for adding the Network, - // with the shared container name as NetNS info, - // This is passed down to the platform to replicate some necessary information to the new container - - // - // This place is chosen as a hack for now, since getContainerIP would end up calling CNI's addToNetwork - // That is why addToNetwork is required to be idempotent - - // Instead of relying on this call, an explicit call to addToNetwork should be - // done immediately after ContainerCreation, in case of Windows only. TBD Issue # to handle this - - if containerIP := getContainerIP(r); containerIP != "" { + // ds.getIP will call the CNI plugin to fetch the IP + if containerIP := ds.getIP(c.ID, r); containerIP != "" { return containerIP } } @@ -153,14 +172,3 @@ func getNetworkNamespace(c *dockertypes.ContainerJSON) (string, error) { // so returning the docker networkMode (which holds container: for network namespace here return string(c.HostConfig.NetworkMode), nil } - -func getContainerIP(container *dockertypes.ContainerJSON) string { - if container.NetworkSettings != nil { - for _, network := range container.NetworkSettings.Networks { - if network.IPAddress != "" { - return network.IPAddress - } - } - } - return "" -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker/BUILD index e3e75cff4..73b1d79fa 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker/BUILD @@ -40,7 +40,6 @@ go_library( "//vendor/github.com/docker/docker/pkg/stdcopy:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/opencontainers/go-digest:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker/kube_docker_client.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker/kube_docker_client.go index 0cc0c3ae0..02ef40bc7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker/kube_docker_client.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker/kube_docker_client.go @@ -18,6 +18,7 @@ package libdocker import ( "bytes" + "context" "encoding/base64" "encoding/json" "fmt" @@ -35,7 +36,6 @@ import ( dockerapi "github.com/docker/docker/client" dockermessage "github.com/docker/docker/pkg/jsonmessage" dockerstdcopy "github.com/docker/docker/pkg/stdcopy" - "golang.org/x/net/context" ) // kubeDockerClient is a wrapped layer of docker client for kubelet internal use. This layer is added to: @@ -337,7 +337,7 @@ func (p *progressReporter) start() { case <-ticker.C: progress, timestamp := p.progress.get() // If there is no progress for p.imagePullProgressDeadline, cancel the operation. - if time.Now().Sub(timestamp) > p.imagePullProgressDeadline { + if time.Since(timestamp) > p.imagePullProgressDeadline { glog.Errorf("Cancel pulling image %q because of no progress for %v, latest progress: %q", p.image, p.imagePullProgressDeadline, progress) p.cancel() return diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/BUILD new file mode 100644 index 000000000..b1760d099 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/BUILD @@ -0,0 +1,46 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "network.go", + "plugins.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/network", + visibility = ["//visibility:public"], + deps = [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network/hostport:go_default_library", + "//pkg/kubelet/dockershim/network/metrics:go_default_library", + "//pkg/util/sysctl:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/kubelet/dockershim/network/cni:all-srcs", + "//pkg/kubelet/dockershim/network/hairpin:all-srcs", + "//pkg/kubelet/dockershim/network/hostport:all-srcs", + "//pkg/kubelet/dockershim/network/kubenet:all-srcs", + "//pkg/kubelet/dockershim/network/metrics:all-srcs", + "//pkg/kubelet/dockershim/network/testing:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/OWNERS b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/OWNERS new file mode 100644 index 000000000..73c2c95f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/OWNERS @@ -0,0 +1,9 @@ +approvers: +- thockin +- dchen1107 +- matchstick +- freehan +- dcbw +reviewers: +- sig-network-reviewers + diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/BUILD new file mode 100644 index 000000000..7fd7e2d16 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/BUILD @@ -0,0 +1,110 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "cni.go", + ] + select({ + "@io_bazel_rules_go//go/platform:android": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:nacl": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "cni_others.go", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "cni_windows.go", + ], + "//conditions:default": [], + }), + importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni", + deps = [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + "//vendor/github.com/containernetworking/cni/libcni:go_default_library", + "//vendor/github.com/containernetworking/cni/pkg/types:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + ] + select({ + "@io_bazel_rules_go//go/platform:windows": [ + "//vendor/github.com/containernetworking/cni/pkg/types/020:go_default_library", + ], + "//conditions:default": [], + }), +) + +go_test( + name = "go_default_test", + srcs = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "cni_test.go", + ], + "//conditions:default": [], + }), + embed = [":go_default_library"], + deps = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/container/testing:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + "//pkg/kubelet/dockershim/network/cni/testing:go_default_library", + "//pkg/kubelet/dockershim/network/hostport:go_default_library", + "//pkg/kubelet/dockershim/network/testing:go_default_library", + "//vendor/github.com/containernetworking/cni/pkg/types/020:go_default_library", + "//vendor/github.com/stretchr/testify/mock:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/util/testing:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + "//vendor/k8s.io/utils/exec/testing:go_default_library", + ], + "//conditions:default": [], + }), +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/kubelet/dockershim/network/cni/testing:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni.go similarity index 81% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni.go index 15724afc4..776f3eeda 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni.go @@ -28,15 +28,14 @@ import ( "github.com/golang/glog" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" utilexec "k8s.io/utils/exec" ) const ( - CNIPluginName = "cni" - DefaultNetDir = "/etc/cni/net.d" - DefaultCNIDir = "/opt/cni/bin" - VendorCNIDirTemplate = "%s/opt/%s/bin" + CNIPluginName = "cni" + DefaultConfDir = "/etc/cni/net.d" + DefaultBinDir = "/opt/cni/bin" ) type cniNetworkPlugin struct { @@ -47,12 +46,11 @@ type cniNetworkPlugin struct { sync.RWMutex defaultNetwork *cniNetwork - host network.Host - execer utilexec.Interface - nsenterPath string - pluginDir string - binDir string - vendorCNIDirPrefix string + host network.Host + execer utilexec.Interface + nsenterPath string + confDir string + binDirs []string } type cniNetwork struct { @@ -70,17 +68,33 @@ type cniPortMapping struct { HostIP string `json:"hostIP"` } -func probeNetworkPluginsWithVendorCNIDirPrefix(pluginDir, binDir, vendorCNIDirPrefix string) []network.NetworkPlugin { - if binDir == "" { - binDir = DefaultCNIDir +func SplitDirs(dirs string) []string { + // Use comma rather than colon to work better with Windows too + return strings.Split(dirs, ",") +} + +func ProbeNetworkPlugins(confDir string, binDirs []string) []network.NetworkPlugin { + old := binDirs + binDirs = make([]string, 0, len(binDirs)) + for _, dir := range old { + if dir != "" { + binDirs = append(binDirs, dir) + } + } + if len(binDirs) == 0 { + binDirs = []string{DefaultBinDir} + } + + if confDir == "" { + confDir = DefaultConfDir } + plugin := &cniNetworkPlugin{ - defaultNetwork: nil, - loNetwork: getLoNetwork(binDir, vendorCNIDirPrefix), - execer: utilexec.New(), - pluginDir: pluginDir, - binDir: binDir, - vendorCNIDirPrefix: vendorCNIDirPrefix, + defaultNetwork: nil, + loNetwork: getLoNetwork(binDirs), + execer: utilexec.New(), + confDir: confDir, + binDirs: binDirs, } // sync NetworkConfig in best effort during probing. @@ -88,20 +102,13 @@ func probeNetworkPluginsWithVendorCNIDirPrefix(pluginDir, binDir, vendorCNIDirPr return []network.NetworkPlugin{plugin} } -func ProbeNetworkPlugins(pluginDir, binDir string) []network.NetworkPlugin { - return probeNetworkPluginsWithVendorCNIDirPrefix(pluginDir, binDir, "") -} - -func getDefaultCNINetwork(pluginDir, binDir, vendorCNIDirPrefix string) (*cniNetwork, error) { - if pluginDir == "" { - pluginDir = DefaultNetDir - } - files, err := libcni.ConfFiles(pluginDir, []string{".conf", ".conflist", ".json"}) +func getDefaultCNINetwork(confDir string, binDirs []string) (*cniNetwork, error) { + files, err := libcni.ConfFiles(confDir, []string{".conf", ".conflist", ".json"}) switch { case err != nil: return nil, err case len(files) == 0: - return nil, fmt.Errorf("No networks found in %s", pluginDir) + return nil, fmt.Errorf("No networks found in %s", confDir) } sort.Strings(files) @@ -136,21 +143,15 @@ func getDefaultCNINetwork(pluginDir, binDir, vendorCNIDirPrefix string) (*cniNet glog.Warningf("CNI config list %s has no networks, skipping", confFile) continue } - confType := confList.Plugins[0].Network.Type - // Search for vendor-specific plugins as well as default plugins in the CNI codebase. - vendorDir := vendorCNIDir(vendorCNIDirPrefix, confType) - cninet := &libcni.CNIConfig{ - Path: []string{vendorDir, binDir}, + network := &cniNetwork{ + name: confList.Name, + NetworkConfig: confList, + CNIConfig: &libcni.CNIConfig{Path: binDirs}, } - network := &cniNetwork{name: confList.Name, NetworkConfig: confList, CNIConfig: cninet} return network, nil } - return nil, fmt.Errorf("No valid networks found in %s", pluginDir) -} - -func vendorCNIDir(prefix, pluginType string) string { - return fmt.Sprintf(VendorCNIDirTemplate, prefix, pluginType) + return nil, fmt.Errorf("No valid networks found in %s", confDir) } func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { @@ -166,7 +167,7 @@ func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfi } func (plugin *cniNetworkPlugin) syncNetworkConfig() { - network, err := getDefaultCNINetwork(plugin.pluginDir, plugin.binDir, plugin.vendorCNIDirPrefix) + network, err := getDefaultCNINetwork(plugin.confDir, plugin.binDirs) if err != nil { glog.Warningf("Unable to update cni config: %s", err) return @@ -198,7 +199,7 @@ func (plugin *cniNetworkPlugin) Name() string { } func (plugin *cniNetworkPlugin) Status() error { - // sync network config from pluginDir periodically to detect network config updates + // sync network config from confDir periodically to detect network config updates plugin.syncNetworkConfig() // Can't set up pods if we don't have any CNI network configs yet diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni_others.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni_others.go similarity index 90% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni_others.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni_others.go index 735db9cc6..56f75ca3a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni_others.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni_others.go @@ -23,10 +23,10 @@ import ( "github.com/containernetworking/cni/libcni" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" ) -func getLoNetwork(binDir, vendorDirPrefix string) *cniNetwork { +func getLoNetwork(binDirs []string) *cniNetwork { loConfig, err := libcni.ConfListFromBytes([]byte(`{ "cniVersion": "0.2.0", "name": "cni-loopback", @@ -39,13 +39,10 @@ func getLoNetwork(binDir, vendorDirPrefix string) *cniNetwork { // catch this panic(err) } - cninet := &libcni.CNIConfig{ - Path: []string{vendorCNIDir(vendorDirPrefix, "loopback"), binDir}, - } loNetwork := &cniNetwork{ name: "lo", NetworkConfig: loConfig, - CNIConfig: cninet, + CNIConfig: &libcni.CNIConfig{Path: binDirs}, } return loNetwork diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni_test.go similarity index 79% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni_test.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni_test.go index b34488ed4..b8ffbe4eb 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni_test.go @@ -39,42 +39,39 @@ import ( "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" - "k8s.io/kubernetes/pkg/kubelet/network" - "k8s.io/kubernetes/pkg/kubelet/network/cni/testing" - "k8s.io/kubernetes/pkg/kubelet/network/hostport" - networktest "k8s.io/kubernetes/pkg/kubelet/network/testing" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" + networktest "k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing" "k8s.io/utils/exec" fakeexec "k8s.io/utils/exec/testing" ) -func installPluginUnderTest(t *testing.T, testVendorCNIDirPrefix, testNetworkConfigPath, vendorName string, plugName string) { - pluginDir := path.Join(testNetworkConfigPath, plugName) - err := os.MkdirAll(pluginDir, 0777) - if err != nil { - t.Fatalf("Failed to create plugin config dir: %v", err) +// Returns .in file path, .out file path, and .env file path +func installPluginUnderTest(t *testing.T, testBinDir, testConfDir, testDataDir, binName string, confName string) (string, string, string) { + for _, dir := range []string{testBinDir, testConfDir, testDataDir} { + err := os.MkdirAll(dir, 0777) + if err != nil { + t.Fatalf("Failed to create test plugin dir %s: %v", dir, err) + } } - pluginConfig := path.Join(pluginDir, plugName+".conf") - f, err := os.Create(pluginConfig) + + confFile := path.Join(testConfDir, confName+".conf") + f, err := os.Create(confFile) if err != nil { - t.Fatalf("Failed to install plugin") + t.Fatalf("Failed to install plugin %s: %v", confFile, err) } - networkConfig := fmt.Sprintf(`{ "name": "%s", "type": "%s", "capabilities": {"portMappings": true} }`, plugName, vendorName) - + networkConfig := fmt.Sprintf(`{ "name": "%s", "type": "%s", "capabilities": {"portMappings": true} }`, confName, binName) _, err = f.WriteString(networkConfig) if err != nil { t.Fatalf("Failed to write network config file (%v)", err) } f.Close() - vendorCNIDir := fmt.Sprintf(VendorCNIDirTemplate, testVendorCNIDirPrefix, vendorName) - err = os.MkdirAll(vendorCNIDir, 0777) - if err != nil { - t.Fatalf("Failed to create plugin dir: %v", err) - } - pluginExec := path.Join(vendorCNIDir, vendorName) + pluginExec := path.Join(testBinDir, binName) f, err = os.Create(pluginExec) - const execScriptTempl = `#!/bin/bash + const execScriptTempl = `#!/usr/bin/env bash cat > {{.InputFile}} env > {{.OutputEnv}} echo "%@" >> {{.OutputEnv}} @@ -83,11 +80,14 @@ mkdir -p {{.OutputDir}} &> /dev/null echo -n "$CNI_COMMAND $CNI_NETNS $K8S_POD_NAMESPACE $K8S_POD_NAME $K8S_POD_INFRA_CONTAINER_ID" >& {{.OutputFile}} echo -n "{ \"ip4\": { \"ip\": \"10.1.0.23/24\" } }" ` + inputFile := path.Join(testDataDir, binName+".in") + outputFile := path.Join(testDataDir, binName+".out") + envFile := path.Join(testDataDir, binName+".env") execTemplateData := &map[string]interface{}{ - "InputFile": path.Join(pluginDir, plugName+".in"), - "OutputFile": path.Join(pluginDir, plugName+".out"), - "OutputEnv": path.Join(pluginDir, plugName+".env"), - "OutputDir": pluginDir, + "InputFile": inputFile, + "OutputFile": outputFile, + "OutputEnv": envFile, + "OutputDir": testDataDir, } tObj := template.Must(template.New("test").Parse(execScriptTempl)) @@ -107,6 +107,8 @@ echo -n "{ \"ip4\": { \"ip\": \"10.1.0.23/24\" } }" } f.Close() + + return inputFile, outputFile, envFile } func tearDownPlugin(tmpDir string) { @@ -155,8 +157,8 @@ func (fnh *fakeNetworkHost) SupportsLegacyFeatures() bool { func TestCNIPlugin(t *testing.T) { // install some random plugin - pluginName := fmt.Sprintf("test%d", rand.Intn(1000)) - vendorName := fmt.Sprintf("test_vendor%d", rand.Intn(1000)) + netName := fmt.Sprintf("test%d", rand.Intn(1000)) + binName := fmt.Sprintf("test_vendor%d", rand.Intn(1000)) podIP := "10.0.0.2" podIPOutput := fmt.Sprintf("4: eth0 inet %s/24 scope global dynamic eth0\\ valid_lft forever preferred_lft forever", podIP) @@ -183,10 +185,11 @@ func TestCNIPlugin(t *testing.T) { // TODO mock for the test plugin too tmpDir := utiltesting.MkTmpdirOrDie("cni-test") - testNetworkConfigPath := path.Join(tmpDir, "plugins", "net", "cni") - testVendorCNIDirPrefix := tmpDir + testConfDir := path.Join(tmpDir, "etc", "cni", "net.d") + testBinDir := path.Join(tmpDir, "opt", "cni", "bin") + testDataDir := path.Join(tmpDir, "output") defer tearDownPlugin(tmpDir) - installPluginUnderTest(t, testVendorCNIDirPrefix, testNetworkConfigPath, vendorName, pluginName) + inputFile, outputFile, outputEnv := installPluginUnderTest(t, testBinDir, testConfDir, testDataDir, binName, netName) containerID := kubecontainer.ContainerID{Type: "test", ID: "test_infra_container"} pods := []*containertest.FakePod{{ @@ -198,7 +201,7 @@ func TestCNIPlugin(t *testing.T) { NetnsPath: "/proc/12345/ns/net", }} - plugins := probeNetworkPluginsWithVendorCNIDirPrefix(path.Join(testNetworkConfigPath, pluginName), "", testVendorCNIDirPrefix) + plugins := ProbeNetworkPlugins(testConfDir, []string{testBinDir}) if len(plugins) != 1 { t.Fatalf("Expected only one network plugin, got %d", len(plugins)) } @@ -238,9 +241,7 @@ func TestCNIPlugin(t *testing.T) { if err != nil { t.Errorf("Expected nil: %v", err) } - outputEnv := path.Join(testNetworkConfigPath, pluginName, pluginName+".env") eo, eerr := ioutil.ReadFile(outputEnv) - outputFile := path.Join(testNetworkConfigPath, pluginName, pluginName+".out") output, err := ioutil.ReadFile(outputFile) if err != nil || eerr != nil { t.Errorf("Failed to read output file %s: %v (env %s err %v)", outputFile, err, eo, eerr) @@ -257,7 +258,6 @@ func TestCNIPlugin(t *testing.T) { PortMappings []map[string]interface{} `json:"portMappings"` } `json:"runtimeConfig"` }{} - inputFile := path.Join(testNetworkConfigPath, pluginName, pluginName+".in") inputBytes, inerr := ioutil.ReadFile(inputFile) parseerr := json.Unmarshal(inputBytes, &inputConfig) if inerr != nil || parseerr != nil { @@ -285,7 +285,7 @@ func TestCNIPlugin(t *testing.T) { if err != nil { t.Errorf("Expected nil: %v", err) } - output, err = ioutil.ReadFile(path.Join(testNetworkConfigPath, pluginName, pluginName+".out")) + output, err = ioutil.ReadFile(outputFile) expectedOutput = "DEL /proc/12345/ns/net podNamespace podName test_infra_container" if string(output) != expectedOutput { t.Errorf("Mismatch in expected output for setup hook. Expected '%s', got '%s'", expectedOutput, string(output)) @@ -295,7 +295,7 @@ func TestCNIPlugin(t *testing.T) { } func TestLoNetNonNil(t *testing.T) { - if conf := getLoNetwork("", ""); conf == nil { + if conf := getLoNetwork(nil); conf == nil { t.Error("Expected non-nil lo network") } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni_windows.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni_windows.go similarity index 94% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni_windows.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni_windows.go index 9a0b17c8f..82324b9ac 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/cni_windows.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/cni_windows.go @@ -24,10 +24,10 @@ import ( cniTypes020 "github.com/containernetworking/cni/pkg/types/020" "github.com/golang/glog" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" ) -func getLoNetwork(binDir, vendorDirPrefix string) *cniNetwork { +func getLoNetwork(binDirs []string) *cniNetwork { return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing/BUILD new file mode 100644 index 000000000..efcec7de0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing/BUILD @@ -0,0 +1,30 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["mock_cni.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing", + deps = [ + "//vendor/github.com/containernetworking/cni/libcni:go_default_library", + "//vendor/github.com/containernetworking/cni/pkg/types:go_default_library", + "//vendor/github.com/stretchr/testify/mock:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/testing/mock_cni.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing/mock_cni.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/testing/mock_cni.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing/mock_cni.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hairpin/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hairpin/BUILD new file mode 100644 index 000000000..94401b469 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hairpin/BUILD @@ -0,0 +1,40 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = ["hairpin.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hairpin", + deps = [ + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["hairpin_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/utils/exec:go_default_library", + "//vendor/k8s.io/utils/exec/testing:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hairpin/hairpin.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hairpin/hairpin.go similarity index 75% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/hairpin/hairpin.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hairpin/hairpin.go index fd9cdf43e..d933131ed 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hairpin/hairpin.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hairpin/hairpin.go @@ -40,29 +40,6 @@ var ( ethtoolOutputRegex = regexp.MustCompile("peer_ifindex: (\\d+)") ) -func SetUpContainerPid(containerPid int, containerInterfaceName string) error { - pidStr := fmt.Sprintf("%d", containerPid) - nsenterArgs := []string{"-t", pidStr, "-n"} - return setUpContainerInternal(containerInterfaceName, pidStr, nsenterArgs) -} - -func SetUpContainerPath(netnsPath string, containerInterfaceName string) error { - if netnsPath[0] != '/' { - return fmt.Errorf("netnsPath path '%s' was invalid", netnsPath) - } - nsenterArgs := []string{"--net=" + netnsPath} - return setUpContainerInternal(containerInterfaceName, netnsPath, nsenterArgs) -} - -func setUpContainerInternal(containerInterfaceName, containerDesc string, nsenterArgs []string) error { - e := exec.New() - hostIfName, err := findPairInterfaceOfContainerInterface(e, containerInterfaceName, containerDesc, nsenterArgs) - if err != nil { - return err - } - return setUpInterface(hostIfName) -} - func findPairInterfaceOfContainerInterface(e exec.Interface, containerInterfaceName, containerDesc string, nsenterArgs []string) (string, error) { nsenterPath, err := e.LookPath("nsenter") if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hairpin/hairpin_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hairpin/hairpin_test.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/hairpin/hairpin_test.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hairpin/hairpin_test.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/BUILD new file mode 100644 index 000000000..afd8c4292 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/BUILD @@ -0,0 +1,62 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "fake_iptables.go", + "hostport.go", + "hostport_manager.go", + "hostport_syncer.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport", + deps = [ + "//pkg/proxy/iptables:go_default_library", + "//pkg/util/conntrack:go_default_library", + "//pkg/util/iptables:go_default_library", + "//pkg/util/net:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "fake_iptables_test.go", + "hostport_manager_test.go", + "hostport_syncer_test.go", + "hostport_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//pkg/util/iptables:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/kubelet/dockershim/network/hostport/testing:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/fake_iptables.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/fake_iptables.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/fake_iptables.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/fake_iptables.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/fake_iptables_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/fake_iptables_test.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/fake_iptables_test.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/fake_iptables_test.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport.go new file mode 100644 index 000000000..e04107fa3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport.go @@ -0,0 +1,143 @@ +/* +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 hostport + +import ( + "fmt" + "net" + "strings" + + "github.com/golang/glog" + + "k8s.io/api/core/v1" + utiliptables "k8s.io/kubernetes/pkg/util/iptables" +) + +const ( + // the hostport chain + kubeHostportsChain utiliptables.Chain = "KUBE-HOSTPORTS" + // prefix for hostport chains + kubeHostportChainPrefix string = "KUBE-HP-" +) + +// PortMapping represents a network port in a container +type PortMapping struct { + Name string + HostPort int32 + ContainerPort int32 + Protocol v1.Protocol + HostIP string +} + +// PodPortMapping represents a pod's network state and associated container port mappings +type PodPortMapping struct { + Namespace string + Name string + PortMappings []*PortMapping + HostNetwork bool + IP net.IP +} + +type hostport struct { + port int32 + protocol string +} + +type hostportOpener func(*hostport) (closeable, error) + +type closeable interface { + Close() error +} + +func openLocalPort(hp *hostport) (closeable, error) { + // For ports on node IPs, open the actual port and hold it, even though we + // use iptables to redirect traffic. + // This ensures a) that it's safe to use that port and b) that (a) stays + // true. The risk is that some process on the node (e.g. sshd or kubelet) + // is using a port and we give that same port out to a Service. That would + // be bad because iptables would silently claim the traffic but the process + // would never know. + // NOTE: We should not need to have a real listen()ing socket - bind() + // should be enough, but I can't figure out a way to e2e test without + // it. Tools like 'ss' and 'netstat' do not show sockets that are + // bind()ed but not listen()ed, and at least the default debian netcat + // has no way to avoid about 10 seconds of retries. + var socket closeable + switch hp.protocol { + case "tcp": + listener, err := net.Listen("tcp", fmt.Sprintf(":%d", hp.port)) + if err != nil { + return nil, err + } + socket = listener + case "udp": + addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", hp.port)) + if err != nil { + return nil, err + } + conn, err := net.ListenUDP("udp", addr) + if err != nil { + return nil, err + } + socket = conn + default: + return nil, fmt.Errorf("unknown protocol %q", hp.protocol) + } + glog.V(3).Infof("Opened local port %s", hp.String()) + return socket, nil +} + +// portMappingToHostport creates hostport structure based on input portmapping +func portMappingToHostport(portMapping *PortMapping) hostport { + return hostport{ + port: portMapping.HostPort, + protocol: strings.ToLower(string(portMapping.Protocol)), + } +} + +// ensureKubeHostportChains ensures the KUBE-HOSTPORTS chain is setup correctly +func ensureKubeHostportChains(iptables utiliptables.Interface, natInterfaceName string) error { + glog.V(4).Info("Ensuring kubelet hostport chains") + // Ensure kubeHostportChain + if _, err := iptables.EnsureChain(utiliptables.TableNAT, kubeHostportsChain); err != nil { + return fmt.Errorf("Failed to ensure that %s chain %s exists: %v", utiliptables.TableNAT, kubeHostportsChain, err) + } + tableChainsNeedJumpServices := []struct { + table utiliptables.Table + chain utiliptables.Chain + }{ + {utiliptables.TableNAT, utiliptables.ChainOutput}, + {utiliptables.TableNAT, utiliptables.ChainPrerouting}, + } + args := []string{"-m", "comment", "--comment", "kube hostport portals", + "-m", "addrtype", "--dst-type", "LOCAL", + "-j", string(kubeHostportsChain)} + for _, tc := range tableChainsNeedJumpServices { + // KUBE-HOSTPORTS chain needs to be appended to the system chains. + // This ensures KUBE-SERVICES chain gets processed first. + // Since rules in KUBE-HOSTPORTS chain matches broader cases, allow the more specific rules to be processed first. + if _, err := iptables.EnsureRule(utiliptables.Append, tc.table, tc.chain, args...); err != nil { + return fmt.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", tc.table, tc.chain, kubeHostportsChain, err) + } + } + // Need to SNAT traffic from localhost + args = []string{"-m", "comment", "--comment", "SNAT for localhost access to hostports", "-o", natInterfaceName, "-s", "127.0.0.0/8", "-j", "MASQUERADE"} + if _, err := iptables.EnsureRule(utiliptables.Append, utiliptables.TableNAT, utiliptables.ChainPostrouting, args...); err != nil { + return fmt.Errorf("Failed to ensure that %s chain %s jumps to MASQUERADE: %v", utiliptables.TableNAT, utiliptables.ChainPostrouting, err) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_manager.go similarity index 91% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_manager.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_manager.go index 3177ac5ad..6d85c75ef 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_manager.go @@ -96,7 +96,7 @@ func (hm *hostportManager) Add(id string, podPortMapping *PodPortMapping, natInt defer hm.mu.Unlock() // try to open hostports - ports, err := openHostports(hm.portOpener, podPortMapping) + ports, err := hm.openHostports(podPortMapping) if err != nil { return err } @@ -254,8 +254,38 @@ func (hm *hostportManager) syncIPTables(lines []byte) error { return nil } +// openHostports opens all given hostports using the given hostportOpener +// If encounter any error, clean up and return the error +// If all ports are opened successfully, return the hostport and socket mapping +func (hm *hostportManager) openHostports(podPortMapping *PodPortMapping) (map[hostport]closeable, error) { + var retErr error + ports := make(map[hostport]closeable) + for _, pm := range podPortMapping.PortMappings { + if pm.HostPort <= 0 { + continue + } + hp := portMappingToHostport(pm) + socket, err := hm.portOpener(&hp) + if err != nil { + retErr = fmt.Errorf("cannot open hostport %d for pod %s: %v", pm.HostPort, getPodFullName(podPortMapping), err) + break + } + ports[hp] = socket + } + + // If encounter any error, close all hostports that just got opened. + if retErr != nil { + for hp, socket := range ports { + if err := socket.Close(); err != nil { + glog.Errorf("Cannot clean up hostport %d for pod %s: %v", hp.port, getPodFullName(podPortMapping), err) + } + } + return nil, retErr + } + return ports, nil +} + // closeHostports tries to close all the listed host ports -// TODO: move closeHostports and openHostports into a common struct func (hm *hostportManager) closeHostports(hostportMappings []*PortMapping) error { errList := []error{} for _, pm := range hostportMappings { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_manager_test.go new file mode 100644 index 000000000..1b3b460cb --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_manager_test.go @@ -0,0 +1,335 @@ +/* +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 hostport + +import ( + "bytes" + "net" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/api/core/v1" + utiliptables "k8s.io/kubernetes/pkg/util/iptables" + "k8s.io/utils/exec" +) + +func TestOpenCloseHostports(t *testing.T) { + openPortCases := []struct { + podPortMapping *PodPortMapping + expectError bool + }{ + { + &PodPortMapping{ + Namespace: "ns1", + Name: "n0", + }, + false, + }, + { + &PodPortMapping{ + Namespace: "ns1", + Name: "n1", + PortMappings: []*PortMapping{ + {HostPort: 80, Protocol: v1.Protocol("TCP")}, + {HostPort: 8080, Protocol: v1.Protocol("TCP")}, + {HostPort: 443, Protocol: v1.Protocol("TCP")}, + }, + }, + false, + }, + { + &PodPortMapping{ + Namespace: "ns1", + Name: "n2", + PortMappings: []*PortMapping{ + {HostPort: 80, Protocol: v1.Protocol("TCP")}, + }, + }, + true, + }, + { + &PodPortMapping{ + Namespace: "ns1", + Name: "n3", + PortMappings: []*PortMapping{ + {HostPort: 8081, Protocol: v1.Protocol("TCP")}, + {HostPort: 8080, Protocol: v1.Protocol("TCP")}, + }, + }, + true, + }, + { + &PodPortMapping{ + Namespace: "ns1", + Name: "n3", + PortMappings: []*PortMapping{ + {HostPort: 8081, Protocol: v1.Protocol("TCP")}, + }, + }, + false, + }, + } + + iptables := NewFakeIPTables() + portOpener := NewFakeSocketManager() + manager := &hostportManager{ + hostPortMap: make(map[hostport]closeable), + iptables: iptables, + portOpener: portOpener.openFakeSocket, + execer: exec.New(), + } + + for _, tc := range openPortCases { + mapping, err := manager.openHostports(tc.podPortMapping) + if tc.expectError { + assert.Error(t, err) + continue + } + assert.NoError(t, err) + assert.EqualValues(t, len(mapping), len(tc.podPortMapping.PortMappings)) + } + + // We have 4 ports: 80, 443, 8080, 8081 open now. + closePortCases := []struct { + portMappings []*PortMapping + expectError bool + }{ + { + portMappings: nil, + }, + { + + portMappings: []*PortMapping{ + {HostPort: 80, Protocol: v1.Protocol("TCP")}, + {HostPort: 8080, Protocol: v1.Protocol("TCP")}, + {HostPort: 443, Protocol: v1.Protocol("TCP")}, + }, + }, + { + + portMappings: []*PortMapping{ + {HostPort: 80, Protocol: v1.Protocol("TCP")}, + }, + }, + { + portMappings: []*PortMapping{ + {HostPort: 8081, Protocol: v1.Protocol("TCP")}, + {HostPort: 8080, Protocol: v1.Protocol("TCP")}, + }, + }, + { + portMappings: []*PortMapping{ + {HostPort: 8081, Protocol: v1.Protocol("TCP")}, + }, + }, + { + portMappings: []*PortMapping{ + {HostPort: 7070, Protocol: v1.Protocol("TCP")}, + }, + }, + } + + for _, tc := range closePortCases { + err := manager.closeHostports(tc.portMappings) + if tc.expectError { + assert.Error(t, err) + continue + } + assert.NoError(t, err) + } + // Clear all elements in hostPortMap + assert.Zero(t, len(manager.hostPortMap)) +} + +func TestHostportManager(t *testing.T) { + iptables := NewFakeIPTables() + portOpener := NewFakeSocketManager() + manager := &hostportManager{ + hostPortMap: make(map[hostport]closeable), + iptables: iptables, + portOpener: portOpener.openFakeSocket, + execer: exec.New(), + } + + testCases := []struct { + mapping *PodPortMapping + expectError bool + }{ + { + mapping: &PodPortMapping{ + Name: "pod1", + Namespace: "ns1", + IP: net.ParseIP("10.1.1.2"), + HostNetwork: false, + PortMappings: []*PortMapping{ + { + HostPort: 8080, + ContainerPort: 80, + Protocol: v1.ProtocolTCP, + }, + { + HostPort: 8081, + ContainerPort: 81, + Protocol: v1.ProtocolUDP, + }, + }, + }, + expectError: false, + }, + { + mapping: &PodPortMapping{ + Name: "pod2", + Namespace: "ns1", + IP: net.ParseIP("10.1.1.3"), + HostNetwork: false, + PortMappings: []*PortMapping{ + { + HostPort: 8082, + ContainerPort: 80, + Protocol: v1.ProtocolTCP, + }, + { + HostPort: 8081, + ContainerPort: 81, + Protocol: v1.ProtocolUDP, + }, + }, + }, + expectError: true, + }, + { + mapping: &PodPortMapping{ + Name: "pod3", + Namespace: "ns1", + IP: net.ParseIP("10.1.1.4"), + HostNetwork: false, + PortMappings: []*PortMapping{ + { + HostPort: 8443, + ContainerPort: 443, + Protocol: v1.ProtocolTCP, + }, + }, + }, + expectError: false, + }, + } + + // Add Hostports + for _, tc := range testCases { + err := manager.Add("id", tc.mapping, "cbr0") + if tc.expectError { + assert.Error(t, err) + continue + } + assert.NoError(t, err) + } + + // Check port opened + expectedPorts := []hostport{{8080, "tcp"}, {8081, "udp"}, {8443, "tcp"}} + openedPorts := make(map[hostport]bool) + for hp, port := range portOpener.mem { + if !port.closed { + openedPorts[hp] = true + } + } + assert.EqualValues(t, len(openedPorts), len(expectedPorts)) + for _, hp := range expectedPorts { + _, ok := openedPorts[hp] + assert.EqualValues(t, true, ok) + } + + // Check Iptables-save result after adding hostports + raw := bytes.NewBuffer(nil) + err := iptables.SaveInto(utiliptables.TableNAT, raw) + assert.NoError(t, err) + + lines := strings.Split(string(raw.Bytes()), "\n") + expectedLines := map[string]bool{ + `*nat`: true, + `:KUBE-HOSTPORTS - [0:0]`: true, + `:OUTPUT - [0:0]`: true, + `:PREROUTING - [0:0]`: true, + `:POSTROUTING - [0:0]`: true, + `:KUBE-HP-IJHALPHTORMHHPPK - [0:0]`: true, + `:KUBE-HP-63UPIDJXVRSZGSUZ - [0:0]`: true, + `:KUBE-HP-WFBOALXEP42XEMJK - [0:0]`: true, + "-A KUBE-HOSTPORTS -m comment --comment \"pod3_ns1 hostport 8443\" -m tcp -p tcp --dport 8443 -j KUBE-HP-WFBOALXEP42XEMJK": true, + "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8081\" -m udp -p udp --dport 8081 -j KUBE-HP-63UPIDJXVRSZGSUZ": true, + "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8080\" -m tcp -p tcp --dport 8080 -j KUBE-HP-IJHALPHTORMHHPPK": true, + "-A OUTPUT -m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS": true, + "-A PREROUTING -m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS": true, + "-A POSTROUTING -m comment --comment \"SNAT for localhost access to hostports\" -o cbr0 -s 127.0.0.0/8 -j MASQUERADE": true, + "-A KUBE-HP-IJHALPHTORMHHPPK -m comment --comment \"pod1_ns1 hostport 8080\" -s 10.1.1.2/32 -j KUBE-MARK-MASQ": true, + "-A KUBE-HP-IJHALPHTORMHHPPK -m comment --comment \"pod1_ns1 hostport 8080\" -m tcp -p tcp -j DNAT --to-destination 10.1.1.2:80": true, + "-A KUBE-HP-63UPIDJXVRSZGSUZ -m comment --comment \"pod1_ns1 hostport 8081\" -s 10.1.1.2/32 -j KUBE-MARK-MASQ": true, + "-A KUBE-HP-63UPIDJXVRSZGSUZ -m comment --comment \"pod1_ns1 hostport 8081\" -m udp -p udp -j DNAT --to-destination 10.1.1.2:81": true, + "-A KUBE-HP-WFBOALXEP42XEMJK -m comment --comment \"pod3_ns1 hostport 8443\" -s 10.1.1.4/32 -j KUBE-MARK-MASQ": true, + "-A KUBE-HP-WFBOALXEP42XEMJK -m comment --comment \"pod3_ns1 hostport 8443\" -m tcp -p tcp -j DNAT --to-destination 10.1.1.4:443": true, + `COMMIT`: true, + } + for _, line := range lines { + if len(strings.TrimSpace(line)) > 0 { + _, ok := expectedLines[strings.TrimSpace(line)] + assert.EqualValues(t, true, ok) + } + } + + // Remove all added hostports + for _, tc := range testCases { + if !tc.expectError { + err := manager.Remove("id", tc.mapping) + assert.NoError(t, err) + } + } + + // Check Iptables-save result after deleting hostports + raw.Reset() + err = iptables.SaveInto(utiliptables.TableNAT, raw) + assert.NoError(t, err) + lines = strings.Split(string(raw.Bytes()), "\n") + remainingChains := make(map[string]bool) + for _, line := range lines { + if strings.HasPrefix(line, ":") { + remainingChains[strings.TrimSpace(line)] = true + } + } + expectDeletedChains := []string{"KUBE-HP-4YVONL46AKYWSKS3", "KUBE-HP-7THKRFSEH4GIIXK7", "KUBE-HP-5N7UH5JAXCVP5UJR"} + for _, chain := range expectDeletedChains { + _, ok := remainingChains[chain] + assert.EqualValues(t, false, ok) + } + + // check if all ports are closed + for _, port := range portOpener.mem { + assert.EqualValues(t, true, port.closed) + } +} + +func TestGetHostportChain(t *testing.T) { + m := make(map[string]int) + chain := getHostportChain("testrdma-2", &PortMapping{HostPort: 57119, Protocol: "TCP", ContainerPort: 57119}) + m[string(chain)] = 1 + chain = getHostportChain("testrdma-2", &PortMapping{HostPort: 55429, Protocol: "TCP", ContainerPort: 55429}) + m[string(chain)] = 1 + chain = getHostportChain("testrdma-2", &PortMapping{HostPort: 56833, Protocol: "TCP", ContainerPort: 56833}) + m[string(chain)] = 1 + if len(m) != 3 { + t.Fatal(m) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_syncer.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_syncer.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_syncer.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_syncer.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_syncer_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_syncer_test.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_syncer_test.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_syncer_test.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_test.go new file mode 100644 index 000000000..97dd907c3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/hostport_test.go @@ -0,0 +1,82 @@ +/* +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 hostport + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + utiliptables "k8s.io/kubernetes/pkg/util/iptables" +) + +type fakeSocket struct { + port int32 + protocol string + closed bool +} + +func (f *fakeSocket) Close() error { + if f.closed { + return fmt.Errorf("Socket %q.%s already closed!", f.port, f.protocol) + } + f.closed = true + return nil +} + +func NewFakeSocketManager() *fakeSocketManager { + return &fakeSocketManager{mem: make(map[hostport]*fakeSocket)} +} + +type fakeSocketManager struct { + mem map[hostport]*fakeSocket +} + +func (f *fakeSocketManager) openFakeSocket(hp *hostport) (closeable, error) { + if socket, ok := f.mem[*hp]; ok && !socket.closed { + return nil, fmt.Errorf("hostport is occupied") + } + fs := &fakeSocket{hp.port, hp.protocol, false} + f.mem[*hp] = fs + return fs, nil +} + +func TestEnsureKubeHostportChains(t *testing.T) { + interfaceName := "cbr0" + builtinChains := []string{"PREROUTING", "OUTPUT"} + jumpRule := "-m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS" + masqRule := "-m comment --comment \"SNAT for localhost access to hostports\" -o cbr0 -s 127.0.0.0/8 -j MASQUERADE" + + fakeIPTables := NewFakeIPTables() + assert.NoError(t, ensureKubeHostportChains(fakeIPTables, interfaceName)) + + _, _, err := fakeIPTables.getChain(utiliptables.TableNAT, utiliptables.Chain("KUBE-HOSTPORTS")) + assert.NoError(t, err) + + _, chain, err := fakeIPTables.getChain(utiliptables.TableNAT, utiliptables.ChainPostrouting) + assert.NoError(t, err) + assert.EqualValues(t, len(chain.rules), 1) + assert.Contains(t, chain.rules[0], masqRule) + + for _, chainName := range builtinChains { + _, chain, err := fakeIPTables.getChain(utiliptables.TableNAT, utiliptables.Chain(chainName)) + assert.NoError(t, err) + assert.EqualValues(t, len(chain.rules), 1) + assert.Contains(t, chain.rules[0], jumpRule) + } + +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/testing/BUILD new file mode 100644 index 000000000..2df330347 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/testing/BUILD @@ -0,0 +1,26 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["fake.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/testing", + deps = ["//pkg/kubelet/dockershim/network/hostport:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/testing/fake.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/testing/fake.go new file mode 100644 index 000000000..1d14c02ed --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/testing/fake.go @@ -0,0 +1,43 @@ +/* +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 testing + +import ( + "fmt" + + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" +) + +type fakeSyncer struct{} + +func NewFakeHostportSyncer() hostport.HostportSyncer { + return &fakeSyncer{} +} + +func (h *fakeSyncer) OpenPodHostportsAndSync(newPortMapping *hostport.PodPortMapping, natInterfaceName string, activePortMapping []*hostport.PodPortMapping) error { + return h.SyncHostports(natInterfaceName, activePortMapping) +} + +func (h *fakeSyncer) SyncHostports(natInterfaceName string, activePortMapping []*hostport.PodPortMapping) error { + for _, r := range activePortMapping { + if r.IP.To4() == nil { + return fmt.Errorf("Invalid or missing pod %s/%s IP", r.Namespace, r.Name) + } + } + + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/BUILD new file mode 100644 index 000000000..869f297b6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/BUILD @@ -0,0 +1,166 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "kubenet.go", + ] + select({ + "@io_bazel_rules_go//go/platform:android": [ + "kubenet_unsupported.go", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "kubenet_unsupported.go", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "kubenet_unsupported.go", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "kubenet_unsupported.go", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "kubenet_linux.go", + ], + "@io_bazel_rules_go//go/platform:nacl": [ + "kubenet_unsupported.go", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "kubenet_unsupported.go", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "kubenet_unsupported.go", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "kubenet_unsupported.go", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "kubenet_unsupported.go", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "kubenet_unsupported.go", + ], + "//conditions:default": [], + }), + importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet", + deps = select({ + "@io_bazel_rules_go//go/platform:android": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + "//pkg/kubelet/dockershim/network/hostport:go_default_library", + "//pkg/util/bandwidth:go_default_library", + "//pkg/util/dbus:go_default_library", + "//pkg/util/ebtables:go_default_library", + "//pkg/util/iptables:go_default_library", + "//pkg/util/sysctl:go_default_library", + "//vendor/github.com/containernetworking/cni/libcni:go_default_library", + "//vendor/github.com/containernetworking/cni/pkg/types:go_default_library", + "//vendor/github.com/containernetworking/cni/pkg/types/020:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/vishvananda/netlink:go_default_library", + "//vendor/golang.org/x/sys/unix:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + ], + "@io_bazel_rules_go//go/platform:nacl": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + ], + "//conditions:default": [], + }), +) + +go_test( + name = "go_default_test", + srcs = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "kubenet_linux_test.go", + ], + "//conditions:default": [], + }), + embed = [":go_default_library"], + deps = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + "//pkg/kubelet/dockershim/network/cni/testing:go_default_library", + "//pkg/kubelet/dockershim/network/hostport/testing:go_default_library", + "//pkg/kubelet/dockershim/network/testing:go_default_library", + "//pkg/util/bandwidth:go_default_library", + "//pkg/util/iptables/testing:go_default_library", + "//pkg/util/sysctl/testing:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/github.com/stretchr/testify/mock:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + "//vendor/k8s.io/utils/exec/testing: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"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet_linux.go new file mode 100644 index 000000000..cb9452b24 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet_linux.go @@ -0,0 +1,688 @@ +// +build linux + +/* +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 kubenet + +import ( + "fmt" + "io/ioutil" + "net" + "strings" + "sync" + "time" + + "github.com/containernetworking/cni/libcni" + cnitypes "github.com/containernetworking/cni/pkg/types" + cnitypes020 "github.com/containernetworking/cni/pkg/types/020" + "github.com/golang/glog" + "github.com/vishvananda/netlink" + "golang.org/x/sys/unix" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + utilnet "k8s.io/apimachinery/pkg/util/net" + utilsets "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" + kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" + "k8s.io/kubernetes/pkg/util/bandwidth" + utildbus "k8s.io/kubernetes/pkg/util/dbus" + utilebtables "k8s.io/kubernetes/pkg/util/ebtables" + utiliptables "k8s.io/kubernetes/pkg/util/iptables" + utilsysctl "k8s.io/kubernetes/pkg/util/sysctl" + utilexec "k8s.io/utils/exec" +) + +const ( + BridgeName = "cbr0" + DefaultCNIDir = "/opt/cni/bin" + + sysctlBridgeCallIPTables = "net/bridge/bridge-nf-call-iptables" + + // fallbackMTU is used if an MTU is not specified, and we cannot determine the MTU + fallbackMTU = 1460 + + // ebtables Chain to store dedup rules + dedupChain = utilebtables.Chain("KUBE-DEDUP") + + // defaultIPAMDir is the default location for the checkpoint files stored by host-local ipam + // https://github.com/containernetworking/cni/tree/master/plugins/ipam/host-local#backends + defaultIPAMDir = "/var/lib/cni/networks" +) + +// CNI plugins required by kubenet in /opt/cni/bin or user-specified directory +var requiredCNIPlugins = [...]string{"bridge", "host-local", "loopback"} + +type kubenetNetworkPlugin struct { + network.NoopNetworkPlugin + + host network.Host + netConfig *libcni.NetworkConfig + loConfig *libcni.NetworkConfig + cniConfig libcni.CNI + bandwidthShaper bandwidth.BandwidthShaper + mu sync.Mutex //Mutex for protecting podIPs map, netConfig, and shaper initialization + podIPs map[kubecontainer.ContainerID]string + mtu int + execer utilexec.Interface + nsenterPath string + hairpinMode kubeletconfig.HairpinMode + // kubenet can use either hostportSyncer and hostportManager to implement hostports + // Currently, if network host supports legacy features, hostportSyncer will be used, + // otherwise, hostportManager will be used. + hostportSyncer hostport.HostportSyncer + hostportManager hostport.HostPortManager + iptables utiliptables.Interface + sysctl utilsysctl.Interface + ebtables utilebtables.Interface + // binDirs is passed by kubelet cni-bin-dir parameter. + // kubenet will search for CNI binaries in DefaultCNIDir first, then continue to binDirs. + binDirs []string + nonMasqueradeCIDR string + podCidr string + gateway net.IP +} + +func NewPlugin(networkPluginDirs []string) network.NetworkPlugin { + protocol := utiliptables.ProtocolIpv4 + execer := utilexec.New() + dbus := utildbus.New() + sysctl := utilsysctl.New() + iptInterface := utiliptables.New(execer, dbus, protocol) + return &kubenetNetworkPlugin{ + podIPs: make(map[kubecontainer.ContainerID]string), + execer: utilexec.New(), + iptables: iptInterface, + sysctl: sysctl, + binDirs: append([]string{DefaultCNIDir}, networkPluginDirs...), + hostportSyncer: hostport.NewHostportSyncer(iptInterface), + hostportManager: hostport.NewHostportManager(iptInterface), + nonMasqueradeCIDR: "10.0.0.0/8", + } +} + +func (plugin *kubenetNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { + plugin.host = host + plugin.hairpinMode = hairpinMode + plugin.nonMasqueradeCIDR = nonMasqueradeCIDR + plugin.cniConfig = &libcni.CNIConfig{Path: plugin.binDirs} + + if mtu == network.UseDefaultMTU { + if link, err := findMinMTU(); err == nil { + plugin.mtu = link.MTU + glog.V(5).Infof("Using interface %s MTU %d as bridge MTU", link.Name, link.MTU) + } else { + plugin.mtu = fallbackMTU + glog.Warningf("Failed to find default bridge MTU, using %d: %v", fallbackMTU, err) + } + } else { + plugin.mtu = mtu + } + + // Since this plugin uses a Linux bridge, set bridge-nf-call-iptables=1 + // is necessary to ensure kube-proxy functions correctly. + // + // This will return an error on older kernel version (< 3.18) as the module + // was built-in, we simply ignore the error here. A better thing to do is + // to check the kernel version in the future. + plugin.execer.Command("modprobe", "br-netfilter").CombinedOutput() + err := plugin.sysctl.SetSysctl(sysctlBridgeCallIPTables, 1) + if err != nil { + glog.Warningf("can't set sysctl %s: %v", sysctlBridgeCallIPTables, err) + } + + plugin.loConfig, err = libcni.ConfFromBytes([]byte(`{ + "cniVersion": "0.1.0", + "name": "kubenet-loopback", + "type": "loopback" +}`)) + if err != nil { + return fmt.Errorf("Failed to generate loopback config: %v", err) + } + + plugin.nsenterPath, err = plugin.execer.LookPath("nsenter") + if err != nil { + return fmt.Errorf("Failed to find nsenter binary: %v", err) + } + + // Need to SNAT outbound traffic from cluster + if err = plugin.ensureMasqRule(); err != nil { + return err + } + return nil +} + +// TODO: move thic logic into cni bridge plugin and remove this from kubenet +func (plugin *kubenetNetworkPlugin) ensureMasqRule() error { + if plugin.nonMasqueradeCIDR != "0.0.0.0/0" { + if _, err := plugin.iptables.EnsureRule(utiliptables.Append, utiliptables.TableNAT, utiliptables.ChainPostrouting, + "-m", "comment", "--comment", "kubenet: SNAT for outbound traffic from cluster", + "-m", "addrtype", "!", "--dst-type", "LOCAL", + "!", "-d", plugin.nonMasqueradeCIDR, + "-j", "MASQUERADE"); err != nil { + return fmt.Errorf("Failed to ensure that %s chain %s jumps to MASQUERADE: %v", utiliptables.TableNAT, utiliptables.ChainPostrouting, err) + } + } + return nil +} + +func findMinMTU() (*net.Interface, error) { + intfs, err := net.Interfaces() + if err != nil { + return nil, err + } + + mtu := 999999 + defIntfIndex := -1 + for i, intf := range intfs { + if ((intf.Flags & net.FlagUp) != 0) && (intf.Flags&(net.FlagLoopback|net.FlagPointToPoint) == 0) { + if intf.MTU < mtu { + mtu = intf.MTU + defIntfIndex = i + } + } + } + + if mtu >= 999999 || mtu < 576 || defIntfIndex < 0 { + return nil, fmt.Errorf("no suitable interface: %v", BridgeName) + } + + return &intfs[defIntfIndex], nil +} + +const NET_CONFIG_TEMPLATE = `{ + "cniVersion": "0.1.0", + "name": "kubenet", + "type": "bridge", + "bridge": "%s", + "mtu": %d, + "addIf": "%s", + "isGateway": true, + "ipMasq": false, + "hairpinMode": %t, + "ipam": { + "type": "host-local", + "subnet": "%s", + "gateway": "%s", + "routes": [ + { "dst": "0.0.0.0/0" } + ] + } +}` + +func (plugin *kubenetNetworkPlugin) Event(name string, details map[string]interface{}) { + if name != network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE { + return + } + + plugin.mu.Lock() + defer plugin.mu.Unlock() + + podCIDR, ok := details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR].(string) + if !ok { + glog.Warningf("%s event didn't contain pod CIDR", network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE) + return + } + + if plugin.netConfig != nil { + glog.Warningf("Ignoring subsequent pod CIDR update to %s", podCIDR) + return + } + + glog.V(5).Infof("PodCIDR is set to %q", podCIDR) + _, cidr, err := net.ParseCIDR(podCIDR) + if err == nil { + setHairpin := plugin.hairpinMode == kubeletconfig.HairpinVeth + // Set bridge address to first address in IPNet + cidr.IP[len(cidr.IP)-1] += 1 + + json := fmt.Sprintf(NET_CONFIG_TEMPLATE, BridgeName, plugin.mtu, network.DefaultInterfaceName, setHairpin, podCIDR, cidr.IP.String()) + glog.V(2).Infof("CNI network config set to %v", json) + plugin.netConfig, err = libcni.ConfFromBytes([]byte(json)) + if err == nil { + glog.V(5).Infof("CNI network config:\n%s", json) + + // Ensure cbr0 has no conflicting addresses; CNI's 'bridge' + // plugin will bail out if the bridge has an unexpected one + plugin.clearBridgeAddressesExcept(cidr) + } + plugin.podCidr = podCIDR + plugin.gateway = cidr.IP + } + + if err != nil { + glog.Warningf("Failed to generate CNI network config: %v", err) + } +} + +func (plugin *kubenetNetworkPlugin) clearBridgeAddressesExcept(keep *net.IPNet) { + bridge, err := netlink.LinkByName(BridgeName) + if err != nil { + return + } + + addrs, err := netlink.AddrList(bridge, unix.AF_INET) + if err != nil { + return + } + + for _, addr := range addrs { + if !utilnet.IPNetEqual(addr.IPNet, keep) { + glog.V(2).Infof("Removing old address %s from %s", addr.IPNet.String(), BridgeName) + netlink.AddrDel(bridge, &addr) + } + } +} + +func (plugin *kubenetNetworkPlugin) Name() string { + return KubenetPluginName +} + +func (plugin *kubenetNetworkPlugin) Capabilities() utilsets.Int { + return utilsets.NewInt() +} + +// setup sets up networking through CNI using the given ns/name and sandbox ID. +func (plugin *kubenetNetworkPlugin) setup(namespace string, name string, id kubecontainer.ContainerID, annotations map[string]string) error { + // Disable DAD so we skip the kernel delay on bringing up new interfaces. + if err := plugin.disableContainerDAD(id); err != nil { + glog.V(3).Infof("Failed to disable DAD in container: %v", err) + } + + // Bring up container loopback interface + if _, err := plugin.addContainerToNetwork(plugin.loConfig, "lo", namespace, name, id); err != nil { + return err + } + + // Hook container up with our bridge + resT, err := plugin.addContainerToNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id) + if err != nil { + return err + } + // Coerce the CNI result version + res, err := cnitypes020.GetResult(resT) + if err != nil { + return fmt.Errorf("unable to understand network config: %v", err) + } + if res.IP4 == nil { + return fmt.Errorf("CNI plugin reported no IPv4 address for container %v.", id) + } + ip4 := res.IP4.IP.IP.To4() + if ip4 == nil { + return fmt.Errorf("CNI plugin reported an invalid IPv4 address for container %v: %+v.", id, res.IP4) + } + + // Put the container bridge into promiscuous mode to force it to accept hairpin packets. + // TODO: Remove this once the kernel bug (#20096) is fixed. + if plugin.hairpinMode == kubeletconfig.PromiscuousBridge { + link, err := netlink.LinkByName(BridgeName) + if err != nil { + return fmt.Errorf("failed to lookup %q: %v", BridgeName, err) + } + if link.Attrs().Promisc != 1 { + // promiscuous mode is not on, then turn it on. + err := netlink.SetPromiscOn(link) + if err != nil { + return fmt.Errorf("Error setting promiscuous mode on %s: %v", BridgeName, err) + } + } + + // configure the ebtables rules to eliminate duplicate packets by best effort + plugin.syncEbtablesDedupRules(link.Attrs().HardwareAddr) + } + + plugin.podIPs[id] = ip4.String() + + // The first SetUpPod call creates the bridge; get a shaper for the sake of initialization + // TODO: replace with CNI traffic shaper plugin + shaper := plugin.shaper() + ingress, egress, err := bandwidth.ExtractPodBandwidthResources(annotations) + if err != nil { + return fmt.Errorf("Error reading pod bandwidth annotations: %v", err) + } + if egress != nil || ingress != nil { + if err := shaper.ReconcileCIDR(fmt.Sprintf("%s/32", ip4.String()), egress, ingress); err != nil { + return fmt.Errorf("Failed to add pod to shaper: %v", err) + } + } + + // TODO: replace with CNI port-forwarding plugin + portMappings, err := plugin.host.GetPodPortMappings(id.ID) + if err != nil { + return err + } + if portMappings != nil && len(portMappings) > 0 { + if err := plugin.hostportManager.Add(id.ID, &hostport.PodPortMapping{ + Namespace: namespace, + Name: name, + PortMappings: portMappings, + IP: ip4, + HostNetwork: false, + }, BridgeName); err != nil { + return err + } + } + return nil +} + +func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID, annotations map[string]string) error { + plugin.mu.Lock() + defer plugin.mu.Unlock() + + start := time.Now() + defer func() { + glog.V(4).Infof("SetUpPod took %v for %s/%s", time.Since(start), namespace, name) + }() + + if err := plugin.Status(); err != nil { + return fmt.Errorf("Kubenet cannot SetUpPod: %v", err) + } + + if err := plugin.setup(namespace, name, id, annotations); err != nil { + // Make sure everything gets cleaned up on errors + podIP, _ := plugin.podIPs[id] + if err := plugin.teardown(namespace, name, id, podIP); err != nil { + // Not a hard error or warning + glog.V(4).Infof("Failed to clean up %s/%s after SetUpPod failure: %v", namespace, name, err) + } + return err + } + + // Need to SNAT outbound traffic from cluster + if err := plugin.ensureMasqRule(); err != nil { + glog.Errorf("Failed to ensure MASQ rule: %v", err) + } + + return nil +} + +// Tears down as much of a pod's network as it can even if errors occur. Returns +// an aggregate error composed of all errors encountered during the teardown. +func (plugin *kubenetNetworkPlugin) teardown(namespace string, name string, id kubecontainer.ContainerID, podIP string) error { + errList := []error{} + + if podIP != "" { + glog.V(5).Infof("Removing pod IP %s from shaper", podIP) + // shaper wants /32 + if err := plugin.shaper().Reset(fmt.Sprintf("%s/32", podIP)); err != nil { + // Possible bandwidth shaping wasn't enabled for this pod anyways + glog.V(4).Infof("Failed to remove pod IP %s from shaper: %v", podIP, err) + } + + delete(plugin.podIPs, id) + } + + if err := plugin.delContainerFromNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id); err != nil { + // This is to prevent returning error when TearDownPod is called twice on the same pod. This helps to reduce event pollution. + if podIP != "" { + glog.Warningf("Failed to delete container from kubenet: %v", err) + } else { + errList = append(errList, err) + } + } + + portMappings, err := plugin.host.GetPodPortMappings(id.ID) + if err != nil { + errList = append(errList, err) + } else if portMappings != nil && len(portMappings) > 0 { + if err = plugin.hostportManager.Remove(id.ID, &hostport.PodPortMapping{ + Namespace: namespace, + Name: name, + PortMappings: portMappings, + HostNetwork: false, + }); err != nil { + errList = append(errList, err) + } + } + return utilerrors.NewAggregate(errList) +} + +func (plugin *kubenetNetworkPlugin) TearDownPod(namespace string, name string, id kubecontainer.ContainerID) error { + plugin.mu.Lock() + defer plugin.mu.Unlock() + + start := time.Now() + defer func() { + glog.V(4).Infof("TearDownPod took %v for %s/%s", time.Since(start), namespace, name) + }() + + if plugin.netConfig == nil { + return fmt.Errorf("Kubenet needs a PodCIDR to tear down pods") + } + + // no cached IP is Ok during teardown + podIP, _ := plugin.podIPs[id] + if err := plugin.teardown(namespace, name, id, podIP); err != nil { + return err + } + + // Need to SNAT outbound traffic from cluster + if err := plugin.ensureMasqRule(); err != nil { + glog.Errorf("Failed to ensure MASQ rule: %v", err) + } + + return nil +} + +// TODO: Use the addToNetwork function to obtain the IP of the Pod. That will assume idempotent ADD call to the plugin. +// Also fix the runtime's call to Status function to be done only in the case that the IP is lost, no need to do periodic calls +func (plugin *kubenetNetworkPlugin) GetPodNetworkStatus(namespace string, name string, id kubecontainer.ContainerID) (*network.PodNetworkStatus, error) { + plugin.mu.Lock() + defer plugin.mu.Unlock() + // Assuming the ip of pod does not change. Try to retrieve ip from kubenet map first. + if podIP, ok := plugin.podIPs[id]; ok { + return &network.PodNetworkStatus{IP: net.ParseIP(podIP)}, nil + } + + netnsPath, err := plugin.host.GetNetNS(id.ID) + if err != nil { + return nil, fmt.Errorf("Kubenet failed to retrieve network namespace path: %v", err) + } + if netnsPath == "" { + return nil, fmt.Errorf("Cannot find the network namespace, skipping pod network status for container %q", id) + } + ip, err := network.GetPodIP(plugin.execer, plugin.nsenterPath, netnsPath, network.DefaultInterfaceName) + if err != nil { + return nil, err + } + + plugin.podIPs[id] = ip.String() + return &network.PodNetworkStatus{IP: ip}, nil +} + +func (plugin *kubenetNetworkPlugin) Status() error { + // Can't set up pods if we don't have a PodCIDR yet + if plugin.netConfig == nil { + return fmt.Errorf("Kubenet does not have netConfig. This is most likely due to lack of PodCIDR") + } + + if !plugin.checkRequiredCNIPlugins() { + return fmt.Errorf("could not locate kubenet required CNI plugins %v at %q", requiredCNIPlugins, plugin.binDirs) + } + return nil +} + +// checkRequiredCNIPlugins returns if all kubenet required cni plugins can be found at /opt/cni/bin or user specified NetworkPluginDir. +func (plugin *kubenetNetworkPlugin) checkRequiredCNIPlugins() bool { + for _, dir := range plugin.binDirs { + if plugin.checkRequiredCNIPluginsInOneDir(dir) { + return true + } + } + return false +} + +// checkRequiredCNIPluginsInOneDir returns true if all required cni plugins are placed in dir +func (plugin *kubenetNetworkPlugin) checkRequiredCNIPluginsInOneDir(dir string) bool { + files, err := ioutil.ReadDir(dir) + if err != nil { + return false + } + for _, cniPlugin := range requiredCNIPlugins { + found := false + for _, file := range files { + if strings.TrimSpace(file.Name()) == cniPlugin { + found = true + break + } + } + if !found { + return false + } + } + return true +} + +func (plugin *kubenetNetworkPlugin) buildCNIRuntimeConf(ifName string, id kubecontainer.ContainerID, needNetNs bool) (*libcni.RuntimeConf, error) { + netnsPath, err := plugin.host.GetNetNS(id.ID) + if needNetNs && err != nil { + glog.Errorf("Kubenet failed to retrieve network namespace path: %v", err) + } + + return &libcni.RuntimeConf{ + ContainerID: id.ID, + NetNS: netnsPath, + IfName: ifName, + }, nil +} + +func (plugin *kubenetNetworkPlugin) addContainerToNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) (cnitypes.Result, error) { + rt, err := plugin.buildCNIRuntimeConf(ifName, id, true) + if err != nil { + return nil, fmt.Errorf("Error building CNI config: %v", err) + } + + glog.V(3).Infof("Adding %s/%s to '%s' with CNI '%s' plugin and runtime: %+v", namespace, name, config.Network.Name, config.Network.Type, rt) + // The network plugin can take up to 3 seconds to execute, + // so yield the lock while it runs. + plugin.mu.Unlock() + res, err := plugin.cniConfig.AddNetwork(config, rt) + plugin.mu.Lock() + if err != nil { + return nil, fmt.Errorf("Error adding container to network: %v", err) + } + return res, nil +} + +func (plugin *kubenetNetworkPlugin) delContainerFromNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) error { + rt, err := plugin.buildCNIRuntimeConf(ifName, id, false) + if err != nil { + return fmt.Errorf("Error building CNI config: %v", err) + } + + glog.V(3).Infof("Removing %s/%s from '%s' with CNI '%s' plugin and runtime: %+v", namespace, name, config.Network.Name, config.Network.Type, rt) + err = plugin.cniConfig.DelNetwork(config, rt) + // The pod may not get deleted successfully at the first time. + // Ignore "no such file or directory" error in case the network has already been deleted in previous attempts. + if err != nil && !strings.Contains(err.Error(), "no such file or directory") { + return fmt.Errorf("Error removing container from network: %v", err) + } + return nil +} + +// shaper retrieves the bandwidth shaper and, if it hasn't been fetched before, +// initializes it and ensures the bridge is appropriately configured +// This function should only be called while holding the `plugin.mu` lock +func (plugin *kubenetNetworkPlugin) shaper() bandwidth.BandwidthShaper { + if plugin.bandwidthShaper == nil { + plugin.bandwidthShaper = bandwidth.NewTCShaper(BridgeName) + plugin.bandwidthShaper.ReconcileInterface() + } + return plugin.bandwidthShaper +} + +//TODO: make this into a goroutine and rectify the dedup rules periodically +func (plugin *kubenetNetworkPlugin) syncEbtablesDedupRules(macAddr net.HardwareAddr) { + if plugin.ebtables == nil { + plugin.ebtables = utilebtables.New(plugin.execer) + glog.V(3).Infof("Flushing dedup chain") + if err := plugin.ebtables.FlushChain(utilebtables.TableFilter, dedupChain); err != nil { + glog.Errorf("Failed to flush dedup chain: %v", err) + } + } + _, err := plugin.ebtables.GetVersion() + if err != nil { + glog.Warningf("Failed to get ebtables version. Skip syncing ebtables dedup rules: %v", err) + return + } + + glog.V(3).Infof("Filtering packets with ebtables on mac address: %v, gateway: %v, pod CIDR: %v", macAddr.String(), plugin.gateway.String(), plugin.podCidr) + _, err = plugin.ebtables.EnsureChain(utilebtables.TableFilter, dedupChain) + if err != nil { + glog.Errorf("Failed to ensure %v chain %v", utilebtables.TableFilter, dedupChain) + return + } + + _, err = plugin.ebtables.EnsureRule(utilebtables.Append, utilebtables.TableFilter, utilebtables.ChainOutput, "-j", string(dedupChain)) + if err != nil { + glog.Errorf("Failed to ensure %v chain %v jump to %v chain: %v", utilebtables.TableFilter, utilebtables.ChainOutput, dedupChain, err) + return + } + + commonArgs := []string{"-p", "IPv4", "-s", macAddr.String(), "-o", "veth+"} + _, err = plugin.ebtables.EnsureRule(utilebtables.Prepend, utilebtables.TableFilter, dedupChain, append(commonArgs, "--ip-src", plugin.gateway.String(), "-j", "ACCEPT")...) + if err != nil { + glog.Errorf("Failed to ensure packets from cbr0 gateway to be accepted") + return + + } + _, err = plugin.ebtables.EnsureRule(utilebtables.Append, utilebtables.TableFilter, dedupChain, append(commonArgs, "--ip-src", plugin.podCidr, "-j", "DROP")...) + if err != nil { + glog.Errorf("Failed to ensure packets from podCidr but has mac address of cbr0 to get dropped.") + return + } +} + +// disableContainerDAD disables duplicate address detection in the container. +// DAD has a negative affect on pod creation latency, since we have to wait +// a second or more for the addresses to leave the "tentative" state. Since +// we're sure there won't be an address conflict (since we manage them manually), +// this is safe. See issue 54651. +// +// This sets net.ipv6.conf.default.dad_transmits to 0. It must be run *before* +// the CNI plugins are run. +func (plugin *kubenetNetworkPlugin) disableContainerDAD(id kubecontainer.ContainerID) error { + key := "net/ipv6/conf/default/dad_transmits" + + sysctlBin, err := plugin.execer.LookPath("sysctl") + if err != nil { + return fmt.Errorf("Could not find sysctl binary: %s", err) + } + + netnsPath, err := plugin.host.GetNetNS(id.ID) + if err != nil { + return fmt.Errorf("Failed to get netns: %v", err) + } + if netnsPath == "" { + return fmt.Errorf("Pod has no network namespace") + } + + // If the sysctl doesn't exist, it means ipv6 is disabled; log and move on + if _, err := plugin.sysctl.GetSysctl(key); err != nil { + return fmt.Errorf("Ipv6 not enabled: %v", err) + } + + output, err := plugin.execer.Command(plugin.nsenterPath, + fmt.Sprintf("--net=%s", netnsPath), "-F", "--", + sysctlBin, "-w", fmt.Sprintf("%s=%s", key, "0"), + ).CombinedOutput() + if err != nil { + return fmt.Errorf("Failed to write sysctl: output: %s error: %s", + output, err) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet_linux_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet_linux_test.go similarity index 96% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet_linux_test.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet_linux_test.go index 01f6a04b3..f9fd4067f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet_linux_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet_linux_test.go @@ -26,10 +26,10 @@ import ( "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/network" - "k8s.io/kubernetes/pkg/kubelet/network/cni/testing" - hostporttest "k8s.io/kubernetes/pkg/kubelet/network/hostport/testing" - nettest "k8s.io/kubernetes/pkg/kubelet/network/testing" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing" + hostporttest "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport/testing" + nettest "k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing" "k8s.io/kubernetes/pkg/util/bandwidth" ipttest "k8s.io/kubernetes/pkg/util/iptables/testing" sysctltest "k8s.io/kubernetes/pkg/util/sysctl/testing" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet_unsupported.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet_unsupported.go similarity index 93% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet_unsupported.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet_unsupported.go index 1cbc7ab72..3fb4f966e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet/kubenet_unsupported.go @@ -23,14 +23,14 @@ import ( "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" ) type kubenetNetworkPlugin struct { network.NoopNetworkPlugin } -func NewPlugin(networkPluginDir string) network.NetworkPlugin { +func NewPlugin(networkPluginDirs []string) network.NetworkPlugin { return &kubenetNetworkPlugin{} } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics/BUILD new file mode 100644 index 000000000..a473e363a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["metrics.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics", + visibility = ["//visibility:public"], + deps = ["//vendor/github.com/prometheus/client_golang/prometheus:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/metrics/metrics.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics/metrics.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/metrics/metrics.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics/metrics.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/network.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/network.go similarity index 100% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/network.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/network.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/plugins.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/plugins.go similarity index 90% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/plugins.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/plugins.go index 24e358943..7968b2316 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/plugins.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/plugins.go @@ -24,16 +24,14 @@ import ( "time" "github.com/golang/glog" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilsets "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" - clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/network/hostport" - "k8s.io/kubernetes/pkg/kubelet/network/metrics" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics" utilsysctl "k8s.io/kubernetes/pkg/util/sysctl" utilexec "k8s.io/utils/exec" ) @@ -91,29 +89,6 @@ type PodNetworkStatus struct { IP net.IP `json:"ip" description:"Primary IP address of the pod"` } -// LegacyHost implements the methods required by network plugins that -// were directly invoked by the kubelet. Implementations of this interface -// that do not wish to support these features can simply return false -// to SupportsLegacyFeatures. -type LegacyHost interface { - // Get the pod structure by its name, namespace - // Only used for hostport management and bw shaping - GetPodByName(namespace, name string) (*v1.Pod, bool) - - // GetKubeClient returns a client interface - // Only used in testing - GetKubeClient() clientset.Interface - - // GetContainerRuntime returns the container runtime that implements the containers (e.g. docker/rkt) - // Only used for hostport management - GetRuntime() kubecontainer.Runtime - - // SupportsLegacyFeatures returns true if the network host support GetPodByName, KubeClient interface and kubelet - // runtime interface. These interfaces will no longer be implemented by CRI shims. - // This function helps network plugins to choose their behavior based on runtime. - SupportsLegacyFeatures() bool -} - // Host is an interface that plugins can use to access the kubelet. // TODO(#35457): get rid of this backchannel to the kubelet. The scope of // the back channel is restricted to host-ports/testing, and restricted @@ -126,12 +101,6 @@ type Host interface { // PortMappingGetter is a getter for sandbox port mapping information. PortMappingGetter - - // LegacyHost contains methods that trap back into the Kubelet. Dependence - // *do not* add more dependencies in this interface. In a post-cri world, - // network plugins will be invoked by the runtime shim, and should only - // require GetNetNS and GetPodPortMappings. - LegacyHost } // NamespaceGetter is an interface to retrieve namespace information for a given @@ -196,10 +165,6 @@ func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host H return chosenPlugin, utilerrors.NewAggregate(allErrs) } -func UnescapePluginName(in string) string { - return strings.Replace(in, "~", "/", -1) -} - type NoopNetworkPlugin struct { Sysctl utilsysctl.Interface } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/BUILD new file mode 100644 index 000000000..07ccc89c0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/BUILD @@ -0,0 +1,55 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "fake_host.go", + "mock_network_plugin.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing", + deps = [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/container/testing:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + "//pkg/kubelet/dockershim/network/hostport:go_default_library", + "//vendor/github.com/golang/mock/gomock:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["plugins_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/dockershim/network:go_default_library", + "//pkg/util/sysctl/testing:go_default_library", + "//vendor/github.com/golang/mock/gomock:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/fake_host.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/fake_host.go similarity index 96% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/fake_host.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/fake_host.go index ca9999ff2..71dbf1d07 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/fake_host.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/fake_host.go @@ -24,7 +24,7 @@ import ( clientset "k8s.io/client-go/kubernetes" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" - "k8s.io/kubernetes/pkg/kubelet/network/hostport" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" ) type fakeNetworkHost struct { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/mock_network_plugin.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/mock_network_plugin.go similarity index 98% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/mock_network_plugin.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/mock_network_plugin.go index a13712f20..72fc56f89 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/mock_network_plugin.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/mock_network_plugin.go @@ -25,7 +25,7 @@ import ( sets "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" container "k8s.io/kubernetes/pkg/kubelet/container" - network "k8s.io/kubernetes/pkg/kubelet/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" ) // Mock of NetworkPlugin interface diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/plugins_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/plugins_test.go similarity index 99% rename from vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/plugins_test.go rename to vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/plugins_test.go index 6398948fa..59772e051 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/plugins_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing/plugins_test.go @@ -25,7 +25,7 @@ import ( utilsets "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/network" + "k8s.io/kubernetes/pkg/kubelet/dockershim/network" sysctltest "k8s.io/kubernetes/pkg/util/sysctl/testing" "github.com/golang/mock/gomock" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/remote/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/remote/BUILD index 4ac86b9d3..a40ce09ea 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/remote/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/remote/BUILD @@ -13,7 +13,6 @@ go_library( "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/dockershim:go_default_library", "//pkg/kubelet/util:go_default_library", - "//pkg/util/interrupt:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/remote/docker_server.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/remote/docker_server.go index 53f52526e..546c3b6c4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/remote/docker_server.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/remote/docker_server.go @@ -21,13 +21,15 @@ import ( "github.com/golang/glog" "google.golang.org/grpc" - runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" "k8s.io/kubernetes/pkg/kubelet/dockershim" "k8s.io/kubernetes/pkg/kubelet/util" - "k8s.io/kubernetes/pkg/util/interrupt" ) +// maxMsgSize use 8MB as the default message size limit. +// grpc library default is 4MB +const maxMsgSize = 1024 * 1024 * 8 + // DockerServer is the grpc server of dockershim. type DockerServer struct { // endpoint is the endpoint to serve on. @@ -60,22 +62,16 @@ func (s *DockerServer) Start() error { return fmt.Errorf("failed to listen on %q: %v", s.endpoint, err) } // Create the grpc server and register runtime and image services. - s.server = grpc.NewServer() + s.server = grpc.NewServer( + grpc.MaxRecvMsgSize(maxMsgSize), + grpc.MaxSendMsgSize(maxMsgSize), + ) runtimeapi.RegisterRuntimeServiceServer(s.server, s.service) runtimeapi.RegisterImageServiceServer(s.server, s.service) go func() { - // Use interrupt handler to make sure the server to be stopped properly. - h := interrupt.New(nil, s.Stop) - err := h.Run(func() error { return s.server.Serve(l) }) - if err != nil { - glog.Errorf("Failed to serve connections: %v", err) + if err := s.server.Serve(l); err != nil { + glog.Fatalf("Failed to serve connections: %v", err) } }() return nil } - -// Stop stops the dockershim grpc server. -func (s *DockerServer) Stop() { - glog.V(2).Infof("Stop docker server") - s.server.Stop() -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/security_context.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/security_context.go index 28b420b67..d060144cb 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/security_context.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/security_context.go @@ -25,7 +25,7 @@ import ( dockercontainer "github.com/docker/docker/api/types/container" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" - knetwork "k8s.io/kubernetes/pkg/kubelet/network" + knetwork "k8s.io/kubernetes/pkg/kubelet/dockershim/network" ) // applySandboxSecurityContext updates docker sandbox options according to security context. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/selinux_util.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/selinux_util.go index d9a59cf0a..8df8ed924 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/selinux_util.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/selinux_util.go @@ -54,12 +54,6 @@ func selinuxLabelLevel(separator rune) string { return fmt.Sprintf("label%clevel", separator) } -// dockerLaelDisable returns the Docker security opt that disables SELinux for -// the container. -func selinuxLabelDisable(separator rune) string { - return fmt.Sprintf("label%cdisable", separator) -} - // addSELinuxOptions adds SELinux options to config using the given // separator. func addSELinuxOptions(config []string, selinuxOpts *runtimeapi.SELinuxOption, separator rune) []string { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/testing/BUILD deleted file mode 100644 index 0e57c9b08..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/testing/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["util.go"], - importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim/testing", -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/testing/util.go b/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/testing/util.go deleted file mode 100644 index 34bbb5303..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/dockershim/testing/util.go +++ /dev/null @@ -1,66 +0,0 @@ -/* -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 testing - -import ( - "fmt" - "sync" -) - -// MemStore is an implementation of CheckpointStore interface which stores checkpoint in memory. -type MemStore struct { - mem map[string][]byte - sync.Mutex -} - -func NewMemStore() *MemStore { - return &MemStore{mem: make(map[string][]byte)} -} - -func (mstore *MemStore) Write(key string, data []byte) error { - mstore.Lock() - defer mstore.Unlock() - mstore.mem[key] = data - return nil -} - -func (mstore *MemStore) Read(key string) ([]byte, error) { - mstore.Lock() - defer mstore.Unlock() - data, ok := mstore.mem[key] - if !ok { - return nil, fmt.Errorf("checkpoint is not found") - } - return data, nil -} - -func (mstore *MemStore) Delete(key string) error { - mstore.Lock() - defer mstore.Unlock() - delete(mstore.mem, key) - return nil -} - -func (mstore *MemStore) List() ([]string, error) { - mstore.Lock() - defer mstore.Unlock() - keys := make([]string, 0) - for key := range mstore.mem { - keys = append(keys, key) - } - return keys, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/BUILD index caa68996f..a6e6c8476 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/BUILD @@ -11,6 +11,8 @@ go_test( srcs = [ "eviction_manager_test.go", "helpers_test.go", + "memory_threshold_notifier_test.go", + "mock_threshold_notifier_test.go", ], embed = [":go_default_library"], deps = [ @@ -20,7 +22,7 @@ go_test( "//pkg/kubelet/eviction/api:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/types:go_default_library", - "//pkg/quota:go_default_library", + "//vendor/github.com/stretchr/testify/mock:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -37,6 +39,7 @@ go_library( "doc.go", "eviction_manager.go", "helpers.go", + "memory_threshold_notifier.go", "types.go", ] + select({ "@io_bazel_rules_go//go/platform:android": [ @@ -77,6 +80,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/kubelet/eviction", deps = [ "//pkg/api/v1/resource:go_default_library", + "//pkg/apis/core/v1/helper:go_default_library", "//pkg/apis/core/v1/helper/qos:go_default_library", "//pkg/features:go_default_library", "//pkg/kubelet/apis/stats/v1alpha1:go_default_library", @@ -88,13 +92,13 @@ go_library( "//pkg/kubelet/server/stats:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/format:go_default_library", + "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/util:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1: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/util/clock:go_default_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/tools/record:go_default_library", ] + select({ diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/api/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/api/types.go index 3e16d249c..d32ba9b30 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/api/types.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/api/types.go @@ -38,8 +38,6 @@ const ( SignalImageFsInodesFree Signal = "imagefs.inodesFree" // SignalAllocatableMemoryAvailable is amount of memory available for pod allocation (i.e. allocatable - workingSet (of pods), in bytes. SignalAllocatableMemoryAvailable Signal = "allocatableMemory.available" - // SignalAllocatableNodeFsAvailable is amount of local storage available for pod allocation - SignalAllocatableNodeFsAvailable Signal = "allocatableNodeFs.available" // SignalPIDAvailable is amount of PID available for pod allocation SignalPIDAvailable Signal = "pid.available" ) @@ -60,13 +58,11 @@ const ( // from either above or below, never both). There is thus no reason to expose the // operator in the Kubelet's public API. Instead, we internally map signal types to operators. var OpForSignal = map[Signal]ThresholdOperator{ - SignalMemoryAvailable: OpLessThan, - SignalNodeFsAvailable: OpLessThan, - SignalNodeFsInodesFree: OpLessThan, - SignalImageFsAvailable: OpLessThan, - SignalImageFsInodesFree: OpLessThan, - SignalAllocatableMemoryAvailable: OpLessThan, - SignalAllocatableNodeFsAvailable: OpLessThan, + SignalMemoryAvailable: OpLessThan, + SignalNodeFsAvailable: OpLessThan, + SignalNodeFsInodesFree: OpLessThan, + SignalImageFsAvailable: OpLessThan, + SignalImageFsInodesFree: OpLessThan, } // ThresholdValue is a value holder that abstracts literal versus percentage based quantity diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/eviction_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/eviction_manager.go index ddc5499b8..98833d925 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/eviction_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/eviction_manager.go @@ -19,7 +19,6 @@ package eviction import ( "fmt" "sort" - "strconv" "sync" "time" @@ -28,14 +27,13 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/clock" - "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/record" apiv1resource "k8s.io/kubernetes/pkg/api/v1/resource" + v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos" "k8s.io/kubernetes/pkg/features" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" - "k8s.io/kubernetes/pkg/kubelet/cm" evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/metrics" @@ -43,6 +41,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/server/stats" kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" + "k8s.io/kubernetes/pkg/scheduler/algorithm" ) const ( @@ -78,16 +77,18 @@ type managerImpl struct { thresholdsFirstObservedAt thresholdsObservedAt // records the set of thresholds that have been met (including graceperiod) but not yet resolved thresholdsMet []evictionapi.Threshold - // resourceToRankFunc maps a resource to ranking function for that resource. - resourceToRankFunc map[v1.ResourceName]rankFunc - // resourceToNodeReclaimFuncs maps a resource to an ordered list of functions that know how to reclaim that resource. - resourceToNodeReclaimFuncs map[v1.ResourceName]nodeReclaimFuncs + // signalToRankFunc maps a resource to ranking function for that resource. + signalToRankFunc map[evictionapi.Signal]rankFunc + // signalToNodeReclaimFuncs maps a resource to an ordered list of functions that know how to reclaim that resource. + signalToNodeReclaimFuncs map[evictionapi.Signal]nodeReclaimFuncs // last observations from synchronize lastObservations signalObservations - // notifiersInitialized indicates if the threshold notifiers have been initialized (i.e. synchronize() has been called once) - notifiersInitialized bool // dedicatedImageFs indicates if imagefs is on a separate device from the rootfs dedicatedImageFs *bool + // thresholdNotifiers is a list of memory threshold notifiers which each notify for a memory eviction threshold + thresholdNotifiers []ThresholdNotifier + // thresholdsLastUpdated is the last time the thresholdNotifiers were updated. + thresholdsLastUpdated time.Time } // ensure it implements the required interface @@ -116,6 +117,7 @@ func NewManager( nodeConditionsLastObservedAt: nodeConditionsObservedAt{}, thresholdsFirstObservedAt: thresholdsObservedAt{}, dedicatedImageFs: nil, + thresholdNotifiers: []ThresholdNotifier{}, } return manager, manager } @@ -138,19 +140,46 @@ func (m *managerImpl) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAd if notBestEffort { return lifecycle.PodAdmitResult{Admit: true} } + + // When node has memory pressure and TaintNodesByCondition is enabled, check BestEffort Pod's toleration: + // admit it if tolerates memory pressure taint, fail for other tolerations, e.g. OutOfDisk. + if utilfeature.DefaultFeatureGate.Enabled(features.TaintNodesByCondition) && + v1helper.TolerationsTolerateTaint(attrs.Pod.Spec.Tolerations, &v1.Taint{ + Key: algorithm.TaintNodeMemoryPressure, + Effect: v1.TaintEffectNoSchedule, + }) { + return lifecycle.PodAdmitResult{Admit: true} + } } // reject pods when under memory pressure (if pod is best effort), or if under disk pressure. glog.Warningf("Failed to admit pod %s - node has conditions: %v", format.Pod(attrs.Pod), m.nodeConditions) return lifecycle.PodAdmitResult{ Admit: false, - Reason: reason, - Message: fmt.Sprintf(message, m.nodeConditions), + Reason: Reason, + Message: fmt.Sprintf(nodeLowMessageFmt, m.nodeConditions), } } // Start starts the control loop to observe and response to low compute resources. func (m *managerImpl) Start(diskInfoProvider DiskInfoProvider, podFunc ActivePodsFunc, podCleanedUpFunc PodCleanedUpFunc, monitoringInterval time.Duration) { + thresholdHandler := func(message string) { + glog.Infof(message) + m.synchronize(diskInfoProvider, podFunc) + } + if m.config.KernelMemcgNotification { + for _, threshold := range m.config.Thresholds { + if threshold.Signal == evictionapi.SignalMemoryAvailable || threshold.Signal == evictionapi.SignalAllocatableMemoryAvailable { + notifier, err := NewMemoryThresholdNotifier(threshold, m.config.PodCgroupRoot, &CgroupNotifierFactory{}, thresholdHandler) + if err != nil { + glog.Warningf("eviction manager: failed to create memory threshold notifier: %v", err) + } else { + go notifier.Start() + m.thresholdNotifiers = append(m.thresholdNotifiers, notifier) + } + } + } + } // start the eviction manager monitoring go func() { for { @@ -185,39 +214,6 @@ func (m *managerImpl) IsUnderPIDPressure() bool { return hasNodeCondition(m.nodeConditions, v1.NodePIDPressure) } -func startMemoryThresholdNotifier(thresholds []evictionapi.Threshold, observations signalObservations, hard bool, handler thresholdNotifierHandlerFunc) error { - for _, threshold := range thresholds { - if threshold.Signal != evictionapi.SignalMemoryAvailable || hard != isHardEvictionThreshold(threshold) { - continue - } - observed, found := observations[evictionapi.SignalMemoryAvailable] - if !found { - continue - } - cgroups, err := cm.GetCgroupSubsystems() - if err != nil { - return err - } - // TODO add support for eviction from --cgroup-root - cgpath, found := cgroups.MountPoints["memory"] - if !found || len(cgpath) == 0 { - return fmt.Errorf("memory cgroup mount point not found") - } - attribute := "memory.usage_in_bytes" - quantity := evictionapi.GetThresholdQuantity(threshold.Value, observed.capacity) - usageThreshold := resource.NewQuantity(observed.capacity.Value(), resource.DecimalSI) - usageThreshold.Sub(*quantity) - description := fmt.Sprintf("<%s available", formatThresholdValue(threshold.Value)) - memcgThresholdNotifier, err := NewMemCGThresholdNotifier(cgpath, attribute, strconv.FormatInt(usageThreshold.Value(), 10), description, handler) - if err != nil { - return err - } - go memcgThresholdNotifier.Start(wait.NeverStop) - return nil - } - return nil -} - // synchronize is the main control loop that enforces eviction thresholds. // Returns the pod that was killed, or nil if no pod was killed. func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc ActivePodsFunc) []*v1.Pod { @@ -236,8 +232,8 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act return nil } m.dedicatedImageFs = &hasImageFs - m.resourceToRankFunc = buildResourceToRankFunc(hasImageFs) - m.resourceToNodeReclaimFuncs = buildResourceToNodeReclaimFuncs(m.imageGC, m.containerGC, hasImageFs) + m.signalToRankFunc = buildSignalToRankFunc(hasImageFs) + m.signalToNodeReclaimFuncs = buildSignalToNodeReclaimFuncs(m.imageGC, m.containerGC, hasImageFs) } activePods := podFunc() @@ -248,33 +244,19 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act return nil } + if m.clock.Since(m.thresholdsLastUpdated) > notifierRefreshInterval { + m.thresholdsLastUpdated = m.clock.Now() + for _, notifier := range m.thresholdNotifiers { + if err := notifier.UpdateThreshold(summary); err != nil { + glog.Warningf("eviction manager: failed to update %s: %v", notifier.Description(), err) + } + } + } + // make observations and get a function to derive pod usage stats relative to those observations. observations, statsFunc := makeSignalObservations(summary) debugLogObservations("observations", observations) - // attempt to create a threshold notifier to improve eviction response time - if m.config.KernelMemcgNotification && !m.notifiersInitialized { - glog.Infof("eviction manager attempting to integrate with kernel memcg notification api") - m.notifiersInitialized = true - // start soft memory notification - err = startMemoryThresholdNotifier(m.config.Thresholds, observations, false, func(desc string) { - glog.Infof("soft memory eviction threshold crossed at %s", desc) - // TODO wait grace period for soft memory limit - m.synchronize(diskInfoProvider, podFunc) - }) - if err != nil { - glog.Warningf("eviction manager: failed to create soft memory threshold notifier: %v", err) - } - // start hard memory notification - err = startMemoryThresholdNotifier(m.config.Thresholds, observations, true, func(desc string) { - glog.Infof("hard memory eviction threshold crossed at %s", desc) - m.synchronize(diskInfoProvider, podFunc) - }) - if err != nil { - glog.Warningf("eviction manager: failed to create hard memory threshold notifier: %v", err) - } - } - // determine the set of thresholds met independent of grace period thresholds = thresholdsMet(thresholds, observations, false) debugLogThresholdsWithObservation("thresholds - ignoring grace period", thresholds, observations) @@ -331,26 +313,26 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act } } - // determine the set of resources under starvation - starvedResources := getStarvedResources(thresholds) - if len(starvedResources) == 0 { + if len(thresholds) == 0 { glog.V(3).Infof("eviction manager: no resources are starved") return nil } - // rank the resources to reclaim by eviction priority - sort.Sort(byEvictionPriority(starvedResources)) - resourceToReclaim := starvedResources[0] + // rank the thresholds by eviction priority + sort.Sort(byEvictionPriority(thresholds)) + thresholdToReclaim := thresholds[0] + resourceToReclaim, found := signalToResource[thresholdToReclaim.Signal] + if !found { + glog.V(3).Infof("eviction manager: threshold %s was crossed, but reclaim is not implemented for this threshold.", thresholdToReclaim.Signal) + return nil + } glog.Warningf("eviction manager: attempting to reclaim %v", resourceToReclaim) - // determine if this is a soft or hard eviction associated with the resource - softEviction := isSoftEvictionThresholds(thresholds, resourceToReclaim) - // record an event about the resources we are now attempting to reclaim via eviction m.recorder.Eventf(m.nodeRef, v1.EventTypeWarning, "EvictionThresholdMet", "Attempting to reclaim %s", resourceToReclaim) // check if there are node-level resources we can reclaim to reduce pressure before evicting end-user pods. - if m.reclaimNodeLevelResources(resourceToReclaim) { + if m.reclaimNodeLevelResources(thresholdToReclaim.Signal, resourceToReclaim) { glog.Infof("eviction manager: able to reduce %v pressure without evicting pods.", resourceToReclaim) return nil } @@ -358,9 +340,9 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act glog.Infof("eviction manager: must evict pod(s) to reclaim %v", resourceToReclaim) // rank the pods for eviction - rank, ok := m.resourceToRankFunc[resourceToReclaim] + rank, ok := m.signalToRankFunc[thresholdToReclaim.Signal] if !ok { - glog.Errorf("eviction manager: no ranking function for resource %s", resourceToReclaim) + glog.Errorf("eviction manager: no ranking function for signal %s", thresholdToReclaim.Signal) return nil } @@ -386,30 +368,14 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act // we kill at most a single pod during each eviction interval for i := range activePods { pod := activePods[i] - // If the pod is marked as critical and static, and support for critical pod annotations is enabled, - // do not evict such pods. Static pods are not re-admitted after evictions. - // https://github.com/kubernetes/kubernetes/issues/40573 has more details. - if utilfeature.DefaultFeatureGate.Enabled(features.ExperimentalCriticalPodAnnotation) && - kubelettypes.IsCriticalPod(pod) && kubepod.IsStaticPod(pod) { - continue - } - status := v1.PodStatus{ - Phase: v1.PodFailed, - Message: fmt.Sprintf(message, resourceToReclaim), - Reason: reason, - } - // record that we are evicting the pod - m.recorder.Eventf(pod, v1.EventTypeWarning, reason, fmt.Sprintf(message, resourceToReclaim)) gracePeriodOverride := int64(0) - if softEviction { + if !isHardEvictionThreshold(thresholdToReclaim) { gracePeriodOverride = m.config.MaxPodGracePeriodSeconds } - // this is a blocking call and should only return when the pod and its containers are killed. - err := m.killPodFunc(pod, status, &gracePeriodOverride) - if err != nil { - glog.Warningf("eviction manager: error while evicting pod %s: %v", format.Pod(pod), err) + message, annotations := evictionMessage(resourceToReclaim, pod, statsFunc) + if m.evictPod(pod, gracePeriodOverride, message, annotations) { + return []*v1.Pod{pod} } - return []*v1.Pod{pod} } glog.Infof("eviction manager: unable to evict any pods from the node") return nil @@ -417,13 +383,15 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act func (m *managerImpl) waitForPodsCleanup(podCleanedUpFunc PodCleanedUpFunc, pods []*v1.Pod) { timeout := m.clock.NewTimer(podCleanupTimeout) - tick := m.clock.Tick(podCleanupPollFreq) + defer timeout.Stop() + ticker := m.clock.NewTicker(podCleanupPollFreq) + defer ticker.Stop() for { select { case <-timeout.C(): glog.Warningf("eviction manager: timed out waiting for pods %s to be cleaned up", format.Pods(pods)) return - case <-tick: + case <-ticker.C(): for i, pod := range pods { if !podCleanedUpFunc(pod) { break @@ -438,8 +406,8 @@ func (m *managerImpl) waitForPodsCleanup(podCleanedUpFunc PodCleanedUpFunc, pods } // reclaimNodeLevelResources attempts to reclaim node level resources. returns true if thresholds were satisfied and no pod eviction is required. -func (m *managerImpl) reclaimNodeLevelResources(resourceToReclaim v1.ResourceName) bool { - nodeReclaimFuncs := m.resourceToNodeReclaimFuncs[resourceToReclaim] +func (m *managerImpl) reclaimNodeLevelResources(signalToReclaim evictionapi.Signal, resourceToReclaim v1.ResourceName) bool { + nodeReclaimFuncs := m.signalToNodeReclaimFuncs[signalToReclaim] for _, nodeReclaimFunc := range nodeReclaimFuncs { // attempt to reclaim the pressured resource. if err := nodeReclaimFunc(); err != nil { @@ -510,7 +478,7 @@ func (m *managerImpl) emptyDirLimitEviction(podStats statsapi.PodStats, pod *v1. used := podVolumeUsed[pod.Spec.Volumes[i].Name] if used != nil && size != nil && size.Sign() == 1 && used.Cmp(*size) > 0 { // the emptyDir usage exceeds the size limit, evict the pod - return m.evictPod(pod, v1.ResourceName("EmptyDir"), fmt.Sprintf("emptyDir usage exceeds the limit %q", size.String())) + return m.evictPod(pod, 0, fmt.Sprintf(emptyDirMessageFmt, pod.Spec.Volumes[i].Name, size.String()), nil) } } } @@ -538,10 +506,11 @@ func (m *managerImpl) podEphemeralStorageLimitEviction(podStats statsapi.PodStat return false } - podEphemeralStorageTotalUsage.Add(podEphemeralUsage[resourceDisk]) - if podEphemeralStorageTotalUsage.Cmp(podLimits[v1.ResourceEphemeralStorage]) > 0 { + podEphemeralStorageTotalUsage.Add(podEphemeralUsage[v1.ResourceEphemeralStorage]) + podEphemeralStorageLimit := podLimits[v1.ResourceEphemeralStorage] + if podEphemeralStorageTotalUsage.Cmp(podEphemeralStorageLimit) > 0 { // the total usage of pod exceeds the total size limit of containers, evict the pod - return m.evictPod(pod, v1.ResourceEphemeralStorage, fmt.Sprintf("pod ephemeral local storage usage exceeds the total limit of containers %v", podLimits[v1.ResourceEphemeralStorage])) + return m.evictPod(pod, 0, fmt.Sprintf(podEphemeralStorageMessageFmt, podEphemeralStorageLimit.String()), nil) } return false } @@ -563,7 +532,7 @@ func (m *managerImpl) containerEphemeralStorageLimitEviction(podStats statsapi.P if ephemeralStorageThreshold, ok := thresholdsMap[containerStat.Name]; ok { if ephemeralStorageThreshold.Cmp(*containerUsed) < 0 { - return m.evictPod(pod, v1.ResourceEphemeralStorage, fmt.Sprintf("container's ephemeral local storage usage exceeds the limit %q", ephemeralStorageThreshold.String())) + return m.evictPod(pod, 0, fmt.Sprintf(containerEphemeralStorageMessageFmt, containerStat.Name, ephemeralStorageThreshold.String()), nil) } } @@ -571,21 +540,24 @@ func (m *managerImpl) containerEphemeralStorageLimitEviction(podStats statsapi.P return false } -func (m *managerImpl) evictPod(pod *v1.Pod, resourceName v1.ResourceName, evictMsg string) bool { +func (m *managerImpl) evictPod(pod *v1.Pod, gracePeriodOverride int64, evictMsg string, annotations map[string]string) bool { + // If the pod is marked as critical and static, and support for critical pod annotations is enabled, + // do not evict such pods. Static pods are not re-admitted after evictions. + // https://github.com/kubernetes/kubernetes/issues/40573 has more details. if utilfeature.DefaultFeatureGate.Enabled(features.ExperimentalCriticalPodAnnotation) && kubelettypes.IsCriticalPod(pod) && kubepod.IsStaticPod(pod) { - glog.Errorf("eviction manager: cannot evict a critical pod %s", format.Pod(pod)) + glog.Errorf("eviction manager: cannot evict a critical static pod %s", format.Pod(pod)) return false } status := v1.PodStatus{ Phase: v1.PodFailed, - Message: fmt.Sprintf(message, resourceName), - Reason: reason, + Message: evictMsg, + Reason: Reason, } // record that we are evicting the pod - m.recorder.Eventf(pod, v1.EventTypeWarning, reason, evictMsg) - gracePeriod := int64(0) - err := m.killPodFunc(pod, status, &gracePeriod) + m.recorder.AnnotatedEventf(pod, annotations, v1.EventTypeWarning, Reason, evictMsg) + // this is a blocking call and should only return when the pod and its containers are killed. + err := m.killPodFunc(pod, status, &gracePeriodOverride) if err != nil { glog.Errorf("eviction manager: pod %s failed to evict %v", format.Pod(pod), err) } else { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/eviction_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/eviction_manager_test.go index 9ec64c408..e8b4a4e36 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/eviction_manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/eviction_manager_test.go @@ -17,6 +17,7 @@ limitations under the License. package eviction import ( + "fmt" "testing" "time" @@ -1434,3 +1435,74 @@ func TestAllocatableMemoryPressure(t *testing.T) { } } } + +func TestUpdateMemcgThreshold(t *testing.T) { + activePodsFunc := func() []*v1.Pod { + return []*v1.Pod{} + } + + fakeClock := clock.NewFakeClock(time.Now()) + podKiller := &mockPodKiller{} + diskInfoProvider := &mockDiskInfoProvider{dedicatedImageFs: false} + diskGC := &mockDiskGC{err: nil} + nodeRef := &v1.ObjectReference{Kind: "Node", Name: "test", UID: types.UID("test"), Namespace: ""} + + config := Config{ + MaxPodGracePeriodSeconds: 5, + PressureTransitionPeriod: time.Minute * 5, + Thresholds: []evictionapi.Threshold{ + { + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("1Gi"), + }, + }, + }, + PodCgroupRoot: "kubepods", + } + summaryProvider := &fakeSummaryProvider{result: makeMemoryStats("2Gi", map[*v1.Pod]statsapi.PodStats{})} + + thresholdNotifier := &MockThresholdNotifier{} + thresholdNotifier.On("UpdateThreshold", summaryProvider.result).Return(nil).Twice() + + manager := &managerImpl{ + clock: fakeClock, + killPodFunc: podKiller.killPodNow, + imageGC: diskGC, + containerGC: diskGC, + config: config, + recorder: &record.FakeRecorder{}, + summaryProvider: summaryProvider, + nodeRef: nodeRef, + nodeConditionsLastObservedAt: nodeConditionsObservedAt{}, + thresholdsFirstObservedAt: thresholdsObservedAt{}, + thresholdNotifiers: []ThresholdNotifier{thresholdNotifier}, + } + + manager.synchronize(diskInfoProvider, activePodsFunc) + // The UpdateThreshold method should have been called once, since this is the first run. + thresholdNotifier.AssertNumberOfCalls(t, "UpdateThreshold", 1) + + manager.synchronize(diskInfoProvider, activePodsFunc) + // The UpdateThreshold method should not have been called again, since not enough time has passed + thresholdNotifier.AssertNumberOfCalls(t, "UpdateThreshold", 1) + + fakeClock.Step(2 * notifierRefreshInterval) + manager.synchronize(diskInfoProvider, activePodsFunc) + // The UpdateThreshold method should be called again since enough time has passed + thresholdNotifier.AssertNumberOfCalls(t, "UpdateThreshold", 2) + + // new memory threshold notifier that returns an error + thresholdNotifier = &MockThresholdNotifier{} + thresholdNotifier.On("UpdateThreshold", summaryProvider.result).Return(fmt.Errorf("error updating threshold")) + thresholdNotifier.On("Description").Return("mock thresholdNotifier").Once() + manager.thresholdNotifiers = []ThresholdNotifier{thresholdNotifier} + + fakeClock.Step(2 * notifierRefreshInterval) + manager.synchronize(diskInfoProvider, activePodsFunc) + // The UpdateThreshold method should be called because at least notifierRefreshInterval time has passed. + // The Description method should be called because UpdateThreshold returned an error + thresholdNotifier.AssertNumberOfCalls(t, "UpdateThreshold", 1) + thresholdNotifier.AssertNumberOfCalls(t, "Description", 1) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/helpers.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/helpers.go index 92c10ad6f..c078ce93d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/helpers.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/helpers.go @@ -36,22 +36,26 @@ import ( const ( unsupportedEvictionSignal = "unsupported eviction signal %v" - // the reason reported back in status. - reason = "Evicted" - // the message associated with the reason. - message = "The node was low on resource: %v." - // disk, in bytes. internal to this module, used to account for local disk usage. - resourceDisk v1.ResourceName = "disk" + // Reason is the reason reported back in status. + Reason = "Evicted" + // nodeLowMessageFmt is the message for evictions due to resource pressure. + nodeLowMessageFmt = "The node was low on resource: %v. " + // containerMessageFmt provides additional information for containers exceeding requests + containerMessageFmt = "Container %s was using %s, which exceeds its request of %s. " + // containerEphemeralStorageMessageFmt provides additional information for containers which have exceeded their ES limit + containerEphemeralStorageMessageFmt = "Container %s exceeded its local ephemeral storage limit %q. " + // podEphemeralStorageMessageFmt provides additional information for pods which have exceeded their ES limit + podEphemeralStorageMessageFmt = "Pod ephemeral local storage usage exceeds the total limit of containers %s. " + // emptyDirMessageFmt provides additional information for empty-dir volumes which have exceeded their size limit + emptyDirMessageFmt = "Usage of EmptyDir volume %q exceeds the limit %q. " // inodes, number. internal to this module, used to account for local disk inode consumption. resourceInodes v1.ResourceName = "inodes" - // imagefs, in bytes. internal to this module, used to account for local image filesystem usage. - resourceImageFs v1.ResourceName = "imagefs" - // imagefs inodes, number. internal to this module, used to account for local image filesystem inodes. - resourceImageFsInodes v1.ResourceName = "imagefsInodes" - // nodefs, in bytes. internal to this module, used to account for local node root filesystem usage. - resourceNodeFs v1.ResourceName = "nodefs" - // nodefs inodes, number. internal to this module, used to account for local node root filesystem inodes. - resourceNodeFsInodes v1.ResourceName = "nodefsInodes" + // OffendingContainersKey is the key in eviction event annotations for the list of container names which exceeded their requests + OffendingContainersKey = "offending_containers" + // OffendingContainersUsageKey is the key in eviction event annotations for the list of usage of containers which exceeded their requests + OffendingContainersUsageKey = "offending_containers_usage" + // StarvedResourceKey is the key for the starved resource in eviction event annotations + StarvedResourceKey = "starved_resource" ) var ( @@ -59,8 +63,6 @@ var ( signalToNodeCondition map[evictionapi.Signal]v1.NodeConditionType // signalToResource maps a Signal to its associated Resource. signalToResource map[evictionapi.Signal]v1.ResourceName - // resourceClaimToSignal maps a Resource that can be reclaimed to its associated Signal - resourceClaimToSignal map[v1.ResourceName][]evictionapi.Signal ) func init() { @@ -78,17 +80,10 @@ func init() { signalToResource = map[evictionapi.Signal]v1.ResourceName{} signalToResource[evictionapi.SignalMemoryAvailable] = v1.ResourceMemory signalToResource[evictionapi.SignalAllocatableMemoryAvailable] = v1.ResourceMemory - signalToResource[evictionapi.SignalImageFsAvailable] = resourceImageFs - signalToResource[evictionapi.SignalImageFsInodesFree] = resourceImageFsInodes - signalToResource[evictionapi.SignalNodeFsAvailable] = resourceNodeFs - signalToResource[evictionapi.SignalNodeFsInodesFree] = resourceNodeFsInodes - - // maps resource to signals (the following resource could be reclaimed) - resourceClaimToSignal = map[v1.ResourceName][]evictionapi.Signal{} - resourceClaimToSignal[resourceNodeFs] = []evictionapi.Signal{evictionapi.SignalNodeFsAvailable} - resourceClaimToSignal[resourceImageFs] = []evictionapi.Signal{evictionapi.SignalImageFsAvailable} - resourceClaimToSignal[resourceNodeFsInodes] = []evictionapi.Signal{evictionapi.SignalNodeFsInodesFree} - resourceClaimToSignal[resourceImageFsInodes] = []evictionapi.Signal{evictionapi.SignalImageFsInodesFree} + signalToResource[evictionapi.SignalImageFsAvailable] = v1.ResourceEphemeralStorage + signalToResource[evictionapi.SignalImageFsInodesFree] = resourceInodes + signalToResource[evictionapi.SignalNodeFsAvailable] = v1.ResourceEphemeralStorage + signalToResource[evictionapi.SignalNodeFsInodesFree] = resourceInodes } // validSignal returns true if the signal is supported. @@ -305,10 +300,10 @@ func diskUsage(fsStats *statsapi.FsStats) *resource.Quantity { // inodeUsage converts inodes consumed into a resource quantity. func inodeUsage(fsStats *statsapi.FsStats) *resource.Quantity { if fsStats == nil || fsStats.InodesUsed == nil { - return &resource.Quantity{Format: resource.BinarySI} + return &resource.Quantity{Format: resource.DecimalSI} } usage := int64(*fsStats.InodesUsed) - return resource.NewQuantity(usage, resource.BinarySI) + return resource.NewQuantity(usage, resource.DecimalSI) } // memoryUsage converts working set into a resource quantity. @@ -338,7 +333,7 @@ func localVolumeNames(pod *v1.Pod) []string { // containerUsage aggregates container disk usage and inode consumption for the specified stats to measure. func containerUsage(podStats statsapi.PodStats, statsToMeasure []fsStatsType) v1.ResourceList { disk := resource.Quantity{Format: resource.BinarySI} - inodes := resource.Quantity{Format: resource.BinarySI} + inodes := resource.Quantity{Format: resource.DecimalSI} for _, container := range podStats.Containers { if hasFsStatsType(statsToMeasure, fsStatsRoot) { disk.Add(*diskUsage(container.Rootfs)) @@ -350,15 +345,15 @@ func containerUsage(podStats statsapi.PodStats, statsToMeasure []fsStatsType) v1 } } return v1.ResourceList{ - resourceDisk: disk, - resourceInodes: inodes, + v1.ResourceEphemeralStorage: disk, + resourceInodes: inodes, } } // podLocalVolumeUsage aggregates pod local volumes disk usage and inode consumption for the specified stats to measure. func podLocalVolumeUsage(volumeNames []string, podStats statsapi.PodStats) v1.ResourceList { disk := resource.Quantity{Format: resource.BinarySI} - inodes := resource.Quantity{Format: resource.BinarySI} + inodes := resource.Quantity{Format: resource.DecimalSI} for _, volumeName := range volumeNames { for _, volumeStats := range podStats.VolumeStats { if volumeStats.Name == volumeName { @@ -369,29 +364,29 @@ func podLocalVolumeUsage(volumeNames []string, podStats statsapi.PodStats) v1.Re } } return v1.ResourceList{ - resourceDisk: disk, - resourceInodes: inodes, + v1.ResourceEphemeralStorage: disk, + resourceInodes: inodes, } } // podDiskUsage aggregates pod disk usage and inode consumption for the specified stats to measure. func podDiskUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType) (v1.ResourceList, error) { disk := resource.Quantity{Format: resource.BinarySI} - inodes := resource.Quantity{Format: resource.BinarySI} + inodes := resource.Quantity{Format: resource.DecimalSI} containerUsageList := containerUsage(podStats, statsToMeasure) - disk.Add(containerUsageList[resourceDisk]) + disk.Add(containerUsageList[v1.ResourceEphemeralStorage]) inodes.Add(containerUsageList[resourceInodes]) if hasFsStatsType(statsToMeasure, fsStatsLocalVolumeSource) { volumeNames := localVolumeNames(pod) podLocalVolumeUsageList := podLocalVolumeUsage(volumeNames, podStats) - disk.Add(podLocalVolumeUsageList[resourceDisk]) + disk.Add(podLocalVolumeUsageList[v1.ResourceEphemeralStorage]) inodes.Add(podLocalVolumeUsageList[resourceInodes]) } return v1.ResourceList{ - resourceDisk: disk, - resourceInodes: inodes, + v1.ResourceEphemeralStorage: disk, + resourceInodes: inodes, }, nil } @@ -421,21 +416,21 @@ func localEphemeralVolumeNames(pod *v1.Pod) []string { // podLocalEphemeralStorageUsage aggregates pod local ephemeral storage usage and inode consumption for the specified stats to measure. func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType) (v1.ResourceList, error) { disk := resource.Quantity{Format: resource.BinarySI} - inodes := resource.Quantity{Format: resource.BinarySI} + inodes := resource.Quantity{Format: resource.DecimalSI} containerUsageList := containerUsage(podStats, statsToMeasure) - disk.Add(containerUsageList[resourceDisk]) + disk.Add(containerUsageList[v1.ResourceEphemeralStorage]) inodes.Add(containerUsageList[resourceInodes]) if hasFsStatsType(statsToMeasure, fsStatsLocalVolumeSource) { volumeNames := localEphemeralVolumeNames(pod) podLocalVolumeUsageList := podLocalVolumeUsage(volumeNames, podStats) - disk.Add(podLocalVolumeUsageList[resourceDisk]) + disk.Add(podLocalVolumeUsageList[v1.ResourceEphemeralStorage]) inodes.Add(podLocalVolumeUsageList[resourceInodes]) } return v1.ResourceList{ - resourceDisk: disk, - resourceInodes: inodes, + v1.ResourceEphemeralStorage: disk, + resourceInodes: inodes, }, nil } @@ -600,7 +595,7 @@ func memory(stats statsFunc) cmpFunc { // max(max of init container requests, sum of container requests) func podRequest(pod *v1.Pod, resourceName v1.ResourceName) resource.Quantity { containerValue := resource.Quantity{Format: resource.BinarySI} - if resourceName == resourceDisk && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { + if resourceName == v1.ResourceEphemeralStorage && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { // if the local storage capacity isolation feature gate is disabled, pods request 0 disk return containerValue } @@ -608,7 +603,7 @@ func podRequest(pod *v1.Pod, resourceName v1.ResourceName) resource.Quantity { switch resourceName { case v1.ResourceMemory: containerValue.Add(*pod.Spec.Containers[i].Resources.Requests.Memory()) - case resourceDisk: + case v1.ResourceEphemeralStorage: containerValue.Add(*pod.Spec.Containers[i].Resources.Requests.StorageEphemeral()) } } @@ -619,7 +614,7 @@ func podRequest(pod *v1.Pod, resourceName v1.ResourceName) resource.Quantity { if initValue.Cmp(*pod.Spec.InitContainers[i].Resources.Requests.Memory()) < 0 { initValue = *pod.Spec.InitContainers[i].Resources.Requests.Memory() } - case resourceDisk: + case v1.ResourceEphemeralStorage: if initValue.Cmp(*pod.Spec.InitContainers[i].Resources.Requests.StorageEphemeral()) < 0 { initValue = *pod.Spec.InitContainers[i].Resources.Requests.StorageEphemeral() } @@ -676,9 +671,9 @@ func disk(stats statsFunc, fsStatsToMeasure []fsStatsType, diskResource v1.Resou // adjust p1, p2 usage relative to the request (if any) p1Disk := p1Usage[diskResource] p2Disk := p2Usage[diskResource] - p1Request := podRequest(p1, resourceDisk) + p1Request := podRequest(p1, v1.ResourceEphemeralStorage) p1Disk.Sub(p1Request) - p2Request := podRequest(p2, resourceDisk) + p2Request := podRequest(p2, v1.ResourceEphemeralStorage) p2Disk.Sub(p2Request) // prioritize evicting the pod which has the larger consumption of disk return p2Disk.Cmp(p1Disk) @@ -711,14 +706,15 @@ func rankDiskPressureFunc(fsStatsToMeasure []fsStatsType, diskResource v1.Resour } // byEvictionPriority implements sort.Interface for []v1.ResourceName. -type byEvictionPriority []v1.ResourceName +type byEvictionPriority []evictionapi.Threshold func (a byEvictionPriority) Len() int { return len(a) } func (a byEvictionPriority) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -// Less ranks memory before all other resources. +// Less ranks memory before all other resources, and ranks thresholds with no resource to reclaim last func (a byEvictionPriority) Less(i, j int) bool { - return a[i] == v1.ResourceMemory + _, jSignalHasResource := signalToResource[a[j].Signal] + return a[i].Signal == evictionapi.SignalMemoryAvailable || a[i].Signal == evictionapi.SignalAllocatableMemoryAvailable || !jSignalHasResource } // makeSignalObservations derives observations using the specified summary provider. @@ -756,8 +752,8 @@ func makeSignalObservations(summary *statsapi.Summary) (signalObservations, stat } if nodeFs.InodesFree != nil && nodeFs.Inodes != nil { result[evictionapi.SignalNodeFsInodesFree] = signalObservation{ - available: resource.NewQuantity(int64(*nodeFs.InodesFree), resource.BinarySI), - capacity: resource.NewQuantity(int64(*nodeFs.Inodes), resource.BinarySI), + available: resource.NewQuantity(int64(*nodeFs.InodesFree), resource.DecimalSI), + capacity: resource.NewQuantity(int64(*nodeFs.Inodes), resource.DecimalSI), time: nodeFs.Time, } } @@ -772,8 +768,8 @@ func makeSignalObservations(summary *statsapi.Summary) (signalObservations, stat } if imageFs.InodesFree != nil && imageFs.Inodes != nil { result[evictionapi.SignalImageFsInodesFree] = signalObservation{ - available: resource.NewQuantity(int64(*imageFs.InodesFree), resource.BinarySI), - capacity: resource.NewQuantity(int64(*imageFs.Inodes), resource.BinarySI), + available: resource.NewQuantity(int64(*imageFs.InodesFree), resource.DecimalSI), + capacity: resource.NewQuantity(int64(*imageFs.Inodes), resource.DecimalSI), time: imageFs.Time, } } @@ -1001,82 +997,102 @@ func compareThresholdValue(a evictionapi.ThresholdValue, b evictionapi.Threshold return a.Percentage == b.Percentage } -// getStarvedResources returns the set of resources that are starved based on thresholds met. -func getStarvedResources(thresholds []evictionapi.Threshold) []v1.ResourceName { - results := []v1.ResourceName{} - for _, threshold := range thresholds { - if starvedResource, found := signalToResource[threshold.Signal]; found { - results = append(results, starvedResource) - } - } - return results -} - -// isSoftEviction returns true if the thresholds met for the starved resource are only soft thresholds -func isSoftEvictionThresholds(thresholds []evictionapi.Threshold, starvedResource v1.ResourceName) bool { - for _, threshold := range thresholds { - if resourceToCheck := signalToResource[threshold.Signal]; resourceToCheck != starvedResource { - continue - } - if isHardEvictionThreshold(threshold) { - return false - } - } - return true -} - // isHardEvictionThreshold returns true if eviction should immediately occur func isHardEvictionThreshold(threshold evictionapi.Threshold) bool { return threshold.GracePeriod == time.Duration(0) } -// buildResourceToRankFunc returns ranking functions associated with resources -func buildResourceToRankFunc(withImageFs bool) map[v1.ResourceName]rankFunc { - resourceToRankFunc := map[v1.ResourceName]rankFunc{ - v1.ResourceMemory: rankMemoryPressure, +func isAllocatableEvictionThreshold(threshold evictionapi.Threshold) bool { + return threshold.Signal == evictionapi.SignalAllocatableMemoryAvailable +} + +// buildSignalToRankFunc returns ranking functions associated with resources +func buildSignalToRankFunc(withImageFs bool) map[evictionapi.Signal]rankFunc { + signalToRankFunc := map[evictionapi.Signal]rankFunc{ + evictionapi.SignalMemoryAvailable: rankMemoryPressure, + evictionapi.SignalAllocatableMemoryAvailable: rankMemoryPressure, } // usage of an imagefs is optional if withImageFs { // with an imagefs, nodefs pod rank func for eviction only includes logs and local volumes - resourceToRankFunc[resourceNodeFs] = rankDiskPressureFunc([]fsStatsType{fsStatsLogs, fsStatsLocalVolumeSource}, resourceDisk) - resourceToRankFunc[resourceNodeFsInodes] = rankDiskPressureFunc([]fsStatsType{fsStatsLogs, fsStatsLocalVolumeSource}, resourceInodes) + signalToRankFunc[evictionapi.SignalNodeFsAvailable] = rankDiskPressureFunc([]fsStatsType{fsStatsLogs, fsStatsLocalVolumeSource}, v1.ResourceEphemeralStorage) + signalToRankFunc[evictionapi.SignalNodeFsInodesFree] = rankDiskPressureFunc([]fsStatsType{fsStatsLogs, fsStatsLocalVolumeSource}, resourceInodes) // with an imagefs, imagefs pod rank func for eviction only includes rootfs - resourceToRankFunc[resourceImageFs] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot}, resourceDisk) - resourceToRankFunc[resourceImageFsInodes] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot}, resourceInodes) + signalToRankFunc[evictionapi.SignalImageFsAvailable] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot}, v1.ResourceEphemeralStorage) + signalToRankFunc[evictionapi.SignalImageFsInodesFree] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot}, resourceInodes) } else { // without an imagefs, nodefs pod rank func for eviction looks at all fs stats. // since imagefs and nodefs share a common device, they share common ranking functions. - resourceToRankFunc[resourceNodeFs] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, resourceDisk) - resourceToRankFunc[resourceNodeFsInodes] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, resourceInodes) - resourceToRankFunc[resourceImageFs] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, resourceDisk) - resourceToRankFunc[resourceImageFsInodes] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, resourceInodes) + signalToRankFunc[evictionapi.SignalNodeFsAvailable] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, v1.ResourceEphemeralStorage) + signalToRankFunc[evictionapi.SignalNodeFsInodesFree] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, resourceInodes) + signalToRankFunc[evictionapi.SignalImageFsAvailable] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, v1.ResourceEphemeralStorage) + signalToRankFunc[evictionapi.SignalImageFsInodesFree] = rankDiskPressureFunc([]fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, resourceInodes) } - return resourceToRankFunc + return signalToRankFunc } // PodIsEvicted returns true if the reported pod status is due to an eviction. func PodIsEvicted(podStatus v1.PodStatus) bool { - return podStatus.Phase == v1.PodFailed && podStatus.Reason == reason + return podStatus.Phase == v1.PodFailed && podStatus.Reason == Reason } -// buildResourceToNodeReclaimFuncs returns reclaim functions associated with resources. -func buildResourceToNodeReclaimFuncs(imageGC ImageGC, containerGC ContainerGC, withImageFs bool) map[v1.ResourceName]nodeReclaimFuncs { - resourceToReclaimFunc := map[v1.ResourceName]nodeReclaimFuncs{} +// buildSignalToNodeReclaimFuncs returns reclaim functions associated with resources. +func buildSignalToNodeReclaimFuncs(imageGC ImageGC, containerGC ContainerGC, withImageFs bool) map[evictionapi.Signal]nodeReclaimFuncs { + signalToReclaimFunc := map[evictionapi.Signal]nodeReclaimFuncs{} // usage of an imagefs is optional if withImageFs { // with an imagefs, nodefs pressure should just delete logs - resourceToReclaimFunc[resourceNodeFs] = nodeReclaimFuncs{} - resourceToReclaimFunc[resourceNodeFsInodes] = nodeReclaimFuncs{} + signalToReclaimFunc[evictionapi.SignalNodeFsAvailable] = nodeReclaimFuncs{} + signalToReclaimFunc[evictionapi.SignalNodeFsInodesFree] = nodeReclaimFuncs{} // with an imagefs, imagefs pressure should delete unused images - resourceToReclaimFunc[resourceImageFs] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} - resourceToReclaimFunc[resourceImageFsInodes] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} + signalToReclaimFunc[evictionapi.SignalImageFsAvailable] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} + signalToReclaimFunc[evictionapi.SignalImageFsInodesFree] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} } else { // without an imagefs, nodefs pressure should delete logs, and unused images // since imagefs and nodefs share a common device, they share common reclaim functions - resourceToReclaimFunc[resourceNodeFs] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} - resourceToReclaimFunc[resourceNodeFsInodes] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} - resourceToReclaimFunc[resourceImageFs] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} - resourceToReclaimFunc[resourceImageFsInodes] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} + signalToReclaimFunc[evictionapi.SignalNodeFsAvailable] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} + signalToReclaimFunc[evictionapi.SignalNodeFsInodesFree] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} + signalToReclaimFunc[evictionapi.SignalImageFsAvailable] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} + signalToReclaimFunc[evictionapi.SignalImageFsInodesFree] = nodeReclaimFuncs{containerGC.DeleteAllUnusedContainers, imageGC.DeleteUnusedImages} + } + return signalToReclaimFunc +} + +// evictionMessage constructs a useful message about why an eviction occurred, and annotations to provide metadata about the eviction +func evictionMessage(resourceToReclaim v1.ResourceName, pod *v1.Pod, stats statsFunc) (message string, annotations map[string]string) { + annotations = make(map[string]string) + message = fmt.Sprintf(nodeLowMessageFmt, resourceToReclaim) + containers := []string{} + containerUsage := []string{} + podStats, ok := stats(pod) + if !ok { + return + } + for _, containerStats := range podStats.Containers { + for _, container := range pod.Spec.Containers { + if container.Name == containerStats.Name { + requests := container.Resources.Requests[resourceToReclaim] + var usage *resource.Quantity + switch resourceToReclaim { + case v1.ResourceEphemeralStorage: + if containerStats.Rootfs != nil && containerStats.Rootfs.UsedBytes != nil && containerStats.Logs != nil && containerStats.Logs.UsedBytes != nil { + usage = resource.NewQuantity(int64(*containerStats.Rootfs.UsedBytes+*containerStats.Logs.UsedBytes), resource.BinarySI) + } + case v1.ResourceMemory: + if containerStats.Memory != nil && containerStats.Memory.WorkingSetBytes != nil { + usage = resource.NewQuantity(int64(*containerStats.Memory.WorkingSetBytes), resource.BinarySI) + } + } + if usage != nil && usage.Cmp(requests) > 0 { + message += fmt.Sprintf(containerMessageFmt, container.Name, usage.String(), requests.String()) + containers = append(containers, container.Name) + containerUsage = append(containerUsage, usage.String()) + } + } + } } - return resourceToReclaimFunc + annotations[OffendingContainersKey] = strings.Join(containers, ",") + annotations[OffendingContainersUsageKey] = strings.Join(containerUsage, ",") + annotations[StarvedResourceKey] = string(resourceToReclaim) + return } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/helpers_test.go index a61d19fee..0ed5a1b67 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/helpers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/helpers_test.go @@ -19,6 +19,7 @@ package eviction import ( "fmt" "reflect" + "sort" "testing" "time" @@ -27,12 +28,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" utilfeature "k8s.io/apiserver/pkg/util/feature" - api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/features" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" - "k8s.io/kubernetes/pkg/quota" ) func quantityMustParse(value string) *resource.Quantity { @@ -468,7 +467,7 @@ func TestOrderedByExceedsRequestDisk(t *testing.T) { return result, found } pods := []*v1.Pod{below, exceeds} - orderedBy(exceedDiskRequests(statsFn, []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, resourceDisk)).Sort(pods) + orderedBy(exceedDiskRequests(statsFn, []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, v1.ResourceEphemeralStorage)).Sort(pods) expected := []*v1.Pod{exceeds, below} for i := range expected { @@ -582,7 +581,7 @@ func TestOrderedbyDisk(t *testing.T) { return result, found } pods := []*v1.Pod{pod1, pod2, pod3, pod4, pod5, pod6} - orderedBy(disk(statsFn, []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, resourceDisk)).Sort(pods) + orderedBy(disk(statsFn, []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, v1.ResourceEphemeralStorage)).Sort(pods) expected := []*v1.Pod{pod1, pod3, pod2, pod4, pod5, pod6} for i := range expected { if pods[i] != expected[i] { @@ -649,7 +648,7 @@ func TestOrderedbyDiskDisableLocalStorage(t *testing.T) { return result, found } pods := []*v1.Pod{pod1, pod3, pod2, pod4, pod5, pod6} - orderedBy(disk(statsFn, []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, resourceDisk)).Sort(pods) + orderedBy(disk(statsFn, []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}, v1.ResourceEphemeralStorage)).Sort(pods) expected := []*v1.Pod{pod5, pod3, pod1, pod6, pod4, pod2} for i := range expected { if pods[i] != expected[i] { @@ -778,7 +777,7 @@ func TestOrderedByPriorityDisk(t *testing.T) { pods := []*v1.Pod{pod8, pod7, pod6, pod5, pod4, pod3, pod2, pod1} expected := []*v1.Pod{pod1, pod2, pod3, pod4, pod5, pod6, pod7, pod8} fsStatsToMeasure := []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource} - orderedBy(exceedDiskRequests(statsFn, fsStatsToMeasure, resourceDisk), priority, disk(statsFn, fsStatsToMeasure, resourceDisk)).Sort(pods) + orderedBy(exceedDiskRequests(statsFn, fsStatsToMeasure, v1.ResourceEphemeralStorage), priority, disk(statsFn, fsStatsToMeasure, v1.ResourceEphemeralStorage)).Sort(pods) for i := range expected { if pods[i] != expected[i] { t.Errorf("Expected pod[%d]: %s, but got: %s", i, expected[i].Name, pods[i].Name) @@ -930,6 +929,80 @@ func TestOrderedByPriorityMemory(t *testing.T) { } } +func TestSortByEvictionPriority(t *testing.T) { + for _, tc := range []struct { + name string + thresholds []evictionapi.Threshold + expected []evictionapi.Threshold + }{ + { + name: "empty threshold list", + thresholds: []evictionapi.Threshold{}, + expected: []evictionapi.Threshold{}, + }, + { + name: "memory first, PID last", + thresholds: []evictionapi.Threshold{ + { + Signal: evictionapi.SignalPIDAvailable, + }, + { + Signal: evictionapi.SignalNodeFsAvailable, + }, + { + Signal: evictionapi.SignalMemoryAvailable, + }, + }, + expected: []evictionapi.Threshold{ + { + Signal: evictionapi.SignalMemoryAvailable, + }, + { + Signal: evictionapi.SignalNodeFsAvailable, + }, + { + Signal: evictionapi.SignalPIDAvailable, + }, + }, + }, + { + name: "allocatable memory first, PID last", + thresholds: []evictionapi.Threshold{ + { + Signal: evictionapi.SignalPIDAvailable, + }, + { + Signal: evictionapi.SignalNodeFsAvailable, + }, + { + Signal: evictionapi.SignalAllocatableMemoryAvailable, + }, + }, + expected: []evictionapi.Threshold{ + { + Signal: evictionapi.SignalAllocatableMemoryAvailable, + }, + { + Signal: evictionapi.SignalNodeFsAvailable, + }, + { + Signal: evictionapi.SignalPIDAvailable, + }, + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + sort.Sort(byEvictionPriority(tc.thresholds)) + for i := range tc.expected { + if tc.thresholds[i].Signal != tc.expected[i].Signal { + t.Errorf("At index %d, expected threshold with signal %s, but got %s", i, tc.expected[i].Signal, tc.thresholds[i].Signal) + } + } + + }) + } +} + type fakeSummaryProvider struct { result *statsapi.Summary } @@ -1620,47 +1693,6 @@ func TestHasNodeConditions(t *testing.T) { } } -func TestGetStarvedResources(t *testing.T) { - testCases := map[string]struct { - inputs []evictionapi.Threshold - result []v1.ResourceName - }{ - "memory.available": { - inputs: []evictionapi.Threshold{ - {Signal: evictionapi.SignalMemoryAvailable}, - }, - result: []v1.ResourceName{v1.ResourceMemory}, - }, - "imagefs.available": { - inputs: []evictionapi.Threshold{ - {Signal: evictionapi.SignalImageFsAvailable}, - }, - result: []v1.ResourceName{resourceImageFs}, - }, - "nodefs.available": { - inputs: []evictionapi.Threshold{ - {Signal: evictionapi.SignalNodeFsAvailable}, - }, - result: []v1.ResourceName{resourceNodeFs}, - }, - } - var internalResourceNames = func(in []v1.ResourceName) []api.ResourceName { - var out []api.ResourceName - for _, name := range in { - out = append(out, api.ResourceName(name)) - } - return out - } - for testName, testCase := range testCases { - actual := getStarvedResources(testCase.inputs) - actualSet := quota.ToSet(internalResourceNames(actual)) - expectedSet := quota.ToSet(internalResourceNames(testCase.result)) - if !actualSet.Equal(expectedSet) { - t.Errorf("Test case: %s, expected: %v, actual: %v", testName, expectedSet, actualSet) - } - } -} - func TestParsePercentage(t *testing.T) { testCases := map[string]struct { hasError bool diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/memory_threshold_notifier.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/memory_threshold_notifier.go new file mode 100644 index 000000000..8d86944f3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/memory_threshold_notifier.go @@ -0,0 +1,135 @@ +/* +Copyright 2018 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 eviction + +import ( + "fmt" + "time" + + "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/api/resource" + statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" + "k8s.io/kubernetes/pkg/kubelet/cm" + evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" +) + +const ( + memoryUsageAttribute = "memory.usage_in_bytes" + // this prevents constantly updating the memcg notifier if synchronize + // is run frequently. + notifierRefreshInterval = 10 * time.Second +) + +type memoryThresholdNotifier struct { + threshold evictionapi.Threshold + cgroupPath string + events chan struct{} + factory NotifierFactory + handler func(string) + notifier CgroupNotifier +} + +var _ ThresholdNotifier = &memoryThresholdNotifier{} + +// NewMemoryThresholdNotifier creates a ThresholdNotifier which is designed to respond to the given threshold. +// UpdateThreshold must be called once before the threshold will be active. +func NewMemoryThresholdNotifier(threshold evictionapi.Threshold, cgroupRoot string, factory NotifierFactory, handler func(string)) (ThresholdNotifier, error) { + cgroups, err := cm.GetCgroupSubsystems() + if err != nil { + return nil, err + } + cgpath, found := cgroups.MountPoints["memory"] + if !found || len(cgpath) == 0 { + return nil, fmt.Errorf("memory cgroup mount point not found") + } + if isAllocatableEvictionThreshold(threshold) { + // for allocatable thresholds, point the cgroup notifier at the allocatable cgroup + cgpath += cgroupRoot + } + return &memoryThresholdNotifier{ + threshold: threshold, + cgroupPath: cgpath, + events: make(chan struct{}), + handler: handler, + factory: factory, + }, nil +} + +func (m *memoryThresholdNotifier) Start() { + glog.Infof("eviction manager: created %s", m.Description()) + for range m.events { + m.handler(fmt.Sprintf("eviction manager: %s crossed", m.Description())) + } +} + +func (m *memoryThresholdNotifier) UpdateThreshold(summary *statsapi.Summary) error { + memoryStats := summary.Node.Memory + if isAllocatableEvictionThreshold(m.threshold) { + allocatableContainer, err := getSysContainer(summary.Node.SystemContainers, statsapi.SystemContainerPods) + if err != nil { + return err + } + memoryStats = allocatableContainer.Memory + } + if memoryStats == nil || memoryStats.UsageBytes == nil || memoryStats.WorkingSetBytes == nil || memoryStats.AvailableBytes == nil { + return fmt.Errorf("summary was incomplete. Expected MemoryStats and all subfields to be non-nil, but got %+v", memoryStats) + } + // Set threshold on usage to capacity - eviction_hard + inactive_file, + // since we want to be notified when working_set = capacity - eviction_hard + inactiveFile := resource.NewQuantity(int64(*memoryStats.UsageBytes-*memoryStats.WorkingSetBytes), resource.BinarySI) + capacity := resource.NewQuantity(int64(*memoryStats.AvailableBytes+*memoryStats.WorkingSetBytes), resource.BinarySI) + evictionThresholdQuantity := evictionapi.GetThresholdQuantity(m.threshold.Value, capacity) + memcgThreshold := capacity.DeepCopy() + memcgThreshold.Sub(*evictionThresholdQuantity) + memcgThreshold.Add(*inactiveFile) + + glog.V(3).Infof("eviction manager: setting %s to %s\n", m.Description(), memcgThreshold.String()) + if m.notifier != nil { + m.notifier.Stop() + } + newNotifier, err := m.factory.NewCgroupNotifier(m.cgroupPath, memoryUsageAttribute, memcgThreshold.Value()) + if err != nil { + return err + } + m.notifier = newNotifier + go m.notifier.Start(m.events) + return nil +} + +func (m *memoryThresholdNotifier) Description() string { + var hard, allocatable string + if isHardEvictionThreshold(m.threshold) { + hard = "hard " + } else { + hard = "soft " + } + if isAllocatableEvictionThreshold(m.threshold) { + allocatable = "allocatable " + } + return fmt.Sprintf("%s%smemory eviction threshold", hard, allocatable) +} + +var _ NotifierFactory = &CgroupNotifierFactory{} + +// CgroupNotifierFactory knows how to make CgroupNotifiers which integrate with the kernel +type CgroupNotifierFactory struct{} + +// NewCgroupNotifier implements the NotifierFactory interface +func (n *CgroupNotifierFactory) NewCgroupNotifier(path, attribute string, threshold int64) (CgroupNotifier, error) { + return NewCgroupNotifier(path, attribute, threshold) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/memory_threshold_notifier_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/memory_threshold_notifier_test.go new file mode 100644 index 000000000..8317e051f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/memory_threshold_notifier_test.go @@ -0,0 +1,270 @@ +/* +Copyright 2018 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 eviction + +import ( + "fmt" + "strings" + "sync" + "testing" + "time" + + "k8s.io/apimachinery/pkg/api/resource" + statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" + evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" +) + +const testCgroupPath = "/sys/fs/cgroups/memory" + +func nodeSummary(available, workingSet, usage resource.Quantity, allocatable bool) *statsapi.Summary { + availableBytes := uint64(available.Value()) + workingSetBytes := uint64(workingSet.Value()) + usageBytes := uint64(usage.Value()) + memoryStats := statsapi.MemoryStats{ + AvailableBytes: &availableBytes, + WorkingSetBytes: &workingSetBytes, + UsageBytes: &usageBytes, + } + if allocatable { + return &statsapi.Summary{ + Node: statsapi.NodeStats{ + SystemContainers: []statsapi.ContainerStats{ + { + Name: statsapi.SystemContainerPods, + Memory: &memoryStats, + }, + }, + }, + } + } + return &statsapi.Summary{ + Node: statsapi.NodeStats{ + Memory: &memoryStats, + }, + } +} + +func newTestMemoryThresholdNotifier(threshold evictionapi.Threshold, factory NotifierFactory, handler func(string)) *memoryThresholdNotifier { + return &memoryThresholdNotifier{ + threshold: threshold, + cgroupPath: testCgroupPath, + events: make(chan struct{}), + factory: factory, + handler: handler, + } +} + +func TestUpdateThreshold(t *testing.T) { + testCases := []struct { + description string + available resource.Quantity + workingSet resource.Quantity + usage resource.Quantity + evictionThreshold evictionapi.Threshold + expectedThreshold resource.Quantity + updateThresholdErr error + expectErr bool + }{ + { + description: "node level threshold", + available: resource.MustParse("3Gi"), + usage: resource.MustParse("2Gi"), + workingSet: resource.MustParse("1Gi"), + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("1Gi"), + }, + }, + expectedThreshold: resource.MustParse("4Gi"), + updateThresholdErr: nil, + expectErr: false, + }, + { + description: "allocatable threshold", + available: resource.MustParse("4Gi"), + usage: resource.MustParse("3Gi"), + workingSet: resource.MustParse("1Gi"), + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalAllocatableMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("1Gi"), + }, + }, + expectedThreshold: resource.MustParse("6Gi"), + updateThresholdErr: nil, + expectErr: false, + }, + { + description: "error updating node level threshold", + available: resource.MustParse("3Gi"), + usage: resource.MustParse("2Gi"), + workingSet: resource.MustParse("1Gi"), + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("1Gi"), + }, + }, + expectedThreshold: resource.MustParse("4Gi"), + updateThresholdErr: fmt.Errorf("unexpected error"), + expectErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + notifierFactory := &MockNotifierFactory{} + notifier := &MockCgroupNotifier{} + m := newTestMemoryThresholdNotifier(tc.evictionThreshold, notifierFactory, nil) + notifierFactory.On("NewCgroupNotifier", testCgroupPath, memoryUsageAttribute, tc.expectedThreshold.Value()).Return(notifier, tc.updateThresholdErr) + var events chan<- struct{} + events = m.events + notifier.On("Start", events).Return() + err := m.UpdateThreshold(nodeSummary(tc.available, tc.workingSet, tc.usage, isAllocatableEvictionThreshold(tc.evictionThreshold))) + if err != nil && !tc.expectErr { + t.Errorf("Unexpected error updating threshold: %v", err) + } else if err == nil && tc.expectErr { + t.Errorf("Expected error updating threshold, but got nil") + } + if !tc.expectErr { + notifierFactory.AssertNumberOfCalls(t, "NewCgroupNotifier", 1) + } + }) + } +} + +func TestStart(t *testing.T) { + noResources := resource.MustParse("0") + threshold := evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: &noResources, + }, + } + notifier := &MockCgroupNotifier{} + notifierFactory := &MockNotifierFactory{} + + var wg sync.WaitGroup + wg.Add(4) + m := newTestMemoryThresholdNotifier(threshold, notifierFactory, func(string) { + wg.Done() + }) + notifierFactory.On("NewCgroupNotifier", testCgroupPath, memoryUsageAttribute, int64(0)).Return(notifier, nil) + var events chan<- struct{} + events = m.events + notifier.On("Start", events).Return() + notifier.On("Stop").Return() + + err := m.UpdateThreshold(nodeSummary(noResources, noResources, noResources, isAllocatableEvictionThreshold(threshold))) + if err != nil { + t.Errorf("Unexpected error updating threshold: %v", err) + } + notifierFactory.AssertNumberOfCalls(t, "NewCgroupNotifier", 1) + + go m.Start() + + for i := 0; i < 4; i++ { + m.events <- struct{}{} + } + wg.Wait() +} + +func TestThresholdDescription(t *testing.T) { + testCases := []struct { + description string + evictionThreshold evictionapi.Threshold + expectedSubstrings []string + omittedSubstrings []string + }{ + { + description: "hard node level threshold", + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("2Gi"), + }, + }, + expectedSubstrings: []string{"hard"}, + omittedSubstrings: []string{"allocatable", "soft"}, + }, + { + description: "soft node level threshold", + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("2Gi"), + }, + GracePeriod: time.Minute * 2, + }, + expectedSubstrings: []string{"soft"}, + omittedSubstrings: []string{"allocatable", "hard"}, + }, + { + description: "hard allocatable threshold", + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalAllocatableMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("2Gi"), + }, + GracePeriod: time.Minute * 2, + }, + expectedSubstrings: []string{"soft", "allocatable"}, + omittedSubstrings: []string{"hard"}, + }, + { + description: "soft allocatable threshold", + evictionThreshold: evictionapi.Threshold{ + Signal: evictionapi.SignalAllocatableMemoryAvailable, + Operator: evictionapi.OpLessThan, + Value: evictionapi.ThresholdValue{ + Quantity: quantityMustParse("2Gi"), + }, + }, + expectedSubstrings: []string{"hard", "allocatable"}, + omittedSubstrings: []string{"soft"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + m := &memoryThresholdNotifier{ + notifier: &MockCgroupNotifier{}, + threshold: tc.evictionThreshold, + cgroupPath: testCgroupPath, + } + desc := m.Description() + for _, expected := range tc.expectedSubstrings { + if !strings.Contains(desc, expected) { + t.Errorf("expected description for notifier with threshold %+v to contain %s, but it did not", tc.evictionThreshold, expected) + } + } + for _, omitted := range tc.omittedSubstrings { + if strings.Contains(desc, omitted) { + t.Errorf("expected description for notifier with threshold %+v NOT to contain %s, but it did", tc.evictionThreshold, omitted) + } + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/mock_threshold_notifier_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/mock_threshold_notifier_test.go new file mode 100644 index 000000000..c94e6fe5f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/mock_threshold_notifier_test.go @@ -0,0 +1,98 @@ +/* +Copyright 2018 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 eviction + +import ( + mock "github.com/stretchr/testify/mock" + statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" +) + +// MockCgroupNotifier is a mock implementation of the CgroupNotifier interface +type MockCgroupNotifier struct { + mock.Mock +} + +// Start implements the NotifierFactory interface +func (m *MockCgroupNotifier) Start(a0 chan<- struct{}) { + m.Called(a0) +} + +// Stop implements the NotifierFactory interface +func (m *MockCgroupNotifier) Stop() { + m.Called() +} + +// MockNotifierFactory is a mock of the NotifierFactory interface +type MockNotifierFactory struct { + mock.Mock +} + +// NewCgroupNotifier implements the NotifierFactory interface +func (m *MockNotifierFactory) NewCgroupNotifier(a0, a1 string, a2 int64) (CgroupNotifier, error) { + ret := m.Called(a0, a1, a2) + + var r0 CgroupNotifier + if rf, ok := ret.Get(0).(func(string, string, int64) CgroupNotifier); ok { + r0 = rf(a0, a1, a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(CgroupNotifier) + } + } + var r1 error + if rf, ok := ret.Get(1).(func(string, string, int64) error); ok { + r1 = rf(a0, a1, a2) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockThresholdNotifier is a mock implementation of the ThresholdNotifier interface +type MockThresholdNotifier struct { + mock.Mock +} + +// Start implements the ThresholdNotifier interface +func (m *MockThresholdNotifier) Start() { + m.Called() +} + +// UpdateThreshold implements the ThresholdNotifier interface +func (m *MockThresholdNotifier) UpdateThreshold(a0 *statsapi.Summary) error { + ret := m.Called(a0) + + var r0 error + if rf, ok := ret.Get(0).(func(*statsapi.Summary) error); ok { + r0 = rf(a0) + } else { + r0 = ret.Error(0) + } + return r0 +} + +// Description implements the ThresholdNotifier interface +func (m *MockThresholdNotifier) Description() string { + ret := m.Called() + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.String(0) + } + return r0 +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/threshold_notifier_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/threshold_notifier_linux.go index 1709cac8b..4fabd7345 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/threshold_notifier_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/threshold_notifier_linux.go @@ -18,100 +18,168 @@ package eviction import ( "fmt" + "sync" + "time" "github.com/golang/glog" "golang.org/x/sys/unix" ) -type memcgThresholdNotifier struct { - watchfd int - controlfd int - eventfd int - handler thresholdNotifierHandlerFunc - description string +const ( + // eventSize is the number of bytes returned by a successful read from an eventfd + // see http://man7.org/linux/man-pages/man2/eventfd.2.html for more information + eventSize = 8 + // numFdEvents is the number of events we can record at once. + // If EpollWait finds more than this, they will be missed. + numFdEvents = 6 +) + +type linuxCgroupNotifier struct { + eventfd int + epfd int + stop chan struct{} + stopLock sync.Mutex } -var _ ThresholdNotifier = &memcgThresholdNotifier{} +var _ CgroupNotifier = &linuxCgroupNotifier{} -// NewMemCGThresholdNotifier sends notifications when a cgroup threshold -// is crossed (in either direction) for a given cgroup attribute -func NewMemCGThresholdNotifier(path, attribute, threshold, description string, handler thresholdNotifierHandlerFunc) (ThresholdNotifier, error) { - watchfd, err := unix.Open(fmt.Sprintf("%s/%s", path, attribute), unix.O_RDONLY, 0) +// NewCgroupNotifier returns a linuxCgroupNotifier, which performs cgroup control operations required +// to receive notifications from the cgroup when the threshold is crossed in either direction. +func NewCgroupNotifier(path, attribute string, threshold int64) (CgroupNotifier, error) { + var watchfd, eventfd, epfd, controlfd int + var err error + watchfd, err = unix.Open(fmt.Sprintf("%s/%s", path, attribute), unix.O_RDONLY, 0) if err != nil { return nil, err } - defer func() { - if err != nil { - unix.Close(watchfd) - } - }() - controlfd, err := unix.Open(fmt.Sprintf("%s/cgroup.event_control", path), unix.O_WRONLY, 0) + defer unix.Close(watchfd) + controlfd, err = unix.Open(fmt.Sprintf("%s/cgroup.event_control", path), unix.O_WRONLY, 0) if err != nil { return nil, err } + defer unix.Close(controlfd) + eventfd, err = unix.Eventfd(0, unix.EFD_CLOEXEC) + if err != nil { + return nil, err + } + if eventfd < 0 { + err = fmt.Errorf("eventfd call failed") + return nil, err + } defer func() { + // Close eventfd if we get an error later in initialization if err != nil { - unix.Close(controlfd) + unix.Close(eventfd) } }() - eventfd, err := unix.Eventfd(0, unix.EFD_CLOEXEC) + epfd, err = unix.EpollCreate1(0) if err != nil { return nil, err } - if eventfd < 0 { - err = fmt.Errorf("eventfd call failed") + if epfd < 0 { + err = fmt.Errorf("EpollCreate1 call failed") return nil, err } defer func() { + // Close epfd if we get an error later in initialization if err != nil { - unix.Close(eventfd) + unix.Close(epfd) } }() - glog.V(2).Infof("eviction: setting notification threshold to %s", threshold) - config := fmt.Sprintf("%d %d %s", eventfd, watchfd, threshold) + config := fmt.Sprintf("%d %d %d", eventfd, watchfd, threshold) _, err = unix.Write(controlfd, []byte(config)) if err != nil { return nil, err } - return &memcgThresholdNotifier{ - watchfd: watchfd, - controlfd: controlfd, - eventfd: eventfd, - handler: handler, - description: description, + return &linuxCgroupNotifier{ + eventfd: eventfd, + epfd: epfd, + stop: make(chan struct{}), }, nil } -func getThresholdEvents(eventfd int, eventCh chan<- struct{}, stopCh <-chan struct{}) { +func (n *linuxCgroupNotifier) Start(eventCh chan<- struct{}) { + err := unix.EpollCtl(n.epfd, unix.EPOLL_CTL_ADD, n.eventfd, &unix.EpollEvent{ + Fd: int32(n.eventfd), + Events: unix.EPOLLIN, + }) + if err != nil { + glog.Warningf("eviction manager: error adding epoll eventfd: %v", err) + return + } for { - buf := make([]byte, 8) - _, err := unix.Read(eventfd, buf) + select { + case <-n.stop: + return + default: + } + event, err := wait(n.epfd, n.eventfd, notifierRefreshInterval) if err != nil { + glog.Warningf("eviction manager: error while waiting for memcg events: %v", err) return + } else if !event { + // Timeout on wait. This is expected if the threshold was not crossed + continue } - - select { - case eventCh <- struct{}{}: - case <-stopCh: + // Consume the event from the eventfd + buf := make([]byte, eventSize) + _, err = unix.Read(n.eventfd, buf) + if err != nil { + glog.Warningf("eviction manager: error reading memcg events: %v", err) return } + eventCh <- struct{}{} } } -func (n *memcgThresholdNotifier) Start(stopCh <-chan struct{}) { - eventCh := make(chan struct{}) - go getThresholdEvents(n.eventfd, eventCh, stopCh) - for { - select { - case <-stopCh: - glog.V(2).Infof("eviction: stopping threshold notifier") - unix.Close(n.watchfd) - unix.Close(n.controlfd) - unix.Close(n.eventfd) - return - case <-eventCh: - glog.V(2).Infof("eviction: threshold crossed") - n.handler(n.description) +// wait waits up to notifierRefreshInterval for an event on the Epoll FD for the +// eventfd we are concerned about. It returns an error if one occurrs, and true +// if the consumer should read from the eventfd. +func wait(epfd, eventfd int, timeout time.Duration) (bool, error) { + events := make([]unix.EpollEvent, numFdEvents+1) + timeoutMS := int(timeout / time.Millisecond) + n, err := unix.EpollWait(epfd, events, timeoutMS) + if n == -1 { + if err == unix.EINTR { + // Interrupt, ignore the error + return false, nil } + return false, err + } + if n == 0 { + // Timeout + return false, nil + } + if n > numFdEvents { + return false, fmt.Errorf("epoll_wait returned more events than we know what to do with") + } + for _, event := range events[:n] { + if event.Fd == int32(eventfd) { + if event.Events&unix.EPOLLHUP != 0 || event.Events&unix.EPOLLERR != 0 || event.Events&unix.EPOLLIN != 0 { + // EPOLLHUP: should not happen, but if it does, treat it as a wakeup. + + // EPOLLERR: If an error is waiting on the file descriptor, we should pretend + // something is ready to read, and let unix.Read pick up the error. + + // EPOLLIN: There is data to read. + return true, nil + } + } + } + // An event occurred that we don't care about. + return false, nil +} + +func (n *linuxCgroupNotifier) Stop() { + n.stopLock.Lock() + defer n.stopLock.Unlock() + select { + case <-n.stop: + // the linuxCgroupNotifier is already stopped + return + default: } + unix.Close(n.eventfd) + unix.Close(n.epfd) + close(n.stop) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/threshold_notifier_unsupported.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/threshold_notifier_unsupported.go index 77a9b26cf..7078c7865 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/threshold_notifier_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/threshold_notifier_unsupported.go @@ -18,10 +18,16 @@ limitations under the License. package eviction -import "fmt" +import "github.com/golang/glog" -// NewMemCGThresholdNotifier sends notifications when a cgroup threshold -// is crossed (in either direction) for a given cgroup attribute -func NewMemCGThresholdNotifier(path, attribute, threshold, description string, handler thresholdNotifierHandlerFunc) (ThresholdNotifier, error) { - return nil, fmt.Errorf("threshold notification not supported") +// NewCgroupNotifier creates a cgroup notifier that does nothing because cgroups do not exist on non-linux systems. +func NewCgroupNotifier(path, attribute string, threshold int64) (CgroupNotifier, error) { + glog.V(5).Infof("cgroup notifications not supported") + return &unsupportedThresholdNotifier{}, nil } + +type unsupportedThresholdNotifier struct{} + +func (*unsupportedThresholdNotifier) Start(_ chan<- struct{}) {} + +func (*unsupportedThresholdNotifier) Stop() {} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/types.go index e4fca84d7..d78e7e069 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/types.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/eviction/types.go @@ -48,6 +48,8 @@ type Config struct { Thresholds []evictionapi.Threshold // KernelMemcgNotification if true will integrate with the kernel memcg notification to determine if memory thresholds are crossed. KernelMemcgNotification bool + // PodCgroupRoot is the cgroup which contains all pods. + PodCgroupRoot string } // Manager evaluates when an eviction threshold for node stability has been met on the node. @@ -129,10 +131,30 @@ type nodeReclaimFunc func() error // nodeReclaimFuncs is an ordered list of nodeReclaimFunc type nodeReclaimFuncs []nodeReclaimFunc -// thresholdNotifierHandlerFunc is a function that takes action in response to a crossed threshold -type thresholdNotifierHandlerFunc func(thresholdDescription string) +// CgroupNotifier generates events from cgroup events +type CgroupNotifier interface { + // Start causes the CgroupNotifier to begin notifying on the eventCh + Start(eventCh chan<- struct{}) + // Stop stops all processes and cleans up file descriptors associated with the CgroupNotifier + Stop() +} + +// NotifierFactory creates CgroupNotifer +type NotifierFactory interface { + // NewCgroupNotifier creates a CgroupNotifier that creates events when the threshold + // on the attribute in the cgroup specified by the path is crossed. + NewCgroupNotifier(path, attribute string, threshold int64) (CgroupNotifier, error) +} -// ThresholdNotifier notifies the user when an attribute crosses a threshold value +// ThresholdNotifier manages CgroupNotifiers based on memory eviction thresholds, and performs a function +// when memory eviction thresholds are crossed type ThresholdNotifier interface { - Start(stopCh <-chan struct{}) + // Start calls the notifier function when the CgroupNotifier notifies the ThresholdNotifier that an event occurred + Start() + // UpdateThreshold updates the memory cgroup threshold based on the metrics provided. + // Calling UpdateThreshold with recent metrics allows the ThresholdNotifier to trigger at the + // eviction threshold more accurately + UpdateThreshold(summary *statsapi.Summary) error + // Description produces a relevant string describing the Memory Threshold Notifier + Description() string } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/BUILD deleted file mode 100644 index 1747aa67a..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "gpu_manager_stub.go", - "types.go", - ], - importpath = "k8s.io/kubernetes/pkg/kubelet/gpu", - deps = ["//vendor/k8s.io/api/core/v1:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/kubelet/gpu/nvidia:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/OWNERS b/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/OWNERS deleted file mode 100644 index 7635d5b58..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/OWNERS +++ /dev/null @@ -1,12 +0,0 @@ -approvers: -- dchen1107 -- derekwaynecarr -- vishh -- yujuhong -reviewers: -- cmluciano -- jiayingz -- mindprince -- RenaudWasTaken -- vishh -- sig-node-reviewers diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/gpu_manager_stub.go b/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/gpu_manager_stub.go deleted file mode 100644 index c0dbcf46c..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/gpu_manager_stub.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -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 gpu - -import ( - "fmt" - - "k8s.io/api/core/v1" -) - -type gpuManagerStub struct{} - -func (gms *gpuManagerStub) Start() error { - return nil -} - -func (gms *gpuManagerStub) Capacity() v1.ResourceList { - return nil -} - -func (gms *gpuManagerStub) AllocateGPU(_ *v1.Pod, _ *v1.Container) ([]string, error) { - return nil, fmt.Errorf("GPUs are not supported") -} - -func NewGPUManagerStub() GPUManager { - return &gpuManagerStub{} -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/BUILD deleted file mode 100644 index 28feb876f..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/BUILD +++ /dev/null @@ -1,54 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "helpers.go", - "nvidia_gpu_manager.go", - ], - importpath = "k8s.io/kubernetes/pkg/kubelet/gpu/nvidia", - deps = [ - "//pkg/kubelet/dockershim:go_default_library", - "//pkg/kubelet/dockershim/libdocker:go_default_library", - "//pkg/kubelet/gpu:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) - -go_test( - name = "go_default_test", - srcs = ["nvidia_gpu_manager_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/kubelet/dockershim:go_default_library", - "//pkg/kubelet/dockershim/libdocker:go_default_library", - "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/api/core/v1: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/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", - ], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/helpers.go b/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/helpers.go deleted file mode 100644 index a6ed7c4f9..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/helpers.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -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 nvidia - -import "k8s.io/apimachinery/pkg/util/sets" - -type containerToGPU map[string]sets.String - -// podGPUs represents a list of pod to GPU mappings. -type podGPUs struct { - podGPUMapping map[string]containerToGPU -} - -func newPodGPUs() *podGPUs { - return &podGPUs{ - podGPUMapping: make(map[string]containerToGPU), - } -} -func (pgpu *podGPUs) pods() sets.String { - ret := sets.NewString() - for k := range pgpu.podGPUMapping { - ret.Insert(k) - } - return ret -} - -func (pgpu *podGPUs) insert(podUID, contName string, device string) { - if _, exists := pgpu.podGPUMapping[podUID]; !exists { - pgpu.podGPUMapping[podUID] = make(containerToGPU) - } - if _, exists := pgpu.podGPUMapping[podUID][contName]; !exists { - pgpu.podGPUMapping[podUID][contName] = sets.NewString() - } - pgpu.podGPUMapping[podUID][contName].Insert(device) -} - -func (pgpu *podGPUs) getGPUs(podUID, contName string) sets.String { - containers, exists := pgpu.podGPUMapping[podUID] - if !exists { - return nil - } - devices, exists := containers[contName] - if !exists { - return nil - } - return devices -} - -func (pgpu *podGPUs) delete(pods []string) { - for _, uid := range pods { - delete(pgpu.podGPUMapping, uid) - } -} - -func (pgpu *podGPUs) devices() sets.String { - ret := sets.NewString() - for _, containerToGPU := range pgpu.podGPUMapping { - for _, deviceSet := range containerToGPU { - ret = ret.Union(deviceSet) - } - } - return ret -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager.go deleted file mode 100644 index 37c30d14b..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager.go +++ /dev/null @@ -1,280 +0,0 @@ -/* -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 nvidia - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "regexp" - "strings" - "sync" - - "github.com/golang/glog" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/kubernetes/pkg/kubelet/dockershim" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - "k8s.io/kubernetes/pkg/kubelet/gpu" -) - -// TODO: rework to use Nvidia's NVML, which is more complex, but also provides more fine-grained information and stats. -const ( - // All NVIDIA GPUs cards should be mounted with nvidiactl and nvidia-uvm - // If the driver installed correctly, the 2 devices will be there. - nvidiaCtlDevice string = "/dev/nvidiactl" - nvidiaUVMDevice string = "/dev/nvidia-uvm" - // Optional device. - nvidiaUVMToolsDevice string = "/dev/nvidia-uvm-tools" - devDirectory = "/dev" -) - -var ( - nvidiaDeviceRE = regexp.MustCompile(`^nvidia[0-9]*$`) - nvidiaFullpathRE = regexp.MustCompile(`^/dev/nvidia[0-9]*$`) -) - -type activePodsLister interface { - // Returns a list of active pods on the node. - GetActivePods() []*v1.Pod -} - -// nvidiaGPUManager manages nvidia gpu devices. -type nvidiaGPUManager struct { - sync.Mutex - // All gpus available on the Node - allGPUs sets.String - allocated *podGPUs - defaultDevices []string - // The interface which could get GPU mapping from all the containers. - // TODO: Should make this independent of Docker in the future. - dockerClient libdocker.Interface - activePodsLister activePodsLister -} - -// NewNvidiaGPUManager returns a GPUManager that manages local Nvidia GPUs. -// TODO: Migrate to use pod level cgroups and make it generic to all runtimes. -func NewNvidiaGPUManager(activePodsLister activePodsLister, config *dockershim.ClientConfig) (gpu.GPUManager, error) { - dockerClient := dockershim.NewDockerClientFromConfig(config) - if dockerClient == nil { - return nil, fmt.Errorf("invalid docker client configure specified") - } - - return &nvidiaGPUManager{ - allGPUs: sets.NewString(), - dockerClient: dockerClient, - activePodsLister: activePodsLister, - }, nil -} - -// Initialize the GPU devices, so far only needed to discover the GPU paths. -func (ngm *nvidiaGPUManager) Start() error { - if ngm.dockerClient == nil { - return fmt.Errorf("Invalid docker client specified in GPU Manager") - } - ngm.Lock() - defer ngm.Unlock() - - if _, err := os.Stat(nvidiaCtlDevice); err != nil { - return err - } - - if _, err := os.Stat(nvidiaUVMDevice); err != nil { - return err - } - ngm.defaultDevices = []string{nvidiaCtlDevice, nvidiaUVMDevice} - _, err := os.Stat(nvidiaUVMToolsDevice) - if !os.IsNotExist(err) { - ngm.defaultDevices = append(ngm.defaultDevices, nvidiaUVMToolsDevice) - } - - if err := ngm.discoverGPUs(); err != nil { - return err - } - - // We ignore errors when identifying allocated GPUs because it is possible that the runtime interfaces may be not be logically up. - return nil -} - -// Get how many GPU cards we have. -func (ngm *nvidiaGPUManager) Capacity() v1.ResourceList { - gpus := resource.NewQuantity(int64(len(ngm.allGPUs)), resource.DecimalSI) - return v1.ResourceList{ - v1.ResourceNvidiaGPU: *gpus, - } -} - -// AllocateGPUs returns `num` GPUs if available, error otherwise. -// Allocation is made thread safe using the following logic. -// A list of all GPUs allocated is maintained along with their respective Pod UIDs. -// It is expected that the list of active pods will not return any false positives. -// As part of initialization or allocation, the list of GPUs in use will be computed once. -// Whenever an allocation happens, the list of GPUs allocated is updated based on the list of currently active pods. -// GPUs allocated to terminated pods are freed up lazily as part of allocation. -// GPUs are allocated based on the internal list of allocatedGPUs. -// It is not safe to generate a list of GPUs in use by inspecting active containers because of the delay between GPU allocation and container creation. -// A GPU allocated to a container might be re-allocated to a subsequent container because the original container wasn't started quick enough. -// The current algorithm scans containers only once and then uses a list of active pods to track GPU usage. -// This is a sub-optimal solution and a better alternative would be that of using pod level cgroups instead. -// GPUs allocated to containers should be reflected in pod level device cgroups before completing allocations. -// The pod level cgroups will then serve as a checkpoint of GPUs in use. -func (ngm *nvidiaGPUManager) AllocateGPU(pod *v1.Pod, container *v1.Container) ([]string, error) { - gpusNeeded := container.Resources.Limits.NvidiaGPU().Value() - if gpusNeeded == 0 { - return []string{}, nil - } - ngm.Lock() - defer ngm.Unlock() - if ngm.allocated == nil { - // Initialization is not complete. Try now. Failures can no longer be tolerated. - ngm.allocated = ngm.gpusInUse() - } else { - // update internal list of GPUs in use prior to allocating new GPUs. - ngm.updateAllocatedGPUs() - } - // Check if GPUs have already been allocated. If so return them right away. - // This can happen if a container restarts for example. - if devices := ngm.allocated.getGPUs(string(pod.UID), container.Name); devices != nil { - glog.V(2).Infof("Found pre-allocated GPUs for container %q in Pod %q: %v", container.Name, pod.UID, devices.List()) - return append(devices.List(), ngm.defaultDevices...), nil - } - // Get GPU devices in use. - devicesInUse := ngm.allocated.devices() - glog.V(5).Infof("gpus in use: %v", devicesInUse.List()) - // Get a list of available GPUs. - available := ngm.allGPUs.Difference(devicesInUse) - glog.V(5).Infof("gpus available: %v", available.List()) - if int64(available.Len()) < gpusNeeded { - return nil, fmt.Errorf("requested number of GPUs unavailable. Requested: %d, Available: %d", gpusNeeded, available.Len()) - } - ret := available.UnsortedList()[:gpusNeeded] - for _, device := range ret { - // Update internal allocated GPU cache. - ngm.allocated.insert(string(pod.UID), container.Name, device) - } - // Add standard devices files that needs to be exposed. - ret = append(ret, ngm.defaultDevices...) - - return ret, nil -} - -// updateAllocatedGPUs updates the list of GPUs in use. -// It gets a list of active pods and then frees any GPUs that are bound to terminated pods. -// Returns error on failure. -func (ngm *nvidiaGPUManager) updateAllocatedGPUs() { - activePods := ngm.activePodsLister.GetActivePods() - activePodUids := sets.NewString() - for _, pod := range activePods { - activePodUids.Insert(string(pod.UID)) - } - allocatedPodUids := ngm.allocated.pods() - podsToBeRemoved := allocatedPodUids.Difference(activePodUids) - glog.V(5).Infof("pods to be removed: %v", podsToBeRemoved.List()) - ngm.allocated.delete(podsToBeRemoved.List()) -} - -// discoverGPUs identifies allGPUs NVIDIA GPU devices available on the local node by walking `/dev` directory. -// TODO: Without NVML support we only can check whether there has GPU devices, but -// could not give a health check or get more information like GPU cores, memory, or -// family name. Need to support NVML in the future. But we do not need NVML until -// we want more features, features like schedule containers according to GPU family -// name. -func (ngm *nvidiaGPUManager) discoverGPUs() error { - files, err := ioutil.ReadDir(devDirectory) - if err != nil { - return err - } - for _, f := range files { - if f.IsDir() { - continue - } - if nvidiaDeviceRE.MatchString(f.Name()) { - glog.V(2).Infof("Found Nvidia GPU %q", f.Name()) - ngm.allGPUs.Insert(path.Join(devDirectory, f.Name())) - } - } - - return nil -} - -// gpusInUse returns a list of GPUs in use along with the respective pods that are using it. -func (ngm *nvidiaGPUManager) gpusInUse() *podGPUs { - pods := ngm.activePodsLister.GetActivePods() - type containerIdentifier struct { - id string - name string - } - type podContainers struct { - uid string - containers []containerIdentifier - } - // List of containers to inspect. - podContainersToInspect := []podContainers{} - for _, pod := range pods { - containers := sets.NewString() - for _, container := range pod.Spec.Containers { - // GPUs are expected to be specified only in limits. - if !container.Resources.Limits.NvidiaGPU().IsZero() { - containers.Insert(container.Name) - } - } - // If no GPUs were requested skip this pod. - if containers.Len() == 0 { - continue - } - // TODO: If kubelet restarts right after allocating a GPU to a pod, the container might not have started yet and so container status might not be available yet. - // Use an internal checkpoint instead or try using the CRI if its checkpoint is reliable. - var containersToInspect []containerIdentifier - for _, container := range pod.Status.ContainerStatuses { - if containers.Has(container.Name) { - containersToInspect = append(containersToInspect, containerIdentifier{strings.Replace(container.ContainerID, "docker://", "", 1), container.Name}) - } - } - // add the pod and its containers that need to be inspected. - podContainersToInspect = append(podContainersToInspect, podContainers{string(pod.UID), containersToInspect}) - } - ret := newPodGPUs() - for _, podContainer := range podContainersToInspect { - for _, containerIdentifier := range podContainer.containers { - containerJSON, err := ngm.dockerClient.InspectContainer(containerIdentifier.id) - if err != nil { - glog.V(3).Infof("Failed to inspect container %q in pod %q while attempting to reconcile nvidia gpus in use", containerIdentifier.id, podContainer.uid) - continue - } - - devices := containerJSON.HostConfig.Devices - if devices == nil { - continue - } - - for _, device := range devices { - if isValidPath(device.PathOnHost) { - glog.V(4).Infof("Nvidia GPU %q is in use by Docker Container: %q", device.PathOnHost, containerJSON.ID) - ret.insert(podContainer.uid, containerIdentifier.name, device.PathOnHost) - } - } - } - } - return ret -} - -func isValidPath(path string) bool { - return nvidiaFullpathRE.MatchString(path) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager_test.go deleted file mode 100644 index 8dc2cd6e6..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager_test.go +++ /dev/null @@ -1,213 +0,0 @@ -/* -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 nvidia - -import ( - "os" - "reflect" - "testing" - - "github.com/stretchr/testify/assert" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/kubernetes/pkg/kubelet/dockershim" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -type testActivePodsLister struct { - activePods []*v1.Pod -} - -func (tapl *testActivePodsLister) GetActivePods() []*v1.Pod { - return tapl.activePods -} - -func makeTestPod(numContainers, gpusPerContainer int) *v1.Pod { - quantity := resource.NewQuantity(int64(gpusPerContainer), resource.DecimalSI) - resources := v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceNvidiaGPU: *quantity, - }, - } - pod := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - UID: uuid.NewUUID(), - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{}, - }, - } - for ; numContainers > 0; numContainers-- { - pod.Spec.Containers = append(pod.Spec.Containers, v1.Container{ - Name: string(uuid.NewUUID()), - Resources: resources, - }) - } - return pod -} - -func TestNewNvidiaGPUManager(t *testing.T) { - podLister := &testActivePodsLister{} - - // Expects nil GPUManager and an error with nil dockerClient. - testGpuManager1, err := NewNvidiaGPUManager(podLister, nil) - as := assert.New(t) - as.Nil(testGpuManager1) - as.NotNil(err) - - // Expects a GPUManager to be created with non-nil dockerClient. - testGpuManager2, err := NewNvidiaGPUManager(podLister, &dockershim.ClientConfig{ - DockerEndpoint: libdocker.FakeDockerEndpoint, - }) - as.NotNil(testGpuManager2) - as.Nil(err) - - // Expects zero capacity without any GPUs. - gpuCapacity := testGpuManager2.Capacity() - as.Equal(len(gpuCapacity), 1) - rgpu := gpuCapacity[v1.ResourceNvidiaGPU] - as.Equal(rgpu.Value(), int64(0)) - - err2 := testGpuManager2.Start() - if !os.IsNotExist(err2) { - gpus := reflect.ValueOf(testGpuManager2).Elem().FieldByName("allGPUs").Len() - as.NotZero(gpus) - } -} - -func TestMultiContainerPodGPUAllocation(t *testing.T) { - podLister := &testActivePodsLister{} - - testGpuManager := &nvidiaGPUManager{ - activePodsLister: podLister, - allGPUs: sets.NewString("/dev/nvidia0", "/dev/nvidia1"), - allocated: newPodGPUs(), - } - - // Expect that no devices are in use. - gpusInUse := testGpuManager.gpusInUse() - as := assert.New(t) - as.Equal(len(gpusInUse.devices()), 0) - - // Allocated GPUs for a pod with two containers. - pod := makeTestPod(2, 1) - // Allocate for the first container. - devices1, err := testGpuManager.AllocateGPU(pod, &pod.Spec.Containers[0]) - as.Nil(err) - as.Equal(len(devices1), 1) - - podLister.activePods = append(podLister.activePods, pod) - // Allocate for the second container. - devices2, err := testGpuManager.AllocateGPU(pod, &pod.Spec.Containers[1]) - as.Nil(err) - as.Equal(len(devices2), 1) - - as.NotEqual(devices1, devices2, "expected containers to get different devices") - - // further allocations should fail. - newPod := makeTestPod(2, 1) - devices1, err = testGpuManager.AllocateGPU(newPod, &newPod.Spec.Containers[0]) - as.NotNil(err, "expected gpu allocation to fail. got: %v", devices1) - - // Now terminate the original pod and observe that GPU allocation for new pod succeeds. - podLister.activePods = podLister.activePods[:0] - - devices1, err = testGpuManager.AllocateGPU(newPod, &newPod.Spec.Containers[0]) - as.Nil(err) - as.Equal(len(devices1), 1) - - podLister.activePods = append(podLister.activePods, newPod) - - devices2, err = testGpuManager.AllocateGPU(newPod, &newPod.Spec.Containers[1]) - as.Nil(err) - as.Equal(len(devices2), 1) - - as.NotEqual(devices1, devices2, "expected containers to get different devices") -} - -func TestMultiPodGPUAllocation(t *testing.T) { - podLister := &testActivePodsLister{} - - testGpuManager := &nvidiaGPUManager{ - activePodsLister: podLister, - allGPUs: sets.NewString("/dev/nvidia0", "/dev/nvidia1"), - allocated: newPodGPUs(), - } - - // Expect that no devices are in use. - gpusInUse := testGpuManager.gpusInUse() - as := assert.New(t) - as.Equal(len(gpusInUse.devices()), 0) - - // Allocated GPUs for a pod with two containers. - podA := makeTestPod(1, 1) - // Allocate for the first container. - devicesA, err := testGpuManager.AllocateGPU(podA, &podA.Spec.Containers[0]) - as.Nil(err) - as.Equal(len(devicesA), 1) - - podLister.activePods = append(podLister.activePods, podA) - - // further allocations should fail. - podB := makeTestPod(1, 1) - // Allocate for the first container. - devicesB, err := testGpuManager.AllocateGPU(podB, &podB.Spec.Containers[0]) - as.Nil(err) - as.Equal(len(devicesB), 1) - as.NotEqual(devicesA, devicesB, "expected pods to get different devices") -} - -func TestPodContainerRestart(t *testing.T) { - podLister := &testActivePodsLister{} - - testGpuManager := &nvidiaGPUManager{ - activePodsLister: podLister, - allGPUs: sets.NewString("/dev/nvidia0", "/dev/nvidia1"), - allocated: newPodGPUs(), - defaultDevices: []string{"/dev/nvidia-smi"}, - } - - // Expect that no devices are in use. - gpusInUse := testGpuManager.gpusInUse() - as := assert.New(t) - as.Equal(len(gpusInUse.devices()), 0) - - // Make a pod with one containers that requests two GPUs. - podA := makeTestPod(1, 2) - // Allocate GPUs - devicesA, err := testGpuManager.AllocateGPU(podA, &podA.Spec.Containers[0]) - as.Nil(err) - as.Equal(len(devicesA), 3) - - podLister.activePods = append(podLister.activePods, podA) - - // further allocations should fail. - podB := makeTestPod(1, 1) - _, err = testGpuManager.AllocateGPU(podB, &podB.Spec.Containers[0]) - as.NotNil(err) - - // Allcate GPU for existing Pod A. - // The same gpus must be returned. - devicesAretry, err := testGpuManager.AllocateGPU(podA, &podA.Spec.Containers[0]) - as.Nil(err) - as.Equal(len(devicesA), 3) - as.True(sets.NewString(devicesA...).Equal(sets.NewString(devicesAretry...))) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/types.go deleted file mode 100644 index b834c9b52..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/gpu/types.go +++ /dev/null @@ -1,32 +0,0 @@ -/* -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 gpu - -import "k8s.io/api/core/v1" - -// GPUManager manages GPUs on a local node. -// Implementations are expected to be thread safe. -type GPUManager interface { - // Start logically initializes GPUManager - Start() error - // Capacity returns the total number of GPUs on the node. - Capacity() v1.ResourceList - // AllocateGPU attempts to allocate GPUs for input container. - // Returns paths to allocated GPUs and nil on success. - // Returns an error on failure. - AllocateGPU(*v1.Pod, *v1.Container) ([]string, error) -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go index 40b694663..ff1e54787 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go @@ -27,7 +27,6 @@ import ( "os" "path" "sort" - "strings" "sync" "sync/atomic" "time" @@ -61,6 +60,7 @@ import ( kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/cadvisor" kubeletcertificate "k8s.io/kubernetes/pkg/kubelet/certificate" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" "k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/configmap" @@ -69,8 +69,6 @@ import ( dockerremote "k8s.io/kubernetes/pkg/kubelet/dockershim/remote" "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/pkg/kubelet/eviction" - "k8s.io/kubernetes/pkg/kubelet/gpu" - "k8s.io/kubernetes/pkg/kubelet/gpu/nvidia" "k8s.io/kubernetes/pkg/kubelet/images" "k8s.io/kubernetes/pkg/kubelet/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/kuberuntime" @@ -78,7 +76,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/logs" "k8s.io/kubernetes/pkg/kubelet/metrics" "k8s.io/kubernetes/pkg/kubelet/metrics/collectors" - "k8s.io/kubernetes/pkg/kubelet/network" "k8s.io/kubernetes/pkg/kubelet/network/dns" "k8s.io/kubernetes/pkg/kubelet/pleg" kubepod "k8s.io/kubernetes/pkg/kubelet/pod" @@ -86,7 +83,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/prober" proberesults "k8s.io/kubernetes/pkg/kubelet/prober/results" "k8s.io/kubernetes/pkg/kubelet/remote" - "k8s.io/kubernetes/pkg/kubelet/rkt" "k8s.io/kubernetes/pkg/kubelet/secret" "k8s.io/kubernetes/pkg/kubelet/server" serverstats "k8s.io/kubernetes/pkg/kubelet/server/stats" @@ -94,13 +90,17 @@ import ( "k8s.io/kubernetes/pkg/kubelet/stats" "k8s.io/kubernetes/pkg/kubelet/status" "k8s.io/kubernetes/pkg/kubelet/sysctl" + "k8s.io/kubernetes/pkg/kubelet/token" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" + "k8s.io/kubernetes/pkg/kubelet/util/manager" + "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" "k8s.io/kubernetes/pkg/kubelet/util/queue" "k8s.io/kubernetes/pkg/kubelet/util/sliceutils" "k8s.io/kubernetes/pkg/kubelet/volumemanager" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/security/apparmor" + sysctlwhitelist "k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl" utildbus "k8s.io/kubernetes/pkg/util/dbus" kubeio "k8s.io/kubernetes/pkg/util/io" utilipt "k8s.io/kubernetes/pkg/util/iptables" @@ -108,6 +108,7 @@ import ( nodeutil "k8s.io/kubernetes/pkg/util/node" "k8s.io/kubernetes/pkg/util/oom" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/csi" utilexec "k8s.io/utils/exec" ) @@ -221,7 +222,8 @@ type Builder func(kubeCfg *kubeletconfiginternal.KubeletConfiguration, keepTerminatedPodVolumes bool, nodeLabels map[string]string, seccompProfileRoot string, - bootstrapCheckpointPath string) (Bootstrap, error) + bootstrapCheckpointPath string, + nodeStatusMaxImages int32) (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 @@ -241,7 +243,6 @@ type Dependencies struct { KubeClient clientset.Interface ExternalKubeClient clientset.Interface Mounter mount.Interface - NetworkPlugins []network.NetworkPlugin OOMAdjuster *oom.OOMAdjuster OSInterface kubecontainer.OSInterface PodConfig *config.PodConfig @@ -347,7 +348,8 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, keepTerminatedPodVolumes bool, nodeLabels map[string]string, seccompProfileRoot string, - bootstrapCheckpointPath string) (*Kubelet, error) { + bootstrapCheckpointPath string, + nodeStatusMaxImages int32) (*Kubelet, error) { if rootDirectory == "" { return nil, fmt.Errorf("invalid root directory %q", rootDirectory) } @@ -444,6 +446,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, MaxPodGracePeriodSeconds: int64(kubeCfg.EvictionMaxPodGracePeriod), Thresholds: thresholds, KernelMemcgNotification: experimentalKernelMemcgNotification, + PodCgroupRoot: kubeDeps.ContainerManager.GetPodCgroupRoot(), } serviceIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) @@ -514,20 +517,22 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, nodeRef: nodeRef, nodeLabels: nodeLabels, nodeStatusUpdateFrequency: kubeCfg.NodeStatusUpdateFrequency.Duration, - os: kubeDeps.OSInterface, - oomWatcher: oomWatcher, - cgroupsPerQOS: kubeCfg.CgroupsPerQOS, - cgroupRoot: kubeCfg.CgroupRoot, - mounter: kubeDeps.Mounter, - writer: kubeDeps.Writer, - maxPods: int(kubeCfg.MaxPods), - podsPerCore: int(kubeCfg.PodsPerCore), - syncLoopMonitor: atomic.Value{}, - daemonEndpoints: daemonEndpoints, - containerManager: kubeDeps.ContainerManager, - containerRuntimeName: containerRuntime, - nodeIP: parsedNodeIP, - clock: clock.RealClock{}, + os: kubeDeps.OSInterface, + oomWatcher: oomWatcher, + cgroupsPerQOS: kubeCfg.CgroupsPerQOS, + cgroupRoot: kubeCfg.CgroupRoot, + mounter: kubeDeps.Mounter, + writer: kubeDeps.Writer, + maxPods: int(kubeCfg.MaxPods), + podsPerCore: int(kubeCfg.PodsPerCore), + syncLoopMonitor: atomic.Value{}, + daemonEndpoints: daemonEndpoints, + containerManager: kubeDeps.ContainerManager, + containerRuntimeName: containerRuntime, + redirectContainerStreaming: crOptions.RedirectContainerStreaming, + nodeIP: parsedNodeIP, + nodeIPValidator: validateNodeIP, + clock: clock.RealClock{}, enableControllerAttachDetach: kubeCfg.EnableControllerAttachDetach, iptClient: utilipt.New(utilexec.New(), utildbus.New(), utilipt.ProtocolIpv4), makeIPTablesUtilChains: kubeCfg.MakeIPTablesUtilChains, @@ -535,33 +540,29 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, iptablesDropBit: int(kubeCfg.IPTablesDropBit), experimentalHostUserNamespaceDefaulting: utilfeature.DefaultFeatureGate.Enabled(features.ExperimentalHostUserNamespaceDefaultingGate), keepTerminatedPodVolumes: keepTerminatedPodVolumes, + nodeStatusMaxImages: nodeStatusMaxImages, + enablePluginsWatcher: utilfeature.DefaultFeatureGate.Enabled(features.KubeletPluginsWatcher), + } + + if klet.cloud != nil { + klet.cloudproviderRequestParallelism = make(chan int, 1) + klet.cloudproviderRequestSync = make(chan int) + // TODO(jchaloup): Make it configurable via --cloud-provider-request-timeout + klet.cloudproviderRequestTimeout = 10 * time.Second } secretManager := secret.NewCachingSecretManager( - kubeDeps.KubeClient, secret.GetObjectTTLFromNodeFunc(klet.GetNode)) + kubeDeps.KubeClient, manager.GetObjectTTLFromNodeFunc(klet.GetNode)) klet.secretManager = secretManager configMapManager := configmap.NewCachingConfigMapManager( - kubeDeps.KubeClient, configmap.GetObjectTTLFromNodeFunc(klet.GetNode)) + kubeDeps.KubeClient, manager.GetObjectTTLFromNodeFunc(klet.GetNode)) klet.configMapManager = configMapManager if klet.experimentalHostUserNamespaceDefaulting { glog.Infof("Experimental host user namespace defaulting is enabled.") } - hairpinMode, err := effectiveHairpinMode(kubeletconfiginternal.HairpinMode(kubeCfg.HairpinMode), containerRuntime, crOptions.NetworkPluginName) - if err != nil { - // This is a non-recoverable error. Returning it up the callstack will just - // lead to retries of the same failure, so just fail hard. - glog.Fatalf("Invalid hairpin mode: %v", err) - } - 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)) - if err != nil { - return nil, err - } - klet.networkPlugin = plug machineInfo, err := klet.cadvisor.MachineInfo() if err != nil { return nil, err @@ -573,8 +574,15 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, klet.livenessManager = proberesults.NewManager() klet.podCache = kubecontainer.NewCache() + var checkpointManager checkpointmanager.CheckpointManager + if bootstrapCheckpointPath != "" { + checkpointManager, err = checkpointmanager.NewCheckpointManager(bootstrapCheckpointPath) + if err != nil { + return nil, fmt.Errorf("failed to initialize checkpoint manager: %+v", err) + } + } // podManager is also responsible for keeping secretManager and configMapManager contents up-to-date. - klet.podManager = kubepod.NewBasicPodManager(kubepod.NewBasicMirrorClient(klet.kubeClient), secretManager, configMapManager) + klet.podManager = kubepod.NewBasicPodManager(kubepod.NewBasicMirrorClient(klet.kubeClient), secretManager, configMapManager, checkpointManager) if remoteRuntimeEndpoint != "" { // remoteImageEndpoint is same as remoteRuntimeEndpoint if not explicitly specified @@ -585,161 +593,110 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, // TODO: These need to become arguments to a standalone docker shim. pluginSettings := dockershim.NetworkPluginSettings{ - HairpinMode: hairpinMode, - NonMasqueradeCIDR: nonMasqueradeCIDR, - PluginName: crOptions.NetworkPluginName, - PluginConfDir: crOptions.CNIConfDir, - PluginBinDir: crOptions.CNIBinDir, - MTU: int(crOptions.NetworkPluginMTU), + HairpinMode: kubeletconfiginternal.HairpinMode(kubeCfg.HairpinMode), + NonMasqueradeCIDR: nonMasqueradeCIDR, + PluginName: crOptions.NetworkPluginName, + PluginConfDir: crOptions.CNIConfDir, + PluginBinDirString: crOptions.CNIBinDir, + MTU: int(crOptions.NetworkPluginMTU), } klet.resourceAnalyzer = serverstats.NewResourceAnalyzer(klet, kubeCfg.VolumeStatsAggPeriod.Duration) - // Remote runtime shim just cannot talk back to kubelet, so it doesn't - // support bandwidth shaping or hostports till #35457. To enable legacy - // features, replace with networkHost. - var nl *NoOpLegacyHost - pluginSettings.LegacyRuntimeHost = nl - - if containerRuntime == kubetypes.RktContainerRuntime { - glog.Warningln("rktnetes has been deprecated in favor of rktlet. Please see https://github.com/kubernetes-incubator/rktlet for more information.") - } - - // rktnetes cannot be run with CRI. - if containerRuntime != kubetypes.RktContainerRuntime { - // kubelet defers to the runtime shim to setup networking. Setting - // this to nil will prevent it from trying to invoke the plugin. - // It's easier to always probe and initialize plugins till cri - // becomes the default. - klet.networkPlugin = nil - // if left at nil, that means it is unneeded - var legacyLogProvider kuberuntime.LegacyLogProvider - - switch containerRuntime { - case kubetypes.DockerContainerRuntime: - // Create and start the CRI shim running as a grpc server. - streamingConfig := getStreamingConfig(kubeCfg, kubeDeps) - ds, err := dockershim.NewDockerService(kubeDeps.DockerClientConfig, crOptions.PodSandboxImage, streamingConfig, - &pluginSettings, runtimeCgroups, kubeCfg.CgroupDriver, crOptions.DockershimRootDirectory, - crOptions.DockerDisableSharedPID) - if err != nil { - return nil, err - } - // For now, the CRI shim redirects the streaming requests to the - // kubelet, which handles the requests using DockerService.. - klet.criHandler = ds + if containerRuntime == "rkt" { + glog.Fatalln("rktnetes has been deprecated in favor of rktlet. Please see https://github.com/kubernetes-incubator/rktlet for more information.") + } - // The unix socket for kubelet <-> dockershim communication. - glog.V(5).Infof("RemoteRuntimeEndpoint: %q, RemoteImageEndpoint: %q", - remoteRuntimeEndpoint, - remoteImageEndpoint) - glog.V(2).Infof("Starting the GRPC server for the docker CRI shim.") - server := dockerremote.NewDockerServer(remoteRuntimeEndpoint, ds) - if err := server.Start(); err != nil { - return nil, err - } + // if left at nil, that means it is unneeded + var legacyLogProvider kuberuntime.LegacyLogProvider - // Create dockerLegacyService when the logging driver is not supported. - supported, err := ds.IsCRISupportedLogDriver() - if err != nil { - return nil, err - } - if !supported { - klet.dockerLegacyService = ds - legacyLogProvider = ds - } - case kubetypes.RemoteContainerRuntime: - // No-op. - break - default: - return nil, fmt.Errorf("unsupported CRI runtime: %q", containerRuntime) - } - runtimeService, imageService, err := getRuntimeAndImageServices(remoteRuntimeEndpoint, remoteImageEndpoint, kubeCfg.RuntimeRequestTimeout) + switch containerRuntime { + case kubetypes.DockerContainerRuntime: + // Create and start the CRI shim running as a grpc server. + streamingConfig := getStreamingConfig(kubeCfg, kubeDeps, crOptions) + ds, err := dockershim.NewDockerService(kubeDeps.DockerClientConfig, crOptions.PodSandboxImage, streamingConfig, + &pluginSettings, runtimeCgroups, kubeCfg.CgroupDriver, crOptions.DockershimRootDirectory, + crOptions.DockerDisableSharedPID, !crOptions.RedirectContainerStreaming) if err != nil { return nil, err } - klet.runtimeService = runtimeService - runtime, err := kuberuntime.NewKubeGenericRuntimeManager( - kubecontainer.FilterEventRecorder(kubeDeps.Recorder), - klet.livenessManager, - seccompProfileRoot, - containerRefManager, - machineInfo, - klet, - kubeDeps.OSInterface, - klet, - httpClient, - imageBackOff, - kubeCfg.SerializeImagePulls, - float32(kubeCfg.RegistryPullQPS), - int(kubeCfg.RegistryBurst), - kubeCfg.CPUCFSQuota, - runtimeService, - imageService, - kubeDeps.ContainerManager.InternalContainerLifecycle(), - legacyLogProvider, - ) - if err != nil { - return nil, err + if crOptions.RedirectContainerStreaming { + klet.criHandler = ds } - klet.containerRuntime = runtime - klet.runner = runtime - if cadvisor.UsingLegacyCadvisorStats(containerRuntime, remoteRuntimeEndpoint) { - klet.StatsProvider = stats.NewCadvisorStatsProvider( - klet.cadvisor, - klet.resourceAnalyzer, - klet.podManager, - klet.runtimeCache, - klet.containerRuntime) - } else { - klet.StatsProvider = stats.NewCRIStatsProvider( - klet.cadvisor, - klet.resourceAnalyzer, - klet.podManager, - klet.runtimeCache, - runtimeService, - imageService, - stats.NewLogMetricsService()) + // The unix socket for kubelet <-> dockershim communication. + glog.V(5).Infof("RemoteRuntimeEndpoint: %q, RemoteImageEndpoint: %q", + remoteRuntimeEndpoint, + remoteImageEndpoint) + glog.V(2).Infof("Starting the GRPC server for the docker CRI shim.") + server := dockerremote.NewDockerServer(remoteRuntimeEndpoint, ds) + if err := server.Start(); err != nil { + return nil, err } - } else { - // rkt uses the legacy, non-CRI, integration. Configure it the old way. - // TODO: Include hairpin mode settings in rkt? - conf := &rkt.Config{ - Path: crOptions.RktPath, - Stage1Image: crOptions.RktStage1Image, - InsecureOptions: "image,ondisk", - } - runtime, err := rkt.New( - crOptions.RktAPIEndpoint, - conf, - klet, - kubeDeps.Recorder, - containerRefManager, - klet, - klet.livenessManager, - httpClient, - klet.networkPlugin, - hairpinMode == kubeletconfiginternal.HairpinVeth, - utilexec.New(), - kubecontainer.RealOS{}, - imageBackOff, - kubeCfg.SerializeImagePulls, - float32(kubeCfg.RegistryPullQPS), - int(kubeCfg.RegistryBurst), - kubeCfg.RuntimeRequestTimeout.Duration, - ) + + // Create dockerLegacyService when the logging driver is not supported. + supported, err := ds.IsCRISupportedLogDriver() if err != nil { return nil, err } - klet.containerRuntime = runtime - klet.runner = kubecontainer.DirectStreamingRunner(runtime) + if !supported { + klet.dockerLegacyService = ds + legacyLogProvider = ds + } + case kubetypes.RemoteContainerRuntime: + // No-op. + break + default: + return nil, fmt.Errorf("unsupported CRI runtime: %q", containerRuntime) + } + runtimeService, imageService, err := getRuntimeAndImageServices(remoteRuntimeEndpoint, remoteImageEndpoint, kubeCfg.RuntimeRequestTimeout) + if err != nil { + return nil, err + } + klet.runtimeService = runtimeService + runtime, err := kuberuntime.NewKubeGenericRuntimeManager( + kubecontainer.FilterEventRecorder(kubeDeps.Recorder), + klet.livenessManager, + seccompProfileRoot, + containerRefManager, + machineInfo, + klet, + kubeDeps.OSInterface, + klet, + httpClient, + imageBackOff, + kubeCfg.SerializeImagePulls, + float32(kubeCfg.RegistryPullQPS), + int(kubeCfg.RegistryBurst), + kubeCfg.CPUCFSQuota, + runtimeService, + imageService, + kubeDeps.ContainerManager.InternalContainerLifecycle(), + legacyLogProvider, + ) + if err != nil { + return nil, err + } + klet.containerRuntime = runtime + klet.streamingRuntime = runtime + klet.runner = runtime + + if cadvisor.UsingLegacyCadvisorStats(containerRuntime, remoteRuntimeEndpoint) { klet.StatsProvider = stats.NewCadvisorStatsProvider( klet.cadvisor, klet.resourceAnalyzer, klet.podManager, klet.runtimeCache, klet.containerRuntime) + } else { + klet.StatsProvider = stats.NewCRIStatsProvider( + klet.cadvisor, + klet.resourceAnalyzer, + klet.podManager, + klet.runtimeCache, + runtimeService, + imageService, + stats.NewLogMetricsService()) } klet.pleg = pleg.NewGenericPLEG(klet.containerRuntime, plegChannelCapacity, plegRelistPeriod, klet.podCache, clock.RealClock{}) @@ -779,21 +736,29 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, klet.statusManager = status.NewManager(klet.kubeClient, klet.podManager, klet) - if utilfeature.DefaultFeatureGate.Enabled(features.RotateKubeletServerCertificate) && kubeDeps.TLSOptions != nil { - var ips []net.IP - cfgAddress := net.ParseIP(kubeCfg.Address) - if cfgAddress == nil || cfgAddress.IsUnspecified() { - localIPs, err := allLocalIPsWithoutLoopback() + if kubeCfg.ServerTLSBootstrap && kubeDeps.TLSOptions != nil && utilfeature.DefaultFeatureGate.Enabled(features.RotateKubeletServerCertificate) { + var ( + ips []net.IP + names []string + ) + + // If the address was explicitly configured, use that. Otherwise, try to + // discover addresses from the cloudprovider. Otherwise, make a best guess. + if cfgAddress := net.ParseIP(kubeCfg.Address); cfgAddress != nil && !cfgAddress.IsUnspecified() { + ips = []net.IP{cfgAddress} + names = []string{klet.GetHostname(), hostnameOverride} + } else if len(cloudIPs) != 0 || len(cloudNames) != 0 { + ips = cloudIPs + names = cloudNames + } else { + localIPs, err := allGlobalUnicastIPs() if err != nil { return nil, err } ips = localIPs - } else { - ips = []net.IP{cfgAddress} + names = []string{klet.GetHostname(), hostnameOverride} } - ips = append(ips, cloudIPs...) - names := append([]string{klet.GetHostname(), hostnameOverride}, cloudNames...) klet.serverCertificateManager, err = kubeletcertificate.NewKubeletServerCertificateManager(klet.kubeClient, kubeCfg, klet.nodeName, ips, names, certDirectory) if err != nil { return nil, fmt.Errorf("failed to initialize certificate manager: %v", err) @@ -814,11 +779,16 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, containerRefManager, kubeDeps.Recorder) + tokenManager := token.NewManager(kubeDeps.KubeClient) + klet.volumePluginMgr, err = - NewInitializedVolumePluginMgr(klet, secretManager, configMapManager, kubeDeps.VolumePlugins, kubeDeps.DynamicPluginProber) + NewInitializedVolumePluginMgr(klet, secretManager, configMapManager, tokenManager, kubeDeps.VolumePlugins, kubeDeps.DynamicPluginProber) if err != nil { return nil, err } + if klet.enablePluginsWatcher { + klet.pluginWatcher = pluginwatcher.NewWatcher(klet.getPluginsDir()) + } // If the experimentalMounterPathFlag is set, we do not want to // check node capabilities since the mount path is not the default @@ -863,25 +833,23 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, klet.evictionManager = evictionManager klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler) - // add sysctl admission - runtimeSupport, err := sysctl.NewRuntimeAdmitHandler(klet.containerRuntime) - if err != nil { - return nil, err - } - safeWhitelist, err := sysctl.NewWhitelist(sysctl.SafeSysctlWhitelist(), v1.SysctlsPodAnnotationKey) - if err != nil { - return nil, err - } - // Safe, whitelisted sysctls can always be used as unsafe sysctls in the spec - // Hence, we concatenate those two lists. - safeAndUnsafeSysctls := append(sysctl.SafeSysctlWhitelist(), allowedUnsafeSysctls...) - unsafeWhitelist, err := sysctl.NewWhitelist(safeAndUnsafeSysctls, v1.UnsafeSysctlsPodAnnotationKey) - if err != nil { - return nil, err + if utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) { + // add sysctl admission + runtimeSupport, err := sysctl.NewRuntimeAdmitHandler(klet.containerRuntime) + if err != nil { + return nil, err + } + + // Safe, whitelisted sysctls can always be used as unsafe sysctls in the spec. + // Hence, we concatenate those two lists. + safeAndUnsafeSysctls := append(sysctlwhitelist.SafeSysctlWhitelist(), allowedUnsafeSysctls...) + sysctlsWhitelist, err := sysctl.NewWhitelist(safeAndUnsafeSysctls) + if err != nil { + return nil, err + } + klet.admitHandlers.AddPodAdmitHandler(runtimeSupport) + klet.admitHandlers.AddPodAdmitHandler(sysctlsWhitelist) } - klet.admitHandlers.AddPodAdmitHandler(runtimeSupport) - klet.admitHandlers.AddPodAdmitHandler(safeWhitelist) - klet.admitHandlers.AddPodAdmitHandler(unsafeWhitelist) // enable active deadline handler activeDeadlineHandler, err := newActiveDeadlineHandler(klet.statusManager, kubeDeps.Recorder, klet.clock) @@ -901,20 +869,6 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, klet.appArmorValidator = apparmor.NewValidator(containerRuntime) klet.softAdmitHandlers.AddPodAdmitHandler(lifecycle.NewAppArmorAdmitHandler(klet.appArmorValidator)) klet.softAdmitHandlers.AddPodAdmitHandler(lifecycle.NewNoNewPrivsAdmitHandler(klet.containerRuntime)) - if utilfeature.DefaultFeatureGate.Enabled(features.Accelerators) { - if containerRuntime == kubetypes.DockerContainerRuntime { - glog.Warningln("Accelerators feature is deprecated and will be removed in v1.11. Please use device plugins instead. They can be enabled using the DevicePlugins feature gate.") - if klet.gpuManager, err = nvidia.NewNvidiaGPUManager(klet, kubeDeps.DockerClientConfig); err != nil { - return nil, err - } - } else { - glog.Errorf("Accelerators feature is supported with docker runtime only. Disabling this feature internally.") - } - } - // Set GPU manager to a stub implementation if it is not enabled or cannot be supported. - if klet.gpuManager == nil { - klet.gpuManager = gpu.NewGPUManagerStub() - } // Finally, put the most recent version of the config on the Kubelet, so // people can see how it was configured. klet.kubeletConfiguration = *kubeCfg @@ -994,9 +948,6 @@ type Kubelet struct { // Volume plugins. volumePluginMgr *volume.VolumePluginMgr - // Network plugin. - networkPlugin network.NetworkPlugin - // Handles container probing. probeManager prober.Manager // Manages container health check results. @@ -1043,6 +994,14 @@ type Kubelet struct { // Cloud provider interface. cloud cloudprovider.Interface + // To keep exclusive access to the cloudproviderRequestParallelism + cloudproviderRequestMux sync.Mutex + // Keep the count of requests processed in parallel (expected to be 1 at most at a given time) + cloudproviderRequestParallelism chan int + // Sync with finished requests + cloudproviderRequestSync chan int + // Request timeout + cloudproviderRequestTimeout time.Duration // Indicates that the node initialization happens in an external cloud controller externalCloudProvider bool @@ -1052,9 +1011,15 @@ type Kubelet struct { // The name of the container runtime containerRuntimeName string + // redirectContainerStreaming enables container streaming redirect. + redirectContainerStreaming bool + // Container runtime. containerRuntime kubecontainer.Runtime + // Streaming runtime handles container streaming. + streamingRuntime kubecontainer.StreamingRuntime + // Container runtime service (needed by container runtime Start()). // TODO(CD): try to make this available without holding a reference in this // struct. For example, by adding a getter to generic runtime. @@ -1131,6 +1096,9 @@ type Kubelet struct { // If non-nil, use this IP address for the node nodeIP net.IP + // use this function to validate the kubelet nodeIP + nodeIPValidator func(net.IP) error + // If non-nil, this is a unique identifier for the node in an external database, eg. cloudprovider providerID string @@ -1190,9 +1158,6 @@ type Kubelet struct { // experimental behavior is desired. experimentalHostUserNamespaceDefaulting bool - // GPU Manager - gpuManager gpu.GPUManager - // dockerLegacyService contains some legacy methods for backward compatibility. // It should be set only when docker is using non json-file logging driver. dockerLegacyService dockershim.DockerLegacyService @@ -1200,15 +1165,23 @@ 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 + + // pluginwatcher is a utility for Kubelet to register different types of node-level plugins + // such as device plugins or CSI plugins. It discovers plugins by monitoring inotify events under the + // directory returned by kubelet.getPluginsDir() + pluginWatcher pluginwatcher.Watcher + + // This flag sets a maximum number of images to report in the node status. + nodeStatusMaxImages int32 + + // This flag indicates that kubelet should start plugin watcher utility server for discovering Kubelet plugins + enablePluginsWatcher bool } -func allLocalIPsWithoutLoopback() ([]net.IP, error) { +func allGlobalUnicastIPs() ([]net.IP, error) { interfaces, err := net.Interfaces() if err != nil { return nil, fmt.Errorf("could not list network interfaces: %v", err) @@ -1222,7 +1195,7 @@ func allLocalIPsWithoutLoopback() ([]net.IP, error) { for _, address := range addresses { switch v := address.(type) { case *net.IPNet: - if !v.IP.IsLoopback() { + if v.IP.IsGlobalUnicast() { ips = append(ips, v.IP) } } @@ -1271,6 +1244,12 @@ func (kl *Kubelet) StartGarbageCollection() { } }, ContainerGCPeriod, wait.NeverStop) + // when the high threshold is set to 100, stub the image GC manager + if kl.kubeletConfiguration.ImageGCHighThresholdPercent == 100 { + glog.V(2).Infof("ImageGCHighThresholdPercent is set 100, Disable image GC") + return + } + prevImageGCFailed := false go wait.Until(func() { if err := kl.imageManager.GarbageCollect(); err != nil { @@ -1315,8 +1294,8 @@ func (kl *Kubelet) initializeModules() error { // Start the image manager. kl.imageManager.Start() - // Start the certificate manager. - if utilfeature.DefaultFeatureGate.Enabled(features.RotateKubeletServerCertificate) { + // Start the certificate manager if it was enabled. + if kl.serverCertificateManager != nil { kl.serverCertificateManager.Start() } @@ -1325,11 +1304,6 @@ func (kl *Kubelet) initializeModules() error { return fmt.Errorf("Failed to start OOM watcher %v", err) } - // Initialize GPUs - if err := kl.gpuManager.Start(); err != nil { - glog.Errorf("Failed to start gpuManager %v", err) - } - // Start resource analyzer kl.resourceAnalyzer.Start() @@ -1364,6 +1338,16 @@ func (kl *Kubelet) initializeRuntimeDependentModules() { // container log manager must start after container runtime is up to retrieve information from container runtime // and inform container to reopen log file after log rotation. kl.containerLogManager.Start() + if kl.enablePluginsWatcher { + // Adding Registration Callback function for CSI Driver + kl.pluginWatcher.AddHandler("CSIPlugin", csi.RegistrationCallback) + // Start the plugin watcher + glog.V(4).Infof("starting watcher") + if err := kl.pluginWatcher.Start(); err != nil { + kl.recorder.Eventf(kl.nodeRef, v1.EventTypeWarning, events.KubeletSetupFailed, err.Error()) + glog.Fatalf("failed to start Plugin Watcher. err: %v", err) + } + } } // Run starts the kubelet reacting to config updates @@ -1387,7 +1371,6 @@ func (kl *Kubelet) Run(updates <-chan kubetypes.PodUpdate) { // Start syncing node status immediately, this may set up things the runtime needs to run. go wait.Until(kl.syncNodeStatus, kl.nodeStatusUpdateFrequency, wait.NeverStop) } - go wait.Until(kl.syncNetworkStatus, 30*time.Second, wait.NeverStop) go wait.Until(kl.updateRuntimeUp, 5*time.Second, wait.NeverStop) // Start loop to sync iptables util rules @@ -1413,13 +1396,6 @@ func (kl *Kubelet) Run(updates <-chan kubetypes.PodUpdate) { kl.syncLoop(updates, kl) } -// GetKubeClient returns the Kubernetes client. -// TODO: This is currently only required by network plugins. Replace -// with more specific methods. -func (kl *Kubelet) GetKubeClient() clientset.Interface { - return kl.kubeClient -} - // syncPod is the transaction script for the sync of a single pod. // // Arguments: @@ -2071,11 +2047,18 @@ func (kl *Kubelet) HandlePodRemoves(pods []*v1.Pod) { // HandlePodReconcile is the callback in the SyncHandler interface for pods // that should be reconciled. func (kl *Kubelet) HandlePodReconcile(pods []*v1.Pod) { + start := kl.clock.Now() for _, pod := range pods { // Update the pod in pod manager, status manager will do periodically reconcile according // to the pod manager. kl.podManager.UpdatePod(pod) + // Reconcile Pod "Ready" condition if necessary. Trigger sync pod for reconciliation. + if status.NeedToReconcilePodReadiness(pod) { + mirrorPod, _ := kl.podManager.GetMirrorPodByPod(pod) + kl.dispatchWork(pod, kubetypes.SyncPodSync, mirrorPod, start) + } + // After an evicted pod is synced, all dead containers in the pod can be removed. if eviction.PodIsEvicted(pod.Status) { if podStatus, err := kl.podCache.Get(pod.UID); err == nil { @@ -2114,53 +2097,35 @@ func (kl *Kubelet) updateRuntimeUp() { glog.Errorf("Container runtime sanity check failed: %v", err) return } - // rkt uses the legacy, non-CRI integration. Don't check the runtime - // conditions for it. - if kl.containerRuntimeName != kubetypes.RktContainerRuntime { - if s == nil { - glog.Errorf("Container runtime status is nil") - return - } - // Periodically log the whole runtime status for debugging. - // TODO(random-liu): Consider to send node event when optional - // condition is unmet. - glog.V(4).Infof("Container runtime status: %v", s) - networkReady := s.GetRuntimeCondition(kubecontainer.NetworkReady) - if networkReady == nil || !networkReady.Status { - glog.Errorf("Container runtime network not ready: %v", networkReady) - kl.runtimeState.setNetworkState(fmt.Errorf("runtime network not ready: %v", networkReady)) - } else { - // Set nil if the container runtime network is ready. - kl.runtimeState.setNetworkState(nil) - } - // TODO(random-liu): Add runtime error in runtimeState, and update it - // when runtime is not ready, so that the information in RuntimeReady - // condition will be propagated to NodeReady condition. - runtimeReady := s.GetRuntimeCondition(kubecontainer.RuntimeReady) - // If RuntimeReady is not set or is false, report an error. - if runtimeReady == nil || !runtimeReady.Status { - glog.Errorf("Container runtime not ready: %v", runtimeReady) - return - } + if s == nil { + glog.Errorf("Container runtime status is nil") + return + } + // Periodically log the whole runtime status for debugging. + // TODO(random-liu): Consider to send node event when optional + // condition is unmet. + glog.V(4).Infof("Container runtime status: %v", s) + networkReady := s.GetRuntimeCondition(kubecontainer.NetworkReady) + if networkReady == nil || !networkReady.Status { + glog.Errorf("Container runtime network not ready: %v", networkReady) + kl.runtimeState.setNetworkState(fmt.Errorf("runtime network not ready: %v", networkReady)) + } else { + // Set nil if the container runtime network is ready. + kl.runtimeState.setNetworkState(nil) + } + // TODO(random-liu): Add runtime error in runtimeState, and update it + // when runtime is not ready, so that the information in RuntimeReady + // condition will be propagated to NodeReady condition. + runtimeReady := s.GetRuntimeCondition(kubecontainer.RuntimeReady) + // If RuntimeReady is not set or is false, report an error. + if runtimeReady == nil || !runtimeReady.Status { + glog.Errorf("Container runtime not ready: %v", runtimeReady) + return } kl.oneTimeInitializer.Do(kl.initializeRuntimeDependentModules) kl.runtimeState.setRuntimeSync(kl.clock.Now()) } -// updateCloudProviderFromMachineInfo updates the node's provider ID field -// from the given cadvisor machine info. -func (kl *Kubelet) updateCloudProviderFromMachineInfo(node *v1.Node, info *cadvisorapi.MachineInfo) { - if info.CloudProvider != cadvisorapi.UnknownProvider && - info.CloudProvider != cadvisorapi.Baremetal { - // The cloud providers from pkg/cloudprovider/providers/* that update ProviderID - // will use the format of cloudprovider://project/availability_zone/instance_name - // here we only have the cloudprovider and the instance name so we leave project - // and availability zone empty for compatibility. - node.Spec.ProviderID = strings.ToLower(string(info.CloudProvider)) + - ":////" + string(info.InstanceID) - } -} - // GetConfiguration returns the KubeletConfiguration used to configure the kubelet. func (kl *Kubelet) GetConfiguration() kubeletconfiginternal.KubeletConfiguration { return kl.kubeletConfiguration @@ -2172,11 +2137,6 @@ func (kl *Kubelet) BirthCry() { kl.recorder.Eventf(kl.nodeRef, v1.EventTypeNormal, events.StartingKubelet, "Starting kubelet.") } -// StreamingConnectionIdleTimeout returns the timeout for streaming connections to the HTTP server. -func (kl *Kubelet) StreamingConnectionIdleTimeout() time.Duration { - return kl.streamingConnectionIdleTimeout -} - // ResyncInterval returns the interval used for periodic syncs. func (kl *Kubelet) ResyncInterval() time.Duration { return kl.resyncInterval @@ -2184,12 +2144,12 @@ func (kl *Kubelet) ResyncInterval() time.Duration { // ListenAndServe runs the kubelet HTTP server. func (kl *Kubelet) ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableDebuggingHandlers, enableContentionProfiling bool) { - server.ListenAndServeKubeletServer(kl, kl.resourceAnalyzer, address, port, tlsOptions, auth, enableDebuggingHandlers, enableContentionProfiling, kl.containerRuntime, kl.criHandler) + server.ListenAndServeKubeletServer(kl, kl.resourceAnalyzer, address, port, tlsOptions, auth, enableDebuggingHandlers, enableContentionProfiling, kl.redirectContainerStreaming, kl.criHandler) } // ListenAndServeReadOnly runs the kubelet HTTP server in read-only mode. func (kl *Kubelet) ListenAndServeReadOnly(address net.IP, port uint) { - server.ListenAndServeKubeletReadOnlyServer(kl, kl.resourceAnalyzer, address, port, kl.containerRuntime) + server.ListenAndServeKubeletReadOnlyServer(kl, kl.resourceAnalyzer, address, port) } // Delete the eligible dead container instances in a pod. Depending on the configuration, the latest dead containers may be kept around. @@ -2213,19 +2173,23 @@ func isSyncPodWorthy(event *pleg.PodLifecycleEvent) bool { } // Gets the streaming server configuration to use with in-process CRI shims. -func getStreamingConfig(kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *Dependencies) *streaming.Config { +func getStreamingConfig(kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *Dependencies, crOptions *config.ContainerRuntimeOptions) *streaming.Config { config := &streaming.Config{ - // Use a relative redirect (no scheme or host). - BaseURL: &url.URL{ - Path: "/cri/", - }, StreamIdleTimeout: kubeCfg.StreamingConnectionIdleTimeout.Duration, StreamCreationTimeout: streaming.DefaultConfig.StreamCreationTimeout, SupportedRemoteCommandProtocols: streaming.DefaultConfig.SupportedRemoteCommandProtocols, SupportedPortForwardProtocols: streaming.DefaultConfig.SupportedPortForwardProtocols, } - if kubeDeps.TLSOptions != nil { - config.TLSConfig = kubeDeps.TLSOptions.Config + if !crOptions.RedirectContainerStreaming { + config.Addr = net.JoinHostPort("localhost", "0") + } else { + // Use a relative redirect (no scheme or host). + config.BaseURL = &url.URL{ + Path: "/cri/", + } + if kubeDeps.TLSOptions != nil { + config.TLSConfig = kubeDeps.TLSOptions.Config + } } return config } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_getters.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_getters.go index 04284f6e3..89077eb7f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_getters.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_getters.go @@ -174,6 +174,16 @@ func (kl *Kubelet) GetPodByName(namespace, name string) (*v1.Pod, bool) { return kl.podManager.GetPodByName(namespace, name) } +// GetPodByCgroupfs provides the pod that maps to the specified cgroup, as well +// as whether the pod was found. +func (kl *Kubelet) GetPodByCgroupfs(cgroupfs string) (*v1.Pod, bool) { + pcm := kl.containerManager.NewPodContainerManager() + if result, podUID := pcm.IsPodCgroup(cgroupfs); result { + return kl.podManager.GetPodByUID(podUID) + } + return nil, false +} + // GetHostname Returns the hostname as the kubelet sees it. func (kl *Kubelet) GetHostname() string { return kl.hostname diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network.go index c33b5a7ed..fd7a84e48 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network.go @@ -21,12 +21,7 @@ import ( "github.com/golang/glog" "k8s.io/api/core/v1" - clientset "k8s.io/client-go/kubernetes" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/network" - kubetypes "k8s.io/kubernetes/pkg/kubelet/types" utiliptables "k8s.io/kubernetes/pkg/util/iptables" ) @@ -45,106 +40,6 @@ const ( KubeFirewallChain utiliptables.Chain = "KUBE-FIREWALL" ) -// This just exports required functions from kubelet proper, for use by network -// plugins. -// TODO(#35457): get rid of this backchannel to the kubelet. The scope of -// the back channel is restricted to host-ports/testing, and restricted -// to kubenet. No other network plugin wrapper needs it. Other plugins -// only require a way to access namespace information, which they can do -// directly through the methods implemented by criNetworkHost. -type networkHost struct { - kubelet *Kubelet -} - -func (nh *networkHost) GetPodByName(name, namespace string) (*v1.Pod, bool) { - return nh.kubelet.GetPodByName(name, namespace) -} - -func (nh *networkHost) GetKubeClient() clientset.Interface { - return nh.kubelet.kubeClient -} - -func (nh *networkHost) GetRuntime() kubecontainer.Runtime { - return nh.kubelet.getRuntime() -} - -func (nh *networkHost) SupportsLegacyFeatures() bool { - return true -} - -// criNetworkHost implements the part of network.Host required by the -// cri (NamespaceGetter). It leechs off networkHost for all other -// methods, because networkHost is slated for deletion. -type criNetworkHost struct { - *networkHost - // criNetworkHost currently support legacy features. Hence no need to support PortMappingGetter - *network.NoopPortMappingGetter -} - -// GetNetNS returns the network namespace of the given containerID. -// This method satisfies the network.NamespaceGetter interface for -// networkHost. It's only meant to be used from network plugins -// that are directly invoked by the kubelet (aka: legacy, pre-cri). -// Any network plugin invoked by a cri must implement NamespaceGetter -// to talk directly to the runtime instead. -func (c *criNetworkHost) GetNetNS(containerID string) (string, error) { - return c.kubelet.getRuntime().GetNetNS(kubecontainer.ContainerID{Type: "", ID: containerID}) -} - -// NoOpLegacyHost implements the network.LegacyHost interface for the remote -// runtime shim by just returning empties. It doesn't support legacy features -// like host port and bandwidth shaping. -type NoOpLegacyHost struct{} - -// GetPodByName always returns "nil, true" for 'NoOpLegacyHost' -func (n *NoOpLegacyHost) GetPodByName(namespace, name string) (*v1.Pod, bool) { - return nil, true -} - -// GetKubeClient always returns "nil" for 'NoOpLegacyHost' -func (n *NoOpLegacyHost) GetKubeClient() clientset.Interface { - return nil -} - -// getRuntime always returns "nil" for 'NoOpLegacyHost' -func (n *NoOpLegacyHost) GetRuntime() kubecontainer.Runtime { - return nil -} - -// SupportsLegacyFeatures always returns "false" for 'NoOpLegacyHost' -func (n *NoOpLegacyHost) SupportsLegacyFeatures() bool { - return false -} - -// effectiveHairpinMode determines the effective hairpin mode given the -// configured mode, container runtime, and whether cbr0 should be configured. -func effectiveHairpinMode(hairpinMode kubeletconfig.HairpinMode, containerRuntime string, networkPlugin string) (kubeletconfig.HairpinMode, error) { - // The hairpin mode setting doesn't matter if: - // - We're not using a bridge network. This is hard to check because we might - // be using a plugin. - // - It's set to hairpin-veth for a container runtime that doesn't know how - // to set the hairpin flag on the veth's of containers. Currently the - // docker runtime is the only one that understands this. - // - It's set to "none". - if hairpinMode == kubeletconfig.PromiscuousBridge || hairpinMode == kubeletconfig.HairpinVeth { - // Only on docker. - if containerRuntime != kubetypes.DockerContainerRuntime { - glog.Warningf("Hairpin mode set to %q but container runtime is %q, ignoring", hairpinMode, containerRuntime) - return kubeletconfig.HairpinNone, nil - } - if hairpinMode == kubeletconfig.PromiscuousBridge && networkPlugin != "kubenet" { - // This is not a valid combination, since promiscuous-bridge only works on kubenet. Users might be using the - // default values (from before the hairpin-mode flag existed) and we - // should keep the old behavior. - glog.Warningf("Hairpin mode set to %q but kubenet is not enabled, falling back to %q", hairpinMode, kubeletconfig.HairpinVeth) - return kubeletconfig.HairpinVeth, nil - } - } else if hairpinMode != kubeletconfig.HairpinNone { - return "", fmt.Errorf("unknown value: %q", hairpinMode) - } - return hairpinMode, nil -} - // providerRequiresNetworkingConfiguration returns whether the cloud provider // requires special networking configuration. func (kl *Kubelet) providerRequiresNetworkingConfiguration() bool { @@ -159,16 +54,6 @@ func (kl *Kubelet) providerRequiresNetworkingConfiguration() bool { return supported } -// syncNetworkStatus updates the network state -func (kl *Kubelet) syncNetworkStatus() { - // For cri integration, network state will be updated in updateRuntimeUp, - // we'll get runtime network status through cri directly. - // TODO: Remove this once we completely switch to cri integration. - if kl.networkPlugin != nil { - kl.runtimeState.setNetworkState(kl.networkPlugin.Status()) - } -} - // updatePodCIDR updates the pod CIDR in the runtime state if it is different // from the current CIDR. func (kl *Kubelet) updatePodCIDR(cidr string) { @@ -178,16 +63,8 @@ func (kl *Kubelet) updatePodCIDR(cidr string) { return } - // kubelet -> network plugin - // cri runtime shims are responsible for their own network plugins - if kl.networkPlugin != nil { - details := make(map[string]interface{}) - details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR] = cidr - kl.networkPlugin.Event(network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE, details) - } - // kubelet -> generic runtime -> runtime shim -> network plugin - // docker/rkt non-cri implementations have a passthrough UpdatePodCIDR + // docker/non-cri implementations have a passthrough UpdatePodCIDR if err := kl.getRuntime().UpdatePodCIDR(cidr); err != nil { glog.Errorf("Failed to update pod CIDR: %v", err) return diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network_test.go index edc91af2b..7e611766c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network_test.go @@ -17,174 +17,11 @@ limitations under the License. package kubelet import ( - "fmt" - "net" "testing" "github.com/stretchr/testify/assert" ) -func TestNetworkHostGetsPodNotFound(t *testing.T) { - testKubelet := newTestKubelet(t, true) - defer testKubelet.Cleanup() - nh := networkHost{testKubelet.kubelet} - - actualPod, _ := nh.GetPodByName("", "") - if actualPod != nil { - t.Fatalf("Was expected nil, received %v instead", actualPod) - } -} - -func TestNetworkHostGetsKubeClient(t *testing.T) { - testKubelet := newTestKubelet(t, true) - defer testKubelet.Cleanup() - nh := networkHost{testKubelet.kubelet} - - if nh.GetKubeClient() != testKubelet.fakeKubeClient { - t.Fatalf("NetworkHost client does not match testKubelet's client") - } -} - -func TestNetworkHostGetsRuntime(t *testing.T) { - testKubelet := newTestKubelet(t, true) - defer testKubelet.Cleanup() - nh := networkHost{testKubelet.kubelet} - - if nh.GetRuntime() != testKubelet.fakeRuntime { - t.Fatalf("NetworkHost runtime does not match testKubelet's runtime") - } -} - -func TestNetworkHostSupportsLegacyFeatures(t *testing.T) { - testKubelet := newTestKubelet(t, true) - defer testKubelet.Cleanup() - nh := networkHost{testKubelet.kubelet} - - if nh.SupportsLegacyFeatures() == false { - t.Fatalf("SupportsLegacyFeatures should not be false") - } -} - -func TestNoOpHostGetsName(t *testing.T) { - nh := NoOpLegacyHost{} - pod, err := nh.GetPodByName("", "") - if pod != nil && err != true { - t.Fatalf("noOpLegacyHost getpodbyname expected to be nil and true") - } -} - -func TestNoOpHostGetsKubeClient(t *testing.T) { - nh := NoOpLegacyHost{} - if nh.GetKubeClient() != nil { - t.Fatalf("noOpLegacyHost client expected to be nil") - } -} - -func TestNoOpHostGetsRuntime(t *testing.T) { - nh := NoOpLegacyHost{} - if nh.GetRuntime() != nil { - t.Fatalf("noOpLegacyHost runtime expected to be nil") - } -} - -func TestNoOpHostSupportsLegacyFeatures(t *testing.T) { - nh := NoOpLegacyHost{} - if nh.SupportsLegacyFeatures() != false { - t.Fatalf("noOpLegacyHost legacy features expected to be false") - } -} - -func TestNodeIPParam(t *testing.T) { - type test struct { - nodeIP string - success bool - testName string - } - tests := []test{ - { - nodeIP: "", - success: false, - testName: "IP not set", - }, - { - nodeIP: "127.0.0.1", - success: false, - testName: "IPv4 loopback address", - }, - { - nodeIP: "::1", - success: false, - testName: "IPv6 loopback address", - }, - { - nodeIP: "224.0.0.1", - success: false, - testName: "multicast IPv4 address", - }, - { - nodeIP: "ff00::1", - success: false, - testName: "multicast IPv6 address", - }, - { - nodeIP: "169.254.0.1", - success: false, - testName: "IPv4 link-local unicast address", - }, - { - nodeIP: "fe80::0202:b3ff:fe1e:8329", - success: false, - testName: "IPv6 link-local unicast address", - }, - { - nodeIP: "0.0.0.0", - success: false, - testName: "Unspecified IPv4 address", - }, - { - nodeIP: "::", - success: false, - testName: "Unspecified IPv6 address", - }, - { - nodeIP: "1.2.3.4", - success: false, - testName: "IPv4 address that doesn't belong to host", - }, - } - addrs, err := net.InterfaceAddrs() - if err != nil { - assert.Error(t, err, fmt.Sprintf( - "Unable to obtain a list of the node's unicast interface addresses.")) - } - for _, addr := range addrs { - var ip net.IP - switch v := addr.(type) { - case *net.IPNet: - ip = v.IP - case *net.IPAddr: - ip = v.IP - } - if ip.IsLoopback() || ip.IsLinkLocalUnicast() { - break - } - successTest := test{ - nodeIP: ip.String(), - success: true, - testName: fmt.Sprintf("Success test case for address %s", ip.String()), - } - tests = append(tests, successTest) - } - for _, test := range tests { - err := validateNodeIP(net.ParseIP(test.nodeIP)) - if test.success { - assert.NoError(t, err, "test %s", test.testName) - } else { - assert.Error(t, err, fmt.Sprintf("test %s", test.testName)) - } - } -} - func TestGetIPTablesMark(t *testing.T) { tests := []struct { bit int diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status.go index 1907ee311..4126eb997 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status.go @@ -49,9 +49,6 @@ import ( ) const ( - // maxImagesInNodeStatus is the number of max images we store in image status. - maxImagesInNodeStatus = 50 - // maxNamesPerImageInNodeStatus is max number of names per image stored in // the node status. maxNamesPerImageInNodeStatus = 5 @@ -123,34 +120,35 @@ func (kl *Kubelet) tryRegisterWithAPIServer(node *v1.Node) bool { return false } - if existingNode.Spec.ExternalID == node.Spec.ExternalID { - glog.Infof("Node %s was previously registered", kl.nodeName) + glog.Infof("Node %s was previously registered", kl.nodeName) - // Edge case: the node was previously registered; reconcile - // the value of the controller-managed attach-detach - // annotation. - requiresUpdate := kl.reconcileCMADAnnotationWithExistingNode(node, existingNode) - requiresUpdate = kl.updateDefaultLabels(node, existingNode) || requiresUpdate - if requiresUpdate { - if _, _, err := nodeutil.PatchNodeStatus(kl.kubeClient.CoreV1(), types.NodeName(kl.nodeName), originalNode, existingNode); err != nil { - glog.Errorf("Unable to reconcile node %q with API server: error updating node: %v", kl.nodeName, err) - return false - } + // Edge case: the node was previously registered; reconcile + // the value of the controller-managed attach-detach + // annotation. + requiresUpdate := kl.reconcileCMADAnnotationWithExistingNode(node, existingNode) + requiresUpdate = kl.updateDefaultLabels(node, existingNode) || requiresUpdate + requiresUpdate = kl.reconcileExtendedResource(node, existingNode) || requiresUpdate + if requiresUpdate { + if _, _, err := nodeutil.PatchNodeStatus(kl.kubeClient.CoreV1(), types.NodeName(kl.nodeName), originalNode, existingNode); err != nil { + glog.Errorf("Unable to reconcile node %q with API server: error updating node: %v", kl.nodeName, err) + return false } - - return true } - glog.Errorf("Previously node %q had externalID %q; now it is %q; will delete and recreate.", - kl.nodeName, node.Spec.ExternalID, existingNode.Spec.ExternalID, - ) - if err := kl.kubeClient.CoreV1().Nodes().Delete(node.Name, nil); err != nil { - glog.Errorf("Unable to register node %q with API server: error deleting old node: %v", kl.nodeName, err) - } else { - glog.Infof("Deleted old node object %q", kl.nodeName) - } + return true +} - return false +// Zeros out extended resource capacity during reconciliation. +func (kl *Kubelet) reconcileExtendedResource(initialNode, node *v1.Node) bool { + requiresUpdate := false + for k := range node.Status.Capacity { + if v1helper.IsExtendedResourceName(k) { + node.Status.Capacity[k] = *resource.NewQuantity(int64(0), resource.DecimalSI) + node.Status.Allocatable[k] = *resource.NewQuantity(int64(0), resource.DecimalSI) + requiresUpdate = true + } + } + return requiresUpdate } // updateDefaultLabels will set the default labels on the node @@ -300,18 +298,10 @@ func (kl *Kubelet) initialNode() (*v1.Node, error) { return nil, fmt.Errorf("failed to get instances from cloud provider") } - // TODO(roberthbailey): Can we do this without having credentials to talk - // to the cloud provider? - // TODO: ExternalID is deprecated, we'll have to drop this code - externalID, err := instances.ExternalID(context.TODO(), kl.nodeName) - if err != nil { - return nil, fmt.Errorf("failed to get external ID from cloud provider: %v", err) - } - node.Spec.ExternalID = externalID - // TODO: We can't assume that the node has credentials to talk to the // cloudprovider from arbitrary nodes. At most, we should talk to a // local metadata server here. + var err error if node.Spec.ProviderID == "" { node.Spec.ProviderID, err = cloudprovider.GetInstanceProviderID(context.TODO(), kl.cloud, kl.nodeName) if err != nil { @@ -343,14 +333,37 @@ func (kl *Kubelet) initialNode() (*v1.Node, error) { node.ObjectMeta.Labels[kubeletapis.LabelZoneRegion] = zone.Region } } - } else { - node.Spec.ExternalID = kl.hostname } + kl.setNodeStatus(node) return node, nil } +// setVolumeLimits updates volume limits on the node +func (kl *Kubelet) setVolumeLimits(node *v1.Node) { + if node.Status.Capacity == nil { + node.Status.Capacity = v1.ResourceList{} + } + + if node.Status.Allocatable == nil { + node.Status.Allocatable = v1.ResourceList{} + } + + pluginWithLimits := kl.volumePluginMgr.ListVolumePluginWithLimits() + for _, volumePlugin := range pluginWithLimits { + attachLimits, err := volumePlugin.GetVolumeLimits() + if err != nil { + glog.V(4).Infof("Error getting volume limit for plugin %s", volumePlugin.GetPluginName()) + continue + } + for limitKey, value := range attachLimits { + node.Status.Capacity[v1.ResourceName(limitKey)] = *resource.NewQuantity(value, resource.DecimalSI) + node.Status.Allocatable[v1.ResourceName(limitKey)] = *resource.NewQuantity(value, resource.DecimalSI) + } + } +} + // syncNodeStatus should be called periodically from a goroutine. // It synchronizes node status to master, registering the kubelet first if // necessary. @@ -369,6 +382,7 @@ func (kl *Kubelet) syncNodeStatus() { // updateNodeStatus updates node status to master with retries. func (kl *Kubelet) updateNodeStatus() error { + glog.V(5).Infof("Updating node status") for i := 0; i < nodeStatusUpdateRetry; i++ { if err := kl.tryUpdateNodeStatus(i); err != nil { if i > 0 && kl.onRepeatedHeartbeatFailure != nil { @@ -405,7 +419,9 @@ func (kl *Kubelet) tryUpdateNodeStatus(tryNumber int) error { return fmt.Errorf("nil %q node object", kl.nodeName) } - kl.updatePodCIDR(node.Spec.PodCIDR) + if node.Spec.PodCIDR != "" { + kl.updatePodCIDR(node.Spec.PodCIDR) + } kl.setNodeStatus(node) // Patch the current status on the API server @@ -431,7 +447,7 @@ func (kl *Kubelet) recordNodeStatusEvent(eventType, event string) { // Set IP and hostname addresses for the node. func (kl *Kubelet) setNodeAddress(node *v1.Node) error { if kl.nodeIP != nil { - if err := validateNodeIP(kl.nodeIP); err != nil { + if err := kl.nodeIPValidator(kl.nodeIP); err != nil { return fmt.Errorf("failed to validate nodeIP: %v", err) } glog.V(2).Infof("Using node IP: %q", kl.nodeIP.String()) @@ -456,18 +472,57 @@ func (kl *Kubelet) setNodeAddress(node *v1.Node) error { // to the cloud provider? // TODO(justinsb): We can if CurrentNodeName() was actually CurrentNode() and returned an interface // TODO: If IP addresses couldn't be fetched from the cloud provider, should kubelet fallback on the other methods for getting the IP below? - nodeAddresses, err := instances.NodeAddresses(context.TODO(), kl.nodeName) + var nodeAddresses []v1.NodeAddress + var err error + + // Make sure the instances.NodeAddresses returns even if the cloud provider API hangs for a long time + func() { + kl.cloudproviderRequestMux.Lock() + if len(kl.cloudproviderRequestParallelism) > 0 { + kl.cloudproviderRequestMux.Unlock() + return + } + kl.cloudproviderRequestParallelism <- 0 + kl.cloudproviderRequestMux.Unlock() + + go func() { + nodeAddresses, err = instances.NodeAddresses(context.TODO(), kl.nodeName) + + kl.cloudproviderRequestMux.Lock() + <-kl.cloudproviderRequestParallelism + kl.cloudproviderRequestMux.Unlock() + + kl.cloudproviderRequestSync <- 0 + }() + }() + + select { + case <-kl.cloudproviderRequestSync: + case <-time.After(kl.cloudproviderRequestTimeout): + err = fmt.Errorf("Timeout after %v", kl.cloudproviderRequestTimeout) + } + if err != nil { return fmt.Errorf("failed to get node address from cloud provider: %v", err) } if kl.nodeIP != nil { enforcedNodeAddresses := []v1.NodeAddress{} + + var nodeIPType v1.NodeAddressType for _, nodeAddress := range nodeAddresses { if nodeAddress.Address == kl.nodeIP.String() { enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: nodeAddress.Type, Address: nodeAddress.Address}) + nodeIPType = nodeAddress.Type + break } } if len(enforcedNodeAddresses) > 0 { + for _, nodeAddress := range nodeAddresses { + if nodeAddress.Type != nodeIPType && nodeAddress.Type != v1.NodeHostName { + enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: nodeAddress.Type, Address: nodeAddress.Address}) + } + } + enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: v1.NodeHostName, Address: kl.GetHostname()}) node.Status.Addresses = enforcedNodeAddresses return nil @@ -508,7 +563,7 @@ func (kl *Kubelet) setNodeAddress(node *v1.Node) error { var addrs []net.IP addrs, _ = net.LookupIP(node.Name) for _, addr := range addrs { - if err = validateNodeIP(addr); err == nil { + if err = kl.nodeIPValidator(addr); err == nil { if addr.To4() != nil { ipAddr = addr break @@ -543,14 +598,6 @@ func (kl *Kubelet) setNodeStatusMachineInfo(node *v1.Node) { node.Status.Capacity = v1.ResourceList{} } - // populate GPU capacity. - gpuCapacity := kl.gpuManager.Capacity() - if gpuCapacity != nil { - for k, v := range gpuCapacity { - node.Status.Capacity[k] = v - } - } - var devicePluginAllocatable v1.ResourceList var devicePluginCapacity v1.ResourceList var removedDevicePlugins []string @@ -602,7 +649,9 @@ func (kl *Kubelet) setNodeStatusMachineInfo(node *v1.Node) { devicePluginCapacity, devicePluginAllocatable, removedDevicePlugins = kl.containerManager.GetDevicePluginResourceCapacity() if devicePluginCapacity != nil { for k, v := range devicePluginCapacity { - glog.V(2).Infof("Update capacity for %s to %d", k, v.Value()) + if old, ok := node.Status.Capacity[k]; !ok || old.Value() != v.Value() { + glog.V(2).Infof("Update capacity for %s to %d", k, v.Value()) + } node.Status.Capacity[k] = v } } @@ -645,9 +694,12 @@ func (kl *Kubelet) setNodeStatusMachineInfo(node *v1.Node) { } node.Status.Allocatable[k] = value } + if devicePluginAllocatable != nil { for k, v := range devicePluginAllocatable { - glog.V(2).Infof("Update allocatable for %s to %d", k, v.Value()) + if old, ok := node.Status.Allocatable[k]; !ok || old.Value() != v.Value() { + glog.V(2).Infof("Update allocatable for %s to %d", k, v.Value()) + } node.Status.Allocatable[k] = v } } @@ -704,8 +756,9 @@ func (kl *Kubelet) setNodeStatusImages(node *v1.Node) { return } // sort the images from max to min, and only set top N images into the node status. - if maxImagesInNodeStatus < len(containerImages) { - containerImages = containerImages[0:maxImagesInNodeStatus] + if int(kl.nodeStatusMaxImages) > -1 && + int(kl.nodeStatusMaxImages) < len(containerImages) { + containerImages = containerImages[0:kl.nodeStatusMaxImages] } for _, image := range containerImages { @@ -736,6 +789,9 @@ func (kl *Kubelet) setNodeStatusInfo(node *v1.Node) { kl.setNodeStatusDaemonEndpoints(node) kl.setNodeStatusImages(node) kl.setNodeStatusGoRuntime(node) + if utilfeature.DefaultFeatureGate.Enabled(features.AttachVolumeLimit) { + kl.setVolumeLimits(node) + } } // Set Ready condition for the node. @@ -1052,7 +1108,8 @@ func (kl *Kubelet) setNodeVolumesInUseStatus(node *v1.Node) { // TODO(madhusudancs): Simplify the logic for setting node conditions and // refactor the node status condition code out to a different file. func (kl *Kubelet) setNodeStatus(node *v1.Node) { - for _, f := range kl.setNodeStatusFuncs { + for i, f := range kl.setNodeStatusFuncs { + glog.V(5).Infof("Setting node status at position %v", i) if err := f(node); err != nil { glog.Warningf("Failed to set some node status fields: %s", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status_test.go index 4a01d58a2..ab79aa41b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status_test.go @@ -60,8 +60,8 @@ const ( maxImageTagsForTest = 20 ) -// generateTestingImageList generate randomly generated image list and corresponding expectedImageList. -func generateTestingImageList(count int) ([]kubecontainer.Image, []v1.ContainerImage) { +// generateTestingImageLists generate randomly generated image list and corresponding expectedImageList. +func generateTestingImageLists(count int, maxImages int) ([]kubecontainer.Image, []v1.ContainerImage) { // imageList is randomly generated image list var imageList []kubecontainer.Image for ; count > 0; count-- { @@ -73,7 +73,12 @@ func generateTestingImageList(count int) ([]kubecontainer.Image, []v1.ContainerI imageList = append(imageList, imageItem) } - // expectedImageList is generated by imageList according to size and maxImagesInNodeStatus + expectedImageList := makeExpectedImageList(imageList, maxImages) + return imageList, expectedImageList +} + +func makeExpectedImageList(imageList []kubecontainer.Image, maxImages int) []v1.ContainerImage { + // expectedImageList is generated by imageList according to size and maxImages // 1. sort the imageList by size sort.Sort(sliceutils.ByImageSize(imageList)) // 2. convert sorted imageList to v1.ContainerImage list @@ -86,8 +91,11 @@ func generateTestingImageList(count int) ([]kubecontainer.Image, []v1.ContainerI expectedImageList = append(expectedImageList, apiImage) } - // 3. only returns the top maxImagesInNodeStatus images in expectedImageList - return imageList, expectedImageList[0:maxImagesInNodeStatus] + // 3. only returns the top maxImages images in expectedImageList + if maxImages == -1 { // -1 means no limit + return expectedImageList + } + return expectedImageList[0:maxImages] } func generateImageTags() []string { @@ -139,239 +147,350 @@ func TestNodeStatusWithCloudProviderNodeIP(t *testing.T) { kubelet.kubeClient = nil // ensure only the heartbeat client is used kubelet.hostname = testKubeletHostname - existingNode := v1.Node{ - ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname, Annotations: make(map[string]string)}, - Spec: v1.NodeSpec{}, - } - - // TODO : is it possible to mock validateNodeIP() to avoid relying on the host interface addresses ? - addrs, err := net.InterfaceAddrs() - assert.NoError(t, err) - for _, addr := range addrs { - var ip net.IP - switch v := addr.(type) { - case *net.IPNet: - ip = v.IP - case *net.IPAddr: - ip = v.IP - } - if ip != nil && !ip.IsLoopback() && ip.To4() != nil { - kubelet.nodeIP = ip - break - } - } - assert.NotNil(t, kubelet.nodeIP) - - fakeCloud := &fakecloud.FakeCloud{ - Addresses: []v1.NodeAddress{ - { - Type: v1.NodeExternalIP, - Address: "132.143.154.163", + cases := []struct { + name string + nodeIP net.IP + nodeAddresses []v1.NodeAddress + expectedAddresses []v1.NodeAddress + shouldError bool + }{ + { + name: "A single InternalIP", + nodeIP: net.ParseIP("10.1.1.1"), + nodeAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "10.1.1.1"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, }, - { - Type: v1.NodeExternalIP, - Address: kubelet.nodeIP.String(), + expectedAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "10.1.1.1"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, }, - { - Type: v1.NodeInternalIP, - Address: "132.143.154.164", + shouldError: false, + }, + { + name: "NodeIP is external", + nodeIP: net.ParseIP("55.55.55.55"), + nodeAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "10.1.1.1"}, + {Type: v1.NodeExternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, }, - { - Type: v1.NodeInternalIP, - Address: kubelet.nodeIP.String(), + expectedAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "10.1.1.1"}, + {Type: v1.NodeExternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, }, - { - Type: v1.NodeInternalIP, - Address: "132.143.154.165", + shouldError: false, + }, + { + // Accommodating #45201 and #49202 + name: "InternalIP and ExternalIP are the same", + nodeIP: net.ParseIP("55.55.55.55"), + nodeAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeExternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, }, - { - Type: v1.NodeHostName, - Address: testKubeletHostname, + expectedAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeExternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, }, + shouldError: false, }, - Err: nil, - } - kubelet.cloud = fakeCloud - - kubelet.setNodeAddress(&existingNode) - - expectedAddresses := []v1.NodeAddress{ { - Type: v1.NodeExternalIP, - Address: kubelet.nodeIP.String(), + name: "An Internal/ExternalIP, an Internal/ExternalDNS", + nodeIP: net.ParseIP("10.1.1.1"), + nodeAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "10.1.1.1"}, + {Type: v1.NodeExternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeInternalDNS, Address: "ip-10-1-1-1.us-west-2.compute.internal"}, + {Type: v1.NodeExternalDNS, Address: "ec2-55-55-55-55.us-west-2.compute.amazonaws.com"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, + }, + expectedAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "10.1.1.1"}, + {Type: v1.NodeExternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeInternalDNS, Address: "ip-10-1-1-1.us-west-2.compute.internal"}, + {Type: v1.NodeExternalDNS, Address: "ec2-55-55-55-55.us-west-2.compute.amazonaws.com"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, + }, + shouldError: false, }, { - Type: v1.NodeInternalIP, - Address: kubelet.nodeIP.String(), + name: "An Internal with multiple internal IPs", + nodeIP: net.ParseIP("10.1.1.1"), + nodeAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "10.1.1.1"}, + {Type: v1.NodeInternalIP, Address: "10.2.2.2"}, + {Type: v1.NodeInternalIP, Address: "10.3.3.3"}, + {Type: v1.NodeExternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, + }, + expectedAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "10.1.1.1"}, + {Type: v1.NodeExternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, + }, + shouldError: false, }, { - Type: v1.NodeHostName, - Address: testKubeletHostname, + name: "An InternalIP that isn't valid: should error", + nodeIP: net.ParseIP("10.2.2.2"), + nodeAddresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "10.1.1.1"}, + {Type: v1.NodeExternalIP, Address: "55.55.55.55"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, + }, + expectedAddresses: nil, + shouldError: true, }, } - assert.True(t, apiequality.Semantic.DeepEqual(expectedAddresses, existingNode.Status.Addresses), "%s", diff.ObjectDiff(expectedAddresses, existingNode.Status.Addresses)) + for _, testCase := range cases { + // testCase setup + existingNode := v1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname, Annotations: make(map[string]string)}, + Spec: v1.NodeSpec{}, + } + + kubelet.nodeIP = testCase.nodeIP + + fakeCloud := &fakecloud.FakeCloud{ + Addresses: testCase.nodeAddresses, + Err: nil, + } + kubelet.cloud = fakeCloud + kubelet.cloudproviderRequestParallelism = make(chan int, 1) + kubelet.cloudproviderRequestSync = make(chan int) + kubelet.cloudproviderRequestTimeout = 10 * time.Second + kubelet.nodeIPValidator = func(nodeIP net.IP) error { + return nil + } + + // execute method + err := kubelet.setNodeAddress(&existingNode) + if err != nil && !testCase.shouldError { + t.Errorf("Unexpected error for test %s: %q", testCase.name, err) + continue + } else if err != nil && testCase.shouldError { + // expected an error + continue + } + + // Sort both sets for consistent equality + sortNodeAddresses(testCase.expectedAddresses) + sortNodeAddresses(existingNode.Status.Addresses) + + assert.True( + t, + apiequality.Semantic.DeepEqual( + testCase.expectedAddresses, + existingNode.Status.Addresses, + ), + fmt.Sprintf("Test %s failed %%s", testCase.name), + diff.ObjectDiff(testCase.expectedAddresses, existingNode.Status.Addresses), + ) + } +} + +// sortableNodeAddress is a type for sorting []v1.NodeAddress +type sortableNodeAddress []v1.NodeAddress + +func (s sortableNodeAddress) Len() int { return len(s) } +func (s sortableNodeAddress) Less(i, j int) bool { + return (string(s[i].Type) + s[i].Address) < (string(s[j].Type) + s[j].Address) +} +func (s sortableNodeAddress) Swap(i, j int) { s[j], s[i] = s[i], s[j] } + +func sortNodeAddresses(addrs sortableNodeAddress) { + sort.Sort(addrs) } func TestUpdateNewNodeStatus(t *testing.T) { - // generate one more than maxImagesInNodeStatus in inputImageList - inputImageList, expectedImageList := generateTestingImageList(maxImagesInNodeStatus + 1) - testKubelet := newTestKubeletWithImageList( - t, inputImageList, false /* controllerAttachDetachEnabled */) - defer testKubelet.Cleanup() - kubelet := testKubelet.kubelet - kubelet.kubeClient = nil // ensure only the heartbeat client is used - kubelet.containerManager = &localCM{ - ContainerManager: cm.NewStubContainerManager(), - allocatableReservation: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI), - v1.ResourceEphemeralStorage: *resource.NewQuantity(2000, resource.BinarySI), + cases := []struct { + desc string + nodeStatusMaxImages int32 + }{ + { + desc: "5 image limit", + nodeStatusMaxImages: 5, }, - capacity: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), - v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + { + desc: "no image limit", + nodeStatusMaxImages: -1, }, } - kubeClient := testKubelet.fakeKubeClient - existingNode := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}} - kubeClient.ReactionChain = fake.NewSimpleClientset(&v1.NodeList{Items: []v1.Node{existingNode}}).ReactionChain - machineInfo := &cadvisorapi.MachineInfo{ - MachineID: "123", - SystemUUID: "abc", - BootID: "1b3", - NumCores: 2, - MemoryCapacity: 10E9, // 10G - } - mockCadvisor := testKubelet.fakeCadvisor - mockCadvisor.On("Start").Return(nil) - mockCadvisor.On("MachineInfo").Return(machineInfo, nil) - versionInfo := &cadvisorapi.VersionInfo{ - KernelVersion: "3.16.0-0.bpo.4-amd64", - ContainerOsVersion: "Debian GNU/Linux 7 (wheezy)", - } - mockCadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{ - Usage: 400, - Capacity: 5000, - Available: 600, - }, nil) - mockCadvisor.On("RootFsInfo").Return(cadvisorapiv2.FsInfo{ - Usage: 400, - Capacity: 5000, - Available: 600, - }, nil) - mockCadvisor.On("VersionInfo").Return(versionInfo, nil) - maxAge := 0 * time.Second - options := cadvisorapiv2.RequestOptions{IdType: cadvisorapiv2.TypeName, Count: 2, Recursive: false, MaxAge: &maxAge} - mockCadvisor.On("ContainerInfoV2", "/", options).Return(map[string]cadvisorapiv2.ContainerInfo{}, nil) - kubelet.machineInfo = machineInfo - expectedNode := &v1.Node{ - ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}, - Spec: v1.NodeSpec{}, - Status: v1.NodeStatus{ - Conditions: []v1.NodeCondition{ - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionFalse, - Reason: "KubeletHasSufficientDisk", - Message: fmt.Sprintf("kubelet has sufficient disk space available"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, - }, - { - Type: v1.NodeMemoryPressure, - Status: v1.ConditionFalse, - Reason: "KubeletHasSufficientMemory", - Message: fmt.Sprintf("kubelet has sufficient memory available"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, - }, - { - Type: v1.NodeDiskPressure, - Status: v1.ConditionFalse, - Reason: "KubeletHasNoDiskPressure", - Message: fmt.Sprintf("kubelet has no disk pressure"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + // generate one more in inputImageList than we configure the Kubelet to report, + // or 5 images if unlimited + numTestImages := int(tc.nodeStatusMaxImages) + 1 + if tc.nodeStatusMaxImages == -1 { + numTestImages = 5 + } + inputImageList, expectedImageList := generateTestingImageLists(numTestImages, int(tc.nodeStatusMaxImages)) + testKubelet := newTestKubeletWithImageList( + t, inputImageList, false /* controllerAttachDetachEnabled */, true /*initFakeVolumePlugin*/) + defer testKubelet.Cleanup() + kubelet := testKubelet.kubelet + kubelet.nodeStatusMaxImages = tc.nodeStatusMaxImages + kubelet.kubeClient = nil // ensure only the heartbeat client is used + kubelet.containerManager = &localCM{ + ContainerManager: cm.NewStubContainerManager(), + allocatableReservation: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(2000, resource.BinarySI), }, - { - Type: v1.NodePIDPressure, - Status: v1.ConditionFalse, - Reason: "KubeletHasSufficientPID", - Message: fmt.Sprintf("kubelet has sufficient PID available"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, + capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), }, - { - Type: v1.NodeReady, - Status: v1.ConditionTrue, - Reason: "KubeletReady", - Message: fmt.Sprintf("kubelet is posting ready status"), - LastHeartbeatTime: metav1.Time{}, - LastTransitionTime: metav1.Time{}, + } + kubeClient := testKubelet.fakeKubeClient + existingNode := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}} + kubeClient.ReactionChain = fake.NewSimpleClientset(&v1.NodeList{Items: []v1.Node{existingNode}}).ReactionChain + machineInfo := &cadvisorapi.MachineInfo{ + MachineID: "123", + SystemUUID: "abc", + BootID: "1b3", + NumCores: 2, + MemoryCapacity: 10E9, // 10G + } + mockCadvisor := testKubelet.fakeCadvisor + mockCadvisor.On("Start").Return(nil) + mockCadvisor.On("MachineInfo").Return(machineInfo, nil) + versionInfo := &cadvisorapi.VersionInfo{ + KernelVersion: "3.16.0-0.bpo.4-amd64", + ContainerOsVersion: "Debian GNU/Linux 7 (wheezy)", + } + mockCadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{ + Usage: 400, + Capacity: 5000, + Available: 600, + }, nil) + mockCadvisor.On("RootFsInfo").Return(cadvisorapiv2.FsInfo{ + Usage: 400, + Capacity: 5000, + Available: 600, + }, nil) + mockCadvisor.On("VersionInfo").Return(versionInfo, nil) + maxAge := 0 * time.Second + options := cadvisorapiv2.RequestOptions{IdType: cadvisorapiv2.TypeName, Count: 2, Recursive: false, MaxAge: &maxAge} + mockCadvisor.On("ContainerInfoV2", "/", options).Return(map[string]cadvisorapiv2.ContainerInfo{}, nil) + kubelet.machineInfo = machineInfo + + expectedNode := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}, + Spec: v1.NodeSpec{}, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeOutOfDisk, + Status: v1.ConditionFalse, + Reason: "KubeletHasSufficientDisk", + Message: fmt.Sprintf("kubelet has sufficient disk space available"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + { + Type: v1.NodeMemoryPressure, + Status: v1.ConditionFalse, + Reason: "KubeletHasSufficientMemory", + Message: fmt.Sprintf("kubelet has sufficient memory available"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + { + Type: v1.NodeDiskPressure, + Status: v1.ConditionFalse, + Reason: "KubeletHasNoDiskPressure", + Message: fmt.Sprintf("kubelet has no disk pressure"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + { + Type: v1.NodePIDPressure, + Status: v1.ConditionFalse, + Reason: "KubeletHasSufficientPID", + Message: fmt.Sprintf("kubelet has sufficient PID available"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + { + Type: v1.NodeReady, + Status: v1.ConditionTrue, + Reason: "KubeletReady", + Message: fmt.Sprintf("kubelet is posting ready status"), + LastHeartbeatTime: metav1.Time{}, + LastTransitionTime: metav1.Time{}, + }, + }, + NodeInfo: v1.NodeSystemInfo{ + MachineID: "123", + SystemUUID: "abc", + BootID: "1b3", + KernelVersion: "3.16.0-0.bpo.4-amd64", + OSImage: "Debian GNU/Linux 7 (wheezy)", + OperatingSystem: goruntime.GOOS, + Architecture: goruntime.GOARCH, + ContainerRuntimeVersion: "test://1.5.0", + KubeletVersion: version.Get().String(), + KubeProxyVersion: version.Get().String(), + }, + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(1800, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(9900E6, resource.BinarySI), + v1.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(3000, resource.BinarySI), + }, + Addresses: []v1.NodeAddress{ + {Type: v1.NodeInternalIP, Address: "127.0.0.1"}, + {Type: v1.NodeHostName, Address: testKubeletHostname}, + }, + Images: expectedImageList, }, - }, - NodeInfo: v1.NodeSystemInfo{ - MachineID: "123", - SystemUUID: "abc", - BootID: "1b3", - KernelVersion: "3.16.0-0.bpo.4-amd64", - OSImage: "Debian GNU/Linux 7 (wheezy)", - OperatingSystem: goruntime.GOOS, - Architecture: goruntime.GOARCH, - ContainerRuntimeVersion: "test://1.5.0", - KubeletVersion: version.Get().String(), - KubeProxyVersion: version.Get().String(), - }, - Capacity: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), - v1.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI), - v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), - }, - Allocatable: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(1800, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(9900E6, resource.BinarySI), - v1.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI), - v1.ResourceEphemeralStorage: *resource.NewQuantity(3000, resource.BinarySI), - }, - Addresses: []v1.NodeAddress{ - {Type: v1.NodeInternalIP, Address: "127.0.0.1"}, - {Type: v1.NodeHostName, Address: testKubeletHostname}, - }, - Images: expectedImageList, - }, - } + } - kubelet.updateRuntimeUp() - assert.NoError(t, kubelet.updateNodeStatus()) - actions := kubeClient.Actions() - require.Len(t, actions, 2) - require.True(t, actions[1].Matches("patch", "nodes")) - require.Equal(t, actions[1].GetSubresource(), "status") + kubelet.updateRuntimeUp() + assert.NoError(t, kubelet.updateNodeStatus()) + actions := kubeClient.Actions() + require.Len(t, actions, 2) + require.True(t, actions[1].Matches("patch", "nodes")) + require.Equal(t, actions[1].GetSubresource(), "status") + + updatedNode, err := applyNodeStatusPatch(&existingNode, actions[1].(core.PatchActionImpl).GetPatch()) + assert.NoError(t, err) + for i, cond := range updatedNode.Status.Conditions { + assert.False(t, cond.LastHeartbeatTime.IsZero(), "LastHeartbeatTime for %v condition is zero", cond.Type) + assert.False(t, cond.LastTransitionTime.IsZero(), "LastTransitionTime for %v condition is zero", cond.Type) + updatedNode.Status.Conditions[i].LastHeartbeatTime = metav1.Time{} + updatedNode.Status.Conditions[i].LastTransitionTime = metav1.Time{} + } - updatedNode, err := applyNodeStatusPatch(&existingNode, actions[1].(core.PatchActionImpl).GetPatch()) - assert.NoError(t, err) - for i, cond := range updatedNode.Status.Conditions { - assert.False(t, cond.LastHeartbeatTime.IsZero(), "LastHeartbeatTime for %v condition is zero", cond.Type) - assert.False(t, cond.LastTransitionTime.IsZero(), "LastTransitionTime for %v condition is zero", cond.Type) - updatedNode.Status.Conditions[i].LastHeartbeatTime = metav1.Time{} - updatedNode.Status.Conditions[i].LastTransitionTime = metav1.Time{} + // Version skew workaround. See: https://github.com/kubernetes/kubernetes/issues/16961 + assert.Equal(t, v1.NodeReady, updatedNode.Status.Conditions[len(updatedNode.Status.Conditions)-1].Type, + "NotReady should be last") + assert.Len(t, updatedNode.Status.Images, len(expectedImageList)) + assert.True(t, apiequality.Semantic.DeepEqual(expectedNode, updatedNode), "%s", diff.ObjectDiff(expectedNode, updatedNode)) + }) } - - // Version skew workaround. See: https://github.com/kubernetes/kubernetes/issues/16961 - assert.Equal(t, v1.NodeReady, updatedNode.Status.Conditions[len(updatedNode.Status.Conditions)-1].Type, - "NotReady should be last") - assert.Len(t, updatedNode.Status.Images, maxImagesInNodeStatus) - assert.True(t, apiequality.Semantic.DeepEqual(expectedNode, updatedNode), "%s", diff.ObjectDiff(expectedNode, updatedNode)) } func TestUpdateExistingNodeStatus(t *testing.T) { testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) defer testKubelet.Cleanup() kubelet := testKubelet.kubelet - kubelet.kubeClient = nil // ensure only the heartbeat client is used + kubelet.nodeStatusMaxImages = 5 // don't truncate the image list that gets constructed by hand for this test + kubelet.kubeClient = nil // ensure only the heartbeat client is used kubelet.containerManager = &localCM{ ContainerManager: cm.NewStubContainerManager(), allocatableReservation: v1.ResourceList{ @@ -643,8 +762,8 @@ func TestUpdateExistingNodeStatusTimeout(t *testing.T) { assert.Error(t, kubelet.updateNodeStatus()) // should have attempted multiple times - if actualAttempts := atomic.LoadInt64(&attempts); actualAttempts != nodeStatusUpdateRetry { - t.Errorf("Expected %d attempts, got %d", nodeStatusUpdateRetry, actualAttempts) + if actualAttempts := atomic.LoadInt64(&attempts); actualAttempts < nodeStatusUpdateRetry { + t.Errorf("Expected at least %d attempts, got %d", nodeStatusUpdateRetry, actualAttempts) } // should have gotten multiple failure callbacks if actualFailureCallbacks := atomic.LoadInt64(&failureCallbacks); actualFailureCallbacks < (nodeStatusUpdateRetry - 1) { @@ -656,7 +775,8 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) { testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) defer testKubelet.Cleanup() kubelet := testKubelet.kubelet - kubelet.kubeClient = nil // ensure only the heartbeat client is used + kubelet.nodeStatusMaxImages = 5 // don't truncate the image list that gets constructed by hand for this test + kubelet.kubeClient = nil // ensure only the heartbeat client is used kubelet.containerManager = &localCM{ ContainerManager: cm.NewStubContainerManager(), allocatableReservation: v1.ResourceList{ @@ -793,7 +913,7 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) { require.True(t, actions[1].Matches("patch", "nodes")) require.Equal(t, actions[1].GetSubresource(), "status") - updatedNode, err := applyNodeStatusPatch(&existingNode, actions[1].(core.PatchActionImpl).GetPatch()) + updatedNode, err := kubeClient.CoreV1().Nodes().Get(testKubeletHostname, metav1.GetOptions{}) require.NoError(t, err, "can't apply node status patch") for i, cond := range updatedNode.Status.Conditions { @@ -805,7 +925,6 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) { // Version skew workaround. See: https://github.com/kubernetes/kubernetes/issues/16961 lastIndex := len(updatedNode.Status.Conditions) - 1 - assert.Equal(t, v1.NodeReady, updatedNode.Status.Conditions[lastIndex].Type, "NodeReady should be the last condition") assert.NotEmpty(t, updatedNode.Status.Conditions[lastIndex].Message) @@ -920,7 +1039,6 @@ func TestRegisterWithApiServer(t *testing.T) { kubeletapis.LabelArch: goruntime.GOARCH, }, }, - Spec: v1.NodeSpec{ExternalID: testKubeletHostname}, }, nil }) kubeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { @@ -974,7 +1092,7 @@ func TestTryRegisterWithApiServer(t *testing.T) { ErrStatus: metav1.Status{Reason: metav1.StatusReasonConflict}, } - newNode := func(cmad bool, externalID string) *v1.Node { + newNode := func(cmad bool) *v1.Node { node := &v1.Node{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ @@ -983,9 +1101,6 @@ func TestTryRegisterWithApiServer(t *testing.T) { kubeletapis.LabelArch: goruntime.GOARCH, }, }, - Spec: v1.NodeSpec{ - ExternalID: externalID, - }, } if cmad { @@ -1018,17 +1133,17 @@ func TestTryRegisterWithApiServer(t *testing.T) { }, { name: "success case - existing node - no change in CMAD", - newNode: newNode(true, "a"), + newNode: newNode(true), createError: alreadyExists, - existingNode: newNode(true, "a"), + existingNode: newNode(true), expectedResult: true, expectedActions: 2, }, { name: "success case - existing node - CMAD disabled", - newNode: newNode(false, "a"), + newNode: newNode(false), createError: alreadyExists, - existingNode: newNode(true, "a"), + existingNode: newNode(true), expectedResult: true, expectedActions: 3, testSavedNode: true, @@ -1037,33 +1152,25 @@ func TestTryRegisterWithApiServer(t *testing.T) { }, { name: "success case - existing node - CMAD enabled", - newNode: newNode(true, "a"), + newNode: newNode(true), createError: alreadyExists, - existingNode: newNode(false, "a"), + existingNode: newNode(false), expectedResult: true, expectedActions: 3, testSavedNode: true, savedNodeIndex: 2, savedNodeCMAD: true, }, - { - name: "success case - external ID changed", - newNode: newNode(false, "b"), - createError: alreadyExists, - existingNode: newNode(false, "a"), - expectedResult: false, - expectedActions: 3, - }, { name: "create failed", - newNode: newNode(false, "b"), + newNode: newNode(false), createError: conflict, expectedResult: false, expectedActions: 1, }, { name: "get existing node failed", - newNode: newNode(false, "a"), + newNode: newNode(false), createError: alreadyExists, getError: conflict, expectedResult: false, @@ -1071,22 +1178,13 @@ func TestTryRegisterWithApiServer(t *testing.T) { }, { name: "update existing node failed", - newNode: newNode(false, "a"), + newNode: newNode(false), createError: alreadyExists, - existingNode: newNode(true, "a"), + existingNode: newNode(true), patchError: conflict, expectedResult: false, expectedActions: 3, }, - { - name: "delete existing node failed", - newNode: newNode(false, "b"), - createError: alreadyExists, - existingNode: newNode(false, "a"), - deleteError: conflict, - expectedResult: false, - expectedActions: 3, - }, } notImplemented := func(action core.Action) (bool, runtime.Object, error) { @@ -1149,12 +1247,15 @@ func TestTryRegisterWithApiServer(t *testing.T) { } func TestUpdateNewNodeStatusTooLargeReservation(t *testing.T) { - // generate one more than maxImagesInNodeStatus in inputImageList - inputImageList, _ := generateTestingImageList(maxImagesInNodeStatus + 1) + const nodeStatusMaxImages = 5 + + // generate one more in inputImageList than we configure the Kubelet to report + inputImageList, _ := generateTestingImageLists(nodeStatusMaxImages+1, nodeStatusMaxImages) testKubelet := newTestKubeletWithImageList( - t, inputImageList, false /* controllerAttachDetachEnabled */) + t, inputImageList, false /* controllerAttachDetachEnabled */, true /* initFakeVolumePlugin */) defer testKubelet.Cleanup() kubelet := testKubelet.kubelet + kubelet.nodeStatusMaxImages = nodeStatusMaxImages kubelet.kubeClient = nil // ensure only the heartbeat client is used kubelet.containerManager = &localCM{ ContainerManager: cm.NewStubContainerManager(), @@ -1424,3 +1525,277 @@ func TestUpdateDefaultLabels(t *testing.T) { assert.Equal(t, tc.finalLabels, tc.existingNode.Labels, tc.name) } } + +func TestReconcileExtendedResource(t *testing.T) { + testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) + testKubelet.kubelet.kubeClient = nil // ensure only the heartbeat client is used + extendedResourceName1 := v1.ResourceName("test.com/resource1") + extendedResourceName2 := v1.ResourceName("test.com/resource2") + + cases := []struct { + name string + existingNode *v1.Node + expectedNode *v1.Node + needsUpdate bool + }{ + { + name: "no update needed without extended resource", + existingNode: &v1.Node{ + Status: v1.NodeStatus{ + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + }, + }, + expectedNode: &v1.Node{ + Status: v1.NodeStatus{ + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + }, + }, + needsUpdate: false, + }, + { + name: "extended resource capacity is zeroed", + existingNode: &v1.Node{ + Status: v1.NodeStatus{ + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + extendedResourceName1: *resource.NewQuantity(int64(2), resource.DecimalSI), + extendedResourceName2: *resource.NewQuantity(int64(10), resource.DecimalSI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + extendedResourceName1: *resource.NewQuantity(int64(2), resource.DecimalSI), + extendedResourceName2: *resource.NewQuantity(int64(10), resource.DecimalSI), + }, + }, + }, + expectedNode: &v1.Node{ + Status: v1.NodeStatus{ + Capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + extendedResourceName1: *resource.NewQuantity(int64(0), resource.DecimalSI), + extendedResourceName2: *resource.NewQuantity(int64(0), resource.DecimalSI), + }, + Allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + extendedResourceName1: *resource.NewQuantity(int64(0), resource.DecimalSI), + extendedResourceName2: *resource.NewQuantity(int64(0), resource.DecimalSI), + }, + }, + }, + needsUpdate: true, + }, + } + + for _, tc := range cases { + defer testKubelet.Cleanup() + kubelet := testKubelet.kubelet + initialNode := &v1.Node{} + + needsUpdate := kubelet.reconcileExtendedResource(initialNode, tc.existingNode) + assert.Equal(t, tc.needsUpdate, needsUpdate, tc.name) + assert.Equal(t, tc.expectedNode, tc.existingNode, tc.name) + } + +} + +func TestValidateNodeIPParam(t *testing.T) { + type test struct { + nodeIP string + success bool + testName string + } + tests := []test{ + { + nodeIP: "", + success: false, + testName: "IP not set", + }, + { + nodeIP: "127.0.0.1", + success: false, + testName: "IPv4 loopback address", + }, + { + nodeIP: "::1", + success: false, + testName: "IPv6 loopback address", + }, + { + nodeIP: "224.0.0.1", + success: false, + testName: "multicast IPv4 address", + }, + { + nodeIP: "ff00::1", + success: false, + testName: "multicast IPv6 address", + }, + { + nodeIP: "169.254.0.1", + success: false, + testName: "IPv4 link-local unicast address", + }, + { + nodeIP: "fe80::0202:b3ff:fe1e:8329", + success: false, + testName: "IPv6 link-local unicast address", + }, + { + nodeIP: "0.0.0.0", + success: false, + testName: "Unspecified IPv4 address", + }, + { + nodeIP: "::", + success: false, + testName: "Unspecified IPv6 address", + }, + { + nodeIP: "1.2.3.4", + success: false, + testName: "IPv4 address that doesn't belong to host", + }, + } + addrs, err := net.InterfaceAddrs() + if err != nil { + assert.Error(t, err, fmt.Sprintf( + "Unable to obtain a list of the node's unicast interface addresses.")) + } + for _, addr := range addrs { + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + if ip.IsLoopback() || ip.IsLinkLocalUnicast() { + break + } + successTest := test{ + nodeIP: ip.String(), + success: true, + testName: fmt.Sprintf("Success test case for address %s", ip.String()), + } + tests = append(tests, successTest) + } + for _, test := range tests { + err := validateNodeIP(net.ParseIP(test.nodeIP)) + if test.success { + assert.NoError(t, err, "test %s", test.testName) + } else { + assert.Error(t, err, fmt.Sprintf("test %s", test.testName)) + } + } +} + +func TestSetVolumeLimits(t *testing.T) { + testKubelet := newTestKubeletWithoutFakeVolumePlugin(t, false /* controllerAttachDetachEnabled */) + defer testKubelet.Cleanup() + kubelet := testKubelet.kubelet + kubelet.kubeClient = nil // ensure only the heartbeat client is used + kubelet.hostname = testKubeletHostname + + var testcases = []struct { + name string + cloudProviderName string + expectedVolumeKey string + expectedLimit int64 + }{ + { + name: "For default GCE cloudprovider", + cloudProviderName: "gce", + expectedVolumeKey: util.GCEVolumeLimitKey, + expectedLimit: 16, + }, + { + name: "For default AWS Cloudprovider", + cloudProviderName: "aws", + expectedVolumeKey: util.EBSVolumeLimitKey, + expectedLimit: 39, + }, + { + name: "for default Azure cloudprovider", + cloudProviderName: "azure", + expectedVolumeKey: util.AzureVolumeLimitKey, + expectedLimit: 16, + }, + { + name: "when no cloudprovider is present", + cloudProviderName: "", + expectedVolumeKey: util.AzureVolumeLimitKey, + expectedLimit: -1, + }, + } + for _, test := range testcases { + node := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname, Annotations: make(map[string]string)}, + Spec: v1.NodeSpec{}, + } + + if test.cloudProviderName != "" { + fakeCloud := &fakecloud.FakeCloud{ + Provider: test.cloudProviderName, + Err: nil, + } + kubelet.cloud = fakeCloud + kubelet.cloudproviderRequestParallelism = make(chan int, 1) + kubelet.cloudproviderRequestSync = make(chan int) + kubelet.cloudproviderRequestTimeout = 10 * time.Second + } else { + kubelet.cloud = nil + } + + kubelet.setVolumeLimits(node) + nodeLimits := []v1.ResourceList{} + nodeLimits = append(nodeLimits, node.Status.Allocatable) + nodeLimits = append(nodeLimits, node.Status.Capacity) + for _, volumeLimits := range nodeLimits { + if test.expectedLimit == -1 { + _, ok := volumeLimits[v1.ResourceName(test.expectedVolumeKey)] + if ok { + t.Errorf("Expected no volume limit found for %s", test.expectedVolumeKey) + } + } else { + fl, ok := volumeLimits[v1.ResourceName(test.expectedVolumeKey)] + + if !ok { + t.Errorf("Expected to found volume limit for %s found none", test.expectedVolumeKey) + } + foundLimit, _ := fl.AsInt64() + expectedValue := resource.NewQuantity(test.expectedLimit, resource.DecimalSI) + if expectedValue.Cmp(fl) != 0 { + t.Errorf("Expected volume limit for %s to be %v found %v", test.expectedVolumeKey, test.expectedLimit, foundLimit) + } + } + + } + + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods.go index 48751776a..0e9ea8682 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods.go @@ -30,7 +30,6 @@ import ( "sort" "strings" "sync" - "time" "github.com/golang/glog" "k8s.io/api/core/v1" @@ -41,7 +40,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" utilvalidation "k8s.io/apimachinery/pkg/util/validation" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/client-go/tools/remotecommand" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/api/v1/resource" podshelper "k8s.io/kubernetes/pkg/apis/core/pods" @@ -60,7 +58,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/status" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" - utilfile "k8s.io/kubernetes/pkg/util/file" mountutil "k8s.io/kubernetes/pkg/util/mount" volumeutil "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" @@ -68,6 +65,11 @@ import ( "k8s.io/kubernetes/third_party/forked/golang/expansion" ) +const ( + managedHostsHeader = "# Kubernetes-managed hosts file.\n" + managedHostsHeaderWithHostNetwork = "# Kubernetes-managed hosts file (host network).\n" +) + // Get a list of pods that have data directories. func (kl *Kubelet) listPodsFromDisk() ([]types.UID, error) { podInfos, err := ioutil.ReadDir(kl.getPodsDir()) @@ -90,26 +92,6 @@ func (kl *Kubelet) GetActivePods() []*v1.Pod { return activePods } -// makeGPUDevices determines the devices for the given container. -// Experimental. -func (kl *Kubelet) makeGPUDevices(pod *v1.Pod, container *v1.Container) ([]kubecontainer.DeviceInfo, error) { - if container.Resources.Limits.NvidiaGPU().IsZero() { - return nil, nil - } - - nvidiaGPUPaths, err := kl.gpuManager.AllocateGPU(pod, container) - if err != nil { - return nil, err - } - var devices []kubecontainer.DeviceInfo - for _, path := range nvidiaGPUPaths { - // Devices have to be mapped one to one because of nvidia CUDA library requirements. - devices = append(devices, kubecontainer.DeviceInfo{PathOnHost: path, PathInContainer: path, Permissions: "mrw"}) - } - - return devices, nil -} - // makeBlockVolumes maps the raw block devices specified in the path of the container // Experimental func (kl *Kubelet) makeBlockVolumes(pod *v1.Pod, container *v1.Container, podVolumes kubecontainer.VolumeMap, blkutil volumepathhandler.BlockVolumePathHandler) ([]kubecontainer.DeviceInfo, error) { @@ -144,7 +126,8 @@ func (kl *Kubelet) makeBlockVolumes(pod *v1.Pod, container *v1.Container, podVol } // makeMounts determines the mount points for the given container. -func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, hostDomain, podIP string, podVolumes kubecontainer.VolumeMap, mounter mountutil.Interface) ([]kubecontainer.Mount, func(), error) { +func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, hostDomain, podIP string, podVolumes kubecontainer.VolumeMap, mounter mountutil.Interface, expandEnvs []kubecontainer.EnvVar) ([]kubecontainer.Mount, func(), error) { + // Kubernetes only mounts on /etc/hosts if: // - container is not an infrastructure (pause) container // - container is not already mounting on /etc/hosts @@ -181,6 +164,11 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h return nil, cleanupAction, fmt.Errorf("volume subpaths are disabled") } + // Expand subpath variables + if utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpathEnvExpansion) { + mount.SubPath = kubecontainer.ExpandContainerVolumeMounts(mount, expandEnvs) + } + if filepath.IsAbs(mount.SubPath) { return nil, cleanupAction, fmt.Errorf("error SubPath `%s` must not be an absolute path", mount.SubPath) } @@ -190,19 +178,10 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h return nil, cleanupAction, fmt.Errorf("unable to provision SubPath `%s`: %v", mount.SubPath, err) } - fileinfo, err := os.Lstat(hostPath) - if err != nil { - return nil, cleanupAction, err - } - perm := fileinfo.Mode() - - volumePath, err := filepath.EvalSymlinks(hostPath) - if err != nil { - return nil, cleanupAction, err - } + volumePath := hostPath hostPath = filepath.Join(volumePath, mount.SubPath) - if subPathExists, err := utilfile.FileOrSymlinkExists(hostPath); err != nil { + if subPathExists, err := mounter.ExistsPath(hostPath); err != nil { glog.Errorf("Could not determine if subPath %s exists; will not attempt to change its permissions", hostPath) } else if !subPathExists { // Create the sub path now because if it's auto-created later when referenced, it may have an @@ -210,10 +189,15 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h // when the pod specifies an fsGroup, and if the directory is not created here, Docker will // later auto-create it with the incorrect mode 0750 // Make extra care not to escape the volume! - if err := mounter.SafeMakeDir(hostPath, volumePath, perm); err != nil { - glog.Errorf("failed to mkdir %q: %v", hostPath, err) + perm, err := mounter.GetMode(volumePath) + if err != nil { return nil, cleanupAction, err } + if err := mounter.SafeMakeDir(mount.SubPath, volumePath, perm); err != nil { + // Don't pass detailed error back to the user because it could give information about host filesystem + glog.Errorf("failed to create subPath directory for volumeMount %q of container %q: %v", mount.Name, container.Name, err) + return nil, cleanupAction, fmt.Errorf("failed to create subPath directory for volumeMount %q of container %q", mount.Name, container.Name) + } } hostPath, cleanupAction, err = mounter.PrepareSafeSubpath(mountutil.Subpath{ VolumeMountIndex: i, @@ -341,15 +325,18 @@ func nodeHostsFileContent(hostsFilePath string, hostAliases []v1.HostAlias) ([]b if err != nil { return nil, err } - hostsFileContent = append(hostsFileContent, hostsEntriesFromHostAliases(hostAliases)...) - return hostsFileContent, nil + var buffer bytes.Buffer + buffer.WriteString(managedHostsHeaderWithHostNetwork) + buffer.Write(hostsFileContent) + buffer.Write(hostsEntriesFromHostAliases(hostAliases)) + return buffer.Bytes(), nil } // managedHostsFileContent generates the content of the managed etc hosts based on Pod IP and other // information. func managedHostsFileContent(hostIP, hostName, hostDomainName string, hostAliases []v1.HostAlias) []byte { var buffer bytes.Buffer - buffer.WriteString("# Kubernetes-managed hosts file.\n") + buffer.WriteString(managedHostsHeader) buffer.WriteString("127.0.0.1\tlocalhost\n") // ipv4 localhost buffer.WriteString("::1\tlocalhost ip6-localhost ip6-loopback\n") // ipv6 localhost buffer.WriteString("fe00::0\tip6-localnet\n") @@ -361,9 +348,8 @@ func managedHostsFileContent(hostIP, hostName, hostDomainName string, hostAliase } else { buffer.WriteString(fmt.Sprintf("%s\t%s\n", hostIP, hostName)) } - hostsFileContent := buffer.Bytes() - hostsFileContent = append(hostsFileContent, hostsEntriesFromHostAliases(hostAliases)...) - return hostsFileContent + buffer.Write(hostsEntriesFromHostAliases(hostAliases)) + return buffer.Bytes() } func hostsEntriesFromHostAliases(hostAliases []v1.HostAlias) []byte { @@ -446,8 +432,6 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Contai return nil, nil, err } - cgroupParent := kl.GetPodCgroupParent(pod) - opts.CgroupParent = cgroupParent hostname, hostDomainName, err := kl.GeneratePodHostNameAndDomain(pod) if err != nil { return nil, nil, err @@ -457,12 +441,6 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Contai volumes := kl.volumeManager.GetMountedVolumesForPod(podName) opts.PortMappings = kubecontainer.MakePortMappings(container) - // TODO(random-liu): Move following convert functions into pkg/kubelet/container - devices, err := kl.makeGPUDevices(pod, container) - if err != nil { - return nil, nil, err - } - opts.Devices = append(opts.Devices, devices...) // TODO: remove feature gate check after no longer needed if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { @@ -474,17 +452,17 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Contai opts.Devices = append(opts.Devices, blkVolumes...) } - mounts, cleanupAction, err := makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIP, volumes, kl.mounter) + envs, err := kl.makeEnvironmentVariables(pod, container, podIP) if err != nil { - return nil, cleanupAction, err + return nil, nil, err } - opts.Mounts = append(opts.Mounts, mounts...) + opts.Envs = append(opts.Envs, envs...) - envs, err := kl.makeEnvironmentVariables(pod, container, podIP) + mounts, cleanupAction, err := makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIP, volumes, kl.mounter, opts.Envs) if err != nil { return nil, cleanupAction, err } - opts.Envs = append(opts.Envs, envs...) + opts.Mounts = append(opts.Mounts, mounts...) // Disabling adding TerminationMessagePath on Windows as these files would be mounted as docker volume and // Docker for Windows has a bug where only directories can be mounted @@ -924,7 +902,11 @@ func (kl *Kubelet) PodResourcesAreReclaimed(pod *v1.Pod, status v1.PodStatus) bo return false } if len(runtimeStatus.ContainerStatuses) > 0 { - glog.V(3).Infof("Pod %q is terminated, but some containers have not been cleaned up: %+v", format.Pod(pod), runtimeStatus.ContainerStatuses) + var statusStr string + for _, status := range runtimeStatus.ContainerStatuses { + statusStr += fmt.Sprintf("%+v ", *status) + } + glog.V(3).Infof("Pod %q is terminated, but some containers have not been cleaned up: %s", format.Pod(pod), statusStr) return false } if kl.podVolumesExist(pod.UID) && !kl.keepTerminatedPodVolumes { @@ -1084,35 +1066,28 @@ func (kl *Kubelet) podKiller() { killing := sets.NewString() // guard for the killing set lock := sync.Mutex{} - for { - select { - case podPair, ok := <-kl.podKillingCh: - if !ok { - return - } + for podPair := range kl.podKillingCh { + runningPod := podPair.RunningPod + apiPod := podPair.APIPod - runningPod := podPair.RunningPod - apiPod := podPair.APIPod - - lock.Lock() - exists := killing.Has(string(runningPod.ID)) - if !exists { - killing.Insert(string(runningPod.ID)) - } - lock.Unlock() + lock.Lock() + exists := killing.Has(string(runningPod.ID)) + if !exists { + killing.Insert(string(runningPod.ID)) + } + lock.Unlock() - if !exists { - go func(apiPod *v1.Pod, runningPod *kubecontainer.Pod) { - glog.V(2).Infof("Killing unwanted pod %q", runningPod.Name) - err := kl.killPod(apiPod, runningPod, nil, nil) - if err != nil { - glog.Errorf("Failed killing the pod %q: %v", runningPod.Name, err) - } - lock.Lock() - killing.Delete(string(runningPod.ID)) - lock.Unlock() - }(apiPod, runningPod) - } + if !exists { + go func(apiPod *v1.Pod, runningPod *kubecontainer.Pod) { + glog.V(2).Infof("Killing unwanted pod %q", runningPod.Name) + err := kl.killPod(apiPod, runningPod, nil, nil) + if err != nil { + glog.Errorf("Failed killing the pod %q: %v", runningPod.Name, err) + } + lock.Lock() + killing.Delete(string(runningPod.ID)) + lock.Unlock() + }(apiPod, runningPod) } } } @@ -1378,7 +1353,8 @@ func (kl *Kubelet) generateAPIPodStatus(pod *v1.Pod, podStatus *kubecontainer.Po } kl.probeManager.UpdatePodStatus(pod.UID, s) s.Conditions = append(s.Conditions, status.GeneratePodInitializedCondition(spec, s.InitContainerStatuses, s.Phase)) - s.Conditions = append(s.Conditions, status.GeneratePodReadyCondition(spec, s.ContainerStatuses, s.Phase)) + s.Conditions = append(s.Conditions, status.GeneratePodReadyCondition(spec, s.Conditions, s.ContainerStatuses, s.Phase)) + s.Conditions = append(s.Conditions, status.GenerateContainersReadyCondition(spec, s.ContainerStatuses, s.Phase)) // Status manager will take care of the LastTransitionTimestamp, either preserve // the timestamp from apiserver, or set a new one. When kubelet sees the pod, // `PodScheduled` condition must be true. @@ -1431,6 +1407,12 @@ func (kl *Kubelet) convertStatusToAPIStatus(pod *v1.Pod, podStatus *kubecontaine true, ) + // Preserves conditions not controlled by kubelet + for _, c := range pod.Status.Conditions { + if !kubetypes.PodConditionByKubelet(c.Type) { + apiPodStatus.Conditions = append(apiPodStatus.Conditions, c) + } + } return &apiPodStatus } @@ -1612,142 +1594,60 @@ func (kl *Kubelet) RunInContainer(podFullName string, podUID types.UID, containe return kl.runner.RunInContainer(container.ID, cmd, 0) } -// ExecInContainer executes a command in a container, connecting the supplied -// stdin/stdout/stderr to the command's IO streams. -func (kl *Kubelet) ExecInContainer(podFullName string, podUID types.UID, containerName string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime) - if !ok { - return fmt.Errorf("streaming methods not supported by runtime") - } - +// GetExec gets the URL the exec will be served from, or nil if the Kubelet will serve it. +func (kl *Kubelet) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) (*url.URL, error) { container, err := kl.findContainer(podFullName, podUID, containerName) if err != nil { - return err + return nil, err } if container == nil { - return fmt.Errorf("container not found (%q)", containerName) + return nil, fmt.Errorf("container not found (%q)", containerName) } - return streamingRuntime.ExecInContainer(container.ID, cmd, stdin, stdout, stderr, tty, resize, timeout) + return kl.streamingRuntime.GetExec(container.ID, cmd, streamOpts.Stdin, streamOpts.Stdout, streamOpts.Stderr, streamOpts.TTY) } -// AttachContainer uses the container runtime to attach the given streams to -// the given container. -func (kl *Kubelet) AttachContainer(podFullName string, podUID types.UID, containerName string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime) - if !ok { - return fmt.Errorf("streaming methods not supported by runtime") - } - +// GetAttach gets the URL the attach will be served from, or nil if the Kubelet will serve it. +func (kl *Kubelet) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommandserver.Options) (*url.URL, error) { container, err := kl.findContainer(podFullName, podUID, containerName) if err != nil { - return err + return nil, err } if container == nil { - return fmt.Errorf("container not found (%q)", containerName) + return nil, fmt.Errorf("container %s not found in pod %s", containerName, podFullName) } - return streamingRuntime.AttachContainer(container.ID, stdin, stdout, stderr, tty, resize) -} -// PortForward connects to the pod's port and copies data between the port -// and the stream. -func (kl *Kubelet) PortForward(podFullName string, podUID types.UID, port int32, stream io.ReadWriteCloser) error { - streamingRuntime, ok := kl.containerRuntime.(kubecontainer.DirectStreamingRuntime) - if !ok { - return fmt.Errorf("streaming methods not supported by runtime") + // The TTY setting for attach must match the TTY setting in the initial container configuration, + // since whether the process is running in a TTY cannot be changed after it has started. We + // need the api.Pod to get the TTY status. + pod, found := kl.GetPodByFullName(podFullName) + if !found || (string(podUID) != "" && pod.UID != podUID) { + return nil, fmt.Errorf("pod %s not found", podFullName) + } + containerSpec := kubecontainer.GetContainerSpec(pod, containerName) + if containerSpec == nil { + return nil, fmt.Errorf("container %s not found in pod %s", containerName, podFullName) } + tty := containerSpec.TTY + + return kl.streamingRuntime.GetAttach(container.ID, streamOpts.Stdin, streamOpts.Stdout, streamOpts.Stderr, tty) +} +// GetPortForward gets the URL the port-forward will be served from, or nil if the Kubelet will serve it. +func (kl *Kubelet) GetPortForward(podName, podNamespace string, podUID types.UID, portForwardOpts portforward.V4Options) (*url.URL, error) { pods, err := kl.containerRuntime.GetPods(false) if err != nil { - return err + return nil, err } // Resolve and type convert back again. // We need the static pod UID but the kubecontainer API works with types.UID. podUID = types.UID(kl.podManager.TranslatePodUID(podUID)) + podFullName := kubecontainer.BuildPodFullName(podName, podNamespace) pod := kubecontainer.Pods(pods).FindPod(podFullName, podUID) if pod.IsEmpty() { - return fmt.Errorf("pod not found (%q)", podFullName) - } - return streamingRuntime.PortForward(&pod, port, stream) -} - -// GetExec gets the URL the exec will be served from, or nil if the Kubelet will serve it. -func (kl *Kubelet) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) (*url.URL, error) { - switch streamingRuntime := kl.containerRuntime.(type) { - case kubecontainer.DirectStreamingRuntime: - // Kubelet will serve the exec directly. - return nil, nil - case kubecontainer.IndirectStreamingRuntime: - container, err := kl.findContainer(podFullName, podUID, containerName) - if err != nil { - return nil, err - } - if container == nil { - return nil, fmt.Errorf("container not found (%q)", containerName) - } - return streamingRuntime.GetExec(container.ID, cmd, streamOpts.Stdin, streamOpts.Stdout, streamOpts.Stderr, streamOpts.TTY) - default: - return nil, fmt.Errorf("container runtime does not support exec") - } -} - -// GetAttach gets the URL the attach will be served from, or nil if the Kubelet will serve it. -func (kl *Kubelet) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommandserver.Options) (*url.URL, error) { - switch streamingRuntime := kl.containerRuntime.(type) { - case kubecontainer.DirectStreamingRuntime: - // Kubelet will serve the attach directly. - return nil, nil - case kubecontainer.IndirectStreamingRuntime: - container, err := kl.findContainer(podFullName, podUID, containerName) - if err != nil { - return nil, err - } - if container == nil { - return nil, fmt.Errorf("container %s not found in pod %s", containerName, podFullName) - } - - // The TTY setting for attach must match the TTY setting in the initial container configuration, - // since whether the process is running in a TTY cannot be changed after it has started. We - // need the api.Pod to get the TTY status. - pod, found := kl.GetPodByFullName(podFullName) - if !found || (string(podUID) != "" && pod.UID != podUID) { - return nil, fmt.Errorf("pod %s not found", podFullName) - } - containerSpec := kubecontainer.GetContainerSpec(pod, containerName) - if containerSpec == nil { - return nil, fmt.Errorf("container %s not found in pod %s", containerName, podFullName) - } - tty := containerSpec.TTY - - return streamingRuntime.GetAttach(container.ID, streamOpts.Stdin, streamOpts.Stdout, streamOpts.Stderr, tty) - default: - return nil, fmt.Errorf("container runtime does not support attach") + return nil, fmt.Errorf("pod not found (%q)", podFullName) } -} -// GetPortForward gets the URL the port-forward will be served from, or nil if the Kubelet will serve it. -func (kl *Kubelet) GetPortForward(podName, podNamespace string, podUID types.UID, portForwardOpts portforward.V4Options) (*url.URL, error) { - switch streamingRuntime := kl.containerRuntime.(type) { - case kubecontainer.DirectStreamingRuntime: - // Kubelet will serve the attach directly. - return nil, nil - case kubecontainer.IndirectStreamingRuntime: - pods, err := kl.containerRuntime.GetPods(false) - if err != nil { - return nil, err - } - // Resolve and type convert back again. - // We need the static pod UID but the kubecontainer API works with types.UID. - podUID = types.UID(kl.podManager.TranslatePodUID(podUID)) - podFullName := kubecontainer.BuildPodFullName(podName, podNamespace) - pod := kubecontainer.Pods(pods).FindPod(podFullName, podUID) - if pod.IsEmpty() { - return nil, fmt.Errorf("pod not found (%q)", podFullName) - } - - return streamingRuntime.GetPortForward(podName, podNamespace, podUID, portForwardOpts.Ports) - default: - return nil, fmt.Errorf("container runtime does not support port-forward") - } + return kl.streamingRuntime.GetPortForward(podName, podNamespace, podUID, portForwardOpts.Ports) } // cleanupOrphanedPodCgroups removes cgroups that should no longer exist. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_test.go index ccda5dffb..f4fc43b5f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_test.go @@ -17,7 +17,6 @@ limitations under the License. package kubelet import ( - "bytes" "errors" "fmt" "io/ioutil" @@ -38,9 +37,9 @@ import ( core "k8s.io/client-go/testing" "k8s.io/client-go/tools/record" // TODO: remove this import if - // api.Registry.GroupOrDie(v1.GroupName).GroupVersion.String() is changed + // api.Registry.GroupOrDie(v1.GroupName).GroupVersions[0].String() is changed // to "v1"? - "k8s.io/kubernetes/pkg/api/legacyscheme" + _ "k8s.io/kubernetes/pkg/apis/core/install" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" @@ -273,7 +272,7 @@ func TestMakeMounts(t *testing.T) { return } - mounts, _, err := makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", "", tc.podVolumes, fm) + mounts, _, err := makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", "", tc.podVolumes, fm, nil) // validate only the error if we expect an error if tc.expectErr { @@ -296,7 +295,7 @@ func TestMakeMounts(t *testing.T) { t.Errorf("Failed to enable feature gate for MountPropagation: %v", err) return } - mounts, _, err = makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", "", tc.podVolumes, fm) + mounts, _, err = makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", "", tc.podVolumes, fm, nil) if !tc.expectErr { expectedPrivateMounts := []kubecontainer.Mount{} for _, mount := range tc.expectedMounts { @@ -357,7 +356,7 @@ func TestDisabledSubpath(t *testing.T) { defer utilfeature.DefaultFeatureGate.Set("VolumeSubpath=true") for name, test := range cases { - _, _, err := makeMounts(&pod, "/pod", &test.container, "fakepodname", "", "", podVolumes, fm) + _, _, err := makeMounts(&pod, "/pod", &test.container, "fakepodname", "", "", podVolumes, fm, nil) if err != nil && !test.expectError { t.Errorf("test %v failed: %v", name, err) } @@ -519,7 +518,8 @@ fe00::1 ip6-allnodes fe00::2 ip6-allrouters 123.45.67.89 some.domain `, - `# hosts file for testing. + `# Kubernetes-managed hosts file (host network). +# hosts file for testing. 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet @@ -541,7 +541,8 @@ fe00::1 ip6-allnodes fe00::2 ip6-allrouters 12.34.56.78 another.domain `, - `# another hosts file for testing. + `# Kubernetes-managed hosts file (host network). +# another hosts file for testing. 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet @@ -565,7 +566,8 @@ fe00::1 ip6-allnodes fe00::2 ip6-allrouters 123.45.67.89 some.domain `, - `# hosts file for testing. + `# Kubernetes-managed hosts file (host network). +# hosts file for testing. 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet @@ -595,7 +597,8 @@ fe00::1 ip6-allnodes fe00::2 ip6-allrouters 12.34.56.78 another.domain `, - `# another hosts file for testing. + `# Kubernetes-managed hosts file (host network). +# another hosts file for testing. 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet @@ -993,7 +996,7 @@ func TestMakeEnvironmentVariables(t *testing.T) { Name: "POD_NAME", ValueFrom: &v1.EnvVarSource{ FieldRef: &v1.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.name", }, }, @@ -1002,7 +1005,7 @@ func TestMakeEnvironmentVariables(t *testing.T) { Name: "POD_NAMESPACE", ValueFrom: &v1.EnvVarSource{ FieldRef: &v1.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.namespace", }, }, @@ -1011,7 +1014,7 @@ func TestMakeEnvironmentVariables(t *testing.T) { Name: "POD_NODE_NAME", ValueFrom: &v1.EnvVarSource{ FieldRef: &v1.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "spec.nodeName", }, }, @@ -1020,7 +1023,7 @@ func TestMakeEnvironmentVariables(t *testing.T) { Name: "POD_SERVICE_ACCOUNT_NAME", ValueFrom: &v1.EnvVarSource{ FieldRef: &v1.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "spec.serviceAccountName", }, }, @@ -1029,7 +1032,7 @@ func TestMakeEnvironmentVariables(t *testing.T) { Name: "POD_IP", ValueFrom: &v1.EnvVarSource{ FieldRef: &v1.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "status.podIP", }, }, @@ -1038,7 +1041,7 @@ func TestMakeEnvironmentVariables(t *testing.T) { Name: "HOST_IP", ValueFrom: &v1.EnvVarSource{ FieldRef: &v1.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "status.hostIP", }, }, @@ -1069,7 +1072,7 @@ func TestMakeEnvironmentVariables(t *testing.T) { Name: "POD_NAME", ValueFrom: &v1.EnvVarSource{ FieldRef: &v1.ObjectFieldSelector{ - APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(), + APIVersion: "v1", FieldPath: "metadata.name", }, }, @@ -2091,7 +2094,7 @@ func (f *fakeReadWriteCloser) Close() error { return nil } -func TestExec(t *testing.T) { +func TestGetExec(t *testing.T) { const ( podName = "podFoo" podNamespace = "nsFoo" @@ -2102,9 +2105,6 @@ func TestExec(t *testing.T) { var ( podFullName = kubecontainer.GetPodFullName(podWithUIDNameNs(podUID, podName, podNamespace)) command = []string{"ls"} - stdin = &bytes.Buffer{} - stdout = &fakeReadWriteCloser{} - stderr = &fakeReadWriteCloser{} ) testcases := []struct { @@ -2145,66 +2145,28 @@ func TestExec(t *testing.T) { }}, } - { // No streaming case - description := "no streaming - " + tc.description - redirect, err := kubelet.GetExec(tc.podFullName, podUID, tc.container, command, remotecommand.Options{}) - assert.Error(t, err, description) - assert.Nil(t, redirect, description) + description := "streaming - " + tc.description + fakeRuntime := &containertest.FakeStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} + kubelet.containerRuntime = fakeRuntime + kubelet.streamingRuntime = fakeRuntime - err = kubelet.ExecInContainer(tc.podFullName, podUID, tc.container, command, stdin, stdout, stderr, tty, nil, 0) + redirect, err := kubelet.GetExec(tc.podFullName, podUID, tc.container, command, remotecommand.Options{}) + if tc.expectError { assert.Error(t, err, description) - } - { // Direct streaming case - description := "direct streaming - " + tc.description - fakeRuntime := &containertest.FakeDirectStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} - kubelet.containerRuntime = fakeRuntime - - redirect, err := kubelet.GetExec(tc.podFullName, podUID, tc.container, command, remotecommand.Options{}) + } else { assert.NoError(t, err, description) - assert.Nil(t, redirect, description) - - err = kubelet.ExecInContainer(tc.podFullName, podUID, tc.container, command, stdin, stdout, stderr, tty, nil, 0) - if tc.expectError { - assert.Error(t, err, description) - } else { - assert.NoError(t, err, description) - assert.Equal(t, fakeRuntime.Args.ContainerID.ID, containerID, description+": ID") - assert.Equal(t, fakeRuntime.Args.Cmd, command, description+": Command") - assert.Equal(t, fakeRuntime.Args.Stdin, stdin, description+": Stdin") - assert.Equal(t, fakeRuntime.Args.Stdout, stdout, description+": Stdout") - assert.Equal(t, fakeRuntime.Args.Stderr, stderr, description+": Stderr") - assert.Equal(t, fakeRuntime.Args.TTY, tty, description+": TTY") - } - } - { // Indirect streaming case - description := "indirect streaming - " + tc.description - fakeRuntime := &containertest.FakeIndirectStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} - kubelet.containerRuntime = fakeRuntime - - redirect, err := kubelet.GetExec(tc.podFullName, podUID, tc.container, command, remotecommand.Options{}) - if tc.expectError { - assert.Error(t, err, description) - } else { - assert.NoError(t, err, description) - assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect") - } - - err = kubelet.ExecInContainer(tc.podFullName, podUID, tc.container, command, stdin, stdout, stderr, tty, nil, 0) - assert.Error(t, err, description) + assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect") } } } -func TestPortForward(t *testing.T) { +func TestGetPortForward(t *testing.T) { const ( podName = "podFoo" podNamespace = "nsFoo" podUID types.UID = "12345678" port int32 = 5000 ) - var ( - stream = &fakeReadWriteCloser{} - ) testcases := []struct { description string @@ -2236,50 +2198,17 @@ func TestPortForward(t *testing.T) { }}, } - podFullName := kubecontainer.GetPodFullName(podWithUIDNameNs(podUID, tc.podName, podNamespace)) - { // No streaming case - description := "no streaming - " + tc.description - redirect, err := kubelet.GetPortForward(tc.podName, podNamespace, podUID, portforward.V4Options{}) - assert.Error(t, err, description) - assert.Nil(t, redirect, description) + description := "streaming - " + tc.description + fakeRuntime := &containertest.FakeStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} + kubelet.containerRuntime = fakeRuntime + kubelet.streamingRuntime = fakeRuntime - err = kubelet.PortForward(podFullName, podUID, port, stream) + redirect, err := kubelet.GetPortForward(tc.podName, podNamespace, podUID, portforward.V4Options{}) + if tc.expectError { assert.Error(t, err, description) - } - { // Direct streaming case - description := "direct streaming - " + tc.description - fakeRuntime := &containertest.FakeDirectStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} - kubelet.containerRuntime = fakeRuntime - - redirect, err := kubelet.GetPortForward(tc.podName, podNamespace, podUID, portforward.V4Options{}) + } else { assert.NoError(t, err, description) - assert.Nil(t, redirect, description) - - err = kubelet.PortForward(podFullName, podUID, port, stream) - if tc.expectError { - assert.Error(t, err, description) - } else { - assert.NoError(t, err, description) - require.Equal(t, fakeRuntime.Args.Pod.ID, podUID, description+": Pod UID") - require.Equal(t, fakeRuntime.Args.Port, port, description+": Port") - require.Equal(t, fakeRuntime.Args.Stream, stream, description+": stream") - } - } - { // Indirect streaming case - description := "indirect streaming - " + tc.description - fakeRuntime := &containertest.FakeIndirectStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime} - kubelet.containerRuntime = fakeRuntime - - redirect, err := kubelet.GetPortForward(tc.podName, podNamespace, podUID, portforward.V4Options{}) - if tc.expectError { - assert.Error(t, err, description) - } else { - assert.NoError(t, err, description) - assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect") - } - - err = kubelet.PortForward(podFullName, podUID, port, stream) - assert.Error(t, err, description) + assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect") } } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_windows_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_windows_test.go index cc16b358f..628c2ecdd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_windows_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_windows_test.go @@ -66,7 +66,7 @@ func TestMakeMountsWindows(t *testing.T) { } fm := &mount.FakeMounter{} - mounts, _, _ := makeMounts(&pod, "/pod", &container, "fakepodname", "", "", podVolumes, fm) + mounts, _, _ := makeMounts(&pod, "/pod", &container, "fakepodname", "", "", podVolumes, fm, nil) expectedMounts := []kubecontainer.Mount{ { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_test.go index b849f91da..fd18b1283 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_test.go @@ -41,7 +41,6 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/flowcontrol" "k8s.io/kubernetes/pkg/capabilities" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing" "k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/pkg/kubelet/config" @@ -49,12 +48,9 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" "k8s.io/kubernetes/pkg/kubelet/eviction" - "k8s.io/kubernetes/pkg/kubelet/gpu" "k8s.io/kubernetes/pkg/kubelet/images" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/logs" - "k8s.io/kubernetes/pkg/kubelet/network" - nettest "k8s.io/kubernetes/pkg/kubelet/network/testing" "k8s.io/kubernetes/pkg/kubelet/pleg" kubepod "k8s.io/kubernetes/pkg/kubelet/pod" podtest "k8s.io/kubernetes/pkg/kubelet/pod/testing" @@ -65,12 +61,16 @@ import ( "k8s.io/kubernetes/pkg/kubelet/stats" "k8s.io/kubernetes/pkg/kubelet/status" statustest "k8s.io/kubernetes/pkg/kubelet/status/testing" + "k8s.io/kubernetes/pkg/kubelet/token" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/queue" kubeletvolume "k8s.io/kubernetes/pkg/kubelet/volumemanager" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/aws_ebs" + "k8s.io/kubernetes/pkg/volume/azure_dd" + "k8s.io/kubernetes/pkg/volume/gce_pd" _ "k8s.io/kubernetes/pkg/volume/host_path" volumetest "k8s.io/kubernetes/pkg/volume/testing" "k8s.io/kubernetes/pkg/volume/util" @@ -137,13 +137,30 @@ func newTestKubelet(t *testing.T, controllerAttachDetachEnabled bool) *TestKubel Size: 456, }, } - return newTestKubeletWithImageList(t, imageList, controllerAttachDetachEnabled) + return newTestKubeletWithImageList(t, imageList, controllerAttachDetachEnabled, true /*initFakeVolumePlugin*/) +} + +func newTestKubeletWithoutFakeVolumePlugin(t *testing.T, controllerAttachDetachEnabled bool) *TestKubelet { + imageList := []kubecontainer.Image{ + { + ID: "abc", + RepoTags: []string{"k8s.gcr.io:v1", "k8s.gcr.io:v2"}, + Size: 123, + }, + { + ID: "efg", + RepoTags: []string{"k8s.gcr.io:v3", "k8s.gcr.io:v4"}, + Size: 456, + }, + } + return newTestKubeletWithImageList(t, imageList, controllerAttachDetachEnabled, false /*initFakeVolumePlugin*/) } func newTestKubeletWithImageList( t *testing.T, imageList []kubecontainer.Image, - controllerAttachDetachEnabled bool) *TestKubelet { + controllerAttachDetachEnabled bool, + initFakeVolumePlugin bool) *TestKubelet { fakeRuntime := &containertest.FakeRuntime{} fakeRuntime.RuntimeType = "test" fakeRuntime.VersionInfo = "1.5.0" @@ -169,7 +186,6 @@ func newTestKubeletWithImageList( kubelet.nodeName = types.NodeName(testKubeletHostname) kubelet.runtimeState = newRuntimeState(maxWaitForContainerRuntime) kubelet.runtimeState.setNetworkState(nil) - kubelet.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", nettest.NewFakeHost(nil), kubeletconfig.HairpinNone, "", 1440) if tempDir, err := ioutil.TempDir("/tmp", "kubelet_test."); err != nil { t.Fatalf("can't make a temp rootdir: %v", err) } else { @@ -220,7 +236,7 @@ func newTestKubeletWithImageList( kubelet.secretManager = secretManager configMapManager := configmap.NewSimpleConfigMapManager(kubelet.kubeClient) kubelet.configMapManager = configMapManager - kubelet.podManager = kubepod.NewBasicPodManager(fakeMirrorClient, kubelet.secretManager, kubelet.configMapManager) + kubelet.podManager = kubepod.NewBasicPodManager(fakeMirrorClient, kubelet.secretManager, kubelet.configMapManager, podtest.NewMockCheckpointManager()) kubelet.statusManager = status.NewManager(fakeKubeClient, kubelet.podManager, &statustest.FakePodDeletionSafetyProvider{}) kubelet.containerRuntime = fakeRuntime @@ -298,10 +314,19 @@ func newTestKubeletWithImageList( // Add this as cleanup predicate pod admitter kubelet.admitHandlers.AddPodAdmitHandler(lifecycle.NewPredicateAdmitHandler(kubelet.getNodeAnyWay, lifecycle.NewAdmissionFailureHandlerStub(), kubelet.containerManager.UpdatePluginResources)) + allPlugins := []volume.VolumePlugin{} plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil} + if initFakeVolumePlugin { + allPlugins = append(allPlugins, plug) + } else { + allPlugins = append(allPlugins, aws_ebs.ProbeVolumePlugins()...) + allPlugins = append(allPlugins, gce_pd.ProbeVolumePlugins()...) + allPlugins = append(allPlugins, azure_dd.ProbeVolumePlugins()...) + } + var prober volume.DynamicPluginProber = nil // TODO (#51147) inject mock kubelet.volumePluginMgr, err = - NewInitializedVolumePluginMgr(kubelet, kubelet.secretManager, kubelet.configMapManager, []volume.VolumePlugin{plug}, prober) + NewInitializedVolumePluginMgr(kubelet, kubelet.secretManager, kubelet.configMapManager, token.NewManager(kubelet.kubeClient), allPlugins, prober) require.NoError(t, err, "Failed to initialize VolumePluginMgr") kubelet.mounter = &mount.FakeMounter{} @@ -325,7 +350,6 @@ func newTestKubeletWithImageList( kubelet.AddPodSyncLoopHandler(activeDeadlineHandler) kubelet.AddPodSyncHandler(activeDeadlineHandler) - kubelet.gpuManager = gpu.NewGPUManagerStub() return &TestKubelet{kubelet, fakeRuntime, mockCadvisor, fakeKubeClient, fakeMirrorClient, fakeClock, nil, plug} } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_volumes_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_volumes_test.go index dc2c89a66..a82aa0616 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_volumes_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_volumes_test.go @@ -261,7 +261,7 @@ func TestVolumeUnmountAndDetachControllerDisabled(t *testing.T) { 1 /* expectedTearDownCallCount */, testKubelet.volumePlugin)) // Verify volumes detached and no longer reported as in use - assert.NoError(t, waitForVolumeDetach(v1.UniqueVolumeName("fake/vol1"), kubelet.volumeManager)) + assert.NoError(t, waitForVolumeDetach(v1.UniqueVolumeName("fake/fake-device"), kubelet.volumeManager)) assert.True(t, testKubelet.volumePlugin.GetNewAttacherCallCount() >= 1, "Expected plugin NewAttacher to be called at least once") assert.NoError(t, volumetest.VerifyDetachCallCount( 1 /* expectedDetachCallCount */, testKubelet.volumePlugin)) @@ -279,11 +279,10 @@ func TestVolumeAttachAndMountControllerEnabled(t *testing.T) { Status: v1.NodeStatus{ VolumesAttached: []v1.AttachedVolume{ { - Name: "fake/vol1", + Name: "fake/fake-device", DevicePath: "fake/path", }, }}, - Spec: v1.NodeSpec{ExternalID: testKubeletHostname}, }, nil }) kubeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { @@ -310,7 +309,7 @@ func TestVolumeAttachAndMountControllerEnabled(t *testing.T) { // Fake node status update go simulateVolumeInUseUpdate( - v1.UniqueVolumeName("fake/vol1"), + v1.UniqueVolumeName("fake/fake-device"), stopCh, kubelet.volumeManager) @@ -346,11 +345,10 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) { Status: v1.NodeStatus{ VolumesAttached: []v1.AttachedVolume{ { - Name: "fake/vol1", + Name: "fake/fake-device", DevicePath: "fake/path", }, }}, - Spec: v1.NodeSpec{ExternalID: testKubeletHostname}, }, nil }) kubeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { @@ -378,7 +376,7 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) { // Fake node status update go simulateVolumeInUseUpdate( - v1.UniqueVolumeName("fake/vol1"), + v1.UniqueVolumeName("fake/fake-device"), stopCh, kubelet.volumeManager) @@ -419,7 +417,7 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) { 1 /* expectedTearDownCallCount */, testKubelet.volumePlugin)) // Verify volumes detached and no longer reported as in use - assert.NoError(t, waitForVolumeDetach(v1.UniqueVolumeName("fake/vol1"), kubelet.volumeManager)) + assert.NoError(t, waitForVolumeDetach(v1.UniqueVolumeName("fake/fake-device"), kubelet.volumeManager)) assert.True(t, testKubelet.volumePlugin.GetNewAttacherCallCount() >= 1, "Expected plugin NewAttacher to be called at least once") assert.NoError(t, volumetest.VerifyZeroDetachCallCount(testKubelet.volumePlugin)) } @@ -465,6 +463,11 @@ func (f *stubBlockVolume) GetPodDeviceMapPath() (string, string) { func (f *stubBlockVolume) SetUpDevice() (string, error) { return "", nil } + +func (f stubBlockVolume) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return nil +} + func (f *stubBlockVolume) TearDownDevice(mapPath string, devicePath string) error { return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/BUILD index ae3e99f67..c409bd2a3 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/BUILD @@ -19,12 +19,12 @@ go_library( "//pkg/kubelet/kubeletconfig/checkpoint:go_default_library", "//pkg/kubelet/kubeletconfig/checkpoint/store:go_default_library", "//pkg/kubelet/kubeletconfig/status:go_default_library", - "//pkg/kubelet/kubeletconfig/util/equal:go_default_library", "//pkg/kubelet/kubeletconfig/util/log:go_default_library", "//pkg/kubelet/kubeletconfig/util/panic:go_default_library", "//pkg/util/filesystem:go_default_library", "//vendor/github.com/golang/glog: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/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/BUILD index a04eed0d3..a0b744629 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/BUILD @@ -9,48 +9,44 @@ load( go_test( name = "go_default_test", srcs = [ - "checkpoint_test.go", "configmap_test.go", "download_test.go", ], embed = [":go_default_library"], deps = [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", - "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", - "//pkg/kubelet/kubeletconfig/util/codec:go_default_library", "//pkg/kubelet/kubeletconfig/util/test:go_default_library", "//vendor/github.com/davecgh/go-spew/spew: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/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", ], ) go_library( name = "go_default_library", srcs = [ - "checkpoint.go", "configmap.go", "download.go", ], importpath = "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint", deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", "//pkg/kubelet/kubeletconfig/status:go_default_library", "//pkg/kubelet/kubeletconfig/util/codec:go_default_library", "//pkg/kubelet/kubeletconfig/util/log: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/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/checkpoint.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/checkpoint.go deleted file mode 100644 index be44aaaa3..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/checkpoint.go +++ /dev/null @@ -1,72 +0,0 @@ -/* -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 checkpoint - -import ( - "fmt" - - apiv1 "k8s.io/api/core/v1" - apiequality "k8s.io/apimachinery/pkg/api/equality" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" -) - -// Checkpoint represents a local copy of a config source (payload) object -type Checkpoint interface { - // UID returns the UID of the config source object behind the Checkpoint - UID() string - // Parse extracts the KubeletConfiguration from the checkpoint, applies defaults, and converts to the internal type - Parse() (*kubeletconfig.KubeletConfiguration, error) - // Encode returns a []byte representation of the config source object behind the Checkpoint - Encode() ([]byte, error) - - // object returns the underlying checkpointed object. If you want to compare sources for equality, use EqualCheckpoints, - // which compares the underlying checkpointed objects for semantic API equality. - object() interface{} -} - -// DecodeCheckpoint is a helper for using the apimachinery to decode serialized checkpoints -func DecodeCheckpoint(data []byte) (Checkpoint, error) { - // decode the checkpoint - obj, err := runtime.Decode(legacyscheme.Codecs.UniversalDecoder(), data) - if err != nil { - return nil, fmt.Errorf("failed to decode, error: %v", err) - } - - // TODO(mtaufen): for now we assume we are trying to load a ConfigMap checkpoint, may need to extend this if we allow other checkpoint types - - // convert it to the external ConfigMap type, so we're consistently working with the external type outside of the on-disk representation - cm := &apiv1.ConfigMap{} - err = legacyscheme.Scheme.Convert(obj, cm, nil) - if err != nil { - return nil, fmt.Errorf("failed to convert decoded object into a v1 ConfigMap, error: %v", err) - } - - return NewConfigMapCheckpoint(cm) -} - -// EqualCheckpoints compares two Checkpoints for equality, if their underlying objects are equal, so are the Checkpoints -func EqualCheckpoints(a, b Checkpoint) bool { - if a != nil && b != nil { - return apiequality.Semantic.DeepEqual(a.object(), b.object()) - } - if a == nil && b == nil { - return true - } - return false -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/checkpoint_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/checkpoint_test.go deleted file mode 100644 index abcf9981b..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/checkpoint_test.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -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 checkpoint - -import ( - "testing" - - "github.com/davecgh/go-spew/spew" - - apiv1 "k8s.io/api/core/v1" - 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" - utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec" - utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test" -) - -func TestDecodeCheckpoint(t *testing.T) { - // generate correct Checkpoint for v1/ConfigMap test case - cm, err := NewConfigMapCheckpoint(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: types.UID("uid")}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // generate unsupported object encoding for unsupported type test case - unsupported := newUnsupportedEncoded(t) - - // test cases - cases := []struct { - desc string - data []byte - expect Checkpoint // expect a deeply-equal Checkpoint to be returned from Decode - err string // expect error to contain this substring - }{ - // v1/ConfigMap - {"v1/ConfigMap", []byte(`{"apiVersion": "v1","kind": "ConfigMap","metadata": {"uid": "uid"}}`), cm, ""}, - // malformed - {"malformed", []byte("malformed"), nil, "failed to decode"}, - // no UID - {"no UID", []byte(`{"apiVersion": "v1","kind": "ConfigMap"}`), nil, "ConfigMap must have a UID"}, - // well-formed, but unsupported type - {"well-formed, but unsupported encoded type", unsupported, nil, "failed to convert"}, - } - - for _, c := range cases { - cpt, err := DecodeCheckpoint(c.data) - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - // Unfortunately reflect.DeepEqual treats nil data structures as != empty data structures, so - // we have to settle for semantic equality of the underlying checkpointed API objects. - // If additional fields are added to the object that implements the Checkpoint interface, - // they should be added to a named sub-object to facilitate a DeepEquals comparison - // of the extra fields. - // decoded checkpoint should match expected checkpoint - if !apiequality.Semantic.DeepEqual(cpt.object(), c.expect.object()) { - t.Errorf("case %q, expect checkpoint %s but got %s", c.desc, spew.Sdump(c.expect), spew.Sdump(cpt)) - } - } -} - -// newUnsupportedEncoded returns an encoding of an object that does not have a Checkpoint implementation -func newUnsupportedEncoded(t *testing.T) []byte { - encoder, err := utilcodec.NewJSONEncoder(apiv1.GroupName) - if err != nil { - t.Fatalf("could not create an encoder, error: %v", err) - } - unsupported := &apiv1.Node{} - data, err := runtime.Encode(encoder, unsupported) - if err != nil { - t.Fatalf("could not encode object, error: %v", err) - } - return data -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/configmap.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/configmap.go index 076e7ed33..b79e67e75 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/configmap.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/configmap.go @@ -20,75 +20,42 @@ import ( "fmt" apiv1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" - kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" - utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec" ) const configMapConfigKey = "kubelet" -// configMapCheckpoint implements Checkpoint, backed by a v1/ConfigMap config source object -type configMapCheckpoint struct { - kubeletCodecs *serializer.CodecFactory // codecs for the KubeletConfiguration - configMap *apiv1.ConfigMap +// configMapPayload implements Payload, backed by a v1/ConfigMap config source object +type configMapPayload struct { + cm *apiv1.ConfigMap } -// NewConfigMapCheckpoint returns a Checkpoint backed by `cm`. `cm` must be non-nil -// and have a non-empty ObjectMeta.UID, or an error will be returned. -func NewConfigMapCheckpoint(cm *apiv1.ConfigMap) (Checkpoint, error) { - if cm == nil { - return nil, fmt.Errorf("ConfigMap must be non-nil to be treated as a Checkpoint") - } else if len(cm.ObjectMeta.UID) == 0 { - return nil, fmt.Errorf("ConfigMap must have a UID to be treated as a Checkpoint") - } +var _ Payload = (*configMapPayload)(nil) - _, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs() - if err != nil { - return nil, err +// NewConfigMapPayload constructs a Payload backed by a ConfigMap, which must have a non-empty UID +func NewConfigMapPayload(cm *apiv1.ConfigMap) (Payload, error) { + if cm == nil { + return nil, fmt.Errorf("ConfigMap must be non-nil") + } else if cm.ObjectMeta.UID == "" { + return nil, fmt.Errorf("ConfigMap must have a non-empty UID") + } else if cm.ObjectMeta.ResourceVersion == "" { + return nil, fmt.Errorf("ConfigMap must have a non-empty ResourceVersion") } - return &configMapCheckpoint{kubeletCodecs, cm}, nil + return &configMapPayload{cm}, nil } -// UID returns the UID of a configMapCheckpoint -func (c *configMapCheckpoint) UID() string { - return string(c.configMap.UID) +func (p *configMapPayload) UID() string { + return string(p.cm.UID) } -// Parse extracts the KubeletConfiguration from v1/ConfigMap checkpoints, applies defaults, and converts to the internal type -func (c *configMapCheckpoint) Parse() (*kubeletconfig.KubeletConfiguration, error) { - const emptyCfgErr = "config was empty, but some parameters are required" - - if len(c.configMap.Data) == 0 { - return nil, fmt.Errorf(emptyCfgErr) - } - - config, ok := c.configMap.Data[configMapConfigKey] - if !ok { - return nil, fmt.Errorf("key %q not found in ConfigMap", configMapConfigKey) - } else if len(config) == 0 { - return nil, fmt.Errorf(emptyCfgErr) - } - - return utilcodec.DecodeKubeletConfiguration(c.kubeletCodecs, []byte(config)) +func (p *configMapPayload) ResourceVersion() string { + return p.cm.ResourceVersion } -// Encode encodes a configMapCheckpoint -func (c *configMapCheckpoint) Encode() ([]byte, error) { - cm := c.configMap - encoder, err := utilcodec.NewJSONEncoder(apiv1.GroupName) - if err != nil { - return nil, err - } - data, err := runtime.Encode(encoder, cm) - if err != nil { - return nil, err - } - return data, nil +func (p *configMapPayload) Files() map[string]string { + return p.cm.Data } -func (c *configMapCheckpoint) object() interface{} { - return c.configMap +func (p *configMapPayload) object() interface{} { + return p.cm } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/configmap_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/configmap_test.go index a60f34aa6..db44fab3b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/configmap_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/configmap_test.go @@ -17,7 +17,7 @@ limitations under the License. package checkpoint import ( - "fmt" + "reflect" "testing" "github.com/davecgh/go-spew/spew" @@ -25,213 +25,124 @@ import ( apiv1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" - kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" - kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test" ) -func TestNewConfigMapCheckpoint(t *testing.T) { +func TestNewConfigMapPayload(t *testing.T) { cases := []struct { desc string cm *apiv1.ConfigMap err string }{ - {"nil v1/ConfigMap", nil, "must be non-nil"}, - {"empty v1/ConfigMap", &apiv1.ConfigMap{}, "must have a UID"}, - {"populated v1/ConfigMap", - &apiv1.ConfigMap{ + { + desc: "nil", + cm: nil, + err: "ConfigMap must be non-nil", + }, + { + desc: "missing uid", + cm: &apiv1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "name", + ResourceVersion: "rv", + }, + }, + err: "ConfigMap must have a non-empty UID", + }, + { + desc: "missing resourceVersion", + cm: &apiv1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "name", - UID: types.UID("uid"), + UID: "uid", + }, + }, + err: "ConfigMap must have a non-empty ResourceVersion", + }, + { + desc: "populated v1/ConfigMap", + cm: &apiv1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "name", + UID: "uid", + ResourceVersion: "rv", }, Data: map[string]string{ "key1": "value1", "key2": "value2", }, - }, ""}, + }, + err: "", + }, } for _, c := range cases { - cpt, err := NewConfigMapCheckpoint(c.cm) - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - // underlying object should match the object passed in - if !apiequality.Semantic.DeepEqual(cpt.object(), c.cm) { - t.Errorf("case %q, expect Checkpoint %s but got %s", c.desc, spew.Sdump(c.cm), spew.Sdump(cpt)) - } + t.Run(c.desc, func(t *testing.T) { + payload, err := NewConfigMapPayload(c.cm) + utiltest.ExpectError(t, err, c.err) + if err != nil { + return + } + // underlying object should match the object passed in + if !apiequality.Semantic.DeepEqual(c.cm, payload.object()) { + t.Errorf("expect %s but got %s", spew.Sdump(c.cm), spew.Sdump(payload)) + } + }) } } -func TestConfigMapCheckpointUID(t *testing.T) { - _, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs() +func TestConfigMapPayloadUID(t *testing.T) { + const expect = "uid" + payload, err := NewConfigMapPayload(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: expect, ResourceVersion: "rv"}}) if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatalf("error constructing payload: %v", err) } - - cases := []string{"", "uid", "376dfb73-56db-11e7-a01e-42010a800002"} - for _, uidIn := range cases { - cpt := &configMapCheckpoint{ - kubeletCodecs, - &apiv1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{UID: types.UID(uidIn)}, - }, - } - // UID method should return the correct value of the UID - uidOut := cpt.UID() - if uidIn != uidOut { - t.Errorf("expect UID() to return %q, but got %q", uidIn, uidOut) - } + uid := payload.UID() + if expect != uid { + t.Errorf("expect %q, but got %q", expect, uid) } } -func TestConfigMapCheckpointParse(t *testing.T) { - kubeletScheme, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs() +func TestConfigMapPayloadResourceVersion(t *testing.T) { + const expect = "rv" + payload, err := NewConfigMapPayload(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: "uid", ResourceVersion: expect}}) if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatalf("error constructing payload: %v", err) } - - // get the built-in default configuration - external := &kubeletconfigv1beta1.KubeletConfiguration{} - kubeletScheme.Default(external) - defaultConfig := &kubeletconfig.KubeletConfiguration{} - err = kubeletScheme.Convert(external, defaultConfig, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - cases := []struct { - desc string - cm *apiv1.ConfigMap - expect *kubeletconfig.KubeletConfiguration - err string - }{ - {"empty data", &apiv1.ConfigMap{}, nil, "config was empty"}, - // missing kubelet key - {"missing kubelet key", &apiv1.ConfigMap{Data: map[string]string{ - "bogus": "stuff"}}, nil, fmt.Sprintf("key %q not found", configMapConfigKey)}, - // invalid format - {"invalid yaml", &apiv1.ConfigMap{Data: map[string]string{ - "kubelet": "*"}}, nil, "failed to decode"}, - {"invalid json", &apiv1.ConfigMap{Data: map[string]string{ - "kubelet": "{*"}}, nil, "failed to decode"}, - // invalid object - {"missing kind", &apiv1.ConfigMap{Data: map[string]string{ - "kubelet": `{"apiVersion":"kubelet.config.k8s.io/v1beta1"}`}}, nil, "failed to decode"}, - {"missing version", &apiv1.ConfigMap{Data: map[string]string{ - "kubelet": `{"kind":"KubeletConfiguration"}`}}, nil, "failed to decode"}, - {"unregistered kind", &apiv1.ConfigMap{Data: map[string]string{ - "kubelet": `{"kind":"BogusKind","apiVersion":"kubelet.config.k8s.io/v1beta1"}`}}, nil, "failed to decode"}, - {"unregistered version", &apiv1.ConfigMap{Data: map[string]string{ - "kubelet": `{"kind":"KubeletConfiguration","apiVersion":"bogusversion"}`}}, nil, "failed to decode"}, - // empty object with correct kind and version should result in the defaults for that kind and version - {"default from yaml", &apiv1.ConfigMap{Data: map[string]string{ - "kubelet": `kind: KubeletConfiguration -apiVersion: kubelet.config.k8s.io/v1beta1`}}, defaultConfig, ""}, - {"default from json", &apiv1.ConfigMap{Data: map[string]string{ - "kubelet": `{"kind":"KubeletConfiguration","apiVersion":"kubelet.config.k8s.io/v1beta1"}`}}, defaultConfig, ""}, - } - for _, c := range cases { - cpt := &configMapCheckpoint{kubeletCodecs, c.cm} - kc, err := cpt.Parse() - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - // we expect the parsed configuration to match what we described in the ConfigMap - if !apiequality.Semantic.DeepEqual(c.expect, kc) { - t.Errorf("case %q, expect config %s but got %s", c.desc, spew.Sdump(c.expect), spew.Sdump(kc)) - } + resourceVersion := payload.ResourceVersion() + if expect != resourceVersion { + t.Errorf("expect %q, but got %q", expect, resourceVersion) } } -func TestConfigMapCheckpointEncode(t *testing.T) { - _, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // only one case, based on output from the existing encoder, and since - // this is hard to test (key order isn't guaranteed), we should probably - // just stick to this test case and mostly rely on the round-trip test. +func TestConfigMapPayloadFiles(t *testing.T) { cases := []struct { desc string - cpt *configMapCheckpoint - expect string + data map[string]string + expect map[string]string }{ - // we expect Checkpoints to be encoded as a json representation of the underlying API object - {"one-key", - &configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{Name: "one-key"}, - Data: map[string]string{"one": ""}}}, - `{"kind":"ConfigMap","apiVersion":"v1","metadata":{"name":"one-key","creationTimestamp":null},"data":{"one":""}} -`}, - } - - for _, c := range cases { - data, err := c.cpt.Encode() - // we don't expect any errors from encoding - if utiltest.SkipRest(t, c.desc, err, "") { - continue - } - if string(data) != c.expect { - t.Errorf("case %q, expect encoding %q but got %q", c.desc, c.expect, string(data)) - } - } -} - -func TestConfigMapCheckpointRoundTrip(t *testing.T) { - _, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - cases := []struct { - desc string - cpt *configMapCheckpoint - decodeErr string - }{ - // empty data - {"empty data", - &configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "empty-data-sha256-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - UID: "uid", - }, - Data: map[string]string{}}}, - ""}, - // two keys - {"two keys", - &configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "two-keys-sha256-2bff03d6249c8a9dc9a1436d087c124741361ccfac6615b81b67afcff5c42431", - UID: "uid", - }, - Data: map[string]string{"one": "", "two": "2"}}}, - ""}, - // missing uid - {"missing uid", - &configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "two-keys-sha256-2bff03d6249c8a9dc9a1436d087c124741361ccfac6615b81b67afcff5c42431", - UID: "", - }, - Data: map[string]string{"one": "", "two": "2"}}}, - "must have a UID"}, + {"nil", nil, nil}, + {"empty", map[string]string{}, map[string]string{}}, + {"populated", + map[string]string{ + "foo": "1", + "bar": "2", + }, + map[string]string{ + "foo": "1", + "bar": "2", + }}, } for _, c := range cases { - // we don't expect any errors from encoding - data, err := c.cpt.Encode() - if utiltest.SkipRest(t, c.desc, err, "") { - continue - } - after, err := DecodeCheckpoint(data) - if utiltest.SkipRest(t, c.desc, err, c.decodeErr) { - continue - } - if !apiequality.Semantic.DeepEqual(c.cpt.object(), after.object()) { - t.Errorf("case %q, expect round-trip result %s but got %s", c.desc, spew.Sdump(c.cpt), spew.Sdump(after)) - } + t.Run(c.desc, func(t *testing.T) { + payload, err := NewConfigMapPayload(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: "uid", ResourceVersion: "rv"}, Data: c.data}) + if err != nil { + t.Fatalf("error constructing payload: %v", err) + } + files := payload.Files() + if !reflect.DeepEqual(c.expect, files) { + t.Errorf("expected %v, but got %v", c.expect, files) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/download.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/download.go index 9b516a0eb..eb7059806 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/download.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/download.go @@ -18,89 +18,130 @@ package checkpoint import ( "fmt" + "math/rand" + "time" apiv1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" + kuberuntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/client-go/tools/cache" + kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status" utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec" utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log" ) +// Payload represents a local copy of a config source (payload) object +type Payload interface { + // UID returns a globally unique (space and time) identifier for the payload. + // The return value is guaranteed non-empty. + UID() string + + // ResourceVersion returns a resource version for the payload. + // The return value is guaranteed non-empty. + ResourceVersion() string + + // Files returns a map of filenames to file contents. + Files() map[string]string + + // object returns the underlying checkpointed object. + object() interface{} +} + // RemoteConfigSource represents a remote config source object that can be downloaded as a Checkpoint type RemoteConfigSource interface { - // UID returns the UID of the remote config source object - UID() string + // KubeletFilename returns the name of the Kubelet config file as it should appear in the keys of Payload.Files() + KubeletFilename() string + // APIPath returns the API path to the remote resource, e.g. its SelfLink APIPath() string - // Download downloads the remote config source object returns a Checkpoint backed by the object, - // or a sanitized failure reason and error if the download fails - Download(client clientset.Interface) (Checkpoint, string, error) + + // UID returns the globally unique identifier for the most recently downloaded payload targeted by the source. + UID() string + + // ResourceVersion returns the resource version of the most recently downloaded payload targeted by the source. + ResourceVersion() string + + // Download downloads the remote config source's target object and returns a Payload backed by the object, + // or a sanitized failure reason and error if the download fails. + // Download takes an optional store as an argument. If provided, Download will check this store for the + // target object prior to contacting the API server. + // Download updates the local UID and ResourceVersion tracked by this source, based on the downloaded payload. + Download(client clientset.Interface, store cache.Store) (Payload, string, error) + + // Informer returns an informer that can be used to detect changes to the remote config source + Informer(client clientset.Interface, handler cache.ResourceEventHandlerFuncs) cache.SharedInformer + // Encode returns a []byte representation of the object behind the RemoteConfigSource Encode() ([]byte, error) - // object returns the underlying source object. If you want to compare sources for equality, use EqualRemoteConfigSources, - // which compares the underlying source objects for semantic API equality. - object() interface{} + // NodeConfigSource returns a copy of the underlying apiv1.NodeConfigSource object. + // All RemoteConfigSources are expected to be backed by a NodeConfigSource, + // though the convenience methods on the interface will target the source + // type that was detected in a call to NewRemoteConfigSource. + NodeConfigSource() *apiv1.NodeConfigSource } -// NewRemoteConfigSource constructs a RemoteConfigSource from a v1/NodeConfigSource object, or returns -// a sanitized failure reason and an error if the `source` is blatantly invalid. +// NewRemoteConfigSource constructs a RemoteConfigSource from a v1/NodeConfigSource object // You should only call this with a non-nil config source. +// Note that the API server validates Node.Spec.ConfigSource. func NewRemoteConfigSource(source *apiv1.NodeConfigSource) (RemoteConfigSource, string, error) { - // exactly one subfield of the config source must be non-nil, toady ConfigMapRef is the only reference - if source.ConfigMapRef == nil { - return nil, status.FailSyncReasonAllNilSubfields, fmt.Errorf("%s, NodeConfigSource was: %#v", status.FailSyncReasonAllNilSubfields, source) - } - - // validate the NodeConfigSource: + // NOTE: Even though the API server validates the config, we check whether all *known* fields are + // nil here, so that if a new API server allows a new config source type, old clients can send + // an error message rather than crashing due to a nil pointer dereference. - // at this point we know we're using the ConfigMapRef subfield - ref := source.ConfigMapRef - - // name, namespace, and UID must all be non-empty for ConfigMapRef - if ref.Name == "" || ref.Namespace == "" || string(ref.UID) == "" { - return nil, status.FailSyncReasonPartialObjectReference, fmt.Errorf("%s, ObjectReference was: %#v", status.FailSyncReasonPartialObjectReference, ref) + // Exactly one reference subfield of the config source must be non-nil. + // Currently ConfigMap is the only reference subfield. + if source.ConfigMap == nil { + return nil, status.AllNilSubfieldsError, fmt.Errorf("%s, NodeConfigSource was: %#v", status.AllNilSubfieldsError, source) } - return &remoteConfigMap{source}, "", nil } // DecodeRemoteConfigSource is a helper for using the apimachinery to decode serialized RemoteConfigSources; -// e.g. the objects stored in the .cur and .lkg files by checkpoint/store/fsstore.go +// e.g. the metadata stored by checkpoint/store/fsstore.go func DecodeRemoteConfigSource(data []byte) (RemoteConfigSource, error) { // decode the remote config source - obj, err := runtime.Decode(legacyscheme.Codecs.UniversalDecoder(), data) + _, codecs, err := scheme.NewSchemeAndCodecs() + if err != nil { + return nil, err + } + + obj, err := runtime.Decode(codecs.UniversalDecoder(), data) if err != nil { return nil, fmt.Errorf("failed to decode, error: %v", err) } - // for now we assume we are trying to load an apiv1.NodeConfigSource, + // for now we assume we are trying to load an kubeletconfigv1beta1.SerializedNodeConfigSource, // this may need to be extended if e.g. a new version of the api is born + cs, ok := obj.(*kubeletconfiginternal.SerializedNodeConfigSource) + if !ok { + return nil, fmt.Errorf("failed to cast decoded remote config source to *k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig.SerializedNodeConfigSource") + } - // convert it to the external NodeConfigSource type, so we're consistently working with the external type outside of the on-disk representation - cs := &apiv1.NodeConfigSource{} - err = legacyscheme.Scheme.Convert(obj, cs, nil) + // we use the v1.NodeConfigSource type on internal and external, so no need to convert to external here + source, _, err := NewRemoteConfigSource(&cs.Source) if err != nil { - return nil, fmt.Errorf("failed to convert decoded object into a v1 NodeConfigSource, error: %v", err) + return nil, err } - source, _, err := NewRemoteConfigSource(cs) - return source, err + + return source, nil } // EqualRemoteConfigSources is a helper for comparing remote config sources by // comparing the underlying API objects for semantic equality. func EqualRemoteConfigSources(a, b RemoteConfigSource) bool { if a != nil && b != nil { - return apiequality.Semantic.DeepEqual(a.object(), b.object()) - } - if a == nil && b == nil { - return true + return apiequality.Semantic.DeepEqual(a.NodeConfigSource(), b.NodeConfigSource()) } - return false + return a == b } // remoteConfigMap implements RemoteConfigSource for v1/ConfigMap config sources @@ -108,58 +149,125 @@ type remoteConfigMap struct { source *apiv1.NodeConfigSource } -func (r *remoteConfigMap) UID() string { - return string(r.source.ConfigMapRef.UID) +var _ RemoteConfigSource = (*remoteConfigMap)(nil) + +func (r *remoteConfigMap) KubeletFilename() string { + return r.source.ConfigMap.KubeletConfigKey } const configMapAPIPathFmt = "/api/v1/namespaces/%s/configmaps/%s" func (r *remoteConfigMap) APIPath() string { - ref := r.source.ConfigMapRef + ref := r.source.ConfigMap return fmt.Sprintf(configMapAPIPathFmt, ref.Namespace, ref.Name) } -func (r *remoteConfigMap) Download(client clientset.Interface) (Checkpoint, string, error) { - var reason string - uid := string(r.source.ConfigMapRef.UID) +func (r *remoteConfigMap) UID() string { + return string(r.source.ConfigMap.UID) +} - utillog.Infof("attempting to download ConfigMap with UID %q", uid) +func (r *remoteConfigMap) ResourceVersion() string { + return r.source.ConfigMap.ResourceVersion +} - // get the ConfigMap via namespace/name, there doesn't seem to be a way to get it by UID - cm, err := client.CoreV1().ConfigMaps(r.source.ConfigMapRef.Namespace).Get(r.source.ConfigMapRef.Name, metav1.GetOptions{}) +func (r *remoteConfigMap) Download(client clientset.Interface, store cache.Store) (Payload, string, error) { + var ( + cm *apiv1.ConfigMap + err error + ) + // check the in-memory store for the ConfigMap, so we can skip unnecessary downloads + if store != nil { + utillog.Infof("checking in-memory store for %s", r.APIPath()) + cm, err = getConfigMapFromStore(store, r.source.ConfigMap.Namespace, r.source.ConfigMap.Name) + if err != nil { + // just log the error, we'll attempt a direct download instead + utillog.Errorf("failed to check in-memory store for %s, error: %v", r.APIPath(), err) + } else if cm != nil { + utillog.Infof("found %s in in-memory store, UID: %s, ResourceVersion: %s", r.APIPath(), cm.UID, cm.ResourceVersion) + } else { + utillog.Infof("did not find %s in in-memory store", r.APIPath()) + } + } + // if we didn't find the ConfigMap in the in-memory store, download it from the API server + if cm == nil { + utillog.Infof("attempting to download %s", r.APIPath()) + cm, err = client.CoreV1().ConfigMaps(r.source.ConfigMap.Namespace).Get(r.source.ConfigMap.Name, metav1.GetOptions{}) + if err != nil { + return nil, status.DownloadError, fmt.Errorf("%s, error: %v", status.DownloadError, err) + } + utillog.Infof("successfully downloaded %s, UID: %s, ResourceVersion: %s", r.APIPath(), cm.UID, cm.ResourceVersion) + } // Assert: Now we have a non-nil ConfigMap + // construct Payload from the ConfigMap + payload, err := NewConfigMapPayload(cm) if err != nil { - reason = fmt.Sprintf(status.FailSyncReasonDownloadFmt, r.APIPath()) - return nil, reason, fmt.Errorf("%s, error: %v", reason, err) + // We only expect an error here if ObjectMeta is lacking UID or ResourceVersion. This should + // never happen on objects in the informer's store, or objects downloaded from the API server + // directly, so we report InternalError. + return nil, status.InternalError, fmt.Errorf("%s, error: %v", status.InternalError, err) } + // update internal UID and ResourceVersion based on latest ConfigMap + r.source.ConfigMap.UID = cm.UID + r.source.ConfigMap.ResourceVersion = cm.ResourceVersion + return payload, "", nil +} - // ensure that UID matches the UID on the reference, the ObjectReference must be unambiguous - if r.source.ConfigMapRef.UID != cm.UID { - reason = fmt.Sprintf(status.FailSyncReasonUIDMismatchFmt, r.source.ConfigMapRef.UID, r.APIPath(), cm.UID) - return nil, reason, fmt.Errorf(reason) - } +func (r *remoteConfigMap) Informer(client clientset.Interface, handler cache.ResourceEventHandlerFuncs) cache.SharedInformer { + // select ConfigMap by name + fieldselector := fields.OneTermEqualSelector("metadata.name", r.source.ConfigMap.Name) - checkpoint, err := NewConfigMapCheckpoint(cm) - if err != nil { - reason = fmt.Sprintf("invalid downloaded object") - return nil, reason, fmt.Errorf("%s, error: %v", reason, err) + // add some randomness to resync period, which can help avoid controllers falling into lock-step + minResyncPeriod := 15 * time.Minute + factor := rand.Float64() + 1 + resyncPeriod := time.Duration(float64(minResyncPeriod.Nanoseconds()) * factor) + + lw := &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (kuberuntime.Object, error) { + return client.CoreV1().ConfigMaps(r.source.ConfigMap.Namespace).List(metav1.ListOptions{ + FieldSelector: fieldselector.String(), + }) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + return client.CoreV1().ConfigMaps(r.source.ConfigMap.Namespace).Watch(metav1.ListOptions{ + FieldSelector: fieldselector.String(), + ResourceVersion: options.ResourceVersion, + }) + }, } - utillog.Infof("successfully downloaded ConfigMap with UID %q", uid) - return checkpoint, "", nil + informer := cache.NewSharedInformer(lw, &apiv1.ConfigMap{}, resyncPeriod) + informer.AddEventHandler(handler) + + return informer } func (r *remoteConfigMap) Encode() ([]byte, error) { - encoder, err := utilcodec.NewJSONEncoder(apiv1.GroupName) + encoder, err := utilcodec.NewKubeletconfigYAMLEncoder(kubeletconfigv1beta1.SchemeGroupVersion) if err != nil { return nil, err } - data, err := runtime.Encode(encoder, r.source) + + data, err := runtime.Encode(encoder, &kubeletconfigv1beta1.SerializedNodeConfigSource{Source: *r.source}) if err != nil { return nil, err } return data, nil } -func (r *remoteConfigMap) object() interface{} { - return r.source +func (r *remoteConfigMap) NodeConfigSource() *apiv1.NodeConfigSource { + return r.source.DeepCopy() +} + +func getConfigMapFromStore(store cache.Store, namespace, name string) (*apiv1.ConfigMap, error) { + key := fmt.Sprintf("%s/%s", namespace, name) + obj, ok, err := store.GetByKey(key) + if err != nil || !ok { + return nil, err + } + cm, ok := obj.(*apiv1.ConfigMap) + if !ok { + err := fmt.Errorf("failed to cast object %s from informer's store to ConfigMap", key) + utillog.Errorf(err.Error()) + return nil, err + } + return cm, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/download_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/download_test.go index 345319fd3..df92ee9f6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/download_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/download_test.go @@ -25,9 +25,9 @@ import ( apiv1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" + clientset "k8s.io/client-go/kubernetes" fakeclient "k8s.io/client-go/kubernetes/fake" - kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" + "k8s.io/client-go/tools/cache" utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test" ) @@ -38,118 +38,205 @@ func TestNewRemoteConfigSource(t *testing.T) { expect RemoteConfigSource err string }{ - // all NodeConfigSource subfields nil - {"all NodeConfigSource subfields nil", - &apiv1.NodeConfigSource{}, nil, "exactly one subfield must be non-nil"}, - {"ConfigMapRef: empty name, namespace, and UID", - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{}}, nil, "invalid ObjectReference"}, - // ConfigMapRef: empty name and namespace - {"ConfigMapRef: empty name and namespace", - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{UID: "uid"}}, nil, "invalid ObjectReference"}, - // ConfigMapRef: empty name and UID - {"ConfigMapRef: empty name and UID", - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Namespace: "namespace"}}, nil, "invalid ObjectReference"}, - // ConfigMapRef: empty namespace and UID - {"ConfigMapRef: empty namespace and UID", - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name"}}, nil, "invalid ObjectReference"}, - // ConfigMapRef: empty UID - {"ConfigMapRef: empty namespace and UID", - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace"}}, nil, "invalid ObjectReference"}, - // ConfigMapRef: empty namespace - {"ConfigMapRef: empty namespace and UID", - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", UID: "uid"}}, nil, "invalid ObjectReference"}, - // ConfigMapRef: empty name - {"ConfigMapRef: empty namespace and UID", - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Namespace: "namespace", UID: "uid"}}, nil, "invalid ObjectReference"}, - // ConfigMapRef: valid reference - {"ConfigMapRef: valid reference", - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}, - &remoteConfigMap{&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}}, ""}, + { + desc: "all NodeConfigSource subfields nil", + source: &apiv1.NodeConfigSource{}, + expect: nil, + err: "exactly one subfield must be non-nil", + }, + { + desc: "ConfigMap: valid reference", + source: &apiv1.NodeConfigSource{ + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + KubeletConfigKey: "kubelet", + }}, + expect: &remoteConfigMap{&apiv1.NodeConfigSource{ + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + KubeletConfigKey: "kubelet", + }}}, + err: "", + }, } for _, c := range cases { - src, _, err := NewRemoteConfigSource(c.source) - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - // underlying object should match the object passed in - if !apiequality.Semantic.DeepEqual(c.expect.object(), src.object()) { - t.Errorf("case %q, expect RemoteConfigSource %s but got %s", c.desc, spew.Sdump(c.expect), spew.Sdump(src)) - } + t.Run(c.desc, func(t *testing.T) { + source, _, err := NewRemoteConfigSource(c.source) + utiltest.ExpectError(t, err, c.err) + if err != nil { + return + } + // underlying object should match the object passed in + if !apiequality.Semantic.DeepEqual(c.expect.NodeConfigSource(), source.NodeConfigSource()) { + t.Errorf("case %q, expect RemoteConfigSource %s but got %s", c.desc, spew.Sdump(c.expect), spew.Sdump(source)) + } + }) } } func TestRemoteConfigMapUID(t *testing.T) { - cases := []string{"", "uid", "376dfb73-56db-11e7-a01e-42010a800002"} - for _, uidIn := range cases { - cpt := &remoteConfigMap{ - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: types.UID(uidIn)}}, - } - // UID method should return the correct value of the UID - uidOut := cpt.UID() - if uidIn != uidOut { - t.Errorf("expect UID() to return %q, but got %q", uidIn, uidOut) - } + const expect = "uid" + source, _, err := NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: expect, + KubeletConfigKey: "kubelet", + }}) + if err != nil { + t.Fatalf("error constructing remote config source: %v", err) + } + uid := source.UID() + if expect != uid { + t.Errorf("expect %q, but got %q", expect, uid) } } func TestRemoteConfigMapAPIPath(t *testing.T) { - name := "name" - namespace := "namespace" - cpt := &remoteConfigMap{ - &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: name, Namespace: namespace, UID: ""}}, + const ( + name = "name" + namespace = "namespace" + ) + source, _, err := NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: name, + Namespace: namespace, + UID: "uid", + KubeletConfigKey: "kubelet", + }}) + if err != nil { + t.Fatalf("error constructing remote config source: %v", err) } - expect := fmt.Sprintf(configMapAPIPathFmt, cpt.source.ConfigMapRef.Namespace, cpt.source.ConfigMapRef.Name) - // APIPath() method should return the correct path to the referenced resource - path := cpt.APIPath() + expect := fmt.Sprintf(configMapAPIPathFmt, namespace, name) + path := source.APIPath() + if expect != path { - t.Errorf("expect APIPath() to return %q, but got %q", expect, namespace) + t.Errorf("expect %q, but got %q", expect, path) } } func TestRemoteConfigMapDownload(t *testing.T) { - _, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - cm := &apiv1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: "name", - Namespace: "namespace", - UID: "uid", + Name: "name", + Namespace: "namespace", + UID: "uid", + ResourceVersion: "1", }} - client := fakeclient.NewSimpleClientset(cm) + + source := &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + KubeletConfigKey: "kubelet", + }} + + expectPayload, err := NewConfigMapPayload(cm) + if err != nil { + t.Fatalf("error constructing payload: %v", err) + } + + missingStore := cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc) + hasStore := cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc) + if err := hasStore.Add(cm); err != nil { + t.Fatalf("unexpected error constructing hasStore") + } + + missingClient := fakeclient.NewSimpleClientset() + hasClient := fakeclient.NewSimpleClientset(cm) cases := []struct { desc string - source RemoteConfigSource - expect Checkpoint + client clientset.Interface + store cache.Store err string }{ + { + desc: "nil store, object does not exist in API server", + client: missingClient, + err: "not found", + }, + { + desc: "nil store, object exists in API server", + client: hasClient, + }, + { + desc: "object exists in store and API server", + store: hasStore, + client: hasClient, + }, + { + desc: "object exists in store, but does not exist in API server", + store: hasStore, + client: missingClient, + }, + { + desc: "object does not exist in store, but exists in API server", + store: missingStore, + client: hasClient, + }, + { + desc: "object does not exist in store or API server", + client: missingClient, + store: missingStore, + err: "not found", + }, + } - // object doesn't exist - {"object doesn't exist", - &remoteConfigMap{&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "bogus", Namespace: "namespace", UID: "bogus"}}}, - nil, "not found"}, - // UID of downloaded object doesn't match UID of referent found via namespace/name - {"UID is incorrect for namespace/name", - &remoteConfigMap{&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "bogus"}}}, - nil, "does not match"}, - // successful download - {"object exists and reference is correct", - &remoteConfigMap{&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}}, - &configMapCheckpoint{kubeletCodecs, cm}, ""}, + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + // deep copy so we can always check the UID/ResourceVersion are set after Download + s, _, err := NewRemoteConfigSource(source.DeepCopy()) + if err != nil { + t.Fatalf("error constructing remote config source %v", err) + } + // attempt download + p, _, err := s.Download(c.client, c.store) + utiltest.ExpectError(t, err, c.err) + if err != nil { + return + } + // downloaded object should match the expected + if !apiequality.Semantic.DeepEqual(expectPayload.object(), p.object()) { + t.Errorf("expect Checkpoint %s but got %s", spew.Sdump(expectPayload), spew.Sdump(p)) + } + // source UID and ResourceVersion should be updated by Download + if p.UID() != s.UID() { + t.Errorf("expect UID to be updated by Download to match payload: %s, but got source UID: %s", p.UID(), s.UID()) + } + if p.ResourceVersion() != s.ResourceVersion() { + t.Errorf("expect ResourceVersion to be updated by Download to match payload: %s, but got source ResourceVersion: %s", p.ResourceVersion(), s.ResourceVersion()) + } + }) + } +} + +func TestEqualRemoteConfigSources(t *testing.T) { + cases := []struct { + desc string + a RemoteConfigSource + b RemoteConfigSource + expect bool + }{ + {"both nil", nil, nil, true}, + {"a nil", nil, &remoteConfigMap{}, false}, + {"b nil", &remoteConfigMap{}, nil, false}, + {"neither nil, equal", &remoteConfigMap{}, &remoteConfigMap{}, true}, + { + desc: "neither nil, not equal", + a: &remoteConfigMap{&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{Name: "a"}}}, + b: &remoteConfigMap{&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{KubeletConfigKey: "kubelet"}}}, + expect: false, + }, } for _, c := range cases { - cpt, _, err := c.source.Download(client) - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - // "downloaded" object should match the expected - if !apiequality.Semantic.DeepEqual(c.expect.object(), cpt.object()) { - t.Errorf("case %q, expect Checkpoint %s but got %s", c.desc, spew.Sdump(c.expect), spew.Sdump(cpt)) - } + t.Run(c.desc, func(t *testing.T) { + if EqualRemoteConfigSources(c.a, c.b) != c.expect { + t.Errorf("expected EqualRemoteConfigSources to return %t, but got %t", c.expect, !c.expect) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/BUILD index 035a9641d..76f46e824 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/BUILD @@ -14,7 +14,11 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", "//pkg/kubelet/kubeletconfig/checkpoint:go_default_library", + "//pkg/kubelet/kubeletconfig/util/codec:go_default_library", "//pkg/kubelet/kubeletconfig/util/files:go_default_library", "//pkg/kubelet/kubeletconfig/util/test:go_default_library", "//pkg/util/filesystem:go_default_library", @@ -34,7 +38,9 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store", deps = [ + "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/kubeletconfig/checkpoint:go_default_library", + "//pkg/kubelet/kubeletconfig/configfiles:go_default_library", "//pkg/kubelet/kubeletconfig/util/files:go_default_library", "//pkg/kubelet/kubeletconfig/util/log:go_default_library", "//pkg/util/filesystem:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fakestore.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fakestore.go index cb5d2491b..cd72c827a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fakestore.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fakestore.go @@ -20,52 +20,51 @@ import ( "fmt" "time" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint" ) -// so far only implements Current(), LastKnownGood(), SetCurrent(), and SetLastKnownGood() +// so far only implements Assigned(), LastKnownGood(), SetAssigned(), and SetLastKnownGood() type fakeStore struct { - current checkpoint.RemoteConfigSource + assigned checkpoint.RemoteConfigSource lastKnownGood checkpoint.RemoteConfigSource } +var _ Store = (*fakeStore)(nil) + func (s *fakeStore) Initialize() error { return fmt.Errorf("Initialize method not supported") } -func (s *fakeStore) Exists(uid string) (bool, error) { +func (s *fakeStore) Exists(source checkpoint.RemoteConfigSource) (bool, error) { return false, fmt.Errorf("Exists method not supported") } -func (s *fakeStore) Save(c checkpoint.Checkpoint) error { +func (s *fakeStore) Save(c checkpoint.Payload) error { return fmt.Errorf("Save method not supported") } -func (s *fakeStore) Load(uid string) (checkpoint.Checkpoint, error) { +func (s *fakeStore) Load(source checkpoint.RemoteConfigSource) (*kubeletconfig.KubeletConfiguration, error) { return nil, fmt.Errorf("Load method not supported") } -func (s *fakeStore) CurrentModified() (time.Time, error) { - return time.Time{}, fmt.Errorf("CurrentModified method not supported") +func (s *fakeStore) AssignedModified() (time.Time, error) { + return time.Time{}, fmt.Errorf("AssignedModified method not supported") } -func (s *fakeStore) Current() (checkpoint.RemoteConfigSource, error) { - return s.current, nil +func (s *fakeStore) Assigned() (checkpoint.RemoteConfigSource, error) { + return s.assigned, nil } func (s *fakeStore) LastKnownGood() (checkpoint.RemoteConfigSource, error) { return s.lastKnownGood, nil } -func (s *fakeStore) SetCurrent(source checkpoint.RemoteConfigSource) error { - s.current = source +func (s *fakeStore) SetAssigned(source checkpoint.RemoteConfigSource) error { + s.assigned = source return nil } -func (s *fakeStore) SetCurrentUpdated(source checkpoint.RemoteConfigSource) (bool, error) { - return setCurrentUpdated(s, source) -} - func (s *fakeStore) SetLastKnownGood(source checkpoint.RemoteConfigSource) error { s.lastKnownGood = source return nil diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore.go index 1026b97a8..94cd42fea 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore.go @@ -21,82 +21,112 @@ import ( "path/filepath" "time" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint" + "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/configfiles" utilfiles "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files" utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log" utilfs "k8s.io/kubernetes/pkg/util/filesystem" ) const ( - curFile = ".cur" - lkgFile = ".lkg" + metaDir = "meta" + assignedFile = "assigned" + lastKnownGoodFile = "last-known-good" + + checkpointsDir = "checkpoints" ) // fsStore is for tracking checkpoints in the local filesystem, implements Store type fsStore struct { // fs is the filesystem to use for storage operations; can be mocked for testing fs utilfs.Filesystem - // checkpointsDir is the absolute path to the storage directory for fsStore - checkpointsDir string + // dir is the absolute path to the storage directory for fsStore + dir string } -// NewFsStore returns a Store that saves its data in `checkpointsDir` -func NewFsStore(fs utilfs.Filesystem, checkpointsDir string) Store { +var _ Store = (*fsStore)(nil) + +// NewFsStore returns a Store that saves its data in dir +func NewFsStore(fs utilfs.Filesystem, dir string) Store { return &fsStore{ - fs: fs, - checkpointsDir: checkpointsDir, + fs: fs, + dir: dir, } } func (s *fsStore) Initialize() error { - utillog.Infof("initializing config checkpoints directory %q", s.checkpointsDir) - if err := utilfiles.EnsureDir(s.fs, s.checkpointsDir); err != nil { + utillog.Infof("initializing config checkpoints directory %q", s.dir) + // ensure top-level dir for store + if err := utilfiles.EnsureDir(s.fs, s.dir); err != nil { + return err + } + // ensure metadata directory and reference files (tracks assigned and lkg configs) + if err := utilfiles.EnsureDir(s.fs, filepath.Join(s.dir, metaDir)); err != nil { + return err + } + if err := utilfiles.EnsureFile(s.fs, s.metaPath(assignedFile)); err != nil { return err } - if err := utilfiles.EnsureFile(s.fs, filepath.Join(s.checkpointsDir, curFile)); err != nil { + if err := utilfiles.EnsureFile(s.fs, s.metaPath(lastKnownGoodFile)); err != nil { return err } - return utilfiles.EnsureFile(s.fs, filepath.Join(s.checkpointsDir, lkgFile)) + // ensure checkpoints directory (saves unpacked payloads in subdirectories named after payload UID) + return utilfiles.EnsureDir(s.fs, filepath.Join(s.dir, checkpointsDir)) } -func (s *fsStore) Exists(uid string) (bool, error) { - ok, err := utilfiles.FileExists(s.fs, filepath.Join(s.checkpointsDir, uid)) +func (s *fsStore) Exists(source checkpoint.RemoteConfigSource) (bool, error) { + const errfmt = "failed to determine whether checkpoint exists for source %s, UID: %s, ResourceVersion: %s exists, error: %v" + if len(source.UID()) == 0 { + return false, fmt.Errorf(errfmt, source.APIPath(), source.UID(), source.ResourceVersion(), "empty UID is ambiguous") + } + if len(source.ResourceVersion()) == 0 { + return false, fmt.Errorf(errfmt, source.APIPath(), source.UID(), source.ResourceVersion(), "empty ResourceVersion is ambiguous") + } + + // we check whether the directory was created for the resource + ok, err := utilfiles.DirExists(s.fs, s.checkpointPath(source.UID(), source.ResourceVersion())) if err != nil { - return false, fmt.Errorf("failed to determine whether checkpoint %q exists, error: %v", uid, err) + return false, fmt.Errorf(errfmt, source.APIPath(), source.UID(), source.ResourceVersion(), err) } return ok, nil } -func (s *fsStore) Save(c checkpoint.Checkpoint) error { - // encode the checkpoint - data, err := c.Encode() - if err != nil { +func (s *fsStore) Save(payload checkpoint.Payload) error { + // Note: Payload interface guarantees UID() and ResourceVersion() to be non-empty + path := s.checkpointPath(payload.UID(), payload.ResourceVersion()) + // ensure the parent dir (checkpoints/uid) exists, since ReplaceDir requires the parent of the replacee + // to exist, and we checkpoint as checkpoints/uid/resourceVersion/files-from-configmap + if err := utilfiles.EnsureDir(s.fs, filepath.Dir(path)); err != nil { return err } - // save the file - return utilfiles.ReplaceFile(s.fs, filepath.Join(s.checkpointsDir, c.UID()), data) + // save the checkpoint's files in the appropriate checkpoint dir + return utilfiles.ReplaceDir(s.fs, path, payload.Files()) } -func (s *fsStore) Load(uid string) (checkpoint.Checkpoint, error) { - filePath := filepath.Join(s.checkpointsDir, uid) - utillog.Infof("loading configuration from %q", filePath) - - // load the file - data, err := s.fs.ReadFile(filePath) +func (s *fsStore) Load(source checkpoint.RemoteConfigSource) (*kubeletconfig.KubeletConfiguration, error) { + sourceFmt := fmt.Sprintf("%s, UID: %s, ResourceVersion: %s", source.APIPath(), source.UID(), source.ResourceVersion()) + // check if a checkpoint exists for the source + if ok, err := s.Exists(source); err != nil { + return nil, err + } else if !ok { + return nil, fmt.Errorf("no checkpoint for source %s", sourceFmt) + } + // load the kubelet config file + utillog.Infof("loading Kubelet configuration checkpoint for source %s", sourceFmt) + loader, err := configfiles.NewFsLoader(s.fs, filepath.Join(s.checkpointPath(source.UID(), source.ResourceVersion()), source.KubeletFilename())) if err != nil { - return nil, fmt.Errorf("failed to read checkpoint file %q, error: %v", filePath, err) + return nil, err } - - // decode it - c, err := checkpoint.DecodeCheckpoint(data) + kc, err := loader.Load() if err != nil { - return nil, fmt.Errorf("failed to decode checkpoint file %q, error: %v", filePath, err) + return nil, err } - return c, nil + return kc, nil } -func (s *fsStore) CurrentModified() (time.Time, error) { - path := filepath.Join(s.checkpointsDir, curFile) +func (s *fsStore) AssignedModified() (time.Time, error) { + path := s.metaPath(assignedFile) info, err := s.fs.Stat(path) if err != nil { return time.Time{}, fmt.Errorf("failed to stat %q while checking modification time, error: %v", path, err) @@ -104,35 +134,36 @@ func (s *fsStore) CurrentModified() (time.Time, error) { return info.ModTime(), nil } -func (s *fsStore) Current() (checkpoint.RemoteConfigSource, error) { - return s.sourceFromFile(curFile) +func (s *fsStore) Assigned() (checkpoint.RemoteConfigSource, error) { + return readRemoteConfigSource(s.fs, s.metaPath(assignedFile)) } func (s *fsStore) LastKnownGood() (checkpoint.RemoteConfigSource, error) { - return s.sourceFromFile(lkgFile) -} - -func (s *fsStore) SetCurrent(source checkpoint.RemoteConfigSource) error { - return s.setSourceFile(curFile, source) + return readRemoteConfigSource(s.fs, s.metaPath(lastKnownGoodFile)) } -func (s *fsStore) SetCurrentUpdated(source checkpoint.RemoteConfigSource) (bool, error) { - return setCurrentUpdated(s, source) +func (s *fsStore) SetAssigned(source checkpoint.RemoteConfigSource) error { + return writeRemoteConfigSource(s.fs, s.metaPath(assignedFile), source) } func (s *fsStore) SetLastKnownGood(source checkpoint.RemoteConfigSource) error { - return s.setSourceFile(lkgFile, source) + return writeRemoteConfigSource(s.fs, s.metaPath(lastKnownGoodFile), source) } func (s *fsStore) Reset() (bool, error) { return reset(s) } -// sourceFromFile returns the RemoteConfigSource stored in the file at `s.checkpointsDir/relPath`, -// or nil if the file is empty -func (s *fsStore) sourceFromFile(relPath string) (checkpoint.RemoteConfigSource, error) { - path := filepath.Join(s.checkpointsDir, relPath) - data, err := s.fs.ReadFile(path) +func (s *fsStore) checkpointPath(uid, resourceVersion string) string { + return filepath.Join(s.dir, checkpointsDir, uid, resourceVersion) +} + +func (s *fsStore) metaPath(name string) string { + return filepath.Join(s.dir, metaDir, name) +} + +func readRemoteConfigSource(fs utilfs.Filesystem, path string) (checkpoint.RemoteConfigSource, error) { + data, err := fs.ReadFile(path) if err != nil { return nil, err } else if len(data) == 0 { @@ -141,17 +172,23 @@ func (s *fsStore) sourceFromFile(relPath string) (checkpoint.RemoteConfigSource, return checkpoint.DecodeRemoteConfigSource(data) } -// set source file replaces the file at `s.checkpointsDir/relPath` with a file containing `source` -func (s *fsStore) setSourceFile(relPath string, source checkpoint.RemoteConfigSource) error { - path := filepath.Join(s.checkpointsDir, relPath) +func writeRemoteConfigSource(fs utilfs.Filesystem, path string, source checkpoint.RemoteConfigSource) error { // if nil, reset the file if source == nil { - return utilfiles.ReplaceFile(s.fs, path, []byte{}) + return utilfiles.ReplaceFile(fs, path, []byte{}) + } + // check that UID and ResourceVersion are non-empty, + // error to save reference if the checkpoint can't be fully resolved + if source.UID() == "" { + return fmt.Errorf("failed to write RemoteConfigSource, empty UID is ambiguous") + } + if source.ResourceVersion() == "" { + return fmt.Errorf("failed to write RemoteConfigSource, empty ResourceVersion is ambiguous") } // encode the source and save it to the file data, err := source.Encode() if err != nil { return err } - return utilfiles.ReplaceFile(s.fs, path, data) + return utilfiles.ReplaceFile(fs, path, data) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore_test.go index 939ffb2ad..27414a10d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore_test.go @@ -18,7 +18,9 @@ package store import ( "fmt" + "io/ioutil" "path/filepath" + "reflect" "testing" "time" @@ -27,17 +29,37 @@ import ( apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint" + utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec" utilfiles "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files" utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test" utilfs "k8s.io/kubernetes/pkg/util/filesystem" ) -const testCheckpointsDir = "/test-checkpoints-dir" +var testdir string + +func init() { + tmp, err := ioutil.TempDir("", "fsstore-test") + if err != nil { + panic(err) + } + testdir = tmp +} func newInitializedFakeFsStore() (*fsStore, error) { - fs := utilfs.NewFakeFs() - store := NewFsStore(fs, testCheckpointsDir) + // Test with the default filesystem, the fake filesystem has an issue caused by afero: https://github.com/spf13/afero/issues/141 + // The default filesystem also behaves more like production, so we should probably not mock the filesystem for unit tests. + fs := utilfs.DefaultFs{} + + tmpdir, err := fs.TempDir(testdir, "store-") + if err != nil { + return nil, err + } + + store := NewFsStore(fs, tmpdir) if err := store.Initialize(); err != nil { return nil, err } @@ -50,190 +72,264 @@ func TestFsStoreInitialize(t *testing.T) { t.Fatalf("fsStore.Initialize() failed with error: %v", err) } - // check that testCheckpointsDir exists - _, err = store.fs.Stat(testCheckpointsDir) - if err != nil { - t.Fatalf("expect %q to exist, but stat failed with error: %v", testCheckpointsDir, err) + // check that store.dir exists + if _, err := store.fs.Stat(store.dir); err != nil { + t.Fatalf("expect %q to exist, but stat failed with error: %v", store.dir, err) } - // check that testCheckpointsDir contains the curFile - curPath := filepath.Join(testCheckpointsDir, curFile) - _, err = store.fs.Stat(curPath) - if err != nil { - t.Fatalf("expect %q to exist, but stat failed with error: %v", curPath, err) + // check that meta dir exists + if _, err := store.fs.Stat(store.metaPath("")); err != nil { + t.Fatalf("expect %q to exist, but stat failed with error: %v", store.metaPath(""), err) } - // check that testCheckpointsDir contains the lkgFile - lkgPath := filepath.Join(testCheckpointsDir, lkgFile) - _, err = store.fs.Stat(lkgPath) - if err != nil { - t.Fatalf("expect %q to exist, but stat failed with error: %v", lkgPath, err) + // check that checkpoints dir exists + if _, err := store.fs.Stat(filepath.Join(store.dir, checkpointsDir)); err != nil { + t.Fatalf("expect %q to exist, but stat failed with error: %v", filepath.Join(store.dir, checkpointsDir), err) + } + + // check that assignedFile exists + if _, err := store.fs.Stat(store.metaPath(assignedFile)); err != nil { + t.Fatalf("expect %q to exist, but stat failed with error: %v", store.metaPath(assignedFile), err) + } + + // check that lastKnownGoodFile exists + if _, err := store.fs.Stat(store.metaPath(lastKnownGoodFile)); err != nil { + t.Fatalf("expect %q to exist, but stat failed with error: %v", store.metaPath(lastKnownGoodFile), err) } } func TestFsStoreExists(t *testing.T) { store, err := newInitializedFakeFsStore() if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) + t.Fatalf("error constructing store: %v", err) } - // create a checkpoint file; this is enough for an exists check - cpt, err := checkpoint.NewConfigMapCheckpoint(&apiv1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{UID: "uid"}, - }) + // checkpoint a payload + const ( + uid = "uid" + resourceVersion = "1" + ) + p, err := checkpoint.NewConfigMapPayload(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: uid, ResourceVersion: resourceVersion}}) if err != nil { - t.Fatalf("could not construct checkpoint, error: %v", err) + t.Fatalf("could not construct Payload, error: %v", err) + } + if err := store.Save(p); err != nil { + t.Fatalf("unexpected error: %v", err) } - saveTestCheckpointFile(t, store.fs, cpt) cases := []struct { - desc string - uid string // the uid to test - expect bool - err string + desc string + uid types.UID + resourceVersion string + expect bool + err string }{ - {"exists", "uid", true, ""}, - {"does not exist", "bogus-uid", false, ""}, + {"exists", uid, resourceVersion, true, ""}, + {"does not exist", "bogus-uid", "bogus-resourceVersion", false, ""}, + {"ambiguous UID", "", "bogus-resourceVersion", false, "empty UID is ambiguous"}, + {"ambiguous ResourceVersion", "bogus-uid", "", false, "empty ResourceVersion is ambiguous"}, } for _, c := range cases { - ok, err := store.Exists(c.uid) - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - if c.expect != ok { - t.Errorf("case %q, expect %t but got %t", c.desc, c.expect, ok) - } + t.Run(c.desc, func(t *testing.T) { + source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: c.uid, + ResourceVersion: c.resourceVersion, + KubeletConfigKey: "kubelet", + }}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + ok, err := store.Exists(source) + utiltest.ExpectError(t, err, c.err) + if err != nil { + return + } + if c.expect != ok { + t.Errorf("expect %t but got %t", c.expect, ok) + } + }) } } func TestFsStoreSave(t *testing.T) { store, err := newInitializedFakeFsStore() if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) + t.Fatalf("error constructing store: %v", err) } - cpt, err := checkpoint.NewConfigMapCheckpoint(&apiv1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{UID: "uid"}, - }) - if err != nil { - t.Fatalf("could not construct checkpoint, error: %v", err) - } + nameTooLong := func() string { + s := "" + for i := 0; i < 256; i++ { + s += "a" + } + return s + }() - // save the checkpoint - err = store.Save(cpt) - if err != nil { - t.Fatalf("unable to save checkpoint, error: %v", err) - } + const ( + uid = "uid" + resourceVersion = "1" + ) - // expect the saved checkpoint file to match the encoding of the checkpoint - data, err := cpt.Encode() - if err != nil { - t.Fatalf("unable to encode the checkpoint, error: %v", err) + cases := []struct { + desc string + uid types.UID + resourceVersion string + files map[string]string + err string + }{ + {"valid payload", uid, resourceVersion, map[string]string{"foo": "foocontent", "bar": "barcontent"}, ""}, + {"empty key name", uid, resourceVersion, map[string]string{"": "foocontent"}, "must not be empty"}, + {"key name is not a base file name (foo/bar)", uid, resourceVersion, map[string]string{"foo/bar": "foocontent"}, "only base names are allowed"}, + {"key name is not a base file name (/foo)", uid, resourceVersion, map[string]string{"/bar": "foocontent"}, "only base names are allowed"}, + {"used .", uid, resourceVersion, map[string]string{".": "foocontent"}, "may not be '.' or '..'"}, + {"used ..", uid, resourceVersion, map[string]string{"..": "foocontent"}, "may not be '.' or '..'"}, + {"length violation", uid, resourceVersion, map[string]string{nameTooLong: "foocontent"}, "must be less than 255 characters"}, } - expect := string(data) - - data = readTestCheckpointFile(t, store.fs, cpt.UID()) - cptFile := string(data) - if expect != cptFile { - t.Errorf("expect %q but got %q", expect, cptFile) + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + // construct the payload + p, err := checkpoint.NewConfigMapPayload(&apiv1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{UID: c.uid, ResourceVersion: c.resourceVersion}, + Data: c.files, + }) + // if no error, save the payload, otherwise skip straight to error handler + if err == nil { + err = store.Save(p) + } + utiltest.ExpectError(t, err, c.err) + if err != nil { + return + } + // read the saved checkpoint + m, err := mapFromCheckpoint(store, p.UID(), p.ResourceVersion()) + if err != nil { + t.Fatalf("error loading checkpoint to map: %v", err) + } + // compare our expectation to what got saved + expect := p.Files() + if !reflect.DeepEqual(expect, m) { + t.Errorf("expect %v, but got %v", expect, m) + } + }) } } func TestFsStoreLoad(t *testing.T) { store, err := newInitializedFakeFsStore() if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) + t.Fatalf("error constructing store: %v", err) } - - const uid = "uid" - cpt, err := checkpoint.NewConfigMapCheckpoint(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: types.UID(uid)}}) + // encode a kubelet configuration that has all defaults set + expect, err := newKubeletConfiguration() if err != nil { - t.Fatalf("unable to construct checkpoint, error: %v", err) - } - - cases := []struct { - desc string - loadUID string - cpt checkpoint.Checkpoint - err string - }{ - {"checkpoint exists", uid, cpt, ""}, - {"checkpoint does not exist", "bogus-uid", nil, "failed to read"}, + t.Fatalf("error constructing KubeletConfiguration: %v", err) } - for _, c := range cases { - if c.cpt != nil { - saveTestCheckpointFile(t, store.fs, c.cpt) - } - cpt, err := store.Load(c.loadUID) - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - if !checkpoint.EqualCheckpoints(c.cpt, cpt) { - t.Errorf("case %q, expect %q but got %q", c.desc, spew.Sdump(c.cpt), spew.Sdump(cpt)) - } - } -} - -func TestFsStoreRoundTrip(t *testing.T) { - store, err := newInitializedFakeFsStore() + data, err := utilcodec.EncodeKubeletConfig(expect, v1beta1.SchemeGroupVersion) if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) + t.Fatalf("error encoding KubeletConfiguration: %v", err) } - const uid = "uid" - cpt, err := checkpoint.NewConfigMapCheckpoint(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: types.UID(uid)}}) + // construct a payload that contains the kubeletconfig + const ( + uid = "uid" + resourceVersion = "1" + kubeletKey = "kubelet" + ) + p, err := checkpoint.NewConfigMapPayload(&apiv1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{UID: types.UID(uid), ResourceVersion: resourceVersion}, + Data: map[string]string{ + kubeletKey: string(data), + }, + }) if err != nil { - t.Fatalf("unable to construct checkpoint, error: %v", err) + t.Fatalf("error constructing payload: %v", err) } - err = store.Save(cpt) + // save the payload + err = store.Save(p) if err != nil { - t.Fatalf("unable to save checkpoint, error: %v", err) + t.Fatalf("error saving payload: %v", err) } - cptAfter, err := store.Load(uid) - if err != nil { - t.Fatalf("unable to load checkpoint, error: %v", err) + + cases := []struct { + desc string + uid types.UID + resourceVersion string + err string + }{ + {"checkpoint exists", uid, resourceVersion, ""}, + {"checkpoint does not exist", "bogus-uid", "bogus-resourceVersion", "no checkpoint for source"}, + {"ambiguous UID", "", "bogus-resourceVersion", "empty UID is ambiguous"}, + {"ambiguous ResourceVersion", "bogus-uid", "", "empty ResourceVersion is ambiguous"}, } - if !checkpoint.EqualCheckpoints(cpt, cptAfter) { - t.Errorf("expect %q but got %q", spew.Sdump(cpt), spew.Sdump(cptAfter)) + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: c.uid, + ResourceVersion: c.resourceVersion, + KubeletConfigKey: kubeletKey, + }}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + loaded, err := store.Load(source) + utiltest.ExpectError(t, err, c.err) + if err != nil { + return + } + if !reflect.DeepEqual(expect, loaded) { + t.Errorf("expect %#v, but got %#v", expect, loaded) + } + }) } } -func TestFsStoreCurrentModified(t *testing.T) { +func TestFsStoreAssignedModified(t *testing.T) { store, err := newInitializedFakeFsStore() if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) + t.Fatalf("error constructing store: %v", err) } - // create an empty current file, this is good enough for testing - saveTestSourceFile(t, store.fs, curFile, nil) + // create an empty assigned file, this is good enough for testing + saveTestSourceFile(t, store, assignedFile, nil) - // set the timestamps to the current time, so we can compare to result of store.SetCurrentModified + // set the timestamps to the current time, so we can compare to result of store.AssignedModified now := time.Now() - err = store.fs.Chtimes(filepath.Join(testCheckpointsDir, curFile), now, now) + err = store.fs.Chtimes(store.metaPath(assignedFile), now, now) if err != nil { t.Fatalf("could not change timestamps, error: %v", err) } // for now we hope that the system won't truncate the time to a less precise unit, // if this test fails on certain systems that may be the reason. - modTime, err := store.CurrentModified() + modTime, err := store.AssignedModified() if err != nil { - t.Fatalf("unable to determine modification time of current config source, error: %v", err) + t.Fatalf("unable to determine modification time of assigned config source, error: %v", err) } if !now.Equal(modTime) { t.Errorf("expect %q but got %q", now.Format(time.RFC3339), modTime.Format(time.RFC3339)) } } -func TestFsStoreCurrent(t *testing.T) { +func TestFsStoreAssigned(t *testing.T) { store, err := newInitializedFakeFsStore() if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) + t.Fatalf("error constructing store: %v", err) } source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ - ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}) + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + KubeletConfigKey: "kubelet", + }}) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -247,28 +343,36 @@ func TestFsStoreCurrent(t *testing.T) { {"non-default source", source, ""}, } for _, c := range cases { - // save the last known good source - saveTestSourceFile(t, store.fs, curFile, c.expect) + t.Run(c.desc, func(t *testing.T) { + // save the last known good source + saveTestSourceFile(t, store, assignedFile, c.expect) - // load last-known-good and compare to expected result - source, err := store.Current() - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - if !checkpoint.EqualRemoteConfigSources(c.expect, source) { - t.Errorf("case %q, expect %q but got %q", spew.Sdump(c.expect), spew.Sdump(c.expect), spew.Sdump(source)) - } + // load last-known-good and compare to expected result + source, err := store.Assigned() + utiltest.ExpectError(t, err, c.err) + if err != nil { + return + } + if !checkpoint.EqualRemoteConfigSources(c.expect, source) { + t.Errorf("case %q, expect %q but got %q", spew.Sdump(c.expect), spew.Sdump(c.expect), spew.Sdump(source)) + } + }) } } func TestFsStoreLastKnownGood(t *testing.T) { store, err := newInitializedFakeFsStore() if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) + t.Fatalf("error constructing store: %v", err) } source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ - ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}) + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + KubeletConfigKey: "kubelet", + }}) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -282,166 +386,216 @@ func TestFsStoreLastKnownGood(t *testing.T) { {"non-default source", source, ""}, } for _, c := range cases { - // save the last known good source - saveTestSourceFile(t, store.fs, lkgFile, c.expect) + t.Run(c.desc, func(t *testing.T) { + // save the last known good source + saveTestSourceFile(t, store, lastKnownGoodFile, c.expect) - // load last-known-good and compare to expected result - source, err := store.LastKnownGood() - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - if !checkpoint.EqualRemoteConfigSources(c.expect, source) { - t.Errorf("case %q, expect %q but got %q", spew.Sdump(c.expect), spew.Sdump(c.expect), spew.Sdump(source)) - } - } -} - -func TestFsStoreSetCurrent(t *testing.T) { - store, err := newInitializedFakeFsStore() - if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) - } - - const uid = "uid" - expect := fmt.Sprintf(`{"kind":"NodeConfigSource","apiVersion":"v1","configMapRef":{"namespace":"namespace","name":"name","uid":"%s"}}%s`, uid, "\n") - source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - Name: "name", Namespace: "namespace", UID: types.UID(uid)}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // save the current source - if err := store.SetCurrent(source); err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // check that the source saved as we would expect - data := readTestSourceFile(t, store.fs, curFile) - if expect != string(data) { - t.Errorf("expect current source file to contain %q, but got %q", expect, string(data)) + // load last-known-good and compare to expected result + source, err := store.LastKnownGood() + utiltest.ExpectError(t, err, c.err) + if err != nil { + return + } + if !checkpoint.EqualRemoteConfigSources(c.expect, source) { + t.Errorf("case %q, expect %q but got %q", spew.Sdump(c.expect), spew.Sdump(c.expect), spew.Sdump(source)) + } + }) } } -func TestFsStoreSetCurrentUpdated(t *testing.T) { +func TestFsStoreSetAssigned(t *testing.T) { store, err := newInitializedFakeFsStore() if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) + t.Fatalf("error constructing store: %v", err) } cases := []struct { - current string - newCurrent string - expectUpdated bool - err string + desc string + source *apiv1.NodeConfigSource + expect string + err string }{ - {"", "", false, ""}, - {"uid", "", true, ""}, - {"", "uid", true, ""}, - {"uid", "uid", false, ""}, - {"uid", "other-uid", true, ""}, - {"other-uid", "uid", true, ""}, - {"other-uid", "other-uid", false, ""}, + { + desc: "nil source", + expect: "", // empty file + }, + { + desc: "non-nil source", + source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + ResourceVersion: "1", + KubeletConfigKey: "kubelet", + }}, + expect: `apiVersion: kubelet.config.k8s.io/v1beta1 +kind: SerializedNodeConfigSource +source: + configMap: + kubeletConfigKey: kubelet + name: name + namespace: namespace + resourceVersion: "1" + uid: uid +`, + }, + { + desc: "missing UID", + source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + ResourceVersion: "1", + KubeletConfigKey: "kubelet", + }}, + err: "failed to write RemoteConfigSource, empty UID is ambiguous", + }, + { + desc: "missing ResourceVersion", + source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + KubeletConfigKey: "kubelet", + }}, + err: "failed to write RemoteConfigSource, empty ResourceVersion is ambiguous", + }, } for _, c := range cases { - // construct current source - var source checkpoint.RemoteConfigSource - expectSource := "" - if len(c.current) > 0 { - expectSource = fmt.Sprintf(`{"kind":"NodeConfigSource","apiVersion":"v1","configMapRef":{"namespace":"namespace","name":"name","uid":"%s"}}%s`, c.current, "\n") - source, _, err = checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - Name: "name", Namespace: "namespace", UID: types.UID(c.current)}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Run(c.desc, func(t *testing.T) { + var source checkpoint.RemoteConfigSource + if c.source != nil { + s, _, err := checkpoint.NewRemoteConfigSource(c.source) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + source = s } - } - - // construct new source - var newSource checkpoint.RemoteConfigSource - expectNewSource := "" - if len(c.newCurrent) > 0 { - expectNewSource = fmt.Sprintf(`{"kind":"NodeConfigSource","apiVersion":"v1","configMapRef":{"namespace":"namespace","name":"new-name","uid":"%s"}}%s`, c.newCurrent, "\n") - newSource, _, err = checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - Name: "new-name", Namespace: "namespace", UID: types.UID(c.newCurrent)}}) + // save the assigned source + err = store.SetAssigned(source) + utiltest.ExpectError(t, err, c.err) if err != nil { - t.Fatalf("unexpected error: %v", err) + return } - } - - // set the initial current - if err := store.SetCurrent(source); err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // update to the new current - updated, err := store.SetCurrentUpdated(newSource) - if utiltest.SkipRest(t, fmt.Sprintf("%q -> %q", c.current, c.newCurrent), err, c.err) { - continue - } - - // check that SetCurrentUpdated correctly reports whether the current checkpoint changed - if c.expectUpdated != updated { - t.Errorf("case %q -> %q, expect %v but got %v", c.current, c.newCurrent, c.expectUpdated, updated) - } - - // check that curFile is saved by SetCurrentUpdated as we expect - data := readTestSourceFile(t, store.fs, curFile) - if c.current == c.newCurrent { - // same UID should leave file unchanged - if expectSource != string(data) { - t.Errorf("case %q -> %q, expect current source file to contain %q, but got %q", c.current, c.newCurrent, expectSource, string(data)) + // check that the source saved as we would expect + data := readTestSourceFile(t, store, assignedFile) + if c.expect != string(data) { + t.Errorf("expect assigned source file to contain %q, but got %q", c.expect, string(data)) } - } else if expectNewSource != string(data) { - // otherwise expect the file to change - t.Errorf("case %q -> %q, expect current source file to contain %q, but got %q", c.current, c.newCurrent, expectNewSource, string(data)) - } + }) } - } func TestFsStoreSetLastKnownGood(t *testing.T) { store, err := newInitializedFakeFsStore() if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) - } - - const uid = "uid" - expect := fmt.Sprintf(`{"kind":"NodeConfigSource","apiVersion":"v1","configMapRef":{"namespace":"namespace","name":"name","uid":"%s"}}%s`, uid, "\n") - source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - Name: "name", Namespace: "namespace", UID: types.UID(uid)}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatalf("error constructing store: %v", err) } - // save the last known good source - if err := store.SetLastKnownGood(source); err != nil { - t.Fatalf("unexpected error: %v", err) + cases := []struct { + desc string + source *apiv1.NodeConfigSource + expect string + err string + }{ + { + desc: "nil source", + expect: "", // empty file + }, + { + desc: "non-nil source", + source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + ResourceVersion: "1", + KubeletConfigKey: "kubelet", + }}, + expect: `apiVersion: kubelet.config.k8s.io/v1beta1 +kind: SerializedNodeConfigSource +source: + configMap: + kubeletConfigKey: kubelet + name: name + namespace: namespace + resourceVersion: "1" + uid: uid +`, + }, + { + desc: "missing UID", + source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + ResourceVersion: "1", + KubeletConfigKey: "kubelet", + }}, + err: "failed to write RemoteConfigSource, empty UID is ambiguous", + }, + { + desc: "missing ResourceVersion", + source: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + KubeletConfigKey: "kubelet", + }}, + err: "failed to write RemoteConfigSource, empty ResourceVersion is ambiguous", + }, } - // check that the source saved as we would expect - data := readTestSourceFile(t, store.fs, lkgFile) - if expect != string(data) { - t.Errorf("expect last-known-good source file to contain %q, but got %q", expect, string(data)) + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + var source checkpoint.RemoteConfigSource + if c.source != nil { + s, _, err := checkpoint.NewRemoteConfigSource(c.source) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + source = s + } + // save the assigned source + err = store.SetLastKnownGood(source) + utiltest.ExpectError(t, err, c.err) + if err != nil { + return + } + // check that the source saved as we would expect + data := readTestSourceFile(t, store, lastKnownGoodFile) + if c.expect != string(data) { + t.Errorf("expect assigned source file to contain %q, but got %q", c.expect, string(data)) + } + }) } } func TestFsStoreReset(t *testing.T) { store, err := newInitializedFakeFsStore() if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) + t.Fatalf("error constructing store: %v", err) } - source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}) + source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + KubeletConfigKey: "kubelet", + }}) if err != nil { t.Fatalf("unexpected error: %v", err) } - otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "other-name", Namespace: "namespace", UID: "other-uid"}}) + otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "other-name", + Namespace: "namespace", + UID: "other-uid", + KubeletConfigKey: "kubelet", + }}) if err != nil { t.Fatalf("unexpected error: %v", err) } cases := []struct { desc string - current checkpoint.RemoteConfigSource + assigned checkpoint.RemoteConfigSource lastKnownGood checkpoint.RemoteConfigSource updated bool }{ @@ -453,176 +607,111 @@ func TestFsStoreReset(t *testing.T) { {"otherSource -> source", otherSource, source, true}, } for _, c := range cases { - // manually save the sources to their respective files - saveTestSourceFile(t, store.fs, curFile, c.current) - saveTestSourceFile(t, store.fs, lkgFile, c.lastKnownGood) - - // reset - updated, err := store.Reset() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // make sure the files were emptied - if size := testSourceFileSize(t, store.fs, curFile); size > 0 { - t.Errorf("case %q, expect source file %q to be empty but got %d bytes", c.desc, curFile, size) - } - if size := testSourceFileSize(t, store.fs, lkgFile); size > 0 { - t.Errorf("case %q, expect source file %q to be empty but got %d bytes", c.desc, lkgFile, size) - } - - // make sure Current() and LastKnownGood() both return nil - current, err := store.Current() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - lastKnownGood, err := store.LastKnownGood() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if current != nil || lastKnownGood != nil { - t.Errorf("case %q, expect nil for current and last-known-good checkpoints, but still have %q and %q, respectively", - c.desc, current, lastKnownGood) - } - if c.updated != updated { - t.Errorf("case %q, expect reset to return %t, but got %t", c.desc, c.updated, updated) - } - } -} - -func TestFsStoreSourceFromFile(t *testing.T) { - store, err := newInitializedFakeFsStore() - if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) - } - - source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ - ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - cases := []struct { - desc string - expect checkpoint.RemoteConfigSource - err string - }{ - {"default source", nil, ""}, - {"non-default source", source, ""}, - } - - const name = "some-source-file" - for _, c := range cases { - saveTestSourceFile(t, store.fs, name, c.expect) - source, err := store.sourceFromFile(name) - if utiltest.SkipRest(t, c.desc, err, c.err) { - continue - } - if !checkpoint.EqualRemoteConfigSources(c.expect, source) { - t.Errorf("case %q, expect %q but got %q", spew.Sdump(c.expect), spew.Sdump(c.expect), spew.Sdump(source)) - } - } -} - -func TestFsStoreSetSourceFile(t *testing.T) { - store, err := newInitializedFakeFsStore() - if err != nil { - t.Fatalf("failed to construct a store, error: %v", err) - } + t.Run(c.desc, func(t *testing.T) { + // manually save the sources to their respective files + saveTestSourceFile(t, store, assignedFile, c.assigned) + saveTestSourceFile(t, store, lastKnownGoodFile, c.lastKnownGood) - source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } + // reset + updated, err := store.Reset() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } - cases := []struct { - source checkpoint.RemoteConfigSource - }{ - {nil}, - {source}, - } + // make sure the files were emptied + if size := testSourceFileSize(t, store, assignedFile); size > 0 { + t.Errorf("case %q, expect source file %q to be empty but got %d bytes", c.desc, assignedFile, size) + } + if size := testSourceFileSize(t, store, lastKnownGoodFile); size > 0 { + t.Errorf("case %q, expect source file %q to be empty but got %d bytes", c.desc, lastKnownGoodFile, size) + } - const name = "some-source-file" - for _, c := range cases { - // set the source file - err := store.setSourceFile(name, c.source) - if err != nil { - t.Fatalf("unable to set source file, error: %v", err) - } - // read back the file - data := readTestSourceFile(t, store.fs, name) - str := string(data) - - if c.source != nil { - // expect the contents to match the encoding of the source - data, err := c.source.Encode() - expect := string(data) + // make sure Assigned() and LastKnownGood() both return nil + assigned, err := store.Assigned() if err != nil { - t.Fatalf("couldn't encode source, error: %v", err) + t.Fatalf("unexpected error: %v", err) } - if expect != str { - t.Errorf("case %q, expect %q but got %q", spew.Sdump(c.source), expect, str) + lastKnownGood, err := store.LastKnownGood() + if err != nil { + t.Fatalf("unexpected error: %v", err) } - } else { - // expect empty file - expect := "" - if expect != str { - t.Errorf("case %q, expect %q but got %q", spew.Sdump(c.source), expect, str) + if assigned != nil || lastKnownGood != nil { + t.Errorf("case %q, expect nil for assigned and last-known-good checkpoints, but still have %q and %q, respectively", + c.desc, assigned, lastKnownGood) } - } - } -} - -func readTestCheckpointFile(t *testing.T, fs utilfs.Filesystem, uid string) []byte { - data, err := fs.ReadFile(filepath.Join(testCheckpointsDir, uid)) - if err != nil { - t.Fatalf("unable to read test checkpoint file, error: %v", err) + if c.updated != updated { + t.Errorf("case %q, expect reset to return %t, but got %t", c.desc, c.updated, updated) + } + }) } - return data } -func saveTestCheckpointFile(t *testing.T, fs utilfs.Filesystem, cpt checkpoint.Checkpoint) { - data, err := cpt.Encode() +func mapFromCheckpoint(store *fsStore, uid, resourceVersion string) (map[string]string, error) { + files, err := store.fs.ReadDir(store.checkpointPath(uid, resourceVersion)) if err != nil { - t.Fatalf("unable to encode test checkpoint, error: %v", err) + return nil, err } - fmt.Println(cpt.UID()) - err = utilfiles.ReplaceFile(fs, filepath.Join(testCheckpointsDir, cpt.UID()), data) - if err != nil { - t.Fatalf("unable to save test checkpoint file, error: %v", err) + m := map[string]string{} + for _, f := range files { + // expect no subdirs, only regular files + if !f.Mode().IsRegular() { + return nil, fmt.Errorf("expect only regular files in checkpoint dir %q", uid) + } + // read the file contents and build the map + data, err := store.fs.ReadFile(filepath.Join(store.checkpointPath(uid, resourceVersion), f.Name())) + if err != nil { + return nil, err + } + m[f.Name()] = string(data) } + return m, nil } -func readTestSourceFile(t *testing.T, fs utilfs.Filesystem, relPath string) []byte { - data, err := fs.ReadFile(filepath.Join(testCheckpointsDir, relPath)) +func readTestSourceFile(t *testing.T, store *fsStore, relPath string) []byte { + data, err := store.fs.ReadFile(store.metaPath(relPath)) if err != nil { t.Fatalf("unable to read test source file, error: %v", err) } return data } -func saveTestSourceFile(t *testing.T, fs utilfs.Filesystem, relPath string, source checkpoint.RemoteConfigSource) { +func saveTestSourceFile(t *testing.T, store *fsStore, relPath string, source checkpoint.RemoteConfigSource) { if source != nil { data, err := source.Encode() if err != nil { t.Fatalf("unable to save test source file, error: %v", err) } - err = utilfiles.ReplaceFile(fs, filepath.Join(testCheckpointsDir, relPath), data) + err = utilfiles.ReplaceFile(store.fs, store.metaPath(relPath), data) if err != nil { t.Fatalf("unable to save test source file, error: %v", err) } } else { - err := utilfiles.ReplaceFile(fs, filepath.Join(testCheckpointsDir, relPath), []byte{}) + err := utilfiles.ReplaceFile(store.fs, store.metaPath(relPath), []byte{}) if err != nil { t.Fatalf("unable to save test source file, error: %v", err) } } } -func testSourceFileSize(t *testing.T, fs utilfs.Filesystem, relPath string) int64 { - info, err := fs.Stat(filepath.Join(testCheckpointsDir, relPath)) +func testSourceFileSize(t *testing.T, store *fsStore, relPath string) int64 { + info, err := store.fs.Stat(store.metaPath(relPath)) if err != nil { t.Fatalf("unexpected error: %v", err) } return info.Size() } + +// newKubeletConfiguration will create a new KubeletConfiguration with default values set +func newKubeletConfiguration() (*kubeletconfig.KubeletConfiguration, error) { + s, _, err := scheme.NewSchemeAndCodecs() + if err != nil { + return nil, err + } + versioned := &v1beta1.KubeletConfiguration{} + s.Default(versioned) + config := &kubeletconfig.KubeletConfiguration{} + if err := s.Convert(versioned, config, nil); err != nil { + return nil, err + } + return config, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/store.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/store.go index a6bdb736b..0ceb34a60 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/store.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/store.go @@ -20,65 +20,51 @@ import ( "fmt" "time" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint" ) -// Store saves checkpoints and information about which is the current and last-known-good checkpoint to a storage layer +// Store saves checkpoints and information about which is the assigned and last-known-good checkpoint to a storage layer type Store interface { // Initialize sets up the storage layer Initialize() error - // Exists returns true if a checkpoint with `uid` exists in the store, false otherwise - Exists(uid string) (bool, error) - // Save saves the checkpoint to the storage layer - Save(c checkpoint.Checkpoint) error - // Load loads the checkpoint with UID `uid` from the storage layer, or returns an error if the checkpoint does not exist - Load(uid string) (checkpoint.Checkpoint, error) - // CurrentModified returns the last time that the current UID was set - CurrentModified() (time.Time, error) - // Current returns the source that points to the current checkpoint, or nil if no current checkpoint is set - Current() (checkpoint.RemoteConfigSource, error) + + // Exists returns true if the object referenced by `source` has been checkpointed. + // The source must be unambiguous - e.g. if referencing an API object it must specify both uid and resourceVersion. + Exists(source checkpoint.RemoteConfigSource) (bool, error) + // Save Kubelet config payloads to the storage layer. It must be possible to unmarshal the payload to a KubeletConfiguration. + // The following payload types are supported: + // - k8s.io/api/core/v1.ConfigMap + Save(c checkpoint.Payload) error + // Load loads the KubeletConfiguration from the checkpoint referenced by `source`. + Load(source checkpoint.RemoteConfigSource) (*kubeletconfig.KubeletConfiguration, error) + + // AssignedModified returns the last time that the assigned checkpoint was set + AssignedModified() (time.Time, error) + // Assigned returns the source that points to the checkpoint currently assigned to the Kubelet, or nil if no assigned checkpoint is set + Assigned() (checkpoint.RemoteConfigSource, error) // LastKnownGood returns the source that points to the last-known-good checkpoint, or nil if no last-known-good checkpoint is set LastKnownGood() (checkpoint.RemoteConfigSource, error) - // SetCurrent saves the source that points to the current checkpoint, set to nil to unset - SetCurrent(source checkpoint.RemoteConfigSource) error - // SetCurrentUpdated is similar to SetCurrent, but also returns whether the current checkpoint changed as a result - SetCurrentUpdated(source checkpoint.RemoteConfigSource) (bool, error) + + // SetAssigned saves the source that points to the assigned checkpoint, set to nil to unset + SetAssigned(source checkpoint.RemoteConfigSource) error // SetLastKnownGood saves the source that points to the last-known-good checkpoint, set to nil to unset SetLastKnownGood(source checkpoint.RemoteConfigSource) error - // Reset unsets the current and last-known-good UIDs and returns whether the current UID was unset as a result of the reset + // Reset unsets the assigned and last-known-good checkpoints and returns whether the assigned checkpoint was unset as a result of the reset Reset() (bool, error) } // reset is a helper for implementing Reset, which can be implemented in terms of Store methods func reset(s Store) (bool, error) { - if err := s.SetLastKnownGood(nil); err != nil { - return false, fmt.Errorf("failed to reset last-known-good UID in checkpoint store, error: %v", err) - } - updated, err := s.SetCurrentUpdated(nil) - if err != nil { - return false, fmt.Errorf("failed to reset current UID in checkpoint store, error: %v", err) - } - return updated, nil -} - -// setCurrentUpdated is a helper for implementing SetCurrentUpdated, which can be implemented in terms of Store methods -func setCurrentUpdated(s Store, source checkpoint.RemoteConfigSource) (bool, error) { - cur, err := s.Current() + assigned, err := s.Assigned() if err != nil { return false, err } - - // if both are nil, no need to update - if cur == nil && source == nil { - return false, nil - } - // if UIDs match, no need to update - if (source != nil && cur != nil) && cur.UID() == source.UID() { - return false, nil + if err := s.SetLastKnownGood(nil); err != nil { + return false, fmt.Errorf("failed to reset last-known-good UID in checkpoint store, error: %v", err) } - // update the source - if err := s.SetCurrent(source); err != nil { - return false, err + if err := s.SetAssigned(nil); err != nil { + return false, fmt.Errorf("failed to reset assigned UID in checkpoint store, error: %v", err) } - return true, nil + return assigned != nil, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/store_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/store_test.go index c269d7858..f587de984 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/store_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint/store/store_test.go @@ -26,11 +26,21 @@ import ( ) func TestReset(t *testing.T) { - source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}) + source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "name", + Namespace: "namespace", + UID: "uid", + KubeletConfigKey: "kubelet", + }}) if err != nil { t.Fatalf("unexpected error: %v", err) } - otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "other-name", Namespace: "namespace", UID: "other-uid"}}) + otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "other-name", + Namespace: "namespace", + UID: "other-uid", + KubeletConfigKey: "kubelet", + }}) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -38,59 +48,24 @@ func TestReset(t *testing.T) { s *fakeStore updated bool }{ - {&fakeStore{current: nil, lastKnownGood: nil}, false}, - {&fakeStore{current: source, lastKnownGood: nil}, true}, - {&fakeStore{current: nil, lastKnownGood: source}, false}, - {&fakeStore{current: source, lastKnownGood: source}, true}, - {&fakeStore{current: source, lastKnownGood: otherSource}, true}, - {&fakeStore{current: otherSource, lastKnownGood: source}, true}, + {&fakeStore{assigned: nil, lastKnownGood: nil}, false}, + {&fakeStore{assigned: source, lastKnownGood: nil}, true}, + {&fakeStore{assigned: nil, lastKnownGood: source}, false}, + {&fakeStore{assigned: source, lastKnownGood: source}, true}, + {&fakeStore{assigned: source, lastKnownGood: otherSource}, true}, + {&fakeStore{assigned: otherSource, lastKnownGood: source}, true}, } for _, c := range cases { updated, err := reset(c.s) if err != nil { t.Fatalf("unexpected error: %v", err) } - if c.s.current != nil || c.s.lastKnownGood != nil { - t.Errorf("case %q, expect nil for current and last-known-good checkpoints, but still have %q and %q, respectively", - spew.Sdump(c.s), c.s.current, c.s.lastKnownGood) + if c.s.assigned != nil || c.s.lastKnownGood != nil { + t.Errorf("case %q, expect nil for assigned and last-known-good checkpoints, but still have %q and %q, respectively", + spew.Sdump(c.s), c.s.assigned, c.s.lastKnownGood) } if c.updated != updated { t.Errorf("case %q, expect reset to return %t, but got %t", spew.Sdump(c.s), c.updated, updated) } } } - -func TestSetCurrentUpdated(t *testing.T) { - source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "other-name", Namespace: "namespace", UID: "other-uid"}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - cases := []struct { - s *fakeStore - newCurrent checkpoint.RemoteConfigSource - updated bool - }{ - {&fakeStore{current: nil}, nil, false}, - {&fakeStore{current: nil}, source, true}, - {&fakeStore{current: source}, source, false}, - {&fakeStore{current: source}, nil, true}, - {&fakeStore{current: source}, otherSource, true}, - } - for _, c := range cases { - current := c.s.current - updated, err := setCurrentUpdated(c.s, c.newCurrent) - if err != nil { - t.Fatalf("case %q -> %q, unexpected error: %v", current, c.newCurrent, err) - } - if c.newCurrent != c.s.current { - t.Errorf("case %q -> %q, expect current UID to be %q, but got %q", current, c.newCurrent, c.newCurrent, c.s.current) - } - if c.updated != updated { - t.Errorf("case %q -> %q, expect setCurrentUpdated to return %t, but got %t", current, c.newCurrent, c.updated, updated) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/configsync.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/configsync.go index 2584bc2ef..cb92fb7e6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/configsync.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/configsync.go @@ -37,10 +37,10 @@ import ( const ( // KubeletConfigChangedEventReason identifies an event as a change of Kubelet configuration KubeletConfigChangedEventReason = "KubeletConfigChanged" - // EventMessageFmt is the message format for Kubelet config change events - EventMessageFmt = "Kubelet will restart to use: %s" - // LocalConfigMessage is the text to apply to EventMessageFmt when the Kubelet has been configured to use its local config (init or defaults) - LocalConfigMessage = "local config" + // LocalEventMessage is sent when the Kubelet restarts to use local config + LocalEventMessage = "Kubelet restarting to use local config" + // RemoteEventMessageFmt is sent when the Kubelet restarts to use a remote config + RemoteEventMessageFmt = "Kubelet restarting to use %s, UID: %s, ResourceVersion: %s, KubeletConfigKey: %s" ) // pokeConfiSourceWorker tells the worker thread that syncs config sources that work needs to be done @@ -69,124 +69,144 @@ func (cc *Controller) syncConfigSource(client clientset.Interface, eventClient v } }() - node, err := latestNode(cc.informer.GetStore(), nodeName) + // get the latest Node.Spec.ConfigSource from the informer + source, err := latestNodeConfigSource(cc.nodeInformer.GetStore(), nodeName) if err != nil { - cc.configOk.SetFailSyncCondition(status.FailSyncReasonInformer) - syncerr = fmt.Errorf("%s, error: %v", status.FailSyncReasonInformer, err) + cc.configStatus.SetErrorOverride(fmt.Sprintf(status.SyncErrorFmt, status.InternalError)) + syncerr = fmt.Errorf("%s, error: %v", status.InternalError, err) return } - // check the Node and download any new config - if updated, cur, reason, err := cc.doSyncConfigSource(client, node.Spec.ConfigSource); err != nil { - cc.configOk.SetFailSyncCondition(reason) - syncerr = fmt.Errorf("%s, error: %v", reason, err) - return - } else if updated { - path := LocalConfigMessage - if cur != nil { - path = cur.APIPath() - } - // we directly log and send the event, instead of using the event recorder, - // because the event recorder won't flush its queue before we exit (we'd lose the event) - event := eventf(nodeName, apiv1.EventTypeNormal, KubeletConfigChangedEventReason, EventMessageFmt, path) - glog.V(3).Infof("Event(%#v): type: '%v' reason: '%v' %v", event.InvolvedObject, event.Type, event.Reason, event.Message) - if _, err := eventClient.Events(apiv1.NamespaceDefault).Create(event); err != nil { - utillog.Errorf("failed to send event, error: %v", err) - } - os.Exit(0) - } - - // If we get here: - // - there is no need to restart to update the current config - // - there was no error trying to sync configuration - // - if, previously, there was an error trying to sync configuration, we need to clear that error from the condition - cc.configOk.ClearFailSyncCondition() -} - -// doSyncConfigSource checkpoints and sets the store's current config to the new config or resets config, -// depending on the `source`, and returns whether the current config in the checkpoint store was updated as a result -func (cc *Controller) doSyncConfigSource(client clientset.Interface, source *apiv1.NodeConfigSource) (bool, checkpoint.RemoteConfigSource, string, error) { + // a nil source simply means we reset to local defaults if source == nil { - utillog.Infof("Node.Spec.ConfigSource is empty, will reset current and last-known-good to defaults") - updated, reason, err := cc.resetConfig() - if err != nil { - return false, nil, reason, err + utillog.Infof("Node.Spec.ConfigSource is empty, will reset assigned and last-known-good to defaults") + if updated, reason, err := cc.resetConfig(); err != nil { + reason = fmt.Sprintf(status.SyncErrorFmt, reason) + cc.configStatus.SetErrorOverride(reason) + syncerr = fmt.Errorf("%s, error: %v", reason, err) + return + } else if updated { + restartForNewConfig(eventClient, nodeName, nil) } - return updated, nil, "", nil + return } - // if the NodeConfigSource is non-nil, download the config + // a non-nil source means we should attempt to download the config, and checkpoint it if necessary utillog.Infof("Node.Spec.ConfigSource is non-empty, will checkpoint source and update config if necessary") + + // TODO(mtaufen): It would be nice if we could check the payload's metadata before (re)downloading the whole payload + // we at least try pulling the latest configmap out of the local informer store. + + // construct the interface that can dynamically dispatch the correct Download, etc. methods for the given source type remote, reason, err := checkpoint.NewRemoteConfigSource(source) if err != nil { - return false, nil, reason, err + reason = fmt.Sprintf(status.SyncErrorFmt, reason) + cc.configStatus.SetErrorOverride(reason) + syncerr = fmt.Errorf("%s, error: %v", reason, err) + return } - reason, err = cc.checkpointConfigSource(client, remote) + + // "download" source, either from informer's in-memory store or directly from the API server, if the informer doesn't have a copy + payload, reason, err := cc.downloadConfigPayload(client, remote) if err != nil { - return false, nil, reason, err + reason = fmt.Sprintf(status.SyncErrorFmt, reason) + cc.configStatus.SetErrorOverride(reason) + syncerr = fmt.Errorf("%s, error: %v", reason, err) + return } - updated, reason, err := cc.setCurrentConfig(remote) - if err != nil { - return false, nil, reason, err + + // save a checkpoint for the payload, if one does not already exist + if reason, err := cc.saveConfigCheckpoint(remote, payload); err != nil { + reason = fmt.Sprintf(status.SyncErrorFmt, reason) + cc.configStatus.SetErrorOverride(reason) + syncerr = fmt.Errorf("%s, error: %v", reason, err) + return } - return updated, remote, "", nil -} -// checkpointConfigSource downloads and checkpoints the object referred to by `source` if the checkpoint does not already exist, -// if a failure occurs, returns a sanitized failure reason and an error -func (cc *Controller) checkpointConfigSource(client clientset.Interface, source checkpoint.RemoteConfigSource) (string, error) { - uid := source.UID() - - // if the checkpoint already exists, skip downloading - if ok, err := cc.checkpointStore.Exists(uid); err != nil { - reason := fmt.Sprintf(status.FailSyncReasonCheckpointExistenceFmt, source.APIPath(), uid) - return reason, fmt.Errorf("%s, error: %v", reason, err) - } else if ok { - utillog.Infof("checkpoint already exists for object with UID %q, skipping download", uid) - return "", nil + // update the local, persistent record of assigned config + if updated, reason, err := cc.setAssignedConfig(remote); err != nil { + reason = fmt.Sprintf(status.SyncErrorFmt, reason) + cc.configStatus.SetErrorOverride(reason) + syncerr = fmt.Errorf("%s, error: %v", reason, err) + return + } else if updated { + restartForNewConfig(eventClient, nodeName, remote) } - // download - checkpoint, reason, err := source.Download(client) - if err != nil { - return reason, fmt.Errorf("%s, error: %v", reason, err) + // If we get here: + // - there is no need to restart to use new config + // - there was no error trying to sync configuration + // - if, previously, there was an error trying to sync configuration, we need to clear that error from the status + cc.configStatus.SetErrorOverride("") +} + +// Note: source has up-to-date uid and resourceVersion after calling downloadConfigPayload. +func (cc *Controller) downloadConfigPayload(client clientset.Interface, source checkpoint.RemoteConfigSource) (checkpoint.Payload, string, error) { + var store cache.Store + if cc.remoteConfigSourceInformer != nil { + store = cc.remoteConfigSourceInformer.GetStore() } + return source.Download(client, store) +} - // save - err = cc.checkpointStore.Save(checkpoint) +func (cc *Controller) saveConfigCheckpoint(source checkpoint.RemoteConfigSource, payload checkpoint.Payload) (string, error) { + ok, err := cc.checkpointStore.Exists(source) if err != nil { - reason := fmt.Sprintf(status.FailSyncReasonSaveCheckpointFmt, source.APIPath(), checkpoint.UID()) - return reason, fmt.Errorf("%s, error: %v", reason, err) + return status.InternalError, fmt.Errorf("%s, error: %v", status.InternalError, err) + } + if ok { + utillog.Infof("checkpoint already exists for %s, UID: %s, ResourceVersion: %s", source.APIPath(), payload.UID(), payload.ResourceVersion()) + return "", nil + } + if err := cc.checkpointStore.Save(payload); err != nil { + return status.InternalError, fmt.Errorf("%s, error: %v", status.InternalError, err) } - return "", nil } -// setCurrentConfig updates UID of the current checkpoint in the checkpoint store to `uid` and returns whether the -// current UID changed as a result, or a sanitized failure reason and an error. -func (cc *Controller) setCurrentConfig(source checkpoint.RemoteConfigSource) (bool, string, error) { - updated, err := cc.checkpointStore.SetCurrentUpdated(source) +// setAssignedConfig updates the assigned checkpoint config in the store. +// Returns whether the assigned config changed as a result, or a sanitized failure reason and an error. +func (cc *Controller) setAssignedConfig(source checkpoint.RemoteConfigSource) (bool, string, error) { + assigned, err := cc.checkpointStore.Assigned() if err != nil { - if source == nil { - return false, status.FailSyncReasonSetCurrentLocal, err - } - return false, fmt.Sprintf(status.FailSyncReasonSetCurrentUIDFmt, source.APIPath(), source.UID()), err + return false, status.InternalError, err } - return updated, "", nil + if err := cc.checkpointStore.SetAssigned(source); err != nil { + return false, status.InternalError, err + } + return !checkpoint.EqualRemoteConfigSources(assigned, source), "", nil } -// resetConfig resets the current and last-known-good checkpoints in the checkpoint store to their default values and -// returns whether the current checkpoint changed as a result, or a sanitized failure reason and an error. +// resetConfig resets the assigned and last-known-good checkpoints in the checkpoint store to their default values and +// returns whether the assigned checkpoint changed as a result, or a sanitized failure reason and an error. func (cc *Controller) resetConfig() (bool, string, error) { updated, err := cc.checkpointStore.Reset() if err != nil { - return false, status.FailSyncReasonReset, err + return false, status.InternalError, err } return updated, "", nil } -// latestNode returns the most recent Node with `nodeName` from `store` -func latestNode(store cache.Store, nodeName string) (*apiv1.Node, error) { +// restartForNewConfig presumes the Kubelet is managed by a babysitter, e.g. systemd +// It will send an event before exiting. +func restartForNewConfig(eventClient v1core.EventsGetter, nodeName string, source checkpoint.RemoteConfigSource) { + message := LocalEventMessage + if source != nil { + message = fmt.Sprintf(RemoteEventMessageFmt, source.APIPath(), source.UID(), source.ResourceVersion(), source.KubeletFilename()) + } + // we directly log and send the event, instead of using the event recorder, + // because the event recorder won't flush its queue before we exit (we'd lose the event) + event := makeEvent(nodeName, apiv1.EventTypeNormal, KubeletConfigChangedEventReason, message) + glog.V(3).Infof("Event(%#v): type: '%v' reason: '%v' %v", event.InvolvedObject, event.Type, event.Reason, event.Message) + if _, err := eventClient.Events(apiv1.NamespaceDefault).Create(event); err != nil { + utillog.Errorf("failed to send event, error: %v", err) + } + utillog.Infof(message) + os.Exit(0) +} + +// latestNodeConfigSource returns a copy of the most recent NodeConfigSource from the Node with `nodeName` in `store` +func latestNodeConfigSource(store cache.Store, nodeName string) (*apiv1.NodeConfigSource, error) { obj, ok, err := store.GetByKey(nodeName) if err != nil { err := fmt.Errorf("failed to retrieve Node %q from informer's store, error: %v", nodeName, err) @@ -203,13 +223,11 @@ func latestNode(store cache.Store, nodeName string) (*apiv1.Node, error) { utillog.Errorf(err.Error()) return nil, err } - return node, nil -} - -// eventf constructs and returns an event containing a formatted message -// similar to k8s.io/client-go/tools/record/event.go -func eventf(nodeName, eventType, reason, messageFmt string, args ...interface{}) *apiv1.Event { - return makeEvent(nodeName, eventType, reason, fmt.Sprintf(messageFmt, args...)) + // Copy the source, so anyone who modifies it after here doesn't mess up the informer's store! + // This was previously the cause of a bug that made the Kubelet frequently resync config; Download updated + // the UID and ResourceVersion on the NodeConfigSource, but the pointer was still drilling all the way + // into the informer's copy! + return node.Spec.ConfigSource.DeepCopy(), nil } // makeEvent constructs an event diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/controller.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/controller.go index 352a310f4..afe707b69 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/controller.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/controller.go @@ -21,7 +21,7 @@ import ( "path/filepath" "time" - apiv1 "k8s.io/api/core/v1" + apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" v1core "k8s.io/client-go/kubernetes/typed/core/v1" @@ -38,67 +38,101 @@ import ( ) const ( - checkpointsDir = "checkpoints" + storeDir = "store" // TODO(mtaufen): We may expose this in a future API, but for the time being we use an internal default, // because it is not especially clear where this should live in the API. configTrialDuration = 10 * time.Minute ) +// TransformFunc edits the KubeletConfiguration in-place, and returns an +// error if any of the transformations failed. +type TransformFunc func(kc *kubeletconfig.KubeletConfiguration) error + // Controller manages syncing dynamic Kubelet configurations // For more information, see the proposal: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/dynamic-kubelet-configuration.md type Controller struct { - // defaultConfig is the configuration to use if no initConfig is provided - defaultConfig *kubeletconfig.KubeletConfiguration + // transform applies an arbitrary transformation to config after loading, and before validation. + // This can be used, for example, to include config from flags before the controller's validation step. + // If transform returns an error, loadConfig will fail, and an InternalError will be reported. + // Be wary if using this function as an extension point, in most cases the controller should + // probably just be natively extended to do what you need. Injecting flag precedence transformations + // is something of an exception because the caller of this controller (cmd/) is aware of flags, but this + // controller's tree (pkg/) is not. + transform TransformFunc // pendingConfigSource; write to this channel to indicate that the config source needs to be synced from the API server pendingConfigSource chan bool - // configOk manages the KubeletConfigOk condition that is reported in Node.Status.Conditions - configOk status.ConfigOkCondition + // configStatus manages the status we report on the Node object + configStatus status.NodeConfigStatus + + // nodeInformer is the informer that watches the Node object + nodeInformer cache.SharedInformer - // informer is the informer that watches the Node object - informer cache.SharedInformer + // remoteConfigSourceInformer is the informer that watches the assigned config source + remoteConfigSourceInformer cache.SharedInformer // checkpointStore persists config source checkpoints to a storage layer checkpointStore store.Store } -// NewController constructs a new Controller object and returns it. Directory paths must be absolute. -func NewController(defaultConfig *kubeletconfig.KubeletConfiguration, dynamicConfigDir string) *Controller { +// NewController constructs a new Controller object and returns it. The dynamicConfigDir +// path must be absolute. transform applies an arbitrary transformation to config after loading, and before validation. +// This can be used, for example, to include config from flags before the controller's validation step. +// If transform returns an error, loadConfig will fail, and an InternalError will be reported. +// Be wary if using this function as an extension point, in most cases the controller should +// probably just be natively extended to do what you need. Injecting flag precedence transformations +// is something of an exception because the caller of this controller (cmd/) is aware of flags, but this +// controller's tree (pkg/) is not. +func NewController(dynamicConfigDir string, transform TransformFunc) *Controller { return &Controller{ - defaultConfig: defaultConfig, + transform: transform, // channels must have capacity at least 1, since we signal with non-blocking writes pendingConfigSource: make(chan bool, 1), - configOk: status.NewConfigOkCondition(), - checkpointStore: store.NewFsStore(utilfs.DefaultFs{}, filepath.Join(dynamicConfigDir, checkpointsDir)), + configStatus: status.NewNodeConfigStatus(), + checkpointStore: store.NewFsStore(utilfs.DefaultFs{}, filepath.Join(dynamicConfigDir, storeDir)), } } // Bootstrap attempts to return a valid KubeletConfiguration based on the configuration of the Controller, // or returns an error if no valid configuration could be produced. Bootstrap should be called synchronously before StartSync. +// If the pre-existing local configuration should be used, Bootstrap returns a nil config. func (cc *Controller) Bootstrap() (*kubeletconfig.KubeletConfiguration, error) { utillog.Infof("starting controller") - // ALWAYS validate the local config. This makes incorrectly provisioned nodes an error. - // It must be valid because it is the default last-known-good config. - utillog.Infof("validating local config") - if err := validation.ValidateKubeletConfiguration(cc.defaultConfig); err != nil { - return nil, fmt.Errorf("local config failed validation, error: %v", err) - } - // ensure the filesystem is initialized if err := cc.initializeDynamicConfigDir(); err != nil { return nil, err } - assigned, curSource, reason, err := cc.loadAssignedConfig(cc.defaultConfig) + // determine assigned source and set status + assignedSource, err := cc.checkpointStore.Assigned() + if err != nil { + return nil, err + } + if assignedSource != nil { + cc.configStatus.SetAssigned(assignedSource.NodeConfigSource()) + } + + // determine last-known-good source and set status + lastKnownGoodSource, err := cc.checkpointStore.LastKnownGood() + if err != nil { + return nil, err + } + if lastKnownGoodSource != nil { + cc.configStatus.SetLastKnownGood(lastKnownGoodSource.NodeConfigSource()) + } + + // if the assigned source is nil, return nil to indicate local config + if assignedSource == nil { + return nil, nil + } + + // attempt to load assigned config + assignedConfig, reason, err := cc.loadConfig(assignedSource) if err == nil { - // set the status to indicate we will use the assigned config - if curSource != nil { - cc.configOk.Set(fmt.Sprintf(status.CurRemoteMessageFmt, curSource.APIPath()), reason, apiv1.ConditionTrue) - } else { - cc.configOk.Set(status.CurLocalMessage, reason, apiv1.ConditionTrue) - } + // update the active source to the non-nil assigned source + cc.configStatus.SetActive(assignedSource.NodeConfigSource()) // update the last-known-good config if necessary, and start a timer that // periodically checks whether the last-known good needs to be updated @@ -106,134 +140,126 @@ func (cc *Controller) Bootstrap() (*kubeletconfig.KubeletConfiguration, error) { // wait.Forever will call the func once before starting the timer go wait.Forever(func() { cc.checkTrial(configTrialDuration) }, 10*time.Second) - return assigned, nil - } // Assert: the assigned config failed to load, parse, or validate + return assignedConfig, nil + } // Assert: the assigned config failed to load or validate // TODO(mtaufen): consider re-attempting download when a load/verify/parse/validate // error happens outside trial period, we already made it past the trial so it's probably filesystem corruption - // or something else scary (unless someone is using a 0-length trial period) - // load from checkpoint + // or something else scary // log the reason and error details for the failure to load the assigned config utillog.Errorf(fmt.Sprintf("%s, error: %v", reason, err)) - // load the last-known-good config - lkg, lkgSource, err := cc.loadLastKnownGoodConfig(cc.defaultConfig) - if err != nil { - return nil, err + // set status to indicate the failure with the assigned config + cc.configStatus.SetError(reason) + + // if the last-known-good source is nil, return nil to indicate local config + if lastKnownGoodSource == nil { + return nil, nil } - // set the status to indicate that we had to roll back to the lkg for the reason reported when we tried to load the assigned config - if lkgSource != nil { - cc.configOk.Set(fmt.Sprintf(status.LkgRemoteMessageFmt, lkgSource.APIPath()), reason, apiv1.ConditionFalse) - } else { - cc.configOk.Set(status.LkgLocalMessage, reason, apiv1.ConditionFalse) + // attempt to load the last-known-good config + lastKnownGoodConfig, _, err := cc.loadConfig(lastKnownGoodSource) + if err != nil { + // we failed to load the last-known-good, so something is really messed up and we just return the error + return nil, err } - // return the last-known-good config - return lkg, nil + // set status to indicate the active source is the non-nil last-known-good source + cc.configStatus.SetActive(lastKnownGoodSource.NodeConfigSource()) + return lastKnownGoodConfig, nil } -// StartSync launches the controller's sync loops if `client` is non-nil and `nodeName` is non-empty. -// It will always start the Node condition reporting loop, and will also start the dynamic conifg sync loops -// if dynamic config is enabled on the controller. If `nodeName` is empty but `client` is non-nil, an error is logged. -func (cc *Controller) StartSync(client clientset.Interface, eventClient v1core.EventsGetter, nodeName string) { +// StartSync tells the controller to start the goroutines that sync status/config to/from the API server. +// The clients must be non-nil, and the nodeName must be non-empty. +func (cc *Controller) StartSync(client clientset.Interface, eventClient v1core.EventsGetter, nodeName string) error { + const errFmt = "cannot start Kubelet config sync: %s" if client == nil { - utillog.Infof("nil client, will not start sync loops") - return - } else if len(nodeName) == 0 { - utillog.Errorf("cannot start sync loops with empty nodeName") - return + return fmt.Errorf(errFmt, "nil client") + } + if eventClient == nil { + return fmt.Errorf(errFmt, "nil event client") + } + if nodeName == "" { + return fmt.Errorf(errFmt, "empty nodeName") } - // start the ConfigOk condition sync loop - go utilpanic.HandlePanic(func() { - utillog.Infof("starting ConfigOk condition sync loop") - wait.JitterUntil(func() { - cc.configOk.Sync(client, nodeName) - }, 10*time.Second, 0.2, true, wait.NeverStop) - })() - - cc.informer = newSharedNodeInformer(client, nodeName, - cc.onAddNodeEvent, cc.onUpdateNodeEvent, cc.onDeleteNodeEvent) - // start the informer loop // Rather than use utilruntime.HandleCrash, which doesn't actually crash in the Kubelet, // we use HandlePanic to manually call the panic handlers and then crash. // We have a better chance of recovering normal operation if we just restart the Kubelet in the event // of a Go runtime error. - go utilpanic.HandlePanic(func() { - utillog.Infof("starting Node informer sync loop") - cc.informer.Run(wait.NeverStop) - })() - - // start the config source sync loop - go utilpanic.HandlePanic(func() { - utillog.Infof("starting config source sync loop") + // NOTE(mtaufen): utilpanic.HandlePanic returns a function and you have to call it for your thing to run! + // This was EVIL to debug (difficult to see missing `()`). + // The code now uses `go name()` instead of `go utilpanic.HandlePanic(func(){...})()` to avoid confusion. + + // status sync worker + statusSyncLoopFunc := utilpanic.HandlePanic(func() { + utillog.Infof("starting status sync loop") wait.JitterUntil(func() { - cc.syncConfigSource(client, eventClient, nodeName) + cc.configStatus.Sync(client, nodeName) }, 10*time.Second, 0.2, true, wait.NeverStop) - })() - -} - -// loadAssignedConfig loads the Kubelet's currently assigned config, -// based on the setting in the local checkpoint store. -// It returns the loaded configuration, the checkpoint store's config source record, -// a clean success or failure reason that can be reported in the status, and any error that occurs. -// If the local config should be used, it will be returned. You should validate local before passing it to this function. -func (cc *Controller) loadAssignedConfig(local *kubeletconfig.KubeletConfiguration) (*kubeletconfig.KubeletConfiguration, checkpoint.RemoteConfigSource, string, error) { - src, err := cc.checkpointStore.Current() - if err != nil { - return nil, nil, fmt.Sprintf(status.CurFailLoadReasonFmt, "unknown"), err - } - // nil source is the signal to use the local config - if src == nil { - return local, src, status.CurLocalOkayReason, nil - } - curUID := src.UID() - // load from checkpoint - checkpoint, err := cc.checkpointStore.Load(curUID) - if err != nil { - return nil, src, fmt.Sprintf(status.CurFailLoadReasonFmt, src.APIPath()), err - } - cur, err := checkpoint.Parse() + }) + // remote config source informer, if we have a remote source to watch + assignedSource, err := cc.checkpointStore.Assigned() if err != nil { - return nil, src, fmt.Sprintf(status.CurFailParseReasonFmt, src.APIPath()), err - } - if err := validation.ValidateKubeletConfiguration(cur); err != nil { - return nil, src, fmt.Sprintf(status.CurFailValidateReasonFmt, src.APIPath()), err + return fmt.Errorf(errFmt, err) + } else if assignedSource == nil { + utillog.Infof("local source is assigned, will not start remote config source informer") + } else { + cc.remoteConfigSourceInformer = assignedSource.Informer(client, cache.ResourceEventHandlerFuncs{ + AddFunc: cc.onAddRemoteConfigSourceEvent, + UpdateFunc: cc.onUpdateRemoteConfigSourceEvent, + DeleteFunc: cc.onDeleteRemoteConfigSourceEvent, + }, + ) } - return cur, src, status.CurRemoteOkayReason, nil + remoteConfigSourceInformerFunc := utilpanic.HandlePanic(func() { + if cc.remoteConfigSourceInformer != nil { + utillog.Infof("starting remote config source informer") + cc.remoteConfigSourceInformer.Run(wait.NeverStop) + } + }) + // node informer + cc.nodeInformer = newSharedNodeInformer(client, nodeName, + cc.onAddNodeEvent, cc.onUpdateNodeEvent, cc.onDeleteNodeEvent) + nodeInformerFunc := utilpanic.HandlePanic(func() { + utillog.Infof("starting Node informer") + cc.nodeInformer.Run(wait.NeverStop) + }) + // config sync worker + configSyncLoopFunc := utilpanic.HandlePanic(func() { + utillog.Infof("starting Kubelet config sync loop") + wait.JitterUntil(func() { + cc.syncConfigSource(client, eventClient, nodeName) + }, 10*time.Second, 0.2, true, wait.NeverStop) + }) + + go statusSyncLoopFunc() + go remoteConfigSourceInformerFunc() + go nodeInformerFunc() + go configSyncLoopFunc() + return nil } -// loadLastKnownGoodConfig loads the Kubelet's last-known-good config, -// based on the setting in the local checkpoint store. -// It returns the loaded configuration, the checkpoint store's config source record, -// and any error that occurs. -// If the local config should be used, it will be returned. You should validate local before passing it to this function. -func (cc *Controller) loadLastKnownGoodConfig(local *kubeletconfig.KubeletConfiguration) (*kubeletconfig.KubeletConfiguration, checkpoint.RemoteConfigSource, error) { - src, err := cc.checkpointStore.LastKnownGood() - if err != nil { - return nil, nil, fmt.Errorf("unable to determine last-known-good config, error: %v", err) - } - // nil source is the signal to use the local config - if src == nil { - return local, src, nil - } - lkgUID := src.UID() - // load from checkpoint - checkpoint, err := cc.checkpointStore.Load(lkgUID) +// loadConfig loads Kubelet config from a checkpoint +// It returns the loaded configuration or a clean failure reason (for status reporting) and an error. +func (cc *Controller) loadConfig(source checkpoint.RemoteConfigSource) (*kubeletconfig.KubeletConfiguration, string, error) { + // load KubeletConfiguration from checkpoint + kc, err := cc.checkpointStore.Load(source) if err != nil { - return nil, src, fmt.Errorf("%s, error: %v", fmt.Sprintf(status.LkgFailLoadReasonFmt, src.APIPath()), err) + return nil, status.LoadError, err } - lkg, err := checkpoint.Parse() - if err != nil { - return nil, src, fmt.Errorf("%s, error: %v", fmt.Sprintf(status.LkgFailParseReasonFmt, src.APIPath()), err) + // apply any required transformations to the KubeletConfiguration + if cc.transform != nil { + if err := cc.transform(kc); err != nil { + return nil, status.InternalError, err + } } - if err := validation.ValidateKubeletConfiguration(lkg); err != nil { - return nil, src, fmt.Errorf("%s, error: %v", fmt.Sprintf(status.LkgFailValidateReasonFmt, src.APIPath()), err) + // validate the result + if err := validation.ValidateKubeletConfiguration(kc); err != nil { + return nil, status.ValidateError, err } - return lkg, src, nil + return kc, "", nil } // initializeDynamicConfigDir makes sure that the storage layers for various controller components are set up correctly @@ -249,17 +275,16 @@ func (cc *Controller) checkTrial(duration time.Duration) { if trial, err := cc.inTrial(duration); err != nil { utillog.Errorf("failed to check trial period for assigned config, error: %v", err) } else if !trial { - utillog.Infof("assigned config passed trial period, will set as last-known-good") if err := cc.graduateAssignedToLastKnownGood(); err != nil { utillog.Errorf("failed to set last-known-good to assigned config, error: %v", err) } } } -// inTrial returns true if the time elapsed since the last modification of the current config does not exceed `trialDur`, false otherwise +// inTrial returns true if the time elapsed since the last modification of the assigned config does not exceed `trialDur`, false otherwise func (cc *Controller) inTrial(trialDur time.Duration) (bool, error) { now := time.Now() - t, err := cc.checkpointStore.CurrentModified() + t, err := cc.checkpointStore.AssignedModified() if err != nil { return false, err } @@ -269,16 +294,31 @@ func (cc *Controller) inTrial(trialDur time.Duration) (bool, error) { return false, nil } -// graduateAssignedToLastKnownGood sets the last-known-good UID on the checkpointStore -// to the same value as the current UID maintained by the checkpointStore +// graduateAssignedToLastKnownGood sets the last-known-good in the checkpointStore +// to the same value as the assigned config maintained by the checkpointStore func (cc *Controller) graduateAssignedToLastKnownGood() error { - curUID, err := cc.checkpointStore.Current() + // get assigned + assigned, err := cc.checkpointStore.Assigned() if err != nil { return err } - err = cc.checkpointStore.SetLastKnownGood(curUID) + // get last-known-good + lastKnownGood, err := cc.checkpointStore.LastKnownGood() + if err != nil { + return err + } + // if the sources are equal, no need to change + if assigned == lastKnownGood || + assigned != nil && lastKnownGood != nil && apiequality.Semantic.DeepEqual(assigned, lastKnownGood) { + return nil + } + // update last-known-good + err = cc.checkpointStore.SetLastKnownGood(assigned) if err != nil { return err } + // update the status to reflect the new last-known-good config + cc.configStatus.SetLastKnownGood(assigned.NodeConfigSource()) + utillog.Infof("updated last-known-good config to %s, UID: %s, ResourceVersion: %s", assigned.APIPath(), assigned.UID(), assigned.ResourceVersion()) return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status/BUILD index 6de1a105e..fe925bfc9 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status/BUILD @@ -10,14 +10,12 @@ go_library( srcs = ["status.go"], importpath = "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status", deps = [ - "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core:go_default_library", - "//pkg/kubelet/kubeletconfig/util/equal:go_default_library", "//pkg/kubelet/kubeletconfig/util/log:go_default_library", + "//pkg/kubelet/metrics:go_default_library", + "//pkg/util/node:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status/status.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status/status.go index 4cd5db1f7..d1fdfeb8c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status/status.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status/status.go @@ -19,302 +19,184 @@ package status import ( "fmt" "sync" - "time" apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kuberuntime "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/apimachinery/pkg/types" clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/api/legacyscheme" - api "k8s.io/kubernetes/pkg/apis/core" - utilequal "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/equal" utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log" + "k8s.io/kubernetes/pkg/kubelet/metrics" + nodeutil "k8s.io/kubernetes/pkg/util/node" ) -// TODO(mtaufen): s/current/assigned, as this is more accurate e.g. if you are using lkg, you aren't currently using "current" :) const ( - // CurLocalMessage indicates that the Kubelet is using its local config, which consists of defaults, flags, and/or local files - CurLocalMessage = "using current: local" - // LkgLocalMessage indicates that the Kubelet is using its local config, which consists of defaults, flags, and/or local files - LkgLocalMessage = "using last-known-good: local" - - // CurRemoteMessageFmt indicates the Kubelet is using its current config, which is from an API source - CurRemoteMessageFmt = "using current: %s" - // LkgRemoteMessageFmt indicates the Kubelet is using its last-known-good config, which is from an API source - LkgRemoteMessageFmt = "using last-known-good: %s" - - // CurLocalOkayReason indicates that the Kubelet is using its local config - CurLocalOkayReason = "when the config source is nil, the Kubelet uses its local config" - // CurRemoteOkayReason indicates that the config referenced by Node.ConfigSource is currently passing all checks - CurRemoteOkayReason = "passing all checks" - - // CurFailLoadReasonFmt indicates that the Kubelet failed to load the current config checkpoint for an API source - CurFailLoadReasonFmt = "failed to load current: %s" - // CurFailParseReasonFmt indicates that the Kubelet failed to parse the current config checkpoint for an API source - CurFailParseReasonFmt = "failed to parse current: %s" - // CurFailValidateReasonFmt indicates that the Kubelet failed to validate the current config checkpoint for an API source - CurFailValidateReasonFmt = "failed to validate current: %s" - - // LkgFail*ReasonFmt reasons are currently used to print errors in the Kubelet log, but do not appear in Node.Status.Conditions - - // LkgFailLoadReasonFmt indicates that the Kubelet failed to load the last-known-good config checkpoint for an API source - LkgFailLoadReasonFmt = "failed to load last-known-good: %s" - // LkgFailParseReasonFmt indicates that the Kubelet failed to parse the last-known-good config checkpoint for an API source - LkgFailParseReasonFmt = "failed to parse last-known-good: %s" - // LkgFailValidateReasonFmt indicates that the Kubelet failed to validate the last-known-good config checkpoint for an API source - LkgFailValidateReasonFmt = "failed to validate last-known-good: %s" - - // FailSyncReasonFmt is used when the system couldn't sync the config, due to a malformed Node.Spec.ConfigSource, a download failure, etc. - FailSyncReasonFmt = "failed to sync, reason: %s" - // FailSyncReasonAllNilSubfields is used when no subfields are set - FailSyncReasonAllNilSubfields = "invalid NodeConfigSource, exactly one subfield must be non-nil, but all were nil" - // FailSyncReasonPartialObjectReference is used when some required subfields remain unset - FailSyncReasonPartialObjectReference = "invalid ObjectReference, all of UID, Name, and Namespace must be specified" - // FailSyncReasonUIDMismatchFmt is used when there is a UID mismatch between the referenced and downloaded ConfigMaps, - // this can happen because objects must be downloaded by namespace/name, rather than by UID - FailSyncReasonUIDMismatchFmt = "invalid ConfigSource.ConfigMapRef.UID: %s does not match %s.UID: %s" - // FailSyncReasonDownloadFmt is used when the download fails, e.g. due to network issues - FailSyncReasonDownloadFmt = "failed to download: %s" - // FailSyncReasonInformer is used when the informer fails to report the Node object - FailSyncReasonInformer = "failed to read Node from informer object cache" - // FailSyncReasonReset is used when we can't reset the local configuration references, e.g. due to filesystem issues - FailSyncReasonReset = "failed to reset to local config" - // FailSyncReasonCheckpointExistenceFmt is used when we can't determine if a checkpoint already exists, e.g. due to filesystem issues - FailSyncReasonCheckpointExistenceFmt = "failed to determine whether object %s with UID %s was already checkpointed" - // FailSyncReasonSaveCheckpointFmt is used when we can't save a checkpoint, e.g. due to filesystem issues - FailSyncReasonSaveCheckpointFmt = "failed to save config checkpoint for object %s with UID %s" - // FailSyncReasonSetCurrentDefault is used when we can't set the current config checkpoint to the local default, e.g. due to filesystem issues - FailSyncReasonSetCurrentLocal = "failed to set current config checkpoint to local config" - // FailSyncReasonSetCurrentUIDFmt is used when we can't set the current config checkpoint to a checkpointed object, e.g. due to filesystem issues - FailSyncReasonSetCurrentUIDFmt = "failed to set current config checkpoint to object %s with UID %s" - - // EmptyMessage is a placeholder in the case that we accidentally set the condition's message to the empty string. - // Doing so can result in a partial patch, and thus a confusing status; this makes it clear that the message was not provided. - EmptyMessage = "unknown - message not provided" - // EmptyReason is a placeholder in the case that we accidentally set the condition's reason to the empty string. - // Doing so can result in a partial patch, and thus a confusing status; this makes it clear that the reason was not provided. - EmptyReason = "unknown - reason not provided" + // LoadError indicates that the Kubelet failed to load the config checkpoint + LoadError = "failed to load config, see Kubelet log for details" + // ValidateError indicates that the Kubelet failed to validate the config checkpoint + ValidateError = "failed to validate config, see Kubelet log for details" + // AllNilSubfieldsError is used when no subfields are set + // This could happen in the case that an old client tries to read an object from a newer API server with a set subfield it does not know about + AllNilSubfieldsError = "invalid NodeConfigSource, exactly one subfield must be non-nil, but all were nil" + // DownloadError is used when the download fails, e.g. due to network issues + DownloadError = "failed to download config, see Kubelet log for details" + // InternalError indicates that some internal error happened while trying to sync config, e.g. filesystem issues + InternalError = "internal failure, see Kubelet log for details" + + // SyncErrorFmt is used when the system couldn't sync the config, due to a malformed Node.Spec.ConfigSource, a download failure, etc. + SyncErrorFmt = "failed to sync: %s" ) -// ConfigOkCondition represents a ConfigOk NodeCondition -type ConfigOkCondition interface { - // Set sets the Message, Reason, and Status of the condition - Set(message, reason string, status apiv1.ConditionStatus) - // SetFailSyncCondition sets the condition for when syncing Kubelet config fails - SetFailSyncCondition(reason string) - // ClearFailSyncCondition clears the overlay from SetFailSyncCondition - ClearFailSyncCondition() - // Sync patches the current condition into the Node identified by `nodeName` +// NodeConfigStatus represents Node.Status.Config +type NodeConfigStatus interface { + // SetActive sets the active source in the status + SetActive(source *apiv1.NodeConfigSource) + // SetAssigned sets the assigned source in the status + SetAssigned(source *apiv1.NodeConfigSource) + // SetLastKnownGood sets the last-known-good source in the status + SetLastKnownGood(source *apiv1.NodeConfigSource) + // SetError sets the error associated with the status + SetError(err string) + // SetErrorOverride sets an error that overrides the base error set by SetError. + // If the override is set to the empty string, the base error is reported in + // the status, otherwise the override is reported. + SetErrorOverride(err string) + // Sync patches the current status into the Node identified by `nodeName` if an update is pending Sync(client clientset.Interface, nodeName string) } -// configOkCondition implements ConfigOkCondition -type configOkCondition struct { - // conditionMux is a mutex on the condition, alternate between setting and syncing the condition - conditionMux sync.Mutex - // message will appear as the condition's message - message string - // reason will appear as the condition's reason - reason string - // status will appear as the condition's status - status apiv1.ConditionStatus - // failedSyncReason is sent in place of the usual reason when the Kubelet is failing to sync the remote config - failedSyncReason string - // pendingCondition; write to this channel to indicate that ConfigOk needs to be synced to the API server - pendingCondition chan bool +type nodeConfigStatus struct { + // status is the core NodeConfigStatus that we report + status apiv1.NodeConfigStatus + // mux is a mutex on the nodeConfigStatus, alternate between setting and syncing the status + mux sync.Mutex + // errorOverride is sent in place of the usual error if it is non-empty + errorOverride string + // syncCh; write to this channel to indicate that the status needs to be synced to the API server + syncCh chan bool } -// NewConfigOkCondition returns a new ConfigOkCondition -func NewConfigOkCondition() ConfigOkCondition { - return &configOkCondition{ - message: EmptyMessage, - reason: EmptyReason, - status: apiv1.ConditionUnknown, - // channels must have capacity at least 1, since we signal with non-blocking writes - pendingCondition: make(chan bool, 1), +// NewNodeConfigStatus returns a new NodeConfigStatus interface +func NewNodeConfigStatus() NodeConfigStatus { + // channels must have capacity at least 1, since we signal with non-blocking writes + syncCh := make(chan bool, 1) + // prime new status managers to sync with the API server on the first call to Sync + syncCh <- true + return &nodeConfigStatus{ + syncCh: syncCh, } } -// unsafeSet sets the current state of the condition -// it does not grab the conditionMux lock, so you should generally use setConfigOk unless you need to grab the lock -// at a higher level to synchronize additional operations -func (c *configOkCondition) unsafeSet(message, reason string, status apiv1.ConditionStatus) { - // We avoid an empty Message, Reason, or Status on the condition. Since we use Patch to update conditions, an empty - // field might cause a value from a previous condition to leak through, which can be very confusing. +// transact grabs the lock, performs the fn, records the need to sync, and releases the lock +func (s *nodeConfigStatus) transact(fn func()) { + s.mux.Lock() + defer s.mux.Unlock() + fn() + s.sync() +} - // message - if len(message) == 0 { - message = EmptyMessage - } - c.message = message - // reason - if len(reason) == 0 { - reason = EmptyReason - } - c.reason = reason - // status - if len(string(status)) == 0 { - status = apiv1.ConditionUnknown - } - c.status = status - // always poke worker after update - c.pokeSyncWorker() +func (s *nodeConfigStatus) SetAssigned(source *apiv1.NodeConfigSource) { + s.transact(func() { + s.status.Assigned = source + }) +} + +func (s *nodeConfigStatus) SetActive(source *apiv1.NodeConfigSource) { + s.transact(func() { + s.status.Active = source + }) } -func (c *configOkCondition) Set(message, reason string, status apiv1.ConditionStatus) { - c.conditionMux.Lock() - defer c.conditionMux.Unlock() - c.unsafeSet(message, reason, status) +func (s *nodeConfigStatus) SetLastKnownGood(source *apiv1.NodeConfigSource) { + s.transact(func() { + s.status.LastKnownGood = source + }) } -// SetFailSyncCondition updates the ConfigOk status to reflect that we failed to sync to the latest config, -// e.g. due to a malformed Node.Spec.ConfigSource, a download failure, etc. -func (c *configOkCondition) SetFailSyncCondition(reason string) { - c.conditionMux.Lock() - defer c.conditionMux.Unlock() - // set the reason overlay and poke the sync worker to send the update - c.failedSyncReason = fmt.Sprintf(FailSyncReasonFmt, reason) - c.pokeSyncWorker() +func (s *nodeConfigStatus) SetError(err string) { + s.transact(func() { + s.status.Error = err + }) } -// ClearFailSyncCondition removes the "failed to sync" reason overlay -func (c *configOkCondition) ClearFailSyncCondition() { - c.conditionMux.Lock() - defer c.conditionMux.Unlock() - // clear the reason overlay and poke the sync worker to send the update - c.failedSyncReason = "" - c.pokeSyncWorker() +func (s *nodeConfigStatus) SetErrorOverride(err string) { + s.transact(func() { + s.errorOverride = err + }) } -// pokeSyncWorker notes that the ConfigOk condition needs to be synced to the API server -func (c *configOkCondition) pokeSyncWorker() { +// sync notes that the status needs to be synced to the API server +func (s *nodeConfigStatus) sync() { select { - case c.pendingCondition <- true: + case s.syncCh <- true: default: } } -// Sync attempts to sync `c.condition` with the Node object for this Kubelet, +// Sync attempts to sync the status with the Node object for this Kubelet, // if syncing fails, an error is logged, and work is queued for retry. -func (c *configOkCondition) Sync(client clientset.Interface, nodeName string) { +func (s *nodeConfigStatus) Sync(client clientset.Interface, nodeName string) { select { - case <-c.pendingCondition: + case <-s.syncCh: default: // no work to be done, return return } + utillog.Infof("updating Node.Status.Config") + // grab the lock - c.conditionMux.Lock() - defer c.conditionMux.Unlock() + s.mux.Lock() + defer s.mux.Unlock() // if the sync fails, we want to retry var err error defer func() { if err != nil { utillog.Errorf(err.Error()) - c.pokeSyncWorker() + s.sync() } }() - // get the Node so we can check the current condition - node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) + // get the Node so we can check the current status + oldNode, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) if err != nil { - err = fmt.Errorf("could not get Node %q, will not sync ConfigOk condition, error: %v", nodeName, err) - return - } - - // construct the node condition - condition := &apiv1.NodeCondition{ - Type: apiv1.NodeKubeletConfigOk, - Message: c.message, - Reason: c.reason, - Status: c.status, - } - - // overlay failed sync reason, if necessary - if len(c.failedSyncReason) > 0 { - condition.Reason = c.failedSyncReason - condition.Status = apiv1.ConditionFalse - } - - // set timestamps - syncTime := metav1.NewTime(time.Now()) - condition.LastHeartbeatTime = syncTime - if remote := getKubeletConfigOk(node.Status.Conditions); remote == nil || !utilequal.KubeletConfigOkEq(remote, condition) { - // update transition time the first time we create the condition, - // or if we are semantically changing the condition - condition.LastTransitionTime = syncTime - } else { - // since the conditions are semantically equal, use lastTransitionTime from the condition currently on the Node - // we need to do this because the field will always be represented in the patch generated below, and this copy - // prevents nullifying the field during the patch operation - condition.LastTransitionTime = remote.LastTransitionTime - } - - // generate the patch - mediaType := "application/json" - info, ok := kuberuntime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), mediaType) - if !ok { - err = fmt.Errorf("unsupported media type %q", mediaType) - return - } - versions := legacyscheme.Registry.EnabledVersionsForGroup(api.GroupName) - if len(versions) == 0 { - err = fmt.Errorf("no enabled versions for group %q", api.GroupName) + err = fmt.Errorf("could not get Node %q, will not sync status, error: %v", nodeName, err) return } - // the "best" version supposedly comes first in the list returned from apiv1.Registry.EnabledVersionsForGroup - encoder := legacyscheme.Codecs.EncoderForVersion(info.Serializer, versions[0]) - before, err := kuberuntime.Encode(encoder, node) - if err != nil { - err = fmt.Errorf(`failed to encode "before" node while generating patch, error: %v`, err) - return + status := &s.status + // override error, if necessary + if len(s.errorOverride) > 0 { + // copy the status, so we don't overwrite the prior error + // with the override + status = status.DeepCopy() + status.Error = s.errorOverride } - patchConfigOk(node, condition) - after, err := kuberuntime.Encode(encoder, node) + // update metrics based on the status we will sync + metrics.SetConfigError(len(status.Error) > 0) + err = metrics.SetAssignedConfig(status.Assigned) if err != nil { - err = fmt.Errorf(`failed to encode "after" node while generating patch, error: %v`, err) + err = fmt.Errorf("failed to update Assigned config metric, error: %v", err) return } - - patch, err := strategicpatch.CreateTwoWayMergePatch(before, after, apiv1.Node{}) + err = metrics.SetActiveConfig(status.Active) if err != nil { - err = fmt.Errorf("failed to generate patch for updating ConfigOk condition, error: %v", err) + err = fmt.Errorf("failed to update Active config metric, error: %v", err) return } - - // patch the remote Node object - _, err = client.CoreV1().Nodes().PatchStatus(nodeName, patch) + err = metrics.SetLastKnownGoodConfig(status.LastKnownGood) if err != nil { - err = fmt.Errorf("could not update ConfigOk condition, error: %v", err) + err = fmt.Errorf("failed to update LastKnownGood config metric, error: %v", err) return } -} -// patchConfigOk replaces or adds the ConfigOk condition to the node -func patchConfigOk(node *apiv1.Node, configOk *apiv1.NodeCondition) { - for i := range node.Status.Conditions { - if node.Status.Conditions[i].Type == apiv1.NodeKubeletConfigOk { - // edit the condition - node.Status.Conditions[i] = *configOk - return - } - } - // append the condition - node.Status.Conditions = append(node.Status.Conditions, *configOk) -} + // apply the status to a copy of the node so we don't modify the object in the informer's store + newNode := oldNode.DeepCopy() + newNode.Status.Config = status -// getKubeletConfigOk returns the first NodeCondition in `cs` with Type == apiv1.NodeKubeletConfigOk, -// or if no such condition exists, returns nil. -func getKubeletConfigOk(cs []apiv1.NodeCondition) *apiv1.NodeCondition { - for i := range cs { - if cs[i].Type == apiv1.NodeKubeletConfigOk { - return &cs[i] - } + // patch the node with the new status + if _, _, err := nodeutil.PatchNodeStatus(client.CoreV1(), types.NodeName(nodeName), oldNode, newNode); err != nil { + utillog.Errorf("failed to patch node status, error: %v", err) } - return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/BUILD index 50b123e7a..43ea8c214 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/BUILD @@ -13,7 +13,9 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core/install:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/scheme: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:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/codec.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/codec.go index 3316f955a..b8356fabd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/codec.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/codec.go @@ -23,23 +23,51 @@ import ( _ "k8s.io/kubernetes/pkg/apis/core/install" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" ) -// TODO(mtaufen): allow an encoder to be injected into checkpoint objects at creation time? (then we could ultimately instantiate only one encoder) +// EncodeKubeletConfig encodes an internal KubeletConfiguration to an external YAML representation +func EncodeKubeletConfig(internal *kubeletconfig.KubeletConfiguration, targetVersion schema.GroupVersion) ([]byte, error) { + encoder, err := NewKubeletconfigYAMLEncoder(targetVersion) + if err != nil { + return nil, err + } + // encoder will convert to external version + data, err := runtime.Encode(encoder, internal) + if err != nil { + return nil, err + } + return data, nil +} + +// NewKubeletconfigYAMLEncoder returns an encoder that can write objects in the kubeletconfig API group to YAML +func NewKubeletconfigYAMLEncoder(targetVersion schema.GroupVersion) (runtime.Encoder, error) { + _, codecs, err := scheme.NewSchemeAndCodecs() + if err != nil { + return nil, err + } + mediaType := "application/yaml" + info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType) + if !ok { + return nil, fmt.Errorf("unsupported media type %q", mediaType) + } + return codecs.EncoderForVersion(info.Serializer, targetVersion), nil +} -// NewJSONEncoder generates a new runtime.Encoder that encodes objects to JSON -func NewJSONEncoder(groupName string) (runtime.Encoder, error) { - // encode to json - mediaType := "application/json" +// NewYAMLEncoder generates a new runtime.Encoder that encodes objects to YAML +func NewYAMLEncoder(groupName string) (runtime.Encoder, error) { + // encode to YAML + mediaType := "application/yaml" info, ok := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), mediaType) if !ok { return nil, fmt.Errorf("unsupported media type %q", mediaType) } - versions := legacyscheme.Registry.EnabledVersionsForGroup(groupName) + versions := legacyscheme.Scheme.PrioritizedVersionsForGroup(groupName) if len(versions) == 0 { return nil, fmt.Errorf("no enabled versions for group %q", groupName) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/equal/equal.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/equal/equal.go index 5a59edb94..b943e019f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/equal/equal.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/equal/equal.go @@ -18,33 +18,6 @@ package equal import apiv1 "k8s.io/api/core/v1" -// ConfigSourceEq returns true if the two config sources are semantically equivalent in the context of dynamic config -func ConfigSourceEq(a, b *apiv1.NodeConfigSource) bool { - if a == b { - return true - } else if a == nil || b == nil { - // not equal, and one is nil - return false - } - // check equality of config source subifelds - if a.ConfigMapRef != b.ConfigMapRef { - return ObjectRefEq(a.ConfigMapRef, b.ConfigMapRef) - } - // all internal subfields of the config source are equal - return true -} - -// ObjectRefEq returns true if the two object references are semantically equivalent in the context of dynamic config -func ObjectRefEq(a, b *apiv1.ObjectReference) bool { - if a == b { - return true - } else if a == nil || b == nil { - // not equal, and one is nil - return false - } - return a.UID == b.UID && a.Namespace == b.Namespace && a.Name == b.Name -} - // KubeletConfigOkEq returns true if the two conditions are semantically equivalent in the context of dynamic config func KubeletConfigOkEq(a, b *apiv1.NodeCondition) bool { return a.Message == b.Message && a.Reason == b.Reason && a.Status == b.Status diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/BUILD index ae93b6f99..5f6e0c1e0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/BUILD @@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( @@ -24,3 +25,13 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["files_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/kubelet/kubeletconfig/util/test:go_default_library", + "//pkg/util/filesystem:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files.go index aa76e151d..fc42151a7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files.go @@ -24,7 +24,10 @@ import ( utilfs "k8s.io/kubernetes/pkg/util/filesystem" ) -const defaultPerm = 0666 +const ( + defaultPerm = 0755 + tmptag = "tmp_" // additional prefix to prevent accidental collisions +) // FileExists returns true if a regular file exists at `path`, false if `path` does not exist, otherwise an error func FileExists(fs utilfs.Filesystem, path string) (bool, error) { @@ -64,9 +67,10 @@ func EnsureFile(fs utilfs.Filesystem, path string) error { } // WriteTmpFile creates a temporary file at `path`, writes `data` into it, and fsyncs the file +// Expects the parent directory to exist. func WriteTmpFile(fs utilfs.Filesystem, path string, data []byte) (tmpPath string, retErr error) { dir := filepath.Dir(path) - prefix := filepath.Base(path) + prefix := tmptag + filepath.Base(path) // create the tmp file tmpFile, err := fs.TempFile(dir, prefix) @@ -81,7 +85,7 @@ func WriteTmpFile(fs utilfs.Filesystem, path string, data []byte) (tmpPath strin // if there was an error writing, syncing, or closing, delete the temporary file and return the error if retErr != nil { if err := fs.Remove(tmpPath); err != nil { - retErr = fmt.Errorf("attempted to remove temporary file %q after error %v, but failed due to error: %v", path, retErr, err) + retErr = fmt.Errorf("attempted to remove temporary file %q after error %v, but failed due to error: %v", tmpPath, retErr, err) } tmpPath = "" } @@ -100,7 +104,8 @@ func WriteTmpFile(fs utilfs.Filesystem, path string, data []byte) (tmpPath strin } // ReplaceFile replaces the contents of the file at `path` with `data` by writing to a tmp file in the same -// dir as `path` and renaming the tmp file over `path`. The file does not have to exist to use ReplaceFile. +// dir as `path` and renaming the tmp file over `path`. The file does not have to exist to use ReplaceFile, +// but the parent directory must exist. // Note ReplaceFile calls fsync. func ReplaceFile(fs utilfs.Filesystem, path string, data []byte) error { // write data to a temporary file @@ -118,7 +123,7 @@ func DirExists(fs utilfs.Filesystem, path string) (bool, error) { if info.IsDir() { return true, nil } - return false, fmt.Errorf("expected dir at %q, but mode is is %q", path, info.Mode().String()) + return false, fmt.Errorf("expected dir at %q, but mode is %q", path, info.Mode().String()) } else if os.IsNotExist(err) { return false, nil } else { @@ -137,3 +142,88 @@ func EnsureDir(fs utilfs.Filesystem, path string) error { // create the dir return fs.MkdirAll(path, defaultPerm) } + +// WriteTempDir creates a temporary dir at `path`, writes `files` into it, and fsyncs all the files +// The keys of `files` represent file names. These names must not: +// - be empty +// - be a path that contains more than the base name of a file (e.g. foo/bar is invalid, as is /bar) +// - match `.` or `..` exactly +// - be longer than 255 characters +// The above validation rules are based on atomic_writer.go, though in this case are more restrictive +// because we only allow a flat hierarchy. +func WriteTempDir(fs utilfs.Filesystem, path string, files map[string]string) (tmpPath string, retErr error) { + // validate the filename keys; for now we only allow a flat keyset + for name := range files { + // invalidate empty names + if name == "" { + return "", fmt.Errorf("invalid file key: must not be empty: %q", name) + } + // invalidate: foo/bar and /bar + if name != filepath.Base(name) { + return "", fmt.Errorf("invalid file key %q, only base names are allowed", name) + } + // invalidate `.` and `..` + if name == "." || name == ".." { + return "", fmt.Errorf("invalid file key, may not be '.' or '..'") + } + // invalidate length > 255 characters + if len(name) > 255 { + return "", fmt.Errorf("invalid file key %q, must be less than 255 characters", name) + } + } + + // write the temp directory in parent dir and return path to the tmp directory + dir := filepath.Dir(path) + prefix := tmptag + filepath.Base(path) + + // create the tmp dir + var err error + tmpPath, err = fs.TempDir(dir, prefix) + if err != nil { + return "", err + } + // be sure to clean up if there was an error + defer func() { + if retErr != nil { + if err := fs.RemoveAll(tmpPath); err != nil { + retErr = fmt.Errorf("attempted to remove temporary directory %q after error %v, but failed due to error: %v", tmpPath, retErr, err) + } + } + }() + // write data + for name, data := range files { + // create the file + file, err := fs.Create(filepath.Join(tmpPath, name)) + if err != nil { + return tmpPath, err + } + // be sure to close the file when we're done + defer func() { + // close the file when we're done, don't overwrite primary retErr if close fails + if err := file.Close(); retErr == nil { + retErr = err + } + }() + // write the file + if _, err := file.Write([]byte(data)); err != nil { + return tmpPath, err + } + // sync the file, to ensure it's written in case a hard reset happens + if err := file.Sync(); err != nil { + return tmpPath, err + } + } + return tmpPath, nil +} + +// ReplaceDir replaces the contents of the dir at `path` with `files` by writing to a tmp dir in the same +// dir as `path` and renaming the tmp dir over `path`. The dir does not have to exist to use ReplaceDir. +func ReplaceDir(fs utilfs.Filesystem, path string, files map[string]string) error { + // write data to a temporary directory + tmpPath, err := WriteTempDir(fs, path, files) + if err != nil { + return err + } + // rename over target directory + return fs.Rename(tmpPath, path) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files_test.go new file mode 100644 index 000000000..4917679ab --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files_test.go @@ -0,0 +1,476 @@ +/* +Copyright 2018 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 files + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test" + utilfs "k8s.io/kubernetes/pkg/util/filesystem" +) + +const ( + prefix = "test-util-files" +) + +type file struct { + name string + // mode distinguishes file type, + // we only check for regular vs. directory in these tests, + // specify regular as 0, directory as os.ModeDir + mode os.FileMode + data string // ignored if mode == os.ModeDir +} + +func (f *file) write(fs utilfs.Filesystem, dir string) error { + path := filepath.Join(dir, f.name) + if f.mode.IsDir() { + if err := fs.MkdirAll(path, defaultPerm); err != nil { + return err + } + } else if f.mode.IsRegular() { + // create parent directories, if necessary + parents := filepath.Dir(path) + if err := fs.MkdirAll(parents, defaultPerm); err != nil { + return err + } + // create the file + handle, err := fs.Create(path) + if err != nil { + return err + } + _, err = handle.Write([]byte(f.data)) + if err != nil { + if cerr := handle.Close(); cerr != nil { + return fmt.Errorf("error %v closing file after error: %v", cerr, err) + } + return err + } + } else { + return fmt.Errorf("mode not implemented for testing %s", f.mode.String()) + } + return nil +} + +func (f *file) expect(fs utilfs.Filesystem, dir string) error { + path := filepath.Join(dir, f.name) + if f.mode.IsDir() { + info, err := fs.Stat(path) + if err != nil { + return err + } + if !info.IsDir() { + return fmt.Errorf("expected directory, got mode %s", info.Mode().String()) + } + } else if f.mode.IsRegular() { + info, err := fs.Stat(path) + if err != nil { + return err + } + if !info.Mode().IsRegular() { + return fmt.Errorf("expected regular file, got mode %s", info.Mode().String()) + } + data, err := fs.ReadFile(path) + if err != nil { + return err + } + if f.data != string(data) { + return fmt.Errorf("expected file data %q, got %q", f.data, string(data)) + } + } else { + return fmt.Errorf("mode not implemented for testing %s", f.mode.String()) + } + return nil +} + +// write files, perform some function, then attempt to read files back +// if err is non-empty, expects an error from the function performed in the test +// and skips reading back the expected files +type test struct { + desc string + writes []file + expects []file + fn func(fs utilfs.Filesystem, dir string, c *test) []error + err string +} + +func (c *test) write(t *testing.T, fs utilfs.Filesystem, dir string) { + for _, f := range c.writes { + if err := f.write(fs, dir); err != nil { + t.Fatalf("error pre-writing file: %v", err) + } + } +} + +// you can optionally skip calling t.Errorf by passing a nil t, and process the +// returned errors instead +func (c *test) expect(t *testing.T, fs utilfs.Filesystem, dir string) []error { + errs := []error{} + for _, f := range c.expects { + if err := f.expect(fs, dir); err != nil { + msg := fmt.Errorf("expect %#v, got error: %v", f, err) + errs = append(errs, msg) + if t != nil { + t.Errorf("%s", msg) + } + } + } + return errs +} + +// run a test case, with an arbitrary function to execute between write and expect +// if c.fn is nil, errors from c.expect are checked against c.err, instead of errors +// from fn being checked against c.err +func (c *test) run(t *testing.T, fs utilfs.Filesystem) { + // isolate each test case in a new temporary directory + dir, err := fs.TempDir("", prefix) + if err != nil { + t.Fatalf("error creating temporary directory for test: %v", err) + } + c.write(t, fs, dir) + // if fn exists, check errors from fn, then check expected files + if c.fn != nil { + errs := c.fn(fs, dir, c) + if len(errs) > 0 { + for _, err := range errs { + utiltest.ExpectError(t, err, c.err) + } + // skip checking expected files if we expected errors + // (usually means we didn't create file) + return + } + c.expect(t, fs, dir) + return + } + // just check expected files, and compare errors from c.expect to c.err + // (this lets us test the helper functions above) + errs := c.expect(nil, fs, dir) + for _, err := range errs { + utiltest.ExpectError(t, err, c.err) + } +} + +// simple test of the above helper functions +func TestHelpers(t *testing.T) { + // omitting the test.fn means test.err is compared to errors from test.expect + cases := []test{ + { + desc: "regular file", + writes: []file{{name: "foo", data: "bar"}}, + expects: []file{{name: "foo", data: "bar"}}, + }, + { + desc: "directory", + writes: []file{{name: "foo", mode: os.ModeDir}}, + expects: []file{{name: "foo", mode: os.ModeDir}}, + }, + { + desc: "deep regular file", + writes: []file{{name: "foo/bar", data: "baz"}}, + expects: []file{{name: "foo/bar", data: "baz"}}, + }, + { + desc: "deep directory", + writes: []file{{name: "foo/bar", mode: os.ModeDir}}, + expects: []file{{name: "foo/bar", mode: os.ModeDir}}, + }, + { + desc: "missing file", + expects: []file{{name: "foo", data: "bar"}}, + err: "no such file or directory", + }, + { + desc: "missing directory", + expects: []file{{name: "foo/bar", mode: os.ModeDir}}, + err: "no such file or directory", + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + c.run(t, utilfs.DefaultFs{}) + }) + } +} + +func TestFileExists(t *testing.T) { + fn := func(fs utilfs.Filesystem, dir string, c *test) []error { + ok, err := FileExists(fs, filepath.Join(dir, "foo")) + if err != nil { + return []error{err} + } + if !ok { + return []error{fmt.Errorf("does not exist (test)")} + } + return nil + } + cases := []test{ + { + fn: fn, + desc: "file exists", + writes: []file{{name: "foo"}}, + }, + { + fn: fn, + desc: "file does not exist", + err: "does not exist (test)", + }, + { + fn: fn, + desc: "object has non-file mode", + writes: []file{{name: "foo", mode: os.ModeDir}}, + err: "expected regular file", + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + c.run(t, utilfs.DefaultFs{}) + }) + } +} + +func TestEnsureFile(t *testing.T) { + fn := func(fs utilfs.Filesystem, dir string, c *test) []error { + var errs []error + for _, f := range c.expects { + if err := EnsureFile(fs, filepath.Join(dir, f.name)); err != nil { + errs = append(errs, err) + } + } + return errs + } + cases := []test{ + { + fn: fn, + desc: "file exists", + writes: []file{{name: "foo"}}, + expects: []file{{name: "foo"}}, + }, + { + fn: fn, + desc: "file does not exist", + expects: []file{{name: "bar"}}, + }, + { + fn: fn, + desc: "neither parent nor file exists", + expects: []file{{name: "baz/quux"}}, + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + c.run(t, utilfs.DefaultFs{}) + }) + } +} + +// Note: This transitively tests WriteTmpFile +func TestReplaceFile(t *testing.T) { + fn := func(fs utilfs.Filesystem, dir string, c *test) []error { + var errs []error + for _, f := range c.expects { + if err := ReplaceFile(fs, filepath.Join(dir, f.name), []byte(f.data)); err != nil { + errs = append(errs, err) + } + } + return errs + } + cases := []test{ + { + fn: fn, + desc: "file exists", + writes: []file{{name: "foo"}}, + expects: []file{{name: "foo", data: "bar"}}, + }, + { + fn: fn, + desc: "file does not exist", + expects: []file{{name: "foo", data: "bar"}}, + }, + { + fn: func(fs utilfs.Filesystem, dir string, c *test) []error { + if err := ReplaceFile(fs, filepath.Join(dir, "foo/bar"), []byte("")); err != nil { + return []error{err} + } + return nil + }, + desc: "neither parent nor file exists", + err: "no such file or directory", + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + c.run(t, utilfs.DefaultFs{}) + }) + } +} + +func TestDirExists(t *testing.T) { + fn := func(fs utilfs.Filesystem, dir string, c *test) []error { + ok, err := DirExists(fs, filepath.Join(dir, "foo")) + if err != nil { + return []error{err} + } + if !ok { + return []error{fmt.Errorf("does not exist (test)")} + } + return nil + } + cases := []test{ + { + fn: fn, + desc: "dir exists", + writes: []file{{name: "foo", mode: os.ModeDir}}, + }, + { + fn: fn, + desc: "dir does not exist", + err: "does not exist (test)", + }, + { + fn: fn, + desc: "object has non-dir mode", + writes: []file{{name: "foo"}}, + err: "expected dir", + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + c.run(t, utilfs.DefaultFs{}) + }) + } +} + +func TestEnsureDir(t *testing.T) { + fn := func(fs utilfs.Filesystem, dir string, c *test) []error { + var errs []error + for _, f := range c.expects { + if err := EnsureDir(fs, filepath.Join(dir, f.name)); err != nil { + errs = append(errs, err) + } + } + return errs + } + cases := []test{ + { + fn: fn, + desc: "dir exists", + writes: []file{{name: "foo", mode: os.ModeDir}}, + expects: []file{{name: "foo", mode: os.ModeDir}}, + }, + { + fn: fn, + desc: "dir does not exist", + expects: []file{{name: "bar", mode: os.ModeDir}}, + }, + { + fn: fn, + desc: "neither parent nor dir exists", + expects: []file{{name: "baz/quux", mode: os.ModeDir}}, + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + c.run(t, utilfs.DefaultFs{}) + }) + } +} + +func TestWriteTempDir(t *testing.T) { + // writing a tmp dir is covered by TestReplaceDir, but we additionally test filename validation here + c := test{ + desc: "invalid file key", + err: "invalid file key", + fn: func(fs utilfs.Filesystem, dir string, c *test) []error { + if _, err := WriteTempDir(fs, filepath.Join(dir, "tmpdir"), map[string]string{"foo/bar": ""}); err != nil { + return []error{err} + } + return nil + }, + } + c.run(t, utilfs.DefaultFs{}) +} + +func TestReplaceDir(t *testing.T) { + fn := func(fs utilfs.Filesystem, dir string, c *test) []error { + errs := []error{} + + // compute filesets from expected files and call ReplaceDir for each + // we don't nest dirs in test cases, order of ReplaceDir call is not guaranteed + dirs := map[string]map[string]string{} + + // allocate dirs + for _, f := range c.expects { + if f.mode.IsDir() { + path := filepath.Join(dir, f.name) + if _, ok := dirs[path]; !ok { + dirs[path] = map[string]string{} + } + } else if f.mode.IsRegular() { + path := filepath.Join(dir, filepath.Dir(f.name)) + if _, ok := dirs[path]; !ok { + // require an expectation for the parent directory if there is an expectation for the file + errs = append(errs, fmt.Errorf("no prior parent directory in c.expects for file %s", f.name)) + continue + } + dirs[path][filepath.Base(f.name)] = f.data + } + } + + // short-circuit test case validation errors + if len(errs) > 0 { + return errs + } + + // call ReplaceDir for each desired dir + for path, files := range dirs { + if err := ReplaceDir(fs, path, files); err != nil { + errs = append(errs, err) + } + } + return errs + } + cases := []test{ + { + fn: fn, + desc: "fn catches invalid test case", + expects: []file{{name: "foo/bar"}}, + err: "no prior parent directory", + }, + { + fn: fn, + desc: "empty dir", + expects: []file{{name: "foo", mode: os.ModeDir}}, + }, + { + fn: fn, + desc: "dir with files", + expects: []file{ + {name: "foo", mode: os.ModeDir}, + {name: "foo/bar", data: "baz"}, + {name: "foo/baz", data: "bar"}, + }, + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + c.run(t, utilfs.DefaultFs{}) + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test/test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test/test.go index 1c18e8344..789246ecd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test/test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test/test.go @@ -21,6 +21,21 @@ import ( "testing" ) +// ExpectError calls t.Fatalf if the error does not contain a substr match. +// If substr is empty, a nil error is expected. +// It is useful to call ExpectError from subtests. +func ExpectError(t *testing.T, err error, substr string) { + if err != nil { + if len(substr) == 0 { + t.Fatalf("expect nil error but got %q", err.Error()) + } else if !strings.Contains(err.Error(), substr) { + t.Fatalf("expect error to contain %q but got %q", substr, err.Error()) + } + } else if len(substr) > 0 { + t.Fatalf("expect error to contain %q but got nil error", substr) + } +} + // SkipRest returns true if there was a non-nil error or if we expected an error that didn't happen, // and logs the appropriate error on the test object. // The return value indicates whether we should skip the rest of the test case due to the error result. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/watch.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/watch.go index 8c02e3c9a..879fb747c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/watch.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/watch.go @@ -21,13 +21,13 @@ import ( "time" apiv1 "k8s.io/api/core/v1" + apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" kuberuntime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" - utilequal "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/equal" utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log" ) @@ -86,6 +86,7 @@ func (cc *Controller) onUpdateNodeEvent(oldObj interface{}, newObj interface{}) } if oldObj == nil { // Node was just added, need to sync + utillog.Infof("initial Node watch event") cc.pokeConfigSourceWorker() return } @@ -94,32 +95,60 @@ func (cc *Controller) onUpdateNodeEvent(oldObj interface{}, newObj interface{}) utillog.Errorf("failed to cast old object to Node, couldn't handle event") return } - if !utilequal.ConfigSourceEq(oldNode.Spec.ConfigSource, newNode.Spec.ConfigSource) { + if !apiequality.Semantic.DeepEqual(oldNode.Spec.ConfigSource, newNode.Spec.ConfigSource) { + utillog.Infof("Node.Spec.ConfigSource was updated") cc.pokeConfigSourceWorker() } } -// onDeleteNodeEvent logs a message if the Node was deleted and may log errors -// if an unexpected DeletedFinalStateUnknown was received. +// onDeleteNodeEvent logs a message if the Node was deleted // We allow the sync-loop to continue, because it is possible that the Kubelet detected // a Node with unexpected externalID and is attempting to delete and re-create the Node // (see pkg/kubelet/kubelet_node_status.go), or that someone accidentally deleted the Node // (the Kubelet will re-create it). func (cc *Controller) onDeleteNodeEvent(deletedObj interface{}) { - node, ok := deletedObj.(*apiv1.Node) + // For this case, we just log the event. + // We don't want to poke the worker, because a temporary deletion isn't worth reporting an error for. + // If the Node is deleted because the VM is being deleted, then the Kubelet has nothing to do. + utillog.Infof("Node was deleted") +} + +// onAddRemoteConfigSourceEvent calls onUpdateConfigMapEvent with the new object and a nil old object +func (cc *Controller) onAddRemoteConfigSourceEvent(newObj interface{}) { + cc.onUpdateRemoteConfigSourceEvent(nil, newObj) +} + +// onUpdateRemoteConfigSourceEvent checks whether the configSource changed between oldObj and newObj, +// and pokes the sync worker if there was a change +func (cc *Controller) onUpdateRemoteConfigSourceEvent(oldObj interface{}, newObj interface{}) { + // since ConfigMap is currently the only source type, we handle that here + newConfigMap, ok := newObj.(*apiv1.ConfigMap) if !ok { - tombstone, ok := deletedObj.(cache.DeletedFinalStateUnknown) - if !ok { - utillog.Errorf("couldn't cast deleted object to DeletedFinalStateUnknown, object: %+v", deletedObj) - return - } - node, ok = tombstone.Obj.(*apiv1.Node) - if !ok { - utillog.Errorf("received DeletedFinalStateUnknown object but it did not contain a Node, object: %+v", deletedObj) - return - } - utillog.Infof("Node was deleted (DeletedFinalStateUnknown), sync-loop will continue because the Kubelet might recreate the Node, node: %+v", node) + utillog.Errorf("failed to cast new object to ConfigMap, couldn't handle event") + return + } + if oldObj == nil { + // ConfigMap was just added, need to sync + utillog.Infof("initial ConfigMap watch event") + cc.pokeConfigSourceWorker() return } - utillog.Infof("Node was deleted, sync-loop will continue because the Kubelet might recreate the Node, node: %+v", node) + oldConfigMap, ok := oldObj.(*apiv1.ConfigMap) + if !ok { + utillog.Errorf("failed to cast old object to ConfigMap, couldn't handle event") + return + } + if !apiequality.Semantic.DeepEqual(oldConfigMap, newConfigMap) { + utillog.Infof("assigned ConfigMap was updated") + cc.pokeConfigSourceWorker() + } +} + +// onDeleteRemoteConfigSourceEvent logs a message if the ConfigMap was deleted and pokes the sync worker +func (cc *Controller) onDeleteRemoteConfigSourceEvent(deletedObj interface{}) { + // If the ConfigMap we're watching is deleted, we log the event and poke the sync worker. + // This requires a sync, because if the Node is still configured to use the deleted ConfigMap, + // the Kubelet should report a DownloadError. + utillog.Infof("assigned ConfigMap was deleted") + cc.pokeConfigSourceWorker() } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/BUILD index 7fc904d31..29121b944 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/BUILD @@ -72,7 +72,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/kubelet/kuberuntime", deps = [ "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/credentialprovider:go_default_library", "//pkg/credentialprovider/secrets:go_default_library", "//pkg/features:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/helpers.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/helpers.go index a1e6119a2..d52faa064 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/helpers.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/helpers.go @@ -26,7 +26,6 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" utilfeature "k8s.io/apiserver/pkg/util/feature" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/features" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" @@ -191,24 +190,6 @@ func toKubeRuntimeStatus(status *runtimeapi.RuntimeStatus) *kubecontainer.Runtim return &kubecontainer.RuntimeStatus{Conditions: conditions} } -// getSysctlsFromAnnotations gets sysctls and unsafeSysctls from annotations. -func getSysctlsFromAnnotations(annotations map[string]string) (map[string]string, error) { - apiSysctls, apiUnsafeSysctls, err := v1helper.SysctlsFromPodAnnotations(annotations) - if err != nil { - return nil, err - } - - sysctls := make(map[string]string) - for _, c := range apiSysctls { - sysctls[c.Name] = c.Value - } - for _, c := range apiUnsafeSysctls { - sysctls[c.Name] = c.Value - } - - return sysctls, nil -} - // getSeccompProfileFromAnnotations gets seccomp profile from annotations. // It gets pod's profile if containerName is empty. func (m *kubeGenericRuntimeManager) getSeccompProfileFromAnnotations(annotations map[string]string, containerName string) string { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/helpers_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/helpers_test.go index 473796200..0db2ad4d7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/helpers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/helpers_test.go @@ -56,46 +56,6 @@ func TestStableKey(t *testing.T) { assert.NotEqual(t, oldKey, newKey) } -// TestGetSystclsFromAnnotations tests the logic of getting sysctls from annotations. -func TestGetSystclsFromAnnotations(t *testing.T) { - tests := []struct { - annotations map[string]string - expectedSysctls map[string]string - }{{ - annotations: map[string]string{ - v1.SysctlsPodAnnotationKey: "kernel.shmmni=32768,kernel.shmmax=1000000000", - v1.UnsafeSysctlsPodAnnotationKey: "knet.ipv4.route.min_pmtu=1000", - }, - expectedSysctls: map[string]string{ - "kernel.shmmni": "32768", - "kernel.shmmax": "1000000000", - "knet.ipv4.route.min_pmtu": "1000", - }, - }, { - annotations: map[string]string{ - v1.SysctlsPodAnnotationKey: "kernel.shmmni=32768,kernel.shmmax=1000000000", - }, - expectedSysctls: map[string]string{ - "kernel.shmmni": "32768", - "kernel.shmmax": "1000000000", - }, - }, { - annotations: map[string]string{ - v1.UnsafeSysctlsPodAnnotationKey: "knet.ipv4.route.min_pmtu=1000", - }, - expectedSysctls: map[string]string{ - "knet.ipv4.route.min_pmtu": "1000", - }, - }} - - for i, test := range tests { - actualSysctls, err := getSysctlsFromAnnotations(test.annotations) - assert.NoError(t, err, "TestCase[%d]", i) - assert.Len(t, actualSysctls, len(test.expectedSysctls), "TestCase[%d]", i) - assert.Equal(t, test.expectedSysctls, actualSysctls, "TestCase[%d]", i) - } -} - func TestToKubeContainer(t *testing.T) { c := &runtimeapi.Container{ Id: "test-id", @@ -231,20 +191,35 @@ func TestGetSeccompProfileFromAnnotations(t *testing.T) { containerName: "container1", expectedProfile: "", }, + { + description: "pod runtime/default seccomp profile should return runtime/default", + annotation: map[string]string{ + v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault, + }, + expectedProfile: v1.SeccompProfileRuntimeDefault, + }, { description: "pod docker/default seccomp profile should return docker/default", annotation: map[string]string{ - v1.SeccompPodAnnotationKey: "docker/default", + v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault, }, - expectedProfile: "docker/default", + expectedProfile: v1.DeprecatedSeccompProfileDockerDefault, + }, + { + description: "pod runtime/default seccomp profile with containerName should return runtime/default", + annotation: map[string]string{ + v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault, + }, + containerName: "container1", + expectedProfile: v1.SeccompProfileRuntimeDefault, }, { description: "pod docker/default seccomp profile with containerName should return docker/default", annotation: map[string]string{ - v1.SeccompPodAnnotationKey: "docker/default", + v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault, }, containerName: "container1", - expectedProfile: "docker/default", + expectedProfile: v1.DeprecatedSeccompProfileDockerDefault, }, { description: "pod unconfined seccomp profile should return unconfined", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go index ec9f29535..4f2444dd8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -150,9 +150,15 @@ func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandb legacySymlink := legacyLogSymlink(containerID, containerMeta.Name, sandboxMeta.Name, sandboxMeta.Namespace) containerLog := filepath.Join(podSandboxConfig.LogDirectory, containerConfig.LogPath) - if err := m.osInterface.Symlink(containerLog, legacySymlink); err != nil { - glog.Errorf("Failed to create legacy symbolic link %q to container %q log %q: %v", - legacySymlink, containerID, containerLog, err) + // only create legacy symlink if containerLog path exists (or the error is not IsNotExist). + // Because if containerLog path does not exist, only dandling legacySymlink is created. + // This dangling legacySymlink is later removed by container gc, so it does not make sense + // to create it in the first place. it happens when journald logging driver is used with docker. + if _, err := m.osInterface.Stat(containerLog); !os.IsNotExist(err) { + if err := m.osInterface.Symlink(containerLog, legacySymlink); err != nil { + glog.Errorf("Failed to create legacy symbolic link %q to container %q log %q: %v", + legacySymlink, containerID, containerLog, err) + } } // Step 4: execute the post start hook. @@ -730,10 +736,7 @@ func (m *kubeGenericRuntimeManager) GetContainerLogs(pod *v1.Pod, containerID ku glog.V(4).Infof("failed to get container status for %v: %v", containerID.String(), err) return fmt.Errorf("Unable to retrieve container logs for %v", containerID.String()) } - labeledInfo := getContainerInfoFromLabels(status.Labels) - annotatedInfo := getContainerInfoFromAnnotations(status.Annotations) - path := buildFullContainerLogsPath(pod.UID, labeledInfo.ContainerName, annotatedInfo.RestartCount) - return m.ReadLogs(path, containerID.ID, logOptions, stdout, stderr) + return m.ReadLogs(status.GetLogPath(), containerID.ID, logOptions, stdout, stderr) } // GetExec gets the endpoint the runtime will serve the exec request from. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go index 3ab880312..d04b20f74 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go @@ -64,6 +64,8 @@ func TestGenerateContainerConfig(t *testing.T) { _, imageService, m, err := createTestRuntimeManager() assert.NoError(t, err) + runAsUser := int64(1000) + runAsGroup := int64(2000) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ UID: "12345678", @@ -78,6 +80,10 @@ func TestGenerateContainerConfig(t *testing.T) { ImagePullPolicy: v1.PullIfNotPresent, Command: []string{"testCommand"}, WorkingDir: "testWorkingDir", + SecurityContext: &v1.SecurityContext{ + RunAsUser: &runAsUser, + RunAsGroup: &runAsGroup, + }, }, }, }, @@ -87,8 +93,10 @@ func TestGenerateContainerConfig(t *testing.T) { containerConfig, _, err := m.generateContainerConfig(&pod.Spec.Containers[0], pod, 0, "", pod.Spec.Containers[0].Image, kubecontainer.ContainerTypeRegular) assert.NoError(t, err) assert.Equal(t, expectedConfig, containerConfig, "generate container config for kubelet runtime v1.") + assert.Equal(t, runAsUser, containerConfig.GetLinux().GetSecurityContext().GetRunAsUser().GetValue(), "RunAsUser should be set") + assert.Equal(t, runAsGroup, containerConfig.GetLinux().GetSecurityContext().GetRunAsGroup().GetValue(), "RunAsGroup should be set") - runAsUser := int64(0) + runAsRoot := int64(0) runAsNonRootTrue := true podWithContainerSecurityContext := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -106,7 +114,7 @@ func TestGenerateContainerConfig(t *testing.T) { WorkingDir: "testWorkingDir", SecurityContext: &v1.SecurityContext{ RunAsNonRoot: &runAsNonRootTrue, - RunAsUser: &runAsUser, + RunAsUser: &runAsRoot, }, }, }, diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container_windows.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container_windows.go index 6ea1928cf..77165e81b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container_windows.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container_windows.go @@ -19,24 +19,32 @@ limitations under the License. package kuberuntime import ( + "fmt" "github.com/docker/docker/pkg/sysinfo" "k8s.io/api/core/v1" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" + "k8s.io/kubernetes/pkg/securitycontext" ) // applyPlatformSpecificContainerConfig applies platform specific configurations to runtimeapi.ContainerConfig. func (m *kubeGenericRuntimeManager) applyPlatformSpecificContainerConfig(config *runtimeapi.ContainerConfig, container *v1.Container, pod *v1.Pod, uid *int64, username string) error { - config.Windows = m.generateWindowsContainerConfig(container, pod, uid, username) + windowsConfig, err := m.generateWindowsContainerConfig(container, pod, uid, username) + if err != nil { + return err + } + + config.Windows = windowsConfig return nil } // generateWindowsContainerConfig generates windows container config for kubelet runtime v1. // Refer https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/cri-windows.md. -func (m *kubeGenericRuntimeManager) generateWindowsContainerConfig(container *v1.Container, pod *v1.Pod, uid *int64, username string) *runtimeapi.WindowsContainerConfig { +func (m *kubeGenericRuntimeManager) generateWindowsContainerConfig(container *v1.Container, pod *v1.Pod, uid *int64, username string) (*runtimeapi.WindowsContainerConfig, error) { wc := &runtimeapi.WindowsContainerConfig{ - Resources: &runtimeapi.WindowsContainerResources{}, + Resources: &runtimeapi.WindowsContainerResources{}, + SecurityContext: &runtimeapi.WindowsContainerSecurityContext{}, } cpuRequest := container.Resources.Requests.Cpu() @@ -77,5 +85,15 @@ func (m *kubeGenericRuntimeManager) generateWindowsContainerConfig(container *v1 wc.Resources.MemoryLimitInBytes = memoryLimit } - return wc + // setup security context + effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container) + // RunAsUser only supports int64 from Kubernetes API, but Windows containers only support username. + if effectiveSc.RunAsUser != nil { + return nil, fmt.Errorf("run as uid (%d) is not supported on Windows", *effectiveSc.RunAsUser) + } + if username != "" { + wc.SecurityContext.RunAsUsername = username + } + + return wc, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_gc_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_gc_test.go index e55ec1066..49513d442 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_gc_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_gc_test.go @@ -96,6 +96,28 @@ func TestSandboxGC(t *testing.T) { remain: []int{0, 1}, evictTerminatedPods: false, }, + { + description: "older exited sandboxes without containers for existing pods should be garbage collected if there are more than one exited sandboxes.", + sandboxes: []sandboxTemplate{ + makeGCSandbox(pods[0], 1, runtimeapi.PodSandboxState_SANDBOX_NOTREADY, true, 1), + makeGCSandbox(pods[0], 0, runtimeapi.PodSandboxState_SANDBOX_NOTREADY, true, 0), + }, + containers: []containerTemplate{}, + remain: []int{0}, + evictTerminatedPods: false, + }, + { + description: "older exited sandboxes with containers for existing pods should not be garbage collected even if there are more than one exited sandboxes.", + sandboxes: []sandboxTemplate{ + makeGCSandbox(pods[0], 1, runtimeapi.PodSandboxState_SANDBOX_NOTREADY, true, 1), + makeGCSandbox(pods[0], 0, runtimeapi.PodSandboxState_SANDBOX_NOTREADY, true, 0), + }, + containers: []containerTemplate{ + {pod: pods[0], container: &pods[0].Spec.Containers[0], sandboxAttempt: 0, state: runtimeapi.ContainerState_CONTAINER_EXITED}, + }, + remain: []int{0, 1}, + evictTerminatedPods: false, + }, { description: "non-running sandboxes for existing pods should be garbage collected if evictTerminatedPods is set.", sandboxes: []sandboxTemplate{ @@ -187,6 +209,7 @@ func TestContainerGC(t *testing.T) { policy *kubecontainer.ContainerGCPolicy // container gc policy remain []int // template indexes of remaining containers evictTerminatedPods bool + allSourcesReady bool }{ { description: "all containers should be removed when max container limit is 0", @@ -196,6 +219,7 @@ func TestContainerGC(t *testing.T) { policy: &kubecontainer.ContainerGCPolicy{MinAge: time.Minute, MaxPerPodContainer: 1, MaxContainers: 0}, remain: []int{}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "max containers should be complied when no max per pod container limit is set", @@ -209,6 +233,7 @@ func TestContainerGC(t *testing.T) { policy: &kubecontainer.ContainerGCPolicy{MinAge: time.Minute, MaxPerPodContainer: -1, MaxContainers: 4}, remain: []int{0, 1, 2, 3}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "no containers should be removed if both max container and per pod container limits are not set", @@ -220,6 +245,7 @@ func TestContainerGC(t *testing.T) { policy: &kubecontainer.ContainerGCPolicy{MinAge: time.Minute, MaxPerPodContainer: -1, MaxContainers: -1}, remain: []int{0, 1, 2}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "recently started containers should not be removed", @@ -230,6 +256,7 @@ func TestContainerGC(t *testing.T) { }, remain: []int{0, 1, 2}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "oldest containers should be removed when per pod container limit exceeded", @@ -240,6 +267,7 @@ func TestContainerGC(t *testing.T) { }, remain: []int{0, 1}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "running containers should not be removed", @@ -250,6 +278,7 @@ func TestContainerGC(t *testing.T) { }, remain: []int{0, 1, 2}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "no containers should be removed when limits are not exceeded", @@ -259,6 +288,7 @@ func TestContainerGC(t *testing.T) { }, remain: []int{0, 1}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "max container count should apply per (UID, container) pair", @@ -275,6 +305,7 @@ func TestContainerGC(t *testing.T) { }, remain: []int{0, 1, 3, 4, 6, 7}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "max limit should apply and try to keep from every pod", @@ -292,6 +323,7 @@ func TestContainerGC(t *testing.T) { }, remain: []int{0, 2, 4, 6, 8}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "oldest pods should be removed if limit exceeded", @@ -309,6 +341,7 @@ func TestContainerGC(t *testing.T) { }, remain: []int{0, 2, 4, 6, 8, 9}, evictTerminatedPods: false, + allSourcesReady: true, }, { description: "all non-running containers should be removed when evictTerminatedPods is set", @@ -322,6 +355,7 @@ func TestContainerGC(t *testing.T) { }, remain: []int{4, 5}, evictTerminatedPods: true, + allSourcesReady: true, }, { description: "containers for deleted pods should be removed", @@ -335,6 +369,16 @@ func TestContainerGC(t *testing.T) { }, remain: []int{0, 1, 2}, evictTerminatedPods: false, + allSourcesReady: true, + }, + { + description: "containers for deleted pods may not be removed if allSourcesReady is set false ", + containers: []containerTemplate{ + makeGCContainer("deleted", "bar1", 0, 0, runtimeapi.ContainerState_CONTAINER_EXITED), + }, + remain: []int{0}, + evictTerminatedPods: true, + allSourcesReady: false, }, } { t.Logf("TestCase #%d: %+v", c, test) @@ -344,7 +388,7 @@ func TestContainerGC(t *testing.T) { if test.policy == nil { test.policy = &defaultGCPolicy } - err := m.containerGC.evictContainers(*test.policy, true, test.evictTerminatedPods) + err := m.containerGC.evictContainers(*test.policy, test.allSourcesReady, test.evictTerminatedPods) assert.NoError(t, err) realRemain, err := fakeRuntime.ListContainers(nil) assert.NoError(t, err) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_manager.go index c34136b56..df207fb43 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -120,7 +120,7 @@ type kubeGenericRuntimeManager struct { type KubeGenericRuntime interface { kubecontainer.Runtime - kubecontainer.IndirectStreamingRuntime + kubecontainer.StreamingRuntime kubecontainer.ContainerCommandRunner } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go index cddf3385d..04419a07f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go @@ -25,6 +25,8 @@ import ( "github.com/golang/glog" "k8s.io/api/core/v1" kubetypes "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/types" @@ -134,10 +136,15 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxLinuxConfig(pod *v1.Pod) ( }, } - sysctls, err := getSysctlsFromAnnotations(pod.Annotations) - if err != nil { - return nil, fmt.Errorf("failed to get sysctls from annotations %v for pod %q: %v", pod.Annotations, format.Pod(pod), err) + sysctls := make(map[string]string) + if utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) { + if pod.Spec.SecurityContext != nil { + for _, c := range pod.Spec.SecurityContext.Sysctls { + sysctls[c.Name] = c.Value + } + } } + lc.Sysctls = sysctls if pod.Spec.SecurityContext != nil { @@ -145,6 +152,9 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxLinuxConfig(pod *v1.Pod) ( if sc.RunAsUser != nil { lc.SecurityContext.RunAsUser = &runtimeapi.Int64Value{Value: int64(*sc.RunAsUser)} } + if sc.RunAsGroup != nil { + lc.SecurityContext.RunAsGroup = &runtimeapi.Int64Value{Value: int64(*sc.RunAsGroup)} + } lc.SecurityContext.NamespaceOptions = namespacesForPod(pod) if sc.FSGroup != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/legacy_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/legacy_test.go index a3508bdc0..31e4d6967 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/legacy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/legacy_test.go @@ -45,3 +45,14 @@ func TestLogSymLink(t *testing.T) { expectedPath := path.Join(containerLogsDir, fmt.Sprintf("%s_%s-%s", podFullName, containerName, dockerId)[:251]+".log") as.Equal(expectedPath, logSymlink(containerLogsDir, podFullName, containerName, dockerId)) } + +func TestLegacyLogSymLink(t *testing.T) { + as := assert.New(t) + containerID := randStringBytes(80) + containerName := randStringBytes(70) + podName := randStringBytes(128) + podNamespace := randStringBytes(10) + // The file name cannot exceed 255 characters. Since .log suffix is required, the prefix cannot exceed 251 characters. + expectedPath := path.Join(legacyContainerLogsDir, fmt.Sprintf("%s_%s_%s-%s", podName, podNamespace, containerName, containerID)[:251]+".log") + as.Equal(expectedPath, legacyLogSymlink(containerID, containerName, podName, podNamespace)) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/logs/logs.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/logs/logs.go index 5ccd226fe..b948c883b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/logs/logs.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/logs/logs.go @@ -354,9 +354,28 @@ func ReadLogs(path, containerID string, opts *LogOptions, runtimeService interna } } +func isContainerRunning(id string, r internalapi.RuntimeService) (bool, error) { + s, err := r.ContainerStatus(id) + if err != nil { + return false, err + } + // Only keep following container log when it is running. + if s.State != runtimeapi.ContainerState_CONTAINER_RUNNING { + glog.V(5).Infof("Container %q is not running (state=%q)", id, s.State) + // Do not return error because it's normal that the container stops + // during waiting. + return false, nil + } + return true, nil +} + // waitLogs wait for the next log write. It returns a boolean and an error. The boolean // indicates whether a new log is found; the error is error happens during waiting new logs. func waitLogs(id string, w *fsnotify.Watcher, runtimeService internalapi.RuntimeService) (bool, error) { + // no need to wait if the pod is not running + if running, err := isContainerRunning(id, runtimeService); !running { + return false, err + } errRetry := 5 for { select { @@ -374,17 +393,9 @@ func waitLogs(id string, w *fsnotify.Watcher, runtimeService internalapi.Runtime } errRetry-- case <-time.After(stateCheckPeriod): - s, err := runtimeService.ContainerStatus(id) - if err != nil { + if running, err := isContainerRunning(id, runtimeService); !running { return false, err } - // Only keep following container log when it is running. - if s.State != runtimeapi.ContainerState_CONTAINER_RUNNING { - glog.Errorf("Container %q is not running (state=%q)", id, s.State) - // Do not return error because it's normal that the container stops - // during waiting. - return false, nil - } } } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/security_context.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/security_context.go index c01fd5206..20e11e7fc 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/security_context.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/security_context.go @@ -108,6 +108,9 @@ func convertToRuntimeSecurityContext(securityContext *v1.SecurityContext) *runti if securityContext.RunAsUser != nil { sc.RunAsUser = &runtimeapi.Int64Value{Value: int64(*securityContext.RunAsUser)} } + if securityContext.RunAsGroup != nil { + sc.RunAsGroup = &runtimeapi.Int64Value{Value: int64(*securityContext.RunAsGroup)} + } if securityContext.Privileged != nil { sc.Privileged = *securityContext.Privileged } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/BUILD index 872a19591..74be426ff 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/BUILD @@ -11,7 +11,6 @@ go_library( srcs = [ "admission_failure_handler_stub.go", "doc.go", - "fake_handler_runner.go", "handlers.go", "interfaces.go", "predicate.go", @@ -24,7 +23,7 @@ go_library( "//pkg/kubelet/util/format:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/security/apparmor:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -43,7 +42,7 @@ go_test( deps = [ "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/util/format:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/fake_handler_runner.go b/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/fake_handler_runner.go deleted file mode 100644 index 5606b1987..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/fake_handler_runner.go +++ /dev/null @@ -1,62 +0,0 @@ -/* -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 lifecycle - -import ( - "fmt" - "sync" - - "k8s.io/api/core/v1" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/util/format" -) - -type FakeHandlerRunner struct { - sync.Mutex - HandlerRuns []string - Err error -} - -func NewFakeHandlerRunner() *FakeHandlerRunner { - return &FakeHandlerRunner{HandlerRuns: []string{}} -} - -func (hr *FakeHandlerRunner) Run(containerID kubecontainer.ContainerID, pod *v1.Pod, container *v1.Container, handler *v1.Handler) (string, error) { - hr.Lock() - defer hr.Unlock() - - if hr.Err != nil { - return "", hr.Err - } - - switch { - case handler.Exec != nil: - hr.HandlerRuns = append(hr.HandlerRuns, fmt.Sprintf("exec on pod: %v, container: %v: %v", format.Pod(pod), container.Name, containerID.String())) - case handler.HTTPGet != nil: - hr.HandlerRuns = append(hr.HandlerRuns, fmt.Sprintf("http-get on pod: %v, container: %v: %v", format.Pod(pod), container.Name, containerID.String())) - case handler.TCPSocket != nil: - hr.HandlerRuns = append(hr.HandlerRuns, fmt.Sprintf("tcp-socket on pod: %v, container: %v: %v", format.Pod(pod), container.Name, containerID.String())) - default: - return "", fmt.Errorf("Invalid handler: %v", handler) - } - return "", nil -} - -func (hr *FakeHandlerRunner) Reset() { - hr.HandlerRuns = []string{} - hr.Err = nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/predicate.go b/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/predicate.go index e917acab3..420bae216 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/predicate.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/predicate.go @@ -26,7 +26,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/util/format" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) type getNodeAnyWayFuncType func() (*v1.Node, error) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/predicate_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/predicate_test.go index 325bafe02..47b792fbb 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/predicate_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/lifecycle/predicate_test.go @@ -22,7 +22,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var ( diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/logs/container_log_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/logs/container_log_manager.go index baedd6c4c..12ba95bd7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/logs/container_log_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/logs/container_log_manager.go @@ -168,7 +168,7 @@ func NewContainerLogManager(runtimeService internalapi.RuntimeService, maxSize s // Start the container log manager. func (c *containerLogManager) Start() { - // Start a goroutine peirodically does container log rotation. + // Start a goroutine periodically does container log rotation. go wait.Forever(func() { if err := c.rotateLogs(); err != nil { glog.Errorf("Failed to rotate container logs: %v", err) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/BUILD index 2f8d88397..8e6041502 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/BUILD @@ -10,9 +10,12 @@ go_library( srcs = ["metrics.go"], importpath = "k8s.io/kubernetes/pkg/kubelet/metrics", deps = [ + "//pkg/features:go_default_library", "//pkg/kubelet/container:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/collectors/volume_stats.go b/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/collectors/volume_stats.go index 7f80243dc..e6f1cf36d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/collectors/volume_stats.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/collectors/volume_stats.go @@ -58,17 +58,17 @@ var ( ) ) -type volumeStatsCollecotr struct { +type volumeStatsCollector struct { statsProvider serverstats.StatsProvider } // NewVolumeStatsCollector creates a volume stats prometheus collector. func NewVolumeStatsCollector(statsProvider serverstats.StatsProvider) prometheus.Collector { - return &volumeStatsCollecotr{statsProvider: statsProvider} + return &volumeStatsCollector{statsProvider: statsProvider} } // Describe implements the prometheus.Collector interface. -func (collector *volumeStatsCollecotr) Describe(ch chan<- *prometheus.Desc) { +func (collector *volumeStatsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- volumeStatsCapacityBytesDesc ch <- volumeStatsAvailableBytesDesc ch <- volumeStatsUsedBytesDesc @@ -78,7 +78,7 @@ func (collector *volumeStatsCollecotr) Describe(ch chan<- *prometheus.Desc) { } // Collect implements the prometheus.Collector interface. -func (collector *volumeStatsCollecotr) Collect(ch chan<- prometheus.Metric) { +func (collector *volumeStatsCollector) Collect(ch chan<- prometheus.Metric) { podStats, err := collector.statsProvider.ListPodStats() if err != nil { return diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/collectors/volume_stats_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/collectors/volume_stats_test.go index 903169d00..3e4d07e1d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/collectors/volume_stats_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/collectors/volume_stats_test.go @@ -129,7 +129,7 @@ func TestVolumeStatsCollector(t *testing.T) { mockStatsProvider := new(statstest.StatsProvider) mockStatsProvider.On("ListPodStats").Return(podStats, nil) - if err := gatherAndCompare(&volumeStatsCollecotr{statsProvider: mockStatsProvider}, want, metrics); err != nil { + if err := gatherAndCompare(&volumeStatsCollector{statsProvider: mockStatsProvider}, want, metrics); err != nil { t.Errorf("unexpected collecting result:\n%s", err) } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/metrics.go b/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/metrics.go index 4e9470f5a..058253258 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/metrics.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/metrics/metrics.go @@ -17,11 +17,15 @@ limitations under the License. package metrics import ( + "fmt" "sync" "time" "github.com/golang/glog" "github.com/prometheus/client_golang/prometheus" + corev1 "k8s.io/api/core/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" ) @@ -47,6 +51,17 @@ const ( // Metrics keys of device plugin operations DevicePluginRegistrationCountKey = "device_plugin_registration_count" DevicePluginAllocationLatencyKey = "device_plugin_alloc_latency_microseconds" + + // Metric keys for node config + AssignedConfigKey = "node_config_assigned" + ActiveConfigKey = "node_config_active" + LastKnownGoodConfigKey = "node_config_last_known_good" + ConfigErrorKey = "node_config_error" + ConfigSourceLabelKey = "node_config_source" + ConfigSourceLabelValueLocal = "local" + ConfigUIDLabelKey = "node_config_uid" + ConfigResourceVersionLabelKey = "node_config_resource_version" + KubeletConfigKeyLabelKey = "node_config_kubelet_key" ) var ( @@ -150,6 +165,40 @@ var ( }, []string{"resource_name"}, ) + + // Metrics for node config + + AssignedConfig = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Subsystem: KubeletSubsystem, + Name: AssignedConfigKey, + Help: "The node's understanding of intended config. The count is always 1.", + }, + []string{ConfigSourceLabelKey, ConfigUIDLabelKey, ConfigResourceVersionLabelKey, KubeletConfigKeyLabelKey}, + ) + ActiveConfig = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Subsystem: KubeletSubsystem, + Name: ActiveConfigKey, + Help: "The config source the node is actively using. The count is always 1.", + }, + []string{ConfigSourceLabelKey, ConfigUIDLabelKey, ConfigResourceVersionLabelKey, KubeletConfigKeyLabelKey}, + ) + LastKnownGoodConfig = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Subsystem: KubeletSubsystem, + Name: LastKnownGoodConfigKey, + Help: "The config source the node will fall back to when it encounters certain errors. The count is always 1.", + }, + []string{ConfigSourceLabelKey, ConfigUIDLabelKey, ConfigResourceVersionLabelKey, KubeletConfigKeyLabelKey}, + ) + ConfigError = prometheus.NewGauge( + prometheus.GaugeOpts{ + Subsystem: KubeletSubsystem, + Name: ConfigErrorKey, + Help: "This metric is true (1) if the node is experiencing a configuration-related error, false (0) otherwise.", + }, + ) ) var registerMetrics sync.Once @@ -172,6 +221,12 @@ func Register(containerCache kubecontainer.RuntimeCache, collectors ...prometheu prometheus.MustRegister(EvictionStatsAge) prometheus.MustRegister(DevicePluginRegistrationCount) prometheus.MustRegister(DevicePluginAllocationLatency) + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { + prometheus.MustRegister(AssignedConfig) + prometheus.MustRegister(ActiveConfig) + prometheus.MustRegister(LastKnownGoodConfig) + prometheus.MustRegister(ConfigError) + } for _, collector := range collectors { prometheus.MustRegister(collector) } @@ -232,3 +287,88 @@ func (pc *podAndContainerCollector) Collect(ch chan<- prometheus.Metric) { prometheus.GaugeValue, float64(runningContainers)) } + +const configMapAPIPathFmt = "/api/v1/namespaces/%s/configmaps/%s" + +func configLabels(source *corev1.NodeConfigSource) (map[string]string, error) { + if source == nil { + return map[string]string{ + // prometheus requires all of the labels that can be set on the metric + ConfigSourceLabelKey: "local", + ConfigUIDLabelKey: "", + ConfigResourceVersionLabelKey: "", + KubeletConfigKeyLabelKey: "", + }, nil + } + if source.ConfigMap != nil { + return map[string]string{ + ConfigSourceLabelKey: fmt.Sprintf(configMapAPIPathFmt, source.ConfigMap.Namespace, source.ConfigMap.Name), + ConfigUIDLabelKey: string(source.ConfigMap.UID), + ConfigResourceVersionLabelKey: source.ConfigMap.ResourceVersion, + KubeletConfigKeyLabelKey: source.ConfigMap.KubeletConfigKey, + }, nil + } + return nil, fmt.Errorf("unrecognized config source type, all source subfields were nil") +} + +// track labels across metric updates, so we can delete old label sets and prevent leaks +var assignedConfigLabels map[string]string = map[string]string{} + +func SetAssignedConfig(source *corev1.NodeConfigSource) error { + // compute the timeseries labels from the source + labels, err := configLabels(source) + if err != nil { + return err + } + // clean up the old timeseries (WithLabelValues creates a new one for each distinct label set) + AssignedConfig.Delete(assignedConfigLabels) + // record the new timeseries + assignedConfigLabels = labels + // expose the new timeseries with a constant count of 1 + AssignedConfig.With(assignedConfigLabels).Set(1) + return nil +} + +// track labels across metric updates, so we can delete old label sets and prevent leaks +var activeConfigLabels map[string]string = map[string]string{} + +func SetActiveConfig(source *corev1.NodeConfigSource) error { + // compute the timeseries labels from the source + labels, err := configLabels(source) + if err != nil { + return err + } + // clean up the old timeseries (WithLabelValues creates a new one for each distinct label set) + ActiveConfig.Delete(activeConfigLabels) + // record the new timeseries + activeConfigLabels = labels + // expose the new timeseries with a constant count of 1 + ActiveConfig.With(activeConfigLabels).Set(1) + return nil +} + +// track labels across metric updates, so we can delete old label sets and prevent leaks +var lastKnownGoodConfigLabels map[string]string = map[string]string{} + +func SetLastKnownGoodConfig(source *corev1.NodeConfigSource) error { + // compute the timeseries labels from the source + labels, err := configLabels(source) + if err != nil { + return err + } + // clean up the old timeseries (WithLabelValues creates a new one for each distinct label set) + LastKnownGoodConfig.Delete(lastKnownGoodConfigLabels) + // record the new timeseries + lastKnownGoodConfigLabels = labels + // expose the new timeseries with a constant count of 1 + LastKnownGoodConfig.With(lastKnownGoodConfigLabels).Set(1) + return nil +} + +func SetConfigError(err bool) { + if err { + ConfigError.Set(1) + } else { + ConfigError.Set(0) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/mountpod/mount_pod_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/mountpod/mount_pod_test.go index 3f84739ff..bf7a0ec56 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/mountpod/mount_pod_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/mountpod/mount_pod_test.go @@ -52,7 +52,7 @@ func TestGetVolumeExec(t *testing.T) { fakeSecretManager := secret.NewFakeManager() fakeConfigMapManager := configmap.NewFakeManager() podManager := kubepod.NewBasicPodManager( - podtest.NewFakeMirrorClient(), fakeSecretManager, fakeConfigMapManager) + podtest.NewFakeMirrorClient(), fakeSecretManager, fakeConfigMapManager, podtest.NewMockCheckpointManager()) podManager.SetPods(pods) // Prepare fake /var/lib/kubelet diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/network/BUILD index 51b32deeb..1f62350aa 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/network/BUILD @@ -1,34 +1,5 @@ package(default_visibility = ["//visibility:public"]) -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "network.go", - "plugins.go", - ], - importpath = "k8s.io/kubernetes/pkg/kubelet/network", - deps = [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network/hostport:go_default_library", - "//pkg/kubelet/network/metrics:go_default_library", - "//pkg/util/sysctl:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - ], -) - filegroup( name = "package-srcs", srcs = glob(["**"]), @@ -40,13 +11,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//pkg/kubelet/network/cni:all-srcs", "//pkg/kubelet/network/dns:all-srcs", - "//pkg/kubelet/network/hairpin:all-srcs", - "//pkg/kubelet/network/hostport:all-srcs", - "//pkg/kubelet/network/kubenet:all-srcs", - "//pkg/kubelet/network/metrics:all-srcs", - "//pkg/kubelet/network/testing:all-srcs", ], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/BUILD deleted file mode 100644 index b21f8bee1..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/BUILD +++ /dev/null @@ -1,110 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "cni.go", - ] + select({ - "@io_bazel_rules_go//go/platform:android": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:darwin": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:dragonfly": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:freebsd": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:linux": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:nacl": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:netbsd": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:openbsd": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:plan9": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:solaris": [ - "cni_others.go", - ], - "@io_bazel_rules_go//go/platform:windows": [ - "cni_windows.go", - ], - "//conditions:default": [], - }), - importpath = "k8s.io/kubernetes/pkg/kubelet/network/cni", - deps = [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//vendor/github.com/containernetworking/cni/libcni:go_default_library", - "//vendor/github.com/containernetworking/cni/pkg/types:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - ] + select({ - "@io_bazel_rules_go//go/platform:windows": [ - "//vendor/github.com/containernetworking/cni/pkg/types/020:go_default_library", - ], - "//conditions:default": [], - }), -) - -go_test( - name = "go_default_test", - srcs = select({ - "@io_bazel_rules_go//go/platform:linux": [ - "cni_test.go", - ], - "//conditions:default": [], - }), - embed = [":go_default_library"], - deps = select({ - "@io_bazel_rules_go//go/platform:linux": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/container/testing:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/cni/testing:go_default_library", - "//pkg/kubelet/network/hostport:go_default_library", - "//pkg/kubelet/network/testing:go_default_library", - "//vendor/github.com/containernetworking/cni/pkg/types/020:go_default_library", - "//vendor/github.com/stretchr/testify/mock:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/util/testing:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - "//vendor/k8s.io/utils/exec/testing:go_default_library", - ], - "//conditions:default": [], - }), -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/kubelet/network/cni/testing:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/testing/BUILD deleted file mode 100644 index 30c27c0e6..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/cni/testing/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["mock_cni.go"], - importpath = "k8s.io/kubernetes/pkg/kubelet/network/cni/testing", - deps = [ - "//vendor/github.com/containernetworking/cni/libcni:go_default_library", - "//vendor/github.com/containernetworking/cni/pkg/types:go_default_library", - "//vendor/github.com/stretchr/testify/mock:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hairpin/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/network/hairpin/BUILD deleted file mode 100644 index 6081b12b2..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hairpin/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["hairpin.go"], - importpath = "k8s.io/kubernetes/pkg/kubelet/network/hairpin", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["hairpin_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/utils/exec:go_default_library", - "//vendor/k8s.io/utils/exec/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/BUILD deleted file mode 100644 index 7cc35a9c2..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/BUILD +++ /dev/null @@ -1,62 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "fake_iptables.go", - "hostport.go", - "hostport_manager.go", - "hostport_syncer.go", - ], - importpath = "k8s.io/kubernetes/pkg/kubelet/network/hostport", - deps = [ - "//pkg/proxy/iptables:go_default_library", - "//pkg/util/conntrack:go_default_library", - "//pkg/util/iptables:go_default_library", - "//pkg/util/net:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "fake_iptables_test.go", - "hostport_manager_test.go", - "hostport_syncer_test.go", - "hostport_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//pkg/util/iptables:go_default_library", - "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/kubelet/network/hostport/testing:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport.go b/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport.go deleted file mode 100644 index cdfeb1135..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport.go +++ /dev/null @@ -1,200 +0,0 @@ -/* -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 hostport - -import ( - "fmt" - "net" - "strings" - - "github.com/golang/glog" - - "k8s.io/api/core/v1" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" -) - -const ( - // the hostport chain - kubeHostportsChain utiliptables.Chain = "KUBE-HOSTPORTS" - // prefix for hostport chains - kubeHostportChainPrefix string = "KUBE-HP-" -) - -// PortMapping represents a network port in a container -type PortMapping struct { - Name string - HostPort int32 - ContainerPort int32 - Protocol v1.Protocol - HostIP string -} - -// PodPortMapping represents a pod's network state and associated container port mappings -type PodPortMapping struct { - Namespace string - Name string - PortMappings []*PortMapping - HostNetwork bool - IP net.IP -} - -// ConstructPodPortMapping creates a PodPortMapping from the ports specified in the pod's -// containers. -func ConstructPodPortMapping(pod *v1.Pod, podIP net.IP) *PodPortMapping { - portMappings := make([]*PortMapping, 0) - for _, c := range pod.Spec.Containers { - for _, port := range c.Ports { - portMappings = append(portMappings, &PortMapping{ - Name: port.Name, - HostPort: port.HostPort, - ContainerPort: port.ContainerPort, - Protocol: port.Protocol, - HostIP: port.HostIP, - }) - } - } - - return &PodPortMapping{ - Namespace: pod.Namespace, - Name: pod.Name, - PortMappings: portMappings, - HostNetwork: pod.Spec.HostNetwork, - IP: podIP, - } -} - -type hostport struct { - port int32 - protocol string -} - -type hostportOpener func(*hostport) (closeable, error) - -type closeable interface { - Close() error -} - -func openLocalPort(hp *hostport) (closeable, error) { - // For ports on node IPs, open the actual port and hold it, even though we - // use iptables to redirect traffic. - // This ensures a) that it's safe to use that port and b) that (a) stays - // true. The risk is that some process on the node (e.g. sshd or kubelet) - // is using a port and we give that same port out to a Service. That would - // be bad because iptables would silently claim the traffic but the process - // would never know. - // NOTE: We should not need to have a real listen()ing socket - bind() - // should be enough, but I can't figure out a way to e2e test without - // it. Tools like 'ss' and 'netstat' do not show sockets that are - // bind()ed but not listen()ed, and at least the default debian netcat - // has no way to avoid about 10 seconds of retries. - var socket closeable - switch hp.protocol { - case "tcp": - listener, err := net.Listen("tcp", fmt.Sprintf(":%d", hp.port)) - if err != nil { - return nil, err - } - socket = listener - case "udp": - addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", hp.port)) - if err != nil { - return nil, err - } - conn, err := net.ListenUDP("udp", addr) - if err != nil { - return nil, err - } - socket = conn - default: - return nil, fmt.Errorf("unknown protocol %q", hp.protocol) - } - glog.V(3).Infof("Opened local port %s", hp.String()) - return socket, nil -} - -// openHostports opens all given hostports using the given hostportOpener -// If encounter any error, clean up and return the error -// If all ports are opened successfully, return the hostport and socket mapping -// TODO: move openHostports and closeHostports into a common struct -func openHostports(portOpener hostportOpener, podPortMapping *PodPortMapping) (map[hostport]closeable, error) { - var retErr error - ports := make(map[hostport]closeable) - for _, pm := range podPortMapping.PortMappings { - if pm.HostPort <= 0 { - continue - } - hp := portMappingToHostport(pm) - socket, err := portOpener(&hp) - if err != nil { - retErr = fmt.Errorf("cannot open hostport %d for pod %s: %v", pm.HostPort, getPodFullName(podPortMapping), err) - break - } - ports[hp] = socket - } - - // If encounter any error, close all hostports that just got opened. - if retErr != nil { - for hp, socket := range ports { - if err := socket.Close(); err != nil { - glog.Errorf("Cannot clean up hostport %d for pod %s: %v", hp.port, getPodFullName(podPortMapping), err) - } - } - return nil, retErr - } - return ports, nil -} - -// portMappingToHostport creates hostport structure based on input portmapping -func portMappingToHostport(portMapping *PortMapping) hostport { - return hostport{ - port: portMapping.HostPort, - protocol: strings.ToLower(string(portMapping.Protocol)), - } -} - -// ensureKubeHostportChains ensures the KUBE-HOSTPORTS chain is setup correctly -func ensureKubeHostportChains(iptables utiliptables.Interface, natInterfaceName string) error { - glog.V(4).Info("Ensuring kubelet hostport chains") - // Ensure kubeHostportChain - if _, err := iptables.EnsureChain(utiliptables.TableNAT, kubeHostportsChain); err != nil { - return fmt.Errorf("Failed to ensure that %s chain %s exists: %v", utiliptables.TableNAT, kubeHostportsChain, err) - } - tableChainsNeedJumpServices := []struct { - table utiliptables.Table - chain utiliptables.Chain - }{ - {utiliptables.TableNAT, utiliptables.ChainOutput}, - {utiliptables.TableNAT, utiliptables.ChainPrerouting}, - } - args := []string{"-m", "comment", "--comment", "kube hostport portals", - "-m", "addrtype", "--dst-type", "LOCAL", - "-j", string(kubeHostportsChain)} - for _, tc := range tableChainsNeedJumpServices { - // KUBE-HOSTPORTS chain needs to be appended to the system chains. - // This ensures KUBE-SERVICES chain gets processed first. - // Since rules in KUBE-HOSTPORTS chain matches broader cases, allow the more specific rules to be processed first. - if _, err := iptables.EnsureRule(utiliptables.Append, tc.table, tc.chain, args...); err != nil { - return fmt.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", tc.table, tc.chain, kubeHostportsChain, err) - } - } - // Need to SNAT traffic from localhost - args = []string{"-m", "comment", "--comment", "SNAT for localhost access to hostports", "-o", natInterfaceName, "-s", "127.0.0.0/8", "-j", "MASQUERADE"} - if _, err := iptables.EnsureRule(utiliptables.Append, utiliptables.TableNAT, utiliptables.ChainPostrouting, args...); err != nil { - return fmt.Errorf("Failed to ensure that %s chain %s jumps to MASQUERADE: %v", utiliptables.TableNAT, utiliptables.ChainPostrouting, err) - } - return nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_manager_test.go deleted file mode 100644 index 019d36e78..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_manager_test.go +++ /dev/null @@ -1,207 +0,0 @@ -/* -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 hostport - -import ( - "bytes" - "net" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "k8s.io/api/core/v1" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" - "k8s.io/utils/exec" -) - -func TestHostportManager(t *testing.T) { - iptables := NewFakeIPTables() - portOpener := NewFakeSocketManager() - manager := &hostportManager{ - hostPortMap: make(map[hostport]closeable), - iptables: iptables, - portOpener: portOpener.openFakeSocket, - execer: exec.New(), - } - - testCases := []struct { - mapping *PodPortMapping - expectError bool - }{ - { - mapping: &PodPortMapping{ - Name: "pod1", - Namespace: "ns1", - IP: net.ParseIP("10.1.1.2"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8080, - ContainerPort: 80, - Protocol: v1.ProtocolTCP, - }, - { - HostPort: 8081, - ContainerPort: 81, - Protocol: v1.ProtocolUDP, - }, - }, - }, - expectError: false, - }, - { - mapping: &PodPortMapping{ - Name: "pod2", - Namespace: "ns1", - IP: net.ParseIP("10.1.1.3"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8082, - ContainerPort: 80, - Protocol: v1.ProtocolTCP, - }, - { - HostPort: 8081, - ContainerPort: 81, - Protocol: v1.ProtocolUDP, - }, - }, - }, - expectError: true, - }, - { - mapping: &PodPortMapping{ - Name: "pod3", - Namespace: "ns1", - IP: net.ParseIP("10.1.1.4"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8443, - ContainerPort: 443, - Protocol: v1.ProtocolTCP, - }, - }, - }, - expectError: false, - }, - } - - // Add Hostports - for _, tc := range testCases { - err := manager.Add("id", tc.mapping, "cbr0") - if tc.expectError { - assert.Error(t, err) - continue - } - assert.NoError(t, err) - } - - // Check port opened - expectedPorts := []hostport{{8080, "tcp"}, {8081, "udp"}, {8443, "tcp"}} - openedPorts := make(map[hostport]bool) - for hp, port := range portOpener.mem { - if !port.closed { - openedPorts[hp] = true - } - } - assert.EqualValues(t, len(openedPorts), len(expectedPorts)) - for _, hp := range expectedPorts { - _, ok := openedPorts[hp] - assert.EqualValues(t, true, ok) - } - - // Check Iptables-save result after adding hostports - raw := bytes.NewBuffer(nil) - err := iptables.SaveInto(utiliptables.TableNAT, raw) - assert.NoError(t, err) - - lines := strings.Split(string(raw.Bytes()), "\n") - expectedLines := map[string]bool{ - `*nat`: true, - `:KUBE-HOSTPORTS - [0:0]`: true, - `:OUTPUT - [0:0]`: true, - `:PREROUTING - [0:0]`: true, - `:POSTROUTING - [0:0]`: true, - `:KUBE-HP-IJHALPHTORMHHPPK - [0:0]`: true, - `:KUBE-HP-63UPIDJXVRSZGSUZ - [0:0]`: true, - `:KUBE-HP-WFBOALXEP42XEMJK - [0:0]`: true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod3_ns1 hostport 8443\" -m tcp -p tcp --dport 8443 -j KUBE-HP-WFBOALXEP42XEMJK": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8081\" -m udp -p udp --dport 8081 -j KUBE-HP-63UPIDJXVRSZGSUZ": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8080\" -m tcp -p tcp --dport 8080 -j KUBE-HP-IJHALPHTORMHHPPK": true, - "-A OUTPUT -m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS": true, - "-A PREROUTING -m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS": true, - "-A POSTROUTING -m comment --comment \"SNAT for localhost access to hostports\" -o cbr0 -s 127.0.0.0/8 -j MASQUERADE": true, - "-A KUBE-HP-IJHALPHTORMHHPPK -m comment --comment \"pod1_ns1 hostport 8080\" -s 10.1.1.2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-IJHALPHTORMHHPPK -m comment --comment \"pod1_ns1 hostport 8080\" -m tcp -p tcp -j DNAT --to-destination 10.1.1.2:80": true, - "-A KUBE-HP-63UPIDJXVRSZGSUZ -m comment --comment \"pod1_ns1 hostport 8081\" -s 10.1.1.2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-63UPIDJXVRSZGSUZ -m comment --comment \"pod1_ns1 hostport 8081\" -m udp -p udp -j DNAT --to-destination 10.1.1.2:81": true, - "-A KUBE-HP-WFBOALXEP42XEMJK -m comment --comment \"pod3_ns1 hostport 8443\" -s 10.1.1.4/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-WFBOALXEP42XEMJK -m comment --comment \"pod3_ns1 hostport 8443\" -m tcp -p tcp -j DNAT --to-destination 10.1.1.4:443": true, - `COMMIT`: true, - } - for _, line := range lines { - if len(strings.TrimSpace(line)) > 0 { - _, ok := expectedLines[strings.TrimSpace(line)] - assert.EqualValues(t, true, ok) - } - } - - // Remove all added hostports - for _, tc := range testCases { - if !tc.expectError { - err := manager.Remove("id", tc.mapping) - assert.NoError(t, err) - } - } - - // Check Iptables-save result after deleting hostports - raw.Reset() - err = iptables.SaveInto(utiliptables.TableNAT, raw) - assert.NoError(t, err) - lines = strings.Split(string(raw.Bytes()), "\n") - remainingChains := make(map[string]bool) - for _, line := range lines { - if strings.HasPrefix(line, ":") { - remainingChains[strings.TrimSpace(line)] = true - } - } - expectDeletedChains := []string{"KUBE-HP-4YVONL46AKYWSKS3", "KUBE-HP-7THKRFSEH4GIIXK7", "KUBE-HP-5N7UH5JAXCVP5UJR"} - for _, chain := range expectDeletedChains { - _, ok := remainingChains[chain] - assert.EqualValues(t, false, ok) - } - - // check if all ports are closed - for _, port := range portOpener.mem { - assert.EqualValues(t, true, port.closed) - } -} - -func TestGetHostportChain(t *testing.T) { - m := make(map[string]int) - chain := getHostportChain("testrdma-2", &PortMapping{HostPort: 57119, Protocol: "TCP", ContainerPort: 57119}) - m[string(chain)] = 1 - chain = getHostportChain("testrdma-2", &PortMapping{HostPort: 55429, Protocol: "TCP", ContainerPort: 55429}) - m[string(chain)] = 1 - chain = getHostportChain("testrdma-2", &PortMapping{HostPort: 56833, Protocol: "TCP", ContainerPort: 56833}) - m[string(chain)] = 1 - if len(m) != 3 { - t.Fatal(m) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_test.go deleted file mode 100644 index 306cb6252..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/hostport_test.go +++ /dev/null @@ -1,152 +0,0 @@ -/* -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 hostport - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "k8s.io/api/core/v1" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" -) - -type fakeSocket struct { - port int32 - protocol string - closed bool -} - -func (f *fakeSocket) Close() error { - if f.closed { - return fmt.Errorf("Socket %q.%s already closed!", f.port, f.protocol) - } - f.closed = true - return nil -} - -func NewFakeSocketManager() *fakeSocketManager { - return &fakeSocketManager{mem: make(map[hostport]*fakeSocket)} -} - -type fakeSocketManager struct { - mem map[hostport]*fakeSocket -} - -func (f *fakeSocketManager) openFakeSocket(hp *hostport) (closeable, error) { - if socket, ok := f.mem[*hp]; ok && !socket.closed { - return nil, fmt.Errorf("hostport is occupied") - } - fs := &fakeSocket{hp.port, hp.protocol, false} - f.mem[*hp] = fs - return fs, nil -} - -func TestOpenHostports(t *testing.T) { - opener := NewFakeSocketManager() - testCases := []struct { - podPortMapping *PodPortMapping - expectError bool - }{ - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n0", - }, - false, - }, - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n1", - PortMappings: []*PortMapping{ - {HostPort: 80, Protocol: v1.Protocol("TCP")}, - {HostPort: 8080, Protocol: v1.Protocol("TCP")}, - {HostPort: 443, Protocol: v1.Protocol("TCP")}, - }, - }, - false, - }, - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n2", - PortMappings: []*PortMapping{ - {HostPort: 80, Protocol: v1.Protocol("TCP")}, - }, - }, - true, - }, - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n3", - PortMappings: []*PortMapping{ - {HostPort: 8081, Protocol: v1.Protocol("TCP")}, - {HostPort: 8080, Protocol: v1.Protocol("TCP")}, - }, - }, - true, - }, - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n3", - PortMappings: []*PortMapping{ - {HostPort: 8081, Protocol: v1.Protocol("TCP")}, - }, - }, - false, - }, - } - - for _, tc := range testCases { - mapping, err := openHostports(opener.openFakeSocket, tc.podPortMapping) - if tc.expectError { - assert.Error(t, err) - continue - } - assert.NoError(t, err) - assert.EqualValues(t, len(mapping), len(tc.podPortMapping.PortMappings)) - } -} - -func TestEnsureKubeHostportChains(t *testing.T) { - interfaceName := "cbr0" - builtinChains := []string{"PREROUTING", "OUTPUT"} - jumpRule := "-m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS" - masqRule := "-m comment --comment \"SNAT for localhost access to hostports\" -o cbr0 -s 127.0.0.0/8 -j MASQUERADE" - - fakeIPTables := NewFakeIPTables() - assert.NoError(t, ensureKubeHostportChains(fakeIPTables, interfaceName)) - - _, _, err := fakeIPTables.getChain(utiliptables.TableNAT, utiliptables.Chain("KUBE-HOSTPORTS")) - assert.NoError(t, err) - - _, chain, err := fakeIPTables.getChain(utiliptables.TableNAT, utiliptables.ChainPostrouting) - assert.NoError(t, err) - assert.EqualValues(t, len(chain.rules), 1) - assert.Contains(t, chain.rules[0], masqRule) - - for _, chainName := range builtinChains { - _, chain, err := fakeIPTables.getChain(utiliptables.TableNAT, utiliptables.Chain(chainName)) - assert.NoError(t, err) - assert.EqualValues(t, len(chain.rules), 1) - assert.Contains(t, chain.rules[0], jumpRule) - } - -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/testing/BUILD deleted file mode 100644 index 9616cf9e3..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/testing/BUILD +++ /dev/null @@ -1,26 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["fake.go"], - importpath = "k8s.io/kubernetes/pkg/kubelet/network/hostport/testing", - deps = ["//pkg/kubelet/network/hostport:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/testing/fake.go b/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/testing/fake.go deleted file mode 100644 index 1d0a78f0b..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/hostport/testing/fake.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -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 testing - -import ( - "fmt" - - "k8s.io/kubernetes/pkg/kubelet/network/hostport" -) - -type fakeSyncer struct{} - -func NewFakeHostportSyncer() hostport.HostportSyncer { - return &fakeSyncer{} -} - -func (h *fakeSyncer) OpenPodHostportsAndSync(newPortMapping *hostport.PodPortMapping, natInterfaceName string, activePortMapping []*hostport.PodPortMapping) error { - return h.SyncHostports(natInterfaceName, activePortMapping) -} - -func (h *fakeSyncer) SyncHostports(natInterfaceName string, activePortMapping []*hostport.PodPortMapping) error { - for _, r := range activePortMapping { - if r.IP.To4() == nil { - return fmt.Errorf("Invalid or missing pod %s/%s IP", r.Namespace, r.Name) - } - } - - return nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/BUILD deleted file mode 100644 index d13c20baf..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/BUILD +++ /dev/null @@ -1,167 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "kubenet.go", - ] + select({ - "@io_bazel_rules_go//go/platform:android": [ - "kubenet_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:darwin": [ - "kubenet_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:dragonfly": [ - "kubenet_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:freebsd": [ - "kubenet_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:linux": [ - "kubenet_linux.go", - ], - "@io_bazel_rules_go//go/platform:nacl": [ - "kubenet_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:netbsd": [ - "kubenet_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:openbsd": [ - "kubenet_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:plan9": [ - "kubenet_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:solaris": [ - "kubenet_unsupported.go", - ], - "@io_bazel_rules_go//go/platform:windows": [ - "kubenet_unsupported.go", - ], - "//conditions:default": [], - }), - importpath = "k8s.io/kubernetes/pkg/kubelet/network/kubenet", - deps = select({ - "@io_bazel_rules_go//go/platform:android": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "@io_bazel_rules_go//go/platform:darwin": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "@io_bazel_rules_go//go/platform:dragonfly": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "@io_bazel_rules_go//go/platform:freebsd": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "@io_bazel_rules_go//go/platform:linux": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/hostport:go_default_library", - "//pkg/util/bandwidth:go_default_library", - "//pkg/util/dbus:go_default_library", - "//pkg/util/ebtables:go_default_library", - "//pkg/util/iptables:go_default_library", - "//pkg/util/sysctl:go_default_library", - "//vendor/github.com/containernetworking/cni/libcni:go_default_library", - "//vendor/github.com/containernetworking/cni/pkg/types:go_default_library", - "//vendor/github.com/containernetworking/cni/pkg/types/020:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/vishvananda/netlink:go_default_library", - "//vendor/golang.org/x/sys/unix:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:nacl": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "@io_bazel_rules_go//go/platform:netbsd": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "@io_bazel_rules_go//go/platform:openbsd": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "@io_bazel_rules_go//go/platform:plan9": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "@io_bazel_rules_go//go/platform:solaris": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "@io_bazel_rules_go//go/platform:windows": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - ], - "//conditions:default": [], - }), -) - -go_test( - name = "go_default_test", - srcs = select({ - "@io_bazel_rules_go//go/platform:linux": [ - "kubenet_linux_test.go", - ], - "//conditions:default": [], - }), - embed = [":go_default_library"], - deps = select({ - "@io_bazel_rules_go//go/platform:linux": [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/cni/testing:go_default_library", - "//pkg/kubelet/network/hostport/testing:go_default_library", - "//pkg/kubelet/network/testing:go_default_library", - "//pkg/util/bandwidth:go_default_library", - "//pkg/util/iptables/testing:go_default_library", - "//pkg/util/sysctl/testing:go_default_library", - "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/github.com/stretchr/testify/mock:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - "//vendor/k8s.io/utils/exec/testing: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"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet_linux.go b/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet_linux.go deleted file mode 100644 index 9fc7e3b27..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/kubenet/kubenet_linux.go +++ /dev/null @@ -1,868 +0,0 @@ -// +build linux - -/* -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 kubenet - -import ( - "fmt" - "io/ioutil" - "net" - "path/filepath" - "strings" - "sync" - "time" - - "github.com/containernetworking/cni/libcni" - cnitypes "github.com/containernetworking/cni/pkg/types" - cnitypes020 "github.com/containernetworking/cni/pkg/types/020" - "github.com/golang/glog" - "github.com/vishvananda/netlink" - "golang.org/x/sys/unix" - "k8s.io/api/core/v1" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - utilnet "k8s.io/apimachinery/pkg/util/net" - utilsets "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/network" - "k8s.io/kubernetes/pkg/kubelet/network/hostport" - "k8s.io/kubernetes/pkg/util/bandwidth" - utildbus "k8s.io/kubernetes/pkg/util/dbus" - utilebtables "k8s.io/kubernetes/pkg/util/ebtables" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" - utilsysctl "k8s.io/kubernetes/pkg/util/sysctl" - utilexec "k8s.io/utils/exec" -) - -const ( - BridgeName = "cbr0" - DefaultCNIDir = "/opt/cni/bin" - - sysctlBridgeCallIPTables = "net/bridge/bridge-nf-call-iptables" - - // fallbackMTU is used if an MTU is not specified, and we cannot determine the MTU - fallbackMTU = 1460 - - // ebtables Chain to store dedup rules - dedupChain = utilebtables.Chain("KUBE-DEDUP") - - // defaultIPAMDir is the default location for the checkpoint files stored by host-local ipam - // https://github.com/containernetworking/cni/tree/master/plugins/ipam/host-local#backends - defaultIPAMDir = "/var/lib/cni/networks" -) - -// CNI plugins required by kubenet in /opt/cni/bin or vendor directory -var requiredCNIPlugins = [...]string{"bridge", "host-local", "loopback"} - -type kubenetNetworkPlugin struct { - network.NoopNetworkPlugin - - host network.Host - netConfig *libcni.NetworkConfig - loConfig *libcni.NetworkConfig - cniConfig libcni.CNI - bandwidthShaper bandwidth.BandwidthShaper - mu sync.Mutex //Mutex for protecting podIPs map, netConfig, and shaper initialization - podIPs map[kubecontainer.ContainerID]string - mtu int - execer utilexec.Interface - nsenterPath string - hairpinMode kubeletconfig.HairpinMode - // kubenet can use either hostportSyncer and hostportManager to implement hostports - // Currently, if network host supports legacy features, hostportSyncer will be used, - // otherwise, hostportManager will be used. - hostportSyncer hostport.HostportSyncer - hostportManager hostport.HostPortManager - iptables utiliptables.Interface - sysctl utilsysctl.Interface - ebtables utilebtables.Interface - // vendorDir is passed by kubelet cni-bin-dir parameter. - // kubenet will search for cni binaries in DefaultCNIDir first, then continue to vendorDir. - vendorDir string - nonMasqueradeCIDR string - podCidr string - gateway net.IP -} - -func NewPlugin(networkPluginDir string) network.NetworkPlugin { - protocol := utiliptables.ProtocolIpv4 - execer := utilexec.New() - dbus := utildbus.New() - sysctl := utilsysctl.New() - iptInterface := utiliptables.New(execer, dbus, protocol) - return &kubenetNetworkPlugin{ - podIPs: make(map[kubecontainer.ContainerID]string), - execer: utilexec.New(), - iptables: iptInterface, - sysctl: sysctl, - vendorDir: networkPluginDir, - hostportSyncer: hostport.NewHostportSyncer(iptInterface), - hostportManager: hostport.NewHostportManager(iptInterface), - nonMasqueradeCIDR: "10.0.0.0/8", - } -} - -func (plugin *kubenetNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { - plugin.host = host - plugin.hairpinMode = hairpinMode - plugin.nonMasqueradeCIDR = nonMasqueradeCIDR - plugin.cniConfig = &libcni.CNIConfig{ - Path: []string{DefaultCNIDir, plugin.vendorDir}, - } - - if mtu == network.UseDefaultMTU { - if link, err := findMinMTU(); err == nil { - plugin.mtu = link.MTU - glog.V(5).Infof("Using interface %s MTU %d as bridge MTU", link.Name, link.MTU) - } else { - plugin.mtu = fallbackMTU - glog.Warningf("Failed to find default bridge MTU, using %d: %v", fallbackMTU, err) - } - } else { - plugin.mtu = mtu - } - - // Since this plugin uses a Linux bridge, set bridge-nf-call-iptables=1 - // is necessary to ensure kube-proxy functions correctly. - // - // This will return an error on older kernel version (< 3.18) as the module - // was built-in, we simply ignore the error here. A better thing to do is - // to check the kernel version in the future. - plugin.execer.Command("modprobe", "br-netfilter").CombinedOutput() - err := plugin.sysctl.SetSysctl(sysctlBridgeCallIPTables, 1) - if err != nil { - glog.Warningf("can't set sysctl %s: %v", sysctlBridgeCallIPTables, err) - } - - plugin.loConfig, err = libcni.ConfFromBytes([]byte(`{ - "cniVersion": "0.1.0", - "name": "kubenet-loopback", - "type": "loopback" -}`)) - if err != nil { - return fmt.Errorf("Failed to generate loopback config: %v", err) - } - - plugin.nsenterPath, err = plugin.execer.LookPath("nsenter") - if err != nil { - return fmt.Errorf("Failed to find nsenter binary: %v", err) - } - - // Need to SNAT outbound traffic from cluster - if err = plugin.ensureMasqRule(); err != nil { - return err - } - return nil -} - -// TODO: move thic logic into cni bridge plugin and remove this from kubenet -func (plugin *kubenetNetworkPlugin) ensureMasqRule() error { - if plugin.nonMasqueradeCIDR != "0.0.0.0/0" { - if _, err := plugin.iptables.EnsureRule(utiliptables.Append, utiliptables.TableNAT, utiliptables.ChainPostrouting, - "-m", "comment", "--comment", "kubenet: SNAT for outbound traffic from cluster", - "-m", "addrtype", "!", "--dst-type", "LOCAL", - "!", "-d", plugin.nonMasqueradeCIDR, - "-j", "MASQUERADE"); err != nil { - return fmt.Errorf("Failed to ensure that %s chain %s jumps to MASQUERADE: %v", utiliptables.TableNAT, utiliptables.ChainPostrouting, err) - } - } - return nil -} - -func findMinMTU() (*net.Interface, error) { - intfs, err := net.Interfaces() - if err != nil { - return nil, err - } - - mtu := 999999 - defIntfIndex := -1 - for i, intf := range intfs { - if ((intf.Flags & net.FlagUp) != 0) && (intf.Flags&(net.FlagLoopback|net.FlagPointToPoint) == 0) { - if intf.MTU < mtu { - mtu = intf.MTU - defIntfIndex = i - } - } - } - - if mtu >= 999999 || mtu < 576 || defIntfIndex < 0 { - return nil, fmt.Errorf("no suitable interface: %v", BridgeName) - } - - return &intfs[defIntfIndex], nil -} - -const NET_CONFIG_TEMPLATE = `{ - "cniVersion": "0.1.0", - "name": "kubenet", - "type": "bridge", - "bridge": "%s", - "mtu": %d, - "addIf": "%s", - "isGateway": true, - "ipMasq": false, - "hairpinMode": %t, - "ipam": { - "type": "host-local", - "subnet": "%s", - "gateway": "%s", - "routes": [ - { "dst": "0.0.0.0/0" } - ] - } -}` - -func (plugin *kubenetNetworkPlugin) Event(name string, details map[string]interface{}) { - if name != network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE { - return - } - - plugin.mu.Lock() - defer plugin.mu.Unlock() - - podCIDR, ok := details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR].(string) - if !ok { - glog.Warningf("%s event didn't contain pod CIDR", network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE) - return - } - - if plugin.netConfig != nil { - glog.Warningf("Ignoring subsequent pod CIDR update to %s", podCIDR) - return - } - - glog.V(5).Infof("PodCIDR is set to %q", podCIDR) - _, cidr, err := net.ParseCIDR(podCIDR) - if err == nil { - setHairpin := plugin.hairpinMode == kubeletconfig.HairpinVeth - // Set bridge address to first address in IPNet - cidr.IP[len(cidr.IP)-1] += 1 - - json := fmt.Sprintf(NET_CONFIG_TEMPLATE, BridgeName, plugin.mtu, network.DefaultInterfaceName, setHairpin, podCIDR, cidr.IP.String()) - glog.V(2).Infof("CNI network config set to %v", json) - plugin.netConfig, err = libcni.ConfFromBytes([]byte(json)) - if err == nil { - glog.V(5).Infof("CNI network config:\n%s", json) - - // Ensure cbr0 has no conflicting addresses; CNI's 'bridge' - // plugin will bail out if the bridge has an unexpected one - plugin.clearBridgeAddressesExcept(cidr) - } - plugin.podCidr = podCIDR - plugin.gateway = cidr.IP - } - - if err != nil { - glog.Warningf("Failed to generate CNI network config: %v", err) - } -} - -func (plugin *kubenetNetworkPlugin) clearBridgeAddressesExcept(keep *net.IPNet) { - bridge, err := netlink.LinkByName(BridgeName) - if err != nil { - return - } - - addrs, err := netlink.AddrList(bridge, unix.AF_INET) - if err != nil { - return - } - - for _, addr := range addrs { - if !utilnet.IPNetEqual(addr.IPNet, keep) { - glog.V(2).Infof("Removing old address %s from %s", addr.IPNet.String(), BridgeName) - netlink.AddrDel(bridge, &addr) - } - } -} - -func (plugin *kubenetNetworkPlugin) Name() string { - return KubenetPluginName -} - -func (plugin *kubenetNetworkPlugin) Capabilities() utilsets.Int { - return utilsets.NewInt() -} - -// setup sets up networking through CNI using the given ns/name and sandbox ID. -// TODO: Don't pass the pod to this method, it only needs it for bandwidth -// shaping and hostport management. -func (plugin *kubenetNetworkPlugin) setup(namespace string, name string, id kubecontainer.ContainerID, pod *v1.Pod, annotations map[string]string) error { - // Disable DAD so we skip the kernel delay on bringing up new interfaces. - if err := plugin.disableContainerDAD(id); err != nil { - glog.V(3).Infof("Failed to disable DAD in container: %v", err) - } - - // Bring up container loopback interface - if _, err := plugin.addContainerToNetwork(plugin.loConfig, "lo", namespace, name, id); err != nil { - return err - } - - // Hook container up with our bridge - resT, err := plugin.addContainerToNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id) - if err != nil { - return err - } - // Coerce the CNI result version - res, err := cnitypes020.GetResult(resT) - if err != nil { - return fmt.Errorf("unable to understand network config: %v", err) - } - if res.IP4 == nil { - return fmt.Errorf("CNI plugin reported no IPv4 address for container %v.", id) - } - ip4 := res.IP4.IP.IP.To4() - if ip4 == nil { - return fmt.Errorf("CNI plugin reported an invalid IPv4 address for container %v: %+v.", id, res.IP4) - } - - // Put the container bridge into promiscuous mode to force it to accept hairpin packets. - // TODO: Remove this once the kernel bug (#20096) is fixed. - if plugin.hairpinMode == kubeletconfig.PromiscuousBridge { - link, err := netlink.LinkByName(BridgeName) - if err != nil { - return fmt.Errorf("failed to lookup %q: %v", BridgeName, err) - } - if link.Attrs().Promisc != 1 { - // promiscuous mode is not on, then turn it on. - err := netlink.SetPromiscOn(link) - if err != nil { - return fmt.Errorf("Error setting promiscuous mode on %s: %v", BridgeName, err) - } - } - - // configure the ebtables rules to eliminate duplicate packets by best effort - plugin.syncEbtablesDedupRules(link.Attrs().HardwareAddr) - } - - plugin.podIPs[id] = ip4.String() - - // The first SetUpPod call creates the bridge; get a shaper for the sake of initialization - // TODO: replace with CNI traffic shaper plugin - shaper := plugin.shaper() - ingress, egress, err := bandwidth.ExtractPodBandwidthResources(annotations) - if err != nil { - return fmt.Errorf("Error reading pod bandwidth annotations: %v", err) - } - if egress != nil || ingress != nil { - if err := shaper.ReconcileCIDR(fmt.Sprintf("%s/32", ip4.String()), egress, ingress); err != nil { - return fmt.Errorf("Failed to add pod to shaper: %v", err) - } - } - - // The host can choose to not support "legacy" features. The remote - // shim doesn't support it (#35457), but the kubelet does. - if plugin.host.SupportsLegacyFeatures() { - // Open any hostport the pod's containers want - activePodPortMappings, err := plugin.getPodPortMappings() - if err != nil { - return err - } - - newPodPortMapping := hostport.ConstructPodPortMapping(pod, ip4) - if err := plugin.hostportSyncer.OpenPodHostportsAndSync(newPodPortMapping, BridgeName, activePodPortMappings); err != nil { - return err - } - } else { - // TODO: replace with CNI port-forwarding plugin - portMappings, err := plugin.host.GetPodPortMappings(id.ID) - if err != nil { - return err - } - if portMappings != nil && len(portMappings) > 0 { - if err := plugin.hostportManager.Add(id.ID, &hostport.PodPortMapping{ - Namespace: namespace, - Name: name, - PortMappings: portMappings, - IP: ip4, - HostNetwork: false, - }, BridgeName); err != nil { - return err - } - } - } - return nil -} - -func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID, annotations map[string]string) error { - plugin.mu.Lock() - defer plugin.mu.Unlock() - - start := time.Now() - defer func() { - glog.V(4).Infof("SetUpPod took %v for %s/%s", time.Since(start), namespace, name) - }() - - // TODO: Entire pod object only required for bw shaping and hostport. - pod, ok := plugin.host.GetPodByName(namespace, name) - if !ok { - return fmt.Errorf("pod %q cannot be found", name) - } - - if err := plugin.Status(); err != nil { - return fmt.Errorf("Kubenet cannot SetUpPod: %v", err) - } - - if err := plugin.setup(namespace, name, id, pod, annotations); err != nil { - // Make sure everything gets cleaned up on errors - podIP, _ := plugin.podIPs[id] - if err := plugin.teardown(namespace, name, id, podIP); err != nil { - // Not a hard error or warning - glog.V(4).Infof("Failed to clean up %s/%s after SetUpPod failure: %v", namespace, name, err) - } - - // TODO(#34278): Figure out if we need IP GC through the cri. - // The cri should always send us teardown events for stale sandboxes, - // this obviates the need for GC in the common case, for kubenet. - if plugin.host.SupportsLegacyFeatures() { - - // TODO: Remove this hack once we've figured out how to retrieve the netns - // of an exited container. Currently, restarting docker will leak a bunch of - // ips. This will exhaust available ip space unless we cleanup old ips. At the - // same time we don't want to try GC'ing them periodically as that could lead - // to a performance regression in starting pods. So on each setup failure, try - // GC on the assumption that the kubelet is going to retry pod creation, and - // when it does, there will be ips. - plugin.ipamGarbageCollection() - } - return err - } - - // Need to SNAT outbound traffic from cluster - if err := plugin.ensureMasqRule(); err != nil { - glog.Errorf("Failed to ensure MASQ rule: %v", err) - } - - return nil -} - -// Tears down as much of a pod's network as it can even if errors occur. Returns -// an aggregate error composed of all errors encountered during the teardown. -func (plugin *kubenetNetworkPlugin) teardown(namespace string, name string, id kubecontainer.ContainerID, podIP string) error { - errList := []error{} - - if podIP != "" { - glog.V(5).Infof("Removing pod IP %s from shaper", podIP) - // shaper wants /32 - if err := plugin.shaper().Reset(fmt.Sprintf("%s/32", podIP)); err != nil { - // Possible bandwidth shaping wasn't enabled for this pod anyways - glog.V(4).Infof("Failed to remove pod IP %s from shaper: %v", podIP, err) - } - - delete(plugin.podIPs, id) - } - - if err := plugin.delContainerFromNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id); err != nil { - // This is to prevent returning error when TearDownPod is called twice on the same pod. This helps to reduce event pollution. - if podIP != "" { - glog.Warningf("Failed to delete container from kubenet: %v", err) - } else { - errList = append(errList, err) - } - } - - // The host can choose to not support "legacy" features. The remote - // shim doesn't support it (#35457), but the kubelet does. - if plugin.host.SupportsLegacyFeatures() { - activePodPortMapping, err := plugin.getPodPortMappings() - if err == nil { - err = plugin.hostportSyncer.SyncHostports(BridgeName, activePodPortMapping) - } - if err != nil { - errList = append(errList, err) - } - } else { - portMappings, err := plugin.host.GetPodPortMappings(id.ID) - if err != nil { - errList = append(errList, err) - } else if portMappings != nil && len(portMappings) > 0 { - if err = plugin.hostportManager.Remove(id.ID, &hostport.PodPortMapping{ - Namespace: namespace, - Name: name, - PortMappings: portMappings, - HostNetwork: false, - }); err != nil { - errList = append(errList, err) - } - } - } - return utilerrors.NewAggregate(errList) -} - -func (plugin *kubenetNetworkPlugin) TearDownPod(namespace string, name string, id kubecontainer.ContainerID) error { - plugin.mu.Lock() - defer plugin.mu.Unlock() - - start := time.Now() - defer func() { - glog.V(4).Infof("TearDownPod took %v for %s/%s", time.Since(start), namespace, name) - }() - - if plugin.netConfig == nil { - return fmt.Errorf("Kubenet needs a PodCIDR to tear down pods") - } - - // no cached IP is Ok during teardown - podIP, _ := plugin.podIPs[id] - if err := plugin.teardown(namespace, name, id, podIP); err != nil { - return err - } - - // Need to SNAT outbound traffic from cluster - if err := plugin.ensureMasqRule(); err != nil { - glog.Errorf("Failed to ensure MASQ rule: %v", err) - } - - return nil -} - -// TODO: Use the addToNetwork function to obtain the IP of the Pod. That will assume idempotent ADD call to the plugin. -// Also fix the runtime's call to Status function to be done only in the case that the IP is lost, no need to do periodic calls -func (plugin *kubenetNetworkPlugin) GetPodNetworkStatus(namespace string, name string, id kubecontainer.ContainerID) (*network.PodNetworkStatus, error) { - plugin.mu.Lock() - defer plugin.mu.Unlock() - // Assuming the ip of pod does not change. Try to retrieve ip from kubenet map first. - if podIP, ok := plugin.podIPs[id]; ok { - return &network.PodNetworkStatus{IP: net.ParseIP(podIP)}, nil - } - - netnsPath, err := plugin.host.GetNetNS(id.ID) - if err != nil { - return nil, fmt.Errorf("Kubenet failed to retrieve network namespace path: %v", err) - } - if netnsPath == "" { - return nil, fmt.Errorf("Cannot find the network namespace, skipping pod network status for container %q", id) - } - ip, err := network.GetPodIP(plugin.execer, plugin.nsenterPath, netnsPath, network.DefaultInterfaceName) - if err != nil { - return nil, err - } - - plugin.podIPs[id] = ip.String() - return &network.PodNetworkStatus{IP: ip}, nil -} - -func (plugin *kubenetNetworkPlugin) Status() error { - // Can't set up pods if we don't have a PodCIDR yet - if plugin.netConfig == nil { - return fmt.Errorf("Kubenet does not have netConfig. This is most likely due to lack of PodCIDR") - } - - if !plugin.checkCNIPlugin() { - return fmt.Errorf("could not locate kubenet required CNI plugins %v at %q or %q", requiredCNIPlugins, DefaultCNIDir, plugin.vendorDir) - } - return nil -} - -// checkCNIPlugin returns if all kubenet required cni plugins can be found at /opt/cni/bin or user specified NetworkPluginDir. -func (plugin *kubenetNetworkPlugin) checkCNIPlugin() bool { - if plugin.checkCNIPluginInDir(DefaultCNIDir) || plugin.checkCNIPluginInDir(plugin.vendorDir) { - return true - } - return false -} - -// checkCNIPluginInDir returns if all required cni plugins are placed in dir -func (plugin *kubenetNetworkPlugin) checkCNIPluginInDir(dir string) bool { - files, err := ioutil.ReadDir(dir) - if err != nil { - return false - } - for _, cniPlugin := range requiredCNIPlugins { - found := false - for _, file := range files { - if strings.TrimSpace(file.Name()) == cniPlugin { - found = true - break - } - } - if !found { - return false - } - } - return true -} - -// getNonExitedPods returns a list of pods that have at least one running container. -func (plugin *kubenetNetworkPlugin) getNonExitedPods() ([]*kubecontainer.Pod, error) { - ret := []*kubecontainer.Pod{} - pods, err := plugin.host.GetRuntime().GetPods(true) - if err != nil { - return nil, fmt.Errorf("Failed to retrieve pods from runtime: %v", err) - } - for _, p := range pods { - if podIsExited(p) { - continue - } - ret = append(ret, p) - } - return ret, nil -} - -func (plugin *kubenetNetworkPlugin) getPodPortMappings() ([]*hostport.PodPortMapping, error) { - pods, err := plugin.getNonExitedPods() - if err != nil { - return nil, err - } - activePodPortMappings := make([]*hostport.PodPortMapping, 0) - for _, p := range pods { - containerID, err := plugin.host.GetRuntime().GetPodContainerID(p) - if err != nil { - continue - } - ipString, ok := plugin.podIPs[containerID] - if !ok { - continue - } - podIP := net.ParseIP(ipString) - if podIP == nil { - continue - } - if pod, ok := plugin.host.GetPodByName(p.Namespace, p.Name); ok { - activePodPortMappings = append(activePodPortMappings, hostport.ConstructPodPortMapping(pod, podIP)) - } - } - return activePodPortMappings, nil -} - -// ipamGarbageCollection will release unused IP. -// kubenet uses the CNI bridge plugin, which stores allocated ips on file. Each -// file created under defaultIPAMDir has the format: ip/container-hash. So this -// routine looks for hashes that are not reported by the currently running docker, -// and invokes DelNetwork on each one. Note that this will only work for the -// current CNI bridge plugin, because we have no way of finding the NetNs. -func (plugin *kubenetNetworkPlugin) ipamGarbageCollection() { - glog.V(2).Infof("Starting IP garbage collection") - - ipamDir := filepath.Join(defaultIPAMDir, KubenetPluginName) - files, err := ioutil.ReadDir(ipamDir) - if err != nil { - glog.Errorf("Failed to list files in %q: %v", ipamDir, err) - return - } - - // gather containerIDs for allocated ips - ipContainerIdMap := make(map[string]string) - for _, file := range files { - // skip non checkpoint file - if ip := net.ParseIP(file.Name()); ip == nil { - continue - } - - content, err := ioutil.ReadFile(filepath.Join(ipamDir, file.Name())) - if err != nil { - glog.Errorf("Failed to read file %v: %v", file, err) - } - ipContainerIdMap[file.Name()] = strings.TrimSpace(string(content)) - } - - // gather infra container IDs of current running Pods - runningContainerIDs := utilsets.String{} - pods, err := plugin.getNonExitedPods() - if err != nil { - glog.Errorf("Failed to get pods: %v", err) - return - } - for _, pod := range pods { - containerID, err := plugin.host.GetRuntime().GetPodContainerID(pod) - if err != nil { - glog.Warningf("Failed to get infra containerID of %q/%q: %v", pod.Namespace, pod.Name, err) - continue - } - - runningContainerIDs.Insert(strings.TrimSpace(containerID.ID)) - } - - // release leaked ips - for ip, containerID := range ipContainerIdMap { - // if the container is not running, release IP - if runningContainerIDs.Has(containerID) { - continue - } - // CNI requires all config to be presented, although only containerID is needed in this case - rt := &libcni.RuntimeConf{ - ContainerID: containerID, - IfName: network.DefaultInterfaceName, - // TODO: How do we find the NetNs of an exited container? docker inspect - // doesn't show us the pid, so we probably need to checkpoint - NetNS: "", - } - - glog.V(2).Infof("Releasing IP %q allocated to %q.", ip, containerID) - // CNI bridge plugin should try to release IP and then return - if err := plugin.cniConfig.DelNetwork(plugin.netConfig, rt); err != nil { - glog.Errorf("Error while releasing IP: %v", err) - } - } -} - -// podIsExited returns true if the pod is exited (all containers inside are exited). -func podIsExited(p *kubecontainer.Pod) bool { - for _, c := range p.Containers { - if c.State != kubecontainer.ContainerStateExited { - return false - } - } - for _, c := range p.Sandboxes { - if c.State != kubecontainer.ContainerStateExited { - return false - } - } - return true -} - -func (plugin *kubenetNetworkPlugin) buildCNIRuntimeConf(ifName string, id kubecontainer.ContainerID, needNetNs bool) (*libcni.RuntimeConf, error) { - netnsPath, err := plugin.host.GetNetNS(id.ID) - if needNetNs && err != nil { - glog.Errorf("Kubenet failed to retrieve network namespace path: %v", err) - } - - return &libcni.RuntimeConf{ - ContainerID: id.ID, - NetNS: netnsPath, - IfName: ifName, - }, nil -} - -func (plugin *kubenetNetworkPlugin) addContainerToNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) (cnitypes.Result, error) { - rt, err := plugin.buildCNIRuntimeConf(ifName, id, true) - if err != nil { - return nil, fmt.Errorf("Error building CNI config: %v", err) - } - - glog.V(3).Infof("Adding %s/%s to '%s' with CNI '%s' plugin and runtime: %+v", namespace, name, config.Network.Name, config.Network.Type, rt) - // The network plugin can take up to 3 seconds to execute, - // so yield the lock while it runs. - plugin.mu.Unlock() - res, err := plugin.cniConfig.AddNetwork(config, rt) - plugin.mu.Lock() - if err != nil { - return nil, fmt.Errorf("Error adding container to network: %v", err) - } - return res, nil -} - -func (plugin *kubenetNetworkPlugin) delContainerFromNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) error { - rt, err := plugin.buildCNIRuntimeConf(ifName, id, false) - if err != nil { - return fmt.Errorf("Error building CNI config: %v", err) - } - - glog.V(3).Infof("Removing %s/%s from '%s' with CNI '%s' plugin and runtime: %+v", namespace, name, config.Network.Name, config.Network.Type, rt) - err = plugin.cniConfig.DelNetwork(config, rt) - // The pod may not get deleted successfully at the first time. - // Ignore "no such file or directory" error in case the network has already been deleted in previous attempts. - if err != nil && !strings.Contains(err.Error(), "no such file or directory") { - return fmt.Errorf("Error removing container from network: %v", err) - } - return nil -} - -// shaper retrieves the bandwidth shaper and, if it hasn't been fetched before, -// initializes it and ensures the bridge is appropriately configured -// This function should only be called while holding the `plugin.mu` lock -func (plugin *kubenetNetworkPlugin) shaper() bandwidth.BandwidthShaper { - if plugin.bandwidthShaper == nil { - plugin.bandwidthShaper = bandwidth.NewTCShaper(BridgeName) - plugin.bandwidthShaper.ReconcileInterface() - } - return plugin.bandwidthShaper -} - -//TODO: make this into a goroutine and rectify the dedup rules periodically -func (plugin *kubenetNetworkPlugin) syncEbtablesDedupRules(macAddr net.HardwareAddr) { - if plugin.ebtables == nil { - plugin.ebtables = utilebtables.New(plugin.execer) - glog.V(3).Infof("Flushing dedup chain") - if err := plugin.ebtables.FlushChain(utilebtables.TableFilter, dedupChain); err != nil { - glog.Errorf("Failed to flush dedup chain: %v", err) - } - } - _, err := plugin.ebtables.GetVersion() - if err != nil { - glog.Warningf("Failed to get ebtables version. Skip syncing ebtables dedup rules: %v", err) - return - } - - glog.V(3).Infof("Filtering packets with ebtables on mac address: %v, gateway: %v, pod CIDR: %v", macAddr.String(), plugin.gateway.String(), plugin.podCidr) - _, err = plugin.ebtables.EnsureChain(utilebtables.TableFilter, dedupChain) - if err != nil { - glog.Errorf("Failed to ensure %v chain %v", utilebtables.TableFilter, dedupChain) - return - } - - _, err = plugin.ebtables.EnsureRule(utilebtables.Append, utilebtables.TableFilter, utilebtables.ChainOutput, "-j", string(dedupChain)) - if err != nil { - glog.Errorf("Failed to ensure %v chain %v jump to %v chain: %v", utilebtables.TableFilter, utilebtables.ChainOutput, dedupChain, err) - return - } - - commonArgs := []string{"-p", "IPv4", "-s", macAddr.String(), "-o", "veth+"} - _, err = plugin.ebtables.EnsureRule(utilebtables.Prepend, utilebtables.TableFilter, dedupChain, append(commonArgs, "--ip-src", plugin.gateway.String(), "-j", "ACCEPT")...) - if err != nil { - glog.Errorf("Failed to ensure packets from cbr0 gateway to be accepted") - return - - } - _, err = plugin.ebtables.EnsureRule(utilebtables.Append, utilebtables.TableFilter, dedupChain, append(commonArgs, "--ip-src", plugin.podCidr, "-j", "DROP")...) - if err != nil { - glog.Errorf("Failed to ensure packets from podCidr but has mac address of cbr0 to get dropped.") - return - } -} - -// disableContainerDAD disables duplicate address detection in the container. -// DAD has a negative affect on pod creation latency, since we have to wait -// a second or more for the addresses to leave the "tentative" state. Since -// we're sure there won't be an address conflict (since we manage them manually), -// this is safe. See issue 54651. -// -// This sets net.ipv6.conf.default.dad_transmits to 0. It must be run *before* -// the CNI plugins are run. -func (plugin *kubenetNetworkPlugin) disableContainerDAD(id kubecontainer.ContainerID) error { - key := "net/ipv6/conf/default/dad_transmits" - - sysctlBin, err := plugin.execer.LookPath("sysctl") - if err != nil { - return fmt.Errorf("Could not find sysctl binary: %s", err) - } - - netnsPath, err := plugin.host.GetNetNS(id.ID) - if err != nil { - return fmt.Errorf("Failed to get netns: %v", err) - } - if netnsPath == "" { - return fmt.Errorf("Pod has no network namespace") - } - - // If the sysctl doesn't exist, it means ipv6 is disabled; log and move on - if _, err := plugin.sysctl.GetSysctl(key); err != nil { - return fmt.Errorf("Ipv6 not enabled: %v", err) - } - - output, err := plugin.execer.Command(plugin.nsenterPath, - fmt.Sprintf("--net=%s", netnsPath), "-F", "--", - sysctlBin, "-w", fmt.Sprintf("%s=%s", key, "0"), - ).CombinedOutput() - if err != nil { - return fmt.Errorf("Failed to write sysctl: output: %s error: %s", - output, err) - } - return nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/metrics/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/network/metrics/BUILD deleted file mode 100644 index 6e3f4c4e5..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/metrics/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["metrics.go"], - importpath = "k8s.io/kubernetes/pkg/kubelet/network/metrics", - visibility = ["//visibility:public"], - deps = ["//vendor/github.com/prometheus/client_golang/prometheus:go_default_library"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/BUILD deleted file mode 100644 index 8759b8479..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/network/testing/BUILD +++ /dev/null @@ -1,55 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "fake_host.go", - "mock_network_plugin.go", - ], - importpath = "k8s.io/kubernetes/pkg/kubelet/network/testing", - deps = [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/container/testing:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/hostport:go_default_library", - "//vendor/github.com/golang/mock/gomock:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["plugins_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/util/sysctl/testing:go_default_library", - "//vendor/github.com/golang/mock/gomock:go_default_library", - "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/BUILD index bba1a722c..93e77dd95 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/BUILD @@ -15,6 +15,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/kubelet/pod", deps = [ "//pkg/kubelet/checkpoint:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/configmap:go_default_library", "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/secret:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager.go index be15616a9..6033ae8d5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager.go @@ -24,6 +24,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/kubelet/checkpoint" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" "k8s.io/kubernetes/pkg/kubelet/configmap" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/secret" @@ -121,18 +122,18 @@ type basicManager struct { // basicManager is keeping secretManager and configMapManager up-to-date. secretManager secret.Manager configMapManager configmap.Manager - checkpointManager checkpoint.Manager + checkpointManager checkpointmanager.CheckpointManager // A mirror pod client to create/delete mirror pods. MirrorClient } // NewBasicPodManager returns a functional Manager. -func NewBasicPodManager(client MirrorClient, secretManager secret.Manager, configMapManager configmap.Manager) Manager { +func NewBasicPodManager(client MirrorClient, secretManager secret.Manager, configMapManager configmap.Manager, cpm checkpointmanager.CheckpointManager) Manager { pm := &basicManager{} pm.secretManager = secretManager pm.configMapManager = configMapManager - pm.checkpointManager = checkpoint.GetInstance() + pm.checkpointManager = cpm pm.MirrorClient = client pm.SetPods(nil) return pm @@ -161,7 +162,7 @@ func (pm *basicManager) UpdatePod(pod *v1.Pod) { defer pm.lock.Unlock() pm.updatePodsInternal(pod) if pm.checkpointManager != nil { - if err := pm.checkpointManager.WritePod(pod); err != nil { + if err := checkpoint.WritePod(pm.checkpointManager, pod); err != nil { glog.Errorf("Error writing checkpoint for pod: %v", pod.GetName()) } } @@ -224,7 +225,7 @@ func (pm *basicManager) DeletePod(pod *v1.Pod) { delete(pm.podByFullName, podFullName) } if pm.checkpointManager != nil { - if err := pm.checkpointManager.DeletePod(pod); err != nil { + if err := checkpoint.DeletePod(pm.checkpointManager, pod); err != nil { glog.Errorf("Error deleting checkpoint for pod: %v", pod.GetName()) } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager_test.go index 557a5927f..0c24325bd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager_test.go @@ -34,7 +34,7 @@ func newTestManager() (*basicManager, *podtest.FakeMirrorClient) { fakeMirrorClient := podtest.NewFakeMirrorClient() secretManager := secret.NewFakeManager() configMapManager := configmap.NewFakeManager() - manager := NewBasicPodManager(fakeMirrorClient, secretManager, configMapManager).(*basicManager) + manager := NewBasicPodManager(fakeMirrorClient, secretManager, configMapManager, podtest.NewMockCheckpointManager()).(*basicManager) return manager, fakeMirrorClient } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/testing/BUILD index b0364a226..28daeb0e3 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/testing/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/testing/BUILD @@ -13,6 +13,8 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/kubelet/pod/testing", deps = [ + "//pkg/kubelet/checkpoint:go_default_library", + "//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/types:go_default_library", "//vendor/github.com/stretchr/testify/mock:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/testing/fake_mirror_client.go b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/testing/fake_mirror_client.go index 7a7dd6ae6..a36a80a2c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/pod/testing/fake_mirror_client.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/pod/testing/fake_mirror_client.go @@ -21,6 +21,8 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" + cp "k8s.io/kubernetes/pkg/kubelet/checkpoint" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" ) @@ -81,3 +83,37 @@ func (fmc *FakeMirrorClient) GetCounts(podFullName string) (int, int) { defer fmc.mirrorPodLock.RUnlock() return fmc.createCounts[podFullName], fmc.deleteCounts[podFullName] } + +type MockCheckpointManager struct { + checkpoint map[string]*cp.Data +} + +func (ckm *MockCheckpointManager) CreateCheckpoint(checkpointKey string, checkpoint checkpointmanager.Checkpoint) error { + ckm.checkpoint[checkpointKey] = (checkpoint.(*cp.Data)) + return nil +} + +func (ckm *MockCheckpointManager) GetCheckpoint(checkpointKey string, checkpoint checkpointmanager.Checkpoint) error { + *(checkpoint.(*cp.Data)) = *(ckm.checkpoint[checkpointKey]) + return nil +} + +func (ckm *MockCheckpointManager) RemoveCheckpoint(checkpointKey string) error { + _, ok := ckm.checkpoint[checkpointKey] + if ok { + delete(ckm.checkpoint, "moo") + } + return nil +} + +func (ckm *MockCheckpointManager) ListCheckpoints() ([]string, error) { + var keys []string + for key := range ckm.checkpoint { + keys = append(keys, key) + } + return keys, nil +} + +func NewMockCheckpointManager() checkpointmanager.CheckpointManager { + return &MockCheckpointManager{checkpoint: make(map[string]*cp.Data)} +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/pod_container_deletor.go b/vendor/k8s.io/kubernetes/pkg/kubelet/pod_container_deletor.go index caf00b05c..48a85958d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/pod_container_deletor.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/pod_container_deletor.go @@ -45,10 +45,8 @@ func newPodContainerDeletor(runtime kubecontainer.Runtime, containersToKeep int) buffer := make(chan kubecontainer.ContainerID, containerDeletorBufferLimit) go wait.Until(func() { for { - select { - case id := <-buffer: - runtime.DeleteContainer(id) - } + id := <-buffer + runtime.DeleteContainer(id) } }, 0, wait.NeverStop) @@ -101,6 +99,7 @@ func (p *podContainerDeletor) deleteContainersInPod(filterContainerID string, po containersToKeep := p.containersToKeep if removeAll { containersToKeep = 0 + filterContainerID = "" } for _, candidate := range getContainersToDeleteInPod(filterContainerID, podStatus, containersToKeep) { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/pod_workers.go b/vendor/k8s.io/kubernetes/pkg/kubelet/pod_workers.go index 6a8a33353..5a1fb9927 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/pod_workers.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/pod_workers.go @@ -235,7 +235,7 @@ func (p *podWorkers) removeWorker(uid types.UID) { delete(p.podUpdates, uid) // If there is an undelivered work update for this pod we need to remove it // since per-pod goroutine won't be able to put it to the already closed - // channel when it finish processing the current work update. + // channel when it finishes processing the current work update. if _, cached := p.lastUndeliveredWorkUpdate[uid]; cached { delete(p.lastUndeliveredWorkUpdate, uid) } @@ -306,7 +306,7 @@ func killPodNow(podWorkers PodWorkers, recorder record.EventRecorder) eviction.K type response struct { err error } - ch := make(chan response) + ch := make(chan response, 1) podWorkers.UpdatePod(&UpdatePodOptions{ Pod: pod, UpdateType: kubetypes.SyncPodKill, diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/preemption/preemption.go b/vendor/k8s.io/kubernetes/pkg/kubelet/preemption/preemption.go index 96d829e4f..fdccd2c40 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/preemption/preemption.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/preemption/preemption.go @@ -248,7 +248,6 @@ func sortPodsByQOS(pods []*v1.Pod) (bestEffort, burstable, guaranteed []*v1.Pod) // returns true if pod1 has a smaller request than pod2 func smallerResourceRequest(pod1 *v1.Pod, pod2 *v1.Pod) bool { priorityList := []v1.ResourceName{ - v1.ResourceNvidiaGPU, v1.ResourceMemory, v1.ResourceCPU, } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/BUILD index e208ff07b..0807bfa08 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/BUILD @@ -26,6 +26,7 @@ go_library( "//pkg/probe/http:go_default_library", "//pkg/probe/tcp:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/common_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/common_test.go index f19ecd97b..74cd10b4b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/common_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/common_test.go @@ -99,7 +99,7 @@ func setTestProbe(pod *v1.Pod, probeType probeType, probeSpec v1.Probe) { func newTestManager() *manager { refManager := kubecontainer.NewRefManager() refManager.SetRef(testContainerID, &v1.ObjectReference{}) // Suppress prober warnings. - podManager := kubepod.NewBasicPodManager(nil, nil, nil) + podManager := kubepod.NewBasicPodManager(nil, nil, nil, nil) // Add test pod to pod manager, so that status manager can get the pod from pod manager if needed. podManager.AddPod(getTestPod()) m := NewManager( diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/prober_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/prober_manager.go index fcbad24fe..0e53e0940 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/prober_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/prober_manager.go @@ -20,6 +20,7 @@ import ( "sync" "github.com/golang/glog" + "github.com/prometheus/client_golang/prometheus" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" @@ -31,6 +32,16 @@ import ( "k8s.io/kubernetes/pkg/kubelet/util/format" ) +// ProberResults stores the results of a probe as prometheus metrics. +var ProberResults = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Subsystem: "prober", + Name: "probe_result", + Help: "The result of a liveness or readiness probe for a container.", + }, + []string{"probe_type", "container_name", "pod_name", "namespace", "pod_uid"}, +) + // Manager manages pod probing. It creates a probe "worker" for every container that specifies a // probe (AddPod). The worker periodically probes its assigned container and caches the results. The // manager use the cached probe results to set the appropriate Ready state in the PodStatus when diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/results/results_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/results/results_manager.go index 2b01be7ba..f66a472c3 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/results/results_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/results/results_manager.go @@ -58,6 +58,18 @@ func (r Result) String() string { } } +// ToPrometheusType translates a Result to a form which is better understood by prometheus. +func (r Result) ToPrometheusType() float64 { + switch r { + case Success: + return 0 + case Failure: + return 1 + default: + return -1 + } +} + // Update is an enum of the types of updates sent over the Updates channel. type Update struct { ContainerID kubecontainer.ContainerID diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker.go b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker.go index d96365a2e..cdefc1da2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker.go @@ -21,6 +21,7 @@ import ( "time" "github.com/golang/glog" + "github.com/prometheus/client_golang/prometheus" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/runtime" podutil "k8s.io/kubernetes/pkg/api/v1/pod" @@ -65,6 +66,10 @@ type worker struct { // If set, skip probing. onHold bool + + // proberResultsMetricLabels holds the labels attached to this worker + // for the ProberResults metric. + proberResultsMetricLabels prometheus.Labels } // Creates and starts a new probe worker. @@ -93,6 +98,14 @@ func newWorker( w.initialValue = results.Success } + w.proberResultsMetricLabels = prometheus.Labels{ + "probe_type": w.probeType.String(), + "container_name": w.container.Name, + "pod_name": w.pod.Name, + "namespace": w.pod.Namespace, + "pod_uid": string(w.pod.UID), + } + return w } @@ -114,6 +127,7 @@ func (w *worker) run() { } w.probeManager.removeWorker(w.pod.UID, w.container.Name, w.probeType) + ProberResults.Delete(w.proberResultsMetricLabels) }() probeLoop: @@ -218,6 +232,7 @@ func (w *worker) doProbe() (keepGoing bool) { } w.resultsManager.Set(w.containerID, result, w.pod) + ProberResults.With(w.proberResultsMetricLabels).Set(result.ToPrometheusType()) if w.probeType == liveness && result == results.Failure { // The container fails a liveness check, it will need to be restarted. @@ -225,7 +240,7 @@ func (w *worker) doProbe() (keepGoing bool) { // chance of hitting #21751, where running `docker exec` when a // container is being stopped may lead to corrupted container state. w.onHold = true - w.resultRun = 1 + w.resultRun = 0 } return true diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker_test.go index f05723e1c..d7473a35b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker_test.go @@ -118,7 +118,7 @@ func TestDoProbe(t *testing.T) { } // Clean up. - m.statusManager = status.NewManager(&fake.Clientset{}, kubepod.NewBasicPodManager(nil, nil, nil), &statustest.FakePodDeletionSafetyProvider{}) + m.statusManager = status.NewManager(&fake.Clientset{}, kubepod.NewBasicPodManager(nil, nil, nil, nil), &statustest.FakePodDeletionSafetyProvider{}) resultsManager(m, probeType).Remove(testContainerID) } } @@ -352,7 +352,7 @@ func TestResultRunOnLivenessCheckFailure(t *testing.T) { expectContinue(t, w, w.doProbe(), msg) expectResult(t, w, results.Success, msg) if w.resultRun != 1 { - t.Errorf("Prober resultRun should 1") + t.Errorf("Prober resultRun should be 1") } m.prober.exec = fakeExecProber{probe.Failure, nil} @@ -360,7 +360,7 @@ func TestResultRunOnLivenessCheckFailure(t *testing.T) { expectContinue(t, w, w.doProbe(), msg) expectResult(t, w, results.Success, msg) if w.resultRun != 1 { - t.Errorf("Prober resultRun should 1") + t.Errorf("Prober resultRun should be 1") } m.prober.exec = fakeExecProber{probe.Failure, nil} @@ -372,13 +372,13 @@ func TestResultRunOnLivenessCheckFailure(t *testing.T) { } // Exceeding FailureThreshold should cause resultRun to - // reset to 1 so that the probe on the restarted pod + // reset to 0 so that the probe on the restarted pod // also gets FailureThreshold attempts to succeed. m.prober.exec = fakeExecProber{probe.Failure, nil} msg = "3rd probe failure, result failure" expectContinue(t, w, w.doProbe(), msg) expectResult(t, w, results.Failure, msg) - if w.resultRun != 1 { - t.Errorf("Prober resultRun should be reset to 1") + if w.resultRun != 0 { + t.Errorf("Prober resultRun should be reset to 0") } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/BUILD index 6f3112676..05c6efd27 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/BUILD @@ -20,7 +20,6 @@ go_library( "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/util:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/BUILD index 883c78248..a8db6e73c 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/BUILD @@ -55,7 +55,6 @@ go_library( "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/apis/cri/testing:go_default_library", "//pkg/kubelet/util:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/fake_image_service.go b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/fake_image_service.go index cdb90b927..1f89b457a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/fake_image_service.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/fake_image_service.go @@ -17,7 +17,8 @@ limitations under the License. package fake import ( - "golang.org/x/net/context" + "context" + kubeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/fake_runtime.go b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/fake_runtime.go index e6a7ce93b..ebb826e27 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/fake_runtime.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/fake/fake_runtime.go @@ -17,10 +17,10 @@ limitations under the License. package fake import ( + "context" "fmt" "time" - "golang.org/x/net/context" "google.golang.org/grpc" kubeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" apitest "k8s.io/kubernetes/pkg/kubelet/apis/cri/testing" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/remote_image.go b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/remote_image.go index 21bcaea63..d6eae5e38 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/remote_image.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/remote_image.go @@ -43,7 +43,7 @@ func NewRemoteImageService(endpoint string, connectionTimeout time.Duration) (in return nil, err } - conn, err := grpc.Dial(addr, grpc.WithInsecure(), grpc.WithTimeout(connectionTimeout), grpc.WithDialer(dailer)) + conn, err := grpc.Dial(addr, grpc.WithInsecure(), grpc.WithTimeout(connectionTimeout), grpc.WithDialer(dailer), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize))) if err != nil { glog.Errorf("Connect remote image service %s failed: %v", addr, err) return nil, err diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/remote_runtime.go b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/remote_runtime.go index 9860d7356..197cd913f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/remote_runtime.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/remote_runtime.go @@ -17,13 +17,13 @@ limitations under the License. package remote import ( + "context" "errors" "fmt" "strings" "time" "github.com/golang/glog" - "golang.org/x/net/context" "google.golang.org/grpc" internalapi "k8s.io/kubernetes/pkg/kubelet/apis/cri" @@ -40,12 +40,12 @@ type RemoteRuntimeService struct { // NewRemoteRuntimeService creates a new internalapi.RuntimeService. func NewRemoteRuntimeService(endpoint string, connectionTimeout time.Duration) (internalapi.RuntimeService, error) { - glog.Infof("Connecting to runtime service %s", endpoint) + glog.V(3).Infof("Connecting to runtime service %s", endpoint) addr, dailer, err := util.GetAddressAndDialer(endpoint) if err != nil { return nil, err } - conn, err := grpc.Dial(addr, grpc.WithInsecure(), grpc.WithTimeout(connectionTimeout), grpc.WithDialer(dailer)) + conn, err := grpc.Dial(addr, grpc.WithInsecure(), grpc.WithTimeout(connectionTimeout), grpc.WithDialer(dailer), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize))) if err != nil { glog.Errorf("Connect remote runtime %s failed: %v", addr, err) return nil, err diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/utils.go b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/utils.go index bd86492ac..784882aa2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/remote/utils.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/remote/utils.go @@ -17,14 +17,17 @@ limitations under the License. package remote import ( + "context" "fmt" "time" - "golang.org/x/net/context" - runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) +// maxMsgSize use 8MB as the default message size limit. +// grpc library default is 4MB +const maxMsgSize = 1024 * 1024 * 8 + // getContextWithTimeout returns a context with timeout. func getContextWithTimeout(timeout time.Duration) (context.Context, context.CancelFunc) { return context.WithTimeout(context.Background(), timeout) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/BUILD deleted file mode 100644 index 83c07f979..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/BUILD +++ /dev/null @@ -1,110 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "cap.go", - "config.go", - "container_id.go", - "doc.go", - "image.go", - "log.go", - "rkt.go", - "systemd.go", - "version.go", - ], - importpath = "k8s.io/kubernetes/pkg/kubelet/rkt", - deps = [ - "//pkg/credentialprovider:go_default_library", - "//pkg/credentialprovider/secrets:go_default_library", - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/events:go_default_library", - "//pkg/kubelet/images:go_default_library", - "//pkg/kubelet/leaky:go_default_library", - "//pkg/kubelet/lifecycle:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/hairpin:go_default_library", - "//pkg/kubelet/prober/results:go_default_library", - "//pkg/kubelet/types:go_default_library", - "//pkg/kubelet/util/format:go_default_library", - "//pkg/securitycontext:go_default_library", - "//pkg/util/parsers:go_default_library", - "//pkg/util/selinux:go_default_library", - "//pkg/util/strings:go_default_library", - "//pkg/util/term:go_default_library", - "//pkg/util/version:go_default_library", - "//vendor/github.com/appc/spec/schema:go_default_library", - "//vendor/github.com/appc/spec/schema/types:go_default_library", - "//vendor/github.com/coreos/go-systemd/dbus:go_default_library", - "//vendor/github.com/coreos/go-systemd/unit:go_default_library", - "//vendor/github.com/coreos/rkt/api/v1alpha:go_default_library", - "//vendor/github.com/docker/docker/api/types:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/google.golang.org/grpc:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait: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/flowcontrol:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "fake_rkt_interface_test.go", - "rkt_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/container/testing:go_default_library", - "//pkg/kubelet/lifecycle:go_default_library", - "//pkg/kubelet/network:go_default_library", - "//pkg/kubelet/network/kubenet:go_default_library", - "//pkg/kubelet/network/testing:go_default_library", - "//pkg/kubelet/types:go_default_library", - "//vendor/github.com/appc/spec/schema:go_default_library", - "//vendor/github.com/appc/spec/schema/types:go_default_library", - "//vendor/github.com/coreos/go-systemd/dbus:go_default_library", - "//vendor/github.com/coreos/go-systemd/unit:go_default_library", - "//vendor/github.com/coreos/rkt/api/v1alpha:go_default_library", - "//vendor/github.com/golang/mock/gomock:go_default_library", - "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/google.golang.org/grpc:go_default_library", - "//vendor/k8s.io/api/core/v1: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/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", - "//vendor/k8s.io/client-go/util/testing:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - "//vendor/k8s.io/utils/exec/testing:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/OWNERS b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/OWNERS deleted file mode 100644 index 9b15beaf0..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -approvers: -- euank -- yifan-gu diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/cap.go b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/cap.go deleted file mode 100644 index bbf7cdb55..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/cap.go +++ /dev/null @@ -1,110 +0,0 @@ -/* -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 rkt - -// TODO(yifan): Export this to higher level package. -const ( - CAP_CHOWN = iota - CAP_DAC_OVERRIDE - CAP_DAC_READ_SEARCH - CAP_FOWNER - CAP_FSETID - CAP_KILL - CAP_SETGID - CAP_SETUID - CAP_SETPCAP - CAP_LINUX_IMMUTABLE - CAP_NET_BIND_SERVICE - CAP_NET_BROADCAST - CAP_NET_ADMIN - CAP_NET_RAW - CAP_IPC_LOCK - CAP_IPC_OWNER - CAP_SYS_MODULE - CAP_SYS_RAWIO - CAP_SYS_CHROOT - CAP_SYS_PTRACE - CAP_SYS_PACCT - CAP_SYS_ADMIN - CAP_SYS_BOOT - CAP_SYS_NICE - CAP_SYS_RESOURCE - CAP_SYS_TIME - CAP_SYS_TTY_CONFIG - CAP_MKNOD - CAP_LEASE - CAP_AUDIT_WRITE - CAP_AUDIT_CONTROL - CAP_SETFCAP - CAP_MAC_OVERRIDE - CAP_MAC_ADMIN - CAP_SYSLOG - CAP_WAKE_ALARM - CAP_BLOCK_SUSPEND - CAP_AUDIT_READ -) - -// TODO(yifan): Export this to higher level package. -var capabilityList = map[int]string{ - CAP_CHOWN: "CAP_CHOWN", - CAP_DAC_OVERRIDE: "CAP_DAC_OVERRIDE", - CAP_DAC_READ_SEARCH: "CAP_DAC_READ_SEARCH", - CAP_FOWNER: "CAP_FOWNER", - CAP_FSETID: "CAP_FSETID", - CAP_KILL: "CAP_KILL", - CAP_SETGID: "CAP_SETGID", - CAP_SETUID: "CAP_SETUID", - CAP_SETPCAP: "CAP_SETPCAP", - CAP_LINUX_IMMUTABLE: "CAP_LINUX_IMMUTABLE", - CAP_NET_BIND_SERVICE: "CAP_NET_BIND_SERVICE", - CAP_NET_BROADCAST: "CAP_NET_BROADCAST", - CAP_NET_ADMIN: "CAP_NET_ADMIN", - CAP_NET_RAW: "CAP_NET_RAW", - CAP_IPC_LOCK: "CAP_IPC_LOCK", - CAP_IPC_OWNER: "CAP_IPC_OWNER", - CAP_SYS_MODULE: "CAP_SYS_MODULE", - CAP_SYS_RAWIO: "CAP_SYS_RAWIO", - CAP_SYS_CHROOT: "CAP_SYS_CHROOT", - CAP_SYS_PTRACE: "CAP_SYS_PTRACE", - CAP_SYS_PACCT: "CAP_SYS_PACCT", - CAP_SYS_ADMIN: "CAP_SYS_ADMIN", - CAP_SYS_BOOT: "CAP_SYS_BOOT", - CAP_SYS_NICE: "CAP_SYS_NICE", - CAP_SYS_RESOURCE: "CAP_SYS_RESOURCE", - CAP_SYS_TIME: "CAP_SYS_TIME", - CAP_SYS_TTY_CONFIG: "CAP_SYS_TTY_CONFIG", - CAP_MKNOD: "CAP_MKNOD", - CAP_LEASE: "CAP_LEASE", - CAP_AUDIT_WRITE: "CAP_AUDIT_WRITE", - CAP_AUDIT_CONTROL: "CAP_AUDIT_CONTROL", - CAP_SETFCAP: "CAP_SETFCAP", - CAP_MAC_OVERRIDE: "CAP_MAC_OVERRIDE", - CAP_MAC_ADMIN: "CAP_MAC_ADMIN", - CAP_SYSLOG: "CAP_SYSLOG", - CAP_WAKE_ALARM: "CAP_WAKE_ALARM", - CAP_BLOCK_SUSPEND: "CAP_BLOCK_SUSPEND", - CAP_AUDIT_READ: "CAP_AUDIT_READ", -} - -// allCapabilities returns the capability list with all capabilities. -func allCapabilities() []string { - var capabilities []string - for _, cap := range capabilityList { - capabilities = append(capabilities, cap) - } - return capabilities -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/config.go b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/config.go deleted file mode 100644 index ebdf34a1e..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/config.go +++ /dev/null @@ -1,108 +0,0 @@ -/* -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 rkt - -import ( - "fmt" - - rktapi "github.com/coreos/rkt/api/v1alpha" - "golang.org/x/net/context" -) - -// Config stores the global configuration for the rkt runtime. -// Detailed documents can be found at: -// https://github.com/coreos/rkt/blob/master/Documentation/commands.md#global-options -type Config struct { - // The absolute path to the binary, or leave empty to find it in $PATH. - Path string - // The rkt data directory. - Dir string - // The image to use as stage1. - Stage1Image string - // The debug flag for rkt. - Debug bool - // Comma-separated list of security features to disable. - // Allowed values: "none", "image", "tls", "ondisk", "http", "all". - InsecureOptions string - // The local config directory. - LocalConfigDir string - // The user config directory. - UserConfigDir string - // The system config directory. - SystemConfigDir string -} - -// buildGlobalOptions returns an array of global command line options. -func (c *Config) buildGlobalOptions() []string { - var result []string - if c == nil { - return result - } - - if c.Debug { - result = append(result, "--debug=true") - } - if c.InsecureOptions != "" { - result = append(result, fmt.Sprintf("--insecure-options=%s", c.InsecureOptions)) - } - if c.LocalConfigDir != "" { - result = append(result, fmt.Sprintf("--local-config=%s", c.LocalConfigDir)) - } - if c.UserConfigDir != "" { - result = append(result, fmt.Sprintf("--user-config=%s", c.UserConfigDir)) - } - if c.SystemConfigDir != "" { - result = append(result, fmt.Sprintf("--system-config=%s", c.SystemConfigDir)) - } - if c.Dir != "" { - result = append(result, fmt.Sprintf("--dir=%s", c.Dir)) - } - return result -} - -// getConfig gets configurations from the rkt API service -// and merge it with the existing config. The merge rule is -// that the fields in the provided config will override the -// result that get from the rkt api service. -func (r *Runtime) getConfig(cfg *Config) (*Config, error) { - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - resp, err := r.apisvc.GetInfo(ctx, &rktapi.GetInfoRequest{}) - if err != nil { - return nil, err - } - - flags := resp.Info.GlobalFlags - - if flags.Dir != "" { - cfg.Dir = flags.Dir - } - if flags.LocalConfigDir != "" { - cfg.LocalConfigDir = flags.LocalConfigDir - } - if flags.UserConfigDir != "" { - cfg.UserConfigDir = flags.UserConfigDir - } - if flags.SystemConfigDir != "" { - cfg.SystemConfigDir = flags.SystemConfigDir - } - if flags.InsecureFlags != "" { - cfg.InsecureOptions = fmt.Sprintf("%s,%s", cfg.InsecureOptions, flags.InsecureFlags) - } - - return cfg, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/container_id.go b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/container_id.go deleted file mode 100644 index ac37c1815..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/container_id.go +++ /dev/null @@ -1,55 +0,0 @@ -/* -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 rkt - -import ( - "fmt" - "strings" - - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" -) - -// containerID defines the ID of rkt containers, it will -// be returned to kubelet, and kubelet will use this for -// container level operations. -type containerID struct { - uuid string // rkt uuid of the pod. - appName string // Name of the app in that pod. -} - -// buildContainerID constructs the containers's ID using containerID, -// which consists of the pod uuid and the container name. -// The result can be used to uniquely identify a container. -func buildContainerID(c *containerID) kubecontainer.ContainerID { - return kubecontainer.ContainerID{ - Type: RktType, - ID: fmt.Sprintf("%s:%s", c.uuid, c.appName), - } -} - -// parseContainerID parses the containerID into pod uuid and the container name. The -// results can be used to get more information of the container. -func parseContainerID(id kubecontainer.ContainerID) (*containerID, error) { - tuples := strings.Split(id.ID, ":") - if len(tuples) != 2 { - return nil, fmt.Errorf("rkt: cannot parse container ID for: %q, required format is [UUID:APPNAME]", id) - } - return &containerID{ - uuid: tuples[0], - appName: tuples[1], - }, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/doc.go b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/doc.go deleted file mode 100644 index ac3ca3636..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -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 rkt contains the Containerruntime interface implementation for rkt. -package rkt // import "k8s.io/kubernetes/pkg/kubelet/rkt" diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/fake_rkt_interface_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/fake_rkt_interface_test.go deleted file mode 100644 index 90ca9c35c..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/fake_rkt_interface_test.go +++ /dev/null @@ -1,218 +0,0 @@ -/* -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 rkt - -import ( - "fmt" - "strconv" - "strings" - "sync" - - "github.com/coreos/go-systemd/dbus" - rktapi "github.com/coreos/rkt/api/v1alpha" - "golang.org/x/net/context" - "google.golang.org/grpc" - "k8s.io/apimachinery/pkg/types" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" -) - -// fakeRktInterface mocks the rktapi.PublicAPIClient interface for testing purpose. -type fakeRktInterface struct { - sync.Mutex - info rktapi.Info - images []*rktapi.Image - podFilters []*rktapi.PodFilter - pods []*rktapi.Pod - called []string - err error -} - -func newFakeRktInterface() *fakeRktInterface { - return &fakeRktInterface{} -} - -func (f *fakeRktInterface) CleanCalls() { - f.Lock() - defer f.Unlock() - f.called = nil -} - -func (f *fakeRktInterface) GetInfo(ctx context.Context, in *rktapi.GetInfoRequest, opts ...grpc.CallOption) (*rktapi.GetInfoResponse, error) { - f.Lock() - defer f.Unlock() - - f.called = append(f.called, "GetInfo") - return &rktapi.GetInfoResponse{Info: &f.info}, f.err -} - -func (f *fakeRktInterface) ListPods(ctx context.Context, in *rktapi.ListPodsRequest, opts ...grpc.CallOption) (*rktapi.ListPodsResponse, error) { - f.Lock() - defer f.Unlock() - - f.called = append(f.called, "ListPods") - f.podFilters = in.Filters - return &rktapi.ListPodsResponse{Pods: f.pods}, f.err -} - -func (f *fakeRktInterface) InspectPod(ctx context.Context, in *rktapi.InspectPodRequest, opts ...grpc.CallOption) (*rktapi.InspectPodResponse, error) { - f.Lock() - defer f.Unlock() - - f.called = append(f.called, "InspectPod") - for _, pod := range f.pods { - if pod.Id == in.Id { - return &rktapi.InspectPodResponse{Pod: pod}, f.err - } - } - return &rktapi.InspectPodResponse{}, fmt.Errorf("pod %q not found", in.Id) -} - -func (f *fakeRktInterface) ListImages(ctx context.Context, in *rktapi.ListImagesRequest, opts ...grpc.CallOption) (*rktapi.ListImagesResponse, error) { - f.Lock() - defer f.Unlock() - - f.called = append(f.called, "ListImages") - return &rktapi.ListImagesResponse{Images: f.images}, f.err -} - -func (f *fakeRktInterface) InspectImage(ctx context.Context, in *rktapi.InspectImageRequest, opts ...grpc.CallOption) (*rktapi.InspectImageResponse, error) { - return nil, fmt.Errorf("Not implemented") -} - -func (f *fakeRktInterface) ListenEvents(ctx context.Context, in *rktapi.ListenEventsRequest, opts ...grpc.CallOption) (rktapi.PublicAPI_ListenEventsClient, error) { - return nil, fmt.Errorf("Not implemented") -} - -func (f *fakeRktInterface) GetLogs(ctx context.Context, in *rktapi.GetLogsRequest, opts ...grpc.CallOption) (rktapi.PublicAPI_GetLogsClient, error) { - return nil, fmt.Errorf("Not implemented") -} - -// fakeSystemd mocks the systemdInterface for testing purpose. -// TODO(yifan): Remove this once we have a package for launching rkt pods. -// See https://github.com/coreos/rkt/issues/1769. -type fakeSystemd struct { - sync.Mutex - called []string - resetFailedUnits []string - version string - err error -} - -func newFakeSystemd() *fakeSystemd { - return &fakeSystemd{} -} - -func (f *fakeSystemd) CleanCalls() { - f.Lock() - defer f.Unlock() - f.called = nil -} - -func (f *fakeSystemd) Version() (systemdVersion, error) { - f.Lock() - defer f.Unlock() - - f.called = append(f.called, "Version") - v, _ := strconv.Atoi(f.version) - return systemdVersion(v), f.err -} - -func (f *fakeSystemd) ListUnits() ([]dbus.UnitStatus, error) { - return nil, fmt.Errorf("Not implemented") -} - -func (f *fakeSystemd) StopUnit(name string, mode string, ch chan<- string) (int, error) { - return 0, fmt.Errorf("Not implemented") -} - -func (f *fakeSystemd) RestartUnit(name string, mode string, ch chan<- string) (int, error) { - return 0, fmt.Errorf("Not implemented") -} - -func (f *fakeSystemd) ResetFailedUnit(name string) error { - f.called = append(f.called, "ResetFailedUnit") - f.resetFailedUnits = append(f.resetFailedUnits, name) - return f.err -} - -type fakeRktCli struct { - sync.Mutex - cmds []string - result []string - err error -} - -func newFakeRktCli() *fakeRktCli { - return &fakeRktCli{ - cmds: []string{}, - result: []string{}, - } -} - -func (f *fakeRktCli) RunCommand(config *Config, args ...string) (result []string, err error) { - f.Lock() - defer f.Unlock() - cmd := append([]string{"rkt"}, args...) - f.cmds = append(f.cmds, strings.Join(cmd, " ")) - return f.result, f.err -} - -func (f *fakeRktCli) Reset() { - f.cmds = []string{} - f.result = []string{} - f.err = nil -} - -type fakePodDeletionProvider struct { - pods map[types.UID]struct{} -} - -func newFakePodDeletionProvider() *fakePodDeletionProvider { - return &fakePodDeletionProvider{ - pods: make(map[types.UID]struct{}), - } -} - -func (f *fakePodDeletionProvider) IsPodDeleted(uid types.UID) bool { - _, found := f.pods[uid] - return !found -} - -type fakeUnitGetter struct { - networkNamespace kubecontainer.ContainerID -} - -func newfakeUnitGetter() *fakeUnitGetter { - return &fakeUnitGetter{ - networkNamespace: kubecontainer.ContainerID{}, - } -} - -func (f *fakeUnitGetter) getNetworkNamespace(uid types.UID, latestPod *rktapi.Pod) (kubecontainer.ContainerID, error) { - return kubecontainer.ContainerID{ID: "42"}, nil -} - -func (f *fakeUnitGetter) getKubernetesDirective(serviceFilePath string) (podServiceDirective, error) { - podService := podServiceDirective{ - id: "fake", - name: "fake", - namespace: "fake", - hostNetwork: true, - networkNamespace: kubecontainer.ContainerID{ID: "42"}, - } - return podService, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/image.go b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/image.go deleted file mode 100644 index 180dcfa51..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/image.go +++ /dev/null @@ -1,293 +0,0 @@ -/* -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. -*/ - -// This file contains all image related functions for rkt runtime. -package rkt - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" - "sort" - "strings" - - appcschema "github.com/appc/spec/schema" - appctypes "github.com/appc/spec/schema/types" - rktapi "github.com/coreos/rkt/api/v1alpha" - dockertypes "github.com/docker/docker/api/types" - "github.com/golang/glog" - "golang.org/x/net/context" - "k8s.io/api/core/v1" - "k8s.io/kubernetes/pkg/credentialprovider" - credentialprovidersecrets "k8s.io/kubernetes/pkg/credentialprovider/secrets" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/util/parsers" -) - -// PullImage invokes 'rkt fetch' to download an aci. -// TODO(yifan): Now we only support docker images, this should be changed -// once the format of image is landed, see: -// -// http://issue.k8s.io/7203 -// -func (r *Runtime) PullImage(image kubecontainer.ImageSpec, pullSecrets []v1.Secret) (string, error) { - img := image.Image - // TODO(yifan): The credential operation is a copy from dockertools package, - // Need to resolve the code duplication. - repoToPull, _, _, err := parsers.ParseImageName(img) - if err != nil { - return "", err - } - - keyring, err := credentialprovidersecrets.MakeDockerKeyring(pullSecrets, r.dockerKeyring) - if err != nil { - return "", err - } - - creds, ok := keyring.Lookup(repoToPull) - if !ok { - glog.V(1).Infof("Pulling image %s without credentials", img) - } - - userConfigDir, err := ioutil.TempDir("", "rktnetes-user-config-dir-") - if err != nil { - return "", fmt.Errorf("rkt: Cannot create a temporary user-config directory: %v", err) - } - defer os.RemoveAll(userConfigDir) - - config := *r.config - config.UserConfigDir = userConfigDir - - if err := r.writeDockerAuthConfig(img, creds, userConfigDir); err != nil { - return "", err - } - - // Today, `--no-store` will fetch the remote image regardless of whether the content of the image - // has changed or not. This causes performance downgrades when the image tag is ':latest' and - // the image pull policy is 'always'. The issue is tracked in https://github.com/coreos/rkt/issues/2937. - if _, err := r.cli.RunCommand(&config, "fetch", "--no-store", dockerPrefix+img); err != nil { - glog.Errorf("Failed to fetch: %v", err) - return "", err - } - return r.getImageID(img) -} - -func (r *Runtime) GetImageRef(image kubecontainer.ImageSpec) (string, error) { - images, err := r.listImages(image.Image, false) - if err != nil { - return "", err - } - if len(images) == 0 { - return "", nil - } - return images[0].Id, nil -} - -// ListImages lists all the available appc images on the machine by invoking 'rkt image list'. -func (r *Runtime) ListImages() ([]kubecontainer.Image, error) { - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - listResp, err := r.apisvc.ListImages(ctx, &rktapi.ListImagesRequest{}) - if err != nil { - return nil, fmt.Errorf("couldn't list images: %v", err) - } - - images := make([]kubecontainer.Image, len(listResp.Images)) - for i, image := range listResp.Images { - images[i] = kubecontainer.Image{ - ID: image.Id, - RepoTags: []string{buildImageName(image)}, - Size: image.Size, - } - } - return images, nil -} - -// RemoveImage removes an on-disk image using 'rkt image rm'. -func (r *Runtime) RemoveImage(image kubecontainer.ImageSpec) error { - imageID, err := r.getImageID(image.Image) - if err != nil { - return err - } - if _, err := r.cli.RunCommand(nil, "image", "rm", imageID); err != nil { - return err - } - return nil -} - -// buildImageName constructs the image name for kubecontainer.Image. -// If the annotations contain the docker2aci metadata for this image, those are -// used instead as they may be more accurate in some cases, namely if a -// non-appc valid character is present -func buildImageName(img *rktapi.Image) string { - registry := "" - repository := "" - for _, anno := range img.Annotations { - if anno.Key == appcDockerRegistryURL { - registry = anno.Value - } - if anno.Key == appcDockerRepository { - repository = anno.Value - } - } - if registry != "" && repository != "" { - // TODO(euank): This could do the special casing for dockerhub and library images - return fmt.Sprintf("%s/%s:%s", registry, repository, img.Version) - } - - return fmt.Sprintf("%s:%s", img.Name, img.Version) -} - -// getImageID tries to find the image ID for the given image name. -// imageName should be in the form of 'name[:version]', e.g., 'example.com/app:latest'. -// The name should matches the result of 'rkt image list'. If the version is empty, -// then 'latest' is assumed. -func (r *Runtime) getImageID(imageName string) (string, error) { - images, err := r.listImages(imageName, false) - if err != nil { - return "", err - } - if len(images) == 0 { - return "", fmt.Errorf("cannot find the image %q", imageName) - } - return images[0].Id, nil -} - -type sortByImportTime []*rktapi.Image - -func (s sortByImportTime) Len() int { return len(s) } -func (s sortByImportTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s sortByImportTime) Less(i, j int) bool { return s[i].ImportTimestamp < s[j].ImportTimestamp } - -// listImages lists the images that have the given name. If detail is true, -// then image manifest is also included in the result. -// Note that there could be more than one images that have the given name, we -// will return the result reversely sorted by the import time, so that the latest -// image comes first. -func (r *Runtime) listImages(image string, detail bool) ([]*rktapi.Image, error) { - repoToPull, tag, _, err := parsers.ParseImageName(image) - if err != nil { - return nil, err - } - - imageFilters := []*rktapi.ImageFilter{ - { - // TODO(yifan): Add a field in the ImageFilter to match the whole name, - // not just keywords. - // https://github.com/coreos/rkt/issues/1872#issuecomment-166456938 - Keywords: []string{repoToPull}, - Labels: []*rktapi.KeyValue{{Key: "version", Value: tag}}, - }, - } - - // If the repo name is not a valid ACIdentifier (namely if it has a port), - // then it will have a different name in the store. Search for both the - // original name and this modified name in case we choose to also change the - // api-service to do this un-conversion on its end. - if appcRepoToPull, err := appctypes.SanitizeACIdentifier(repoToPull); err != nil { - glog.Warningf("could not convert %v to an aci identifier: %v", err) - } else { - imageFilters = append(imageFilters, &rktapi.ImageFilter{ - Keywords: []string{appcRepoToPull}, - Labels: []*rktapi.KeyValue{{Key: "version", Value: tag}}, - }) - } - - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - listResp, err := r.apisvc.ListImages(ctx, &rktapi.ListImagesRequest{ - Detail: detail, - Filters: imageFilters, - }) - if err != nil { - return nil, fmt.Errorf("couldn't list images: %v", err) - } - - // TODO(yifan): Let the API service to sort the result: - // See https://github.com/coreos/rkt/issues/1911. - sort.Sort(sort.Reverse(sortByImportTime(listResp.Images))) - return listResp.Images, nil -} - -// getImageManifest retrieves the image manifest for the given image. -func (r *Runtime) getImageManifest(image string) (*appcschema.ImageManifest, error) { - var manifest appcschema.ImageManifest - - images, err := r.listImages(image, true) - if err != nil { - return nil, err - } - if len(images) == 0 { - return nil, fmt.Errorf("cannot find the image %q", image) - } - - return &manifest, json.Unmarshal(images[0].Manifest, &manifest) -} - -// TODO(yifan): This is very racy, inefficient, and unsafe, we need to provide -// different namespaces. See: https://github.com/coreos/rkt/issues/836. -func (r *Runtime) writeDockerAuthConfig(image string, credsSlice []credentialprovider.LazyAuthConfiguration, userConfigDir string) error { - if len(credsSlice) == 0 { - return nil - } - - creds := dockertypes.AuthConfig{} - // TODO handle multiple creds - if len(credsSlice) >= 1 { - creds = credentialprovider.LazyProvide(credsSlice[0]) - } - - registry := "index.docker.io" - // Image spec: [/]/[: 0 { - set, err := appctypes.NewLinuxCapabilitiesRetainSet(addCaps...) - if err != nil { - return err - } - isolator, err := set.AsIsolator() - if err != nil { - return err - } - isolators = append(isolators, *isolator) - } - if len(dropCaps) > 0 { - set, err := appctypes.NewLinuxCapabilitiesRevokeSet(dropCaps...) - if err != nil { - return err - } - isolator, err := set.AsIsolator() - if err != nil { - return err - } - isolators = append(isolators, *isolator) - } - } - - // Resources isolators. - type resource struct { - limit string - request string - } - - // If limit is empty, populate it with request and vice versa. - resources := make(map[v1.ResourceName]*resource) - for name, quantity := range c.Resources.Limits { - resources[name] = &resource{limit: quantity.String(), request: quantity.String()} - } - for name, quantity := range c.Resources.Requests { - r, ok := resources[name] - if ok { - r.request = quantity.String() - continue - } - resources[name] = &resource{limit: quantity.String(), request: quantity.String()} - } - - for name, res := range resources { - switch name { - case v1.ResourceCPU: - cpu, err := appctypes.NewResourceCPUIsolator(res.request, res.limit) - if err != nil { - return err - } - isolators = append(isolators, cpu.AsIsolator()) - case v1.ResourceMemory: - memory, err := appctypes.NewResourceMemoryIsolator(res.request, res.limit) - if err != nil { - return err - } - isolators = append(isolators, memory.AsIsolator()) - default: - return fmt.Errorf("resource type not supported: %v", name) - } - } - - if ok := securitycontext.AddNoNewPrivileges(ctx); ok { - isolator, err := newNoNewPrivilegesIsolator(true) - if err != nil { - return err - } - isolators = append(isolators, *isolator) - } - - mergeIsolators(app, isolators) - return nil -} - -// mergeIsolators replaces the app.Isolators with isolators. -func mergeIsolators(app *appctypes.App, isolators []appctypes.Isolator) { - for _, is := range isolators { - found := false - for j, js := range app.Isolators { - if is.Name.Equals(js.Name) { - switch is.Name { - case appctypes.LinuxCapabilitiesRetainSetName: - // TODO(yifan): More fine grain merge for capability set instead of override. - fallthrough - case appctypes.LinuxCapabilitiesRevokeSetName: - fallthrough - case appctypes.ResourceCPUName: - fallthrough - case appctypes.ResourceMemoryName: - app.Isolators[j] = is - default: - panic(fmt.Sprintf("unexpected isolator name: %v", is.Name)) - } - found = true - break - } - } - if !found { - app.Isolators = append(app.Isolators, is) - } - } -} - -// mergeEnv merges the optEnv with the image's environments. -// The environments defined in the image will be overridden by -// the ones with the same name in optEnv. -func mergeEnv(app *appctypes.App, optEnv []kubecontainer.EnvVar) { - envMap := make(map[string]string) - for _, e := range app.Environment { - envMap[e.Name] = e.Value - } - for _, e := range optEnv { - envMap[e.Name] = e.Value - } - app.Environment = nil - for name, value := range envMap { - app.Environment = append(app.Environment, appctypes.EnvironmentVariable{ - Name: name, - Value: value, - }) - } -} - -// mergeMounts merges the mountPoints with the image's mount points. -// The mount points defined in the image will be overridden by the ones -// with the same container path. -func mergeMounts(app *appctypes.App, mountPoints []appctypes.MountPoint) { - mountMap := make(map[string]appctypes.MountPoint) - for _, m := range app.MountPoints { - mountMap[m.Path] = m - } - for _, m := range mountPoints { - mountMap[m.Path] = m - } - app.MountPoints = nil - for _, mount := range mountMap { - app.MountPoints = append(app.MountPoints, mount) - } -} - -// mergePortMappings merges the containerPorts with the image's container ports. -// The port mappings defined in the image will be overridden by the ones -// with the same name in optPortMappings. -func mergePortMappings(app *appctypes.App, containerPorts []appctypes.Port) { - portMap := make(map[appctypes.ACName]appctypes.Port) - for _, p := range app.Ports { - portMap[p.Name] = p - } - for _, p := range containerPorts { - portMap[p.Name] = p - } - app.Ports = nil - for _, port := range portMap { - app.Ports = append(app.Ports, port) - } -} - -func verifyNonRoot(app *appctypes.App, ctx *v1.SecurityContext) error { - if ctx != nil && ctx.RunAsNonRoot != nil && *ctx.RunAsNonRoot { - if ctx.RunAsUser != nil && *ctx.RunAsUser == 0 { - return fmt.Errorf("container's runAsUser breaks non-root policy") - } - if ctx.RunAsUser == nil && app.User == "0" { - return fmt.Errorf("container has no runAsUser and image will run as root") - } - } - return nil -} - -func setSupplementalGIDs(app *appctypes.App, podCtx *v1.PodSecurityContext, supplementalGids []int64) { - if podCtx != nil || len(supplementalGids) != 0 { - app.SupplementaryGIDs = app.SupplementaryGIDs[:0] - } - if podCtx != nil { - for _, v := range podCtx.SupplementalGroups { - app.SupplementaryGIDs = append(app.SupplementaryGIDs, int(v)) - } - if podCtx.FSGroup != nil { - app.SupplementaryGIDs = append(app.SupplementaryGIDs, int(*podCtx.FSGroup)) - } - } - for _, v := range supplementalGids { - app.SupplementaryGIDs = append(app.SupplementaryGIDs, int(v)) - } -} - -// setApp merges the container spec with the image's manifest. -func setApp(imgManifest *appcschema.ImageManifest, c *v1.Container, - mountPoints []appctypes.MountPoint, containerPorts []appctypes.Port, envs []kubecontainer.EnvVar, - ctx *v1.SecurityContext, podCtx *v1.PodSecurityContext, supplementalGids []int64) error { - - app := imgManifest.App - - // Set up Exec. - var command, args []string - cmd, ok := imgManifest.Annotations.Get(appcDockerEntrypoint) - if ok { - err := json.Unmarshal([]byte(cmd), &command) - if err != nil { - return fmt.Errorf("cannot unmarshal ENTRYPOINT %q: %v", cmd, err) - } - } - ag, ok := imgManifest.Annotations.Get(appcDockerCmd) - if ok { - err := json.Unmarshal([]byte(ag), &args) - if err != nil { - return fmt.Errorf("cannot unmarshal CMD %q: %v", ag, err) - } - } - userCommand, userArgs := kubecontainer.ExpandContainerCommandAndArgs(c, envs) - - if len(userCommand) > 0 { - command = userCommand - args = nil // If 'command' is specified, then drop the default args. - } - if len(userArgs) > 0 { - args = userArgs - } - - exec := append(command, args...) - if len(exec) > 0 { - app.Exec = exec - } - - // Set UID and GIDs. - if err := verifyNonRoot(app, ctx); err != nil { - return err - } - if ctx != nil && ctx.RunAsUser != nil { - app.User = strconv.Itoa(int(*ctx.RunAsUser)) - } - setSupplementalGIDs(app, podCtx, supplementalGids) - - // If 'User' or 'Group' are still empty at this point, - // then apply the root UID and GID. - // TODO(yifan): If only the GID is empty, rkt should be able to determine the GID - // using the /etc/passwd file in the image. - // See https://github.com/appc/docker2aci/issues/175. - // Maybe we can remove this check in the future. - if app.User == "" { - app.User = "0" - app.Group = "0" - } - if app.Group == "" { - return fmt.Errorf("cannot determine the GID of the app %q", imgManifest.Name) - } - - // Set working directory. - if len(c.WorkingDir) > 0 { - app.WorkingDirectory = c.WorkingDir - } - - // Notes that we don't create Mounts section in the pod manifest here, - // as Mounts will be automatically generated by rkt. - mergeMounts(app, mountPoints) - mergeEnv(app, envs) - mergePortMappings(app, containerPorts) - - return setIsolators(app, c, ctx) -} - -// makePodManifest transforms a kubelet pod spec to the rkt pod manifest. -func (r *Runtime) makePodManifest(pod *v1.Pod, podIP string, pullSecrets []v1.Secret) (*appcschema.PodManifest, error) { - manifest := appcschema.BlankPodManifest() - - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - listResp, err := r.apisvc.ListPods(ctx, &rktapi.ListPodsRequest{ - Detail: true, - Filters: kubernetesPodFilters(pod.UID), - }) - if err != nil { - return nil, fmt.Errorf("couldn't list pods: %v", err) - } - - restartCount := 0 - for _, pod := range listResp.Pods { - manifest := &appcschema.PodManifest{} - err = json.Unmarshal(pod.Manifest, manifest) - if err != nil { - glog.Warningf("rkt: error unmatshaling pod manifest: %v", err) - continue - } - - if countString, ok := manifest.Annotations.Get(k8sRktRestartCountAnno); ok { - num, err := strconv.Atoi(countString) - if err != nil { - glog.Warningf("rkt: error reading restart count on pod: %v", err) - continue - } - if num+1 > restartCount { - restartCount = num + 1 - } - } - } - - requiresPrivileged := false - manifest.Annotations.Set(*appctypes.MustACIdentifier(k8sRktKubeletAnno), k8sRktKubeletAnnoValue) - manifest.Annotations.Set(*appctypes.MustACIdentifier(types.KubernetesPodUIDLabel), string(pod.UID)) - manifest.Annotations.Set(*appctypes.MustACIdentifier(types.KubernetesPodNameLabel), pod.Name) - manifest.Annotations.Set(*appctypes.MustACIdentifier(types.KubernetesPodNamespaceLabel), pod.Namespace) - manifest.Annotations.Set(*appctypes.MustACIdentifier(types.KubernetesContainerNameLabel), leaky.PodInfraContainerName) - manifest.Annotations.Set(*appctypes.MustACIdentifier(k8sRktRestartCountAnno), strconv.Itoa(restartCount)) - if stage1Name, ok := pod.Annotations[k8sRktStage1NameAnno]; ok { - requiresPrivileged = true - manifest.Annotations.Set(*appctypes.MustACIdentifier(k8sRktStage1NameAnno), stage1Name) - } - - for _, c := range pod.Spec.Containers { - err := r.newAppcRuntimeApp(pod, podIP, c, requiresPrivileged, pullSecrets, manifest) - if err != nil { - return nil, err - } - } - - // TODO(yifan): Set pod-level isolators once it's supported in kubernetes. - return manifest, nil -} - -func copyfile(src, dst string) error { - data, err := ioutil.ReadFile(src) - if err != nil { - return err - } - return ioutil.WriteFile(dst, data, 0644) -} - -// TODO(yifan): Can make rkt handle this when '--net=host'. See https://github.com/coreos/rkt/issues/2430. -func makeHostNetworkMount(opts *kubecontainer.RunContainerOptions) (*kubecontainer.Mount, *kubecontainer.Mount, error) { - mountHosts, mountResolvConf := true, true - for _, mnt := range opts.Mounts { - switch mnt.ContainerPath { - case etcHostsPath: - mountHosts = false - case etcResolvConfPath: - mountResolvConf = false - } - } - - var hostsMount, resolvMount kubecontainer.Mount - if mountHosts { - hostsPath := filepath.Join(opts.PodContainerDir, "etc-hosts") - if err := copyfile(etcHostsPath, hostsPath); err != nil { - return nil, nil, err - } - hostsMount = kubecontainer.Mount{ - Name: "kubernetes-hostnetwork-hosts-conf", - ContainerPath: etcHostsPath, - HostPath: hostsPath, - } - opts.Mounts = append(opts.Mounts, hostsMount) - } - - if mountResolvConf { - resolvPath := filepath.Join(opts.PodContainerDir, "etc-resolv-conf") - if err := copyfile(etcResolvConfPath, resolvPath); err != nil { - return nil, nil, err - } - resolvMount = kubecontainer.Mount{ - Name: "kubernetes-hostnetwork-resolv-conf", - ContainerPath: etcResolvConfPath, - HostPath: resolvPath, - } - opts.Mounts = append(opts.Mounts, resolvMount) - } - return &hostsMount, &resolvMount, nil -} - -// podFinishedMarkerPath returns the path to a file which should be used to -// indicate the pod exiting, and the time thereof. -// If the file at the path does not exist, the pod should not be exited. If it -// does exist, then the ctime of the file should indicate the time the pod -// exited. -func podFinishedMarkerPath(podDir string, rktUID string) string { - return filepath.Join(podDir, "finished-"+rktUID) -} - -func podFinishedMarkCommand(touchPath, podDir, rktUID string) string { - // TODO, if the path has a `'` character in it, this breaks. - return touchPath + " " + podFinishedMarkerPath(podDir, rktUID) -} - -// podFinishedAt returns the time that a pod exited, or a zero time if it has -// not. -func (r *Runtime) podFinishedAt(podUID kubetypes.UID, rktUID string) time.Time { - markerFile := podFinishedMarkerPath(r.runtimeHelper.GetPodDir(podUID), rktUID) - stat, err := r.os.Stat(markerFile) - if err != nil { - if !os.IsNotExist(err) { - glog.Warningf("rkt: unexpected fs error checking pod finished marker: %v", err) - } - return time.Time{} - } - return stat.ModTime() -} - -func (r *Runtime) makeContainerLogMount(opts *kubecontainer.RunContainerOptions, container *v1.Container) (*kubecontainer.Mount, error) { - if opts.PodContainerDir == "" || container.TerminationMessagePath == "" { - return nil, nil - } - - // In docker runtime, the container log path contains the container ID. - // However, for rkt runtime, we cannot get the container ID before the - // the container is launched, so here we generate a random uuid to enable - // us to map a container's termination message path to a unique log file - // on the disk. - randomUID := uuid.NewUUID() - containerLogPath := path.Join(opts.PodContainerDir, string(randomUID)) - fs, err := r.os.Create(containerLogPath) - if err != nil { - return nil, err - } - - if err := fs.Close(); err != nil { - return nil, err - } - - mnt := kubecontainer.Mount{ - // Use a random name for the termination message mount, so that - // when a container restarts, it will not overwrite the old termination - // message. - Name: fmt.Sprintf("termination-message-%s", randomUID), - ContainerPath: container.TerminationMessagePath, - HostPath: containerLogPath, - ReadOnly: false, - } - opts.Mounts = append(opts.Mounts, mnt) - - return &mnt, nil -} - -func (r *Runtime) newAppcRuntimeApp(pod *v1.Pod, podIP string, c v1.Container, requiresPrivileged bool, pullSecrets []v1.Secret, manifest *appcschema.PodManifest) error { - var annotations appctypes.Annotations = []appctypes.Annotation{ - { - Name: *appctypes.MustACIdentifier(k8sRktContainerHashAnno), - Value: strconv.FormatUint(kubecontainer.HashContainerLegacy(&c), 10), - }, - { - Name: *appctypes.MustACIdentifier(types.KubernetesContainerNameLabel), - Value: c.Name, - }, - } - - if requiresPrivileged && !securitycontext.HasPrivilegedRequest(&c) { - return fmt.Errorf("cannot make %q: running a custom stage1 requires a privileged security context", format.Pod(pod)) - } - imageRef, _, err := r.imagePuller.EnsureImageExists(pod, &c, pullSecrets) - if err != nil { - return err - } - imgManifest, err := r.getImageManifest(c.Image) - if err != nil { - return err - } - - if imgManifest.App == nil { - imgManifest.App = new(appctypes.App) - } - - hash, err := appctypes.NewHash(imageRef) - if err != nil { - return err - } - - // TODO: determine how this should be handled for rkt - opts, _, err := r.runtimeHelper.GenerateRunContainerOptions(pod, &c, podIP) - if err != nil { - return err - } - - // Create additional mount for termination message path. - mount, err := r.makeContainerLogMount(opts, &c) - if err != nil { - return err - } - mounts := append(opts.Mounts, *mount) - annotations = append(annotations, appctypes.Annotation{ - Name: *appctypes.MustACIdentifier(k8sRktTerminationMessagePathAnno), - Value: mount.HostPath, - }) - - // If run in 'hostnetwork' mode, then copy the host's /etc/resolv.conf and /etc/hosts, - // and add mounts. - if kubecontainer.IsHostNetworkPod(pod) { - hostsMount, resolvMount, err := makeHostNetworkMount(opts) - if err != nil { - return err - } - mounts = append(mounts, *hostsMount, *resolvMount) - } - - supplementalGids := r.runtimeHelper.GetExtraSupplementalGroupsForPod(pod) - ctx := securitycontext.DetermineEffectiveSecurityContext(pod, &c) - - volumes, mountPoints := convertKubeMounts(mounts) - containerPorts, hostPorts := convertKubePortMappings(opts.PortMappings) - - if err := setApp(imgManifest, &c, mountPoints, containerPorts, opts.Envs, ctx, pod.Spec.SecurityContext, supplementalGids); err != nil { - return err - } - - ra := appcschema.RuntimeApp{ - Name: convertToACName(c.Name), - Image: appcschema.RuntimeImage{ID: *hash}, - App: imgManifest.App, - Annotations: annotations, - } - - if c.SecurityContext != nil && c.SecurityContext.ReadOnlyRootFilesystem != nil { - ra.ReadOnlyRootFS = *c.SecurityContext.ReadOnlyRootFilesystem - } - - manifest.Apps = append(manifest.Apps, ra) - manifest.Volumes = append(manifest.Volumes, volumes...) - manifest.Ports = append(manifest.Ports, hostPorts...) - - return nil -} - -func runningKubernetesPodFilters(uid kubetypes.UID) []*rktapi.PodFilter { - return []*rktapi.PodFilter{ - { - States: []rktapi.PodState{ - rktapi.PodState_POD_STATE_RUNNING, - }, - Annotations: []*rktapi.KeyValue{ - { - Key: k8sRktKubeletAnno, - Value: k8sRktKubeletAnnoValue, - }, - { - Key: types.KubernetesPodUIDLabel, - Value: string(uid), - }, - }, - }, - } -} - -func kubernetesPodFilters(uid kubetypes.UID) []*rktapi.PodFilter { - return []*rktapi.PodFilter{ - { - Annotations: []*rktapi.KeyValue{ - { - Key: k8sRktKubeletAnno, - Value: k8sRktKubeletAnnoValue, - }, - { - Key: types.KubernetesPodUIDLabel, - Value: string(uid), - }, - }, - }, - } -} - -func kubernetesPodsFilters() []*rktapi.PodFilter { - return []*rktapi.PodFilter{ - { - Annotations: []*rktapi.KeyValue{ - { - Key: k8sRktKubeletAnno, - Value: k8sRktKubeletAnnoValue, - }, - }, - }, - } -} - -func newUnitOption(section, name, value string) *unit.UnitOption { - return &unit.UnitOption{Section: section, Name: name, Value: value} -} - -// apiPodToruntimePod converts an v1.Pod to kubelet/container.Pod. -func apiPodToruntimePod(uuid string, pod *v1.Pod) *kubecontainer.Pod { - p := &kubecontainer.Pod{ - ID: pod.UID, - Name: pod.Name, - Namespace: pod.Namespace, - } - for i := range pod.Spec.Containers { - c := &pod.Spec.Containers[i] - p.Containers = append(p.Containers, &kubecontainer.Container{ - ID: buildContainerID(&containerID{uuid, c.Name}), - Name: c.Name, - Image: c.Image, - Hash: kubecontainer.HashContainerLegacy(c), - }) - } - return p -} - -// serviceFilePath returns the absolute path of the service file. -func serviceFilePath(serviceName string) string { - return path.Join(systemdServiceDir, serviceName) -} - -// shouldCreateNetns returns true if: -// The pod does not run in host network. And -// The pod runs inside a netns created outside of rkt. -func (r *Runtime) shouldCreateNetns(pod *v1.Pod) bool { - return !kubecontainer.IsHostNetworkPod(pod) && r.network.PluginName() != network.DefaultPluginName -} - -// usesRktHostNetwork returns true if: -// The pod runs in the host network. Or -// The pod runs inside a netns created outside of rkt. -func (r *Runtime) usesRktHostNetwork(pod *v1.Pod) bool { - return kubecontainer.IsHostNetworkPod(pod) || r.shouldCreateNetns(pod) -} - -// generateRunCommand crafts a 'rkt run-prepared' command with necessary parameters. -func (r *Runtime) generateRunCommand(pod *v1.Pod, uuid, networkNamespaceID string) (string, error) { - config := *r.config - privileged := true - - for _, c := range pod.Spec.Containers { - ctx := securitycontext.DetermineEffectiveSecurityContext(pod, &c) - if ctx == nil || ctx.Privileged == nil || *ctx.Privileged == false { - privileged = false - break - } - } - - // Use "all-run" insecure option (https://github.com/coreos/rkt/pull/2983) to take care - // of privileged pod. - // TODO(yifan): Have more granular app-level control of the insecure options. - // See: https://github.com/coreos/rkt/issues/2996. - if privileged { - config.InsecureOptions = fmt.Sprintf("%s,%s", config.InsecureOptions, "all-run") - } - - runPrepared := buildCommand(&config, "run-prepared").Args - - var hostname string - var err error - - osInfos, err := getOSReleaseInfo() - if err != nil { - glog.Warningf("rkt: Failed to read the os release info: %v", err) - } else { - // Overlay fs is not supported for SELinux yet on many distros. - // See https://github.com/coreos/rkt/issues/1727#issuecomment-173203129. - // For now, coreos carries a patch to support it: https://github.com/coreos/coreos-overlay/pull/1703 - if osInfos["ID"] != "coreos" && pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SELinuxOptions != nil { - runPrepared = append(runPrepared, "--no-overlay=true") - } - } - - // Apply '--net=host' to pod that is running on host network or inside a network namespace. - if r.usesRktHostNetwork(pod) { - runPrepared = append(runPrepared, "--net=host") - } else { - runPrepared = append(runPrepared, fmt.Sprintf("--net=%s", defaultNetworkName)) - } - - if kubecontainer.IsHostNetworkPod(pod) { - // TODO(yifan): Let runtimeHelper.GeneratePodHostNameAndDomain() to handle this. - hostname, err = r.os.Hostname() - if err != nil { - return "", err - } - } else { - // Setup DNS. - dnsConfig, err := r.runtimeHelper.GetPodDNS(pod) - if err != nil { - return "", err - } - for _, server := range dnsConfig.Servers { - runPrepared = append(runPrepared, fmt.Sprintf("--dns=%s", server)) - } - for _, search := range dnsConfig.Searches { - runPrepared = append(runPrepared, fmt.Sprintf("--dns-search=%s", search)) - } - if len(dnsConfig.Servers) > 0 || len(dnsConfig.Searches) > 0 { - runPrepared = append(runPrepared, fmt.Sprintf("--dns-opt=%s", defaultDNSOption)) - } - - // TODO(yifan): host domain is not being used. - hostname, _, err = r.runtimeHelper.GeneratePodHostNameAndDomain(pod) - if err != nil { - return "", err - } - } - - runPrepared = append(runPrepared, fmt.Sprintf("--hostname=%s", hostname)) - runPrepared = append(runPrepared, uuid) - - if r.shouldCreateNetns(pod) { - // Drop the `rkt run-prepared` into the network namespace we - // created. - // TODO: switch to 'ip netns exec' once we can depend on a new - // enough version that doesn't have bugs like - // https://bugzilla.redhat.com/show_bug.cgi?id=882047 - nsenterExec := []string{r.nsenterPath, "--net=" + netnsPathFromName(networkNamespaceID), "--"} - runPrepared = append(nsenterExec, runPrepared...) - } - - return strings.Join(runPrepared, " "), nil -} - -func (r *Runtime) cleanupPodNetwork(pod *v1.Pod, networkNamespace kubecontainer.ContainerID) error { - // No-op if the pod is not running in a created netns. - if !r.shouldCreateNetns(pod) { - return nil - } - - glog.V(3).Infof("Calling network plugin %s to tear down pod for %s", r.network.PluginName(), format.Pod(pod)) - teardownErr := r.network.TearDownPod(pod.Namespace, pod.Name, networkNamespace) - if teardownErr != nil { - glog.Error(teardownErr) - } - - if _, err := r.execer.Command("ip", "netns", "del", networkNamespace.ID).Output(); err != nil { - return fmt.Errorf("rkt: Failed to remove network namespace for pod %s: %v", format.Pod(pod), err) - } - - return teardownErr -} - -func (r *Runtime) preparePodArgs(manifest *appcschema.PodManifest, manifestFileName string) []string { - // Order of precedence for the stage1: - // 1) pod annotation (stage1 name) - // 2) kubelet configured stage1 (stage1 path) - // 3) empty; whatever rkt's compiled to default to - stage1ImageCmd := "" - if r.config.Stage1Image != "" { - stage1ImageCmd = "--stage1-name=" + r.config.Stage1Image - } - if stage1Name, ok := manifest.Annotations.Get(k8sRktStage1NameAnno); ok { - stage1ImageCmd = "--stage1-name=" + stage1Name - } - - // Run 'rkt prepare' to get the rkt UUID. - cmds := []string{"prepare", "--quiet", "--pod-manifest", manifestFileName} - if stage1ImageCmd != "" { - cmds = append(cmds, stage1ImageCmd) - } - return cmds -} - -func (r *Runtime) getSelinuxContext(opt *v1.SELinuxOptions) (string, error) { - selinuxRunner := selinux.NewSELinuxRunner() - str, err := selinuxRunner.Getfilecon(r.config.Dir) - if err != nil { - return "", err - } - - ctx := strings.SplitN(str, ":", 4) - if len(ctx) != 4 { - return "", fmt.Errorf("malformated selinux context") - } - - if opt.User != "" { - ctx[0] = opt.User - } - if opt.Role != "" { - ctx[1] = opt.Role - } - if opt.Type != "" { - ctx[2] = opt.Type - } - if opt.Level != "" { - ctx[3] = opt.Level - } - - return strings.Join(ctx, ":"), nil -} - -// From the generateName or the podName return a basename for improving the logging with the Journal -// journalctl -t podBaseName -func constructSyslogIdentifier(generateName string, podName string) string { - if len(generateName) > 1 && generateName[len(generateName)-1] == '-' { - return generateName[0 : len(generateName)-1] - } - if len(generateName) > 0 { - return generateName - } - return podName -} - -// Setup additional systemd field specified in the Pod Annotation -func setupSystemdCustomFields(annotations map[string]string, unitOptionArray []*unit.UnitOption) ([]*unit.UnitOption, error) { - // LimitNOFILE - if strSize := annotations[k8sRktLimitNoFileAnno]; strSize != "" { - size, err := strconv.Atoi(strSize) - if err != nil { - return unitOptionArray, err - } - if size < 1 { - return unitOptionArray, fmt.Errorf("invalid value for %s: %s", k8sRktLimitNoFileAnno, strSize) - } - unitOptionArray = append(unitOptionArray, newUnitOption("Service", "LimitNOFILE", strSize)) - } - - return unitOptionArray, nil -} - -// preparePod will: -// -// 1. Invoke 'rkt prepare' to prepare the pod, and get the rkt pod uuid. -// 2. Create the unit file and save it under systemdUnitDir. -// -// On success, it will return a string that represents name of the unit file -// and the runtime pod. -func (r *Runtime) preparePod(pod *v1.Pod, podIP string, pullSecrets []v1.Secret, networkNamespaceID string) (string, *kubecontainer.Pod, error) { - // Generate the appc pod manifest from the k8s pod spec. - manifest, err := r.makePodManifest(pod, podIP, pullSecrets) - if err != nil { - return "", nil, err - } - manifestFile, err := ioutil.TempFile("", fmt.Sprintf("manifest-%s-", pod.Name)) - if err != nil { - return "", nil, err - } - defer func() { - manifestFile.Close() - if err := r.os.Remove(manifestFile.Name()); err != nil { - glog.Warningf("rkt: Cannot remove temp manifest file %q: %v", manifestFile.Name(), err) - } - }() - - data, err := json.Marshal(manifest) - if err != nil { - return "", nil, err - } - - glog.V(4).Infof("Generating pod manifest for pod %q: %v", format.Pod(pod), string(data)) - // Since File.Write returns error if the written length is less than len(data), - // so check error is enough for us. - if _, err := manifestFile.Write(data); err != nil { - return "", nil, err - } - - prepareCmd := r.preparePodArgs(manifest, manifestFile.Name()) - output, err := r.cli.RunCommand(nil, prepareCmd...) - if err != nil { - return "", nil, err - } - if len(output) != 1 { - return "", nil, fmt.Errorf("invalid output from 'rkt prepare': %v", output) - } - uuid := output[0] - glog.V(4).Infof("'rkt prepare' returns %q", uuid) - - // Create systemd service file for the rkt pod. - runPrepared, err := r.generateRunCommand(pod, uuid, networkNamespaceID) - if err != nil { - return "", nil, fmt.Errorf("failed to generate 'rkt run-prepared' command: %v", err) - } - - // TODO handle pod.Spec.HostPID - // TODO handle pod.Spec.HostIPC - - // TODO per container finishedAt, not just per pod - markPodFinished := podFinishedMarkCommand(r.touchPath, r.runtimeHelper.GetPodDir(pod.UID), uuid) - - hostNetwork := kubecontainer.IsHostNetworkPod(pod) - units := []*unit.UnitOption{ - newUnitOption("Service", "ExecStart", runPrepared), - newUnitOption("Service", "ExecStopPost", markPodFinished), - // This enables graceful stop. - newUnitOption("Service", "KillMode", "mixed"), - newUnitOption("Service", "TimeoutStopSec", fmt.Sprintf("%ds", getPodTerminationGracePeriodInSecond(pod))), - // Ops helpers - newUnitOption("Unit", "Description", pod.Name), - newUnitOption("Service", "SyslogIdentifier", constructSyslogIdentifier(pod.GenerateName, pod.Name)), - // Track pod info for garbage collection - newUnitOption(unitKubernetesSection, unitPodUID, string(pod.UID)), - newUnitOption(unitKubernetesSection, unitPodName, pod.Name), - newUnitOption(unitKubernetesSection, unitPodNamespace, pod.Namespace), - newUnitOption(unitKubernetesSection, unitPodHostNetwork, fmt.Sprintf("%v", hostNetwork)), - newUnitOption(unitKubernetesSection, unitPodNetworkNamespace, networkNamespaceID), - } - - if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SELinuxOptions != nil { - opt := pod.Spec.SecurityContext.SELinuxOptions - selinuxContext, err := r.getSelinuxContext(opt) - if err != nil { - glog.Errorf("rkt: Failed to construct selinux context with selinux option %q: %v", opt, err) - return "", nil, err - } - units = append(units, newUnitOption("Service", "SELinuxContext", selinuxContext)) - } - - units, err = setupSystemdCustomFields(pod.Annotations, units) - if err != nil { - glog.Warningf("fail to add custom systemd fields provided by pod Annotations: %q", err) - } - - serviceName := makePodServiceFileName(uuid) - glog.V(4).Infof("rkt: Creating service file %q for pod %q", serviceName, format.Pod(pod)) - serviceFile, err := r.os.Create(serviceFilePath(serviceName)) - if err != nil { - return "", nil, err - } - if _, err := io.Copy(serviceFile, unit.Serialize(units)); err != nil { - return "", nil, err - } - serviceFile.Close() - - return serviceName, apiPodToruntimePod(uuid, pod), nil -} - -// generateEvents is a helper function that generates some container -// life cycle events for containers in a pod. -func (r *Runtime) generateEvents(runtimePod *kubecontainer.Pod, reason string, failure error) { - // Set up container references. - for _, c := range runtimePod.Containers { - containerID := c.ID - id, err := parseContainerID(containerID) - if err != nil { - glog.Warningf("Invalid container ID %q", containerID) - continue - } - - ref, ok := r.containerRefManager.GetRef(containerID) - if !ok { - glog.Warningf("No ref for container %q", containerID) - continue - } - - // Note that 'rkt id' is the pod id. - uuid := utilstrings.ShortenString(id.uuid, 8) - switch reason { - case "Created": - r.recorder.Eventf(ref, v1.EventTypeNormal, events.CreatedContainer, "Created with rkt id %v", uuid) - case "Started": - r.recorder.Eventf(ref, v1.EventTypeNormal, events.StartedContainer, "Started with rkt id %v", uuid) - case "Failed": - r.recorder.Eventf(ref, v1.EventTypeWarning, events.FailedToStartContainer, "Failed to start with rkt id %v with error %v", uuid, failure) - case "Killing": - r.recorder.Eventf(ref, v1.EventTypeNormal, events.KillingContainer, "Killing with rkt id %v", uuid) - default: - glog.Errorf("rkt: Unexpected event %q", reason) - } - } - return -} - -// Generate a Network Namespace based on a New UUID -// to run the Pod and all of its containers inside a dedicated unique namespace -func generateNetworkNamespaceUUID() kubecontainer.ContainerID { - return kubecontainer.ContainerID{ID: fmt.Sprintf("%s%s", kubernetesUnitPrefix, uuid.NewUUID())} -} - -func netnsPathFromName(netnsName string) string { - return fmt.Sprintf("/var/run/netns/%s", netnsName) -} - -// setupPodNetwork creates a network namespace for the given pod and calls -// configured NetworkPlugin's setup function on it. -// It returns the namespace name, configured IP (if available), and an error if -// one occurred. -// -// If the pod is running in host network or is running using the no-op plugin, then nothing will be done. -func (r *Runtime) setupPodNetwork(pod *v1.Pod) (kubecontainer.ContainerID, string, error) { - glog.V(3).Infof("Calling network plugin %s to set up pod for %s", r.network.PluginName(), format.Pod(pod)) - - var networkNamespace kubecontainer.ContainerID - - // No-op if the pod is not running in a created netns. - if !r.shouldCreateNetns(pod) { - return networkNamespace, "", nil - } - - networkNamespace = generateNetworkNamespaceUUID() - glog.V(5).Infof("New network namespace %q generated for pod %s", networkNamespace.ID, format.Pod(pod)) - - // Create the network namespace for the pod - _, err := r.execer.Command("ip", "netns", "add", networkNamespace.ID).Output() - if err != nil { - return networkNamespace, "", fmt.Errorf("failed to create pod network namespace: %v", err) - } - - // Set up networking with the network plugin - err = r.network.SetUpPod(pod.Namespace, pod.Name, networkNamespace, pod.Annotations) - if err != nil { - return networkNamespace, "", err - } - status, err := r.network.GetPodNetworkStatus(pod.Namespace, pod.Name, networkNamespace) - if err != nil { - return networkNamespace, "", err - } - - if r.configureHairpinMode { - if err = hairpin.SetUpContainerPath(netnsPathFromName(networkNamespace.ID), network.DefaultInterfaceName); err != nil { - glog.Warningf("Hairpin setup failed for pod %q: %v", format.Pod(pod), err) - } - } - - return networkNamespace, status.IP.String(), nil -} - -// For a hostPath volume: rkt doesn't create any missing volume on the node/host so we need to create it -func createHostPathVolumes(pod *v1.Pod) (err error) { - for _, v := range pod.Spec.Volumes { - if v.VolumeSource.HostPath != nil { - _, err = os.Stat(v.HostPath.Path) - if os.IsNotExist(err) { - if err = os.MkdirAll(v.HostPath.Path, os.ModePerm); err != nil { - glog.Errorf("Create volume HostPath %q for Pod %q failed: %q", v.HostPath.Path, format.Pod(pod), err.Error()) - return err - } - glog.V(4).Infof("Created volume HostPath %q for Pod %q", v.HostPath.Path, format.Pod(pod)) - } - } - } - return nil -} - -// RunPod first creates the unit file for a pod, and then -// starts the unit over d-bus. -func (r *Runtime) RunPod(pod *v1.Pod, pullSecrets []v1.Secret) error { - glog.V(4).Infof("Rkt starts to run pod: name %q.", format.Pod(pod)) - - var err error - var networkNamespace kubecontainer.ContainerID - var podIP string - - err = createHostPathVolumes(pod) - if err != nil { - return err - } - - networkNamespace, podIP, err = r.setupPodNetwork(pod) - if err != nil { - r.cleanupPodNetwork(pod, networkNamespace) - return err - } - - name, runtimePod, prepareErr := r.preparePod(pod, podIP, pullSecrets, networkNamespace.ID) - - // Set container references and generate events. - // If preparedPod fails, then send out 'failed' events for each container. - // Otherwise, store the container references so we can use them later to send events. - for i, c := range pod.Spec.Containers { - ref, err := kubecontainer.GenerateContainerRef(pod, &c) - if err != nil { - glog.Errorf("Couldn't make a ref to pod %q, container %v: '%v'", format.Pod(pod), c.Name, err) - continue - } - if prepareErr != nil { - r.recorder.Eventf(ref, v1.EventTypeWarning, events.FailedToCreateContainer, "Failed to create rkt container with error: %v", prepareErr) - continue - } - containerID := runtimePod.Containers[i].ID - r.containerRefManager.SetRef(containerID, ref) - } - - if prepareErr != nil { - r.cleanupPodNetwork(pod, networkNamespace) - return prepareErr - } - - r.generateEvents(runtimePod, "Created", nil) - - // RestartUnit has the same effect as StartUnit if the unit is not running, besides it can restart - // a unit if the unit file is changed and reloaded. - reschan := make(chan string) - _, err = r.systemd.RestartUnit(name, "replace", reschan) - if err != nil { - r.generateEvents(runtimePod, "Failed", err) - r.cleanupPodNetwork(pod, networkNamespace) - return err - } - - res := <-reschan - if res != "done" { - err := fmt.Errorf("Failed to restart unit %q: %s", name, res) - r.generateEvents(runtimePod, "Failed", err) - r.cleanupPodNetwork(pod, networkNamespace) - return err - } - - r.generateEvents(runtimePod, "Started", nil) - - // This is a temporary solution until we have a clean design on how - // kubelet handles events. See https://github.com/kubernetes/kubernetes/issues/23084. - if err := r.runLifecycleHooks(pod, runtimePod, lifecyclePostStartHook); err != nil { - if errKill := r.KillPod(pod, *runtimePod, nil); errKill != nil { - return errors.NewAggregate([]error{err, errKill}) - } - r.cleanupPodNetwork(pod, networkNamespace) - return err - } - - return nil -} - -func (r *Runtime) runPreStopHook(containerID kubecontainer.ContainerID, pod *v1.Pod, container *v1.Container) error { - glog.V(4).Infof("rkt: Running pre-stop hook for container %q of pod %q", container.Name, format.Pod(pod)) - msg, err := r.runner.Run(containerID, pod, container, container.Lifecycle.PreStop) - if err != nil { - ref, ok := r.containerRefManager.GetRef(containerID) - if !ok { - glog.Warningf("No ref for container %q", containerID) - } else { - r.recorder.Eventf(ref, v1.EventTypeWarning, events.FailedPreStopHook, msg) - } - } - return err -} - -func (r *Runtime) runPostStartHook(containerID kubecontainer.ContainerID, pod *v1.Pod, container *v1.Container) error { - glog.V(4).Infof("rkt: Running post-start hook for container %q of pod %q", container.Name, format.Pod(pod)) - cid, err := parseContainerID(containerID) - if err != nil { - return fmt.Errorf("cannot parse container ID %v", containerID) - } - - isContainerRunning := func() (done bool, err error) { - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - resp, err := r.apisvc.InspectPod(ctx, &rktapi.InspectPodRequest{Id: cid.uuid}) - if err != nil { - return false, fmt.Errorf("failed to inspect rkt pod %q for pod %q", cid.uuid, format.Pod(pod)) - } - - for _, app := range resp.Pod.Apps { - if app.Name == cid.appName { - return app.State == rktapi.AppState_APP_STATE_RUNNING, nil - } - } - return false, fmt.Errorf("failed to find container %q in rkt pod %q", cid.appName, cid.uuid) - } - - // TODO(yifan): Polling the pod's state for now. - timeout := time.Second * 5 - pollInterval := time.Millisecond * 500 - if err := utilwait.Poll(pollInterval, timeout, isContainerRunning); err != nil { - return fmt.Errorf("rkt: Pod %q doesn't become running in %v: %v", format.Pod(pod), timeout, err) - } - - msg, err := r.runner.Run(containerID, pod, container, container.Lifecycle.PostStart) - if err != nil { - ref, ok := r.containerRefManager.GetRef(containerID) - if !ok { - glog.Warningf("No ref for container %q", containerID) - } else { - r.recorder.Eventf(ref, v1.EventTypeWarning, events.FailedPostStartHook, msg) - } - } - return err -} - -type lifecycleHookType string - -const ( - lifecyclePostStartHook lifecycleHookType = "post-start" - lifecyclePreStopHook lifecycleHookType = "pre-stop" -) - -func (r *Runtime) runLifecycleHooks(pod *v1.Pod, runtimePod *kubecontainer.Pod, typ lifecycleHookType) error { - var wg sync.WaitGroup - var errlist []error - errCh := make(chan error, len(pod.Spec.Containers)) - - wg.Add(len(pod.Spec.Containers)) - - for i, c := range pod.Spec.Containers { - var hookFunc func(kubecontainer.ContainerID, *v1.Pod, *v1.Container) error - - switch typ { - case lifecyclePostStartHook: - if c.Lifecycle != nil && c.Lifecycle.PostStart != nil { - hookFunc = r.runPostStartHook - } - case lifecyclePreStopHook: - if c.Lifecycle != nil && c.Lifecycle.PreStop != nil { - hookFunc = r.runPreStopHook - } - default: - errCh <- fmt.Errorf("Unrecognized lifecycle hook type %q for container %q in pod %q", typ, c.Name, format.Pod(pod)) - } - - if hookFunc == nil { - wg.Done() - continue - } - - container := &pod.Spec.Containers[i] - runtimeContainer := runtimePod.FindContainerByName(container.Name) - if runtimeContainer == nil { - // Container already gone. - wg.Done() - continue - } - containerID := runtimeContainer.ID - - go func() { - defer wg.Done() - if err := hookFunc(containerID, pod, container); err != nil { - glog.Errorf("rkt: Failed to run %s hook for container %q of pod %q: %v", typ, container.Name, format.Pod(pod), err) - errCh <- err - } else { - glog.V(4).Infof("rkt: %s hook completed successfully for container %q of pod %q", typ, container.Name, format.Pod(pod)) - } - }() - } - - wg.Wait() - close(errCh) - - for err := range errCh { - errlist = append(errlist, err) - } - return errors.NewAggregate(errlist) -} - -// convertRktPod will convert a rktapi.Pod to a kubecontainer.Pod -func (r *Runtime) convertRktPod(rktpod *rktapi.Pod) (*kubecontainer.Pod, error) { - manifest := &appcschema.PodManifest{} - err := json.Unmarshal(rktpod.Manifest, manifest) - if err != nil { - return nil, err - } - - podUID, ok := manifest.Annotations.Get(types.KubernetesPodUIDLabel) - if !ok { - return nil, fmt.Errorf("pod is missing annotation %s", types.KubernetesPodUIDLabel) - } - podName, ok := manifest.Annotations.Get(types.KubernetesPodNameLabel) - if !ok { - return nil, fmt.Errorf("pod is missing annotation %s", types.KubernetesPodNameLabel) - } - podNamespace, ok := manifest.Annotations.Get(types.KubernetesPodNamespaceLabel) - if !ok { - return nil, fmt.Errorf("pod is missing annotation %s", types.KubernetesPodNamespaceLabel) - } - - kubepod := &kubecontainer.Pod{ - ID: kubetypes.UID(podUID), - Name: podName, - Namespace: podNamespace, - } - - for i, app := range rktpod.Apps { - // The order of the apps is determined by the rkt pod manifest. - // TODO(yifan): Let the server to unmarshal the annotations? https://github.com/coreos/rkt/issues/1872 - hashStr, ok := manifest.Apps[i].Annotations.Get(k8sRktContainerHashAnno) - if !ok { - return nil, fmt.Errorf("app %q is missing annotation %s", app.Name, k8sRktContainerHashAnno) - } - containerHash, err := strconv.ParseUint(hashStr, 10, 64) - if err != nil { - return nil, fmt.Errorf("couldn't parse container's hash %q: %v", hashStr, err) - } - - kubepod.Containers = append(kubepod.Containers, &kubecontainer.Container{ - ID: buildContainerID(&containerID{rktpod.Id, app.Name}), - Name: app.Name, - // By default, the version returned by rkt API service will be "latest" if not specified. - Image: fmt.Sprintf("%s:%s", app.Image.Name, app.Image.Version), - ImageID: app.Image.Id, - Hash: containerHash, - State: appStateToContainerState(app.State), - }) - } - - return kubepod, nil -} - -// GetPods runs 'rkt list' to get the list of rkt pods. -// Then it will use the result to construct a list of container runtime pods. -// If all is false, then only running pods will be returned, otherwise all pods will be -// returned. -func (r *Runtime) GetPods(all bool) ([]*kubecontainer.Pod, error) { - glog.V(4).Infof("Rkt getting pods") - - listReq := &rktapi.ListPodsRequest{ - Detail: true, - Filters: []*rktapi.PodFilter{ - { - Annotations: []*rktapi.KeyValue{ - { - Key: k8sRktKubeletAnno, - Value: k8sRktKubeletAnnoValue, - }, - }, - }, - }, - } - if !all { - listReq.Filters[0].States = []rktapi.PodState{rktapi.PodState_POD_STATE_RUNNING} - } - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - listResp, err := r.apisvc.ListPods(ctx, listReq) - if err != nil { - return nil, fmt.Errorf("couldn't list pods: %v", err) - } - - pods := make(map[kubetypes.UID]*kubecontainer.Pod) - var podIDs []kubetypes.UID - for _, pod := range listResp.Pods { - pod, err := r.convertRktPod(pod) - if err != nil { - glog.Warningf("rkt: Cannot construct pod from unit file: %v.", err) - continue - } - - // Group pods together. - oldPod, found := pods[pod.ID] - if !found { - pods[pod.ID] = pod - podIDs = append(podIDs, pod.ID) - continue - } - - oldPod.Containers = append(oldPod.Containers, pod.Containers...) - } - - // Convert map to list, using the consistent order from the podIDs array. - var result []*kubecontainer.Pod - for _, id := range podIDs { - result = append(result, pods[id]) - } - - return result, nil -} - -func getPodTerminationGracePeriodInSecond(pod *v1.Pod) int64 { - var gracePeriod int64 - switch { - case pod.DeletionGracePeriodSeconds != nil: - gracePeriod = *pod.DeletionGracePeriodSeconds - case pod.Spec.TerminationGracePeriodSeconds != nil: - gracePeriod = *pod.Spec.TerminationGracePeriodSeconds - } - if gracePeriod < minimumGracePeriodInSeconds { - gracePeriod = minimumGracePeriodInSeconds - } - return gracePeriod -} - -func (r *Runtime) waitPreStopHooks(pod *v1.Pod, runningPod *kubecontainer.Pod) { - gracePeriod := getPodTerminationGracePeriodInSecond(pod) - - done := make(chan struct{}) - go func() { - if err := r.runLifecycleHooks(pod, runningPod, lifecyclePreStopHook); err != nil { - glog.Errorf("rkt: Some pre-stop hooks failed for pod %q: %v", format.Pod(pod), err) - } - close(done) - }() - - select { - case <-time.After(time.Duration(gracePeriod) * time.Second): - glog.V(2).Infof("rkt: Some pre-stop hooks did not complete in %d seconds for pod %q", gracePeriod, format.Pod(pod)) - case <-done: - } -} - -// KillPod invokes 'systemctl kill' to kill the unit that runs the pod. -// TODO: add support for gracePeriodOverride which is used in eviction scenarios -func (r *Runtime) KillPod(pod *v1.Pod, runningPod kubecontainer.Pod, gracePeriodOverride *int64) error { - glog.V(4).Infof("Rkt is killing pod: name %q.", runningPod.Name) - - if len(runningPod.Containers) == 0 { - glog.V(4).Infof("rkt: Pod %q is already being killed, no action will be taken", runningPod.Name) - return nil - } - - if pod != nil { - r.waitPreStopHooks(pod, &runningPod) - } - - containerID, err := parseContainerID(runningPod.Containers[0].ID) - if err != nil { - glog.Errorf("rkt: Failed to get rkt uuid of the pod %q: %v", runningPod.Name, err) - return err - } - serviceName := makePodServiceFileName(containerID.uuid) - serviceFile := serviceFilePath(serviceName) - - r.generateEvents(&runningPod, "Killing", nil) - for _, c := range runningPod.Containers { - r.containerRefManager.ClearRef(c.ID) - } - - // Since all service file have 'KillMode=mixed', the processes in - // the unit's cgroup will receive a SIGKILL if the normal stop timeouts. - reschan := make(chan string) - if _, err = r.systemd.StopUnit(serviceName, "replace", reschan); err != nil { - glog.Errorf("rkt: Failed to stop unit %q: %v", serviceName, err) - return err - } - - res := <-reschan - if res != "done" { - err := fmt.Errorf("invalid result: %s", res) - glog.Errorf("rkt: Failed to stop unit %q: %v", serviceName, err) - return err - } - - // Clean up networking. Use the service file to get pod details since 'pod' can be nil. - if err := r.cleanupPodNetworkFromServiceFile(serviceFile); err != nil { - glog.Errorf("rkt: failed to tear down network for unit %q: %v", serviceName, err) - return err - } - - return nil -} - -func (r *Runtime) Type() string { - return RktType -} - -func (r *Runtime) Version() (kubecontainer.Version, error) { - r.versions.RLock() - defer r.versions.RUnlock() - return r.versions.binVersion, nil -} - -func (r *Runtime) APIVersion() (kubecontainer.Version, error) { - r.versions.RLock() - defer r.versions.RUnlock() - return r.versions.apiVersion, nil -} - -// Status returns error if rkt is unhealthy, nil otherwise. -func (r *Runtime) Status() (*kubecontainer.RuntimeStatus, error) { - return nil, r.checkVersion(minimumRktBinVersion, minimumRktApiVersion, minimumSystemdVersion) -} - -// SyncPod syncs the running pod to match the specified desired pod. -func (r *Runtime) SyncPod(pod *v1.Pod, _ v1.PodStatus, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, backOff *flowcontrol.Backoff) (result kubecontainer.PodSyncResult) { - var err error - defer func() { - if err != nil { - result.Fail(err) - } - }() - // TODO: (random-liu) Stop using running pod in SyncPod() - runningPod := kubecontainer.ConvertPodStatusToRunningPod(r.Type(), podStatus) - // Add references to all containers. - unidentifiedContainers := make(map[kubecontainer.ContainerID]*kubecontainer.Container) - for _, c := range runningPod.Containers { - unidentifiedContainers[c.ID] = c - } - - restartPod := false - for _, container := range pod.Spec.Containers { - expectedHash := kubecontainer.HashContainerLegacy(&container) - - c := runningPod.FindContainerByName(container.Name) - if c == nil { - if kubecontainer.ShouldContainerBeRestarted(&container, pod, podStatus) { - glog.V(3).Infof("Container %+v is dead, but RestartPolicy says that we should restart it.", container) - // TODO(yifan): Containers in one pod are fate-sharing at this moment, see: - // https://github.com/appc/spec/issues/276. - restartPod = true - break - } - continue - } - - // TODO: check for non-root image directives. See ../docker/manager.go#SyncPod - - // TODO(yifan): Take care of host network change. - containerChanged := c.Hash != 0 && c.Hash != expectedHash - if containerChanged { - glog.Infof("Pod %q container %q hash changed (%d vs %d), it will be killed and re-created.", format.Pod(pod), container.Name, c.Hash, expectedHash) - restartPod = true - break - } - - liveness, found := r.livenessManager.Get(c.ID) - if found && liveness != proberesults.Success && pod.Spec.RestartPolicy != v1.RestartPolicyNever { - glog.Infof("Pod %q container %q is unhealthy, it will be killed and re-created.", format.Pod(pod), container.Name) - restartPod = true - break - } - - delete(unidentifiedContainers, c.ID) - } - - // If there is any unidentified containers, restart the pod. - if len(unidentifiedContainers) > 0 { - restartPod = true - } - - if restartPod { - // Kill the pod only if the pod is actually running. - if len(runningPod.Containers) > 0 { - if err = r.KillPod(pod, runningPod, nil); err != nil { - return - } - } - if err = r.RunPod(pod, pullSecrets); err != nil { - return - } - } - return -} - -// Sort rkt pods by creation time. -type podsByCreatedAt []*rktapi.Pod - -func (s podsByCreatedAt) Len() int { return len(s) } -func (s podsByCreatedAt) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s podsByCreatedAt) Less(i, j int) bool { return s[i].CreatedAt < s[j].CreatedAt } - -// getPodUID returns the pod's API UID, it returns -// empty UID if the UID cannot be determined. -func getPodUID(pod *rktapi.Pod) kubetypes.UID { - for _, anno := range pod.Annotations { - if anno.Key == types.KubernetesPodUIDLabel { - return kubetypes.UID(anno.Value) - } - } - return kubetypes.UID("") -} - -// podIsActive returns true if the pod is embryo, preparing or running. -// If a pod is prepared, it is not guaranteed to be active (e.g. the systemd -// service might fail). -func podIsActive(pod *rktapi.Pod) bool { - return pod.State == rktapi.PodState_POD_STATE_EMBRYO || - pod.State == rktapi.PodState_POD_STATE_PREPARING || - pod.State == rktapi.PodState_POD_STATE_RUNNING -} - -// GetNetNS returns the network namespace path for the given container -func (r *Runtime) GetNetNS(containerID kubecontainer.ContainerID) (string, error) { - // Currently the containerID is a UUID for a network namespace - // This hack is a way to create an unique network namespace for each new starting/restarting Pod - // We can do this because we played the same trick in - // `networkPlugin.SetUpPod` and `networkPlugin.TearDownPod`. - // See https://github.com/kubernetes/kubernetes/issues/45149 - return netnsPathFromName(containerID.ID), nil -} - -func (r *Runtime) GetPodContainerID(pod *kubecontainer.Pod) (kubecontainer.ContainerID, error) { - return kubecontainer.ContainerID{ID: string(pod.ID)}, nil -} - -func (r *Runtime) getKubernetesDirective(serviceFilePath string) (podService podServiceDirective, err error) { - f, err := os.Open(serviceFilePath) - if err != nil { - return podService, err - } - defer f.Close() - - opts, err := unit.Deserialize(f) - if err != nil { - return podService, err - } - - var hostnetwork, networkNamespace string - for _, o := range opts { - if o.Section != unitKubernetesSection { - continue - } - switch o.Name { - case unitPodUID: - podService.id = o.Value - case unitPodName: - podService.name = o.Value - case unitPodNamespace: - podService.namespace = o.Value - case unitPodHostNetwork: - hostnetwork = o.Value - case unitPodNetworkNamespace: - networkNamespace = o.Value - } - - if podService.id != "" && podService.name != "" && podService.namespace != "" && hostnetwork != "" && networkNamespace != "" { - podService.hostNetwork, err = strconv.ParseBool(hostnetwork) - podService.networkNamespace = kubecontainer.ContainerID{ID: networkNamespace} - if err != nil { - return podService, err - } - return podService, nil - } - } - - return podService, fmt.Errorf("failed to parse pod from file %s", serviceFilePath) -} - -func (r *Runtime) DeleteContainer(containerID kubecontainer.ContainerID) error { - return fmt.Errorf("unimplemented") -} - -// Collects all the systemd units for k8s Pods -func (r *Runtime) getPodSystemdServiceFiles() ([]os.FileInfo, error) { - // Get all the current units - files, err := r.os.ReadDir(systemdServiceDir) - if err != nil { - glog.Errorf("rkt: Failed to read the systemd service directory: %v", err) - return files, err - } - - // Keep only k8s unit files - k8sSystemdServiceFiles := files[:0] - for _, f := range files { - if strings.HasPrefix(f.Name(), kubernetesUnitPrefix) { - k8sSystemdServiceFiles = append(k8sSystemdServiceFiles, f) - } - } - return k8sSystemdServiceFiles, err -} - -// GarbageCollect collects the pods/containers. -// After one GC iteration: -// - The deleted pods will be removed. -// - If the number of containers exceeds gcPolicy.MaxContainers, -// then containers whose ages are older than gcPolicy.minAge will -// be removed. -func (r *Runtime) GarbageCollect(gcPolicy kubecontainer.ContainerGCPolicy, allSourcesReady bool, _ bool) error { - var errlist []error - var totalInactiveContainers int - var inactivePods []*rktapi.Pod - var removeCandidates []*rktapi.Pod - var allPods = map[string]*rktapi.Pod{} - - glog.V(4).Infof("rkt: Garbage collecting triggered with policy %v", gcPolicy) - - // GC all inactive systemd service files and pods. - files, err := r.getPodSystemdServiceFiles() - if err != nil { - return err - } - - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - resp, err := r.apisvc.ListPods(ctx, &rktapi.ListPodsRequest{Filters: kubernetesPodsFilters()}) - if err != nil { - glog.Errorf("rkt: Failed to list pods: %v", err) - return err - } - - // Mark inactive pods. - for _, pod := range resp.Pods { - allPods[pod.Id] = pod - if !podIsActive(pod) { - uid := getPodUID(pod) - if uid == kubetypes.UID("") { - glog.Errorf("rkt: Cannot get the UID of pod %q, pod is broken, will remove it", pod.Id) - removeCandidates = append(removeCandidates, pod) - continue - } - if r.podDeletionProvider.IsPodDeleted(uid) && allSourcesReady { - removeCandidates = append(removeCandidates, pod) - continue - } - - inactivePods = append(inactivePods, pod) - totalInactiveContainers = totalInactiveContainers + len(pod.Apps) - } - } - - // Remove any orphan service files. - for _, f := range files { - serviceName := f.Name() - rktUUID := getRktUUIDFromServiceFileName(serviceName) - if _, ok := allPods[rktUUID]; !ok { - glog.V(4).Infof("rkt: No rkt pod found for service file %q, will remove it", serviceName) - - if err := r.cleanupByPodId(rktUUID); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to clean up rkt pod %q: %v", rktUUID, err)) - } - } - } - - sort.Sort(podsByCreatedAt(inactivePods)) - - // Enforce GCPolicy.MaxContainers. - for _, pod := range inactivePods { - if totalInactiveContainers <= gcPolicy.MaxContainers { - break - } - creationTime := time.Unix(0, pod.CreatedAt) - if creationTime.Add(gcPolicy.MinAge).Before(time.Now()) { - // The pod is old and we are exceeding the MaxContainers limit. - // Delete the pod. - removeCandidates = append(removeCandidates, pod) - totalInactiveContainers = totalInactiveContainers - len(pod.Apps) - } - } - - // Remove pods and their service files. - for _, pod := range removeCandidates { - if err := r.removePod(pod); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to clean up rkt pod %q: %v", pod.Id, err)) - } - } - - return errors.NewAggregate(errlist) -} - -// Read kubernetes pod UUID, namespace, netns and name from systemd service file and -// use that to clean up any pod network that may still exist. -func (r *Runtime) cleanupPodNetworkFromServiceFile(serviceFilePath string) error { - podService, err := r.unitGetter.getKubernetesDirective(serviceFilePath) - if err != nil { - return err - } - return r.cleanupPodNetwork(&v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - UID: kubetypes.UID(podService.id), - Name: podService.name, - Namespace: podService.namespace, - }, - Spec: v1.PodSpec{ - HostNetwork: podService.hostNetwork, - }, - }, podService.networkNamespace) -} - -// Remove the touched file created by ExecStartPost in the systemd service file -func (r *Runtime) removeFinishedMarkerFile(serviceName string) error { - serviceFile := serviceFilePath(serviceName) - podDetail, err := r.unitGetter.getKubernetesDirective(serviceFile) - if err != nil { - return err - } - podDir := r.runtimeHelper.GetPodDir(kubetypes.UID(podDetail.id)) - finishedFile := podFinishedMarkerPath(podDir, getRktUUIDFromServiceFileName(serviceName)) - return r.os.Remove(finishedFile) -} - -// Iter over each container in the pod to delete its termination log file -func (r *Runtime) removeTerminationFiles(pod *rktapi.Pod) (errlist []error) { - // container == app - for _, app := range pod.Apps { - for _, annotation := range app.Annotations { - if annotation.GetKey() == k8sRktTerminationMessagePathAnno { - if err := r.os.Remove(annotation.GetValue()); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to remove for pod %q container file %v", pod.Id, err)) - } - } - } - } - return errlist -} - -func (r *Runtime) cleanupByPodId(podID string) (errlist []error) { - serviceName := makePodServiceFileName(podID) - serviceFile := serviceFilePath(serviceName) - - if err := r.cleanupPodNetworkFromServiceFile(serviceFile); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to clean up pod network from service %q: %v, the network may not be around already", serviceName, err)) - } - - // GC finished marker, termination-log file, systemd service files as well. - if err := r.systemd.ResetFailedUnit(serviceName); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to reset the failed systemd service %q: %v", serviceName, err)) - } - if err := r.removeFinishedMarkerFile(serviceName); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to remove finished file %q for unit %q: %v", serviceName, podID, err)) - } - if err := r.os.Remove(serviceFile); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to remove service file %q for pod %q: %v", serviceFile, podID, err)) - } - return errlist -} - -// removePod calls 'rkt rm $UUID' to delete a rkt pod, -// it also remove the systemd service file, -// the finished-* marker and the termination-log files -// related to the pod. -func (r *Runtime) removePod(pod *rktapi.Pod) error { - var errlist []error - glog.V(4).Infof("rkt: GC is removing pod %q", pod) - - if err := r.cleanupByPodId(pod.Id); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to remove pod %q: %v", pod.Id, err)) - } - if err := r.removeTerminationFiles(pod); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to clean up pod TerminationMessageFile %q: %v", pod.Id, err)) - } - - if _, err := r.cli.RunCommand(nil, "rm", pod.Id); err != nil { - errlist = append(errlist, fmt.Errorf("rkt: Failed to remove pod %q: %v", pod.Id, err)) - } - - return errors.NewAggregate(errlist) -} - -// rktExitError implements /pkg/util/exec.ExitError interface. -type rktExitError struct{ *exec.ExitError } - -var _ utilexec.ExitError = &rktExitError{} - -func (r *rktExitError) ExitStatus() int { - if status, ok := r.Sys().(syscall.WaitStatus); ok { - return status.ExitStatus() - } - return 0 -} - -func newRktExitError(e error) error { - if exitErr, ok := e.(*exec.ExitError); ok { - return &rktExitError{exitErr} - } - return e -} - -func (r *Runtime) AttachContainer(containerID kubecontainer.ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - return fmt.Errorf("unimplemented") -} - -// Note: In rkt, the container ID is in the form of "UUID:appName", where UUID is -// the rkt UUID, and appName is the container name. -// TODO(yifan): If the rkt is using lkvm as the stage1 image, then this function will fail. -func (r *Runtime) ExecInContainer(containerID kubecontainer.ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - glog.V(4).Infof("Rkt execing in container.") - - id, err := parseContainerID(containerID) - if err != nil { - return err - } - args := []string{"enter", fmt.Sprintf("--app=%s", id.appName), id.uuid} - args = append(args, cmd...) - command := buildCommand(r.config, args...) - - if tty { - p, err := kubecontainer.StartPty(command) - if err != nil { - return err - } - defer p.Close() - - // make sure to close the stdout stream - defer stdout.Close() - - kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) { - term.SetSize(p.Fd(), size) - }) - - if stdin != nil { - go io.Copy(p, stdin) - } - if stdout != nil { - go io.Copy(stdout, p) - } - return newRktExitError(command.Wait()) - } - if stdin != nil { - // Use an os.Pipe here as it returns true *os.File objects. - // This way, if you run 'kubectl exec -i bash' (no tty) and type 'exit', - // the call below to command.Run() can unblock because its Stdin is the read half - // of the pipe. - r, w, err := r.os.Pipe() - if err != nil { - return newRktExitError(err) - } - go io.Copy(w, stdin) - - command.Stdin = r - } - if stdout != nil { - command.Stdout = stdout - } - if stderr != nil { - command.Stderr = stderr - } - return newRktExitError(command.Run()) -} - -// PortForward executes socat in the pod's network namespace and copies -// data between stream (representing the user's local connection on their -// computer) and the specified port in the container. -// -// TODO: -// - match cgroups of container -// - should we support nsenter + socat on the host? (current impl) -// - should we support nsenter + socat in a container, running with elevated privs and --pid=host? -// -// TODO(yifan): Merge with the same function in dockertools. -func (r *Runtime) PortForward(pod *kubecontainer.Pod, port int32, stream io.ReadWriteCloser) error { - glog.V(4).Infof("Rkt port forwarding in container.") - - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - listResp, err := r.apisvc.ListPods(ctx, &rktapi.ListPodsRequest{ - Detail: true, - Filters: runningKubernetesPodFilters(pod.ID), - }) - if err != nil { - return fmt.Errorf("couldn't list pods: %v", err) - } - - if len(listResp.Pods) != 1 { - var podlist []string - for _, p := range listResp.Pods { - podlist = append(podlist, p.Id) - } - return fmt.Errorf("more than one running rkt pod for the kubernetes pod [%s]", strings.Join(podlist, ", ")) - } - listPod := listResp.Pods[0] - - socatPath, lookupErr := exec.LookPath("socat") - if lookupErr != nil { - return fmt.Errorf("unable to do port forwarding: socat not found.") - } - - // Check in config and in annotations if we're running kvm flavor - isKvm := strings.Contains(r.config.Stage1Image, "kvm") - for _, anno := range listPod.Annotations { - if anno.Key == k8sRktStage1NameAnno { - isKvm = strings.Contains(anno.Value, "kvm") - break - } - } - - var args []string - var fwCaller string - if isKvm { - podNetworks := listPod.GetNetworks() - if podNetworks == nil { - return fmt.Errorf("unable to get networks") - } - args = []string{"-", fmt.Sprintf("TCP4:%s:%d", podNetworks[0].Ipv4, port)} - fwCaller = socatPath - } else { - args = []string{"-t", fmt.Sprintf("%d", listPod.Pid), "-n", socatPath, "-", fmt.Sprintf("TCP4:localhost:%d", port)} - nsenterPath, lookupErr := exec.LookPath("nsenter") - if lookupErr != nil { - return fmt.Errorf("unable to do port forwarding: nsenter not found") - } - fwCaller = nsenterPath - } - - command := exec.Command(fwCaller, args...) - command.Stdout = stream - - // If we use Stdin, command.Run() won't return until the goroutine that's copying - // from stream finishes. Unfortunately, if you have a client like telnet connected - // via port forwarding, as long as the user's telnet client is connected to the user's - // local listener that port forwarding sets up, the telnet session never exits. This - // means that even if socat has finished running, command.Run() won't ever return - // (because the client still has the connection and stream open). - // - // The work around is to use StdinPipe(), as Wait() (called by Run()) closes the pipe - // when the command (socat) exits. - inPipe, err := command.StdinPipe() - if err != nil { - return fmt.Errorf("unable to do port forwarding: error creating stdin pipe: %v", err) - } - go func() { - io.Copy(inPipe, stream) - inPipe.Close() - }() - - return command.Run() -} - -// UpdatePodCIDR updates the runtimeconfig with the podCIDR. -// Currently no-ops, just implemented to satisfy the cri. -func (r *Runtime) UpdatePodCIDR(podCIDR string) error { - return nil -} - -// appStateToContainerState converts rktapi.AppState to kubecontainer.ContainerState. -func appStateToContainerState(state rktapi.AppState) kubecontainer.ContainerState { - switch state { - case rktapi.AppState_APP_STATE_RUNNING: - return kubecontainer.ContainerStateRunning - case rktapi.AppState_APP_STATE_EXITED: - return kubecontainer.ContainerStateExited - } - return kubecontainer.ContainerStateUnknown -} - -// getPodInfo returns the pod manifest, creation time and restart count of the pod. -func getPodInfo(pod *rktapi.Pod) (podManifest *appcschema.PodManifest, restartCount int, err error) { - // TODO(yifan): The manifest is only used for getting the annotations. - // Consider to let the server to unmarshal the annotations. - var manifest appcschema.PodManifest - if err = json.Unmarshal(pod.Manifest, &manifest); err != nil { - return - } - - if countString, ok := manifest.Annotations.Get(k8sRktRestartCountAnno); ok { - restartCount, err = strconv.Atoi(countString) - if err != nil { - return - } - } - - return &manifest, restartCount, nil -} - -// populateContainerStatus fills the container status according to the app's information. -func populateContainerStatus(pod rktapi.Pod, app rktapi.App, runtimeApp appcschema.RuntimeApp, restartCount int, finishedTime time.Time) (*kubecontainer.ContainerStatus, error) { - hashStr, ok := runtimeApp.Annotations.Get(k8sRktContainerHashAnno) - if !ok { - return nil, fmt.Errorf("No container hash in pod manifest") - } - - hashNum, err := strconv.ParseUint(hashStr, 10, 64) - if err != nil { - return nil, err - } - - var reason, message string - if app.State == rktapi.AppState_APP_STATE_EXITED { - if app.ExitCode == 0 { - reason = "Completed" - } else { - reason = "Error" - } - } - - terminationMessagePath, ok := runtimeApp.Annotations.Get(k8sRktTerminationMessagePathAnno) - if ok { - if data, err := ioutil.ReadFile(terminationMessagePath); err != nil { - message = fmt.Sprintf("Error on reading termination-log %s: %v", terminationMessagePath, err) - } else { - message = string(data) - } - } - - createdTime := time.Unix(0, pod.CreatedAt) - startedTime := time.Unix(0, pod.StartedAt) - - return &kubecontainer.ContainerStatus{ - ID: buildContainerID(&containerID{uuid: pod.Id, appName: app.Name}), - Name: app.Name, - State: appStateToContainerState(app.State), - CreatedAt: createdTime, - StartedAt: startedTime, - FinishedAt: finishedTime, - ExitCode: int(app.ExitCode), - // By default, the version returned by rkt API service will be "latest" if not specified. - Image: fmt.Sprintf("%s:%s", app.Image.Name, app.Image.Version), - ImageID: "rkt://" + app.Image.Id, // TODO(yifan): Add the prefix only in v1.PodStatus. - Hash: hashNum, - // TODO(yifan): Note that now all apps share the same restart count, this might - // change once apps don't share the same lifecycle. - // See https://github.com/appc/spec/pull/547. - RestartCount: restartCount, - Reason: reason, - Message: message, - }, nil -} - -// from a running systemd unit, return the network namespace of a Pod -// this field is inside the X-Kubernetes directive -func (r *Runtime) getNetworkNamespace(uid kubetypes.UID, latestPod *rktapi.Pod) (networkNamespace kubecontainer.ContainerID, err error) { - serviceFiles, err := r.getPodSystemdServiceFiles() - if err != nil { - return networkNamespace, err - } - - for _, f := range serviceFiles { - fileName := f.Name() - if latestPod.Id == getRktUUIDFromServiceFileName(fileName) { - podService, err := r.unitGetter.getKubernetesDirective(serviceFilePath(fileName)) - if err != nil { - return networkNamespace, err - } - return podService.networkNamespace, nil - } - } - - return networkNamespace, fmt.Errorf("Pod %q containing rktPod %q haven't find a corresponding NetworkNamespace in %d systemd units", uid, latestPod.Id, len(serviceFiles)) -} - -// GetPodStatus returns the status for a pod specified by a given UID, name, -// and namespace. It will attempt to find pod's information via a request to -// the rkt api server. -// An error will be returned if the api server returns an error. If the api -// server doesn't error, but doesn't provide meaningful information about the -// pod, a status with no information (other than the passed in arguments) is -// returned anyways. -func (r *Runtime) GetPodStatus(uid kubetypes.UID, name, namespace string) (*kubecontainer.PodStatus, error) { - podStatus := &kubecontainer.PodStatus{ - ID: uid, - Name: name, - Namespace: namespace, - } - - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - listResp, err := r.apisvc.ListPods(ctx, &rktapi.ListPodsRequest{ - Detail: true, - Filters: kubernetesPodFilters(uid), - }) - if err != nil { - return nil, fmt.Errorf("couldn't list pods: %v", err) - } - - var latestPod *rktapi.Pod - var latestRestartCount int = -1 - - // In this loop, we group all containers from all pods together, - // also we try to find the latest pod, so we can fill other info of the pod below. - for _, pod := range listResp.Pods { - manifest, restartCount, err := getPodInfo(pod) - if err != nil { - glog.Warningf("rkt: Couldn't get necessary info from the rkt pod, (uuid %q): %v", pod.Id, err) - continue - } - - if restartCount > latestRestartCount { - latestPod = pod - latestRestartCount = restartCount - } - - finishedTime := r.podFinishedAt(uid, pod.Id) - for i, app := range pod.Apps { - // The order of the apps is determined by the rkt pod manifest. - cs, err := populateContainerStatus(*pod, *app, manifest.Apps[i], restartCount, finishedTime) - if err != nil { - glog.Warningf("rkt: Failed to populate container status(uuid %q, app %q): %v", pod.Id, app.Name, err) - continue - } - podStatus.ContainerStatuses = append(podStatus.ContainerStatuses, cs) - } - } - - if latestPod == nil { - glog.Warningf("No latestPod: rkt api-svc returns [%d]rktPods, cannot fill podStatus.IP", len(listResp.Pods)) - return podStatus, nil - } - - // If we are running no-op network plugin, then get the pod IP from the rkt pod status. - if r.network.PluginName() == network.DefaultPluginName { - for _, n := range latestPod.Networks { - if n.Name == defaultNetworkName { - podStatus.IP = n.Ipv4 - break - } - } - return podStatus, nil - } - - networkNamespace, err := r.unitGetter.getNetworkNamespace(uid, latestPod) - if err != nil { - glog.Warningf("networkNamespace: %v", err) - } - status, err := r.network.GetPodNetworkStatus(namespace, name, networkNamespace) - if err != nil { - glog.Warningf("rkt: %v", err) - } else if status != nil { - // status can be nil when the pod is running on the host network, - // in which case the pod IP will be populated by the upper layer. - podStatus.IP = status.IP.String() - } - - return podStatus, nil -} - -// getOSReleaseInfo reads /etc/os-release and returns a map -// that contains the key value pairs in that file. -func getOSReleaseInfo() (map[string]string, error) { - result := make(map[string]string) - - path := "/etc/os-release" - f, err := os.Open(path) - if err != nil { - return nil, err - } - defer f.Close() - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - if len(strings.TrimSpace(line)) == 0 { - // Skips empty lines - continue - } - - info := strings.SplitN(line, "=", 2) - if len(info) != 2 { - glog.Warningf("Unexpected entry in os-release %q", line) - continue - } - result[info[0]] = info[1] - } - if err := scanner.Err(); err != nil { - return nil, err - } - return result, nil -} - -// convertKubeMounts creates appc volumes and mount points according to the given mounts. -// Only one volume will be created for every unique host path. -// Only one mount point will be created for every unique container path. -func convertKubeMounts(mounts []kubecontainer.Mount) ([]appctypes.Volume, []appctypes.MountPoint) { - volumeMap := make(map[string]*appctypes.Volume) - mountPointMap := make(map[string]*appctypes.MountPoint) - - for _, mnt := range mounts { - readOnly := mnt.ReadOnly - - if _, existed := volumeMap[mnt.HostPath]; !existed { - volumeMap[mnt.HostPath] = &appctypes.Volume{ - Name: *appctypes.MustACName(string(uuid.NewUUID())), - Kind: "host", - Source: mnt.HostPath, - ReadOnly: &readOnly, - } - } - - if _, existed := mountPointMap[mnt.ContainerPath]; existed { - glog.Warningf("Multiple mount points with the same container path %v, ignore it", mnt) - continue - } - - mountPointMap[mnt.ContainerPath] = &appctypes.MountPoint{ - Name: volumeMap[mnt.HostPath].Name, - Path: mnt.ContainerPath, - ReadOnly: readOnly, - } - } - - volumes := make([]appctypes.Volume, 0, len(volumeMap)) - mountPoints := make([]appctypes.MountPoint, 0, len(mountPointMap)) - - for _, vol := range volumeMap { - volumes = append(volumes, *vol) - } - for _, mnt := range mountPointMap { - mountPoints = append(mountPoints, *mnt) - } - - return volumes, mountPoints -} - -// convertKubePortMappings creates appc container ports and host ports according to the given port mappings. -// The container ports and host ports are mapped by PortMapping.Name. -func convertKubePortMappings(portMappings []kubecontainer.PortMapping) ([]appctypes.Port, []appctypes.ExposedPort) { - containerPorts := make([]appctypes.Port, 0, len(portMappings)) - hostPorts := make([]appctypes.ExposedPort, 0, len(portMappings)) - - for _, p := range portMappings { - // This matches the docker code's behaviour. - if p.HostPort == 0 { - continue - } - - portName := convertToACName(p.Name) - containerPorts = append(containerPorts, appctypes.Port{ - Name: portName, - Protocol: string(p.Protocol), - Port: uint(p.ContainerPort), - }) - - hostPorts = append(hostPorts, appctypes.ExposedPort{ - Name: portName, - HostPort: uint(p.HostPort), - }) - } - - return containerPorts, hostPorts -} - -func newNoNewPrivilegesIsolator(v bool) (*appctypes.Isolator, error) { - b := fmt.Sprintf(`{"name": "%s", "value": %t}`, appctypes.LinuxNoNewPrivilegesName, v) - - i := &appctypes.Isolator{ - Name: appctypes.LinuxNoNewPrivilegesName, - } - if err := i.UnmarshalJSON([]byte(b)); err != nil { - return nil, err - } - - return i, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/rkt_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/rkt_test.go deleted file mode 100644 index d235fe289..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/rkt_test.go +++ /dev/null @@ -1,2129 +0,0 @@ -/* -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 rkt - -import ( - "encoding/json" - "fmt" - "net" - "os" - "path/filepath" - "sort" - "strings" - "testing" - "time" - - appcschema "github.com/appc/spec/schema" - appctypes "github.com/appc/spec/schema/types" - "github.com/coreos/go-systemd/unit" - rktapi "github.com/coreos/rkt/api/v1alpha" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubetypes "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/errors" - utiltesting "k8s.io/client-go/util/testing" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - containertesting "k8s.io/kubernetes/pkg/kubelet/container/testing" - "k8s.io/kubernetes/pkg/kubelet/lifecycle" - "k8s.io/kubernetes/pkg/kubelet/network" - "k8s.io/kubernetes/pkg/kubelet/network/kubenet" - nettest "k8s.io/kubernetes/pkg/kubelet/network/testing" - "k8s.io/kubernetes/pkg/kubelet/types" - "k8s.io/utils/exec" - fakeexec "k8s.io/utils/exec/testing" -) - -func mustMarshalPodManifest(man *appcschema.PodManifest) []byte { - manblob, err := json.Marshal(man) - if err != nil { - panic(err) - } - return manblob -} - -func mustMarshalImageManifest(man *appcschema.ImageManifest) []byte { - manblob, err := json.Marshal(man) - if err != nil { - panic(err) - } - return manblob -} - -func mustRktHash(hash string) *appctypes.Hash { - h, err := appctypes.NewHash(hash) - if err != nil { - panic(err) - } - return h -} - -func makeRktPod(rktPodState rktapi.PodState, - rktPodID, podUID, podName, podNamespace string, podCreatedAt, podStartedAt int64, - podRestartCount string, appNames, imgIDs, imgNames, - containerHashes []string, appStates []rktapi.AppState, - exitcodes []int32, ips map[string]string) *rktapi.Pod { - - podManifest := &appcschema.PodManifest{ - ACKind: appcschema.PodManifestKind, - ACVersion: appcschema.AppContainerVersion, - Annotations: appctypes.Annotations{ - appctypes.Annotation{ - Name: *appctypes.MustACIdentifier(k8sRktKubeletAnno), - Value: k8sRktKubeletAnnoValue, - }, - appctypes.Annotation{ - Name: *appctypes.MustACIdentifier(types.KubernetesPodUIDLabel), - Value: podUID, - }, - appctypes.Annotation{ - Name: *appctypes.MustACIdentifier(types.KubernetesPodNameLabel), - Value: podName, - }, - appctypes.Annotation{ - Name: *appctypes.MustACIdentifier(types.KubernetesPodNamespaceLabel), - Value: podNamespace, - }, - appctypes.Annotation{ - Name: *appctypes.MustACIdentifier(k8sRktRestartCountAnno), - Value: podRestartCount, - }, - }, - } - - appNum := len(appNames) - if appNum != len(imgNames) || - appNum != len(imgIDs) || - appNum != len(containerHashes) || - appNum != len(appStates) { - panic("inconsistent app number") - } - - apps := make([]*rktapi.App, appNum) - for i := range appNames { - apps[i] = &rktapi.App{ - Name: appNames[i], - State: appStates[i], - Image: &rktapi.Image{ - Id: imgIDs[i], - Name: imgNames[i], - Version: "latest", - Manifest: mustMarshalImageManifest( - &appcschema.ImageManifest{ - ACKind: appcschema.ImageManifestKind, - ACVersion: appcschema.AppContainerVersion, - Name: *appctypes.MustACIdentifier(imgNames[i]), - Annotations: appctypes.Annotations{ - appctypes.Annotation{ - Name: *appctypes.MustACIdentifier(k8sRktContainerHashAnno), - Value: containerHashes[i], - }, - }, - }, - ), - }, - ExitCode: exitcodes[i], - } - podManifest.Apps = append(podManifest.Apps, appcschema.RuntimeApp{ - Name: *appctypes.MustACName(appNames[i]), - Image: appcschema.RuntimeImage{ID: *mustRktHash("sha512-foo")}, - Annotations: appctypes.Annotations{ - appctypes.Annotation{ - Name: *appctypes.MustACIdentifier(k8sRktContainerHashAnno), - Value: containerHashes[i], - }, - }, - }) - } - - var networks []*rktapi.Network - for name, ip := range ips { - networks = append(networks, &rktapi.Network{Name: name, Ipv4: ip}) - } - - return &rktapi.Pod{ - Id: rktPodID, - State: rktPodState, - Apps: apps, - Manifest: mustMarshalPodManifest(podManifest), - StartedAt: podStartedAt, - CreatedAt: podCreatedAt, - Networks: networks, - } -} - -func TestCheckVersion(t *testing.T) { - fr := newFakeRktInterface() - fs := newFakeSystemd() - r := &Runtime{apisvc: fr, systemd: fs} - - fr.info = rktapi.Info{ - RktVersion: "1.2.3+git", - AppcVersion: "1.2.4+git", - ApiVersion: "1.2.6-alpha", - } - fs.version = "100" - tests := []struct { - minimumRktBinVersion string - minimumRktApiVersion string - minimumSystemdVersion string - err error - calledGetInfo bool - calledSystemVersion bool - }{ - // Good versions. - { - "1.2.3", - "1.2.5", - "99", - nil, - true, - true, - }, - // Good versions. - { - "1.2.3+git", - "1.2.6-alpha", - "100", - nil, - true, - true, - }, - // Requires greater binary version. - { - "1.2.4", - "1.2.6-alpha", - "100", - fmt.Errorf("rkt: binary version is too old(%v), requires at least %v", fr.info.RktVersion, "1.2.4"), - true, - true, - }, - // Requires greater API version. - { - "1.2.3", - "1.2.6", - "100", - fmt.Errorf("rkt: API version is too old(%v), requires at least %v", fr.info.ApiVersion, "1.2.6"), - true, - true, - }, - // Requires greater API version. - { - "1.2.3", - "1.2.7", - "100", - fmt.Errorf("rkt: API version is too old(%v), requires at least %v", fr.info.ApiVersion, "1.2.7"), - true, - true, - }, - // Requires greater systemd version. - { - "1.2.3", - "1.2.7", - "101", - fmt.Errorf("rkt: systemd version(%v) is too old, requires at least %v", fs.version, "101"), - false, - true, - }, - } - - for i, tt := range tests { - testCaseHint := fmt.Sprintf("test case #%d", i) - err := r.checkVersion(tt.minimumRktBinVersion, tt.minimumRktApiVersion, tt.minimumSystemdVersion) - assert.Equal(t, tt.err, err, testCaseHint) - - if tt.calledGetInfo { - assert.Equal(t, fr.called, []string{"GetInfo"}, testCaseHint) - } - if tt.calledSystemVersion { - assert.Equal(t, fs.called, []string{"Version"}, testCaseHint) - } - if err == nil { - assert.Equal(t, fr.info.RktVersion, r.versions.binVersion.String(), testCaseHint) - assert.Equal(t, fr.info.ApiVersion, r.versions.apiVersion.String(), testCaseHint) - } - fr.CleanCalls() - fs.CleanCalls() - } -} - -func TestListImages(t *testing.T) { - fr := newFakeRktInterface() - fs := newFakeSystemd() - r := &Runtime{apisvc: fr, systemd: fs} - - tests := []struct { - images []*rktapi.Image - expected []kubecontainer.Image - }{ - {nil, []kubecontainer.Image{}}, - { - []*rktapi.Image{ - { - Id: "sha512-a2fb8f390702", - Name: "quay.io/coreos/alpine-sh", - Version: "latest", - }, - }, - []kubecontainer.Image{ - { - ID: "sha512-a2fb8f390702", - RepoTags: []string{"quay.io/coreos/alpine-sh:latest"}, - }, - }, - }, - { - []*rktapi.Image{ - { - Id: "sha512-a2fb8f390702", - Name: "quay.io/coreos/alpine-sh", - Version: "latest", - Size: 400, - }, - { - Id: "sha512-c6b597f42816", - Name: "coreos.com/rkt/stage1-coreos", - Version: "0.10.0", - Size: 400, - }, - }, - []kubecontainer.Image{ - { - ID: "sha512-a2fb8f390702", - RepoTags: []string{"quay.io/coreos/alpine-sh:latest"}, - Size: 400, - }, - { - ID: "sha512-c6b597f42816", - RepoTags: []string{"coreos.com/rkt/stage1-coreos:0.10.0"}, - Size: 400, - }, - }, - }, - { - []*rktapi.Image{ - { - Id: "sha512-a2fb8f390702", - Name: "quay.io_443/coreos/alpine-sh", - Version: "latest", - Annotations: []*rktapi.KeyValue{ - { - Key: appcDockerRegistryURL, - Value: "quay.io:443", - }, - { - Key: appcDockerRepository, - Value: "coreos/alpine-sh", - }, - }, - Size: 400, - }, - }, - []kubecontainer.Image{ - { - ID: "sha512-a2fb8f390702", - RepoTags: []string{"quay.io:443/coreos/alpine-sh:latest"}, - Size: 400, - }, - }, - }, - } - - for i, tt := range tests { - fr.images = tt.images - - images, err := r.ListImages() - if err != nil { - t.Errorf("%v", err) - } - assert.Equal(t, tt.expected, images) - assert.Equal(t, fr.called, []string{"ListImages"}, fmt.Sprintf("test case %d: unexpected called list", i)) - - fr.CleanCalls() - } -} - -func TestGetPods(t *testing.T) { - fr := newFakeRktInterface() - fs := newFakeSystemd() - r := &Runtime{apisvc: fr, systemd: fs} - - ns := func(seconds int64) int64 { - return seconds * 1e9 - } - - tests := []struct { - pods []*rktapi.Pod - result []*kubecontainer.Pod - }{ - // No pods. - {}, - // One pod. - { - []*rktapi.Pod{ - makeRktPod(rktapi.PodState_POD_STATE_RUNNING, - "uuid-4002", "42", "guestbook", "default", - ns(10), ns(10), "7", - []string{"app-1", "app-2"}, - []string{"img-id-1", "img-id-2"}, - []string{"img-name-1", "img-name-2"}, - []string{"1001", "1002"}, - []rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED}, - []int32{0, 0}, - nil, - ), - }, - []*kubecontainer.Pod{ - { - ID: "42", - Name: "guestbook", - Namespace: "default", - Containers: []*kubecontainer.Container{ - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-1"), - Name: "app-1", - Image: "img-name-1:latest", - ImageID: "img-id-1", - Hash: 1001, - State: "running", - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-2"), - Name: "app-2", - Image: "img-name-2:latest", - ImageID: "img-id-2", - Hash: 1002, - State: "exited", - }, - }, - }, - }, - }, - // Multiple pods. - { - []*rktapi.Pod{ - makeRktPod(rktapi.PodState_POD_STATE_RUNNING, - "uuid-4002", "42", "guestbook", "default", - ns(10), ns(20), "7", - []string{"app-1", "app-2"}, - []string{"img-id-1", "img-id-2"}, - []string{"img-name-1", "img-name-2"}, - []string{"1001", "1002"}, - []rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED}, - []int32{0, 0}, - nil, - ), - makeRktPod(rktapi.PodState_POD_STATE_EXITED, - "uuid-4003", "43", "guestbook", "default", - ns(30), ns(40), "7", - []string{"app-11", "app-22"}, - []string{"img-id-11", "img-id-22"}, - []string{"img-name-11", "img-name-22"}, - []string{"10011", "10022"}, - []rktapi.AppState{rktapi.AppState_APP_STATE_EXITED, rktapi.AppState_APP_STATE_EXITED}, - []int32{0, 0}, - nil, - ), - makeRktPod(rktapi.PodState_POD_STATE_EXITED, - "uuid-4004", "43", "guestbook", "default", - ns(50), ns(60), "8", - []string{"app-11", "app-22"}, - []string{"img-id-11", "img-id-22"}, - []string{"img-name-11", "img-name-22"}, - []string{"10011", "10022"}, - []rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_RUNNING}, - []int32{0, 0}, - nil, - ), - }, - []*kubecontainer.Pod{ - { - ID: "42", - Name: "guestbook", - Namespace: "default", - Containers: []*kubecontainer.Container{ - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-1"), - Name: "app-1", - Image: "img-name-1:latest", - ImageID: "img-id-1", - Hash: 1001, - State: "running", - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-2"), - Name: "app-2", - Image: "img-name-2:latest", - ImageID: "img-id-2", - Hash: 1002, - State: "exited", - }, - }, - }, - { - ID: "43", - Name: "guestbook", - Namespace: "default", - Containers: []*kubecontainer.Container{ - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4003:app-11"), - Name: "app-11", - Image: "img-name-11:latest", - ImageID: "img-id-11", - Hash: 10011, - State: "exited", - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4003:app-22"), - Name: "app-22", - Image: "img-name-22:latest", - ImageID: "img-id-22", - Hash: 10022, - State: "exited", - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4004:app-11"), - Name: "app-11", - Image: "img-name-11:latest", - ImageID: "img-id-11", - Hash: 10011, - State: "running", - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4004:app-22"), - Name: "app-22", - Image: "img-name-22:latest", - ImageID: "img-id-22", - Hash: 10022, - State: "running", - }, - }, - }, - }, - }, - } - - for i, tt := range tests { - testCaseHint := fmt.Sprintf("test case #%d", i) - fr.pods = tt.pods - - pods, err := r.GetPods(true) - if err != nil { - t.Errorf("test case #%d: unexpected error: %v", i, err) - } - - assert.Equal(t, tt.result, pods, testCaseHint) - assert.Equal(t, []string{"ListPods"}, fr.called, fmt.Sprintf("test case %d: unexpected called list", i)) - - fr.CleanCalls() - } -} - -func TestGetPodsFilters(t *testing.T) { - fr := newFakeRktInterface() - fs := newFakeSystemd() - r := &Runtime{apisvc: fr, systemd: fs} - - for _, test := range []struct { - All bool - ExpectedFilters []*rktapi.PodFilter - }{ - { - true, - []*rktapi.PodFilter{ - { - Annotations: []*rktapi.KeyValue{ - { - Key: k8sRktKubeletAnno, - Value: k8sRktKubeletAnnoValue, - }, - }, - }, - }, - }, - { - false, - []*rktapi.PodFilter{ - { - States: []rktapi.PodState{rktapi.PodState_POD_STATE_RUNNING}, - Annotations: []*rktapi.KeyValue{ - { - Key: k8sRktKubeletAnno, - Value: k8sRktKubeletAnnoValue, - }, - }, - }, - }, - }, - } { - _, err := r.GetPods(test.All) - if err != nil { - t.Errorf("%v", err) - } - assert.Equal(t, test.ExpectedFilters, fr.podFilters, "filters didn't match when all=%b", test.All) - } -} - -func TestGetPodStatus(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - fr := newFakeRktInterface() - fs := newFakeSystemd() - fug := newfakeUnitGetter() - fnp := nettest.NewMockNetworkPlugin(ctrl) - fos := &containertesting.FakeOS{} - frh := &containertesting.FakeRuntimeHelper{} - r := &Runtime{ - apisvc: fr, - systemd: fs, - runtimeHelper: frh, - os: fos, - network: network.NewPluginManager(fnp), - unitGetter: fug, - } - - ns := func(seconds int64) int64 { - return seconds * 1e9 - } - - tests := []struct { - networkPluginName string - pods []*rktapi.Pod - result *kubecontainer.PodStatus - }{ - // # case 0, No pods. - { - kubenet.KubenetPluginName, - nil, - &kubecontainer.PodStatus{ID: "42", Name: "guestbook", Namespace: "default"}, - }, - // # case 1, One pod. - { - kubenet.KubenetPluginName, - []*rktapi.Pod{ - makeRktPod(rktapi.PodState_POD_STATE_RUNNING, - "uuid-4002", "42", "guestbook", "default", - ns(10), ns(20), "7", - []string{"app-1", "app-2"}, - []string{"img-id-1", "img-id-2"}, - []string{"img-name-1", "img-name-2"}, - []string{"1001", "1002"}, - []rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED}, - []int32{0, 0}, - nil, - ), - }, - &kubecontainer.PodStatus{ - ID: "42", - Name: "guestbook", - Namespace: "default", - IP: "10.10.10.42", - ContainerStatuses: []*kubecontainer.ContainerStatus{ - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-1"), - Name: "app-1", - State: kubecontainer.ContainerStateRunning, - CreatedAt: time.Unix(10, 0), - StartedAt: time.Unix(20, 0), - FinishedAt: time.Unix(0, 30), - Image: "img-name-1:latest", - ImageID: "rkt://img-id-1", - Hash: 1001, - RestartCount: 7, - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-2"), - Name: "app-2", - State: kubecontainer.ContainerStateExited, - CreatedAt: time.Unix(10, 0), - StartedAt: time.Unix(20, 0), - FinishedAt: time.Unix(0, 30), - Image: "img-name-2:latest", - ImageID: "rkt://img-id-2", - Hash: 1002, - RestartCount: 7, - Reason: "Completed", - }, - }, - }, - }, - // # case 2, One pod with no-op network plugin name. - { - network.DefaultPluginName, - []*rktapi.Pod{ - makeRktPod(rktapi.PodState_POD_STATE_RUNNING, - "uuid-4002", "42", "guestbook", "default", - ns(10), ns(20), "7", - []string{"app-1", "app-2"}, - []string{"img-id-1", "img-id-2"}, - []string{"img-name-1", "img-name-2"}, - []string{"1001", "1002"}, - []rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED}, - []int32{0, 0}, - map[string]string{defaultNetworkName: "10.10.10.22"}, - ), - }, - &kubecontainer.PodStatus{ - ID: "42", - Name: "guestbook", - Namespace: "default", - IP: "10.10.10.22", - ContainerStatuses: []*kubecontainer.ContainerStatus{ - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-1"), - Name: "app-1", - State: kubecontainer.ContainerStateRunning, - CreatedAt: time.Unix(10, 0), - StartedAt: time.Unix(20, 0), - FinishedAt: time.Unix(0, 30), - Image: "img-name-1:latest", - ImageID: "rkt://img-id-1", - Hash: 1001, - RestartCount: 7, - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-2"), - Name: "app-2", - State: kubecontainer.ContainerStateExited, - CreatedAt: time.Unix(10, 0), - StartedAt: time.Unix(20, 0), - FinishedAt: time.Unix(0, 30), - Image: "img-name-2:latest", - ImageID: "rkt://img-id-2", - Hash: 1002, - RestartCount: 7, - Reason: "Completed", - }, - }, - }, - }, - // # case 3, Multiple pods. - { - kubenet.KubenetPluginName, - []*rktapi.Pod{ - makeRktPod(rktapi.PodState_POD_STATE_EXITED, - "uuid-4002", "42", "guestbook", "default", - ns(10), ns(20), "7", - []string{"app-1", "app-2"}, - []string{"img-id-1", "img-id-2"}, - []string{"img-name-1", "img-name-2"}, - []string{"1001", "1002"}, - []rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED}, - []int32{0, 0}, - nil, - ), - makeRktPod(rktapi.PodState_POD_STATE_RUNNING, // The latest pod is running. - "uuid-4003", "42", "guestbook", "default", - ns(10), ns(20), "10", - []string{"app-1", "app-2"}, - []string{"img-id-1", "img-id-2"}, - []string{"img-name-1", "img-name-2"}, - []string{"1001", "1002"}, - []rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED}, - []int32{0, 1}, - nil, - ), - }, - &kubecontainer.PodStatus{ - ID: "42", - Name: "guestbook", - Namespace: "default", - IP: "10.10.10.42", - // Result should contain all containers. - ContainerStatuses: []*kubecontainer.ContainerStatus{ - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-1"), - Name: "app-1", - State: kubecontainer.ContainerStateRunning, - CreatedAt: time.Unix(10, 0), - StartedAt: time.Unix(20, 0), - FinishedAt: time.Unix(0, 30), - Image: "img-name-1:latest", - ImageID: "rkt://img-id-1", - Hash: 1001, - RestartCount: 7, - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-2"), - Name: "app-2", - State: kubecontainer.ContainerStateExited, - CreatedAt: time.Unix(10, 0), - StartedAt: time.Unix(20, 0), - FinishedAt: time.Unix(0, 30), - Image: "img-name-2:latest", - ImageID: "rkt://img-id-2", - Hash: 1002, - RestartCount: 7, - Reason: "Completed", - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4003:app-1"), - Name: "app-1", - State: kubecontainer.ContainerStateRunning, - CreatedAt: time.Unix(10, 0), - StartedAt: time.Unix(20, 0), - FinishedAt: time.Unix(0, 30), - Image: "img-name-1:latest", - ImageID: "rkt://img-id-1", - Hash: 1001, - RestartCount: 10, - }, - { - ID: kubecontainer.BuildContainerID("rkt", "uuid-4003:app-2"), - Name: "app-2", - State: kubecontainer.ContainerStateExited, - CreatedAt: time.Unix(10, 0), - StartedAt: time.Unix(20, 0), - FinishedAt: time.Unix(0, 30), - Image: "img-name-2:latest", - ImageID: "rkt://img-id-2", - Hash: 1002, - RestartCount: 10, - ExitCode: 1, - Reason: "Error", - }, - }, - }, - }, - } - - for i, tt := range tests { - testCaseHint := fmt.Sprintf("test case #%d", i) - fr.pods = tt.pods - - podTimes := map[string]time.Time{} - for _, pod := range tt.pods { - podTimes[podFinishedMarkerPath(r.runtimeHelper.GetPodDir(tt.result.ID), pod.Id)] = tt.result.ContainerStatuses[0].FinishedAt - } - - ctrl := gomock.NewController(t) - - r.os.(*containertesting.FakeOS).StatFn = func(name string) (os.FileInfo, error) { - podTime, ok := podTimes[name] - if !ok { - t.Errorf("osStat called with %v, but only knew about %#v", name, podTimes) - } - mockFI := containertesting.NewMockFileInfo(ctrl) - mockFI.EXPECT().ModTime().Return(podTime) - return mockFI, nil - } - - if tt.networkPluginName == network.DefaultPluginName { - fnp.EXPECT().Name().Return(tt.networkPluginName) - } - - if tt.pods != nil && tt.networkPluginName == kubenet.KubenetPluginName { - fnp.EXPECT().Name().Return(tt.networkPluginName) - if tt.result.IP != "" { - fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}). - Return(&network.PodNetworkStatus{IP: net.ParseIP(tt.result.IP)}, nil) - } else { - fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}). - Return(nil, fmt.Errorf("no such network")) - // Plugin name only requested again in error case - fnp.EXPECT().Name().Return(tt.networkPluginName) - } - } - - status, err := r.GetPodStatus("42", "guestbook", "default") - if err != nil { - t.Errorf("test case #%d: unexpected error: %v", i, err) - } - - assert.Equal(t, tt.result, status, testCaseHint) - assert.Equal(t, []string{"ListPods"}, fr.called, testCaseHint) - fug.networkNamespace = kubecontainer.ContainerID{} - fr.CleanCalls() - ctrl.Finish() - } -} - -func generateCapRetainIsolator(t *testing.T, caps ...string) appctypes.Isolator { - retain, err := appctypes.NewLinuxCapabilitiesRetainSet(caps...) - if err != nil { - t.Fatalf("Error generating cap retain isolator: %v", err) - } - isolator, err := retain.AsIsolator() - if err != nil { - t.Fatalf("Error generating cap retain isolator: %v", err) - } - return *isolator -} - -func generateCapRevokeIsolator(t *testing.T, caps ...string) appctypes.Isolator { - revoke, err := appctypes.NewLinuxCapabilitiesRevokeSet(caps...) - if err != nil { - t.Fatalf("Error generating cap revoke isolator: %v", err) - } - isolator, err := revoke.AsIsolator() - if err != nil { - t.Fatalf("Error generating cap revoke isolator: %v", err) - } - return *isolator -} - -func generateCPUIsolator(t *testing.T, request, limit string) appctypes.Isolator { - cpu, err := appctypes.NewResourceCPUIsolator(request, limit) - if err != nil { - t.Fatalf("Error generating cpu resource isolator: %v", err) - } - return cpu.AsIsolator() -} - -func generateMemoryIsolator(t *testing.T, request, limit string) appctypes.Isolator { - memory, err := appctypes.NewResourceMemoryIsolator(request, limit) - if err != nil { - t.Fatalf("Error generating memory resource isolator: %v", err) - } - return memory.AsIsolator() -} - -func baseApp(t *testing.T) *appctypes.App { - return &appctypes.App{ - User: "0", - Group: "0", - Exec: appctypes.Exec{"/bin/foo", "bar"}, - SupplementaryGIDs: []int{4, 5, 6}, - WorkingDirectory: "/foo", - Environment: []appctypes.EnvironmentVariable{ - {Name: "env-foo", Value: "bar"}, - }, - MountPoints: []appctypes.MountPoint{ - {Name: *appctypes.MustACName("mnt-foo"), Path: "/mnt-foo", ReadOnly: false}, - }, - Ports: []appctypes.Port{ - {Name: *appctypes.MustACName("port-foo"), Protocol: "TCP", Port: 4242}, - }, - Isolators: []appctypes.Isolator{ - generateCapRetainIsolator(t, "CAP_SYS_ADMIN"), - generateCapRevokeIsolator(t, "CAP_NET_ADMIN"), - generateCPUIsolator(t, "100m", "200m"), - generateMemoryIsolator(t, "10M", "20M"), - }, - } -} - -func baseImageManifest(t *testing.T) *appcschema.ImageManifest { - img := &appcschema.ImageManifest{App: baseApp(t)} - entrypoint, err := json.Marshal([]string{"/bin/foo"}) - if err != nil { - t.Fatal(err) - } - cmd, err := json.Marshal([]string{"bar"}) - if err != nil { - t.Fatal(err) - } - img.Annotations.Set(*appctypes.MustACIdentifier(appcDockerEntrypoint), string(entrypoint)) - img.Annotations.Set(*appctypes.MustACIdentifier(appcDockerCmd), string(cmd)) - return img -} - -func baseAppWithRootUserGroup(t *testing.T) *appctypes.App { - app := baseApp(t) - app.User, app.Group = "0", "0" - app.Isolators = append(app.Isolators) - return app -} - -type envByName []appctypes.EnvironmentVariable - -func (s envByName) Len() int { return len(s) } -func (s envByName) Less(i, j int) bool { return s[i].Name < s[j].Name } -func (s envByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -type mountsByName []appctypes.MountPoint - -func (s mountsByName) Len() int { return len(s) } -func (s mountsByName) Less(i, j int) bool { return s[i].Name < s[j].Name } -func (s mountsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -type portsByName []appctypes.Port - -func (s portsByName) Len() int { return len(s) } -func (s portsByName) Less(i, j int) bool { return s[i].Name < s[j].Name } -func (s portsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -type isolatorsByName []appctypes.Isolator - -func (s isolatorsByName) Len() int { return len(s) } -func (s isolatorsByName) Less(i, j int) bool { return s[i].Name < s[j].Name } -func (s isolatorsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -func sortAppFields(app *appctypes.App) { - sort.Sort(envByName(app.Environment)) - sort.Sort(mountsByName(app.MountPoints)) - sort.Sort(portsByName(app.Ports)) - sort.Sort(isolatorsByName(app.Isolators)) -} - -type sortedStringList []string - -func (s sortedStringList) Len() int { return len(s) } -func (s sortedStringList) Less(i, j int) bool { return s[i] < s[j] } -func (s sortedStringList) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -func TestSetApp(t *testing.T) { - tmpDir, err := utiltesting.MkTmpdir("rkt_test") - if err != nil { - t.Fatalf("error creating temp dir: %v", err) - } - defer os.RemoveAll(tmpDir) - - rootUser := int64(0) - nonRootUser := int64(42) - runAsNonRootTrue := true - fsgid := int64(3) - - tests := []struct { - container *v1.Container - mountPoints []appctypes.MountPoint - containerPorts []appctypes.Port - envs []kubecontainer.EnvVar - ctx *v1.SecurityContext - podCtx *v1.PodSecurityContext - supplementalGids []int64 - expect *appctypes.App - err error - }{ - // Nothing should change, but the "User" and "Group" should be filled. - { - container: &v1.Container{}, - mountPoints: []appctypes.MountPoint{}, - containerPorts: []appctypes.Port{}, - envs: []kubecontainer.EnvVar{}, - ctx: nil, - podCtx: nil, - supplementalGids: nil, - expect: baseAppWithRootUserGroup(t), - err: nil, - }, - - // error verifying non-root. - { - container: &v1.Container{}, - mountPoints: []appctypes.MountPoint{}, - containerPorts: []appctypes.Port{}, - envs: []kubecontainer.EnvVar{}, - ctx: &v1.SecurityContext{ - RunAsNonRoot: &runAsNonRootTrue, - RunAsUser: &rootUser, - }, - podCtx: nil, - supplementalGids: nil, - expect: nil, - err: fmt.Errorf("container has no runAsUser and image will run as root"), - }, - - // app's args should be changed. - { - container: &v1.Container{ - Args: []string{"foo"}, - }, - mountPoints: []appctypes.MountPoint{}, - containerPorts: []appctypes.Port{}, - envs: []kubecontainer.EnvVar{}, - ctx: nil, - podCtx: nil, - supplementalGids: nil, - expect: &appctypes.App{ - Exec: appctypes.Exec{"/bin/foo", "foo"}, - User: "0", - Group: "0", - SupplementaryGIDs: []int{4, 5, 6}, - WorkingDirectory: "/foo", - Environment: []appctypes.EnvironmentVariable{ - {Name: "env-foo", Value: "bar"}, - }, - MountPoints: []appctypes.MountPoint{ - {Name: *appctypes.MustACName("mnt-foo"), Path: "/mnt-foo", ReadOnly: false}, - }, - Ports: []appctypes.Port{ - {Name: *appctypes.MustACName("port-foo"), Protocol: "TCP", Port: 4242}, - }, - Isolators: []appctypes.Isolator{ - generateCapRetainIsolator(t, "CAP_SYS_ADMIN"), - generateCapRevokeIsolator(t, "CAP_NET_ADMIN"), - generateCPUIsolator(t, "100m", "200m"), - generateMemoryIsolator(t, "10M", "20M"), - }, - }, - err: nil, - }, - - // app should be changed. - { - container: &v1.Container{ - Command: []string{"/bin/bar", "$(env-bar)"}, - WorkingDir: tmpDir, - Resources: v1.ResourceRequirements{ - Limits: v1.ResourceList{v1.ResourceCPU: resource.MustParse("50m"), v1.ResourceMemory: resource.MustParse("50M")}, - Requests: v1.ResourceList{v1.ResourceCPU: resource.MustParse("5m"), v1.ResourceMemory: resource.MustParse("5M")}, - }, - }, - mountPoints: []appctypes.MountPoint{ - {Name: *appctypes.MustACName("mnt-bar"), Path: "/mnt-bar", ReadOnly: true}, - }, - containerPorts: []appctypes.Port{ - {Name: *appctypes.MustACName("port-bar"), Protocol: "TCP", Port: 1234}, - }, - envs: []kubecontainer.EnvVar{ - {Name: "env-bar", Value: "foo"}, - }, - ctx: &v1.SecurityContext{ - Capabilities: &v1.Capabilities{ - Add: []v1.Capability{"CAP_SYS_CHROOT", "CAP_SYS_BOOT"}, - Drop: []v1.Capability{"CAP_SETUID", "CAP_SETGID"}, - }, - RunAsUser: &nonRootUser, - RunAsNonRoot: &runAsNonRootTrue, - }, - podCtx: &v1.PodSecurityContext{ - SupplementalGroups: []int64{ - int64(1), - int64(2), - }, - FSGroup: &fsgid, - }, - supplementalGids: []int64{4}, - expect: &appctypes.App{ - Exec: appctypes.Exec{"/bin/bar", "foo"}, - User: "42", - Group: "0", - SupplementaryGIDs: []int{1, 2, 3, 4}, - WorkingDirectory: tmpDir, - Environment: []appctypes.EnvironmentVariable{ - {Name: "env-foo", Value: "bar"}, - {Name: "env-bar", Value: "foo"}, - }, - MountPoints: []appctypes.MountPoint{ - {Name: *appctypes.MustACName("mnt-foo"), Path: "/mnt-foo", ReadOnly: false}, - {Name: *appctypes.MustACName("mnt-bar"), Path: "/mnt-bar", ReadOnly: true}, - }, - Ports: []appctypes.Port{ - {Name: *appctypes.MustACName("port-foo"), Protocol: "TCP", Port: 4242}, - {Name: *appctypes.MustACName("port-bar"), Protocol: "TCP", Port: 1234}, - }, - Isolators: []appctypes.Isolator{ - generateCapRetainIsolator(t, "CAP_SYS_CHROOT", "CAP_SYS_BOOT"), - generateCapRevokeIsolator(t, "CAP_SETUID", "CAP_SETGID"), - generateCPUIsolator(t, "5m", "50m"), - generateMemoryIsolator(t, "5M", "50M"), - }, - }, - }, - - // app should be changed. (env, mounts, ports, are overrided). - { - container: &v1.Container{ - Name: "hello-world", - Command: []string{"/bin/hello", "$(env-foo)"}, - Args: []string{"hello", "world", "$(env-bar)"}, - WorkingDir: tmpDir, - Resources: v1.ResourceRequirements{ - Limits: v1.ResourceList{v1.ResourceCPU: resource.MustParse("50m")}, - Requests: v1.ResourceList{v1.ResourceMemory: resource.MustParse("5M")}, - }, - }, - mountPoints: []appctypes.MountPoint{ - {Name: *appctypes.MustACName("mnt-foo"), Path: "/mnt-foo", ReadOnly: true}, - }, - containerPorts: []appctypes.Port{ - {Name: *appctypes.MustACName("port-foo"), Protocol: "TCP", Port: 1234}, - }, - envs: []kubecontainer.EnvVar{ - {Name: "env-foo", Value: "foo"}, - {Name: "env-bar", Value: "bar"}, - }, - ctx: &v1.SecurityContext{ - Capabilities: &v1.Capabilities{ - Add: []v1.Capability{"CAP_SYS_CHROOT", "CAP_SYS_BOOT"}, - Drop: []v1.Capability{"CAP_SETUID", "CAP_SETGID"}, - }, - RunAsUser: &nonRootUser, - RunAsNonRoot: &runAsNonRootTrue, - }, - podCtx: &v1.PodSecurityContext{ - SupplementalGroups: []int64{ - int64(1), - int64(2), - }, - FSGroup: &fsgid, - }, - supplementalGids: []int64{4}, - expect: &appctypes.App{ - Exec: appctypes.Exec{"/bin/hello", "foo", "hello", "world", "bar"}, - User: "42", - Group: "0", - SupplementaryGIDs: []int{1, 2, 3, 4}, - WorkingDirectory: tmpDir, - Environment: []appctypes.EnvironmentVariable{ - {Name: "env-foo", Value: "foo"}, - {Name: "env-bar", Value: "bar"}, - }, - MountPoints: []appctypes.MountPoint{ - {Name: *appctypes.MustACName("mnt-foo"), Path: "/mnt-foo", ReadOnly: true}, - }, - Ports: []appctypes.Port{ - {Name: *appctypes.MustACName("port-foo"), Protocol: "TCP", Port: 1234}, - }, - Isolators: []appctypes.Isolator{ - generateCapRetainIsolator(t, "CAP_SYS_CHROOT", "CAP_SYS_BOOT"), - generateCapRevokeIsolator(t, "CAP_SETUID", "CAP_SETGID"), - generateCPUIsolator(t, "50m", "50m"), - generateMemoryIsolator(t, "5M", "5M"), - }, - }, - }, - } - - for i, tt := range tests { - testCaseHint := fmt.Sprintf("test case #%d", i) - img := baseImageManifest(t) - - err := setApp(img, tt.container, - tt.mountPoints, tt.containerPorts, tt.envs, - tt.ctx, tt.podCtx, tt.supplementalGids) - - if err == nil && tt.err != nil || err != nil && tt.err == nil { - t.Errorf("%s: expect %v, saw %v", testCaseHint, tt.err, err) - } - if err == nil { - sortAppFields(tt.expect) - sortAppFields(img.App) - assert.Equal(t, tt.expect, img.App, testCaseHint) - } - } -} - -func TestGenerateRunCommand(t *testing.T) { - hostName := "test-hostname" - boolTrue := true - boolFalse := false - - tests := []struct { - networkPlugin network.NetworkPlugin - pod *v1.Pod - uuid string - netnsName string - - dnsServers []string - dnsSearches []string - hostName string - err error - - expect string - }{ - // Case #0, returns error. - { - kubenet.NewPlugin("/tmp"), - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-name-foo", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container-foo"}}, - }, - }, - "rkt-uuid-foo", - "default", - []string{}, - []string{}, - "", - fmt.Errorf("failed to get cluster dns"), - "", - }, - // Case #1, returns no dns, with private-net. - { - kubenet.NewPlugin("/tmp"), - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-name-foo", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container-foo"}}, - }, - }, - "rkt-uuid-foo", - "default", - []string{}, - []string{}, - "pod-hostname-foo", - nil, - "/usr/bin/nsenter --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=pod-hostname-foo rkt-uuid-foo", - }, - // Case #2, returns no dns, with host-net. - { - kubenet.NewPlugin("/tmp"), - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-name-foo", - }, - Spec: v1.PodSpec{ - HostNetwork: true, - - Containers: []v1.Container{{Name: "container-foo"}}, - }, - }, - "rkt-uuid-foo", - "", - []string{}, - []string{}, - "", - nil, - fmt.Sprintf("/bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=%s rkt-uuid-foo", hostName), - }, - // Case #3, returns dns, dns searches, with private-net. - { - kubenet.NewPlugin("/tmp"), - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-name-foo", - }, - Spec: v1.PodSpec{ - HostNetwork: false, - - Containers: []v1.Container{{Name: "container-foo"}}, - }, - }, - "rkt-uuid-foo", - "default", - []string{"127.0.0.1"}, - []string{"."}, - "pod-hostname-foo", - nil, - "/usr/bin/nsenter --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --dns=127.0.0.1 --dns-search=. --dns-opt=ndots:5 --hostname=pod-hostname-foo rkt-uuid-foo", - }, - // Case #4, returns no dns, dns searches, with host-network. - { - kubenet.NewPlugin("/tmp"), - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-name-foo", - }, - Spec: v1.PodSpec{ - HostNetwork: true, - - Containers: []v1.Container{{Name: "container-foo"}}, - }, - }, - "rkt-uuid-foo", - "", - []string{"127.0.0.1"}, - []string{"."}, - "pod-hostname-foo", - nil, - fmt.Sprintf("/bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=%s rkt-uuid-foo", hostName), - }, - // Case #5, with no-op plugin, returns --net=rkt.kubernetes.io, with dns and dns search. - { - &network.NoopNetworkPlugin{}, - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-name-foo", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container-foo"}}, - }, - }, - "rkt-uuid-foo", - "default", - []string{"127.0.0.1"}, - []string{"."}, - "pod-hostname-foo", - nil, - "/bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=rkt.kubernetes.io --dns=127.0.0.1 --dns-search=. --dns-opt=ndots:5 --hostname=pod-hostname-foo rkt-uuid-foo", - }, - // Case #6, if all containers are privileged, the result should have 'insecure-options=all-run' - { - kubenet.NewPlugin("/tmp"), - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-name-foo", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - {Name: "container-foo", SecurityContext: &v1.SecurityContext{Privileged: &boolTrue}}, - {Name: "container-bar", SecurityContext: &v1.SecurityContext{Privileged: &boolTrue}}, - }, - }, - }, - "rkt-uuid-foo", - "default", - []string{}, - []string{}, - "pod-hostname-foo", - nil, - "/usr/bin/nsenter --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk,all-run --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=pod-hostname-foo rkt-uuid-foo", - }, - // Case #7, if not all containers are privileged, the result should not have 'insecure-options=all-run' - { - kubenet.NewPlugin("/tmp"), - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-name-foo", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - {Name: "container-foo", SecurityContext: &v1.SecurityContext{Privileged: &boolTrue}}, - {Name: "container-bar", SecurityContext: &v1.SecurityContext{Privileged: &boolFalse}}, - }, - }, - }, - "rkt-uuid-foo", - "default", - []string{}, - []string{}, - "pod-hostname-foo", - nil, - "/usr/bin/nsenter --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=pod-hostname-foo rkt-uuid-foo", - }, - } - - rkt := &Runtime{ - nsenterPath: "/usr/bin/nsenter", - os: &containertesting.FakeOS{HostName: hostName}, - config: &Config{ - Path: "/bin/rkt/rkt", - Stage1Image: "/bin/rkt/stage1-coreos.aci", - Dir: "/var/data", - InsecureOptions: "image,ondisk", - LocalConfigDir: "/var/rkt/local/data", - }, - } - - for i, tt := range tests { - testCaseHint := fmt.Sprintf("test case #%d", i) - rkt.network = network.NewPluginManager(tt.networkPlugin) - rkt.runtimeHelper = &containertesting.FakeRuntimeHelper{ - DNSServers: tt.dnsServers, - DNSSearches: tt.dnsSearches, - HostName: tt.hostName, - Err: tt.err, - } - rkt.execer = &fakeexec.FakeExec{CommandScript: []fakeexec.FakeCommandAction{func(cmd string, args ...string) exec.Cmd { - return fakeexec.InitFakeCmd(&fakeexec.FakeCmd{}, cmd, args...) - }}} - - // a command should be created of this form, but the returned command shouldn't be called (asserted by having no expectations on it) - - result, err := rkt.generateRunCommand(tt.pod, tt.uuid, tt.netnsName) - assert.Equal(t, tt.err, err, testCaseHint) - assert.Equal(t, tt.expect, result, testCaseHint) - } -} - -func TestLifeCycleHooks(t *testing.T) { - runner := lifecycle.NewFakeHandlerRunner() - fr := newFakeRktInterface() - fs := newFakeSystemd() - - rkt := &Runtime{ - runner: runner, - apisvc: fr, - systemd: fs, - containerRefManager: kubecontainer.NewRefManager(), - } - - tests := []struct { - pod *v1.Pod - runtimePod *kubecontainer.Pod - postStartRuns []string - preStopRuns []string - err error - }{ - { - // Case 0, container without any hooks. - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-1", - Namespace: "ns-1", - UID: "uid-1", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - {Name: "container-name-1"}, - }, - }, - }, - &kubecontainer.Pod{ - Containers: []*kubecontainer.Container{ - {ID: kubecontainer.BuildContainerID("rkt", "id-1")}, - }, - }, - []string{}, - []string{}, - nil, - }, - { - // Case 1, containers with post-start and pre-stop hooks. - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-1", - Namespace: "ns-1", - UID: "uid-1", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "container-name-1", - Lifecycle: &v1.Lifecycle{ - PostStart: &v1.Handler{ - Exec: &v1.ExecAction{}, - }, - }, - }, - { - Name: "container-name-2", - Lifecycle: &v1.Lifecycle{ - PostStart: &v1.Handler{ - HTTPGet: &v1.HTTPGetAction{}, - }, - }, - }, - { - Name: "container-name-3", - Lifecycle: &v1.Lifecycle{ - PreStop: &v1.Handler{ - Exec: &v1.ExecAction{}, - }, - }, - }, - { - Name: "container-name-4", - Lifecycle: &v1.Lifecycle{ - PreStop: &v1.Handler{ - HTTPGet: &v1.HTTPGetAction{}, - }, - }, - }, - }, - }, - }, - &kubecontainer.Pod{ - Containers: []*kubecontainer.Container{ - { - ID: kubecontainer.ParseContainerID("rkt://uuid:container-name-4"), - Name: "container-name-4", - }, - { - ID: kubecontainer.ParseContainerID("rkt://uuid:container-name-3"), - Name: "container-name-3", - }, - { - ID: kubecontainer.ParseContainerID("rkt://uuid:container-name-2"), - Name: "container-name-2", - }, - { - ID: kubecontainer.ParseContainerID("rkt://uuid:container-name-1"), - Name: "container-name-1", - }, - }, - }, - []string{ - "exec on pod: pod-1_ns-1(uid-1), container: container-name-1: rkt://uuid:container-name-1", - "http-get on pod: pod-1_ns-1(uid-1), container: container-name-2: rkt://uuid:container-name-2", - }, - []string{ - "exec on pod: pod-1_ns-1(uid-1), container: container-name-3: rkt://uuid:container-name-3", - "http-get on pod: pod-1_ns-1(uid-1), container: container-name-4: rkt://uuid:container-name-4", - }, - nil, - }, - { - // Case 2, one container with invalid hooks. - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-1", - Namespace: "ns-1", - UID: "uid-1", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "container-name-1", - Lifecycle: &v1.Lifecycle{ - PostStart: &v1.Handler{}, - PreStop: &v1.Handler{}, - }, - }, - }, - }, - }, - &kubecontainer.Pod{ - Containers: []*kubecontainer.Container{ - { - ID: kubecontainer.ParseContainerID("rkt://uuid:container-name-1"), - Name: "container-name-1", - }, - }, - }, - []string{}, - []string{}, - errors.NewAggregate([]error{fmt.Errorf("Invalid handler: %v", &v1.Handler{})}), - }, - } - - for i, tt := range tests { - testCaseHint := fmt.Sprintf("test case #%d", i) - - pod := &rktapi.Pod{Id: "uuid"} - for _, c := range tt.runtimePod.Containers { - pod.Apps = append(pod.Apps, &rktapi.App{ - Name: c.Name, - State: rktapi.AppState_APP_STATE_RUNNING, - }) - } - fr.pods = []*rktapi.Pod{pod} - - // Run post-start hooks - err := rkt.runLifecycleHooks(tt.pod, tt.runtimePod, lifecyclePostStartHook) - assert.Equal(t, tt.err, err, testCaseHint) - - sort.Sort(sortedStringList(tt.postStartRuns)) - sort.Sort(sortedStringList(runner.HandlerRuns)) - - assert.Equal(t, tt.postStartRuns, runner.HandlerRuns, testCaseHint) - - runner.Reset() - - // Run pre-stop hooks. - err = rkt.runLifecycleHooks(tt.pod, tt.runtimePod, lifecyclePreStopHook) - assert.Equal(t, tt.err, err, testCaseHint) - - sort.Sort(sortedStringList(tt.preStopRuns)) - sort.Sort(sortedStringList(runner.HandlerRuns)) - - assert.Equal(t, tt.preStopRuns, runner.HandlerRuns, testCaseHint) - - runner.Reset() - } -} - -func TestImageStats(t *testing.T) { - fr := newFakeRktInterface() - rkt := &Runtime{apisvc: fr} - - fr.images = []*rktapi.Image{ - {Size: 100}, - {Size: 200}, - {Size: 300}, - } - - result, err := rkt.ImageStats() - assert.NoError(t, err) - assert.Equal(t, result, &kubecontainer.ImageStats{TotalStorageBytes: 600}) -} - -func TestGarbageCollect(t *testing.T) { - fr := newFakeRktInterface() - fs := newFakeSystemd() - cli := newFakeRktCli() - fakeOS := containertesting.NewFakeOS() - deletionProvider := newFakePodDeletionProvider() - fug := newfakeUnitGetter() - frh := &containertesting.FakeRuntimeHelper{} - - rkt := &Runtime{ - os: fakeOS, - cli: cli, - apisvc: fr, - podDeletionProvider: deletionProvider, - systemd: fs, - containerRefManager: kubecontainer.NewRefManager(), - unitGetter: fug, - runtimeHelper: frh, - } - - fakeApp := &rktapi.App{Name: "app-foo"} - - tests := []struct { - gcPolicy kubecontainer.ContainerGCPolicy - apiPods []*v1.Pod - pods []*rktapi.Pod - serviceFilesOnDisk []string - expectedCommands []string - expectedDeletedFiles []string - }{ - // All running pods, should not be gc'd. - // Dead, new pods should not be gc'd. - // Dead, old pods should be gc'd. - // Deleted pods should be gc'd. - // Service files without corresponded pods should be removed. - { - kubecontainer.ContainerGCPolicy{ - MinAge: 0, - MaxContainers: 0, - }, - []*v1.Pod{ - {ObjectMeta: metav1.ObjectMeta{UID: "pod-uid-1"}}, - {ObjectMeta: metav1.ObjectMeta{UID: "pod-uid-2"}}, - {ObjectMeta: metav1.ObjectMeta{UID: "pod-uid-3"}}, - {ObjectMeta: metav1.ObjectMeta{UID: "pod-uid-4"}}, - }, - []*rktapi.Pod{ - { - Id: "deleted-foo", - State: rktapi.PodState_POD_STATE_EXITED, - CreatedAt: time.Now().Add(time.Hour).UnixNano(), - StartedAt: time.Now().Add(time.Hour).UnixNano(), - Apps: []*rktapi.App{fakeApp}, - Annotations: []*rktapi.KeyValue{ - { - Key: types.KubernetesPodUIDLabel, - Value: "pod-uid-0", - }, - }, - }, - { - Id: "running-foo", - State: rktapi.PodState_POD_STATE_RUNNING, - CreatedAt: 0, - StartedAt: 0, - Apps: []*rktapi.App{fakeApp}, - Annotations: []*rktapi.KeyValue{ - { - Key: types.KubernetesPodUIDLabel, - Value: "pod-uid-1", - }, - }, - }, - { - Id: "running-bar", - State: rktapi.PodState_POD_STATE_RUNNING, - CreatedAt: 0, - StartedAt: 0, - Apps: []*rktapi.App{fakeApp}, - Annotations: []*rktapi.KeyValue{ - { - Key: types.KubernetesPodUIDLabel, - Value: "pod-uid-2", - }, - }, - }, - { - Id: "dead-old", - State: rktapi.PodState_POD_STATE_EXITED, - CreatedAt: 0, - StartedAt: 0, - Apps: []*rktapi.App{fakeApp}, - Annotations: []*rktapi.KeyValue{ - { - Key: types.KubernetesPodUIDLabel, - Value: "pod-uid-3", - }, - }, - }, - { - Id: "dead-new", - State: rktapi.PodState_POD_STATE_EXITED, - CreatedAt: time.Now().Add(time.Hour).UnixNano(), - StartedAt: time.Now().Add(time.Hour).UnixNano(), - Apps: []*rktapi.App{fakeApp}, - Annotations: []*rktapi.KeyValue{ - { - Key: types.KubernetesPodUIDLabel, - Value: "pod-uid-4", - }, - }, - }, - }, - []string{"k8s_dead-old.service", "k8s_deleted-foo.service", "k8s_non-existing-bar.service"}, - []string{"rkt rm dead-old", "rkt rm deleted-foo"}, - []string{"/poddir/fake/finished-dead-old", "/poddir/fake/finished-deleted-foo", "/poddir/fake/finished-non-existing-bar", "/run/systemd/system/k8s_dead-old.service", "/run/systemd/system/k8s_deleted-foo.service", "/run/systemd/system/k8s_non-existing-bar.service"}, - }, - // gcPolicy.MaxContainers should be enforced. - // Oldest ones are removed first. - { - kubecontainer.ContainerGCPolicy{ - MinAge: 0, - MaxContainers: 1, - }, - []*v1.Pod{ - {ObjectMeta: metav1.ObjectMeta{UID: "pod-uid-0"}}, - {ObjectMeta: metav1.ObjectMeta{UID: "pod-uid-1"}}, - {ObjectMeta: metav1.ObjectMeta{UID: "pod-uid-2"}}, - }, - []*rktapi.Pod{ - { - Id: "dead-2", - State: rktapi.PodState_POD_STATE_EXITED, - CreatedAt: 2, - StartedAt: 2, - Apps: []*rktapi.App{fakeApp}, - Annotations: []*rktapi.KeyValue{ - { - Key: types.KubernetesPodUIDLabel, - Value: "pod-uid-2", - }, - }, - }, - { - Id: "dead-1", - State: rktapi.PodState_POD_STATE_EXITED, - CreatedAt: 1, - StartedAt: 1, - Apps: []*rktapi.App{fakeApp}, - Annotations: []*rktapi.KeyValue{ - { - Key: types.KubernetesPodUIDLabel, - Value: "pod-uid-1", - }, - }, - }, - { - Id: "dead-0", - State: rktapi.PodState_POD_STATE_EXITED, - CreatedAt: 0, - StartedAt: 0, - Apps: []*rktapi.App{fakeApp}, - Annotations: []*rktapi.KeyValue{ - { - Key: types.KubernetesPodUIDLabel, - Value: "pod-uid-0", - }, - }, - }, - }, - []string{"k8s_dead-0.service", "k8s_dead-1.service", "k8s_dead-2.service"}, - []string{"rkt rm dead-0", "rkt rm dead-1"}, - []string{"/poddir/fake/finished-dead-0", "/poddir/fake/finished-dead-1", "/run/systemd/system/k8s_dead-0.service", "/run/systemd/system/k8s_dead-1.service"}, - }, - } - - for i, tt := range tests { - testCaseHint := fmt.Sprintf("test case #%d", i) - - ctrl := gomock.NewController(t) - - fakeOS.ReadDirFn = func(dirname string) ([]os.FileInfo, error) { - serviceFileNames := tt.serviceFilesOnDisk - var fileInfos []os.FileInfo - - for _, name := range serviceFileNames { - mockFI := containertesting.NewMockFileInfo(ctrl) - // we need to specify two calls - // first: get all systemd units - // second: filter only the files with a k8s_ prefix - mockFI.EXPECT().Name().Return(name) - mockFI.EXPECT().Name().Return(name) - fileInfos = append(fileInfos, mockFI) - } - return fileInfos, nil - } - - fr.pods = tt.pods - for _, p := range tt.apiPods { - deletionProvider.pods[p.UID] = struct{}{} - } - - allSourcesReady := true - evictNonDeletedPods := false - err := rkt.GarbageCollect(tt.gcPolicy, allSourcesReady, evictNonDeletedPods) - assert.NoError(t, err, testCaseHint) - - sort.Sort(sortedStringList(tt.expectedCommands)) - sort.Sort(sortedStringList(cli.cmds)) - - assert.Equal(t, tt.expectedCommands, cli.cmds, testCaseHint) - - sort.Sort(sortedStringList(tt.expectedDeletedFiles)) - sort.Sort(sortedStringList(fakeOS.Removes)) - sort.Sort(sortedStringList(fs.resetFailedUnits)) - - assert.Equal(t, tt.expectedDeletedFiles, fakeOS.Removes, testCaseHint) - var expectedService []string - for _, f := range tt.expectedDeletedFiles { - unit := filepath.Base(f) - if strings.HasSuffix(unit, ".service") && strings.HasPrefix(unit, kubernetesUnitPrefix) { - expectedService = append(expectedService, unit) - } - } - assert.Equal(t, expectedService, fs.resetFailedUnits, testCaseHint) - - // Cleanup after each test. - cli.Reset() - ctrl.Finish() - fakeOS.Removes = []string{} - fs.resetFailedUnits = []string{} - deletionProvider.pods = make(map[kubetypes.UID]struct{}) - } -} - -type annotationsByName []appctypes.Annotation - -func (a annotationsByName) Len() int { return len(a) } -func (a annotationsByName) Less(x, y int) bool { return a[x].Name < a[y].Name } -func (a annotationsByName) Swap(x, y int) { a[x], a[y] = a[y], a[x] } - -func TestMakePodManifestAnnotations(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - fr := newFakeRktInterface() - fs := newFakeSystemd() - r := &Runtime{apisvc: fr, systemd: fs} - - testCases := []struct { - in *v1.Pod - out *appcschema.PodManifest - outerr error - }{ - { - in: &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - UID: "uid-1", - Name: "name-1", - Namespace: "namespace-1", - Annotations: map[string]string{ - k8sRktStage1NameAnno: "stage1-override-img", - }, - }, - }, - out: &appcschema.PodManifest{ - Annotations: []appctypes.Annotation{ - { - Name: "io.kubernetes.container.name", - Value: "POD", - }, - { - Name: appctypes.ACIdentifier(k8sRktStage1NameAnno), - Value: "stage1-override-img", - }, - { - Name: appctypes.ACIdentifier(types.KubernetesPodUIDLabel), - Value: "uid-1", - }, - { - Name: appctypes.ACIdentifier(types.KubernetesPodNameLabel), - Value: "name-1", - }, - { - Name: appctypes.ACIdentifier(k8sRktKubeletAnno), - Value: "true", - }, - { - Name: appctypes.ACIdentifier(types.KubernetesPodNamespaceLabel), - Value: "namespace-1", - }, - { - Name: appctypes.ACIdentifier(k8sRktRestartCountAnno), - Value: "0", - }, - }, - }, - }, - } - - for i, testCase := range testCases { - hint := fmt.Sprintf("case #%d", i) - - result, err := r.makePodManifest(testCase.in, "", []v1.Secret{}) - assert.Equal(t, testCase.outerr, err, hint) - if err == nil { - sort.Sort(annotationsByName(result.Annotations)) - sort.Sort(annotationsByName(testCase.out.Annotations)) - assert.Equal(t, testCase.out.Annotations, result.Annotations, hint) - } - } -} - -func TestPreparePodArgs(t *testing.T) { - r := &Runtime{ - config: &Config{}, - } - - testCases := []struct { - manifest appcschema.PodManifest - stage1Config string - cmd []string - }{ - { - appcschema.PodManifest{ - Annotations: appctypes.Annotations{ - { - Name: k8sRktStage1NameAnno, - Value: "stage1-image", - }, - }, - }, - "", - []string{"prepare", "--quiet", "--pod-manifest", "file", "--stage1-name=stage1-image"}, - }, - { - appcschema.PodManifest{ - Annotations: appctypes.Annotations{ - { - Name: k8sRktStage1NameAnno, - Value: "stage1-image", - }, - }, - }, - "stage1-image0", - []string{"prepare", "--quiet", "--pod-manifest", "file", "--stage1-name=stage1-image"}, - }, - { - appcschema.PodManifest{ - Annotations: appctypes.Annotations{}, - }, - "stage1-image0", - []string{"prepare", "--quiet", "--pod-manifest", "file", "--stage1-name=stage1-image0"}, - }, - { - appcschema.PodManifest{ - Annotations: appctypes.Annotations{}, - }, - "", - []string{"prepare", "--quiet", "--pod-manifest", "file"}, - }, - } - - for i, testCase := range testCases { - r.config.Stage1Image = testCase.stage1Config - cmd := r.preparePodArgs(&testCase.manifest, "file") - assert.Equal(t, testCase.cmd, cmd, fmt.Sprintf("Test case #%d", i)) - } -} - -func TestConstructSyslogIdentifier(t *testing.T) { - testCases := []struct { - podName string - podGenerateName string - identifier string - }{ - { - "prometheus-node-exporter-rv90m", - "prometheus-node-exporter-", - "prometheus-node-exporter", - }, - { - "simplepod", - "", - "simplepod", - }, - { - "p", - "", - "p", - }, - } - for i, testCase := range testCases { - identifier := constructSyslogIdentifier(testCase.podGenerateName, testCase.podName) - assert.Equal(t, testCase.identifier, identifier, fmt.Sprintf("Test case #%d", i)) - } -} - -func TestGetPodSystemdServiceFiles(t *testing.T) { - fs := containertesting.NewFakeOS() - r := &Runtime{os: fs} - - testCases := []struct { - serviceFilesOnDisk []string - expected []string - }{ - { - []string{"one.service", "two.service", "k8s_513ce947-8f6e-4d27-8c03-99f97b78d680.service", "k8s_184482df-8630-4d41-b84f-302684871758.service", "k8s_f4a244d8-5ec2-4f59-b7dd-c9e130d6e7a3.service", "k8s_f5aad446-5598-488f-93a4-5a27e03e7fcb.service"}, - []string{"k8s_513ce947-8f6e-4d27-8c03-99f97b78d680.service", "k8s_184482df-8630-4d41-b84f-302684871758.service", "k8s_f4a244d8-5ec2-4f59-b7dd-c9e130d6e7a3.service", "k8s_f5aad446-5598-488f-93a4-5a27e03e7fcb.service"}, - }, - { - []string{"one.service", "two.service"}, - []string{}, - }, - { - []string{"one.service", "k8s_513ce947-8f6e-4d27-8c03-99f97b78d680.service"}, - []string{"k8s_513ce947-8f6e-4d27-8c03-99f97b78d680.service"}, - }, - } - for i, tt := range testCases { - ctrl := gomock.NewController(t) - - fs.ReadDirFn = func(dirname string) ([]os.FileInfo, error) { - serviceFileNames := tt.serviceFilesOnDisk - var fileInfos []os.FileInfo - - for _, name := range serviceFileNames { - mockFI := containertesting.NewMockFileInfo(ctrl) - // we need to specify two calls - // first: get all systemd units - // second: filter only the files with a k8s_ prefix - mockFI.EXPECT().Name().Return(name) - mockFI.EXPECT().Name().Return(name) - fileInfos = append(fileInfos, mockFI) - } - return fileInfos, nil - } - serviceFiles, err := r.getPodSystemdServiceFiles() - if err != nil { - t.Errorf("%v", err) - } - for _, f := range serviceFiles { - assert.Contains(t, tt.expected, f.Name(), fmt.Sprintf("Test case #%d", i)) - - } - } -} - -func TestSetupSystemdCustomFields(t *testing.T) { - testCases := []struct { - unitOpts []*unit.UnitOption - podAnnotations map[string]string - expectedValues []string - raiseErr bool - }{ - // without annotation - { - []*unit.UnitOption{ - {Section: "Service", Name: "ExecStart", Value: "/bin/true"}, - }, - map[string]string{}, - []string{"/bin/true"}, - false, - }, - // with valid annotation for LimitNOFile - { - []*unit.UnitOption{ - {Section: "Service", Name: "ExecStart", Value: "/bin/true"}, - }, - map[string]string{k8sRktLimitNoFileAnno: "1024"}, - []string{"/bin/true", "1024"}, - false, - }, - // with invalid annotation for LimitNOFile - { - []*unit.UnitOption{ - {Section: "Service", Name: "ExecStart", Value: "/bin/true"}, - }, - map[string]string{k8sRktLimitNoFileAnno: "-1"}, - []string{"/bin/true"}, - true, - }, - } - - for i, tt := range testCases { - raiseErr := false - newUnitsOpts, err := setupSystemdCustomFields(tt.podAnnotations, tt.unitOpts) - if err != nil { - raiseErr = true - } - assert.Equal(t, tt.raiseErr, raiseErr, fmt.Sprintf("Test case #%d", i)) - for _, opt := range newUnitsOpts { - assert.Equal(t, "Service", opt.Section, fmt.Sprintf("Test case #%d", i)) - assert.Contains(t, tt.expectedValues, opt.Value, fmt.Sprintf("Test case #%d", i)) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/systemd.go b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/systemd.go deleted file mode 100644 index 73768e5ea..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/systemd.go +++ /dev/null @@ -1,92 +0,0 @@ -/* -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 rkt - -import ( - "fmt" - "strconv" - "strings" - - "github.com/coreos/go-systemd/dbus" -) - -// systemdVersion is a type wraps the int to implement kubecontainer.Version interface. -type systemdVersion int - -func (s systemdVersion) String() string { - return fmt.Sprintf("%d", s) -} - -func (s systemdVersion) Compare(other string) (int, error) { - v, err := strconv.Atoi(other) - if err != nil { - return -1, err - } - if int(s) < v { - return -1, nil - } else if int(s) > v { - return 1, nil - } - return 0, nil -} - -// systemdInterface is an abstraction of the go-systemd/dbus to make -// it mockable for testing. -// TODO(yifan): Eventually we should move these functionalities to: -// 1. a package for launching/stopping rkt pods. -// 2. rkt api-service interface for listing pods. -// See https://github.com/coreos/rkt/issues/1769. -type systemdInterface interface { - // Version returns the version of the systemd. - Version() (systemdVersion, error) - // ListUnits lists all the loaded units. - ListUnits() ([]dbus.UnitStatus, error) - // StopUnits stops the unit with the given name. - StopUnit(name string, mode string, ch chan<- string) (int, error) - // RestartUnit restarts the unit with the given name. - RestartUnit(name string, mode string, ch chan<- string) (int, error) - // ResetFailedUnit resets the "failed" state of a specific unit. - ResetFailedUnit(name string) error -} - -// systemd implements the systemdInterface using dbus and systemctl. -// All the functions other then Version() are already implemented by go-systemd/dbus. -type systemd struct { - *dbus.Conn -} - -// newSystemd creates a systemd object that implements systemdInterface. -func newSystemd() (*systemd, error) { - dbusConn, err := dbus.New() - if err != nil { - return nil, err - } - return &systemd{dbusConn}, nil -} - -// Version returns the version of the systemd. -func (s *systemd) Version() (systemdVersion, error) { - versionStr, err := s.Conn.GetManagerProperty("Version") - if err != nil { - return -1, err - } - result, err := strconv.Atoi(strings.Trim(versionStr, "\"")) - if err != nil { - return -1, err - } - return systemdVersion(result), nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/version.go b/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/version.go deleted file mode 100644 index 3609bf97b..000000000 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/rkt/version.go +++ /dev/null @@ -1,111 +0,0 @@ -/* -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 rkt - -import ( - "fmt" - "sync" - - rktapi "github.com/coreos/rkt/api/v1alpha" - "golang.org/x/net/context" - - utilversion "k8s.io/kubernetes/pkg/util/version" -) - -type versions struct { - sync.RWMutex - binVersion *utilversion.Version - apiVersion *utilversion.Version - systemdVersion systemdVersion -} - -func newRktVersion(version string) (*utilversion.Version, error) { - return utilversion.ParseSemantic(version) -} - -func (r *Runtime) getVersions() error { - r.versions.Lock() - defer r.versions.Unlock() - - // Get systemd version. - var err error - r.versions.systemdVersion, err = r.systemd.Version() - if err != nil { - return err - } - - ctx, cancel := context.WithTimeout(context.Background(), r.requestTimeout) - defer cancel() - // Example for the version strings returned by GetInfo(): - // RktVersion:"0.10.0+gitb7349b1" AppcVersion:"0.7.1" ApiVersion:"1.0.0-alpha" - resp, err := r.apisvc.GetInfo(ctx, &rktapi.GetInfoRequest{}) - if err != nil { - return err - } - - // Get rkt binary version. - r.versions.binVersion, err = newRktVersion(resp.Info.RktVersion) - if err != nil { - return err - } - - // Get rkt API version. - r.versions.apiVersion, err = newRktVersion(resp.Info.ApiVersion) - if err != nil { - return err - } - return nil -} - -// checkVersion tests whether the rkt/systemd/rkt-api-service that meet the version requirement. -// If all version requirements are met, it returns nil. -func (r *Runtime) checkVersion(minimumRktBinVersion, minimumRktApiVersion, minimumSystemdVersion string) error { - if err := r.getVersions(); err != nil { - return err - } - - r.versions.RLock() - defer r.versions.RUnlock() - - // Check systemd version. - result, err := r.versions.systemdVersion.Compare(minimumSystemdVersion) - if err != nil { - return err - } - if result < 0 { - return fmt.Errorf("rkt: systemd version(%v) is too old, requires at least %v", r.versions.systemdVersion, minimumSystemdVersion) - } - - // Check rkt binary version. - result, err = r.versions.binVersion.Compare(minimumRktBinVersion) - if err != nil { - return err - } - if result < 0 { - return fmt.Errorf("rkt: binary version is too old(%v), requires at least %v", r.versions.binVersion, minimumRktBinVersion) - } - - // Check rkt API version. - result, err = r.versions.apiVersion.Compare(minimumRktApiVersion) - if err != nil { - return err - } - if result < 0 { - return fmt.Errorf("rkt: API version is too old(%v), requires at least %v", r.versions.apiVersion, minimumRktApiVersion) - } - return nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/runonce.go b/vendor/k8s.io/kubernetes/pkg/kubelet/runonce.go index 82a73d512..294580e7a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/runonce.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/runonce.go @@ -91,8 +91,12 @@ func (kl *Kubelet) runOnce(pods []*v1.Pod, retryDelay time.Duration) (results [] res := <-ch results = append(results, res) if res.Err != nil { - // TODO(proppy): report which containers failed the pod. - glog.Infof("failed to start pod %q: %v", format.Pod(res.Pod), res.Err) + faliedContainerName, err := kl.getFailedContainers(res.Pod) + if err != nil { + glog.Infof("unable to get failed containers' names for pod %q, error:%v", format.Pod(res.Pod), err) + } else { + glog.Infof("unable to start pod %q because container:%v failed", format.Pod(res.Pod), faliedContainerName) + } failedPods = append(failedPods, format.Pod(res.Pod)) } else { glog.Infof("started pod %q", format.Pod(res.Pod)) @@ -156,3 +160,18 @@ func (kl *Kubelet) isPodRunning(pod *v1.Pod, status *kubecontainer.PodStatus) bo } return true } + +// getFailedContainer returns failed container name for pod. +func (kl *Kubelet) getFailedContainers(pod *v1.Pod) ([]string, error) { + status, err := kl.containerRuntime.GetPodStatus(pod.UID, pod.Name, pod.Namespace) + if err != nil { + return nil, fmt.Errorf("unable to get status for pod %q: %v", format.Pod(pod), err) + } + var containerNames []string + for _, cs := range status.ContainerStatuses { + if cs.State != kubecontainer.ContainerStateRunning && cs.ExitCode != 0 { + containerNames = append(containerNames, cs.Name) + } + } + return containerNames, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/runonce_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/runonce_test.go index c9f01a744..6047d664b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/runonce_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/runonce_test.go @@ -30,15 +30,12 @@ import ( "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/tools/record" utiltesting "k8s.io/client-go/util/testing" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing" "k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/pkg/kubelet/configmap" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" "k8s.io/kubernetes/pkg/kubelet/eviction" - "k8s.io/kubernetes/pkg/kubelet/network" - nettest "k8s.io/kubernetes/pkg/kubelet/network/testing" kubepod "k8s.io/kubernetes/pkg/kubelet/pod" podtest "k8s.io/kubernetes/pkg/kubelet/pod/testing" "k8s.io/kubernetes/pkg/kubelet/secret" @@ -66,7 +63,7 @@ func TestRunOnce(t *testing.T) { fakeSecretManager := secret.NewFakeManager() fakeConfigMapManager := configmap.NewFakeManager() podManager := kubepod.NewBasicPodManager( - podtest.NewFakeMirrorClient(), fakeSecretManager, fakeConfigMapManager) + podtest.NewFakeMirrorClient(), fakeSecretManager, fakeConfigMapManager, podtest.NewMockCheckpointManager()) fakeRuntime := &containertest.FakeRuntime{} basePath, err := utiltesting.MkTmpdir("kubelet") if err != nil { @@ -93,7 +90,7 @@ func TestRunOnce(t *testing.T) { plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil} kb.volumePluginMgr, err = - NewInitializedVolumePluginMgr(kb, fakeSecretManager, fakeConfigMapManager, []volume.VolumePlugin{plug}, nil /* prober */) + NewInitializedVolumePluginMgr(kb, fakeSecretManager, fakeConfigMapManager, nil, []volume.VolumePlugin{plug}, nil /* prober */) if err != nil { t.Fatalf("failed to initialize VolumePluginMgr: %v", err) } @@ -111,7 +108,6 @@ func TestRunOnce(t *testing.T) { false, /* experimentalCheckNodeCapabilitiesBeforeMount */ false /* keepTerminatedPodVolumes */) - kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", nettest.NewFakeHost(nil), kubeletconfig.HairpinNone, "", network.UseDefaultMTU) // TODO: Factor out "StatsProvider" from Kubelet so we don't have a cyclic dependency volumeStatsAggPeriod := time.Second * 10 kb.resourceAnalyzer = stats.NewResourceAnalyzer(kb, volumeStatsAggPeriod) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/secret/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/secret/BUILD index 1fdb5850c..4b39334d0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/secret/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/secret/BUILD @@ -11,14 +11,13 @@ go_test( srcs = ["secret_manager_test.go"], embed = [":go_default_library"], deps = [ - "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//pkg/kubelet/util/manager:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", ], ) @@ -31,13 +30,12 @@ go_library( importpath = "k8s.io/kubernetes/pkg/kubelet/secret", deps = [ "//pkg/api/v1/pod:go_default_library", - "//pkg/kubelet/util:go_default_library", + "//pkg/kubelet/util/manager:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apiserver/pkg/storage/etcd:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager.go index 3de230a90..a33969413 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager.go @@ -18,26 +18,19 @@ package secret import ( "fmt" - "strconv" - "sync" "time" "k8s.io/api/core/v1" - storageetcd "k8s.io/apiserver/pkg/storage/etcd" clientset "k8s.io/client-go/kubernetes" podutil "k8s.io/kubernetes/pkg/api/v1/pod" - "k8s.io/kubernetes/pkg/kubelet/util" + "k8s.io/kubernetes/pkg/kubelet/util/manager" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/clock" "k8s.io/apimachinery/pkg/util/sets" ) -const ( - defaultTTL = time.Minute -) - type Manager interface { // Get secret by secret namespace and name. GetSecret(namespace, name string) (*v1.Secret, error) @@ -73,191 +66,31 @@ func (s *simpleSecretManager) RegisterPod(pod *v1.Pod) { func (s *simpleSecretManager) UnregisterPod(pod *v1.Pod) { } -type GetObjectTTLFunc func() (time.Duration, bool) - -type objectKey struct { - namespace string - name string -} - -// secretStoreItems is a single item stored in secretStore. -type secretStoreItem struct { - refCount int - secret *secretData -} - -type secretData struct { - sync.Mutex - - secret *v1.Secret - err error - lastUpdateTime time.Time -} - -// secretStore is a local cache of secrets. -type secretStore struct { - kubeClient clientset.Interface - clock clock.Clock - - lock sync.Mutex - items map[objectKey]*secretStoreItem - - defaultTTL time.Duration - getTTL GetObjectTTLFunc +// secretManager keeps a store with secrets necessary +// for registered pods. Different implementations of the store +// may result in different semantics for freshness of secrets +// (e.g. ttl-based implementation vs watch-based implementation). +type secretManager struct { + manager manager.Manager } -func newSecretStore(kubeClient clientset.Interface, clock clock.Clock, getTTL GetObjectTTLFunc, ttl time.Duration) *secretStore { - return &secretStore{ - kubeClient: kubeClient, - clock: clock, - items: make(map[objectKey]*secretStoreItem), - defaultTTL: ttl, - getTTL: getTTL, +func (s *secretManager) GetSecret(namespace, name string) (*v1.Secret, error) { + object, err := s.manager.GetObject(namespace, name) + if err != nil { + return nil, err } -} - -func isSecretOlder(newSecret, oldSecret *v1.Secret) bool { - if newSecret == nil || oldSecret == nil { - return false - } - newVersion, _ := storageetcd.Versioner.ObjectResourceVersion(newSecret) - oldVersion, _ := storageetcd.Versioner.ObjectResourceVersion(oldSecret) - return newVersion < oldVersion -} - -func (s *secretStore) Add(namespace, name string) { - key := objectKey{namespace: namespace, name: name} - - // Add is called from RegisterPod, thus it needs to be efficient. - // Thus Add() is only increasing refCount and generation of a given secret. - // Then Get() is responsible for fetching if needed. - s.lock.Lock() - defer s.lock.Unlock() - item, exists := s.items[key] - if !exists { - item = &secretStoreItem{ - refCount: 0, - secret: &secretData{}, - } - s.items[key] = item - } - - item.refCount++ - // This will trigger fetch on the next Get() operation. - item.secret = nil -} - -func (s *secretStore) Delete(namespace, name string) { - key := objectKey{namespace: namespace, name: name} - - s.lock.Lock() - defer s.lock.Unlock() - if item, ok := s.items[key]; ok { - item.refCount-- - if item.refCount == 0 { - delete(s.items, key) - } + if secret, ok := object.(*v1.Secret); ok { + return secret, nil } + return nil, fmt.Errorf("unexpected object type: %v", object) } -func GetObjectTTLFromNodeFunc(getNode func() (*v1.Node, error)) GetObjectTTLFunc { - return func() (time.Duration, bool) { - node, err := getNode() - if err != nil { - return time.Duration(0), false - } - if node != nil && node.Annotations != nil { - if value, ok := node.Annotations[v1.ObjectTTLAnnotationKey]; ok { - if intValue, err := strconv.Atoi(value); err == nil { - return time.Duration(intValue) * time.Second, true - } - } - } - return time.Duration(0), false - } +func (s *secretManager) RegisterPod(pod *v1.Pod) { + s.manager.RegisterPod(pod) } -func (s *secretStore) isSecretFresh(data *secretData) bool { - secretTTL := s.defaultTTL - if ttl, ok := s.getTTL(); ok { - secretTTL = ttl - } - return s.clock.Now().Before(data.lastUpdateTime.Add(secretTTL)) -} - -func (s *secretStore) Get(namespace, name string) (*v1.Secret, error) { - key := objectKey{namespace: namespace, name: name} - - data := func() *secretData { - s.lock.Lock() - defer s.lock.Unlock() - item, exists := s.items[key] - if !exists { - return nil - } - if item.secret == nil { - item.secret = &secretData{} - } - return item.secret - }() - if data == nil { - return nil, fmt.Errorf("secret %q/%q not registered", namespace, name) - } - - // After updating data in secretStore, lock the data, fetch secret if - // needed and return data. - data.Lock() - defer data.Unlock() - if data.err != nil || !s.isSecretFresh(data) { - opts := metav1.GetOptions{} - if data.secret != nil && data.err == nil { - // This is just a periodic refresh of a secret we successfully fetched previously. - // In this case, server data from apiserver cache to reduce the load on both - // etcd and apiserver (the cache is eventually consistent). - util.FromApiserverCache(&opts) - } - secret, err := s.kubeClient.CoreV1().Secrets(namespace).Get(name, opts) - if err != nil && !apierrors.IsNotFound(err) && data.secret == nil && data.err == nil { - // Couldn't fetch the latest secret, but there is no cached data to return. - // Return the fetch result instead. - return secret, err - } - if (err == nil && !isSecretOlder(secret, data.secret)) || apierrors.IsNotFound(err) { - // If the fetch succeeded with a newer version of the secret, or if the - // secret could not be found in the apiserver, update the cached data to - // reflect the current status. - data.secret = secret - data.err = err - data.lastUpdateTime = s.clock.Now() - } - } - return data.secret, data.err -} - -// cachingSecretManager keeps a cache of all secrets necessary for registered pods. -// It implements the following logic: -// - whenever a pod is created or updated, the cached versions of all its secrets -// are invalidated -// - every GetSecret() call tries to fetch the value from local cache; if it is -// not there, invalidated or too old, we fetch it from apiserver and refresh the -// value in cache; otherwise it is just fetched from cache -type cachingSecretManager struct { - secretStore *secretStore - - lock sync.Mutex - registeredPods map[objectKey]*v1.Pod -} - -func NewCachingSecretManager(kubeClient clientset.Interface, getTTL GetObjectTTLFunc) Manager { - csm := &cachingSecretManager{ - secretStore: newSecretStore(kubeClient, clock.RealClock{}, getTTL, defaultTTL), - registeredPods: make(map[objectKey]*v1.Pod), - } - return csm -} - -func (c *cachingSecretManager) GetSecret(namespace, name string) (*v1.Secret, error) { - return c.secretStore.Get(namespace, name) +func (s *secretManager) UnregisterPod(pod *v1.Pod) { + s.manager.UnregisterPod(pod) } func getSecretNames(pod *v1.Pod) sets.String { @@ -269,39 +102,24 @@ func getSecretNames(pod *v1.Pod) sets.String { return result } -func (c *cachingSecretManager) RegisterPod(pod *v1.Pod) { - names := getSecretNames(pod) - c.lock.Lock() - defer c.lock.Unlock() - for name := range names { - c.secretStore.Add(pod.Namespace, name) - } - var prev *v1.Pod - key := objectKey{namespace: pod.Namespace, name: pod.Name} - prev = c.registeredPods[key] - c.registeredPods[key] = pod - if prev != nil { - for name := range getSecretNames(prev) { - // On an update, the .Add() call above will have re-incremented the - // ref count of any existing secrets, so any secrets that are in both - // names and prev need to have their ref counts decremented. Any that - // are only in prev need to be completely removed. This unconditional - // call takes care of both cases. - c.secretStore.Delete(prev.Namespace, name) - } - } -} +const ( + defaultTTL = time.Minute +) -func (c *cachingSecretManager) UnregisterPod(pod *v1.Pod) { - var prev *v1.Pod - key := objectKey{namespace: pod.Namespace, name: pod.Name} - c.lock.Lock() - defer c.lock.Unlock() - prev = c.registeredPods[key] - delete(c.registeredPods, key) - if prev != nil { - for name := range getSecretNames(prev) { - c.secretStore.Delete(prev.Namespace, name) - } +// NewCachingSecretManager creates a manager that keeps a cache of all secrets +// necessary for registered pods. +// It implements the following logic: +// - whenever a pod is created or updated, the cached versions of all secrets +// are invalidated +// - every GetObject() call tries to fetch the value from local cache; if it is +// not there, invalidated or too old, we fetch it from apiserver and refresh the +// value in cache; otherwise it is just fetched from cache +func NewCachingSecretManager(kubeClient clientset.Interface, getTTL manager.GetObjectTTLFunc) Manager { + getSecret := func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { + return kubeClient.CoreV1().Secrets(namespace).Get(name, opts) + } + secretStore := manager.NewObjectStore(getSecret, clock.RealClock{}, getTTL, defaultTTL) + return &secretManager{ + manager: manager.NewCacheBasedManager(secretStore, getSecretNames), } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager_test.go index 36380e514..0dba94a02 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager_test.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 2018 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. @@ -18,30 +18,27 @@ package secret import ( "fmt" - "reflect" "strings" - "sync" "testing" "time" "k8s.io/api/core/v1" - "k8s.io/client-go/kubernetes/fake" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/clock" - core "k8s.io/client-go/testing" - "github.com/stretchr/testify/assert" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/pkg/kubelet/util/manager" ) -func checkSecret(t *testing.T, store *secretStore, ns, name string, shouldExist bool) { +func checkObject(t *testing.T, store manager.Store, ns, name string, shouldExist bool) { _, err := store.Get(ns, name) if shouldExist && err != nil { t.Errorf("unexpected actions: %#v", err) } - if !shouldExist && (err == nil || !strings.Contains(err.Error(), fmt.Sprintf("secret %q/%q not registered", ns, name))) { + if !shouldExist && (err == nil || !strings.Contains(err.Error(), fmt.Sprintf("object %q/%q not registered", ns, name))) { t.Errorf("unexpected actions: %#v", err) } } @@ -50,242 +47,9 @@ func noObjectTTL() (time.Duration, bool) { return time.Duration(0), false } -func TestSecretStore(t *testing.T) { - fakeClient := &fake.Clientset{} - store := newSecretStore(fakeClient, clock.RealClock{}, noObjectTTL, 0) - store.Add("ns1", "name1") - store.Add("ns2", "name2") - store.Add("ns1", "name1") - store.Add("ns1", "name1") - store.Delete("ns1", "name1") - store.Delete("ns2", "name2") - store.Add("ns3", "name3") - - // Adds don't issue Get requests. - actions := fakeClient.Actions() - assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) - // Should issue Get request - store.Get("ns1", "name1") - // Shouldn't issue Get request, as secret is not registered - store.Get("ns2", "name2") - // Should issue Get request - store.Get("ns3", "name3") - - actions = fakeClient.Actions() - assert.Equal(t, 2, len(actions), "unexpected actions: %#v", actions) - - for _, a := range actions { - assert.True(t, a.Matches("get", "secrets"), "unexpected actions: %#v", a) - } - - checkSecret(t, store, "ns1", "name1", true) - checkSecret(t, store, "ns2", "name2", false) - checkSecret(t, store, "ns3", "name3", true) - checkSecret(t, store, "ns4", "name4", false) -} - -func TestSecretStoreDeletingSecret(t *testing.T) { - fakeClient := &fake.Clientset{} - store := newSecretStore(fakeClient, clock.RealClock{}, noObjectTTL, 0) - store.Add("ns", "name") - - result := &v1.Secret{ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "name", ResourceVersion: "10"}} - fakeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) { - return true, result, nil - }) - secret, err := store.Get("ns", "name") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if !reflect.DeepEqual(secret, result) { - t.Errorf("Unexpected secret: %v", secret) - } - - fakeClient.PrependReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) { - return true, &v1.Secret{}, apierrors.NewNotFound(v1.Resource("secret"), "name") - }) - secret, err = store.Get("ns", "name") - if err == nil || !apierrors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } - if !reflect.DeepEqual(secret, &v1.Secret{}) { - t.Errorf("Unexpected secret: %v", secret) - } -} - -func TestSecretStoreGetAlwaysRefresh(t *testing.T) { - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Now()) - store := newSecretStore(fakeClient, fakeClock, noObjectTTL, 0) - - for i := 0; i < 10; i++ { - store.Add(fmt.Sprintf("ns-%d", i), fmt.Sprintf("name-%d", i)) - } - fakeClient.ClearActions() - - wg := sync.WaitGroup{} - wg.Add(100) - for i := 0; i < 100; i++ { - go func(i int) { - store.Get(fmt.Sprintf("ns-%d", i%10), fmt.Sprintf("name-%d", i%10)) - wg.Done() - }(i) - } - wg.Wait() - actions := fakeClient.Actions() - assert.Equal(t, 100, len(actions), "unexpected actions: %#v", actions) - - for _, a := range actions { - assert.True(t, a.Matches("get", "secrets"), "unexpected actions: %#v", a) - } -} - -func TestSecretStoreGetNeverRefresh(t *testing.T) { - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Now()) - store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute) - - for i := 0; i < 10; i++ { - store.Add(fmt.Sprintf("ns-%d", i), fmt.Sprintf("name-%d", i)) - } - fakeClient.ClearActions() - - wg := sync.WaitGroup{} - wg.Add(100) - for i := 0; i < 100; i++ { - go func(i int) { - store.Get(fmt.Sprintf("ns-%d", i%10), fmt.Sprintf("name-%d", i%10)) - wg.Done() - }(i) - } - wg.Wait() - actions := fakeClient.Actions() - // Only first Get, should forward the Get request. - assert.Equal(t, 10, len(actions), "unexpected actions: %#v", actions) -} - -func TestCustomTTL(t *testing.T) { - ttl := time.Duration(0) - ttlExists := false - customTTL := func() (time.Duration, bool) { - return ttl, ttlExists - } - - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Time{}) - store := newSecretStore(fakeClient, fakeClock, customTTL, time.Minute) - - store.Add("ns", "name") - store.Get("ns", "name") - fakeClient.ClearActions() - - // Set 0-ttl and see if that works. - ttl = time.Duration(0) - ttlExists = true - store.Get("ns", "name") - actions := fakeClient.Actions() - assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() - - // Set 5-minute ttl and see if this works. - ttl = time.Duration(5) * time.Minute - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) - // Still no effect after 4 minutes. - fakeClock.Step(4 * time.Minute) - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) - // Now it should have an effect. - fakeClock.Step(time.Minute) - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() - - // Now remove the custom ttl and see if that works. - ttlExists = false - fakeClock.Step(55 * time.Second) - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) - // Pass the minute and it should be triggered now. - fakeClock.Step(5 * time.Second) - store.Get("ns", "name") - actions = fakeClient.Actions() - assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions) -} - -func TestParseNodeAnnotation(t *testing.T) { - testCases := []struct { - node *v1.Node - err error - exists bool - ttl time.Duration - }{ - { - node: nil, - err: fmt.Errorf("error"), - exists: false, - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - }, - }, - exists: false, - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - Annotations: map[string]string{}, - }, - }, - exists: false, - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "bad"}, - }, - }, - exists: false, - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "0"}, - }, - }, - exists: true, - ttl: time.Duration(0), - }, - { - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node", - Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "60"}, - }, - }, - exists: true, - ttl: time.Minute, - }, - } - for i, testCase := range testCases { - getNode := func() (*v1.Node, error) { return testCase.node, testCase.err } - ttl, exists := GetObjectTTLFromNodeFunc(getNode)() - if exists != testCase.exists { - t.Errorf("%d: incorrect parsing: %t", i, exists) - continue - } - if exists && ttl != testCase.ttl { - t.Errorf("%d: incorrect ttl: %v", i, ttl) - } +func getSecret(fakeClient clientset.Interface) manager.GetObjectFunc { + return func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { + return fakeClient.CoreV1().Secrets(namespace).Get(name, opts) } } @@ -341,158 +105,11 @@ func podWithSecrets(ns, podName string, toAttach secretsToAttach) *v1.Pod { return pod } -func TestCacheInvalidation(t *testing.T) { - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Now()) - store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute) - manager := &cachingSecretManager{ - secretStore: store, - registeredPods: make(map[objectKey]*v1.Pod), - } - - // Create a pod with some secrets. - s1 := secretsToAttach{ - imagePullSecretNames: []string{"s1"}, - containerEnvSecrets: []envSecrets{ - {envVarNames: []string{"s1"}, envFromNames: []string{"s10"}}, - {envVarNames: []string{"s2"}}, - }, - } - manager.RegisterPod(podWithSecrets("ns1", "name1", s1)) - // Fetch both secrets - this should triggger get operations. - store.Get("ns1", "s1") - store.Get("ns1", "s10") - store.Get("ns1", "s2") - actions := fakeClient.Actions() - assert.Equal(t, 3, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() - - // Update a pod with a new secret. - s2 := secretsToAttach{ - imagePullSecretNames: []string{"s1"}, - containerEnvSecrets: []envSecrets{ - {envVarNames: []string{"s1"}}, - {envVarNames: []string{"s2"}, envFromNames: []string{"s20"}}, - {envVarNames: []string{"s3"}}, - }, - } - manager.RegisterPod(podWithSecrets("ns1", "name1", s2)) - // All secrets should be invalidated - this should trigger get operations. - store.Get("ns1", "s1") - store.Get("ns1", "s2") - store.Get("ns1", "s20") - store.Get("ns1", "s3") - actions = fakeClient.Actions() - assert.Equal(t, 4, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() - - // Create a new pod that is refencing the first three secrets - those should - // be invalidated. - manager.RegisterPod(podWithSecrets("ns1", "name2", s1)) - store.Get("ns1", "s1") - store.Get("ns1", "s10") - store.Get("ns1", "s2") - store.Get("ns1", "s20") - store.Get("ns1", "s3") - actions = fakeClient.Actions() - assert.Equal(t, 3, len(actions), "unexpected actions: %#v", actions) - fakeClient.ClearActions() -} - -func TestCacheRefcounts(t *testing.T) { - fakeClient := &fake.Clientset{} - fakeClock := clock.NewFakeClock(time.Now()) - store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute) - manager := &cachingSecretManager{ - secretStore: store, - registeredPods: make(map[objectKey]*v1.Pod), - } - - s1 := secretsToAttach{ - imagePullSecretNames: []string{"s1"}, - containerEnvSecrets: []envSecrets{ - {envVarNames: []string{"s1"}, envFromNames: []string{"s10"}}, - {envVarNames: []string{"s2"}}, - {envVarNames: []string{"s3"}}, - }, - } - manager.RegisterPod(podWithSecrets("ns1", "name1", s1)) - manager.RegisterPod(podWithSecrets("ns1", "name2", s1)) - s2 := secretsToAttach{ - imagePullSecretNames: []string{"s2"}, - containerEnvSecrets: []envSecrets{ - {envVarNames: []string{"s4"}}, - {envVarNames: []string{"s5"}, envFromNames: []string{"s50"}}, - }, - } - manager.RegisterPod(podWithSecrets("ns1", "name2", s2)) - manager.RegisterPod(podWithSecrets("ns1", "name3", s2)) - manager.RegisterPod(podWithSecrets("ns1", "name4", s2)) - manager.UnregisterPod(podWithSecrets("ns1", "name3", s2)) - s3 := secretsToAttach{ - imagePullSecretNames: []string{"s1"}, - containerEnvSecrets: []envSecrets{ - {envVarNames: []string{"s3"}, envFromNames: []string{"s30"}}, - {envVarNames: []string{"s5"}}, - }, - } - manager.RegisterPod(podWithSecrets("ns1", "name5", s3)) - manager.RegisterPod(podWithSecrets("ns1", "name6", s3)) - s4 := secretsToAttach{ - imagePullSecretNames: []string{"s3"}, - containerEnvSecrets: []envSecrets{ - {envVarNames: []string{"s6"}}, - {envFromNames: []string{"s60"}}, - }, - } - manager.RegisterPod(podWithSecrets("ns1", "name7", s4)) - manager.UnregisterPod(podWithSecrets("ns1", "name7", s4)) - - // Also check the Add + Update + Remove scenario. - manager.RegisterPod(podWithSecrets("ns1", "other-name", s1)) - manager.RegisterPod(podWithSecrets("ns1", "other-name", s2)) - manager.UnregisterPod(podWithSecrets("ns1", "other-name", s2)) - - s5 := secretsToAttach{ - containerEnvSecrets: []envSecrets{ - {envVarNames: []string{"s7"}}, - {envFromNames: []string{"s70"}}, - }, - } - // Check the no-op update scenario - manager.RegisterPod(podWithSecrets("ns1", "noop-pod", s5)) - manager.RegisterPod(podWithSecrets("ns1", "noop-pod", s5)) - - // Now we have: 3 pods with s1, 2 pods with s2 and 2 pods with s3, 0 pods with s4. - refs := func(ns, name string) int { - store.lock.Lock() - defer store.lock.Unlock() - item, ok := store.items[objectKey{ns, name}] - if !ok { - return 0 - } - return item.refCount - } - assert.Equal(t, 3, refs("ns1", "s1")) - assert.Equal(t, 1, refs("ns1", "s10")) - assert.Equal(t, 3, refs("ns1", "s2")) - assert.Equal(t, 3, refs("ns1", "s3")) - assert.Equal(t, 2, refs("ns1", "s30")) - assert.Equal(t, 2, refs("ns1", "s4")) - assert.Equal(t, 4, refs("ns1", "s5")) - assert.Equal(t, 2, refs("ns1", "s50")) - assert.Equal(t, 0, refs("ns1", "s6")) - assert.Equal(t, 0, refs("ns1", "s60")) - assert.Equal(t, 1, refs("ns1", "s7")) - assert.Equal(t, 1, refs("ns1", "s70")) -} - -func TestCachingSecretManager(t *testing.T) { +func TestCacheBasedSecretManager(t *testing.T) { fakeClient := &fake.Clientset{} - secretStore := newSecretStore(fakeClient, clock.RealClock{}, noObjectTTL, 0) - manager := &cachingSecretManager{ - secretStore: secretStore, - registeredPods: make(map[objectKey]*v1.Pod), + store := manager.NewObjectStore(getSecret(fakeClient), clock.RealClock{}, noObjectTTL, 0) + manager := &secretManager{ + manager: manager.NewCacheBasedManager(store, getSecretNames), } // Create a pod with some secrets. @@ -533,7 +150,7 @@ func TestCachingSecretManager(t *testing.T) { for _, secret := range []string{"s1", "s2", "s3", "s4", "s5", "s6", "s20", "s40", "s50"} { shouldExist := (secret == "s1" || secret == "s3" || secret == "s4" || secret == "s40") && (ns == "ns1" || ns == "ns2") - checkSecret(t, secretStore, ns, secret, shouldExist) + checkObject(t, store, ns, secret, shouldExist) } } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/server/BUILD index a310a7d5f..69a71140f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/BUILD @@ -19,13 +19,13 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/core/v1/validation:go_default_library", "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/prober:go_default_library", "//pkg/kubelet/server/portforward:go_default_library", "//pkg/kubelet/server/remotecommand:go_default_library", "//pkg/kubelet/server/stats:go_default_library", "//pkg/kubelet/server/streaming:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/util/configz:go_default_library", - "//pkg/util/limitwriter:go_default_library", "//vendor/github.com/emicklei/go-restful:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", @@ -37,7 +37,7 @@ go_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/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/remotecommand:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/proxy:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", @@ -45,7 +45,6 @@ go_library( "//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/httplog:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flushwriter:go_default_library", - "//vendor/k8s.io/client-go/tools/remotecommand:go_default_library", ], ) @@ -60,13 +59,14 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/apis/core/install:go_default_library", + "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/apis/stats/v1alpha1:go_default_library", "//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/container:go_default_library", - "//pkg/kubelet/container/testing:go_default_library", "//pkg/kubelet/server/portforward:go_default_library", "//pkg/kubelet/server/remotecommand:go_default_library", "//pkg/kubelet/server/stats:go_default_library", + "//pkg/kubelet/server/streaming:go_default_library", "//pkg/volume:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/server.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/server.go index d22096e48..b96bf6b14 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/server.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/server.go @@ -42,30 +42,30 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" - remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand" + "k8s.io/apimachinery/pkg/util/proxy" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/httplog" "k8s.io/apiserver/pkg/util/flushwriter" - "k8s.io/client-go/tools/remotecommand" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/v1/validation" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" + "k8s.io/kubernetes/pkg/kubelet/prober" "k8s.io/kubernetes/pkg/kubelet/server/portforward" remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" "k8s.io/kubernetes/pkg/kubelet/server/stats" "k8s.io/kubernetes/pkg/kubelet/server/streaming" kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/util/configz" - "k8s.io/kubernetes/pkg/util/limitwriter" ) const ( metricsPath = "/metrics" cadvisorMetricsPath = "/metrics/cadvisor" + proberMetricsPath = "/metrics/probes" specPath = "/spec/" statsPath = "/stats/" logsPath = "/logs/" @@ -73,11 +73,11 @@ const ( // Server is a http.Handler which exposes kubelet functionality over HTTP. type Server struct { - auth AuthInterface - host HostInterface - restfulCont containerInterface - resourceAnalyzer stats.ResourceAnalyzer - runtime kubecontainer.Runtime + auth AuthInterface + host HostInterface + restfulCont containerInterface + resourceAnalyzer stats.ResourceAnalyzer + redirectContainerStreaming bool } type TLSOptions struct { @@ -123,11 +123,11 @@ func ListenAndServeKubeletServer( tlsOptions *TLSOptions, auth AuthInterface, enableDebuggingHandlers, - enableContentionProfiling bool, - runtime kubecontainer.Runtime, + enableContentionProfiling, + redirectContainerStreaming bool, criHandler http.Handler) { glog.Infof("Starting to listen on %s:%d", address, port) - handler := NewServer(host, resourceAnalyzer, auth, enableDebuggingHandlers, enableContentionProfiling, runtime, criHandler) + handler := NewServer(host, resourceAnalyzer, auth, enableDebuggingHandlers, enableContentionProfiling, redirectContainerStreaming, criHandler) s := &http.Server{ Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)), Handler: &handler, @@ -145,9 +145,9 @@ func ListenAndServeKubeletServer( } // ListenAndServeKubeletReadOnlyServer initializes a server to respond to HTTP network requests on the Kubelet. -func ListenAndServeKubeletReadOnlyServer(host HostInterface, resourceAnalyzer stats.ResourceAnalyzer, address net.IP, port uint, runtime kubecontainer.Runtime) { +func ListenAndServeKubeletReadOnlyServer(host HostInterface, resourceAnalyzer stats.ResourceAnalyzer, address net.IP, port uint) { glog.V(1).Infof("Starting to listen read-only on %s:%d", address, port) - s := NewServer(host, resourceAnalyzer, nil, false, false, runtime, nil) + s := NewServer(host, resourceAnalyzer, nil, false, false, false, nil) server := &http.Server{ Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)), @@ -172,12 +172,8 @@ type HostInterface interface { GetCachedMachineInfo() (*cadvisorapi.MachineInfo, error) GetRunningPods() ([]*v1.Pod, error) RunInContainer(name string, uid types.UID, container string, cmd []string) ([]byte, error) - ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error - AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error GetKubeletContainerLogs(podFullName, containerName string, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error ServeLogs(w http.ResponseWriter, req *http.Request) - PortForward(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error - StreamingConnectionIdleTimeout() time.Duration ResyncInterval() time.Duration GetHostname() string LatestLoopEntryTime() time.Time @@ -192,15 +188,15 @@ func NewServer( resourceAnalyzer stats.ResourceAnalyzer, auth AuthInterface, enableDebuggingHandlers, - enableContentionProfiling bool, - runtime kubecontainer.Runtime, + enableContentionProfiling, + redirectContainerStreaming bool, criHandler http.Handler) Server { server := Server{ - host: host, - resourceAnalyzer: resourceAnalyzer, - auth: auth, - restfulCont: &filteringContainer{Container: restful.NewContainer()}, - runtime: runtime, + host: host, + resourceAnalyzer: resourceAnalyzer, + auth: auth, + restfulCont: &filteringContainer{Container: restful.NewContainer()}, + redirectContainerStreaming: redirectContainerStreaming, } if auth != nil { server.InstallAuthFilter() @@ -276,11 +272,18 @@ func (s *Server) InstallDefaultHandlers() { // cAdvisor metrics are exposed under the secured handler as well r := prometheus.NewRegistry() - r.MustRegister(metrics.NewPrometheusCollector(prometheusHostAdapter{s.host}, containerPrometheusLabels)) + r.MustRegister(metrics.NewPrometheusCollector(prometheusHostAdapter{s.host}, containerPrometheusLabelsFunc(s.host))) s.restfulCont.Handle(cadvisorMetricsPath, promhttp.HandlerFor(r, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}), ) + // prober metrics are exposed under a different endpoint + p := prometheus.NewRegistry() + p.MustRegister(prober.ProberResults) + s.restfulCont.Handle(proberMetricsPath, + promhttp.HandlerFor(p, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}), + ) + ws = new(restful.WebService) ws. Path(specPath). @@ -523,17 +526,9 @@ func (s *Server) getContainerLogs(request *restful.Request, response *restful.Re return } fw := flushwriter.Wrap(response.ResponseWriter) - // Byte limit logic is already implemented in kuberuntime. However, we still need this for - // old runtime integration. - // TODO(random-liu): Remove this once we switch to CRI integration. - if logOptions.LimitBytes != nil { - fw = limitwriter.New(fw, *logOptions.LimitBytes) - } response.Header().Set("Transfer-Encoding", "chunked") if err := s.host.GetKubeletContainerLogs(kubecontainer.GetPodFullName(pod), containerName, logOptions, fw, fw); err != nil { - if err != limitwriter.ErrMaximumWrite { - response.WriteError(http.StatusBadRequest, err) - } + response.WriteError(http.StatusBadRequest, err) return } } @@ -627,6 +622,22 @@ func getPortForwardRequestParams(req *restful.Request) portForwardRequestParams } } +type responder struct { + errorMessage string +} + +func (r *responder) Error(w http.ResponseWriter, req *http.Request, err error) { + glog.Errorf("Error while proxying request: %v", err) + http.Error(w, err.Error(), http.StatusInternalServerError) +} + +// proxyStream proxies stream to url. +func proxyStream(w http.ResponseWriter, r *http.Request, url *url.URL) { + // TODO(random-liu): Set MaxBytesPerSec to throttle the stream. + handler := proxy.NewUpgradeAwareHandler(url, nil /*transport*/, false /*wrapTransport*/, true /*upgradeRequired*/, &responder{}) + handler.ServeHTTP(w, r) +} + // getAttach handles requests to attach to a container. func (s *Server) getAttach(request *restful.Request, response *restful.Response) { params := getExecRequestParams(request) @@ -643,26 +654,17 @@ func (s *Server) getAttach(request *restful.Request, response *restful.Response) } podFullName := kubecontainer.GetPodFullName(pod) - redirect, err := s.host.GetAttach(podFullName, params.podUID, params.containerName, *streamOpts) + url, err := s.host.GetAttach(podFullName, params.podUID, params.containerName, *streamOpts) if err != nil { streaming.WriteError(err, response.ResponseWriter) return } - if redirect != nil { - http.Redirect(response.ResponseWriter, request.Request, redirect.String(), http.StatusFound) + + if s.redirectContainerStreaming { + http.Redirect(response.ResponseWriter, request.Request, url.String(), http.StatusFound) return } - - remotecommandserver.ServeAttach(response.ResponseWriter, - request.Request, - s.host, - podFullName, - params.podUID, - params.containerName, - streamOpts, - s.host.StreamingConnectionIdleTimeout(), - remotecommandconsts.DefaultStreamCreationTimeout, - remotecommandconsts.SupportedStreamingProtocols) + proxyStream(response.ResponseWriter, request.Request, url) } // getExec handles requests to run a command inside a container. @@ -681,27 +683,16 @@ func (s *Server) getExec(request *restful.Request, response *restful.Response) { } podFullName := kubecontainer.GetPodFullName(pod) - redirect, err := s.host.GetExec(podFullName, params.podUID, params.containerName, params.cmd, *streamOpts) + url, err := s.host.GetExec(podFullName, params.podUID, params.containerName, params.cmd, *streamOpts) if err != nil { streaming.WriteError(err, response.ResponseWriter) return } - if redirect != nil { - http.Redirect(response.ResponseWriter, request.Request, redirect.String(), http.StatusFound) + if s.redirectContainerStreaming { + http.Redirect(response.ResponseWriter, request.Request, url.String(), http.StatusFound) return } - - remotecommandserver.ServeExec(response.ResponseWriter, - request.Request, - s.host, - podFullName, - params.podUID, - params.containerName, - params.cmd, - streamOpts, - s.host.StreamingConnectionIdleTimeout(), - remotecommandconsts.DefaultStreamCreationTimeout, - remotecommandconsts.SupportedStreamingProtocols) + proxyStream(response.ResponseWriter, request.Request, url) } // getRun handles requests to run a command inside a container. @@ -758,25 +749,16 @@ func (s *Server) getPortForward(request *restful.Request, response *restful.Resp return } - redirect, err := s.host.GetPortForward(pod.Name, pod.Namespace, pod.UID, *portForwardOptions) + url, err := s.host.GetPortForward(pod.Name, pod.Namespace, pod.UID, *portForwardOptions) if err != nil { streaming.WriteError(err, response.ResponseWriter) return } - if redirect != nil { - http.Redirect(response.ResponseWriter, request.Request, redirect.String(), http.StatusFound) + if s.redirectContainerStreaming { + http.Redirect(response.ResponseWriter, request.Request, url.String(), http.StatusFound) return } - - portforward.ServePortForward(response.ResponseWriter, - request.Request, - s.host, - kubecontainer.GetPodFullName(pod), - params.podUID, - portForwardOptions, - s.host.StreamingConnectionIdleTimeout(), - remotecommandconsts.DefaultStreamCreationTimeout, - portforward.SupportedProtocols) + proxyStream(response.ResponseWriter, request.Request, url) } // ServeHTTP responds to HTTP requests on the Kubelet. @@ -816,31 +798,40 @@ func (a prometheusHostAdapter) GetMachineInfo() (*cadvisorapi.MachineInfo, error return a.host.GetCachedMachineInfo() } -// containerPrometheusLabels maps cAdvisor labels to prometheus labels. -func containerPrometheusLabels(c *cadvisorapi.ContainerInfo) map[string]string { - // Prometheus requires that all metrics in the same family have the same labels, - // so we arrange to supply blank strings for missing labels - var name, image, podName, namespace, containerName string - if len(c.Aliases) > 0 { - name = c.Aliases[0] - } - image = c.Spec.Image - if v, ok := c.Spec.Labels[kubelettypes.KubernetesPodNameLabel]; ok { - podName = v - } - if v, ok := c.Spec.Labels[kubelettypes.KubernetesPodNamespaceLabel]; ok { - namespace = v - } - if v, ok := c.Spec.Labels[kubelettypes.KubernetesContainerNameLabel]; ok { - containerName = v - } - set := map[string]string{ - metrics.LabelID: c.Name, - metrics.LabelName: name, - metrics.LabelImage: image, - "pod_name": podName, - "namespace": namespace, - "container_name": containerName, +func containerPrometheusLabelsFunc(s stats.StatsProvider) metrics.ContainerLabelsFunc { + // containerPrometheusLabels maps cAdvisor labels to prometheus labels. + return func(c *cadvisorapi.ContainerInfo) map[string]string { + // Prometheus requires that all metrics in the same family have the same labels, + // so we arrange to supply blank strings for missing labels + var name, image, podName, namespace, containerName string + if len(c.Aliases) > 0 { + name = c.Aliases[0] + } + image = c.Spec.Image + if v, ok := c.Spec.Labels[kubelettypes.KubernetesPodNameLabel]; ok { + podName = v + } + if v, ok := c.Spec.Labels[kubelettypes.KubernetesPodNamespaceLabel]; ok { + namespace = v + } + if v, ok := c.Spec.Labels[kubelettypes.KubernetesContainerNameLabel]; ok { + containerName = v + } + // Associate pod cgroup with pod so we have an accurate accounting of sandbox + if podName == "" && namespace == "" { + if pod, found := s.GetPodByCgroupfs(c.Name); found { + podName = pod.Name + namespace = pod.Namespace + } + } + set := map[string]string{ + metrics.LabelID: c.Name, + metrics.LabelName: name, + metrics.LabelImage: image, + "pod_name": podName, + "namespace": namespace, + "container_name": containerName, + } + return set } - return set } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/server_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/server_test.go index a42994018..e84bec4d6 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/server_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/server_test.go @@ -48,41 +48,44 @@ import ( "k8s.io/client-go/tools/remotecommand" utiltesting "k8s.io/client-go/util/testing" api "k8s.io/kubernetes/pkg/apis/core" + runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" // Do some initialization to decode the query parameters correctly. _ "k8s.io/kubernetes/pkg/apis/core/install" "k8s.io/kubernetes/pkg/kubelet/cm" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - kubecontainertesting "k8s.io/kubernetes/pkg/kubelet/container/testing" "k8s.io/kubernetes/pkg/kubelet/server/portforward" remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" "k8s.io/kubernetes/pkg/kubelet/server/stats" + "k8s.io/kubernetes/pkg/kubelet/server/streaming" "k8s.io/kubernetes/pkg/volume" ) const ( - testUID = "9b01b80f-8fb4-11e4-95ab-4200af06647" + testUID = "9b01b80f-8fb4-11e4-95ab-4200af06647" + testContainerID = "container789" + testPodSandboxID = "pod0987" ) type fakeKubelet struct { - podByNameFunc func(namespace, name string) (*v1.Pod, bool) - containerInfoFunc func(podFullName string, uid types.UID, containerName string, req *cadvisorapi.ContainerInfoRequest) (*cadvisorapi.ContainerInfo, error) - rawInfoFunc func(query *cadvisorapi.ContainerInfoRequest) (map[string]*cadvisorapi.ContainerInfo, error) - machineInfoFunc func() (*cadvisorapi.MachineInfo, error) - podsFunc func() []*v1.Pod - runningPodsFunc func() ([]*v1.Pod, error) - logFunc func(w http.ResponseWriter, req *http.Request) - runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) - execFunc func(pod string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool) error - attachFunc func(pod string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool) error - portForwardFunc func(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error - containerLogsFunc func(podFullName, containerName string, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error - streamingConnectionIdleTimeoutFunc func() time.Duration - hostnameFunc func() string - resyncInterval time.Duration - loopEntryTime time.Time - plegHealth bool - redirectURL *url.URL + podByNameFunc func(namespace, name string) (*v1.Pod, bool) + containerInfoFunc func(podFullName string, uid types.UID, containerName string, req *cadvisorapi.ContainerInfoRequest) (*cadvisorapi.ContainerInfo, error) + rawInfoFunc func(query *cadvisorapi.ContainerInfoRequest) (map[string]*cadvisorapi.ContainerInfo, error) + machineInfoFunc func() (*cadvisorapi.MachineInfo, error) + podsFunc func() []*v1.Pod + runningPodsFunc func() ([]*v1.Pod, error) + logFunc func(w http.ResponseWriter, req *http.Request) + runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) + getExecCheck func(string, types.UID, string, []string, remotecommandserver.Options) + getAttachCheck func(string, types.UID, string, remotecommandserver.Options) + getPortForwardCheck func(string, string, types.UID, portforward.V4Options) + + containerLogsFunc func(podFullName, containerName string, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error + hostnameFunc func() string + resyncInterval time.Duration + loopEntryTime time.Time + plegHealth bool + streamingRuntime streaming.Server } func (fk *fakeKubelet) ResyncInterval() time.Duration { @@ -137,39 +140,116 @@ func (fk *fakeKubelet) RunInContainer(podFullName string, uid types.UID, contain return fk.runFunc(podFullName, uid, containerName, cmd) } -func (fk *fakeKubelet) ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - return fk.execFunc(name, uid, container, cmd, in, out, err, tty) +type fakeRuntime struct { + execFunc func(string, []string, io.Reader, io.WriteCloser, io.WriteCloser, bool, <-chan remotecommand.TerminalSize) error + attachFunc func(string, io.Reader, io.WriteCloser, io.WriteCloser, bool, <-chan remotecommand.TerminalSize) error + portForwardFunc func(string, int32, io.ReadWriteCloser) error } -func (fk *fakeKubelet) AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - return fk.attachFunc(name, uid, container, in, out, err, tty) +func (f *fakeRuntime) Exec(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { + return f.execFunc(containerID, cmd, stdin, stdout, stderr, tty, resize) } -func (fk *fakeKubelet) PortForward(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error { - return fk.portForwardFunc(name, uid, port, stream) +func (f *fakeRuntime) Attach(containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { + return f.attachFunc(containerID, stdin, stdout, stderr, tty, resize) +} + +func (f *fakeRuntime) PortForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error { + return f.portForwardFunc(podSandboxID, port, stream) +} + +type testStreamingServer struct { + streaming.Server + fakeRuntime *fakeRuntime + testHTTPServer *httptest.Server +} + +func newTestStreamingServer(streamIdleTimeout time.Duration) (s *testStreamingServer, err error) { + s = &testStreamingServer{} + s.testHTTPServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.ServeHTTP(w, r) + })) + defer func() { + if err != nil { + s.testHTTPServer.Close() + } + }() + + testURL, err := url.Parse(s.testHTTPServer.URL) + if err != nil { + return nil, err + } + + s.fakeRuntime = &fakeRuntime{} + config := streaming.DefaultConfig + config.BaseURL = testURL + if streamIdleTimeout != 0 { + config.StreamIdleTimeout = streamIdleTimeout + } + s.Server, err = streaming.NewServer(config, s.fakeRuntime) + if err != nil { + return nil, err + } + return s, nil } func (fk *fakeKubelet) GetExec(podFullName string, podUID types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) (*url.URL, error) { - return fk.redirectURL, nil + if fk.getExecCheck != nil { + fk.getExecCheck(podFullName, podUID, containerName, cmd, streamOpts) + } + // Always use testContainerID + resp, err := fk.streamingRuntime.GetExec(&runtimeapi.ExecRequest{ + ContainerId: testContainerID, + Cmd: cmd, + Tty: streamOpts.TTY, + Stdin: streamOpts.Stdin, + Stdout: streamOpts.Stdout, + Stderr: streamOpts.Stderr, + }) + if err != nil { + return nil, err + } + return url.Parse(resp.GetUrl()) } func (fk *fakeKubelet) GetAttach(podFullName string, podUID types.UID, containerName string, streamOpts remotecommandserver.Options) (*url.URL, error) { - return fk.redirectURL, nil + if fk.getAttachCheck != nil { + fk.getAttachCheck(podFullName, podUID, containerName, streamOpts) + } + // Always use testContainerID + resp, err := fk.streamingRuntime.GetAttach(&runtimeapi.AttachRequest{ + ContainerId: testContainerID, + Tty: streamOpts.TTY, + Stdin: streamOpts.Stdin, + Stdout: streamOpts.Stdout, + Stderr: streamOpts.Stderr, + }) + if err != nil { + return nil, err + } + return url.Parse(resp.GetUrl()) } func (fk *fakeKubelet) GetPortForward(podName, podNamespace string, podUID types.UID, portForwardOpts portforward.V4Options) (*url.URL, error) { - return fk.redirectURL, nil -} - -func (fk *fakeKubelet) StreamingConnectionIdleTimeout() time.Duration { - return fk.streamingConnectionIdleTimeoutFunc() + if fk.getPortForwardCheck != nil { + fk.getPortForwardCheck(podName, podNamespace, podUID, portForwardOpts) + } + // Always use testPodSandboxID + resp, err := fk.streamingRuntime.GetPortForward(&runtimeapi.PortForwardRequest{ + PodSandboxId: testPodSandboxID, + Port: portForwardOpts.Ports, + }) + if err != nil { + return nil, err + } + return url.Parse(resp.GetUrl()) } // Unused functions -func (_ *fakeKubelet) GetNode() (*v1.Node, error) { return nil, nil } -func (_ *fakeKubelet) GetNodeConfig() cm.NodeConfig { return cm.NodeConfig{} } -func (_ *fakeKubelet) GetPodCgroupRoot() string { return "" } - +func (_ *fakeKubelet) GetNode() (*v1.Node, error) { return nil, nil } +func (_ *fakeKubelet) GetNodeConfig() cm.NodeConfig { return cm.NodeConfig{} } +func (_ *fakeKubelet) GetPodCgroupRoot() string { return "" } +func (_ *fakeKubelet) GetPodByCgroupfs(cgroupfs string) (*v1.Pod, bool) { return nil, false } func (fk *fakeKubelet) ListVolumesForPod(podUID types.UID) (map[string]volume.Volume, bool) { return map[string]volume.Volume{}, true } @@ -199,18 +279,20 @@ func (f *fakeAuth) Authorize(a authorizer.Attributes) (authorized authorizer.Dec } type serverTestFramework struct { - serverUnderTest *Server - fakeKubelet *fakeKubelet - fakeAuth *fakeAuth - testHTTPServer *httptest.Server - criHandler *utiltesting.FakeHandler + serverUnderTest *Server + fakeKubelet *fakeKubelet + fakeAuth *fakeAuth + testHTTPServer *httptest.Server + fakeRuntime *fakeRuntime + testStreamingHTTPServer *httptest.Server + criHandler *utiltesting.FakeHandler } func newServerTest() *serverTestFramework { - return newServerTestWithDebug(true) + return newServerTestWithDebug(true, false, nil) } -func newServerTestWithDebug(enableDebugging bool) *serverTestFramework { +func newServerTestWithDebug(enableDebugging, redirectContainerStreaming bool, streamingServer streaming.Server) *serverTestFramework { fw := &serverTestFramework{} fw.fakeKubelet = &fakeKubelet{ hostnameFunc: func() string { @@ -225,7 +307,8 @@ func newServerTestWithDebug(enableDebugging bool) *serverTestFramework { }, }, true }, - plegHealth: true, + plegHealth: true, + streamingRuntime: streamingServer, } fw.fakeAuth = &fakeAuth{ authenticateFunc: func(req *http.Request) (user.Info, bool, error) { @@ -247,7 +330,7 @@ func newServerTestWithDebug(enableDebugging bool) *serverTestFramework { fw.fakeAuth, enableDebugging, false, - &kubecontainertesting.Mock{}, + redirectContainerStreaming, fw.criHandler) fw.serverUnderTest = &server fw.testHTTPServer = httptest.NewServer(fw.serverUnderTest) @@ -943,33 +1026,6 @@ func TestContainerLogs(t *testing.T) { } } -func TestContainerLogsWithLimitBytes(t *testing.T) { - fw := newServerTest() - defer fw.testHTTPServer.Close() - output := "foo bar" - podNamespace := "other" - podName := "foo" - expectedPodName := getPodName(podName, podNamespace) - expectedContainerName := "baz" - bytes := int64(3) - setPodByNameFunc(fw, podNamespace, podName, expectedContainerName) - setGetContainerLogsFunc(fw, t, expectedPodName, expectedContainerName, &v1.PodLogOptions{LimitBytes: &bytes}, output) - resp, err := http.Get(fw.testHTTPServer.URL + "/containerLogs/" + podNamespace + "/" + podName + "/" + expectedContainerName + "?limitBytes=3") - if err != nil { - t.Errorf("Got error GETing: %v", err) - } - defer resp.Body.Close() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Errorf("Error reading container logs: %v", err) - } - result := string(body) - if result != output[:bytes] { - t.Errorf("Expected: '%v', got: '%v'", output[:bytes], result) - } -} - func TestContainerLogsWithTail(t *testing.T) { fw := newServerTest() defer fw.testHTTPServer.Close() @@ -1097,13 +1153,12 @@ func TestContainerLogsWithFollow(t *testing.T) { } func TestServeExecInContainerIdleTimeout(t *testing.T) { - fw := newServerTest() + ss, err := newTestStreamingServer(100 * time.Millisecond) + require.NoError(t, err) + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, false, ss) defer fw.testHTTPServer.Close() - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 100 * time.Millisecond - } - podNamespace := "other" podName := "foo" expectedContainerName := "baz" @@ -1135,280 +1190,221 @@ func TestServeExecInContainerIdleTimeout(t *testing.T) { } func testExecAttach(t *testing.T, verb string) { - tests := []struct { + tests := map[string]struct { stdin bool stdout bool stderr bool tty bool responseStatusCode int uid bool - responseLocation string + redirect bool }{ - {responseStatusCode: http.StatusBadRequest}, - {stdin: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdout: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdout: true, stderr: true, tty: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdin: true, stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, - {stdout: true, responseStatusCode: http.StatusFound, responseLocation: "http://localhost:12345/" + verb}, - } - - for i, test := range tests { - fw := newServerTest() - defer fw.testHTTPServer.Close() - - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 0 - } - - if test.responseLocation != "" { - var err error - fw.fakeKubelet.redirectURL, err = url.Parse(test.responseLocation) + "no input or output": {responseStatusCode: http.StatusBadRequest}, + "stdin": {stdin: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdout": {stdout: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stderr": {stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdout and stderr": {stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdout stderr and tty": {stdout: true, stderr: true, tty: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdin stdout and stderr": {stdin: true, stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols}, + "stdin stdout stderr with uid": {stdin: true, stdout: true, stderr: true, responseStatusCode: http.StatusSwitchingProtocols, uid: true}, + "stdout with redirect": {stdout: true, responseStatusCode: http.StatusFound, redirect: true}, + } + + for desc, test := range tests { + test := test + t.Run(desc, func(t *testing.T) { + ss, err := newTestStreamingServer(0) require.NoError(t, err) - } - - podNamespace := "other" - podName := "foo" - expectedPodName := getPodName(podName, podNamespace) - expectedContainerName := "baz" - expectedCommand := "ls -a" - expectedStdin := "stdin" - expectedStdout := "stdout" - expectedStderr := "stderr" - done := make(chan struct{}) - clientStdoutReadDone := make(chan struct{}) - clientStderrReadDone := make(chan struct{}) - execInvoked := false - attachInvoked := false - - testStreamFunc := func(podFullName string, uid types.UID, containerName string, cmd []string, in io.Reader, out, stderr io.WriteCloser, tty bool, done chan struct{}) error { - defer close(done) - - if podFullName != expectedPodName { - t.Fatalf("%d: podFullName: expected %s, got %s", i, expectedPodName, podFullName) - } - if test.uid && string(uid) != testUID { - t.Fatalf("%d: uid: expected %v, got %v", i, testUID, uid) - } - if containerName != expectedContainerName { - t.Fatalf("%d: containerName: expected %s, got %s", i, expectedContainerName, containerName) + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, test.redirect, ss) + defer fw.testHTTPServer.Close() + fmt.Println(desc) + + podNamespace := "other" + podName := "foo" + expectedPodName := getPodName(podName, podNamespace) + expectedContainerName := "baz" + expectedCommand := "ls -a" + expectedStdin := "stdin" + expectedStdout := "stdout" + expectedStderr := "stderr" + done := make(chan struct{}) + clientStdoutReadDone := make(chan struct{}) + clientStderrReadDone := make(chan struct{}) + execInvoked := false + attachInvoked := false + + checkStream := func(podFullName string, uid types.UID, containerName string, streamOpts remotecommandserver.Options) { + assert.Equal(t, expectedPodName, podFullName, "podFullName") + if test.uid { + assert.Equal(t, testUID, string(uid), "uid") + } + assert.Equal(t, expectedContainerName, containerName, "containerName") + assert.Equal(t, test.stdin, streamOpts.Stdin, "stdin") + assert.Equal(t, test.stdout, streamOpts.Stdout, "stdout") + assert.Equal(t, test.tty, streamOpts.TTY, "tty") + assert.Equal(t, !test.tty && test.stderr, streamOpts.Stderr, "stderr") } - if test.stdin { - if in == nil { - t.Fatalf("%d: stdin: expected non-nil", i) - } - b := make([]byte, 10) - n, err := in.Read(b) - if err != nil { - t.Fatalf("%d: error reading from stdin: %v", i, err) - } - if e, a := expectedStdin, string(b[0:n]); e != a { - t.Fatalf("%d: stdin: expected to read %v, got %v", i, e, a) - } - } else if in != nil { - t.Fatalf("%d: stdin: expected nil: %#v", i, in) + fw.fakeKubelet.getExecCheck = func(podFullName string, uid types.UID, containerName string, cmd []string, streamOpts remotecommandserver.Options) { + execInvoked = true + assert.Equal(t, expectedCommand, strings.Join(cmd, " "), "cmd") + checkStream(podFullName, uid, containerName, streamOpts) } - if test.stdout { - if out == nil { - t.Fatalf("%d: stdout: expected non-nil", i) - } - _, err := out.Write([]byte(expectedStdout)) - if err != nil { - t.Fatalf("%d:, error writing to stdout: %v", i, err) - } - out.Close() - <-clientStdoutReadDone - } else if out != nil { - t.Fatalf("%d: stdout: expected nil: %#v", i, out) + fw.fakeKubelet.getAttachCheck = func(podFullName string, uid types.UID, containerName string, streamOpts remotecommandserver.Options) { + attachInvoked = true + checkStream(podFullName, uid, containerName, streamOpts) } - if tty { - if stderr != nil { - t.Fatalf("%d: tty set but received non-nil stderr: %v", i, stderr) + testStream := func(containerID string, in io.Reader, out, stderr io.WriteCloser, tty bool, done chan struct{}) error { + close(done) + assert.Equal(t, testContainerID, containerID, "containerID") + assert.Equal(t, test.tty, tty, "tty") + require.Equal(t, test.stdin, in != nil, "in") + require.Equal(t, test.stdout, out != nil, "out") + require.Equal(t, !test.tty && test.stderr, stderr != nil, "err") + + if test.stdin { + b := make([]byte, 10) + n, err := in.Read(b) + assert.NoError(t, err, "reading from stdin") + assert.Equal(t, expectedStdin, string(b[0:n]), "content from stdin") } - } else if test.stderr { - if stderr == nil { - t.Fatalf("%d: stderr: expected non-nil", i) + + if test.stdout { + _, err := out.Write([]byte(expectedStdout)) + assert.NoError(t, err, "writing to stdout") + out.Close() + <-clientStdoutReadDone } - _, err := stderr.Write([]byte(expectedStderr)) - if err != nil { - t.Fatalf("%d:, error writing to stderr: %v", i, err) + + if !test.tty && test.stderr { + _, err := stderr.Write([]byte(expectedStderr)) + assert.NoError(t, err, "writing to stderr") + stderr.Close() + <-clientStderrReadDone } - stderr.Close() - <-clientStderrReadDone - } else if stderr != nil { - t.Fatalf("%d: stderr: expected nil: %#v", i, stderr) + return nil } - return nil - } - - fw.fakeKubelet.execFunc = func(podFullName string, uid types.UID, containerName string, cmd []string, in io.Reader, out, stderr io.WriteCloser, tty bool) error { - execInvoked = true - if strings.Join(cmd, " ") != expectedCommand { - t.Fatalf("%d: cmd: expected: %s, got %v", i, expectedCommand, cmd) + ss.fakeRuntime.execFunc = func(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { + assert.Equal(t, expectedCommand, strings.Join(cmd, " "), "cmd") + return testStream(containerID, stdin, stdout, stderr, tty, done) } - return testStreamFunc(podFullName, uid, containerName, cmd, in, out, stderr, tty, done) - } - fw.fakeKubelet.attachFunc = func(podFullName string, uid types.UID, containerName string, in io.Reader, out, stderr io.WriteCloser, tty bool) error { - attachInvoked = true - return testStreamFunc(podFullName, uid, containerName, nil, in, out, stderr, tty, done) - } - - var url string - if test.uid { - url = fw.testHTTPServer.URL + "/" + verb + "/" + podNamespace + "/" + podName + "/" + testUID + "/" + expectedContainerName + "?ignore=1" - } else { - url = fw.testHTTPServer.URL + "/" + verb + "/" + podNamespace + "/" + podName + "/" + expectedContainerName + "?ignore=1" - } - if verb == "exec" { - url += "&command=ls&command=-a" - } - if test.stdin { - url += "&" + api.ExecStdinParam + "=1" - } - if test.stdout { - url += "&" + api.ExecStdoutParam + "=1" - } - if test.stderr && !test.tty { - url += "&" + api.ExecStderrParam + "=1" - } - if test.tty { - url += "&" + api.ExecTTYParam + "=1" - } - - var ( - resp *http.Response - err error - upgradeRoundTripper httpstream.UpgradeRoundTripper - c *http.Client - ) - - if test.responseStatusCode != http.StatusSwitchingProtocols { - c = &http.Client{} - // Don't follow redirects, since we want to inspect the redirect response. - c.CheckRedirect = func(*http.Request, []*http.Request) error { - return http.ErrUseLastResponse + ss.fakeRuntime.attachFunc = func(containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { + return testStream(containerID, stdin, stdout, stderr, tty, done) } - } else { - upgradeRoundTripper = spdy.NewRoundTripper(nil, true) - c = &http.Client{Transport: upgradeRoundTripper} - } - resp, err = c.Post(url, "", nil) - if err != nil { - t.Fatalf("%d: Got error POSTing: %v", i, err) - } - defer resp.Body.Close() + var url string + if test.uid { + url = fw.testHTTPServer.URL + "/" + verb + "/" + podNamespace + "/" + podName + "/" + testUID + "/" + expectedContainerName + "?ignore=1" + } else { + url = fw.testHTTPServer.URL + "/" + verb + "/" + podNamespace + "/" + podName + "/" + expectedContainerName + "?ignore=1" + } + if verb == "exec" { + url += "&command=ls&command=-a" + } + if test.stdin { + url += "&" + api.ExecStdinParam + "=1" + } + if test.stdout { + url += "&" + api.ExecStdoutParam + "=1" + } + if test.stderr && !test.tty { + url += "&" + api.ExecStderrParam + "=1" + } + if test.tty { + url += "&" + api.ExecTTYParam + "=1" + } - _, err = ioutil.ReadAll(resp.Body) - if err != nil { - t.Errorf("%d: Error reading response body: %v", i, err) - } + var ( + resp *http.Response + upgradeRoundTripper httpstream.UpgradeRoundTripper + c *http.Client + ) + if test.redirect { + c = &http.Client{} + // Don't follow redirects, since we want to inspect the redirect response. + c.CheckRedirect = func(*http.Request, []*http.Request) error { + return http.ErrUseLastResponse + } + } else { + upgradeRoundTripper = spdy.NewRoundTripper(nil, true) + c = &http.Client{Transport: upgradeRoundTripper} + } - if e, a := test.responseStatusCode, resp.StatusCode; e != a { - t.Fatalf("%d: response status: expected %v, got %v", i, e, a) - } + resp, err = c.Post(url, "", nil) + require.NoError(t, err, "POSTing") + defer resp.Body.Close() - if e, a := test.responseLocation, resp.Header.Get("Location"); e != a { - t.Errorf("%d: response location: expected %v, got %v", i, e, a) - } + _, err = ioutil.ReadAll(resp.Body) + assert.NoError(t, err, "reading response body") - if test.responseStatusCode != http.StatusSwitchingProtocols { - continue - } + require.Equal(t, test.responseStatusCode, resp.StatusCode, "response status") + if test.responseStatusCode != http.StatusSwitchingProtocols { + return + } - conn, err := upgradeRoundTripper.NewConnection(resp) - if err != nil { - t.Fatalf("Unexpected error creating streaming connection: %s", err) - } - if conn == nil { - t.Fatalf("%d: unexpected nil conn", i) - } - defer conn.Close() + conn, err := upgradeRoundTripper.NewConnection(resp) + require.NoError(t, err, "creating streaming connection") + defer conn.Close() - h := http.Header{} - h.Set(api.StreamType, api.StreamTypeError) - if _, err := conn.CreateStream(h); err != nil { - t.Fatalf("%d: error creating error stream: %v", i, err) - } + h := http.Header{} + h.Set(api.StreamType, api.StreamTypeError) + _, err = conn.CreateStream(h) + require.NoError(t, err, "creating error stream") - if test.stdin { - h.Set(api.StreamType, api.StreamTypeStdin) - stream, err := conn.CreateStream(h) - if err != nil { - t.Fatalf("%d: error creating stdin stream: %v", i, err) - } - _, err = stream.Write([]byte(expectedStdin)) - if err != nil { - t.Fatalf("%d: error writing to stdin stream: %v", i, err) + if test.stdin { + h.Set(api.StreamType, api.StreamTypeStdin) + stream, err := conn.CreateStream(h) + require.NoError(t, err, "creating stdin stream") + _, err = stream.Write([]byte(expectedStdin)) + require.NoError(t, err, "writing to stdin stream") } - } - var stdoutStream httpstream.Stream - if test.stdout { - h.Set(api.StreamType, api.StreamTypeStdout) - stdoutStream, err = conn.CreateStream(h) - if err != nil { - t.Fatalf("%d: error creating stdout stream: %v", i, err) + var stdoutStream httpstream.Stream + if test.stdout { + h.Set(api.StreamType, api.StreamTypeStdout) + stdoutStream, err = conn.CreateStream(h) + require.NoError(t, err, "creating stdout stream") } - } - var stderrStream httpstream.Stream - if test.stderr && !test.tty { - h.Set(api.StreamType, api.StreamTypeStderr) - stderrStream, err = conn.CreateStream(h) - if err != nil { - t.Fatalf("%d: error creating stderr stream: %v", i, err) + var stderrStream httpstream.Stream + if test.stderr && !test.tty { + h.Set(api.StreamType, api.StreamTypeStderr) + stderrStream, err = conn.CreateStream(h) + require.NoError(t, err, "creating stderr stream") } - } - if test.stdout { - output := make([]byte, 10) - n, err := stdoutStream.Read(output) - close(clientStdoutReadDone) - if err != nil { - t.Fatalf("%d: error reading from stdout stream: %v", i, err) - } - if e, a := expectedStdout, string(output[0:n]); e != a { - t.Fatalf("%d: stdout: expected '%v', got '%v'", i, e, a) + if test.stdout { + output := make([]byte, 10) + n, err := stdoutStream.Read(output) + close(clientStdoutReadDone) + assert.NoError(t, err, "reading from stdout stream") + assert.Equal(t, expectedStdout, string(output[0:n]), "stdout") } - } - if test.stderr && !test.tty { - output := make([]byte, 10) - n, err := stderrStream.Read(output) - close(clientStderrReadDone) - if err != nil { - t.Fatalf("%d: error reading from stderr stream: %v", i, err) + if test.stderr && !test.tty { + output := make([]byte, 10) + n, err := stderrStream.Read(output) + close(clientStderrReadDone) + assert.NoError(t, err, "reading from stderr stream") + assert.Equal(t, expectedStderr, string(output[0:n]), "stderr") } - if e, a := expectedStderr, string(output[0:n]); e != a { - t.Fatalf("%d: stderr: expected '%v', got '%v'", i, e, a) - } - } - // wait for the server to finish before checking if the attach/exec funcs were invoked - <-done + // wait for the server to finish before checking if the attach/exec funcs were invoked + <-done - if verb == "exec" { - if !execInvoked { - t.Errorf("%d: exec was not invoked", i) + if verb == "exec" { + assert.True(t, execInvoked, "exec should be invoked") + assert.False(t, attachInvoked, "attach should not be invoked") + } else { + assert.True(t, attachInvoked, "attach should be invoked") + assert.False(t, execInvoked, "exec should not be invoked") } - if attachInvoked { - t.Errorf("%d: attach should not have been invoked", i) - } - } else { - if !attachInvoked { - t.Errorf("%d: attach was not invoked", i) - } - if execInvoked { - t.Errorf("%d: exec should not have been invoked", i) - } - } + }) } } @@ -1421,13 +1417,12 @@ func TestServeAttachContainer(t *testing.T) { } func TestServePortForwardIdleTimeout(t *testing.T) { - fw := newServerTest() + ss, err := newTestStreamingServer(100 * time.Millisecond) + require.NoError(t, err) + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, false, ss) defer fw.testHTTPServer.Close() - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 100 * time.Millisecond - } - podNamespace := "other" podName := "foo" @@ -1455,174 +1450,139 @@ func TestServePortForwardIdleTimeout(t *testing.T) { } func TestServePortForward(t *testing.T) { - tests := []struct { - port string - uid bool - clientData string - containerData string - shouldError bool - responseLocation string + tests := map[string]struct { + port string + uid bool + clientData string + containerData string + redirect bool + shouldError bool }{ - {port: "", shouldError: true}, - {port: "abc", shouldError: true}, - {port: "-1", shouldError: true}, - {port: "65536", shouldError: true}, - {port: "0", shouldError: true}, - {port: "1", shouldError: false}, - {port: "8000", shouldError: false}, - {port: "8000", clientData: "client data", containerData: "container data", shouldError: false}, - {port: "65535", shouldError: false}, - {port: "65535", uid: true, shouldError: false}, - {port: "65535", responseLocation: "http://localhost:12345/portforward", shouldError: false}, + "no port": {port: "", shouldError: true}, + "none number port": {port: "abc", shouldError: true}, + "negative port": {port: "-1", shouldError: true}, + "too large port": {port: "65536", shouldError: true}, + "0 port": {port: "0", shouldError: true}, + "min port": {port: "1", shouldError: false}, + "normal port": {port: "8000", shouldError: false}, + "normal port with data forward": {port: "8000", clientData: "client data", containerData: "container data", shouldError: false}, + "max port": {port: "65535", shouldError: false}, + "normal port with uid": {port: "8000", uid: true, shouldError: false}, + "normal port with redirect": {port: "8000", redirect: true, shouldError: false}, } podNamespace := "other" podName := "foo" - expectedPodName := getPodName(podName, podNamespace) - - for i, test := range tests { - fw := newServerTest() - defer fw.testHTTPServer.Close() - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 0 - } - - if test.responseLocation != "" { - var err error - fw.fakeKubelet.redirectURL, err = url.Parse(test.responseLocation) + for desc, test := range tests { + test := test + t.Run(desc, func(t *testing.T) { + ss, err := newTestStreamingServer(0) require.NoError(t, err) - } + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, test.redirect, ss) + defer fw.testHTTPServer.Close() - portForwardFuncDone := make(chan struct{}) - - fw.fakeKubelet.portForwardFunc = func(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error { - defer close(portForwardFuncDone) - - if e, a := expectedPodName, name; e != a { - t.Fatalf("%d: pod name: expected '%v', got '%v'", i, e, a) - } + portForwardFuncDone := make(chan struct{}) - if e, a := testUID, uid; test.uid && e != string(a) { - t.Fatalf("%d: uid: expected '%v', got '%v'", i, e, a) - } - - p, err := strconv.ParseInt(test.port, 10, 32) - if err != nil { - t.Fatalf("%d: error parsing port string '%s': %v", i, test.port, err) - } - if e, a := int32(p), port; e != a { - t.Fatalf("%d: port: expected '%v', got '%v'", i, e, a) + fw.fakeKubelet.getPortForwardCheck = func(name, namespace string, uid types.UID, opts portforward.V4Options) { + assert.Equal(t, podName, name, "pod name") + assert.Equal(t, podNamespace, namespace, "pod namespace") + if test.uid { + assert.Equal(t, testUID, string(uid), "uid") + } } - if test.clientData != "" { - fromClient := make([]byte, 32) - n, err := stream.Read(fromClient) - if err != nil { - t.Fatalf("%d: error reading client data: %v", i, err) + ss.fakeRuntime.portForwardFunc = func(podSandboxID string, port int32, stream io.ReadWriteCloser) error { + defer close(portForwardFuncDone) + assert.Equal(t, testPodSandboxID, podSandboxID, "pod sandbox id") + // The port should be valid if it reaches here. + testPort, err := strconv.ParseInt(test.port, 10, 32) + require.NoError(t, err, "parse port") + assert.Equal(t, int32(testPort), port, "port") + + if test.clientData != "" { + fromClient := make([]byte, 32) + n, err := stream.Read(fromClient) + assert.NoError(t, err, "reading client data") + assert.Equal(t, test.clientData, string(fromClient[0:n]), "client data") } - if e, a := test.clientData, string(fromClient[0:n]); e != a { - t.Fatalf("%d: client data: expected to receive '%v', got '%v'", i, e, a) + + if test.containerData != "" { + _, err := stream.Write([]byte(test.containerData)) + assert.NoError(t, err, "writing container data") } + + return nil } - if test.containerData != "" { - _, err := stream.Write([]byte(test.containerData)) - if err != nil { - t.Fatalf("%d: error writing container data: %v", i, err) - } + var url string + if test.uid { + url = fmt.Sprintf("%s/portForward/%s/%s/%s", fw.testHTTPServer.URL, podNamespace, podName, testUID) + } else { + url = fmt.Sprintf("%s/portForward/%s/%s", fw.testHTTPServer.URL, podNamespace, podName) } - return nil - } + var ( + upgradeRoundTripper httpstream.UpgradeRoundTripper + c *http.Client + ) - var url string - if test.uid { - url = fmt.Sprintf("%s/portForward/%s/%s/%s", fw.testHTTPServer.URL, podNamespace, podName, testUID) - } else { - url = fmt.Sprintf("%s/portForward/%s/%s", fw.testHTTPServer.URL, podNamespace, podName) - } + if test.redirect { + c = &http.Client{} + // Don't follow redirects, since we want to inspect the redirect response. + c.CheckRedirect = func(*http.Request, []*http.Request) error { + return http.ErrUseLastResponse + } + } else { + upgradeRoundTripper = spdy.NewRoundTripper(nil, true) + c = &http.Client{Transport: upgradeRoundTripper} + } - var ( - upgradeRoundTripper httpstream.UpgradeRoundTripper - c *http.Client - ) + resp, err := c.Post(url, "", nil) + require.NoError(t, err, "POSTing") + defer resp.Body.Close() - if len(test.responseLocation) > 0 { - c = &http.Client{} - // Don't follow redirects, since we want to inspect the redirect response. - c.CheckRedirect = func(*http.Request, []*http.Request) error { - return http.ErrUseLastResponse + if test.redirect { + assert.Equal(t, http.StatusFound, resp.StatusCode, "status code") + return + } else { + assert.Equal(t, http.StatusSwitchingProtocols, resp.StatusCode, "status code") } - } else { - upgradeRoundTripper = spdy.NewRoundTripper(nil, true) - c = &http.Client{Transport: upgradeRoundTripper} - } - - resp, err := c.Post(url, "", nil) - if err != nil { - t.Fatalf("%d: Got error POSTing: %v", i, err) - } - defer resp.Body.Close() - if test.responseLocation != "" { - assert.Equal(t, http.StatusFound, resp.StatusCode, "%d: status code", i) - assert.Equal(t, test.responseLocation, resp.Header.Get("Location"), "%d: location", i) - continue - } else { - assert.Equal(t, http.StatusSwitchingProtocols, resp.StatusCode, "%d: status code", i) - } + conn, err := upgradeRoundTripper.NewConnection(resp) + require.NoError(t, err, "creating streaming connection") + defer conn.Close() - conn, err := upgradeRoundTripper.NewConnection(resp) - if err != nil { - t.Fatalf("Unexpected error creating streaming connection: %s", err) - } - if conn == nil { - t.Fatalf("%d: Unexpected nil connection", i) - } - defer conn.Close() - - headers := http.Header{} - headers.Set("streamType", "error") - headers.Set("port", test.port) - errorStream, err := conn.CreateStream(headers) - _ = errorStream - haveErr := err != nil - if e, a := test.shouldError, haveErr; e != a { - t.Fatalf("%d: create stream: expected err=%t, got %t: %v", i, e, a, err) - } + headers := http.Header{} + headers.Set("streamType", "error") + headers.Set("port", test.port) + _, err = conn.CreateStream(headers) + assert.Equal(t, test.shouldError, err != nil, "expect error") - if test.shouldError { - continue - } + if test.shouldError { + return + } - headers.Set("streamType", "data") - headers.Set("port", test.port) - dataStream, err := conn.CreateStream(headers) - haveErr = err != nil - if e, a := test.shouldError, haveErr; e != a { - t.Fatalf("%d: create stream: expected err=%t, got %t: %v", i, e, a, err) - } + headers.Set("streamType", "data") + headers.Set("port", test.port) + dataStream, err := conn.CreateStream(headers) + require.NoError(t, err, "create stream") - if test.clientData != "" { - _, err := dataStream.Write([]byte(test.clientData)) - if err != nil { - t.Fatalf("%d: unexpected error writing client data: %v", i, err) + if test.clientData != "" { + _, err := dataStream.Write([]byte(test.clientData)) + assert.NoError(t, err, "writing client data") } - } - if test.containerData != "" { - fromContainer := make([]byte, 32) - n, err := dataStream.Read(fromContainer) - if err != nil { - t.Fatalf("%d: unexpected error reading container data: %v", i, err) - } - if e, a := test.containerData, string(fromContainer[0:n]); e != a { - t.Fatalf("%d: expected to receive '%v' from container, got '%v'", i, e, a) + if test.containerData != "" { + fromContainer := make([]byte, 32) + n, err := dataStream.Read(fromContainer) + assert.NoError(t, err, "reading container data") + assert.Equal(t, test.containerData, string(fromContainer[0:n]), "container data") } - } - <-portForwardFuncDone + <-portForwardFuncDone + }) } } @@ -1643,7 +1603,7 @@ func TestCRIHandler(t *testing.T) { } func TestDebuggingDisabledHandlers(t *testing.T) { - fw := newServerTestWithDebug(false) + fw := newServerTestWithDebug(false, false, nil) defer fw.testHTTPServer.Close() paths := []string{ diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/server_websocket_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/server_websocket_test.go index 058b67d97..daf6d356b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/server_websocket_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/server_websocket_test.go @@ -23,11 +23,13 @@ import ( "strconv" "sync" "testing" - "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/net/websocket" "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/kubelet/server/portforward" ) const ( @@ -36,152 +38,114 @@ const ( ) func TestServeWSPortForward(t *testing.T) { - tests := []struct { + tests := map[string]struct { port string uid bool clientData string containerData string shouldError bool }{ - {port: "", shouldError: true}, - {port: "abc", shouldError: true}, - {port: "-1", shouldError: true}, - {port: "65536", shouldError: true}, - {port: "0", shouldError: true}, - {port: "1", shouldError: false}, - {port: "8000", shouldError: false}, - {port: "8000", clientData: "client data", containerData: "container data", shouldError: false}, - {port: "65535", shouldError: false}, - {port: "65535", uid: true, shouldError: false}, + "no port": {port: "", shouldError: true}, + "none number port": {port: "abc", shouldError: true}, + "negative port": {port: "-1", shouldError: true}, + "too large port": {port: "65536", shouldError: true}, + "0 port": {port: "0", shouldError: true}, + "min port": {port: "1", shouldError: false}, + "normal port": {port: "8000", shouldError: false}, + "normal port with data forward": {port: "8000", clientData: "client data", containerData: "container data", shouldError: false}, + "max port": {port: "65535", shouldError: false}, + "normal port with uid": {port: "8000", uid: true, shouldError: false}, } podNamespace := "other" podName := "foo" - expectedPodName := getPodName(podName, podNamespace) - expectedUid := "9b01b80f-8fb4-11e4-95ab-4200af06647" - for i, test := range tests { - fw := newServerTest() - defer fw.testHTTPServer.Close() - - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 0 - } - - portForwardFuncDone := make(chan struct{}) - - fw.fakeKubelet.portForwardFunc = func(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error { - defer close(portForwardFuncDone) - - if e, a := expectedPodName, name; e != a { - t.Fatalf("%d: pod name: expected '%v', got '%v'", i, e, a) - } - - if e, a := expectedUid, uid; test.uid && e != string(a) { - t.Fatalf("%d: uid: expected '%v', got '%v'", i, e, a) - } - - p, err := strconv.ParseInt(test.port, 10, 32) - if err != nil { - t.Fatalf("%d: error parsing port string '%s': %v", i, test.port, err) - } - if e, a := int32(p), port; e != a { - t.Fatalf("%d: port: expected '%v', got '%v'", i, e, a) - } - - if test.clientData != "" { - fromClient := make([]byte, 32) - n, err := stream.Read(fromClient) - if err != nil { - t.Fatalf("%d: error reading client data: %v", i, err) - } - if e, a := test.clientData, string(fromClient[0:n]); e != a { - t.Fatalf("%d: client data: expected to receive '%v', got '%v'", i, e, a) + for desc, test := range tests { + test := test + t.Run(desc, func(t *testing.T) { + ss, err := newTestStreamingServer(0) + require.NoError(t, err) + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, false, ss) + defer fw.testHTTPServer.Close() + + portForwardFuncDone := make(chan struct{}) + + fw.fakeKubelet.getPortForwardCheck = func(name, namespace string, uid types.UID, opts portforward.V4Options) { + assert.Equal(t, podName, name, "pod name") + assert.Equal(t, podNamespace, namespace, "pod namespace") + if test.uid { + assert.Equal(t, testUID, string(uid), "uid") } } - if test.containerData != "" { - _, err := stream.Write([]byte(test.containerData)) - if err != nil { - t.Fatalf("%d: error writing container data: %v", i, err) + ss.fakeRuntime.portForwardFunc = func(podSandboxID string, port int32, stream io.ReadWriteCloser) error { + defer close(portForwardFuncDone) + assert.Equal(t, testPodSandboxID, podSandboxID, "pod sandbox id") + // The port should be valid if it reaches here. + testPort, err := strconv.ParseInt(test.port, 10, 32) + require.NoError(t, err, "parse port") + assert.Equal(t, int32(testPort), port, "port") + + if test.clientData != "" { + fromClient := make([]byte, 32) + n, err := stream.Read(fromClient) + assert.NoError(t, err, "reading client data") + assert.Equal(t, test.clientData, string(fromClient[0:n]), "client data") } - } - return nil - } + if test.containerData != "" { + _, err := stream.Write([]byte(test.containerData)) + assert.NoError(t, err, "writing container data") + } - var url string - if test.uid { - url = fmt.Sprintf("ws://%s/portForward/%s/%s/%s?port=%s", fw.testHTTPServer.Listener.Addr().String(), podNamespace, podName, expectedUid, test.port) - } else { - url = fmt.Sprintf("ws://%s/portForward/%s/%s?port=%s", fw.testHTTPServer.Listener.Addr().String(), podNamespace, podName, test.port) - } + return nil + } - ws, err := websocket.Dial(url, "", "http://127.0.0.1/") - if test.shouldError { - if err == nil { - t.Fatalf("%d: websocket dial expected err", i) + var url string + if test.uid { + url = fmt.Sprintf("ws://%s/portForward/%s/%s/%s?port=%s", fw.testHTTPServer.Listener.Addr().String(), podNamespace, podName, testUID, test.port) + } else { + url = fmt.Sprintf("ws://%s/portForward/%s/%s?port=%s", fw.testHTTPServer.Listener.Addr().String(), podNamespace, podName, test.port) } - continue - } else if err != nil { - t.Fatalf("%d: websocket dial unexpected err: %v", i, err) - } - defer ws.Close() + ws, err := websocket.Dial(url, "", "http://127.0.0.1/") + assert.Equal(t, test.shouldError, err != nil, "websocket dial") + if test.shouldError { + return + } + defer ws.Close() - p, err := strconv.ParseUint(test.port, 10, 16) - if err != nil { - t.Fatalf("%d: error parsing port string '%s': %v", i, test.port, err) - } - p16 := uint16(p) + p, err := strconv.ParseUint(test.port, 10, 16) + require.NoError(t, err, "parse port") + p16 := uint16(p) - channel, data, err := wsRead(ws) - if err != nil { - t.Fatalf("%d: read failed: expected no error: got %v", i, err) - } - if channel != dataChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", i, channel, dataChannel) - } - if len(data) != binary.Size(p16) { - t.Fatalf("%d: wrong data size: got %q: expected %d", i, data, binary.Size(p16)) - } - if e, a := p16, binary.LittleEndian.Uint16(data); e != a { - t.Fatalf("%d: wrong data: got %q: expected %s", i, data, test.port) - } + channel, data, err := wsRead(ws) + require.NoError(t, err, "read") + assert.Equal(t, dataChannel, int(channel), "channel") + assert.Len(t, data, binary.Size(p16), "data size") + assert.Equal(t, p16, binary.LittleEndian.Uint16(data), "data") - channel, data, err = wsRead(ws) - if err != nil { - t.Fatalf("%d: read succeeded: expected no error: got %v", i, err) - } - if channel != errorChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", i, channel, errorChannel) - } - if len(data) != binary.Size(p16) { - t.Fatalf("%d: wrong data size: got %q: expected %d", i, data, binary.Size(p16)) - } - if e, a := p16, binary.LittleEndian.Uint16(data); e != a { - t.Fatalf("%d: wrong data: got %q: expected %s", i, data, test.port) - } + channel, data, err = wsRead(ws) + assert.NoError(t, err, "read") + assert.Equal(t, errorChannel, int(channel), "channel") + assert.Len(t, data, binary.Size(p16), "data size") + assert.Equal(t, p16, binary.LittleEndian.Uint16(data), "data") - if test.clientData != "" { - println("writing the client data") - err := wsWrite(ws, dataChannel, []byte(test.clientData)) - if err != nil { - t.Fatalf("%d: unexpected error writing client data: %v", i, err) + if test.clientData != "" { + println("writing the client data") + err := wsWrite(ws, dataChannel, []byte(test.clientData)) + assert.NoError(t, err, "writing client data") } - } - if test.containerData != "" { - _, data, err = wsRead(ws) - if err != nil { - t.Fatalf("%d: unexpected error reading container data: %v", i, err) - } - if e, a := test.containerData, string(data); e != a { - t.Fatalf("%d: expected to receive '%v' from container, got '%v'", i, e, a) + if test.containerData != "" { + _, data, err = wsRead(ws) + assert.NoError(t, err, "reading container data") + assert.Equal(t, test.containerData, string(data), "container data") } - } - <-portForwardFuncDone + <-portForwardFuncDone + }) } } @@ -190,27 +154,27 @@ func TestServeWSMultiplePortForward(t *testing.T) { ports := []uint16{7000, 8000, 9000} podNamespace := "other" podName := "foo" - expectedPodName := getPodName(podName, podNamespace) - fw := newServerTest() + ss, err := newTestStreamingServer(0) + require.NoError(t, err) + defer ss.testHTTPServer.Close() + fw := newServerTestWithDebug(true, false, ss) defer fw.testHTTPServer.Close() - fw.fakeKubelet.streamingConnectionIdleTimeoutFunc = func() time.Duration { - return 0 - } - portForwardWG := sync.WaitGroup{} portForwardWG.Add(len(ports)) portsMutex := sync.Mutex{} portsForwarded := map[int32]struct{}{} - fw.fakeKubelet.portForwardFunc = func(name string, uid types.UID, port int32, stream io.ReadWriteCloser) error { - defer portForwardWG.Done() + fw.fakeKubelet.getPortForwardCheck = func(name, namespace string, uid types.UID, opts portforward.V4Options) { + assert.Equal(t, podName, name, "pod name") + assert.Equal(t, podNamespace, namespace, "pod namespace") + } - if e, a := expectedPodName, name; e != a { - t.Fatalf("%d: pod name: expected '%v', got '%v'", port, e, a) - } + ss.fakeRuntime.portForwardFunc = func(podSandboxID string, port int32, stream io.ReadWriteCloser) error { + defer portForwardWG.Done() + assert.Equal(t, testPodSandboxID, podSandboxID, "pod sandbox id") portsMutex.Lock() portsForwarded[port] = struct{}{} @@ -218,17 +182,11 @@ func TestServeWSMultiplePortForward(t *testing.T) { fromClient := make([]byte, 32) n, err := stream.Read(fromClient) - if err != nil { - t.Fatalf("%d: error reading client data: %v", port, err) - } - if e, a := fmt.Sprintf("client data on port %d", port), string(fromClient[0:n]); e != a { - t.Fatalf("%d: client data: expected to receive '%v', got '%v'", port, e, a) - } + assert.NoError(t, err, "reading client data") + assert.Equal(t, fmt.Sprintf("client data on port %d", port), string(fromClient[0:n]), "client data") _, err = stream.Write([]byte(fmt.Sprintf("container data on port %d", port))) - if err != nil { - t.Fatalf("%d: error writing container data: %v", port, err) - } + assert.NoError(t, err, "writing container data") return nil } @@ -239,70 +197,42 @@ func TestServeWSMultiplePortForward(t *testing.T) { } ws, err := websocket.Dial(url, "", "http://127.0.0.1/") - if err != nil { - t.Fatalf("websocket dial unexpected err: %v", err) - } + require.NoError(t, err, "websocket dial") defer ws.Close() for i, port := range ports { channel, data, err := wsRead(ws) - if err != nil { - t.Fatalf("%d: read failed: expected no error: got %v", i, err) - } - if int(channel) != i*2+dataChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", i, channel, i*2+dataChannel) - } - if len(data) != binary.Size(port) { - t.Fatalf("%d: wrong data size: got %q: expected %d", i, data, binary.Size(port)) - } - if e, a := port, binary.LittleEndian.Uint16(data); e != a { - t.Fatalf("%d: wrong data: got %q: expected %d", i, data, port) - } + assert.NoError(t, err, "port %d read", port) + assert.Equal(t, i*2+dataChannel, int(channel), "port %d channel", port) + assert.Len(t, data, binary.Size(port), "port %d data size", port) + assert.Equal(t, binary.LittleEndian.Uint16(data), port, "port %d data", port) channel, data, err = wsRead(ws) - if err != nil { - t.Fatalf("%d: read succeeded: expected no error: got %v", i, err) - } - if int(channel) != i*2+errorChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", i, channel, i*2+errorChannel) - } - if len(data) != binary.Size(port) { - t.Fatalf("%d: wrong data size: got %q: expected %d", i, data, binary.Size(port)) - } - if e, a := port, binary.LittleEndian.Uint16(data); e != a { - t.Fatalf("%d: wrong data: got %q: expected %d", i, data, port) - } + assert.NoError(t, err, "port %d read", port) + assert.Equal(t, i*2+errorChannel, int(channel), "port %d channel", port) + assert.Len(t, data, binary.Size(port), "port %d data size", port) + assert.Equal(t, binary.LittleEndian.Uint16(data), port, "port %d data", port) } for i, port := range ports { - println("writing the client data", port) + t.Logf("port %d writing the client data", port) err := wsWrite(ws, byte(i*2+dataChannel), []byte(fmt.Sprintf("client data on port %d", port))) - if err != nil { - t.Fatalf("%d: unexpected error writing client data: %v", i, err) - } + assert.NoError(t, err, "port %d write client data", port) channel, data, err := wsRead(ws) - if err != nil { - t.Fatalf("%d: unexpected error reading container data: %v", i, err) - } - - if int(channel) != i*2+dataChannel { - t.Fatalf("%d: wrong channel: got %q: expected %q", port, channel, i*2+dataChannel) - } - if e, a := fmt.Sprintf("container data on port %d", port), string(data); e != a { - t.Fatalf("%d: expected to receive '%v' from container, got '%v'", i, e, a) - } + assert.NoError(t, err, "port %d read container data", port) + assert.Equal(t, i*2+dataChannel, int(channel), "port %d channel", port) + assert.Equal(t, fmt.Sprintf("container data on port %d", port), string(data), "port %d container data", port) } portForwardWG.Wait() portsMutex.Lock() defer portsMutex.Unlock() - if len(ports) != len(portsForwarded) { - t.Fatalf("expected to forward %d ports; got %v", len(ports), portsForwarded) - } + assert.Len(t, portsForwarded, len(ports), "all ports forwarded") } + func wsWrite(conn *websocket.Conn, channel byte, data []byte) error { frame := make([]byte, len(data)+1) frame[0] = channel diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/stats/handler.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/stats/handler.go index ba2033c95..f069cd898 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/stats/handler.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/stats/handler.go @@ -84,6 +84,10 @@ type StatsProvider interface { // GetPodCgroupRoot returns the literal cgroupfs value for the cgroup containing all pods GetPodCgroupRoot() string + + // GetPodByCgroupfs provides the pod that maps to the specified cgroup literal, as well + // as whether the pod was found. + GetPodByCgroupfs(cgroupfs string) (*v1.Pod, bool) } type handler struct { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/stats/testing/mock_stats_provider.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/stats/testing/mock_stats_provider.go index 2923df963..a50ad43b3 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/stats/testing/mock_stats_provider.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/stats/testing/mock_stats_provider.go @@ -25,7 +25,6 @@ import v1 "github.com/google/cadvisor/info/v1" import v1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" import volume "k8s.io/kubernetes/pkg/volume" -// DO NOT EDIT // GENERATED BY mockery // StatsProvider is an autogenerated mock type for the StatsProvider type @@ -65,6 +64,12 @@ func (_m *StatsProvider) GetCgroupStats(cgroupName string, updateStats bool) (*v return r0, r1, r2 } +// GetPodByCgroupfs provides the pod that maps to the specified cgroup, as well +// as whether the pod was found. +func (_m *StatsProvider) GetPodByCgroupfs(cgroupfs string) (*corev1.Pod, bool) { + return nil, false +} + // GetContainerInfo provides a mock function with given fields: podFullName, uid, containerName, req func (_m *StatsProvider) GetContainerInfo(podFullName string, uid types.UID, containerName string, req *v1.ContainerInfoRequest) (*v1.ContainerInfo, error) { ret := _m.Called(podFullName, uid, containerName, req) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/BUILD index 64e176022..36150aef2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/BUILD @@ -21,6 +21,7 @@ go_library( "//vendor/github.com/emicklei/go-restful:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/google.golang.org/grpc/codes:go_default_library", + "//vendor/google.golang.org/grpc/status:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/remotecommand:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/errors.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/errors.go index 9f16b4eb2..62bcef790 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/errors.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/errors.go @@ -23,15 +23,16 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) func ErrorStreamingDisabled(method string) error { - return grpc.Errorf(codes.NotFound, fmt.Sprintf("streaming method %s disabled", method)) + return status.Errorf(codes.NotFound, fmt.Sprintf("streaming method %s disabled", method)) } // The error returned when the maximum number of in-flight requests is exceeded. func ErrorTooManyInFlight() error { - return grpc.Errorf(codes.ResourceExhausted, "maximum number of in-flight requests exceeded") + return status.Errorf(codes.ResourceExhausted, "maximum number of in-flight requests exceeded") } // Translates a CRI streaming error into an appropriate HTTP response. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/server.go b/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/server.go index 64bd52f33..7cbc424c4 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/server.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/server/streaming/server.go @@ -20,13 +20,14 @@ import ( "crypto/tls" "errors" "io" + "net" "net/http" "net/url" "path" "time" - "google.golang.org/grpc" "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" restful "github.com/emicklei/go-restful" @@ -71,6 +72,7 @@ type Config struct { Addr string // The optional base URL for constructing streaming URLs. If empty, the baseURL will be // constructed from the serve address. + // Note that for port "0", the URL port will be set to actual port in use. BaseURL *url.URL // How long to leave idle connections open for. @@ -160,15 +162,15 @@ type server struct { func validateExecRequest(req *runtimeapi.ExecRequest) error { if req.ContainerId == "" { - return grpc.Errorf(codes.InvalidArgument, "missing required container_id") + return status.Errorf(codes.InvalidArgument, "missing required container_id") } if req.Tty && req.Stderr { // If TTY is set, stderr cannot be true because multiplexing is not // supported. - return grpc.Errorf(codes.InvalidArgument, "tty and stderr cannot both be true") + return status.Errorf(codes.InvalidArgument, "tty and stderr cannot both be true") } if !req.Stdin && !req.Stdout && !req.Stderr { - return grpc.Errorf(codes.InvalidArgument, "one of stdin, stdout, or stderr must be set") + return status.Errorf(codes.InvalidArgument, "one of stdin, stdout, or stderr must be set") } return nil } @@ -188,15 +190,15 @@ func (s *server) GetExec(req *runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, func validateAttachRequest(req *runtimeapi.AttachRequest) error { if req.ContainerId == "" { - return grpc.Errorf(codes.InvalidArgument, "missing required container_id") + return status.Errorf(codes.InvalidArgument, "missing required container_id") } if req.Tty && req.Stderr { // If TTY is set, stderr cannot be true because multiplexing is not // supported. - return grpc.Errorf(codes.InvalidArgument, "tty and stderr cannot both be true") + return status.Errorf(codes.InvalidArgument, "tty and stderr cannot both be true") } if !req.Stdin && !req.Stdout && !req.Stderr { - return grpc.Errorf(codes.InvalidArgument, "one of stdin, stdout, and stderr must be set") + return status.Errorf(codes.InvalidArgument, "one of stdin, stdout, and stderr must be set") } return nil } @@ -216,7 +218,7 @@ func (s *server) GetAttach(req *runtimeapi.AttachRequest) (*runtimeapi.AttachRes func (s *server) GetPortForward(req *runtimeapi.PortForwardRequest) (*runtimeapi.PortForwardResponse, error) { if req.PodSandboxId == "" { - return nil, grpc.Errorf(codes.InvalidArgument, "missing required pod_sandbox_id") + return nil, status.Errorf(codes.InvalidArgument, "missing required pod_sandbox_id") } token, err := s.cache.Insert(req) if err != nil { @@ -233,10 +235,16 @@ func (s *server) Start(stayUp bool) error { return errors.New("stayUp=false is not yet implemented") } + listener, err := net.Listen("tcp", s.config.Addr) + if err != nil { + return err + } + // Use the actual address as baseURL host. This handles the "0" port case. + s.config.BaseURL.Host = listener.Addr().String() if s.config.TLSConfig != nil { - return s.server.ListenAndServeTLS("", "") // Use certs from TLSConfig. + return s.server.ServeTLS(listener, "", "") // Use certs from TLSConfig. } else { - return s.server.ListenAndServe() + return s.server.Serve(listener) } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/BUILD index 8bbca05b2..8cee7f265 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/BUILD @@ -55,13 +55,11 @@ go_library( "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/kuberuntime:go_default_library", "//pkg/kubelet/leaky:go_default_library", - "//pkg/kubelet/network:go_default_library", "//pkg/kubelet/pod:go_default_library", "//pkg/kubelet/server/stats:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/volume:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/golang/protobuf/proto:go_default_library", "//vendor/github.com/google/cadvisor/fs:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/google/cadvisor/info/v2:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cadvisor_stats_provider.go b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cadvisor_stats_provider.go index 67da08d40..8529872cd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cadvisor_stats_provider.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cadvisor_stats_provider.go @@ -255,9 +255,14 @@ func isPodManagedContainer(cinfo *cadvisorapiv2.ContainerInfo) bool { func getCadvisorPodInfoFromPodUID(podUID types.UID, infos map[string]cadvisorapiv2.ContainerInfo) *cadvisorapiv2.ContainerInfo { for key, info := range infos { if cm.IsSystemdStyleName(key) { - key = cm.RevertFromSystemdToCgroupStyleName(key) + // Convert to internal cgroup name and take the last component only. + internalCgroupName := cm.ParseSystemdToCgroupName(key) + key = internalCgroupName[len(internalCgroupName)-1] + } else { + // Take last component only. + key = path.Base(key) } - if cm.GetPodCgroupNameSuffix(podUID) == path.Base(key) { + if cm.GetPodCgroupNameSuffix(podUID) == key { return &info } } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cri_stats_provider.go b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cri_stats_provider.go index 1ed2e300e..1af0a0cbf 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cri_stats_provider.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cri_stats_provider.go @@ -25,7 +25,6 @@ import ( "time" "github.com/golang/glog" - "github.com/golang/protobuf/proto" cadvisorfs "github.com/google/cadvisor/fs" cadvisorapiv2 "github.com/google/cadvisor/info/v2" @@ -143,12 +142,14 @@ func (p *criStatsProvider) ListPodStats() ([]statsapi.PodStats, error) { ps, found := sandboxIDToPodStats[podSandboxID] if !found { ps = buildPodStats(podSandbox) - // Fill stats from cadvisor is available for full set of required pod stats - p.addCadvisorPodNetworkStats(ps, podSandboxID, caInfos) - p.addCadvisorPodCPUMemoryStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos) sandboxIDToPodStats[podSandboxID] = ps } + + // Fill available stats for full set of required pod stats cs := p.makeContainerStats(stats, container, &rootFsInfo, fsIDtoInfo, podSandbox.GetMetadata().GetUid()) + p.addPodNetworkStats(ps, podSandboxID, caInfos, cs) + p.addPodCPUMemoryStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs) + // If cadvisor stats is available for the container, use it to populate // container stats caStats, caFound := caInfos[containerID] @@ -264,29 +265,69 @@ func (p *criStatsProvider) makePodStorageStats(s *statsapi.PodStats, rootFsInfo return s } -func (p *criStatsProvider) addCadvisorPodNetworkStats( +func (p *criStatsProvider) addPodNetworkStats( ps *statsapi.PodStats, podSandboxID string, caInfos map[string]cadvisorapiv2.ContainerInfo, + cs *statsapi.ContainerStats, ) { caPodSandbox, found := caInfos[podSandboxID] + // try get network stats from cadvisor first. if found { ps.Network = cadvisorInfoToNetworkStats(ps.PodRef.Name, &caPodSandbox) - } else { - glog.V(4).Infof("Unable to find cadvisor stats for sandbox %q", podSandboxID) + return } + + // TODO: sum Pod network stats from container stats. + glog.V(4).Infof("Unable to find cadvisor stats for sandbox %q", podSandboxID) } -func (p *criStatsProvider) addCadvisorPodCPUMemoryStats( +func (p *criStatsProvider) addPodCPUMemoryStats( ps *statsapi.PodStats, podUID types.UID, allInfos map[string]cadvisorapiv2.ContainerInfo, + cs *statsapi.ContainerStats, ) { + // try get cpu and memory stats from cadvisor first. podCgroupInfo := getCadvisorPodInfoFromPodUID(podUID, allInfos) if podCgroupInfo != nil { cpu, memory := cadvisorInfoToCPUandMemoryStats(podCgroupInfo) ps.CPU = cpu ps.Memory = memory + return + } + + // Sum Pod cpu and memory stats from containers stats. + if cs.CPU != nil { + if ps.CPU == nil { + ps.CPU = &statsapi.CPUStats{} + } + + ps.CPU.Time = cs.StartTime + usageCoreNanoSeconds := getUint64Value(cs.CPU.UsageCoreNanoSeconds) + getUint64Value(ps.CPU.UsageCoreNanoSeconds) + usageNanoCores := getUint64Value(cs.CPU.UsageNanoCores) + getUint64Value(ps.CPU.UsageNanoCores) + ps.CPU.UsageCoreNanoSeconds = &usageCoreNanoSeconds + ps.CPU.UsageNanoCores = &usageNanoCores + } + + if cs.Memory != nil { + if ps.Memory == nil { + ps.Memory = &statsapi.MemoryStats{} + } + + ps.Memory.Time = cs.Memory.Time + availableBytes := getUint64Value(cs.Memory.AvailableBytes) + getUint64Value(ps.Memory.AvailableBytes) + usageBytes := getUint64Value(cs.Memory.UsageBytes) + getUint64Value(ps.Memory.UsageBytes) + workingSetBytes := getUint64Value(cs.Memory.WorkingSetBytes) + getUint64Value(ps.Memory.WorkingSetBytes) + rSSBytes := getUint64Value(cs.Memory.RSSBytes) + getUint64Value(ps.Memory.RSSBytes) + pageFaults := getUint64Value(cs.Memory.PageFaults) + getUint64Value(ps.Memory.PageFaults) + majorPageFaults := getUint64Value(cs.Memory.MajorPageFaults) + getUint64Value(ps.Memory.MajorPageFaults) + ps.Memory.AvailableBytes = &availableBytes + ps.Memory.UsageBytes = &usageBytes + ps.Memory.WorkingSetBytes = &workingSetBytes + ps.Memory.RSSBytes = &rSSBytes + ps.Memory.PageFaults = &pageFaults + ps.Memory.MajorPageFaults = &majorPageFaults } } @@ -301,15 +342,9 @@ func (p *criStatsProvider) makeContainerStats( Name: stats.Attributes.Metadata.Name, // The StartTime in the summary API is the container creation time. StartTime: metav1.NewTime(time.Unix(0, container.CreatedAt)), - // Work around heapster bug. https://github.com/kubernetes/kubernetes/issues/54962 - // TODO(random-liu): Remove this after heapster is updated to newer than 1.5.0-beta.0. - CPU: &statsapi.CPUStats{ - UsageNanoCores: proto.Uint64(0), - }, - Memory: &statsapi.MemoryStats{ - RSSBytes: proto.Uint64(0), - }, - Rootfs: &statsapi.FsStats{}, + CPU: &statsapi.CPUStats{}, + Memory: &statsapi.MemoryStats{}, + Rootfs: &statsapi.FsStats{}, // UserDefinedMetrics is not supported by CRI. } if stats.Cpu != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cri_stats_provider_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cri_stats_provider_test.go index 3ce0b2378..9e1dd1bb8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cri_stats_provider_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/cri_stats_provider_test.go @@ -18,6 +18,7 @@ package stats import ( "math/rand" + "runtime" "testing" "time" @@ -464,6 +465,9 @@ func checkCRINetworkStats(assert *assert.Assertions, actual *statsapi.NetworkSta } func checkCRIPodCPUAndMemoryStats(assert *assert.Assertions, actual statsapi.PodStats, cs *cadvisorapiv2.ContainerStats) { + if runtime.GOOS != "linux" { + return + } assert.Equal(cs.Timestamp.UnixNano(), actual.CPU.Time.UnixNano()) assert.Equal(cs.Cpu.Usage.Total, *actual.CPU.UsageCoreNanoSeconds) assert.Equal(cs.CpuInst.Usage.Total, *actual.CPU.UsageNanoCores) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/helper.go b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/helper.go index cee923722..a195b9c63 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/stats/helper.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/stats/helper.go @@ -27,9 +27,13 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" "k8s.io/kubernetes/pkg/kubelet/cadvisor" - "k8s.io/kubernetes/pkg/kubelet/network" ) +// defaultNetworkInterfaceName is used for collectng network stats. +// This logic relies on knowledge of the container runtime implementation and +// is not reliable. +const defaultNetworkInterfaceName = "eth0" + func cadvisorInfoToCPUandMemoryStats(info *cadvisorapiv2.ContainerInfo) (*statsapi.CPUStats, *statsapi.MemoryStats) { cstat, found := latestContainerStats(info) if !found { @@ -153,7 +157,7 @@ func cadvisorInfoToNetworkStats(name string, info *cadvisorapiv2.ContainerInfo) TxErrors: &inter.TxErrors, } - if inter.Name == network.DefaultInterfaceName { + if inter.Name == defaultNetworkInterfaceName { iStats.InterfaceStats = iStat } @@ -299,3 +303,11 @@ func buildRootfsStats(cstat *cadvisorapiv2.ContainerStats, imageFs *cadvisorapiv Inodes: imageFs.Inodes, } } + +func getUint64Value(value *uint64) uint64 { + if value == nil { + return 0 + } + + return *value +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/status/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/status/BUILD index ccc78651f..63e32a391 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/status/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/status/BUILD @@ -19,6 +19,7 @@ go_library( "//pkg/kubelet/pod:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/format:go_default_library", + "//pkg/util/pod:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/status/generate.go b/vendor/k8s.io/kubernetes/pkg/kubelet/status/generate.go index c094a95d8..8d9415d22 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/status/generate.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/status/generate.go @@ -29,15 +29,16 @@ const ( PodCompleted = "PodCompleted" ContainersNotReady = "ContainersNotReady" ContainersNotInitialized = "ContainersNotInitialized" + ReadinessGatesNotReady = "ReadinessGatesNotReady" ) -// GeneratePodReadyCondition returns ready condition if all containers in a pod are ready, else it -// returns an unready condition. -func GeneratePodReadyCondition(spec *v1.PodSpec, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition { +// GenerateContainersReadyCondition returns the status of "ContainersReady" condition. +// The status of "ContainersReady" condition is true when all containers are ready. +func GenerateContainersReadyCondition(spec *v1.PodSpec, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition { // Find if all containers are ready or not. if containerStatuses == nil { return v1.PodCondition{ - Type: v1.PodReady, + Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: UnknownContainerStatuses, } @@ -57,12 +58,13 @@ func GeneratePodReadyCondition(spec *v1.PodSpec, containerStatuses []v1.Containe // If all containers are known and succeeded, just return PodCompleted. if podPhase == v1.PodSucceeded && len(unknownContainers) == 0 { return v1.PodCondition{ - Type: v1.PodReady, + Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: PodCompleted, } } + // Generate message for containers in unknown condition. unreadyMessages := []string{} if len(unknownContainers) > 0 { unreadyMessages = append(unreadyMessages, fmt.Sprintf("containers with unknown status: %s", unknownContainers)) @@ -73,13 +75,57 @@ func GeneratePodReadyCondition(spec *v1.PodSpec, containerStatuses []v1.Containe unreadyMessage := strings.Join(unreadyMessages, ", ") if unreadyMessage != "" { return v1.PodCondition{ - Type: v1.PodReady, + Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: ContainersNotReady, Message: unreadyMessage, } } + return v1.PodCondition{ + Type: v1.ContainersReady, + Status: v1.ConditionTrue, + } +} + +// GeneratePodReadyCondition returns "Ready" condition of a pod. +// The status of "Ready" condition is "True", if all containers in a pod are ready +// AND all matching conditions specified in the ReadinessGates have status equal to "True". +func GeneratePodReadyCondition(spec *v1.PodSpec, conditions []v1.PodCondition, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition { + containersReady := GenerateContainersReadyCondition(spec, containerStatuses, podPhase) + // If the status of ContainersReady is not True, return the same status, reason and message as ContainersReady. + if containersReady.Status != v1.ConditionTrue { + return v1.PodCondition{ + Type: v1.PodReady, + Status: containersReady.Status, + Reason: containersReady.Reason, + Message: containersReady.Message, + } + } + + // Evaluate corresponding conditions specified in readiness gate + // Generate message if any readiness gate is not satisfied. + unreadyMessages := []string{} + for _, rg := range spec.ReadinessGates { + _, c := podutil.GetPodConditionFromList(conditions, rg.ConditionType) + if c == nil { + unreadyMessages = append(unreadyMessages, fmt.Sprintf("corresponding condition of pod readiness gate %q does not exist.", string(rg.ConditionType))) + } else if c.Status != v1.ConditionTrue { + unreadyMessages = append(unreadyMessages, fmt.Sprintf("the status of pod readiness gate %q is not \"True\", but %v", string(rg.ConditionType), c.Status)) + } + } + + // Set "Ready" condition to "False" if any readiness gate is not ready. + if len(unreadyMessages) != 0 { + unreadyMessage := strings.Join(unreadyMessages, ", ") + return v1.PodCondition{ + Type: v1.PodReady, + Status: v1.ConditionFalse, + Reason: ReadinessGatesNotReady, + Message: unreadyMessage, + } + } + return v1.PodCondition{ Type: v1.PodReady, Status: v1.ConditionTrue, diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/status/generate_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/status/generate_test.go index 9b0b61cdb..a8a191d1b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/status/generate_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/status/generate_test.go @@ -24,24 +24,119 @@ import ( "k8s.io/api/core/v1" ) +func TestGenerateContainersReadyCondition(t *testing.T) { + tests := []struct { + spec *v1.PodSpec + containerStatuses []v1.ContainerStatus + podPhase v1.PodPhase + expectReady v1.PodCondition + }{ + { + spec: nil, + containerStatuses: nil, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, UnknownContainerStatuses, ""), + }, + { + spec: &v1.PodSpec{}, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + }, + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [1234]"), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + {Name: "5678"}, + }, + }, + containerStatuses: []v1.ContainerStatus{ + getReadyStatus("1234"), + getReadyStatus("5678"), + }, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + {Name: "5678"}, + }, + }, + containerStatuses: []v1.ContainerStatus{ + getReadyStatus("1234"), + }, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [5678]"), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + {Name: "5678"}, + }, + }, + containerStatuses: []v1.ContainerStatus{ + getReadyStatus("1234"), + getNotReadyStatus("5678"), + }, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, ContainersNotReady, "containers with unready status: [5678]"), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + }, + }, + containerStatuses: []v1.ContainerStatus{ + getNotReadyStatus("1234"), + }, + podPhase: v1.PodSucceeded, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, PodCompleted, ""), + }, + } + + for i, test := range tests { + ready := GenerateContainersReadyCondition(test.spec, test.containerStatuses, test.podPhase) + if !reflect.DeepEqual(ready, test.expectReady) { + t.Errorf("On test case %v, expectReady:\n%+v\ngot\n%+v\n", i, test.expectReady, ready) + } + } +} + func TestGeneratePodReadyCondition(t *testing.T) { tests := []struct { spec *v1.PodSpec + conditions []v1.PodCondition containerStatuses []v1.ContainerStatus podPhase v1.PodPhase - expected v1.PodCondition + expectReady v1.PodCondition }{ { spec: nil, + conditions: nil, containerStatuses: nil, podPhase: v1.PodRunning, - expected: getReadyCondition(false, UnknownContainerStatuses, ""), + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, UnknownContainerStatuses, ""), }, { spec: &v1.PodSpec{}, + conditions: nil, containerStatuses: []v1.ContainerStatus{}, podPhase: v1.PodRunning, - expected: getReadyCondition(true, "", ""), + expectReady: getPodCondition(v1.PodReady, v1.ConditionTrue, "", ""), }, { spec: &v1.PodSpec{ @@ -49,9 +144,10 @@ func TestGeneratePodReadyCondition(t *testing.T) { {Name: "1234"}, }, }, + conditions: nil, containerStatuses: []v1.ContainerStatus{}, podPhase: v1.PodRunning, - expected: getReadyCondition(false, ContainersNotReady, "containers with unknown status: [1234]"), + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [1234]"), }, { spec: &v1.PodSpec{ @@ -60,12 +156,13 @@ func TestGeneratePodReadyCondition(t *testing.T) { {Name: "5678"}, }, }, + conditions: nil, containerStatuses: []v1.ContainerStatus{ getReadyStatus("1234"), getReadyStatus("5678"), }, - podPhase: v1.PodRunning, - expected: getReadyCondition(true, "", ""), + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionTrue, "", ""), }, { spec: &v1.PodSpec{ @@ -74,11 +171,12 @@ func TestGeneratePodReadyCondition(t *testing.T) { {Name: "5678"}, }, }, + conditions: nil, containerStatuses: []v1.ContainerStatus{ getReadyStatus("1234"), }, - podPhase: v1.PodRunning, - expected: getReadyCondition(false, ContainersNotReady, "containers with unknown status: [5678]"), + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [5678]"), }, { spec: &v1.PodSpec{ @@ -87,12 +185,13 @@ func TestGeneratePodReadyCondition(t *testing.T) { {Name: "5678"}, }, }, + conditions: nil, containerStatuses: []v1.ContainerStatus{ getReadyStatus("1234"), getNotReadyStatus("5678"), }, - podPhase: v1.PodRunning, - expected: getReadyCondition(false, ContainersNotReady, "containers with unready status: [5678]"), + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ContainersNotReady, "containers with unready status: [5678]"), }, { spec: &v1.PodSpec{ @@ -100,18 +199,116 @@ func TestGeneratePodReadyCondition(t *testing.T) { {Name: "1234"}, }, }, + conditions: nil, containerStatuses: []v1.ContainerStatus{ getNotReadyStatus("1234"), }, - podPhase: v1.PodSucceeded, - expected: getReadyCondition(false, PodCompleted, ""), + podPhase: v1.PodSucceeded, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, PodCompleted, ""), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + }, + }, + conditions: nil, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ReadinessGatesNotReady, `corresponding condition of pod readiness gate "gate1" does not exist.`), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionFalse, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ReadinessGatesNotReady, `the status of pod readiness gate "gate1" is not "True", but False`), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + {ConditionType: v1.PodConditionType("gate2")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ReadinessGatesNotReady, `corresponding condition of pod readiness gate "gate2" does not exist.`), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + {ConditionType: v1.PodConditionType("gate2")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + getPodCondition("gate2", v1.ConditionFalse, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ReadinessGatesNotReady, `the status of pod readiness gate "gate2" is not "True", but False`), + }, + { + spec: &v1.PodSpec{ + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + {ConditionType: v1.PodConditionType("gate2")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + getPodCondition("gate2", v1.ConditionTrue, "", ""), + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + }, + ReadinessGates: []v1.PodReadinessGate{ + {ConditionType: v1.PodConditionType("gate1")}, + }, + }, + conditions: []v1.PodCondition{ + getPodCondition("gate1", v1.ConditionTrue, "", ""), + }, + containerStatuses: []v1.ContainerStatus{getNotReadyStatus("1234")}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.PodReady, v1.ConditionFalse, ContainersNotReady, "containers with unready status: [1234]"), }, } for i, test := range tests { - condition := GeneratePodReadyCondition(test.spec, test.containerStatuses, test.podPhase) - if !reflect.DeepEqual(condition, test.expected) { - t.Errorf("On test case %v, expected:\n%+v\ngot\n%+v\n", i, test.expected, condition) + ready := GeneratePodReadyCondition(test.spec, test.conditions, test.containerStatuses, test.podPhase) + if !reflect.DeepEqual(ready, test.expectReady) { + t.Errorf("On test case %v, expectReady:\n%+v\ngot\n%+v\n", i, test.expectReady, ready) } } } @@ -220,13 +417,9 @@ func TestGeneratePodInitializedCondition(t *testing.T) { } } -func getReadyCondition(ready bool, reason, message string) v1.PodCondition { - status := v1.ConditionFalse - if ready { - status = v1.ConditionTrue - } +func getPodCondition(conditionType v1.PodConditionType, status v1.ConditionStatus, reason, message string) v1.PodCondition { return v1.PodCondition{ - Type: v1.PodReady, + Type: conditionType, Status: status, Reason: reason, Message: message, diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager.go index eaf5b9a05..1dbfc6aa5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager.go @@ -37,6 +37,7 @@ import ( kubepod "k8s.io/kubernetes/pkg/kubelet/pod" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" + statusutil "k8s.io/kubernetes/pkg/util/pod" ) // A wrapper around v1.PodStatus that includes a version to enforce that stale pod statuses are @@ -121,11 +122,22 @@ func NewManager(kubeClient clientset.Interface, podManager kubepod.Manager, podD } } -// isStatusEqual returns true if the given pod statuses are equal, false otherwise. +// isPodStatusByKubeletEqual returns true if the given pod statuses are equal when non-kubelet-owned +// pod conditions are excluded. // This method normalizes the status before comparing so as to make sure that meaningless // changes will be ignored. -func isStatusEqual(oldStatus, status *v1.PodStatus) bool { - return apiequality.Semantic.DeepEqual(status, oldStatus) +func isPodStatusByKubeletEqual(oldStatus, status *v1.PodStatus) bool { + oldCopy := oldStatus.DeepCopy() + for _, c := range status.Conditions { + if kubetypes.PodConditionByKubelet(c.Type) { + _, oc := podutil.GetPodCondition(oldCopy, c.Type) + if oc == nil || oc.Status != c.Status { + return false + } + } + } + oldCopy.Conditions = status.Conditions + return apiequality.Semantic.DeepEqual(oldCopy, status) } func (m *manager) Start() { @@ -162,6 +174,13 @@ func (m *manager) GetPodStatus(uid types.UID) (v1.PodStatus, bool) { func (m *manager) SetPodStatus(pod *v1.Pod, status v1.PodStatus) { m.podStatusesLock.Lock() defer m.podStatusesLock.Unlock() + + for _, c := range pod.Status.Conditions { + if !kubetypes.PodConditionByKubelet(c.Type) { + glog.Errorf("Kubelet is trying to update pod condition %q for pod %q. "+ + "But it is not owned by kubelet.", string(c.Type), format.Pod(pod)) + } + } // Make sure we're caching a deep copy. status = *status.DeepCopy() @@ -207,22 +226,24 @@ func (m *manager) SetContainerReadiness(podUID types.UID, containerID kubecontai containerStatus, _, _ = findContainerStatus(&status, containerID.String()) containerStatus.Ready = ready - // Update pod condition. - readyConditionIndex := -1 - for i, condition := range status.Conditions { - if condition.Type == v1.PodReady { - readyConditionIndex = i - break + // updateConditionFunc updates the corresponding type of condition + updateConditionFunc := func(conditionType v1.PodConditionType, condition v1.PodCondition) { + conditionIndex := -1 + for i, condition := range status.Conditions { + if condition.Type == conditionType { + conditionIndex = i + break + } + } + if conditionIndex != -1 { + status.Conditions[conditionIndex] = condition + } else { + glog.Warningf("PodStatus missing %s type condition: %+v", conditionType, status) + status.Conditions = append(status.Conditions, condition) } } - readyCondition := GeneratePodReadyCondition(&pod.Spec, status.ContainerStatuses, status.Phase) - if readyConditionIndex != -1 { - status.Conditions[readyConditionIndex] = readyCondition - } else { - glog.Warningf("PodStatus missing PodReady condition: %+v", status) - status.Conditions = append(status.Conditions, readyCondition) - } - + updateConditionFunc(v1.PodReady, GeneratePodReadyCondition(&pod.Spec, status.Conditions, status.ContainerStatuses, status.Phase)) + updateConditionFunc(v1.ContainersReady, GenerateContainersReadyCondition(&pod.Spec, status.ContainerStatuses, status.Phase)) m.updateStatusInternal(pod, status, false) } @@ -336,7 +357,7 @@ func (m *manager) updateStatusInternal(pod *v1.Pod, status v1.PodStatus, forceUp normalizeStatus(pod, &status) // The intent here is to prevent concurrent updates to a pod's status from // clobbering each other so the phase of a pod progresses monotonically. - if isCached && isStatusEqual(&cachedStatus.status, &status) && !forceUpdate { + if isCached && isPodStatusByKubeletEqual(&cachedStatus.status, &status) && !forceUpdate { glog.V(3).Infof("Ignoring same status for pod %q, status: %+v", format.Pod(pod), status) return false // No new status. } @@ -469,9 +490,10 @@ func (m *manager) syncPod(uid types.UID, status versionedPodStatus) { m.deletePodStatus(uid) return } - pod.Status = status.status - // TODO: handle conflict as a retry, make that easier too. - newPod, err := m.kubeClient.CoreV1().Pods(pod.Namespace).UpdateStatus(pod) + + oldStatus := pod.Status.DeepCopy() + newPod, patchBytes, err := statusutil.PatchPodStatus(m.kubeClient, pod.Namespace, pod.Name, *oldStatus, mergePodStatus(*oldStatus, status.status)) + glog.V(3).Infof("Patch status for pod %q with %q", format.Pod(pod), patchBytes) if err != nil { glog.Warningf("Failed to update status for pod %q: %v", format.Pod(pod), err) return @@ -546,7 +568,7 @@ func (m *manager) needsReconcile(uid types.UID, status v1.PodStatus) bool { podStatus := pod.Status.DeepCopy() normalizeStatus(pod, podStatus) - if isStatusEqual(podStatus, &status) { + if isPodStatusByKubeletEqual(podStatus, &status) { // If the status from the source is the same with the cached status, // reconcile is not needed. Just return. return false @@ -559,7 +581,7 @@ func (m *manager) needsReconcile(uid types.UID, status v1.PodStatus) bool { // We add this function, because apiserver only supports *RFC3339* now, which means that the timestamp returned by // apiserver has no nanosecond information. However, the timestamp returned by metav1.Now() contains nanosecond, -// so when we do comparison between status from apiserver and cached status, isStatusEqual() will always return false. +// so when we do comparison between status from apiserver and cached status, isPodStatusByKubeletEqual() will always return false. // There is related issue #15262 and PR #15263 about this. // In fact, the best way to solve this is to do it on api side. However, for now, we normalize the status locally in // kubelet temporarily. @@ -613,3 +635,36 @@ func normalizeStatus(pod *v1.Pod, status *v1.PodStatus) *v1.PodStatus { kubetypes.SortInitContainerStatuses(pod, status.InitContainerStatuses) return status } + +// mergePodStatus merges oldPodStatus and newPodStatus where pod conditions +// not owned by kubelet is preserved from oldPodStatus +func mergePodStatus(oldPodStatus, newPodStatus v1.PodStatus) v1.PodStatus { + podConditions := []v1.PodCondition{} + for _, c := range oldPodStatus.Conditions { + if !kubetypes.PodConditionByKubelet(c.Type) { + podConditions = append(podConditions, c) + } + } + + for _, c := range newPodStatus.Conditions { + if kubetypes.PodConditionByKubelet(c.Type) { + podConditions = append(podConditions, c) + } + } + newPodStatus.Conditions = podConditions + return newPodStatus +} + +// NeedToReconcilePodReadiness returns if the pod "Ready" condition need to be reconcile +func NeedToReconcilePodReadiness(pod *v1.Pod) bool { + if len(pod.Spec.ReadinessGates) == 0 { + return false + } + podReadyCondition := GeneratePodReadyCondition(&pod.Spec, pod.Status.Conditions, pod.Status.ContainerStatuses, pod.Status.Phase) + i, curCondition := podutil.GetPodConditionFromList(pod.Status.Conditions, v1.PodReady) + // Only reconcile if "Ready" condition is present + if i >= 0 && curCondition.Status != podReadyCondition.Status { + return true + } + return false +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager_test.go index 6e68b20d5..03f79b2a1 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager_test.go @@ -19,6 +19,7 @@ package status import ( "fmt" "math/rand" + "reflect" "strconv" "strings" "testing" @@ -48,6 +49,10 @@ import ( // Generate new instance of test pod with the same initial value. func getTestPod() *v1.Pod { return &v1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: "v1", + }, ObjectMeta: metav1.ObjectMeta{ UID: "12345678", Name: "foo", @@ -75,7 +80,7 @@ func (m *manager) testSyncBatch() { } func newTestManager(kubeClient clientset.Interface) *manager { - podManager := kubepod.NewBasicPodManager(podtest.NewFakeMirrorClient(), kubesecret.NewFakeManager(), kubeconfigmap.NewFakeManager()) + podManager := kubepod.NewBasicPodManager(podtest.NewFakeMirrorClient(), kubesecret.NewFakeManager(), kubeconfigmap.NewFakeManager(), podtest.NewMockCheckpointManager()) podManager.AddPod(getTestPod()) return NewManager(kubeClient, podManager, &statustest.FakePodDeletionSafetyProvider{}).(*manager) } @@ -303,7 +308,7 @@ func TestSyncPod(t *testing.T) { testPod := getTestPod() syncer.kubeClient = fake.NewSimpleClientset(testPod) syncer.SetPodStatus(testPod, getRandomPodStatus()) - verifyActions(t, syncer, []core.Action{getAction(), updateAction()}) + verifyActions(t, syncer, []core.Action{getAction(), patchAction()}) } func TestSyncPodChecksMismatchedUID(t *testing.T) { @@ -357,18 +362,18 @@ func TestSyncPodNoDeadlock(t *testing.T) { t.Logf("Pod not deleted (success case).") ret = getTestPod() m.SetPodStatus(pod, getRandomPodStatus()) - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Pod is terminated, but still running.") - pod.DeletionTimestamp = new(metav1.Time) + pod.DeletionTimestamp = &metav1.Time{Time: time.Now()} m.SetPodStatus(pod, getRandomPodStatus()) - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Pod is terminated successfully.") pod.Status.ContainerStatuses[0].State.Running = nil pod.Status.ContainerStatuses[0].State.Terminated = &v1.ContainerStateTerminated{} m.SetPodStatus(pod, getRandomPodStatus()) - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Error case.") ret = nil @@ -392,7 +397,7 @@ func TestStaleUpdates(t *testing.T) { t.Logf("sync batch before syncPods pushes latest status, so we should see three statuses in the channel, but only one update") m.syncBatch() verifyUpdates(t, m, 3) - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Nothing left in the channel to sync") verifyActions(t, m, []core.Action{}) @@ -406,7 +411,7 @@ func TestStaleUpdates(t *testing.T) { m.SetPodStatus(pod, status) m.syncBatch() - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("Nothing stuck in the pipe.") verifyUpdates(t, m, 0) @@ -443,10 +448,27 @@ func TestStatusEquality(t *testing.T) { } normalizeStatus(&pod, &oldPodStatus) normalizeStatus(&pod, &podStatus) - if !isStatusEqual(&oldPodStatus, &podStatus) { + if !isPodStatusByKubeletEqual(&oldPodStatus, &podStatus) { t.Fatalf("Order of container statuses should not affect normalized equality.") } } + + oldPodStatus := podStatus + podStatus.Conditions = append(podStatus.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("www.example.com/feature"), + Status: v1.ConditionTrue, + }) + + oldPodStatus.Conditions = append(podStatus.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("www.example.com/feature"), + Status: v1.ConditionFalse, + }) + + normalizeStatus(&pod, &oldPodStatus) + normalizeStatus(&pod, &podStatus) + if !isPodStatusByKubeletEqual(&oldPodStatus, &podStatus) { + t.Fatalf("Differences in pod condition not owned by kubelet should not affect normalized equality.") + } } func TestStatusNormalizationEnforcesMaxBytes(t *testing.T) { @@ -507,7 +529,7 @@ func TestStaticPod(t *testing.T) { t.Logf("Should be able to get the static pod status from status manager") retrievedStatus := expectPodStatus(t, m, staticPod) normalizeStatus(staticPod, &status) - assert.True(t, isStatusEqual(&status, &retrievedStatus), "Expected: %+v, Got: %+v", status, retrievedStatus) + assert.True(t, isPodStatusByKubeletEqual(&status, &retrievedStatus), "Expected: %+v, Got: %+v", status, retrievedStatus) t.Logf("Should not sync pod in syncBatch because there is no corresponding mirror pod for the static pod.") m.syncBatch() @@ -520,10 +542,10 @@ func TestStaticPod(t *testing.T) { t.Logf("Should be able to get the mirror pod status from status manager") retrievedStatus, _ = m.GetPodStatus(mirrorPod.UID) - assert.True(t, isStatusEqual(&status, &retrievedStatus), "Expected: %+v, Got: %+v", status, retrievedStatus) + assert.True(t, isPodStatusByKubeletEqual(&status, &retrievedStatus), "Expected: %+v, Got: %+v", status, retrievedStatus) t.Logf("Should sync pod because the corresponding mirror pod is created") - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) t.Logf("syncBatch should not sync any pods because nothing is changed.") m.testSyncBatch() @@ -741,7 +763,7 @@ func TestReconcilePodStatus(t *testing.T) { t.Errorf("Pod status is different, a reconciliation is needed") } syncer.syncBatch() - verifyActions(t, syncer, []core.Action{getAction(), updateAction()}) + verifyActions(t, syncer, []core.Action{getAction(), patchAction()}) } func expectPodStatus(t *testing.T, m *manager, pod *v1.Pod) v1.PodStatus { @@ -755,18 +777,16 @@ func expectPodStatus(t *testing.T, m *manager, pod *v1.Pod) v1.PodStatus { func TestDeletePods(t *testing.T) { pod := getTestPod() t.Logf("Set the deletion timestamp.") - pod.DeletionTimestamp = new(metav1.Time) + pod.DeletionTimestamp = &metav1.Time{Time: time.Now()} client := fake.NewSimpleClientset(pod) m := newTestManager(client) m.podManager.AddPod(pod) - status := getRandomPodStatus() now := metav1.Now() status.StartTime = &now m.SetPodStatus(pod, status) - t.Logf("Expect to see a delete action.") - verifyActions(t, m, []core.Action{getAction(), updateAction(), deleteAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction(), deleteAction()}) } func TestDoNotDeleteMirrorPods(t *testing.T) { @@ -779,7 +799,7 @@ func TestDoNotDeleteMirrorPods(t *testing.T) { kubetypes.ConfigMirrorAnnotationKey: "mirror", } t.Logf("Set the deletion timestamp.") - mirrorPod.DeletionTimestamp = new(metav1.Time) + mirrorPod.DeletionTimestamp = &metav1.Time{Time: time.Now()} client := fake.NewSimpleClientset(mirrorPod) m := newTestManager(client) m.podManager.AddPod(staticPod) @@ -795,7 +815,7 @@ func TestDoNotDeleteMirrorPods(t *testing.T) { m.SetPodStatus(staticPod, status) t.Logf("Expect not to see a delete action.") - verifyActions(t, m, []core.Action{getAction(), updateAction()}) + verifyActions(t, m, []core.Action{getAction(), patchAction()}) } func TestUpdateLastTransitionTime(t *testing.T) { @@ -867,6 +887,197 @@ func updateAction() core.UpdateAction { return core.UpdateActionImpl{ActionImpl: core.ActionImpl{Verb: "update", Resource: schema.GroupVersionResource{Resource: "pods"}, Subresource: "status"}} } +func patchAction() core.PatchAction { + return core.PatchActionImpl{ActionImpl: core.ActionImpl{Verb: "patch", Resource: schema.GroupVersionResource{Resource: "pods"}, Subresource: "status"}} +} + func deleteAction() core.DeleteAction { return core.DeleteActionImpl{ActionImpl: core.ActionImpl{Verb: "delete", Resource: schema.GroupVersionResource{Resource: "pods"}}} } + +func TestMergePodStatus(t *testing.T) { + useCases := []struct { + desc string + oldPodStatus func(input v1.PodStatus) v1.PodStatus + newPodStatus func(input v1.PodStatus) v1.PodStatus + expectPodStatus v1.PodStatus + }{ + { + "no change", + func(input v1.PodStatus) v1.PodStatus { return input }, + func(input v1.PodStatus) v1.PodStatus { return input }, + getPodStatus(), + }, + { + "readiness changes", + func(input v1.PodStatus) v1.PodStatus { return input }, + func(input v1.PodStatus) v1.PodStatus { + input.Conditions[0].Status = v1.ConditionFalse + return input + }, + v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionFalse, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + }, + }, + { + "additional pod condition", + func(input v1.PodStatus) v1.PodStatus { + input.Conditions = append(input.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }) + return input + }, + func(input v1.PodStatus) v1.PodStatus { return input }, + v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + }, + }, + { + "additional pod condition and readiness changes", + func(input v1.PodStatus) v1.PodStatus { + input.Conditions = append(input.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }) + return input + }, + func(input v1.PodStatus) v1.PodStatus { + input.Conditions[0].Status = v1.ConditionFalse + return input + }, + v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionFalse, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + }, + }, + { + "additional pod condition changes", + func(input v1.PodStatus) v1.PodStatus { + input.Conditions = append(input.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }) + return input + }, + func(input v1.PodStatus) v1.PodStatus { + input.Conditions = append(input.Conditions, v1.PodCondition{ + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionFalse, + }) + return input + }, + v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodConditionType("example.com/feature"), + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + }, + }, + } + + for _, tc := range useCases { + output := mergePodStatus(tc.oldPodStatus(getPodStatus()), tc.newPodStatus(getPodStatus())) + if !conditionsEqual(output.Conditions, tc.expectPodStatus.Conditions) || !statusEqual(output, tc.expectPodStatus) { + t.Errorf("test case %q failed, expect: %+v, got %+v", tc.desc, tc.expectPodStatus, output) + } + } + +} + +func statusEqual(left, right v1.PodStatus) bool { + left.Conditions = nil + right.Conditions = nil + return reflect.DeepEqual(left, right) +} + +func conditionsEqual(left, right []v1.PodCondition) bool { + if len(left) != len(right) { + return false + } + + for _, l := range left { + found := false + for _, r := range right { + if l.Type == r.Type { + found = true + if l.Status != r.Status { + return false + } + } + } + if !found { + return false + } + } + return true +} + +func getPodStatus() v1.PodStatus { + return v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + }, + Message: "Message", + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/BUILD index 949a75823..f8c52b92d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/BUILD @@ -15,9 +15,8 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/kubelet/sysctl", deps = [ - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/apis/core/validation:go_default_library", - "//pkg/apis/extensions/validation:go_default_library", + "//pkg/apis/policy/validation:go_default_library", "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", ], @@ -30,7 +29,7 @@ go_test( "whitelist_test.go", ], embed = [":go_default_library"], - deps = ["//vendor/k8s.io/api/core/v1:go_default_library"], + deps = ["//pkg/security/podsecuritypolicy/sysctl:go_default_library"], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/runtime.go b/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/runtime.go index 7ccbbdf53..8b37c65c5 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/runtime.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/runtime.go @@ -19,7 +19,6 @@ package sysctl import ( "fmt" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/lifecycle" ) @@ -31,7 +30,6 @@ const ( dockerMinimumAPIVersion = "1.24.0" dockerTypeName = "docker" - rktTypeName = "rkt" ) // TODO: The admission logic in this file is runtime-dependent. It should be @@ -72,14 +70,6 @@ func NewRuntimeAdmitHandler(runtime container.Runtime) (*runtimeAdmitHandler, er Message: "Docker API version before 1.24 does not support sysctls", }, }, nil - case rktTypeName: - return &runtimeAdmitHandler{ - result: lifecycle.PodAdmitResult{ - Admit: false, - Reason: UnsupportedReason, - Message: "Rkt does not support sysctls", - }, - }, nil default: // Return admit for other runtimes. return &runtimeAdmitHandler{ @@ -92,17 +82,11 @@ func NewRuntimeAdmitHandler(runtime container.Runtime) (*runtimeAdmitHandler, er // Admit checks whether the runtime supports sysctls. func (w *runtimeAdmitHandler) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult { - sysctls, unsafeSysctls, err := v1helper.SysctlsFromPodAnnotations(attrs.Pod.Annotations) - if err != nil { - return lifecycle.PodAdmitResult{ - Admit: false, - Reason: AnnotationInvalidReason, - Message: fmt.Sprintf("invalid sysctl annotation: %v", err), - } - } + if attrs.Pod.Spec.SecurityContext != nil { - if len(sysctls)+len(unsafeSysctls) > 0 { - return w.result + if len(attrs.Pod.Spec.SecurityContext.Sysctls) > 0 { + return w.result + } } return lifecycle.PodAdmitResult{ diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/whitelist.go b/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/whitelist.go index e236f7952..067409a7e 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/whitelist.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/whitelist.go @@ -20,9 +20,8 @@ import ( "fmt" "strings" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/apis/core/validation" - extvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" + policyvalidation "k8s.io/kubernetes/pkg/apis/policy/validation" "k8s.io/kubernetes/pkg/kubelet/lifecycle" ) @@ -31,44 +30,29 @@ const ( ForbiddenReason = "SysctlForbidden" ) -// SafeSysctlWhitelist returns the whitelist of safe sysctls and safe sysctl patterns (ending in *). -// -// A sysctl is called safe iff -// - it is namespaced in the container or the pod -// - it is isolated, i.e. has no influence on any other pod on the same node. -func SafeSysctlWhitelist() []string { - return []string{ - "kernel.shm_rmid_forced", - "net.ipv4.ip_local_port_range", - "net.ipv4.tcp_syncookies", - } -} - // patternWhitelist takes a list of sysctls or sysctl patterns (ending in *) and // checks validity via a sysctl and prefix map, rejecting those which are not known // to be namespaced. type patternWhitelist struct { - sysctls map[string]Namespace - prefixes map[string]Namespace - annotationKey string + sysctls map[string]Namespace + prefixes map[string]Namespace } var _ lifecycle.PodAdmitHandler = &patternWhitelist{} // NewWhitelist creates a new Whitelist from a list of sysctls and sysctl pattern (ending in *). -func NewWhitelist(patterns []string, annotationKey string) (*patternWhitelist, error) { +func NewWhitelist(patterns []string) (*patternWhitelist, error) { w := &patternWhitelist{ - sysctls: map[string]Namespace{}, - prefixes: map[string]Namespace{}, - annotationKey: annotationKey, + sysctls: map[string]Namespace{}, + prefixes: map[string]Namespace{}, } for _, s := range patterns { - if !extvalidation.IsValidSysctlPattern(s) { + if !policyvalidation.IsValidSysctlPattern(s) { return nil, fmt.Errorf("sysctl %q must have at most %d characters and match regex %s", s, validation.SysctlMaxLength, - extvalidation.SysctlPatternFmt, + policyvalidation.SysctlPatternFmt, ) } if strings.HasSuffix(s, "*") { @@ -121,32 +105,22 @@ func (w *patternWhitelist) validateSysctl(sysctl string, hostNet, hostIPC bool) return fmt.Errorf("%q not whitelisted", sysctl) } -// Admit checks that all sysctls given in annotations v1.SysctlsPodAnnotationKey and v1.UnsafeSysctlsPodAnnotationKey +// Admit checks that all sysctls given in pod's security context // are valid according to the whitelist. func (w *patternWhitelist) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult { pod := attrs.Pod - a := pod.Annotations[w.annotationKey] - if a == "" { + if pod.Spec.SecurityContext == nil || len(pod.Spec.SecurityContext.Sysctls) == 0 { return lifecycle.PodAdmitResult{ Admit: true, } } - sysctls, err := v1helper.SysctlsFromPodAnnotation(a) - if err != nil { - return lifecycle.PodAdmitResult{ - Admit: false, - Reason: AnnotationInvalidReason, - Message: fmt.Sprintf("invalid %s annotation: %v", w.annotationKey, err), - } - } - var hostNet, hostIPC bool if pod.Spec.SecurityContext != nil { hostNet = pod.Spec.HostNetwork hostIPC = pod.Spec.HostIPC } - for _, s := range sysctls { + for _, s := range pod.Spec.SecurityContext.Sysctls { if err := w.validateSysctl(s.Name, hostNet, hostIPC); err != nil { return lifecycle.PodAdmitResult{ Admit: false, diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/whitelist_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/whitelist_test.go index 77f253337..0b6401e34 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/whitelist_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/sysctl/whitelist_test.go @@ -19,7 +19,7 @@ package sysctl import ( "testing" - "k8s.io/api/core/v1" + "k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl" ) func TestNewWhitelist(t *testing.T) { @@ -35,7 +35,7 @@ func TestNewWhitelist(t *testing.T) { {sysctls: []string{"net.*.foo"}, err: true}, {sysctls: []string{"foo"}, err: true}, } { - _, err := NewWhitelist(append(SafeSysctlWhitelist(), test.sysctls...), v1.SysctlsPodAnnotationKey) + _, err := NewWhitelist(append(sysctl.SafeSysctlWhitelist(), test.sysctls...)) if test.err && err == nil { t.Errorf("expected an error creating a whitelist for %v", test.sysctls) } else if !test.err && err != nil { @@ -65,7 +65,7 @@ func TestWhitelist(t *testing.T) { {sysctl: "kernel.sem", hostIPC: true}, } - w, err := NewWhitelist(append(SafeSysctlWhitelist(), "kernel.msg*", "kernel.sem"), v1.SysctlsPodAnnotationKey) + w, err := NewWhitelist(append(sysctl.SafeSysctlWhitelist(), "kernel.msg*", "kernel.sem")) if err != nil { t.Fatalf("failed to create whitelist: %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/token/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/token/BUILD new file mode 100644 index 000000000..d4d812a25 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/token/BUILD @@ -0,0 +1,40 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + srcs = ["token_manager.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/token", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["token_manager_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/authentication/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/token/OWNERS b/vendor/k8s.io/kubernetes/pkg/kubelet/token/OWNERS new file mode 100644 index 000000000..33904f778 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/token/OWNERS @@ -0,0 +1,6 @@ +approvers: +- mikedanese +reviewers: +- mikedanese +- awly +- tallclair diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/token/token_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/token/token_manager.go new file mode 100644 index 000000000..d081bdd14 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/token/token_manager.go @@ -0,0 +1,151 @@ +/* +Copyright 2018 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 token implements a manager of serviceaccount tokens for pods running +// on the node. +package token + +import ( + "errors" + "fmt" + "sync" + "time" + + "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" + "k8s.io/apimachinery/pkg/util/clock" + "k8s.io/apimachinery/pkg/util/wait" + clientset "k8s.io/client-go/kubernetes" +) + +const ( + maxTTL = 24 * time.Hour + gcPeriod = time.Minute +) + +// NewManager returns a new token manager. +func NewManager(c clientset.Interface) *Manager { + m := &Manager{ + getToken: func(name, namespace string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + if c == nil { + return nil, errors.New("cannot use TokenManager when kubelet is in standalone mode") + } + return c.CoreV1().ServiceAccounts(namespace).CreateToken(name, tr) + }, + cache: make(map[string]*authenticationv1.TokenRequest), + clock: clock.RealClock{}, + } + go wait.Forever(m.cleanup, gcPeriod) + return m +} + +// Manager manages service account tokens for pods. +type Manager struct { + + // cacheMutex guards the cache + cacheMutex sync.RWMutex + cache map[string]*authenticationv1.TokenRequest + + // mocked for testing + getToken func(name, namespace string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) + clock clock.Clock +} + +// GetServiceAccountToken gets a service account token for a pod from cache or +// from the TokenRequest API. This process is as follows: +// * Check the cache for the current token request. +// * If the token exists and does not require a refresh, return the current token. +// * Attempt to refresh the token. +// * If the token is refreshed successfully, save it in the cache and return the token. +// * If refresh fails and the old token is still valid, log an error and return the old token. +// * If refresh fails and the old token is no longer valid, return an error +func (m *Manager) GetServiceAccountToken(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + key := keyFunc(name, namespace, tr) + ctr, ok := m.get(key) + + if ok && !m.requiresRefresh(ctr) { + return ctr, nil + } + + tr, err := m.getToken(name, namespace, tr) + if err != nil { + switch { + case !ok: + return nil, fmt.Errorf("failed to fetch token: %v", err) + case m.expired(ctr): + return nil, fmt.Errorf("token %s expired and refresh failed: %v", key, err) + default: + glog.Errorf("couldn't update token %s: %v", key, err) + return ctr, nil + } + } + + m.set(key, tr) + return tr, nil +} + +func (m *Manager) cleanup() { + m.cacheMutex.Lock() + defer m.cacheMutex.Unlock() + for k, tr := range m.cache { + if m.expired(tr) { + delete(m.cache, k) + } + } +} + +func (m *Manager) get(key string) (*authenticationv1.TokenRequest, bool) { + m.cacheMutex.RLock() + defer m.cacheMutex.RUnlock() + ctr, ok := m.cache[key] + return ctr, ok +} + +func (m *Manager) set(key string, tr *authenticationv1.TokenRequest) { + m.cacheMutex.Lock() + defer m.cacheMutex.Unlock() + m.cache[key] = tr +} + +func (m *Manager) expired(t *authenticationv1.TokenRequest) bool { + return m.clock.Now().After(t.Status.ExpirationTimestamp.Time) +} + +// requiresRefresh returns true if the token is older than 80% of its total +// ttl, or if the token is older than 24 hours. +func (m *Manager) requiresRefresh(tr *authenticationv1.TokenRequest) bool { + if tr.Spec.ExpirationSeconds == nil { + glog.Errorf("expiration seconds was nil for tr: %#v", tr) + return false + } + now := m.clock.Now() + exp := tr.Status.ExpirationTimestamp.Time + iat := exp.Add(-1 * time.Duration(*tr.Spec.ExpirationSeconds) * time.Second) + + if now.After(iat.Add(maxTTL)) { + return true + } + // Require a refresh if within 20% of the TTL from the expiration time. + if now.After(exp.Add(-1 * time.Duration((*tr.Spec.ExpirationSeconds*20)/100) * time.Second)) { + return true + } + return false +} + +// keys should be nonconfidential and safe to log +func keyFunc(name, namespace string, tr *authenticationv1.TokenRequest) string { + return fmt.Sprintf("%q/%q/%#v", name, namespace, tr.Spec) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/token/token_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/token/token_manager_test.go new file mode 100644 index 000000000..2d877652d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/token/token_manager_test.go @@ -0,0 +1,223 @@ +/* +Copyright 2018 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 token + +import ( + "fmt" + "testing" + "time" + + authenticationv1 "k8s.io/api/authentication/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/clock" +) + +func TestTokenCachingAndExpiration(t *testing.T) { + type suite struct { + clock *clock.FakeClock + tg *fakeTokenGetter + mgr *Manager + } + + cases := []struct { + name string + exp time.Duration + f func(t *testing.T, s *suite) + }{ + { + name: "rotate hour token expires in the last 12 minutes", + exp: time.Hour, + f: func(t *testing.T, s *suite) { + s.clock.SetTime(s.clock.Now().Add(50 * time.Minute)) + if _, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if s.tg.count != 2 { + t.Fatalf("expected token to be refreshed: call count was %d", s.tg.count) + } + }, + }, + { + name: "rotate 24 hour token that expires in 40 hours", + exp: 40 * time.Hour, + f: func(t *testing.T, s *suite) { + s.clock.SetTime(s.clock.Now().Add(25 * time.Hour)) + if _, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if s.tg.count != 2 { + t.Fatalf("expected token to be refreshed: call count was %d", s.tg.count) + } + }, + }, + { + name: "rotate hour token fails, old token is still valid, doesn't error", + exp: time.Hour, + f: func(t *testing.T, s *suite) { + s.clock.SetTime(s.clock.Now().Add(50 * time.Minute)) + tg := &fakeTokenGetter{ + err: fmt.Errorf("err"), + } + s.mgr.getToken = tg.getToken + tr, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if tr.Status.Token != "foo" { + t.Fatalf("unexpected token: %v", tr.Status.Token) + } + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + clock := clock.NewFakeClock(time.Time{}.Add(30 * 24 * time.Hour)) + expSecs := int64(c.exp.Seconds()) + s := &suite{ + clock: clock, + mgr: NewManager(nil), + tg: &fakeTokenGetter{ + tr: &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + ExpirationSeconds: &expSecs, + }, + Status: authenticationv1.TokenRequestStatus{ + Token: "foo", + ExpirationTimestamp: metav1.Time{Time: clock.Now().Add(c.exp)}, + }, + }, + }, + } + s.mgr.getToken = s.tg.getToken + s.mgr.clock = s.clock + if _, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if s.tg.count != 1 { + t.Fatalf("unexpected client call, got: %d, want: 1", s.tg.count) + } + + if _, err := s.mgr.GetServiceAccountToken("a", "b", &authenticationv1.TokenRequest{}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if s.tg.count != 1 { + t.Fatalf("expected token to be served from cache: saw %d", s.tg.count) + } + + c.f(t, s) + }) + } +} + +func TestRequiresRefresh(t *testing.T) { + start := time.Now() + cases := []struct { + now, exp time.Time + expectRefresh bool + }{ + { + now: start.Add(10 * time.Minute), + exp: start.Add(60 * time.Minute), + expectRefresh: false, + }, + { + now: start.Add(50 * time.Minute), + exp: start.Add(60 * time.Minute), + expectRefresh: true, + }, + { + now: start.Add(25 * time.Hour), + exp: start.Add(60 * time.Hour), + expectRefresh: true, + }, + { + now: start.Add(70 * time.Minute), + exp: start.Add(60 * time.Minute), + expectRefresh: true, + }, + } + + for i, c := range cases { + t.Run(fmt.Sprint(i), func(t *testing.T) { + clock := clock.NewFakeClock(c.now) + secs := int64(c.exp.Sub(start).Seconds()) + tr := &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + ExpirationSeconds: &secs, + }, + Status: authenticationv1.TokenRequestStatus{ + ExpirationTimestamp: metav1.Time{Time: c.exp}, + }, + } + mgr := NewManager(nil) + mgr.clock = clock + + rr := mgr.requiresRefresh(tr) + if rr != c.expectRefresh { + t.Fatalf("unexpected requiresRefresh result, got: %v, want: %v", rr, c.expectRefresh) + } + }) + } +} + +type fakeTokenGetter struct { + count int + tr *authenticationv1.TokenRequest + err error +} + +func (ftg *fakeTokenGetter) getToken(name, namespace string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + ftg.count++ + return ftg.tr, ftg.err +} + +func TestCleanup(t *testing.T) { + cases := []struct { + name string + relativeExp time.Duration + expectedCacheSize int + }{ + { + name: "don't cleanup unexpired tokens", + relativeExp: -1 * time.Hour, + expectedCacheSize: 0, + }, + { + name: "cleanup expired tokens", + relativeExp: time.Hour, + expectedCacheSize: 1, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + clock := clock.NewFakeClock(time.Time{}.Add(24 * time.Hour)) + mgr := NewManager(nil) + mgr.clock = clock + + mgr.set("key", &authenticationv1.TokenRequest{ + Status: authenticationv1.TokenRequestStatus{ + ExpirationTimestamp: metav1.Time{Time: mgr.clock.Now().Add(c.relativeExp)}, + }, + }) + mgr.cleanup() + if got, want := len(mgr.cache), c.expectedCacheSize; got != want { + t.Fatalf("unexpected number of cache entries after cleanup, got: %d, want: %d", got, want) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/types/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/types/BUILD index 762979d5b..b1d5ffd1a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/types/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/types/BUILD @@ -12,13 +12,14 @@ go_library( "constants.go", "doc.go", "labels.go", + "pod_status.go", "pod_update.go", "types.go", ], importpath = "k8s.io/kubernetes/pkg/kubelet/types", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/scheduler/api:go_default_library", + "//pkg/apis/scheduling:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", @@ -29,6 +30,7 @@ go_test( name = "go_default_test", srcs = [ "labels_test.go", + "pod_status_test.go", "pod_update_test.go", "types_test.go", ], diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/types/constants.go b/vendor/k8s.io/kubernetes/pkg/kubelet/types/constants.go index 2c83908a7..f2f703a8d 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/types/constants.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/types/constants.go @@ -22,7 +22,6 @@ const ( // different container runtimes DockerContainerRuntime = "docker" - RktContainerRuntime = "rkt" RemoteContainerRuntime = "remote" // User visible keys for managing node allocatable enforcement on the node. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_status.go b/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_status.go new file mode 100644 index 000000000..8c46ba39e --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_status.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 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 types + +import ( + "k8s.io/api/core/v1" +) + +// PodConditionsByKubelet is the list of pod conditions owned by kubelet +var PodConditionsByKubelet = []v1.PodConditionType{ + v1.PodScheduled, + v1.PodReady, + v1.PodInitialized, + v1.PodReasonUnschedulable, + v1.ContainersReady, +} + +// PodConditionByKubelet returns if the pod condition type is owned by kubelet +func PodConditionByKubelet(conditionType v1.PodConditionType) bool { + for _, c := range PodConditionsByKubelet { + if c == conditionType { + return true + } + } + return false +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_status_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_status_test.go new file mode 100644 index 000000000..61c837748 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_status_test.go @@ -0,0 +1,47 @@ +/* +Copyright 2018 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 types + +import ( + "k8s.io/api/core/v1" + "testing" +) + +func TestPodConditionByKubelet(t *testing.T) { + trueCases := []v1.PodConditionType{ + v1.PodScheduled, + v1.PodReady, + v1.PodInitialized, + v1.PodReasonUnschedulable, + } + + for _, tc := range trueCases { + if !PodConditionByKubelet(tc) { + t.Errorf("Expect %q to be condition owned by kubelet.", tc) + } + } + + falseCases := []v1.PodConditionType{ + v1.PodConditionType("abcd"), + } + + for _, tc := range falseCases { + if PodConditionByKubelet(tc) { + t.Errorf("Expect %q NOT to be condition owned by kubelet.", tc) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update.go b/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update.go index 62116985f..64083315b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update.go @@ -22,7 +22,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeapi "k8s.io/kubernetes/pkg/apis/core" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + "k8s.io/kubernetes/pkg/apis/scheduling" ) const ( @@ -144,7 +144,7 @@ func (sp SyncPodType) String() string { // or equal to SystemCriticalPriority. Both the rescheduler(deprecated in 1.10) and the kubelet use this function // to make admission and scheduling decisions. func IsCriticalPod(pod *v1.Pod) bool { - return IsCritical(pod.Namespace, pod.Annotations) || (pod.Spec.Priority != nil && IsCriticalPodBasedOnPriority(pod.Namespace, *pod.Spec.Priority)) + return IsCritical(pod.Namespace, pod.Annotations) || (pod.Spec.Priority != nil && IsCriticalPodBasedOnPriority(*pod.Spec.Priority)) } // IsCritical returns true if parameters bear the critical pod annotation @@ -163,12 +163,8 @@ func IsCritical(ns string, annotations map[string]string) bool { } // IsCriticalPodBasedOnPriority checks if the given pod is a critical pod based on priority resolved from pod Spec. -func IsCriticalPodBasedOnPriority(ns string, priority int32) bool { - // Critical pods are restricted to "kube-system" namespace as of now. - if ns != kubeapi.NamespaceSystem { - return false - } - if priority >= schedulerapi.SystemCriticalPriority { +func IsCriticalPodBasedOnPriority(priority int32) bool { + if priority >= scheduling.SystemCriticalPriority { return true } return false diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update_test.go index 849995452..b9f4b2613 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update_test.go @@ -176,3 +176,28 @@ func TestIsCriticalPod(t *testing.T) { } } } + +func TestIsCriticalPodBasedOnPriority(t *testing.T) { + tests := []struct { + priority int32 + description string + expected bool + }{ + { + priority: int32(2000000001), + description: "A system critical pod", + expected: true, + }, + { + priority: int32(1000000000), + description: "A non system critical pod", + expected: false, + }, + } + for _, test := range tests { + actual := IsCriticalPodBasedOnPriority(test.priority) + if actual != test.expected { + t.Errorf("IsCriticalPodBased on priority should have returned %v for test %v but got %v", test.expected, test.description, actual) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/util/BUILD index e76e870bb..ff1755ebd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/BUILD @@ -92,9 +92,12 @@ filegroup( "//pkg/kubelet/util/cache:all-srcs", "//pkg/kubelet/util/format:all-srcs", "//pkg/kubelet/util/ioutils:all-srcs", + "//pkg/kubelet/util/manager:all-srcs", + "//pkg/kubelet/util/pluginwatcher:all-srcs", "//pkg/kubelet/util/queue:all-srcs", "//pkg/kubelet/util/sliceutils:all-srcs", "//pkg/kubelet/util/store:all-srcs", ], tags = ["automanaged"], + visibility = ["//visibility:public"], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/BUILD new file mode 100644 index 000000000..e789de207 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/BUILD @@ -0,0 +1,66 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "cache_based_manager.go", + "manager.go", + "watch_based_manager.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubelet/util/manager", + visibility = ["//visibility:public"], + deps = [ + "//pkg/kubelet/util:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/fields: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/util/clock:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/apiserver/pkg/storage/etcd:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "cache_based_manager_test.go", + "watch_based_manager_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//pkg/api/v1/pod:go_default_library", + "//pkg/apis/core/v1:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", + "//vendor/k8s.io/client-go/testing:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/cache_based_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/cache_based_manager.go new file mode 100644 index 000000000..f8c1100f4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/cache_based_manager.go @@ -0,0 +1,272 @@ +/* +Copyright 2018 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 manager + +import ( + "fmt" + "strconv" + "sync" + "time" + + "k8s.io/api/core/v1" + storageetcd "k8s.io/apiserver/pkg/storage/etcd" + "k8s.io/kubernetes/pkg/kubelet/util" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/clock" + "k8s.io/apimachinery/pkg/util/sets" +) + +// GetObjectTTLFunc defines a function to get value of TTL. +type GetObjectTTLFunc func() (time.Duration, bool) + +// GetObjectFunc defines a function to get object with a given namespace and name. +type GetObjectFunc func(string, string, metav1.GetOptions) (runtime.Object, error) + +type objectKey struct { + namespace string + name string +} + +// objectStoreItems is a single item stored in objectStore. +type objectStoreItem struct { + refCount int + data *objectData +} + +type objectData struct { + sync.Mutex + + object runtime.Object + err error + lastUpdateTime time.Time +} + +// objectStore is a local cache of objects. +type objectStore struct { + getObject GetObjectFunc + clock clock.Clock + + lock sync.Mutex + items map[objectKey]*objectStoreItem + + defaultTTL time.Duration + getTTL GetObjectTTLFunc +} + +// NewObjectStore returns a new ttl-based instance of Store interface. +func NewObjectStore(getObject GetObjectFunc, clock clock.Clock, getTTL GetObjectTTLFunc, ttl time.Duration) Store { + return &objectStore{ + getObject: getObject, + clock: clock, + items: make(map[objectKey]*objectStoreItem), + defaultTTL: ttl, + getTTL: getTTL, + } +} + +func isObjectOlder(newObject, oldObject runtime.Object) bool { + if newObject == nil || oldObject == nil { + return false + } + newVersion, _ := storageetcd.Versioner.ObjectResourceVersion(newObject) + oldVersion, _ := storageetcd.Versioner.ObjectResourceVersion(oldObject) + return newVersion < oldVersion +} + +func (s *objectStore) AddReference(namespace, name string) { + key := objectKey{namespace: namespace, name: name} + + // AddReference is called from RegisterPod, thus it needs to be efficient. + // Thus Add() is only increasing refCount and generation of a given object. + // Then Get() is responsible for fetching if needed. + s.lock.Lock() + defer s.lock.Unlock() + item, exists := s.items[key] + if !exists { + item = &objectStoreItem{ + refCount: 0, + data: &objectData{}, + } + s.items[key] = item + } + + item.refCount++ + // This will trigger fetch on the next Get() operation. + item.data = nil +} + +func (s *objectStore) DeleteReference(namespace, name string) { + key := objectKey{namespace: namespace, name: name} + + s.lock.Lock() + defer s.lock.Unlock() + if item, ok := s.items[key]; ok { + item.refCount-- + if item.refCount == 0 { + delete(s.items, key) + } + } +} + +// GetObjectTTLFromNodeFunc returns a function that returns TTL value +// from a given Node object. +func GetObjectTTLFromNodeFunc(getNode func() (*v1.Node, error)) GetObjectTTLFunc { + return func() (time.Duration, bool) { + node, err := getNode() + if err != nil { + return time.Duration(0), false + } + if node != nil && node.Annotations != nil { + if value, ok := node.Annotations[v1.ObjectTTLAnnotationKey]; ok { + if intValue, err := strconv.Atoi(value); err == nil { + return time.Duration(intValue) * time.Second, true + } + } + } + return time.Duration(0), false + } +} + +func (s *objectStore) isObjectFresh(data *objectData) bool { + objectTTL := s.defaultTTL + if ttl, ok := s.getTTL(); ok { + objectTTL = ttl + } + return s.clock.Now().Before(data.lastUpdateTime.Add(objectTTL)) +} + +func (s *objectStore) Get(namespace, name string) (runtime.Object, error) { + key := objectKey{namespace: namespace, name: name} + + data := func() *objectData { + s.lock.Lock() + defer s.lock.Unlock() + item, exists := s.items[key] + if !exists { + return nil + } + if item.data == nil { + item.data = &objectData{} + } + return item.data + }() + if data == nil { + return nil, fmt.Errorf("object %q/%q not registered", namespace, name) + } + + // After updating data in objectStore, lock the data, fetch object if + // needed and return data. + data.Lock() + defer data.Unlock() + if data.err != nil || !s.isObjectFresh(data) { + opts := metav1.GetOptions{} + if data.object != nil && data.err == nil { + // This is just a periodic refresh of an object we successfully fetched previously. + // In this case, server data from apiserver cache to reduce the load on both + // etcd and apiserver (the cache is eventually consistent). + util.FromApiserverCache(&opts) + } + + object, err := s.getObject(namespace, name, opts) + if err != nil && !apierrors.IsNotFound(err) && data.object == nil && data.err == nil { + // Couldn't fetch the latest object, but there is no cached data to return. + // Return the fetch result instead. + return object, err + } + if (err == nil && !isObjectOlder(object, data.object)) || apierrors.IsNotFound(err) { + // If the fetch succeeded with a newer version of the object, or if the + // object could not be found in the apiserver, update the cached data to + // reflect the current status. + data.object = object + data.err = err + data.lastUpdateTime = s.clock.Now() + } + } + return data.object, data.err +} + +// cacheBasedManager keeps a store with objects necessary +// for registered pods. Different implementations of the store +// may result in different semantics for freshness of objects +// (e.g. ttl-based implementation vs watch-based implementation). +type cacheBasedManager struct { + objectStore Store + getReferencedObjects func(*v1.Pod) sets.String + + lock sync.Mutex + registeredPods map[objectKey]*v1.Pod +} + +func (c *cacheBasedManager) GetObject(namespace, name string) (runtime.Object, error) { + return c.objectStore.Get(namespace, name) +} + +func (c *cacheBasedManager) RegisterPod(pod *v1.Pod) { + names := c.getReferencedObjects(pod) + c.lock.Lock() + defer c.lock.Unlock() + for name := range names { + c.objectStore.AddReference(pod.Namespace, name) + } + var prev *v1.Pod + key := objectKey{namespace: pod.Namespace, name: pod.Name} + prev = c.registeredPods[key] + c.registeredPods[key] = pod + if prev != nil { + for name := range c.getReferencedObjects(prev) { + // On an update, the .Add() call above will have re-incremented the + // ref count of any existing object, so any objects that are in both + // names and prev need to have their ref counts decremented. Any that + // are only in prev need to be completely removed. This unconditional + // call takes care of both cases. + c.objectStore.DeleteReference(prev.Namespace, name) + } + } +} + +func (c *cacheBasedManager) UnregisterPod(pod *v1.Pod) { + var prev *v1.Pod + key := objectKey{namespace: pod.Namespace, name: pod.Name} + c.lock.Lock() + defer c.lock.Unlock() + prev = c.registeredPods[key] + delete(c.registeredPods, key) + if prev != nil { + for name := range c.getReferencedObjects(prev) { + c.objectStore.DeleteReference(prev.Namespace, name) + } + } +} + +// NewCacheBasedManager creates a manager that keeps a cache of all objects +// necessary for registered pods. +// It implements the following logic: +// - whenever a pod is created or updated, the cached versions of all objects +// is is referencing are invalidated +// - every GetObject() call tries to fetch the value from local cache; if it is +// not there, invalidated or too old, we fetch it from apiserver and refresh the +// value in cache; otherwise it is just fetched from cache +func NewCacheBasedManager(objectStore Store, getReferencedObjects func(*v1.Pod) sets.String) Manager { + return &cacheBasedManager{ + objectStore: objectStore, + getReferencedObjects: getReferencedObjects, + registeredPods: make(map[objectKey]*v1.Pod), + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/cache_based_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/cache_based_manager_test.go new file mode 100644 index 000000000..c21584df5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/cache_based_manager_test.go @@ -0,0 +1,563 @@ +/* +Copyright 2018 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 manager + +import ( + "fmt" + "reflect" + "strings" + "sync" + "testing" + "time" + + "k8s.io/api/core/v1" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/clock" + "k8s.io/apimachinery/pkg/util/sets" + + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" + core "k8s.io/client-go/testing" + podutil "k8s.io/kubernetes/pkg/api/v1/pod" + + "github.com/stretchr/testify/assert" +) + +func checkObject(t *testing.T, store *objectStore, ns, name string, shouldExist bool) { + _, err := store.Get(ns, name) + if shouldExist && err != nil { + t.Errorf("unexpected actions: %#v", err) + } + if !shouldExist && (err == nil || !strings.Contains(err.Error(), fmt.Sprintf("object %q/%q not registered", ns, name))) { + t.Errorf("unexpected actions: %#v", err) + } +} + +func noObjectTTL() (time.Duration, bool) { + return time.Duration(0), false +} + +func getSecret(fakeClient clientset.Interface) GetObjectFunc { + return func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { + return fakeClient.CoreV1().Secrets(namespace).Get(name, opts) + } +} + +func newSecretStore(fakeClient clientset.Interface, clock clock.Clock, getTTL GetObjectTTLFunc, ttl time.Duration) *objectStore { + return &objectStore{ + getObject: getSecret(fakeClient), + clock: clock, + items: make(map[objectKey]*objectStoreItem), + defaultTTL: ttl, + getTTL: getTTL, + } +} + +func getSecretNames(pod *v1.Pod) sets.String { + result := sets.NewString() + podutil.VisitPodSecretNames(pod, func(name string) bool { + result.Insert(name) + return true + }) + return result +} + +func newCacheBasedSecretManager(store Store) Manager { + return NewCacheBasedManager(store, getSecretNames) +} + +func TestSecretStore(t *testing.T) { + fakeClient := &fake.Clientset{} + store := newSecretStore(fakeClient, clock.RealClock{}, noObjectTTL, 0) + store.AddReference("ns1", "name1") + store.AddReference("ns2", "name2") + store.AddReference("ns1", "name1") + store.AddReference("ns1", "name1") + store.DeleteReference("ns1", "name1") + store.DeleteReference("ns2", "name2") + store.AddReference("ns3", "name3") + + // Adds don't issue Get requests. + actions := fakeClient.Actions() + assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) + // Should issue Get request + store.Get("ns1", "name1") + // Shouldn't issue Get request, as secret is not registered + store.Get("ns2", "name2") + // Should issue Get request + store.Get("ns3", "name3") + + actions = fakeClient.Actions() + assert.Equal(t, 2, len(actions), "unexpected actions: %#v", actions) + + for _, a := range actions { + assert.True(t, a.Matches("get", "secrets"), "unexpected actions: %#v", a) + } + + checkObject(t, store, "ns1", "name1", true) + checkObject(t, store, "ns2", "name2", false) + checkObject(t, store, "ns3", "name3", true) + checkObject(t, store, "ns4", "name4", false) +} + +func TestSecretStoreDeletingSecret(t *testing.T) { + fakeClient := &fake.Clientset{} + store := newSecretStore(fakeClient, clock.RealClock{}, noObjectTTL, 0) + store.AddReference("ns", "name") + + result := &v1.Secret{ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "name", ResourceVersion: "10"}} + fakeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) { + return true, result, nil + }) + secret, err := store.Get("ns", "name") + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if !reflect.DeepEqual(secret, result) { + t.Errorf("Unexpected secret: %v", secret) + } + + fakeClient.PrependReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) { + return true, &v1.Secret{}, apierrors.NewNotFound(v1.Resource("secret"), "name") + }) + secret, err = store.Get("ns", "name") + if err == nil || !apierrors.IsNotFound(err) { + t.Errorf("Unexpected error: %v", err) + } + if !reflect.DeepEqual(secret, &v1.Secret{}) { + t.Errorf("Unexpected secret: %v", secret) + } +} + +func TestSecretStoreGetAlwaysRefresh(t *testing.T) { + fakeClient := &fake.Clientset{} + fakeClock := clock.NewFakeClock(time.Now()) + store := newSecretStore(fakeClient, fakeClock, noObjectTTL, 0) + + for i := 0; i < 10; i++ { + store.AddReference(fmt.Sprintf("ns-%d", i), fmt.Sprintf("name-%d", i)) + } + fakeClient.ClearActions() + + wg := sync.WaitGroup{} + wg.Add(100) + for i := 0; i < 100; i++ { + go func(i int) { + store.Get(fmt.Sprintf("ns-%d", i%10), fmt.Sprintf("name-%d", i%10)) + wg.Done() + }(i) + } + wg.Wait() + actions := fakeClient.Actions() + assert.Equal(t, 100, len(actions), "unexpected actions: %#v", actions) + + for _, a := range actions { + assert.True(t, a.Matches("get", "secrets"), "unexpected actions: %#v", a) + } +} + +func TestSecretStoreGetNeverRefresh(t *testing.T) { + fakeClient := &fake.Clientset{} + fakeClock := clock.NewFakeClock(time.Now()) + store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute) + + for i := 0; i < 10; i++ { + store.AddReference(fmt.Sprintf("ns-%d", i), fmt.Sprintf("name-%d", i)) + } + fakeClient.ClearActions() + + wg := sync.WaitGroup{} + wg.Add(100) + for i := 0; i < 100; i++ { + go func(i int) { + store.Get(fmt.Sprintf("ns-%d", i%10), fmt.Sprintf("name-%d", i%10)) + wg.Done() + }(i) + } + wg.Wait() + actions := fakeClient.Actions() + // Only first Get, should forward the Get request. + assert.Equal(t, 10, len(actions), "unexpected actions: %#v", actions) +} + +func TestCustomTTL(t *testing.T) { + ttl := time.Duration(0) + ttlExists := false + customTTL := func() (time.Duration, bool) { + return ttl, ttlExists + } + + fakeClient := &fake.Clientset{} + fakeClock := clock.NewFakeClock(time.Time{}) + store := newSecretStore(fakeClient, fakeClock, customTTL, time.Minute) + + store.AddReference("ns", "name") + store.Get("ns", "name") + fakeClient.ClearActions() + + // Set 0-ttl and see if that works. + ttl = time.Duration(0) + ttlExists = true + store.Get("ns", "name") + actions := fakeClient.Actions() + assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions) + fakeClient.ClearActions() + + // Set 5-minute ttl and see if this works. + ttl = time.Duration(5) * time.Minute + store.Get("ns", "name") + actions = fakeClient.Actions() + assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) + // Still no effect after 4 minutes. + fakeClock.Step(4 * time.Minute) + store.Get("ns", "name") + actions = fakeClient.Actions() + assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) + // Now it should have an effect. + fakeClock.Step(time.Minute) + store.Get("ns", "name") + actions = fakeClient.Actions() + assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions) + fakeClient.ClearActions() + + // Now remove the custom ttl and see if that works. + ttlExists = false + fakeClock.Step(55 * time.Second) + store.Get("ns", "name") + actions = fakeClient.Actions() + assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions) + // Pass the minute and it should be triggered now. + fakeClock.Step(5 * time.Second) + store.Get("ns", "name") + actions = fakeClient.Actions() + assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions) +} + +func TestParseNodeAnnotation(t *testing.T) { + testCases := []struct { + node *v1.Node + err error + exists bool + ttl time.Duration + }{ + { + node: nil, + err: fmt.Errorf("error"), + exists: false, + }, + { + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node", + }, + }, + exists: false, + }, + { + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node", + Annotations: map[string]string{}, + }, + }, + exists: false, + }, + { + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node", + Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "bad"}, + }, + }, + exists: false, + }, + { + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node", + Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "0"}, + }, + }, + exists: true, + ttl: time.Duration(0), + }, + { + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node", + Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "60"}, + }, + }, + exists: true, + ttl: time.Minute, + }, + } + for i, testCase := range testCases { + getNode := func() (*v1.Node, error) { return testCase.node, testCase.err } + ttl, exists := GetObjectTTLFromNodeFunc(getNode)() + if exists != testCase.exists { + t.Errorf("%d: incorrect parsing: %t", i, exists) + continue + } + if exists && ttl != testCase.ttl { + t.Errorf("%d: incorrect ttl: %v", i, ttl) + } + } +} + +type envSecrets struct { + envVarNames []string + envFromNames []string +} + +type secretsToAttach struct { + imagePullSecretNames []string + containerEnvSecrets []envSecrets +} + +func podWithSecrets(ns, podName string, toAttach secretsToAttach) *v1.Pod { + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: podName, + }, + Spec: v1.PodSpec{}, + } + for _, name := range toAttach.imagePullSecretNames { + pod.Spec.ImagePullSecrets = append( + pod.Spec.ImagePullSecrets, v1.LocalObjectReference{Name: name}) + } + for i, secrets := range toAttach.containerEnvSecrets { + container := v1.Container{ + Name: fmt.Sprintf("container-%d", i), + } + for _, name := range secrets.envFromNames { + envFrom := v1.EnvFromSource{ + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: name, + }, + }, + } + container.EnvFrom = append(container.EnvFrom, envFrom) + } + + for _, name := range secrets.envVarNames { + envSource := &v1.EnvVarSource{ + SecretKeyRef: &v1.SecretKeySelector{ + LocalObjectReference: v1.LocalObjectReference{ + Name: name, + }, + }, + } + container.Env = append(container.Env, v1.EnvVar{ValueFrom: envSource}) + } + pod.Spec.Containers = append(pod.Spec.Containers, container) + } + return pod +} + +func TestCacheInvalidation(t *testing.T) { + fakeClient := &fake.Clientset{} + fakeClock := clock.NewFakeClock(time.Now()) + store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute) + manager := newCacheBasedSecretManager(store) + + // Create a pod with some secrets. + s1 := secretsToAttach{ + imagePullSecretNames: []string{"s1"}, + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s1"}, envFromNames: []string{"s10"}}, + {envVarNames: []string{"s2"}}, + }, + } + manager.RegisterPod(podWithSecrets("ns1", "name1", s1)) + // Fetch both secrets - this should triggger get operations. + store.Get("ns1", "s1") + store.Get("ns1", "s10") + store.Get("ns1", "s2") + actions := fakeClient.Actions() + assert.Equal(t, 3, len(actions), "unexpected actions: %#v", actions) + fakeClient.ClearActions() + + // Update a pod with a new secret. + s2 := secretsToAttach{ + imagePullSecretNames: []string{"s1"}, + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s1"}}, + {envVarNames: []string{"s2"}, envFromNames: []string{"s20"}}, + {envVarNames: []string{"s3"}}, + }, + } + manager.RegisterPod(podWithSecrets("ns1", "name1", s2)) + // All secrets should be invalidated - this should trigger get operations. + store.Get("ns1", "s1") + store.Get("ns1", "s2") + store.Get("ns1", "s20") + store.Get("ns1", "s3") + actions = fakeClient.Actions() + assert.Equal(t, 4, len(actions), "unexpected actions: %#v", actions) + fakeClient.ClearActions() + + // Create a new pod that is refencing the first three secrets - those should + // be invalidated. + manager.RegisterPod(podWithSecrets("ns1", "name2", s1)) + store.Get("ns1", "s1") + store.Get("ns1", "s10") + store.Get("ns1", "s2") + store.Get("ns1", "s20") + store.Get("ns1", "s3") + actions = fakeClient.Actions() + assert.Equal(t, 3, len(actions), "unexpected actions: %#v", actions) + fakeClient.ClearActions() +} + +func TestCacheRefcounts(t *testing.T) { + fakeClient := &fake.Clientset{} + fakeClock := clock.NewFakeClock(time.Now()) + store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute) + manager := newCacheBasedSecretManager(store) + + s1 := secretsToAttach{ + imagePullSecretNames: []string{"s1"}, + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s1"}, envFromNames: []string{"s10"}}, + {envVarNames: []string{"s2"}}, + {envVarNames: []string{"s3"}}, + }, + } + manager.RegisterPod(podWithSecrets("ns1", "name1", s1)) + manager.RegisterPod(podWithSecrets("ns1", "name2", s1)) + s2 := secretsToAttach{ + imagePullSecretNames: []string{"s2"}, + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s4"}}, + {envVarNames: []string{"s5"}, envFromNames: []string{"s50"}}, + }, + } + manager.RegisterPod(podWithSecrets("ns1", "name2", s2)) + manager.RegisterPod(podWithSecrets("ns1", "name3", s2)) + manager.RegisterPod(podWithSecrets("ns1", "name4", s2)) + manager.UnregisterPod(podWithSecrets("ns1", "name3", s2)) + s3 := secretsToAttach{ + imagePullSecretNames: []string{"s1"}, + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s3"}, envFromNames: []string{"s30"}}, + {envVarNames: []string{"s5"}}, + }, + } + manager.RegisterPod(podWithSecrets("ns1", "name5", s3)) + manager.RegisterPod(podWithSecrets("ns1", "name6", s3)) + s4 := secretsToAttach{ + imagePullSecretNames: []string{"s3"}, + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s6"}}, + {envFromNames: []string{"s60"}}, + }, + } + manager.RegisterPod(podWithSecrets("ns1", "name7", s4)) + manager.UnregisterPod(podWithSecrets("ns1", "name7", s4)) + + // Also check the Add + Update + Remove scenario. + manager.RegisterPod(podWithSecrets("ns1", "other-name", s1)) + manager.RegisterPod(podWithSecrets("ns1", "other-name", s2)) + manager.UnregisterPod(podWithSecrets("ns1", "other-name", s2)) + + s5 := secretsToAttach{ + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s7"}}, + {envFromNames: []string{"s70"}}, + }, + } + // Check the no-op update scenario + manager.RegisterPod(podWithSecrets("ns1", "noop-pod", s5)) + manager.RegisterPod(podWithSecrets("ns1", "noop-pod", s5)) + + // Now we have: 3 pods with s1, 2 pods with s2 and 2 pods with s3, 0 pods with s4. + refs := func(ns, name string) int { + store.lock.Lock() + defer store.lock.Unlock() + item, ok := store.items[objectKey{ns, name}] + if !ok { + return 0 + } + return item.refCount + } + assert.Equal(t, 3, refs("ns1", "s1")) + assert.Equal(t, 1, refs("ns1", "s10")) + assert.Equal(t, 3, refs("ns1", "s2")) + assert.Equal(t, 3, refs("ns1", "s3")) + assert.Equal(t, 2, refs("ns1", "s30")) + assert.Equal(t, 2, refs("ns1", "s4")) + assert.Equal(t, 4, refs("ns1", "s5")) + assert.Equal(t, 2, refs("ns1", "s50")) + assert.Equal(t, 0, refs("ns1", "s6")) + assert.Equal(t, 0, refs("ns1", "s60")) + assert.Equal(t, 1, refs("ns1", "s7")) + assert.Equal(t, 1, refs("ns1", "s70")) +} + +func TestCacheBasedSecretManager(t *testing.T) { + fakeClient := &fake.Clientset{} + store := newSecretStore(fakeClient, clock.RealClock{}, noObjectTTL, 0) + manager := newCacheBasedSecretManager(store) + + // Create a pod with some secrets. + s1 := secretsToAttach{ + imagePullSecretNames: []string{"s1"}, + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s1"}}, + {envVarNames: []string{"s2"}}, + {envFromNames: []string{"s20"}}, + }, + } + manager.RegisterPod(podWithSecrets("ns1", "name1", s1)) + // Update the pod with a different secrets. + s2 := secretsToAttach{ + imagePullSecretNames: []string{"s1"}, + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s3"}}, + {envVarNames: []string{"s4"}}, + {envFromNames: []string{"s40"}}, + }, + } + manager.RegisterPod(podWithSecrets("ns1", "name1", s2)) + // Create another pod, but with same secrets in different namespace. + manager.RegisterPod(podWithSecrets("ns2", "name2", s2)) + // Create and delete a pod with some other secrets. + s3 := secretsToAttach{ + imagePullSecretNames: []string{"s5"}, + containerEnvSecrets: []envSecrets{ + {envVarNames: []string{"s6"}}, + {envFromNames: []string{"s60"}}, + }, + } + manager.RegisterPod(podWithSecrets("ns3", "name", s3)) + manager.UnregisterPod(podWithSecrets("ns3", "name", s3)) + + // We should have only: s1, s3 and s4 secrets in namespaces: ns1 and ns2. + for _, ns := range []string{"ns1", "ns2", "ns3"} { + for _, secret := range []string{"s1", "s2", "s3", "s4", "s5", "s6", "s20", "s40", "s50"} { + shouldExist := + (secret == "s1" || secret == "s3" || secret == "s4" || secret == "s40") && (ns == "ns1" || ns == "ns2") + checkObject(t, store, ns, secret, shouldExist) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/manager.go new file mode 100644 index 000000000..4d4b958d0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/manager.go @@ -0,0 +1,56 @@ +/* +Copyright 2018 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 manager + +import ( + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// Manager is the interface for registering and unregistering +// objects referenced by pods in the underlying cache and +// extracting those from that cache if needed. +type Manager interface { + // Get object by its namespace and name. + GetObject(namespace, name string) (runtime.Object, error) + + // WARNING: Register/UnregisterPod functions should be efficient, + // i.e. should not block on network operations. + + // RegisterPod registers all objects referenced from a given pod. + RegisterPod(pod *v1.Pod) + + // UnregisterPod unregisters objects referenced from a given pod that are not + // used by any other registered pod. + UnregisterPod(pod *v1.Pod) +} + +// Store is the interface for a object cache that +// can be used by cacheBasedManager. +type Store interface { + // AddReference adds a reference to the object to the store. + // Note that multiple additions to the store has to be allowed + // in the implementations and effectively treated as refcounted. + AddReference(namespace, name string) + // DeleteReference deletes reference to the object from the store. + // Note that object should be deleted only when there was a + // corresponding Delete call for each of Add calls (effectively + // when refcount was reduced to zero). + DeleteReference(namespace, name string) + // Get an object from a store. + Get(namespace, name string) (runtime.Object, error) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/watch_based_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/watch_based_manager.go new file mode 100644 index 000000000..719f1f3b1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/watch_based_manager.go @@ -0,0 +1,194 @@ +/* +Copyright 2018 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: We did some scalability tests and using watchBasedManager +// seems to help with apiserver performance at scale visibly. +// No issues we also observed at the scale of ~200k watchers with a +// single apiserver. +// However, we need to perform more extensive testing before we +// enable this in production setups. + +package manager + +import ( + "fmt" + "sync" + "time" + + "k8s.io/api/core/v1" + "k8s.io/client-go/tools/cache" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/watch" +) + +type listObjectFunc func(string, metav1.ListOptions) (runtime.Object, error) +type watchObjectFunc func(string, metav1.ListOptions) (watch.Interface, error) +type newObjectFunc func() runtime.Object + +// objectCacheItem is a single item stored in objectCache. +type objectCacheItem struct { + refCount int + store cache.Store + hasSynced func() (bool, error) + stopCh chan struct{} +} + +// objectCache is a local cache of objects propagated via +// individual watches. +type objectCache struct { + listObject listObjectFunc + watchObject watchObjectFunc + newObject newObjectFunc + groupResource schema.GroupResource + + lock sync.Mutex + items map[objectKey]*objectCacheItem +} + +// NewObjectCache returns a new watch-based instance of Store interface. +func NewObjectCache(listObject listObjectFunc, watchObject watchObjectFunc, newObject newObjectFunc, groupResource schema.GroupResource) Store { + return &objectCache{ + listObject: listObject, + watchObject: watchObject, + newObject: newObject, + groupResource: groupResource, + items: make(map[objectKey]*objectCacheItem), + } +} + +func (c *objectCache) newStore() cache.Store { + // TODO: We may consider created a dedicated store keeping just a single + // item, instead of using a generic store implementation for this purpose. + // However, simple benchmarks show that memory overhead in that case is + // decrease from ~600B to ~300B per object. So we are not optimizing it + // until we will see a good reason for that. + return cache.NewStore(cache.MetaNamespaceKeyFunc) +} + +func (c *objectCache) newReflector(namespace, name string) *objectCacheItem { + fieldSelector := fields.Set{"metadata.name": name}.AsSelector().String() + listFunc := func(options metav1.ListOptions) (runtime.Object, error) { + options.FieldSelector = fieldSelector + return c.listObject(namespace, options) + } + watchFunc := func(options metav1.ListOptions) (watch.Interface, error) { + options.FieldSelector = fieldSelector + return c.watchObject(namespace, options) + } + store := c.newStore() + reflector := cache.NewNamedReflector( + fmt.Sprintf("object-%q/%q", namespace, name), + &cache.ListWatch{ListFunc: listFunc, WatchFunc: watchFunc}, + c.newObject(), + store, + 0, + ) + stopCh := make(chan struct{}) + go reflector.Run(stopCh) + return &objectCacheItem{ + refCount: 0, + store: store, + hasSynced: func() (bool, error) { return reflector.LastSyncResourceVersion() != "", nil }, + stopCh: stopCh, + } +} + +func (c *objectCache) AddReference(namespace, name string) { + key := objectKey{namespace: namespace, name: name} + + // AddReference is called from RegisterPod thus it needs to be efficient. + // Thus, it is only increaisng refCount and in case of first registration + // of a given object it starts corresponding reflector. + // It's responsibility of the first Get operation to wait until the + // reflector propagated the store. + c.lock.Lock() + defer c.lock.Unlock() + item, exists := c.items[key] + if !exists { + item = c.newReflector(namespace, name) + c.items[key] = item + } + item.refCount++ +} + +func (c *objectCache) DeleteReference(namespace, name string) { + key := objectKey{namespace: namespace, name: name} + + c.lock.Lock() + defer c.lock.Unlock() + if item, ok := c.items[key]; ok { + item.refCount-- + if item.refCount == 0 { + // Stop the underlying reflector. + close(item.stopCh) + delete(c.items, key) + } + } +} + +// key returns key of an object with a given name and namespace. +// This has to be in-sync with cache.MetaNamespaceKeyFunc. +func (c *objectCache) key(namespace, name string) string { + if len(namespace) > 0 { + return namespace + "/" + name + } + return name +} + +func (c *objectCache) Get(namespace, name string) (runtime.Object, error) { + key := objectKey{namespace: namespace, name: name} + + c.lock.Lock() + item, exists := c.items[key] + c.lock.Unlock() + + if !exists { + return nil, fmt.Errorf("object %q/%q not registered", namespace, name) + } + if err := wait.PollImmediate(10*time.Millisecond, time.Second, item.hasSynced); err != nil { + return nil, fmt.Errorf("couldn't propagate object cache: %v", err) + } + + obj, exists, err := item.store.GetByKey(c.key(namespace, name)) + if err != nil { + return nil, err + } + if !exists { + return nil, apierrors.NewNotFound(c.groupResource, name) + } + if object, ok := obj.(runtime.Object); ok { + return object, nil + } + return nil, fmt.Errorf("unexpected object type: %v", obj) +} + +// NewWatchBasedManager creates a manager that keeps a cache of all objects +// necessary for registered pods. +// It implements the following logic: +// - whenever a pod is created or updated, we start individual watches for all +// referenced objects that aren't referenced from other registered pods +// - every GetObject() returns a value from local cache propagated via watches +func NewWatchBasedManager(listObject listObjectFunc, watchObject watchObjectFunc, newObject newObjectFunc, groupResource schema.GroupResource, getReferencedObjects func(*v1.Pod) sets.String) Manager { + objectStore := NewObjectCache(listObject, watchObject, newObject, groupResource) + return NewCacheBasedManager(objectStore, getReferencedObjects) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/watch_based_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/watch_based_manager_test.go new file mode 100644 index 000000000..fc27a7374 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/watch_based_manager_test.go @@ -0,0 +1,184 @@ +/* +Copyright 2018 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 manager + +import ( + "fmt" + "strings" + "testing" + "time" + + "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/watch" + + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" + core "k8s.io/client-go/testing" + + corev1 "k8s.io/kubernetes/pkg/apis/core/v1" + + "github.com/stretchr/testify/assert" +) + +func listSecret(fakeClient clientset.Interface) listObjectFunc { + return func(namespace string, opts metav1.ListOptions) (runtime.Object, error) { + return fakeClient.CoreV1().Secrets(namespace).List(opts) + } +} + +func watchSecret(fakeClient clientset.Interface) watchObjectFunc { + return func(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return fakeClient.CoreV1().Secrets(namespace).Watch(opts) + } +} + +func newSecretCache(fakeClient clientset.Interface) *objectCache { + return &objectCache{ + listObject: listSecret(fakeClient), + watchObject: watchSecret(fakeClient), + newObject: func() runtime.Object { return &v1.Secret{} }, + groupResource: corev1.Resource("secret"), + items: make(map[objectKey]*objectCacheItem), + } +} + +func TestSecretCache(t *testing.T) { + fakeClient := &fake.Clientset{} + + listReactor := func(a core.Action) (bool, runtime.Object, error) { + result := &v1.SecretList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "123", + }, + } + return true, result, nil + } + fakeClient.AddReactor("list", "secrets", listReactor) + fakeWatch := watch.NewFake() + fakeClient.AddWatchReactor("secrets", core.DefaultWatchReactor(fakeWatch, nil)) + + store := newSecretCache(fakeClient) + + store.AddReference("ns", "name") + _, err := store.Get("ns", "name") + if !apierrors.IsNotFound(err) { + t.Errorf("Expected NotFound error, got: %v", err) + } + + // Eventually we should be able to read added secret. + secret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "name", Namespace: "ns", ResourceVersion: "125"}, + } + fakeWatch.Add(secret) + getFn := func() (bool, error) { + object, err := store.Get("ns", "name") + if err != nil { + if apierrors.IsNotFound(err) { + return false, nil + } + return false, err + } + secret := object.(*v1.Secret) + if secret == nil || secret.Name != "name" || secret.Namespace != "ns" { + return false, fmt.Errorf("unexpected secret: %v", secret) + } + return true, nil + } + if err := wait.PollImmediate(10*time.Millisecond, time.Second, getFn); err != nil { + t.Errorf("unexpected error: %v", err) + } + + // Eventually we should observer secret deletion. + fakeWatch.Delete(secret) + getFn = func() (bool, error) { + _, err := store.Get("ns", "name") + if err != nil { + if apierrors.IsNotFound(err) { + return true, nil + } + return false, err + } + return false, nil + } + if err := wait.PollImmediate(10*time.Millisecond, time.Second, getFn); err != nil { + t.Errorf("unexpected error: %v", err) + } + + store.DeleteReference("ns", "name") + _, err = store.Get("ns", "name") + if err == nil || !strings.Contains(err.Error(), "not registered") { + t.Errorf("unexpected error: %v", err) + } +} + +func TestSecretCacheMultipleRegistrations(t *testing.T) { + fakeClient := &fake.Clientset{} + + listReactor := func(a core.Action) (bool, runtime.Object, error) { + result := &v1.SecretList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "123", + }, + } + return true, result, nil + } + fakeClient.AddReactor("list", "secrets", listReactor) + fakeWatch := watch.NewFake() + fakeClient.AddWatchReactor("secrets", core.DefaultWatchReactor(fakeWatch, nil)) + + store := newSecretCache(fakeClient) + + store.AddReference("ns", "name") + // This should trigger List and Watch actions eventually. + actionsFn := func() (bool, error) { + actions := fakeClient.Actions() + if len(actions) > 2 { + return false, fmt.Errorf("too many actions: %v", actions) + } + if len(actions) < 2 { + return false, nil + } + if actions[0].GetVerb() != "list" || actions[1].GetVerb() != "watch" { + return false, fmt.Errorf("unexpected actions: %v", actions) + } + return true, nil + } + if err := wait.PollImmediate(10*time.Millisecond, time.Second, actionsFn); err != nil { + t.Errorf("unexpected error: %v", err) + } + + // Next registrations shouldn't trigger any new actions. + for i := 0; i < 20; i++ { + store.AddReference("ns", "name") + store.DeleteReference("ns", "name") + } + actions := fakeClient.Actions() + assert.Equal(t, 2, len(actions), "unexpected actions: %#v", actions) + + // Final delete also doesn't trigger any action. + store.DeleteReference("ns", "name") + _, err := store.Get("ns", "name") + if err == nil || !strings.Contains(err.Error(), "not registered") { + t.Errorf("unexpected error: %v", err) + } + actions = fakeClient.Actions() + assert.Equal(t, 2, len(actions), "unexpected actions: %#v", actions) +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/BUILD new file mode 100644 index 000000000..b4173ab5e --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/BUILD @@ -0,0 +1,58 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "example_plugin.go", + "plugin_watcher.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher", + deps = [ + "//pkg/kubelet/apis/pluginregistration/v1alpha1:go_default_library", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1:go_default_library", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2:go_default_library", + "//pkg/util/filesystem:go_default_library", + "//vendor/github.com/fsnotify/fsnotify:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1:all-srcs", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["plugin_watcher_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/kubelet/apis/pluginregistration/v1alpha1:go_default_library", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1:go_default_library", + "//pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2:go_default_library", + "//vendor/github.com/stretchr/testify/require:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/README b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/README new file mode 100644 index 000000000..9654b2cf6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/README @@ -0,0 +1,29 @@ +This folder contains a utility, pluginwatcher, for Kubelet to register +different types of node-level plugins such as device plugins or CSI plugins. +It discovers plugins by monitoring inotify events under the directory returned by +kubelet.getPluginsDir(). Lets refer this directory as PluginsSockDir. +For any discovered plugin, pluginwatcher issues Registration.GetInfo grpc call +to get plugin type, name and supported service API versions. For any registered plugin type, +pluginwatcher calls the registered callback function with the received plugin +name, supported service API versions, and the full socket path. The Kubelet +component that receives this callback can acknowledge or reject the plugin +according to its own logic, and use the socket path to establish its service +communication with any API version supported by the plugin. + +Here are the general rules that Kubelet plugin developers should follow: +- Run as 'root' user. Currently creating socket under PluginsSockDir, a root owned directory, requires + plugin process to be running as 'root'. +- Implements the Registration service specified in + pkg/kubelet/apis/pluginregistration/v*/api.proto. +- The plugin name sent during Registration.GetInfo grpc should be unique + for the given plugin type (CSIPlugin or DevicePlugin). +- The socket path needs to be unique and doesn't conflict with the path chosen + by any other potential plugins. Currently we only support flat fs namespace + under PluginsSockDir but will soon support recursive inotify watch for + hierarchical socket paths. +- A plugin should clean up its own socket upon exiting or when a new instance + comes up. A plugin should NOT remove any sockets belonging to other plugins. +- A plugin should make sure it has service ready for any supported service API + version listed in the PluginInfo. +- For an example plugin implementation, take a look at example_plugin.go + included in this directory. diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin.go new file mode 100644 index 000000000..fbca43aca --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin.go @@ -0,0 +1,150 @@ +/* +Copyright 2018 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 pluginwatcher + +import ( + "fmt" + "net" + "sync" + "time" + + "github.com/golang/glog" + "golang.org/x/net/context" + "google.golang.org/grpc" + + registerapi "k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1" + v1beta1 "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1" + v1beta2 "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2" +) + +const ( + PluginName = "example-plugin" + PluginType = "example-plugin-type" +) + +// examplePlugin is a sample plugin to work with plugin watcher +type examplePlugin struct { + grpcServer *grpc.Server + wg sync.WaitGroup + registrationStatus chan registerapi.RegistrationStatus // for testing + endpoint string // for testing +} + +type pluginServiceV1Beta1 struct { + server *examplePlugin +} + +func (s *pluginServiceV1Beta1) GetExampleInfo(ctx context.Context, rqt *v1beta1.ExampleRequest) (*v1beta1.ExampleResponse, error) { + glog.Infof("GetExampleInfo v1beta1field: %s", rqt.V1Beta1Field) + return &v1beta1.ExampleResponse{}, nil +} + +func (s *pluginServiceV1Beta1) RegisterService() { + v1beta1.RegisterExampleServer(s.server.grpcServer, s) +} + +type pluginServiceV1Beta2 struct { + server *examplePlugin +} + +func (s *pluginServiceV1Beta2) GetExampleInfo(ctx context.Context, rqt *v1beta2.ExampleRequest) (*v1beta2.ExampleResponse, error) { + glog.Infof("GetExampleInfo v1beta2_field: %s", rqt.V1Beta2Field) + return &v1beta2.ExampleResponse{}, nil +} + +func (s *pluginServiceV1Beta2) RegisterService() { + v1beta2.RegisterExampleServer(s.server.grpcServer, s) +} + +// NewExamplePlugin returns an initialized examplePlugin instance +func NewExamplePlugin() *examplePlugin { + return &examplePlugin{} +} + +// NewTestExamplePlugin returns an initialized examplePlugin instance for testing +func NewTestExamplePlugin(endpoint string) *examplePlugin { + return &examplePlugin{ + registrationStatus: make(chan registerapi.RegistrationStatus), + endpoint: endpoint, + } +} + +// GetInfo is the RPC invoked by plugin watcher +func (e *examplePlugin) GetInfo(ctx context.Context, req *registerapi.InfoRequest) (*registerapi.PluginInfo, error) { + return ®isterapi.PluginInfo{ + Type: PluginType, + Name: PluginName, + Endpoint: e.endpoint, + SupportedVersions: []string{"v1beta1", "v1beta2"}, + }, nil +} + +func (e *examplePlugin) NotifyRegistrationStatus(ctx context.Context, status *registerapi.RegistrationStatus) (*registerapi.RegistrationStatusResponse, error) { + if e.registrationStatus != nil { + e.registrationStatus <- *status + } + if !status.PluginRegistered { + glog.Errorf("Registration failed: %s\n", status.Error) + } + return ®isterapi.RegistrationStatusResponse{}, nil +} + +// Serve starts example plugin grpc server +func (e *examplePlugin) Serve(socketPath string) error { + glog.Infof("starting example server at: %s\n", socketPath) + lis, err := net.Listen("unix", socketPath) + if err != nil { + return err + } + glog.Infof("example server started at: %s\n", socketPath) + e.grpcServer = grpc.NewServer() + // Registers kubelet plugin watcher api. + registerapi.RegisterRegistrationServer(e.grpcServer, e) + // Registers services for both v1beta1 and v1beta2 versions. + v1beta1 := &pluginServiceV1Beta1{server: e} + v1beta1.RegisterService() + v1beta2 := &pluginServiceV1Beta2{server: e} + v1beta2.RegisterService() + + // Starts service + e.wg.Add(1) + go func() { + defer e.wg.Done() + // Blocking call to accept incoming connections. + if err := e.grpcServer.Serve(lis); err != nil { + glog.Errorf("example server stopped serving: %v", err) + } + }() + return nil +} + +func (e *examplePlugin) Stop() error { + glog.Infof("Stopping example server\n") + e.grpcServer.Stop() + c := make(chan struct{}) + go func() { + defer close(c) + e.wg.Wait() + }() + select { + case <-c: + return nil + case <-time.After(time.Second): + glog.Errorf("Timed out on waiting for stop completion") + return fmt.Errorf("Timed out on waiting for stop completion") + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/BUILD new file mode 100644 index 000000000..affbd0aee --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/BUILD @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +filegroup( + name = "go_default_library_protos", + srcs = ["api.proto"], + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + srcs = ["api.pb.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", + "//vendor/github.com/gogo/protobuf/proto:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.pb.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.pb.go new file mode 100644 index 000000000..671e3df49 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.pb.go @@ -0,0 +1,632 @@ +/* +Copyright 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. +*/ + +// Code generated by protoc-gen-gogo. +// source: api.proto +// DO NOT EDIT! + +/* + Package v1beta1 is a generated protocol buffer package. + + It is generated from these files: + api.proto + + It has these top-level messages: + ExampleRequest + ExampleResponse +*/ +package v1beta1 + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +import strings "strings" +import reflect "reflect" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +type ExampleRequest struct { + Request string `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` + V1Beta1Field string `protobuf:"bytes,2,opt,name=v1beta1_field,json=v1beta1Field,proto3" json:"v1beta1_field,omitempty"` +} + +func (m *ExampleRequest) Reset() { *m = ExampleRequest{} } +func (*ExampleRequest) ProtoMessage() {} +func (*ExampleRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{0} } + +func (m *ExampleRequest) GetRequest() string { + if m != nil { + return m.Request + } + return "" +} + +func (m *ExampleRequest) GetV1Beta1Field() string { + if m != nil { + return m.V1Beta1Field + } + return "" +} + +type ExampleResponse struct { + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *ExampleResponse) Reset() { *m = ExampleResponse{} } +func (*ExampleResponse) ProtoMessage() {} +func (*ExampleResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{1} } + +func (m *ExampleResponse) GetError() string { + if m != nil { + return m.Error + } + return "" +} + +func init() { + proto.RegisterType((*ExampleRequest)(nil), "v1beta1.ExampleRequest") + proto.RegisterType((*ExampleResponse)(nil), "v1beta1.ExampleResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Example service + +type ExampleClient interface { + GetExampleInfo(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ExampleResponse, error) +} + +type exampleClient struct { + cc *grpc.ClientConn +} + +func NewExampleClient(cc *grpc.ClientConn) ExampleClient { + return &exampleClient{cc} +} + +func (c *exampleClient) GetExampleInfo(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ExampleResponse, error) { + out := new(ExampleResponse) + err := grpc.Invoke(ctx, "/v1beta1.Example/GetExampleInfo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Example service + +type ExampleServer interface { + GetExampleInfo(context.Context, *ExampleRequest) (*ExampleResponse, error) +} + +func RegisterExampleServer(s *grpc.Server, srv ExampleServer) { + s.RegisterService(&_Example_serviceDesc, srv) +} + +func _Example_GetExampleInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExampleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExampleServer).GetExampleInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/v1beta1.Example/GetExampleInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExampleServer).GetExampleInfo(ctx, req.(*ExampleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Example_serviceDesc = grpc.ServiceDesc{ + ServiceName: "v1beta1.Example", + HandlerType: (*ExampleServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetExampleInfo", + Handler: _Example_GetExampleInfo_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api.proto", +} + +func (m *ExampleRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExampleRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Request) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Request))) + i += copy(dAtA[i:], m.Request) + } + if len(m.V1Beta1Field) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.V1Beta1Field))) + i += copy(dAtA[i:], m.V1Beta1Field) + } + return i, nil +} + +func (m *ExampleResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExampleResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Error) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Error))) + i += copy(dAtA[i:], m.Error) + } + return i, nil +} + +func encodeFixed64Api(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Api(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintApi(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *ExampleRequest) Size() (n int) { + var l int + _ = l + l = len(m.Request) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.V1Beta1Field) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *ExampleResponse) Size() (n int) { + var l int + _ = l + l = len(m.Error) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func sovApi(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozApi(x uint64) (n int) { + return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *ExampleRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ExampleRequest{`, + `Request:` + fmt.Sprintf("%v", this.Request) + `,`, + `V1Beta1Field:` + fmt.Sprintf("%v", this.V1Beta1Field) + `,`, + `}`, + }, "") + return s +} +func (this *ExampleResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ExampleResponse{`, + `Error:` + fmt.Sprintf("%v", this.Error) + `,`, + `}`, + }, "") + return s +} +func valueToStringApi(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *ExampleRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExampleRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExampleRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Request", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Request = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field V1Beta1Field", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.V1Beta1Field = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExampleResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExampleResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExampleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipApi(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthApi + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipApi(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } + +var fileDescriptorApi = []byte{ + // 227 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x2c, 0xc8, 0xd4, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0x94, 0xd2, + 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0x4f, 0xcf, 0xd7, + 0x07, 0xcb, 0x27, 0x95, 0xa6, 0x81, 0x79, 0x60, 0x0e, 0x98, 0x05, 0xd1, 0xa7, 0xe4, 0xcf, 0xc5, + 0xe7, 0x5a, 0x91, 0x98, 0x5b, 0x90, 0x93, 0x1a, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 0x22, 0x24, + 0xc1, 0xc5, 0x5e, 0x04, 0x61, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xc1, 0xb8, 0x42, 0xca, + 0x5c, 0xbc, 0x50, 0x5b, 0xe2, 0xd3, 0x32, 0x53, 0x73, 0x52, 0x24, 0x98, 0xc0, 0xf2, 0x3c, 0x50, + 0x41, 0x37, 0x90, 0x98, 0x92, 0x3a, 0x17, 0x3f, 0xdc, 0xc0, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, + 0x21, 0x11, 0x2e, 0xd6, 0xd4, 0xa2, 0xa2, 0xfc, 0x22, 0xa8, 0x79, 0x10, 0x8e, 0x51, 0x00, 0x17, + 0x3b, 0x54, 0xa1, 0x90, 0x2b, 0x17, 0x9f, 0x7b, 0x6a, 0x09, 0x94, 0xe7, 0x99, 0x97, 0x96, 0x2f, + 0x24, 0xae, 0x07, 0x35, 0x54, 0x0f, 0xd5, 0x75, 0x52, 0x12, 0x98, 0x12, 0x10, 0x5b, 0x94, 0x18, + 0x9c, 0x64, 0x4e, 0x3c, 0x94, 0x63, 0xbc, 0xf1, 0x50, 0x8e, 0xa1, 0xe1, 0x91, 0x1c, 0xe3, 0x89, + 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0x43, + 0x12, 0x1b, 0xd8, 0xc3, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x99, 0x62, 0xd1, 0x9c, 0x35, + 0x01, 0x00, 0x00, +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.proto b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.proto new file mode 100644 index 000000000..14aa7df2c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1/api.proto @@ -0,0 +1,28 @@ +syntax = 'proto3'; + +package v1beta1; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +option (gogoproto.goproto_stringer_all) = false; +option (gogoproto.stringer_all) = true; +option (gogoproto.goproto_getters_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.goproto_unrecognized_all) = false; + +message ExampleRequest { + string request = 1; + string v1beta1_field = 2; +} + +message ExampleResponse { + string error = 1; +} + +// Example is a simple example service for general reference on the recommended +// kubelet plugin model and plugin watcher testing. +service Example { + rpc GetExampleInfo(ExampleRequest) returns (ExampleResponse) {} +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/BUILD new file mode 100644 index 000000000..f2b53898d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/BUILD @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +filegroup( + name = "go_default_library_protos", + srcs = ["api.proto"], + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + srcs = ["api.pb.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/gogo/protobuf/gogoproto:go_default_library", + "//vendor/github.com/gogo/protobuf/proto:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.pb.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.pb.go new file mode 100644 index 000000000..0c63b3142 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.pb.go @@ -0,0 +1,633 @@ +/* +Copyright 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. +*/ + +// Code generated by protoc-gen-gogo. +// source: api.proto +// DO NOT EDIT! + +/* + Package v1beta2 is a generated protocol buffer package. + + It is generated from these files: + api.proto + + It has these top-level messages: + ExampleRequest + ExampleResponse +*/ +package v1beta2 + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +import strings "strings" +import reflect "reflect" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +// Renames a field from v1beta1 ExampleRequest. +type ExampleRequest struct { + Request string `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` + V1Beta2Field string `protobuf:"bytes,2,opt,name=v1beta2_field,json=v1beta2Field,proto3" json:"v1beta2_field,omitempty"` +} + +func (m *ExampleRequest) Reset() { *m = ExampleRequest{} } +func (*ExampleRequest) ProtoMessage() {} +func (*ExampleRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{0} } + +func (m *ExampleRequest) GetRequest() string { + if m != nil { + return m.Request + } + return "" +} + +func (m *ExampleRequest) GetV1Beta2Field() string { + if m != nil { + return m.V1Beta2Field + } + return "" +} + +type ExampleResponse struct { + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *ExampleResponse) Reset() { *m = ExampleResponse{} } +func (*ExampleResponse) ProtoMessage() {} +func (*ExampleResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{1} } + +func (m *ExampleResponse) GetError() string { + if m != nil { + return m.Error + } + return "" +} + +func init() { + proto.RegisterType((*ExampleRequest)(nil), "v1beta2.ExampleRequest") + proto.RegisterType((*ExampleResponse)(nil), "v1beta2.ExampleResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Example service + +type ExampleClient interface { + GetExampleInfo(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ExampleResponse, error) +} + +type exampleClient struct { + cc *grpc.ClientConn +} + +func NewExampleClient(cc *grpc.ClientConn) ExampleClient { + return &exampleClient{cc} +} + +func (c *exampleClient) GetExampleInfo(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ExampleResponse, error) { + out := new(ExampleResponse) + err := grpc.Invoke(ctx, "/v1beta2.Example/GetExampleInfo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Example service + +type ExampleServer interface { + GetExampleInfo(context.Context, *ExampleRequest) (*ExampleResponse, error) +} + +func RegisterExampleServer(s *grpc.Server, srv ExampleServer) { + s.RegisterService(&_Example_serviceDesc, srv) +} + +func _Example_GetExampleInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExampleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExampleServer).GetExampleInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/v1beta2.Example/GetExampleInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExampleServer).GetExampleInfo(ctx, req.(*ExampleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Example_serviceDesc = grpc.ServiceDesc{ + ServiceName: "v1beta2.Example", + HandlerType: (*ExampleServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetExampleInfo", + Handler: _Example_GetExampleInfo_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api.proto", +} + +func (m *ExampleRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExampleRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Request) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Request))) + i += copy(dAtA[i:], m.Request) + } + if len(m.V1Beta2Field) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.V1Beta2Field))) + i += copy(dAtA[i:], m.V1Beta2Field) + } + return i, nil +} + +func (m *ExampleResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExampleResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Error) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintApi(dAtA, i, uint64(len(m.Error))) + i += copy(dAtA[i:], m.Error) + } + return i, nil +} + +func encodeFixed64Api(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Api(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintApi(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *ExampleRequest) Size() (n int) { + var l int + _ = l + l = len(m.Request) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.V1Beta2Field) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *ExampleResponse) Size() (n int) { + var l int + _ = l + l = len(m.Error) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func sovApi(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozApi(x uint64) (n int) { + return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *ExampleRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ExampleRequest{`, + `Request:` + fmt.Sprintf("%v", this.Request) + `,`, + `V1Beta2Field:` + fmt.Sprintf("%v", this.V1Beta2Field) + `,`, + `}`, + }, "") + return s +} +func (this *ExampleResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ExampleResponse{`, + `Error:` + fmt.Sprintf("%v", this.Error) + `,`, + `}`, + }, "") + return s +} +func valueToStringApi(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *ExampleRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExampleRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExampleRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Request", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Request = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field V1Beta2Field", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.V1Beta2Field = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExampleResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExampleResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExampleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipApi(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthApi + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipApi(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("api.proto", fileDescriptorApi) } + +var fileDescriptorApi = []byte{ + // 227 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x2c, 0xc8, 0xd4, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0x92, 0xd2, + 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0x4f, 0xcf, 0xd7, + 0x07, 0xcb, 0x27, 0x95, 0xa6, 0x81, 0x79, 0x60, 0x0e, 0x98, 0x05, 0xd1, 0xa7, 0xe4, 0xcf, 0xc5, + 0xe7, 0x5a, 0x91, 0x98, 0x5b, 0x90, 0x93, 0x1a, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 0x22, 0x24, + 0xc1, 0xc5, 0x5e, 0x04, 0x61, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xc1, 0xb8, 0x42, 0xca, + 0x5c, 0xbc, 0x50, 0x5b, 0xe2, 0xd3, 0x32, 0x53, 0x73, 0x52, 0x24, 0x98, 0xc0, 0xf2, 0x3c, 0x50, + 0x41, 0x37, 0x90, 0x98, 0x92, 0x3a, 0x17, 0x3f, 0xdc, 0xc0, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, + 0x21, 0x11, 0x2e, 0xd6, 0xd4, 0xa2, 0xa2, 0xfc, 0x22, 0xa8, 0x79, 0x10, 0x8e, 0x51, 0x00, 0x17, + 0x3b, 0x54, 0xa1, 0x90, 0x2b, 0x17, 0x9f, 0x7b, 0x6a, 0x09, 0x94, 0xe7, 0x99, 0x97, 0x96, 0x2f, + 0x24, 0xae, 0x07, 0x35, 0x54, 0x0f, 0xd5, 0x75, 0x52, 0x12, 0x98, 0x12, 0x10, 0x5b, 0x94, 0x18, + 0x9c, 0x64, 0x4e, 0x3c, 0x94, 0x63, 0xbc, 0xf1, 0x50, 0x8e, 0xa1, 0xe1, 0x91, 0x1c, 0xe3, 0x89, + 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0x43, + 0x12, 0x1b, 0xd8, 0xc3, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa8, 0x79, 0x17, 0x13, 0x35, + 0x01, 0x00, 0x00, +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.proto b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.proto new file mode 100644 index 000000000..e34697f3a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2/api.proto @@ -0,0 +1,29 @@ +syntax = 'proto3'; + +package v1beta2; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +option (gogoproto.goproto_stringer_all) = false; +option (gogoproto.stringer_all) = true; +option (gogoproto.goproto_getters_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.goproto_unrecognized_all) = false; + +// Renames a field from v1beta1 ExampleRequest. +message ExampleRequest { + string request = 1; + string v1beta2_field = 2; +} + +message ExampleResponse { + string error = 1; +} + +// Example is a simple example service for general reference on the recommended +// kubelet plugin model and plugin watcher testing. +service Example { + rpc GetExampleInfo(ExampleRequest) returns (ExampleResponse) {} +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/plugin_watcher.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/plugin_watcher.go new file mode 100644 index 000000000..9a5241cb2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/plugin_watcher.go @@ -0,0 +1,260 @@ +/* +Copyright 2018 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 pluginwatcher + +import ( + "fmt" + "net" + "os" + "path" + "path/filepath" + "sync" + "time" + + "github.com/fsnotify/fsnotify" + "github.com/golang/glog" + "golang.org/x/net/context" + "google.golang.org/grpc" + registerapi "k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1" + utilfs "k8s.io/kubernetes/pkg/util/filesystem" +) + +// RegisterCallbackFn is the type of the callback function that handlers will provide +type RegisterCallbackFn func(pluginName string, endpoint string, versions []string, socketPath string) (error, chan bool) + +// Watcher is the plugin watcher +type Watcher struct { + path string + handlers map[string]RegisterCallbackFn + stopCh chan interface{} + fs utilfs.Filesystem + watcher *fsnotify.Watcher + wg sync.WaitGroup + mutex sync.Mutex +} + +// NewWatcher provides a new watcher +func NewWatcher(sockDir string) Watcher { + return Watcher{ + path: sockDir, + handlers: make(map[string]RegisterCallbackFn), + fs: &utilfs.DefaultFs{}, + } +} + +// AddHandler registers a callback to be invoked for a particular type of plugin +func (w *Watcher) AddHandler(handlerType string, handlerCbkFn RegisterCallbackFn) { + w.mutex.Lock() + defer w.mutex.Unlock() + w.handlers[handlerType] = handlerCbkFn +} + +// Creates the plugin directory, if it doesn't already exist. +func (w *Watcher) createPluginDir() error { + glog.V(4).Infof("Ensuring Plugin directory at %s ", w.path) + if err := w.fs.MkdirAll(w.path, 0755); err != nil { + return fmt.Errorf("error (re-)creating driver directory: %s", err) + } + return nil +} + +// Walks through the plugin directory to discover any existing plugin sockets. +func (w *Watcher) traversePluginDir() error { + files, err := w.fs.ReadDir(w.path) + if err != nil { + return fmt.Errorf("error reading the plugin directory: %v", err) + } + for _, f := range files { + // Currently only supports flat fs namespace under the plugin directory. + // TODO: adds support for hierarchical fs namespace. + if !f.IsDir() && filepath.Base(f.Name())[0] != '.' { + go func(sockName string) { + w.watcher.Events <- fsnotify.Event{ + Name: sockName, + Op: fsnotify.Op(uint32(1)), + } + }(path.Join(w.path, f.Name())) + } + } + return nil +} + +func (w *Watcher) init() error { + if err := w.createPluginDir(); err != nil { + return err + } + return nil +} + +func (w *Watcher) registerPlugin(socketPath string) error { + //TODO: Implement rate limiting to mitigate any DOS kind of attacks. + glog.V(4).Infof("registerPlugin called for socketPath: %s", socketPath) + client, conn, err := dial(socketPath) + if err != nil { + return fmt.Errorf("dial failed at socket %s, err: %v", socketPath, err) + } + defer conn.Close() + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + infoResp, err := client.GetInfo(ctx, ®isterapi.InfoRequest{}) + if err != nil { + return fmt.Errorf("failed to get plugin info using RPC GetInfo at socket %s, err: %v", socketPath, err) + } + if err := w.invokeRegistrationCallbackAtHandler(ctx, client, infoResp, socketPath); err != nil { + return fmt.Errorf("failed to register plugin. Callback handler returned err: %v", err) + } + glog.V(4).Infof("Successfully registered plugin for plugin type: %s, name: %s, socket: %s", infoResp.Type, infoResp.Name, socketPath) + return nil +} + +func (w *Watcher) invokeRegistrationCallbackAtHandler(ctx context.Context, client registerapi.RegistrationClient, infoResp *registerapi.PluginInfo, socketPath string) error { + var handlerCbkFn RegisterCallbackFn + var ok bool + handlerCbkFn, ok = w.handlers[infoResp.Type] + if !ok { + if _, err := client.NotifyRegistrationStatus(ctx, ®isterapi.RegistrationStatus{ + PluginRegistered: false, + Error: fmt.Sprintf("No handler found registered for plugin type: %s, socket: %s", infoResp.Type, socketPath), + }); err != nil { + glog.Errorf("Failed to send registration status at socket %s, err: %v", socketPath, err) + } + return fmt.Errorf("no handler found registered for plugin type: %s, socket: %s", infoResp.Type, socketPath) + } + + var versions []string + for _, version := range infoResp.SupportedVersions { + versions = append(versions, version) + } + // calls handler callback to verify registration request + err, chanForAckOfNotification := handlerCbkFn(infoResp.Name, infoResp.Endpoint, versions, socketPath) + if err != nil { + if _, err := client.NotifyRegistrationStatus(ctx, ®isterapi.RegistrationStatus{ + PluginRegistered: false, + Error: fmt.Sprintf("Plugin registration failed with err: %v", err), + }); err != nil { + glog.Errorf("Failed to send registration status at socket %s, err: %v", socketPath, err) + } + chanForAckOfNotification <- false + return fmt.Errorf("plugin registration failed with err: %v", err) + } + + if _, err := client.NotifyRegistrationStatus(ctx, ®isterapi.RegistrationStatus{ + PluginRegistered: true, + }); err != nil { + return fmt.Errorf("failed to send registration status at socket %s, err: %v", socketPath, err) + } + chanForAckOfNotification <- true + return nil +} + +// Start watches for the creation of plugin sockets at the path +func (w *Watcher) Start() error { + glog.V(2).Infof("Plugin Watcher Start at %s", w.path) + w.stopCh = make(chan interface{}) + + // Creating the directory to be watched if it doesn't exist yet, + // and walks through the directory to discover the existing plugins. + if err := w.init(); err != nil { + return err + } + + watcher, err := fsnotify.NewWatcher() + if err != nil { + return fmt.Errorf("failed to start plugin watcher, err: %v", err) + } + + if err := watcher.Add(w.path); err != nil { + watcher.Close() + return fmt.Errorf("failed to start plugin watcher, err: %v", err) + } + + w.watcher = watcher + + if err := w.traversePluginDir(); err != nil { + watcher.Close() + return fmt.Errorf("failed to traverse plugin socket path, err: %v", err) + } + + w.wg.Add(1) + go func(watcher *fsnotify.Watcher) { + defer w.wg.Done() + for { + select { + case event := <-watcher.Events: + if event.Op&fsnotify.Create == fsnotify.Create { + go func(eventName string) { + err := w.registerPlugin(eventName) + if err != nil { + glog.Errorf("Plugin %s registration failed with error: %v", eventName, err) + } + }(event.Name) + } + continue + case err := <-watcher.Errors: + //TODO: Handle errors by taking corrective measures + if err != nil { + glog.Errorf("Watcher received error: %v", err) + } + continue + + case <-w.stopCh: + watcher.Close() + break + } + break + } + }(watcher) + return nil +} + +// Stop stops probing the creation of plugin sockets at the path +func (w *Watcher) Stop() error { + close(w.stopCh) + c := make(chan struct{}) + go func() { + defer close(c) + w.wg.Wait() + }() + select { + case <-c: + case <-time.After(10 * time.Second): + return fmt.Errorf("timeout on stopping watcher") + } + return nil +} + +// Cleanup cleans the path by removing sockets +func (w *Watcher) Cleanup() error { + return os.RemoveAll(w.path) +} + +// Dial establishes the gRPC communication with the picked up plugin socket. https://godoc.org/google.golang.org/grpc#Dial +func dial(unixSocketPath string) (registerapi.RegistrationClient, *grpc.ClientConn, error) { + c, err := grpc.Dial(unixSocketPath, grpc.WithInsecure(), grpc.WithBlock(), + grpc.WithTimeout(10*time.Second), + grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { + return net.DialTimeout("unix", addr, timeout) + }), + ) + + if err != nil { + return nil, nil, fmt.Errorf("failed to dial socket %s, err: %v", unixSocketPath, err) + } + + return registerapi.NewRegistrationClient(c), c, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/plugin_watcher_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/plugin_watcher_test.go new file mode 100644 index 000000000..44bccf9a6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/plugin_watcher_test.go @@ -0,0 +1,220 @@ +/* +Copyright 2018 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 pluginwatcher + +import ( + "fmt" + "io/ioutil" + "strconv" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + "golang.org/x/net/context" + + "k8s.io/apimachinery/pkg/util/sets" + registerapi "k8s.io/kubernetes/pkg/kubelet/apis/pluginregistration/v1alpha1" + v1beta1 "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta1" + v1beta2 "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher/example_plugin_apis/v1beta2" +) + +func TestExamplePlugin(t *testing.T) { + socketDir, err := ioutil.TempDir("", "plugin_test") + require.NoError(t, err) + socketPath := socketDir + "/plugin.sock" + w := NewWatcher(socketDir) + + testCases := []struct { + description string + expectedEndpoint string + returnErr error + }{ + { + description: "Successfully register plugin through inotify", + expectedEndpoint: "", + returnErr: nil, + }, + { + description: "Successfully register plugin through inotify and got expected optional endpoint", + expectedEndpoint: "dummyEndpoint", + returnErr: nil, + }, + { + description: "Fails registration because endpoint is expected to be non-empty", + expectedEndpoint: "dummyEndpoint", + returnErr: fmt.Errorf("empty endpoint received"), + }, + { + description: "Successfully register plugin through inotify after plugin restarts", + expectedEndpoint: "", + returnErr: nil, + }, + { + description: "Fails registration with conflicting plugin name", + expectedEndpoint: "", + returnErr: fmt.Errorf("conflicting plugin name"), + }, + { + description: "Successfully register plugin during initial traverse after plugin watcher restarts", + expectedEndpoint: "", + returnErr: nil, + }, + { + description: "Fails registration with conflicting plugin name during initial traverse after plugin watcher restarts", + expectedEndpoint: "", + returnErr: fmt.Errorf("conflicting plugin name"), + }, + } + + callbackCount := struct { + mutex sync.Mutex + count int32 + }{} + w.AddHandler(PluginType, func(name string, endpoint string, versions []string, sockPath string) (error, chan bool) { + callbackCount.mutex.Lock() + localCount := callbackCount.count + callbackCount.count = callbackCount.count + 1 + callbackCount.mutex.Unlock() + + require.True(t, localCount <= int32((len(testCases)-1))) + require.Equal(t, PluginName, name, "Plugin name mismatched!!") + retError := testCases[localCount].returnErr + if retError == nil || retError.Error() != "empty endpoint received" { + require.Equal(t, testCases[localCount].expectedEndpoint, endpoint, "Unexpected endpoint") + } else { + require.NotEqual(t, testCases[localCount].expectedEndpoint, endpoint, "Unexpected endpoint") + } + + require.Equal(t, []string{"v1beta1", "v1beta2"}, versions, "Plugin version mismatched!!") + // Verifies the grpcServer is ready to serve services. + _, conn, err := dial(sockPath) + require.Nil(t, err) + defer conn.Close() + + // The plugin handler should be able to use any listed service API version. + v1beta1Client := v1beta1.NewExampleClient(conn) + v1beta2Client := v1beta2.NewExampleClient(conn) + + // Tests v1beta1 GetExampleInfo + _, err = v1beta1Client.GetExampleInfo(context.Background(), &v1beta1.ExampleRequest{}) + require.Nil(t, err) + + // Tests v1beta1 GetExampleInfo + _, err = v1beta2Client.GetExampleInfo(context.Background(), &v1beta2.ExampleRequest{}) + //atomic.AddInt32(&callbackCount, 1) + chanForAckOfNotification := make(chan bool) + + go func() { + select { + case <-chanForAckOfNotification: + close(chanForAckOfNotification) + case <-time.After(time.Second): + t.Fatalf("Timed out while waiting for notification ack") + } + }() + return retError, chanForAckOfNotification + }) + require.NoError(t, w.Start()) + + p := NewTestExamplePlugin("") + require.NoError(t, p.Serve(socketPath)) + require.True(t, waitForPluginRegistrationStatus(t, p.registrationStatus)) + + require.NoError(t, p.Stop()) + + p = NewTestExamplePlugin("dummyEndpoint") + require.NoError(t, p.Serve(socketPath)) + require.True(t, waitForPluginRegistrationStatus(t, p.registrationStatus)) + + require.NoError(t, p.Stop()) + + p = NewTestExamplePlugin("") + require.NoError(t, p.Serve(socketPath)) + require.False(t, waitForPluginRegistrationStatus(t, p.registrationStatus)) + + // Trying to start a plugin service at the same socket path should fail + // with "bind: address already in use" + require.NotNil(t, p.Serve(socketPath)) + + // grpcServer.Stop() will remove the socket and starting plugin service + // at the same path again should succeeds and trigger another callback. + require.NoError(t, p.Stop()) + p = NewTestExamplePlugin("") + go func() { + require.Nil(t, p.Serve(socketPath)) + }() + require.True(t, waitForPluginRegistrationStatus(t, p.registrationStatus)) + + // Starting another plugin with the same name got verification error. + p2 := NewTestExamplePlugin("") + socketPath2 := socketDir + "/plugin2.sock" + go func() { + require.NoError(t, p2.Serve(socketPath2)) + }() + require.False(t, waitForPluginRegistrationStatus(t, p2.registrationStatus)) + + // Restarts plugin watcher should traverse the socket directory and issues a + // callback for every existing socket. + require.NoError(t, w.Stop()) + errCh := make(chan error) + go func() { + errCh <- w.Start() + }() + + var wg sync.WaitGroup + wg.Add(2) + var pStatus string + var p2Status string + go func() { + pStatus = strconv.FormatBool(waitForPluginRegistrationStatus(t, p.registrationStatus)) + wg.Done() + }() + go func() { + p2Status = strconv.FormatBool(waitForPluginRegistrationStatus(t, p2.registrationStatus)) + wg.Done() + }() + wg.Wait() + expectedSet := sets.NewString() + expectedSet.Insert("true", "false") + actualSet := sets.NewString() + actualSet.Insert(pStatus, p2Status) + + require.Equal(t, expectedSet, actualSet) + + select { + case err = <-errCh: + require.NoError(t, err) + case <-time.After(time.Second): + t.Fatalf("Timed out while waiting for watcher start") + + } + + require.NoError(t, w.Stop()) + err = w.Cleanup() + require.NoError(t, err) +} + +func waitForPluginRegistrationStatus(t *testing.T, statusCh chan registerapi.RegistrationStatus) bool { + select { + case status := <-statusCh: + return status.PluginRegistered + case <-time.After(10 * time.Second): + t.Fatalf("Timed out while waiting for registration status") + } + return false +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volume_host.go b/vendor/k8s.io/kubernetes/pkg/kubelet/volume_host.go index cf1fc77de..1d8bfcc9f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volume_host.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volume_host.go @@ -23,16 +23,19 @@ import ( "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/configmap" "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/mountpod" "k8s.io/kubernetes/pkg/kubelet/secret" + "k8s.io/kubernetes/pkg/kubelet/token" "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" @@ -49,6 +52,7 @@ func NewInitializedVolumePluginMgr( kubelet *Kubelet, secretManager secret.Manager, configMapManager configmap.Manager, + tokenManager *token.Manager, plugins []volume.VolumePlugin, prober volume.DynamicPluginProber) (*volume.VolumePluginMgr, error) { @@ -61,6 +65,7 @@ func NewInitializedVolumePluginMgr( volumePluginMgr: volume.VolumePluginMgr{}, secretManager: secretManager, configMapManager: configMapManager, + tokenManager: tokenManager, mountPodManager: mountPodManager, } @@ -84,6 +89,7 @@ type kubeletVolumeHost struct { kubelet *Kubelet volumePluginMgr volume.VolumePluginMgr secretManager secret.Manager + tokenManager *token.Manager configMapManager configmap.Manager mountPodManager mountpod.Manager } @@ -92,6 +98,10 @@ func (kvh *kubeletVolumeHost) GetVolumeDevicePluginDir(pluginName string) string return kvh.kubelet.getVolumeDevicePluginDir(pluginName) } +func (kvh *kubeletVolumeHost) GetPodsDir() string { + return kvh.kubelet.getPodsDir() +} + func (kvh *kubeletVolumeHost) GetPodVolumeDir(podUID types.UID, pluginName string, volumeName string) string { dir := kvh.kubelet.getPodVolumeDir(podUID, pluginName, volumeName) if runtime.GOOS == "windows" { @@ -148,7 +158,7 @@ func (kvh *kubeletVolumeHost) GetCloudProvider() cloudprovider.Interface { func (kvh *kubeletVolumeHost) GetMounter(pluginName string) mount.Interface { exec, err := kvh.getMountExec(pluginName) if err != nil { - glog.V(2).Info("Error finding mount pod for plugin %s: %s", pluginName, err.Error()) + glog.V(2).Infof("Error finding mount pod for plugin %s: %s", pluginName, err.Error()) // Use the default mounter exec = nil } @@ -186,6 +196,10 @@ func (kvh *kubeletVolumeHost) GetConfigMapFunc() func(namespace, name string) (* return kvh.configMapManager.GetConfigMap } +func (kvh *kubeletVolumeHost) GetServiceAccountTokenFunc() func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return kvh.tokenManager.GetServiceAccountToken +} + func (kvh *kubeletVolumeHost) GetNodeLabels() (map[string]string, error) { node, err := kvh.kubelet.GetNode() if err != nil { @@ -198,10 +212,14 @@ func (kvh *kubeletVolumeHost) GetNodeName() types.NodeName { return kvh.kubelet.nodeName } +func (kvh *kubeletVolumeHost) GetEventRecorder() record.EventRecorder { + return kvh.kubelet.recorder +} + func (kvh *kubeletVolumeHost) GetExec(pluginName string) mount.Exec { exec, err := kvh.getMountExec(pluginName) if err != nil { - glog.V(2).Info("Error finding mount pod for plugin %s: %s", pluginName, err.Error()) + glog.V(2).Infof("Error finding mount pod for plugin %s: %s", pluginName, err.Error()) // Use the default exec exec = nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/BUILD index bac59a12b..c79fad513 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/BUILD @@ -14,6 +14,7 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/kubelet/volumemanager/cache", deps = [ + "//pkg/features:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/util:go_default_library", "//pkg/volume/util/operationexecutor:go_default_library", @@ -21,6 +22,7 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/actual_state_of_world.go b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/actual_state_of_world.go index 140c434fe..82aef86c7 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/actual_state_of_world.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/actual_state_of_world.go @@ -28,6 +28,8 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/operationexecutor" @@ -58,7 +60,7 @@ type ActualStateOfWorld interface { // volume, reset the pod's remountRequired value. // If a volume with the name volumeName does not exist in the list of // attached volumes, an error is returned. - AddPodToVolume(podName volumetypes.UniquePodName, podUID types.UID, volumeName v1.UniqueVolumeName, mounter volume.Mounter, blockVolumeMapper volume.BlockVolumeMapper, outerVolumeSpecName string, volumeGidValue string) error + AddPodToVolume(podName volumetypes.UniquePodName, podUID types.UID, volumeName v1.UniqueVolumeName, mounter volume.Mounter, blockVolumeMapper volume.BlockVolumeMapper, outerVolumeSpecName string, volumeGidValue string, volumeSpec *volume.Spec) error // MarkRemountRequired marks each volume that is successfully attached and // mounted for the specified pod as requiring remount (if the plugin for the @@ -148,6 +150,11 @@ type ActualStateOfWorld interface { // with pod's unique name. This map can be used to determine which pod is currently // in actual state of world. GetPods() map[volumetypes.UniquePodName]bool + + // MarkFSResizeRequired marks each volume that is successfully attached and + // mounted for the specified pod as requiring file system resize (if the plugin for the + // volume indicates it requires file system resize). + MarkFSResizeRequired(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) } // MountedVolume represents a volume that has successfully been mounted to a pod. @@ -268,6 +275,13 @@ type mountedPod struct { // mapper used to block volumes support blockVolumeMapper volume.BlockVolumeMapper + // spec is the volume spec containing the specification for this volume. + // Used to generate the volume plugin object, and passed to plugin methods. + // In particular, the Unmount method uses spec.Name() as the volumeSpecName + // in the mount path: + // /var/lib/kubelet/pods/{podUID}/volumes/{escapeQualifiedPluginName}/{volumeSpecName}/ + volumeSpec *volume.Spec + // outerVolumeSpecName is the volume.Spec.Name() of the volume as referenced // directly in the pod. If the volume was referenced through a persistent // volume claim, this contains the volume.Spec.Name() of the persistent @@ -284,6 +298,10 @@ type mountedPod struct { // volumeGidValue contains the value of the GID annotation, if present. volumeGidValue string + + // fsResizeRequired indicates the underlying volume has been successfully + // mounted to this pod but its size has been expanded after that. + fsResizeRequired bool } func (asw *actualStateOfWorld) MarkVolumeAsAttached( @@ -303,7 +321,8 @@ func (asw *actualStateOfWorld) MarkVolumeAsMounted( mounter volume.Mounter, blockVolumeMapper volume.BlockVolumeMapper, outerVolumeSpecName string, - volumeGidValue string) error { + volumeGidValue string, + volumeSpec *volume.Spec) error { return asw.AddPodToVolume( podName, podUID, @@ -311,7 +330,8 @@ func (asw *actualStateOfWorld) MarkVolumeAsMounted( mounter, blockVolumeMapper, outerVolumeSpecName, - volumeGidValue) + volumeGidValue, + volumeSpec) } func (asw *actualStateOfWorld) AddVolumeToReportAsAttached(volumeName v1.UniqueVolumeName, nodeName types.NodeName) { @@ -403,7 +423,8 @@ func (asw *actualStateOfWorld) AddPodToVolume( mounter volume.Mounter, blockVolumeMapper volume.BlockVolumeMapper, outerVolumeSpecName string, - volumeGidValue string) error { + volumeGidValue string, + volumeSpec *volume.Spec) error { asw.Lock() defer asw.Unlock() @@ -423,6 +444,7 @@ func (asw *actualStateOfWorld) AddPodToVolume( blockVolumeMapper: blockVolumeMapper, outerVolumeSpecName: outerVolumeSpecName, volumeGidValue: volumeGidValue, + volumeSpec: volumeSpec, } } @@ -433,6 +455,34 @@ func (asw *actualStateOfWorld) AddPodToVolume( return nil } +func (asw *actualStateOfWorld) MarkVolumeAsResized( + podName volumetypes.UniquePodName, + volumeName v1.UniqueVolumeName) error { + asw.Lock() + defer asw.Unlock() + + volumeObj, volumeExists := asw.attachedVolumes[volumeName] + if !volumeExists { + return fmt.Errorf( + "no volume with the name %q exists in the list of attached volumes", + volumeName) + } + + podObj, podExists := volumeObj.mountedPods[podName] + if !podExists { + return fmt.Errorf( + "no pod with the name %q exists in the mounted pods list of volume %s", + podName, + volumeName) + } + + glog.V(5).Infof("Volume %s(OuterVolumeSpecName %s) of pod %s has been resized", + volumeName, podObj.outerVolumeSpecName, podName) + podObj.fsResizeRequired = false + asw.attachedVolumes[volumeName].mountedPods[podName] = podObj + return nil +} + func (asw *actualStateOfWorld) MarkRemountRequired( podName volumetypes.UniquePodName) { asw.Lock() @@ -444,7 +494,7 @@ func (asw *actualStateOfWorld) MarkRemountRequired( } volumePlugin, err := - asw.volumePluginMgr.FindPluginBySpec(volumeObj.spec) + asw.volumePluginMgr.FindPluginBySpec(podObj.volumeSpec) if err != nil || volumePlugin == nil { // Log and continue processing glog.Errorf( @@ -452,7 +502,7 @@ func (asw *actualStateOfWorld) MarkRemountRequired( podObj.podName, podObj.podUID, volumeObj.volumeName, - volumeObj.spec.Name()) + podObj.volumeSpec.Name()) continue } @@ -464,6 +514,46 @@ func (asw *actualStateOfWorld) MarkRemountRequired( } } +func (asw *actualStateOfWorld) MarkFSResizeRequired( + volumeName v1.UniqueVolumeName, + podName volumetypes.UniquePodName) { + asw.Lock() + defer asw.Unlock() + volumeObj, exist := asw.attachedVolumes[volumeName] + if !exist { + glog.Warningf("MarkFSResizeRequired for volume %s failed as volume not exist", volumeName) + return + } + + podObj, exist := volumeObj.mountedPods[podName] + if !exist { + glog.Warningf("MarkFSResizeRequired for volume %s failed "+ + "as pod(%s) not exist", volumeName, podName) + return + } + + volumePlugin, err := + asw.volumePluginMgr.FindExpandablePluginBySpec(podObj.volumeSpec) + if err != nil || volumePlugin == nil { + // Log and continue processing + glog.Errorf( + "MarkFSResizeRequired failed to find expandable plugin for pod %q volume: %q (volSpecName: %q)", + podObj.podName, + volumeObj.volumeName, + podObj.volumeSpec.Name()) + return + } + + if volumePlugin.RequiresFSResize() { + if !podObj.fsResizeRequired { + glog.V(3).Infof("PVC volume %s(OuterVolumeSpecName %s) of pod %s requires file system resize", + volumeName, podObj.outerVolumeSpecName, podName) + podObj.fsResizeRequired = true + } + asw.attachedVolumes[volumeName].mountedPods[podName] = podObj + } +} + func (asw *actualStateOfWorld) SetVolumeGloballyMounted( volumeName v1.UniqueVolumeName, globallyMounted bool, devicePath, deviceMountPath string) error { asw.Lock() @@ -535,8 +625,14 @@ func (asw *actualStateOfWorld) PodExistsInVolume( } podObj, podExists := volumeObj.mountedPods[podName] - if podExists && podObj.remountRequired { - return true, volumeObj.devicePath, newRemountRequiredError(volumeObj.volumeName, podObj.podName) + if podExists { + if podObj.remountRequired { + return true, volumeObj.devicePath, newRemountRequiredError(volumeObj.volumeName, podObj.podName) + } + if podObj.fsResizeRequired && + utilfeature.DefaultFeatureGate.Enabled(features.ExpandInUsePersistentVolumes) { + return true, volumeObj.devicePath, newFsResizeRequiredError(volumeObj.volumeName, podObj.podName) + } } return podExists, volumeObj.devicePath, nil @@ -546,8 +642,8 @@ func (asw *actualStateOfWorld) VolumeExistsWithSpecName(podName volumetypes.Uniq asw.RLock() defer asw.RUnlock() for _, volumeObj := range asw.attachedVolumes { - for name := range volumeObj.mountedPods { - if podName == name && volumeObj.spec.Name() == volumeSpecName { + for name, podObj := range volumeObj.mountedPods { + if podName == name && podObj.volumeSpec.Name() == volumeSpecName { return true } } @@ -705,6 +801,35 @@ func newRemountRequiredError( } } +// fsResizeRequiredError is an error returned when PodExistsInVolume() found +// volume/pod attached/mounted but fsResizeRequired was true, indicating the +// given volume receives an resize request after attached/mounted. +type fsResizeRequiredError struct { + volumeName v1.UniqueVolumeName + podName volumetypes.UniquePodName +} + +func (err fsResizeRequiredError) Error() string { + return fmt.Sprintf( + "volumeName %q mounted to %q needs to resize file system", + err.volumeName, err.podName) +} + +func newFsResizeRequiredError( + volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) error { + return fsResizeRequiredError{ + volumeName: volumeName, + podName: podName, + } +} + +// IsFSResizeRequiredError returns true if the specified error is a +// fsResizeRequiredError. +func IsFSResizeRequiredError(err error) bool { + _, ok := err.(fsResizeRequiredError) + return ok +} + // getMountedVolume constructs and returns a MountedVolume object from the given // mountedPod and attachedVolume objects. func getMountedVolume( @@ -713,13 +838,13 @@ func getMountedVolume( MountedVolume: operationexecutor.MountedVolume{ PodName: mountedPod.podName, VolumeName: attachedVolume.volumeName, - InnerVolumeSpecName: attachedVolume.spec.Name(), + InnerVolumeSpecName: mountedPod.volumeSpec.Name(), OuterVolumeSpecName: mountedPod.outerVolumeSpecName, PluginName: attachedVolume.pluginName, PodUID: mountedPod.podUID, Mounter: mountedPod.mounter, BlockVolumeMapper: mountedPod.blockVolumeMapper, VolumeGidValue: mountedPod.volumeGidValue, - VolumeSpec: attachedVolume.spec, + VolumeSpec: mountedPod.volumeSpec, DeviceMountPath: attachedVolume.deviceMountPath}} } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/actual_state_of_world_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/actual_state_of_world_test.go index 634a3328c..9ae03e5cf 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/actual_state_of_world_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/actual_state_of_world_test.go @@ -56,10 +56,13 @@ func Test_MarkVolumeAsAttached_Positive_NewVolume(t *testing.T) { } volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]} devicePath := "fake/device/path" - generatedVolumeName, _ := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) + generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) + if err != nil { + t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: Actual: <%v>", err) + } // Act - err := asw.MarkVolumeAsAttached(emptyVolumeName, volumeSpec, "" /* nodeName */, devicePath) + err = asw.MarkVolumeAsAttached(emptyVolumeName, volumeSpec, "" /* nodeName */, devicePath) // Assert if err != nil { @@ -143,9 +146,12 @@ func Test_MarkVolumeAsAttached_Positive_ExistingVolume(t *testing.T) { }, } volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]} - generatedVolumeName, _ := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) + generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) + if err != nil { + t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: Actual: <%v>", err) + } - err := asw.MarkVolumeAsAttached(emptyVolumeName, volumeSpec, "" /* nodeName */, devicePath) + err = asw.MarkVolumeAsAttached(emptyVolumeName, volumeSpec, "" /* nodeName */, devicePath) if err != nil { t.Fatalf("MarkVolumeAsAttached failed. Expected: Actual: <%v>", err) } @@ -192,6 +198,9 @@ func Test_AddPodToVolume_Positive_ExistingVolumeNewNode(t *testing.T) { } volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]} generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) + if err != nil { + t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: Actual: <%v>", err) + } err = asw.MarkVolumeAsAttached(emptyVolumeName, volumeSpec, "" /* nodeName */, devicePath) if err != nil { @@ -211,7 +220,7 @@ func Test_AddPodToVolume_Positive_ExistingVolumeNewNode(t *testing.T) { // Act err = asw.AddPodToVolume( - podName, pod.UID, generatedVolumeName, mounter, mapper, volumeSpec.Name(), "" /* volumeGidValue */) + podName, pod.UID, generatedVolumeName, mounter, mapper, volumeSpec.Name(), "" /* volumeGidValue */, volumeSpec) // Assert if err != nil { @@ -257,6 +266,9 @@ func Test_AddPodToVolume_Positive_ExistingVolumeExistingNode(t *testing.T) { volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]} generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec( plugin, volumeSpec) + if err != nil { + t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: Actual: <%v>", err) + } err = asw.MarkVolumeAsAttached(emptyVolumeName, volumeSpec, "" /* nodeName */, devicePath) if err != nil { @@ -275,14 +287,14 @@ func Test_AddPodToVolume_Positive_ExistingVolumeExistingNode(t *testing.T) { } err = asw.AddPodToVolume( - podName, pod.UID, generatedVolumeName, mounter, mapper, volumeSpec.Name(), "" /* volumeGidValue */) + podName, pod.UID, generatedVolumeName, mounter, mapper, volumeSpec.Name(), "" /* volumeGidValue */, volumeSpec) if err != nil { t.Fatalf("AddPodToVolume failed. Expected: Actual: <%v>", err) } // Act err = asw.AddPodToVolume( - podName, pod.UID, generatedVolumeName, mounter, mapper, volumeSpec.Name(), "" /* volumeGidValue */) + podName, pod.UID, generatedVolumeName, mounter, mapper, volumeSpec.Name(), "" /* volumeGidValue */, volumeSpec) // Assert if err != nil { @@ -296,6 +308,119 @@ func Test_AddPodToVolume_Positive_ExistingVolumeExistingNode(t *testing.T) { verifyVolumeExistsWithSpecNameInVolumeAsw(t, podName, volumeSpec.Name(), asw) } +// Populates data struct with a volume +// Calls AddPodToVolume() twice to add the same pod to the volume +// Verifies volume/pod combo exist using PodExistsInVolume() and the second call +// did not fail. +func Test_AddTwoPodsToVolume_Positive(t *testing.T) { + // Arrange + volumePluginMgr, plugin := volumetesting.GetTestVolumePluginMgr(t) + asw := NewActualStateOfWorld("mynode" /* nodeName */, volumePluginMgr) + devicePath := "fake/device/path" + + pod1 := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + UID: "pod1uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "volume-name-1", + VolumeSource: v1.VolumeSource{ + GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ + PDName: "fake-device1", + }, + }, + }, + }, + }, + } + + pod2 := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod2", + UID: "pod2uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "volume-name-2", + VolumeSource: v1.VolumeSource{ + GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ + PDName: "fake-device1", + }, + }, + }, + }, + }, + } + volumeSpec1 := &volume.Spec{Volume: &pod1.Spec.Volumes[0]} + volumeSpec2 := &volume.Spec{Volume: &pod2.Spec.Volumes[0]} + generatedVolumeName1, err := util.GetUniqueVolumeNameFromSpec( + plugin, volumeSpec1) + generatedVolumeName2, err := util.GetUniqueVolumeNameFromSpec( + plugin, volumeSpec2) + + if generatedVolumeName1 != generatedVolumeName2 { + t.Fatalf( + "Unique volume names should be the same. unique volume name 1: <%q> unique volume name 2: <%q>, spec1 %v, spec2 %v", + generatedVolumeName1, + generatedVolumeName2, volumeSpec1, volumeSpec2) + } + + err = asw.MarkVolumeAsAttached(generatedVolumeName1, volumeSpec1, "" /* nodeName */, devicePath) + if err != nil { + t.Fatalf("MarkVolumeAsAttached failed. Expected: Actual: <%v>", err) + } + podName1 := util.GetUniquePodName(pod1) + + mounter1, err := plugin.NewMounter(volumeSpec1, pod1, volume.VolumeOptions{}) + if err != nil { + t.Fatalf("NewMounter failed. Expected: Actual: <%v>", err) + } + + mapper1, err := plugin.NewBlockVolumeMapper(volumeSpec1, pod1, volume.VolumeOptions{}) + if err != nil { + t.Fatalf("NewBlockVolumeMapper failed. Expected: Actual: <%v>", err) + } + + err = asw.AddPodToVolume( + podName1, pod1.UID, generatedVolumeName1, mounter1, mapper1, volumeSpec1.Name(), "" /* volumeGidValue */, volumeSpec1) + if err != nil { + t.Fatalf("AddPodToVolume failed. Expected: Actual: <%v>", err) + } + + podName2 := util.GetUniquePodName(pod2) + + mounter2, err := plugin.NewMounter(volumeSpec2, pod2, volume.VolumeOptions{}) + if err != nil { + t.Fatalf("NewMounter failed. Expected: Actual: <%v>", err) + } + + mapper2, err := plugin.NewBlockVolumeMapper(volumeSpec2, pod2, volume.VolumeOptions{}) + if err != nil { + t.Fatalf("NewBlockVolumeMapper failed. Expected: Actual: <%v>", err) + } + + err = asw.AddPodToVolume( + podName2, pod2.UID, generatedVolumeName1, mounter2, mapper2, volumeSpec2.Name(), "" /* volumeGidValue */, volumeSpec2) + if err != nil { + t.Fatalf("AddPodToVolume failed. Expected: Actual: <%v>", err) + } + + verifyVolumeExistsAsw(t, generatedVolumeName1, true /* shouldExist */, asw) + verifyVolumeDoesntExistInUnmountedVolumes(t, generatedVolumeName1, asw) + verifyVolumeDoesntExistInGloballyMountedVolumes(t, generatedVolumeName1, asw) + verifyPodExistsInVolumeAsw(t, podName1, generatedVolumeName1, "fake/device/path" /* expectedDevicePath */, asw) + verifyVolumeExistsWithSpecNameInVolumeAsw(t, podName1, volumeSpec1.Name(), asw) + verifyPodExistsInVolumeAsw(t, podName2, generatedVolumeName2, "fake/device/path" /* expectedDevicePath */, asw) + verifyVolumeExistsWithSpecNameInVolumeAsw(t, podName2, volumeSpec2.Name(), asw) + verifyVolumeSpecNameInVolumeAsw(t, podName1, []*volume.Spec{volumeSpec1}, asw) + verifyVolumeSpecNameInVolumeAsw(t, podName2, []*volume.Spec{volumeSpec2}, asw) + +} + // Calls AddPodToVolume() to add pod to empty data struct // Verifies call fails with "volume does not exist" error. func Test_AddPodToVolume_Negative_VolumeDoesntExist(t *testing.T) { @@ -356,7 +481,7 @@ func Test_AddPodToVolume_Negative_VolumeDoesntExist(t *testing.T) { // Act err = asw.AddPodToVolume( - podName, pod.UID, volumeName, mounter, mapper, volumeSpec.Name(), "" /* volumeGidValue */) + podName, pod.UID, volumeName, mounter, mapper, volumeSpec.Name(), "" /* volumeGidValue */, volumeSpec) // Assert if err == nil { @@ -405,6 +530,9 @@ func Test_MarkDeviceAsMounted_Positive_NewVolume(t *testing.T) { devicePath := "fake/device/path" deviceMountPath := "fake/device/mount/path" generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) + if err != nil { + t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: Actual: <%v>", err) + } err = asw.MarkVolumeAsAttached(emptyVolumeName, volumeSpec, "" /* nodeName */, devicePath) if err != nil { @@ -580,3 +708,18 @@ func verifyVolumeDoesntExistWithSpecNameInVolumeAsw( podExistsInVolume) } } + +func verifyVolumeSpecNameInVolumeAsw( + t *testing.T, + podToCheck volumetypes.UniquePodName, + volumeSpecs []*volume.Spec, + asw ActualStateOfWorld) { + mountedVolumes := + asw.GetMountedVolumesForPod(podToCheck) + + for i, volume := range mountedVolumes { + if volume.InnerVolumeSpecName != volumeSpecs[i].Name() { + t.Fatalf("Volume spec name does not match Expected: <%q> Actual: <%q>", volumeSpecs[i].Name(), volume.InnerVolumeSpecName) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/desired_state_of_world.go b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/desired_state_of_world.go index a61752d8c..fd52aaaa8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/desired_state_of_world.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/desired_state_of_world.go @@ -171,7 +171,7 @@ type podToMount struct { // generate the volume plugin object, and passed to plugin methods. // For non-PVC volumes this is the same as defined in the pod object. For // PVC volumes it is from the dereferenced PV object. - spec *volume.Spec + volumeSpec *volume.Spec // outerVolumeSpecName is the volume.Spec.Name() of the volume as referenced // directly in the pod. If the volume was referenced through a persistent @@ -220,16 +220,14 @@ func (dsw *desiredStateOfWorld) AddPodToVolume( volumeName = util.GetUniqueVolumeNameForNonAttachableVolume(podName, volumePlugin, volumeSpec) } - volumeObj, volumeExists := dsw.volumesToMount[volumeName] - if !volumeExists { - volumeObj = volumeToMount{ + if _, volumeExists := dsw.volumesToMount[volumeName]; !volumeExists { + dsw.volumesToMount[volumeName] = volumeToMount{ volumeName: volumeName, podsToMount: make(map[types.UniquePodName]podToMount), pluginIsAttachable: attachable, volumeGidValue: volumeGidValue, reportedInUse: false, } - dsw.volumesToMount[volumeName] = volumeObj } // Create new podToMount object. If it already exists, it is refreshed with @@ -238,7 +236,7 @@ func (dsw *desiredStateOfWorld) AddPodToVolume( dsw.volumesToMount[volumeName].podsToMount[podName] = podToMount{ podName: podName, pod: pod, - spec: volumeSpec, + volumeSpec: volumeSpec, outerVolumeSpecName: outerVolumeSpecName, } return volumeName, nil @@ -314,7 +312,7 @@ func (dsw *desiredStateOfWorld) VolumeExistsWithSpecName(podName types.UniquePod defer dsw.RUnlock() for _, volumeObj := range dsw.volumesToMount { for name, podObj := range volumeObj.podsToMount { - if podName == name && podObj.spec.Name() == volumeSpecName { + if podName == name && podObj.volumeSpec.Name() == volumeSpecName { return true } } @@ -351,7 +349,7 @@ func (dsw *desiredStateOfWorld) GetVolumesToMount() []VolumeToMount { VolumeName: volumeName, PodName: podName, Pod: podObj.pod, - VolumeSpec: podObj.spec, + VolumeSpec: podObj.volumeSpec, PluginIsAttachable: volumeObj.pluginIsAttachable, OuterVolumeSpecName: podObj.outerVolumeSpecName, VolumeGidValue: volumeObj.volumeGidValue, diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/BUILD index c44312cb7..fe4d2da5a 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/BUILD @@ -25,6 +25,7 @@ go_library( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_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", @@ -49,6 +50,7 @@ go_test( srcs = ["desired_state_of_world_populator_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/features:go_default_library", "//pkg/kubelet/configmap:go_default_library", "//pkg/kubelet/container/testing:go_default_library", "//pkg/kubelet/pod:go_default_library", @@ -61,6 +63,7 @@ go_test( "//pkg/volume/util:go_default_library", "//pkg/volume/util/types:go_default_library", "//vendor/k8s.io/api/core/v1: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/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go index cc642511a..e65fdc1b2 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go @@ -30,6 +30,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" @@ -182,12 +183,26 @@ func (dswp *desiredStateOfWorldPopulator) isPodTerminated(pod *v1.Pod) bool { // Iterate through all pods and add to desired state of world if they don't // exist but should func (dswp *desiredStateOfWorldPopulator) findAndAddNewPods() { + // Map unique pod name to outer volume name to MountedVolume. + mountedVolumesForPod := make(map[volumetypes.UniquePodName]map[string]cache.MountedVolume) + if utilfeature.DefaultFeatureGate.Enabled(features.ExpandInUsePersistentVolumes) { + for _, mountedVolume := range dswp.actualStateOfWorld.GetMountedVolumes() { + mountedVolumes, exist := mountedVolumesForPod[mountedVolume.PodName] + if !exist { + mountedVolumes = make(map[string]cache.MountedVolume) + mountedVolumesForPod[mountedVolume.PodName] = mountedVolumes + } + mountedVolumes[mountedVolume.OuterVolumeSpecName] = mountedVolume + } + } + + processedVolumesForFSResize := sets.NewString() for _, pod := range dswp.podManager.GetPods() { if dswp.isPodTerminated(pod) { // Do not (re)add volumes for terminated pods continue } - dswp.processPodVolumes(pod) + dswp.processPodVolumes(pod, mountedVolumesForPod, processedVolumesForFSResize) } } @@ -259,7 +274,10 @@ func (dswp *desiredStateOfWorldPopulator) findAndRemoveDeletedPods() { // processPodVolumes processes the volumes in the given pod and adds them to the // desired state of the world. -func (dswp *desiredStateOfWorldPopulator) processPodVolumes(pod *v1.Pod) { +func (dswp *desiredStateOfWorldPopulator) processPodVolumes( + pod *v1.Pod, + mountedVolumesForPod map[volumetypes.UniquePodName]map[string]cache.MountedVolume, + processedVolumesForFSResize sets.String) { if pod == nil { return } @@ -274,7 +292,7 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(pod *v1.Pod) { // Process volume spec for each volume defined in pod for _, podVolume := range pod.Spec.Volumes { - volumeSpec, volumeGidValue, err := + pvc, volumeSpec, volumeGidValue, err := dswp.createVolumeSpec(podVolume, pod.Name, pod.Namespace, mountsMap, devicesMap) if err != nil { glog.Errorf( @@ -304,6 +322,11 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(pod *v1.Pod) { podVolume.Name, volumeSpec.Name(), uniquePodName) + + if utilfeature.DefaultFeatureGate.Enabled(features.ExpandInUsePersistentVolumes) { + dswp.checkVolumeFSResize(pod, podVolume, pvc, volumeSpec, + uniquePodName, mountedVolumesForPod, processedVolumesForFSResize) + } } // some of the volume additions may have failed, should not mark this pod as fully processed @@ -316,6 +339,106 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(pod *v1.Pod) { } +// checkVolumeFSResize checks whether a PVC mounted by the pod requires file +// system resize or not. If so, marks this volume as fsResizeRequired in ASW. +// - mountedVolumesForPod stores all mounted volumes in ASW, because online +// volume resize only considers mounted volumes. +// - processedVolumesForFSResize stores all volumes we have checked in current loop, +// because file system resize operation is a global operation for volume, so +// we only need to check it once if more than one pod use it. +func (dswp *desiredStateOfWorldPopulator) checkVolumeFSResize( + pod *v1.Pod, + podVolume v1.Volume, + pvc *v1.PersistentVolumeClaim, + volumeSpec *volume.Spec, + uniquePodName volumetypes.UniquePodName, + mountedVolumesForPod map[volumetypes.UniquePodName]map[string]cache.MountedVolume, + processedVolumesForFSResize sets.String) { + if podVolume.PersistentVolumeClaim == nil { + // Only PVC supports resize operation. + return + } + uniqueVolumeName, exist := getUniqueVolumeName(uniquePodName, podVolume.Name, mountedVolumesForPod) + if !exist { + // Volume not exist in ASW, we assume it hasn't been mounted yet. If it needs resize, + // it will be handled as offline resize(if it indeed hasn't been mounted yet), + // or online resize in subsequent loop(after we confirm it has been mounted). + return + } + fsVolume, err := util.CheckVolumeModeFilesystem(volumeSpec) + if err != nil { + glog.Errorf("Check volume mode failed for volume %s(OuterVolumeSpecName %s): %v", + uniqueVolumeName, podVolume.Name, err) + return + } + if !fsVolume { + glog.V(5).Infof("Block mode volume needn't to check file system resize request") + return + } + if processedVolumesForFSResize.Has(string(uniqueVolumeName)) { + // File system resize operation is a global operation for volume, + // so we only need to check it once if more than one pod use it. + return + } + if mountedReadOnlyByPod(podVolume, pod) { + // This volume is used as read only by this pod, we don't perform resize for read only volumes. + glog.V(5).Infof("Skip file system resize check for volume %s in pod %s/%s "+ + "as the volume is mounted as readonly", podVolume.Name, pod.Namespace, pod.Name) + return + } + if volumeRequiresFSResize(pvc, volumeSpec.PersistentVolume) { + dswp.actualStateOfWorld.MarkFSResizeRequired(uniqueVolumeName, uniquePodName) + } + processedVolumesForFSResize.Insert(string(uniqueVolumeName)) +} + +func mountedReadOnlyByPod(podVolume v1.Volume, pod *v1.Pod) bool { + if podVolume.PersistentVolumeClaim.ReadOnly { + return true + } + for _, container := range pod.Spec.InitContainers { + if !mountedReadOnlyByContainer(podVolume.Name, &container) { + return false + } + } + for _, container := range pod.Spec.Containers { + if !mountedReadOnlyByContainer(podVolume.Name, &container) { + return false + } + } + return true +} + +func mountedReadOnlyByContainer(volumeName string, container *v1.Container) bool { + for _, volumeMount := range container.VolumeMounts { + if volumeMount.Name == volumeName && !volumeMount.ReadOnly { + return false + } + } + return true +} + +func getUniqueVolumeName( + podName volumetypes.UniquePodName, + outerVolumeSpecName string, + mountedVolumesForPod map[volumetypes.UniquePodName]map[string]cache.MountedVolume) (v1.UniqueVolumeName, bool) { + mountedVolumes, exist := mountedVolumesForPod[podName] + if !exist { + return "", false + } + mountedVolume, exist := mountedVolumes[outerVolumeSpecName] + if !exist { + return "", false + } + return mountedVolume.VolumeName, true +} + +func volumeRequiresFSResize(pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) bool { + capacity := pvc.Status.Capacity[v1.ResourceStorage] + requested := pv.Spec.Capacity[v1.ResourceStorage] + return requested.Cmp(capacity) > 0 +} + // podPreviouslyProcessed returns true if the volumes for this pod have already // been processed by the populator func (dswp *desiredStateOfWorldPopulator) podPreviouslyProcessed( @@ -350,7 +473,7 @@ func (dswp *desiredStateOfWorldPopulator) deleteProcessedPod( // specified volume. It dereference any PVC to get PV objects, if needed. // Returns an error if unable to obtain the volume at this time. func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( - podVolume v1.Volume, podName string, podNamespace string, mountsMap map[string]bool, devicesMap map[string]bool) (*volume.Spec, string, error) { + podVolume v1.Volume, podName string, podNamespace string, mountsMap map[string]bool, devicesMap map[string]bool) (*v1.PersistentVolumeClaim, *volume.Spec, string, error) { if pvcSource := podVolume.VolumeSource.PersistentVolumeClaim; pvcSource != nil { glog.V(5).Infof( @@ -359,15 +482,16 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( pvcSource.ClaimName) // If podVolume is a PVC, fetch the real PV behind the claim - pvName, pvcUID, err := dswp.getPVCExtractPV( + pvc, err := dswp.getPVCExtractPV( podNamespace, pvcSource.ClaimName) if err != nil { - return nil, "", fmt.Errorf( + return nil, nil, "", fmt.Errorf( "error processing PVC %q/%q: %v", podNamespace, pvcSource.ClaimName, err) } + pvName, pvcUID := pvc.Spec.VolumeName, pvc.UID glog.V(5).Infof( "Found bound PV for PVC (ClaimName %q/%q pvcUID %v): pvName=%q", @@ -380,7 +504,7 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( volumeSpec, volumeGidValue, err := dswp.getPVSpec(pvName, pvcSource.ReadOnly, pvcUID) if err != nil { - return nil, "", fmt.Errorf( + return nil, nil, "", fmt.Errorf( "error processing PVC %q/%q: %v", podNamespace, pvcSource.ClaimName, @@ -399,11 +523,11 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { volumeMode, err := util.GetVolumeMode(volumeSpec) if err != nil { - return nil, "", err + return nil, nil, "", err } // Error if a container has volumeMounts but the volumeMode of PVC isn't Filesystem if mountsMap[podVolume.Name] && volumeMode != v1.PersistentVolumeFilesystem { - return nil, "", fmt.Errorf( + return nil, nil, "", fmt.Errorf( "Volume %q has volumeMode %q, but is specified in volumeMounts for pod %q/%q", podVolume.Name, volumeMode, @@ -412,7 +536,7 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( } // Error if a container has volumeDevices but the volumeMode of PVC isn't Block if devicesMap[podVolume.Name] && volumeMode != v1.PersistentVolumeBlock { - return nil, "", fmt.Errorf( + return nil, nil, "", fmt.Errorf( "Volume %q has volumeMode %q, but is specified in volumeDevices for pod %q/%q", podVolume.Name, volumeMode, @@ -420,13 +544,13 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( podName) } } - return volumeSpec, volumeGidValue, nil + return pvc, volumeSpec, volumeGidValue, nil } // Do not return the original volume object, since the source could mutate it clonedPodVolume := podVolume.DeepCopy() - return volume.NewSpecFromVolume(clonedPodVolume), "", nil + return nil, volume.NewSpecFromVolume(clonedPodVolume), "", nil } // getPVCExtractPV fetches the PVC object with the given namespace and name from @@ -434,11 +558,11 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec( // it is pointing to and returns it. // An error is returned if the PVC object's phase is not "Bound". func (dswp *desiredStateOfWorldPopulator) getPVCExtractPV( - namespace string, claimName string) (string, types.UID, error) { + namespace string, claimName string) (*v1.PersistentVolumeClaim, error) { pvc, err := dswp.kubeClient.CoreV1().PersistentVolumeClaims(namespace).Get(claimName, metav1.GetOptions{}) if err != nil || pvc == nil { - return "", "", fmt.Errorf( + return nil, fmt.Errorf( "failed to fetch PVC %s/%s from API server. err=%v", namespace, claimName, @@ -455,7 +579,7 @@ func (dswp *desiredStateOfWorldPopulator) getPVCExtractPV( // It should happen only in very rare case when scheduler schedules // a pod and user deletes a PVC that's used by it at the same time. if pvc.ObjectMeta.DeletionTimestamp != nil { - return "", "", fmt.Errorf( + return nil, fmt.Errorf( "can't start pod because PVC %s/%s is being deleted", namespace, claimName) @@ -464,7 +588,7 @@ func (dswp *desiredStateOfWorldPopulator) getPVCExtractPV( if pvc.Status.Phase != v1.ClaimBound || pvc.Spec.VolumeName == "" { - return "", "", fmt.Errorf( + return nil, fmt.Errorf( "PVC %s/%s has non-bound phase (%q) or empty pvc.Spec.VolumeName (%q)", namespace, claimName, @@ -472,7 +596,7 @@ func (dswp *desiredStateOfWorldPopulator) getPVCExtractPV( pvc.Spec.VolumeName) } - return pvc.Spec.VolumeName, pvc.UID, nil + return pvc, nil } // getPVSpec fetches the PV object with the given name from the API server diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go index 90c6bf182..969ac6691 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go @@ -20,12 +20,16 @@ import ( "testing" "time" + "fmt" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/configmap" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" kubepod "k8s.io/kubernetes/pkg/kubelet/pod" @@ -294,7 +298,7 @@ func TestCreateVolumeSpec_Valid_File_VolumeMounts(t *testing.T) { fakePodManager.AddPod(pod) mountsMap, devicesMap := dswp.makeVolumeMap(pod.Spec.Containers) - volumeSpec, _, err := + _, volumeSpec, _, err := dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap) // Assert @@ -343,7 +347,7 @@ func TestCreateVolumeSpec_Valid_Block_VolumeDevices(t *testing.T) { fakePodManager.AddPod(pod) mountsMap, devicesMap := dswp.makeVolumeMap(pod.Spec.Containers) - volumeSpec, _, err := + _, volumeSpec, _, err := dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap) // Assert @@ -395,7 +399,7 @@ func TestCreateVolumeSpec_Invalid_File_VolumeDevices(t *testing.T) { fakePodManager.AddPod(pod) mountsMap, devicesMap := dswp.makeVolumeMap(pod.Spec.Containers) - volumeSpec, _, err := + _, volumeSpec, _, err := dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap) // Assert @@ -447,7 +451,7 @@ func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) { fakePodManager.AddPod(pod) mountsMap, devicesMap := dswp.makeVolumeMap(pod.Spec.Containers) - volumeSpec, _, err := + _, volumeSpec, _, err := dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap) // Assert @@ -459,6 +463,155 @@ func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) { utilfeature.DefaultFeatureGate.Set("BlockVolume=false") } +func TestCheckVolumeFSResize(t *testing.T) { + pv := &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dswp-test-volume-name", + }, + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{RBD: &v1.RBDPersistentVolumeSource{}}, + Capacity: volumeCapacity(1), + ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"}, + }, + } + pvc := &v1.PersistentVolumeClaim{ + Spec: v1.PersistentVolumeClaimSpec{ + VolumeName: "dswp-test-volume-name", + Resources: v1.ResourceRequirements{ + Requests: volumeCapacity(1), + }, + }, + Status: v1.PersistentVolumeClaimStatus{ + Phase: v1.ClaimBound, + Capacity: volumeCapacity(1), + }, + } + dswp, fakePodManager, fakeDSW := createDswpWithVolume(t, pv, pvc) + fakeASW := dswp.actualStateOfWorld + + // create pod + containers := []v1.Container{ + { + VolumeMounts: []v1.VolumeMount{ + { + Name: "dswp-test-volume-name", + MountPath: "/mnt", + }, + }, + }, + } + pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "file-bound", containers) + uniquePodName := types.UniquePodName(pod.UID) + uniqueVolumeName := v1.UniqueVolumeName("fake-plugin/" + pod.Spec.Volumes[0].Name) + + fakePodManager.AddPod(pod) + // Fill the dsw to contains volumes and pods. + dswp.findAndAddNewPods() + reconcileASW(fakeASW, fakeDSW, t) + + // No resize request for volume, volumes in ASW shouldn't be marked as fsResizeRequired. + setExpandOnlinePersistentVolumesFeatureGate("true", t) + resizeRequiredVolumes := reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) > 0 { + t.Fatalf("No resize request for any volumes, but found resize required volumes in ASW: %v", resizeRequiredVolumes) + } + + // Add a resize request to volume. + pv.Spec.Capacity = volumeCapacity(2) + pvc.Spec.Resources.Requests = volumeCapacity(2) + + // Disable the feature gate, so volume shouldn't be marked as fsResizeRequired. + setExpandOnlinePersistentVolumesFeatureGate("false", t) + resizeRequiredVolumes = reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) > 0 { + t.Fatalf("Feature gate disabled, but found resize required volumes in ASW: %v", resizeRequiredVolumes) + } + + // Make volume used as ReadOnly, so volume shouldn't be marked as fsResizeRequired. + setExpandOnlinePersistentVolumesFeatureGate("true", t) + pod.Spec.Containers[0].VolumeMounts[0].ReadOnly = true + resizeRequiredVolumes = reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) > 0 { + t.Fatalf("volume mounted as ReadOnly, but found resize required volumes in ASW: %v", resizeRequiredVolumes) + } + + // Clear ASW, so volume shouldn't be marked as fsResizeRequired because they are not mounted. + pod.Spec.Containers[0].VolumeMounts[0].ReadOnly = false + clearASW(fakeASW, fakeDSW, t) + resizeRequiredVolumes = reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) > 0 { + t.Fatalf("volume hasn't been mounted, but found resize required volumes in ASW: %v", resizeRequiredVolumes) + } + + // volume in ASW should be marked as fsResizeRequired. + reconcileASW(fakeASW, fakeDSW, t) + resizeRequiredVolumes = reprocess(dswp, uniquePodName, fakeDSW, fakeASW) + if len(resizeRequiredVolumes) == 0 { + t.Fatalf("Request resize for volume, but volume in ASW hasn't been marked as fsResizeRequired") + } + if len(resizeRequiredVolumes) != 1 { + t.Fatalf("Some unexpected volumes are marked as fsResizeRequired: %v", resizeRequiredVolumes) + } + if resizeRequiredVolumes[0] != uniqueVolumeName { + t.Fatalf("Mark wrong volume as fsResizeRequired: %s", resizeRequiredVolumes[0]) + } +} + +func volumeCapacity(size int) v1.ResourceList { + return v1.ResourceList{v1.ResourceStorage: resource.MustParse(fmt.Sprintf("%dGi", size))} +} + +func setExpandOnlinePersistentVolumesFeatureGate(value string, t *testing.T) { + err := utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=%s", features.ExpandInUsePersistentVolumes, value)) + if err != nil { + t.Fatalf("Set ExpandInUsePersistentVolumes feature gate to %s failed: %v", value, err) + } +} + +func reconcileASW(asw cache.ActualStateOfWorld, dsw cache.DesiredStateOfWorld, t *testing.T) { + for _, volumeToMount := range dsw.GetVolumesToMount() { + err := asw.MarkVolumeAsAttached(volumeToMount.VolumeName, volumeToMount.VolumeSpec, "", "") + if err != nil { + t.Fatalf("Unexpected error when MarkVolumeAsAttached: %v", err) + } + err = asw.MarkVolumeAsMounted(volumeToMount.PodName, volumeToMount.Pod.UID, + volumeToMount.VolumeName, nil, nil, volumeToMount.OuterVolumeSpecName, volumeToMount.VolumeGidValue, volumeToMount.VolumeSpec) + if err != nil { + t.Fatalf("Unexpected error when MarkVolumeAsMounted: %v", err) + } + } +} + +func clearASW(asw cache.ActualStateOfWorld, dsw cache.DesiredStateOfWorld, t *testing.T) { + for _, volumeToMount := range dsw.GetVolumesToMount() { + err := asw.MarkVolumeAsUnmounted(volumeToMount.PodName, volumeToMount.VolumeName) + if err != nil { + t.Fatalf("Unexpected error when MarkVolumeAsUnmounted: %v", err) + } + } + for _, volumeToMount := range dsw.GetVolumesToMount() { + asw.MarkVolumeAsDetached(volumeToMount.VolumeName, "") + } +} + +func reprocess(dswp *desiredStateOfWorldPopulator, uniquePodName types.UniquePodName, + dsw cache.DesiredStateOfWorld, asw cache.ActualStateOfWorld) []v1.UniqueVolumeName { + dswp.ReprocessPod(uniquePodName) + dswp.findAndAddNewPods() + return getResizeRequiredVolumes(dsw, asw) +} + +func getResizeRequiredVolumes(dsw cache.DesiredStateOfWorld, asw cache.ActualStateOfWorld) []v1.UniqueVolumeName { + resizeRequiredVolumes := []v1.UniqueVolumeName{} + for _, volumeToMount := range dsw.GetVolumesToMount() { + _, _, err := asw.PodExistsInVolume(volumeToMount.PodName, volumeToMount.VolumeName) + if cache.IsFSResizeRequiredError(err) { + resizeRequiredVolumes = append(resizeRequiredVolumes, volumeToMount.VolumeName) + } + } + return resizeRequiredVolumes +} + func verifyVolumeExistsInVolumesToMount(t *testing.T, expectedVolumeName v1.UniqueVolumeName, expectReportedInUse bool, dsw cache.DesiredStateOfWorld) { volumesToMount := dsw.GetVolumesToMount() for _, volume := range volumesToMount { @@ -523,7 +676,7 @@ func createDswpWithVolume(t *testing.T, pv *v1.PersistentVolume, pvc *v1.Persist fakeSecretManager := secret.NewFakeManager() fakeConfigMapManager := configmap.NewFakeManager() fakePodManager := kubepod.NewBasicPodManager( - podtest.NewFakeMirrorClient(), fakeSecretManager, fakeConfigMapManager) + podtest.NewFakeMirrorClient(), fakeSecretManager, fakeConfigMapManager, podtest.NewMockCheckpointManager()) fakesDSW := cache.NewDesiredStateOfWorld(fakeVolumePluginMgr) fakeASW := cache.NewActualStateOfWorld("fake", fakeVolumePluginMgr) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/BUILD b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/BUILD index b2a41d000..5877ceced 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/BUILD @@ -38,6 +38,7 @@ go_test( srcs = ["reconciler_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/features:go_default_library", "//pkg/kubelet/volumemanager/cache:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/volume:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/reconciler.go b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/reconciler.go index 6fb3b63ab..2ffb5c99f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/reconciler.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/reconciler.go @@ -254,6 +254,22 @@ func (rc *reconciler) reconcile() { glog.V(5).Infof(volumeToMount.GenerateMsgDetailed("operationExecutor.MountVolume started", remountingLogStr)) } } + } else if cache.IsFSResizeRequiredError(err) && + utilfeature.DefaultFeatureGate.Enabled(features.ExpandInUsePersistentVolumes) { + glog.V(4).Infof(volumeToMount.GenerateMsgDetailed("Starting operationExecutor.ExpandVolumeFSWithoutUnmounting", "")) + err := rc.operationExecutor.ExpandVolumeFSWithoutUnmounting( + volumeToMount.VolumeToMount, + rc.actualStateOfWorld) + if err != nil && + !nestedpendingoperations.IsAlreadyExists(err) && + !exponentialbackoff.IsExponentialBackoff(err) { + // Ignore nestedpendingoperations.IsAlreadyExists and exponentialbackoff.IsExponentialBackoff errors, they are expected. + // Log all other errors. + glog.Errorf(volumeToMount.GenerateErrorDetailed("operationExecutor.ExpandVolumeFSWithoutUnmounting failed", err).Error()) + } + if err == nil { + glog.V(4).Infof(volumeToMount.GenerateMsgDetailed("operationExecutor.ExpandVolumeFSWithoutUnmounting started", "")) + } } } @@ -593,7 +609,8 @@ func (rc *reconciler) updateStates(volumesNeedUpdate map[v1.UniqueVolumeName]*re volume.mounter, volume.blockVolumeMapper, volume.outerVolumeSpecName, - volume.volumeGidValue) + volume.volumeGidValue, + volume.volumeSpec) if err != nil { glog.Errorf("Could not add pod to volume information to actual state of world: %v", err) continue diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/reconciler_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/reconciler_test.go index 4e49d2ba7..38eaba2f0 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/reconciler_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/reconciler/reconciler_test.go @@ -32,6 +32,7 @@ import ( "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" "k8s.io/client-go/tools/record" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/volumemanager/cache" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" @@ -479,7 +480,7 @@ func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) { ObjectMeta: metav1.ObjectMeta{UID: "001", Name: "volume-name"}, Spec: v1.PersistentVolumeSpec{ Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("10G")}, - PersistentVolumeSource: v1.PersistentVolumeSource{GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{}}, + PersistentVolumeSource: v1.PersistentVolumeSource{GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{PDName: "fake-device1"}}, AccessModes: []v1.PersistentVolumeAccessMode{ v1.ReadWriteOnce, v1.ReadOnlyMany, @@ -508,12 +509,8 @@ func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) { 1 /* expectedAttachCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyWaitForAttachCallCount( 1 /* expectedWaitForAttachCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetGlobalMapPathCallCount( - 1 /* expectedGetGlobalMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetPodDeviceMapPathCallCount( - 1 /* expectedPodDeviceMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifySetUpDeviceCallCount( - 1 /* expectedSetUpDeviceCallCount */, fakePlugin)) + assert.NoError(t, volumetesting.VerifyGetMapDeviceCallCount( + 1 /* expectedGetMapDeviceCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroTearDownDeviceCallCount(fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroDetachCallCount(fakePlugin)) @@ -570,7 +567,7 @@ func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) { ObjectMeta: metav1.ObjectMeta{UID: "001", Name: "volume-name"}, Spec: v1.PersistentVolumeSpec{ Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("10G")}, - PersistentVolumeSource: v1.PersistentVolumeSource{GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{}}, + PersistentVolumeSource: v1.PersistentVolumeSource{GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{PDName: "fake-device1"}}, AccessModes: []v1.PersistentVolumeAccessMode{ v1.ReadWriteOnce, v1.ReadOnlyMany, @@ -600,12 +597,8 @@ func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) { assert.NoError(t, volumetesting.VerifyZeroAttachCalls(fakePlugin)) assert.NoError(t, volumetesting.VerifyWaitForAttachCallCount( 1 /* expectedWaitForAttachCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetGlobalMapPathCallCount( - 1 /* expectedGetGlobalMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetPodDeviceMapPathCallCount( - 1 /* expectedPodDeviceMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifySetUpDeviceCallCount( - 1 /* expectedSetUpCallCount */, fakePlugin)) + assert.NoError(t, volumetesting.VerifyGetMapDeviceCallCount( + 1 /* expectedGetMapDeviceCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroTearDownDeviceCallCount(fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroDetachCallCount(fakePlugin)) @@ -662,7 +655,7 @@ func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) { ObjectMeta: metav1.ObjectMeta{UID: "001", Name: "volume-name"}, Spec: v1.PersistentVolumeSpec{ Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("10G")}, - PersistentVolumeSource: v1.PersistentVolumeSource{GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{}}, + PersistentVolumeSource: v1.PersistentVolumeSource{GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{PDName: "fake-device1"}}, AccessModes: []v1.PersistentVolumeAccessMode{ v1.ReadWriteOnce, v1.ReadOnlyMany, @@ -691,12 +684,8 @@ func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) { 1 /* expectedAttachCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyWaitForAttachCallCount( 1 /* expectedWaitForAttachCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetGlobalMapPathCallCount( - 1 /* expectedGetGlobalMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetPodDeviceMapPathCallCount( - 1 /* expectedPodDeviceMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifySetUpDeviceCallCount( - 1 /* expectedSetUpCallCount */, fakePlugin)) + assert.NoError(t, volumetesting.VerifyGetMapDeviceCallCount( + 1 /* expectedGetMapDeviceCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroTearDownDeviceCallCount(fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroDetachCallCount(fakePlugin)) @@ -764,7 +753,7 @@ func Test_Run_Positive_VolumeUnmapControllerAttachEnabled(t *testing.T) { ObjectMeta: metav1.ObjectMeta{UID: "001", Name: "volume-name"}, Spec: v1.PersistentVolumeSpec{ Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("10G")}, - PersistentVolumeSource: v1.PersistentVolumeSource{GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{}}, + PersistentVolumeSource: v1.PersistentVolumeSource{GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{PDName: "fake-device1"}}, AccessModes: []v1.PersistentVolumeAccessMode{ v1.ReadWriteOnce, v1.ReadOnlyMany, @@ -795,12 +784,8 @@ func Test_Run_Positive_VolumeUnmapControllerAttachEnabled(t *testing.T) { assert.NoError(t, volumetesting.VerifyZeroAttachCalls(fakePlugin)) assert.NoError(t, volumetesting.VerifyWaitForAttachCallCount( 1 /* expectedWaitForAttachCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetGlobalMapPathCallCount( - 1 /* expectedGetGlobalMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifyGetPodDeviceMapPathCallCount( - 1 /* expectedPodDeviceMapPathCallCount */, fakePlugin)) - assert.NoError(t, volumetesting.VerifySetUpDeviceCallCount( - 1 /* expectedSetUpCallCount */, fakePlugin)) + assert.NoError(t, volumetesting.VerifyGetMapDeviceCallCount( + 1 /* expectedGetMapDeviceCallCount */, fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroTearDownDeviceCallCount(fakePlugin)) assert.NoError(t, volumetesting.VerifyZeroDetachCallCount(fakePlugin)) @@ -965,6 +950,120 @@ func Test_GenerateUnmapDeviceFunc_Plugin_Not_Found(t *testing.T) { utilfeature.DefaultFeatureGate.Set("BlockVolume=false") } +// Populates desiredStateOfWorld cache with one volume/pod. +// Enables controllerAttachDetachEnabled. +// Calls Run() +// Wait for volume mounted. +// Mark volume as fsResizeRequired in ASW. +// Verifies volume's fsResizeRequired flag is cleared later. +func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.ExpandInUsePersistentVolumes)) + pv := &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pv", + UID: "pvuid", + }, + Spec: v1.PersistentVolumeSpec{ + ClaimRef: &v1.ObjectReference{Name: "pvc"}, + }, + } + pvc := &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pvc", + UID: "pvcuid", + }, + Spec: v1.PersistentVolumeClaimSpec{ + VolumeName: "pv", + }, + } + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + UID: "pod1uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "volume-name", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc.Name, + }, + }, + }, + }, + }, + } + + volumePluginMgr, fakePlugin := volumetesting.GetTestVolumePluginMgr(t) + dsw := cache.NewDesiredStateOfWorld(volumePluginMgr) + asw := cache.NewActualStateOfWorld(nodeName, volumePluginMgr) + kubeClient := createtestClientWithPVPVC(pv, pvc) + fakeRecorder := &record.FakeRecorder{} + fakeHandler := volumetesting.NewBlockVolumePathHandler() + oex := operationexecutor.NewOperationExecutor(operationexecutor.NewOperationGenerator( + kubeClient, + volumePluginMgr, + fakeRecorder, + false, /* checkNodeCapabilitiesBeforeMount */ + fakeHandler)) + + reconciler := NewReconciler( + kubeClient, + true, /* controllerAttachDetachEnabled */ + reconcilerLoopSleepDuration, + reconcilerSyncStatesSleepPeriod, + waitForAttachTimeout, + nodeName, + dsw, + asw, + hasAddedPods, + oex, + &mount.FakeMounter{}, + volumePluginMgr, + kubeletPodsDir) + + volumeSpec := &volume.Spec{PersistentVolume: pv} + podName := util.GetUniquePodName(pod) + volumeName, err := dsw.AddPodToVolume( + podName, pod, volumeSpec, volumeSpec.Name(), "" /* volumeGidValue */) + // Assert + if err != nil { + t.Fatalf("AddPodToVolume failed. Expected: Actual: <%v>", err) + } + dsw.MarkVolumesReportedInUse([]v1.UniqueVolumeName{volumeName}) + + // Start the reconciler to fill ASW. + stopChan, stoppedChan := make(chan struct{}), make(chan struct{}) + go func() { + reconciler.Run(stopChan) + close(stoppedChan) + }() + waitForMount(t, fakePlugin, volumeName, asw) + // Stop the reconciler. + close(stopChan) + <-stoppedChan + + // Mark volume as fsResizeRequired. + asw.MarkFSResizeRequired(volumeName, podName) + _, _, podExistErr := asw.PodExistsInVolume(podName, volumeName) + if !cache.IsFSResizeRequiredError(podExistErr) { + t.Fatalf("Volume should be marked as fsResizeRequired, but receive unexpected error: %v", podExistErr) + } + + // Start the reconciler again, we hope reconciler will perform the + // resize operation and clear the fsResizeRequired flag for volume. + go reconciler.Run(wait.NeverStop) + + waitErr := retryWithExponentialBackOff(500*time.Millisecond, func() (done bool, err error) { + mounted, _, err := asw.PodExistsInVolume(podName, volumeName) + return mounted && err == nil, nil + }) + if waitErr != nil { + t.Fatal("Volume resize should succeeded") + } +} + func waitForMount( t *testing.T, fakePlugin *volumetesting.FakeVolumePlugin, @@ -1029,11 +1128,10 @@ func createTestClient() *fake.Clientset { Status: v1.NodeStatus{ VolumesAttached: []v1.AttachedVolume{ { - Name: "fake-plugin/volume-name", + Name: "fake-plugin/fake-device1", DevicePath: "fake/path", }, }}, - Spec: v1.NodeSpec{ExternalID: string(nodeName)}, }, nil }) fakeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { @@ -1045,3 +1143,30 @@ func createTestClient() *fake.Clientset { func runReconciler(reconciler Reconciler) { go reconciler.Run(wait.NeverStop) } + +func createtestClientWithPVPVC(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) *fake.Clientset { + fakeClient := &fake.Clientset{} + fakeClient.AddReactor("get", "nodes", + func(action core.Action) (bool, runtime.Object, error) { + return true, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: string(nodeName)}, + Status: v1.NodeStatus{ + VolumesAttached: []v1.AttachedVolume{ + { + Name: "fake-plugin/pv", + DevicePath: "fake/path", + }, + }}, + }, nil + }) + fakeClient.AddReactor("get", "persistentvolumeclaims", func(action core.Action) (bool, runtime.Object, error) { + return true, pvc, nil + }) + fakeClient.AddReactor("get", "persistentvolumes", func(action core.Action) (bool, runtime.Object, error) { + return true, pv, nil + }) + fakeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { + return true, nil, fmt.Errorf("no reaction implemented for %s", action) + }) + return fakeClient +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/volume_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/volume_manager_test.go index bb9b156b5..74656d805 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/volume_manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/volumemanager/volume_manager_test.go @@ -55,7 +55,8 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) { t.Fatalf("can't make a temp dir: %v", err) } defer os.RemoveAll(tmpDir) - podManager := kubepod.NewBasicPodManager(podtest.NewFakeMirrorClient(), secret.NewFakeManager(), configmap.NewFakeManager()) + cpm := podtest.NewMockCheckpointManager() + podManager := kubepod.NewBasicPodManager(podtest.NewFakeMirrorClient(), secret.NewFakeManager(), configmap.NewFakeManager(), cpm) node, pod, pv, claim := createObjects() kubeClient := fake.NewSimpleClientset(node, pod, pv, claim) @@ -97,7 +98,8 @@ func TestInitialPendingVolumesForPodAndGetVolumesInUse(t *testing.T) { t.Fatalf("can't make a temp dir: %v", err) } defer os.RemoveAll(tmpDir) - podManager := kubepod.NewBasicPodManager(podtest.NewFakeMirrorClient(), secret.NewFakeManager(), configmap.NewFakeManager()) + cpm := podtest.NewMockCheckpointManager() + podManager := kubepod.NewBasicPodManager(podtest.NewFakeMirrorClient(), secret.NewFakeManager(), configmap.NewFakeManager(), cpm) node, pod, pv, claim := createObjects() claim.Status = v1.PersistentVolumeClaimStatus{ @@ -135,7 +137,8 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) { t.Fatalf("can't make a temp dir: %v", err) } defer os.RemoveAll(tmpDir) - podManager := kubepod.NewBasicPodManager(podtest.NewFakeMirrorClient(), secret.NewFakeManager(), configmap.NewFakeManager()) + cpm := podtest.NewMockCheckpointManager() + podManager := kubepod.NewBasicPodManager(podtest.NewFakeMirrorClient(), secret.NewFakeManager(), configmap.NewFakeManager(), cpm) node, pod, _, claim := createObjects() @@ -243,11 +246,10 @@ func createObjects() (*v1.Node, *v1.Pod, *v1.PersistentVolume, *v1.PersistentVol Status: v1.NodeStatus{ VolumesAttached: []v1.AttachedVolume{ { - Name: "fake/pvA", + Name: "fake/fake-device", DevicePath: "fake/path", }, }}, - Spec: v1.NodeSpec{ExternalID: testHostname}, } pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/vendor/k8s.io/kubernetes/pkg/master/BUILD b/vendor/k8s.io/kubernetes/pkg/master/BUILD index e8ac47c70..8a4fb9042 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/master/BUILD @@ -19,7 +19,6 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/master", deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/admission/install:go_default_library", "//pkg/apis/admissionregistration/install:go_default_library", "//pkg/apis/apps/install:go_default_library", @@ -73,6 +72,7 @@ go_library( "//pkg/util/node:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", + "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", @@ -85,6 +85,7 @@ go_library( "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/api/batch/v1beta1:go_default_library", + "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/events/v1beta1:go_default_library", @@ -92,8 +93,13 @@ go_library( "//vendor/k8s.io/api/networking/v1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", "//vendor/k8s.io/api/rbac/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", + "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", "//vendor/k8s.io/api/storage/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -159,7 +165,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/master/client_ca_hook_test.go b/vendor/k8s.io/kubernetes/pkg/master/client_ca_hook_test.go index 64aa61712..011078bdd 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/client_ca_hook_test.go +++ b/vendor/k8s.io/kubernetes/pkg/master/client_ca_hook_test.go @@ -189,18 +189,18 @@ func TestWriteClientCAs(t *testing.T) { } for _, test := range tests { - client := fake.NewSimpleClientset(test.preexistingObjs...) - test.hook.tryToWriteClientCAs(client.Core()) + t.Run(test.name, func(t *testing.T) { + client := fake.NewSimpleClientset(test.preexistingObjs...) + test.hook.tryToWriteClientCAs(client.Core()) - actualConfigMaps, updated := getFinalConfiMaps(client) - if !reflect.DeepEqual(test.expectedConfigMaps, actualConfigMaps) { - t.Errorf("%s: %v", test.name, diff.ObjectReflectDiff(test.expectedConfigMaps, actualConfigMaps)) - continue - } - if test.expectUpdate != updated { - t.Errorf("%s: expected %v, got %v", test.name, test.expectUpdate, updated) - continue - } + actualConfigMaps, updated := getFinalConfiMaps(client) + if !reflect.DeepEqual(test.expectedConfigMaps, actualConfigMaps) { + t.Fatalf("%s: %v", test.name, diff.ObjectReflectDiff(test.expectedConfigMaps, actualConfigMaps)) + } + if test.expectUpdate != updated { + t.Fatalf("%s: expected %v, got %v", test.name, test.expectUpdate, updated) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/master/controller.go b/vendor/k8s.io/kubernetes/pkg/master/controller.go index 78154d176..ac5a86db1 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/controller.go +++ b/vendor/k8s.io/kubernetes/pkg/master/controller.go @@ -152,7 +152,22 @@ func (c *Controller) Stop() { c.runner.Stop() } endpointPorts := createEndpointPortSpec(c.PublicServicePort, "https", c.ExtraEndpointPorts) - c.EndpointReconciler.StopReconciling("kubernetes", c.PublicIP, endpointPorts) + finishedReconciling := make(chan struct{}) + go func() { + defer close(finishedReconciling) + glog.Infof("Shutting down kubernetes service endpoint reconciler") + if err := c.EndpointReconciler.StopReconciling("kubernetes", c.PublicIP, endpointPorts); err != nil { + glog.Error(err) + } + }() + + select { + case <-finishedReconciling: + // done + case <-time.After(2 * c.EndpointInterval): + // don't block server shutdown forever if we can't reach etcd to remove ourselves + glog.Warning("StopReconciling() timed out") + } } // RunKubernetesNamespaces periodically makes sure that all internal namespaces exist @@ -257,7 +272,7 @@ func (c *Controller) CreateOrUpdateMasterServiceIfNeeded(serviceName string, ser // maintained by this code, not by the pod selector Selector: nil, ClusterIP: serviceIP.String(), - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: serviceType, }, } diff --git a/vendor/k8s.io/kubernetes/pkg/master/controller/crdregistration/crdregistration_controller.go b/vendor/k8s.io/kubernetes/pkg/master/controller/crdregistration/crdregistration_controller.go index c3a87b418..49e3b1edc 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/controller/crdregistration/crdregistration_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/master/controller/crdregistration/crdregistration_controller.go @@ -77,9 +77,11 @@ func NewAutoRegistrationController(crdinformer crdinformers.CustomResourceDefini cast := obj.(*apiextensions.CustomResourceDefinition) c.enqueueCRD(cast) }, - UpdateFunc: func(_, obj interface{}) { - cast := obj.(*apiextensions.CustomResourceDefinition) - c.enqueueCRD(cast) + UpdateFunc: func(oldObj, newObj interface{}) { + // Enqueue both old and new object to make sure we remove and add appropriate API services. + // The working queue will resolve any duplicates and only changes will stay in the queue. + c.enqueueCRD(oldObj.(*apiextensions.CustomResourceDefinition)) + c.enqueueCRD(newObj.(*apiextensions.CustomResourceDefinition)) }, DeleteFunc: func(obj interface{}) { cast, ok := obj.(*apiextensions.CustomResourceDefinition) @@ -120,8 +122,10 @@ func (c *crdRegistrationController) Run(threadiness int, stopCh <-chan struct{}) utilruntime.HandleError(err) } else { for _, crd := range crds { - if err := c.syncHandler(schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version}); err != nil { - utilruntime.HandleError(err) + for _, version := range crd.Spec.Versions { + if err := c.syncHandler(schema.GroupVersion{Group: crd.Spec.Group, Version: version.Name}); err != nil { + utilruntime.HandleError(err) + } } } } @@ -182,11 +186,12 @@ func (c *crdRegistrationController) processNextWorkItem() bool { } func (c *crdRegistrationController) enqueueCRD(crd *apiextensions.CustomResourceDefinition) { - c.queue.Add(schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version}) + for _, version := range crd.Spec.Versions { + c.queue.Add(schema.GroupVersion{Group: crd.Spec.Group, Version: version.Name}) + } } func (c *crdRegistrationController) handleVersionUpdate(groupVersion schema.GroupVersion) error { - found := false apiServiceName := groupVersion.Version + "." + groupVersion.Group // check all CRDs. There shouldn't that many, but if we have problems later we can index them @@ -195,26 +200,27 @@ func (c *crdRegistrationController) handleVersionUpdate(groupVersion schema.Grou return err } for _, crd := range crds { - if crd.Spec.Version == groupVersion.Version && crd.Spec.Group == groupVersion.Group { - found = true - break + if crd.Spec.Group != groupVersion.Group { + continue } - } + for _, version := range crd.Spec.Versions { + if version.Name != groupVersion.Version || !version.Served { + continue + } - if !found { - c.apiServiceRegistration.RemoveAPIServiceToSync(apiServiceName) - return nil + c.apiServiceRegistration.AddAPIServiceToSync(&apiregistration.APIService{ + ObjectMeta: metav1.ObjectMeta{Name: apiServiceName}, + Spec: apiregistration.APIServiceSpec{ + Group: groupVersion.Group, + Version: groupVersion.Version, + GroupPriorityMinimum: 1000, // CRDs should have relatively low priority + VersionPriority: 100, // CRDs will be sorted by kube-like versions like any other APIService with the same VersionPriority + }, + }) + return nil + } } - c.apiServiceRegistration.AddAPIServiceToSync(&apiregistration.APIService{ - ObjectMeta: metav1.ObjectMeta{Name: apiServiceName}, - Spec: apiregistration.APIServiceSpec{ - Group: groupVersion.Group, - Version: groupVersion.Version, - GroupPriorityMinimum: 1000, // CRDs should have relatively low priority - VersionPriority: 100, // CRDs should have relatively low priority - }, - }) - + c.apiServiceRegistration.RemoveAPIServiceToSync(apiServiceName) return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/master/controller/crdregistration/crdregistration_controller_test.go b/vendor/k8s.io/kubernetes/pkg/master/controller/crdregistration/crdregistration_controller_test.go index 1e2d8df58..ec553dec4 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/controller/crdregistration/crdregistration_controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/master/controller/crdregistration/crdregistration_controller_test.go @@ -42,8 +42,16 @@ func TestHandleVersionUpdate(t *testing.T) { startingCRDs: []*apiextensions.CustomResourceDefinition{ { Spec: apiextensions.CustomResourceDefinitionSpec{ - Group: "group.com", - Version: "v1", + Group: "group.com", + // Version field is deprecated and crd registration won't rely on it at all. + // defaulting route will fill up Versions field if user only provided version field. + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + }, + }, }, }, }, @@ -66,8 +74,14 @@ func TestHandleVersionUpdate(t *testing.T) { startingCRDs: []*apiextensions.CustomResourceDefinition{ { Spec: apiextensions.CustomResourceDefinitionSpec{ - Group: "group.com", - Version: "v1", + Group: "group.com", + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + }, + }, }, }, }, @@ -78,27 +92,28 @@ func TestHandleVersionUpdate(t *testing.T) { } for _, test := range tests { - registration := &fakeAPIServiceRegistration{} - crdCache := cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) - crdLister := crdlisters.NewCustomResourceDefinitionLister(crdCache) - c := crdRegistrationController{ - crdLister: crdLister, - apiServiceRegistration: registration, - } - for i := range test.startingCRDs { - crdCache.Add(test.startingCRDs[i]) - } - - c.handleVersionUpdate(test.version) - - if !reflect.DeepEqual(test.expectedAdded, registration.added) { - t.Errorf("%s expected %v, got %v", test.name, test.expectedAdded, registration.added) - } - if !reflect.DeepEqual(test.expectedRemoved, registration.removed) { - t.Errorf("%s expected %v, got %v", test.name, test.expectedRemoved, registration.removed) - } + t.Run(test.name, func(t *testing.T) { + registration := &fakeAPIServiceRegistration{} + crdCache := cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) + crdLister := crdlisters.NewCustomResourceDefinitionLister(crdCache) + c := crdRegistrationController{ + crdLister: crdLister, + apiServiceRegistration: registration, + } + for i := range test.startingCRDs { + crdCache.Add(test.startingCRDs[i]) + } + + c.handleVersionUpdate(test.version) + + if !reflect.DeepEqual(test.expectedAdded, registration.added) { + t.Errorf("%s expected %v, got %v", test.name, test.expectedAdded, registration.added) + } + if !reflect.DeepEqual(test.expectedRemoved, registration.removed) { + t.Errorf("%s expected %v, got %v", test.name, test.expectedRemoved, registration.removed) + } + }) } - } type fakeAPIServiceRegistration struct { diff --git a/vendor/k8s.io/kubernetes/pkg/master/controller_test.go b/vendor/k8s.io/kubernetes/pkg/master/controller_test.go index ec7d63158..a20d82cd6 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/controller_test.go +++ b/vendor/k8s.io/kubernetes/pkg/master/controller_test.go @@ -570,7 +570,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -625,7 +625,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -637,7 +637,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -658,7 +658,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -671,7 +671,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -691,7 +691,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -703,7 +703,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -723,7 +723,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -735,7 +735,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -755,7 +755,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -767,7 +767,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -787,7 +787,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -799,7 +799,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -819,7 +819,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeNodePort, }, }, @@ -831,7 +831,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -851,7 +851,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, @@ -910,7 +910,7 @@ func TestCreateOrUpdateMasterService(t *testing.T) { }, Selector: nil, ClusterIP: "1.2.3.4", - SessionAffinity: api.ServiceAffinityClientIP, + SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, }, }, diff --git a/vendor/k8s.io/kubernetes/pkg/master/import_known_versions.go b/vendor/k8s.io/kubernetes/pkg/master/import_known_versions.go index baf2502e9..38d355af6 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/import_known_versions.go +++ b/vendor/k8s.io/kubernetes/pkg/master/import_known_versions.go @@ -18,10 +18,6 @@ package master // These imports are the API groups the API server will support. import ( - "fmt" - - "k8s.io/kubernetes/pkg/api/legacyscheme" - _ "k8s.io/kubernetes/pkg/apis/admission/install" _ "k8s.io/kubernetes/pkg/apis/admissionregistration/install" _ "k8s.io/kubernetes/pkg/apis/apps/install" @@ -42,9 +38,3 @@ import ( _ "k8s.io/kubernetes/pkg/apis/settings/install" _ "k8s.io/kubernetes/pkg/apis/storage/install" ) - -func init() { - if missingVersions := legacyscheme.Registry.ValidateEnvRequestedVersions(); len(missingVersions) != 0 { - panic(fmt.Sprintf("KUBE_API_VERSIONS contains versions that are not installed: %q.", missingVersions)) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/master/import_known_versions_test.go b/vendor/k8s.io/kubernetes/pkg/master/import_known_versions_test.go index e6a69e7d6..c2aba1401 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/import_known_versions_test.go +++ b/vendor/k8s.io/kubernetes/pkg/master/import_known_versions_test.go @@ -49,7 +49,7 @@ func TestGroupVersions(t *testing.T) { t.Errorf("No additional unnamespaced groups should be created") } - for _, gv := range legacyscheme.Registry.RegisteredGroupVersions() { + for _, gv := range legacyscheme.Scheme.PrioritizedVersionsAllGroups() { if !strings.HasSuffix(gv.Group, ".k8s.io") && !legacyUnsuffixedGroups.Has(gv.Group) { t.Errorf("Group %s does not have the standard kubernetes API group suffix of .k8s.io", gv.Group) } diff --git a/vendor/k8s.io/kubernetes/pkg/master/master.go b/vendor/k8s.io/kubernetes/pkg/master/master.go index d90dadfda..240f631a8 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/master.go +++ b/vendor/k8s.io/kubernetes/pkg/master/master.go @@ -24,6 +24,7 @@ import ( "strconv" "time" + admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1" admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" appsv1 "k8s.io/api/apps/v1" appsv1beta1 "k8s.io/api/apps/v1beta1" @@ -36,6 +37,7 @@ import ( autoscalingapiv2beta1 "k8s.io/api/autoscaling/v2beta1" batchapiv1 "k8s.io/api/batch/v1" batchapiv1beta1 "k8s.io/api/batch/v1beta1" + batchapiv2alpha1 "k8s.io/api/batch/v2alpha1" certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1" apiv1 "k8s.io/api/core/v1" eventsv1beta1 "k8s.io/api/events/v1beta1" @@ -43,8 +45,13 @@ import ( networkingapiv1 "k8s.io/api/networking/v1" policyapiv1beta1 "k8s.io/api/policy/v1beta1" rbacv1 "k8s.io/api/rbac/v1" + rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" + schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + schedulingapiv1beta1 "k8s.io/api/scheduling/v1beta1" + settingsv1alpha1 "k8s.io/api/settings/v1alpha1" storageapiv1 "k8s.io/api/storage/v1" + storageapiv1alpha1 "k8s.io/api/storage/v1alpha1" storageapiv1beta1 "k8s.io/api/storage/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilnet "k8s.io/apimachinery/pkg/util/net" @@ -103,7 +110,6 @@ type ExtraConfig struct { APIResourceConfigSource serverstorage.APIResourceConfigSource StorageFactory serverstorage.StorageFactory - EnableCoreControllers bool EndpointReconcilerConfig EndpointReconcilerConfig EventTTL time.Duration KubeletClientConfig kubeletclient.KubeletClientConfig @@ -284,9 +290,6 @@ func (cfg *Config) Complete(informers informers.SharedInformerFactory) Completed c.ExtraConfig.EndpointReconcilerConfig.Reconciler = cfg.createEndpointReconciler() } - // this has always been hardcoded true in the past - c.GenericConfig.EnableMetrics = true - return CompletedConfig{&c} } @@ -371,13 +374,11 @@ func (m *Master) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic. glog.Fatalf("Error building core storage: %v", err) } - if c.ExtraConfig.EnableCoreControllers { - controllerName := "bootstrap-controller" - coreClient := coreclient.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig) - bootstrapController := c.NewBootstrapController(legacyRESTStorage, coreClient, coreClient, coreClient) - m.GenericAPIServer.AddPostStartHookOrDie(controllerName, bootstrapController.PostStartHook) - m.GenericAPIServer.AddPreShutdownHookOrDie(controllerName, bootstrapController.PreShutdownHook) - } + controllerName := "bootstrap-controller" + coreClient := coreclient.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig) + bootstrapController := c.NewBootstrapController(legacyRESTStorage, coreClient, coreClient, coreClient) + m.GenericAPIServer.AddPostStartHookOrDie(controllerName, bootstrapController.PostStartHook) + m.GenericAPIServer.AddPreShutdownHookOrDie(controllerName, bootstrapController.PreShutdownHook) if err := m.GenericAPIServer.InstallLegacyAPIGroup(genericapiserver.DefaultLegacyAPIPrefix, &apiGroupInfo); err != nil { glog.Fatalf("Error in registering group versions: %v", err) @@ -462,28 +463,38 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { ret := serverstorage.NewResourceConfig() // NOTE: GroupVersions listed here will be enabled by default. Don't put alpha versions in the list. ret.EnableVersions( + admissionregistrationv1beta1.SchemeGroupVersion, apiv1.SchemeGroupVersion, - extensionsapiv1beta1.SchemeGroupVersion, - batchapiv1.SchemeGroupVersion, - batchapiv1beta1.SchemeGroupVersion, + appsv1beta1.SchemeGroupVersion, + appsv1beta2.SchemeGroupVersion, + appsv1.SchemeGroupVersion, authenticationv1.SchemeGroupVersion, authenticationv1beta1.SchemeGroupVersion, + authorizationapiv1.SchemeGroupVersion, + authorizationapiv1beta1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion, autoscalingapiv2beta1.SchemeGroupVersion, - appsv1beta1.SchemeGroupVersion, - appsv1beta2.SchemeGroupVersion, - appsv1.SchemeGroupVersion, + batchapiv1.SchemeGroupVersion, + batchapiv1beta1.SchemeGroupVersion, + certificatesapiv1beta1.SchemeGroupVersion, + eventsv1beta1.SchemeGroupVersion, + extensionsapiv1beta1.SchemeGroupVersion, + networkingapiv1.SchemeGroupVersion, policyapiv1beta1.SchemeGroupVersion, rbacv1.SchemeGroupVersion, rbacv1beta1.SchemeGroupVersion, storageapiv1.SchemeGroupVersion, storageapiv1beta1.SchemeGroupVersion, - certificatesapiv1beta1.SchemeGroupVersion, - authorizationapiv1.SchemeGroupVersion, - authorizationapiv1beta1.SchemeGroupVersion, - networkingapiv1.SchemeGroupVersion, - eventsv1beta1.SchemeGroupVersion, - admissionregistrationv1beta1.SchemeGroupVersion, + schedulingapiv1beta1.SchemeGroupVersion, + ) + // disable alpha versions explicitly so we have a full list of what's possible to serve + ret.DisableVersions( + admissionregistrationv1alpha1.SchemeGroupVersion, + batchapiv2alpha1.SchemeGroupVersion, + rbacv1alpha1.SchemeGroupVersion, + schedulingv1alpha1.SchemeGroupVersion, + settingsv1alpha1.SchemeGroupVersion, + storageapiv1alpha1.SchemeGroupVersion, ) return ret diff --git a/vendor/k8s.io/kubernetes/pkg/master/master_openapi_test.go b/vendor/k8s.io/kubernetes/pkg/master/master_openapi_test.go index d640582a3..b8053e89a 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/master_openapi_test.go +++ b/vendor/k8s.io/kubernetes/pkg/master/master_openapi_test.go @@ -27,7 +27,7 @@ import ( "net/http/httptest" "testing" - apirequest "k8s.io/apiserver/pkg/endpoints/request" + openapinamer "k8s.io/apiserver/pkg/endpoints/openapi" genericapiserver "k8s.io/apiserver/pkg/server" "k8s.io/kubernetes/pkg/api/legacyscheme" openapigen "k8s.io/kubernetes/pkg/generated/openapi" @@ -45,7 +45,7 @@ func TestValidOpenAPISpec(t *testing.T) { defer etcdserver.Terminate(t) config.GenericConfig.EnableIndex = true - config.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapigen.GetOpenAPIDefinitions, legacyscheme.Scheme) + config.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapigen.GetOpenAPIDefinitions, openapinamer.NewDefinitionNamer(legacyscheme.Scheme)) config.GenericConfig.OpenAPIConfig.Info = &spec.Info{ InfoProps: spec.InfoProps{ Title: "Kubernetes", @@ -54,13 +54,13 @@ func TestValidOpenAPISpec(t *testing.T) { } config.GenericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig() - master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate) + master, err := config.Complete(sharedInformers).New(genericapiserver.NewEmptyDelegate()) if err != nil { t.Fatalf("Error in bringing up the master: %v", err) } // make sure swagger.json is not registered before calling PrepareRun. - server := httptest.NewServer(apirequest.WithRequestContext(master.GenericAPIServer.Handler.Director, master.GenericAPIServer.RequestContextMapper())) + server := httptest.NewServer(master.GenericAPIServer.Handler.Director) defer server.Close() resp, err := http.Get(server.URL + "/swagger.json") if !assert.NoError(err) { diff --git a/vendor/k8s.io/kubernetes/pkg/master/master_test.go b/vendor/k8s.io/kubernetes/pkg/master/master_test.go index bb4681e3b..eb7032169 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/master_test.go +++ b/vendor/k8s.io/kubernetes/pkg/master/master_test.go @@ -17,6 +17,7 @@ limitations under the License. package master import ( + "context" "crypto/tls" "encoding/json" "io/ioutil" @@ -35,7 +36,6 @@ import ( utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/version" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericapiserver "k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server/options" serverstorage "k8s.io/apiserver/pkg/server/storage" @@ -78,18 +78,18 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, informers.SharedI }, } - resourceEncoding := serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Registry) - resourceEncoding.SetVersionEncoding(api.GroupName, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, schema.GroupVersion{Group: api.GroupName, Version: runtime.APIVersionInternal}) - resourceEncoding.SetVersionEncoding(autoscaling.GroupName, *testapi.Autoscaling.GroupVersion(), schema.GroupVersion{Group: autoscaling.GroupName, Version: runtime.APIVersionInternal}) - resourceEncoding.SetVersionEncoding(batch.GroupName, *testapi.Batch.GroupVersion(), schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal}) + resourceEncoding := serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Scheme) + resourceEncoding.SetVersionEncoding(api.GroupName, schema.GroupVersion{Group: "", Version: "v1"}, schema.GroupVersion{Group: api.GroupName, Version: runtime.APIVersionInternal}) + resourceEncoding.SetVersionEncoding(autoscaling.GroupName, schema.GroupVersion{Group: "autoscaling", Version: "v1"}, schema.GroupVersion{Group: autoscaling.GroupName, Version: runtime.APIVersionInternal}) + resourceEncoding.SetVersionEncoding(batch.GroupName, schema.GroupVersion{Group: "batch", Version: "v1"}, schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal}) // FIXME (soltysh): this GroupVersionResource override should be configurable resourceEncoding.SetResourceEncoding(schema.GroupResource{Group: "batch", Resource: "cronjobs"}, schema.GroupVersion{Group: batch.GroupName, Version: "v1beta1"}, schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal}) resourceEncoding.SetResourceEncoding(schema.GroupResource{Group: "storage.k8s.io", Resource: "volumeattachments"}, schema.GroupVersion{Group: storage.GroupName, Version: "v1beta1"}, schema.GroupVersion{Group: storage.GroupName, Version: runtime.APIVersionInternal}) - resourceEncoding.SetVersionEncoding(apps.GroupName, *testapi.Apps.GroupVersion(), schema.GroupVersion{Group: apps.GroupName, Version: runtime.APIVersionInternal}) - resourceEncoding.SetVersionEncoding(extensions.GroupName, *testapi.Extensions.GroupVersion(), schema.GroupVersion{Group: extensions.GroupName, Version: runtime.APIVersionInternal}) - resourceEncoding.SetVersionEncoding(rbac.GroupName, *testapi.Rbac.GroupVersion(), schema.GroupVersion{Group: rbac.GroupName, Version: runtime.APIVersionInternal}) - resourceEncoding.SetVersionEncoding(certificates.GroupName, *testapi.Certificates.GroupVersion(), schema.GroupVersion{Group: certificates.GroupName, Version: runtime.APIVersionInternal}) + resourceEncoding.SetVersionEncoding(apps.GroupName, schema.GroupVersion{Group: "apps", Version: "v1"}, schema.GroupVersion{Group: apps.GroupName, Version: runtime.APIVersionInternal}) + resourceEncoding.SetVersionEncoding(extensions.GroupName, schema.GroupVersion{Group: "extensions", Version: "v1beta1"}, schema.GroupVersion{Group: extensions.GroupName, Version: runtime.APIVersionInternal}) + resourceEncoding.SetVersionEncoding(rbac.GroupName, schema.GroupVersion{Group: "rbac.authorization.k8s.io", Version: "v1"}, schema.GroupVersion{Group: rbac.GroupName, Version: runtime.APIVersionInternal}) + resourceEncoding.SetVersionEncoding(certificates.GroupName, schema.GroupVersion{Group: "certificates.k8s.io", Version: "v1beta1"}, schema.GroupVersion{Group: certificates.GroupName, Version: runtime.APIVersionInternal}) storageFactory := serverstorage.NewDefaultStorageFactory(*storageConfig, testapi.StorageMediaType(), legacyscheme.Codecs, resourceEncoding, DefaultAPIResourceConfigSource(), nil) etcdOptions := options.NewEtcdOptions(storageConfig) @@ -106,13 +106,10 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, informers.SharedI config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs}} config.GenericConfig.PublicAddress = net.ParseIP("192.168.10.4") config.GenericConfig.LegacyAPIGroupPrefixes = sets.NewString("/api") - config.GenericConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper() config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs}} - config.GenericConfig.EnableMetrics = true - config.ExtraConfig.EnableCoreControllers = false config.ExtraConfig.KubeletClientConfig = kubeletclient.KubeletClientConfig{Port: 10250} config.ExtraConfig.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{ - Dial: func(network, addr string) (net.Conn, error) { return nil, nil }, + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { return nil, nil }, TLSClientConfig: &tls.Config{}, }) @@ -187,7 +184,7 @@ func TestCertificatesRestStorageStrategies(t *testing.T) { func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) { etcdserver, config, sharedInformers, assert := setUp(t) - master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate) + master, err := config.Complete(sharedInformers).New(genericapiserver.NewEmptyDelegate()) if err != nil { t.Fatalf("Error in bringing up the master: %v", err) } @@ -280,7 +277,7 @@ func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) { master, etcdserver, _, assert := newMaster(t) defer etcdserver.Terminate(t) - server := httptest.NewServer(genericapirequest.WithRequestContext(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux, master.GenericAPIServer.RequestContextMapper())) + server := httptest.NewServer(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux) // /api exists in release-1.1 resp, err := http.Get(server.URL + "/api") diff --git a/vendor/k8s.io/kubernetes/pkg/master/reconcilers/lease_test.go b/vendor/k8s.io/kubernetes/pkg/master/reconcilers/lease_test.go index e16612e25..97000d39f 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/reconcilers/lease_test.go +++ b/vendor/k8s.io/kubernetes/pkg/master/reconcilers/lease_test.go @@ -509,29 +509,31 @@ func TestLeaseEndpointReconciler(t *testing.T) { }, } for _, test := range nonReconcileTests { - fakeLeases := newFakeLeases() - fakeLeases.SetKeys(test.endpointKeys) - registry := ®istrytest.EndpointRegistry{ - Endpoints: test.endpoints, - } - r := NewLeaseEndpointReconciler(registry, fakeLeases) - err := r.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, false) - if err != nil { - t.Errorf("case %q: unexpected error: %v", test.testName, err) - } - if test.expectUpdate != nil { - if len(registry.Updates) != 1 { - t.Errorf("case %q: unexpected updates: %v", test.testName, registry.Updates) - } else if e, a := test.expectUpdate, ®istry.Updates[0]; !reflect.DeepEqual(e, a) { - t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + t.Run(test.testName, func(t *testing.T) { + fakeLeases := newFakeLeases() + fakeLeases.SetKeys(test.endpointKeys) + registry := ®istrytest.EndpointRegistry{ + Endpoints: test.endpoints, } - } - if test.expectUpdate == nil && len(registry.Updates) > 0 { - t.Errorf("case %q: no update expected, yet saw: %v", test.testName, registry.Updates) - } - if updatedKeys := fakeLeases.GetUpdatedKeys(); len(updatedKeys) != 1 || updatedKeys[0] != test.ip { - t.Errorf("case %q: expected the master's IP to be refreshed, but the following IPs were refreshed instead: %v", test.testName, updatedKeys) - } + r := NewLeaseEndpointReconciler(registry, fakeLeases) + err := r.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, false) + if err != nil { + t.Errorf("case %q: unexpected error: %v", test.testName, err) + } + if test.expectUpdate != nil { + if len(registry.Updates) != 1 { + t.Errorf("case %q: unexpected updates: %v", test.testName, registry.Updates) + } else if e, a := test.expectUpdate, ®istry.Updates[0]; !reflect.DeepEqual(e, a) { + t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + } + } + if test.expectUpdate == nil && len(registry.Updates) > 0 { + t.Errorf("case %q: no update expected, yet saw: %v", test.testName, registry.Updates) + } + if updatedKeys := fakeLeases.GetUpdatedKeys(); len(updatedKeys) != 1 || updatedKeys[0] != test.ip { + t.Errorf("case %q: expected the master's IP to be refreshed, but the following IPs were refreshed instead: %v", test.testName, updatedKeys) + } + }) } } @@ -604,30 +606,32 @@ func TestLeaseStopReconciling(t *testing.T) { }, } for _, test := range stopTests { - fakeLeases := newFakeLeases() - fakeLeases.SetKeys(test.endpointKeys) - registry := ®istrytest.EndpointRegistry{ - Endpoints: test.endpoints, - } - r := NewLeaseEndpointReconciler(registry, fakeLeases) - err := r.StopReconciling(test.serviceName, net.ParseIP(test.ip), test.endpointPorts) - if err != nil { - t.Errorf("case %q: unexpected error: %v", test.testName, err) - } - if test.expectUpdate != nil { - if len(registry.Updates) != 1 { - t.Errorf("case %q: unexpected updates: %v", test.testName, registry.Updates) - } else if e, a := test.expectUpdate, ®istry.Updates[0]; !reflect.DeepEqual(e, a) { - t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + t.Run(test.testName, func(t *testing.T) { + fakeLeases := newFakeLeases() + fakeLeases.SetKeys(test.endpointKeys) + registry := ®istrytest.EndpointRegistry{ + Endpoints: test.endpoints, } - } - if test.expectUpdate == nil && len(registry.Updates) > 0 { - t.Errorf("case %q: no update expected, yet saw: %v", test.testName, registry.Updates) - } - for _, key := range fakeLeases.GetUpdatedKeys() { - if key == test.ip { - t.Errorf("case %q: Found ip %s in leases but shouldn't be there", test.testName, key) + r := NewLeaseEndpointReconciler(registry, fakeLeases) + err := r.StopReconciling(test.serviceName, net.ParseIP(test.ip), test.endpointPorts) + if err != nil { + t.Errorf("case %q: unexpected error: %v", test.testName, err) } - } + if test.expectUpdate != nil { + if len(registry.Updates) != 1 { + t.Errorf("case %q: unexpected updates: %v", test.testName, registry.Updates) + } else if e, a := test.expectUpdate, ®istry.Updates[0]; !reflect.DeepEqual(e, a) { + t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + } + } + if test.expectUpdate == nil && len(registry.Updates) > 0 { + t.Errorf("case %q: no update expected, yet saw: %v", test.testName, registry.Updates) + } + for _, key := range fakeLeases.GetUpdatedKeys() { + if key == test.ip { + t.Errorf("case %q: Found ip %s in leases but shouldn't be there", test.testName, key) + } + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/master/tunneler/ssh.go b/vendor/k8s.io/kubernetes/pkg/master/tunneler/ssh.go index 2bee87326..6a55015d5 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/tunneler/ssh.go +++ b/vendor/k8s.io/kubernetes/pkg/master/tunneler/ssh.go @@ -43,7 +43,7 @@ type AddressFunc func() (addresses []string, err error) type Tunneler interface { Run(AddressFunc) Stop() - Dial(net, addr string) (net.Conn, error) + Dial(ctx context.Context, net, addr string) (net.Conn, error) SecondsSinceSync() int64 SecondsSinceSSHKeySync() int64 } @@ -149,8 +149,8 @@ func (c *SSHTunneler) Stop() { } } -func (c *SSHTunneler) Dial(net, addr string) (net.Conn, error) { - return c.tunnels.Dial(net, addr) +func (c *SSHTunneler) Dial(ctx context.Context, net, addr string) (net.Conn, error) { + return c.tunnels.Dial(ctx, net, addr) } func (c *SSHTunneler) SecondsSinceSync() int64 { diff --git a/vendor/k8s.io/kubernetes/pkg/master/tunneler/ssh_test.go b/vendor/k8s.io/kubernetes/pkg/master/tunneler/ssh_test.go index 1b1f40058..f4f58b0f6 100644 --- a/vendor/k8s.io/kubernetes/pkg/master/tunneler/ssh_test.go +++ b/vendor/k8s.io/kubernetes/pkg/master/tunneler/ssh_test.go @@ -17,6 +17,7 @@ limitations under the License. package tunneler import ( + "context" "fmt" "net" "os" @@ -32,39 +33,66 @@ import ( // TestSecondsSinceSync verifies that proper results are returned // when checking the time between syncs func TestSecondsSinceSync(t *testing.T) { - tunneler := &SSHTunneler{} - assert := assert.New(t) - - tunneler.lastSync = time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix() - - // Nano Second. No difference. - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 1, 2, time.UTC)) - assert.Equal(int64(0), tunneler.SecondsSinceSync()) - - // Second - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 2, 1, time.UTC)) - assert.Equal(int64(1), tunneler.SecondsSinceSync()) - - // Minute - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 2, 1, 1, time.UTC)) - assert.Equal(int64(60), tunneler.SecondsSinceSync()) - - // Hour - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 2, 1, 1, 1, time.UTC)) - assert.Equal(int64(3600), tunneler.SecondsSinceSync()) - - // Day - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 2, 1, 1, 1, 1, time.UTC)) - assert.Equal(int64(86400), tunneler.SecondsSinceSync()) - - // Month - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC)) - assert.Equal(int64(2678400), tunneler.SecondsSinceSync()) + tests := []struct { + name string + lastSync int64 + clock *clock.FakeClock + want int64 + }{ + { + name: "Nano Second. No difference", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 1, 2, time.UTC)), + want: int64(0), + }, + { + name: "Second", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 2, 1, time.UTC)), + want: int64(1), + }, + { + name: "Minute", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 2, 1, 1, time.UTC)), + want: int64(60), + }, + { + name: "Hour", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 2, 1, 1, 1, time.UTC)), + want: int64(3600), + }, + { + name: "Day", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 2, 1, 1, 1, 1, time.UTC)), + want: int64(86400), + }, + { + name: "Month", + lastSync: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC)), + want: int64(2678400), + }, + { + name: "Future Month. Should be -Month", + lastSync: time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC).Unix(), + clock: clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 1, 2, time.UTC)), + want: int64(-2678400), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tunneler := &SSHTunneler{} + assert := assert.New(t) + tunneler.lastSync = tt.lastSync + tunneler.clock = tt.clock + assert.Equal(int64(tt.want), tunneler.SecondsSinceSync()) + }) + } - // Future Month. Should be -Month. - tunneler.lastSync = time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC).Unix() - tunneler.clock = clock.NewFakeClock(time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC)) - assert.Equal(int64(-2678400), tunneler.SecondsSinceSync()) } // generateTempFile creates a temporary file path @@ -111,11 +139,11 @@ type FakeTunneler struct { SecondsSinceSSHKeySyncValue int64 } -func (t *FakeTunneler) Run(AddressFunc) {} -func (t *FakeTunneler) Stop() {} -func (t *FakeTunneler) Dial(net, addr string) (net.Conn, error) { return nil, nil } -func (t *FakeTunneler) SecondsSinceSync() int64 { return t.SecondsSinceSyncValue } -func (t *FakeTunneler) SecondsSinceSSHKeySync() int64 { return t.SecondsSinceSSHKeySyncValue } +func (t *FakeTunneler) Run(AddressFunc) {} +func (t *FakeTunneler) Stop() {} +func (t *FakeTunneler) Dial(ctx context.Context, net, addr string) (net.Conn, error) { return nil, nil } +func (t *FakeTunneler) SecondsSinceSync() int64 { return t.SecondsSinceSyncValue } +func (t *FakeTunneler) SecondsSinceSSHKeySync() int64 { return t.SecondsSinceSSHKeySyncValue } // TestIsTunnelSyncHealthy verifies that the 600 second lag test // is honored. diff --git a/vendor/k8s.io/kubernetes/pkg/printers/BUILD b/vendor/k8s.io/kubernetes/pkg/printers/BUILD index 4e2dd0000..c08e56962 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/printers/BUILD @@ -10,20 +10,17 @@ go_library( name = "go_default_library", srcs = [ "customcolumn.go", + "customcolumn_flags.go", "humanreadable.go", "interface.go", - "json.go", - "jsonpath.go", - "name.go", - "printers.go", "tabwriter.go", - "template.go", - "versioned.go", ], importpath = "k8s.io/kubernetes/pkg/printers", deps = [ - "//vendor/github.com/ghodss/yaml:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", + "//pkg/kubectl/scheme:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", @@ -31,25 +28,11 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels: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/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/client-go/util/jsonpath:go_default_library", ], ) -go_test( - name = "go_default_xtest", - srcs = ["customcolumn_test.go"], - deps = [ - ":go_default_library", - "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - ], -) - filegroup( name = "package-srcs", srcs = glob(["**"]), @@ -69,10 +52,17 @@ filegroup( go_test( name = "go_default_test", - srcs = ["humanreadable_test.go"], + srcs = [ + "customcolumn_flags_test.go", + "customcolumn_test.go", + "humanreadable_test.go", + ], embed = [":go_default_library"], deps = [ + "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/printers/customcolumn.go b/vendor/k8s.io/kubernetes/pkg/printers/customcolumn.go index bba5bc4ce..45141e0cb 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/customcolumn.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/customcolumn.go @@ -29,14 +29,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/util/jsonpath" -) - -const ( - columnwidth = 10 - tabwidth = 4 - padding = 3 - padding_character = ' ' - flags = 0 + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" ) var jsonRegexp = regexp.MustCompile("^\\{\\.?([^{}]+)\\}$|^\\.?([^{}]+)$") @@ -158,12 +151,19 @@ type CustomColumnsPrinter struct { lastType reflect.Type } -func (s *CustomColumnsPrinter) AfterPrint(w io.Writer, res string) error { - return nil -} - func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error { - w := tabwriter.NewWriter(out, columnwidth, tabwidth, padding, padding_character, flags) + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if printers.InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(printers.InternalObjectPrinterErr) + } + + if w, found := out.(*tabwriter.Writer); !found { + w = GetNewTabWriter(out) + out = w + defer w.Flush() + } t := reflect.TypeOf(obj) if !s.NoHeaders && t != s.lastType { @@ -171,7 +171,7 @@ func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error for ix := range s.Columns { headers[ix] = s.Columns[ix].Header } - fmt.Fprintln(w, strings.Join(headers, "\t")) + fmt.Fprintln(out, strings.Join(headers, "\t")) s.lastType = t } parsers := make([]*jsonpath.JSONPath, len(s.Columns)) @@ -188,16 +188,16 @@ func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error return err } for ix := range objs { - if err := s.printOneObject(objs[ix], parsers, w); err != nil { + if err := s.printOneObject(objs[ix], parsers, out); err != nil { return err } } } else { - if err := s.printOneObject(obj, parsers, w); err != nil { + if err := s.printOneObject(obj, parsers, out); err != nil { return err } } - return w.Flush() + return nil } func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jsonpath.JSONPath, out io.Writer) error { @@ -240,11 +240,3 @@ func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jso fmt.Fprintln(out, strings.Join(columns, "\t")) return nil } - -func (s *CustomColumnsPrinter) HandledResources() []string { - return []string{} -} - -func (s *CustomColumnsPrinter) IsGeneric() bool { - return true -} diff --git a/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_flags.go b/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_flags.go new file mode 100644 index 000000000..9ef91f97e --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_flags.go @@ -0,0 +1,109 @@ +/* +Copyright 2018 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 printers + +import ( + "fmt" + "os" + "strings" + + "github.com/spf13/cobra" + + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/scheme" +) + +var columnsFormats = map[string]bool{ + "custom-columns-file": true, + "custom-columns": true, +} + +// CustomColumnsPrintFlags provides default flags necessary for printing +// custom resource columns from an inline-template or file. +type CustomColumnsPrintFlags struct { + NoHeaders bool + TemplateArgument string +} + +func (f *CustomColumnsPrintFlags) AllowedFormats() []string { + formats := make([]string, 0, len(columnsFormats)) + for format := range columnsFormats { + formats = append(formats, format) + } + return formats +} + +// ToPrinter receives an templateFormat and returns a printer capable of +// handling custom-column printing. +// Returns false if the specified templateFormat does not match a supported format. +// Supported format types can be found in pkg/printers/printers.go +func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter, error) { + if len(templateFormat) == 0 { + return nil, genericclioptions.NoCompatiblePrinterError{} + } + + templateValue := "" + + if len(f.TemplateArgument) == 0 { + for format := range columnsFormats { + format = format + "=" + if strings.HasPrefix(templateFormat, format) { + templateValue = templateFormat[len(format):] + templateFormat = format[:len(format)-1] + break + } + } + } else { + templateValue = f.TemplateArgument + } + + if _, supportedFormat := columnsFormats[templateFormat]; !supportedFormat { + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()} + } + + if len(templateValue) == 0 { + return nil, fmt.Errorf("custom-columns format specified but no custom columns given") + } + + decoder := scheme.Codecs.UniversalDecoder() + + if templateFormat == "custom-columns-file" { + file, err := os.Open(templateValue) + if err != nil { + return nil, fmt.Errorf("error reading template %s, %v\n", templateValue, err) + } + defer file.Close() + p, err := NewCustomColumnsPrinterFromTemplate(file, decoder) + return p, err + } + + return NewCustomColumnsPrinterFromSpec(templateValue, decoder, f.NoHeaders) +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to custom-columns printing +func (f *CustomColumnsPrintFlags) AddFlags(c *cobra.Command) {} + +// NewCustomColumnsPrintFlags returns flags associated with +// custom-column printing, with default values set. +// NoHeaders and TemplateArgument should be set by callers. +func NewCustomColumnsPrintFlags() *CustomColumnsPrintFlags { + return &CustomColumnsPrintFlags{ + NoHeaders: false, + TemplateArgument: "", + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_flags_test.go b/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_flags_test.go new file mode 100644 index 000000000..1aed87449 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_flags_test.go @@ -0,0 +1,139 @@ +/* +Copyright 2018 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 printers + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "strings" + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" +) + +func TestPrinterSupportsExpectedCustomColumnFormats(t *testing.T) { + testObject := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + + customColumnsFile, err := ioutil.TempFile("", "printers_jsonpath_flags") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + defer func(tempFile *os.File) { + tempFile.Close() + os.Remove(tempFile.Name()) + }(customColumnsFile) + + fmt.Fprintf(customColumnsFile, "NAME\n.metadata.name") + + testCases := []struct { + name string + outputFormat string + templateArg string + expectedError string + expectedParseError string + expectedOutput string + expectNoMatch bool + }{ + { + name: "valid output format also containing the custom-columns argument succeeds", + outputFormat: "custom-columns=NAME:.metadata.name", + expectedOutput: "foo", + }, + { + name: "valid output format and no --template argument results in an error", + outputFormat: "custom-columns", + expectedError: "custom-columns format specified but no custom columns given", + }, + { + name: "valid output format and --template argument succeeds", + outputFormat: "custom-columns", + templateArg: "NAME:.metadata.name", + expectedOutput: "foo", + }, + { + name: "custom-columns template file should match, and successfully return correct value", + outputFormat: "custom-columns-file", + templateArg: customColumnsFile.Name(), + expectedOutput: "foo", + }, + { + name: "valid output format and invalid --template argument results in a parsing error from the printer", + outputFormat: "custom-columns", + templateArg: "invalid", + expectedError: "unexpected custom-columns spec: invalid, expected
    :", + }, + { + name: "no printer is matched on an invalid outputFormat", + outputFormat: "invalid", + expectNoMatch: true, + }, + { + name: "custom-columns printer should not match on any other format supported by another printer", + outputFormat: "go-template", + expectNoMatch: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + printFlags := CustomColumnsPrintFlags{ + TemplateArgument: tc.templateArg, + } + + p, err := printFlags.ToPrinter(tc.outputFormat) + if tc.expectNoMatch { + if !genericclioptions.IsNoCompatiblePrinterError(err) { + t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) + } + return + } + if genericclioptions.IsNoCompatiblePrinterError(err) { + t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) + } + + if len(tc.expectedError) > 0 { + if err == nil || !strings.Contains(err.Error(), tc.expectedError) { + t.Errorf("expecting error %q, got %v", tc.expectedError, err) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + out := bytes.NewBuffer([]byte{}) + err = p.PrintObj(testObject, out) + if len(tc.expectedParseError) > 0 { + if err == nil || !strings.Contains(err.Error(), tc.expectedParseError) { + t.Errorf("expecting error %q, got %v", tc.expectedError, err) + } + return + } + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if !strings.Contains(out.String(), tc.expectedOutput) { + t.Errorf("unexpected output: expecting %q, got %q", tc.expectedOutput, out.String()) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_test.go b/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_test.go index cb67a4ef7..d01c9c123 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_test.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/customcolumn_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package printers_test +package printers import ( "bytes" @@ -27,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/printers" ) func TestMassageJSONPath(t *testing.T) { @@ -47,27 +46,29 @@ func TestMassageJSONPath(t *testing.T) { {input: "{{foo.bar}", expectErr: true}, } for _, test := range tests { - output, err := printers.RelaxedJSONPathExpression(test.input) - if err != nil && !test.expectErr { - t.Errorf("unexpected error: %v", err) - continue - } - if test.expectErr { - if err == nil { - t.Error("unexpected non-error") + t.Run(test.input, func(t *testing.T) { + output, err := RelaxedJSONPathExpression(test.input) + if err != nil && !test.expectErr { + t.Errorf("unexpected error: %v", err) + return } - continue - } - if output != test.expectedOutput { - t.Errorf("input: %s, expected: %s, saw: %s", test.input, test.expectedOutput, output) - } + if test.expectErr { + if err == nil { + t.Error("unexpected non-error") + } + return + } + if output != test.expectedOutput { + t.Errorf("input: %s, expected: %s, saw: %s", test.input, test.expectedOutput, output) + } + }) } } func TestNewColumnPrinterFromSpec(t *testing.T) { tests := []struct { spec string - expectedColumns []printers.Column + expectedColumns []Column expectErr bool name string noHeaders bool @@ -95,7 +96,7 @@ func TestNewColumnPrinterFromSpec(t *testing.T) { { spec: "NAME:metadata.name,API_VERSION:apiVersion", name: "ok", - expectedColumns: []printers.Column{ + expectedColumns: []Column{ { Header: "NAME", FieldSpec: "{.metadata.name}", @@ -113,33 +114,34 @@ func TestNewColumnPrinterFromSpec(t *testing.T) { }, } for _, test := range tests { - printer, err := printers.NewCustomColumnsPrinterFromSpec(test.spec, legacyscheme.Codecs.UniversalDecoder(), test.noHeaders) - if test.expectErr { - if err == nil { - t.Errorf("[%s] unexpected non-error", test.name) + t.Run(test.name, func(t *testing.T) { + printer, err := NewCustomColumnsPrinterFromSpec(test.spec, legacyscheme.Codecs.UniversalDecoder(), test.noHeaders) + if test.expectErr { + if err == nil { + t.Errorf("[%s] unexpected non-error", test.name) + } + return } - continue - } - if !test.expectErr && err != nil { - t.Errorf("[%s] unexpected error: %v", test.name, err) - continue - } - if test.noHeaders { - buffer := &bytes.Buffer{} - - printer.PrintObj(&api.Pod{}, buffer) - if err != nil { - t.Fatalf("An error occurred printing Pod: %#v", err) + if !test.expectErr && err != nil { + t.Errorf("[%s] unexpected error: %v", test.name, err) + return } + if test.noHeaders { + buffer := &bytes.Buffer{} - if contains(strings.Fields(buffer.String()), "API_VERSION") { - t.Errorf("unexpected header API_VERSION") - } + printer.PrintObj(&api.Pod{}, buffer) + if err != nil { + t.Fatalf("An error occurred printing Pod: %#v", err) + } - } else if !reflect.DeepEqual(test.expectedColumns, printer.Columns) { - t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v\n", test.name, test.expectedColumns, printer.Columns) - } + if contains(strings.Fields(buffer.String()), "API_VERSION") { + t.Errorf("unexpected header API_VERSION") + } + } else if !reflect.DeepEqual(test.expectedColumns, printer.Columns) { + t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v\n", test.name, test.expectedColumns, printer.Columns) + } + }) } } @@ -161,7 +163,7 @@ const exampleTemplateTwo = `NAME API_VERSION func TestNewColumnPrinterFromTemplate(t *testing.T) { tests := []struct { spec string - expectedColumns []printers.Column + expectedColumns []Column expectErr bool name string }{ @@ -188,7 +190,7 @@ func TestNewColumnPrinterFromTemplate(t *testing.T) { { spec: exampleTemplateOne, name: "ok", - expectedColumns: []printers.Column{ + expectedColumns: []Column{ { Header: "NAME", FieldSpec: "{.metadata.name}", @@ -202,7 +204,7 @@ func TestNewColumnPrinterFromTemplate(t *testing.T) { { spec: exampleTemplateTwo, name: "ok-2", - expectedColumns: []printers.Column{ + expectedColumns: []Column{ { Header: "NAME", FieldSpec: "{.metadata.name}", @@ -215,34 +217,35 @@ func TestNewColumnPrinterFromTemplate(t *testing.T) { }, } for _, test := range tests { - reader := bytes.NewBufferString(test.spec) - printer, err := printers.NewCustomColumnsPrinterFromTemplate(reader, legacyscheme.Codecs.UniversalDecoder()) - if test.expectErr { - if err == nil { - t.Errorf("[%s] unexpected non-error", test.name) + t.Run(test.name, func(t *testing.T) { + reader := bytes.NewBufferString(test.spec) + printer, err := NewCustomColumnsPrinterFromTemplate(reader, legacyscheme.Codecs.UniversalDecoder()) + if test.expectErr { + if err == nil { + t.Errorf("[%s] unexpected non-error", test.name) + } + return + } + if !test.expectErr && err != nil { + t.Errorf("[%s] unexpected error: %v", test.name, err) + return } - continue - } - if !test.expectErr && err != nil { - t.Errorf("[%s] unexpected error: %v", test.name, err) - continue - } - - if !reflect.DeepEqual(test.expectedColumns, printer.Columns) { - t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v\n", test.name, test.expectedColumns, printer.Columns) - } + if !reflect.DeepEqual(test.expectedColumns, printer.Columns) { + t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v\n", test.name, test.expectedColumns, printer.Columns) + } + }) } } func TestColumnPrint(t *testing.T) { tests := []struct { - columns []printers.Column + columns []Column obj runtime.Object expectedOutput string }{ { - columns: []printers.Column{ + columns: []Column{ { Header: "NAME", FieldSpec: "{.metadata.name}", @@ -254,7 +257,7 @@ foo `, }, { - columns: []printers.Column{ + columns: []Column{ { Header: "NAME", FieldSpec: "{.metadata.name}", @@ -272,7 +275,7 @@ bar `, }, { - columns: []printers.Column{ + columns: []Column{ { Header: "NAME", FieldSpec: "{.metadata.name}", @@ -288,7 +291,7 @@ foo baz `, }, { - columns: []printers.Column{ + columns: []Column{ { Header: "NAME", FieldSpec: "{.metadata.name}", @@ -310,16 +313,60 @@ foo baz } for _, test := range tests { - printer := &printers.CustomColumnsPrinter{ - Columns: test.columns, - Decoder: legacyscheme.Codecs.UniversalDecoder(), - } - buffer := &bytes.Buffer{} - if err := printer.PrintObj(test.obj, buffer); err != nil { + t.Run(test.expectedOutput, func(t *testing.T) { + printer := &CustomColumnsPrinter{ + Columns: test.columns, + Decoder: legacyscheme.Codecs.UniversalDecoder(), + } + buffer := &bytes.Buffer{} + if err := printer.PrintObj(test.obj, buffer); err != nil { + t.Errorf("unexpected error: %v", err) + } + if buffer.String() != test.expectedOutput { + t.Errorf("\nexpected:\n'%s'\nsaw\n'%s'\n", test.expectedOutput, buffer.String()) + } + }) + } +} + +// this mimics how resource/get.go calls the customcolumn printer +func TestIndividualPrintObjOnExistingTabWriter(t *testing.T) { + columns := []Column{ + { + Header: "NAME", + FieldSpec: "{.metadata.name}", + }, + { + Header: "LONG COLUMN NAME", // name is longer than all values of label1 + FieldSpec: "{.metadata.labels.label1}", + }, + { + Header: "LABEL 2", + FieldSpec: "{.metadata.labels.label2}", + }, + } + objects := []*v1.Pod{ + {ObjectMeta: metav1.ObjectMeta{Name: "foo", Labels: map[string]string{"label1": "foo", "label2": "foo"}}}, + {ObjectMeta: metav1.ObjectMeta{Name: "bar", Labels: map[string]string{"label1": "bar", "label2": "bar"}}}, + } + expectedOutput := `NAME LONG COLUMN NAME LABEL 2 +foo foo foo +bar bar bar +` + + buffer := &bytes.Buffer{} + tabWriter := GetNewTabWriter(buffer) + printer := &CustomColumnsPrinter{ + Columns: columns, + Decoder: legacyscheme.Codecs.UniversalDecoder(), + } + for _, obj := range objects { + if err := printer.PrintObj(obj, tabWriter); err != nil { t.Errorf("unexpected error: %v", err) } - if buffer.String() != test.expectedOutput { - t.Errorf("\nexpected:\n'%s'\nsaw\n'%s'\n", test.expectedOutput, buffer.String()) - } + } + tabWriter.Flush() + if buffer.String() != expectedOutput { + t.Errorf("\nexpected:\n'%s'\nsaw\n'%s'\n", expectedOutput, buffer.String()) } } diff --git a/vendor/k8s.io/kubernetes/pkg/printers/humanreadable.go b/vendor/k8s.io/kubernetes/pkg/printers/humanreadable.go index 7b63c83a2..ff926114a 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/humanreadable.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/humanreadable.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" @@ -70,11 +71,10 @@ var _ PrintHandler = &HumanReadablePrinter{} // NewHumanReadablePrinter creates a HumanReadablePrinter. // If encoder and decoder are provided, an attempt to convert unstructured types to internal types is made. -func NewHumanReadablePrinter(encoder runtime.Encoder, decoder runtime.Decoder, options PrintOptions) *HumanReadablePrinter { +func NewHumanReadablePrinter(decoder runtime.Decoder, options PrintOptions) *HumanReadablePrinter { printer := &HumanReadablePrinter{ handlerMap: make(map[reflect.Type]*handlerEntry), options: options, - encoder: encoder, decoder: decoder, } return printer @@ -257,14 +257,6 @@ func (h *HumanReadablePrinter) HandledResources() []string { return keys } -func (h *HumanReadablePrinter) AfterPrint(output io.Writer, res string) error { - return nil -} - -func (h *HumanReadablePrinter) IsGeneric() bool { - return false -} - func (h *HumanReadablePrinter) unknown(data []byte, w io.Writer) error { _, err := fmt.Fprintf(w, "Unknown object: %s", string(data)) return err @@ -278,12 +270,9 @@ func printHeader(columnNames []string, w io.Writer) error { } // PrintObj prints the obj in a human-friendly format according to the type of the obj. -// TODO: unify the behavior of PrintObj, which often expects single items and tracks -// headers and filtering, with other printers, that expect list objects. The tracking -// behavior should probably be a higher level wrapper (MultiObjectTablePrinter) that -// calls into the PrintTable method and then displays consistent output. func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error { - if w, found := output.(*tabwriter.Writer); !found && !h.skipTabWriter { + w, found := output.(*tabwriter.Writer) + if !found && !h.skipTabWriter { w = GetNewTabWriter(output) output = w defer w.Flush() @@ -299,14 +288,19 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er // check if the object is unstructured. If so, let's attempt to convert it to a type we can understand before // trying to print, since the printers are keyed by type. This is extremely expensive. - if h.encoder != nil && h.decoder != nil { - obj, _ = decodeUnknownObject(obj, h.encoder, h.decoder) + if h.decoder != nil { + obj, _ = decodeUnknownObject(obj, h.decoder) } // print with a registered handler t := reflect.TypeOf(obj) if handler := h.handlerMap[t]; handler != nil { includeHeaders := h.lastType != t && !h.options.NoHeaders + + if h.lastType != nil && h.lastType != t && !h.options.NoHeaders { + fmt.Fprintln(output) + } + if err := printRowsForHandlerEntry(output, handler, obj, h.options, includeHeaders); err != nil { return err } @@ -317,6 +311,11 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er // print with the default handler if set, and use the columns from the last time if h.defaultHandler != nil { includeHeaders := h.lastType != h.defaultHandler && !h.options.NoHeaders + + if h.lastType != nil && h.lastType != h.defaultHandler && !h.options.NoHeaders { + fmt.Fprintln(output) + } + if err := printRowsForHandlerEntry(output, h.defaultHandler, obj, h.options, includeHeaders); err != nil { return err } @@ -362,11 +361,13 @@ func PrintTable(table *metav1beta1.Table, output io.Writer, options PrintOptions fmt.Fprintln(output) } for _, row := range table.Rows { - if !options.ShowAll && hasCondition(row.Conditions, metav1beta1.RowCompleted) { - continue - } first := true for i, cell := range row.Cells { + if i >= len(table.ColumnDefinitions) { + // https://issue.k8s.io/66379 + // don't panic in case of bad output from the server, with more cells than column definitions + break + } column := table.ColumnDefinitions[i] if !options.Wide && column.Priority != 0 { continue @@ -813,15 +814,19 @@ func AppendAllLabels(showLabels bool, itemLabels map[string]string) string { } // check if the object is unstructured. If so, attempt to convert it to a type we can understand. -func decodeUnknownObject(obj runtime.Object, encoder runtime.Encoder, decoder runtime.Decoder) (runtime.Object, error) { +func decodeUnknownObject(obj runtime.Object, decoder runtime.Decoder) (runtime.Object, error) { var err error - switch obj.(type) { - case runtime.Unstructured, *runtime.Unknown: - if objBytes, err := runtime.Encode(encoder, obj); err == nil { + switch t := obj.(type) { + case runtime.Unstructured: + if objBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj); err == nil { if decodedObj, err := runtime.Decode(decoder, objBytes); err == nil { obj = decodedObj } } + case *runtime.Unknown: + if decodedObj, err := runtime.Decode(decoder, t.Raw); err == nil { + obj = decodedObj + } } return obj, err diff --git a/vendor/k8s.io/kubernetes/pkg/printers/humanreadable_test.go b/vendor/k8s.io/kubernetes/pkg/printers/humanreadable_test.go index bfd1d7874..1a86bb671 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/humanreadable_test.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/humanreadable_test.go @@ -48,7 +48,8 @@ func testPrintNamespace(obj *api.Namespace, options PrintOptions) ([]metav1beta1 func TestPrintRowsForHandlerEntry(t *testing.T) { printFunc := reflect.ValueOf(testPrintNamespace) - testCase := map[string]struct { + testCase := []struct { + name string h *handlerEntry opt PrintOptions obj runtime.Object @@ -56,7 +57,8 @@ func TestPrintRowsForHandlerEntry(t *testing.T) { expectOut string expectErr string }{ - "no tablecolumndefinition and includeheader flase": { + { + name: "no tablecolumndefinition and includeheader flase", h: &handlerEntry{ columnDefinitions: []metav1beta1.TableColumnDefinition{}, printRows: true, @@ -69,7 +71,8 @@ func TestPrintRowsForHandlerEntry(t *testing.T) { includeHeader: false, expectOut: "test\t\t\n", }, - "no tablecolumndefinition and includeheader true": { + { + name: "no tablecolumndefinition and includeheader true", h: &handlerEntry{ columnDefinitions: []metav1beta1.TableColumnDefinition{}, printRows: true, @@ -82,7 +85,8 @@ func TestPrintRowsForHandlerEntry(t *testing.T) { includeHeader: true, expectOut: "\ntest\t\t\n", }, - "have tablecolumndefinition and includeheader true": { + { + name: "have tablecolumndefinition and includeheader true", h: &handlerEntry{ columnDefinitions: testNamespaceColumnDefinitions, printRows: true, @@ -95,7 +99,8 @@ func TestPrintRowsForHandlerEntry(t *testing.T) { includeHeader: true, expectOut: "NAME\tSTATUS\tAGE\ntest\t\t\n", }, - "print namespace and withnamespace true, should not print header": { + { + name: "print namespace and withnamespace true, should not print header", h: &handlerEntry{ columnDefinitions: testNamespaceColumnDefinitions, printRows: true, @@ -112,16 +117,18 @@ func TestPrintRowsForHandlerEntry(t *testing.T) { expectErr: "namespace is not namespaced", }, } - for name, test := range testCase { - buffer := &bytes.Buffer{} - err := printRowsForHandlerEntry(buffer, test.h, test.obj, test.opt, test.includeHeader) - if err != nil { - if err.Error() != test.expectErr { - t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", name, test.expectErr, err) + for _, test := range testCase { + t.Run(test.name, func(t *testing.T) { + buffer := &bytes.Buffer{} + err := printRowsForHandlerEntry(buffer, test.h, test.obj, test.opt, test.includeHeader) + if err != nil { + if err.Error() != test.expectErr { + t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", test.name, test.expectErr, err) + } } - } - if test.expectOut != buffer.String() { - t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", name, test.expectOut, buffer.String()) - } + if test.expectOut != buffer.String() { + t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", test.name, test.expectOut, buffer.String()) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/printers/interface.go b/vendor/k8s.io/kubernetes/pkg/printers/interface.go index 840ae0859..f528de5ca 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/interface.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/interface.go @@ -28,12 +28,6 @@ import ( type ResourcePrinter interface { // Print receives a runtime object, formats it and prints it to a writer. PrintObj(runtime.Object, io.Writer) error - HandledResources() []string - //Can be used to print out warning/clarifications if needed - //after all objects were printed - AfterPrint(io.Writer, string) error - // Identify if it is a generic printer - IsGeneric() bool } // ResourcePrinterFunc is a function that can print objects @@ -44,19 +38,6 @@ func (fn ResourcePrinterFunc) PrintObj(obj runtime.Object, w io.Writer) error { return fn(obj, w) } -// TODO: implement HandledResources() -func (fn ResourcePrinterFunc) HandledResources() []string { - return []string{} -} - -func (fn ResourcePrinterFunc) AfterPrint(io.Writer, string) error { - return nil -} - -func (fn ResourcePrinterFunc) IsGeneric() bool { - return true -} - type PrintOptions struct { // supported Format types can be found in pkg/printers/printers.go OutputFormatType string diff --git a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/BUILD b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/BUILD index 1921aa44b..e28ee5404 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/BUILD @@ -27,11 +27,13 @@ go_test( "//pkg/apis/storage:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset/fake:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", + "//pkg/kubectl/genericclioptions/printers:go_default_library", "//pkg/printers:go_default_library", "//pkg/util/pointer:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -70,6 +72,7 @@ go_library( "//pkg/apis/networking:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/scheduling:go_default_library", "//pkg/apis/storage:go_default_library", "//pkg/apis/storage/util:go_default_library", @@ -83,6 +86,7 @@ go_library( "//pkg/util/slice:go_default_library", "//vendor/github.com/fatih/camelcase:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", @@ -90,6 +94,7 @@ go_library( "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", @@ -106,7 +111,8 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/describe.go b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/describe.go index 318148dfa..c1b59cf96 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/describe.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/describe.go @@ -33,7 +33,9 @@ import ( "github.com/golang/glog" "github.com/fatih/camelcase" - versionedextension "k8s.io/api/extensions/v1beta1" + + appsv1 "k8s.io/api/apps/v1" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/resource" @@ -45,7 +47,8 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/dynamic" - clientextensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" + externalclient "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" "k8s.io/kubernetes/pkg/api/events" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/ref" @@ -61,6 +64,7 @@ import ( "k8s.io/kubernetes/pkg/apis/networking" "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" "k8s.io/kubernetes/pkg/apis/scheduling" "k8s.io/kubernetes/pkg/apis/storage" storageutil "k8s.io/kubernetes/pkg/apis/storage/util" @@ -122,7 +126,16 @@ func (pw *prefixWriter) Flush() { } } -func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer { +func describerMap(clientConfig *rest.Config) (map[schema.GroupKind]printers.Describer, error) { + c, err := clientset.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + externalclient, err := externalclient.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + m := map[schema.GroupKind]printers.Describer{ api.Kind("Pod"): &PodDescriber{c}, api.Kind("ReplicationController"): &ReplicationControllerDescriber{c}, @@ -144,43 +157,38 @@ func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer extensions.Kind("PodSecurityPolicy"): &PodSecurityPolicyDescriber{c}, autoscaling.Kind("HorizontalPodAutoscaler"): &HorizontalPodAutoscalerDescriber{c}, extensions.Kind("DaemonSet"): &DaemonSetDescriber{c}, - extensions.Kind("Deployment"): &DeploymentDescriber{c, versionedExtensionsClientV1beta1(c)}, + extensions.Kind("Deployment"): &DeploymentDescriber{c, externalclient}, extensions.Kind("Ingress"): &IngressDescriber{c}, batch.Kind("Job"): &JobDescriber{c}, - batch.Kind("CronJob"): &CronJobDescriber{c}, + batch.Kind("CronJob"): &CronJobDescriber{c, externalclient}, apps.Kind("StatefulSet"): &StatefulSetDescriber{c}, - apps.Kind("Deployment"): &DeploymentDescriber{c, versionedExtensionsClientV1beta1(c)}, + apps.Kind("Deployment"): &DeploymentDescriber{c, externalclient}, apps.Kind("DaemonSet"): &DaemonSetDescriber{c}, apps.Kind("ReplicaSet"): &ReplicaSetDescriber{c}, certificates.Kind("CertificateSigningRequest"): &CertificateSigningRequestDescriber{c}, storage.Kind("StorageClass"): &StorageClassDescriber{c}, policy.Kind("PodDisruptionBudget"): &PodDisruptionBudgetDescriber{c}, - rbac.Kind("Role"): &RoleDescriber{c}, - rbac.Kind("ClusterRole"): &ClusterRoleDescriber{c}, - rbac.Kind("RoleBinding"): &RoleBindingDescriber{c}, - rbac.Kind("ClusterRoleBinding"): &ClusterRoleBindingDescriber{c}, + rbac.Kind("Role"): &RoleDescriber{externalclient}, + rbac.Kind("ClusterRole"): &ClusterRoleDescriber{externalclient}, + rbac.Kind("RoleBinding"): &RoleBindingDescriber{externalclient}, + rbac.Kind("ClusterRoleBinding"): &ClusterRoleBindingDescriber{externalclient}, networking.Kind("NetworkPolicy"): &NetworkPolicyDescriber{c}, scheduling.Kind("PriorityClass"): &PriorityClassDescriber{c}, } - return m -} - -// DescribableResources lists all resource types we can describe. -func DescribableResources() []string { - keys := make([]string, 0) - - for k := range describerMap(nil) { - resource := strings.ToLower(k.Kind) - keys = append(keys, resource) - } - return keys + return m, nil } // DescriberFor returns the default describe functions for each of the standard // Kubernetes types. -func DescriberFor(kind schema.GroupKind, c clientset.Interface) (printers.Describer, bool) { - f, ok := describerMap(c)[kind] +func DescriberFor(kind schema.GroupKind, clientConfig *rest.Config) (printers.Describer, bool) { + describers, err := describerMap(clientConfig) + if err != nil { + glog.V(1).Info(err) + return nil, false + } + + f, ok := describers[kind] return f, ok } @@ -197,12 +205,7 @@ type genericDescriber struct { } func (g *genericDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (output string, err error) { - apiResource := &metav1.APIResource{ - Name: g.mapping.Resource, - Namespaced: g.mapping.Scope.Name() == meta.RESTScopeNameNamespace, - Kind: g.mapping.GroupVersionKind.Kind, - } - obj, err := g.dynamic.Resource(apiResource, namespace).Get(name, metav1.GetOptions{}) + obj, err := g.dynamic.Resource(g.mapping.Resource).Namespace(namespace).Get(name, metav1.GetOptions{}) if err != nil { return "", err } @@ -963,7 +966,17 @@ func printCinderVolumeSource(cinder *api.CinderVolumeSource, w PrefixWriter) { " VolumeID:\t%v\n"+ " FSType:\t%v\n"+ " ReadOnly:\t%v\n", - cinder.VolumeID, cinder.FSType, cinder.ReadOnly) + " SecretRef:\t%v\n"+ + cinder.VolumeID, cinder.FSType, cinder.ReadOnly, cinder.SecretRef) +} + +func printCinderPersistentVolumeSource(cinder *api.CinderPersistentVolumeSource, w PrefixWriter) { + w.Write(LEVEL_2, "Type:\tCinder (a Persistent Disk resource in OpenStack)\n"+ + " VolumeID:\t%v\n"+ + " FSType:\t%v\n"+ + " ReadOnly:\t%v\n", + " SecretRef:\t%v\n"+ + cinder.VolumeID, cinder.SecretRef, cinder.FSType, cinder.ReadOnly, cinder.SecretRef) } func printScaleIOVolumeSource(sio *api.ScaleIOVolumeSource, w PrefixWriter) { @@ -1225,7 +1238,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) ( case pv.Spec.VsphereVolume != nil: printVsphereVolumeSource(pv.Spec.VsphereVolume, w) case pv.Spec.Cinder != nil: - printCinderVolumeSource(pv.Spec.Cinder, w) + printCinderPersistentVolumeSource(pv.Spec.Cinder, w) case pv.Spec.AzureDisk != nil: printAzureDiskVolumeSource(pv.Spec.AzureDisk, w) case pv.Spec.PhotonPersistentDisk != nil: @@ -1307,6 +1320,20 @@ func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.E if pvc.Spec.VolumeMode != nil { w.Write(LEVEL_0, "VolumeMode:\t%v\n", *pvc.Spec.VolumeMode) } + if len(pvc.Status.Conditions) > 0 { + w.Write(LEVEL_0, "Conditions:\n") + w.Write(LEVEL_1, "Type\tStatus\tLastProbeTime\tLastTransitionTime\tReason\tMessage\n") + w.Write(LEVEL_1, "----\t------\t-----------------\t------------------\t------\t-------\n") + for _, c := range pvc.Status.Conditions { + w.Write(LEVEL_1, "%v \t%v \t%s \t%s \t%v \t%v\n", + c.Type, + c.Status, + c.LastProbeTime.Time.Format(time.RFC1123Z), + c.LastTransitionTime.Time.Format(time.RFC1123Z), + c.Reason, + c.Message) + } + } if events != nil { DescribeEvents(events, w) } @@ -1840,10 +1867,11 @@ func describeJob(job *batch.Job, events *api.EventList) (string, error) { // CronJobDescriber generates information about a cron job and the jobs it has created. type CronJobDescriber struct { clientset.Interface + external externalclient.Interface } func (d *CronJobDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { - cronJob, err := d.Batch().CronJobs(namespace).Get(name, metav1.GetOptions{}) + cronJob, err := d.external.BatchV1beta1().CronJobs(namespace).Get(name, metav1.GetOptions{}) if err != nil { return "", err } @@ -1853,7 +1881,12 @@ func (d *CronJobDescriber) Describe(namespace, name string, describerSettings pr events, _ = d.Core().Events(namespace).Search(legacyscheme.Scheme, cronJob) } - return describeCronJob(cronJob, events) + internalCronJob := &batch.CronJob{} + if err := legacyscheme.Scheme.Convert(cronJob, internalCronJob, nil); err != nil { + return "", err + } + + return describeCronJob(internalCronJob, events) } func describeCronJob(cronJob *batch.CronJob, events *api.EventList) (string, error) { @@ -2422,7 +2455,7 @@ func describeServiceAccount(serviceAccount *api.ServiceAccount, tokens []api.Sec // RoleDescriber generates information about a node. type RoleDescriber struct { - clientset.Interface + externalclient.Interface } func (d *RoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { @@ -2431,7 +2464,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print return "", err } - breakdownRules := []rbac.PolicyRule{} + breakdownRules := []rbacv1.PolicyRule{} for _, rule := range role.Rules { breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...) } @@ -2440,7 +2473,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print if err != nil { return "", err } - sort.Stable(rbac.SortableRuleSlice(compactRules)) + sort.Stable(rbacv1helpers.SortableRuleSlice(compactRules)) return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) @@ -2461,7 +2494,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print // ClusterRoleDescriber generates information about a node. type ClusterRoleDescriber struct { - clientset.Interface + externalclient.Interface } func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { @@ -2470,7 +2503,7 @@ func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSetting return "", err } - breakdownRules := []rbac.PolicyRule{} + breakdownRules := []rbacv1.PolicyRule{} for _, rule := range role.Rules { breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...) } @@ -2479,7 +2512,7 @@ func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSetting if err != nil { return "", err } - sort.Stable(rbac.SortableRuleSlice(compactRules)) + sort.Stable(rbacv1helpers.SortableRuleSlice(compactRules)) return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) @@ -2517,7 +2550,7 @@ func combineResourceGroup(resource, group []string) string { // RoleBindingDescriber generates information about a node. type RoleBindingDescriber struct { - clientset.Interface + externalclient.Interface } func (d *RoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { @@ -2549,7 +2582,7 @@ func (d *RoleBindingDescriber) Describe(namespace, name string, describerSetting // ClusterRoleBindingDescriber generates information about a node. type ClusterRoleBindingDescriber struct { - clientset.Interface + externalclient.Interface } func (d *ClusterRoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { @@ -2689,9 +2722,6 @@ func describeNode(node *api.Node, nodeNonTerminatedPodsList *api.PodList, events if len(node.Spec.PodCIDR) > 0 { w.Write(LEVEL_0, "PodCIDR:\t%s\n", node.Spec.PodCIDR) } - if len(node.Spec.ExternalID) > 0 { - w.Write(LEVEL_0, "ExternalID:\t%s\n", node.Spec.ExternalID) - } if len(node.Spec.ProviderID) > 0 { w.Write(LEVEL_0, "ProviderID:\t%s\n", node.Spec.ProviderID) } @@ -2746,6 +2776,14 @@ func describeStatefulSet(ps *apps.StatefulSet, selector labels.Selector, events printLabelsMultiline(w, "Labels", ps.Labels) printAnnotationsMultiline(w, "Annotations", ps.Annotations) w.Write(LEVEL_0, "Replicas:\t%d desired | %d total\n", ps.Spec.Replicas, ps.Status.Replicas) + w.Write(LEVEL_0, "Update Strategy:\t%s\n", ps.Spec.UpdateStrategy.Type) + if ps.Spec.UpdateStrategy.RollingUpdate != nil { + ru := ps.Spec.UpdateStrategy.RollingUpdate + if ru.Partition != 0 { + w.Write(LEVEL_1, "Partition:\t%d\n", ru.Partition) + } + } + w.Write(LEVEL_0, "Pods Status:\t%d Running / %d Waiting / %d Succeeded / %d Failed\n", running, waiting, succeeded, failed) DescribePodTemplate(&ps.Spec.Template, w) describeVolumeClaimTemplates(ps.Spec.VolumeClaimTemplates, w) @@ -2924,17 +2962,9 @@ func describeHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, e } w.Write(LEVEL_0, "Min replicas:\t%s\n", minReplicas) w.Write(LEVEL_0, "Max replicas:\t%d\n", hpa.Spec.MaxReplicas) + w.Write(LEVEL_0, "%s pods:\t", hpa.Spec.ScaleTargetRef.Kind) + w.Write(LEVEL_0, "%d current / %d desired\n", hpa.Status.CurrentReplicas, hpa.Status.DesiredReplicas) - // TODO: switch to scale subresource once the required code is submitted. - if strings.ToLower(hpa.Spec.ScaleTargetRef.Kind) == "replicationcontroller" { - w.Write(LEVEL_0, "ReplicationController pods:\t") - rc, err := d.client.Core().ReplicationControllers(hpa.Namespace).Get(hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{}) - if err == nil { - w.Write(LEVEL_0, "%d current / %d desired\n", rc.Status.Replicas, rc.Spec.Replicas) - } else { - w.Write(LEVEL_0, "failed to check Replication Controller\n") - } - } if len(hpa.Status.Conditions) > 0 { w.Write(LEVEL_0, "Conditions:\n") w.Write(LEVEL_1, "Type\tStatus\tReason\tMessage\n") @@ -2973,8 +3003,9 @@ func describeNodeResource(nodeNonTerminatedPodsList *api.PodList, node *api.Node memoryReq.String(), int64(fractionMemoryReq), memoryLimit.String(), int64(fractionMemoryLimit)) } - w.Write(LEVEL_0, "Allocated resources:\n (Total limits may be over 100 percent, i.e., overcommitted.)\n CPU Requests\tCPU Limits\tMemory Requests\tMemory Limits\n") - w.Write(LEVEL_1, "------------\t----------\t---------------\t-------------\n") + w.Write(LEVEL_0, "Allocated resources:\n (Total limits may be over 100 percent, i.e., overcommitted.)\n") + w.Write(LEVEL_1, "Resource\tRequests\tLimits\n") + w.Write(LEVEL_1, "--------\t--------\t------\n") reqs, limits := getPodsTotalRequestsAndLimits(nodeNonTerminatedPodsList) cpuReqs, cpuLimits, memoryReqs, memoryLimits := reqs[api.ResourceCPU], limits[api.ResourceCPU], reqs[api.ResourceMemory], limits[api.ResourceMemory] fractionCpuReqs := float64(0) @@ -2989,9 +3020,21 @@ func describeNodeResource(nodeNonTerminatedPodsList *api.PodList, node *api.Node fractionMemoryReqs = float64(memoryReqs.Value()) / float64(allocatable.Memory().Value()) * 100 fractionMemoryLimits = float64(memoryLimits.Value()) / float64(allocatable.Memory().Value()) * 100 } - w.Write(LEVEL_1, "%s (%d%%)\t%s (%d%%)\t%s (%d%%)\t%s (%d%%)\n", - cpuReqs.String(), int64(fractionCpuReqs), cpuLimits.String(), int64(fractionCpuLimits), - memoryReqs.String(), int64(fractionMemoryReqs), memoryLimits.String(), int64(fractionMemoryLimits)) + w.Write(LEVEL_1, "%s\t%s (%d%%)\t%s (%d%%)\n", + api.ResourceCPU, cpuReqs.String(), int64(fractionCpuReqs), cpuLimits.String(), int64(fractionCpuLimits)) + w.Write(LEVEL_1, "%s\t%s (%d%%)\t%s (%d%%)\n", + api.ResourceMemory, memoryReqs.String(), int64(fractionMemoryReqs), memoryLimits.String(), int64(fractionMemoryLimits)) + extResources := make([]string, 0, len(allocatable)) + for resource := range allocatable { + if !helper.IsStandardContainerResourceName(string(resource)) && resource != api.ResourcePods { + extResources = append(extResources, string(resource)) + } + } + sort.Strings(extResources) + for _, ext := range extResources { + extRequests, extLimits := reqs[api.ResourceName(ext)], limits[api.ResourceName(ext)] + w.Write(LEVEL_1, "%s\t%s\t%s\n", ext, extRequests.String(), extLimits.String()) + } } func getPodsTotalRequestsAndLimits(podList *api.PodList) (reqs map[api.ResourceName]resource.Quantity, limits map[api.ResourceName]resource.Quantity) { @@ -3047,11 +3090,11 @@ func DescribeEvents(el *api.EventList, w PrefixWriter) { // DeploymentDescriber generates information about a deployment. type DeploymentDescriber struct { clientset.Interface - extensionV1beta1Client clientextensionsv1beta1.ExtensionsV1beta1Interface + external externalclient.Interface } func (dd *DeploymentDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { - d, err := dd.extensionV1beta1Client.Deployments(namespace).Get(name, metav1.GetOptions{}) + d, err := dd.external.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{}) if err != nil { return "", err } @@ -3072,7 +3115,7 @@ func (dd *DeploymentDescriber) Describe(namespace, name string, describerSetting return describeDeployment(d, selector, internalDeployment, events, dd) } -func describeDeployment(d *versionedextension.Deployment, selector labels.Selector, internalDeployment *extensions.Deployment, events *api.EventList, dd *DeploymentDescriber) (string, error) { +func describeDeployment(d *appsv1.Deployment, selector labels.Selector, internalDeployment *extensions.Deployment, events *api.EventList, dd *DeploymentDescriber) (string, error) { return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) w.Write(LEVEL_0, "Name:\t%s\n", d.ObjectMeta.Name) @@ -3096,10 +3139,10 @@ func describeDeployment(d *versionedextension.Deployment, selector labels.Select w.Write(LEVEL_1, "%v \t%v\t%v\n", c.Type, c.Status, c.Reason) } } - oldRSs, _, newRS, err := deploymentutil.GetAllReplicaSets(d, dd.extensionV1beta1Client) + oldRSs, _, newRS, err := deploymentutil.GetAllReplicaSets(d, dd.external.AppsV1()) if err == nil { w.Write(LEVEL_0, "OldReplicaSets:\t%s\n", printReplicaSetsByLabels(oldRSs)) - var newRSs []*versionedextension.ReplicaSet + var newRSs []*appsv1.ReplicaSet if newRS != nil { newRSs = append(newRSs, newRS) } @@ -3113,7 +3156,7 @@ func describeDeployment(d *versionedextension.Deployment, selector labels.Select }) } -func printReplicaSetsByLabels(matchingRSs []*versionedextension.ReplicaSet) string { +func printReplicaSetsByLabels(matchingRSs []*appsv1.ReplicaSet) string { // Format the matching ReplicaSets into strings. rsStrings := make([]string, 0, len(matchingRSs)) for _, rs := range matchingRSs { @@ -3258,15 +3301,18 @@ func printNetworkPolicySpecIngressFrom(npirs []networking.NetworkPolicyIngressRu w.Write(LEVEL_0, "%s%s\n", initialIndent, "From: (traffic not restricted by source)") } else { for _, from := range npir.From { - w.Write(LEVEL_0, "%s", initialIndent) - if from.PodSelector != nil { - w.Write(LEVEL_0, "%s: %s\n", "From PodSelector", metav1.FormatLabelSelector(from.PodSelector)) + w.Write(LEVEL_0, "%s%s\n", initialIndent, "From:") + if from.PodSelector != nil && from.NamespaceSelector != nil { + w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "NamespaceSelector", metav1.FormatLabelSelector(from.NamespaceSelector)) + w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "PodSelector", metav1.FormatLabelSelector(from.PodSelector)) + } else if from.PodSelector != nil { + w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "PodSelector", metav1.FormatLabelSelector(from.PodSelector)) } else if from.NamespaceSelector != nil { - w.Write(LEVEL_0, "%s: %s\n", "From NamespaceSelector", metav1.FormatLabelSelector(from.NamespaceSelector)) + w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "NamespaceSelector", metav1.FormatLabelSelector(from.NamespaceSelector)) } else if from.IPBlock != nil { - w.Write(LEVEL_0, "From IPBlock:\n") - w.Write(LEVEL_0, "%s%sCIDR: %s\n", initialIndent, initialIndent, from.IPBlock.CIDR) - w.Write(LEVEL_0, "%s%sExcept: %v\n", initialIndent, initialIndent, strings.Join(from.IPBlock.Except, ", ")) + w.Write(LEVEL_1, "%sIPBlock:\n", initialIndent) + w.Write(LEVEL_2, "%sCIDR: %s\n", initialIndent, from.IPBlock.CIDR) + w.Write(LEVEL_2, "%sExcept: %v\n", initialIndent, strings.Join(from.IPBlock.Except, ", ")) } } } @@ -3299,15 +3345,18 @@ func printNetworkPolicySpecEgressTo(npers []networking.NetworkPolicyEgressRule, w.Write(LEVEL_0, "%s%s\n", initialIndent, "To: (traffic not restricted by source)") } else { for _, to := range nper.To { - w.Write(LEVEL_0, "%s", initialIndent) - if to.PodSelector != nil { - w.Write(LEVEL_0, "%s: %s\n", "To PodSelector", metav1.FormatLabelSelector(to.PodSelector)) + w.Write(LEVEL_0, "%s%s\n", initialIndent, "To:") + if to.PodSelector != nil && to.NamespaceSelector != nil { + w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "NamespaceSelector", metav1.FormatLabelSelector(to.NamespaceSelector)) + w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "PodSelector", metav1.FormatLabelSelector(to.PodSelector)) + } else if to.PodSelector != nil { + w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "PodSelector", metav1.FormatLabelSelector(to.PodSelector)) } else if to.NamespaceSelector != nil { - w.Write(LEVEL_0, "%s: %s\n", "To NamespaceSelector", metav1.FormatLabelSelector(to.NamespaceSelector)) + w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "NamespaceSelector", metav1.FormatLabelSelector(to.NamespaceSelector)) } else if to.IPBlock != nil { - w.Write(LEVEL_0, "To IPBlock:\n") - w.Write(LEVEL_0, "%s%sCIDR: %s\n", initialIndent, initialIndent, to.IPBlock.CIDR) - w.Write(LEVEL_0, "%s%sExcept: %v\n", initialIndent, initialIndent, strings.Join(to.IPBlock.Except, ", ")) + w.Write(LEVEL_1, "%sIPBlock:\n", initialIndent) + w.Write(LEVEL_2, "%sCIDR: %s\n", initialIndent, to.IPBlock.CIDR) + w.Write(LEVEL_2, "%sExcept: %v\n", initialIndent, strings.Join(to.IPBlock.Except, ", ")) } } } @@ -3456,7 +3505,7 @@ type PodSecurityPolicyDescriber struct { } func (d *PodSecurityPolicyDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { - psp, err := d.Extensions().PodSecurityPolicies().Get(name, metav1.GetOptions{}) + psp, err := d.Policy().PodSecurityPolicies().Get(name, metav1.GetOptions{}) if err != nil { return "", err } @@ -3464,7 +3513,7 @@ func (d *PodSecurityPolicyDescriber) Describe(namespace, name string, describerS return describePodSecurityPolicy(psp) } -func describePodSecurityPolicy(psp *extensions.PodSecurityPolicy) (string, error) { +func describePodSecurityPolicy(psp *policy.PodSecurityPolicy) (string, error) { return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) w.Write(LEVEL_0, "Name:\t%s\n", psp.Name) @@ -3501,13 +3550,13 @@ func describePodSecurityPolicy(psp *extensions.PodSecurityPolicy) (string, error w.Write(LEVEL_2, "Level:\t%s\n", stringOrNone(level)) w.Write(LEVEL_1, "Run As User Strategy: %s\t\n", string(psp.Spec.RunAsUser.Rule)) - w.Write(LEVEL_2, "Ranges:\t%s\n", userIDRangeToString(psp.Spec.RunAsUser.Ranges)) + w.Write(LEVEL_2, "Ranges:\t%s\n", idRangeToString(psp.Spec.RunAsUser.Ranges)) w.Write(LEVEL_1, "FSGroup Strategy: %s\t\n", string(psp.Spec.FSGroup.Rule)) - w.Write(LEVEL_2, "Ranges:\t%s\n", groupIDRangeToString(psp.Spec.FSGroup.Ranges)) + w.Write(LEVEL_2, "Ranges:\t%s\n", idRangeToString(psp.Spec.FSGroup.Ranges)) w.Write(LEVEL_1, "Supplemental Groups Strategy: %s\t\n", string(psp.Spec.SupplementalGroups.Rule)) - w.Write(LEVEL_2, "Ranges:\t%s\n", groupIDRangeToString(psp.Spec.SupplementalGroups.Ranges)) + w.Write(LEVEL_2, "Ranges:\t%s\n", idRangeToString(psp.Spec.SupplementalGroups.Ranges)) return nil }) @@ -3524,7 +3573,7 @@ func stringOrDefaultValue(s, defaultValue string) string { return defaultValue } -func fsTypeToString(volumes []extensions.FSType) string { +func fsTypeToString(volumes []policy.FSType) string { strVolumes := []string{} for _, v := range volumes { strVolumes = append(strVolumes, string(v)) @@ -3532,7 +3581,7 @@ func fsTypeToString(volumes []extensions.FSType) string { return stringOrNone(strings.Join(strVolumes, ",")) } -func flexVolumesToString(flexVolumes []extensions.AllowedFlexVolume) string { +func flexVolumesToString(flexVolumes []policy.AllowedFlexVolume) string { volumes := []string{} for _, flexVolume := range flexVolumes { volumes = append(volumes, "driver="+flexVolume.Driver) @@ -3540,19 +3589,7 @@ func flexVolumesToString(flexVolumes []extensions.AllowedFlexVolume) string { return stringOrDefaultValue(strings.Join(volumes, ","), "") } -func hostPortRangeToString(ranges []extensions.HostPortRange) string { - formattedString := "" - if ranges != nil { - strRanges := []string{} - for _, r := range ranges { - strRanges = append(strRanges, fmt.Sprintf("%d-%d", r.Min, r.Max)) - } - formattedString = strings.Join(strRanges, ",") - } - return stringOrNone(formattedString) -} - -func userIDRangeToString(ranges []extensions.UserIDRange) string { +func hostPortRangeToString(ranges []policy.HostPortRange) string { formattedString := "" if ranges != nil { strRanges := []string{} @@ -3564,7 +3601,7 @@ func userIDRangeToString(ranges []extensions.UserIDRange) string { return stringOrNone(formattedString) } -func groupIDRangeToString(ranges []extensions.GroupIDRange) string { +func idRangeToString(ranges []policy.IDRange) string { formattedString := "" if ranges != nil { strRanges := []string{} @@ -3794,23 +3831,19 @@ func printTaintsMultilineWithIndent(w PrefixWriter, initialIndent, title, innerI } // to print taints in the sorted order - keys := make([]string, 0, len(taints)) - for _, taint := range taints { - keys = append(keys, string(taint.Effect)+","+taint.Key) - } - sort.Strings(keys) + sort.Slice(taints, func(i, j int) bool { + cmpKey := func(taint api.Taint) string { + return string(taint.Effect) + "," + taint.Key + } + return cmpKey(taints[i]) < cmpKey(taints[j]) + }) - for i, key := range keys { - for _, taint := range taints { - if string(taint.Effect)+","+taint.Key == key { - if i != 0 { - w.Write(LEVEL_0, "%s", initialIndent) - w.Write(LEVEL_0, "%s", innerIndent) - } - w.Write(LEVEL_0, "%s\n", taint.ToString()) - i++ - } + for i, taint := range taints { + if i != 0 { + w.Write(LEVEL_0, "%s", initialIndent) + w.Write(LEVEL_0, "%s", innerIndent) } + w.Write(LEVEL_0, "%s\n", taint.ToString()) } } @@ -3829,33 +3862,26 @@ func printTolerationsMultilineWithIndent(w PrefixWriter, initialIndent, title, i } // to print tolerations in the sorted order - keys := make([]string, 0, len(tolerations)) - for _, toleration := range tolerations { - keys = append(keys, toleration.Key) - } - sort.Strings(keys) + sort.Slice(tolerations, func(i, j int) bool { + return tolerations[i].Key < tolerations[j].Key + }) - for i, key := range keys { - for _, toleration := range tolerations { - if toleration.Key == key { - if i != 0 { - w.Write(LEVEL_0, "%s", initialIndent) - w.Write(LEVEL_0, "%s", innerIndent) - } - w.Write(LEVEL_0, "%s", toleration.Key) - if len(toleration.Value) != 0 { - w.Write(LEVEL_0, "=%s", toleration.Value) - } - if len(toleration.Effect) != 0 { - w.Write(LEVEL_0, ":%s", toleration.Effect) - } - if toleration.TolerationSeconds != nil { - w.Write(LEVEL_0, " for %ds", *toleration.TolerationSeconds) - } - w.Write(LEVEL_0, "\n") - i++ - } + for i, toleration := range tolerations { + if i != 0 { + w.Write(LEVEL_0, "%s", initialIndent) + w.Write(LEVEL_0, "%s", innerIndent) + } + w.Write(LEVEL_0, "%s", toleration.Key) + if len(toleration.Value) != 0 { + w.Write(LEVEL_0, "=%s", toleration.Value) + } + if len(toleration.Effect) != 0 { + w.Write(LEVEL_0, ":%s", toleration.Effect) } + if toleration.TolerationSeconds != nil { + w.Write(LEVEL_0, " for %ds", *toleration.TolerationSeconds) + } + w.Write(LEVEL_0, "\n") } } @@ -3944,14 +3970,6 @@ func (list SortableVolumeDevices) Less(i, j int) bool { return list[i].DevicePath < list[j].DevicePath } -// TODO: get rid of this and plumb the caller correctly -func versionedExtensionsClientV1beta1(internalClient clientset.Interface) clientextensionsv1beta1.ExtensionsV1beta1Interface { - if internalClient == nil { - return &clientextensionsv1beta1.ExtensionsV1beta1Client{} - } - return clientextensionsv1beta1.New(internalClient.Extensions().RESTClient()) -} - var maxAnnotationLen = 200 // printAnnotationsMultilineWithFilter prints filtered multiple annotations with a proper alignment. diff --git a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/describe_test.go b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/describe_test.go index 491937144..284ece579 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/describe_test.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/describe_test.go @@ -25,14 +25,15 @@ import ( "testing" "time" + appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/intstr" versionedfake "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/autoscaling" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/extensions" @@ -282,10 +283,12 @@ func getResourceList(cpu, memory string) api.ResourceList { func TestDescribeService(t *testing.T) { testCases := []struct { + name string service *api.Service expect []string }{ { + name: "test1", service: &api.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", @@ -323,6 +326,7 @@ func TestDescribeService(t *testing.T) { }, }, { + name: "test2", service: &api.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", @@ -361,18 +365,20 @@ func TestDescribeService(t *testing.T) { }, } for _, testCase := range testCases { - fake := fake.NewSimpleClientset(testCase.service) - c := &describeClient{T: t, Namespace: "foo", Interface: fake} - d := ServiceDescriber{c} - out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - for _, expected := range testCase.expect { - if !strings.Contains(out, expected) { - t.Errorf("expected to find %q in output: %q", expected, out) + t.Run(testCase.name, func(t *testing.T) { + fake := fake.NewSimpleClientset(testCase.service) + c := &describeClient{T: t, Namespace: "foo", Interface: fake} + d := ServiceDescriber{c} + out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) + if err != nil { + t.Errorf("unexpected error: %v", err) } - } + for _, expected := range testCase.expect { + if !strings.Contains(out, expected) { + t.Errorf("expected to find %q in output: %q", expected, out) + } + } + }) } } @@ -452,12 +458,14 @@ func VerifyDatesInOrder( func TestDescribeContainers(t *testing.T) { trueVal := true testCases := []struct { + name string container api.Container status api.ContainerStatus expectedElements []string }{ // Running state. { + name: "test1", container: api.Container{Name: "test", Image: "image"}, status: api.ContainerStatus{ Name: "test", @@ -473,6 +481,7 @@ func TestDescribeContainers(t *testing.T) { }, // Waiting state. { + name: "test2", container: api.Container{Name: "test", Image: "image"}, status: api.ContainerStatus{ Name: "test", @@ -488,6 +497,7 @@ func TestDescribeContainers(t *testing.T) { }, // Terminated state. { + name: "test3", container: api.Container{Name: "test", Image: "image"}, status: api.ContainerStatus{ Name: "test", @@ -506,6 +516,7 @@ func TestDescribeContainers(t *testing.T) { }, // Last Terminated { + name: "test4", container: api.Container{Name: "test", Image: "image"}, status: api.ContainerStatus{ Name: "test", @@ -529,6 +540,7 @@ func TestDescribeContainers(t *testing.T) { }, // No state defaults to waiting. { + name: "test5", container: api.Container{Name: "test", Image: "image"}, status: api.ContainerStatus{ Name: "test", @@ -539,6 +551,7 @@ func TestDescribeContainers(t *testing.T) { }, // Env { + name: "test6", container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{ConfigMapRef: &api.ConfigMapEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}}, status: api.ContainerStatus{ Name: "test", @@ -548,6 +561,7 @@ func TestDescribeContainers(t *testing.T) { expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap\tOptional: false"}, }, { + name: "test7", container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{Prefix: "p_", ConfigMapRef: &api.ConfigMapEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}}, status: api.ContainerStatus{ Name: "test", @@ -557,6 +571,7 @@ func TestDescribeContainers(t *testing.T) { expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap with prefix 'p_'\tOptional: false"}, }, { + name: "test8", container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{ConfigMapRef: &api.ConfigMapEnvSource{Optional: &trueVal, LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}}, status: api.ContainerStatus{ Name: "test", @@ -566,6 +581,7 @@ func TestDescribeContainers(t *testing.T) { expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap\tOptional: true"}, }, { + name: "test9", container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{SecretRef: &api.SecretEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}, Optional: &trueVal}}}}, status: api.ContainerStatus{ Name: "test", @@ -575,6 +591,7 @@ func TestDescribeContainers(t *testing.T) { expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tSecret\tOptional: true"}, }, { + name: "test10", container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{Prefix: "p_", SecretRef: &api.SecretEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}}, status: api.ContainerStatus{ Name: "test", @@ -585,6 +602,7 @@ func TestDescribeContainers(t *testing.T) { }, // Command { + name: "test11", container: api.Container{Name: "test", Image: "image", Command: []string{"sleep", "1000"}}, status: api.ContainerStatus{ Name: "test", @@ -595,6 +613,7 @@ func TestDescribeContainers(t *testing.T) { }, // Args { + name: "test12", container: api.Container{Name: "test", Image: "image", Args: []string{"time", "1000"}}, status: api.ContainerStatus{ Name: "test", @@ -605,6 +624,7 @@ func TestDescribeContainers(t *testing.T) { }, // Using limits. { + name: "test13", container: api.Container{ Name: "test", Image: "image", @@ -625,6 +645,7 @@ func TestDescribeContainers(t *testing.T) { }, // Using requests. { + name: "test14", container: api.Container{ Name: "test", Image: "image", @@ -640,6 +661,7 @@ func TestDescribeContainers(t *testing.T) { }, // volumeMounts read/write { + name: "test15", container: api.Container{ Name: "test", Image: "image", @@ -654,6 +676,7 @@ func TestDescribeContainers(t *testing.T) { }, // volumeMounts readonly { + name: "test16", container: api.Container{ Name: "test", Image: "image", @@ -670,6 +693,7 @@ func TestDescribeContainers(t *testing.T) { // volumeDevices { + name: "test17", container: api.Container{ Name: "test", Image: "image", @@ -685,23 +709,25 @@ func TestDescribeContainers(t *testing.T) { } for i, testCase := range testCases { - out := new(bytes.Buffer) - pod := api.Pod{ - Spec: api.PodSpec{ - Containers: []api.Container{testCase.container}, - }, - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{testCase.status}, - }, - } - writer := NewPrefixWriter(out) - describeContainers("Containers", pod.Spec.Containers, pod.Status.ContainerStatuses, EnvValueRetriever(&pod), writer, "") - output := out.String() - for _, expected := range testCase.expectedElements { - if !strings.Contains(output, expected) { - t.Errorf("Test case %d: expected to find %q in output: %q", i, expected, output) + t.Run(testCase.name, func(t *testing.T) { + out := new(bytes.Buffer) + pod := api.Pod{ + Spec: api.PodSpec{ + Containers: []api.Container{testCase.container}, + }, + Status: api.PodStatus{ + ContainerStatuses: []api.ContainerStatus{testCase.status}, + }, } - } + writer := NewPrefixWriter(out) + describeContainers("Containers", pod.Spec.Containers, pod.Status.ContainerStatuses, EnvValueRetriever(&pod), writer, "") + output := out.String() + for _, expected := range testCase.expectedElements { + if !strings.Contains(output, expected) { + t.Errorf("Test case %d: expected to find %q in output: %q", i, expected, output) + } + } + }) } } @@ -787,10 +813,12 @@ func TestDefaultDescribers(t *testing.T) { func TestGetPodsTotalRequests(t *testing.T) { testCases := []struct { + name string pods *api.PodList expectedReqs map[api.ResourceName]resource.Quantity }{ { + name: "test1", pods: &api.PodList{ Items: []api.Pod{ { @@ -852,10 +880,12 @@ func TestGetPodsTotalRequests(t *testing.T) { } for _, testCase := range testCases { - reqs, _ := getPodsTotalRequestsAndLimits(testCase.pods) - if !apiequality.Semantic.DeepEqual(reqs, testCase.expectedReqs) { - t.Errorf("Expected %v, got %v", testCase.expectedReqs, reqs) - } + t.Run(testCase.name, func(t *testing.T) { + reqs, _ := getPodsTotalRequestsAndLimits(testCase.pods) + if !apiequality.Semantic.DeepEqual(reqs, testCase.expectedReqs) { + t.Errorf("Expected %v, got %v", testCase.expectedReqs, reqs) + } + }) } } @@ -863,12 +893,14 @@ func TestPersistentVolumeDescriber(t *testing.T) { block := api.PersistentVolumeBlock file := api.PersistentVolumeFilesystem testCases := []struct { + name string plugin string pv *api.PersistentVolume expectedElements []string unexpectedElements []string }{ { + name: "test0", plugin: "hostpath", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -881,6 +913,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { unexpectedElements: []string{"VolumeMode", "Filesystem"}, }, { + name: "test1", plugin: "gce", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -894,6 +927,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { expectedElements: []string{"VolumeMode", "Filesystem"}, }, { + name: "test2", plugin: "ebs", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -906,6 +940,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { unexpectedElements: []string{"VolumeMode", "Filesystem"}, }, { + name: "test3", plugin: "nfs", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -918,6 +953,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { unexpectedElements: []string{"VolumeMode", "Filesystem"}, }, { + name: "test4", plugin: "iscsi", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -931,6 +967,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { expectedElements: []string{"VolumeMode", "Block"}, }, { + name: "test5", plugin: "gluster", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -943,6 +980,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { unexpectedElements: []string{"VolumeMode", "Filesystem"}, }, { + name: "test6", plugin: "rbd", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -955,6 +993,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { unexpectedElements: []string{"VolumeMode", "Filesystem"}, }, { + name: "test7", plugin: "quobyte", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -967,18 +1006,20 @@ func TestPersistentVolumeDescriber(t *testing.T) { unexpectedElements: []string{"VolumeMode", "Filesystem"}, }, { + name: "test8", plugin: "cinder", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, Spec: api.PersistentVolumeSpec{ PersistentVolumeSource: api.PersistentVolumeSource{ - Cinder: &api.CinderVolumeSource{}, + Cinder: &api.CinderPersistentVolumeSource{}, }, }, }, unexpectedElements: []string{"VolumeMode", "Filesystem"}, }, { + name: "test9", plugin: "fc", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -992,6 +1033,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { expectedElements: []string{"VolumeMode", "Block"}, }, { + name: "test10", plugin: "local", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -1005,6 +1047,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { unexpectedElements: []string{"Required Terms", "Term "}, }, { + name: "test11", plugin: "local", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -1019,6 +1062,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { unexpectedElements: []string{"Required Terms", "Term "}, }, { + name: "test12", plugin: "local", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -1035,6 +1079,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { unexpectedElements: []string{"Term "}, }, { + name: "test13", plugin: "local", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -1059,6 +1104,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { expectedElements: []string{"Node Affinity", "Required Terms", "Term 0", "Term 1"}, }, { + name: "test14", plugin: "local", pv: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{Name: "bar"}, @@ -1094,25 +1140,27 @@ func TestPersistentVolumeDescriber(t *testing.T) { } for _, test := range testCases { - fake := fake.NewSimpleClientset(test.pv) - c := PersistentVolumeDescriber{fake} - str, err := c.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("Unexpected error for test %s: %v", test.plugin, err) - } - if str == "" { - t.Errorf("Unexpected empty string for test %s. Expected PV Describer output", test.plugin) - } - for _, expected := range test.expectedElements { - if !strings.Contains(str, expected) { - t.Errorf("expected to find %q in output: %q", expected, str) + t.Run(test.name, func(t *testing.T) { + fake := fake.NewSimpleClientset(test.pv) + c := PersistentVolumeDescriber{fake} + str, err := c.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) + if err != nil { + t.Errorf("Unexpected error for test %s: %v", test.plugin, err) } - } - for _, unexpected := range test.unexpectedElements { - if strings.Contains(str, unexpected) { - t.Errorf("unexpected to find %q in output: %q", unexpected, str) + if str == "" { + t.Errorf("Unexpected empty string for test %s. Expected PV Describer output", test.plugin) } - } + for _, expected := range test.expectedElements { + if !strings.Contains(str, expected) { + t.Errorf("expected to find %q in output: %q", expected, str) + } + } + for _, unexpected := range test.unexpectedElements { + if strings.Contains(str, unexpected) { + t.Errorf("unexpected to find %q in output: %q", unexpected, str) + } + } + }) } } @@ -1120,6 +1168,7 @@ func TestPersistentVolumeClaimDescriber(t *testing.T) { block := api.PersistentVolumeBlock file := api.PersistentVolumeFilesystem goldClassName := "gold" + now := time.Now() testCases := []struct { name string pvc *api.PersistentVolumeClaim @@ -1170,39 +1219,138 @@ func TestPersistentVolumeClaimDescriber(t *testing.T) { }, expectedElements: []string{"VolumeMode", "Block"}, }, + // Tests for Status.Condition. + { + name: "condition-type", + pvc: &api.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"}, + Spec: api.PersistentVolumeClaimSpec{ + VolumeName: "volume4", + StorageClassName: &goldClassName, + }, + Status: api.PersistentVolumeClaimStatus{ + Conditions: []api.PersistentVolumeClaimCondition{ + {Type: api.PersistentVolumeClaimResizing}, + }, + }, + }, + expectedElements: []string{"Conditions", "Type", "Resizing"}, + }, + { + name: "condition-status", + pvc: &api.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"}, + Spec: api.PersistentVolumeClaimSpec{ + VolumeName: "volume5", + StorageClassName: &goldClassName, + }, + Status: api.PersistentVolumeClaimStatus{ + Conditions: []api.PersistentVolumeClaimCondition{ + {Status: api.ConditionTrue}, + }, + }, + }, + expectedElements: []string{"Conditions", "Status", "True"}, + }, + { + name: "condition-last-probe-time", + pvc: &api.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"}, + Spec: api.PersistentVolumeClaimSpec{ + VolumeName: "volume6", + StorageClassName: &goldClassName, + }, + Status: api.PersistentVolumeClaimStatus{ + Conditions: []api.PersistentVolumeClaimCondition{ + {LastProbeTime: metav1.Time{Time: now}}, + }, + }, + }, + expectedElements: []string{"Conditions", "LastProbeTime", now.Format(time.RFC1123Z)}, + }, + { + name: "condition-last-transition-time", + pvc: &api.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"}, + Spec: api.PersistentVolumeClaimSpec{ + VolumeName: "volume7", + StorageClassName: &goldClassName, + }, + Status: api.PersistentVolumeClaimStatus{ + Conditions: []api.PersistentVolumeClaimCondition{ + {LastTransitionTime: metav1.Time{Time: now}}, + }, + }, + }, + expectedElements: []string{"Conditions", "LastTransitionTime", now.Format(time.RFC1123Z)}, + }, + { + name: "condition-reason", + pvc: &api.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"}, + Spec: api.PersistentVolumeClaimSpec{ + VolumeName: "volume8", + StorageClassName: &goldClassName, + }, + Status: api.PersistentVolumeClaimStatus{ + Conditions: []api.PersistentVolumeClaimCondition{ + {Reason: "OfflineResize"}, + }, + }, + }, + expectedElements: []string{"Conditions", "Reason", "OfflineResize"}, + }, + { + name: "condition-message", + pvc: &api.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"}, + Spec: api.PersistentVolumeClaimSpec{ + VolumeName: "volume9", + StorageClassName: &goldClassName, + }, + Status: api.PersistentVolumeClaimStatus{ + Conditions: []api.PersistentVolumeClaimCondition{ + {Message: "User request resize"}, + }, + }, + }, + expectedElements: []string{"Conditions", "Message", "User request resize"}, + }, } for _, test := range testCases { - fake := fake.NewSimpleClientset(test.pvc) - c := PersistentVolumeClaimDescriber{fake} - str, err := c.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("Unexpected error for test %s: %v", test.name, err) - } - if str == "" { - t.Errorf("Unexpected empty string for test %s. Expected PVC Describer output", test.name) - } - for _, expected := range test.expectedElements { - if !strings.Contains(str, expected) { - t.Errorf("expected to find %q in output: %q", expected, str) + t.Run(test.name, func(t *testing.T) { + fake := fake.NewSimpleClientset(test.pvc) + c := PersistentVolumeClaimDescriber{fake} + str, err := c.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) + if err != nil { + t.Errorf("Unexpected error for test %s: %v", test.name, err) } - } - for _, unexpected := range test.unexpectedElements { - if strings.Contains(str, unexpected) { - t.Errorf("unexpected to find %q in output: %q", unexpected, str) + if str == "" { + t.Errorf("Unexpected empty string for test %s. Expected PVC Describer output", test.name) } - } + for _, expected := range test.expectedElements { + if !strings.Contains(str, expected) { + t.Errorf("expected to find %q in output: %q", expected, str) + } + } + for _, unexpected := range test.unexpectedElements { + if strings.Contains(str, unexpected) { + t.Errorf("unexpected to find %q in output: %q", unexpected, str) + } + } + }) } } func TestDescribeDeployment(t *testing.T) { fake := fake.NewSimpleClientset() - versionedFake := versionedfake.NewSimpleClientset(&v1beta1.Deployment{ + versionedFake := versionedfake.NewSimpleClientset(&appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "foo", }, - Spec: v1beta1.DeploymentSpec{ + Spec: appsv1.DeploymentSpec{ Replicas: utilpointer.Int32Ptr(1), Selector: &metav1.LabelSelector{}, Template: v1.PodTemplateSpec{ @@ -1214,7 +1362,7 @@ func TestDescribeDeployment(t *testing.T) { }, }, }) - d := DeploymentDescriber{fake, versionedFake.ExtensionsV1beta1()} + d := DeploymentDescriber{fake, versionedFake} out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) if err != nil { t.Errorf("unexpected error: %v", err) @@ -1781,20 +1929,22 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) { } for _, test := range tests { - test.hpa.ObjectMeta = metav1.ObjectMeta{ - Name: "bar", - Namespace: "foo", - } - fake := fake.NewSimpleClientset(&test.hpa) - desc := HorizontalPodAutoscalerDescriber{fake} - str, err := desc.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("Unexpected error for test %s: %v", test.name, err) - } - if str == "" { - t.Errorf("Unexpected empty string for test %s. Expected HPA Describer output", test.name) - } - t.Logf("Description for %q:\n%s", test.name, str) + t.Run(test.name, func(t *testing.T) { + test.hpa.ObjectMeta = metav1.ObjectMeta{ + Name: "bar", + Namespace: "foo", + } + fake := fake.NewSimpleClientset(&test.hpa) + desc := HorizontalPodAutoscalerDescriber{fake} + str, err := desc.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) + if err != nil { + t.Errorf("Unexpected error for test %s: %v", test.name, err) + } + if str == "" { + t.Errorf("Unexpected empty string for test %s. Expected HPA Describer output", test.name) + } + t.Logf("Description for %q:\n%s", test.name, str) + }) } } @@ -1827,16 +1977,16 @@ func TestDescribeEvents(t *testing.T) { }, "DeploymentDescriber": &DeploymentDescriber{ fake.NewSimpleClientset(events), - versionedfake.NewSimpleClientset(&v1beta1.Deployment{ + versionedfake.NewSimpleClientset(&appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "foo", }, - Spec: v1beta1.DeploymentSpec{ + Spec: appsv1.DeploymentSpec{ Replicas: utilpointer.Int32Ptr(1), Selector: &metav1.LabelSelector{}, }, - }).ExtensionsV1beta1(), + }), }, "EndpointsDescriber": &EndpointsDescriber{ fake.NewSimpleClientset(&api.Endpoints{ @@ -1924,27 +2074,29 @@ func TestDescribeEvents(t *testing.T) { } for name, d := range m { - out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("unexpected error for %q: %v", name, err) - } - if !strings.Contains(out, "bar") { - t.Errorf("unexpected out for %q: %s", name, out) - } - if !strings.Contains(out, "Events:") { - t.Errorf("events not found for %q when ShowEvents=true: %s", name, out) - } + t.Run(name, func(t *testing.T) { + out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) + if err != nil { + t.Errorf("unexpected error for %q: %v", name, err) + } + if !strings.Contains(out, "bar") { + t.Errorf("unexpected out for %q: %s", name, out) + } + if !strings.Contains(out, "Events:") { + t.Errorf("events not found for %q when ShowEvents=true: %s", name, out) + } - out, err = d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: false}) - if err != nil { - t.Errorf("unexpected error for %q: %s", name, err) - } - if !strings.Contains(out, "bar") { - t.Errorf("unexpected out for %q: %s", name, out) - } - if strings.Contains(out, "Events:") { - t.Errorf("events found for %q when ShowEvents=false: %s", name, out) - } + out, err = d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: false}) + if err != nil { + t.Errorf("unexpected error for %q: %s", name, err) + } + if !strings.Contains(out, "bar") { + t.Errorf("unexpected out for %q: %s", name, out) + } + if strings.Contains(out, "Events:") { + t.Errorf("events found for %q when ShowEvents=false: %s", name, out) + } + }) } } @@ -1972,13 +2124,15 @@ func TestPrintLabelsMultiline(t *testing.T) { }, } for i, testCase := range testCases { - out := new(bytes.Buffer) - writer := NewPrefixWriter(out) - printAnnotationsMultiline(writer, "Annotations", testCase.annotations) - output := out.String() - if output != testCase.expectPrint { - t.Errorf("Test case %d: expected to find %q in output: %q", i, testCase.expectPrint, output) - } + t.Run(testCase.expectPrint, func(t *testing.T) { + out := new(bytes.Buffer) + writer := NewPrefixWriter(out) + printAnnotationsMultiline(writer, "Annotations", testCase.annotations) + output := out.String() + if output != testCase.expectPrint { + t.Errorf("Test case %d: expected to find %q in output: %q", i, testCase.expectPrint, output) + } + }) } } @@ -2089,22 +2243,22 @@ func TestDescribePodSecurityPolicy(t *testing.T) { "Supplemental Groups Strategy: RunAsAny", } - fake := fake.NewSimpleClientset(&extensions.PodSecurityPolicy{ + fake := fake.NewSimpleClientset(&policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "mypsp", }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, }) @@ -2177,10 +2331,17 @@ Spec: Allowing ingress traffic: To Port: 80/TCP To Port: 82/TCP - From PodSelector: id=app2,id2=app3 - From NamespaceSelector: id=app2,id2=app3 - From NamespaceSelector: foo in (bar1,bar2),id=app2,id2=app3 - From IPBlock: + From: + NamespaceSelector: id=ns1,id2=ns2 + PodSelector: id=pod1,id2=pod2 + From: + PodSelector: id=app2,id2=app3 + From: + NamespaceSelector: id=app2,id2=app3 + From: + NamespaceSelector: foo in (bar1,bar2),id=app2,id2=app3 + From: + IPBlock: CIDR: 192.168.0.0/16 Except: 192.168.3.0/24, 192.168.4.0/24 ---------- @@ -2189,10 +2350,17 @@ Spec: Allowing egress traffic: To Port: 80/TCP To Port: 82/TCP - To PodSelector: id=app2,id2=app3 - To NamespaceSelector: id=app2,id2=app3 - To NamespaceSelector: foo in (bar1,bar2),id=app2,id2=app3 - To IPBlock: + To: + NamespaceSelector: id=ns1,id2=ns2 + PodSelector: id=pod1,id2=pod2 + To: + PodSelector: id=app2,id2=app3 + To: + NamespaceSelector: id=app2,id2=app3 + To: + NamespaceSelector: foo in (bar1,bar2),id=app2,id2=app3 + To: + IPBlock: CIDR: 192.168.0.0/16 Except: 192.168.3.0/24, 192.168.4.0/24 ---------- @@ -2229,6 +2397,20 @@ Spec: {Port: &port82, Protocol: &protoTCP}, }, From: []networking.NetworkPolicyPeer{ + { + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "id": "pod1", + "id2": "pod2", + }, + }, + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "id": "ns1", + "id2": "ns2", + }, + }, + }, { PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{ @@ -2273,6 +2455,20 @@ Spec: {Port: &port82, Protocol: &protoTCP}, }, To: []networking.NetworkPolicyPeer{ + { + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "id": "pod1", + "id2": "pod2", + }, + }, + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "id": "ns1", + "id2": "ns2", + }, + }, + }, { PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{ @@ -2386,6 +2582,46 @@ func TestDescribeNode(t *testing.T) { } +func TestDescribeStatefulSet(t *testing.T) { + fake := fake.NewSimpleClientset(&apps.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + Namespace: "foo", + }, + Spec: apps.StatefulSetSpec{ + Replicas: 1, + Selector: &metav1.LabelSelector{}, + Template: api.PodTemplateSpec{ + Spec: api.PodSpec{ + Containers: []api.Container{ + {Image: "mytest-image:latest"}, + }, + }, + }, + UpdateStrategy: apps.StatefulSetUpdateStrategy{ + Type: apps.RollingUpdateStatefulSetStrategyType, + RollingUpdate: &apps.RollingUpdateStatefulSetStrategy{ + Partition: 2, + }, + }, + }, + }) + d := StatefulSetDescriber{fake} + out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + expectedOutputs := []string{ + "bar", "foo", "Containers:", "mytest-image:latest", "Update Strategy", "RollingUpdate", "Partition", + } + for _, o := range expectedOutputs { + if !strings.Contains(out, o) { + t.Errorf("unexpected out: %s", out) + break + } + } +} + // boolPtr returns a pointer to a bool func boolPtr(b bool) *bool { o := b diff --git a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/printers.go b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/printers.go index 3941ebf0c..1f3473d9c 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/printers.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/printers.go @@ -82,6 +82,7 @@ func AddHandlers(h printers.PrintHandler) { {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, {Name: "IP", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["podIP"]}, {Name: "Node", Type: "string", Priority: 1, Description: apiv1.PodSpec{}.SwaggerDoc()["nodeName"]}, + {Name: "Nominated Node", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["nominatedNodeName"]}, } h.TableHandler(podColumnDefinitions, printPodList) h.TableHandler(podColumnDefinitions, printPod) @@ -221,6 +222,7 @@ func AddHandlers(h printers.PrintHandler) { {Name: "Roles", Type: "string", Description: "The roles of the node"}, {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, {Name: "Version", Type: "string", Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["kubeletVersion"]}, + {Name: "Internal-IP", Type: "string", Priority: 1, Description: apiv1.NodeStatus{}.SwaggerDoc()["addresses"]}, {Name: "External-IP", Type: "string", Priority: 1, Description: apiv1.NodeStatus{}.SwaggerDoc()["addresses"]}, {Name: "OS-Image", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["osImage"]}, {Name: "Kernel-Version", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["kernelVersion"]}, @@ -341,7 +343,7 @@ func AddHandlers(h printers.PrintHandler) { podSecurityPolicyColumnDefinitions := []metav1beta1.TableColumnDefinition{ {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, - {Name: "Data", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["privileged"]}, + {Name: "Priv", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["privileged"]}, {Name: "Caps", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["allowedCapabilities"]}, {Name: "SELinux", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["seLinux"]}, {Name: "RunAsUser", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["runAsUser"]}, @@ -502,7 +504,8 @@ func translateTimestamp(timestamp metav1.Time) string { if timestamp.IsZero() { return "" } - return duration.ShortHumanDuration(time.Now().Sub(timestamp.Time)) + + return duration.ShortHumanDuration(time.Since(timestamp.Time)) } var ( @@ -573,6 +576,7 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR } if !initializing { restarts = 0 + hasRunning := false for i := len(pod.Status.ContainerStatuses) - 1; i >= 0; i-- { container := pod.Status.ContainerStatuses[i] @@ -588,9 +592,15 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR reason = fmt.Sprintf("ExitCode:%d", container.State.Terminated.ExitCode) } } else if container.Ready && container.State.Running != nil { + hasRunning = true readyContainers++ } } + + // change pod status back to "Running" if there is at least one container still reporting as "Running" status + if reason == "Completed" && hasRunning { + reason = "Running" + } } if pod.DeletionTimestamp != nil && pod.Status.Reason == node.NodeUnreachablePodReason { @@ -599,10 +609,11 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR reason = "Terminating" } - row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, restarts, translateTimestamp(pod.CreationTimestamp)) + row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, int64(restarts), translateTimestamp(pod.CreationTimestamp)) if options.Wide { nodeName := pod.Spec.NodeName + nominatedNodeName := pod.Status.NominatedNodeName podIP := pod.Status.PodIP if podIP == "" { podIP = "" @@ -610,10 +621,10 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR if nodeName == "" { nodeName = "" } - row.Cells = append(row.Cells, podIP, nodeName) - if len(pod.Status.NominatedNodeName) > 0 { - row.Cells = append(row.Cells, pod.Status.NominatedNodeName) + if nominatedNodeName == "" { + nominatedNodeName = "" } + row.Cells = append(row.Cells, podIP, nodeName, nominatedNodeName) } return []metav1beta1.TableRow{row}, nil @@ -659,7 +670,7 @@ func printPodDisruptionBudget(obj *policy.PodDisruptionBudget, options printers. maxUnavailable = "N/A" } - row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, obj.Status.PodDisruptionsAllowed, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, int64(obj.Status.PodDisruptionsAllowed), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } @@ -685,7 +696,7 @@ func printReplicationController(obj *api.ReplicationController, options printers currentReplicas := obj.Status.Replicas readyReplicas := obj.Status.ReadyReplicas - row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, readyReplicas, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, labels.FormatLabels(obj.Spec.Selector)) @@ -714,7 +725,7 @@ func printReplicaSet(obj *extensions.ReplicaSet, options printers.PrintOptions) currentReplicas := obj.Status.Replicas readyReplicas := obj.Status.ReadyReplicas - row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, readyReplicas, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) @@ -746,7 +757,7 @@ func printJob(obj *batch.Job, options printers.PrintOptions) ([]metav1beta1.Tabl completions = "" } - row.Cells = append(row.Cells, obj.Name, completions, obj.Status.Succeeded, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, completions, int64(obj.Status.Succeeded), translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) @@ -776,7 +787,7 @@ func printCronJob(obj *batch.CronJob, options printers.PrintOptions) ([]metav1be lastScheduleTime = translateTimestamp(*obj.Status.LastScheduleTime) } - row.Cells = append(row.Cells, obj.Name, obj.Spec.Schedule, printBoolPtr(obj.Spec.Suspend), len(obj.Status.Active), lastScheduleTime, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, obj.Spec.Schedule, printBoolPtr(obj.Spec.Suspend), int64(len(obj.Status.Active)), lastScheduleTime, translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.JobTemplate.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.JobTemplate.Spec.Selector)) @@ -963,7 +974,7 @@ func printStatefulSet(obj *apps.StatefulSet, options printers.PrintOptions) ([]m desiredReplicas := obj.Spec.Replicas currentReplicas := obj.Status.Replicas createTime := translateTimestamp(obj.CreationTimestamp) - row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, createTime) + row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), createTime) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images) @@ -994,7 +1005,7 @@ func printDaemonSet(obj *extensions.DaemonSet, options printers.PrintOptions) ([ numberUpdated := obj.Status.UpdatedNumberScheduled numberAvailable := obj.Status.NumberAvailable - row.Cells = append(row.Cells, obj.Name, desiredScheduled, currentScheduled, numberReady, numberUpdated, numberAvailable, labels.FormatLabels(obj.Spec.Template.Spec.NodeSelector), translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(desiredScheduled), int64(currentScheduled), int64(numberReady), int64(numberUpdated), int64(numberAvailable), labels.FormatLabels(obj.Spec.Template.Spec.NodeSelector), translateTimestamp(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) @@ -1058,7 +1069,7 @@ func printSecret(obj *api.Secret, options printers.PrintOptions) ([]metav1beta1. row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, string(obj.Type), len(obj.Data), translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, string(obj.Type), int64(len(obj.Data)), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } @@ -1078,7 +1089,7 @@ func printServiceAccount(obj *api.ServiceAccount, options printers.PrintOptions) row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, len(obj.Secrets), translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(len(obj.Secrets)), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } @@ -1139,7 +1150,7 @@ func printNode(obj *api.Node, options printers.PrintOptions) ([]metav1beta1.Tabl if crVersion == "" { crVersion = "" } - row.Cells = append(row.Cells, getNodeExternalIP(obj), osImage, kernelVersion, crVersion) + row.Cells = append(row.Cells, getNodeInternalIP(obj), getNodeExternalIP(obj), osImage, kernelVersion, crVersion) } return []metav1beta1.TableRow{row}, nil @@ -1156,6 +1167,17 @@ func getNodeExternalIP(node *api.Node) string { return "" } +// Returns the internal IP of the node or "" if none is found. +func getNodeInternalIP(node *api.Node) string { + for _, address := range node.Status.Addresses { + if address.Type == api.NodeInternalIP { + return address.Address + } + } + + return "" +} + // findNodeRoles returns the roles of a given node. // The roles are determined by looking for: // * a node-role.kubernetes.io/="" label @@ -1279,7 +1301,7 @@ func printEvent(obj *api.Event, options printers.PrintOptions) ([]metav1beta1.Ta LastTimestamp = translateTimestamp(obj.LastTimestamp) } row.Cells = append(row.Cells, LastTimestamp, FirstTimestamp, - obj.Count, obj.Name, obj.InvolvedObject.Kind, + int64(obj.Count), obj.Name, obj.InvolvedObject.Kind, obj.InvolvedObject.FieldPath, obj.Type, obj.Reason, formatEventSource(obj.Source), obj.Message) @@ -1462,7 +1484,7 @@ func printDeployment(obj *extensions.Deployment, options printers.PrintOptions) // this shouldn't happen if LabelSelector passed validation return nil, err } - row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, updatedReplicas, availableReplicas, age) + row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(updatedReplicas), int64(availableReplicas), age) if options.Wide { containers, images := layoutContainerCells(containers) row.Cells = append(row.Cells, containers, images, selector.String()) @@ -1571,7 +1593,7 @@ func printHorizontalPodAutoscaler(obj *autoscaling.HorizontalPodAutoscaler, opti } maxPods := obj.Spec.MaxReplicas currentReplicas := obj.Status.CurrentReplicas - row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, maxPods, currentReplicas, translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, int64(maxPods), int64(currentReplicas), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } @@ -1591,7 +1613,7 @@ func printConfigMap(obj *api.ConfigMap, options printers.PrintOptions) ([]metav1 row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, len(obj.Data), translateTimestamp(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(len(obj.Data)), translateTimestamp(obj.CreationTimestamp)) return []metav1beta1.TableRow{row}, nil } @@ -1607,7 +1629,7 @@ func printConfigMapList(list *api.ConfigMapList, options printers.PrintOptions) return rows, nil } -func printPodSecurityPolicy(obj *extensions.PodSecurityPolicy, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { +func printPodSecurityPolicy(obj *policy.PodSecurityPolicy, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } @@ -1628,7 +1650,7 @@ func printPodSecurityPolicy(obj *extensions.PodSecurityPolicy, options printers. return []metav1beta1.TableRow{row}, nil } -func printPodSecurityPolicyList(list *extensions.PodSecurityPolicyList, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { +func printPodSecurityPolicyList(list *policy.PodSecurityPolicyList, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { rows := make([]metav1beta1.TableRow, 0, len(list.Items)) for i := range list.Items { r, err := printPodSecurityPolicy(&list.Items[i], options) diff --git a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/printers_test.go b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/printers_test.go index 747e9b3f7..2744b8f8a 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/internalversion/printers_test.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/internalversion/printers_test.go @@ -50,15 +50,18 @@ import ( "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/storage" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + genericprinters "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/printers" ) func init() { - legacyscheme.Scheme.AddKnownTypes(testapi.Default.InternalGroupVersion(), &TestPrintType{}) - legacyscheme.Scheme.AddKnownTypes(legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, &TestPrintType{}) + legacyscheme.Scheme.AddKnownTypes(schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal}, &TestPrintType{}) + legacyscheme.Scheme.AddKnownTypes(schema.GroupVersion{Group: "", Version: "v1"}, &TestPrintType{}) } var testData = TestStruct{ + TypeMeta: metav1.TypeMeta{APIVersion: "foo/bar", Kind: "TestStruct"}, Key: "testValue", Map: map[string]int{"TestSubkey": 1}, StringList: []string{"a", "b", "c"}, @@ -78,47 +81,6 @@ func (in *TestStruct) DeepCopyObject() runtime.Object { panic("never called") } -func TestVersionedPrinter(t *testing.T) { - original := &TestPrintType{Data: "value"} - p := printers.NewVersionedPrinter( - printers.ResourcePrinterFunc(func(obj runtime.Object, w io.Writer) error { - if obj == original { - t.Fatalf("object should not be identical: %#v", obj) - } - if obj.(*TestPrintType).Data != "value" { - t.Fatalf("object was not converted: %#v", obj) - } - return nil - }), - legacyscheme.Scheme, - legacyscheme.Scheme, - legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, - ) - if err := p.PrintObj(original, nil); err != nil { - t.Errorf("unexpected error: %v", err) - } -} - -func TestPrintDefault(t *testing.T) { - printerTests := []struct { - Name string - Format string - }{ - {"test wide", "wide"}, - {"test blank format", ""}, - } - - for _, test := range printerTests { - printer, err := printers.GetStandardPrinter(nil, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{AllowMissingKeys: false}) - if err != nil { - t.Errorf("in %s, unexpected error: %#v", test.Name, err) - } - if printer.IsGeneric() { - t.Errorf("in %s, printer should not be generic: %#v", test.Name, printer) - } - } -} - func TestPrintUnstructuredObject(t *testing.T) { obj := &unstructured.Unstructured{ Object: map[string]interface{}{ @@ -212,7 +174,7 @@ func TestPrintUnstructuredObject(t *testing.T) { for _, test := range tests { out.Reset() - printer := printers.NewHumanReadablePrinter(nil, nil, test.options).With(AddDefaultHandlers) + printer := printers.NewHumanReadablePrinter(nil, test.options).With(AddDefaultHandlers) printer.PrintObj(test.object, out) matches, err := regexp.MatchString(test.expected, out.String()) @@ -249,78 +211,6 @@ func (obj *TestUnknownType) DeepCopyObject() runtime.Object { return &clone } -func TestPrinter(t *testing.T) { - //test inputs - simpleTest := &TestPrintType{"foo"} - podTest := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} - podListTest := &api.PodList{ - Items: []api.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, - {ObjectMeta: metav1.ObjectMeta{Name: "bar"}}, - }, - } - emptyListTest := &api.PodList{} - testapi, err := legacyscheme.Scheme.ConvertToVersion(podTest, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - printerTests := []struct { - Name string - PrintOpts *printers.PrintOptions - Input runtime.Object - OutputVersions []schema.GroupVersion - Expect string - }{ - {"test json", &printers.PrintOptions{OutputFormatType: "json", AllowMissingKeys: true}, simpleTest, nil, "{\n \"Data\": \"foo\"\n}\n"}, - {"test yaml", &printers.PrintOptions{OutputFormatType: "yaml", AllowMissingKeys: true}, simpleTest, nil, "Data: foo\n"}, - {"test template", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{if .id}}{{.id}}{{end}}{{if .metadata.name}}{{.metadata.name}}{{end}}", AllowMissingKeys: true}, - podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo"}, - {"test jsonpath", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.metadata.name}", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo"}, - {"test jsonpath list", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.items[*].metadata.name}", AllowMissingKeys: true}, podListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo bar"}, - {"test jsonpath empty list", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.items[*].metadata.name}", AllowMissingKeys: true}, emptyListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, ""}, - {"test name", &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "pod/foo\n"}, - {"emits versioned objects", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{.kind}}", AllowMissingKeys: true}, testapi, []schema.GroupVersion{v1.SchemeGroupVersion}, "Pod"}, - } - for _, test := range printerTests { - buf := bytes.NewBuffer([]byte{}) - printer, err := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts) - if err != nil { - t.Errorf("in %s, unexpected error: %#v", test.Name, err) - } - if printer.IsGeneric() && len(test.OutputVersions) > 0 { - printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, legacyscheme.Scheme, test.OutputVersions...) - } - if err := printer.PrintObj(test.Input, buf); err != nil { - t.Errorf("in %s, unexpected error: %#v", test.Name, err) - } - if buf.String() != test.Expect { - t.Errorf("in %s, expect %q, got %q", test.Name, test.Expect, buf.String()) - } - } - -} - -func TestBadPrinter(t *testing.T) { - badPrinterTests := []struct { - Name string - PrintOpts *printers.PrintOptions - Error error - }{ - {"empty template", &printers.PrintOptions{OutputFormatType: "template", AllowMissingKeys: false}, fmt.Errorf("template format specified but no template given")}, - {"bad template", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{ .Name", AllowMissingKeys: false}, fmt.Errorf("error parsing template {{ .Name, template: output:1: unclosed action\n")}, - {"bad templatefile", &printers.PrintOptions{OutputFormatType: "templatefile", AllowMissingKeys: false}, fmt.Errorf("templatefile format specified but no template file given")}, - {"bad jsonpath", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.Name", AllowMissingKeys: false}, fmt.Errorf("error parsing jsonpath {.Name, unclosed action\n")}, - {"unknown format", &printers.PrintOptions{OutputFormatType: "anUnknownFormat", OutputFormatArgument: "", AllowMissingKeys: false}, fmt.Errorf("output format \"anUnknownFormat\" not recognized")}, - } - for _, test := range badPrinterTests { - _, err := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts) - if err == nil || err.Error() != test.Error.Error() { - t.Errorf("in %s, expect %s, got %s", test.Name, test.Error, err) - } - } -} - func testPrinter(t *testing.T, printer printers.ResourcePrinter, unmarshalFunc func(data []byte, v interface{}) error) { buf := bytes.NewBuffer([]byte{}) @@ -344,19 +234,20 @@ func testPrinter(t *testing.T, printer printers.ResourcePrinter, unmarshalFunc f t.Errorf("Test data and unmarshaled data are not equal: %v", diff.ObjectDiff(poutput, testData)) } - obj := &api.Pod{ + obj := &v1.Pod{ + TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"}, ObjectMeta: metav1.ObjectMeta{Name: "foo"}, } buf.Reset() printer.PrintObj(obj, buf) - var objOut api.Pod + var objOut v1.Pod // Verify that given function runs without error. err = unmarshalFunc(buf.Bytes(), &objOut) if err != nil { t.Fatalf("unexpected error: %#v", err) } // Use real decode function to undo the versioning process. - objOut = api.Pod{} + objOut = v1.Pod{} if err := runtime.DecodeInto(s, buf.Bytes(), &objOut); err != nil { t.Fatal(err) } @@ -366,11 +257,11 @@ func testPrinter(t *testing.T, printer printers.ResourcePrinter, unmarshalFunc f } func TestYAMLPrinter(t *testing.T) { - testPrinter(t, &printers.YAMLPrinter{}, yaml.Unmarshal) + testPrinter(t, genericprinters.NewTypeSetter(legacyscheme.Scheme).ToPrinter(&genericprinters.YAMLPrinter{}), yaml.Unmarshal) } func TestJSONPrinter(t *testing.T) { - testPrinter(t, &printers.JSONPrinter{}, json.Unmarshal) + testPrinter(t, genericprinters.NewTypeSetter(legacyscheme.Scheme).ToPrinter(&genericprinters.JSONPrinter{}), json.Unmarshal) } func TestFormatResourceName(t *testing.T) { @@ -408,7 +299,7 @@ func ErrorPrintHandler(obj *TestPrintType, w io.Writer, options printers.PrintOp func TestCustomTypePrinting(t *testing.T) { columns := []string{"Data"} - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) printer.Handler(columns, nil, PrintCustomType) obj := TestPrintType{"test object"} @@ -425,7 +316,7 @@ func TestCustomTypePrinting(t *testing.T) { func TestPrintHandlerError(t *testing.T) { columns := []string{"Data"} - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) printer.Handler(columns, nil, ErrorPrintHandler) obj := TestPrintType{"test object"} buffer := &bytes.Buffer{} @@ -436,7 +327,7 @@ func TestPrintHandlerError(t *testing.T) { } func TestUnknownTypePrinting(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) buffer := &bytes.Buffer{} err := printer.PrintObj(&TestUnknownType{}, buffer) if err == nil { @@ -446,12 +337,12 @@ func TestUnknownTypePrinting(t *testing.T) { func TestTemplatePanic(t *testing.T) { tmpl := `{{and ((index .currentState.info "foo").state.running.startedAt) .currentState.info.net.state.running.startedAt}}` - printer, err := printers.NewTemplatePrinter([]byte(tmpl)) + printer, err := genericprinters.NewGoTemplatePrinter([]byte(tmpl)) if err != nil { t.Fatalf("tmpl fail: %v", err) } buffer := &bytes.Buffer{} - err = printer.PrintObj(&api.Pod{}, buffer) + err = printer.PrintObj(&v1.Pod{}, buffer) if err == nil { t.Fatalf("expected that template to crash") } @@ -466,7 +357,7 @@ func TestNamePrinter(t *testing.T) { expect string }{ "singleObject": { - &api.Pod{ + &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", }, @@ -476,23 +367,32 @@ func TestNamePrinter(t *testing.T) { }, "pod/foo\n"}, "List": { - &v1.List{ - TypeMeta: metav1.TypeMeta{ - Kind: "List", + &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "kind": "List", + "apiVersion": "v1", }, - Items: []runtime.RawExtension{ + Items: []unstructured.Unstructured{ { - Raw: []byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": { "name": "foo"}}`), - }, - { - Raw: []byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": { "name": "bar"}}`), + Object: map[string]interface{}{ + "kind": "Pod", + "apiVersion": "v1", + "metadata": map[string]interface{}{ + "name": "bar", + }, + }, }, }, }, - "pod/foo\npod/bar\n"}, + "pod/bar\n"}, + } + + printFlags := genericclioptions.NewPrintFlags("").WithTypeSetter(legacyscheme.Scheme).WithDefaultOutput("name") + printer, err := printFlags.ToPrinter() + if err != nil { + t.Fatalf("unexpected err: %v", err) } - printOpts := &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: false} - printer, _ := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *printOpts) + for name, item := range tests { buff := &bytes.Buffer{} err := printer.PrintObj(item.obj, buff) @@ -510,15 +410,15 @@ func TestNamePrinter(t *testing.T) { func TestTemplateStrings(t *testing.T) { // This unit tests the "exists" function as well as the template from update.sh table := map[string]struct { - pod api.Pod + pod v1.Pod expect string }{ - "nilInfo": {api.Pod{}, "false"}, - "emptyInfo": {api.Pod{Status: api.PodStatus{ContainerStatuses: []api.ContainerStatus{}}}, "false"}, + "nilInfo": {v1.Pod{}, "false"}, + "emptyInfo": {v1.Pod{Status: v1.PodStatus{ContainerStatuses: []v1.ContainerStatus{}}}, "false"}, "fooExists": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ + v1.Pod{ + Status: v1.PodStatus{ + ContainerStatuses: []v1.ContainerStatus{ { Name: "foo", }, @@ -528,9 +428,9 @@ func TestTemplateStrings(t *testing.T) { "false", }, "barExists": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ + v1.Pod{ + Status: v1.PodStatus{ + ContainerStatuses: []v1.ContainerStatus{ { Name: "bar", }, @@ -540,9 +440,9 @@ func TestTemplateStrings(t *testing.T) { "false", }, "bothExist": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ + v1.Pod{ + Status: v1.PodStatus{ + ContainerStatuses: []v1.ContainerStatus{ { Name: "foo", }, @@ -555,16 +455,16 @@ func TestTemplateStrings(t *testing.T) { "false", }, "barValid": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ + v1.Pod{ + Status: v1.PodStatus{ + ContainerStatuses: []v1.ContainerStatus{ { Name: "foo", }, { Name: "bar", - State: api.ContainerState{ - Running: &api.ContainerStateRunning{ + State: v1.ContainerState{ + Running: &v1.ContainerStateRunning{ StartedAt: metav1.Time{}, }, }, @@ -575,21 +475,21 @@ func TestTemplateStrings(t *testing.T) { "false", }, "bothValid": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ + v1.Pod{ + Status: v1.PodStatus{ + ContainerStatuses: []v1.ContainerStatus{ { Name: "foo", - State: api.ContainerState{ - Running: &api.ContainerStateRunning{ + State: v1.ContainerState{ + Running: &v1.ContainerStateRunning{ StartedAt: metav1.Time{}, }, }, }, { Name: "bar", - State: api.ContainerState{ - Running: &api.ContainerStateRunning{ + State: v1.ContainerState{ + Running: &v1.ContainerStateRunning{ StartedAt: metav1.Time{}, }, }, @@ -602,13 +502,11 @@ func TestTemplateStrings(t *testing.T) { } // The point of this test is to verify that the below template works. tmpl := `{{if (exists . "status" "containerStatuses")}}{{range .status.containerStatuses}}{{if (and (eq .name "foo") (exists . "state" "running"))}}true{{end}}{{end}}{{end}}` - p, err := printers.NewTemplatePrinter([]byte(tmpl)) + printer, err := genericprinters.NewGoTemplatePrinter([]byte(tmpl)) if err != nil { t.Fatalf("tmpl fail: %v", err) } - printer := printers.NewVersionedPrinter(p, legacyscheme.Scheme, legacyscheme.Scheme, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion) - for name, item := range table { buffer := &bytes.Buffer{} err = printer.PrintObj(&item.pod, buffer) @@ -636,49 +534,37 @@ func TestPrinters(t *testing.T) { jsonpathPrinter printers.ResourcePrinter ) - templatePrinter, err = printers.NewTemplatePrinter([]byte("{{.name}}")) + templatePrinter, err = genericprinters.NewGoTemplatePrinter([]byte("{{.name}}")) if err != nil { t.Fatal(err) } - templatePrinter = printers.NewVersionedPrinter(templatePrinter, legacyscheme.Scheme, legacyscheme.Scheme, v1.SchemeGroupVersion) - templatePrinter2, err = printers.NewTemplatePrinter([]byte("{{len .items}}")) + templatePrinter2, err = genericprinters.NewGoTemplatePrinter([]byte("{{len .items}}")) if err != nil { t.Fatal(err) } - templatePrinter2 = printers.NewVersionedPrinter(templatePrinter2, legacyscheme.Scheme, legacyscheme.Scheme, v1.SchemeGroupVersion) - jsonpathPrinter, err = printers.NewJSONPathPrinter("{.metadata.name}") + jsonpathPrinter, err = genericprinters.NewJSONPathPrinter("{.metadata.name}") if err != nil { t.Fatal(err) } - jsonpathPrinter = printers.NewVersionedPrinter(jsonpathPrinter, legacyscheme.Scheme, legacyscheme.Scheme, v1.SchemeGroupVersion) - allPrinters := map[string]printers.ResourcePrinter{ - "humanReadable": printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ - NoHeaders: true, - }), - "humanReadableHeaders": printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}), - "json": &printers.JSONPrinter{}, - "yaml": &printers.YAMLPrinter{}, - "template": templatePrinter, - "template2": templatePrinter2, - "jsonpath": jsonpathPrinter, - "name": &printers.NamePrinter{ - Typer: legacyscheme.Scheme, - Decoders: []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, - }, - } - AddHandlers((allPrinters["humanReadable"]).(*printers.HumanReadablePrinter)) - AddHandlers((allPrinters["humanReadableHeaders"]).(*printers.HumanReadablePrinter)) + genericPrinters := map[string]printers.ResourcePrinter{ + // TODO(juanvallejo): move "generic printer" tests to pkg/kubectl/genericclioptions/printers + "json": genericprinters.NewTypeSetter(legacyscheme.Scheme).ToPrinter(&genericprinters.JSONPrinter{}), + "yaml": genericprinters.NewTypeSetter(legacyscheme.Scheme).ToPrinter(&genericprinters.YAMLPrinter{}), + "template": templatePrinter, + "template2": templatePrinter2, + "jsonpath": jsonpathPrinter, + } objects := map[string]runtime.Object{ - "pod": &api.Pod{ObjectMeta: om("pod")}, - "emptyPodList": &api.PodList{}, - "nonEmptyPodList": &api.PodList{Items: []api.Pod{{}}}, - "endpoints": &api.Endpoints{ - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}, {IP: "localhost"}}, - Ports: []api.EndpointPort{{Port: 8080}}, + "pod": &v1.Pod{ObjectMeta: om("pod")}, + "emptyPodList": &v1.PodList{}, + "nonEmptyPodList": &v1.PodList{Items: []v1.Pod{{}}}, + "endpoints": &v1.Endpoints{ + Subsets: []v1.EndpointSubset{{ + Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}, {IP: "localhost"}}, + Ports: []v1.EndpointPort{{Port: 8080}}, }}}, } // map of printer name to set of objects it should fail on. @@ -687,7 +573,29 @@ func TestPrinters(t *testing.T) { "jsonpath": sets.NewString("emptyPodList", "nonEmptyPodList", "endpoints"), } - for pName, p := range allPrinters { + for pName, p := range genericPrinters { + for oName, obj := range objects { + b := &bytes.Buffer{} + if err := p.PrintObj(obj, b); err != nil { + if set, found := expectedErrors[pName]; found && set.Has(oName) { + // expected error + continue + } + t.Errorf("printer '%v', object '%v'; error: '%v'", pName, oName, err) + } + } + } + + // a humanreadable printer deals with internal-versioned objects + humanReadablePrinter := map[string]printers.ResourcePrinter{ + "humanReadable": printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + NoHeaders: true, + }), + "humanReadableHeaders": printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}), + } + AddHandlers((humanReadablePrinter["humanReadable"]).(*printers.HumanReadablePrinter)) + AddHandlers((humanReadablePrinter["humanReadableHeaders"]).(*printers.HumanReadablePrinter)) + for pName, p := range humanReadablePrinter { for oName, obj := range objects { b := &bytes.Buffer{} if err := p.PrintObj(obj, b); err != nil { @@ -703,7 +611,7 @@ func TestPrinters(t *testing.T) { func TestPrintEventsResultSorted(t *testing.T) { // Arrange - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) AddHandlers(printer) obj := api.EventList{ @@ -748,7 +656,7 @@ func TestPrintEventsResultSorted(t *testing.T) { } func TestPrintNodeStatus(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) AddHandlers(printer) table := []struct { node api.Node @@ -838,7 +746,7 @@ func TestPrintNodeStatus(t *testing.T) { } func TestPrintNodeRole(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) AddHandlers(printer) table := []struct { node api.Node @@ -883,7 +791,7 @@ func TestPrintNodeRole(t *testing.T) { } func TestPrintNodeOSImage(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ ColumnLabels: []string{}, Wide: true, }) @@ -928,7 +836,7 @@ func TestPrintNodeOSImage(t *testing.T) { } func TestPrintNodeKernelVersion(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ ColumnLabels: []string{}, Wide: true, }) @@ -973,7 +881,7 @@ func TestPrintNodeKernelVersion(t *testing.T) { } func TestPrintNodeContainerRuntimeVersion(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ ColumnLabels: []string{}, Wide: true, }) @@ -1018,7 +926,7 @@ func TestPrintNodeContainerRuntimeVersion(t *testing.T) { } func TestPrintNodeName(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ Wide: true, }) AddHandlers(printer) @@ -1055,7 +963,7 @@ func TestPrintNodeName(t *testing.T) { } func TestPrintNodeExternalIP(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ Wide: true, }) AddHandlers(printer) @@ -1102,6 +1010,54 @@ func TestPrintNodeExternalIP(t *testing.T) { } } +func TestPrintNodeInternalIP(t *testing.T) { + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + Wide: true, + }) + AddHandlers(printer) + table := []struct { + node api.Node + internalIP string + }{ + { + node: api.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "foo1"}, + Status: api.NodeStatus{Addresses: []api.NodeAddress{{Type: api.NodeInternalIP, Address: "1.1.1.1"}}}, + }, + internalIP: "1.1.1.1", + }, + { + node: api.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "foo2"}, + Status: api.NodeStatus{Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}}}, + }, + internalIP: "", + }, + { + node: api.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "foo3"}, + Status: api.NodeStatus{Addresses: []api.NodeAddress{ + {Type: api.NodeInternalIP, Address: "2.2.2.2"}, + {Type: api.NodeExternalIP, Address: "3.3.3.3"}, + {Type: api.NodeInternalIP, Address: "4.4.4.4"}, + }}, + }, + internalIP: "2.2.2.2", + }, + } + + for _, test := range table { + buffer := &bytes.Buffer{} + err := printer.PrintObj(&test.node, buffer) + if err != nil { + t.Fatalf("An error occurred printing Node: %#v", err) + } + if !contains(strings.Fields(buffer.String()), test.internalIP) { + t.Fatalf("Expect printing node %s with internal ip %#v, got: %#v", test.node.Name, test.internalIP, buffer.String()) + } + } +} + func contains(fields []string, field string) bool { for _, v := range fields { if v == field { @@ -1142,6 +1098,7 @@ func TestPrintHunmanReadableIngressWithColumnLabels(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buff, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -1271,6 +1228,7 @@ func TestPrintHumanReadableService(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buff, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -1457,7 +1415,7 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) { for i, test := range table { if test.isNamespaced { // Expect output to include namespace when requested. - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ WithNamespace: true, }) AddHandlers(printer) @@ -1472,7 +1430,7 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) { } } else { // Expect error when trying to get all namespaces for un-namespaced object. - printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ WithNamespace: true, }) buffer := &bytes.Buffer{} @@ -1526,7 +1484,7 @@ func TestPrintPodTable(t *testing.T) { expect: "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\tLABELS\ntest1\t1/2\tRunning\t6\t\ta=1,b=2\n", }, { - obj: &api.PodList{Items: []api.Pod{*runningPod, *failedPod}}, opts: printers.PrintOptions{ShowAll: true, ColumnLabels: []string{"a"}}, + obj: &api.PodList{Items: []api.Pod{*runningPod, *failedPod}}, opts: printers.PrintOptions{ColumnLabels: []string{"a"}}, expect: "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\tA\ntest1\t1/2\tRunning\t6\t\t1\ntest2\t1/2\tFailed\t6\t\t\n", }, { @@ -1535,11 +1493,11 @@ func TestPrintPodTable(t *testing.T) { }, { obj: failedPod, opts: printers.PrintOptions{}, - expect: "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\n", + expect: "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\ntest2\t1/2\tFailed\t6\t\n", ignoreLegacy: true, // filtering is not done by the printer in the legacy path }, { - obj: failedPod, opts: printers.PrintOptions{ShowAll: true}, + obj: failedPod, opts: printers.PrintOptions{}, expect: "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\ntest2\t1/2\tFailed\t6\t\n", }, } @@ -1549,8 +1507,9 @@ func TestPrintPodTable(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) buf := &bytes.Buffer{} - p := printers.NewHumanReadablePrinter(nil, nil, test.opts).With(AddHandlers).AddTabWriter(false) + p := printers.NewHumanReadablePrinter(nil, test.opts).With(AddHandlers).AddTabWriter(false) if err := p.PrintObj(table, buf); err != nil { t.Fatal(err) } @@ -1589,7 +1548,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), ""}}}, }, { // Test container error overwrites pod phase @@ -1604,7 +1563,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", int64(6), ""}}}, }, { // Test the same as the above but with Terminated state and the first container overwrites the rest @@ -1619,7 +1578,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test3", "0/2", "ContainerWaitingReason", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test3", "0/2", "ContainerWaitingReason", int64(6), ""}}}, }, { // Test ready is not enough for reporting running @@ -1634,7 +1593,7 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "podPhase", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "podPhase", int64(6), ""}}}, }, { // Test ready is not enough for reporting running @@ -1650,12 +1609,28 @@ func TestPrintPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "podReason", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "podReason", int64(6), ""}}}, + }, + { + // Test pod has 2 containers, one is running and the other is completed. + api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "test6"}, + Spec: api.PodSpec{Containers: make([]api.Container, 2)}, + Status: api.PodStatus{ + Phase: "Running", + Reason: "", + ContainerStatuses: []api.ContainerStatus{ + {Ready: true, RestartCount: 3, State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Completed", ExitCode: 0}}}, + {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, + }, + }, + }, + []metav1beta1.TableRow{{Cells: []interface{}{"test6", "1/2", "Running", int64(6), ""}}}, }, } for i, test := range tests { - rows, err := printPod(&test.pod, printers.PrintOptions{ShowAll: true}) + rows, err := printPod(&test.pod, printers.PrintOptions{}) if err != nil { t.Fatal(err) } @@ -1691,7 +1666,7 @@ func TestPrintPodwide(t *testing.T) { NominatedNodeName: "node1", }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "", "1.1.1.1", "test1", "node1"}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "", "1.1.1.1", "test1", "node1"}}}, }, { // Test when the NodeName and PodIP are none @@ -1710,7 +1685,7 @@ func TestPrintPodwide(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", 6, "", "", ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", int64(6), "", "", "", ""}}}, }, } @@ -1760,12 +1735,12 @@ func TestPrintPodList(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "2/2", "podPhase", 6, ""}}, {Cells: []interface{}{"test2", "1/1", "podPhase", 1, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "2/2", "podPhase", int64(6), ""}}, {Cells: []interface{}{"test2", "1/1", "podPhase", int64(1), ""}}}, }, } for _, test := range tests { - rows, err := printPodList(&test.pods, printers.PrintOptions{ShowAll: true}) + rows, err := printPodList(&test.pods, printers.PrintOptions{}) if err != nil { t.Fatal(err) @@ -1797,7 +1772,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "Running", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "Running", int64(6), ""}}}, }, { // Test pod phase Pending should be printed @@ -1812,7 +1787,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "Pending", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "Pending", int64(6), ""}}}, }, { // Test pod phase Unknown should be printed @@ -1827,7 +1802,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test3", "1/2", "Unknown", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test3", "1/2", "Unknown", int64(6), ""}}}, }, { // Test pod phase Succeeded shouldn't be printed @@ -1842,7 +1817,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "Succeeded", 6, ""}, Conditions: podSuccessConditions}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "Succeeded", int64(6), ""}, Conditions: podSuccessConditions}}, }, { // Test pod phase Failed shouldn't be printed @@ -1857,7 +1832,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "Failed", 6, ""}, Conditions: podFailedConditions}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "Failed", int64(6), ""}, Conditions: podFailedConditions}}, }, } @@ -1866,6 +1841,7 @@ func TestPrintNonTerminatedPod(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) rows := table.Rows for i := range rows { rows[i].Object.Object = nil @@ -1899,7 +1875,7 @@ func TestPrintPodWithLabels(t *testing.T) { }, }, []string{"col1", "COL2"}, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "", "asd", "zxc"}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "", "asd", "zxc"}}}, }, { // Test name, num of containers, restarts, container ready status @@ -1918,7 +1894,7 @@ func TestPrintPodWithLabels(t *testing.T) { }, }, []string{}, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), ""}}}, }, } @@ -1927,6 +1903,7 @@ func TestPrintPodWithLabels(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) rows := table.Rows for i := range rows { rows[i].Object.Object = nil @@ -2010,6 +1987,7 @@ func TestPrintDeployment(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2018,6 +1996,7 @@ func TestPrintDeployment(t *testing.T) { } buf.Reset() table, err = printers.NewTablePrinter().With(AddHandlers).PrintTable(&test.deployment, printers.PrintOptions{Wide: true}) + verifyTable(t, table) // print deployment with '-o wide' option if err := printers.PrintTable(table, buf, printers.PrintOptions{Wide: true, NoHeaders: true}); err != nil { t.Fatal(err) @@ -2063,6 +2042,7 @@ func TestPrintDaemonSet(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2117,6 +2097,7 @@ func TestPrintJob(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2648,6 +2629,7 @@ func TestPrintHPA(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buff, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2682,7 +2664,7 @@ func TestPrintPodShowLabels(t *testing.T) { }, }, true, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "", "COL2=zxc,col1=asd"}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "", "COL2=zxc,col1=asd"}}}, }, { // Test name, num of containers, restarts, container ready status @@ -2701,7 +2683,7 @@ func TestPrintPodShowLabels(t *testing.T) { }, }, false, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), ""}}}, }, } @@ -2710,6 +2692,7 @@ func TestPrintPodShowLabels(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) rows := table.Rows for i := range rows { rows[i].Object.Object = nil @@ -2876,6 +2859,7 @@ func TestPrintService(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2933,6 +2917,7 @@ func TestPrintPodDisruptionBudget(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -2943,44 +2928,6 @@ func TestPrintPodDisruptionBudget(t *testing.T) { } } -func TestAllowMissingKeys(t *testing.T) { - tests := []struct { - Name string - PrintOpts *printers.PrintOptions - Input runtime.Object - Expect string - Error string - }{ - {"test template, allow missing keys", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{.blarg}}", AllowMissingKeys: true}, &api.Pod{}, "", ""}, - {"test template, strict", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{.blarg}}", AllowMissingKeys: false}, &api.Pod{}, "", `error executing template "{{.blarg}}": template: output:1:2: executing "output" at <.blarg>: map has no entry for key "blarg"`}, - {"test jsonpath, allow missing keys", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.blarg}", AllowMissingKeys: true}, &api.Pod{}, "", ""}, - {"test jsonpath, strict", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.blarg}", AllowMissingKeys: false}, &api.Pod{}, "", "error executing jsonpath \"{.blarg}\": blarg is not found\n"}, - } - for _, test := range tests { - buf := bytes.NewBuffer([]byte{}) - printer, err := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts) - if err != nil { - t.Errorf("in %s, unexpected error: %#v", test.Name, err) - } - err = printer.PrintObj(test.Input, buf) - if len(test.Error) == 0 && err != nil { - t.Errorf("in %s, unexpected error: %v", test.Name, err) - continue - } - if len(test.Error) > 0 { - if err == nil { - t.Errorf("in %s, expected to get error: %v", test.Name, test.Error) - } else if e, a := test.Error, err.Error(); e != a { - t.Errorf("in %s, expected error %q, got %q", test.Name, e, a) - } - continue - } - if buf.String() != test.Expect { - t.Errorf("in %s, expect %q, got %q", test.Name, test.Expect, buf.String()) - } - } -} - func TestPrintControllerRevision(t *testing.T) { tests := []struct { history apps.ControllerRevision @@ -3051,6 +2998,7 @@ func TestPrintControllerRevision(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3111,6 +3059,7 @@ func TestPrintReplicaSet(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3123,6 +3072,7 @@ func TestPrintReplicaSet(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true, Wide: true}); err != nil { t.Fatal(err) } @@ -3221,6 +3171,7 @@ func TestPrintPersistentVolumeClaim(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3293,6 +3244,7 @@ func TestPrintCronJob(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3336,6 +3288,7 @@ func TestPrintStorageClass(t *testing.T) { if err != nil { t.Fatal(err) } + verifyTable(t, table) if err := printers.PrintTable(table, buf, printers.PrintOptions{NoHeaders: true}); err != nil { t.Fatal(err) } @@ -3345,3 +3298,17 @@ func TestPrintStorageClass(t *testing.T) { buf.Reset() } } + +func verifyTable(t *testing.T, table *metav1beta1.Table) { + var panicErr interface{} + func() { + defer func() { + panicErr = recover() + }() + table.DeepCopyObject() // cells are untyped, better check that types are JSON types and can be deep copied + }() + + if panicErr != nil { + t.Errorf("unexpected panic during deepcopy of table %#v: %v", table, panicErr) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/printers/json.go b/vendor/k8s.io/kubernetes/pkg/printers/json.go deleted file mode 100644 index 1547d2d48..000000000 --- a/vendor/k8s.io/kubernetes/pkg/printers/json.go +++ /dev/null @@ -1,109 +0,0 @@ -/* -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 printers - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - - "k8s.io/apimachinery/pkg/runtime" - - "github.com/ghodss/yaml" -) - -// JSONPrinter is an implementation of ResourcePrinter which outputs an object as JSON. -type JSONPrinter struct { -} - -func (p *JSONPrinter) AfterPrint(w io.Writer, res string) error { - return nil -} - -// PrintObj is an implementation of ResourcePrinter.PrintObj which simply writes the object to the Writer. -func (p *JSONPrinter) PrintObj(obj runtime.Object, w io.Writer) error { - switch obj := obj.(type) { - case *runtime.Unknown: - var buf bytes.Buffer - err := json.Indent(&buf, obj.Raw, "", " ") - if err != nil { - return err - } - buf.WriteRune('\n') - _, err = buf.WriteTo(w) - return err - } - - data, err := json.MarshalIndent(obj, "", " ") - if err != nil { - return err - } - data = append(data, '\n') - _, err = w.Write(data) - return err -} - -// TODO: implement HandledResources() -func (p *JSONPrinter) HandledResources() []string { - return []string{} -} - -func (p *JSONPrinter) IsGeneric() bool { - return true -} - -// YAMLPrinter is an implementation of ResourcePrinter which outputs an object as YAML. -// The input object is assumed to be in the internal version of an API and is converted -// to the given version first. -type YAMLPrinter struct { - version string - converter runtime.ObjectConvertor -} - -func (p *YAMLPrinter) AfterPrint(w io.Writer, res string) error { - return nil -} - -// PrintObj prints the data as YAML. -func (p *YAMLPrinter) PrintObj(obj runtime.Object, w io.Writer) error { - switch obj := obj.(type) { - case *runtime.Unknown: - data, err := yaml.JSONToYAML(obj.Raw) - if err != nil { - return err - } - _, err = w.Write(data) - return err - } - - output, err := yaml.Marshal(obj) - if err != nil { - return err - } - _, err = fmt.Fprint(w, string(output)) - return err -} - -// TODO: implement HandledResources() -func (p *YAMLPrinter) HandledResources() []string { - return []string{} -} - -func (p *YAMLPrinter) IsGeneric() bool { - return true -} diff --git a/vendor/k8s.io/kubernetes/pkg/printers/name.go b/vendor/k8s.io/kubernetes/pkg/printers/name.go deleted file mode 100644 index 4d8903e4a..000000000 --- a/vendor/k8s.io/kubernetes/pkg/printers/name.go +++ /dev/null @@ -1,118 +0,0 @@ -/* -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 printers - -import ( - "fmt" - "io" - "strings" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - utilerrors "k8s.io/apimachinery/pkg/util/errors" -) - -// NamePrinter is an implementation of ResourcePrinter which outputs "resource/name" pair of an object. -type NamePrinter struct { - Decoders []runtime.Decoder - Typer runtime.ObjectTyper -} - -func (p *NamePrinter) AfterPrint(w io.Writer, res string) error { - return nil -} - -// PrintObj is an implementation of ResourcePrinter.PrintObj which decodes the object -// and print "resource/name" pair. If the object is a List, print all items in it. -func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error { - if meta.IsListType(obj) { - items, err := meta.ExtractList(obj) - if err != nil { - return err - } - if errs := runtime.DecodeList(items, p.Decoders...); len(errs) > 0 { - return utilerrors.NewAggregate(errs) - } - for _, obj := range items { - if err := p.PrintObj(obj, w); err != nil { - return err - } - } - return nil - } - - name := "" - if acc, err := meta.Accessor(obj); err == nil { - if n := acc.GetName(); len(n) > 0 { - name = n - } - } - - return printObj(w, name, GetObjectGroupKind(obj, p.Typer)) -} - -func GetObjectGroupKind(obj runtime.Object, typer runtime.ObjectTyper) schema.GroupKind { - if obj == nil { - return schema.GroupKind{Kind: ""} - } - groupVersionKind := obj.GetObjectKind().GroupVersionKind() - if len(groupVersionKind.Kind) > 0 { - return groupVersionKind.GroupKind() - } - - if gvks, _, err := typer.ObjectKinds(obj); err == nil { - for _, gvk := range gvks { - if len(gvk.Kind) == 0 { - continue - } - return gvk.GroupKind() - } - } - - if uns, ok := obj.(*unstructured.Unstructured); ok { - if len(uns.GroupVersionKind().Kind) > 0 { - return uns.GroupVersionKind().GroupKind() - } - } - - return schema.GroupKind{Kind: ""} -} - -func printObj(w io.Writer, name string, groupKind schema.GroupKind) error { - if len(groupKind.Kind) == 0 { - return fmt.Errorf("missing kind for resource with name %v", name) - } - - if len(groupKind.Group) == 0 { - fmt.Fprintf(w, "%s/%s\n", strings.ToLower(groupKind.Kind), name) - return nil - } - - fmt.Fprintf(w, "%s.%s/%s\n", strings.ToLower(groupKind.Kind), groupKind.Group, name) - return nil -} - -// TODO: implement HandledResources() -func (p *NamePrinter) HandledResources() []string { - return []string{} -} - -func (p *NamePrinter) IsGeneric() bool { - return true -} diff --git a/vendor/k8s.io/kubernetes/pkg/printers/printers.go b/vendor/k8s.io/kubernetes/pkg/printers/printers.go deleted file mode 100644 index 357faf498..000000000 --- a/vendor/k8s.io/kubernetes/pkg/printers/printers.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -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 printers - -import ( - "fmt" - "io/ioutil" - "os" - - "k8s.io/apimachinery/pkg/runtime" -) - -// GetStandardPrinter takes a format type, an optional format argument. It will return -// a printer or an error. The printer is agnostic to schema versions, so you must -// send arguments to PrintObj in the version you wish them to be shown using a -// VersionedPrinter (typically when generic is true). -func GetStandardPrinter(typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options PrintOptions) (ResourcePrinter, error) { - format, formatArgument, allowMissingTemplateKeys := options.OutputFormatType, options.OutputFormatArgument, options.AllowMissingKeys - - var printer ResourcePrinter - switch format { - - case "json": - printer = &JSONPrinter{} - - case "yaml": - printer = &YAMLPrinter{} - - case "name": - printer = &NamePrinter{ - Typer: typer, - Decoders: decoders, - } - - case "template", "go-template": - if len(formatArgument) == 0 { - return nil, fmt.Errorf("template format specified but no template given") - } - templatePrinter, err := NewTemplatePrinter([]byte(formatArgument)) - if err != nil { - return nil, fmt.Errorf("error parsing template %s, %v\n", formatArgument, err) - } - templatePrinter.AllowMissingKeys(allowMissingTemplateKeys) - printer = templatePrinter - - case "templatefile", "go-template-file": - if len(formatArgument) == 0 { - return nil, fmt.Errorf("templatefile format specified but no template file given") - } - data, err := ioutil.ReadFile(formatArgument) - if err != nil { - return nil, fmt.Errorf("error reading template %s, %v\n", formatArgument, err) - } - templatePrinter, err := NewTemplatePrinter(data) - if err != nil { - return nil, fmt.Errorf("error parsing template %s, %v\n", string(data), err) - } - templatePrinter.AllowMissingKeys(allowMissingTemplateKeys) - printer = templatePrinter - - case "jsonpath": - if len(formatArgument) == 0 { - return nil, fmt.Errorf("jsonpath template format specified but no template given") - } - jsonpathPrinter, err := NewJSONPathPrinter(formatArgument) - if err != nil { - return nil, fmt.Errorf("error parsing jsonpath %s, %v\n", formatArgument, err) - } - jsonpathPrinter.AllowMissingKeys(allowMissingTemplateKeys) - printer = jsonpathPrinter - - case "jsonpath-file": - if len(formatArgument) == 0 { - return nil, fmt.Errorf("jsonpath file format specified but no template file given") - } - data, err := ioutil.ReadFile(formatArgument) - if err != nil { - return nil, fmt.Errorf("error reading template %s, %v\n", formatArgument, err) - } - jsonpathPrinter, err := NewJSONPathPrinter(string(data)) - if err != nil { - return nil, fmt.Errorf("error parsing template %s, %v\n", string(data), err) - } - jsonpathPrinter.AllowMissingKeys(allowMissingTemplateKeys) - printer = jsonpathPrinter - - case "custom-columns": - var err error - if printer, err = NewCustomColumnsPrinterFromSpec(formatArgument, decoders[0], options.NoHeaders); err != nil { - return nil, err - } - - case "custom-columns-file": - file, err := os.Open(formatArgument) - if err != nil { - return nil, fmt.Errorf("error reading template %s, %v\n", formatArgument, err) - } - defer file.Close() - if printer, err = NewCustomColumnsPrinterFromTemplate(file, decoders[0]); err != nil { - return nil, err - } - - case "wide": - fallthrough - case "": - - printer = NewHumanReadablePrinter(encoder, decoders[0], options) - default: - return nil, fmt.Errorf("output format %q not recognized", format) - } - return printer, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/printers/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/printers/storage/BUILD index a560d725a..afb74a8a9 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/printers/storage/BUILD @@ -13,7 +13,6 @@ go_library( "//pkg/printers:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/printers/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/printers/storage/storage.go index 3eee73825..f2b732974 100644 --- a/vendor/k8s.io/kubernetes/pkg/printers/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/printers/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/kubernetes/pkg/printers" ) @@ -27,6 +28,6 @@ type TableConvertor struct { printers.TablePrinter } -func (c TableConvertor) ConvertToTable(ctx genericapirequest.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { +func (c TableConvertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { return c.TablePrinter.PrintTable(obj, printers.PrintOptions{Wide: true}) } diff --git a/vendor/k8s.io/kubernetes/pkg/printers/template.go b/vendor/k8s.io/kubernetes/pkg/printers/template.go deleted file mode 100644 index c54c511a2..000000000 --- a/vendor/k8s.io/kubernetes/pkg/printers/template.go +++ /dev/null @@ -1,114 +0,0 @@ -/* -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 printers - -import ( - "encoding/json" - "fmt" - "io" - "text/template" - - "k8s.io/apimachinery/pkg/runtime" -) - -// TemplatePrinter is an implementation of ResourcePrinter which formats data with a Go Template. -type TemplatePrinter struct { - rawTemplate string - template *template.Template -} - -func NewTemplatePrinter(tmpl []byte) (*TemplatePrinter, error) { - t, err := template.New("output"). - Funcs(template.FuncMap{"exists": exists}). - Parse(string(tmpl)) - if err != nil { - return nil, err - } - return &TemplatePrinter{ - rawTemplate: string(tmpl), - template: t, - }, nil -} - -// AllowMissingKeys tells the template engine if missing keys are allowed. -func (p *TemplatePrinter) AllowMissingKeys(allow bool) { - if allow { - p.template.Option("missingkey=default") - } else { - p.template.Option("missingkey=error") - } -} - -func (p *TemplatePrinter) AfterPrint(w io.Writer, res string) error { - return nil -} - -// PrintObj formats the obj with the Go Template. -func (p *TemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error { - var data []byte - var err error - data, err = json.Marshal(obj) - if err != nil { - return err - } - - out := map[string]interface{}{} - if err := json.Unmarshal(data, &out); err != nil { - return err - } - if err = p.safeExecute(w, out); err != nil { - // It is way easier to debug this stuff when it shows up in - // stdout instead of just stdin. So in addition to returning - // a nice error, also print useful stuff with the writer. - fmt.Fprintf(w, "Error executing template: %v. Printing more information for debugging the template:\n", err) - fmt.Fprintf(w, "\ttemplate was:\n\t\t%v\n", p.rawTemplate) - fmt.Fprintf(w, "\traw data was:\n\t\t%v\n", string(data)) - fmt.Fprintf(w, "\tobject given to template engine was:\n\t\t%+v\n\n", out) - return fmt.Errorf("error executing template %q: %v", p.rawTemplate, err) - } - return nil -} - -// TODO: implement HandledResources() -func (p *TemplatePrinter) HandledResources() []string { - return []string{} -} - -func (p *TemplatePrinter) IsGeneric() bool { - return true -} - -// safeExecute tries to execute the template, but catches panics and returns an error -// should the template engine panic. -func (p *TemplatePrinter) safeExecute(w io.Writer, obj interface{}) error { - var panicErr error - // Sorry for the double anonymous function. There's probably a clever way - // to do this that has the defer'd func setting the value to be returned, but - // that would be even less obvious. - retErr := func() error { - defer func() { - if x := recover(); x != nil { - panicErr = fmt.Errorf("caught panic: %+v", x) - } - }() - return p.template.Execute(w, obj) - }() - if panicErr != nil { - return panicErr - } - return retErr -} diff --git a/vendor/k8s.io/kubernetes/pkg/printers/versioned.go b/vendor/k8s.io/kubernetes/pkg/printers/versioned.go deleted file mode 100644 index d8a057d87..000000000 --- a/vendor/k8s.io/kubernetes/pkg/printers/versioned.go +++ /dev/null @@ -1,104 +0,0 @@ -/* -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 printers - -import ( - "fmt" - "io" - - "github.com/golang/glog" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// VersionedPrinter takes runtime objects and ensures they are converted to a given API version -// prior to being passed to a nested printer. -type VersionedPrinter struct { - printer ResourcePrinter - converter runtime.ObjectConvertor - typer runtime.ObjectTyper - versions []schema.GroupVersion -} - -// NewVersionedPrinter wraps a printer to convert objects to a known API version prior to printing. -func NewVersionedPrinter(printer ResourcePrinter, converter runtime.ObjectConvertor, typer runtime.ObjectTyper, versions ...schema.GroupVersion) ResourcePrinter { - return &VersionedPrinter{ - printer: printer, - converter: converter, - typer: typer, - versions: versions, - } -} - -func (p *VersionedPrinter) AfterPrint(w io.Writer, res string) error { - return nil -} - -// PrintObj implements ResourcePrinter -func (p *VersionedPrinter) PrintObj(obj runtime.Object, w io.Writer) error { - // if we're unstructured, no conversion necessary - if _, ok := obj.(*unstructured.Unstructured); ok { - return p.printer.PrintObj(obj, w) - } - // if we aren't a generic printer, we don't convert. This means the printer must be aware of what it is getting. - // The default printers fall into this category. - // TODO eventually, all printers must be generic - if !p.IsGeneric() { - return p.printer.PrintObj(obj, w) - } - - // if we're already external, no conversion necessary - gvks, _, err := p.typer.ObjectKinds(obj) - if err != nil { - glog.V(1).Info("error determining type for %T, using passed object: %v", obj, err) - return p.printer.PrintObj(obj, w) - } - needsConversion := false - for _, gvk := range gvks { - if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal { - needsConversion = true - } - } - - if !needsConversion { - // We might be an external type, but have empty kind/apiVersion fields. Ensure they are populated before printing. - if obj.GetObjectKind().GroupVersionKind().Empty() { - obj = obj.DeepCopyObject() - obj.GetObjectKind().SetGroupVersionKind(gvks[0]) - } - return p.printer.PrintObj(obj, w) - } - - if len(p.versions) == 0 { - return fmt.Errorf("no version specified, object cannot be converted") - } - converted, err := p.converter.ConvertToVersion(obj, schema.GroupVersions(p.versions)) - if err != nil { - return err - } - return p.printer.PrintObj(converted, w) -} - -// TODO: implement HandledResources() -func (p *VersionedPrinter) HandledResources() []string { - return []string{} -} - -func (p *VersionedPrinter) IsGeneric() bool { - return p.printer.IsGeneric() -} diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/BUILD b/vendor/k8s.io/kubernetes/pkg/proxy/BUILD index ba71f18ca..bb5b4b616 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/proxy/BUILD @@ -18,7 +18,6 @@ go_library( deps = [ "//pkg/api/service:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", "//pkg/proxy/util:go_default_library", "//pkg/util/net:go_default_library", "//vendor/github.com/golang/glog:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/types.go b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/types.go index b9e662826..bb4467526 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/types.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/types.go @@ -67,6 +67,9 @@ type KubeProxyIPVSConfiguration struct { MinSyncPeriod metav1.Duration // ipvs scheduler Scheduler string + // excludeCIDRs is a list of CIDR's which the ipvs proxier should not touch + // when cleaning up ipvs services. + ExcludeCIDRs []string } // KubeProxyConntrackConfiguration contains conntrack settings for diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/types.go b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/types.go index b0e44c1fe..beab095d6 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/types.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/types.go @@ -63,6 +63,9 @@ type KubeProxyIPVSConfiguration struct { MinSyncPeriod metav1.Duration `json:"minSyncPeriod"` // ipvs scheduler Scheduler string `json:"scheduler"` + // excludeCIDRs is a list of CIDR's which the ipvs proxier should not touch + // when cleaning up ipvs services. + ExcludeCIDRs []string `json:"excludeCIDRs"` } // KubeProxyConntrackConfiguration contains conntrack settings for diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.conversion.go index d5613f037..72549ce42 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -206,6 +206,7 @@ func autoConvert_v1alpha1_KubeProxyIPVSConfiguration_To_kubeproxyconfig_KubeProx out.SyncPeriod = in.SyncPeriod out.MinSyncPeriod = in.MinSyncPeriod out.Scheduler = in.Scheduler + out.ExcludeCIDRs = *(*[]string)(unsafe.Pointer(&in.ExcludeCIDRs)) return nil } @@ -218,6 +219,7 @@ func autoConvert_kubeproxyconfig_KubeProxyIPVSConfiguration_To_v1alpha1_KubeProx out.SyncPeriod = in.SyncPeriod out.MinSyncPeriod = in.MinSyncPeriod out.Scheduler = in.Scheduler + out.ExcludeCIDRs = *(*[]string)(unsafe.Pointer(&in.ExcludeCIDRs)) return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.deepcopy.go index 4ab893fdc..e6839b867 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -54,7 +54,7 @@ func (in *KubeProxyConfiguration) DeepCopyInto(out *KubeProxyConfiguration) { } out.ClientConnection = in.ClientConnection in.IPTables.DeepCopyInto(&out.IPTables) - out.IPVS = in.IPVS + in.IPVS.DeepCopyInto(&out.IPVS) if in.OOMScoreAdj != nil { in, out := &in.OOMScoreAdj, &out.OOMScoreAdj if *in == nil { @@ -186,6 +186,11 @@ func (in *KubeProxyIPVSConfiguration) DeepCopyInto(out *KubeProxyIPVSConfigurati *out = *in out.SyncPeriod = in.SyncPeriod out.MinSyncPeriod = in.MinSyncPeriod + if in.ExcludeCIDRs != nil { + in, out := &in.ExcludeCIDRs, &out.ExcludeCIDRs + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.defaults.go index 3799fbf9d..72f1cb7e7 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation/validation.go index d28453e2b..90730fcee 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation/validation.go @@ -60,7 +60,9 @@ func Validate(config *kubeproxyconfig.KubeProxyConfiguration) field.ErrorList { allErrs = append(allErrs, field.Invalid(newPath.Child("BindAddress"), config.BindAddress, "not a valid textual representation of an IP address")) } - allErrs = append(allErrs, validateHostPort(config.HealthzBindAddress, newPath.Child("HealthzBindAddress"))...) + if config.HealthzBindAddress != "" { + allErrs = append(allErrs, validateHostPort(config.HealthzBindAddress, newPath.Child("HealthzBindAddress"))...) + } allErrs = append(allErrs, validateHostPort(config.MetricsBindAddress, newPath.Child("MetricsBindAddress"))...) if config.ClusterCIDR != "" { @@ -116,6 +118,7 @@ func validateKubeProxyIPVSConfiguration(config kubeproxyconfig.KubeProxyIPVSConf } allErrs = append(allErrs, validateIPVSSchedulerMethod(kubeproxyconfig.IPVSSchedulerMethod(config.Scheduler), fldPath.Child("Scheduler"))...) + allErrs = append(allErrs, validateIPVSExcludeCIDRs(config.ExcludeCIDRs, fldPath.Child("ExcludeCidrs"))...) return allErrs } @@ -253,3 +256,14 @@ func validateKubeProxyNodePortAddress(nodePortAddresses []string, fldPath *field return allErrs } + +func validateIPVSExcludeCIDRs(excludeCIDRs []string, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + for i := range excludeCIDRs { + if _, _, err := net.ParseCIDR(excludeCIDRs[i]); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath, excludeCIDRs, "must be a valid IP block")) + } + } + return allErrs +} diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go index aeb53a3e5..328980911 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go @@ -82,6 +82,26 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, }, }, + { + BindAddress: "192.168.59.103", + HealthzBindAddress: "", + MetricsBindAddress: "127.0.0.1:10249", + ClusterCIDR: "192.168.59.0/24", + UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, + ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, + IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, + }, + Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ + Max: pointer.Int32Ptr(2), + MaxPerCore: pointer.Int32Ptr(1), + Min: pointer.Int32Ptr(1), + TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, + TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, + }, + }, } for _, successCase := range successCases { @@ -749,3 +769,75 @@ func TestValidateKubeProxyNodePortAddress(t *testing.T) { } } } + +func TestValidateKubeProxyExcludeCIDRs(t *testing.T) { + // TODO(rramkumar): This test is a copy of TestValidateKubeProxyNodePortAddress. + // Maybe some code can be shared? + newPath := field.NewPath("KubeProxyConfiguration") + + successCases := []struct { + addresses []string + }{ + {[]string{}}, + {[]string{"127.0.0.0/8"}}, + {[]string{"0.0.0.0/0"}}, + {[]string{"::/0"}}, + {[]string{"127.0.0.1/32", "1.2.3.0/24"}}, + {[]string{"127.0.0.0/8"}}, + {[]string{"127.0.0.1/32"}}, + {[]string{"::1/128"}}, + {[]string{"1.2.3.4/32"}}, + {[]string{"10.20.30.0/24"}}, + {[]string{"10.20.0.0/16", "100.200.0.0/16"}}, + {[]string{"10.0.0.0/8"}}, + {[]string{"2001:db8::/32"}}, + } + + for _, successCase := range successCases { + if errs := validateIPVSExcludeCIDRs(successCase.addresses, newPath.Child("ExcludeCIDRs")); len(errs) != 0 { + t.Errorf("expected success: %v", errs) + } + } + + errorCases := []struct { + addresses []string + msg string + }{ + { + addresses: []string{"foo"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"1.2.3"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{""}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"10.20.30.40"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"::1"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"2001:db8:1"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"2001:db8:xyz/64"}, + msg: "must be a valid IP block", + }, + } + + for _, errorCase := range errorCases { + if errs := validateIPVSExcludeCIDRs(errorCase.addresses, newPath.Child("ExcludeCIDRs")); len(errs) == 0 { + t.Errorf("expected failure for %s", errorCase.msg) + } else if !strings.Contains(errs[0].Error(), errorCase.msg) { + t.Errorf("unexpected error: %v, expected: %s", errs[0], errorCase.msg) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/zz_generated.deepcopy.go index ed7e5ef4d..db491d40c 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -76,7 +76,7 @@ func (in *KubeProxyConfiguration) DeepCopyInto(out *KubeProxyConfiguration) { } out.ClientConnection = in.ClientConnection in.IPTables.DeepCopyInto(&out.IPTables) - out.IPVS = in.IPVS + in.IPVS.DeepCopyInto(&out.IPVS) if in.OOMScoreAdj != nil { in, out := &in.OOMScoreAdj, &out.OOMScoreAdj if *in == nil { @@ -208,6 +208,11 @@ func (in *KubeProxyIPVSConfiguration) DeepCopyInto(out *KubeProxyIPVSConfigurati *out = *in out.SyncPeriod = in.SyncPeriod out.MinSyncPeriod = in.MinSyncPeriod + if in.ExcludeCIDRs != nil { + in, out := &in.ExcludeCIDRs, &out.ExcludeCIDRs + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/iptables/proxier.go b/vendor/k8s.io/kubernetes/pkg/proxy/iptables/proxier.go index 4b57e0440..a4338f62d 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/iptables/proxier.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/iptables/proxier.go @@ -960,32 +960,53 @@ func (proxier *Proxier) syncProxyRules() { if svcInfo.NodePort != 0 { // Hold the local port open so no other process can open it // (because the socket might open but it would never work). - lp := utilproxy.LocalPort{ - Description: "nodePort for " + svcNameString, - IP: "", - Port: svcInfo.NodePort, - Protocol: protocol, + addresses, err := utilproxy.GetNodeAddresses(proxier.nodePortAddresses, proxier.networkInterfacer) + if err != nil { + glog.Errorf("Failed to get node ip address matching nodeport cidr: %v", err) + continue } - if proxier.portsMap[lp] != nil { - glog.V(4).Infof("Port %s was open before and is still needed", lp.String()) - replacementPortsMap[lp] = proxier.portsMap[lp] - } else { - socket, err := proxier.portMapper.OpenLocalPort(&lp) - if err != nil { - glog.Errorf("can't open %s, skipping this nodePort: %v", lp.String(), err) - continue + + lps := make([]utilproxy.LocalPort, 0) + for address := range addresses { + lp := utilproxy.LocalPort{ + Description: "nodePort for " + svcNameString, + IP: address, + Port: svcInfo.NodePort, + Protocol: protocol, + } + if utilproxy.IsZeroCIDR(address) { + // Empty IP address means all + lp.IP = "" + lps = append(lps, lp) + // If we encounter a zero CIDR, then there is no point in processing the rest of the addresses. + break } - if lp.Protocol == "udp" { - // TODO: We might have multiple services using the same port, and this will clear conntrack for all of them. - // This is very low impact. The NodePort range is intentionally obscure, and unlikely to actually collide with real Services. - // This only affects UDP connections, which are not common. - // See issue: https://github.com/kubernetes/kubernetes/issues/49881 - err := conntrack.ClearEntriesForPort(proxier.exec, lp.Port, isIPv6, v1.ProtocolUDP) + lps = append(lps, lp) + } + + // For ports on node IPs, open the actual port and hold it. + for _, lp := range lps { + if proxier.portsMap[lp] != nil { + glog.V(4).Infof("Port %s was open before and is still needed", lp.String()) + replacementPortsMap[lp] = proxier.portsMap[lp] + } else { + socket, err := proxier.portMapper.OpenLocalPort(&lp) if err != nil { - glog.Errorf("Failed to clear udp conntrack for port %d, error: %v", lp.Port, err) + glog.Errorf("can't open %s, skipping this nodePort: %v", lp.String(), err) + continue + } + if lp.Protocol == "udp" { + // TODO: We might have multiple services using the same port, and this will clear conntrack for all of them. + // This is very low impact. The NodePort range is intentionally obscure, and unlikely to actually collide with real Services. + // This only affects UDP connections, which are not common. + // See issue: https://github.com/kubernetes/kubernetes/issues/49881 + err := conntrack.ClearEntriesForPort(proxier.exec, lp.Port, isIPv6, v1.ProtocolUDP) + if err != nil { + glog.Errorf("Failed to clear udp conntrack for port %d, error: %v", lp.Port, err) + } } + replacementPortsMap[lp] = socket } - replacementPortsMap[lp] = socket } if hasEndpoints { diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/iptables/proxier_test.go b/vendor/k8s.io/kubernetes/pkg/proxy/iptables/proxier_test.go index 65be9536e..7f315262b 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/iptables/proxier_test.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/iptables/proxier_test.go @@ -595,7 +595,7 @@ func TestClusterIPReject(t *testing.T) { } makeServiceMap(fp, - makeTestService(svcPortName.Namespace, svcPortName.Namespace, func(svc *api.Service) { + makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *api.Service) { svc.Spec.ClusterIP = svcIP svc.Spec.Ports = []api.ServicePort{{ Name: svcPortName.Port, diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/README.md b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/README.md index 6af327f0b..cd6fc1153 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/README.md +++ b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/README.md @@ -1,6 +1,22 @@ -# How to use IPVS +- [IPVS](#ipvs) + - [What is IPVS](#what-is-ipvs) + - [IPVS vs. IPTABLES](#ipvs-vs-iptables) + - [When ipvs falls back to iptables](#when-ipvs-falls-back-to-iptables) + - [Run kube-proxy in ipvs mode](#run-kube-proxy-in-ipvs-mode) + - [Prerequisite](#prerequisite) + - [Local UP Cluster](#local-up-cluster) + - [GCE Cluster](#gce-cluster) + - [Cluster Created by Kubeadm](#cluster-created-by-kubeadm) + - [Debug](#debug) + - [Check IPVS proxy rules](#check-ipvs-proxy-rules) + - [Why kube-proxy can't start IPVS mode](#why-kube-proxy-cant-start-ipvs-mode) -This document shows how to use kube-proxy ipvs mode. +# IPVS + +This document intends to show users +- what is IPVS +- difference between IPVS and IPTABLES +- how to run kube-proxy in ipvs mode and info on debugging ## What is IPVS @@ -10,22 +26,258 @@ Linux kernel. IPVS runs on a host and acts as a load balancer in front of a cluster of real servers. IPVS can direct requests for TCP and UDP-based services to the real servers, and make services of real servers appear as virtual services on a single IP address. +## IPVS vs. IPTABLES +IPVS mode was introduced in Kubernetes v1.8 and goes beta in v1.9. IPTABLES mode was added in v1.1 and become the default operating mode since v1.2. Both IPVS and IPTABLES are based on `netfilter`. +Differences between IPVS mode and IPTABLES mode are as follows: + +1. IPVS provides better scalability and performance for large clusters. + +2. IPVS supports more sophisticated load balancing algorithms than iptables (least load, least connections, locality, weighted, etc.). + +3. IPVS supports server health checking and connection retries, etc. + +### When ipvs falls back to iptables +IPVS proxier will employ iptables in doing packet filtering, SNAT and supporting NodePort type service. Specifically, ipvs proxier will fall back on iptables in the following 4 scenarios. + +**1. kube-proxy starts with --masquerade-all=true** + +If kube-proxy starts with `--masquerade-all=true`, ipvs proxier will masquerade all traffic accessing service Cluster IP, which behaves the same as what iptables proxier. Suppose there is a service with Cluster IP `10.244.5.1` and port `8080`, then the iptables installed by ipvs proxier should be like what is shown below. + +```shell +# iptables -t nat -nL + +Chain PREROUTING (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain POSTROUTING (policy ACCEPT) +target prot opt source destination +KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ + +Chain KUBE-POSTROUTING (1 references) +target prot opt source destination +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 + +Chain KUBE-MARK-DROP (0 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x8000 + +Chain KUBE-MARK-MASQ (6 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 + +Chain KUBE-SERVICES (2 references) +target prot opt source destination +KUBE-MARK-MASQ tcp -- 0.0.0.0/0 10.244.5.1 /* default/foo:http cluster IP */ tcp dpt:8080 +``` + +**2. Specify cluster CIDR in kube-proxy startup** + +If kube-proxy starts with `--cluster-cidr=`, ipvs proxier will masquerade off-cluster traffic accessing service Cluster IP, which behaves the same as what iptables proxier. Suppose kube-proxy is provided with the cluster cidr `10.244.16.0/24`, and service Cluster IP is `10.244.5.1` and port is `8080`, then the iptables installed by ipvs proxier should be like what is shown below. + +```shell +# iptables -t nat -nL + +Chain PREROUTING (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain POSTROUTING (policy ACCEPT) +target prot opt source destination +KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ + +Chain KUBE-POSTROUTING (1 references) +target prot opt source destination +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 + +Chain KUBE-MARK-DROP (0 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x8000 + +Chain KUBE-MARK-MASQ (6 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 + +Chain KUBE-SERVICES (2 references) +target prot opt source destination +KUBE-MARK-MASQ tcp -- !10.244.16.0/24 10.244.5.1 /* default/foo:http cluster IP */ tcp dpt:8080 +``` + +**3. Load Balancer Source Ranges is specified for LB type service** + +When service's `LoadBalancerStatus.ingress.IP` is not empty and service's `LoadBalancerSourceRanges` is specified, ipvs proxier will install iptables which looks like what is shown below. + +Suppose service's `LoadBalancerStatus.ingress.IP` is `10.96.1.2` and service's `LoadBalancerSourceRanges` is `10.120.2.0/24`. + +```shell +# iptables -t nat -nL + +Chain PREROUTING (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain POSTROUTING (policy ACCEPT) +target prot opt source destination +KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ + +Chain KUBE-POSTROUTING (1 references) +target prot opt source destination +MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 + +Chain KUBE-MARK-DROP (0 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x8000 + +Chain KUBE-MARK-MASQ (6 references) +target prot opt source destination +MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 + +Chain KUBE-SERVICES (2 references) +target prot opt source destination +ACCEPT tcp -- 10.120.2.0/24 10.96.1.2 /* default/foo:http loadbalancer IP */ tcp dpt:8080 +DROP tcp -- 0.0.0.0/0 10.96.1.2 /* default/foo:http loadbalancer IP */ tcp dpt:8080 +``` + +**4. Support NodePort type service** + +For supporting NodePort type service, ipvs will recruit the existing implementation in iptables proxier. For example, + +```shell +# kubectl describe svc nginx-service +Name: nginx-service +... +Type: NodePort +IP: 10.101.28.148 +Port: http 3080/TCP +NodePort: http 31604/TCP +Endpoints: 172.17.0.2:80 +Session Affinity: None + +# iptables -t nat -nL + +[root@100-106-179-225 ~]# iptables -t nat -nL +Chain PREROUTING (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */ + +Chain KUBE-SERVICES (2 references) +target prot opt source destination +KUBE-MARK-MASQ tcp -- !172.16.0.0/16 10.101.28.148 /* default/nginx-service:http cluster IP */ tcp dpt:3080 +KUBE-SVC-6IM33IEVEEV7U3GP tcp -- 0.0.0.0/0 10.101.28.148 /* default/nginx-service:http cluster IP */ tcp dpt:3080 +KUBE-NODEPORTS all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL + +Chain KUBE-NODEPORTS (1 references) +target prot opt source destination +KUBE-MARK-MASQ tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-service:http */ tcp dpt:31604 +KUBE-SVC-6IM33IEVEEV7U3GP tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-service:http */ tcp dpt:31604 + +Chain KUBE-SVC-6IM33IEVEEV7U3GP (2 references) +target prot opt source destination +KUBE-SEP-Q3UCPZ54E6Q2R4UT all -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-service:http */ +Chain KUBE-SEP-Q3UCPZ54E6Q2R4UT (1 references) +target prot opt source destination +KUBE-MARK-MASQ all -- 172.17.0.2 0.0.0.0/0 /* default/nginx-service:http */ +DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-service:http */ tcp to:172.17.0.2:80 +``` ## Run kube-proxy in ipvs mode -Currently, local-up scripts and kubeadm support switching IPVS proxy mode via exporting environment variables or specifying flags. +Currently, local-up scripts, GCE scripts and kubeadm support switching IPVS proxy mode via exporting environment variables or specifying flags. + +### Prerequisite +Ensure IPVS required kernel modules +```shell +ip_vs +ip_vs_rr +ip_vs_wrr +ip_vs_sh +nf_conntrack_ipv4 +``` +1. have been compiled into the node kernel. Use + +`grep -e ipvs -e nf_conntrack_ipv4 /lib/modules/$(uname -r)/modules.builtin` + +and get results like the followings if compiled into kernel. +``` +kernel/net/ipv4/netfilter/nf_conntrack_ipv4.ko +kernel/net/netfilter/ipvs/ip_vs.ko +kernel/net/netfilter/ipvs/ip_vs_rr.ko +kernel/net/netfilter/ipvs/ip_vs_wrr.ko +kernel/net/netfilter/ipvs/ip_vs_lc.ko +kernel/net/netfilter/ipvs/ip_vs_wlc.ko +kernel/net/netfilter/ipvs/ip_vs_fo.ko +kernel/net/netfilter/ipvs/ip_vs_ovf.ko +kernel/net/netfilter/ipvs/ip_vs_lblc.ko +kernel/net/netfilter/ipvs/ip_vs_lblcr.ko +kernel/net/netfilter/ipvs/ip_vs_dh.ko +kernel/net/netfilter/ipvs/ip_vs_sh.ko +kernel/net/netfilter/ipvs/ip_vs_sed.ko +kernel/net/netfilter/ipvs/ip_vs_nq.ko +kernel/net/netfilter/ipvs/ip_vs_ftp.ko +``` + +OR + +2. have been loaded. +```shell +# load module +modprobe -- ip_vs +modprobe -- ip_vs_rr +modprobe -- ip_vs_wrr +modprobe -- ip_vs_sh +modprobe -- nf_conntrack_ipv4 + +# to check loaded modules, use +lsmod | grep -e ipvs -e nf_conntrack_ipv4 +# or +cut -f1 -d " " /proc/modules | grep -e ip_vs -e nf_conntrack_ipv4 + ``` + +Packages such as `ipset` should also be installed on the node before using IPVS mode. + +Kube-proxy will fall back to IPTABLES mode if those requirements are not met. ### Local UP Cluster Kube-proxy will run in iptables mode by default in a [local-up cluster](https://github.com/kubernetes/community/blob/master/contributors/devel/running-locally.md). -Users should export the env `KUBE_PROXY_MODE=ipvs` to specify the ipvs mode before deploying the cluster if want to run kube-proxy in ipvs mode. +To use IPVS mode, users should export the env `KUBE_PROXY_MODE=ipvs` to specify the ipvs mode before [starting the cluster](https://github.com/kubernetes/community/blob/master/contributors/devel/running-locally.md#starting-the-cluster): +```shell +# before running `hack/local-up-cluster.sh` +export KUBE_PROXY_MODE=ipvs +``` + +### GCE Cluster + +Similar to local-up cluster, kube-proxy in [clusters running on GCE](https://kubernetes.io/docs/getting-started-guides/gce/) run in iptables mode by default. Users need to export the env `KUBE_PROXY_MODE=ipvs` before [starting a cluster](https://kubernetes.io/docs/getting-started-guides/gce/#starting-a-cluster): +```shell +#before running one of the commmands chosen to start a cluster: +# curl -sS https://get.k8s.io | bash +# wget -q -O - https://get.k8s.io | bash +# cluster/kube-up.sh +export KUBE_PROXY_MODE=ipvs +``` ### Cluster Created by Kubeadm Kube-proxy will run in iptables mode by default in a cluster deployed by [kubeadm](https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/). If you are using kubeadm with a [configuration file](https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/#config-file), you can specify the ipvs mode adding `SupportIPVSProxyMode: true` below the `kubeProxy` field. -Then the configuration file is similar to: ```json kind: MasterConfiguration @@ -37,46 +289,79 @@ kubeProxy: mode: ipvs ... ``` +before running + +`kube init --config ` + +If you are using Kubernetes v1.8, you can also add the flag `--feature-gates=SupportIPVSProxyMode=true` (deprecated since v1.9) in `kubeadm init` command + +``` +kubeadm init --feature-gates=SupportIPVSProxyMode=true +``` + +to specify the ipvs mode before deploying the cluster. + +**Notes** +If ipvs mode is successfully on, you should see ipvs proxy rules (use `ipvsadm`) like +```shell + # ipvsadm -ln +IP Virtual Server version 1.2.1 (size=4096) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 10.0.0.1:443 rr persistent 10800 + -> 192.168.0.1:6443 Masq 1 1 0 +``` +or similar logs occur in kube-proxy logs (for example, `/tmp/kube-proxy.log` for local-up cluster) when the local cluster is running: +``` +Using ipvs Proxier. +``` + +While there is no ipvs proxy rules or the following logs ocuurs indicate that the kube-proxy fails to use ipvs mode: +``` +Can't use ipvs proxier, trying iptables proxier +Using iptables Proxier. +``` +See the following section for more details on debugging. ## Debug ### Check IPVS proxy rules -People can use `ipvsadm` tool to check whether kube-proxy are maintaining IPVS rules correctly. For example, we may get IPVS proxy rules like: +Users can use `ipvsadm` tool to check whether kube-proxy are maintaining IPVS rules correctly. For example, we have the following services in the cluster: + +``` + # kubectl get svc --all-namespaces +NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +default kubernetes ClusterIP 10.0.0.1 443/TCP 1d +kube-system kube-dns ClusterIP 10.0.0.10 53/UDP,53/TCP 1d +``` +We may get IPVS proxy rules like: ```shell -# ipvsadm -ln + # ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.0.0.1:443 rr persistent 10800 - -> 10.229.43.2:6443 Masq 1 0 0 -TCP 10.0.0.10:53 rr + -> 192.168.0.1:6443 Masq 1 1 0 +TCP 10.0.0.10:53 rr + -> 172.17.0.2:53 Masq 1 0 0 UDP 10.0.0.10:53 rr + -> 172.17.0.2:53 Masq 1 0 0 ``` ### Why kube-proxy can't start IPVS mode -People can do the following check list step by step: +Use the following check list to help you solve the problems: **1. Enable IPVS feature gateway** -Currently IPVS-based kube-proxy is still in alpha phase, people need to enable `--feature-gates=SupportIPVSProxyMode=true` explicitly. +For Kubernetes v1.10 and later, feature gate `SupportIPVSProxyMode` is set to `true` by default. However, you need to enable `--feature-gates=SupportIPVSProxyMode=true` explicitly for Kubernetes before v1.10. **2. Specify proxy-mode=ipvs** -Tell kube-proxy that proxy-mode=ipvs, please. +Check whether the kube-proxy mode has been set to `ipvs`. -**3. Load ipvs required kernel modules** - -The following kernel modules are required by IPVS-based kube-proxy: - -```shell -ip_vs -ip_vs_rr -ip_vs_wrr -ip_vs_sh -nf_conntrack_ipv4 -``` +**3. Install required kernel modules and packages** -IPVS-based kube-proxy will load them automatically. If it fails to load them, please check whether they are compiled into your kernel. +Check whether the ipvs required kernel modules have been compiled into the kernel and packages installed. (see Prerequisite) diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/ipset.go b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/ipset.go index 16637455b..5da72749b 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/ipset.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/ipset.go @@ -21,6 +21,7 @@ import ( utilipset "k8s.io/kubernetes/pkg/util/ipset" utilversion "k8s.io/kubernetes/pkg/util/version" + "fmt" "github.com/golang/glog" ) @@ -28,32 +29,41 @@ const ( // MinIPSetCheckVersion is the min ipset version we need. IPv6 is supported in ipset 6.x MinIPSetCheckVersion = "6.0" - // KubeLoopBackIPSet is used to store endpoints dst ip:port, source ip for solving hairpin purpose. - KubeLoopBackIPSet = "KUBE-LOOP-BACK" + kubeLoopBackIPSetComment = "Kubernetes endpoints dst ip:port, source ip for solving hairpin purpose" + kubeLoopBackIPSet = "KUBE-LOOP-BACK" - // KubeClusterIPSet is used to store service cluster ip + port for masquerade purpose. - KubeClusterIPSet = "KUBE-CLUSTER-IP" + kubeClusterIPSetComment = "Kubernetes service cluster ip + port for masquerade purpose" + kubeClusterIPSet = "KUBE-CLUSTER-IP" - // KubeExternalIPSet is used to store service external ip + port for masquerade and filter purpose. - KubeExternalIPSet = "KUBE-EXTERNAL-IP" + kubeExternalIPSetComment = "Kubernetes service external ip + port for masquerade and filter purpose" + kubeExternalIPSet = "KUBE-EXTERNAL-IP" - // KubeLoadBalancerSet is used to store service load balancer ingress ip + port, it is the service lb portal. - KubeLoadBalancerSet = "KUBE-LOAD-BALANCER" + kubeLoadBalancerSetComment = "Kubernetes service lb portal" + kubeLoadBalancerSet = "KUBE-LOAD-BALANCER" - // KubeLoadBalancerMasqSet is used to store service load balancer ingress ip + port for masquerade purpose. - KubeLoadBalancerMasqSet = "KUBE-LOAD-BALANCER-MASQ" + kubeLoadBalancerLocalSetComment = "Kubernetes service load balancer ip + port with externalTrafficPolicy=local" + kubeLoadBalancerLocalSet = "KUBE-LOAD-BALANCER-LOCAL" - // KubeLoadBalancerSourceIPSet is used to store service load balancer ingress ip + port + source IP for packet filter purpose. - KubeLoadBalancerSourceIPSet = "KUBE-LOAD-BALANCER-SOURCE-IP" + kubeLoadbalancerFWSetComment = "Kubernetes service load balancer ip + port for load balancer with sourceRange" + kubeLoadbalancerFWSet = "KUBE-LOAD-BALANCER-FW" - // KubeLoadBalancerSourceCIDRSet is used to store service load balancer ingress ip + port + source cidr for packet filter purpose. - KubeLoadBalancerSourceCIDRSet = "KUBE-LOAD-BALANCER-SOURCE-CIDR" + kubeLoadBalancerSourceIPSetComment = "Kubernetes service load balancer ip + port + source IP for packet filter purpose" + kubeLoadBalancerSourceIPSet = "KUBE-LOAD-BALANCER-SOURCE-IP" - // KubeNodePortSetTCP is used to store nodeport TCP port for masquerade purpose. - KubeNodePortSetTCP = "KUBE-NODE-PORT-TCP" + kubeLoadBalancerSourceCIDRSetComment = "Kubernetes service load balancer ip + port + source cidr for packet filter purpose" + kubeLoadBalancerSourceCIDRSet = "KUBE-LOAD-BALANCER-SOURCE-CIDR" - // KubeNodePortSetUDP is used to store nodeport UDP port for masquerade purpose. - KubeNodePortSetUDP = "KUBE-NODE-PORT-UDP" + kubeNodePortSetTCPComment = "Kubernetes nodeport TCP port for masquerade purpose" + kubeNodePortSetTCP = "KUBE-NODE-PORT-TCP" + + kubeNodePortLocalSetTCPComment = "Kubernetes nodeport TCP port with externalTrafficPolicy=local" + kubeNodePortLocalSetTCP = "KUBE-NODE-PORT-LOCAL-TCP" + + kubeNodePortSetUDPComment = "Kubernetes nodeport UDP port for masquerade purpose" + kubeNodePortSetUDP = "KUBE-NODE-PORT-UDP" + + kubeNodePortLocalSetUDPComment = "Kubernetes nodeport UDP port with externalTrafficPolicy=local" + kubeNodePortLocalSetUDP = "KUBE-NODE-PORT-LOCAL-UDP" ) // IPSetVersioner can query the current ipset version. @@ -72,7 +82,7 @@ type IPSet struct { } // NewIPSet initialize a new IPSet struct -func NewIPSet(handle utilipset.Interface, name string, setType utilipset.Type, isIPv6 bool) *IPSet { +func NewIPSet(handle utilipset.Interface, name string, setType utilipset.Type, isIPv6 bool, comment string) *IPSet { hashFamily := utilipset.ProtocolFamilyIPV4 if isIPv6 { hashFamily = utilipset.ProtocolFamilyIPV6 @@ -82,6 +92,7 @@ func NewIPSet(handle utilipset.Interface, name string, setType utilipset.Type, i Name: name, SetType: setType, HashFamily: hashFamily, + Comment: comment, }, activeEntries: sets.NewString(), handle: handle, @@ -97,6 +108,10 @@ func (set *IPSet) isEmpty() bool { return len(set.activeEntries.UnsortedList()) == 0 } +func (set *IPSet) getComment() string { + return fmt.Sprintf("\"%s\"", set.Comment) +} + func (set *IPSet) resetEntries() { set.activeEntries = sets.NewString() } @@ -136,12 +151,10 @@ func (set *IPSet) syncIPSetEntries() { } } -func ensureIPSets(ipSets ...*IPSet) error { - for _, set := range ipSets { - if err := set.handle.CreateSet(&set.IPSet, true); err != nil { - glog.Errorf("Failed to make sure ip set: %v exist, error: %v", set, err) - return err - } +func ensureIPSet(set *IPSet) error { + if err := set.handle.CreateSet(&set.IPSet, true); err != nil { + glog.Errorf("Failed to make sure ip set: %v exist, error: %v", set, err) + return err } return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/ipset_test.go b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/ipset_test.go index 4610aceb9..2e6f667de 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/ipset_test.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/ipset_test.go @@ -182,7 +182,7 @@ func TestSyncIPSetEntries(t *testing.T) { } for i := range testCases { - set := NewIPSet(fakeipset.NewFake(testIPSetVersion), testCases[i].set.Name, testCases[i].setType, testCases[i].ipv6) + set := NewIPSet(fakeipset.NewFake(testIPSetVersion), testCases[i].set.Name, testCases[i].setType, testCases[i].ipv6, "comment-"+testCases[i].set.Name) if err := set.handle.CreateSet(&set.IPSet, true); err != nil { t.Errorf("Unexpected error: %v", err) diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/proxier.go b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/proxier.go index 7f0e7630f..dbbc505cb 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/proxier.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/proxier.go @@ -16,14 +16,12 @@ limitations under the License. package ipvs -// -// NOTE: this needs to be tested in e2e since it uses ipvs for everything. -// - import ( "bytes" "fmt" + "io/ioutil" "net" + "regexp" "strconv" "strings" "sync" @@ -56,11 +54,8 @@ const ( // kubeServicesChain is the services portal chain kubeServicesChain utiliptables.Chain = "KUBE-SERVICES" - // KubeServiceIPSetsChain is the services access IP chain - KubeServiceIPSetsChain utiliptables.Chain = "KUBE-SVC-IPSETS" - // KubeFireWallChain is the kubernetes firewall chain. - KubeFireWallChain utiliptables.Chain = "KUBE-FIRE-WALL" + KubeFireWallChain utiliptables.Chain = "KUBE-FIREWALL" // kubePostroutingChain is the kubernetes postrouting chain kubePostroutingChain utiliptables.Chain = "KUBE-POSTROUTING" @@ -68,23 +63,92 @@ const ( // KubeMarkMasqChain is the mark-for-masquerade chain KubeMarkMasqChain utiliptables.Chain = "KUBE-MARK-MASQ" + // KubeNodePortChain is the kubernetes node port chain + KubeNodePortChain utiliptables.Chain = "KUBE-NODE-PORT" + // KubeMarkDropChain is the mark-for-drop chain KubeMarkDropChain utiliptables.Chain = "KUBE-MARK-DROP" + // KubeForwardChain is the kubernetes forward chain + KubeForwardChain utiliptables.Chain = "KUBE-FORWARD" + + // KubeLoadBalancerChain is the kubernetes chain for loadbalancer type service + KubeLoadBalancerChain utiliptables.Chain = "KUBE-LOAD-BALANCER" + // DefaultScheduler is the default ipvs scheduler algorithm - round robin. DefaultScheduler = "rr" - // DefaultDummyDevice is the default dummy interface where ipvs service address will bind to it. + // DefaultDummyDevice is the default dummy interface which ipvs service address will bind to it. DefaultDummyDevice = "kube-ipvs0" ) -// tableChainsWithJumpService is the iptables chains ipvs proxy mode used. -var tableChainsWithJumpService = []struct { +// iptablesJumpChain is tables of iptables chains that ipvs proxier used to install iptables or cleanup iptables. +// `to` is the iptables chain we want to operate. +// `from` is the source iptables chain +var iptablesJumpChain = []struct { + table utiliptables.Table + from utiliptables.Chain + to utiliptables.Chain + comment string +}{ + {utiliptables.TableNAT, utiliptables.ChainOutput, kubeServicesChain, "kubernetes service portals"}, + {utiliptables.TableNAT, utiliptables.ChainPrerouting, kubeServicesChain, "kubernetes service portals"}, + {utiliptables.TableNAT, utiliptables.ChainPostrouting, kubePostroutingChain, "kubernetes postrouting rules"}, + {utiliptables.TableFilter, utiliptables.ChainForward, KubeForwardChain, "kubernetes forwarding rules"}, +} + +var iptablesChains = []struct { table utiliptables.Table chain utiliptables.Chain }{ - {utiliptables.TableNAT, utiliptables.ChainOutput}, - {utiliptables.TableNAT, utiliptables.ChainPrerouting}, + {utiliptables.TableNAT, kubeServicesChain}, + {utiliptables.TableNAT, kubePostroutingChain}, + {utiliptables.TableNAT, KubeFireWallChain}, + {utiliptables.TableNAT, KubeNodePortChain}, + {utiliptables.TableNAT, KubeLoadBalancerChain}, + {utiliptables.TableNAT, KubeMarkMasqChain}, + {utiliptables.TableFilter, KubeForwardChain}, +} + +// ipsetInfo is all ipset we needed in ipvs proxier +var ipsetInfo = []struct { + name string + setType utilipset.Type + isIPv6 bool + comment string +}{ + {kubeLoopBackIPSet, utilipset.HashIPPortIP, true, kubeLoopBackIPSetComment}, + {kubeClusterIPSet, utilipset.HashIPPort, true, kubeClusterIPSetComment}, + {kubeExternalIPSet, utilipset.HashIPPort, true, kubeExternalIPSetComment}, + {kubeLoadBalancerSet, utilipset.HashIPPort, true, kubeLoadBalancerSetComment}, + {kubeLoadbalancerFWSet, utilipset.HashIPPort, true, kubeLoadbalancerFWSetComment}, + {kubeLoadBalancerLocalSet, utilipset.HashIPPort, true, kubeLoadBalancerLocalSetComment}, + {kubeLoadBalancerSourceIPSet, utilipset.HashIPPortIP, true, kubeLoadBalancerSourceIPSetComment}, + {kubeLoadBalancerSourceCIDRSet, utilipset.HashIPPortNet, true, kubeLoadBalancerSourceCIDRSetComment}, + {kubeNodePortSetTCP, utilipset.BitmapPort, false, kubeNodePortSetTCPComment}, + {kubeNodePortLocalSetTCP, utilipset.BitmapPort, false, kubeNodePortLocalSetTCPComment}, + {kubeNodePortSetUDP, utilipset.BitmapPort, false, kubeNodePortSetUDPComment}, + {kubeNodePortLocalSetUDP, utilipset.BitmapPort, false, kubeNodePortLocalSetUDPComment}, +} + +// ipsetWithIptablesChain is the ipsets list with iptables source chain and the chain jump to +// `iptables -t nat -A -m set --match-set -j ` +// example: iptables -t nat -A KUBE-SERVICES -m set --match-set KUBE-NODE-PORT-TCP dst -j KUBE-NODE-PORT +// ipsets with other match rules will be created Individually. +var ipsetWithIptablesChain = []struct { + name string + from string + to string + matchType string +}{ + {kubeLoopBackIPSet, string(kubePostroutingChain), "MASQUERADE", "dst,dst,src"}, + {kubeLoadBalancerSet, string(kubeServicesChain), string(KubeLoadBalancerChain), "dst,dst"}, + {kubeLoadbalancerFWSet, string(KubeLoadBalancerChain), string(KubeFireWallChain), "dst,dst"}, + {kubeLoadBalancerSourceCIDRSet, string(KubeFireWallChain), "RETURN", "dst,dst,src"}, + {kubeLoadBalancerSourceIPSet, string(KubeFireWallChain), "RETURN", "dst,dst,src"}, + {kubeLoadBalancerLocalSet, string(KubeLoadBalancerChain), "RETURN", "dst,dst"}, + {kubeNodePortSetTCP, string(kubeServicesChain), string(KubeNodePortChain), "dst"}, + {kubeNodePortLocalSetTCP, string(KubeNodePortChain), "RETURN", "dst"}, } var ipvsModules = []string{ @@ -124,8 +188,10 @@ type Proxier struct { syncRunner *async.BoundedFrequencyRunner // governs calls to syncProxyRules // These are effectively const and do not need the mutex to be held. - syncPeriod time.Duration - minSyncPeriod time.Duration + syncPeriod time.Duration + minSyncPeriod time.Duration + // Values are CIDR's to exclude when cleaning up IPVS rules. + excludeCIDRs []string iptables utiliptables.Interface ipvs utilipvs.Interface ipset utilipset.Interface @@ -146,30 +212,14 @@ type Proxier struct { // that are significantly impacting performance. iptablesData *bytes.Buffer natChains *bytes.Buffer + filterChains *bytes.Buffer natRules *bytes.Buffer + filterRules *bytes.Buffer // Added as a member to the struct to allow injection for testing. netlinkHandle NetLinkHandle - // loopbackSet is the ipset where stores all endpoints IP:Port,IP for solving hairpin mode purpose. - loopbackSet *IPSet - // clusterIPSet is the ipset where stores all service ClusterIP:Port - clusterIPSet *IPSet - // nodePortSetTCP is the bitmap:port type ipset where stores all TCP node port - nodePortSetTCP *IPSet - // nodePortSetTCP is the bitmap:port type ipset where stores all UDP node port - nodePortSetUDP *IPSet - // externalIPSet is the hash:ip,port type ipset where stores all service ExternalIP:Port - externalIPSet *IPSet - // lbIngressSet is the hash:ip,port type ipset where stores all service load balancer ingress IP:Port. - lbIngressSet *IPSet - // lbMasqSet is the hash:ip,port type ipset where stores all service load balancer ingress IP:Port which needs masquerade. - lbMasqSet *IPSet - // lbWhiteListIPSet is the hash:ip,port,ip type ipset where stores all service load balancer ingress IP:Port,sourceIP pair, any packets - // with the source IP visit ingress IP:Port can pass through. - lbWhiteListIPSet *IPSet - // lbWhiteListIPSet is the hash:ip,port,net type ipset where stores all service load balancer ingress IP:Port,sourceCIDR pair, any packets - // from the source CIDR visit ingress IP:Port can pass through. - lbWhiteListCIDRSet *IPSet - // Values are as a parameter to select the interfaces where nodeport works. + // ipsetList is the list of ipsets that ipvs proxier used. + ipsetList map[string]*IPSet + // Values are as a parameter to select the interfaces which nodeport works. nodePortAddresses []string // networkInterfacer defines an interface for several net library functions. // Inject for test purpose. @@ -249,6 +299,7 @@ func NewProxier(ipt utiliptables.Interface, exec utilexec.Interface, syncPeriod time.Duration, minSyncPeriod time.Duration, + excludeCIDRs []string, masqueradeAll bool, masqueradeBit int, clusterCIDR string, @@ -308,43 +359,45 @@ func NewProxier(ipt utiliptables.Interface, healthChecker := healthcheck.NewServer(hostname, recorder, nil, nil) // use default implementations of deps proxier := &Proxier{ - portsMap: make(map[utilproxy.LocalPort]utilproxy.Closeable), - serviceMap: make(proxy.ServiceMap), - serviceChanges: proxy.NewServiceChangeTracker(newServiceInfo, &isIPv6, recorder), - endpointsMap: make(proxy.EndpointsMap), - endpointsChanges: proxy.NewEndpointChangeTracker(hostname, nil, &isIPv6, recorder), - syncPeriod: syncPeriod, - minSyncPeriod: minSyncPeriod, - iptables: ipt, - masqueradeAll: masqueradeAll, - masqueradeMark: masqueradeMark, - exec: exec, - clusterCIDR: clusterCIDR, - hostname: hostname, - nodeIP: nodeIP, - portMapper: &listenPortOpener{}, - recorder: recorder, - healthChecker: healthChecker, - healthzServer: healthzServer, - ipvs: ipvs, - ipvsScheduler: scheduler, - ipGetter: &realIPGetter{nl: NewNetLinkHandle()}, - iptablesData: bytes.NewBuffer(nil), - natChains: bytes.NewBuffer(nil), - natRules: bytes.NewBuffer(nil), - netlinkHandle: NewNetLinkHandle(), - ipset: ipset, - loopbackSet: NewIPSet(ipset, KubeLoopBackIPSet, utilipset.HashIPPortIP, isIPv6), - clusterIPSet: NewIPSet(ipset, KubeClusterIPSet, utilipset.HashIPPort, isIPv6), - externalIPSet: NewIPSet(ipset, KubeExternalIPSet, utilipset.HashIPPort, isIPv6), - lbIngressSet: NewIPSet(ipset, KubeLoadBalancerSet, utilipset.HashIPPort, isIPv6), - lbMasqSet: NewIPSet(ipset, KubeLoadBalancerMasqSet, utilipset.HashIPPort, isIPv6), - lbWhiteListIPSet: NewIPSet(ipset, KubeLoadBalancerSourceIPSet, utilipset.HashIPPortIP, isIPv6), - lbWhiteListCIDRSet: NewIPSet(ipset, KubeLoadBalancerSourceCIDRSet, utilipset.HashIPPortNet, isIPv6), - nodePortSetTCP: NewIPSet(ipset, KubeNodePortSetTCP, utilipset.BitmapPort, false), - nodePortSetUDP: NewIPSet(ipset, KubeNodePortSetUDP, utilipset.BitmapPort, false), - nodePortAddresses: nodePortAddresses, - networkInterfacer: utilproxy.RealNetwork{}, + portsMap: make(map[utilproxy.LocalPort]utilproxy.Closeable), + serviceMap: make(proxy.ServiceMap), + serviceChanges: proxy.NewServiceChangeTracker(newServiceInfo, &isIPv6, recorder), + endpointsMap: make(proxy.EndpointsMap), + endpointsChanges: proxy.NewEndpointChangeTracker(hostname, nil, &isIPv6, recorder), + syncPeriod: syncPeriod, + minSyncPeriod: minSyncPeriod, + excludeCIDRs: excludeCIDRs, + iptables: ipt, + masqueradeAll: masqueradeAll, + masqueradeMark: masqueradeMark, + exec: exec, + clusterCIDR: clusterCIDR, + hostname: hostname, + nodeIP: nodeIP, + portMapper: &listenPortOpener{}, + recorder: recorder, + healthChecker: healthChecker, + healthzServer: healthzServer, + ipvs: ipvs, + ipvsScheduler: scheduler, + ipGetter: &realIPGetter{nl: NewNetLinkHandle()}, + iptablesData: bytes.NewBuffer(nil), + natChains: bytes.NewBuffer(nil), + natRules: bytes.NewBuffer(nil), + filterChains: bytes.NewBuffer(nil), + filterRules: bytes.NewBuffer(nil), + netlinkHandle: NewNetLinkHandle(), + ipset: ipset, + nodePortAddresses: nodePortAddresses, + networkInterfacer: utilproxy.RealNetwork{}, + } + // initialize ipsetList with all sets we needed + proxier.ipsetList = make(map[string]*IPSet) + for _, is := range ipsetInfo { + if is.isIPv6 { + proxier.ipsetList[is.name] = NewIPSet(ipset, is.name, is.setType, isIPv6, is.comment) + } + proxier.ipsetList[is.name] = NewIPSet(ipset, is.name, is.setType, false, is.comment) } burstSyncs := 2 glog.V(3).Infof("minSyncPeriod: %v, syncPeriod: %v, burstSyncs: %d", minSyncPeriod, syncPeriod, burstSyncs) @@ -390,6 +443,25 @@ func NewLinuxKernelHandler() *LinuxKernelHandler { // GetModules returns all installed kernel modules. func (handle *LinuxKernelHandler) GetModules() ([]string, error) { + // Check whether IPVS required kernel modules are built-in + kernelVersionFile := "/proc/sys/kernel/osrelease" + b, err := ioutil.ReadFile(kernelVersionFile) + if err != nil { + glog.Errorf("Failed to read file %s with error %v", kernelVersionFile, err) + } + kernelVersion := strings.TrimSpace(string(b)) + builtinModsFilePath := fmt.Sprintf("/lib/modules/%s/modules.builtin", kernelVersion) + b, err = ioutil.ReadFile(builtinModsFilePath) + if err != nil { + glog.Errorf("Failed to read file %s with error %v", builtinModsFilePath, err) + } + var bmods []string + for _, module := range ipvsModules { + if match, _ := regexp.Match(module+".ko", b); match { + bmods = append(bmods, module) + } + } + // Try to load IPVS required kernel modules using modprobe first for _, kmod := range ipvsModules { err := handle.executor.Command("modprobe", "--", kmod).Run() @@ -406,7 +478,7 @@ func (handle *LinuxKernelHandler) GetModules() ([]string, error) { } mods := strings.Split(string(out), "\n") - return mods, nil + return append(mods, bmods...), nil } // CanUseIPVSProxier returns true if we can use the ipvs Proxier. @@ -441,52 +513,44 @@ func CanUseIPVSProxier(handle KernelHandler, ipsetver IPSetVersioner) (bool, err // CleanupIptablesLeftovers removes all iptables rules and chains created by the Proxier // It returns true if an error was encountered. Errors are logged. func cleanupIptablesLeftovers(ipt utiliptables.Interface) (encounteredError bool) { - // Unlink the services chain. - args := []string{ - "-m", "comment", "--comment", "kubernetes service portals", - "-j", string(kubeServicesChain), - } - for _, tc := range tableChainsWithJumpService { - if err := ipt.DeleteRule(tc.table, tc.chain, args...); err != nil { + // Unlink the iptables chains created by ipvs Proxier + for _, jc := range iptablesJumpChain { + args := []string{ + "-m", "comment", "--comment", jc.comment, + "-j", string(jc.to), + } + if err := ipt.DeleteRule(jc.table, jc.from, args...); err != nil { if !utiliptables.IsNotFoundError(err) { - glog.Errorf("Error removing pure-iptables proxy rule: %v", err) + glog.Errorf("Error removing iptables rules in ipvs proxier: %v", err) encounteredError = true } } } - // Unlink the postrouting chain. - args = []string{ - "-m", "comment", "--comment", "kubernetes postrouting rules", - "-j", string(kubePostroutingChain), - } - if err := ipt.DeleteRule(utiliptables.TableNAT, utiliptables.ChainPostrouting, args...); err != nil { - if !utiliptables.IsNotFoundError(err) { - glog.Errorf("Error removing ipvs Proxier iptables rule: %v", err) - encounteredError = true - } - } - // Flush and remove all of our chains. - for _, chain := range []utiliptables.Chain{kubeServicesChain, kubePostroutingChain} { - if err := ipt.FlushChain(utiliptables.TableNAT, chain); err != nil { + for _, ch := range iptablesChains { + if err := ipt.FlushChain(ch.table, ch.chain); err != nil { if !utiliptables.IsNotFoundError(err) { - glog.Errorf("Error removing ipvs Proxier iptables rule: %v", err) + glog.Errorf("Error removing iptables rules in ipvs proxier: %v", err) encounteredError = true } } - if err := ipt.DeleteChain(utiliptables.TableNAT, chain); err != nil { + if err := ipt.DeleteChain(ch.table, ch.chain); err != nil { if !utiliptables.IsNotFoundError(err) { - glog.Errorf("Error removing ipvs Proxier iptables rule: %v", err) + glog.Errorf("Error removing iptables rules in ipvs proxier: %v", err) encounteredError = true } } } + return encounteredError } // CleanupLeftovers clean up all ipvs and iptables rules created by ipvs Proxier. func CleanupLeftovers(ipvs utilipvs.Interface, ipt utiliptables.Interface, ipset utilipset.Interface, cleanupIPVS bool) (encounteredError bool) { + if canUse, _ := CanUseIPVSProxier(NewLinuxKernelHandler(), ipset); !canUse { + return false + } if cleanupIPVS { // Return immediately when ipvs interface is nil - Probably initialization failed in somewhere. if ipvs == nil { @@ -510,10 +574,8 @@ func CleanupLeftovers(ipvs utilipvs.Interface, ipt utiliptables.Interface, ipset encounteredError = cleanupIptablesLeftovers(ipt) || encounteredError // Destroy ip sets created by ipvs Proxier. We should call it after cleaning up // iptables since we can NOT delete ip set which is still referenced by iptables. - ipSetsToDestroy := []string{KubeLoopBackIPSet, KubeClusterIPSet, KubeLoadBalancerSet, KubeNodePortSetTCP, KubeNodePortSetUDP, - KubeExternalIPSet, KubeLoadBalancerSourceIPSet, KubeLoadBalancerSourceCIDRSet, KubeLoadBalancerMasqSet} - for _, set := range ipSetsToDestroy { - err = ipset.DestroySet(set) + for _, set := range ipsetInfo { + err = ipset.DestroySet(set.name) if err != nil { if !utilipset.IsNotFoundError(err) { glog.Errorf("Error removing ipset %s, error: %v", set, err) @@ -599,8 +661,10 @@ func (proxier *Proxier) OnEndpointsDelete(endpoints *api.Endpoints) { func (proxier *Proxier) OnEndpointsSynced() { proxier.mu.Lock() proxier.endpointsSynced = true + proxier.setInitialized(proxier.servicesSynced && proxier.endpointsSynced) proxier.mu.Unlock() + // Sync unconditionally - this is called once per lifetime. proxier.syncProxyRules() } @@ -641,70 +705,32 @@ func (proxier *Proxier) syncProxyRules() { glog.V(3).Infof("Syncing ipvs Proxier rules") - // TODO: UT output result // Begin install iptables - // Get iptables-save output so we can check for existing chains and rules. - // This will be a map of chain name to chain with rules as stored in iptables-save/iptables-restore - existingNATChains := make(map[utiliptables.Chain]string) - proxier.iptablesData.Reset() - err := proxier.iptables.SaveInto(utiliptables.TableNAT, proxier.iptablesData) - if err != nil { // if we failed to get any rules - glog.Errorf("Failed to execute iptables-save, syncing all rules: %v", err) - } else { // otherwise parse the output - existingNATChains = utiliptables.GetChainLines(utiliptables.TableNAT, proxier.iptablesData.Bytes()) - } + // Reset all buffers used later. // This is to avoid memory reallocations and thus improve performance. proxier.natChains.Reset() proxier.natRules.Reset() + // Write table headers. + writeLine(proxier.filterChains, "*filter") writeLine(proxier.natChains, "*nat") - // Make sure we keep stats for the top-level chains, if they existed - // (which most should have because we created them above). - if chain, ok := existingNATChains[kubePostroutingChain]; ok { - writeLine(proxier.natChains, chain) - } else { - writeLine(proxier.natChains, utiliptables.MakeChainLine(kubePostroutingChain)) - } - // Install the kubernetes-specific postrouting rules. We use a whole chain for - // this so that it is easier to flush and change, for example if the mark - // value should ever change. - writeLine(proxier.natRules, []string{ - "-A", string(kubePostroutingChain), - "-m", "comment", "--comment", `"kubernetes service traffic requiring SNAT"`, - "-m", "mark", "--mark", proxier.masqueradeMark, - "-j", "MASQUERADE", - }...) - if chain, ok := existingNATChains[KubeMarkMasqChain]; ok { - writeLine(proxier.natChains, chain) - } else { - writeLine(proxier.natChains, utiliptables.MakeChainLine(KubeMarkMasqChain)) - } - // Install the kubernetes-specific masquerade mark rule. We use a whole chain for - // this so that it is easier to flush and change, for example if the mark - // value should ever change. - writeLine(proxier.natRules, []string{ - "-A", string(KubeMarkMasqChain), - "-j", "MARK", "--set-xmark", proxier.masqueradeMark, - }...) - // End install iptables + proxier.createAndLinkeKubeChain() // make sure dummy interface exists in the system where ipvs Proxier will bind service address on it - _, err = proxier.netlinkHandle.EnsureDummyDevice(DefaultDummyDevice) + _, err := proxier.netlinkHandle.EnsureDummyDevice(DefaultDummyDevice) if err != nil { glog.Errorf("Failed to create dummy interface: %s, error: %v", DefaultDummyDevice, err) return } // make sure ip sets exists in the system. - ipSets := []*IPSet{proxier.loopbackSet, proxier.clusterIPSet, proxier.externalIPSet, proxier.nodePortSetUDP, proxier.nodePortSetTCP, - proxier.lbIngressSet, proxier.lbMasqSet, proxier.lbWhiteListCIDRSet, proxier.lbWhiteListIPSet} - if err := ensureIPSets(ipSets...); err != nil { - return - } - for i := range ipSets { - ipSets[i].resetEntries() + for _, set := range proxier.ipsetList { + if err := ensureIPSet(set); err != nil { + return + } + set.resetEntries() } // Accumulate the set of local ports that we will be holding open once this update is complete @@ -714,29 +740,6 @@ func (proxier *Proxier) syncProxyRules() { // currentIPVSServices represent IPVS services listed from the system currentIPVSServices := make(map[string]*utilipvs.VirtualServer) - // We are creating those slices ones here to avoid memory reallocations - // in every loop. Note that reuse the memory, instead of doing: - // slice = - // you should always do one of the below: - // slice = slice[:0] // and then append to it - // slice = append(slice[:0], ...) - // To avoid growing this slice, we arbitrarily set its size to 64, - // there is never more than that many arguments for a single line. - // Note that even if we go over 64, it will still be correct - it - // is just for efficiency, not correctness. - args := make([]string, 64) - - // Kube service portal - if err := proxier.linkKubeServiceChain(existingNATChains, proxier.natChains); err != nil { - glog.Errorf("Failed to link KUBE-SERVICES chain: %v", err) - return - } - // Kube service ipset - if err := proxier.createKubeFireWallChain(existingNATChains, proxier.natChains); err != nil { - glog.Errorf("Failed to create KUBE-FIRE-WALL chain: %v", err) - return - } - // Build IPVS rules for each service. for svcName, svc := range proxier.serviceMap { svcInfo, ok := svc.(*serviceInfo) @@ -769,11 +772,11 @@ func (proxier *Proxier) syncProxyRules() { IP2: epIP, SetType: utilipset.HashIPPortIP, } - if valid := proxier.loopbackSet.validateEntry(entry); !valid { - glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.loopbackSet.Name)) + if valid := proxier.ipsetList[kubeLoopBackIPSet].validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeLoopBackIPSet].Name)) continue } - proxier.loopbackSet.activeEntries.Insert(entry.String()) + proxier.ipsetList[kubeLoopBackIPSet].activeEntries.Insert(entry.String()) } // Capture the clusterIP. @@ -786,14 +789,11 @@ func (proxier *Proxier) syncProxyRules() { } // add service Cluster IP:Port to kubeServiceAccess ip set for the purpose of solving hairpin. // proxier.kubeServiceAccessSet.activeEntries.Insert(entry.String()) - // Install masquerade rules if 'masqueradeAll' or 'clusterCIDR' is specified. - if proxier.masqueradeAll || len(proxier.clusterCIDR) > 0 { - if valid := proxier.clusterIPSet.validateEntry(entry); !valid { - glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.clusterIPSet.Name)) - continue - } - proxier.clusterIPSet.activeEntries.Insert(entry.String()) + if valid := proxier.ipsetList[kubeClusterIPSet].validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeClusterIPSet].Name)) + continue } + proxier.ipsetList[kubeClusterIPSet].activeEntries.Insert(entry.String()) // ipvs call serv := &utilipvs.VirtualServer{ Address: svcInfo.ClusterIP, @@ -859,11 +859,11 @@ func (proxier *Proxier) syncProxyRules() { SetType: utilipset.HashIPPort, } // We have to SNAT packets to external IPs. - if valid := proxier.externalIPSet.validateEntry(entry); !valid { - glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.externalIPSet.Name)) + if valid := proxier.ipsetList[kubeExternalIPSet].validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeExternalIPSet].Name)) continue } - proxier.externalIPSet.activeEntries.Insert(entry.String()) + proxier.ipsetList[kubeExternalIPSet].activeEntries.Insert(entry.String()) // ipvs call serv := &utilipvs.VirtualServer{ @@ -876,10 +876,9 @@ func (proxier *Proxier) syncProxyRules() { serv.Flags |= utilipvs.FlagPersistent serv.Timeout = uint32(svcInfo.StickyMaxAgeSeconds) } - // There is no need to bind externalIP to dummy interface, so set parameter `bindAddr` to `false`. - if err := proxier.syncService(svcNameString, serv, false); err == nil { + if err := proxier.syncService(svcNameString, serv, true); err == nil { activeIPVSServices[serv.String()] = true - if err := proxier.syncEndpoint(svcName, svcInfo.OnlyNodeLocalEndpoints, serv); err != nil { + if err := proxier.syncEndpoint(svcName, false, serv); err != nil { glog.Errorf("Failed to sync endpoint for service: %v, err: %v", serv, err) } } else { @@ -901,23 +900,28 @@ func (proxier *Proxier) syncProxyRules() { // proxier.kubeServiceAccessSet.activeEntries.Insert(entry.String()) // If we are proxying globally, we need to masquerade in case we cross nodes. // If we are proxying only locally, we can retain the source IP. - if !svcInfo.OnlyNodeLocalEndpoints { - if valid := proxier.lbMasqSet.validateEntry(entry); !valid { - glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.lbMasqSet.Name)) + if valid := proxier.ipsetList[kubeLoadBalancerSet].validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeLoadBalancerSet].Name)) + continue + } + proxier.ipsetList[kubeLoadBalancerSet].activeEntries.Insert(entry.String()) + // insert loadbalancer entry to lbIngressLocalSet if service externaltrafficpolicy=local + if svcInfo.OnlyNodeLocalEndpoints { + if valid := proxier.ipsetList[kubeLoadBalancerLocalSet].validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeLoadBalancerLocalSet].Name)) continue } - proxier.lbMasqSet.activeEntries.Insert(entry.String()) + proxier.ipsetList[kubeLoadBalancerLocalSet].activeEntries.Insert(entry.String()) } if len(svcInfo.LoadBalancerSourceRanges) != 0 { // The service firewall rules are created based on ServiceSpec.loadBalancerSourceRanges field. // This currently works for loadbalancers that preserves source ips. // For loadbalancers which direct traffic to service NodePort, the firewall rules will not apply. - if valid := proxier.lbIngressSet.validateEntry(entry); !valid { - glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.lbIngressSet.Name)) + if valid := proxier.ipsetList[kubeLoadbalancerFWSet].validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeLoadbalancerFWSet].Name)) continue } - proxier.lbIngressSet.activeEntries.Insert(entry.String()) - + proxier.ipsetList[kubeLoadbalancerFWSet].activeEntries.Insert(entry.String()) allowFromNode := false for _, src := range svcInfo.LoadBalancerSourceRanges { // ipset call @@ -929,11 +933,11 @@ func (proxier *Proxier) syncProxyRules() { SetType: utilipset.HashIPPortNet, } // enumerate all white list source cidr - if valid := proxier.lbWhiteListCIDRSet.validateEntry(entry); !valid { - glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.lbWhiteListCIDRSet.Name)) + if valid := proxier.ipsetList[kubeLoadBalancerSourceCIDRSet].validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeLoadBalancerSourceCIDRSet].Name)) continue } - proxier.lbWhiteListCIDRSet.activeEntries.Insert(entry.String()) + proxier.ipsetList[kubeLoadBalancerSourceCIDRSet].activeEntries.Insert(entry.String()) // ignore error because it has been validated _, cidr, _ := net.ParseCIDR(src) @@ -953,11 +957,11 @@ func (proxier *Proxier) syncProxyRules() { SetType: utilipset.HashIPPortIP, } // enumerate all white list source ip - if valid := proxier.lbWhiteListIPSet.validateEntry(entry); !valid { - glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.lbWhiteListIPSet.Name)) + if valid := proxier.ipsetList[kubeLoadBalancerSourceIPSet].validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeLoadBalancerSourceIPSet].Name)) continue } - proxier.lbWhiteListIPSet.activeEntries.Insert(entry.String()) + proxier.ipsetList[kubeLoadBalancerSourceIPSet].activeEntries.Insert(entry.String()) } } @@ -972,10 +976,11 @@ func (proxier *Proxier) syncProxyRules() { serv.Flags |= utilipvs.FlagPersistent serv.Timeout = uint32(svcInfo.StickyMaxAgeSeconds) } - // There is no need to bind LB ingress.IP to dummy interface, so set parameter `bindAddr` to `false`. - if err := proxier.syncService(svcNameString, serv, false); err == nil { + if err := proxier.syncService(svcNameString, serv, true); err == nil { + // check if service need skip endpoints that not in same host as kube-proxy + onlyLocal := svcInfo.SessionAffinityType == api.ServiceAffinityClientIP && svcInfo.OnlyNodeLocalEndpoints activeIPVSServices[serv.String()] = true - if err := proxier.syncEndpoint(svcName, svcInfo.OnlyNodeLocalEndpoints, serv); err != nil { + if err := proxier.syncEndpoint(svcName, onlyLocal, serv); err != nil { glog.Errorf("Failed to sync endpoint for service: %v, err: %v", serv, err) } } else { @@ -985,64 +990,98 @@ func (proxier *Proxier) syncProxyRules() { } if svcInfo.NodePort != 0 { - lp := utilproxy.LocalPort{ - Description: "nodePort for " + svcNameString, - IP: "", - Port: svcInfo.NodePort, - Protocol: protocol, + addresses, err := utilproxy.GetNodeAddresses(proxier.nodePortAddresses, proxier.networkInterfacer) + if err != nil { + glog.Errorf("Failed to get node ip address matching nodeport cidr: %v", err) + continue } - if proxier.portsMap[lp] != nil { - glog.V(4).Infof("Port %s was open before and is still needed", lp.String()) - replacementPortsMap[lp] = proxier.portsMap[lp] - } else { - socket, err := proxier.portMapper.OpenLocalPort(&lp) - if err != nil { - glog.Errorf("can't open %s, skipping this nodePort: %v", lp.String(), err) - continue + + lps := make([]utilproxy.LocalPort, 0) + for address := range addresses { + lp := utilproxy.LocalPort{ + Description: "nodePort for " + svcNameString, + IP: address, + Port: svcInfo.NodePort, + Protocol: protocol, } - if lp.Protocol == "udp" { - isIPv6 := utilnet.IsIPv6(svcInfo.ClusterIP) - conntrack.ClearEntriesForPort(proxier.exec, lp.Port, isIPv6, clientv1.ProtocolUDP) + if utilproxy.IsZeroCIDR(address) { + // Empty IP address means all + lp.IP = "" + lps = append(lps, lp) + // If we encounter a zero CIDR, then there is no point in processing the rest of the addresses. + break } - replacementPortsMap[lp] = socket - } // We're holding the port, so it's OK to install ipvs rules. + lps = append(lps, lp) + } + + // For ports on node IPs, open the actual port and hold it. + for _, lp := range lps { + if proxier.portsMap[lp] != nil { + glog.V(4).Infof("Port %s was open before and is still needed", lp.String()) + replacementPortsMap[lp] = proxier.portsMap[lp] + } else { + socket, err := proxier.portMapper.OpenLocalPort(&lp) + if err != nil { + glog.Errorf("can't open %s, skipping this nodePort: %v", lp.String(), err) + continue + } + if lp.Protocol == "udp" { + isIPv6 := utilnet.IsIPv6(svcInfo.ClusterIP) + conntrack.ClearEntriesForPort(proxier.exec, lp.Port, isIPv6, clientv1.ProtocolUDP) + } + replacementPortsMap[lp] = socket + } // We're holding the port, so it's OK to install ipvs rules. + } // Nodeports need SNAT, unless they're local. // ipset call - if !svcInfo.OnlyNodeLocalEndpoints { - entry = &utilipset.Entry{ - // No need to provide ip info - Port: svcInfo.NodePort, - Protocol: protocol, - SetType: utilipset.BitmapPort, + entry = &utilipset.Entry{ + // No need to provide ip info + Port: svcInfo.NodePort, + Protocol: protocol, + SetType: utilipset.BitmapPort, + } + var nodePortSet *IPSet + switch protocol { + case "tcp": + nodePortSet = proxier.ipsetList[kubeNodePortSetTCP] + case "udp": + nodePortSet = proxier.ipsetList[kubeNodePortSetUDP] + default: + // It should never hit + glog.Errorf("Unsupported protocol type: %s", protocol) + } + if nodePortSet != nil { + if valid := nodePortSet.validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, nodePortSet.Name)) + continue } - var nodePortSet *IPSet - switch protocol { + nodePortSet.activeEntries.Insert(entry.String()) + } + // Add externaltrafficpolicy=local type nodeport entry + if svcInfo.OnlyNodeLocalEndpoints { + var nodePortLocalSet *IPSet + switch protocol { case "tcp": - nodePortSet = proxier.nodePortSetTCP + nodePortLocalSet = proxier.ipsetList[kubeNodePortLocalSetTCP] case "udp": - nodePortSet = proxier.nodePortSetUDP + nodePortLocalSet = proxier.ipsetList[kubeNodePortLocalSetUDP] default: // It should never hit glog.Errorf("Unsupported protocol type: %s", protocol) } - if nodePortSet != nil { - if valid := nodePortSet.validateEntry(entry); !valid { - glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, nodePortSet.Name)) + if nodePortLocalSet != nil { + if valid := nodePortLocalSet.validateEntry(entry); !valid { + glog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, nodePortLocalSet.Name)) continue } - nodePortSet.activeEntries.Insert(entry.String()) + nodePortLocalSet.activeEntries.Insert(entry.String()) } } // Build ipvs kernel routes for each node ip address nodeIPs := make([]net.IP, 0) - addresses, err := utilproxy.GetNodeAddresses(proxier.nodePortAddresses, proxier.networkInterfacer) - if err != nil { - glog.Errorf("Failed to get node ip address matching nodeport cidr") - continue - } for address := range addresses { if !utilproxy.IsZeroCIDR(address) { nodeIPs = append(nodeIPs, net.ParseIP(address)) @@ -1069,7 +1108,7 @@ func (proxier *Proxier) syncProxyRules() { // There is no need to bind Node IP to dummy interface, so set parameter `bindAddr` to `false`. if err := proxier.syncService(svcNameString, serv, false); err == nil { activeIPVSServices[serv.String()] = true - if err := proxier.syncEndpoint(svcName, svcInfo.OnlyNodeLocalEndpoints, serv); err != nil { + if err := proxier.syncEndpoint(svcName, false, serv); err != nil { glog.Errorf("Failed to sync endpoint for service: %v, err: %v", serv, err) } } else { @@ -1080,44 +1119,134 @@ func (proxier *Proxier) syncProxyRules() { } // sync ipset entries - ipsetsToSync := []*IPSet{proxier.loopbackSet, proxier.clusterIPSet, proxier.lbIngressSet, proxier.lbMasqSet, proxier.nodePortSetTCP, - proxier.nodePortSetUDP, proxier.externalIPSet, proxier.lbWhiteListIPSet, proxier.lbWhiteListCIDRSet} - for i := range ipsetsToSync { - ipsetsToSync[i].syncIPSetEntries() + for _, set := range proxier.ipsetList { + set.syncIPSetEntries() } // Tail call iptables rules for ipset, make sure only call iptables once // in a single loop per ip set. - if !proxier.loopbackSet.isEmpty() { - args = append(args[:0], - "-A", string(kubePostroutingChain), - "-m", "set", "--match-set", proxier.loopbackSet.Name, - "dst,dst,src", - ) - writeLine(proxier.natRules, append(args, "-j", "MASQUERADE")...) + proxier.writeIptablesRules() + + // Sync iptables rules. + // NOTE: NoFlushTables is used so we don't flush non-kubernetes chains in the table. + proxier.iptablesData.Reset() + proxier.iptablesData.Write(proxier.natChains.Bytes()) + proxier.iptablesData.Write(proxier.natRules.Bytes()) + + glog.V(5).Infof("Restoring iptables rules: %s", proxier.iptablesData.Bytes()) + err = proxier.iptables.RestoreAll(proxier.iptablesData.Bytes(), utiliptables.NoFlushTables, utiliptables.RestoreCounters) + if err != nil { + glog.Errorf("Failed to execute iptables-restore: %v\nRules:\n%s", err, proxier.iptablesData.Bytes()) + // Revert new local ports. + utilproxy.RevertPorts(replacementPortsMap, proxier.portsMap) + return + } + + // Close old local ports and save new ones. + for k, v := range proxier.portsMap { + if replacementPortsMap[k] == nil { + v.Close() + } + } + proxier.portsMap = replacementPortsMap + + // Clean up legacy IPVS services + appliedSvcs, err := proxier.ipvs.GetVirtualServers() + if err == nil { + for _, appliedSvc := range appliedSvcs { + currentIPVSServices[appliedSvc.String()] = appliedSvc + } + } else { + glog.Errorf("Failed to get ipvs service, err: %v", err) + } + proxier.cleanLegacyService(activeIPVSServices, currentIPVSServices) + + // Update healthz timestamp + if proxier.healthzServer != nil { + proxier.healthzServer.UpdateTimestamp() + } + + // Update healthchecks. The endpoints list might include services that are + // not "OnlyLocal", but the services list will not, and the healthChecker + // will just drop those endpoints. + if err := proxier.healthChecker.SyncServices(serviceUpdateResult.HCServiceNodePorts); err != nil { + glog.Errorf("Error syncing healtcheck services: %v", err) } - if !proxier.clusterIPSet.isEmpty() { + if err := proxier.healthChecker.SyncEndpoints(endpointUpdateResult.HCEndpointsLocalIPSize); err != nil { + glog.Errorf("Error syncing healthcheck endpoints: %v", err) + } + + // Finish housekeeping. + // TODO: these could be made more consistent. + for _, svcIP := range staleServices.UnsortedList() { + if err := conntrack.ClearEntriesForIP(proxier.exec, svcIP, clientv1.ProtocolUDP); err != nil { + glog.Errorf("Failed to delete stale service IP %s connections, error: %v", svcIP, err) + } + } + proxier.deleteEndpointConnections(endpointUpdateResult.StaleEndpoints) +} + +// writeIptablesRules write all iptables rules to proxier.natRules or proxier.FilterRules that ipvs proxier needed +// according to proxier.ipsetList information and the ipset match relationship that `ipsetWithIptablesChain` specified. +// some ipset(kubeClusterIPSet for example) have particular match rules and iptables jump relation should be sync separately. +func (proxier *Proxier) writeIptablesRules() { + // We are creating those slices ones here to avoid memory reallocations + // in every loop. Note that reuse the memory, instead of doing: + // slice = + // you should always do one of the below: + // slice = slice[:0] // and then append to it + // slice = append(slice[:0], ...) + // To avoid growing this slice, we arbitrarily set its size to 64, + // there is never more than that many arguments for a single line. + // Note that even if we go over 64, it will still be correct - it + // is just for efficiency, not correctness. + args := make([]string, 64) + + for _, set := range ipsetWithIptablesChain { + if _, find := proxier.ipsetList[set.name]; find && !proxier.ipsetList[set.name].isEmpty() { + args = append(args[:0], + "-A", set.from, + "-m", "comment", "--comment", proxier.ipsetList[set.name].getComment(), + "-m", "set", "--match-set", set.name, + set.matchType, + ) + writeLine(proxier.natRules, append(args, "-j", set.to)...) + } + } + + if !proxier.ipsetList[kubeClusterIPSet].isEmpty() { args = append(args[:0], "-A", string(kubeServicesChain), - "-m", "set", "--match-set", proxier.clusterIPSet.Name, - "dst,dst", + "-m", "comment", "--comment", proxier.ipsetList[kubeClusterIPSet].getComment(), + "-m", "set", "--match-set", kubeClusterIPSet, ) if proxier.masqueradeAll { - writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...) + writeLine(proxier.natRules, append(args, "dst,dst", "-j", string(KubeMarkMasqChain))...) } else if len(proxier.clusterCIDR) > 0 { // This masquerades off-cluster traffic to a service VIP. The idea // is that you can establish a static route for your Service range, // routing to any node, and that node will bridge into the Service // for you. Since that might bounce off-node, we masquerade here. // If/when we support "Local" policy for VIPs, we should update this. - writeLine(proxier.natRules, append(args, "! -s", proxier.clusterCIDR, "-j", string(KubeMarkMasqChain))...) + writeLine(proxier.natRules, append(args, "dst,dst", "! -s", proxier.clusterCIDR, "-j", string(KubeMarkMasqChain))...) + } else { + // Masquerade all OUTPUT traffic coming from a service ip. + // The kube dummy interface has all service VIPs assigned which + // results in the service VIP being picked as the source IP to reach + // a VIP. This leads to a connection from VIP: to + // VIP:. + // Always masquerading OUTPUT (node-originating) traffic with a VIP + // source ip and service port destination fixes the outgoing connections. + writeLine(proxier.natRules, append(args, "src,dst", "-j", string(KubeMarkMasqChain))...) } } - if !proxier.externalIPSet.isEmpty() { + + if !proxier.ipsetList[kubeExternalIPSet].isEmpty() { // Build masquerade rules for packets to external IPs. args = append(args[:0], "-A", string(kubeServicesChain), - "-m", "set", "--match-set", proxier.externalIPSet.Name, + "-m", "comment", "--comment", proxier.ipsetList[kubeExternalIPSet].getComment(), + "-m", "set", "--match-set", kubeExternalIPSet, "dst,dst", ) writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...) @@ -1134,124 +1263,180 @@ func (proxier *Proxier) syncProxyRules() { // This covers cases like GCE load-balancers which get added to the local routing table. writeLine(proxier.natRules, append(dstLocalOnlyArgs, "-j", "ACCEPT")...) } - if !proxier.lbMasqSet.isEmpty() { - // Build masquerade rules for packets which cross node visit load balancer ingress IPs. + + if !proxier.ipsetList[kubeNodePortSetUDP].isEmpty() { + // accept for nodeports w/ externaltrafficpolicy=local args = append(args[:0], "-A", string(kubeServicesChain), - "-m", "set", "--match-set", proxier.lbMasqSet.Name, - "dst,dst", + "-m", "udp", "-p", "udp", + "-m", "comment", "--comment", proxier.ipsetList[kubeNodePortSetUDP].getComment(), + "-m", "set", "--match-set", kubeNodePortSetUDP, + "dst", ) - writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...) - } - if !proxier.lbWhiteListCIDRSet.isEmpty() || !proxier.lbWhiteListIPSet.isEmpty() { - // link kube-services chain -> kube-fire-wall chain - args := []string{"-m", "set", "--match-set", proxier.lbIngressSet.Name, "dst,dst", "-j", string(KubeFireWallChain)} - if _, err := proxier.iptables.EnsureRule(utiliptables.Append, utiliptables.TableNAT, kubeServicesChain, args...); err != nil { - glog.Errorf("Failed to ensure that ipset %s chain %s jumps to %s: %v", proxier.lbIngressSet.Name, kubeServicesChain, KubeFireWallChain, err) - } - if !proxier.lbWhiteListCIDRSet.isEmpty() { + writeLine(proxier.natRules, append(args, "-j", string(KubeNodePortChain))...) + if !proxier.ipsetList[kubeNodePortLocalSetUDP].isEmpty() { args = append(args[:0], - "-A", string(KubeFireWallChain), - "-m", "set", "--match-set", proxier.lbWhiteListCIDRSet.Name, - "dst,dst,src", - ) - writeLine(proxier.natRules, append(args, "-j", "ACCEPT")...) - } - if !proxier.lbWhiteListIPSet.isEmpty() { - args = append(args[:0], - "-A", string(KubeFireWallChain), - "-m", "set", "--match-set", proxier.lbWhiteListIPSet.Name, - "dst,dst,src", + "-A", string(KubeNodePortChain), + "-m", "comment", "--comment", proxier.ipsetList[kubeNodePortLocalSetUDP].getComment(), + "-m", "set", "--match-set", kubeNodePortLocalSetUDP, + "dst", ) writeLine(proxier.natRules, append(args, "-j", "ACCEPT")...) } + // mark masq for others args = append(args[:0], - "-A", string(KubeFireWallChain), - ) - // If the packet was able to reach the end of firewall chain, then it did not get DNATed. - // It means the packet cannot go thru the firewall, then mark it for DROP - writeLine(proxier.natRules, append(args, "-j", string(KubeMarkDropChain))...) - } - if !proxier.nodePortSetTCP.isEmpty() { - // Build masquerade rules for packets which cross node visit nodeport. - args = append(args[:0], - "-A", string(kubeServicesChain), - "-m", "tcp", "-p", "tcp", - "-m", "set", "--match-set", proxier.nodePortSetTCP.Name, - "dst", + "-A", string(KubeNodePortChain), + "-m", "comment", "--comment", + fmt.Sprintf(`"mark MASQ for externaltrafficpolicy=cluster"`), ) writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...) } - if !proxier.nodePortSetUDP.isEmpty() { - args = append(args[:0], - "-A", string(kubeServicesChain), - "-m", "udp", "-p", "udp", - "-m", "set", "--match-set", proxier.nodePortSetUDP.Name, - "dst", + + // mark masq for KUBE-NODE-PORT + writeLine(proxier.natRules, []string{ + "-A", string(KubeNodePortChain), + "-j", string(KubeMarkMasqChain), + }...) + + // mark drop for KUBE-LOAD-BALANCER + writeLine(proxier.natRules, []string{ + "-A", string(KubeLoadBalancerChain), + "-j", string(KubeMarkMasqChain), + }...) + + // mark drop for KUBE-FIRE-WALL + writeLine(proxier.natRules, []string{ + "-A", string(KubeFireWallChain), + "-j", string(KubeMarkDropChain), + }...) + + // Accept all traffic with destination of ipvs virtual service, in case other iptables rules + // block the traffic, that may result in ipvs rules invalid. + // Those rules must be in the end of KUBE-SERVICE chain + proxier.acceptIPVSTraffic() + + // If the masqueradeMark has been added then we want to forward that same + // traffic, this allows NodePort traffic to be forwarded even if the default + // FORWARD policy is not accept. + writeLine(proxier.filterRules, + "-A", string(KubeForwardChain), + "-m", "comment", "--comment", `"kubernetes forwarding rules"`, + "-m", "mark", "--mark", proxier.masqueradeMark, + "-j", "ACCEPT", + ) + + // The following rules can only be set if clusterCIDR has been defined. + if len(proxier.clusterCIDR) != 0 { + // The following two rules ensure the traffic after the initial packet + // accepted by the "kubernetes forwarding rules" rule above will be + // accepted, to be as specific as possible the traffic must be sourced + // or destined to the clusterCIDR (to/from a pod). + writeLine(proxier.filterRules, + "-A", string(KubeForwardChain), + "-s", proxier.clusterCIDR, + "-m", "comment", "--comment", `"kubernetes forwarding conntrack pod source rule"`, + "-m", "conntrack", + "--ctstate", "RELATED,ESTABLISHED", + "-j", "ACCEPT", + ) + writeLine(proxier.filterRules, + "-A", string(KubeForwardChain), + "-m", "comment", "--comment", `"kubernetes forwarding conntrack pod destination rule"`, + "-d", proxier.clusterCIDR, + "-m", "conntrack", + "--ctstate", "RELATED,ESTABLISHED", + "-j", "ACCEPT", ) - writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...) } // Write the end-of-table markers. + writeLine(proxier.filterRules, "COMMIT") writeLine(proxier.natRules, "COMMIT") +} - // Sync iptables rules. - // NOTE: NoFlushTables is used so we don't flush non-kubernetes chains in the table. - proxier.iptablesData.Reset() - proxier.iptablesData.Write(proxier.natChains.Bytes()) - proxier.iptablesData.Write(proxier.natRules.Bytes()) - - glog.V(5).Infof("Restoring iptables rules: %s", proxier.iptablesData.Bytes()) - err = proxier.iptables.RestoreAll(proxier.iptablesData.Bytes(), utiliptables.NoFlushTables, utiliptables.RestoreCounters) - if err != nil { - glog.Errorf("Failed to execute iptables-restore: %v\nRules:\n%s", err, proxier.iptablesData.Bytes()) - // Revert new local ports. - utilproxy.RevertPorts(replacementPortsMap, proxier.portsMap) - return +func (proxier *Proxier) acceptIPVSTraffic() { + sets := []string{kubeClusterIPSet, kubeLoadBalancerSet} + for _, set := range sets { + var matchType string + if !proxier.ipsetList[set].isEmpty() { + switch proxier.ipsetList[set].SetType { + case utilipset.BitmapPort: + matchType = "dst" + default: + matchType = "dst,dst" + } + writeLine(proxier.natRules, []string{ + "-A", string(kubeServicesChain), + "-m", "set", "--match-set", set, matchType, + "-j", "ACCEPT", + }...) + } } +} - // Close old local ports and save new ones. - for k, v := range proxier.portsMap { - if replacementPortsMap[k] == nil { - v.Close() +// createAndLinkeKubeChain create all kube chains that ipvs proxier need and write basic link. +func (proxier *Proxier) createAndLinkeKubeChain() { + existingFilterChains := proxier.getExistingChains(utiliptables.TableFilter) + existingNATChains := proxier.getExistingChains(utiliptables.TableNAT) + + // Make sure we keep stats for the top-level chains + for _, ch := range iptablesChains { + if _, err := proxier.iptables.EnsureChain(ch.table, ch.chain); err != nil { + glog.Errorf("Failed to ensure that %s chain %s exists: %v", ch.table, ch.chain, err) + return + } + if ch.table == utiliptables.TableNAT { + if chain, ok := existingNATChains[ch.chain]; ok { + writeLine(proxier.natChains, chain) + } else { + writeLine(proxier.natChains, utiliptables.MakeChainLine(kubePostroutingChain)) + } + } else { + if chain, ok := existingFilterChains[KubeForwardChain]; ok { + writeLine(proxier.filterChains, chain) + } else { + writeLine(proxier.filterChains, utiliptables.MakeChainLine(KubeForwardChain)) + } } } - proxier.portsMap = replacementPortsMap - // Clean up legacy IPVS services - appliedSvcs, err := proxier.ipvs.GetVirtualServers() - if err == nil { - for _, appliedSvc := range appliedSvcs { - currentIPVSServices[appliedSvc.String()] = appliedSvc + for _, jc := range iptablesJumpChain { + args := []string{"-m", "comment", "--comment", jc.comment, "-j", string(jc.to)} + if _, err := proxier.iptables.EnsureRule(utiliptables.Prepend, jc.table, jc.from, args...); err != nil { + glog.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", jc.table, jc.from, jc.to, err) } - } else { - glog.Errorf("Failed to get ipvs service, err: %v", err) } - proxier.cleanLegacyService(activeIPVSServices, currentIPVSServices) - // Update healthz timestamp - if proxier.healthzServer != nil { - proxier.healthzServer.UpdateTimestamp() - } + // Install the kubernetes-specific postrouting rules. We use a whole chain for + // this so that it is easier to flush and change, for example if the mark + // value should ever change. + writeLine(proxier.natRules, []string{ + "-A", string(kubePostroutingChain), + "-m", "comment", "--comment", `"kubernetes service traffic requiring SNAT"`, + "-m", "mark", "--mark", proxier.masqueradeMark, + "-j", "MASQUERADE", + }...) - // Update healthchecks. The endpoints list might include services that are - // not "OnlyLocal", but the services list will not, and the healthChecker - // will just drop those endpoints. - if err := proxier.healthChecker.SyncServices(serviceUpdateResult.HCServiceNodePorts); err != nil { - glog.Errorf("Error syncing healtcheck services: %v", err) - } - if err := proxier.healthChecker.SyncEndpoints(endpointUpdateResult.HCEndpointsLocalIPSize); err != nil { - glog.Errorf("Error syncing healthcheck endpoints: %v", err) - } + // Install the kubernetes-specific masquerade mark rule. We use a whole chain for + // this so that it is easier to flush and change, for example if the mark + // value should ever change. + writeLine(proxier.natRules, []string{ + "-A", string(KubeMarkMasqChain), + "-j", "MARK", "--set-xmark", proxier.masqueradeMark, + }...) +} - // Finish housekeeping. - // TODO: these could be made more consistent. - for _, svcIP := range staleServices.UnsortedList() { - if err := conntrack.ClearEntriesForIP(proxier.exec, svcIP, clientv1.ProtocolUDP); err != nil { - glog.Errorf("Failed to delete stale service IP %s connections, error: %v", svcIP, err) - } +// getExistingChains get iptables-save output so we can check for existing chains and rules. +// This will be a map of chain name to chain with rules as stored in iptables-save/iptables-restore +func (proxier *Proxier) getExistingChains(table utiliptables.Table) map[utiliptables.Chain]string { + proxier.iptablesData.Reset() + err := proxier.iptables.SaveInto(table, proxier.iptablesData) + if err != nil { // if we failed to get any rules + glog.Errorf("Failed to execute iptables-save, syncing all rules: %v", err) + } else { // otherwise parse the output + return utiliptables.GetChainLines(table, proxier.iptablesData.Bytes()) } - proxier.deleteEndpointConnections(endpointUpdateResult.StaleEndpoints) + return nil } // After a UDP endpoint has been removed, we must flush any pending conntrack entries to it, or else we @@ -1324,9 +1509,10 @@ func (proxier *Proxier) syncEndpoint(svcPortName proxy.ServicePortName, onlyNode } for _, epInfo := range proxier.endpointsMap[svcPortName] { - if !onlyNodeLocalEndpoints || onlyNodeLocalEndpoints && epInfo.GetIsLocal() { - newEndpoints.Insert(epInfo.String()) + if onlyNodeLocalEndpoints && !epInfo.GetIsLocal() { + continue } + newEndpoints.Insert(epInfo.String()) } if !curEndpoints.Equal(newEndpoints) { @@ -1381,16 +1567,28 @@ func (proxier *Proxier) syncEndpoint(svcPortName proxy.ServicePortName, onlyNode return nil } -func (proxier *Proxier) cleanLegacyService(atciveServices map[string]bool, currentServices map[string]*utilipvs.VirtualServer) { +func (proxier *Proxier) cleanLegacyService(activeServices map[string]bool, currentServices map[string]*utilipvs.VirtualServer) { unbindIPAddr := sets.NewString() - for cS := range currentServices { - if !atciveServices[cS] { - svc := currentServices[cS] - err := proxier.ipvs.DeleteVirtualServer(svc) - if err != nil { - glog.Errorf("Failed to delete service, error: %v", err) + for cs := range currentServices { + svc := currentServices[cs] + if _, ok := activeServices[cs]; !ok { + // This service was not processed in the latest sync loop so before deleting it, + // make sure it does not fall within an excluded CIDR range. + okayToDelete := true + for _, excludedCIDR := range proxier.excludeCIDRs { + // Any validation of this CIDR already should have occurred. + _, n, _ := net.ParseCIDR(excludedCIDR) + if n.Contains(svc.Address) { + okayToDelete = false + break + } + } + if okayToDelete { + if err := proxier.ipvs.DeleteVirtualServer(svc); err != nil { + glog.Errorf("Failed to delete service, error: %v", err) + } + unbindIPAddr.Insert(svc.Address.String()) } - unbindIPAddr.Insert(svc.Address.String()) } } @@ -1403,54 +1601,6 @@ func (proxier *Proxier) cleanLegacyService(atciveServices map[string]bool, curre } } -// linkKubeServiceChain will Create chain KUBE-SERVICES and link the chin in PREROUTING and OUTPUT - -// Chain PREROUTING (policy ACCEPT) -// target prot opt source destination -// KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 - -// Chain OUTPUT (policy ACCEPT) -// target prot opt source destination -// KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 - -// Chain KUBE-SERVICES (2 references) -func (proxier *Proxier) linkKubeServiceChain(existingNATChains map[utiliptables.Chain]string, natChains *bytes.Buffer) error { - if _, err := proxier.iptables.EnsureChain(utiliptables.TableNAT, kubeServicesChain); err != nil { - return fmt.Errorf("Failed to ensure that %s chain %s exists: %v", utiliptables.TableNAT, kubeServicesChain, err) - } - comment := "kubernetes service portals" - args := []string{"-m", "comment", "--comment", comment, "-j", string(kubeServicesChain)} - for _, tc := range tableChainsWithJumpService { - if _, err := proxier.iptables.EnsureRule(utiliptables.Prepend, tc.table, tc.chain, args...); err != nil { - return fmt.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", tc.table, tc.chain, kubeServicesChain, err) - } - } - - // equal to `iptables -t nat -N KUBE-SERVICES` - // write `:KUBE-SERVICES - [0:0]` in nat table - if chain, ok := existingNATChains[kubeServicesChain]; ok { - writeLine(natChains, chain) - } else { - writeLine(natChains, utiliptables.MakeChainLine(kubeServicesChain)) - } - return nil -} - -func (proxier *Proxier) createKubeFireWallChain(existingNATChains map[utiliptables.Chain]string, natChains *bytes.Buffer) error { - // `iptables -t nat -N KUBE-FIRE-WALL` - if _, err := proxier.iptables.EnsureChain(utiliptables.TableNAT, KubeFireWallChain); err != nil { - return fmt.Errorf("Failed to ensure that %s chain %s exists: %v", utiliptables.TableNAT, KubeFireWallChain, err) - } - - // write `:KUBE-FIRE-WALL - [0:0]` in nat table - if chain, ok := existingNATChains[KubeFireWallChain]; ok { - writeLine(natChains, chain) - } else { - writeLine(natChains, utiliptables.MakeChainLine(KubeFireWallChain)) - } - return nil -} - // Join all words with spaces, terminate with newline and write to buff. func writeLine(buf *bytes.Buffer, words ...string) { // We avoid strings.Join for performance reasons. diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/proxier_test.go b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/proxier_test.go index 904c5c051..5b2df8089 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/proxier_test.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/proxier_test.go @@ -21,7 +21,9 @@ import ( "fmt" "net" "reflect" + "strings" "testing" + "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -106,6 +108,24 @@ func (fake *fakeIPSetVersioner) GetVersion() (string, error) { return fake.version, fake.err } +// New returns a new FakeSysctl +func NewFakeSysctl() *FakeSysctl { + return &FakeSysctl{} +} + +type FakeSysctl struct { +} + +// GetSysctl returns the value for the specified sysctl setting +func (fakeSysctl *FakeSysctl) GetSysctl(sysctl string) (int, error) { + return 1, nil +} + +// SetSysctl modifies the specified sysctl flag to the new value +func (fakeSysctl *FakeSysctl) SetSysctl(sysctl string, newVal int) error { + return nil +} + func NewFakeProxier(ipt utiliptables.Interface, ipvs utilipvs.Interface, ipset utilipset.Interface, nodeIPs []net.IP) *Proxier { fcmd := fakeexec.FakeCmd{ CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ @@ -118,37 +138,37 @@ func NewFakeProxier(ipt utiliptables.Interface, ipvs utilipvs.Interface, ipset u }, LookPathFunc: func(cmd string) (string, error) { return cmd, nil }, } + // initialize ipsetList with all sets we needed + ipsetList := make(map[string]*IPSet) + for _, is := range ipsetInfo { + ipsetList[is.name] = NewIPSet(ipset, is.name, is.setType, false, is.comment) + } return &Proxier{ - exec: fexec, - serviceMap: make(proxy.ServiceMap), - serviceChanges: proxy.NewServiceChangeTracker(newServiceInfo, nil, nil), - endpointsMap: make(proxy.EndpointsMap), - endpointsChanges: proxy.NewEndpointChangeTracker(testHostname, nil, nil, nil), - iptables: ipt, - ipvs: ipvs, - ipset: ipset, - clusterCIDR: "10.0.0.0/24", - hostname: testHostname, - portsMap: make(map[utilproxy.LocalPort]utilproxy.Closeable), - portMapper: &fakePortOpener{[]*utilproxy.LocalPort{}}, - healthChecker: newFakeHealthChecker(), - ipvsScheduler: DefaultScheduler, - ipGetter: &fakeIPGetter{nodeIPs: nodeIPs}, - iptablesData: bytes.NewBuffer(nil), - natChains: bytes.NewBuffer(nil), - natRules: bytes.NewBuffer(nil), - netlinkHandle: netlinktest.NewFakeNetlinkHandle(), - loopbackSet: NewIPSet(ipset, KubeLoopBackIPSet, utilipset.HashIPPortIP, false), - clusterIPSet: NewIPSet(ipset, KubeClusterIPSet, utilipset.HashIPPort, false), - externalIPSet: NewIPSet(ipset, KubeExternalIPSet, utilipset.HashIPPort, false), - lbIngressSet: NewIPSet(ipset, KubeLoadBalancerSet, utilipset.HashIPPort, false), - lbMasqSet: NewIPSet(ipset, KubeLoadBalancerMasqSet, utilipset.HashIPPort, false), - lbWhiteListIPSet: NewIPSet(ipset, KubeLoadBalancerSourceIPSet, utilipset.HashIPPortIP, false), - lbWhiteListCIDRSet: NewIPSet(ipset, KubeLoadBalancerSourceCIDRSet, utilipset.HashIPPortNet, false), - nodePortSetTCP: NewIPSet(ipset, KubeNodePortSetTCP, utilipset.BitmapPort, false), - nodePortSetUDP: NewIPSet(ipset, KubeNodePortSetUDP, utilipset.BitmapPort, false), - nodePortAddresses: make([]string, 0), - networkInterfacer: proxyutiltest.NewFakeNetwork(), + exec: fexec, + serviceMap: make(proxy.ServiceMap), + serviceChanges: proxy.NewServiceChangeTracker(newServiceInfo, nil, nil), + endpointsMap: make(proxy.EndpointsMap), + endpointsChanges: proxy.NewEndpointChangeTracker(testHostname, nil, nil, nil), + excludeCIDRs: make([]string, 0), + iptables: ipt, + ipvs: ipvs, + ipset: ipset, + clusterCIDR: "10.0.0.0/24", + hostname: testHostname, + portsMap: make(map[utilproxy.LocalPort]utilproxy.Closeable), + portMapper: &fakePortOpener{[]*utilproxy.LocalPort{}}, + healthChecker: newFakeHealthChecker(), + ipvsScheduler: DefaultScheduler, + ipGetter: &fakeIPGetter{nodeIPs: nodeIPs}, + iptablesData: bytes.NewBuffer(nil), + natChains: bytes.NewBuffer(nil), + natRules: bytes.NewBuffer(nil), + filterChains: bytes.NewBuffer(nil), + filterRules: bytes.NewBuffer(nil), + netlinkHandle: netlinktest.NewFakeNetlinkHandle(), + ipsetList: ipsetList, + nodePortAddresses: make([]string, 0), + networkInterfacer: proxyutiltest.NewFakeNetwork(), } } @@ -802,16 +822,10 @@ func TestLoadBalancer(t *testing.T) { fp.syncProxyRules() } -func strPtr(s string) *string { - return &s -} - func TestOnlyLocalNodePorts(t *testing.T) { - ipt := iptablestest.NewFake() - ipvs := ipvstest.NewFake() - ipset := ipsettest.NewFake(testIPSetVersion) nodeIP := net.ParseIP("100.101.102.103") - fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIP}) + ipt, fp := buildFakeProxier() + svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001 @@ -834,17 +848,13 @@ func TestOnlyLocalNodePorts(t *testing.T) { }), ) - epIP1 := "10.180.0.1" - epIP2 := "10.180.2.1" + epIP := "10.180.0.1" makeEndpointsMap(fp, makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *api.Endpoints) { ept.Subsets = []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{ - IP: epIP1, + IP: epIP, NodeName: nil, - }, { - IP: epIP2, - NodeName: strPtr(testHostname), }}, Ports: []api.EndpointPort{{ Name: svcPortName.Port, @@ -865,41 +875,204 @@ func TestOnlyLocalNodePorts(t *testing.T) { fp.syncProxyRules() // Expect 3 services and 1 destination - services, err := ipvs.GetVirtualServers() - if err != nil { - t.Errorf("Failed to get ipvs services, err: %v", err) + epVS := &netlinktest.ExpectedVirtualServer{ + VSNum: 3, IP: nodeIP.String(), Port: uint16(svcNodePort), Protocol: string(api.ProtocolTCP), + RS: []netlinktest.ExpectedRealServer{{ + IP: epIP, Port: uint16(svcPort), + }}} + checkIPVS(t, fp, epVS) + + // check ipSet rules + epEntry := &utilipset.Entry{ + Port: svcNodePort, + Protocol: strings.ToLower(string(api.ProtocolTCP)), + SetType: utilipset.BitmapPort, + } + epIPSet := netlinktest.ExpectedIPSet{ + kubeNodePortSetTCP: {epEntry}, + kubeNodePortLocalSetTCP: {epEntry}, + } + checkIPSet(t, fp, epIPSet) + + // Check iptables chain and rules + epIpt := netlinktest.ExpectedIptablesChain{ + string(kubeServicesChain): {{ + JumpChain: string(KubeNodePortChain), MatchSet: kubeNodePortSetTCP, + }}, + string(KubeNodePortChain): {{ + JumpChain: "RETURN", MatchSet: kubeNodePortLocalSetTCP, + }, { + JumpChain: string(KubeMarkMasqChain), MatchSet: "", + }}, } - if len(services) != 3 { - t.Errorf("Expect 3 ipvs services, got %d", len(services)) + checkIptables(t, ipt, epIpt) +} +func TestLoadBalanceSourceRanges(t *testing.T) { + ipt, fp := buildFakeProxier() + + svcIP := "10.20.30.41" + svcPort := 80 + svcLBIP := "1.2.3.4" + svcLBSource := "10.0.0.0/8" + svcPortName := proxy.ServicePortName{ + NamespacedName: makeNSN("ns1", "svc1"), + Port: "p80", } - found := false - for _, svc := range services { - if svc.Address.Equal(nodeIP) && svc.Port == uint16(svcNodePort) && svc.Protocol == string(api.ProtocolTCP) { - found = true - destinations, err := ipvs.GetRealServers(svc) - if err != nil { - t.Errorf("Failed to get ipvs destinations, err: %v", err) + epIP := "10.180.0.1" + + makeServiceMap(fp, + makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *api.Service) { + svc.Spec.Type = "LoadBalancer" + svc.Spec.ClusterIP = svcIP + svc.Spec.Ports = []api.ServicePort{{ + Name: svcPortName.Port, + Port: int32(svcPort), + Protocol: api.ProtocolTCP, + }} + svc.Status.LoadBalancer.Ingress = []api.LoadBalancerIngress{{ + IP: svcLBIP, + }} + svc.Spec.LoadBalancerSourceRanges = []string{ + svcLBSource, } - if len(destinations) != 1 { - t.Errorf("Expect 1 ipvs destination, got %d", len(destinations)) - } else { - if destinations[0].Address.String() != epIP2 || destinations[0].Port != uint16(svcPort) { - t.Errorf("service Endpoint mismatch ipvs service destination") + }), + ) + makeEndpointsMap(fp, + makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{{ + Addresses: []api.EndpointAddress{{ + IP: epIP, + NodeName: nil, + }}, + Ports: []api.EndpointPort{{ + Name: svcPortName.Port, + Port: int32(svcPort), + }}, + }} + }), + ) + + fp.syncProxyRules() + + // Check ipvs service and destinations + epVS := &netlinktest.ExpectedVirtualServer{ + VSNum: 2, IP: svcLBIP, Port: uint16(svcPort), Protocol: string(api.ProtocolTCP), + RS: []netlinktest.ExpectedRealServer{{ + IP: epIP, Port: uint16(svcPort), + }}} + checkIPVS(t, fp, epVS) + + // Check ipset entry + epIPSet := netlinktest.ExpectedIPSet{ + kubeLoadBalancerSet: {{ + IP: svcLBIP, + Port: svcPort, + Protocol: strings.ToLower(string(api.ProtocolTCP)), + SetType: utilipset.HashIPPort, + }}, + kubeLoadbalancerFWSet: {{ + IP: svcLBIP, + Port: svcPort, + Protocol: strings.ToLower(string(api.ProtocolTCP)), + SetType: utilipset.HashIPPort, + }}, + kubeLoadBalancerSourceCIDRSet: {{ + IP: svcLBIP, + Port: svcPort, + Protocol: strings.ToLower(string(api.ProtocolTCP)), + Net: svcLBSource, + SetType: utilipset.HashIPPortNet, + }}, + } + checkIPSet(t, fp, epIPSet) + + // Check iptables chain and rules + epIpt := netlinktest.ExpectedIptablesChain{ + string(kubeServicesChain): {{ + JumpChain: string(KubeLoadBalancerChain), MatchSet: kubeLoadBalancerSet, + }}, + string(KubeLoadBalancerChain): {{ + JumpChain: string(KubeFireWallChain), MatchSet: kubeLoadbalancerFWSet, + }, { + JumpChain: string(KubeMarkMasqChain), MatchSet: "", + }}, + string(KubeFireWallChain): {{ + JumpChain: "RETURN", MatchSet: kubeLoadBalancerSourceCIDRSet, + }, { + JumpChain: string(KubeMarkDropChain), MatchSet: "", + }}, + } + checkIptables(t, ipt, epIpt) +} + +func TestAcceptIPVSTraffic(t *testing.T) { + ipt, fp := buildFakeProxier() + + ingressIP := "1.2.3.4" + externalIP := []string{"5.6.7.8"} + svcInfos := []struct { + svcType api.ServiceType + svcIP string + svcName string + epIP string + }{ + {api.ServiceTypeClusterIP, "10.20.30.40", "svc1", "10.180.0.1"}, + {api.ServiceTypeLoadBalancer, "10.20.30.41", "svc2", "10.180.0.2"}, + {api.ServiceTypeNodePort, "10.20.30.42", "svc3", "10.180.0.3"}, + } + + for _, svcInfo := range svcInfos { + makeServiceMap(fp, + makeTestService("ns1", svcInfo.svcName, func(svc *api.Service) { + svc.Spec.Type = svcInfo.svcType + svc.Spec.ClusterIP = svcInfo.svcIP + svc.Spec.Ports = []api.ServicePort{{ + Name: "p80", + Port: 80, + Protocol: api.ProtocolTCP, + NodePort: 80, + }} + if svcInfo.svcType == api.ServiceTypeLoadBalancer { + svc.Status.LoadBalancer.Ingress = []api.LoadBalancerIngress{{ + IP: ingressIP, + }} } - } - break - } + if svcInfo.svcType == api.ServiceTypeClusterIP { + svc.Spec.ExternalIPs = externalIP + } + }), + ) + + makeEndpointsMap(fp, + makeTestEndpoints("ns1", "p80", func(ept *api.Endpoints) { + ept.Subsets = []api.EndpointSubset{{ + Addresses: []api.EndpointAddress{{ + IP: svcInfo.epIP, + }}, + Ports: []api.EndpointPort{{ + Name: "p80", + Port: 80, + }}, + }} + }), + ) } - if !found { - t.Errorf("Expect node port type service, got none") + fp.syncProxyRules() + + // Check iptables chain and rules + epIpt := netlinktest.ExpectedIptablesChain{ + string(kubeServicesChain): { + {JumpChain: "ACCEPT", MatchSet: kubeClusterIPSet}, + {JumpChain: "ACCEPT", MatchSet: kubeLoadBalancerSet}, + {JumpChain: "ACCEPT", MatchSet: kubeExternalIPSet}, + }, } + checkIptables(t, ipt, epIpt) } func TestOnlyLocalLoadBalancing(t *testing.T) { - ipt := iptablestest.NewFake() - ipvs := ipvstest.NewFake() - ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + ipt, fp := buildFakeProxier() + svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001 @@ -926,17 +1099,13 @@ func TestOnlyLocalLoadBalancing(t *testing.T) { }), ) - epIP1 := "10.180.0.1" - epIP2 := "10.180.2.1" + epIP := "10.180.0.1" makeEndpointsMap(fp, makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *api.Endpoints) { ept.Subsets = []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{ - IP: epIP1, + IP: epIP, NodeName: nil, - }, { - IP: epIP2, - NodeName: strPtr(testHostname), }}, Ports: []api.EndpointPort{{ Name: svcPortName.Port, @@ -947,6 +1116,44 @@ func TestOnlyLocalLoadBalancing(t *testing.T) { ) fp.syncProxyRules() + + // Expect 2 services and 1 destination + epVS := &netlinktest.ExpectedVirtualServer{ + VSNum: 2, IP: svcLBIP, Port: uint16(svcPort), Protocol: string(api.ProtocolTCP), + RS: []netlinktest.ExpectedRealServer{{ + IP: epIP, Port: uint16(svcPort), + }}} + checkIPVS(t, fp, epVS) + + // check ipSet rules + epIPSet := netlinktest.ExpectedIPSet{ + kubeLoadBalancerSet: {{ + IP: svcLBIP, + Port: svcPort, + Protocol: strings.ToLower(string(api.ProtocolTCP)), + SetType: utilipset.HashIPPort, + }}, + kubeLoadBalancerLocalSet: {{ + IP: svcLBIP, + Port: svcPort, + Protocol: strings.ToLower(string(api.ProtocolTCP)), + SetType: utilipset.HashIPPort, + }}, + } + checkIPSet(t, fp, epIPSet) + + // Check iptables chain and rules + epIpt := netlinktest.ExpectedIptablesChain{ + string(kubeServicesChain): {{ + JumpChain: string(KubeLoadBalancerChain), MatchSet: kubeLoadBalancerSet, + }}, + string(KubeLoadBalancerChain): {{ + JumpChain: "RETURN", MatchSet: kubeLoadBalancerLocalSet, + }, { + JumpChain: string(KubeMarkMasqChain), MatchSet: "", + }}, + } + checkIptables(t, ipt, epIpt) } func addTestPort(array []api.ServicePort, name string, protocol api.Protocol, port, nodeport int32, targetPort int) []api.ServicePort { @@ -2277,3 +2484,179 @@ func Test_syncService(t *testing.T) { } } } + +func buildFakeProxier() (*iptablestest.FakeIPTables, *Proxier) { + ipt := iptablestest.NewFake() + ipvs := ipvstest.NewFake() + ipset := ipsettest.NewFake(testIPSetVersion) + return ipt, NewFakeProxier(ipt, ipvs, ipset, nil) +} + +func hasJump(rules []iptablestest.Rule, destChain, ipSet string) bool { + for _, r := range rules { + if r[iptablestest.Jump] == destChain { + if ipSet == "" { + return true + } + if strings.Contains(r[iptablestest.MatchSet], ipSet) { + return true + } + } + } + return false +} + +// checkIptabless to check expected iptables chain and rules +func checkIptables(t *testing.T, ipt *iptablestest.FakeIPTables, epIpt netlinktest.ExpectedIptablesChain) { + for epChain, epRules := range epIpt { + rules := ipt.GetRules(epChain) + for _, epRule := range epRules { + if !hasJump(rules, epRule.JumpChain, epRule.MatchSet) { + t.Errorf("Didn't find jump from chain %v match set %v to %v", epChain, epRule.MatchSet, epRule.JumpChain) + } + } + } +} + +// checkIPSet to check expected ipset and entries +func checkIPSet(t *testing.T, fp *Proxier, ipSet netlinktest.ExpectedIPSet) { + for set, entries := range ipSet { + ents, err := fp.ipset.ListEntries(set) + if err != nil || len(ents) != len(entries) { + t.Errorf("Check ipset entries failed for ipset: %q, expect %d, got %d", set, len(entries), len(ents)) + continue + } + if len(entries) == 1 { + if ents[0] != entries[0].String() { + t.Errorf("Check ipset entries failed for ipset: %q", set) + } + } + } +} + +// checkIPVS to check expected ipvs service and destination +func checkIPVS(t *testing.T, fp *Proxier, vs *netlinktest.ExpectedVirtualServer) { + services, err := fp.ipvs.GetVirtualServers() + if err != nil { + t.Errorf("Failed to get ipvs services, err: %v", err) + } + if len(services) != vs.VSNum { + t.Errorf("Expect %d ipvs services, got %d", vs.VSNum, len(services)) + } + for _, svc := range services { + if svc.Address.String() == vs.IP && svc.Port == vs.Port && svc.Protocol == vs.Protocol { + destinations, _ := fp.ipvs.GetRealServers(svc) + if len(destinations) != len(vs.RS) { + t.Errorf("Expected %d destinations, got %d destinations", len(vs.RS), len(destinations)) + } + if len(vs.RS) == 1 { + if destinations[0].Address.String() != vs.RS[0].IP || destinations[0].Port != vs.RS[0].Port { + t.Errorf("Unexpected mismatch destinations") + } + } + } + } +} + +func TestCleanLegacyService(t *testing.T) { + execer := exec.New() + ipt := iptablestest.NewFake() + ipvs := ipvstest.NewFake() + ipset := ipsettest.NewFake(testIPSetVersion) + excludeCIDRs := []string{"3.3.3.0/24", "4.4.4.0/24"} + proxier, err := NewProxier( + ipt, + ipvs, + ipset, + NewFakeSysctl(), + execer, + 250*time.Millisecond, + 100*time.Millisecond, + excludeCIDRs, + false, + 0, + "10.0.0.0/24", + testHostname, + net.ParseIP("127.0.0.1"), + nil, + nil, + DefaultScheduler, + make([]string, 0), + ) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + // All ipvs services that were processed in the latest sync loop. + activeServices := map[string]bool{"ipvs0": true, "ipvs1": true} + // All ipvs services in the system. + currentServices := map[string]*utilipvs.VirtualServer{ + // Created by kube-proxy. + "ipvs0": { + Address: net.ParseIP("1.1.1.1"), + Protocol: string(api.ProtocolUDP), + Port: 53, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by kube-proxy. + "ipvs1": { + Address: net.ParseIP("2.2.2.2"), + Protocol: string(api.ProtocolUDP), + Port: 54, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by an external party. + "ipvs2": { + Address: net.ParseIP("3.3.3.3"), + Protocol: string(api.ProtocolUDP), + Port: 55, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by an external party. + "ipvs3": { + Address: net.ParseIP("4.4.4.4"), + Protocol: string(api.ProtocolUDP), + Port: 56, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by an external party. + "ipvs4": { + Address: net.ParseIP("5.5.5.5"), + Protocol: string(api.ProtocolUDP), + Port: 57, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by kube-proxy, but now stale. + "ipvs5": { + Address: net.ParseIP("6.6.6.6"), + Protocol: string(api.ProtocolUDP), + Port: 58, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + } + for v := range currentServices { + proxier.ipvs.AddVirtualServer(currentServices[v]) + } + proxier.cleanLegacyService(activeServices, currentServices) + // ipvs4 and ipvs5 should have been cleaned. + remainingVirtualServers, _ := proxier.ipvs.GetVirtualServers() + if len(remainingVirtualServers) != 4 { + t.Errorf("Expected number of remaining IPVS services after cleanup to be %v. Got %v", 4, len(remainingVirtualServers)) + } + + for _, vs := range remainingVirtualServers { + // Checking that ipvs4 and ipvs5 were removed. + if vs.Port == 57 { + t.Errorf("Expected ipvs4 to be removed after cleanup. It still remains") + } + if vs.Port == 58 { + t.Errorf("Expected ipvs5 to be removed after cleanup. It still remains") + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/testing/BUILD index 576024cee..090650341 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/testing/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/testing/BUILD @@ -10,10 +10,16 @@ load( go_library( name = "go_default_library", - srcs = ["fake.go"], + srcs = [ + "fake.go", + "util.go", + ], importpath = "k8s.io/kubernetes/pkg/proxy/ipvs/testing", tags = ["automanaged"], - deps = ["//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library"], + deps = [ + "//pkg/util/ipset:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + ], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/testing/util.go b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/testing/util.go new file mode 100644 index 000000000..2dbff14d1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/proxy/ipvs/testing/util.go @@ -0,0 +1,51 @@ +/* +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 testing + +import ( + utilipset "k8s.io/kubernetes/pkg/util/ipset" +) + +// ExpectedVirtualServer is the expected ipvs rules with VirtualServer and RealServer +// VSNum is the expected ipvs virtual server number +// IP:Port protocol is the expected ipvs vs info +// RS is the RealServer of this expected VirtualServer +type ExpectedVirtualServer struct { + VSNum int + IP string + Port uint16 + Protocol string + RS []ExpectedRealServer +} + +// ExpectedRealServer is the expected ipvs RealServer +type ExpectedRealServer struct { + IP string + Port uint16 +} + +// ExpectedIptablesChain is a map of expected iptables chain and jump rules +type ExpectedIptablesChain map[string][]ExpectedIptablesRule + +// ExpectedIptablesRule is the expected iptables rules with jump chain and match ipset name +type ExpectedIptablesRule struct { + JumpChain string + MatchSet string +} + +// ExpectedIPSet is the expected ipset with set name and entries name +type ExpectedIPSet map[string][]*utilipset.Entry diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/service.go b/vendor/k8s.io/kubernetes/pkg/proxy/service.go index 23911a43c..88e804517 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/service.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/service.go @@ -30,7 +30,6 @@ import ( "k8s.io/client-go/tools/record" apiservice "k8s.io/kubernetes/pkg/api/service" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" utilproxy "k8s.io/kubernetes/pkg/proxy/util" utilnet "k8s.io/kubernetes/pkg/util/net" ) @@ -91,7 +90,7 @@ func (sct *ServiceChangeTracker) newBaseServiceInfo(port *api.ServicePort, servi Protocol: port.Protocol, NodePort: int(port.NodePort), // Deep-copy in case the service instance changes - LoadBalancerStatus: *helper.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer), + LoadBalancerStatus: *service.Status.LoadBalancer.DeepCopy(), SessionAffinityType: service.Spec.SessionAffinity, StickyMaxAgeSeconds: stickyMaxAgeSeconds, OnlyNodeLocalEndpoints: onlyNodeLocalEndpoints, diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/BUILD b/vendor/k8s.io/kubernetes/pkg/proxy/userspace/BUILD index 715e176fb..95051c60a 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/proxy/userspace/BUILD @@ -14,7 +14,6 @@ go_library( "proxier.go", "proxysocket.go", "roundrobin.go", - "udp_server.go", ] + select({ "@io_bazel_rules_go//go/platform:android": [ "rlimit.go", diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/proxier.go b/vendor/k8s.io/kubernetes/pkg/proxy/userspace/proxier.go index 3fc49c064..1efced086 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/proxier.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/userspace/proxier.go @@ -447,7 +447,7 @@ func (proxier *Proxier) mergeService(service *api.Service) sets.String { info.portal.port = int(servicePort.Port) info.externalIPs = service.Spec.ExternalIPs // Deep-copy in case the service instance changes - info.loadBalancerStatus = *helper.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer) + info.loadBalancerStatus = *service.Status.LoadBalancer.DeepCopy() info.nodePort = int(servicePort.NodePort) info.sessionAffinityType = service.Spec.SessionAffinity // Kube-apiserver side guarantees SessionAffinityConfig won't be nil when session affinity type is ClientIP @@ -1095,7 +1095,7 @@ func (proxier *Proxier) iptablesHostNodePortArgs(nodePort int, protocol api.Prot // Build a slice of iptables args for an from-non-local public-port rule. func (proxier *Proxier) iptablesNonLocalNodePortArgs(nodePort int, protocol api.Protocol, proxyIP net.IP, proxyPort int, service proxy.ServicePortName) []string { args := iptablesCommonPortalArgs(nil, false, false, proxyPort, protocol, service) - args = append(args, "-m", "comment", "--comment", service.String(), "-m", "state", "--state", "NEW", "-j", "ACCEPT") + args = append(args, "-m", "state", "--state", "NEW", "-j", "ACCEPT") return args } diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/proxier_test.go b/vendor/k8s.io/kubernetes/pkg/proxy/userspace/proxier_test.go index ef55b1ba0..6c9ce711a 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/proxier_test.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/userspace/proxier_test.go @@ -86,6 +86,31 @@ func waitForClosedPortUDP(p *Proxier, proxyPort int) error { return fmt.Errorf("port %d still open", proxyPort) } +// udpEchoServer is a simple echo server in UDP, intended for testing the proxy. +type udpEchoServer struct { + net.PacketConn +} + +func newUDPEchoServer() (*udpEchoServer, error) { + packetconn, err := net.ListenPacket("udp", ":0") + if err != nil { + return nil, err + } + return &udpEchoServer{packetconn}, nil +} + +func (r *udpEchoServer) Loop() { + var buffer [4096]byte + for { + n, cliAddr, err := r.ReadFrom(buffer[0:]) + if err != nil { + fmt.Printf("ReadFrom failed: %v\n", err) + continue + } + r.WriteTo(buffer[0:n], cliAddr) + } +} + var tcpServerPort int32 var udpServerPort int32 diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/roundrobin.go b/vendor/k8s.io/kubernetes/pkg/proxy/userspace/roundrobin.go index e2aca2991..3ca546b5e 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/roundrobin.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/userspace/roundrobin.go @@ -159,7 +159,7 @@ func (lb *LoadBalancerRR) NextEndpoint(svcPort proxy.ServicePortName, srcAddr ne } if !sessionAffinityReset { sessionAffinity, exists := state.affinity.affinityMap[ipaddr] - if exists && int(time.Now().Sub(sessionAffinity.lastUsed).Seconds()) < state.affinity.ttlSeconds { + if exists && int(time.Since(sessionAffinity.lastUsed).Seconds()) < state.affinity.ttlSeconds { // Affinity wins. endpoint := sessionAffinity.endpoint sessionAffinity.lastUsed = time.Now() @@ -378,7 +378,7 @@ func (lb *LoadBalancerRR) CleanupStaleStickySessions(svcPort proxy.ServicePortNa return } for ip, affinity := range state.affinity.affinityMap { - if int(time.Now().Sub(affinity.lastUsed).Seconds()) >= state.affinity.ttlSeconds { + if int(time.Since(affinity.lastUsed).Seconds()) >= state.affinity.ttlSeconds { glog.V(4).Infof("Removing client %s from affinityMap for service %q", affinity.clientIP, svcPort) delete(state.affinity.affinityMap, ip) } diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/udp_server.go b/vendor/k8s.io/kubernetes/pkg/proxy/userspace/udp_server.go deleted file mode 100644 index 49e8d603f..000000000 --- a/vendor/k8s.io/kubernetes/pkg/proxy/userspace/udp_server.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -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 userspace - -import ( - "fmt" - "net" -) - -// udpEchoServer is a simple echo server in UDP, intended for testing the proxy. -type udpEchoServer struct { - net.PacketConn -} - -func (r *udpEchoServer) Loop() { - var buffer [4096]byte - for { - n, cliAddr, err := r.ReadFrom(buffer[0:]) - if err != nil { - fmt.Printf("ReadFrom failed: %v\n", err) - continue - } - r.WriteTo(buffer[0:n], cliAddr) - } -} - -func newUDPEchoServer() (*udpEchoServer, error) { - packetconn, err := net.ListenPacket("udp", ":0") - if err != nil { - return nil, err - } - return &udpEchoServer{packetconn}, nil -} - -/* -func main() { - r,_ := newUDPEchoServer() - r.Loop() -} -*/ diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/winkernel/proxier.go b/vendor/k8s.io/kubernetes/pkg/proxy/winkernel/proxier.go index 595286520..e22295426 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/winkernel/proxier.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/winkernel/proxier.go @@ -175,7 +175,7 @@ func newServiceInfo(svcPortName proxy.ServicePortName, port *api.ServicePort, se nodePort: int(port.NodePort), targetPort: port.TargetPort.IntValue(), // Deep-copy in case the service instance changes - loadBalancerStatus: *helper.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer), + loadBalancerStatus: *service.Status.LoadBalancer.DeepCopy(), sessionAffinityType: service.Spec.SessionAffinity, stickyMaxAgeSeconds: stickyMaxAgeSeconds, loadBalancerSourceRanges: make([]string, len(service.Spec.LoadBalancerSourceRanges)), diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/BUILD b/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/BUILD index 4a4829c87..c680a3ead 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/BUILD @@ -14,7 +14,6 @@ go_library( "proxysocket.go", "roundrobin.go", "types.go", - "udp_server.go", ], importpath = "k8s.io/kubernetes/pkg/proxy/winuserspace", deps = [ diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/proxier_test.go b/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/proxier_test.go index f69e64c63..587d4e3bf 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/proxier_test.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/proxier_test.go @@ -84,6 +84,31 @@ func waitForClosedPortUDP(p *Proxier, proxyPort int) error { return fmt.Errorf("port %d still open", proxyPort) } +// udpEchoServer is a simple echo server in UDP, intended for testing the proxy. +type udpEchoServer struct { + net.PacketConn +} + +func newUDPEchoServer() (*udpEchoServer, error) { + packetconn, err := net.ListenPacket("udp", ":0") + if err != nil { + return nil, err + } + return &udpEchoServer{packetconn}, nil +} + +func (r *udpEchoServer) Loop() { + var buffer [4096]byte + for { + n, cliAddr, err := r.ReadFrom(buffer[0:]) + if err != nil { + fmt.Printf("ReadFrom failed: %v\n", err) + continue + } + r.WriteTo(buffer[0:n], cliAddr) + } +} + var tcpServerPort int32 var udpServerPort int32 diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/roundrobin.go b/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/roundrobin.go index 27b835559..161d616ab 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/roundrobin.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/roundrobin.go @@ -149,7 +149,7 @@ func (lb *LoadBalancerRR) NextEndpoint(svcPort proxy.ServicePortName, srcAddr ne } if !sessionAffinityReset { sessionAffinity, exists := state.affinity.affinityMap[ipaddr] - if exists && int(time.Now().Sub(sessionAffinity.lastUsed).Seconds()) < state.affinity.ttlSeconds { + if exists && int(time.Since(sessionAffinity.lastUsed).Seconds()) < state.affinity.ttlSeconds { // Affinity wins. endpoint := sessionAffinity.endpoint sessionAffinity.lastUsed = time.Now() @@ -366,7 +366,7 @@ func (lb *LoadBalancerRR) CleanupStaleStickySessions(svcPort proxy.ServicePortNa return } for ip, affinity := range state.affinity.affinityMap { - if int(time.Now().Sub(affinity.lastUsed).Seconds()) >= state.affinity.ttlSeconds { + if int(time.Since(affinity.lastUsed).Seconds()) >= state.affinity.ttlSeconds { glog.V(4).Infof("Removing client %s from affinityMap for service %q", affinity.clientIP, svcPort) delete(state.affinity.affinityMap, ip) } diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/udp_server.go b/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/udp_server.go deleted file mode 100644 index c95c1e059..000000000 --- a/vendor/k8s.io/kubernetes/pkg/proxy/winuserspace/udp_server.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -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 winuserspace - -import ( - "fmt" - "net" -) - -// udpEchoServer is a simple echo server in UDP, intended for testing the proxy. -type udpEchoServer struct { - net.PacketConn -} - -func (r *udpEchoServer) Loop() { - var buffer [4096]byte - for { - n, cliAddr, err := r.ReadFrom(buffer[0:]) - if err != nil { - fmt.Printf("ReadFrom failed: %v\n", err) - continue - } - r.WriteTo(buffer[0:n], cliAddr) - } -} - -func newUDPEchoServer() (*udpEchoServer, error) { - packetconn, err := net.ListenPacket("udp", ":0") - if err != nil { - return nil, err - } - return &udpEchoServer{packetconn}, nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/BUILD b/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/BUILD index 8d254028c..7a6cbe11c 100644 --- a/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/BUILD @@ -27,6 +27,7 @@ go_library( "//pkg/quota/generic:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels: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/util/clock:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/persistent_volume_claims.go b/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/persistent_volume_claims.go index 4547f370d..62051e451 100644 --- a/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/persistent_volume_claims.go +++ b/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/persistent_volume_claims.go @@ -123,6 +123,17 @@ func (p *pvcEvaluator) Matches(resourceQuota *api.ResourceQuota, item runtime.Ob return generic.Matches(resourceQuota, item, p.MatchingResources, generic.MatchesNoScopeFunc) } +// MatchingScopes takes the input specified list of scopes and input object. Returns the set of scopes resource matches. +func (p *pvcEvaluator) MatchingScopes(item runtime.Object, scopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + +// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. +// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope +func (p *pvcEvaluator) UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + // MatchingResources takes the input specified list of resources and returns the set of resources it matches. func (p *pvcEvaluator) MatchingResources(items []api.ResourceName) []api.ResourceName { result := []api.ResourceName{} diff --git a/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/pods.go b/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/pods.go index a2d94c96c..3d1572271 100644 --- a/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/pods.go +++ b/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/pods.go @@ -23,6 +23,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -81,7 +82,7 @@ func maskResourceWithPrefix(resource api.ResourceName, prefix string) api.Resour func isExtendedResourceNameForQuota(name api.ResourceName) bool { // As overcommit is not supported by extended resources for now, // only quota objects in format of "requests.resourceName" is allowed. - return !helper.IsDefaultNamespaceResource(name) && strings.HasPrefix(string(name), api.DefaultResourceRequestsPrefix) + return !helper.IsNativeResource(name) && strings.HasPrefix(string(name), api.DefaultResourceRequestsPrefix) } // NOTE: it was a mistake, but if a quota tracks cpu or memory related resources, @@ -117,7 +118,7 @@ type podEvaluator struct { func (p *podEvaluator) Constraints(required []api.ResourceName, item runtime.Object) error { pod, ok := item.(*api.Pod) if !ok { - return fmt.Errorf("Unexpected input object %v", item) + return fmt.Errorf("unexpected input object %v", item) } // BACKWARD COMPATIBILITY REQUIREMENT: if we quota cpu or memory, then each container @@ -181,6 +182,41 @@ func (p *podEvaluator) MatchingResources(input []api.ResourceName) []api.Resourc return result } +// MatchingScopes takes the input specified list of scopes and pod object. Returns the set of scope selectors pod matches. +func (p *podEvaluator) MatchingScopes(item runtime.Object, scopeSelectors []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + matchedScopes := []api.ScopedResourceSelectorRequirement{} + for _, selector := range scopeSelectors { + match, err := podMatchesScopeFunc(selector, item) + if err != nil { + return []api.ScopedResourceSelectorRequirement{}, fmt.Errorf("error on matching scope %v: %v", selector, err) + } + if match { + matchedScopes = append(matchedScopes, selector) + } + } + return matchedScopes, nil +} + +// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. +// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope +func (p *podEvaluator) UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + uncoveredScopes := []api.ScopedResourceSelectorRequirement{} + for _, selector := range limitedScopes { + isCovered := false + for _, matchedScopeSelector := range matchedQuotaScopes { + if matchedScopeSelector.ScopeName == selector.ScopeName { + isCovered = true + break + } + } + + if !isCovered { + uncoveredScopes = append(uncoveredScopes, selector) + } + } + return uncoveredScopes, nil +} + // Usage knows how to measure usage associated with pods func (p *podEvaluator) Usage(item runtime.Object) (api.ResourceList, error) { // delegate to normal usage @@ -265,12 +301,12 @@ func toInternalPodOrError(obj runtime.Object) (*api.Pod, error) { } // podMatchesScopeFunc is a function that knows how to evaluate if a pod matches a scope -func podMatchesScopeFunc(scope api.ResourceQuotaScope, object runtime.Object) (bool, error) { +func podMatchesScopeFunc(selector api.ScopedResourceSelectorRequirement, object runtime.Object) (bool, error) { pod, err := toInternalPodOrError(object) if err != nil { return false, err } - switch scope { + switch selector.ScopeName { case api.ResourceQuotaScopeTerminating: return isTerminating(pod), nil case api.ResourceQuotaScopeNotTerminating: @@ -279,6 +315,8 @@ func podMatchesScopeFunc(scope api.ResourceQuotaScope, object runtime.Object) (b return isBestEffort(pod), nil case api.ResourceQuotaScopeNotBestEffort: return !isBestEffort(pod), nil + case api.ResourceQuotaScopePriorityClass: + return podMatchesSelector(pod, selector) } return false, nil } @@ -337,6 +375,18 @@ func isTerminating(pod *api.Pod) bool { return false } +func podMatchesSelector(pod *api.Pod, selector api.ScopedResourceSelectorRequirement) (bool, error) { + labelSelector, err := helper.ScopedResourceSelectorRequirementsAsSelector(selector) + if err != nil { + return false, fmt.Errorf("failed to parse and convert selector: %v", err) + } + m := map[string]string{string(api.ResourceQuotaScopePriorityClass): pod.Spec.PriorityClassName} + if labelSelector.Matches(labels.Set(m)) { + return true, nil + } + return false, nil +} + // QuotaPod returns true if the pod is eligible to track against a quota // A pod is eligible for quota, unless any of the following are true: // - pod has a terminal phase (failed or succeeded) diff --git a/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/services.go b/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/services.go index cdddaf064..006c0e9b1 100644 --- a/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/services.go +++ b/vendor/k8s.io/kubernetes/pkg/quota/evaluator/core/services.go @@ -82,6 +82,17 @@ func (p *serviceEvaluator) MatchingResources(input []api.ResourceName) []api.Res return quota.Intersection(input, serviceResources) } +// MatchingScopes takes the input specified list of scopes and input object. Returns the set of scopes resource matches. +func (p *serviceEvaluator) MatchingScopes(item runtime.Object, scopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + +// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. +// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope +func (p *serviceEvaluator) UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + // convert the input object to an internal service object or error. func toInternalServiceOrError(obj runtime.Object) (*api.Service, error) { svc := &api.Service{} diff --git a/vendor/k8s.io/kubernetes/pkg/quota/generic/evaluator.go b/vendor/k8s.io/kubernetes/pkg/quota/generic/evaluator.go index 6324ce5dd..7df5243e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/quota/generic/evaluator.go +++ b/vendor/k8s.io/kubernetes/pkg/quota/generic/evaluator.go @@ -67,7 +67,7 @@ func ObjectCountQuotaResourceNameFor(groupResource schema.GroupResource) api.Res type ListFuncByNamespace func(namespace string) ([]runtime.Object, error) // MatchesScopeFunc knows how to evaluate if an object matches a scope -type MatchesScopeFunc func(scope api.ResourceQuotaScope, object runtime.Object) (bool, error) +type MatchesScopeFunc func(scope api.ScopedResourceSelectorRequirement, object runtime.Object) (bool, error) // UsageFunc knows how to measure usage associated with an object type UsageFunc func(object runtime.Object) (api.ResourceList, error) @@ -76,12 +76,14 @@ type UsageFunc func(object runtime.Object) (api.ResourceList, error) type MatchingResourceNamesFunc func(input []api.ResourceName) []api.ResourceName // MatchesNoScopeFunc returns false on all match checks -func MatchesNoScopeFunc(scope api.ResourceQuotaScope, object runtime.Object) (bool, error) { +func MatchesNoScopeFunc(scope api.ScopedResourceSelectorRequirement, object runtime.Object) (bool, error) { return false, nil } // Matches returns true if the quota matches the specified item. -func Matches(resourceQuota *api.ResourceQuota, item runtime.Object, matchFunc MatchingResourceNamesFunc, scopeFunc MatchesScopeFunc) (bool, error) { +func Matches( + resourceQuota *api.ResourceQuota, item runtime.Object, + matchFunc MatchingResourceNamesFunc, scopeFunc MatchesScopeFunc) (bool, error) { if resourceQuota == nil { return false, fmt.Errorf("expected non-nil quota") } @@ -89,7 +91,7 @@ func Matches(resourceQuota *api.ResourceQuota, item runtime.Object, matchFunc Ma matchResource := len(matchFunc(quota.ResourceNames(resourceQuota.Status.Hard))) > 0 // by default, no scopes matches all matchScope := true - for _, scope := range resourceQuota.Spec.Scopes { + for _, scope := range getScopeSelectorsFromQuota(resourceQuota) { innerMatch, err := scopeFunc(scope, item) if err != nil { return false, err @@ -99,6 +101,21 @@ func Matches(resourceQuota *api.ResourceQuota, item runtime.Object, matchFunc Ma return matchResource && matchScope, nil } +func getScopeSelectorsFromQuota(quota *api.ResourceQuota) []api.ScopedResourceSelectorRequirement { + selectors := []api.ScopedResourceSelectorRequirement{} + for _, scope := range quota.Spec.Scopes { + selectors = append(selectors, api.ScopedResourceSelectorRequirement{ + ScopeName: scope, + Operator: api.ScopeSelectorOpExists}) + } + if quota.Spec.ScopeSelector != nil { + for _, scopeSelector := range quota.Spec.ScopeSelector.MatchExpressions { + selectors = append(selectors, scopeSelector) + } + } + return selectors +} + // CalculateUsageStats is a utility function that knows how to calculate aggregate usage. func CalculateUsageStats(options quota.UsageStatsOptions, listFunc ListFuncByNamespace, @@ -117,7 +134,7 @@ func CalculateUsageStats(options quota.UsageStatsOptions, // need to verify that the item matches the set of scopes matchesScopes := true for _, scope := range options.Scopes { - innerMatch, err := scopeFunc(scope, item) + innerMatch, err := scopeFunc(api.ScopedResourceSelectorRequirement{ScopeName: scope}, item) if err != nil { return result, nil } @@ -125,6 +142,15 @@ func CalculateUsageStats(options quota.UsageStatsOptions, matchesScopes = false } } + if options.ScopeSelector != nil { + for _, selector := range options.ScopeSelector.MatchExpressions { + innerMatch, err := scopeFunc(selector, item) + if err != nil { + return result, nil + } + matchesScopes = matchesScopes && innerMatch + } + } // only count usage if there was a match if matchesScopes { usage, err := usageFunc(item) @@ -176,6 +202,17 @@ func (o *objectCountEvaluator) MatchingResources(input []api.ResourceName) []api return quota.Intersection(input, o.resourceNames) } +// MatchingScopes takes the input specified list of scopes and input object. Returns the set of scopes resource matches. +func (o *objectCountEvaluator) MatchingScopes(item runtime.Object, scopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + +// UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. +// It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope +func (o *objectCountEvaluator) UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) { + return []api.ScopedResourceSelectorRequirement{}, nil +} + // Usage returns the resource usage for the specified object func (o *objectCountEvaluator) Usage(object runtime.Object) (api.ResourceList, error) { quantity := resource.NewQuantity(1, resource.DecimalSI) diff --git a/vendor/k8s.io/kubernetes/pkg/quota/interfaces.go b/vendor/k8s.io/kubernetes/pkg/quota/interfaces.go index 8d7295ef0..e6723b8ae 100644 --- a/vendor/k8s.io/kubernetes/pkg/quota/interfaces.go +++ b/vendor/k8s.io/kubernetes/pkg/quota/interfaces.go @@ -31,7 +31,8 @@ type UsageStatsOptions struct { // Scopes that must match counted objects Scopes []api.ResourceQuotaScope // Resources are the set of resources to include in the measurement - Resources []api.ResourceName + Resources []api.ResourceName + ScopeSelector *api.ScopeSelector } // UsageStats is result of measuring observed resource use in the system @@ -51,6 +52,10 @@ type Evaluator interface { Handles(operation admission.Attributes) bool // Matches returns true if the specified quota matches the input item Matches(resourceQuota *api.ResourceQuota, item runtime.Object) (bool, error) + // MatchingScopes takes the input specified list of scopes and input object and returns the set of scopes that matches input object. + MatchingScopes(item runtime.Object, scopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) + // UncoveredQuotaScopes takes the input matched scopes which are limited by configuration and the matched quota scopes. It returns the scopes which are in limited scopes but dont have a corresponding covering quota scope + UncoveredQuotaScopes(limitedScopes []api.ScopedResourceSelectorRequirement, matchedQuotaScopes []api.ScopedResourceSelectorRequirement) ([]api.ScopedResourceSelectorRequirement, error) // MatchingResources takes the input specified list of resources and returns the set of resources evaluator matches. MatchingResources(input []api.ResourceName) []api.ResourceName // Usage returns the resource usage for the specified object diff --git a/vendor/k8s.io/kubernetes/pkg/quota/resources.go b/vendor/k8s.io/kubernetes/pkg/quota/resources.go index a40a81a64..f77d2d742 100644 --- a/vendor/k8s.io/kubernetes/pkg/quota/resources.go +++ b/vendor/k8s.io/kubernetes/pkg/quota/resources.go @@ -253,7 +253,7 @@ func ToSet(resourceNames []api.ResourceName) sets.String { } // CalculateUsage calculates and returns the requested ResourceList usage -func CalculateUsage(namespaceName string, scopes []api.ResourceQuotaScope, hardLimits api.ResourceList, registry Registry) (api.ResourceList, error) { +func CalculateUsage(namespaceName string, scopes []api.ResourceQuotaScope, hardLimits api.ResourceList, registry Registry, scopeSelector *api.ScopeSelector) (api.ResourceList, error) { // find the intersection between the hard resources on the quota // and the resources this controller can track to know what we can // look to measure updated usage stats for @@ -275,7 +275,7 @@ func CalculateUsage(namespaceName string, scopes []api.ResourceQuotaScope, hardL continue } - usageStatsOptions := UsageStatsOptions{Namespace: namespaceName, Scopes: scopes, Resources: intersection} + usageStatsOptions := UsageStatsOptions{Namespace: namespaceName, Scopes: scopes, Resources: intersection, ScopeSelector: scopeSelector} stats, err := evaluator.UsageStats(usageStatsOptions) if err != nil { return nil, err diff --git a/vendor/k8s.io/kubernetes/pkg/quota/resources_test.go b/vendor/k8s.io/kubernetes/pkg/quota/resources_test.go index 8cf26a767..2df5dbd74 100644 --- a/vendor/k8s.io/kubernetes/pkg/quota/resources_test.go +++ b/vendor/k8s.io/kubernetes/pkg/quota/resources_test.go @@ -102,6 +102,11 @@ func TestMax(t *testing.T) { b: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")}, expected: api.ResourceList{api.ResourceCPU: resource.MustParse("150m")}, }, + "matching-equal": { + a: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")}, + b: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")}, + expected: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")}, + }, } for testName, testCase := range testCases { sum := Max(testCase.a, testCase.b) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/BUILD index be61c8554..73f892bce 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/BUILD @@ -70,11 +70,11 @@ filegroup( "//pkg/registry/events/rest:all-srcs", "//pkg/registry/extensions/controller/storage:all-srcs", "//pkg/registry/extensions/ingress:all-srcs", - "//pkg/registry/extensions/podsecuritypolicy:all-srcs", "//pkg/registry/extensions/rest:all-srcs", "//pkg/registry/networking/networkpolicy:all-srcs", "//pkg/registry/networking/rest:all-srcs", "//pkg/registry/policy/poddisruptionbudget:all-srcs", + "//pkg/registry/policy/podsecuritypolicy:all-srcs", "//pkg/registry/policy/rest:all-srcs", "//pkg/registry/rbac:all-srcs", "//pkg/registry/registrytest:all-srcs", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/BUILD index 29c56e75b..76fe73c88 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/BUILD @@ -18,7 +18,6 @@ go_library( "//pkg/apis/admissionregistration/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/strategy.go index f32e4ea9d..70b2be0cc 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/initializerconfiguration/strategy.go @@ -17,11 +17,11 @@ limitations under the License. package initializerconfiguration import ( + "context" "reflect" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/admissionregistration" @@ -43,13 +43,13 @@ func (initializerConfigurationStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of an InitializerConfiguration before creation. -func (initializerConfigurationStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (initializerConfigurationStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { ic := obj.(*admissionregistration.InitializerConfiguration) ic.Generation = 1 } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (initializerConfigurationStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (initializerConfigurationStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newIC := obj.(*admissionregistration.InitializerConfiguration) oldIC := old.(*admissionregistration.InitializerConfiguration) @@ -62,7 +62,7 @@ func (initializerConfigurationStrategy) PrepareForUpdate(ctx genericapirequest.C } // Validate validates a new InitializerConfiguration. -func (initializerConfigurationStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (initializerConfigurationStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { ic := obj.(*admissionregistration.InitializerConfiguration) return validation.ValidateInitializerConfiguration(ic) } @@ -77,7 +77,7 @@ func (initializerConfigurationStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (initializerConfigurationStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (initializerConfigurationStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { validationErrorList := validation.ValidateInitializerConfiguration(obj.(*admissionregistration.InitializerConfiguration)) updateErrorList := validation.ValidateInitializerConfigurationUpdate(obj.(*admissionregistration.InitializerConfiguration), old.(*admissionregistration.InitializerConfiguration)) return append(validationErrorList, updateErrorList...) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration/BUILD index 92ae7b566..c16824304 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration/BUILD @@ -18,7 +18,6 @@ go_library( "//pkg/apis/admissionregistration/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration/strategy.go index 735980ac4..ae0f8b7f9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/mutatingwebhookconfiguration/strategy.go @@ -17,11 +17,11 @@ limitations under the License. package mutatingwebhookconfiguration import ( + "context" "reflect" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/admissionregistration" @@ -43,13 +43,13 @@ func (mutatingWebhookConfigurationStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of an mutatingWebhookConfiguration before creation. -func (mutatingWebhookConfigurationStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (mutatingWebhookConfigurationStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { ic := obj.(*admissionregistration.MutatingWebhookConfiguration) ic.Generation = 1 } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (mutatingWebhookConfigurationStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (mutatingWebhookConfigurationStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newIC := obj.(*admissionregistration.MutatingWebhookConfiguration) oldIC := old.(*admissionregistration.MutatingWebhookConfiguration) @@ -62,7 +62,7 @@ func (mutatingWebhookConfigurationStrategy) PrepareForUpdate(ctx genericapireque } // Validate validates a new mutatingWebhookConfiguration. -func (mutatingWebhookConfigurationStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (mutatingWebhookConfigurationStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { ic := obj.(*admissionregistration.MutatingWebhookConfiguration) return validation.ValidateMutatingWebhookConfiguration(ic) } @@ -77,7 +77,7 @@ func (mutatingWebhookConfigurationStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (mutatingWebhookConfigurationStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (mutatingWebhookConfigurationStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { validationErrorList := validation.ValidateMutatingWebhookConfiguration(obj.(*admissionregistration.MutatingWebhookConfiguration)) updateErrorList := validation.ValidateMutatingWebhookConfigurationUpdate(obj.(*admissionregistration.MutatingWebhookConfiguration), old.(*admissionregistration.MutatingWebhookConfiguration)) return append(validationErrorList, updateErrorList...) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/rest/storage_apiserver.go b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/rest/storage_apiserver.go index 53e604193..8bfcb35eb 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/rest/storage_apiserver.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/rest/storage_apiserver.go @@ -33,17 +33,15 @@ import ( type RESTStorageProvider struct{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(admissionregistration.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(admissionregistration.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(admissionregistrationv1alpha1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[admissionregistrationv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = admissionregistrationv1alpha1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(admissionregistrationv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[admissionregistrationv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = admissionregistrationv1beta1.SchemeGroupVersion } return apiGroupInfo, true } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/BUILD index 0b07d3028..363e6531c 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/BUILD @@ -18,7 +18,6 @@ go_library( "//pkg/apis/admissionregistration/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/strategy.go index e59ecc989..ee696717b 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/admissionregistration/validatingwebhookconfiguration/strategy.go @@ -17,11 +17,11 @@ limitations under the License. package validatingwebhookconfiguration import ( + "context" "reflect" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/admissionregistration" @@ -43,13 +43,13 @@ func (validatingWebhookConfigurationStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of an validatingWebhookConfiguration before creation. -func (validatingWebhookConfigurationStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (validatingWebhookConfigurationStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { ic := obj.(*admissionregistration.ValidatingWebhookConfiguration) ic.Generation = 1 } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (validatingWebhookConfigurationStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (validatingWebhookConfigurationStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newIC := obj.(*admissionregistration.ValidatingWebhookConfiguration) oldIC := old.(*admissionregistration.ValidatingWebhookConfiguration) @@ -62,7 +62,7 @@ func (validatingWebhookConfigurationStrategy) PrepareForUpdate(ctx genericapireq } // Validate validates a new validatingWebhookConfiguration. -func (validatingWebhookConfigurationStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (validatingWebhookConfigurationStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { ic := obj.(*admissionregistration.ValidatingWebhookConfiguration) return validation.ValidateValidatingWebhookConfiguration(ic) } @@ -77,7 +77,7 @@ func (validatingWebhookConfigurationStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (validatingWebhookConfigurationStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (validatingWebhookConfigurationStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { validationErrorList := validation.ValidateValidatingWebhookConfiguration(obj.(*admissionregistration.ValidatingWebhookConfiguration)) updateErrorList := validation.ValidateValidatingWebhookConfigurationUpdate(obj.(*admissionregistration.ValidatingWebhookConfiguration), old.(*admissionregistration.ValidatingWebhookConfiguration)) return append(validationErrorList, updateErrorList...) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/controllerrevision/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/apps/controllerrevision/BUILD index 474d6bb1b..1b45798f1 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/controllerrevision/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/controllerrevision/BUILD @@ -32,7 +32,6 @@ go_library( "//pkg/apis/apps/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/controllerrevision/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/controllerrevision/strategy.go index 08161d718..a47f8587c 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/controllerrevision/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/controllerrevision/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package controllerrevision import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -54,17 +55,17 @@ func (strategy) AllowCreateOnUpdate() bool { return false } -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { _ = obj.(*apps.ControllerRevision) } -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { revision := obj.(*apps.ControllerRevision) return validation.ValidateControllerRevision(revision) } -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, newObj, oldObj runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, newObj, oldObj runtime.Object) { _ = oldObj.(*apps.ControllerRevision) _ = newObj.(*apps.ControllerRevision) } @@ -73,7 +74,7 @@ func (strategy) AllowUnconditionalUpdate() bool { return true } -func (strategy) ValidateUpdate(ctx genericapirequest.Context, newObj, oldObj runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, newObj, oldObj runtime.Object) field.ErrorList { oldRevision, newRevision := oldObj.(*apps.ControllerRevision), newObj.(*apps.ControllerRevision) return validation.ValidateControllerRevisionUpdate(newRevision, oldRevision) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/storage/BUILD index dc992ae1e..88d5df242 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/storage/BUILD @@ -36,7 +36,6 @@ go_library( "//pkg/registry/apps/daemonset:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/storage/storage.go index 8a961399d..aeb09657d 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -90,11 +91,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/strategy.go index 04723fdcf..cdc70a600 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/daemonset/strategy.go @@ -17,6 +17,8 @@ limitations under the License. package daemonset import ( + "context" + appsv1beta2 "k8s.io/api/apps/v1beta2" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" @@ -43,7 +45,7 @@ type daemonSetStrategy struct { var Strategy = daemonSetStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} // DefaultGarbageCollectionPolicy returns OrphanDependents by default. For apps/v1, returns DeleteDependents. -func (daemonSetStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (daemonSetStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} switch groupVersion { @@ -63,7 +65,7 @@ func (daemonSetStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a daemon set before creation. -func (daemonSetStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (daemonSetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { daemonSet := obj.(*extensions.DaemonSet) daemonSet.Status = extensions.DaemonSetStatus{} @@ -76,7 +78,7 @@ func (daemonSetStrategy) PrepareForCreate(ctx genericapirequest.Context, obj run } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (daemonSetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (daemonSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newDaemonSet := obj.(*extensions.DaemonSet) oldDaemonSet := old.(*extensions.DaemonSet) @@ -111,7 +113,7 @@ func (daemonSetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, ol } // Validate validates a new daemon set. -func (daemonSetStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (daemonSetStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { daemonSet := obj.(*extensions.DaemonSet) return validation.ValidateDaemonSet(daemonSet) } @@ -127,7 +129,7 @@ func (daemonSetStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (daemonSetStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (daemonSetStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { newDaemonSet := obj.(*extensions.DaemonSet) oldDaemonSet := old.(*extensions.DaemonSet) allErrs := validation.ValidateDaemonSet(obj.(*extensions.DaemonSet)) @@ -162,12 +164,12 @@ type daemonSetStatusStrategy struct { var StatusStrategy = daemonSetStatusStrategy{Strategy} -func (daemonSetStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (daemonSetStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newDaemonSet := obj.(*extensions.DaemonSet) oldDaemonSet := old.(*extensions.DaemonSet) newDaemonSet.Spec = oldDaemonSet.Spec } -func (daemonSetStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (daemonSetStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateDaemonSetStatusUpdate(obj.(*extensions.DaemonSet), old.(*extensions.DaemonSet)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/registry.go index 951e86863..cf09bda58 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/registry.go @@ -17,22 +17,22 @@ limitations under the License. package deployment import ( + "context" "fmt" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/extensions" ) // Registry is an interface for things that know how to store Deployments. type Registry interface { - ListDeployments(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*extensions.DeploymentList, error) - GetDeployment(ctx genericapirequest.Context, deploymentID string, options *metav1.GetOptions) (*extensions.Deployment, error) - CreateDeployment(ctx genericapirequest.Context, deployment *extensions.Deployment, createValidation rest.ValidateObjectFunc) (*extensions.Deployment, error) - UpdateDeployment(ctx genericapirequest.Context, deployment *extensions.Deployment, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*extensions.Deployment, error) - DeleteDeployment(ctx genericapirequest.Context, deploymentID string) error + ListDeployments(ctx context.Context, options *metainternalversion.ListOptions) (*extensions.DeploymentList, error) + GetDeployment(ctx context.Context, deploymentID string, options *metav1.GetOptions) (*extensions.Deployment, error) + CreateDeployment(ctx context.Context, deployment *extensions.Deployment, createValidation rest.ValidateObjectFunc) (*extensions.Deployment, error) + UpdateDeployment(ctx context.Context, deployment *extensions.Deployment, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*extensions.Deployment, error) + DeleteDeployment(ctx context.Context, deploymentID string) error } // storage puts strong typing around storage calls @@ -45,7 +45,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListDeployments(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*extensions.DeploymentList, error) { +func (s *storage) ListDeployments(ctx context.Context, options *metainternalversion.ListOptions) (*extensions.DeploymentList, error) { if options != nil && options.FieldSelector != nil && !options.FieldSelector.Empty() { return nil, fmt.Errorf("field selector not supported yet") } @@ -56,7 +56,7 @@ func (s *storage) ListDeployments(ctx genericapirequest.Context, options *metain return obj.(*extensions.DeploymentList), err } -func (s *storage) GetDeployment(ctx genericapirequest.Context, deploymentID string, options *metav1.GetOptions) (*extensions.Deployment, error) { +func (s *storage) GetDeployment(ctx context.Context, deploymentID string, options *metav1.GetOptions) (*extensions.Deployment, error) { obj, err := s.Get(ctx, deploymentID, options) if err != nil { return nil, err @@ -64,7 +64,7 @@ func (s *storage) GetDeployment(ctx genericapirequest.Context, deploymentID stri return obj.(*extensions.Deployment), nil } -func (s *storage) CreateDeployment(ctx genericapirequest.Context, deployment *extensions.Deployment, createValidation rest.ValidateObjectFunc) (*extensions.Deployment, error) { +func (s *storage) CreateDeployment(ctx context.Context, deployment *extensions.Deployment, createValidation rest.ValidateObjectFunc) (*extensions.Deployment, error) { obj, err := s.Create(ctx, deployment, createValidation, false) if err != nil { return nil, err @@ -72,7 +72,7 @@ func (s *storage) CreateDeployment(ctx genericapirequest.Context, deployment *ex return obj.(*extensions.Deployment), nil } -func (s *storage) UpdateDeployment(ctx genericapirequest.Context, deployment *extensions.Deployment, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*extensions.Deployment, error) { +func (s *storage) UpdateDeployment(ctx context.Context, deployment *extensions.Deployment, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*extensions.Deployment, error) { obj, _, err := s.Update(ctx, deployment.Name, rest.DefaultUpdatedObjectInfo(deployment), createValidation, updateValidation) if err != nil { return nil, err @@ -80,7 +80,7 @@ func (s *storage) UpdateDeployment(ctx genericapirequest.Context, deployment *ex return obj.(*extensions.Deployment), nil } -func (s *storage) DeleteDeployment(ctx genericapirequest.Context, deploymentID string) error { +func (s *storage) DeleteDeployment(ctx context.Context, deploymentID string) error { _, _, err := s.Delete(ctx, deploymentID, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/storage/BUILD index 488a9f08b..600ff2032 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/storage/BUILD @@ -53,7 +53,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/storage/storage.go index 2fa85ea97..c8b469ec4 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/storage/storage.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "fmt" "net/http" @@ -24,7 +25,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -123,12 +123,12 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } @@ -144,7 +144,7 @@ func (r *RollbackREST) New() runtime.Object { var _ = rest.Creater(&RollbackREST{}) -func (r *RollbackREST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *RollbackREST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { rollback, ok := obj.(*extensions.DeploymentRollback) if !ok { return nil, errors.NewBadRequest(fmt.Sprintf("not a DeploymentRollback: %#v", obj)) @@ -166,7 +166,7 @@ func (r *RollbackREST) Create(ctx genericapirequest.Context, obj runtime.Object, }, nil } -func (r *RollbackREST) rollbackDeployment(ctx genericapirequest.Context, deploymentID string, config *extensions.RollbackConfig, annotations map[string]string) error { +func (r *RollbackREST) rollbackDeployment(ctx context.Context, deploymentID string, config *extensions.RollbackConfig, annotations map[string]string) error { if _, err := r.setDeploymentRollback(ctx, deploymentID, config, annotations); err != nil { err = storeerr.InterpretGetError(err, extensions.Resource("deployments"), deploymentID) err = storeerr.InterpretUpdateError(err, extensions.Resource("deployments"), deploymentID) @@ -178,7 +178,7 @@ func (r *RollbackREST) rollbackDeployment(ctx genericapirequest.Context, deploym return nil } -func (r *RollbackREST) setDeploymentRollback(ctx genericapirequest.Context, deploymentID string, config *extensions.RollbackConfig, annotations map[string]string) (*extensions.Deployment, error) { +func (r *RollbackREST) setDeploymentRollback(ctx context.Context, deploymentID string, config *extensions.RollbackConfig, annotations map[string]string) (*extensions.Deployment, error) { dKey, err := r.store.KeyFunc(ctx, deploymentID) if err != nil { return nil, err @@ -228,7 +228,7 @@ func (r *ScaleREST) New() runtime.Object { return &autoscaling.Scale{} } -func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *ScaleREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { deployment, err := r.registry.GetDeployment(ctx, name, options) if err != nil { return nil, errors.NewNotFound(extensions.Resource("deployments/scale"), name) @@ -240,7 +240,7 @@ func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *met return scale, nil } -func (r *ScaleREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { deployment, err := r.registry.GetDeployment(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, errors.NewNotFound(extensions.Resource("deployments/scale"), name) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/strategy.go index 29fcd750a..139d6df6a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/deployment/strategy.go @@ -17,6 +17,8 @@ limitations under the License. package deployment import ( + "context" + appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta2 "k8s.io/api/apps/v1beta2" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" @@ -45,7 +47,7 @@ type deploymentStrategy struct { var Strategy = deploymentStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} // DefaultGarbageCollectionPolicy returns OrphanDependents by default. For apps/v1, returns DeleteDependents. -func (deploymentStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (deploymentStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} switch groupVersion { @@ -65,7 +67,7 @@ func (deploymentStrategy) NamespaceScoped() bool { } // PrepareForCreate clears fields that are not allowed to be set by end users on creation. -func (deploymentStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (deploymentStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { deployment := obj.(*extensions.Deployment) deployment.Status = extensions.DeploymentStatus{} deployment.Generation = 1 @@ -74,7 +76,7 @@ func (deploymentStrategy) PrepareForCreate(ctx genericapirequest.Context, obj ru } // Validate validates a new deployment. -func (deploymentStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (deploymentStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { deployment := obj.(*extensions.Deployment) return validation.ValidateDeployment(deployment) } @@ -89,7 +91,7 @@ func (deploymentStrategy) AllowCreateOnUpdate() bool { } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (deploymentStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (deploymentStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newDeployment := obj.(*extensions.Deployment) oldDeployment := old.(*extensions.Deployment) newDeployment.Status = oldDeployment.Status @@ -107,7 +109,7 @@ func (deploymentStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, o } // ValidateUpdate is the default update validation for an end user. -func (deploymentStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (deploymentStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { newDeployment := obj.(*extensions.Deployment) oldDeployment := old.(*extensions.Deployment) allErrs := validation.ValidateDeploymentUpdate(newDeployment, oldDeployment) @@ -142,7 +144,7 @@ type deploymentStatusStrategy struct { var StatusStrategy = deploymentStatusStrategy{Strategy} // PrepareForUpdate clears fields that are not allowed to be set by end users on update of status -func (deploymentStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (deploymentStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newDeployment := obj.(*extensions.Deployment) oldDeployment := old.(*extensions.Deployment) newDeployment.Spec = oldDeployment.Spec @@ -150,6 +152,6 @@ func (deploymentStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, } // ValidateUpdate is the default update validation for an end user updating status -func (deploymentStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (deploymentStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateDeploymentStatusUpdate(obj.(*extensions.Deployment), old.(*extensions.Deployment)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/registry.go index 029631eb6..83dd85f4a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/registry.go @@ -19,24 +19,24 @@ limitations under the License. package replicaset import ( + "context" "fmt" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/extensions" ) // Registry is an interface for things that know how to store ReplicaSets. type Registry interface { - ListReplicaSets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*extensions.ReplicaSetList, error) - WatchReplicaSets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) - GetReplicaSet(ctx genericapirequest.Context, replicaSetID string, options *metav1.GetOptions) (*extensions.ReplicaSet, error) - CreateReplicaSet(ctx genericapirequest.Context, replicaSet *extensions.ReplicaSet, createValidation rest.ValidateObjectFunc) (*extensions.ReplicaSet, error) - UpdateReplicaSet(ctx genericapirequest.Context, replicaSet *extensions.ReplicaSet, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*extensions.ReplicaSet, error) - DeleteReplicaSet(ctx genericapirequest.Context, replicaSetID string) error + ListReplicaSets(ctx context.Context, options *metainternalversion.ListOptions) (*extensions.ReplicaSetList, error) + WatchReplicaSets(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetReplicaSet(ctx context.Context, replicaSetID string, options *metav1.GetOptions) (*extensions.ReplicaSet, error) + CreateReplicaSet(ctx context.Context, replicaSet *extensions.ReplicaSet, createValidation rest.ValidateObjectFunc) (*extensions.ReplicaSet, error) + UpdateReplicaSet(ctx context.Context, replicaSet *extensions.ReplicaSet, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*extensions.ReplicaSet, error) + DeleteReplicaSet(ctx context.Context, replicaSetID string) error } // storage puts strong typing around storage calls @@ -50,7 +50,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListReplicaSets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*extensions.ReplicaSetList, error) { +func (s *storage) ListReplicaSets(ctx context.Context, options *metainternalversion.ListOptions) (*extensions.ReplicaSetList, error) { if options != nil && options.FieldSelector != nil && !options.FieldSelector.Empty() { return nil, fmt.Errorf("field selector not supported yet") } @@ -61,11 +61,11 @@ func (s *storage) ListReplicaSets(ctx genericapirequest.Context, options *metain return obj.(*extensions.ReplicaSetList), err } -func (s *storage) WatchReplicaSets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchReplicaSets(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetReplicaSet(ctx genericapirequest.Context, replicaSetID string, options *metav1.GetOptions) (*extensions.ReplicaSet, error) { +func (s *storage) GetReplicaSet(ctx context.Context, replicaSetID string, options *metav1.GetOptions) (*extensions.ReplicaSet, error) { obj, err := s.Get(ctx, replicaSetID, options) if err != nil { return nil, err @@ -73,7 +73,7 @@ func (s *storage) GetReplicaSet(ctx genericapirequest.Context, replicaSetID stri return obj.(*extensions.ReplicaSet), nil } -func (s *storage) CreateReplicaSet(ctx genericapirequest.Context, replicaSet *extensions.ReplicaSet, createValidation rest.ValidateObjectFunc) (*extensions.ReplicaSet, error) { +func (s *storage) CreateReplicaSet(ctx context.Context, replicaSet *extensions.ReplicaSet, createValidation rest.ValidateObjectFunc) (*extensions.ReplicaSet, error) { obj, err := s.Create(ctx, replicaSet, createValidation, false) if err != nil { return nil, err @@ -81,7 +81,7 @@ func (s *storage) CreateReplicaSet(ctx genericapirequest.Context, replicaSet *ex return obj.(*extensions.ReplicaSet), nil } -func (s *storage) UpdateReplicaSet(ctx genericapirequest.Context, replicaSet *extensions.ReplicaSet, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*extensions.ReplicaSet, error) { +func (s *storage) UpdateReplicaSet(ctx context.Context, replicaSet *extensions.ReplicaSet, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*extensions.ReplicaSet, error) { obj, _, err := s.Update(ctx, replicaSet.Name, rest.DefaultUpdatedObjectInfo(replicaSet), createValidation, updateValidation) if err != nil { return nil, err @@ -89,7 +89,7 @@ func (s *storage) UpdateReplicaSet(ctx genericapirequest.Context, replicaSet *ex return obj.(*extensions.ReplicaSet), nil } -func (s *storage) DeleteReplicaSet(ctx genericapirequest.Context, replicaSetID string) error { +func (s *storage) DeleteReplicaSet(ctx context.Context, replicaSetID string) error { _, _, err := s.Delete(ctx, replicaSetID, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/BUILD index 917b635c4..20785a44d 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/BUILD @@ -50,7 +50,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/storage.go index d181b35c9..aa8ee4e17 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/storage.go @@ -19,13 +19,13 @@ limitations under the License. package storage import ( + "context" "fmt" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -121,12 +121,12 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } @@ -156,7 +156,7 @@ func (r *ScaleREST) New() runtime.Object { return &autoscaling.Scale{} } -func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *ScaleREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { rs, err := r.registry.GetReplicaSet(ctx, name, options) if err != nil { return nil, errors.NewNotFound(extensions.Resource("replicasets/scale"), name) @@ -168,7 +168,7 @@ func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *met return scale, err } -func (r *ScaleREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { rs, err := r.registry.GetReplicaSet(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, errors.NewNotFound(extensions.Resource("replicasets/scale"), name) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/storage_test.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/storage_test.go index 670cede92..9ce94fcfc 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/storage_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/storage/storage_test.go @@ -158,6 +158,9 @@ func TestGenerationNumber(t *testing.T) { modifiedSno.Status.ObservedGeneration = 10 ctx := genericapirequest.NewDefaultContext() rs, err := createReplicaSet(storage.ReplicaSet, modifiedSno, t) + if err != nil { + t.Errorf("unexpected error: %v", err) + } etcdRS, err := storage.ReplicaSet.Get(ctx, rs.Name, &metav1.GetOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) @@ -165,14 +168,13 @@ func TestGenerationNumber(t *testing.T) { storedRS, _ := etcdRS.(*extensions.ReplicaSet) // Generation initialization - if storedRS.Generation != 1 && storedRS.Status.ObservedGeneration != 0 { + if storedRS.Generation != 1 || storedRS.Status.ObservedGeneration != 0 { t.Fatalf("Unexpected generation number %v, status generation %v", storedRS.Generation, storedRS.Status.ObservedGeneration) } // Updates to spec should increment the generation number storedRS.Spec.Replicas += 1 - storage.ReplicaSet.Update(ctx, storedRS.Name, rest.DefaultUpdatedObjectInfo(storedRS), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc) - if err != nil { + if _, _, err := storage.ReplicaSet.Update(ctx, storedRS.Name, rest.DefaultUpdatedObjectInfo(storedRS), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc); err != nil { t.Errorf("unexpected error: %v", err) } etcdRS, err = storage.ReplicaSet.Get(ctx, rs.Name, &metav1.GetOptions{}) @@ -186,8 +188,7 @@ func TestGenerationNumber(t *testing.T) { // Updates to status should not increment either spec or status generation numbers storedRS.Status.Replicas += 1 - storage.ReplicaSet.Update(ctx, storedRS.Name, rest.DefaultUpdatedObjectInfo(storedRS), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc) - if err != nil { + if _, _, err := storage.ReplicaSet.Update(ctx, storedRS.Name, rest.DefaultUpdatedObjectInfo(storedRS), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc); err != nil { t.Errorf("unexpected error: %v", err) } etcdRS, err = storage.ReplicaSet.Get(ctx, rs.Name, &metav1.GetOptions{}) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/strategy.go index fac1f2a5a..decb062c6 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/replicaset/strategy.go @@ -19,6 +19,7 @@ limitations under the License. package replicaset import ( + "context" "fmt" "strconv" @@ -52,7 +53,7 @@ type rsStrategy struct { var Strategy = rsStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} // DefaultGarbageCollectionPolicy returns OrphanDependents by default. For apps/v1, returns DeleteDependents. -func (rsStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (rsStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} switch groupVersion { @@ -72,7 +73,7 @@ func (rsStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a ReplicaSet before creation. -func (rsStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (rsStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { rs := obj.(*extensions.ReplicaSet) rs.Status = extensions.ReplicaSetStatus{} @@ -82,7 +83,7 @@ func (rsStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Ob } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (rsStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (rsStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newRS := obj.(*extensions.ReplicaSet) oldRS := old.(*extensions.ReplicaSet) // update is not allowed to set status @@ -105,7 +106,7 @@ func (rsStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runti } // Validate validates a new ReplicaSet. -func (rsStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (rsStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { rs := obj.(*extensions.ReplicaSet) return validation.ValidateReplicaSet(rs) } @@ -121,7 +122,7 @@ func (rsStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (rsStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (rsStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { newReplicaSet := obj.(*extensions.ReplicaSet) oldReplicaSet := old.(*extensions.ReplicaSet) allErrs := validation.ValidateReplicaSet(obj.(*extensions.ReplicaSet)) @@ -184,13 +185,13 @@ type rsStatusStrategy struct { var StatusStrategy = rsStatusStrategy{Strategy} -func (rsStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (rsStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newRS := obj.(*extensions.ReplicaSet) oldRS := old.(*extensions.ReplicaSet) // update is not allowed to set spec newRS.Spec = oldRS.Spec } -func (rsStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (rsStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateReplicaSetStatusUpdate(obj.(*extensions.ReplicaSet), old.(*extensions.ReplicaSet)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/rest/storage_apps.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/rest/storage_apps.go index 96bb06963..b8e683ee9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/rest/storage_apps.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/rest/storage_apps.go @@ -36,21 +36,18 @@ import ( type RESTStorageProvider struct{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(appsapiv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[appsapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = appsapiv1beta1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(appsapiv1beta2.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[appsapiv1beta2.SchemeGroupVersion.Version] = p.v1beta2Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = appsapiv1beta2.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(appsapiv1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[appsapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = appsapiv1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/registry.go index eb33b6e1c..b9d496478 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/registry.go @@ -17,25 +17,25 @@ limitations under the License. package statefulset import ( + "context" "fmt" "k8s.io/apimachinery/pkg/api/errors" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/apps" ) // Registry is an interface for things that know how to store StatefulSets. type Registry interface { - ListStatefulSets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*apps.StatefulSetList, error) - WatchStatefulSets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) - GetStatefulSet(ctx genericapirequest.Context, statefulSetID string, options *metav1.GetOptions) (*apps.StatefulSet, error) - CreateStatefulSet(ctx genericapirequest.Context, statefulSet *apps.StatefulSet, createValidation rest.ValidateObjectFunc) (*apps.StatefulSet, error) - UpdateStatefulSet(ctx genericapirequest.Context, statefulSet *apps.StatefulSet, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*apps.StatefulSet, error) - DeleteStatefulSet(ctx genericapirequest.Context, statefulSetID string) error + ListStatefulSets(ctx context.Context, options *metainternalversion.ListOptions) (*apps.StatefulSetList, error) + WatchStatefulSets(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetStatefulSet(ctx context.Context, statefulSetID string, options *metav1.GetOptions) (*apps.StatefulSet, error) + CreateStatefulSet(ctx context.Context, statefulSet *apps.StatefulSet, createValidation rest.ValidateObjectFunc) (*apps.StatefulSet, error) + UpdateStatefulSet(ctx context.Context, statefulSet *apps.StatefulSet, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*apps.StatefulSet, error) + DeleteStatefulSet(ctx context.Context, statefulSetID string) error } // storage puts strong typing around storage calls @@ -49,7 +49,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListStatefulSets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*apps.StatefulSetList, error) { +func (s *storage) ListStatefulSets(ctx context.Context, options *metainternalversion.ListOptions) (*apps.StatefulSetList, error) { if options != nil && options.FieldSelector != nil && !options.FieldSelector.Empty() { return nil, fmt.Errorf("field selector not supported yet") } @@ -60,11 +60,11 @@ func (s *storage) ListStatefulSets(ctx genericapirequest.Context, options *metai return obj.(*apps.StatefulSetList), err } -func (s *storage) WatchStatefulSets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchStatefulSets(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetStatefulSet(ctx genericapirequest.Context, statefulSetID string, options *metav1.GetOptions) (*apps.StatefulSet, error) { +func (s *storage) GetStatefulSet(ctx context.Context, statefulSetID string, options *metav1.GetOptions) (*apps.StatefulSet, error) { obj, err := s.Get(ctx, statefulSetID, options) if err != nil { return nil, errors.NewNotFound(apps.Resource("statefulsets/scale"), statefulSetID) @@ -72,7 +72,7 @@ func (s *storage) GetStatefulSet(ctx genericapirequest.Context, statefulSetID st return obj.(*apps.StatefulSet), nil } -func (s *storage) CreateStatefulSet(ctx genericapirequest.Context, statefulSet *apps.StatefulSet, createValidation rest.ValidateObjectFunc) (*apps.StatefulSet, error) { +func (s *storage) CreateStatefulSet(ctx context.Context, statefulSet *apps.StatefulSet, createValidation rest.ValidateObjectFunc) (*apps.StatefulSet, error) { obj, err := s.Create(ctx, statefulSet, rest.ValidateAllObjectFunc, false) if err != nil { return nil, err @@ -80,7 +80,7 @@ func (s *storage) CreateStatefulSet(ctx genericapirequest.Context, statefulSet * return obj.(*apps.StatefulSet), nil } -func (s *storage) UpdateStatefulSet(ctx genericapirequest.Context, statefulSet *apps.StatefulSet, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*apps.StatefulSet, error) { +func (s *storage) UpdateStatefulSet(ctx context.Context, statefulSet *apps.StatefulSet, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*apps.StatefulSet, error) { obj, _, err := s.Update(ctx, statefulSet.Name, rest.DefaultUpdatedObjectInfo(statefulSet), createValidation, updateValidation) if err != nil { return nil, err @@ -88,7 +88,7 @@ func (s *storage) UpdateStatefulSet(ctx genericapirequest.Context, statefulSet * return obj.(*apps.StatefulSet), nil } -func (s *storage) DeleteStatefulSet(ctx genericapirequest.Context, statefulSetID string) error { +func (s *storage) DeleteStatefulSet(ctx context.Context, statefulSetID string) error { _, _, err := s.Delete(ctx, statefulSetID, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/storage/BUILD index b67e2fea5..3708a705f 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/storage/BUILD @@ -49,7 +49,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/storage/storage.go index d97f17270..5ec3dfb2a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/storage/storage.go @@ -17,13 +17,13 @@ limitations under the License. package storage import ( + "context" "fmt" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -104,12 +104,12 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } @@ -145,7 +145,7 @@ func (r *ScaleREST) New() runtime.Object { return &autoscaling.Scale{} } -func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *ScaleREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { ss, err := r.registry.GetStatefulSet(ctx, name, options) if err != nil { return nil, err @@ -157,7 +157,7 @@ func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *met return scale, err } -func (r *ScaleREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { ss, err := r.registry.GetStatefulSet(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, err diff --git a/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/strategy.go index 08ff765a3..cbf584933 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/apps/statefulset/strategy.go @@ -17,6 +17,8 @@ limitations under the License. package statefulset import ( + "context" + appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta2 "k8s.io/api/apps/v1beta2" apiequality "k8s.io/apimachinery/pkg/api/equality" @@ -42,7 +44,7 @@ type statefulSetStrategy struct { var Strategy = statefulSetStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} // DefaultGarbageCollectionPolicy returns OrphanDependents by default. For apps/v1, returns DeleteDependents. -func (statefulSetStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (statefulSetStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} switch groupVersion { @@ -62,7 +64,7 @@ func (statefulSetStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of an StatefulSet before creation. -func (statefulSetStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (statefulSetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { statefulSet := obj.(*apps.StatefulSet) // create cannot set status statefulSet.Status = apps.StatefulSetStatus{} @@ -73,7 +75,7 @@ func (statefulSetStrategy) PrepareForCreate(ctx genericapirequest.Context, obj r } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (statefulSetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (statefulSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newStatefulSet := obj.(*apps.StatefulSet) oldStatefulSet := old.(*apps.StatefulSet) // Update is not allowed to set status @@ -92,7 +94,7 @@ func (statefulSetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, } // Validate validates a new StatefulSet. -func (statefulSetStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (statefulSetStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { statefulSet := obj.(*apps.StatefulSet) return validation.ValidateStatefulSet(statefulSet) } @@ -107,7 +109,7 @@ func (statefulSetStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (statefulSetStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (statefulSetStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { validationErrorList := validation.ValidateStatefulSet(obj.(*apps.StatefulSet)) updateErrorList := validation.ValidateStatefulSetUpdate(obj.(*apps.StatefulSet), old.(*apps.StatefulSet)) return append(validationErrorList, updateErrorList...) @@ -125,7 +127,7 @@ type statefulSetStatusStrategy struct { var StatusStrategy = statefulSetStatusStrategy{Strategy} // PrepareForUpdate clears fields that are not allowed to be set by end users on update of status -func (statefulSetStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (statefulSetStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newStatefulSet := obj.(*apps.StatefulSet) oldStatefulSet := old.(*apps.StatefulSet) // status changes are not allowed to update spec @@ -133,7 +135,7 @@ func (statefulSetStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, } // ValidateUpdate is the default update validation for an end user updating status -func (statefulSetStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (statefulSetStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { // TODO: Validate status updates. return validation.ValidateStatefulSetStatusUpdate(obj.(*apps.StatefulSet), old.(*apps.StatefulSet)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/authentication/rest/storage_authentication.go b/vendor/k8s.io/kubernetes/pkg/registry/authentication/rest/storage_authentication.go index c55bd530d..5dec4aeb0 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/authentication/rest/storage_authentication.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/authentication/rest/storage_authentication.go @@ -39,17 +39,15 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag // return genericapiserver.APIGroupInfo{}, false // } - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(authentication.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(authentication.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(authenticationv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[authenticationv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = authenticationv1beta1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(authenticationv1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[authenticationv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = authenticationv1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/authentication/tokenreview/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/authentication/tokenreview/storage.go index 28c1da7c8..c90a01b68 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/authentication/tokenreview/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/authentication/tokenreview/storage.go @@ -17,6 +17,7 @@ limitations under the License. package tokenreview import ( + "context" "fmt" "net/http" @@ -36,11 +37,15 @@ func NewREST(tokenAuthenticator authenticator.Request) *REST { return &REST{tokenAuthenticator: tokenAuthenticator} } +func (r *REST) NamespaceScoped() bool { + return false +} + func (r *REST) New() runtime.Object { return &authentication.TokenReview{} } -func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { tokenReview, ok := obj.(*authentication.TokenReview) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("not a TokenReview: %#v", obj)) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/authorization/localsubjectaccessreview/rest.go b/vendor/k8s.io/kubernetes/pkg/registry/authorization/localsubjectaccessreview/rest.go index af49b6bd4..c2e6a5dcc 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/authorization/localsubjectaccessreview/rest.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/authorization/localsubjectaccessreview/rest.go @@ -17,6 +17,7 @@ limitations under the License. package localsubjectaccessreview import ( + "context" "fmt" kapierrors "k8s.io/apimachinery/pkg/api/errors" @@ -37,11 +38,15 @@ func NewREST(authorizer authorizer.Authorizer) *REST { return &REST{authorizer} } +func (r *REST) NamespaceScoped() bool { + return true +} + func (r *REST) New() runtime.Object { return &authorizationapi.LocalSubjectAccessReview{} } -func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { localSubjectAccessReview, ok := obj.(*authorizationapi.LocalSubjectAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a LocaLocalSubjectAccessReview: %#v", obj)) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/authorization/rest/storage_authorization.go b/vendor/k8s.io/kubernetes/pkg/registry/authorization/rest/storage_authorization.go index f127e19cc..af79bf441 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/authorization/rest/storage_authorization.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/authorization/rest/storage_authorization.go @@ -42,18 +42,16 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag return genericapiserver.APIGroupInfo{}, false } - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(authorization.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(authorization.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(authorizationv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[authorizationv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = authorizationv1beta1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(authorizationv1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[authorizationv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = authorizationv1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/authorization/selfsubjectaccessreview/rest.go b/vendor/k8s.io/kubernetes/pkg/registry/authorization/selfsubjectaccessreview/rest.go index 38900a877..236034eea 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/authorization/selfsubjectaccessreview/rest.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/authorization/selfsubjectaccessreview/rest.go @@ -17,6 +17,7 @@ limitations under the License. package selfsubjectaccessreview import ( + "context" "fmt" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -37,11 +38,15 @@ func NewREST(authorizer authorizer.Authorizer) *REST { return &REST{authorizer} } +func (r *REST) NamespaceScoped() bool { + return false +} + func (r *REST) New() runtime.Object { return &authorizationapi.SelfSubjectAccessReview{} } -func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { selfSAR, ok := obj.(*authorizationapi.SelfSubjectAccessReview) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("not a SelfSubjectAccessReview: %#v", obj)) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/authorization/selfsubjectrulesreview/rest.go b/vendor/k8s.io/kubernetes/pkg/registry/authorization/selfsubjectrulesreview/rest.go index 2093f324e..610d88230 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/authorization/selfsubjectrulesreview/rest.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/authorization/selfsubjectrulesreview/rest.go @@ -17,6 +17,7 @@ limitations under the License. package selfsubjectrulesreview import ( + "context" "fmt" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -37,13 +38,18 @@ func NewREST(ruleResolver authorizer.RuleResolver) *REST { return &REST{ruleResolver} } +// NamespaceScoped fulfill rest.Scoper +func (r *REST) NamespaceScoped() bool { + return false +} + // New creates a new selfsubjectrulesreview object. func (r *REST) New() runtime.Object { return &authorizationapi.SelfSubjectRulesReview{} } // Create attempts to get self subject rules in specific namespace. -func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { selfSRR, ok := obj.(*authorizationapi.SelfSubjectRulesReview) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("not a SelfSubjectRulesReview: %#v", obj)) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview/BUILD index 09d797c1f..d15e51e6d 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview/BUILD @@ -17,7 +17,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview/rest.go b/vendor/k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview/rest.go index 92da3d342..3fe3da03c 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview/rest.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview/rest.go @@ -17,12 +17,12 @@ limitations under the License. package subjectaccessreview import ( + "context" "fmt" kapierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/authorization/authorizer" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" authorizationvalidation "k8s.io/kubernetes/pkg/apis/authorization/validation" @@ -37,11 +37,15 @@ func NewREST(authorizer authorizer.Authorizer) *REST { return &REST{authorizer} } +func (r *REST) NamespaceScoped() bool { + return false +} + func (r *REST) New() runtime.Object { return &authorizationapi.SubjectAccessReview{} } -func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { subjectAccessReview, ok := obj.(*authorizationapi.SubjectAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a SubjectAccessReview: %#v", obj)) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/BUILD index e5fef0856..0e2901c76 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/BUILD @@ -18,7 +18,6 @@ go_library( "//pkg/apis/autoscaling/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/storage/BUILD index f5fde8df4..f180e2d2e 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/storage/BUILD @@ -41,7 +41,6 @@ go_library( "//pkg/registry/autoscaling/horizontalpodautoscaler:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go index 4e5ccca06..f6a6dc5cf 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -83,11 +84,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/strategy.go index 3100a9698..12dbad2dd 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package horizontalpodautoscaler import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/autoscaling" @@ -42,7 +43,7 @@ func (autoscalerStrategy) NamespaceScoped() bool { } // PrepareForCreate clears fields that are not allowed to be set by end users on creation. -func (autoscalerStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (autoscalerStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { newHPA := obj.(*autoscaling.HorizontalPodAutoscaler) // create cannot set status @@ -50,7 +51,7 @@ func (autoscalerStrategy) PrepareForCreate(ctx genericapirequest.Context, obj ru } // Validate validates a new autoscaler. -func (autoscalerStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (autoscalerStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { autoscaler := obj.(*autoscaling.HorizontalPodAutoscaler) return validation.ValidateHorizontalPodAutoscaler(autoscaler) } @@ -65,7 +66,7 @@ func (autoscalerStrategy) AllowCreateOnUpdate() bool { } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (autoscalerStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (autoscalerStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newHPA := obj.(*autoscaling.HorizontalPodAutoscaler) oldHPA := old.(*autoscaling.HorizontalPodAutoscaler) // Update is not allowed to set status @@ -73,7 +74,7 @@ func (autoscalerStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, o } // ValidateUpdate is the default update validation for an end user. -func (autoscalerStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (autoscalerStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateHorizontalPodAutoscalerUpdate(obj.(*autoscaling.HorizontalPodAutoscaler), old.(*autoscaling.HorizontalPodAutoscaler)) } @@ -87,13 +88,13 @@ type autoscalerStatusStrategy struct { var StatusStrategy = autoscalerStatusStrategy{Strategy} -func (autoscalerStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (autoscalerStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newAutoscaler := obj.(*autoscaling.HorizontalPodAutoscaler) oldAutoscaler := old.(*autoscaling.HorizontalPodAutoscaler) // status changes are not allowed to update spec newAutoscaler.Spec = oldAutoscaler.Spec } -func (autoscalerStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (autoscalerStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateHorizontalPodAutoscalerStatusUpdate(obj.(*autoscaling.HorizontalPodAutoscaler), old.(*autoscaling.HorizontalPodAutoscaler)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/rest/storage_autoscaling.go b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/rest/storage_autoscaling.go index 7a023571c..021beb070 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/rest/storage_autoscaling.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/autoscaling/rest/storage_autoscaling.go @@ -31,17 +31,15 @@ import ( type RESTStorageProvider struct{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(autoscaling.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(autoscaling.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(autoscalingapiv2beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv2beta1.SchemeGroupVersion.Version] = p.v2beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = autoscalingapiv2beta1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(autoscalingapiv1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = autoscalingapiv1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/BUILD index ac61eca1d..c71f3fb08 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/BUILD @@ -20,7 +20,6 @@ go_library( "//pkg/apis/batch/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/storage/BUILD index ab8de0a52..674818aa1 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/storage/BUILD @@ -38,7 +38,6 @@ go_library( "//pkg/registry/batch/cronjob:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/storage/storage.go index 7826ea5a1..dcb151f76 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -82,11 +83,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/strategy.go index 3544ca10b..1e756d6b1 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/cronjob/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package cronjob import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -39,7 +40,7 @@ var Strategy = cronJobStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} // DefaultGarbageCollectionPolicy returns Orphan because that was the default // behavior before the server-side garbage collection was implemented. -func (cronJobStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (cronJobStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { return rest.OrphanDependents } @@ -49,7 +50,7 @@ func (cronJobStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a scheduled job before creation. -func (cronJobStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (cronJobStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { cronJob := obj.(*batch.CronJob) cronJob.Status = batch.CronJobStatus{} @@ -57,7 +58,7 @@ func (cronJobStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runti } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (cronJobStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (cronJobStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newCronJob := obj.(*batch.CronJob) oldCronJob := old.(*batch.CronJob) newCronJob.Status = oldCronJob.Status @@ -67,7 +68,7 @@ func (cronJobStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old } // Validate validates a new scheduled job. -func (cronJobStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (cronJobStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { cronJob := obj.(*batch.CronJob) return validation.ValidateCronJob(cronJob) } @@ -86,7 +87,7 @@ func (cronJobStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (cronJobStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (cronJobStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateCronJobUpdate(obj.(*batch.CronJob), old.(*batch.CronJob)) } @@ -96,12 +97,12 @@ type cronJobStatusStrategy struct { var StatusStrategy = cronJobStatusStrategy{Strategy} -func (cronJobStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (cronJobStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newJob := obj.(*batch.CronJob) oldJob := old.(*batch.CronJob) newJob.Spec = oldJob.Spec } -func (cronJobStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (cronJobStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return field.ErrorList{} } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/BUILD index 1c3e57aed..31f9eea1a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/BUILD @@ -23,7 +23,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/storage/BUILD index e53918f07..86b5dd8de 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/storage/BUILD @@ -36,7 +36,6 @@ go_library( "//pkg/registry/batch/job:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/storage/storage.go index 580cc5a75..7162f61dd 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -93,11 +94,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/strategy.go index aecf38a36..c0eb2be5f 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/strategy.go @@ -17,6 +17,7 @@ limitations under the License. package job import ( + "context" "fmt" "strconv" @@ -25,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage" @@ -47,7 +47,7 @@ var Strategy = jobStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} // DefaultGarbageCollectionPolicy returns Orphan because that was the default // behavior before the server-side garbage collection was implemented. -func (jobStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (jobStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { return rest.OrphanDependents } @@ -57,7 +57,7 @@ func (jobStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a job before creation. -func (jobStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (jobStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { job := obj.(*batch.Job) job.Status = batch.JobStatus{} @@ -65,7 +65,7 @@ func (jobStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.O } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (jobStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (jobStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newJob := obj.(*batch.Job) oldJob := old.(*batch.Job) newJob.Status = oldJob.Status @@ -75,7 +75,7 @@ func (jobStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runt } // Validate validates a new job. -func (jobStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (jobStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { job := obj.(*batch.Job) // TODO: move UID generation earlier and do this in defaulting logic? if job.Spec.ManualSelector == nil || *job.Spec.ManualSelector == false { @@ -148,7 +148,7 @@ func (jobStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (jobStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (jobStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { validationErrorList := validation.ValidateJob(obj.(*batch.Job)) updateErrorList := validation.ValidateJobUpdate(obj.(*batch.Job), old.(*batch.Job)) return append(validationErrorList, updateErrorList...) @@ -160,13 +160,13 @@ type jobStatusStrategy struct { var StatusStrategy = jobStatusStrategy{Strategy} -func (jobStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (jobStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newJob := obj.(*batch.Job) oldJob := old.(*batch.Job) newJob.Spec = oldJob.Spec } -func (jobStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (jobStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateJobUpdateStatus(obj.(*batch.Job), old.(*batch.Job)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/rest/storage_batch.go b/vendor/k8s.io/kubernetes/pkg/registry/batch/rest/storage_batch.go index 7b225a5f7..4568e8bd9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/rest/storage_batch.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/rest/storage_batch.go @@ -33,21 +33,18 @@ import ( type RESTStorageProvider struct{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(batchapiv1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[batchapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = batchapiv1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(batchapiv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[batchapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = batchapiv1beta1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(batchapiv2alpha1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[batchapiv2alpha1.SchemeGroupVersion.Version] = p.v2alpha1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = batchapiv2alpha1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/registry.go index d3eea018b..e48a6382b 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/registry.go @@ -17,22 +17,23 @@ limitations under the License. package certificates import ( + "context" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/certificates" ) // Registry is an interface for things that know how to store CSRs. type Registry interface { - ListCSRs(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*certificates.CertificateSigningRequestList, error) - CreateCSR(ctx genericapirequest.Context, csr *certificates.CertificateSigningRequest, createValidation rest.ValidateObjectFunc) error - UpdateCSR(ctx genericapirequest.Context, csr *certificates.CertificateSigningRequest, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetCSR(ctx genericapirequest.Context, csrID string, options *metav1.GetOptions) (*certificates.CertificateSigningRequest, error) - DeleteCSR(ctx genericapirequest.Context, csrID string) error - WatchCSRs(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ListCSRs(ctx context.Context, options *metainternalversion.ListOptions) (*certificates.CertificateSigningRequestList, error) + CreateCSR(ctx context.Context, csr *certificates.CertificateSigningRequest, createValidation rest.ValidateObjectFunc) error + UpdateCSR(ctx context.Context, csr *certificates.CertificateSigningRequest, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error + GetCSR(ctx context.Context, csrID string, options *metav1.GetOptions) (*certificates.CertificateSigningRequest, error) + DeleteCSR(ctx context.Context, csrID string) error + WatchCSRs(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) } // storage puts strong typing around storage calls @@ -46,7 +47,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListCSRs(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*certificates.CertificateSigningRequestList, error) { +func (s *storage) ListCSRs(ctx context.Context, options *metainternalversion.ListOptions) (*certificates.CertificateSigningRequestList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err @@ -55,21 +56,21 @@ func (s *storage) ListCSRs(ctx genericapirequest.Context, options *metainternalv return obj.(*certificates.CertificateSigningRequestList), nil } -func (s *storage) CreateCSR(ctx genericapirequest.Context, csr *certificates.CertificateSigningRequest, createValidation rest.ValidateObjectFunc) error { +func (s *storage) CreateCSR(ctx context.Context, csr *certificates.CertificateSigningRequest, createValidation rest.ValidateObjectFunc) error { _, err := s.Create(ctx, csr, createValidation, false) return err } -func (s *storage) UpdateCSR(ctx genericapirequest.Context, csr *certificates.CertificateSigningRequest, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { +func (s *storage) UpdateCSR(ctx context.Context, csr *certificates.CertificateSigningRequest, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { _, _, err := s.Update(ctx, csr.Name, rest.DefaultUpdatedObjectInfo(csr), createValidation, updateValidation) return err } -func (s *storage) WatchCSRs(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchCSRs(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetCSR(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*certificates.CertificateSigningRequest, error) { +func (s *storage) GetCSR(ctx context.Context, name string, options *metav1.GetOptions) (*certificates.CertificateSigningRequest, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err @@ -77,7 +78,7 @@ func (s *storage) GetCSR(ctx genericapirequest.Context, name string, options *me return obj.(*certificates.CertificateSigningRequest), nil } -func (s *storage) DeleteCSR(ctx genericapirequest.Context, name string) error { +func (s *storage) DeleteCSR(ctx context.Context, name string) error { _, _, err := s.Delete(ctx, name, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/storage/BUILD index 23a233920..35113cdd6 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/storage/BUILD @@ -15,8 +15,8 @@ go_library( "//pkg/printers/internalversion:go_default_library", "//pkg/printers/storage:go_default_library", "//pkg/registry/certificates/certificates:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/storage/storage.go index 77ab436fc..378c6f29a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/storage/storage.go @@ -17,8 +17,10 @@ limitations under the License. package storage import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -82,11 +84,18 @@ func (r *StatusREST) New() runtime.Object { return &certificates.CertificateSigningRequest{} } +// Get retrieves the object from the storage. It is required to support Patch. +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + return r.store.Get(ctx, name, options) +} + // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } +var _ = rest.Patcher(&StatusREST{}) + // ApprovalREST implements the REST endpoint for changing the approval state of a CSR. type ApprovalREST struct { store *genericregistry.Store @@ -97,6 +106,6 @@ func (r *ApprovalREST) New() runtime.Object { } // Update alters the approval subset of an object. -func (r *ApprovalREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *ApprovalREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/strategy.go index eff6a8965..82830ea6e 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/strategy.go @@ -17,6 +17,7 @@ limitations under the License. package certificates import ( + "context" "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -51,7 +52,7 @@ func (csrStrategy) AllowCreateOnUpdate() bool { // PrepareForCreate clears fields that are not allowed to be set by end users // on creation. -func (csrStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (csrStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { csr := obj.(*certificates.CertificateSigningRequest) // Clear any user-specified info @@ -79,7 +80,7 @@ func (csrStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.O // PrepareForUpdate clears fields that are not allowed to be set by end users // on update. Certificate requests are immutable after creation except via subresources. -func (csrStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (csrStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newCSR := obj.(*certificates.CertificateSigningRequest) oldCSR := old.(*certificates.CertificateSigningRequest) @@ -88,7 +89,7 @@ func (csrStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runt } // Validate validates a new CSR. Validation must check for a correct signature. -func (csrStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (csrStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { csr := obj.(*certificates.CertificateSigningRequest) return validation.ValidateCertificateSigningRequest(csr) } @@ -97,7 +98,7 @@ func (csrStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) f func (csrStrategy) Canonicalize(obj runtime.Object) {} // ValidateUpdate is the default update validation for an end user. -func (csrStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (csrStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { oldCSR := old.(*certificates.CertificateSigningRequest) newCSR := obj.(*certificates.CertificateSigningRequest) return validation.ValidateCertificateSigningRequestUpdate(newCSR, oldCSR) @@ -112,7 +113,7 @@ func (csrStrategy) AllowUnconditionalUpdate() bool { return true } -func (s csrStrategy) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error { +func (s csrStrategy) Export(ctx context.Context, obj runtime.Object, exact bool) error { csr, ok := obj.(*certificates.CertificateSigningRequest) if !ok { // unexpected programmer error @@ -134,7 +135,7 @@ type csrStatusStrategy struct { var StatusStrategy = csrStatusStrategy{Strategy} -func (csrStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (csrStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newCSR := obj.(*certificates.CertificateSigningRequest) oldCSR := old.(*certificates.CertificateSigningRequest) @@ -150,7 +151,7 @@ func (csrStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, ol } } -func (csrStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (csrStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateCertificateSigningRequestUpdate(obj.(*certificates.CertificateSigningRequest), old.(*certificates.CertificateSigningRequest)) } @@ -168,7 +169,7 @@ var ApprovalStrategy = csrApprovalStrategy{Strategy} // PrepareForUpdate prepares the new certificate signing request by limiting // the data that is updated to only the conditions. Also, if there is no // existing LastUpdateTime on a condition, the current date/time will be set. -func (csrApprovalStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (csrApprovalStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newCSR := obj.(*certificates.CertificateSigningRequest) oldCSR := old.(*certificates.CertificateSigningRequest) @@ -186,6 +187,6 @@ func (csrApprovalStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, newCSR.Status = oldCSR.Status } -func (csrApprovalStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (csrApprovalStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateCertificateSigningRequestUpdate(obj.(*certificates.CertificateSigningRequest), old.(*certificates.CertificateSigningRequest)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/strategy_test.go b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/strategy_test.go index d6d2b2c01..b1b660ba0 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/strategy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/certificates/certificates/strategy_test.go @@ -17,6 +17,7 @@ limitations under the License. package certificates import ( + "context" "reflect" "testing" @@ -29,7 +30,7 @@ import ( func TestStrategyCreate(t *testing.T) { tests := map[string]struct { - ctx genericapirequest.Context + ctx context.Context obj runtime.Object expectedObj runtime.Object }{ diff --git a/vendor/k8s.io/kubernetes/pkg/registry/certificates/rest/storage_certificates.go b/vendor/k8s.io/kubernetes/pkg/registry/certificates/rest/storage_certificates.go index 777312aa0..aa1fbc1ae 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/certificates/rest/storage_certificates.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/certificates/rest/storage_certificates.go @@ -30,13 +30,12 @@ import ( type RESTStorageProvider struct{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(certificates.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(certificates.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(certificatesapiv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = certificatesapiv1beta1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/componentstatus/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/componentstatus/BUILD index d58dd84b1..453aa8128 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/componentstatus/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/componentstatus/BUILD @@ -22,7 +22,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/componentstatus/rest.go b/vendor/k8s.io/kubernetes/pkg/registry/core/componentstatus/rest.go index c67b42ead..ed8aaec6c 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/componentstatus/rest.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/componentstatus/rest.go @@ -17,13 +17,13 @@ limitations under the License. package componentstatus import ( + "context" "fmt" "sync" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/probe" @@ -40,6 +40,10 @@ func NewStorage(serverRetriever func() map[string]*Server) *REST { } } +func (*REST) NamespaceScoped() bool { + return false +} + func (rs *REST) New() runtime.Object { return &api.ComponentStatus{} } @@ -50,7 +54,7 @@ func (rs *REST) NewList() runtime.Object { // Returns the list of component status. Note that the label and field are both ignored. // Note that this call doesn't support labels or selectors. -func (rs *REST) List(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { +func (rs *REST) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { servers := rs.GetServersToValidate() wait := sync.WaitGroup{} @@ -73,7 +77,7 @@ func (rs *REST) List(ctx genericapirequest.Context, options *metainternalversion return &api.ComponentStatusList{Items: reply}, nil } -func (rs *REST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (rs *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { servers := rs.GetServersToValidate() if server, ok := servers[name]; !ok { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/BUILD index b9f7c6398..d14a2eb29 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/BUILD @@ -23,7 +23,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/registry.go index 440300f2d..33784fe5e 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/registry.go @@ -17,22 +17,23 @@ limitations under the License. package configmap import ( + "context" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" ) // Registry is an interface for things that know how to store ConfigMaps. type Registry interface { - ListConfigMaps(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.ConfigMapList, error) - WatchConfigMaps(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) - GetConfigMap(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*api.ConfigMap, error) - CreateConfigMap(ctx genericapirequest.Context, cfg *api.ConfigMap, createValidation rest.ValidateObjectFunc) (*api.ConfigMap, error) - UpdateConfigMap(ctx genericapirequest.Context, cfg *api.ConfigMap, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.ConfigMap, error) - DeleteConfigMap(ctx genericapirequest.Context, name string) error + ListConfigMaps(ctx context.Context, options *metainternalversion.ListOptions) (*api.ConfigMapList, error) + WatchConfigMaps(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetConfigMap(ctx context.Context, name string, options *metav1.GetOptions) (*api.ConfigMap, error) + CreateConfigMap(ctx context.Context, cfg *api.ConfigMap, createValidation rest.ValidateObjectFunc) (*api.ConfigMap, error) + UpdateConfigMap(ctx context.Context, cfg *api.ConfigMap, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.ConfigMap, error) + DeleteConfigMap(ctx context.Context, name string) error } // storage puts strong typing around storage calls @@ -46,7 +47,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListConfigMaps(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.ConfigMapList, error) { +func (s *storage) ListConfigMaps(ctx context.Context, options *metainternalversion.ListOptions) (*api.ConfigMapList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err @@ -55,11 +56,11 @@ func (s *storage) ListConfigMaps(ctx genericapirequest.Context, options *metaint return obj.(*api.ConfigMapList), err } -func (s *storage) WatchConfigMaps(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchConfigMaps(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetConfigMap(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*api.ConfigMap, error) { +func (s *storage) GetConfigMap(ctx context.Context, name string, options *metav1.GetOptions) (*api.ConfigMap, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err @@ -68,7 +69,7 @@ func (s *storage) GetConfigMap(ctx genericapirequest.Context, name string, optio return obj.(*api.ConfigMap), nil } -func (s *storage) CreateConfigMap(ctx genericapirequest.Context, cfg *api.ConfigMap, createValidation rest.ValidateObjectFunc) (*api.ConfigMap, error) { +func (s *storage) CreateConfigMap(ctx context.Context, cfg *api.ConfigMap, createValidation rest.ValidateObjectFunc) (*api.ConfigMap, error) { obj, err := s.Create(ctx, cfg, createValidation, false) if err != nil { return nil, err @@ -77,7 +78,7 @@ func (s *storage) CreateConfigMap(ctx genericapirequest.Context, cfg *api.Config return obj.(*api.ConfigMap), nil } -func (s *storage) UpdateConfigMap(ctx genericapirequest.Context, cfg *api.ConfigMap, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.ConfigMap, error) { +func (s *storage) UpdateConfigMap(ctx context.Context, cfg *api.ConfigMap, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.ConfigMap, error) { obj, _, err := s.Update(ctx, cfg.Name, rest.DefaultUpdatedObjectInfo(cfg), createValidation, updateValidation) if err != nil { return nil, err @@ -86,7 +87,7 @@ func (s *storage) UpdateConfigMap(ctx genericapirequest.Context, cfg *api.Config return obj.(*api.ConfigMap), nil } -func (s *storage) DeleteConfigMap(ctx genericapirequest.Context, name string) error { +func (s *storage) DeleteConfigMap(ctx context.Context, name string) error { _, _, err := s.Delete(ctx, name, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/strategy.go index 58f57f4f9..6cf9a6172 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/configmap/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package configmap import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -47,11 +48,11 @@ func (strategy) NamespaceScoped() bool { return true } -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { _ = obj.(*api.ConfigMap) } -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { cfg := obj.(*api.ConfigMap) return validation.ValidateConfigMap(cfg) @@ -65,7 +66,7 @@ func (strategy) AllowCreateOnUpdate() bool { return false } -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, newObj, oldObj runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, newObj, oldObj runtime.Object) { _ = oldObj.(*api.ConfigMap) _ = newObj.(*api.ConfigMap) } @@ -74,7 +75,7 @@ func (strategy) AllowUnconditionalUpdate() bool { return true } -func (strategy) ValidateUpdate(ctx genericapirequest.Context, newObj, oldObj runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, newObj, oldObj runtime.Object) field.ErrorList { oldCfg, newCfg := oldObj.(*api.ConfigMap), newObj.(*api.ConfigMap) return validation.ValidateConfigMapUpdate(newCfg, oldCfg) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/BUILD index 775b19583..d87f67932 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/BUILD @@ -23,7 +23,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/registry.go index 3cb03c4f9..fec4e517d 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/registry.go @@ -17,21 +17,22 @@ limitations under the License. package endpoint import ( + "context" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" ) // Registry is an interface for things that know how to store endpoints. type Registry interface { - ListEndpoints(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.EndpointsList, error) - GetEndpoints(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*api.Endpoints, error) - WatchEndpoints(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) - UpdateEndpoints(ctx genericapirequest.Context, e *api.Endpoints, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - DeleteEndpoints(ctx genericapirequest.Context, name string) error + ListEndpoints(ctx context.Context, options *metainternalversion.ListOptions) (*api.EndpointsList, error) + GetEndpoints(ctx context.Context, name string, options *metav1.GetOptions) (*api.Endpoints, error) + WatchEndpoints(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + UpdateEndpoints(ctx context.Context, e *api.Endpoints, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error + DeleteEndpoints(ctx context.Context, name string) error } // storage puts strong typing around storage calls @@ -45,7 +46,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListEndpoints(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.EndpointsList, error) { +func (s *storage) ListEndpoints(ctx context.Context, options *metainternalversion.ListOptions) (*api.EndpointsList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err @@ -53,11 +54,11 @@ func (s *storage) ListEndpoints(ctx genericapirequest.Context, options *metainte return obj.(*api.EndpointsList), nil } -func (s *storage) WatchEndpoints(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchEndpoints(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetEndpoints(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*api.Endpoints, error) { +func (s *storage) GetEndpoints(ctx context.Context, name string, options *metav1.GetOptions) (*api.Endpoints, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err @@ -65,12 +66,12 @@ func (s *storage) GetEndpoints(ctx genericapirequest.Context, name string, optio return obj.(*api.Endpoints), nil } -func (s *storage) UpdateEndpoints(ctx genericapirequest.Context, endpoints *api.Endpoints, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { +func (s *storage) UpdateEndpoints(ctx context.Context, endpoints *api.Endpoints, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { _, _, err := s.Update(ctx, endpoints.Name, rest.DefaultUpdatedObjectInfo(endpoints), createValidation, updateValidation) return err } -func (s *storage) DeleteEndpoints(ctx genericapirequest.Context, name string) error { +func (s *storage) DeleteEndpoints(ctx context.Context, name string) error { _, _, err := s.Delete(ctx, name, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/strategy.go index 93204e6ca..bd6ede7cd 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/endpoint/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package endpoint import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" endptspkg "k8s.io/kubernetes/pkg/api/endpoints" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -43,15 +44,15 @@ func (endpointsStrategy) NamespaceScoped() bool { } // PrepareForCreate clears fields that are not allowed to be set by end users on creation. -func (endpointsStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (endpointsStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (endpointsStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (endpointsStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } // Validate validates a new endpoints. -func (endpointsStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (endpointsStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return validation.ValidateEndpoints(obj.(*api.Endpoints)) } @@ -67,7 +68,7 @@ func (endpointsStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (endpointsStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (endpointsStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { errorList := validation.ValidateEndpoints(obj.(*api.Endpoints)) return append(errorList, validation.ValidateEndpointsUpdate(obj.(*api.Endpoints), old.(*api.Endpoints))...) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/event/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/event/BUILD index 53fa733b7..90401ab9b 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/event/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/event/BUILD @@ -21,7 +21,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", @@ -34,7 +33,6 @@ go_test( srcs = ["strategy_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/apis/core:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/event/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/event/strategy.go index 0ca15dfa6..bfe3c9d59 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/event/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/event/strategy.go @@ -17,13 +17,13 @@ limitations under the License. package event import ( + "context" "fmt" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage" @@ -42,7 +42,7 @@ type eventStrategy struct { // Event objects via the REST API. var Strategy = eventStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} -func (eventStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (eventStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { return rest.Unsupported } @@ -50,13 +50,13 @@ func (eventStrategy) NamespaceScoped() bool { return true } -func (eventStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (eventStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { } -func (eventStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (eventStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } -func (eventStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (eventStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { event := obj.(*api.Event) return validation.ValidateEvent(event) } @@ -69,7 +69,7 @@ func (eventStrategy) AllowCreateOnUpdate() bool { return true } -func (eventStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (eventStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { event := obj.(*api.Event) return validation.ValidateEvent(event) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/event/strategy_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/event/strategy_test.go index fe1763798..96813e197 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/event/strategy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/event/strategy_test.go @@ -23,7 +23,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/util/diff" - "k8s.io/kubernetes/pkg/api/legacyscheme" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" @@ -42,7 +41,7 @@ func TestGetAttrs(t *testing.T) { Name: "foo", Namespace: "baz", UID: "long uid string", - APIVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + APIVersion: "v1", ResourceVersion: "0", FieldPath: "", }, @@ -58,7 +57,7 @@ func TestGetAttrs(t *testing.T) { "involvedObject.name": "foo", "involvedObject.namespace": "baz", "involvedObject.uid": "long uid string", - "involvedObject.apiVersion": legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + "involvedObject.apiVersion": "v1", "involvedObject.resourceVersion": "0", "involvedObject.fieldPath": "", "reason": "ForTesting", @@ -73,7 +72,7 @@ func TestGetAttrs(t *testing.T) { func TestSelectableFieldLabelConversions(t *testing.T) { fset := EventToSelectableFields(&api.Event{}) apitesting.TestSelectableFieldLabelConversionsOfKind(t, - legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + "v1", "Event", fset, nil, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/limitrange/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/limitrange/BUILD index 303471f79..e4daeb369 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/limitrange/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/limitrange/BUILD @@ -19,7 +19,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/limitrange/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/limitrange/strategy.go index b4a55075b..17e506e46 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/limitrange/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/limitrange/strategy.go @@ -17,10 +17,11 @@ limitations under the License. package limitrange import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" @@ -40,17 +41,17 @@ func (limitrangeStrategy) NamespaceScoped() bool { return true } -func (limitrangeStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (limitrangeStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { limitRange := obj.(*api.LimitRange) if len(limitRange.Name) == 0 { limitRange.Name = string(uuid.NewUUID()) } } -func (limitrangeStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (limitrangeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } -func (limitrangeStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (limitrangeStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { limitRange := obj.(*api.LimitRange) return validation.ValidateLimitRange(limitRange) } @@ -63,7 +64,7 @@ func (limitrangeStrategy) AllowCreateOnUpdate() bool { return true } -func (limitrangeStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (limitrangeStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { limitRange := obj.(*api.LimitRange) return validation.ValidateLimitRange(limitRange) } @@ -72,7 +73,7 @@ func (limitrangeStrategy) AllowUnconditionalUpdate() bool { return true } -func (limitrangeStrategy) Export(genericapirequest.Context, runtime.Object, bool) error { +func (limitrangeStrategy) Export(context.Context, runtime.Object, bool) error { // Copied from OpenShift exporter // TODO: this needs to be fixed // limitrange.Strategy.PrepareForCreate(ctx, obj) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/BUILD index 675e7db80..86ff2e237 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/BUILD @@ -25,7 +25,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", @@ -38,7 +37,6 @@ go_test( srcs = ["strategy_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/apis/core:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/registry.go index cbd470d15..ec5cf6749 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/registry.go @@ -17,22 +17,23 @@ limitations under the License. package namespace import ( + "context" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" ) // Registry is an interface implemented by things that know how to store Namespace objects. type Registry interface { - ListNamespaces(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.NamespaceList, error) - WatchNamespaces(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) - GetNamespace(ctx genericapirequest.Context, namespaceID string, options *metav1.GetOptions) (*api.Namespace, error) - CreateNamespace(ctx genericapirequest.Context, namespace *api.Namespace, createValidation rest.ValidateObjectFunc) error - UpdateNamespace(ctx genericapirequest.Context, namespace *api.Namespace, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - DeleteNamespace(ctx genericapirequest.Context, namespaceID string) error + ListNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (*api.NamespaceList, error) + WatchNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetNamespace(ctx context.Context, namespaceID string, options *metav1.GetOptions) (*api.Namespace, error) + CreateNamespace(ctx context.Context, namespace *api.Namespace, createValidation rest.ValidateObjectFunc) error + UpdateNamespace(ctx context.Context, namespace *api.Namespace, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error + DeleteNamespace(ctx context.Context, namespaceID string) error } // storage puts strong typing around storage calls @@ -46,7 +47,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListNamespaces(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.NamespaceList, error) { +func (s *storage) ListNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (*api.NamespaceList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err @@ -54,11 +55,11 @@ func (s *storage) ListNamespaces(ctx genericapirequest.Context, options *metaint return obj.(*api.NamespaceList), nil } -func (s *storage) WatchNamespaces(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetNamespace(ctx genericapirequest.Context, namespaceName string, options *metav1.GetOptions) (*api.Namespace, error) { +func (s *storage) GetNamespace(ctx context.Context, namespaceName string, options *metav1.GetOptions) (*api.Namespace, error) { obj, err := s.Get(ctx, namespaceName, options) if err != nil { return nil, err @@ -66,17 +67,17 @@ func (s *storage) GetNamespace(ctx genericapirequest.Context, namespaceName stri return obj.(*api.Namespace), nil } -func (s *storage) CreateNamespace(ctx genericapirequest.Context, namespace *api.Namespace, createValidation rest.ValidateObjectFunc) error { +func (s *storage) CreateNamespace(ctx context.Context, namespace *api.Namespace, createValidation rest.ValidateObjectFunc) error { _, err := s.Create(ctx, namespace, createValidation, false) return err } -func (s *storage) UpdateNamespace(ctx genericapirequest.Context, namespace *api.Namespace, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { +func (s *storage) UpdateNamespace(ctx context.Context, namespace *api.Namespace, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { _, _, err := s.Update(ctx, namespace.Name, rest.DefaultUpdatedObjectInfo(namespace), createValidation, updateValidation) return err } -func (s *storage) DeleteNamespace(ctx genericapirequest.Context, namespaceID string) error { +func (s *storage) DeleteNamespace(ctx context.Context, namespaceID string) error { _, _, err := s.Delete(ctx, namespaceID, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/storage/BUILD index ff853936a..9834572df 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/storage/BUILD @@ -40,7 +40,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/storage/storage.go index 77f8747b5..4ac632006 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/storage/storage.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "fmt" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -25,7 +26,6 @@ import ( metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -84,6 +84,10 @@ func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, *Finaliz return &REST{store: store, status: &statusStore}, &StatusREST{store: &statusStore}, &FinalizeREST{store: &finalizeStore} } +func (r *REST) NamespaceScoped() bool { + return r.store.NamespaceScoped() +} + func (r *REST) New() runtime.Object { return r.store.New() } @@ -92,32 +96,32 @@ func (r *REST) NewList() runtime.Object { return r.store.NewList() } -func (r *REST) List(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { +func (r *REST) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { return r.store.List(ctx, options) } -func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { return r.store.Create(ctx, obj, createValidation, includeUninitialized) } -func (r *REST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *REST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } -func (r *REST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } -func (r *REST) Watch(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return r.store.Watch(ctx, options) } -func (r *REST) Export(ctx genericapirequest.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { +func (r *REST) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { return r.store.Export(ctx, name, opts) } // Delete enforces life-cycle rules for namespace termination -func (r *REST) Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { +func (r *REST) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { nsObj, err := r.Get(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, err @@ -208,7 +212,7 @@ func (r *REST) Delete(ctx genericapirequest.Context, name string, options *metav return r.store.Delete(ctx, name, options) } -func (e *REST) ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { +func (e *REST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { return e.store.ConvertToTable(ctx, object, tableOptions) } @@ -225,12 +229,12 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } @@ -239,6 +243,6 @@ func (r *FinalizeREST) New() runtime.Object { } // Update alters the status finalizers subset of an object. -func (r *FinalizeREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *FinalizeREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/strategy.go index 53a139e52..be15c1b96 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/strategy.go @@ -17,13 +17,13 @@ limitations under the License. package namespace import ( + "context" "fmt" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" apistorage "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" @@ -48,7 +48,7 @@ func (namespaceStrategy) NamespaceScoped() bool { } // PrepareForCreate clears fields that are not allowed to be set by end users on creation. -func (namespaceStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (namespaceStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { // on create, status is active namespace := obj.(*api.Namespace) namespace.Status = api.NamespaceStatus{ @@ -73,7 +73,7 @@ func (namespaceStrategy) PrepareForCreate(ctx genericapirequest.Context, obj run } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (namespaceStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (namespaceStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newNamespace := obj.(*api.Namespace) oldNamespace := old.(*api.Namespace) newNamespace.Spec.Finalizers = oldNamespace.Spec.Finalizers @@ -81,7 +81,7 @@ func (namespaceStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, ol } // Validate validates a new namespace. -func (namespaceStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (namespaceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { namespace := obj.(*api.Namespace) return validation.ValidateNamespace(namespace) } @@ -96,7 +96,7 @@ func (namespaceStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (namespaceStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (namespaceStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { errorList := validation.ValidateNamespace(obj.(*api.Namespace)) return append(errorList, validation.ValidateNamespaceUpdate(obj.(*api.Namespace), old.(*api.Namespace))...) } @@ -111,13 +111,13 @@ type namespaceStatusStrategy struct { var StatusStrategy = namespaceStatusStrategy{Strategy} -func (namespaceStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (namespaceStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newNamespace := obj.(*api.Namespace) oldNamespace := old.(*api.Namespace) newNamespace.Spec = oldNamespace.Spec } -func (namespaceStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (namespaceStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateNamespaceStatusUpdate(obj.(*api.Namespace), old.(*api.Namespace)) } @@ -127,12 +127,12 @@ type namespaceFinalizeStrategy struct { var FinalizeStrategy = namespaceFinalizeStrategy{Strategy} -func (namespaceFinalizeStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (namespaceFinalizeStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateNamespaceFinalizeUpdate(obj.(*api.Namespace), old.(*api.Namespace)) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (namespaceFinalizeStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (namespaceFinalizeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newNamespace := obj.(*api.Namespace) oldNamespace := old.(*api.Namespace) newNamespace.Status = oldNamespace.Status diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/strategy_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/strategy_test.go index 9ebac3133..45982ad68 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/strategy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/namespace/strategy_test.go @@ -21,7 +21,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/kubernetes/pkg/api/legacyscheme" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" @@ -139,7 +138,7 @@ func TestNamespaceFinalizeStrategy(t *testing.T) { func TestSelectableFieldLabelConversions(t *testing.T) { apitesting.TestSelectableFieldLabelConversionsOfKind(t, - legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + "v1", "Namespace", NamespaceToSelectableFields(&api.Namespace{}), map[string]string{"name": "metadata.name"}, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/node/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/node/BUILD index 32a872cb4..03bad39ae 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/node/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/node/BUILD @@ -30,7 +30,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", @@ -44,7 +43,6 @@ go_test( srcs = ["strategy_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/apis/core:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/node/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/core/node/registry.go index e4476ded4..71752425a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/node/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/node/registry.go @@ -17,22 +17,23 @@ limitations under the License. package node import ( + "context" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" ) // Registry is an interface for things that know how to store node. type Registry interface { - ListNodes(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.NodeList, error) - CreateNode(ctx genericapirequest.Context, node *api.Node, createValidation rest.ValidateObjectFunc) error - UpdateNode(ctx genericapirequest.Context, node *api.Node, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetNode(ctx genericapirequest.Context, nodeID string, options *metav1.GetOptions) (*api.Node, error) - DeleteNode(ctx genericapirequest.Context, nodeID string) error - WatchNodes(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ListNodes(ctx context.Context, options *metainternalversion.ListOptions) (*api.NodeList, error) + CreateNode(ctx context.Context, node *api.Node, createValidation rest.ValidateObjectFunc) error + UpdateNode(ctx context.Context, node *api.Node, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error + GetNode(ctx context.Context, nodeID string, options *metav1.GetOptions) (*api.Node, error) + DeleteNode(ctx context.Context, nodeID string) error + WatchNodes(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) } // storage puts strong typing around storage calls @@ -46,7 +47,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListNodes(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.NodeList, error) { +func (s *storage) ListNodes(ctx context.Context, options *metainternalversion.ListOptions) (*api.NodeList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err @@ -55,21 +56,21 @@ func (s *storage) ListNodes(ctx genericapirequest.Context, options *metainternal return obj.(*api.NodeList), nil } -func (s *storage) CreateNode(ctx genericapirequest.Context, node *api.Node, createValidation rest.ValidateObjectFunc) error { +func (s *storage) CreateNode(ctx context.Context, node *api.Node, createValidation rest.ValidateObjectFunc) error { _, err := s.Create(ctx, node, createValidation, false) return err } -func (s *storage) UpdateNode(ctx genericapirequest.Context, node *api.Node, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { +func (s *storage) UpdateNode(ctx context.Context, node *api.Node, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { _, _, err := s.Update(ctx, node.Name, rest.DefaultUpdatedObjectInfo(node), createValidation, updateValidation) return err } -func (s *storage) WatchNodes(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchNodes(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetNode(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*api.Node, error) { +func (s *storage) GetNode(ctx context.Context, name string, options *metav1.GetOptions) (*api.Node, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err @@ -77,7 +78,7 @@ func (s *storage) GetNode(ctx genericapirequest.Context, name string, options *m return obj.(*api.Node), nil } -func (s *storage) DeleteNode(ctx genericapirequest.Context, name string) error { +func (s *storage) DeleteNode(ctx context.Context, name string) error { _, _, err := s.Delete(ctx, name, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/node/rest/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/node/rest/BUILD index 1425ee920..b0dcb27da 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/node/rest/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/node/rest/BUILD @@ -17,7 +17,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/proxy:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/node/rest/proxy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/node/rest/proxy.go index b314617f4..2701d3c04 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/node/rest/proxy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/node/rest/proxy.go @@ -17,6 +17,7 @@ limitations under the License. package node import ( + "context" "fmt" "net/http" "net/url" @@ -24,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/proxy" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" @@ -61,7 +61,7 @@ func (r *ProxyREST) NewConnectOptions() (runtime.Object, bool, string) { } // Connect returns a handler for the node proxy -func (r *ProxyREST) Connect(ctx genericapirequest.Context, id string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { +func (r *ProxyREST) Connect(ctx context.Context, id string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { proxyOpts, ok := opts.(*api.NodeProxyOptions) if !ok { return nil, fmt.Errorf("Invalid options object: %#v", opts) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/node/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/node/storage/storage.go index a61e57588..1197b23a4 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/node/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/node/storage/storage.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "fmt" "net/http" "net/url" @@ -53,7 +54,7 @@ type REST struct { proxyTransport http.RoundTripper } -// StatusREST implements the REST endpoint for changing the status of a pod. +// StatusREST implements the REST endpoint for changing the status of a node. type StatusREST struct { store *genericregistry.Store } @@ -63,12 +64,12 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } @@ -137,7 +138,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, kubeletClientConfig client var _ = rest.Redirector(&REST{}) // ResourceLocation returns a URL to which one can send traffic for the specified node. -func (r *REST) ResourceLocation(ctx genericapirequest.Context, id string) (*url.URL, http.RoundTripper, error) { +func (r *REST) ResourceLocation(ctx context.Context, id string) (*url.URL, http.RoundTripper, error) { return node.ResourceLocation(r, r.connection, r.proxyTransport, ctx, id) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/node/storage/storage_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/node/storage/storage_test.go index ebb7c8b3e..fef92d9bb 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/node/storage/storage_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/node/storage/storage_test.go @@ -55,9 +55,6 @@ func validNewNode() *api.Node { "name": "foo", }, }, - Spec: api.NodeSpec{ - ExternalID: "external", - }, Status: api.NodeStatus{ Capacity: api.ResourceList{ api.ResourceName(api.ResourceCPU): resource.MustParse("10"), diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/node/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/node/strategy.go index 4653b3f44..f15c83ce0 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/node/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/node/strategy.go @@ -17,6 +17,7 @@ limitations under the License. package node import ( + "context" "fmt" "net" "net/http" @@ -30,7 +31,6 @@ import ( "k8s.io/apimachinery/pkg/types" utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" pkgstorage "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" @@ -63,7 +63,7 @@ func (nodeStrategy) AllowCreateOnUpdate() bool { } // PrepareForCreate clears fields that are not allowed to be set by end users on creation. -func (nodeStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (nodeStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { node := obj.(*api.Node) // Nodes allow *all* fields, including status, to be set on create. @@ -73,7 +73,7 @@ func (nodeStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime. } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (nodeStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (nodeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newNode := obj.(*api.Node) oldNode := old.(*api.Node) newNode.Status = oldNode.Status @@ -85,7 +85,7 @@ func (nodeStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old run } // Validate validates a new node. -func (nodeStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (nodeStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { node := obj.(*api.Node) return validation.ValidateNode(node) } @@ -95,7 +95,7 @@ func (nodeStrategy) Canonicalize(obj runtime.Object) { } // ValidateUpdate is the default update validation for an end user. -func (nodeStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (nodeStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { errorList := validation.ValidateNode(obj.(*api.Node)) return append(errorList, validation.ValidateNodeUpdate(obj.(*api.Node), old.(*api.Node))...) } @@ -104,7 +104,7 @@ func (nodeStrategy) AllowUnconditionalUpdate() bool { return true } -func (ns nodeStrategy) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error { +func (ns nodeStrategy) Export(ctx context.Context, obj runtime.Object, exact bool) error { n, ok := obj.(*api.Node) if !ok { // unexpected programmer error @@ -126,18 +126,27 @@ type nodeStatusStrategy struct { var StatusStrategy = nodeStatusStrategy{Strategy} -func (nodeStatusStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { - _ = obj.(*api.Node) +func (nodeStatusStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { + node := obj.(*api.Node) // Nodes allow *all* fields, including status, to be set on create. + + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { + node.Status.Config = nil + } } -func (nodeStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (nodeStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newNode := obj.(*api.Node) oldNode := old.(*api.Node) newNode.Spec = oldNode.Spec + + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { + newNode.Status.Config = nil + oldNode.Status.Config = nil + } } -func (nodeStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (nodeStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateNodeUpdate(obj.(*api.Node), old.(*api.Node)) } @@ -147,7 +156,7 @@ func (nodeStatusStrategy) Canonicalize(obj runtime.Object) { // ResourceGetter is an interface for retrieving resources by ResourceLocation. type ResourceGetter interface { - Get(genericapirequest.Context, string, *metav1.GetOptions) (runtime.Object, error) + Get(context.Context, string, *metav1.GetOptions) (runtime.Object, error) } // NodeToSelectableFields returns a field set that represents the object. @@ -184,8 +193,8 @@ func NodeNameTriggerFunc(obj runtime.Object) []pkgstorage.MatchValue { return []pkgstorage.MatchValue{result} } -// ResourceLocation returns an URL and transport which one can use to send traffic for the specified node. -func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGetter, proxyTransport http.RoundTripper, ctx genericapirequest.Context, id string) (*url.URL, http.RoundTripper, error) { +// ResourceLocation returns a URL and transport which one can use to send traffic for the specified node. +func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGetter, proxyTransport http.RoundTripper, ctx context.Context, id string) (*url.URL, http.RoundTripper, error) { schemeReq, name, portReq, valid := utilnet.SplitSchemeNamePort(id) if !valid { return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid node request %q", id)) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/node/strategy_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/node/strategy_test.go index c32da10bb..9d1adbaf5 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/node/strategy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/node/strategy_test.go @@ -21,7 +21,6 @@ import ( "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" - "k8s.io/kubernetes/pkg/api/legacyscheme" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" @@ -52,7 +51,7 @@ func TestMatchNode(t *testing.T) { func TestSelectableFieldLabelConversions(t *testing.T) { apitesting.TestSelectableFieldLabelConversionsOfKind(t, - legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + "v1", "Node", NodeToSelectableFields(&api.Node{}), nil, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/BUILD index 8cf27c1c9..03ce25e4b 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/BUILD @@ -23,7 +23,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", @@ -35,7 +34,6 @@ go_test( srcs = ["strategy_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/apis/core:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/storage/BUILD index 25c758afd..602854b44 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/storage/BUILD @@ -40,7 +40,6 @@ go_library( "//pkg/registry/core/persistentvolume:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/storage/storage.go index 519b7cb9c..c272364ef 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -78,11 +79,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/strategy.go index 477bca2ba..eb172251a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/strategy.go @@ -17,13 +17,13 @@ limitations under the License. package persistentvolume import ( + "context" "fmt" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" @@ -49,14 +49,14 @@ func (persistentvolumeStrategy) NamespaceScoped() bool { } // ResetBeforeCreate clears the Status field which is not allowed to be set by end users on creation. -func (persistentvolumeStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (persistentvolumeStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { pv := obj.(*api.PersistentVolume) pv.Status = api.PersistentVolumeStatus{} pvutil.DropDisabledAlphaFields(&pv.Spec) } -func (persistentvolumeStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (persistentvolumeStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { persistentvolume := obj.(*api.PersistentVolume) errorList := validation.ValidatePersistentVolume(persistentvolume) return append(errorList, volumevalidation.ValidatePersistentVolume(persistentvolume)...) @@ -71,7 +71,7 @@ func (persistentvolumeStrategy) AllowCreateOnUpdate() bool { } // PrepareForUpdate sets the Status fields which is not allowed to be set by an end user updating a PV -func (persistentvolumeStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (persistentvolumeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPv := obj.(*api.PersistentVolume) oldPv := old.(*api.PersistentVolume) newPv.Status = oldPv.Status @@ -80,7 +80,7 @@ func (persistentvolumeStrategy) PrepareForUpdate(ctx genericapirequest.Context, pvutil.DropDisabledAlphaFields(&oldPv.Spec) } -func (persistentvolumeStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (persistentvolumeStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { newPv := obj.(*api.PersistentVolume) errorList := validation.ValidatePersistentVolume(newPv) errorList = append(errorList, volumevalidation.ValidatePersistentVolume(newPv)...) @@ -98,13 +98,13 @@ type persistentvolumeStatusStrategy struct { var StatusStrategy = persistentvolumeStatusStrategy{Strategy} // PrepareForUpdate sets the Spec field which is not allowed to be changed when updating a PV's Status -func (persistentvolumeStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (persistentvolumeStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPv := obj.(*api.PersistentVolume) oldPv := old.(*api.PersistentVolume) newPv.Spec = oldPv.Spec } -func (persistentvolumeStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (persistentvolumeStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidatePersistentVolumeStatusUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/strategy_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/strategy_test.go index 3c5fbb7d9..91d95db68 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/strategy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolume/strategy_test.go @@ -19,7 +19,6 @@ package persistentvolume import ( "testing" - "k8s.io/kubernetes/pkg/api/legacyscheme" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" @@ -29,7 +28,7 @@ import ( func TestSelectableFieldLabelConversions(t *testing.T) { apitesting.TestSelectableFieldLabelConversionsOfKind(t, - legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + "v1", "PersistentVolume", PersistentVolumeToSelectableFields(&api.PersistentVolume{}), map[string]string{"name": "metadata.name"}, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/BUILD index dcf84be08..88182fda5 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/BUILD @@ -22,7 +22,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", @@ -34,7 +33,6 @@ go_test( srcs = ["strategy_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/apis/core:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/storage/BUILD index c927ef5b3..277f11556 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/storage/BUILD @@ -40,7 +40,6 @@ go_library( "//pkg/registry/core/persistentvolumeclaim:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/storage/storage.go index 2720c2d58..3d4a0d269 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -78,11 +79,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/strategy.go index 1a63e1fae..abefe0de1 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/strategy.go @@ -17,13 +17,13 @@ limitations under the License. package persistentvolumeclaim import ( + "context" "fmt" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" @@ -48,14 +48,14 @@ func (persistentvolumeclaimStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the Status field which is not allowed to be set by end users on creation. -func (persistentvolumeclaimStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (persistentvolumeclaimStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { pvc := obj.(*api.PersistentVolumeClaim) pvc.Status = api.PersistentVolumeClaimStatus{} pvcutil.DropDisabledAlphaFields(&pvc.Spec) } -func (persistentvolumeclaimStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (persistentvolumeclaimStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { pvc := obj.(*api.PersistentVolumeClaim) return validation.ValidatePersistentVolumeClaim(pvc) } @@ -69,7 +69,7 @@ func (persistentvolumeclaimStrategy) AllowCreateOnUpdate() bool { } // PrepareForUpdate sets the Status field which is not allowed to be set by end users on update -func (persistentvolumeclaimStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (persistentvolumeclaimStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPvc := obj.(*api.PersistentVolumeClaim) oldPvc := old.(*api.PersistentVolumeClaim) newPvc.Status = oldPvc.Status @@ -78,7 +78,7 @@ func (persistentvolumeclaimStrategy) PrepareForUpdate(ctx genericapirequest.Cont pvcutil.DropDisabledAlphaFields(&oldPvc.Spec) } -func (persistentvolumeclaimStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (persistentvolumeclaimStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { errorList := validation.ValidatePersistentVolumeClaim(obj.(*api.PersistentVolumeClaim)) return append(errorList, validation.ValidatePersistentVolumeClaimUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim))...) } @@ -94,13 +94,13 @@ type persistentvolumeclaimStatusStrategy struct { var StatusStrategy = persistentvolumeclaimStatusStrategy{Strategy} // PrepareForUpdate sets the Spec field which is not allowed to be changed when updating a PV's Status -func (persistentvolumeclaimStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (persistentvolumeclaimStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPv := obj.(*api.PersistentVolumeClaim) oldPv := old.(*api.PersistentVolumeClaim) newPv.Spec = oldPv.Spec } -func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidatePersistentVolumeClaimStatusUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/strategy_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/strategy_test.go index ae0ef9970..b34eb72b9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/strategy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/strategy_test.go @@ -19,7 +19,6 @@ package persistentvolumeclaim import ( "testing" - "k8s.io/kubernetes/pkg/api/legacyscheme" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" @@ -29,7 +28,7 @@ import ( func TestSelectableFieldLabelConversions(t *testing.T) { apitesting.TestSelectableFieldLabelConversionsOfKind(t, - legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + "v1", "PersistentVolumeClaim", PersistentVolumeClaimToSelectableFields(&api.PersistentVolumeClaim{}), map[string]string{"name": "metadata.name"}, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/BUILD index 34e64e351..e445cd3b9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/BUILD @@ -30,7 +30,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/features:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", @@ -44,7 +43,6 @@ go_test( srcs = ["strategy_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/apis/core:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/BUILD index 114159cde..ee4116277 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/BUILD @@ -23,7 +23,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/proxy:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/features:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/log.go b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/log.go index e33f2a7fe..ea74dff5c 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/log.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/log.go @@ -17,11 +17,11 @@ limitations under the License. package rest import ( + "context" "fmt" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" genericrest "k8s.io/apiserver/pkg/registry/generic/rest" "k8s.io/apiserver/pkg/registry/rest" @@ -62,7 +62,7 @@ func (r *LogREST) ProducesObject(verb string) interface{} { } // Get retrieves a runtime.Object that will stream the contents of the pod log -func (r *LogREST) Get(ctx genericapirequest.Context, name string, opts runtime.Object) (runtime.Object, error) { +func (r *LogREST) Get(ctx context.Context, name string, opts runtime.Object) (runtime.Object, error) { logOpts, ok := opts.(*api.PodLogOptions) if !ok { return nil, fmt.Errorf("invalid options object: %#v", opts) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/subresources.go b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/subresources.go index 2df827976..641237367 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/subresources.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/rest/subresources.go @@ -17,6 +17,7 @@ limitations under the License. package rest import ( + "context" "fmt" "net/http" "net/url" @@ -24,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/proxy" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericfeatures "k8s.io/apiserver/pkg/features" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -62,7 +62,7 @@ func (r *ProxyREST) NewConnectOptions() (runtime.Object, bool, string) { } // Connect returns a handler for the pod proxy -func (r *ProxyREST) Connect(ctx genericapirequest.Context, id string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { +func (r *ProxyREST) Connect(ctx context.Context, id string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { proxyOpts, ok := opts.(*api.PodProxyOptions) if !ok { return nil, fmt.Errorf("Invalid options object: %#v", opts) @@ -94,7 +94,7 @@ func (r *AttachREST) New() runtime.Object { } // Connect returns a handler for the pod exec proxy -func (r *AttachREST) Connect(ctx genericapirequest.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { +func (r *AttachREST) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { attachOpts, ok := opts.(*api.PodAttachOptions) if !ok { return nil, fmt.Errorf("Invalid options object: %#v", opts) @@ -131,7 +131,7 @@ func (r *ExecREST) New() runtime.Object { } // Connect returns a handler for the pod exec proxy -func (r *ExecREST) Connect(ctx genericapirequest.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { +func (r *ExecREST) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { execOpts, ok := opts.(*api.PodExecOptions) if !ok { return nil, fmt.Errorf("invalid options object: %#v", opts) @@ -179,7 +179,7 @@ func (r *PortForwardREST) ConnectMethods() []string { } // Connect returns a handler for the pod portforward proxy -func (r *PortForwardREST) Connect(ctx genericapirequest.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { +func (r *PortForwardREST) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { portForwardOpts, ok := opts.(*api.PodPortForwardOptions) if !ok { return nil, fmt.Errorf("invalid options object: %#v", opts) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/BUILD index c409b87a3..f830237c2 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/BUILD @@ -14,7 +14,6 @@ go_test( "//pkg/apis/core:go_default_library", "//pkg/registry/registrytest:go_default_library", "//pkg/securitycontext:go_default_library", - "//vendor/golang.org/x/net/context: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/errors:go_default_library", @@ -62,7 +61,6 @@ go_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/util/wait:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/eviction.go b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/eviction.go index e98a93211..5eb66cb6e 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/eviction.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/eviction.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "fmt" "time" @@ -26,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/client-go/util/retry" @@ -78,7 +78,7 @@ func (r *EvictionREST) New() runtime.Object { } // Create attempts to create a new eviction. That is, it tries to evict a pod. -func (r *EvictionREST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *EvictionREST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { eviction := obj.(*policy.Eviction) obj, err := r.store.Get(ctx, eviction.Name, &metav1.GetOptions{}) @@ -177,7 +177,7 @@ func (r *EvictionREST) checkAndDecrement(namespace string, podName string, pdb p } // getPodDisruptionBudgets returns any PDBs that match the pod or err if there's an error. -func (r *EvictionREST) getPodDisruptionBudgets(ctx genericapirequest.Context, pod *api.Pod) ([]policy.PodDisruptionBudget, error) { +func (r *EvictionREST) getPodDisruptionBudgets(ctx context.Context, pod *api.Pod) ([]policy.PodDisruptionBudget, error) { if len(pod.Labels) == 0 { return nil, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/storage.go index 129fd1a43..216daa6df 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/storage.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "fmt" "net/http" "net/url" @@ -24,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -102,7 +102,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGet var _ = rest.Redirector(&REST{}) // ResourceLocation returns a pods location from its HostIP -func (r *REST) ResourceLocation(ctx genericapirequest.Context, name string) (*url.URL, http.RoundTripper, error) { +func (r *REST) ResourceLocation(ctx context.Context, name string) (*url.URL, http.RoundTripper, error) { return pod.ResourceLocation(r, r.proxyTransport, ctx, name) } @@ -127,6 +127,11 @@ type BindingREST struct { store *genericregistry.Store } +// NamespaceScoped fulfill rest.Scoper +func (r *BindingREST) NamespaceScoped() bool { + return r.store.NamespaceScoped() +} + // New creates a new binding resource func (r *BindingREST) New() runtime.Object { return &api.Binding{} @@ -135,7 +140,7 @@ func (r *BindingREST) New() runtime.Object { var _ = rest.Creater(&BindingREST{}) // Create ensures a pod is bound to a specific host. -func (r *BindingREST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (out runtime.Object, err error) { +func (r *BindingREST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (out runtime.Object, err error) { binding := obj.(*api.Binding) // TODO: move me to a binding strategy @@ -151,7 +156,7 @@ func (r *BindingREST) Create(ctx genericapirequest.Context, obj runtime.Object, // setPodHostAndAnnotations sets the given pod's host to 'machine' if and only if it was // previously 'oldMachine' and merges the provided annotations with those of the pod. // Returns the current state of the pod, or an error. -func (r *BindingREST) setPodHostAndAnnotations(ctx genericapirequest.Context, podID, oldMachine, machine string, annotations map[string]string) (finalPod *api.Pod, err error) { +func (r *BindingREST) setPodHostAndAnnotations(ctx context.Context, podID, oldMachine, machine string, annotations map[string]string) (finalPod *api.Pod, err error) { podKey, err := r.store.KeyFunc(ctx, podID) if err != nil { return nil, err @@ -185,7 +190,7 @@ func (r *BindingREST) setPodHostAndAnnotations(ctx genericapirequest.Context, po } // assignPod assigns the given pod to the given machine. -func (r *BindingREST) assignPod(ctx genericapirequest.Context, podID string, machine string, annotations map[string]string) (err error) { +func (r *BindingREST) assignPod(ctx context.Context, podID string, machine string, annotations map[string]string) (err error) { if _, err = r.setPodHostAndAnnotations(ctx, podID, "", machine, annotations); err != nil { err = storeerr.InterpretGetError(err, api.Resource("pods"), podID) err = storeerr.InterpretUpdateError(err, api.Resource("pods"), podID) @@ -207,11 +212,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/storage_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/storage_test.go index f25e682cb..76fad36e0 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/storage_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/storage/storage_test.go @@ -17,11 +17,11 @@ limitations under the License. package storage import ( + "context" "strings" "testing" "time" - "golang.org/x/net/context" "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" @@ -417,6 +417,7 @@ func TestConvertToTableList(t *testing.T) { {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, {Name: "IP", Type: "string", Priority: 1, Description: v1.PodStatus{}.SwaggerDoc()["podIP"]}, {Name: "Node", Type: "string", Priority: 1, Description: v1.PodSpec{}.SwaggerDoc()["nodeName"]}, + {Name: "Nominated Node", Type: "string", Priority: 1, Description: v1.PodStatus{}.SwaggerDoc()["nominatedNodeName"]}, } pod1 := &api.Pod{ @@ -435,6 +436,7 @@ func TestConvertToTableList(t *testing.T) { {Name: "ctr1", State: api.ContainerState{Running: &api.ContainerStateRunning{}}, RestartCount: 10, Ready: true}, {Name: "ctr2", State: api.ContainerState{Waiting: &api.ContainerStateWaiting{}}, RestartCount: 0}, }, + NominatedNodeName: "nominated-node", }, } @@ -452,7 +454,7 @@ func TestConvertToTableList(t *testing.T) { out: &metav1beta1.Table{ ColumnDefinitions: columns, Rows: []metav1beta1.TableRow{ - {Cells: []interface{}{"", "0/0", "", 0, "", "", ""}, Object: runtime.RawExtension{Object: &api.Pod{}}}, + {Cells: []interface{}{"", "0/0", "", int64(0), "", "", "", ""}, Object: runtime.RawExtension{Object: &api.Pod{}}}, }, }, }, @@ -461,7 +463,7 @@ func TestConvertToTableList(t *testing.T) { out: &metav1beta1.Table{ ColumnDefinitions: columns, Rows: []metav1beta1.TableRow{ - {Cells: []interface{}{"foo", "1/2", "Pending", 10, "1y", "10.1.2.3", "test-node"}, Object: runtime.RawExtension{Object: pod1}}, + {Cells: []interface{}{"foo", "1/2", "Pending", int64(10), "1y", "10.1.2.3", "test-node", "nominated-node"}, Object: runtime.RawExtension{Object: pod1}}, }, }, }, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/strategy.go index 90118016c..a36589111 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/strategy.go @@ -17,6 +17,7 @@ limitations under the License. package pod import ( + "context" "fmt" "net" "net/http" @@ -35,7 +36,6 @@ import ( "k8s.io/apimachinery/pkg/types" utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/storage" @@ -65,7 +65,7 @@ func (podStrategy) NamespaceScoped() bool { } // PrepareForCreate clears fields that are not allowed to be set by end users on creation. -func (podStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (podStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { pod := obj.(*api.Pod) pod.Status = api.PodStatus{ Phase: api.PodPending, @@ -76,7 +76,7 @@ func (podStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.O } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (podStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (podStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPod := obj.(*api.Pod) oldPod := old.(*api.Pod) newPod.Status = oldPod.Status @@ -86,7 +86,7 @@ func (podStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runt } // Validate validates a new pod. -func (podStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (podStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { pod := obj.(*api.Pod) return validation.ValidatePod(pod) } @@ -116,7 +116,7 @@ func isUpdatingUninitializedPod(old runtime.Object) (bool, error) { } // ValidateUpdate is the default update validation for an end user. -func (podStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (podStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { errorList := validation.ValidatePod(obj.(*api.Pod)) uninitializedUpdate, err := isUpdatingUninitializedPod(old) if err != nil { @@ -135,7 +135,7 @@ func (podStrategy) AllowUnconditionalUpdate() bool { // CheckGracefulDelete allows a pod to be gracefully deleted. It updates the DeleteOptions to // reflect the desired grace value. -func (podStrategy) CheckGracefulDelete(ctx genericapirequest.Context, obj runtime.Object, options *metav1.DeleteOptions) bool { +func (podStrategy) CheckGracefulDelete(ctx context.Context, obj runtime.Object, options *metav1.DeleteOptions) bool { if options == nil { return false } @@ -168,7 +168,7 @@ type podStrategyWithoutGraceful struct { } // CheckGracefulDelete prohibits graceful deletion. -func (podStrategyWithoutGraceful) CheckGracefulDelete(ctx genericapirequest.Context, obj runtime.Object, options *metav1.DeleteOptions) bool { +func (podStrategyWithoutGraceful) CheckGracefulDelete(ctx context.Context, obj runtime.Object, options *metav1.DeleteOptions) bool { return false } @@ -181,7 +181,7 @@ type podStatusStrategy struct { var StatusStrategy = podStatusStrategy{Strategy} -func (podStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (podStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPod := obj.(*api.Pod) oldPod := old.(*api.Pod) newPod.Spec = oldPod.Spec @@ -192,7 +192,7 @@ func (podStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, ol newPod.OwnerReferences = oldPod.OwnerReferences } -func (podStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (podStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { var errorList field.ErrorList uninitializedUpdate, err := isUpdatingUninitializedPod(old) if err != nil { @@ -249,10 +249,10 @@ func PodToSelectableFields(pod *api.Pod) fields.Set { // ResourceGetter is an interface for retrieving resources by ResourceLocation. type ResourceGetter interface { - Get(genericapirequest.Context, string, *metav1.GetOptions) (runtime.Object, error) + Get(context.Context, string, *metav1.GetOptions) (runtime.Object, error) } -func getPod(getter ResourceGetter, ctx genericapirequest.Context, name string) (*api.Pod, error) { +func getPod(getter ResourceGetter, ctx context.Context, name string) (*api.Pod, error) { obj, err := getter.Get(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, err @@ -265,7 +265,7 @@ func getPod(getter ResourceGetter, ctx genericapirequest.Context, name string) ( } // ResourceLocation returns a URL to which one can send traffic for the specified pod. -func ResourceLocation(getter ResourceGetter, rt http.RoundTripper, ctx genericapirequest.Context, id string) (*url.URL, http.RoundTripper, error) { +func ResourceLocation(getter ResourceGetter, rt http.RoundTripper, ctx context.Context, id string) (*url.URL, http.RoundTripper, error) { // Allow ID as "podname" or "podname:port" or "scheme:podname:port". // If port is not specified, try to use the first defined port on the pod. scheme, name, port, valid := utilnet.SplitSchemeNamePort(id) @@ -314,7 +314,7 @@ func getContainerNames(containers []api.Container) string { func LogLocation( getter ResourceGetter, connInfo client.ConnectionInfoGetter, - ctx genericapirequest.Context, + ctx context.Context, name string, opts *api.PodLogOptions, ) (*url.URL, http.RoundTripper, error) { @@ -450,7 +450,7 @@ func streamParams(params url.Values, opts runtime.Object) error { func AttachLocation( getter ResourceGetter, connInfo client.ConnectionInfoGetter, - ctx genericapirequest.Context, + ctx context.Context, name string, opts *api.PodAttachOptions, ) (*url.URL, http.RoundTripper, error) { @@ -462,7 +462,7 @@ func AttachLocation( func ExecLocation( getter ResourceGetter, connInfo client.ConnectionInfoGetter, - ctx genericapirequest.Context, + ctx context.Context, name string, opts *api.PodExecOptions, ) (*url.URL, http.RoundTripper, error) { @@ -472,7 +472,7 @@ func ExecLocation( func streamLocation( getter ResourceGetter, connInfo client.ConnectionInfoGetter, - ctx genericapirequest.Context, + ctx context.Context, name string, opts runtime.Object, container, @@ -531,7 +531,7 @@ func streamLocation( func PortForwardLocation( getter ResourceGetter, connInfo client.ConnectionInfoGetter, - ctx genericapirequest.Context, + ctx context.Context, name string, opts *api.PodPortForwardOptions, ) (*url.URL, http.RoundTripper, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/strategy_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/strategy_test.go index 260108342..b1c207307 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/pod/strategy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/pod/strategy_test.go @@ -17,6 +17,7 @@ limitations under the License. package pod import ( + "context" "net/url" "reflect" "testing" @@ -29,7 +30,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/kubernetes/pkg/api/legacyscheme" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubelet/client" @@ -268,7 +268,7 @@ type mockPodGetter struct { pod *api.Pod } -func (g mockPodGetter) Get(genericapirequest.Context, string, *metav1.GetOptions) (runtime.Object, error) { +func (g mockPodGetter) Get(context.Context, string, *metav1.GetOptions) (runtime.Object, error) { return g.pod, nil } @@ -370,7 +370,7 @@ func TestCheckLogLocation(t *testing.T) { func TestSelectableFieldLabelConversions(t *testing.T) { apitesting.TestSelectableFieldLabelConversionsOfKind(t, - legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + "v1", "Pod", PodToSelectableFields(&api.Pod{}), nil, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/podtemplate/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/podtemplate/BUILD index 5841503ea..9caae700d 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/podtemplate/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/podtemplate/BUILD @@ -19,7 +19,6 @@ go_library( "//pkg/apis/core/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/podtemplate/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/podtemplate/strategy.go index 0f19250d9..83c516fc8 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/podtemplate/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/podtemplate/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package podtemplate import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/pod" @@ -43,14 +44,14 @@ func (podTemplateStrategy) NamespaceScoped() bool { } // PrepareForCreate clears fields that are not allowed to be set by end users on creation. -func (podTemplateStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (podTemplateStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { template := obj.(*api.PodTemplate) pod.DropDisabledAlphaFields(&template.Template.Spec) } // Validate validates a new pod template. -func (podTemplateStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (podTemplateStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { pod := obj.(*api.PodTemplate) return validation.ValidatePodTemplate(pod) } @@ -65,7 +66,7 @@ func (podTemplateStrategy) AllowCreateOnUpdate() bool { } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (podTemplateStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (podTemplateStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newTemplate := obj.(*api.PodTemplate) oldTemplate := old.(*api.PodTemplate) @@ -74,7 +75,7 @@ func (podTemplateStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, } // ValidateUpdate is the default update validation for an end user. -func (podTemplateStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (podTemplateStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidatePodTemplateUpdate(obj.(*api.PodTemplate), old.(*api.PodTemplate)) } @@ -82,7 +83,7 @@ func (podTemplateStrategy) AllowUnconditionalUpdate() bool { return true } -func (podTemplateStrategy) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error { +func (podTemplateStrategy) Export(ctx context.Context, obj runtime.Object, exact bool) error { // Do nothing return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/BUILD index a55314ed7..cd89a4f53 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/BUILD @@ -28,7 +28,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", @@ -41,7 +40,6 @@ go_test( srcs = ["strategy_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/apis/core:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/registry.go index 199981db0..caf5d78fc 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/registry.go @@ -19,24 +19,24 @@ limitations under the License. package replicationcontroller import ( + "context" "fmt" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" ) // Registry is an interface for things that know how to store ReplicationControllers. type Registry interface { - ListControllers(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.ReplicationControllerList, error) - WatchControllers(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) - GetController(ctx genericapirequest.Context, controllerID string, options *metav1.GetOptions) (*api.ReplicationController, error) - CreateController(ctx genericapirequest.Context, controller *api.ReplicationController, createValidation rest.ValidateObjectFunc) (*api.ReplicationController, error) - UpdateController(ctx genericapirequest.Context, controller *api.ReplicationController, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.ReplicationController, error) - DeleteController(ctx genericapirequest.Context, controllerID string) error + ListControllers(ctx context.Context, options *metainternalversion.ListOptions) (*api.ReplicationControllerList, error) + WatchControllers(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetController(ctx context.Context, controllerID string, options *metav1.GetOptions) (*api.ReplicationController, error) + CreateController(ctx context.Context, controller *api.ReplicationController, createValidation rest.ValidateObjectFunc) (*api.ReplicationController, error) + UpdateController(ctx context.Context, controller *api.ReplicationController, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.ReplicationController, error) + DeleteController(ctx context.Context, controllerID string) error } // storage puts strong typing around storage calls @@ -50,7 +50,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListControllers(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.ReplicationControllerList, error) { +func (s *storage) ListControllers(ctx context.Context, options *metainternalversion.ListOptions) (*api.ReplicationControllerList, error) { if options != nil && options.FieldSelector != nil && !options.FieldSelector.Empty() { return nil, fmt.Errorf("field selector not supported yet") } @@ -61,11 +61,11 @@ func (s *storage) ListControllers(ctx genericapirequest.Context, options *metain return obj.(*api.ReplicationControllerList), err } -func (s *storage) WatchControllers(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchControllers(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetController(ctx genericapirequest.Context, controllerID string, options *metav1.GetOptions) (*api.ReplicationController, error) { +func (s *storage) GetController(ctx context.Context, controllerID string, options *metav1.GetOptions) (*api.ReplicationController, error) { obj, err := s.Get(ctx, controllerID, options) if err != nil { return nil, err @@ -73,7 +73,7 @@ func (s *storage) GetController(ctx genericapirequest.Context, controllerID stri return obj.(*api.ReplicationController), nil } -func (s *storage) CreateController(ctx genericapirequest.Context, controller *api.ReplicationController, createValidation rest.ValidateObjectFunc) (*api.ReplicationController, error) { +func (s *storage) CreateController(ctx context.Context, controller *api.ReplicationController, createValidation rest.ValidateObjectFunc) (*api.ReplicationController, error) { obj, err := s.Create(ctx, controller, createValidation, false) if err != nil { return nil, err @@ -81,7 +81,7 @@ func (s *storage) CreateController(ctx genericapirequest.Context, controller *ap return obj.(*api.ReplicationController), nil } -func (s *storage) UpdateController(ctx genericapirequest.Context, controller *api.ReplicationController, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.ReplicationController, error) { +func (s *storage) UpdateController(ctx context.Context, controller *api.ReplicationController, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.ReplicationController, error) { obj, _, err := s.Update(ctx, controller.Name, rest.DefaultUpdatedObjectInfo(controller), createValidation, updateValidation) if err != nil { return nil, err @@ -89,7 +89,7 @@ func (s *storage) UpdateController(ctx genericapirequest.Context, controller *ap return obj.(*api.ReplicationController), nil } -func (s *storage) DeleteController(ctx genericapirequest.Context, controllerID string) error { +func (s *storage) DeleteController(ctx context.Context, controllerID string) error { _, _, err := s.Delete(ctx, controllerID, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/BUILD index 0ccf4bf19..ef5a16ef8 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/BUILD @@ -48,7 +48,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels: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/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/storage.go index ead95842d..0c5217f37 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/storage.go @@ -19,6 +19,7 @@ limitations under the License. package storage import ( + "context" "fmt" "k8s.io/apimachinery/pkg/api/errors" @@ -26,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -114,12 +114,12 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } @@ -145,7 +145,7 @@ func (r *ScaleREST) New() runtime.Object { return &autoscaling.Scale{} } -func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *ScaleREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { rc, err := r.registry.GetController(ctx, name, options) if err != nil { return nil, errors.NewNotFound(autoscaling.Resource("replicationcontrollers/scale"), name) @@ -153,7 +153,7 @@ func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *met return scaleFromRC(rc), nil } -func (r *ScaleREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { rc, err := r.registry.GetController(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, errors.NewNotFound(autoscaling.Resource("replicationcontrollers/scale"), name) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/storage_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/storage_test.go index 2ffb6446a..1d5e37dc5 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/storage_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage/storage_test.go @@ -161,6 +161,9 @@ func TestGenerationNumber(t *testing.T) { modifiedSno.Status.ObservedGeneration = 10 ctx := genericapirequest.NewDefaultContext() rc, err := createController(storage.Controller, modifiedSno, t) + if err != nil { + t.Errorf("unexpected error: %v", err) + } ctrl, err := storage.Controller.Get(ctx, rc.Name, &metav1.GetOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) @@ -168,14 +171,13 @@ func TestGenerationNumber(t *testing.T) { controller, _ := ctrl.(*api.ReplicationController) // Generation initialization - if controller.Generation != 1 && controller.Status.ObservedGeneration != 0 { + if controller.Generation != 1 || controller.Status.ObservedGeneration != 0 { t.Fatalf("Unexpected generation number %v, status generation %v", controller.Generation, controller.Status.ObservedGeneration) } // Updates to spec should increment the generation number controller.Spec.Replicas += 1 - storage.Controller.Update(ctx, controller.Name, rest.DefaultUpdatedObjectInfo(controller), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc) - if err != nil { + if _, _, err := storage.Controller.Update(ctx, controller.Name, rest.DefaultUpdatedObjectInfo(controller), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc); err != nil { t.Errorf("unexpected error: %v", err) } ctrl, err = storage.Controller.Get(ctx, rc.Name, &metav1.GetOptions{}) @@ -189,8 +191,7 @@ func TestGenerationNumber(t *testing.T) { // Updates to status should not increment either spec or status generation numbers controller.Status.Replicas += 1 - storage.Controller.Update(ctx, controller.Name, rest.DefaultUpdatedObjectInfo(controller), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc) - if err != nil { + if _, _, err := storage.Controller.Update(ctx, controller.Name, rest.DefaultUpdatedObjectInfo(controller), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc); err != nil { t.Errorf("unexpected error: %v", err) } ctrl, err = storage.Controller.Get(ctx, rc.Name, &metav1.GetOptions{}) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/strategy.go index ede6e6724..0cc784bc9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/strategy.go @@ -19,6 +19,7 @@ limitations under the License. package replicationcontroller import ( + "context" "fmt" "strconv" "strings" @@ -28,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" apistorage "k8s.io/apiserver/pkg/storage" @@ -51,7 +51,7 @@ var Strategy = rcStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} // DefaultGarbageCollectionPolicy returns Orphan because that was the default // behavior before the server-side garbage collection was implemented. -func (rcStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (rcStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { return rest.OrphanDependents } @@ -61,7 +61,7 @@ func (rcStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a replication controller before creation. -func (rcStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (rcStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { controller := obj.(*api.ReplicationController) controller.Status = api.ReplicationControllerStatus{} @@ -73,7 +73,7 @@ func (rcStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Ob } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (rcStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (rcStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newController := obj.(*api.ReplicationController) oldController := old.(*api.ReplicationController) // update is not allowed to set status @@ -100,7 +100,7 @@ func (rcStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runti } // Validate validates a new replication controller. -func (rcStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (rcStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { controller := obj.(*api.ReplicationController) return validation.ValidateReplicationController(controller) } @@ -116,7 +116,7 @@ func (rcStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (rcStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (rcStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { oldRc := old.(*api.ReplicationController) newRc := obj.(*api.ReplicationController) @@ -183,13 +183,13 @@ type rcStatusStrategy struct { var StatusStrategy = rcStatusStrategy{Strategy} -func (rcStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (rcStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newRc := obj.(*api.ReplicationController) oldRc := old.(*api.ReplicationController) // update is not allowed to set spec newRc.Spec = oldRc.Spec } -func (rcStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (rcStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateReplicationControllerStatusUpdate(obj.(*api.ReplicationController), old.(*api.ReplicationController)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/strategy_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/strategy_test.go index 1a89135ab..36867ceb6 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/strategy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/replicationcontroller/strategy_test.go @@ -22,7 +22,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/kubernetes/pkg/api/legacyscheme" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" @@ -149,7 +148,7 @@ func TestControllerStatusStrategy(t *testing.T) { func TestSelectableFieldLabelConversions(t *testing.T) { apitesting.TestSelectableFieldLabelConversionsOfKind(t, - legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + "v1", "ReplicationController", ControllerToSelectableFields(&api.ReplicationController{}), nil, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/BUILD index a2458fa36..699f8dda4 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/BUILD @@ -19,7 +19,6 @@ go_library( "//pkg/apis/core/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/storage/BUILD index fb088527b..773c5ea9a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/storage/BUILD @@ -36,7 +36,6 @@ go_library( "//pkg/registry/core/resourcequota:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/storage/storage.go index 391cb17f0..8e9ea9533 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -72,11 +73,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/strategy.go index eecfc59d9..dc313ac9b 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/resourcequota/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package resourcequota import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" @@ -42,20 +43,20 @@ func (resourcequotaStrategy) NamespaceScoped() bool { } // PrepareForCreate clears fields that are not allowed to be set by end users on creation. -func (resourcequotaStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (resourcequotaStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { resourcequota := obj.(*api.ResourceQuota) resourcequota.Status = api.ResourceQuotaStatus{} } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (resourcequotaStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (resourcequotaStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newResourcequota := obj.(*api.ResourceQuota) oldResourcequota := old.(*api.ResourceQuota) newResourcequota.Status = oldResourcequota.Status } // Validate validates a new resourcequota. -func (resourcequotaStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (resourcequotaStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { resourcequota := obj.(*api.ResourceQuota) return validation.ValidateResourceQuota(resourcequota) } @@ -70,7 +71,7 @@ func (resourcequotaStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (resourcequotaStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (resourcequotaStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { errorList := validation.ValidateResourceQuota(obj.(*api.ResourceQuota)) return append(errorList, validation.ValidateResourceQuotaUpdate(obj.(*api.ResourceQuota), old.(*api.ResourceQuota))...) } @@ -85,12 +86,12 @@ type resourcequotaStatusStrategy struct { var StatusStrategy = resourcequotaStatusStrategy{Strategy} -func (resourcequotaStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (resourcequotaStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newResourcequota := obj.(*api.ResourceQuota) oldResourcequota := old.(*api.ResourceQuota) newResourcequota.Spec = oldResourcequota.Spec } -func (resourcequotaStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (resourcequotaStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateResourceQuotaStatusUpdate(obj.(*api.ResourceQuota), old.(*api.ResourceQuota)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/rest/storage_core.go b/vendor/k8s.io/kubernetes/pkg/registry/core/rest/storage_core.go index d085022aa..41e21f995 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/rest/storage_core.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/rest/storage_core.go @@ -95,7 +95,7 @@ type LegacyRESTStorage struct { func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generic.RESTOptionsGetter) (LegacyRESTStorage, genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.APIGroupInfo{ - GroupMeta: *legacyscheme.Registry.GroupOrDie(api.GroupName), + PrioritizedVersions: legacyscheme.Scheme.PrioritizedVersionsForGroup(""), VersionedResourcesStorageMap: map[string]map[string]rest.Storage{}, Scheme: legacyscheme.Scheme, ParameterCodec: legacyscheme.ParameterCodec, @@ -103,7 +103,7 @@ func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generi } var podDisruptionClient policyclient.PodDisruptionBudgetsGetter - if policyGroupVersion := (schema.GroupVersion{Group: "policy", Version: "v1beta1"}); legacyscheme.Registry.IsEnabledVersion(policyGroupVersion) { + if policyGroupVersion := (schema.GroupVersion{Group: "policy", Version: "v1beta1"}); legacyscheme.Scheme.IsVersionRegistered(policyGroupVersion) { var err error podDisruptionClient, err = policyclient.NewForConfig(c.LoopbackClientConfig) if err != nil { @@ -226,10 +226,10 @@ func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generi "componentStatuses": componentstatus.NewStorage(componentStatusStorage{c.StorageFactory}.serversToValidate), } - if legacyscheme.Registry.IsEnabledVersion(schema.GroupVersion{Group: "autoscaling", Version: "v1"}) { + if legacyscheme.Scheme.IsVersionRegistered(schema.GroupVersion{Group: "autoscaling", Version: "v1"}) { restStorageMap["replicationControllers/scale"] = controllerStorage.Scale } - if legacyscheme.Registry.IsEnabledVersion(schema.GroupVersion{Group: "policy", Version: "v1beta1"}) { + if legacyscheme.Scheme.IsVersionRegistered(schema.GroupVersion{Group: "policy", Version: "v1beta1"}) { restStorageMap["pods/eviction"] = podStorage.Eviction } if serviceAccountStorage.Token != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/secret/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/secret/BUILD index 2626c3cec..7d166d5e9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/secret/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/secret/BUILD @@ -22,7 +22,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", @@ -35,7 +34,6 @@ go_test( srcs = ["strategy_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/apis/core:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/secret/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/secret/storage/storage.go index 20c6413b6..d6c91ab48 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/secret/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/secret/storage/storage.go @@ -46,7 +46,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST { TableConvertor: printerstorage.TableConvertor{TablePrinter: printers.NewTablePrinter().With(printersinternal.AddHandlers)}, } - options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: secret.GetAttrs} + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: secret.GetAttrs, TriggerFunc: secret.SecretNameTriggerFunc} if err := store.CompleteWithOptions(options); err != nil { panic(err) // TODO: Propagate error up } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/secret/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/secret/strategy.go index fbdb05572..d52fd42ab 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/secret/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/secret/strategy.go @@ -17,6 +17,7 @@ limitations under the License. package secret import ( + "context" "fmt" "k8s.io/apimachinery/pkg/api/errors" @@ -24,10 +25,9 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" - apistorage "k8s.io/apiserver/pkg/storage" + pkgstorage "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" @@ -52,10 +52,10 @@ func (strategy) NamespaceScoped() bool { return true } -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { } -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return validation.ValidateSecret(obj.(*api.Secret)) } @@ -66,10 +66,10 @@ func (strategy) AllowCreateOnUpdate() bool { return false } -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } -func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateSecretUpdate(obj.(*api.Secret), old.(*api.Secret)) } @@ -77,7 +77,7 @@ func (strategy) AllowUnconditionalUpdate() bool { return true } -func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error { +func (s strategy) Export(ctx context.Context, obj runtime.Object, exact bool) error { t, ok := obj.(*api.Secret) if !ok { // unexpected programmer error @@ -107,14 +107,21 @@ func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) { } // Matcher returns a generic matcher for a given label and field selector. -func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate { - return apistorage.SelectionPredicate{ - Label: label, - Field: field, - GetAttrs: GetAttrs, +func Matcher(label labels.Selector, field fields.Selector) pkgstorage.SelectionPredicate { + return pkgstorage.SelectionPredicate{ + Label: label, + Field: field, + GetAttrs: GetAttrs, + IndexFields: []string{"metadata.name"}, } } +func SecretNameTriggerFunc(obj runtime.Object) []pkgstorage.MatchValue { + secret := obj.(*api.Secret) + result := pkgstorage.MatchValue{IndexName: "metadata.name", Value: secret.ObjectMeta.Name} + return []pkgstorage.MatchValue{result} +} + // SelectableFields returns a field set that can be used for filter selection func SelectableFields(obj *api.Secret) fields.Set { objectMetaFieldsSet := generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/secret/strategy_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/secret/strategy_test.go index dda59ab1e..f54d5e295 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/secret/strategy_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/secret/strategy_test.go @@ -23,7 +23,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/kubernetes/pkg/api/legacyscheme" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" @@ -107,7 +106,7 @@ func TestExportSecret(t *testing.T) { func TestSelectableFieldLabelConversions(t *testing.T) { apitesting.TestSelectableFieldLabelConversionsOfKind(t, - legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + "v1", "Secret", SelectableFields(&api.Secret{}), nil, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/service/BUILD index fd277aa7c..87bf41841 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/BUILD @@ -27,7 +27,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/proxy:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/BUILD index d77f66c40..ce71b7a4a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/BUILD @@ -14,7 +14,6 @@ go_test( "//pkg/apis/core:go_default_library", "//pkg/registry/core/service/allocator:go_default_library", "//pkg/registry/registrytest:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library", ], @@ -28,7 +27,6 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/registry/core/rangeallocation:go_default_library", "//pkg/registry/core/service/allocator:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/storage.go index 03f28431a..52a9acde0 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/storage.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "errors" "fmt" "sync" @@ -32,8 +33,6 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/registry/core/rangeallocation" "k8s.io/kubernetes/pkg/registry/core/service/allocator" - - "golang.org/x/net/context" ) var ( diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/storage_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/storage_test.go index a0f2cceb6..aaacb0f86 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/storage_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/allocator/storage/storage_test.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "strings" "testing" @@ -25,8 +26,6 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/registry/core/service/allocator" "k8s.io/kubernetes/pkg/registry/registrytest" - - "golang.org/x/net/context" ) func newStorage(t *testing.T) (*Etcd, *etcdtesting.EtcdTestServer, allocator.Interface, *storagebackend.Config) { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/ipallocator/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/service/ipallocator/storage/BUILD index 3c7b085ca..d3597b78b 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/ipallocator/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/ipallocator/storage/BUILD @@ -16,7 +16,6 @@ go_test( "//pkg/registry/core/service/allocator/storage:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", "//pkg/registry/registrytest:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/ipallocator/storage/storage_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/service/ipallocator/storage/storage_test.go index f70197d72..85fb2bce5 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/ipallocator/storage/storage_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/ipallocator/storage/storage_test.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "net" "strings" "testing" @@ -30,8 +31,6 @@ import ( allocatorstore "k8s.io/kubernetes/pkg/registry/core/service/allocator/storage" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" "k8s.io/kubernetes/pkg/registry/registrytest" - - "golang.org/x/net/context" ) func newStorage(t *testing.T) (*etcdtesting.EtcdTestServer, ipallocator.Interface, allocator.Interface, storage.Interface, factory.DestroyFunc) { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/proxy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/service/proxy.go index 23e016b07..2ddf87df9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/proxy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/proxy.go @@ -17,6 +17,7 @@ limitations under the License. package service import ( + "context" "fmt" "net/http" "net/url" @@ -24,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/proxy" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/capabilities" @@ -57,7 +57,7 @@ func (r *ProxyREST) NewConnectOptions() (runtime.Object, bool, string) { } // Connect returns a handler for the service proxy -func (r *ProxyREST) Connect(ctx genericapirequest.Context, id string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { +func (r *ProxyREST) Connect(ctx context.Context, id string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { proxyOpts, ok := opts.(*api.ServiceProxyOptions) if !ok { return nil, fmt.Errorf("Invalid options object: %#v", opts) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/core/service/registry.go index 332d651e7..cbb738489 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/registry.go @@ -17,25 +17,25 @@ limitations under the License. package service import ( + "context" "fmt" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" ) // Registry is an interface for things that know how to store services. type Registry interface { - ListServices(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.ServiceList, error) - CreateService(ctx genericapirequest.Context, svc *api.Service, createValidation rest.ValidateObjectFunc) (*api.Service, error) - GetService(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*api.Service, error) - DeleteService(ctx genericapirequest.Context, name string) error - UpdateService(ctx genericapirequest.Context, svc *api.Service, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.Service, error) - WatchServices(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) - ExportService(ctx genericapirequest.Context, name string, options metav1.ExportOptions) (*api.Service, error) + ListServices(ctx context.Context, options *metainternalversion.ListOptions) (*api.ServiceList, error) + CreateService(ctx context.Context, svc *api.Service, createValidation rest.ValidateObjectFunc) (*api.Service, error) + GetService(ctx context.Context, name string, options *metav1.GetOptions) (*api.Service, error) + DeleteService(ctx context.Context, name string) error + UpdateService(ctx context.Context, svc *api.Service, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.Service, error) + WatchServices(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ExportService(ctx context.Context, name string, options metav1.ExportOptions) (*api.Service, error) } // storage puts strong typing around storage calls @@ -49,7 +49,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListServices(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.ServiceList, error) { +func (s *storage) ListServices(ctx context.Context, options *metainternalversion.ListOptions) (*api.ServiceList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err @@ -57,7 +57,7 @@ func (s *storage) ListServices(ctx genericapirequest.Context, options *metainter return obj.(*api.ServiceList), nil } -func (s *storage) CreateService(ctx genericapirequest.Context, svc *api.Service, createValidation rest.ValidateObjectFunc) (*api.Service, error) { +func (s *storage) CreateService(ctx context.Context, svc *api.Service, createValidation rest.ValidateObjectFunc) (*api.Service, error) { obj, err := s.Create(ctx, svc, createValidation, false) if err != nil { return nil, err @@ -65,7 +65,7 @@ func (s *storage) CreateService(ctx genericapirequest.Context, svc *api.Service, return obj.(*api.Service), nil } -func (s *storage) GetService(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*api.Service, error) { +func (s *storage) GetService(ctx context.Context, name string, options *metav1.GetOptions) (*api.Service, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err @@ -73,12 +73,12 @@ func (s *storage) GetService(ctx genericapirequest.Context, name string, options return obj.(*api.Service), nil } -func (s *storage) DeleteService(ctx genericapirequest.Context, name string) error { +func (s *storage) DeleteService(ctx context.Context, name string) error { _, _, err := s.Delete(ctx, name, nil) return err } -func (s *storage) UpdateService(ctx genericapirequest.Context, svc *api.Service, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.Service, error) { +func (s *storage) UpdateService(ctx context.Context, svc *api.Service, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.Service, error) { obj, _, err := s.Update(ctx, svc.Name, rest.DefaultUpdatedObjectInfo(svc), createValidation, updateValidation) if err != nil { return nil, err @@ -86,13 +86,13 @@ func (s *storage) UpdateService(ctx genericapirequest.Context, svc *api.Service, return obj.(*api.Service), nil } -func (s *storage) WatchServices(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchServices(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } // If StandardStorage implements rest.Exporter, returns exported service. // Otherwise export is not supported. -func (s *storage) ExportService(ctx genericapirequest.Context, name string, options metav1.ExportOptions) (*api.Service, error) { +func (s *storage) ExportService(ctx context.Context, name string, options metav1.ExportOptions) (*api.Service, error) { exporter, isExporter := s.StandardStorage.(rest.Exporter) if !isExporter { return nil, fmt.Errorf("export is not supported") diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/rest.go b/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/rest.go index 6dea373d1..f8c0e8582 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/rest.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/rest.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "fmt" "math/rand" "net" @@ -69,6 +70,7 @@ type ServiceNodePort struct { } type ServiceStorage interface { + rest.Scoper rest.Getter rest.Lister rest.CreaterUpdater @@ -122,6 +124,10 @@ func (rs *REST) Categories() []string { return []string{"all"} } +func (rs *REST) NamespaceScoped() bool { + return rs.services.NamespaceScoped() +} + func (rs *REST) New() runtime.Object { return rs.services.New() } @@ -130,23 +136,23 @@ func (rs *REST) NewList() runtime.Object { return rs.services.NewList() } -func (rs *REST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (rs *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return rs.services.Get(ctx, name, options) } -func (rs *REST) List(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { +func (rs *REST) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { return rs.services.List(ctx, options) } -func (rs *REST) Watch(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (rs *REST) Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return rs.services.Watch(ctx, options) } -func (rs *REST) Export(ctx genericapirequest.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { +func (rs *REST) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { return rs.services.Export(ctx, name, opts) } -func (rs *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (rs *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { service := obj.(*api.Service) if err := rest.BeforeCreate(registry.Strategy, ctx, obj); err != nil { @@ -207,7 +213,7 @@ func (rs *REST) Create(ctx genericapirequest.Context, obj runtime.Object, create return out, err } -func (rs *REST) Delete(ctx genericapirequest.Context, id string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { +func (rs *REST) Delete(ctx context.Context, id string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { // TODO: handle graceful obj, _, err := rs.services.Delete(ctx, id, options) if err != nil { @@ -320,7 +326,7 @@ func (rs *REST) healthCheckNodePortUpdate(oldService, service *api.Service, node return true, nil } -func (rs *REST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (rs *REST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { oldObj, err := rs.services.Get(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, err @@ -338,9 +344,8 @@ func (rs *REST) Update(ctx genericapirequest.Context, name string, objInfo rest. } // Copy over non-user fields - // TODO: make this a merge function - if errs := validation.ValidateServiceUpdate(service, oldService); len(errs) > 0 { - return nil, false, errors.NewInvalid(api.Kind("Service"), service.Name, errs) + if err := rest.BeforeUpdate(registry.Strategy, ctx, service, oldService); err != nil { + return nil, false, err } // TODO: this should probably move to strategy.PrepareForCreate() @@ -413,7 +418,7 @@ func (rs *REST) Update(ctx genericapirequest.Context, name string, objInfo rest. var _ = rest.Redirector(&REST{}) // ResourceLocation returns a URL to which one can send traffic for the specified service. -func (rs *REST) ResourceLocation(ctx genericapirequest.Context, id string) (*url.URL, http.RoundTripper, error) { +func (rs *REST) ResourceLocation(ctx context.Context, id string) (*url.URL, http.RoundTripper, error) { // Allow ID as "svcname", "svcname:port", or "scheme:svcname:port". svcScheme, svcName, portStr, valid := utilnet.SplitSchemeNamePort(id) if !valid { @@ -486,11 +491,11 @@ func (rs *REST) ResourceLocation(ctx genericapirequest.Context, id string) (*url return nil, nil, errors.NewServiceUnavailable(fmt.Sprintf("no endpoints available for service %q", id)) } -func (r *REST) ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { +func (r *REST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { return r.services.ConvertToTable(ctx, object, tableOptions) } -func isValidAddress(ctx genericapirequest.Context, addr *api.EndpointAddress, pods rest.Getter) error { +func isValidAddress(ctx context.Context, addr *api.EndpointAddress, pods rest.Getter) error { if addr.TargetRef == nil { return fmt.Errorf("Address has no target ref, skipping: %v", addr) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/rest_test.go b/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/rest_test.go index 9fbb7f26f..3705b6215 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/rest_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/rest_test.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "net" "reflect" "strings" @@ -64,12 +65,16 @@ type serviceStorage struct { Err error } -func (s *serviceStorage) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (s *serviceStorage) NamespaceScoped() bool { + return true +} + +func (s *serviceStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { s.GottenID = name return s.Service, s.Err } -func (s *serviceStorage) GetService(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*api.Service, error) { +func (s *serviceStorage) GetService(ctx context.Context, name string, options *metav1.GetOptions) (*api.Service, error) { return s.Service, s.Err } @@ -77,7 +82,7 @@ func (s *serviceStorage) NewList() runtime.Object { panic("not implemented") } -func (s *serviceStorage) List(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { +func (s *serviceStorage) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { ns, _ := genericapirequest.NamespaceFrom(ctx) // Copy metadata from internal list into result @@ -102,7 +107,7 @@ func (s *serviceStorage) New() runtime.Object { panic("not implemented") } -func (s *serviceStorage) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (s *serviceStorage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { svc := obj.(*api.Service) s.CreatedID = obj.(metav1.Object).GetName() s.Service = svc.DeepCopy() @@ -115,7 +120,7 @@ func (s *serviceStorage) Create(ctx genericapirequest.Context, obj runtime.Objec return svc, s.Err } -func (s *serviceStorage) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (s *serviceStorage) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { s.UpdatedID = name obj, err := objInfo.UpdatedObject(ctx, s.OldService) if err != nil { @@ -125,24 +130,24 @@ func (s *serviceStorage) Update(ctx genericapirequest.Context, name string, objI return s.Service, s.Created, s.Err } -func (s *serviceStorage) Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { +func (s *serviceStorage) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { s.DeletedID = name return s.Service, s.DeletedImmediately, s.Err } -func (s *serviceStorage) DeleteCollection(ctx genericapirequest.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) { +func (s *serviceStorage) DeleteCollection(ctx context.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) { panic("not implemented") } -func (s *serviceStorage) Watch(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *serviceStorage) Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { panic("not implemented") } -func (s *serviceStorage) ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { +func (s *serviceStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { panic("not implemented") } -func (s *serviceStorage) Export(ctx genericapirequest.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { +func (s *serviceStorage) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { panic("not implemented") } @@ -207,7 +212,7 @@ func makeIPNet(t *testing.T) *net.IPNet { return net } -func releaseServiceNodePorts(t *testing.T, ctx genericapirequest.Context, svcName string, rest *REST, registry ServiceStorage) { +func releaseServiceNodePorts(t *testing.T, ctx context.Context, svcName string, rest *REST, registry ServiceStorage) { obj, err := registry.Get(ctx, svcName, &metav1.GetOptions{}) if err != nil { t.Errorf("Unexpected error: %v", err) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/storage.go index 131c7c2ba..aa983c8e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -84,11 +85,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/service/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/service/strategy.go index 278da88ed..71cdda7f1 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/service/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/service/strategy.go @@ -17,11 +17,11 @@ limitations under the License. package service import ( + "context" "fmt" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" @@ -44,20 +44,20 @@ func (svcStrategy) NamespaceScoped() bool { } // PrepareForCreate clears fields that are not allowed to be set by end users on creation. -func (svcStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (svcStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { service := obj.(*api.Service) service.Status = api.ServiceStatus{} } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (svcStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (svcStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newService := obj.(*api.Service) oldService := old.(*api.Service) newService.Status = oldService.Status } // Validate validates a new service. -func (svcStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (svcStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { service := obj.(*api.Service) return validation.ValidateService(service) } @@ -70,7 +70,7 @@ func (svcStrategy) AllowCreateOnUpdate() bool { return true } -func (svcStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (svcStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateServiceUpdate(obj.(*api.Service), old.(*api.Service)) } @@ -78,7 +78,7 @@ func (svcStrategy) AllowUnconditionalUpdate() bool { return true } -func (svcStrategy) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error { +func (svcStrategy) Export(ctx context.Context, obj runtime.Object, exact bool) error { t, ok := obj.(*api.Service) if !ok { // unexpected programmer error @@ -108,7 +108,7 @@ type serviceStatusStrategy struct { var StatusStrategy = serviceStatusStrategy{Strategy} // PrepareForUpdate clears fields that are not allowed to be set by end users on update of status -func (serviceStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (serviceStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newService := obj.(*api.Service) oldService := old.(*api.Service) // status changes are not allowed to update spec @@ -116,6 +116,6 @@ func (serviceStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj } // ValidateUpdate is the default update validation for an end user updating status -func (serviceStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (serviceStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateServiceStatusUpdate(obj.(*api.Service), old.(*api.Service)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/BUILD index 076f7f734..a1327e3e0 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/BUILD @@ -18,7 +18,6 @@ go_library( "//pkg/apis/core/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/OWNERS b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/OWNERS new file mode 100644 index 000000000..1d5fd2603 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/OWNERS @@ -0,0 +1,6 @@ +reviewers: +- mikedanese +- liggitt +approvers: +- mikedanese +- liggitt diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage/BUILD index 1469f6638..d74dcd4db 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage/BUILD @@ -32,6 +32,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage", deps = [ "//pkg/apis/authentication:go_default_library", + "//pkg/apis/authentication/validation:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage/token.go b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage/token.go index 276681bd7..e1a94f6e5 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage/token.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage/token.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "fmt" authenticationapiv1 "k8s.io/api/authentication/v1" @@ -28,6 +29,7 @@ import ( genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" authenticationapi "k8s.io/kubernetes/pkg/apis/authentication" + authenticationvalidation "k8s.io/kubernetes/pkg/apis/authentication/validation" api "k8s.io/kubernetes/pkg/apis/core" token "k8s.io/kubernetes/pkg/serviceaccount" ) @@ -45,14 +47,25 @@ type TokenREST struct { } var _ = rest.NamedCreater(&TokenREST{}) +var _ = rest.GroupVersionKindProvider(&TokenREST{}) -func (r *TokenREST) Create(ctx genericapirequest.Context, name string, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +var gvk = schema.GroupVersionKind{ + Group: authenticationapiv1.SchemeGroupVersion.Group, + Version: authenticationapiv1.SchemeGroupVersion.Version, + Kind: "TokenRequest", +} + +func (r *TokenREST) Create(ctx context.Context, name string, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { if err := createValidation(obj); err != nil { return nil, err } out := obj.(*authenticationapi.TokenRequest) + if errs := authenticationvalidation.ValidateTokenRequest(out); len(errs) != 0 { + return nil, errors.NewInvalid(gvk.GroupKind(), "", errs) + } + svcacctObj, err := r.svcaccts.Get(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, err @@ -70,17 +83,19 @@ func (r *TokenREST) Create(ctx genericapirequest.Context, name string, obj runti gvk := schema.FromAPIVersionAndKind(ref.APIVersion, ref.Kind) switch { case gvk.Group == "" && gvk.Kind == "Pod": - podObj, err := r.pods.Get(ctx, ref.Name, &metav1.GetOptions{}) + newCtx := newContext(ctx, "pods", ref.Name, gvk) + podObj, err := r.pods.Get(newCtx, ref.Name, &metav1.GetOptions{}) if err != nil { return nil, err } pod = podObj.(*api.Pod) if name != pod.Spec.ServiceAccountName { - return nil, errors.NewBadRequest(fmt.Sprintf("cannot bind token for serviceaccount %q to pod running with serviceaccount %q", name, pod.Spec.ServiceAccountName)) + return nil, errors.NewBadRequest(fmt.Sprintf("cannot bind token for serviceaccount %q to pod running with different serviceaccount name.", name)) } uid = pod.UID case gvk.Group == "" && gvk.Kind == "Secret": - secretObj, err := r.secrets.Get(ctx, ref.Name, &metav1.GetOptions{}) + newCtx := newContext(ctx, "secrets", ref.Name, gvk) + secretObj, err := r.secrets.Get(newCtx, ref.Name, &metav1.GetOptions{}) if err != nil { return nil, err } @@ -90,7 +105,7 @@ func (r *TokenREST) Create(ctx genericapirequest.Context, name string, obj runti return nil, errors.NewBadRequest(fmt.Sprintf("cannot bind token to object of type %s", gvk.String())) } if ref.UID != "" && uid != ref.UID { - return nil, errors.NewConflict(schema.GroupResource{Group: gvk.Group, Resource: gvk.Kind}, ref.Name, fmt.Errorf("the UID in the bound object reference (%s) does not match the UID in record (%s). The object might have been deleted and then recreated", ref.UID, uid)) + return nil, errors.NewConflict(schema.GroupResource{Group: gvk.Group, Resource: gvk.Kind}, ref.Name, fmt.Errorf("the UID in the bound object reference (%s) does not match the UID in record. The object might have been deleted and then recreated", ref.UID)) } } if len(out.Spec.Audiences) == 0 { @@ -109,14 +124,29 @@ func (r *TokenREST) Create(ctx genericapirequest.Context, name string, obj runti return out, nil } -func (r *TokenREST) GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind { - return schema.GroupVersionKind{ - Group: authenticationapiv1.SchemeGroupVersion.Group, - Version: authenticationapiv1.SchemeGroupVersion.Version, - Kind: "TokenRequest", - } +func (r *TokenREST) GroupVersionKind(schema.GroupVersion) schema.GroupVersionKind { + return gvk } type getter interface { - Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) + Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) +} + +// newContext return a copy of ctx in which new RequestInfo is set +func newContext(ctx context.Context, resource, name string, gvk schema.GroupVersionKind) context.Context { + oldInfo, found := genericapirequest.RequestInfoFrom(ctx) + if !found { + return ctx + } + newInfo := genericapirequest.RequestInfo{ + IsResourceRequest: true, + Verb: "get", + Namespace: oldInfo.Namespace, + Resource: resource, + Name: name, + Parts: []string{resource, name}, + APIGroup: gvk.Group, + APIVersion: gvk.Version, + } + return genericapirequest.WithRequestInfo(ctx, &newInfo) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/strategy.go index 8a6a37207..a37826dd8 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/serviceaccount/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package serviceaccount import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" @@ -40,11 +41,11 @@ func (strategy) NamespaceScoped() bool { return true } -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { cleanSecretReferences(obj.(*api.ServiceAccount)) } -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return validation.ValidateServiceAccount(obj.(*api.ServiceAccount)) } @@ -56,7 +57,7 @@ func (strategy) AllowCreateOnUpdate() bool { return false } -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { cleanSecretReferences(obj.(*api.ServiceAccount)) } @@ -66,7 +67,7 @@ func cleanSecretReferences(serviceAccount *api.ServiceAccount) { } } -func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateServiceAccountUpdate(obj.(*api.ServiceAccount), old.(*api.ServiceAccount)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/events/event/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/events/event/BUILD index 6f69eb739..8c5f488f5 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/events/event/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/events/event/BUILD @@ -16,7 +16,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/events/event/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/events/event/strategy.go index f2958c4b1..a043384ad 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/events/event/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/events/event/strategy.go @@ -17,13 +17,13 @@ limitations under the License. package event import ( + "context" "fmt" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" apistorage "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" @@ -47,15 +47,15 @@ func (eventStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a Pod Preset before creation. -func (eventStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (eventStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (eventStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (eventStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } // Validate validates a new Event. -func (eventStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (eventStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { event := obj.(*api.Event) return validation.ValidateEvent(event) } @@ -69,7 +69,7 @@ func (eventStrategy) AllowCreateOnUpdate() bool { func (eventStrategy) Canonicalize(obj runtime.Object) {} // ValidateUpdate is the default update validation for an end user. -func (eventStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (eventStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { event := obj.(*api.Event) return validation.ValidateEvent(event) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/events/rest/storage_events.go b/vendor/k8s.io/kubernetes/pkg/registry/events/rest/storage_events.go index b7bea4f0f..de4caba38 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/events/rest/storage_events.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/events/rest/storage_events.go @@ -34,13 +34,12 @@ type RESTStorageProvider struct { } func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(events.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(events.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(eventsapiv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[eventsapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = eventsapiv1beta1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/controller/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/extensions/controller/storage/BUILD index 26a1fd9f4..63b97e272 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/controller/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/extensions/controller/storage/BUILD @@ -39,7 +39,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/controller/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/extensions/controller/storage/storage.go index 774a78911..ce4d89701 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/controller/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/extensions/controller/storage/storage.go @@ -17,13 +17,13 @@ limitations under the License. package storage import ( + "context" "fmt" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/autoscaling" @@ -63,7 +63,7 @@ func (r *ScaleREST) New() runtime.Object { return &autoscaling.Scale{} } -func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *ScaleREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { rc, err := (*r.registry).GetController(ctx, name, options) if err != nil { return nil, errors.NewNotFound(extensions.Resource("replicationcontrollers/scale"), name) @@ -71,7 +71,7 @@ func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *met return scaleFromRC(rc), nil } -func (r *ScaleREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { rc, err := (*r.registry).GetController(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, errors.NewNotFound(extensions.Resource("replicationcontrollers/scale"), name) @@ -124,6 +124,10 @@ func scaleFromRC(rc *api.ReplicationController) *autoscaling.Scale { // Dummy implementation type RcREST struct{} +func (r *RcREST) NamespaceScoped() bool { + return true +} + func (r *RcREST) New() runtime.Object { return &extensions.ReplicationControllerDummy{} } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/BUILD index 63b888a32..3c98c6bf1 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/BUILD @@ -20,7 +20,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/storage/BUILD index bffa12adb..b4c59e0c7 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/storage/BUILD @@ -37,7 +37,6 @@ go_library( "//pkg/registry/extensions/ingress:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/storage/storage.go index 0c7273d85..26fa74c10 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -76,11 +77,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/strategy.go index e970d105c..1dc2efbd4 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/extensions/ingress/strategy.go @@ -17,10 +17,11 @@ limitations under the License. package ingress import ( + "context" + apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/extensions" @@ -42,7 +43,7 @@ func (ingressStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of an Ingress before creation. -func (ingressStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (ingressStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { ingress := obj.(*extensions.Ingress) // create cannot set status ingress.Status = extensions.IngressStatus{} @@ -51,7 +52,7 @@ func (ingressStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runti } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (ingressStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (ingressStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newIngress := obj.(*extensions.Ingress) oldIngress := old.(*extensions.Ingress) // Update is not allowed to set status @@ -67,7 +68,7 @@ func (ingressStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old } // Validate validates a new Ingress. -func (ingressStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (ingressStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { ingress := obj.(*extensions.Ingress) err := validation.ValidateIngress(ingress) return err @@ -83,7 +84,7 @@ func (ingressStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (ingressStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (ingressStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { validationErrorList := validation.ValidateIngress(obj.(*extensions.Ingress)) updateErrorList := validation.ValidateIngressUpdate(obj.(*extensions.Ingress), old.(*extensions.Ingress)) return append(validationErrorList, updateErrorList...) @@ -101,7 +102,7 @@ type ingressStatusStrategy struct { var StatusStrategy = ingressStatusStrategy{Strategy} // PrepareForUpdate clears fields that are not allowed to be set by end users on update of status -func (ingressStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (ingressStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newIngress := obj.(*extensions.Ingress) oldIngress := old.(*extensions.Ingress) // status changes are not allowed to update spec @@ -109,6 +110,6 @@ func (ingressStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj } // ValidateUpdate is the default update validation for an end user updating status -func (ingressStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (ingressStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateIngressStatusUpdate(obj.(*extensions.Ingress), old.(*extensions.Ingress)) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/BUILD deleted file mode 100644 index eadcc39d2..000000000 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "strategy.go", - ], - importpath = "k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy", - deps = [ - "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/extensions:go_default_library", - "//pkg/apis/extensions/validation:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", - "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", - "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/registry/extensions/podsecuritypolicy/storage:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/doc.go b/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/doc.go deleted file mode 100644 index 0768815df..000000000 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -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 podsecuritypolicy provides Registry interface and its REST -// implementation for storing PodSecurityPolicy api objects. -package podsecuritypolicy // import "k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy" diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage/BUILD deleted file mode 100644 index 335150fe0..000000000 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage/BUILD +++ /dev/null @@ -1,54 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["storage_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/apis/extensions:go_default_library", - "//pkg/registry/registrytest:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", - "//vendor/k8s.io/apiserver/pkg/registry/generic/testing:go_default_library", - "//vendor/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = ["storage.go"], - importpath = "k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage", - deps = [ - "//pkg/apis/extensions:go_default_library", - "//pkg/printers:go_default_library", - "//pkg/printers/internalversion:go_default_library", - "//pkg/printers/storage:go_default_library", - "//pkg/registry/extensions/podsecuritypolicy:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", - "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/strategy.go deleted file mode 100644 index 118b69146..000000000 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/strategy.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -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 podsecuritypolicy - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/apiserver/pkg/registry/rest" - "k8s.io/apiserver/pkg/storage/names" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/apis/extensions/validation" -) - -// strategy implements behavior for PodSecurityPolicy objects -type strategy struct { - runtime.ObjectTyper - names.NameGenerator -} - -// Strategy is the default logic that applies when creating and updating PodSecurityPolicy -// objects via the REST API. -var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator} - -var _ = rest.RESTCreateStrategy(Strategy) - -var _ = rest.RESTUpdateStrategy(Strategy) - -func (strategy) NamespaceScoped() bool { - return false -} - -func (strategy) AllowCreateOnUpdate() bool { - return false -} - -func (strategy) AllowUnconditionalUpdate() bool { - return true -} - -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { -} - -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { -} - -func (strategy) Canonicalize(obj runtime.Object) { -} - -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { - return validation.ValidatePodSecurityPolicy(obj.(*extensions.PodSecurityPolicy)) -} - -func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { - return validation.ValidatePodSecurityPolicyUpdate(old.(*extensions.PodSecurityPolicy), obj.(*extensions.PodSecurityPolicy)) -} diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/rest/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/extensions/rest/BUILD index 4e984a458..a93751bbd 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/rest/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/extensions/rest/BUILD @@ -17,8 +17,8 @@ go_library( "//pkg/registry/apps/replicaset/storage:go_default_library", "//pkg/registry/extensions/controller/storage:go_default_library", "//pkg/registry/extensions/ingress/storage:go_default_library", - "//pkg/registry/extensions/podsecuritypolicy/storage:go_default_library", "//pkg/registry/networking/networkpolicy/storage:go_default_library", + "//pkg/registry/policy/podsecuritypolicy/storage:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/rest/storage_extensions.go b/vendor/k8s.io/kubernetes/pkg/registry/extensions/rest/storage_extensions.go index b77ca23ba..2b21e502f 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/rest/storage_extensions.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/extensions/rest/storage_extensions.go @@ -29,20 +29,19 @@ import ( replicasetstore "k8s.io/kubernetes/pkg/registry/apps/replicaset/storage" expcontrollerstore "k8s.io/kubernetes/pkg/registry/extensions/controller/storage" ingressstore "k8s.io/kubernetes/pkg/registry/extensions/ingress/storage" - pspstore "k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage" networkpolicystore "k8s.io/kubernetes/pkg/registry/networking/networkpolicy/storage" + pspstore "k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage" ) type RESTStorageProvider struct{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(extensions.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(extensions.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[extensionsapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = extensionsapiv1beta1.SchemeGroupVersion } return apiGroupInfo, true @@ -74,8 +73,8 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag storage["ingresses/status"] = ingressStatusStorage // podsecuritypolicy - podSecurityExtensionsStorage := pspstore.NewREST(restOptionsGetter) - storage["podSecurityPolicies"] = podSecurityExtensionsStorage + podSecurityPolicyStorage := pspstore.NewREST(restOptionsGetter) + storage["podSecurityPolicies"] = podSecurityPolicyStorage // replicasets replicaSetStorage := replicasetstore.NewStorage(restOptionsGetter) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/BUILD index f5e836166..816dbf69a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/BUILD @@ -22,7 +22,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/registry.go index 1ddcd2139..465667303 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/registry.go @@ -17,22 +17,23 @@ limitations under the License. package networkpolicy import ( + "context" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/networking" ) // Registry is an interface for things that know how to store NetworkPolicies. type Registry interface { - ListNetworkPolicies(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*networking.NetworkPolicyList, error) - CreateNetworkPolicy(ctx genericapirequest.Context, np *networking.NetworkPolicy, createValidation rest.ValidateObjectFunc) error - UpdateNetworkPolicy(ctx genericapirequest.Context, np *networking.NetworkPolicy, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetNetworkPolicy(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*networking.NetworkPolicy, error) - DeleteNetworkPolicy(ctx genericapirequest.Context, name string) error - WatchNetworkPolicies(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ListNetworkPolicies(ctx context.Context, options *metainternalversion.ListOptions) (*networking.NetworkPolicyList, error) + CreateNetworkPolicy(ctx context.Context, np *networking.NetworkPolicy, createValidation rest.ValidateObjectFunc) error + UpdateNetworkPolicy(ctx context.Context, np *networking.NetworkPolicy, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error + GetNetworkPolicy(ctx context.Context, name string, options *metav1.GetOptions) (*networking.NetworkPolicy, error) + DeleteNetworkPolicy(ctx context.Context, name string) error + WatchNetworkPolicies(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) } // storage puts strong typing around storage calls @@ -46,7 +47,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListNetworkPolicies(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*networking.NetworkPolicyList, error) { +func (s *storage) ListNetworkPolicies(ctx context.Context, options *metainternalversion.ListOptions) (*networking.NetworkPolicyList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err @@ -55,21 +56,21 @@ func (s *storage) ListNetworkPolicies(ctx genericapirequest.Context, options *me return obj.(*networking.NetworkPolicyList), nil } -func (s *storage) CreateNetworkPolicy(ctx genericapirequest.Context, np *networking.NetworkPolicy, createValidation rest.ValidateObjectFunc) error { +func (s *storage) CreateNetworkPolicy(ctx context.Context, np *networking.NetworkPolicy, createValidation rest.ValidateObjectFunc) error { _, err := s.Create(ctx, np, createValidation, false) return err } -func (s *storage) UpdateNetworkPolicy(ctx genericapirequest.Context, np *networking.NetworkPolicy, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { +func (s *storage) UpdateNetworkPolicy(ctx context.Context, np *networking.NetworkPolicy, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { _, _, err := s.Update(ctx, np.Name, rest.DefaultUpdatedObjectInfo(np), createValidation, updateValidation) return err } -func (s *storage) WatchNetworkPolicies(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchNetworkPolicies(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetNetworkPolicy(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*networking.NetworkPolicy, error) { +func (s *storage) GetNetworkPolicy(ctx context.Context, name string, options *metav1.GetOptions) (*networking.NetworkPolicy, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err @@ -77,7 +78,7 @@ func (s *storage) GetNetworkPolicy(ctx genericapirequest.Context, name string, o return obj.(*networking.NetworkPolicy), nil } -func (s *storage) DeleteNetworkPolicy(ctx genericapirequest.Context, name string) error { +func (s *storage) DeleteNetworkPolicy(ctx context.Context, name string) error { _, _, err := s.Delete(ctx, name, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/strategy.go index 16e0b54a6..8dc3ea7ed 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/networking/networkpolicy/strategy.go @@ -17,11 +17,11 @@ limitations under the License. package networkpolicy import ( + "context" "reflect" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/networking" @@ -43,13 +43,13 @@ func (networkPolicyStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a NetworkPolicy before creation. -func (networkPolicyStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (networkPolicyStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { networkPolicy := obj.(*networking.NetworkPolicy) networkPolicy.Generation = 1 } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (networkPolicyStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (networkPolicyStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newNetworkPolicy := obj.(*networking.NetworkPolicy) oldNetworkPolicy := old.(*networking.NetworkPolicy) @@ -62,7 +62,7 @@ func (networkPolicyStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj } // Validate validates a new NetworkPolicy. -func (networkPolicyStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (networkPolicyStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { networkPolicy := obj.(*networking.NetworkPolicy) return validation.ValidateNetworkPolicy(networkPolicy) } @@ -76,7 +76,7 @@ func (networkPolicyStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (networkPolicyStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (networkPolicyStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { validationErrorList := validation.ValidateNetworkPolicy(obj.(*networking.NetworkPolicy)) updateErrorList := validation.ValidateNetworkPolicyUpdate(obj.(*networking.NetworkPolicy), old.(*networking.NetworkPolicy)) return append(validationErrorList, updateErrorList...) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/networking/rest/storage_settings.go b/vendor/k8s.io/kubernetes/pkg/registry/networking/rest/storage_settings.go index d50862bb0..40cf8c525 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/networking/rest/storage_settings.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/networking/rest/storage_settings.go @@ -30,13 +30,12 @@ import ( type RESTStorageProvider struct{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(networking.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(networking.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(networkingapiv1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[networkingapiv1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = networkingapiv1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/BUILD index bc8ab60b6..804d7a2c9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/BUILD @@ -20,7 +20,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage/BUILD index 7c1ad4c60..c291e29a8 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage/BUILD @@ -37,7 +37,6 @@ go_library( "//pkg/registry/policy/poddisruptionbudget:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage/storage.go index 40aff589d..b69157401 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage/storage.go @@ -17,9 +17,10 @@ limitations under the License. package storage import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -73,11 +74,11 @@ func (r *StatusREST) New() runtime.Object { } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/strategy.go index 382dc92ab..36e940b6a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/strategy.go @@ -17,10 +17,11 @@ limitations under the License. package poddisruptionbudget import ( + "context" + apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/policy" @@ -42,7 +43,7 @@ func (podDisruptionBudgetStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of an PodDisruptionBudget before creation. -func (podDisruptionBudgetStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (podDisruptionBudgetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { podDisruptionBudget := obj.(*policy.PodDisruptionBudget) // create cannot set status podDisruptionBudget.Status = policy.PodDisruptionBudgetStatus{} @@ -51,7 +52,7 @@ func (podDisruptionBudgetStrategy) PrepareForCreate(ctx genericapirequest.Contex } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (podDisruptionBudgetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (podDisruptionBudgetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPodDisruptionBudget := obj.(*policy.PodDisruptionBudget) oldPodDisruptionBudget := old.(*policy.PodDisruptionBudget) // Update is not allowed to set status @@ -66,7 +67,7 @@ func (podDisruptionBudgetStrategy) PrepareForUpdate(ctx genericapirequest.Contex } // Validate validates a new PodDisruptionBudget. -func (podDisruptionBudgetStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (podDisruptionBudgetStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { podDisruptionBudget := obj.(*policy.PodDisruptionBudget) return validation.ValidatePodDisruptionBudget(podDisruptionBudget) } @@ -81,7 +82,7 @@ func (podDisruptionBudgetStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (podDisruptionBudgetStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (podDisruptionBudgetStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { validationErrorList := validation.ValidatePodDisruptionBudget(obj.(*policy.PodDisruptionBudget)) updateErrorList := validation.ValidatePodDisruptionBudgetUpdate(obj.(*policy.PodDisruptionBudget), old.(*policy.PodDisruptionBudget)) return append(validationErrorList, updateErrorList...) @@ -100,7 +101,7 @@ type podDisruptionBudgetStatusStrategy struct { var StatusStrategy = podDisruptionBudgetStatusStrategy{Strategy} // PrepareForUpdate clears fields that are not allowed to be set by end users on update of status -func (podDisruptionBudgetStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (podDisruptionBudgetStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPodDisruptionBudget := obj.(*policy.PodDisruptionBudget) oldPodDisruptionBudget := old.(*policy.PodDisruptionBudget) // status changes are not allowed to update spec @@ -108,7 +109,7 @@ func (podDisruptionBudgetStatusStrategy) PrepareForUpdate(ctx genericapirequest. } // ValidateUpdate is the default update validation for an end user updating status -func (podDisruptionBudgetStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (podDisruptionBudgetStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { // TODO: Validate status updates. return field.ErrorList{} // return validation.ValidatePodDisruptionBudgetStatusUpdate(obj.(*policy.PodDisruptionBudget), old.(*policy.PodDisruptionBudget)) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/BUILD new file mode 100644 index 000000000..659c7ec19 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/BUILD @@ -0,0 +1,40 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "strategy.go", + ], + importpath = "k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy", + deps = [ + "//pkg/api/legacyscheme:go_default_library", + "//pkg/apis/policy:go_default_library", + "//pkg/apis/policy/validation:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", + "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/registry/policy/podsecuritypolicy/storage:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/doc.go b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/doc.go new file mode 100644 index 000000000..160901d96 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/doc.go @@ -0,0 +1,19 @@ +/* +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 podsecuritypolicy provides Registry interface and its REST +// implementation for storing PodSecurityPolicy api objects. +package podsecuritypolicy // import "k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy" diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage/BUILD new file mode 100644 index 000000000..b4b03dd8c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage/BUILD @@ -0,0 +1,54 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_test( + name = "go_default_test", + srcs = ["storage_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/apis/policy:go_default_library", + "//pkg/registry/registrytest:go_default_library", + "//vendor/k8s.io/api/policy/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/runtime:go_default_library", + "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", + "//vendor/k8s.io/apiserver/pkg/registry/generic/testing:go_default_library", + "//vendor/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library", + ], +) + +go_library( + name = "go_default_library", + srcs = ["storage.go"], + importpath = "k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage", + deps = [ + "//pkg/apis/policy:go_default_library", + "//pkg/printers:go_default_library", + "//pkg/printers/internalversion:go_default_library", + "//pkg/printers/storage:go_default_library", + "//pkg/registry/policy/podsecuritypolicy:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", + "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage/storage.go similarity index 83% rename from vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage/storage.go rename to vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage/storage.go index ceaecefa3..5e8e5c696 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage/storage.go @@ -20,11 +20,11 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" printerstorage "k8s.io/kubernetes/pkg/printers/storage" - "k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy" + "k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy" ) // REST implements a RESTStorage for PodSecurityPolicies. @@ -35,9 +35,9 @@ type REST struct { // NewREST returns a RESTStorage object that will work against PodSecurityPolicy objects. func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &extensions.PodSecurityPolicy{} }, - NewListFunc: func() runtime.Object { return &extensions.PodSecurityPolicyList{} }, - DefaultQualifiedResource: extensions.Resource("podsecuritypolicies"), + NewFunc: func() runtime.Object { return &policy.PodSecurityPolicy{} }, + NewListFunc: func() runtime.Object { return &policy.PodSecurityPolicyList{} }, + DefaultQualifiedResource: policy.Resource("podsecuritypolicies"), CreateStrategy: podsecuritypolicy.Strategy, UpdateStrategy: podsecuritypolicy.Strategy, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage/storage_test.go b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage/storage_test.go similarity index 80% rename from vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage/storage_test.go rename to vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage/storage_test.go index d380c1ac0..8cca24c74 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage/storage_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage/storage_test.go @@ -20,9 +20,9 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/apis/extensions" - // Ensure that extensions/v1beta1 package is initialized. - _ "k8s.io/api/extensions/v1beta1" + "k8s.io/kubernetes/pkg/apis/policy" + // Ensure that policy/v1beta1 package is initialized. + _ "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" @@ -33,7 +33,7 @@ import ( ) func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { - etcdStorage, server := registrytest.NewEtcdStorage(t, "extensions") + etcdStorage, server := registrytest.NewEtcdStorage(t, "policy") restOptions := generic.RESTOptions{ StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, @@ -43,23 +43,23 @@ func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { return NewREST(restOptions), server } -func validNewPodSecurityPolicy() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ +func validNewPodSecurityPolicy() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } @@ -76,7 +76,7 @@ func TestCreate(t *testing.T) { // valid psp, // invalid - &extensions.PodSecurityPolicy{ + &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{Name: "name with spaces"}, }, ) @@ -92,7 +92,7 @@ func TestUpdate(t *testing.T) { validNewPodSecurityPolicy(), // updateFunc func(obj runtime.Object) runtime.Object { - object := obj.(*extensions.PodSecurityPolicy) + object := obj.(*policy.PodSecurityPolicy) object.Labels = map[string]string{"a": "b"} return object }, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/strategy.go new file mode 100644 index 000000000..668bafa33 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/strategy.go @@ -0,0 +1,72 @@ +/* +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 podsecuritypolicy + +import ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apiserver/pkg/registry/rest" + "k8s.io/apiserver/pkg/storage/names" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/policy" + "k8s.io/kubernetes/pkg/apis/policy/validation" +) + +// strategy implements behavior for PodSecurityPolicy objects +type strategy struct { + runtime.ObjectTyper + names.NameGenerator +} + +// Strategy is the default logic that applies when creating and updating PodSecurityPolicy +// objects via the REST API. +var Strategy = strategy{legacyscheme.Scheme, names.SimpleNameGenerator} + +var _ = rest.RESTCreateStrategy(Strategy) + +var _ = rest.RESTUpdateStrategy(Strategy) + +func (strategy) NamespaceScoped() bool { + return false +} + +func (strategy) AllowCreateOnUpdate() bool { + return false +} + +func (strategy) AllowUnconditionalUpdate() bool { + return true +} + +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { +} + +func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { +} + +func (strategy) Canonicalize(obj runtime.Object) { +} + +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { + return validation.ValidatePodSecurityPolicy(obj.(*policy.PodSecurityPolicy)) +} + +func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { + return validation.ValidatePodSecurityPolicyUpdate(old.(*policy.PodSecurityPolicy), obj.(*policy.PodSecurityPolicy)) +} diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/rest/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/policy/rest/BUILD index 904fd2078..bbbc32645 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/policy/rest/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/rest/BUILD @@ -12,8 +12,8 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/policy:go_default_library", - "//pkg/registry/extensions/podsecuritypolicy/storage:go_default_library", "//pkg/registry/policy/poddisruptionbudget/storage:go_default_library", + "//pkg/registry/policy/podsecuritypolicy/storage:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/policy/rest/storage_policy.go b/vendor/k8s.io/kubernetes/pkg/registry/policy/rest/storage_policy.go index 153686d76..a4ddb9591 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/policy/rest/storage_policy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/policy/rest/storage_policy.go @@ -24,20 +24,19 @@ import ( serverstorage "k8s.io/apiserver/pkg/server/storage" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/policy" - pspstore "k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage" poddisruptionbudgetstore "k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage" + pspstore "k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage" ) type RESTStorageProvider struct{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(policy.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(policy.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(policyapiv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[policyapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = policyapiv1beta1.SchemeGroupVersion } return apiGroupInfo, true } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/BUILD index 57fac87d9..c4fda28a5 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/BUILD @@ -16,12 +16,12 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/rbac/validation:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/BUILD index e58b32eac..77afcb6cf 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/BUILD @@ -16,7 +16,6 @@ go_library( "//pkg/registry/rbac/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/storage.go index 0b32fdebf..767673d25 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/storage.go @@ -18,11 +18,11 @@ limitations under the License. package policybased import ( + "context" "errors" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" kapihelper "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/apis/rbac" @@ -42,24 +42,28 @@ func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.Auth return &Storage{s, ruleResolver} } +func (r *Storage) NamespaceScoped() bool { + return false +} + var fullAuthority = []rbac.PolicyRule{ rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(), rbac.NewRule("*").URLs("*").RuleOrDie(), } -func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, createValidatingAdmission rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidatingAdmission rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { if rbacregistry.EscalationAllowed(ctx) { return s.StandardStorage.Create(ctx, obj, createValidatingAdmission, includeUninitialized) } clusterRole := obj.(*rbac.ClusterRole) rules := clusterRole.Rules - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, err) } // to set the aggregation rule, since it can gather anything, requires * on *.* if hasAggregationRule(clusterRole) { - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, fullAuthority); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, fullAuthority); err != nil { return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, errors.New("must have cluster-admin privileges to use the aggregationRule")) } } @@ -67,12 +71,12 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, crea return s.StandardStorage.Create(ctx, obj, createValidatingAdmission, includeUninitialized) } -func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { if rbacregistry.EscalationAllowed(ctx) { return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation) } - nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx genericapirequest.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { + nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { clusterRole := obj.(*rbac.ClusterRole) oldClusterRole := oldObj.(*rbac.ClusterRole) @@ -82,12 +86,12 @@ func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.Up } rules := clusterRole.Rules - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, err) } // to change the aggregation rule, since it can gather anything and prevent tightening, requires * on *.* if hasAggregationRule(clusterRole) || hasAggregationRule(oldClusterRole) { - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, fullAuthority); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, fullAuthority); err != nil { return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, errors.New("must have cluster-admin privileges to use the aggregationRule")) } } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/registry.go index b8b1a21b5..5fdc5024d 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/registry.go @@ -17,27 +17,24 @@ limitations under the License. package clusterrole import ( - metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" + "context" + + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) // Registry is an interface for things that know how to store ClusterRoles. type Registry interface { - ListClusterRoles(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleList, error) - CreateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc) error - UpdateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetClusterRole(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRole, error) - DeleteClusterRole(ctx genericapirequest.Context, name string) error - WatchClusterRoles(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.ClusterRole, error) } // storage puts strong typing around storage calls type storage struct { - rest.StandardStorage + rest.Getter } // NewRegistry returns a new Registry interface for the given Storage. Any mismatched @@ -46,40 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListClusterRoles(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleList, error) { - obj, err := s.List(ctx, options) +func (s *storage) GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.ClusterRole, error) { + obj, err := s.Get(ctx, name, options) if err != nil { return nil, err } - return obj.(*rbac.ClusterRoleList), nil -} - -func (s *storage) CreateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc) error { - _, err := s.Create(ctx, clusterRole, createValidation, false) - return err -} - -func (s *storage) UpdateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { - _, _, err := s.Update(ctx, clusterRole.Name, rest.DefaultUpdatedObjectInfo(clusterRole), createValidation, updateValidation) - return err -} - -func (s *storage) WatchClusterRoles(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { - return s.Watch(ctx, options) -} - -func (s *storage) GetClusterRole(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRole, error) { - obj, err := s.Get(ctx, name, options) - if err != nil { + ret := &rbacv1.ClusterRole{} + if err := rbacv1helpers.Convert_rbac_ClusterRole_To_v1_ClusterRole(obj.(*rbac.ClusterRole), ret, nil); err != nil { return nil, err } - return obj.(*rbac.ClusterRole), nil -} - -func (s *storage) DeleteClusterRole(ctx genericapirequest.Context, name string) error { - _, _, err := s.Delete(ctx, name, nil) - return err + return ret, nil } // AuthorizerAdapter adapts the registry to the authorizer interface @@ -87,6 +61,6 @@ type AuthorizerAdapter struct { Registry Registry } -func (a AuthorizerAdapter) GetClusterRole(name string) (*rbac.ClusterRole, error) { +func (a AuthorizerAdapter) GetClusterRole(name string) (*rbacv1.ClusterRole, error) { return a.Registry.GetClusterRole(genericapirequest.NewContext(), name, &metav1.GetOptions{}) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/strategy.go index e1be1f06c..eb5475793 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package clusterrole import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -55,12 +56,12 @@ func (strategy) AllowCreateOnUpdate() bool { // PrepareForCreate clears fields that are not allowed to be set by end users // on creation. -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { _ = obj.(*rbac.ClusterRole) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newClusterRole := obj.(*rbac.ClusterRole) oldClusterRole := old.(*rbac.ClusterRole) @@ -68,7 +69,7 @@ func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime } // Validate validates a new ClusterRole. Validation must check for a correct signature. -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { clusterRole := obj.(*rbac.ClusterRole) return validation.ValidateClusterRole(clusterRole) } @@ -79,7 +80,7 @@ func (strategy) Canonicalize(obj runtime.Object) { } // ValidateUpdate is the default update validation for an end user. -func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { newObj := obj.(*rbac.ClusterRole) errorList := validation.ValidateClusterRole(newObj) return append(errorList, validation.ValidateClusterRoleUpdate(newObj, old.(*rbac.ClusterRole))...) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/BUILD index 3f7f3015b..5b327e876 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/BUILD @@ -16,12 +16,12 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/rbac/validation:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/BUILD index 2141978ee..db396f2b7 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/BUILD @@ -12,13 +12,14 @@ go_library( deps = [ "//pkg/apis/core/helper:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac:go_default_library", "//pkg/registry/rbac/validation:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/storage.go index 12264dba4..0217fcc35 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/storage.go @@ -18,14 +18,17 @@ limitations under the License. package policybased import ( + "context" + + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/authorization/authorizer" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" kapihelper "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) @@ -44,7 +47,11 @@ func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleRe return &Storage{s, authorizer, ruleResolver} } -func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *Storage) NamespaceScoped() bool { + return false +} + +func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { if rbacregistry.EscalationAllowed(ctx) { return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } @@ -54,7 +61,12 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, crea return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } - rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone) + v1RoleRef := rbacv1.RoleRef{} + err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&clusterRoleBinding.RoleRef, &v1RoleRef, nil) + if err != nil { + return nil, err + } + rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, metav1.NamespaceNone) if err != nil { return nil, err } @@ -64,12 +76,12 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, crea return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } -func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { if rbacregistry.EscalationAllowed(ctx) { return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation) } - nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx genericapirequest.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { + nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { clusterRoleBinding := obj.(*rbac.ClusterRoleBinding) // if we're only mutating fields needed for the GC to eventually delete this obj, return @@ -83,7 +95,12 @@ func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.Up } // Otherwise, see if we already have all the permissions contained in the referenced clusterrole - rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone) + v1RoleRef := rbacv1.RoleRef{} + err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&clusterRoleBinding.RoleRef, &v1RoleRef, nil) + if err != nil { + return nil, err + } + rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, metav1.NamespaceNone) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/registry.go index 2a3524e6e..34f5b73a9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/registry.go @@ -17,27 +17,24 @@ limitations under the License. package clusterrolebinding import ( + "context" + + rbacv1 "k8s.io/api/rbac/v1" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) // Registry is an interface for things that know how to store ClusterRoleBindings. type Registry interface { - ListClusterRoleBindings(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleBindingList, error) - CreateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc) error - UpdateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetClusterRoleBinding(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRoleBinding, error) - DeleteClusterRoleBinding(ctx genericapirequest.Context, name string) error - WatchClusterRoleBindings(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.ClusterRoleBindingList, error) } // storage puts strong typing around storage calls type storage struct { - rest.StandardStorage + rest.Lister } // NewRegistry returns a new Registry interface for the given Storage. Any mismatched @@ -46,40 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListClusterRoleBindings(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleBindingList, error) { +func (s *storage) ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.ClusterRoleBindingList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err } - return obj.(*rbac.ClusterRoleBindingList), nil -} - -func (s *storage) CreateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc) error { - _, err := s.Create(ctx, clusterRoleBinding, createValidation, false) - return err -} - -func (s *storage) UpdateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { - _, _, err := s.Update(ctx, clusterRoleBinding.Name, rest.DefaultUpdatedObjectInfo(clusterRoleBinding), createValidation, updateValidation) - return err -} - -func (s *storage) WatchClusterRoleBindings(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { - return s.Watch(ctx, options) -} - -func (s *storage) GetClusterRoleBinding(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRoleBinding, error) { - obj, err := s.Get(ctx, name, options) - if err != nil { + ret := &rbacv1.ClusterRoleBindingList{} + if err := rbacv1helpers.Convert_rbac_ClusterRoleBindingList_To_v1_ClusterRoleBindingList(obj.(*rbac.ClusterRoleBindingList), ret, nil); err != nil { return nil, err } - return obj.(*rbac.ClusterRoleBinding), nil -} - -func (s *storage) DeleteClusterRoleBinding(ctx genericapirequest.Context, name string) error { - _, _, err := s.Delete(ctx, name, nil) - return err + return ret, nil } // AuthorizerAdapter adapts the registry to the authorizer interface @@ -87,13 +61,13 @@ type AuthorizerAdapter struct { Registry Registry } -func (a AuthorizerAdapter) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) { +func (a AuthorizerAdapter) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) { list, err := a.Registry.ListClusterRoleBindings(genericapirequest.NewContext(), &metainternalversion.ListOptions{}) if err != nil { return nil, err } - ret := []*rbac.ClusterRoleBinding{} + ret := []*rbacv1.ClusterRoleBinding{} for i := range list.Items { ret = append(ret, &list.Items[i]) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/strategy.go index 1b2e33772..e7be7a634 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package clusterrolebinding import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -55,12 +56,12 @@ func (strategy) AllowCreateOnUpdate() bool { // PrepareForCreate clears fields that are not allowed to be set by end users // on creation. -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { _ = obj.(*rbac.ClusterRoleBinding) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newClusterRoleBinding := obj.(*rbac.ClusterRoleBinding) oldClusterRoleBinding := old.(*rbac.ClusterRoleBinding) @@ -68,7 +69,7 @@ func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime } // Validate validates a new ClusterRoleBinding. Validation must check for a correct signature. -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { clusterRoleBinding := obj.(*rbac.ClusterRoleBinding) return validation.ValidateClusterRoleBinding(clusterRoleBinding) } @@ -79,7 +80,7 @@ func (strategy) Canonicalize(obj runtime.Object) { } // ValidateUpdate is the default update validation for an end user. -func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { newObj := obj.(*rbac.ClusterRoleBinding) errorList := validation.ValidateClusterRoleBinding(newObj) return append(errorList, validation.ValidateClusterRoleBindingUpdate(newObj, old.(*rbac.ClusterRoleBinding))...) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/escalation_check.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/escalation_check.go index 4ac1392fb..74d6aff7c 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/escalation_check.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/escalation_check.go @@ -17,6 +17,7 @@ limitations under the License. package rbac import ( + "context" "fmt" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -26,7 +27,7 @@ import ( "k8s.io/kubernetes/pkg/apis/rbac" ) -func EscalationAllowed(ctx genericapirequest.Context) bool { +func EscalationAllowed(ctx context.Context) bool { u, ok := genericapirequest.UserFrom(ctx) if !ok { return false @@ -44,7 +45,7 @@ func EscalationAllowed(ctx genericapirequest.Context) bool { } // BindingAuthorized returns true if the user associated with the context is explicitly authorized to bind the specified roleRef -func BindingAuthorized(ctx genericapirequest.Context, roleRef rbac.RoleRef, bindingNamespace string, a authorizer.Authorizer) bool { +func BindingAuthorized(ctx context.Context, roleRef rbac.RoleRef, bindingNamespace string, a authorizer.Authorizer) bool { if a == nil { return false } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/BUILD index 4b14eed1c..42ff2c210 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/BUILD @@ -15,7 +15,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core/helper:go_default_library", - "//pkg/apis/rbac:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", ], @@ -34,16 +34,16 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/registry/rbac/reconciliation", deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/apis/rbac:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/registry/rbac/validation:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/clusterrole_interfaces.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/clusterrole_interfaces.go index 419cc1df2..68dc97fd3 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/clusterrole_interfaces.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/clusterrole_interfaces.go @@ -17,17 +17,17 @@ limitations under the License. package reconciliation import ( + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/apis/rbac" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" ) // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RuleOwner // +k8s:deepcopy-gen:nonpointer-interfaces=true type ClusterRoleRuleOwner struct { - ClusterRole *rbac.ClusterRole + ClusterRole *rbacv1.ClusterRole } func (o ClusterRoleRuleOwner) GetObject() runtime.Object { @@ -58,24 +58,24 @@ func (o ClusterRoleRuleOwner) SetAnnotations(in map[string]string) { o.ClusterRole.Annotations = in } -func (o ClusterRoleRuleOwner) GetRules() []rbac.PolicyRule { +func (o ClusterRoleRuleOwner) GetRules() []rbacv1.PolicyRule { return o.ClusterRole.Rules } -func (o ClusterRoleRuleOwner) SetRules(in []rbac.PolicyRule) { +func (o ClusterRoleRuleOwner) SetRules(in []rbacv1.PolicyRule) { o.ClusterRole.Rules = in } -func (o ClusterRoleRuleOwner) GetAggregationRule() *rbac.AggregationRule { +func (o ClusterRoleRuleOwner) GetAggregationRule() *rbacv1.AggregationRule { return o.ClusterRole.AggregationRule } -func (o ClusterRoleRuleOwner) SetAggregationRule(in *rbac.AggregationRule) { +func (o ClusterRoleRuleOwner) SetAggregationRule(in *rbacv1.AggregationRule) { o.ClusterRole.AggregationRule = in } type ClusterRoleModifier struct { - Client internalversion.ClusterRoleInterface + Client rbacv1client.ClusterRoleInterface } func (c ClusterRoleModifier) Get(namespace, name string) (RuleOwner, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/clusterrolebinding_interfaces.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/clusterrolebinding_interfaces.go index aa07f107f..b669a5951 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/clusterrolebinding_interfaces.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/clusterrolebinding_interfaces.go @@ -17,18 +17,18 @@ limitations under the License. package reconciliation import ( + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/apis/rbac" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" ) // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RoleBinding // +k8s:deepcopy-gen:nonpointer-interfaces=true type ClusterRoleBindingAdapter struct { - ClusterRoleBinding *rbac.ClusterRoleBinding + ClusterRoleBinding *rbacv1.ClusterRoleBinding } func (o ClusterRoleBindingAdapter) GetObject() runtime.Object { @@ -63,20 +63,20 @@ func (o ClusterRoleBindingAdapter) SetAnnotations(in map[string]string) { o.ClusterRoleBinding.Annotations = in } -func (o ClusterRoleBindingAdapter) GetRoleRef() rbac.RoleRef { +func (o ClusterRoleBindingAdapter) GetRoleRef() rbacv1.RoleRef { return o.ClusterRoleBinding.RoleRef } -func (o ClusterRoleBindingAdapter) GetSubjects() []rbac.Subject { +func (o ClusterRoleBindingAdapter) GetSubjects() []rbacv1.Subject { return o.ClusterRoleBinding.Subjects } -func (o ClusterRoleBindingAdapter) SetSubjects(in []rbac.Subject) { +func (o ClusterRoleBindingAdapter) SetSubjects(in []rbacv1.Subject) { o.ClusterRoleBinding.Subjects = in } type ClusterRoleBindingClientAdapter struct { - Client internalversion.ClusterRoleBindingInterface + Client rbacv1client.ClusterRoleBindingInterface } func (c ClusterRoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_role.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_role.go index 1ab840c75..8197b9f75 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_role.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_role.go @@ -20,11 +20,11 @@ import ( "fmt" "reflect" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/registry/rbac/validation" ) @@ -51,10 +51,10 @@ type RuleOwner interface { SetLabels(map[string]string) GetAnnotations() map[string]string SetAnnotations(map[string]string) - GetRules() []rbac.PolicyRule - SetRules([]rbac.PolicyRule) - GetAggregationRule() *rbac.AggregationRule - SetAggregationRule(*rbac.AggregationRule) + GetRules() []rbacv1.PolicyRule + SetRules([]rbacv1.PolicyRule) + GetAggregationRule() *rbacv1.AggregationRule + SetAggregationRule(*rbacv1.AggregationRule) DeepCopyRuleOwner() RuleOwner } @@ -75,9 +75,9 @@ type ReconcileClusterRoleResult struct { Role RuleOwner // MissingRules contains expected rules that were missing from the currently persisted role - MissingRules []rbac.PolicyRule + MissingRules []rbacv1.PolicyRule // ExtraRules contains extra permissions the currently persisted role had - ExtraRules []rbac.PolicyRule + ExtraRules []rbacv1.PolicyRule // MissingAggregationRuleSelectors contains expected selectors that were missing from the currently persisted role MissingAggregationRuleSelectors []metav1.LabelSelector @@ -112,7 +112,7 @@ func (o *ReconcileRoleOptions) run(attempts int) (*ReconcileClusterRoleResult, e case errors.IsNotFound(err): aggregationRule := o.Role.GetAggregationRule() if aggregationRule == nil { - aggregationRule = &rbac.AggregationRule{} + aggregationRule = &rbacv1.AggregationRule{} } result = &ReconcileClusterRoleResult{ Role: o.Role, @@ -178,7 +178,7 @@ func (o *ReconcileRoleOptions) run(attempts int) (*ReconcileClusterRoleResult, e func computeReconciledRole(existing, expected RuleOwner, removeExtraPermissions bool) (*ReconcileClusterRoleResult, error) { result := &ReconcileClusterRoleResult{Operation: ReconcileNone} - result.Protected = (existing.GetAnnotations()[rbac.AutoUpdateAnnotationKey] == "false") + result.Protected = (existing.GetAnnotations()[rbacv1.AutoUpdateAnnotationKey] == "false") // Start with a copy of the existing object result.Role = existing.DeepCopyRuleOwner() @@ -223,7 +223,7 @@ func computeReconciledRole(existing, expected RuleOwner, removeExtraPermissions // add missing rules in the union case aggregationRule := result.Role.GetAggregationRule() if aggregationRule == nil { - aggregationRule = &rbac.AggregationRule{} + aggregationRule = &rbacv1.AggregationRule{} } aggregationRule.ClusterRoleSelectors = append(aggregationRule.ClusterRoleSelectors, result.MissingAggregationRuleSelectors...) result.Role.SetAggregationRule(aggregationRule) @@ -254,7 +254,7 @@ func merge(maps ...map[string]string) map[string]string { // aggregationRuleCovers determines whether or not the ownerSelectors cover the servantSelectors in terms of semantically // equal label selectors. // It returns whether or not the ownerSelectors cover and a list of the rules that the ownerSelectors do not cover. -func aggregationRuleCovers(ownerRule, servantRule *rbac.AggregationRule) (bool, []metav1.LabelSelector) { +func aggregationRuleCovers(ownerRule, servantRule *rbacv1.AggregationRule) (bool, []metav1.LabelSelector) { switch { case ownerRule == nil && servantRule == nil: return true, []metav1.LabelSelector{} diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_role_test.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_role_test.go index 6a7f632b4..be3712798 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_role_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_role_test.go @@ -19,23 +19,23 @@ package reconciliation import ( "testing" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/kubernetes/pkg/apis/core/helper" - "k8s.io/kubernetes/pkg/apis/rbac" ) -func role(rules []rbac.PolicyRule, labels map[string]string, annotations map[string]string) *rbac.ClusterRole { - return &rbac.ClusterRole{ +func role(rules []rbacv1.PolicyRule, labels map[string]string, annotations map[string]string) *rbacv1.ClusterRole { + return &rbacv1.ClusterRole{ Rules: rules, ObjectMeta: metav1.ObjectMeta{Labels: labels, Annotations: annotations}, } } -func rules(resources ...string) []rbac.PolicyRule { - r := []rbac.PolicyRule{} +func rules(resources ...string) []rbacv1.PolicyRule { + r := []rbacv1.PolicyRule{} for _, resource := range resources { - r = append(r, rbac.PolicyRule{APIGroups: []string{""}, Verbs: []string{"get"}, Resources: []string{resource}}) + r = append(r, rbacv1.PolicyRule{APIGroups: []string{""}, Verbs: []string{"get"}, Resources: []string{resource}}) } return r } @@ -44,11 +44,11 @@ type ss map[string]string func TestComputeReconciledRoleRules(t *testing.T) { tests := map[string]struct { - expectedRole *rbac.ClusterRole - actualRole *rbac.ClusterRole + expectedRole *rbacv1.ClusterRole + actualRole *rbacv1.ClusterRole removeExtraPermissions bool - expectedReconciledRole *rbac.ClusterRole + expectedReconciledRole *rbacv1.ClusterRole expectedReconciliationNeeded bool }{ "empty": { @@ -278,14 +278,14 @@ func TestComputeReconciledRoleRules(t *testing.T) { } } -func aggregatedRole(aggregationRule *rbac.AggregationRule) *rbac.ClusterRole { - return &rbac.ClusterRole{ +func aggregatedRole(aggregationRule *rbacv1.AggregationRule) *rbacv1.ClusterRole { + return &rbacv1.ClusterRole{ AggregationRule: aggregationRule, } } -func aggregationrule(selectors []map[string]string) *rbac.AggregationRule { - ret := &rbac.AggregationRule{} +func aggregationrule(selectors []map[string]string) *rbacv1.AggregationRule { + ret := &rbacv1.AggregationRule{} for _, selector := range selectors { ret.ClusterRoleSelectors = append(ret.ClusterRoleSelectors, metav1.LabelSelector{MatchLabels: selector}) @@ -295,15 +295,15 @@ func aggregationrule(selectors []map[string]string) *rbac.AggregationRule { func TestComputeReconciledRoleAggregationRules(t *testing.T) { tests := map[string]struct { - expectedRole *rbac.ClusterRole - actualRole *rbac.ClusterRole + expectedRole *rbacv1.ClusterRole + actualRole *rbacv1.ClusterRole removeExtraPermissions bool - expectedReconciledRole *rbac.ClusterRole + expectedReconciledRole *rbacv1.ClusterRole expectedReconciliationNeeded bool }{ "empty": { - expectedRole: aggregatedRole(&rbac.AggregationRule{}), + expectedRole: aggregatedRole(&rbacv1.AggregationRule{}), actualRole: aggregatedRole(nil), removeExtraPermissions: true, @@ -311,8 +311,8 @@ func TestComputeReconciledRoleAggregationRules(t *testing.T) { expectedReconciliationNeeded: false, }, "empty-2": { - expectedRole: aggregatedRole(&rbac.AggregationRule{}), - actualRole: aggregatedRole(&rbac.AggregationRule{}), + expectedRole: aggregatedRole(&rbacv1.AggregationRule{}), + actualRole: aggregatedRole(&rbacv1.AggregationRule{}), removeExtraPermissions: true, expectedReconciledRole: nil, @@ -365,7 +365,7 @@ func TestComputeReconciledRoleAggregationRules(t *testing.T) { // desired role is not aggregated expectedRole: role(rules("pods", "nodes", "secrets"), nil, nil), // existing role is aggregated and has other permissions - actualRole: func() *rbac.ClusterRole { + actualRole: func() *rbacv1.ClusterRole { r := aggregatedRole(aggregationrule([]map[string]string{{"alpha": "bravo"}})) r.Rules = rules("deployments") return r diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_rolebindings.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_rolebindings.go index ac138da58..65ca2bd1a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_rolebindings.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_rolebindings.go @@ -20,10 +20,10 @@ import ( "fmt" "reflect" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/apis/rbac" ) type RoleBindingModifier interface { @@ -42,9 +42,9 @@ type RoleBinding interface { SetLabels(map[string]string) GetAnnotations() map[string]string SetAnnotations(map[string]string) - GetRoleRef() rbac.RoleRef - GetSubjects() []rbac.Subject - SetSubjects([]rbac.Subject) + GetRoleRef() rbacv1.RoleRef + GetSubjects() []rbacv1.Subject + SetSubjects([]rbacv1.Subject) DeepCopyRoleBinding() RoleBinding } @@ -67,9 +67,9 @@ type ReconcileClusterRoleBindingResult struct { RoleBinding RoleBinding // MissingSubjects contains expected subjects that were missing from the currently persisted rolebinding - MissingSubjects []rbac.Subject + MissingSubjects []rbacv1.Subject // ExtraSubjects contains extra subjects the currently persisted rolebinding had - ExtraSubjects []rbac.Subject + ExtraSubjects []rbacv1.Subject // Operation is the API operation required to reconcile. // If no reconciliation was needed, it is set to ReconcileNone. @@ -176,7 +176,7 @@ func (o *ReconcileRoleBindingOptions) run(attempts int) (*ReconcileClusterRoleBi func computeReconciledRoleBinding(existing, expected RoleBinding, removeExtraSubjects bool) (*ReconcileClusterRoleBindingResult, error) { result := &ReconcileClusterRoleBindingResult{Operation: ReconcileNone} - result.Protected = (existing.GetAnnotations()[rbac.AutoUpdateAnnotationKey] == "false") + result.Protected = (existing.GetAnnotations()[rbacv1.AutoUpdateAnnotationKey] == "false") // Reset the binding completely if the roleRef is different if expected.GetRoleRef() != existing.GetRoleRef() { @@ -216,7 +216,7 @@ func computeReconciledRoleBinding(existing, expected RoleBinding, removeExtraSub return result, nil } -func contains(list []rbac.Subject, item rbac.Subject) bool { +func contains(list []rbacv1.Subject, item rbacv1.Subject) bool { for _, listItem := range list { if listItem == item { return true @@ -229,7 +229,7 @@ func contains(list []rbac.Subject, item rbac.Subject) bool { // list1Only = list1 - list2 // list2Only = list2 - list1 // if both returned lists are empty, the provided lists are equal -func diffSubjectLists(list1 []rbac.Subject, list2 []rbac.Subject) (list1Only []rbac.Subject, list2Only []rbac.Subject) { +func diffSubjectLists(list1 []rbacv1.Subject, list2 []rbacv1.Subject) (list1Only []rbacv1.Subject, list2Only []rbacv1.Subject) { for _, list1Item := range list1 { if !contains(list2, list1Item) { if !contains(list1Only, list1Item) { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_rolebindings_test.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_rolebindings_test.go index 0cdd3cf46..6abb09081 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_rolebindings_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/reconcile_rolebindings_test.go @@ -19,24 +19,24 @@ package reconciliation import ( "testing" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/kubernetes/pkg/apis/core/helper" - "k8s.io/kubernetes/pkg/apis/rbac" ) -func binding(roleRef rbac.RoleRef, subjects []rbac.Subject) *rbac.ClusterRoleBinding { - return &rbac.ClusterRoleBinding{RoleRef: roleRef, Subjects: subjects} +func binding(roleRef rbacv1.RoleRef, subjects []rbacv1.Subject) *rbacv1.ClusterRoleBinding { + return &rbacv1.ClusterRoleBinding{RoleRef: roleRef, Subjects: subjects} } -func ref(name string) rbac.RoleRef { - return rbac.RoleRef{Name: name} +func ref(name string) rbacv1.RoleRef { + return rbacv1.RoleRef{Name: name} } -func subject(name string) rbac.Subject { - return rbac.Subject{Name: name} +func subject(name string) rbacv1.Subject { + return rbacv1.Subject{Name: name} } -func subjects(names ...string) []rbac.Subject { - r := []rbac.Subject{} +func subjects(names ...string) []rbacv1.Subject { + r := []rbacv1.Subject{} for _, name := range names { r = append(r, subject(name)) } @@ -45,10 +45,10 @@ func subjects(names ...string) []rbac.Subject { func TestDiffObjectReferenceLists(t *testing.T) { tests := map[string]struct { - A []rbac.Subject - B []rbac.Subject - ExpectedOnlyA []rbac.Subject - ExpectedOnlyB []rbac.Subject + A []rbacv1.Subject + B []rbacv1.Subject + ExpectedOnlyA []rbacv1.Subject + ExpectedOnlyB []rbacv1.Subject }{ "empty": {}, @@ -92,11 +92,11 @@ func TestDiffObjectReferenceLists(t *testing.T) { func TestComputeUpdate(t *testing.T) { tests := map[string]struct { - ExpectedBinding *rbac.ClusterRoleBinding - ActualBinding *rbac.ClusterRoleBinding + ExpectedBinding *rbacv1.ClusterRoleBinding + ActualBinding *rbacv1.ClusterRoleBinding RemoveExtraSubjects bool - ExpectedUpdatedBinding *rbac.ClusterRoleBinding + ExpectedUpdatedBinding *rbacv1.ClusterRoleBinding ExpectedUpdateNeeded bool }{ "match without union": { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/role_interfaces.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/role_interfaces.go index b46e9e872..24cb7899d 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/role_interfaces.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/role_interfaces.go @@ -17,20 +17,20 @@ limitations under the License. package reconciliation import ( + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/rbac" - core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" ) // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RuleOwner // +k8s:deepcopy-gen:nonpointer-interfaces=true type RoleRuleOwner struct { - Role *rbac.Role + Role *rbacv1.Role } func (o RoleRuleOwner) GetObject() runtime.Object { @@ -61,24 +61,24 @@ func (o RoleRuleOwner) SetAnnotations(in map[string]string) { o.Role.Annotations = in } -func (o RoleRuleOwner) GetRules() []rbac.PolicyRule { +func (o RoleRuleOwner) GetRules() []rbacv1.PolicyRule { return o.Role.Rules } -func (o RoleRuleOwner) SetRules(in []rbac.PolicyRule) { +func (o RoleRuleOwner) SetRules(in []rbacv1.PolicyRule) { o.Role.Rules = in } -func (o RoleRuleOwner) GetAggregationRule() *rbac.AggregationRule { +func (o RoleRuleOwner) GetAggregationRule() *rbacv1.AggregationRule { return nil } -func (o RoleRuleOwner) SetAggregationRule(in *rbac.AggregationRule) { +func (o RoleRuleOwner) SetAggregationRule(in *rbacv1.AggregationRule) { } type RoleModifier struct { - Client internalversion.RolesGetter - NamespaceClient core.NamespaceInterface + Client rbacv1client.RolesGetter + NamespaceClient corev1client.NamespaceInterface } func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) { @@ -90,7 +90,7 @@ func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) { } func (c RoleModifier) Create(in RuleOwner) (RuleOwner, error) { - ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} + ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go index 126f479cb..23bf6b653 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go @@ -17,21 +17,21 @@ limitations under the License. package reconciliation import ( + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/rbac" - core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" ) // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RoleBinding // +k8s:deepcopy-gen:nonpointer-interfaces=true type RoleBindingAdapter struct { - RoleBinding *rbac.RoleBinding + RoleBinding *rbacv1.RoleBinding } func (o RoleBindingAdapter) GetObject() runtime.Object { @@ -66,21 +66,21 @@ func (o RoleBindingAdapter) SetAnnotations(in map[string]string) { o.RoleBinding.Annotations = in } -func (o RoleBindingAdapter) GetRoleRef() rbac.RoleRef { +func (o RoleBindingAdapter) GetRoleRef() rbacv1.RoleRef { return o.RoleBinding.RoleRef } -func (o RoleBindingAdapter) GetSubjects() []rbac.Subject { +func (o RoleBindingAdapter) GetSubjects() []rbacv1.Subject { return o.RoleBinding.Subjects } -func (o RoleBindingAdapter) SetSubjects(in []rbac.Subject) { +func (o RoleBindingAdapter) SetSubjects(in []rbacv1.Subject) { o.RoleBinding.Subjects = in } type RoleBindingClientAdapter struct { - Client internalversion.RoleBindingsGetter - NamespaceClient core.NamespaceInterface + Client rbacv1client.RoleBindingsGetter + NamespaceClient corev1client.NamespaceInterface } func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) { @@ -92,7 +92,7 @@ func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, erro } func (c RoleBindingClientAdapter) Create(in RoleBinding) (RoleBinding, error) { - ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} + ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/zz_generated.deepcopy.go index 8a1633296..411cfbd48 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/reconciliation/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,7 +21,7 @@ limitations under the License. package reconciliation import ( - rbac "k8s.io/kubernetes/pkg/apis/rbac" + v1 "k8s.io/api/rbac/v1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -32,7 +32,7 @@ func (in *ClusterRoleBindingAdapter) DeepCopyInto(out *ClusterRoleBindingAdapter if *in == nil { *out = nil } else { - *out = new(rbac.ClusterRoleBinding) + *out = new(v1.ClusterRoleBinding) (*in).DeepCopyInto(*out) } } @@ -62,7 +62,7 @@ func (in *ClusterRoleRuleOwner) DeepCopyInto(out *ClusterRoleRuleOwner) { if *in == nil { *out = nil } else { - *out = new(rbac.ClusterRole) + *out = new(v1.ClusterRole) (*in).DeepCopyInto(*out) } } @@ -92,7 +92,7 @@ func (in *RoleBindingAdapter) DeepCopyInto(out *RoleBindingAdapter) { if *in == nil { *out = nil } else { - *out = new(rbac.RoleBinding) + *out = new(v1.RoleBinding) (*in).DeepCopyInto(*out) } } @@ -122,7 +122,7 @@ func (in *RoleRuleOwner) DeepCopyInto(out *RoleRuleOwner) { if *in == nil { *out = nil } else { - *out = new(rbac.Role) + *out = new(v1.Role) (*in).DeepCopyInto(*out) } } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/BUILD index 685a8334b..0d84ad2f8 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/BUILD @@ -12,8 +12,6 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/registry/rbac/clusterrole:go_default_library", "//pkg/registry/rbac/clusterrole/policybased:go_default_library", "//pkg/registry/rbac/clusterrole/storage:go_default_library", @@ -43,6 +41,8 @@ go_library( "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", "//vendor/k8s.io/client-go/util/retry:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/storage_rbac.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/storage_rbac.go index bed2bc36b..53ace70eb 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/storage_rbac.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/storage_rbac.go @@ -35,11 +35,11 @@ import ( "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" serverstorage "k8s.io/apiserver/pkg/server/storage" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" "k8s.io/client-go/util/retry" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/rbac" - coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" clusterrolepolicybased "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased" clusterrolestore "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/storage" @@ -66,21 +66,18 @@ type RESTStorageProvider struct { var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(rbac.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(rbac.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(rbacapiv1alpha1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1alpha1.SchemeGroupVersion.Version] = p.storage(rbacapiv1alpha1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = rbacapiv1alpha1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(rbacapiv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1beta1.SchemeGroupVersion.Version] = p.storage(rbacapiv1beta1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = rbacapiv1beta1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(rbacapiv1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1.SchemeGroupVersion.Version] = p.storage(rbacapiv1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = rbacapiv1.SchemeGroupVersion } return apiGroupInfo, true @@ -127,10 +124,10 @@ func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStart } type PolicyData struct { - ClusterRoles []rbac.ClusterRole - ClusterRoleBindings []rbac.ClusterRoleBinding - Roles map[string][]rbac.Role - RoleBindings map[string][]rbac.RoleBinding + ClusterRoles []rbacapiv1.ClusterRole + ClusterRoleBindings []rbacapiv1.ClusterRoleBinding + Roles map[string][]rbacapiv1.Role + RoleBindings map[string][]rbacapiv1.RoleBinding // ClusterRolesToAggregate maps from previous clusterrole name to the new clusterrole name ClusterRolesToAggregate map[string]string } @@ -141,13 +138,13 @@ func (p *PolicyData) EnsureRBACPolicy() genericapiserver.PostStartHookFunc { // starts, the roles don't initialize, and nothing works. err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) { - coreclientset, err := coreclient.NewForConfig(hookContext.LoopbackClientConfig) + coreclientset, err := corev1client.NewForConfig(hookContext.LoopbackClientConfig) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err)) return false, nil } - clientset, err := rbacclient.NewForConfig(hookContext.LoopbackClientConfig) + clientset, err := rbacv1client.NewForConfig(hookContext.LoopbackClientConfig) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err)) return false, nil @@ -306,7 +303,7 @@ func (p RESTStorageProvider) GroupName() string { // primeAggregatedClusterRoles copies roles that have transitioned to aggregated roles and may need to pick up changes // that were done to the legacy roles. -func primeAggregatedClusterRoles(clusterRolesToAggregate map[string]string, clusterRoleClient rbacclient.ClusterRolesGetter) error { +func primeAggregatedClusterRoles(clusterRolesToAggregate map[string]string, clusterRoleClient rbacv1client.ClusterRolesGetter) error { for oldName, newName := range clusterRolesToAggregate { _, err := clusterRoleClient.ClusterRoles().Get(newName, metav1.GetOptions{}) if err == nil { diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/BUILD index a4fde9839..03c6f598e 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/BUILD @@ -16,12 +16,12 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/rbac/validation:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/BUILD index 65fa12025..0c1e56066 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/BUILD @@ -16,7 +16,6 @@ go_library( "//pkg/registry/rbac/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/storage.go index d67e3777f..447cd1178 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/storage.go @@ -18,9 +18,10 @@ limitations under the License. package policybased import ( + "context" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" kapihelper "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/apis/rbac" @@ -40,25 +41,29 @@ func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.Auth return &Storage{s, ruleResolver} } -func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *Storage) NamespaceScoped() bool { + return true +} + +func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { if rbacregistry.EscalationAllowed(ctx) { return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } role := obj.(*rbac.Role) rules := role.Rules - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { return nil, errors.NewForbidden(groupResource, role.Name, err) } return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } -func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { if rbacregistry.EscalationAllowed(ctx) { return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation) } - nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx genericapirequest.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { + nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { role := obj.(*rbac.Role) // if we're only mutating fields needed for the GC to eventually delete this obj, return @@ -67,7 +72,7 @@ func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.Up } rules := role.Rules - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { return nil, errors.NewForbidden(groupResource, role.Name, err) } return obj, nil diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/registry.go index bbf26b5e2..30626acf4 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/registry.go @@ -17,27 +17,24 @@ limitations under the License. package role import ( - metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" + "context" + + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) // Registry is an interface for things that know how to store Roles. type Registry interface { - ListRoles(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*rbac.RoleList, error) - CreateRole(ctx genericapirequest.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc) error - UpdateRole(ctx genericapirequest.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetRole(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.Role, error) - DeleteRole(ctx genericapirequest.Context, name string) error - WatchRoles(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.Role, error) } // storage puts strong typing around storage calls type storage struct { - rest.StandardStorage + rest.Getter } // NewRegistry returns a new Registry interface for the given Storage. Any mismatched @@ -46,41 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListRoles(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*rbac.RoleList, error) { - obj, err := s.List(ctx, options) +func (s *storage) GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.Role, error) { + obj, err := s.Get(ctx, name, options) if err != nil { return nil, err } - return obj.(*rbac.RoleList), nil -} - -func (s *storage) CreateRole(ctx genericapirequest.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc) error { - _, err := s.Create(ctx, role, createValidation, false) - return err -} - -func (s *storage) UpdateRole(ctx genericapirequest.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { - // TODO: any admission? - _, _, err := s.Update(ctx, role.Name, rest.DefaultUpdatedObjectInfo(role), createValidation, updateValidation) - return err -} - -func (s *storage) WatchRoles(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { - return s.Watch(ctx, options) -} - -func (s *storage) GetRole(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.Role, error) { - obj, err := s.Get(ctx, name, options) - if err != nil { + ret := &rbacv1.Role{} + if err := rbacv1helpers.Convert_rbac_Role_To_v1_Role(obj.(*rbac.Role), ret, nil); err != nil { return nil, err } - return obj.(*rbac.Role), nil -} - -func (s *storage) DeleteRole(ctx genericapirequest.Context, name string) error { - _, _, err := s.Delete(ctx, name, nil) - return err + return ret, nil } // AuthorizerAdapter adapts the registry to the authorizer interface @@ -88,6 +61,6 @@ type AuthorizerAdapter struct { Registry Registry } -func (a AuthorizerAdapter) GetRole(namespace, name string) (*rbac.Role, error) { +func (a AuthorizerAdapter) GetRole(namespace, name string) (*rbacv1.Role, error) { return a.Registry.GetRole(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), name, &metav1.GetOptions{}) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/strategy.go index b815f98db..b6358b3bf 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/role/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package role import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -55,12 +56,12 @@ func (strategy) AllowCreateOnUpdate() bool { // PrepareForCreate clears fields that are not allowed to be set by end users // on creation. -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { _ = obj.(*rbac.Role) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newRole := obj.(*rbac.Role) oldRole := old.(*rbac.Role) @@ -68,7 +69,7 @@ func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime } // Validate validates a new Role. Validation must check for a correct signature. -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { role := obj.(*rbac.Role) return validation.ValidateRole(role) } @@ -79,7 +80,7 @@ func (strategy) Canonicalize(obj runtime.Object) { } // ValidateUpdate is the default update validation for an end user. -func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { newObj := obj.(*rbac.Role) errorList := validation.ValidateRole(newObj) return append(errorList, validation.ValidateRoleUpdate(newObj, old.(*rbac.Role))...) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/BUILD index e30725311..63ad28699 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/BUILD @@ -16,12 +16,12 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/rbac/validation:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/BUILD index fd05f21b4..eaca04543 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/BUILD @@ -12,8 +12,10 @@ go_library( deps = [ "//pkg/apis/core/helper:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac:go_default_library", "//pkg/registry/rbac/validation:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/storage.go index 9e539a77a..b71821c0c 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/storage.go @@ -18,6 +18,9 @@ limitations under the License. package policybased import ( + "context" + + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/authorization/authorizer" @@ -25,6 +28,7 @@ import ( "k8s.io/apiserver/pkg/registry/rest" kapihelper "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) @@ -43,7 +47,11 @@ func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleRe return &Storage{s, authorizer, ruleResolver} } -func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (r *Storage) NamespaceScoped() bool { + return true +} + +func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { if rbacregistry.EscalationAllowed(ctx) { return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } @@ -60,7 +68,12 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, crea return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } - rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace) + v1RoleRef := rbacv1.RoleRef{} + err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&roleBinding.RoleRef, &v1RoleRef, nil) + if err != nil { + return nil, err + } + rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, namespace) if err != nil { return nil, err } @@ -70,12 +83,12 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, crea return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } -func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { if rbacregistry.EscalationAllowed(ctx) { return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation) } - nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx genericapirequest.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { + nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { // Get the namespace from the context (populated from the URL). // The namespace in the object can be empty until StandardStorage.Update()->BeforeUpdate() populates it from the context. namespace, ok := genericapirequest.NamespaceFrom(ctx) @@ -96,7 +109,12 @@ func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.Up } // Otherwise, see if we already have all the permissions contained in the referenced role - rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace) + v1RoleRef := rbacv1.RoleRef{} + err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&roleBinding.RoleRef, &v1RoleRef, nil) + if err != nil { + return nil, err + } + rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, namespace) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/registry.go index c708d088b..af78c1a49 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/registry.go @@ -17,27 +17,24 @@ limitations under the License. package rolebinding import ( + "context" + + rbacv1 "k8s.io/api/rbac/v1" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) // Registry is an interface for things that know how to store RoleBindings. type Registry interface { - ListRoleBindings(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*rbac.RoleBindingList, error) - CreateRoleBinding(ctx genericapirequest.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc) error - UpdateRoleBinding(ctx genericapirequest.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetRoleBinding(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.RoleBinding, error) - DeleteRoleBinding(ctx genericapirequest.Context, name string) error - WatchRoleBindings(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.RoleBindingList, error) } // storage puts strong typing around storage calls type storage struct { - rest.StandardStorage + rest.Lister } // NewRegistry returns a new Registry interface for the given Storage. Any mismatched @@ -46,41 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListRoleBindings(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*rbac.RoleBindingList, error) { +func (s *storage) ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.RoleBindingList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err } - return obj.(*rbac.RoleBindingList), nil -} - -func (s *storage) CreateRoleBinding(ctx genericapirequest.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc) error { - // TODO(ericchiang): add additional validation - _, err := s.Create(ctx, roleBinding, createValidation, false) - return err -} - -func (s *storage) UpdateRoleBinding(ctx genericapirequest.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { - _, _, err := s.Update(ctx, roleBinding.Name, rest.DefaultUpdatedObjectInfo(roleBinding), createValidation, updateValidation) - return err -} - -func (s *storage) WatchRoleBindings(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { - return s.Watch(ctx, options) -} - -func (s *storage) GetRoleBinding(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.RoleBinding, error) { - obj, err := s.Get(ctx, name, options) - if err != nil { + ret := &rbacv1.RoleBindingList{} + if err := rbacv1helpers.Convert_rbac_RoleBindingList_To_v1_RoleBindingList(obj.(*rbac.RoleBindingList), ret, nil); err != nil { return nil, err } - return obj.(*rbac.RoleBinding), nil -} - -func (s *storage) DeleteRoleBinding(ctx genericapirequest.Context, name string) error { - _, _, err := s.Delete(ctx, name, nil) - return err + return ret, nil } // AuthorizerAdapter adapts the registry to the authorizer interface @@ -88,13 +61,13 @@ type AuthorizerAdapter struct { Registry Registry } -func (a AuthorizerAdapter) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { +func (a AuthorizerAdapter) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) { list, err := a.Registry.ListRoleBindings(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), &metainternalversion.ListOptions{}) if err != nil { return nil, err } - ret := []*rbac.RoleBinding{} + ret := []*rbacv1.RoleBinding{} for i := range list.Items { ret = append(ret, &list.Items[i]) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/strategy.go index 136cffd34..2715b2353 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package rolebinding import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -55,12 +56,12 @@ func (strategy) AllowCreateOnUpdate() bool { // PrepareForCreate clears fields that are not allowed to be set by end users // on creation. -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { _ = obj.(*rbac.RoleBinding) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newRoleBinding := obj.(*rbac.RoleBinding) oldRoleBinding := old.(*rbac.RoleBinding) @@ -68,7 +69,7 @@ func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime } // Validate validates a new RoleBinding. Validation must check for a correct signature. -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { roleBinding := obj.(*rbac.RoleBinding) return validation.ValidateRoleBinding(roleBinding) } @@ -79,7 +80,7 @@ func (strategy) Canonicalize(obj runtime.Object) { } // ValidateUpdate is the default update validation for an end user. -func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { newObj := obj.(*rbac.RoleBinding) errorList := validation.ValidateRoleBinding(newObj) return append(errorList, validation.ValidateRoleBindingUpdate(newObj, old.(*rbac.RoleBinding))...) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/BUILD index ddfb6431f..152ae0387 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/BUILD @@ -15,7 +15,8 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", @@ -25,6 +26,7 @@ go_test( go_library( name = "go_default_library", srcs = [ + "internal_version_adapter.go", "policy_compact.go", "policy_comparator.go", "rule.go", @@ -32,7 +34,9 @@ go_library( importpath = "k8s.io/kubernetes/pkg/registry/rbac/validation", deps = [ "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/internal_version_adapter.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/internal_version_adapter.go new file mode 100644 index 000000000..bfb57242d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/internal_version_adapter.go @@ -0,0 +1,39 @@ +/* +Copyright 2018 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 validation + +import ( + "context" + + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" +) + +func ConfirmNoEscalationInternal(ctx context.Context, ruleResolver AuthorizationRuleResolver, inRules []rbac.PolicyRule) error { + rules := []rbacv1.PolicyRule{} + for i := range inRules { + v1Rule := rbacv1.PolicyRule{} + err := rbacv1helpers.Convert_rbac_PolicyRule_To_v1_PolicyRule(&inRules[i], &v1Rule, nil) + if err != nil { + return err + } + rules = append(rules, v1Rule) + } + + return ConfirmNoEscalation(ctx, ruleResolver, rules) +} diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_compact.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_compact.go index 303bbc7a0..182657b1c 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_compact.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_compact.go @@ -19,7 +19,7 @@ package validation import ( "reflect" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1 "k8s.io/api/rbac/v1" ) type simpleResource struct { @@ -31,10 +31,10 @@ type simpleResource struct { // CompactRules combines rules that contain a single APIGroup/Resource, differ only by verb, and contain no other attributes. // this is a fast check, and works well with the decomposed "missing rules" list from a Covers check. -func CompactRules(rules []rbac.PolicyRule) ([]rbac.PolicyRule, error) { - compacted := make([]rbac.PolicyRule, 0, len(rules)) +func CompactRules(rules []rbacv1.PolicyRule) ([]rbacv1.PolicyRule, error) { + compacted := make([]rbacv1.PolicyRule, 0, len(rules)) - simpleRules := map[simpleResource]*rbac.PolicyRule{} + simpleRules := map[simpleResource]*rbacv1.PolicyRule{} for _, rule := range rules { if resource, isSimple := isSimpleResourceRule(&rule); isSimple { if existingRule, ok := simpleRules[resource]; ok { @@ -61,7 +61,7 @@ func CompactRules(rules []rbac.PolicyRule) ([]rbac.PolicyRule, error) { } // isSimpleResourceRule returns true if the given rule contains verbs, a single resource, a single API group, at most one Resource Name, and no other values -func isSimpleResourceRule(rule *rbac.PolicyRule) (simpleResource, bool) { +func isSimpleResourceRule(rule *rbacv1.PolicyRule) (simpleResource, bool) { resource := simpleResource{} // If we have "complex" rule attributes, return early without allocations or expensive comparisons @@ -74,7 +74,7 @@ func isSimpleResourceRule(rule *rbac.PolicyRule) (simpleResource, bool) { } // Test if this rule only contains APIGroups/Resources/Verbs/ResourceNames - simpleRule := &rbac.PolicyRule{APIGroups: rule.APIGroups, Resources: rule.Resources, Verbs: rule.Verbs, ResourceNames: rule.ResourceNames} + simpleRule := &rbacv1.PolicyRule{APIGroups: rule.APIGroups, Resources: rule.Resources, Verbs: rule.Verbs, ResourceNames: rule.ResourceNames} if !reflect.DeepEqual(simpleRule, rule) { return resource, false } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_compact_test.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_compact_test.go index 214926132..4444657be 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_compact_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_compact_test.go @@ -21,20 +21,21 @@ import ( "sort" "testing" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1 "k8s.io/api/rbac/v1" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) func TestCompactRules(t *testing.T) { testcases := map[string]struct { - Rules []rbac.PolicyRule - Expected []rbac.PolicyRule + Rules []rbacv1.PolicyRule + Expected []rbacv1.PolicyRule }{ "empty": { - Rules: []rbac.PolicyRule{}, - Expected: []rbac.PolicyRule{}, + Rules: []rbacv1.PolicyRule{}, + Expected: []rbacv1.PolicyRule{}, }, "simple": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}}, {Verbs: []string{"update", "patch"}, APIGroups: []string{""}, Resources: []string{"builds"}}, @@ -55,7 +56,7 @@ func TestCompactRules(t *testing.T) { {Verbs: nil, APIGroups: []string{""}, Resources: []string{"pods"}}, {Verbs: []string{"create"}, APIGroups: []string{""}, Resources: []string{"pods"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"create", "delete"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}}, {Verbs: []string{"patch"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{""}}, {Verbs: []string{"get", "list"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{"foo"}}, @@ -66,44 +67,44 @@ func TestCompactRules(t *testing.T) { }, }, "complex multi-group": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}}, {Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}}, {Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}}, }, }, "complex multi-resource": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, }, }, "complex named-resource": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}}, }, }, "complex non-resource": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}}, {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}}, {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}}, }, @@ -112,7 +113,7 @@ func TestCompactRules(t *testing.T) { for k, tc := range testcases { rules := tc.Rules - originalRules := make([]rbac.PolicyRule, len(tc.Rules)) + originalRules := make([]rbacv1.PolicyRule, len(tc.Rules)) for i := range tc.Rules { originalRules[i] = *tc.Rules[i].DeepCopy() } @@ -134,8 +135,8 @@ func TestCompactRules(t *testing.T) { continue } - sort.Stable(rbac.SortableRuleSlice(compacted)) - sort.Stable(rbac.SortableRuleSlice(tc.Expected)) + sort.Stable(rbacv1helpers.SortableRuleSlice(compacted)) + sort.Stable(rbacv1helpers.SortableRuleSlice(tc.Expected)) if !reflect.DeepEqual(compacted, tc.Expected) { t.Errorf("%s: Expected\n%#v\ngot\n%#v", k, tc.Expected, compacted) continue @@ -145,68 +146,68 @@ func TestCompactRules(t *testing.T) { func TestIsSimpleResourceRule(t *testing.T) { testcases := map[string]struct { - Rule rbac.PolicyRule + Rule rbacv1.PolicyRule Simple bool Resource simpleResource }{ "simple, no verbs": { - Rule: rbac.PolicyRule{Verbs: []string{}, APIGroups: []string{""}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{}, APIGroups: []string{""}, Resources: []string{"builds"}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds"}, }, "simple, one verb": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds"}, }, "simple, one empty resource name": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{""}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{""}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: ""}, }, "simple, one resource name": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo"}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: "foo"}, }, "simple, multi verb": { - Rule: rbac.PolicyRule{Verbs: []string{"get", "list"}, APIGroups: []string{""}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get", "list"}, APIGroups: []string{""}, Resources: []string{"builds"}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds"}, }, "complex, empty": { - Rule: rbac.PolicyRule{}, + Rule: rbacv1.PolicyRule{}, Simple: false, Resource: simpleResource{}, }, "complex, no group": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{}, Resources: []string{"builds"}}, Simple: false, Resource: simpleResource{}, }, "complex, multi group": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{"a", "b"}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{"a", "b"}, Resources: []string{"builds"}}, Simple: false, Resource: simpleResource{}, }, "complex, no resource": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{}}, Simple: false, Resource: simpleResource{}, }, "complex, multi resource": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, Simple: false, Resource: simpleResource{}, }, "complex, resource names": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo", "bar"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo", "bar"}}, Simple: false, Resource: simpleResource{}, }, "complex, non-resource urls": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}}, Simple: false, Resource: simpleResource{}, }, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator.go index 4b2ba5158..7a0268b5e 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator.go @@ -19,23 +19,23 @@ package validation import ( "strings" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1 "k8s.io/api/rbac/v1" ) // Covers determines whether or not the ownerRules cover the servantRules in terms of allowed actions. // It returns whether or not the ownerRules cover and a list of the rules that the ownerRules do not cover. -func Covers(ownerRules, servantRules []rbac.PolicyRule) (bool, []rbac.PolicyRule) { +func Covers(ownerRules, servantRules []rbacv1.PolicyRule) (bool, []rbacv1.PolicyRule) { // 1. Break every servantRule into individual rule tuples: group, verb, resource, resourceName // 2. Compare the mini-rules against each owner rule. Because the breakdown is down to the most atomic level, we're guaranteed that each mini-servant rule will be either fully covered or not covered by a single owner rule // 3. Any left over mini-rules means that we are not covered and we have a nice list of them. // TODO: it might be nice to collapse the list down into something more human readable - subrules := []rbac.PolicyRule{} + subrules := []rbacv1.PolicyRule{} for _, servantRule := range servantRules { subrules = append(subrules, BreakdownRule(servantRule)...) } - uncoveredRules := []rbac.PolicyRule{} + uncoveredRules := []rbacv1.PolicyRule{} for _, subrule := range subrules { covered := false for _, ownerRule := range ownerRules { @@ -55,18 +55,18 @@ func Covers(ownerRules, servantRules []rbac.PolicyRule) (bool, []rbac.PolicyRule // BreadownRule takes a rule and builds an equivalent list of rules that each have at most one verb, one // resource, and one resource name -func BreakdownRule(rule rbac.PolicyRule) []rbac.PolicyRule { - subrules := []rbac.PolicyRule{} +func BreakdownRule(rule rbacv1.PolicyRule) []rbacv1.PolicyRule { + subrules := []rbacv1.PolicyRule{} for _, group := range rule.APIGroups { for _, resource := range rule.Resources { for _, verb := range rule.Verbs { if len(rule.ResourceNames) > 0 { for _, resourceName := range rule.ResourceNames { - subrules = append(subrules, rbac.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}, ResourceNames: []string{resourceName}}) + subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}, ResourceNames: []string{resourceName}}) } } else { - subrules = append(subrules, rbac.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}}) + subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}}) } } @@ -76,7 +76,7 @@ func BreakdownRule(rule rbac.PolicyRule) []rbac.PolicyRule { // Non-resource URLs are unique because they only combine with verbs. for _, nonResourceURL := range rule.NonResourceURLs { for _, verb := range rule.Verbs { - subrules = append(subrules, rbac.PolicyRule{NonResourceURLs: []string{nonResourceURL}, Verbs: []string{verb}}) + subrules = append(subrules, rbacv1.PolicyRule{NonResourceURLs: []string{nonResourceURL}, Verbs: []string{verb}}) } } @@ -107,7 +107,7 @@ func hasAll(set, contains []string) bool { func resourceCoversAll(setResources, coversResources []string) bool { // if we have a star or an exact match on all resources, then we match - if has(setResources, rbac.ResourceAll) || hasAll(setResources, coversResources) { + if has(setResources, rbacv1.ResourceAll) || hasAll(setResources, coversResources) { return true } @@ -155,9 +155,9 @@ func nonResourceURLCovers(ownerPath, subPath string) bool { // ruleCovers determines whether the ownerRule (which may have multiple verbs, resources, and resourceNames) covers // the subrule (which may only contain at most one verb, resource, and resourceName) -func ruleCovers(ownerRule, subRule rbac.PolicyRule) bool { - verbMatches := has(ownerRule.Verbs, rbac.VerbAll) || hasAll(ownerRule.Verbs, subRule.Verbs) - groupMatches := has(ownerRule.APIGroups, rbac.APIGroupAll) || hasAll(ownerRule.APIGroups, subRule.APIGroups) +func ruleCovers(ownerRule, subRule rbacv1.PolicyRule) bool { + verbMatches := has(ownerRule.Verbs, rbacv1.VerbAll) || hasAll(ownerRule.Verbs, subRule.Verbs) + groupMatches := has(ownerRule.APIGroups, rbacv1.APIGroupAll) || hasAll(ownerRule.APIGroups, subRule.APIGroups) resourceMatches := resourceCoversAll(ownerRule.Resources, subRule.Resources) nonResourceURLMatches := nonResourceURLsCoversAll(ownerRule.NonResourceURLs, subRule.NonResourceURLs) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator_test.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator_test.go index b8b947f72..e983c2abc 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator_test.go @@ -20,65 +20,65 @@ import ( "reflect" "testing" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1 "k8s.io/api/rbac/v1" ) type escalationTest struct { - ownerRules []rbac.PolicyRule - servantRules []rbac.PolicyRule + ownerRules []rbacv1.PolicyRule + servantRules []rbacv1.PolicyRule expectedCovered bool - expectedUncoveredRules []rbac.PolicyRule + expectedUncoveredRules []rbacv1.PolicyRule } func TestCoversExactMatch(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversSubresourceWildcard(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*/scale"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"foo/scale"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversMultipleRulesCoveringSingleRule(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}}, {APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}}, {APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversMultipleAPIGroupsCoveringSingleRule(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}}, {APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}}, {APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}}, @@ -86,22 +86,22 @@ func TestCoversMultipleAPIGroupsCoveringSingleRule(t *testing.T) { {APIGroups: []string{"group2"}, Verbs: []string{"delete"}, Resources: []string{"builds"}}, {APIGroups: []string{"group2"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversSingleAPIGroupsCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}}, {APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}}, {APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}}, @@ -111,23 +111,23 @@ func TestCoversSingleAPIGroupsCoveringMultiple(t *testing.T) { }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversMultipleRulesMissingSingleVerbResourceCombination(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}}, {APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"pods"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments", "pods"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"pods"}}, }, }.test(t) @@ -135,29 +135,29 @@ func TestCoversMultipleRulesMissingSingleVerbResourceCombination(t *testing.T) { func TestCoversAPIGroupStarCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1", "group2"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversEnumerationNotCoveringAPIGroupStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"dummy-group"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, }.test(t) @@ -165,43 +165,43 @@ func TestCoversEnumerationNotCoveringAPIGroupStar(t *testing.T) { func TestCoversAPIGroupStarCoveringStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversVerbStarCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"watch", "list"}, Resources: []string{"roles"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversEnumerationNotCoveringVerbStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get", "list", "watch", "create", "update", "delete", "exec"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, }.test(t) @@ -209,43 +209,43 @@ func TestCoversEnumerationNotCoveringVerbStar(t *testing.T) { func TestCoversVerbStarCoveringStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversResourceStarCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"resourcegroup:deployments"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversEnumerationNotCoveringResourceStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"roles", "resourcegroup:deployments"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, }.test(t) @@ -253,43 +253,43 @@ func TestCoversEnumerationNotCoveringResourceStar(t *testing.T) { func TestCoversResourceStarCoveringStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversResourceNameEmptyCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversEnumerationNotCoveringResourceNameEmpty(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}}, }, }.test(t) @@ -297,43 +297,43 @@ func TestCoversEnumerationNotCoveringResourceNameEmpty(t *testing.T) { func TestCoversNonResourceURLs(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversNonResourceURLsStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"*"}, Verbs: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis", "/apis/v1", "/"}, Verbs: []string{"*"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversNonResourceURLsStarAfterPrefixDoesntCover(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis", "/apis/v1"}, Verbs: []string{"get"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}}, }, }.test(t) @@ -341,43 +341,43 @@ func TestCoversNonResourceURLsStarAfterPrefixDoesntCover(t *testing.T) { func TestCoversNonResourceURLsStarAfterPrefix(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis/v1/foo", "/apis/v1"}, Verbs: []string{"get"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversNonResourceURLsWithOtherFields(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversNonResourceURLsWithOtherFieldsFailure(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}}}, + expectedUncoveredRules: []rbacv1.PolicyRule{{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}}}, }.test(t) } @@ -393,7 +393,7 @@ func (test escalationTest) test(t *testing.T) { } } -func rulesMatch(expectedRules, actualRules []rbac.PolicyRule) bool { +func rulesMatch(expectedRules, actualRules []rbacv1.PolicyRule) bool { if len(expectedRules) != len(actualRules) { return false } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule.go index e80382e6d..366a9a97b 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule.go @@ -17,36 +17,37 @@ limitations under the License. package validation import ( + "context" "errors" "fmt" "github.com/golang/glog" + rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/apiserver/pkg/authentication/user" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/kubernetes/pkg/apis/rbac" ) type AuthorizationRuleResolver interface { // GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namepsace // of the role binding, the empty string if a cluster role binding. - GetRoleReferenceRules(roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error) + GetRoleReferenceRules(roleRef rbacv1.RoleRef, namespace string) ([]rbacv1.PolicyRule, error) // RulesFor returns the list of rules that apply to a given user in a given namespace and error. If an error is returned, the slice of // PolicyRules may not be complete, but it contains all retrievable rules. This is done because policy rules are purely additive and policy determinations // can be made on the basis of those rules that are found. - RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error) + RulesFor(user user.Info, namespace string) ([]rbacv1.PolicyRule, error) // VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace, and each error encountered resolving those rules. // If visitor() returns false, visiting is short-circuited. - VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool) + VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool) } // ConfirmNoEscalation determines if the roles for a given user in a given namespace encompass the provided role. -func ConfirmNoEscalation(ctx genericapirequest.Context, ruleResolver AuthorizationRuleResolver, rules []rbac.PolicyRule) error { +func ConfirmNoEscalation(ctx context.Context, ruleResolver AuthorizationRuleResolver, rules []rbacv1.PolicyRule) error { ruleResolutionErrors := []error{} user, ok := genericapirequest.UserFrom(ctx) @@ -81,33 +82,33 @@ func NewDefaultRuleResolver(roleGetter RoleGetter, roleBindingLister RoleBinding } type RoleGetter interface { - GetRole(namespace, name string) (*rbac.Role, error) + GetRole(namespace, name string) (*rbacv1.Role, error) } type RoleBindingLister interface { - ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) + ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) } type ClusterRoleGetter interface { - GetClusterRole(name string) (*rbac.ClusterRole, error) + GetClusterRole(name string) (*rbacv1.ClusterRole, error) } type ClusterRoleBindingLister interface { - ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) + ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) } -func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error) { +func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbacv1.PolicyRule, error) { visitor := &ruleAccumulator{} r.VisitRulesFor(user, namespace, visitor.visit) return visitor.rules, utilerrors.NewAggregate(visitor.errors) } type ruleAccumulator struct { - rules []rbac.PolicyRule + rules []rbacv1.PolicyRule errors []error } -func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool { +func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool { if rule != nil { r.rules = append(r.rules, *rule) } @@ -117,9 +118,9 @@ func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbac.PolicyRule, err return true } -func describeSubject(s *rbac.Subject, bindingNamespace string) string { +func describeSubject(s *rbacv1.Subject, bindingNamespace string) string { switch s.Kind { - case rbac.ServiceAccountKind: + case rbacv1.ServiceAccountKind: if len(s.Namespace) > 0 { return fmt.Sprintf("%s %q", s.Kind, s.Name+"/"+s.Namespace) } @@ -130,8 +131,8 @@ func describeSubject(s *rbac.Subject, bindingNamespace string) string { } type clusterRoleBindingDescriber struct { - binding *rbac.ClusterRoleBinding - subject *rbac.Subject + binding *rbacv1.ClusterRoleBinding + subject *rbacv1.Subject } func (d *clusterRoleBindingDescriber) String() string { @@ -144,8 +145,8 @@ func (d *clusterRoleBindingDescriber) String() string { } type roleBindingDescriber struct { - binding *rbac.RoleBinding - subject *rbac.Subject + binding *rbacv1.RoleBinding + subject *rbacv1.Subject } func (d *roleBindingDescriber) String() string { @@ -157,7 +158,7 @@ func (d *roleBindingDescriber) String() string { ) } -func (r *DefaultRuleResolver) VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool) { +func (r *DefaultRuleResolver) VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool) { if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(); err != nil { if !visitor(nil, nil, err) { return @@ -218,16 +219,16 @@ func (r *DefaultRuleResolver) VisitRulesFor(user user.Info, namespace string, vi } // GetRoleReferenceRules attempts to resolve the RoleBinding or ClusterRoleBinding. -func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbac.RoleRef, bindingNamespace string) ([]rbac.PolicyRule, error) { - switch kind := rbac.RoleRefGroupKind(roleRef); kind { - case rbac.Kind("Role"): +func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbacv1.RoleRef, bindingNamespace string) ([]rbacv1.PolicyRule, error) { + switch roleRef.Kind { + case "Role": role, err := r.roleGetter.GetRole(bindingNamespace, roleRef.Name) if err != nil { return nil, err } return role.Rules, nil - case rbac.Kind("ClusterRole"): + case "ClusterRole": clusterRole, err := r.clusterRoleGetter.GetClusterRole(roleRef.Name) if err != nil { return nil, err @@ -235,13 +236,13 @@ func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbac.RoleRef, bindin return clusterRole.Rules, nil default: - return nil, fmt.Errorf("unsupported role reference kind: %q", kind) + return nil, fmt.Errorf("unsupported role reference kind: %q", roleRef.Kind) } } // appliesTo returns whether any of the bindingSubjects applies to the specified subject, // and if true, the index of the first subject that applies -func appliesTo(user user.Info, bindingSubjects []rbac.Subject, namespace string) (int, bool) { +func appliesTo(user user.Info, bindingSubjects []rbacv1.Subject, namespace string) (int, bool) { for i, bindingSubject := range bindingSubjects { if appliesToUser(user, bindingSubject, namespace) { return i, true @@ -250,15 +251,15 @@ func appliesTo(user user.Info, bindingSubjects []rbac.Subject, namespace string) return 0, false } -func appliesToUser(user user.Info, subject rbac.Subject, namespace string) bool { +func appliesToUser(user user.Info, subject rbacv1.Subject, namespace string) bool { switch subject.Kind { - case rbac.UserKind: + case rbacv1.UserKind: return user.GetName() == subject.Name - case rbac.GroupKind: + case rbacv1.GroupKind: return has(user.GetGroups(), subject.Name) - case rbac.ServiceAccountKind: + case rbacv1.ServiceAccountKind: // default the namespace to namespace we're working in if its available. This allows rolebindings that reference // SAs in th local namespace to avoid having to qualify them. saNamespace := namespace @@ -275,7 +276,7 @@ func appliesToUser(user user.Info, subject rbac.Subject, namespace string) bool } // NewTestRuleResolver returns a rule resolver from lists of role objects. -func NewTestRuleResolver(roles []*rbac.Role, roleBindings []*rbac.RoleBinding, clusterRoles []*rbac.ClusterRole, clusterRoleBindings []*rbac.ClusterRoleBinding) (AuthorizationRuleResolver, *StaticRoles) { +func NewTestRuleResolver(roles []*rbacv1.Role, roleBindings []*rbacv1.RoleBinding, clusterRoles []*rbacv1.ClusterRole, clusterRoleBindings []*rbacv1.ClusterRoleBinding) (AuthorizationRuleResolver, *StaticRoles) { r := StaticRoles{ roles: roles, roleBindings: roleBindings, @@ -291,13 +292,13 @@ func newMockRuleResolver(r *StaticRoles) AuthorizationRuleResolver { // StaticRoles is a rule resolver that resolves from lists of role objects. type StaticRoles struct { - roles []*rbac.Role - roleBindings []*rbac.RoleBinding - clusterRoles []*rbac.ClusterRole - clusterRoleBindings []*rbac.ClusterRoleBinding + roles []*rbacv1.Role + roleBindings []*rbacv1.RoleBinding + clusterRoles []*rbacv1.ClusterRole + clusterRoleBindings []*rbacv1.ClusterRoleBinding } -func (r *StaticRoles) GetRole(namespace, name string) (*rbac.Role, error) { +func (r *StaticRoles) GetRole(namespace, name string) (*rbacv1.Role, error) { if len(namespace) == 0 { return nil, errors.New("must provide namespace when getting role") } @@ -309,21 +310,21 @@ func (r *StaticRoles) GetRole(namespace, name string) (*rbac.Role, error) { return nil, errors.New("role not found") } -func (r *StaticRoles) GetClusterRole(name string) (*rbac.ClusterRole, error) { +func (r *StaticRoles) GetClusterRole(name string) (*rbacv1.ClusterRole, error) { for _, clusterRole := range r.clusterRoles { if clusterRole.Name == name { return clusterRole, nil } } - return nil, errors.New("role not found") + return nil, errors.New("clusterrole not found") } -func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { +func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) { if len(namespace) == 0 { return nil, errors.New("must provide namespace when listing role bindings") } - roleBindingList := []*rbac.RoleBinding{} + roleBindingList := []*rbacv1.RoleBinding{} for _, roleBinding := range r.roleBindings { if roleBinding.Namespace != namespace { continue @@ -334,6 +335,6 @@ func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, e return roleBindingList, nil } -func (r *StaticRoles) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) { +func (r *StaticRoles) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) { return r.clusterRoleBindings, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule_test.go b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule_test.go index 1a176126b..b892f501a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule_test.go @@ -23,14 +23,14 @@ import ( "sort" "testing" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/kubernetes/pkg/apis/rbac" ) // compute a hash of a policy rule so we can sort in a deterministic order -func hashOf(p rbac.PolicyRule) string { +func hashOf(p rbacv1.PolicyRule) string { hash := fnv.New32() writeStrings := func(slis ...[]string) { for _, sli := range slis { @@ -44,68 +44,68 @@ func hashOf(p rbac.PolicyRule) string { } // byHash sorts a set of policy rules by a hash of its fields -type byHash []rbac.PolicyRule +type byHash []rbacv1.PolicyRule func (b byHash) Len() int { return len(b) } func (b byHash) Less(i, j int) bool { return hashOf(b[i]) < hashOf(b[j]) } func (b byHash) Swap(i, j int) { b[i], b[j] = b[j], b[i] } func TestDefaultRuleResolver(t *testing.T) { - ruleReadPods := rbac.PolicyRule{ + ruleReadPods := rbacv1.PolicyRule{ Verbs: []string{"GET", "WATCH"}, APIGroups: []string{"v1"}, Resources: []string{"pods"}, } - ruleReadServices := rbac.PolicyRule{ + ruleReadServices := rbacv1.PolicyRule{ Verbs: []string{"GET", "WATCH"}, APIGroups: []string{"v1"}, Resources: []string{"services"}, } - ruleWriteNodes := rbac.PolicyRule{ + ruleWriteNodes := rbacv1.PolicyRule{ Verbs: []string{"PUT", "CREATE", "UPDATE"}, APIGroups: []string{"v1"}, Resources: []string{"nodes"}, } - ruleAdmin := rbac.PolicyRule{ + ruleAdmin := rbacv1.PolicyRule{ Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}, } staticRoles1 := StaticRoles{ - roles: []*rbac.Role{ + roles: []*rbacv1.Role{ { ObjectMeta: metav1.ObjectMeta{Namespace: "namespace1", Name: "readthings"}, - Rules: []rbac.PolicyRule{ruleReadPods, ruleReadServices}, + Rules: []rbacv1.PolicyRule{ruleReadPods, ruleReadServices}, }, }, - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ { ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"}, - Rules: []rbac.PolicyRule{ruleAdmin}, + Rules: []rbacv1.PolicyRule{ruleAdmin}, }, { ObjectMeta: metav1.ObjectMeta{Name: "write-nodes"}, - Rules: []rbac.PolicyRule{ruleWriteNodes}, + Rules: []rbacv1.PolicyRule{ruleWriteNodes}, }, }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ { ObjectMeta: metav1.ObjectMeta{Namespace: "namespace1"}, - Subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "foobar"}, - {Kind: rbac.GroupKind, Name: "group1"}, + Subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "foobar"}, + {Kind: rbacv1.GroupKind, Name: "group1"}, }, - RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "readthings"}, + RoleRef: rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "Role", Name: "readthings"}, }, }, - clusterRoleBindings: []*rbac.ClusterRoleBinding{ + clusterRoleBindings: []*rbacv1.ClusterRoleBinding{ { - Subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "admin"}, - {Kind: rbac.GroupKind, Name: "admin"}, + Subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "admin"}, + {Kind: rbacv1.GroupKind, Name: "admin"}, }, - RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "cluster-admin"}, + RoleRef: rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: "cluster-admin"}, }, }, } @@ -116,13 +116,13 @@ func TestDefaultRuleResolver(t *testing.T) { // For a given context, what are the rules that apply? user user.Info namespace string - effectiveRules []rbac.PolicyRule + effectiveRules []rbacv1.PolicyRule }{ { StaticRoles: staticRoles1, user: &user.DefaultInfo{Name: "foobar"}, namespace: "namespace1", - effectiveRules: []rbac.PolicyRule{ruleReadPods, ruleReadServices}, + effectiveRules: []rbacv1.PolicyRule{ruleReadPods, ruleReadServices}, }, { StaticRoles: staticRoles1, @@ -134,7 +134,7 @@ func TestDefaultRuleResolver(t *testing.T) { StaticRoles: staticRoles1, // Same as above but without a namespace. Only cluster rules should apply. user: &user.DefaultInfo{Name: "foobar", Groups: []string{"admin"}}, - effectiveRules: []rbac.PolicyRule{ruleAdmin}, + effectiveRules: []rbacv1.PolicyRule{ruleAdmin}, }, { StaticRoles: staticRoles1, @@ -164,7 +164,7 @@ func TestDefaultRuleResolver(t *testing.T) { func TestAppliesTo(t *testing.T) { tests := []struct { - subjects []rbac.Subject + subjects []rbacv1.Subject user user.Info namespace string appliesTo bool @@ -172,8 +172,8 @@ func TestAppliesTo(t *testing.T) { testCase string }{ { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "foobar"}, appliesTo: true, @@ -181,9 +181,9 @@ func TestAppliesTo(t *testing.T) { testCase: "single subject that matches username", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.UserKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.UserKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "foobar"}, appliesTo: true, @@ -191,18 +191,18 @@ func TestAppliesTo(t *testing.T) { testCase: "multiple subjects, one that matches username", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.UserKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.UserKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "zimzam"}, appliesTo: false, testCase: "multiple subjects, none that match username", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.GroupKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.GroupKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}}, appliesTo: true, @@ -210,9 +210,9 @@ func TestAppliesTo(t *testing.T) { testCase: "multiple subjects, one that match group", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.GroupKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.GroupKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}}, namespace: "namespace1", @@ -221,10 +221,10 @@ func TestAppliesTo(t *testing.T) { testCase: "multiple subjects, one that match group, should ignore namespace", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.GroupKind, Name: "foobar"}, - {Kind: rbac.ServiceAccountKind, Namespace: "kube-system", Name: "default"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.GroupKind, Name: "foobar"}, + {Kind: rbacv1.ServiceAccountKind, Namespace: "kube-system", Name: "default"}, }, user: &user.DefaultInfo{Name: "system:serviceaccount:kube-system:default"}, namespace: "default", @@ -233,8 +233,8 @@ func TestAppliesTo(t *testing.T) { testCase: "multiple subjects with a service account that matches", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "*"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "*"}, }, user: &user.DefaultInfo{Name: "foobar"}, namespace: "default", @@ -242,9 +242,9 @@ func TestAppliesTo(t *testing.T) { testCase: "* user subject name doesn't match all users", }, { - subjects: []rbac.Subject{ - {Kind: rbac.GroupKind, Name: user.AllAuthenticated}, - {Kind: rbac.GroupKind, Name: user.AllUnauthenticated}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, Name: user.AllAuthenticated}, + {Kind: rbacv1.GroupKind, Name: user.AllUnauthenticated}, }, user: &user.DefaultInfo{Name: "foobar", Groups: []string{user.AllAuthenticated}}, namespace: "default", @@ -253,9 +253,9 @@ func TestAppliesTo(t *testing.T) { testCase: "binding to all authenticated and unauthenticated subjects matches authenticated user", }, { - subjects: []rbac.Subject{ - {Kind: rbac.GroupKind, Name: user.AllAuthenticated}, - {Kind: rbac.GroupKind, Name: user.AllUnauthenticated}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, Name: user.AllAuthenticated}, + {Kind: rbacv1.GroupKind, Name: user.AllUnauthenticated}, }, user: &user.DefaultInfo{Name: "system:anonymous", Groups: []string{user.AllUnauthenticated}}, namespace: "default", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/registrytest/endpoint.go b/vendor/k8s.io/kubernetes/pkg/registry/registrytest/endpoint.go index 170b95955..cc22b478e 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/registrytest/endpoint.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/registrytest/endpoint.go @@ -17,6 +17,7 @@ limitations under the License. package registrytest import ( + "context" "fmt" "sync" @@ -24,7 +25,6 @@ import ( metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" ) @@ -38,7 +38,7 @@ type EndpointRegistry struct { lock sync.Mutex } -func (e *EndpointRegistry) ListEndpoints(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.EndpointsList, error) { +func (e *EndpointRegistry) ListEndpoints(ctx context.Context, options *metainternalversion.ListOptions) (*api.EndpointsList, error) { // TODO: support namespaces in this mock e.lock.Lock() defer e.lock.Unlock() @@ -46,7 +46,7 @@ func (e *EndpointRegistry) ListEndpoints(ctx genericapirequest.Context, options return e.Endpoints, e.Err } -func (e *EndpointRegistry) GetEndpoints(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*api.Endpoints, error) { +func (e *EndpointRegistry) GetEndpoints(ctx context.Context, name string, options *metav1.GetOptions) (*api.Endpoints, error) { // TODO: support namespaces in this mock e.lock.Lock() defer e.lock.Unlock() @@ -63,11 +63,11 @@ func (e *EndpointRegistry) GetEndpoints(ctx genericapirequest.Context, name stri return nil, errors.NewNotFound(api.Resource("endpoints"), name) } -func (e *EndpointRegistry) WatchEndpoints(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (e *EndpointRegistry) WatchEndpoints(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return nil, fmt.Errorf("unimplemented!") } -func (e *EndpointRegistry) UpdateEndpoints(ctx genericapirequest.Context, endpoints *api.Endpoints, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { +func (e *EndpointRegistry) UpdateEndpoints(ctx context.Context, endpoints *api.Endpoints, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { // TODO: support namespaces in this mock e.lock.Lock() defer e.lock.Unlock() @@ -94,7 +94,7 @@ func (e *EndpointRegistry) UpdateEndpoints(ctx genericapirequest.Context, endpoi return nil } -func (e *EndpointRegistry) DeleteEndpoints(ctx genericapirequest.Context, name string) error { +func (e *EndpointRegistry) DeleteEndpoints(ctx context.Context, name string) error { // TODO: support namespaces in this mock e.lock.Lock() defer e.lock.Unlock() diff --git a/vendor/k8s.io/kubernetes/pkg/registry/registrytest/node.go b/vendor/k8s.io/kubernetes/pkg/registry/registrytest/node.go index e4d813dfe..9186006a2 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/registrytest/node.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/registrytest/node.go @@ -17,13 +17,13 @@ limitations under the License. package registrytest import ( + "context" "sync" "k8s.io/apimachinery/pkg/api/errors" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" api "k8s.io/kubernetes/pkg/apis/core" ) @@ -60,13 +60,13 @@ func (r *NodeRegistry) SetError(err error) { r.Err = err } -func (r *NodeRegistry) ListNodes(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.NodeList, error) { +func (r *NodeRegistry) ListNodes(ctx context.Context, options *metainternalversion.ListOptions) (*api.NodeList, error) { r.Lock() defer r.Unlock() return &r.Nodes, r.Err } -func (r *NodeRegistry) CreateNode(ctx genericapirequest.Context, node *api.Node) error { +func (r *NodeRegistry) CreateNode(ctx context.Context, node *api.Node) error { r.Lock() defer r.Unlock() r.Node = node.Name @@ -74,7 +74,7 @@ func (r *NodeRegistry) CreateNode(ctx genericapirequest.Context, node *api.Node) return r.Err } -func (r *NodeRegistry) UpdateNode(ctx genericapirequest.Context, node *api.Node) error { +func (r *NodeRegistry) UpdateNode(ctx context.Context, node *api.Node) error { r.Lock() defer r.Unlock() for i, item := range r.Nodes.Items { @@ -86,7 +86,7 @@ func (r *NodeRegistry) UpdateNode(ctx genericapirequest.Context, node *api.Node) return r.Err } -func (r *NodeRegistry) GetNode(ctx genericapirequest.Context, nodeID string, options *metav1.GetOptions) (*api.Node, error) { +func (r *NodeRegistry) GetNode(ctx context.Context, nodeID string, options *metav1.GetOptions) (*api.Node, error) { r.Lock() defer r.Unlock() if r.Err != nil { @@ -100,7 +100,7 @@ func (r *NodeRegistry) GetNode(ctx genericapirequest.Context, nodeID string, opt return nil, errors.NewNotFound(api.Resource("nodes"), nodeID) } -func (r *NodeRegistry) DeleteNode(ctx genericapirequest.Context, nodeID string) error { +func (r *NodeRegistry) DeleteNode(ctx context.Context, nodeID string) error { r.Lock() defer r.Unlock() var newList []api.Node @@ -113,6 +113,6 @@ func (r *NodeRegistry) DeleteNode(ctx genericapirequest.Context, nodeID string) return r.Err } -func (r *NodeRegistry) WatchNodes(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (r *NodeRegistry) WatchNodes(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return nil, r.Err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/registrytest/service.go b/vendor/k8s.io/kubernetes/pkg/registry/registrytest/service.go index 136d34153..490bc0e37 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/registrytest/service.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/registrytest/service.go @@ -17,6 +17,7 @@ limitations under the License. package registrytest import ( + "context" "sync" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" @@ -49,7 +50,7 @@ func (r *ServiceRegistry) SetError(err error) { r.Err = err } -func (r *ServiceRegistry) ListServices(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*api.ServiceList, error) { +func (r *ServiceRegistry) ListServices(ctx context.Context, options *metainternalversion.ListOptions) (*api.ServiceList, error) { r.mu.Lock() defer r.mu.Unlock() @@ -73,7 +74,7 @@ func (r *ServiceRegistry) ListServices(ctx genericapirequest.Context, options *m return res, r.Err } -func (r *ServiceRegistry) CreateService(ctx genericapirequest.Context, svc *api.Service, createValidation rest.ValidateObjectFunc) (*api.Service, error) { +func (r *ServiceRegistry) CreateService(ctx context.Context, svc *api.Service, createValidation rest.ValidateObjectFunc) (*api.Service, error) { r.mu.Lock() defer r.mu.Unlock() @@ -83,7 +84,7 @@ func (r *ServiceRegistry) CreateService(ctx genericapirequest.Context, svc *api. return svc, r.Err } -func (r *ServiceRegistry) GetService(ctx genericapirequest.Context, id string, options *metav1.GetOptions) (*api.Service, error) { +func (r *ServiceRegistry) GetService(ctx context.Context, id string, options *metav1.GetOptions) (*api.Service, error) { r.mu.Lock() defer r.mu.Unlock() @@ -91,7 +92,7 @@ func (r *ServiceRegistry) GetService(ctx genericapirequest.Context, id string, o return r.Service, r.Err } -func (r *ServiceRegistry) DeleteService(ctx genericapirequest.Context, id string) error { +func (r *ServiceRegistry) DeleteService(ctx context.Context, id string) error { r.mu.Lock() defer r.mu.Unlock() @@ -100,7 +101,7 @@ func (r *ServiceRegistry) DeleteService(ctx genericapirequest.Context, id string return r.Err } -func (r *ServiceRegistry) UpdateService(ctx genericapirequest.Context, svc *api.Service, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.Service, error) { +func (r *ServiceRegistry) UpdateService(ctx context.Context, svc *api.Service, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*api.Service, error) { r.mu.Lock() defer r.mu.Unlock() @@ -110,14 +111,14 @@ func (r *ServiceRegistry) UpdateService(ctx genericapirequest.Context, svc *api. return svc, r.Err } -func (r *ServiceRegistry) WatchServices(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (r *ServiceRegistry) WatchServices(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { r.mu.Lock() defer r.mu.Unlock() return nil, r.Err } -func (r *ServiceRegistry) ExportService(ctx genericapirequest.Context, name string, options metav1.ExportOptions) (*api.Service, error) { +func (r *ServiceRegistry) ExportService(ctx context.Context, name string, options metav1.ExportOptions) (*api.Service, error) { r.mu.Lock() defer r.mu.Unlock() diff --git a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/BUILD index 498ccb32c..579329ebb 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/BUILD @@ -34,7 +34,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/registry.go index 5e4c44dc1..c9c36989e 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/registry.go @@ -17,22 +17,23 @@ limitations under the License. package priorityclass import ( + "context" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/scheduling" ) // Registry is an interface for things that know how to store PriorityClass. type Registry interface { - ListPriorityClasses(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*scheduling.PriorityClassList, error) - CreatePriorityClass(ctx genericapirequest.Context, pc *scheduling.PriorityClass, createValidation rest.ValidateObjectFunc) error - UpdatePriorityClass(ctx genericapirequest.Context, pc *scheduling.PriorityClass, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetPriorityClass(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*scheduling.PriorityClass, error) - DeletePriorityClass(ctx genericapirequest.Context, name string) error - WatchPriorityClasses(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ListPriorityClasses(ctx context.Context, options *metainternalversion.ListOptions) (*scheduling.PriorityClassList, error) + CreatePriorityClass(ctx context.Context, pc *scheduling.PriorityClass, createValidation rest.ValidateObjectFunc) error + UpdatePriorityClass(ctx context.Context, pc *scheduling.PriorityClass, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error + GetPriorityClass(ctx context.Context, name string, options *metav1.GetOptions) (*scheduling.PriorityClass, error) + DeletePriorityClass(ctx context.Context, name string) error + WatchPriorityClasses(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) } // storage puts strong typing around storage calls @@ -46,7 +47,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListPriorityClasses(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*scheduling.PriorityClassList, error) { +func (s *storage) ListPriorityClasses(ctx context.Context, options *metainternalversion.ListOptions) (*scheduling.PriorityClassList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err @@ -55,21 +56,21 @@ func (s *storage) ListPriorityClasses(ctx genericapirequest.Context, options *me return obj.(*scheduling.PriorityClassList), nil } -func (s *storage) CreatePriorityClass(ctx genericapirequest.Context, pc *scheduling.PriorityClass, createValidation rest.ValidateObjectFunc) error { +func (s *storage) CreatePriorityClass(ctx context.Context, pc *scheduling.PriorityClass, createValidation rest.ValidateObjectFunc) error { _, err := s.Create(ctx, pc, createValidation, false) return err } -func (s *storage) UpdatePriorityClass(ctx genericapirequest.Context, pc *scheduling.PriorityClass, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { +func (s *storage) UpdatePriorityClass(ctx context.Context, pc *scheduling.PriorityClass, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { _, _, err := s.Update(ctx, pc.Name, rest.DefaultUpdatedObjectInfo(pc), createValidation, updateValidation) return err } -func (s *storage) WatchPriorityClasses(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchPriorityClasses(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetPriorityClass(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*scheduling.PriorityClass, error) { +func (s *storage) GetPriorityClass(ctx context.Context, name string, options *metav1.GetOptions) (*scheduling.PriorityClass, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err @@ -77,7 +78,7 @@ func (s *storage) GetPriorityClass(ctx genericapirequest.Context, name string, o return obj.(*scheduling.PriorityClass), nil } -func (s *storage) DeletePriorityClass(ctx genericapirequest.Context, name string) error { +func (s *storage) DeletePriorityClass(ctx context.Context, name string) error { _, _, err := s.Delete(ctx, name, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/BUILD index 7c0f95e78..6cff83196 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/BUILD @@ -17,6 +17,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/testing:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library", @@ -30,6 +31,8 @@ go_library( deps = [ "//pkg/apis/scheduling:go_default_library", "//pkg/registry/scheduling/priorityclass:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/storage.go b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/storage.go index b42036211..e0594bb16 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/storage.go @@ -17,11 +17,16 @@ limitations under the License. package storage import ( + "context" + "errors" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" - schedulingapi "k8s.io/kubernetes/pkg/apis/scheduling" + "k8s.io/kubernetes/pkg/apis/scheduling" "k8s.io/kubernetes/pkg/registry/scheduling/priorityclass" ) @@ -33,9 +38,9 @@ type REST struct { // NewREST returns a RESTStorage object that will work against priority classes. func NewREST(optsGetter generic.RESTOptionsGetter) *REST { store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &schedulingapi.PriorityClass{} }, - NewListFunc: func() runtime.Object { return &schedulingapi.PriorityClassList{} }, - DefaultQualifiedResource: schedulingapi.Resource("priorityclasses"), + NewFunc: func() runtime.Object { return &scheduling.PriorityClass{} }, + NewListFunc: func() runtime.Object { return &scheduling.PriorityClassList{} }, + DefaultQualifiedResource: scheduling.Resource("priorityclasses"), CreateStrategy: priorityclass.Strategy, UpdateStrategy: priorityclass.Strategy, @@ -56,3 +61,14 @@ var _ rest.ShortNamesProvider = &REST{} func (r *REST) ShortNames() []string { return []string{"pc"} } + +// Delete ensures that system priority classes are not deleted. +func (r *REST) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { + for _, spc := range scheduling.SystemPriorityClasses() { + if name == spc.Name { + return nil, false, apierrors.NewForbidden(scheduling.Resource("priorityclasses"), spc.Name, errors.New("this is a system priority class and cannot be deleted")) + } + } + + return r.Store.Delete(ctx, name, options) +} diff --git a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/storage_test.go b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/storage_test.go index 8ef95fd59..01a081ea5 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/storage_test.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage/storage_test.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" @@ -105,6 +106,22 @@ func TestDelete(t *testing.T) { test.TestDelete(validNewPriorityClass()) } +// TestDeleteSystemPriorityClass checks that system priority classes cannot be deleted. +func TestDeleteSystemPriorityClass(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + key := "test/system-node-critical" + ctx := genericapirequest.NewContext() + pc := scheduling.SystemPriorityClasses()[0] + if err := storage.Store.Storage.Create(ctx, key, pc, nil, 0); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if _, _, err := storage.Delete(ctx, pc.Name, nil); err == nil { + t.Error("expected to receive an error") + } +} + func TestGet(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/strategy.go index f39dce1df..0a5b87a55 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package priorityclass import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/scheduling" @@ -41,19 +42,19 @@ func (priorityClassStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a PriorityClass before creation. -func (priorityClassStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (priorityClassStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { pc := obj.(*scheduling.PriorityClass) pc.Generation = 1 } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (priorityClassStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (priorityClassStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { _ = obj.(*scheduling.PriorityClass) _ = old.(*scheduling.PriorityClass) } // Validate validates a new PriorityClass. -func (priorityClassStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (priorityClassStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { pc := obj.(*scheduling.PriorityClass) return validation.ValidatePriorityClass(pc) } @@ -67,10 +68,8 @@ func (priorityClassStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (priorityClassStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { - validationErrorList := validation.ValidatePriorityClass(obj.(*scheduling.PriorityClass)) - updateErrorList := validation.ValidatePriorityClassUpdate(obj.(*scheduling.PriorityClass), old.(*scheduling.PriorityClass)) - return append(validationErrorList, updateErrorList...) +func (priorityClassStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { + return validation.ValidatePriorityClassUpdate(obj.(*scheduling.PriorityClass), old.(*scheduling.PriorityClass)) } // AllowUnconditionalUpdate is the default update policy for PriorityClass objects. diff --git a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/rest/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/rest/BUILD index 54e6dd25c..dfdff1788 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/rest/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/rest/BUILD @@ -13,7 +13,14 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/scheduling:go_default_library", "//pkg/apis/scheduling/v1alpha1:go_default_library", + "//pkg/apis/scheduling/v1beta1:go_default_library", + "//pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion:go_default_library", "//pkg/registry/scheduling/priorityclass/storage:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/rest/storage_scheduling.go b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/rest/storage_scheduling.go index 3074fb7d4..aad6e09ec 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/scheduling/rest/storage_scheduling.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/scheduling/rest/storage_scheduling.go @@ -17,6 +17,15 @@ limitations under the License. package rest import ( + "fmt" + "time" + + "github.com/golang/glog" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" @@ -24,23 +33,30 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/scheduling" schedulingapiv1alpha1 "k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1" + schedulingapiv1beta1 "k8s.io/kubernetes/pkg/apis/scheduling/v1beta1" + schedulingclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion" priorityclassstore "k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage" ) +const PostStartHookName = "scheduling/bootstrap-system-priority-classes" + type RESTStorageProvider struct{} +var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{} + func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(scheduling.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(scheduling.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) if apiResourceConfigSource.VersionEnabled(schedulingapiv1alpha1.SchemeGroupVersion) { - apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = schedulingapiv1alpha1.SchemeGroupVersion + apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1alpha1.SchemeGroupVersion.Version] = p.storage(apiResourceConfigSource, restOptionsGetter) + } + if apiResourceConfigSource.VersionEnabled(schedulingapiv1beta1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1beta1.SchemeGroupVersion.Version] = p.storage(apiResourceConfigSource, restOptionsGetter) } - return apiGroupInfo, true } -func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { +func (p RESTStorageProvider) storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { storage := map[string]rest.Storage{} // priorityclasses priorityClassStorage := priorityclassstore.NewREST(restOptionsGetter) @@ -49,6 +65,49 @@ func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstora return storage } +func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStartHookFunc, error) { + return PostStartHookName, AddSystemPriorityClasses(), nil +} + +func AddSystemPriorityClasses() genericapiserver.PostStartHookFunc { + return func(hookContext genericapiserver.PostStartHookContext) error { + // Adding system priority classes is important. If they fail to add, many critical system + // components may fail and cluster may break. + err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) { + schedClientSet, err := schedulingclient.NewForConfig(hookContext.LoopbackClientConfig) + if err != nil { + utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err)) + return false, nil + } + + for _, pc := range scheduling.SystemPriorityClasses() { + _, err := schedClientSet.PriorityClasses().Get(pc.Name, metav1.GetOptions{}) + if err != nil { + if apierrors.IsNotFound(err) { + _, err := schedClientSet.PriorityClasses().Create(pc) + if err != nil && !apierrors.IsAlreadyExists(err) { + return false, err + } else { + glog.Infof("created PriorityClass %s with value %v", pc.Name, pc.Value) + } + } else { + // Unable to get the priority class for reasons other than "not found". + glog.Warningf("unable to get PriorityClass %v: %v. Retrying...", pc.Name, err) + return false, err + } + } + } + glog.Infof("all system priority classes are created successfully or already exist.") + return true, nil + }) + // if we're never able to make it through initialization, kill the API server. + if err != nil { + return fmt.Errorf("unable to add default system priority classes: %v", err) + } + return nil + } +} + func (p RESTStorageProvider) GroupName() string { return scheduling.GroupName } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/BUILD index 5d58bda6a..e495b5329 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/BUILD @@ -23,7 +23,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/registry.go b/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/registry.go index 74b056d0e..e90032b98 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/registry.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/registry.go @@ -17,22 +17,23 @@ limitations under the License. package podpreset import ( + "context" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/settings" ) // Registry is an interface for things that know how to store PodPresets. type Registry interface { - ListPodPresets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*settings.PodPresetList, error) - CreatePodPreset(ctx genericapirequest.Context, pp *settings.PodPreset, createValidation rest.ValidateObjectFunc) error - UpdatePodPreset(ctx genericapirequest.Context, pp *settings.PodPreset, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetPodPreset(ctx genericapirequest.Context, ppID string, options *metav1.GetOptions) (*settings.PodPreset, error) - DeletePodPreset(ctx genericapirequest.Context, ppID string) error - WatchPodPresets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ListPodPresets(ctx context.Context, options *metainternalversion.ListOptions) (*settings.PodPresetList, error) + CreatePodPreset(ctx context.Context, pp *settings.PodPreset, createValidation rest.ValidateObjectFunc) error + UpdatePodPreset(ctx context.Context, pp *settings.PodPreset, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error + GetPodPreset(ctx context.Context, ppID string, options *metav1.GetOptions) (*settings.PodPreset, error) + DeletePodPreset(ctx context.Context, ppID string) error + WatchPodPresets(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) } // storage puts strong typing around storage calls @@ -46,7 +47,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListPodPresets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*settings.PodPresetList, error) { +func (s *storage) ListPodPresets(ctx context.Context, options *metainternalversion.ListOptions) (*settings.PodPresetList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err @@ -55,21 +56,21 @@ func (s *storage) ListPodPresets(ctx genericapirequest.Context, options *metaint return obj.(*settings.PodPresetList), nil } -func (s *storage) CreatePodPreset(ctx genericapirequest.Context, pp *settings.PodPreset, createValidation rest.ValidateObjectFunc) error { +func (s *storage) CreatePodPreset(ctx context.Context, pp *settings.PodPreset, createValidation rest.ValidateObjectFunc) error { _, err := s.Create(ctx, pp, createValidation, false) return err } -func (s *storage) UpdatePodPreset(ctx genericapirequest.Context, pp *settings.PodPreset, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { +func (s *storage) UpdatePodPreset(ctx context.Context, pp *settings.PodPreset, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { _, _, err := s.Update(ctx, pp.Name, rest.DefaultUpdatedObjectInfo(pp), createValidation, updateValidation) return err } -func (s *storage) WatchPodPresets(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchPodPresets(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetPodPreset(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*settings.PodPreset, error) { +func (s *storage) GetPodPreset(ctx context.Context, name string, options *metav1.GetOptions) (*settings.PodPreset, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err @@ -77,7 +78,7 @@ func (s *storage) GetPodPreset(ctx genericapirequest.Context, name string, optio return obj.(*settings.PodPreset), nil } -func (s *storage) DeletePodPreset(ctx genericapirequest.Context, name string) error { +func (s *storage) DeletePodPreset(ctx context.Context, name string) error { _, _, err := s.Delete(ctx, name, nil) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/strategy.go index eaeb92792..b6e2f2c7b 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/settings/podpreset/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package podpreset import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/pod" @@ -42,7 +43,7 @@ func (podPresetStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a Pod Preset before creation. -func (podPresetStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (podPresetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { pip := obj.(*settings.PodPreset) pip.Generation = 1 @@ -50,7 +51,7 @@ func (podPresetStrategy) PrepareForCreate(ctx genericapirequest.Context, obj run } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (podPresetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (podPresetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPodPreset := obj.(*settings.PodPreset) oldPodPreset := old.(*settings.PodPreset) @@ -62,7 +63,7 @@ func (podPresetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, ol } // Validate validates a new PodPreset. -func (podPresetStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (podPresetStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { pip := obj.(*settings.PodPreset) return validation.ValidatePodPreset(pip) } @@ -76,7 +77,7 @@ func (podPresetStrategy) AllowCreateOnUpdate() bool { } // ValidateUpdate is the default update validation for an end user. -func (podPresetStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (podPresetStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { validationErrorList := validation.ValidatePodPreset(obj.(*settings.PodPreset)) updateErrorList := validation.ValidatePodPresetUpdate(obj.(*settings.PodPreset), old.(*settings.PodPreset)) return append(validationErrorList, updateErrorList...) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/settings/rest/storage_settings.go b/vendor/k8s.io/kubernetes/pkg/registry/settings/rest/storage_settings.go index 7cc958b25..3f50a54f9 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/settings/rest/storage_settings.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/settings/rest/storage_settings.go @@ -30,13 +30,12 @@ import ( type RESTStorageProvider struct{} func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(settings.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(settings.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(settingsapiv1alpha1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[settingsapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = settingsapiv1alpha1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/storage/rest/storage_storage.go b/vendor/k8s.io/kubernetes/pkg/registry/storage/rest/storage_storage.go index 3b581c113..5e8b2529a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/storage/rest/storage_storage.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/storage/rest/storage_storage.go @@ -34,21 +34,18 @@ type RESTStorageProvider struct { } func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(storageapi.GroupName, legacyscheme.Registry, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(storageapi.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(storageapiv1alpha1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[storageapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = storageapiv1alpha1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(storageapiv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[storageapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = storageapiv1beta1.SchemeGroupVersion } if apiResourceConfigSource.VersionEnabled(storageapiv1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[storageapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) - apiGroupInfo.GroupMeta.GroupVersion = storageapiv1.SchemeGroupVersion } return apiGroupInfo, true diff --git a/vendor/k8s.io/kubernetes/pkg/registry/storage/storageclass/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/storage/storageclass/BUILD index d0a99123f..d251687bc 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/storage/storageclass/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/storage/storageclass/BUILD @@ -21,7 +21,6 @@ go_library( "//pkg/features:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/registry/storage/storageclass/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/storage/storageclass/strategy.go index b1cbf49eb..b570d39e2 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/storage/storageclass/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/storage/storageclass/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package storageclass import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -44,7 +45,7 @@ func (storageClassStrategy) NamespaceScoped() bool { } // ResetBeforeCreate clears the Status field which is not allowed to be set by end users on creation. -func (storageClassStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (storageClassStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { class := obj.(*storage.StorageClass) if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) { @@ -54,7 +55,7 @@ func (storageClassStrategy) PrepareForCreate(ctx genericapirequest.Context, obj storageutil.DropDisabledAlphaFields(class) } -func (storageClassStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (storageClassStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { storageClass := obj.(*storage.StorageClass) return validation.ValidateStorageClass(storageClass) } @@ -68,7 +69,7 @@ func (storageClassStrategy) AllowCreateOnUpdate() bool { } // PrepareForUpdate sets the Status fields which is not allowed to be set by an end user updating a PV -func (storageClassStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (storageClassStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newClass := obj.(*storage.StorageClass) oldClass := old.(*storage.StorageClass) @@ -80,7 +81,7 @@ func (storageClassStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, storageutil.DropDisabledAlphaFields(newClass) } -func (storageClassStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (storageClassStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { errorList := validation.ValidateStorageClass(obj.(*storage.StorageClass)) return append(errorList, validation.ValidateStorageClassUpdate(obj.(*storage.StorageClass), old.(*storage.StorageClass))...) } diff --git a/vendor/k8s.io/kubernetes/pkg/registry/storage/volumeattachment/BUILD b/vendor/k8s.io/kubernetes/pkg/registry/storage/volumeattachment/BUILD index 582dd5533..40f3de8bc 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/storage/volumeattachment/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/registry/storage/volumeattachment/BUILD @@ -14,7 +14,6 @@ go_library( "//pkg/apis/storage/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/registry/storage/volumeattachment/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/storage/volumeattachment/strategy.go index e319a0d87..9ee76f187 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/storage/volumeattachment/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/storage/volumeattachment/strategy.go @@ -17,9 +17,10 @@ limitations under the License. package volumeattachment import ( + "context" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/storage" @@ -41,10 +42,10 @@ func (volumeAttachmentStrategy) NamespaceScoped() bool { } // ResetBeforeCreate clears the Status field which is not allowed to be set by end users on creation. -func (volumeAttachmentStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (volumeAttachmentStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { } -func (volumeAttachmentStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (volumeAttachmentStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { volumeAttachment := obj.(*storage.VolumeAttachment) return validation.ValidateVolumeAttachment(volumeAttachment) } @@ -58,10 +59,10 @@ func (volumeAttachmentStrategy) AllowCreateOnUpdate() bool { } // PrepareForUpdate sets the Status fields which is not allowed to be set by an end user updating a PV -func (volumeAttachmentStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (volumeAttachmentStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } -func (volumeAttachmentStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (volumeAttachmentStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { newVolumeAttachmentObj := obj.(*storage.VolumeAttachment) oldVolumeAttachmentObj := old.(*storage.VolumeAttachment) errorList := validation.ValidateVolumeAttachment(newVolumeAttachmentObj) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/BUILD index 4a4a322cf..1e14062c5 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/BUILD @@ -15,10 +15,9 @@ go_test( "//pkg/controller/volume/persistentvolume:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/core:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/testing:go_default_library", - "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -45,9 +44,9 @@ go_library( "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/api:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/core:go_default_library", "//pkg/scheduler/metrics:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -76,10 +75,10 @@ filegroup( "//pkg/scheduler/algorithm:all-srcs", "//pkg/scheduler/algorithmprovider:all-srcs", "//pkg/scheduler/api:all-srcs", + "//pkg/scheduler/cache:all-srcs", "//pkg/scheduler/core:all-srcs", "//pkg/scheduler/factory:all-srcs", "//pkg/scheduler/metrics:all-srcs", - "//pkg/scheduler/schedulercache:all-srcs", "//pkg/scheduler/testing:all-srcs", "//pkg/scheduler/util:all-srcs", "//pkg/scheduler/volumebinder:all-srcs", diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/OWNERS b/vendor/k8s.io/kubernetes/pkg/scheduler/OWNERS index d2792efd5..fe768eadb 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/OWNERS @@ -2,3 +2,5 @@ approvers: - sig-scheduling-maintainers reviewers: - sig-scheduling +labels: +- sig/scheduling diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/BUILD index f2230c48c..37bfb4fb9 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/BUILD @@ -16,8 +16,9 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/scheduler/algorithm", deps = [ + "//pkg/apis/core:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", @@ -33,7 +34,7 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/BUILD index d85c82287..13e216174 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/BUILD @@ -23,7 +23,7 @@ go_library( "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//pkg/volume/util:go_default_library", @@ -32,6 +32,7 @@ go_library( "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/util/rand:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", @@ -45,6 +46,7 @@ go_library( go_test( name = "go_default_test", srcs = [ + "max_attachable_volume_predicate_test.go", "metadata_test.go", "predicates_test.go", "utils_test.go", @@ -52,10 +54,12 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core/v1/helper:go_default_library", + "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/algorithm:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/testing:go_default_library", + "//pkg/volume/util:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -63,6 +67,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/error.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/error.go index 6f7160dfa..1e1cbcaa9 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/error.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/error.go @@ -61,6 +61,8 @@ var ( ErrNodeUnderMemoryPressure = newPredicateFailureError("NodeUnderMemoryPressure", "node(s) had memory pressure") // ErrNodeUnderDiskPressure is used for NodeUnderDiskPressure predicate error. ErrNodeUnderDiskPressure = newPredicateFailureError("NodeUnderDiskPressure", "node(s) had disk pressure") + // ErrNodeUnderPIDPressure is used for NodeUnderPIDPressure predicate error. + ErrNodeUnderPIDPressure = newPredicateFailureError("NodeUnderPIDPressure", "node(s) had pid pressure") // ErrNodeOutOfDisk is used for NodeOutOfDisk predicate error. ErrNodeOutOfDisk = newPredicateFailureError("NodeOutOfDisk", "node(s) were out of disk space") // ErrNodeNotReady is used for NodeNotReady predicate error. diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go new file mode 100644 index 000000000..60aa5879a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go @@ -0,0 +1,854 @@ +/* +Copyright 2018 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 predicates + +import ( + "os" + "reflect" + "strconv" + "strings" + "testing" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" + utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/scheduler/algorithm" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + volumeutil "k8s.io/kubernetes/pkg/volume/util" +) + +func onePVCPod(filterName string) *v1.Pod { + return &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "some" + filterName + "Vol", + }, + }, + }, + }, + }, + } +} + +func splitPVCPod(filterName string) *v1.Pod { + return &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "someNon" + filterName + "Vol", + }, + }, + }, + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "some" + filterName + "Vol", + }, + }, + }, + }, + }, + } +} + +func TestVolumeCountConflicts(t *testing.T) { + oneVolPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"}, + }, + }, + }, + }, + } + twoVolPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp1"}, + }, + }, + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp2"}, + }, + }, + }, + }, + } + splitVolsPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{}, + }, + }, + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "svp"}, + }, + }, + }, + }, + } + nonApplicablePod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{}, + }, + }, + }, + }, + } + deletedPVCPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "deletedPVC", + }, + }, + }, + }, + }, + } + twoDeletedPVCPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "deletedPVC", + }, + }, + }, + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "anotherDeletedPVC", + }, + }, + }, + }, + }, + } + deletedPVPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "pvcWithDeletedPV", + }, + }, + }, + }, + }, + } + // deletedPVPod2 is a different pod than deletedPVPod but using the same PVC + deletedPVPod2 := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "pvcWithDeletedPV", + }, + }, + }, + }, + }, + } + // anotherDeletedPVPod is a different pod than deletedPVPod and uses another PVC + anotherDeletedPVPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "anotherPVCWithDeletedPV", + }, + }, + }, + }, + }, + } + emptyPod := &v1.Pod{ + Spec: v1.PodSpec{}, + } + unboundPVCPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "unboundPVC", + }, + }, + }, + }, + }, + } + // Different pod than unboundPVCPod, but using the same unbound PVC + unboundPVCPod2 := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "unboundPVC", + }, + }, + }, + }, + }, + } + + // pod with unbound PVC that's different to unboundPVC + anotherUnboundPVCPod := &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "anotherUnboundPVC", + }, + }, + }, + }, + }, + } + + tests := []struct { + newPod *v1.Pod + existingPods []*v1.Pod + filterName string + maxVols int + fits bool + test string + }{ + // filterName:EBSVolumeFilterType + { + newPod: oneVolPod, + existingPods: []*v1.Pod{twoVolPod, oneVolPod}, + filterName: EBSVolumeFilterType, + maxVols: 4, + fits: true, + test: "fits when node capacity >= new pod's EBS volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "doesn't fit when node capacity < new pod's EBS volumes", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{twoVolPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores non-EBS volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts ignore non-EBS volumes", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count considers PVCs backed by EBS volumes", + }, + { + newPod: splitPVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores PVCs not backed by EBS volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, onePVCPod(EBSVolumeFilterType)}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: false, + test: "existing pods' counts considers PVCs backed by EBS volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(EBSVolumeFilterType)}, + filterName: EBSVolumeFilterType, + maxVols: 4, + fits: true, + test: "already-mounted EBS volumes are always ok to allow", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(EBSVolumeFilterType)}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "the same EBS volumes are not counted multiple times", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: false, + test: "pod with missing two PVCs is counted towards the PV limit twice", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: deletedPVPod2, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing the same PV are counted towards the PV limit only once", + }, + { + newPod: anotherDeletedPVPod, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "two pods missing different PVs are counted towards the PV limit twice", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(EBSVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: unboundPVCPod2, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: true, + test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", + }, + { + newPod: anotherUnboundPVCPod, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: EBSVolumeFilterType, + maxVols: 2, + fits: false, + test: "two different unbound PVCs are counted towards the PV limit as two volumes", + }, + // filterName:GCEPDVolumeFilterType + { + newPod: oneVolPod, + existingPods: []*v1.Pod{twoVolPod, oneVolPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 4, + fits: true, + test: "fits when node capacity >= new pod's GCE volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "fit when node capacity < new pod's GCE volumes", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{twoVolPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores non-GCE volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts ignore non-GCE volumes", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count considers PVCs backed by GCE volumes", + }, + { + newPod: splitPVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores PVCs not backed by GCE volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, onePVCPod(GCEPDVolumeFilterType)}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts considers PVCs backed by GCE volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(GCEPDVolumeFilterType)}, + filterName: GCEPDVolumeFilterType, + maxVols: 4, + fits: true, + test: "already-mounted EBS volumes are always ok to allow", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(GCEPDVolumeFilterType)}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "the same GCE volumes are not counted multiple times", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing two PVCs is counted towards the PV limit twice", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: deletedPVPod2, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing the same PV are counted towards the PV limit only once", + }, + { + newPod: anotherDeletedPVPod, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing different PVs are counted towards the PV limit twice", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(GCEPDVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: unboundPVCPod2, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", + }, + { + newPod: anotherUnboundPVCPod, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: GCEPDVolumeFilterType, + maxVols: 2, + fits: true, + test: "two different unbound PVCs are counted towards the PV limit as two volumes", + }, + // filterName:AzureDiskVolumeFilterType + { + newPod: oneVolPod, + existingPods: []*v1.Pod{twoVolPod, oneVolPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 4, + fits: true, + test: "fits when node capacity >= new pod's AzureDisk volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "fit when node capacity < new pod's AzureDisk volumes", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{twoVolPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores non-AzureDisk volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts ignore non-AzureDisk volumes", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count considers PVCs backed by AzureDisk volumes", + }, + { + newPod: splitPVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "new pod's count ignores PVCs not backed by AzureDisk volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, onePVCPod(AzureDiskVolumeFilterType)}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "existing pods' counts considers PVCs backed by AzureDisk volumes", + }, + { + newPod: twoVolPod, + existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(AzureDiskVolumeFilterType)}, + filterName: AzureDiskVolumeFilterType, + maxVols: 4, + fits: true, + test: "already-mounted AzureDisk volumes are always ok to allow", + }, + { + newPod: splitVolsPod, + existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(AzureDiskVolumeFilterType)}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "the same AzureDisk volumes are not counted multiple times", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing two PVCs is counted towards the PV limit twice", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with missing PV is counted towards the PV limit", + }, + { + newPod: deletedPVPod2, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing the same PV are counted towards the PV limit only once", + }, + { + newPod: anotherDeletedPVPod, + existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "two pods missing different PVs are counted towards the PV limit twice", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: onePVCPod(AzureDiskVolumeFilterType), + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 3, + fits: true, + test: "pod with unbound PVC is counted towards the PV limit", + }, + { + newPod: unboundPVCPod2, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", + }, + { + newPod: anotherUnboundPVCPod, + existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, + filterName: AzureDiskVolumeFilterType, + maxVols: 2, + fits: true, + test: "two different unbound PVCs are counted towards the PV limit as two volumes", + }, + } + + pvInfo := func(filterName string) FakePersistentVolumeInfo { + return FakePersistentVolumeInfo{ + { + ObjectMeta: metav1.ObjectMeta{Name: "some" + filterName + "Vol"}, + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: strings.ToLower(filterName) + "Vol"}, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "someNon" + filterName + "Vol"}, + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{}, + }, + }, + } + } + + pvcInfo := func(filterName string) FakePersistentVolumeClaimInfo { + return FakePersistentVolumeClaimInfo{ + { + ObjectMeta: metav1.ObjectMeta{Name: "some" + filterName + "Vol"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: "some" + filterName + "Vol"}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "someNon" + filterName + "Vol"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: "someNon" + filterName + "Vol"}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "pvcWithDeletedPV"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: "pvcWithDeletedPV"}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "anotherPVCWithDeletedPV"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: "anotherPVCWithDeletedPV"}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "unboundPVC"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: ""}, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "anotherUnboundPVC"}, + Spec: v1.PersistentVolumeClaimSpec{VolumeName: ""}, + }, + } + } + + expectedFailureReasons := []algorithm.PredicateFailureReason{ErrMaxVolumeCountExceeded} + + // running attachable predicate tests without feature gate and no limit present on nodes + for _, test := range tests { + os.Setenv(KubeMaxPDVols, strconv.Itoa(test.maxVols)) + pred := NewMaxPDVolumeCountPredicate(test.filterName, pvInfo(test.filterName), pvcInfo(test.filterName)) + fits, reasons, err := pred(test.newPod, PredicateMetadata(test.newPod, nil), schedulercache.NewNodeInfo(test.existingPods...)) + if err != nil { + t.Errorf("[%s]%s: unexpected error: %v", test.filterName, test.test, err) + } + if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) { + t.Errorf("[%s]%s: unexpected failure reasons: %v, want: %v", test.filterName, test.test, reasons, expectedFailureReasons) + } + if fits != test.fits { + t.Errorf("[%s]%s: expected %v, got %v", test.filterName, test.test, test.fits, fits) + } + } + + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AttachVolumeLimit, true)() + + // running attachable predicate tests with feature gate and limit present on nodes + for _, test := range tests { + node := getNodeWithPodAndVolumeLimits(test.existingPods, int64(test.maxVols), test.filterName) + pred := NewMaxPDVolumeCountPredicate(test.filterName, pvInfo(test.filterName), pvcInfo(test.filterName)) + fits, reasons, err := pred(test.newPod, PredicateMetadata(test.newPod, nil), node) + if err != nil { + t.Errorf("Using allocatable [%s]%s: unexpected error: %v", test.filterName, test.test, err) + } + if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) { + t.Errorf("Using allocatable [%s]%s: unexpected failure reasons: %v, want: %v", test.filterName, test.test, reasons, expectedFailureReasons) + } + if fits != test.fits { + t.Errorf("Using allocatable [%s]%s: expected %v, got %v", test.filterName, test.test, test.fits, fits) + } + } +} + +func getNodeWithPodAndVolumeLimits(pods []*v1.Pod, limit int64, filter string) *schedulercache.NodeInfo { + nodeInfo := schedulercache.NewNodeInfo(pods...) + node := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "node-for-max-pd-test-1"}, + Status: v1.NodeStatus{ + Allocatable: v1.ResourceList{ + getVolumeLimitKey(filter): *resource.NewQuantity(limit, resource.DecimalSI), + }, + }, + } + nodeInfo.SetNode(node) + return nodeInfo +} + +func getVolumeLimitKey(filterType string) v1.ResourceName { + switch filterType { + case EBSVolumeFilterType: + return v1.ResourceName(volumeutil.EBSVolumeLimitKey) + case GCEPDVolumeFilterType: + return v1.ResourceName(volumeutil.GCEVolumeLimitKey) + case AzureDiskVolumeFilterType: + return v1.ResourceName(volumeutil.AzureVolumeLimitKey) + default: + return "" + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/metadata.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/metadata.go index a83e153e5..2b276ede6 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/metadata.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/metadata.go @@ -20,14 +20,17 @@ import ( "fmt" "sync" + "github.com/golang/glog" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/util/workqueue" "k8s.io/kubernetes/pkg/scheduler/algorithm" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedutil "k8s.io/kubernetes/pkg/scheduler/util" - - "github.com/golang/glog" ) // PredicateMetadataFactory defines a factory of predicate metadata. @@ -50,7 +53,13 @@ type predicateMetadata struct { podRequest *schedulercache.Resource podPorts []*v1.ContainerPort //key is a pod full name with the anti-affinity rules. - matchingAntiAffinityTerms map[string][]matchingPodAntiAffinityTerm + matchingAntiAffinityTerms map[string][]matchingPodAntiAffinityTerm + // A map of node name to a list of Pods on the node that can potentially match + // the affinity rules of the "pod". + nodeNameToMatchingAffinityPods map[string][]*v1.Pod + // A map of node name to a list of Pods on the node that can potentially match + // the anti-affinity rules of the "pod". + nodeNameToMatchingAntiAffinityPods map[string][]*v1.Pod serviceAffinityInUse bool serviceAffinityMatchingPodList []*v1.Pod serviceAffinityMatchingPodServices []*v1.Service @@ -108,12 +117,19 @@ func (pfactory *PredicateMetadataFactory) GetMetadata(pod *v1.Pod, nodeNameToInf if err != nil { return nil } + affinityPods, antiAffinityPods, err := getPodsMatchingAffinity(pod, nodeNameToInfoMap) + if err != nil { + glog.Errorf("[predicate meta data generation] error finding pods that match affinity terms: %v", err) + return nil + } predicateMetadata := &predicateMetadata{ - pod: pod, - podBestEffort: isPodBestEffort(pod), - podRequest: GetResourceRequest(pod), - podPorts: schedutil.GetContainerPorts(pod), - matchingAntiAffinityTerms: matchingTerms, + pod: pod, + podBestEffort: isPodBestEffort(pod), + podRequest: GetResourceRequest(pod), + podPorts: schedutil.GetContainerPorts(pod), + matchingAntiAffinityTerms: matchingTerms, + nodeNameToMatchingAffinityPods: affinityPods, + nodeNameToMatchingAntiAffinityPods: antiAffinityPods, } for predicateName, precomputeFunc := range predicateMetadataProducers { glog.V(10).Infof("Precompute: %v", predicateName) @@ -131,6 +147,33 @@ func (meta *predicateMetadata) RemovePod(deletedPod *v1.Pod) error { } // Delete any anti-affinity rule from the deletedPod. delete(meta.matchingAntiAffinityTerms, deletedPodFullName) + // Delete pod from the matching affinity or anti-affinity pods if exists. + affinity := meta.pod.Spec.Affinity + podNodeName := deletedPod.Spec.NodeName + if affinity != nil && len(podNodeName) > 0 { + if affinity.PodAffinity != nil { + for i, p := range meta.nodeNameToMatchingAffinityPods[podNodeName] { + if p == deletedPod { + s := meta.nodeNameToMatchingAffinityPods[podNodeName] + s[i] = s[len(s)-1] + s = s[:len(s)-1] + meta.nodeNameToMatchingAffinityPods[podNodeName] = s + break + } + } + } + if affinity.PodAntiAffinity != nil { + for i, p := range meta.nodeNameToMatchingAntiAffinityPods[podNodeName] { + if p == deletedPod { + s := meta.nodeNameToMatchingAntiAffinityPods[podNodeName] + s[i] = s[len(s)-1] + s = s[:len(s)-1] + meta.nodeNameToMatchingAntiAffinityPods[podNodeName] = s + break + } + } + } + } // All pods in the serviceAffinityMatchingPodList are in the same namespace. // So, if the namespace of the first one is not the same as the namespace of the // deletedPod, we don't need to check the list, as deletedPod isn't in the list. @@ -173,6 +216,35 @@ func (meta *predicateMetadata) AddPod(addedPod *v1.Pod, nodeInfo *schedulercache meta.matchingAntiAffinityTerms[addedPodFullName] = podMatchingTerms } } + // Add the pod to nodeNameToMatchingAffinityPods and nodeNameToMatchingAntiAffinityPods if needed. + affinity := meta.pod.Spec.Affinity + podNodeName := addedPod.Spec.NodeName + if affinity != nil && len(podNodeName) > 0 { + if targetPodMatchesAffinityOfPod(meta.pod, addedPod) { + found := false + for _, p := range meta.nodeNameToMatchingAffinityPods[podNodeName] { + if p == addedPod { + found = true + break + } + } + if !found { + meta.nodeNameToMatchingAffinityPods[podNodeName] = append(meta.nodeNameToMatchingAffinityPods[podNodeName], addedPod) + } + } + if targetPodMatchesAntiAffinityOfPod(meta.pod, addedPod) { + found := false + for _, p := range meta.nodeNameToMatchingAntiAffinityPods[podNodeName] { + if p == addedPod { + found = true + break + } + } + if !found { + meta.nodeNameToMatchingAntiAffinityPods[podNodeName] = append(meta.nodeNameToMatchingAntiAffinityPods[podNodeName], addedPod) + } + } + } // If addedPod is in the same namespace as the meta.pod, update the list // of matching pods if applicable. if meta.serviceAffinityInUse && addedPod.Namespace == meta.pod.Namespace { @@ -200,9 +272,162 @@ func (meta *predicateMetadata) ShallowCopy() algorithm.PredicateMetadata { for k, v := range meta.matchingAntiAffinityTerms { newPredMeta.matchingAntiAffinityTerms[k] = append([]matchingPodAntiAffinityTerm(nil), v...) } + newPredMeta.nodeNameToMatchingAffinityPods = make(map[string][]*v1.Pod) + for k, v := range meta.nodeNameToMatchingAffinityPods { + newPredMeta.nodeNameToMatchingAffinityPods[k] = append([]*v1.Pod(nil), v...) + } + newPredMeta.nodeNameToMatchingAntiAffinityPods = make(map[string][]*v1.Pod) + for k, v := range meta.nodeNameToMatchingAntiAffinityPods { + newPredMeta.nodeNameToMatchingAntiAffinityPods[k] = append([]*v1.Pod(nil), v...) + } newPredMeta.serviceAffinityMatchingPodServices = append([]*v1.Service(nil), meta.serviceAffinityMatchingPodServices...) newPredMeta.serviceAffinityMatchingPodList = append([]*v1.Pod(nil), meta.serviceAffinityMatchingPodList...) return (algorithm.PredicateMetadata)(newPredMeta) } + +type affinityTermProperties struct { + namespaces sets.String + selector labels.Selector +} + +// getAffinityTermProperties receives a Pod and affinity terms and returns the namespaces and +// selectors of the terms. +func getAffinityTermProperties(pod *v1.Pod, terms []v1.PodAffinityTerm) (properties []*affinityTermProperties, err error) { + if terms == nil { + return properties, nil + } + + for _, term := range terms { + namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(pod, &term) + selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector) + if err != nil { + return nil, err + } + properties = append(properties, &affinityTermProperties{namespaces: namespaces, selector: selector}) + } + return properties, nil +} + +// podMatchesAffinityTermProperties return true IFF the given pod matches all the given properties. +func podMatchesAffinityTermProperties(pod *v1.Pod, properties []*affinityTermProperties) bool { + if len(properties) == 0 { + return false + } + for _, property := range properties { + if !priorityutil.PodMatchesTermsNamespaceAndSelector(pod, property.namespaces, property.selector) { + return false + } + } + return true +} + +// getPodsMatchingAffinity finds existing Pods that match affinity terms of the given "pod". +// It ignores topology. It returns a set of Pods that are checked later by the affinity +// predicate. With this set of pods available, the affinity predicate does not +// need to check all the pods in the cluster. +func getPodsMatchingAffinity(pod *v1.Pod, nodeInfoMap map[string]*schedulercache.NodeInfo) (affinityPods map[string][]*v1.Pod, antiAffinityPods map[string][]*v1.Pod, err error) { + allNodeNames := make([]string, 0, len(nodeInfoMap)) + + affinity := pod.Spec.Affinity + if affinity == nil || (affinity.PodAffinity == nil && affinity.PodAntiAffinity == nil) { + return nil, nil, nil + } + + for name := range nodeInfoMap { + allNodeNames = append(allNodeNames, name) + } + + var lock sync.Mutex + var firstError error + affinityPods = make(map[string][]*v1.Pod) + antiAffinityPods = make(map[string][]*v1.Pod) + appendResult := func(nodeName string, affPods, antiAffPods []*v1.Pod) { + lock.Lock() + defer lock.Unlock() + if len(affPods) > 0 { + affinityPods[nodeName] = affPods + } + if len(antiAffPods) > 0 { + antiAffinityPods[nodeName] = antiAffPods + } + } + + catchError := func(err error) { + lock.Lock() + defer lock.Unlock() + if firstError == nil { + firstError = err + } + } + + affinityProperties, err := getAffinityTermProperties(pod, GetPodAffinityTerms(affinity.PodAffinity)) + if err != nil { + return nil, nil, err + } + antiAffinityProperties, err := getAffinityTermProperties(pod, GetPodAntiAffinityTerms(affinity.PodAntiAffinity)) + if err != nil { + return nil, nil, err + } + + processNode := func(i int) { + nodeInfo := nodeInfoMap[allNodeNames[i]] + node := nodeInfo.Node() + if node == nil { + catchError(fmt.Errorf("nodeInfo.Node is nil")) + return + } + affPods := make([]*v1.Pod, 0, len(nodeInfo.Pods())) + antiAffPods := make([]*v1.Pod, 0, len(nodeInfo.Pods())) + for _, existingPod := range nodeInfo.Pods() { + // Check affinity properties. + if podMatchesAffinityTermProperties(existingPod, affinityProperties) { + affPods = append(affPods, existingPod) + } + // Check anti-affinity properties. + if podMatchesAffinityTermProperties(existingPod, antiAffinityProperties) { + antiAffPods = append(antiAffPods, existingPod) + } + } + if len(antiAffPods) > 0 || len(affPods) > 0 { + appendResult(node.Name, affPods, antiAffPods) + } + } + workqueue.Parallelize(16, len(allNodeNames), processNode) + return affinityPods, antiAffinityPods, firstError +} + +// podMatchesAffinity returns true if "targetPod" matches any affinity rule of +// "pod". Similar to getPodsMatchingAffinity, this function does not check topology. +// So, whether the targetPod actually matches or not needs further checks for a specific +// node. +func targetPodMatchesAffinityOfPod(pod, targetPod *v1.Pod) bool { + affinity := pod.Spec.Affinity + if affinity == nil || affinity.PodAffinity == nil { + return false + } + affinityProperties, err := getAffinityTermProperties(pod, GetPodAffinityTerms(affinity.PodAffinity)) + if err != nil { + glog.Errorf("error in getting affinity properties of Pod %v", pod.Name) + return false + } + return podMatchesAffinityTermProperties(targetPod, affinityProperties) +} + +// targetPodMatchesAntiAffinityOfPod returns true if "targetPod" matches any anti-affinity +// rule of "pod". Similar to getPodsMatchingAffinity, this function does not check topology. +// So, whether the targetPod actually matches or not needs further checks for a specific +// node. +func targetPodMatchesAntiAffinityOfPod(pod, targetPod *v1.Pod) bool { + affinity := pod.Spec.Affinity + if affinity == nil || affinity.PodAntiAffinity == nil { + return false + } + properties, err := getAffinityTermProperties(pod, GetPodAntiAffinityTerms(affinity.PodAntiAffinity)) + if err != nil { + glog.Errorf("error in getting anti-affinity properties of Pod %v", pod.Name) + return false + } + return podMatchesAffinityTermProperties(targetPod, properties) +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/metadata_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/metadata_test.go index fab725d40..013d546e1 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/metadata_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/metadata_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -88,6 +88,13 @@ func (s sortableServices) Swap(i, j int) { s[i], s[j] = s[j], s[i] } var _ = sort.Interface(&sortableServices{}) +func sortNodePodMap(np map[string][]*v1.Pod) { + for _, pl := range np { + sortablePods := sortablePods(pl) + sort.Sort(sortablePods) + } +} + // predicateMetadataEquivalent returns true if the two metadata are equivalent. // Note: this function does not compare podRequest. func predicateMetadataEquivalent(meta1, meta2 *predicateMetadata) error { @@ -111,6 +118,16 @@ func predicateMetadataEquivalent(meta1, meta2 *predicateMetadata) error { if !reflect.DeepEqual(meta1.matchingAntiAffinityTerms, meta2.matchingAntiAffinityTerms) { return fmt.Errorf("matchingAntiAffinityTerms are not euqal") } + sortNodePodMap(meta1.nodeNameToMatchingAffinityPods) + sortNodePodMap(meta2.nodeNameToMatchingAffinityPods) + if !reflect.DeepEqual(meta1.nodeNameToMatchingAffinityPods, meta2.nodeNameToMatchingAffinityPods) { + return fmt.Errorf("nodeNameToMatchingAffinityPods are not euqal") + } + sortNodePodMap(meta1.nodeNameToMatchingAntiAffinityPods) + sortNodePodMap(meta2.nodeNameToMatchingAntiAffinityPods) + if !reflect.DeepEqual(meta1.nodeNameToMatchingAntiAffinityPods, meta2.nodeNameToMatchingAntiAffinityPods) { + return fmt.Errorf("nodeNameToMatchingAntiAffinityPods are not euqal") + } if meta1.serviceAffinityInUse { sortablePods1 := sortablePods(meta1.serviceAffinityMatchingPodList) sort.Sort(sortablePods1) @@ -189,6 +206,34 @@ func TestPredicateMetadata_AddRemovePod(t *testing.T) { }, }, } + affinityComplex := &v1.PodAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ + { + LabelSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "foo", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"bar", "buzz"}, + }, + }, + }, + TopologyKey: "region", + }, + { + LabelSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "service", + Operator: metav1.LabelSelectorOpNotIn, + Values: []string{"bar", "security", "test"}, + }, + }, + }, + TopologyKey: "zone", + }, + }, + } tests := []struct { description string @@ -312,6 +357,41 @@ func TestPredicateMetadata_AddRemovePod(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeC", Labels: label3}}, }, }, + { + description: "metadata matching pod affinity and anti-affinity are updated correctly after adding and removing a pod", + pendingPod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "pending", Labels: selector1}, + }, + existingPods: []*v1.Pod{ + {ObjectMeta: metav1.ObjectMeta{Name: "p1", Labels: selector1}, + Spec: v1.PodSpec{NodeName: "nodeA"}, + }, + {ObjectMeta: metav1.ObjectMeta{Name: "p2"}, + Spec: v1.PodSpec{ + NodeName: "nodeC", + Affinity: &v1.Affinity{ + PodAntiAffinity: antiAffinityFooBar, + PodAffinity: affinityComplex, + }, + }, + }, + }, + addedPod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "addedPod", Labels: selector1}, + Spec: v1.PodSpec{ + NodeName: "nodeA", + Affinity: &v1.Affinity{ + PodAntiAffinity: antiAffinityComplex, + }, + }, + }, + services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector1}}}, + nodes: []*v1.Node{ + {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: label1}}, + {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: label2}}, + {ObjectMeta: metav1.ObjectMeta{Name: "nodeC", Labels: label3}}, + }, + }, } for _, test := range tests { @@ -360,6 +440,7 @@ func TestPredicateMetadata_AddRemovePod(t *testing.T) { // on the idea that shallow-copy should produce an object that is deep-equal to the original // object. func TestPredicateMetadata_ShallowCopy(t *testing.T) { + selector1 := map[string]string{"foo": "bar"} source := predicateMetadata{ pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -392,6 +473,45 @@ func TestPredicateMetadata_ShallowCopy(t *testing.T) { }, }, }, + nodeNameToMatchingAffinityPods: map[string][]*v1.Pod{ + "nodeA": { + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p1", Labels: selector1}, + Spec: v1.PodSpec{NodeName: "nodeA"}, + }, + }, + "nodeC": { + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p2"}, + Spec: v1.PodSpec{ + NodeName: "nodeC", + }, + }, + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p6", Labels: selector1}, + Spec: v1.PodSpec{NodeName: "nodeC"}, + }, + }, + }, + nodeNameToMatchingAntiAffinityPods: map[string][]*v1.Pod{ + "nodeN": { + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p1", Labels: selector1}, + Spec: v1.PodSpec{NodeName: "nodeN"}, + }, + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p2"}, + Spec: v1.PodSpec{ + NodeName: "nodeM", + }, + }, + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p3"}, + Spec: v1.PodSpec{ + NodeName: "nodeM", + }, + }, + }, + "nodeM": { + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p6", Labels: selector1}, + Spec: v1.PodSpec{NodeName: "nodeM"}, + }, + }, + }, serviceAffinityInUse: true, serviceAffinityMatchingPodList: []*v1.Pod{ {ObjectMeta: metav1.ObjectMeta{Name: "pod1"}}, diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates.go index 217d1934a..aaf28f962 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates.go @@ -23,10 +23,13 @@ import ( "strconv" "sync" + "github.com/golang/glog" + "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/sets" @@ -40,12 +43,10 @@ import ( kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedutil "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" volumeutil "k8s.io/kubernetes/pkg/volume/util" - - "github.com/golang/glog" ) const ( @@ -89,6 +90,8 @@ const ( CheckNodeMemoryPressurePred = "CheckNodeMemoryPressure" // CheckNodeDiskPressurePred defines the name of predicate CheckNodeDiskPressure. CheckNodeDiskPressurePred = "CheckNodeDiskPressure" + // CheckNodePIDPressurePred defines the name of predicate CheckNodePIDPressure. + CheckNodePIDPressurePred = "CheckNodePIDPressure" // DefaultMaxEBSVolumes is the limit for volumes attached to an instance. // Amazon recommends no more than 40; the system root volume uses at least one. @@ -133,7 +136,7 @@ var ( PodToleratesNodeTaintsPred, PodToleratesNodeNoExecuteTaintsPred, CheckNodeLabelPresencePred, CheckServiceAffinityPred, MaxEBSVolumeCountPred, MaxGCEPDVolumeCountPred, MaxAzureDiskVolumeCountPred, CheckVolumeBindingPred, NoVolumeZoneConflictPred, - CheckNodeMemoryPressurePred, CheckNodeDiskPressurePred, MatchInterPodAffinityPred} + CheckNodeMemoryPressurePred, CheckNodePIDPressurePred, CheckNodeDiskPressurePred, MatchInterPodAffinityPred} ) // NodeInfo interface represents anything that can get node object from node ID. @@ -286,10 +289,11 @@ func NoDiskConflict(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *sch // MaxPDVolumeCountChecker contains information to check the max number of volumes for a predicate. type MaxPDVolumeCountChecker struct { - filter VolumeFilter - maxVolumes int - pvInfo PersistentVolumeInfo - pvcInfo PersistentVolumeClaimInfo + filter VolumeFilter + volumeLimitKey v1.ResourceName + maxVolumes int + pvInfo PersistentVolumeInfo + pvcInfo PersistentVolumeClaimInfo // The string below is generated randomly during the struct's initialization. // It is used to prefix volumeID generated inside the predicate() method to @@ -310,21 +314,25 @@ type VolumeFilter struct { // The predicate looks for both volumes used directly, as well as PVC volumes that are backed by relevant volume // types, counts the number of unique volumes, and rejects the new pod if it would place the total count over // the maximum. -func NewMaxPDVolumeCountPredicate(filterName string, pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo) algorithm.FitPredicate { - +func NewMaxPDVolumeCountPredicate( + filterName string, pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo) algorithm.FitPredicate { var filter VolumeFilter var maxVolumes int + var volumeLimitKey v1.ResourceName switch filterName { case EBSVolumeFilterType: filter = EBSVolumeFilter + volumeLimitKey = v1.ResourceName(volumeutil.EBSVolumeLimitKey) maxVolumes = getMaxVols(DefaultMaxEBSVolumes) case GCEPDVolumeFilterType: filter = GCEPDVolumeFilter + volumeLimitKey = v1.ResourceName(volumeutil.GCEVolumeLimitKey) maxVolumes = getMaxVols(DefaultMaxGCEPDVolumes) case AzureDiskVolumeFilterType: filter = AzureDiskVolumeFilter + volumeLimitKey = v1.ResourceName(volumeutil.AzureVolumeLimitKey) maxVolumes = getMaxVols(DefaultMaxAzureDiskVolumes) default: glog.Fatalf("Wrong filterName, Only Support %v %v %v ", EBSVolumeFilterType, @@ -334,6 +342,7 @@ func NewMaxPDVolumeCountPredicate(filterName string, pvInfo PersistentVolumeInfo } c := &MaxPDVolumeCountChecker{ filter: filter, + volumeLimitKey: volumeLimitKey, maxVolumes: maxVolumes, pvInfo: pvInfo, pvcInfo: pvcInfo, @@ -359,7 +368,6 @@ func getMaxVols(defaultVal int) int { } func (c *MaxPDVolumeCountChecker) filterVolumes(volumes []v1.Volume, namespace string, filteredVolumes map[string]bool) error { - for i := range volumes { vol := &volumes[i] if id, ok := c.filter.FilterVolume(vol); ok { @@ -446,12 +454,25 @@ func (c *MaxPDVolumeCountChecker) predicate(pod *v1.Pod, meta algorithm.Predicat } numNewVolumes := len(newVolumes) + maxAttachLimit := c.maxVolumes - if numExistingVolumes+numNewVolumes > c.maxVolumes { + if utilfeature.DefaultFeatureGate.Enabled(features.AttachVolumeLimit) { + volumeLimits := nodeInfo.VolumeLimits() + if maxAttachLimitFromAllocatable, ok := volumeLimits[c.volumeLimitKey]; ok { + maxAttachLimit = int(maxAttachLimitFromAllocatable) + } + } + + if numExistingVolumes+numNewVolumes > maxAttachLimit { // violates MaxEBSVolumeCount or MaxGCEPDVolumeCount return false, []algorithm.PredicateFailureReason{ErrMaxVolumeCountExceeded}, nil } - + if nodeInfo != nil && nodeInfo.TransientInfo != nil && utilfeature.DefaultFeatureGate.Enabled(features.BalanceAttachedNodeVolumes) { + nodeInfo.TransientInfo.TransientLock.Lock() + defer nodeInfo.TransientInfo.TransientLock.Unlock() + nodeInfo.TransientInfo.TransNodeInfo.AllocatableVolumesCount = maxAttachLimit - numExistingVolumes + nodeInfo.TransientInfo.TransNodeInfo.RequestedVolumes = numNewVolumes + } return true, nil, nil } @@ -584,9 +605,9 @@ func (c *VolumeZoneChecker) predicate(pod *v1.Pod, meta algorithm.PredicateMetad pvName := pvc.Spec.VolumeName if pvName == "" { if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - scName := pvc.Spec.StorageClassName - if scName != nil && len(*scName) > 0 { - class, _ := c.classInfo.GetStorageClassInfo(*scName) + scName := v1helper.GetPersistentVolumeClaimClass(pvc) + if len(scName) > 0 { + class, _ := c.classInfo.GetStorageClassInfo(scName) if class != nil { if class.VolumeBindingMode == nil { return false, nil, fmt.Errorf("VolumeBindingMode not set for StorageClass %q", scName) @@ -664,33 +685,7 @@ func GetResourceRequest(pod *v1.Pod) *schedulercache.Resource { // take max_resource(sum_pod, any_init_container) for _, container := range pod.Spec.InitContainers { - for rName, rQuantity := range container.Resources.Requests { - switch rName { - case v1.ResourceMemory: - if mem := rQuantity.Value(); mem > result.Memory { - result.Memory = mem - } - case v1.ResourceEphemeralStorage: - if ephemeralStorage := rQuantity.Value(); ephemeralStorage > result.EphemeralStorage { - result.EphemeralStorage = ephemeralStorage - } - case v1.ResourceCPU: - if cpu := rQuantity.MilliValue(); cpu > result.MilliCPU { - result.MilliCPU = cpu - } - case v1.ResourceNvidiaGPU: - if gpu := rQuantity.Value(); gpu > result.NvidiaGPU { - result.NvidiaGPU = gpu - } - default: - if v1helper.IsScalarResourceName(rName) { - value := rQuantity.Value() - if value > result.ScalarResources[rName] { - result.SetScalar(rName, value) - } - } - } - } + result.SetMaxResource(container.Resources.Requests) } return result @@ -730,7 +725,6 @@ func PodFitsResources(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *s } if podRequest.MilliCPU == 0 && podRequest.Memory == 0 && - podRequest.NvidiaGPU == 0 && podRequest.EphemeralStorage == 0 && len(podRequest.ScalarResources) == 0 { return len(predicateFails) == 0, predicateFails, nil @@ -743,10 +737,6 @@ func PodFitsResources(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *s if allocatable.Memory < podRequest.Memory+nodeInfo.RequestedResource().Memory { predicateFails = append(predicateFails, NewInsufficientResourceError(v1.ResourceMemory, podRequest.Memory, nodeInfo.RequestedResource().Memory, allocatable.Memory)) } - if allocatable.NvidiaGPU < podRequest.NvidiaGPU+nodeInfo.RequestedResource().NvidiaGPU { - predicateFails = append(predicateFails, NewInsufficientResourceError(v1.ResourceNvidiaGPU, podRequest.NvidiaGPU, nodeInfo.RequestedResource().NvidiaGPU, allocatable.NvidiaGPU)) - } - if allocatable.EphemeralStorage < podRequest.EphemeralStorage+nodeInfo.RequestedResource().EphemeralStorage { predicateFails = append(predicateFails, NewInsufficientResourceError(v1.ResourceEphemeralStorage, podRequest.EphemeralStorage, nodeInfo.RequestedResource().EphemeralStorage, allocatable.EphemeralStorage)) } @@ -778,21 +768,16 @@ func PodFitsResources(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *s // nodeMatchesNodeSelectorTerms checks if a node's labels satisfy a list of node selector terms, // terms are ORed, and an empty list of terms will match nothing. func nodeMatchesNodeSelectorTerms(node *v1.Node, nodeSelectorTerms []v1.NodeSelectorTerm) bool { - for _, req := range nodeSelectorTerms { - nodeSelector, err := v1helper.NodeSelectorRequirementsAsSelector(req.MatchExpressions) - if err != nil { - glog.V(10).Infof("Failed to parse MatchExpressions: %+v, regarding as not match.", req.MatchExpressions) - return false - } - if nodeSelector.Matches(labels.Set(node.Labels)) { - return true - } + nodeFields := map[string]string{} + for k, f := range algorithm.NodeFieldSelectorKeys { + nodeFields[k] = f(node) } - return false + return v1helper.MatchNodeSelectorTerms(nodeSelectorTerms, labels.Set(node.Labels), fields.Set(nodeFields)) } -// The pod can only schedule onto nodes that satisfy requirements in both NodeAffinity and nodeSelector. -func podMatchesNodeLabels(pod *v1.Pod, node *v1.Node) bool { +// podMatchesNodeSelectorAndAffinityTerms checks whether the pod is schedulable onto nodes according to +// the requirements in both NodeAffinity and nodeSelector. +func podMatchesNodeSelectorAndAffinityTerms(pod *v1.Pod, node *v1.Node) bool { // Check if node.Labels match pod.Spec.NodeSelector. if len(pod.Spec.NodeSelector) > 0 { selector := labels.SelectorFromSet(pod.Spec.NodeSelector) @@ -843,7 +828,7 @@ func PodMatchNodeSelector(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInf if node == nil { return false, nil, fmt.Errorf("node not found") } - if podMatchesNodeLabels(pod, node) { + if podMatchesNodeSelectorAndAffinityTerms(pod, node) { return true, nil, nil } return false, []algorithm.PredicateFailureReason{ErrNodeSelectorNotMatch}, nil @@ -1155,7 +1140,7 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm if affinity == nil || (affinity.PodAffinity == nil && affinity.PodAntiAffinity == nil) { return true, nil, nil } - if failedPredicates, error := c.satisfiesPodsAffinityAntiAffinity(pod, nodeInfo, affinity); failedPredicates != nil { + if failedPredicates, error := c.satisfiesPodsAffinityAntiAffinity(pod, meta, nodeInfo, affinity); failedPredicates != nil { failedPredicates := append([]algorithm.PredicateFailureReason{ErrPodAffinityNotMatch}, failedPredicates) return false, failedPredicates, error } @@ -1169,39 +1154,36 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm return true, nil, nil } -// anyPodMatchesPodAffinityTerm checks if any of given pods can match the specific podAffinityTerm. -// First return value indicates whether a matching pod exists on a node that matches the topology key, -// while the second return value indicates whether a matching pod exists anywhere. -// TODO: Do we really need any pod matching, or all pods matching? I think the latter. -func (c *PodAffinityChecker) anyPodMatchesPodAffinityTerm(pod *v1.Pod, pods []*v1.Pod, nodeInfo *schedulercache.NodeInfo, term *v1.PodAffinityTerm) (bool, bool, error) { - if len(term.TopologyKey) == 0 { - return false, false, fmt.Errorf("empty topologyKey is not allowed except for PreferredDuringScheduling pod anti-affinity") +// podMatchesPodAffinityTerms checks if the "targetPod" matches the given "terms" +// of the "pod" on the given "nodeInfo".Node(). It returns three values: 1) whether +// targetPod matches all the terms and their topologies, 2) whether targetPod +// matches all the terms label selector and namespaces (AKA term properties), +// 3) any error. +func (c *PodAffinityChecker) podMatchesPodAffinityTerms(pod *v1.Pod, targetPod *v1.Pod, nodeInfo *schedulercache.NodeInfo, terms []v1.PodAffinityTerm) (bool, bool, error) { + if len(terms) == 0 { + return false, false, fmt.Errorf("terms array is empty") } - matchingPodExists := false - namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(pod, term) - selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector) + props, err := getAffinityTermProperties(pod, terms) if err != nil { return false, false, err } - // Special case: When the topological domain is node, we can limit our - // search to pods on that node without searching the entire cluster. - if term.TopologyKey == kubeletapis.LabelHostname { - pods = nodeInfo.Pods() + if !podMatchesAffinityTermProperties(targetPod, props) { + return false, false, nil } - for _, existingPod := range pods { - match := priorityutil.PodMatchesTermsNamespaceAndSelector(existingPod, namespaces, selector) - if match { - matchingPodExists = true - existingPodNode, err := c.info.GetNodeInfo(existingPod.Spec.NodeName) - if err != nil { - return false, matchingPodExists, err - } - if priorityutil.NodesHaveSameTopologyKey(nodeInfo.Node(), existingPodNode, term.TopologyKey) { - return true, matchingPodExists, nil - } + // Namespace and selector of the terms have matched. Now we check topology of the terms. + targetPodNode, err := c.info.GetNodeInfo(targetPod.Spec.NodeName) + if err != nil { + return false, false, err + } + for _, term := range terms { + if len(term.TopologyKey) == 0 { + return false, false, fmt.Errorf("empty topologyKey is not allowed except for PreferredDuringScheduling pod anti-affinity") + } + if !priorityutil.NodesHaveSameTopologyKey(nodeInfo.Node(), targetPodNode, term.TopologyKey) { + return false, true, nil } } - return false, matchingPodExists, nil + return true, true, nil } // GetPodAffinityTerms gets pod affinity terms by a pod affinity object. @@ -1385,57 +1367,127 @@ func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta return nil, nil } +// anyPodsMatchingTopologyTerms checks whether any of the nodes given via +// "targetPods" matches topology of all the "terms" for the give "pod" and "nodeInfo". +func (c *PodAffinityChecker) anyPodsMatchingTopologyTerms(pod *v1.Pod, targetPods map[string][]*v1.Pod, nodeInfo *schedulercache.NodeInfo, terms []v1.PodAffinityTerm) (bool, error) { + for nodeName, targetPods := range targetPods { + targetPodNodeInfo, err := c.info.GetNodeInfo(nodeName) + if err != nil { + return false, err + } + if len(targetPods) > 0 { + allTermsMatched := true + for _, term := range terms { + if !priorityutil.NodesHaveSameTopologyKey(nodeInfo.Node(), targetPodNodeInfo, term.TopologyKey) { + allTermsMatched = false + break + } + } + if allTermsMatched { + // We have 1 or more pods on the target node that have already matched namespace and selector + // and all of the terms topologies matched the target node. So, there is at least 1 matching pod on the node. + return true, nil + } + } + } + return false, nil +} + // Checks if scheduling the pod onto this node would break any rules of this pod. -func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo, affinity *v1.Affinity) (algorithm.PredicateFailureReason, error) { +func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, + meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo, + affinity *v1.Affinity) (algorithm.PredicateFailureReason, error) { node := nodeInfo.Node() if node == nil { return ErrPodAffinityRulesNotMatch, fmt.Errorf("Node is nil") } - filteredPods, err := c.podLister.FilteredList(nodeInfo.Filter, labels.Everything()) - if err != nil { - return ErrPodAffinityRulesNotMatch, err - } + if predicateMeta, ok := meta.(*predicateMetadata); ok { + // Check all affinity terms. + matchingPods := predicateMeta.nodeNameToMatchingAffinityPods + if affinityTerms := GetPodAffinityTerms(affinity.PodAffinity); len(affinityTerms) > 0 { + matchExists, err := c.anyPodsMatchingTopologyTerms(pod, matchingPods, nodeInfo, affinityTerms) + if err != nil { + errMessage := fmt.Sprintf("Cannot schedule pod %+v onto node %v, because of PodAffinity, err: %v", podName(pod), node.Name, err) + glog.Errorf(errMessage) + return ErrPodAffinityRulesNotMatch, errors.New(errMessage) + } + if !matchExists { + // This pod may the first pod in a series that have affinity to themselves. In order + // to not leave such pods in pending state forever, we check that if no other pod + // in the cluster matches the namespace and selector of this pod and the pod matches + // its own terms, then we allow the pod to pass the affinity check. + if !(len(matchingPods) == 0 && targetPodMatchesAffinityOfPod(pod, pod)) { + glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAffinity", + podName(pod), node.Name) + return ErrPodAffinityRulesNotMatch, nil + } + } + } - // Check all affinity terms. - for _, term := range GetPodAffinityTerms(affinity.PodAffinity) { - termMatches, matchingPodExists, err := c.anyPodMatchesPodAffinityTerm(pod, filteredPods, nodeInfo, &term) + // Check all anti-affinity terms. + matchingPods = predicateMeta.nodeNameToMatchingAntiAffinityPods + if antiAffinityTerms := GetPodAntiAffinityTerms(affinity.PodAntiAffinity); len(antiAffinityTerms) > 0 { + matchExists, err := c.anyPodsMatchingTopologyTerms(pod, matchingPods, nodeInfo, antiAffinityTerms) + if err != nil || matchExists { + glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAntiAffinity, err: %v", + podName(pod), node.Name, err) + return ErrPodAntiAffinityRulesNotMatch, nil + } + } + } else { // We don't have precomputed metadata. We have to follow a slow path to check affinity rules. + filteredPods, err := c.podLister.FilteredList(nodeInfo.Filter, labels.Everything()) if err != nil { - errMessage := fmt.Sprintf("Cannot schedule pod %+v onto node %v, because of PodAffinityTerm %v, err: %v", podName(pod), node.Name, term, err) - glog.Error(errMessage) - return ErrPodAffinityRulesNotMatch, errors.New(errMessage) + return ErrPodAffinityRulesNotMatch, err } - if !termMatches { - // If the requirement matches a pod's own labels are namespace, and there are - // no other such pods, then disregard the requirement. This is necessary to - // not block forever because the first pod of the collection can't be scheduled. - if matchingPodExists { - glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAffinityTerm %v", - podName(pod), node.Name, term) - return ErrPodAffinityRulesNotMatch, nil - } - namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(pod, &term) - selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector) - if err != nil { - errMessage := fmt.Sprintf("Cannot parse selector on term %v for pod %v. Details %v", term, podName(pod), err) - glog.Error(errMessage) - return ErrPodAffinityRulesNotMatch, errors.New(errMessage) + + affinityTerms := GetPodAffinityTerms(affinity.PodAffinity) + antiAffinityTerms := GetPodAntiAffinityTerms(affinity.PodAntiAffinity) + matchFound, termsSelectorMatchFound := false, false + for _, targetPod := range filteredPods { + // Check all affinity terms. + if !matchFound && len(affinityTerms) > 0 { + affTermsMatch, termsSelectorMatch, err := c.podMatchesPodAffinityTerms(pod, targetPod, nodeInfo, affinityTerms) + if err != nil { + errMessage := fmt.Sprintf("Cannot schedule pod %+v onto node %v, because of PodAffinity, err: %v", podName(pod), node.Name, err) + glog.Error(errMessage) + return ErrPodAffinityRulesNotMatch, errors.New(errMessage) + } + if termsSelectorMatch { + termsSelectorMatchFound = true + } + if affTermsMatch { + matchFound = true + } } - match := priorityutil.PodMatchesTermsNamespaceAndSelector(pod, namespaces, selector) - if !match { - glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAffinityTerm %v", - podName(pod), node.Name, term) - return ErrPodAffinityRulesNotMatch, nil + + // Check all anti-affinity terms. + if len(antiAffinityTerms) > 0 { + antiAffTermsMatch, _, err := c.podMatchesPodAffinityTerms(pod, targetPod, nodeInfo, antiAffinityTerms) + if err != nil || antiAffTermsMatch { + glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAntiAffinityTerm, err: %v", + podName(pod), node.Name, err) + return ErrPodAntiAffinityRulesNotMatch, nil + } } } - } - // Check all anti-affinity terms. - for _, term := range GetPodAntiAffinityTerms(affinity.PodAntiAffinity) { - termMatches, _, err := c.anyPodMatchesPodAffinityTerm(pod, filteredPods, nodeInfo, &term) - if err != nil || termMatches { - glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAntiAffinityTerm %v, err: %v", - podName(pod), node.Name, term, err) - return ErrPodAntiAffinityRulesNotMatch, nil + if !matchFound && len(affinityTerms) > 0 { + // We have not been able to find any matches for the pod's affinity rules. + // This pod may be the first pod in a series that have affinity to themselves. In order + // to not leave such pods in pending state forever, we check that if no other pod + // in the cluster matches the namespace and selector of this pod and the pod matches + // its own terms, then we allow the pod to pass the affinity check. + if termsSelectorMatchFound { + glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAffinity", + podName(pod), node.Name) + return ErrPodAffinityRulesNotMatch, nil + } + // Check if pod matches its own affinity properties (namespace and label selector). + if !targetPodMatchesAffinityOfPod(pod, pod) { + glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAffinity", + podName(pod), node.Name) + return ErrPodAffinityRulesNotMatch, nil + } } } @@ -1529,6 +1581,16 @@ func CheckNodeDiskPressurePredicate(pod *v1.Pod, meta algorithm.PredicateMetadat return true, nil, nil } +// CheckNodePIDPressurePredicate checks if a pod can be scheduled on a node +// reporting pid pressure condition. +func CheckNodePIDPressurePredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { + // check if node is under pid pressure + if nodeInfo.PIDPressureCondition() == v1.ConditionTrue { + return false, []algorithm.PredicateFailureReason{ErrNodeUnderPIDPressure}, nil + } + return true, nil, nil +} + // CheckNodeConditionPredicate checks if a pod can be scheduled on a node reporting out of disk, // network unavailable and not ready condition. Only node conditions are accounted in this predicate. func CheckNodeConditionPredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates_test.go index d26eff918..b664590f3 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates_test.go @@ -32,23 +32,24 @@ import ( v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/scheduler/algorithm" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) var ( - extendedResourceA = v1.ResourceName("example.com/aaa") - extendedResourceB = v1.ResourceName("example.com/bbb") - hugePageResourceA = v1helper.HugePageResourceName(resource.MustParse("2Mi")) + extendedResourceA = v1.ResourceName("example.com/aaa") + extendedResourceB = v1.ResourceName("example.com/bbb") + kubernetesIOResourceA = v1.ResourceName("kubernetes.io/something") + kubernetesIOResourceB = v1.ResourceName("subdomain.kubernetes.io/something") + hugePageResourceA = v1helper.HugePageResourceName(resource.MustParse("2Mi")) ) -func makeResources(milliCPU, memory, nvidiaGPUs, pods, extendedA, storage, hugePageA int64) v1.NodeResources { +func makeResources(milliCPU, memory, pods, extendedA, storage, hugePageA int64) v1.NodeResources { return v1.NodeResources{ Capacity: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(milliCPU, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(memory, resource.BinarySI), v1.ResourcePods: *resource.NewQuantity(pods, resource.DecimalSI), - v1.ResourceNvidiaGPU: *resource.NewQuantity(nvidiaGPUs, resource.DecimalSI), extendedResourceA: *resource.NewQuantity(extendedA, resource.DecimalSI), v1.ResourceEphemeralStorage: *resource.NewQuantity(storage, resource.BinarySI), hugePageResourceA: *resource.NewQuantity(hugePageA, resource.BinarySI), @@ -56,12 +57,11 @@ func makeResources(milliCPU, memory, nvidiaGPUs, pods, extendedA, storage, hugeP } } -func makeAllocatableResources(milliCPU, memory, nvidiaGPUs, pods, extendedA, storage, hugePageA int64) v1.ResourceList { +func makeAllocatableResources(milliCPU, memory, pods, extendedA, storage, hugePageA int64) v1.ResourceList { return v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(milliCPU, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(memory, resource.BinarySI), v1.ResourcePods: *resource.NewQuantity(pods, resource.DecimalSI), - v1.ResourceNvidiaGPU: *resource.NewQuantity(nvidiaGPUs, resource.DecimalSI), extendedResourceA: *resource.NewQuantity(extendedA, resource.DecimalSI), v1.ResourceEphemeralStorage: *resource.NewQuantity(storage, resource.BinarySI), hugePageResourceA: *resource.NewQuantity(hugePageA, resource.BinarySI), @@ -297,6 +297,24 @@ func TestPodFitsResources(t *testing.T) { test: "extended resource allocatable enforced for unknown resource for init container", reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(extendedResourceB, 1, 0, 0)}, }, + { + pod: newResourcePod( + schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{kubernetesIOResourceA: 10}}), + nodeInfo: schedulercache.NewNodeInfo( + newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0})), + fits: false, + test: "kubernetes.io resource capacity enforced", + reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(kubernetesIOResourceA, 10, 0, 0)}, + }, + { + pod: newResourceInitPod(newResourcePod(schedulercache.Resource{}), + schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{kubernetesIOResourceB: 10}}), + nodeInfo: schedulercache.NewNodeInfo( + newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0})), + fits: false, + test: "kubernetes.io resource capacity enforced for init container", + reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(kubernetesIOResourceB, 10, 0, 0)}, + }, { pod: newResourcePod( schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 10}}), @@ -337,7 +355,7 @@ func TestPodFitsResources(t *testing.T) { } for _, test := range enoughPodsTests { - node := v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 0, 32, 5, 20, 5).Capacity, Allocatable: makeAllocatableResources(10, 20, 0, 32, 5, 20, 5)}} + node := v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 5, 20, 5).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 5, 20, 5)}} test.nodeInfo.SetNode(&node) RegisterPredicateMetadataProducerWithExtendedResourceOptions(test.ignoredExtendedResources) meta := PredicateMetadata(test.pod, nil) @@ -394,7 +412,7 @@ func TestPodFitsResources(t *testing.T) { }, } for _, test := range notEnoughPodsTests { - node := v1.Node{Status: v1.NodeStatus{Capacity: v1.ResourceList{}, Allocatable: makeAllocatableResources(10, 20, 0, 1, 0, 0, 0)}} + node := v1.Node{Status: v1.NodeStatus{Capacity: v1.ResourceList{}, Allocatable: makeAllocatableResources(10, 20, 1, 0, 0, 0)}} test.nodeInfo.SetNode(&node) fits, reasons, err := PodFitsResources(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { @@ -452,7 +470,7 @@ func TestPodFitsResources(t *testing.T) { } for _, test := range storagePodsTests { - node := v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 0, 32, 5, 20, 5).Capacity, Allocatable: makeAllocatableResources(10, 20, 0, 32, 5, 20, 5)}} + node := v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 5, 20, 5).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 5, 20, 5)}} test.nodeInfo.SetNode(&node) fits, reasons, err := PodFitsResources(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { @@ -893,10 +911,11 @@ func TestISCSIDiskConflicts(t *testing.T) { // TODO: Add test case for RequiredDuringSchedulingRequiredDuringExecution after it's implemented. func TestPodFitsSelector(t *testing.T) { tests := []struct { - pod *v1.Pod - labels map[string]string - fits bool - test string + pod *v1.Pod + labels map[string]string + nodeName string + fits bool + test string }{ { pod: &v1.Pod{}, @@ -1369,11 +1388,206 @@ func TestPodFitsSelector(t *testing.T) { fits: false, test: "Pod with an invalid value in Affinity term won't be scheduled onto the node", }, + { + pod: &v1.Pod{ + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + nodeName: "node_1", + fits: true, + test: "Pod with matchFields using In operator that matches the existing node", + }, + { + pod: &v1.Pod{ + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node_1"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + nodeName: "node_2", + fits: false, + test: "Pod with matchFields using In operator that does not match the existing node", + }, + { + pod: &v1.Pod{ + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node_1"}, + }, + }, + }, + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "foo", + Operator: v1.NodeSelectorOpIn, + Values: []string{"bar"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + nodeName: "node_2", + labels: map[string]string{"foo": "bar"}, + fits: true, + test: "Pod with two terms: matchFields does not match, but matchExpressions matches", + }, + { + pod: &v1.Pod{ + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node_1"}, + }, + }, + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "foo", + Operator: v1.NodeSelectorOpIn, + Values: []string{"bar"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + nodeName: "node_2", + labels: map[string]string{"foo": "bar"}, + fits: false, + test: "Pod with one term: matchFields does not match, but matchExpressions matches", + }, + { + pod: &v1.Pod{ + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node_1"}, + }, + }, + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "foo", + Operator: v1.NodeSelectorOpIn, + Values: []string{"bar"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + nodeName: "node_1", + labels: map[string]string{"foo": "bar"}, + fits: true, + test: "Pod with one term: both matchFields and matchExpressions match", + }, + { + pod: &v1.Pod{ + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node_1"}, + }, + }, + }, + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "foo", + Operator: v1.NodeSelectorOpIn, + Values: []string{"not-match-to-bar"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + nodeName: "node_2", + labels: map[string]string{"foo": "bar"}, + fits: false, + test: "Pod with two terms: both matchFields and matchExpressions do not match", + }, } expectedFailureReasons := []algorithm.PredicateFailureReason{ErrNodeSelectorNotMatch} for _, test := range tests { - node := v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: test.labels}} + node := v1.Node{ObjectMeta: metav1.ObjectMeta{ + Name: test.nodeName, + Labels: test.labels, + }} nodeInfo := schedulercache.NewNodeInfo() nodeInfo.SetNode(&node) @@ -1619,425 +1833,6 @@ func TestServiceAffinity(t *testing.T) { } } -func TestEBSVolumeCountConflicts(t *testing.T) { - oneVolPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"}, - }, - }, - }, - }, - } - ebsPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol", - }, - }, - }, - }, - }, - } - splitPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someNonEBSVol", - }, - }, - }, - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol", - }, - }, - }, - }, - }, - } - twoVolPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp1"}, - }, - }, - { - VolumeSource: v1.VolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp2"}, - }, - }, - }, - }, - } - splitVolsPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{}, - }, - }, - { - VolumeSource: v1.VolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "svp"}, - }, - }, - }, - }, - } - nonApplicablePod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{}, - }, - }, - }, - }, - } - deletedPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "deletedPVC", - }, - }, - }, - }, - }, - } - twoDeletedPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "deletedPVC", - }, - }, - }, - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "anotherDeletedPVC", - }, - }, - }, - }, - }, - } - deletedPVPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "pvcWithDeletedPV", - }, - }, - }, - }, - }, - } - // deletedPVPod2 is a different pod than deletedPVPod but using the same PVC - deletedPVPod2 := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "pvcWithDeletedPV", - }, - }, - }, - }, - }, - } - // anotherDeletedPVPod is a different pod than deletedPVPod and uses another PVC - anotherDeletedPVPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "anotherPVCWithDeletedPV", - }, - }, - }, - }, - }, - } - emptyPod := &v1.Pod{ - Spec: v1.PodSpec{}, - } - unboundPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "unboundPVC", - }, - }, - }, - }, - }, - } - // Different pod than unboundPVCPod, but using the same unbound PVC - unboundPVCPod2 := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "unboundPVC", - }, - }, - }, - }, - }, - } - - // pod with unbound PVC that's different to unboundPVC - anotherUnboundPVCPod := &v1.Pod{ - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "anotherUnboundPVC", - }, - }, - }, - }, - }, - } - - tests := []struct { - newPod *v1.Pod - existingPods []*v1.Pod - maxVols int - fits bool - test string - }{ - { - newPod: oneVolPod, - existingPods: []*v1.Pod{twoVolPod, oneVolPod}, - maxVols: 4, - fits: true, - test: "fits when node capacity >= new pod's EBS volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod}, - maxVols: 2, - fits: false, - test: "doesn't fit when node capacity < new pod's EBS volumes", - }, - { - newPod: splitVolsPod, - existingPods: []*v1.Pod{twoVolPod}, - maxVols: 3, - fits: true, - test: "new pod's count ignores non-EBS volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, - maxVols: 3, - fits: true, - test: "existing pods' counts ignore non-EBS volumes", - }, - { - newPod: ebsPVCPod, - existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod}, - maxVols: 3, - fits: true, - test: "new pod's count considers PVCs backed by EBS volumes", - }, - { - newPod: splitPVCPod, - existingPods: []*v1.Pod{splitVolsPod, oneVolPod}, - maxVols: 3, - fits: true, - test: "new pod's count ignores PVCs not backed by EBS volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod, ebsPVCPod}, - maxVols: 3, - fits: false, - test: "existing pods' counts considers PVCs backed by EBS volumes", - }, - { - newPod: twoVolPod, - existingPods: []*v1.Pod{oneVolPod, twoVolPod, ebsPVCPod}, - maxVols: 4, - fits: true, - test: "already-mounted EBS volumes are always ok to allow", - }, - { - newPod: splitVolsPod, - existingPods: []*v1.Pod{oneVolPod, oneVolPod, ebsPVCPod}, - maxVols: 3, - fits: true, - test: "the same EBS volumes are not counted multiple times", - }, - { - newPod: ebsPVCPod, - existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, - maxVols: 2, - fits: false, - test: "pod with missing PVC is counted towards the PV limit", - }, - { - newPod: ebsPVCPod, - existingPods: []*v1.Pod{oneVolPod, deletedPVCPod}, - maxVols: 3, - fits: true, - test: "pod with missing PVC is counted towards the PV limit", - }, - { - newPod: ebsPVCPod, - existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod}, - maxVols: 3, - fits: false, - test: "pod with missing two PVCs is counted towards the PV limit twice", - }, - { - newPod: ebsPVCPod, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - maxVols: 2, - fits: false, - test: "pod with missing PV is counted towards the PV limit", - }, - { - newPod: ebsPVCPod, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - maxVols: 3, - fits: true, - test: "pod with missing PV is counted towards the PV limit", - }, - { - newPod: deletedPVPod2, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - maxVols: 2, - fits: true, - test: "two pods missing the same PV are counted towards the PV limit only once", - }, - { - newPod: anotherDeletedPVPod, - existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, - maxVols: 2, - fits: false, - test: "two pods missing different PVs are counted towards the PV limit twice", - }, - { - newPod: ebsPVCPod, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - maxVols: 2, - fits: false, - test: "pod with unbound PVC is counted towards the PV limit", - }, - { - newPod: ebsPVCPod, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - maxVols: 3, - fits: true, - test: "pod with unbound PVC is counted towards the PV limit", - }, - { - newPod: unboundPVCPod2, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - maxVols: 2, - fits: true, - test: "the same unbound PVC in multiple pods is counted towards the PV limit only once", - }, - { - newPod: anotherUnboundPVCPod, - existingPods: []*v1.Pod{oneVolPod, unboundPVCPod}, - maxVols: 2, - fits: false, - test: "two different unbound PVCs are counted towards the PV limit as two volumes", - }, - } - - pvInfo := FakePersistentVolumeInfo{ - { - ObjectMeta: metav1.ObjectMeta{Name: "someEBSVol"}, - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{ - AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ebsVol"}, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "someNonEBSVol"}, - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{}, - }, - }, - } - - pvcInfo := FakePersistentVolumeClaimInfo{ - { - ObjectMeta: metav1.ObjectMeta{Name: "someEBSVol"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "someEBSVol"}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "someNonEBSVol"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "someNonEBSVol"}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "pvcWithDeletedPV"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "pvcWithDeletedPV"}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "anotherPVCWithDeletedPV"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "anotherPVCWithDeletedPV"}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "unboundPVC"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: ""}, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "anotherUnboundPVC"}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: ""}, - }, - } - - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrMaxVolumeCountExceeded} - - for _, test := range tests { - os.Setenv(KubeMaxPDVols, strconv.Itoa(test.maxVols)) - pred := NewMaxPDVolumeCountPredicate(EBSVolumeFilterType, pvInfo, pvcInfo) - fits, reasons, err := pred(test.newPod, PredicateMetadata(test.newPod, nil), schedulercache.NewNodeInfo(test.existingPods...)) - if err != nil { - t.Errorf("%s: unexpected error: %v", test.test, err) - } - if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) { - t.Errorf("%s: unexpected failure reasons: %v, want: %v", test.test, reasons, expectedFailureReasons) - } - if fits != test.fits { - t.Errorf("%s: expected %v, got %v", test.test, test.fits, fits) - } - } -} - func newPodWithPort(hostPorts ...int) *v1.Pod { networkPorts := []v1.ContainerPort{} for _, port := range hostPorts { @@ -2070,7 +1865,7 @@ func TestRunGeneralPredicates(t *testing.T) { newResourcePod(schedulercache.Resource{MilliCPU: 9, Memory: 19})), node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "machine1"}, - Status: v1.NodeStatus{Capacity: makeResources(10, 20, 0, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 0, 32, 0, 0, 0)}, + Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 0, 0, 0)}, }, fits: true, wErr: nil, @@ -2082,7 +1877,7 @@ func TestRunGeneralPredicates(t *testing.T) { newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 19})), node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "machine1"}, - Status: v1.NodeStatus{Capacity: makeResources(10, 20, 0, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 0, 32, 0, 0, 0)}, + Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 0, 0, 0)}, }, fits: false, wErr: nil, @@ -2092,34 +1887,6 @@ func TestRunGeneralPredicates(t *testing.T) { }, test: "not enough cpu and memory resource", }, - { - pod: &v1.Pod{}, - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 9, Memory: 19})), - node: &v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 1, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 1, 32, 0, 0, 0)}}, - fits: true, - wErr: nil, - test: "no resources/port/host requested always fits on GPU machine", - }, - { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 3, Memory: 1, NvidiaGPU: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 10, NvidiaGPU: 1})), - node: &v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 1, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 1, 32, 0, 0, 0)}}, - fits: false, - wErr: nil, - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourceNvidiaGPU, 1, 1, 1)}, - test: "not enough GPU resource", - }, - { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 3, Memory: 1, NvidiaGPU: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 10, NvidiaGPU: 0})), - node: &v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 1, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 1, 32, 0, 0, 0)}}, - fits: true, - wErr: nil, - test: "enough GPU resource", - }, { pod: &v1.Pod{ Spec: v1.PodSpec{ @@ -2129,7 +1896,7 @@ func TestRunGeneralPredicates(t *testing.T) { nodeInfo: schedulercache.NewNodeInfo(), node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "machine1"}, - Status: v1.NodeStatus{Capacity: makeResources(10, 20, 0, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 0, 32, 0, 0, 0)}, + Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 0, 0, 0)}, }, fits: false, wErr: nil, @@ -2141,7 +1908,7 @@ func TestRunGeneralPredicates(t *testing.T) { nodeInfo: schedulercache.NewNodeInfo(newPodWithPort(123)), node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "machine1"}, - Status: v1.NodeStatus{Capacity: makeResources(10, 20, 0, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 0, 32, 0, 0, 0)}, + Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 0, 0, 0)}, }, fits: false, wErr: nil, @@ -2831,7 +2598,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { }, }, pods: []*v1.Pod{ - {Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelA}}, + {Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Name: "p1", Labels: podLabelA}}, }, nodes: []v1.Node{ {ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, @@ -2903,7 +2670,8 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ - "foo": "bar", + "foo": "bar", + "service": "securityscan", }, }, Spec: v1.PodSpec{ @@ -2922,12 +2690,24 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { }, TopologyKey: "zone", }, + { + LabelSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "service", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"securityscan"}, + }, + }, + }, + TopologyKey: "zone", + }, }, }, }, }, }, - pods: []*v1.Pod{}, + pods: []*v1.Pod{{Spec: v1.PodSpec{NodeName: "nodeA"}, ObjectMeta: metav1.ObjectMeta{Name: "p1", Labels: map[string]string{"foo": "bar"}}}}, nodes: []v1.Node{ {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"zone": "az1", "hostname": "h1"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"zone": "az2", "hostname": "h2"}}}, @@ -2977,6 +2757,55 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { }, test: "NodeA and nodeB have same topologyKey and label value. NodeA has an existing pod that match the inter pod affinity rule. The pod can not be scheduled onto nodeA and nodeB.", }, + { + pod: &v1.Pod{ + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + PodAntiAffinity: &v1.PodAntiAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ + { + LabelSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "foo", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"abc"}, + }, + }, + }, + TopologyKey: "region", + }, + { + LabelSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "service", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"securityscan"}, + }, + }, + }, + TopologyKey: "zone", + }, + }, + }, + }, + }, + }, + pods: []*v1.Pod{ + {Spec: v1.PodSpec{NodeName: "nodeA"}, ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "abc", "service": "securityscan"}}}, + }, + nodes: []v1.Node{ + {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, + {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, + }, + nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}}, + fits: map[string]bool{ + "nodeA": false, + "nodeB": true, + }, + test: "This test ensures that anti-affinity matches a pod when all terms of the anti-affinity rule matches a pod.", + }, { pod: &v1.Pod{ Spec: v1.PodSpec{ @@ -3014,7 +2843,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { "nodeB": false, "nodeC": true, }, - test: "NodeA and nodeB have same topologyKey and label value. NodeA has an existing pod that match the inter pod affinity rule. The pod can not be scheduled onto nodeA and nodeB but can be schedulerd onto nodeC", + test: "NodeA and nodeB have same topologyKey and label value. NodeA has an existing pod that match the inter pod affinity rule. The pod can not be scheduled onto nodeA and nodeB but can be scheduled onto nodeC", }, { pod: &v1.Pod{ @@ -3162,7 +2991,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { "nodeB": false, "nodeC": true, }, - test: "NodeA and nodeB have same topologyKey and label value. NodeA has an existing pod that match the inter pod affinity rule. The pod can not be scheduled onto nodeA, nodeB, but can be schedulerd onto nodeC (NodeC has an existing pod that match the inter pod affinity rule but in different namespace)", + test: "NodeA and nodeB have same topologyKey and label value. NodeA has an existing pod that match the inter pod affinity rule. The pod can not be scheduled onto nodeA, nodeB, but can be scheduled onto nodeC (NodeC has an existing pod that match the inter pod affinity rule but in different namespace)", }, } @@ -3170,7 +2999,8 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { for indexTest, test := range tests { nodeListInfo := FakeNodeListInfo(test.nodes) - for indexNode, node := range test.nodes { + nodeInfoMap := make(map[string]*schedulercache.NodeInfo) + for i, node := range test.nodes { var podsOnNode []*v1.Pod for _, pod := range test.pods { if pod.Spec.NodeName == node.Name { @@ -3178,21 +3008,23 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { } } + nodeInfo := schedulercache.NewNodeInfo(podsOnNode...) + nodeInfo.SetNode(&test.nodes[i]) + nodeInfoMap[node.Name] = nodeInfo + } + + for indexNode, node := range test.nodes { testFit := PodAffinityChecker{ info: nodeListInfo, podLister: schedulertesting.FakePodLister(test.pods), } - nodeInfo := schedulercache.NewNodeInfo(podsOnNode...) - nodeInfo.SetNode(&node) - nodeInfoMap := map[string]*schedulercache.NodeInfo{node.Name: nodeInfo} var meta algorithm.PredicateMetadata - if !test.nometa { meta = PredicateMetadata(test.pod, nodeInfoMap) } - fits, reasons, _ := testFit.InterPodAffinityMatches(test.pod, meta, nodeInfo) + fits, reasons, _ := testFit.InterPodAffinityMatches(test.pod, meta, nodeInfoMap[node.Name]) if !fits && !reflect.DeepEqual(reasons, test.nodesExpectAffinityFailureReasons[indexNode]) { t.Errorf("index: %d test: %s unexpected failure reasons: %v expect: %v", indexTest, test.test, reasons, test.nodesExpectAffinityFailureReasons[indexNode]) } @@ -3451,7 +3283,7 @@ func TestPodSchedulesOnNodeWithMemoryPressureCondition(t *testing.T) { ImagePullPolicy: "Always", // at least one requirement -> burstable pod Resources: v1.ResourceRequirements{ - Requests: makeAllocatableResources(100, 100, 100, 100, 0, 0, 0), + Requests: makeAllocatableResources(100, 100, 100, 0, 0, 0), }, }, }, diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/utils.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/utils.go index 2e8761279..2b9c94f9d 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/utils.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/utils.go @@ -17,12 +17,8 @@ limitations under the License. package predicates import ( - "github.com/golang/glog" "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/kubernetes/pkg/scheduler/algorithm" schedutil "k8s.io/kubernetes/pkg/scheduler/util" ) @@ -70,69 +66,6 @@ func CreateSelectorFromLabels(aL map[string]string) labels.Selector { return labels.Set(aL).AsSelector() } -// EquivalencePodGenerator is a generator of equivalence class for pod with consideration of PVC info. -type EquivalencePodGenerator struct { - pvcInfo PersistentVolumeClaimInfo -} - -// NewEquivalencePodGenerator returns a getEquivalencePod method with consideration of PVC info. -func NewEquivalencePodGenerator(pvcInfo PersistentVolumeClaimInfo) algorithm.GetEquivalencePodFunc { - g := &EquivalencePodGenerator{ - pvcInfo: pvcInfo, - } - return g.getEquivalencePod -} - -// GetEquivalencePod returns a EquivalencePod which contains a group of pod attributes which can be reused. -func (e *EquivalencePodGenerator) getEquivalencePod(pod *v1.Pod) interface{} { - // For now we only consider pods: - // 1. OwnerReferences is Controller - // 2. with same OwnerReferences - // 3. with same PVC claim - // to be equivalent - for _, ref := range pod.OwnerReferences { - if ref.Controller != nil && *ref.Controller { - pvcSet, err := e.getPVCSet(pod) - if err == nil { - // A pod can only belongs to one controller, so let's return. - return &EquivalencePod{ - ControllerRef: ref, - PVCSet: pvcSet, - } - } - - // If error encountered, log warning and return nil (i.e. no equivalent pod found) - glog.Warningf("[EquivalencePodGenerator] for pod: %v failed due to: %v", pod.GetName(), err) - return nil - } - } - return nil -} - -// getPVCSet returns a set of PVC UIDs of given pod. -func (e *EquivalencePodGenerator) getPVCSet(pod *v1.Pod) (sets.String, error) { - result := sets.NewString() - for _, volume := range pod.Spec.Volumes { - if volume.PersistentVolumeClaim == nil { - continue - } - pvcName := volume.PersistentVolumeClaim.ClaimName - pvc, err := e.pvcInfo.GetPersistentVolumeClaimInfo(pod.GetNamespace(), pvcName) - if err != nil { - return nil, err - } - result.Insert(string(pvc.UID)) - } - - return result, nil -} - -// EquivalencePod is a group of pod attributes which can be reused as equivalence to schedule other pods. -type EquivalencePod struct { - ControllerRef metav1.OwnerReference - PVCSet sets.String -} - // portsConflict check whether existingPorts and wantPorts conflict with each other // return true if we have a conflict func portsConflict(existingPorts schedutil.HostPortInfo, wantPorts []*v1.ContainerPort) bool { diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/BUILD index 9012ddcb2..cb8f0e5c0 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/BUILD @@ -19,6 +19,7 @@ go_library( "node_label.go", "node_prefer_avoid_pods.go", "reduce.go", + "requested_to_capacity_ratio.go", "resource_allocation.go", "resource_limits.go", "selector_spreading.go", @@ -28,18 +29,21 @@ go_library( importpath = "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities", deps = [ "//pkg/apis/core/v1/helper:go_default_library", + "//pkg/features:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/util/node:go_default_library", + "//pkg/util/parsers:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_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/labels:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/util/workqueue:go_default_library", ], ) @@ -56,22 +60,27 @@ go_test( "node_affinity_test.go", "node_label_test.go", "node_prefer_avoid_pods_test.go", + "requested_to_capacity_ratio_test.go", "resource_limits_test.go", "selector_spreading_test.go", "taint_toleration_test.go", ], embed = [":go_default_library"], deps = [ + "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/testing:go_default_library", + "//pkg/util/parsers:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/apps/v1beta1: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/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go index 5f070caac..ec36f1bf7 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go @@ -19,8 +19,10 @@ package priorities import ( "math" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var ( @@ -36,17 +38,31 @@ var ( BalancedResourceAllocationMap = balancedResourcePriority.PriorityMap ) -func balancedResourceScorer(requested, allocable *schedulercache.Resource) int64 { +func balancedResourceScorer(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { cpuFraction := fractionOfCapacity(requested.MilliCPU, allocable.MilliCPU) memoryFraction := fractionOfCapacity(requested.Memory, allocable.Memory) + // This to find a node which has most balanced CPU, memory and volume usage. + if includeVolumes && utilfeature.DefaultFeatureGate.Enabled(features.BalanceAttachedNodeVolumes) && allocatableVolumes > 0 { + volumeFraction := float64(requestedVolumes) / float64(allocatableVolumes) + if cpuFraction >= 1 || memoryFraction >= 1 || volumeFraction >= 1 { + // if requested >= capacity, the corresponding host should never be preferred. + return 0 + } + // Compute variance for all the three fractions. + mean := (cpuFraction + memoryFraction + volumeFraction) / float64(3) + variance := float64((((cpuFraction - mean) * (cpuFraction - mean)) + ((memoryFraction - mean) * (memoryFraction - mean)) + ((volumeFraction - mean) * (volumeFraction - mean))) / float64(3)) + // Since the variance is between positive fractions, it will be positive fraction. 1-variance lets the + // score to be higher for node which has least variance and multiplying it with 10 provides the scaling + // factor needed. + return int64((1 - variance) * float64(schedulerapi.MaxPriority)) + } if cpuFraction >= 1 || memoryFraction >= 1 { // if requested >= capacity, the corresponding host should never be preferred. return 0 } - // Upper and lower boundary of difference between cpuFraction and memoryFraction are -1 and 1 - // respectively. Multilying the absolute value of the difference by 10 scales the value to + // respectively. Multiplying the absolute value of the difference by 10 scales the value to // 0-10 with 0 representing well balanced allocation and 10 poorly balanced. Subtracting it from // 10 leads to the score which also scales from 0 to 10 while 10 representing well balanced. diff := math.Abs(cpuFraction - memoryFraction) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go index 9b109d109..ae7b601b8 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go @@ -17,17 +17,118 @@ limitations under the License. package priorities import ( + "fmt" "reflect" "testing" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) +// getExistingVolumeCountForNode gets the current number of volumes on node. +func getExistingVolumeCountForNode(pods []*v1.Pod, maxVolumes int) int { + volumeCount := 0 + for _, pod := range pods { + volumeCount += len(pod.Spec.Volumes) + } + if maxVolumes-volumeCount > 0 { + return maxVolumes - volumeCount + } + return 0 +} + func TestBalancedResourceAllocation(t *testing.T) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) + podwithVol1 := v1.PodSpec{ + Containers: []v1.Container{ + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("1000m"), + v1.ResourceMemory: resource.MustParse("2000"), + }, + }, + }, + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("2000m"), + v1.ResourceMemory: resource.MustParse("3000"), + }, + }, + }, + }, + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"}, + }, + }, + }, + NodeName: "machine4", + } + podwithVol2 := v1.PodSpec{ + Containers: []v1.Container{ + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("0m"), + v1.ResourceMemory: resource.MustParse("0"), + }, + }, + }, + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("0m"), + v1.ResourceMemory: resource.MustParse("0"), + }, + }, + }, + }, + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp1"}, + }, + }, + }, + NodeName: "machine4", + } + podwithVol3 := v1.PodSpec{ + Containers: []v1.Container{ + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("0m"), + v1.ResourceMemory: resource.MustParse("0"), + }, + }, + }, + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("0m"), + v1.ResourceMemory: resource.MustParse("0"), + }, + }, + }, + }, + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp1"}, + }, + }, + }, + NodeName: "machine4", + } labels1 := map[string]string{ "foo": "bar", "baz": "blah", @@ -89,12 +190,33 @@ func TestBalancedResourceAllocation(t *testing.T) { }, }, } + cpuAndMemory3 := v1.PodSpec{ + NodeName: "machine3", + Containers: []v1.Container{ + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("1000m"), + v1.ResourceMemory: resource.MustParse("2000"), + }, + }, + }, + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("2000m"), + v1.ResourceMemory: resource.MustParse("3000"), + }, + }, + }, + }, + } tests := []struct { pod *v1.Pod pods []*v1.Pod nodes []*v1.Node expectedList schedulerapi.HostPriorityList - test string + name string }{ { /* @@ -111,7 +233,7 @@ func TestBalancedResourceAllocation(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "nothing scheduled, nothing requested", + name: "nothing scheduled, nothing requested", }, { /* @@ -128,7 +250,7 @@ func TestBalancedResourceAllocation(t *testing.T) { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 6000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 7}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "nothing scheduled, resources requested, differently sized machines", + name: "nothing scheduled, resources requested, differently sized machines", }, { /* @@ -145,7 +267,7 @@ func TestBalancedResourceAllocation(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "no resources requested, pods scheduled", + name: "no resources requested, pods scheduled", pods: []*v1.Pod{ {Spec: machine1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, {Spec: machine1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -168,7 +290,7 @@ func TestBalancedResourceAllocation(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 20000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 4}, {Host: "machine2", Score: 6}}, - test: "no resources requested, pods scheduled with resources", + name: "no resources requested, pods scheduled with resources", pods: []*v1.Pod{ {Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, {Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -191,7 +313,7 @@ func TestBalancedResourceAllocation(t *testing.T) { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 20000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 6}, {Host: "machine2", Score: 9}}, - test: "resources requested, pods scheduled with resources", + name: "resources requested, pods scheduled with resources", pods: []*v1.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, @@ -212,7 +334,7 @@ func TestBalancedResourceAllocation(t *testing.T) { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 50000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 6}, {Host: "machine2", Score: 6}}, - test: "resources requested, pods scheduled with resources, differently sized machines", + name: "resources requested, pods scheduled with resources, differently sized machines", pods: []*v1.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, @@ -233,7 +355,7 @@ func TestBalancedResourceAllocation(t *testing.T) { pod: &v1.Pod{Spec: cpuOnly}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}}, - test: "requested resources exceed node capacity", + name: "requested resources exceed node capacity", pods: []*v1.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, @@ -243,22 +365,57 @@ func TestBalancedResourceAllocation(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 0, 0), makeNode("machine2", 0, 0)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}}, - test: "zero node resources, pods scheduled with resources", + name: "zero node resources, pods scheduled with resources", pods: []*v1.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, }, }, + { + /* + Machine4 will be chosen here because it already has a existing volume making the variance + of volume count, CPU usage, memory usage closer. + */ + pod: &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp2"}, + }, + }, + }, + }, + }, + nodes: []*v1.Node{makeNode("machine3", 3500, 40000), makeNode("machine4", 4000, 10000)}, + expectedList: []schedulerapi.HostPriority{{Host: "machine3", Score: 8}, {Host: "machine4", Score: 9}}, + name: "Include volume count on a node for balanced resource allocation", + pods: []*v1.Pod{ + {Spec: cpuAndMemory3}, + {Spec: podwithVol1}, + {Spec: podwithVol2}, + {Spec: podwithVol3}, + }, + }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) - list, err := priorityFunction(BalancedResourceAllocationMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedList, list) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + if len(test.pod.Spec.Volumes) > 0 { + maxVolumes := 5 + for _, info := range nodeNameToInfo { + info.TransientInfo.TransNodeInfo.AllocatableVolumesCount = getExistingVolumeCountForNode(info.Pods(), maxVolumes) + info.TransientInfo.TransNodeInfo.RequestedVolumes = len(test.pod.Spec.Volumes) + } + } + list, err := priorityFunction(BalancedResourceAllocationMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/image_locality.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/image_locality.go index 5df5d3530..2d399469d 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/image_locality.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/image_locality.go @@ -18,10 +18,12 @@ package priorities import ( "fmt" + "strings" "k8s.io/api/core/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + "k8s.io/kubernetes/pkg/util/parsers" ) // This is a reasonable size range of all container images. 90%ile of images on dockerhub drops into this range. @@ -42,7 +44,7 @@ func ImageLocalityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *scheduler return schedulerapi.HostPriority{}, fmt.Errorf("node not found") } - sumSize := totalImageSize(node, pod.Spec.Containers) + sumSize := totalImageSize(nodeInfo, pod.Spec.Containers) return schedulerapi.HostPriority{ Host: node.Name, @@ -69,20 +71,27 @@ func calculateScoreFromSize(sumSize int64) int { } // totalImageSize returns the total image size of all the containers that are already on the node. -func totalImageSize(node *v1.Node, containers []v1.Container) int64 { - imageSizes := make(map[string]int64) - for _, image := range node.Status.Images { - for _, name := range image.Names { - imageSizes[name] = image.SizeBytes - } - } - +func totalImageSize(nodeInfo *schedulercache.NodeInfo, containers []v1.Container) int64 { var total int64 + + imageSizes := nodeInfo.ImageSizes() for _, container := range containers { - if size, ok := imageSizes[container.Image]; ok { + if size, ok := imageSizes[normalizedImageName(container.Image)]; ok { total += size } } return total } + +// normalizedImageName returns the CRI compliant name for a given image. +// TODO: cover the corner cases of missed matches, e.g, +// 1. Using Docker as runtime and docker.io/library/test:tag in pod spec, but only test:tag will present in node status +// 2. Using the implicit registry, i.e., test:tag or library/test:tag in pod spec but only docker.io/library/test:tag +// in node status; note that if users consistently use one registry format, this should not happen. +func normalizedImageName(name string) string { + if strings.LastIndex(name, ":") <= strings.LastIndex(name, "/") { + name = name + ":" + parsers.DefaultImageTag + } + return name +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/image_locality_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/image_locality_test.go index dd7637184..a8f76a03d 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/image_locality_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/image_locality_test.go @@ -17,14 +17,17 @@ limitations under the License. package priorities import ( + "crypto/sha256" "reflect" "sort" "testing" + "encoding/hex" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + "k8s.io/kubernetes/pkg/util/parsers" ) func TestImageLocalityPriority(t *testing.T) { @@ -65,7 +68,7 @@ func TestImageLocalityPriority(t *testing.T) { Images: []v1.ContainerImage{ { Names: []string{ - "gcr.io/40", + "gcr.io/40:" + parsers.DefaultImageTag, "gcr.io/40:v1", "gcr.io/40:v1", }, @@ -73,14 +76,14 @@ func TestImageLocalityPriority(t *testing.T) { }, { Names: []string{ - "gcr.io/140", + "gcr.io/140:" + parsers.DefaultImageTag, "gcr.io/140:v1", }, SizeBytes: int64(140 * mb), }, { Names: []string{ - "gcr.io/2000", + "gcr.io/2000:" + parsers.DefaultImageTag, }, SizeBytes: int64(2000 * mb), }, @@ -91,13 +94,13 @@ func TestImageLocalityPriority(t *testing.T) { Images: []v1.ContainerImage{ { Names: []string{ - "gcr.io/250", + "gcr.io/250:" + parsers.DefaultImageTag, }, SizeBytes: int64(250 * mb), }, { Names: []string{ - "gcr.io/10", + "gcr.io/10:" + parsers.DefaultImageTag, "gcr.io/10:v1", }, SizeBytes: int64(10 * mb), @@ -110,28 +113,28 @@ func TestImageLocalityPriority(t *testing.T) { pods []*v1.Pod nodes []*v1.Node expectedList schedulerapi.HostPriorityList - test string + name string }{ { // Pod: gcr.io/40 gcr.io/250 // Node1 - // Image: gcr.io/40 40MB + // Image: gcr.io/40:latest 40MB // Score: (40M-23M)/97.7M + 1 = 1 // Node2 - // Image: gcr.io/250 250MB + // Image: gcr.io/250:latest 250MB // Score: (250M-23M)/97.7M + 1 = 3 pod: &v1.Pod{Spec: test40250}, nodes: []*v1.Node{makeImageNode("machine1", node401402000), makeImageNode("machine2", node25010)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 1}, {Host: "machine2", Score: 3}}, - test: "two images spread on two nodes, prefer the larger image one", + name: "two images spread on two nodes, prefer the larger image one", }, { // Pod: gcr.io/40 gcr.io/140 // Node1 - // Image: gcr.io/40 40MB, gcr.io/140 140MB + // Image: gcr.io/40:latest 40MB, gcr.io/140:latest 140MB // Score: (40M+140M-23M)/97.7M + 1 = 2 // Node2 @@ -140,37 +143,56 @@ func TestImageLocalityPriority(t *testing.T) { pod: &v1.Pod{Spec: test40140}, nodes: []*v1.Node{makeImageNode("machine1", node401402000), makeImageNode("machine2", node25010)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 2}, {Host: "machine2", Score: 0}}, - test: "two images on one node, prefer this node", + name: "two images on one node, prefer this node", }, { // Pod: gcr.io/2000 gcr.io/10 // Node1 - // Image: gcr.io/2000 2000MB + // Image: gcr.io/2000:latest 2000MB // Score: 2000 > max score = 10 // Node2 - // Image: gcr.io/10 10MB + // Image: gcr.io/10:latest 10MB // Score: 10 < min score = 0 pod: &v1.Pod{Spec: testMinMax}, nodes: []*v1.Node{makeImageNode("machine1", node401402000), makeImageNode("machine2", node25010)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}}, - test: "if exceed limit, use limit", + name: "if exceed limit, use limit", }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) - list, err := priorityFunction(ImageLocalityPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - sort.Sort(test.expectedList) - sort.Sort(list) + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + list, err := priorityFunction(ImageLocalityPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + sort.Sort(test.expectedList) + sort.Sort(list) + + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) + } +} - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedList, list) +func TestNormalizedImageName(t *testing.T) { + for _, testCase := range []struct { + Input string + Output string + }{ + {Input: "root", Output: "root:latest"}, + {Input: "root:tag", Output: "root:tag"}, + {Input: "gcr.io:5000/root", Output: "gcr.io:5000/root:latest"}, + {Input: "root@" + getImageFakeDigest("root"), Output: "root@" + getImageFakeDigest("root")}, + } { + image := normalizedImageName(testCase.Input) + if image != testCase.Output { + t.Errorf("expected image reference: %q, got %q", testCase.Output, image) } } } @@ -181,3 +203,8 @@ func makeImageNode(node string, status v1.NodeStatus) *v1.Node { Status: status, } } + +func getImageFakeDigest(fakeContent string) string { + hash := sha256.Sum256([]byte(fakeContent)) + return "sha256:" + hex.EncodeToString(hash[:]) +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/interpod_affinity.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/interpod_affinity.go index f3e9c9647..6aa5a3896 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/interpod_affinity.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/interpod_affinity.go @@ -27,7 +27,7 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "github.com/golang/glog" ) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go index 6987e1d9e..7f86006d5 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -267,7 +267,7 @@ func TestInterPodAffinityPriority(t *testing.T) { pods []*v1.Pod nodes []*v1.Node expectedList schedulerapi.HostPriorityList - test string + name string }{ { pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, @@ -277,7 +277,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}}, - test: "all machines are same priority as Affinity is nil", + name: "all machines are same priority as Affinity is nil", }, // the node(machine1) that have the label {"region": "China"} (match the topology key) and that have existing pods that match the labelSelector get high score // the node(machine3) that don't have the label {"region": "whatever the value is"} (mismatch the topology key) but that have existing pods that match the labelSelector get low score @@ -295,7 +295,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}}, - test: "Affinity: pod that matches topology key & pods in nodes will get high score comparing to others" + + name: "Affinity: pod that matches topology key & pods in nodes will get high score comparing to others" + "which doesn't match either pods in nodes or in topology key", }, // the node1(machine1) that have the label {"region": "China"} (match the topology key) and that have existing pods that match the labelSelector get high score @@ -313,7 +313,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelRgIndia}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: 0}}, - test: "All the nodes that have the same topology key & label value with one of them has an existing pod that match the affinity rules, have the same score", + name: "All the nodes that have the same topology key & label value with one of them has an existing pod that match the affinity rules, have the same score", }, // there are 2 regions, say regionChina(machine1,machine3,machine4) and regionIndia(machine2,machine5), both regions have nodes that match the preference. // But there are more nodes(actually more existing pods) in regionChina that match the preference than regionIndia. @@ -337,7 +337,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine5", Labels: labelRgIndia}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 5}, {Host: "machine3", Score: schedulerapi.MaxPriority}, {Host: "machine4", Score: schedulerapi.MaxPriority}, {Host: "machine5", Score: 5}}, - test: "Affinity: nodes in one region has more matching pods comparing to other reqion, so the region which has more macthes will get high score", + name: "Affinity: nodes in one region has more matching pods comparing to other reqion, so the region which has more macthes will get high score", }, // Test with the different operators and values for pod affinity scheduling preference, including some match failures. { @@ -353,7 +353,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 2}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: 0}}, - test: "Affinity: different Label operators and values for pod affinity scheduling preference, including some match failures ", + name: "Affinity: different Label operators and values for pod affinity scheduling preference, including some match failures ", }, // Test the symmetry cases for affinity, the difference between affinity and symmetry is not the pod wants to run together with some existing pods, // but the existing pods have the inter pod affinity preference while the pod to schedule satisfy the preference. @@ -369,7 +369,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: 0}}, - test: "Affinity symmetry: considred only the preferredDuringSchedulingIgnoredDuringExecution in pod affinity symmetry", + name: "Affinity symmetry: considred only the preferredDuringSchedulingIgnoredDuringExecution in pod affinity symmetry", }, { pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, @@ -383,7 +383,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: 0}}, - test: "Affinity symmetry: considred RequiredDuringSchedulingIgnoredDuringExecution in pod affinity symmetry", + name: "Affinity symmetry: considred RequiredDuringSchedulingIgnoredDuringExecution in pod affinity symmetry", }, // The pod to schedule prefer to stay away from some existing pods at node level using the pod anti affinity. @@ -403,7 +403,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgChina}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "Anti Affinity: pod that doesnot match existing pods in node will get high score ", + name: "Anti Affinity: pod that doesnot match existing pods in node will get high score ", }, { pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, @@ -416,7 +416,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgChina}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "Anti Affinity: pod that does not matches topology key & matches the pods in nodes will get higher score comparing to others ", + name: "Anti Affinity: pod that does not matches topology key & matches the pods in nodes will get higher score comparing to others ", }, { pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, @@ -430,7 +430,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "Anti Affinity: one node has more matching pods comparing to other node, so the node which has more unmacthes will get high score", + name: "Anti Affinity: one node has more matching pods comparing to other node, so the node which has more unmacthes will get high score", }, // Test the symmetry cases for anti affinity { @@ -444,7 +444,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelAzAz2}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "Anti Affinity symmetry: the existing pods in node which has anti affinity match will get high score", + name: "Anti Affinity symmetry: the existing pods in node which has anti affinity match will get high score", }, // Test both affinity and anti-affinity { @@ -458,7 +458,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelAzAz1}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}}, - test: "Affinity and Anti Affinity: considered only preferredDuringSchedulingIgnoredDuringExecution in both pod affinity & anti affinity", + name: "Affinity and Anti Affinity: considered only preferredDuringSchedulingIgnoredDuringExecution in both pod affinity & anti affinity", }, // Combined cases considering both affinity and anti-affinity, the pod to schedule and existing pods have the same labels (they are in the same RC/service), // the pod prefer to run together with its brother pods in the same region, but wants to stay away from them at node level, @@ -483,7 +483,7 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine5", Labels: labelRgIndia}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 4}, {Host: "machine3", Score: schedulerapi.MaxPriority}, {Host: "machine4", Score: schedulerapi.MaxPriority}, {Host: "machine5", Score: 4}}, - test: "Affinity and Anti Affinity: considering both affinity and anti-affinity, the pod to schedule and existing pods have the same labels", + name: "Affinity and Anti Affinity: considering both affinity and anti-affinity, the pod to schedule and existing pods have the same labels", }, // Consider Affinity, Anti Affinity and symmetry together. // for Affinity, the weights are: 8, 0, 0, 0 @@ -505,24 +505,26 @@ func TestInterPodAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine4", Labels: labelAzAz2}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: schedulerapi.MaxPriority}, {Host: "machine4", Score: 0}}, - test: "Affinity and Anti Affinity and symmetry: considered only preferredDuringSchedulingIgnoredDuringExecution in both pod affinity & anti affinity & symmetry", + name: "Affinity and Anti Affinity and symmetry: considered only preferredDuringSchedulingIgnoredDuringExecution in both pod affinity & anti affinity & symmetry", }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) - interPodAffinity := InterPodAffinity{ - info: FakeNodeListInfo(test.nodes), - nodeLister: schedulertesting.FakeNodeLister(test.nodes), - podLister: schedulertesting.FakePodLister(test.pods), - hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight, - } - list, err := interPodAffinity.CalculateInterPodAffinityPriority(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: \nexpected \n\t%#v, \ngot \n\t%#v\n", test.test, test.expectedList, list) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + interPodAffinity := InterPodAffinity{ + info: FakeNodeListInfo(test.nodes), + nodeLister: schedulertesting.FakeNodeLister(test.nodes), + podLister: schedulertesting.FakePodLister(test.pods), + hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight, + } + list, err := interPodAffinity.CalculateInterPodAffinityPriority(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected \n\t%#v, \ngot \n\t%#v\n", test.expectedList, list) + } + }) } } @@ -563,7 +565,7 @@ func TestHardPodAffinitySymmetricWeight(t *testing.T) { nodes []*v1.Node hardPodAffinityWeight int32 expectedList schedulerapi.HostPriorityList - test string + name string }{ { pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelServiceS1}}, @@ -578,7 +580,7 @@ func TestHardPodAffinitySymmetricWeight(t *testing.T) { }, hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: 0}}, - test: "Hard Pod Affinity symmetry: hard pod affinity symmetry weights 1 by default, then nodes that match the hard pod affinity symmetry rules, get a high score", + name: "Hard Pod Affinity symmetry: hard pod affinity symmetry weights 1 by default, then nodes that match the hard pod affinity symmetry rules, get a high score", }, { pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelServiceS1}}, @@ -593,23 +595,25 @@ func TestHardPodAffinitySymmetricWeight(t *testing.T) { }, hardPodAffinityWeight: 0, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}}, - test: "Hard Pod Affinity symmetry: hard pod affinity symmetry is closed(weights 0), then nodes that match the hard pod affinity symmetry rules, get same score with those not match", + name: "Hard Pod Affinity symmetry: hard pod affinity symmetry is closed(weights 0), then nodes that match the hard pod affinity symmetry rules, get same score with those not match", }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) - ipa := InterPodAffinity{ - info: FakeNodeListInfo(test.nodes), - nodeLister: schedulertesting.FakeNodeLister(test.nodes), - podLister: schedulertesting.FakePodLister(test.pods), - hardPodAffinityWeight: test.hardPodAffinityWeight, - } - list, err := ipa.CalculateInterPodAffinityPriority(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: \nexpected \n\t%#v, \ngot \n\t%#v\n", test.test, test.expectedList, list) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + ipa := InterPodAffinity{ + info: FakeNodeListInfo(test.nodes), + nodeLister: schedulertesting.FakeNodeLister(test.nodes), + podLister: schedulertesting.FakePodLister(test.pods), + hardPodAffinityWeight: test.hardPodAffinityWeight, + } + list, err := ipa.CalculateInterPodAffinityPriority(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected \n\t%#v, \ngot \n\t%#v\n", test.expectedList, list) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/least_requested.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/least_requested.go index 33d6e5a6c..9f8b78dae 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/least_requested.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/least_requested.go @@ -18,7 +18,7 @@ package priorities import ( schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var ( @@ -33,7 +33,7 @@ var ( LeastRequestedPriorityMap = leastResourcePriority.PriorityMap ) -func leastResourceScorer(requested, allocable *schedulercache.Resource) int64 { +func leastResourceScorer(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { return (leastRequestedScore(requested.MilliCPU, allocable.MilliCPU) + leastRequestedScore(requested.Memory, allocable.Memory)) / 2 } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/least_requested_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/least_requested_test.go index 3b5308d7b..ca9d569bf 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/least_requested_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/least_requested_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestLeastRequested(t *testing.T) { @@ -94,7 +94,7 @@ func TestLeastRequested(t *testing.T) { pods []*v1.Pod nodes []*v1.Node expectedList schedulerapi.HostPriorityList - test string + name string }{ { /* @@ -111,7 +111,7 @@ func TestLeastRequested(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "nothing scheduled, nothing requested", + name: "nothing scheduled, nothing requested", }, { /* @@ -128,7 +128,7 @@ func TestLeastRequested(t *testing.T) { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 6000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 3}, {Host: "machine2", Score: 5}}, - test: "nothing scheduled, resources requested, differently sized machines", + name: "nothing scheduled, resources requested, differently sized machines", }, { /* @@ -145,7 +145,7 @@ func TestLeastRequested(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "no resources requested, pods scheduled", + name: "no resources requested, pods scheduled", pods: []*v1.Pod{ {Spec: machine1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, {Spec: machine1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -168,7 +168,7 @@ func TestLeastRequested(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 20000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 7}, {Host: "machine2", Score: 5}}, - test: "no resources requested, pods scheduled with resources", + name: "no resources requested, pods scheduled with resources", pods: []*v1.Pod{ {Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, {Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -191,7 +191,7 @@ func TestLeastRequested(t *testing.T) { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 20000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 5}, {Host: "machine2", Score: 4}}, - test: "resources requested, pods scheduled with resources", + name: "resources requested, pods scheduled with resources", pods: []*v1.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, @@ -212,7 +212,7 @@ func TestLeastRequested(t *testing.T) { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 50000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 5}, {Host: "machine2", Score: 6}}, - test: "resources requested, pods scheduled with resources, differently sized machines", + name: "resources requested, pods scheduled with resources, differently sized machines", pods: []*v1.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, @@ -233,7 +233,7 @@ func TestLeastRequested(t *testing.T) { pod: &v1.Pod{Spec: cpuOnly}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 5}, {Host: "machine2", Score: 2}}, - test: "requested resources exceed node capacity", + name: "requested resources exceed node capacity", pods: []*v1.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, @@ -243,7 +243,7 @@ func TestLeastRequested(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 0, 0), makeNode("machine2", 0, 0)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}}, - test: "zero node resources, pods scheduled with resources", + name: "zero node resources, pods scheduled with resources", pods: []*v1.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, @@ -252,13 +252,15 @@ func TestLeastRequested(t *testing.T) { } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) - list, err := priorityFunction(LeastRequestedPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedList, list) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + list, err := priorityFunction(LeastRequestedPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/metadata.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/metadata.go index da88a9f3a..3cb0f2f44 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/metadata.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/metadata.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/kubernetes/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // PriorityMetadataFactory is a factory to produce PriorityMetadata. diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/metadata_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/metadata_test.go index be354217a..19bde2d9b 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/metadata_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/metadata_test.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -117,13 +117,13 @@ func TestPriorityMetadata(t *testing.T) { } tests := []struct { pod *v1.Pod - test string + name string expected interface{} }{ { pod: nil, expected: nil, - test: "pod is nil , priorityMetadata is nil", + name: "pod is nil , priorityMetadata is nil", }, { pod: podWithTolerationsAndAffinity, @@ -132,7 +132,7 @@ func TestPriorityMetadata(t *testing.T) { podTolerations: tolerations, affinity: podAffinity, }, - test: "Produce a priorityMetadata with default requests", + name: "Produce a priorityMetadata with default requests", }, { pod: podWithTolerationsAndRequests, @@ -141,7 +141,7 @@ func TestPriorityMetadata(t *testing.T) { podTolerations: tolerations, affinity: nil, }, - test: "Produce a priorityMetadata with specified requests", + name: "Produce a priorityMetadata with specified requests", }, { pod: podWithAffinityAndRequests, @@ -150,7 +150,7 @@ func TestPriorityMetadata(t *testing.T) { podTolerations: nil, affinity: podAffinity, }, - test: "Produce a priorityMetadata with specified requests", + name: "Produce a priorityMetadata with specified requests", }, } mataDataProducer := NewPriorityMetadataFactory( @@ -159,9 +159,11 @@ func TestPriorityMetadata(t *testing.T) { schedulertesting.FakeReplicaSetLister([]*extensions.ReplicaSet{}), schedulertesting.FakeStatefulSetLister([]*apps.StatefulSet{})) for _, test := range tests { - ptData := mataDataProducer(test.pod, nil) - if !reflect.DeepEqual(test.expected, ptData) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expected, ptData) - } + t.Run(test.name, func(t *testing.T) { + ptData := mataDataProducer(test.pod, nil) + if !reflect.DeepEqual(test.expected, ptData) { + t.Errorf("expected %#v, got %#v", test.expected, ptData) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/most_requested.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/most_requested.go index 6cb6fe323..ea12e8ef8 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/most_requested.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/most_requested.go @@ -18,7 +18,7 @@ package priorities import ( schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var ( @@ -31,7 +31,7 @@ var ( MostRequestedPriorityMap = mostResourcePriority.PriorityMap ) -func mostResourceScorer(requested, allocable *schedulercache.Resource) int64 { +func mostResourceScorer(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { return (mostRequestedScore(requested.MilliCPU, allocable.MilliCPU) + mostRequestedScore(requested.Memory, allocable.Memory)) / 2 } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/most_requested_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/most_requested_test.go index 427a6674f..94262d32c 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/most_requested_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/most_requested_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestMostRequested(t *testing.T) { @@ -109,7 +109,7 @@ func TestMostRequested(t *testing.T) { pods []*v1.Pod nodes []*v1.Node expectedList schedulerapi.HostPriorityList - test string + name string }{ { /* @@ -126,7 +126,7 @@ func TestMostRequested(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}}, - test: "nothing scheduled, nothing requested", + name: "nothing scheduled, nothing requested", }, { /* @@ -143,7 +143,7 @@ func TestMostRequested(t *testing.T) { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 6000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 6}, {Host: "machine2", Score: 5}}, - test: "nothing scheduled, resources requested, differently sized machines", + name: "nothing scheduled, resources requested, differently sized machines", }, { /* @@ -160,7 +160,7 @@ func TestMostRequested(t *testing.T) { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 20000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 3}, {Host: "machine2", Score: 4}}, - test: "no resources requested, pods scheduled with resources", + name: "no resources requested, pods scheduled with resources", pods: []*v1.Pod{ {Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, {Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -183,7 +183,7 @@ func TestMostRequested(t *testing.T) { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 20000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 4}, {Host: "machine2", Score: 5}}, - test: "resources requested, pods scheduled with resources", + name: "resources requested, pods scheduled with resources", pods: []*v1.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, @@ -204,18 +204,20 @@ func TestMostRequested(t *testing.T) { pod: &v1.Pod{Spec: bigCPUAndMemory}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 10000, 8000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 4}, {Host: "machine2", Score: 2}}, - test: "resources requested with more than the node, pods scheduled with resources", + name: "resources requested with more than the node, pods scheduled with resources", }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) - list, err := priorityFunction(MostRequestedPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedList, list) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + list, err := priorityFunction(MostRequestedPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_affinity.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_affinity.go index ca0a35165..e274e1709 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_affinity.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_affinity.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/labels" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // CalculateNodeAffinityPriorityMap prioritizes nodes according to node affinity scheduling preferences @@ -37,12 +37,11 @@ func CalculateNodeAffinityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *s return schedulerapi.HostPriority{}, fmt.Errorf("node not found") } - var affinity *v1.Affinity + // default is the podspec. + affinity := pod.Spec.Affinity if priorityMeta, ok := meta.(*priorityMetadata); ok { + // We were able to parse metadata, use affinity from there. affinity = priorityMeta.affinity - } else { - // We couldn't parse metadata - fallback to the podspec. - affinity = pod.Spec.Affinity } var count int32 diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_affinity_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_affinity_test.go index e7054b151..8ba1cb1e8 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_affinity_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_affinity_test.go @@ -23,7 +23,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestNodeAffinityPriority(t *testing.T) { @@ -105,7 +105,7 @@ func TestNodeAffinityPriority(t *testing.T) { pod *v1.Pod nodes []*v1.Node expectedList schedulerapi.HostPriorityList - test string + name string }{ { pod: &v1.Pod{ @@ -119,7 +119,7 @@ func TestNodeAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: label3}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}}, - test: "all machines are same priority as NodeAffinity is nil", + name: "all machines are same priority as NodeAffinity is nil", }, { pod: &v1.Pod{ @@ -133,7 +133,7 @@ func TestNodeAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: label3}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}}, - test: "no machine macthes preferred scheduling requirements in NodeAffinity of pod so all machines' priority is zero", + name: "no machine macthes preferred scheduling requirements in NodeAffinity of pod so all machines' priority is zero", }, { pod: &v1.Pod{ @@ -147,7 +147,7 @@ func TestNodeAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: label3}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}}, - test: "only machine1 matches the preferred scheduling requirements of pod", + name: "only machine1 matches the preferred scheduling requirements of pod", }, { pod: &v1.Pod{ @@ -161,19 +161,21 @@ func TestNodeAffinityPriority(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: label2}}, }, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 1}, {Host: "machine5", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 3}}, - test: "all machines matches the preferred scheduling requirements of pod but with different priorities ", + name: "all machines matches the preferred scheduling requirements of pod but with different priorities ", }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) - nap := priorityFunction(CalculateNodeAffinityPriorityMap, CalculateNodeAffinityPriorityReduce, nil) - list, err := nap(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: \nexpected %#v, \ngot %#v", test.test, test.expectedList, list) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + nap := priorityFunction(CalculateNodeAffinityPriorityMap, CalculateNodeAffinityPriorityReduce, nil) + list, err := nap(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, \ngot %#v", test.expectedList, list) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_label.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_label.go index ae5d070a1..82505f788 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_label.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_label.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // NodeLabelPrioritizer contains information to calculate node label priority. diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_label_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_label_test.go index 416fc9cc0..f713d02f3 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_label_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_label_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestNewNodeLabelPriority(t *testing.T) { @@ -36,7 +36,7 @@ func TestNewNodeLabelPriority(t *testing.T) { label string presence bool expectedList schedulerapi.HostPriorityList - test string + name string }{ { nodes: []*v1.Node{ @@ -47,7 +47,7 @@ func TestNewNodeLabelPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}}, label: "baz", presence: true, - test: "no match found, presence true", + name: "no match found, presence true", }, { nodes: []*v1.Node{ @@ -58,7 +58,7 @@ func TestNewNodeLabelPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: schedulerapi.MaxPriority}}, label: "baz", presence: false, - test: "no match found, presence false", + name: "no match found, presence false", }, { nodes: []*v1.Node{ @@ -69,7 +69,7 @@ func TestNewNodeLabelPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}}, label: "foo", presence: true, - test: "one match found, presence true", + name: "one match found, presence true", }, { nodes: []*v1.Node{ @@ -80,7 +80,7 @@ func TestNewNodeLabelPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: schedulerapi.MaxPriority}}, label: "foo", presence: false, - test: "one match found, presence false", + name: "one match found, presence false", }, { nodes: []*v1.Node{ @@ -91,7 +91,7 @@ func TestNewNodeLabelPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: schedulerapi.MaxPriority}}, label: "bar", presence: true, - test: "two matches found, presence true", + name: "two matches found, presence true", }, { nodes: []*v1.Node{ @@ -102,25 +102,27 @@ func TestNewNodeLabelPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}}, label: "bar", presence: false, - test: "two matches found, presence false", + name: "two matches found, presence false", }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) - labelPrioritizer := &NodeLabelPrioritizer{ - label: test.label, - presence: test.presence, - } - list, err := priorityFunction(labelPrioritizer.CalculateNodeLabelPriorityMap, nil, nil)(nil, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - // sort the two lists to avoid failures on account of different ordering - sort.Sort(test.expectedList) - sort.Sort(list) - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedList, list) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + labelPrioritizer := &NodeLabelPrioritizer{ + label: test.label, + presence: test.presence, + } + list, err := priorityFunction(labelPrioritizer.CalculateNodeLabelPriorityMap, nil, nil)(nil, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + // sort the two lists to avoid failures on account of different ordering + sort.Sort(test.expectedList) + sort.Sort(list) + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go index da27daae8..282044de8 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go @@ -24,7 +24,7 @@ import ( v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // CalculateNodePreferAvoidPodsPriorityMap priorities nodes according to the node annotation diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods_test.go index 8fb852fc6..c9b8c9365 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestNodePreferAvoidPriority(t *testing.T) { @@ -84,7 +84,7 @@ func TestNodePreferAvoidPriority(t *testing.T) { pod *v1.Pod nodes []*v1.Node expectedList schedulerapi.HostPriorityList - test string + name string }{ { pod: &v1.Pod{ @@ -97,7 +97,7 @@ func TestNodePreferAvoidPriority(t *testing.T) { }, nodes: testNodes, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: schedulerapi.MaxPriority}}, - test: "pod managed by ReplicationController should avoid a node, this node get lowest priority score", + name: "pod managed by ReplicationController should avoid a node, this node get lowest priority score", }, { pod: &v1.Pod{ @@ -110,7 +110,7 @@ func TestNodePreferAvoidPriority(t *testing.T) { }, nodes: testNodes, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: schedulerapi.MaxPriority}}, - test: "ownership by random controller should be ignored", + name: "ownership by random controller should be ignored", }, { pod: &v1.Pod{ @@ -123,7 +123,7 @@ func TestNodePreferAvoidPriority(t *testing.T) { }, nodes: testNodes, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}, {Host: "machine3", Score: schedulerapi.MaxPriority}}, - test: "owner without Controller field set should be ignored", + name: "owner without Controller field set should be ignored", }, { pod: &v1.Pod{ @@ -136,21 +136,23 @@ func TestNodePreferAvoidPriority(t *testing.T) { }, nodes: testNodes, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: schedulerapi.MaxPriority}}, - test: "pod managed by ReplicaSet should avoid a node, this node get lowest priority score", + name: "pod managed by ReplicaSet should avoid a node, this node get lowest priority score", }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) - list, err := priorityFunction(CalculateNodePreferAvoidPodsPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - // sort the two lists to avoid failures on account of different ordering - sort.Sort(test.expectedList) - sort.Sort(list) - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedList, list) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + list, err := priorityFunction(CalculateNodePreferAvoidPodsPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + // sort the two lists to avoid failures on account of different ordering + sort.Sort(test.expectedList) + sort.Sort(list) + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/reduce.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/reduce.go index 608a83355..6a6a7427f 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/reduce.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/reduce.go @@ -20,7 +20,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // NormalizeReduce generates a PriorityReduceFunction that can normalize the result diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go new file mode 100644 index 000000000..a6ac7a837 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go @@ -0,0 +1,141 @@ +/* +Copyright 2018 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 priorities + +import ( + "fmt" + + schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" +) + +// FunctionShape represents shape of scoring function. +// For safety use NewFunctionShape which performs precondition checks for struct creation. +type FunctionShape []FunctionShapePoint + +// FunctionShapePoint represents single point in scoring function shape. +type FunctionShapePoint struct { + // Utilization is function argument. + Utilization int64 + // Score is function value. + Score int64 +} + +var ( + // give priority to least utilized nodes by default + defaultFunctionShape, _ = NewFunctionShape([]FunctionShapePoint{{0, 10}, {100, 0}}) +) + +const ( + minUtilization = 0 + maxUtilization = 100 + minScore = 0 + maxScore = schedulerapi.MaxPriority +) + +// NewFunctionShape creates instance of FunctionShape in a safe way performing all +// necessary sanity checks. +func NewFunctionShape(points []FunctionShapePoint) (FunctionShape, error) { + + n := len(points) + + if n == 0 { + return nil, fmt.Errorf("at least one point must be specified") + } + + for i := 1; i < n; i++ { + if points[i-1].Utilization >= points[i].Utilization { + return nil, fmt.Errorf("utilization values must be sorted. Utilization[%d]==%d >= Utilization[%d]==%d", i-1, points[i-1].Utilization, i, points[i].Utilization) + } + } + + for i, point := range points { + if point.Utilization < minUtilization { + return nil, fmt.Errorf("utilization values must not be less than %d. Utilization[%d]==%d", minUtilization, i, point.Utilization) + } + if point.Utilization > maxUtilization { + return nil, fmt.Errorf("utilization values must not be greater than %d. Utilization[%d]==%d", maxUtilization, i, point.Utilization) + } + if point.Score < minScore { + return nil, fmt.Errorf("score values must not be less than %d. Score[%d]==%d", minScore, i, point.Score) + } + if point.Score > maxScore { + return nil, fmt.Errorf("score valuses not be greater than %d. Score[%d]==%d", maxScore, i, point.Score) + } + } + + // We make defensive copy so we make no assumption if array passed as argument is not changed afterwards + pointsCopy := make(FunctionShape, n) + copy(pointsCopy, points) + return pointsCopy, nil +} + +// RequestedToCapacityRatioResourceAllocationPriorityDefault creates a requestedToCapacity based +// ResourceAllocationPriority using default resource scoring function shape. +// The default function assigns 1.0 to resource when all capacity is available +// and 0.0 when requested amount is equal to capacity. +func RequestedToCapacityRatioResourceAllocationPriorityDefault() *ResourceAllocationPriority { + return RequestedToCapacityRatioResourceAllocationPriority(defaultFunctionShape) +} + +// RequestedToCapacityRatioResourceAllocationPriority creates a requestedToCapacity based +// ResourceAllocationPriority using provided resource scoring function shape. +func RequestedToCapacityRatioResourceAllocationPriority(scoringFunctionShape FunctionShape) *ResourceAllocationPriority { + return &ResourceAllocationPriority{"RequestedToCapacityRatioResourceAllocationPriority", buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape)} +} + +func buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape FunctionShape) func(*schedulercache.Resource, *schedulercache.Resource, bool, int, int) int64 { + rawScoringFunction := buildBrokenLinearFunction(scoringFunctionShape) + + resourceScoringFunction := func(requested, capacity int64) int64 { + if capacity == 0 || requested > capacity { + return rawScoringFunction(maxUtilization) + } + + return rawScoringFunction(maxUtilization - (capacity-requested)*maxUtilization/capacity) + } + + return func(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { + cpuScore := resourceScoringFunction(requested.MilliCPU, allocable.MilliCPU) + memoryScore := resourceScoringFunction(requested.Memory, allocable.Memory) + return (cpuScore + memoryScore) / 2 + } +} + +// Creates a function which is built using linear segments. Segments are defined via shape array. +// Shape[i].Utilization slice represents points on "utilization" axis where different segments meet. +// Shape[i].Score represents function values at meeting points. +// +// function f(p) is defined as: +// shape[0].Score for p < f[0].Utilization +// shape[i].Score for p == shape[i].Utilization +// shape[n-1].Score for p > shape[n-1].Utilization +// and linear between points (p < shape[i].Utilization) +func buildBrokenLinearFunction(shape FunctionShape) func(int64) int64 { + n := len(shape) + return func(p int64) int64 { + for i := 0; i < n; i++ { + if p <= shape[i].Utilization { + if i == 0 { + return shape[0].Score + } + return shape[i-1].Score + (shape[i].Score-shape[i-1].Score)*(p-shape[i-1].Utilization)/(shape[i].Utilization-shape[i-1].Utilization) + } + } + return shape[n-1].Score + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go new file mode 100644 index 000000000..f9ecfbd6a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go @@ -0,0 +1,241 @@ +/* +Copyright 2018 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 priorities + +import ( + "reflect" + "sort" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" +) + +func TestCreatingFunctionShapeErrorsIfEmptyPoints(t *testing.T) { + var err error + _, err = NewFunctionShape([]FunctionShapePoint{}) + assert.Equal(t, "at least one point must be specified", err.Error()) +} + +func TestCreatingFunctionShapeErrorsIfXIsNotSorted(t *testing.T) { + var err error + _, err = NewFunctionShape([]FunctionShapePoint{{10, 1}, {15, 2}, {20, 3}, {19, 4}, {25, 5}}) + assert.Equal(t, "utilization values must be sorted. Utilization[2]==20 >= Utilization[3]==19", err.Error()) + + _, err = NewFunctionShape([]FunctionShapePoint{{10, 1}, {20, 2}, {20, 3}, {22, 4}, {25, 5}}) + assert.Equal(t, "utilization values must be sorted. Utilization[1]==20 >= Utilization[2]==20", err.Error()) +} + +func TestCreatingFunctionPointNotInAllowedRange(t *testing.T) { + var err error + _, err = NewFunctionShape([]FunctionShapePoint{{-1, 0}, {100, 10}}) + assert.Equal(t, "utilization values must not be less than 0. Utilization[0]==-1", err.Error()) + + _, err = NewFunctionShape([]FunctionShapePoint{{0, 0}, {101, 10}}) + assert.Equal(t, "utilization values must not be greater than 100. Utilization[1]==101", err.Error()) + + _, err = NewFunctionShape([]FunctionShapePoint{{0, -1}, {100, 10}}) + assert.Equal(t, "score values must not be less than 0. Score[0]==-1", err.Error()) + + _, err = NewFunctionShape([]FunctionShapePoint{{0, 0}, {100, 11}}) + assert.Equal(t, "score valuses not be greater than 10. Score[1]==11", err.Error()) +} + +func TestBrokenLinearFunction(t *testing.T) { + type Assertion struct { + p int64 + expected int64 + } + type Test struct { + points []FunctionShapePoint + assertions []Assertion + } + + tests := []Test{ + { + points: []FunctionShapePoint{{10, 1}, {90, 9}}, + assertions: []Assertion{ + {p: -10, expected: 1}, + {p: 0, expected: 1}, + {p: 9, expected: 1}, + {p: 10, expected: 1}, + {p: 15, expected: 1}, + {p: 19, expected: 1}, + {p: 20, expected: 2}, + {p: 89, expected: 8}, + {p: 90, expected: 9}, + {p: 99, expected: 9}, + {p: 100, expected: 9}, + {p: 110, expected: 9}, + }, + }, + { + points: []FunctionShapePoint{{0, 2}, {40, 10}, {100, 0}}, + assertions: []Assertion{ + {p: -10, expected: 2}, + {p: 0, expected: 2}, + {p: 20, expected: 6}, + {p: 30, expected: 8}, + {p: 40, expected: 10}, + {p: 70, expected: 5}, + {p: 100, expected: 0}, + {p: 110, expected: 0}, + }, + }, + { + points: []FunctionShapePoint{{0, 2}, {40, 2}, {100, 2}}, + assertions: []Assertion{ + {p: -10, expected: 2}, + {p: 0, expected: 2}, + {p: 20, expected: 2}, + {p: 30, expected: 2}, + {p: 40, expected: 2}, + {p: 70, expected: 2}, + {p: 100, expected: 2}, + {p: 110, expected: 2}, + }, + }, + } + + for _, test := range tests { + functionShape, err := NewFunctionShape(test.points) + assert.Nil(t, err) + function := buildBrokenLinearFunction(functionShape) + for _, assertion := range test.assertions { + assert.InDelta(t, assertion.expected, function(assertion.p), 0.1, "points=%v, p=%f", test.points, assertion.p) + } + } +} + +func TestRequestedToCapacityRatio(t *testing.T) { + type resources struct { + cpu int64 + mem int64 + } + + type nodeResources struct { + capacity resources + used resources + } + + type test struct { + test string + requested resources + nodes map[string]nodeResources + expectedPriorities schedulerapi.HostPriorityList + } + + tests := []test{ + { + test: "nothing scheduled, nothing requested (default - least requested nodes have priority)", + requested: resources{0, 0}, + nodes: map[string]nodeResources{ + "node1": { + capacity: resources{4000, 10000}, + used: resources{0, 0}, + }, + "node2": { + capacity: resources{4000, 10000}, + used: resources{0, 0}, + }, + }, + expectedPriorities: []schedulerapi.HostPriority{{Host: "node1", Score: 10}, {Host: "node2", Score: 10}}, + }, + { + test: "nothing scheduled, resources requested, differently sized machines (default - least requested nodes have priority)", + requested: resources{3000, 5000}, + nodes: map[string]nodeResources{ + "node1": { + capacity: resources{4000, 10000}, + used: resources{0, 0}, + }, + "node2": { + capacity: resources{6000, 10000}, + used: resources{0, 0}, + }, + }, + expectedPriorities: []schedulerapi.HostPriority{{Host: "node1", Score: 4}, {Host: "node2", Score: 5}}, + }, + { + test: "no resources requested, pods scheduled with resources (default - least requested nodes have priority)", + requested: resources{0, 0}, + nodes: map[string]nodeResources{ + "node1": { + capacity: resources{4000, 10000}, + used: resources{3000, 5000}, + }, + "node2": { + capacity: resources{6000, 10000}, + used: resources{3000, 5000}, + }, + }, + expectedPriorities: []schedulerapi.HostPriority{{Host: "node1", Score: 4}, {Host: "node2", Score: 5}}, + }, + } + + buildResourcesPod := func(node string, requestedResources resources) *v1.Pod { + return &v1.Pod{Spec: v1.PodSpec{ + NodeName: node, + Containers: []v1.Container{ + { + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(requestedResources.cpu, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(requestedResources.mem, resource.DecimalSI), + }, + }, + }, + }, + }, + } + } + + for _, test := range tests { + + nodeNames := make([]string, 0) + for nodeName := range test.nodes { + nodeNames = append(nodeNames, nodeName) + } + sort.Strings(nodeNames) + + nodes := make([]*v1.Node, 0) + for _, nodeName := range nodeNames { + node := test.nodes[nodeName] + nodes = append(nodes, makeNode(nodeName, node.capacity.cpu, node.capacity.mem)) + } + + scheduledPods := make([]*v1.Pod, 0) + for name, node := range test.nodes { + scheduledPods = append(scheduledPods, + buildResourcesPod(name, node.used)) + } + + newPod := buildResourcesPod("", test.requested) + + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(scheduledPods, nodes) + list, err := priorityFunction(RequestedToCapacityRatioResourceAllocationPriorityDefault().PriorityMap, nil, nil)(newPod, nodeNameToInfo, nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expectedPriorities, list) { + t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedPriorities, list) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_allocation.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_allocation.go index 2d569b1d3..a3e329df0 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_allocation.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_allocation.go @@ -23,13 +23,13 @@ import ( "k8s.io/api/core/v1" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // ResourceAllocationPriority contains information to calculate resource allocation priority. type ResourceAllocationPriority struct { Name string - scorer func(requested, allocable *schedulercache.Resource) int64 + scorer func(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 } // PriorityMap priorities nodes according to the resource allocations on the node. @@ -54,8 +54,13 @@ func (r *ResourceAllocationPriority) PriorityMap( requested.MilliCPU += nodeInfo.NonZeroRequest().MilliCPU requested.Memory += nodeInfo.NonZeroRequest().Memory - - score := r.scorer(&requested, &allocatable) + var score int64 + // Check if the pod has volumes and this could be added to scorer function for balanced resource allocation. + if len(pod.Spec.Volumes) >= 0 && nodeInfo.TransientInfo != nil { + score = r.scorer(&requested, &allocatable, true, nodeInfo.TransientInfo.TransNodeInfo.RequestedVolumes, nodeInfo.TransientInfo.TransNodeInfo.AllocatableVolumesCount) + } else { + score = r.scorer(&requested, &allocatable, false, 0, 0) + } if glog.V(10) { glog.Infof( diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_limits.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_limits.go index 3267368d2..165ac3e3e 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_limits.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_limits.go @@ -20,9 +20,8 @@ import ( "fmt" "k8s.io/api/core/v1" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "github.com/golang/glog" ) @@ -93,35 +92,7 @@ func getResourceLimits(pod *v1.Pod) *schedulercache.Resource { // take max_resource(sum_pod, any_init_container) for _, container := range pod.Spec.InitContainers { - for rName, rQuantity := range container.Resources.Limits { - switch rName { - case v1.ResourceMemory: - if mem := rQuantity.Value(); mem > result.Memory { - result.Memory = mem - } - case v1.ResourceCPU: - if cpu := rQuantity.MilliValue(); cpu > result.MilliCPU { - result.MilliCPU = cpu - } - // keeping these resources though score computation in other priority functions and in this - // are only computed based on cpu and memory only. - case v1.ResourceEphemeralStorage: - if ephemeralStorage := rQuantity.Value(); ephemeralStorage > result.EphemeralStorage { - result.EphemeralStorage = ephemeralStorage - } - case v1.ResourceNvidiaGPU: - if gpu := rQuantity.Value(); gpu > result.NvidiaGPU { - result.NvidiaGPU = gpu - } - default: - if v1helper.IsScalarResourceName(rName) { - value := rQuantity.Value() - if value > result.ScalarResources[rName] { - result.SetScalar(rName, value) - } - } - } - } + result.SetMaxResource(container.Resources.Limits) } return result diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_limits_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_limits_test.go index e3056dcc6..86ecd8cca 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_limits_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/resource_limits_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" //metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func TestResourceLimistPriority(t *testing.T) { @@ -103,49 +103,50 @@ func TestResourceLimistPriority(t *testing.T) { pod *v1.Pod nodes []*v1.Node expectedList schedulerapi.HostPriorityList - test string + name string }{ { pod: &v1.Pod{Spec: noResources}, nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 0), makeNode("machine3", 0, 10000), makeNode("machine4", 0, 0)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}, {Host: "machine3", Score: 0}, {Host: "machine4", Score: 0}}, - test: "pod does not specify its resource limits", + name: "pod does not specify its resource limits", }, { pod: &v1.Pod{Spec: cpuOnly}, nodes: []*v1.Node{makeNode("machine1", 3000, 10000), makeNode("machine2", 2000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 1}, {Host: "machine2", Score: 0}}, - test: "pod only specifies cpu limits", + name: "pod only specifies cpu limits", }, { pod: &v1.Pod{Spec: memOnly}, nodes: []*v1.Node{makeNode("machine1", 4000, 4000), makeNode("machine2", 5000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 1}}, - test: "pod only specifies mem limits", + name: "pod only specifies mem limits", }, { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 4000, 4000), makeNode("machine2", 5000, 10000)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 1}, {Host: "machine2", Score: 1}}, - test: "pod specifies both cpu and mem limits", + name: "pod specifies both cpu and mem limits", }, { pod: &v1.Pod{Spec: cpuAndMemory}, nodes: []*v1.Node{makeNode("machine1", 0, 0)}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}}, - test: "node does not advertise its allocatables", + name: "node does not advertise its allocatables", }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) - list, err := priorityFunction(ResourceLimitsPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedList, list) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + list, err := priorityFunction(ResourceLimitsPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) } - } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/selector_spreading.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/selector_spreading.go index 713972880..512ec08d7 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/selector_spreading.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/selector_spreading.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" utilnode "k8s.io/kubernetes/pkg/util/node" "github.com/golang/glog" @@ -211,7 +211,9 @@ func filteredPod(namespace string, selector labels.Selector, nodeInfo *scheduler return []*v1.Pod{} } for _, pod := range nodeInfo.Pods() { - if namespace == pod.Namespace && selector.Matches(labels.Set(pod.Labels)) { + // Ignore pods being deleted for spreading purposes + // Similar to how it is done for SelectorSpreadPriority + if namespace == pod.Namespace && pod.DeletionTimestamp == nil && selector.Matches(labels.Set(pod.Labels)) { pods = append(pods, pod) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/selector_spreading_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/selector_spreading_test.go index 5abd1736a..9f2b8dc03 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/selector_spreading_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/selector_spreading_test.go @@ -27,7 +27,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -64,20 +64,20 @@ func TestSelectorSpreadPriority(t *testing.T) { services []*v1.Service sss []*apps.StatefulSet expectedList schedulerapi.HostPriorityList - test string + name string }{ { pod: new(v1.Pod), nodes: []string{"machine1", "machine2"}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "nothing scheduled", + name: "nothing scheduled", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, pods: []*v1.Pod{{Spec: zone1Spec}}, nodes: []string{"machine1", "machine2"}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "no services", + name: "no services", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -85,7 +85,7 @@ func TestSelectorSpreadPriority(t *testing.T) { nodes: []string{"machine1", "machine2"}, services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: map[string]string{"key": "value"}}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: schedulerapi.MaxPriority}}, - test: "different services", + name: "different services", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -96,7 +96,7 @@ func TestSelectorSpreadPriority(t *testing.T) { nodes: []string{"machine1", "machine2"}, services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}}, - test: "two pods, one service pod", + name: "two pods, one service pod", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -110,7 +110,7 @@ func TestSelectorSpreadPriority(t *testing.T) { nodes: []string{"machine1", "machine2"}, services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}}, - test: "five pods, one service pod in no namespace", + name: "five pods, one service pod in no namespace", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: metav1.NamespaceDefault}}, @@ -123,7 +123,7 @@ func TestSelectorSpreadPriority(t *testing.T) { nodes: []string{"machine1", "machine2"}, services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}}, - test: "four pods, one service pod in default namespace", + name: "four pods, one service pod in default namespace", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, @@ -137,7 +137,7 @@ func TestSelectorSpreadPriority(t *testing.T) { nodes: []string{"machine1", "machine2"}, services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}, ObjectMeta: metav1.ObjectMeta{Namespace: "ns1"}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: schedulerapi.MaxPriority}, {Host: "machine2", Score: 0}}, - test: "five pods, one service pod in specific namespace", + name: "five pods, one service pod in specific namespace", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -149,7 +149,7 @@ func TestSelectorSpreadPriority(t *testing.T) { nodes: []string{"machine1", "machine2"}, services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}}, - test: "three pods, two service pods on different machines", + name: "three pods, two service pods on different machines", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -162,7 +162,7 @@ func TestSelectorSpreadPriority(t *testing.T) { nodes: []string{"machine1", "machine2"}, services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 5}, {Host: "machine2", Score: 0}}, - test: "four pods, three service pods", + name: "four pods, three service pods", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -174,7 +174,7 @@ func TestSelectorSpreadPriority(t *testing.T) { nodes: []string{"machine1", "machine2"}, services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "service with partial pod label matches", + name: "service with partial pod label matches", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, OwnerReferences: controllerRef("ReplicationController", "name", "abc123")}}, @@ -189,7 +189,7 @@ func TestSelectorSpreadPriority(t *testing.T) { // "baz=blah" matches both labels1 and labels2, and "foo=bar" matches only labels 1. This means that we assume that we want to // do spreading between all pods. The result should be exactly as above. expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "service with partial pod label matches with service and replication controller", + name: "service with partial pod label matches with service and replication controller", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, OwnerReferences: controllerRef("ReplicaSet", "name", "abc123")}}, @@ -203,7 +203,7 @@ func TestSelectorSpreadPriority(t *testing.T) { rss: []*extensions.ReplicaSet{{Spec: extensions.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, // We use ReplicaSet, instead of ReplicationController. The result should be exactly as above. expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "service with partial pod label matches with service and replica set", + name: "service with partial pod label matches with service and replica set", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, OwnerReferences: controllerRef("StatefulSet", "name", "abc123")}}, @@ -216,7 +216,7 @@ func TestSelectorSpreadPriority(t *testing.T) { services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}}, sss: []*apps.StatefulSet{{Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "service with partial pod label matches with service and replica set", + name: "service with partial pod label matches with service and replica set", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "bar", "bar": "foo"}, OwnerReferences: controllerRef("ReplicationController", "name", "abc123")}}, @@ -230,7 +230,7 @@ func TestSelectorSpreadPriority(t *testing.T) { services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: map[string]string{"bar": "foo"}}}}, // Taken together Service and Replication Controller should match all Pods, hence result should be equal to one above. expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "disjoined service and replication controller should be treated equally", + name: "disjoined service and replication controller should be treated equally", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "bar", "bar": "foo"}, OwnerReferences: controllerRef("ReplicaSet", "name", "abc123")}}, @@ -244,7 +244,7 @@ func TestSelectorSpreadPriority(t *testing.T) { rss: []*extensions.ReplicaSet{{Spec: extensions.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, // We use ReplicaSet, instead of ReplicationController. The result should be exactly as above. expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "disjoined service and replica set should be treated equally", + name: "disjoined service and replica set should be treated equally", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "bar", "bar": "foo"}, OwnerReferences: controllerRef("StatefulSet", "name", "abc123")}}, @@ -257,7 +257,7 @@ func TestSelectorSpreadPriority(t *testing.T) { services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: map[string]string{"bar": "foo"}}}}, sss: []*apps.StatefulSet{{Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "disjoined service and replica set should be treated equally", + name: "disjoined service and replica set should be treated equally", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, OwnerReferences: controllerRef("ReplicationController", "name", "abc123")}}, @@ -270,7 +270,7 @@ func TestSelectorSpreadPriority(t *testing.T) { rcs: []*v1.ReplicationController{{Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"foo": "bar"}}}}, // Both Nodes have one pod from the given RC, hence both get 0 score. expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}}, - test: "Replication controller with partial pod label matches", + name: "Replication controller with partial pod label matches", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, OwnerReferences: controllerRef("ReplicaSet", "name", "abc123")}}, @@ -283,7 +283,7 @@ func TestSelectorSpreadPriority(t *testing.T) { rss: []*extensions.ReplicaSet{{Spec: extensions.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, // We use ReplicaSet, instead of ReplicationController. The result should be exactly as above. expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}}, - test: "Replica set with partial pod label matches", + name: "Replica set with partial pod label matches", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, OwnerReferences: controllerRef("StatefulSet", "name", "abc123")}}, @@ -296,7 +296,7 @@ func TestSelectorSpreadPriority(t *testing.T) { sss: []*apps.StatefulSet{{Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, // We use StatefulSet, instead of ReplicationController. The result should be exactly as above. expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 0}}, - test: "StatefulSet with partial pod label matches", + name: "StatefulSet with partial pod label matches", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, OwnerReferences: controllerRef("ReplicationController", "name", "abc123")}}, @@ -308,7 +308,7 @@ func TestSelectorSpreadPriority(t *testing.T) { nodes: []string{"machine1", "machine2"}, rcs: []*v1.ReplicationController{{Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"baz": "blah"}}}}, expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "Another replication controller with partial pod label matches", + name: "Another replication controller with partial pod label matches", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, OwnerReferences: controllerRef("ReplicaSet", "name", "abc123")}}, @@ -321,7 +321,7 @@ func TestSelectorSpreadPriority(t *testing.T) { rss: []*extensions.ReplicaSet{{Spec: extensions.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"baz": "blah"}}}}}, // We use ReplicaSet, instead of ReplicationController. The result should be exactly as above. expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "Another replication set with partial pod label matches", + name: "Another replication set with partial pod label matches", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, OwnerReferences: controllerRef("StatefulSet", "name", "abc123")}}, @@ -334,34 +334,36 @@ func TestSelectorSpreadPriority(t *testing.T) { sss: []*apps.StatefulSet{{Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"baz": "blah"}}}}}, // We use StatefulSet, instead of ReplicationController. The result should be exactly as above. expectedList: []schedulerapi.HostPriority{{Host: "machine1", Score: 0}, {Host: "machine2", Score: 5}}, - test: "Another stateful set with partial pod label matches", + name: "Another stateful set with partial pod label matches", }, } - for i, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, makeNodeList(test.nodes)) - selectorSpread := SelectorSpread{ - serviceLister: schedulertesting.FakeServiceLister(test.services), - controllerLister: schedulertesting.FakeControllerLister(test.rcs), - replicaSetLister: schedulertesting.FakeReplicaSetLister(test.rss), - statefulSetLister: schedulertesting.FakeStatefulSetLister(test.sss), - } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, makeNodeList(test.nodes)) + selectorSpread := SelectorSpread{ + serviceLister: schedulertesting.FakeServiceLister(test.services), + controllerLister: schedulertesting.FakeControllerLister(test.rcs), + replicaSetLister: schedulertesting.FakeReplicaSetLister(test.rss), + statefulSetLister: schedulertesting.FakeStatefulSetLister(test.sss), + } - mataDataProducer := NewPriorityMetadataFactory( - schedulertesting.FakeServiceLister(test.services), - schedulertesting.FakeControllerLister(test.rcs), - schedulertesting.FakeReplicaSetLister(test.rss), - schedulertesting.FakeStatefulSetLister(test.sss)) - mataData := mataDataProducer(test.pod, nodeNameToInfo) + mataDataProducer := NewPriorityMetadataFactory( + schedulertesting.FakeServiceLister(test.services), + schedulertesting.FakeControllerLister(test.rcs), + schedulertesting.FakeReplicaSetLister(test.rss), + schedulertesting.FakeStatefulSetLister(test.sss)) + mataData := mataDataProducer(test.pod, nodeNameToInfo) - ttp := priorityFunction(selectorSpread.CalculateSpreadPriorityMap, selectorSpread.CalculateSpreadPriorityReduce, mataData) - list, err := ttp(test.pod, nodeNameToInfo, makeNodeList(test.nodes)) - if err != nil { - t.Errorf("unexpected error: %v index : %d\n", err, i) - } - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedList, list) - } + ttp := priorityFunction(selectorSpread.CalculateSpreadPriorityMap, selectorSpread.CalculateSpreadPriorityReduce, mataData) + list, err := ttp(test.pod, nodeNameToInfo, makeNodeList(test.nodes)) + if err != nil { + t.Errorf("unexpected error: %v \n", err) + } + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) } } @@ -407,13 +409,12 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { tests := []struct { pod *v1.Pod pods []*v1.Pod - nodes []string rcs []*v1.ReplicationController rss []*extensions.ReplicaSet services []*v1.Service sss []*apps.StatefulSet expectedList schedulerapi.HostPriorityList - test string + name string }{ { pod: new(v1.Pod), @@ -425,7 +426,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { {Host: nodeMachine2Zone3, Score: schedulerapi.MaxPriority}, {Host: nodeMachine3Zone3, Score: schedulerapi.MaxPriority}, }, - test: "nothing scheduled", + name: "nothing scheduled", }, { pod: buildPod("", labels1, nil), @@ -438,7 +439,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { {Host: nodeMachine2Zone3, Score: schedulerapi.MaxPriority}, {Host: nodeMachine3Zone3, Score: schedulerapi.MaxPriority}, }, - test: "no services", + name: "no services", }, { pod: buildPod("", labels1, nil), @@ -452,7 +453,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { {Host: nodeMachine2Zone3, Score: schedulerapi.MaxPriority}, {Host: nodeMachine3Zone3, Score: schedulerapi.MaxPriority}, }, - test: "different services", + name: "different services", }, { pod: buildPod("", labels1, nil), @@ -469,7 +470,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { {Host: nodeMachine2Zone3, Score: schedulerapi.MaxPriority}, {Host: nodeMachine3Zone3, Score: schedulerapi.MaxPriority}, }, - test: "two pods, 0 matching", + name: "two pods, 0 matching", }, { pod: buildPod("", labels1, nil), @@ -486,7 +487,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { {Host: nodeMachine2Zone3, Score: schedulerapi.MaxPriority}, {Host: nodeMachine3Zone3, Score: schedulerapi.MaxPriority}, }, - test: "two pods, 1 matching (in z2)", + name: "two pods, 1 matching (in z2)", }, { pod: buildPod("", labels1, nil), @@ -506,7 +507,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { {Host: nodeMachine2Zone3, Score: 3}, // Pod on node {Host: nodeMachine3Zone3, Score: 6}, // Pod in zone }, - test: "five pods, 3 matching (z2=2, z3=1)", + name: "five pods, 3 matching (z2=2, z3=1)", }, { pod: buildPod("", labels1, nil), @@ -525,7 +526,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { {Host: nodeMachine2Zone3, Score: 3}, // Pod in zone {Host: nodeMachine3Zone3, Score: 3}, // Pod in zone }, - test: "four pods, 3 matching (z1=1, z2=1, z3=1)", + name: "four pods, 3 matching (z1=1, z2=1, z3=1)", }, { pod: buildPod("", labels1, nil), @@ -544,7 +545,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { {Host: nodeMachine2Zone3, Score: 3}, // Pod in zone {Host: nodeMachine3Zone3, Score: 3}, // Pod in zone }, - test: "four pods, 3 matching (z1=1, z2=1, z3=1)", + name: "four pods, 3 matching (z1=1, z2=1, z3=1)", }, { pod: buildPod("", labels1, controllerRef("ReplicationController", "name", "abc123")), @@ -569,36 +570,38 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { {Host: nodeMachine2Zone3, Score: 3}, // Pod in zone {Host: nodeMachine3Zone3, Score: 3}, // Pod in zone }, - test: "Replication controller spreading (z1=0, z2=1, z3=2)", + name: "Replication controller spreading (z1=0, z2=1, z3=2)", }, } - for i, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, makeLabeledNodeList(labeledNodes)) - selectorSpread := SelectorSpread{ - serviceLister: schedulertesting.FakeServiceLister(test.services), - controllerLister: schedulertesting.FakeControllerLister(test.rcs), - replicaSetLister: schedulertesting.FakeReplicaSetLister(test.rss), - statefulSetLister: schedulertesting.FakeStatefulSetLister(test.sss), - } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, makeLabeledNodeList(labeledNodes)) + selectorSpread := SelectorSpread{ + serviceLister: schedulertesting.FakeServiceLister(test.services), + controllerLister: schedulertesting.FakeControllerLister(test.rcs), + replicaSetLister: schedulertesting.FakeReplicaSetLister(test.rss), + statefulSetLister: schedulertesting.FakeStatefulSetLister(test.sss), + } - mataDataProducer := NewPriorityMetadataFactory( - schedulertesting.FakeServiceLister(test.services), - schedulertesting.FakeControllerLister(test.rcs), - schedulertesting.FakeReplicaSetLister(test.rss), - schedulertesting.FakeStatefulSetLister(test.sss)) - mataData := mataDataProducer(test.pod, nodeNameToInfo) - ttp := priorityFunction(selectorSpread.CalculateSpreadPriorityMap, selectorSpread.CalculateSpreadPriorityReduce, mataData) - list, err := ttp(test.pod, nodeNameToInfo, makeLabeledNodeList(labeledNodes)) - if err != nil { - t.Errorf("unexpected error: %v index : %d", err, i) - } - // sort the two lists to avoid failures on account of different ordering - sort.Sort(test.expectedList) - sort.Sort(list) - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s: expected %#v, got %#v", test.test, test.expectedList, list) - } + mataDataProducer := NewPriorityMetadataFactory( + schedulertesting.FakeServiceLister(test.services), + schedulertesting.FakeControllerLister(test.rcs), + schedulertesting.FakeReplicaSetLister(test.rss), + schedulertesting.FakeStatefulSetLister(test.sss)) + mataData := mataDataProducer(test.pod, nodeNameToInfo) + ttp := priorityFunction(selectorSpread.CalculateSpreadPriorityMap, selectorSpread.CalculateSpreadPriorityReduce, mataData) + list, err := ttp(test.pod, nodeNameToInfo, makeLabeledNodeList(labeledNodes)) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + // sort the two lists to avoid failures on account of different ordering + sort.Sort(test.expectedList) + sort.Sort(list) + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) } } @@ -640,7 +643,7 @@ func TestZoneSpreadPriority(t *testing.T) { nodes map[string]map[string]string services []*v1.Service expectedList schedulerapi.HostPriorityList - test string + name string }{ { pod: new(v1.Pod), @@ -648,7 +651,7 @@ func TestZoneSpreadPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine11", Score: schedulerapi.MaxPriority}, {Host: "machine12", Score: schedulerapi.MaxPriority}, {Host: "machine21", Score: schedulerapi.MaxPriority}, {Host: "machine22", Score: schedulerapi.MaxPriority}, {Host: "machine01", Score: 0}, {Host: "machine02", Score: 0}}, - test: "nothing scheduled", + name: "nothing scheduled", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -657,7 +660,7 @@ func TestZoneSpreadPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine11", Score: schedulerapi.MaxPriority}, {Host: "machine12", Score: schedulerapi.MaxPriority}, {Host: "machine21", Score: schedulerapi.MaxPriority}, {Host: "machine22", Score: schedulerapi.MaxPriority}, {Host: "machine01", Score: 0}, {Host: "machine02", Score: 0}}, - test: "no services", + name: "no services", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -667,7 +670,7 @@ func TestZoneSpreadPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine11", Score: schedulerapi.MaxPriority}, {Host: "machine12", Score: schedulerapi.MaxPriority}, {Host: "machine21", Score: schedulerapi.MaxPriority}, {Host: "machine22", Score: schedulerapi.MaxPriority}, {Host: "machine01", Score: 0}, {Host: "machine02", Score: 0}}, - test: "different services", + name: "different services", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -681,7 +684,7 @@ func TestZoneSpreadPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine11", Score: schedulerapi.MaxPriority}, {Host: "machine12", Score: schedulerapi.MaxPriority}, {Host: "machine21", Score: 0}, {Host: "machine22", Score: 0}, {Host: "machine01", Score: 0}, {Host: "machine02", Score: 0}}, - test: "three pods, one service pod", + name: "three pods, one service pod", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -695,7 +698,7 @@ func TestZoneSpreadPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine11", Score: 5}, {Host: "machine12", Score: 5}, {Host: "machine21", Score: 5}, {Host: "machine22", Score: 5}, {Host: "machine01", Score: 0}, {Host: "machine02", Score: 0}}, - test: "three pods, two service pods on different machines", + name: "three pods, two service pods on different machines", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: metav1.NamespaceDefault}}, @@ -710,7 +713,7 @@ func TestZoneSpreadPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine11", Score: 0}, {Host: "machine12", Score: 0}, {Host: "machine21", Score: schedulerapi.MaxPriority}, {Host: "machine22", Score: schedulerapi.MaxPriority}, {Host: "machine01", Score: 0}, {Host: "machine02", Score: 0}}, - test: "three service label match pods in different namespaces", + name: "three service label match pods in different namespaces", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -725,7 +728,7 @@ func TestZoneSpreadPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine11", Score: 6}, {Host: "machine12", Score: 6}, {Host: "machine21", Score: 3}, {Host: "machine22", Score: 3}, {Host: "machine01", Score: 0}, {Host: "machine02", Score: 0}}, - test: "four pods, three service pods", + name: "four pods, three service pods", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -739,7 +742,7 @@ func TestZoneSpreadPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine11", Score: 3}, {Host: "machine12", Score: 3}, {Host: "machine21", Score: 6}, {Host: "machine22", Score: 6}, {Host: "machine01", Score: 0}, {Host: "machine02", Score: 0}}, - test: "service with partial pod label matches", + name: "service with partial pod label matches", }, { pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, @@ -754,7 +757,7 @@ func TestZoneSpreadPriority(t *testing.T) { expectedList: []schedulerapi.HostPriority{{Host: "machine11", Score: 7}, {Host: "machine12", Score: 7}, {Host: "machine21", Score: 5}, {Host: "machine22", Score: 5}, {Host: "machine01", Score: 0}, {Host: "machine02", Score: 0}}, - test: "service pod on non-zoned node", + name: "service pod on non-zoned node", }, } // these local variables just make sure controllerLister\replicaSetLister\statefulSetLister not nil @@ -763,28 +766,30 @@ func TestZoneSpreadPriority(t *testing.T) { rcs := []*v1.ReplicationController{{Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"foo": "bar"}}}} rss := []*extensions.ReplicaSet{{Spec: extensions.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}} - for i, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, makeLabeledNodeList(test.nodes)) - zoneSpread := ServiceAntiAffinity{podLister: schedulertesting.FakePodLister(test.pods), serviceLister: schedulertesting.FakeServiceLister(test.services), label: "zone"} + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, makeLabeledNodeList(test.nodes)) + zoneSpread := ServiceAntiAffinity{podLister: schedulertesting.FakePodLister(test.pods), serviceLister: schedulertesting.FakeServiceLister(test.services), label: "zone"} - mataDataProducer := NewPriorityMetadataFactory( - schedulertesting.FakeServiceLister(test.services), - schedulertesting.FakeControllerLister(rcs), - schedulertesting.FakeReplicaSetLister(rss), - schedulertesting.FakeStatefulSetLister(sss)) - mataData := mataDataProducer(test.pod, nodeNameToInfo) - ttp := priorityFunction(zoneSpread.CalculateAntiAffinityPriorityMap, zoneSpread.CalculateAntiAffinityPriorityReduce, mataData) - list, err := ttp(test.pod, nodeNameToInfo, makeLabeledNodeList(test.nodes)) - if err != nil { - t.Errorf("unexpected error: %v index : %d", err, i) - } + mataDataProducer := NewPriorityMetadataFactory( + schedulertesting.FakeServiceLister(test.services), + schedulertesting.FakeControllerLister(rcs), + schedulertesting.FakeReplicaSetLister(rss), + schedulertesting.FakeStatefulSetLister(sss)) + mataData := mataDataProducer(test.pod, nodeNameToInfo) + ttp := priorityFunction(zoneSpread.CalculateAntiAffinityPriorityMap, zoneSpread.CalculateAntiAffinityPriorityReduce, mataData) + list, err := ttp(test.pod, nodeNameToInfo, makeLabeledNodeList(test.nodes)) + if err != nil { + t.Errorf("unexpected error: %v", err) + } - // sort the two lists to avoid failures on account of different ordering - sort.Sort(test.expectedList) - sort.Sort(list) - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("test index %d (%s): expected %#v, got %#v", i, test.test, test.expectedList, list) - } + // sort the two lists to avoid failures on account of different ordering + sort.Sort(test.expectedList) + sort.Sort(list) + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected %#v, got %#v", test.expectedList, list) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/taint_toleration.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/taint_toleration.go index c6847c0ea..5790a4b09 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/taint_toleration.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/taint_toleration.go @@ -22,7 +22,7 @@ import ( "k8s.io/api/core/v1" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // CountIntolerableTaintsPreferNoSchedule gives the count of intolerable taints of a pod with effect PreferNoSchedule diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/taint_toleration_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/taint_toleration_test.go index 3ef61dd98..70b69aed6 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/taint_toleration_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/taint_toleration_test.go @@ -23,7 +23,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func nodeWithTaints(nodeName string, taints []v1.Taint) *v1.Node { @@ -54,11 +54,11 @@ func TestTaintAndToleration(t *testing.T) { pod *v1.Pod nodes []*v1.Node expectedList schedulerapi.HostPriorityList - test string + name string }{ // basic test case { - test: "node with taints tolerated by the pod, gets a higher score than those node with intolerable taints", + name: "node with taints tolerated by the pod, gets a higher score than those node with intolerable taints", pod: podWithTolerations([]v1.Toleration{{ Key: "foo", Operator: v1.TolerationOpEqual, @@ -84,7 +84,7 @@ func TestTaintAndToleration(t *testing.T) { }, // the count of taints that are tolerated by pod, does not matter. { - test: "the nodes that all of their taints are tolerated by the pod, get the same score, no matter how many tolerable taints a node has", + name: "the nodes that all of their taints are tolerated by the pod, get the same score, no matter how many tolerable taints a node has", pod: podWithTolerations([]v1.Toleration{ { Key: "cpu-type", @@ -127,7 +127,7 @@ func TestTaintAndToleration(t *testing.T) { }, // the count of taints on a node that are not tolerated by pod, matters. { - test: "the more intolerable taints a node has, the lower score it gets.", + name: "the more intolerable taints a node has, the lower score it gets.", pod: podWithTolerations([]v1.Toleration{{ Key: "foo", Operator: v1.TolerationOpEqual, @@ -163,7 +163,7 @@ func TestTaintAndToleration(t *testing.T) { }, // taints-tolerations priority only takes care about the taints and tolerations that have effect PreferNoSchedule { - test: "only taints and tolerations that have effect PreferNoSchedule are checked by taints-tolerations priority function", + name: "only taints and tolerations that have effect PreferNoSchedule are checked by taints-tolerations priority function", pod: podWithTolerations([]v1.Toleration{ { Key: "cpu-type", @@ -205,7 +205,7 @@ func TestTaintAndToleration(t *testing.T) { }, }, { - test: "Default behaviour No taints and tolerations, lands on node with no taints", + name: "Default behaviour No taints and tolerations, lands on node with no taints", //pod without tolerations pod: podWithTolerations([]v1.Toleration{}), nodes: []*v1.Node{ @@ -226,16 +226,17 @@ func TestTaintAndToleration(t *testing.T) { }, } for _, test := range tests { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) - ttp := priorityFunction(ComputeTaintTolerationPriorityMap, ComputeTaintTolerationPriorityReduce, nil) - list, err := ttp(test.pod, nodeNameToInfo, test.nodes) - if err != nil { - t.Errorf("%s, unexpected error: %v", test.test, err) - } + t.Run(test.name, func(t *testing.T) { + nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + ttp := priorityFunction(ComputeTaintTolerationPriorityMap, ComputeTaintTolerationPriorityReduce, nil) + list, err := ttp(test.pod, nodeNameToInfo, test.nodes) + if err != nil { + t.Errorf("unexpected error: %v", err) + } - if !reflect.DeepEqual(test.expectedList, list) { - t.Errorf("%s,\nexpected:\n\t%+v,\ngot:\n\t%+v", test.test, test.expectedList, list) - } + if !reflect.DeepEqual(test.expectedList, list) { + t.Errorf("expected:\n\t%+v,\ngot:\n\t%+v", test.expectedList, list) + } + }) } - } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/test_util.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/test_util.go index d1756c038..74ffef34c 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/test_util.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/test_util.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) func makeNode(node string, milliCPU, memory int64) *v1.Node { diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util/non_zero.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util/non_zero.go index bfbe86d66..b671945f3 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util/non_zero.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util/non_zero.go @@ -32,9 +32,8 @@ const DefaultMilliCPURequest int64 = 100 // 0.1 core // DefaultMemoryRequest defines default memory request size. const DefaultMemoryRequest int64 = 200 * 1024 * 1024 // 200 MB -// GetNonzeroRequests returns the default resource request if none is found or what is provided on the request -// TODO: Consider setting default as a fixed fraction of machine capacity (take "capacity v1.ResourceList" -// as an additional argument here) rather than using constants +// GetNonzeroRequests returns the default resource request if none is found or +// what is provided on the request. func GetNonzeroRequests(requests *v1.ResourceList) (int64, int64) { var outMilliCPU, outMemory int64 // Override if un-set, but not if explicitly set to zero diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/scheduler_interface.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/scheduler_interface.go index f86015b49..ffa275d45 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/scheduler_interface.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/scheduler_interface.go @@ -19,7 +19,7 @@ package algorithm import ( "k8s.io/api/core/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // SchedulerExtender is an interface for external processes to influence scheduling @@ -29,7 +29,9 @@ type SchedulerExtender interface { // Filter based on extender-implemented predicate functions. The filtered list is // expected to be a subset of the supplied list. failedNodesMap optionally contains // the list of failed nodes and failure reasons. - Filter(pod *v1.Pod, nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo) (filteredNodes []*v1.Node, failedNodesMap schedulerapi.FailedNodesMap, err error) + Filter(pod *v1.Pod, + nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo, + ) (filteredNodes []*v1.Node, failedNodesMap schedulerapi.FailedNodesMap, err error) // Prioritize based on extender-implemented priority functions. The returned scores & weight // are used to compute the weighted score for an extender. The weighted scores are added to @@ -45,6 +47,27 @@ type SchedulerExtender interface { // IsInterested returns true if at least one extended resource requested by // this pod is managed by this extender. IsInterested(pod *v1.Pod) bool + + // ProcessPreemption returns nodes with their victim pods processed by extender based on + // given: + // 1. Pod to schedule + // 2. Candidate nodes and victim pods (nodeToVictims) generated by previous scheduling process. + // 3. nodeNameToInfo to restore v1.Node from node name if extender cache is enabled. + // The possible changes made by extender may include: + // 1. Subset of given candidate nodes after preemption phase of extender. + // 2. A different set of victim pod for every given candidate node after preemption phase of extender. + ProcessPreemption( + pod *v1.Pod, + nodeToVictims map[*v1.Node]*schedulerapi.Victims, + nodeNameToInfo map[string]*schedulercache.NodeInfo, + ) (map[*v1.Node]*schedulerapi.Victims, error) + + // SupportsPreemption returns if the scheduler extender support preemption or not. + SupportsPreemption() bool + + // IsIgnorable returns true indicates scheduling should not fail when this extender + // is unavailable. This gives scheduler ability to fail fast and tolerate non-critical extenders as well. + IsIgnorable() bool } // ScheduleAlgorithm is an interface implemented by things that know how to schedule pods diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/types.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/types.go index 60ad348c9..7bb5eecff 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/types.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/types.go @@ -22,9 +22,15 @@ import ( extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/labels" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) +// NodeFieldSelectorKeys is a map that: the key are node field selector keys; the values are +// the functions to get the value of the node field. +var NodeFieldSelectorKeys = map[string]func(*v1.Node) string{ + NodeFieldSelectorKeyNodeName: func(n *v1.Node) string { return n.Name }, +} + // FitPredicate is a function that indicates if a pod fits into an existing node. // The failure information is given by the error. type FitPredicate func(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []PredicateFailureReason, error) @@ -78,9 +84,6 @@ type PredicateFailureReason interface { GetReason() string } -// GetEquivalencePodFunc is a function that gets a EquivalencePod from a pod. -type GetEquivalencePodFunc func(pod *v1.Pod) interface{} - // NodeLister interface represents anything that can list nodes for a scheduler. type NodeLister interface { // We explicitly return []*v1.Node, instead of v1.NodeList, to avoid diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/types_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/types_test.go index 58ead064d..e613c8c50 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/types_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/types_test.go @@ -21,7 +21,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // EmptyPriorityMetadataProducer should returns a no-op PriorityMetadataProducer type. diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/well_known_labels.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/well_known_labels.go index 4b3ba39d1..3482649b4 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/well_known_labels.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithm/well_known_labels.go @@ -16,6 +16,10 @@ limitations under the License. package algorithm +import ( + api "k8s.io/kubernetes/pkg/apis/core" +) + const ( // TaintNodeNotReady will be added when node is not ready // and feature-gate for TaintBasedEvictions flag is enabled, @@ -71,4 +75,11 @@ const ( // from the cloud-controller-manager intitializes this node, and then removes // the taint TaintExternalCloudProvider = "node.cloudprovider.kubernetes.io/uninitialized" + + // TaintNodeShutdown when node is shutdown in external cloud provider + TaintNodeShutdown = "node.cloudprovider.kubernetes.io/shutdown" + + // NodeFieldSelectorKeyNodeName ('metadata.name') uses this as node field selector key + // when selecting node by node's name. + NodeFieldSelectorKeyNodeName = api.ObjectNameField ) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/BUILD index b260bee37..7b0f53951 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/BUILD @@ -31,7 +31,6 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core/install:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/api:go_default_library", @@ -39,6 +38,7 @@ go_test( "//pkg/scheduler/factory:go_default_library", "//vendor/k8s.io/api/core/v1: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/util/sets:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go index 77c421bc8..903b08b88 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go @@ -24,12 +24,12 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" utiltesting "k8s.io/client-go/util/testing" - "k8s.io/kubernetes/pkg/api/legacyscheme" _ "k8s.io/kubernetes/pkg/apis/core/install" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" @@ -349,7 +349,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {"name": "TaintTolerationPriority", "weight": 2}, {"name": "InterPodAffinityPriority", "weight": 2}, {"name": "MostRequestedPriority", "weight": 2} - ] + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "BindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true + }] }`, ExpectedPolicy: schedulerapi.Policy{ Predicates: []schedulerapi.PredicatePolicy{ @@ -382,6 +392,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "InterPodAffinityPriority", Weight: 2}, {Name: "MostRequestedPriority", Weight: 2}, }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + URLPrefix: "/prefix", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + BindVerb: "bind", // 1.7 was missing json tags on the BindVerb field and required "BindVerb" + EnableHTTPS: true, + TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + }}, }, }, // Do not change this JSON after the corresponding release has been tagged. @@ -419,7 +440,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {"name": "TaintTolerationPriority", "weight": 2}, {"name": "InterPodAffinityPriority", "weight": 2}, {"name": "MostRequestedPriority", "weight": 2} - ] + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "bindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true + }] }`, ExpectedPolicy: schedulerapi.Policy{ Predicates: []schedulerapi.PredicatePolicy{ @@ -453,6 +484,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "InterPodAffinityPriority", Weight: 2}, {Name: "MostRequestedPriority", Weight: 2}, }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + URLPrefix: "/prefix", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + BindVerb: "bind", // 1.8 became case-insensitive and tolerated "bindVerb" + EnableHTTPS: true, + TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + }}, }, }, // Do not change this JSON after the corresponding release has been tagged. @@ -480,7 +522,102 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {"name": "CheckVolumeBinding"}, {"name": "TestServiceAffinity", "argument": {"serviceAffinity" : {"labels" : ["region"]}}}, {"name": "TestLabelsPresence", "argument": {"labelsPresence" : {"labels" : ["foo"], "presence":true}}} + ],"priorities": [ + {"name": "EqualPriority", "weight": 2}, + {"name": "ImageLocalityPriority", "weight": 2}, + {"name": "LeastRequestedPriority", "weight": 2}, + {"name": "BalancedResourceAllocation", "weight": 2}, + {"name": "SelectorSpreadPriority", "weight": 2}, + {"name": "NodePreferAvoidPodsPriority", "weight": 2}, + {"name": "NodeAffinityPriority", "weight": 2}, + {"name": "TaintTolerationPriority", "weight": 2}, + {"name": "InterPodAffinityPriority", "weight": 2}, + {"name": "MostRequestedPriority", "weight": 2} + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "bindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true + }] + }`, + ExpectedPolicy: schedulerapi.Policy{ + Predicates: []schedulerapi.PredicatePolicy{ + {Name: "MatchNodeSelector"}, + {Name: "PodFitsResources"}, + {Name: "PodFitsHostPorts"}, + {Name: "HostName"}, + {Name: "NoDiskConflict"}, + {Name: "NoVolumeZoneConflict"}, + {Name: "PodToleratesNodeTaints"}, + {Name: "CheckNodeMemoryPressure"}, + {Name: "CheckNodeDiskPressure"}, + {Name: "CheckNodeCondition"}, + {Name: "MaxEBSVolumeCount"}, + {Name: "MaxGCEPDVolumeCount"}, + {Name: "MaxAzureDiskVolumeCount"}, + {Name: "MatchInterPodAffinity"}, + {Name: "GeneralPredicates"}, + {Name: "CheckVolumeBinding"}, + {Name: "TestServiceAffinity", Argument: &schedulerapi.PredicateArgument{ServiceAffinity: &schedulerapi.ServiceAffinity{Labels: []string{"region"}}}}, + {Name: "TestLabelsPresence", Argument: &schedulerapi.PredicateArgument{LabelsPresence: &schedulerapi.LabelsPresence{Labels: []string{"foo"}, Presence: true}}}, + }, + Priorities: []schedulerapi.PriorityPolicy{ + {Name: "EqualPriority", Weight: 2}, + {Name: "ImageLocalityPriority", Weight: 2}, + {Name: "LeastRequestedPriority", Weight: 2}, + {Name: "BalancedResourceAllocation", Weight: 2}, + {Name: "SelectorSpreadPriority", Weight: 2}, + {Name: "NodePreferAvoidPodsPriority", Weight: 2}, + {Name: "NodeAffinityPriority", Weight: 2}, + {Name: "TaintTolerationPriority", Weight: 2}, + {Name: "InterPodAffinityPriority", Weight: 2}, + {Name: "MostRequestedPriority", Weight: 2}, + }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + URLPrefix: "/prefix", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + BindVerb: "bind", // 1.9 was case-insensitive and tolerated "bindVerb" + EnableHTTPS: true, + TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + }}, + }, + }, + // Do not change this JSON after the corresponding release has been tagged. + // A failure indicates backwards compatibility with the specified release was broken. + "1.10": { + JSON: `{ + "kind": "Policy", + "apiVersion": "v1", + "predicates": [ + {"name": "MatchNodeSelector"}, + {"name": "PodFitsResources"}, + {"name": "PodFitsHostPorts"}, + {"name": "HostName"}, + {"name": "NoDiskConflict"}, + {"name": "NoVolumeZoneConflict"}, + {"name": "PodToleratesNodeTaints"}, + {"name": "CheckNodeMemoryPressure"}, + {"name": "CheckNodeDiskPressure"}, + {"name": "CheckNodePIDPressure"}, + {"name": "CheckNodeCondition"}, + {"name": "MaxEBSVolumeCount"}, + {"name": "MaxGCEPDVolumeCount"}, + {"name": "MaxAzureDiskVolumeCount"}, + {"name": "MatchInterPodAffinity"}, + {"name": "GeneralPredicates"}, + {"name": "CheckVolumeBinding"}, + {"name": "TestServiceAffinity", "argument": {"serviceAffinity" : {"labels" : ["region"]}}}, + {"name": "TestLabelsPresence", "argument": {"labelsPresence" : {"labels" : ["foo"], "presence":true}}} ],"priorities": [ {"name": "EqualPriority", "weight": 2}, {"name": "ImageLocalityPriority", "weight": 2}, @@ -492,7 +629,130 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {"name": "TaintTolerationPriority", "weight": 2}, {"name": "InterPodAffinityPriority", "weight": 2}, {"name": "MostRequestedPriority", "weight": 2} - ] + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "bindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true, + "managedResources": [{"name":"example.com/foo","ignoredByScheduler":true}], + "ignorable":true + }] + }`, + ExpectedPolicy: schedulerapi.Policy{ + Predicates: []schedulerapi.PredicatePolicy{ + {Name: "MatchNodeSelector"}, + {Name: "PodFitsResources"}, + {Name: "PodFitsHostPorts"}, + {Name: "HostName"}, + {Name: "NoDiskConflict"}, + {Name: "NoVolumeZoneConflict"}, + {Name: "PodToleratesNodeTaints"}, + {Name: "CheckNodeMemoryPressure"}, + {Name: "CheckNodeDiskPressure"}, + {Name: "CheckNodePIDPressure"}, + {Name: "CheckNodeCondition"}, + {Name: "MaxEBSVolumeCount"}, + {Name: "MaxGCEPDVolumeCount"}, + {Name: "MaxAzureDiskVolumeCount"}, + {Name: "MatchInterPodAffinity"}, + {Name: "GeneralPredicates"}, + {Name: "CheckVolumeBinding"}, + {Name: "TestServiceAffinity", Argument: &schedulerapi.PredicateArgument{ServiceAffinity: &schedulerapi.ServiceAffinity{Labels: []string{"region"}}}}, + {Name: "TestLabelsPresence", Argument: &schedulerapi.PredicateArgument{LabelsPresence: &schedulerapi.LabelsPresence{Labels: []string{"foo"}, Presence: true}}}, + }, + Priorities: []schedulerapi.PriorityPolicy{ + {Name: "EqualPriority", Weight: 2}, + {Name: "ImageLocalityPriority", Weight: 2}, + {Name: "LeastRequestedPriority", Weight: 2}, + {Name: "BalancedResourceAllocation", Weight: 2}, + {Name: "SelectorSpreadPriority", Weight: 2}, + {Name: "NodePreferAvoidPodsPriority", Weight: 2}, + {Name: "NodeAffinityPriority", Weight: 2}, + {Name: "TaintTolerationPriority", Weight: 2}, + {Name: "InterPodAffinityPriority", Weight: 2}, + {Name: "MostRequestedPriority", Weight: 2}, + }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + URLPrefix: "/prefix", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + BindVerb: "bind", // 1.10 was case-insensitive and tolerated "bindVerb" + EnableHTTPS: true, + TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, + Ignorable: true, + }}, + }, + }, + // Do not change this JSON after the corresponding release has been tagged. + // A failure indicates backwards compatibility with the specified release was broken. + "1.11": { + JSON: `{ + "kind": "Policy", + "apiVersion": "v1", + "predicates": [ + {"name": "MatchNodeSelector"}, + {"name": "PodFitsResources"}, + {"name": "PodFitsHostPorts"}, + {"name": "HostName"}, + {"name": "NoDiskConflict"}, + {"name": "NoVolumeZoneConflict"}, + {"name": "PodToleratesNodeTaints"}, + {"name": "CheckNodeMemoryPressure"}, + {"name": "CheckNodeDiskPressure"}, + {"name": "CheckNodePIDPressure"}, + {"name": "CheckNodeCondition"}, + {"name": "MaxEBSVolumeCount"}, + {"name": "MaxGCEPDVolumeCount"}, + {"name": "MaxAzureDiskVolumeCount"}, + {"name": "MatchInterPodAffinity"}, + {"name": "GeneralPredicates"}, + {"name": "CheckVolumeBinding"}, + {"name": "TestServiceAffinity", "argument": {"serviceAffinity" : {"labels" : ["region"]}}}, + {"name": "TestLabelsPresence", "argument": {"labelsPresence" : {"labels" : ["foo"], "presence":true}}} + ],"priorities": [ + {"name": "EqualPriority", "weight": 2}, + {"name": "ImageLocalityPriority", "weight": 2}, + {"name": "LeastRequestedPriority", "weight": 2}, + {"name": "BalancedResourceAllocation", "weight": 2}, + {"name": "SelectorSpreadPriority", "weight": 2}, + {"name": "NodePreferAvoidPodsPriority", "weight": 2}, + {"name": "NodeAffinityPriority", "weight": 2}, + {"name": "TaintTolerationPriority", "weight": 2}, + {"name": "InterPodAffinityPriority", "weight": 2}, + {"name": "MostRequestedPriority", "weight": 2}, + { + "name": "RequestedToCapacityRatioPriority", + "weight": 2, + "argument": { + "requestedToCapacityRatioArguments": { + "shape": [ + {"utilization": 0, "score": 0}, + {"utilization": 50, "score": 7} + ] + } + }} + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "bindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true, + "managedResources": [{"name":"example.com/foo","ignoredByScheduler":true}], + "ignorable":true + }] }`, ExpectedPolicy: schedulerapi.Policy{ Predicates: []schedulerapi.PredicatePolicy{ @@ -505,6 +765,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "PodToleratesNodeTaints"}, {Name: "CheckNodeMemoryPressure"}, {Name: "CheckNodeDiskPressure"}, + {Name: "CheckNodePIDPressure"}, {Name: "CheckNodeCondition"}, {Name: "MaxEBSVolumeCount"}, {Name: "MaxGCEPDVolumeCount"}, @@ -526,7 +787,31 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "TaintTolerationPriority", Weight: 2}, {Name: "InterPodAffinityPriority", Weight: 2}, {Name: "MostRequestedPriority", Weight: 2}, + { + Name: "RequestedToCapacityRatioPriority", + Weight: 2, + Argument: &schedulerapi.PriorityArgument{ + RequestedToCapacityRatioArguments: &schedulerapi.RequestedToCapacityRatioArguments{ + UtilizationShape: []schedulerapi.UtilizationShapePoint{ + {Utilization: 0, Score: 0}, + {Utilization: 50, Score: 7}, + }}, + }, + }, }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + URLPrefix: "/prefix", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + BindVerb: "bind", // 1.11 restored case-sensitivity, but allowed either "BindVerb" or "bindVerb" + EnableHTTPS: true, + TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, + Ignorable: true, + }}, }, }, } @@ -561,7 +846,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) informerFactory := informers.NewSharedInformerFactory(client, 0) if _, err := factory.NewConfigFactory( @@ -579,6 +864,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { informerFactory.Storage().V1().StorageClasses(), v1.DefaultHardPodAffinitySymmetricWeight, enableEquivalenceCache, + false, ).CreateFromConfig(policy); err != nil { t.Errorf("%s: Error constructing: %v", v, err) continue diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/defaults.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/defaults.go index 3267d457b..94d73b7e7 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/defaults.go @@ -17,6 +17,8 @@ limitations under the License. package defaults import ( + "github.com/golang/glog" + "k8s.io/apimachinery/pkg/util/sets" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -26,8 +28,6 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" "k8s.io/kubernetes/pkg/scheduler/core" "k8s.io/kubernetes/pkg/scheduler/factory" - - "github.com/golang/glog" ) const ( @@ -56,7 +56,7 @@ func init() { // For example: // https://github.com/kubernetes/kubernetes/blob/36a218e/plugin/pkg/scheduler/factory/factory.go#L422 - // Registers predicates and priorities that are not enabled by default, but user can pick when creating his + // Registers predicates and priorities that are not enabled by default, but user can pick when creating their // own set of priorities/predicates. // PodFitsPorts has been replaced by PodFitsHostPorts for better user understanding. @@ -77,13 +77,6 @@ func init() { // Fit is determined by node selector query. factory.RegisterFitPredicate(predicates.MatchNodeSelectorPred, predicates.PodMatchNodeSelector) - // Use equivalence class to speed up heavy predicates phase. - factory.RegisterGetEquivalencePodFunction( - func(args factory.PluginFactoryArgs) algorithm.GetEquivalencePodFunc { - return predicates.NewEquivalencePodGenerator(args.PVCInfo) - }, - ) - // ServiceSpreadingPriority is a priority config factory that spreads pods by minimizing // the number of pods (belonging to the same service) on the same node. // Register the factory so that it's available, but do not include it as part of the default priorities @@ -107,6 +100,11 @@ func init() { factory.RegisterPriorityFunction2("ImageLocalityPriority", priorities.ImageLocalityPriorityMap, nil, 1) // Optional, cluster-autoscaler friendly priority function - give used nodes higher priority. factory.RegisterPriorityFunction2("MostRequestedPriority", priorities.MostRequestedPriorityMap, nil, 1) + factory.RegisterPriorityFunction2( + "RequestedToCapacityRatioPriority", + priorities.RequestedToCapacityRatioResourceAllocationPriorityDefault().PriorityMap, + nil, + 1) } func defaultPredicates() sets.String { @@ -160,6 +158,9 @@ func defaultPredicates() sets.String { // Fit is determined by node disk pressure condition. factory.RegisterFitPredicate(predicates.CheckNodeDiskPressurePred, predicates.CheckNodeDiskPressurePredicate), + // Fit is determined by node pid pressure condition. + factory.RegisterFitPredicate(predicates.CheckNodePIDPressurePred, predicates.CheckNodePIDPressurePredicate), + // Fit is determined by node conditions: not ready, network unavailable or out of disk. factory.RegisterMandatoryFitPredicate(predicates.CheckNodeConditionPred, predicates.CheckNodeConditionPredicate), @@ -179,12 +180,20 @@ func defaultPredicates() sets.String { // ApplyFeatureGates applies algorithm by feature gates. func ApplyFeatureGates() { if utilfeature.DefaultFeatureGate.Enabled(features.TaintNodesByCondition) { - // Remove "CheckNodeCondition" predicate + // Remove "CheckNodeCondition", "CheckNodeMemoryPressure", "CheckNodePIDPressurePred" + // and "CheckNodeDiskPressure" predicates factory.RemoveFitPredicate(predicates.CheckNodeConditionPred) - // Remove Key "CheckNodeCondition" From All Algorithm Provider + factory.RemoveFitPredicate(predicates.CheckNodeMemoryPressurePred) + factory.RemoveFitPredicate(predicates.CheckNodeDiskPressurePred) + factory.RemoveFitPredicate(predicates.CheckNodePIDPressurePred) + // Remove key "CheckNodeCondition", "CheckNodeMemoryPressure" and "CheckNodeDiskPressure" + // from ALL algorithm provider // The key will be removed from all providers which in algorithmProviderMap[] // if you just want remove specific provider, call func RemovePredicateKeyFromAlgoProvider() factory.RemovePredicateKeyFromAlgorithmProviderMap(predicates.CheckNodeConditionPred) + factory.RemovePredicateKeyFromAlgorithmProviderMap(predicates.CheckNodeMemoryPressurePred) + factory.RemovePredicateKeyFromAlgorithmProviderMap(predicates.CheckNodeDiskPressurePred) + factory.RemovePredicateKeyFromAlgorithmProviderMap(predicates.CheckNodePIDPressurePred) // Fit is determined based on whether a pod can tolerate all of the node's taints factory.RegisterMandatoryFitPredicate(predicates.PodToleratesNodeTaintsPred, predicates.PodToleratesNodeTaints) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/defaults_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/defaults_test.go index d78bb6283..8c1a66de2 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/defaults_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/defaults_test.go @@ -76,6 +76,7 @@ func TestDefaultPredicates(t *testing.T) { "GeneralPredicates", "CheckNodeMemoryPressure", "CheckNodeDiskPressure", + "CheckNodePIDPressure", "CheckNodeCondition", "PodToleratesNodeTaints", predicates.CheckVolumeBindingPred, diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/api/types.go b/vendor/k8s.io/kubernetes/pkg/scheduler/api/types.go index cfc8d219e..4964349ad 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/api/types.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/api/types.go @@ -36,14 +36,6 @@ const ( MaxPriority = 10 // MaxWeight defines the max weight value. MaxWeight = MaxInt / MaxPriority - // HighestUserDefinablePriority is the highest priority for user defined priority classes. Priority values larger than 1 billion are reserved for Kubernetes system use. - HighestUserDefinablePriority = int32(1000000000) - // SystemCriticalPriority is the beginning of the range of priority values for critical system components. - SystemCriticalPriority = 2 * HighestUserDefinablePriority - // NOTE: In order to avoid conflict of names with user-defined priority classes, all the names must - // start with scheduling.SystemPriorityClassPrefix which is by default "system-". - SystemClusterCritical = "system-cluster-critical" - SystemNodeCritical = "system-node-critical" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -117,6 +109,8 @@ type PriorityArgument struct { // The priority function that checks whether a particular node has a certain label // defined or not, regardless of value LabelPreference *LabelPreference + // The RequestedToCapacityRatio priority function is parametrized with function shape. + RequestedToCapacityRatioArguments *RequestedToCapacityRatioArguments } // ServiceAffinity holds the parameters that are used to configure the corresponding predicate in scheduler policy configuration. @@ -151,6 +145,20 @@ type LabelPreference struct { Presence bool } +// RequestedToCapacityRatioArguments holds arguments specific to RequestedToCapacityRatio priority function +type RequestedToCapacityRatioArguments struct { + // Array of point defining priority function shape + UtilizationShape []UtilizationShapePoint +} + +// UtilizationShapePoint represents single point of priority function shape +type UtilizationShapePoint struct { + // Utilization (x axis). Valid values are 0 to 100. Fully utilized node maps to 100. + Utilization int + // Score assigned to given utilization (y axis). Valid values are 0 to 10. + Score int +} + // ExtenderManagedResource describes the arguments of extended resources // managed by an extender. type ExtenderManagedResource struct { @@ -168,6 +176,8 @@ type ExtenderConfig struct { URLPrefix string // Verb for the filter call, empty if not supported. This verb is appended to the URLPrefix when issuing the filter call to extender. FilterVerb string + // Verb for the preempt call, empty if not supported. This verb is appended to the URLPrefix when issuing the preempt call to extender. + PreemptVerb string // Verb for the prioritize call, empty if not supported. This verb is appended to the URLPrefix when issuing the prioritize call to extender. PrioritizeVerb string // The numeric multiplier for the node scores that the prioritize call generates. @@ -198,13 +208,53 @@ type ExtenderConfig struct { // will skip checking the resource in predicates. // +optional ManagedResources []ExtenderManagedResource + // Ignorable specifies if the extender is ignorable, i.e. scheduling should not + // fail when the extender returns an error or is not reachable. + Ignorable bool +} + +// ExtenderPreemptionResult represents the result returned by preemption phase of extender. +type ExtenderPreemptionResult struct { + NodeNameToMetaVictims map[string]*MetaVictims +} + +// ExtenderPreemptionArgs represents the arguments needed by the extender to preempt pods on nodes. +type ExtenderPreemptionArgs struct { + // Pod being scheduled + Pod *v1.Pod + // Victims map generated by scheduler preemption phase + // Only set NodeNameToMetaVictims if ExtenderConfig.NodeCacheCapable == true. Otherwise, only set NodeNameToVictims. + NodeNameToVictims map[string]*Victims + NodeNameToMetaVictims map[string]*MetaVictims +} + +// Victims represents: +// pods: a group of pods expected to be preempted. +// numPDBViolations: the count of violations of PodDisruptionBudget +type Victims struct { + Pods []*v1.Pod + NumPDBViolations int +} + +// MetaPod represent identifier for a v1.Pod +type MetaPod struct { + UID string +} + +// MetaVictims represents: +// pods: a group of pods expected to be preempted. +// Only Pod identifiers will be sent and user are expect to get v1.Pod in their own way. +// numPDBViolations: the count of violations of PodDisruptionBudget +type MetaVictims struct { + Pods []*MetaPod + NumPDBViolations int } // ExtenderArgs represents the arguments needed by the extender to filter/prioritize // nodes for a pod. type ExtenderArgs struct { // Pod being scheduled - Pod v1.Pod + Pod *v1.Pod // List of candidate nodes where the pod can be scheduled; to be populated // only if ExtenderConfig.NodeCacheCapable == false Nodes *v1.NodeList @@ -259,12 +309,6 @@ type HostPriority struct { // HostPriorityList declares a []HostPriority type. type HostPriorityList []HostPriority -// SystemPriorityClasses defines special priority classes which are used by system critical pods that should not be preempted by workload pods. -var SystemPriorityClasses = map[string]int32{ - SystemClusterCritical: SystemCriticalPriority, - SystemNodeCritical: SystemCriticalPriority + 1000, -} - func (h HostPriorityList) Len() int { return len(h) } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/api/v1/types.go b/vendor/k8s.io/kubernetes/pkg/scheduler/api/v1/types.go index 32ac25795..10ea29bb3 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/api/v1/types.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/api/v1/types.go @@ -17,6 +17,7 @@ limitations under the License. package v1 import ( + gojson "encoding/json" "time" apiv1 "k8s.io/api/core/v1" @@ -91,6 +92,8 @@ type PriorityArgument struct { // The priority function that checks whether a particular node has a certain label // defined or not, regardless of value LabelPreference *LabelPreference `json:"labelPreference"` + // The RequestedToCapacityRatio priority function is parametrized with function shape. + RequestedToCapacityRatioArguments *RequestedToCapacityRatioArguments `json:"requestedToCapacityRatioArguments"` } // ServiceAffinity holds the parameters that are used to configure the corresponding predicate in scheduler policy configuration. @@ -125,6 +128,20 @@ type LabelPreference struct { Presence bool `json:"presence"` } +// RequestedToCapacityRatioArguments holds arguments specific to RequestedToCapacityRatio priority function +type RequestedToCapacityRatioArguments struct { + // Array of point defining priority function shape + UtilizationShape []UtilizationShapePoint `json:"shape"` +} + +// UtilizationShapePoint represents single point of priority function shape +type UtilizationShapePoint struct { + // Utilization (x axis). Valid values are 0 to 100. Fully utilized node maps to 100. + Utilization int `json:"utilization"` + // Score assigned to given utilization (y axis). Valid values are 0 to 10. + Score int `json:"score"` +} + // ExtenderManagedResource describes the arguments of extended resources // managed by an extender. type ExtenderManagedResource struct { @@ -142,6 +159,8 @@ type ExtenderConfig struct { URLPrefix string `json:"urlPrefix"` // Verb for the filter call, empty if not supported. This verb is appended to the URLPrefix when issuing the filter call to extender. FilterVerb string `json:"filterVerb,omitempty"` + // Verb for the preempt call, empty if not supported. This verb is appended to the URLPrefix when issuing the preempt call to extender. + PreemptVerb string `json:"preemptVerb,omitempty"` // Verb for the prioritize call, empty if not supported. This verb is appended to the URLPrefix when issuing the prioritize call to extender. PrioritizeVerb string `json:"prioritizeVerb,omitempty"` // The numeric multiplier for the node scores that the prioritize call generates. @@ -172,13 +191,28 @@ type ExtenderConfig struct { // will skip checking the resource in predicates. // +optional ManagedResources []ExtenderManagedResource `json:"managedResources,omitempty"` + // Ignorable specifies if the extender is ignorable, i.e. scheduling should not + // fail when the extender returns an error or is not reachable. + Ignorable bool `json:"ignorable,omitempty"` +} + +// caseInsensitiveExtenderConfig is a type alias which lets us use the stdlib case-insensitive decoding +// to preserve compatibility with incorrectly specified scheduler config fields: +// * BindVerb, which originally did not specify a json tag, and required upper-case serialization in 1.7 +// * TLSConfig, which uses a struct not intended for serialization, and does not include any json tags +type caseInsensitiveExtenderConfig *ExtenderConfig + +// UnmarshalJSON implements the json.Unmarshaller interface. +// This preserves compatibility with incorrect case-insensitive configuration fields. +func (t *ExtenderConfig) UnmarshalJSON(b []byte) error { + return gojson.Unmarshal(b, caseInsensitiveExtenderConfig(t)) } // ExtenderArgs represents the arguments needed by the extender to filter/prioritize // nodes for a pod. type ExtenderArgs struct { // Pod being scheduled - Pod apiv1.Pod `json:"pod"` + Pod *apiv1.Pod `json:"pod"` // List of candidate nodes where the pod can be scheduled; to be populated // only if ExtenderConfig.NodeCacheCapable == false Nodes *apiv1.NodeList `json:"nodes,omitempty"` @@ -187,6 +221,43 @@ type ExtenderArgs struct { NodeNames *[]string `json:"nodenames,omitempty"` } +// ExtenderPreemptionResult represents the result returned by preemption phase of extender. +type ExtenderPreemptionResult struct { + NodeNameToMetaVictims map[string]*MetaVictims `json:"nodeNameToMetaVictims,omitempty"` +} + +// ExtenderPreemptionArgs represents the arguments needed by the extender to preempt pods on nodes. +type ExtenderPreemptionArgs struct { + // Pod being scheduled + Pod *apiv1.Pod `json:"pod"` + // Victims map generated by scheduler preemption phase + // Only set NodeNameToMetaVictims if ExtenderConfig.NodeCacheCapable == true. Otherwise, only set NodeNameToVictims. + NodeNameToVictims map[string]*Victims `json:"nodeToVictims,omitempty"` + NodeNameToMetaVictims map[string]*MetaVictims `json:"nodeNameToMetaVictims,omitempty"` +} + +// Victims represents: +// pods: a group of pods expected to be preempted. +// numPDBViolations: the count of violations of PodDisruptionBudget +type Victims struct { + Pods []*apiv1.Pod `json:"pods"` + NumPDBViolations int `json:"numPDBViolations"` +} + +// MetaPod represent identifier for a v1.Pod +type MetaPod struct { + UID string `json:"uid"` +} + +// MetaVictims represents: +// pods: a group of pods expected to be preempted. +// Only Pod identifiers will be sent and user are expect to get v1.Pod in their own way. +// numPDBViolations: the count of violations of PodDisruptionBudget +type MetaVictims struct { + Pods []*MetaPod `json:"pods"` + NumPDBViolations int `json:"numPDBViolations"` +} + // FailedNodesMap represents the filtered out nodes, with node names and failure messages type FailedNodesMap map[string]string diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/api/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/scheduler/api/v1/zz_generated.deepcopy.go index 98f8fcbf7..cbe8dc90c 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/api/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/api/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -29,7 +29,15 @@ import ( // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtenderArgs) DeepCopyInto(out *ExtenderArgs) { *out = *in - in.Pod.DeepCopyInto(&out.Pod) + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + if *in == nil { + *out = nil + } else { + *out = new(core_v1.Pod) + (*in).DeepCopyInto(*out) + } + } if in.Nodes != nil { in, out := &in.Nodes, &out.Nodes if *in == nil { @@ -188,6 +196,83 @@ func (in *ExtenderManagedResource) DeepCopy() *ExtenderManagedResource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtenderPreemptionArgs) DeepCopyInto(out *ExtenderPreemptionArgs) { + *out = *in + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + if *in == nil { + *out = nil + } else { + *out = new(core_v1.Pod) + (*in).DeepCopyInto(*out) + } + } + if in.NodeNameToVictims != nil { + in, out := &in.NodeNameToVictims, &out.NodeNameToVictims + *out = make(map[string]*Victims, len(*in)) + for key, val := range *in { + if val == nil { + (*out)[key] = nil + } else { + (*out)[key] = new(Victims) + val.DeepCopyInto((*out)[key]) + } + } + } + if in.NodeNameToMetaVictims != nil { + in, out := &in.NodeNameToMetaVictims, &out.NodeNameToMetaVictims + *out = make(map[string]*MetaVictims, len(*in)) + for key, val := range *in { + if val == nil { + (*out)[key] = nil + } else { + (*out)[key] = new(MetaVictims) + val.DeepCopyInto((*out)[key]) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderPreemptionArgs. +func (in *ExtenderPreemptionArgs) DeepCopy() *ExtenderPreemptionArgs { + if in == nil { + return nil + } + out := new(ExtenderPreemptionArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtenderPreemptionResult) DeepCopyInto(out *ExtenderPreemptionResult) { + *out = *in + if in.NodeNameToMetaVictims != nil { + in, out := &in.NodeNameToMetaVictims, &out.NodeNameToMetaVictims + *out = make(map[string]*MetaVictims, len(*in)) + for key, val := range *in { + if val == nil { + (*out)[key] = nil + } else { + (*out)[key] = new(MetaVictims) + val.DeepCopyInto((*out)[key]) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderPreemptionResult. +func (in *ExtenderPreemptionResult) DeepCopy() *ExtenderPreemptionResult { + if in == nil { + return nil + } + out := new(ExtenderPreemptionResult) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in FailedNodesMap) DeepCopyInto(out *FailedNodesMap) { { @@ -283,6 +368,50 @@ func (in *LabelsPresence) DeepCopy() *LabelsPresence { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetaPod) DeepCopyInto(out *MetaPod) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetaPod. +func (in *MetaPod) DeepCopy() *MetaPod { + if in == nil { + return nil + } + out := new(MetaPod) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetaVictims) DeepCopyInto(out *MetaVictims) { + *out = *in + if in.Pods != nil { + in, out := &in.Pods, &out.Pods + *out = make([]*MetaPod, len(*in)) + for i := range *in { + if (*in)[i] == nil { + (*out)[i] = nil + } else { + (*out)[i] = new(MetaPod) + (*in)[i].DeepCopyInto((*out)[i]) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetaVictims. +func (in *MetaVictims) DeepCopy() *MetaVictims { + if in == nil { + return nil + } + out := new(MetaVictims) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Policy) DeepCopyInto(out *Policy) { *out = *in @@ -409,6 +538,15 @@ func (in *PriorityArgument) DeepCopyInto(out *PriorityArgument) { **out = **in } } + if in.RequestedToCapacityRatioArguments != nil { + in, out := &in.RequestedToCapacityRatioArguments, &out.RequestedToCapacityRatioArguments + if *in == nil { + *out = nil + } else { + *out = new(RequestedToCapacityRatioArguments) + (*in).DeepCopyInto(*out) + } + } return } @@ -447,6 +585,27 @@ func (in *PriorityPolicy) DeepCopy() *PriorityPolicy { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RequestedToCapacityRatioArguments) DeepCopyInto(out *RequestedToCapacityRatioArguments) { + *out = *in + if in.UtilizationShape != nil { + in, out := &in.UtilizationShape, &out.UtilizationShape + *out = make([]UtilizationShapePoint, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestedToCapacityRatioArguments. +func (in *RequestedToCapacityRatioArguments) DeepCopy() *RequestedToCapacityRatioArguments { + if in == nil { + return nil + } + out := new(RequestedToCapacityRatioArguments) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceAffinity) DeepCopyInto(out *ServiceAffinity) { *out = *in @@ -483,3 +642,47 @@ func (in *ServiceAntiAffinity) DeepCopy() *ServiceAntiAffinity { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UtilizationShapePoint) DeepCopyInto(out *UtilizationShapePoint) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UtilizationShapePoint. +func (in *UtilizationShapePoint) DeepCopy() *UtilizationShapePoint { + if in == nil { + return nil + } + out := new(UtilizationShapePoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Victims) DeepCopyInto(out *Victims) { + *out = *in + if in.Pods != nil { + in, out := &in.Pods, &out.Pods + *out = make([]*core_v1.Pod, len(*in)) + for i := range *in { + if (*in)[i] == nil { + (*out)[i] = nil + } else { + (*out)[i] = new(core_v1.Pod) + (*in)[i].DeepCopyInto((*out)[i]) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Victims. +func (in *Victims) DeepCopy() *Victims { + if in == nil { + return nil + } + out := new(Victims) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/api/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/api/validation/validation_test.go index ede1b2c42..9c3a5cd35 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/api/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/api/validation/validation_test.go @@ -61,6 +61,10 @@ func TestValidatePolicy(t *testing.T) { policy: api.Policy{ExtenderConfigs: []api.ExtenderConfig{{URLPrefix: "http://127.0.0.1:8081/extender", FilterVerb: "filter"}}}, expected: nil, }, + { + policy: api.Policy{ExtenderConfigs: []api.ExtenderConfig{{URLPrefix: "http://127.0.0.1:8081/extender", PreemptVerb: "preempt"}}}, + expected: nil, + }, { policy: api.Policy{ ExtenderConfigs: []api.ExtenderConfig{ diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/api/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/pkg/scheduler/api/zz_generated.deepcopy.go index 1986933b9..d8654dd27 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/api/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/api/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -29,7 +29,15 @@ import ( // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtenderArgs) DeepCopyInto(out *ExtenderArgs) { *out = *in - in.Pod.DeepCopyInto(&out.Pod) + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + if *in == nil { + *out = nil + } else { + *out = new(v1.Pod) + (*in).DeepCopyInto(*out) + } + } if in.Nodes != nil { in, out := &in.Nodes, &out.Nodes if *in == nil { @@ -188,6 +196,83 @@ func (in *ExtenderManagedResource) DeepCopy() *ExtenderManagedResource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtenderPreemptionArgs) DeepCopyInto(out *ExtenderPreemptionArgs) { + *out = *in + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + if *in == nil { + *out = nil + } else { + *out = new(v1.Pod) + (*in).DeepCopyInto(*out) + } + } + if in.NodeNameToVictims != nil { + in, out := &in.NodeNameToVictims, &out.NodeNameToVictims + *out = make(map[string]*Victims, len(*in)) + for key, val := range *in { + if val == nil { + (*out)[key] = nil + } else { + (*out)[key] = new(Victims) + val.DeepCopyInto((*out)[key]) + } + } + } + if in.NodeNameToMetaVictims != nil { + in, out := &in.NodeNameToMetaVictims, &out.NodeNameToMetaVictims + *out = make(map[string]*MetaVictims, len(*in)) + for key, val := range *in { + if val == nil { + (*out)[key] = nil + } else { + (*out)[key] = new(MetaVictims) + val.DeepCopyInto((*out)[key]) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderPreemptionArgs. +func (in *ExtenderPreemptionArgs) DeepCopy() *ExtenderPreemptionArgs { + if in == nil { + return nil + } + out := new(ExtenderPreemptionArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtenderPreemptionResult) DeepCopyInto(out *ExtenderPreemptionResult) { + *out = *in + if in.NodeNameToMetaVictims != nil { + in, out := &in.NodeNameToMetaVictims, &out.NodeNameToMetaVictims + *out = make(map[string]*MetaVictims, len(*in)) + for key, val := range *in { + if val == nil { + (*out)[key] = nil + } else { + (*out)[key] = new(MetaVictims) + val.DeepCopyInto((*out)[key]) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderPreemptionResult. +func (in *ExtenderPreemptionResult) DeepCopy() *ExtenderPreemptionResult { + if in == nil { + return nil + } + out := new(ExtenderPreemptionResult) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in FailedNodesMap) DeepCopyInto(out *FailedNodesMap) { { @@ -283,6 +368,50 @@ func (in *LabelsPresence) DeepCopy() *LabelsPresence { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetaPod) DeepCopyInto(out *MetaPod) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetaPod. +func (in *MetaPod) DeepCopy() *MetaPod { + if in == nil { + return nil + } + out := new(MetaPod) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetaVictims) DeepCopyInto(out *MetaVictims) { + *out = *in + if in.Pods != nil { + in, out := &in.Pods, &out.Pods + *out = make([]*MetaPod, len(*in)) + for i := range *in { + if (*in)[i] == nil { + (*out)[i] = nil + } else { + (*out)[i] = new(MetaPod) + (*in)[i].DeepCopyInto((*out)[i]) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetaVictims. +func (in *MetaVictims) DeepCopy() *MetaVictims { + if in == nil { + return nil + } + out := new(MetaVictims) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Policy) DeepCopyInto(out *Policy) { *out = *in @@ -409,6 +538,15 @@ func (in *PriorityArgument) DeepCopyInto(out *PriorityArgument) { **out = **in } } + if in.RequestedToCapacityRatioArguments != nil { + in, out := &in.RequestedToCapacityRatioArguments, &out.RequestedToCapacityRatioArguments + if *in == nil { + *out = nil + } else { + *out = new(RequestedToCapacityRatioArguments) + (*in).DeepCopyInto(*out) + } + } return } @@ -447,6 +585,27 @@ func (in *PriorityPolicy) DeepCopy() *PriorityPolicy { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RequestedToCapacityRatioArguments) DeepCopyInto(out *RequestedToCapacityRatioArguments) { + *out = *in + if in.UtilizationShape != nil { + in, out := &in.UtilizationShape, &out.UtilizationShape + *out = make([]UtilizationShapePoint, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestedToCapacityRatioArguments. +func (in *RequestedToCapacityRatioArguments) DeepCopy() *RequestedToCapacityRatioArguments { + if in == nil { + return nil + } + out := new(RequestedToCapacityRatioArguments) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceAffinity) DeepCopyInto(out *ServiceAffinity) { *out = *in @@ -483,3 +642,47 @@ func (in *ServiceAntiAffinity) DeepCopy() *ServiceAntiAffinity { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UtilizationShapePoint) DeepCopyInto(out *UtilizationShapePoint) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UtilizationShapePoint. +func (in *UtilizationShapePoint) DeepCopy() *UtilizationShapePoint { + if in == nil { + return nil + } + out := new(UtilizationShapePoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Victims) DeepCopyInto(out *Victims) { + *out = *in + if in.Pods != nil { + in, out := &in.Pods, &out.Pods + *out = make([]*v1.Pod, len(*in)) + for i := range *in { + if (*in)[i] == nil { + (*out)[i] = nil + } else { + (*out)[i] = new(v1.Pod) + (*in)[i].DeepCopyInto((*out)[i]) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Victims. +func (in *Victims) DeepCopy() *Victims { + if in == nil { + return nil + } + out := new(Victims) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/cache/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/BUILD new file mode 100644 index 000000000..eece6843d --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/BUILD @@ -0,0 +1,64 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "cache.go", + "interface.go", + "node_info.go", + "util.go", + ], + importpath = "k8s.io/kubernetes/pkg/scheduler/cache", + visibility = ["//visibility:public"], + deps = [ + "//pkg/apis/core/v1/helper:go_default_library", + "//pkg/features:go_default_library", + "//pkg/scheduler/algorithm/priorities/util:go_default_library", + "//pkg/scheduler/util:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/policy/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "cache_test.go", + "node_info_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//pkg/features:go_default_library", + "//pkg/scheduler/algorithm/priorities/util:go_default_library", + "//pkg/scheduler/util:go_default_library", + "//pkg/util/parsers:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/policy/v1beta1: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/labels: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/wait:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/cache.go b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/cache.go similarity index 90% rename from vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/cache.go rename to vendor/k8s.io/kubernetes/pkg/scheduler/cache/cache.go index 78cdca25b..38e26f51b 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/cache.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/cache.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package schedulercache +package cache import ( "fmt" @@ -24,6 +24,8 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/wait" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" "github.com/golang/glog" policy "k8s.io/api/policy/v1beta1" @@ -80,10 +82,42 @@ func newSchedulerCache(ttl, period time.Duration, stop <-chan struct{}) *schedul } } +// Snapshot takes a snapshot of the current schedulerCache. The method has performance impact, +// and should be only used in non-critical path. +func (cache *schedulerCache) Snapshot() *Snapshot { + cache.mu.Lock() + defer cache.mu.Unlock() + + nodes := make(map[string]*NodeInfo) + for k, v := range cache.nodes { + nodes[k] = v.Clone() + } + + assumedPods := make(map[string]bool) + for k, v := range cache.assumedPods { + assumedPods[k] = v + } + + pdbs := make(map[string]*policy.PodDisruptionBudget) + for k, v := range cache.pdbs { + pdbs[k] = v.DeepCopy() + } + + return &Snapshot{ + Nodes: nodes, + AssumedPods: assumedPods, + Pdbs: pdbs, + } +} + func (cache *schedulerCache) UpdateNodeNameToInfoMap(nodeNameToInfo map[string]*NodeInfo) error { cache.mu.Lock() defer cache.mu.Unlock() for name, info := range cache.nodes { + if utilfeature.DefaultFeatureGate.Enabled(features.BalanceAttachedNodeVolumes) && info.TransientInfo != nil { + // Transient scheduler info is reset here. + info.TransientInfo.resetTransientSchedulerInfo() + } if current, ok := nodeNameToInfo[name]; !ok || current.generation != info.generation { nodeNameToInfo[name] = info.Clone() } @@ -398,7 +432,7 @@ func (cache *schedulerCache) AddPDB(pdb *policy.PodDisruptionBudget) error { defer cache.mu.Unlock() // Unconditionally update cache. - cache.pdbs[pdb.Name] = pdb + cache.pdbs[string(pdb.UID)] = pdb return nil } @@ -410,7 +444,7 @@ func (cache *schedulerCache) RemovePDB(pdb *policy.PodDisruptionBudget) error { cache.mu.Lock() defer cache.mu.Unlock() - delete(cache.pdbs, pdb.Name) + delete(cache.pdbs, string(pdb.UID)) return nil } @@ -426,6 +460,13 @@ func (cache *schedulerCache) ListPDBs(selector labels.Selector) ([]*policy.PodDi return pdbs, nil } +func (cache *schedulerCache) IsUpToDate(n *NodeInfo) bool { + cache.mu.Lock() + defer cache.mu.Unlock() + node, ok := cache.nodes[n.Node().Name] + return ok && n.generation == node.generation +} + func (cache *schedulerCache) run() { go wait.Until(cache.cleanupExpiredAssumedPods, cache.period, cache.stop) } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/cache_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/cache_test.go similarity index 83% rename from vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/cache_test.go rename to vendor/k8s.io/kubernetes/pkg/scheduler/cache/cache_test.go index 724f25b4f..597211377 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/cache_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/cache_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package schedulercache +package cache import ( "fmt" @@ -30,6 +30,9 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/wait" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedutil "k8s.io/kubernetes/pkg/scheduler/util" ) @@ -73,6 +76,8 @@ func (b *hostPortInfoBuilder) build() schedutil.HostPortInfo { // TestAssumePodScheduled tests that after a pod is assumed, its information is aggregated // on node level. func TestAssumePodScheduled(t *testing.T) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) nodeName := "node" testPods := []*v1.Pod{ makeBasePod(t, nodeName, "test", "100m", "500", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 80, Protocol: "TCP"}}), @@ -99,9 +104,11 @@ func TestAssumePodScheduled(t *testing.T) { MilliCPU: 100, Memory: 500, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[0]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), + imageSizes: map[string]int64{}, }, }, { pods: []*v1.Pod{testPods[1], testPods[2]}, @@ -114,9 +121,11 @@ func TestAssumePodScheduled(t *testing.T) { MilliCPU: 300, Memory: 1524, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[1], testPods[2]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).add("TCP", "127.0.0.1", 8080).build(), + imageSizes: map[string]int64{}, }, }, { // test non-zero request pods: []*v1.Pod{testPods[3]}, @@ -129,9 +138,11 @@ func TestAssumePodScheduled(t *testing.T) { MilliCPU: priorityutil.DefaultMilliCPURequest, Memory: priorityutil.DefaultMemoryRequest, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[3]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), + imageSizes: map[string]int64{}, }, }, { pods: []*v1.Pod{testPods[4]}, @@ -145,9 +156,11 @@ func TestAssumePodScheduled(t *testing.T) { MilliCPU: 100, Memory: 500, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[4]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), + imageSizes: map[string]int64{}, }, }, { pods: []*v1.Pod{testPods[4], testPods[5]}, @@ -161,9 +174,11 @@ func TestAssumePodScheduled(t *testing.T) { MilliCPU: 300, Memory: 1524, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[4], testPods[5]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).add("TCP", "127.0.0.1", 8080).build(), + imageSizes: map[string]int64{}, }, }, { pods: []*v1.Pod{testPods[6]}, @@ -176,9 +191,11 @@ func TestAssumePodScheduled(t *testing.T) { MilliCPU: 100, Memory: 500, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[6]}, usedPorts: newHostPortInfoBuilder().build(), + imageSizes: map[string]int64{}, }, }, } @@ -219,6 +236,8 @@ func assumeAndFinishBinding(cache *schedulerCache, pod *v1.Pod, assumedTime time // TestExpirePod tests that assumed pods will be removed if expired. // The removal will be reflected in node info. func TestExpirePod(t *testing.T) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) nodeName := "node" testPods := []*v1.Pod{ makeBasePod(t, nodeName, "test-1", "100m", "500", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 80, Protocol: "TCP"}}), @@ -252,9 +271,11 @@ func TestExpirePod(t *testing.T) { MilliCPU: 200, Memory: 1024, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[1]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 8080).build(), + imageSizes: map[string]int64{}, }, }} @@ -276,6 +297,8 @@ func TestExpirePod(t *testing.T) { // TestAddPodWillConfirm tests that a pod being Add()ed will be confirmed if assumed. // The pod info should still exist after manually expiring unconfirmed pods. func TestAddPodWillConfirm(t *testing.T) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) nodeName := "node" now := time.Now() ttl := 10 * time.Second @@ -301,9 +324,11 @@ func TestAddPodWillConfirm(t *testing.T) { MilliCPU: 100, Memory: 500, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[0]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), + imageSizes: map[string]int64{}, }, }} @@ -326,6 +351,46 @@ func TestAddPodWillConfirm(t *testing.T) { } } +func TestSnapshot(t *testing.T) { + nodeName := "node" + now := time.Now() + ttl := 10 * time.Second + + testPods := []*v1.Pod{ + makeBasePod(t, nodeName, "test-1", "100m", "500", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 80, Protocol: "TCP"}}), + makeBasePod(t, nodeName, "test-2", "200m", "1Ki", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 80, Protocol: "TCP"}}), + } + tests := []struct { + podsToAssume []*v1.Pod + podsToAdd []*v1.Pod + }{{ // two pod were assumed at same time. But first one is called Add() and gets confirmed. + podsToAssume: []*v1.Pod{testPods[0], testPods[1]}, + podsToAdd: []*v1.Pod{testPods[0]}, + }} + + for _, tt := range tests { + cache := newSchedulerCache(ttl, time.Second, nil) + for _, podToAssume := range tt.podsToAssume { + if err := assumeAndFinishBinding(cache, podToAssume, now); err != nil { + t.Fatalf("assumePod failed: %v", err) + } + } + for _, podToAdd := range tt.podsToAdd { + if err := cache.AddPod(podToAdd); err != nil { + t.Fatalf("AddPod failed: %v", err) + } + } + + snapshot := cache.Snapshot() + if !reflect.DeepEqual(snapshot.Nodes, cache.nodes) { + t.Fatalf("expect \n%+v; got \n%+v", cache.nodes, snapshot.Nodes) + } + if !reflect.DeepEqual(snapshot.AssumedPods, cache.assumedPods) { + t.Fatalf("expect \n%+v; got \n%+v", cache.assumedPods, snapshot.AssumedPods) + } + } +} + // TestAddPodWillReplaceAssumed tests that a pod being Add()ed will replace any assumed pod. func TestAddPodWillReplaceAssumed(t *testing.T) { now := time.Now() @@ -356,9 +421,11 @@ func TestAddPodWillReplaceAssumed(t *testing.T) { MilliCPU: 200, Memory: 500, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{updatedPod.DeepCopy()}, usedPorts: newHostPortInfoBuilder().add("TCP", "0.0.0.0", 90).build(), + imageSizes: map[string]int64{}, }, }, }} @@ -390,6 +457,8 @@ func TestAddPodWillReplaceAssumed(t *testing.T) { // TestAddPodAfterExpiration tests that a pod being Add()ed will be added back if expired. func TestAddPodAfterExpiration(t *testing.T) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) nodeName := "node" ttl := 10 * time.Second basePod := makeBasePod(t, nodeName, "test", "100m", "500", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 80, Protocol: "TCP"}}) @@ -408,9 +477,11 @@ func TestAddPodAfterExpiration(t *testing.T) { MilliCPU: 100, Memory: 500, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{basePod}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), + imageSizes: map[string]int64{}, }, }} @@ -437,6 +508,8 @@ func TestAddPodAfterExpiration(t *testing.T) { // TestUpdatePod tests that a pod will be updated if added before. func TestUpdatePod(t *testing.T) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) nodeName := "node" ttl := 10 * time.Second testPods := []*v1.Pod{ @@ -444,7 +517,6 @@ func TestUpdatePod(t *testing.T) { makeBasePod(t, nodeName, "test", "200m", "1Ki", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 8080, Protocol: "TCP"}}), } tests := []struct { - podsToAssume []*v1.Pod podsToAdd []*v1.Pod podsToUpdate []*v1.Pod @@ -461,9 +533,11 @@ func TestUpdatePod(t *testing.T) { MilliCPU: 200, Memory: 1024, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[1]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 8080).build(), + imageSizes: map[string]int64{}, }, { requestedResource: &Resource{ MilliCPU: 100, @@ -473,9 +547,11 @@ func TestUpdatePod(t *testing.T) { MilliCPU: 100, Memory: 500, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[0]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), + imageSizes: map[string]int64{}, }}, }} @@ -503,6 +579,8 @@ func TestUpdatePod(t *testing.T) { // TestExpireAddUpdatePod test the sequence that a pod is expired, added, then updated func TestExpireAddUpdatePod(t *testing.T) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) nodeName := "node" ttl := 10 * time.Second testPods := []*v1.Pod{ @@ -528,9 +606,11 @@ func TestExpireAddUpdatePod(t *testing.T) { MilliCPU: 200, Memory: 1024, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[1]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 8080).build(), + imageSizes: map[string]int64{}, }, { requestedResource: &Resource{ MilliCPU: 100, @@ -540,9 +620,11 @@ func TestExpireAddUpdatePod(t *testing.T) { MilliCPU: 100, Memory: 500, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{testPods[0]}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), + imageSizes: map[string]int64{}, }}, }} @@ -598,6 +680,8 @@ func makePodWithEphemeralStorage(nodeName, ephemeralStorage string) *v1.Pod { } func TestEphemeralStorageResource(t *testing.T) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) nodeName := "node" podE := makePodWithEphemeralStorage(nodeName, "500") tests := []struct { @@ -614,9 +698,11 @@ func TestEphemeralStorageResource(t *testing.T) { MilliCPU: priorityutil.DefaultMilliCPURequest, Memory: priorityutil.DefaultMemoryRequest, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{podE}, usedPorts: schedutil.HostPortInfo{}, + imageSizes: map[string]int64{}, }, }, } @@ -641,6 +727,8 @@ func TestEphemeralStorageResource(t *testing.T) { // TestRemovePod tests after added pod is removed, its information should also be subtracted. func TestRemovePod(t *testing.T) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) nodeName := "node" basePod := makeBasePod(t, nodeName, "test", "100m", "500", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 80, Protocol: "TCP"}}) tests := []struct { @@ -657,9 +745,11 @@ func TestRemovePod(t *testing.T) { MilliCPU: 100, Memory: 500, }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, pods: []*v1.Pod{basePod}, usedPorts: newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), + imageSizes: map[string]int64{}, }, }} @@ -917,6 +1007,8 @@ func TestNodeOperators(t *testing.T) { t.Errorf("Failed to find node %v in schedulercache.", node.Name) } + // Generations are globally unique. We check in our unit tests that they are incremented correctly. + expected.generation = got.generation if !reflect.DeepEqual(got, expected) { t.Errorf("Failed to add node into schedulercache:\n got: %+v \nexpected: %+v", got, expected) } @@ -928,6 +1020,7 @@ func TestNodeOperators(t *testing.T) { if !found || len(cachedNodes) != 1 { t.Errorf("failed to dump cached nodes:\n got: %v \nexpected: %v", cachedNodes, cache.nodes) } + expected.generation = newNode.generation if !reflect.DeepEqual(newNode, expected) { t.Errorf("Failed to clone node:\n got: %+v, \n expected: %+v", newNode, expected) } @@ -935,12 +1028,15 @@ func TestNodeOperators(t *testing.T) { // Case 3: update node attribute successfully. node.Status.Allocatable[v1.ResourceMemory] = mem50m expected.allocatableResource.Memory = mem50m.Value() - expected.generation++ cache.UpdateNode(nil, node) got, found = cache.nodes[node.Name] if !found { t.Errorf("Failed to find node %v in schedulercache after UpdateNode.", node.Name) } + if got.generation <= expected.generation { + t.Errorf("generation is not incremented. got: %v, expected: %v", got.generation, expected.generation) + } + expected.generation = got.generation if !reflect.DeepEqual(got, expected) { t.Errorf("Failed to update node in schedulercache:\n got: %+v \nexpected: %+v", got, expected) @@ -962,6 +1058,17 @@ func BenchmarkList1kNodes30kPods(b *testing.B) { } } +func BenchmarkUpdate1kNodes30kPods(b *testing.B) { + // Enable volumesOnNodeForBalancing to do balanced resource allocation + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.BalanceAttachedNodeVolumes)) + cache := setupCacheOf1kNodes30kPods(b) + b.ResetTimer() + for n := 0; n < b.N; n++ { + cachedNodes := map[string]*NodeInfo{} + cache.UpdateNodeNameToInfoMap(cachedNodes) + } +} + func BenchmarkExpire100Pods(b *testing.B) { benchmarkExpire(b, 100) } @@ -1052,13 +1159,14 @@ func setupCacheWithAssumedPods(b *testing.B, podNum int, assumedTime time.Time) return cache } -func makePDB(name, namespace string, labels map[string]string, minAvailable int) *v1beta1.PodDisruptionBudget { +func makePDB(name, namespace string, uid types.UID, labels map[string]string, minAvailable int) *v1beta1.PodDisruptionBudget { intstrMin := intstr.FromInt(minAvailable) pdb := &v1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: name, Labels: labels, + UID: uid, }, Spec: v1beta1.PodDisruptionBudgetSpec{ MinAvailable: &intstrMin, @@ -1073,14 +1181,14 @@ func makePDB(name, namespace string, labels map[string]string, minAvailable int) func TestPDBOperations(t *testing.T) { ttl := 10 * time.Second testPDBs := []*v1beta1.PodDisruptionBudget{ - makePDB("pdb0", "ns1", map[string]string{"tkey1": "tval1"}, 3), - makePDB("pdb1", "ns1", map[string]string{"tkey1": "tval1", "tkey2": "tval2"}, 1), - makePDB("pdb2", "ns3", map[string]string{"tkey3": "tval3", "tkey2": "tval2"}, 10), + makePDB("pdb0", "ns1", "uid0", map[string]string{"tkey1": "tval1"}, 3), + makePDB("pdb1", "ns1", "uid1", map[string]string{"tkey1": "tval1", "tkey2": "tval2"}, 1), + makePDB("pdb2", "ns3", "uid2", map[string]string{"tkey3": "tval3", "tkey2": "tval2"}, 10), } updatedPDBs := []*v1beta1.PodDisruptionBudget{ - makePDB("pdb0", "ns1", map[string]string{"tkey4": "tval4"}, 8), - makePDB("pdb1", "ns1", map[string]string{"tkey1": "tval1"}, 1), - makePDB("pdb2", "ns3", map[string]string{"tkey3": "tval3", "tkey1": "tval1", "tkey2": "tval2"}, 10), + makePDB("pdb0", "ns1", "uid0", map[string]string{"tkey4": "tval4"}, 8), + makePDB("pdb1", "ns1", "uid1", map[string]string{"tkey1": "tval1"}, 1), + makePDB("pdb2", "ns3", "uid2", map[string]string{"tkey3": "tval3", "tkey1": "tval1", "tkey2": "tval2"}, 10), } tests := []struct { pdbsToAdd []*v1beta1.PodDisruptionBudget @@ -1140,7 +1248,7 @@ func TestPDBOperations(t *testing.T) { found := false // find it among the cached ones for _, cpdb := range cachedPDBs { - if pdb.Name == cpdb.Name { + if pdb.UID == cpdb.UID { found = true if !reflect.DeepEqual(pdb, cpdb) { t.Errorf("%v is not equal to %v", pdb, cpdb) @@ -1149,9 +1257,32 @@ func TestPDBOperations(t *testing.T) { } } if !found { - t.Errorf("PDB with name '%v' was not found in the cache.", pdb.Name) + t.Errorf("PDB with uid '%v' was not found in the cache.", pdb.UID) } } } } + +func TestIsUpToDate(t *testing.T) { + cache := New(time.Duration(0), wait.NeverStop) + if err := cache.AddNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "n1"}}); err != nil { + t.Errorf("Could not add node: %v", err) + } + s := cache.Snapshot() + node := s.Nodes["n1"] + if !cache.IsUpToDate(node) { + t.Errorf("Node incorrectly marked as stale") + } + pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p1", UID: "p1"}, Spec: v1.PodSpec{NodeName: "n1"}} + if err := cache.AddPod(pod); err != nil { + t.Errorf("Could not add pod: %v", err) + } + if cache.IsUpToDate(node) { + t.Errorf("Node incorrectly marked as up to date") + } + badNode := &NodeInfo{node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "n2"}}} + if cache.IsUpToDate(badNode) { + t.Errorf("Nonexistant node incorrectly marked as up to date") + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/cache/interface.go b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/interface.go new file mode 100644 index 000000000..336688470 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/interface.go @@ -0,0 +1,135 @@ +/* +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 cache + +import ( + "k8s.io/api/core/v1" + policy "k8s.io/api/policy/v1beta1" + "k8s.io/apimachinery/pkg/labels" +) + +// PodFilter is a function to filter a pod. If pod passed return true else return false. +type PodFilter func(*v1.Pod) bool + +// Cache collects pods' information and provides node-level aggregated information. +// It's intended for generic scheduler to do efficient lookup. +// Cache's operations are pod centric. It does incremental updates based on pod events. +// Pod events are sent via network. We don't have guaranteed delivery of all events: +// We use Reflector to list and watch from remote. +// Reflector might be slow and do a relist, which would lead to missing events. +// +// State Machine of a pod's events in scheduler's cache: +// +// +// +-------------------------------------------+ +----+ +// | Add | | | +// | | | | Update +// + Assume Add v v | +//Initial +--------> Assumed +------------+---> Added <--+ +// ^ + + | + +// | | | | | +// | | | Add | | Remove +// | | | | | +// | | | + | +// +----------------+ +-----------> Expired +----> Deleted +// Forget Expire +// +// +// Note that an assumed pod can expire, because if we haven't received Add event notifying us +// for a while, there might be some problems and we shouldn't keep the pod in cache anymore. +// +// Note that "Initial", "Expired", and "Deleted" pods do not actually exist in cache. +// Based on existing use cases, we are making the following assumptions: +// - No pod would be assumed twice +// - A pod could be added without going through scheduler. In this case, we will see Add but not Assume event. +// - If a pod wasn't added, it wouldn't be removed or updated. +// - Both "Expired" and "Deleted" are valid end states. In case of some problems, e.g. network issue, +// a pod might have changed its state (e.g. added and deleted) without delivering notification to the cache. +type Cache interface { + // AssumePod assumes a pod scheduled and aggregates the pod's information into its node. + // The implementation also decides the policy to expire pod before being confirmed (receiving Add event). + // After expiration, its information would be subtracted. + AssumePod(pod *v1.Pod) error + + // FinishBinding signals that cache for assumed pod can be expired + FinishBinding(pod *v1.Pod) error + + // ForgetPod removes an assumed pod from cache. + ForgetPod(pod *v1.Pod) error + + // AddPod either confirms a pod if it's assumed, or adds it back if it's expired. + // If added back, the pod's information would be added again. + AddPod(pod *v1.Pod) error + + // UpdatePod removes oldPod's information and adds newPod's information. + UpdatePod(oldPod, newPod *v1.Pod) error + + // RemovePod removes a pod. The pod's information would be subtracted from assigned node. + RemovePod(pod *v1.Pod) error + + // GetPod returns the pod from the cache with the same namespace and the + // same name of the specified pod. + GetPod(pod *v1.Pod) (*v1.Pod, error) + + // IsAssumedPod returns true if the pod is assumed and not expired. + IsAssumedPod(pod *v1.Pod) (bool, error) + + // AddNode adds overall information about node. + AddNode(node *v1.Node) error + + // UpdateNode updates overall information about node. + UpdateNode(oldNode, newNode *v1.Node) error + + // RemoveNode removes overall information about node. + RemoveNode(node *v1.Node) error + + // AddPDB adds a PodDisruptionBudget object to the cache. + AddPDB(pdb *policy.PodDisruptionBudget) error + + // UpdatePDB updates a PodDisruptionBudget object in the cache. + UpdatePDB(oldPDB, newPDB *policy.PodDisruptionBudget) error + + // RemovePDB removes a PodDisruptionBudget object from the cache. + RemovePDB(pdb *policy.PodDisruptionBudget) error + + // List lists all cached PDBs matching the selector. + ListPDBs(selector labels.Selector) ([]*policy.PodDisruptionBudget, error) + + // UpdateNodeNameToInfoMap updates the passed infoMap to the current contents of Cache. + // The node info contains aggregated information of pods scheduled (including assumed to be) + // on this node. + UpdateNodeNameToInfoMap(infoMap map[string]*NodeInfo) error + + // List lists all cached pods (including assumed ones). + List(labels.Selector) ([]*v1.Pod, error) + + // FilteredList returns all cached pods that pass the filter. + FilteredList(filter PodFilter, selector labels.Selector) ([]*v1.Pod, error) + + // Snapshot takes a snapshot on current cache + Snapshot() *Snapshot + + // IsUpToDate returns true if the given NodeInfo matches the current data in the cache. + IsUpToDate(n *NodeInfo) bool +} + +// Snapshot is a snapshot of cache state +type Snapshot struct { + AssumedPods map[string]bool + Nodes map[string]*NodeInfo + Pdbs map[string]*policy.PodDisruptionBudget +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/cache/node_info.go b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/node_info.go new file mode 100644 index 000000000..7eed8e69c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/node_info.go @@ -0,0 +1,661 @@ +/* +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 cache + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + + "github.com/golang/glog" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" + priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" + "k8s.io/kubernetes/pkg/scheduler/util" +) + +var ( + emptyResource = Resource{} + generation int64 +) + +// NodeInfo is node level aggregated information. +type NodeInfo struct { + // Overall node information. + node *v1.Node + + pods []*v1.Pod + podsWithAffinity []*v1.Pod + usedPorts util.HostPortInfo + + // Total requested resource of all pods on this node. + // It includes assumed pods which scheduler sends binding to apiserver but + // didn't get it as scheduled yet. + requestedResource *Resource + nonzeroRequest *Resource + // We store allocatedResources (which is Node.Status.Allocatable.*) explicitly + // as int64, to avoid conversions and accessing map. + allocatableResource *Resource + + // Cached taints of the node for faster lookup. + taints []v1.Taint + taintsErr error + + // This is a map from image name to image size, also for checking image existence on the node + // Cache it here to avoid rebuilding the map during scheduling, e.g., in image_locality.go + imageSizes map[string]int64 + + // TransientInfo holds the information pertaining to a scheduling cycle. This will be destructed at the end of + // scheduling cycle. + // TODO: @ravig. Remove this once we have a clear approach for message passing across predicates and priorities. + TransientInfo *transientSchedulerInfo + + // Cached conditions of node for faster lookup. + memoryPressureCondition v1.ConditionStatus + diskPressureCondition v1.ConditionStatus + pidPressureCondition v1.ConditionStatus + + // Whenever NodeInfo changes, generation is bumped. + // This is used to avoid cloning it if the object didn't change. + generation int64 +} + +//initializeNodeTransientInfo initializes transient information pertaining to node. +func initializeNodeTransientInfo() nodeTransientInfo { + return nodeTransientInfo{AllocatableVolumesCount: 0, RequestedVolumes: 0} +} + +// nextGeneration: Let's make sure history never forgets the name... +// Increments the generation number monotonically ensuring that generation numbers never collide. +// Collision of the generation numbers would be particularly problematic if a node was deleted and +// added back with the same name. See issue#63262. +func nextGeneration() int64 { + return atomic.AddInt64(&generation, 1) +} + +// nodeTransientInfo contains transient node information while scheduling. +type nodeTransientInfo struct { + // AllocatableVolumesCount contains number of volumes that could be attached to node. + AllocatableVolumesCount int + // Requested number of volumes on a particular node. + RequestedVolumes int +} + +// transientSchedulerInfo is a transient structure which is destructed at the end of each scheduling cycle. +// It consists of items that are valid for a scheduling cycle and is used for message passing across predicates and +// priorities. Some examples which could be used as fields are number of volumes being used on node, current utilization +// on node etc. +// IMPORTANT NOTE: Make sure that each field in this structure is documented along with usage. Expand this structure +// only when absolutely needed as this data structure will be created and destroyed during every scheduling cycle. +type transientSchedulerInfo struct { + TransientLock sync.Mutex + // NodeTransInfo holds the information related to nodeTransientInformation. NodeName is the key here. + TransNodeInfo nodeTransientInfo +} + +// newTransientSchedulerInfo returns a new scheduler transient structure with initialized values. +func newTransientSchedulerInfo() *transientSchedulerInfo { + tsi := &transientSchedulerInfo{ + TransNodeInfo: initializeNodeTransientInfo(), + } + return tsi +} + +// resetTransientSchedulerInfo resets the transientSchedulerInfo. +func (transientSchedInfo *transientSchedulerInfo) resetTransientSchedulerInfo() { + transientSchedInfo.TransientLock.Lock() + defer transientSchedInfo.TransientLock.Unlock() + // Reset TransientNodeInfo. + transientSchedInfo.TransNodeInfo.AllocatableVolumesCount = 0 + transientSchedInfo.TransNodeInfo.RequestedVolumes = 0 +} + +// Resource is a collection of compute resource. +type Resource struct { + MilliCPU int64 + Memory int64 + EphemeralStorage int64 + // We store allowedPodNumber (which is Node.Status.Allocatable.Pods().Value()) + // explicitly as int, to avoid conversions and improve performance. + AllowedPodNumber int + // ScalarResources + ScalarResources map[v1.ResourceName]int64 +} + +// NewResource creates a Resource from ResourceList +func NewResource(rl v1.ResourceList) *Resource { + r := &Resource{} + r.Add(rl) + return r +} + +// Add adds ResourceList into Resource. +func (r *Resource) Add(rl v1.ResourceList) { + if r == nil { + return + } + + for rName, rQuant := range rl { + switch rName { + case v1.ResourceCPU: + r.MilliCPU += rQuant.MilliValue() + case v1.ResourceMemory: + r.Memory += rQuant.Value() + case v1.ResourcePods: + r.AllowedPodNumber += int(rQuant.Value()) + case v1.ResourceEphemeralStorage: + r.EphemeralStorage += rQuant.Value() + default: + if v1helper.IsScalarResourceName(rName) { + r.AddScalar(rName, rQuant.Value()) + } + } + } +} + +// ResourceList returns a resource list of this resource. +func (r *Resource) ResourceList() v1.ResourceList { + result := v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(r.MilliCPU, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(r.Memory, resource.BinarySI), + v1.ResourcePods: *resource.NewQuantity(int64(r.AllowedPodNumber), resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(r.EphemeralStorage, resource.BinarySI), + } + for rName, rQuant := range r.ScalarResources { + if v1helper.IsHugePageResourceName(rName) { + result[rName] = *resource.NewQuantity(rQuant, resource.BinarySI) + } else { + result[rName] = *resource.NewQuantity(rQuant, resource.DecimalSI) + } + } + return result +} + +// Clone returns a copy of this resource. +func (r *Resource) Clone() *Resource { + res := &Resource{ + MilliCPU: r.MilliCPU, + Memory: r.Memory, + AllowedPodNumber: r.AllowedPodNumber, + EphemeralStorage: r.EphemeralStorage, + } + if r.ScalarResources != nil { + res.ScalarResources = make(map[v1.ResourceName]int64) + for k, v := range r.ScalarResources { + res.ScalarResources[k] = v + } + } + return res +} + +// AddScalar adds a resource by a scalar value of this resource. +func (r *Resource) AddScalar(name v1.ResourceName, quantity int64) { + r.SetScalar(name, r.ScalarResources[name]+quantity) +} + +// SetScalar sets a resource by a scalar value of this resource. +func (r *Resource) SetScalar(name v1.ResourceName, quantity int64) { + // Lazily allocate scalar resource map. + if r.ScalarResources == nil { + r.ScalarResources = map[v1.ResourceName]int64{} + } + r.ScalarResources[name] = quantity +} + +// SetMaxResource compares with ResourceList and takes max value for each Resource. +func (r *Resource) SetMaxResource(rl v1.ResourceList) { + if r == nil { + return + } + + for rName, rQuantity := range rl { + switch rName { + case v1.ResourceMemory: + if mem := rQuantity.Value(); mem > r.Memory { + r.Memory = mem + } + case v1.ResourceCPU: + if cpu := rQuantity.MilliValue(); cpu > r.MilliCPU { + r.MilliCPU = cpu + } + case v1.ResourceEphemeralStorage: + if ephemeralStorage := rQuantity.Value(); ephemeralStorage > r.EphemeralStorage { + r.EphemeralStorage = ephemeralStorage + } + default: + if v1helper.IsScalarResourceName(rName) { + value := rQuantity.Value() + if value > r.ScalarResources[rName] { + r.SetScalar(rName, value) + } + } + } + } +} + +// NewNodeInfo returns a ready to use empty NodeInfo object. +// If any pods are given in arguments, their information will be aggregated in +// the returned object. +func NewNodeInfo(pods ...*v1.Pod) *NodeInfo { + ni := &NodeInfo{ + requestedResource: &Resource{}, + nonzeroRequest: &Resource{}, + allocatableResource: &Resource{}, + TransientInfo: newTransientSchedulerInfo(), + generation: nextGeneration(), + usedPorts: make(util.HostPortInfo), + imageSizes: make(map[string]int64), + } + for _, pod := range pods { + ni.AddPod(pod) + } + return ni +} + +// Node returns overall information about this node. +func (n *NodeInfo) Node() *v1.Node { + if n == nil { + return nil + } + return n.node +} + +// Pods return all pods scheduled (including assumed to be) on this node. +func (n *NodeInfo) Pods() []*v1.Pod { + if n == nil { + return nil + } + return n.pods +} + +// UsedPorts returns used ports on this node. +func (n *NodeInfo) UsedPorts() util.HostPortInfo { + if n == nil { + return nil + } + return n.usedPorts +} + +// ImageSizes returns the image size information on this node. +func (n *NodeInfo) ImageSizes() map[string]int64 { + if n == nil { + return nil + } + return n.imageSizes +} + +// PodsWithAffinity return all pods with (anti)affinity constraints on this node. +func (n *NodeInfo) PodsWithAffinity() []*v1.Pod { + if n == nil { + return nil + } + return n.podsWithAffinity +} + +// AllowedPodNumber returns the number of the allowed pods on this node. +func (n *NodeInfo) AllowedPodNumber() int { + if n == nil || n.allocatableResource == nil { + return 0 + } + return n.allocatableResource.AllowedPodNumber +} + +// Taints returns the taints list on this node. +func (n *NodeInfo) Taints() ([]v1.Taint, error) { + if n == nil { + return nil, nil + } + return n.taints, n.taintsErr +} + +// MemoryPressureCondition returns the memory pressure condition status on this node. +func (n *NodeInfo) MemoryPressureCondition() v1.ConditionStatus { + if n == nil { + return v1.ConditionUnknown + } + return n.memoryPressureCondition +} + +// DiskPressureCondition returns the disk pressure condition status on this node. +func (n *NodeInfo) DiskPressureCondition() v1.ConditionStatus { + if n == nil { + return v1.ConditionUnknown + } + return n.diskPressureCondition +} + +// PIDPressureCondition returns the pid pressure condition status on this node. +func (n *NodeInfo) PIDPressureCondition() v1.ConditionStatus { + if n == nil { + return v1.ConditionUnknown + } + return n.pidPressureCondition +} + +// RequestedResource returns aggregated resource request of pods on this node. +func (n *NodeInfo) RequestedResource() Resource { + if n == nil { + return emptyResource + } + return *n.requestedResource +} + +// NonZeroRequest returns aggregated nonzero resource request of pods on this node. +func (n *NodeInfo) NonZeroRequest() Resource { + if n == nil { + return emptyResource + } + return *n.nonzeroRequest +} + +// AllocatableResource returns allocatable resources on a given node. +func (n *NodeInfo) AllocatableResource() Resource { + if n == nil { + return emptyResource + } + return *n.allocatableResource +} + +// SetAllocatableResource sets the allocatableResource information of given node. +func (n *NodeInfo) SetAllocatableResource(allocatableResource *Resource) { + n.allocatableResource = allocatableResource + n.generation = nextGeneration() +} + +// Clone returns a copy of this node. +func (n *NodeInfo) Clone() *NodeInfo { + clone := &NodeInfo{ + node: n.node, + requestedResource: n.requestedResource.Clone(), + nonzeroRequest: n.nonzeroRequest.Clone(), + allocatableResource: n.allocatableResource.Clone(), + taintsErr: n.taintsErr, + TransientInfo: n.TransientInfo, + memoryPressureCondition: n.memoryPressureCondition, + diskPressureCondition: n.diskPressureCondition, + pidPressureCondition: n.pidPressureCondition, + usedPorts: make(util.HostPortInfo), + imageSizes: n.imageSizes, + generation: n.generation, + } + if len(n.pods) > 0 { + clone.pods = append([]*v1.Pod(nil), n.pods...) + } + if len(n.usedPorts) > 0 { + // util.HostPortInfo is a map-in-map struct + // make sure it's deep copied + for ip, portMap := range n.usedPorts { + clone.usedPorts[ip] = make(map[util.ProtocolPort]struct{}) + for protocolPort, v := range portMap { + clone.usedPorts[ip][protocolPort] = v + } + } + } + if len(n.podsWithAffinity) > 0 { + clone.podsWithAffinity = append([]*v1.Pod(nil), n.podsWithAffinity...) + } + if len(n.taints) > 0 { + clone.taints = append([]v1.Taint(nil), n.taints...) + } + return clone +} + +// VolumeLimits returns volume limits associated with the node +func (n *NodeInfo) VolumeLimits() map[v1.ResourceName]int64 { + volumeLimits := map[v1.ResourceName]int64{} + for k, v := range n.AllocatableResource().ScalarResources { + if v1helper.IsAttachableVolumeResourceName(k) { + volumeLimits[k] = v + } + } + return volumeLimits +} + +// String returns representation of human readable format of this NodeInfo. +func (n *NodeInfo) String() string { + podKeys := make([]string, len(n.pods)) + for i, pod := range n.pods { + podKeys[i] = pod.Name + } + return fmt.Sprintf("&NodeInfo{Pods:%v, RequestedResource:%#v, NonZeroRequest: %#v, UsedPort: %#v, AllocatableResource:%#v}", + podKeys, n.requestedResource, n.nonzeroRequest, n.usedPorts, n.allocatableResource) +} + +func hasPodAffinityConstraints(pod *v1.Pod) bool { + affinity := pod.Spec.Affinity + return affinity != nil && (affinity.PodAffinity != nil || affinity.PodAntiAffinity != nil) +} + +// AddPod adds pod information to this NodeInfo. +func (n *NodeInfo) AddPod(pod *v1.Pod) { + res, non0CPU, non0Mem := calculateResource(pod) + n.requestedResource.MilliCPU += res.MilliCPU + n.requestedResource.Memory += res.Memory + n.requestedResource.EphemeralStorage += res.EphemeralStorage + if n.requestedResource.ScalarResources == nil && len(res.ScalarResources) > 0 { + n.requestedResource.ScalarResources = map[v1.ResourceName]int64{} + } + for rName, rQuant := range res.ScalarResources { + n.requestedResource.ScalarResources[rName] += rQuant + } + n.nonzeroRequest.MilliCPU += non0CPU + n.nonzeroRequest.Memory += non0Mem + n.pods = append(n.pods, pod) + if hasPodAffinityConstraints(pod) { + n.podsWithAffinity = append(n.podsWithAffinity, pod) + } + + // Consume ports when pods added. + n.updateUsedPorts(pod, true) + + n.generation = nextGeneration() +} + +// RemovePod subtracts pod information from this NodeInfo. +func (n *NodeInfo) RemovePod(pod *v1.Pod) error { + k1, err := getPodKey(pod) + if err != nil { + return err + } + + for i := range n.podsWithAffinity { + k2, err := getPodKey(n.podsWithAffinity[i]) + if err != nil { + glog.Errorf("Cannot get pod key, err: %v", err) + continue + } + if k1 == k2 { + // delete the element + n.podsWithAffinity[i] = n.podsWithAffinity[len(n.podsWithAffinity)-1] + n.podsWithAffinity = n.podsWithAffinity[:len(n.podsWithAffinity)-1] + break + } + } + for i := range n.pods { + k2, err := getPodKey(n.pods[i]) + if err != nil { + glog.Errorf("Cannot get pod key, err: %v", err) + continue + } + if k1 == k2 { + // delete the element + n.pods[i] = n.pods[len(n.pods)-1] + n.pods = n.pods[:len(n.pods)-1] + // reduce the resource data + res, non0CPU, non0Mem := calculateResource(pod) + + n.requestedResource.MilliCPU -= res.MilliCPU + n.requestedResource.Memory -= res.Memory + n.requestedResource.EphemeralStorage -= res.EphemeralStorage + if len(res.ScalarResources) > 0 && n.requestedResource.ScalarResources == nil { + n.requestedResource.ScalarResources = map[v1.ResourceName]int64{} + } + for rName, rQuant := range res.ScalarResources { + n.requestedResource.ScalarResources[rName] -= rQuant + } + n.nonzeroRequest.MilliCPU -= non0CPU + n.nonzeroRequest.Memory -= non0Mem + + // Release ports when remove Pods. + n.updateUsedPorts(pod, false) + + n.generation = nextGeneration() + + return nil + } + } + return fmt.Errorf("no corresponding pod %s in pods of node %s", pod.Name, n.node.Name) +} + +func calculateResource(pod *v1.Pod) (res Resource, non0CPU int64, non0Mem int64) { + resPtr := &res + for _, c := range pod.Spec.Containers { + resPtr.Add(c.Resources.Requests) + + non0CPUReq, non0MemReq := priorityutil.GetNonzeroRequests(&c.Resources.Requests) + non0CPU += non0CPUReq + non0Mem += non0MemReq + // No non-zero resources for GPUs or opaque resources. + } + + return +} + +func (n *NodeInfo) updateUsedPorts(pod *v1.Pod, add bool) { + for j := range pod.Spec.Containers { + container := &pod.Spec.Containers[j] + for k := range container.Ports { + podPort := &container.Ports[k] + if add { + n.usedPorts.Add(podPort.HostIP, string(podPort.Protocol), podPort.HostPort) + } else { + n.usedPorts.Remove(podPort.HostIP, string(podPort.Protocol), podPort.HostPort) + } + } + } +} + +func (n *NodeInfo) updateImageSizes() { + node := n.Node() + imageSizes := make(map[string]int64) + for _, image := range node.Status.Images { + for _, name := range image.Names { + imageSizes[name] = image.SizeBytes + } + } + n.imageSizes = imageSizes +} + +// SetNode sets the overall node information. +func (n *NodeInfo) SetNode(node *v1.Node) error { + n.node = node + + n.allocatableResource = NewResource(node.Status.Allocatable) + + n.taints = node.Spec.Taints + for i := range node.Status.Conditions { + cond := &node.Status.Conditions[i] + switch cond.Type { + case v1.NodeMemoryPressure: + n.memoryPressureCondition = cond.Status + case v1.NodeDiskPressure: + n.diskPressureCondition = cond.Status + case v1.NodePIDPressure: + n.pidPressureCondition = cond.Status + default: + // We ignore other conditions. + } + } + n.TransientInfo = newTransientSchedulerInfo() + n.updateImageSizes() + n.generation = nextGeneration() + return nil +} + +// RemoveNode removes the overall information about the node. +func (n *NodeInfo) RemoveNode(node *v1.Node) error { + // We don't remove NodeInfo for because there can still be some pods on this node - + // this is because notifications about pods are delivered in a different watch, + // and thus can potentially be observed later, even though they happened before + // node removal. This is handled correctly in cache.go file. + n.node = nil + n.allocatableResource = &Resource{} + n.taints, n.taintsErr = nil, nil + n.memoryPressureCondition = v1.ConditionUnknown + n.diskPressureCondition = v1.ConditionUnknown + n.pidPressureCondition = v1.ConditionUnknown + n.generation = nextGeneration() + return nil +} + +// FilterOutPods receives a list of pods and filters out those whose node names +// are equal to the node of this NodeInfo, but are not found in the pods of this NodeInfo. +// +// Preemption logic simulates removal of pods on a node by removing them from the +// corresponding NodeInfo. In order for the simulation to work, we call this method +// on the pods returned from SchedulerCache, so that predicate functions see +// only the pods that are not removed from the NodeInfo. +func (n *NodeInfo) FilterOutPods(pods []*v1.Pod) []*v1.Pod { + node := n.Node() + if node == nil { + return pods + } + filtered := make([]*v1.Pod, 0, len(pods)) + for _, p := range pods { + if p.Spec.NodeName != node.Name { + filtered = append(filtered, p) + continue + } + // If pod is on the given node, add it to 'filtered' only if it is present in nodeInfo. + podKey, _ := getPodKey(p) + for _, np := range n.Pods() { + npodkey, _ := getPodKey(np) + if npodkey == podKey { + filtered = append(filtered, p) + break + } + } + } + return filtered +} + +// getPodKey returns the string key of a pod. +func getPodKey(pod *v1.Pod) (string, error) { + uid := string(pod.UID) + if len(uid) == 0 { + return "", errors.New("Cannot get cache key for pod with empty UID") + } + return uid, nil +} + +// Filter implements PodFilter interface. It returns false only if the pod node name +// matches NodeInfo.node and the pod is not found in the pods list. Otherwise, +// returns true. +func (n *NodeInfo) Filter(pod *v1.Pod) bool { + if pod.Spec.NodeName != n.node.Name { + return true + } + for _, p := range n.pods { + if p.Name == pod.Name && p.Namespace == pod.Namespace { + return true + } + } + return false +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/node_info_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/node_info_test.go similarity index 83% rename from vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/node_info_test.go rename to vendor/k8s.io/kubernetes/pkg/scheduler/cache/node_info_test.go index 583b2d08d..ebb78e748 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/node_info_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/node_info_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package schedulercache +package cache import ( "fmt" @@ -26,6 +26,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/scheduler/util" + "k8s.io/kubernetes/pkg/util/parsers" ) func TestNewResource(t *testing.T) { @@ -41,7 +42,6 @@ func TestNewResource(t *testing.T) { resourceList: map[v1.ResourceName]resource.Quantity{ v1.ResourceCPU: *resource.NewScaledQuantity(4, -3), v1.ResourceMemory: *resource.NewQuantity(2000, resource.BinarySI), - v1.ResourceNvidiaGPU: *resource.NewQuantity(1000, resource.DecimalSI), v1.ResourcePods: *resource.NewQuantity(80, resource.BinarySI), v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), "scalar.test/" + "scalar1": *resource.NewQuantity(1, resource.DecimalSI), @@ -50,7 +50,6 @@ func TestNewResource(t *testing.T) { expected: &Resource{ MilliCPU: 4, Memory: 2000, - NvidiaGPU: 1000, EphemeralStorage: 5000, AllowedPodNumber: 80, ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2}, @@ -76,7 +75,6 @@ func TestResourceList(t *testing.T) { expected: map[v1.ResourceName]resource.Quantity{ v1.ResourceCPU: *resource.NewScaledQuantity(0, -3), v1.ResourceMemory: *resource.NewQuantity(0, resource.BinarySI), - v1.ResourceNvidiaGPU: *resource.NewQuantity(0, resource.DecimalSI), v1.ResourcePods: *resource.NewQuantity(0, resource.BinarySI), v1.ResourceEphemeralStorage: *resource.NewQuantity(0, resource.BinarySI), }, @@ -85,18 +83,21 @@ func TestResourceList(t *testing.T) { resource: &Resource{ MilliCPU: 4, Memory: 2000, - NvidiaGPU: 1000, EphemeralStorage: 5000, AllowedPodNumber: 80, - ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2}, + ScalarResources: map[v1.ResourceName]int64{ + "scalar.test/scalar1": 1, + "hugepages-test": 2, + "attachable-volumes-aws-ebs": 39, + }, }, expected: map[v1.ResourceName]resource.Quantity{ v1.ResourceCPU: *resource.NewScaledQuantity(4, -3), v1.ResourceMemory: *resource.NewQuantity(2000, resource.BinarySI), - v1.ResourceNvidiaGPU: *resource.NewQuantity(1000, resource.DecimalSI), v1.ResourcePods: *resource.NewQuantity(80, resource.BinarySI), v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), "scalar.test/" + "scalar1": *resource.NewQuantity(1, resource.DecimalSI), + "attachable-volumes-aws-ebs": *resource.NewQuantity(39, resource.DecimalSI), v1.ResourceHugePagesPrefix + "test": *resource.NewQuantity(2, resource.BinarySI), }, }, @@ -123,7 +124,6 @@ func TestResourceClone(t *testing.T) { resource: &Resource{ MilliCPU: 4, Memory: 2000, - NvidiaGPU: 1000, EphemeralStorage: 5000, AllowedPodNumber: 80, ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2}, @@ -131,7 +131,6 @@ func TestResourceClone(t *testing.T) { expected: &Resource{ MilliCPU: 4, Memory: 2000, - NvidiaGPU: 1000, EphemeralStorage: 5000, AllowedPodNumber: 80, ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2}, @@ -168,7 +167,6 @@ func TestResourceAddScalar(t *testing.T) { resource: &Resource{ MilliCPU: 4, Memory: 2000, - NvidiaGPU: 1000, EphemeralStorage: 5000, AllowedPodNumber: 80, ScalarResources: map[v1.ResourceName]int64{"hugepages-test": 2}, @@ -178,7 +176,6 @@ func TestResourceAddScalar(t *testing.T) { expected: &Resource{ MilliCPU: 4, Memory: 2000, - NvidiaGPU: 1000, EphemeralStorage: 5000, AllowedPodNumber: 80, ScalarResources: map[v1.ResourceName]int64{"hugepages-test": 2, "scalar2": 200}, @@ -194,6 +191,96 @@ func TestResourceAddScalar(t *testing.T) { } } +func TestSetMaxResource(t *testing.T) { + tests := []struct { + resource *Resource + resourceList v1.ResourceList + expected *Resource + }{ + { + resource: &Resource{}, + resourceList: map[v1.ResourceName]resource.Quantity{ + v1.ResourceCPU: *resource.NewScaledQuantity(4, -3), + v1.ResourceMemory: *resource.NewQuantity(2000, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), + }, + expected: &Resource{ + MilliCPU: 4, + Memory: 2000, + EphemeralStorage: 5000, + }, + }, + { + resource: &Resource{ + MilliCPU: 4, + Memory: 4000, + EphemeralStorage: 5000, + ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 1, "hugepages-test": 2}, + }, + resourceList: map[v1.ResourceName]resource.Quantity{ + v1.ResourceCPU: *resource.NewScaledQuantity(4, -3), + v1.ResourceMemory: *resource.NewQuantity(2000, resource.BinarySI), + v1.ResourceEphemeralStorage: *resource.NewQuantity(7000, resource.BinarySI), + "scalar.test/scalar1": *resource.NewQuantity(4, resource.DecimalSI), + v1.ResourceHugePagesPrefix + "test": *resource.NewQuantity(5, resource.BinarySI), + }, + expected: &Resource{ + MilliCPU: 4, + Memory: 4000, + EphemeralStorage: 7000, + ScalarResources: map[v1.ResourceName]int64{"scalar.test/scalar1": 4, "hugepages-test": 5}, + }, + }, + } + + for _, test := range tests { + test.resource.SetMaxResource(test.resourceList) + if !reflect.DeepEqual(test.expected, test.resource) { + t.Errorf("expected: %#v, got: %#v", test.expected, test.resource) + } + } +} + +func TestImageSizes(t *testing.T) { + ni := fakeNodeInfo() + ni.node = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-node", + }, + Status: v1.NodeStatus{ + Images: []v1.ContainerImage{ + { + Names: []string{ + "gcr.io/10:" + parsers.DefaultImageTag, + "gcr.io/10:v1", + }, + SizeBytes: int64(10 * 1024 * 1024), + }, + { + Names: []string{ + "gcr.io/50:" + parsers.DefaultImageTag, + "gcr.io/50:v1", + }, + SizeBytes: int64(50 * 1024 * 1024), + }, + }, + }, + } + + ni.updateImageSizes() + expected := map[string]int64{ + "gcr.io/10:" + parsers.DefaultImageTag: 10 * 1024 * 1024, + "gcr.io/10:v1": 10 * 1024 * 1024, + "gcr.io/50:" + parsers.DefaultImageTag: 50 * 1024 * 1024, + "gcr.io/50:v1": 50 * 1024 * 1024, + } + + imageSizes := ni.ImageSizes() + if !reflect.DeepEqual(expected, imageSizes) { + t.Errorf("expected: %#v, got: %#v", expected, imageSizes) + } +} + func TestNewNodeInfo(t *testing.T) { nodeName := "test-node" pods := []*v1.Pod{ @@ -205,7 +292,6 @@ func TestNewNodeInfo(t *testing.T) { requestedResource: &Resource{ MilliCPU: 300, Memory: 1524, - NvidiaGPU: 0, EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources: map[v1.ResourceName]int64(nil), @@ -213,11 +299,11 @@ func TestNewNodeInfo(t *testing.T) { nonzeroRequest: &Resource{ MilliCPU: 300, Memory: 1524, - NvidiaGPU: 0, EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources: map[v1.ResourceName]int64(nil), }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, generation: 2, usedPorts: util.HostPortInfo{ @@ -226,6 +312,7 @@ func TestNewNodeInfo(t *testing.T) { {Protocol: "TCP", Port: 8080}: {}, }, }, + imageSizes: map[string]int64{}, pods: []*v1.Pod{ { ObjectMeta: metav1.ObjectMeta{ @@ -284,7 +371,12 @@ func TestNewNodeInfo(t *testing.T) { }, } + gen := generation ni := NewNodeInfo(pods...) + if ni.generation <= gen { + t.Errorf("generation is not incremented. previous: %v, current: %v", gen, ni.generation) + } + expected.generation = ni.generation if !reflect.DeepEqual(expected, ni) { t.Errorf("expected: %#v, got: %#v", expected, ni) } @@ -300,6 +392,7 @@ func TestNodeInfoClone(t *testing.T) { nodeInfo: &NodeInfo{ requestedResource: &Resource{}, nonzeroRequest: &Resource{}, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, generation: 2, usedPorts: util.HostPortInfo{ @@ -308,6 +401,9 @@ func TestNodeInfoClone(t *testing.T) { {Protocol: "TCP", Port: 8080}: {}, }, }, + imageSizes: map[string]int64{ + "gcr.io/10": 10 * 1024 * 1024, + }, pods: []*v1.Pod{ { ObjectMeta: metav1.ObjectMeta{ @@ -368,6 +464,7 @@ func TestNodeInfoClone(t *testing.T) { expected: &NodeInfo{ requestedResource: &Resource{}, nonzeroRequest: &Resource{}, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, generation: 2, usedPorts: util.HostPortInfo{ @@ -376,6 +473,9 @@ func TestNodeInfoClone(t *testing.T) { {Protocol: "TCP", Port: 8080}: {}, }, }, + imageSizes: map[string]int64{ + "gcr.io/10": 10 * 1024 * 1024, + }, pods: []*v1.Pod{ { ObjectMeta: metav1.ObjectMeta{ @@ -440,6 +540,7 @@ func TestNodeInfoClone(t *testing.T) { ni := test.nodeInfo.Clone() // Modify the field to check if the result is a clone of the origin one. test.nodeInfo.generation += 10 + test.nodeInfo.usedPorts.Remove("127.0.0.1", "TCP", 80) if !reflect.DeepEqual(test.expected, ni) { t.Errorf("expected: %#v, got: %#v", test.expected, ni) } @@ -513,7 +614,6 @@ func TestNodeInfoAddPod(t *testing.T) { requestedResource: &Resource{ MilliCPU: 300, Memory: 1524, - NvidiaGPU: 0, EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources: map[v1.ResourceName]int64(nil), @@ -521,11 +621,11 @@ func TestNodeInfoAddPod(t *testing.T) { nonzeroRequest: &Resource{ MilliCPU: 300, Memory: 1524, - NvidiaGPU: 0, EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources: map[v1.ResourceName]int64(nil), }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, generation: 2, usedPorts: util.HostPortInfo{ @@ -534,6 +634,7 @@ func TestNodeInfoAddPod(t *testing.T) { {Protocol: "TCP", Port: 8080}: {}, }, }, + imageSizes: map[string]int64{}, pods: []*v1.Pod{ { ObjectMeta: metav1.ObjectMeta{ @@ -593,10 +694,16 @@ func TestNodeInfoAddPod(t *testing.T) { } ni := fakeNodeInfo() + gen := ni.generation for _, pod := range pods { ni.AddPod(pod) + if ni.generation <= gen { + t.Errorf("generation is not incremented. Prev: %v, current: %v", gen, ni.generation) + } + gen = ni.generation } + expected.generation = ni.generation if !reflect.DeepEqual(expected, ni) { t.Errorf("expected: %#v, got: %#v", expected, ni) } @@ -626,7 +733,6 @@ func TestNodeInfoRemovePod(t *testing.T) { requestedResource: &Resource{ MilliCPU: 300, Memory: 1524, - NvidiaGPU: 0, EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources: map[v1.ResourceName]int64(nil), @@ -634,11 +740,11 @@ func TestNodeInfoRemovePod(t *testing.T) { nonzeroRequest: &Resource{ MilliCPU: 300, Memory: 1524, - NvidiaGPU: 0, EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources: map[v1.ResourceName]int64(nil), }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, generation: 2, usedPorts: util.HostPortInfo{ @@ -647,6 +753,7 @@ func TestNodeInfoRemovePod(t *testing.T) { {Protocol: "TCP", Port: 8080}: {}, }, }, + imageSizes: map[string]int64{}, pods: []*v1.Pod{ { ObjectMeta: metav1.ObjectMeta{ @@ -743,7 +850,6 @@ func TestNodeInfoRemovePod(t *testing.T) { requestedResource: &Resource{ MilliCPU: 200, Memory: 1024, - NvidiaGPU: 0, EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources: map[v1.ResourceName]int64(nil), @@ -751,11 +857,11 @@ func TestNodeInfoRemovePod(t *testing.T) { nonzeroRequest: &Resource{ MilliCPU: 200, Memory: 1024, - NvidiaGPU: 0, EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources: map[v1.ResourceName]int64(nil), }, + TransientInfo: newTransientSchedulerInfo(), allocatableResource: &Resource{}, generation: 3, usedPorts: util.HostPortInfo{ @@ -763,6 +869,7 @@ func TestNodeInfoRemovePod(t *testing.T) { {Protocol: "TCP", Port: 8080}: {}, }, }, + imageSizes: map[string]int64{}, pods: []*v1.Pod{ { ObjectMeta: metav1.ObjectMeta{ @@ -799,6 +906,7 @@ func TestNodeInfoRemovePod(t *testing.T) { for _, test := range tests { ni := fakeNodeInfo(pods...) + gen := ni.generation err := ni.RemovePod(test.pod) if err != nil { if test.errExpected { @@ -809,8 +917,13 @@ func TestNodeInfoRemovePod(t *testing.T) { } else { t.Errorf("expected no error, got: %v", err) } + } else { + if ni.generation <= gen { + t.Errorf("generation is not incremented. Prev: %v, current: %v", gen, ni.generation) + } } + test.expectedNodeInfo.generation = ni.generation if !reflect.DeepEqual(test.expectedNodeInfo, ni) { t.Errorf("expected: %#v, got: %#v", test.expectedNodeInfo, ni) } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/cache/util.go b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/util.go new file mode 100644 index 000000000..c3037dcc3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/cache/util.go @@ -0,0 +1,39 @@ +/* +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 cache + +import "k8s.io/api/core/v1" + +// CreateNodeNameToInfoMap obtains a list of pods and pivots that list into a map where the keys are node names +// and the values are the aggregated information for that node. +func CreateNodeNameToInfoMap(pods []*v1.Pod, nodes []*v1.Node) map[string]*NodeInfo { + nodeNameToInfo := make(map[string]*NodeInfo) + for _, pod := range pods { + nodeName := pod.Spec.NodeName + if _, ok := nodeNameToInfo[nodeName]; !ok { + nodeNameToInfo[nodeName] = NewNodeInfo() + } + nodeNameToInfo[nodeName].AddPod(pod) + } + for _, node := range nodes { + if _, ok := nodeNameToInfo[node.Name]; !ok { + nodeNameToInfo[node.Name] = NewNodeInfo() + } + nodeNameToInfo[node.Name].SetNode(node) + } + return nodeNameToInfo +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/core/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/core/BUILD index 6be7c9fa9..0e8cd4177 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/core/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/core/BUILD @@ -21,7 +21,7 @@ go_test( "//pkg/scheduler/algorithm/priorities:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/testing:go_default_library", "//pkg/scheduler/util:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", @@ -50,13 +50,12 @@ go_library( "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/metrics:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//pkg/util/hash:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/golang/groupcache/lru:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/core/equivalence_cache.go b/vendor/k8s.io/kubernetes/pkg/scheduler/core/equivalence_cache.go index 3eebe9dcb..fb67ad3bb 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/core/equivalence_cache.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/core/equivalence_cache.go @@ -17,35 +17,30 @@ limitations under the License. package core import ( + "fmt" "hash/fnv" "sync" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" hashutil "k8s.io/kubernetes/pkg/util/hash" "github.com/golang/glog" - "github.com/golang/groupcache/lru" ) -// We use predicate names as cache's key, its count is limited -const maxCacheEntries = 100 - // EquivalenceCache holds: // 1. a map of AlgorithmCache with node name as key // 2. function to get equivalence pod type EquivalenceCache struct { - sync.RWMutex - getEquivalencePod algorithm.GetEquivalencePodFunc - algorithmCache map[string]AlgorithmCache + mu sync.RWMutex + algorithmCache map[string]AlgorithmCache } -// The AlgorithmCache stores PredicateMap with predicate name as key -type AlgorithmCache struct { - // Only consider predicates for now - predicatesCache *lru.Cache -} +// The AlgorithmCache stores PredicateMap with predicate name as key, PredicateMap as value. +type AlgorithmCache map[string]PredicateMap // PredicateMap stores HostPrediacte with equivalence hash as key type PredicateMap map[uint64]HostPredicate @@ -56,82 +51,105 @@ type HostPredicate struct { FailReasons []algorithm.PredicateFailureReason } -func newAlgorithmCache() AlgorithmCache { - return AlgorithmCache{ - predicatesCache: lru.New(maxCacheEntries), +// NewEquivalenceCache returns EquivalenceCache to speed up predicates by caching +// result from previous scheduling. +func NewEquivalenceCache() *EquivalenceCache { + return &EquivalenceCache{ + algorithmCache: make(map[string]AlgorithmCache), } } -// NewEquivalenceCache creates a EquivalenceCache object. -func NewEquivalenceCache(getEquivalencePodFunc algorithm.GetEquivalencePodFunc) *EquivalenceCache { - return &EquivalenceCache{ - getEquivalencePod: getEquivalencePodFunc, - algorithmCache: make(map[string]AlgorithmCache), +// RunPredicate will return a cached predicate result. In case of a cache miss, the predicate will +// be run and its results cached for the next call. +// +// NOTE: RunPredicate will not update the equivalence cache if the given NodeInfo is stale. +func (ec *EquivalenceCache) RunPredicate( + pred algorithm.FitPredicate, + predicateKey string, + pod *v1.Pod, + meta algorithm.PredicateMetadata, + nodeInfo *schedulercache.NodeInfo, + equivClassInfo *equivalenceClassInfo, + cache schedulercache.Cache, +) (bool, []algorithm.PredicateFailureReason, error) { + if nodeInfo == nil || nodeInfo.Node() == nil { + // This may happen during tests. + return false, []algorithm.PredicateFailureReason{}, fmt.Errorf("nodeInfo is nil or node is invalid") + } + + fit, reasons, invalid := ec.lookupResult(pod.GetName(), nodeInfo.Node().GetName(), predicateKey, equivClassInfo.hash) + if !invalid { + return fit, reasons, nil + } + fit, reasons, err := pred(pod, meta, nodeInfo) + if err != nil { + return fit, reasons, err + } + if cache != nil { + ec.updateResult(pod.GetName(), predicateKey, fit, reasons, equivClassInfo.hash, cache, nodeInfo) } + return fit, reasons, nil } -// UpdateCachedPredicateItem updates pod predicate for equivalence class -func (ec *EquivalenceCache) UpdateCachedPredicateItem( - podName, nodeName, predicateKey string, +// updateResult updates the cached result of a predicate. +func (ec *EquivalenceCache) updateResult( + podName, predicateKey string, fit bool, reasons []algorithm.PredicateFailureReason, equivalenceHash uint64, - needLock bool, + cache schedulercache.Cache, + nodeInfo *schedulercache.NodeInfo, ) { - if needLock { - ec.Lock() - defer ec.Unlock() + ec.mu.Lock() + defer ec.mu.Unlock() + if nodeInfo == nil || nodeInfo.Node() == nil { + // This may happen during tests. + return + } + // Skip update if NodeInfo is stale. + if !cache.IsUpToDate(nodeInfo) { + return } + nodeName := nodeInfo.Node().GetName() if _, exist := ec.algorithmCache[nodeName]; !exist { - ec.algorithmCache[nodeName] = newAlgorithmCache() + ec.algorithmCache[nodeName] = AlgorithmCache{} } predicateItem := HostPredicate{ Fit: fit, FailReasons: reasons, } // if cached predicate map already exists, just update the predicate by key - if v, ok := ec.algorithmCache[nodeName].predicatesCache.Get(predicateKey); ok { - predicateMap := v.(PredicateMap) + if predicateMap, ok := ec.algorithmCache[nodeName][predicateKey]; ok { // maps in golang are references, no need to add them back predicateMap[equivalenceHash] = predicateItem } else { - ec.algorithmCache[nodeName].predicatesCache.Add(predicateKey, + ec.algorithmCache[nodeName][predicateKey] = PredicateMap{ equivalenceHash: predicateItem, - }) + } } glog.V(5).Infof("Updated cached predicate: %v for pod: %v on node: %s, with item %v", predicateKey, podName, nodeName, predicateItem) } -// PredicateWithECache returns: -// 1. if fit -// 2. reasons if not fit -// 3. if this cache is invalid -// based on cached predicate results -func (ec *EquivalenceCache) PredicateWithECache( +// lookupResult returns cached predicate results: +// 1. if pod fit +// 2. reasons if pod did not fit +// 3. if cache item is not found +func (ec *EquivalenceCache) lookupResult( podName, nodeName, predicateKey string, - equivalenceHash uint64, needLock bool, + equivalenceHash uint64, ) (bool, []algorithm.PredicateFailureReason, bool) { - if needLock { - ec.RLock() - defer ec.RUnlock() - } + ec.mu.RLock() + defer ec.mu.RUnlock() glog.V(5).Infof("Begin to calculate predicate: %v for pod: %s on node: %s based on equivalence cache", predicateKey, podName, nodeName) - if algorithmCache, exist := ec.algorithmCache[nodeName]; exist { - if cachePredicate, exist := algorithmCache.predicatesCache.Get(predicateKey); exist { - predicateMap := cachePredicate.(PredicateMap) - // TODO(resouer) Is it possible a race that cache failed to update immediately? - if hostPredicate, ok := predicateMap[equivalenceHash]; ok { - if hostPredicate.Fit { - return true, []algorithm.PredicateFailureReason{}, false - } - return false, hostPredicate.FailReasons, false - } - // is invalid - return false, []algorithm.PredicateFailureReason{}, true + if hostPredicate, exist := ec.algorithmCache[nodeName][predicateKey][equivalenceHash]; exist { + if hostPredicate.Fit { + return true, []algorithm.PredicateFailureReason{}, false } + return false, hostPredicate.FailReasons, false } + // is invalid return false, []algorithm.PredicateFailureReason{}, true } @@ -140,12 +158,10 @@ func (ec *EquivalenceCache) InvalidateCachedPredicateItem(nodeName string, predi if len(predicateKeys) == 0 { return } - ec.Lock() - defer ec.Unlock() - if algorithmCache, exist := ec.algorithmCache[nodeName]; exist { - for predicateKey := range predicateKeys { - algorithmCache.predicatesCache.Remove(predicateKey) - } + ec.mu.Lock() + defer ec.mu.Unlock() + for predicateKey := range predicateKeys { + delete(ec.algorithmCache[nodeName], predicateKey) } glog.V(5).Infof("Done invalidating cached predicates: %v on node: %s", predicateKeys, nodeName) } @@ -155,13 +171,12 @@ func (ec *EquivalenceCache) InvalidateCachedPredicateItemOfAllNodes(predicateKey if len(predicateKeys) == 0 { return } - ec.Lock() - defer ec.Unlock() + ec.mu.Lock() + defer ec.mu.Unlock() // algorithmCache uses nodeName as key, so we just iterate it and invalid given predicates for _, algorithmCache := range ec.algorithmCache { for predicateKey := range predicateKeys { - // just use keys is enough - algorithmCache.predicatesCache.Remove(predicateKey) + delete(algorithmCache, predicateKey) } } glog.V(5).Infof("Done invalidating cached predicates: %v on all node", predicateKeys) @@ -169,8 +184,8 @@ func (ec *EquivalenceCache) InvalidateCachedPredicateItemOfAllNodes(predicateKey // InvalidateAllCachedPredicateItemOfNode marks all cached items on given node as invalid func (ec *EquivalenceCache) InvalidateAllCachedPredicateItemOfNode(nodeName string) { - ec.Lock() - defer ec.Unlock() + ec.mu.Lock() + defer ec.mu.Unlock() delete(ec.algorithmCache, nodeName) glog.V(5).Infof("Done invalidating all cached predicates on node: %s", nodeName) } @@ -191,21 +206,21 @@ func (ec *EquivalenceCache) InvalidateCachedPredicateItemForPodAdd(pod *v1.Pod, // it will also fits to equivalence class of existing pods // GeneralPredicates: will always be affected by adding a new pod - invalidPredicates := sets.NewString("GeneralPredicates") + invalidPredicates := sets.NewString(predicates.GeneralPred) // MaxPDVolumeCountPredicate: we check the volumes of pod to make decision. for _, vol := range pod.Spec.Volumes { if vol.PersistentVolumeClaim != nil { - invalidPredicates.Insert("MaxEBSVolumeCount", "MaxGCEPDVolumeCount", "MaxAzureDiskVolumeCount") + invalidPredicates.Insert(predicates.MaxEBSVolumeCountPred, predicates.MaxGCEPDVolumeCountPred, predicates.MaxAzureDiskVolumeCountPred) } else { if vol.AWSElasticBlockStore != nil { - invalidPredicates.Insert("MaxEBSVolumeCount") + invalidPredicates.Insert(predicates.MaxEBSVolumeCountPred) } if vol.GCEPersistentDisk != nil { - invalidPredicates.Insert("MaxGCEPDVolumeCount") + invalidPredicates.Insert(predicates.MaxGCEPDVolumeCountPred) } if vol.AzureDisk != nil { - invalidPredicates.Insert("MaxAzureDiskVolumeCount") + invalidPredicates.Insert(predicates.MaxAzureDiskVolumeCountPred) } } } @@ -219,9 +234,11 @@ type equivalenceClassInfo struct { hash uint64 } -// getEquivalenceClassInfo returns the equivalence class of given pod. +// getEquivalenceClassInfo returns a hash of the given pod. +// The hashing function returns the same value for any two pods that are +// equivalent from the perspective of scheduling. func (ec *EquivalenceCache) getEquivalenceClassInfo(pod *v1.Pod) *equivalenceClassInfo { - equivalencePod := ec.getEquivalencePod(pod) + equivalencePod := getEquivalenceHash(pod) if equivalencePod != nil { hash := fnv.New32a() hashutil.DeepHashObject(hash, equivalencePod) @@ -231,3 +248,60 @@ func (ec *EquivalenceCache) getEquivalenceClassInfo(pod *v1.Pod) *equivalenceCla } return nil } + +// equivalencePod is the set of pod attributes which must match for two pods to +// be considered equivalent for scheduling purposes. For correctness, this must +// include any Pod field which is used by a FitPredicate. +// +// NOTE: For equivalence hash to be formally correct, lists and maps in the +// equivalencePod should be normalized. (e.g. by sorting them) However, the +// vast majority of equivalent pod classes are expected to be created from a +// single pod template, so they will all have the same ordering. +type equivalencePod struct { + Namespace *string + Labels map[string]string + Affinity *v1.Affinity + Containers []v1.Container // See note about ordering + InitContainers []v1.Container // See note about ordering + NodeName *string + NodeSelector map[string]string + Tolerations []v1.Toleration + Volumes []v1.Volume // See note about ordering +} + +// getEquivalenceHash returns the equivalencePod for a Pod. +func getEquivalenceHash(pod *v1.Pod) *equivalencePod { + ep := &equivalencePod{ + Namespace: &pod.Namespace, + Labels: pod.Labels, + Affinity: pod.Spec.Affinity, + Containers: pod.Spec.Containers, + InitContainers: pod.Spec.InitContainers, + NodeName: &pod.Spec.NodeName, + NodeSelector: pod.Spec.NodeSelector, + Tolerations: pod.Spec.Tolerations, + Volumes: pod.Spec.Volumes, + } + // DeepHashObject considers nil and empty slices to be different. Normalize them. + if len(ep.Containers) == 0 { + ep.Containers = nil + } + if len(ep.InitContainers) == 0 { + ep.InitContainers = nil + } + if len(ep.Tolerations) == 0 { + ep.Tolerations = nil + } + if len(ep.Volumes) == 0 { + ep.Volumes = nil + } + // Normalize empty maps also. + if len(ep.Labels) == 0 { + ep.Labels = nil + } + if len(ep.NodeSelector) == 0 { + ep.NodeSelector = nil + } + // TODO(misterikkit): Also normalize nested maps and slices. + return ep +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/core/equivalence_cache_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/core/equivalence_cache_test.go index fcb2c9455..2791111fa 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/core/equivalence_cache_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/core/equivalence_cache_test.go @@ -17,22 +17,291 @@ limitations under the License. package core import ( + "errors" "reflect" + "sync" "testing" + "time" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) +// makeBasicPod returns a Pod object with many of the fields populated. +func makeBasicPod(name string) *v1.Pod { + isController := true + return &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "test-ns", + Labels: map[string]string{"app": "web", "env": "prod"}, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "v1", + Kind: "ReplicationController", + Name: "rc", + UID: "123", + Controller: &isController, + }, + }, + }, + Spec: v1.PodSpec{ + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "failure-domain.beta.kubernetes.io/zone", + Operator: "Exists", + }, + }, + }, + }, + }, + }, + PodAffinity: &v1.PodAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ + { + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "db"}}, + TopologyKey: "kubernetes.io/hostname", + }, + }, + }, + PodAntiAffinity: &v1.PodAntiAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ + { + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "web"}}, + TopologyKey: "kubernetes.io/hostname", + }, + }, + }, + }, + InitContainers: []v1.Container{ + { + Name: "init-pause", + Image: "gcr.io/google_containers/pause", + Resources: v1.ResourceRequirements{ + Limits: v1.ResourceList{ + "cpu": resource.MustParse("1"), + "mem": resource.MustParse("100Mi"), + }, + }, + }, + }, + Containers: []v1.Container{ + { + Name: "pause", + Image: "gcr.io/google_containers/pause", + Resources: v1.ResourceRequirements{ + Limits: v1.ResourceList{ + "cpu": resource.MustParse("1"), + "mem": resource.MustParse("100Mi"), + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "nfs", + MountPath: "/srv/data", + }, + }, + }, + }, + NodeSelector: map[string]string{"node-type": "awesome"}, + Tolerations: []v1.Toleration{ + { + Effect: "NoSchedule", + Key: "experimental", + Operator: "Exists", + }, + }, + Volumes: []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "someEBSVol1", + }, + }, + }, + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "someEBSVol2", + }, + }, + }, + { + Name: "nfs", + VolumeSource: v1.VolumeSource{ + NFS: &v1.NFSVolumeSource{ + Server: "nfs.corp.example.com", + }, + }, + }, + }, + }, + } +} + type predicateItemType struct { fit bool reasons []algorithm.PredicateFailureReason } -func TestUpdateCachedPredicateItem(t *testing.T) { +// upToDateCache is a fake Cache where IsUpToDate always returns true. +type upToDateCache = schedulertesting.FakeCache + +// staleNodeCache is a fake Cache where IsUpToDate always returns false. +type staleNodeCache struct { + schedulertesting.FakeCache +} + +func (c *staleNodeCache) IsUpToDate(*schedulercache.NodeInfo) bool { return false } + +// mockPredicate provides an algorithm.FitPredicate with pre-set return values. +type mockPredicate struct { + fit bool + reasons []algorithm.PredicateFailureReason + err error + callCount int +} + +func (p *mockPredicate) predicate(*v1.Pod, algorithm.PredicateMetadata, *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { + p.callCount++ + return p.fit, p.reasons, p.err +} + +func TestRunPredicate(t *testing.T) { + tests := []struct { + name string + pred mockPredicate + cache schedulercache.Cache + expectFit, expectCacheHit, expectCacheWrite bool + expectedReasons []algorithm.PredicateFailureReason + expectedError string + }{ + { + name: "pod fits/cache hit", + pred: mockPredicate{}, + cache: &upToDateCache{}, + expectFit: true, + expectCacheHit: true, + expectCacheWrite: false, + }, + { + name: "pod fits/cache miss", + pred: mockPredicate{fit: true}, + cache: &upToDateCache{}, + expectFit: true, + expectCacheHit: false, + expectCacheWrite: true, + }, + { + name: "pod fits/cache miss/no write", + pred: mockPredicate{fit: true}, + cache: &staleNodeCache{}, + expectFit: true, + expectCacheHit: false, + expectCacheWrite: false, + }, + { + name: "pod doesn't fit/cache miss", + pred: mockPredicate{reasons: []algorithm.PredicateFailureReason{predicates.ErrFakePredicate}}, + cache: &upToDateCache{}, + expectFit: false, + expectCacheHit: false, + expectCacheWrite: true, + expectedReasons: []algorithm.PredicateFailureReason{predicates.ErrFakePredicate}, + }, + { + name: "pod doesn't fit/cache hit", + pred: mockPredicate{}, + cache: &upToDateCache{}, + expectFit: false, + expectCacheHit: true, + expectCacheWrite: false, + expectedReasons: []algorithm.PredicateFailureReason{predicates.ErrFakePredicate}, + }, + { + name: "predicate error", + pred: mockPredicate{err: errors.New("This is expected")}, + cache: &upToDateCache{}, + expectFit: false, + expectCacheHit: false, + expectCacheWrite: false, + expectedError: "This is expected", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + node := schedulercache.NewNodeInfo() + node.SetNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "n1"}}) + pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p1"}} + meta := algorithm.EmptyPredicateMetadataProducer(nil, nil) + + ecache := NewEquivalenceCache() + equivClass := ecache.getEquivalenceClassInfo(pod) + if test.expectCacheHit { + ecache.updateResult(pod.Name, "testPredicate", test.expectFit, test.expectedReasons, equivClass.hash, test.cache, node) + } + + fit, reasons, err := ecache.RunPredicate(test.pred.predicate, "testPredicate", pod, meta, node, equivClass, test.cache) + + if err != nil { + if err.Error() != test.expectedError { + t.Errorf("Expected error %v but got %v", test.expectedError, err) + } + } else if len(test.expectedError) > 0 { + t.Errorf("Expected error %v but got nil", test.expectedError) + } + if fit && !test.expectFit { + t.Errorf("pod should not fit") + } + if !fit && test.expectFit { + t.Errorf("pod should fit") + } + if len(reasons) != len(test.expectedReasons) { + t.Errorf("Expected failures: %v but got %v", test.expectedReasons, reasons) + } else { + for i, reason := range reasons { + if reason != test.expectedReasons[i] { + t.Errorf("Expected failures: %v but got %v", test.expectedReasons, reasons) + break + } + } + } + if test.expectCacheHit && test.pred.callCount != 0 { + t.Errorf("Predicate should not be called") + } + if !test.expectCacheHit && test.pred.callCount == 0 { + t.Errorf("Predicate should be called") + } + _, _, invalid := ecache.lookupResult(pod.Name, node.Node().Name, "testPredicate", equivClass.hash) + if invalid && test.expectCacheWrite { + t.Errorf("Cache write should happen") + } + if !test.expectCacheHit && test.expectCacheWrite && invalid { + t.Errorf("Cache write should happen") + } + if !test.expectCacheHit && !test.expectCacheWrite && !invalid { + t.Errorf("Cache write should not happen") + } + }) + } +} + +func TestUpdateResult(t *testing.T) { tests := []struct { name string pod string @@ -43,6 +312,7 @@ func TestUpdateCachedPredicateItem(t *testing.T) { equivalenceHash uint64 expectPredicateMap bool expectCacheItem HostPredicate + cache schedulercache.Cache }{ { name: "test 1", @@ -55,6 +325,7 @@ func TestUpdateCachedPredicateItem(t *testing.T) { expectCacheItem: HostPredicate{ Fit: true, }, + cache: &upToDateCache{}, }, { name: "test 2", @@ -67,38 +338,39 @@ func TestUpdateCachedPredicateItem(t *testing.T) { expectCacheItem: HostPredicate{ Fit: false, }, + cache: &upToDateCache{}, }, } for _, test := range tests { - // this case does not need to calculate equivalence hash, just pass an empty function - fakeGetEquivalencePodFunc := func(pod *v1.Pod) interface{} { return nil } - ecache := NewEquivalenceCache(fakeGetEquivalencePodFunc) + ecache := NewEquivalenceCache() if test.expectPredicateMap { - ecache.algorithmCache[test.nodeName] = newAlgorithmCache() + ecache.algorithmCache[test.nodeName] = AlgorithmCache{} predicateItem := HostPredicate{ Fit: true, } - ecache.algorithmCache[test.nodeName].predicatesCache.Add(test.predicateKey, + ecache.algorithmCache[test.nodeName][test.predicateKey] = PredicateMap{ test.equivalenceHash: predicateItem, - }) + } } - ecache.UpdateCachedPredicateItem( + + node := schedulercache.NewNodeInfo() + node.SetNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: test.nodeName}}) + ecache.updateResult( test.pod, - test.nodeName, test.predicateKey, test.fit, test.reasons, test.equivalenceHash, - true, + test.cache, + node, ) - value, ok := ecache.algorithmCache[test.nodeName].predicatesCache.Get(test.predicateKey) + cachedMapItem, ok := ecache.algorithmCache[test.nodeName][test.predicateKey] if !ok { t.Errorf("Failed: %s, can't find expected cache item: %v", test.name, test.expectCacheItem) } else { - cachedMapItem := value.(PredicateMap) if !reflect.DeepEqual(cachedMapItem[test.equivalenceHash], test.expectCacheItem) { t.Errorf("Failed: %s, expected cached item: %v, but got: %v", test.name, test.expectCacheItem, cachedMapItem[test.equivalenceHash]) @@ -107,7 +379,15 @@ func TestUpdateCachedPredicateItem(t *testing.T) { } } -func TestPredicateWithECache(t *testing.T) { +// slicesEqual wraps reflect.DeepEqual, but returns true when comparing nil and empty slice. +func slicesEqual(a, b []algorithm.PredicateFailureReason) bool { + if len(a) == 0 && len(b) == 0 { + return true + } + return reflect.DeepEqual(a, b) +} + +func TestLookupResult(t *testing.T) { tests := []struct { name string podName string @@ -119,6 +399,7 @@ func TestPredicateWithECache(t *testing.T) { expectedInvalidPredicateKey bool expectedInvalidEquivalenceHash bool expectedPredicateItem predicateItemType + cache schedulercache.Cache }{ { name: "test 1", @@ -136,6 +417,7 @@ func TestPredicateWithECache(t *testing.T) { fit: false, reasons: []algorithm.PredicateFailureReason{}, }, + cache: &upToDateCache{}, }, { name: "test 2", @@ -152,6 +434,7 @@ func TestPredicateWithECache(t *testing.T) { fit: true, reasons: []algorithm.PredicateFailureReason{}, }, + cache: &upToDateCache{}, }, { name: "test 3", @@ -169,6 +452,7 @@ func TestPredicateWithECache(t *testing.T) { fit: false, reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, }, + cache: &upToDateCache{}, }, { name: "test 4", @@ -187,22 +471,23 @@ func TestPredicateWithECache(t *testing.T) { fit: false, reasons: []algorithm.PredicateFailureReason{}, }, + cache: &upToDateCache{}, }, } for _, test := range tests { - // this case does not need to calculate equivalence hash, just pass an empty function - fakeGetEquivalencePodFunc := func(pod *v1.Pod) interface{} { return nil } - ecache := NewEquivalenceCache(fakeGetEquivalencePodFunc) + ecache := NewEquivalenceCache() + node := schedulercache.NewNodeInfo() + node.SetNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: test.nodeName}}) // set cached item to equivalence cache - ecache.UpdateCachedPredicateItem( + ecache.updateResult( test.podName, - test.nodeName, test.predicateKey, test.cachedItem.fit, test.cachedItem.reasons, test.equivalenceHashForUpdatePredicate, - true, + test.cache, + node, ) // if we want to do invalid, invalid the cached item if test.expectedInvalidPredicateKey { @@ -211,11 +496,10 @@ func TestPredicateWithECache(t *testing.T) { ecache.InvalidateCachedPredicateItem(test.nodeName, predicateKeys) } // calculate predicate with equivalence cache - fit, reasons, invalid := ecache.PredicateWithECache(test.podName, + fit, reasons, invalid := ecache.lookupResult(test.podName, test.nodeName, test.predicateKey, test.equivalenceHashForCalPredicate, - true, ) // returned invalid should match expectedInvalidPredicateKey or expectedInvalidEquivalenceHash if test.equivalenceHashForUpdatePredicate != test.equivalenceHashForCalPredicate { @@ -233,212 +517,53 @@ func TestPredicateWithECache(t *testing.T) { if fit != test.expectedPredicateItem.fit { t.Errorf("Failed: %s, expected fit: %v, but got: %v", test.name, test.cachedItem.fit, fit) } - if !reflect.DeepEqual(reasons, test.expectedPredicateItem.reasons) { + if !slicesEqual(reasons, test.expectedPredicateItem.reasons) { t.Errorf("Failed: %s, expected reasons: %v, but got: %v", - test.name, test.cachedItem.reasons, reasons) + test.name, test.expectedPredicateItem.reasons, reasons) } } } -func TestGetHashEquivalencePod(t *testing.T) { - - testNamespace := "test" - - pvcInfo := predicates.FakePersistentVolumeClaimInfo{ - { - ObjectMeta: metav1.ObjectMeta{UID: "someEBSVol1", Name: "someEBSVol1", Namespace: testNamespace}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "someEBSVol1"}, - }, - { - ObjectMeta: metav1.ObjectMeta{UID: "someEBSVol2", Name: "someEBSVol2", Namespace: testNamespace}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "someNonEBSVol"}, - }, - { - ObjectMeta: metav1.ObjectMeta{UID: "someEBSVol3-0", Name: "someEBSVol3-0", Namespace: testNamespace}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "pvcWithDeletedPV"}, - }, - { - ObjectMeta: metav1.ObjectMeta{UID: "someEBSVol3-1", Name: "someEBSVol3-1", Namespace: testNamespace}, - Spec: v1.PersistentVolumeClaimSpec{VolumeName: "anotherPVCWithDeletedPV"}, - }, - } +func TestGetEquivalenceHash(t *testing.T) { - // use default equivalence class generator - ecache := NewEquivalenceCache(predicates.NewEquivalencePodGenerator(pvcInfo)) + ecache := NewEquivalenceCache() - isController := true + pod1 := makeBasicPod("pod1") + pod2 := makeBasicPod("pod2") - pod1 := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod1", - Namespace: testNamespace, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: "v1", - Kind: "ReplicationController", - Name: "rc", - UID: "123", - Controller: &isController, - }, - }, - }, - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol1", - }, - }, - }, - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol2", - }, - }, + pod3 := makeBasicPod("pod3") + pod3.Spec.Volumes = []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "someEBSVol111", }, }, }, } - pod2 := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod2", - Namespace: testNamespace, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: "v1", - Kind: "ReplicationController", - Name: "rc", - UID: "123", - Controller: &isController, - }, - }, - }, - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol2", - }, - }, - }, - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol1", - }, - }, + pod4 := makeBasicPod("pod4") + pod4.Spec.Volumes = []v1.Volume{ + { + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: "someEBSVol222", }, }, }, } - pod3 := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod3", - Namespace: testNamespace, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: "v1", - Kind: "ReplicationController", - Name: "rc", - UID: "567", - Controller: &isController, - }, - }, - }, - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol3-1", - }, - }, - }, - }, - }, - } + pod5 := makeBasicPod("pod5") + pod5.Spec.Volumes = []v1.Volume{} - pod4 := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod4", - Namespace: testNamespace, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: "v1", - Kind: "ReplicationController", - Name: "rc", - UID: "567", - Controller: &isController, - }, - }, - }, - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol3-0", - }, - }, - }, - }, - }, - } + pod6 := makeBasicPod("pod6") + pod6.Spec.Volumes = nil - pod5 := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod5", - Namespace: testNamespace, - }, - } + pod7 := makeBasicPod("pod7") + pod7.Spec.NodeSelector = nil - pod6 := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod6", - Namespace: testNamespace, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: "v1", - Kind: "ReplicationController", - Name: "rc", - UID: "567", - Controller: &isController, - }, - }, - }, - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "no-exists-pvc", - }, - }, - }, - }, - }, - } - - pod7 := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod7", - Namespace: testNamespace, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: "v1", - Kind: "ReplicationController", - Name: "rc", - UID: "567", - Controller: &isController, - }, - }, - }, - } + pod8 := makeBasicPod("pod8") + pod8.Spec.NodeSelector = make(map[string]string) type podInfo struct { pod *v1.Pod @@ -446,39 +571,41 @@ func TestGetHashEquivalencePod(t *testing.T) { } tests := []struct { + name string podInfoList []podInfo isEquivalent bool }{ - // pods with same controllerRef and same pvc claim { + name: "pods with everything the same except name", podInfoList: []podInfo{ {pod: pod1, hashIsValid: true}, {pod: pod2, hashIsValid: true}, }, isEquivalent: true, }, - // pods with same controllerRef but different pvc claim { + name: "pods that only differ in their PVC volume sources", podInfoList: []podInfo{ {pod: pod3, hashIsValid: true}, {pod: pod4, hashIsValid: true}, }, isEquivalent: false, }, - // pod without controllerRef { + name: "pods that have no volumes, but one uses nil and one uses an empty slice", podInfoList: []podInfo{ - {pod: pod5, hashIsValid: false}, + {pod: pod5, hashIsValid: true}, + {pod: pod6, hashIsValid: true}, }, - isEquivalent: false, + isEquivalent: true, }, - // pods with same controllerRef but one has non-exists pvc claim { + name: "pods that have no NodeSelector, but one uses nil and one uses an empty map", podInfoList: []podInfo{ - {pod: pod6, hashIsValid: false}, {pod: pod7, hashIsValid: true}, + {pod: pod8, hashIsValid: true}, }, - isEquivalent: false, + isEquivalent: true, }, } @@ -488,28 +615,30 @@ func TestGetHashEquivalencePod(t *testing.T) { ) for _, test := range tests { - for i, podInfo := range test.podInfoList { - testPod := podInfo.pod - eclassInfo := ecache.getEquivalenceClassInfo(testPod) - if eclassInfo == nil && podInfo.hashIsValid { - t.Errorf("Failed: pod %v is expected to have valid hash", testPod) - } + t.Run(test.name, func(t *testing.T) { + for i, podInfo := range test.podInfoList { + testPod := podInfo.pod + eclassInfo := ecache.getEquivalenceClassInfo(testPod) + if eclassInfo == nil && podInfo.hashIsValid { + t.Errorf("Failed: pod %v is expected to have valid hash", testPod) + } - if eclassInfo != nil { - // NOTE(harry): the first element will be used as target so - // this logic can't verify more than two inequivalent pods - if i == 0 { - targetHash = eclassInfo.hash - targetPodInfo = podInfo - } else { - if targetHash != eclassInfo.hash { - if test.isEquivalent { - t.Errorf("Failed: pod: %v is expected to be equivalent to: %v", testPod, targetPodInfo.pod) + if eclassInfo != nil { + // NOTE(harry): the first element will be used as target so + // this logic can't verify more than two inequivalent pods + if i == 0 { + targetHash = eclassInfo.hash + targetPodInfo = podInfo + } else { + if targetHash != eclassInfo.hash { + if test.isEquivalent { + t.Errorf("Failed: pod: %v is expected to be equivalent to: %v", testPod, targetPodInfo.pod) + } } } } } - } + }) } } @@ -519,9 +648,9 @@ func TestInvalidateCachedPredicateItemOfAllNodes(t *testing.T) { tests := []struct { podName string nodeName string - predicateKey string equivalenceHashForUpdatePredicate uint64 cachedItem predicateItemType + cache schedulercache.Cache }{ { podName: "testPod", @@ -533,6 +662,7 @@ func TestInvalidateCachedPredicateItemOfAllNodes(t *testing.T) { predicates.ErrPodNotFitsHostPorts, }, }, + cache: &upToDateCache{}, }, { podName: "testPod", @@ -544,6 +674,7 @@ func TestInvalidateCachedPredicateItemOfAllNodes(t *testing.T) { predicates.ErrPodNotFitsHostPorts, }, }, + cache: &upToDateCache{}, }, { podName: "testPod", @@ -552,22 +683,23 @@ func TestInvalidateCachedPredicateItemOfAllNodes(t *testing.T) { cachedItem: predicateItemType{ fit: true, }, + cache: &upToDateCache{}, }, } - // this case does not need to calculate equivalence hash, just pass an empty function - fakeGetEquivalencePodFunc := func(pod *v1.Pod) interface{} { return nil } - ecache := NewEquivalenceCache(fakeGetEquivalencePodFunc) + ecache := NewEquivalenceCache() for _, test := range tests { + node := schedulercache.NewNodeInfo() + node.SetNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: test.nodeName}}) // set cached item to equivalence cache - ecache.UpdateCachedPredicateItem( + ecache.updateResult( test.podName, - test.nodeName, testPredicate, test.cachedItem.fit, test.cachedItem.reasons, test.equivalenceHashForUpdatePredicate, - true, + test.cache, + node, ) } @@ -577,7 +709,7 @@ func TestInvalidateCachedPredicateItemOfAllNodes(t *testing.T) { // there should be no cached predicate any more for _, test := range tests { if algorithmCache, exist := ecache.algorithmCache[test.nodeName]; exist { - if _, exist := algorithmCache.predicatesCache.Get(testPredicate); exist { + if _, exist := algorithmCache[testPredicate]; exist { t.Errorf("Failed: cached item for predicate key: %v on node: %v should be invalidated", testPredicate, test.nodeName) break @@ -592,9 +724,9 @@ func TestInvalidateAllCachedPredicateItemOfNode(t *testing.T) { tests := []struct { podName string nodeName string - predicateKey string equivalenceHashForUpdatePredicate uint64 cachedItem predicateItemType + cache schedulercache.Cache }{ { podName: "testPod", @@ -604,6 +736,7 @@ func TestInvalidateAllCachedPredicateItemOfNode(t *testing.T) { fit: false, reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, }, + cache: &upToDateCache{}, }, { podName: "testPod", @@ -613,6 +746,7 @@ func TestInvalidateAllCachedPredicateItemOfNode(t *testing.T) { fit: false, reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, }, + cache: &upToDateCache{}, }, { podName: "testPod", @@ -621,22 +755,23 @@ func TestInvalidateAllCachedPredicateItemOfNode(t *testing.T) { cachedItem: predicateItemType{ fit: true, }, + cache: &upToDateCache{}, }, } - // this case does not need to calculate equivalence hash, just pass an empty function - fakeGetEquivalencePodFunc := func(pod *v1.Pod) interface{} { return nil } - ecache := NewEquivalenceCache(fakeGetEquivalencePodFunc) + ecache := NewEquivalenceCache() for _, test := range tests { + node := schedulercache.NewNodeInfo() + node.SetNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: test.nodeName}}) // set cached item to equivalence cache - ecache.UpdateCachedPredicateItem( + ecache.updateResult( test.podName, - test.nodeName, testPredicate, test.cachedItem.fit, test.cachedItem.reasons, test.equivalenceHashForUpdatePredicate, - true, + test.cache, + node, ) } @@ -649,3 +784,107 @@ func TestInvalidateAllCachedPredicateItemOfNode(t *testing.T) { } } } + +func BenchmarkEquivalenceHash(b *testing.B) { + pod := makeBasicPod("test") + for i := 0; i < b.N; i++ { + getEquivalenceHash(pod) + } +} + +// syncingMockCache delegates method calls to an actual Cache, +// but calls to UpdateNodeNameToInfoMap synchronize with the test. +type syncingMockCache struct { + schedulercache.Cache + cycleStart, cacheInvalidated chan struct{} + once sync.Once +} + +// UpdateNodeNameToInfoMap delegates to the real implementation, but on the first call, it +// synchronizes with the test. +// +// Since UpdateNodeNameToInfoMap is one of the first steps of (*genericScheduler).Schedule, we use +// this point to signal to the test that a scheduling cycle has started. +func (c *syncingMockCache) UpdateNodeNameToInfoMap(infoMap map[string]*schedulercache.NodeInfo) error { + err := c.Cache.UpdateNodeNameToInfoMap(infoMap) + c.once.Do(func() { + c.cycleStart <- struct{}{} + <-c.cacheInvalidated + }) + return err +} + +// TestEquivalenceCacheInvalidationRace tests that equivalence cache invalidation is correctly +// handled when an invalidation event happens early in a scheduling cycle. Specifically, the event +// occurs after schedulercache is snapshotted and before equivalence cache lock is acquired. +func TestEquivalenceCacheInvalidationRace(t *testing.T) { + // Create a predicate that returns false the first time and true on subsequent calls. + podWillFit := false + var callCount int + testPredicate := func(pod *v1.Pod, + meta algorithm.PredicateMetadata, + nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { + callCount++ + if !podWillFit { + podWillFit = true + return false, []algorithm.PredicateFailureReason{predicates.ErrFakePredicate}, nil + } + return true, nil, nil + } + + // Set up the mock cache. + cache := schedulercache.New(time.Duration(0), wait.NeverStop) + cache.AddNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine1"}}) + mockCache := &syncingMockCache{ + Cache: cache, + cycleStart: make(chan struct{}), + cacheInvalidated: make(chan struct{}), + } + + eCache := NewEquivalenceCache() + // Ensure that equivalence cache invalidation happens after the scheduling cycle starts, but before + // the equivalence cache would be updated. + go func() { + <-mockCache.cycleStart + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "new-pod", UID: "new-pod"}, + Spec: v1.PodSpec{NodeName: "machine1"}} + if err := cache.AddPod(pod); err != nil { + t.Errorf("Could not add pod to cache: %v", err) + } + eCache.InvalidateAllCachedPredicateItemOfNode("machine1") + mockCache.cacheInvalidated <- struct{}{} + }() + + // Set up the scheduler. + ps := map[string]algorithm.FitPredicate{"testPredicate": testPredicate} + predicates.SetPredicatesOrdering([]string{"testPredicate"}) + prioritizers := []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}} + pvcLister := schedulertesting.FakePersistentVolumeClaimLister([]*v1.PersistentVolumeClaim{}) + scheduler := NewGenericScheduler( + mockCache, + eCache, + NewSchedulingQueue(), + ps, + algorithm.EmptyPredicateMetadataProducer, + prioritizers, + algorithm.EmptyPriorityMetadataProducer, + nil, nil, pvcLister, true, false) + + // First scheduling attempt should fail. + nodeLister := schedulertesting.FakeNodeLister(makeNodeList([]string{"machine1"})) + pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "test-pod"}} + machine, err := scheduler.Schedule(pod, nodeLister) + if machine != "" || err == nil { + t.Error("First scheduling attempt did not fail") + } + + // Second scheduling attempt should succeed because cache was invalidated. + _, err = scheduler.Schedule(pod, nodeLister) + if err != nil { + t.Errorf("Second scheduling attempt failed: %v", err) + } + if callCount != 2 { + t.Errorf("Predicate should have been called twice. Was called %d times.", callCount) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/core/extender.go b/vendor/k8s.io/kubernetes/pkg/scheduler/core/extender.go index 022db87f5..94d143493 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/core/extender.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/core/extender.go @@ -30,7 +30,7 @@ import ( restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) const ( @@ -41,6 +41,7 @@ const ( // HTTPExtender implements the algorithm.SchedulerExtender interface. type HTTPExtender struct { extenderURL string + preemptVerb string filterVerb string prioritizeVerb string bindVerb string @@ -48,6 +49,7 @@ type HTTPExtender struct { client *http.Client nodeCacheCapable bool managedResources sets.String + ignorable bool } func makeTransport(config *schedulerapi.ExtenderConfig) (http.RoundTripper, error) { @@ -93,6 +95,7 @@ func NewHTTPExtender(config *schedulerapi.ExtenderConfig) (algorithm.SchedulerEx } return &HTTPExtender{ extenderURL: config.URLPrefix, + preemptVerb: config.PreemptVerb, filterVerb: config.FilterVerb, prioritizeVerb: config.PrioritizeVerb, bindVerb: config.BindVerb, @@ -100,13 +103,150 @@ func NewHTTPExtender(config *schedulerapi.ExtenderConfig) (algorithm.SchedulerEx client: client, nodeCacheCapable: config.NodeCacheCapable, managedResources: managedResources, + ignorable: config.Ignorable, }, nil } +// IsIgnorable returns true indicates scheduling should not fail when this extender +// is unavailable +func (h *HTTPExtender) IsIgnorable() bool { + return h.ignorable +} + +// SupportsPreemption returns if a extender support preemption. +// A extender should have preempt verb defined and enabled its own node cache. +func (h *HTTPExtender) SupportsPreemption() bool { + return len(h.preemptVerb) > 0 +} + +// ProcessPreemption returns filtered candidate nodes and victims after running preemption logic in extender. +func (h *HTTPExtender) ProcessPreemption( + pod *v1.Pod, + nodeToVictims map[*v1.Node]*schedulerapi.Victims, + nodeNameToInfo map[string]*schedulercache.NodeInfo, +) (map[*v1.Node]*schedulerapi.Victims, error) { + var ( + result schedulerapi.ExtenderPreemptionResult + args *schedulerapi.ExtenderPreemptionArgs + ) + + if !h.SupportsPreemption() { + return nil, fmt.Errorf("preempt verb is not defined for extender %v but run into ProcessPreemption", h.extenderURL) + } + + if h.nodeCacheCapable { + // If extender has cached node info, pass NodeNameToMetaVictims in args. + nodeNameToMetaVictims := convertToNodeNameToMetaVictims(nodeToVictims) + args = &schedulerapi.ExtenderPreemptionArgs{ + Pod: pod, + NodeNameToMetaVictims: nodeNameToMetaVictims, + } + } else { + nodeNameToVictims := convertToNodeNameToVictims(nodeToVictims) + args = &schedulerapi.ExtenderPreemptionArgs{ + Pod: pod, + NodeNameToVictims: nodeNameToVictims, + } + } + + if err := h.send(h.preemptVerb, args, &result); err != nil { + return nil, err + } + + // Extender will always return NodeNameToMetaVictims. + // So let's convert it to NodeToVictims by using NodeNameToInfo. + newNodeToVictims, err := h.convertToNodeToVictims(result.NodeNameToMetaVictims, nodeNameToInfo) + if err != nil { + return nil, err + } + // Do not override nodeToVictims + return newNodeToVictims, nil +} + +// convertToNodeToVictims converts "nodeNameToMetaVictims" from object identifiers, +// such as UIDs and names, to object pointers. +func (h *HTTPExtender) convertToNodeToVictims( + nodeNameToMetaVictims map[string]*schedulerapi.MetaVictims, + nodeNameToInfo map[string]*schedulercache.NodeInfo, +) (map[*v1.Node]*schedulerapi.Victims, error) { + nodeToVictims := map[*v1.Node]*schedulerapi.Victims{} + for nodeName, metaVictims := range nodeNameToMetaVictims { + victims := &schedulerapi.Victims{ + Pods: []*v1.Pod{}, + } + for _, metaPod := range metaVictims.Pods { + pod, err := h.convertPodUIDToPod(metaPod, nodeName, nodeNameToInfo) + if err != nil { + return nil, err + } + victims.Pods = append(victims.Pods, pod) + } + nodeToVictims[nodeNameToInfo[nodeName].Node()] = victims + } + return nodeToVictims, nil +} + +// convertPodUIDToPod returns v1.Pod object for given MetaPod and node name. +// The v1.Pod object is restored by nodeInfo.Pods(). +// It should return error if there's cache inconsistency between default scheduler and extender +// so that this pod or node is missing from nodeNameToInfo. +func (h *HTTPExtender) convertPodUIDToPod( + metaPod *schedulerapi.MetaPod, + nodeName string, + nodeNameToInfo map[string]*schedulercache.NodeInfo) (*v1.Pod, error) { + var nodeInfo *schedulercache.NodeInfo + if nodeInfo, ok := nodeNameToInfo[nodeName]; ok { + for _, pod := range nodeInfo.Pods() { + if string(pod.UID) == metaPod.UID { + return pod, nil + } + } + return nil, fmt.Errorf("extender: %v claims to preempt pod (UID: %v) on node: %v, but the pod is not found on that node", + h.extenderURL, metaPod, nodeInfo.Node().Name) + } + + return nil, fmt.Errorf("extender: %v claims to preempt on node: %v but the node is not found in nodeNameToInfo map", + h.extenderURL, nodeInfo.Node().Name) +} + +// convertToNodeNameToMetaVictims converts from struct type to meta types. +func convertToNodeNameToMetaVictims( + nodeToVictims map[*v1.Node]*schedulerapi.Victims, +) map[string]*schedulerapi.MetaVictims { + nodeNameToVictims := map[string]*schedulerapi.MetaVictims{} + for node, victims := range nodeToVictims { + metaVictims := &schedulerapi.MetaVictims{ + Pods: []*schedulerapi.MetaPod{}, + } + for _, pod := range victims.Pods { + metaPod := &schedulerapi.MetaPod{ + UID: string(pod.UID), + } + metaVictims.Pods = append(metaVictims.Pods, metaPod) + } + nodeNameToVictims[node.GetName()] = metaVictims + } + return nodeNameToVictims +} + +// convertToNodeNameToVictims converts from node type to node name as key. +func convertToNodeNameToVictims( + nodeToVictims map[*v1.Node]*schedulerapi.Victims, +) map[string]*schedulerapi.Victims { + nodeNameToVictims := map[string]*schedulerapi.Victims{} + for node, victims := range nodeToVictims { + nodeNameToVictims[node.GetName()] = victims + } + return nodeNameToVictims +} + // Filter based on extender implemented predicate functions. The filtered list is // expected to be a subset of the supplied list. failedNodesMap optionally contains // the list of failed nodes and failure reasons. -func (h *HTTPExtender) Filter(pod *v1.Pod, nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo) ([]*v1.Node, schedulerapi.FailedNodesMap, error) { +func (h *HTTPExtender) Filter( + pod *v1.Pod, + nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo, +) ([]*v1.Node, schedulerapi.FailedNodesMap, error) { var ( result schedulerapi.ExtenderFilterResult nodeList *v1.NodeList @@ -133,7 +273,7 @@ func (h *HTTPExtender) Filter(pod *v1.Pod, nodes []*v1.Node, nodeNameToInfo map[ } args = &schedulerapi.ExtenderArgs{ - Pod: *pod, + Pod: pod, Nodes: nodeList, NodeNames: nodeNames, } @@ -193,7 +333,7 @@ func (h *HTTPExtender) Prioritize(pod *v1.Pod, nodes []*v1.Node) (*schedulerapi. } args = &schedulerapi.ExtenderArgs{ - Pod: *pod, + Pod: pod, Nodes: nodeList, NodeNames: nodeNames, } @@ -254,7 +394,7 @@ func (h *HTTPExtender) send(action string, args interface{}, result interface{}) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return fmt.Errorf("Failed %v with extender at URL %v, code %v", action, h.extenderURL, resp.StatusCode) + return fmt.Errorf("Failed %v with extender at URL %v, code %v", action, url, resp.StatusCode) } return json.NewDecoder(resp.Body).Decode(result) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/core/extender_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/core/extender_test.go index 766ee2dec..41fe6e91a 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/core/extender_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/core/extender_test.go @@ -26,8 +26,9 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" + "k8s.io/kubernetes/pkg/scheduler/util" ) type fitPredicate func(pod *v1.Pod, node *v1.Node) (bool, error) @@ -111,22 +112,159 @@ type FakeExtender struct { nodeCacheCapable bool filteredNodes []*v1.Node unInterested bool + ignorable bool + + // Cached node information for fake extender + cachedNodeNameToInfo map[string]*schedulercache.NodeInfo +} + +func (f *FakeExtender) IsIgnorable() bool { + return f.ignorable +} + +func (f *FakeExtender) SupportsPreemption() bool { + // Assume preempt verb is always defined. + return true +} + +func (f *FakeExtender) ProcessPreemption( + pod *v1.Pod, + nodeToVictims map[*v1.Node]*schedulerapi.Victims, + nodeNameToInfo map[string]*schedulercache.NodeInfo, +) (map[*v1.Node]*schedulerapi.Victims, error) { + nodeToVictimsCopy := map[*v1.Node]*schedulerapi.Victims{} + // We don't want to change the original nodeToVictims + for k, v := range nodeToVictims { + // In real world implementation, extender's user should have their own way to get node object + // by name if needed (e.g. query kube-apiserver etc). + // + // For test purpose, we just use node from parameters directly. + nodeToVictimsCopy[k] = v + } + + for node, victims := range nodeToVictimsCopy { + // Try to do preemption on extender side. + extenderVictimPods, extendernPDBViolations, fits, err := f.selectVictimsOnNodeByExtender(pod, node, nodeNameToInfo) + if err != nil { + return nil, err + } + // If it's unfit after extender's preemption, this node is unresolvable by preemption overall, + // let's remove it from potential preemption nodes. + if !fits { + delete(nodeToVictimsCopy, node) + } else { + // Append new victims to original victims + nodeToVictimsCopy[node].Pods = append(victims.Pods, extenderVictimPods...) + nodeToVictimsCopy[node].NumPDBViolations = victims.NumPDBViolations + extendernPDBViolations + } + } + return nodeToVictimsCopy, nil +} + +// selectVictimsOnNodeByExtender checks the given nodes->pods map with predicates on extender's side. +// Returns: +// 1. More victim pods (if any) amended by preemption phase of extender. +// 2. Number of violating victim (used to calculate PDB). +// 3. Fits or not after preemption phase on extender's side. +func (f *FakeExtender) selectVictimsOnNodeByExtender( + pod *v1.Pod, + node *v1.Node, + nodeNameToInfo map[string]*schedulercache.NodeInfo, +) ([]*v1.Pod, int, bool, error) { + // If a extender support preemption but have no cached node info, let's run filter to make sure + // default scheduler's decision still stand with given pod and node. + if !f.nodeCacheCapable { + fits, err := f.runPredicate(pod, node) + if err != nil { + return nil, 0, false, err + } + if !fits { + return nil, 0, false, nil + } + return []*v1.Pod{}, 0, true, nil + } + + // Otherwise, as a extender support preemption and have cached node info, we will assume cachedNodeNameToInfo is available + // and get cached node info by given node name. + nodeInfoCopy := f.cachedNodeNameToInfo[node.GetName()].Clone() + + potentialVictims := util.SortableList{CompFunc: util.HigherPriorityPod} + + removePod := func(rp *v1.Pod) { + nodeInfoCopy.RemovePod(rp) + } + addPod := func(ap *v1.Pod) { + nodeInfoCopy.AddPod(ap) + } + // As the first step, remove all the lower priority pods from the node and + // check if the given pod can be scheduled. + podPriority := util.GetPodPriority(pod) + for _, p := range nodeInfoCopy.Pods() { + if util.GetPodPriority(p) < podPriority { + potentialVictims.Items = append(potentialVictims.Items, p) + removePod(p) + } + } + potentialVictims.Sort() + + // If the new pod does not fit after removing all the lower priority pods, + // we are almost done and this node is not suitable for preemption. + fits, err := f.runPredicate(pod, nodeInfoCopy.Node()) + if err != nil { + return nil, 0, false, err + } + if !fits { + return nil, 0, false, nil + } + + var victims []*v1.Pod + + // TODO(harry): handle PDBs in the future. + numViolatingVictim := 0 + + reprievePod := func(p *v1.Pod) bool { + addPod(p) + fits, _ := f.runPredicate(pod, nodeInfoCopy.Node()) + if !fits { + removePod(p) + victims = append(victims, p) + } + return fits + } + + // For now, assume all potential victims to be non-violating. + // Now we try to reprieve non-violating victims. + for _, p := range potentialVictims.Items { + reprievePod(p.(*v1.Pod)) + } + + return victims, numViolatingVictim, true, nil +} + +// runPredicate run predicates of extender one by one for given pod and node. +// Returns: fits or not. +func (f *FakeExtender) runPredicate(pod *v1.Pod, node *v1.Node) (bool, error) { + fits := true + var err error + for _, predicate := range f.predicates { + fits, err = predicate(pod, node) + if err != nil { + return false, err + } + if !fits { + break + } + } + return fits, nil } func (f *FakeExtender) Filter(pod *v1.Pod, nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo) ([]*v1.Node, schedulerapi.FailedNodesMap, error) { filtered := []*v1.Node{} failedNodesMap := schedulerapi.FailedNodesMap{} for _, node := range nodes { - fits := true - for _, predicate := range f.predicates { - fit, err := predicate(pod, node) - if err != nil { - return []*v1.Node{}, schedulerapi.FailedNodesMap{}, err - } - if !fit { - fits = false - break - } + fits, err := f.runPredicate(pod, node) + if err != nil { + return []*v1.Node{}, schedulerapi.FailedNodesMap{}, err } if fits { filtered = append(filtered, node) @@ -192,15 +330,13 @@ var _ algorithm.SchedulerExtender = &FakeExtender{} func TestGenericSchedulerWithExtenders(t *testing.T) { tests := []struct { - name string - predicates map[string]algorithm.FitPredicate - prioritizers []algorithm.PriorityConfig - extenders []FakeExtender - extenderPredicates []fitPredicate - extenderPrioritizers []priorityConfig - nodes []string - expectedHost string - expectsErr bool + name string + predicates map[string]algorithm.FitPredicate + prioritizers []algorithm.PriorityConfig + extenders []FakeExtender + nodes []string + expectedHost string + expectsErr bool }{ { predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, @@ -314,7 +450,7 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { // Filter/Prioritize phases if the extender is not interested in // the pod. // - // If scheduler sends the pod by mistake, the test will fail + // If scheduler sends the pod by mistake, the test would fail // because of the errors from errorPredicateExtender and/or // errorPrioritizerExtender. predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, @@ -331,6 +467,28 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { expectedHost: "machine2", // machine2 has higher score name: "test 8", }, + { + // Scheduling is expected to not fail in + // Filter/Prioritize phases if the extender is not available and ignorable. + // + // If scheduler did not ignore the extender, the test would fail + // because of the errors from errorPredicateExtender. + predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, + extenders: []FakeExtender{ + { + predicates: []fitPredicate{errorPredicateExtender}, + ignorable: true, + }, + { + predicates: []fitPredicate{machine1PredicateExtender}, + }, + }, + nodes: []string{"machine1", "machine2"}, + expectsErr: false, + expectedHost: "machine1", + name: "test 9", + }, } for _, test := range tests { @@ -340,11 +498,22 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { } cache := schedulercache.New(time.Duration(0), wait.NeverStop) for _, name := range test.nodes { - cache.AddNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: name}}) + cache.AddNode(createNode(name)) } queue := NewSchedulingQueue() scheduler := NewGenericScheduler( - cache, nil, queue, test.predicates, algorithm.EmptyPredicateMetadataProducer, test.prioritizers, algorithm.EmptyPriorityMetadataProducer, extenders, nil, schedulertesting.FakePersistentVolumeClaimLister{}, false) + cache, + nil, + queue, + test.predicates, + algorithm.EmptyPredicateMetadataProducer, + test.prioritizers, + algorithm.EmptyPriorityMetadataProducer, + extenders, + nil, + schedulertesting.FakePersistentVolumeClaimLister{}, + false, + false) podIgnored := &v1.Pod{} machine, err := scheduler.Schedule(podIgnored, schedulertesting.FakeNodeLister(makeNodeList(test.nodes))) if test.expectsErr { @@ -362,3 +531,7 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { } } } + +func createNode(name string) *v1.Node { + return &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: name}} +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler.go b/vendor/k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler.go index d93c59fb4..21aadbf69 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler.go @@ -25,6 +25,8 @@ import ( "sync/atomic" "time" + "github.com/golang/glog" + "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -36,12 +38,10 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/metrics" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" - - "github.com/golang/glog" ) // FailedPredicateMap declares a map[string][]algorithm.PredicateFailureReason type. @@ -54,13 +54,7 @@ type FitError struct { FailedPredicates FailedPredicateMap } -// Victims describes pod victims. -type Victims struct { - pods []*v1.Pod - numPDBViolations int -} - -// ErrNoNodesAvailable defines an error of no nodes available. +// ErrNoNodesAvailable is used to describe the error that no nodes available to schedule pods. var ErrNoNodesAvailable = fmt.Errorf("no nodes available to schedule pods") const ( @@ -104,6 +98,7 @@ type genericScheduler struct { cachedNodeInfoMap map[string]*schedulercache.NodeInfo volumeBinder *volumebinder.VolumeBinder pvcLister corelisters.PersistentVolumeClaimLister + disablePreemption bool } // Schedule tries to schedule the given pod to one of the nodes in the node list. @@ -133,7 +128,7 @@ func (g *genericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister trace.Step("Computing predicates") startPredicateEvalTime := time.Now() - filteredNodes, failedPredicateMap, err := findNodesThatFit(pod, g.cachedNodeInfoMap, nodes, g.predicates, g.extenders, g.predicateMetaProducer, g.equivalenceCache, g.schedulingQueue, g.alwaysCheckAllPredicates) + filteredNodes, failedPredicateMap, err := g.findNodesThatFit(pod, nodes) if err != nil { return "", err } @@ -146,6 +141,7 @@ func (g *genericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister } } metrics.SchedulingAlgorithmPredicateEvaluationDuration.Observe(metrics.SinceInMicroseconds(startPredicateEvalTime)) + metrics.SchedulingLatency.WithLabelValues(metrics.PredicateEvaluation).Observe(metrics.SinceInSeconds(startPredicateEvalTime)) trace.Step("Prioritizing") startPriorityEvalTime := time.Now() @@ -161,6 +157,7 @@ func (g *genericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister return "", err } metrics.SchedulingAlgorithmPriorityEvaluationDuration.Observe(metrics.SinceInMicroseconds(startPriorityEvalTime)) + metrics.SchedulingLatency.WithLabelValues(metrics.PriorityEvaluation).Observe(metrics.SinceInSeconds(startPriorityEvalTime)) trace.Step("Selecting host") return g.selectHost(priorityList) @@ -234,34 +231,77 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister, if err != nil { return nil, nil, nil, err } - nodeToVictims, err := selectNodesForPreemption(pod, g.cachedNodeInfoMap, potentialNodes, g.predicates, g.predicateMetaProducer, g.schedulingQueue, pdbs) + nodeToVictims, err := selectNodesForPreemption(pod, g.cachedNodeInfoMap, potentialNodes, g.predicates, + g.predicateMetaProducer, g.schedulingQueue, pdbs) if err != nil { return nil, nil, nil, err } - for len(nodeToVictims) > 0 { - node := pickOneNodeForPreemption(nodeToVictims) - if node == nil { - return nil, nil, nil, err - } - passes, pErr := nodePassesExtendersForPreemption(pod, node.Name, nodeToVictims[node].pods, g.cachedNodeInfoMap, g.extenders) - if passes && pErr == nil { - // Lower priority pods nominated to run on this node, may no longer fit on - // this node. So, we should remove their nomination. Removing their - // nomination updates these pods and moves them to the active queue. It - // lets scheduler find another place for them. - nominatedPods := g.getLowerPriorityNominatedPods(pod, node.Name) - return node, nodeToVictims[node].pods, nominatedPods, err - } - if pErr != nil { - glog.Errorf("Error occurred while checking extenders for preemption on node %v: %v", node, pErr) + + // We will only check nodeToVictims with extenders that support preemption. + // Extenders which do not support preemption may later prevent preemptor from being scheduled on the nominated + // node. In that case, scheduler will find a different host for the preemptor in subsequent scheduling cycles. + nodeToVictims, err = g.processPreemptionWithExtenders(pod, nodeToVictims) + if err != nil { + return nil, nil, nil, err + } + + candidateNode := pickOneNodeForPreemption(nodeToVictims) + if candidateNode == nil { + return nil, nil, nil, err + } + + // Lower priority pods nominated to run on this node, may no longer fit on + // this node. So, we should remove their nomination. Removing their + // nomination updates these pods and moves them to the active queue. It + // lets scheduler find another place for them. + nominatedPods := g.getLowerPriorityNominatedPods(pod, candidateNode.Name) + if nodeInfo, ok := g.cachedNodeInfoMap[candidateNode.Name]; ok { + return nodeInfo.Node(), nodeToVictims[candidateNode].Pods, nominatedPods, err + } + + return nil, nil, nil, fmt.Errorf( + "preemption failed: the target node %s has been deleted from scheduler cache", + candidateNode.Name) +} + +// processPreemptionWithExtenders processes preemption with extenders +func (g *genericScheduler) processPreemptionWithExtenders( + pod *v1.Pod, + nodeToVictims map[*v1.Node]*schedulerapi.Victims, +) (map[*v1.Node]*schedulerapi.Victims, error) { + if len(nodeToVictims) > 0 { + for _, extender := range g.extenders { + if extender.SupportsPreemption() { + newNodeToVictims, err := extender.ProcessPreemption( + pod, + nodeToVictims, + g.cachedNodeInfoMap, + ) + if err != nil { + if extender.IsIgnorable() { + glog.Warningf("Skipping extender %v as it returned error %v and has ignorable flag set", + extender, err) + continue + } + return nil, err + } + + // Replace nodeToVictims with new result after preemption. So the + // rest of extenders can continue use it as parameter. + nodeToVictims = newNodeToVictims + + // If node list becomes empty, no preemption can happen regardless of other extenders. + if len(nodeToVictims) == 0 { + break + } + } } - // Remove the node from the map and try to pick a different node. - delete(nodeToVictims, node) } - return nil, nil, nil, err + + return nodeToVictims, nil } -// GetLowerPriorityNominatedPods returns pods whose priority is smaller than the +// getLowerPriorityNominatedPods returns pods whose priority is smaller than the // priority of the given "pod" and are nominated to run on the given node. // Note: We could possibly check if the nominated lower priority pods still fit // and return those that no longer fit, but that would require lots of @@ -270,6 +310,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister, // small number of nominated pods per node. func (g *genericScheduler) getLowerPriorityNominatedPods(pod *v1.Pod, nodeName string) []*v1.Pod { pods := g.schedulingQueue.WaitingPodsForNode(nodeName) + if len(pods) == 0 { return nil } @@ -286,21 +327,11 @@ func (g *genericScheduler) getLowerPriorityNominatedPods(pod *v1.Pod, nodeName s // Filters the nodes to find the ones that fit based on the given predicate functions // Each node is passed through the predicate functions to determine if it is a fit -func findNodesThatFit( - pod *v1.Pod, - nodeNameToInfo map[string]*schedulercache.NodeInfo, - nodes []*v1.Node, - predicateFuncs map[string]algorithm.FitPredicate, - extenders []algorithm.SchedulerExtender, - metadataProducer algorithm.PredicateMetadataProducer, - ecache *EquivalenceCache, - schedulingQueue SchedulingQueue, - alwaysCheckAllPredicates bool, -) ([]*v1.Node, FailedPredicateMap, error) { +func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v1.Node, FailedPredicateMap, error) { var filtered []*v1.Node failedPredicateMap := FailedPredicateMap{} - if len(predicateFuncs) == 0 { + if len(g.predicates) == 0 { filtered = nodes } else { // Create filtered list with enough space to avoid growing it @@ -311,12 +342,12 @@ func findNodesThatFit( var filteredLen int32 // We can use the same metadata producer for all nodes. - meta := metadataProducer(pod, nodeNameToInfo) + meta := g.predicateMetaProducer(pod, g.cachedNodeInfoMap) var equivCacheInfo *equivalenceClassInfo - if ecache != nil { + if g.equivalenceCache != nil { // getEquivalenceClassInfo will return immediately if no equivalence pod found - equivCacheInfo = ecache.getEquivalenceClassInfo(pod) + equivCacheInfo = g.equivalenceCache.getEquivalenceClassInfo(pod) } checkNode := func(i int) { @@ -324,11 +355,12 @@ func findNodesThatFit( fits, failedPredicates, err := podFitsOnNode( pod, meta, - nodeNameToInfo[nodeName], - predicateFuncs, - ecache, - schedulingQueue, - alwaysCheckAllPredicates, + g.cachedNodeInfoMap[nodeName], + g.predicates, + g.cache, + g.equivalenceCache, + g.schedulingQueue, + g.alwaysCheckAllPredicates, equivCacheInfo, ) if err != nil { @@ -352,14 +384,20 @@ func findNodesThatFit( } } - if len(filtered) > 0 && len(extenders) != 0 { - for _, extender := range extenders { + if len(filtered) > 0 && len(g.extenders) != 0 { + for _, extender := range g.extenders { if !extender.IsInterested(pod) { continue } - filteredList, failedMap, err := extender.Filter(pod, filtered, nodeNameToInfo) + filteredList, failedMap, err := extender.Filter(pod, filtered, g.cachedNodeInfoMap) if err != nil { - return []*v1.Node{}, FailedPredicateMap{}, err + if extender.IsIgnorable() { + glog.Warningf("Skipping extender %v as it returned error %v and has ignorable flag set", + extender, err) + continue + } else { + return []*v1.Node{}, FailedPredicateMap{}, err + } } for failedNodeName, failedMsg := range failedMap { @@ -422,6 +460,7 @@ func podFitsOnNode( meta algorithm.PredicateMetadata, info *schedulercache.NodeInfo, predicateFuncs map[string]algorithm.FitPredicate, + cache schedulercache.Cache, ecache *EquivalenceCache, queue SchedulingQueue, alwaysCheckAllPredicates bool, @@ -431,7 +470,6 @@ func podFitsOnNode( eCacheAvailable bool failedPredicates []algorithm.PredicateFailureReason ) - predicateResults := make(map[string]HostPredicate) podsAdded := false // We run predicates twice in some cases. If the node has greater or equal priority @@ -472,45 +510,11 @@ func podFitsOnNode( ) //TODO (yastij) : compute average predicate restrictiveness to export it as Prometheus metric if predicate, exist := predicateFuncs[predicateKey]; exist { - // Use an in-line function to guarantee invocation of ecache.Unlock() - // when the in-line function returns. - func() { - var invalid bool - if eCacheAvailable { - // Lock ecache here to avoid a race condition against cache invalidation invoked - // in event handlers. This race has existed despite locks in equivClassCacheimplementation. - ecache.Lock() - defer ecache.Unlock() - // PredicateWithECache will return its cached predicate results. - fit, reasons, invalid = ecache.PredicateWithECache( - pod.GetName(), info.Node().GetName(), - predicateKey, equivCacheInfo.hash, false) - } - - if !eCacheAvailable || invalid { - // we need to execute predicate functions since equivalence cache does not work - fit, reasons, err = predicate(pod, metaToUse, nodeInfoToUse) - if err != nil { - return - } - - if eCacheAvailable { - // Store data to update equivClassCacheafter this loop. - if res, exists := predicateResults[predicateKey]; exists { - res.Fit = res.Fit && fit - res.FailReasons = append(res.FailReasons, reasons...) - predicateResults[predicateKey] = res - } else { - predicateResults[predicateKey] = HostPredicate{Fit: fit, FailReasons: reasons} - } - result := predicateResults[predicateKey] - ecache.UpdateCachedPredicateItem( - pod.GetName(), info.Node().GetName(), - predicateKey, result.Fit, result.FailReasons, equivCacheInfo.hash, false) - } - } - }() - + if eCacheAvailable { + fit, reasons, err = ecache.RunPredicate(predicate, predicateKey, pod, metaToUse, nodeInfoToUse, equivCacheInfo, cache) + } else { + fit, reasons, err = predicate(pod, metaToUse, nodeInfoToUse) + } if err != nil { return false, []algorithm.PredicateFailureReason{}, err } @@ -697,7 +701,7 @@ func EqualPriorityMap(_ *v1.Pod, _ interface{}, nodeInfo *schedulercache.NodeInf // 5. If there are still ties, the first such node is picked (sort of randomly). // The 'minNodes1' and 'minNodes2' are being reused here to save the memory // allocation and garbage collection time. -func pickOneNodeForPreemption(nodesToVictims map[*v1.Node]*Victims) *v1.Node { +func pickOneNodeForPreemption(nodesToVictims map[*v1.Node]*schedulerapi.Victims) *v1.Node { if len(nodesToVictims) == 0 { return nil } @@ -705,14 +709,14 @@ func pickOneNodeForPreemption(nodesToVictims map[*v1.Node]*Victims) *v1.Node { var minNodes1 []*v1.Node lenNodes1 := 0 for node, victims := range nodesToVictims { - if len(victims.pods) == 0 { + if len(victims.Pods) == 0 { // We found a node that doesn't need any preemption. Return it! // This should happen rarely when one or more pods are terminated between // the time that scheduler tries to schedule the pod and the time that // preemption logic tries to find nodes for preemption. return node } - numPDBViolatingPods := victims.numPDBViolations + numPDBViolatingPods := victims.NumPDBViolations if numPDBViolatingPods < minNumPDBViolatingPods { minNumPDBViolatingPods = numPDBViolatingPods minNodes1 = nil @@ -736,7 +740,7 @@ func pickOneNodeForPreemption(nodesToVictims map[*v1.Node]*Victims) *v1.Node { node := minNodes1[i] victims := nodesToVictims[node] // highestPodPriority is the highest priority among the victims on this node. - highestPodPriority := util.GetPodPriority(victims.pods[0]) + highestPodPriority := util.GetPodPriority(victims.Pods[0]) if highestPodPriority < minHighestPriority { minHighestPriority = highestPodPriority lenNodes2 = 0 @@ -757,7 +761,7 @@ func pickOneNodeForPreemption(nodesToVictims map[*v1.Node]*Victims) *v1.Node { for i := 0; i < lenNodes2; i++ { var sumPriorities int64 node := minNodes2[i] - for _, pod := range nodesToVictims[node].pods { + for _, pod := range nodesToVictims[node].Pods { // We add MaxInt32+1 to all priorities to make all of them >= 0. This is // needed so that a node with a few pods with negative priority is not // picked over a node with a smaller number of pods with the same negative @@ -783,7 +787,7 @@ func pickOneNodeForPreemption(nodesToVictims map[*v1.Node]*Victims) *v1.Node { lenNodes2 = 0 for i := 0; i < lenNodes1; i++ { node := minNodes1[i] - numPods := len(nodesToVictims[node].pods) + numPods := len(nodesToVictims[node].Pods) if numPods < minNumPods { minNumPods = numPods lenNodes2 = 0 @@ -811,9 +815,9 @@ func selectNodesForPreemption(pod *v1.Pod, metadataProducer algorithm.PredicateMetadataProducer, queue SchedulingQueue, pdbs []*policy.PodDisruptionBudget, -) (map[*v1.Node]*Victims, error) { +) (map[*v1.Node]*schedulerapi.Victims, error) { - nodeNameToVictims := map[*v1.Node]*Victims{} + nodeToVictims := map[*v1.Node]*schedulerapi.Victims{} var resultLock sync.Mutex // We can use the same metadata producer for all nodes. @@ -827,50 +831,16 @@ func selectNodesForPreemption(pod *v1.Pod, pods, numPDBViolations, fits := selectVictimsOnNode(pod, metaCopy, nodeNameToInfo[nodeName], predicates, queue, pdbs) if fits { resultLock.Lock() - victims := Victims{ - pods: pods, - numPDBViolations: numPDBViolations, + victims := schedulerapi.Victims{ + Pods: pods, + NumPDBViolations: numPDBViolations, } - nodeNameToVictims[potentialNodes[i]] = &victims + nodeToVictims[potentialNodes[i]] = &victims resultLock.Unlock() } } workqueue.Parallelize(16, len(potentialNodes), checkNode) - return nodeNameToVictims, nil -} - -func nodePassesExtendersForPreemption( - pod *v1.Pod, - nodeName string, - victims []*v1.Pod, - nodeNameToInfo map[string]*schedulercache.NodeInfo, - extenders []algorithm.SchedulerExtender) (bool, error) { - // If there are any extenders, run them and filter the list of candidate nodes. - if len(extenders) == 0 { - return true, nil - } - // Remove the victims from the corresponding nodeInfo and send nodes to the - // extenders for filtering. - originalNodeInfo := nodeNameToInfo[nodeName] - nodeInfoCopy := nodeNameToInfo[nodeName].Clone() - for _, victim := range victims { - nodeInfoCopy.RemovePod(victim) - } - nodeNameToInfo[nodeName] = nodeInfoCopy - defer func() { nodeNameToInfo[nodeName] = originalNodeInfo }() - filteredNodes := []*v1.Node{nodeInfoCopy.Node()} - for _, extender := range extenders { - var err error - var failedNodesMap map[string]string - filteredNodes, failedNodesMap, err = extender.Filter(pod, filteredNodes, nodeNameToInfo) - if err != nil { - return false, err - } - if _, found := failedNodesMap[nodeName]; found || len(filteredNodes) == 0 { - return false, nil - } - } - return true, nil + return nodeToVictims, nil } // filterPodsWithPDBViolation groups the given "pods" into two groups of "violatingPods" @@ -965,7 +935,7 @@ func selectVictimsOnNode( // that we should check is if the "pod" is failing to schedule due to pod affinity // failure. // TODO(bsalamat): Consider checking affinity to lower priority pods if feasible with reasonable performance. - if fits, _, err := podFitsOnNode(pod, meta, nodeInfoCopy, fitPredicates, nil, queue, false, nil); !fits { + if fits, _, err := podFitsOnNode(pod, meta, nodeInfoCopy, fitPredicates, nil, nil, queue, false, nil); !fits { if err != nil { glog.Warningf("Encountered error while selecting victims on node %v: %v", nodeInfo.Node().Name, err) } @@ -979,7 +949,7 @@ func selectVictimsOnNode( violatingVictims, nonViolatingVictims := filterPodsWithPDBViolation(potentialVictims.Items, pdbs) reprievePod := func(p *v1.Pod) bool { addPod(p) - fits, _, _ := podFitsOnNode(pod, meta, nodeInfoCopy, fitPredicates, nil, queue, false, nil) + fits, _, _ := podFitsOnNode(pod, meta, nodeInfoCopy, fitPredicates, nil, nil, queue, false, nil) if !fits { removePod(p) victims = append(victims, p) @@ -1010,6 +980,7 @@ func nodesWherePreemptionMightHelp(pod *v1.Pod, nodes []*v1.Node, failedPredicat // (which is the case today), the !found case should never happen, but we'd prefer // to rely less on such assumptions in the code when checking does not impose // significant overhead. + // Also, we currently assume all failures returned by extender as resolvable. for _, failedPredicate := range failedPredicates { switch failedPredicate { case @@ -1096,7 +1067,9 @@ func NewGenericScheduler( extenders []algorithm.SchedulerExtender, volumeBinder *volumebinder.VolumeBinder, pvcLister corelisters.PersistentVolumeClaimLister, - alwaysCheckAllPredicates bool) algorithm.ScheduleAlgorithm { + alwaysCheckAllPredicates bool, + disablePreemption bool, +) algorithm.ScheduleAlgorithm { return &genericScheduler{ cache: cache, equivalenceCache: eCache, @@ -1110,5 +1083,6 @@ func NewGenericScheduler( volumeBinder: volumeBinder, pvcLister: pvcLister, alwaysCheckAllPredicates: alwaysCheckAllPredicates, + disablePreemption: disablePreemption, } } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler_test.go index 4250b0b09..aa7a16745 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler_test.go @@ -38,7 +38,7 @@ import ( algorithmpriorities "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -404,13 +404,23 @@ func TestGenericScheduler(t *testing.T) { cache.AddNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: name}}) } pvcs := []*v1.PersistentVolumeClaim{} - for _, pvc := range test.pvcs { - pvcs = append(pvcs, pvc) - } + pvcs = append(pvcs, test.pvcs...) + pvcLister := schedulertesting.FakePersistentVolumeClaimLister(pvcs) scheduler := NewGenericScheduler( - cache, nil, NewSchedulingQueue(), test.predicates, algorithm.EmptyPredicateMetadataProducer, test.prioritizers, algorithm.EmptyPriorityMetadataProducer, []algorithm.SchedulerExtender{}, nil, pvcLister, test.alwaysCheckAllPredicates) + cache, + nil, + NewSchedulingQueue(), + test.predicates, + algorithm.EmptyPredicateMetadataProducer, + test.prioritizers, + algorithm.EmptyPriorityMetadataProducer, + []algorithm.SchedulerExtender{}, + nil, + pvcLister, + test.alwaysCheckAllPredicates, + false) machine, err := scheduler.Schedule(test.pod, schedulertesting.FakeNodeLister(makeNodeList(test.nodes))) if !reflect.DeepEqual(err, test.wErr) { @@ -422,16 +432,35 @@ func TestGenericScheduler(t *testing.T) { } } -func TestFindFitAllError(t *testing.T) { +// makeScheduler makes a simple genericScheduler for testing. +func makeScheduler(predicates map[string]algorithm.FitPredicate, nodes []*v1.Node) *genericScheduler { algorithmpredicates.SetPredicatesOrdering(order) - nodes := []string{"3", "2", "1"} - predicates := map[string]algorithm.FitPredicate{"true": truePredicate, "false": falsePredicate} - nodeNameToInfo := map[string]*schedulercache.NodeInfo{ - "3": schedulercache.NewNodeInfo(), - "2": schedulercache.NewNodeInfo(), - "1": schedulercache.NewNodeInfo(), + cache := schedulercache.New(time.Duration(0), wait.NeverStop) + for _, n := range nodes { + cache.AddNode(n) } - _, predicateMap, err := findNodesThatFit(&v1.Pod{}, nodeNameToInfo, makeNodeList(nodes), predicates, nil, algorithm.EmptyPredicateMetadataProducer, nil, nil, false) + prioritizers := []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}} + + s := NewGenericScheduler( + cache, + nil, + NewSchedulingQueue(), + predicates, + algorithm.EmptyPredicateMetadataProducer, + prioritizers, + algorithm.EmptyPriorityMetadataProducer, + nil, nil, nil, false, false) + cache.UpdateNodeNameToInfoMap(s.(*genericScheduler).cachedNodeInfoMap) + return s.(*genericScheduler) + +} + +func TestFindFitAllError(t *testing.T) { + predicates := map[string]algorithm.FitPredicate{"true": truePredicate, "matches": matchesPredicate} + nodes := makeNodeList([]string{"3", "2", "1"}) + scheduler := makeScheduler(predicates, nodes) + + _, predicateMap, err := scheduler.findNodesThatFit(&v1.Pod{}, nodes) if err != nil { t.Errorf("unexpected error: %v", err) @@ -442,9 +471,9 @@ func TestFindFitAllError(t *testing.T) { } for _, node := range nodes { - failures, found := predicateMap[node] + failures, found := predicateMap[node.Name] if !found { - t.Errorf("failed to find node: %s in %v", node, predicateMap) + t.Errorf("failed to find node: %s in %v", node.Name, predicateMap) } if len(failures) != 1 || failures[0] != algorithmpredicates.ErrFakePredicate { t.Errorf("unexpected failures: %v", failures) @@ -453,20 +482,13 @@ func TestFindFitAllError(t *testing.T) { } func TestFindFitSomeError(t *testing.T) { - algorithmpredicates.SetPredicatesOrdering(order) - nodes := []string{"3", "2", "1"} predicates := map[string]algorithm.FitPredicate{"true": truePredicate, "matches": matchesPredicate} + nodes := makeNodeList([]string{"3", "2", "1"}) + scheduler := makeScheduler(predicates, nodes) + pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "1", UID: types.UID("1")}} - nodeNameToInfo := map[string]*schedulercache.NodeInfo{ - "3": schedulercache.NewNodeInfo(), - "2": schedulercache.NewNodeInfo(), - "1": schedulercache.NewNodeInfo(pod), - } - for name := range nodeNameToInfo { - nodeNameToInfo[name].SetNode(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: name}}) - } + _, predicateMap, err := scheduler.findNodesThatFit(pod, nodes) - _, predicateMap, err := findNodesThatFit(pod, nodeNameToInfo, makeNodeList(nodes), predicates, nil, algorithm.EmptyPredicateMetadataProducer, nil, nil, false) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -476,12 +498,12 @@ func TestFindFitSomeError(t *testing.T) { } for _, node := range nodes { - if node == pod.Name { + if node.Name == pod.Name { continue } - failures, found := predicateMap[node] + failures, found := predicateMap[node.Name] if !found { - t.Errorf("failed to find node: %s in %v", node, predicateMap) + t.Errorf("failed to find node: %s in %v", node.Name, predicateMap) } if len(failures) != 1 || failures[0] != algorithmpredicates.ErrFakePredicate { t.Errorf("unexpected failures: %v", failures) @@ -661,11 +683,11 @@ func TestZeroRequest(t *testing.T) { } } -func printNodeToVictims(nodeToVictims map[*v1.Node]*Victims) string { +func printNodeToVictims(nodeToVictims map[*v1.Node]*schedulerapi.Victims) string { var output string for node, victims := range nodeToVictims { output += node.Name + ": [" - for _, pod := range victims.pods { + for _, pod := range victims.Pods { output += pod.Name + ", " } output += "]" @@ -673,15 +695,15 @@ func printNodeToVictims(nodeToVictims map[*v1.Node]*Victims) string { return output } -func checkPreemptionVictims(testName string, expected map[string]map[string]bool, nodeToPods map[*v1.Node]*Victims) error { +func checkPreemptionVictims(testName string, expected map[string]map[string]bool, nodeToPods map[*v1.Node]*schedulerapi.Victims) error { if len(expected) == len(nodeToPods) { for k, victims := range nodeToPods { if expPods, ok := expected[k.Name]; ok { - if len(victims.pods) != len(expPods) { + if len(victims.Pods) != len(expPods) { return fmt.Errorf("test [%v]: unexpected number of pods. expected: %v, got: %v", testName, expected, printNodeToVictims(nodeToPods)) } prevPriority := int32(math.MaxInt32) - for _, p := range victims.pods { + for _, p := range victims.Pods { // Check that pods are sorted by their priority. if *p.Spec.Priority > prevPriority { return fmt.Errorf("test [%v]: pod %v of node %v was not sorted by priority", testName, p.Name, k) @@ -884,7 +906,7 @@ func TestSelectNodesForPreemption(t *testing.T) { for _, test := range tests { nodes := []*v1.Node{} for _, n := range test.nodes { - node := makeNode(n, priorityutil.DefaultMilliCPURequest*5, priorityutil.DefaultMemoryRequest*5) + node := makeNode(n, 1000*5, priorityutil.DefaultMemoryRequest*5) node.ObjectMeta.Labels = map[string]string{"hostname": node.Name} nodes = append(nodes, node) } @@ -1275,6 +1297,30 @@ func TestPreempt(t *testing.T) { expectedNode: "", expectedPods: []string{}, }, + { + name: "One scheduler extender allows only machine1, the other returns error but ignorable. Only machine1 would be chosen", + pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", UID: types.UID("pod1")}, Spec: v1.PodSpec{ + Containers: veryLargeContainers, + Priority: &highPriority}, + }, + pods: []*v1.Pod{ + {ObjectMeta: metav1.ObjectMeta{Name: "m1.1", UID: types.UID("m1.1")}, Spec: v1.PodSpec{Containers: smallContainers, Priority: &midPriority, NodeName: "machine1"}, Status: v1.PodStatus{Phase: v1.PodRunning}}, + {ObjectMeta: metav1.ObjectMeta{Name: "m1.2", UID: types.UID("m1.2")}, Spec: v1.PodSpec{Containers: smallContainers, Priority: &lowPriority, NodeName: "machine1"}, Status: v1.PodStatus{Phase: v1.PodRunning}}, + + {ObjectMeta: metav1.ObjectMeta{Name: "m2.1", UID: types.UID("m2.1")}, Spec: v1.PodSpec{Containers: largeContainers, Priority: &midPriority, NodeName: "machine2"}, Status: v1.PodStatus{Phase: v1.PodRunning}}, + }, + extenders: []*FakeExtender{ + { + predicates: []fitPredicate{errorPredicateExtender}, + ignorable: true, + }, + { + predicates: []fitPredicate{machine1PredicateExtender}, + }, + }, + expectedNode: "machine1", + expectedPods: []string{"m1.1", "m1.2"}, + }, } for _, test := range tests { @@ -1283,15 +1329,35 @@ func TestPreempt(t *testing.T) { for _, pod := range test.pods { cache.AddPod(pod) } + cachedNodeInfoMap := map[string]*schedulercache.NodeInfo{} for _, name := range nodeNames { - cache.AddNode(makeNode(name, priorityutil.DefaultMilliCPURequest*5, priorityutil.DefaultMemoryRequest*5)) + node := makeNode(name, 1000*5, priorityutil.DefaultMemoryRequest*5) + cache.AddNode(node) + + // Set nodeInfo to extenders to mock extenders' cache for preemption. + cachedNodeInfo := schedulercache.NewNodeInfo() + cachedNodeInfo.SetNode(node) + cachedNodeInfoMap[name] = cachedNodeInfo } extenders := []algorithm.SchedulerExtender{} for _, extender := range test.extenders { + // Set nodeInfoMap as extenders cached node information. + extender.cachedNodeNameToInfo = cachedNodeInfoMap extenders = append(extenders, extender) } scheduler := NewGenericScheduler( - cache, nil, NewSchedulingQueue(), map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, algorithm.EmptyPredicateMetadataProducer, []algorithm.PriorityConfig{{Function: numericPriority, Weight: 1}}, algorithm.EmptyPriorityMetadataProducer, extenders, nil, schedulertesting.FakePersistentVolumeClaimLister{}, false) + cache, + nil, + NewSchedulingQueue(), + map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + algorithm.EmptyPredicateMetadataProducer, + []algorithm.PriorityConfig{{Function: numericPriority, Weight: 1}}, + algorithm.EmptyPriorityMetadataProducer, + extenders, + nil, + schedulertesting.FakePersistentVolumeClaimLister{}, + false, + false) // Call Preempt and check the expected results. node, victims, _, err := scheduler.Preempt(test.pod, schedulertesting.FakeNodeLister(makeNodeList(nodeNames)), error(&FitError{Pod: test.pod, FailedPredicates: failedPredMap})) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/core/scheduling_queue.go b/vendor/k8s.io/kubernetes/pkg/scheduler/core/scheduling_queue.go index 914541665..2b789f338 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/core/scheduling_queue.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/core/scheduling_queue.go @@ -29,8 +29,11 @@ package core import ( "container/heap" "fmt" + "reflect" "sync" + "github.com/golang/glog" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/cache" @@ -38,9 +41,6 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" "k8s.io/kubernetes/pkg/scheduler/util" - - "github.com/golang/glog" - "reflect" ) // SchedulingQueue is an interface for a queue to store pods waiting to be scheduled. @@ -57,6 +57,7 @@ type SchedulingQueue interface { AssignedPodAdded(pod *v1.Pod) AssignedPodUpdated(pod *v1.Pod) WaitingPodsForNode(nodeName string) []*v1.Pod + WaitingPods() []*v1.Pod } // NewSchedulingQueue initializes a new scheduling queue. If pod priority is @@ -116,6 +117,15 @@ func (f *FIFO) Pop() (*v1.Pod, error) { return result.(*v1.Pod), nil } +// WaitingPods returns all the waiting pods in the queue. +func (f *FIFO) WaitingPods() []*v1.Pod { + result := []*v1.Pod{} + for _, pod := range f.FIFO.List() { + result = append(result, pod.(*v1.Pod)) + } + return result +} + // FIFO does not need to react to events, as all pods are always in the active // scheduling queue anyway. @@ -460,6 +470,21 @@ func (p *PriorityQueue) WaitingPodsForNode(nodeName string) []*v1.Pod { return nil } +// WaitingPods returns all the waiting pods in the queue. +func (p *PriorityQueue) WaitingPods() []*v1.Pod { + p.lock.Lock() + defer p.lock.Unlock() + + result := []*v1.Pod{} + for _, pod := range p.activeQ.List() { + result = append(result, pod.(*v1.Pod)) + } + for _, pod := range p.unschedulableQ.pods { + result = append(result, pod) + } + return result +} + // UnschedulablePodsMap holds pods that cannot be scheduled. This data structure // is used to implement unschedulableQ. type UnschedulablePodsMap struct { diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/BUILD index a4c87066f..faf552687 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/BUILD @@ -9,14 +9,49 @@ load( go_library( name = "go_default_library", srcs = [ + "cache_comparer.go", "factory.go", "plugins.go", - ], + ] + select({ + "@io_bazel_rules_go//go/platform:android": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:nacl": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "signal.go", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "signal_windows.go", + ], + "//conditions:default": [], + }), importpath = "k8s.io/kubernetes/pkg/scheduler/factory", deps = [ "//pkg/api/v1/pod:go_default_library", "//pkg/apis/core/helper:go_default_library", - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler:go_default_library", @@ -25,8 +60,8 @@ go_library( "//pkg/scheduler/algorithm/priorities:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/api/validation:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/core:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -59,24 +94,29 @@ go_library( go_test( name = "go_default_test", srcs = [ + "cache_comparer_test.go", "factory_test.go", "plugins_test.go", ], embed = [":go_default_library"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/scheduler:go_default_library", "//pkg/scheduler/algorithm:go_default_library", + "//pkg/scheduler/algorithm/priorities:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/api/latest:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/core:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//pkg/scheduler/testing:go_default_library", "//pkg/scheduler/util: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/policy/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/cache_comparer.go b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/cache_comparer.go new file mode 100644 index 000000000..fadd7be2c --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/cache_comparer.go @@ -0,0 +1,161 @@ +/* +Copyright 2018 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 factory + +import ( + "sort" + "strings" + + "github.com/golang/glog" + "k8s.io/api/core/v1" + policy "k8s.io/api/policy/v1beta1" + "k8s.io/apimachinery/pkg/labels" + corelisters "k8s.io/client-go/listers/core/v1" + v1beta1 "k8s.io/client-go/listers/policy/v1beta1" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + "k8s.io/kubernetes/pkg/scheduler/core" +) + +type cacheComparer struct { + nodeLister corelisters.NodeLister + podLister corelisters.PodLister + pdbLister v1beta1.PodDisruptionBudgetLister + cache schedulercache.Cache + podQueue core.SchedulingQueue + + compareStrategy +} + +func (c *cacheComparer) Compare() error { + glog.V(3).Info("cache comparer started") + defer glog.V(3).Info("cache comparer finished") + + nodes, err := c.nodeLister.List(labels.Everything()) + if err != nil { + return err + } + + pods, err := c.podLister.List(labels.Everything()) + if err != nil { + return err + } + + pdbs, err := c.pdbLister.List(labels.Everything()) + if err != nil { + return err + } + + snapshot := c.cache.Snapshot() + + waitingPods := c.podQueue.WaitingPods() + + if missed, redundant := c.CompareNodes(nodes, snapshot.Nodes); len(missed)+len(redundant) != 0 { + glog.Warningf("cache mismatch: missed nodes: %s; redundant nodes: %s", missed, redundant) + } + + if missed, redundant := c.ComparePods(pods, waitingPods, snapshot.Nodes); len(missed)+len(redundant) != 0 { + glog.Warningf("cache mismatch: missed pods: %s; redundant pods: %s", missed, redundant) + } + + if missed, redundant := c.ComparePdbs(pdbs, snapshot.Pdbs); len(missed)+len(redundant) != 0 { + glog.Warningf("cache mismatch: missed pdbs: %s; redundant pdbs: %s", missed, redundant) + } + + return nil +} + +type compareStrategy struct { +} + +func (c compareStrategy) CompareNodes(nodes []*v1.Node, nodeinfos map[string]*schedulercache.NodeInfo) (missed, redundant []string) { + actual := []string{} + for _, node := range nodes { + actual = append(actual, node.Name) + } + + cached := []string{} + for nodeName := range nodeinfos { + cached = append(cached, nodeName) + } + + return compareStrings(actual, cached) +} + +func (c compareStrategy) ComparePods(pods, waitingPods []*v1.Pod, nodeinfos map[string]*schedulercache.NodeInfo) (missed, redundant []string) { + actual := []string{} + for _, pod := range pods { + actual = append(actual, string(pod.UID)) + } + + cached := []string{} + for _, nodeinfo := range nodeinfos { + for _, pod := range nodeinfo.Pods() { + cached = append(cached, string(pod.UID)) + } + } + for _, pod := range waitingPods { + cached = append(cached, string(pod.UID)) + } + + return compareStrings(actual, cached) +} + +func (c compareStrategy) ComparePdbs(pdbs []*policy.PodDisruptionBudget, pdbCache map[string]*policy.PodDisruptionBudget) (missed, redundant []string) { + actual := []string{} + for _, pdb := range pdbs { + actual = append(actual, string(pdb.UID)) + } + + cached := []string{} + for pdbUID := range pdbCache { + cached = append(cached, pdbUID) + } + + return compareStrings(actual, cached) +} + +func compareStrings(actual, cached []string) (missed, redundant []string) { + missed, redundant = []string{}, []string{} + + sort.Strings(actual) + sort.Strings(cached) + + compare := func(i, j int) int { + if i == len(actual) { + return 1 + } else if j == len(cached) { + return -1 + } + return strings.Compare(actual[i], cached[j]) + } + + for i, j := 0, 0; i < len(actual) || j < len(cached); { + switch compare(i, j) { + case 0: + i++ + j++ + case -1: + missed = append(missed, actual[i]) + i++ + case 1: + redundant = append(redundant, cached[j]) + j++ + } + } + + return +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/cache_comparer_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/cache_comparer_test.go new file mode 100644 index 000000000..174133099 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/cache_comparer_test.go @@ -0,0 +1,228 @@ +/* +Copyright 2018 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 factory + +import ( + "reflect" + "testing" + + "k8s.io/api/core/v1" + policy "k8s.io/api/policy/v1beta1" + "k8s.io/apimachinery/pkg/types" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" +) + +func TestCompareNodes(t *testing.T) { + compare := compareStrategy{} + + tests := []struct { + actual []string + cached []string + missing []string + redundant []string + }{ + { + actual: []string{"foo", "bar"}, + cached: []string{"bar", "foo", "foobar"}, + missing: []string{}, + redundant: []string{"foobar"}, + }, + { + actual: []string{"foo", "bar", "foobar"}, + cached: []string{"bar", "foo"}, + missing: []string{"foobar"}, + redundant: []string{}, + }, + { + actual: []string{"foo", "bar", "foobar"}, + cached: []string{"bar", "foobar", "foo"}, + missing: []string{}, + redundant: []string{}, + }, + } + + for _, test := range tests { + nodes := []*v1.Node{} + for _, nodeName := range test.actual { + node := &v1.Node{} + node.Name = nodeName + nodes = append(nodes, node) + } + + nodeInfo := make(map[string]*schedulercache.NodeInfo) + for _, nodeName := range test.cached { + nodeInfo[nodeName] = &schedulercache.NodeInfo{} + } + + m, r := compare.CompareNodes(nodes, nodeInfo) + + if !reflect.DeepEqual(m, test.missing) { + t.Errorf("missing expected to be %s; got %s", test.missing, m) + } + + if !reflect.DeepEqual(r, test.redundant) { + t.Errorf("redundant expected to be %s; got %s", test.redundant, r) + } + } +} + +func TestComparePods(t *testing.T) { + compare := compareStrategy{} + + tests := []struct { + actual []string + cached []string + queued []string + missing []string + redundant []string + }{ + { + actual: []string{"foo", "bar"}, + cached: []string{"bar", "foo", "foobar"}, + queued: []string{}, + missing: []string{}, + redundant: []string{"foobar"}, + }, + { + actual: []string{"foo", "bar"}, + cached: []string{"foo", "foobar"}, + queued: []string{"bar"}, + missing: []string{}, + redundant: []string{"foobar"}, + }, + { + actual: []string{"foo", "bar", "foobar"}, + cached: []string{"bar", "foo"}, + queued: []string{}, + missing: []string{"foobar"}, + redundant: []string{}, + }, + { + actual: []string{"foo", "bar", "foobar"}, + cached: []string{"foo"}, + queued: []string{"bar"}, + missing: []string{"foobar"}, + redundant: []string{}, + }, + { + actual: []string{"foo", "bar", "foobar"}, + cached: []string{"bar", "foobar", "foo"}, + queued: []string{}, + missing: []string{}, + redundant: []string{}, + }, + { + actual: []string{"foo", "bar", "foobar"}, + cached: []string{"foobar", "foo"}, + queued: []string{"bar"}, + missing: []string{}, + redundant: []string{}, + }, + } + + for _, test := range tests { + pods := []*v1.Pod{} + for _, uid := range test.actual { + pod := &v1.Pod{} + pod.UID = types.UID(uid) + pods = append(pods, pod) + } + + queuedPods := []*v1.Pod{} + for _, uid := range test.queued { + pod := &v1.Pod{} + pod.UID = types.UID(uid) + queuedPods = append(queuedPods, pod) + } + + nodeInfo := make(map[string]*schedulercache.NodeInfo) + for _, uid := range test.cached { + pod := &v1.Pod{} + pod.UID = types.UID(uid) + pod.Namespace = "ns" + pod.Name = uid + + nodeInfo[uid] = schedulercache.NewNodeInfo(pod) + } + + m, r := compare.ComparePods(pods, queuedPods, nodeInfo) + + if !reflect.DeepEqual(m, test.missing) { + t.Errorf("missing expected to be %s; got %s", test.missing, m) + } + + if !reflect.DeepEqual(r, test.redundant) { + t.Errorf("redundant expected to be %s; got %s", test.redundant, r) + } + } +} + +func TestComparePdbs(t *testing.T) { + compare := compareStrategy{} + + tests := []struct { + actual []string + cached []string + missing []string + redundant []string + }{ + { + actual: []string{"foo", "bar"}, + cached: []string{"bar", "foo", "foobar"}, + missing: []string{}, + redundant: []string{"foobar"}, + }, + { + actual: []string{"foo", "bar", "foobar"}, + cached: []string{"bar", "foo"}, + missing: []string{"foobar"}, + redundant: []string{}, + }, + { + actual: []string{"foo", "bar", "foobar"}, + cached: []string{"bar", "foobar", "foo"}, + missing: []string{}, + redundant: []string{}, + }, + } + + for _, test := range tests { + pdbs := []*policy.PodDisruptionBudget{} + for _, uid := range test.actual { + pdb := &policy.PodDisruptionBudget{} + pdb.UID = types.UID(uid) + pdbs = append(pdbs, pdb) + } + + cache := make(map[string]*policy.PodDisruptionBudget) + for _, uid := range test.cached { + pdb := &policy.PodDisruptionBudget{} + pdb.UID = types.UID(uid) + cache[uid] = pdb + } + + m, r := compare.ComparePdbs(pdbs, cache) + + if !reflect.DeepEqual(m, test.missing) { + t.Errorf("missing expected to be %s; got %s", test.missing, m) + } + + if !reflect.DeepEqual(r, test.redundant) { + t.Errorf("redundant expected to be %s; got %s", test.redundant, r) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/factory.go b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/factory.go index 60e8f84f8..06a1b24bd 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/factory.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/factory.go @@ -20,6 +20,8 @@ package factory import ( "fmt" + "os" + "os/signal" "reflect" "time" @@ -50,7 +52,6 @@ import ( "k8s.io/client-go/tools/cache" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/apis/core/helper" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/features" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/scheduler" @@ -58,8 +59,8 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" "k8s.io/kubernetes/pkg/scheduler/api/validation" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/core" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" ) @@ -113,7 +114,7 @@ type configFactory struct { schedulerCache schedulercache.Cache // SchedulerName of a scheduler is used to select which pods will be - // processed by this scheduler, based on pods's "spec.SchedulerName". + // processed by this scheduler, based on pods's "spec.schedulerName". schedulerName string // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule @@ -132,6 +133,9 @@ type configFactory struct { // always check all predicates even if the middle of one predicate fails. alwaysCheckAllPredicates bool + + // Disable pod preemption or not. + disablePreemption bool } // NewConfigFactory initializes the default implementation of a Configurator To encourage eventual privatization of the struct type, we only @@ -151,6 +155,7 @@ func NewConfigFactory( storageClassInformer storageinformers.StorageClassInformer, hardPodAffinitySymmetricWeight int32, enableEquivalenceClassCache bool, + disablePreemption bool, ) scheduler.Configurator { stopEverything := make(chan struct{}) schedulerCache := schedulercache.New(30*time.Second, stopEverything) @@ -178,6 +183,7 @@ func NewConfigFactory( schedulerName: schedulerName, hardPodAffinitySymmetricWeight: hardPodAffinitySymmetricWeight, enableEquivalenceClassCache: enableEquivalenceClassCache, + disablePreemption: disablePreemption, } c.scheduledPodsHasSynced = podInformer.Informer().HasSynced @@ -212,10 +218,10 @@ func NewConfigFactory( FilterFunc: func(obj interface{}) bool { switch t := obj.(type) { case *v1.Pod: - return unassignedNonTerminatedPod(t) + return unassignedNonTerminatedPod(t) && responsibleForPod(t, schedulerName) case cache.DeletedFinalStateUnknown: if pod, ok := t.Obj.(*v1.Pod); ok { - return unassignedNonTerminatedPod(pod) + return unassignedNonTerminatedPod(pod) && responsibleForPod(pod, schedulerName) } runtime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, c)) return false @@ -295,6 +301,29 @@ func NewConfigFactory( c.volumeBinder = volumebinder.NewVolumeBinder(client, pvcInformer, pvInformer, storageClassInformer) } + // Setup cache comparer + comparer := &cacheComparer{ + podLister: podInformer.Lister(), + nodeLister: nodeInformer.Lister(), + pdbLister: pdbInformer.Lister(), + cache: c.schedulerCache, + podQueue: c.podQueue, + } + + ch := make(chan os.Signal, 1) + signal.Notify(ch, compareSignal) + + go func() { + for { + select { + case <-c.StopEverything: + return + case <-ch: + comparer.Compare() + } + } + }() + return c } @@ -381,23 +410,6 @@ func (c *configFactory) invalidatePredicatesForPvUpdate(oldPV, newPV *v1.Persist break } } - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - oldAffinity, err := v1helper.GetStorageNodeAffinityFromAnnotation(oldPV.Annotations) - if err != nil { - glog.Errorf("cannot get node affinity fo *v1.PersistentVolume: %v", oldPV) - return - } - newAffinity, err := v1helper.GetStorageNodeAffinityFromAnnotation(newPV.Annotations) - if err != nil { - glog.Errorf("cannot get node affinity fo *v1.PersistentVolume: %v", newPV) - return - } - - // If node affinity of PV is changed. - if !reflect.DeepEqual(oldAffinity, newAffinity) { - invalidPredicates.Insert(predicates.CheckVolumeBindingPred) - } - } c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(invalidPredicates) } @@ -622,6 +634,9 @@ func (c *configFactory) updatePodInCache(oldObj, newObj interface{}) { return } + // NOTE: Because the scheduler uses snapshots of schedulerCache and the live + // version of equivalencePodCache, updates must be written to schedulerCache + // before invalidating equivalencePodCache. if err := c.schedulerCache.UpdatePod(oldPod, newPod); err != nil { glog.Errorf("scheduler cache UpdatePod failed: %v", err) } @@ -708,6 +723,9 @@ func (c *configFactory) deletePodFromCache(obj interface{}) { glog.Errorf("cannot convert to *v1.Pod: %v", t) return } + // NOTE: Because the scheduler uses snapshots of schedulerCache and the live + // version of equivalencePodCache, updates must be written to schedulerCache + // before invalidating equivalencePodCache. if err := c.schedulerCache.RemovePod(pod); err != nil { glog.Errorf("scheduler cache RemovePod failed: %v", err) } @@ -764,6 +782,9 @@ func (c *configFactory) updateNodeInCache(oldObj, newObj interface{}) { return } + // NOTE: Because the scheduler uses snapshots of schedulerCache and the live + // version of equivalencePodCache, updates must be written to schedulerCache + // before invalidating equivalencePodCache. if err := c.schedulerCache.UpdateNode(oldNode, newNode); err != nil { glog.Errorf("scheduler cache UpdateNode failed: %v", err) } @@ -825,6 +846,9 @@ func (c *configFactory) invalidateCachedPredicatesOnNodeUpdate(newNode *v1.Node, if oldConditions[v1.NodeDiskPressure] != newConditions[v1.NodeDiskPressure] { invalidPredicates.Insert(predicates.CheckNodeDiskPressurePred) } + if oldConditions[v1.NodePIDPressure] != newConditions[v1.NodePIDPressure] { + invalidPredicates.Insert(predicates.CheckNodePIDPressurePred) + } if oldConditions[v1.NodeReady] != newConditions[v1.NodeReady] || oldConditions[v1.NodeOutOfDisk] != newConditions[v1.NodeOutOfDisk] || oldConditions[v1.NodeNetworkUnavailable] != newConditions[v1.NodeNetworkUnavailable] { @@ -854,6 +878,9 @@ func (c *configFactory) deleteNodeFromCache(obj interface{}) { glog.Errorf("cannot convert to *v1.Node: %v", t) return } + // NOTE: Because the scheduler uses snapshots of schedulerCache and the live + // version of equivalencePodCache, updates must be written to schedulerCache + // before invalidating equivalencePodCache. if err := c.schedulerCache.RemoveNode(node); err != nil { glog.Errorf("scheduler cache RemoveNode failed: %v", err) } @@ -1046,18 +1073,25 @@ func (c *configFactory) CreateFromKeys(predicateKeys, priorityKeys sets.String, } // Init equivalence class cache - if c.enableEquivalenceClassCache && getEquivalencePodFuncFactory != nil { - pluginArgs, err := c.getPluginArgs() - if err != nil { - return nil, err - } - c.equivalencePodCache = core.NewEquivalenceCache( - getEquivalencePodFuncFactory(*pluginArgs), - ) + if c.enableEquivalenceClassCache { + c.equivalencePodCache = core.NewEquivalenceCache() glog.Info("Created equivalence class cache") } - algo := core.NewGenericScheduler(c.schedulerCache, c.equivalencePodCache, c.podQueue, predicateFuncs, predicateMetaProducer, priorityConfigs, priorityMetaProducer, extenders, c.volumeBinder, c.pVCLister, c.alwaysCheckAllPredicates) + algo := core.NewGenericScheduler( + c.schedulerCache, + c.equivalencePodCache, + c.podQueue, + predicateFuncs, + predicateMetaProducer, + priorityConfigs, + priorityMetaProducer, + extenders, + c.volumeBinder, + c.pVCLister, + c.alwaysCheckAllPredicates, + c.disablePreemption, + ) podBackoff := util.CreateDefaultPodBackoff() return &scheduler.Config{ @@ -1173,6 +1207,11 @@ func assignedNonTerminatedPod(pod *v1.Pod) bool { return true } +// responsibleForPod returns true if the pod has asked to be scheduled by the given scheduler. +func responsibleForPod(pod *v1.Pod, schedulerName string) bool { + return schedulerName == pod.Spec.SchedulerName +} + // assignedPodLister filters the pods returned from a PodLister to // only include those that have a node name set. type assignedPodLister struct { @@ -1245,10 +1284,9 @@ func (i *podInformer) Lister() corelisters.PodLister { } // NewPodInformer creates a shared index informer that returns only non-terminal pods. -func NewPodInformer(client clientset.Interface, resyncPeriod time.Duration, schedulerName string) coreinformers.PodInformer { +func NewPodInformer(client clientset.Interface, resyncPeriod time.Duration) coreinformers.PodInformer { selector := fields.ParseSelectorOrDie( - "spec.schedulerName=" + schedulerName + - ",status.phase!=" + string(v1.PodSucceeded) + + "status.phase!=" + string(v1.PodSucceeded) + ",status.phase!=" + string(v1.PodFailed)) lw := cache.NewListWatchFromClient(client.CoreV1().RESTClient(), string(v1.ResourcePods), metav1.NamespaceAll, selector) return &podInformer{ @@ -1271,6 +1309,9 @@ func (c *configFactory) MakeDefaultErrorFunc(backoff *util.PodBackoff, podQueue _, err := c.client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) if err != nil && errors.IsNotFound(err) { node := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: nodeName}} + // NOTE: Because the scheduler uses snapshots of schedulerCache and the live + // version of equivalencePodCache, updates must be written to schedulerCache + // before invalidating equivalencePodCache. c.schedulerCache.RemoveNode(&node) // invalidate cached predicate for the node if c.enableEquivalenceClassCache { diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/factory_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/factory_test.go index 1ddce5808..36ecf26ec 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/factory_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/factory_test.go @@ -28,25 +28,28 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" utiltesting "k8s.io/client-go/util/testing" - "k8s.io/kubernetes/pkg/api/legacyscheme" apitesting "k8s.io/kubernetes/pkg/api/testing" "k8s.io/kubernetes/pkg/scheduler" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/core" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" "k8s.io/kubernetes/pkg/scheduler/util" ) -const enableEquivalenceCache = true +const ( + enableEquivalenceCache = true + disablePodPreemption = false +) func TestCreate(t *testing.T) { handler := utiltesting.FakeHandler{ @@ -56,7 +59,7 @@ func TestCreate(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight) factory.Create() } @@ -74,7 +77,7 @@ func TestCreateFromConfig(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight) // Pre-register some predicate and priority functions @@ -119,7 +122,7 @@ func TestCreateFromConfigWithHardPodAffinitySymmetricWeight(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight) // Pre-register some predicate and priority functions @@ -165,7 +168,7 @@ func TestCreateFromEmptyConfig(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight) configData = []byte(`{}`) @@ -187,7 +190,7 @@ func TestCreateFromConfigWithUnspecifiedPredicatesOrPriorities(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight) RegisterFitPredicate("PredicateOne", PredicateOne) @@ -227,7 +230,7 @@ func TestCreateFromConfigWithEmptyPredicatesOrPriorities(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight) RegisterFitPredicate("PredicateOne", PredicateOne) @@ -281,16 +284,16 @@ func TestDefaultErrorFunc(t *testing.T) { } handler := utiltesting.FakeHandler{ StatusCode: 200, - ResponseBody: runtime.EncodeOrDie(util.Test.Codec(), testPod), + ResponseBody: runtime.EncodeOrDie(schedulertesting.Test.Codec(), testPod), T: t, } mux := http.NewServeMux() // FakeHandler mustn't be sent requests other than the one you want to test. - mux.Handle(util.Test.ResourcePath(string(v1.ResourcePods), "bar", "foo"), &handler) + mux.Handle(schedulertesting.Test.ResourcePath(string(v1.ResourcePods), "bar", "foo"), &handler) server := httptest.NewServer(mux) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight) queue := &core.FIFO{FIFO: cache.NewFIFO(cache.MetaNamespaceKeyFunc)} podBackoff := util.CreatePodBackoff(1*time.Millisecond, 1*time.Second) @@ -306,7 +309,7 @@ func TestDefaultErrorFunc(t *testing.T) { if !exists { continue } - handler.ValidateRequest(t, util.Test.ResourcePath(string(v1.ResourcePods), "bar", "foo"), "GET", nil) + handler.ValidateRequest(t, schedulertesting.Test.ResourcePath(string(v1.ResourcePods), "bar", "foo"), "GET", nil) if e, a := testPod, got; !reflect.DeepEqual(e, a) { t.Errorf("Expected %v, got %v", e, a) } @@ -361,16 +364,16 @@ func TestBind(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) b := binder{client} if err := b.Bind(item.binding); err != nil { t.Errorf("Unexpected error: %v", err) continue } - expectedBody := runtime.EncodeOrDie(util.Test.Codec(), item.binding) + expectedBody := runtime.EncodeOrDie(schedulertesting.Test.Codec(), item.binding) handler.ValidateRequest(t, - util.Test.SubResourcePath(string(v1.ResourcePods), metav1.NamespaceDefault, "foo", "binding"), + schedulertesting.Test.SubResourcePath(string(v1.ResourcePods), metav1.NamespaceDefault, "foo", "binding"), "POST", &expectedBody) } } @@ -383,7 +386,7 @@ func TestInvalidHardPodAffinitySymmetricWeight(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) // factory of "default-scheduler" factory := newConfigFactory(client, -1) _, err := factory.Create() @@ -400,7 +403,7 @@ func TestInvalidFactoryArgs(t *testing.T) { } server := httptest.NewServer(&handler) defer server.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) testCases := []struct { hardPodAffinitySymmetricWeight int32 @@ -533,19 +536,44 @@ func newConfigFactory(client *clientset.Clientset, hardPodAffinitySymmetricWeigh informerFactory.Storage().V1().StorageClasses(), hardPodAffinitySymmetricWeight, enableEquivalenceCache, + disablePodPreemption, ) } type fakeExtender struct { isBinder bool interestedPodName string + ignorable bool +} + +func (f *fakeExtender) IsIgnorable() bool { + return f.ignorable +} + +func (f *fakeExtender) ProcessPreemption( + pod *v1.Pod, + nodeToVictims map[*v1.Node]*schedulerapi.Victims, + nodeNameToInfo map[string]*schedulercache.NodeInfo, +) (map[*v1.Node]*schedulerapi.Victims, error) { + return nil, nil +} + +func (f *fakeExtender) SupportsPreemption() bool { + return false } -func (f *fakeExtender) Filter(pod *v1.Pod, nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo) (filteredNodes []*v1.Node, failedNodesMap schedulerapi.FailedNodesMap, err error) { +func (f *fakeExtender) Filter( + pod *v1.Pod, + nodes []*v1.Node, + nodeNameToInfo map[string]*schedulercache.NodeInfo, +) (filteredNodes []*v1.Node, failedNodesMap schedulerapi.FailedNodesMap, err error) { return nil, nil, nil } -func (f *fakeExtender) Prioritize(pod *v1.Pod, nodes []*v1.Node) (hostPriorities *schedulerapi.HostPriorityList, weight int, err error) { +func (f *fakeExtender) Prioritize( + pod *v1.Pod, + nodes []*v1.Node, +) (hostPriorities *schedulerapi.HostPriorityList, weight int, err error) { return nil, 0, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/plugins.go b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/plugins.go index bd33dad00..f9a668b4a 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/plugins.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/plugins.go @@ -75,9 +75,6 @@ type PriorityConfigFactory struct { Weight int } -// EquivalencePodFuncFactory produces a function to get equivalence class for given pod. -type EquivalencePodFuncFactory func(PluginFactoryArgs) algorithm.GetEquivalencePodFunc - var ( schedulerFactoryMutex sync.Mutex @@ -90,9 +87,6 @@ var ( // Registered metadata producers priorityMetadataProducer PriorityMetadataProducerFactory predicateMetadataProducer PredicateMetadataProducerFactory - - // get equivalence pod function - getEquivalencePodFuncFactory EquivalencePodFuncFactory ) const ( @@ -328,6 +322,15 @@ func RegisterCustomPriorityFunction(policy schedulerapi.PriorityPolicy) string { }, Weight: policy.Weight, } + } else if policy.Argument.RequestedToCapacityRatioArguments != nil { + pcf = &PriorityConfigFactory{ + MapReduceFunction: func(args PluginFactoryArgs) (algorithm.PriorityMapFunction, algorithm.PriorityReduceFunction) { + scoringFunctionShape := buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(policy.Argument.RequestedToCapacityRatioArguments) + p := priorities.RequestedToCapacityRatioResourceAllocationPriority(scoringFunctionShape) + return p.PriorityMap, nil + }, + Weight: policy.Weight, + } } } else if existingPcf, ok := priorityFunctionMap[policy.Name]; ok { glog.V(2).Infof("Priority type %s already registered, reusing.", policy.Name) @@ -346,9 +349,17 @@ func RegisterCustomPriorityFunction(policy schedulerapi.PriorityPolicy) string { return RegisterPriorityConfigFactory(policy.Name, *pcf) } -// RegisterGetEquivalencePodFunction registers equivalenceFuncFactory to produce equivalence class for given pod. -func RegisterGetEquivalencePodFunction(equivalenceFuncFactory EquivalencePodFuncFactory) { - getEquivalencePodFuncFactory = equivalenceFuncFactory +func buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(arguments *schedulerapi.RequestedToCapacityRatioArguments) priorities.FunctionShape { + n := len(arguments.UtilizationShape) + points := make([]priorities.FunctionShapePoint, 0, n) + for _, point := range arguments.UtilizationShape { + points = append(points, priorities.FunctionShapePoint{Utilization: int64(point.Utilization), Score: int64(point.Score)}) + } + shape, err := priorities.NewFunctionShape(points) + if err != nil { + glog.Fatalf("invalid RequestedToCapacityRatioPriority arguments: %s", err.Error()) + } + return shape } // IsPriorityFunctionRegistered is useful for testing providers. @@ -505,6 +516,9 @@ func validatePriorityOrDie(priority schedulerapi.PriorityPolicy) { if priority.Argument.LabelPreference != nil { numArgs++ } + if priority.Argument.RequestedToCapacityRatioArguments != nil { + numArgs++ + } if numArgs != 1 { glog.Fatalf("Exactly 1 priority argument is required, numArgs: %v, Priority: %s", numArgs, priority.Name) } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/plugins_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/plugins_test.go index a3508c139..ee813de97 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/plugins_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/plugins_test.go @@ -19,7 +19,9 @@ package factory import ( "testing" + "github.com/stretchr/testify/assert" "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" "k8s.io/kubernetes/pkg/scheduler/api" ) @@ -80,3 +82,19 @@ func TestValidatePriorityConfigOverFlow(t *testing.T) { } } } + +func TestBuildScoringFunctionShapeFromRequestedToCapacityRatioArguments(t *testing.T) { + arguments := api.RequestedToCapacityRatioArguments{ + UtilizationShape: []api.UtilizationShapePoint{ + {Utilization: 10, Score: 1}, + {Utilization: 30, Score: 5}, + {Utilization: 70, Score: 2}, + }} + builtShape := buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(&arguments) + expectedShape, _ := priorities.NewFunctionShape([]priorities.FunctionShapePoint{ + {Utilization: 10, Score: 1}, + {Utilization: 30, Score: 5}, + {Utilization: 70, Score: 2}, + }) + assert.Equal(t, expectedShape, builtShape) +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/signal.go b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/signal.go new file mode 100644 index 000000000..8ec17048e --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/signal.go @@ -0,0 +1,25 @@ +// +build !windows + +/* +Copyright 2018 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 factory + +import "syscall" + +// compareSignal is the signal to trigger cache compare. For non-windows +// environment it's SIGUSR2. +var compareSignal = syscall.SIGUSR2 diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/factory/signal_windows.go b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/signal_windows.go new file mode 100644 index 000000000..9df239874 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/factory/signal_windows.go @@ -0,0 +1,23 @@ +/* +Copyright 2018 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 factory + +import "os" + +// compareSignal is the signal to trigger cache compare. For windows, +// it's SIGINT. +var compareSignal = os.Interrupt diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/metrics/metrics.go b/vendor/k8s.io/kubernetes/pkg/scheduler/metrics/metrics.go index 4836ac4b9..1b5d77b47 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/metrics/metrics.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/metrics/metrics.go @@ -23,13 +23,43 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -const schedulerSubsystem = "scheduler" +const ( + // SchedulerSubsystem - subsystem name used by scheduler + SchedulerSubsystem = "scheduler" + // SchedulingLatencyName - scheduler latency metric name + SchedulingLatencyName = "scheduling_latency_seconds" + + // OperationLabel - operation label name + OperationLabel = "operation" + // Below are possible values for the operation label. Each represents a substep of e2e scheduling: + + // PredicateEvaluation - predicate evaluation operation label value + PredicateEvaluation = "predicate_evaluation" + // PriorityEvaluation - priority evaluation operation label value + PriorityEvaluation = "priority_evaluation" + // PreemptionEvaluation - preemption evaluation operation label value (occurs in case of scheduling fitError). + PreemptionEvaluation = "preemption_evaluation" + // Binding - binding operation label value + Binding = "binding" + // E2eScheduling - e2e scheduling operation label value +) // All the histogram based metrics have 1ms as size for the smallest bucket. var ( + SchedulingLatency = prometheus.NewSummaryVec( + prometheus.SummaryOpts{ + Subsystem: SchedulerSubsystem, + Name: SchedulingLatencyName, + Help: "Scheduling latency in seconds split by sub-parts of the scheduling operation", + // Make the sliding window of 5h. + // TODO: The value for this should be based on some SLI definition (long term). + MaxAge: 5 * time.Hour, + }, + []string{OperationLabel}, + ) E2eSchedulingLatency = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "e2e_scheduling_latency_microseconds", Help: "E2e scheduling latency (scheduling algorithm + binding)", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -37,7 +67,7 @@ var ( ) SchedulingAlgorithmLatency = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "scheduling_algorithm_latency_microseconds", Help: "Scheduling algorithm latency", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -45,7 +75,7 @@ var ( ) SchedulingAlgorithmPredicateEvaluationDuration = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "scheduling_algorithm_predicate_evaluation", Help: "Scheduling algorithm predicate evaluation duration", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -53,7 +83,7 @@ var ( ) SchedulingAlgorithmPriorityEvaluationDuration = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "scheduling_algorithm_priority_evaluation", Help: "Scheduling algorithm priority evaluation duration", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -61,7 +91,7 @@ var ( ) SchedulingAlgorithmPremptionEvaluationDuration = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "scheduling_algorithm_preemption_evaluation", Help: "Scheduling algorithm preemption evaluation duration", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -69,7 +99,7 @@ var ( ) BindingLatency = prometheus.NewHistogram( prometheus.HistogramOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "binding_latency_microseconds", Help: "Binding latency", Buckets: prometheus.ExponentialBuckets(1000, 2, 15), @@ -77,16 +107,27 @@ var ( ) PreemptionVictims = prometheus.NewGauge( prometheus.GaugeOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "pod_preemption_victims", Help: "Number of selected preemption victims", }) PreemptionAttempts = prometheus.NewCounter( prometheus.CounterOpts{ - Subsystem: schedulerSubsystem, + Subsystem: SchedulerSubsystem, Name: "total_preemption_attempts", Help: "Total preemption attempts in the cluster till now", }) + metricsList = []prometheus.Collector{ + SchedulingLatency, + E2eSchedulingLatency, + SchedulingAlgorithmLatency, + BindingLatency, + SchedulingAlgorithmPredicateEvaluationDuration, + SchedulingAlgorithmPriorityEvaluationDuration, + SchedulingAlgorithmPremptionEvaluationDuration, + PreemptionVictims, + PreemptionAttempts, + } ) var registerMetrics sync.Once @@ -95,19 +136,23 @@ var registerMetrics sync.Once func Register() { // Register the metrics. registerMetrics.Do(func() { - prometheus.MustRegister(E2eSchedulingLatency) - prometheus.MustRegister(SchedulingAlgorithmLatency) - prometheus.MustRegister(BindingLatency) - - prometheus.MustRegister(SchedulingAlgorithmPredicateEvaluationDuration) - prometheus.MustRegister(SchedulingAlgorithmPriorityEvaluationDuration) - prometheus.MustRegister(SchedulingAlgorithmPremptionEvaluationDuration) - prometheus.MustRegister(PreemptionVictims) - prometheus.MustRegister(PreemptionAttempts) + for _, metric := range metricsList { + prometheus.MustRegister(metric) + } }) } +// Reset resets metrics +func Reset() { + SchedulingLatency.Reset() +} + // SinceInMicroseconds gets the time since the specified start in microseconds. func SinceInMicroseconds(start time.Time) float64 { return float64(time.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds()) } + +// SinceInSeconds gets the time since the specified start in seconds. +func SinceInSeconds(start time.Time) float64 { + return time.Since(start).Seconds() +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/scheduler.go b/vendor/k8s.io/kubernetes/pkg/scheduler/scheduler.go index ebab58d45..10cc9f082 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/scheduler.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/scheduler.go @@ -32,9 +32,9 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/core" "k8s.io/kubernetes/pkg/scheduler/metrics" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" @@ -137,6 +137,9 @@ type Config struct { // VolumeBinder handles PVC/PV binding for the pod. VolumeBinder *volumebinder.VolumeBinder + + // Disable pod preemption or not. + DisablePreemption bool } // NewFromConfigurator returns a new scheduler that is created entirely by the Configurator. Assumes Create() is implemented. @@ -207,8 +210,9 @@ func (sched *Scheduler) schedule(pod *v1.Pod) (string, error) { // If it succeeds, it adds the name of the node where preemption has happened to the pod annotations. // It returns the node name and an error if any. func (sched *Scheduler) preempt(preemptor *v1.Pod, scheduleErr error) (string, error) { - if !util.PodPriorityEnabled() { - glog.V(3).Infof("Pod priority feature is not enabled. No preemption is performed.") + if !util.PodPriorityEnabled() || sched.config.DisablePreemption { + glog.V(3).Infof("Pod priority feature is not enabled or preemption is disabled by scheduler configuration." + + " No preemption is performed.") return "", nil } preemptor, err := sched.config.PodPreemptor.GetUpdatedPod(preemptor) @@ -328,7 +332,7 @@ func (sched *Scheduler) bindVolumesWorker() { // The Pod is always sent back to the scheduler afterwards. err := sched.config.VolumeBinder.Binder.BindPodVolumes(assumed) if err != nil { - glog.V(1).Infof("Failed to bind volumes for pod \"%v/%v\"", assumed.Namespace, assumed.Name, err) + glog.V(1).Infof("Failed to bind volumes for pod \"%v/%v\": %v", assumed.Namespace, assumed.Name, err) reason = "VolumeBindingFailed" eventType = v1.EventTypeWarning } else { @@ -369,6 +373,9 @@ func (sched *Scheduler) assume(assumed *v1.Pod, host string) error { // If the binding fails, scheduler will release resources allocated to assumed pod // immediately. assumed.Spec.NodeName = host + // NOTE: Because the scheduler uses snapshots of SchedulerCache and the live + // version of Ecache, updates must be written to SchedulerCache before + // invalidating Ecache. if err := sched.config.SchedulerCache.AssumePod(assumed); err != nil { glog.Errorf("scheduler cache AssumePod failed: %v", err) @@ -423,7 +430,8 @@ func (sched *Scheduler) bind(assumed *v1.Pod, b *v1.Binding) error { } metrics.BindingLatency.Observe(metrics.SinceInMicroseconds(bindingStart)) - sched.config.Recorder.Eventf(assumed, v1.EventTypeNormal, "Scheduled", "Successfully assigned %v to %v", assumed.Name, b.Target.Name) + metrics.SchedulingLatency.WithLabelValues(metrics.Binding).Observe(metrics.SinceInSeconds(bindingStart)) + sched.config.Recorder.Eventf(assumed, v1.EventTypeNormal, "Scheduled", "Successfully assigned %v/%v to %v", assumed.Namespace, assumed.Name, b.Target.Name) return nil } @@ -451,6 +459,7 @@ func (sched *Scheduler) scheduleOne() { sched.preempt(pod, fitError) metrics.PreemptionAttempts.Inc() metrics.SchedulingAlgorithmPremptionEvaluationDuration.Observe(metrics.SinceInMicroseconds(preemptionStartTime)) + metrics.SchedulingLatency.WithLabelValues(metrics.PreemptionEvaluation).Observe(metrics.SinceInSeconds(preemptionStartTime)) } return } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/scheduler_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/scheduler_test.go index 4debe5217..21a074cff 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/scheduler_test.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/scheduler_test.go @@ -37,10 +37,9 @@ import ( "k8s.io/kubernetes/pkg/controller/volume/persistentvolume" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/core" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" - "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" ) @@ -79,7 +78,7 @@ func podWithID(id, desiredHost string) *v1.Pod { ObjectMeta: metav1.ObjectMeta{ Name: id, UID: types.UID(id), - SelfLink: util.Test.SelfLink(string(v1.ResourcePods), id), + SelfLink: schedulertesting.Test.SelfLink(string(v1.ResourcePods), id), }, Spec: v1.PodSpec{ NodeName: desiredHost, @@ -93,7 +92,7 @@ func deletingPod(id string) *v1.Pod { ObjectMeta: metav1.ObjectMeta{ Name: id, UID: types.UID(id), - SelfLink: util.Test.SelfLink(string(v1.ResourcePods), id), + SelfLink: schedulertesting.Test.SelfLink(string(v1.ResourcePods), id), DeletionTimestamp: &deletionTimestamp, }, Spec: v1.PodSpec{ @@ -548,6 +547,7 @@ func setupTestScheduler(queuedPodStore *clientcache.FIFO, scache schedulercache. []algorithm.SchedulerExtender{}, nil, schedulertesting.FakePersistentVolumeClaimLister{}, + false, false) bindingChan := make(chan *v1.Binding, 1) errChan := make(chan error, 1) @@ -596,6 +596,7 @@ func setupTestSchedulerLongBindingWithRetry(queuedPodStore *clientcache.FIFO, sc []algorithm.SchedulerExtender{}, nil, schedulertesting.FakePersistentVolumeClaimLister{}, + false, false) bindingChan := make(chan *v1.Binding, 2) configurator := &FakeConfigurator{ @@ -659,8 +660,6 @@ func makePredicateError(failReason string) error { } func TestSchedulerWithVolumeBinding(t *testing.T) { - order := []string{predicates.CheckVolumeBindingPred, predicates.GeneralPred} - predicates.SetPredicatesOrdering(order) findErr := fmt.Errorf("find err") assumeErr := fmt.Errorf("assume err") bindErr := fmt.Errorf("bind err") diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/BUILD deleted file mode 100644 index 90daac4cd..000000000 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/BUILD +++ /dev/null @@ -1,58 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "cache.go", - "interface.go", - "node_info.go", - "util.go", - ], - importpath = "k8s.io/kubernetes/pkg/scheduler/schedulercache", - visibility = ["//visibility:public"], - deps = [ - "//pkg/apis/core/v1/helper:go_default_library", - "//pkg/scheduler/algorithm/priorities/util:go_default_library", - "//pkg/scheduler/util:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "cache_test.go", - "node_info_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//pkg/scheduler/algorithm/priorities/util:go_default_library", - "//pkg/scheduler/util:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/policy/v1beta1: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/labels:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/interface.go b/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/interface.go deleted file mode 100644 index d3c65313b..000000000 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/interface.go +++ /dev/null @@ -1,122 +0,0 @@ -/* -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 schedulercache - -import ( - "k8s.io/api/core/v1" - policy "k8s.io/api/policy/v1beta1" - "k8s.io/apimachinery/pkg/labels" -) - -// PodFilter is a function to filter a pod. If pod passed return true else return false. -type PodFilter func(*v1.Pod) bool - -// Cache collects pods' information and provides node-level aggregated information. -// It's intended for generic scheduler to do efficient lookup. -// Cache's operations are pod centric. It does incremental updates based on pod events. -// Pod events are sent via network. We don't have guaranteed delivery of all events: -// We use Reflector to list and watch from remote. -// Reflector might be slow and do a relist, which would lead to missing events. -// -// State Machine of a pod's events in scheduler's cache: -// -// -// +-------------------------------------------+ +----+ -// | Add | | | -// | | | | Update -// + Assume Add v v | -//Initial +--------> Assumed +------------+---> Added <--+ -// ^ + + | + -// | | | | | -// | | | Add | | Remove -// | | | | | -// | | | + | -// +----------------+ +-----------> Expired +----> Deleted -// Forget Expire -// -// -// Note that an assumed pod can expire, because if we haven't received Add event notifying us -// for a while, there might be some problems and we shouldn't keep the pod in cache anymore. -// -// Note that "Initial", "Expired", and "Deleted" pods do not actually exist in cache. -// Based on existing use cases, we are making the following assumptions: -// - No pod would be assumed twice -// - A pod could be added without going through scheduler. In this case, we will see Add but not Assume event. -// - If a pod wasn't added, it wouldn't be removed or updated. -// - Both "Expired" and "Deleted" are valid end states. In case of some problems, e.g. network issue, -// a pod might have changed its state (e.g. added and deleted) without delivering notification to the cache. -type Cache interface { - // AssumePod assumes a pod scheduled and aggregates the pod's information into its node. - // The implementation also decides the policy to expire pod before being confirmed (receiving Add event). - // After expiration, its information would be subtracted. - AssumePod(pod *v1.Pod) error - - // FinishBinding signals that cache for assumed pod can be expired - FinishBinding(pod *v1.Pod) error - - // ForgetPod removes an assumed pod from cache. - ForgetPod(pod *v1.Pod) error - - // AddPod either confirms a pod if it's assumed, or adds it back if it's expired. - // If added back, the pod's information would be added again. - AddPod(pod *v1.Pod) error - - // UpdatePod removes oldPod's information and adds newPod's information. - UpdatePod(oldPod, newPod *v1.Pod) error - - // RemovePod removes a pod. The pod's information would be subtracted from assigned node. - RemovePod(pod *v1.Pod) error - - // GetPod returns the pod from the cache with the same namespace and the - // same name of the specified pod. - GetPod(pod *v1.Pod) (*v1.Pod, error) - - // IsAssumedPod returns true if the pod is assumed and not expired. - IsAssumedPod(pod *v1.Pod) (bool, error) - - // AddNode adds overall information about node. - AddNode(node *v1.Node) error - - // UpdateNode updates overall information about node. - UpdateNode(oldNode, newNode *v1.Node) error - - // RemoveNode removes overall information about node. - RemoveNode(node *v1.Node) error - - // AddPDB adds a PodDisruptionBudget object to the cache. - AddPDB(pdb *policy.PodDisruptionBudget) error - - // UpdatePDB updates a PodDisruptionBudget object in the cache. - UpdatePDB(oldPDB, newPDB *policy.PodDisruptionBudget) error - - // RemovePDB removes a PodDisruptionBudget object from the cache. - RemovePDB(pdb *policy.PodDisruptionBudget) error - - // List lists all cached PDBs matching the selector. - ListPDBs(selector labels.Selector) ([]*policy.PodDisruptionBudget, error) - - // UpdateNodeNameToInfoMap updates the passed infoMap to the current contents of Cache. - // The node info contains aggregated information of pods scheduled (including assumed to be) - // on this node. - UpdateNodeNameToInfoMap(infoMap map[string]*NodeInfo) error - - // List lists all cached pods (including assumed ones). - List(labels.Selector) ([]*v1.Pod, error) - - // FilteredList returns all cached pods that pass the filter. - FilteredList(filter PodFilter, selector labels.Selector) ([]*v1.Pod, error) -} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/node_info.go b/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/node_info.go deleted file mode 100644 index 3c981982a..000000000 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/node_info.go +++ /dev/null @@ -1,518 +0,0 @@ -/* -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 schedulercache - -import ( - "errors" - "fmt" - - "github.com/golang/glog" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" - priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - "k8s.io/kubernetes/pkg/scheduler/util" -) - -var emptyResource = Resource{} - -// NodeInfo is node level aggregated information. -type NodeInfo struct { - // Overall node information. - node *v1.Node - - pods []*v1.Pod - podsWithAffinity []*v1.Pod - usedPorts util.HostPortInfo - - // Total requested resource of all pods on this node. - // It includes assumed pods which scheduler sends binding to apiserver but - // didn't get it as scheduled yet. - requestedResource *Resource - nonzeroRequest *Resource - // We store allocatedResources (which is Node.Status.Allocatable.*) explicitly - // as int64, to avoid conversions and accessing map. - allocatableResource *Resource - - // Cached tains of the node for faster lookup. - taints []v1.Taint - taintsErr error - - // Cached conditions of node for faster lookup. - memoryPressureCondition v1.ConditionStatus - diskPressureCondition v1.ConditionStatus - - // Whenever NodeInfo changes, generation is bumped. - // This is used to avoid cloning it if the object didn't change. - generation int64 -} - -// Resource is a collection of compute resource. -type Resource struct { - MilliCPU int64 - Memory int64 - NvidiaGPU int64 - EphemeralStorage int64 - // We store allowedPodNumber (which is Node.Status.Allocatable.Pods().Value()) - // explicitly as int, to avoid conversions and improve performance. - AllowedPodNumber int - // ScalarResources - ScalarResources map[v1.ResourceName]int64 -} - -// NewResource creates a Resource from ResourceList -func NewResource(rl v1.ResourceList) *Resource { - r := &Resource{} - r.Add(rl) - return r -} - -// Add adds ResourceList into Resource. -func (r *Resource) Add(rl v1.ResourceList) { - if r == nil { - return - } - - for rName, rQuant := range rl { - switch rName { - case v1.ResourceCPU: - r.MilliCPU += rQuant.MilliValue() - case v1.ResourceMemory: - r.Memory += rQuant.Value() - case v1.ResourceNvidiaGPU: - r.NvidiaGPU += rQuant.Value() - case v1.ResourcePods: - r.AllowedPodNumber += int(rQuant.Value()) - case v1.ResourceEphemeralStorage: - r.EphemeralStorage += rQuant.Value() - default: - if v1helper.IsScalarResourceName(rName) { - r.AddScalar(rName, rQuant.Value()) - } - } - } -} - -// ResourceList returns a resource list of this resource. -func (r *Resource) ResourceList() v1.ResourceList { - result := v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(r.MilliCPU, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(r.Memory, resource.BinarySI), - v1.ResourceNvidiaGPU: *resource.NewQuantity(r.NvidiaGPU, resource.DecimalSI), - v1.ResourcePods: *resource.NewQuantity(int64(r.AllowedPodNumber), resource.BinarySI), - v1.ResourceEphemeralStorage: *resource.NewQuantity(r.EphemeralStorage, resource.BinarySI), - } - for rName, rQuant := range r.ScalarResources { - if v1helper.IsHugePageResourceName(rName) { - result[rName] = *resource.NewQuantity(rQuant, resource.BinarySI) - } else { - result[rName] = *resource.NewQuantity(rQuant, resource.DecimalSI) - } - } - return result -} - -// Clone returns a copy of this resource. -func (r *Resource) Clone() *Resource { - res := &Resource{ - MilliCPU: r.MilliCPU, - Memory: r.Memory, - NvidiaGPU: r.NvidiaGPU, - AllowedPodNumber: r.AllowedPodNumber, - EphemeralStorage: r.EphemeralStorage, - } - if r.ScalarResources != nil { - res.ScalarResources = make(map[v1.ResourceName]int64) - for k, v := range r.ScalarResources { - res.ScalarResources[k] = v - } - } - return res -} - -// AddScalar adds a resource by a scalar value of this resource. -func (r *Resource) AddScalar(name v1.ResourceName, quantity int64) { - r.SetScalar(name, r.ScalarResources[name]+quantity) -} - -// SetScalar sets a resource by a scalar value of this resource. -func (r *Resource) SetScalar(name v1.ResourceName, quantity int64) { - // Lazily allocate scalar resource map. - if r.ScalarResources == nil { - r.ScalarResources = map[v1.ResourceName]int64{} - } - r.ScalarResources[name] = quantity -} - -// NewNodeInfo returns a ready to use empty NodeInfo object. -// If any pods are given in arguments, their information will be aggregated in -// the returned object. -func NewNodeInfo(pods ...*v1.Pod) *NodeInfo { - ni := &NodeInfo{ - requestedResource: &Resource{}, - nonzeroRequest: &Resource{}, - allocatableResource: &Resource{}, - generation: 0, - usedPorts: make(util.HostPortInfo), - } - for _, pod := range pods { - ni.AddPod(pod) - } - return ni -} - -// Node returns overall information about this node. -func (n *NodeInfo) Node() *v1.Node { - if n == nil { - return nil - } - return n.node -} - -// Pods return all pods scheduled (including assumed to be) on this node. -func (n *NodeInfo) Pods() []*v1.Pod { - if n == nil { - return nil - } - return n.pods -} - -// UsedPorts returns used ports on this node. -func (n *NodeInfo) UsedPorts() util.HostPortInfo { - if n == nil { - return nil - } - return n.usedPorts -} - -// PodsWithAffinity return all pods with (anti)affinity constraints on this node. -func (n *NodeInfo) PodsWithAffinity() []*v1.Pod { - if n == nil { - return nil - } - return n.podsWithAffinity -} - -// AllowedPodNumber returns the number of the allowed pods on this node. -func (n *NodeInfo) AllowedPodNumber() int { - if n == nil || n.allocatableResource == nil { - return 0 - } - return n.allocatableResource.AllowedPodNumber -} - -// Taints returns the taints list on this node. -func (n *NodeInfo) Taints() ([]v1.Taint, error) { - if n == nil { - return nil, nil - } - return n.taints, n.taintsErr -} - -// MemoryPressureCondition returns the memory pressure condition status on this node. -func (n *NodeInfo) MemoryPressureCondition() v1.ConditionStatus { - if n == nil { - return v1.ConditionUnknown - } - return n.memoryPressureCondition -} - -// DiskPressureCondition returns the disk pressure condition status on this node. -func (n *NodeInfo) DiskPressureCondition() v1.ConditionStatus { - if n == nil { - return v1.ConditionUnknown - } - return n.diskPressureCondition -} - -// RequestedResource returns aggregated resource request of pods on this node. -func (n *NodeInfo) RequestedResource() Resource { - if n == nil { - return emptyResource - } - return *n.requestedResource -} - -// NonZeroRequest returns aggregated nonzero resource request of pods on this node. -func (n *NodeInfo) NonZeroRequest() Resource { - if n == nil { - return emptyResource - } - return *n.nonzeroRequest -} - -// AllocatableResource returns allocatable resources on a given node. -func (n *NodeInfo) AllocatableResource() Resource { - if n == nil { - return emptyResource - } - return *n.allocatableResource -} - -// SetAllocatableResource sets the allocatableResource information of given node. -func (n *NodeInfo) SetAllocatableResource(allocatableResource *Resource) { - n.allocatableResource = allocatableResource -} - -// Clone returns a copy of this node. -func (n *NodeInfo) Clone() *NodeInfo { - clone := &NodeInfo{ - node: n.node, - requestedResource: n.requestedResource.Clone(), - nonzeroRequest: n.nonzeroRequest.Clone(), - allocatableResource: n.allocatableResource.Clone(), - taintsErr: n.taintsErr, - memoryPressureCondition: n.memoryPressureCondition, - diskPressureCondition: n.diskPressureCondition, - usedPorts: make(util.HostPortInfo), - generation: n.generation, - } - if len(n.pods) > 0 { - clone.pods = append([]*v1.Pod(nil), n.pods...) - } - if len(n.usedPorts) > 0 { - for k, v := range n.usedPorts { - clone.usedPorts[k] = v - } - } - if len(n.podsWithAffinity) > 0 { - clone.podsWithAffinity = append([]*v1.Pod(nil), n.podsWithAffinity...) - } - if len(n.taints) > 0 { - clone.taints = append([]v1.Taint(nil), n.taints...) - } - return clone -} - -// String returns representation of human readable format of this NodeInfo. -func (n *NodeInfo) String() string { - podKeys := make([]string, len(n.pods)) - for i, pod := range n.pods { - podKeys[i] = pod.Name - } - return fmt.Sprintf("&NodeInfo{Pods:%v, RequestedResource:%#v, NonZeroRequest: %#v, UsedPort: %#v, AllocatableResource:%#v}", - podKeys, n.requestedResource, n.nonzeroRequest, n.usedPorts, n.allocatableResource) -} - -func hasPodAffinityConstraints(pod *v1.Pod) bool { - affinity := pod.Spec.Affinity - return affinity != nil && (affinity.PodAffinity != nil || affinity.PodAntiAffinity != nil) -} - -// AddPod adds pod information to this NodeInfo. -func (n *NodeInfo) AddPod(pod *v1.Pod) { - res, non0CPU, non0Mem := calculateResource(pod) - n.requestedResource.MilliCPU += res.MilliCPU - n.requestedResource.Memory += res.Memory - n.requestedResource.NvidiaGPU += res.NvidiaGPU - n.requestedResource.EphemeralStorage += res.EphemeralStorage - if n.requestedResource.ScalarResources == nil && len(res.ScalarResources) > 0 { - n.requestedResource.ScalarResources = map[v1.ResourceName]int64{} - } - for rName, rQuant := range res.ScalarResources { - n.requestedResource.ScalarResources[rName] += rQuant - } - n.nonzeroRequest.MilliCPU += non0CPU - n.nonzeroRequest.Memory += non0Mem - n.pods = append(n.pods, pod) - if hasPodAffinityConstraints(pod) { - n.podsWithAffinity = append(n.podsWithAffinity, pod) - } - - // Consume ports when pods added. - n.updateUsedPorts(pod, true) - - n.generation++ -} - -// RemovePod subtracts pod information from this NodeInfo. -func (n *NodeInfo) RemovePod(pod *v1.Pod) error { - k1, err := getPodKey(pod) - if err != nil { - return err - } - - for i := range n.podsWithAffinity { - k2, err := getPodKey(n.podsWithAffinity[i]) - if err != nil { - glog.Errorf("Cannot get pod key, err: %v", err) - continue - } - if k1 == k2 { - // delete the element - n.podsWithAffinity[i] = n.podsWithAffinity[len(n.podsWithAffinity)-1] - n.podsWithAffinity = n.podsWithAffinity[:len(n.podsWithAffinity)-1] - break - } - } - for i := range n.pods { - k2, err := getPodKey(n.pods[i]) - if err != nil { - glog.Errorf("Cannot get pod key, err: %v", err) - continue - } - if k1 == k2 { - // delete the element - n.pods[i] = n.pods[len(n.pods)-1] - n.pods = n.pods[:len(n.pods)-1] - // reduce the resource data - res, non0CPU, non0Mem := calculateResource(pod) - - n.requestedResource.MilliCPU -= res.MilliCPU - n.requestedResource.Memory -= res.Memory - n.requestedResource.NvidiaGPU -= res.NvidiaGPU - n.requestedResource.EphemeralStorage -= res.EphemeralStorage - if len(res.ScalarResources) > 0 && n.requestedResource.ScalarResources == nil { - n.requestedResource.ScalarResources = map[v1.ResourceName]int64{} - } - for rName, rQuant := range res.ScalarResources { - n.requestedResource.ScalarResources[rName] -= rQuant - } - n.nonzeroRequest.MilliCPU -= non0CPU - n.nonzeroRequest.Memory -= non0Mem - - // Release ports when remove Pods. - n.updateUsedPorts(pod, false) - - n.generation++ - - return nil - } - } - return fmt.Errorf("no corresponding pod %s in pods of node %s", pod.Name, n.node.Name) -} - -func calculateResource(pod *v1.Pod) (res Resource, non0CPU int64, non0Mem int64) { - resPtr := &res - for _, c := range pod.Spec.Containers { - resPtr.Add(c.Resources.Requests) - - non0CPUReq, non0MemReq := priorityutil.GetNonzeroRequests(&c.Resources.Requests) - non0CPU += non0CPUReq - non0Mem += non0MemReq - // No non-zero resources for GPUs or opaque resources. - } - - return -} - -func (n *NodeInfo) updateUsedPorts(pod *v1.Pod, add bool) { - for j := range pod.Spec.Containers { - container := &pod.Spec.Containers[j] - for k := range container.Ports { - podPort := &container.Ports[k] - if add { - n.usedPorts.Add(podPort.HostIP, string(podPort.Protocol), podPort.HostPort) - } else { - n.usedPorts.Remove(podPort.HostIP, string(podPort.Protocol), podPort.HostPort) - } - } - } -} - -// SetNode sets the overall node information. -func (n *NodeInfo) SetNode(node *v1.Node) error { - n.node = node - - n.allocatableResource = NewResource(node.Status.Allocatable) - - n.taints = node.Spec.Taints - for i := range node.Status.Conditions { - cond := &node.Status.Conditions[i] - switch cond.Type { - case v1.NodeMemoryPressure: - n.memoryPressureCondition = cond.Status - case v1.NodeDiskPressure: - n.diskPressureCondition = cond.Status - default: - // We ignore other conditions. - } - } - n.generation++ - return nil -} - -// RemoveNode removes the overall information about the node. -func (n *NodeInfo) RemoveNode(node *v1.Node) error { - // We don't remove NodeInfo for because there can still be some pods on this node - - // this is because notifications about pods are delivered in a different watch, - // and thus can potentially be observed later, even though they happened before - // node removal. This is handled correctly in cache.go file. - n.node = nil - n.allocatableResource = &Resource{} - n.taints, n.taintsErr = nil, nil - n.memoryPressureCondition = v1.ConditionUnknown - n.diskPressureCondition = v1.ConditionUnknown - n.generation++ - return nil -} - -// FilterOutPods receives a list of pods and filters out those whose node names -// are equal to the node of this NodeInfo, but are not found in the pods of this NodeInfo. -// -// Preemption logic simulates removal of pods on a node by removing them from the -// corresponding NodeInfo. In order for the simulation to work, we call this method -// on the pods returned from SchedulerCache, so that predicate functions see -// only the pods that are not removed from the NodeInfo. -func (n *NodeInfo) FilterOutPods(pods []*v1.Pod) []*v1.Pod { - node := n.Node() - if node == nil { - return pods - } - filtered := make([]*v1.Pod, 0, len(pods)) - for _, p := range pods { - if p.Spec.NodeName == node.Name { - // If pod is on the given node, add it to 'filtered' only if it is present in nodeInfo. - podKey, _ := getPodKey(p) - for _, np := range n.Pods() { - npodkey, _ := getPodKey(np) - if npodkey == podKey { - filtered = append(filtered, p) - break - } - } - } else { - filtered = append(filtered, p) - } - } - return filtered -} - -// getPodKey returns the string key of a pod. -func getPodKey(pod *v1.Pod) (string, error) { - uid := string(pod.UID) - if len(uid) == 0 { - return "", errors.New("Cannot get cache key for pod with empty UID") - } - return uid, nil -} - -// Filter implements PodFilter interface. It returns false only if the pod node name -// matches NodeInfo.node and the pod is not found in the pods list. Otherwise, -// returns true. -func (n *NodeInfo) Filter(pod *v1.Pod) bool { - if pod.Spec.NodeName != n.node.Name { - return true - } - for _, p := range n.pods { - if p.Name == pod.Name && p.Namespace == pod.Namespace { - return true - } - } - return false -} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/util.go b/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/util.go deleted file mode 100644 index e2ac2d907..000000000 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/schedulercache/util.go +++ /dev/null @@ -1,39 +0,0 @@ -/* -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 schedulercache - -import "k8s.io/api/core/v1" - -// CreateNodeNameToInfoMap obtains a list of pods and pivots that list into a map where the keys are node names -// and the values are the aggregated information for that node. -func CreateNodeNameToInfoMap(pods []*v1.Pod, nodes []*v1.Node) map[string]*NodeInfo { - nodeNameToInfo := make(map[string]*NodeInfo) - for _, pod := range pods { - nodeName := pod.Spec.NodeName - if _, ok := nodeNameToInfo[nodeName]; !ok { - nodeNameToInfo[nodeName] = NewNodeInfo() - } - nodeNameToInfo[nodeName].AddPod(pod) - } - for _, node := range nodes { - if _, ok := nodeNameToInfo[node.Name]; !ok { - nodeNameToInfo[node.Name] = NewNodeInfo() - } - nodeNameToInfo[node.Name].SetNode(node) - } - return nodeNameToInfo -} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/BUILD index 3b4b65c08..241218afd 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/BUILD @@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( @@ -11,17 +12,23 @@ go_library( "fake_cache.go", "fake_lister.go", "pods_to_cache.go", + "util.go", ], importpath = "k8s.io/kubernetes/pkg/scheduler/testing", deps = [ + "//pkg/api/legacyscheme:go_default_library", + "//pkg/apis/core:go_default_library", + "//pkg/apis/core/install:go_default_library", "//pkg/scheduler/algorithm:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels: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/client-go/listers/core/v1:go_default_library", ], ) @@ -38,3 +45,13 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["util_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/fake_cache.go b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/fake_cache.go index 21c4528ae..65036bd34 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/fake_cache.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/fake_cache.go @@ -20,7 +20,7 @@ import ( "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // FakeCache is used for testing @@ -100,3 +100,11 @@ func (f *FakeCache) List(s labels.Selector) ([]*v1.Pod, error) { return nil, nil func (f *FakeCache) FilteredList(filter schedulercache.PodFilter, selector labels.Selector) ([]*v1.Pod, error) { return nil, nil } + +// Snapshot is a fake method for testing +func (f *FakeCache) Snapshot() *schedulercache.Snapshot { + return &schedulercache.Snapshot{} +} + +// IsUpToDate is a fake mthod for testing +func (f *FakeCache) IsUpToDate(*schedulercache.NodeInfo) bool { return true } diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/fake_lister.go b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/fake_lister.go index 6cb34a245..a65c409b3 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/fake_lister.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/fake_lister.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/labels" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/kubernetes/pkg/scheduler/algorithm" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) var _ algorithm.NodeLister = &FakeNodeLister{} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/pods_to_cache.go b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/pods_to_cache.go index 09053ae8c..ecb237bfb 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/pods_to_cache.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/pods_to_cache.go @@ -19,7 +19,7 @@ package testing import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" ) // PodsToCache is used for testing diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/util.go b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/util.go new file mode 100644 index 000000000..25921a2e0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/util.go @@ -0,0 +1,173 @@ +/* +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 testing + +import ( + "fmt" + "mime" + "os" + "reflect" + "strings" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kubernetes/pkg/api/legacyscheme" + api "k8s.io/kubernetes/pkg/apis/core" + + // Init the core api installation + _ "k8s.io/kubernetes/pkg/apis/core/install" +) + +// TestGroup defines a api group for testing. +type TestGroup struct { + externalGroupVersion schema.GroupVersion + internalGroupVersion schema.GroupVersion + internalTypes map[string]reflect.Type + externalTypes map[string]reflect.Type +} + +var ( + // Groups defines a TestGroup map. + Groups = make(map[string]TestGroup) + // Test defines a TestGroup object. + Test TestGroup + + serializer runtime.SerializerInfo +) + +func init() { + if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 { + var ok bool + mediaType, _, err := mime.ParseMediaType(apiMediaType) + if err != nil { + panic(err) + } + serializer, ok = runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), mediaType) + if !ok { + panic(fmt.Sprintf("no serializer for %s", apiMediaType)) + } + } + + kubeTestAPI := os.Getenv("KUBE_TEST_API") + if len(kubeTestAPI) != 0 { + // priority is "first in list preferred", so this has to run in reverse order + testGroupVersions := strings.Split(kubeTestAPI, ",") + for i := len(testGroupVersions) - 1; i >= 0; i-- { + gvString := testGroupVersions[i] + groupVersion, err := schema.ParseGroupVersion(gvString) + if err != nil { + panic(fmt.Sprintf("Error parsing groupversion %v: %v", gvString, err)) + } + + internalGroupVersion := schema.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal} + Groups[groupVersion.Group] = TestGroup{ + externalGroupVersion: groupVersion, + internalGroupVersion: internalGroupVersion, + internalTypes: legacyscheme.Scheme.KnownTypes(internalGroupVersion), + externalTypes: legacyscheme.Scheme.KnownTypes(groupVersion), + } + } + } + + if _, ok := Groups[api.GroupName]; !ok { + externalGroupVersion := schema.GroupVersion{Group: api.GroupName, Version: "v1"} + Groups[api.GroupName] = TestGroup{ + externalGroupVersion: externalGroupVersion, + internalGroupVersion: api.SchemeGroupVersion, + internalTypes: legacyscheme.Scheme.KnownTypes(api.SchemeGroupVersion), + externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), + } + } + + Test = Groups[api.GroupName] +} + +// Codec returns the codec for the API version to test against, as set by the +// KUBE_TEST_API_TYPE env var. +func (g TestGroup) Codec() runtime.Codec { + if serializer.Serializer == nil { + return legacyscheme.Codecs.LegacyCodec(g.externalGroupVersion) + } + return legacyscheme.Codecs.CodecForVersions(serializer.Serializer, legacyscheme.Codecs.UniversalDeserializer(), schema.GroupVersions{g.externalGroupVersion}, nil) +} + +// SelfLink returns a self link that will appear to be for the version Version(). +// 'resource' should be the resource path, e.g. "pods" for the Pod type. 'name' should be +// empty for lists. +func (g TestGroup) SelfLink(resource, name string) string { + if g.externalGroupVersion.Group == api.GroupName { + if name == "" { + return fmt.Sprintf("/api/%s/%s", g.externalGroupVersion.Version, resource) + } + return fmt.Sprintf("/api/%s/%s/%s", g.externalGroupVersion.Version, resource, name) + } + + // TODO: will need a /apis prefix once we have proper multi-group + // support + if name == "" { + return fmt.Sprintf("/apis/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource) + } + return fmt.Sprintf("/apis/%s/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource, name) +} + +// ResourcePathWithPrefix returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name. +// For ex, this is of the form: +// /api/v1/watch/namespaces/foo/pods/pod0 for v1. +func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name string) string { + var path string + if g.externalGroupVersion.Group == api.GroupName { + path = "/api/" + g.externalGroupVersion.Version + } else { + // TODO: switch back once we have proper multiple group support + // path = "/apis/" + g.Group + "/" + Version(group...) + path = "/apis/" + g.externalGroupVersion.Group + "/" + g.externalGroupVersion.Version + } + + if prefix != "" { + path = path + "/" + prefix + } + if namespace != "" { + path = path + "/namespaces/" + namespace + } + // Resource names are lower case. + resource = strings.ToLower(resource) + if resource != "" { + path = path + "/" + resource + } + if name != "" { + path = path + "/" + name + } + return path +} + +// ResourcePath returns the appropriate path for the given resource, namespace and name. +// For example, this is of the form: +// /api/v1/namespaces/foo/pods/pod0 for v1. +func (g TestGroup) ResourcePath(resource, namespace, name string) string { + return g.ResourcePathWithPrefix("", resource, namespace, name) +} + +// SubResourcePath returns the appropriate path for the given resource, namespace, +// name and subresource. +func (g TestGroup) SubResourcePath(resource, namespace, name, sub string) string { + path := g.ResourcePathWithPrefix("", resource, namespace, name) + if sub != "" { + path = path + "/" + sub + } + + return path +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/testing/util_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/util_test.go new file mode 100644 index 000000000..e6545b005 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/testing/util_test.go @@ -0,0 +1,214 @@ +/* +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 testing + +import ( + "encoding/json" + "reflect" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +func TestResourcePathWithPrefix(t *testing.T) { + testCases := []struct { + prefix string + resource string + namespace string + name string + expected string + }{ + {"prefix", "resource", "mynamespace", "myresource", "/api/" + Test.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource/myresource"}, + {"prefix", "resource", "", "myresource", "/api/" + Test.externalGroupVersion.Version + "/prefix/resource/myresource"}, + {"prefix", "resource", "mynamespace", "", "/api/" + Test.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource"}, + {"prefix", "resource", "", "", "/api/" + Test.externalGroupVersion.Version + "/prefix/resource"}, + {"", "resource", "mynamespace", "myresource", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, + } + for _, item := range testCases { + if actual := Test.ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected { + t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name) + } + } + + TestGroup := Test + TestGroup.externalGroupVersion.Group = "TestGroup" + + testGroupCases := []struct { + prefix string + resource string + namespace string + name string + expected string + }{ + {"prefix", "resource", "mynamespace", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource/myresource"}, + {"prefix", "resource", "", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/resource/myresource"}, + {"prefix", "resource", "mynamespace", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource"}, + {"prefix", "resource", "", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/resource"}, + {"", "resource", "mynamespace", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, + } + for _, item := range testGroupCases { + if actual := TestGroup.ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected { + t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name) + } + } + +} + +func TestResourcePath(t *testing.T) { + testCases := []struct { + resource string + namespace string + name string + expected string + }{ + {"resource", "mynamespace", "myresource", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, + {"resource", "", "myresource", "/api/" + Test.externalGroupVersion.Version + "/resource/myresource"}, + {"resource", "mynamespace", "", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource"}, + {"resource", "", "", "/api/" + Test.externalGroupVersion.Version + "/resource"}, + } + for _, item := range testCases { + if actual := Test.ResourcePath(item.resource, item.namespace, item.name); actual != item.expected { + t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name) + } + } + + TestGroup := Test + TestGroup.externalGroupVersion.Group = "TestGroup" + + testGroupCases := []struct { + resource string + namespace string + name string + expected string + }{ + {"resource", "mynamespace", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, + {"resource", "", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource/myresource"}, + {"resource", "mynamespace", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource"}, + {"resource", "", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource"}, + } + for _, item := range testGroupCases { + if actual := TestGroup.ResourcePath(item.resource, item.namespace, item.name); actual != item.expected { + t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name) + } + } + +} + +func TestSubResourcePath(t *testing.T) { + testCases := []struct { + resource string + namespace string + name string + sub string + expected string + }{ + {"resource", "mynamespace", "myresource", "subresource", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource/subresource"}, + {"resource", "mynamespace", "myresource", "", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, + } + for _, item := range testCases { + if actual := Test.SubResourcePath(item.resource, item.namespace, item.name, item.sub); actual != item.expected { + t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s, name: %s and sub: %s", item.expected, actual, item.resource, item.namespace, item.name, item.sub) + } + } + + TestGroup := Test + TestGroup.externalGroupVersion.Group = "TestGroup" + + testGroupCases := []struct { + resource string + namespace string + name string + sub string + expected string + }{ + {"resource", "mynamespace", "myresource", "subresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource/subresource"}, + {"resource", "mynamespace", "myresource", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, + } + for _, item := range testGroupCases { + if actual := TestGroup.SubResourcePath(item.resource, item.namespace, item.name, item.sub); actual != item.expected { + t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s, name: %s and sub: %s", item.expected, actual, item.resource, item.namespace, item.name, item.sub) + } + } + +} + +func TestSelfLink(t *testing.T) { + testCases := []struct { + resource string + name string + expected string + }{ + {"resource", "name", "/api/" + Test.externalGroupVersion.Version + "/resource/name"}, + {"resource", "", "/api/" + Test.externalGroupVersion.Version + "/resource"}, + } + for _, item := range testCases { + if actual := Test.SelfLink(item.resource, item.name); actual != item.expected { + t.Errorf("Expected: %s, got: %s for resource: %s and name: %s", item.expected, actual, item.resource, item.name) + } + } + + TestGroup := Test + TestGroup.externalGroupVersion.Group = "TestGroup" + + testGroupCases := []struct { + resource string + name string + expected string + }{ + {"resource", "name", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource/name"}, + {"resource", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource"}, + } + for _, item := range testGroupCases { + if actual := TestGroup.SelfLink(item.resource, item.name); actual != item.expected { + t.Errorf("Expected: %s, got: %s for resource: %s and name: %s", item.expected, actual, item.resource, item.name) + } + } +} + +var status = &metav1.Status{ + Status: metav1.StatusFailure, + Code: 200, + Reason: metav1.StatusReasonUnknown, + Message: "", +} + +func TestV1EncodeDecodeStatus(t *testing.T) { + v1Codec := Test.Codec() + + encoded, err := runtime.Encode(v1Codec, status) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + typeMeta := metav1.TypeMeta{} + if err := json.Unmarshal(encoded, &typeMeta); err != nil { + t.Errorf("unexpected error: %v", err) + } + if typeMeta.Kind != "Status" { + t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded)) + } + if typeMeta.APIVersion != "v1" { + t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded)) + } + decoded, err := runtime.Decode(v1Codec, encoded) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(status, decoded) { + t.Errorf("expected: %#v, got: %#v", status, decoded) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/util/BUILD b/vendor/k8s.io/kubernetes/pkg/scheduler/util/BUILD index 37f3b829f..87bce617c 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/util/BUILD @@ -10,15 +10,12 @@ go_test( name = "go_default_test", srcs = [ "backoff_utils_test.go", - "testutil_test.go", "utils_test.go", ], embed = [":go_default_library"], deps = [ "//pkg/apis/scheduling:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", ], ) @@ -27,20 +24,14 @@ go_library( name = "go_default_library", srcs = [ "backoff_utils.go", - "testutil.go", "utils.go", ], importpath = "k8s.io/kubernetes/pkg/scheduler/util", deps = [ - "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core:go_default_library", - "//pkg/apis/core/install:go_default_library", "//pkg/apis/scheduling:go_default_library", "//pkg/features:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1: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/types:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/util/testutil.go b/vendor/k8s.io/kubernetes/pkg/scheduler/util/testutil.go deleted file mode 100644 index 7b3cf0d21..000000000 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/util/testutil.go +++ /dev/null @@ -1,173 +0,0 @@ -/* -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 util - -import ( - "fmt" - "mime" - "os" - "reflect" - "strings" - - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/pkg/api/legacyscheme" - api "k8s.io/kubernetes/pkg/apis/core" - - // Init the core api installation - _ "k8s.io/kubernetes/pkg/apis/core/install" -) - -// TestGroup defines a api group for testing. -type TestGroup struct { - externalGroupVersion schema.GroupVersion - internalGroupVersion schema.GroupVersion - internalTypes map[string]reflect.Type - externalTypes map[string]reflect.Type -} - -var ( - // Groups defines a TestGroup map. - Groups = make(map[string]TestGroup) - // Test defines a TestGroup object. - Test TestGroup - - serializer runtime.SerializerInfo -) - -func init() { - if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 { - var ok bool - mediaType, _, err := mime.ParseMediaType(apiMediaType) - if err != nil { - panic(err) - } - serializer, ok = runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), mediaType) - if !ok { - panic(fmt.Sprintf("no serializer for %s", apiMediaType)) - } - } - - kubeTestAPI := os.Getenv("KUBE_TEST_API") - if len(kubeTestAPI) != 0 { - // priority is "first in list preferred", so this has to run in reverse order - testGroupVersions := strings.Split(kubeTestAPI, ",") - for i := len(testGroupVersions) - 1; i >= 0; i-- { - gvString := testGroupVersions[i] - groupVersion, err := schema.ParseGroupVersion(gvString) - if err != nil { - panic(fmt.Sprintf("Error parsing groupversion %v: %v", gvString, err)) - } - - internalGroupVersion := schema.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal} - Groups[groupVersion.Group] = TestGroup{ - externalGroupVersion: groupVersion, - internalGroupVersion: internalGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(internalGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(groupVersion), - } - } - } - - if _, ok := Groups[api.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: api.GroupName, Version: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.Version} - Groups[api.GroupName] = TestGroup{ - externalGroupVersion: externalGroupVersion, - internalGroupVersion: api.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(api.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), - } - } - - Test = Groups[api.GroupName] -} - -// Codec returns the codec for the API version to test against, as set by the -// KUBE_TEST_API_TYPE env var. -func (g TestGroup) Codec() runtime.Codec { - if serializer.Serializer == nil { - return legacyscheme.Codecs.LegacyCodec(g.externalGroupVersion) - } - return legacyscheme.Codecs.CodecForVersions(serializer.Serializer, legacyscheme.Codecs.UniversalDeserializer(), schema.GroupVersions{g.externalGroupVersion}, nil) -} - -// SelfLink returns a self link that will appear to be for the version Version(). -// 'resource' should be the resource path, e.g. "pods" for the Pod type. 'name' should be -// empty for lists. -func (g TestGroup) SelfLink(resource, name string) string { - if g.externalGroupVersion.Group == api.GroupName { - if name == "" { - return fmt.Sprintf("/api/%s/%s", g.externalGroupVersion.Version, resource) - } - return fmt.Sprintf("/api/%s/%s/%s", g.externalGroupVersion.Version, resource, name) - } - - // TODO: will need a /apis prefix once we have proper multi-group - // support - if name == "" { - return fmt.Sprintf("/apis/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource) - } - return fmt.Sprintf("/apis/%s/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource, name) -} - -// ResourcePathWithPrefix returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name. -// For ex, this is of the form: -// /api/v1/watch/namespaces/foo/pods/pod0 for v1. -func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name string) string { - var path string - if g.externalGroupVersion.Group == api.GroupName { - path = "/api/" + g.externalGroupVersion.Version - } else { - // TODO: switch back once we have proper multiple group support - // path = "/apis/" + g.Group + "/" + Version(group...) - path = "/apis/" + g.externalGroupVersion.Group + "/" + g.externalGroupVersion.Version - } - - if prefix != "" { - path = path + "/" + prefix - } - if namespace != "" { - path = path + "/namespaces/" + namespace - } - // Resource names are lower case. - resource = strings.ToLower(resource) - if resource != "" { - path = path + "/" + resource - } - if name != "" { - path = path + "/" + name - } - return path -} - -// ResourcePath returns the appropriate path for the given resource, namespace and name. -// For example, this is of the form: -// /api/v1/namespaces/foo/pods/pod0 for v1. -func (g TestGroup) ResourcePath(resource, namespace, name string) string { - return g.ResourcePathWithPrefix("", resource, namespace, name) -} - -// SubResourcePath returns the appropriate path for the given resource, namespace, -// name and subresource. -func (g TestGroup) SubResourcePath(resource, namespace, name, sub string) string { - path := g.ResourcePathWithPrefix("", resource, namespace, name) - if sub != "" { - path = path + "/" + sub - } - - return path -} diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/util/testutil_test.go b/vendor/k8s.io/kubernetes/pkg/scheduler/util/testutil_test.go deleted file mode 100644 index 98e76902d..000000000 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/util/testutil_test.go +++ /dev/null @@ -1,214 +0,0 @@ -/* -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 util - -import ( - "encoding/json" - "reflect" - "testing" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -func TestResourcePathWithPrefix(t *testing.T) { - testCases := []struct { - prefix string - resource string - namespace string - name string - expected string - }{ - {"prefix", "resource", "mynamespace", "myresource", "/api/" + Test.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource/myresource"}, - {"prefix", "resource", "", "myresource", "/api/" + Test.externalGroupVersion.Version + "/prefix/resource/myresource"}, - {"prefix", "resource", "mynamespace", "", "/api/" + Test.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource"}, - {"prefix", "resource", "", "", "/api/" + Test.externalGroupVersion.Version + "/prefix/resource"}, - {"", "resource", "mynamespace", "myresource", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - } - for _, item := range testCases { - if actual := Test.ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name) - } - } - - TestGroup := Test - TestGroup.externalGroupVersion.Group = "TestGroup" - - testGroupCases := []struct { - prefix string - resource string - namespace string - name string - expected string - }{ - {"prefix", "resource", "mynamespace", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource/myresource"}, - {"prefix", "resource", "", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/resource/myresource"}, - {"prefix", "resource", "mynamespace", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource"}, - {"prefix", "resource", "", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/resource"}, - {"", "resource", "mynamespace", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - } - for _, item := range testGroupCases { - if actual := TestGroup.ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name) - } - } - -} - -func TestResourcePath(t *testing.T) { - testCases := []struct { - resource string - namespace string - name string - expected string - }{ - {"resource", "mynamespace", "myresource", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - {"resource", "", "myresource", "/api/" + Test.externalGroupVersion.Version + "/resource/myresource"}, - {"resource", "mynamespace", "", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource"}, - {"resource", "", "", "/api/" + Test.externalGroupVersion.Version + "/resource"}, - } - for _, item := range testCases { - if actual := Test.ResourcePath(item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name) - } - } - - TestGroup := Test - TestGroup.externalGroupVersion.Group = "TestGroup" - - testGroupCases := []struct { - resource string - namespace string - name string - expected string - }{ - {"resource", "mynamespace", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - {"resource", "", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource/myresource"}, - {"resource", "mynamespace", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource"}, - {"resource", "", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource"}, - } - for _, item := range testGroupCases { - if actual := TestGroup.ResourcePath(item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name) - } - } - -} - -func TestSubResourcePath(t *testing.T) { - testCases := []struct { - resource string - namespace string - name string - sub string - expected string - }{ - {"resource", "mynamespace", "myresource", "subresource", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource/subresource"}, - {"resource", "mynamespace", "myresource", "", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - } - for _, item := range testCases { - if actual := Test.SubResourcePath(item.resource, item.namespace, item.name, item.sub); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s, name: %s and sub: %s", item.expected, actual, item.resource, item.namespace, item.name, item.sub) - } - } - - TestGroup := Test - TestGroup.externalGroupVersion.Group = "TestGroup" - - testGroupCases := []struct { - resource string - namespace string - name string - sub string - expected string - }{ - {"resource", "mynamespace", "myresource", "subresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource/subresource"}, - {"resource", "mynamespace", "myresource", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - } - for _, item := range testGroupCases { - if actual := TestGroup.SubResourcePath(item.resource, item.namespace, item.name, item.sub); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s, name: %s and sub: %s", item.expected, actual, item.resource, item.namespace, item.name, item.sub) - } - } - -} - -func TestSelfLink(t *testing.T) { - testCases := []struct { - resource string - name string - expected string - }{ - {"resource", "name", "/api/" + Test.externalGroupVersion.Version + "/resource/name"}, - {"resource", "", "/api/" + Test.externalGroupVersion.Version + "/resource"}, - } - for _, item := range testCases { - if actual := Test.SelfLink(item.resource, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s and name: %s", item.expected, actual, item.resource, item.name) - } - } - - TestGroup := Test - TestGroup.externalGroupVersion.Group = "TestGroup" - - testGroupCases := []struct { - resource string - name string - expected string - }{ - {"resource", "name", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource/name"}, - {"resource", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource"}, - } - for _, item := range testGroupCases { - if actual := TestGroup.SelfLink(item.resource, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s and name: %s", item.expected, actual, item.resource, item.name) - } - } -} - -var status = &metav1.Status{ - Status: metav1.StatusFailure, - Code: 200, - Reason: metav1.StatusReasonUnknown, - Message: "", -} - -func TestV1EncodeDecodeStatus(t *testing.T) { - v1Codec := Test.Codec() - - encoded, err := runtime.Encode(v1Codec, status) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - typeMeta := metav1.TypeMeta{} - if err := json.Unmarshal(encoded, &typeMeta); err != nil { - t.Errorf("unexpected error: %v", err) - } - if typeMeta.Kind != "Status" { - t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded)) - } - if typeMeta.APIVersion != "v1" { - t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded)) - } - decoded, err := runtime.Decode(v1Codec, encoded) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(status, decoded) { - t.Errorf("expected: %#v, got: %#v", status, decoded) - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/BUILD b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/BUILD index f2c8a3329..fdfc19bfa 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/BUILD @@ -17,7 +17,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/security/podsecuritypolicy", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", "//pkg/security/podsecuritypolicy/apparmor:go_default_library", "//pkg/security/podsecuritypolicy/capabilities:go_default_library", "//pkg/security/podsecuritypolicy/group:go_default_library", @@ -39,7 +39,7 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/apis/core/v1:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", "//pkg/security/apparmor:go_default_library", "//pkg/security/podsecuritypolicy/seccomp:go_default_library", "//pkg/security/podsecuritypolicy/util:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/BUILD b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/BUILD index cafbaa634..82bab2c5a 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/BUILD @@ -16,7 +16,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], @@ -28,7 +28,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/capabilities.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/capabilities.go index bb713c7be..0e1f41c61 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/capabilities.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/capabilities.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) // defaultCapabilities implements the Strategy interface @@ -100,7 +100,7 @@ func (s *defaultCapabilities) Validate(pod *api.Pod, container *api.Container, c } allowedAdd := makeCapSet(s.allowedCaps) - allowAllCaps := allowedAdd.Has(string(extensions.AllowAllCapabilities)) + allowAllCaps := allowedAdd.Has(string(policy.AllowAllCapabilities)) if allowAllCaps { // skip validation against allowed/defaultAdd/requiredDrop because all capabilities are allowed by a wildcard return allErrs diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/capabilities_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/capabilities_test.go index 56cf5db5a..6f752a031 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/capabilities_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities/capabilities_test.go @@ -21,7 +21,7 @@ import ( "testing" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) func TestGenerateAdds(t *testing.T) { @@ -278,7 +278,7 @@ func TestValidateAdds(t *testing.T) { }, }, "no required, all allowed, container requests valid": { - allowedCaps: []api.Capability{extensions.AllowAllCapabilities}, + allowedCaps: []api.Capability{policy.AllowAllCapabilities}, containerCaps: &api.Capabilities{ Add: []api.Capability{"foo"}, }, diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/factory.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/factory.go index 69cf3945d..05c7f0d8b 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/factory.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/factory.go @@ -21,7 +21,7 @@ import ( "k8s.io/apimachinery/pkg/util/errors" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/apparmor" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/group" @@ -39,7 +39,7 @@ func NewSimpleStrategyFactory() StrategyFactory { return &simpleStrategyFactory{} } -func (f *simpleStrategyFactory) CreateStrategies(psp *extensions.PodSecurityPolicy, namespace string) (*ProviderStrategies, error) { +func (f *simpleStrategyFactory) CreateStrategies(psp *policy.PodSecurityPolicy, namespace string) (*ProviderStrategies, error) { errs := []error{} userStrat, err := createUserStrategy(&psp.Spec.RunAsUser) @@ -77,15 +77,7 @@ func (f *simpleStrategyFactory) CreateStrategies(psp *extensions.PodSecurityPoli errs = append(errs, err) } - var unsafeSysctls []string - if ann, found := psp.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey]; found { - var err error - unsafeSysctls, err = extensions.SysctlsFromPodSecurityPolicyAnnotation(ann) - if err != nil { - errs = append(errs, err) - } - } - sysctlsStrat := createSysctlsStrategy(unsafeSysctls) + sysctlsStrat := createSysctlsStrategy(sysctl.SafeSysctlWhitelist(), psp.Spec.AllowedUnsafeSysctls, psp.Spec.ForbiddenSysctls) if len(errs) > 0 { return nil, errors.NewAggregate(errs) @@ -106,13 +98,13 @@ func (f *simpleStrategyFactory) CreateStrategies(psp *extensions.PodSecurityPoli } // createUserStrategy creates a new user strategy. -func createUserStrategy(opts *extensions.RunAsUserStrategyOptions) (user.RunAsUserStrategy, error) { +func createUserStrategy(opts *policy.RunAsUserStrategyOptions) (user.RunAsUserStrategy, error) { switch opts.Rule { - case extensions.RunAsUserStrategyMustRunAs: + case policy.RunAsUserStrategyMustRunAs: return user.NewMustRunAs(opts) - case extensions.RunAsUserStrategyMustRunAsNonRoot: + case policy.RunAsUserStrategyMustRunAsNonRoot: return user.NewRunAsNonRoot(opts) - case extensions.RunAsUserStrategyRunAsAny: + case policy.RunAsUserStrategyRunAsAny: return user.NewRunAsAny(opts) default: return nil, fmt.Errorf("Unrecognized RunAsUser strategy type %s", opts.Rule) @@ -120,11 +112,11 @@ func createUserStrategy(opts *extensions.RunAsUserStrategyOptions) (user.RunAsUs } // createSELinuxStrategy creates a new selinux strategy. -func createSELinuxStrategy(opts *extensions.SELinuxStrategyOptions) (selinux.SELinuxStrategy, error) { +func createSELinuxStrategy(opts *policy.SELinuxStrategyOptions) (selinux.SELinuxStrategy, error) { switch opts.Rule { - case extensions.SELinuxStrategyMustRunAs: + case policy.SELinuxStrategyMustRunAs: return selinux.NewMustRunAs(opts) - case extensions.SELinuxStrategyRunAsAny: + case policy.SELinuxStrategyRunAsAny: return selinux.NewRunAsAny(opts) default: return nil, fmt.Errorf("Unrecognized SELinuxContext strategy type %s", opts.Rule) @@ -132,21 +124,21 @@ func createSELinuxStrategy(opts *extensions.SELinuxStrategyOptions) (selinux.SEL } // createAppArmorStrategy creates a new AppArmor strategy. -func createAppArmorStrategy(psp *extensions.PodSecurityPolicy) (apparmor.Strategy, error) { +func createAppArmorStrategy(psp *policy.PodSecurityPolicy) (apparmor.Strategy, error) { return apparmor.NewStrategy(psp.Annotations), nil } // createSeccompStrategy creates a new seccomp strategy. -func createSeccompStrategy(psp *extensions.PodSecurityPolicy) (seccomp.Strategy, error) { +func createSeccompStrategy(psp *policy.PodSecurityPolicy) (seccomp.Strategy, error) { return seccomp.NewStrategy(psp.Annotations), nil } // createFSGroupStrategy creates a new fsgroup strategy -func createFSGroupStrategy(opts *extensions.FSGroupStrategyOptions) (group.GroupStrategy, error) { +func createFSGroupStrategy(opts *policy.FSGroupStrategyOptions) (group.GroupStrategy, error) { switch opts.Rule { - case extensions.FSGroupStrategyRunAsAny: + case policy.FSGroupStrategyRunAsAny: return group.NewRunAsAny() - case extensions.FSGroupStrategyMustRunAs: + case policy.FSGroupStrategyMustRunAs: return group.NewMustRunAs(opts.Ranges, fsGroupField) default: return nil, fmt.Errorf("Unrecognized FSGroup strategy type %s", opts.Rule) @@ -154,11 +146,11 @@ func createFSGroupStrategy(opts *extensions.FSGroupStrategyOptions) (group.Group } // createSupplementalGroupStrategy creates a new supplemental group strategy -func createSupplementalGroupStrategy(opts *extensions.SupplementalGroupsStrategyOptions) (group.GroupStrategy, error) { +func createSupplementalGroupStrategy(opts *policy.SupplementalGroupsStrategyOptions) (group.GroupStrategy, error) { switch opts.Rule { - case extensions.SupplementalGroupsStrategyRunAsAny: + case policy.SupplementalGroupsStrategyRunAsAny: return group.NewRunAsAny() - case extensions.SupplementalGroupsStrategyMustRunAs: + case policy.SupplementalGroupsStrategyMustRunAs: return group.NewMustRunAs(opts.Ranges, supplementalGroupsField) default: return nil, fmt.Errorf("Unrecognized SupplementalGroups strategy type %s", opts.Rule) @@ -170,7 +162,7 @@ func createCapabilitiesStrategy(defaultAddCaps, requiredDropCaps, allowedCaps [] return capabilities.NewDefaultCapabilities(defaultAddCaps, requiredDropCaps, allowedCaps) } -// createSysctlsStrategy creates a new unsafe sysctls strategy. -func createSysctlsStrategy(sysctlsPatterns []string) sysctl.SysctlsStrategy { - return sysctl.NewMustMatchPatterns(sysctlsPatterns) +// createSysctlsStrategy creates a new sysctls strategy. +func createSysctlsStrategy(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls []string) sysctl.SysctlsStrategy { + return sysctl.NewMustMatchPatterns(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls) } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/BUILD b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/BUILD index 27e2be78b..7c74b01dd 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/BUILD @@ -17,7 +17,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/security/podsecuritypolicy/group", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", "//pkg/security/podsecuritypolicy/util:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], @@ -30,7 +30,7 @@ go_test( "runasany_test.go", ], embed = [":go_default_library"], - deps = ["//pkg/apis/extensions:go_default_library"], + deps = ["//pkg/apis/policy:go_default_library"], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/mustrunas.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/mustrunas.go index 8fc48ac29..9e2b8b879 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/mustrunas.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/mustrunas.go @@ -21,20 +21,20 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) // mustRunAs implements the GroupStrategy interface type mustRunAs struct { - ranges []extensions.GroupIDRange + ranges []policy.IDRange field string } var _ GroupStrategy = &mustRunAs{} // NewMustRunAs provides a new MustRunAs strategy based on ranges. -func NewMustRunAs(ranges []extensions.GroupIDRange, field string) (GroupStrategy, error) { +func NewMustRunAs(ranges []policy.IDRange, field string) (GroupStrategy, error) { if len(ranges) == 0 { return nil, fmt.Errorf("ranges must be supplied for MustRunAs") } @@ -70,7 +70,7 @@ func (s *mustRunAs) Validate(_ *api.Pod, groups []int64) field.ErrorList { for _, group := range groups { if !s.isGroupValid(group) { - detail := fmt.Sprintf("%d is not an allowed group", group) + detail := fmt.Sprintf("group %d must be in the ranges: %v", group, s.ranges) allErrs = append(allErrs, field.Invalid(field.NewPath(s.field), groups, detail)) } } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/mustrunas_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/mustrunas_test.go index 462344cdd..3d7c17e33 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/mustrunas_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/group/mustrunas_test.go @@ -17,20 +17,22 @@ limitations under the License. package group import ( - "k8s.io/kubernetes/pkg/apis/extensions" + "strings" "testing" + + "k8s.io/kubernetes/pkg/apis/policy" ) func TestMustRunAsOptions(t *testing.T) { tests := map[string]struct { - ranges []extensions.GroupIDRange + ranges []policy.IDRange pass bool }{ "empty": { - ranges: []extensions.GroupIDRange{}, + ranges: []policy.IDRange{}, }, "ranges": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 1}, }, pass: true, @@ -50,23 +52,23 @@ func TestMustRunAsOptions(t *testing.T) { func TestGenerate(t *testing.T) { tests := map[string]struct { - ranges []extensions.GroupIDRange + ranges []policy.IDRange expected []int64 }{ "multi value": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 2}, }, expected: []int64{1}, }, "single value": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 1}, }, expected: []int64{1}, }, "multi range": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 1}, {Min: 2, Max: 500}, }, @@ -108,54 +110,53 @@ func TestGenerate(t *testing.T) { func TestValidate(t *testing.T) { tests := map[string]struct { - ranges []extensions.GroupIDRange - groups []int64 - pass bool + ranges []policy.IDRange + groups []int64 + expectedError string }{ "nil security context": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 3}, }, + expectedError: "unable to validate empty groups against required ranges", }, "empty groups": { - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 3}, }, + expectedError: "unable to validate empty groups against required ranges", }, "not in range": { groups: []int64{5}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 3}, {Min: 4, Max: 4}, }, + expectedError: "group 5 must be in the ranges: [{1 3} {4 4}]", }, "in range 1": { groups: []int64{2}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 3}, }, - pass: true, }, "in range boundary min": { groups: []int64{1}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 3}, }, - pass: true, }, "in range boundary max": { groups: []int64{3}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 1, Max: 3}, }, - pass: true, }, "singular range": { groups: []int64{4}, - ranges: []extensions.GroupIDRange{ + ranges: []policy.IDRange{ {Min: 4, Max: 4}, }, - pass: true, }, } @@ -165,11 +166,14 @@ func TestValidate(t *testing.T) { t.Errorf("error creating strategy for %s: %v", k, err) } errs := s.Validate(nil, v.groups) - if v.pass && len(errs) > 0 { + if v.expectedError == "" && len(errs) > 0 { t.Errorf("unexpected errors for %s: %v", k, errs) } - if !v.pass && len(errs) == 0 { - t.Errorf("expected no errors for %s but got: %v", k, errs) + if v.expectedError != "" && len(errs) == 0 { + t.Errorf("expected errors for %s but got: %v", k, errs) + } + if v.expectedError != "" && len(errs) > 0 && !strings.Contains(errs[0].Error(), v.expectedError) { + t.Errorf("expected error for %s: %v, but got: %v", k, v.expectedError, errs[0]) } } } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/provider.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/provider.go index 8567ecf43..7458eb8a5 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/provider.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/provider.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" "k8s.io/kubernetes/pkg/securitycontext" ) @@ -36,7 +36,7 @@ const ( // simpleProvider is the default implementation of Provider. type simpleProvider struct { - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy strategies *ProviderStrategies } @@ -44,7 +44,7 @@ type simpleProvider struct { var _ Provider = &simpleProvider{} // NewSimpleProvider creates a new Provider instance. -func NewSimpleProvider(psp *extensions.PodSecurityPolicy, namespace string, strategyFactory StrategyFactory) (Provider, error) { +func NewSimpleProvider(psp *policy.PodSecurityPolicy, namespace string, strategyFactory StrategyFactory) (Provider, error) { if psp == nil { return nil, fmt.Errorf("NewSimpleProvider requires a PodSecurityPolicy") } @@ -144,7 +144,7 @@ func (s *simpleProvider) DefaultContainerSecurityContext(pod *api.Pod, container // if we're using the non-root strategy set the marker that this container should not be // run as root which will signal to the kubelet to do a final check either on the runAsUser // or, if runAsUser is not set, the image UID will be checked. - if sc.RunAsNonRoot() == nil && sc.RunAsUser() == nil && s.psp.Spec.RunAsUser.Rule == extensions.RunAsUserStrategyMustRunAsNonRoot { + if sc.RunAsNonRoot() == nil && sc.RunAsUser() == nil && s.psp.Spec.RunAsUser.Rule == policy.RunAsUserStrategyMustRunAsNonRoot { nonRoot := true sc.SetRunAsNonRoot(&nonRoot) } @@ -226,15 +226,38 @@ func (s *simpleProvider) ValidatePod(pod *api.Pod, fldPath *field.Path) field.Er continue } - if fsType == extensions.HostPath { - if !psputil.AllowsHostVolumePath(s.psp, v.HostPath.Path) { + if fsType == policy.HostPath { + allows, mustBeReadOnly := psputil.AllowsHostVolumePath(s.psp, v.HostPath.Path) + if !allows { allErrs = append(allErrs, field.Invalid( field.NewPath("spec", "volumes").Index(i).Child("hostPath", "pathPrefix"), v.HostPath.Path, fmt.Sprintf("is not allowed to be used"))) + } else if mustBeReadOnly { + // Ensure all the VolumeMounts that use this volume are read-only + for i, c := range pod.Spec.InitContainers { + for j, cv := range c.VolumeMounts { + if cv.Name == v.Name && !cv.ReadOnly { + allErrs = append(allErrs, field.Invalid( + field.NewPath("spec", "initContainers").Index(i).Child("volumeMounts").Index(j).Child("readOnly"), + cv.ReadOnly, "must be read-only"), + ) + } + } + } + for i, c := range pod.Spec.Containers { + for j, cv := range c.VolumeMounts { + if cv.Name == v.Name && !cv.ReadOnly { + allErrs = append(allErrs, field.Invalid( + field.NewPath("spec", "containers").Index(i).Child("volumeMounts").Index(j).Child("readOnly"), + cv.ReadOnly, "must be read-only"), + ) + } + } + } } } - if fsType == extensions.FlexVolume && len(s.psp.Spec.AllowedFlexVolumes) > 0 { + if fsType == policy.FlexVolume && len(s.psp.Spec.AllowedFlexVolumes) > 0 { found := false driver := v.FlexVolume.Driver for _, allowedFlexVolume := range s.psp.Spec.AllowedFlexVolumes { @@ -273,10 +296,6 @@ func (s *simpleProvider) ValidateContainerSecurityContext(pod *api.Pod, containe allErrs = append(allErrs, s.strategies.CapabilitiesStrategy.Validate(pod, container, sc.Capabilities())...) - if !s.psp.Spec.HostNetwork && podSC.HostNetwork() { - allErrs = append(allErrs, field.Invalid(fldPath.Child("hostNetwork"), podSC.HostNetwork(), "Host network is not allowed to be used")) - } - containersPath := fldPath.Child("containers") for idx, c := range pod.Spec.Containers { idxPath := containersPath.Index(idx) @@ -289,14 +308,6 @@ func (s *simpleProvider) ValidateContainerSecurityContext(pod *api.Pod, containe allErrs = append(allErrs, s.hasInvalidHostPort(&c, idxPath)...) } - if !s.psp.Spec.HostPID && podSC.HostPID() { - allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPID"), podSC.HostPID(), "Host PID is not allowed to be used")) - } - - if !s.psp.Spec.HostIPC && podSC.HostIPC() { - allErrs = append(allErrs, field.Invalid(fldPath.Child("hostIPC"), podSC.HostIPC(), "Host IPC is not allowed to be used")) - } - if s.psp.Spec.ReadOnlyRootFilesystem { readOnly := sc.ReadOnlyRootFilesystem() if readOnly == nil { @@ -345,7 +356,7 @@ func (s *simpleProvider) GetPSPName() string { return s.psp.Name } -func hostPortRangesToString(ranges []extensions.HostPortRange) string { +func hostPortRangesToString(ranges []policy.HostPortRange) string { formattedString := "" if ranges != nil { strRanges := []string{} diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/provider_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/provider_test.go index aabaf9ffb..a7b8174a9 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/provider_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/provider_test.go @@ -30,7 +30,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/security/apparmor" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" @@ -49,27 +49,27 @@ func TestDefaultPodSecurityContextNonmutating(t *testing.T) { } // Create a PSP with strategies that will populate a blank psc - createPSP := func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ + createPSP := func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "psp-sa", Annotations: map[string]string{ seccomp.AllowedProfilesAnnotationKey: "*", }, }, - Spec: extensions.PodSecurityPolicySpec{ + Spec: policy.PodSecurityPolicySpec{ AllowPrivilegeEscalation: true, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } @@ -120,8 +120,8 @@ func TestDefaultContainerSecurityContextNonmutating(t *testing.T) { } // Create a PSP with strategies that will populate a blank security context - createPSP := func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ + createPSP := func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "psp-sa", Annotations: map[string]string{ @@ -129,19 +129,19 @@ func TestDefaultContainerSecurityContextNonmutating(t *testing.T) { seccomp.DefaultProfileAnnotationKey: "foo", }, }, - Spec: extensions.PodSecurityPolicySpec{ + Spec: policy.PodSecurityPolicySpec{ AllowPrivilegeEscalation: true, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } @@ -184,9 +184,9 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { failSupplementalGroupPod := defaultPod() failSupplementalGroupPod.Spec.SecurityContext.SupplementalGroups = []int64{999} failSupplementalGroupPSP := defaultPSP() - failSupplementalGroupPSP.Spec.SupplementalGroups = extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + failSupplementalGroupPSP.Spec.SupplementalGroups = policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyMustRunAs, + Ranges: []policy.IDRange{ {Min: 1, Max: 1}, }, } @@ -195,16 +195,16 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { fsGroup := int64(999) failFSGroupPod.Spec.SecurityContext.FSGroup = &fsGroup failFSGroupPSP := defaultPSP() - failFSGroupPSP.Spec.FSGroup = extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + failFSGroupPSP.Spec.FSGroup = policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyMustRunAs, + Ranges: []policy.IDRange{ {Min: 1, Max: 1}, }, } failNilSELinuxPod := defaultPod() failSELinuxPSP := defaultPSP() - failSELinuxPSP.Spec.SELinux.Rule = extensions.SELinuxStrategyMustRunAs + failSELinuxPSP.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs failSELinuxPSP.Spec.SELinux.SELinuxOptions = &api.SELinuxOptions{ Level: "foo", } @@ -236,22 +236,65 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { }, } failHostPathDirPSP := defaultPSP() - failHostPathDirPSP.Spec.Volumes = []extensions.FSType{extensions.HostPath} - failHostPathDirPSP.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ + failHostPathDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath} + failHostPathDirPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ {PathPrefix: "/foo/bar"}, } - failOtherSysctlsAllowedPSP := defaultPSP() - failOtherSysctlsAllowedPSP.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "bar,abc" + failHostPathReadOnlyPod := defaultPod() + failHostPathReadOnlyPod.Spec.Containers[0].VolumeMounts = []api.VolumeMount{ + { + Name: "bad volume", + ReadOnly: false, + }, + } + failHostPathReadOnlyPod.Spec.Volumes = []api.Volume{ + { + Name: "bad volume", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/foo", + }, + }, + }, + } + failHostPathReadOnlyPSP := defaultPSP() + failHostPathReadOnlyPSP.Spec.Volumes = []policy.FSType{policy.HostPath} + failHostPathReadOnlyPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ + { + PathPrefix: "/foo", + ReadOnly: true, + }, + } - failNoSysctlAllowedPSP := defaultPSP() - failNoSysctlAllowedPSP.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "" + failSysctlDisallowedPSP := defaultPSP() + failSysctlDisallowedPSP.Spec.ForbiddenSysctls = []string{"kernel.shm_rmid_forced"} - failSafeSysctlFooPod := defaultPod() - failSafeSysctlFooPod.Annotations[api.SysctlsPodAnnotationKey] = "foo=1" + failNoSafeSysctlAllowedPSP := defaultPSP() + failNoSafeSysctlAllowedPSP.Spec.ForbiddenSysctls = []string{"*"} - failUnsafeSysctlFooPod := defaultPod() - failUnsafeSysctlFooPod.Annotations[api.UnsafeSysctlsPodAnnotationKey] = "foo=1" + failAllUnsafeSysctlsPSP := defaultPSP() + failAllUnsafeSysctlsPSP.Spec.AllowedUnsafeSysctls = []string{} + + failSafeSysctlKernelPod := defaultPod() + failSafeSysctlKernelPod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: "kernel.shm_rmid_forced", + Value: "1", + }, + }, + } + + failUnsafeSysctlPod := defaultPod() + failUnsafeSysctlPod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: "kernel.sem", + Value: "32000", + }, + }, + } failSeccompProfilePod := defaultPod() failSeccompProfilePod.Annotations = map[string]string{api.SeccompPodAnnotationKey: "foo"} @@ -270,7 +313,7 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { errorCases := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy expectedError string }{ "failHostNetwork": { @@ -291,7 +334,7 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { "failSupplementalGroupOutOfRange": { pod: failSupplementalGroupPod, psp: failSupplementalGroupPSP, - expectedError: "999 is not an allowed group", + expectedError: "group 999 must be in the ranges: [{1 1}]", }, "failSupplementalGroupEmpty": { pod: defaultPod(), @@ -301,7 +344,7 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { "failFSGroupOutOfRange": { pod: failFSGroupPod, psp: failFSGroupPSP, - expectedError: "999 is not an allowed group", + expectedError: "group 999 must be in the ranges: [{1 1}]", }, "failFSGroupEmpty": { pod: defaultPod(), @@ -328,25 +371,25 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { psp: failHostPathDirPSP, expectedError: "is not allowed to be used", }, - "failSafeSysctlFooPod with failNoSysctlAllowedSCC": { - pod: failSafeSysctlFooPod, - psp: failNoSysctlAllowedPSP, - expectedError: "sysctls are not allowed", + "failHostPathReadOnlyPSP": { + pod: failHostPathReadOnlyPod, + psp: failHostPathReadOnlyPSP, + expectedError: "must be read-only", }, - "failUnsafeSysctlFooPod with failNoSysctlAllowedSCC": { - pod: failUnsafeSysctlFooPod, - psp: failNoSysctlAllowedPSP, - expectedError: "sysctls are not allowed", + "failSafeSysctlKernelPod with failNoSafeSysctlAllowedPSP": { + pod: failSafeSysctlKernelPod, + psp: failNoSafeSysctlAllowedPSP, + expectedError: "sysctl \"kernel.shm_rmid_forced\" is not allowed", }, - "failSafeSysctlFooPod with failOtherSysctlsAllowedSCC": { - pod: failSafeSysctlFooPod, - psp: failOtherSysctlsAllowedPSP, - expectedError: "sysctl \"foo\" is not allowed", + "failSafeSysctlKernelPod with failSysctlDisallowedPSP": { + pod: failSafeSysctlKernelPod, + psp: failSysctlDisallowedPSP, + expectedError: "sysctl \"kernel.shm_rmid_forced\" is not allowed", }, - "failUnsafeSysctlFooPod with failOtherSysctlsAllowedSCC": { - pod: failUnsafeSysctlFooPod, - psp: failOtherSysctlsAllowedPSP, - expectedError: "sysctl \"foo\" is not allowed", + "failUnsafeSysctlPod with failAllUnsafeSysctlsPSP": { + pod: failUnsafeSysctlPod, + psp: failAllUnsafeSysctlsPSP, + expectedError: "unsafe sysctl \"kernel.sem\" is not allowed", }, "failInvalidSeccomp": { pod: failSeccompProfilePod, @@ -380,24 +423,24 @@ func TestValidatePodSecurityContextFailures(t *testing.T) { } } -func allowFlexVolumesPSP(allowAllFlexVolumes, allowAllVolumes bool) *extensions.PodSecurityPolicy { +func allowFlexVolumesPSP(allowAllFlexVolumes, allowAllVolumes bool) *policy.PodSecurityPolicy { psp := defaultPSP() - allowedVolumes := []extensions.AllowedFlexVolume{ + allowedVolumes := []policy.AllowedFlexVolume{ {Driver: "example/foo"}, {Driver: "example/bar"}, } if allowAllFlexVolumes { - allowedVolumes = []extensions.AllowedFlexVolume{} + allowedVolumes = []policy.AllowedFlexVolume{} } - allowedVolumeType := extensions.FlexVolume + allowedVolumeType := policy.FlexVolume if allowAllVolumes { - allowedVolumeType = extensions.All + allowedVolumeType = policy.All } psp.Spec.AllowedFlexVolumes = allowedVolumes - psp.Spec.Volumes = []extensions.FSType{allowedVolumeType} + psp.Spec.Volumes = []policy.FSType{allowedVolumeType} return psp } @@ -407,17 +450,17 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) { failUserPSP := defaultPSP() uid := int64(999) badUID := int64(1) - failUserPSP.Spec.RunAsUser = extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyMustRunAs, - Ranges: []extensions.UserIDRange{{Min: uid, Max: uid}}, + failUserPSP.Spec.RunAsUser = policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyMustRunAs, + Ranges: []policy.IDRange{{Min: uid, Max: uid}}, } failUserPod := defaultPod() failUserPod.Spec.Containers[0].SecurityContext.RunAsUser = &badUID // fail selinux strategy failSELinuxPSP := defaultPSP() - failSELinuxPSP.Spec.SELinux = extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyMustRunAs, + failSELinuxPSP.Spec.SELinux = policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyMustRunAs, SELinuxOptions: &api.SELinuxOptions{ Level: "foo", }, @@ -469,7 +512,7 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) { errorCases := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy expectedError string }{ "failUserPSP": { @@ -562,9 +605,9 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { hostIPCPod.Spec.SecurityContext.HostIPC = true supGroupPSP := defaultPSP() - supGroupPSP.Spec.SupplementalGroups = extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + supGroupPSP.Spec.SupplementalGroups = policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyMustRunAs, + Ranges: []policy.IDRange{ {Min: 1, Max: 5}, }, } @@ -572,9 +615,9 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { supGroupPod.Spec.SecurityContext.SupplementalGroups = []int64{3} fsGroupPSP := defaultPSP() - fsGroupPSP.Spec.FSGroup = extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + fsGroupPSP.Spec.FSGroup = policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyMustRunAs, + Ranges: []policy.IDRange{ {Min: 1, Max: 5}, }, } @@ -590,7 +633,7 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { Level: "level", } seLinuxPSP := defaultPSP() - seLinuxPSP.Spec.SELinux.Rule = extensions.SELinuxStrategyMustRunAs + seLinuxPSP.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs seLinuxPSP.Spec.SELinux.SELinuxOptions = &api.SELinuxOptions{ User: "user", Role: "role", @@ -598,38 +641,107 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { Level: "level", } + hostPathDirPodVolumeMounts := []api.VolumeMount{ + { + Name: "writeable /foo/bar", + ReadOnly: false, + }, + { + Name: "read only /foo/bar/baz", + ReadOnly: true, + }, + { + Name: "parent read only volume", + ReadOnly: true, + }, + { + Name: "read only child volume", + ReadOnly: true, + }, + } + hostPathDirPod := defaultPod() + hostPathDirPod.Spec.InitContainers = []api.Container{ + { + Name: defaultContainerName, + VolumeMounts: hostPathDirPodVolumeMounts, + }, + } + + hostPathDirPod.Spec.Containers[0].VolumeMounts = hostPathDirPodVolumeMounts hostPathDirPod.Spec.Volumes = []api.Volume{ { - Name: "good volume", + Name: "writeable /foo/bar", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/foo/bar", + }, + }, + }, + { + Name: "read only /foo/bar/baz", VolumeSource: api.VolumeSource{ HostPath: &api.HostPathVolumeSource{ Path: "/foo/bar/baz", }, }, }, + { + Name: "parent read only volume", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/foo/", + }, + }, + }, + { + Name: "read only child volume", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/foo/readonly/child", + }, + }, + }, } hostPathDirPSP := defaultPSP() - hostPathDirPSP.Spec.Volumes = []extensions.FSType{extensions.HostPath} - hostPathDirPSP.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ - {PathPrefix: "/foo/bar"}, + hostPathDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath} + hostPathDirPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ + // overlapping test case where child is different than parent directory. + {PathPrefix: "/foo/bar/baz", ReadOnly: true}, + {PathPrefix: "/foo", ReadOnly: true}, + {PathPrefix: "/foo/bar", ReadOnly: false}, } hostPathDirAsterisksPSP := defaultPSP() - hostPathDirAsterisksPSP.Spec.Volumes = []extensions.FSType{extensions.All} - hostPathDirAsterisksPSP.Spec.AllowedHostPaths = []extensions.AllowedHostPath{ - {PathPrefix: "/foo/bar"}, + hostPathDirAsterisksPSP.Spec.Volumes = []policy.FSType{policy.All} + hostPathDirAsterisksPSP.Spec.AllowedHostPaths = []policy.AllowedHostPath{ + {PathPrefix: "/foo"}, } - sysctlAllowFooPSP := defaultPSP() - sysctlAllowFooPSP.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "foo" + sysctlAllowAllPSP := defaultPSP() + sysctlAllowAllPSP.Spec.ForbiddenSysctls = []string{} + sysctlAllowAllPSP.Spec.AllowedUnsafeSysctls = []string{"*"} - safeSysctlFooPod := defaultPod() - safeSysctlFooPod.Annotations[api.SysctlsPodAnnotationKey] = "foo=1" + safeSysctlKernelPod := defaultPod() + safeSysctlKernelPod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: "kernel.shm_rmid_forced", + Value: "1", + }, + }, + } - unsafeSysctlFooPod := defaultPod() - unsafeSysctlFooPod.Annotations[api.UnsafeSysctlsPodAnnotationKey] = "foo=1" + unsafeSysctlKernelPod := defaultPod() + unsafeSysctlKernelPod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: "kernel.sem", + Value: "32000", + }, + }, + } seccompPSP := defaultPSP() seccompPSP.Annotations = map[string]string{ @@ -655,7 +767,7 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { successCases := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy }{ "pass hostNetwork validating PSP": { pod: hostNetworkPod, @@ -681,21 +793,13 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) { pod: seLinuxPod, psp: seLinuxPSP, }, - "pass sysctl specific profile with safe sysctl": { - pod: safeSysctlFooPod, - psp: sysctlAllowFooPSP, + "pass sysctl specific profile with safe kernel sysctl": { + pod: safeSysctlKernelPod, + psp: sysctlAllowAllPSP, }, - "pass sysctl specific profile with unsafe sysctl": { - pod: unsafeSysctlFooPod, - psp: sysctlAllowFooPSP, - }, - "pass empty profile with safe sysctl": { - pod: safeSysctlFooPod, - psp: defaultPSP(), - }, - "pass empty profile with unsafe sysctl": { - pod: unsafeSysctlFooPod, - psp: defaultPSP(), + "pass sysctl specific profile with unsafe kernel sysctl": { + pod: unsafeSysctlKernelPod, + psp: sysctlAllowAllPSP, }, "pass hostDir allowed directory validating PSP": { pod: hostPathDirPod, @@ -744,17 +848,17 @@ func TestValidateContainerSecurityContextSuccess(t *testing.T) { // success user strategy userPSP := defaultPSP() uid := int64(999) - userPSP.Spec.RunAsUser = extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyMustRunAs, - Ranges: []extensions.UserIDRange{{Min: uid, Max: uid}}, + userPSP.Spec.RunAsUser = policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyMustRunAs, + Ranges: []policy.IDRange{{Min: uid, Max: uid}}, } userPod := defaultPod() userPod.Spec.Containers[0].SecurityContext.RunAsUser = &uid // success selinux strategy seLinuxPSP := defaultPSP() - seLinuxPSP.Spec.SELinux = extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyMustRunAs, + seLinuxPSP.Spec.SELinux = policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyMustRunAs, SELinuxOptions: &api.SELinuxOptions{ Level: "foo", }, @@ -795,7 +899,7 @@ func TestValidateContainerSecurityContextSuccess(t *testing.T) { } hostDirPSP := defaultPSP() - hostDirPSP.Spec.Volumes = []extensions.FSType{extensions.HostPath} + hostDirPSP.Spec.Volumes = []policy.FSType{policy.HostPath} hostDirPod := defaultPod() hostDirPod.Spec.Volumes = []api.Volume{ { @@ -807,7 +911,7 @@ func TestValidateContainerSecurityContextSuccess(t *testing.T) { } hostPortPSP := defaultPSP() - hostPortPSP.Spec.HostPorts = []extensions.HostPortRange{{Min: 1, Max: 1}} + hostPortPSP.Spec.HostPorts = []policy.HostPortRange{{Min: 1, Max: 1}} hostPortPod := defaultPod() hostPortPod.Spec.Containers[0].Ports = []api.ContainerPort{{HostPort: 1}} @@ -836,7 +940,7 @@ func TestValidateContainerSecurityContextSuccess(t *testing.T) { successCases := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy }{ "pass user must run as PSP": { pod: userPod, @@ -922,7 +1026,7 @@ func TestGenerateContainerSecurityContextReadOnlyRootFS(t *testing.T) { tests := map[string]struct { pod *api.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy expected *bool }{ "false psp, nil sc": { @@ -985,24 +1089,24 @@ func TestGenerateContainerSecurityContextReadOnlyRootFS(t *testing.T) { } } -func defaultPSP() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ +func defaultPSP() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "psp-sa", Annotations: map[string]string{}, }, - Spec: extensions.PodSecurityPolicySpec{ - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, AllowPrivilegeEscalation: true, }, @@ -1017,7 +1121,7 @@ func defaultPod() *api.Pod { }, Spec: api.PodSpec{ SecurityContext: &api.PodSecurityContext{ - // fill in for test cases + // fill in for test cases }, Containers: []api.Container{ { @@ -1041,7 +1145,7 @@ func defaultV1Pod() *v1.Pod { }, Spec: v1.PodSpec{ SecurityContext: &v1.PodSecurityContext{ - // fill in for test cases + // fill in for test cases }, Containers: []v1.Container{ { @@ -1104,14 +1208,14 @@ func TestValidateAllowedVolumes(t *testing.T) { } // now add the fstype directly to the psp and it should validate - psp.Spec.Volumes = []extensions.FSType{fsType} + psp.Spec.Volumes = []policy.FSType{fsType} errs = provider.ValidatePod(pod, field.NewPath("")) if len(errs) != 0 { t.Errorf("directly allowing volume expected no errors for %s but got %v", fieldVal.Name, errs) } // now change the psp to allow any volumes and the pod should still validate - psp.Spec.Volumes = []extensions.FSType{extensions.All} + psp.Spec.Volumes = []policy.FSType{policy.All} errs = provider.ValidatePod(pod, field.NewPath("")) if len(errs) != 0 { t.Errorf("wildcard volume expected no errors for %s but got %v", fieldVal.Name, errs) diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/BUILD b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/BUILD index c86629123..23db6e068 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/BUILD @@ -17,7 +17,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", "//pkg/security/podsecuritypolicy/util:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], @@ -32,7 +32,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/mustrunas.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/mustrunas.go index 67f23b995..e958555ff 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/mustrunas.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/mustrunas.go @@ -23,17 +23,17 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) type mustRunAs struct { - opts *extensions.SELinuxStrategyOptions + opts *policy.SELinuxStrategyOptions } var _ SELinuxStrategy = &mustRunAs{} -func NewMustRunAs(options *extensions.SELinuxStrategyOptions) (SELinuxStrategy, error) { +func NewMustRunAs(options *policy.SELinuxStrategyOptions) (SELinuxStrategy, error) { if options == nil { return nil, fmt.Errorf("MustRunAs requires SELinuxContextStrategyOptions") } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/mustrunas_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/mustrunas_test.go index 4c57df737..41fbce7b3 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/mustrunas_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/mustrunas_test.go @@ -18,7 +18,7 @@ package selinux import ( api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "reflect" "strings" "testing" @@ -26,15 +26,19 @@ import ( func TestMustRunAsOptions(t *testing.T) { tests := map[string]struct { - opts *extensions.SELinuxStrategyOptions + opts *policy.SELinuxStrategyOptions pass bool }{ + "nil opts": { + opts: nil, + pass: false, + }, "invalid opts": { - opts: &extensions.SELinuxStrategyOptions{}, + opts: &policy.SELinuxStrategyOptions{}, pass: false, }, "valid opts": { - opts: &extensions.SELinuxStrategyOptions{SELinuxOptions: &api.SELinuxOptions{}}, + opts: &policy.SELinuxStrategyOptions{SELinuxOptions: &api.SELinuxOptions{}}, pass: true, }, } @@ -50,7 +54,7 @@ func TestMustRunAsOptions(t *testing.T) { } func TestMustRunAsGenerate(t *testing.T) { - opts := &extensions.SELinuxStrategyOptions{ + opts := &policy.SELinuxStrategyOptions{ SELinuxOptions: &api.SELinuxOptions{ User: "user", Role: "role", @@ -141,7 +145,7 @@ func TestMustRunAsValidate(t *testing.T) { } for name, tc := range tests { - opts := &extensions.SELinuxStrategyOptions{ + opts := &policy.SELinuxStrategyOptions{ SELinuxOptions: tc.pspSeLinux, } mustRunAs, err := NewMustRunAs(opts) diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/runasany.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/runasany.go index 008ad0a41..63e590c7c 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/runasany.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/runasany.go @@ -19,7 +19,7 @@ package selinux import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) // runAsAny implements the SELinuxStrategy interface. @@ -28,7 +28,7 @@ type runAsAny struct{} var _ SELinuxStrategy = &runAsAny{} // NewRunAsAny provides a strategy that will return the configured se linux context or nil. -func NewRunAsAny(options *extensions.SELinuxStrategyOptions) (SELinuxStrategy, error) { +func NewRunAsAny(options *policy.SELinuxStrategyOptions) (SELinuxStrategy, error) { return &runAsAny{}, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/runasany_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/runasany_test.go index 8e1a7f1b0..71ff38505 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/runasany_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/selinux/runasany_test.go @@ -18,7 +18,7 @@ package selinux import ( api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "testing" ) @@ -27,14 +27,14 @@ func TestRunAsAnyOptions(t *testing.T) { if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } - _, err = NewRunAsAny(&extensions.SELinuxStrategyOptions{}) + _, err = NewRunAsAny(&policy.SELinuxStrategyOptions{}) if err != nil { t.Errorf("unexpected error initializing NewRunAsAny %v", err) } } func TestRunAsAnyGenerate(t *testing.T) { - s, err := NewRunAsAny(&extensions.SELinuxStrategyOptions{}) + s, err := NewRunAsAny(&policy.SELinuxStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } @@ -48,7 +48,7 @@ func TestRunAsAnyGenerate(t *testing.T) { } func TestRunAsAnyValidate(t *testing.T) { - s, err := NewRunAsAny(&extensions.SELinuxStrategyOptions{ + s, err := NewRunAsAny(&policy.SELinuxStrategyOptions{ SELinuxOptions: &api.SELinuxOptions{ Level: "foo", }, @@ -61,7 +61,7 @@ func TestRunAsAnyValidate(t *testing.T) { if len(errs) != 0 { t.Errorf("unexpected errors validating with ") } - s, err = NewRunAsAny(&extensions.SELinuxStrategyOptions{}) + s, err = NewRunAsAny(&policy.SELinuxStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/BUILD b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/BUILD index b466cbbeb..445907ccf 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/BUILD @@ -15,7 +15,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], ) @@ -24,10 +23,7 @@ go_test( name = "go_default_test", srcs = ["mustmatchpatterns_test.go"], embed = [":go_default_library"], - deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", - ], + deps = ["//pkg/apis/core:go_default_library"], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns.go index b59dd9d3f..6c33276c5 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns.go @@ -22,12 +22,26 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" ) +// SafeSysctlWhitelist returns the whitelist of safe sysctls and safe sysctl patterns (ending in *). +// +// A sysctl is called safe iff +// - it is namespaced in the container or the pod +// - it is isolated, i.e. has no influence on any other pod on the same node. +func SafeSysctlWhitelist() []string { + return []string{ + "kernel.shm_rmid_forced", + "net.ipv4.ip_local_port_range", + "net.ipv4.tcp_syncookies", + } +} + // mustMatchPatterns implements the SysctlsStrategy interface type mustMatchPatterns struct { - patterns []string + safeWhitelist []string + allowedUnsafeSysctls []string + forbiddenSysctls []string } var ( @@ -38,56 +52,75 @@ var ( // NewMustMatchPatterns creates a new mustMatchPatterns strategy that will provide validation. // Passing nil means the default pattern, passing an empty list means to disallow all sysctls. -func NewMustMatchPatterns(patterns []string) SysctlsStrategy { - if patterns == nil { - patterns = defaultSysctlsPatterns - } +func NewMustMatchPatterns(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls []string) SysctlsStrategy { return &mustMatchPatterns{ - patterns: patterns, + safeWhitelist: safeWhitelist, + allowedUnsafeSysctls: allowedUnsafeSysctls, + forbiddenSysctls: forbiddenSysctls, } } -// Validate ensures that the specified values fall within the range of the strategy. -func (s *mustMatchPatterns) Validate(pod *api.Pod) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, s.validateAnnotation(pod, api.SysctlsPodAnnotationKey)...) - allErrs = append(allErrs, s.validateAnnotation(pod, api.UnsafeSysctlsPodAnnotationKey)...) - return allErrs +func (s *mustMatchPatterns) isForbidden(sysctlName string) bool { + // Is the sysctl forbidden? + for _, s := range s.forbiddenSysctls { + if strings.HasSuffix(s, "*") { + prefix := strings.TrimSuffix(s, "*") + if strings.HasPrefix(sysctlName, prefix) { + return true + } + } else if sysctlName == s { + return true + } + } + return false } -func (s *mustMatchPatterns) validateAnnotation(pod *api.Pod, key string) field.ErrorList { - allErrs := field.ErrorList{} - - fieldPath := field.NewPath("pod", "metadata", "annotations").Key(key) - - sysctls, err := helper.SysctlsFromPodAnnotation(pod.Annotations[key]) - if err != nil { - allErrs = append(allErrs, field.Invalid(fieldPath, pod.Annotations[key], err.Error())) +func (s *mustMatchPatterns) isSafe(sysctlName string) bool { + for _, ws := range s.safeWhitelist { + if sysctlName == ws { + return true + } } + return false +} - if len(sysctls) > 0 { - if len(s.patterns) == 0 { - allErrs = append(allErrs, field.Invalid(fieldPath, pod.Annotations[key], "sysctls are not allowed")) - } else { - for i, sysctl := range sysctls { - allErrs = append(allErrs, s.ValidateSysctl(sysctl.Name, fieldPath.Index(i))...) +func (s *mustMatchPatterns) isAllowedUnsafe(sysctlName string) bool { + for _, s := range s.allowedUnsafeSysctls { + if strings.HasSuffix(s, "*") { + prefix := strings.TrimSuffix(s, "*") + if strings.HasPrefix(sysctlName, prefix) { + return true } + } else if sysctlName == s { + return true } } - - return allErrs + return false } -func (s *mustMatchPatterns) ValidateSysctl(sysctlName string, fldPath *field.Path) field.ErrorList { - for _, s := range s.patterns { - if s[len(s)-1] == '*' { - prefix := s[:len(s)-1] - if strings.HasPrefix(sysctlName, string(prefix)) { - return nil - } - } else if sysctlName == s { - return nil +// Validate ensures that the specified values fall within the range of the strategy. +func (s *mustMatchPatterns) Validate(pod *api.Pod) field.ErrorList { + allErrs := field.ErrorList{} + + var sysctls []api.Sysctl + if pod.Spec.SecurityContext != nil { + sysctls = pod.Spec.SecurityContext.Sysctls + } + + fieldPath := field.NewPath("pod", "spec", "securityContext").Child("sysctls") + + for i, sysctl := range sysctls { + switch { + case s.isForbidden(sysctl.Name): + allErrs = append(allErrs, field.ErrorList{field.Forbidden(fieldPath.Index(i), fmt.Sprintf("sysctl %q is not allowed", sysctl.Name))}...) + case s.isSafe(sysctl.Name): + continue + case s.isAllowedUnsafe(sysctl.Name): + continue + default: + allErrs = append(allErrs, field.ErrorList{field.Forbidden(fieldPath.Index(i), fmt.Sprintf("unsafe sysctl %q is not allowed", sysctl.Name))}...) } } - return field.ErrorList{field.Forbidden(fldPath, fmt.Sprintf("sysctl %q is not allowed", sysctlName))} + + return allErrs } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns_test.go index 7622c8266..9bc7b0c6a 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl/mustmatchpatterns_test.go @@ -17,48 +17,47 @@ limitations under the License. package sysctl import ( - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" "testing" + + api "k8s.io/kubernetes/pkg/apis/core" ) func TestValidate(t *testing.T) { tests := map[string]struct { - patterns []string - allowed []string - disallowed []string + whitelist []string + forbiddenSafe []string + allowedUnsafe []string + allowed []string + disallowed []string }{ // no container requests - "nil": { - patterns: nil, - allowed: []string{"foo"}, + "with allow all": { + whitelist: []string{"foo"}, + allowed: []string{"foo"}, }, "empty": { - patterns: []string{}, - disallowed: []string{"foo"}, + whitelist: []string{"foo"}, + forbiddenSafe: []string{"*"}, + disallowed: []string{"foo"}, }, "without wildcard": { - patterns: []string{"a", "a.b"}, + whitelist: []string{"a", "a.b"}, allowed: []string{"a", "a.b"}, disallowed: []string{"b"}, }, - "with catch-all wildcard": { - patterns: []string{"*"}, - allowed: []string{"a", "a.b"}, - }, "with catch-all wildcard and non-wildcard": { - patterns: []string{"a.b.c", "*"}, - allowed: []string{"a", "a.b", "a.b.c", "b"}, + allowedUnsafe: []string{"a.b.c", "*"}, + allowed: []string{"a", "a.b", "a.b.c", "b"}, }, "without catch-all wildcard": { - patterns: []string{"a.*", "b.*", "c.d.e", "d.e.f.*"}, - allowed: []string{"a.b", "b.c", "c.d.e", "d.e.f.g.h"}, - disallowed: []string{"a", "b", "c", "c.d", "d.e", "d.e.f"}, + allowedUnsafe: []string{"a.*", "b.*", "c.d.e", "d.e.f.*"}, + allowed: []string{"a.b", "b.c", "c.d.e", "d.e.f.g.h"}, + disallowed: []string{"a", "b", "c", "c.d", "d.e", "d.e.f"}, }, } for k, v := range tests { - strategy := NewMustMatchPatterns(v.patterns) + strategy := NewMustMatchPatterns(v.whitelist, v.allowedUnsafe, v.forbiddenSafe) pod := &api.Pod{} errs := strategy.Validate(pod) @@ -66,37 +65,40 @@ func TestValidate(t *testing.T) { t.Errorf("%s: unexpected validaton errors for empty sysctls: %v", k, errs) } - sysctls := []api.Sysctl{} - for _, s := range v.allowed { - sysctls = append(sysctls, api.Sysctl{ - Name: s, - Value: "dummy", - }) - } - testAllowed := func(key string, category string) { - pod.Annotations = map[string]string{ - key: helper.PodAnnotationsFromSysctls(sysctls), + testAllowed := func() { + sysctls := []api.Sysctl{} + for _, s := range v.allowed { + sysctls = append(sysctls, api.Sysctl{ + Name: s, + Value: "dummy", + }) + } + pod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: sysctls, } errs = strategy.Validate(pod) if len(errs) != 0 { - t.Errorf("%s: unexpected validaton errors for %s sysctls: %v", k, category, errs) + t.Errorf("%s: unexpected validaton errors for sysctls: %v", k, errs) } } - testDisallowed := func(key string, category string) { + testDisallowed := func() { for _, s := range v.disallowed { - pod.Annotations = map[string]string{ - key: helper.PodAnnotationsFromSysctls([]api.Sysctl{{Name: s, Value: "dummy"}}), + pod.Spec.SecurityContext = &api.PodSecurityContext{ + Sysctls: []api.Sysctl{ + { + Name: s, + Value: "dummy", + }, + }, } errs = strategy.Validate(pod) if len(errs) == 0 { - t.Errorf("%s: expected error for %s sysctl %q", k, category, s) + t.Errorf("%s: expected error for sysctl %q", k, s) } } } - testAllowed(api.SysctlsPodAnnotationKey, "safe") - testAllowed(api.UnsafeSysctlsPodAnnotationKey, "unsafe") - testDisallowed(api.SysctlsPodAnnotationKey, "safe") - testDisallowed(api.UnsafeSysctlsPodAnnotationKey, "unsafe") + testAllowed() + testDisallowed() } } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/types.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/types.go index c839c680e..ee7fdae1e 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/types.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/types.go @@ -19,7 +19,7 @@ package podsecuritypolicy import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/apparmor" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/capabilities" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/group" @@ -54,7 +54,7 @@ type Provider interface { type StrategyFactory interface { // CreateStrategies creates the strategies that a provider will use. The namespace argument // should be the namespace of the object being checked (the pod's namespace). - CreateStrategies(psp *extensions.PodSecurityPolicy, namespace string) (*ProviderStrategies, error) + CreateStrategies(psp *policy.PodSecurityPolicy, namespace string) (*ProviderStrategies, error) } // ProviderStrategies is a holder for all strategies that the provider requires to be populated. diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/BUILD b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/BUILD index 03ebcfeea..64a5cac0a 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/BUILD @@ -18,7 +18,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/security/podsecuritypolicy/user", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", "//pkg/security/podsecuritypolicy/util:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], @@ -34,7 +34,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/mustrunas.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/mustrunas.go index 6b0ed1397..fdcf519ed 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/mustrunas.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/mustrunas.go @@ -21,22 +21,22 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" ) // mustRunAs implements the RunAsUserStrategy interface type mustRunAs struct { - opts *extensions.RunAsUserStrategyOptions + opts *policy.RunAsUserStrategyOptions } // NewMustRunAs provides a strategy that requires the container to run as a specific UID in a range. -func NewMustRunAs(options *extensions.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { +func NewMustRunAs(options *policy.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { if options == nil { - return nil, fmt.Errorf("MustRunAsRange requires run as user options") + return nil, fmt.Errorf("MustRunAs requires run as user options") } if len(options.Ranges) == 0 { - return nil, fmt.Errorf("MustRunAsRange requires at least one range") + return nil, fmt.Errorf("MustRunAs requires at least one range") } return &mustRunAs{ opts: options, diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/mustrunas_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/mustrunas_test.go index 5a0a77037..f8358fb07 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/mustrunas_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/mustrunas_test.go @@ -18,14 +18,14 @@ package user import ( api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "strings" "testing" ) func TestNewMustRunAs(t *testing.T) { tests := map[string]struct { - opts *extensions.RunAsUserStrategyOptions + opts *policy.RunAsUserStrategyOptions pass bool }{ "nil opts": { @@ -33,12 +33,12 @@ func TestNewMustRunAs(t *testing.T) { pass: false, }, "invalid opts": { - opts: &extensions.RunAsUserStrategyOptions{}, + opts: &policy.RunAsUserStrategyOptions{}, pass: false, }, "valid opts": { - opts: &extensions.RunAsUserStrategyOptions{ - Ranges: []extensions.UserIDRange{ + opts: &policy.RunAsUserStrategyOptions{ + Ranges: []policy.IDRange{ {Min: 1, Max: 1}, }, }, @@ -57,8 +57,8 @@ func TestNewMustRunAs(t *testing.T) { } func TestGenerate(t *testing.T) { - opts := &extensions.RunAsUserStrategyOptions{ - Ranges: []extensions.UserIDRange{ + opts := &policy.RunAsUserStrategyOptions{ + Ranges: []policy.IDRange{ {Min: 1, Max: 1}, }, } @@ -76,8 +76,8 @@ func TestGenerate(t *testing.T) { } func TestValidate(t *testing.T) { - opts := &extensions.RunAsUserStrategyOptions{ - Ranges: []extensions.UserIDRange{ + opts := &policy.RunAsUserStrategyOptions{ + Ranges: []policy.IDRange{ {Min: 1, Max: 1}, {Min: 10, Max: 20}, }, diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/nonroot.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/nonroot.go index 68e644a7e..64c32caa0 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/nonroot.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/nonroot.go @@ -19,14 +19,14 @@ package user import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) type nonRoot struct{} var _ RunAsUserStrategy = &nonRoot{} -func NewRunAsNonRoot(options *extensions.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { +func NewRunAsNonRoot(options *policy.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { return &nonRoot{}, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/nonroot_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/nonroot_test.go index 1597af008..4a02f3f41 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/nonroot_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/nonroot_test.go @@ -18,7 +18,7 @@ package user import ( api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" "testing" ) @@ -27,14 +27,14 @@ func TestNonRootOptions(t *testing.T) { if err != nil { t.Fatalf("unexpected error initializing NewRunAsNonRoot %v", err) } - _, err = NewRunAsNonRoot(&extensions.RunAsUserStrategyOptions{}) + _, err = NewRunAsNonRoot(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Errorf("unexpected error initializing NewRunAsNonRoot %v", err) } } func TestNonRootGenerate(t *testing.T) { - s, err := NewRunAsNonRoot(&extensions.RunAsUserStrategyOptions{}) + s, err := NewRunAsNonRoot(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsNonRoot %v", err) } @@ -52,7 +52,7 @@ func TestNonRootValidate(t *testing.T) { badUID := int64(0) untrue := false unfalse := true - s, err := NewRunAsNonRoot(&extensions.RunAsUserStrategyOptions{}) + s, err := NewRunAsNonRoot(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewMustRunAs %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/runasany.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/runasany.go index e1384f2da..935338978 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/runasany.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/runasany.go @@ -19,7 +19,7 @@ package user import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) // runAsAny implements the interface RunAsUserStrategy. @@ -28,7 +28,7 @@ type runAsAny struct{} var _ RunAsUserStrategy = &runAsAny{} // NewRunAsAny provides a strategy that will return nil. -func NewRunAsAny(options *extensions.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { +func NewRunAsAny(options *policy.RunAsUserStrategyOptions) (RunAsUserStrategy, error) { return &runAsAny{}, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/runasany_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/runasany_test.go index 9a3181b48..43b02b698 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/runasany_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/user/runasany_test.go @@ -19,7 +19,7 @@ package user import ( "testing" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) func TestRunAsAnyOptions(t *testing.T) { @@ -27,14 +27,14 @@ func TestRunAsAnyOptions(t *testing.T) { if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } - _, err = NewRunAsAny(&extensions.RunAsUserStrategyOptions{}) + _, err = NewRunAsAny(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Errorf("unexpected error initializing NewRunAsAny %v", err) } } func TestRunAsAnyGenerate(t *testing.T) { - s, err := NewRunAsAny(&extensions.RunAsUserStrategyOptions{}) + s, err := NewRunAsAny(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } @@ -48,7 +48,7 @@ func TestRunAsAnyGenerate(t *testing.T) { } func TestRunAsAnyValidate(t *testing.T) { - s, err := NewRunAsAny(&extensions.RunAsUserStrategyOptions{}) + s, err := NewRunAsAny(&policy.RunAsUserStrategyOptions{}) if err != nil { t.Fatalf("unexpected error initializing NewRunAsAny %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/BUILD b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/BUILD index aa2d98053..24c8ec07c 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/BUILD @@ -15,7 +15,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", ], ) @@ -26,7 +26,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", + "//pkg/apis/policy:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/util.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/util.go index d581f5012..3f29f6e7a 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/util.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/util.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/policy" ) const ( @@ -40,102 +40,102 @@ func GetAllFSTypesExcept(exceptions ...string) sets.String { func GetAllFSTypesAsSet() sets.String { fstypes := sets.NewString() fstypes.Insert( - string(extensions.HostPath), - string(extensions.AzureFile), - string(extensions.Flocker), - string(extensions.FlexVolume), - string(extensions.EmptyDir), - string(extensions.GCEPersistentDisk), - string(extensions.AWSElasticBlockStore), - string(extensions.GitRepo), - string(extensions.Secret), - string(extensions.NFS), - string(extensions.ISCSI), - string(extensions.Glusterfs), - string(extensions.PersistentVolumeClaim), - string(extensions.RBD), - string(extensions.Cinder), - string(extensions.CephFS), - string(extensions.DownwardAPI), - string(extensions.FC), - string(extensions.ConfigMap), - string(extensions.VsphereVolume), - string(extensions.Quobyte), - string(extensions.AzureDisk), - string(extensions.PhotonPersistentDisk), - string(extensions.StorageOS), - string(extensions.Projected), - string(extensions.PortworxVolume), - string(extensions.ScaleIO), - string(extensions.CSI), + string(policy.HostPath), + string(policy.AzureFile), + string(policy.Flocker), + string(policy.FlexVolume), + string(policy.EmptyDir), + string(policy.GCEPersistentDisk), + string(policy.AWSElasticBlockStore), + string(policy.GitRepo), + string(policy.Secret), + string(policy.NFS), + string(policy.ISCSI), + string(policy.Glusterfs), + string(policy.PersistentVolumeClaim), + string(policy.RBD), + string(policy.Cinder), + string(policy.CephFS), + string(policy.DownwardAPI), + string(policy.FC), + string(policy.ConfigMap), + string(policy.VsphereVolume), + string(policy.Quobyte), + string(policy.AzureDisk), + string(policy.PhotonPersistentDisk), + string(policy.StorageOS), + string(policy.Projected), + string(policy.PortworxVolume), + string(policy.ScaleIO), + string(policy.CSI), ) return fstypes } // getVolumeFSType gets the FSType for a volume. -func GetVolumeFSType(v api.Volume) (extensions.FSType, error) { +func GetVolumeFSType(v api.Volume) (policy.FSType, error) { switch { case v.HostPath != nil: - return extensions.HostPath, nil + return policy.HostPath, nil case v.EmptyDir != nil: - return extensions.EmptyDir, nil + return policy.EmptyDir, nil case v.GCEPersistentDisk != nil: - return extensions.GCEPersistentDisk, nil + return policy.GCEPersistentDisk, nil case v.AWSElasticBlockStore != nil: - return extensions.AWSElasticBlockStore, nil + return policy.AWSElasticBlockStore, nil case v.GitRepo != nil: - return extensions.GitRepo, nil + return policy.GitRepo, nil case v.Secret != nil: - return extensions.Secret, nil + return policy.Secret, nil case v.NFS != nil: - return extensions.NFS, nil + return policy.NFS, nil case v.ISCSI != nil: - return extensions.ISCSI, nil + return policy.ISCSI, nil case v.Glusterfs != nil: - return extensions.Glusterfs, nil + return policy.Glusterfs, nil case v.PersistentVolumeClaim != nil: - return extensions.PersistentVolumeClaim, nil + return policy.PersistentVolumeClaim, nil case v.RBD != nil: - return extensions.RBD, nil + return policy.RBD, nil case v.FlexVolume != nil: - return extensions.FlexVolume, nil + return policy.FlexVolume, nil case v.Cinder != nil: - return extensions.Cinder, nil + return policy.Cinder, nil case v.CephFS != nil: - return extensions.CephFS, nil + return policy.CephFS, nil case v.Flocker != nil: - return extensions.Flocker, nil + return policy.Flocker, nil case v.DownwardAPI != nil: - return extensions.DownwardAPI, nil + return policy.DownwardAPI, nil case v.FC != nil: - return extensions.FC, nil + return policy.FC, nil case v.AzureFile != nil: - return extensions.AzureFile, nil + return policy.AzureFile, nil case v.ConfigMap != nil: - return extensions.ConfigMap, nil + return policy.ConfigMap, nil case v.VsphereVolume != nil: - return extensions.VsphereVolume, nil + return policy.VsphereVolume, nil case v.Quobyte != nil: - return extensions.Quobyte, nil + return policy.Quobyte, nil case v.AzureDisk != nil: - return extensions.AzureDisk, nil + return policy.AzureDisk, nil case v.PhotonPersistentDisk != nil: - return extensions.PhotonPersistentDisk, nil + return policy.PhotonPersistentDisk, nil case v.StorageOS != nil: - return extensions.StorageOS, nil + return policy.StorageOS, nil case v.Projected != nil: - return extensions.Projected, nil + return policy.Projected, nil case v.PortworxVolume != nil: - return extensions.PortworxVolume, nil + return policy.PortworxVolume, nil case v.ScaleIO != nil: - return extensions.ScaleIO, nil + return policy.ScaleIO, nil } return "", fmt.Errorf("unknown volume type for volume: %#v", v) } // FSTypeToStringSet converts an FSType slice to a string set. -func FSTypeToStringSet(fsTypes []extensions.FSType) sets.String { +func FSTypeToStringSet(fsTypes []policy.FSType) sets.String { set := sets.NewString() for _, v := range fsTypes { set.Insert(string(v)) @@ -144,19 +144,19 @@ func FSTypeToStringSet(fsTypes []extensions.FSType) sets.String { } // PSPAllowsAllVolumes checks for FSTypeAll in the psp's allowed volumes. -func PSPAllowsAllVolumes(psp *extensions.PodSecurityPolicy) bool { - return PSPAllowsFSType(psp, extensions.All) +func PSPAllowsAllVolumes(psp *policy.PodSecurityPolicy) bool { + return PSPAllowsFSType(psp, policy.All) } // PSPAllowsFSType is a utility for checking if a PSP allows a particular FSType. // If all volumes are allowed then this will return true for any FSType passed. -func PSPAllowsFSType(psp *extensions.PodSecurityPolicy, fsType extensions.FSType) bool { +func PSPAllowsFSType(psp *policy.PodSecurityPolicy, fsType policy.FSType) bool { if psp == nil { return false } for _, v := range psp.Spec.Volumes { - if v == fsType || v == extensions.All { + if v == fsType || v == policy.All { return true } } @@ -164,34 +164,38 @@ func PSPAllowsFSType(psp *extensions.PodSecurityPolicy, fsType extensions.FSType } // UserFallsInRange is a utility to determine it the id falls in the valid range. -func UserFallsInRange(id int64, rng extensions.UserIDRange) bool { +func UserFallsInRange(id int64, rng policy.IDRange) bool { return id >= rng.Min && id <= rng.Max } // GroupFallsInRange is a utility to determine it the id falls in the valid range. -func GroupFallsInRange(id int64, rng extensions.GroupIDRange) bool { +func GroupFallsInRange(id int64, rng policy.IDRange) bool { return id >= rng.Min && id <= rng.Max } // AllowsHostVolumePath is a utility for checking if a PSP allows the host volume path. // This only checks the path. You should still check to make sure the host volume fs type is allowed. -func AllowsHostVolumePath(psp *extensions.PodSecurityPolicy, hostPath string) bool { +func AllowsHostVolumePath(psp *policy.PodSecurityPolicy, hostPath string) (pathIsAllowed, mustBeReadOnly bool) { if psp == nil { - return false + return false, false } // If no allowed paths are specified then allow any path if len(psp.Spec.AllowedHostPaths) == 0 { - return true + return true, false } for _, allowedPath := range psp.Spec.AllowedHostPaths { if hasPathPrefix(hostPath, allowedPath.PathPrefix) { - return true + if !allowedPath.ReadOnly { + return true, allowedPath.ReadOnly + } + pathIsAllowed = true + mustBeReadOnly = true } } - return false + return pathIsAllowed, mustBeReadOnly } // hasPathPrefix returns true if the string matches pathPrefix exactly, or if is prefixed with pathPrefix at a path segment boundary diff --git a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/util_test.go b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/util_test.go index 12e0970d7..f3d099d30 100644 --- a/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/security/podsecuritypolicy/util/util_test.go @@ -17,10 +17,11 @@ limitations under the License. package util import ( - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/extensions" "reflect" "testing" + + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/policy" ) // TestVolumeSourceFSTypeDrift ensures that for every known type of volume source (by the fields on @@ -52,45 +53,45 @@ func TestVolumeSourceFSTypeDrift(t *testing.T) { func TestPSPAllowsFSType(t *testing.T) { tests := map[string]struct { - psp *extensions.PodSecurityPolicy - fsType extensions.FSType + psp *policy.PodSecurityPolicy + fsType policy.FSType allows bool }{ "nil psp": { psp: nil, - fsType: extensions.HostPath, + fsType: policy.HostPath, allows: false, }, "empty volumes": { - psp: &extensions.PodSecurityPolicy{}, - fsType: extensions.HostPath, + psp: &policy.PodSecurityPolicy{}, + fsType: policy.HostPath, allows: false, }, "non-matching": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - Volumes: []extensions.FSType{extensions.AWSElasticBlockStore}, + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + Volumes: []policy.FSType{policy.AWSElasticBlockStore}, }, }, - fsType: extensions.HostPath, + fsType: policy.HostPath, allows: false, }, "match on FSTypeAll": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - Volumes: []extensions.FSType{extensions.All}, + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + Volumes: []policy.FSType{policy.All}, }, }, - fsType: extensions.HostPath, + fsType: policy.HostPath, allows: true, }, "match on direct match": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - Volumes: []extensions.FSType{extensions.HostPath}, + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + Volumes: []policy.FSType{policy.HostPath}, }, }, - fsType: extensions.HostPath, + fsType: policy.HostPath, allows: true, }, } @@ -105,92 +106,113 @@ func TestPSPAllowsFSType(t *testing.T) { func TestAllowsHostVolumePath(t *testing.T) { tests := map[string]struct { - psp *extensions.PodSecurityPolicy - path string - allows bool + psp *policy.PodSecurityPolicy + path string + allows bool + mustBeReadOnly bool }{ "nil psp": { - psp: nil, - path: "/test", - allows: false, + psp: nil, + path: "/test", + allows: false, + mustBeReadOnly: false, }, "empty allowed paths": { - psp: &extensions.PodSecurityPolicy{}, - path: "/test", - allows: true, + psp: &policy.PodSecurityPolicy{}, + path: "/test", + allows: true, + mustBeReadOnly: false, }, "non-matching": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ - {PathPrefix: "/foo"}, + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ + { + PathPrefix: "/foo", + ReadOnly: true, + }, }, }, }, - path: "/foobar", - allows: false, + path: "/foobar", + allows: false, + mustBeReadOnly: false, }, "match on direct match": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ - {PathPrefix: "/foo"}, + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ + { + PathPrefix: "/foo", + ReadOnly: true, + }, }, }, }, - path: "/foo", - allows: true, + path: "/foo", + allows: true, + mustBeReadOnly: true, }, "match with trailing slash on host path": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ {PathPrefix: "/foo"}, }, }, }, - path: "/foo/", - allows: true, + path: "/foo/", + allows: true, + mustBeReadOnly: false, }, "match with trailing slash on allowed path": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ {PathPrefix: "/foo/"}, }, }, }, - path: "/foo", - allows: true, + path: "/foo", + allows: true, + mustBeReadOnly: false, }, "match child directory": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ - {PathPrefix: "/foo/"}, + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ + { + PathPrefix: "/foo/", + ReadOnly: true, + }, }, }, }, - path: "/foo/bar", - allows: true, + path: "/foo/bar", + allows: true, + mustBeReadOnly: true, }, "non-matching parent directory": { - psp: &extensions.PodSecurityPolicy{ - Spec: extensions.PodSecurityPolicySpec{ - AllowedHostPaths: []extensions.AllowedHostPath{ + psp: &policy.PodSecurityPolicy{ + Spec: policy.PodSecurityPolicySpec{ + AllowedHostPaths: []policy.AllowedHostPath{ {PathPrefix: "/foo/bar"}, }, }, }, - path: "/foo", - allows: false, + path: "/foo", + allows: false, + mustBeReadOnly: false, }, } for k, v := range tests { - allows := AllowsHostVolumePath(v.psp, v.path) + allows, mustBeReadOnly := AllowsHostVolumePath(v.psp, v.path) if v.allows != allows { - t.Errorf("%s expected %t but got %t", k, v.allows, allows) + t.Errorf("allows: %s expected %t but got %t", k, v.allows, allows) + } + if v.mustBeReadOnly != mustBeReadOnly { + t.Errorf("mustBeReadOnly: %s expected %t but got %t", k, v.mustBeReadOnly, mustBeReadOnly) } } } diff --git a/vendor/k8s.io/kubernetes/pkg/securitycontext/util.go b/vendor/k8s.io/kubernetes/pkg/securitycontext/util.go index 38377f40f..5ade55881 100644 --- a/vendor/k8s.io/kubernetes/pkg/securitycontext/util.go +++ b/vendor/k8s.io/kubernetes/pkg/securitycontext/util.go @@ -67,27 +67,6 @@ func ParseSELinuxOptions(context string) (*v1.SELinuxOptions, error) { }, nil } -// HasNonRootUID returns true if the runAsUser is set and is greater than 0. -func HasRootUID(container *v1.Container) bool { - if container.SecurityContext == nil { - return false - } - if container.SecurityContext.RunAsUser == nil { - return false - } - return *container.SecurityContext.RunAsUser == 0 -} - -// HasRunAsUser determines if the sc's runAsUser field is set. -func HasRunAsUser(container *v1.Container) bool { - return container.SecurityContext != nil && container.SecurityContext.RunAsUser != nil -} - -// HasRootRunAsUser returns true if the run as user is set and it is set to 0. -func HasRootRunAsUser(container *v1.Container) bool { - return HasRunAsUser(container) && HasRootUID(container) -} - func DetermineEffectiveSecurityContext(pod *v1.Pod, container *v1.Container) *v1.SecurityContext { effectiveSc := securityContextFromPodSecurityContext(pod) containerSc := container.SecurityContext diff --git a/vendor/k8s.io/kubernetes/pkg/securitycontext/util_test.go b/vendor/k8s.io/kubernetes/pkg/securitycontext/util_test.go index 5cc3fa71a..475356c40 100644 --- a/vendor/k8s.io/kubernetes/pkg/securitycontext/util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/securitycontext/util_test.go @@ -84,99 +84,6 @@ func compareContexts(name string, ex, ac *v1.SELinuxOptions, t *testing.T) { } } -func containerWithUser(ptr *int64) *v1.Container { - return &v1.Container{SecurityContext: &v1.SecurityContext{RunAsUser: ptr}} -} - -func TestHaRootUID(t *testing.T) { - nonRoot := int64(1) - root := int64(0) - - tests := map[string]struct { - container *v1.Container - expect bool - }{ - "nil sc": { - container: &v1.Container{SecurityContext: nil}, - }, - "nil runAsuser": { - container: containerWithUser(nil), - }, - "runAsUser non-root": { - container: containerWithUser(&nonRoot), - }, - "runAsUser root": { - container: containerWithUser(&root), - expect: true, - }, - } - - for k, v := range tests { - actual := HasRootUID(v.container) - if actual != v.expect { - t.Errorf("%s failed, expected %t but received %t", k, v.expect, actual) - } - } -} - -func TestHasRunAsUser(t *testing.T) { - runAsUser := int64(0) - - tests := map[string]struct { - container *v1.Container - expect bool - }{ - "nil sc": { - container: &v1.Container{SecurityContext: nil}, - }, - "nil runAsUser": { - container: containerWithUser(nil), - }, - "valid runAsUser": { - container: containerWithUser(&runAsUser), - expect: true, - }, - } - - for k, v := range tests { - actual := HasRunAsUser(v.container) - if actual != v.expect { - t.Errorf("%s failed, expected %t but received %t", k, v.expect, actual) - } - } -} - -func TestHasRootRunAsUser(t *testing.T) { - nonRoot := int64(1) - root := int64(0) - - tests := map[string]struct { - container *v1.Container - expect bool - }{ - "nil sc": { - container: &v1.Container{SecurityContext: nil}, - }, - "nil runAsuser": { - container: containerWithUser(nil), - }, - "runAsUser non-root": { - container: containerWithUser(&nonRoot), - }, - "runAsUser root": { - container: containerWithUser(&root), - expect: true, - }, - } - - for k, v := range tests { - actual := HasRootRunAsUser(v.container) - if actual != v.expect { - t.Errorf("%s failed, expected %t but received %t", k, v.expect, actual) - } - } -} - func TestAddNoNewPrivileges(t *testing.T) { pfalse := false ptrue := true diff --git a/vendor/k8s.io/kubernetes/pkg/serviceaccount/BUILD b/vendor/k8s.io/kubernetes/pkg/serviceaccount/BUILD index eaa64787b..63ddcf928 100644 --- a/vendor/k8s.io/kubernetes/pkg/serviceaccount/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/serviceaccount/BUILD @@ -36,7 +36,6 @@ go_test( "//pkg/controller/serviceaccount:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", "//vendor/k8s.io/client-go/util/cert:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/serviceaccount/OWNERS b/vendor/k8s.io/kubernetes/pkg/serviceaccount/OWNERS index c799f8b6a..b2ae9a659 100644 --- a/vendor/k8s.io/kubernetes/pkg/serviceaccount/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/serviceaccount/OWNERS @@ -1,6 +1,7 @@ approvers: - liggitt - deads2k +- mikedanese reviewers: - liggitt - deads2k diff --git a/vendor/k8s.io/kubernetes/pkg/serviceaccount/claims.go b/vendor/k8s.io/kubernetes/pkg/serviceaccount/claims.go index c3ed29c4c..9acc6ccc1 100644 --- a/vendor/k8s.io/kubernetes/pkg/serviceaccount/claims.go +++ b/vendor/k8s.io/kubernetes/pkg/serviceaccount/claims.go @@ -155,8 +155,8 @@ func (v *validator) Validate(_ string, public *jwt.Claims, privateObj interface{ glog.V(4).Infof("Bound secret is deleted and awaiting removal: %s/%s for service account %s/%s", namespace, secref.Name, namespace, saref.Name) return "", "", "", errors.New("Token has been invalidated") } - if string(secref.UID) != secref.UID { - glog.V(4).Infof("Secret UID no longer matches %s/%s: %q != %q", namespace, secref.Name, string(serviceAccount.UID), secref.UID) + if secref.UID != string(secret.UID) { + glog.V(4).Infof("Secret UID no longer matches %s/%s: %q != %q", namespace, secref.Name, string(secret.UID), secref.UID) return "", "", "", fmt.Errorf("Secret UID (%s) does not match claim (%s)", secret.UID, secref.UID) } } @@ -172,8 +172,8 @@ func (v *validator) Validate(_ string, public *jwt.Claims, privateObj interface{ glog.V(4).Infof("Bound pod is deleted and awaiting removal: %s/%s for service account %s/%s", namespace, podref.Name, namespace, saref.Name) return "", "", "", errors.New("Token has been invalidated") } - if string(podref.UID) != podref.UID { - glog.V(4).Infof("Pod UID no longer matches %s/%s: %q != %q", namespace, podref.Name, string(serviceAccount.UID), podref.UID) + if podref.UID != string(pod.UID) { + glog.V(4).Infof("Pod UID no longer matches %s/%s: %q != %q", namespace, podref.Name, string(pod.UID), podref.UID) return "", "", "", fmt.Errorf("Pod UID (%s) does not match claim (%s)", pod.UID, podref.UID) } } diff --git a/vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt.go b/vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt.go index 01c369a31..73960d7f1 100644 --- a/vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt.go +++ b/vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt.go @@ -22,7 +22,6 @@ import ( "crypto/rsa" "encoding/base64" "encoding/json" - "errors" "fmt" "strings" @@ -140,8 +139,6 @@ type Validator interface { NewPrivateClaims() interface{} } -var errMismatchedSigningMethod = errors.New("invalid signing method") - func (j *jwtTokenAuthenticator) AuthenticateToken(tokenData string) (user.Info, bool, error) { if !j.hasCorrectIssuer(tokenData) { return nil, false, nil diff --git a/vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt_test.go b/vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt_test.go index a8cffd9f3..0f0c52f0f 100644 --- a/vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt_test.go +++ b/vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt_test.go @@ -22,7 +22,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" certutil "k8s.io/client-go/util/cert" @@ -304,22 +303,3 @@ func TestTokenGenerateAndValidate(t *testing.T) { } } } - -func TestMakeSplitUsername(t *testing.T) { - username := apiserverserviceaccount.MakeUsername("ns", "name") - ns, name, err := apiserverserviceaccount.SplitUsername(username) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - if ns != "ns" || name != "name" { - t.Errorf("Expected ns/name, got %s/%s", ns, name) - } - - invalid := []string{"test", "system:serviceaccount", "system:serviceaccount:", "system:serviceaccount:ns", "system:serviceaccount:ns:name:extra"} - for _, n := range invalid { - _, _, err := apiserverserviceaccount.SplitUsername("test") - if err == nil { - t.Errorf("Expected error for %s", n) - } - } -} diff --git a/vendor/k8s.io/kubernetes/pkg/ssh/ssh.go b/vendor/k8s.io/kubernetes/pkg/ssh/ssh.go index c138acb32..dc8aa3acc 100644 --- a/vendor/k8s.io/kubernetes/pkg/ssh/ssh.go +++ b/vendor/k8s.io/kubernetes/pkg/ssh/ssh.go @@ -18,6 +18,7 @@ package ssh import ( "bytes" + "context" "crypto/rand" "crypto/rsa" "crypto/tls" @@ -121,10 +122,11 @@ func (s *SSHTunnel) Open() error { return err } -func (s *SSHTunnel) Dial(network, address string) (net.Conn, error) { +func (s *SSHTunnel) Dial(ctx context.Context, network, address string) (net.Conn, error) { if s.client == nil { return nil, errors.New("tunnel is not opened.") } + // This Dial method does not allow to pass a context unfortunately return s.client.Dial(network, address) } @@ -294,7 +296,7 @@ func ParsePublicKeyFromFile(keyFile string) (*rsa.PublicKey, error) { type tunnel interface { Open() error Close() error - Dial(network, address string) (net.Conn, error) + Dial(ctx context.Context, network, address string) (net.Conn, error) } type sshTunnelEntry struct { @@ -361,7 +363,7 @@ func (l *SSHTunnelList) delayedHealthCheck(e sshTunnelEntry, delay time.Duration func (l *SSHTunnelList) healthCheck(e sshTunnelEntry) error { // GET the healthcheck path using the provided tunnel's dial function. transport := utilnet.SetTransportDefaults(&http.Transport{ - Dial: e.Tunnel.Dial, + DialContext: e.Tunnel.Dial, // TODO(cjcullen): Plumb real TLS options through. TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // We don't reuse the clients, so disable the keep-alive to properly @@ -394,18 +396,18 @@ func (l *SSHTunnelList) removeAndReAdd(e sshTunnelEntry) { go l.createAndAddTunnel(e.Address) } -func (l *SSHTunnelList) Dial(net, addr string) (net.Conn, error) { +func (l *SSHTunnelList) Dial(ctx context.Context, net, addr string) (net.Conn, error) { start := time.Now() id := mathrand.Int63() // So you can match begins/ends in the log. glog.Infof("[%x: %v] Dialing...", id, addr) defer func() { - glog.Infof("[%x: %v] Dialed in %v.", id, addr, time.Now().Sub(start)) + glog.Infof("[%x: %v] Dialed in %v.", id, addr, time.Since(start)) }() tunnel, err := l.pickTunnel(strings.Split(addr, ":")[0]) if err != nil { return nil, err } - return tunnel.Dial(net, addr) + return tunnel.Dial(ctx, net, addr) } func (l *SSHTunnelList) pickTunnel(addr string) (tunnel, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/ssh/ssh_test.go b/vendor/k8s.io/kubernetes/pkg/ssh/ssh_test.go index 3d9dcdb30..a8098973d 100644 --- a/vendor/k8s.io/kubernetes/pkg/ssh/ssh_test.go +++ b/vendor/k8s.io/kubernetes/pkg/ssh/ssh_test.go @@ -17,6 +17,7 @@ limitations under the License. package ssh import ( + "context" "fmt" "io" "net" @@ -145,7 +146,7 @@ func TestSSHTunnel(t *testing.T) { t.FailNow() } - _, err = tunnel.Dial("tcp", "127.0.0.1:8080") + _, err = tunnel.Dial(context.Background(), "tcp", "127.0.0.1:8080") if err != nil { t.Errorf("unexpected error: %v", err) } @@ -176,7 +177,7 @@ func (*fakeTunnel) Close() error { return nil } -func (*fakeTunnel) Dial(network, address string) (net.Conn, error) { +func (*fakeTunnel) Dial(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/util/BUILD b/vendor/k8s.io/kubernetes/pkg/util/BUILD index 1622fe715..27bee9d6c 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/util/BUILD @@ -45,6 +45,7 @@ filegroup( "//pkg/util/nsenter:all-srcs", "//pkg/util/oom:all-srcs", "//pkg/util/parsers:all-srcs", + "//pkg/util/pod:all-srcs", "//pkg/util/pointer:all-srcs", "//pkg/util/procfs:all-srcs", "//pkg/util/reflector/prometheus:all-srcs", diff --git a/vendor/k8s.io/kubernetes/pkg/util/configz/configz.go b/vendor/k8s.io/kubernetes/pkg/util/configz/configz.go index cc2aa3a9f..99413d5e7 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/configz/configz.go +++ b/vendor/k8s.io/kubernetes/pkg/util/configz/configz.go @@ -19,7 +19,6 @@ package configz import ( "encoding/json" "fmt" - "io" "net/http" "sync" ) @@ -74,7 +73,7 @@ func handle(w http.ResponseWriter, r *http.Request) { } } -func write(w io.Writer) error { +func write(w http.ResponseWriter) error { var b []byte var err error func() { @@ -85,6 +84,7 @@ func write(w io.Writer) error { if err != nil { return fmt.Errorf("error marshaling json: %v", err) } + w.Header().Set("Content-Type", "application/json") _, err = w.Write(b) return err } diff --git a/vendor/k8s.io/kubernetes/pkg/util/configz/configz_test.go b/vendor/k8s.io/kubernetes/pkg/util/configz/configz_test.go index 78f22593d..850739df2 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/configz/configz_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/configz/configz_test.go @@ -44,7 +44,7 @@ func TestConfigz(t *testing.T) { t.Fatalf("err: %v", err) } if string(body) != `{"testing":"blah"}` { - t.Fatalf("unexpected output: %v", err) + t.Fatalf("unexpected output: %s", body) } v.Set("bing") @@ -58,7 +58,7 @@ func TestConfigz(t *testing.T) { t.Fatalf("err: %v", err) } if string(body) != `{"testing":"bing"}` { - t.Fatalf("unexpected output: %v", err) + t.Fatalf("unexpected output: %s", body) } Delete("testing") @@ -72,6 +72,9 @@ func TestConfigz(t *testing.T) { t.Fatalf("err: %v", err) } if string(body) != `{}` { - t.Fatalf("unexpected output: %v", err) + t.Fatalf("unexpected output: %s", body) + } + if resp.Header.Get("Content-Type") != "application/json" { + t.Fatalf("unexpected Content-Type: %s", resp.Header.Get("Content-Type")) } } diff --git a/vendor/k8s.io/kubernetes/pkg/util/filesystem/defaultfs.go b/vendor/k8s.io/kubernetes/pkg/util/filesystem/defaultfs.go index f87fe3d6d..f621be83e 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/filesystem/defaultfs.go +++ b/vendor/k8s.io/kubernetes/pkg/util/filesystem/defaultfs.go @@ -72,6 +72,11 @@ func (DefaultFs) ReadFile(filename string) ([]byte, error) { return ioutil.ReadFile(filename) } +// TempDir via ioutil.TempDir +func (DefaultFs) TempDir(dir, prefix string) (string, error) { + return ioutil.TempDir(dir, prefix) +} + // TempFile via ioutil.TempFile func (DefaultFs) TempFile(dir, prefix string) (File, error) { file, err := ioutil.TempFile(dir, prefix) diff --git a/vendor/k8s.io/kubernetes/pkg/util/filesystem/fakefs.go b/vendor/k8s.io/kubernetes/pkg/util/filesystem/fakefs.go index b103007a5..d86b31b6a 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/filesystem/fakefs.go +++ b/vendor/k8s.io/kubernetes/pkg/util/filesystem/fakefs.go @@ -68,6 +68,11 @@ func (fs *fakeFs) ReadFile(filename string) ([]byte, error) { return fs.a.ReadFile(filename) } +// TempDir via afero.TempDir +func (fs *fakeFs) TempDir(dir, prefix string) (string, error) { + return fs.a.TempDir(dir, prefix) +} + // TempFile via afero.TempFile func (fs *fakeFs) TempFile(dir, prefix string) (File, error) { file, err := fs.a.TempFile(dir, prefix) diff --git a/vendor/k8s.io/kubernetes/pkg/util/filesystem/filesystem.go b/vendor/k8s.io/kubernetes/pkg/util/filesystem/filesystem.go index 16e329b30..9b25e14b9 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/filesystem/filesystem.go +++ b/vendor/k8s.io/kubernetes/pkg/util/filesystem/filesystem.go @@ -35,6 +35,7 @@ type Filesystem interface { // from "io/ioutil" ReadFile(filename string) ([]byte, error) + TempDir(dir, prefix string) (string, error) TempFile(dir, prefix string) (File, error) ReadDir(dirname string) ([]os.FileInfo, error) Walk(root string, walkFn filepath.WalkFunc) error diff --git a/vendor/k8s.io/kubernetes/pkg/util/initsystem/initsystem.go b/vendor/k8s.io/kubernetes/pkg/util/initsystem/initsystem.go index e4f8870a3..6638bab5e 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/initsystem/initsystem.go +++ b/vendor/k8s.io/kubernetes/pkg/util/initsystem/initsystem.go @@ -29,6 +29,9 @@ type InitSystem interface { // ServiceStop tries to stop a specific service ServiceStop(service string) error + // ServiceRestart tries to reload the environment and restart the specific service + ServiceRestart(service string) error + // ServiceExists ensures the service is defined for this init system. ServiceExists(service string) bool @@ -41,16 +44,34 @@ type InitSystem interface { type SystemdInitSystem struct{} +func (sysd SystemdInitSystem) reloadSystemd() error { + if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil { + return fmt.Errorf("failed to reload systemd: %v", err) + } + return nil +} + func (sysd SystemdInitSystem) ServiceStart(service string) error { + // Before we try to start any service, make sure that systemd is ready + if err := sysd.reloadSystemd(); err != nil { + return err + } args := []string{"start", service} - err := exec.Command("systemctl", args...).Run() - return err + return exec.Command("systemctl", args...).Run() +} + +func (sysd SystemdInitSystem) ServiceRestart(service string) error { + // Before we try to restart any service, make sure that systemd is ready + if err := sysd.reloadSystemd(); err != nil { + return err + } + args := []string{"restart", service} + return exec.Command("systemctl", args...).Run() } func (sysd SystemdInitSystem) ServiceStop(service string) error { args := []string{"stop", service} - err := exec.Command("systemctl", args...).Run() - return err + return exec.Command("systemctl", args...).Run() } func (sysd SystemdInitSystem) ServiceExists(service string) bool { @@ -95,6 +116,16 @@ func (sysd WindowsInitSystem) ServiceStart(service string) error { return err } +func (sysd WindowsInitSystem) ServiceRestart(service string) error { + if err := sysd.ServiceStop(service); err != nil { + return fmt.Errorf("couldn't stop service: %v", err) + } + if err := sysd.ServiceStart(service); err != nil { + return fmt.Errorf("couldn't start service: %v", err) + } + return nil +} + func (sysd WindowsInitSystem) ServiceStop(service string) error { args := []string{"Stop-Service", service} err := exec.Command("powershell", args...).Run() diff --git a/vendor/k8s.io/kubernetes/pkg/util/io/writer.go b/vendor/k8s.io/kubernetes/pkg/util/io/writer.go index 8d1d9964e..7c457d04a 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/io/writer.go +++ b/vendor/k8s.io/kubernetes/pkg/util/io/writer.go @@ -50,15 +50,24 @@ func (writer *StdWriter) WriteFile(filename string, data []byte, perm os.FileMod // it will not see the mounted device in its own namespace. To work around this // limitation one has to first enter hosts namespace (by using 'nsenter') and // only then write data. -type NsenterWriter struct{} +type NsenterWriter struct { + ne *nsenter.Nsenter +} + +// NewNsenterWriter creates a new Writer that allows writing data to file using +// nsenter command. +func NewNsenterWriter(ne *nsenter.Nsenter) *NsenterWriter { + return &NsenterWriter{ + ne: ne, + } +} // WriteFile calls 'nsenter cat - > ' and 'nsenter chmod' to create a // file on the host. func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.FileMode) error { - ne := nsenter.NewNsenter() echoArgs := []string{"-c", fmt.Sprintf("cat > %s", filename)} glog.V(5).Infof("nsenter: write data to file %s by nsenter", filename) - command := ne.Exec("sh", echoArgs) + command := writer.ne.Exec("sh", echoArgs) command.SetStdin(bytes.NewBuffer(data)) outputBytes, err := command.CombinedOutput() if err != nil { @@ -68,7 +77,7 @@ func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.Fil chmodArgs := []string{fmt.Sprintf("%o", perm), filename} glog.V(5).Infof("nsenter: change permissions of file %s to %s", filename, chmodArgs[0]) - outputBytes, err = ne.Exec("chmod", chmodArgs).CombinedOutput() + outputBytes, err = writer.ne.Exec("chmod", chmodArgs).CombinedOutput() if err != nil { glog.Errorf("Output from chmod command: %v", string(outputBytes)) return err diff --git a/vendor/k8s.io/kubernetes/pkg/util/ipset/ipset.go b/vendor/k8s.io/kubernetes/pkg/util/ipset/ipset.go index 3615caefe..e7c7991ea 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/ipset/ipset.go +++ b/vendor/k8s.io/kubernetes/pkg/util/ipset/ipset.go @@ -87,7 +87,8 @@ type IPSet struct { MaxElem int // PortRange specifies the port range of bitmap:port type ipset. PortRange string - // TODO: add comment message for ipset + // comment message for ipset + Comment string } // Validate checks if a given ipset is valid or not. diff --git a/vendor/k8s.io/kubernetes/pkg/util/ipset/ipset_test.go b/vendor/k8s.io/kubernetes/pkg/util/ipset/ipset_test.go index eaab92401..192b9beb5 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/ipset/ipset_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/ipset/ipset_test.go @@ -225,107 +225,215 @@ func TestCreateSet(t *testing.T) { } } -func TestAddEntry(t *testing.T) { - testEntry := &Entry{ - IP: "192.168.1.1", - Port: 53, - Protocol: ProtocolUDP, - SetType: HashIPPort, - } - - testSet := &IPSet{ - Name: "FOOBAR", - } +var testCases = []struct { + entry *Entry + set *IPSet + addCombinedOutputLog [][]string + delCombinedOutputLog []string +}{ + { // case 0 + entry: &Entry{ + IP: "192.168.1.1", + Port: 53, + Protocol: ProtocolUDP, + SetType: HashIPPort, + }, + set: &IPSet{ + Name: "ZERO", + }, + addCombinedOutputLog: [][]string{ + {"ipset", "add", "ZERO", "192.168.1.1,udp:53"}, + {"ipset", "add", "ZERO", "192.168.1.1,udp:53", "-exist"}, + }, + delCombinedOutputLog: []string{"ipset", "del", "ZERO", "192.168.1.1,udp:53"}, + }, + { // case 1 + entry: &Entry{ + IP: "192.168.1.2", + Port: 80, + Protocol: ProtocolTCP, + SetType: HashIPPort, + }, + set: &IPSet{ + Name: "UN", + }, + addCombinedOutputLog: [][]string{ + {"ipset", "add", "UN", "192.168.1.2,tcp:80"}, + {"ipset", "add", "UN", "192.168.1.2,tcp:80", "-exist"}, + }, + delCombinedOutputLog: []string{"ipset", "del", "UN", "192.168.1.2,tcp:80"}, + }, + { // case 2 + entry: &Entry{ + IP: "192.168.1.3", + Port: 53, + Protocol: ProtocolUDP, + SetType: HashIPPortIP, + IP2: "10.20.30.1", + }, + set: &IPSet{ + Name: "DEUX", + }, + addCombinedOutputLog: [][]string{ + {"ipset", "add", "DEUX", "192.168.1.3,udp:53,10.20.30.1"}, + {"ipset", "add", "DEUX", "192.168.1.3,udp:53,10.20.30.1", "-exist"}, + }, + delCombinedOutputLog: []string{"ipset", "del", "DEUX", "192.168.1.3,udp:53,10.20.30.1"}, + }, + { // case 3 + entry: &Entry{ + IP: "192.168.1.4", + Port: 80, + Protocol: ProtocolTCP, + SetType: HashIPPortIP, + IP2: "10.20.30.2", + }, + set: &IPSet{ + Name: "TROIS", + }, + addCombinedOutputLog: [][]string{ + {"ipset", "add", "TROIS", "192.168.1.4,tcp:80,10.20.30.2"}, + {"ipset", "add", "TROIS", "192.168.1.4,tcp:80,10.20.30.2", "-exist"}, + }, + delCombinedOutputLog: []string{"ipset", "del", "TROIS", "192.168.1.4,tcp:80,10.20.30.2"}, + }, + { // case 4 + entry: &Entry{ + IP: "192.168.1.5", + Port: 53, + Protocol: ProtocolUDP, + SetType: HashIPPortNet, + Net: "10.20.30.0/24", + }, + set: &IPSet{ + Name: "QUATRE", + }, + addCombinedOutputLog: [][]string{ + {"ipset", "add", "QUATRE", "192.168.1.5,udp:53,10.20.30.0/24"}, + {"ipset", "add", "QUATRE", "192.168.1.5,udp:53,10.20.30.0/24", "-exist"}, + }, + delCombinedOutputLog: []string{"ipset", "del", "QUATRE", "192.168.1.5,udp:53,10.20.30.0/24"}, + }, + { // case 5 + entry: &Entry{ + IP: "192.168.1.6", + Port: 80, + Protocol: ProtocolTCP, + SetType: HashIPPortNet, + Net: "10.20.40.0/24", + }, + set: &IPSet{ + Name: "CINQ", + }, + addCombinedOutputLog: [][]string{ + {"ipset", "add", "CINQ", "192.168.1.6,tcp:80,10.20.40.0/24"}, + {"ipset", "add", "CINQ", "192.168.1.6,tcp:80,10.20.40.0/24", "-exist"}, + }, + delCombinedOutputLog: []string{"ipset", "del", "CINQ", "192.168.1.6,tcp:80,10.20.40.0/24"}, + }, + { // case 6 + entry: &Entry{ + Port: 80, + Protocol: ProtocolTCP, + SetType: BitmapPort, + }, + set: &IPSet{ + Name: "SIX", + }, + addCombinedOutputLog: [][]string{ + {"ipset", "add", "SIX", "80"}, + {"ipset", "add", "SIX", "80", "-exist"}, + }, + delCombinedOutputLog: []string{"ipset", "del", "SIX", "80"}, + }, +} - fcmd := fakeexec.FakeCmd{ - CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ - // Success - func() ([]byte, error) { return []byte{}, nil }, - // Success - func() ([]byte, error) { return []byte{}, nil }, - // Failure - func() ([]byte, error) { - return []byte("ipset v6.19: Set cannot be created: set with the same name already exists"), &fakeexec.FakeExitError{Status: 1} +func TestAddEntry(t *testing.T) { + for i := range testCases { + fcmd := fakeexec.FakeCmd{ + CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ + // Success + func() ([]byte, error) { return []byte{}, nil }, + // Success + func() ([]byte, error) { return []byte{}, nil }, + // Failure + func() ([]byte, error) { + return []byte("ipset v6.19: Set cannot be created: set with the same name already exists"), &fakeexec.FakeExitError{Status: 1} + }, }, - }, - } - fexec := fakeexec.FakeExec{ - CommandScript: []fakeexec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec) - // Create with ignoreExistErr = false, expect success - err := runner.AddEntry(testEntry.String(), testSet, false) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 1 { - t.Errorf("expected 1 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[0]...).HasAll("ipset", "add", "FOOBAR", "192.168.1.1,udp:53") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0]) - } - // Create with ignoreExistErr = true, expect success - err = runner.AddEntry(testEntry.String(), testSet, true) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll("ipset", "add", "FOOBAR", "192.168.1.1,udp:53", "-exist") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } - // Create with ignoreExistErr = false, expect failure - err = runner.AddEntry(testEntry.String(), testSet, false) - if err == nil { - t.Errorf("expected failure, got nil") + } + fexec := fakeexec.FakeExec{ + CommandScript: []fakeexec.FakeCommandAction{ + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + }, + } + runner := New(&fexec) + // Create with ignoreExistErr = false, expect success + err := runner.AddEntry(testCases[i].entry.String(), testCases[i].set, false) + if err != nil { + t.Errorf("expected success, got %v", err) + } + if fcmd.CombinedOutputCalls != 1 { + t.Errorf("expected 1 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) + } + if !sets.NewString(fcmd.CombinedOutputLog[0]...).HasAll(testCases[i].addCombinedOutputLog[0]...) { + t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0]) + } + // Create with ignoreExistErr = true, expect success + err = runner.AddEntry(testCases[i].entry.String(), testCases[i].set, true) + if err != nil { + t.Errorf("expected success, got %v", err) + } + if fcmd.CombinedOutputCalls != 2 { + t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) + } + if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll(testCases[i].addCombinedOutputLog[1]...) { + t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) + } + // Create with ignoreExistErr = false, expect failure + err = runner.AddEntry(testCases[i].entry.String(), testCases[i].set, false) + if err == nil { + t.Errorf("expected failure, got nil") + } } } func TestDelEntry(t *testing.T) { - // TODO: Test more set type - testEntry := &Entry{ - IP: "192.168.1.1", - Port: 53, - Protocol: ProtocolUDP, - SetType: HashIPPort, - } - - fcmd := fakeexec.FakeCmd{ - CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ - // Success - func() ([]byte, error) { return []byte{}, nil }, - // Failure - func() ([]byte, error) { - return []byte("ipset v6.19: Element cannot be deleted from the set: it's not added"), &fakeexec.FakeExitError{Status: 1} + for i := range testCases { + fcmd := fakeexec.FakeCmd{ + CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ + // Success + func() ([]byte, error) { return []byte{}, nil }, + // Failure + func() ([]byte, error) { + return []byte("ipset v6.19: Element cannot be deleted from the set: it's not added"), &fakeexec.FakeExitError{Status: 1} + }, }, - }, - } - fexec := fakeexec.FakeExec{ - CommandScript: []fakeexec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec) + } + fexec := fakeexec.FakeExec{ + CommandScript: []fakeexec.FakeCommandAction{ + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + }, + } + runner := New(&fexec) - err := runner.DelEntry(testEntry.String(), "FOOBAR") - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 1 { - t.Errorf("expected 1 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[0]...).HasAll("ipset", "del", "FOOBAR", "192.168.1.1,udp:53") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0]) - } - err = runner.DelEntry(testEntry.String(), "FOOBAR") - if err == nil { - t.Errorf("expected failure, got nil") + err := runner.DelEntry(testCases[i].entry.String(), testCases[i].set.Name) + if err != nil { + t.Errorf("expected success, got %v", err) + } + if fcmd.CombinedOutputCalls != 1 { + t.Errorf("expected 1 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) + } + if !sets.NewString(fcmd.CombinedOutputLog[0]...).HasAll(testCases[i].delCombinedOutputLog...) { + t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0]) + } + err = runner.DelEntry(testCases[i].entry.String(), testCases[i].set.Name) + if err == nil { + t.Errorf("expected failure, got nil") + } } } diff --git a/vendor/k8s.io/kubernetes/pkg/util/iptables/iptables.go b/vendor/k8s.io/kubernetes/pkg/util/iptables/iptables.go index 0fb03468f..2b932adab 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/iptables/iptables.go +++ b/vendor/k8s.io/kubernetes/pkg/util/iptables/iptables.go @@ -18,10 +18,12 @@ package iptables import ( "bytes" + "context" "fmt" "regexp" "strings" "sync" + "time" godbus "github.com/godbus/dbus" "github.com/golang/glog" @@ -413,11 +415,18 @@ func iptablesCommand(protocol Protocol) string { } func (runner *runner) run(op operation, args []string) ([]byte, error) { + return runner.runContext(nil, op, args) +} + +func (runner *runner) runContext(ctx context.Context, op operation, args []string) ([]byte, error) { iptablesCmd := iptablesCommand(runner.protocol) fullArgs := append(runner.waitFlag, string(op)) fullArgs = append(fullArgs, args...) glog.V(5).Infof("running iptables %s %v", string(op), args) - return runner.exec.Command(iptablesCmd, fullArgs...).CombinedOutput() + if ctx == nil { + return runner.exec.Command(iptablesCmd, fullArgs...).CombinedOutput() + } + return runner.exec.CommandContext(ctx, iptablesCmd, fullArgs...).CombinedOutput() // Don't log err here - callers might not think it is an error. } @@ -426,9 +435,8 @@ func (runner *runner) run(op operation, args []string) ([]byte, error) { func (runner *runner) checkRule(table Table, chain Chain, args ...string) (bool, error) { if runner.hasCheck { return runner.checkRuleUsingCheck(makeFullArgs(table, chain, args...)) - } else { - return runner.checkRuleWithoutCheck(table, chain, args...) } + return runner.checkRuleWithoutCheck(table, chain, args...) } var hexnumRE = regexp.MustCompile("0x0+([0-9])") @@ -489,7 +497,13 @@ func (runner *runner) checkRuleWithoutCheck(table Table, chain Chain, args ...st // Executes the rule check using the "-C" flag func (runner *runner) checkRuleUsingCheck(args []string) (bool, error) { - out, err := runner.run(opCheckRule, args) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + + out, err := runner.runContext(ctx, opCheckRule, args) + if ctx.Err() == context.DeadlineExceeded { + return false, fmt.Errorf("timed out while checking rules") + } if err == nil { return true, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/util/iptables/testing/fake.go b/vendor/k8s.io/kubernetes/pkg/util/iptables/testing/fake.go index 3a69efa67..cb504f904 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/iptables/testing/fake.go +++ b/vendor/k8s.io/kubernetes/pkg/util/iptables/testing/fake.go @@ -33,6 +33,7 @@ const ( Reject = "REJECT" ToDest = "--to-destination " Recent = "recent " + MatchSet = "--match-set " ) type Rule map[string]string @@ -112,7 +113,7 @@ func (f *FakeIPTables) GetRules(chainName string) (rules []Rule) { for _, l := range strings.Split(string(f.Lines), "\n") { if strings.Contains(l, fmt.Sprintf("-A %v", chainName)) { newRule := Rule(map[string]string{}) - for _, arg := range []string{Destination, Source, DPort, Protocol, Jump, ToDest, Recent} { + for _, arg := range []string{Destination, Source, DPort, Protocol, Jump, ToDest, Recent, MatchSet} { tok := getToken(l, arg) if tok != "" { newRule[arg] = tok diff --git a/vendor/k8s.io/kubernetes/pkg/util/ipvs/BUILD b/vendor/k8s.io/kubernetes/pkg/util/ipvs/BUILD index 90ddf07b0..5a85d7448 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/ipvs/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/util/ipvs/BUILD @@ -13,6 +13,7 @@ go_test( ] + select({ "@io_bazel_rules_go//go/platform:linux": [ "ipvs_linux_test.go", + "kernelcheck_linux_test.go", ], "//conditions:default": [], }), @@ -20,6 +21,8 @@ go_test( deps = select({ "@io_bazel_rules_go//go/platform:linux": [ "//vendor/github.com/docker/libnetwork/ipvs:go_default_library", + "//vendor/k8s.io/utils/exec:go_default_library", + "//vendor/k8s.io/utils/exec/testing:go_default_library", ], "//conditions:default": [], }), @@ -32,36 +35,47 @@ go_library( ] + select({ "@io_bazel_rules_go//go/platform:android": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "@io_bazel_rules_go//go/platform:darwin": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "@io_bazel_rules_go//go/platform:dragonfly": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "@io_bazel_rules_go//go/platform:freebsd": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "@io_bazel_rules_go//go/platform:linux": [ "ipvs_linux.go", + "kernelcheck_linux.go", ], "@io_bazel_rules_go//go/platform:nacl": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "@io_bazel_rules_go//go/platform:netbsd": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "@io_bazel_rules_go//go/platform:openbsd": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "@io_bazel_rules_go//go/platform:plan9": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "@io_bazel_rules_go//go/platform:solaris": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "@io_bazel_rules_go//go/platform:windows": [ "ipvs_unsupported.go", + "kernelcheck_unsupported.go", ], "//conditions:default": [], }), @@ -82,6 +96,7 @@ go_library( "@io_bazel_rules_go//go/platform:linux": [ "//vendor/github.com/docker/libnetwork/ipvs:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], "@io_bazel_rules_go//go/platform:nacl": [ diff --git a/vendor/k8s.io/kubernetes/pkg/util/ipvs/ipvs.go b/vendor/k8s.io/kubernetes/pkg/util/ipvs/ipvs.go index 9d15beb0c..58e76a56c 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/ipvs/ipvs.go +++ b/vendor/k8s.io/kubernetes/pkg/util/ipvs/ipvs.go @@ -61,8 +61,19 @@ const ( FlagPersistent = 0x1 // FlagHashed specify IPVS service hash flag FlagHashed = 0x2 + // IPVSProxyMode is match set up cluster with ipvs proxy model + IPVSProxyMode = "ipvs" ) +// Sets of IPVS required kernel modules. +var ipvsModules = []string{ + "ip_vs", + "ip_vs_rr", + "ip_vs_wrr", + "ip_vs_sh", + "nf_conntrack_ipv4", +} + // Equal check the equality of virtual server. // We don't use struct == since it doesn't work because of slice. func (svc *VirtualServer) Equal(other *VirtualServer) bool { diff --git a/vendor/k8s.io/kubernetes/pkg/util/ipvs/ipvs_linux_test.go b/vendor/k8s.io/kubernetes/pkg/util/ipvs/ipvs_linux_test.go index 11f7be67c..9a6de6c0b 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/ipvs/ipvs_linux_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/ipvs/ipvs_linux_test.go @@ -306,7 +306,7 @@ func Test_toRealServer(t *testing.T) { for i := range Tests { got, err := toRealServer(&Tests[i].ipvsDestination) if err != nil { - t.Errorf("case %d unexpected error: %d", i, err) + t.Errorf("case %d unexpected error: %v", i, err) } if !reflect.DeepEqual(*got, Tests[i].realServer) { t.Errorf("case %d Failed to translate Destination - got %#v, want %#v", i, *got, Tests[i].realServer) @@ -349,7 +349,7 @@ func Test_toIPVSDestination(t *testing.T) { for i := range Tests { got, err := toIPVSDestination(&Tests[i].realServer) if err != nil { - t.Errorf("case %d unexpected error: %d", i, err) + t.Errorf("case %d unexpected error: %v", i, err) } if !reflect.DeepEqual(*got, Tests[i].ipvsDestination) { t.Errorf("case %d failed to translate Destination - got %#v, want %#v", i, *got, Tests[i].ipvsDestination) diff --git a/vendor/k8s.io/kubernetes/pkg/util/ipvs/kernelcheck_linux.go b/vendor/k8s.io/kubernetes/pkg/util/ipvs/kernelcheck_linux.go new file mode 100644 index 000000000..83c3e6b0f --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/ipvs/kernelcheck_linux.go @@ -0,0 +1,94 @@ +// +build linux + +/* +Copyright 2018 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 ipvs + +import ( + "fmt" + "regexp" + "strings" + + "k8s.io/apimachinery/pkg/util/sets" + utilsexec "k8s.io/utils/exec" + + "github.com/golang/glog" +) + +// RequiredIPVSKernelModulesAvailableCheck tests IPVS required kernel modules. +type RequiredIPVSKernelModulesAvailableCheck struct { + Executor utilsexec.Interface +} + +// Name returns label for RequiredIPVSKernelModulesAvailableCheck +func (r RequiredIPVSKernelModulesAvailableCheck) Name() string { + return "RequiredIPVSKernelModulesAvailable" +} + +// Check try to validates IPVS required kernel modules exists or not. +// The name of function can not be changed. +func (r RequiredIPVSKernelModulesAvailableCheck) Check() (warnings, errors []error) { + glog.V(1).Infoln("validating the kernel module IPVS required exists in machine or not") + + // Find out loaded kernel modules + out, err := r.Executor.Command("cut", "-f1", "-d", " ", "/proc/modules").CombinedOutput() + if err != nil { + errors = append(errors, fmt.Errorf("error getting installed ipvs required kernel modules: %v(%s)", err, out)) + return nil, errors + } + mods := strings.Split(string(out), "\n") + + wantModules := sets.NewString() + loadModules := sets.NewString() + wantModules.Insert(ipvsModules...) + loadModules.Insert(mods...) + modules := wantModules.Difference(loadModules).UnsortedList() + + // Check builtin modules exist or not + if len(modules) != 0 { + kernelVersionFile := "/proc/sys/kernel/osrelease" + b, err := r.Executor.Command("cut", "-f1", "-d", " ", kernelVersionFile).CombinedOutput() + if err != nil { + errors = append(errors, fmt.Errorf("error getting os release kernel version: %v(%s)", err, out)) + return nil, errors + } + + kernelVersion := strings.TrimSpace(string(b)) + builtinModsFilePath := fmt.Sprintf("/lib/modules/%s/modules.builtin", kernelVersion) + out, err := r.Executor.Command("cut", "-f1", "-d", " ", builtinModsFilePath).CombinedOutput() + if err != nil { + errors = append(errors, fmt.Errorf("error getting required builtin kernel modules: %v(%s)", err, out)) + return nil, errors + } + + builtInModules := sets.NewString() + for _, builtInMode := range ipvsModules { + match, _ := regexp.Match(builtInMode+".ko", out) + if !match { + builtInModules.Insert(string(builtInMode)) + } + } + if len(builtInModules) != 0 { + warnings = append(warnings, fmt.Errorf( + "the IPVS proxier will not be used, because the following required kernel modules are not loaded: %v or no builtin kernel ipvs support: %v\n"+ + "you can solve this problem with following methods:\n 1. Run 'modprobe -- ' to load missing kernel modules;\n"+ + "2. Provide the missing builtin kernel ipvs support\n", modules, builtInModules)) + } + } + + return warnings, errors +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/ipvs/kernelcheck_linux_test.go b/vendor/k8s.io/kubernetes/pkg/util/ipvs/kernelcheck_linux_test.go new file mode 100644 index 000000000..1f87a9239 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/ipvs/kernelcheck_linux_test.go @@ -0,0 +1,130 @@ +/* +Copyright 2018 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 ipvs + +import ( + "testing" + + utilsexec "k8s.io/utils/exec" + fakeexec "k8s.io/utils/exec/testing" +) + +func TestRequiredIPVSKernelModulesAvailableCheck(t *testing.T) { + cases := []struct { + caseName string + + loadedKernel string + kernelVersion string + builtinKernel string + + expectErrors bool + expectWarnings bool + }{ + { + caseName: "no installed kernel modules and no builtin kernel modules", + loadedKernel: "", + kernelVersion: "3.13.0-24-generic", + builtinKernel: "", + expectErrors: false, + expectWarnings: true, + }, + { + caseName: "no installed kernel modules and missing builtin kernel modules", + loadedKernel: "", + kernelVersion: "3.13.0-24-generic", + builtinKernel: "kernel/net/netfilter/ipvs/ip_vs.ko\n" + + "kernel/net/ipv4/netfilter/nf_conntrack_ipv4.ko", + expectErrors: false, + expectWarnings: true, + }, + { + caseName: "no installed kernel modules and own all builtin kernel modules", + loadedKernel: "", + kernelVersion: "3.13.0-24-generic", + builtinKernel: "kernel/net/netfilter/ipvs/ip_vs.ko\n" + + "kernel/net/netfilter/ipvs/ip_vs_rr.ko\n" + + "kernel/net/netfilter/ipvs/ip_vs_wrr.ko\n" + + "kernel/net/netfilter/ipvs/ip_vs_sh.ko\n" + + "kernel/net/ipv4/netfilter/nf_conntrack_ipv4.ko", + expectErrors: false, + expectWarnings: false, + }, + { + caseName: "missing installed kernel modules and no builtin kernel modules", + loadedKernel: "ip_vs", + kernelVersion: "3.13.0-24-generic", + builtinKernel: "", + expectErrors: false, + expectWarnings: true, + }, + { + caseName: "own all installed kernel modules and no builtin kernel modules", + loadedKernel: "ip_vs\n" + "ip_vs_wrr\n" + "nf_conntrack_ipv4\n" + + "ip_vs_rr\n" + "ip_vs_sh", + kernelVersion: "3.13.0-24-generic", + builtinKernel: "", + expectErrors: false, + expectWarnings: false, + }, + { + caseName: "own all installed kernel modules and all builtin kernel modules", + loadedKernel: "ip_vs\n" + "ip_vs_wrr\n" + "nf_conntrack_ipv4\n" + "ip_vs_rr\n" + "ip_vs_sh", + kernelVersion: "3.13.0-24-generic", + builtinKernel: "kernel/net/netfilter/ipvs/ip_vs.ko\n" + + "kernel/net/netfilter/ipvs/ip_vs_rr.ko\n" + + "kernel/net/netfilter/ipvs/ip_vs_wrr.ko\n" + + "kernel/net/netfilter/ipvs/ip_vs_sh.ko\n" + + "kernel/net/ipv4/netfilter/nf_conntrack_ipv4.ko", + expectErrors: false, + expectWarnings: false, + }, + } + + for i, tc := range cases { + fcmd := fakeexec.FakeCmd{ + CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ + func() ([]byte, error) { return []byte(cases[i].loadedKernel), nil }, + func() ([]byte, error) { return []byte(cases[i].kernelVersion), nil }, + func() ([]byte, error) { return []byte(cases[i].builtinKernel), nil }, + }, + } + + fexec := fakeexec.FakeExec{ + CommandScript: []fakeexec.FakeCommandAction{ + func(cmd string, args ...string) utilsexec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + func(cmd string, args ...string) utilsexec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + func(cmd string, args ...string) utilsexec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + }, + } + + check := RequiredIPVSKernelModulesAvailableCheck{ + Executor: &fexec, + } + warnings, errors := check.Check() + + switch { + case warnings != nil && !tc.expectWarnings: + t.Errorf("RequiredIPVSKernelModulesAvailableCheck: unexpected warnings for installed kernel modules %v and builtin kernel modules %v. Warnings: %v", tc.loadedKernel, tc.builtinKernel, warnings) + case warnings == nil && tc.expectWarnings: + t.Errorf("RequiredIPVSKernelModulesAvailableCheck: expected warnings for installed kernel modules %v and builtin kernel modules %v but got nothing", tc.loadedKernel, tc.builtinKernel) + case errors != nil && !tc.expectErrors: + t.Errorf("RequiredIPVSKernelModulesAvailableCheck: unexpected errors for installed kernel modules %v and builtin kernel modules %v. errors: %v", tc.loadedKernel, tc.builtinKernel, errors) + case errors == nil && tc.expectErrors: + t.Errorf("RequiredIPVSKernelModulesAvailableCheck: expected errors for installed kernel modules %v and builtin kernel modules %v but got nothing", tc.loadedKernel, tc.builtinKernel) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/ipvs/kernelcheck_unsupported.go b/vendor/k8s.io/kubernetes/pkg/util/ipvs/kernelcheck_unsupported.go new file mode 100644 index 000000000..6247bff85 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/ipvs/kernelcheck_unsupported.go @@ -0,0 +1,39 @@ +// +build !linux + +/* +Copyright 2018 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 ipvs + +import ( + utilsexec "k8s.io/utils/exec" +) + +// RequiredIPVSKernelModulesAvailableCheck tests IPVS required kernel modules. +type RequiredIPVSKernelModulesAvailableCheck struct { + Executor utilsexec.Interface +} + +// Name returns label for RequiredIPVSKernelModulesAvailableCheck +func (r RequiredIPVSKernelModulesAvailableCheck) Name() string { + return "RequiredIPVSKernelModulesAvailable" +} + +// Check try to validates IPVS required kernel modules exists or not. +func (r RequiredIPVSKernelModulesAvailableCheck) Check() (warnings, errors []error) { + + return nil, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/BUILD b/vendor/k8s.io/kubernetes/pkg/util/mount/BUILD index 9040cd93b..6f2df9aca 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/BUILD @@ -71,12 +71,44 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ] + select({ + "@io_bazel_rules_go//go/platform:android": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "//pkg/util/nsenter:go_default_library", + ], "@io_bazel_rules_go//go/platform:linux": [ + "//pkg/util/file:go_default_library", "//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", ], + "@io_bazel_rules_go//go/platform:nacl": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "//pkg/util/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "//pkg/util/file:go_default_library", + "//pkg/util/nsenter:go_default_library", + ], "//conditions:default": [], }), ) @@ -101,7 +133,9 @@ go_test( "//vendor/k8s.io/utils/exec/testing:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:linux": [ + "//pkg/util/nsenter:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], "@io_bazel_rules_go//go/platform:windows": [ diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/OWNERS b/vendor/k8s.io/kubernetes/pkg/util/mount/OWNERS index 8b4ff6218..2d6f262fb 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/OWNERS +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/OWNERS @@ -3,6 +3,7 @@ reviewers: - saad-ali - jsafrane - msau42 + - andyzhangx approvers: - jingxu97 - saad-ali diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount.go b/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount.go index f4f561f3d..fe7dcbd7e 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount.go @@ -136,7 +136,7 @@ func (m *execMounter) MakeDir(pathname string) error { return m.wrappedMounter.MakeDir(pathname) } -func (m *execMounter) ExistsPath(pathname string) bool { +func (m *execMounter) ExistsPath(pathname string) (bool, error) { return m.wrappedMounter.ExistsPath(pathname) } @@ -152,6 +152,18 @@ func (m *execMounter) SafeMakeDir(pathname string, base string, perm os.FileMode return m.wrappedMounter.SafeMakeDir(pathname, base, perm) } +func (m *execMounter) GetMountRefs(pathname string) ([]string, error) { + return m.wrappedMounter.GetMountRefs(pathname) +} + +func (m *execMounter) GetFSGroup(pathname string) (int64, error) { + return m.wrappedMounter.GetFSGroup(pathname) +} + func (m *execMounter) GetSELinuxSupport(pathname string) (bool, error) { return m.wrappedMounter.GetSELinuxSupport(pathname) } + +func (m *execMounter) GetMode(pathname string) (os.FileMode, error) { + return m.wrappedMounter.GetMode(pathname) +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_test.go b/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_test.go index 94feb8b20..9619356f7 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_test.go @@ -147,8 +147,8 @@ func (fm *fakeMounter) MakeFile(pathname string) error { func (fm *fakeMounter) MakeDir(pathname string) error { return nil } -func (fm *fakeMounter) ExistsPath(pathname string) bool { - return false +func (fm *fakeMounter) ExistsPath(pathname string) (bool, error) { + return false, errors.New("not implemented") } func (fm *fakeMounter) GetFileType(pathname string) (FileType, error) { return FileTypeFile, nil @@ -165,6 +165,18 @@ func (fm *fakeMounter) SafeMakeDir(pathname string, base string, perm os.FileMod return nil } +func (fm *fakeMounter) GetMountRefs(pathname string) ([]string, error) { + return nil, errors.New("not implemented") +} + +func (fm *fakeMounter) GetFSGroup(pathname string) (int64, error) { + return -1, errors.New("not implemented") +} + func (fm *fakeMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (fm *fakeMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_unsupported.go b/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_unsupported.go index 30ae9ea47..6854b32b2 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_unsupported.go @@ -83,8 +83,8 @@ func (mounter *execMounter) MakeFile(pathname string) error { return nil } -func (mounter *execMounter) ExistsPath(pathname string) bool { - return true +func (mounter *execMounter) ExistsPath(pathname string) (bool, error) { + return true, errors.New("not implemented") } func (mounter *execMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { @@ -99,6 +99,18 @@ func (mounter *execMounter) SafeMakeDir(pathname string, base string, perm os.Fi return nil } +func (mounter *execMounter) GetMountRefs(pathname string) ([]string, error) { + return nil, errors.New("not implemented") +} + +func (mounter *execMounter) GetFSGroup(pathname string) (int64, error) { + return -1, errors.New("not implemented") +} + func (mounter *execMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (mounter *execMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/fake.go b/vendor/k8s.io/kubernetes/pkg/util/mount/fake.go index 12522a198..10832fd32 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/fake.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/fake.go @@ -201,8 +201,8 @@ func (f *FakeMounter) MakeFile(pathname string) error { return nil } -func (f *FakeMounter) ExistsPath(pathname string) bool { - return false +func (f *FakeMounter) ExistsPath(pathname string) (bool, error) { + return false, errors.New("not implemented") } func (f *FakeMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { @@ -216,6 +216,23 @@ func (mounter *FakeMounter) SafeMakeDir(pathname string, base string, perm os.Fi return nil } +func (f *FakeMounter) GetMountRefs(pathname string) ([]string, error) { + realpath, err := filepath.EvalSymlinks(pathname) + if err != nil { + // Ignore error in FakeMounter, because we actually didn't create files. + realpath = pathname + } + return getMountRefsByDev(f, realpath) +} + +func (f *FakeMounter) GetFSGroup(pathname string) (int64, error) { + return -1, errors.New("GetFSGroup not implemented") +} + func (f *FakeMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("GetSELinuxSupport not implemented") } + +func (f *FakeMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/mount.go b/vendor/k8s.io/kubernetes/pkg/util/mount/mount.go index 6ed3e6f77..f5ce194ca 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/mount.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/mount.go @@ -23,7 +23,6 @@ import ( "os" "path/filepath" "strings" - "syscall" ) type FileType string @@ -85,16 +84,18 @@ type Interface interface { // MakeDir creates a new directory. // Will operate in the host mount namespace if kubelet is running in a container MakeDir(pathname string) error - // SafeMakeDir makes sure that the created directory does not escape given - // base directory mis-using symlinks. The directory is created in the same - // mount namespace as where kubelet is running. Note that the function makes - // sure that it creates the directory somewhere under the base, nothing - // else. E.g. if the directory already exists, it may exists outside of the - // base due to symlinks. - SafeMakeDir(pathname string, base string, perm os.FileMode) 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 + // SafeMakeDir creates subdir within given base. It makes sure that the + // created directory does not escape given base directory mis-using + // symlinks. Note that the function makes sure that it creates the directory + // somewhere under the base, nothing else. E.g. if the directory already + // exists, it may exist outside of the base due to symlinks. + // This method should be used if the directory to create is inside volume + // that's under user control. User must not be able to use symlinks to + // escape the volume to create directories somewhere else. + SafeMakeDir(subdir string, base string, perm os.FileMode) error + // Will operate in the host mount namespace if kubelet is running in a container. + // Error is returned on any other error than "file not found". + ExistsPath(pathname string) (bool, error) // CleanSubPaths removes any bind-mounts created by PrepareSafeSubpath in given // pod volume directory. CleanSubPaths(podDir string, volumeName string) error @@ -109,9 +110,17 @@ type Interface interface { // subpath starts. On the other hand, Interface.CleanSubPaths must be called // when the pod finishes. PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) + // GetMountRefs finds all mount references to the path, returns a + // list of paths. Path could be a mountpoint path, device or a normal + // directory (for bind mount). + GetMountRefs(pathname string) ([]string, error) + // GetFSGroup returns FSGroup of the path. + GetFSGroup(pathname string) (int64, error) // GetSELinuxSupport returns true if given path is on a mount that supports // SELinux. GetSELinuxSupport(pathname string) (bool, error) + // GetMode returns permissions of the path. + GetMode(pathname string) (os.FileMode, error) } type Subpath struct { @@ -170,22 +179,19 @@ func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string, return mounter.formatAndMount(source, target, fstype, options) } -// GetMountRefsByDev finds all references to the device provided +// getMountRefsByDev finds all references to the device provided // by mountPath; returns a list of paths. -func GetMountRefsByDev(mounter Interface, mountPath string) ([]string, error) { +// Note that mountPath should be path after the evaluation of any symblolic links. +func getMountRefsByDev(mounter Interface, mountPath string) ([]string, error) { mps, err := mounter.List() if err != nil { return nil, err } - slTarget, err := filepath.EvalSymlinks(mountPath) - if err != nil { - slTarget = mountPath - } // Finding the device mounted to mountPath diskDev := "" for i := range mps { - if slTarget == mps[i].Path { + if mountPath == mps[i].Path { diskDev = mps[i].Device break } @@ -194,8 +200,8 @@ func GetMountRefsByDev(mounter Interface, mountPath string) ([]string, error) { // Find all references to the device. var refs []string for i := range mps { - if mps[i].Device == diskDev || mps[i].Device == slTarget { - if mps[i].Path != slTarget { + if mps[i].Device == diskDev || mps[i].Device == mountPath { + if mps[i].Path != mountPath { refs = append(refs, mps[i].Path) } } @@ -236,13 +242,6 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e return device, refCount, nil } -func isNotDirErr(err error) bool { - if e, ok := err.(*os.PathError); ok && e.Err == syscall.ENOTDIR { - return true - } - return false -} - // 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 @@ -258,7 +257,7 @@ func IsNotMountPoint(mounter Interface, file string) (bool, error) { notMnt = true notMntErr = nil } - if notMntErr != nil && isNotDirErr(notMntErr) { + if notMntErr != nil { return notMnt, notMntErr } // identified as mountpoint, so return this fact diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go index 1aeb8a989..e80dad590 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go @@ -33,6 +33,7 @@ import ( "github.com/golang/glog" "golang.org/x/sys/unix" "k8s.io/apimachinery/pkg/util/sets" + utilfile "k8s.io/kubernetes/pkg/util/file" utilio "k8s.io/kubernetes/pkg/util/io" utilexec "k8s.io/utils/exec" ) @@ -42,6 +43,8 @@ const ( maxListTries = 3 // Number of fields per line in /proc/mounts as per the fstab man page. expectedNumFieldsPerLine = 6 + // At least number of fields per line in /proc//mountinfo. + expectedAtLeastNumFieldsPerMountInfo = 10 // Location of the mount file to use procMountsPath = "/proc/mounts" // Location of the mountinfo file @@ -447,12 +450,8 @@ func (mounter *Mounter) MakeFile(pathname string) error { return nil } -func (mounter *Mounter) ExistsPath(pathname string) bool { - _, err := os.Stat(pathname) - if err != nil { - return false - } - return true +func (mounter *Mounter) ExistsPath(pathname string) (bool, error) { + return utilfile.FileExists(pathname) } // formatAndMount uses unix utils to format and mount the given disk @@ -511,7 +510,11 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, } if fstype == "ext4" || fstype == "ext3" { - args = []string{"-F", source} + args = []string{ + "-F", // Force flag + "-m0", // Zero blocks reserved for super-user + source, + } } glog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args) _, err := mounter.Exec.Run("mkfs."+fstype, args...) @@ -598,7 +601,7 @@ func isShared(mount string, mountInfoPath string) (bool, error) { } // parse optional parameters - for _, opt := range info.optional { + for _, opt := range info.optionalFields { if strings.HasPrefix(opt, "shared:") { return true, nil } @@ -606,14 +609,27 @@ func isShared(mount string, mountInfoPath string) (bool, error) { return false, nil } +// This represents a single line in /proc//mountinfo. type mountInfo struct { - // Path of the mount point + // Unique ID for the mount (maybe reused after umount). + id int + // The ID of the parent mount (or of self for the root of this mount namespace's mount tree). + parentID int + // The value of `st_dev` for files on this filesystem. + majorMinor string + // The pathname of the directory in the filesystem which forms the root of this mount. + root string + // Mount source, filesystem-specific information. e.g. device, tmpfs name. + source string + // Mount point, the pathname of the mount point. mountPoint string - // list of "optional parameters", mount propagation is one of them - optional []string - // mount options + // Optional fieds, zero or more fields of the form "tag[:value]". + optionalFields []string + // The filesystem type in the form "type[.subtype]". + fsType string + // Per-mount options. mountOptions []string - // super options: per-superblock options. + // Per-superblock options. superOptions []string } @@ -633,20 +649,38 @@ func parseMountInfo(filename string) ([]mountInfo, error) { } // See `man proc` for authoritative description of format of the file. fields := strings.Fields(line) - if len(fields) < 10 { - return nil, fmt.Errorf("wrong number of fields in (expected %d, got %d): %s", 10, len(fields), line) + if len(fields) < expectedAtLeastNumFieldsPerMountInfo { + return nil, fmt.Errorf("wrong number of fields in (expected at least %d, got %d): %s", expectedAtLeastNumFieldsPerMountInfo, len(fields), line) + } + id, err := strconv.Atoi(fields[0]) + if err != nil { + return nil, err + } + parentID, err := strconv.Atoi(fields[1]) + if err != nil { + return nil, err } info := mountInfo{ + id: id, + parentID: parentID, + majorMinor: fields[2], + root: fields[3], mountPoint: fields[4], mountOptions: strings.Split(fields[5], ","), - optional: []string{}, } // All fields until "-" are "optional fields". - for i := 6; i < len(fields) && fields[i] != "-"; i++ { - info.optional = append(info.optional, fields[i]) + i := 6 + for ; i < len(fields) && fields[i] != "-"; i++ { + info.optionalFields = append(info.optionalFields, fields[i]) + } + // Parse the rest 3 fields. + i += 1 + if len(fields)-i < 3 { + return nil, fmt.Errorf("expect 3 fields in %s, got %d", line, len(fields)-i) } - superOpts := fields[len(fields)-1] - info.superOptions = strings.Split(superOpts, ",") + info.fsType = fields[i] + info.source = fields[i+1] + info.superOptions = strings.Split(fields[i+2], ",") infos = append(infos, info) } return infos, nil @@ -723,7 +757,8 @@ func getSELinuxSupport(path string, mountInfoFilename string) (bool, error) { } func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { - newHostPath, err = doBindSubPath(mounter, subPath, os.Getpid()) + newHostPath, err = doBindSubPath(mounter, subPath) + // There is no action when the container starts. Bind-mount will be cleaned // when container stops by CleanSubPaths. cleanupAction = nil @@ -731,47 +766,31 @@ func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, } // This implementation is shared between Linux and NsEnterMounter -// kubeletPid is PID of kubelet in the PID namespace where bind-mount is done, -// i.e. pid on the *host* if kubelet runs in a container. -func doBindSubPath(mounter Interface, subpath Subpath, kubeletPid int) (hostPath string, err error) { - // Check early for symlink. This is just a pre-check to avoid bind-mount - // before the final check. - evalSubPath, err := filepath.EvalSymlinks(subpath.Path) - if err != nil { - return "", fmt.Errorf("evalSymlinks %q failed: %v", subpath.Path, err) - } - glog.V(5).Infof("doBindSubPath %q, full subpath %q for volumepath %q", subpath.Path, evalSubPath, subpath.VolumePath) - - evalSubPath = filepath.Clean(evalSubPath) - if !pathWithinBase(evalSubPath, subpath.VolumePath) { - return "", fmt.Errorf("subpath %q not within volume path %q", evalSubPath, subpath.VolumePath) +func safeOpenSubPath(mounter Interface, subpath Subpath) (int, error) { + if !pathWithinBase(subpath.Path, subpath.VolumePath) { + return -1, fmt.Errorf("subpath %q not within volume path %q", subpath.Path, subpath.VolumePath) } - - // Prepare directory for bind mounts - // containerName is DNS label, i.e. safe as a directory name. - bindDir := filepath.Join(subpath.PodDir, containerSubPathDirectoryName, subpath.VolumeName, subpath.ContainerName) - err = os.MkdirAll(bindDir, 0750) - if err != nil && !os.IsExist(err) { - return "", fmt.Errorf("error creating directory %s: %s", bindDir, err) + fd, err := doSafeOpen(subpath.Path, subpath.VolumePath) + if err != nil { + return -1, fmt.Errorf("error opening subpath %v: %v", subpath.Path, err) } - bindPathTarget := filepath.Join(bindDir, strconv.Itoa(subpath.VolumeMountIndex)) - - success := false - defer func() { - // Cleanup subpath on error - if !success { - glog.V(4).Infof("doBindSubPath() failed for %q, cleaning up subpath", bindPathTarget) - if cleanErr := cleanSubPath(mounter, subpath); cleanErr != nil { - glog.Errorf("Failed to clean subpath %q: %v", bindPathTarget, cleanErr) - } - } - }() + return fd, nil +} - // Check it's not already bind-mounted +// prepareSubpathTarget creates target for bind-mount of subpath. It returns +// "true" when the target already exists and something is mounted there. +// Given Subpath must have all paths with already resolved symlinks and with +// paths relevant to kubelet (when it runs in a container). +// This function is called also by NsEnterMounter. It works because +// /var/lib/kubelet is mounted from the host into the container with Kubelet as +// /var/lib/kubelet too. +func prepareSubpathTarget(mounter Interface, subpath Subpath) (bool, string, error) { + // Early check for already bind-mounted subpath. + bindPathTarget := getSubpathBindTarget(subpath) notMount, err := IsNotMountPoint(mounter, bindPathTarget) if err != nil { if !os.IsNotExist(err) { - return "", fmt.Errorf("error checking path %s for mount: %s", bindPathTarget, err) + return false, "", fmt.Errorf("error checking path %s for mount: %s", bindPathTarget, err) } // Ignore ErrorNotExist: the file/directory will be created below if it does not exist yet. notMount = true @@ -779,37 +798,88 @@ func doBindSubPath(mounter Interface, subpath Subpath, kubeletPid int) (hostPath if !notMount { // It's already mounted glog.V(5).Infof("Skipping bind-mounting subpath %s: already mounted", bindPathTarget) - success = true - return bindPathTarget, nil + return true, bindPathTarget, nil + } + + // bindPathTarget is in /var/lib/kubelet and thus reachable without any + // translation even to containerized kubelet. + bindParent := filepath.Dir(bindPathTarget) + err = os.MkdirAll(bindParent, 0750) + if err != nil && !os.IsExist(err) { + return false, "", fmt.Errorf("error creating directory %s: %s", bindParent, err) } - // Create target of the bind mount. A directory for directories, empty file - // for everything else. t, err := os.Lstat(subpath.Path) if err != nil { - return "", fmt.Errorf("lstat %s failed: %s", subpath.Path, err) + return false, "", fmt.Errorf("lstat %s failed: %s", subpath.Path, err) } + if t.Mode()&os.ModeDir > 0 { if err = os.Mkdir(bindPathTarget, 0750); err != nil && !os.IsExist(err) { - return "", fmt.Errorf("error creating directory %s: %s", bindPathTarget, err) + return false, "", fmt.Errorf("error creating directory %s: %s", bindPathTarget, err) } } else { - // "/bin/touch ". + // "/bin/touch ". // A file is enough for all possible targets (symlink, device, pipe, // socket, ...), bind-mounting them into a file correctly changes type // of the target file. if err = ioutil.WriteFile(bindPathTarget, []byte{}, 0640); err != nil { - return "", fmt.Errorf("error creating file %s: %s", bindPathTarget, err) + return false, "", fmt.Errorf("error creating file %s: %s", bindPathTarget, err) } } + return false, bindPathTarget, nil +} + +func getSubpathBindTarget(subpath Subpath) string { + // containerName is DNS label, i.e. safe as a directory name. + return filepath.Join(subpath.PodDir, containerSubPathDirectoryName, subpath.VolumeName, subpath.ContainerName, strconv.Itoa(subpath.VolumeMountIndex)) +} + +func doBindSubPath(mounter Interface, subpath Subpath) (hostPath string, err error) { + // Linux, kubelet runs on the host: + // - safely open the subpath + // - bind-mount /proc//fd/ to subpath target + // User can't change /proc//fd/ to point to a bad place. + + // Evaluate all symlinks here once for all subsequent functions. + newVolumePath, err := filepath.EvalSymlinks(subpath.VolumePath) + if err != nil { + return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.VolumePath, err) + } + newPath, err := filepath.EvalSymlinks(subpath.Path) + if err != nil { + return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.Path, err) + } + glog.V(5).Infof("doBindSubPath %q (%q) for volumepath %q", subpath.Path, newPath, subpath.VolumePath) + subpath.VolumePath = newVolumePath + subpath.Path = newPath - // Safe open subpath and get the fd - fd, err := doSafeOpen(evalSubPath, subpath.VolumePath) + fd, err := safeOpenSubPath(mounter, subpath) if err != nil { - return "", fmt.Errorf("error opening subpath %v: %v", evalSubPath, err) + return "", err } defer syscall.Close(fd) + alreadyMounted, bindPathTarget, err := prepareSubpathTarget(mounter, subpath) + if err != nil { + return "", err + } + if alreadyMounted { + return bindPathTarget, nil + } + + success := false + defer func() { + // Cleanup subpath on error + if !success { + glog.V(4).Infof("doBindSubPath() failed for %q, cleaning up subpath", bindPathTarget) + if cleanErr := cleanSubPath(mounter, subpath); cleanErr != nil { + glog.Errorf("Failed to clean subpath %q: %v", bindPathTarget, cleanErr) + } + } + }() + + kubeletPid := os.Getpid() mountSource := fmt.Sprintf("/proc/%d/fd/%v", kubeletPid, fd) // Do the bind mount @@ -818,8 +888,8 @@ func doBindSubPath(mounter Interface, subpath Subpath, kubeletPid int) (hostPath if err = mounter.Mount(mountSource, bindPathTarget, "" /*fstype*/, options); err != nil { return "", fmt.Errorf("error mounting %s: %s", subpath.Path, err) } - success = true + glog.V(3).Infof("Bound SubPath %s into %s", subpath.Path, bindPathTarget) return bindPathTarget, nil } @@ -954,15 +1024,62 @@ func removeEmptyDirs(baseDir, endDir string) error { return nil } -func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { - return doSafeMakeDir(pathname, base, perm) +func (mounter *Mounter) SafeMakeDir(subdir string, base string, perm os.FileMode) error { + realBase, err := filepath.EvalSymlinks(base) + if err != nil { + return fmt.Errorf("error resolving symlinks in %s: %s", base, err) + } + + realFullPath := filepath.Join(realBase, subdir) + + return doSafeMakeDir(realFullPath, realBase, perm) +} + +func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) { + realpath, err := filepath.EvalSymlinks(pathname) + if err != nil { + return nil, err + } + return searchMountPoints(realpath, procMountInfoPath) } func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) { return getSELinuxSupport(pathname, procMountInfoPath) } +func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { + realpath, err := filepath.EvalSymlinks(pathname) + if err != nil { + return 0, err + } + return getFSGroup(realpath) +} + +func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { + return getMode(pathname) +} + +// This implementation is shared between Linux and NsEnterMounter +func getFSGroup(pathname string) (int64, error) { + info, err := os.Stat(pathname) + if err != nil { + return 0, err + } + return int64(info.Sys().(*syscall.Stat_t).Gid), nil +} + // This implementation is shared between Linux and NsEnterMounter +func getMode(pathname string) (os.FileMode, error) { + info, err := os.Stat(pathname) + if err != nil { + return 0, err + } + return info.Mode(), nil +} + +// This implementation is shared between Linux and NsEnterMounter. Both pathname +// and base must be either already resolved symlinks or thet will be resolved in +// kubelet's mount namespace (in case it runs containerized). func doSafeMakeDir(pathname string, base string, perm os.FileMode) error { glog.V(4).Infof("Creating directory %q within base %q", pathname, base) @@ -1116,6 +1233,9 @@ func findExistingPrefix(base, pathname string) (string, []string, error) { // Symlinks are disallowed (pathname must already resolve symlinks), // and the path must be within the base directory. func doSafeOpen(pathname string, base string) (int, error) { + pathname = filepath.Clean(pathname) + base = filepath.Clean(base) + // Calculate segments to follow subpath, err := filepath.Rel(base, pathname) if err != nil { @@ -1187,3 +1307,51 @@ func doSafeOpen(pathname string, base string) (int, error) { return finalFD, nil } + +// searchMountPoints finds all mount references to the source, returns a list of +// mountpoints. +// This function assumes source cannot be device. +// Some filesystems may share a source name, e.g. tmpfs. And for bind mounting, +// it's possible to mount a non-root path of a filesystem, so we need to use +// root path and major:minor to represent mount source uniquely. +// This implementation is shared between Linux and NsEnterMounter +func searchMountPoints(hostSource, mountInfoPath string) ([]string, error) { + mis, err := parseMountInfo(mountInfoPath) + if err != nil { + return nil, err + } + + mountID := 0 + rootPath := "" + majorMinor := "" + + // Finding the underlying root path and major:minor if possible. + // We need search in backward order because it's possible for later mounts + // to overlap earlier mounts. + for i := len(mis) - 1; i >= 0; i-- { + if hostSource == mis[i].mountPoint || pathWithinBase(hostSource, mis[i].mountPoint) { + // If it's a mount point or path under a mount point. + mountID = mis[i].id + rootPath = filepath.Join(mis[i].root, strings.TrimPrefix(hostSource, mis[i].mountPoint)) + majorMinor = mis[i].majorMinor + break + } + } + + if rootPath == "" || majorMinor == "" { + return nil, fmt.Errorf("failed to get root path and major:minor for %s", hostSource) + } + + var refs []string + for i := range mis { + if mis[i].id == mountID { + // Ignore mount entry for mount source itself. + continue + } + if mis[i].root == rootPath && mis[i].majorMinor == majorMinor { + refs = append(refs, mis[i].mountPoint) + } + } + + return refs, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux_test.go b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux_test.go index 9735176e2..0324bf88d 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux_test.go @@ -203,7 +203,7 @@ func TestGetMountRefsByDev(t *testing.T) { for i, test := range tests { - if refs, err := GetMountRefsByDev(fm, test.mountPath); err != nil || !setEquivalent(test.expectedRefs, refs) { + if refs, err := getMountRefsByDev(fm, test.mountPath); err != nil || !setEquivalent(test.expectedRefs, refs) { t.Errorf("%d. getMountRefsByDev(%q) = %v, %v; expected %v, nil", i, test.mountPath, refs, err, test.expectedRefs) } } @@ -1191,10 +1191,6 @@ func TestBindSubPath(t *testing.T) { return nil, "", "", err } - if err := os.MkdirAll(subpathMount, defaultPerm); err != nil { - return nil, "", "", err - } - socketFile, socketCreateError := createSocketFile(volpath) return mounts, volpath, socketFile, socketCreateError @@ -1210,10 +1206,6 @@ func TestBindSubPath(t *testing.T) { return nil, "", "", err } - if err := os.MkdirAll(subpathMount, defaultPerm); err != nil { - return nil, "", "", err - } - testFifo := filepath.Join(volpath, "mount_test.fifo") err := syscall.Mkfifo(testFifo, 0) return mounts, volpath, testFifo, err @@ -1247,7 +1239,7 @@ func TestBindSubPath(t *testing.T) { } _, subpathMount := getTestPaths(base) - bindPathTarget, err := doBindSubPath(fm, subpath, 1) + bindPathTarget, err := doBindSubPath(fm, subpath) if test.expectError { if err == nil { t.Errorf("test %q failed: expected error, got success", test.name) @@ -1304,6 +1296,19 @@ func TestParseMountInfo(t *testing.T) { 187 23 0:58 / /var/lib/kubelet/pods/1fc5ea21-eff4-11e7-ac80-0e858b8eaf40/volumes/kubernetes.io~nfs/nfs2 rw,relatime shared:96 - nfs4 172.18.4.223:/srv/nfs2 rw,vers=4.0,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=172.18.4.223,local_lock=none,addr=172.18.4.223 188 24 0:58 / /var/lib/kubelet/pods/43219158-e5e1-11e7-a392-0e858b8eaf40/volume-subpaths/nfs1/subpath1/0 rw,relatime shared:89 - nfs4 172.18.4.223:/srv/nfs/foo rw,vers=4.0,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=172.18.4.223,local_lock=none,addr=172.18.4.223 347 60 0:71 / /var/lib/kubelet/pods/13195d46-f9fa-11e7-bbf1-5254007a695a/volumes/kubernetes.io~nfs/vol2 rw,relatime shared:170 - nfs 172.17.0.3:/exports/2 rw,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=172.17.0.3,mountvers=3,mountport=20048,mountproto=udp,local_lock=none,addr=172.17.0.3 +222 24 253:0 /tmp/src /mnt/dst rw,relatime shared:1 - ext4 /dev/mapper/vagrant--vg-root rw,errors=remount-ro,data=ordered +28 18 0:24 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755 +29 28 0:25 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd +31 28 0:27 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,cpuset +32 28 0:28 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,cpu,cpuacct +33 28 0:29 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,freezer +34 28 0:30 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,net_cls,net_prio +35 28 0:31 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,pids +36 28 0:32 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,devices +37 28 0:33 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb +38 28 0:34 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,blkio +39 28 0:35 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,memory +40 28 0:36 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,perf_event ` tempDir, filename, err := writeFile(info) if err != nil { @@ -1313,17 +1318,103 @@ func TestParseMountInfo(t *testing.T) { tests := []struct { name string - mountPoint string + id int expectedInfo mountInfo }{ { "simple bind mount", - "/var/lib/kubelet", + 189, + mountInfo{ + id: 189, + parentID: 80, + majorMinor: "8:1", + root: "/var/lib/kubelet", + source: "/dev/sda1", + mountPoint: "/var/lib/kubelet", + optionalFields: []string{"shared:30"}, + fsType: "ext4", + mountOptions: []string{"rw", "relatime"}, + superOptions: []string{"rw", "commit=30", "data=ordered"}, + }, + }, + { + "bind mount a directory", + 222, + mountInfo{ + id: 222, + parentID: 24, + majorMinor: "253:0", + root: "/tmp/src", + source: "/dev/mapper/vagrant--vg-root", + mountPoint: "/mnt/dst", + optionalFields: []string{"shared:1"}, + fsType: "ext4", + mountOptions: []string{"rw", "relatime"}, + superOptions: []string{"rw", "errors=remount-ro", "data=ordered"}, + }, + }, + { + "more than one optional fields", + 224, + mountInfo{ + id: 224, + parentID: 62, + majorMinor: "253:0", + root: "/var/lib/docker/devicemapper/test/shared", + source: "/dev/mapper/ssd-root", + mountPoint: "/var/lib/docker/devicemapper/test/shared", + optionalFields: []string{"master:1", "shared:44"}, + fsType: "ext4", + mountOptions: []string{"rw", "relatime"}, + superOptions: []string{"rw", "seclabel", "data=ordered"}, + }, + }, + { + "cgroup-mountpoint", + 28, + mountInfo{ + id: 28, + parentID: 18, + majorMinor: "0:24", + root: "/", + source: "tmpfs", + mountPoint: "/sys/fs/cgroup", + optionalFields: []string{"shared:9"}, + fsType: "tmpfs", + mountOptions: []string{"ro", "nosuid", "nodev", "noexec"}, + superOptions: []string{"ro", "mode=755"}, + }, + }, + { + "cgroup-subsystem-systemd-mountpoint", + 29, mountInfo{ - mountPoint: "/var/lib/kubelet", - optional: []string{"shared:30"}, - mountOptions: []string{"rw", "relatime"}, - superOptions: []string{"rw", "commit=30", "data=ordered"}, + id: 29, + parentID: 28, + majorMinor: "0:25", + root: "/", + source: "cgroup", + mountPoint: "/sys/fs/cgroup/systemd", + optionalFields: []string{"shared:10"}, + fsType: "cgroup", + mountOptions: []string{"rw", "nosuid", "nodev", "noexec", "relatime"}, + superOptions: []string{"rw", "xattr", "release_agent=/lib/systemd/systemd-cgroups-agent", "name=systemd"}, + }, + }, + { + "cgroup-subsystem-cpuset-mountpoint", + 31, + mountInfo{ + id: 31, + parentID: 28, + majorMinor: "0:27", + root: "/", + source: "cgroup", + mountPoint: "/sys/fs/cgroup/cpuset", + optionalFields: []string{"shared:13"}, + fsType: "cgroup", + mountOptions: []string{"rw", "nosuid", "nodev", "noexec", "relatime"}, + superOptions: []string{"rw", "cpuset"}, }, }, } @@ -1336,7 +1427,7 @@ func TestParseMountInfo(t *testing.T) { for _, test := range tests { found := false for _, info := range infos { - if info.mountPoint == test.mountPoint { + if info.id == test.id { found = true if !reflect.DeepEqual(info, test.expectedInfo) { t.Errorf("Test case %q:\n expected: %+v\n got: %+v", test.name, test.expectedInfo, info) @@ -1345,7 +1436,7 @@ func TestParseMountInfo(t *testing.T) { } } if !found { - t.Errorf("Test case %q: mountPoint %s not found", test.name, test.mountPoint) + t.Errorf("Test case %q: mountPoint %d not found", test.name, test.id) } } } @@ -1838,3 +1929,153 @@ func isOperationNotPermittedError(err error) bool { } return false } + +func TestSearchMountPoints(t *testing.T) { + base := ` +19 25 0:18 / /sys rw,nosuid,nodev,noexec,relatime shared:7 - sysfs sysfs rw +20 25 0:4 / /proc rw,nosuid,nodev,noexec,relatime shared:12 - proc proc rw +21 25 0:6 / /dev rw,nosuid,relatime shared:2 - devtmpfs udev rw,size=4058156k,nr_inodes=1014539,mode=755 +22 21 0:14 / /dev/pts rw,nosuid,noexec,relatime shared:3 - devpts devpts rw,gid=5,mode=620,ptmxmode=000 +23 25 0:19 / /run rw,nosuid,noexec,relatime shared:5 - tmpfs tmpfs rw,size=815692k,mode=755 +25 0 252:0 / / rw,relatime shared:1 - ext4 /dev/mapper/ubuntu--vg-root rw,errors=remount-ro,data=ordered +26 19 0:12 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:8 - securityfs securityfs rw +27 21 0:21 / /dev/shm rw,nosuid,nodev shared:4 - tmpfs tmpfs rw +28 23 0:22 / /run/lock rw,nosuid,nodev,noexec,relatime shared:6 - tmpfs tmpfs rw,size=5120k +29 19 0:23 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755 +30 29 0:24 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd +31 19 0:25 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:11 - pstore pstore rw +32 29 0:26 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,devices +33 29 0:27 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,freezer +34 29 0:28 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,pids +35 29 0:29 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,blkio +36 29 0:30 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,memory +37 29 0:31 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,perf_event +38 29 0:32 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb +39 29 0:33 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,cpu,cpuacct +40 29 0:34 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,cpuset +41 29 0:35 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,net_cls,net_prio +58 25 7:1 / /mnt/disks/blkvol1 rw,relatime shared:38 - ext4 /dev/loop1 rw,data=ordere +` + + testcases := []struct { + name string + source string + mountInfos string + expectedRefs []string + expectedErr error + }{ + { + "dir", + "/mnt/disks/vol1", + base, + nil, + nil, + }, + { + "dir-used", + "/mnt/disks/vol1", + base + ` +56 25 252:0 /mnt/disks/vol1 /var/lib/kubelet/pods/1890aef5-5a60-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test rw,relatime shared:1 - ext4 /dev/mapper/ubuntu--vg-root rw,errors=remount-ro,data=ordered +57 25 0:45 / /mnt/disks/vol rw,relatime shared:36 - tmpfs tmpfs rw +`, + []string{"/var/lib/kubelet/pods/1890aef5-5a60-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test"}, + nil, + }, + { + "tmpfs-vol", + "/mnt/disks/vol1", + base + `120 25 0:76 / /mnt/disks/vol1 rw,relatime shared:41 - tmpfs vol1 rw,size=10000k +`, + nil, + nil, + }, + { + "tmpfs-vol-used-by-two-pods", + "/mnt/disks/vol1", + base + `120 25 0:76 / /mnt/disks/vol1 rw,relatime shared:41 - tmpfs vol1 rw,size=10000k +196 25 0:76 / /var/lib/kubelet/pods/ade3ac21-5a5b-11e8-8559-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-8f263585 rw,relatime shared:41 - tmpfs vol1 rw,size=10000k +228 25 0:76 / /var/lib/kubelet/pods/ac60532d-5a5b-11e8-8559-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-8f263585 rw,relatime shared:41 - tmpfs vol1 rw,size=10000k +`, + []string{ + "/var/lib/kubelet/pods/ade3ac21-5a5b-11e8-8559-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-8f263585", + "/var/lib/kubelet/pods/ac60532d-5a5b-11e8-8559-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-8f263585", + }, + nil, + }, + { + "tmpfs-subdir-used-indirectly-via-bindmount-dir-by-one-pod", + "/mnt/vol1/foo", + base + `177 25 0:46 / /mnt/data rw,relatime shared:37 - tmpfs data rw +190 25 0:46 /vol1 /mnt/vol1 rw,relatime shared:37 - tmpfs data rw +191 25 0:46 /vol2 /mnt/vol2 rw,relatime shared:37 - tmpfs data rw +62 25 0:46 /vol1/foo /var/lib/kubelet/pods/e25f2f01-5b06-11e8-8694-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test rw,relatime shared:37 - tmpfs data rw +`, + []string{"/var/lib/kubelet/pods/e25f2f01-5b06-11e8-8694-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test"}, + nil, + }, + { + "dir-bindmounted", + "/mnt/disks/vol2", + base + `342 25 252:0 /mnt/disks/vol2 /mnt/disks/vol2 rw,relatime shared:1 - ext4 /dev/mapper/ubuntu--vg-root rw,errors=remount-ro,data=ordered +`, + nil, + nil, + }, + { + "dir-bindmounted-used-by-one-pod", + "/mnt/disks/vol2", + base + `342 25 252:0 /mnt/disks/vol2 /mnt/disks/vol2 rw,relatime shared:1 - ext4 /dev/mapper/ubuntu--vg-root rw,errors=remount-ro,data=ordered +77 25 252:0 /mnt/disks/vol2 /var/lib/kubelet/pods/f30dc360-5a5d-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-1fb30a1c rw,relatime shared:1 - ext4 /dev/mapper/ubuntu--vg-root rw,errors=remount-ro,data=ordered +`, + []string{"/var/lib/kubelet/pods/f30dc360-5a5d-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-1fb30a1c"}, + nil, + }, + { + "blockfs", + "/mnt/disks/blkvol1", + base + `58 25 7:1 / /mnt/disks/blkvol1 rw,relatime shared:38 - ext4 /dev/loop1 rw,data=ordered +`, + nil, + nil, + }, + { + "blockfs-used-by-one-pod", + "/mnt/disks/blkvol1", + base + `58 25 7:1 / /mnt/disks/blkvol1 rw,relatime shared:38 - ext4 /dev/loop1 rw,data=ordered +62 25 7:1 / /var/lib/kubelet/pods/f19fe4e2-5a63-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test rw,relatime shared:38 - ext4 /dev/loop1 rw,data=ordered +`, + []string{"/var/lib/kubelet/pods/f19fe4e2-5a63-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test"}, + nil, + }, + { + "blockfs-used-by-two-pods", + "/mnt/disks/blkvol1", + base + `58 25 7:1 / /mnt/disks/blkvol1 rw,relatime shared:38 - ext4 /dev/loop1 rw,data=ordered +62 25 7:1 / /var/lib/kubelet/pods/f19fe4e2-5a63-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test rw,relatime shared:38 - ext4 /dev/loop1 rw,data=ordered +95 25 7:1 / /var/lib/kubelet/pods/4854a48b-5a64-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test rw,relatime shared:38 - ext4 /dev/loop1 rw,data=ordered +`, + []string{"/var/lib/kubelet/pods/f19fe4e2-5a63-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test", + "/var/lib/kubelet/pods/4854a48b-5a64-11e8-962f-000c29bb0377/volumes/kubernetes.io~local-volume/local-pv-test"}, + nil, + }, + } + tmpFile, err := ioutil.TempFile("", "test-get-filetype") + if err != nil { + t.Fatal(err) + } + defer os.Remove(tmpFile.Name()) + defer tmpFile.Close() + for _, v := range testcases { + tmpFile.Truncate(0) + tmpFile.Seek(0, 0) + tmpFile.WriteString(v.mountInfos) + tmpFile.Sync() + refs, err := searchMountPoints(v.source, tmpFile.Name()) + if !reflect.DeepEqual(refs, v.expectedRefs) { + t.Errorf("test %q: expected Refs: %#v, got %#v", v.name, v.expectedRefs, refs) + } + if !reflect.DeepEqual(err, v.expectedErr) { + t.Errorf("test %q: expected err: %v, got %v", v.name, v.expectedErr, err) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_unsupported.go b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_unsupported.go index 4082ff571..6143aec18 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_unsupported.go @@ -27,6 +27,8 @@ type Mounter struct { mounterPath string } +var unsupportedErr = errors.New("util/mount on this platform is not supported") + // New returns a mount.Interface for the current system. // It provides options to override the default mounter behavior. // mounterPath allows using an alternative to `/bin/mount` for mounting. @@ -37,21 +39,21 @@ func New(mounterPath string) Interface { } func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error { - return nil + return unsupportedErr } func (mounter *Mounter) Unmount(target string) error { - return nil + return unsupportedErr } // 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 + return []string{}, unsupportedErr } func (mounter *Mounter) List() ([]MountPoint, error) { - return []MountPoint{}, nil + return []MountPoint{}, unsupportedErr } func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool { @@ -63,27 +65,27 @@ func (mounter *Mounter) IsNotMountPoint(dir string) (bool, error) { } func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { - return true, nil + return true, unsupportedErr } func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { - return "", nil + return "", unsupportedErr } func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (string, error) { - return "", nil + return "", unsupportedErr } func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) { - return false, nil + return false, unsupportedErr } func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) { - return true, nil + return true, unsupportedErr } func (mounter *Mounter) MakeRShared(path string) error { - return nil + return unsupportedErr } func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error { @@ -91,37 +93,49 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, } func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) { - return true, nil + return true, unsupportedErr } func (mounter *Mounter) GetFileType(pathname string) (FileType, error) { - return FileType("fake"), errors.New("not implemented") + return FileType("fake"), unsupportedErr } func (mounter *Mounter) MakeDir(pathname string) error { - return nil + return unsupportedErr } func (mounter *Mounter) MakeFile(pathname string) error { - return nil + return unsupportedErr } -func (mounter *Mounter) ExistsPath(pathname string) bool { - return true +func (mounter *Mounter) ExistsPath(pathname string) (bool, error) { + return true, errors.New("not implemented") } func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { - return subPath.Path, nil, nil + return subPath.Path, nil, unsupportedErr } func (mounter *Mounter) CleanSubPaths(podDir string, volumeName string) error { - return nil + return unsupportedErr } func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { - return nil + return unsupportedErr +} + +func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) { + return nil, errors.New("not implemented") +} + +func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { + return -1, errors.New("not implemented") } func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows.go b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows.go index 46f854634..9c9518c60 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows.go @@ -29,6 +29,8 @@ import ( "syscall" "github.com/golang/glog" + + utilfile "k8s.io/kubernetes/pkg/util/file" ) // Mounter provides the default implementation of mount.Interface @@ -81,14 +83,20 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio 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]) - bindSource = source - cmdLine += fmt.Sprintf(";New-SmbGlobalMapping -RemotePath %s -Credential $Credential", source) - if output, err := exec.Command("powershell", "/c", cmdLine).CombinedOutput(); err != nil { + // use PowerShell Environment Variables to store user input string to prevent command line injection + // https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables?view=powershell-5.1 + cmdLine := fmt.Sprintf(`$PWord = ConvertTo-SecureString -String $Env:smbpassword -AsPlainText -Force` + + `;$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Env:smbuser, $PWord` + + `;New-SmbGlobalMapping -RemotePath $Env:smbremotepath -Credential $Credential`) + + cmd := exec.Command("powershell", "/c", cmdLine) + cmd.Env = append(os.Environ(), + fmt.Sprintf("smbuser=%s", options[0]), + fmt.Sprintf("smbpassword=%s", options[1]), + fmt.Sprintf("smbremotepath=%s", source)) + if output, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("azureMount: SmbGlobalMapping failed: %v, only SMB mount is supported now, output: %q", err, string(output)) } } @@ -145,7 +153,15 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { } // If current file is a symlink, then it is a mountpoint. if stat.Mode()&os.ModeSymlink != 0 { - return false, nil + target, err := os.Readlink(file) + if err != nil { + return true, fmt.Errorf("readlink error: %v", err) + } + exists, err := mounter.ExistsPath(target) + if err != nil { + return true, err + } + return !exists, nil } return true, nil @@ -228,12 +244,8 @@ func (mounter *Mounter) MakeFile(pathname string) error { } // 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 *Mounter) ExistsPath(pathname string) (bool, error) { + return utilfile.FileExists(pathname) } // check whether hostPath is within volume path @@ -358,10 +370,23 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, glog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, source, target) if err := ValidateDiskNumber(source); err != nil { - glog.Errorf("azureMount: formatAndMount failed, err: %v\n", err) + glog.Errorf("diskMount: formatAndMount failed, err: %v", err) return err } + if len(fstype) == 0 { + // Use 'NTFS' as the default + fstype = "NTFS" + } + + // format disk if it is unformatted(raw) + cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru"+ + " | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", source, fstype) + if output, err := mounter.Exec.Run("powershell", "/c", cmd); err != nil { + return fmt.Errorf("diskMount: format disk failed, error: %v, output: %q", err, string(output)) + } + glog.V(4).Infof("diskMount: Disk successfully formatted, disk: %q, fstype: %q", source, fstype) + driveLetter, err := getDriveLetterByDiskNumber(source, mounter.Exec) if err != nil { return err @@ -438,14 +463,42 @@ func getAllParentLinks(path string) ([]string, error) { return links, nil } +func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) { + realpath, err := filepath.EvalSymlinks(pathname) + if err != nil { + return nil, err + } + return getMountRefsByDev(mounter, realpath) +} + +// Note that on windows, it always returns 0. We actually don't set FSGroup on +// windows platform, see SetVolumeOwnership implementation. +func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { + return 0, nil +} + func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) { // Windows does not support SELinux. return false, nil } +func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { + info, err := os.Stat(pathname) + if err != nil { + return 0, err + } + return info.Mode(), nil +} + // SafeMakeDir makes sure that the created directory does not escape given base directory mis-using symlinks. -func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { - return doSafeMakeDir(pathname, base, perm) +func (mounter *Mounter) SafeMakeDir(subdir string, base string, perm os.FileMode) error { + realBase, err := filepath.EvalSymlinks(base) + if err != nil { + return fmt.Errorf("error resolving symlinks in %s: %s", base, err) + } + + realFullPath := filepath.Join(realBase, subdir) + return doSafeMakeDir(realFullPath, realBase, perm) } func doSafeMakeDir(pathname string, base string, perm os.FileMode) error { diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows_test.go b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows_test.go index 12fa5152f..a6e26bec8 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows_test.go @@ -24,6 +24,7 @@ import ( "os" "os/exec" "path/filepath" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -139,7 +140,14 @@ func TestGetMountRefs(t *testing.T) { } func TestDoSafeMakeDir(t *testing.T) { - const testingVolumePath = `c:\tmp\DoSafeMakeDirTest` + base, err := ioutil.TempDir("", "TestDoSafeMakeDir") + if err != nil { + t.Fatalf(err.Error()) + } + + defer os.RemoveAll(base) + + testingVolumePath := filepath.Join(base, "testingVolumePath") os.MkdirAll(testingVolumePath, 0755) defer os.RemoveAll(testingVolumePath) @@ -171,7 +179,7 @@ func TestDoSafeMakeDir(t *testing.T) { volumePath: testingVolumePath, subPath: filepath.Join(testingVolumePath, `symlink`), expectError: false, - symlinkTarget: `c:\tmp`, + symlinkTarget: base, }, { volumePath: testingVolumePath, @@ -189,7 +197,7 @@ func TestDoSafeMakeDir(t *testing.T) { volumePath: testingVolumePath, subPath: filepath.Join(testingVolumePath, `a\b\symlink`), expectError: false, - symlinkTarget: `c:\tmp`, + symlinkTarget: base, }, { volumePath: testingVolumePath, @@ -228,7 +236,14 @@ func TestDoSafeMakeDir(t *testing.T) { } func TestLockAndCheckSubPath(t *testing.T) { - const testingVolumePath = `c:\tmp\LockAndCheckSubPathTest` + base, err := ioutil.TempDir("", "TestLockAndCheckSubPath") + if err != nil { + t.Fatalf(err.Error()) + } + + defer os.RemoveAll(base) + + testingVolumePath := filepath.Join(base, "testingVolumePath") tests := []struct { volumePath string @@ -270,14 +285,14 @@ func TestLockAndCheckSubPath(t *testing.T) { subPath: filepath.Join(testingVolumePath, `symlink`), expectedHandleCount: 0, expectError: true, - symlinkTarget: `c:\tmp`, + symlinkTarget: base, }, { volumePath: testingVolumePath, subPath: filepath.Join(testingVolumePath, `a\b\c\symlink`), expectedHandleCount: 0, expectError: true, - symlinkTarget: `c:\tmp`, + symlinkTarget: base, }, { volumePath: testingVolumePath, @@ -325,7 +340,14 @@ func TestLockAndCheckSubPath(t *testing.T) { } func TestLockAndCheckSubPathWithoutSymlink(t *testing.T) { - const testingVolumePath = `c:\tmp\LockAndCheckSubPathWithoutSymlinkTest` + base, err := ioutil.TempDir("", "TestLockAndCheckSubPathWithoutSymlink") + if err != nil { + t.Fatalf(err.Error()) + } + + defer os.RemoveAll(base) + + testingVolumePath := filepath.Join(base, "testingVolumePath") tests := []struct { volumePath string @@ -367,14 +389,14 @@ func TestLockAndCheckSubPathWithoutSymlink(t *testing.T) { subPath: filepath.Join(testingVolumePath, `symlink`), expectedHandleCount: 1, expectError: true, - symlinkTarget: `c:\tmp`, + symlinkTarget: base, }, { volumePath: testingVolumePath, subPath: filepath.Join(testingVolumePath, `a\b\c\symlink`), expectedHandleCount: 4, expectError: true, - symlinkTarget: `c:\tmp`, + symlinkTarget: base, }, { volumePath: testingVolumePath, @@ -422,7 +444,14 @@ func TestLockAndCheckSubPathWithoutSymlink(t *testing.T) { } func TestFindExistingPrefix(t *testing.T) { - const testingVolumePath = `c:\tmp\FindExistingPrefixTest` + base, err := ioutil.TempDir("", "TestFindExistingPrefix") + if err != nil { + t.Fatalf(err.Error()) + } + + defer os.RemoveAll(base) + + testingVolumePath := filepath.Join(base, "testingVolumePath") tests := []struct { base string @@ -601,3 +630,166 @@ func TestGetFileType(t *testing.T) { } } } + +func TestIsLikelyNotMountPoint(t *testing.T) { + mounter := Mounter{"fake/path"} + + tests := []struct { + fileName string + targetLinkName string + setUp func(base, fileName, targetLinkName string) error + expectedResult bool + expectError bool + }{ + { + "Dir", + "", + func(base, fileName, targetLinkName string) error { + return os.Mkdir(filepath.Join(base, fileName), 0750) + }, + true, + false, + }, + { + "InvalidDir", + "", + func(base, fileName, targetLinkName string) error { + return nil + }, + true, + true, + }, + { + "ValidSymLink", + "targetSymLink", + func(base, fileName, targetLinkName string) error { + targeLinkPath := filepath.Join(base, targetLinkName) + if err := os.Mkdir(targeLinkPath, 0750); err != nil { + return err + } + + filePath := filepath.Join(base, fileName) + if err := makeLink(filePath, targeLinkPath); err != nil { + return err + } + return nil + }, + false, + false, + }, + { + "InvalidSymLink", + "targetSymLink2", + func(base, fileName, targetLinkName string) error { + targeLinkPath := filepath.Join(base, targetLinkName) + if err := os.Mkdir(targeLinkPath, 0750); err != nil { + return err + } + + filePath := filepath.Join(base, fileName) + if err := makeLink(filePath, targeLinkPath); err != nil { + return err + } + return removeLink(targeLinkPath) + }, + true, + false, + }, + } + + for _, test := range tests { + base, err := ioutil.TempDir("", test.fileName) + if err != nil { + t.Fatalf(err.Error()) + } + + defer os.RemoveAll(base) + + if err := test.setUp(base, test.fileName, test.targetLinkName); err != nil { + t.Fatalf("unexpected error in setUp(%s, %s): %v", test.fileName, test.targetLinkName, err) + } + + filePath := filepath.Join(base, test.fileName) + result, err := mounter.IsLikelyNotMountPoint(filePath) + assert.Equal(t, result, test.expectedResult, "Expect result not equal with IsLikelyNotMountPoint(%s) return: %q, expected: %q", + filePath, result, test.expectedResult) + + if test.expectError { + assert.NotNil(t, err, "Expect error during IsLikelyNotMountPoint(%s)", filePath) + } else { + assert.Nil(t, err, "Expect error is nil during IsLikelyNotMountPoint(%s)", filePath) + } + } +} + +func TestFormatAndMount(t *testing.T) { + fakeMounter := ErrorMounter{&FakeMounter{}, 0, nil} + execCallback := func(cmd string, args ...string) ([]byte, error) { + for j := range args { + if strings.Contains(args[j], "Get-Disk -Number") { + return []byte("0"), nil + } + + if strings.Contains(args[j], "Get-Partition -DiskNumber") { + return []byte("0"), nil + } + + if strings.Contains(args[j], "mklink") { + return nil, nil + } + } + return nil, fmt.Errorf("Unexpected cmd %s, args %v", cmd, args) + } + fakeExec := NewFakeExec(execCallback) + + mounter := SafeFormatAndMount{ + Interface: &fakeMounter, + Exec: fakeExec, + } + + tests := []struct { + device string + target string + fstype string + mountOptions []string + expectError bool + }{ + { + "0", + "disk", + "NTFS", + []string{}, + false, + }, + { + "0", + "disk", + "", + []string{}, + false, + }, + { + "invalidDevice", + "disk", + "NTFS", + []string{}, + true, + }, + } + + for _, test := range tests { + base, err := ioutil.TempDir("", test.device) + if err != nil { + t.Fatalf(err.Error()) + } + defer os.RemoveAll(base) + + target := filepath.Join(base, test.target) + err = mounter.FormatAndMount(test.device, target, test.fstype, test.mountOptions) + if test.expectError { + assert.NotNil(t, err, "Expect error during FormatAndMount(%s, %s, %s, %v)", test.device, test.target, test.fstype, test.mountOptions) + } else { + assert.Nil(t, err, "Expect error is nil during FormatAndMount(%s, %s, %s, %v)", test.device, test.target, test.fstype, test.mountOptions) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go b/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go index f7ffe955c..a122411ce 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go @@ -22,12 +22,12 @@ import ( "fmt" "os" "path/filepath" - "regexp" - "strconv" "strings" + "syscall" "github.com/golang/glog" - utilio "k8s.io/kubernetes/pkg/util/io" + "golang.org/x/sys/unix" + utilfile "k8s.io/kubernetes/pkg/util/file" "k8s.io/kubernetes/pkg/util/nsenter" ) @@ -36,13 +36,6 @@ const ( hostProcMountsPath = "/rootfs/proc/1/mounts" // hostProcMountinfoPath is the default mount info path for rootfs hostProcMountinfoPath = "/rootfs/proc/1/mountinfo" - // hostProcSelfStatusPath is the default path to /proc/self/status on the host - hostProcSelfStatusPath = "/rootfs/proc/self/status" -) - -var ( - // pidRegExp matches "Pid: " in /proc/self/status - pidRegExp = regexp.MustCompile(`\nPid:\t([0-9]*)\n`) ) // Currently, all docker containers receive their own mount namespaces. @@ -50,10 +43,16 @@ var ( // the host's mount namespace. type NsenterMounter struct { ne *nsenter.Nsenter + // rootDir is location of /var/lib/kubelet directory. + rootDir string } -func NewNsenterMounter() *NsenterMounter { - return &NsenterMounter{ne: nsenter.NewNsenter()} +// NewNsenterMounter creates a new mounter for kubelet that runs as a container. +func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { + return &NsenterMounter{ + rootDir: rootDir, + ne: ne, + } } // NsenterMounter implements mount.Interface @@ -277,53 +276,177 @@ func (mounter *NsenterMounter) MakeFile(pathname string) error { return nil } -func (mounter *NsenterMounter) ExistsPath(pathname string) bool { - args := []string{pathname} - _, err := mounter.ne.Exec("ls", args).CombinedOutput() - if err == nil { - return true +func (mounter *NsenterMounter) ExistsPath(pathname string) (bool, error) { + // Resolve the symlinks but allow the target not to exist. EvalSymlinks + // would return an generic error when the target does not exist. + hostPath, err := mounter.ne.EvalSymlinks(pathname, false /* mustExist */) + if err != nil { + return false, err } - return false + kubeletpath := mounter.ne.KubeletPath(hostPath) + return utilfile.FileExists(kubeletpath) } func (mounter *NsenterMounter) CleanSubPaths(podDir string, volumeName string) error { return doCleanSubPaths(mounter, podDir, volumeName) } -// getPidOnHost returns kubelet's pid in the host pid namespace -func (mounter *NsenterMounter) getPidOnHost(procStatusPath string) (int, error) { - // Get the PID from /rootfs/proc/self/status - statusBytes, err := utilio.ConsistentRead(procStatusPath, maxListTries) +func (mounter *NsenterMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { + // Bind-mount the subpath to avoid using symlinks in subpaths. + newHostPath, err = doNsEnterBindSubPath(mounter, subPath) + + // There is no action when the container starts. Bind-mount will be cleaned + // when container stops by CleanSubPaths. + cleanupAction = nil + return newHostPath, cleanupAction, err +} + +func (mounter *NsenterMounter) SafeMakeDir(subdir string, base string, perm os.FileMode) error { + fullSubdirPath := filepath.Join(base, subdir) + evaluatedSubdirPath, err := mounter.ne.EvalSymlinks(fullSubdirPath, false /* mustExist */) if err != nil { - return 0, fmt.Errorf("error reading %s: %s", procStatusPath, err) + return fmt.Errorf("error resolving symlinks in %s: %s", fullSubdirPath, err) } - matches := pidRegExp.FindSubmatch(statusBytes) - if len(matches) < 2 { - return 0, fmt.Errorf("cannot parse %s: no Pid:", procStatusPath) + evaluatedSubdirPath = filepath.Clean(evaluatedSubdirPath) + + evaluatedBase, err := mounter.ne.EvalSymlinks(base, true /* mustExist */) + if err != nil { + return fmt.Errorf("error resolving symlinks in %s: %s", base, err) + } + evaluatedBase = filepath.Clean(evaluatedBase) + + rootDir := filepath.Clean(mounter.rootDir) + if pathWithinBase(evaluatedBase, rootDir) { + // Base is in /var/lib/kubelet. This directory is shared between the + // container with kubelet and the host. We don't need to add '/rootfs'. + // This is useful when /rootfs is mounted as read-only - we can still + // create subpaths for paths in /var/lib/kubelet. + return doSafeMakeDir(evaluatedSubdirPath, evaluatedBase, perm) } - return strconv.Atoi(string(matches[1])) + + // Base is somewhere on the host's filesystem. Add /rootfs and try to make + // the directory there. + // This requires /rootfs to be writable. + kubeletSubdirPath := mounter.ne.KubeletPath(evaluatedSubdirPath) + kubeletBase := mounter.ne.KubeletPath(evaluatedBase) + return doSafeMakeDir(kubeletSubdirPath, kubeletBase, perm) } -func (mounter *NsenterMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { - hostPid, err := mounter.getPidOnHost(hostProcSelfStatusPath) +func (mounter *NsenterMounter) GetMountRefs(pathname string) ([]string, error) { + hostpath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) if err != nil { - return "", nil, err + return nil, err } - glog.V(4).Infof("Kubelet's PID on the host is %d", hostPid) + return searchMountPoints(hostpath, hostProcMountinfoPath) +} - // Bind-mount the subpath to avoid using symlinks in subpaths. - newHostPath, err = doBindSubPath(mounter, subPath, hostPid) +func doNsEnterBindSubPath(mounter *NsenterMounter, subpath Subpath) (hostPath string, err error) { + // Linux, kubelet runs in a container: + // - safely open the subpath + // - bind-mount the subpath to target (this can be unsafe) + // - check that we mounted the right thing by comparing device ID and inode + // of the subpath (via safely opened fd) and the target (that's under our + // control) - // There is no action when the container starts. Bind-mount will be cleaned - // when container stops by CleanSubPaths. - cleanupAction = nil - return newHostPath, cleanupAction, err + // Evaluate all symlinks here once for all subsequent functions. + evaluatedHostVolumePath, err := mounter.ne.EvalSymlinks(subpath.VolumePath, true /*mustExist*/) + if err != nil { + return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.VolumePath, err) + } + evaluatedHostSubpath, err := mounter.ne.EvalSymlinks(subpath.Path, true /*mustExist*/) + if err != nil { + return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.Path, err) + } + glog.V(5).Infof("doBindSubPath %q (%q) for volumepath %q", subpath.Path, evaluatedHostSubpath, subpath.VolumePath) + subpath.VolumePath = mounter.ne.KubeletPath(evaluatedHostVolumePath) + subpath.Path = mounter.ne.KubeletPath(evaluatedHostSubpath) + + // Check the subpath is correct and open it + fd, err := safeOpenSubPath(mounter, subpath) + if err != nil { + return "", err + } + defer syscall.Close(fd) + + alreadyMounted, bindPathTarget, err := prepareSubpathTarget(mounter, subpath) + if err != nil { + return "", err + } + if alreadyMounted { + return bindPathTarget, nil + } + + success := false + defer func() { + // Cleanup subpath on error + if !success { + glog.V(4).Infof("doNsEnterBindSubPath() failed for %q, cleaning up subpath", bindPathTarget) + if cleanErr := cleanSubPath(mounter, subpath); cleanErr != nil { + glog.Errorf("Failed to clean subpath %q: %v", bindPathTarget, cleanErr) + } + } + }() + + // Leap of faith: optimistically expect that nobody has modified previously + // expanded evalSubPath with evil symlinks and bind-mount it. + // Mount is done on the host! don't use kubelet path! + glog.V(5).Infof("bind mounting %q at %q", evaluatedHostSubpath, bindPathTarget) + if err = mounter.Mount(evaluatedHostSubpath, bindPathTarget, "" /*fstype*/, []string{"bind"}); err != nil { + return "", fmt.Errorf("error mounting %s: %s", evaluatedHostSubpath, err) + } + + // Check that the bind-mount target is the same inode and device as the + // source that we keept open, i.e. we mounted the right thing. + err = checkDeviceInode(fd, bindPathTarget) + if err != nil { + return "", fmt.Errorf("error checking bind mount for subpath %s: %s", subpath.VolumePath, err) + } + + success = true + glog.V(3).Infof("Bound SubPath %s into %s", subpath.Path, bindPathTarget) + return bindPathTarget, nil +} + +// checkDeviceInode checks that opened file and path represent the same file. +func checkDeviceInode(fd int, path string) error { + var srcStat, dstStat unix.Stat_t + err := unix.Fstat(fd, &srcStat) + if err != nil { + return fmt.Errorf("error running fstat on subpath FD: %v", err) + } + + err = unix.Stat(path, &dstStat) + if err != nil { + return fmt.Errorf("error running fstat on %s: %v", path, err) + } + + if srcStat.Dev != dstStat.Dev { + return fmt.Errorf("different device number") + } + if srcStat.Ino != dstStat.Ino { + return fmt.Errorf("different inode") + } + return nil } -func (mounter *NsenterMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { - return doSafeMakeDir(pathname, base, perm) +func (mounter *NsenterMounter) GetFSGroup(pathname string) (int64, error) { + hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) + if err != nil { + return -1, err + } + kubeletpath := mounter.ne.KubeletPath(hostPath) + return getFSGroup(kubeletpath) } func (mounter *NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { - return getSELinuxSupport(pathname, procMountInfoPath) + return getSELinuxSupport(pathname, hostProcMountsPath) +} + +func (mounter *NsenterMounter) GetMode(pathname string) (os.FileMode, error) { + hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) + if err != nil { + return 0, err + } + kubeletpath := mounter.ne.KubeletPath(hostPath) + return getMode(kubeletpath) } diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_test.go b/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_test.go index 2aee4ad5f..c541a4cdf 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_test.go @@ -21,9 +21,12 @@ package mount import ( "io/ioutil" "os" - "path" - "strconv" + "path/filepath" + "strings" "testing" + + "golang.org/x/sys/unix" + "k8s.io/kubernetes/pkg/util/nsenter" ) func TestParseFindMnt(t *testing.T) { @@ -72,120 +75,635 @@ func TestParseFindMnt(t *testing.T) { } } -func TestGetPidOnHost(t *testing.T) { - tempDir, err := ioutil.TempDir("", "get_pid_on_host_tests") +func TestCheckDeviceInode(t *testing.T) { + testDir, err := ioutil.TempDir("", "nsenter-mounter-device-") + if err != nil { + t.Fatalf("Cannot create temporary directory: %s", err) + } + defer os.RemoveAll(testDir) + + tests := []struct { + name string + srcPath string + dstPath string + expectError string + }{ + { + name: "the same file", + srcPath: filepath.Join(testDir, "1"), + dstPath: filepath.Join(testDir, "1"), + expectError: "", + }, + { + name: "different file on the same FS", + srcPath: filepath.Join(testDir, "2.1"), + dstPath: filepath.Join(testDir, "2.2"), + expectError: "different inode", + }, + { + name: "different file on different device", + srcPath: filepath.Join(testDir, "3"), + // /proc is always on a different "device" than /tmp (or $TEMP) + dstPath: "/proc/self/status", + expectError: "different device", + }, + } + + for _, test := range tests { + if err := ioutil.WriteFile(test.srcPath, []byte{}, 0644); err != nil { + t.Errorf("Test %q: cannot create srcPath %s: %s", test.name, test.srcPath, err) + continue + } + + // Don't create dst if it exists + if _, err := os.Stat(test.dstPath); os.IsNotExist(err) { + if err := ioutil.WriteFile(test.dstPath, []byte{}, 0644); err != nil { + t.Errorf("Test %q: cannot create dstPath %s: %s", test.name, test.dstPath, err) + continue + } + } else if err != nil { + t.Errorf("Test %q: cannot check existence of dstPath %s: %s", test.name, test.dstPath, err) + continue + } + + fd, err := unix.Open(test.srcPath, unix.O_CREAT, 0644) + if err != nil { + t.Errorf("Test %q: cannot open srcPath %s: %s", test.name, test.srcPath, err) + continue + } + + err = checkDeviceInode(fd, test.dstPath) + + if test.expectError == "" && err != nil { + t.Errorf("Test %q: expected no error, got %s", test.name, err) + } + if test.expectError != "" { + if err == nil { + t.Errorf("Test %q: expected error, got none", test.name) + } else { + if !strings.Contains(err.Error(), test.expectError) { + t.Errorf("Test %q: expected error %q, got %q", test.name, test.expectError, err) + } + } + } + } +} + +func newFakeNsenterMounter(tmpdir string, t *testing.T) (mounter *NsenterMounter, rootfsPath string, varlibPath string, err error) { + rootfsPath = filepath.Join(tmpdir, "rootfs") + if err := os.Mkdir(rootfsPath, 0755); err != nil { + return nil, "", "", err + } + ne, err := nsenter.NewFakeNsenter(rootfsPath) if err != nil { - t.Fatalf(err.Error()) + return nil, "", "", err + } + + varlibPath = filepath.Join(tmpdir, "/var/lib/kubelet") + if err := os.MkdirAll(varlibPath, 0755); err != nil { + return nil, "", "", err + } + + return NewNsenterMounter(varlibPath, ne), rootfsPath, varlibPath, nil +} + +func TestNsenterExistsFile(t *testing.T) { + tests := []struct { + name string + prepare func(base, rootfs string) (string, error) + expectedOutput bool + expectError bool + }{ + { + name: "simple existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/file + path := filepath.Join(base, "file") + if err := ioutil.WriteFile(path, []byte{}, 0644); err != nil { + return "", err + } + // In kubelet: /rootfs/base/file + if _, err := writeRootfsFile(rootfs, path, 0644); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: true, + }, + { + name: "simple non-existing file", + prepare: func(base, rootfs string) (string, error) { + path := filepath.Join(base, "file") + return path, nil + }, + expectedOutput: false, + }, + { + name: "simple non-accessible file", + prepare: func(base, rootfs string) (string, error) { + // On the host: + // create /base/dir/file, then make the dir inaccessible + dir := filepath.Join(base, "dir") + if err := os.MkdirAll(dir, 0755); err != nil { + return "", err + } + path := filepath.Join(dir, "file") + if err := ioutil.WriteFile(path, []byte{}, 0); err != nil { + return "", err + } + if err := os.Chmod(dir, 0644); err != nil { + return "", err + } + + // In kubelet: do the same with /rootfs/base/dir/file + rootfsPath, err := writeRootfsFile(rootfs, path, 0777) + if err != nil { + return "", err + } + rootfsDir := filepath.Dir(rootfsPath) + if err := os.Chmod(rootfsDir, 0644); err != nil { + return "", err + } + + return path, nil + }, + expectedOutput: false, + expectError: true, + }, + { + name: "relative symlink to existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/link -> file + file := filepath.Join(base, "file") + if err := ioutil.WriteFile(file, []byte{}, 0); err != nil { + return "", err + } + path := filepath.Join(base, "link") + if err := os.Symlink("file", path); err != nil { + return "", err + } + // In kubelet: /rootfs/base/file + if _, err := writeRootfsFile(rootfs, file, 0644); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: true, + }, + { + name: "absolute symlink to existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/link -> /base/file + file := filepath.Join(base, "file") + if err := ioutil.WriteFile(file, []byte{}, 0); err != nil { + return "", err + } + path := filepath.Join(base, "link") + if err := os.Symlink(file, path); err != nil { + return "", err + } + // In kubelet: /rootfs/base/file + if _, err := writeRootfsFile(rootfs, file, 0644); err != nil { + return "", err + } + + return path, nil + }, + expectedOutput: true, + }, + { + name: "relative symlink to non-existing file", + prepare: func(base, rootfs string) (string, error) { + path := filepath.Join(base, "link") + if err := os.Symlink("file", path); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: false, + }, + { + name: "absolute symlink to non-existing file", + prepare: func(base, rootfs string) (string, error) { + file := filepath.Join(base, "file") + path := filepath.Join(base, "link") + if err := os.Symlink(file, path); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: false, + }, + { + name: "symlink loop", + prepare: func(base, rootfs string) (string, error) { + path := filepath.Join(base, "link") + if err := os.Symlink(path, path); err != nil { + return "", err + } + return path, nil + }, + expectedOutput: false, + // TODO: realpath -m is not able to detect symlink loop. Should we care? + expectError: false, + }, + } + + for _, test := range tests { + tmpdir, err := ioutil.TempDir("", "nsenter-exists-file") + if err != nil { + t.Error(err) + continue + } + defer os.RemoveAll(tmpdir) + + testBase := filepath.Join(tmpdir, "base") + if err := os.Mkdir(testBase, 0755); err != nil { + t.Error(err) + continue + } + + mounter, rootfs, _, err := newFakeNsenterMounter(tmpdir, t) + if err != nil { + t.Error(err) + continue + } + + path, err := test.prepare(testBase, rootfs) + if err != nil { + t.Error(err) + continue + } + + out, err := mounter.ExistsPath(path) + if err != nil && !test.expectError { + t.Errorf("Test %q: unexpected error: %s", test.name, err) + } + if err == nil && test.expectError { + t.Errorf("Test %q: expected error, got none", test.name) + } + + if out != test.expectedOutput { + t.Errorf("Test %q: expected return value %v, got %v", test.name, test.expectedOutput, out) + } + } +} + +func TestNsenterGetMode(t *testing.T) { + tests := []struct { + name string + prepare func(base, rootfs string) (string, error) + expectedMode os.FileMode + expectError bool + }{ + { + name: "simple file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/file + path := filepath.Join(base, "file") + if err := ioutil.WriteFile(path, []byte{}, 0644); err != nil { + return "", err + } + + // Prepare a different file as /rootfs/base/file (="the host + // visible from container") to check that NsEnterMounter calls + // stat on this file and not on /base/file. + // Visible from kubelet: /rootfs/base/file + if _, err := writeRootfsFile(rootfs, path, 0777); err != nil { + return "", err + } + + return path, nil + }, + expectedMode: 0777, + }, + { + name: "non-existing file", + prepare: func(base, rootfs string) (string, error) { + path := filepath.Join(base, "file") + return path, nil + }, + expectedMode: 0, + expectError: true, + }, + { + name: "absolute symlink to existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/link -> /base/file + file := filepath.Join(base, "file") + if err := ioutil.WriteFile(file, []byte{}, 0644); err != nil { + return "", err + } + path := filepath.Join(base, "link") + if err := os.Symlink(file, path); err != nil { + return "", err + } + + // Visible from kubelet: + // /rootfs/base/file + if _, err := writeRootfsFile(rootfs, file, 0747); err != nil { + return "", err + } + + return path, nil + }, + expectedMode: 0747, + }, + { + name: "relative symlink to existing file", + prepare: func(base, rootfs string) (string, error) { + // On the host: /base/link -> file + file := filepath.Join(base, "file") + if err := ioutil.WriteFile(file, []byte{}, 0741); err != nil { + return "", err + } + path := filepath.Join(base, "link") + if err := os.Symlink("file", path); err != nil { + return "", err + } + + // Visible from kubelet: + // /rootfs/base/file + if _, err := writeRootfsFile(rootfs, file, 0647); err != nil { + return "", err + } + + return path, nil + }, + expectedMode: 0647, + }, + } + + for _, test := range tests { + tmpdir, err := ioutil.TempDir("", "nsenter-get-mode-") + if err != nil { + t.Error(err) + continue + } + defer os.RemoveAll(tmpdir) + + testBase := filepath.Join(tmpdir, "base") + if err := os.Mkdir(testBase, 0755); err != nil { + t.Error(err) + continue + } + + mounter, rootfs, _, err := newFakeNsenterMounter(tmpdir, t) + if err != nil { + t.Error(err) + continue + } + + path, err := test.prepare(testBase, rootfs) + if err != nil { + t.Error(err) + continue + } + + mode, err := mounter.GetMode(path) + if err != nil && !test.expectError { + t.Errorf("Test %q: unexpected error: %s", test.name, err) + } + if err == nil && test.expectError { + t.Errorf("Test %q: expected error, got none", test.name) + } + + if mode != test.expectedMode { + t.Errorf("Test %q: expected return value %v, got %v", test.name, test.expectedMode, mode) + } + } +} + +func writeRootfsFile(rootfs, path string, mode os.FileMode) (string, error) { + fullPath := filepath.Join(rootfs, path) + dir := filepath.Dir(fullPath) + if err := os.MkdirAll(dir, 0755); err != nil { + return "", err + } + if err := ioutil.WriteFile(fullPath, []byte{}, mode); err != nil { + return "", err + } + // Use chmod, io.WriteFile is affected by umask + if err := os.Chmod(fullPath, mode); err != nil { + return "", err } - defer os.RemoveAll(tempDir) + return fullPath, nil +} +func TestNsenterSafeMakeDir(t *testing.T) { tests := []struct { name string - procFile string - expectedPid int + prepare func(base, rootfs, varlib string) (expectedDir string, err error) + subdir string expectError bool + // If true, "base" directory for SafeMakeDir will be /var/lib/kubelet + baseIsVarLib bool }{ { - name: "valid status file", - procFile: `Name: cat -Umask: 0002 -State: R (running) -Tgid: 15041 -Ngid: 0 -Pid: 15041 -PPid: 22699 -TracerPid: 0 -Uid: 1000 1000 1000 1000 -Gid: 1000 1000 1000 1000 -FDSize: 256 -Groups: 10 135 156 157 158 973 984 1000 1001 -NStgid: 15041 -NSpid: 15041 -NSpgid: 15041 -NSsid: 22699 -VmPeak: 115016 kB -VmSize: 115016 kB -VmLck: 0 kB -VmPin: 0 kB -VmHWM: 816 kB -VmRSS: 816 kB -RssAnon: 64 kB -RssFile: 752 kB -RssShmem: 0 kB -VmData: 312 kB -VmStk: 136 kB -VmExe: 32 kB -VmLib: 2060 kB -VmPTE: 44 kB -VmPMD: 12 kB -VmSwap: 0 kB -HugetlbPages: 0 kB -Threads: 1 -SigQ: 2/60752 -SigPnd: 0000000000000000 -ShdPnd: 0000000000000000 -SigBlk: 0000000000000000 -SigIgn: 0000000000000000 -SigCgt: 0000000000000000 -CapInh: 0000000000000000 -CapPrm: 0000000000000000 -CapEff: 0000000000000000 -CapBnd: 0000003fffffffff -CapAmb: 0000000000000000 -NoNewPrivs: 0 -Seccomp: 0 -Cpus_allowed: ff -Cpus_allowed_list: 0-7 -Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001 -Mems_allowed_list: 0 -voluntary_ctxt_switches: 0 -nonvoluntary_ctxt_switches: 0 -`, - expectedPid: 15041, - }, - { - name: "no Pid:", - procFile: `Name: cat -Umask: 0002 -State: R (running) -Tgid: 15041 -Ngid: 0 -PPid: 22699 -`, - expectedPid: 0, + name: "simple directory", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // expected to be created in /roots/ + expectedDir = filepath.Join(rootfs, base, "some/subdirectory/structure") + return expectedDir, nil + }, + }, + { + name: "simple existing directory", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: directory exists + hostPath := filepath.Join(base, "some/subdirectory/structure") + if err := os.MkdirAll(hostPath, 0755); err != nil { + return "", err + } + // In rootfs: directory exists + kubeletPath := filepath.Join(rootfs, hostPath) + if err := os.MkdirAll(kubeletPath, 0755); err != nil { + return "", err + } + // expected to be created in /roots/ + expectedDir = kubeletPath + return expectedDir, nil + }, + }, + { + name: "absolute symlink into safe place", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /base/other/subdirectory exists, /base/some is link to /base/other + hostPath := filepath.Join(base, "other/subdirectory") + if err := os.MkdirAll(hostPath, 0755); err != nil { + return "", err + } + somePath := filepath.Join(base, "some") + otherPath := filepath.Join(base, "other") + if err := os.Symlink(otherPath, somePath); err != nil { + return "", err + } + + // In rootfs: /base/other/subdirectory exists + kubeletPath := filepath.Join(rootfs, hostPath) + if err := os.MkdirAll(kubeletPath, 0755); err != nil { + return "", err + } + // expected 'structure' to be created + expectedDir = filepath.Join(rootfs, hostPath, "structure") + return expectedDir, nil + }, + }, + { + name: "relative symlink into safe place", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /base/other/subdirectory exists, /base/some is link to other + hostPath := filepath.Join(base, "other/subdirectory") + if err := os.MkdirAll(hostPath, 0755); err != nil { + return "", err + } + somePath := filepath.Join(base, "some") + if err := os.Symlink("other", somePath); err != nil { + return "", err + } + + // In rootfs: /base/other/subdirectory exists + kubeletPath := filepath.Join(rootfs, hostPath) + if err := os.MkdirAll(kubeletPath, 0755); err != nil { + return "", err + } + // expected 'structure' to be created + expectedDir = filepath.Join(rootfs, hostPath, "structure") + return expectedDir, nil + }, + }, + { + name: "symlink into unsafe place", + // evaluated in base + subdir: "some/subdirectory/structure", + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /base/some is link to /bin/other + somePath := filepath.Join(base, "some") + if err := os.Symlink("/bin", somePath); err != nil { + return "", err + } + return "", nil + }, expectError: true, }, { - name: "invalid Pid:", - procFile: `Name: cat -Umask: 0002 -State: R (running) -Tgid: 15041 -Ngid: 0 -Pid: invalid -PPid: 22699 -`, - expectedPid: 0, + name: "simple directory in /var/lib/kubelet", + // evaluated in varlib + subdir: "some/subdirectory/structure", + baseIsVarLib: true, + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // expected to be created in /base/var/lib/kubelet, not in /rootfs! + expectedDir = filepath.Join(varlib, "some/subdirectory/structure") + return expectedDir, nil + }, + }, + { + name: "safe symlink in /var/lib/kubelet", + // evaluated in varlib + subdir: "some/subdirectory/structure", + baseIsVarLib: true, + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /varlib/kubelet/other/subdirectory exists, /varlib/some is link to other + hostPath := filepath.Join(varlib, "other/subdirectory") + if err := os.MkdirAll(hostPath, 0755); err != nil { + return "", err + } + somePath := filepath.Join(varlib, "some") + if err := os.Symlink("other", somePath); err != nil { + return "", err + } + + // expected to be created in /base/var/lib/kubelet, not in /rootfs! + expectedDir = filepath.Join(varlib, "other/subdirectory/structure") + return expectedDir, nil + }, + }, + { + name: "unsafe symlink in /var/lib/kubelet", + // evaluated in varlib + subdir: "some/subdirectory/structure", + baseIsVarLib: true, + prepare: func(base, rootfs, varlib string) (expectedDir string, err error) { + // On the host: /varlib/some is link to /bin + somePath := filepath.Join(varlib, "some") + if err := os.Symlink("/bin", somePath); err != nil { + return "", err + } + + return "", nil + }, expectError: true, }, } + for _, test := range tests { + tmpdir, err := ioutil.TempDir("", "nsenter-get-mode-") + if err != nil { + t.Error(err) + continue + } + defer os.RemoveAll(tmpdir) - for i, test := range tests { - filename := path.Join(tempDir, strconv.Itoa(i)) - err := ioutil.WriteFile(filename, []byte(test.procFile), 0666) + mounter, rootfs, varlib, err := newFakeNsenterMounter(tmpdir, t) if err != nil { - t.Fatalf(err.Error()) + t.Error(err) + continue + } + // Prepare base directory for the test + testBase := filepath.Join(tmpdir, "base") + if err := os.Mkdir(testBase, 0755); err != nil { + t.Error(err) + continue } - mounter := NsenterMounter{} - pid, err := mounter.getPidOnHost(filename) + // Prepare base directory also in /rootfs + rootfsBase := filepath.Join(rootfs, testBase) + if err := os.MkdirAll(rootfsBase, 0755); err != nil { + t.Error(err) + continue + } + + expectedDir := "" + if test.prepare != nil { + expectedDir, err = test.prepare(testBase, rootfs, varlib) + if err != nil { + t.Error(err) + continue + } + } + + if test.baseIsVarLib { + // use /var/lib/kubelet as the test base so we can test creating + // subdirs there directly in /var/lib/kubenet and not in + // /rootfs/var/lib/kubelet + testBase = varlib + } + + err = mounter.SafeMakeDir(test.subdir, testBase, 0755) if err != nil && !test.expectError { t.Errorf("Test %q: unexpected error: %s", test.name, err) } - if err == nil && test.expectError { - t.Errorf("Test %q: expected error, got none", test.name) + if test.expectError { + if err == nil { + t.Errorf("Test %q: expected error, got none", test.name) + } else { + if !strings.Contains(err.Error(), "is outside of allowed base") { + t.Errorf("Test %q: expected error to contain \"is outside of allowed base\", got this one instead: %s", test.name, err) + } + } } - if pid != test.expectedPid { - t.Errorf("Test %q: expected pid %d, got %d", test.name, test.expectedPid, pid) + + if expectedDir != "" { + _, err := os.Stat(expectedDir) + if err != nil { + t.Errorf("Test %q: expected %q to exist, got error: %s", test.name, expectedDir, err) + } } } } diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_unsupported.go b/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_unsupported.go index 022f3b7ee..f417ba9bc 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_unsupported.go @@ -21,11 +21,13 @@ package mount import ( "errors" "os" + + "k8s.io/kubernetes/pkg/util/nsenter" ) type NsenterMounter struct{} -func NewNsenterMounter() *NsenterMounter { +func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { return &NsenterMounter{} } @@ -83,8 +85,8 @@ func (*NsenterMounter) MakeFile(pathname string) error { return nil } -func (*NsenterMounter) ExistsPath(pathname string) bool { - return true +func (*NsenterMounter) ExistsPath(pathname string) (bool, error) { + return true, errors.New("not implemented") } func (*NsenterMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { @@ -99,6 +101,18 @@ func (*NsenterMounter) CleanSubPaths(podDir string, volumeName string) error { return nil } +func (*NsenterMounter) GetMountRefs(pathname string) ([]string, error) { + return nil, errors.New("not implemented") +} + +func (*NsenterMounter) GetFSGroup(pathname string) (int64, error) { + return -1, errors.New("not implemented") +} + func (*NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } + +func (*NsenterMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/safe_format_and_mount_test.go b/vendor/k8s.io/kubernetes/pkg/util/mount/safe_format_and_mount_test.go index 20bfeb9f6..506126b30 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/mount/safe_format_and_mount_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/mount/safe_format_and_mount_test.go @@ -116,7 +116,7 @@ func TestSafeFormatAndMount(t *testing.T) { execScripts: []ExecArgs{ {"fsck", []string{"-a", "/dev/foo"}, "", nil}, {"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}}, - {"mkfs.ext4", []string{"-F", "/dev/foo"}, "", fmt.Errorf("formatting failed")}, + {"mkfs.ext4", []string{"-F", "-m0", "/dev/foo"}, "", fmt.Errorf("formatting failed")}, }, expectedError: fmt.Errorf("formatting failed"), }, @@ -127,7 +127,7 @@ func TestSafeFormatAndMount(t *testing.T) { execScripts: []ExecArgs{ {"fsck", []string{"-a", "/dev/foo"}, "", nil}, {"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}}, - {"mkfs.ext4", []string{"-F", "/dev/foo"}, "", nil}, + {"mkfs.ext4", []string{"-F", "-m0", "/dev/foo"}, "", nil}, }, expectedError: fmt.Errorf("Still cannot mount"), }, @@ -138,7 +138,7 @@ func TestSafeFormatAndMount(t *testing.T) { execScripts: []ExecArgs{ {"fsck", []string{"-a", "/dev/foo"}, "", nil}, {"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}}, - {"mkfs.ext4", []string{"-F", "/dev/foo"}, "", nil}, + {"mkfs.ext4", []string{"-F", "-m0", "/dev/foo"}, "", nil}, }, expectedError: nil, }, @@ -149,7 +149,7 @@ func TestSafeFormatAndMount(t *testing.T) { execScripts: []ExecArgs{ {"fsck", []string{"-a", "/dev/foo"}, "", nil}, {"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}}, - {"mkfs.ext3", []string{"-F", "/dev/foo"}, "", nil}, + {"mkfs.ext3", []string{"-F", "-m0", "/dev/foo"}, "", nil}, }, expectedError: nil, }, diff --git a/vendor/k8s.io/kubernetes/pkg/util/nsenter/BUILD b/vendor/k8s.io/kubernetes/pkg/util/nsenter/BUILD index 988fef01b..286b88827 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/nsenter/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/util/nsenter/BUILD @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -92,3 +92,20 @@ filegroup( tags = ["automanaged"], visibility = ["//visibility:public"], ) + +go_test( + name = "go_default_test", + srcs = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "nsenter_test.go", + ], + "//conditions:default": [], + }), + embed = [":go_default_library"], + deps = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "//vendor/k8s.io/utils/exec:go_default_library", + ], + "//conditions:default": [], + }), +) diff --git a/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter.go b/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter.go index 32fbc0848..e928a57ac 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter.go +++ b/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter.go @@ -19,9 +19,12 @@ limitations under the License. package nsenter import ( + "context" + "errors" "fmt" "os" "path/filepath" + "strings" "k8s.io/utils/exec" @@ -29,9 +32,11 @@ import ( ) const ( - hostRootFsPath = "/rootfs" - // hostProcMountNsPath is the default mount namespace for rootfs - hostProcMountNsPath = "/rootfs/proc/1/ns/mnt" + // DefaultHostRootFsPath is path to host's filesystem mounted into container + // with kubelet. + DefaultHostRootFsPath = "/rootfs" + // mountNsPath is the default mount namespace of the host + mountNsPath = "/proc/1/ns/mnt" // nsenterPath is the default nsenter command nsenterPath = "nsenter" ) @@ -57,55 +62,73 @@ const ( // 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 +// 7. The host image should have systemd-run in /bin, /usr/sbin, or /usr/bin if +// systemd is installed/enabled in the operating system. // 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 + + // Path to the host filesystem, typically "/rootfs". Used only for testing. + hostRootFsPath string + + // Exec implementation, used only for testing + executor exec.Interface } // NewNsenter constructs a new instance of Nsenter -func NewNsenter() *Nsenter { +func NewNsenter(hostRootFsPath string, executor exec.Interface) (*Nsenter, error) { ne := &Nsenter{ - paths: map[string]string{ - "mount": "", - "findmnt": "", - "umount": "", - "systemd-run": "", - "stat": "", - "touch": "", - "mkdir": "", - "ls": "", - "sh": "", - "chmod": "", - }, + hostRootFsPath: hostRootFsPath, + executor: executor, + } + if err := ne.initPaths(); err != nil { + return nil, err + } + return ne, nil +} + +func (ne *Nsenter) initPaths() error { + ne.paths = map[string]string{} + binaries := []string{ + "mount", + "findmnt", + "umount", + "systemd-run", + "stat", + "touch", + "mkdir", + "sh", + "chmod", + "realpath", } // 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"} { + for _, binary := range binaries { + // check for binary under the following directories + for _, path := range []string{"/", "/bin", "/usr/sbin", "/usr/bin"} { binPath := filepath.Join(path, binary) - if _, err := os.Stat(filepath.Join(hostRootFsPath, binPath)); err != nil { + if _, err := os.Stat(filepath.Join(ne.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) + // systemd-run is optional, bailout if we don't find any of the other binaries + if ne.paths[binary] == "" && binary != "systemd-run" { + return fmt.Errorf("unable to find %v", binary) + } } - return ne + return nil } // Exec executes nsenter commands in hostProcMountNsPath mount namespace func (ne *Nsenter) Exec(cmd string, args []string) exec.Cmd { + hostProcMountNsPath := filepath.Join(ne.hostRootFsPath, mountNsPath) 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...) + return ne.executor.Command(nsenterPath, fullArgs...) } // AbsHostPath returns the absolute runnable path for a specified command @@ -119,6 +142,95 @@ func (ne *Nsenter) AbsHostPath(command string) string { // SupportsSystemd checks whether command systemd-run exists func (ne *Nsenter) SupportsSystemd() (string, bool) { - systemdRunPath, hasSystemd := ne.paths["systemd-run"] - return systemdRunPath, hasSystemd + systemdRunPath, ok := ne.paths["systemd-run"] + return systemdRunPath, ok && systemdRunPath != "" +} + +// EvalSymlinks returns the path name on the host after evaluating symlinks on the +// host. +// mustExist makes EvalSymlinks to return error when the path does not +// exist. When it's false, it evaluates symlinks of the existing part and +// blindly adds the non-existing part: +// pathname: /mnt/volume/non/existing/directory +// /mnt/volume exists +// non/existing/directory does not exist +// -> It resolves symlinks in /mnt/volume to say /mnt/foo and returns +// /mnt/foo/non/existing/directory. +// +// BEWARE! EvalSymlinks is not able to detect symlink looks with mustExist=false! +// If /tmp/link is symlink to /tmp/link, EvalSymlinks(/tmp/link/foo) returns /tmp/link/foo. +func (ne *Nsenter) EvalSymlinks(pathname string, mustExist bool) (string, error) { + var args []string + if mustExist { + // "realpath -e: all components of the path must exist" + args = []string{"-e", pathname} + } else { + // "realpath -m: no path components need exist or be a directory" + args = []string{"-m", pathname} + } + outBytes, err := ne.Exec("realpath", args).CombinedOutput() + if err != nil { + glog.Infof("failed to resolve symbolic links on %s: %v", pathname, err) + return "", err + } + return strings.TrimSpace(string(outBytes)), nil +} + +// KubeletPath returns the path name that can be accessed by containerized +// kubelet. It is recommended to resolve symlinks on the host by EvalSymlinks +// before calling this function +func (ne *Nsenter) KubeletPath(pathname string) string { + return filepath.Join(ne.hostRootFsPath, pathname) +} + +// NewFakeNsenter returns a Nsenter that does not run "nsenter --mount=... --", +// but runs everything in the same mount namespace as the unit test binary. +// rootfsPath is supposed to be a symlink, e.g. /tmp/xyz/rootfs -> /. +// This fake Nsenter is enough for most operations, e.g. to resolve symlinks, +// but it's not enough to call /bin/mount - unit tests don't run as root. +func NewFakeNsenter(rootfsPath string) (*Nsenter, error) { + executor := &fakeExec{ + rootfsPath: rootfsPath, + } + // prepare /rootfs/bin, usr/bin and usr/sbin + bin := filepath.Join(rootfsPath, "bin") + if err := os.Symlink("/bin", bin); err != nil { + return nil, err + } + + usr := filepath.Join(rootfsPath, "usr") + if err := os.Mkdir(usr, 0755); err != nil { + return nil, err + } + usrbin := filepath.Join(usr, "bin") + if err := os.Symlink("/usr/bin", usrbin); err != nil { + return nil, err + } + usrsbin := filepath.Join(usr, "sbin") + if err := os.Symlink("/usr/sbin", usrsbin); err != nil { + return nil, err + } + + return NewNsenter(rootfsPath, executor) +} + +type fakeExec struct { + rootfsPath string +} + +func (f fakeExec) Command(cmd string, args ...string) exec.Cmd { + // This will intentionaly panic if Nsenter does not provide enough arguments. + realCmd := args[2] + realArgs := args[3:] + return exec.New().Command(realCmd, realArgs...) +} + +func (fakeExec) LookPath(file string) (string, error) { + return "", errors.New("not implemented") +} + +func (fakeExec) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { + return nil } + +var _ exec.Interface = fakeExec{} diff --git a/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter_test.go b/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter_test.go new file mode 100644 index 000000000..3158a55bb --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter_test.go @@ -0,0 +1,311 @@ +// +build linux + +/* +Copyright 2018 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 ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "k8s.io/utils/exec" +) + +func TestExec(t *testing.T) { + tests := []struct { + name string + command string + args []string + expectedOutput string + expectError bool + }{ + { + name: "simple command", + command: "echo", + args: []string{"hello", "world"}, + expectedOutput: "hello world\n", + }, + { + name: "nozero exit code", + command: "false", + expectError: true, + }, + } + + executor := fakeExec{ + rootfsPath: "/rootfs", + } + for _, test := range tests { + ns := Nsenter{ + hostRootFsPath: "/rootfs", + executor: executor, + } + cmd := ns.Exec(test.command, test.args) + outBytes, err := cmd.CombinedOutput() + out := string(outBytes) + if err != nil && !test.expectError { + t.Errorf("Test %q: unexpected error: %s", test.name, err) + } + if err == nil && test.expectError { + t.Errorf("Test %q: expected error, got none", test.name) + } + if test.expectedOutput != out { + t.Errorf("test %q: expected output %q, got %q", test.name, test.expectedOutput, out) + } + } +} + +func TestKubeletPath(t *testing.T) { + tests := []struct { + rootfs string + hostpath string + expectedKubeletPath string + }{ + { + // simple join + "/rootfs", + "/some/path", + "/rootfs/some/path", + }, + { + // squash slashes + "/rootfs/", + "//some/path", + "/rootfs/some/path", + }, + } + + for _, test := range tests { + ns := Nsenter{ + hostRootFsPath: test.rootfs, + } + out := ns.KubeletPath(test.hostpath) + if out != test.expectedKubeletPath { + t.Errorf("Expected path %q, got %q", test.expectedKubeletPath, out) + } + + } +} + +func TestEvalSymlinks(t *testing.T) { + tests := []struct { + name string + mustExist bool + prepare func(tmpdir string) (src string, expectedDst string, err error) + expectError bool + }{ + { + name: "simple file /src", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + src = filepath.Join(tmpdir, "src") + err = ioutil.WriteFile(src, []byte{}, 0644) + return src, src, err + }, + }, + { + name: "non-existing file /src", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + src = filepath.Join(tmpdir, "src") + return src, "", nil + }, + expectError: true, + }, + { + name: "non-existing file /src/ with mustExist=false", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + src = filepath.Join(tmpdir, "src") + return src, src, nil + }, + }, + { + name: "non-existing file /existing/path/src with mustExist=false with existing directories", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + src = filepath.Join(tmpdir, "existing/path") + if err := os.MkdirAll(src, 0755); err != nil { + return "", "", err + } + src = filepath.Join(src, "src") + return src, src, nil + }, + }, + { + name: "simple symlink /src -> /dst", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "dst") + if err = ioutil.WriteFile(dst, []byte{}, 0644); err != nil { + return "", "", err + } + src = filepath.Join(tmpdir, "src") + err = os.Symlink(dst, src) + return src, dst, err + }, + }, + { + name: "dangling symlink /src -> /non-existing-path", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "non-existing-path") + src = filepath.Join(tmpdir, "src") + err = os.Symlink(dst, src) + return src, "", err + }, + expectError: true, + }, + { + name: "dangling symlink /src -> /non-existing-path with mustExist=false", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "non-existing-path") + src = filepath.Join(tmpdir, "src") + err = os.Symlink(dst, src) + return src, dst, err + }, + }, + { + name: "symlink to directory /src/file, where /src is link to /dst", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "dst") + if err = os.Mkdir(dst, 0755); err != nil { + return "", "", err + } + dstFile := filepath.Join(dst, "file") + if err = ioutil.WriteFile(dstFile, []byte{}, 0644); err != nil { + return "", "", err + } + + src = filepath.Join(tmpdir, "src") + if err = os.Symlink(dst, src); err != nil { + return "", "", err + } + srcFile := filepath.Join(src, "file") + return srcFile, dstFile, nil + }, + }, + { + name: "symlink to non-existing directory: /src/file, where /src is link to /dst and dst does not exist", + mustExist: true, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "dst") + + src = filepath.Join(tmpdir, "src") + if err = os.Symlink(dst, src); err != nil { + return "", "", err + } + srcFile := filepath.Join(src, "file") + return srcFile, "", nil + }, + expectError: true, + }, + { + name: "symlink to non-existing directory: /src/file, where /src is link to /dst and dst does not exist with mustExist=false", + mustExist: false, + prepare: func(tmpdir string) (src string, expectedDst string, err error) { + dst := filepath.Join(tmpdir, "dst") + dstFile := filepath.Join(dst, "file") + + src = filepath.Join(tmpdir, "src") + if err = os.Symlink(dst, src); err != nil { + return "", "", err + } + srcFile := filepath.Join(src, "file") + return srcFile, dstFile, nil + }, + }, + } + + for _, test := range tests { + ns := Nsenter{ + hostRootFsPath: "/rootfs", + executor: fakeExec{ + rootfsPath: "/rootfs", + }, + } + + tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + src, expectedDst, err := test.prepare(tmpdir) + if err != nil { + t.Error(err) + continue + } + + dst, err := ns.EvalSymlinks(src, test.mustExist) + if err != nil && !test.expectError { + t.Errorf("Test %q: unexpected error: %s", test.name, err) + } + if err == nil && test.expectError { + t.Errorf("Test %q: expected error, got none", test.name) + } + if dst != expectedDst { + t.Errorf("Test %q: expected destination %q, got %q", test.name, expectedDst, dst) + } + } +} + +func TestNewNsenter(t *testing.T) { + // Create a symlink /tmp/xyz/rootfs -> / and use it as rootfs path + // It should resolve all binaries correctly, the test runs on Linux + + tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + rootfs := filepath.Join(tmpdir, "rootfs") + if err = os.Symlink("/", rootfs); err != nil { + t.Fatal(err) + } + + _, err = NewNsenter(rootfs, exec.New()) + if err != nil { + t.Errorf("Error: %s", err) + } +} + +func TestNewNsenterError(t *testing.T) { + // Create empty dir /tmp/xyz/rootfs and use it as rootfs path + // It should resolve all binaries correctly, the test runs on Linux + + tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + rootfs := filepath.Join(tmpdir, "rootfs") + if err = os.MkdirAll(rootfs, 0755); err != nil { + t.Fatal(err) + } + + _, err = NewNsenter(rootfs, exec.New()) + if err == nil { + t.Errorf("Expected error, got none") + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter_unsupported.go b/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter_unsupported.go index 9c2130cb6..0618b9da4 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter_unsupported.go @@ -22,6 +22,12 @@ import ( "k8s.io/utils/exec" ) +const ( + // DefaultHostRootFsPath is path to host's filesystem mounted into container + // with kubelet. + DefaultHostRootFsPath = "/rootfs" +) + // Nsenter is part of experimental support for running the kubelet // in a container. type Nsenter struct { @@ -30,8 +36,8 @@ type Nsenter struct { } // NewNsenter constructs a new instance of Nsenter -func NewNsenter() *Nsenter { - return &Nsenter{} +func NewNsenter(hostRootFsPath string, executor exec.Interface) (*Nsenter, error) { + return &Nsenter{}, nil } // Exec executes nsenter commands in hostProcMountNsPath mount namespace diff --git a/vendor/k8s.io/kubernetes/pkg/util/pod/BUILD b/vendor/k8s.io/kubernetes/pkg/util/pod/BUILD new file mode 100644 index 000000000..57a081ab7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/pod/BUILD @@ -0,0 +1,39 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["pod.go"], + importpath = "k8s.io/kubernetes/pkg/util/pod", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["pod_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/util/pod/pod.go b/vendor/k8s.io/kubernetes/pkg/util/pod/pod.go new file mode 100644 index 000000000..81d4304fa --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/pod/pod.go @@ -0,0 +1,63 @@ +/* +Copyright 2018 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 pod + +import ( + "encoding/json" + "fmt" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/strategicpatch" + clientset "k8s.io/client-go/kubernetes" +) + +// PatchPodStatus patches pod status. +func PatchPodStatus(c clientset.Interface, namespace, name string, oldPodStatus, newPodStatus v1.PodStatus) (*v1.Pod, []byte, error) { + patchBytes, err := preparePatchBytesforPodStatus(namespace, name, oldPodStatus, newPodStatus) + if err != nil { + return nil, nil, err + } + + updatedPod, err := c.CoreV1().Pods(namespace).Patch(name, types.StrategicMergePatchType, patchBytes, "status") + if err != nil { + return nil, nil, fmt.Errorf("failed to patch status %q for pod %q/%q: %v", patchBytes, namespace, name, err) + } + return updatedPod, patchBytes, nil +} + +func preparePatchBytesforPodStatus(namespace, name string, oldPodStatus, newPodStatus v1.PodStatus) ([]byte, error) { + oldData, err := json.Marshal(v1.Pod{ + Status: oldPodStatus, + }) + if err != nil { + return nil, fmt.Errorf("failed to Marshal oldData for pod %q/%q: %v", namespace, name, err) + } + + newData, err := json.Marshal(v1.Pod{ + Status: newPodStatus, + }) + if err != nil { + return nil, fmt.Errorf("failed to Marshal newData for pod %q/%q: %v", namespace, name, err) + } + + patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Pod{}) + if err != nil { + return nil, fmt.Errorf("failed to CreateTwoWayMergePatch for pod %q/%q: %v", namespace, name, err) + } + return patchBytes, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/pod/pod_test.go b/vendor/k8s.io/kubernetes/pkg/util/pod/pod_test.go new file mode 100644 index 000000000..af0278fa0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/util/pod/pod_test.go @@ -0,0 +1,116 @@ +/* +Copyright 2018 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 pod + +import ( + "testing" + + "fmt" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" + "reflect" +) + +func TestPatchPodStatus(t *testing.T) { + ns := "ns" + name := "name" + client := &fake.Clientset{} + client.CoreV1().Pods(ns).Create(&v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: name, + }, + }) + + testCases := []struct { + description string + mutate func(input v1.PodStatus) v1.PodStatus + expectedPatchBytes []byte + }{ + { + "no change", + func(input v1.PodStatus) v1.PodStatus { return input }, + []byte(fmt.Sprintf(`{}`)), + }, + { + "message change", + func(input v1.PodStatus) v1.PodStatus { + input.Message = "random message" + return input + }, + []byte(fmt.Sprintf(`{"status":{"message":"random message"}}`)), + }, + { + "pod condition change", + func(input v1.PodStatus) v1.PodStatus { + input.Conditions[0].Status = v1.ConditionFalse + return input + }, + []byte(fmt.Sprintf(`{"status":{"$setElementOrder/conditions":[{"type":"Ready"},{"type":"PodScheduled"}],"conditions":[{"status":"False","type":"Ready"}]}}`)), + }, + { + "additional init container condition", + func(input v1.PodStatus) v1.PodStatus { + input.InitContainerStatuses = []v1.ContainerStatus{ + { + Name: "init-container", + Ready: true, + }, + } + return input + }, + []byte(fmt.Sprintf(`{"status":{"initContainerStatuses":[{"image":"","imageID":"","lastState":{},"name":"init-container","ready":true,"restartCount":0,"state":{}}]}}`)), + }, + } + for _, tc := range testCases { + _, patchBytes, err := PatchPodStatus(client, ns, name, getPodStatus(), tc.mutate(getPodStatus())) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !reflect.DeepEqual(patchBytes, tc.expectedPatchBytes) { + t.Errorf("for test case %q, expect patchBytes: %q, got: %q\n", tc.description, tc.expectedPatchBytes, patchBytes) + } + } +} + +func getPodStatus() v1.PodStatus { + return v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + { + Type: v1.PodScheduled, + Status: v1.ConditionTrue, + }, + }, + ContainerStatuses: []v1.ContainerStatus{ + { + Name: "container1", + Ready: true, + }, + { + Name: "container2", + Ready: true, + }, + }, + Message: "Message", + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/pointer/pointer.go b/vendor/k8s.io/kubernetes/pkg/util/pointer/pointer.go index a970bf7f5..1a517e12c 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/pointer/pointer.go +++ b/vendor/k8s.io/kubernetes/pkg/util/pointer/pointer.go @@ -48,8 +48,12 @@ func AllPtrFieldsNil(obj interface{}) bool { // Int32Ptr returns a pointer to an int32 func Int32Ptr(i int32) *int32 { - o := i - return &o + return &i +} + +// Int64Ptr returns a pointer to an int64 +func Int64Ptr(i int64) *int64 { + return &i } // Int32PtrDerefOr dereference the int32 ptr and returns it i not nil, @@ -63,6 +67,5 @@ func Int32PtrDerefOr(ptr *int32, def int32) int32 { // BoolPtr returns a pointer to a bool func BoolPtr(b bool) *bool { - o := b - return &o + return &b } diff --git a/vendor/k8s.io/kubernetes/pkg/util/removeall/removeall_test.go b/vendor/k8s.io/kubernetes/pkg/util/removeall/removeall_test.go index 91d6f1c32..1b67cc981 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/removeall/removeall_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/removeall/removeall_test.go @@ -75,8 +75,8 @@ func (mounter *fakeMounter) MakeFile(pathname string) error { return nil } -func (mounter *fakeMounter) ExistsPath(pathname string) bool { - return true +func (mounter *fakeMounter) ExistsPath(pathname string) (bool, error) { + return true, errors.New("not implemented") } func (mounter *fakeMounter) PrepareSafeSubpath(subPath mount.Subpath) (newHostPath string, cleanupAction func(), err error) { @@ -91,10 +91,22 @@ func (mounter *fakeMounter) SafeMakeDir(_, _ string, _ os.FileMode) error { return nil } +func (mounter *fakeMounter) GetMountRefs(pathname string) ([]string, error) { + return nil, errors.New("not implemented") +} + +func (mounter *fakeMounter) GetFSGroup(pathname string) (int64, error) { + return -1, errors.New("not implemented") +} + func (mounter *fakeMounter) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } +func (mounter *fakeMounter) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} + func (mounter *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { name := path.Base(file) if strings.HasPrefix(name, "mount") { diff --git a/vendor/k8s.io/kubernetes/pkg/util/verify-util-pkg.sh b/vendor/k8s.io/kubernetes/pkg/util/verify-util-pkg.sh index 755924a09..5c1fbecc7 100755 --- a/vendor/k8s.io/kubernetes/pkg/util/verify-util-pkg.sh +++ b/vendor/k8s.io/kubernetes/pkg/util/verify-util-pkg.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -41,7 +41,7 @@ pushd "${BASH_DIR}" > /dev/null done popd > /dev/null -if [[ ${ret} > 0 ]]; then +if [[ ${ret} -gt 0 ]]; then exit ${ret} fi diff --git a/vendor/k8s.io/kubernetes/pkg/volume/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/BUILD index ffcd7bc4d..28c8c8a68 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/BUILD @@ -56,6 +56,7 @@ go_library( "//pkg/volume/util/fs:go_default_library", "//pkg/volume/util/recyclerclient:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -63,6 +64,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/BUILD index 5354b9e31..506240f67 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/BUILD @@ -19,6 +19,7 @@ go_library( deps = [ "//pkg/cloudprovider:go_default_library", "//pkg/cloudprovider/providers/aws:go_default_library", + "//pkg/features:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/strings:go_default_library", "//pkg/volume:go_default_library", @@ -29,6 +30,7 @@ go_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/types:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/attacher.go b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/attacher.go index 059431e16..ac716ed1b 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/attacher.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/attacher.go @@ -59,7 +59,7 @@ func (plugin *awsElasticBlockStorePlugin) GetDeviceMountRefs(deviceMountPath str } func (attacher *awsElasticBlockStoreAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) { - volumeSource, readOnly, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { return "", err } @@ -68,7 +68,7 @@ func (attacher *awsElasticBlockStoreAttacher) Attach(spec *volume.Spec, nodeName // awsCloud.AttachDisk checks if disk is already attached to node and // succeeds in that case, so no need to do that separately. - devicePath, err := attacher.awsVolumes.AttachDisk(volumeID, nodeName, readOnly) + devicePath, err := attacher.awsVolumes.AttachDisk(volumeID, nodeName) if err != nil { glog.Errorf("Error attaching volume %q to node %q: %+v", volumeID, nodeName, err) return "", err diff --git a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/attacher_test.go b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/attacher_test.go index 1076d0691..36ed854d1 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/attacher_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/attacher_test.go @@ -76,15 +76,14 @@ type testcase struct { func TestAttachDetach(t *testing.T) { diskName := aws.KubernetesVolumeID("disk") nodeName := types.NodeName("instance") - readOnly := false - spec := createVolSpec(diskName, readOnly) + spec := createVolSpec(diskName, false) attachError := errors.New("Fake attach error") detachError := errors.New("Fake detach error") tests := []testcase{ // Successful Attach call { name: "Attach_Positive", - attach: attachCall{diskName, nodeName, readOnly, "/dev/sda", nil}, + attach: attachCall{diskName, nodeName, "/dev/sda", nil}, test: func(testcase *testcase) (string, error) { attacher := newAttacher(testcase) return attacher.Attach(spec, nodeName) @@ -95,7 +94,7 @@ func TestAttachDetach(t *testing.T) { // Attach call fails { name: "Attach_Negative", - attach: attachCall{diskName, nodeName, readOnly, "", attachError}, + attach: attachCall{diskName, nodeName, "", attachError}, test: func(testcase *testcase) (string, error) { attacher := newAttacher(testcase) return attacher.Attach(spec, nodeName) @@ -195,7 +194,6 @@ func createPVSpec(name aws.KubernetesVolumeID, readOnly bool) *volume.Spec { type attachCall struct { diskName aws.KubernetesVolumeID nodeName types.NodeName - readOnly bool retDeviceName string ret error } @@ -214,7 +212,7 @@ type diskIsAttachedCall struct { ret error } -func (testcase *testcase) AttachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName, readOnly bool) (string, error) { +func (testcase *testcase) AttachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName) (string, error) { expected := &testcase.attach if expected.diskName == "" && expected.nodeName == "" { @@ -234,12 +232,7 @@ func (testcase *testcase) AttachDisk(diskName aws.KubernetesVolumeID, nodeName t return "", errors.New("Unexpected AttachDisk call: wrong nodeName") } - if expected.readOnly != readOnly { - testcase.t.Errorf("Unexpected AttachDisk call: expected readOnly %v, got %v", expected.readOnly, readOnly) - return "", errors.New("Unexpected AttachDisk call: wrong readOnly") - } - - glog.V(4).Infof("AttachDisk call: %s, %s, %v, returning %q, %v", diskName, nodeName, readOnly, expected.retDeviceName, expected.ret) + glog.V(4).Infof("AttachDisk call: %s, %s, returning %q, %v", diskName, nodeName, expected.retDeviceName, expected.ret) return expected.retDeviceName, expected.ret } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs.go b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs.go index 869d06773..4ba24bd6f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs.go @@ -17,10 +17,11 @@ limitations under the License. package aws_ebs import ( + "context" "fmt" "os" - "path" "path/filepath" + "regexp" "strconv" "strings" @@ -29,7 +30,9 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/mount" kstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" @@ -94,6 +97,47 @@ func (plugin *awsElasticBlockStorePlugin) SupportsBulkVolumeVerification() bool return true } +func (plugin *awsElasticBlockStorePlugin) GetVolumeLimits() (map[string]int64, error) { + volumeLimits := map[string]int64{ + util.EBSVolumeLimitKey: 39, + } + cloud := plugin.host.GetCloudProvider() + + // if we can't fetch cloudprovider we return an error + // hoping external CCM or admin can set it. Returning + // default values from here will mean, no one can + // override them. + if cloud == nil { + return nil, fmt.Errorf("No cloudprovider present") + } + + if cloud.ProviderName() != aws.ProviderName { + return nil, fmt.Errorf("Expected aws cloud, found %s", cloud.ProviderName()) + } + + instances, ok := cloud.Instances() + if !ok { + glog.V(3).Infof("Failed to get instances from cloud provider") + return volumeLimits, nil + } + + instanceType, err := instances.InstanceType(context.TODO(), plugin.host.GetNodeName()) + if err != nil { + glog.Errorf("Failed to get instance type from AWS cloud provider") + return volumeLimits, nil + } + + if ok, _ := regexp.MatchString("^[cm]5.*", instanceType); ok { + volumeLimits[util.EBSVolumeLimitKey] = 25 + } + + return volumeLimits, nil +} + +func (plugin *awsElasticBlockStorePlugin) VolumeLimitKey(spec *volume.Spec) string { + return util.EBSVolumeLimitKey +} + func (plugin *awsElasticBlockStorePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode { return []v1.PersistentVolumeAccessMode{ v1.ReadWriteOnce, @@ -266,6 +310,7 @@ func (plugin *awsElasticBlockStorePlugin) ExpandVolumeDevice( } var _ volume.ExpandableVolumePlugin = &awsElasticBlockStorePlugin{} +var _ volume.VolumePluginWithAttachLimits = &awsElasticBlockStorePlugin{} // Abstract interface to PD operations. type ebsManager interface { @@ -387,12 +432,12 @@ func makeGlobalPDPath(host volume.VolumeHost, volumeID aws.KubernetesVolumeID) s // Clean up the URI to be more fs-friendly name := string(volumeID) name = strings.Replace(name, "://", "/", -1) - return path.Join(host.GetPluginDir(awsElasticBlockStorePluginName), mount.MountsInGlobalPDPath, name) + return filepath.Join(host.GetPluginDir(awsElasticBlockStorePluginName), mount.MountsInGlobalPDPath, name) } // Reverses the mapping done in makeGlobalPDPath func getVolumeIDFromGlobalMount(host volume.VolumeHost, globalPath string) (string, error) { - basePath := path.Join(host.GetPluginDir(awsElasticBlockStorePluginName), mount.MountsInGlobalPDPath) + basePath := filepath.Join(host.GetPluginDir(awsElasticBlockStorePluginName), mount.MountsInGlobalPDPath) rel, err := filepath.Rel(basePath, globalPath) if err != nil { glog.Errorf("Failed to get volume id from global mount %s - %v", globalPath, err) @@ -454,7 +499,7 @@ type awsElasticBlockStoreProvisioner struct { var _ volume.Provisioner = &awsElasticBlockStoreProvisioner{} -func (c *awsElasticBlockStoreProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *awsElasticBlockStoreProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } @@ -508,5 +553,9 @@ func (c *awsElasticBlockStoreProvisioner) Provision() (*v1.PersistentVolume, err } } + if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + pv.Spec.VolumeMode = c.options.PVC.Spec.VolumeMode + } + return pv, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_block.go b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_block.go index d104bafa5..5eaefb23f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_block.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_block.go @@ -18,7 +18,6 @@ package aws_ebs import ( "fmt" - "path" "path/filepath" "strconv" "strings" @@ -30,6 +29,7 @@ import ( "k8s.io/kubernetes/pkg/util/mount" kstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" ) @@ -156,6 +156,10 @@ func (b *awsElasticBlockStoreMapper) SetUpDevice() (string, error) { return "", nil } +func (b *awsElasticBlockStoreMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + // GetGlobalMapPath returns global map path and error // path: plugins/kubernetes.io/{PluginName}/volumeDevices/volumeID // plugins/kubernetes.io/aws-ebs/volumeDevices/vol-XXXXXX @@ -164,7 +168,7 @@ func (ebs *awsElasticBlockStore) GetGlobalMapPath(spec *volume.Spec) (string, er if err != nil { return "", err } - return path.Join(ebs.plugin.host.GetVolumeDevicePluginDir(awsElasticBlockStorePluginName), string(volumeSource.VolumeID)), nil + return filepath.Join(ebs.plugin.host.GetVolumeDevicePluginDir(awsElasticBlockStorePluginName), string(volumeSource.VolumeID)), nil } // GetPodDeviceMapPath returns pod device map path and volume name diff --git a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_block_test.go b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_block_test.go index a1a4ba37d..5181492d6 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_block_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_block_test.go @@ -18,7 +18,7 @@ package aws_ebs import ( "os" - "path" + "path/filepath" "testing" "k8s.io/api/core/v1" @@ -47,7 +47,7 @@ func TestGetVolumeSpecFromGlobalMapPath(t *testing.T) { //deferred clean up defer os.RemoveAll(tmpVDir) - expectedGlobalPath := path.Join(tmpVDir, testGlobalPath) + expectedGlobalPath := filepath.Join(tmpVDir, testGlobalPath) //Bad Path badspec, err := getVolumeSpecFromGlobalMapPath("") @@ -102,8 +102,8 @@ func TestGetPodAndPluginMapPaths(t *testing.T) { //deferred clean up defer os.RemoveAll(tmpVDir) - expectedGlobalPath := path.Join(tmpVDir, testGlobalPath) - expectedPodPath := path.Join(tmpVDir, testPodPath) + expectedGlobalPath := filepath.Join(tmpVDir, testGlobalPath) + expectedPodPath := filepath.Join(tmpVDir, testPodPath) spec := getTestVolume(false, true /*isBlock*/) plugMgr := volume.VolumePluginMgr{} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_test.go b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_test.go index 95d81c049..f5ceb20f1 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/aws_ebs/aws_ebs_test.go @@ -19,7 +19,7 @@ package aws_ebs import ( "fmt" "os" - "path" + "path/filepath" "testing" "k8s.io/api/core/v1" @@ -129,7 +129,7 @@ func TestPlugin(t *testing.T) { t.Errorf("Got a nil Mounter") } - volPath := path.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~aws-ebs/vol1") + volPath := filepath.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~aws-ebs/vol1") path := mounter.GetPath() if path != volPath { t.Errorf("Got unexpected path: %s", path) @@ -173,7 +173,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Errorf("Error creating new provisioner:%v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/BUILD index 163c75e25..cb1ccc3bf 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/BUILD @@ -12,6 +12,7 @@ go_library( "attacher.go", "azure_common.go", "azure_dd.go", + "azure_dd_block.go", "azure_mounter.go", "azure_provision.go", ] + select({ @@ -55,13 +56,15 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/cloudprovider:go_default_library", "//pkg/cloudprovider/providers/azure:go_default_library", + "//pkg/features:go_default_library", "//pkg/util/keymutex:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/strings:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/util:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/compute:go_default_library", - "//vendor/github.com/Azure/azure-sdk-for-go/arm/storage:go_default_library", + "//pkg/volume/util/volumepathhandler:go_default_library", + "//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute:go_default_library", + "//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -69,6 +72,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) @@ -89,6 +93,7 @@ go_test( name = "go_default_test", srcs = [ "azure_common_test.go", + "azure_dd_block_test.go", "azure_dd_test.go", ], embed = [":go_default_library"], @@ -97,6 +102,8 @@ go_test( "//pkg/volume:go_default_library", "//pkg/volume/testing:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/client-go/util/testing:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/attacher.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/attacher.go index 3a00b86d2..adfd1ab72 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/attacher.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/attacher.go @@ -20,14 +20,14 @@ import ( "context" "fmt" "os" - "path" "path/filepath" "runtime" "strconv" "time" - "github.com/Azure/azure-sdk-for-go/arm/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" "github.com/golang/glog" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" @@ -57,7 +57,7 @@ var getLunMutex = keymutex.NewKeyMutex() // Attach attaches a volume.Spec to an Azure VM referenced by NodeName, returning the disk's LUN func (a *azureDiskAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) { - volumeSource, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { glog.Warningf("failed to get azure disk spec (%v)", err) return "", err @@ -114,7 +114,7 @@ func (a *azureDiskAttacher) VolumesAreAttached(specs []*volume.Spec, nodeName ty volumeSpecMap := make(map[string]*volume.Spec) volumeIDList := []string{} for _, spec := range specs { - volumeSource, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { glog.Errorf("azureDisk - Error getting volume (%q) source : %v", spec.Name(), err) continue @@ -151,7 +151,7 @@ func (a *azureDiskAttacher) VolumesAreAttached(specs []*volume.Spec, nodeName ty func (a *azureDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath string, _ *v1.Pod, timeout time.Duration) (string, error) { var err error - volumeSource, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { return "", err } @@ -185,10 +185,6 @@ func (a *azureDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath string, // did we find it? if newDevicePath != "" { - // the current sequence k8s uses for unformated disk (check-disk, mount, fail, mkfs.extX) hangs on - // Azure Managed disk scsi interface. this is a hack and will be replaced once we identify and solve - // the root case on Azure. - formatIfNotFormatted(newDevicePath, *volumeSource.FSType, exec) return true, nil } @@ -203,13 +199,13 @@ func (a *azureDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath string, // this is generalized for both managed and blob disks // we also prefix the hash with m/b based on disk kind func (a *azureDiskAttacher) GetDeviceMountPath(spec *volume.Spec) (string, error) { - volumeSource, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { return "", err } if volumeSource.Kind == nil { // this spec was constructed from info on the node - pdPath := path.Join(a.plugin.host.GetPluginDir(azureDataDiskPluginName), mount.MountsInGlobalPDPath, volumeSource.DataDiskURI) + pdPath := filepath.Join(a.plugin.host.GetPluginDir(azureDataDiskPluginName), mount.MountsInGlobalPDPath, volumeSource.DataDiskURI) return pdPath, nil } @@ -250,7 +246,7 @@ func (attacher *azureDiskAttacher) MountDevice(spec *volume.Spec, devicePath str } } - volumeSource, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common.go index 61a713544..eeb95e6eb 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common.go @@ -20,10 +20,11 @@ import ( "fmt" "io/ioutil" "os" - "path" + "path/filepath" libstrings "strings" - storage "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" @@ -45,6 +46,7 @@ type dataDisk struct { volumeName string diskName string podUID types.UID + plugin *azureDataDiskPlugin } var ( @@ -76,12 +78,12 @@ func makeGlobalPDPath(host volume.VolumeHost, diskUri string, isManaged bool) (s } // "{m for managed b for blob}{hashed diskUri or DiskId depending on disk kind }" diskName := fmt.Sprintf(uniqueDiskNameTemplate, prefix, hashedDiskUri) - pdPath := path.Join(host.GetPluginDir(azureDataDiskPluginName), mount.MountsInGlobalPDPath, diskName) + pdPath := filepath.Join(host.GetPluginDir(azureDataDiskPluginName), mount.MountsInGlobalPDPath, diskName) return pdPath, nil } -func makeDataDisk(volumeName string, podUID types.UID, diskName string, host volume.VolumeHost) *dataDisk { +func makeDataDisk(volumeName string, podUID types.UID, diskName string, host volume.VolumeHost, plugin *azureDataDiskPlugin) *dataDisk { var metricProvider volume.MetricsProvider if podUID != "" { metricProvider = volume.NewMetricsStatFS(getPath(podUID, volumeName, host)) @@ -92,19 +94,20 @@ func makeDataDisk(volumeName string, podUID types.UID, diskName string, host vol volumeName: volumeName, diskName: diskName, podUID: podUID, + plugin: plugin, } } -func getVolumeSource(spec *volume.Spec) (*v1.AzureDiskVolumeSource, error) { +func getVolumeSource(spec *volume.Spec) (volumeSource *v1.AzureDiskVolumeSource, readOnly bool, err error) { if spec.Volume != nil && spec.Volume.AzureDisk != nil { - return spec.Volume.AzureDisk, nil + return spec.Volume.AzureDisk, spec.Volume.AzureDisk.ReadOnly != nil && *spec.Volume.AzureDisk.ReadOnly, nil } if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.AzureDisk != nil { - return spec.PersistentVolume.Spec.AzureDisk, nil + return spec.PersistentVolume.Spec.AzureDisk, spec.ReadOnly, nil } - return nil, fmt.Errorf("azureDisk - Spec does not reference an Azure disk volume type") + return nil, false, fmt.Errorf("azureDisk - Spec does not reference an Azure disk volume type") } func normalizeKind(kind string) (v1.AzureDataDiskKind, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common_linux.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common_linux.go index 3c19b9244..383b46f46 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common_linux.go @@ -20,7 +20,7 @@ package azure_dd import ( "fmt" - "path" + "path/filepath" "strconv" libstrings "strings" @@ -124,7 +124,7 @@ func findDiskByLunWithConstraint(lun int, io ioHandler, azureDisks []string) (st if lun == l { // find the matching LUN // read vendor and model to ensure it is a VHD disk - vendorPath := path.Join(sys_path, name, "vendor") + vendorPath := filepath.Join(sys_path, name, "vendor") vendorBytes, err := io.ReadFile(vendorPath) if err != nil { glog.Errorf("failed to read device vendor, err: %v", err) @@ -136,7 +136,7 @@ func findDiskByLunWithConstraint(lun int, io ioHandler, azureDisks []string) (st continue } - modelPath := path.Join(sys_path, name, "model") + modelPath := filepath.Join(sys_path, name, "model") modelBytes, err := io.ReadFile(modelPath) if err != nil { glog.Errorf("failed to read device model, err: %v", err) @@ -149,7 +149,7 @@ func findDiskByLunWithConstraint(lun int, io ioHandler, azureDisks []string) (st } // find a disk, validate name - dir := path.Join(sys_path, name, "block") + dir := filepath.Join(sys_path, name, "block") if dev, err := io.ReadDir(dir); err == nil { found := false devName := dev[0].Name() @@ -178,45 +178,3 @@ func findDiskByLunWithConstraint(lun int, io ioHandler, azureDisks []string) (st } return "", err } - -func formatIfNotFormatted(disk string, fstype string, exec mount.Exec) { - notFormatted, err := diskLooksUnformatted(disk, exec) - if err == nil && notFormatted { - args := []string{disk} - // Disk is unformatted so format it. - // Use 'ext4' as the default - if len(fstype) == 0 { - fstype = "ext4" - } - if fstype == "ext4" || fstype == "ext3" { - args = []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", disk} - } - glog.Infof("azureDisk - Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", disk, fstype, args) - - _, err := exec.Run("mkfs."+fstype, args...) - if err == nil { - // the disk has been formatted successfully try to mount it again. - glog.Infof("azureDisk - Disk successfully formatted with 'mkfs.%s %v'", fstype, args) - } else { - glog.Warningf("azureDisk - Error formatting volume with 'mkfs.%s %v': %v", fstype, args, err) - } - } else { - if err != nil { - glog.Warningf("azureDisk - Failed to check if the disk %s formatted with error %s, will attach anyway", disk, err) - } else { - glog.Infof("azureDisk - Disk %s already formatted, will not format", disk) - } - } -} - -func diskLooksUnformatted(disk string, exec mount.Exec) (bool, error) { - args := []string{"-nd", "-o", "FSTYPE", disk} - glog.V(4).Infof("Attempting to determine if disk %q is formatted using lsblk with args: (%v)", disk, args) - dataOut, err := exec.Run("lsblk", args...) - if err != nil { - glog.Errorf("Could not determine if disk %q is formatted (%v)", disk, err) - return false, err - } - output := libstrings.TrimSpace(string(dataOut)) - return output == "", nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common_unsupported.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common_unsupported.go index 6710af8fc..ba938ccc2 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_common_unsupported.go @@ -26,6 +26,3 @@ func scsiHostRescan(io ioHandler, exec mount.Exec) { func findDiskByLun(lun int, io ioHandler, exec mount.Exec) (string, error) { return "", nil } - -func formatIfNotFormatted(disk string, fstype string, exec mount.Exec) { -} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd.go index c0b51a23d..91745c39f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd.go @@ -17,13 +17,18 @@ limitations under the License. package azure_dd import ( - "github.com/Azure/azure-sdk-for-go/arm/compute" - storage "github.com/Azure/azure-sdk-for-go/arm/storage" + "fmt" + + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" "github.com/golang/glog" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/cloudprovider/providers/azure" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/util" ) // interface exposed by the cloud provider implementing Disk functionality @@ -31,7 +36,7 @@ type DiskController interface { CreateBlobDisk(dataDiskName string, storageAccountType storage.SkuName, sizeGB int) (string, error) DeleteBlobDisk(diskUri string) error - CreateManagedDisk(diskName string, storageAccountType storage.SkuName, sizeGB int, tags map[string]string) (string, error) + CreateManagedDisk(diskName string, storageAccountType storage.SkuName, resourceGroup string, sizeGB int, tags map[string]string) (string, error) DeleteManagedDisk(diskURI string) error // Attaches the disk to the host machine. @@ -51,6 +56,9 @@ type DiskController interface { CreateVolume(name, storageAccount, storageAccountType, location string, requestGB int) (string, string, int, error) // Delete a VHD blob DeleteVolume(diskURI string) error + + // Expand the disk to new size + ResizeDisk(diskURI string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error) } type azureDataDiskPlugin struct { @@ -62,6 +70,8 @@ var _ volume.PersistentVolumePlugin = &azureDataDiskPlugin{} var _ volume.DeletableVolumePlugin = &azureDataDiskPlugin{} var _ volume.ProvisionableVolumePlugin = &azureDataDiskPlugin{} var _ volume.AttachableVolumePlugin = &azureDataDiskPlugin{} +var _ volume.VolumePluginWithAttachLimits = &azureDataDiskPlugin{} +var _ volume.ExpandableVolumePlugin = &azureDataDiskPlugin{} const ( azureDataDiskPluginName = "kubernetes.io/azure-disk" @@ -81,7 +91,7 @@ func (plugin *azureDataDiskPlugin) GetPluginName() string { } func (plugin *azureDataDiskPlugin) GetVolumeName(spec *volume.Spec) (string, error) { - volumeSource, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { return "", err } @@ -106,6 +116,32 @@ func (plugin *azureDataDiskPlugin) SupportsBulkVolumeVerification() bool { return false } +func (plugin *azureDataDiskPlugin) GetVolumeLimits() (map[string]int64, error) { + volumeLimits := map[string]int64{ + util.AzureVolumeLimitKey: 16, + } + + cloud := plugin.host.GetCloudProvider() + + // if we can't fetch cloudprovider we return an error + // hoping external CCM or admin can set it. Returning + // default values from here will mean, no one can + // override them. + if cloud == nil { + return nil, fmt.Errorf("No cloudprovider present") + } + + if cloud.ProviderName() != azure.CloudProviderName { + return nil, fmt.Errorf("Expected Azure cloudprovider, got %s", cloud.ProviderName()) + } + + return volumeLimits, nil +} + +func (plugin *azureDataDiskPlugin) VolumeLimitKey(spec *volume.Spec) string { + return util.AzureVolumeLimitKey +} + func (plugin *azureDataDiskPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode { return []v1.PersistentVolumeAccessMode{ v1.ReadWriteOnce, @@ -140,12 +176,12 @@ func (plugin *azureDataDiskPlugin) NewDetacher() (volume.Detacher, error) { } func (plugin *azureDataDiskPlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, error) { - volumeSource, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { return nil, err } - disk := makeDataDisk(spec.Name(), "", volumeSource.DiskName, plugin.host) + disk := makeDataDisk(spec.Name(), "", volumeSource.DiskName, plugin.host, plugin) return &azureDiskDeleter{ spec: spec, @@ -166,11 +202,11 @@ func (plugin *azureDataDiskPlugin) NewProvisioner(options volume.VolumeOptions) } func (plugin *azureDataDiskPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, options volume.VolumeOptions) (volume.Mounter, error) { - volumeSource, err := getVolumeSource(spec) + volumeSource, _, err := getVolumeSource(spec) if err != nil { return nil, err } - disk := makeDataDisk(spec.Name(), pod.UID, volumeSource.DiskName, plugin.host) + disk := makeDataDisk(spec.Name(), pod.UID, volumeSource.DiskName, plugin.host, plugin) return &azureDiskMounter{ plugin: plugin, @@ -181,7 +217,7 @@ func (plugin *azureDataDiskPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, op } func (plugin *azureDataDiskPlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) { - disk := makeDataDisk(volName, podUID, "", plugin.host) + disk := makeDataDisk(volName, podUID, "", plugin.host, plugin) return &azureDiskUnmounter{ plugin: plugin, @@ -189,6 +225,26 @@ func (plugin *azureDataDiskPlugin) NewUnmounter(volName string, podUID types.UID }, nil } +func (plugin *azureDataDiskPlugin) RequiresFSResize() bool { + return true +} + +func (plugin *azureDataDiskPlugin) ExpandVolumeDevice( + spec *volume.Spec, + newSize resource.Quantity, + oldSize resource.Quantity) (resource.Quantity, error) { + if spec.PersistentVolume == nil || spec.PersistentVolume.Spec.AzureDisk == nil { + return oldSize, fmt.Errorf("invalid PV spec") + } + + diskController, err := getDiskController(plugin.host) + if err != nil { + return oldSize, err + } + + return diskController.ResizeDisk(spec.PersistentVolume.Spec.AzureDisk.DataDiskURI, oldSize, newSize) +} + func (plugin *azureDataDiskPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) { mounter := plugin.host.GetMounter(plugin.GetPluginName()) pluginDir := plugin.host.GetPluginDir(plugin.GetPluginName()) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd_block.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd_block.go new file mode 100644 index 000000000..af1d19504 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd_block.go @@ -0,0 +1,161 @@ +/* +Copyright 2018 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 azure_dd + +import ( + "fmt" + "path/filepath" + + "github.com/golang/glog" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/util/mount" + kstrings "k8s.io/kubernetes/pkg/util/strings" + "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/util" + "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" +) + +var _ volume.VolumePlugin = &azureDataDiskPlugin{} +var _ volume.PersistentVolumePlugin = &azureDataDiskPlugin{} +var _ volume.BlockVolumePlugin = &azureDataDiskPlugin{} +var _ volume.DeletableVolumePlugin = &azureDataDiskPlugin{} +var _ volume.ProvisionableVolumePlugin = &azureDataDiskPlugin{} + +func (plugin *azureDataDiskPlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, mapPath string) (*volume.Spec, error) { + pluginDir := plugin.host.GetVolumeDevicePluginDir(azureDataDiskPluginName) + blkutil := volumepathhandler.NewBlockVolumePathHandler() + globalMapPathUUID, err := blkutil.FindGlobalMapPathUUIDFromPod(pluginDir, mapPath, podUID) + if err != nil { + return nil, err + } + glog.V(5).Infof("constructing block volume spec from globalMapPathUUID: %s", globalMapPathUUID) + + globalMapPath := filepath.Dir(globalMapPathUUID) + if len(globalMapPath) <= 1 { + return nil, fmt.Errorf("failed to get volume plugin information from globalMapPathUUID: %v", globalMapPathUUID) + } + + return getVolumeSpecFromGlobalMapPath(globalMapPath, volumeName) +} + +func getVolumeSpecFromGlobalMapPath(globalMapPath, volumeName string) (*volume.Spec, error) { + // Get volume spec information from globalMapPath + // globalMapPath example: + // plugins/kubernetes.io/{PluginName}/{DefaultKubeletVolumeDevicesDirName}/{volumeID} + // plugins/kubernetes.io/azure-disk/volumeDevices/vol-XXXXXX + diskName := filepath.Base(globalMapPath) + if len(diskName) <= 1 { + return nil, fmt.Errorf("failed to get diskName from global path=%s", globalMapPath) + } + glog.V(5).Infof("got diskName(%s) from globalMapPath: %s", globalMapPath, diskName) + block := v1.PersistentVolumeBlock + pv := &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: volumeName, + }, + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{ + AzureDisk: &v1.AzureDiskVolumeSource{ + DiskName: diskName, + }, + }, + VolumeMode: &block, + }, + } + + return volume.NewSpecFromPersistentVolume(pv, true), nil +} + +// NewBlockVolumeMapper creates a new volume.BlockVolumeMapper from an API specification. +func (plugin *azureDataDiskPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.BlockVolumeMapper, error) { + // If this is called via GenerateUnmapDeviceFunc(), pod is nil. + // Pass empty string as dummy uid since uid isn't used in the case. + var uid types.UID + if pod != nil { + uid = pod.UID + } + + return plugin.newBlockVolumeMapperInternal(spec, uid, plugin.host.GetMounter(plugin.GetPluginName())) +} + +func (plugin *azureDataDiskPlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, mounter mount.Interface) (volume.BlockVolumeMapper, error) { + volumeSource, readOnly, err := getVolumeSource(spec) + if err != nil { + return nil, err + } + + disk := makeDataDisk(spec.Name(), podUID, volumeSource.DiskName, plugin.host, plugin) + + return &azureDataDiskMapper{ + dataDisk: disk, + readOnly: readOnly, + }, nil +} + +func (plugin *azureDataDiskPlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (volume.BlockVolumeUnmapper, error) { + return plugin.newUnmapperInternal(volName, podUID, plugin.host.GetMounter(plugin.GetPluginName())) +} + +func (plugin *azureDataDiskPlugin) newUnmapperInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.BlockVolumeUnmapper, error) { + disk := makeDataDisk(volName, podUID, "", plugin.host, plugin) + return &azureDataDiskUnmapper{dataDisk: disk}, nil +} + +func (c *azureDataDiskUnmapper) TearDownDevice(mapPath, devicePath string) error { + return nil +} + +type azureDataDiskUnmapper struct { + *dataDisk +} + +var _ volume.BlockVolumeUnmapper = &azureDataDiskUnmapper{} + +type azureDataDiskMapper struct { + *dataDisk + readOnly bool +} + +var _ volume.BlockVolumeMapper = &azureDataDiskMapper{} + +func (b *azureDataDiskMapper) SetUpDevice() (string, error) { + return "", nil +} + +func (b *azureDataDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + +// GetGlobalMapPath returns global map path and error +// path: plugins/kubernetes.io/{PluginName}/volumeDevices/volumeID +// plugins/kubernetes.io/azure-disk/volumeDevices/vol-XXXXXX +func (disk *dataDisk) GetGlobalMapPath(spec *volume.Spec) (string, error) { + volumeSource, _, err := getVolumeSource(spec) + if err != nil { + return "", err + } + return filepath.Join(disk.plugin.host.GetVolumeDevicePluginDir(azureDataDiskPluginName), string(volumeSource.DiskName)), nil +} + +// GetPodDeviceMapPath returns pod device map path and volume name +// path: pods/{podUid}/volumeDevices/kubernetes.io~azure +func (disk *dataDisk) GetPodDeviceMapPath() (string, string) { + name := azureDataDiskPluginName + return disk.plugin.host.GetPodVolumeDeviceDir(disk.podUID, kstrings.EscapeQualifiedNameForDisk(name)), disk.volumeName +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd_block_test.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd_block_test.go new file mode 100644 index 000000000..195170747 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_dd_block_test.go @@ -0,0 +1,145 @@ +/* +Copyright 2018 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 azure_dd + +import ( + "os" + "path/filepath" + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + utiltesting "k8s.io/client-go/util/testing" + "k8s.io/kubernetes/pkg/volume" + volumetest "k8s.io/kubernetes/pkg/volume/testing" +) + +const ( + testDiskName = "disk1" + testPVName = "pv1" + testGlobalPath = "plugins/kubernetes.io/azure-disk/volumeDevices/disk1" + testPodPath = "pods/poduid/volumeDevices/kubernetes.io~azure-disk" +) + +func TestGetVolumeSpecFromGlobalMapPath(t *testing.T) { + // make our test path for fake GlobalMapPath + // /tmp symbolized our pluginDir + // /tmp/testGlobalPathXXXXX/plugins/kubernetes.io/azure-disk/volumeDevices/disk1 + tmpVDir, err := utiltesting.MkTmpdir("azureDiskBlockTest") + if err != nil { + t.Fatalf("can't make a temp dir: %v", err) + } + //deferred clean up + defer os.RemoveAll(tmpVDir) + + expectedGlobalPath := filepath.Join(tmpVDir, testGlobalPath) + + //Bad Path + badspec, err := getVolumeSpecFromGlobalMapPath("", "") + if badspec != nil || err == nil { + t.Errorf("Expected not to get spec from GlobalMapPath but did") + } + + // Good Path + spec, err := getVolumeSpecFromGlobalMapPath(expectedGlobalPath, "") + if spec == nil || err != nil { + t.Fatalf("Failed to get spec from GlobalMapPath: %v", err) + } + if spec.PersistentVolume.Spec.AzureDisk.DiskName != testDiskName { + t.Errorf("Invalid pdName from GlobalMapPath spec: %s", spec.PersistentVolume.Spec.AzureDisk.DiskName) + } + block := v1.PersistentVolumeBlock + specMode := spec.PersistentVolume.Spec.VolumeMode + if &specMode == nil { + t.Errorf("Invalid volumeMode from GlobalMapPath spec: %v expected: %v", &specMode, block) + } + if *specMode != block { + t.Errorf("Invalid volumeMode from GlobalMapPath spec: %v expected: %v", *specMode, block) + } +} + +func getTestVolume(readOnly bool, path string, isBlock bool) *volume.Spec { + pv := &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPVName, + }, + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{ + AzureDisk: &v1.AzureDiskVolumeSource{ + DiskName: testDiskName, + }, + }, + }, + } + + if isBlock { + blockMode := v1.PersistentVolumeBlock + pv.Spec.VolumeMode = &blockMode + } + return volume.NewSpecFromPersistentVolume(pv, readOnly) +} + +func TestGetPodAndPluginMapPaths(t *testing.T) { + tmpVDir, err := utiltesting.MkTmpdir("azureDiskBlockTest") + if err != nil { + t.Fatalf("can't make a temp dir: %v", err) + } + //deferred clean up + defer os.RemoveAll(tmpVDir) + + expectedGlobalPath := filepath.Join(tmpVDir, testGlobalPath) + expectedPodPath := filepath.Join(tmpVDir, testPodPath) + + spec := getTestVolume(false, tmpVDir, true /*isBlock*/) + plugMgr := volume.VolumePluginMgr{} + plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(tmpVDir, nil, nil)) + plug, err := plugMgr.FindMapperPluginByName(azureDataDiskPluginName) + if err != nil { + os.RemoveAll(tmpVDir) + t.Fatalf("Can't find the plugin by name: %q", azureDataDiskPluginName) + } + if plug.GetPluginName() != azureDataDiskPluginName { + t.Fatalf("Wrong name: %s", plug.GetPluginName()) + } + pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} + mapper, err := plug.NewBlockVolumeMapper(spec, pod, volume.VolumeOptions{}) + if err != nil { + t.Fatalf("Failed to make a new Mounter: %v", err) + } + if mapper == nil { + t.Fatalf("Got a nil Mounter") + } + + //GetGlobalMapPath + gMapPath, err := mapper.GetGlobalMapPath(spec) + if err != nil || len(gMapPath) == 0 { + t.Fatalf("Invalid GlobalMapPath from spec: %s, error: %v", spec.PersistentVolume.Spec.AzureDisk.DiskName, err) + } + if gMapPath != expectedGlobalPath { + t.Errorf("Failed to get GlobalMapPath: %s, expected %s", gMapPath, expectedGlobalPath) + } + + //GetPodDeviceMapPath + gDevicePath, gVolName := mapper.GetPodDeviceMapPath() + if gDevicePath != expectedPodPath { + t.Errorf("Got unexpected pod path: %s, expected %s", gDevicePath, expectedPodPath) + } + if gVolName != testPVName { + t.Errorf("Got unexpected volNamne: %s, expected %s", gVolName, testPVName) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_mounter.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_mounter.go index 514a6dcb1..d8b7ae50d 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_mounter.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_mounter.go @@ -44,7 +44,7 @@ var _ volume.Mounter = &azureDiskMounter{} func (m *azureDiskMounter) GetAttributes() volume.Attributes { readOnly := false - volumeSource, err := getVolumeSource(m.spec) + volumeSource, _, err := getVolumeSource(m.spec) if err != nil { glog.Infof("azureDisk - mounter failed to get volume source for spec %s %v", m.spec.Name(), err) } else if volumeSource.ReadOnly != nil { @@ -71,7 +71,7 @@ func (m *azureDiskMounter) GetPath() string { func (m *azureDiskMounter) SetUpAt(dir string, fsGroup *int64) error { mounter := m.plugin.host.GetMounter(m.plugin.GetPluginName()) - volumeSource, err := getVolumeSource(m.spec) + volumeSource, _, err := getVolumeSource(m.spec) if err != nil { glog.Infof("azureDisk - mounter failed to get volume source for spec %s", m.spec.Name()) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_provision.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_provision.go index 6888bfc4e..2c4c9b8aa 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_provision.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_dd/azure_provision.go @@ -17,12 +17,15 @@ limitations under the License. package azure_dd import ( + "errors" "fmt" "strings" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util" ) @@ -46,7 +49,7 @@ func (d *azureDiskDeleter) GetPath() string { } func (d *azureDiskDeleter) Delete() error { - volumeSource, err := getVolumeSource(d.spec) + volumeSource, _, err := getVolumeSource(d.spec) if err != nil { return err } @@ -65,7 +68,7 @@ func (d *azureDiskDeleter) Delete() error { return diskController.DeleteBlobDisk(volumeSource.DataDiskURI) } -func (p *azureDiskProvisioner) Provision() (*v1.PersistentVolume, error) { +func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(p.plugin.GetAccessModes(), p.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", p.options.PVC.Spec.AccessModes, p.plugin.GetAccessModes()) } @@ -92,6 +95,7 @@ func (p *azureDiskProvisioner) Provision() (*v1.PersistentVolume, error) { cachingMode v1.AzureDataDiskCachingMode strKind string err error + resourceGroup string ) // maxLength = 79 - (4 for ".vhd") = 75 name := util.GenerateVolumeName(p.options.ClusterName, p.options.PVName, 75) @@ -115,6 +119,8 @@ func (p *azureDiskProvisioner) Provision() (*v1.PersistentVolume, error) { cachingMode = v1.AzureDataDiskCachingMode(v) case volume.VolumeParameterFSType: fsType = strings.ToLower(v) + case "resourcegroup": + resourceGroup = v default: return nil, fmt.Errorf("AzureDisk - invalid option %s in storage class", k) } @@ -140,10 +146,18 @@ func (p *azureDiskProvisioner) Provision() (*v1.PersistentVolume, error) { return nil, err } + if resourceGroup != "" && kind != v1.AzureManagedDisk { + return nil, errors.New("StorageClass option 'resourceGroup' can be used only for managed disks") + } + // create disk diskURI := "" if kind == v1.AzureManagedDisk { - diskURI, err = diskController.CreateManagedDisk(name, skuName, requestGB, *(p.options.CloudTags)) + tags := make(map[string]string) + if p.options.CloudTags != nil { + tags = *(p.options.CloudTags) + } + diskURI, err = diskController.CreateManagedDisk(name, skuName, resourceGroup, requestGB, tags) if err != nil { return nil, err } @@ -187,5 +201,10 @@ func (p *azureDiskProvisioner) Provision() (*v1.PersistentVolume, error) { MountOptions: p.options.MountOptions, }, } + + if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + pv.Spec.VolumeMode = p.options.PVC.Spec.VolumeMode + } + return pv, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_file/azure_file_test.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_file/azure_file_test.go index 1f394d69c..43dcd2081 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_file/azure_file_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_file/azure_file_test.go @@ -20,7 +20,7 @@ import ( "fmt" "io/ioutil" "os" - "path" + "path/filepath" "reflect" "strings" "testing" @@ -149,7 +149,7 @@ func testPlugin(t *testing.T, tmpDir string, volumeHost volume.VolumeHost) { if mounter == nil { t.Errorf("Got a nil Mounter") } - volPath := path.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~azure-file/vol1") + volPath := filepath.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~azure-file/vol1") path := mounter.GetPath() if path != volPath { t.Errorf("Got unexpected path: %s", path) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/azure_file/azure_provision.go b/vendor/k8s.io/kubernetes/pkg/volume/azure_file/azure_provision.go index dc155334f..891f2d695 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/azure_file/azure_provision.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/azure_file/azure_provision.go @@ -131,10 +131,13 @@ type azureFileProvisioner struct { var _ volume.Provisioner = &azureFileProvisioner{} -func (a *azureFileProvisioner) Provision() (*v1.PersistentVolume, error) { +func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(a.plugin.GetAccessModes(), a.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", a.options.PVC.Spec.AccessModes, a.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(a.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", a.plugin.GetPluginName()) + } var sku, location, account string diff --git a/vendor/k8s.io/kubernetes/pkg/volume/cephfs/cephfs.go b/vendor/k8s.io/kubernetes/pkg/volume/cephfs/cephfs.go index 426efcc2c..d99577c74 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/cephfs/cephfs.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/cephfs/cephfs.go @@ -405,6 +405,8 @@ func (cephfsVolume *cephfs) execFuseMount(mountpoint string) error { mountArgs = append(mountArgs, mountpoint) mountArgs = append(mountArgs, "-r") mountArgs = append(mountArgs, cephfsVolume.path) + mountArgs = append(mountArgs, "--id") + mountArgs = append(mountArgs, cephfsVolume.id) glog.V(4).Infof("Mounting cmd ceph-fuse with arguments (%s)", mountArgs) command := exec.Command("ceph-fuse", mountArgs...) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/cinder/attacher.go b/vendor/k8s.io/kubernetes/pkg/volume/cinder/attacher.go index bfe66d566..fff3efd55 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/cinder/attacher.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/cinder/attacher.go @@ -120,13 +120,11 @@ func (attacher *cinderDiskAttacher) waitDiskAttached(instanceID, volumeID string } func (attacher *cinderDiskAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) { - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return "", err } - volumeID := volumeSource.VolumeID - instanceID, err := attacher.nodeInstanceID(nodeName) if err != nil { return "", err @@ -175,15 +173,15 @@ func (attacher *cinderDiskAttacher) VolumesAreAttached(specs []*volume.Spec, nod volumeSpecMap := make(map[string]*volume.Spec) volumeIDList := []string{} for _, spec := range specs { - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { glog.Errorf("Error getting volume (%q) source : %v", spec.Name(), err) continue } - volumeIDList = append(volumeIDList, volumeSource.VolumeID) + volumeIDList = append(volumeIDList, volumeID) volumesAttachedCheck[spec] = true - volumeSpecMap[volumeSource.VolumeID] = spec + volumeSpecMap[volumeID] = spec } attachedResult, err := attacher.cinderProvider.DisksAreAttachedByName(nodeName, volumeIDList) @@ -207,13 +205,11 @@ func (attacher *cinderDiskAttacher) VolumesAreAttached(specs []*volume.Spec, nod func (attacher *cinderDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath string, _ *v1.Pod, timeout time.Duration) (string, error) { // NOTE: devicePath is is path as reported by Cinder, which may be incorrect and should not be used. See Issue #33128 - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return "", err } - volumeID := volumeSource.VolumeID - if devicePath == "" { return "", fmt.Errorf("WaitForAttach failed for Cinder disk %q: devicePath is empty", volumeID) } @@ -252,12 +248,12 @@ func (attacher *cinderDiskAttacher) WaitForAttach(spec *volume.Spec, devicePath func (attacher *cinderDiskAttacher) GetDeviceMountPath( spec *volume.Spec) (string, error) { - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return "", err } - return makeGlobalPDName(attacher.host, volumeSource.VolumeID), nil + return makeGlobalPDName(attacher.host, volumeID), nil } // FIXME: this method can be further pruned. @@ -275,7 +271,7 @@ func (attacher *cinderDiskAttacher) MountDevice(spec *volume.Spec, devicePath st } } - volumeSource, readOnly, err := getVolumeSource(spec) + _, volumeFSType, readOnly, err := getVolumeInfo(spec) if err != nil { return err } @@ -287,7 +283,7 @@ func (attacher *cinderDiskAttacher) MountDevice(spec *volume.Spec, devicePath st if notMnt { diskMounter := volumeutil.NewSafeFormatAndMountFromHost(cinderVolumePluginName, attacher.host) mountOptions := volumeutil.MountOptionFromSpec(spec, options...) - err = diskMounter.FormatAndMount(devicePath, deviceMountPath, volumeSource.FSType, mountOptions) + err = diskMounter.FormatAndMount(devicePath, deviceMountPath, volumeFSType, mountOptions) if err != nil { os.Remove(deviceMountPath) return err diff --git a/vendor/k8s.io/kubernetes/pkg/volume/cinder/attacher_test.go b/vendor/k8s.io/kubernetes/pkg/volume/cinder/attacher_test.go index b75fdef56..6acb573a5 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/cinder/attacher_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/cinder/attacher_test.go @@ -393,7 +393,7 @@ func createPVSpec(name string, readOnly bool) *volume.Spec { PersistentVolume: &v1.PersistentVolume{ Spec: v1.PersistentVolumeSpec{ PersistentVolumeSource: v1.PersistentVolumeSource{ - Cinder: &v1.CinderVolumeSource{ + Cinder: &v1.CinderPersistentVolumeSource{ VolumeID: name, ReadOnly: readOnly, }, @@ -712,10 +712,6 @@ func (instances *instances) NodeAddressesByProviderID(ctx context.Context, provi return []v1.NodeAddress{}, errors.New("Not implemented") } -func (instances *instances) ExternalID(ctx context.Context, name types.NodeName) (string, error) { - return "", errors.New("Not implemented") -} - func (instances *instances) InstanceID(ctx context.Context, name types.NodeName) (string, error) { return instances.instanceID, nil } @@ -732,12 +728,16 @@ func (instances *instances) InstanceExistsByProviderID(ctx context.Context, prov return false, errors.New("unimplemented") } +func (instances *instances) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { + return false, errors.New("unimplemented") +} + func (instances *instances) List(filter string) ([]types.NodeName, error) { return []types.NodeName{}, errors.New("Not implemented") } func (instances *instances) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error { - return errors.New("Not implemented") + return cloudprovider.NotImplemented } func (instances *instances) CurrentNodeName(ctx context.Context, hostname string) (types.NodeName, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/cinder/cinder.go b/vendor/k8s.io/kubernetes/pkg/volume/cinder/cinder.go index 121972c46..55aec4586 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/cinder/cinder.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/cinder/cinder.go @@ -94,12 +94,12 @@ func (plugin *cinderPlugin) GetPluginName() string { } func (plugin *cinderPlugin) GetVolumeName(spec *volume.Spec) (string, error) { - volumeSource, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return "", err } - return volumeSource.VolumeID, nil + return volumeID, nil } func (plugin *cinderPlugin) CanSupport(spec *volume.Spec) bool { @@ -129,14 +129,11 @@ func (plugin *cinderPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume. } func (plugin *cinderPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager cdManager, mounter mount.Interface) (volume.Mounter, error) { - cinder, readOnly, err := getVolumeSource(spec) + pdName, fsType, readOnly, err := getVolumeInfo(spec) if err != nil { return nil, err } - pdName := cinder.VolumeID - fsType := cinder.FSType - return &cinderVolumeMounter{ cinderVolume: &cinderVolume{ podUID: podUID, @@ -248,7 +245,7 @@ func (plugin *cinderPlugin) ConstructVolumeSpec(volumeName, mountPath string) (* var _ volume.ExpandableVolumePlugin = &cinderPlugin{} func (plugin *cinderPlugin) ExpandVolumeDevice(spec *volume.Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) { - cinder, _, err := getVolumeSource(spec) + volumeID, _, _, err := getVolumeInfo(spec) if err != nil { return oldSize, err } @@ -257,12 +254,12 @@ func (plugin *cinderPlugin) ExpandVolumeDevice(spec *volume.Spec, newSize resour return oldSize, err } - expandedSize, err := cloud.ExpandVolume(cinder.VolumeID, oldSize, newSize) + expandedSize, err := cloud.ExpandVolume(volumeID, oldSize, newSize) if err != nil { return oldSize, err } - glog.V(2).Infof("volume %s expanded to new size %d successfully", cinder.VolumeID, int(newSize.Value())) + glog.V(2).Infof("volume %s expanded to new size %d successfully", volumeID, int(newSize.Value())) return expandedSize, nil } @@ -503,11 +500,15 @@ type cinderVolumeProvisioner struct { var _ volume.Provisioner = &cinderVolumeProvisioner{} -func (c *cinderVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *cinderVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName()) + } + volumeID, sizeGB, labels, fstype, err := c.manager.CreateVolume(c) if err != nil { return nil, err @@ -528,7 +529,7 @@ func (c *cinderVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)), }, PersistentVolumeSource: v1.PersistentVolumeSource{ - Cinder: &v1.CinderVolumeSource{ + Cinder: &v1.CinderPersistentVolumeSource{ VolumeID: volumeID, FSType: fstype, ReadOnly: false, @@ -544,13 +545,13 @@ func (c *cinderVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { return pv, nil } -func getVolumeSource(spec *volume.Spec) (*v1.CinderVolumeSource, bool, error) { +func getVolumeInfo(spec *volume.Spec) (string, string, bool, error) { if spec.Volume != nil && spec.Volume.Cinder != nil { - return spec.Volume.Cinder, spec.Volume.Cinder.ReadOnly, nil + return spec.Volume.Cinder.VolumeID, spec.Volume.Cinder.FSType, spec.Volume.Cinder.ReadOnly, nil } else if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Cinder != nil { - return spec.PersistentVolume.Spec.Cinder, spec.ReadOnly, nil + return spec.PersistentVolume.Spec.Cinder.VolumeID, spec.PersistentVolume.Spec.Cinder.FSType, spec.ReadOnly, nil } - return nil, false, fmt.Errorf("Spec does not reference a Cinder volume type") + return "", "", false, fmt.Errorf("Spec does not reference a Cinder volume type") } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/cinder/cinder_test.go b/vendor/k8s.io/kubernetes/pkg/volume/cinder/cinder_test.go index f0f1db706..d16b3d09c 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/cinder/cinder_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/cinder/cinder_test.go @@ -51,7 +51,7 @@ func TestCanSupport(t *testing.T) { t.Errorf("Expected true") } - if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Cinder: &v1.CinderVolumeSource{}}}}}) { + if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Cinder: &v1.CinderPersistentVolumeSource{}}}}}) { t.Errorf("Expected true") } } @@ -196,7 +196,7 @@ func TestPlugin(t *testing.T) { PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete, } provisioner, err := plug.(*cinderPlugin).newProvisionerInternal(options, &fakePDManager{0}) - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/configmap/configmap.go b/vendor/k8s.io/kubernetes/pkg/volume/configmap/configmap.go index ff041c0ac..2f108bb72 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/configmap/configmap.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/configmap/configmap.go @@ -191,12 +191,6 @@ func (b *configMapVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { if err != nil { return err } - if err := wrapped.SetUpAt(dir, fsGroup); err != nil { - return err - } - if err := volumeutil.MakeNestedMountpoints(b.volName, dir, b.pod); err != nil { - return err - } optional := b.source.Optional != nil && *b.source.Optional configMap, err := b.getConfigMap(b.pod.Namespace, b.source.Name) @@ -213,6 +207,13 @@ func (b *configMapVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { } } + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { + return err + } + if err := volumeutil.MakeNestedMountpoints(b.volName, dir, b.pod); err != nil { + return err + } + totalBytes := totalBytes(configMap) glog.V(3).Infof("Received configMap %v/%v containing (%v) pieces of data, %v total bytes", b.pod.Namespace, @@ -243,7 +244,6 @@ func (b *configMapVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Error applying volume ownership settings for group: %v", fsGroup) return err } - return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/csi/BUILD index 7068f6757..54a2574eb 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/BUILD @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "csi_attacher.go", + "csi_block.go", "csi_client.go", "csi_mounter.go", "csi_plugin.go", @@ -12,13 +13,14 @@ go_library( importpath = "k8s.io/kubernetes/pkg/volume/csi", visibility = ["//visibility:public"], deps = [ + "//pkg/features:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/strings:go_default_library", "//pkg/volume:go_default_library", + "//pkg/volume/csi/labelmanager:go_default_library", "//pkg/volume/util:go_default_library", "//vendor/github.com/container-storage-interface/spec/lib/go/csi/v0:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/storage/v1beta1:go_default_library", @@ -26,6 +28,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) @@ -34,6 +37,7 @@ go_test( name = "go_default_test", srcs = [ "csi_attacher_test.go", + "csi_block_test.go", "csi_client_test.go", "csi_mounter_test.go", "csi_plugin_test.go", @@ -45,7 +49,6 @@ go_test( "//pkg/volume/testing:go_default_library", "//pkg/volume/util:go_default_library", "//vendor/github.com/container-storage-interface/spec/lib/go/csi/v0:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/storage/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", @@ -54,6 +57,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", "//vendor/k8s.io/client-go/util/testing:go_default_library", @@ -72,6 +76,7 @@ filegroup( srcs = [ ":package-srcs", "//pkg/volume/csi/fake:all-srcs", + "//pkg/volume/csi/labelmanager:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher.go index 921a25879..bef513d92 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher.go @@ -17,6 +17,7 @@ limitations under the License. package csi import ( + "context" "crypto/sha256" "errors" "fmt" @@ -27,7 +28,6 @@ import ( "time" "github.com/golang/glog" - grpctx "golang.org/x/net/context" csipb "github.com/container-storage-interface/spec/lib/go/csi/v0" "k8s.io/api/core/v1" @@ -245,7 +245,7 @@ func (c *csiAttacher) GetDeviceMountPath(spec *volume.Spec) (string, error) { return deviceMountPath, nil } -func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string) error { +func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string) (err error) { glog.V(4).Infof(log("attacher.MountDevice(%s, %s)", devicePath, deviceMountPath)) mounted, err := isDirMounted(c.plugin, deviceMountPath) @@ -269,27 +269,57 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo return err } + // Store volume metadata for UnmountDevice. Keep it around even if the + // driver does not support NodeStage, UnmountDevice still needs it. + if err = os.MkdirAll(deviceMountPath, 0750); err != nil { + glog.Error(log("attacher.MountDevice failed to create dir %#v: %v", deviceMountPath, err)) + return err + } + glog.V(4).Info(log("created target path successfully [%s]", deviceMountPath)) + dataDir := filepath.Dir(deviceMountPath) + data := map[string]string{ + volDataKey.volHandle: csiSource.VolumeHandle, + volDataKey.driverName: csiSource.Driver, + } + if err = saveVolumeData(dataDir, volDataFileName, data); err != nil { + glog.Error(log("failed to save volume info data: %v", err)) + if cleanerr := os.RemoveAll(dataDir); err != nil { + glog.Error(log("failed to remove dir after error [%s]: %v", dataDir, cleanerr)) + } + return err + } + defer func() { + if err != nil { + // clean up metadata + glog.Errorf(log("attacher.MountDevice failed: %v", err)) + if err := removeMountDir(c.plugin, deviceMountPath); err != nil { + glog.Error(log("attacher.MountDevice failed to remove mount dir after errir [%s]: %v", deviceMountPath, err)) + } + } + }() + if c.csiClient == nil { c.csiClient = newCsiDriverClient(csiSource.Driver) } csi := c.csiClient - ctx, cancel := grpctx.WithTimeout(grpctx.Background(), csiTimeout) + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) defer cancel() // Check whether "STAGE_UNSTAGE_VOLUME" is set stageUnstageSet, err := hasStageUnstageCapability(ctx, csi) if err != nil { - glog.Error(log("attacher.MountDevice failed to check STAGE_UNSTAGE_VOLUME: %v", err)) return err } if !stageUnstageSet { glog.Infof(log("attacher.MountDevice STAGE_UNSTAGE_VOLUME capability not set. Skipping MountDevice...")) + // defer does *not* remove the metadata file and it's correct - UnmountDevice needs it there. return nil } // Start MountDevice if deviceMountPath == "" { - return fmt.Errorf("attacher.MountDevice failed, deviceMountPath is empty") + err = fmt.Errorf("attacher.MountDevice failed, deviceMountPath is empty") + return err } nodeName := string(c.plugin.host.GetNodeName()) @@ -298,13 +328,12 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo // search for attachment by VolumeAttachment.Spec.Source.PersistentVolumeName attachment, err := c.k8s.StorageV1beta1().VolumeAttachments().Get(attachID, meta.GetOptions{}) if err != nil { - glog.Error(log("attacher.MountDevice failed while getting volume attachment [id=%v]: %v", attachID, err)) - return err + return err // This err already has enough context ("VolumeAttachment xyz not found") } if attachment == nil { - glog.Error(log("unable to find VolumeAttachment [id=%s]", attachID)) - return errors.New("no existing VolumeAttachment found") + err = errors.New("no existing VolumeAttachment found") + return err } publishVolumeInfo := attachment.Status.AttachmentMetadata @@ -312,18 +341,12 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo if csiSource.NodeStageSecretRef != nil { nodeStageSecrets, err = getCredentialsFromSecret(c.k8s, csiSource.NodeStageSecretRef) if err != nil { - return fmt.Errorf("fetching NodeStageSecretRef %s/%s failed: %v", + err = fmt.Errorf("fetching NodeStageSecretRef %s/%s failed: %v", csiSource.NodeStageSecretRef.Namespace, csiSource.NodeStageSecretRef.Name, err) + return err } } - // create target_dir before call to NodeStageVolume - if err := os.MkdirAll(deviceMountPath, 0750); err != nil { - glog.Error(log("attacher.MountDevice failed to create dir %#v: %v", deviceMountPath, err)) - return err - } - glog.V(4).Info(log("created target path successfully [%s]", deviceMountPath)) - //TODO (vladimirvivien) implement better AccessModes mapping between k8s and CSI accessMode := v1.ReadWriteOnce if spec.PersistentVolume.Spec.AccessModes != nil { @@ -331,10 +354,6 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo } fsType := csiSource.FSType - if len(fsType) == 0 { - fsType = defaultFSType - } - err = csi.NodeStageVolume(ctx, csiSource.VolumeHandle, publishVolumeInfo, @@ -345,11 +364,6 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo csiSource.VolumeAttributes) if err != nil { - glog.Errorf(log("attacher.MountDevice failed: %v", err)) - if err := removeMountDir(c.plugin, deviceMountPath); err != nil { - glog.Error(log("attacher.MountDevice failed to remove mount dir after a NodeStageVolume() error [%s]: %v", deviceMountPath, err)) - return err - } return err } @@ -462,10 +476,21 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error { glog.V(4).Info(log("attacher.UnmountDevice(%s)", deviceMountPath)) // Setup - driverName, volID, err := getDriverAndVolNameFromDeviceMountPath(c.k8s, deviceMountPath) - if err != nil { - glog.Errorf(log("attacher.UnmountDevice failed to get driver and volume name from device mount path: %v", err)) - return err + var driverName, volID string + dataDir := filepath.Dir(deviceMountPath) + data, err := loadVolumeData(dataDir, volDataFileName) + if err == nil { + driverName = data[volDataKey.driverName] + volID = data[volDataKey.volHandle] + } else { + glog.Error(log("UnmountDevice failed to load volume data file [%s]: %v", dataDir, err)) + + // The volume might have been mounted by old CSI volume plugin. Fall back to the old behavior: read PV from API server + driverName, volID, err = getDriverAndVolNameFromDeviceMountPath(c.k8s, deviceMountPath) + if err != nil { + glog.Errorf(log("attacher.UnmountDevice failed to get driver and volume name from device mount path: %v", err)) + return err + } } if c.csiClient == nil { @@ -473,7 +498,7 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error { } csi := c.csiClient - ctx, cancel := grpctx.WithTimeout(grpctx.Background(), csiTimeout) + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) defer cancel() // Check whether "STAGE_UNSTAGE_VOLUME" is set stageUnstageSet, err := hasStageUnstageCapability(ctx, csi) @@ -483,6 +508,11 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error { } if !stageUnstageSet { glog.Infof(log("attacher.UnmountDevice STAGE_UNSTAGE_VOLUME capability not set. Skipping UnmountDevice...")) + // Just delete the global directory + json file + if err := removeMountDir(c.plugin, deviceMountPath); err != nil { + return fmt.Errorf("failed to clean up gloubal mount %s: %s", dataDir, err) + } + return nil } @@ -496,11 +526,16 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error { return err } + // Delete the global directory + json file + if err := removeMountDir(c.plugin, deviceMountPath); err != nil { + return fmt.Errorf("failed to clean up gloubal mount %s: %s", dataDir, err) + } + glog.V(4).Infof(log("attacher.UnmountDevice successfully requested NodeStageVolume [%s]", deviceMountPath)) return nil } -func hasStageUnstageCapability(ctx grpctx.Context, csi csiClient) (bool, error) { +func hasStageUnstageCapability(ctx context.Context, csi csiClient) (bool, error) { capabilities, err := csi.NodeGetCapabilities(ctx) if err != nil { return false, err diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher_test.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher_test.go index 15b65cfab..e31cecfa6 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher_test.go @@ -18,6 +18,7 @@ package csi import ( "fmt" + "io/ioutil" "os" "path/filepath" "testing" @@ -185,17 +186,7 @@ func TestAttacherAttach(t *testing.T) { } func TestAttacherWaitForVolumeAttachment(t *testing.T) { - - plug, fakeWatcher, tmpDir, _ := newTestWatchPlugin(t) - defer os.RemoveAll(tmpDir) - - attacher, err := plug.NewAttacher() - if err != nil { - t.Fatalf("failed to create new attacher: %v", err) - } - csiAttacher := attacher.(*csiAttacher) nodeName := "test-node" - testCases := []struct { name string initAttached bool @@ -203,21 +194,18 @@ func TestAttacherWaitForVolumeAttachment(t *testing.T) { trigerWatchEventTime time.Duration initAttachErr *storage.VolumeError finalAttachErr *storage.VolumeError - sleepTime time.Duration timeout time.Duration shouldFail bool }{ { name: "attach success at get", initAttached: true, - sleepTime: 10 * time.Millisecond, timeout: 50 * time.Millisecond, shouldFail: false, }, { name: "attachment error ant get", initAttachErr: &storage.VolumeError{Message: "missing volume"}, - sleepTime: 10 * time.Millisecond, timeout: 30 * time.Millisecond, shouldFail: true, }, @@ -227,7 +215,6 @@ func TestAttacherWaitForVolumeAttachment(t *testing.T) { finalAttached: true, trigerWatchEventTime: 5 * time.Millisecond, timeout: 50 * time.Millisecond, - sleepTime: 5 * time.Millisecond, shouldFail: false, }, { @@ -236,7 +223,6 @@ func TestAttacherWaitForVolumeAttachment(t *testing.T) { finalAttached: false, finalAttachErr: &storage.VolumeError{Message: "missing volume"}, trigerWatchEventTime: 5 * time.Millisecond, - sleepTime: 10 * time.Millisecond, timeout: 30 * time.Millisecond, shouldFail: true, }, @@ -246,13 +232,19 @@ func TestAttacherWaitForVolumeAttachment(t *testing.T) { finalAttached: true, trigerWatchEventTime: 100 * time.Millisecond, timeout: 50 * time.Millisecond, - sleepTime: 5 * time.Millisecond, shouldFail: true, }, } for i, tc := range testCases { - fakeWatcher.Reset() + plug, fakeWatcher, tmpDir, _ := newTestWatchPlugin(t) + defer os.RemoveAll(tmpDir) + + attacher, err := plug.NewAttacher() + if err != nil { + t.Fatalf("failed to create new attacher: %v", err) + } + csiAttacher := attacher.(*csiAttacher) t.Logf("running test: %v", tc.name) pvName := fmt.Sprintf("test-pv-%d", i) volID := fmt.Sprintf("test-vol-%d", i) @@ -260,18 +252,21 @@ func TestAttacherWaitForVolumeAttachment(t *testing.T) { attachment := makeTestAttachment(attachID, nodeName, pvName) attachment.Status.Attached = tc.initAttached attachment.Status.AttachError = tc.initAttachErr - csiAttacher.waitSleepTime = tc.sleepTime - _, err := csiAttacher.k8s.StorageV1beta1().VolumeAttachments().Create(attachment) + _, err = csiAttacher.k8s.StorageV1beta1().VolumeAttachments().Create(attachment) if err != nil { t.Fatalf("failed to attach: %v", err) } + trigerWatchEventTime := tc.trigerWatchEventTime + finalAttached := tc.finalAttached + finalAttachErr := tc.finalAttachErr // after timeout, fakeWatcher will be closed by csiAttacher.waitForVolumeAttachment if tc.trigerWatchEventTime > 0 && tc.trigerWatchEventTime < tc.timeout { go func() { - time.Sleep(tc.trigerWatchEventTime) - attachment.Status.Attached = tc.finalAttached - attachment.Status.AttachError = tc.finalAttachErr + time.Sleep(trigerWatchEventTime) + attachment := makeTestAttachment(attachID, nodeName, pvName) + attachment.Status.Attached = finalAttached + attachment.Status.AttachError = finalAttachErr fakeWatcher.Modify(attachment) }() } @@ -511,7 +506,7 @@ func TestAttacherMountDevice(t *testing.T) { devicePath: "", deviceMountPath: "path2", stageUnstageSet: true, - shouldFail: true, + shouldFail: false, }, { testName: "no device mount path", @@ -528,10 +523,6 @@ func TestAttacherMountDevice(t *testing.T) { deviceMountPath: "path2", stageUnstageSet: false, }, - { - testName: "stage_unstage not set no vars should not fail", - stageUnstageSet: false, - }, } for _, tc := range testCases { @@ -576,7 +567,7 @@ func TestAttacherMountDevice(t *testing.T) { if !tc.shouldFail { t.Errorf("test should not fail, but error occurred: %v", err) } - return + continue } if err == nil && tc.shouldFail { t.Errorf("test should fail, but no error occurred") @@ -610,41 +601,51 @@ func TestAttacherUnmountDevice(t *testing.T) { testName string volID string deviceMountPath string + jsonFile string + createPV bool stageUnstageSet bool shouldFail bool }{ { - testName: "normal", + testName: "normal, json file exists", volID: "project/zone/test-vol1", - deviceMountPath: "/tmp/csi-test049507108/plugins/csi/pv/test-pv-name/globalmount", + deviceMountPath: "plugins/csi/pv/test-pv-name/globalmount", + jsonFile: `{"driverName": "csi", "volumeHandle":"project/zone/test-vol1"}`, + createPV: false, stageUnstageSet: true, }, { - testName: "no device mount path", + testName: "normal, json file doesn't exist -> use PV", volID: "project/zone/test-vol1", - deviceMountPath: "", + deviceMountPath: "plugins/csi/pv/test-pv-name/globalmount", + jsonFile: "", + createPV: true, stageUnstageSet: true, - shouldFail: true, }, { - testName: "missing part of device mount path", + testName: "invalid json -> use PV", volID: "project/zone/test-vol1", - deviceMountPath: "/tmp/csi-test049507108/plugins/csi/pv/test-pv-name/globalmount", + deviceMountPath: "plugins/csi/pv/test-pv-name/globalmount", + jsonFile: `{"driverName"}}`, + createPV: true, stageUnstageSet: true, - shouldFail: true, }, { - testName: "test volume name mismatch", - volID: "project/zone/test-vol1", - deviceMountPath: "/tmp/csi-test049507108/plugins/csi/pv/test-pv-name/globalmount", - stageUnstageSet: true, + testName: "no json, no PV.volID", + volID: "", + deviceMountPath: "plugins/csi/pv/test-pv-name/globalmount", + jsonFile: "", + createPV: true, shouldFail: true, }, { - testName: "stage_unstage not set", + testName: "no json, no PV", volID: "project/zone/test-vol1", - deviceMountPath: "/tmp/csi-test049507108/plugins/csi/pv/test-pv-name/globalmount", - stageUnstageSet: false, + deviceMountPath: "plugins/csi/pv/test-pv-name/globalmount", + jsonFile: "", + createPV: false, + stageUnstageSet: true, + shouldFail: true, }, { testName: "stage_unstage not set no vars should not fail", @@ -665,29 +666,45 @@ func TestAttacherUnmountDevice(t *testing.T) { csiAttacher := attacher.(*csiAttacher) csiAttacher.csiClient = setupClient(t, tc.stageUnstageSet) + if tc.deviceMountPath != "" { + tc.deviceMountPath = filepath.Join(tmpDir, tc.deviceMountPath) + } + // Add the volume to NodeStagedVolumes cdc := csiAttacher.csiClient.(*fakeCsiDriverClient) cdc.nodeClient.AddNodeStagedVolume(tc.volID, tc.deviceMountPath) - // Make the PV for this object + // Make JSON for this object + if tc.deviceMountPath != "" { + if err := os.MkdirAll(tc.deviceMountPath, 0755); err != nil { + t.Fatalf("error creating directory %s: %s", tc.deviceMountPath, err) + } + } dir := filepath.Dir(tc.deviceMountPath) - // dir is now /var/lib/kubelet/plugins/kubernetes.io/csi/pv/{pvname} - pvName := filepath.Base(dir) - pv := makeTestPV(pvName, 5, "csi", tc.volID) - _, err := csiAttacher.k8s.CoreV1().PersistentVolumes().Create(pv) - if err != nil && !tc.shouldFail { - t.Fatalf("Failed to create PV: %v", err) + if tc.jsonFile != "" { + dataPath := filepath.Join(dir, volDataFileName) + if err := ioutil.WriteFile(dataPath, []byte(tc.jsonFile), 0644); err != nil { + t.Fatalf("error creating %s: %s", dataPath, err) + } + } + if tc.createPV { + // Make the PV for this object + pvName := filepath.Base(dir) + pv := makeTestPV(pvName, 5, "csi", tc.volID) + _, err := csiAttacher.k8s.CoreV1().PersistentVolumes().Create(pv) + if err != nil && !tc.shouldFail { + t.Fatalf("Failed to create PV: %v", err) + } } // Run - err = csiAttacher.UnmountDevice(tc.deviceMountPath) - + err := csiAttacher.UnmountDevice(tc.deviceMountPath) // Verify if err != nil { if !tc.shouldFail { t.Errorf("test should not fail, but error occurred: %v", err) } - return + continue } if err == nil && tc.shouldFail { t.Errorf("test should fail, but no error occurred") @@ -710,18 +727,30 @@ func TestAttacherUnmountDevice(t *testing.T) { t.Errorf("could not find expected staged volume: %s", tc.volID) } + if tc.jsonFile != "" && !tc.shouldFail { + dataPath := filepath.Join(dir, volDataFileName) + if _, err := os.Stat(dataPath); !os.IsNotExist(err) { + if err != nil { + t.Errorf("error checking file %s: %s", dataPath, err) + } else { + t.Errorf("json file %s should not exists, but it does", dataPath) + } + } else { + t.Logf("json file %s was correctly removed", dataPath) + } + } } } // create a plugin mgr to load plugins and setup a fake client -func newTestWatchPlugin(t *testing.T) (*csiPlugin, *watch.FakeWatcher, string, *fakeclient.Clientset) { +func newTestWatchPlugin(t *testing.T) (*csiPlugin, *watch.RaceFreeFakeWatcher, string, *fakeclient.Clientset) { tmpDir, err := utiltesting.MkTmpdir("csi-test") if err != nil { t.Fatalf("can't create temp dir: %v", err) } fakeClient := fakeclient.NewSimpleClientset() - fakeWatcher := watch.NewFake() + fakeWatcher := watch.NewRaceFreeFake() fakeClient.Fake.PrependWatchReactor("*", core.DefaultWatchReactor(fakeWatcher, nil)) fakeClient.Fake.WatchReactionChain = fakeClient.Fake.WatchReactionChain[:1] host := volumetest.NewFakeVolumeHost( diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_block.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_block.go new file mode 100644 index 000000000..502747d28 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_block.go @@ -0,0 +1,283 @@ +/* +Copyright 2018 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 csi + +import ( + "context" + "errors" + "fmt" + "os" + "path/filepath" + + "github.com/golang/glog" + + "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/volume" +) + +type csiBlockMapper struct { + k8s kubernetes.Interface + csiClient csiClient + plugin *csiPlugin + driverName string + specName string + volumeID string + readOnly bool + spec *volume.Spec + podUID types.UID + volumeInfo map[string]string +} + +var _ volume.BlockVolumeMapper = &csiBlockMapper{} + +// GetGlobalMapPath returns a path (on the node) where the devicePath will be symlinked to +// Example: plugins/kubernetes.io/csi/volumeDevices/{volumeID} +func (m *csiBlockMapper) GetGlobalMapPath(spec *volume.Spec) (string, error) { + dir := getVolumeDevicePluginDir(spec.Name(), m.plugin.host) + glog.V(4).Infof(log("blockMapper.GetGlobalMapPath = %s", dir)) + return dir, nil +} + +// GetPodDeviceMapPath returns pod's device map path and volume name +// path: pods/{podUid}/volumeDevices/kubernetes.io~csi/, {volumeID} +func (m *csiBlockMapper) GetPodDeviceMapPath() (string, string) { + path, specName := m.plugin.host.GetPodVolumeDeviceDir(m.podUID, csiPluginName), m.specName + glog.V(4).Infof(log("blockMapper.GetPodDeviceMapPath = %s", path)) + return path, specName +} + +// SetUpDevice ensures the device is attached returns path where the device is located. +func (m *csiBlockMapper) SetUpDevice() (string, error) { + if !m.plugin.blockEnabled { + return "", errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof(log("blockMapper.SetupDevice called")) + + if m.spec == nil { + glog.Error(log("blockMapper.Map spec is nil")) + return "", fmt.Errorf("spec is nil") + } + csiSource, err := getCSISourceFromSpec(m.spec) + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed to get CSI persistent source: %v", err)) + return "", err + } + + globalMapPath, err := m.GetGlobalMapPath(m.spec) + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed to get global map path: %v", err)) + return "", err + } + + csi := m.csiClient + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) + defer cancel() + + // Check whether "STAGE_UNSTAGE_VOLUME" is set + stageUnstageSet, err := hasStageUnstageCapability(ctx, csi) + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed to check STAGE_UNSTAGE_VOLUME capability: %v", err)) + return "", err + } + if !stageUnstageSet { + glog.Infof(log("blockMapper.SetupDevice STAGE_UNSTAGE_VOLUME capability not set. Skipping MountDevice...")) + return "", nil + } + + // Start MountDevice + nodeName := string(m.plugin.host.GetNodeName()) + attachID := getAttachmentName(csiSource.VolumeHandle, csiSource.Driver, nodeName) + + // search for attachment by VolumeAttachment.Spec.Source.PersistentVolumeName + attachment, err := m.k8s.StorageV1beta1().VolumeAttachments().Get(attachID, meta.GetOptions{}) + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed to get volume attachment [id=%v]: %v", attachID, err)) + return "", err + } + + if attachment == nil { + glog.Error(log("blockMapper.SetupDevice unable to find VolumeAttachment [id=%s]", attachID)) + return "", errors.New("no existing VolumeAttachment found") + } + publishVolumeInfo := attachment.Status.AttachmentMetadata + + nodeStageSecrets := map[string]string{} + if csiSource.NodeStageSecretRef != nil { + nodeStageSecrets, err = getCredentialsFromSecret(m.k8s, csiSource.NodeStageSecretRef) + if err != nil { + return "", fmt.Errorf("failed to get NodeStageSecretRef %s/%s: %v", + csiSource.NodeStageSecretRef.Namespace, csiSource.NodeStageSecretRef.Name, err) + } + } + + // create globalMapPath before call to NodeStageVolume + if err := os.MkdirAll(globalMapPath, 0750); err != nil { + glog.Error(log("blockMapper.SetupDevice failed to create dir %s: %v", globalMapPath, err)) + return "", err + } + glog.V(4).Info(log("blockMapper.SetupDevice created global device map path successfully [%s]", globalMapPath)) + + //TODO (vladimirvivien) implement better AccessModes mapping between k8s and CSI + accessMode := v1.ReadWriteOnce + if m.spec.PersistentVolume.Spec.AccessModes != nil { + accessMode = m.spec.PersistentVolume.Spec.AccessModes[0] + } + + err = csi.NodeStageVolume(ctx, + csiSource.VolumeHandle, + publishVolumeInfo, + globalMapPath, + fsTypeBlockName, + accessMode, + nodeStageSecrets, + csiSource.VolumeAttributes) + + if err != nil { + glog.Error(log("blockMapper.SetupDevice failed: %v", err)) + if err := os.RemoveAll(globalMapPath); err != nil { + glog.Error(log("blockMapper.SetupDevice failed to remove dir after a NodeStageVolume() error [%s]: %v", globalMapPath, err)) + } + return "", err + } + + glog.V(4).Infof(log("blockMapper.SetupDevice successfully requested NodeStageVolume [%s]", globalMapPath)) + return globalMapPath, nil +} + +func (m *csiBlockMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + if !m.plugin.blockEnabled { + return errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof(log("blockMapper.MapDevice mapping block device %s", devicePath)) + + if m.spec == nil { + glog.Error(log("blockMapper.MapDevice spec is nil")) + return fmt.Errorf("spec is nil") + } + + csiSource, err := getCSISourceFromSpec(m.spec) + if err != nil { + glog.Error(log("blockMapper.Map failed to get CSI persistent source: %v", err)) + return err + } + + dir := filepath.Join(volumeMapPath, volumeMapName) + csi := m.csiClient + + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) + defer cancel() + + nodeName := string(m.plugin.host.GetNodeName()) + attachID := getAttachmentName(csiSource.VolumeHandle, csiSource.Driver, nodeName) + + // search for attachment by VolumeAttachment.Spec.Source.PersistentVolumeName + attachment, err := m.k8s.StorageV1beta1().VolumeAttachments().Get(attachID, meta.GetOptions{}) + if err != nil { + glog.Error(log("blockMapper.MapDevice failed to get volume attachment [id=%v]: %v", attachID, err)) + return err + } + + if attachment == nil { + glog.Error(log("blockMapper.MapDevice unable to find VolumeAttachment [id=%s]", attachID)) + return errors.New("no existing VolumeAttachment found") + } + publishVolumeInfo := attachment.Status.AttachmentMetadata + + nodePublishSecrets := map[string]string{} + if csiSource.NodePublishSecretRef != nil { + nodePublishSecrets, err = getCredentialsFromSecret(m.k8s, csiSource.NodePublishSecretRef) + if err != nil { + glog.Errorf("blockMapper.MapDevice failed to get NodePublishSecretRef %s/%s: %v", + csiSource.NodePublishSecretRef.Namespace, csiSource.NodePublishSecretRef.Name, err) + return err + } + } + + if err := os.MkdirAll(dir, 0750); err != nil { + glog.Error(log("blockMapper.MapDevice failed to create dir %#v: %v", dir, err)) + return err + } + glog.V(4).Info(log("blockMapper.MapDevice created NodePublish path [%s]", dir)) + + //TODO (vladimirvivien) implement better AccessModes mapping between k8s and CSI + accessMode := v1.ReadWriteOnce + if m.spec.PersistentVolume.Spec.AccessModes != nil { + accessMode = m.spec.PersistentVolume.Spec.AccessModes[0] + } + + err = csi.NodePublishVolume( + ctx, + m.volumeID, + m.readOnly, + globalMapPath, + dir, + accessMode, + publishVolumeInfo, + csiSource.VolumeAttributes, + nodePublishSecrets, + fsTypeBlockName, + ) + + if err != nil { + glog.Errorf(log("blockMapper.MapDevice failed: %v", err)) + if err := os.RemoveAll(dir); err != nil { + glog.Error(log("blockMapper.MapDevice failed to remove mount dir after a NodePublish() error [%s]: %v", dir, err)) + } + return err + } + + return nil +} + +var _ volume.BlockVolumeUnmapper = &csiBlockMapper{} + +// TearDownDevice removes traces of the SetUpDevice. +func (m *csiBlockMapper) TearDownDevice(globalMapPath, devicePath string) error { + if !m.plugin.blockEnabled { + return errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof(log("unmapper.TearDownDevice(globalMapPath=%s; devicePath=%s)", globalMapPath, devicePath)) + + csi := m.csiClient + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) + defer cancel() + + // unmap global device map path + if err := csi.NodeUnstageVolume(ctx, m.volumeID, globalMapPath); err != nil { + glog.Errorf(log("blockMapper.TearDownDevice failed: %v", err)) + return err + } + glog.V(4).Infof(log("blockMapper.TearDownDevice NodeUnstageVolume successfully [%s]", globalMapPath)) + + // request to remove pod volume map path also + podVolumePath, volumeName := m.GetPodDeviceMapPath() + podVolumeMapPath := filepath.Join(podVolumePath, volumeName) + if err := csi.NodeUnpublishVolume(ctx, m.volumeID, podVolumeMapPath); err != nil { + glog.Error(log("blockMapper.TearDownDevice failed: %v", err)) + return err + } + + glog.V(4).Infof(log("blockMapper.TearDownDevice NodeUnpublished successfully [%s]", podVolumeMapPath)) + + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_block_test.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_block_test.go new file mode 100644 index 000000000..af3401478 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_block_test.go @@ -0,0 +1,264 @@ +/* +Copyright 2018 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 csi + +import ( + "fmt" + "os" + "path" + "path/filepath" + "testing" + + api "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + fakeclient "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/pkg/volume" + volumetest "k8s.io/kubernetes/pkg/volume/testing" +) + +func TestBlockMapperGetGlobalMapPath(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + // TODO (vladimirvivien) specName with slashes will not work + testCases := []struct { + name string + specVolumeName string + path string + }{ + { + name: "simple specName", + specVolumeName: "spec-0", + path: path.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/%s/%s", "spec-0", "dev")), + }, + { + name: "specName with dots", + specVolumeName: "test.spec.1", + path: path.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/%s/%s", "test.spec.1", "dev")), + }, + } + for _, tc := range testCases { + t.Logf("test case: %s", tc.name) + pv := makeTestPV(tc.specVolumeName, 10, testDriver, testVol) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + mapper, err := plug.NewBlockVolumeMapper( + spec, + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("Failed to make a new Mapper: %v", err) + } + csiMapper := mapper.(*csiBlockMapper) + + path, err := csiMapper.GetGlobalMapPath(spec) + if err != nil { + t.Errorf("mapper GetGlobalMapPath failed: %v", err) + } + + if tc.path != path { + t.Errorf("expecting path %s, got %s", tc.path, path) + } + } +} + +func TestBlockMapperSetupDevice(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + fakeClient := fakeclient.NewSimpleClientset() + host := volumetest.NewFakeVolumeHostWithNodeName( + tmpDir, + fakeClient, + nil, + "fakeNode", + ) + plug.host = host + pv := makeTestPV("test-pv", 10, testDriver, testVol) + pvName := pv.GetName() + nodeName := string(plug.host.GetNodeName()) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + + // MapDevice + mapper, err := plug.NewBlockVolumeMapper( + spec, + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("failed to create new mapper: %v", err) + } + csiMapper := mapper.(*csiBlockMapper) + csiMapper.csiClient = setupClient(t, true) + + attachID := getAttachmentName(csiMapper.volumeID, csiMapper.driverName, string(nodeName)) + attachment := makeTestAttachment(attachID, nodeName, pvName) + attachment.Status.Attached = true + _, err = csiMapper.k8s.StorageV1beta1().VolumeAttachments().Create(attachment) + if err != nil { + t.Fatalf("failed to setup VolumeAttachment: %v", err) + } + t.Log("created attachement ", attachID) + + devicePath, err := csiMapper.SetUpDevice() + if err != nil { + t.Fatalf("mapper failed to SetupDevice: %v", err) + } + + globalMapPath, err := csiMapper.GetGlobalMapPath(spec) + if err != nil { + t.Fatalf("mapper failed to GetGlobalMapPath: %v", err) + } + + if devicePath != globalMapPath { + t.Fatalf("mapper.SetupDevice returned unexpected path %s instead of %v", devicePath, globalMapPath) + } + + vols := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodeStagedVolumes() + if vols[csiMapper.volumeID] != devicePath { + t.Error("csi server may not have received NodePublishVolume call") + } +} + +func TestBlockMapperMapDevice(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + fakeClient := fakeclient.NewSimpleClientset() + host := volumetest.NewFakeVolumeHostWithNodeName( + tmpDir, + fakeClient, + nil, + "fakeNode", + ) + plug.host = host + pv := makeTestPV("test-pv", 10, testDriver, testVol) + pvName := pv.GetName() + nodeName := string(plug.host.GetNodeName()) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + + // MapDevice + mapper, err := plug.NewBlockVolumeMapper( + spec, + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("failed to create new mapper: %v", err) + } + csiMapper := mapper.(*csiBlockMapper) + csiMapper.csiClient = setupClient(t, true) + + attachID := getAttachmentName(csiMapper.volumeID, csiMapper.driverName, string(nodeName)) + attachment := makeTestAttachment(attachID, nodeName, pvName) + attachment.Status.Attached = true + _, err = csiMapper.k8s.StorageV1beta1().VolumeAttachments().Create(attachment) + if err != nil { + t.Fatalf("failed to setup VolumeAttachment: %v", err) + } + t.Log("created attachement ", attachID) + + devicePath, err := csiMapper.SetUpDevice() + if err != nil { + t.Fatalf("mapper failed to SetupDevice: %v", err) + } + globalMapPath, err := csiMapper.GetGlobalMapPath(csiMapper.spec) + if err != nil { + t.Fatalf("mapper failed to GetGlobalMapPath: %v", err) + } + + // Map device to global and pod device map path + volumeMapPath, volName := csiMapper.GetPodDeviceMapPath() + err = csiMapper.MapDevice(devicePath, globalMapPath, volumeMapPath, volName, csiMapper.podUID) + if err != nil { + t.Fatalf("mapper failed to GetGlobalMapPath: %v", err) + } + + if _, err := os.Stat(filepath.Join(volumeMapPath, volName)); err != nil { + if os.IsNotExist(err) { + t.Errorf("mapper.MapDevice failed, volume path not created: %s", volumeMapPath) + } else { + t.Errorf("mapper.MapDevice failed: %v", err) + } + } + + pubs := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes() + if pubs[csiMapper.volumeID] != volumeMapPath { + t.Error("csi server may not have received NodePublishVolume call") + } +} + +func TestBlockMapperTearDownDevice(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + fakeClient := fakeclient.NewSimpleClientset() + host := volumetest.NewFakeVolumeHostWithNodeName( + tmpDir, + fakeClient, + nil, + "fakeNode", + ) + plug.host = host + pv := makeTestPV("test-pv", 10, testDriver, testVol) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + + // save volume data + dir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host) + if err := os.MkdirAll(dir, 0755); err != nil && !os.IsNotExist(err) { + t.Errorf("failed to create dir [%s]: %v", dir, err) + } + + if err := saveVolumeData( + dir, + volDataFileName, + map[string]string{ + volDataKey.specVolID: pv.ObjectMeta.Name, + volDataKey.driverName: testDriver, + volDataKey.volHandle: testVol, + }, + ); err != nil { + t.Fatalf("failed to save volume data: %v", err) + } + + unmapper, err := plug.NewBlockVolumeUnmapper(pv.ObjectMeta.Name, testPodUID) + if err != nil { + t.Fatalf("failed to make a new Unmapper: %v", err) + } + + csiUnmapper := unmapper.(*csiBlockMapper) + csiUnmapper.csiClient = setupClient(t, true) + + globalMapPath, err := csiUnmapper.GetGlobalMapPath(spec) + if err != nil { + t.Fatalf("unmapper failed to GetGlobalMapPath: %v", err) + } + + err = csiUnmapper.TearDownDevice(globalMapPath, "/dev/test") + if err != nil { + t.Fatal(err) + } + + // ensure csi client call and node unstaged + vols := csiUnmapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodeStagedVolumes() + if _, ok := vols[csiUnmapper.volumeID]; ok { + t.Error("csi server may not have received NodeUnstageVolume call") + } + + // ensure csi client call and node unpblished + pubs := csiUnmapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes() + if _, ok := pubs[csiUnmapper.volumeID]; ok { + t.Error("csi server may not have received NodeUnpublishVolume call") + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_client.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_client.go index 197a2ead6..e12772d7a 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_client.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_client.go @@ -17,6 +17,7 @@ limitations under the License. package csi import ( + "context" "errors" "fmt" "net" @@ -24,14 +25,15 @@ import ( csipb "github.com/container-storage-interface/spec/lib/go/csi/v0" "github.com/golang/glog" - grpctx "golang.org/x/net/context" "google.golang.org/grpc" api "k8s.io/api/core/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" ) type csiClient interface { NodePublishVolume( - ctx grpctx.Context, + ctx context.Context, volumeid string, readOnly bool, stagingTargetPath string, @@ -43,11 +45,11 @@ type csiClient interface { fsType string, ) error NodeUnpublishVolume( - ctx grpctx.Context, + ctx context.Context, volID string, targetPath string, ) error - NodeStageVolume(ctx grpctx.Context, + NodeStageVolume(ctx context.Context, volID string, publishVolumeInfo map[string]string, stagingTargetPath string, @@ -56,8 +58,8 @@ type csiClient interface { nodeStageSecrets map[string]string, volumeAttribs map[string]string, ) error - NodeUnstageVolume(ctx grpctx.Context, volID, stagingTargetPath string) error - NodeGetCapabilities(ctx grpctx.Context) ([]*csipb.NodeServiceCapability, error) + NodeUnstageVolume(ctx context.Context, volID, stagingTargetPath string) error + NodeGetCapabilities(ctx context.Context) ([]*csipb.NodeServiceCapability, error) } // csiClient encapsulates all csi-plugin methods @@ -74,7 +76,7 @@ func newCsiDriverClient(driverName string) *csiDriverClient { } func (c *csiDriverClient) NodePublishVolume( - ctx grpctx.Context, + ctx context.Context, volID string, readOnly bool, stagingTargetPath string, @@ -111,22 +113,29 @@ func (c *csiDriverClient) NodePublishVolume( AccessMode: &csipb.VolumeCapability_AccessMode{ Mode: asCSIAccessMode(accessMode), }, - AccessType: &csipb.VolumeCapability_Mount{ - Mount: &csipb.VolumeCapability_MountVolume{ - FsType: fsType, - }, - }, }, } if stagingTargetPath != "" { req.StagingTargetPath = stagingTargetPath } + if fsType == fsTypeBlockName { + req.VolumeCapability.AccessType = &csipb.VolumeCapability_Block{ + Block: &csipb.VolumeCapability_BlockVolume{}, + } + } else { + req.VolumeCapability.AccessType = &csipb.VolumeCapability_Mount{ + Mount: &csipb.VolumeCapability_MountVolume{ + FsType: fsType, + }, + } + } + _, err = nodeClient.NodePublishVolume(ctx, req) return err } -func (c *csiDriverClient) NodeUnpublishVolume(ctx grpctx.Context, volID string, targetPath string) error { +func (c *csiDriverClient) NodeUnpublishVolume(ctx context.Context, volID string, targetPath string) error { glog.V(4).Info(log("calling NodeUnpublishVolume rpc: [volid=%s, target_path=%s", volID, targetPath)) if volID == "" { return errors.New("missing volume id") @@ -151,7 +160,7 @@ func (c *csiDriverClient) NodeUnpublishVolume(ctx grpctx.Context, volID string, return err } -func (c *csiDriverClient) NodeStageVolume(ctx grpctx.Context, +func (c *csiDriverClient) NodeStageVolume(ctx context.Context, volID string, publishInfo map[string]string, stagingTargetPath string, @@ -183,21 +192,28 @@ func (c *csiDriverClient) NodeStageVolume(ctx grpctx.Context, AccessMode: &csipb.VolumeCapability_AccessMode{ Mode: asCSIAccessMode(accessMode), }, - AccessType: &csipb.VolumeCapability_Mount{ - Mount: &csipb.VolumeCapability_MountVolume{ - FsType: fsType, - }, - }, }, NodeStageSecrets: nodeStageSecrets, VolumeAttributes: volumeAttribs, } + if fsType == fsTypeBlockName { + req.VolumeCapability.AccessType = &csipb.VolumeCapability_Block{ + Block: &csipb.VolumeCapability_BlockVolume{}, + } + } else { + req.VolumeCapability.AccessType = &csipb.VolumeCapability_Mount{ + Mount: &csipb.VolumeCapability_MountVolume{ + FsType: fsType, + }, + } + } + _, err = nodeClient.NodeStageVolume(ctx, req) return err } -func (c *csiDriverClient) NodeUnstageVolume(ctx grpctx.Context, volID, stagingTargetPath string) error { +func (c *csiDriverClient) NodeUnstageVolume(ctx context.Context, volID, stagingTargetPath string) error { glog.V(4).Info(log("calling NodeUnstageVolume rpc [volid=%s,staging_target_path=%s]", volID, stagingTargetPath)) if volID == "" { return errors.New("missing volume id") @@ -221,7 +237,7 @@ func (c *csiDriverClient) NodeUnstageVolume(ctx grpctx.Context, volID, stagingTa return err } -func (c *csiDriverClient) NodeGetCapabilities(ctx grpctx.Context) ([]*csipb.NodeServiceCapability, error) { +func (c *csiDriverClient) NodeGetCapabilities(ctx context.Context) ([]*csipb.NodeServiceCapability, error) { glog.V(4).Info(log("calling NodeGetCapabilities rpc")) conn, err := newGrpcConn(c.driverName) @@ -255,9 +271,16 @@ func newGrpcConn(driverName string) (*grpc.ClientConn, error) { if driverName == "" { return nil, fmt.Errorf("driver name is empty") } - - network := "unix" addr := fmt.Sprintf(csiAddrTemplate, driverName) + // TODO once KubeletPluginsWatcher graduates to beta, remove FeatureGate check + if utilfeature.DefaultFeatureGate.Enabled(features.KubeletPluginsWatcher) { + driver, ok := csiDrivers.driversMap[driverName] + if !ok { + return nil, fmt.Errorf("driver name %s not found in the list of registered CSI drivers", driverName) + } + addr = driver.driverEndpoint + } + network := "unix" glog.V(4).Infof(log("creating new gRPC connection for [%s://%s]", network, addr)) return grpc.Dial( diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_client_test.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_client_test.go index 18bb12c83..c5b8cf01f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_client_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_client_test.go @@ -22,7 +22,6 @@ import ( "testing" csipb "github.com/container-storage-interface/spec/lib/go/csi/v0" - grpctx "golang.org/x/net/context" api "k8s.io/api/core/v1" "k8s.io/kubernetes/pkg/volume/csi/fake" ) @@ -164,7 +163,7 @@ func TestClientNodePublishVolume(t *testing.T) { t.Logf("test case: %s", tc.name) client.(*fakeCsiDriverClient).nodeClient.SetNextError(tc.err) err := client.NodePublishVolume( - grpctx.Background(), + context.Background(), tc.volID, false, "", @@ -231,7 +230,7 @@ func TestClientNodeStageVolume(t *testing.T) { t.Logf("Running test case: %s", tc.name) client.(*fakeCsiDriverClient).nodeClient.SetNextError(tc.err) err := client.NodeStageVolume( - grpctx.Background(), + context.Background(), tc.volID, map[string]string{"device": "/dev/null"}, tc.stagingTargetPath, @@ -267,7 +266,7 @@ func TestClientNodeUnstageVolume(t *testing.T) { t.Logf("Running test case: %s", tc.name) client.(*fakeCsiDriverClient).nodeClient.SetNextError(tc.err) err := client.NodeUnstageVolume( - grpctx.Background(), + context.Background(), tc.volID, tc.stagingTargetPath, ) if tc.mustFail && err == nil { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_mounter.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_mounter.go index 67f0e4c1d..57700895d 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_mounter.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_mounter.go @@ -17,14 +17,14 @@ limitations under the License. package csi import ( - "encoding/json" + "context" "errors" "fmt" "os" "path" "github.com/golang/glog" - grpctx "golang.org/x/net/context" + api "k8s.io/api/core/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -34,8 +34,6 @@ import ( "k8s.io/kubernetes/pkg/volume/util" ) -const defaultFSType = "ext4" - //TODO (vladimirvivien) move this in a central loc later var ( volDataKey = struct { @@ -118,7 +116,7 @@ func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { nodeName := string(c.plugin.host.GetNodeName()) attachID := getAttachmentName(csiSource.VolumeHandle, csiSource.Driver, nodeName) - ctx, cancel := grpctx.WithTimeout(grpctx.Background(), csiTimeout) + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) defer cancel() // Check for STAGE_UNSTAGE_VOLUME set and populate deviceMountPath if so @@ -177,9 +175,6 @@ func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { } fsType := csiSource.FSType - if len(fsType) == 0 { - fsType = defaultFSType - } err = csi.NodePublishVolume( ctx, c.volumeID, @@ -195,9 +190,8 @@ func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { if err != nil { glog.Errorf(log("mounter.SetupAt failed: %v", err)) - if err := removeMountDir(c.plugin, dir); err != nil { - glog.Error(log("mounter.SetuAt failed to remove mount dir after a NodePublish() error [%s]: %v", dir, err)) - return err + if removeMountDirErr := removeMountDir(c.plugin, dir); removeMountDirErr != nil { + glog.Error(log("mounter.SetupAt failed to remove mount dir after a NodePublish() error [%s]: %v", dir, removeMountDirErr)) } return err } @@ -276,7 +270,7 @@ func (c *csiMountMgr) TearDownAt(dir string) error { volID := c.volumeID csi := c.csiClient - ctx, cancel := grpctx.WithTimeout(grpctx.Background(), csiTimeout) + ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) defer cancel() if err := csi.NodeUnpublishVolume(ctx, volID, dir); err != nil { @@ -294,45 +288,6 @@ func (c *csiMountMgr) TearDownAt(dir string) error { return nil } -// saveVolumeData persists parameter data as json file at the provided location -func saveVolumeData(dir string, fileName string, data map[string]string) error { - dataFilePath := path.Join(dir, fileName) - glog.V(4).Info(log("saving volume data file [%s]", dataFilePath)) - file, err := os.Create(dataFilePath) - if err != nil { - glog.Error(log("failed to save volume data file %s: %v", dataFilePath, err)) - return err - } - defer file.Close() - if err := json.NewEncoder(file).Encode(data); err != nil { - glog.Error(log("failed to save volume data file %s: %v", dataFilePath, err)) - return err - } - glog.V(4).Info(log("volume data file saved successfully [%s]", dataFilePath)) - return nil -} - -// loadVolumeData loads volume info from specified json file/location -func loadVolumeData(dir string, fileName string) (map[string]string, error) { - // remove /mount at the end - dataFileName := path.Join(dir, fileName) - glog.V(4).Info(log("loading volume data file [%s]", dataFileName)) - - file, err := os.Open(dataFileName) - if err != nil { - glog.Error(log("failed to open volume data file [%s]: %v", dataFileName, err)) - return nil, err - } - defer file.Close() - data := map[string]string{} - if err := json.NewDecoder(file).Decode(&data); err != nil { - glog.Error(log("failed to parse volume data file [%s]: %v", dataFileName, err)) - return nil, err - } - - return data, nil -} - // isDirMounted returns the !notMounted result from IsLikelyNotMountPoint check func isDirMounted(plug *csiPlugin, dir string) (bool, error) { mounter := plug.host.GetMounter(plug.GetPluginName()) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_mounter_test.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_mounter_test.go index d1e942871..88b2b1a2d 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_mounter_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_mounter_test.go @@ -144,6 +144,12 @@ func TestMounterSetUp(t *testing.T) { if err := csiMounter.SetUp(&fsGroup); err != nil { t.Fatalf("mounter.Setup failed: %v", err) } + + //Test the default value of file system type is not overridden + if len(csiMounter.spec.PersistentVolume.Spec.CSI.FSType) != 0 { + t.Errorf("default value of file system type was overridden by type %s", csiMounter.spec.PersistentVolume.Spec.CSI.FSType) + } + path := csiMounter.GetPath() if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_plugin.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_plugin.go index 8a993afb9..d10457686 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_plugin.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_plugin.go @@ -21,14 +21,19 @@ import ( "fmt" "os" "path" + "strings" + "sync" "time" "github.com/golang/glog" api "k8s.io/api/core/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/csi/labelmanager" ) const ( @@ -42,16 +47,19 @@ const ( csiTimeout = 15 * time.Second volNameSep = "^" volDataFileName = "vol_data.json" + fsTypeBlockName = "block" ) type csiPlugin struct { - host volume.VolumeHost + host volume.VolumeHost + blockEnabled bool } // ProbeVolumePlugins returns implemented plugins func ProbeVolumePlugins() []volume.VolumePlugin { p := &csiPlugin{ - host: nil, + host: nil, + blockEnabled: utilfeature.DefaultFeatureGate.Enabled(features.CSIBlockVolume), } return []volume.VolumePlugin{p} } @@ -59,9 +67,54 @@ func ProbeVolumePlugins() []volume.VolumePlugin { // volume.VolumePlugin methods var _ volume.VolumePlugin = &csiPlugin{} +type csiDriver struct { + driverName string + driverEndpoint string +} + +type csiDriversStore struct { + driversMap map[string]csiDriver + sync.RWMutex +} + +// csiDrivers map keep track of all registered CSI drivers on the node and their +// corresponding sockets +var csiDrivers csiDriversStore + +var lm labelmanager.Interface + +// RegistrationCallback is called by kubelet's plugin watcher upon detection +// of a new registration socket opened by CSI Driver registrar side car. +func RegistrationCallback(pluginName string, endpoint string, versions []string, socketPath string) (error, chan bool) { + + glog.Infof(log("Callback from kubelet with plugin name: %s endpoint: %s versions: %s socket path: %s", + pluginName, endpoint, strings.Join(versions, ","), socketPath)) + + if endpoint == "" { + endpoint = socketPath + } + // Calling nodeLabelManager to update label for newly registered CSI driver + err := lm.AddLabels(pluginName) + if err != nil { + return err, nil + } + // Storing endpoint of newly registered CSI driver into the map, where CSI driver name will be the key + // all other CSI components will be able to get the actual socket of CSI drivers by its name. + csiDrivers.Lock() + defer csiDrivers.Unlock() + csiDrivers.driversMap[pluginName] = csiDriver{driverName: pluginName, driverEndpoint: endpoint} + + return nil, nil +} + func (p *csiPlugin) Init(host volume.VolumeHost) error { glog.Info(log("plugin initializing...")) p.host = host + + // Initializing csiDrivers map and label management channels + csiDrivers = csiDriversStore{driversMap: map[string]csiDriver{}} + lm = labelmanager.NewLabelManager(host.GetNodeName(), host.GetKubeClient()) + return nil } @@ -259,25 +312,132 @@ func (p *csiPlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) return mount.GetMountRefs(m, deviceMountPath) } -func getCSISourceFromSpec(spec *volume.Spec) (*api.CSIPersistentVolumeSource, error) { - if spec.PersistentVolume != nil && - spec.PersistentVolume.Spec.CSI != nil { - return spec.PersistentVolume.Spec.CSI, nil +// BlockVolumePlugin methods +var _ volume.BlockVolumePlugin = &csiPlugin{} + +func (p *csiPlugin) NewBlockVolumeMapper(spec *volume.Spec, podRef *api.Pod, opts volume.VolumeOptions) (volume.BlockVolumeMapper, error) { + if !p.blockEnabled { + return nil, errors.New("CSIBlockVolume feature not enabled") } - return nil, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") + pvSource, err := getCSISourceFromSpec(spec) + if err != nil { + return nil, err + } + readOnly, err := getReadOnlyFromSpec(spec) + if err != nil { + return nil, err + } + + glog.V(4).Info(log("setting up block mapper for [volume=%v,driver=%v]", pvSource.VolumeHandle, pvSource.Driver)) + client := newCsiDriverClient(pvSource.Driver) + + k8s := p.host.GetKubeClient() + if k8s == nil { + glog.Error(log("failed to get a kubernetes client")) + return nil, errors.New("failed to get a Kubernetes client") + } + + mapper := &csiBlockMapper{ + csiClient: client, + k8s: k8s, + plugin: p, + volumeID: pvSource.VolumeHandle, + driverName: pvSource.Driver, + readOnly: readOnly, + spec: spec, + podUID: podRef.UID, + } + + // Save volume info in pod dir + dataDir := getVolumeDeviceDataDir(spec.Name(), p.host) + + if err := os.MkdirAll(dataDir, 0750); err != nil { + glog.Error(log("failed to create data dir %s: %v", dataDir, err)) + return nil, err + } + glog.V(4).Info(log("created path successfully [%s]", dataDir)) + + // persist volume info data for teardown + node := string(p.host.GetNodeName()) + attachID := getAttachmentName(pvSource.VolumeHandle, pvSource.Driver, node) + volData := map[string]string{ + volDataKey.specVolID: spec.Name(), + volDataKey.volHandle: pvSource.VolumeHandle, + volDataKey.driverName: pvSource.Driver, + volDataKey.nodeName: node, + volDataKey.attachmentID: attachID, + } + + if err := saveVolumeData(dataDir, volDataFileName, volData); err != nil { + glog.Error(log("failed to save volume info data: %v", err)) + if err := os.RemoveAll(dataDir); err != nil { + glog.Error(log("failed to remove dir after error [%s]: %v", dataDir, err)) + return nil, err + } + return nil, err + } + + return mapper, nil } -func getReadOnlyFromSpec(spec *volume.Spec) (bool, error) { - if spec.PersistentVolume != nil && - spec.PersistentVolume.Spec.CSI != nil { - return spec.ReadOnly, nil +func (p *csiPlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (volume.BlockVolumeUnmapper, error) { + if !p.blockEnabled { + return nil, errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof(log("setting up block unmapper for [Spec=%v, podUID=%v]", volName, podUID)) + unmapper := &csiBlockMapper{ + plugin: p, + podUID: podUID, + specName: volName, + } + + // load volume info from file + dataDir := getVolumeDeviceDataDir(unmapper.specName, p.host) + data, err := loadVolumeData(dataDir, volDataFileName) + if err != nil { + glog.Error(log("unmapper failed to load volume data file [%s]: %v", dataDir, err)) + return nil, err } + unmapper.driverName = data[volDataKey.driverName] + unmapper.volumeID = data[volDataKey.volHandle] + unmapper.csiClient = newCsiDriverClient(unmapper.driverName) - return false, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") + return unmapper, nil } -// log prepends log string with `kubernetes.io/csi` -func log(msg string, parts ...interface{}) string { - return fmt.Sprintf(fmt.Sprintf("%s: %s", csiPluginName, msg), parts...) +func (p *csiPlugin) ConstructBlockVolumeSpec(podUID types.UID, specVolName, mapPath string) (*volume.Spec, error) { + if !p.blockEnabled { + return nil, errors.New("CSIBlockVolume feature not enabled") + } + + glog.V(4).Infof("plugin.ConstructBlockVolumeSpec [podUID=%s, specVolName=%s, path=%s]", string(podUID), specVolName, mapPath) + + dataDir := getVolumeDeviceDataDir(specVolName, p.host) + volData, err := loadVolumeData(dataDir, volDataFileName) + if err != nil { + glog.Error(log("plugin.ConstructBlockVolumeSpec failed loading volume data using [%s]: %v", mapPath, err)) + return nil, err + } + + glog.V(4).Info(log("plugin.ConstructBlockVolumeSpec extracted [%#v]", volData)) + + blockMode := api.PersistentVolumeBlock + pv := &api.PersistentVolume{ + ObjectMeta: meta.ObjectMeta{ + Name: volData[volDataKey.specVolID], + }, + Spec: api.PersistentVolumeSpec{ + PersistentVolumeSource: api.PersistentVolumeSource{ + CSI: &api.CSIPersistentVolumeSource{ + Driver: volData[volDataKey.driverName], + VolumeHandle: volData[volDataKey.volHandle], + }, + }, + VolumeMode: &blockMode, + }, + } + + return volume.NewSpecFromPersistentVolume(pv, false), nil } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_plugin_test.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_plugin_test.go index ed7a92ffe..ce76592e4 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_plugin_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_plugin_test.go @@ -20,12 +20,14 @@ import ( "fmt" "os" "path" + "path/filepath" "testing" api "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" fakeclient "k8s.io/client-go/kubernetes/fake" utiltesting "k8s.io/client-go/util/testing" "k8s.io/kubernetes/pkg/volume" @@ -34,6 +36,11 @@ import ( // create a plugin mgr to load plugins and setup a fake client func newTestPlugin(t *testing.T) (*csiPlugin, string) { + err := utilfeature.DefaultFeatureGate.Set("CSIBlockVolume=true") + if err != nil { + t.Fatalf("Failed to enable feature gate for CSIBlockVolume: %v", err) + } + tmpDir, err := utiltesting.MkTmpdir("csi-test") if err != nil { t.Fatalf("can't create temp dir: %v", err) @@ -215,7 +222,21 @@ func TestPluginNewMounter(t *testing.T) { t.Error("mounter pod not set") } if csiMounter.podUID == types.UID("") { - t.Error("mounter podUID mot set") + t.Error("mounter podUID not set") + } + if csiMounter.csiClient == nil { + t.Error("mounter csiClient is nil") + } + + // ensure data file is created + dataDir := path.Dir(mounter.GetPath()) + dataFile := filepath.Join(dataDir, volDataFileName) + if _, err := os.Stat(dataFile); err != nil { + if os.IsNotExist(err) { + t.Errorf("data file not created %s", dataFile) + } else { + t.Fatal(err) + } } } @@ -259,6 +280,9 @@ func TestPluginNewUnmounter(t *testing.T) { t.Error("podUID not set") } + if csiUnmounter.csiClient == nil { + t.Error("unmounter csiClient is nil") + } } func TestPluginNewAttacher(t *testing.T) { @@ -296,3 +320,156 @@ func TestPluginNewDetacher(t *testing.T) { t.Error("Kubernetes client not set for detacher") } } + +func TestPluginNewBlockMapper(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-block-pv", 10, testDriver, testVol) + mounter, err := plug.NewBlockVolumeMapper( + volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly), + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("Failed to make a new BlockMapper: %v", err) + } + + if mounter == nil { + t.Fatal("failed to create CSI BlockMapper, mapper is nill") + } + csiMapper := mounter.(*csiBlockMapper) + + // validate mounter fields + if csiMapper.driverName != testDriver { + t.Error("CSI block mapper missing driver name") + } + if csiMapper.volumeID != testVol { + t.Error("CSI block mapper missing volumeID") + } + + if csiMapper.podUID == types.UID("") { + t.Error("CSI block mapper missing pod.UID") + } + if csiMapper.csiClient == nil { + t.Error("mapper csiClient is nil") + } + + // ensure data file is created + dataFile := getVolumeDeviceDataDir(csiMapper.spec.Name(), plug.host) + if _, err := os.Stat(dataFile); err != nil { + if os.IsNotExist(err) { + t.Errorf("data file not created %s", dataFile) + } else { + t.Fatal(err) + } + } +} + +func TestPluginNewUnmapper(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-pv", 10, testDriver, testVol) + + // save the data file to re-create client + dir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host) + if err := os.MkdirAll(dir, 0755); err != nil && !os.IsNotExist(err) { + t.Errorf("failed to create dir [%s]: %v", dir, err) + } + + if err := saveVolumeData( + dir, + volDataFileName, + map[string]string{ + volDataKey.specVolID: pv.ObjectMeta.Name, + volDataKey.driverName: testDriver, + volDataKey.volHandle: testVol, + }, + ); err != nil { + t.Fatalf("failed to save volume data: %v", err) + } + + // test unmounter + unmapper, err := plug.NewBlockVolumeUnmapper(pv.ObjectMeta.Name, testPodUID) + csiUnmapper := unmapper.(*csiBlockMapper) + + if err != nil { + t.Fatalf("Failed to make a new Unmounter: %v", err) + } + + if csiUnmapper == nil { + t.Fatal("failed to create CSI Unmounter") + } + + if csiUnmapper.podUID != testPodUID { + t.Error("podUID not set") + } + + if csiUnmapper.specName != pv.ObjectMeta.Name { + t.Error("specName not set") + } + + if csiUnmapper.csiClient == nil { + t.Error("unmapper csiClient is nil") + } + + // test loaded vol data + if csiUnmapper.driverName != testDriver { + t.Error("unmapper driverName not set") + } + if csiUnmapper.volumeID != testVol { + t.Error("unmapper volumeHandle not set") + } +} + +func TestPluginConstructBlockVolumeSpec(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + testCases := []struct { + name string + specVolID string + data map[string]string + shouldFail bool + }{ + { + name: "valid spec name", + specVolID: "test.vol.id", + data: map[string]string{volDataKey.specVolID: "test.vol.id", volDataKey.volHandle: "test-vol0", volDataKey.driverName: "test-driver0"}, + }, + } + + for _, tc := range testCases { + t.Logf("test case: %s", tc.name) + deviceDataDir := getVolumeDeviceDataDir(tc.specVolID, plug.host) + + // create data file in csi plugin dir + if tc.data != nil { + if err := os.MkdirAll(deviceDataDir, 0755); err != nil && !os.IsNotExist(err) { + t.Errorf("failed to create dir [%s]: %v", deviceDataDir, err) + } + if err := saveVolumeData(deviceDataDir, volDataFileName, tc.data); err != nil { + t.Fatal(err) + } + } + + // rebuild spec + spec, err := plug.ConstructBlockVolumeSpec("test-podUID", tc.specVolID, getVolumeDevicePluginDir(tc.specVolID, plug.host)) + if tc.shouldFail { + if err == nil { + t.Fatal("expecting ConstructVolumeSpec to fail, but got nil error") + } + continue + } + + volHandle := spec.PersistentVolume.Spec.CSI.VolumeHandle + if volHandle != tc.data[volDataKey.volHandle] { + t.Errorf("expected volID %s, got volID %s", tc.data[volDataKey.volHandle], volHandle) + } + + if spec.Name() != tc.specVolID { + t.Errorf("Unexpected spec name %s", spec.Name()) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_util.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_util.go index 81a973e44..6a0b67212 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_util.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_util.go @@ -17,10 +17,17 @@ limitations under the License. package csi import ( + "encoding/json" + "fmt" + "os" + "path" + "github.com/golang/glog" api "k8s.io/api/core/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" + kstrings "k8s.io/kubernetes/pkg/util/strings" + "k8s.io/kubernetes/pkg/volume" ) func getCredentialsFromSecret(k8s kubernetes.Interface, secretRef *api.SecretReference) (map[string]string, error) { @@ -36,3 +43,81 @@ func getCredentialsFromSecret(k8s kubernetes.Interface, secretRef *api.SecretRef return credentials, nil } + +// saveVolumeData persists parameter data as json file at the provided location +func saveVolumeData(dir string, fileName string, data map[string]string) error { + dataFilePath := path.Join(dir, fileName) + glog.V(4).Info(log("saving volume data file [%s]", dataFilePath)) + file, err := os.Create(dataFilePath) + if err != nil { + glog.Error(log("failed to save volume data file %s: %v", dataFilePath, err)) + return err + } + defer file.Close() + if err := json.NewEncoder(file).Encode(data); err != nil { + glog.Error(log("failed to save volume data file %s: %v", dataFilePath, err)) + return err + } + glog.V(4).Info(log("volume data file saved successfully [%s]", dataFilePath)) + return nil +} + +// loadVolumeData loads volume info from specified json file/location +func loadVolumeData(dir string, fileName string) (map[string]string, error) { + // remove /mount at the end + dataFileName := path.Join(dir, fileName) + glog.V(4).Info(log("loading volume data file [%s]", dataFileName)) + + file, err := os.Open(dataFileName) + if err != nil { + glog.Error(log("failed to open volume data file [%s]: %v", dataFileName, err)) + return nil, err + } + defer file.Close() + data := map[string]string{} + if err := json.NewDecoder(file).Decode(&data); err != nil { + glog.Error(log("failed to parse volume data file [%s]: %v", dataFileName, err)) + return nil, err + } + + return data, nil +} + +func getCSISourceFromSpec(spec *volume.Spec) (*api.CSIPersistentVolumeSource, error) { + if spec.PersistentVolume != nil && + spec.PersistentVolume.Spec.CSI != nil { + return spec.PersistentVolume.Spec.CSI, nil + } + + return nil, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") +} + +func getReadOnlyFromSpec(spec *volume.Spec) (bool, error) { + if spec.PersistentVolume != nil && + spec.PersistentVolume.Spec.CSI != nil { + return spec.ReadOnly, nil + } + + return false, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") +} + +// log prepends log string with `kubernetes.io/csi` +func log(msg string, parts ...interface{}) string { + return fmt.Sprintf(fmt.Sprintf("%s: %s", csiPluginName, msg), parts...) +} + +// getVolumeDevicePluginDir returns the path where the CSI plugin keeps the +// symlink for a block device associated with a given specVolumeID. +// path: plugins/kubernetes.io/csi/volumeDevices/{specVolumeID}/dev +func getVolumeDevicePluginDir(specVolID string, host volume.VolumeHost) string { + sanitizedSpecVolID := kstrings.EscapeQualifiedNameForDisk(specVolID) + return path.Join(host.GetVolumeDevicePluginDir(csiPluginName), sanitizedSpecVolID, "dev") +} + +// getVolumeDeviceDataDir returns the path where the CSI plugin keeps the +// volume data for a block device associated with a given specVolumeID. +// path: plugins/kubernetes.io/csi/volumeDevices/{specVolumeID}/data +func getVolumeDeviceDataDir(specVolID string, host volume.VolumeHost) string { + sanitizedSpecVolID := kstrings.EscapeQualifiedNameForDisk(specVolID) + return path.Join(host.GetVolumeDevicePluginDir(csiPluginName), sanitizedSpecVolID, "data") +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/fake/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/csi/fake/BUILD index 1f715f0c1..4c3287937 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/fake/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/fake/BUILD @@ -7,7 +7,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//vendor/github.com/container-storage-interface/spec/lib/go/csi/v0:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/fake/fake_client.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/fake/fake_client.go index ce95ff947..b4341e715 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/fake/fake_client.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/fake/fake_client.go @@ -24,7 +24,6 @@ import ( "google.golang.org/grpc" csipb "github.com/container-storage-interface/spec/lib/go/csi/v0" - grpctx "golang.org/x/net/context" ) // IdentityClient is a CSI identity client used for testing @@ -94,7 +93,7 @@ func (f *NodeClient) AddNodeStagedVolume(volID, deviceMountPath string) { } // NodePublishVolume implements CSI NodePublishVolume -func (f *NodeClient) NodePublishVolume(ctx grpctx.Context, req *csipb.NodePublishVolumeRequest, opts ...grpc.CallOption) (*csipb.NodePublishVolumeResponse, error) { +func (f *NodeClient) NodePublishVolume(ctx context.Context, req *csipb.NodePublishVolumeRequest, opts ...grpc.CallOption) (*csipb.NodePublishVolumeResponse, error) { if f.nextErr != nil { return nil, f.nextErr @@ -106,7 +105,7 @@ func (f *NodeClient) NodePublishVolume(ctx grpctx.Context, req *csipb.NodePublis if req.GetTargetPath() == "" { return nil, errors.New("missing target path") } - fsTypes := "ext4|xfs|zfs" + fsTypes := "block|ext4|xfs|zfs" fsType := req.GetVolumeCapability().GetMount().GetFsType() if !strings.Contains(fsTypes, fsType) { return nil, errors.New("invalid fstype") @@ -145,7 +144,7 @@ func (f *NodeClient) NodeStageVolume(ctx context.Context, req *csipb.NodeStageVo } fsType := "" - fsTypes := "ext4|xfs|zfs" + fsTypes := "block|ext4|xfs|zfs" mounted := req.GetVolumeCapability().GetMount() if mounted != nil { fsType = mounted.GetFsType() diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/labelmanager/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/csi/labelmanager/BUILD new file mode 100644 index 000000000..1fed83356 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/labelmanager/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["labelmanager.go"], + importpath = "k8s.io/kubernetes/pkg/volume/csi/labelmanager", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/util/retry:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/labelmanager/labelmanager.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/labelmanager/labelmanager.go new file mode 100644 index 000000000..162d7d3dc --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/labelmanager/labelmanager.go @@ -0,0 +1,251 @@ +/* +Copyright 2018 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 labelmanager includes internal functions used to add/delete labels to +// kubernetes nodes for corresponding CSI drivers +package labelmanager // import "k8s.io/kubernetes/pkg/volume/csi/labelmanager" + +import ( + "encoding/json" + "fmt" + + "github.com/golang/glog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/util/retry" +) + +const ( + // Name of node annotation that contains JSON map of driver names to node + // names + annotationKey = "csi.volume.kubernetes.io/nodeid" + csiPluginName = "kubernetes.io/csi" +) + +// labelManagementStruct is struct of channels used for communication between the driver registration +// code and the go routine responsible for managing the node's labels +type labelManagerStruct struct { + nodeName types.NodeName + k8s kubernetes.Interface +} + +// Interface implements an interface for managing labels of a node +type Interface interface { + AddLabels(driverName string) error +} + +// NewLabelManager initializes labelManagerStruct and returns available interfaces +func NewLabelManager(nodeName types.NodeName, kubeClient kubernetes.Interface) Interface { + return labelManagerStruct{ + nodeName: nodeName, + k8s: kubeClient, + } +} + +// nodeLabelManager waits for labeling requests initiated by the driver's registration +// process. +func (lm labelManagerStruct) AddLabels(driverName string) error { + err := verifyAndAddNodeId(string(lm.nodeName), lm.k8s.CoreV1().Nodes(), driverName, string(lm.nodeName)) + if err != nil { + return fmt.Errorf("failed to update node %s's annotation with error: %+v", lm.nodeName, err) + } + return nil +} + +// Clones the given map and returns a new map with the given key and value added. +// Returns the given map, if annotationKey is empty. +func cloneAndAddAnnotation( + annotations map[string]string, + annotationKey, + annotationValue string) map[string]string { + if annotationKey == "" { + // Don't need to add an annotation. + return annotations + } + // Clone. + newAnnotations := map[string]string{} + for key, value := range annotations { + newAnnotations[key] = value + } + newAnnotations[annotationKey] = annotationValue + return newAnnotations +} + +func verifyAndAddNodeId( + k8sNodeName string, + k8sNodesClient corev1.NodeInterface, + csiDriverName string, + csiDriverNodeId string) error { + // Add or update annotation on Node object + retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { + // Retrieve the latest version of Node before attempting update, so that + // existing changes are not overwritten. RetryOnConflict uses + // exponential backoff to avoid exhausting the apiserver. + result, getErr := k8sNodesClient.Get(k8sNodeName, metav1.GetOptions{}) + if getErr != nil { + glog.Errorf("Failed to get latest version of Node: %v", getErr) + return getErr // do not wrap error + } + + var previousAnnotationValue string + if result.ObjectMeta.Annotations != nil { + previousAnnotationValue = + result.ObjectMeta.Annotations[annotationKey] + glog.V(3).Infof( + "previousAnnotationValue=%q", previousAnnotationValue) + } + + existingDriverMap := map[string]string{} + if previousAnnotationValue != "" { + // Parse previousAnnotationValue as JSON + if err := json.Unmarshal([]byte(previousAnnotationValue), &existingDriverMap); err != nil { + return fmt.Errorf( + "failed to parse node's %q annotation value (%q) err=%v", + annotationKey, + previousAnnotationValue, + err) + } + } + + if val, ok := existingDriverMap[csiDriverName]; ok { + if val == csiDriverNodeId { + // Value already exists in node annotation, nothing more to do + glog.V(1).Infof( + "The key value {%q: %q} alredy eixst in node %q annotation, no need to update: %v", + csiDriverName, + csiDriverNodeId, + annotationKey, + previousAnnotationValue) + return nil + } + } + + // Add/update annotation value + existingDriverMap[csiDriverName] = csiDriverNodeId + jsonObj, err := json.Marshal(existingDriverMap) + if err != nil { + return fmt.Errorf( + "failed while trying to add key value {%q: %q} to node %q annotation. Existing value: %v", + csiDriverName, + csiDriverNodeId, + annotationKey, + previousAnnotationValue) + } + + result.ObjectMeta.Annotations = cloneAndAddAnnotation( + result.ObjectMeta.Annotations, + annotationKey, + string(jsonObj)) + _, updateErr := k8sNodesClient.Update(result) + if updateErr == nil { + fmt.Printf( + "Updated node %q successfully for CSI driver %q and CSI node name %q", + k8sNodeName, + csiDriverName, + csiDriverNodeId) + } + return updateErr // do not wrap error + }) + if retryErr != nil { + return fmt.Errorf("node update failed: %v", retryErr) + } + return nil +} + +// Fetches Kubernetes node API object corresponding to k8sNodeName. +// If the csiDriverName is present in the node annotation, it is removed. +func verifyAndDeleteNodeId( + k8sNodeName string, + k8sNodesClient corev1.NodeInterface, + csiDriverName string) error { + retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { + // Retrieve the latest version of Node before attempting update, so that + // existing changes are not overwritten. RetryOnConflict uses + // exponential backoff to avoid exhausting the apiserver. + result, getErr := k8sNodesClient.Get(k8sNodeName, metav1.GetOptions{}) + if getErr != nil { + glog.Errorf("failed to get latest version of Node: %v", getErr) + return getErr // do not wrap error + } + + var previousAnnotationValue string + if result.ObjectMeta.Annotations != nil { + previousAnnotationValue = + result.ObjectMeta.Annotations[annotationKey] + glog.V(3).Infof( + "previousAnnotationValue=%q", previousAnnotationValue) + } + + existingDriverMap := map[string]string{} + if previousAnnotationValue == "" { + // Value already exists in node annotation, nothing more to do + glog.V(1).Infof( + "The key %q does not exist in node %q annotation, no need to cleanup.", + csiDriverName, + annotationKey) + return nil + } + + // Parse previousAnnotationValue as JSON + if err := json.Unmarshal([]byte(previousAnnotationValue), &existingDriverMap); err != nil { + return fmt.Errorf( + "failed to parse node's %q annotation value (%q) err=%v", + annotationKey, + previousAnnotationValue, + err) + } + + if _, ok := existingDriverMap[csiDriverName]; !ok { + // Value already exists in node annotation, nothing more to do + glog.V(1).Infof( + "The key %q does not eixst in node %q annotation, no need to cleanup: %v", + csiDriverName, + annotationKey, + previousAnnotationValue) + return nil + } + + // Add/update annotation value + delete(existingDriverMap, csiDriverName) + jsonObj, err := json.Marshal(existingDriverMap) + if err != nil { + return fmt.Errorf( + "failed while trying to remove key %q from node %q annotation. Existing data: %v", + csiDriverName, + annotationKey, + previousAnnotationValue) + } + + result.ObjectMeta.Annotations = cloneAndAddAnnotation( + result.ObjectMeta.Annotations, + annotationKey, + string(jsonObj)) + _, updateErr := k8sNodesClient.Update(result) + if updateErr == nil { + fmt.Printf( + "Updated node %q annotation to remove CSI driver %q.", + k8sNodeName, + csiDriverName) + } + return updateErr // do not wrap error + }) + if retryErr != nil { + return fmt.Errorf("node update failed: %v", retryErr) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/downwardapi/downwardapi.go b/vendor/k8s.io/kubernetes/pkg/volume/downwardapi/downwardapi.go index dc69a0916..88f7b68f7 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/downwardapi/downwardapi.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/downwardapi/downwardapi.go @@ -19,8 +19,7 @@ package downwardapi import ( "fmt" "path" - "sort" - "strings" + "path/filepath" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" @@ -179,17 +178,19 @@ func (b *downwardAPIVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Couldn't setup downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) return err } - if err := wrapped.SetUpAt(dir, fsGroup); err != nil { - glog.Errorf("Unable to setup downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) + + data, err := CollectData(b.source.Items, b.pod, b.plugin.host, b.source.DefaultMode) + if err != nil { + glog.Errorf("Error preparing data for downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) return err } - if err := volumeutil.MakeNestedMountpoints(b.volName, dir, *b.pod); err != nil { + + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { + glog.Errorf("Unable to setup downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) return err } - data, err := CollectData(b.source.Items, b.pod, b.plugin.host, b.source.DefaultMode) - if err != nil { - glog.Errorf("Error preparing data for downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) + if err := volumeutil.MakeNestedMountpoints(b.volName, dir, *b.pod); err != nil { return err } @@ -229,7 +230,7 @@ func CollectData(items []v1.DownwardAPIVolumeFile, pod *v1.Pod, host volume.Volu data := make(map[string]volumeutil.FileProjection) for _, fileInfo := range items { var fileProjection volumeutil.FileProjection - fPath := path.Clean(fileInfo.Path) + fPath := filepath.Clean(fileInfo.Path) if fileInfo.Mode != nil { fileProjection.Mode = *fileInfo.Mode } else { @@ -241,7 +242,7 @@ func CollectData(items []v1.DownwardAPIVolumeFile, pod *v1.Pod, host volume.Volu glog.Errorf("Unable to extract field %s: %s", fileInfo.FieldRef.FieldPath, err.Error()) errlist = append(errlist, err) } else { - fileProjection.Data = []byte(sortLines(values)) + fileProjection.Data = []byte(values) } } else if fileInfo.ResourceFieldRef != nil { containerName := fileInfo.ResourceFieldRef.ContainerName @@ -252,7 +253,7 @@ func CollectData(items []v1.DownwardAPIVolumeFile, pod *v1.Pod, host volume.Volu glog.Errorf("Unable to extract field %s: %s", fileInfo.ResourceFieldRef.Resource, err.Error()) errlist = append(errlist, err) } else { - fileProjection.Data = []byte(sortLines(values)) + fileProjection.Data = []byte(values) } } @@ -261,14 +262,6 @@ func CollectData(items []v1.DownwardAPIVolumeFile, pod *v1.Pod, host volume.Volu return data, utilerrors.NewAggregate(errlist) } -// sortLines sorts the strings generated from map based data -// (annotations and labels) -func sortLines(values string) string { - splitted := strings.Split(values, "\n") - sort.Strings(splitted) - return strings.Join(splitted, "\n") -} - func (d *downwardAPIVolume) GetPath() string { return d.plugin.host.GetPodVolumeDir(d.podUID, utilstrings.EscapeQualifiedNameForDisk(downwardAPIPluginName), d.volName) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/downwardapi/downwardapi_test.go b/vendor/k8s.io/kubernetes/pkg/volume/downwardapi/downwardapi_test.go index 89c73cb98..7b22eb9aa 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/downwardapi/downwardapi_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/downwardapi/downwardapi_test.go @@ -82,8 +82,9 @@ func TestDownwardAPI(t *testing.T) { "key3": "value3", } annotations := map[string]string{ - "a1": "value1", - "a2": "value2", + "a1": "value1", + "a2": "value2", + "multiline": "c\nb\na", } testCases := []struct { name string @@ -318,8 +319,8 @@ func doVerifyLinesInFile(t *testing.T, volumePath, filename string, expected str t.Errorf(err.Error()) return } - actualStr := sortLines(string(data)) - expectedStr := sortLines(expected) + actualStr := string(data) + expectedStr := expected if actualStr != expectedStr { t.Errorf("Found `%s`, expected `%s`", actualStr, expectedStr) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/fc/fc.go b/vendor/k8s.io/kubernetes/pkg/volume/fc/fc.go index fb7a57015..4160fe055 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/fc/fc.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/fc/fc.go @@ -443,6 +443,10 @@ func (b *fcDiskMapper) SetUpDevice() (string, error) { return "", nil } +func (b *fcDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + type fcDiskUnmapper struct { *fcDisk deviceUtil util.DeviceUtil diff --git a/vendor/k8s.io/kubernetes/pkg/volume/fc/fc_test.go b/vendor/k8s.io/kubernetes/pkg/volume/fc/fc_test.go index f8ee2650b..ecc4155c7 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/fc/fc_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/fc/fc_test.go @@ -19,6 +19,7 @@ package fc import ( "fmt" "os" + "runtime" "strconv" "strings" "testing" @@ -424,6 +425,9 @@ func Test_getWwnsLunWwidsError(t *testing.T) { } func Test_ConstructVolumeSpec(t *testing.T) { + if runtime.GOOS == "darwin" { + t.Skipf("Test_ConstructVolumeSpec is not supported on GOOS=%s", runtime.GOOS) + } fm := &mount.FakeMounter{ MountPoints: []mount.MountPoint{ {Device: "/dev/sdb", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod1"}, @@ -437,7 +441,10 @@ func Test_ConstructVolumeSpec(t *testing.T) { "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod2", } for _, path := range mountPaths { - refs, _ := mount.GetMountRefs(fm, path) + refs, err := mount.GetMountRefs(fm, path) + if err != nil { + t.Errorf("couldn't get mountrefs. err: %v", err) + } var globalPDPath string for _, ref := range refs { if strings.Contains(ref, "kubernetes.io/fc") { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/attacher-defaults.go b/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/attacher-defaults.go index e578443c4..368ac1be0 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/attacher-defaults.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/attacher-defaults.go @@ -30,13 +30,13 @@ type attacherDefaults flexVolumeAttacher // Attach is part of the volume.Attacher interface func (a *attacherDefaults) Attach(spec *volume.Spec, hostName types.NodeName) (string, error) { - glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default Attach for volume ", spec.Name, ", host ", hostName) + glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default Attach for volume ", spec.Name(), ", host ", hostName) return "", nil } // WaitForAttach is part of the volume.Attacher interface func (a *attacherDefaults) WaitForAttach(spec *volume.Spec, devicePath string, timeout time.Duration) (string, error) { - glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default WaitForAttach for volume ", spec.Name, ", device ", devicePath) + glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default WaitForAttach for volume ", spec.Name(), ", device ", devicePath) return devicePath, nil } @@ -47,7 +47,7 @@ func (a *attacherDefaults) GetDeviceMountPath(spec *volume.Spec, mountsDir strin // MountDevice is part of the volume.Attacher interface func (a *attacherDefaults) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string, mounter mount.Interface) error { - glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default MountDevice for volume ", spec.Name, ", device ", devicePath, ", deviceMountPath ", deviceMountPath) + glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default MountDevice for volume ", spec.Name(), ", device ", devicePath, ", deviceMountPath ", deviceMountPath) volSourceFSType, err := getFSType(spec) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/flexvolume_test.go b/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/flexvolume_test.go index c90ad4932..930c46654 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/flexvolume_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/flexvolume_test.go @@ -30,7 +30,7 @@ import ( volumetest "k8s.io/kubernetes/pkg/volume/testing" ) -const execScriptTempl1 = `#!/bin/bash +const execScriptTempl1 = `#!/usr/bin/env bash if [ "$1" == "init" -a $# -eq 1 ]; then echo -n '{ "status": "Success" @@ -73,7 +73,7 @@ exit 1 echo -n $@ &> {{.OutputFile}} ` -const execScriptTempl2 = `#!/bin/bash +const execScriptTempl2 = `#!/usr/bin/env bash if [ "$1" == "init" -a $# -eq 1 ]; then echo -n '{ "status": "Success" diff --git a/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/probe.go b/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/probe.go index 269ff0839..badf14922 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/probe.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/probe.go @@ -25,31 +25,24 @@ import ( "fmt" "path/filepath" "sync" - "time" "github.com/fsnotify/fsnotify" "k8s.io/apimachinery/pkg/util/errors" utilfs "k8s.io/kubernetes/pkg/util/filesystem" + utilstrings "k8s.io/kubernetes/pkg/util/strings" + "strings" ) type flexVolumeProber struct { - mutex sync.Mutex - pluginDir string // Flexvolume driver directory - watcher utilfs.FSWatcher - probeNeeded bool // Must only read and write this through testAndSetProbeNeeded. - lastUpdated time.Time // Last time probeNeeded was updated. - watchEventCount int - factory PluginFactory - fs utilfs.Filesystem + mutex sync.Mutex + pluginDir string // Flexvolume driver directory + watcher utilfs.FSWatcher + factory PluginFactory + fs utilfs.Filesystem + probeAllNeeded bool + eventsMap map[string]volume.ProbeOperation // the key is the driver directory path, the value is the coresponding operation } -const ( - // TODO (cxing) Tune these params based on test results. - // watchEventLimit is the max allowable number of processed watches within watchEventInterval. - watchEventInterval = 5 * time.Second - watchEventLimit = 20 -) - func GetDynamicPluginProber(pluginDir string) volume.DynamicPluginProber { return &flexVolumeProber{ pluginDir: pluginDir, @@ -60,8 +53,8 @@ func GetDynamicPluginProber(pluginDir string) volume.DynamicPluginProber { } func (prober *flexVolumeProber) Init() error { - prober.testAndSetProbeNeeded(true) - prober.lastUpdated = time.Now() + prober.testAndSetProbeAllNeeded(true) + prober.eventsMap = map[string]volume.ProbeOperation{} if err := prober.createPluginDir(); err != nil { return err @@ -73,26 +66,44 @@ func (prober *flexVolumeProber) Init() error { return nil } -// Probes for Flexvolume drivers. -// If a filesystem update has occurred since the last probe, updated = true -// and the list of probed plugins is returned. -// Otherwise, update = false and probedPlugins = nil. -// -// If an error occurs, updated and plugins are set arbitrarily. -func (prober *flexVolumeProber) Probe() (updated bool, plugins []volume.VolumePlugin, err error) { - probeNeeded := prober.testAndSetProbeNeeded(false) +// If probeAllNeeded is true, probe all pluginDir +// else probe events in eventsMap +func (prober *flexVolumeProber) Probe() (events []volume.ProbeEvent, err error) { + if prober.probeAllNeeded { + prober.testAndSetProbeAllNeeded(false) + return prober.probeAll() + } + + return prober.probeMap() +} + +func (prober *flexVolumeProber) probeMap() (events []volume.ProbeEvent, err error) { + // TODO use a concurrent map to avoid Locking the entire map + prober.mutex.Lock() + defer prober.mutex.Unlock() + probeEvents := []volume.ProbeEvent{} + allErrs := []error{} + for driverDirPathAbs, op := range prober.eventsMap { + driverDirName := filepath.Base(driverDirPathAbs) // e.g. driverDirName = vendor~cifs + probeEvent, pluginErr := prober.newProbeEvent(driverDirName, op) + if pluginErr != nil { + allErrs = append(allErrs, pluginErr) + continue + } + probeEvents = append(probeEvents, probeEvent) - if !probeNeeded { - return false, nil, nil + delete(prober.eventsMap, driverDirPathAbs) } + return probeEvents, errors.NewAggregate(allErrs) +} +func (prober *flexVolumeProber) probeAll() (events []volume.ProbeEvent, err error) { + probeEvents := []volume.ProbeEvent{} + allErrs := []error{} files, err := prober.fs.ReadDir(prober.pluginDir) if err != nil { - return false, nil, fmt.Errorf("Error reading the Flexvolume directory: %s", err) + return nil, fmt.Errorf("Error reading the Flexvolume directory: %s", err) } - - plugins = []volume.VolumePlugin{} - allErrs := []error{} for _, f := range files { // only directories with names that do not begin with '.' are counted as plugins // and pluginDir/dirname/dirname should be an executable @@ -100,20 +111,39 @@ func (prober *flexVolumeProber) Probe() (updated bool, plugins []volume.VolumePl // e.g. dirname = vendor~cifs // then, executable will be pluginDir/dirname/cifs if f.IsDir() && filepath.Base(f.Name())[0] != '.' { - plugin, pluginErr := prober.factory.NewFlexVolumePlugin(prober.pluginDir, f.Name()) + probeEvent, pluginErr := prober.newProbeEvent(f.Name(), volume.ProbeAddOrUpdate) if pluginErr != nil { - pluginErr = fmt.Errorf( - "Error creating Flexvolume plugin from directory %s, skipping. Error: %s", - f.Name(), pluginErr) allErrs = append(allErrs, pluginErr) continue } - - plugins = append(plugins, plugin) + probeEvents = append(probeEvents, probeEvent) } } + return probeEvents, errors.NewAggregate(allErrs) +} - return true, plugins, errors.NewAggregate(allErrs) +func (prober *flexVolumeProber) newProbeEvent(driverDirName string, op volume.ProbeOperation) (volume.ProbeEvent, error) { + probeEvent := volume.ProbeEvent{ + Op: op, + } + if op == volume.ProbeAddOrUpdate { + plugin, pluginErr := prober.factory.NewFlexVolumePlugin(prober.pluginDir, driverDirName) + if pluginErr != nil { + pluginErr = fmt.Errorf( + "Error creating Flexvolume plugin from directory %s, skipping. Error: %s", + driverDirName, pluginErr) + return probeEvent, pluginErr + } + probeEvent.Plugin = plugin + probeEvent.PluginName = plugin.GetPluginName() + } else if op == volume.ProbeRemove { + driverName := utilstrings.UnescapePluginName(driverDirName) + probeEvent.PluginName = flexVolumePluginNamePrefix + driverName + + } else { + return probeEvent, fmt.Errorf("Unknown Operation on directory: %s. ", driverDirName) + } + return probeEvent, nil } func (prober *flexVolumeProber) handleWatchEvent(event fsnotify.Event) error { @@ -127,46 +157,67 @@ func (prober *flexVolumeProber) handleWatchEvent(event fsnotify.Event) error { if err != nil { return err } - + parentPathAbs := filepath.Dir(eventPathAbs) pluginDirAbs, err := filepath.Abs(prober.pluginDir) if err != nil { return err } - // If the Flexvolume plugin directory is removed, need to recreate it - // in order to keep it under watch. - if eventOpIs(event, fsnotify.Remove) && eventPathAbs == pluginDirAbs { - if err := prober.createPluginDir(); err != nil { - return err - } - if err := prober.addWatchRecursive(pluginDirAbs); err != nil { - return err + // event of pluginDirAbs + if eventPathAbs == pluginDirAbs { + // If the Flexvolume plugin directory is removed, need to recreate it + // in order to keep it under watch. + if eventOpIs(event, fsnotify.Remove) { + if err := prober.createPluginDir(); err != nil { + return err + } + if err := prober.addWatchRecursive(pluginDirAbs); err != nil { + return err + } } - } else if eventOpIs(event, fsnotify.Create) { + return nil + } + + // watch newly added subdirectories inside a driver directory + if eventOpIs(event, fsnotify.Create) { if err := prober.addWatchRecursive(eventPathAbs); err != nil { return err } } - prober.updateProbeNeeded() + eventRelPathToPluginDir, err := filepath.Rel(pluginDirAbs, eventPathAbs) + if err != nil { + return err + } + + // event inside specific driver dir + if len(eventRelPathToPluginDir) > 0 { + driverDirName := strings.Split(eventRelPathToPluginDir, string(os.PathSeparator))[0] + driverDirAbs := filepath.Join(pluginDirAbs, driverDirName) + // executable is removed, will trigger ProbeRemove event + if eventOpIs(event, fsnotify.Remove) && (eventRelPathToPluginDir == getExecutablePathRel(driverDirName) || parentPathAbs == pluginDirAbs) { + prober.updateEventsMap(driverDirAbs, volume.ProbeRemove) + } else { + prober.updateEventsMap(driverDirAbs, volume.ProbeAddOrUpdate) + } + } return nil } -func (prober *flexVolumeProber) updateProbeNeeded() { - // Within 'watchEventInterval' seconds, a max of 'watchEventLimit' watch events is processed. - // The watch event will not be registered if the limit is reached. - // This prevents increased disk usage from Probe() being triggered too frequently (either - // accidentally or maliciously). - if time.Since(prober.lastUpdated) > watchEventInterval { - // Update, then reset the timer and watch count. - prober.testAndSetProbeNeeded(true) - prober.lastUpdated = time.Now() - prober.watchEventCount = 1 - } else if prober.watchEventCount < watchEventLimit { - prober.testAndSetProbeNeeded(true) - prober.watchEventCount++ +// getExecutableName returns the executableName of a flex plugin +func getExecutablePathRel(driverDirName string) string { + parts := strings.Split(driverDirName, "~") + return filepath.Join(driverDirName, parts[len(parts)-1]) +} + +func (prober *flexVolumeProber) updateEventsMap(eventDirAbs string, op volume.ProbeOperation) { + prober.mutex.Lock() + defer prober.mutex.Unlock() + if prober.probeAllNeeded { + return } + prober.eventsMap[eventDirAbs] = op } // Recursively adds to watch all directories inside and including the file specified by the given filename. @@ -222,10 +273,10 @@ func (prober *flexVolumeProber) createPluginDir() error { return nil } -func (prober *flexVolumeProber) testAndSetProbeNeeded(newval bool) (oldval bool) { +func (prober *flexVolumeProber) testAndSetProbeAllNeeded(newval bool) (oldval bool) { prober.mutex.Lock() defer prober.mutex.Unlock() - oldval, prober.probeNeeded = prober.probeNeeded, newval + oldval, prober.probeAllNeeded = prober.probeAllNeeded, newval return } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/probe_test.go b/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/probe_test.go index 789aa18b7..b52ec5aa7 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/probe_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/flexvolume/probe_test.go @@ -38,13 +38,13 @@ func TestProberExistingDriverBeforeInit(t *testing.T) { driverPath, _, watcher, prober := initTestEnvironment(t) // Act - updated, plugins, err := prober.Probe() + events, err := prober.Probe() // Assert // Probe occurs, 1 plugin should be returned, and 2 watches (pluginDir and all its // current subdirectories) registered. - assert.True(t, updated) - assert.Equal(t, 1, len(plugins)) + assert.Equal(t, 1, len(events)) + assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op) assert.Equal(t, pluginDir, watcher.watches[0]) assert.Equal(t, driverPath, watcher.watches[1]) assert.NoError(t, err) @@ -52,67 +52,120 @@ func TestProberExistingDriverBeforeInit(t *testing.T) { // Should no longer probe. // Act - updated, plugins, err = prober.Probe() + events, err = prober.Probe() // Assert - assert.False(t, updated) - assert.Equal(t, 0, len(plugins)) + assert.Equal(t, 0, len(events)) assert.NoError(t, err) } // Probes newly added drivers after prober is running. -func TestProberAddDriver(t *testing.T) { +func TestProberAddRemoveDriver(t *testing.T) { // Arrange _, fs, watcher, prober := initTestEnvironment(t) prober.Probe() - updated, _, _ := prober.Probe() - assert.False(t, updated) + events, err := prober.Probe() + assert.Equal(t, 0, len(events)) - // Call probe after a file is added. Should return true. + // Call probe after a file is added. Should return 1 event. - // Arrange + // add driver const driverName2 = "fake-driver2" driverPath := path.Join(pluginDir, driverName2) + executablePath := path.Join(driverPath, driverName2) installDriver(driverName2, fs) watcher.TriggerEvent(fsnotify.Create, driverPath) - watcher.TriggerEvent(fsnotify.Create, path.Join(driverPath, driverName2)) + watcher.TriggerEvent(fsnotify.Create, executablePath) // Act - updated, plugins, err := prober.Probe() + events, err = prober.Probe() // Assert - assert.True(t, updated) - assert.Equal(t, 2, len(plugins)) // 1 existing, 1 newly added + assert.Equal(t, 1, len(events)) + assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op) // 1 newly added assert.Equal(t, driverPath, watcher.watches[len(watcher.watches)-1]) // Checks most recent watch assert.NoError(t, err) - // Call probe again, should return false. + // Call probe again, should return 0 event. // Act - updated, _, err = prober.Probe() + events, err = prober.Probe() // Assert - assert.False(t, updated) + assert.Equal(t, 0, len(events)) assert.NoError(t, err) - // Call probe after a non-driver file is added in a subdirectory. Should return true. - - // Arrange + // Call probe after a non-driver file is added in a subdirectory. should return 1 event. fp := path.Join(driverPath, "dummyfile") fs.Create(fp) watcher.TriggerEvent(fsnotify.Create, fp) // Act - updated, plugins, err = prober.Probe() + events, err = prober.Probe() + + // Assert + assert.Equal(t, 1, len(events)) + assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op) + assert.NoError(t, err) + + // Call probe again, should return 0 event. + // Act + events, err = prober.Probe() + // Assert + assert.Equal(t, 0, len(events)) + assert.NoError(t, err) + + // Call probe after a subdirectory is added in a driver directory. should return 1 event. + subdirPath := path.Join(driverPath, "subdir") + fs.Create(subdirPath) + watcher.TriggerEvent(fsnotify.Create, subdirPath) + + // Act + events, err = prober.Probe() // Assert - assert.True(t, updated) - assert.Equal(t, 2, len(plugins)) // Number of plugins should not change. + assert.Equal(t, 1, len(events)) + assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op) assert.NoError(t, err) - // Call probe again, should return false. + // Call probe again, should return 0 event. // Act - updated, _, err = prober.Probe() + events, err = prober.Probe() // Assert - assert.False(t, updated) + assert.Equal(t, 0, len(events)) + assert.NoError(t, err) + + // Call probe after a subdirectory is removed in a driver directory. should return 1 event. + fs.Remove(subdirPath) + watcher.TriggerEvent(fsnotify.Remove, subdirPath) + + // Act + events, err = prober.Probe() + + // Assert + assert.Equal(t, 1, len(events)) + assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op) + assert.NoError(t, err) + + // Call probe again, should return 0 event. + // Act + events, err = prober.Probe() + // Assert + assert.Equal(t, 0, len(events)) + assert.NoError(t, err) + + // Call probe after a driver executable and driver directory is remove. should return 1 event. + fs.Remove(executablePath) + fs.Remove(driverPath) + watcher.TriggerEvent(fsnotify.Remove, executablePath) + watcher.TriggerEvent(fsnotify.Remove, driverPath) + // Act and Assert: 1 ProbeRemove event + events, err = prober.Probe() + assert.Equal(t, 1, len(events)) + assert.Equal(t, volume.ProbeRemove, events[0].Op) + assert.NoError(t, err) + + // Act and Assert: 0 event + events, err = prober.Probe() + assert.Equal(t, 0, len(events)) assert.NoError(t, err) } @@ -130,11 +183,10 @@ func TestEmptyPluginDir(t *testing.T) { prober.Init() // Act - updated, plugins, err := prober.Probe() + events, err := prober.Probe() // Assert - assert.True(t, updated) - assert.Equal(t, 0, len(plugins)) + assert.Equal(t, 0, len(events)) assert.NoError(t, err) } @@ -154,7 +206,37 @@ func TestRemovePluginDir(t *testing.T) { assert.Equal(t, pluginDir, watcher.watches[len(watcher.watches)-1]) } -// Issue multiple events and probe multiple times. Should give true, false, false... +// Issue an event to remove plugindir. New directory should still be watched. +func TestNestedDriverDir(t *testing.T) { + // Arrange + _, fs, watcher, _ := initTestEnvironment(t) + // Assert + assert.Equal(t, 2, len(watcher.watches)) // 2 from initial setup + + // test add testDriverName + testDriverName := "testDriverName" + testDriverPath := path.Join(pluginDir, testDriverName) + fs.MkdirAll(testDriverPath, 0666) + watcher.TriggerEvent(fsnotify.Create, testDriverPath) + // Assert + assert.Equal(t, 3, len(watcher.watches)) // 2 from initial setup, 1 from new watch. + assert.Equal(t, testDriverPath, watcher.watches[len(watcher.watches)-1]) + + // test add nested subdir inside testDriverName + basePath := testDriverPath + for i := 0; i < 10; i++ { + subdirName := "subdirName" + subdirPath := path.Join(basePath, subdirName) + fs.MkdirAll(subdirPath, 0666) + watcher.TriggerEvent(fsnotify.Create, subdirPath) + // Assert + assert.Equal(t, 4+i, len(watcher.watches)) // 3 + newly added + assert.Equal(t, subdirPath, watcher.watches[len(watcher.watches)-1]) + basePath = subdirPath + } +} + +// Issue multiple events and probe multiple times. func TestProberMultipleEvents(t *testing.T) { const iterations = 5 @@ -169,49 +251,20 @@ func TestProberMultipleEvents(t *testing.T) { } // Act - updated, _, err := prober.Probe() + events, err := prober.Probe() // Assert - assert.True(t, updated) + assert.Equal(t, 2, len(events)) + assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op) + assert.Equal(t, volume.ProbeAddOrUpdate, events[1].Op) assert.NoError(t, err) for i := 0; i < iterations-1; i++ { - updated, _, err = prober.Probe() - assert.False(t, updated) + events, err = prober.Probe() + assert.Equal(t, 0, len(events)) assert.NoError(t, err) } } -// When many events are triggered quickly in succession, events should stop triggering a probe update -// after a certain limit. -func TestProberRateLimit(t *testing.T) { - // Arrange - driverPath, _, watcher, prober := initTestEnvironment(t) - for i := 0; i < watchEventLimit; i++ { - watcher.TriggerEvent(fsnotify.Write, path.Join(driverPath, driverName)) - } - - // Act - updated, plugins, err := prober.Probe() - - // Assert - // The probe results should not be different from what it would be if none of the events - // are triggered. - assert.True(t, updated) - assert.Equal(t, 1, len(plugins)) - assert.NoError(t, err) - - // Arrange - watcher.TriggerEvent(fsnotify.Write, path.Join(driverPath, driverName)) - - // Act - updated, _, err = prober.Probe() - - // Assert - // The last event is outside the event limit. Should not trigger a probe. - assert.False(t, updated) - assert.NoError(t, err) -} - func TestProberError(t *testing.T) { fs := utilfs.NewFakeFs() watcher := NewFakeWatcher() @@ -224,7 +277,7 @@ func TestProberError(t *testing.T) { installDriver(driverName, fs) prober.Init() - _, _, err := prober.Probe() + _, err := prober.Probe() assert.Error(t, err) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/flocker/flocker_volume.go b/vendor/k8s.io/kubernetes/pkg/volume/flocker/flocker_volume.go index d7f245d15..e25e2d2fd 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/flocker/flocker_volume.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/flocker/flocker_volume.go @@ -54,7 +54,7 @@ type flockerVolumeProvisioner struct { var _ volume.Provisioner = &flockerVolumeProvisioner{} -func (c *flockerVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *flockerVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } @@ -67,6 +67,10 @@ func (c *flockerVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { return nil, fmt.Errorf("Provisioning failed: Specified unsupported selector") } + if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName()) + } + datasetUUID, sizeGB, labels, err := c.manager.CreateVolume(c) if err != nil { return nil, err diff --git a/vendor/k8s.io/kubernetes/pkg/volume/flocker/flocker_volume_test.go b/vendor/k8s.io/kubernetes/pkg/volume/flocker/flocker_volume_test.go index db24c348b..7a46232d4 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/flocker/flocker_volume_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/flocker/flocker_volume_test.go @@ -57,7 +57,7 @@ func TestProvision(t *testing.T) { dir, provisioner := newTestableProvisioner(assert, options) defer os.RemoveAll(dir) - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) assert.NoError(err, "Provision() failed: ", err) cap := persistentSpec.Spec.Capacity[v1.ResourceStorage] @@ -85,7 +85,7 @@ func TestProvision(t *testing.T) { dir, provisioner = newTestableProvisioner(assert, options) defer os.RemoveAll(dir) - persistentSpec, err = provisioner.Provision() + persistentSpec, err = provisioner.Provision(nil, nil) assert.Error(err, "Provision() did not fail with Parameters specified") // selectors are not supported @@ -97,6 +97,6 @@ func TestProvision(t *testing.T) { dir, provisioner = newTestableProvisioner(assert, options) defer os.RemoveAll(dir) - persistentSpec, err = provisioner.Provision() + persistentSpec, err = provisioner.Provision(nil, nil) assert.Error(err, "Provision() did not fail with Selector specified") } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/BUILD index 91770ff30..56ad3673b 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/BUILD @@ -21,6 +21,7 @@ go_library( "//pkg/cloudprovider/providers/gce:go_default_library", "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", + "//pkg/util/file:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/strings:go_default_library", "//pkg/volume:go_default_library", @@ -43,6 +44,7 @@ go_test( "attacher_test.go", "gce_pd_block_test.go", "gce_pd_test.go", + "gce_util_test.go", ], embed = [":go_default_library"], deps = [ diff --git a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/attacher.go b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/attacher.go index 21d8545b0..404923c71 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/attacher.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/attacher.go @@ -158,7 +158,7 @@ func (attacher *gcePersistentDiskAttacher) WaitForAttach(spec *volume.Spec, devi select { case <-ticker.C: glog.V(5).Infof("Checking GCE PD %q is attached.", pdName) - path, err := verifyDevicePath(devicePaths, sdBeforeSet) + path, err := verifyDevicePath(devicePaths, sdBeforeSet, pdName) if err != nil { // Log error, if any, and continue checking periodically. See issue #11321 glog.Errorf("Error verifying GCE PD (%q) is attached: %v", pdName, err) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd.go b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd.go index 8c78c6754..bcb20328a 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd.go @@ -17,16 +17,21 @@ limitations under the License. package gce_pd import ( + "context" "fmt" "os" "path" "strconv" + "strings" "github.com/golang/glog" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" + gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/mount" kstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" @@ -47,11 +52,24 @@ var _ volume.PersistentVolumePlugin = &gcePersistentDiskPlugin{} var _ volume.DeletableVolumePlugin = &gcePersistentDiskPlugin{} var _ volume.ProvisionableVolumePlugin = &gcePersistentDiskPlugin{} var _ volume.ExpandableVolumePlugin = &gcePersistentDiskPlugin{} +var _ volume.VolumePluginWithAttachLimits = &gcePersistentDiskPlugin{} const ( gcePersistentDiskPluginName = "kubernetes.io/gce-pd" ) +// The constants are used to map from the machine type (number of CPUs) to the limit of +// persistent disks that can be attached to an instance. Please refer to gcloud doc +// https://cloud.google.com/compute/docs/disks/#increased_persistent_disk_limits +const ( + OneCPU = 1 + EightCPUs = 8 + VolumeLimit16 = 16 + VolumeLimit32 = 32 + VolumeLimit64 = 64 + VolumeLimit128 = 128 +) + func getPath(uid types.UID, volName string, host volume.VolumeHost) string { return host.GetPodVolumeDir(uid, kstrings.EscapeQualifiedNameForDisk(gcePersistentDiskPluginName), volName) } @@ -98,6 +116,58 @@ func (plugin *gcePersistentDiskPlugin) GetAccessModes() []v1.PersistentVolumeAcc } } +func (plugin *gcePersistentDiskPlugin) GetVolumeLimits() (map[string]int64, error) { + volumeLimits := map[string]int64{ + util.GCEVolumeLimitKey: VolumeLimit16, + } + cloud := plugin.host.GetCloudProvider() + + // if we can't fetch cloudprovider we return an error + // hoping external CCM or admin can set it. Returning + // default values from here will mean, no one can + // override them. + if cloud == nil { + return nil, fmt.Errorf("No cloudprovider present") + } + + if cloud.ProviderName() != gcecloud.ProviderName { + return nil, fmt.Errorf("Expected gce cloud got %s", cloud.ProviderName()) + } + + instances, ok := cloud.Instances() + if !ok { + glog.Warning("Failed to get instances from cloud provider") + return volumeLimits, nil + } + + instanceType, err := instances.InstanceType(context.TODO(), plugin.host.GetNodeName()) + if err != nil { + glog.Errorf("Failed to get instance type from GCE cloud provider") + return volumeLimits, nil + } + if strings.HasPrefix(instanceType, "n1-") { + splits := strings.Split(instanceType, "-") + if len(splits) < 3 { + return volumeLimits, nil + } + last := splits[2] + if num, err := strconv.Atoi(last); err == nil { + if num == OneCPU { + volumeLimits[util.GCEVolumeLimitKey] = VolumeLimit32 + } else if num < EightCPUs { + volumeLimits[util.GCEVolumeLimitKey] = VolumeLimit64 + } else { + volumeLimits[util.GCEVolumeLimitKey] = VolumeLimit128 + } + } + } + return volumeLimits, nil +} + +func (plugin *gcePersistentDiskPlugin) VolumeLimitKey(spec *volume.Spec) string { + return util.GCEVolumeLimitKey +} + func (plugin *gcePersistentDiskPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) { // Inject real implementations here, test through the internal function. return plugin.newMounterInternal(spec, pod.UID, &GCEDiskUtil{}, plugin.host.GetMounter(plugin.GetPluginName())) @@ -396,7 +466,7 @@ type gcePersistentDiskProvisioner struct { var _ volume.Provisioner = &gcePersistentDiskProvisioner{} -func (c *gcePersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *gcePersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } @@ -422,7 +492,7 @@ func (c *gcePersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error) PersistentVolumeReclaimPolicy: c.options.PersistentVolumeReclaimPolicy, AccessModes: c.options.PVC.Spec.AccessModes, Capacity: v1.ResourceList{ - v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dG", sizeGB)), + v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)), }, PersistentVolumeSource: v1.PersistentVolumeSource{ GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ @@ -448,5 +518,9 @@ func (c *gcePersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error) } } + if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + pv.Spec.VolumeMode = c.options.PVC.Spec.VolumeMode + } + return pv, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd_block.go b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd_block.go index f4398d13b..24dcfce73 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd_block.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd_block.go @@ -28,6 +28,7 @@ import ( "k8s.io/kubernetes/pkg/util/mount" kstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" ) @@ -151,6 +152,10 @@ func (b *gcePersistentDiskMapper) SetUpDevice() (string, error) { return "", nil } +func (b *gcePersistentDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + // GetGlobalMapPath returns global map path and error // path: plugins/kubernetes.io/{PluginName}/volumeDevices/pdName func (pd *gcePersistentDisk) GetGlobalMapPath(spec *volume.Spec) (string, error) { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd_test.go b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd_test.go index 2f22a204f..c3d80c68d 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_pd_test.go @@ -167,7 +167,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Errorf("Error creating new provisioner:%v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } @@ -177,7 +177,7 @@ func TestPlugin(t *testing.T) { } cap := persistentSpec.Spec.Capacity[v1.ResourceStorage] size := cap.Value() - if size != 100*util.GB { + if size != 100*util.GIB { t.Errorf("Provision() returned unexpected volume size: %v", size) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_util.go b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_util.go index 8774d77c8..e635ed0d7 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_util.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_util.go @@ -20,6 +20,7 @@ import ( "fmt" "path" "path/filepath" + "regexp" "strings" "time" @@ -31,6 +32,7 @@ import ( gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" "k8s.io/kubernetes/pkg/features" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + utilfile "k8s.io/kubernetes/pkg/util/file" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" "k8s.io/utils/exec" @@ -50,12 +52,19 @@ const ( // Replication type constants must be lower case. replicationTypeNone = "none" replicationTypeRegionalPD = "regional-pd" + + // scsi_id output should be in the form of: + // 0Google PersistentDisk + scsiPattern = `^0Google\s+PersistentDisk\s+([\S]+)\s*$` ) -// These variables are modified only in unit tests and should be constant -// otherwise. var ( + // errorSleepDuration is modified only in unit tests and should be constant + // otherwise. errorSleepDuration time.Duration = 5 * time.Second + + // regex to parse scsi_id output and extract the serial + scsiRegex = regexp.MustCompile(scsiPattern) ) type GCEDiskUtil struct{} @@ -86,8 +95,8 @@ func (gceutil *GCEDiskUtil) CreateVolume(c *gcePersistentDiskProvisioner) (strin name := volumeutil.GenerateVolumeName(c.options.ClusterName, c.options.PVName, 63) // GCE PD name can have up to 63 characters capacity := c.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] - // GCE PDs are allocated in chunks of GBs (not GiBs) - requestGB := volumeutil.RoundUpToGB(capacity) + // GCE PDs are allocated in chunks of GiBs + requestGB := volumeutil.RoundUpToGiB(capacity) // Apply Parameters. // Values for parameter "replication-type" are canonicalized to lower case. @@ -261,9 +270,11 @@ func createRegionalPD( } // Returns the first path that exists, or empty string if none exist. -func verifyDevicePath(devicePaths []string, sdBeforeSet sets.String) (string, error) { +func verifyDevicePath(devicePaths []string, sdBeforeSet sets.String, diskName string) (string, error) { if err := udevadmChangeToNewDrives(sdBeforeSet); err != nil { - // udevadm errors should not block disk detachment, log and continue + // It's possible udevadm was called on other disks so it should not block this + // call. If it did fail on this disk, then the devicePath will either + // not exist or be wrong. If it's wrong, then the scsi_id check below will fail. glog.Errorf("udevadmChangeToNewDrives failed with: %v", err) } @@ -271,6 +282,22 @@ func verifyDevicePath(devicePaths []string, sdBeforeSet sets.String) (string, er if pathExists, err := volumeutil.PathExists(path); err != nil { return "", fmt.Errorf("Error checking if path exists: %v", err) } else if pathExists { + // validate that the path actually resolves to the correct disk + serial, err := getScsiSerial(path, diskName) + if err != nil { + return "", fmt.Errorf("failed to get scsi serial %v", err) + } + if serial != diskName { + // The device link is not pointing to the correct device + // Trigger udev on this device to try to fix the link + if udevErr := udevadmChangeToDrive(path); udevErr != nil { + glog.Errorf("udevadmChangeToDrive %q failed with: %v", path, err) + } + + // Return error to retry WaitForAttach and verifyDevicePath + return "", fmt.Errorf("scsi_id serial %q for device %q doesn't match disk %q", serial, path, diskName) + } + // The device link is correct return path, nil } } @@ -278,22 +305,38 @@ func verifyDevicePath(devicePaths []string, sdBeforeSet sets.String) (string, er return "", nil } -// Returns the first path that exists, or empty string if none exist. -func verifyAllPathsRemoved(devicePaths []string) (bool, error) { - allPathsRemoved := true - for _, path := range devicePaths { - if err := udevadmChangeToDrive(path); err != nil { - // udevadm errors should not block disk detachment, log and continue - glog.Errorf("%v", err) - } - if exists, err := volumeutil.PathExists(path); err != nil { - return false, fmt.Errorf("Error checking if path exists: %v", err) - } else { - allPathsRemoved = allPathsRemoved && !exists - } +// Calls scsi_id on the given devicePath to get the serial number reported by that device. +func getScsiSerial(devicePath, diskName string) (string, error) { + exists, err := utilfile.FileExists("/lib/udev/scsi_id") + if err != nil { + return "", fmt.Errorf("failed to check scsi_id existence: %v", err) + } + + if !exists { + glog.V(6).Infof("scsi_id doesn't exist; skipping check for %v", devicePath) + return diskName, nil + } + + out, err := exec.New().Command( + "/lib/udev/scsi_id", + "--page=0x83", + "--whitelisted", + fmt.Sprintf("--device=%v", devicePath)).CombinedOutput() + if err != nil { + return "", fmt.Errorf("scsi_id failed for device %q with %v.", devicePath, err) + } + + return parseScsiSerial(string(out)) +} + +// Parse the output returned by scsi_id and extract the serial number +func parseScsiSerial(output string) (string, error) { + substrings := scsiRegex.FindStringSubmatch(output) + if substrings == nil { + return "", fmt.Errorf("scsi_id output cannot be parsed: %q", output) } - return allPathsRemoved, nil + return substrings[1], nil } // Returns list of all /dev/disk/by-id/* paths for given PD. diff --git a/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_util_test.go b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_util_test.go new file mode 100644 index 000000000..91b33cd2a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/volume/gce_pd/gce_util_test.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 gce_pd + +import "testing" + +func TestParseScsiSerial(t *testing.T) { + cases := []struct { + name string + output string + diskName string + expectErr bool + }{ + { + name: "valid", + output: "0Google PersistentDisk test-disk", + diskName: "test-disk", + }, + { + name: "valid with newline", + output: "0Google PersistentDisk test-disk\n", + diskName: "test-disk", + }, + { + name: "invalid prefix", + output: "00Google PersistentDisk test-disk", + expectErr: true, + }, + { + name: "invalid suffix", + output: "0Google PersistentDisk test-disk more", + expectErr: true, + }, + } + + for _, test := range cases { + serial, err := parseScsiSerial(test.output) + if err != nil && !test.expectErr { + t.Errorf("test %v failed: %v", test.name, err) + } + if err == nil && test.expectErr { + t.Errorf("test %q failed: got success", test.name) + } + if serial != test.diskName { + t.Errorf("test %v failed: expected serial %q, got %q", test.name, test.diskName, serial) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/git_repo/git_repo.go b/vendor/k8s.io/kubernetes/pkg/volume/git_repo/git_repo.go index 94f174862..332f33e5a 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/git_repo/git_repo.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/git_repo/git_repo.go @@ -20,6 +20,7 @@ import ( "fmt" "io/ioutil" "path" + "path/filepath" "strings" "k8s.io/api/core/v1" @@ -90,6 +91,10 @@ func (plugin *gitRepoPlugin) SupportsBulkVolumeVerification() bool { } func (plugin *gitRepoPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) { + if err := validateVolume(spec.Volume.GitRepo); err != nil { + return nil, err + } + return &gitRepoVolumeMounter{ gitRepoVolume: &gitRepoVolume{ volName: spec.Name(), @@ -190,7 +195,7 @@ func (b *gitRepoVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { return err } - args := []string{"clone", b.source} + args := []string{"clone", "--", b.source} if len(b.target) != 0 { args = append(args, b.target) @@ -214,7 +219,7 @@ func (b *gitRepoVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { var subdir string switch { - case b.target == ".": + case len(b.target) != 0 && filepath.Clean(b.target) == ".": // if target dir is '.', use the current dir subdir = path.Join(dir) case len(files) == 1: @@ -248,6 +253,19 @@ func (b *gitRepoVolumeMounter) execCommand(command string, args []string, dir st return cmd.CombinedOutput() } +func validateVolume(src *v1.GitRepoVolumeSource) error { + if err := validateNonFlagArgument(src.Repository, "repository"); err != nil { + return err + } + if err := validateNonFlagArgument(src.Revision, "revision"); err != nil { + return err + } + if err := validateNonFlagArgument(src.Directory, "directory"); err != nil { + return err + } + return nil +} + // gitRepoVolumeUnmounter cleans git repo volumes. type gitRepoVolumeUnmounter struct { *gitRepoVolume @@ -276,3 +294,10 @@ func getVolumeSource(spec *volume.Spec) (*v1.GitRepoVolumeSource, bool) { return volumeSource, readOnly } + +func validateNonFlagArgument(arg, argName string) error { + if len(arg) > 0 && arg[0] == '-' { + return fmt.Errorf("%q is an invalid value for %s", arg, argName) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/git_repo/git_repo_test.go b/vendor/k8s.io/kubernetes/pkg/volume/git_repo/git_repo_test.go index 8c6a41a1c..601ce9f66 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/git_repo/git_repo_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/git_repo/git_repo_test.go @@ -93,7 +93,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl, "target_dir"}, + cmd: []string{"git", "clone", "--", gitUrl, "target_dir"}, dir: "", }, { @@ -120,7 +120,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl, "target_dir"}, + cmd: []string{"git", "clone", "--", gitUrl, "target_dir"}, dir: "", }, }, @@ -138,7 +138,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl}, + cmd: []string{"git", "clone", "--", gitUrl}, dir: "", }, }, @@ -158,7 +158,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl}, + cmd: []string{"git", "clone", "--", gitUrl}, dir: "", }, { @@ -186,7 +186,7 @@ func TestPlugin(t *testing.T) { }, expecteds: []expectedCommand{ { - cmd: []string{"git", "clone", gitUrl, "."}, + cmd: []string{"git", "clone", "--", gitUrl, "."}, dir: "", }, { @@ -200,6 +200,72 @@ func TestPlugin(t *testing.T) { }, isExpectedFailure: false, }, + { + name: "current-dir-mess", + vol: &v1.Volume{ + Name: "vol1", + VolumeSource: v1.VolumeSource{ + GitRepo: &v1.GitRepoVolumeSource{ + Repository: gitUrl, + Revision: revision, + Directory: "./.", + }, + }, + }, + expecteds: []expectedCommand{ + { + cmd: []string{"git", "clone", "--", gitUrl, "./."}, + dir: "", + }, + { + cmd: []string{"git", "checkout", revision}, + dir: "", + }, + { + cmd: []string{"git", "reset", "--hard"}, + dir: "", + }, + }, + isExpectedFailure: false, + }, + { + name: "invalid-repository", + vol: &v1.Volume{ + Name: "vol1", + VolumeSource: v1.VolumeSource{ + GitRepo: &v1.GitRepoVolumeSource{ + Repository: "--foo", + }, + }, + }, + isExpectedFailure: true, + }, + { + name: "invalid-revision", + vol: &v1.Volume{ + Name: "vol1", + VolumeSource: v1.VolumeSource{ + GitRepo: &v1.GitRepoVolumeSource{ + Repository: gitUrl, + Revision: "--bar", + }, + }, + }, + isExpectedFailure: true, + }, + { + name: "invalid-directory", + vol: &v1.Volume{ + Name: "vol1", + VolumeSource: v1.VolumeSource{ + GitRepo: &v1.GitRepoVolumeSource{ + Repository: gitUrl, + Directory: "-b", + }, + }, + }, + isExpectedFailure: true, + }, } for _, scenario := range scenarios { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/glusterfs/glusterfs.go b/vendor/k8s.io/kubernetes/pkg/volume/glusterfs/glusterfs.go index d77eb5898..a2d200d21 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/glusterfs/glusterfs.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/glusterfs/glusterfs.go @@ -110,12 +110,8 @@ func (plugin *glusterfsPlugin) GetVolumeName(spec *volume.Spec) (string, error) } func (plugin *glusterfsPlugin) CanSupport(spec *volume.Spec) bool { - if (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Glusterfs == nil) || - (spec.Volume != nil && spec.Volume.Glusterfs == nil) { - return false - } - - return true + return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Glusterfs != nil) || + (spec.Volume != nil && spec.Volume.Glusterfs != nil) } func (plugin *glusterfsPlugin) RequiresRemount() bool { @@ -401,18 +397,19 @@ func (plugin *glusterfsPlugin) newProvisionerInternal(options volume.VolumeOptio } type provisionerConfig struct { - url string - user string - userKey string - secretNamespace string - secretName string - secretValue string - clusterID string - gidMin int - gidMax int - volumeType gapi.VolumeDurabilityInfo - volumeOptions []string - volumeNamePrefix string + url string + user string + userKey string + secretNamespace string + secretName string + secretValue string + clusterID string + gidMin int + gidMax int + volumeType gapi.VolumeDurabilityInfo + volumeOptions []string + volumeNamePrefix string + thinPoolSnapFactor float32 } type glusterfsVolumeProvisioner struct { @@ -667,7 +664,7 @@ func (d *glusterfsVolumeDeleter) Delete() error { return nil } -func (p *glusterfsVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (p *glusterfsVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !volutil.AccessModesContainedInAll(p.plugin.GetAccessModes(), p.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", p.options.PVC.Spec.AccessModes, p.plugin.GetAccessModes()) } @@ -676,6 +673,11 @@ func (p *glusterfsVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { glog.V(4).Infof("not able to parse your claim Selector") return nil, fmt.Errorf("not able to parse your claim Selector") } + + if volutil.CheckPersistentVolumeClaimModeBlock(p.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", p.plugin.GetPluginName()) + } + glog.V(4).Infof("Provision VolumeOptions %v", p.options) scName := v1helper.GetPersistentVolumeClaimClass(p.options.PVC) cfg, err := parseClassParameters(p.options.Parameters, p.plugin.host.GetKubeClient()) @@ -764,7 +766,15 @@ func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsVolum } gid64 := int64(gid) - volumeReq := &gapi.VolumeCreateRequest{Size: sz, Name: customVolumeName, Clusters: clusterIDs, Gid: gid64, Durability: p.volumeType, GlusterVolumeOptions: p.volumeOptions} + snaps := struct { + Enable bool `json:"enable"` + Factor float32 `json:"factor"` + }{ + true, + p.provisionerConfig.thinPoolSnapFactor, + } + + volumeReq := &gapi.VolumeCreateRequest{Size: sz, Name: customVolumeName, Clusters: clusterIDs, Gid: gid64, Durability: p.volumeType, GlusterVolumeOptions: p.volumeOptions, Snapshot: snaps} volume, err := cli.VolumeCreate(volumeReq) if err != nil { glog.Errorf("failed to create volume: %v", err) @@ -931,6 +941,10 @@ func parseClassParameters(params map[string]string, kubeClient clientset.Interfa parseVolumeType := "" parseVolumeOptions := "" parseVolumeNamePrefix := "" + parseThinPoolSnapFactor := "" + + //thin pool snap factor default to 1.0 + cfg.thinPoolSnapFactor = float32(1.0) for k, v := range params { switch dstrings.ToLower(k) { @@ -985,6 +999,11 @@ func parseClassParameters(params map[string]string, kubeClient clientset.Interfa if len(v) != 0 { parseVolumeNamePrefix = v } + case "snapfactor": + if len(v) != 0 { + parseThinPoolSnapFactor = v + } + default: return nil, fmt.Errorf("invalid option %q for volume plugin %s", k, glusterfsPluginName) } @@ -1072,6 +1091,17 @@ func parseClassParameters(params map[string]string, kubeClient clientset.Interfa } cfg.volumeNamePrefix = parseVolumeNamePrefix } + + if len(parseThinPoolSnapFactor) != 0 { + thinPoolSnapFactor, err := strconv.ParseFloat(parseThinPoolSnapFactor, 32) + if err != nil { + return nil, fmt.Errorf("failed to convert snapfactor %v to float: %v", parseThinPoolSnapFactor, err) + } + if thinPoolSnapFactor < 1.0 || thinPoolSnapFactor > 100.0 { + return nil, fmt.Errorf("invalid snapshot factor %v, the value must be between 1 to 100", thinPoolSnapFactor) + } + cfg.thinPoolSnapFactor = float32(thinPoolSnapFactor) + } return &cfg, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/glusterfs/glusterfs_test.go b/vendor/k8s.io/kubernetes/pkg/volume/glusterfs/glusterfs_test.go index 716986acd..2e8d0af83 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/glusterfs/glusterfs_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/glusterfs/glusterfs_test.go @@ -51,12 +51,24 @@ func TestCanSupport(t *testing.T) { if plug.GetPluginName() != "kubernetes.io/glusterfs" { t.Errorf("Wrong name: %s", plug.GetPluginName()) } - if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) { + if plug.CanSupport(&volume.Spec{}) { t.Errorf("Expected false") } if plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) { t.Errorf("Expected false") } + if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{Glusterfs: &v1.GlusterfsVolumeSource{}}}}) { + t.Errorf("Expected true") + } + if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{}}}) { + t.Errorf("Expected false") + } + if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) { + t.Errorf("Expected false") + } + if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Glusterfs: &v1.GlusterfsVolumeSource{}}}}}) { + t.Errorf("Expected true") + } } func TestGetAccessModes(t *testing.T) { @@ -241,13 +253,14 @@ func TestParseClassParameters(t *testing.T) { nil, // secret false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - user: "admin", - userKey: "password", - secretValue: "password", - gidMin: 2000, - gidMax: 2147483647, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + user: "admin", + userKey: "password", + secretValue: "password", + gidMin: 2000, + gidMax: 2147483647, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -261,14 +274,15 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - user: "admin", - secretName: "mysecret", - secretNamespace: "default", - secretValue: "mypassword", - gidMin: 2000, - gidMax: 2147483647, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + user: "admin", + secretName: "mysecret", + secretNamespace: "default", + secretValue: "mypassword", + gidMin: 2000, + gidMax: 2147483647, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -280,10 +294,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 2000, - gidMax: 2147483647, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 2000, + gidMax: 2147483647, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -417,10 +432,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 4000, - gidMax: 2147483647, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 2147483647, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -433,10 +449,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 2000, - gidMax: 5000, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 2000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, { @@ -450,10 +467,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 4000, - gidMax: 5000, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, @@ -469,10 +487,11 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 4000, - gidMax: 5000, - volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 4}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 4}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}}, + thinPoolSnapFactor: float32(1.0), }, }, @@ -488,10 +507,54 @@ func TestParseClassParameters(t *testing.T) { &secret, false, // expect error &provisionerConfig{ - url: "https://localhost:8080", - gidMin: 4000, - gidMax: 5000, - volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}}, + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}}, + thinPoolSnapFactor: float32(1.0), + }, + }, + { + "valid snapfactor: 50", + map[string]string{ + "resturl": "https://localhost:8080", + "restauthenabled": "false", + "gidMin": "4000", + "gidMax": "5000", + "volumetype": "disperse:4:2", + "snapfactor": "50", + }, + &secret, + false, // expect error + &provisionerConfig{ + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}}, + thinPoolSnapFactor: float32(50), + }, + }, + + { + "valid volumenameprefix: dept-dev", + map[string]string{ + "resturl": "https://localhost:8080", + "restauthenabled": "false", + "gidMin": "4000", + "gidMax": "5000", + "volumetype": "disperse:4:2", + "snapfactor": "50", + "volumenameprefix": "dept-dev", + }, + &secret, + false, // expect error + &provisionerConfig{ + url: "https://localhost:8080", + gidMin: 4000, + gidMax: 5000, + volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}}, + thinPoolSnapFactor: float32(50), + volumeNamePrefix: "dept-dev", }, }, { @@ -538,6 +601,50 @@ func TestParseClassParameters(t *testing.T) { true, // expect error nil, }, + { + "invalid thinPoolSnapFactor: value out of range", + map[string]string{ + "resturl": "https://localhost:8080", + "restauthenabled": "false", + "snapfactor": "0.5", + }, + &secret, + true, // expect error + nil, + }, + { + "invalid volumenameprefix: string starting with '_'", + map[string]string{ + "resturl": "https://localhost:8080", + "restauthenabled": "false", + "volumenameprefix": "_", + }, + &secret, + true, // expect error + nil, + }, + { + "invalid volumenameprefix: string with '_'", + map[string]string{ + "resturl": "https://localhost:8080", + "restauthenabled": "false", + "volumenameprefix": "qe_dept", + }, + &secret, + true, // expect error + nil, + }, + { + "invalid thinPoolSnapFactor: value out of range", + map[string]string{ + "resturl": "https://localhost:8080", + "restauthenabled": "false", + "snapfactor": "120", + }, + &secret, + true, // expect error + nil, + }, } for _, test := range tests { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/host_path/host_path.go b/vendor/k8s.io/kubernetes/pkg/volume/host_path/host_path.go index 4a3cb76b6..a2cac9d06 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/host_path/host_path.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/host_path/host_path.go @@ -265,7 +265,11 @@ type hostPathProvisioner struct { // Create for hostPath simply creates a local /tmp/hostpath_pv/%s directory as a new PersistentVolume. // This Provisioner is meant for development and testing only and WILL NOT WORK in a multi-node cluster. -func (r *hostPathProvisioner) Provision() (*v1.PersistentVolume, error) { +func (r *hostPathProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { + if util.CheckPersistentVolumeClaimModeBlock(r.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", r.plugin.GetPluginName()) + } + fullpath := fmt.Sprintf("/tmp/hostpath_pv/%s", uuid.NewUUID()) capacity := r.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] @@ -350,7 +354,8 @@ type fileTypeChecker struct { } func (ftc *fileTypeChecker) Exists() bool { - return ftc.mounter.ExistsPath(ftc.path) + exists, err := ftc.mounter.ExistsPath(ftc.path) + return exists && err == nil } func (ftc *fileTypeChecker) IsFile() bool { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/host_path/host_path_test.go b/vendor/k8s.io/kubernetes/pkg/volume/host_path/host_path_test.go index 92ec95fb3..79d4a063f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/host_path/host_path_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/host_path/host_path_test.go @@ -178,7 +178,7 @@ func TestProvisioner(t *testing.T) { if err != nil { t.Errorf("Failed to make a new Provisioner: %v", err) } - pv, err := creater.Provision() + pv, err := creater.Provision(nil, nil) if err != nil { t.Errorf("Unexpected error creating volume: %v", err) } @@ -369,8 +369,8 @@ func (fftc *fakeFileTypeChecker) MakeDir(pathname string) error { return nil } -func (fftc *fakeFileTypeChecker) ExistsPath(pathname string) bool { - return true +func (fftc *fakeFileTypeChecker) ExistsPath(pathname string) (bool, error) { + return true, nil } func (fftc *fakeFileTypeChecker) GetFileType(_ string) (utilmount.FileType, error) { @@ -389,10 +389,22 @@ func (fftc *fakeFileTypeChecker) SafeMakeDir(_, _ string, _ os.FileMode) error { return nil } +func (fftc *fakeFileTypeChecker) GetMountRefs(pathname string) ([]string, error) { + return nil, errors.New("not implemented") +} + +func (fftc *fakeFileTypeChecker) GetFSGroup(pathname string) (int64, error) { + return -1, errors.New("not implemented") +} + func (fftc *fakeFileTypeChecker) GetSELinuxSupport(pathname string) (bool, error) { return false, errors.New("not implemented") } +func (fftc *fakeFileTypeChecker) GetMode(pathname string) (os.FileMode, error) { + return 0, errors.New("not implemented") +} + func setUp() error { err := os.MkdirAll("/tmp/ExistingFolder", os.FileMode(0755)) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/iscsi/iscsi.go b/vendor/k8s.io/kubernetes/pkg/volume/iscsi/iscsi.go index 525386e19..687f2cc6a 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/iscsi/iscsi.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/iscsi/iscsi.go @@ -112,6 +112,12 @@ func (plugin *iscsiPlugin) newMounterInternal(spec *volume.Spec, podUID types.UI if err != nil { return nil, err } + + if iscsiDisk != nil { + + //Add volume metrics + iscsiDisk.MetricsProvider = volume.NewMetricsStatFS(iscsiDisk.GetPath()) + } return &iscsiDiskMounter{ iscsiDisk: iscsiDisk, fsType: fsType, @@ -164,10 +170,11 @@ func (plugin *iscsiPlugin) NewUnmounter(volName string, podUID types.UID) (volum func (plugin *iscsiPlugin) newUnmounterInternal(volName string, podUID types.UID, manager diskManager, mounter mount.Interface, exec mount.Exec) (volume.Unmounter, error) { return &iscsiDiskUnmounter{ iscsiDisk: &iscsiDisk{ - podUID: podUID, - VolName: volName, - manager: manager, - plugin: plugin, + podUID: podUID, + VolName: volName, + manager: manager, + plugin: plugin, + MetricsProvider: volume.NewMetricsStatFS(plugin.host.GetPodVolumeDir(podUID, utilstrings.EscapeQualifiedNameForDisk(iscsiPluginName), volName)), }, mounter: mounter, exec: exec, @@ -264,7 +271,7 @@ type iscsiDisk struct { plugin *iscsiPlugin // Utility interface that provides API calls to the provider to attach/detach disks. manager diskManager - volume.MetricsNil + volume.MetricsProvider } func (iscsi *iscsiDisk) GetPath() string { @@ -360,6 +367,10 @@ func (b *iscsiDiskMapper) SetUpDevice() (string, error) { return "", nil } +func (b *iscsiDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return ioutil.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + type iscsiDiskUnmapper struct { *iscsiDisk exec mount.Exec diff --git a/vendor/k8s.io/kubernetes/pkg/volume/iscsi/iscsi_util.go b/vendor/k8s.io/kubernetes/pkg/volume/iscsi/iscsi_util.go index ad6382f30..d649e3517 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/iscsi/iscsi_util.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/iscsi/iscsi_util.go @@ -396,25 +396,16 @@ func globalPDPathOperation(b iscsiDiskMounter) func(iscsiDiskMounter, string, *I // DetachDisk unmounts and detaches a volume from node func (util *ISCSIUtil) DetachDisk(c iscsiDiskUnmounter, mntPath string) error { - _, cnt, err := mount.GetDeviceNameFromMount(c.mounter, mntPath) - if err != nil { - glog.Errorf("iscsi detach disk: failed to get device from mnt: %s\nError: %v", mntPath, err) - return err - } if pathExists, pathErr := volumeutil.PathExists(mntPath); pathErr != nil { return fmt.Errorf("Error checking if path exists: %v", pathErr) } else if !pathExists { glog.Warningf("Warning: Unmount skipped because path does not exist: %v", mntPath) return nil } - if err = c.mounter.Unmount(mntPath); err != nil { + if err := c.mounter.Unmount(mntPath); err != nil { glog.Errorf("iscsi detach disk: failed to unmount: %s\nError: %v", mntPath, err) return err } - cnt-- - if cnt != 0 { - return nil - } // if device is no longer used, see if need to logout the target device, prefix, err := extractDeviceAndPrefix(mntPath) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/local/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/local/BUILD index c20da4134..599e2d6e6 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/local/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/local/BUILD @@ -20,7 +20,6 @@ go_library( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/local/local.go b/vendor/k8s.io/kubernetes/pkg/volume/local/local.go index aa84a3293..854c6d968 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/local/local.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/local/local.go @@ -19,20 +19,20 @@ package local import ( "fmt" "os" - "path" + "path/filepath" "runtime" + "strings" "github.com/golang/glog" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/pkg/util/keymutex" "k8s.io/kubernetes/pkg/util/mount" - "k8s.io/kubernetes/pkg/util/strings" + stringsutil "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/validation" @@ -60,10 +60,7 @@ const ( func (plugin *localVolumePlugin) Init(host volume.VolumeHost) error { plugin.host = host plugin.volumeLocks = keymutex.NewKeyMutex() - eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(glog.Infof) - recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "localvolume"}) - plugin.recorder = recorder + plugin.recorder = host.GetEventRecorder() return nil } @@ -223,7 +220,7 @@ type localVolume struct { } func (l *localVolume) GetPath() string { - return l.plugin.host.GetPodVolumeDir(l.podUID, strings.EscapeQualifiedNameForDisk(localVolumePluginName), l.volName) + return l.plugin.host.GetPodVolumeDir(l.podUID, stringsutil.EscapeQualifiedNameForDisk(localVolumePluginName), l.volName) } type localVolumeMounter struct { @@ -277,20 +274,22 @@ func (m *localVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { if !notMnt { return nil } - refs, err := mount.GetMountRefsByDev(m.mounter, m.globalPath) + refs, err := m.mounter.GetMountRefs(m.globalPath) if fsGroup != nil { if err != nil { glog.Errorf("cannot collect mounting information: %s %v", m.globalPath, err) return err } + // Only count mounts from other pods + refs = m.filterPodMounts(refs) if len(refs) > 0 { fsGroupNew := int64(*fsGroup) - fsGroupSame, fsGroupOld, err := volume.IsSameFSGroup(m.globalPath, fsGroupNew) + fsGroupOld, err := m.mounter.GetFSGroup(m.globalPath) if err != nil { return fmt.Errorf("failed to check fsGroup for %s (%v)", m.globalPath, err) } - if !fsGroupSame { + if fsGroupNew != fsGroupOld { m.plugin.recorder.Eventf(m.pod, v1.EventTypeWarning, events.WarnAlreadyMountedVolume, "The requested fsGroup is %d, but the volume %s has GID %d. The volume may not be shareable.", fsGroupNew, m.volName, fsGroupOld) } } @@ -348,6 +347,17 @@ func (m *localVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { return nil } +// filterPodMounts only returns mount paths inside the kubelet pod directory +func (m *localVolumeMounter) filterPodMounts(refs []string) []string { + filtered := []string{} + for _, r := range refs { + if strings.HasPrefix(r, m.plugin.host.GetPodsDir()+string(os.PathSeparator)) { + filtered = append(filtered, r) + } + } + return filtered +} + type localVolumeUnmounter struct { *localVolume } @@ -380,6 +390,10 @@ func (m *localVolumeMapper) SetUpDevice() (string, error) { return globalPath, nil } +func (m *localVolumeMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + // localVolumeUnmapper implements the BlockVolumeUnmapper interface for local volumes. type localVolumeUnmapper struct { *localVolume @@ -396,7 +410,7 @@ func (u *localVolumeUnmapper) TearDownDevice(mapPath, devicePath string) error { // GetGlobalMapPath returns global map path and error. // path: plugins/kubernetes.io/kubernetes.io/local-volume/volumeDevices/{volumeName} func (lv *localVolume) GetGlobalMapPath(spec *volume.Spec) (string, error) { - return path.Join(lv.plugin.host.GetVolumeDevicePluginDir(strings.EscapeQualifiedNameForDisk(localVolumePluginName)), + return filepath.Join(lv.plugin.host.GetVolumeDevicePluginDir(stringsutil.EscapeQualifiedNameForDisk(localVolumePluginName)), lv.volName), nil } @@ -405,5 +419,5 @@ func (lv *localVolume) GetGlobalMapPath(spec *volume.Spec) (string, error) { // volName: local-pv-ff0d6d4 func (lv *localVolume) GetPodDeviceMapPath() (string, string) { return lv.plugin.host.GetPodVolumeDeviceDir(lv.podUID, - strings.EscapeQualifiedNameForDisk(localVolumePluginName)), lv.volName + stringsutil.EscapeQualifiedNameForDisk(localVolumePluginName)), lv.volName } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/local/local_test.go b/vendor/k8s.io/kubernetes/pkg/volume/local/local_test.go index 58ab8623b..2c1763fb5 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/local/local_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/local/local_test.go @@ -22,6 +22,8 @@ import ( "fmt" "os" "path" + "path/filepath" + "reflect" "runtime" "testing" @@ -447,3 +449,57 @@ func TestUnsupportedPlugins(t *testing.T) { t.Errorf("Provisionable plugin found, expected none") } } + +func TestFilterPodMounts(t *testing.T) { + tmpDir, plug := getPlugin(t) + defer os.RemoveAll(tmpDir) + + pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} + mounter, err := plug.NewMounter(getTestVolume(false, tmpDir, false), pod, volume.VolumeOptions{}) + if err != nil { + t.Fatal(err) + } + lvMounter, ok := mounter.(*localVolumeMounter) + if !ok { + t.Fatal("mounter is not localVolumeMounter") + } + + host := volumetest.NewFakeVolumeHost(tmpDir, nil, nil) + podsDir := host.GetPodsDir() + + cases := map[string]struct { + input []string + expected []string + }{ + "empty": { + []string{}, + []string{}, + }, + "not-pod-mount": { + []string{"/mnt/outside"}, + []string{}, + }, + "pod-mount": { + []string{filepath.Join(podsDir, "pod-mount")}, + []string{filepath.Join(podsDir, "pod-mount")}, + }, + "not-directory-prefix": { + []string{podsDir + "pod-mount"}, + []string{}, + }, + "mix": { + []string{"/mnt/outside", + filepath.Join(podsDir, "pod-mount"), + "/another/outside", + filepath.Join(podsDir, "pod-mount2")}, + []string{filepath.Join(podsDir, "pod-mount"), + filepath.Join(podsDir, "pod-mount2")}, + }, + } + for name, test := range cases { + output := lvMounter.filterPodMounts(test.input) + if !reflect.DeepEqual(output, test.expected) { + t.Errorf("%v failed: output %+v doesn't equal expected %+v", name, output, test.expected) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/metrics_du.go b/vendor/k8s.io/kubernetes/pkg/volume/metrics_du.go index 88a985d5a..1cae99c10 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/metrics_du.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/metrics_du.go @@ -25,7 +25,7 @@ import ( var _ MetricsProvider = &metricsDu{} // metricsDu represents a MetricsProvider that calculates the used and -// available Volume space by executing the "du" command and gathering +// available Volume space by calling fs.DiskUsage() and gathering // filesystem info for the Volume path. type metricsDu struct { // the directory path the volume is mounted to. @@ -46,7 +46,7 @@ func (md *metricsDu) GetMetrics() (*Metrics, error) { return metrics, NewNoPathDefinedError() } - err := md.runDu(metrics) + err := md.runDiskUsage(metrics) if err != nil { return metrics, err } @@ -64,9 +64,9 @@ func (md *metricsDu) GetMetrics() (*Metrics, error) { return metrics, nil } -// runDu executes the "du" command and writes the results to metrics.Used -func (md *metricsDu) runDu(metrics *Metrics) error { - used, err := fs.Du(md.path) +// runDiskUsage gets disk usage of md.path and writes the results to metrics.Used +func (md *metricsDu) runDiskUsage(metrics *Metrics) error { + used, err := fs.DiskUsage(md.path) if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/nfs/nfs.go b/vendor/k8s.io/kubernetes/pkg/volume/nfs/nfs.go index 708ff7bab..588687cde 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/nfs/nfs.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/nfs/nfs.go @@ -255,7 +255,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { if err != nil { notMnt, mntErr := b.mounter.IsNotMountPoint(dir) if mntErr != nil { - glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) + glog.Errorf("IsNotMountPoint check failed: %v", mntErr) return err } if !notMnt { @@ -265,7 +265,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { } notMnt, mntErr := b.mounter.IsNotMountPoint(dir) if mntErr != nil { - glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) + glog.Errorf("IsNotMountPoint check failed: %v", mntErr) return err } if !notMnt { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/photon_pd/photon_pd.go b/vendor/k8s.io/kubernetes/pkg/volume/photon_pd/photon_pd.go index 25ca23928..89c385fdb 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/photon_pd/photon_pd.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/photon_pd/photon_pd.go @@ -340,11 +340,15 @@ func (plugin *photonPersistentDiskPlugin) newProvisionerInternal(options volume. }, nil } -func (p *photonPersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error) { +func (p *photonPersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(p.plugin.GetAccessModes(), p.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", p.options.PVC.Spec.AccessModes, p.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(p.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", p.plugin.GetPluginName()) + } + pdID, sizeGB, fstype, err := p.manager.CreateVolume(p) if err != nil { return nil, err diff --git a/vendor/k8s.io/kubernetes/pkg/volume/photon_pd/photon_pd_test.go b/vendor/k8s.io/kubernetes/pkg/volume/photon_pd/photon_pd_test.go index 4ad52b095..d3c14a229 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/photon_pd/photon_pd_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/photon_pd/photon_pd_test.go @@ -166,7 +166,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Fatalf("Error creating new provisioner:%v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/plugins.go b/vendor/k8s.io/kubernetes/pkg/volume/plugins.go index ec4ec5791..fbe0bd4c6 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/plugins.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/plugins.go @@ -23,6 +23,7 @@ import ( "sync" "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -30,18 +31,29 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/validation" clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume/util/recyclerclient" ) +type ProbeOperation uint32 +type ProbeEvent struct { + Plugin VolumePlugin // VolumePlugin that was added/updated/removed. if ProbeEvent.Op is 'ProbeRemove', Plugin should be nil + PluginName string + Op ProbeOperation // The operation to the plugin +} + const ( // Common parameter which can be specified in StorageClass to specify the desired FSType // Provisioners SHOULD implement support for this if they are block device based // Must be a filesystem type supported by the host operating system. // Ex. "ext4", "xfs", "ntfs". Default value depends on the provisioner VolumeParameterFSType = "fstype" + + ProbeAddOrUpdate ProbeOperation = 1 << iota + ProbeRemove ) // VolumeOptions contains option information about a volume. @@ -75,12 +87,8 @@ type VolumeOptions struct { type DynamicPluginProber interface { Init() error - // If an update has occurred since the last probe, updated = true - // and the list of probed plugins is returned. - // Otherwise, update = false and probedPlugins = nil. - // - // If an error occurs, updated and probedPlugins are undefined. - Probe() (updated bool, probedPlugins []VolumePlugin, err error) + // If an error occurs, events are undefined. + Probe() (events []ProbeEvent, err error) } // VolumePlugin is an interface to volume plugins that can be used on a @@ -209,6 +217,32 @@ type ExpandableVolumePlugin interface { RequiresFSResize() bool } +// VolumePluginWithAttachLimits is an extended interface of VolumePlugin that restricts number of +// volumes that can be attached to a node. +type VolumePluginWithAttachLimits interface { + VolumePlugin + // Return maximum number of volumes that can be attached to a node for this plugin. + // The key must be same as string returned by VolumeLimitKey function. The returned + // map may look like: + // - { "storage-limits-aws-ebs": 39 } + // - { "storage-limits-gce-pd": 10 } + // A volume plugin may return error from this function - if it can not be used on a given node or not + // applicable in given environment (where environment could be cloudprovider or any other dependency) + // For example - calling this function for EBS volume plugin on a GCE node should + // result in error. + // The returned values are stored in node allocatable property and will be used + // by scheduler to determine how many pods with volumes can be scheduled on given node. + GetVolumeLimits() (map[string]int64, error) + // Return volume limit key string to be used in node capacity constraints + // The key must start with prefix storage-limits-. For example: + // - storage-limits-aws-ebs + // - storage-limits-csi-cinder + // The key should respect character limit of ResourceName type + // This function may be called by kubelet or scheduler to identify node allocatable property + // which stores volumes limits. + VolumeLimitKey(spec *Spec) string +} + // BlockVolumePlugin is an extend interface of VolumePlugin and is used for block volumes support. type BlockVolumePlugin interface { VolumePlugin @@ -242,6 +276,10 @@ type VolumeHost interface { // ex. plugins/kubernetes.io/{PluginName}/{DefaultKubeletVolumeDevicesDirName}/{volumePluginDependentPath}/ GetVolumeDevicePluginDir(pluginName string) string + // GetPodsDir returns the absolute path to a directory where all the pods + // information is stored + GetPodsDir() string + // GetPodVolumeDir returns the absolute path a directory which // represents the named volume under the named plugin for the given // pod. If the specified pod does not exist, the result of this call @@ -299,6 +337,8 @@ type VolumeHost interface { // Returns a function that returns a configmap. GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error) + GetServiceAccountTokenFunc() func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) + // Returns an interface that should be used to execute any utilities in volume plugins GetExec(pluginName string) mount.Exec @@ -307,6 +347,9 @@ type VolumeHost interface { // Returns the name of the node GetNodeName() types.NodeName + + // Returns the event recorder of kubelet. + GetEventRecorder() record.EventRecorder } // VolumePluginMgr tracks registered plugins. @@ -314,7 +357,7 @@ type VolumePluginMgr struct { mutex sync.Mutex plugins map[string]VolumePlugin prober DynamicPluginProber - probedPlugins []VolumePlugin + probedPlugins map[string]VolumePlugin Host VolumeHost } @@ -431,6 +474,9 @@ func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, prober DynamicPlu if pm.plugins == nil { pm.plugins = map[string]VolumePlugin{} } + if pm.probedPlugins == nil { + pm.probedPlugins = map[string]VolumePlugin{} + } allErrs := []error{} for _, plugin := range plugins { @@ -544,25 +590,40 @@ func (pm *VolumePluginMgr) FindPluginByName(name string) (VolumePlugin, error) { // Check if probedPlugin cache update is required. // If it is, initialize all probed plugins and replace the cache with them. func (pm *VolumePluginMgr) refreshProbedPlugins() { - updated, plugins, err := pm.prober.Probe() + events, err := pm.prober.Probe() if err != nil { glog.Errorf("Error dynamically probing plugins: %s", err) return // Use cached plugins upon failure. } - if updated { - pm.probedPlugins = []VolumePlugin{} - for _, plugin := range plugins { - if err := pm.initProbedPlugin(plugin); err != nil { + for _, event := range events { + if event.Op == ProbeAddOrUpdate { + if err := pm.initProbedPlugin(event.Plugin); err != nil { glog.Errorf("Error initializing dynamically probed plugin %s; error: %s", - plugin.GetPluginName(), err) + event.Plugin.GetPluginName(), err) continue } - pm.probedPlugins = append(pm.probedPlugins, plugin) + pm.probedPlugins[event.Plugin.GetPluginName()] = event.Plugin + } else if event.Op == ProbeRemove { + delete(pm.probedPlugins, event.Plugin.GetPluginName()) + } else { + glog.Errorf("Unknown Operation on PluginName: %s.", + event.Plugin.GetPluginName()) } } } +// ListVolumePluginWithLimits returns plugins that have volume limits on nodes +func (pm *VolumePluginMgr) ListVolumePluginWithLimits() []VolumePluginWithAttachLimits { + matchedPlugins := []VolumePluginWithAttachLimits{} + for _, v := range pm.plugins { + if plugin, ok := v.(VolumePluginWithAttachLimits); ok { + matchedPlugins = append(matchedPlugins, plugin) + } + } + return matchedPlugins +} + // FindPersistentPluginBySpec looks for a persistent volume plugin that can // support a given volume specification. If no plugin is found, return an // error @@ -577,6 +638,20 @@ func (pm *VolumePluginMgr) FindPersistentPluginBySpec(spec *Spec) (PersistentVol return nil, fmt.Errorf("no persistent volume plugin matched") } +// FindVolumePluginWithLimitsBySpec returns volume plugin that has a limit on how many +// of them can be attached to a node +func (pm *VolumePluginMgr) FindVolumePluginWithLimitsBySpec(spec *Spec) (VolumePluginWithAttachLimits, error) { + volumePlugin, err := pm.FindPluginBySpec(spec) + if err != nil { + return nil, fmt.Errorf("Could not find volume plugin for spec : %#v", spec) + } + + if limitedPlugin, ok := volumePlugin.(VolumePluginWithAttachLimits); ok { + return limitedPlugin, nil + } + return nil, fmt.Errorf("no plugin with limits found") +} + // FindPersistentPluginByName fetches a persistent volume plugin by name. If // no plugin is found, returns error. func (pm *VolumePluginMgr) FindPersistentPluginByName(name string) (PersistentVolumePlugin, error) { @@ -803,5 +878,5 @@ func ValidateRecyclerPodTemplate(pod *v1.Pod) error { type dummyPluginProber struct{} -func (*dummyPluginProber) Init() error { return nil } -func (*dummyPluginProber) Probe() (bool, []VolumePlugin, error) { return false, nil, nil } +func (*dummyPluginProber) Init() error { return nil } +func (*dummyPluginProber) Probe() ([]ProbeEvent, error) { return nil, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/portworx/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/portworx/BUILD index 321306515..40e6e6541 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/portworx/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/portworx/BUILD @@ -15,6 +15,7 @@ go_test( "//pkg/volume:go_default_library", "//pkg/volume/testing:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/client-go/util/testing:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go b/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go index 70b6ece93..1edb0baca 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go @@ -50,6 +50,7 @@ var _ volume.VolumePlugin = &portworxVolumePlugin{} var _ volume.PersistentVolumePlugin = &portworxVolumePlugin{} var _ volume.DeletableVolumePlugin = &portworxVolumePlugin{} var _ volume.ProvisionableVolumePlugin = &portworxVolumePlugin{} +var _ volume.ExpandableVolumePlugin = &portworxVolumePlugin{} const ( portworxVolumePluginName = "kubernetes.io/portworx-volume" @@ -171,6 +172,24 @@ func (plugin *portworxVolumePlugin) newProvisionerInternal(options volume.Volume }, nil } +func (plugin *portworxVolumePlugin) RequiresFSResize() bool { + return false +} + +func (plugin *portworxVolumePlugin) ExpandVolumeDevice( + spec *volume.Spec, + newSize resource.Quantity, + oldSize resource.Quantity) (resource.Quantity, error) { + glog.V(4).Infof("Expanding: %s from %v to %v", spec.Name(), oldSize, newSize) + err := plugin.util.ResizeVolume(spec, newSize, plugin.host) + if err != nil { + return oldSize, err + } + + glog.V(4).Infof("Successfully resized %s to %v", spec.Name(), newSize) + return newSize, nil +} + func (plugin *portworxVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) { portworxVolume := &v1.Volume{ Name: volumeName, @@ -206,7 +225,7 @@ func getVolumeSource( // Abstract interface to PD operations. type portworxManager interface { // Creates a volume - CreateVolume(provisioner *portworxVolumeProvisioner) (volumeID string, volumeSizeGB int, labels map[string]string, err error) + CreateVolume(provisioner *portworxVolumeProvisioner) (volumeID string, volumeSizeGB int64, labels map[string]string, err error) // Deletes a volume DeleteVolume(deleter *portworxVolumeDeleter) error // Attach a volume @@ -217,6 +236,8 @@ type portworxManager interface { MountVolume(mounter *portworxVolumeMounter, mountDir string) error // Unmount a volume UnmountVolume(unmounter *portworxVolumeUnmounter, mountDir string) error + // Resize a volume + ResizeVolume(spec *volume.Spec, newSize resource.Quantity, host volume.VolumeHost) error } // portworxVolume volumes are portworx block devices @@ -357,12 +378,16 @@ type portworxVolumeProvisioner struct { var _ volume.Provisioner = &portworxVolumeProvisioner{} -func (c *portworxVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *portworxVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } - volumeID, sizeGB, labels, err := c.manager.CreateVolume(c) + if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName()) + } + + volumeID, sizeGiB, labels, err := c.manager.CreateVolume(c) if err != nil { return nil, err } @@ -379,7 +404,7 @@ func (c *portworxVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { PersistentVolumeReclaimPolicy: c.options.PersistentVolumeReclaimPolicy, AccessModes: c.options.PVC.Spec.AccessModes, Capacity: v1.ResourceList{ - v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)), + v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGiB)), }, PersistentVolumeSource: v1.PersistentVolumeSource{ PortworxVolume: &v1.PortworxVolumeSource{ diff --git a/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_test.go b/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_test.go index 074f25c47..72be62500 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_test.go @@ -23,6 +23,7 @@ import ( "testing" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/types" utiltesting "k8s.io/client-go/util/testing" "k8s.io/kubernetes/pkg/util/mount" @@ -106,7 +107,7 @@ func (fake *fakePortworxManager) UnmountVolume(c *portworxVolumeUnmounter, mount return nil } -func (fake *fakePortworxManager) CreateVolume(c *portworxVolumeProvisioner) (volumeID string, volumeSizeGB int, labels map[string]string, err error) { +func (fake *fakePortworxManager) CreateVolume(c *portworxVolumeProvisioner) (volumeID string, volumeSizeGB int64, labels map[string]string, err error) { labels = make(map[string]string) labels["fakeportworxmanager"] = "yes" return PortworxTestVolume, 100, labels, nil @@ -119,6 +120,10 @@ func (fake *fakePortworxManager) DeleteVolume(cd *portworxVolumeDeleter) error { return nil } +func (fake *fakePortworxManager) ResizeVolume(spec *volume.Spec, newSize resource.Quantity, volumeHost volume.VolumeHost) error { + return nil +} + func TestPlugin(t *testing.T) { tmpDir, err := utiltesting.MkTmpdir("portworxVolumeTest") if err != nil { @@ -199,7 +204,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Errorf("Error creating a new provisioner:%v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_util.go b/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_util.go index 5faed5f1f..22003983a 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_util.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_util.go @@ -17,6 +17,8 @@ limitations under the License. package portworx import ( + "fmt" + "github.com/golang/glog" osdapi "github.com/libopenstorage/openstorage/api" osdclient "github.com/libopenstorage/openstorage/api/client" @@ -24,6 +26,7 @@ import ( osdspec "github.com/libopenstorage/openstorage/api/spec" volumeapi "github.com/libopenstorage/openstorage/volume" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/volume" @@ -45,7 +48,7 @@ type PortworxVolumeUtil struct { } // CreateVolume creates a Portworx volume. -func (util *PortworxVolumeUtil) CreateVolume(p *portworxVolumeProvisioner) (string, int, map[string]string, error) { +func (util *PortworxVolumeUtil) CreateVolume(p *portworxVolumeProvisioner) (string, int64, map[string]string, error) { driver, err := util.getPortworxDriver(p.plugin.host, false /*localOnly*/) if err != nil || driver == nil { glog.Errorf("Failed to get portworx driver. Err: %v", err) @@ -55,8 +58,8 @@ func (util *PortworxVolumeUtil) CreateVolume(p *portworxVolumeProvisioner) (stri glog.Infof("Creating Portworx volume for PVC: %v", p.options.PVC.Name) capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] - // Portworx Volumes are specified in GB - requestGB := int(volutil.RoundUpSize(capacity.Value(), 1024*1024*1024)) + // Portworx Volumes are specified in GiB + requestGiB := volutil.RoundUpToGiB(capacity) // Perform a best-effort parsing of parameters. Portworx 1.2.9 and later parses volume parameters from // spec.VolumeLabels. So even if below SpecFromOpts() fails to parse certain parameters or @@ -71,7 +74,8 @@ func (util *PortworxVolumeUtil) CreateVolume(p *portworxVolumeProvisioner) (stri // Pass all parameters as volume labels for Portworx server-side processing. spec.VolumeLabels = p.options.Parameters // Update the requested size in the spec - spec.Size = uint64(requestGB * 1024 * 1024 * 1024) + spec.Size = uint64(requestGiB * volutil.GIB) + // Change the Portworx Volume name to PV name if locator == nil { locator = &osdapi.VolumeLocator{ @@ -99,7 +103,7 @@ func (util *PortworxVolumeUtil) CreateVolume(p *portworxVolumeProvisioner) (stri } glog.Infof("Successfully created Portworx volume for PVC: %v", p.options.PVC.Name) - return volumeID, requestGB, nil, err + return volumeID, requestGiB, nil, err } // DeleteVolume deletes a Portworx volume @@ -182,6 +186,55 @@ func (util *PortworxVolumeUtil) UnmountVolume(u *portworxVolumeUnmounter, mountP return nil } +func (util *PortworxVolumeUtil) ResizeVolume(spec *volume.Spec, newSize resource.Quantity, volumeHost volume.VolumeHost) error { + driver, err := util.getPortworxDriver(volumeHost, false /*localOnly*/) + if err != nil || driver == nil { + glog.Errorf("Failed to get portworx driver. Err: %v", err) + return err + } + + vols, err := driver.Inspect([]string{spec.Name()}) + if err != nil { + return err + } + + if len(vols) != 1 { + return fmt.Errorf("failed to inspect Portworx volume: %s. Found: %d volumes", spec.Name(), len(vols)) + } + + vol := vols[0] + newSizeInBytes := uint64(volutil.RoundUpToGiB(newSize) * volutil.GIB) + if vol.Spec.Size >= newSizeInBytes { + glog.Infof("Portworx volume: %s already at size: %d greater than or equal to new "+ + "requested size: %d. Skipping resize.", vol.Spec.Size, newSizeInBytes) + return nil + } + + vol.Spec.Size = newSizeInBytes + err = driver.Set(spec.Name(), vol.Locator, vol.Spec) + if err != nil { + return err + } + + // check if the volume's size actually got updated + vols, err = driver.Inspect([]string{spec.Name()}) + if err != nil { + return err + } + + if len(vols) != 1 { + return fmt.Errorf("failed to inspect resized Portworx volume: %s. Found: %d volumes", spec.Name(), len(vols)) + } + + updatedVol := vols[0] + if updatedVol.Spec.Size < vol.Spec.Size { + return fmt.Errorf("Portworx volume: %s doesn't match expected size after resize. expected:%v actual:%v", + spec.Name(), vol.Spec.Size, updatedVol.Spec.Size) + } + + return nil +} + func isClientValid(client *osdclient.Client) (bool, error) { if client == nil { return false, nil diff --git a/vendor/k8s.io/kubernetes/pkg/volume/projected/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/projected/BUILD index a8d0ce634..2f3b388d4 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/projected/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/projected/BUILD @@ -28,6 +28,7 @@ go_library( srcs = ["projected.go"], importpath = "k8s.io/kubernetes/pkg/volume/projected", deps = [ + "//pkg/features:go_default_library", "//pkg/util/strings:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/configmap:go_default_library", @@ -35,11 +36,13 @@ go_library( "//pkg/volume/secret:go_default_library", "//pkg/volume/util:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/projected/projected.go b/vendor/k8s.io/kubernetes/pkg/volume/projected/projected.go index e75f10af5..c17ba4c19 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/projected/projected.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/projected/projected.go @@ -21,18 +21,22 @@ import ( "sort" "strings" - "github.com/golang/glog" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" utilstrings "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/configmap" "k8s.io/kubernetes/pkg/volume/downwardapi" "k8s.io/kubernetes/pkg/volume/secret" volumeutil "k8s.io/kubernetes/pkg/volume/util" + + "github.com/golang/glog" ) // ProbeVolumePlugins is the entry point for plugin detection in a package. @@ -45,9 +49,10 @@ const ( ) type projectedPlugin struct { - host volume.VolumeHost - getSecret func(namespace, name string) (*v1.Secret, error) - getConfigMap func(namespace, name string) (*v1.ConfigMap, error) + host volume.VolumeHost + getSecret func(namespace, name string) (*v1.Secret, error) + getConfigMap func(namespace, name string) (*v1.ConfigMap, error) + getServiceAccountToken func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) } var _ volume.VolumePlugin = &projectedPlugin{} @@ -70,6 +75,7 @@ func (plugin *projectedPlugin) Init(host volume.VolumeHost) error { plugin.host = host plugin.getSecret = host.GetSecretFunc() plugin.getConfigMap = host.GetConfigMapFunc() + plugin.getServiceAccountToken = host.GetServiceAccountTokenFunc() return nil } @@ -188,16 +194,17 @@ func (s *projectedVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { if err != nil { return err } - if err := wrapped.SetUpAt(dir, fsGroup); err != nil { + + data, err := s.collectData() + if err != nil { + glog.Errorf("Error preparing data for projected volume %v for pod %v/%v: %s", s.volName, s.pod.Namespace, s.pod.Name, err.Error()) return err } - if err := volumeutil.MakeNestedMountpoints(s.volName, dir, *s.pod); err != nil { + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { return err } - data, err := s.collectData() - if err != nil { - glog.Errorf("Error preparing data for projected volume %v for pod %v/%v: %s", s.volName, s.pod.Namespace, s.pod.Name, err.Error()) + if err := volumeutil.MakeNestedMountpoints(s.volName, dir, *s.pod); err != nil { return err } @@ -219,7 +226,6 @@ func (s *projectedVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Error applying volume ownership settings for group: %v", fsGroup) return err } - return nil } @@ -236,7 +242,8 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec errlist := []error{} payload := make(map[string]volumeutil.FileProjection) for _, source := range s.source.Sources { - if source.Secret != nil { + switch { + case source.Secret != nil: optional := source.Secret.Optional != nil && *source.Secret.Optional secretapi, err := s.plugin.getSecret(s.pod.Namespace, source.Secret.Name) if err != nil { @@ -261,7 +268,7 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec for k, v := range secretPayload { payload[k] = v } - } else if source.ConfigMap != nil { + case source.ConfigMap != nil: optional := source.ConfigMap.Optional != nil && *source.ConfigMap.Optional configMap, err := s.plugin.getConfigMap(s.pod.Namespace, source.ConfigMap.Name) if err != nil { @@ -286,7 +293,7 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec for k, v := range configMapPayload { payload[k] = v } - } else if source.DownwardAPI != nil { + case source.DownwardAPI != nil: downwardAPIPayload, err := downwardapi.CollectData(source.DownwardAPI.Items, s.pod, s.plugin.host, s.source.DefaultMode) if err != nil { errlist = append(errlist, err) @@ -295,6 +302,34 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec for k, v := range downwardAPIPayload { payload[k] = v } + case source.ServiceAccountToken != nil: + if !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequestProjection) { + errlist = append(errlist, fmt.Errorf("pod request ServiceAccountToken projection but the TokenRequestProjection feature was not enabled")) + continue + } + tp := source.ServiceAccountToken + tr, err := s.plugin.getServiceAccountToken(s.pod.Namespace, s.pod.Spec.ServiceAccountName, &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + Audiences: []string{ + tp.Audience, + }, + ExpirationSeconds: tp.ExpirationSeconds, + BoundObjectRef: &authenticationv1.BoundObjectReference{ + APIVersion: "v1", + Kind: "Pod", + Name: s.pod.Name, + UID: s.pod.UID, + }, + }, + }) + if err != nil { + errlist = append(errlist, err) + continue + } + payload[tp.Path] = volumeutil.FileProjection{ + Data: []byte(tr.Status.Token), + Mode: 0600, + } } } return payload, utilerrors.NewAggregate(errlist) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/quobyte/quobyte.go b/vendor/k8s.io/kubernetes/pkg/volume/quobyte/quobyte.go index 0a5990b29..524a49248 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/quobyte/quobyte.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/quobyte/quobyte.go @@ -354,11 +354,15 @@ type quobyteVolumeProvisioner struct { options volume.VolumeOptions } -func (provisioner *quobyteVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (provisioner *quobyteVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(provisioner.plugin.GetAccessModes(), provisioner.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", provisioner.options.PVC.Spec.AccessModes, provisioner.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(provisioner.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", provisioner.plugin.GetPluginName()) + } + if provisioner.options.PVC.Spec.Selector != nil { return nil, fmt.Errorf("claim Selector is not supported") } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/quobyte/quobyte_util.go b/vendor/k8s.io/kubernetes/pkg/volume/quobyte/quobyte_util.go index c1deb552a..fa9bd54a8 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/quobyte/quobyte_util.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/quobyte/quobyte_util.go @@ -18,7 +18,8 @@ package quobyte import ( "net" - "path" + "os" + "path/filepath" "strings" "k8s.io/api/core/v1" @@ -101,7 +102,7 @@ func (mounter *quobyteMounter) pluginDirIsMounted(pluginDir string) (bool, error } func (mounter *quobyteMounter) correctTraillingSlash(regStr string) string { - return path.Clean(regStr) + "/" + return filepath.Clean(regStr) + string(os.PathSeparator) } func validateRegistry(registry string) bool { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/rbd/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/rbd/BUILD index 65042418c..e6b7fe8ae 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/rbd/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/rbd/BUILD @@ -17,6 +17,7 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/volume/rbd", deps = [ + "//pkg/features:go_default_library", "//pkg/util/file:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/node:go_default_library", @@ -33,6 +34,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_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", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/rbd/attacher.go b/vendor/k8s.io/kubernetes/pkg/volume/rbd/attacher.go index 2e5960092..9a74a608c 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/rbd/attacher.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/rbd/attacher.go @@ -189,21 +189,17 @@ func (detacher *rbdDetacher) UnmountDevice(deviceMountPath string) error { glog.Warningf("Warning: Unmount skipped because path does not exist: %v", deviceMountPath) return nil } - devicePath, cnt, err := mount.GetDeviceNameFromMount(detacher.mounter, deviceMountPath) + devicePath, _, err := mount.GetDeviceNameFromMount(detacher.mounter, deviceMountPath) if err != nil { return err } - if cnt > 1 { - return fmt.Errorf("rbd: more than 1 reference counts at %s", deviceMountPath) - } - if cnt == 1 { - // Unmount the device from the device mount point. - glog.V(4).Infof("rbd: unmouting device mountpoint %s", deviceMountPath) - if err = detacher.mounter.Unmount(deviceMountPath); err != nil { - return err - } - glog.V(3).Infof("rbd: successfully umount device mountpath %s", deviceMountPath) + // Unmount the device from the device mount point. + glog.V(4).Infof("rbd: unmouting device mountpoint %s", deviceMountPath) + if err = detacher.mounter.Unmount(deviceMountPath); err != nil { + return err } + glog.V(3).Infof("rbd: successfully umount device mountpath %s", deviceMountPath) + glog.V(4).Infof("rbd: detaching device %s", devicePath) err = detacher.manager.DetachDisk(detacher.plugin, deviceMountPath, devicePath) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd.go b/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd.go index ffc5c03c1..89b9cd045 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd.go @@ -30,7 +30,9 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" + utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" @@ -232,6 +234,10 @@ func (plugin *rbdPlugin) createMounterFromVolumeSpecAndPod(spec *volume.Spec, po if err != nil { return nil, err } + ams, err := getVolumeAccessModes(spec) + if err != nil { + return nil, err + } secretName, secretNs, err := getSecretNameAndNamespace(spec, pod.Namespace) if err != nil { @@ -255,12 +261,13 @@ func (plugin *rbdPlugin) createMounterFromVolumeSpecAndPod(spec *volume.Spec, po } return &rbdMounter{ - rbd: newRBD("", spec.Name(), img, pool, ro, plugin, &RBDUtil{}), - Mon: mon, - Id: id, - Keyring: keyring, - Secret: secret, - fsType: fstype, + rbd: newRBD("", spec.Name(), img, pool, ro, plugin, &RBDUtil{}), + Mon: mon, + Id: id, + Keyring: keyring, + Secret: secret, + fsType: fstype, + accessModes: ams, }, nil } @@ -319,6 +326,10 @@ func (plugin *rbdPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, if err != nil { return nil, err } + ams, err := getVolumeAccessModes(spec) + if err != nil { + return nil, err + } return &rbdMounter{ rbd: newRBD(podUID, spec.Name(), img, pool, ro, plugin, manager), @@ -328,6 +339,7 @@ func (plugin *rbdPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, Secret: secret, fsType: fstype, mountOptions: volutil.MountOptionFromSpec(spec), + accessModes: ams, }, nil } @@ -434,7 +446,6 @@ func (plugin *rbdPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ uid = pod.UID } secret := "" - // var err error if pod != nil { secretName, secretNs, err := getSecretNameAndNamespace(spec, pod.Namespace) if err != nil { @@ -509,7 +520,7 @@ func (plugin *rbdPlugin) newUnmapperInternal(volName string, podUID types.UID, m } func (plugin *rbdPlugin) getDeviceNameFromOldMountPath(mounter mount.Interface, mountPath string) (string, error) { - refs, err := mount.GetMountRefsByDev(mounter, mountPath) + refs, err := mounter.GetMountRefs(mountPath) if err != nil { return "", err } @@ -568,7 +579,7 @@ type rbdVolumeProvisioner struct { var _ volume.Provisioner = &rbdVolumeProvisioner{} -func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (r *rbdVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !volutil.AccessModesContainedInAll(r.plugin.GetAccessModes(), r.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", r.options.PVC.Spec.AccessModes, r.plugin.GetAccessModes()) } @@ -590,9 +601,7 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { switch dstrings.ToLower(k) { case "monitors": arr := dstrings.Split(v, ",") - for _, m := range arr { - r.Mon = append(r.Mon, m) - } + r.Mon = append(r.Mon, arr...) case "adminid": r.adminId = v case "adminsecretname": @@ -691,6 +700,11 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dMi", sizeMB)), } pv.Spec.MountOptions = r.options.MountOptions + + if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + pv.Spec.VolumeMode = r.options.PVC.Spec.VolumeMode + } + return pv, nil } @@ -767,6 +781,7 @@ type rbdMounter struct { mountOptions []string imageFormat string imageFeatures []string + accessModes []v1.PersistentVolumeAccessMode } var _ volume.Mounter = &rbdMounter{} @@ -863,8 +878,11 @@ func (rbd *rbdDiskMapper) SetUpDevice() (string, error) { return "", nil } +func (rbd *rbdDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error { + return volutil.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID) +} + func (rbd *rbd) rbdGlobalMapPath(spec *volume.Spec) (string, error) { - var err error mon, err := getVolumeSourceMonitors(spec) if err != nil { return "", err @@ -940,14 +958,20 @@ func (rbd *rbdDiskUnmapper) TearDownDevice(mapPath, _ string) error { blkUtil := volumepathhandler.NewBlockVolumePathHandler() loop, err := volumepathhandler.BlockVolumePathHandler.GetLoopDevice(blkUtil, device) if err != nil { - return fmt.Errorf("rbd: failed to get loopback for device: %v, err: %v", device, err) - } - // Remove loop device before detaching volume since volume detach operation gets busy if volume is opened by loopback. - err = volumepathhandler.BlockVolumePathHandler.RemoveLoopDevice(blkUtil, loop) - if err != nil { - return fmt.Errorf("rbd: failed to remove loopback :%v, err: %v", loop, err) + if err.Error() != volumepathhandler.ErrDeviceNotFound { + return fmt.Errorf("rbd: failed to get loopback for device: %v, err: %v", device, err) + } + glog.Warning("rbd: loopback for device: % not found", device) + } else { + if len(loop) != 0 { + // Remove loop device before detaching volume since volume detach operation gets busy if volume is opened by loopback. + err = volumepathhandler.BlockVolumePathHandler.RemoveLoopDevice(blkUtil, loop) + if err != nil { + return fmt.Errorf("rbd: failed to remove loopback :%v, err: %v", loop, err) + } + glog.V(4).Infof("rbd: successfully removed loop device: %s", loop) + } } - glog.V(4).Infof("rbd: successfully removed loop device: %s", loop) err = rbd.manager.DetachBlockDisk(*rbd, mapPath) if err != nil { @@ -1043,6 +1067,19 @@ func getVolumeSourceReadOnly(spec *volume.Spec) (bool, error) { return false, fmt.Errorf("Spec does not reference a RBD volume type") } +func getVolumeAccessModes(spec *volume.Spec) ([]v1.PersistentVolumeAccessMode, error) { + // Only PersistentVolumeSpec has AccessModes + if spec.PersistentVolume != nil { + if spec.PersistentVolume.Spec.RBD != nil { + return spec.PersistentVolume.Spec.AccessModes, nil + } else { + return nil, fmt.Errorf("Spec does not reference a RBD volume type") + } + } + + return nil, nil +} + func parsePodSecret(pod *v1.Pod, secretName string, kubeClient clientset.Interface) (string, error) { secret, err := volutil.GetSecretForPod(pod, secretName, kubeClient) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd_test.go b/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd_test.go index b644fe757..4ab32f6b5 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd_test.go @@ -21,6 +21,7 @@ import ( "os" "path/filepath" "reflect" + "runtime" "strings" "sync" "testing" @@ -357,6 +358,7 @@ func TestPlugin(t *testing.T) { FSType: "ext4", }, }, + AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}, }, }, false), root: tmpDir, @@ -532,6 +534,9 @@ func TestGetDeviceMountPath(t *testing.T) { // https://github.com/kubernetes/kubernetes/issues/57744 func TestConstructVolumeSpec(t *testing.T) { + if runtime.GOOS == "darwin" { + t.Skipf("TestConstructVolumeSpec is not supported on GOOS=%s", runtime.GOOS) + } tmpDir, err := utiltesting.MkTmpdir("rbd_test") if err != nil { t.Fatalf("error creating temp dir: %v", err) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd_util.go b/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd_util.go index 4267f741c..186088677 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd_util.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/rbd/rbd_util.go @@ -346,6 +346,8 @@ func (util *RBDUtil) rbdUnlock(b rbdMounter) error { cmd, err = b.exec.Run("rbd", args...) if err == nil { glog.V(4).Infof("rbd: successfully remove lock (locker_id: %s) on image: %s/%s with id %s mon %s", lock_id, b.Pool, b.Image, b.Id, mon) + } else { + glog.Warningf("rbd: failed to remove lock (lock_id: %s) on image: %s/%s with id %s mon %s: %v", lock_id, b.Pool, b.Image, b.Id, mon, err) } } @@ -388,12 +390,22 @@ func (util *RBDUtil) AttachDisk(b rbdMounter) (string, error) { Factor: rbdImageWatcherFactor, Steps: rbdImageWatcherSteps, } + needValidUsed := true + // If accessModes contain ReadOnlyMany, we don't need check rbd status of being used. + if b.accessModes != nil { + for _, v := range b.accessModes { + if v != v1.ReadWriteOnce { + needValidUsed = false + break + } + } + } err := wait.ExponentialBackoff(backoff, func() (bool, error) { used, rbdOutput, err := util.rbdStatus(&b) if err != nil { return false, fmt.Errorf("fail to check rbd image status with: (%v), rbd output: (%s)", err, rbdOutput) } - return !used, nil + return !needValidUsed || !used, nil }) // Return error if rbd image has not become available for the specified timeout. if err == wait.ErrWaitTimeout { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_client.go b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_client.go index b64d03482..d789bfd6c 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_client.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_client.go @@ -339,10 +339,14 @@ func (c *sioClient) getGuid() (string, error) { func (c *sioClient) getSioDiskPaths() ([]os.FileInfo, error) { files, err := ioutil.ReadDir(sioDiskIDPath) if err != nil { - glog.Error(log("failed to ReadDir %s: %v", sioDiskIDPath, err)) - return nil, err + if os.IsNotExist(err) { + // sioDiskIDPath may not exist yet which is fine + return []os.FileInfo{}, nil + } else { + glog.Error(log("failed to ReadDir %s: %v", sioDiskIDPath, err)) + return nil, err + } } - result := []os.FileInfo{} for _, file := range files { if c.diskRegex.MatchString(file.Name()) { @@ -417,7 +421,7 @@ func (c *sioClient) WaitForAttachedDevice(token string) (string, error) { return "", err } go func() { - glog.V(4).Infof(log("waiting for volume %s to be mapped/attached", token)) + glog.V(4).Info(log("waiting for volume %s to be mapped/attached", token)) }() if path, ok := devMap[token]; ok { glog.V(4).Info(log("device %s mapped to vol %s", path, token)) @@ -451,7 +455,7 @@ func (c *sioClient) WaitForDetachedDevice(token string) error { return err } go func() { - glog.V(4).Infof(log("waiting for volume %s to be unmapped/detached", token)) + glog.V(4).Info(log("waiting for volume %s to be unmapped/detached", token)) }() // cant find vol id, then ok. if _, ok := devMap[token]; !ok { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_plugin.go b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_plugin.go index babd840c6..6eb91b79b 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_plugin.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_plugin.go @@ -27,7 +27,6 @@ import ( ) const ( - sioName = "scaleio" sioPluginName = "kubernetes.io/scaleio" sioConfigFileName = "sioconf.dat" ) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_util_test.go b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_util_test.go index 4be4bd75f..0733adb6e 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_util_test.go @@ -159,11 +159,11 @@ func TestUtilSaveConfig(t *testing.T) { confKey.sslEnabled: "false", } if err := saveConfig(config, data); err != nil { - t.Fatal("failed while saving data", err) + t.Fatalf("failed while saving data: %v", err) } file, err := os.Open(config) if err != nil { - t.Fatal("failed to open conf file: ", file) + t.Fatalf("failed to open conf file %s: %v", config, err) } defer file.Close() dataRcvd := map[string]string{} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_volume.go b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_volume.go index b7f027011..0f10dfa1e 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_volume.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_volume.go @@ -252,13 +252,17 @@ func (v *sioVolume) Delete() error { // ************************ var _ volume.Provisioner = &sioVolume{} -func (v *sioVolume) Provision() (*api.PersistentVolume, error) { +func (v *sioVolume) Provision(selectedNode *api.Node, allowedTopologies []api.TopologySelectorTerm) (*api.PersistentVolume, error) { glog.V(4).Info(log("attempting to dynamically provision pvc %v", v.options.PVC.Name)) if !util.AccessModesContainedInAll(v.plugin.GetAccessModes(), v.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", v.options.PVC.Spec.AccessModes, v.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(v.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", v.plugin.GetPluginName()) + } + // setup volume attrributes genName := v.generateName("k8svol", 11) var oneGig int64 = 1024 * 1024 * 1024 diff --git a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_volume_test.go b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_volume_test.go index bdc13045d..8d725af86 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_volume_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/scaleio/sio_volume_test.go @@ -296,7 +296,7 @@ func TestVolumeProvisioner(t *testing.T) { } sioVol.sioMgr.client = sio - spec, err := provisioner.Provision() + spec, err := provisioner.Provision(nil, nil) if err != nil { t.Fatalf("call to Provision() failed: %v", err) } @@ -467,7 +467,7 @@ func TestVolumeProvisionerWithZeroCapacity(t *testing.T) { } sioVol.sioMgr.client = sio - _, err = provisioner.Provision() + _, err = provisioner.Provision(nil, nil) if err == nil { t.Fatalf("call to Provision() should fail with invalid capacity") } @@ -516,7 +516,7 @@ func TestVolumeProvisionerWithSecretNamespace(t *testing.T) { } sioVol.sioMgr.client = sio - spec, err := sioVol.Provision() + spec, err := sioVol.Provision(nil, nil) if err != nil { t.Fatalf("call to Provision() failed: %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/secret/secret.go b/vendor/k8s.io/kubernetes/pkg/volume/secret/secret.go index c8146d844..3ab27c77c 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/secret/secret.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/secret/secret.go @@ -190,12 +190,6 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { if err != nil { return err } - if err := wrapped.SetUpAt(dir, fsGroup); err != nil { - return err - } - if err := volumeutil.MakeNestedMountpoints(b.volName, dir, b.pod); err != nil { - return err - } optional := b.source.Optional != nil && *b.source.Optional secret, err := b.getSecret(b.pod.Namespace, b.source.SecretName) @@ -212,6 +206,13 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { } } + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { + return err + } + if err := volumeutil.MakeNestedMountpoints(b.volName, dir, b.pod); err != nil { + return err + } + totalBytes := totalSecretBytes(secret) glog.V(3).Infof("Received secret %v/%v containing (%v) pieces of data, %v total bytes", b.pod.Namespace, @@ -242,7 +243,6 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Error applying volume ownership settings for group: %v", fsGroup) return err } - return nil } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos.go b/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos.go index a814c438d..8b5c2311c 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos.go @@ -560,10 +560,13 @@ type storageosProvisioner struct { var _ volume.Provisioner = &storageosProvisioner{} -func (c *storageosProvisioner) Provision() (*v1.PersistentVolume, error) { +func (c *storageosProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName()) + } var adminSecretName, adminSecretNamespace string diff --git a/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos_test.go b/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos_test.go index 9d03ab235..a5732fff7 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos_test.go @@ -269,7 +269,7 @@ func TestPlugin(t *testing.T) { t.Errorf("newProvisionerInternal() failed: %v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Fatalf("Provision() failed: %v", err) } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos_util_test.go b/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos_util_test.go index bff34ca7d..be912b64d 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos_util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/storageos/storageos_util_test.go @@ -184,9 +184,9 @@ func TestCreateVolume(t *testing.T) { if len(vol.Labels) == 0 { t.Error("CreateVolume() Labels are empty") } else { + var val string + var ok bool for k, v := range labels { - var val string - var ok bool if val, ok = vol.Labels[k]; !ok { t.Errorf("CreateVolume() Label %s not set", k) } @@ -194,8 +194,6 @@ func TestCreateVolume(t *testing.T) { t.Errorf("CreateVolume() returned unexpected Label value %s", val) } } - var val string - var ok bool if val, ok = vol.Labels["labelfromapi"]; !ok { t.Error("CreateVolume() Label from api not set") } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/testing/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/testing/BUILD index f434e5b15..6cbd8230c 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/testing/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/testing/BUILD @@ -22,12 +22,14 @@ go_library( "//pkg/volume/util/recyclerclient:go_default_library", "//pkg/volume/util/volumepathhandler:go_default_library", "//vendor/github.com/stretchr/testify/mock:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/core/v1: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/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/client-go/util/testing:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/testing/testing.go b/vendor/k8s.io/kubernetes/pkg/volume/testing/testing.go index 9e5ae2cd1..9192dd0e9 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/testing/testing.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/testing/testing.go @@ -27,12 +27,14 @@ import ( "testing" "time" + authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/uuid" clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/record" utiltesting "k8s.io/client-go/util/testing" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/util/io" @@ -94,6 +96,10 @@ func (f *fakeVolumeHost) GetVolumeDevicePluginDir(pluginName string) string { return path.Join(f.rootDir, "plugins", pluginName, "volumeDevices") } +func (f *fakeVolumeHost) GetPodsDir() string { + return path.Join(f.rootDir, "pods") +} + func (f *fakeVolumeHost) GetPodVolumeDir(podUID types.UID, pluginName, volumeName string) string { return path.Join(f.rootDir, "pods", string(podUID), "volumes", pluginName, volumeName) } @@ -178,6 +184,12 @@ func (f *fakeVolumeHost) GetConfigMapFunc() func(namespace, name string) (*v1.Co } } +func (f *fakeVolumeHost) GetServiceAccountTokenFunc() func(string, string, *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) { + return f.kubeClient.CoreV1().ServiceAccounts(namespace).CreateToken(name, tr) + } +} + func (f *fakeVolumeHost) GetNodeLabels() (map[string]string, error) { if f.nodeLabels == nil { f.nodeLabels = map[string]string{"test-label": "test-value"} @@ -189,6 +201,10 @@ func (f *fakeVolumeHost) GetNodeName() types.NodeName { return types.NodeName(f.nodeName) } +func (f *fakeVolumeHost) GetEventRecorder() record.EventRecorder { + return nil +} + func ProbeVolumePlugins(config VolumeConfig) []VolumePlugin { if _, ok := config.OtherAttributes["fake-property"]; ok { return []VolumePlugin{ @@ -250,7 +266,17 @@ func (plugin *FakeVolumePlugin) GetPluginName() string { } func (plugin *FakeVolumePlugin) GetVolumeName(spec *Spec) (string, error) { - return spec.Name(), nil + var volumeName string + if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil { + volumeName = spec.Volume.GCEPersistentDisk.PDName + } else if spec.PersistentVolume != nil && + spec.PersistentVolume.Spec.GCEPersistentDisk != nil { + volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName + } + if volumeName == "" { + volumeName = spec.Name() + } + return volumeName, nil } func (plugin *FakeVolumePlugin) CanSupport(spec *Spec) bool { @@ -420,6 +446,15 @@ func (plugin *FakeVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]st return []string{}, nil } +// Expandable volume support +func (plugin *FakeVolumePlugin) ExpandVolumeDevice(spec *Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) { + return resource.Quantity{}, nil +} + +func (plugin *FakeVolumePlugin) RequiresFSResize() bool { + return true +} + type FakeFileVolumePlugin struct { } @@ -484,6 +519,7 @@ type FakeVolume struct { GetDeviceMountPathCallCount int SetUpDeviceCallCount int TearDownDeviceCallCount int + MapDeviceCallCount int GlobalMapPathCallCount int PodDeviceMapPathCallCount int } @@ -614,6 +650,21 @@ func (fv *FakeVolume) GetTearDownDeviceCallCount() int { return fv.TearDownDeviceCallCount } +// Block volume support +func (fv *FakeVolume) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, pod types.UID) error { + fv.Lock() + defer fv.Unlock() + fv.MapDeviceCallCount++ + return nil +} + +// Block volume support +func (fv *FakeVolume) GetMapDeviceCallCount() int { + fv.RLock() + defer fv.RUnlock() + return fv.MapDeviceCallCount +} + func (fv *FakeVolume) Attach(spec *Spec, nodeName types.NodeName) (string, error) { fv.Lock() defer fv.Unlock() @@ -705,7 +756,7 @@ type FakeProvisioner struct { Host VolumeHost } -func (fc *FakeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (fc *FakeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { fullpath := fmt.Sprintf("/tmp/hostpath_pv/%s", uuid.NewUUID()) pv := &v1.PersistentVolume{ @@ -1093,6 +1144,24 @@ func VerifyGetPodDeviceMapPathCallCount( expectedPodDeviceMapPathCallCount) } +// VerifyGetMapDeviceCallCount ensures that at least one of the Mappers for this +// plugin has the expectedMapDeviceCallCount number of calls. Otherwise it +// returns an error. +func VerifyGetMapDeviceCallCount( + expectedMapDeviceCallCount int, + fakeVolumePlugin *FakeVolumePlugin) error { + for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() { + actualCallCount := mapper.GetMapDeviceCallCount() + if actualCallCount >= expectedMapDeviceCallCount { + return nil + } + } + + return fmt.Errorf( + "No Mapper have expected MapdDeviceCallCount. Expected: <%v>.", + expectedMapDeviceCallCount) +} + // GetTestVolumePluginMgr creates, initializes, and returns a test volume plugin // manager and fake volume plugin using a fake volume host. func GetTestVolumePluginMgr( diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/util/BUILD index 4430a3131..08d5c3ef0 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/BUILD @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "atomic_writer.go", + "attach_limit.go", "device_util.go", "doc.go", "error.go", @@ -59,6 +60,7 @@ go_library( "//pkg/util/mount:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/util/types:go_default_library", + "//pkg/volume/util/volumepathhandler:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -91,7 +93,6 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core/install:go_default_library", - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/slice:go_default_library", "//pkg/volume:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/atomic_writer_test.go b/vendor/k8s.io/kubernetes/pkg/volume/util/atomic_writer_test.go index 4f8869b1a..6d391ac2b 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/atomic_writer_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/atomic_writer_test.go @@ -804,7 +804,7 @@ func checkVolumeContents(targetDir, tcName string, payload map[string]FileProjec cleanPathPayload := make(map[string]FileProjection, len(payload)) for k, v := range payload { - cleanPathPayload[path.Clean(k)] = v + cleanPathPayload[filepath.Clean(k)] = v } if !reflect.DeepEqual(cleanPathPayload, observedPayload) { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/attach_limit.go b/vendor/k8s.io/kubernetes/pkg/volume/util/attach_limit.go new file mode 100644 index 000000000..610f5f5b2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/attach_limit.go @@ -0,0 +1,29 @@ +/* +Copyright 2018 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 + +// This file is a common place holder for volume limit utility constants +// shared between volume package and scheduler + +const ( + // EBSVolumeLimitKey resource name that will store volume limits for EBS + EBSVolumeLimitKey = "attachable-volumes-aws-ebs" + // AzureVolumeLimitKey stores resource name that will store volume limits for Azure + AzureVolumeLimitKey = "attachable-volumes-azure-disk" + // GCEVolumeLimitKey stores resource name that will store volume limits for GCE node + GCEVolumeLimitKey = "attachable-volumes-gce-pd" +) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/fs/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/util/fs/BUILD index 205ddaaae..0e9be3016 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/fs/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/fs/BUILD @@ -34,7 +34,7 @@ go_library( "fs_unsupported.go", ], "@io_bazel_rules_go//go/platform:windows": [ - "fs_unsupported.go", + "fs_windows.go", ], "//conditions:default": [], }), @@ -74,6 +74,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", ], "@io_bazel_rules_go//go/platform:windows": [ + "//vendor/golang.org/x/sys/windows:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", ], "//conditions:default": [], diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs.go b/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs.go index bbb4b0105..a80a167ee 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs.go @@ -54,7 +54,8 @@ func FsInfo(path string) (int64, int64, int64, int64, int64, int64, error) { return available, capacity, usage, inodes, inodesFree, inodesUsed, nil } -func Du(path string) (*resource.Quantity, error) { +// DiskUsage gets disk usage of specified path. +func DiskUsage(path string) (*resource.Quantity, error) { // Uses the same niceness level as cadvisor.fs does when running du // Uses -B 1 to always scale to a blocksize of 1 byte out, err := exec.Command("nice", "-n", "19", "du", "-s", "-B", "1", path).CombinedOutput() diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs_unsupported.go b/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs_unsupported.go index da41fc8ee..340b4fdc2 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!darwin +// +build !linux,!darwin,!windows /* Copyright 2014 The Kubernetes Authors. @@ -29,7 +29,8 @@ func FsInfo(path string) (int64, int64, int64, int64, int64, int64, error) { return 0, 0, 0, 0, 0, 0, fmt.Errorf("FsInfo not supported for this build.") } -func Du(path string) (*resource.Quantity, error) { +// DiskUsage gets disk usage of specified path. +func DiskUsage(path string) (*resource.Quantity, error) { return nil, fmt.Errorf("Du not supported for this build.") } diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs_windows.go b/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs_windows.go new file mode 100644 index 000000000..ea8c4784a --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/fs/fs_windows.go @@ -0,0 +1,77 @@ +// +build windows + +/* +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 fs + +import ( + "fmt" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" + + "k8s.io/apimachinery/pkg/api/resource" +) + +var ( + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW") +) + +// FSInfo returns (available bytes, byte capacity, byte usage, total inodes, inodes free, inode usage, error) +// for the filesystem that path resides upon. +func FsInfo(path string) (int64, int64, int64, int64, int64, int64, error) { + var freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes int64 + var err error + + ret, _, err := syscall.Syscall6( + procGetDiskFreeSpaceEx.Addr(), + 4, + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), + uintptr(unsafe.Pointer(&freeBytesAvailable)), + uintptr(unsafe.Pointer(&totalNumberOfBytes)), + uintptr(unsafe.Pointer(&totalNumberOfFreeBytes)), + 0, + 0, + ) + if ret == 0 { + return 0, 0, 0, 0, 0, 0, err + } + + return freeBytesAvailable, totalNumberOfBytes, totalNumberOfBytes - freeBytesAvailable, 0, 0, 0, nil +} + +// DiskUsage gets disk usage of specified path. +func DiskUsage(path string) (*resource.Quantity, error) { + _, _, usage, _, _, _, err := FsInfo(path) + if err != nil { + return nil, err + } + + used, err := resource.ParseQuantity(fmt.Sprintf("%d", usage)) + if err != nil { + return nil, fmt.Errorf("failed to parse fs usage %d due to %v", usage, err) + } + used.Format = resource.BinarySI + return &used, nil +} + +// Always return zero since inodes is not supported on Windows. +func Find(path string) (int64, error) { + return 0, nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_executor.go b/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_executor.go index c586b959a..283a32225 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_executor.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_executor.go @@ -142,6 +142,8 @@ type OperationExecutor interface { IsOperationPending(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) bool // Expand Volume will grow size available to PVC ExpandVolume(*expandcache.PVCWithResizeRequest, expandcache.VolumeResizeMap) error + // ExpandVolumeFSWithoutUnmounting will resize volume's file system to expected size without unmounting the volume. + ExpandVolumeFSWithoutUnmounting(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) error // ReconstructVolumeOperation construct a new volumeSpec and returns it created by plugin ReconstructVolumeOperation(volumeMode v1.PersistentVolumeMode, plugin volume.VolumePlugin, mapperPlugin volume.BlockVolumePlugin, uid types.UID, podName volumetypes.UniquePodName, volumeSpecName string, mountPath string, pluginName string) (*volume.Spec, error) // CheckVolumeExistenceOperation checks volume existence @@ -163,7 +165,7 @@ func NewOperationExecutor( // state of the world cache after successful mount/unmount. type ActualStateOfWorldMounterUpdater interface { // Marks the specified volume as mounted to the specified pod - MarkVolumeAsMounted(podName volumetypes.UniquePodName, podUID types.UID, volumeName v1.UniqueVolumeName, mounter volume.Mounter, blockVolumeMapper volume.BlockVolumeMapper, outerVolumeSpecName string, volumeGidValue string) error + MarkVolumeAsMounted(podName volumetypes.UniquePodName, podUID types.UID, volumeName v1.UniqueVolumeName, mounter volume.Mounter, blockVolumeMapper volume.BlockVolumeMapper, outerVolumeSpecName string, volumeGidValue string, volumeSpec *volume.Spec) error // Marks the specified volume as unmounted from the specified pod MarkVolumeAsUnmounted(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) error @@ -173,6 +175,9 @@ type ActualStateOfWorldMounterUpdater interface { // Marks the specified volume as having its global mount unmounted. MarkDeviceAsUnmounted(volumeName v1.UniqueVolumeName) error + + // Marks the specified volume's file system resize request is finished. + MarkVolumeAsResized(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) error } // ActualStateOfWorldAttacherUpdater defines a set of operations updating the @@ -817,6 +822,14 @@ func (oe *operationExecutor) ExpandVolume(pvcWithResizeRequest *expandcache.PVCW return oe.pendingOperations.Run(uniqueVolumeKey, "", generatedOperations) } +func (oe *operationExecutor) ExpandVolumeFSWithoutUnmounting(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) error { + generatedOperations, err := oe.operationGenerator.GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount, actualStateOfWorld) + if err != nil { + return err + } + return oe.pendingOperations.Run(volumeToMount.VolumeName, "", generatedOperations) +} + func (oe *operationExecutor) VerifyControllerAttachedVolume( volumeToMount VolumeToMount, nodeName types.NodeName, diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_executor_test.go b/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_executor_test.go index 0551c4733..7d427e48f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_executor_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_executor_test.go @@ -438,6 +438,16 @@ func (fopg *fakeOperationGenerator) GenerateExpandVolumeFunc(pvcWithResizeReques }, nil } +func (fopg *fakeOperationGenerator) GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) { + opFunc := func() (error, error) { + startOperationAndBlock(fopg.ch, fopg.quit) + return nil, nil + } + return volumetypes.GeneratedOperations{ + OperationFunc: opFunc, + }, nil +} + func (fopg *fakeOperationGenerator) GenerateBulkVolumeVerifyFunc( pluginNodeVolumes map[types.NodeName][]*volume.Spec, pluginNane string, diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_generator.go b/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_generator.go index 7130d8404..51f321ae9 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_generator.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/operationexecutor/operation_generator.go @@ -121,6 +121,9 @@ type OperationGenerator interface { map[*volume.Spec]v1.UniqueVolumeName, ActualStateOfWorldAttacherUpdater) (volumetypes.GeneratedOperations, error) GenerateExpandVolumeFunc(*expandcache.PVCWithResizeRequest, expandcache.VolumeResizeMap) (volumetypes.GeneratedOperations, error) + + // Generates the volume file system resize function, which can resize volume's file system to expected size without unmounting the volume. + GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) } func (og *operationGenerator) GenerateVolumesAreAttachedFunc( @@ -547,12 +550,10 @@ func (og *operationGenerator) GenerateMountVolumeFunc( return volumeToMount.GenerateError("MountVolume.SetUp failed", mountErr) } - simpleMsg, detailedMsg := volumeToMount.GenerateMsg("MountVolume.SetUp succeeded", "") + _, detailedMsg := volumeToMount.GenerateMsg("MountVolume.SetUp succeeded", "") verbosity := glog.Level(1) if isRemount { verbosity = glog.Level(4) - } else { - og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeNormal, kevents.SuccessfulMountVolume, simpleMsg) } glog.V(verbosity).Infof(detailedMsg) @@ -564,7 +565,8 @@ func (og *operationGenerator) GenerateMountVolumeFunc( volumeMounter, nil, volumeToMount.OuterVolumeSpecName, - volumeToMount.VolumeGidValue) + volumeToMount.VolumeGidValue, + volumeToMount.VolumeSpec) if markVolMountedErr != nil { // On failure, return error. Caller will log and retry. return volumeToMount.GenerateError("MountVolume.MarkVolumeAsMounted failed", markVolMountedErr) @@ -854,37 +856,19 @@ func (og *operationGenerator) GenerateMapVolumeFunc( // On failure, return error. Caller will log and retry. return volumeToMount.GenerateError("MapVolume.SetUp failed", mapErr) } - // Update devicePath for none attachable plugin case - if len(devicePath) == 0 { - if len(pluginDevicePath) != 0 { - devicePath = pluginDevicePath - } else { - return volumeToMount.GenerateError("MapVolume failed", fmt.Errorf("Device path of the volume is empty")) - } - } - // Update actual state of world to reflect volume is globally mounted - markDeviceMappedErr := actualStateOfWorld.MarkDeviceAsMounted( - volumeToMount.VolumeName, devicePath, globalMapPath) - if markDeviceMappedErr != nil { - // On failure, return error. Caller will log and retry. - return volumeToMount.GenerateError("MapVolume.MarkDeviceAsMounted failed", markDeviceMappedErr) - } - mapErr = og.blkUtil.MapDevice(devicePath, globalMapPath, string(volumeToMount.Pod.UID)) - if mapErr != nil { - // On failure, return error. Caller will log and retry. - return volumeToMount.GenerateError("MapVolume.MapDevice failed", mapErr) + // if pluginDevicePath is provided, assume attacher may not provide device + // or attachment flow uses SetupDevice to get device path + if len(pluginDevicePath) != 0 { + devicePath = pluginDevicePath + } + if len(devicePath) == 0 { + return volumeToMount.GenerateError("MapVolume failed", fmt.Errorf("Device path of the volume is empty")) } - // Device mapping for global map path succeeded - simpleMsg, detailedMsg := volumeToMount.GenerateMsg("MapVolume.MapDevice succeeded", fmt.Sprintf("globalMapPath %q", globalMapPath)) - verbosity := glog.Level(4) - og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeNormal, kevents.SuccessfulMountVolume, simpleMsg) - glog.V(verbosity).Infof(detailedMsg) - - // Map device to pod device map path under the given pod directory using symbolic link + // Map device to global and pod device map path volumeMapPath, volName := blockVolumeMapper.GetPodDeviceMapPath() - mapErr = og.blkUtil.MapDevice(devicePath, volumeMapPath, volName) + mapErr = blockVolumeMapper.MapDevice(devicePath, globalMapPath, volumeMapPath, volName, volumeToMount.Pod.UID) if mapErr != nil { // On failure, return error. Caller will log and retry. return volumeToMount.GenerateError("MapVolume.MapDevice failed", mapErr) @@ -899,6 +883,20 @@ func (og *operationGenerator) GenerateMapVolumeFunc( return volumeToMount.GenerateError("MapVolume.AttachFileDevice failed", err) } + // Update actual state of world to reflect volume is globally mounted + markDeviceMappedErr := actualStateOfWorld.MarkDeviceAsMounted( + volumeToMount.VolumeName, devicePath, globalMapPath) + if markDeviceMappedErr != nil { + // On failure, return error. Caller will log and retry. + return volumeToMount.GenerateError("MapVolume.MarkDeviceAsMounted failed", markDeviceMappedErr) + } + + // Device mapping for global map path succeeded + simpleMsg, detailedMsg := volumeToMount.GenerateMsg("MapVolume.MapDevice succeeded", fmt.Sprintf("globalMapPath %q", globalMapPath)) + verbosity := glog.Level(4) + og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeNormal, kevents.SuccessfulMountVolume, simpleMsg) + glog.V(verbosity).Infof(detailedMsg) + // Device mapping for pod device map path succeeded simpleMsg, detailedMsg = volumeToMount.GenerateMsg("MapVolume.MapDevice succeeded", fmt.Sprintf("volumeMapPath %q", volumeMapPath)) verbosity = glog.Level(1) @@ -913,7 +911,8 @@ func (og *operationGenerator) GenerateMapVolumeFunc( nil, blockVolumeMapper, volumeToMount.OuterVolumeSpecName, - volumeToMount.VolumeGidValue) + volumeToMount.VolumeGidValue, + volumeToMount.VolumeSpec) if markVolMountedErr != nil { // On failure, return error. Caller will log and retry. return volumeToMount.GenerateError("MapVolume.MarkVolumeAsMounted failed", markVolMountedErr) @@ -1068,11 +1067,18 @@ func (og *operationGenerator) GenerateUnmapDeviceFunc( glog.V(4).Infof("UnmapDevice: deviceToDetach.DevicePath: %v", deviceToDetach.DevicePath) loopPath, err := og.blkUtil.GetLoopDevice(deviceToDetach.DevicePath) if err != nil { - glog.Warningf(deviceToDetach.GenerateMsgDetailed("UnmapDevice: Couldn't find loopback device which takes file descriptor lock", fmt.Sprintf("device path: %q", deviceToDetach.DevicePath))) + if err.Error() == volumepathhandler.ErrDeviceNotFound { + glog.Warningf(deviceToDetach.GenerateMsgDetailed("UnmapDevice: Couldn't find loopback device which takes file descriptor lock", fmt.Sprintf("device path: %q", deviceToDetach.DevicePath))) + } else { + errInfo := "UnmapDevice.GetLoopDevice failed to get loopback device, " + fmt.Sprintf("device path: %q", deviceToDetach.DevicePath) + return deviceToDetach.GenerateError(errInfo, err) + } } else { - err = og.blkUtil.RemoveLoopDevice(loopPath) - if err != nil { - return deviceToDetach.GenerateError("UnmapDevice.AttachFileDevice failed", err) + if len(loopPath) != 0 { + err = og.blkUtil.RemoveLoopDevice(loopPath) + if err != nil { + return deviceToDetach.GenerateError("UnmapDevice.RemoveLoopDevice failed", err) + } } } @@ -1299,6 +1305,62 @@ func (og *operationGenerator) GenerateExpandVolumeFunc( }, nil } +func (og *operationGenerator) GenerateExpandVolumeFSWithoutUnmountingFunc( + volumeToMount VolumeToMount, + actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) { + volumePlugin, err := + og.volumePluginMgr.FindPluginBySpec(volumeToMount.VolumeSpec) + if err != nil || volumePlugin == nil { + return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("VolumeFSResize.FindPluginBySpec failed", err) + } + + attachableVolumePlugin, err := + og.volumePluginMgr.FindAttachablePluginBySpec(volumeToMount.VolumeSpec) + if err != nil || attachableVolumePlugin == nil { + if attachableVolumePlugin == nil { + err = fmt.Errorf("AttachableVolumePlugin is nil") + } + return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("VolumeFSResize.FindAttachablePluginBySpec failed", err) + } + + volumeAttacher, err := attachableVolumePlugin.NewAttacher() + if err != nil || volumeAttacher == nil { + if volumeAttacher == nil { + err = fmt.Errorf("VolumeAttacher is nil") + } + return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("VolumeFSResize.NewAttacher failed", err) + } + + deviceMountPath, err := volumeAttacher.GetDeviceMountPath(volumeToMount.VolumeSpec) + if err != nil { + return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("VolumeFSResize.GetDeviceMountPath failed", err) + } + + fsResizeFunc := func() (error, error) { + resizeSimpleError, resizeDetailedError := og.resizeFileSystem(volumeToMount, volumeToMount.DevicePath, deviceMountPath, volumePlugin.GetPluginName()) + if resizeSimpleError != nil || resizeDetailedError != nil { + return resizeSimpleError, resizeDetailedError + } + markFSResizedErr := actualStateOfWorld.MarkVolumeAsResized(volumeToMount.PodName, volumeToMount.VolumeName) + if markFSResizedErr != nil { + // On failure, return error. Caller will log and retry. + return volumeToMount.GenerateError("VolumeFSResize.MarkVolumeAsResized failed", markFSResizedErr) + } + return nil, nil + } + eventRecorderFunc := func(err *error) { + if *err != nil { + og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeWarning, kevents.VolumeResizeFailed, (*err).Error()) + } + } + + return volumetypes.GeneratedOperations{ + OperationFunc: fsResizeFunc, + EventRecorderFunc: eventRecorderFunc, + CompleteFunc: util.OperationCompleteHook(volumePlugin.GetPluginName(), "volume_fs_resize"), + }, nil +} + func checkMountOptionSupport(og *operationGenerator, volumeToMount VolumeToMount, plugin volume.VolumePlugin) error { mountOptions := util.MountOptionFromSpec(volumeToMount.VolumeSpec) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/recyclerclient/recycler_client.go b/vendor/k8s.io/kubernetes/pkg/volume/util/recyclerclient/recycler_client.go index 1af6465c6..275f55bbe 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/recyclerclient/recycler_client.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/recyclerclient/recycler_client.go @@ -18,6 +18,7 @@ package recyclerclient import ( "fmt" + "sync" "github.com/golang/glog" "k8s.io/api/core/v1" @@ -191,6 +192,8 @@ func (c *realRecyclerClient) Event(eventtype, message string) { c.recorder(eventtype, message) } +// WatchPod watches a pod and events related to it. It sends pod updates and events over the returned channel +// It will continue until stopChannel is closed func (c *realRecyclerClient) WatchPod(name, namespace string, stopChannel chan struct{}) (<-chan watch.Event, error) { podSelector, err := fields.ParseSelector("metadata.name=" + name) if err != nil { @@ -217,33 +220,45 @@ func (c *realRecyclerClient) WatchPod(name, namespace string, stopChannel chan s } eventCh := make(chan watch.Event, 30) + var wg sync.WaitGroup + wg.Add(2) go func() { - defer eventWatch.Stop() - defer podWatch.Stop() defer close(eventCh) - var podWatchChannelClosed bool - var eventWatchChannelClosed bool + wg.Wait() + }() + + go func() { + defer eventWatch.Stop() + defer wg.Done() for { select { case _ = <-stopChannel: return - - case podEvent, ok := <-podWatch.ResultChan(): - if !ok { - podWatchChannelClosed = true - } else { - eventCh <- podEvent - } case eventEvent, ok := <-eventWatch.ResultChan(): if !ok { - eventWatchChannelClosed = true + return } else { eventCh <- eventEvent } } - if podWatchChannelClosed && eventWatchChannelClosed { - break + } + }() + + go func() { + defer podWatch.Stop() + defer wg.Done() + for { + select { + case <-stopChannel: + return + + case podEvent, ok := <-podWatch.ResultChan(): + if !ok { + return + } else { + eventCh <- podEvent + } } } }() diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/util.go b/vendor/k8s.io/kubernetes/pkg/volume/util/util.go index febb81373..1e7b70934 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/util.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/util.go @@ -50,6 +50,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" utypes "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/volume/util/types" + "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" ) const ( @@ -267,39 +268,9 @@ func GetClassForVolume(kubeClient clientset.Interface, pv *v1.PersistentVolume) // CheckNodeAffinity looks at the PV node affinity, and checks if the node has the same corresponding labels // This ensures that we don't mount a volume that doesn't belong to this node func CheckNodeAffinity(pv *v1.PersistentVolume, nodeLabels map[string]string) error { - if err := checkAlphaNodeAffinity(pv, nodeLabels); err != nil { - return err - } return checkVolumeNodeAffinity(pv, nodeLabels) } -func checkAlphaNodeAffinity(pv *v1.PersistentVolume, nodeLabels map[string]string) error { - affinity, err := v1helper.GetStorageNodeAffinityFromAnnotation(pv.Annotations) - if err != nil { - return fmt.Errorf("Error getting storage node affinity: %v", err) - } - if affinity == nil { - return nil - } - - if affinity.RequiredDuringSchedulingIgnoredDuringExecution != nil { - terms := affinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms - glog.V(10).Infof("Match for RequiredDuringSchedulingIgnoredDuringExecution node selector terms %+v", terms) - for _, term := range terms { - selector, err := v1helper.NodeSelectorRequirementsAsSelector(term.MatchExpressions) - if err != nil { - return fmt.Errorf("Failed to parse MatchExpressions: %v", err) - } - if selector.Matches(labels.Set(nodeLabels)) { - // Terms are ORed, so only one needs to match - return nil - } - } - return fmt.Errorf("No matching NodeSelectorTerms") - } - return nil -} - func checkVolumeNodeAffinity(pv *v1.PersistentVolume, nodeLabels map[string]string) error { if pv.Spec.NodeAffinity == nil { return nil @@ -308,18 +279,11 @@ func checkVolumeNodeAffinity(pv *v1.PersistentVolume, nodeLabels map[string]stri if pv.Spec.NodeAffinity.Required != nil { terms := pv.Spec.NodeAffinity.Required.NodeSelectorTerms glog.V(10).Infof("Match for Required node selector terms %+v", terms) - for _, term := range terms { - selector, err := v1helper.NodeSelectorRequirementsAsSelector(term.MatchExpressions) - if err != nil { - return fmt.Errorf("Failed to parse MatchExpressions: %v", err) - } - if selector.Matches(labels.Set(nodeLabels)) { - // Terms are ORed, so only one needs to match - return nil - } + if !v1helper.MatchNodeSelectorTerms(terms, labels.Set(nodeLabels), nil) { + return fmt.Errorf("No matching NodeSelectorTerms") } - return fmt.Errorf("No matching NodeSelectorTerms") } + return nil } @@ -755,6 +719,12 @@ func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) { return true, nil } +// CheckPersistentVolumeClaimModeBlock checks VolumeMode. +// If the mode is Block, return true otherwise return false. +func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool { + return utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock +} + // MakeAbsolutePath convert path to absolute path according to GOOS func MakeAbsolutePath(goos, path string) string { if goos != "windows" { @@ -772,3 +742,30 @@ func MakeAbsolutePath(goos, path string) string { // Otherwise, add 'c:\' return "c:\\" + path } + +// MapBlockVolume is a utility function to provide a common way of mounting +// block device path for a specified volume and pod. This function should be +// called by volume plugins that implements volume.BlockVolumeMapper.Map() method. +func MapBlockVolume( + devicePath, + globalMapPath, + podVolumeMapPath, + volumeMapName string, + podUID utypes.UID, +) error { + blkUtil := volumepathhandler.NewBlockVolumePathHandler() + + // map devicePath to global node path + mapErr := blkUtil.MapDevice(devicePath, globalMapPath, string(podUID)) + if mapErr != nil { + return mapErr + } + + // map devicePath to pod volume path + mapErr = blkUtil.MapDevice(devicePath, podVolumeMapPath, volumeMapName) + if mapErr != nil { + return mapErr + } + + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/util_test.go b/vendor/k8s.io/kubernetes/pkg/volume/util/util_test.go index 3f1d66047..b2790796e 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/util_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/util_test.go @@ -30,7 +30,6 @@ import ( "hash/fnv" _ "k8s.io/kubernetes/pkg/apis/core/install" - "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/util/mount" "reflect" @@ -48,133 +47,6 @@ var nodeLabels map[string]string = map[string]string{ "test-key2": "test-value2", } -func TestCheckAlphaNodeAffinity(t *testing.T) { - type affinityTest struct { - name string - expectSuccess bool - pv *v1.PersistentVolume - } - - cases := []affinityTest{ - { - name: "valid-no-constraints", - expectSuccess: true, - pv: testVolumeWithAlphaNodeAffinity(t, &v1.NodeAffinity{}), - }, - { - name: "valid-constraints", - expectSuccess: true, - pv: testVolumeWithAlphaNodeAffinity(t, &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "test-key1", - Operator: v1.NodeSelectorOpIn, - Values: []string{"test-value1", "test-value3"}, - }, - { - Key: "test-key2", - Operator: v1.NodeSelectorOpIn, - Values: []string{"test-value0", "test-value2"}, - }, - }, - }, - }, - }, - }), - }, - { - name: "invalid-key", - expectSuccess: false, - pv: testVolumeWithAlphaNodeAffinity(t, &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "test-key1", - Operator: v1.NodeSelectorOpIn, - Values: []string{"test-value1", "test-value3"}, - }, - { - Key: "test-key3", - Operator: v1.NodeSelectorOpIn, - Values: []string{"test-value0", "test-value2"}, - }, - }, - }, - }, - }, - }), - }, - { - name: "invalid-values", - expectSuccess: false, - pv: testVolumeWithAlphaNodeAffinity(t, &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "test-key1", - Operator: v1.NodeSelectorOpIn, - Values: []string{"test-value3", "test-value4"}, - }, - { - Key: "test-key2", - Operator: v1.NodeSelectorOpIn, - Values: []string{"test-value0", "test-value2"}, - }, - }, - }, - }, - }, - }), - }, - { - name: "invalid-multiple-terms", - expectSuccess: false, - pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{ - Required: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "test-key3", - Operator: v1.NodeSelectorOpIn, - Values: []string{"test-value1", "test-value3"}, - }, - }, - }, - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "test-key2", - Operator: v1.NodeSelectorOpIn, - Values: []string{"test-value0", "test-value1"}, - }, - }, - }, - }, - }, - }), - }, - } - - for _, c := range cases { - err := CheckNodeAffinity(c.pv, nodeLabels) - - if err != nil && c.expectSuccess { - t.Errorf("CheckTopology %v returned error: %v", c.name, err) - } - if err == nil && !c.expectSuccess { - t.Errorf("CheckTopology %v returned success, expected error", c.name) - } - } -} - func TestCheckVolumeNodeAffinity(t *testing.T) { type affinityTest struct { name string @@ -311,6 +183,34 @@ func TestCheckVolumeNodeAffinity(t *testing.T) { }, }), }, + { + name: "invalid-multiple-terms", + expectSuccess: false, + pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{ + Required: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "test-key3", + Operator: v1.NodeSelectorOpIn, + Values: []string{"test-value1", "test-value3"}, + }, + }, + }, + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "test-key2", + Operator: v1.NodeSelectorOpIn, + Values: []string{"test-value0", "test-value1"}, + }, + }, + }, + }, + }, + }), + }, } for _, c := range cases { @@ -325,19 +225,6 @@ func TestCheckVolumeNodeAffinity(t *testing.T) { } } -func testVolumeWithAlphaNodeAffinity(t *testing.T, affinity *v1.NodeAffinity) *v1.PersistentVolume { - objMeta := metav1.ObjectMeta{Name: "test-constraints"} - objMeta.Annotations = map[string]string{} - err := helper.StorageNodeAffinityToAlphaAnnotation(objMeta.Annotations, affinity) - if err != nil { - t.Fatalf("Failed to get node affinity annotation: %v", err) - } - - return &v1.PersistentVolume{ - ObjectMeta: objMeta, - } -} - func testVolumeWithNodeAffinity(t *testing.T, affinity *v1.VolumeNodeAffinity) *v1.PersistentVolume { objMeta := metav1.ObjectMeta{Name: "test-constraints"} return &v1.PersistentVolume{ diff --git a/vendor/k8s.io/kubernetes/pkg/volume/volume.go b/vendor/k8s.io/kubernetes/pkg/volume/volume.go index 161d84faf..5f633214f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/volume.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/volume.go @@ -162,6 +162,9 @@ type BlockVolumeMapper interface { // at attacher.Attach() and attacher.WaitForAttach(). // This may be called more than once, so implementations must be idempotent. SetUpDevice() (string, error) + + // Map maps the block device path for the specified spec and pod. + MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error } // BlockVolumeUnmapper interface provides methods to cleanup/unmap the volumes. @@ -180,7 +183,7 @@ type Provisioner interface { // Provision creates the resource by allocating the underlying volume in a // storage system. This method should block until completion and returns // PersistentVolume representing the created storage resource. - Provision() (*v1.PersistentVolume, error) + Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) } // Deleter removes the resource from the underlying storage provider. Calls diff --git a/vendor/k8s.io/kubernetes/pkg/volume/volume_linux.go b/vendor/k8s.io/kubernetes/pkg/volume/volume_linux.go index d67ee4a95..ef1f45208 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/volume_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/volume_linux.go @@ -89,17 +89,3 @@ func SetVolumeOwnership(mounter Mounter, fsGroup *int64) error { return nil }) } - -// IsSameFSGroup is called only for requests to mount an already mounted -// volume. It checks if fsGroup of new mount request is the same or not. -// It returns false if it not the same. It also returns current Gid of a path -// provided for dir variable. -func IsSameFSGroup(dir string, fsGroup int64) (bool, int, error) { - info, err := os.Stat(dir) - if err != nil { - glog.Errorf("Error getting stats for %s (%v)", dir, err) - return false, 0, err - } - s := info.Sys().(*syscall.Stat_t) - return int(s.Gid) == int(fsGroup), int(s.Gid), nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/volume_unsupported.go b/vendor/k8s.io/kubernetes/pkg/volume/volume_unsupported.go index 46a6aeaf0..45a6cc5ca 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/volume_unsupported.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/volume_unsupported.go @@ -21,7 +21,3 @@ package volume func SetVolumeOwnership(mounter Mounter, fsGroup *int64) error { return nil } - -func IsSameFSGroup(dir string, fsGroup int64) (bool, int, error) { - return true, int(fsGroup), nil -} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/BUILD b/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/BUILD index f69c1fb6d..1ac39a13f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/BUILD @@ -39,6 +39,9 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//pkg/cloudprovider:go_default_library", + "//pkg/cloudprovider/providers/fake:go_default_library", + "//pkg/cloudprovider/providers/vsphere:go_default_library", "//pkg/cloudprovider/providers/vsphere/vclib:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/volume:go_default_library", diff --git a/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume.go b/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume.go index 7b1e611df..0cd3014fe 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume.go @@ -348,10 +348,13 @@ func (plugin *vsphereVolumePlugin) newProvisionerInternal(options volume.VolumeO }, nil } -func (v *vsphereVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { +func (v *vsphereVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { if !util.AccessModesContainedInAll(v.plugin.GetAccessModes(), v.options.PVC.Spec.AccessModes) { return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", v.options.PVC.Spec.AccessModes, v.plugin.GetAccessModes()) } + if util.CheckPersistentVolumeClaimModeBlock(v.options.PVC) { + return nil, fmt.Errorf("%s does not support block volume provisioning", v.plugin.GetPluginName()) + } volSpec, err := v.manager.CreateVolume(v) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume_test.go b/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume_test.go index 34fec92d6..92c4b4d0b 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume_test.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume_test.go @@ -25,6 +25,9 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" utiltesting "k8s.io/client-go/util/testing" + "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/cloudprovider/providers/fake" + "k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" volumetest "k8s.io/kubernetes/pkg/volume/testing" @@ -156,7 +159,7 @@ func TestPlugin(t *testing.T) { if err != nil { t.Errorf("newProvisionerInternal() failed: %v", err) } - persistentSpec, err := provisioner.Provision() + persistentSpec, err := provisioner.Provision(nil, nil) if err != nil { t.Errorf("Provision() failed: %v", err) } @@ -188,3 +191,49 @@ func TestPlugin(t *testing.T) { t.Errorf("Deleter() failed: %v", err) } } + +func TestUnsupportedCloudProvider(t *testing.T) { + // Initial setup to test volume plugin + tmpDir, err := utiltesting.MkTmpdir("vsphereVolumeTest") + if err != nil { + t.Fatalf("can't make a temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + testcases := []struct { + name string + cloudProvider cloudprovider.Interface + success bool + }{ + {name: "nil cloudprovider", cloudProvider: nil}, + {name: "vSphere", cloudProvider: &vsphere.VSphere{}, success: true}, + {name: "fake cloudprovider", cloudProvider: &fake.FakeCloud{}}, + } + + for _, tc := range testcases { + t.Logf("test case: %v", tc.name) + + plugMgr := volume.VolumePluginMgr{} + plugMgr.InitPlugins(ProbeVolumePlugins(), nil, /* prober */ + volumetest.NewFakeVolumeHostWithCloudProvider(tmpDir, nil, nil, tc.cloudProvider)) + + plug, err := plugMgr.FindAttachablePluginByName("kubernetes.io/vsphere-volume") + if err != nil { + t.Errorf("Can't find the plugin by name") + } + + _, err = plug.NewAttacher() + if !tc.success && err == nil { + t.Errorf("expected error when creating attacher due to incorrect cloud provider, but got none") + } else if tc.success && err != nil { + t.Errorf("expected no error when creating attacher, but got error: %v", err) + } + + _, err = plug.NewDetacher() + if !tc.success && err == nil { + t.Errorf("expected error when creating detacher due to incorrect cloud provider, but got none") + } else if tc.success && err != nil { + t.Errorf("expected no error when creating detacher, but got error: %v", err) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume_util.go b/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume_util.go index 14e235d5d..976dc319f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume_util.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/vsphere_volume/vsphere_volume_util.go @@ -185,8 +185,8 @@ func getCloudProvider(cloud cloudprovider.Interface) (*vsphere.VSphere, error) { return nil, errors.New("Cloud provider not initialized properly") } - vs := cloud.(*vsphere.VSphere) - if vs == nil { + vs, ok := cloud.(*vsphere.VSphere) + if !ok || vs == nil { return nil, errors.New("Invalid cloud provider: expected vSphere") } return vs, nil diff --git a/vendor/k8s.io/kubernetes/plugin/BUILD b/vendor/k8s.io/kubernetes/plugin/BUILD index e0765f5af..caf1b3baf 100644 --- a/vendor/k8s.io/kubernetes/plugin/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/BUILD @@ -21,13 +21,10 @@ filegroup( "//plugin/pkg/admission/extendedresourcetoleration:all-srcs", "//plugin/pkg/admission/gc:all-srcs", "//plugin/pkg/admission/imagepolicy:all-srcs", - "//plugin/pkg/admission/initialresources:all-srcs", "//plugin/pkg/admission/limitranger:all-srcs", "//plugin/pkg/admission/namespace/autoprovision:all-srcs", "//plugin/pkg/admission/namespace/exists:all-srcs", "//plugin/pkg/admission/noderestriction:all-srcs", - "//plugin/pkg/admission/persistentvolume/label:all-srcs", - "//plugin/pkg/admission/persistentvolume/resize:all-srcs", "//plugin/pkg/admission/podnodeselector:all-srcs", "//plugin/pkg/admission/podpreset:all-srcs", "//plugin/pkg/admission/podtolerationrestriction:all-srcs", @@ -36,6 +33,8 @@ filegroup( "//plugin/pkg/admission/security:all-srcs", "//plugin/pkg/admission/securitycontext/scdeny:all-srcs", "//plugin/pkg/admission/serviceaccount:all-srcs", + "//plugin/pkg/admission/storage/persistentvolume/label:all-srcs", + "//plugin/pkg/admission/storage/persistentvolume/resize:all-srcs", "//plugin/pkg/admission/storage/storageclass/setdefault:all-srcs", "//plugin/pkg/admission/storage/storageobjectinuseprotection:all-srcs", "//plugin/pkg/auth:all-srcs", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/BUILD index 35b29f821..7ff9acd2c 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/BUILD @@ -24,7 +24,6 @@ go_library( importpath = "k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds", deps = [ "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission.go index 41c37511c..292be403f 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission.go @@ -24,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apiserver/pkg/admission" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/scheduler/algorithm" ) @@ -39,6 +38,20 @@ var ( defaultUnreachableTolerationSeconds = flag.Int64("default-unreachable-toleration-seconds", 300, "Indicates the tolerationSeconds of the toleration for unreachable:NoExecute"+ " that is added by default to every pod that does not already have such a toleration.") + + notReadyToleration = api.Toleration{ + Key: algorithm.TaintNodeNotReady, + Operator: api.TolerationOpExists, + Effect: api.TaintEffectNoExecute, + TolerationSeconds: defaultNotReadyTolerationSeconds, + } + + unreachableToleration = api.Toleration{ + Key: algorithm.TaintNodeUnreachable, + Operator: api.TolerationOpExists, + Effect: api.TaintEffectNoExecute, + TolerationSeconds: defaultUnreachableTolerationSeconds, + } ) // Register registers a plugin @@ -99,27 +112,13 @@ func (p *Plugin) Admit(attributes admission.Attributes) (err error) { } } - // no change is required, return immediately - if toleratesNodeNotReady && toleratesNodeUnreachable { - return nil - } - if !toleratesNodeNotReady { - helper.AddOrUpdateTolerationInPod(pod, &api.Toleration{ - Key: algorithm.TaintNodeNotReady, - Operator: api.TolerationOpExists, - Effect: api.TaintEffectNoExecute, - TolerationSeconds: defaultNotReadyTolerationSeconds, - }) + pod.Spec.Tolerations = append(pod.Spec.Tolerations, notReadyToleration) } if !toleratesNodeUnreachable { - helper.AddOrUpdateTolerationInPod(pod, &api.Toleration{ - Key: algorithm.TaintNodeUnreachable, - Operator: api.TolerationOpExists, - Effect: api.TaintEffectNoExecute, - TolerationSeconds: defaultUnreachableTolerationSeconds, - }) + pod.Spec.Tolerations = append(pod.Spec.Tolerations, unreachableToleration) } + return nil } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/BUILD index c12c5e39d..9dfc093b7 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/BUILD @@ -45,8 +45,6 @@ go_library( "//plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation:go_default_library", "//vendor/github.com/hashicorp/golang-lru:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/install/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/install/BUILD index 6e2a32ff6..36d008a64 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/install/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/install/BUILD @@ -12,9 +12,8 @@ go_library( deps = [ "//plugin/pkg/admission/eventratelimit/apis/eventratelimit:go_default_library", "//plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/install/install.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/install/install.go index 805cb579f..413cd56b8 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/install/install.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" internalapi "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit" versionedapi "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: internalapi.GroupName, - VersionPreferenceOrder: []string{versionedapi.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: internalapi.AddToScheme, - }, - announced.VersionToSchemeFunc{ - versionedapi.SchemeGroupVersion.Version: versionedapi.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(internalapi.AddToScheme(scheme)) + utilruntime.Must(versionedapi.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(versionedapi.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.conversion.go index a3874100c..9c1ca4fe4 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.deepcopy.go index 3bc52968f..d7a182db1 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.defaults.go index 5392d21f8..fbf617bbf 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/zz_generated.deepcopy.go index f539919ed..56614f05b 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/config.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/config.go index 993ac9ef4..34610391f 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/config.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/config.go @@ -20,10 +20,7 @@ import ( "fmt" "io" "io/ioutil" - "os" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" eventratelimitapi "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit" @@ -32,14 +29,12 @@ import ( ) var ( - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) - scheme = runtime.NewScheme() - codecs = serializer.NewCodecFactory(scheme) + scheme = runtime.NewScheme() + codecs = serializer.NewCodecFactory(scheme) ) func init() { - install.Install(groupFactoryRegistry, registry, scheme) + install.Install(scheme) } // LoadConfiguration loads the provided configuration. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/BUILD index 2573403a4..60b310a67 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/BUILD @@ -30,6 +30,7 @@ go_test( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/kubeapiserver/admission:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission.go index ac8af4417..1bfeaf0a1 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission.go @@ -95,21 +95,26 @@ func (a *gcPermissionsEnforcement) Validate(attributes admission.Attributes) (er return nil } - deleteAttributes := authorizer.AttributesRecord{ - User: attributes.GetUserInfo(), - Verb: "delete", - Namespace: attributes.GetNamespace(), - APIGroup: attributes.GetResource().Group, - APIVersion: attributes.GetResource().Version, - Resource: attributes.GetResource().Resource, - Subresource: attributes.GetSubresource(), - Name: attributes.GetName(), - ResourceRequest: true, - Path: "", - } - decision, reason, err := a.authorizer.Authorize(deleteAttributes) - if decision != authorizer.DecisionAllow { - return admission.NewForbidden(attributes, fmt.Errorf("cannot set an ownerRef on a resource you can't delete: %v, %v", reason, err)) + // if you are creating a thing, you should always be allowed to set an owner ref since you logically had the power + // to never create it. We still need to check block owner deletion below, because the power to delete does not + // imply the power to prevent deletion on other resources. + if attributes.GetOperation() != admission.Create { + deleteAttributes := authorizer.AttributesRecord{ + User: attributes.GetUserInfo(), + Verb: "delete", + Namespace: attributes.GetNamespace(), + APIGroup: attributes.GetResource().Group, + APIVersion: attributes.GetResource().Version, + Resource: attributes.GetResource().Resource, + Subresource: attributes.GetSubresource(), + Name: attributes.GetName(), + ResourceRequest: true, + Path: "", + } + decision, reason, err := a.authorizer.Authorize(deleteAttributes) + if decision != authorizer.DecisionAllow { + return admission.NewForbidden(attributes, fmt.Errorf("cannot set an ownerRef on a resource you can't delete: %v, %v", reason, err)) + } } // Further check if the user is setting ownerReference.blockOwnerDeletion to @@ -119,7 +124,7 @@ func (a *gcPermissionsEnforcement) Validate(attributes admission.Attributes) (er for _, ref := range newBlockingRefs { records, err := a.ownerRefToDeleteAttributeRecords(ref, attributes) if err != nil { - return admission.NewForbidden(attributes, fmt.Errorf("cannot set blockOwnerDeletion in this case because cannot find RESTMapping for APIVersion %s Kind %s: %v, %v", ref.APIVersion, ref.Kind, reason, err)) + return admission.NewForbidden(attributes, fmt.Errorf("cannot set blockOwnerDeletion in this case because cannot find RESTMapping for APIVersion %s Kind %s: %v", ref.APIVersion, ref.Kind, err)) } // Multiple records are returned if ref.Kind could map to multiple // resources. User needs to have delete permission on all the @@ -186,9 +191,9 @@ func (a *gcPermissionsEnforcement) ownerRefToDeleteAttributeRecords(ref metav1.O Verb: "update", // ownerReference can only refer to an object in the same namespace, so attributes.GetNamespace() equals to the owner's namespace Namespace: attributes.GetNamespace(), - APIGroup: groupVersion.Group, - APIVersion: groupVersion.Version, - Resource: mapping.Resource, + APIGroup: mapping.Resource.Group, + APIVersion: mapping.Resource.Version, + Resource: mapping.Resource.Resource, Subresource: "finalizers", Name: ref.Name, ResourceRequest: true, diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission_test.go index db805c9b7..d5eae4465 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission_test.go @@ -20,6 +20,7 @@ import ( "strings" "testing" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -87,7 +88,7 @@ func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) { } genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{}, nil) - pluginInitializer := kubeadmission.NewPluginInitializer(nil, nil, nil, legacyscheme.Registry.RESTMapper(), nil) + pluginInitializer := kubeadmission.NewPluginInitializer(nil, nil, nil, testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme), nil) initializersChain := admission.PluginInitializers{} initializersChain = append(initializersChain, genericPluginInitializer) initializersChain = append(initializersChain, pluginInitializer) @@ -101,6 +102,9 @@ func TestGCAdmission(t *testing.T) { return err == nil } expectCantSetOwnerRefError := func(err error) bool { + if err == nil { + return false + } return strings.Contains(err.Error(), "cannot set an ownerRef on a resource you can't delete") } tests := []struct { @@ -139,7 +143,7 @@ func TestGCAdmission(t *testing.T) { username: "non-deleter", resource: api.SchemeGroupVersion.WithResource("pods"), newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}}, - checkError: expectCantSetOwnerRefError, + checkError: expectNoError, }, { name: "non-pod-deleter, create, no objectref change", @@ -153,7 +157,7 @@ func TestGCAdmission(t *testing.T) { username: "non-pod-deleter", resource: api.SchemeGroupVersion.WithResource("pods"), newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}}, - checkError: expectCantSetOwnerRefError, + checkError: expectNoError, }, { name: "non-pod-deleter, create, objectref change, but not a pod", @@ -253,32 +257,34 @@ func TestGCAdmission(t *testing.T) { checkError: expectNoError, }, } - gcAdmit, err := newGCPermissionsEnforcement() - if err != nil { - t.Error(err) - } for _, tc := range tests { - operation := admission.Create - if tc.oldObj != nil { - operation = admission.Update - } - user := &user.DefaultInfo{Name: tc.username} - attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, user) + t.Run(tc.name, func(t *testing.T) { + gcAdmit, err := newGCPermissionsEnforcement() + if err != nil { + t.Error(err) + } - err := gcAdmit.Validate(attributes) - if !tc.checkError(err) { - t.Errorf("%v: unexpected err: %v", tc.name, err) - } + operation := admission.Create + if tc.oldObj != nil { + operation = admission.Update + } + user := &user.DefaultInfo{Name: tc.username} + attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, user) + + err = gcAdmit.Validate(attributes) + if !tc.checkError(err) { + t.Errorf("unexpected err: %v", err) + } + }) } } func TestBlockOwnerDeletionAdmission(t *testing.T) { podWithOwnerRefs := func(refs ...metav1.OwnerReference) *api.Pod { var refSlice []metav1.OwnerReference - for _, ref := range refs { - refSlice = append(refSlice, ref) - } + refSlice = append(refSlice, refs...) + return &api.Pod{ ObjectMeta: metav1.ObjectMeta{ OwnerReferences: refSlice, diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission.go index 3a3701cf4..76b53c8bb 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission.go @@ -239,7 +239,7 @@ func NewImagePolicyWebhook(configFile io.Reader) (*Plugin, error) { return nil, err } - gw, err := webhook.NewGenericWebhook(legacyscheme.Registry, legacyscheme.Codecs, whConfig.KubeConfigFile, groupVersions, whConfig.RetryBackoff) + gw, err := webhook.NewGenericWebhook(legacyscheme.Scheme, legacyscheme.Codecs, whConfig.KubeConfigFile, groupVersions, whConfig.RetryBackoff) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/gencerts.sh b/vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/gencerts.sh index 384e8f4e9..30304922d 100755 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/gencerts.sh +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/gencerts.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/BUILD deleted file mode 100644 index 243409ddb..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/BUILD +++ /dev/null @@ -1,70 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "admission.go", - "data_source.go", - "gcm.go", - "hawkular.go", - "influxdb.go", - ], - importpath = "k8s.io/kubernetes/plugin/pkg/admission/initialresources", - deps = [ - "//pkg/apis/core:go_default_library", - "//vendor/cloud.google.com/go/compute/metadata:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/hawkular/hawkular-client-go/metrics:go_default_library", - "//vendor/github.com/influxdata/influxdb/client:go_default_library", - "//vendor/golang.org/x/oauth2:go_default_library", - "//vendor/golang.org/x/oauth2/google:go_default_library", - "//vendor/google.golang.org/api/cloudmonitoring/v2beta2:go_default_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/apiserver/pkg/admission:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "admission_test.go", - "data_source_test.go", - "gcm_test.go", - "hawkular_test.go", - "influxdb_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//pkg/apis/core:go_default_library", - "//vendor/github.com/stretchr/testify/require:go_default_library", - "//vendor/golang.org/x/oauth2:go_default_library", - "//vendor/golang.org/x/oauth2/google:go_default_library", - "//vendor/google.golang.org/api/cloudmonitoring/v2beta2: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/apiserver/pkg/admission:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/admission.go deleted file mode 100644 index 4f1c9ecfa..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/admission.go +++ /dev/null @@ -1,220 +0,0 @@ -/* -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 initialresources - -import ( - "flag" - "fmt" - "io" - "sort" - "strings" - "time" - - "github.com/golang/glog" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apiserver/pkg/admission" - api "k8s.io/kubernetes/pkg/apis/core" -) - -var ( - source = flag.String("ir-data-source", "influxdb", "Data source used by InitialResources. Supported options: influxdb, gcm.") - percentile = flag.Int64("ir-percentile", 90, "Which percentile of samples should InitialResources use when estimating resources. For experiment purposes.") - nsOnly = flag.Bool("ir-namespace-only", false, "Whether the estimation should be made only based on data from the same namespace.") -) - -const ( - initialResourcesAnnotation = "kubernetes.io/initial-resources" - samplesThreshold = 30 - week = 7 * 24 * time.Hour - month = 30 * 24 * time.Hour - // PluginName indicates name of admission plugin. - PluginName = "InitialResources" -) - -// Register registers a plugin -// WARNING: this feature is experimental and will definitely change. -func Register(plugins *admission.Plugins) { - plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { - // TODO: remove the usage of flags in favor of reading versioned configuration - s, err := newDataSource(*source) - if err != nil { - return nil, err - } - return newInitialResources(s, *percentile, *nsOnly), nil - }) -} - -type InitialResources struct { - *admission.Handler - source dataSource - percentile int64 - nsOnly bool -} - -var _ admission.MutationInterface = &InitialResources{} - -func newInitialResources(source dataSource, percentile int64, nsOnly bool) *InitialResources { - return &InitialResources{ - Handler: admission.NewHandler(admission.Create), - source: source, - percentile: percentile, - nsOnly: nsOnly, - } -} - -// Admit makes an admission decision based on the request attributes -func (ir InitialResources) Admit(a admission.Attributes) (err error) { - // Ignore all calls to subresources or resources other than pods. - if a.GetSubresource() != "" || a.GetResource().GroupResource() != api.Resource("pods") { - return nil - } - pod, ok := a.GetObject().(*api.Pod) - if !ok { - return apierrors.NewBadRequest("Resource was marked with kind Pod but was unable to be converted") - } - - ir.estimateAndFillResourcesIfNotSet(pod) - return nil -} - -// The method veryfies whether resources should be set for the given pod and -// if there is estimation available the method fills Request field. -func (ir InitialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) { - var annotations []string - for i := range pod.Spec.InitContainers { - annotations = append(annotations, ir.estimateContainer(pod, &pod.Spec.InitContainers[i], "init container")...) - } - for i := range pod.Spec.Containers { - annotations = append(annotations, ir.estimateContainer(pod, &pod.Spec.Containers[i], "container")...) - } - if len(annotations) > 0 { - if pod.ObjectMeta.Annotations == nil { - pod.ObjectMeta.Annotations = make(map[string]string) - } - val := "Initial Resources plugin set: " + strings.Join(annotations, "; ") - pod.ObjectMeta.Annotations[initialResourcesAnnotation] = val - } -} - -func (ir InitialResources) estimateContainer(pod *api.Pod, c *api.Container, message string) []string { - var annotations []string - req := c.Resources.Requests - cpu := ir.getEstimationIfNeeded(api.ResourceCPU, c, pod.ObjectMeta.Namespace) - mem := ir.getEstimationIfNeeded(api.ResourceMemory, c, pod.ObjectMeta.Namespace) - // If Requests doesn't exits and an estimation was made, create Requests. - if req == nil && (cpu != nil || mem != nil) { - c.Resources.Requests = api.ResourceList{} - req = c.Resources.Requests - } - setRes := []string{} - if cpu != nil { - glog.Infof("CPU estimation for %s %v in pod %v/%v is %v", message, c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, cpu.String()) - setRes = append(setRes, string(api.ResourceCPU)) - req[api.ResourceCPU] = *cpu - } - if mem != nil { - glog.Infof("Memory estimation for %s %v in pod %v/%v is %v", message, c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, mem.String()) - setRes = append(setRes, string(api.ResourceMemory)) - req[api.ResourceMemory] = *mem - } - if len(setRes) > 0 { - sort.Strings(setRes) - a := strings.Join(setRes, ", ") + fmt.Sprintf(" request for %s %s", message, c.Name) - annotations = append(annotations, a) - } - return annotations -} - -// getEstimationIfNeeded estimates compute resource for container if its corresponding -// Request(min amount) and Limit(max amount) both are not specified. -func (ir InitialResources) getEstimationIfNeeded(kind api.ResourceName, c *api.Container, ns string) *resource.Quantity { - requests := c.Resources.Requests - limits := c.Resources.Limits - var quantity *resource.Quantity - var err error - if _, requestFound := requests[kind]; !requestFound { - if _, limitFound := limits[kind]; !limitFound { - quantity, err = ir.getEstimation(kind, c, ns) - if err != nil { - glog.Errorf("Error while trying to estimate resources: %v", err) - } - } - } - return quantity -} -func (ir InitialResources) getEstimation(kind api.ResourceName, c *api.Container, ns string) (*resource.Quantity, error) { - end := time.Now() - start := end.Add(-week) - var usage, samples int64 - var err error - - // Historical data from last 7 days for the same image:tag within the same namespace. - if usage, samples, err = ir.source.GetUsagePercentile(kind, ir.percentile, c.Image, ns, true, start, end); err != nil { - return nil, err - } - if samples < samplesThreshold { - // Historical data from last 30 days for the same image:tag within the same namespace. - start := end.Add(-month) - if usage, samples, err = ir.source.GetUsagePercentile(kind, ir.percentile, c.Image, ns, true, start, end); err != nil { - return nil, err - } - } - - // If we are allowed to estimate only based on data from the same namespace. - if ir.nsOnly { - if samples < samplesThreshold { - // Historical data from last 30 days for the same image within the same namespace. - start := end.Add(-month) - image := strings.Split(c.Image, ":")[0] - if usage, samples, err = ir.source.GetUsagePercentile(kind, ir.percentile, image, ns, false, start, end); err != nil { - return nil, err - } - } - } else { - if samples < samplesThreshold { - // Historical data from last 7 days for the same image:tag within all namespaces. - start := end.Add(-week) - if usage, samples, err = ir.source.GetUsagePercentile(kind, ir.percentile, c.Image, "", true, start, end); err != nil { - return nil, err - } - } - if samples < samplesThreshold { - // Historical data from last 30 days for the same image:tag within all namespaces. - start := end.Add(-month) - if usage, samples, err = ir.source.GetUsagePercentile(kind, ir.percentile, c.Image, "", true, start, end); err != nil { - return nil, err - } - } - if samples < samplesThreshold { - // Historical data from last 30 days for the same image within all namespaces. - start := end.Add(-month) - image := strings.Split(c.Image, ":")[0] - if usage, samples, err = ir.source.GetUsagePercentile(kind, ir.percentile, image, "", false, start, end); err != nil { - return nil, err - } - } - } - - if samples > 0 && kind == api.ResourceCPU { - return resource.NewMilliQuantity(usage, resource.DecimalSI), nil - } - if samples > 0 && kind == api.ResourceMemory { - return resource.NewQuantity(usage, resource.DecimalSI), nil - } - return nil, nil -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/admission_test.go deleted file mode 100644 index a265fd93a..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/admission_test.go +++ /dev/null @@ -1,300 +0,0 @@ -/* -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 initialresources - -import ( - "errors" - "testing" - "time" - - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apiserver/pkg/admission" - api "k8s.io/kubernetes/pkg/apis/core" -) - -type fakeSource struct { - f func(kind api.ResourceName, perc int64, image, namespace string, exactMatch bool, start, end time.Time) (int64, int64, error) -} - -func (s *fakeSource) GetUsagePercentile(kind api.ResourceName, perc int64, image, namespace string, exactMatch bool, start, end time.Time) (usage int64, samples int64, err error) { - return s.f(kind, perc, image, namespace, exactMatch, start, end) -} - -func parseReq(cpu, mem string) api.ResourceList { - if cpu == "" && mem == "" { - return nil - } - req := api.ResourceList{} - if cpu != "" { - req[api.ResourceCPU] = resource.MustParse(cpu) - } - if mem != "" { - req[api.ResourceMemory] = resource.MustParse(mem) - } - return req -} - -func addContainer(pod *api.Pod, name, image string, request api.ResourceList) { - pod.Spec.Containers = append(pod.Spec.Containers, api.Container{ - Name: name, - Image: image, - Resources: api.ResourceRequirements{Requests: request}, - }) -} - -func createPod(name string, image string, request api.ResourceList) *api.Pod { - pod := &api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "test-ns"}, - Spec: api.PodSpec{}, - } - pod.Spec.Containers = []api.Container{} - addContainer(pod, "i0", image, request) - pod.Spec.InitContainers = pod.Spec.Containers - pod.Spec.Containers = []api.Container{} - addContainer(pod, "c0", image, request) - return pod -} - -func getPods() []*api.Pod { - return []*api.Pod{ - createPod("p0", "image:v0", parseReq("", "")), - createPod("p1", "image:v1", parseReq("", "300")), - createPod("p2", "image:v2", parseReq("300m", "")), - createPod("p3", "image:v3", parseReq("300m", "300")), - } -} - -func verifyContainer(t *testing.T, c *api.Container, cpu, mem int64) { - req := c.Resources.Requests - if req.Cpu().MilliValue() != cpu { - t.Errorf("Wrong CPU request for container %v. Expected %v, got %v.", c.Name, cpu, req.Cpu().MilliValue()) - } - if req.Memory().Value() != mem { - t.Errorf("Wrong memory request for container %v. Expected %v, got %v.", c.Name, mem, req.Memory().Value()) - } -} - -func verifyPod(t *testing.T, pod *api.Pod, cpu, mem int64) { - verifyContainer(t, &pod.Spec.Containers[0], cpu, mem) - verifyContainer(t, &pod.Spec.InitContainers[0], cpu, mem) -} - -func verifyAnnotation(t *testing.T, pod *api.Pod, expected string) { - a, ok := pod.ObjectMeta.Annotations[initialResourcesAnnotation] - if !ok { - t.Errorf("No annotation but expected %v", expected) - } - if a != expected { - t.Errorf("Wrong annotation set by Initial Resources: got %v, expected %v", a, expected) - } -} - -func expectNoAnnotation(t *testing.T, pod *api.Pod) { - if a, ok := pod.ObjectMeta.Annotations[initialResourcesAnnotation]; ok { - t.Errorf("Expected no annotation but got %v", a) - } -} - -func admit(t *testing.T, ir admission.MutationInterface, pods []*api.Pod) { - for i := range pods { - p := pods[i] - - podKind := api.Kind("Pod").WithVersion("version") - podRes := api.Resource("pods").WithVersion("version") - attrs := admission.NewAttributesRecord(p, nil, podKind, "test", p.ObjectMeta.Name, podRes, "", admission.Create, nil) - if err := ir.Admit(attrs); err != nil { - t.Error(err) - } - } -} - -func testAdminScenarios(t *testing.T, ir admission.MutationInterface, p *api.Pod) { - podKind := api.Kind("Pod").WithVersion("version") - podRes := api.Resource("pods").WithVersion("version") - - var tests = []struct { - attrs admission.Attributes - expectError bool - }{ - { - admission.NewAttributesRecord(p, nil, podKind, "test", p.ObjectMeta.Name, podRes, "foo", admission.Create, nil), - false, - }, - { - admission.NewAttributesRecord(&api.ReplicationController{}, nil, podKind, "test", "", podRes, "", admission.Create, nil), - true, - }, - } - - for _, test := range tests { - err := ir.Admit(test.attrs) - if err != nil && test.expectError == false { - t.Error(err) - } else if err == nil && test.expectError == true { - t.Error("Error expected for Admit but received none") - } - } -} - -func performTest(t *testing.T, ir admission.MutationInterface) { - pods := getPods() - admit(t, ir, pods) - testAdminScenarios(t, ir, pods[0]) - - verifyPod(t, pods[0], 100, 100) - verifyPod(t, pods[1], 100, 300) - verifyPod(t, pods[2], 300, 100) - verifyPod(t, pods[3], 300, 300) - - verifyAnnotation(t, pods[0], "Initial Resources plugin set: cpu, memory request for init container i0; cpu, memory request for container c0") - verifyAnnotation(t, pods[1], "Initial Resources plugin set: cpu request for init container i0") - verifyAnnotation(t, pods[2], "Initial Resources plugin set: memory request for init container i0") - expectNoAnnotation(t, pods[3]) -} - -func TestEstimateReturnsErrorFromSource(t *testing.T) { - f := func(_ api.ResourceName, _ int64, _, ns string, exactMatch bool, start, end time.Time) (int64, int64, error) { - return 0, 0, errors.New("Example error") - } - ir := newInitialResources(&fakeSource{f: f}, 90, false) - admit(t, ir, getPods()) -} - -func TestEstimationBasedOnTheSameImageSameNamespace7d(t *testing.T) { - f := func(_ api.ResourceName, _ int64, _, ns string, exactMatch bool, start, end time.Time) (int64, int64, error) { - if exactMatch && end.Sub(start) == week && ns == "test-ns" { - return 100, 120, nil - } - return 200, 120, nil - } - performTest(t, newInitialResources(&fakeSource{f: f}, 90, false)) -} - -func TestEstimationBasedOnTheSameImageSameNamespace30d(t *testing.T) { - f := func(_ api.ResourceName, _ int64, _, ns string, exactMatch bool, start, end time.Time) (int64, int64, error) { - if exactMatch && end.Sub(start) == week && ns == "test-ns" { - return 200, 20, nil - } - if exactMatch && end.Sub(start) == month && ns == "test-ns" { - return 100, 120, nil - } - return 200, 120, nil - } - performTest(t, newInitialResources(&fakeSource{f: f}, 90, false)) -} - -func TestEstimationBasedOnTheSameImageAllNamespaces7d(t *testing.T) { - f := func(_ api.ResourceName, _ int64, _, ns string, exactMatch bool, start, end time.Time) (int64, int64, error) { - if exactMatch && ns == "test-ns" { - return 200, 20, nil - } - if exactMatch && end.Sub(start) == week && ns == "" { - return 100, 120, nil - } - return 200, 120, nil - } - performTest(t, newInitialResources(&fakeSource{f: f}, 90, false)) -} - -func TestEstimationBasedOnTheSameImageAllNamespaces30d(t *testing.T) { - f := func(_ api.ResourceName, _ int64, _, ns string, exactMatch bool, start, end time.Time) (int64, int64, error) { - if exactMatch && ns == "test-ns" { - return 200, 20, nil - } - if exactMatch && end.Sub(start) == week && ns == "" { - return 200, 20, nil - } - if exactMatch && end.Sub(start) == month && ns == "" { - return 100, 120, nil - } - return 200, 120, nil - } - performTest(t, newInitialResources(&fakeSource{f: f}, 90, false)) -} - -func TestEstimationBasedOnOtherImages(t *testing.T) { - f := func(_ api.ResourceName, _ int64, image, ns string, exactMatch bool, _, _ time.Time) (int64, int64, error) { - if image == "image" && !exactMatch && ns == "" { - return 100, 5, nil - } - return 200, 20, nil - } - performTest(t, newInitialResources(&fakeSource{f: f}, 90, false)) -} - -func TestNoData(t *testing.T) { - f := func(_ api.ResourceName, _ int64, _, ns string, _ bool, _, _ time.Time) (int64, int64, error) { - return 200, 0, nil - } - ir := newInitialResources(&fakeSource{f: f}, 90, false) - - pods := []*api.Pod{ - createPod("p0", "image:v0", parseReq("", "")), - } - admit(t, ir, pods) - - if pods[0].Spec.Containers[0].Resources.Requests != nil { - t.Errorf("Unexpected resource estimation") - } - - expectNoAnnotation(t, pods[0]) -} - -func TestManyContainers(t *testing.T) { - f := func(_ api.ResourceName, _ int64, _, ns string, exactMatch bool, _, _ time.Time) (int64, int64, error) { - if exactMatch { - return 100, 120, nil - } - return 200, 30, nil - } - ir := newInitialResources(&fakeSource{f: f}, 90, false) - - pod := createPod("p", "image:v0", parseReq("", "")) - addContainer(pod, "c1", "image:v1", parseReq("", "300")) - addContainer(pod, "c2", "image:v2", parseReq("300m", "")) - addContainer(pod, "c3", "image:v3", parseReq("300m", "300")) - admit(t, ir, []*api.Pod{pod}) - - verifyContainer(t, &pod.Spec.Containers[0], 100, 100) - verifyContainer(t, &pod.Spec.Containers[1], 100, 300) - verifyContainer(t, &pod.Spec.Containers[2], 300, 100) - verifyContainer(t, &pod.Spec.Containers[3], 300, 300) - - verifyAnnotation(t, pod, "Initial Resources plugin set: cpu, memory request for init container i0; cpu, memory request for container c0; cpu request for container c1; memory request for container c2") -} - -func TestNamespaceAware(t *testing.T) { - f := func(_ api.ResourceName, _ int64, _, ns string, exactMatch bool, start, end time.Time) (int64, int64, error) { - if ns == "test-ns" { - return 200, 0, nil - } - return 200, 120, nil - } - ir := newInitialResources(&fakeSource{f: f}, 90, true) - - pods := []*api.Pod{ - createPod("p0", "image:v0", parseReq("", "")), - } - admit(t, ir, pods) - - if pods[0].Spec.Containers[0].Resources.Requests != nil { - t.Errorf("Unexpected resource estimation") - } - - expectNoAnnotation(t, pods[0]) -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/data_source.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/data_source.go deleted file mode 100644 index a25f5ee80..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/data_source.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -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 initialresources - -import ( - "flag" - "fmt" - api "k8s.io/kubernetes/pkg/apis/core" - "time" -) - -var ( - influxdbHost = flag.String("ir-influxdb-host", "localhost:8080/api/v1/namespaces/kube-system/services/monitoring-influxdb:api/proxy", "Address of InfluxDB which contains metrics required by InitialResources") - user = flag.String("ir-user", "root", "User used for connecting to InfluxDB") - // TODO: figure out how to better pass password here - password = flag.String("ir-password", "root", "Password used for connecting to InfluxDB") - db = flag.String("ir-dbname", "k8s", "InfluxDB database name which contains metrics required by InitialResources") - hawkularConfig = flag.String("ir-hawkular", "", "Hawkular configuration URL") -) - -// WARNING: If you are planning to add another implementation of dataSource interface please bear in mind, -// that dataSource will be moved to Heapster some time in the future and possibly rewritten. -type dataSource interface { - // Returns th of sample values which represent usage of for containers running , - // within time range (start, end), number of samples considered and error if occurred. - // If then take only samples that concern the same image (both name and take are the same), - // otherwise consider also samples with the same image a possibly different tag. - GetUsagePercentile(kind api.ResourceName, perc int64, image, namespace string, exactMatch bool, start, end time.Time) (usage int64, samples int64, err error) -} - -func newDataSource(kind string) (dataSource, error) { - if kind == "influxdb" { - return newInfluxdbSource(*influxdbHost, *user, *password, *db) - } - if kind == "gcm" { - return newGcmSource() - } - if kind == "hawkular" { - return newHawkularSource(*hawkularConfig) - } - return nil, fmt.Errorf("unknown data source %v", kind) -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/data_source_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/data_source_test.go deleted file mode 100644 index 08b21b24d..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/data_source_test.go +++ /dev/null @@ -1,45 +0,0 @@ -/* -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 initialresources - -import "testing" - -func TestInfluxDBDataSource(t *testing.T) { - ds, _ := newDataSource("influxdb") - if _, ok := ds.(*influxdbSource); !ok { - t.Errorf("newDataSource did not return valid InfluxDB type") - } -} - -func TestGCMDataSource(t *testing.T) { - // No ProjectID set - newDataSource("gcm") -} - -func TestHawkularDataSource(t *testing.T) { - ds, _ := newDataSource("hawkular") - if _, ok := ds.(*hawkularSource); !ok { - t.Errorf("newDataSource did not return valid hawkularSource type") - } -} - -func TestNoDataSourceFound(t *testing.T) { - ds, err := newDataSource("") - if ds != nil || err == nil { - t.Errorf("newDataSource found for empty input") - } -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/gcm.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/gcm.go deleted file mode 100644 index fbe64b5db..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/gcm.go +++ /dev/null @@ -1,132 +0,0 @@ -/* -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 initialresources - -import ( - api "k8s.io/kubernetes/pkg/apis/core" - "math" - "sort" - "time" - - gce "cloud.google.com/go/compute/metadata" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - gcm "google.golang.org/api/cloudmonitoring/v2beta2" -) - -const ( - kubePrefix = "custom.cloudmonitoring.googleapis.com/kubernetes.io/" - cpuMetricName = kubePrefix + "cpu/usage_rate" - memMetricName = kubePrefix + "memory/usage" - labelImage = kubePrefix + "label/container_base_image" - labelNs = kubePrefix + "label/pod_namespace" -) - -type gcmSource struct { - project string - gcmService *gcm.Service -} - -func newGcmSource() (dataSource, error) { - // Detect project ID - projectId, err := gce.ProjectID() - if err != nil { - return nil, err - } - - // Create Google Cloud Monitoring service. - client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource("")) - s, err := gcm.New(client) - if err != nil { - return nil, err - } - - return &gcmSource{ - project: projectId, - gcmService: s, - }, nil -} - -func (s *gcmSource) query(metric, oldest, youngest string, labels []string, pageToken string) (*gcm.ListTimeseriesResponse, error) { - req := s.gcmService.Timeseries.List(s.project, metric, youngest, nil). - Oldest(oldest). - Aggregator("mean"). - Window("1m") - for _, l := range labels { - req = req.Labels(l) - } - if pageToken != "" { - req = req.PageToken(pageToken) - } - return req.Do() -} - -func retrieveRawSamples(res *gcm.ListTimeseriesResponse, output *[]int) { - for _, ts := range res.Timeseries { - for _, p := range ts.Points { - *output = append(*output, int(*p.DoubleValue)) - } - } -} - -func (s *gcmSource) GetUsagePercentile(kind api.ResourceName, perc int64, image, namespace string, exactMatch bool, start, end time.Time) (int64, int64, error) { - var metric string - if kind == api.ResourceCPU { - metric = cpuMetricName - } else if kind == api.ResourceMemory { - metric = memMetricName - } - - var labels []string - if exactMatch { - labels = append(labels, labelImage+"=="+image) - } else { - labels = append(labels, labelImage+"=~"+image+".*") - } - if namespace != "" { - labels = append(labels, labelNs+"=="+namespace) - } - - oldest := start.Format(time.RFC3339) - youngest := end.Format(time.RFC3339) - - rawSamples := make([]int, 0) - pageToken := "" - for { - res, err := s.query(metric, oldest, youngest, labels, pageToken) - if err != nil { - return 0, 0, err - } - - retrieveRawSamples(res, &rawSamples) - - pageToken = res.NextPageToken - if pageToken == "" { - break - } - } - - count := len(rawSamples) - if count == 0 { - return 0, 0, nil - } - sort.Ints(rawSamples) - usageIndex := int64(math.Ceil(float64(count)*9/10)) - 1 - usage := rawSamples[usageIndex] - - return int64(usage), int64(count), nil -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/gcm_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/gcm_test.go deleted file mode 100644 index b03960bb3..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/gcm_test.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -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 initialresources - -import ( - "testing" - "time" - - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - gcm "google.golang.org/api/cloudmonitoring/v2beta2" - api "k8s.io/kubernetes/pkg/apis/core" -) - -func TestGCMReturnsErrorIfClientCannotConnect(t *testing.T) { - client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource("")) - service, _ := gcm.New(client) - source := &gcmSource{ - project: "", - gcmService: service, - } - - _, _, err := source.GetUsagePercentile(api.ResourceCPU, 90, "", "", true, time.Now(), time.Now()) - if err == nil { - t.Errorf("Expected error from GCM") - } - - _, _, err = source.GetUsagePercentile(api.ResourceMemory, 90, "", "foo", false, time.Now(), time.Now()) - if err == nil { - t.Errorf("Expected error from GCM") - } -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/hawkular.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/hawkular.go deleted file mode 100644 index 1f5aaea42..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/hawkular.go +++ /dev/null @@ -1,223 +0,0 @@ -/* -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 initialresources - -import ( - "crypto/tls" - "crypto/x509" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "strconv" - "strings" - "time" - - "github.com/golang/glog" - "github.com/hawkular/hawkular-client-go/metrics" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - api "k8s.io/kubernetes/pkg/apis/core" - - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" -) - -type hawkularSource struct { - client *metrics.Client - uri *url.URL - useNamespace bool - modifiers []metrics.Modifier -} - -const ( - containerImageTag string = "container_base_image" - descriptorTag string = "descriptor_name" - separator string = "/" - - defaultServiceAccountFile = "/var/run/secrets/kubernetes.io/serviceaccount/token" -) - -// heapsterName gets the equivalent MetricDescriptor.Name used in the Heapster -func heapsterName(kind api.ResourceName) string { - switch kind { - case api.ResourceCPU: - return "cpu/usage" - case api.ResourceMemory: - return "memory/usage" - default: - return "" - } -} - -// tagQuery creates tagFilter query for Hawkular -func tagQuery(kind api.ResourceName, image string, exactMatch bool) map[string]string { - q := make(map[string]string) - - // Add here the descriptor_tag.. - q[descriptorTag] = heapsterName(kind) - - if exactMatch { - q[containerImageTag] = image - } else { - split := strings.Index(image, "@") - if split < 0 { - split = strings.Index(image, ":") - } - q[containerImageTag] = fmt.Sprintf("%s:*", image[:split]) - } - - return q -} - -// dataSource API - -func (hs *hawkularSource) GetUsagePercentile(kind api.ResourceName, perc int64, image, namespace string, exactMatch bool, start, end time.Time) (int64, int64, error) { - q := tagQuery(kind, image, exactMatch) - - m := make([]metrics.Modifier, len(hs.modifiers), 2+len(hs.modifiers)) - copy(m, hs.modifiers) - - if namespace != metav1.NamespaceAll { - m = append(m, metrics.Tenant(namespace)) - } - - p := float64(perc) - m = append(m, metrics.Filters(metrics.TagsFilter(q), metrics.BucketsFilter(1), metrics.StartTimeFilter(start), metrics.EndTimeFilter(end), metrics.PercentilesFilter([]float64{p}))) - - bp, err := hs.client.ReadBuckets(metrics.Counter, m...) - if err != nil { - return 0, 0, err - } - - if len(bp) > 0 && len(bp[0].Percentiles) > 0 { - return int64(bp[0].Percentiles[0].Value), int64(bp[0].Samples), nil - } - return 0, 0, nil -} - -// newHawkularSource creates a new Hawkular Source. The uri follows the scheme from Heapster -func newHawkularSource(uri string) (dataSource, error) { - u, err := url.Parse(uri) - if err != nil { - return nil, err - } - - d := &hawkularSource{ - uri: u, - } - if err = d.init(); err != nil { - return nil, err - } - return d, nil -} - -// init initializes the Hawkular dataSource. Almost equal to the Heapster initialization -func (hs *hawkularSource) init() error { - hs.modifiers = make([]metrics.Modifier, 0) - p := metrics.Parameters{ - Tenant: "heapster", // This data is stored by the heapster - for no-namespace hits - Url: hs.uri.String(), - } - - opts := hs.uri.Query() - - if v, found := opts["tenant"]; found { - p.Tenant = v[0] - } - - if v, found := opts["useServiceAccount"]; found { - if b, _ := strconv.ParseBool(v[0]); b { - accountFile := defaultServiceAccountFile - if file, f := opts["serviceAccountFile"]; f { - accountFile = file[0] - } - - // If a readable service account token exists, then use it - if contents, err := ioutil.ReadFile(accountFile); err == nil { - p.Token = string(contents) - } else { - glog.Errorf("Could not read contents of %s, no token authentication is used\n", defaultServiceAccountFile) - } - } - } - - // Authentication / Authorization parameters - tC := &tls.Config{} - - if v, found := opts["auth"]; found { - if _, f := opts["caCert"]; f { - return fmt.Errorf("both auth and caCert files provided, combination is not supported") - } - if len(v[0]) > 0 { - // Authfile - kubeConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(&clientcmd.ClientConfigLoadingRules{ - ExplicitPath: v[0]}, - &clientcmd.ConfigOverrides{}).ClientConfig() - if err != nil { - return err - } - tC, err = restclient.TLSConfigFor(kubeConfig) - if err != nil { - return err - } - } - } - - if u, found := opts["user"]; found { - if _, wrong := opts["useServiceAccount"]; wrong { - return fmt.Errorf("if user and password are used, serviceAccount cannot be used") - } - if p, f := opts["pass"]; f { - hs.modifiers = append(hs.modifiers, func(req *http.Request) error { - req.SetBasicAuth(u[0], p[0]) - return nil - }) - } - } - - if v, found := opts["caCert"]; found { - caCert, err := ioutil.ReadFile(v[0]) - if err != nil { - return err - } - - caCertPool := x509.NewCertPool() - caCertPool.AppendCertsFromPEM(caCert) - - tC.RootCAs = caCertPool - } - - if v, found := opts["insecure"]; found { - insecure, err := strconv.ParseBool(v[0]) - if err != nil { - return err - } - tC.InsecureSkipVerify = insecure - } - - p.TLSConfig = tC - - c, err := metrics.NewHawkularClient(p) - if err != nil { - return err - } - - hs.client = c - - glog.Infof("Initialised Hawkular Source with parameters %v", p) - return nil -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/hawkular_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/hawkular_test.go deleted file mode 100644 index 306728f0b..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/hawkular_test.go +++ /dev/null @@ -1,142 +0,0 @@ -/* -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 initialresources - -import ( - "fmt" - api "k8s.io/kubernetes/pkg/apis/core" - "net/http" - "net/http/httptest" - "net/url" - "strings" - "testing" - "time" - - assert "github.com/stretchr/testify/require" -) - -const ( - testImageName string = "hawkular/hawkular-metrics" - testImageVersion string = "latest" - testImageSHA string = "b727ece3780cdd30e9a86226e520f26bcc396071ed7a86b7ef6684bb93a9f717" - testPartialMatch string = "hawkular/hawkular-metrics:*" -) - -func testImageWithVersion() string { - return fmt.Sprintf("%s:%s", testImageName, testImageVersion) -} - -func testImageWithReference() string { - return fmt.Sprintf("%s@sha256:%s", testImageName, testImageSHA) -} - -func TestTaqQuery(t *testing.T) { - kind := api.ResourceCPU - tQ := tagQuery(kind, testImageWithVersion(), false) - - assert.Equal(t, 2, len(tQ)) - assert.Equal(t, testPartialMatch, tQ[containerImageTag]) - assert.Equal(t, "cpu/usage", tQ[descriptorTag]) - - tQe := tagQuery(kind, testImageWithVersion(), true) - assert.Equal(t, 2, len(tQe)) - assert.Equal(t, testImageWithVersion(), tQe[containerImageTag]) - assert.Equal(t, "cpu/usage", tQe[descriptorTag]) - - tQr := tagQuery(kind, testImageWithReference(), false) - assert.Equal(t, 2, len(tQe)) - assert.Equal(t, testPartialMatch, tQr[containerImageTag]) - assert.Equal(t, "cpu/usage", tQr[descriptorTag]) - - tQre := tagQuery(kind, testImageWithReference(), true) - assert.Equal(t, 2, len(tQe)) - assert.Equal(t, testImageWithReference(), tQre[containerImageTag]) - assert.Equal(t, "cpu/usage", tQre[descriptorTag]) - - kind = api.ResourceMemory - tQ = tagQuery(kind, testImageWithReference(), true) - assert.Equal(t, "memory/usage", tQ[descriptorTag]) - - kind = api.ResourceStorage - tQ = tagQuery(kind, testImageWithReference(), true) - assert.Equal(t, "", tQ[descriptorTag]) -} - -func newSource(t *testing.T) (map[string]string, dataSource) { - tenant := "16a8884e4c155457ee38a8901df6b536" - reqs := make(map[string]string) - - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, tenant, r.Header.Get("Hawkular-Tenant")) - assert.Equal(t, "Basic", r.Header.Get("Authorization")[:5]) - - if strings.Contains(r.RequestURI, "counters/data") { - assert.True(t, strings.Contains(r.RequestURI, url.QueryEscape(testImageWithVersion()))) - assert.True(t, strings.Contains(r.RequestURI, "cpu%2Fusage")) - assert.True(t, strings.Contains(r.RequestURI, "percentiles=90")) - - reqs["counters/data"] = r.RequestURI - fmt.Fprintf(w, ` [{"start":1444620095882,"end":1444648895882,"min":1.45,"avg":1.45,"median":1.45,"max":1.45,"percentile95th":1.45,"samples":123456,"percentiles":[{"value":7896.54,"quantile":0.9},{"value":1.45,"quantile":0.99}],"empty":false}]`) - } else { - reqs["unknown"] = r.RequestURI - } - })) - - paramUri := fmt.Sprintf("%s?user=test&pass=yep&tenant=foo&insecure=true", s.URL) - - hSource, err := newHawkularSource(paramUri) - assert.NoError(t, err) - - return reqs, hSource -} - -func TestInsecureMustBeBool(t *testing.T) { - paramUri := fmt.Sprintf("localhost?user=test&pass=yep&insecure=foo") - _, err := newHawkularSource(paramUri) - if err == nil { - t.Errorf("Expected error from newHawkularSource") - } -} - -func TestCAFileMustExist(t *testing.T) { - paramUri := fmt.Sprintf("localhost?user=test&pass=yep&caCert=foo") - _, err := newHawkularSource(paramUri) - if err == nil { - t.Errorf("Expected error from newHawkularSource") - } -} - -func TestServiceAccountIsMutuallyExclusiveWithAuth(t *testing.T) { - paramUri := fmt.Sprintf("localhost?user=test&pass=yep&useServiceAccount=true") - _, err := newHawkularSource(paramUri) - if err == nil { - t.Errorf("Expected error from newHawkularSource") - } -} - -func TestGetUsagePercentile(t *testing.T) { - reqs, hSource := newSource(t) - - usage, samples, err := hSource.GetUsagePercentile(api.ResourceCPU, 90, testImageWithVersion(), "16a8884e4c155457ee38a8901df6b536", true, time.Now(), time.Now()) - assert.NoError(t, err) - - assert.Equal(t, 1, len(reqs)) - assert.Equal(t, "", reqs["unknown"]) - - assert.Equal(t, int64(123456), int64(samples)) - assert.Equal(t, int64(7896), usage) // float64 -> int64 -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/influxdb.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/influxdb.go deleted file mode 100644 index 2986367a7..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/influxdb.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -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 initialresources - -import ( - "fmt" - "strings" - "time" - - influxdb "github.com/influxdata/influxdb/client" - api "k8s.io/kubernetes/pkg/apis/core" -) - -const ( - cpuSeriesName = "autoscaling.cpu.usage.2m" - memSeriesName = "autoscaling.memory.usage.2m" - cpuContinuousQuery = "select derivative(value) as value from \"cpu/usage_ns_cumulative\" where pod_id <> '' group by pod_id, pod_namespace, container_name, container_base_image, time(2m) into " + cpuSeriesName - memContinuousQuery = "select mean(value) as value from \"memory/usage_bytes_gauge\" where pod_id <> '' group by pod_id, pod_namespace, container_name, container_base_image, time(2m) into " + memSeriesName - timeFormat = "2006-01-02 15:04:05" -) - -// TODO(piosz): rewrite this once we will migrate into InfluxDB v0.9. -type influxdbSource struct{} - -func newInfluxdbSource(host, user, password, db string) (dataSource, error) { - return &influxdbSource{}, nil -} - -func (s *influxdbSource) query(query string) ([]*influxdb.Response, error) { - // TODO(piosz): add support again - return nil, fmt.Errorf("temporary not supported; see #18826 for more details") -} - -func (s *influxdbSource) GetUsagePercentile(kind api.ResourceName, perc int64, image, namespace string, exactMatch bool, start, end time.Time) (int64, int64, error) { - var series string - if kind == api.ResourceCPU { - series = cpuSeriesName - } else if kind == api.ResourceMemory { - series = memSeriesName - } - - var imgPattern string - if exactMatch { - imgPattern = "='" + image + "'" - } else { - // Escape character "/" in image pattern. - imgPattern = "=~/^" + strings.Replace(image, "/", "\\/", -1) + "/" - } - var namespaceCond string - if namespace != "" { - namespaceCond = " and pod_namespace='" + namespace + "'" - } - - query := fmt.Sprintf("select percentile(value, %v), count(pod_id) from %v where container_base_image%v%v and time > '%v' and time < '%v'", perc, series, imgPattern, namespaceCond, start.UTC().Format(timeFormat), end.UTC().Format(timeFormat)) - if _, err := s.query(query); err != nil { - return 0, 0, fmt.Errorf("error while trying to query InfluxDB: %v", err) - } - return 0, 0, nil -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/influxdb_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/influxdb_test.go deleted file mode 100644 index 34106ee72..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/influxdb_test.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -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 initialresources - -import ( - "testing" - "time" - - api "k8s.io/kubernetes/pkg/apis/core" -) - -func TestInfluxDBGetUsagePercentileCPU(t *testing.T) { - source, _ := newInfluxdbSource("", "", "", "") - _, _, err := source.GetUsagePercentile(api.ResourceCPU, 90, "", "", true, time.Now(), time.Now()) - if err == nil { - t.Errorf("Expected error because InfluxDB is temporarily disabled") - } -} - -func TestInfluxDBGetUsagePercentileMemory(t *testing.T) { - source, _ := newInfluxdbSource("", "", "", "") - _, _, err := source.GetUsagePercentile(api.ResourceMemory, 90, "", "foo", false, time.Now(), time.Now()) - if err == nil { - t.Errorf("Expected error because InfluxDB is temporarily disabled") - } -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/BUILD index 4e83ee515..25fe19953 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/BUILD @@ -16,13 +16,12 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/auth/nodeidentifier:go_default_library", - "//pkg/client/clientset_generated/internalclientset:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", + "//pkg/client/informers/informers_generated/internalversion:go_default_library", + "//pkg/client/listers/core/internalversion:go_default_library", "//pkg/features:go_default_library", "//pkg/kubeapiserver/admission:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", @@ -38,14 +37,14 @@ go_test( "//pkg/apis/core:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/auth/nodeidentifier:go_default_library", - "//pkg/client/clientset_generated/internalclientset/fake:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", + "//pkg/client/listers/core/internalversion:go_default_library", "//pkg/features:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/OWNERS b/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/OWNERS index c44dfc9fa..77eb1f5a7 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/OWNERS +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/OWNERS @@ -2,7 +2,9 @@ approvers: - deads2k - liggitt - tallclair +- mikedanese reviewers: - deads2k - liggitt - tallclair +- mikedanese diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission.go index 333506e66..1b9851dd5 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission.go @@ -22,7 +22,6 @@ import ( apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apiserver/pkg/admission" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -31,8 +30,8 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/auth/nodeidentifier" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - coreinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" + informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" + internalversion "k8s.io/kubernetes/pkg/client/listers/core/internalversion" "k8s.io/kubernetes/pkg/features" kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" ) @@ -62,18 +61,18 @@ func NewPlugin(nodeIdentifier nodeidentifier.NodeIdentifier) *nodePlugin { type nodePlugin struct { *admission.Handler nodeIdentifier nodeidentifier.NodeIdentifier - podsGetter coreinternalversion.PodsGetter + podsGetter internalversion.PodLister // allows overriding for testing features utilfeature.FeatureGate } var ( _ = admission.Interface(&nodePlugin{}) - _ = kubeapiserveradmission.WantsInternalKubeClientSet(&nodePlugin{}) + _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&nodePlugin{}) ) -func (p *nodePlugin) SetInternalKubeClientSet(f internalclientset.Interface) { - p.podsGetter = f.Core() +func (p *nodePlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { + p.podsGetter = f.Core().InternalVersion().Pods().Lister() } func (p *nodePlugin) ValidateInitialization() error { @@ -183,14 +182,10 @@ func (c *nodePlugin) admitPod(nodeName string, a admission.Attributes) error { return nil case admission.Delete: - // get the existing pod from the server cache - existingPod, err := c.podsGetter.Pods(a.GetNamespace()).Get(a.GetName(), v1.GetOptions{ResourceVersion: "0"}) + // get the existing pod + existingPod, err := c.podsGetter.Pods(a.GetNamespace()).Get(a.GetName()) if errors.IsNotFound(err) { - // wasn't found in the server cache, do a live lookup before forbidding - existingPod, err = c.podsGetter.Pods(a.GetNamespace()).Get(a.GetName(), v1.GetOptions{}) - if errors.IsNotFound(err) { - return err - } + return err } if err != nil { return admission.NewForbidden(a, err) @@ -241,14 +236,10 @@ func (c *nodePlugin) admitPodEviction(nodeName string, a admission.Attributes) e } podName = eviction.Name } - // get the existing pod from the server cache - existingPod, err := c.podsGetter.Pods(a.GetNamespace()).Get(podName, v1.GetOptions{ResourceVersion: "0"}) + // get the existing pod + existingPod, err := c.podsGetter.Pods(a.GetNamespace()).Get(podName) if errors.IsNotFound(err) { - // wasn't found in the server cache, do a live lookup before forbidding - existingPod, err = c.podsGetter.Pods(a.GetNamespace()).Get(podName, v1.GetOptions{}) - if errors.IsNotFound(err) { - return err - } + return err } if err != nil { return admission.NewForbidden(a, err) @@ -347,6 +338,12 @@ func (c *nodePlugin) admitNode(nodeName string, a admission.Attributes) error { if node.Spec.ConfigSource != nil && !apiequality.Semantic.DeepEqual(node.Spec.ConfigSource, oldNode.Spec.ConfigSource) { return admission.NewForbidden(a, fmt.Errorf("cannot update configSource to a new non-nil configSource")) } + + // Don't allow a node to update its own taints. This would allow a node to remove or modify its + // taints in a way that would let it steer disallowed workloads to itself. + if !apiequality.Semantic.DeepEqual(node.Spec.Taints, oldNode.Spec.Taints) { + return admission.NewForbidden(a, fmt.Errorf("cannot modify taints")) + } } return nil @@ -376,7 +373,7 @@ func (c *nodePlugin) admitServiceAccount(nodeName string, a admission.Attributes if ref.UID == "" { return admission.NewForbidden(a, fmt.Errorf("node requested token with a pod binding without a uid")) } - pod, err := c.podsGetter.Pods(a.GetNamespace()).Get(ref.Name, v1.GetOptions{}) + pod, err := c.podsGetter.Pods(a.GetNamespace()).Get(ref.Name) if errors.IsNotFound(err) { return err } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission_test.go index 93dec7146..0c22775df 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission_test.go @@ -25,12 +25,12 @@ import ( "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/authentication/user" utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/client-go/tools/cache" authenticationapi "k8s.io/kubernetes/pkg/apis/authentication" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/auth/nodeidentifier" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - coreinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" + "k8s.io/kubernetes/pkg/client/listers/core/internalversion" "k8s.io/kubernetes/pkg/features" ) @@ -63,6 +63,7 @@ func makeTestPod(namespace, name, node string, mirror bool) *api.Pod { func makeTestPodEviction(name string) *policy.Eviction { eviction := &policy.Eviction{} eviction.Name = name + eviction.Namespace = "ns" return eviction } @@ -91,10 +92,22 @@ func Test_nodePlugin_Admit(t *testing.T) { mynodeObjMeta = metav1.ObjectMeta{Name: "mynode"} mynodeObj = &api.Node{ObjectMeta: mynodeObjMeta} mynodeObjConfigA = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{ConfigSource: &api.NodeConfigSource{ - ConfigMapRef: &api.ObjectReference{Name: "foo", Namespace: "bar", UID: "fooUID"}}}} + ConfigMap: &api.ConfigMapNodeConfigSource{ + Name: "foo", + Namespace: "bar", + UID: "fooUID", + KubeletConfigKey: "kubelet", + }}}} mynodeObjConfigB = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{ConfigSource: &api.NodeConfigSource{ - ConfigMapRef: &api.ObjectReference{Name: "qux", Namespace: "bar", UID: "quxUID"}}}} - othernodeObj = &api.Node{ObjectMeta: metav1.ObjectMeta{Name: "othernode"}} + ConfigMap: &api.ConfigMapNodeConfigSource{ + Name: "qux", + Namespace: "bar", + UID: "quxUID", + KubeletConfigKey: "kubelet", + }}}} + mynodeObjTaintA = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{Taints: []api.Taint{{Key: "mykey", Value: "A"}}}} + mynodeObjTaintB = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{Taints: []api.Taint{{Key: "mykey", Value: "B"}}}} + othernodeObj = &api.Node{ObjectMeta: metav1.ObjectMeta{Name: "othernode"}} mymirrorpod = makeTestPod("ns", "mymirrorpod", "mynode", true) othermirrorpod = makeTestPod("ns", "othermirrorpod", "othernode", true) @@ -125,10 +138,20 @@ func Test_nodePlugin_Admit(t *testing.T) { svcacctResource = api.Resource("serviceaccounts").WithVersion("v1") tokenrequestKind = api.Kind("TokenRequest").WithVersion("v1") - noExistingPods = fake.NewSimpleClientset().Core() - existingPods = fake.NewSimpleClientset(mymirrorpod, othermirrorpod, unboundmirrorpod, mypod, otherpod, unboundpod).Core() + noExistingPodsIndex = cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil) + noExistingPods = internalversion.NewPodLister(noExistingPodsIndex) + + existingPodsIndex = cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil) + existingPods = internalversion.NewPodLister(existingPodsIndex) ) + existingPodsIndex.Add(mymirrorpod) + existingPodsIndex.Add(othermirrorpod) + existingPodsIndex.Add(unboundmirrorpod) + existingPodsIndex.Add(mypod) + existingPodsIndex.Add(otherpod) + existingPodsIndex.Add(unboundpod) + sapod := makeTestPod("ns", "mysapod", "mynode", true) sapod.Spec.ServiceAccountName = "foo" @@ -143,7 +166,7 @@ func Test_nodePlugin_Admit(t *testing.T) { tests := []struct { name string - podsGetter coreinternalversion.PodsGetter + podsGetter internalversion.PodLister attributes admission.Attributes features utilfeature.FeatureGate err string @@ -446,7 +469,7 @@ func Test_nodePlugin_Admit(t *testing.T) { err: "forbidden: unexpected operation", }, { - name: "forbid create of eviction for normal pod bound to another", + name: "forbid create of unnamed eviction for normal pod bound to another", podsGetter: existingPods, attributes: admission.NewAttributesRecord(unnamedEviction, nil, evictionKind, otherpod.Namespace, otherpod.Name, podResource, "eviction", admission.Create, mynode), err: "spec.nodeName set to itself", @@ -612,6 +635,12 @@ func Test_nodePlugin_Admit(t *testing.T) { attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, mynode), err: "", }, + { + name: "allow create of my node with taints", + podsGetter: noExistingPods, + attributes: admission.NewAttributesRecord(mynodeObjTaintA, nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, mynode), + err: "", + }, { name: "allow update of my node", podsGetter: existingPods, @@ -660,6 +689,30 @@ func Test_nodePlugin_Admit(t *testing.T) { attributes: admission.NewAttributesRecord(mynodeObj, mynodeObjConfigA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, mynode), err: "", }, + { + name: "allow update of my node: no change to taints", + podsGetter: existingPods, + attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObjTaintA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, mynode), + err: "", + }, + { + name: "forbid update of my node: add taints", + podsGetter: existingPods, + attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, mynode), + err: "cannot modify taints", + }, + { + name: "forbid update of my node: remove taints", + podsGetter: existingPods, + attributes: admission.NewAttributesRecord(mynodeObj, mynodeObjTaintA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, mynode), + err: "cannot modify taints", + }, + { + name: "forbid update of my node: change taints", + podsGetter: existingPods, + attributes: admission.NewAttributesRecord(mynodeObjTaintA, mynodeObjTaintB, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, mynode), + err: "cannot modify taints", + }, // Other node object { diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/BUILD deleted file mode 100644 index 7a0e4da71..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/BUILD +++ /dev/null @@ -1,54 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "admission.go", - "doc.go", - ], - importpath = "k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label", - deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/cloudprovider:go_default_library", - "//pkg/cloudprovider/providers/aws:go_default_library", - "//pkg/cloudprovider/providers/gce:go_default_library", - "//pkg/kubeapiserver/admission:go_default_library", - "//pkg/kubelet/apis:go_default_library", - "//pkg/volume:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["admission_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/cloudprovider/providers/aws: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/types:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/admission.go deleted file mode 100644 index 819adae19..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/admission.go +++ /dev/null @@ -1,218 +0,0 @@ -/* -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 label - -import ( - "bytes" - "fmt" - "io" - "sync" - - "github.com/golang/glog" - "k8s.io/apiserver/pkg/admission" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/cloudprovider" - "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" - kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" - kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" - vol "k8s.io/kubernetes/pkg/volume" -) - -const PluginName = "PersistentVolumeLabel" - -// Register registers a plugin -func Register(plugins *admission.Plugins) { - plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { - persistentVolumeLabelAdmission := NewPersistentVolumeLabel() - return persistentVolumeLabelAdmission, nil - }) -} - -var _ = admission.Interface(&persistentVolumeLabel{}) - -type persistentVolumeLabel struct { - *admission.Handler - - mutex sync.Mutex - ebsVolumes aws.Volumes - cloudConfig []byte - gceCloudProvider *gce.GCECloud -} - -var _ admission.MutationInterface = &persistentVolumeLabel{} -var _ kubeapiserveradmission.WantsCloudConfig = &persistentVolumeLabel{} - -// NewPersistentVolumeLabel returns an admission.Interface implementation which adds labels to PersistentVolume CREATE requests, -// based on the labels provided by the underlying cloud provider. -// -// As a side effect, the cloud provider may block invalid or non-existent volumes. -func NewPersistentVolumeLabel() *persistentVolumeLabel { - // DEPRECATED: cloud-controller-manager will now start NewPersistentVolumeLabelController - // which does exactly what this admission controller used to do. So once GCE and AWS can - // run externally, we can remove this admission controller. - glog.Warning("PersistentVolumeLabel admission controller is deprecated. " + - "Please remove this controller from your configuration files and scripts.") - return &persistentVolumeLabel{ - Handler: admission.NewHandler(admission.Create), - } -} - -func (l *persistentVolumeLabel) SetCloudConfig(cloudConfig []byte) { - l.cloudConfig = cloudConfig -} - -func (l *persistentVolumeLabel) Admit(a admission.Attributes) (err error) { - if a.GetResource().GroupResource() != api.Resource("persistentvolumes") { - return nil - } - obj := a.GetObject() - if obj == nil { - return nil - } - volume, ok := obj.(*api.PersistentVolume) - if !ok { - return nil - } - - var volumeLabels map[string]string - if volume.Spec.AWSElasticBlockStore != nil { - labels, err := l.findAWSEBSLabels(volume) - if err != nil { - return admission.NewForbidden(a, fmt.Errorf("error querying AWS EBS volume %s: %v", volume.Spec.AWSElasticBlockStore.VolumeID, err)) - } - volumeLabels = labels - } - if volume.Spec.GCEPersistentDisk != nil { - labels, err := l.findGCEPDLabels(volume) - if err != nil { - return admission.NewForbidden(a, fmt.Errorf("error querying GCE PD volume %s: %v", volume.Spec.GCEPersistentDisk.PDName, err)) - } - volumeLabels = labels - } - - if len(volumeLabels) != 0 { - if volume.Labels == nil { - volume.Labels = make(map[string]string) - } - for k, v := range volumeLabels { - // We (silently) replace labels if they are provided. - // This should be OK because they are in the kubernetes.io namespace - // i.e. we own them - volume.Labels[k] = v - } - } - - return nil -} - -func (l *persistentVolumeLabel) findAWSEBSLabels(volume *api.PersistentVolume) (map[string]string, error) { - // Ignore any volumes that are being provisioned - if volume.Spec.AWSElasticBlockStore.VolumeID == vol.ProvisionedVolumeName { - return nil, nil - } - ebsVolumes, err := l.getEBSVolumes() - if err != nil { - return nil, err - } - if ebsVolumes == nil { - return nil, fmt.Errorf("unable to build AWS cloud provider for EBS") - } - - // TODO: GetVolumeLabels is actually a method on the Volumes interface - // If that gets standardized we can refactor to reduce code duplication - spec := aws.KubernetesVolumeID(volume.Spec.AWSElasticBlockStore.VolumeID) - labels, err := ebsVolumes.GetVolumeLabels(spec) - if err != nil { - return nil, err - } - - return labels, nil -} - -// getEBSVolumes returns the AWS Volumes interface for ebs -func (l *persistentVolumeLabel) getEBSVolumes() (aws.Volumes, error) { - l.mutex.Lock() - defer l.mutex.Unlock() - - if l.ebsVolumes == nil { - var cloudConfigReader io.Reader - if len(l.cloudConfig) > 0 { - cloudConfigReader = bytes.NewReader(l.cloudConfig) - } - cloudProvider, err := cloudprovider.GetCloudProvider("aws", cloudConfigReader) - if err != nil || cloudProvider == nil { - return nil, err - } - awsCloudProvider, ok := cloudProvider.(*aws.Cloud) - if !ok { - // GetCloudProvider has gone very wrong - return nil, fmt.Errorf("error retrieving AWS cloud provider") - } - l.ebsVolumes = awsCloudProvider - } - return l.ebsVolumes, nil -} - -func (l *persistentVolumeLabel) findGCEPDLabels(volume *api.PersistentVolume) (map[string]string, error) { - // Ignore any volumes that are being provisioned - if volume.Spec.GCEPersistentDisk.PDName == vol.ProvisionedVolumeName { - return nil, nil - } - - provider, err := l.getGCECloudProvider() - if err != nil { - return nil, err - } - if provider == nil { - return nil, fmt.Errorf("unable to build GCE cloud provider for PD") - } - - // If the zone is already labeled, honor the hint - zone := volume.Labels[kubeletapis.LabelZoneFailureDomain] - - labels, err := provider.GetAutoLabelsForPD(volume.Spec.GCEPersistentDisk.PDName, zone) - if err != nil { - return nil, err - } - - return labels, nil -} - -// getGCECloudProvider returns the GCE cloud provider, for use for querying volume labels -func (l *persistentVolumeLabel) getGCECloudProvider() (*gce.GCECloud, error) { - l.mutex.Lock() - defer l.mutex.Unlock() - - if l.gceCloudProvider == nil { - var cloudConfigReader io.Reader - if len(l.cloudConfig) > 0 { - cloudConfigReader = bytes.NewReader(l.cloudConfig) - } - cloudProvider, err := cloudprovider.GetCloudProvider("gce", cloudConfigReader) - if err != nil || cloudProvider == nil { - return nil, err - } - gceCloudProvider, ok := cloudProvider.(*gce.GCECloud) - if !ok { - // GetCloudProvider has gone very wrong - return nil, fmt.Errorf("error retrieving GCE cloud provider") - } - l.gceCloudProvider = gceCloudProvider - } - return l.gceCloudProvider, nil -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/admission_test.go deleted file mode 100644 index e349c756a..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/admission_test.go +++ /dev/null @@ -1,176 +0,0 @@ -/* -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 label - -import ( - "testing" - - "fmt" - - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apiserver/pkg/admission" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" -) - -type mockVolumes struct { - volumeLabels map[string]string - volumeLabelsError error -} - -var _ aws.Volumes = &mockVolumes{} - -func (v *mockVolumes) AttachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName, readOnly bool) (string, error) { - return "", fmt.Errorf("not implemented") -} - -func (v *mockVolumes) DetachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName) (string, error) { - return "", fmt.Errorf("not implemented") -} - -func (v *mockVolumes) CreateDisk(volumeOptions *aws.VolumeOptions) (volumeName aws.KubernetesVolumeID, err error) { - return "", fmt.Errorf("not implemented") -} - -func (v *mockVolumes) DeleteDisk(volumeName aws.KubernetesVolumeID) (bool, error) { - return false, fmt.Errorf("not implemented") -} - -func (v *mockVolumes) GetVolumeLabels(volumeName aws.KubernetesVolumeID) (map[string]string, error) { - return v.volumeLabels, v.volumeLabelsError -} - -func (c *mockVolumes) GetDiskPath(volumeName aws.KubernetesVolumeID) (string, error) { - return "", fmt.Errorf("not implemented") -} - -func (c *mockVolumes) DiskIsAttached(volumeName aws.KubernetesVolumeID, nodeName types.NodeName) (bool, error) { - return false, fmt.Errorf("not implemented") -} - -func (c *mockVolumes) DisksAreAttached(nodeDisks map[types.NodeName][]aws.KubernetesVolumeID) (map[types.NodeName]map[aws.KubernetesVolumeID]bool, error) { - return nil, fmt.Errorf("not implemented") -} - -func (c *mockVolumes) ResizeDisk( - diskName aws.KubernetesVolumeID, - oldSize resource.Quantity, - newSize resource.Quantity) (resource.Quantity, error) { - return oldSize, nil -} - -func mockVolumeFailure(err error) *mockVolumes { - return &mockVolumes{volumeLabelsError: err} -} - -func mockVolumeLabels(labels map[string]string) *mockVolumes { - return &mockVolumes{volumeLabels: labels} -} - -// TestAdmission -func TestAdmission(t *testing.T) { - pvHandler := NewPersistentVolumeLabel() - handler := admission.NewChainHandler(pvHandler) - ignoredPV := api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{Name: "noncloud", Namespace: "myns"}, - Spec: api.PersistentVolumeSpec{ - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: "/", - }, - }, - }, - } - awsPV := api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{Name: "noncloud", Namespace: "myns"}, - Spec: api.PersistentVolumeSpec{ - PersistentVolumeSource: api.PersistentVolumeSource{ - AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{ - VolumeID: "123", - }, - }, - }, - } - - // Non-cloud PVs are ignored - err := handler.Admit(admission.NewAttributesRecord(&ignoredPV, nil, api.Kind("PersistentVolume").WithVersion("version"), ignoredPV.Namespace, ignoredPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) - if err != nil { - t.Errorf("Unexpected error returned from admission handler (on ignored pv): %v", err) - } - - // We only add labels on creation - err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Delete, nil)) - if err != nil { - t.Errorf("Unexpected error returned from admission handler (when deleting aws pv): %v", err) - } - - // Errors from the cloudprovider block creation of the volume - pvHandler.ebsVolumes = mockVolumeFailure(fmt.Errorf("invalid volume")) - err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) - if err == nil { - t.Errorf("Expected error when aws pv info fails") - } - - // Don't add labels if the cloudprovider doesn't return any - labels := make(map[string]string) - pvHandler.ebsVolumes = mockVolumeLabels(labels) - err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) - if err != nil { - t.Errorf("Expected no error when creating aws pv") - } - if len(awsPV.ObjectMeta.Labels) != 0 { - t.Errorf("Unexpected number of labels") - } - - // Don't panic if the cloudprovider returns nil, nil - pvHandler.ebsVolumes = mockVolumeFailure(nil) - err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) - if err != nil { - t.Errorf("Expected no error when cloud provider returns empty labels") - } - - // Labels from the cloudprovider should be applied to the volume - labels = make(map[string]string) - labels["a"] = "1" - labels["b"] = "2" - pvHandler.ebsVolumes = mockVolumeLabels(labels) - err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) - if err != nil { - t.Errorf("Expected no error when creating aws pv") - } - if awsPV.Labels["a"] != "1" || awsPV.Labels["b"] != "2" { - t.Errorf("Expected label a to be added when creating aws pv") - } - - // User-provided labels should be honored, but cloudprovider labels replace them when they overlap - awsPV.ObjectMeta.Labels = make(map[string]string) - awsPV.ObjectMeta.Labels["a"] = "not1" - awsPV.ObjectMeta.Labels["c"] = "3" - err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) - if err != nil { - t.Errorf("Expected no error when creating aws pv") - } - if awsPV.Labels["a"] != "1" || awsPV.Labels["b"] != "2" { - t.Errorf("Expected cloudprovider labels to replace user labels when creating aws pv") - } - if awsPV.Labels["c"] != "3" { - t.Errorf("Expected (non-conflicting) user provided labels to be honored when creating aws pv") - } - -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/doc.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/doc.go deleted file mode 100644 index b1e2c79e4..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -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. -*/ - -// labels created persistent volumes with zone information -// as provided by the cloud provider -package label // import "k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label" diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/BUILD deleted file mode 100644 index fab03d04f..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/BUILD +++ /dev/null @@ -1,52 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["admission_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/apis/storage:go_default_library", - "//pkg/client/informers/informers_generated/internalversion:go_default_library", - "//pkg/controller: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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = ["admission.go"], - importpath = "k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize", - deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", - "//pkg/client/informers/informers_generated/internalversion:go_default_library", - "//pkg/client/listers/core/internalversion:go_default_library", - "//pkg/client/listers/storage/internalversion:go_default_library", - "//pkg/kubeapiserver/admission:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/admission.go deleted file mode 100644 index 3d04ae812..000000000 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/admission.go +++ /dev/null @@ -1,168 +0,0 @@ -/* -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 resize - -import ( - "fmt" - "io" - - "k8s.io/apiserver/pkg/admission" - api "k8s.io/kubernetes/pkg/apis/core" - apihelper "k8s.io/kubernetes/pkg/apis/core/helper" - informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" - pvlister "k8s.io/kubernetes/pkg/client/listers/core/internalversion" - storagelisters "k8s.io/kubernetes/pkg/client/listers/storage/internalversion" - kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" -) - -const ( - // PluginName is the name of pvc resize admission plugin - PluginName = "PersistentVolumeClaimResize" -) - -// Register registers a plugin -func Register(plugins *admission.Plugins) { - plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { - plugin := newPlugin() - return plugin, nil - }) -} - -var _ admission.Interface = &persistentVolumeClaimResize{} -var _ admission.ValidationInterface = &persistentVolumeClaimResize{} -var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&persistentVolumeClaimResize{}) - -type persistentVolumeClaimResize struct { - *admission.Handler - - pvLister pvlister.PersistentVolumeLister - scLister storagelisters.StorageClassLister -} - -func newPlugin() *persistentVolumeClaimResize { - return &persistentVolumeClaimResize{ - Handler: admission.NewHandler(admission.Update), - } -} - -func (pvcr *persistentVolumeClaimResize) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { - pvcInformer := f.Core().InternalVersion().PersistentVolumes() - pvcr.pvLister = pvcInformer.Lister() - scInformer := f.Storage().InternalVersion().StorageClasses() - pvcr.scLister = scInformer.Lister() - pvcr.SetReadyFunc(func() bool { - return pvcInformer.Informer().HasSynced() && scInformer.Informer().HasSynced() - }) -} - -// ValidateInitialization ensures lister is set. -func (pvcr *persistentVolumeClaimResize) ValidateInitialization() error { - if pvcr.pvLister == nil { - return fmt.Errorf("missing persistent volume lister") - } - if pvcr.scLister == nil { - return fmt.Errorf("missing storageclass lister") - } - return nil -} - -func (pvcr *persistentVolumeClaimResize) Validate(a admission.Attributes) error { - if a.GetResource().GroupResource() != api.Resource("persistentvolumeclaims") { - return nil - } - - if len(a.GetSubresource()) != 0 { - return nil - } - - pvc, ok := a.GetObject().(*api.PersistentVolumeClaim) - // if we can't convert then we don't handle this object so just return - if !ok { - return nil - } - oldPvc, ok := a.GetOldObject().(*api.PersistentVolumeClaim) - if !ok { - return nil - } - - oldSize := oldPvc.Spec.Resources.Requests[api.ResourceStorage] - newSize := pvc.Spec.Resources.Requests[api.ResourceStorage] - - if newSize.Cmp(oldSize) <= 0 { - return nil - } - - if oldPvc.Status.Phase != api.ClaimBound { - return admission.NewForbidden(a, fmt.Errorf("Only bound persistent volume claims can be expanded")) - } - - // Growing Persistent volumes is only allowed for PVCs for which their StorageClass - // explicitly allows it - if !pvcr.allowResize(pvc, oldPvc) { - return admission.NewForbidden(a, fmt.Errorf("only dynamically provisioned pvc can be resized and "+ - "the storageclass that provisions the pvc must support resize")) - } - - // volume plugin must support resize - pv, err := pvcr.pvLister.Get(pvc.Spec.VolumeName) - if err != nil { - return admission.NewForbidden(a, fmt.Errorf("Error updating persistent volume claim because fetching associated persistent volume failed")) - } - - if !pvcr.checkVolumePlugin(pv) { - return admission.NewForbidden(a, fmt.Errorf("volume plugin does not support resize")) - } - return nil -} - -// Growing Persistent volumes is only allowed for PVCs for which their StorageClass -// explicitly allows it. -func (pvcr *persistentVolumeClaimResize) allowResize(pvc, oldPvc *api.PersistentVolumeClaim) bool { - pvcStorageClass := apihelper.GetPersistentVolumeClaimClass(pvc) - oldPvcStorageClass := apihelper.GetPersistentVolumeClaimClass(oldPvc) - if pvcStorageClass == "" || oldPvcStorageClass == "" || pvcStorageClass != oldPvcStorageClass { - return false - } - sc, err := pvcr.scLister.Get(pvcStorageClass) - if err != nil { - return false - } - if sc.AllowVolumeExpansion != nil { - return *sc.AllowVolumeExpansion - } - return false -} - -// checkVolumePlugin checks whether the volume plugin supports resize -func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVolume) bool { - if pv.Spec.Glusterfs != nil || pv.Spec.Cinder != nil || pv.Spec.RBD != nil { - return true - } - - if pv.Spec.GCEPersistentDisk != nil { - return true - } - - if pv.Spec.AWSElasticBlockStore != nil { - return true - } - - if pv.Spec.AzureFile != nil { - return true - } - return false -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/BUILD index f4625122b..6421a1562 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/BUILD @@ -51,8 +51,6 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission_test.go index 1a60e5f21..36abae7d5 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission_test.go @@ -37,21 +37,6 @@ import ( // TestPodAdmission verifies various scenarios involving pod/namespace tolerations func TestPodAdmission(t *testing.T) { - namespace := &api.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: "testNamespace", - Namespace: "", - }, - } - - mockClient := &fake.Clientset{} - handler, informerFactory, err := newHandlerForTest(mockClient) - if err != nil { - t.Errorf("unexpected error initializing handler: %v", err) - } - stopCh := make(chan struct{}) - defer close(stopCh) - informerFactory.Start(stopCh) CPU1000m := resource.MustParse("1000m") CPU500m := resource.MustParse("500m") @@ -230,57 +215,74 @@ func TestPodAdmission(t *testing.T) { }, } for _, test := range tests { - if test.namespaceTolerations != nil { - tolerationStr, err := json.Marshal(test.namespaceTolerations) - if err != nil { - t.Errorf("error in marshalling namespace tolerations %v", test.namespaceTolerations) + t.Run(test.testName, func(t *testing.T) { + namespace := &api.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testNamespace", + Namespace: "", + Annotations: map[string]string{}, + }, } - namespace.Annotations = map[string]string{NSDefaultTolerations: string(tolerationStr)} - } - if test.whitelist != nil { - tolerationStr, err := json.Marshal(test.whitelist) - if err != nil { - t.Errorf("error in marshalling namespace whitelist %v", test.whitelist) + if test.namespaceTolerations != nil { + tolerationStr, err := json.Marshal(test.namespaceTolerations) + if err != nil { + t.Errorf("error in marshalling namespace tolerations %v", test.namespaceTolerations) + } + namespace.Annotations = map[string]string{NSDefaultTolerations: string(tolerationStr)} } - namespace.Annotations[NSWLTolerations] = string(tolerationStr) - } - informerFactory.Core().InternalVersion().Namespaces().Informer().GetStore().Update(namespace) + if test.whitelist != nil { + tolerationStr, err := json.Marshal(test.whitelist) + if err != nil { + t.Errorf("error in marshalling namespace whitelist %v", test.whitelist) + } + namespace.Annotations[NSWLTolerations] = string(tolerationStr) + } - handler.pluginConfig = &pluginapi.Configuration{Default: test.defaultClusterTolerations, Whitelist: test.clusterWhitelist} - pod := test.pod - pod.Spec.Tolerations = test.podTolerations + mockClient := fake.NewSimpleClientset(namespace) + handler, informerFactory, err := newHandlerForTest(mockClient) + if err != nil { + t.Fatalf("unexpected error initializing handler: %v", err) + } + stopCh := make(chan struct{}) + defer close(stopCh) + informerFactory.Start(stopCh) - // copy the original pod for tests of uninitialized pod updates. - oldPod := *pod - oldPod.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init"}}} - oldPod.Spec.Tolerations = []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}} + handler.pluginConfig = &pluginapi.Configuration{Default: test.defaultClusterTolerations, Whitelist: test.clusterWhitelist} + pod := test.pod + pod.Spec.Tolerations = test.podTolerations - err := handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) - if test.admit && err != nil { - t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) - } else if !test.admit && err == nil { - t.Errorf("Test: %s, expected an error", test.testName) - } + // copy the original pod for tests of uninitialized pod updates. + oldPod := *pod + oldPod.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init"}}} + oldPod.Spec.Tolerations = []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}} - updatedPodTolerations := pod.Spec.Tolerations - if test.admit && !tolerations.EqualTolerations(updatedPodTolerations, test.mergedTolerations) { - t.Errorf("Test: %s, expected: %#v but got: %#v", test.testName, test.mergedTolerations, updatedPodTolerations) - } + err = handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) + if test.admit && err != nil { + t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) + } else if !test.admit && err == nil { + t.Errorf("Test: %s, expected an error", test.testName) + } - // handles update of uninitialized pod like it's newly created. - err = handler.Admit(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil)) - if test.admit && err != nil { - t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) - } else if !test.admit && err == nil { - t.Errorf("Test: %s, expected an error", test.testName) - } + updatedPodTolerations := pod.Spec.Tolerations + if test.admit && !tolerations.EqualTolerations(updatedPodTolerations, test.mergedTolerations) { + t.Errorf("Test: %s, expected: %#v but got: %#v", test.testName, test.mergedTolerations, updatedPodTolerations) + } - updatedPodTolerations = pod.Spec.Tolerations - if test.admit && !tolerations.EqualTolerations(updatedPodTolerations, test.mergedTolerations) { - t.Errorf("Test: %s, expected: %#v but got: %#v", test.testName, test.mergedTolerations, updatedPodTolerations) - } + // handles update of uninitialized pod like it's newly created. + err = handler.Admit(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil)) + if test.admit && err != nil { + t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) + } else if !test.admit && err == nil { + t.Errorf("Test: %s, expected an error", test.testName) + } + + updatedPodTolerations = pod.Spec.Tolerations + if test.admit && !tolerations.EqualTolerations(updatedPodTolerations, test.mergedTolerations) { + t.Errorf("Test: %s, expected: %#v but got: %#v", test.testName, test.mergedTolerations, updatedPodTolerations) + } + }) } } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/BUILD index 6b1210fe0..97dabce24 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/BUILD @@ -12,9 +12,8 @@ go_library( deps = [ "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library", "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/install.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/install.go index bc4336a43..3bd5deb15 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/install.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" internalapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" versionedapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: internalapi.GroupName, - VersionPreferenceOrder: []string{versionedapi.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: internalapi.AddToScheme, - }, - announced.VersionToSchemeFunc{ - versionedapi.SchemeGroupVersion.Version: versionedapi.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(internalapi.AddToScheme(scheme)) + utilruntime.Must(versionedapi.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(versionedapi.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.conversion.go index edb4d0148..b7b2a40d1 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.deepcopy.go index 6e7a745b2..008c428fc 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/zz_generated.deepcopy.go index 00934c85f..ea467c145 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/config.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/config.go index 49bcd070b..d5d954a50 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/config.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/config.go @@ -20,10 +20,7 @@ import ( "fmt" "io" "io/ioutil" - "os" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" internalapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" @@ -33,14 +30,12 @@ import ( ) var ( - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) - scheme = runtime.NewScheme() - codecs = serializer.NewCodecFactory(scheme) + scheme = runtime.NewScheme() + codecs = serializer.NewCodecFactory(scheme) ) func init() { - install.Install(groupFactoryRegistry, registry, scheme) + install.Install(scheme) } // LoadConfiguration loads the provided configuration. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/BUILD index 3f9959806..567d05757 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/BUILD @@ -16,10 +16,10 @@ go_test( "//pkg/client/informers/informers_generated/internalversion:go_default_library", "//pkg/controller:go_default_library", "//pkg/features:go_default_library", - "//pkg/scheduler/api:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", + "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) @@ -37,8 +37,8 @@ go_library( "//pkg/features:go_default_library", "//pkg/kubeapiserver/admission:go_default_library", "//pkg/kubelet/types:go_default_library", - "//pkg/scheduler/api:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission.go index 2c7e22242..e7054a474 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission.go @@ -21,6 +21,7 @@ import ( "io" "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apiserver/pkg/admission" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -32,7 +33,6 @@ import ( "k8s.io/kubernetes/pkg/features" kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" ) const ( @@ -97,6 +97,10 @@ var ( // Admit checks Pods and admits or rejects them. It also resolves the priority of pods based on their PriorityClass. // Note that pod validation mechanism prevents update of a pod priority. func (p *priorityPlugin) Admit(a admission.Attributes) error { + if !utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) { + return nil + } + operation := a.GetOperation() // Ignore all calls to subresources if len(a.GetSubresource()) != 0 { @@ -105,7 +109,7 @@ func (p *priorityPlugin) Admit(a admission.Attributes) error { switch a.GetResource().GroupResource() { case podResource: - if operation == admission.Create { + if operation == admission.Create || operation == admission.Update { return p.admitPod(a) } return nil @@ -135,6 +139,20 @@ func (p *priorityPlugin) Validate(a admission.Attributes) error { } } +// priorityClassPermittedInNamespace returns true if we allow the given priority class name in the +// given namespace. It currently checks that system priorities are created only in the system namespace. +func priorityClassPermittedInNamespace(priorityClassName string, namespace string) bool { + // Only allow system priorities in the system namespace. This is to prevent abuse or incorrect + // usage of these priorities. Pods created at these priorities could preempt system critical + // components. + for _, spc := range scheduling.SystemPriorityClasses() { + if spc.Name == priorityClassName && namespace != metav1.NamespaceSystem { + return false + } + } + return true +} + // admitPod makes sure a new pod does not set spec.Priority field. It also makes sure that the PriorityClassName exists if it is provided and resolves the pod priority from the PriorityClassName. func (p *priorityPlugin) admitPod(a admission.Attributes) error { operation := a.GetOperation() @@ -143,18 +161,29 @@ func (p *priorityPlugin) admitPod(a admission.Attributes) error { return errors.NewBadRequest("resource was marked with kind Pod but was unable to be converted") } - // Make sure that the client has not set `priority` at the time of pod creation. - if operation == admission.Create && pod.Spec.Priority != nil { - return admission.NewForbidden(a, fmt.Errorf("the integer value of priority must not be provided in pod spec. Priority admission controller populates the value from the given PriorityClass name")) + if operation == admission.Update { + oldPod, ok := a.GetOldObject().(*api.Pod) + if !ok { + return errors.NewBadRequest("resource was marked with kind Pod but was unable to be converted") + } + + // This admission plugin set pod.Spec.Priority on create. + // Ensure the existing priority is preserved on update. + // API validation prevents mutations to Priority and PriorityClassName, so any other changes will fail update validation and not be persisted. + if pod.Spec.Priority == nil && oldPod.Spec.Priority != nil { + pod.Spec.Priority = oldPod.Spec.Priority + } + return nil } - if utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) { + + if operation == admission.Create { var priority int32 // TODO: @ravig - This is for backwards compatibility to ensure that critical pods with annotations just work fine. // Remove when no longer needed. if len(pod.Spec.PriorityClassName) == 0 && utilfeature.DefaultFeatureGate.Enabled(features.ExperimentalCriticalPodAnnotation) && kubelettypes.IsCritical(a.GetNamespace(), pod.Annotations) { - pod.Spec.PriorityClassName = schedulerapi.SystemClusterCritical + pod.Spec.PriorityClassName = scheduling.SystemClusterCritical } if len(pod.Spec.PriorityClassName) == 0 { var err error @@ -163,22 +192,26 @@ func (p *priorityPlugin) admitPod(a admission.Attributes) error { return fmt.Errorf("failed to get default priority class: %v", err) } } else { - // First try to resolve by system priority classes. - priority, ok = schedulerapi.SystemPriorityClasses[pod.Spec.PriorityClassName] - if !ok { - // Now that we didn't find any system priority, try resolving by user defined priority classes. - pc, err := p.lister.Get(pod.Spec.PriorityClassName) - - if err != nil { - if errors.IsNotFound(err) { - return admission.NewForbidden(a, fmt.Errorf("no PriorityClass with name %v was found", pod.Spec.PriorityClassName)) - } - - return fmt.Errorf("failed to get PriorityClass with name %s: %v", pod.Spec.PriorityClassName, err) + pcName := pod.Spec.PriorityClassName + if !priorityClassPermittedInNamespace(pcName, a.GetNamespace()) { + return admission.NewForbidden(a, fmt.Errorf("pods with %v priorityClass is not permitted in %v namespace", pcName, a.GetNamespace())) + } + + // Try resolving the priority class name. + pc, err := p.lister.Get(pod.Spec.PriorityClassName) + if err != nil { + if errors.IsNotFound(err) { + return admission.NewForbidden(a, fmt.Errorf("no PriorityClass with name %v was found", pod.Spec.PriorityClassName)) } - priority = pc.Value + return fmt.Errorf("failed to get PriorityClass with name %s: %v", pod.Spec.PriorityClassName, err) } + + priority = pc.Value + } + // if the pod contained a priority that differs from the one computed from the priority class, error + if pod.Spec.Priority != nil && *pod.Spec.Priority != priority { + return admission.NewForbidden(a, fmt.Errorf("the integer value of priority (%d) must not be provided in pod spec; priority admission controller computed %d from the given PriorityClass name", *pod.Spec.Priority, priority)) } pod.Spec.Priority = &priority } @@ -192,12 +225,6 @@ func (p *priorityPlugin) validatePriorityClass(a admission.Attributes) error { if !ok { return errors.NewBadRequest("resource was marked with kind PriorityClass but was unable to be converted") } - if pc.Value > schedulerapi.HighestUserDefinablePriority { - return admission.NewForbidden(a, fmt.Errorf("maximum allowed value of a user defined priority is %v", schedulerapi.HighestUserDefinablePriority)) - } - if _, ok := schedulerapi.SystemPriorityClasses[pc.Name]; ok { - return admission.NewForbidden(a, fmt.Errorf("the name of the priority class is a reserved name for system use only: %v", pc.Name)) - } // If the new PriorityClass tries to be the default priority, make sure that no other priority class is marked as default. if pc.GlobalDefault { dpc, err := p.getDefaultPriorityClass() diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission_test.go index 2fb2a1134..05f571f3e 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission_test.go @@ -24,13 +24,13 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/authentication/user" utilfeature "k8s.io/apiserver/pkg/util/feature" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/scheduling" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/features" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" ) func addPriorityClasses(ctrl *priorityPlugin, priorityClasses []*scheduling.PriorityClass) { @@ -75,58 +75,58 @@ var nondefaultClass1 = &scheduling.PriorityClass{ Description: "Just a test priority class", } -func TestPriorityClassAdmission(t *testing.T) { - var tooHighPriorityClass = &scheduling.PriorityClass{ - TypeMeta: metav1.TypeMeta{ - Kind: "PriorityClass", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "toohighclass", - }, - Value: schedulerapi.HighestUserDefinablePriority + 1, - Description: "Just a test priority class", - } +var systemClusterCritical = &scheduling.PriorityClass{ + TypeMeta: metav1.TypeMeta{ + Kind: "PriorityClass", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: scheduling.SystemClusterCritical, + }, + Value: scheduling.SystemCriticalPriority, + GlobalDefault: true, +} +func TestPriorityClassAdmission(t *testing.T) { var systemClass = &scheduling.PriorityClass{ TypeMeta: metav1.TypeMeta{ Kind: "PriorityClass", }, ObjectMeta: metav1.ObjectMeta{ - Name: schedulerapi.SystemClusterCritical, + Name: scheduling.SystemPriorityClassPrefix + "test", }, - Value: schedulerapi.HighestUserDefinablePriority + 1, - Description: "Name conflicts with system priority class names", + Value: scheduling.HighestUserDefinablePriority + 1, + Description: "Name has system critical prefix", } tests := []struct { name string existingClasses []*scheduling.PriorityClass newClass *scheduling.PriorityClass + userInfo user.Info expectError bool }{ { "one default class", []*scheduling.PriorityClass{}, defaultClass1, + nil, false, }, { "more than one default classes", []*scheduling.PriorityClass{defaultClass1}, defaultClass2, + nil, true, }, { - "too high PriorityClass value", - []*scheduling.PriorityClass{}, - tooHighPriorityClass, - true, - }, - { - "system name conflict", + "system name and value are allowed by admission controller", []*scheduling.PriorityClass{}, systemClass, - true, + &user.DefaultInfo{ + Name: user.APIServerUser, + }, + false, }, } @@ -146,7 +146,7 @@ func TestPriorityClassAdmission(t *testing.T) { scheduling.Resource("priorityclasses").WithVersion("version"), "", admission.Create, - nil, + test.userInfo, ) err := ctrl.Validate(attrs) glog.Infof("Got %v", err) @@ -244,6 +244,7 @@ func TestDefaultPriority(t *testing.T) { } } +var zeroPriority = int32(0) var intPriority = int32(1000) func TestPodAdmission(t *testing.T) { @@ -314,7 +315,7 @@ func TestPodAdmission(t *testing.T) { { ObjectMeta: metav1.ObjectMeta{ Name: "pod-w-system-priority", - Namespace: "namespace", + Namespace: metav1.NamespaceSystem, }, Spec: api.PodSpec{ Containers: []api.Container{ @@ -322,14 +323,14 @@ func TestPodAdmission(t *testing.T) { Name: containerName, }, }, - PriorityClassName: schedulerapi.SystemClusterCritical, + PriorityClassName: scheduling.SystemClusterCritical, }, }, // pod[5]: mirror Pod with a system priority class name { ObjectMeta: metav1.ObjectMeta{ Name: "mirror-pod-w-system-priority", - Namespace: "namespace", + Namespace: metav1.NamespaceSystem, Annotations: map[string]string{api.MirrorPodAnnotationKey: ""}, }, Spec: api.PodSpec{ @@ -374,6 +375,67 @@ func TestPodAdmission(t *testing.T) { }, }, }, + // pod[8]: Pod with a system priority class name in non-system namespace + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-w-system-priority-in-nonsystem-namespace", + Namespace: "non-system-namespace", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: containerName, + }, + }, + PriorityClassName: scheduling.SystemClusterCritical, + }, + }, + // pod[9]: Pod with a priority value that matches the resolved priority + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-w-zero-priority-in-nonsystem-namespace", + Namespace: "non-system-namespace", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: containerName, + }, + }, + Priority: &zeroPriority, + }, + }, + // pod[10]: Pod with a priority value that matches the resolved default priority + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-w-priority-matching-default-priority", + Namespace: "non-system-namespace", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: containerName, + }, + }, + Priority: &defaultClass2.Value, + }, + }, + // pod[11]: Pod with a priority value that matches the resolved priority + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-w-priority-matching-resolved-default-priority", + Namespace: metav1.NamespaceSystem, + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: containerName, + }, + }, + PriorityClassName: systemClusterCritical.Name, + Priority: &systemClusterCritical.Value, + }, + }, } // Enable PodPriority feature gate. utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.PodPriority)) @@ -419,9 +481,9 @@ func TestPodAdmission(t *testing.T) { }, { "pod with a system priority class", - []*scheduling.PriorityClass{}, + []*scheduling.PriorityClass{systemClusterCritical}, *pods[4], - schedulerapi.SystemCriticalPriority, + scheduling.SystemCriticalPriority, false, }, { @@ -440,9 +502,9 @@ func TestPodAdmission(t *testing.T) { }, { "mirror pod with system priority class", - []*scheduling.PriorityClass{}, + []*scheduling.PriorityClass{systemClusterCritical}, *pods[5], - schedulerapi.SystemCriticalPriority, + scheduling.SystemCriticalPriority, false, }, { @@ -454,9 +516,37 @@ func TestPodAdmission(t *testing.T) { }, { "pod with critical pod annotation", - []*scheduling.PriorityClass{}, + []*scheduling.PriorityClass{systemClusterCritical}, *pods[7], - schedulerapi.SystemCriticalPriority, + scheduling.SystemCriticalPriority, + false, + }, + { + "pod with system critical priority in non-system namespace", + []*scheduling.PriorityClass{systemClusterCritical}, + *pods[8], + scheduling.SystemCriticalPriority, + true, + }, + { + "pod with priority that matches computed priority", + []*scheduling.PriorityClass{nondefaultClass1}, + *pods[9], + 0, + false, + }, + { + "pod with priority that matches default priority", + []*scheduling.PriorityClass{defaultClass2}, + *pods[10], + defaultClass2.Value, + false, + }, + { + "pod with priority that matches resolved priority", + []*scheduling.PriorityClass{systemClusterCritical}, + *pods[11], + systemClusterCritical.Value, false, }, } @@ -485,8 +575,7 @@ func TestPodAdmission(t *testing.T) { if !test.expectError { if err != nil { t.Errorf("Test %q: unexpected error received: %v", test.name, err) - } - if *test.pod.Spec.Priority != test.expectedPriority { + } else if *test.pod.Spec.Priority != test.expectedPriority { t.Errorf("Test %q: expected priority is %d, but got %d.", test.name, test.expectedPriority, *test.pod.Spec.Priority) } } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/BUILD index e19cf5dc5..66a1b10f6 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/BUILD @@ -32,9 +32,8 @@ go_library( "//plugin/pkg/admission/resourcequota/apis/resourcequota/validation:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/hashicorp/golang-lru:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission_test.go index d94acdf2a..d51ac5012 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission_test.go @@ -17,6 +17,7 @@ limitations under the License. package resourcequota import ( + "fmt" "strconv" "strings" "testing" @@ -73,6 +74,14 @@ func validPod(name string, numContainers int, resources api.ResourceRequirements return pod } +func validPodWithPriority(name string, numContainers int, resources api.ResourceRequirements, priorityClass string) *api.Pod { + pod := validPod(name, numContainers, resources) + if priorityClass != "" { + pod.Spec.PriorityClassName = priorityClass + } + return pod +} + func validPersistentVolumeClaim(name string, resources api.ResourceRequirements) *api.PersistentVolumeClaim { return &api.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "test"}, @@ -1445,3 +1454,672 @@ func TestAdmitLimitedResourceWithQuotaThatDoesNotCover(t *testing.T) { t.Fatalf("Expected an error since the quota did not cover cpu") } } + +// TestAdmitLimitedScopeWithQuota verifies if a limited scope is configured the quota must cover the resource. +func TestAdmitLimitedScopeWithCoverQuota(t *testing.T) { + testCases := []struct { + description string + testPod *api.Pod + quota *api.ResourceQuota + anotherQuota *api.ResourceQuota + config *resourcequotaapi.Configuration + expErr string + }{ + { + description: "Covering quota exists for configured limited scope PriorityClassNameExists.", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists}, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "configured limited scope PriorityClassNameExists and limited cpu resource. No covering quota for cpu and pod admit fails.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists}, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists, + }, + }, + MatchContains: []string{"requests.cpu"}, // match on "requests.cpu" only + }, + }, + }, + expErr: "insufficient quota to consume: requests.cpu", + }, + { + description: "Covering quota does not exist for configured limited scope PriorityClassNameExists.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass Exists []}]", + }, + { + description: "Covering quota does not exist for configured limited scope resourceQuotaBestEffort", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{BestEffort Exists []}]", + }, + { + description: "Covering quota exist for configured limited scope resourceQuotaBestEffort", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota-besteffort", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeBestEffort}, + }, + Status: api.ResourceQuotaStatus{ + Hard: api.ResourceList{ + api.ResourcePods: resource.MustParse("5"), + }, + Used: api.ResourceList{ + api.ResourcePods: resource.MustParse("3"), + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Neither matches pod. Pod allowed", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("100m", "1Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Only BestEffort scope matches pod. Pod admit fails because covering quota is missing for BestEffort scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{BestEffort Exists []}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Only PriorityClass scope matches pod. Pod admit fails because covering quota is missing for PriorityClass scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("100m", "1Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass In [cluster-services]}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Both the scopes matches pod. Pod admit fails because covering quota is missing for PriorityClass scope and BestEffort scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{BestEffort Exists []} {PriorityClass In [cluster-services]}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Both the scopes matches pod. Quota available only for BestEffort scope. Pod admit fails because covering quota is missing for PriorityClass scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota-besteffort", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeBestEffort}, + }, + Status: api.ResourceQuotaStatus{ + Hard: api.ResourceList{ + api.ResourcePods: resource.MustParse("5"), + }, + Used: api.ResourceList{ + api.ResourcePods: resource.MustParse("3"), + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass In [cluster-services]}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Both the scopes matches pod. Quota available only for PriorityClass scope. Pod admit fails because covering quota is missing for BestEffort scope", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{BestEffort Exists []}]", + }, + { + description: "Two scopes,BestEffort and PriorityClassIN, in two LimitedResources. Both the scopes matches pod. Quota available only for both the scopes. Pod admit success. No Error", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("", ""), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota-besteffort", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeBestEffort}, + }, + Status: api.ResourceQuotaStatus{ + Hard: api.ResourceList{ + api.ResourcePods: resource.MustParse("5"), + }, + Used: api.ResourceList{ + api.ResourcePods: resource.MustParse("3"), + }, + }, + }, + anotherQuota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopeBestEffort, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Pod allowed with priorityclass if limited scope PriorityClassNameExists not configured.", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{}, + expErr: "", + }, + { + description: "quota fails, though covering quota for configured limited scope PriorityClassNameExists exists.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "20Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists}, + }, + }, + }, + Status: api.ResourceQuotaStatus{ + Hard: api.ResourceList{ + api.ResourceMemory: resource.MustParse("10Gi"), + }, + Used: api.ResourceList{ + api.ResourceMemory: resource.MustParse("1Gi"), + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists, + }, + }, + }, + }, + }, + expErr: "forbidden: exceeded quota: quota, requested: memory=20Gi, used: memory=1Gi, limited: memory=10Gi", + }, + { + description: "Pod has different priorityclass than configured limited. Covering quota exists for configured limited scope PriorityClassIn.", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "fake-priority"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Pod has limited priorityclass. Covering quota exists for configured limited scope PriorityClassIn.", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"cluster-services"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Pod has limited priorityclass. Covering quota does not exist for configured limited scope PriorityClassIn.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass In [another-priorityclass-name cluster-services]}]", + }, + { + description: "From the above test case, just changing pod priority from cluster-services to another-priorityclass-name. expecting no error", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "another-priorityclass-name"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name"}, + }, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + { + description: "Pod has limited priorityclass. Covering quota does NOT exists for configured limited scope PriorityClassIn.", + testPod: validPodWithPriority("not-allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{}, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "insufficient quota to match these scopes: [{PriorityClass In [another-priorityclass-name cluster-services]}]", + }, + { + description: "Pod has limited priorityclass. Covering quota exists for configured limited scope PriorityClassIn through PriorityClassNameExists", + testPod: validPodWithPriority("allowed-pod", 1, getResourceRequirements(getResourceList("3", "2Gi"), getResourceList("", "")), "cluster-services"), + quota: &api.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, + Spec: api.ResourceQuotaSpec{ + ScopeSelector: &api.ScopeSelector{ + MatchExpressions: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpExists}, + }, + }, + }, + }, + config: &resourcequotaapi.Configuration{ + LimitedResources: []resourcequotaapi.LimitedResource{ + { + Resource: "pods", + MatchScopes: []api.ScopedResourceSelectorRequirement{ + { + ScopeName: api.ResourceQuotaScopePriorityClass, + Operator: api.ScopeSelectorOpIn, + Values: []string{"another-priorityclass-name", "cluster-services"}, + }, + }, + }, + }, + }, + expErr: "", + }, + } + + for _, testCase := range testCases { + newPod := testCase.testPod + config := testCase.config + resourceQuota := testCase.quota + kubeClient := fake.NewSimpleClientset(resourceQuota) + if testCase.anotherQuota != nil { + kubeClient = fake.NewSimpleClientset(resourceQuota, testCase.anotherQuota) + } + indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}) + stopCh := make(chan struct{}) + defer close(stopCh) + + informerFactory := informers.NewSharedInformerFactory(kubeClient, controller.NoResyncPeriodFunc()) + quotaAccessor, _ := newQuotaAccessor() + quotaAccessor.client = kubeClient + quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister() + + quotaConfiguration := install.NewQuotaConfigurationForAdmission() + evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh) + + handler := &QuotaAdmission{ + Handler: admission.NewHandler(admission.Create, admission.Update), + evaluator: evaluator, + } + indexer.Add(resourceQuota) + if testCase.anotherQuota != nil { + indexer.Add(testCase.anotherQuota) + } + err := handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) + if testCase.expErr == "" { + if err != nil { + t.Fatalf("Testcase, %v, failed with unexpected error: %v. ExpErr: %v", testCase.description, err, testCase.expErr) + } + } else { + if !strings.Contains(fmt.Sprintf("%v", err), testCase.expErr) { + t.Fatalf("Testcase, %v, failed with unexpected error: %v. ExpErr: %v", testCase.description, err, testCase.expErr) + } + } + + } +} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD index 7c43ea4a1..0929b3965 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD @@ -15,6 +15,7 @@ go_library( ], importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota", deps = [ + "//pkg/apis/core:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/install/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/install/BUILD index 61d6cc714..dfc40ecfb 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/install/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/install/BUILD @@ -12,9 +12,8 @@ go_library( deps = [ "//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library", "//plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/install/install.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/install/install.go index aa28431ec..87c9d6f9a 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/install/install.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota" resourcequotav1alpha1 "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: resourcequotaapi.GroupName, - VersionPreferenceOrder: []string{resourcequotav1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: resourcequotaapi.AddToScheme, - }, - announced.VersionToSchemeFunc{ - resourcequotav1alpha1.SchemeGroupVersion.Version: resourcequotav1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(resourcequotaapi.AddToScheme(scheme)) + utilruntime.Must(resourcequotav1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(resourcequotav1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/types.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/types.go index 88602d015..7686e4dab 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/types.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/types.go @@ -16,7 +16,10 @@ limitations under the License. package resourcequota -import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/core" +) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -54,4 +57,16 @@ type LimitedResource struct { // with any storage class, the list would include // ".storageclass.storage.k8s.io/requests.storage" MatchContains []string + + // For each intercepted request, the quota system will figure out if the input object + // satisfies a scope which is present in this listing, then + // quota system will ensure that there is a covering quota. In the + // absence of a covering quota, the quota system will deny the request. + // For example, if an administrator wants to globally enforce that + // a quota must exist to create a pod with "cluster-services" priorityclass + // the list would include + // "PriorityClassNameIn=cluster-services" + // +optional + // MatchScopes []string `json:"matchScopes,omitempty"` + MatchScopes []core.ScopedResourceSelectorRequirement `json:"matchScopes,omitempty"` } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/BUILD index 0ffe75d6c..1b4f8ae2d 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/BUILD @@ -18,7 +18,9 @@ go_library( ], importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1", deps = [ + "//pkg/apis/core:go_default_library", "//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library", + "//vendor/k8s.io/api/core/v1: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/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/types.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/types.go index 477458231..9ea8fe5ad 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/types.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/types.go @@ -16,7 +16,10 @@ limitations under the License. package v1alpha1 -import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +import ( + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -54,4 +57,13 @@ type LimitedResource struct { // with any storage class, the list would include // ".storageclass.storage.k8s.io/requests.storage" MatchContains []string `json:"matchContains,omitempty"` + // For each intercepted request, the quota system will figure out if the input object + // satisfies a scope which is present in this listing, then + // quota system will ensure that there is a covering quota. In the + // absence of a covering quota, the quota system will deny the request. + // For example, if an administrator wants to globally enforce that + // a quota must exist to create a pod with "cluster-services" priorityclass + // the list would include "scopeName=PriorityClass, Operator=In, Value=cluster-services" + // +optional + MatchScopes []v1.ScopedResourceSelectorRequirement `json:"matchScopes,omitempty"` } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.conversion.go index 3f2cd5ac8..02f00e8f9 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -23,8 +23,10 @@ package v1alpha1 import ( unsafe "unsafe" + v1 "k8s.io/api/core/v1" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" + core "k8s.io/kubernetes/pkg/apis/core" resourcequota "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota" ) @@ -67,6 +69,7 @@ func autoConvert_v1alpha1_LimitedResource_To_resourcequota_LimitedResource(in *L out.APIGroup = in.APIGroup out.Resource = in.Resource out.MatchContains = *(*[]string)(unsafe.Pointer(&in.MatchContains)) + out.MatchScopes = *(*[]core.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchScopes)) return nil } @@ -79,6 +82,7 @@ func autoConvert_resourcequota_LimitedResource_To_v1alpha1_LimitedResource(in *r out.APIGroup = in.APIGroup out.Resource = in.Resource out.MatchContains = *(*[]string)(unsafe.Pointer(&in.MatchContains)) + out.MatchScopes = *(*[]v1.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchScopes)) return nil } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.deepcopy.go index e30940248..95a100b92 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,6 +21,7 @@ limitations under the License. package v1alpha1 import ( + v1 "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -64,6 +65,13 @@ func (in *LimitedResource) DeepCopyInto(out *LimitedResource) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.MatchScopes != nil { + in, out := &in.MatchScopes, &out.MatchScopes + *out = make([]v1.ScopedResourceSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.defaults.go index 5392d21f8..fbf617bbf 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/zz_generated.deepcopy.go index fad7a32c0..c33c217ca 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,6 +22,7 @@ package resourcequota import ( runtime "k8s.io/apimachinery/pkg/runtime" + core "k8s.io/kubernetes/pkg/apis/core" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -64,6 +65,13 @@ func (in *LimitedResource) DeepCopyInto(out *LimitedResource) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.MatchScopes != nil { + in, out := &in.MatchScopes, &out.MatchScopes + *out = make([]core.ScopedResourceSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/config.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/config.go index d706a9afb..8bb5db13c 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/config.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/config.go @@ -20,10 +20,7 @@ import ( "fmt" "io" "io/ioutil" - "os" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota" @@ -32,14 +29,12 @@ import ( ) var ( - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) - scheme = runtime.NewScheme() - codecs = serializer.NewCodecFactory(scheme) + scheme = runtime.NewScheme() + codecs = serializer.NewCodecFactory(scheme) ) func init() { - install.Install(groupFactoryRegistry, registry, scheme) + install.Install(scheme) } // LoadConfiguration loads the provided configuration. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/controller.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/controller.go index 610961af7..5f0f6fd6e 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/controller.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/controller.go @@ -25,7 +25,9 @@ import ( "github.com/golang/glog" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" @@ -366,6 +368,21 @@ func limitedByDefault(usage api.ResourceList, limitedResources []resourcequotaap return result } +func getMatchedLimitedScopes(evaluator quota.Evaluator, inputObject runtime.Object, limitedResources []resourcequotaapi.LimitedResource) ([]api.ScopedResourceSelectorRequirement, error) { + scopes := []api.ScopedResourceSelectorRequirement{} + for _, limitedResource := range limitedResources { + matched, err := evaluator.MatchingScopes(inputObject, limitedResource.MatchScopes) + if err != nil { + glog.Errorf("Error while matching limited Scopes: %v", err) + return []api.ScopedResourceSelectorRequirement{}, err + } + for _, scope := range matched { + scopes = append(scopes, scope) + } + } + return scopes, nil +} + // checkRequest verifies that the request does not exceed any quota constraint. it returns a copy of quotas not yet persisted // that capture what the usage would be if the request succeeded. It return an error if there is insufficient quota to satisfy the request func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.Attributes) ([]api.ResourceQuota, error) { @@ -382,6 +399,12 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At // if we have limited resources enabled for this resource, always calculate usage inputObject := a.GetObject() + // Check if object matches AdmissionConfiguration matchScopes + limitedScopes, err := getMatchedLimitedScopes(evaluator, inputObject, e.config.LimitedResources) + if err != nil { + return quotas, nil + } + // determine the set of resource names that must exist in a covering quota limitedResourceNames := []api.ResourceName{} limitedResources := filterLimitedResourcesByGroupResource(e.config.LimitedResources, a.GetResource().GroupResource()) @@ -403,10 +426,21 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At // this is needed to know if we have satisfied any constraints where consumption // was limited by default. restrictedResourcesSet := sets.String{} + restrictedScopes := []api.ScopedResourceSelectorRequirement{} for i := range quotas { resourceQuota := quotas[i] + scopeSelectors := getScopeSelectorsFromQuota(resourceQuota) + localRestrictedScopes, err := evaluator.MatchingScopes(inputObject, scopeSelectors) + if err != nil { + return nil, fmt.Errorf("error matching scopes of quota %s, err: %v", resourceQuota.Name, err) + } + for _, scope := range localRestrictedScopes { + restrictedScopes = append(restrictedScopes, scope) + } + match, err := evaluator.Matches(&resourceQuota, inputObject) if err != nil { + glog.Errorf("Error occurred while matching resource quota, %v, against input object. Err: %v", resourceQuota, err) return quotas, err } if !match { @@ -431,7 +465,18 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At // if not, we reject the request. hasNoCoveringQuota := limitedResourceNamesSet.Difference(restrictedResourcesSet) if len(hasNoCoveringQuota) > 0 { - return quotas, fmt.Errorf("insufficient quota to consume: %v", strings.Join(hasNoCoveringQuota.List(), ",")) + return quotas, admission.NewForbidden(a, fmt.Errorf("insufficient quota to consume: %v", strings.Join(hasNoCoveringQuota.List(), ","))) + } + + // verify that for every scope that had limited access enabled + // that there was a corresponding quota that covered it. + // if not, we reject the request. + scopesHasNoCoveringQuota, err := evaluator.UncoveredQuotaScopes(limitedScopes, restrictedScopes) + if err != nil { + return quotas, err + } + if len(scopesHasNoCoveringQuota) > 0 { + return quotas, fmt.Errorf("insufficient quota to match these scopes: %v", scopesHasNoCoveringQuota) } if len(interestingQuotaIndexes) == 0 { @@ -515,6 +560,21 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At return outQuotas, nil } +func getScopeSelectorsFromQuota(quota api.ResourceQuota) []api.ScopedResourceSelectorRequirement { + selectors := []api.ScopedResourceSelectorRequirement{} + for _, scope := range quota.Spec.Scopes { + selectors = append(selectors, api.ScopedResourceSelectorRequirement{ + ScopeName: scope, + Operator: api.ScopeSelectorOpExists}) + } + if quota.Spec.ScopeSelector != nil { + for _, scopeSelector := range quota.Spec.ScopeSelector.MatchExpressions { + selectors = append(selectors, scopeSelector) + } + } + return selectors +} + func (e *quotaEvaluator) Evaluate(a admission.Attributes) error { e.init.Do(func() { go e.run() @@ -531,7 +591,7 @@ func (e *quotaEvaluator) Evaluate(a admission.Attributes) error { evaluator := e.registry.Get(gr) if evaluator == nil { // create an object count evaluator if no evaluator previously registered - // note, we do not need aggregate usage here, so we pass a nil infomer func + // note, we do not need aggregate usage here, so we pass a nil informer func evaluator = generic.NewObjectCountEvaluator(false, gr, nil, "") e.registry.Add(evaluator) glog.Infof("quota admission added evaluator for: %s", gr) @@ -549,7 +609,7 @@ func (e *quotaEvaluator) Evaluate(a admission.Attributes) error { select { case <-waiter.finished: case <-time.After(10 * time.Second): - return fmt.Errorf("timeout") + return apierrors.NewInternalError(fmt.Errorf("resource quota evaluates timeout")) } return waiter.result @@ -582,6 +642,11 @@ func (e *quotaEvaluator) completeWork(ns string) { e.inProgress.Delete(ns) } +// getWork returns a namespace, a list of work items in that +// namespace, and a shutdown boolean. If not shutdown then the return +// must eventually be followed by a call on completeWork for the +// returned namespace (regardless of whether the work item list is +// empty). func (e *quotaEvaluator) getWork() (string, []*admissionWaiter, bool) { uncastNS, shutdown := e.queue.Get() if shutdown { @@ -598,15 +663,8 @@ func (e *quotaEvaluator) getWork() (string, []*admissionWaiter, bool) { work := e.work[ns] delete(e.work, ns) delete(e.dirtyWork, ns) - - if len(work) != 0 { - e.inProgress.Insert(ns) - return ns, work, false - } - - e.queue.Done(ns) - e.inProgress.Delete(ns) - return ns, []*admissionWaiter{}, false + e.inProgress.Insert(ns) + return ns, work, false } // prettyPrint formats a resource list for usage in errors diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/BUILD index c8a3c79ef..448b32c3e 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/BUILD @@ -15,7 +15,7 @@ go_library( "//pkg/apis/extensions:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library", - "//pkg/client/listers/extensions/internalversion:go_default_library", + "//pkg/client/listers/policy/internalversion:go_default_library", "//pkg/kubeapiserver/admission:go_default_library", "//pkg/registry/rbac:go_default_library", "//pkg/security/podsecuritypolicy:go_default_library", @@ -39,8 +39,6 @@ go_test( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", - "//pkg/apis/extensions:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library", "//pkg/controller:go_default_library", @@ -48,6 +46,7 @@ go_test( "//pkg/security/podsecuritypolicy:go_default_library", "//pkg/security/podsecuritypolicy/seccomp:go_default_library", "//pkg/security/podsecuritypolicy/util:go_default_library", + "//pkg/util/pointer:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission.go index 849ab4514..1c1b571f8 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission.go @@ -35,7 +35,7 @@ import ( "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/policy" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" - extensionslisters "k8s.io/kubernetes/pkg/client/listers/extensions/internalversion" + policylisters "k8s.io/kubernetes/pkg/client/listers/policy/internalversion" kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" psp "k8s.io/kubernetes/pkg/security/podsecuritypolicy" @@ -61,7 +61,7 @@ type PodSecurityPolicyPlugin struct { strategyFactory psp.StrategyFactory failOnNoPolicies bool authz authorizer.Authorizer - lister extensionslisters.PodSecurityPolicyLister + lister policylisters.PodSecurityPolicyLister } // SetAuthorizer sets the authorizer. @@ -84,6 +84,7 @@ var _ admission.MutationInterface = &PodSecurityPolicyPlugin{} var _ admission.ValidationInterface = &PodSecurityPolicyPlugin{} var _ genericadmissioninit.WantsAuthorizer = &PodSecurityPolicyPlugin{} var _ kubeapiserveradmission.WantsInternalKubeInformerFactory = &PodSecurityPolicyPlugin{} +var auditKeyPrefix = strings.ToLower(PluginName) + "." + policy.GroupName + ".k8s.io" // newPlugin creates a new PSP admission plugin. func newPlugin(strategyFactory psp.StrategyFactory, failOnNoPolicies bool) *PodSecurityPolicyPlugin { @@ -95,7 +96,7 @@ func newPlugin(strategyFactory psp.StrategyFactory, failOnNoPolicies bool) *PodS } func (a *PodSecurityPolicyPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { - podSecurityPolicyInformer := f.Extensions().InternalVersion().PodSecurityPolicies() + podSecurityPolicyInformer := f.Policy().InternalVersion().PodSecurityPolicies() a.lister = podSecurityPolicyInformer.Lister() a.SetReadyFunc(podSecurityPolicyInformer.Informer().HasSynced) } @@ -136,6 +137,10 @@ func (c *PodSecurityPolicyPlugin) Admit(a admission.Attributes) error { pod.ObjectMeta.Annotations = map[string]string{} } pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation] = pspName + key := auditKeyPrefix + "/" + "admit-policy" + if err := a.AddAnnotation(key, pspName); err != nil { + glog.Warningf("failed to set admission audit annotation %s to %s: %v", key, pspName, err) + } return nil } @@ -154,11 +159,15 @@ func (c *PodSecurityPolicyPlugin) Validate(a admission.Attributes) error { pod := a.GetObject().(*api.Pod) // compute the context. Mutation is not allowed. ValidatedPSPAnnotation is used as a hint to gain same speed-up. - allowedPod, _, validationErrs, err := c.computeSecurityContext(a, pod, false, pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation]) + allowedPod, pspName, validationErrs, err := c.computeSecurityContext(a, pod, false, pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation]) if err != nil { return admission.NewForbidden(a, err) } if apiequality.Semantic.DeepEqual(pod, allowedPod) { + key := auditKeyPrefix + "/" + "validate-policy" + if err := a.AddAnnotation(key, pspName); err != nil { + glog.Warningf("failed to set admission audit annotation %s to %s: %v", key, pspName, err) + } return nil } @@ -329,7 +338,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P } // createProvidersFromPolicies creates providers from the constraints supplied. -func (c *PodSecurityPolicyPlugin) createProvidersFromPolicies(psps []*extensions.PodSecurityPolicy, namespace string) ([]psp.Provider, []error) { +func (c *PodSecurityPolicyPlugin) createProvidersFromPolicies(psps []*policy.PodSecurityPolicy, namespace string) ([]psp.Provider, []error) { var ( // collected providers providers []psp.Provider diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go index dcebde331..92d4a36da 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go @@ -35,8 +35,6 @@ import ( "k8s.io/apiserver/pkg/authorization/authorizerfactory" "k8s.io/kubernetes/pkg/api/legacyscheme" kapi "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" - "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/policy" informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/controller" @@ -44,18 +42,19 @@ import ( kpsp "k8s.io/kubernetes/pkg/security/podsecuritypolicy" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util" + utilpointer "k8s.io/kubernetes/pkg/util/pointer" ) const defaultContainerName = "test-c" // NewTestAdmission provides an admission plugin with test implementations of internal structs. -func NewTestAdmission(psps []*extensions.PodSecurityPolicy, authz authorizer.Authorizer) *PodSecurityPolicyPlugin { +func NewTestAdmission(psps []*policy.PodSecurityPolicy, authz authorizer.Authorizer) *PodSecurityPolicyPlugin { informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc()) - store := informerFactory.Extensions().InternalVersion().PodSecurityPolicies().Informer().GetStore() + store := informerFactory.Policy().InternalVersion().PodSecurityPolicies().Informer().GetStore() for _, psp := range psps { store.Add(psp) } - lister := informerFactory.Extensions().InternalVersion().PodSecurityPolicies().Lister() + lister := informerFactory.Policy().InternalVersion().PodSecurityPolicies().Lister() if authz == nil { authz = &TestAuthorizer{} } @@ -216,7 +215,7 @@ func TestAdmitSeccomp(t *testing.T) { }, }, } - testPSPAdmit(k, []*extensions.PodSecurityPolicy{psp}, pod, v.shouldPassAdmit, v.shouldPassValidate, psp.Name, t) + testPSPAdmit(k, []*policy.PodSecurityPolicy{psp}, pod, v.shouldPassAdmit, v.shouldPassValidate, psp.Name, t) } } @@ -240,7 +239,7 @@ func TestAdmitPrivileged(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPriv *bool @@ -248,7 +247,7 @@ func TestAdmitPrivileged(t *testing.T) { }{ "pod with priv=nil allowed under non priv PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{nonPrivilegedPSP}, + psps: []*policy.PodSecurityPolicy{nonPrivilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: nil, @@ -256,7 +255,7 @@ func TestAdmitPrivileged(t *testing.T) { }, "pod with priv=nil allowed under priv PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{privilegedPSP}, + psps: []*policy.PodSecurityPolicy{privilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: nil, @@ -264,7 +263,7 @@ func TestAdmitPrivileged(t *testing.T) { }, "pod with priv=false allowed under non priv PSP": { pod: createPodWithPriv(false), - psps: []*extensions.PodSecurityPolicy{nonPrivilegedPSP}, + psps: []*policy.PodSecurityPolicy{nonPrivilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: &falseValue, @@ -272,7 +271,7 @@ func TestAdmitPrivileged(t *testing.T) { }, "pod with priv=false allowed under priv PSP": { pod: createPodWithPriv(false), - psps: []*extensions.PodSecurityPolicy{privilegedPSP}, + psps: []*policy.PodSecurityPolicy{privilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: &falseValue, @@ -280,13 +279,13 @@ func TestAdmitPrivileged(t *testing.T) { }, "pod with priv=true denied by non priv PSP": { pod: createPodWithPriv(true), - psps: []*extensions.PodSecurityPolicy{nonPrivilegedPSP}, + psps: []*policy.PodSecurityPolicy{nonPrivilegedPSP}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with priv=true allowed by priv PSP": { pod: createPodWithPriv(true), - psps: []*extensions.PodSecurityPolicy{nonPrivilegedPSP, privilegedPSP}, + psps: []*policy.PodSecurityPolicy{nonPrivilegedPSP, privilegedPSP}, shouldPassAdmit: true, shouldPassValidate: true, expectedPriv: &trueValue, @@ -324,11 +323,11 @@ func defaultPod(t *testing.T, pod *kapi.Pod) *kapi.Pod { func TestAdmitPreferNonmutating(t *testing.T) { mutating1 := restrictivePSP() mutating1.Name = "mutating1" - mutating1.Spec.RunAsUser.Ranges = []extensions.UserIDRange{{Min: int64(1), Max: int64(1)}} + mutating1.Spec.RunAsUser.Ranges = []policy.IDRange{{Min: int64(1), Max: int64(1)}} mutating2 := restrictivePSP() mutating2.Name = "mutating2" - mutating2.Spec.RunAsUser.Ranges = []extensions.UserIDRange{{Min: int64(2), Max: int64(2)}} + mutating2.Spec.RunAsUser.Ranges = []policy.IDRange{{Min: int64(2), Max: int64(2)}} privilegedPSP := permissivePSP() privilegedPSP.Name = "privileged" @@ -363,7 +362,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation kadmission.Operation pod *kapi.Pod podBeforeUpdate *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassValidate bool expectMutation bool expectedContainerUser *int64 @@ -372,7 +371,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { "pod should not be mutated by allow-all strategies": { operation: kadmission.Create, pod: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{privilegedPSP}, + psps: []*policy.PodSecurityPolicy{privilegedPSP}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -381,7 +380,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { "pod should prefer non-mutating PSP on create": { operation: kadmission.Create, pod: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1, privilegedPSP}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1, privilegedPSP}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -390,7 +389,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { "pod should use deterministic mutating PSP on create": { operation: kadmission.Create, pod: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: true, expectMutation: true, expectedContainerUser: &mutating1.Spec.RunAsUser.Ranges[0].Min, @@ -399,7 +398,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { "pod should use deterministic mutating PSP on create even if ValidatedPSPAnnotation is set": { operation: kadmission.Create, pod: podWithAnnotation, - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: true, expectMutation: true, expectedContainerUser: &mutating1.Spec.RunAsUser.Ranges[0].Min, @@ -409,7 +408,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation: kadmission.Update, pod: changedPodWithSC.DeepCopy(), podBeforeUpdate: podWithSC.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1, privilegedPSP}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1, privilegedPSP}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -419,7 +418,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation: kadmission.Update, pod: changedPod.DeepCopy(), podBeforeUpdate: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: false, expectMutation: false, expectedContainerUser: nil, @@ -429,7 +428,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation: kadmission.Update, pod: unprivilegedRunAsAnyPod.DeepCopy(), podBeforeUpdate: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -439,7 +438,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { operation: kadmission.Update, pod: gcChangedPod.DeepCopy(), podBeforeUpdate: unprivilegedRunAsAnyPod.DeepCopy(), - psps: []*extensions.PodSecurityPolicy{mutating2, mutating1}, + psps: []*policy.PodSecurityPolicy{mutating2, mutating1}, shouldPassValidate: true, expectMutation: false, expectedContainerUser: nil, @@ -515,11 +514,11 @@ func TestAdmitCaps(t *testing.T) { allowAllInAllowed := restrictivePSP() allowAllInAllowed.Name = "allowAllCapsInAllowed" - allowAllInAllowed.Spec.AllowedCapabilities = []kapi.Capability{extensions.AllowAllCapabilities} + allowAllInAllowed.Spec.AllowedCapabilities = []kapi.Capability{policy.AllowAllCapabilities} tc := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedCapabilities *kapi.Capabilities @@ -529,7 +528,7 @@ func TestAdmitCaps(t *testing.T) { // should be rejected. "should reject cap add when not allowed or required": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted}, + psps: []*policy.PodSecurityPolicy{restricted}, shouldPassAdmit: false, shouldPassValidate: false, }, @@ -537,7 +536,7 @@ func TestAdmitCaps(t *testing.T) { // to add the cap. "should accept cap add when in allowed": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted, allowsFooInAllowed}, + psps: []*policy.PodSecurityPolicy{restricted, allowsFooInAllowed}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: allowsFooInAllowed.Name, @@ -546,7 +545,7 @@ func TestAdmitCaps(t *testing.T) { // to add the cap. "should accept cap add when in required": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted, allowsFooInRequired}, + psps: []*policy.PodSecurityPolicy{restricted, allowsFooInRequired}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: allowsFooInRequired.Name, @@ -555,7 +554,7 @@ func TestAdmitCaps(t *testing.T) { // in the verification of adds and verification of drops "should reject cap add when requested cap is required to be dropped": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted, requiresFooToBeDropped}, + psps: []*policy.PodSecurityPolicy{restricted, requiresFooToBeDropped}, shouldPassAdmit: false, shouldPassValidate: false, }, @@ -563,7 +562,7 @@ func TestAdmitCaps(t *testing.T) { // a manual request to drop the cap. "should accept cap drop when cap is required to be dropped": { pod: createPodWithCaps(&kapi.Capabilities{Drop: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{requiresFooToBeDropped}, + psps: []*policy.PodSecurityPolicy{requiresFooToBeDropped}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: requiresFooToBeDropped.Name, @@ -571,7 +570,7 @@ func TestAdmitCaps(t *testing.T) { // UC 6: required add is defaulted "required add is defaulted": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{allowsFooInRequired}, + psps: []*policy.PodSecurityPolicy{allowsFooInRequired}, shouldPassAdmit: true, shouldPassValidate: true, expectedCapabilities: &kapi.Capabilities{ @@ -582,7 +581,7 @@ func TestAdmitCaps(t *testing.T) { // UC 7: required drop is defaulted "required drop is defaulted": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{requiresFooToBeDropped}, + psps: []*policy.PodSecurityPolicy{requiresFooToBeDropped}, shouldPassAdmit: true, shouldPassValidate: true, expectedCapabilities: &kapi.Capabilities{ @@ -593,7 +592,7 @@ func TestAdmitCaps(t *testing.T) { // UC 8: using '*' in allowed caps "should accept cap add when all caps are allowed": { pod: createPodWithCaps(&kapi.Capabilities{Add: []kapi.Capability{"foo"}}), - psps: []*extensions.PodSecurityPolicy{restricted, allowAllInAllowed}, + psps: []*policy.PodSecurityPolicy{restricted, allowAllInAllowed}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: allowAllInAllowed.Name, @@ -651,19 +650,19 @@ func TestAdmitVolumes(t *testing.T) { psp := restrictivePSP() // expect a denial for this PSP - testPSPAdmit(fmt.Sprintf("%s denial", string(fsType)), []*extensions.PodSecurityPolicy{psp}, pod, false, false, "", t) + testPSPAdmit(fmt.Sprintf("%s denial", string(fsType)), []*policy.PodSecurityPolicy{psp}, pod, false, false, "", t) // also expect a denial for this PSP if it's an init container useInitContainers(pod) - testPSPAdmit(fmt.Sprintf("%s denial", string(fsType)), []*extensions.PodSecurityPolicy{psp}, pod, false, false, "", t) + testPSPAdmit(fmt.Sprintf("%s denial", string(fsType)), []*policy.PodSecurityPolicy{psp}, pod, false, false, "", t) // now add the fstype directly to the psp and it should validate - psp.Spec.Volumes = []extensions.FSType{fsType} - testPSPAdmit(fmt.Sprintf("%s direct accept", string(fsType)), []*extensions.PodSecurityPolicy{psp}, pod, true, true, psp.Name, t) + psp.Spec.Volumes = []policy.FSType{fsType} + testPSPAdmit(fmt.Sprintf("%s direct accept", string(fsType)), []*policy.PodSecurityPolicy{psp}, pod, true, true, psp.Name, t) // now change the psp to allow any volumes and the pod should still validate - psp.Spec.Volumes = []extensions.FSType{extensions.All} - testPSPAdmit(fmt.Sprintf("%s wildcard accept", string(fsType)), []*extensions.PodSecurityPolicy{psp}, pod, true, true, psp.Name, t) + psp.Spec.Volumes = []policy.FSType{policy.All} + testPSPAdmit(fmt.Sprintf("%s wildcard accept", string(fsType)), []*policy.PodSecurityPolicy{psp}, pod, true, true, psp.Name, t) } } @@ -684,7 +683,7 @@ func TestAdmitHostNetwork(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedHostNetwork bool @@ -692,7 +691,7 @@ func TestAdmitHostNetwork(t *testing.T) { }{ "pod without hostnetwork request allowed under noHostNetwork PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noHostNetwork}, + psps: []*policy.PodSecurityPolicy{noHostNetwork}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostNetwork: false, @@ -700,7 +699,7 @@ func TestAdmitHostNetwork(t *testing.T) { }, "pod without hostnetwork request allowed under hostNetwork PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{hostNetwork}, + psps: []*policy.PodSecurityPolicy{hostNetwork}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostNetwork: false, @@ -708,13 +707,13 @@ func TestAdmitHostNetwork(t *testing.T) { }, "pod with hostnetwork request denied by noHostNetwork PSP": { pod: createPodWithHostNetwork(true), - psps: []*extensions.PodSecurityPolicy{noHostNetwork}, + psps: []*policy.PodSecurityPolicy{noHostNetwork}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with hostnetwork request allowed by hostNetwork PSP": { pod: createPodWithHostNetwork(true), - psps: []*extensions.PodSecurityPolicy{noHostNetwork, hostNetwork}, + psps: []*policy.PodSecurityPolicy{noHostNetwork, hostNetwork}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostNetwork: true, @@ -759,47 +758,47 @@ func TestAdmitHostPorts(t *testing.T) { hostPorts := restrictivePSP() hostPorts.Name = "hostPorts" - hostPorts.Spec.HostPorts = []extensions.HostPortRange{ + hostPorts.Spec.HostPorts = []policy.HostPortRange{ {Min: 1, Max: 10}, } tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPSP string }{ "host port out of range": { pod: createPodWithHostPorts(11), - psps: []*extensions.PodSecurityPolicy{hostPorts}, + psps: []*policy.PodSecurityPolicy{hostPorts}, shouldPassAdmit: false, shouldPassValidate: false, }, "host port in range": { pod: createPodWithHostPorts(5), - psps: []*extensions.PodSecurityPolicy{hostPorts}, + psps: []*policy.PodSecurityPolicy{hostPorts}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: hostPorts.Name, }, "no host ports with range": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{hostPorts}, + psps: []*policy.PodSecurityPolicy{hostPorts}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: hostPorts.Name, }, "no host ports without range": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noHostPorts}, + psps: []*policy.PodSecurityPolicy{noHostPorts}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: noHostPorts.Name, }, "host ports without range": { pod: createPodWithHostPorts(5), - psps: []*extensions.PodSecurityPolicy{noHostPorts}, + psps: []*policy.PodSecurityPolicy{noHostPorts}, shouldPassAdmit: false, shouldPassValidate: false, }, @@ -830,7 +829,7 @@ func TestAdmitHostPID(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedHostPID bool @@ -838,7 +837,7 @@ func TestAdmitHostPID(t *testing.T) { }{ "pod without hostpid request allowed under noHostPID PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noHostPID}, + psps: []*policy.PodSecurityPolicy{noHostPID}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostPID: false, @@ -846,7 +845,7 @@ func TestAdmitHostPID(t *testing.T) { }, "pod without hostpid request allowed under hostPID PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{hostPID}, + psps: []*policy.PodSecurityPolicy{hostPID}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostPID: false, @@ -854,12 +853,12 @@ func TestAdmitHostPID(t *testing.T) { }, "pod with hostpid request denied by noHostPID PSP": { pod: createPodWithHostPID(true), - psps: []*extensions.PodSecurityPolicy{noHostPID}, + psps: []*policy.PodSecurityPolicy{noHostPID}, shouldPassAdmit: false, }, "pod with hostpid request allowed by hostPID PSP": { pod: createPodWithHostPID(true), - psps: []*extensions.PodSecurityPolicy{noHostPID, hostPID}, + psps: []*policy.PodSecurityPolicy{noHostPID, hostPID}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostPID: true, @@ -895,7 +894,7 @@ func TestAdmitHostIPC(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedHostIPC bool @@ -903,7 +902,7 @@ func TestAdmitHostIPC(t *testing.T) { }{ "pod without hostIPC request allowed under noHostIPC PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noHostIPC}, + psps: []*policy.PodSecurityPolicy{noHostIPC}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostIPC: false, @@ -911,7 +910,7 @@ func TestAdmitHostIPC(t *testing.T) { }, "pod without hostIPC request allowed under hostIPC PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{hostIPC}, + psps: []*policy.PodSecurityPolicy{hostIPC}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostIPC: false, @@ -919,13 +918,13 @@ func TestAdmitHostIPC(t *testing.T) { }, "pod with hostIPC request denied by noHostIPC PSP": { pod: createPodWithHostIPC(true), - psps: []*extensions.PodSecurityPolicy{noHostIPC}, + psps: []*policy.PodSecurityPolicy{noHostIPC}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with hostIPC request allowed by hostIPC PSP": { pod: createPodWithHostIPC(true), - psps: []*extensions.PodSecurityPolicy{noHostIPC, hostIPC}, + psps: []*policy.PodSecurityPolicy{noHostIPC, hostIPC}, shouldPassAdmit: true, shouldPassValidate: true, expectedHostIPC: true, @@ -954,12 +953,12 @@ func createPodWithSecurityContexts(podSC *kapi.PodSecurityContext, containerSC * func TestAdmitSELinux(t *testing.T) { runAsAny := permissivePSP() runAsAny.Name = "runAsAny" - runAsAny.Spec.SELinux.Rule = extensions.SELinuxStrategyRunAsAny + runAsAny.Spec.SELinux.Rule = policy.SELinuxStrategyRunAsAny runAsAny.Spec.SELinux.SELinuxOptions = nil mustRunAs := permissivePSP() mustRunAs.Name = "mustRunAs" - mustRunAs.Spec.SELinux.Rule = extensions.SELinuxStrategyMustRunAs + mustRunAs.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs mustRunAs.Spec.SELinux.SELinuxOptions = &kapi.SELinuxOptions{} mustRunAs.Spec.SELinux.SELinuxOptions.Level = "level" mustRunAs.Spec.SELinux.SELinuxOptions.Role = "role" @@ -968,7 +967,7 @@ func TestAdmitSELinux(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPodSC *kapi.PodSecurityContext @@ -977,7 +976,7 @@ func TestAdmitSELinux(t *testing.T) { }{ "runAsAny with no request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -986,7 +985,7 @@ func TestAdmitSELinux(t *testing.T) { }, "runAsAny with empty pod request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{}, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{}, @@ -995,7 +994,7 @@ func TestAdmitSELinux(t *testing.T) { }, "runAsAny with empty container request": { pod: createPodWithSecurityContexts(nil, &kapi.SecurityContext{}), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1005,7 +1004,7 @@ func TestAdmitSELinux(t *testing.T) { "runAsAny with pod request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}, @@ -1014,7 +1013,7 @@ func TestAdmitSELinux(t *testing.T) { }, "runAsAny with container request": { pod: createPodWithSecurityContexts(nil, &kapi.SecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1023,7 +1022,7 @@ func TestAdmitSELinux(t *testing.T) { }, "runAsAny with pod and container request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "bar"}}, &kapi.SecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "bar"}}, @@ -1033,19 +1032,19 @@ func TestAdmitSELinux(t *testing.T) { "mustRunAs with bad pod request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}, nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs with bad container request": { pod: createPodWithSecurityContexts(nil, &kapi.SecurityContext{SELinuxOptions: &kapi.SELinuxOptions{User: "foo"}}), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs with no request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: mustRunAs.Spec.SELinux.SELinuxOptions}, @@ -1057,7 +1056,7 @@ func TestAdmitSELinux(t *testing.T) { &kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{Level: "level", Role: "role", Type: "type", User: "user"}}, nil, ), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: mustRunAs.Spec.SELinux.SELinuxOptions}, @@ -1069,7 +1068,7 @@ func TestAdmitSELinux(t *testing.T) { &kapi.PodSecurityContext{SELinuxOptions: &kapi.SELinuxOptions{Level: "level", Role: "role", Type: "type", User: "user"}}, nil, ), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: mustRunAs.Spec.SELinux.SELinuxOptions}, @@ -1116,7 +1115,7 @@ func TestAdmitAppArmor(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psp *extensions.PodSecurityPolicy + psp *policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedProfile string @@ -1171,7 +1170,7 @@ func TestAdmitAppArmor(t *testing.T) { } for k, v := range tests { - testPSPAdmit(k, []*extensions.PodSecurityPolicy{v.psp}, v.pod, v.shouldPassAdmit, v.shouldPassValidate, v.psp.Name, t) + testPSPAdmit(k, []*policy.PodSecurityPolicy{v.psp}, v.pod, v.shouldPassAdmit, v.shouldPassValidate, v.psp.Name, t) if v.shouldPassAdmit { assert.Equal(t, v.expectedProfile, apparmor.GetProfileNameFromPodAnnotations(v.pod.Annotations, defaultContainerName), k) @@ -1189,24 +1188,24 @@ func TestAdmitRunAsUser(t *testing.T) { runAsAny := permissivePSP() runAsAny.Name = "runAsAny" - runAsAny.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyRunAsAny + runAsAny.Spec.RunAsUser.Rule = policy.RunAsUserStrategyRunAsAny mustRunAs := permissivePSP() mustRunAs.Name = "mustRunAs" - mustRunAs.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAs - mustRunAs.Spec.RunAsUser.Ranges = []extensions.UserIDRange{ + mustRunAs.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAs + mustRunAs.Spec.RunAsUser.Ranges = []policy.IDRange{ {Min: int64(999), Max: int64(1000)}, } runAsNonRoot := permissivePSP() runAsNonRoot.Name = "runAsNonRoot" - runAsNonRoot.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAsNonRoot + runAsNonRoot.Spec.RunAsUser.Rule = policy.RunAsUserStrategyMustRunAsNonRoot trueValue := true tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPodSC *kapi.PodSecurityContext @@ -1215,7 +1214,7 @@ func TestAdmitRunAsUser(t *testing.T) { }{ "runAsAny no pod request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1223,40 +1222,40 @@ func TestAdmitRunAsUser(t *testing.T) { expectedPSP: runAsAny.Name, }, "runAsAny pod request": { - pod: createPodWithSecurityContexts(podSC(userIDPtr(1)), nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), nil), + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPodSC: podSC(userIDPtr(1)), + expectedPodSC: podSC(utilpointer.Int64Ptr(1)), expectedContainerSC: nil, expectedPSP: runAsAny.Name, }, "runAsAny container request": { - pod: createPodWithSecurityContexts(nil, containerSC(userIDPtr(1))), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + pod: createPodWithSecurityContexts(nil, containerSC(utilpointer.Int64Ptr(1))), + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, - expectedContainerSC: containerSC(userIDPtr(1)), + expectedContainerSC: containerSC(utilpointer.Int64Ptr(1)), expectedPSP: runAsAny.Name, }, "mustRunAs pod request out of range": { - pod: createPodWithSecurityContexts(podSC(userIDPtr(1)), nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), nil), + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs container request out of range": { - pod: createPodWithSecurityContexts(podSC(userIDPtr(999)), containerSC(userIDPtr(1))), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(999)), containerSC(utilpointer.Int64Ptr(1))), + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs pod request in range": { - pod: createPodWithSecurityContexts(podSC(userIDPtr(999)), nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(999)), nil), + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(&mustRunAs.Spec.RunAsUser.Ranges[0].Min), @@ -1264,8 +1263,8 @@ func TestAdmitRunAsUser(t *testing.T) { expectedPSP: mustRunAs.Name, }, "mustRunAs container request in range": { - pod: createPodWithSecurityContexts(nil, containerSC(userIDPtr(999))), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + pod: createPodWithSecurityContexts(nil, containerSC(utilpointer.Int64Ptr(999))), + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1273,17 +1272,17 @@ func TestAdmitRunAsUser(t *testing.T) { expectedPSP: mustRunAs.Name, }, "mustRunAs pod and container request in range": { - pod: createPodWithSecurityContexts(podSC(userIDPtr(999)), containerSC(userIDPtr(1000))), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(999)), containerSC(utilpointer.Int64Ptr(1000))), + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPodSC: podSC(userIDPtr(999)), - expectedContainerSC: containerSC(userIDPtr(1000)), + expectedPodSC: podSC(utilpointer.Int64Ptr(999)), + expectedContainerSC: containerSC(utilpointer.Int64Ptr(1000)), expectedPSP: mustRunAs.Name, }, "mustRunAs no request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1293,7 +1292,7 @@ func TestAdmitRunAsUser(t *testing.T) { "runAsNonRoot no request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1301,32 +1300,32 @@ func TestAdmitRunAsUser(t *testing.T) { expectedPSP: runAsNonRoot.Name, }, "runAsNonRoot pod request root": { - pod: createPodWithSecurityContexts(podSC(userIDPtr(0)), nil), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(0)), nil), + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: false, shouldPassValidate: false, }, "runAsNonRoot pod request non-root": { - pod: createPodWithSecurityContexts(podSC(userIDPtr(1)), nil), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), nil), + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPodSC: podSC(userIDPtr(1)), + expectedPodSC: podSC(utilpointer.Int64Ptr(1)), expectedPSP: runAsNonRoot.Name, }, "runAsNonRoot container request root": { - pod: createPodWithSecurityContexts(podSC(userIDPtr(1)), containerSC(userIDPtr(0))), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), containerSC(utilpointer.Int64Ptr(0))), + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: false, shouldPassValidate: false, }, "runAsNonRoot container request non-root": { - pod: createPodWithSecurityContexts(podSC(userIDPtr(1)), containerSC(userIDPtr(2))), - psps: []*extensions.PodSecurityPolicy{runAsNonRoot}, + pod: createPodWithSecurityContexts(podSC(utilpointer.Int64Ptr(1)), containerSC(utilpointer.Int64Ptr(2))), + psps: []*policy.PodSecurityPolicy{runAsNonRoot}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPodSC: podSC(userIDPtr(1)), - expectedContainerSC: containerSC(userIDPtr(2)), + expectedPodSC: podSC(utilpointer.Int64Ptr(1)), + expectedContainerSC: containerSC(utilpointer.Int64Ptr(2)), expectedPSP: runAsNonRoot.Name, }, } @@ -1352,16 +1351,16 @@ func TestAdmitSupplementalGroups(t *testing.T) { runAsAny := permissivePSP() runAsAny.Name = "runAsAny" - runAsAny.Spec.SupplementalGroups.Rule = extensions.SupplementalGroupsStrategyRunAsAny + runAsAny.Spec.SupplementalGroups.Rule = policy.SupplementalGroupsStrategyRunAsAny mustRunAs := permissivePSP() mustRunAs.Name = "mustRunAs" - mustRunAs.Spec.SupplementalGroups.Rule = extensions.SupplementalGroupsStrategyMustRunAs - mustRunAs.Spec.SupplementalGroups.Ranges = []extensions.GroupIDRange{{Min: int64(999), Max: int64(1000)}} + mustRunAs.Spec.SupplementalGroups.Rule = policy.SupplementalGroupsStrategyMustRunAs + mustRunAs.Spec.SupplementalGroups.Ranges = []policy.IDRange{{Min: int64(999), Max: int64(1000)}} tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPodSC *kapi.PodSecurityContext @@ -1369,7 +1368,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }{ "runAsAny no pod request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: nil, @@ -1377,7 +1376,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "runAsAny empty pod request": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{}, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{}, @@ -1385,7 +1384,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "runAsAny empty pod request empty supplemental groups": { pod: createPodWithSecurityContexts(&kapi.PodSecurityContext{SupplementalGroups: []int64{}}, nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SupplementalGroups: []int64{}}, @@ -1393,7 +1392,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "runAsAny pod request": { pod: createPodWithSecurityContexts(podSC(1), nil), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: &kapi.PodSecurityContext{SupplementalGroups: []int64{1}}, @@ -1401,7 +1400,7 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "mustRunAs no pod request": { pod: createPodWithSecurityContexts(nil, nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(mustRunAs.Spec.SupplementalGroups.Ranges[0].Min), @@ -1409,13 +1408,13 @@ func TestAdmitSupplementalGroups(t *testing.T) { }, "mustRunAs bad pod request": { pod: createPodWithSecurityContexts(podSC(1), nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs good pod request": { pod: createPodWithSecurityContexts(podSC(999), nil), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedPodSC: podSC(999), @@ -1435,25 +1434,25 @@ func TestAdmitSupplementalGroups(t *testing.T) { } func TestAdmitFSGroup(t *testing.T) { - createPodWithFSGroup := func(group int) *kapi.Pod { + createPodWithFSGroup := func(group int64) *kapi.Pod { pod := goodPod() // doesn't matter if we set it here or on the container, the // admission controller uses DetermineEffectiveSC to get the defaulting // behavior so it can validate what will be applied at runtime - pod.Spec.SecurityContext.FSGroup = groupIDPtr(group) + pod.Spec.SecurityContext.FSGroup = utilpointer.Int64Ptr(group) return pod } runAsAny := restrictivePSP() runAsAny.Name = "runAsAny" - runAsAny.Spec.FSGroup.Rule = extensions.FSGroupStrategyRunAsAny + runAsAny.Spec.FSGroup.Rule = policy.FSGroupStrategyRunAsAny mustRunAs := restrictivePSP() mustRunAs.Name = "mustRunAs" tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedFSGroup *int64 @@ -1461,7 +1460,7 @@ func TestAdmitFSGroup(t *testing.T) { }{ "runAsAny no pod request": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, expectedFSGroup: nil, @@ -1469,15 +1468,15 @@ func TestAdmitFSGroup(t *testing.T) { }, "runAsAny pod request": { pod: createPodWithFSGroup(1), - psps: []*extensions.PodSecurityPolicy{runAsAny}, + psps: []*policy.PodSecurityPolicy{runAsAny}, shouldPassAdmit: true, shouldPassValidate: true, - expectedFSGroup: groupIDPtr(1), + expectedFSGroup: utilpointer.Int64Ptr(1), expectedPSP: runAsAny.Name, }, "mustRunAs no pod request": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, expectedFSGroup: &mustRunAs.Spec.SupplementalGroups.Ranges[0].Min, @@ -1485,16 +1484,16 @@ func TestAdmitFSGroup(t *testing.T) { }, "mustRunAs bad pod request": { pod: createPodWithFSGroup(1), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: false, shouldPassValidate: false, }, "mustRunAs good pod request": { pod: createPodWithFSGroup(999), - psps: []*extensions.PodSecurityPolicy{mustRunAs}, + psps: []*policy.PodSecurityPolicy{mustRunAs}, shouldPassAdmit: true, shouldPassValidate: true, - expectedFSGroup: groupIDPtr(999), + expectedFSGroup: utilpointer.Int64Ptr(999), expectedPSP: mustRunAs.Name, }, } @@ -1539,7 +1538,7 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedRORFS bool @@ -1547,7 +1546,7 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { }{ "no-rorfs allows pod request with rorfs": { pod: createPodWithRORFS(true), - psps: []*extensions.PodSecurityPolicy{noRORFS}, + psps: []*policy.PodSecurityPolicy{noRORFS}, shouldPassAdmit: true, shouldPassValidate: true, expectedRORFS: true, @@ -1555,7 +1554,7 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { }, "no-rorfs allows pod request without rorfs": { pod: createPodWithRORFS(false), - psps: []*extensions.PodSecurityPolicy{noRORFS}, + psps: []*policy.PodSecurityPolicy{noRORFS}, shouldPassAdmit: true, shouldPassValidate: true, expectedRORFS: false, @@ -1563,13 +1562,13 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { }, "rorfs rejects pod request without rorfs": { pod: createPodWithRORFS(false), - psps: []*extensions.PodSecurityPolicy{rorfs}, + psps: []*policy.PodSecurityPolicy{rorfs}, shouldPassAdmit: false, shouldPassValidate: false, }, "rorfs defaults nil pod request": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{rorfs}, + psps: []*policy.PodSecurityPolicy{rorfs}, shouldPassAdmit: true, shouldPassValidate: true, expectedRORFS: true, @@ -1577,7 +1576,7 @@ func TestAdmitReadOnlyRootFilesystem(t *testing.T) { }, "rorfs accepts pod request with rorfs": { pod: createPodWithRORFS(true), - psps: []*extensions.PodSecurityPolicy{rorfs}, + psps: []*policy.PodSecurityPolicy{rorfs}, shouldPassAdmit: true, shouldPassValidate: true, expectedRORFS: true, @@ -1608,201 +1607,171 @@ func TestAdmitSysctls(t *testing.T) { } return sysctls } - pod.Annotations[kapi.SysctlsPodAnnotationKey] = helper.PodAnnotationsFromSysctls(dummySysctls(safeSysctls)) - pod.Annotations[kapi.UnsafeSysctlsPodAnnotationKey] = helper.PodAnnotationsFromSysctls(dummySysctls(unsafeSysctls)) + pod.Spec.SecurityContext = &kapi.PodSecurityContext{ + Sysctls: dummySysctls(append(safeSysctls, unsafeSysctls...)), + } + return pod } - noSysctls := restrictivePSP() - noSysctls.Name = "no sysctls" + safeSysctls := restrictivePSP() + safeSysctls.Name = "no sysctls" - emptySysctls := restrictivePSP() - emptySysctls.Name = "empty sysctls" - emptySysctls.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "" + noSysctls := restrictivePSP() + noSysctls.Name = "empty sysctls" + noSysctls.Spec.ForbiddenSysctls = []string{"*"} mixedSysctls := restrictivePSP() mixedSysctls.Name = "wildcard sysctls" - mixedSysctls.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "a.*,b.*,c,d.e.f" + mixedSysctls.Spec.ForbiddenSysctls = []string{"net.*"} + mixedSysctls.Spec.AllowedUnsafeSysctls = []string{"a.*", "b.*"} - aSysctl := restrictivePSP() - aSysctl.Name = "a sysctl" - aSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "a" + aUnsafeSysctl := restrictivePSP() + aUnsafeSysctl.Name = "a sysctl" + aUnsafeSysctl.Spec.AllowedUnsafeSysctls = []string{"a"} - bSysctl := restrictivePSP() - bSysctl.Name = "b sysctl" - bSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "b" + bUnsafeSysctl := restrictivePSP() + bUnsafeSysctl.Name = "b sysctl" + bUnsafeSysctl.Spec.AllowedUnsafeSysctls = []string{"b"} - cSysctl := restrictivePSP() - cSysctl.Name = "c sysctl" - cSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "c" + cUnsafeSysctl := restrictivePSP() + cUnsafeSysctl.Name = "c sysctl" + cUnsafeSysctl.Spec.AllowedUnsafeSysctls = []string{"c"} catchallSysctls := restrictivePSP() catchallSysctls.Name = "catchall sysctl" - catchallSysctls.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "*" + catchallSysctls.Spec.AllowedUnsafeSysctls = []string{"*"} tests := map[string]struct { pod *kapi.Pod - psps []*extensions.PodSecurityPolicy + psps []*policy.PodSecurityPolicy shouldPassAdmit bool shouldPassValidate bool expectedPSP string }{ - "pod without unsafe sysctls request allowed under noSysctls PSP": { + "pod without any sysctls request allowed under safeSysctls PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{noSysctls}, + psps: []*policy.PodSecurityPolicy{safeSysctls}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPSP: noSysctls.Name, + expectedPSP: safeSysctls.Name, }, - "pod without any sysctls request allowed under emptySysctls PSP": { + "pod without any sysctls request allowed under noSysctls PSP": { pod: goodPod(), - psps: []*extensions.PodSecurityPolicy{emptySysctls}, - shouldPassAdmit: true, - shouldPassValidate: true, - expectedPSP: emptySysctls.Name, - }, - "pod with safe sysctls request allowed under noSysctls PSP": { - pod: podWithSysctls([]string{"a", "b"}, []string{}), - psps: []*extensions.PodSecurityPolicy{noSysctls}, + psps: []*policy.PodSecurityPolicy{noSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: noSysctls.Name, }, - "pod with unsafe sysctls request allowed under noSysctls PSP": { - pod: podWithSysctls([]string{}, []string{"a", "b"}), - psps: []*extensions.PodSecurityPolicy{noSysctls}, + "pod with safe sysctls request allowed under safeSysctls PSP": { + pod: podWithSysctls([]string{"kernel.shm_rmid_forced", "net.ipv4.tcp_syncookies"}, []string{}), + psps: []*policy.PodSecurityPolicy{safeSysctls}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPSP: noSysctls.Name, + expectedPSP: safeSysctls.Name, }, - "pod with safe sysctls request disallowed under emptySysctls PSP": { - pod: podWithSysctls([]string{"a", "b"}, []string{}), - psps: []*extensions.PodSecurityPolicy{emptySysctls}, + "pod with unsafe sysctls request disallowed under noSysctls PSP": { + pod: podWithSysctls([]string{}, []string{"a", "b"}), + psps: []*policy.PodSecurityPolicy{noSysctls}, shouldPassAdmit: false, shouldPassValidate: false, + expectedPSP: noSysctls.Name, }, - "pod with unsafe sysctls a, b request disallowed under aSysctls SCC": { + "pod with unsafe sysctls a, b request disallowed under aUnsafeSysctl SCC": { pod: podWithSysctls([]string{}, []string{"a", "b"}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aUnsafeSysctl}, shouldPassAdmit: false, shouldPassValidate: false, }, - "pod with unsafe sysctls b request disallowed under aSysctls SCC": { + "pod with unsafe sysctls b request disallowed under aUnsafeSysctl SCC": { pod: podWithSysctls([]string{}, []string{"b"}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aUnsafeSysctl}, shouldPassAdmit: false, shouldPassValidate: false, }, - "pod with unsafe sysctls a request allowed under aSysctls SCC": { + "pod with unsafe sysctls a request allowed under aUnsafeSysctl SCC": { pod: podWithSysctls([]string{}, []string{"a"}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + psps: []*policy.PodSecurityPolicy{aUnsafeSysctl}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPSP: aSysctl.Name, + expectedPSP: aUnsafeSysctl.Name, }, - "pod with safe sysctls a, b request disallowed under aSysctls SCC": { - pod: podWithSysctls([]string{"a", "b"}, []string{}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, - shouldPassAdmit: false, - shouldPassValidate: false, - }, - "pod with safe sysctls b request disallowed under aSysctls SCC": { - pod: podWithSysctls([]string{"b"}, []string{}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, - shouldPassAdmit: false, - shouldPassValidate: false, - }, - "pod with safe sysctls a request allowed under aSysctls SCC": { - pod: podWithSysctls([]string{"a"}, []string{}), - psps: []*extensions.PodSecurityPolicy{aSysctl}, + "pod with safe net sysctl request allowed under aUnsafeSysctl SCC": { + pod: podWithSysctls([]string{"net.ipv4.ip_local_port_range"}, []string{}), + psps: []*policy.PodSecurityPolicy{aUnsafeSysctl}, shouldPassAdmit: true, shouldPassValidate: true, - expectedPSP: aSysctl.Name, + expectedPSP: aUnsafeSysctl.Name, }, - "pod with unsafe sysctls request disallowed under emptySysctls PSP": { - pod: podWithSysctls([]string{}, []string{"a", "b"}), - psps: []*extensions.PodSecurityPolicy{emptySysctls}, + "pod with safe sysctls request disallowed under noSysctls PSP": { + pod: podWithSysctls([]string{"net.ipv4.ip_local_port_range"}, []string{}), + psps: []*policy.PodSecurityPolicy{noSysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with matching sysctls request allowed under mixedSysctls PSP": { - pod: podWithSysctls([]string{"a.b", "b.c"}, []string{"c", "d.e.f"}), - psps: []*extensions.PodSecurityPolicy{mixedSysctls}, + pod: podWithSysctls([]string{"kernel.shm_rmid_forced"}, []string{"a.b", "b.a"}), + psps: []*policy.PodSecurityPolicy{mixedSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: mixedSysctls.Name, }, "pod with not-matching unsafe sysctls request disallowed under mixedSysctls PSP": { - pod: podWithSysctls([]string{"a.b", "b.c", "c", "d.e.f"}, []string{"e"}), - psps: []*extensions.PodSecurityPolicy{mixedSysctls}, + pod: podWithSysctls([]string{}, []string{"e"}), + psps: []*policy.PodSecurityPolicy{mixedSysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with not-matching safe sysctls request disallowed under mixedSysctls PSP": { - pod: podWithSysctls([]string{"a.b", "b.c", "c", "d.e.f", "e"}, []string{}), - psps: []*extensions.PodSecurityPolicy{mixedSysctls}, + pod: podWithSysctls([]string{"net.ipv4.ip_local_port_range"}, []string{}), + psps: []*policy.PodSecurityPolicy{mixedSysctls}, shouldPassAdmit: false, shouldPassValidate: false, }, "pod with sysctls request allowed under catchallSysctls PSP": { - pod: podWithSysctls([]string{"e"}, []string{"f"}), - psps: []*extensions.PodSecurityPolicy{catchallSysctls}, - shouldPassAdmit: true, - shouldPassValidate: true, - expectedPSP: catchallSysctls.Name, - }, - "pod with sysctls request allowed under catchallSysctls PSP, not under mixedSysctls or emptySysctls PSP": { - pod: podWithSysctls([]string{"e"}, []string{"f"}), - psps: []*extensions.PodSecurityPolicy{mixedSysctls, catchallSysctls, emptySysctls}, + pod: podWithSysctls([]string{"net.ipv4.ip_local_port_range"}, []string{"f"}), + psps: []*policy.PodSecurityPolicy{catchallSysctls}, shouldPassAdmit: true, shouldPassValidate: true, expectedPSP: catchallSysctls.Name, }, - "pod with safe c sysctl request allowed under cSysctl PSP, not under aSysctl or bSysctl PSP": { - pod: podWithSysctls([]string{}, []string{"c"}), - psps: []*extensions.PodSecurityPolicy{aSysctl, bSysctl, cSysctl}, - shouldPassAdmit: true, - shouldPassValidate: true, - expectedPSP: cSysctl.Name, - }, - "pod with unsafe c sysctl request allowed under cSysctl PSP, not under aSysctl or bSysctl PSP": { - pod: podWithSysctls([]string{"c"}, []string{}), - psps: []*extensions.PodSecurityPolicy{aSysctl, bSysctl, cSysctl}, - shouldPassAdmit: true, - shouldPassValidate: true, - expectedPSP: cSysctl.Name, - }, } for k, v := range tests { - origSafeSysctls, origUnsafeSysctls, err := helper.SysctlsFromPodAnnotations(v.pod.Annotations) - if err != nil { - t.Fatalf("invalid sysctl annotation: %v", err) - } + origSysctl := v.pod.Spec.SecurityContext.Sysctls testPSPAdmit(k, v.psps, v.pod, v.shouldPassAdmit, v.shouldPassValidate, v.expectedPSP, t) if v.shouldPassAdmit { - safeSysctls, unsafeSysctls, _ := helper.SysctlsFromPodAnnotations(v.pod.Annotations) - if !reflect.DeepEqual(safeSysctls, origSafeSysctls) { - t.Errorf("%s: wrong safe sysctls: expected=%v, got=%v", k, origSafeSysctls, safeSysctls) - } - if !reflect.DeepEqual(unsafeSysctls, origUnsafeSysctls) { - t.Errorf("%s: wrong unsafe sysctls: expected=%v, got=%v", k, origSafeSysctls, safeSysctls) + if !reflect.DeepEqual(v.pod.Spec.SecurityContext.Sysctls, origSysctl) { + t.Errorf("%s: wrong sysctls: expected=%v, got=%v", k, origSysctl, v.pod.Spec.SecurityContext.Sysctls) } } } } -func testPSPAdmit(testCaseName string, psps []*extensions.PodSecurityPolicy, pod *kapi.Pod, shouldPassAdmit, shouldPassValidate bool, expectedPSP string, t *testing.T) { +func testPSPAdmit(testCaseName string, psps []*policy.PodSecurityPolicy, pod *kapi.Pod, shouldPassAdmit, shouldPassValidate bool, expectedPSP string, t *testing.T) { testPSPAdmitAdvanced(testCaseName, kadmission.Create, psps, nil, &user.DefaultInfo{}, pod, nil, shouldPassAdmit, shouldPassValidate, true, expectedPSP, t) } -func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []*extensions.PodSecurityPolicy, authz authorizer.Authorizer, userInfo user.Info, pod, oldPod *kapi.Pod, shouldPassAdmit, shouldPassValidate bool, canMutate bool, expectedPSP string, t *testing.T) { +// fakeAttributes decorate kadmission.Attributes. It's used to trace the added annotations. +type fakeAttributes struct { + kadmission.Attributes + annotations map[string]string +} + +func (f fakeAttributes) AddAnnotation(k, v string) error { + f.annotations[k] = v + return f.Attributes.AddAnnotation(k, v) +} + +func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []*policy.PodSecurityPolicy, authz authorizer.Authorizer, userInfo user.Info, pod, oldPod *kapi.Pod, shouldPassAdmit, shouldPassValidate bool, canMutate bool, expectedPSP string, t *testing.T) { originalPod := pod.DeepCopy() plugin := NewTestAdmission(psps, authz) attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, userInfo) + annotations := make(map[string]string) + attrs = &fakeAttributes{attrs, annotations} err := plugin.Admit(attrs) if shouldPassAdmit && err != nil { @@ -1832,11 +1801,27 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []* } err = plugin.Validate(attrs) + psp := "" + if shouldPassAdmit && op == kadmission.Create { + psp = expectedPSP + } + validateAuditAnnotation(t, testCaseName, annotations, "podsecuritypolicy.policy.k8s.io/admit-policy", psp) if shouldPassValidate && err != nil { t.Errorf("%s: expected no errors on Validate but received %v", testCaseName, err) } else if !shouldPassValidate && err == nil { t.Errorf("%s: expected errors on Validate but received none", testCaseName) } + if shouldPassValidate { + validateAuditAnnotation(t, testCaseName, annotations, "podsecuritypolicy.policy.k8s.io/validate-policy", expectedPSP) + } else { + validateAuditAnnotation(t, testCaseName, annotations, "podsecuritypolicy.policy.k8s.io/validate-policy", "") + } +} + +func validateAuditAnnotation(t *testing.T, testCaseName string, annotations map[string]string, key, value string) { + if annotations[key] != value { + t.Errorf("%s: expected to have annotations[%s] set to %q, got %q", testCaseName, key, value, annotations[key]) + } } func TestAssignSecurityContext(t *testing.T) { @@ -1906,55 +1891,55 @@ func TestAssignSecurityContext(t *testing.T) { func TestCreateProvidersFromConstraints(t *testing.T) { testCases := map[string]struct { // use a generating function so we can test for non-mutation - psp func() *extensions.PodSecurityPolicy + psp func() *policy.PodSecurityPolicy expectedErr string }{ "valid psp": { - psp: func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ + psp: func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "valid psp", }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } }, }, "bad psp strategy options": { - psp: func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ + psp: func() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "bad psp user options", }, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + Spec: policy.PodSecurityPolicySpec{ + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyMustRunAs, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyMustRunAs, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } }, - expectedErr: "MustRunAsRange requires at least one range", + expectedErr: "MustRunAs requires at least one range", }, } @@ -1965,7 +1950,7 @@ func TestCreateProvidersFromConstraints(t *testing.T) { } psp := v.psp() - _, errs := admit.createProvidersFromPolicies([]*extensions.PodSecurityPolicy{psp}, "namespace") + _, errs := admit.createProvidersFromPolicies([]*policy.PodSecurityPolicy{psp}, "namespace") if !reflect.DeepEqual(psp, v.psp()) { diff := diff.ObjectDiff(psp, v.psp()) @@ -1990,7 +1975,7 @@ func TestCreateProvidersFromConstraints(t *testing.T) { } func TestPolicyAuthorization(t *testing.T) { - policyWithName := func(name string) *extensions.PodSecurityPolicy { + policyWithName := func(name string) *policy.PodSecurityPolicy { p := permissivePSP() p.Name = name return p @@ -2001,7 +1986,7 @@ func TestPolicyAuthorization(t *testing.T) { sa string ns string expectedPolicy string - inPolicies []*extensions.PodSecurityPolicy + inPolicies []*policy.PodSecurityPolicy allowed map[string]map[string]map[string]bool allowedGroup string }{ @@ -2014,7 +1999,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "policy", }, "policy allowed by sa (extensions API Group)": { @@ -2026,7 +2011,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "policy", }, "policy allowed by user (policy API Group)": { @@ -2038,7 +2023,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "policy", allowedGroup: policy.GroupName, }, @@ -2051,7 +2036,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "policy", allowedGroup: policy.GroupName, }, @@ -2060,7 +2045,7 @@ func TestPolicyAuthorization(t *testing.T) { sa: "sa", ns: "test", allowed: map[string]map[string]map[string]bool{}, - inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")}, + inPolicies: []*policy.PodSecurityPolicy{policyWithName("policy")}, expectedPolicy: "", }, "multiple policies allowed": { @@ -2079,7 +2064,7 @@ func TestPolicyAuthorization(t *testing.T) { "other": {"policy7": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ // Prefix to force checking these policies first. policyWithName("a_policy1"), // not allowed in this namespace policyWithName("a_policy2"), // not allowed in this namespace @@ -2103,7 +2088,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), policyWithName("policy3"), @@ -2123,7 +2108,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), policyWithName("policy3"), @@ -2143,7 +2128,7 @@ func TestPolicyAuthorization(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), policyWithName("policy3"), @@ -2168,7 +2153,7 @@ func TestPolicyAuthorization(t *testing.T) { } func TestPolicyAuthorizationErrors(t *testing.T) { - policyWithName := func(name string) *extensions.PodSecurityPolicy { + policyWithName := func(name string) *policy.PodSecurityPolicy { p := restrictivePSP() p.Name = name return p @@ -2181,13 +2166,13 @@ func TestPolicyAuthorizationErrors(t *testing.T) { ) tests := map[string]struct { - inPolicies []*extensions.PodSecurityPolicy + inPolicies []*policy.PodSecurityPolicy allowed map[string]map[string]map[string]bool expectValidationErrs int }{ "policies not allowed": { allowed: map[string]map[string]map[string]bool{}, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), }, @@ -2199,7 +2184,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) { "test": {"policy1": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), }, @@ -2211,7 +2196,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), }, @@ -2226,7 +2211,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) { "test": {"policy2": true}, }, }, - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ policyWithName("policy1"), policyWithName("policy2"), }, @@ -2235,14 +2220,11 @@ func TestPolicyAuthorizationErrors(t *testing.T) { } for desc, tc := range tests { t.Run(desc, func(t *testing.T) { - var ( - authz = &TestAuthorizer{usernameToNamespaceToAllowedPSPs: tc.allowed} - privileged = true - ) + authz := &TestAuthorizer{usernameToNamespaceToAllowedPSPs: tc.allowed} pod := goodPod() pod.Namespace = ns pod.Spec.ServiceAccountName = sa - pod.Spec.Containers[0].SecurityContext.Privileged = &privileged + pod.Spec.SecurityContext.HostPID = true plugin := NewTestAdmission(tc.inPolicies, authz) attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), ns, "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &user.DefaultInfo{Name: userName}) @@ -2256,26 +2238,26 @@ func TestPolicyAuthorizationErrors(t *testing.T) { } func TestPreferValidatedPSP(t *testing.T) { - restrictivePSPWithName := func(name string) *extensions.PodSecurityPolicy { + restrictivePSPWithName := func(name string) *policy.PodSecurityPolicy { p := restrictivePSP() p.Name = name return p } - permissivePSPWithName := func(name string) *extensions.PodSecurityPolicy { + permissivePSPWithName := func(name string) *policy.PodSecurityPolicy { p := permissivePSP() p.Name = name return p } tests := map[string]struct { - inPolicies []*extensions.PodSecurityPolicy + inPolicies []*policy.PodSecurityPolicy expectValidationErrs int validatedPSPHint string expectedPSP string }{ "no policy saved in annotations, PSPs are ordered lexicographically": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), permissivePSPWithName("002permissive"), @@ -2287,7 +2269,7 @@ func TestPreferValidatedPSP(t *testing.T) { expectedPSP: "001permissive", }, "policy saved in annotations is preferred": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), permissivePSPWithName("001permissive"), @@ -2299,7 +2281,7 @@ func TestPreferValidatedPSP(t *testing.T) { expectedPSP: "002permissive", }, "policy saved in annotations is invalid": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), }, @@ -2308,7 +2290,7 @@ func TestPreferValidatedPSP(t *testing.T) { expectedPSP: "", }, "policy saved in annotations is disallowed anymore": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), }, @@ -2317,7 +2299,7 @@ func TestPreferValidatedPSP(t *testing.T) { expectedPSP: "", }, "policy saved in annotations is disallowed anymore, but find another one": { - inPolicies: []*extensions.PodSecurityPolicy{ + inPolicies: []*policy.PodSecurityPolicy{ restrictivePSPWithName("001restrictive"), restrictivePSPWithName("002restrictive"), permissivePSPWithName("002permissive"), @@ -2343,39 +2325,39 @@ func TestPreferValidatedPSP(t *testing.T) { _, pspName, validationErrs, err := plugin.computeSecurityContext(attrs, pod, false, tc.validatedPSPHint) assert.NoError(t, err) assert.Len(t, validationErrs, tc.expectValidationErrs) - assert.Equal(t, pspName, tc.expectedPSP) + assert.Equal(t, tc.expectedPSP, pspName) }) } } -func restrictivePSP() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ +func restrictivePSP() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "restrictive", Annotations: map[string]string{}, }, - Spec: extensions.PodSecurityPolicySpec{ - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyMustRunAs, - Ranges: []extensions.UserIDRange{ + Spec: policy.PodSecurityPolicySpec{ + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyMustRunAs, + Ranges: []policy.IDRange{ {Min: int64(999), Max: int64(999)}, }, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyMustRunAs, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyMustRunAs, SELinuxOptions: &kapi.SELinuxOptions{ Level: "s9:z0,z1", }, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyMustRunAs, + Ranges: []policy.IDRange{ {Min: int64(999), Max: int64(999)}, }, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyMustRunAs, - Ranges: []extensions.GroupIDRange{ + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyMustRunAs, + Ranges: []policy.IDRange{ {Min: int64(999), Max: int64(999)}, }, }, @@ -2383,31 +2365,31 @@ func restrictivePSP() *extensions.PodSecurityPolicy { } } -func permissivePSP() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ +func permissivePSP() *policy.PodSecurityPolicy { + return &policy.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "privileged", Annotations: map[string]string{}, }, - Spec: extensions.PodSecurityPolicySpec{ + Spec: policy.PodSecurityPolicySpec{ AllowPrivilegeEscalation: true, HostIPC: true, HostNetwork: true, HostPID: true, - HostPorts: []extensions.HostPortRange{{Min: 0, Max: 65536}}, - Volumes: []extensions.FSType{extensions.All}, - AllowedCapabilities: []kapi.Capability{extensions.AllowAllCapabilities}, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, + HostPorts: []policy.HostPortRange{{Min: 0, Max: 65536}}, + Volumes: []policy.FSType{policy.All}, + AllowedCapabilities: []kapi.Capability{policy.AllowAllCapabilities}, + RunAsUser: policy.RunAsUserStrategyOptions{ + Rule: policy.RunAsUserStrategyRunAsAny, }, - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, + SELinux: policy.SELinuxStrategyOptions{ + Rule: policy.SELinuxStrategyRunAsAny, }, - FSGroup: extensions.FSGroupStrategyOptions{ - Rule: extensions.FSGroupStrategyRunAsAny, + FSGroup: policy.FSGroupStrategyOptions{ + Rule: policy.FSGroupStrategyRunAsAny, }, - SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ - Rule: extensions.SupplementalGroupsStrategyRunAsAny, + SupplementalGroups: policy.SupplementalGroupsStrategyOptions{ + Rule: policy.SupplementalGroupsStrategyRunAsAny, }, }, } @@ -2435,13 +2417,3 @@ func goodPod() *kapi.Pod { }, } } - -func userIDPtr(i int) *int64 { - userID := int64(i) - return &userID -} - -func groupIDPtr(i int) *int64 { - groupID := int64(i) - return &groupID -} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/OWNERS b/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/OWNERS index a678215e9..af89d3e6d 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/OWNERS +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/OWNERS @@ -1,7 +1,9 @@ approvers: - liggitt - deads2k +- mikedanese reviewers: - liggitt - deads2k +- mikedanese - enj diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/admission.go index 6e245ecf8..7a831a295 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/admission.go @@ -208,6 +208,15 @@ func (s *serviceAccount) Validate(a admission.Attributes) (err error) { if hasSecrets { return admission.NewForbidden(a, fmt.Errorf("a mirror pod may not reference secrets")) } + for _, v := range pod.Spec.Volumes { + if proj := v.Projected; proj != nil { + for _, projSource := range proj.Sources { + if projSource.ServiceAccountToken != nil { + return admission.NewForbidden(a, fmt.Errorf("a mirror pod may not use ServiceAccountToken volume projections")) + } + } + } + } return nil } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/admission_test.go index d51677186..18ed0ee9e 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/admission_test.go @@ -138,6 +138,31 @@ func TestRejectsMirrorPodWithSecretVolumes(t *testing.T) { } } +func TestRejectsMirrorPodWithServiceAccountTokenVolumeProjections(t *testing.T) { + pod := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + kubelet.ConfigMirrorAnnotationKey: "true", + }, + }, + Spec: api.PodSpec{ + Volumes: []api.Volume{ + {VolumeSource: api.VolumeSource{ + Projected: &api.ProjectedVolumeSource{ + Sources: []api.VolumeProjection{{ServiceAccountToken: &api.ServiceAccountTokenProjection{}}}, + }, + }, + }, + }, + }, + } + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, nil) + err := NewServiceAccount().Admit(attrs) + if err == nil { + t.Errorf("Expected a mirror pod to be prevented from referencing a ServiceAccountToken volume projection") + } +} + func TestAssignsDefaultServiceAccountAndToleratesMissingAPIToken(t *testing.T) { ns := "myns" diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/BUILD new file mode 100644 index 000000000..d38633056 --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/BUILD @@ -0,0 +1,54 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "admission.go", + "doc.go", + ], + importpath = "k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label", + deps = [ + "//pkg/apis/core:go_default_library", + "//pkg/cloudprovider:go_default_library", + "//pkg/cloudprovider/providers/aws:go_default_library", + "//pkg/cloudprovider/providers/gce:go_default_library", + "//pkg/kubeapiserver/admission:go_default_library", + "//pkg/kubelet/apis:go_default_library", + "//pkg/volume:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["admission_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/apis/core:go_default_library", + "//pkg/cloudprovider/providers/aws: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/types:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/admission.go new file mode 100644 index 000000000..19fc962ca --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/admission.go @@ -0,0 +1,221 @@ +/* +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 label + +import ( + "bytes" + "fmt" + "io" + "sync" + + "github.com/golang/glog" + "k8s.io/apiserver/pkg/admission" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" + kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" + kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + vol "k8s.io/kubernetes/pkg/volume" +) + +const ( + // PluginName is the name of persistent volume label admission plugin + PluginName = "PersistentVolumeLabel" +) + +// Register registers a plugin +func Register(plugins *admission.Plugins) { + plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { + persistentVolumeLabelAdmission := newPersistentVolumeLabel() + return persistentVolumeLabelAdmission, nil + }) +} + +var _ = admission.Interface(&persistentVolumeLabel{}) + +type persistentVolumeLabel struct { + *admission.Handler + + mutex sync.Mutex + ebsVolumes aws.Volumes + cloudConfig []byte + gceCloudProvider *gce.GCECloud +} + +var _ admission.MutationInterface = &persistentVolumeLabel{} +var _ kubeapiserveradmission.WantsCloudConfig = &persistentVolumeLabel{} + +// newPersistentVolumeLabel returns an admission.Interface implementation which adds labels to PersistentVolume CREATE requests, +// based on the labels provided by the underlying cloud provider. +// +// As a side effect, the cloud provider may block invalid or non-existent volumes. +func newPersistentVolumeLabel() *persistentVolumeLabel { + // DEPRECATED: cloud-controller-manager will now start NewPersistentVolumeLabelController + // which does exactly what this admission controller used to do. So once GCE and AWS can + // run externally, we can remove this admission controller. + glog.Warning("PersistentVolumeLabel admission controller is deprecated. " + + "Please remove this controller from your configuration files and scripts.") + return &persistentVolumeLabel{ + Handler: admission.NewHandler(admission.Create), + } +} + +func (l *persistentVolumeLabel) SetCloudConfig(cloudConfig []byte) { + l.cloudConfig = cloudConfig +} + +func (l *persistentVolumeLabel) Admit(a admission.Attributes) (err error) { + if a.GetResource().GroupResource() != api.Resource("persistentvolumes") { + return nil + } + obj := a.GetObject() + if obj == nil { + return nil + } + volume, ok := obj.(*api.PersistentVolume) + if !ok { + return nil + } + + var volumeLabels map[string]string + if volume.Spec.AWSElasticBlockStore != nil { + labels, err := l.findAWSEBSLabels(volume) + if err != nil { + return admission.NewForbidden(a, fmt.Errorf("error querying AWS EBS volume %s: %v", volume.Spec.AWSElasticBlockStore.VolumeID, err)) + } + volumeLabels = labels + } + if volume.Spec.GCEPersistentDisk != nil { + labels, err := l.findGCEPDLabels(volume) + if err != nil { + return admission.NewForbidden(a, fmt.Errorf("error querying GCE PD volume %s: %v", volume.Spec.GCEPersistentDisk.PDName, err)) + } + volumeLabels = labels + } + + if len(volumeLabels) != 0 { + if volume.Labels == nil { + volume.Labels = make(map[string]string) + } + for k, v := range volumeLabels { + // We (silently) replace labels if they are provided. + // This should be OK because they are in the kubernetes.io namespace + // i.e. we own them + volume.Labels[k] = v + } + } + + return nil +} + +func (l *persistentVolumeLabel) findAWSEBSLabels(volume *api.PersistentVolume) (map[string]string, error) { + // Ignore any volumes that are being provisioned + if volume.Spec.AWSElasticBlockStore.VolumeID == vol.ProvisionedVolumeName { + return nil, nil + } + ebsVolumes, err := l.getEBSVolumes() + if err != nil { + return nil, err + } + if ebsVolumes == nil { + return nil, fmt.Errorf("unable to build AWS cloud provider for EBS") + } + + // TODO: GetVolumeLabels is actually a method on the Volumes interface + // If that gets standardized we can refactor to reduce code duplication + spec := aws.KubernetesVolumeID(volume.Spec.AWSElasticBlockStore.VolumeID) + labels, err := ebsVolumes.GetVolumeLabels(spec) + if err != nil { + return nil, err + } + + return labels, nil +} + +// getEBSVolumes returns the AWS Volumes interface for ebs +func (l *persistentVolumeLabel) getEBSVolumes() (aws.Volumes, error) { + l.mutex.Lock() + defer l.mutex.Unlock() + + if l.ebsVolumes == nil { + var cloudConfigReader io.Reader + if len(l.cloudConfig) > 0 { + cloudConfigReader = bytes.NewReader(l.cloudConfig) + } + cloudProvider, err := cloudprovider.GetCloudProvider("aws", cloudConfigReader) + if err != nil || cloudProvider == nil { + return nil, err + } + awsCloudProvider, ok := cloudProvider.(*aws.Cloud) + if !ok { + // GetCloudProvider has gone very wrong + return nil, fmt.Errorf("error retrieving AWS cloud provider") + } + l.ebsVolumes = awsCloudProvider + } + return l.ebsVolumes, nil +} + +func (l *persistentVolumeLabel) findGCEPDLabels(volume *api.PersistentVolume) (map[string]string, error) { + // Ignore any volumes that are being provisioned + if volume.Spec.GCEPersistentDisk.PDName == vol.ProvisionedVolumeName { + return nil, nil + } + + provider, err := l.getGCECloudProvider() + if err != nil { + return nil, err + } + if provider == nil { + return nil, fmt.Errorf("unable to build GCE cloud provider for PD") + } + + // If the zone is already labeled, honor the hint + zone := volume.Labels[kubeletapis.LabelZoneFailureDomain] + + labels, err := provider.GetAutoLabelsForPD(volume.Spec.GCEPersistentDisk.PDName, zone) + if err != nil { + return nil, err + } + + return labels, nil +} + +// getGCECloudProvider returns the GCE cloud provider, for use for querying volume labels +func (l *persistentVolumeLabel) getGCECloudProvider() (*gce.GCECloud, error) { + l.mutex.Lock() + defer l.mutex.Unlock() + + if l.gceCloudProvider == nil { + var cloudConfigReader io.Reader + if len(l.cloudConfig) > 0 { + cloudConfigReader = bytes.NewReader(l.cloudConfig) + } + cloudProvider, err := cloudprovider.GetCloudProvider("gce", cloudConfigReader) + if err != nil || cloudProvider == nil { + return nil, err + } + gceCloudProvider, ok := cloudProvider.(*gce.GCECloud) + if !ok { + // GetCloudProvider has gone very wrong + return nil, fmt.Errorf("error retrieving GCE cloud provider") + } + l.gceCloudProvider = gceCloudProvider + } + return l.gceCloudProvider, nil +} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go new file mode 100644 index 000000000..f04939152 --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go @@ -0,0 +1,176 @@ +/* +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 label + +import ( + "testing" + + "fmt" + + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apiserver/pkg/admission" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" +) + +type mockVolumes struct { + volumeLabels map[string]string + volumeLabelsError error +} + +var _ aws.Volumes = &mockVolumes{} + +func (v *mockVolumes) AttachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName) (string, error) { + return "", fmt.Errorf("not implemented") +} + +func (v *mockVolumes) DetachDisk(diskName aws.KubernetesVolumeID, nodeName types.NodeName) (string, error) { + return "", fmt.Errorf("not implemented") +} + +func (v *mockVolumes) CreateDisk(volumeOptions *aws.VolumeOptions) (volumeName aws.KubernetesVolumeID, err error) { + return "", fmt.Errorf("not implemented") +} + +func (v *mockVolumes) DeleteDisk(volumeName aws.KubernetesVolumeID) (bool, error) { + return false, fmt.Errorf("not implemented") +} + +func (v *mockVolumes) GetVolumeLabels(volumeName aws.KubernetesVolumeID) (map[string]string, error) { + return v.volumeLabels, v.volumeLabelsError +} + +func (v *mockVolumes) GetDiskPath(volumeName aws.KubernetesVolumeID) (string, error) { + return "", fmt.Errorf("not implemented") +} + +func (v *mockVolumes) DiskIsAttached(volumeName aws.KubernetesVolumeID, nodeName types.NodeName) (bool, error) { + return false, fmt.Errorf("not implemented") +} + +func (v *mockVolumes) DisksAreAttached(nodeDisks map[types.NodeName][]aws.KubernetesVolumeID) (map[types.NodeName]map[aws.KubernetesVolumeID]bool, error) { + return nil, fmt.Errorf("not implemented") +} + +func (v *mockVolumes) ResizeDisk( + diskName aws.KubernetesVolumeID, + oldSize resource.Quantity, + newSize resource.Quantity) (resource.Quantity, error) { + return oldSize, nil +} + +func mockVolumeFailure(err error) *mockVolumes { + return &mockVolumes{volumeLabelsError: err} +} + +func mockVolumeLabels(labels map[string]string) *mockVolumes { + return &mockVolumes{volumeLabels: labels} +} + +// TestAdmission +func TestAdmission(t *testing.T) { + pvHandler := newPersistentVolumeLabel() + handler := admission.NewChainHandler(pvHandler) + ignoredPV := api.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{Name: "noncloud", Namespace: "myns"}, + Spec: api.PersistentVolumeSpec{ + PersistentVolumeSource: api.PersistentVolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/", + }, + }, + }, + } + awsPV := api.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{Name: "noncloud", Namespace: "myns"}, + Spec: api.PersistentVolumeSpec{ + PersistentVolumeSource: api.PersistentVolumeSource{ + AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{ + VolumeID: "123", + }, + }, + }, + } + + // Non-cloud PVs are ignored + err := handler.Admit(admission.NewAttributesRecord(&ignoredPV, nil, api.Kind("PersistentVolume").WithVersion("version"), ignoredPV.Namespace, ignoredPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) + if err != nil { + t.Errorf("Unexpected error returned from admission handler (on ignored pv): %v", err) + } + + // We only add labels on creation + err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Delete, nil)) + if err != nil { + t.Errorf("Unexpected error returned from admission handler (when deleting aws pv): %v", err) + } + + // Errors from the cloudprovider block creation of the volume + pvHandler.ebsVolumes = mockVolumeFailure(fmt.Errorf("invalid volume")) + err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) + if err == nil { + t.Errorf("Expected error when aws pv info fails") + } + + // Don't add labels if the cloudprovider doesn't return any + labels := make(map[string]string) + pvHandler.ebsVolumes = mockVolumeLabels(labels) + err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) + if err != nil { + t.Errorf("Expected no error when creating aws pv") + } + if len(awsPV.ObjectMeta.Labels) != 0 { + t.Errorf("Unexpected number of labels") + } + + // Don't panic if the cloudprovider returns nil, nil + pvHandler.ebsVolumes = mockVolumeFailure(nil) + err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) + if err != nil { + t.Errorf("Expected no error when cloud provider returns empty labels") + } + + // Labels from the cloudprovider should be applied to the volume + labels = make(map[string]string) + labels["a"] = "1" + labels["b"] = "2" + pvHandler.ebsVolumes = mockVolumeLabels(labels) + err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) + if err != nil { + t.Errorf("Expected no error when creating aws pv") + } + if awsPV.Labels["a"] != "1" || awsPV.Labels["b"] != "2" { + t.Errorf("Expected label a to be added when creating aws pv") + } + + // User-provided labels should be honored, but cloudprovider labels replace them when they overlap + awsPV.ObjectMeta.Labels = make(map[string]string) + awsPV.ObjectMeta.Labels["a"] = "not1" + awsPV.ObjectMeta.Labels["c"] = "3" + err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) + if err != nil { + t.Errorf("Expected no error when creating aws pv") + } + if awsPV.Labels["a"] != "1" || awsPV.Labels["b"] != "2" { + t.Errorf("Expected cloudprovider labels to replace user labels when creating aws pv") + } + if awsPV.Labels["c"] != "3" { + t.Errorf("Expected (non-conflicting) user provided labels to be honored when creating aws pv") + } + +} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/doc.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/doc.go new file mode 100644 index 000000000..56d4e627f --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label/doc.go @@ -0,0 +1,19 @@ +/* +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 label created persistent volumes with zone information +// as provided by the cloud provider +package label // import "k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/label" diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize/BUILD new file mode 100644 index 000000000..444764320 --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize/BUILD @@ -0,0 +1,52 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_test( + name = "go_default_test", + srcs = ["admission_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/apis/core:go_default_library", + "//pkg/apis/storage:go_default_library", + "//pkg/client/informers/informers_generated/internalversion:go_default_library", + "//pkg/controller: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/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", + ], +) + +go_library( + name = "go_default_library", + srcs = ["admission.go"], + importpath = "k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize", + deps = [ + "//pkg/apis/core:go_default_library", + "//pkg/apis/core/helper:go_default_library", + "//pkg/client/informers/informers_generated/internalversion:go_default_library", + "//pkg/client/listers/core/internalversion:go_default_library", + "//pkg/client/listers/storage/internalversion:go_default_library", + "//pkg/kubeapiserver/admission:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize/admission.go new file mode 100644 index 000000000..389e39395 --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize/admission.go @@ -0,0 +1,172 @@ +/* +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 resize + +import ( + "fmt" + "io" + + "k8s.io/apiserver/pkg/admission" + api "k8s.io/kubernetes/pkg/apis/core" + apihelper "k8s.io/kubernetes/pkg/apis/core/helper" + informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" + pvlister "k8s.io/kubernetes/pkg/client/listers/core/internalversion" + storagelisters "k8s.io/kubernetes/pkg/client/listers/storage/internalversion" + kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" +) + +const ( + // PluginName is the name of pvc resize admission plugin + PluginName = "PersistentVolumeClaimResize" +) + +// Register registers a plugin +func Register(plugins *admission.Plugins) { + plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { + plugin := newPlugin() + return plugin, nil + }) +} + +var _ admission.Interface = &persistentVolumeClaimResize{} +var _ admission.ValidationInterface = &persistentVolumeClaimResize{} +var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&persistentVolumeClaimResize{}) + +type persistentVolumeClaimResize struct { + *admission.Handler + + pvLister pvlister.PersistentVolumeLister + scLister storagelisters.StorageClassLister +} + +func newPlugin() *persistentVolumeClaimResize { + return &persistentVolumeClaimResize{ + Handler: admission.NewHandler(admission.Update), + } +} + +func (pvcr *persistentVolumeClaimResize) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) { + pvcInformer := f.Core().InternalVersion().PersistentVolumes() + pvcr.pvLister = pvcInformer.Lister() + scInformer := f.Storage().InternalVersion().StorageClasses() + pvcr.scLister = scInformer.Lister() + pvcr.SetReadyFunc(func() bool { + return pvcInformer.Informer().HasSynced() && scInformer.Informer().HasSynced() + }) +} + +// ValidateInitialization ensures lister is set. +func (pvcr *persistentVolumeClaimResize) ValidateInitialization() error { + if pvcr.pvLister == nil { + return fmt.Errorf("missing persistent volume lister") + } + if pvcr.scLister == nil { + return fmt.Errorf("missing storageclass lister") + } + return nil +} + +func (pvcr *persistentVolumeClaimResize) Validate(a admission.Attributes) error { + if a.GetResource().GroupResource() != api.Resource("persistentvolumeclaims") { + return nil + } + + if len(a.GetSubresource()) != 0 { + return nil + } + + pvc, ok := a.GetObject().(*api.PersistentVolumeClaim) + // if we can't convert then we don't handle this object so just return + if !ok { + return nil + } + oldPvc, ok := a.GetOldObject().(*api.PersistentVolumeClaim) + if !ok { + return nil + } + + oldSize := oldPvc.Spec.Resources.Requests[api.ResourceStorage] + newSize := pvc.Spec.Resources.Requests[api.ResourceStorage] + + if newSize.Cmp(oldSize) <= 0 { + return nil + } + + if oldPvc.Status.Phase != api.ClaimBound { + return admission.NewForbidden(a, fmt.Errorf("Only bound persistent volume claims can be expanded")) + } + + // Growing Persistent volumes is only allowed for PVCs for which their StorageClass + // explicitly allows it + if !pvcr.allowResize(pvc, oldPvc) { + return admission.NewForbidden(a, fmt.Errorf("only dynamically provisioned pvc can be resized and "+ + "the storageclass that provisions the pvc must support resize")) + } + + // volume plugin must support resize + pv, err := pvcr.pvLister.Get(pvc.Spec.VolumeName) + if err != nil { + return admission.NewForbidden(a, fmt.Errorf("Error updating persistent volume claim because fetching associated persistent volume failed")) + } + + if !pvcr.checkVolumePlugin(pv) { + return admission.NewForbidden(a, fmt.Errorf("volume plugin does not support resize")) + } + return nil +} + +// Growing Persistent volumes is only allowed for PVCs for which their StorageClass +// explicitly allows it. +func (pvcr *persistentVolumeClaimResize) allowResize(pvc, oldPvc *api.PersistentVolumeClaim) bool { + pvcStorageClass := apihelper.GetPersistentVolumeClaimClass(pvc) + oldPvcStorageClass := apihelper.GetPersistentVolumeClaimClass(oldPvc) + if pvcStorageClass == "" || oldPvcStorageClass == "" || pvcStorageClass != oldPvcStorageClass { + return false + } + sc, err := pvcr.scLister.Get(pvcStorageClass) + if err != nil { + return false + } + if sc.AllowVolumeExpansion != nil { + return *sc.AllowVolumeExpansion + } + return false +} + +// checkVolumePlugin checks whether the volume plugin supports resize +func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVolume) bool { + if pv.Spec.Glusterfs != nil || pv.Spec.Cinder != nil || pv.Spec.RBD != nil || pv.Spec.PortworxVolume != nil { + return true + } + + if pv.Spec.GCEPersistentDisk != nil { + return true + } + + if pv.Spec.AWSElasticBlockStore != nil { + return true + } + + if pv.Spec.AzureFile != nil { + return true + } + + if pv.Spec.AzureDisk != nil { + return true + } + return false +} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go similarity index 100% rename from vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/admission_test.go rename to vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/persistentvolume/resize/admission_test.go diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/OWNERS b/vendor/k8s.io/kubernetes/plugin/pkg/auth/OWNERS index 3d732d11f..84fd5cc07 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/OWNERS +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/OWNERS @@ -2,9 +2,11 @@ approvers: - erictune - liggitt - deads2k +- mikedanese reviewers: - erictune - liggitt - deads2k - ericchiang - enj +- mikedanese diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go index a0a615886..bc00833d8 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go @@ -152,13 +152,12 @@ func (t *TokenAuthenticator) AuthenticateToken(token string) (user.Info, bool, e // Copied from k8s.io/client-go/tools/bootstrap/token/api func getSecretString(secret *api.Secret, key string) string { - if secret.Data == nil { + data, ok := secret.Data[key] + if !ok { return "" } - if val, ok := secret.Data[key]; ok { - return string(val) - } - return "" + + return string(data) } // Copied from k8s.io/client-go/tools/bootstrap/token/api @@ -167,11 +166,13 @@ func isSecretExpired(secret *api.Secret) bool { if len(expiration) > 0 { expTime, err2 := time.Parse(time.RFC3339, expiration) if err2 != nil { - tokenErrorf(secret, "has unparsable expiration time (%s). Treating as expired.", expiration) + glog.V(3).Infof("Unparseable expiration time (%s) in %s/%s Secret: %v. Treating as expired.", + expiration, secret.Namespace, secret.Name, err2) return true } if time.Now().After(expTime) { - tokenErrorf(secret, "has expired.", expiration) + glog.V(3).Infof("Expired bootstrap token in %s/%s Secret: %v", + secret.Namespace, secret.Name, expiration) return true } } @@ -181,8 +182,10 @@ func isSecretExpired(secret *api.Secret) bool { // Copied from kubernetes/cmd/kubeadm/app/util/token var ( + // tokenRegexpString defines id.secret regular expression pattern tokenRegexpString = "^([a-z0-9]{6})\\.([a-z0-9]{16})$" - tokenRegexp = regexp.MustCompile(tokenRegexpString) + // tokenRegexp is a compiled regular expression of TokenRegexpString + tokenRegexp = regexp.MustCompile(tokenRegexpString) ) // parseToken tries and parse a valid token from a string. diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/BUILD index 37d0db0b0..5d73814ef 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/BUILD @@ -8,15 +8,21 @@ load( go_test( name = "go_default_test", - srcs = ["node_authorizer_test.go"], + srcs = [ + "graph_test.go", + "intset_test.go", + "node_authorizer_test.go", + ], embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", "//pkg/auth/nodeidentifier:go_default_library", "//pkg/features:go_default_library", "//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/storage/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", @@ -28,6 +34,7 @@ go_library( srcs = [ "graph.go", "graph_populator.go", + "intset.go", "node_authorizer.go", ], importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/node", @@ -35,7 +42,6 @@ go_library( "//pkg/api/persistentvolume:go_default_library", "//pkg/api/pod:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/rbac:go_default_library", "//pkg/apis/storage:go_default_library", "//pkg/auth/nodeidentifier:go_default_library", "//pkg/client/informers/informers_generated/internalversion/core/internalversion:go_default_library", @@ -45,6 +51,7 @@ go_library( "//third_party/forked/gonum/graph/simple:go_default_library", "//third_party/forked/gonum/graph/traverse:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/api/storage/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph.go index 38fea6d03..5781b56b0 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph.go @@ -80,6 +80,11 @@ type Graph struct { graph *simple.DirectedAcyclicGraph // vertices is a map of type -> namespace -> name -> vertex vertices map[vertexType]namespaceVertexMapping + + // destinationEdgeIndex is a map of vertex -> set of destination IDs + destinationEdgeIndex map[int]*intSet + // destinationEdgeThreshold is the minimum number of distinct destination IDs at which to maintain an index + destinationEdgeThreshold int } // namespaceVertexMapping is a map of namespace -> name -> vertex @@ -92,6 +97,11 @@ func NewGraph() *Graph { return &Graph{ vertices: map[vertexType]namespaceVertexMapping{}, graph: simple.NewDirectedAcyclicGraph(0, 0), + + destinationEdgeIndex: map[int]*intSet{}, + // experimentally determined to be the point at which iteration adds an order of magnitude to the authz check. + // since maintaining indexes costs time/memory while processing graph changes, we don't want to make this too low. + destinationEdgeThreshold: 200, } } @@ -165,6 +175,7 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin // find existing neighbors with a single edge (meaning we are their only neighbor) neighborsToRemove := []graph.Node{} + neighborsToRecompute := []graph.Node{} g.graph.VisitFrom(vertex, func(neighbor graph.Node) bool { // this downstream neighbor has only one edge (which must be from us), so remove them as well if g.graph.Degree(neighbor) == 1 { @@ -173,28 +184,115 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin return true }) g.graph.VisitTo(vertex, func(neighbor graph.Node) bool { - // this upstream neighbor has only one edge (which must be to us), so remove them as well if g.graph.Degree(neighbor) == 1 { + // this upstream neighbor has only one edge (which must be to us), so remove them as well neighborsToRemove = append(neighborsToRemove, neighbor) + } else { + // recompute the destination edge index on this neighbor + neighborsToRecompute = append(neighborsToRemove, neighbor) } return true }) // remove the vertex - g.graph.RemoveNode(vertex) - delete(g.vertices[vertexType][namespace], name) - if len(g.vertices[vertexType][namespace]) == 0 { - delete(g.vertices[vertexType], namespace) - } + g.removeVertex_locked(vertex) // remove neighbors that are now edgeless for _, neighbor := range neighborsToRemove { - g.graph.RemoveNode(neighbor) - n := neighbor.(*namedVertex) - delete(g.vertices[n.vertexType][n.namespace], n.name) - if len(g.vertices[n.vertexType][n.namespace]) == 0 { - delete(g.vertices[n.vertexType], n.namespace) + g.removeVertex_locked(neighbor.(*namedVertex)) + } + + // recompute destination indexes for neighbors that dropped outbound edges + for _, neighbor := range neighborsToRecompute { + g.recomputeDestinationIndex_locked(neighbor) + } +} + +// must be called under write lock +// deletes edges from a given vertex type to a specific vertex +// will delete each orphaned "from" vertex, but will never delete the "to" vertex +func (g *Graph) deleteEdges_locked(fromType, toType vertexType, toNamespace, toName string) { + // get the "to" side + toVert, exists := g.getVertex_rlocked(toType, toNamespace, toName) + if !exists { + return + } + + // delete all edges between vertices of fromType and toVert + neighborsToRemove := []*namedVertex{} + neighborsToRecompute := []*namedVertex{} + g.graph.VisitTo(toVert, func(from graph.Node) bool { + fromVert := from.(*namedVertex) + if fromVert.vertexType != fromType { + return true + } + // remove the edge + g.graph.RemoveEdge(simple.Edge{F: fromVert, T: toVert}) + // track vertexes that changed edges + if g.graph.Degree(fromVert) == 0 { + neighborsToRemove = append(neighborsToRemove, fromVert) + } else { + neighborsToRecompute = append(neighborsToRecompute, fromVert) } + return true + }) + + // clean up orphaned verts + for _, v := range neighborsToRemove { + g.removeVertex_locked(v) + } + + // recompute destination indexes for neighbors that dropped outbound edges + for _, v := range neighborsToRecompute { + g.recomputeDestinationIndex_locked(v) + } +} + +// must be called under write lock +// removeVertex_locked removes the specified vertex from the graph and from the maintained indices. +// It does nothing to indexes of neighbor vertices. +func (g *Graph) removeVertex_locked(v *namedVertex) { + g.graph.RemoveNode(v) + delete(g.destinationEdgeIndex, v.ID()) + delete(g.vertices[v.vertexType][v.namespace], v.name) + if len(g.vertices[v.vertexType][v.namespace]) == 0 { + delete(g.vertices[v.vertexType], v.namespace) + } +} + +// must be called under write lock +// recomputeDestinationIndex_locked recomputes the index of destination ids for the specified vertex +func (g *Graph) recomputeDestinationIndex_locked(n graph.Node) { + // don't maintain indices for nodes with few edges + edgeCount := g.graph.Degree(n) + if edgeCount < g.destinationEdgeThreshold { + delete(g.destinationEdgeIndex, n.ID()) + return + } + + // get or create the index + index := g.destinationEdgeIndex[n.ID()] + if index == nil { + index = newIntSet() + } else { + index.startNewGeneration() + } + + // populate the index + g.graph.VisitFrom(n, func(dest graph.Node) bool { + if destinationEdge, ok := g.graph.EdgeBetween(n, dest).(*destinationEdge); ok { + index.mark(destinationEdge.DestinationID()) + } + return true + }) + + // remove existing items no longer in the list + index.sweep() + + if len(index.members) < g.destinationEdgeThreshold { + delete(g.destinationEdgeIndex, n.ID()) + } else { + g.destinationEdgeIndex[n.ID()] = index } } @@ -221,22 +319,30 @@ func (g *Graph) AddPod(pod *api.Pod) { // // ref https://github.com/kubernetes/kubernetes/issues/58790 if len(pod.Spec.ServiceAccountName) > 0 { - g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(serviceAccountVertexType, pod.Namespace, pod.Spec.ServiceAccountName), podVertex, nodeVertex)) + serviceAccountVertex := g.getOrCreateVertex_locked(serviceAccountVertexType, pod.Namespace, pod.Spec.ServiceAccountName) + g.graph.SetEdge(newDestinationEdge(serviceAccountVertex, podVertex, nodeVertex)) + g.recomputeDestinationIndex_locked(serviceAccountVertex) } podutil.VisitPodSecretNames(pod, func(secret string) bool { - g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(secretVertexType, pod.Namespace, secret), podVertex, nodeVertex)) + secretVertex := g.getOrCreateVertex_locked(secretVertexType, pod.Namespace, secret) + g.graph.SetEdge(newDestinationEdge(secretVertex, podVertex, nodeVertex)) + g.recomputeDestinationIndex_locked(secretVertex) return true }) podutil.VisitPodConfigmapNames(pod, func(configmap string) bool { - g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(configMapVertexType, pod.Namespace, configmap), podVertex, nodeVertex)) + configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, pod.Namespace, configmap) + g.graph.SetEdge(newDestinationEdge(configmapVertex, podVertex, nodeVertex)) + g.recomputeDestinationIndex_locked(configmapVertex) return true }) for _, v := range pod.Spec.Volumes { if v.PersistentVolumeClaim != nil { - g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(pvcVertexType, pod.Namespace, v.PersistentVolumeClaim.ClaimName), podVertex, nodeVertex)) + pvcVertex := g.getOrCreateVertex_locked(pvcVertexType, pod.Namespace, v.PersistentVolumeClaim.ClaimName) + g.graph.SetEdge(newDestinationEdge(pvcVertex, podVertex, nodeVertex)) + g.recomputeDestinationIndex_locked(pvcVertex) } } } @@ -301,3 +407,25 @@ func (g *Graph) DeleteVolumeAttachment(name string) { defer g.lock.Unlock() g.deleteVertex_locked(vaVertexType, "", name) } + +// SetNodeConfigMap sets up edges for the Node.Spec.ConfigSource.ConfigMap relationship: +// +// configmap -> node +func (g *Graph) SetNodeConfigMap(nodeName, configMapName, configMapNamespace string) { + g.lock.Lock() + defer g.lock.Unlock() + + // TODO(mtaufen): ensure len(nodeName) > 0 in all cases (would sure be nice to have a dependently-typed language here...) + + // clear edges configmaps -> node where the destination is the current node *only* + // at present, a node can only have one *direct* configmap reference at a time + g.deleteEdges_locked(configMapVertexType, nodeVertexType, "", nodeName) + + // establish new edges if we have a real ConfigMap to reference + if len(configMapName) > 0 && len(configMapNamespace) > 0 { + configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, configMapNamespace, configMapName) + nodeVertex := g.getOrCreateVertex_locked(nodeVertexType, "", nodeName) + g.graph.SetEdge(newDestinationEdge(configmapVertex, nodeVertex, nodeVertex)) + } + +} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph_populator.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph_populator.go index 8c1c36a2d..4769d50e9 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph_populator.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph_populator.go @@ -17,6 +17,7 @@ limitations under the License. package node import ( + "fmt" "github.com/golang/glog" storagev1beta1 "k8s.io/api/storage/v1beta1" @@ -34,6 +35,7 @@ type graphPopulator struct { func AddGraphEventHandlers( graph *Graph, + nodes coreinformers.NodeInformer, pods coreinformers.PodInformer, pvs coreinformers.PersistentVolumeInformer, attachments storageinformers.VolumeAttachmentInformer, @@ -42,6 +44,14 @@ func AddGraphEventHandlers( graph: graph, } + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { + nodes.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: g.addNode, + UpdateFunc: g.updateNode, + DeleteFunc: g.deleteNode, + }) + } + pods.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: g.addPod, UpdateFunc: g.updatePod, @@ -63,6 +73,62 @@ func AddGraphEventHandlers( } } +func (g *graphPopulator) addNode(obj interface{}) { + g.updateNode(nil, obj) +} + +func (g *graphPopulator) updateNode(oldObj, obj interface{}) { + node := obj.(*api.Node) + var oldNode *api.Node + if oldObj != nil { + oldNode = oldObj.(*api.Node) + } + + // we only set up rules for ConfigMap today, because that is the only reference type + + var name, namespace string + if source := node.Spec.ConfigSource; source != nil && source.ConfigMap != nil { + name = source.ConfigMap.Name + namespace = source.ConfigMap.Namespace + } + + var oldName, oldNamespace string + if oldNode != nil { + if oldSource := oldNode.Spec.ConfigSource; oldSource != nil && oldSource.ConfigMap != nil { + oldName = oldSource.ConfigMap.Name + oldNamespace = oldSource.ConfigMap.Namespace + } + } + + // if Node.Spec.ConfigSource wasn't updated, nothing for us to do + if name == oldName && namespace == oldNamespace { + return + } + + path := "nil" + if node.Spec.ConfigSource != nil { + path = fmt.Sprintf("%s/%s", namespace, name) + } + glog.V(4).Infof("updateNode configSource reference to %s for node %s", path, node.Name) + g.graph.SetNodeConfigMap(node.Name, name, namespace) +} + +func (g *graphPopulator) deleteNode(obj interface{}) { + if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok { + obj = tombstone.Obj + } + node, ok := obj.(*api.Node) + if !ok { + glog.Infof("unexpected type %T", obj) + return + } + + // NOTE: We don't remove the node, because if the node is re-created not all pod -> node + // links are re-established (we don't get relevant events because the no mutations need + // to happen in the API; the state is already there). + g.graph.SetNodeConfigMap(node.Name, "", "") +} + func (g *graphPopulator) addPod(obj interface{}) { g.updatePod(nil, obj) } @@ -144,7 +210,7 @@ func (g *graphPopulator) deleteVolumeAttachment(obj interface{}) { if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok { obj = tombstone.Obj } - attachment, ok := obj.(*api.PersistentVolume) + attachment, ok := obj.(*storagev1beta1.VolumeAttachment) if !ok { glog.Infof("unexpected type %T", obj) return diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph_test.go new file mode 100644 index 000000000..02d196205 --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph_test.go @@ -0,0 +1,178 @@ +/* +Copyright 2018 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 node + +import ( + "sort" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDeleteEdges_locked(t *testing.T) { + cases := []struct { + desc string + fromType vertexType + toType vertexType + toNamespace string + toName string + start *Graph + expect *Graph + }{ + { + // single edge from a configmap to a node, will delete edge and orphaned configmap + desc: "edges and source orphans are deleted, destination orphans are preserved", + fromType: configMapVertexType, + toType: nodeVertexType, + toNamespace: "", + toName: "node1", + start: func() *Graph { + g := NewGraph() + g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap2") + nodeVertex := g.getOrCreateVertex_locked(nodeVertexType, "", "node1") + configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap1") + g.graph.SetEdge(newDestinationEdge(configmapVertex, nodeVertex, nodeVertex)) + return g + }(), + expect: func() *Graph { + g := NewGraph() + g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap2") + g.getOrCreateVertex_locked(nodeVertexType, "", "node1") + return g + }(), + }, + { + // two edges from the same configmap to distinct nodes, will delete one of the edges + desc: "edges are deleted, non-orphans and destination orphans are preserved", + fromType: configMapVertexType, + toType: nodeVertexType, + toNamespace: "", + toName: "node2", + start: func() *Graph { + g := NewGraph() + nodeVertex1 := g.getOrCreateVertex_locked(nodeVertexType, "", "node1") + nodeVertex2 := g.getOrCreateVertex_locked(nodeVertexType, "", "node2") + configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap1") + g.graph.SetEdge(newDestinationEdge(configmapVertex, nodeVertex1, nodeVertex1)) + g.graph.SetEdge(newDestinationEdge(configmapVertex, nodeVertex2, nodeVertex2)) + return g + }(), + expect: func() *Graph { + g := NewGraph() + nodeVertex1 := g.getOrCreateVertex_locked(nodeVertexType, "", "node1") + g.getOrCreateVertex_locked(nodeVertexType, "", "node2") + configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap1") + g.graph.SetEdge(newDestinationEdge(configmapVertex, nodeVertex1, nodeVertex1)) + return g + }(), + }, + { + desc: "no edges to delete", + fromType: configMapVertexType, + toType: nodeVertexType, + toNamespace: "", + toName: "node1", + start: func() *Graph { + g := NewGraph() + g.getOrCreateVertex_locked(nodeVertexType, "", "node1") + g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap1") + return g + }(), + expect: func() *Graph { + g := NewGraph() + g.getOrCreateVertex_locked(nodeVertexType, "", "node1") + g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap1") + return g + }(), + }, + { + desc: "destination vertex does not exist", + fromType: configMapVertexType, + toType: nodeVertexType, + toNamespace: "", + toName: "node1", + start: func() *Graph { + g := NewGraph() + g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap1") + return g + }(), + expect: func() *Graph { + g := NewGraph() + g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap1") + return g + }(), + }, + { + desc: "source vertex type doesn't exist", + fromType: configMapVertexType, + toType: nodeVertexType, + toNamespace: "", + toName: "node1", + start: func() *Graph { + g := NewGraph() + g.getOrCreateVertex_locked(nodeVertexType, "", "node1") + return g + }(), + expect: func() *Graph { + g := NewGraph() + g.getOrCreateVertex_locked(nodeVertexType, "", "node1") + return g + }(), + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + c.start.deleteEdges_locked(c.fromType, c.toType, c.toNamespace, c.toName) + + // Note: We assert on substructures (graph.Nodes(), graph.Edges()) because the graph tracks + // freed IDs for reuse, which results in an irrelevant inequality between start and expect. + + // sort the nodes by ID + // (the slices we get back are from map iteration, where order is not guaranteed) + expectNodes := c.expect.graph.Nodes() + sort.Slice(expectNodes, func(i, j int) bool { + return expectNodes[i].ID() < expectNodes[j].ID() + }) + startNodes := c.start.graph.Nodes() + sort.Slice(startNodes, func(i, j int) bool { + return startNodes[i].ID() < startNodes[j].ID() + }) + assert.Equal(t, expectNodes, startNodes) + + // sort the edges by from ID, then to ID + // (the slices we get back are from map iteration, where order is not guaranteed) + expectEdges := c.expect.graph.Edges() + sort.Slice(expectEdges, func(i, j int) bool { + if expectEdges[i].From().ID() == expectEdges[j].From().ID() { + return expectEdges[i].To().ID() < expectEdges[j].To().ID() + } + return expectEdges[i].From().ID() < expectEdges[j].From().ID() + }) + startEdges := c.start.graph.Edges() + sort.Slice(startEdges, func(i, j int) bool { + if startEdges[i].From().ID() == startEdges[j].From().ID() { + return startEdges[i].To().ID() < startEdges[j].To().ID() + } + return startEdges[i].From().ID() < startEdges[j].From().ID() + }) + assert.Equal(t, expectEdges, startEdges) + + // vertices is a recursive map, no need to sort + assert.Equal(t, c.expect.vertices, c.start.vertices) + }) + } +} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/intset.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/intset.go new file mode 100644 index 000000000..812a5367d --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/intset.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 node + +// intSet maintains a set of ints, and supports promoting and culling the previous generation. +// this allows tracking a large, mostly-stable set without constantly reallocating the entire set. +type intSet struct { + currentGeneration byte + members map[int]byte +} + +func newIntSet() *intSet { + return &intSet{members: map[int]byte{}} +} + +// has returns true if the specified int is in the set. +// it is safe to call concurrently, but must not be called concurrently with any of the other methods. +func (s *intSet) has(i int) bool { + if s == nil { + return false + } + _, present := s.members[i] + return present +} + +// startNewGeneration begins a new generation. +// it must be followed by a call to mark() for every member of the generation, +// then a call to sweep() to remove members not present in the generation. +// it is not thread-safe. +func (s *intSet) startNewGeneration() { + s.currentGeneration++ +} + +// mark indicates the specified int belongs to the current generation. +// it is not thread-safe. +func (s *intSet) mark(i int) { + s.members[i] = s.currentGeneration +} + +// sweep removes items not in the current generation. +// it is not thread-safe. +func (s *intSet) sweep() { + for k, v := range s.members { + if v != s.currentGeneration { + delete(s.members, k) + } + } +} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/intset_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/intset_test.go new file mode 100644 index 000000000..0fbc7a308 --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/intset_test.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 node + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIntSet(t *testing.T) { + i := newIntSet() + + assert.False(t, i.has(1)) + assert.False(t, i.has(2)) + assert.False(t, i.has(3)) + assert.False(t, i.has(4)) + + i.startNewGeneration() + i.mark(1) + i.mark(2) + i.sweep() + + assert.True(t, i.has(1)) + assert.True(t, i.has(2)) + assert.False(t, i.has(3)) + assert.False(t, i.has(4)) + + i.startNewGeneration() + i.mark(2) + i.mark(3) + i.sweep() + + assert.False(t, i.has(1)) + assert.True(t, i.has(2)) + assert.True(t, i.has(3)) + assert.False(t, i.has(4)) + + i.startNewGeneration() + i.mark(3) + i.mark(4) + i.sweep() + + assert.False(t, i.has(1)) + assert.False(t, i.has(2)) + assert.True(t, i.has(3)) + assert.True(t, i.has(4)) +} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer.go index b2078d2c6..371df74a8 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer.go @@ -21,11 +21,11 @@ import ( "github.com/golang/glog" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/authorization/authorizer" utilfeature "k8s.io/apiserver/pkg/util/feature" api "k8s.io/kubernetes/pkg/apis/core" - rbacapi "k8s.io/kubernetes/pkg/apis/rbac" storageapi "k8s.io/kubernetes/pkg/apis/storage" "k8s.io/kubernetes/pkg/auth/nodeidentifier" "k8s.io/kubernetes/pkg/features" @@ -38,6 +38,7 @@ import ( // 1. If a request is not from a node (NodeIdentity() returns isNode=false), reject // 2. If a specific node cannot be identified (NodeIdentity() returns nodeName=""), reject // 3. If a request is for a secret, configmap, persistent volume or persistent volume claim, reject unless the verb is get, and the requested object is related to the requesting node: +// node <- configmap // node <- pod // node <- pod <- secret // node <- pod <- configmap @@ -48,14 +49,14 @@ import ( type NodeAuthorizer struct { graph *Graph identifier nodeidentifier.NodeIdentifier - nodeRules []rbacapi.PolicyRule + nodeRules []rbacv1.PolicyRule // allows overriding for testing features utilfeature.FeatureGate } // NewAuthorizer returns a new node authorizer -func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules []rbacapi.PolicyRule) authorizer.Authorizer { +func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules []rbacv1.PolicyRule) authorizer.Authorizer { return &NodeAuthorizer{ graph: graph, identifier: identifier, @@ -90,9 +91,9 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci requestResource := schema.GroupResource{Group: attrs.GetAPIGroup(), Resource: attrs.GetResource()} switch requestResource { case secretResource: - return r.authorizeGet(nodeName, secretVertexType, attrs) + return r.authorizeReadNamespacedObject(nodeName, secretVertexType, attrs) case configMapResource: - return r.authorizeGet(nodeName, configMapVertexType, attrs) + return r.authorizeReadNamespacedObject(nodeName, configMapVertexType, attrs) case pvcResource: if r.features.Enabled(features.ExpandPersistentVolumes) { if attrs.GetSubresource() == "status" { @@ -153,6 +154,24 @@ func (r *NodeAuthorizer) authorizeGet(nodeName string, startingType vertexType, return r.authorize(nodeName, startingType, attrs) } +// authorizeReadNamespacedObject authorizes "get", "list" and "watch" requests to single objects of a +// specified types if they are related to the specified node. +func (r *NodeAuthorizer) authorizeReadNamespacedObject(nodeName string, startingType vertexType, attrs authorizer.Attributes) (authorizer.Decision, string, error) { + if attrs.GetVerb() != "get" && attrs.GetVerb() != "list" && attrs.GetVerb() != "watch" { + glog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) + return authorizer.DecisionNoOpinion, "can only read resources of this type", nil + } + if len(attrs.GetSubresource()) > 0 { + glog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) + return authorizer.DecisionNoOpinion, "cannot read subresource", nil + } + if len(attrs.GetNamespace()) == 0 { + glog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) + return authorizer.DecisionNoOpinion, "can only read namespaced object of this type", nil + } + return r.authorize(nodeName, startingType, attrs) +} + func (r *NodeAuthorizer) authorize(nodeName string, startingType vertexType, attrs authorizer.Attributes) (authorizer.Decision, string, error) { if len(attrs.GetName()) == 0 { glog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) @@ -211,6 +230,11 @@ func (r *NodeAuthorizer) hasPathFrom(nodeName string, startingType vertexType, s return false, fmt.Errorf("node %q cannot get unknown %s %s/%s", nodeName, vertexTypes[startingType], startingNamespace, startingName) } + // Fast check to see if we know of a destination edge + if r.graph.destinationEdgeIndex[startingVertex.ID()].has(nodeVertex.ID()) { + return true, nil + } + found := false traversal := &traverse.VisitingDepthFirst{ EdgeFilter: func(edge graph.Edge) bool { diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer_test.go index 19eb32fdf..956f8d297 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer_test.go @@ -20,12 +20,15 @@ import ( "fmt" "runtime" "runtime/pprof" + "sync/atomic" "testing" + "time" "os" storagev1beta1 "k8s.io/api/storage/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -72,8 +75,8 @@ func TestAuthorizer(t *testing.T) { sharedPVCsPerPod: 0, uniquePVCsPerPod: 1, } - pods, pvs, attachments := generate(opts) - populate(g, pods, pvs, attachments) + nodes, pods, pvs, attachments := generate(opts) + populate(g, nodes, pods, pvs, attachments) identifier := nodeidentifier.NewDefaultNodeIdentifier() authz := NewAuthorizer(g, identifier, bootstrappolicy.NodeRules()).(*NodeAuthorizer) @@ -86,6 +89,11 @@ func TestAuthorizer(t *testing.T) { expect authorizer.Decision features utilfeature.FeatureGate }{ + { + name: "allowed node configmap", + attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node0-configmap", Namespace: "ns0"}, + expect: authorizer.DecisionAllow, + }, { name: "allowed configmap", attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"}, @@ -96,6 +104,31 @@ func TestAuthorizer(t *testing.T) { attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-pod0-node0", Namespace: "ns0"}, expect: authorizer.DecisionAllow, }, + { + name: "list allowed secret via pod", + attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "list", Resource: "secrets", Name: "secret0-pod0-node0", Namespace: "ns0"}, + expect: authorizer.DecisionAllow, + }, + { + name: "watch allowed secret via pod", + attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "watch", Resource: "secrets", Name: "secret0-pod0-node0", Namespace: "ns0"}, + expect: authorizer.DecisionAllow, + }, + { + name: "disallowed list many secrets", + attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "list", Resource: "secrets", Name: "", Namespace: "ns0"}, + expect: authorizer.DecisionNoOpinion, + }, + { + name: "disallowed watch many secrets", + attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "watch", Resource: "secrets", Name: "", Namespace: "ns0"}, + expect: authorizer.DecisionNoOpinion, + }, + { + name: "disallowed list secrets from all namespaces with name", + attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "list", Resource: "secrets", Name: "secret0-pod0-node0", Namespace: ""}, + expect: authorizer.DecisionNoOpinion, + }, { name: "allowed shared secret via pod", attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-shared", Namespace: "ns0"}, @@ -117,6 +150,11 @@ func TestAuthorizer(t *testing.T) { expect: authorizer.DecisionAllow, }, + { + name: "disallowed node configmap", + attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node1-configmap", Namespace: "ns0"}, + expect: authorizer.DecisionNoOpinion, + }, { name: "disallowed configmap", attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"}, @@ -209,6 +247,7 @@ func TestAuthorizer(t *testing.T) { func TestAuthorizerSharedResources(t *testing.T) { g := NewGraph() + g.destinationEdgeThreshold = 1 identifier := nodeidentifier.NewDefaultNodeIdentifier() authz := NewAuthorizer(g, identifier, bootstrappolicy.NodeRules()) @@ -237,7 +276,8 @@ func TestAuthorizerSharedResources(t *testing.T) { }, }, }) - g.AddPod(&api.Pod{ + + pod3 := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "pod3-node3", Namespace: "ns1"}, Spec: api.PodSpec{ NodeName: "node3", @@ -245,11 +285,17 @@ func TestAuthorizerSharedResources(t *testing.T) { {VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "shared-all"}}}, }, }, - }) + } + g.AddPod(pod3) + + g.SetNodeConfigMap("node1", "shared-configmap", "ns1") + g.SetNodeConfigMap("node2", "shared-configmap", "ns1") + g.SetNodeConfigMap("node3", "configmap", "ns1") testcases := []struct { User user.Info Secret string + ConfigMap string ExpectAllowed bool }{ {User: node1, ExpectAllowed: true, Secret: "node1-only"}, @@ -263,18 +309,67 @@ func TestAuthorizerSharedResources(t *testing.T) { {User: node3, ExpectAllowed: false, Secret: "node1-only"}, {User: node3, ExpectAllowed: false, Secret: "node1-node2-only"}, {User: node3, ExpectAllowed: true, Secret: "shared-all"}, + + {User: node1, ExpectAllowed: true, ConfigMap: "shared-configmap"}, + {User: node1, ExpectAllowed: false, ConfigMap: "configmap"}, + + {User: node2, ExpectAllowed: true, ConfigMap: "shared-configmap"}, + {User: node2, ExpectAllowed: false, ConfigMap: "configmap"}, + + {User: node3, ExpectAllowed: false, ConfigMap: "shared-configmap"}, + {User: node3, ExpectAllowed: true, ConfigMap: "configmap"}, } for i, tc := range testcases { - decision, _, err := authz.Authorize(authorizer.AttributesRecord{User: tc.User, ResourceRequest: true, Verb: "get", Resource: "secrets", Namespace: "ns1", Name: tc.Secret}) - if err != nil { - t.Errorf("%d: unexpected error: %v", i, err) - continue + var ( + decision authorizer.Decision + err error + ) + + if len(tc.Secret) > 0 { + decision, _, err = authz.Authorize(authorizer.AttributesRecord{User: tc.User, ResourceRequest: true, Verb: "get", Resource: "secrets", Namespace: "ns1", Name: tc.Secret}) + if err != nil { + t.Errorf("%d: unexpected error: %v", i, err) + continue + } + } else if len(tc.ConfigMap) > 0 { + decision, _, err = authz.Authorize(authorizer.AttributesRecord{User: tc.User, ResourceRequest: true, Verb: "get", Resource: "configmaps", Namespace: "ns1", Name: tc.ConfigMap}) + if err != nil { + t.Errorf("%d: unexpected error: %v", i, err) + continue + } + } else { + t.Fatalf("test case must include a request for a Secret or ConfigMap") } + if (decision == authorizer.DecisionAllow) != tc.ExpectAllowed { t.Errorf("%d: expected %v, got %v", i, tc.ExpectAllowed, decision) } } + + { + node3SharedSecretGet := authorizer.AttributesRecord{User: node3, ResourceRequest: true, Verb: "get", Resource: "secrets", Namespace: "ns1", Name: "shared-all"} + + decision, _, err := authz.Authorize(node3SharedSecretGet) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if decision != authorizer.DecisionAllow { + t.Error("expected allowed") + } + + // should trigger recalculation of the shared secret index + pod3.Spec.Volumes = nil + g.AddPod(pod3) + + decision, _, err = authz.Authorize(node3SharedSecretGet) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if decision == authorizer.DecisionAllow { + t.Errorf("unexpectedly allowed") + } + } } type sampleDataOpts struct { @@ -309,12 +404,12 @@ func BenchmarkPopulationAllocation(b *testing.B) { uniquePVCsPerPod: 1, } - pods, pvs, attachments := generate(opts) + nodes, pods, pvs, attachments := generate(opts) b.ResetTimer() for i := 0; i < b.N; i++ { g := NewGraph() - populate(g, pods, pvs, attachments) + populate(g, nodes, pods, pvs, attachments) } } @@ -340,14 +435,14 @@ func BenchmarkPopulationRetention(b *testing.B) { uniquePVCsPerPod: 1, } - pods, pvs, attachments := generate(opts) + nodes, pods, pvs, attachments := generate(opts) // Garbage collect before the first iteration runtime.GC() b.ResetTimer() for i := 0; i < b.N; i++ { g := NewGraph() - populate(g, pods, pvs, attachments) + populate(g, nodes, pods, pvs, attachments) if i == 0 { f, _ := os.Create("BenchmarkPopulationRetention.profile") @@ -360,10 +455,47 @@ func BenchmarkPopulationRetention(b *testing.B) { } } +func BenchmarkWriteIndexMaintenance(b *testing.B) { + + // Run with: + // go test ./plugin/pkg/auth/authorizer/node -benchmem -bench BenchmarkWriteIndexMaintenance -run None + + opts := sampleDataOpts{ + // simulate high replication in a small number of namespaces: + nodes: 5000, + namespaces: 1, + podsPerNode: 1, + attachmentsPerNode: 20, + sharedConfigMapsPerPod: 0, + uniqueConfigMapsPerPod: 1, + sharedSecretsPerPod: 1, + uniqueSecretsPerPod: 1, + sharedPVCsPerPod: 0, + uniquePVCsPerPod: 1, + } + nodes, pods, pvs, attachments := generate(opts) + g := NewGraph() + populate(g, nodes, pods, pvs, attachments) + // Garbage collect before the first iteration + runtime.GC() + b.ResetTimer() + + b.SetParallelism(100) + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + g.AddPod(pods[0]) + } + }) +} + func BenchmarkAuthorization(b *testing.B) { g := NewGraph() opts := sampleDataOpts{ + // To simulate high replication in a small number of namespaces: + // nodes: 5000, + // namespaces: 10, + // podsPerNode: 10, nodes: 500, namespaces: 200, podsPerNode: 200, @@ -375,8 +507,8 @@ func BenchmarkAuthorization(b *testing.B) { sharedPVCsPerPod: 0, uniquePVCsPerPod: 1, } - pods, pvs, attachments := generate(opts) - populate(g, pods, pvs, attachments) + nodes, pods, pvs, attachments := generate(opts) + populate(g, nodes, pods, pvs, attachments) identifier := nodeidentifier.NewDefaultNodeIdentifier() authz := NewAuthorizer(g, identifier, bootstrappolicy.NodeRules()).(*NodeAuthorizer) @@ -389,6 +521,11 @@ func BenchmarkAuthorization(b *testing.B) { expect authorizer.Decision features utilfeature.FeatureGate }{ + { + name: "allowed node configmap", + attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node0-configmap", Namespace: "ns0"}, + expect: authorizer.DecisionAllow, + }, { name: "allowed configmap", attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"}, @@ -404,6 +541,12 @@ func BenchmarkAuthorization(b *testing.B) { attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-shared", Namespace: "ns0"}, expect: authorizer.DecisionAllow, }, + + { + name: "disallowed node configmap", + attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node1-configmap", Namespace: "ns0"}, + expect: authorizer.DecisionNoOpinion, + }, { name: "disallowed configmap", attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"}, @@ -450,26 +593,102 @@ func BenchmarkAuthorization(b *testing.B) { } b.ResetTimer() - for _, tc := range tests { - if tc.features == nil { - authz.features = utilfeature.DefaultFeatureGate - } else { - authz.features = tc.features - } - b.Run(tc.name, func(b *testing.B) { - for i := 0; i < b.N; i++ { - decision, _, _ := authz.Authorize(tc.attrs) - if decision != tc.expect { - b.Errorf("expected %v, got %v", tc.expect, decision) + for _, testWriteContention := range []bool{false, true} { + + shouldWrite := int32(1) + writes := int64(0) + _1ms := int64(0) + _10ms := int64(0) + _25ms := int64(0) + _50ms := int64(0) + _100ms := int64(0) + _250ms := int64(0) + _500ms := int64(0) + _1000ms := int64(0) + _1s := int64(0) + + contentionPrefix := "" + if testWriteContention { + contentionPrefix = "contentious " + // Start a writer pushing graph modifications 100x a second + go func() { + for shouldWrite == 1 { + go func() { + start := time.Now() + authz.graph.AddPod(&api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "testwrite", Namespace: "ns0"}, + Spec: api.PodSpec{ + NodeName: "node0", + ServiceAccountName: "default", + Volumes: []api.Volume{ + {Name: "token", VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "secret0-shared"}}}, + }, + }, + }) + diff := time.Now().Sub(start) + atomic.AddInt64(&writes, 1) + switch { + case diff < time.Millisecond: + atomic.AddInt64(&_1ms, 1) + case diff < 10*time.Millisecond: + atomic.AddInt64(&_10ms, 1) + case diff < 25*time.Millisecond: + atomic.AddInt64(&_25ms, 1) + case diff < 50*time.Millisecond: + atomic.AddInt64(&_50ms, 1) + case diff < 100*time.Millisecond: + atomic.AddInt64(&_100ms, 1) + case diff < 250*time.Millisecond: + atomic.AddInt64(&_250ms, 1) + case diff < 500*time.Millisecond: + atomic.AddInt64(&_500ms, 1) + case diff < 1000*time.Millisecond: + atomic.AddInt64(&_1000ms, 1) + default: + atomic.AddInt64(&_1s, 1) + } + }() + time.Sleep(10 * time.Millisecond) } + }() + } + + for _, tc := range tests { + if tc.features == nil { + authz.features = utilfeature.DefaultFeatureGate + } else { + authz.features = tc.features } - }) + b.Run(contentionPrefix+tc.name, func(b *testing.B) { + // Run authorization checks in parallel + b.SetParallelism(5000) + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + decision, _, _ := authz.Authorize(tc.attrs) + if decision != tc.expect { + b.Errorf("expected %v, got %v", tc.expect, decision) + } + } + }) + }) + } + + atomic.StoreInt32(&shouldWrite, 0) + if testWriteContention { + b.Logf("graph modifications during contention test: %d", writes) + b.Logf("<1ms=%d, <10ms=%d, <25ms=%d, <50ms=%d, <100ms=%d, <250ms=%d, <500ms=%d, <1000ms=%d, >1000ms=%d", _1ms, _10ms, _25ms, _50ms, _100ms, _250ms, _500ms, _1000ms, _1s) + } else { + b.Logf("graph modifications during non-contention test: %d", writes) + } } } -func populate(graph *Graph, pods []*api.Pod, pvs []*api.PersistentVolume, attachments []*storagev1beta1.VolumeAttachment) { +func populate(graph *Graph, nodes []*api.Node, pods []*api.Pod, pvs []*api.PersistentVolume, attachments []*storagev1beta1.VolumeAttachment) { p := &graphPopulator{} p.graph = graph + for _, node := range nodes { + p.addNode(node) + } for _, pod := range pods { p.addPod(pod) } @@ -485,7 +704,8 @@ func populate(graph *Graph, pods []*api.Pod, pvs []*api.PersistentVolume, attach // the secret/configmap/pvc/node references in the pod and pv objects are named to indicate the connections between the objects. // for example, secret0-pod0-node0 is a secret referenced by pod0 which is bound to node0. // when populated into the graph, the node authorizer should allow node0 to access that secret, but not node1. -func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume, []*storagev1beta1.VolumeAttachment) { +func generate(opts sampleDataOpts) ([]*api.Node, []*api.Pod, []*api.PersistentVolume, []*storagev1beta1.VolumeAttachment) { + nodes := make([]*api.Node, 0, opts.nodes) pods := make([]*api.Pod, 0, opts.nodes*opts.podsPerNode) pvs := make([]*api.PersistentVolume, 0, (opts.nodes*opts.podsPerNode*opts.uniquePVCsPerPod)+(opts.sharedPVCsPerPod*opts.namespaces)) attachments := make([]*storagev1beta1.VolumeAttachment, 0, opts.nodes*opts.attachmentsPerNode) @@ -552,6 +772,21 @@ func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume, []*stor attachment.Spec.NodeName = nodeName attachments = append(attachments, attachment) } + + name := fmt.Sprintf("%s-configmap", nodeName) + nodes = append(nodes, &api.Node{ + ObjectMeta: metav1.ObjectMeta{Name: nodeName}, + Spec: api.NodeSpec{ + ConfigSource: &api.NodeConfigSource{ + ConfigMap: &api.ConfigMapNodeConfigSource{ + Name: name, + Namespace: "ns0", + UID: types.UID(fmt.Sprintf("ns0-%s", name)), + KubeletConfigKey: "kubelet", + }, + }, + }, + }) } - return pods, pvs, attachments + return nodes, pods, pvs, attachments } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/BUILD index 258c860c5..cc7848ece 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/BUILD @@ -14,14 +14,15 @@ go_library( ], importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac", deps = [ - "//pkg/apis/rbac:go_default_library", - "//pkg/client/listers/rbac/internalversion:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac/validation:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", + "//vendor/k8s.io/client-go/listers/rbac/v1:go_default_library", ], ) @@ -33,9 +34,10 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac/validation:go_default_library", "//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD index 4c891015f..83b98d221 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD @@ -15,9 +15,10 @@ go_library( ], importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy", deps = [ - "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/features:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", @@ -37,8 +38,8 @@ go_test( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/install:go_default_library", - "//pkg/apis/rbac:go_default_library", "//pkg/apis/rbac/install:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac/validation:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go index af7e16edc..5dfbaa6f2 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go @@ -21,15 +21,16 @@ import ( "github.com/golang/glog" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilfeature "k8s.io/apiserver/pkg/util/feature" - rbac "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" "k8s.io/kubernetes/pkg/features" ) const saRolePrefix = "system:controller:" -func addControllerRole(controllerRoles *[]rbac.ClusterRole, controllerRoleBindings *[]rbac.ClusterRoleBinding, role rbac.ClusterRole) { +func addControllerRole(controllerRoles *[]rbacv1.ClusterRole, controllerRoleBindings *[]rbacv1.ClusterRoleBinding, role rbacv1.ClusterRole) { if !strings.HasPrefix(role.Name, saRolePrefix) { glog.Fatalf(`role %q must start with %q`, role.Name, saRolePrefix) } @@ -44,298 +45,298 @@ func addControllerRole(controllerRoles *[]rbac.ClusterRole, controllerRoleBindin addClusterRoleLabel(*controllerRoles) *controllerRoleBindings = append(*controllerRoleBindings, - rbac.NewClusterBinding(role.Name).SAs("kube-system", role.Name[len(saRolePrefix):]).BindingOrDie()) + rbacv1helpers.NewClusterBinding(role.Name).SAs("kube-system", role.Name[len(saRolePrefix):]).BindingOrDie()) addClusterRoleBindingLabel(*controllerRoleBindings) } -func eventsRule() rbac.PolicyRule { - return rbac.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie() +func eventsRule() rbacv1.PolicyRule { + return rbacv1helpers.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie() } -func buildControllerRoles() ([]rbac.ClusterRole, []rbac.ClusterRoleBinding) { +func buildControllerRoles() ([]rbacv1.ClusterRole, []rbacv1.ClusterRoleBinding) { // controllerRoles is a slice of roles used for controllers - controllerRoles := []rbac.ClusterRole{} + controllerRoles := []rbacv1.ClusterRole{} // controllerRoleBindings is a slice of roles used for controllers - controllerRoleBindings := []rbac.ClusterRoleBinding{} + controllerRoleBindings := []rbacv1.ClusterRoleBinding{} - addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbac.ClusterRole { - role := rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbacv1.ClusterRole { + role := rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "attachdetach-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("persistentvolumes", "persistentvolumeclaims").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("persistentvolumes", "persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, } if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { - role.Rules = append(role.Rules, rbac.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()) + role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()) } return role }()) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "clusterrole-aggregation-controller"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // this controller must have full permissions to allow it to mutate any role in any way - rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(), - rbac.NewRule("*").URLs("*").RuleOrDie(), + rbacv1helpers.NewRule("*").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("*").URLs("*").RuleOrDie(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "cronjob-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("cronjobs").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "create", "update", "delete", "patch").Groups(batchGroup).Resources("jobs").RuleOrDie(), - rbac.NewRule("update").Groups(batchGroup).Resources("cronjobs/status").RuleOrDie(), - rbac.NewRule("update").Groups(batchGroup).Resources("cronjobs/finalizers").RuleOrDie(), - rbac.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("cronjobs").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "delete", "patch").Groups(batchGroup).Resources("jobs").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("cronjobs/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("cronjobs/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "daemon-set-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("daemonsets").RuleOrDie(), - rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/status").RuleOrDie(), - rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/finalizers").RuleOrDie(), - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("create").Groups(legacyGroup).Resources("pods/binding").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "create", "delete", "update", "patch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("daemonsets").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/binding").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "delete", "update", "patch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "deployment-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), - rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/status").RuleOrDie(), - rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/finalizers").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "create", "update", "patch", "delete").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch", "delete").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), // TODO: remove "update" once // https://github.com/kubernetes/kubernetes/issues/36897 is resolved. - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "disruption-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), - rbac.NewRule("update").Groups(policyGroup).Resources("poddisruptionbudgets/status").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(policyGroup).Resources("poddisruptionbudgets/status").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "endpoint-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services", "pods").RuleOrDie(), - rbac.NewRule("get", "list", "create", "update", "delete").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), - rbac.NewRule("create").Groups(legacyGroup).Resources("endpoints/restricted").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services", "pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "create", "update", "delete").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints/restricted").RuleOrDie(), eventsRule(), }, }) if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) { - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "expand-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), - rbac.NewRule("update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), // glusterfs - rbac.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), eventsRule(), }, }) } - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "generic-garbage-collector"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // the GC controller needs to run list/watches, selective gets, and updates against any resource - rbac.NewRule("get", "list", "watch", "patch", "update", "delete").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "patch", "update", "delete").Groups("*").Resources("*").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "horizontal-pod-autoscaler"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), - rbac.NewRule("update").Groups(autoscalingGroup).Resources("horizontalpodautoscalers/status").RuleOrDie(), - rbac.NewRule("get", "update").Groups("*").Resources("*/scale").RuleOrDie(), - rbac.NewRule("list").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(autoscalingGroup).Resources("horizontalpodautoscalers/status").RuleOrDie(), + rbacv1helpers.NewRule("get", "update").Groups("*").Resources("*/scale").RuleOrDie(), + rbacv1helpers.NewRule("list").Groups(legacyGroup).Resources("pods").RuleOrDie(), // TODO: restrict this to the appropriate namespace - rbac.NewRule("get").Groups(legacyGroup).Resources("services/proxy").Names("https:heapster:", "http:heapster:").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("services/proxy").Names("https:heapster:", "http:heapster:").RuleOrDie(), // allow listing resource metrics and custom metrics - rbac.NewRule("list").Groups(resMetricsGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("get", "list").Groups(customMetricsGroup).Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("list").Groups(resMetricsGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list").Groups(customMetricsGroup).Resources("*").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "job-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("jobs").RuleOrDie(), - rbac.NewRule("update").Groups(batchGroup).Resources("jobs/status").RuleOrDie(), - rbac.NewRule("update").Groups(batchGroup).Resources("jobs/finalizers").RuleOrDie(), - rbac.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("jobs").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("jobs/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("jobs/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "namespace-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("namespaces").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("namespaces/finalize", "namespaces/status").RuleOrDie(), - rbac.NewRule("get", "list", "delete", "deletecollection").Groups("*").Resources("*").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("namespaces").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("namespaces/finalize", "namespaces/status").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "delete", "deletecollection").Groups("*").Resources("*").RuleOrDie(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "node-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "update", "delete", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "update", "delete", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), // used for pod eviction - rbac.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), - rbac.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "persistent-volume-binder"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("persistentvolumes/status").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), - rbac.NewRule("list", "watch", "get", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("persistentvolumes/status").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "get", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), // glusterfs - rbac.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), - rbac.NewRule("get", "create", "delete").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + rbacv1helpers.NewRule("get", "create", "delete").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), // openstack - rbac.NewRule("get", "list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), // recyclerClient.WatchPod - rbac.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(), + rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pod-garbage-collector"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replicaset-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), - rbac.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/status").RuleOrDie(), - rbac.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/finalizers").RuleOrDie(), - rbac.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replication-controller"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // 1.0 controllers needed get, update, so without these old controllers break on new servers - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/status").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/finalizers").RuleOrDie(), - rbac.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "resourcequota-controller"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // quota can count quota on anything for reconciliation, so it needs full viewing powers - rbac.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("resourcequotas/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("resourcequotas/status").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "route-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-account-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("services/status").RuleOrDie(), - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("services/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "statefulset-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), - rbac.NewRule("update").Groups(appsGroup).Resources("statefulsets/status").RuleOrDie(), - rbac.NewRule("update").Groups(appsGroup).Resources("statefulsets/finalizers").RuleOrDie(), - rbac.NewRule("get", "create", "delete", "update", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("get", "create", "delete", "update", "patch", "list", "watch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), - rbac.NewRule("get", "create").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(appsGroup).Resources("statefulsets/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(appsGroup).Resources("statefulsets/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("get", "create", "delete", "update", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "create", "delete", "update", "patch", "list", "watch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), + rbacv1helpers.NewRule("get", "create").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "ttl-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("update", "patch", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("update", "patch", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "certificate-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "delete").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), - rbac.NewRule("update").Groups(certificatesGroup).Resources("certificatesigningrequests/status", "certificatesigningrequests/approval").RuleOrDie(), - rbac.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(certificatesGroup).Resources("certificatesigningrequests/status", "certificatesigningrequests/approval").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pvc-protection-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), - rbac.NewRule("list", "watch", "get").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "get").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pv-protection-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), eventsRule(), }, }) @@ -344,13 +345,13 @@ func buildControllerRoles() ([]rbac.ClusterRole, []rbac.ClusterRoleBinding) { } // ControllerRoles returns the cluster roles used by controllers -func ControllerRoles() []rbac.ClusterRole { +func ControllerRoles() []rbacv1.ClusterRole { controllerRoles, _ := buildControllerRoles() return controllerRoles } // ControllerRoleBindings returns the role bindings used by controllers -func ControllerRoleBindings() []rbac.ClusterRoleBinding { +func ControllerRoleBindings() []rbacv1.ClusterRoleBinding { _, controllerRoleBindings := buildControllerRoles() return controllerRoleBindings } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/namespace_policy.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/namespace_policy.go index 16590fffc..fefe26d2c 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/namespace_policy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/namespace_policy.go @@ -21,19 +21,20 @@ import ( "github.com/golang/glog" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - rbac "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) var ( // namespaceRoles is a map of namespace to slice of roles to create - namespaceRoles = map[string][]rbac.Role{} + namespaceRoles = map[string][]rbacv1.Role{} // namespaceRoleBindings is a map of namespace to slice of roleBindings to create - namespaceRoleBindings = map[string][]rbac.RoleBinding{} + namespaceRoleBindings = map[string][]rbacv1.RoleBinding{} ) -func addNamespaceRole(namespace string, role rbac.Role) { +func addNamespaceRole(namespace string, role rbacv1.Role) { if !strings.HasPrefix(namespace, "kube-") { glog.Fatalf(`roles can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace) } @@ -51,7 +52,7 @@ func addNamespaceRole(namespace string, role rbac.Role) { namespaceRoles[namespace] = existingRoles } -func addNamespaceRoleBinding(namespace string, roleBinding rbac.RoleBinding) { +func addNamespaceRoleBinding(namespace string, roleBinding rbacv1.RoleBinding) { if !strings.HasPrefix(namespace, "kube-") { glog.Fatalf(`rolebindings can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace) } @@ -70,86 +71,86 @@ func addNamespaceRoleBinding(namespace string, roleBinding rbac.RoleBinding) { } func init() { - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for finding authentication config info for starting a server ObjectMeta: metav1.ObjectMeta{Name: "extension-apiserver-authentication-reader"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // this particular config map is exposed and contains authentication configuration information - rbac.NewRule("get").Groups(legacyGroup).Resources("configmaps").Names("extension-apiserver-authentication").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("configmaps").Names("extension-apiserver-authentication").RuleOrDie(), }, }) - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the bootstrap signer to be able to inspect kube-system secrets ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets").RuleOrDie(), }, }) - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the cloud providers to access/create kube-system configmaps // Deprecated starting Kubernetes 1.10 and will be deleted according to GA deprecation policy. ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "cloud-provider"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), }, }) - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the token-cleaner to be able to remove secrets, but only in kube-system ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "token-cleaner"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(), eventsRule(), }, }) // TODO: Create util on Role+Binding for leader locking if more cases evolve. - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the leader locking on supplied configmap ObjectMeta: metav1.ObjectMeta{Name: "system::leader-locking-kube-controller-manager"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), - rbac.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-controller-manager").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), + rbacv1helpers.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-controller-manager").RuleOrDie(), }, }) - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the leader locking on supplied configmap ObjectMeta: metav1.ObjectMeta{Name: "system::leader-locking-kube-scheduler"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), - rbac.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-scheduler").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), + rbacv1helpers.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-scheduler").RuleOrDie(), }, }) addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding("system::leader-locking-kube-controller-manager", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-controller-manager").BindingOrDie()) + rbacv1helpers.NewRoleBinding("system::leader-locking-kube-controller-manager", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-controller-manager").BindingOrDie()) addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding("system::leader-locking-kube-scheduler", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-scheduler").BindingOrDie()) + rbacv1helpers.NewRoleBinding("system::leader-locking-kube-scheduler", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-scheduler").BindingOrDie()) addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie()) + rbacv1helpers.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie()) // cloud-provider is deprecated starting Kubernetes 1.10 and will be deleted according to GA deprecation policy. addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding(saRolePrefix+"cloud-provider", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "cloud-provider").BindingOrDie()) + rbacv1helpers.NewRoleBinding(saRolePrefix+"cloud-provider", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "cloud-provider").BindingOrDie()) addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding(saRolePrefix+"token-cleaner", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "token-cleaner").BindingOrDie()) + rbacv1helpers.NewRoleBinding(saRolePrefix+"token-cleaner", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "token-cleaner").BindingOrDie()) - addNamespaceRole(metav1.NamespacePublic, rbac.Role{ + addNamespaceRole(metav1.NamespacePublic, rbacv1.Role{ // role for the bootstrap signer to be able to write its configmap ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("configmaps").Names("cluster-info").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("configmaps").Names("cluster-info").RuleOrDie(), eventsRule(), }, }) addNamespaceRoleBinding(metav1.NamespacePublic, - rbac.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespacePublic).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie()) + rbacv1helpers.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespacePublic).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie()) } // NamespaceRoles returns a map of namespace to slice of roles to create -func NamespaceRoles() map[string][]rbac.Role { +func NamespaceRoles() map[string][]rbacv1.Role { return namespaceRoles } // NamespaceRoleBindings returns a map of namespace to slice of roles to create -func NamespaceRoleBindings() map[string][]rbac.RoleBinding { +func NamespaceRoleBindings() map[string][]rbacv1.RoleBinding { return namespaceRoleBindings } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go index 74d86d9d1..815f3787c 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go @@ -17,12 +17,13 @@ limitations under the License. package bootstrappolicy import ( + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/authentication/user" utilfeature "k8s.io/apiserver/pkg/util/feature" - rbac "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" "k8s.io/kubernetes/pkg/features" ) @@ -32,7 +33,7 @@ var ( ReadUpdate = []string{"get", "list", "watch", "update", "patch"} Label = map[string]string{"kubernetes.io/bootstrapping": "rbac-defaults"} - Annotation = map[string]string{rbac.AutoUpdateAnnotationKey: "true"} + Annotation = map[string]string{rbacv1.AutoUpdateAnnotationKey: "true"} ) const ( @@ -78,105 +79,105 @@ func addDefaultMetadata(obj runtime.Object) { metadata.SetAnnotations(annotations) } -func addClusterRoleLabel(roles []rbac.ClusterRole) { +func addClusterRoleLabel(roles []rbacv1.ClusterRole) { for i := range roles { addDefaultMetadata(&roles[i]) } return } -func addClusterRoleBindingLabel(rolebindings []rbac.ClusterRoleBinding) { +func addClusterRoleBindingLabel(rolebindings []rbacv1.ClusterRoleBinding) { for i := range rolebindings { addDefaultMetadata(&rolebindings[i]) } return } -func NodeRules() []rbac.PolicyRule { - nodePolicyRules := []rbac.PolicyRule{ +func NodeRules() []rbacv1.PolicyRule { + nodePolicyRules := []rbacv1.PolicyRule{ // Needed to check API access. These creates are non-mutating - rbac.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), - rbac.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews", "localsubjectaccessreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews", "localsubjectaccessreviews").RuleOrDie(), // Needed to build serviceLister, to populate env vars for services - rbac.NewRule(Read...).Groups(legacyGroup).Resources("services").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services").RuleOrDie(), // Nodes can register Node API objects and report status. // Use the NodeRestriction admission plugin to limit a node to creating/updating its own API object. - rbac.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("update", "patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), - rbac.NewRule("update", "patch", "delete").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + rbacv1helpers.NewRule("update", "patch", "delete").Groups(legacyGroup).Resources("nodes").RuleOrDie(), // TODO: restrict to the bound node as creator in the NodeRestrictions admission plugin - rbac.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), + rbacv1helpers.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), // TODO: restrict to pods scheduled on the bound node once field selectors are supported by list/watch authorization - rbac.NewRule(Read...).Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("pods").RuleOrDie(), // Needed for the node to create/delete mirror pods. // Use the NodeRestriction admission plugin to limit a node to creating/deleting mirror pods bound to itself. - rbac.NewRule("create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), // Needed for the node to report status of pods it is running. // Use the NodeRestriction admission plugin to limit a node to updating status of pods bound to itself. - rbac.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), + rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), // Needed for the node to create pod evictions. // Use the NodeRestriction admission plugin to limit a node to creating evictions for pods bound to itself. - rbac.NewRule("create").Groups(legacyGroup).Resources("pods/eviction").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/eviction").RuleOrDie(), // Needed for imagepullsecrets, rbd/ceph and secret volumes, and secrets in envs // Needed for configmap volume and envs // Use the Node authorization mode to limit a node to get secrets/configmaps referenced by pods bound to itself. - rbac.NewRule("get").Groups(legacyGroup).Resources("secrets", "configmaps").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets", "configmaps").RuleOrDie(), // Needed for persistent volumes // Use the Node authorization mode to limit a node to get pv/pvc objects referenced by pods bound to itself. - rbac.NewRule("get").Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(), // TODO: add to the Node authorizer and restrict to endpoints referenced by pods or PVs bound to the node // Needed for glusterfs volumes - rbac.NewRule("get").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), // Used to create a certificatesigningrequest for a node-specific client certificate, and watch // for it to be signed. This allows the kubelet to rotate it's own certificate. - rbac.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), + rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), } if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) { // Use the Node authorization mode to limit a node to update status of pvc objects referenced by pods bound to itself. // Use the NodeRestriction admission plugin to limit a node to just update the status stanza. - pvcStatusPolicyRule := rbac.NewRule("get", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie() + pvcStatusPolicyRule := rbacv1helpers.NewRule("get", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie() nodePolicyRules = append(nodePolicyRules, pvcStatusPolicyRule) } if utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) { // Use the Node authorization to limit a node to create tokens for service accounts running on that node // Use the NodeRestriction admission plugin to limit a node to create tokens bound to pods on that node - tokenRequestRule := rbac.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts/token").RuleOrDie() + tokenRequestRule := rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts/token").RuleOrDie() nodePolicyRules = append(nodePolicyRules, tokenRequestRule) } // CSI if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { - volAttachRule := rbac.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie() + volAttachRule := rbacv1helpers.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie() nodePolicyRules = append(nodePolicyRules, volAttachRule) } return nodePolicyRules } // ClusterRoles returns the cluster roles to bootstrap an API server with -func ClusterRoles() []rbac.ClusterRole { - roles := []rbac.ClusterRole{ +func ClusterRoles() []rbacv1.ClusterRole { + roles := []rbacv1.ClusterRole{ { // a "root" role which can do absolutely anything ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(), - rbac.NewRule("*").URLs("*").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("*").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("*").URLs("*").RuleOrDie(), }, }, { // a role which provides just enough power to determine if the server is ready and discover API versions for negotiation ObjectMeta: metav1.ObjectMeta{Name: "system:discovery"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get").URLs( + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get").URLs( "/healthz", "/version", "/version/", // remove once swagger 1.2 support is removed "/swaggerapi", "/swaggerapi/*", @@ -192,16 +193,16 @@ func ClusterRoles() []rbac.ClusterRole { { // a role which provides minimal resource access to allow a "normal" user to learn information about themselves ObjectMeta: metav1.ObjectMeta{Name: "system:basic-user"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // TODO add future selfsubjectrulesreview, project request APIs, project listing APIs - rbac.NewRule("create").Groups(authorizationGroup).Resources("selfsubjectaccessreviews", "selfsubjectrulesreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("selfsubjectaccessreviews", "selfsubjectrulesreviews").RuleOrDie(), }, }, { // a role for a namespace level admin. It is `edit` plus the power to grant permissions to other users. ObjectMeta: metav1.ObjectMeta{Name: "admin"}, - AggregationRule: &rbac.AggregationRule{ + AggregationRule: &rbacv1.AggregationRule{ ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}}}, }, }, @@ -210,7 +211,7 @@ func ClusterRoles() []rbac.ClusterRole { // It does not grant powers for "privileged" resources which are domain of the system: `/status` // subresources or `quota`/`limits` which are used to control namespaces ObjectMeta: metav1.ObjectMeta{Name: "edit"}, - AggregationRule: &rbac.AggregationRule{ + AggregationRule: &rbacv1.AggregationRule{ ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}}}, }, }, @@ -218,45 +219,46 @@ func ClusterRoles() []rbac.ClusterRole { // a role for namespace level viewing. It grants Read-only access to non-escalating resources in // a namespace. ObjectMeta: metav1.ObjectMeta{Name: "view"}, - AggregationRule: &rbac.AggregationRule{ + AggregationRule: &rbacv1.AggregationRule{ ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}}}, }, }, { // a role for a namespace level admin. It is `edit` plus the power to grant permissions to other users. ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-admin", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", "services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(), - rbac.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(), // read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an // indicator of which namespaces you have access to. - rbac.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), - rbac.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), + rbacv1helpers.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(appsGroup).Resources("statefulsets", + rbacv1helpers.NewRule(ReadWrite...).Groups(appsGroup).Resources( + "statefulsets", "statefulsets/scale", "daemonsets", "deployments", "deployments/scale", "deployments/rollback", "replicasets", "replicasets/scale").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets", + rbacv1helpers.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale", "deployments/rollback", "ingresses", "replicasets", "replicasets/scale", "replicationcontrollers/scale", "networkpolicies").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), // additional admin powers - rbac.NewRule("create").Groups(authorizationGroup).Resources("localsubjectaccessreviews").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(rbacGroup).Resources("roles", "rolebindings").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("localsubjectaccessreviews").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(rbacGroup).Resources("roles", "rolebindings").RuleOrDie(), }, }, { @@ -264,73 +266,75 @@ func ClusterRoles() []rbac.ClusterRole { // It does not grant powers for "privileged" resources which are domain of the system: `/status` // subresources or `quota`/`limits` which are used to control namespaces ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-edit", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", "services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(), - rbac.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(), // read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an // indicator of which namespaces you have access to. - rbac.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), - rbac.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), + rbacv1helpers.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(appsGroup).Resources("statefulsets", + rbacv1helpers.NewRule(ReadWrite...).Groups(appsGroup).Resources( + "statefulsets", "statefulsets/scale", "daemonsets", "deployments", "deployments/scale", "deployments/rollback", "replicasets", "replicasets/scale").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets", + rbacv1helpers.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale", "deployments/rollback", "ingresses", "replicasets", "replicasets/scale", "replicationcontrollers/scale", "networkpolicies").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), }, }, { // a role for namespace level viewing. It grants Read-only access to non-escalating resources in // a namespace. ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-view", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(Read...).Groups(legacyGroup).Resources("pods", "replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("pods", "replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", "services", "endpoints", "persistentvolumeclaims", "configmaps").RuleOrDie(), - rbac.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(), // read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an // indicator of which namespaces you have access to. - rbac.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), - rbac.NewRule(Read...).Groups(appsGroup).Resources("statefulsets", + rbacv1helpers.NewRule(Read...).Groups(appsGroup).Resources( + "statefulsets", "statefulsets/scale", "daemonsets", "deployments", "deployments/scale", "replicasets", "replicasets/scale").RuleOrDie(), - rbac.NewRule(Read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), - rbac.NewRule(Read...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), - rbac.NewRule(Read...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale", + rbacv1helpers.NewRule(Read...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale", "ingresses", "replicasets", "replicasets/scale", "replicationcontrollers/scale", "networkpolicies").RuleOrDie(), - rbac.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule(Read...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), }, }, { // a role to use for heapster's connections back to the API server ObjectMeta: metav1.ObjectMeta{Name: "system:heapster"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(Read...).Groups(legacyGroup).Resources("events", "pods", "nodes", "namespaces").RuleOrDie(), - rbac.NewRule(Read...).Groups(extensionsGroup).Resources("deployments").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("events", "pods", "nodes", "namespaces").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(extensionsGroup).Resources("deployments").RuleOrDie(), }, }, { @@ -342,19 +346,19 @@ func ClusterRoles() []rbac.ClusterRole { // a role to use for node-problem-detector access. It does not get bound to default location since // deployment locations can reasonably vary. ObjectMeta: metav1.ObjectMeta{Name: "system:node-problem-detector"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), eventsRule(), }, }, { // a role to use for setting up a proxy ObjectMeta: metav1.ObjectMeta{Name: "system:node-proxier"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // Used to build serviceLister - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(), eventsRule(), }, @@ -362,142 +366,156 @@ func ClusterRoles() []rbac.ClusterRole { { // a role to use for full access to the kubelet API ObjectMeta: metav1.ObjectMeta{Name: "system:kubelet-api-admin"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // Allow read-only access to the Node API objects - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), // Allow all API calls to the nodes - rbac.NewRule("proxy").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("*").Groups(legacyGroup).Resources("nodes/proxy", "nodes/metrics", "nodes/spec", "nodes/stats", "nodes/log").RuleOrDie(), + rbacv1helpers.NewRule("proxy").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("*").Groups(legacyGroup).Resources("nodes/proxy", "nodes/metrics", "nodes/spec", "nodes/stats", "nodes/log").RuleOrDie(), }, }, { // a role to use for bootstrapping a node's client certificates ObjectMeta: metav1.ObjectMeta{Name: "system:node-bootstrapper"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // used to create a certificatesigningrequest for a node-specific client certificate, and watch for it to be signed - rbac.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), + rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), }, }, { // a role to use for allowing authentication and authorization delegation ObjectMeta: metav1.ObjectMeta{Name: "system:auth-delegator"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // These creates are non-mutating - rbac.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), - rbac.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), }, }, { // a role to use for the API registry, summarization, and proxy handling ObjectMeta: metav1.ObjectMeta{Name: "system:kube-aggregator"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // it needs to see all services so that it knows whether the ones it points to exist or not - rbac.NewRule(Read...).Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), }, }, { // a role to use for bootstrapping the kube-controller-manager so it can create the shared informers // service accounts, and secrets that we need to create separate identities for other controllers ObjectMeta: metav1.ObjectMeta{Name: "system:kube-controller-manager"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ eventsRule(), - rbac.NewRule("create").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(), - rbac.NewRule("delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("endpoints", "namespaces", "secrets", "serviceaccounts").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule("delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("endpoints", "namespaces", "secrets", "serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(), // Needed to check API access. These creates are non-mutating - rbac.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), // Needed for all shared informers - rbac.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(), }, }, { // a role to use for the kube-scheduler ObjectMeta: metav1.ObjectMeta{Name: "system:kube-scheduler"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ eventsRule(), // this is for leaderlease access // TODO: scope this to the kube-system namespace - rbac.NewRule("create").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), - rbac.NewRule("get", "update", "patch", "delete").Groups(legacyGroup).Resources("endpoints").Names("kube-scheduler").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get", "update", "patch", "delete").Groups(legacyGroup).Resources("endpoints").Names("kube-scheduler").RuleOrDie(), // fundamental resources - rbac.NewRule(Read...).Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("create").Groups(legacyGroup).Resources("pods/binding", "bindings").RuleOrDie(), - rbac.NewRule("patch", "update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/binding", "bindings").RuleOrDie(), + rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), // things that select pods - rbac.NewRule(Read...).Groups(legacyGroup).Resources("services", "replicationcontrollers").RuleOrDie(), - rbac.NewRule(Read...).Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), - rbac.NewRule(Read...).Groups(appsGroup).Resources("statefulsets").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services", "replicationcontrollers").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(appsGroup).Resources("statefulsets").RuleOrDie(), // things that pods use or applies to them - rbac.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule(Read...).Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(), }, }, { // a role to use for the kube-dns pod ObjectMeta: metav1.ObjectMeta{Name: "system:kube-dns"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("endpoints", "services").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("endpoints", "services").RuleOrDie(), }, }, { // a role for an external/out-of-tree persistent volume provisioner ObjectMeta: metav1.ObjectMeta{Name: "system:persistent-volume-provisioner"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), // update is needed in addition to read access for setting lock annotations on PVCs - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), - rbac.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), // Needed for watching provisioning success and failure events - rbac.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(), + rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(), eventsRule(), }, }, + { + // a role for the csi external provisioner + ObjectMeta: metav1.ObjectMeta{Name: "system:csi-external-provisioner"}, + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create", "delete", "get", "list", "watch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), + }, + }, + { + // a role for the csi external attacher + ObjectMeta: metav1.ObjectMeta{Name: "system:csi-external-attacher"}, + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), + }, + }, { ObjectMeta: metav1.ObjectMeta{Name: "system:aws-cloud-provider"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), eventsRule(), }, }, { // a role making the csrapprover controller approve a node client CSR ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:nodeclient"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/nodeclient").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/nodeclient").RuleOrDie(), }, }, { // a role making the csrapprover controller approve a node client CSR requested by the node itself ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:selfnodeclient"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeclient").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeclient").RuleOrDie(), }, }, } - if utilfeature.DefaultFeatureGate.Enabled(features.RotateKubeletServerCertificate) { - roles = append(roles, rbac.ClusterRole{ - // a role making the csrapprover controller approve a node server CSR requested by the node itself - ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:selfnodeserver"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeserver").RuleOrDie(), - }, - }) - } - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - roles = append(roles, rbac.ClusterRole{ + rules := []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + } + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + rules = append(rules, rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie()) + } + roles = append(roles, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: "system:volume-scheduler"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), - rbac.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), - }, + Rules: rules, }) } @@ -508,27 +526,27 @@ func ClusterRoles() []rbac.ClusterRole { const systemNodeRoleName = "system:node" // ClusterRoleBindings return default rolebindings to the default roles -func ClusterRoleBindings() []rbac.ClusterRoleBinding { - rolebindings := []rbac.ClusterRoleBinding{ - rbac.NewClusterBinding("cluster-admin").Groups(user.SystemPrivilegedGroup).BindingOrDie(), - rbac.NewClusterBinding("system:discovery").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(), - rbac.NewClusterBinding("system:basic-user").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(), - rbac.NewClusterBinding("system:node-proxier").Users(user.KubeProxy).BindingOrDie(), - rbac.NewClusterBinding("system:kube-controller-manager").Users(user.KubeControllerManager).BindingOrDie(), - rbac.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(), - rbac.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(), - rbac.NewClusterBinding("system:aws-cloud-provider").SAs("kube-system", "aws-cloud-provider").BindingOrDie(), +func ClusterRoleBindings() []rbacv1.ClusterRoleBinding { + rolebindings := []rbacv1.ClusterRoleBinding{ + rbacv1helpers.NewClusterBinding("cluster-admin").Groups(user.SystemPrivilegedGroup).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:discovery").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:basic-user").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:node-proxier").Users(user.KubeProxy).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:kube-controller-manager").Users(user.KubeControllerManager).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:aws-cloud-provider").SAs("kube-system", "aws-cloud-provider").BindingOrDie(), // This default binding of the system:node role to the system:nodes group is deprecated in 1.7 with the availability of the Node authorizer. // This leaves the binding, but with an empty set of subjects, so that tightening reconciliation can remove the subject. { ObjectMeta: metav1.ObjectMeta{Name: systemNodeRoleName}, - RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: systemNodeRoleName}, + RoleRef: rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: systemNodeRoleName}, }, } if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - rolebindings = append(rolebindings, rbac.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie()) + rolebindings = append(rolebindings, rbacv1helpers.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie()) } addClusterRoleBindingLabel(rolebindings) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy_test.go index 830d92576..1b024c441 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy_test.go @@ -34,8 +34,8 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" _ "k8s.io/kubernetes/pkg/apis/core/install" - "k8s.io/kubernetes/pkg/apis/rbac" _ "k8s.io/kubernetes/pkg/apis/rbac/install" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy" ) @@ -43,12 +43,12 @@ import ( // semanticRoles is a few enumerated roles for which the relationships are well established // and we want to maintain symmetric roles type semanticRoles struct { - admin *rbac.ClusterRole - edit *rbac.ClusterRole - view *rbac.ClusterRole + admin *rbacv1.ClusterRole + edit *rbacv1.ClusterRole + view *rbacv1.ClusterRole } -func getSemanticRoles(roles []rbac.ClusterRole) semanticRoles { +func getSemanticRoles(roles []rbacv1.ClusterRole) semanticRoles { ret := semanticRoles{} for i := range roles { role := roles[i] @@ -81,10 +81,10 @@ func TestCovers(t *testing.T) { // additionalAdminPowers is the list of powers that we expect to be different than the editor role. // one resource per rule to make the "does not already contain" check easy -var additionalAdminPowers = []rbac.PolicyRule{ - rbac.NewRule("create").Groups("authorization.k8s.io").Resources("localsubjectaccessreviews").RuleOrDie(), - rbac.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("rolebindings").RuleOrDie(), - rbac.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("roles").RuleOrDie(), +var additionalAdminPowers = []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create").Groups("authorization.k8s.io").Resources("localsubjectaccessreviews").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("rolebindings").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("roles").RuleOrDie(), } func TestAdminEditRelationship(t *testing.T) { @@ -92,7 +92,7 @@ func TestAdminEditRelationship(t *testing.T) { // confirm that the edit role doesn't already have extra powers for _, rule := range additionalAdminPowers { - if covers, _ := rbacregistryvalidation.Covers(semanticRoles.edit.Rules, []rbac.PolicyRule{rule}); covers { + if covers, _ := rbacregistryvalidation.Covers(semanticRoles.edit.Rules, []rbacv1.PolicyRule{rule}); covers { t.Errorf("edit has extra powers: %#v", rule) } } @@ -109,19 +109,19 @@ func TestAdminEditRelationship(t *testing.T) { // viewEscalatingNamespaceResources is the list of rules that would allow privilege escalation attacks based on // ability to view (GET) them -var viewEscalatingNamespaceResources = []rbac.PolicyRule{ - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/attach").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/proxy").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/exec").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/portforward").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("secrets").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("services/proxy").RuleOrDie(), +var viewEscalatingNamespaceResources = []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/attach").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/proxy").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/exec").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/portforward").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("secrets").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("services/proxy").RuleOrDie(), } // ungettableResources is the list of rules that don't allow to view (GET) them // this is purposefully separate list to distinguish from escalating privs -var ungettableResources = []rbac.PolicyRule{ - rbac.NewRule(bootstrappolicy.Read...).Groups("apps", "extensions").Resources("deployments/rollback").RuleOrDie(), +var ungettableResources = []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("apps", "extensions").Resources("deployments/rollback").RuleOrDie(), } func TestEditViewRelationship(t *testing.T) { @@ -143,7 +143,7 @@ func TestEditViewRelationship(t *testing.T) { // confirm that the view role doesn't already have extra powers for _, rule := range viewEscalatingNamespaceResources { - if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbac.PolicyRule{rule}); covers { + if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbacv1.PolicyRule{rule}); covers { t.Errorf("view has extra powers: %#v", rule) } } @@ -151,7 +151,7 @@ func TestEditViewRelationship(t *testing.T) { // confirm that the view role doesn't have ungettable resources for _, rule := range ungettableResources { - if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbac.PolicyRule{rule}); covers { + if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbacv1.PolicyRule{rule}); covers { t.Errorf("view has ungettable resource: %#v", rule) } } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-role-bindings.yaml b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-role-bindings.yaml index 55a883172..ab116df5f 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-role-bindings.yaml +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-role-bindings.yaml @@ -138,7 +138,6 @@ items: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:node - subjects: null - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml index 4a78d8b1c..0aee48909 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml @@ -137,6 +137,7 @@ items: - replicasets - replicasets/scale - statefulsets + - statefulsets/scale verbs: - create - delete @@ -329,6 +330,7 @@ items: - replicasets - replicasets/scale - statefulsets + - statefulsets/scale verbs: - create - delete @@ -471,6 +473,7 @@ items: - replicasets - replicasets/scale - statefulsets + - statefulsets/scale verbs: - get - list @@ -619,6 +622,103 @@ items: - certificatesigningrequests/selfnodeclient verbs: - create +- apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + creationTimestamp: null + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:csi-external-attacher + rules: + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - volumeattachments + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - list + - patch + - update + - watch +- apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + creationTimestamp: null + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:csi-external-provisioner + rules: + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - create + - delete + - get + - list + - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - list + - patch + - update + - watch - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: @@ -999,6 +1099,7 @@ items: resources: - pods/status verbs: + - patch - update - apiGroups: - "" @@ -1013,6 +1114,8 @@ items: - secrets verbs: - get + - list + - watch - apiGroups: - "" resources: @@ -1035,6 +1138,14 @@ items: - get - list - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims/status + verbs: + - get + - patch + - update - apiGroups: - storage.k8s.io resources: diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/controller-role-bindings.yaml b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/controller-role-bindings.yaml index 4bb97a4d3..6d5cb73e5 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/controller-role-bindings.yaml +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/controller-role-bindings.yaml @@ -136,6 +136,23 @@ items: - kind: ServiceAccount name: endpoint-controller namespace: kube-system +- apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + creationTimestamp: null + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:controller:expand-controller + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:controller:expand-controller + subjects: + - kind: ServiceAccount + name: expand-controller + namespace: kube-system - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/controller-roles.yaml b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/controller-roles.yaml index d70cb4936..3344def7c 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/controller-roles.yaml +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/controller-roles.yaml @@ -425,6 +425,70 @@ items: - create - patch - update +- apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + creationTimestamp: null + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:controller:expand-controller + rules: + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims/status + verbs: + - patch + - update + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - endpoints + - services + verbs: + - get + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - update - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/rbac.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/rbac.go index bb714a01a..a0f173c39 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/rbac.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/rbac.go @@ -18,18 +18,18 @@ limitations under the License. package rbac import ( + "bytes" "fmt" "github.com/golang/glog" - "bytes" - + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/labels" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/kubernetes/pkg/apis/rbac" - rbaclisters "k8s.io/kubernetes/pkg/client/listers/rbac/internalversion" + rbaclisters "k8s.io/client-go/listers/rbac/v1" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) @@ -38,12 +38,12 @@ type RequestToRuleMapper interface { // Any rule returned is still valid, since rules are deny by default. If you can pass with the rules // supplied, you do not have to fail the request. If you cannot, you should indicate the error along // with your denial. - RulesFor(subject user.Info, namespace string) ([]rbac.PolicyRule, error) + RulesFor(subject user.Info, namespace string) ([]rbacv1.PolicyRule, error) // VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace, // and each error encountered resolving those rules. Rule may be nil if err is non-nil. // If visitor() returns false, visiting is short-circuited. - VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool) + VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool) } type RBACAuthorizer struct { @@ -59,10 +59,10 @@ type authorizingVisitor struct { errors []error } -func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool { +func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool { if rule != nil && RuleAllows(v.requestAttributes, rule) { v.allowed = true - v.reason = fmt.Sprintf("allowed by %s", source.String()) + v.reason = fmt.Sprintf("RBAC: allowed by %s", source.String()) return false } if err != nil { @@ -120,7 +120,7 @@ func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (aut reason := "" if len(ruleCheckingVisitor.errors) > 0 { - reason = fmt.Sprintf("%v", utilerrors.NewAggregate(ruleCheckingVisitor.errors)) + reason = fmt.Sprintf("RBAC: %v", utilerrors.NewAggregate(ruleCheckingVisitor.errors)) } return authorizer.DecisionNoOpinion, reason, nil } @@ -164,7 +164,7 @@ func New(roles rbacregistryvalidation.RoleGetter, roleBindings rbacregistryvalid return authorizer } -func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbac.PolicyRule) bool { +func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbacv1.PolicyRule) bool { for i := range rules { if RuleAllows(requestAttributes, &rules[i]) { return true @@ -174,28 +174,28 @@ func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbac.PolicyRul return false } -func RuleAllows(requestAttributes authorizer.Attributes, rule *rbac.PolicyRule) bool { +func RuleAllows(requestAttributes authorizer.Attributes, rule *rbacv1.PolicyRule) bool { if requestAttributes.IsResourceRequest() { combinedResource := requestAttributes.GetResource() if len(requestAttributes.GetSubresource()) > 0 { combinedResource = requestAttributes.GetResource() + "/" + requestAttributes.GetSubresource() } - return rbac.VerbMatches(rule, requestAttributes.GetVerb()) && - rbac.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) && - rbac.ResourceMatches(rule, combinedResource, requestAttributes.GetSubresource()) && - rbac.ResourceNameMatches(rule, requestAttributes.GetName()) + return rbacv1helpers.VerbMatches(rule, requestAttributes.GetVerb()) && + rbacv1helpers.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) && + rbacv1helpers.ResourceMatches(rule, combinedResource, requestAttributes.GetSubresource()) && + rbacv1helpers.ResourceNameMatches(rule, requestAttributes.GetName()) } - return rbac.VerbMatches(rule, requestAttributes.GetVerb()) && - rbac.NonResourceURLMatches(rule, requestAttributes.GetPath()) + return rbacv1helpers.VerbMatches(rule, requestAttributes.GetVerb()) && + rbacv1helpers.NonResourceURLMatches(rule, requestAttributes.GetPath()) } type RoleGetter struct { Lister rbaclisters.RoleLister } -func (g *RoleGetter) GetRole(namespace, name string) (*rbac.Role, error) { +func (g *RoleGetter) GetRole(namespace, name string) (*rbacv1.Role, error) { return g.Lister.Roles(namespace).Get(name) } @@ -203,7 +203,7 @@ type RoleBindingLister struct { Lister rbaclisters.RoleBindingLister } -func (l *RoleBindingLister) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { +func (l *RoleBindingLister) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) { return l.Lister.RoleBindings(namespace).List(labels.Everything()) } @@ -211,7 +211,7 @@ type ClusterRoleGetter struct { Lister rbaclisters.ClusterRoleLister } -func (g *ClusterRoleGetter) GetClusterRole(name string) (*rbac.ClusterRole, error) { +func (g *ClusterRoleGetter) GetClusterRole(name string) (*rbacv1.ClusterRole, error) { return g.Lister.Get(name) } @@ -219,6 +219,6 @@ type ClusterRoleBindingLister struct { Lister rbaclisters.ClusterRoleBindingLister } -func (l *ClusterRoleBindingLister) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) { +func (l *ClusterRoleBindingLister) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) { return l.Lister.List(labels.Everything()) } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/rbac_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/rbac_test.go index d4425a604..1b2a8e1ef 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/rbac_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/rbac_test.go @@ -21,16 +21,17 @@ import ( "strings" "testing" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy" ) -func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbac.PolicyRule { - return rbac.PolicyRule{ +func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbacv1.PolicyRule { + return rbacv1.PolicyRule{ Verbs: strings.Split(verbs, ","), APIGroups: strings.Split(apiGroups, ","), Resources: strings.Split(resources, ","), @@ -38,12 +39,12 @@ func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbac.PolicyRul } } -func newRole(name, namespace string, rules ...rbac.PolicyRule) *rbac.Role { - return &rbac.Role{ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules} +func newRole(name, namespace string, rules ...rbacv1.PolicyRule) *rbacv1.Role { + return &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules} } -func newClusterRole(name string, rules ...rbac.PolicyRule) *rbac.ClusterRole { - return &rbac.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: name}, Rules: rules} +func newClusterRole(name string, rules ...rbacv1.PolicyRule) *rbacv1.ClusterRole { + return &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: name}, Rules: rules} } const ( @@ -51,26 +52,26 @@ const ( bindToClusterRole uint16 = 0x1 ) -func newClusterRoleBinding(roleName string, subjects ...string) *rbac.ClusterRoleBinding { - r := &rbac.ClusterRoleBinding{ +func newClusterRoleBinding(roleName string, subjects ...string) *rbacv1.ClusterRoleBinding { + r := &rbacv1.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{}, - RoleRef: rbac.RoleRef{ - APIGroup: rbac.GroupName, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, Kind: "ClusterRole", // ClusterRoleBindings can only refer to ClusterRole Name: roleName, }, } - r.Subjects = make([]rbac.Subject, len(subjects)) + r.Subjects = make([]rbacv1.Subject, len(subjects)) for i, subject := range subjects { split := strings.SplitN(subject, ":", 2) r.Subjects[i].Kind, r.Subjects[i].Name = split[0], split[1] switch r.Subjects[i].Kind { - case rbac.ServiceAccountKind: + case rbacv1.ServiceAccountKind: r.Subjects[i].APIGroup = "" - case rbac.UserKind, rbac.GroupKind: - r.Subjects[i].APIGroup = rbac.GroupName + case rbacv1.UserKind, rbacv1.GroupKind: + r.Subjects[i].APIGroup = rbacv1.GroupName default: panic(fmt.Errorf("invalid kind %s", r.Subjects[i].Kind)) } @@ -78,26 +79,26 @@ func newClusterRoleBinding(roleName string, subjects ...string) *rbac.ClusterRol return r } -func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) *rbac.RoleBinding { - r := &rbac.RoleBinding{ObjectMeta: metav1.ObjectMeta{Namespace: namespace}} +func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) *rbacv1.RoleBinding { + r := &rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Namespace: namespace}} switch bindType { case bindToRole: - r.RoleRef = rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: roleName} + r.RoleRef = rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "Role", Name: roleName} case bindToClusterRole: - r.RoleRef = rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: roleName} + r.RoleRef = rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: roleName} } - r.Subjects = make([]rbac.Subject, len(subjects)) + r.Subjects = make([]rbacv1.Subject, len(subjects)) for i, subject := range subjects { split := strings.SplitN(subject, ":", 2) r.Subjects[i].Kind, r.Subjects[i].Name = split[0], split[1] switch r.Subjects[i].Kind { - case rbac.ServiceAccountKind: + case rbacv1.ServiceAccountKind: r.Subjects[i].APIGroup = "" - case rbac.UserKind, rbac.GroupKind: - r.Subjects[i].APIGroup = rbac.GroupName + case rbacv1.UserKind, rbacv1.GroupKind: + r.Subjects[i].APIGroup = rbacv1.GroupName default: panic(fmt.Errorf("invalid kind %s", r.Subjects[i].Kind)) } @@ -136,19 +137,19 @@ func (d *defaultAttributes) GetPath() string { return "" } func TestAuthorizer(t *testing.T) { tests := []struct { - roles []*rbac.Role - roleBindings []*rbac.RoleBinding - clusterRoles []*rbac.ClusterRole - clusterRoleBindings []*rbac.ClusterRoleBinding + roles []*rbacv1.Role + roleBindings []*rbacv1.RoleBinding + clusterRoles []*rbacv1.ClusterRole + clusterRoleBindings []*rbacv1.ClusterRoleBinding shouldPass []authorizer.Attributes shouldFail []authorizer.Attributes }{ { - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "*", "*")), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, shouldPass: []authorizer.Attributes{ @@ -167,12 +168,12 @@ func TestAuthorizer(t *testing.T) { }, { // Non-resource-url tests - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("non-resource-url-getter", newRule("get", "", "", "/apis")), newClusterRole("non-resource-url", newRule("*", "", "", "/apis")), newClusterRole("non-resource-url-prefix", newRule("get", "", "", "/apis/*")), }, - clusterRoleBindings: []*rbac.ClusterRoleBinding{ + clusterRoleBindings: []*rbacv1.ClusterRoleBinding{ newClusterRoleBinding("non-resource-url-getter", "User:foo", "Group:bar"), newClusterRoleBinding("non-resource-url", "User:admin", "Group:admin"), newClusterRoleBinding("non-resource-url-prefix", "User:prefixed", "Group:prefixed"), @@ -208,10 +209,10 @@ func TestAuthorizer(t *testing.T) { }, { // test subresource resolution - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "pods", "*")), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, shouldPass: []authorizer.Attributes{ @@ -223,13 +224,13 @@ func TestAuthorizer(t *testing.T) { }, { // test subresource resolution - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "pods/status", "*"), newRule("*", "*", "*/scale", "*"), ), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, shouldPass: []authorizer.Attributes{ @@ -263,13 +264,13 @@ func TestAuthorizer(t *testing.T) { func TestRuleMatches(t *testing.T) { tests := []struct { name string - rule rbac.PolicyRule + rule rbacv1.PolicyRule requestsToExpected map[authorizer.AttributesRecord]bool }{ { name: "star verb, exact match other", - rule: rbac.NewRule("*").Groups("group1").Resources("resource1").RuleOrDie(), + rule: rbacv1helpers.NewRule("*").Groups("group1").Resources("resource1").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").New(): false, @@ -283,7 +284,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star group, exact match other", - rule: rbac.NewRule("verb1").Groups("*").Resources("resource1").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1").Groups("*").Resources("resource1").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").New(): true, @@ -297,7 +298,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star resource, exact match other", - rule: rbac.NewRule("verb1").Groups("group1").Resources("*").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1").Groups("group1").Resources("*").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").New(): false, @@ -311,7 +312,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "tuple expansion", - rule: rbac.NewRule("verb1", "verb2").Groups("group1", "group2").Resources("resource1", "resource2").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1", "verb2").Groups("group1", "group2").Resources("resource1", "resource2").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").New(): true, @@ -325,7 +326,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "subresource expansion", - rule: rbac.NewRule("*").Groups("*").Resources("resource1/subresource1").RuleOrDie(), + rule: rbacv1helpers.NewRule("*").Groups("*").Resources("resource1/subresource1").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").Subresource("subresource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").Subresource("subresource2").New(): false, @@ -339,7 +340,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star nonresource, exact match other", - rule: rbac.NewRule("verb1").URLs("*").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1").URLs("*").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ nonresourceRequest("verb1").URL("/foo").New(): true, nonresourceRequest("verb1").URL("/foo/bar").New(): true, @@ -355,7 +356,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star nonresource subpath", - rule: rbac.NewRule("verb1").URLs("/foo/*").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1").URLs("/foo/*").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ nonresourceRequest("verb1").URL("/foo").New(): false, nonresourceRequest("verb1").URL("/foo/bar").New(): true, @@ -371,7 +372,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star verb, exact nonresource", - rule: rbac.NewRule("*").URLs("/foo", "/foo/bar/one").RuleOrDie(), + rule: rbacv1helpers.NewRule("*").URLs("/foo", "/foo/bar/one").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ nonresourceRequest("verb1").URL("/foo").New(): true, nonresourceRequest("verb1").URL("/foo/bar").New(): false, @@ -441,19 +442,19 @@ func (r *requestAttributeBuilder) New() authorizer.AttributesRecord { } func BenchmarkAuthorize(b *testing.B) { - bootstrapRoles := []rbac.ClusterRole{} + bootstrapRoles := []rbacv1.ClusterRole{} bootstrapRoles = append(bootstrapRoles, bootstrappolicy.ControllerRoles()...) bootstrapRoles = append(bootstrapRoles, bootstrappolicy.ClusterRoles()...) - bootstrapBindings := []rbac.ClusterRoleBinding{} + bootstrapBindings := []rbacv1.ClusterRoleBinding{} bootstrapBindings = append(bootstrapBindings, bootstrappolicy.ClusterRoleBindings()...) bootstrapBindings = append(bootstrapBindings, bootstrappolicy.ControllerRoleBindings()...) - clusterRoles := []*rbac.ClusterRole{} + clusterRoles := []*rbacv1.ClusterRole{} for i := range bootstrapRoles { clusterRoles = append(clusterRoles, &bootstrapRoles[i]) } - clusterRoleBindings := []*rbac.ClusterRoleBinding{} + clusterRoleBindings := []*rbacv1.ClusterRoleBinding{} for i := range bootstrapBindings { clusterRoleBindings = append(clusterRoleBindings, &bootstrapBindings[i]) } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/subject_locator.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/subject_locator.go index 0f5f413b9..cdd327e5b 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/subject_locator.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/subject_locator.go @@ -18,21 +18,21 @@ limitations under the License. package rbac import ( + rbacv1 "k8s.io/api/rbac/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/kubernetes/pkg/apis/rbac" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) type RoleToRuleMapper interface { // GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namespace // of the role binding, the empty string if a cluster role binding. - GetRoleReferenceRules(roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error) + GetRoleReferenceRules(roleRef rbacv1.RoleRef, namespace string) ([]rbacv1.PolicyRule, error) } type SubjectLocator interface { - AllowedSubjects(attributes authorizer.Attributes) ([]rbac.Subject, error) + AllowedSubjects(attributes authorizer.Attributes) ([]rbacv1.Subject, error) } var _ = SubjectLocator(&SubjectAccessEvaluator{}) @@ -59,10 +59,10 @@ func NewSubjectAccessEvaluator(roles rbacregistryvalidation.RoleGetter, roleBind // AllowedSubjects returns the subjects that can perform an action and any errors encountered while computing the list. // It is possible to have both subjects and errors returned if some rolebindings couldn't be resolved, but others could be. -func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.Attributes) ([]rbac.Subject, error) { - subjects := []rbac.Subject{{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}} +func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.Attributes) ([]rbacv1.Subject, error) { + subjects := []rbacv1.Subject{{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}} if len(r.superUser) > 0 { - subjects = append(subjects, rbac.Subject{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: r.superUser}) + subjects = append(subjects, rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: r.superUser}) } errorlist := []error{} @@ -104,7 +104,7 @@ func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.At } } - dedupedSubjects := []rbac.Subject{} + dedupedSubjects := []rbacv1.Subject{} for _, subject := range subjects { found := false for _, curr := range dedupedSubjects { diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/subject_locator_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/subject_locator_test.go index 1182a28b5..d79849488 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/subject_locator_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/subject_locator_test.go @@ -20,24 +20,24 @@ import ( "reflect" "testing" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/kubernetes/pkg/apis/rbac" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) func TestSubjectLocator(t *testing.T) { type actionToSubjects struct { action authorizer.Attributes - subjects []rbac.Subject + subjects []rbacv1.Subject } tests := []struct { name string - roles []*rbac.Role - roleBindings []*rbac.RoleBinding - clusterRoles []*rbac.ClusterRole - clusterRoleBindings []*rbac.ClusterRoleBinding + roles []*rbacv1.Role + roleBindings []*rbacv1.RoleBinding + clusterRoles []*rbacv1.ClusterRole + clusterRoleBindings []*rbacv1.ClusterRoleBinding superUser string @@ -45,42 +45,42 @@ func TestSubjectLocator(t *testing.T) { }{ { name: "no super user, star matches star", - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "*", "*")), }, - clusterRoleBindings: []*rbac.ClusterRoleBinding{ + clusterRoleBindings: []*rbacv1.ClusterRoleBinding{ newClusterRoleBinding("admin", "User:super-admin", "Group:super-admins"), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, actionsToSubjects: []actionToSubjects{ { &defaultAttributes{"", "", "get", "Pods", "", "ns1", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "admins"}, }, }, { // cluster role matches star in namespace &defaultAttributes{"", "", "*", "Pods", "", "*", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, }, }, { // empty ns &defaultAttributes{"", "", "*", "Pods", "", "", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, }, }, }, @@ -88,48 +88,48 @@ func TestSubjectLocator(t *testing.T) { { name: "super user, local roles work", superUser: "foo", - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "*", "*")), }, - clusterRoleBindings: []*rbac.ClusterRoleBinding{ + clusterRoleBindings: []*rbacv1.ClusterRoleBinding{ newClusterRoleBinding("admin", "User:super-admin", "Group:super-admins"), }, - roles: []*rbac.Role{ + roles: []*rbacv1.Role{ newRole("admin", "ns1", newRule("get", "*", "Pods", "*")), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToRole, "User:admin", "Group:admins"), }, actionsToSubjects: []actionToSubjects{ { &defaultAttributes{"", "", "get", "Pods", "", "ns1", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "foo"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "foo"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "admins"}, }, }, { // verb matchies correctly &defaultAttributes{"", "", "create", "Pods", "", "ns1", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "foo"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "foo"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, }, }, { // binding only works in correct ns &defaultAttributes{"", "", "get", "Pods", "", "ns2", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "foo"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "foo"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, }, }, }, diff --git a/vendor/k8s.io/kubernetes/staging/BUILD b/vendor/k8s.io/kubernetes/staging/BUILD index 36e5a15cc..8403046c6 100644 --- a/vendor/k8s.io/kubernetes/staging/BUILD +++ b/vendor/k8s.io/kubernetes/staging/BUILD @@ -11,36 +11,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//staging/src/k8s.io/api/admission/v1beta1:all-srcs", - "//staging/src/k8s.io/api/admissionregistration/v1alpha1:all-srcs", - "//staging/src/k8s.io/api/admissionregistration/v1beta1:all-srcs", - "//staging/src/k8s.io/api/apps/v1:all-srcs", - "//staging/src/k8s.io/api/apps/v1beta1:all-srcs", - "//staging/src/k8s.io/api/apps/v1beta2:all-srcs", - "//staging/src/k8s.io/api/authentication/v1:all-srcs", - "//staging/src/k8s.io/api/authentication/v1beta1:all-srcs", - "//staging/src/k8s.io/api/authorization/v1:all-srcs", - "//staging/src/k8s.io/api/authorization/v1beta1:all-srcs", - "//staging/src/k8s.io/api/autoscaling/v1:all-srcs", - "//staging/src/k8s.io/api/autoscaling/v2beta1:all-srcs", - "//staging/src/k8s.io/api/batch/v1:all-srcs", - "//staging/src/k8s.io/api/batch/v1beta1:all-srcs", - "//staging/src/k8s.io/api/batch/v2alpha1:all-srcs", - "//staging/src/k8s.io/api/certificates/v1beta1:all-srcs", - "//staging/src/k8s.io/api/core/v1:all-srcs", - "//staging/src/k8s.io/api/events/v1beta1:all-srcs", - "//staging/src/k8s.io/api/extensions/v1beta1:all-srcs", - "//staging/src/k8s.io/api/imagepolicy/v1alpha1:all-srcs", - "//staging/src/k8s.io/api/networking/v1:all-srcs", - "//staging/src/k8s.io/api/policy/v1beta1:all-srcs", - "//staging/src/k8s.io/api/rbac/v1:all-srcs", - "//staging/src/k8s.io/api/rbac/v1alpha1:all-srcs", - "//staging/src/k8s.io/api/rbac/v1beta1:all-srcs", - "//staging/src/k8s.io/api/scheduling/v1alpha1:all-srcs", - "//staging/src/k8s.io/api/settings/v1alpha1:all-srcs", - "//staging/src/k8s.io/api/storage/v1:all-srcs", - "//staging/src/k8s.io/api/storage/v1alpha1:all-srcs", - "//staging/src/k8s.io/api/storage/v1beta1:all-srcs", + "//staging/src/k8s.io/api:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver:all-srcs", "//staging/src/k8s.io/apimachinery/pkg/api/equality:all-srcs", "//staging/src/k8s.io/apimachinery/pkg/api/errors:all-srcs", @@ -48,7 +19,6 @@ filegroup( "//staging/src/k8s.io/apimachinery/pkg/api/resource:all-srcs", "//staging/src/k8s.io/apimachinery/pkg/api/testing:all-srcs", "//staging/src/k8s.io/apimachinery/pkg/api/validation:all-srcs", - "//staging/src/k8s.io/apimachinery/pkg/apimachinery:all-srcs", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer:all-srcs", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:all-srcs", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:all-srcs", @@ -122,6 +92,7 @@ filegroup( "//staging/src/k8s.io/apiserver/pkg/util/flag:all-srcs", "//staging/src/k8s.io/apiserver/pkg/util/flushwriter:all-srcs", "//staging/src/k8s.io/apiserver/pkg/util/logs:all-srcs", + "//staging/src/k8s.io/apiserver/pkg/util/openapi:all-srcs", "//staging/src/k8s.io/apiserver/pkg/util/proxy:all-srcs", "//staging/src/k8s.io/apiserver/pkg/util/trace:all-srcs", "//staging/src/k8s.io/apiserver/pkg/util/webhook:all-srcs", @@ -129,6 +100,7 @@ filegroup( "//staging/src/k8s.io/apiserver/plugin/pkg/audit:all-srcs", "//staging/src/k8s.io/apiserver/plugin/pkg/authenticator:all-srcs", "//staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook:all-srcs", + "//staging/src/k8s.io/client-go/deprecated-dynamic:all-srcs", "//staging/src/k8s.io/client-go/discovery:all-srcs", "//staging/src/k8s.io/client-go/dynamic:all-srcs", "//staging/src/k8s.io/client-go/examples/create-update-delete-deployment:all-srcs", @@ -162,6 +134,7 @@ filegroup( "//staging/src/k8s.io/client-go/listers/rbac/v1alpha1:all-srcs", "//staging/src/k8s.io/client-go/listers/rbac/v1beta1:all-srcs", "//staging/src/k8s.io/client-go/listers/scheduling/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/listers/scheduling/v1beta1:all-srcs", "//staging/src/k8s.io/client-go/listers/settings/v1alpha1:all-srcs", "//staging/src/k8s.io/client-go/listers/storage/v1:all-srcs", "//staging/src/k8s.io/client-go/listers/storage/v1alpha1:all-srcs", @@ -170,6 +143,7 @@ filegroup( "//staging/src/k8s.io/client-go/pkg/version:all-srcs", "//staging/src/k8s.io/client-go/plugin/pkg/client/auth:all-srcs", "//staging/src/k8s.io/client-go/rest:all-srcs", + "//staging/src/k8s.io/client-go/restmapper:all-srcs", "//staging/src/k8s.io/client-go/scale:all-srcs", "//staging/src/k8s.io/client-go/testing:all-srcs", "//staging/src/k8s.io/client-go/third_party/forked/golang/template:all-srcs", @@ -189,6 +163,7 @@ filegroup( "//staging/src/k8s.io/client-go/util/buffer:all-srcs", "//staging/src/k8s.io/client-go/util/cert:all-srcs", "//staging/src/k8s.io/client-go/util/certificate:all-srcs", + "//staging/src/k8s.io/client-go/util/connrotation:all-srcs", "//staging/src/k8s.io/client-go/util/exec:all-srcs", "//staging/src/k8s.io/client-go/util/flowcontrol:all-srcs", "//staging/src/k8s.io/client-go/util/homedir:all-srcs", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/BUILD new file mode 100644 index 000000000..334629466 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/BUILD @@ -0,0 +1,93 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_test") + +go_test( + name = "go_default_test", + srcs = ["roundtrip_test.go"], + deps = [ + "//vendor/k8s.io/api/admission/v1beta1:go_default_library", + "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", + "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", + "//vendor/k8s.io/api/apps/v1beta1:go_default_library", + "//vendor/k8s.io/api/apps/v1beta2:go_default_library", + "//vendor/k8s.io/api/authentication/v1:go_default_library", + "//vendor/k8s.io/api/authentication/v1beta1:go_default_library", + "//vendor/k8s.io/api/authorization/v1:go_default_library", + "//vendor/k8s.io/api/authorization/v1beta1:go_default_library", + "//vendor/k8s.io/api/autoscaling/v1:go_default_library", + "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", + "//vendor/k8s.io/api/batch/v1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", + "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", + "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/events/v1beta1:go_default_library", + "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", + "//vendor/k8s.io/api/imagepolicy/v1alpha1:go_default_library", + "//vendor/k8s.io/api/networking/v1:go_default_library", + "//vendor/k8s.io/api/policy/v1beta1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", + "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", + "//vendor/k8s.io/api/storage/v1:go_default_library", + "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", + "//vendor/k8s.io/api/storage/v1beta1: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/fuzzer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/api/admission/v1beta1:all-srcs", + "//staging/src/k8s.io/api/admissionregistration/v1alpha1:all-srcs", + "//staging/src/k8s.io/api/admissionregistration/v1beta1:all-srcs", + "//staging/src/k8s.io/api/apps/v1:all-srcs", + "//staging/src/k8s.io/api/apps/v1beta1:all-srcs", + "//staging/src/k8s.io/api/apps/v1beta2:all-srcs", + "//staging/src/k8s.io/api/authentication/v1:all-srcs", + "//staging/src/k8s.io/api/authentication/v1beta1:all-srcs", + "//staging/src/k8s.io/api/authorization/v1:all-srcs", + "//staging/src/k8s.io/api/authorization/v1beta1:all-srcs", + "//staging/src/k8s.io/api/autoscaling/v1:all-srcs", + "//staging/src/k8s.io/api/autoscaling/v2beta1:all-srcs", + "//staging/src/k8s.io/api/batch/v1:all-srcs", + "//staging/src/k8s.io/api/batch/v1beta1:all-srcs", + "//staging/src/k8s.io/api/batch/v2alpha1:all-srcs", + "//staging/src/k8s.io/api/certificates/v1beta1:all-srcs", + "//staging/src/k8s.io/api/core/v1:all-srcs", + "//staging/src/k8s.io/api/events/v1beta1:all-srcs", + "//staging/src/k8s.io/api/extensions/v1beta1:all-srcs", + "//staging/src/k8s.io/api/imagepolicy/v1alpha1:all-srcs", + "//staging/src/k8s.io/api/networking/v1:all-srcs", + "//staging/src/k8s.io/api/policy/v1beta1:all-srcs", + "//staging/src/k8s.io/api/rbac/v1:all-srcs", + "//staging/src/k8s.io/api/rbac/v1alpha1:all-srcs", + "//staging/src/k8s.io/api/rbac/v1beta1:all-srcs", + "//staging/src/k8s.io/api/scheduling/v1alpha1:all-srcs", + "//staging/src/k8s.io/api/scheduling/v1beta1:all-srcs", + "//staging/src/k8s.io/api/settings/v1alpha1:all-srcs", + "//staging/src/k8s.io/api/storage/v1:all-srcs", + "//staging/src/k8s.io/api/storage/v1alpha1:all-srcs", + "//staging/src/k8s.io/api/storage/v1beta1:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/Godeps/Godeps.json index f4c868f18..284ccea51 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/Godeps/Godeps.json @@ -1,11 +1,19 @@ { "ImportPath": "k8s.io/api", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], "Deps": [ + { + "ImportPath": "github.com/davecgh/go-spew/spew", + "Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8" + }, + { + "ImportPath": "github.com/ghodss/yaml", + "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" + }, { "ImportPath": "github.com/gogo/protobuf/proto", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" @@ -18,10 +26,26 @@ "ImportPath": "github.com/golang/glog", "Rev": "44145f04b68cf362d9c4df2182967c2275eaefed" }, + { + "ImportPath": "github.com/golang/protobuf/proto", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, { "ImportPath": "github.com/google/gofuzz", "Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c" }, + { + "ImportPath": "github.com/json-iterator/go", + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" + }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, { "ImportPath": "github.com/spf13/pflag", "Rev": "583c0c0531f06d5278b7d917446061adc344b5cd" @@ -62,10 +86,46 @@ "ImportPath": "gopkg.in/inf.v0", "Rev": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" }, + { + "ImportPath": "gopkg.in/yaml.v2", + "Rev": "670d4cfef0544295bc27a114dbac37980d83185a" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/equality", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/meta", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/api/resource", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/testing", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/conversion", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -90,6 +150,26 @@ "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/selection", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -98,10 +178,18 @@ "ImportPath": "k8s.io/apimachinery/pkg/types", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/diff", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/util/errors", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/framer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/util/intstr", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -134,6 +222,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/util/wait", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/yaml", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/watch", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -146,6 +238,18 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/resource", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -158,6 +262,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/types", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/generated.pb.go index f56a0f063..dc257afac 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1157,52 +1157,51 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 739 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcd, 0x4e, 0xdb, 0x4a, - 0x14, 0x8e, 0x21, 0x7f, 0x9e, 0xa0, 0x0b, 0xcc, 0xdd, 0x58, 0xd1, 0x95, 0xc3, 0x65, 0x71, 0xc5, - 0x95, 0x60, 0x5c, 0x68, 0x8b, 0x50, 0xd5, 0x0d, 0x16, 0xa8, 0x42, 0x95, 0x00, 0x0d, 0xa4, 0x6a, - 0xbb, 0xa8, 0x34, 0x71, 0x86, 0x64, 0x9a, 0xd8, 0xe3, 0x7a, 0xc6, 0xa1, 0xec, 0xfa, 0x08, 0x7d, - 0x93, 0x3e, 0x44, 0x37, 0x2c, 0x59, 0xb2, 0x8a, 0x4a, 0xfa, 0x00, 0xdd, 0xb3, 0xaa, 0x3c, 0x1e, - 0xc7, 0x29, 0x34, 0x2d, 0xad, 0xba, 0xca, 0x9c, 0x73, 0xbe, 0xef, 0x3b, 0xf1, 0x77, 0xce, 0x0c, - 0xd8, 0xed, 0x6d, 0x09, 0xc4, 0xb8, 0xd3, 0x8b, 0x5b, 0x34, 0x0a, 0xa8, 0xa4, 0xc2, 0x19, 0xd0, - 0xa0, 0xcd, 0x23, 0x47, 0x17, 0x48, 0xc8, 0x1c, 0xd2, 0xf6, 0x99, 0x10, 0x8c, 0x07, 0xce, 0x60, - 0xbd, 0x45, 0x25, 0x59, 0x77, 0x3a, 0x34, 0xa0, 0x11, 0x91, 0xb4, 0x8d, 0xc2, 0x88, 0x4b, 0x0e, - 0xff, 0x49, 0xd1, 0x88, 0x84, 0x0c, 0x8d, 0xd1, 0x48, 0xa3, 0xeb, 0x6b, 0x1d, 0x26, 0xbb, 0x71, - 0x0b, 0x79, 0xdc, 0x77, 0x3a, 0xbc, 0xc3, 0x1d, 0x45, 0x6a, 0xc5, 0x27, 0x2a, 0x52, 0x81, 0x3a, - 0xa5, 0x62, 0xf5, 0xd5, 0xc9, 0xd6, 0xb1, 0xec, 0xd2, 0x40, 0x32, 0x8f, 0xc8, 0xb4, 0xff, 0xcd, - 0xd6, 0xf5, 0x07, 0x39, 0xda, 0x27, 0x5e, 0x97, 0x05, 0x34, 0x3a, 0x73, 0xc2, 0x5e, 0x27, 0x49, - 0x08, 0xc7, 0xa7, 0x92, 0x7c, 0x8f, 0xe5, 0x4c, 0x63, 0x45, 0x71, 0x20, 0x99, 0x4f, 0x6f, 0x11, - 0x36, 0x7f, 0x46, 0x10, 0x5e, 0x97, 0xfa, 0xe4, 0x16, 0xef, 0xfe, 0x34, 0x5e, 0x2c, 0x59, 0xdf, - 0x61, 0x81, 0x14, 0x32, 0xba, 0x49, 0x5a, 0xfe, 0x52, 0x02, 0x0b, 0xdb, 0x99, 0x8d, 0x98, 0xbe, - 0x89, 0xa9, 0x90, 0xd0, 0x05, 0xb3, 0x31, 0x6b, 0x5b, 0xc6, 0x92, 0xb1, 0x62, 0xba, 0xf7, 0xce, - 0x87, 0x8d, 0xc2, 0x68, 0xd8, 0x98, 0x6d, 0xee, 0xed, 0x5c, 0x0f, 0x1b, 0xff, 0x4e, 0xeb, 0x22, - 0xcf, 0x42, 0x2a, 0x50, 0x73, 0x6f, 0x07, 0x27, 0x64, 0xf8, 0x1c, 0x14, 0x7b, 0x2c, 0x68, 0x5b, - 0x33, 0x4b, 0xc6, 0x4a, 0x6d, 0x63, 0x13, 0xe5, 0x63, 0x1b, 0xd3, 0x50, 0xd8, 0xeb, 0x24, 0x09, - 0x81, 0x12, 0xef, 0xd0, 0x60, 0x1d, 0x3d, 0x89, 0x78, 0x1c, 0x3e, 0xa3, 0x51, 0xf2, 0x67, 0x9e, - 0xb2, 0xa0, 0xed, 0xce, 0xe9, 0xe6, 0xc5, 0x24, 0xc2, 0x4a, 0x11, 0x76, 0x41, 0x35, 0xa2, 0x82, - 0xc7, 0x91, 0x47, 0xad, 0x59, 0xa5, 0xfe, 0xe8, 0xd7, 0xd5, 0xb1, 0x56, 0x70, 0x17, 0x74, 0x87, - 0x6a, 0x96, 0xc1, 0x63, 0x75, 0xf8, 0x10, 0xd4, 0x44, 0xdc, 0xca, 0x0a, 0x56, 0x51, 0xf9, 0xf1, - 0xb7, 0x26, 0xd4, 0x8e, 0xf2, 0x12, 0x9e, 0xc4, 0xc1, 0x25, 0x50, 0x0c, 0x88, 0x4f, 0xad, 0x92, - 0xc2, 0x8f, 0x3f, 0x61, 0x9f, 0xf8, 0x14, 0xab, 0x0a, 0x74, 0x80, 0x99, 0xfc, 0x8a, 0x90, 0x78, - 0xd4, 0x2a, 0x2b, 0xd8, 0xa2, 0x86, 0x99, 0xfb, 0x59, 0x01, 0xe7, 0x18, 0xf8, 0x18, 0x98, 0x3c, - 0x4c, 0x06, 0xc7, 0x78, 0x60, 0x55, 0x14, 0xc1, 0xce, 0x08, 0x07, 0x59, 0xe1, 0x7a, 0x32, 0xc0, - 0x39, 0x01, 0x1e, 0x83, 0x6a, 0x2c, 0x68, 0xb4, 0x17, 0x9c, 0x70, 0xab, 0xaa, 0x1c, 0xfb, 0x0f, - 0x4d, 0x5e, 0xa3, 0x6f, 0x36, 0x3f, 0x71, 0xaa, 0xa9, 0xd1, 0xb9, 0x3b, 0x59, 0x06, 0x8f, 0x95, - 0x60, 0x13, 0x94, 0x79, 0xeb, 0x35, 0xf5, 0xa4, 0x65, 0x2a, 0xcd, 0xb5, 0xa9, 0x53, 0xd0, 0x8b, - 0x8b, 0x30, 0x39, 0xdd, 0x7d, 0x2b, 0x69, 0x90, 0x0c, 0xc0, 0xfd, 0x4b, 0x4b, 0x97, 0x0f, 0x94, - 0x08, 0xd6, 0x62, 0xf0, 0x15, 0x30, 0x79, 0xbf, 0x9d, 0x26, 0x2d, 0xf0, 0x3b, 0xca, 0x63, 0x2b, - 0x0f, 0x32, 0x1d, 0x9c, 0x4b, 0x2e, 0x7f, 0x98, 0x01, 0x8b, 0x13, 0x1b, 0x2f, 0x42, 0x1e, 0x08, - 0xfa, 0x47, 0x56, 0xfe, 0x7f, 0x50, 0x21, 0xfd, 0x3e, 0x3f, 0xa5, 0xe9, 0xd6, 0x57, 0xdd, 0x79, - 0xad, 0x53, 0xd9, 0x4e, 0xd3, 0x38, 0xab, 0xc3, 0x43, 0x50, 0x16, 0x92, 0xc8, 0x58, 0xe8, 0x0d, - 0x5e, 0xbd, 0xdb, 0x06, 0x1f, 0x29, 0x8e, 0x0b, 0x12, 0xdb, 0x30, 0x15, 0x71, 0x5f, 0x62, 0xad, - 0x03, 0x1b, 0xa0, 0x14, 0x12, 0xe9, 0x75, 0xd5, 0x96, 0xce, 0xb9, 0xe6, 0x68, 0xd8, 0x28, 0x1d, - 0x26, 0x09, 0x9c, 0xe6, 0xe1, 0x16, 0x30, 0xd5, 0xe1, 0xf8, 0x2c, 0xcc, 0x56, 0xb3, 0x9e, 0x98, - 0x74, 0x98, 0x25, 0xaf, 0x27, 0x03, 0x9c, 0x83, 0x97, 0x3f, 0x1a, 0x60, 0x7e, 0xc2, 0xb1, 0x01, - 0xa3, 0xa7, 0xb0, 0x09, 0x2a, 0x51, 0xfa, 0x5a, 0x28, 0xcf, 0x6a, 0x1b, 0x08, 0xfd, 0xe8, 0x61, - 0x46, 0x37, 0xdf, 0x18, 0xb7, 0x96, 0xf8, 0xa2, 0x03, 0x9c, 0x69, 0xc1, 0x17, 0xea, 0x6e, 0xab, - 0x91, 0xe8, 0x97, 0xc3, 0xb9, 0xb3, 0x6e, 0x4a, 0x73, 0xe7, 0xf4, 0x65, 0x56, 0x11, 0x1e, 0xcb, - 0xb9, 0x6b, 0xe7, 0x57, 0x76, 0xe1, 0xe2, 0xca, 0x2e, 0x5c, 0x5e, 0xd9, 0x85, 0x77, 0x23, 0xdb, - 0x38, 0x1f, 0xd9, 0xc6, 0xc5, 0xc8, 0x36, 0x2e, 0x47, 0xb6, 0xf1, 0x69, 0x64, 0x1b, 0xef, 0x3f, - 0xdb, 0x85, 0x97, 0x15, 0x2d, 0xfc, 0x35, 0x00, 0x00, 0xff, 0xff, 0x76, 0x21, 0xd5, 0x35, 0xaf, - 0x06, 0x00, 0x00, + // 728 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x4f, 0xdb, 0x48, + 0x14, 0x8f, 0x21, 0xff, 0x3c, 0x41, 0x0b, 0xcc, 0x5e, 0xac, 0x68, 0xe5, 0xb0, 0x1c, 0x56, 0xac, + 0x04, 0xe3, 0x05, 0xed, 0x22, 0xb4, 0xda, 0x0b, 0x16, 0x68, 0x85, 0x56, 0x02, 0x34, 0x90, 0x55, + 0xdb, 0x43, 0xa5, 0x89, 0xf3, 0x48, 0xdc, 0xc4, 0x1e, 0xd7, 0x33, 0x0e, 0xe5, 0xd6, 0x8f, 0xd0, + 0x6f, 0xd2, 0x0f, 0xd1, 0x0b, 0x47, 0x8e, 0x9c, 0xa2, 0x92, 0x7e, 0x80, 0xde, 0x39, 0x55, 0x1e, + 0x8f, 0xe3, 0x94, 0x96, 0x96, 0x56, 0x3d, 0x65, 0xde, 0x7b, 0xbf, 0xdf, 0xef, 0xc5, 0xbf, 0xf7, + 0x66, 0xd0, 0xfe, 0x60, 0x47, 0x10, 0x9f, 0x3b, 0x83, 0xa4, 0x03, 0x71, 0x08, 0x12, 0x84, 0x33, + 0x82, 0xb0, 0xcb, 0x63, 0x47, 0x17, 0x58, 0xe4, 0x3b, 0xac, 0x1b, 0xf8, 0x42, 0xf8, 0x3c, 0x74, + 0x46, 0x9b, 0x1d, 0x90, 0x6c, 0xd3, 0xe9, 0x41, 0x08, 0x31, 0x93, 0xd0, 0x25, 0x51, 0xcc, 0x25, + 0xc7, 0xbf, 0x64, 0x68, 0xc2, 0x22, 0x9f, 0x4c, 0xd1, 0x44, 0xa3, 0x9b, 0x1b, 0x3d, 0x5f, 0xf6, + 0x93, 0x0e, 0xf1, 0x78, 0xe0, 0xf4, 0x78, 0x8f, 0x3b, 0x8a, 0xd4, 0x49, 0xce, 0x54, 0xa4, 0x02, + 0x75, 0xca, 0xc4, 0x9a, 0xeb, 0xb3, 0xad, 0x13, 0xd9, 0x87, 0x50, 0xfa, 0x1e, 0x93, 0x59, 0xff, + 0xbb, 0xad, 0x9b, 0x7f, 0x16, 0xe8, 0x80, 0x79, 0x7d, 0x3f, 0x84, 0xf8, 0xc2, 0x89, 0x06, 0xbd, + 0x34, 0x21, 0x9c, 0x00, 0x24, 0xfb, 0x1c, 0xcb, 0xb9, 0x8f, 0x15, 0x27, 0xa1, 0xf4, 0x03, 0xf8, + 0x84, 0xb0, 0xfd, 0x35, 0x82, 0xf0, 0xfa, 0x10, 0xb0, 0xbb, 0xbc, 0xd5, 0xf7, 0x15, 0xb4, 0xb4, + 0x9b, 0x3b, 0x42, 0xe1, 0x79, 0x02, 0x42, 0x62, 0x17, 0xcd, 0x27, 0x7e, 0xd7, 0x32, 0x56, 0x8c, + 0x35, 0xd3, 0xfd, 0xe3, 0x72, 0xdc, 0x2a, 0x4d, 0xc6, 0xad, 0xf9, 0xf6, 0xc1, 0xde, 0xed, 0xb8, + 0xf5, 0xeb, 0x7d, 0x8d, 0xe4, 0x45, 0x04, 0x82, 0xb4, 0x0f, 0xf6, 0x68, 0x4a, 0xc6, 0x8f, 0x50, + 0x79, 0xe0, 0x87, 0x5d, 0x6b, 0x6e, 0xc5, 0x58, 0x6b, 0x6c, 0x6d, 0x93, 0x62, 0x02, 0x53, 0x1a, + 0x89, 0x06, 0xbd, 0x34, 0x21, 0x48, 0x6a, 0x03, 0x19, 0x6d, 0x92, 0x7f, 0x63, 0x9e, 0x44, 0xff, + 0x43, 0x9c, 0xfe, 0x99, 0xff, 0xfc, 0xb0, 0xeb, 0x2e, 0xe8, 0xe6, 0xe5, 0x34, 0xa2, 0x4a, 0x11, + 0xf7, 0x51, 0x3d, 0x06, 0xc1, 0x93, 0xd8, 0x03, 0x6b, 0x5e, 0xa9, 0xff, 0xfd, 0xed, 0xea, 0x54, + 0x2b, 0xb8, 0x4b, 0xba, 0x43, 0x3d, 0xcf, 0xd0, 0xa9, 0x3a, 0xfe, 0x0b, 0x35, 0x44, 0xd2, 0xc9, + 0x0b, 0x56, 0x59, 0xf9, 0xf1, 0xb3, 0x26, 0x34, 0x4e, 0x8a, 0x12, 0x9d, 0xc5, 0xe1, 0x15, 0x54, + 0x0e, 0x59, 0x00, 0x56, 0x45, 0xe1, 0xa7, 0x9f, 0x70, 0xc8, 0x02, 0xa0, 0xaa, 0x82, 0x1d, 0x64, + 0xa6, 0xbf, 0x22, 0x62, 0x1e, 0x58, 0x55, 0x05, 0x5b, 0xd6, 0x30, 0xf3, 0x30, 0x2f, 0xd0, 0x02, + 0x83, 0xff, 0x41, 0x26, 0x8f, 0xd2, 0xc1, 0xf9, 0x3c, 0xb4, 0x6a, 0x8a, 0x60, 0xe7, 0x84, 0xa3, + 0xbc, 0x70, 0x3b, 0x1b, 0xd0, 0x82, 0x80, 0x4f, 0x51, 0x3d, 0x11, 0x10, 0x1f, 0x84, 0x67, 0xdc, + 0xaa, 0x2b, 0xc7, 0x7e, 0x23, 0xb3, 0x37, 0xe2, 0xa3, 0x25, 0x4e, 0x9d, 0x6a, 0x6b, 0x74, 0xe1, + 0x4e, 0x9e, 0xa1, 0x53, 0x25, 0xdc, 0x46, 0x55, 0xde, 0x79, 0x06, 0x9e, 0xb4, 0x4c, 0xa5, 0xb9, + 0x71, 0xef, 0x14, 0xf4, 0x0e, 0x12, 0xca, 0xce, 0xf7, 0x5f, 0x48, 0x08, 0xd3, 0x01, 0xb8, 0x3f, + 0x69, 0xe9, 0xea, 0x91, 0x12, 0xa1, 0x5a, 0x0c, 0x3f, 0x45, 0x26, 0x1f, 0x76, 0xb3, 0xa4, 0x85, + 0xbe, 0x47, 0x79, 0x6a, 0xe5, 0x51, 0xae, 0x43, 0x0b, 0xc9, 0xd5, 0xd7, 0x73, 0x68, 0x79, 0x66, + 0xe3, 0x45, 0xc4, 0x43, 0x01, 0x3f, 0x64, 0xe5, 0x7f, 0x47, 0x35, 0x36, 0x1c, 0xf2, 0x73, 0xc8, + 0xb6, 0xbe, 0xee, 0x2e, 0x6a, 0x9d, 0xda, 0x6e, 0x96, 0xa6, 0x79, 0x1d, 0x1f, 0xa3, 0xaa, 0x90, + 0x4c, 0x26, 0x42, 0x6f, 0xf0, 0xfa, 0xc3, 0x36, 0xf8, 0x44, 0x71, 0x5c, 0x94, 0xda, 0x46, 0x41, + 0x24, 0x43, 0x49, 0xb5, 0x0e, 0x6e, 0xa1, 0x4a, 0xc4, 0xa4, 0xd7, 0x57, 0x5b, 0xba, 0xe0, 0x9a, + 0x93, 0x71, 0xab, 0x72, 0x9c, 0x26, 0x68, 0x96, 0xc7, 0x3b, 0xc8, 0x54, 0x87, 0xd3, 0x8b, 0x28, + 0x5f, 0xcd, 0x66, 0x6a, 0xd2, 0x71, 0x9e, 0xbc, 0x9d, 0x0d, 0x68, 0x01, 0x5e, 0x7d, 0x63, 0xa0, + 0xc5, 0x19, 0xc7, 0x46, 0x3e, 0x9c, 0xe3, 0x36, 0xaa, 0xc5, 0xd9, 0x6b, 0xa1, 0x3c, 0x6b, 0x6c, + 0x11, 0xf2, 0xa5, 0x37, 0x96, 0xdc, 0x7d, 0x63, 0xdc, 0x46, 0xea, 0x8b, 0x0e, 0x68, 0xae, 0x85, + 0x1f, 0xab, 0xbb, 0xad, 0x46, 0xa2, 0x5f, 0x0e, 0xe7, 0xc1, 0xba, 0x19, 0xcd, 0x5d, 0xd0, 0x97, + 0x59, 0x45, 0x74, 0x2a, 0xe7, 0x6e, 0x5c, 0xde, 0xd8, 0xa5, 0xab, 0x1b, 0xbb, 0x74, 0x7d, 0x63, + 0x97, 0x5e, 0x4e, 0x6c, 0xe3, 0x72, 0x62, 0x1b, 0x57, 0x13, 0xdb, 0xb8, 0x9e, 0xd8, 0xc6, 0xdb, + 0x89, 0x6d, 0xbc, 0x7a, 0x67, 0x97, 0x9e, 0xd4, 0xb4, 0xf0, 0x87, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xb6, 0xe9, 0xbc, 0x6f, 0x7a, 0x06, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/generated.proto index a4e4ca266..dfc7f4474 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/api/authentication/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go index 1f5313517..c22e3f63c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AdmissionRequest = map[string]string{ "": "AdmissionRequest describes the admission.Attributes for the admission request.", "uid": "UID is an identifier for the individual request/response. It allows us to distinguish instances of requests which are otherwise identical (parallel requests, requests when earlier requests did not modify etc) The UID is meant to track the round trip (request/response) between the KAS and the WebHook, not the user request. It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging.", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go index fc60e1909..e3bcc03a1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admission/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/generated.pb.go index f5d4941d3..b87f74e52 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -989,40 +989,39 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 545 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x51, 0x4d, 0x8b, 0x13, 0x3f, - 0x18, 0x6f, 0xfe, 0xdb, 0x42, 0x9b, 0x76, 0xf9, 0xcb, 0xe0, 0xa1, 0x14, 0x99, 0x96, 0x9e, 0x2a, - 0x62, 0x62, 0x57, 0x59, 0xbc, 0xee, 0xec, 0x41, 0x0a, 0xbe, 0x2c, 0x41, 0x3c, 0x88, 0x07, 0xd3, - 0xf6, 0xd9, 0x69, 0x6c, 0x27, 0x19, 0x92, 0x4c, 0x41, 0x4f, 0x5e, 0xbc, 0x0b, 0x7e, 0xa9, 0x1e, - 0xf7, 0xb8, 0xa7, 0x62, 0x47, 0xf0, 0xe8, 0x67, 0x90, 0x99, 0xe9, 0xec, 0xcc, 0x5a, 0x8b, 0xab, - 0xb7, 0x3c, 0xbf, 0x27, 0xbf, 0xb7, 0x04, 0xb3, 0xf9, 0x63, 0x43, 0x84, 0xa2, 0xf3, 0x68, 0x0c, - 0x5a, 0x82, 0x05, 0x43, 0x97, 0x20, 0xa7, 0x4a, 0xd3, 0xed, 0x82, 0x87, 0x82, 0xf2, 0x69, 0x20, - 0x8c, 0x11, 0x4a, 0x6a, 0xf0, 0x85, 0xb1, 0x9a, 0x5b, 0xa1, 0x24, 0x5d, 0x0e, 0xf9, 0x22, 0x9c, - 0xf1, 0x21, 0xf5, 0x41, 0x82, 0xe6, 0x16, 0xa6, 0x24, 0xd4, 0xca, 0x2a, 0xe7, 0x6e, 0x46, 0x25, - 0x3c, 0x14, 0xe4, 0xb7, 0x54, 0x92, 0x53, 0x3b, 0xf7, 0x7d, 0x61, 0x67, 0xd1, 0x98, 0x4c, 0x54, - 0x40, 0x7d, 0xe5, 0x2b, 0x9a, 0x2a, 0x8c, 0xa3, 0xf3, 0x74, 0x4a, 0x87, 0xf4, 0x94, 0x29, 0x77, - 0x1e, 0x15, 0xa1, 0x02, 0x3e, 0x99, 0x09, 0x09, 0xfa, 0x3d, 0x0d, 0xe7, 0x7e, 0x02, 0x18, 0x1a, - 0x80, 0xe5, 0x74, 0xb9, 0x93, 0xa7, 0x43, 0xf7, 0xb1, 0x74, 0x24, 0xad, 0x08, 0x60, 0x87, 0x70, - 0xfc, 0x27, 0x82, 0x99, 0xcc, 0x20, 0xe0, 0x3b, 0xbc, 0x87, 0xfb, 0x78, 0x91, 0x15, 0x0b, 0x2a, - 0xa4, 0x35, 0x56, 0xff, 0x4a, 0xea, 0x7f, 0x42, 0xb8, 0x39, 0x92, 0xc2, 0x0a, 0xbe, 0x10, 0x1f, - 0x40, 0x3b, 0x3d, 0x5c, 0x95, 0x3c, 0x80, 0x36, 0xea, 0xa1, 0x41, 0xc3, 0x6b, 0xad, 0xd6, 0xdd, - 0x4a, 0xbc, 0xee, 0x56, 0x9f, 0xf3, 0x00, 0x58, 0xba, 0x71, 0x5e, 0xe2, 0x9a, 0x8e, 0x16, 0x60, - 0xda, 0xff, 0xf5, 0x0e, 0x06, 0xcd, 0x23, 0x4a, 0x6e, 0xfc, 0xde, 0x84, 0x45, 0x0b, 0xf0, 0x0e, - 0xb7, 0x9a, 0xb5, 0x64, 0x32, 0x2c, 0x13, 0xeb, 0xff, 0x40, 0xb8, 0x5d, 0xca, 0x71, 0xaa, 0xe4, - 0xb9, 0xf0, 0xa3, 0x4c, 0xc0, 0x79, 0x8b, 0xeb, 0xc9, 0xeb, 0x4e, 0xb9, 0xe5, 0x69, 0xb0, 0xe6, - 0xd1, 0x83, 0x92, 0xeb, 0x55, 0x59, 0x12, 0xce, 0xfd, 0x04, 0x30, 0x24, 0xb9, 0x4d, 0x96, 0x43, - 0xf2, 0x62, 0xfc, 0x0e, 0x26, 0xf6, 0x19, 0x58, 0xee, 0x39, 0x5b, 0x5b, 0x5c, 0x60, 0xec, 0x4a, - 0xd5, 0x09, 0x71, 0x4b, 0x14, 0xee, 0x79, 0xb7, 0xe3, 0xbf, 0xe8, 0x56, 0x0a, 0xef, 0xdd, 0xde, - 0x7a, 0xb5, 0x4a, 0xa0, 0x61, 0xd7, 0x1c, 0xfa, 0xdf, 0x11, 0xbe, 0xb3, 0xaf, 0xf0, 0x53, 0x61, - 0xac, 0xf3, 0x66, 0xa7, 0x34, 0xb9, 0x59, 0xe9, 0x84, 0x9d, 0x56, 0xbe, 0xb5, 0x8d, 0x51, 0xcf, - 0x91, 0x52, 0xe1, 0x19, 0xae, 0x09, 0x0b, 0x41, 0xde, 0xf4, 0xf4, 0xdf, 0x9a, 0x5e, 0x4b, 0x5d, - 0xfc, 0xec, 0x28, 0x51, 0x66, 0x99, 0x41, 0xff, 0x0b, 0xc2, 0xd5, 0xe4, 0xab, 0x9d, 0x7b, 0xb8, - 0xc1, 0x43, 0xf1, 0x44, 0xab, 0x28, 0x34, 0x6d, 0xd4, 0x3b, 0x18, 0x34, 0xbc, 0xc3, 0x78, 0xdd, - 0x6d, 0x9c, 0x9c, 0x8d, 0x32, 0x90, 0x15, 0x7b, 0x67, 0x88, 0x9b, 0x3c, 0x14, 0xaf, 0x40, 0x27, - 0x39, 0xb2, 0x94, 0x0d, 0xef, 0xff, 0x78, 0xdd, 0x6d, 0x9e, 0x9c, 0x8d, 0x72, 0x98, 0x95, 0xef, - 0x24, 0xfa, 0x1a, 0x8c, 0x8a, 0xf4, 0x04, 0x4c, 0xfb, 0xa0, 0xd0, 0x67, 0x39, 0xc8, 0x8a, 0xbd, - 0x47, 0x56, 0x1b, 0xb7, 0x72, 0xb1, 0x71, 0x2b, 0x97, 0x1b, 0xb7, 0xf2, 0x31, 0x76, 0xd1, 0x2a, - 0x76, 0xd1, 0x45, 0xec, 0xa2, 0xcb, 0xd8, 0x45, 0x5f, 0x63, 0x17, 0x7d, 0xfe, 0xe6, 0x56, 0x5e, - 0xd7, 0xf3, 0xd2, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x1d, 0xfb, 0x23, 0x89, 0xaa, 0x04, 0x00, - 0x00, + // 531 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x51, 0x4d, 0x8b, 0x13, 0x31, + 0x18, 0x6e, 0x6c, 0x0b, 0x6d, 0xda, 0x45, 0x19, 0x3c, 0x94, 0x22, 0xd3, 0xd2, 0x53, 0x45, 0x4c, + 0xec, 0x22, 0x8b, 0xd7, 0x9d, 0x3d, 0x48, 0xc1, 0x8f, 0x25, 0x88, 0x07, 0xf1, 0x60, 0xda, 0xbe, + 0x3b, 0x8d, 0xed, 0x4c, 0x86, 0x24, 0x53, 0xd0, 0x93, 0x17, 0xef, 0x82, 0x7f, 0xaa, 0xc7, 0x3d, + 0xee, 0xa9, 0xd8, 0x11, 0x3c, 0xfa, 0x1b, 0x24, 0x33, 0x9d, 0x9d, 0x59, 0xeb, 0xe2, 0xea, 0x2d, + 0xef, 0xf3, 0xe6, 0xf9, 0x4a, 0x30, 0x5b, 0x3c, 0xd1, 0x44, 0x48, 0xba, 0x88, 0x27, 0xa0, 0x42, + 0x30, 0xa0, 0xe9, 0x0a, 0xc2, 0x99, 0x54, 0x74, 0xb7, 0xe0, 0x91, 0xa0, 0x7c, 0x16, 0x08, 0xad, + 0x85, 0x0c, 0x15, 0xf8, 0x42, 0x1b, 0xc5, 0x8d, 0x90, 0x21, 0x5d, 0x8d, 0xf8, 0x32, 0x9a, 0xf3, + 0x11, 0xf5, 0x21, 0x04, 0xc5, 0x0d, 0xcc, 0x48, 0xa4, 0xa4, 0x91, 0xce, 0xfd, 0x8c, 0x4a, 0x78, + 0x24, 0xc8, 0x1f, 0xa9, 0x24, 0xa7, 0x76, 0x1f, 0xfa, 0xc2, 0xcc, 0xe3, 0x09, 0x99, 0xca, 0x80, + 0xfa, 0xd2, 0x97, 0x34, 0x55, 0x98, 0xc4, 0x67, 0xe9, 0x94, 0x0e, 0xe9, 0x29, 0x53, 0xee, 0x3e, + 0x2e, 0x42, 0x05, 0x7c, 0x3a, 0x17, 0x21, 0xa8, 0x0f, 0x34, 0x5a, 0xf8, 0x16, 0xd0, 0x34, 0x00, + 0xc3, 0xe9, 0x6a, 0x2f, 0x4f, 0x97, 0x5e, 0xc7, 0x52, 0x71, 0x68, 0x44, 0x00, 0x7b, 0x84, 0xa3, + 0xbf, 0x11, 0xf4, 0x74, 0x0e, 0x01, 0xff, 0x9d, 0x37, 0xf8, 0x8c, 0x70, 0x6b, 0x1c, 0x0a, 0x23, + 0xf8, 0x52, 0x7c, 0x04, 0xe5, 0xf4, 0x71, 0x2d, 0xe4, 0x01, 0x74, 0x50, 0x1f, 0x0d, 0x9b, 0x5e, + 0x7b, 0xbd, 0xe9, 0x55, 0x92, 0x4d, 0xaf, 0xf6, 0x82, 0x07, 0xc0, 0xd2, 0x8d, 0xf3, 0x0a, 0xd7, + 0x55, 0xbc, 0x04, 0xdd, 0xb9, 0xd5, 0xaf, 0x0e, 0x5b, 0x87, 0x94, 0xdc, 0xf8, 0xe9, 0x08, 0x8b, + 0x97, 0xe0, 0x1d, 0xec, 0x34, 0xeb, 0x76, 0xd2, 0x2c, 0x13, 0x1b, 0xfc, 0x44, 0xb8, 0x53, 0xca, + 0x71, 0x22, 0xc3, 0x33, 0xe1, 0xc7, 0x99, 0x80, 0xf3, 0x0e, 0x37, 0xec, 0x43, 0xcd, 0xb8, 0xe1, + 0x69, 0xb0, 0xd6, 0xe1, 0xa3, 0x92, 0xeb, 0x65, 0x5f, 0x12, 0x2d, 0x7c, 0x0b, 0x68, 0x62, 0x6f, + 0x93, 0xd5, 0x88, 0xbc, 0x9c, 0xbc, 0x87, 0xa9, 0x79, 0x0e, 0x86, 0x7b, 0xce, 0xce, 0x16, 0x17, + 0x18, 0xbb, 0x54, 0x75, 0x22, 0xdc, 0x16, 0x85, 0x7b, 0xde, 0xed, 0xe8, 0x1f, 0xba, 0x95, 0xc2, + 0x7b, 0x77, 0x77, 0x5e, 0xed, 0x12, 0xa8, 0xd9, 0x15, 0x87, 0xc1, 0x0f, 0x84, 0xef, 0x5d, 0x57, + 0xf8, 0x99, 0xd0, 0xc6, 0x79, 0xbb, 0x57, 0x9a, 0xdc, 0xac, 0xb4, 0x65, 0xa7, 0x95, 0xef, 0xec, + 0x62, 0x34, 0x72, 0xa4, 0x54, 0x78, 0x8e, 0xeb, 0xc2, 0x40, 0x90, 0x37, 0x3d, 0xf9, 0xbf, 0xa6, + 0x57, 0x52, 0x17, 0x3f, 0x3b, 0xb6, 0xca, 0x2c, 0x33, 0x18, 0x7c, 0x45, 0xb8, 0x66, 0xbf, 0xda, + 0x79, 0x80, 0x9b, 0x3c, 0x12, 0x4f, 0x95, 0x8c, 0x23, 0xdd, 0x41, 0xfd, 0xea, 0xb0, 0xe9, 0x1d, + 0x24, 0x9b, 0x5e, 0xf3, 0xf8, 0x74, 0x9c, 0x81, 0xac, 0xd8, 0x3b, 0x23, 0xdc, 0xe2, 0x91, 0x78, + 0x0d, 0xca, 0xe6, 0xc8, 0x52, 0x36, 0xbd, 0xdb, 0xc9, 0xa6, 0xd7, 0x3a, 0x3e, 0x1d, 0xe7, 0x30, + 0x2b, 0xdf, 0xb1, 0xfa, 0x0a, 0xb4, 0x8c, 0xd5, 0x14, 0x74, 0xa7, 0x5a, 0xe8, 0xb3, 0x1c, 0x64, + 0xc5, 0xde, 0x23, 0xeb, 0xad, 0x5b, 0x39, 0xdf, 0xba, 0x95, 0x8b, 0xad, 0x5b, 0xf9, 0x94, 0xb8, + 0x68, 0x9d, 0xb8, 0xe8, 0x3c, 0x71, 0xd1, 0x45, 0xe2, 0xa2, 0x6f, 0x89, 0x8b, 0xbe, 0x7c, 0x77, + 0x2b, 0x6f, 0x1a, 0x79, 0xe9, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa2, 0x06, 0xa3, 0xcb, 0x75, + 0x04, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/generated.proto index 11de02ff4..e17b55968 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.admissionregistration.v1alpha1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/types_swagger_doc_generated.go index e2494e5d7..69e4b7c64 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_Initializer = map[string]string{ "": "Initializer describes the name and the failure policy of an initializer, and what resources it applies to.", "name": "Name is the identifier of the initializer. It will be added to the object that needs to be initialized. Name should be fully qualified, e.g., alwayspullimages.kubernetes.io, where \"alwayspullimages\" is the name of the webhook, and kubernetes.io is the name of the organization. Required", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/zz_generated.deepcopy.go index 2ca492946..9f636b484 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/generated.pb.go index 51e5762a8..8b289c4c5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2088,63 +2088,60 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 916 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x54, 0xcf, 0x6f, 0x1b, 0x45, - 0x14, 0xf6, 0xd6, 0x8e, 0x6c, 0x8f, 0x6d, 0xd1, 0x0c, 0x20, 0x99, 0xa8, 0xda, 0xb5, 0x7c, 0x40, - 0x96, 0x50, 0x76, 0x71, 0x8a, 0x10, 0x42, 0x20, 0x94, 0x8d, 0x54, 0x88, 0x94, 0xb4, 0x66, 0x02, - 0xad, 0x84, 0x38, 0x30, 0x5e, 0xbf, 0xd8, 0x83, 0xf7, 0x97, 0x66, 0x66, 0xdd, 0xe6, 0x86, 0xc4, - 0x3f, 0x80, 0xc4, 0x1f, 0xc1, 0x5f, 0xc1, 0x3d, 0x37, 0x7a, 0x41, 0xf4, 0xb4, 0x22, 0xcb, 0x99, - 0x03, 0xd7, 0x9e, 0xd0, 0xce, 0xae, 0xbd, 0x76, 0x1c, 0xa7, 0xee, 0x85, 0x03, 0x37, 0xcf, 0xf7, - 0xde, 0xf7, 0xbd, 0xf7, 0x3d, 0xbf, 0xb7, 0xe8, 0xcb, 0xe9, 0x47, 0xc2, 0x64, 0x81, 0x35, 0x8d, - 0x86, 0xc0, 0x7d, 0x90, 0x20, 0xac, 0x19, 0xf8, 0xa3, 0x80, 0x5b, 0x79, 0x80, 0x86, 0xcc, 0xa2, - 0x23, 0x8f, 0x09, 0xc1, 0x02, 0x9f, 0xc3, 0x98, 0x09, 0xc9, 0xa9, 0x64, 0x81, 0x6f, 0xcd, 0xfa, - 0x43, 0x90, 0xb4, 0x6f, 0x8d, 0xc1, 0x07, 0x4e, 0x25, 0x8c, 0xcc, 0x90, 0x07, 0x32, 0xc0, 0xbd, - 0x8c, 0x69, 0xd2, 0x90, 0x99, 0x37, 0x32, 0xcd, 0x9c, 0xb9, 0xb7, 0x3f, 0x66, 0x72, 0x12, 0x0d, - 0x4d, 0x27, 0xf0, 0xac, 0x71, 0x30, 0x0e, 0x2c, 0x25, 0x30, 0x8c, 0xce, 0xd5, 0x4b, 0x3d, 0xd4, - 0xaf, 0x4c, 0x78, 0xaf, 0xbb, 0xd4, 0x92, 0x13, 0x70, 0xb0, 0x66, 0x6b, 0xc5, 0xf7, 0x4e, 0x8b, - 0x1c, 0x78, 0x26, 0xc1, 0x4f, 0x6b, 0x8b, 0x7d, 0x1a, 0x32, 0x01, 0x7c, 0x06, 0xdc, 0x0a, 0xa7, - 0xe3, 0x34, 0x26, 0x56, 0x13, 0x36, 0x79, 0xd9, 0xfb, 0xa0, 0x90, 0xf3, 0xa8, 0x33, 0x61, 0x3e, - 0xf0, 0x8b, 0x42, 0xc3, 0x03, 0x49, 0x6f, 0x6a, 0xc2, 0xda, 0xc4, 0xe2, 0x91, 0x2f, 0x99, 0x07, - 0x6b, 0x84, 0x0f, 0x5f, 0x45, 0x10, 0xce, 0x04, 0x3c, 0xba, 0xc6, 0xbb, 0xbf, 0x89, 0x17, 0x49, - 0xe6, 0x5a, 0xcc, 0x97, 0x42, 0xf2, 0xeb, 0xa4, 0xee, 0xef, 0x1a, 0xba, 0x77, 0x1a, 0x49, 0x2a, - 0x99, 0x3f, 0x7e, 0x02, 0xc3, 0x49, 0x10, 0x4c, 0x8f, 0x02, 0xff, 0x9c, 0x8d, 0xa3, 0xec, 0xef, - 0xc1, 0xdf, 0xa1, 0x5a, 0xea, 0x6c, 0x44, 0x25, 0x6d, 0x6b, 0x1d, 0xad, 0xd7, 0x38, 0x78, 0xdf, - 0x2c, 0xfe, 0xd3, 0x45, 0x21, 0x33, 0x9c, 0x8e, 0x53, 0x40, 0x98, 0x69, 0xb6, 0x39, 0xeb, 0x9b, - 0x8f, 0x86, 0xdf, 0x83, 0x23, 0x4f, 0x41, 0x52, 0x1b, 0x5f, 0xc6, 0x46, 0x29, 0x89, 0x0d, 0x54, - 0x60, 0x64, 0xa1, 0x8a, 0xcf, 0x50, 0x2d, 0xaf, 0x2c, 0xda, 0x77, 0x3a, 0xe5, 0x5e, 0xe3, 0xa0, - 0x6f, 0x6e, 0xbb, 0x35, 0x66, 0xce, 0xb4, 0x2b, 0x69, 0x09, 0x52, 0x7b, 0x9a, 0x0b, 0x75, 0xff, - 0xd6, 0x50, 0xe7, 0x36, 0x5f, 0x27, 0x4c, 0x48, 0xfc, 0xed, 0x9a, 0x37, 0x73, 0x3b, 0x6f, 0x29, - 0x5b, 0x39, 0xbb, 0x9b, 0x3b, 0xab, 0xcd, 0x91, 0x25, 0x5f, 0x53, 0xb4, 0xc3, 0x24, 0x78, 0x73, - 0x53, 0x0f, 0xb6, 0x37, 0x75, 0x5b, 0xe3, 0x76, 0x2b, 0x2f, 0xb9, 0x73, 0x9c, 0x8a, 0x93, 0xac, - 0x46, 0xf7, 0x67, 0x0d, 0x55, 0x48, 0xe4, 0x02, 0x7e, 0x0f, 0xd5, 0x69, 0xc8, 0x3e, 0xe7, 0x41, - 0x14, 0x8a, 0xb6, 0xd6, 0x29, 0xf7, 0xea, 0x76, 0x2b, 0x89, 0x8d, 0xfa, 0xe1, 0xe0, 0x38, 0x03, - 0x49, 0x11, 0xc7, 0x7d, 0xd4, 0xa0, 0x21, 0x7b, 0x0c, 0x5c, 0x2d, 0xbe, 0x6a, 0xb4, 0x6e, 0xbf, - 0x91, 0xc4, 0x46, 0xe3, 0x70, 0x70, 0x3c, 0x87, 0xc9, 0x72, 0x4e, 0xaa, 0xcf, 0x41, 0x04, 0x11, - 0x77, 0x40, 0xb4, 0xcb, 0x85, 0x3e, 0x99, 0x83, 0xa4, 0x88, 0x77, 0x7f, 0xd1, 0x10, 0x4e, 0xbb, - 0x7a, 0xc2, 0xe4, 0xe4, 0x51, 0x08, 0x99, 0x03, 0x81, 0x3f, 0x43, 0x28, 0x58, 0xbc, 0xf2, 0x26, - 0x0d, 0xb5, 0x1f, 0x0b, 0xf4, 0x65, 0x6c, 0xb4, 0x16, 0xaf, 0xaf, 0x2e, 0x42, 0x20, 0x4b, 0x14, - 0x3c, 0x40, 0x15, 0x1e, 0xb9, 0xd0, 0xbe, 0xb3, 0xf6, 0xa7, 0xbd, 0x62, 0xb2, 0x69, 0x33, 0x76, - 0x33, 0x9f, 0xa0, 0x1a, 0x18, 0x51, 0x4a, 0xdd, 0x1f, 0x35, 0x74, 0xf7, 0x0c, 0xf8, 0x8c, 0x39, - 0x40, 0xe0, 0x1c, 0x38, 0xf8, 0x0e, 0x60, 0x0b, 0xd5, 0x7d, 0xea, 0x81, 0x08, 0xa9, 0x03, 0x6a, - 0x41, 0xea, 0xf6, 0x6e, 0xce, 0xad, 0x3f, 0x9c, 0x07, 0x48, 0x91, 0x83, 0x3b, 0xa8, 0x92, 0x3e, - 0x54, 0x5f, 0xf5, 0xa2, 0x4e, 0x9a, 0x4b, 0x54, 0x04, 0xdf, 0x43, 0x95, 0x90, 0xca, 0x49, 0xbb, - 0xac, 0x32, 0x6a, 0x69, 0x74, 0x40, 0xe5, 0x84, 0x28, 0xb4, 0xfb, 0x87, 0x86, 0xf4, 0xc7, 0xd4, - 0x65, 0xa3, 0xff, 0xdd, 0x3d, 0xfe, 0xa3, 0xa1, 0xee, 0xed, 0xce, 0xfe, 0x83, 0x8b, 0xf4, 0x56, - 0x2f, 0xf2, 0x8b, 0xed, 0x6d, 0xdd, 0xde, 0xfa, 0x86, 0x9b, 0xfc, 0xad, 0x8c, 0xaa, 0x79, 0xfa, - 0x62, 0x33, 0xb4, 0x8d, 0x9b, 0xf1, 0x14, 0x35, 0x1d, 0x97, 0x81, 0x2f, 0x33, 0xe9, 0x7c, 0xb7, - 0x3f, 0x7d, 0xed, 0xd1, 0x1f, 0x2d, 0x89, 0xd8, 0x6f, 0xe5, 0x85, 0x9a, 0xcb, 0x28, 0x59, 0x29, - 0x84, 0x29, 0xda, 0x49, 0x4f, 0x20, 0xbb, 0xe6, 0xc6, 0xc1, 0x27, 0xaf, 0x77, 0x4d, 0xab, 0xa7, - 0x5d, 0x4c, 0x22, 0x8d, 0x09, 0x92, 0x29, 0xe3, 0x13, 0xd4, 0x3a, 0xa7, 0xcc, 0x8d, 0x38, 0x0c, - 0x02, 0x97, 0x39, 0x17, 0xed, 0x8a, 0x1a, 0xc3, 0xbb, 0x49, 0x6c, 0xb4, 0x1e, 0x2c, 0x07, 0x5e, - 0xc6, 0xc6, 0xee, 0x0a, 0xa0, 0x4e, 0x7f, 0x95, 0x8c, 0x9f, 0xa1, 0xdd, 0xc5, 0xc9, 0x9d, 0x81, - 0x0b, 0x8e, 0x0c, 0x78, 0x7b, 0x47, 0x8d, 0xeb, 0xfe, 0x96, 0xdb, 0x42, 0x87, 0xe0, 0xce, 0xa9, - 0xf6, 0xdb, 0x49, 0x6c, 0xec, 0x3e, 0xbc, 0xae, 0x48, 0xd6, 0x8b, 0x74, 0x7f, 0xd5, 0xd0, 0x9b, - 0x37, 0x8c, 0x19, 0x53, 0x54, 0x15, 0xd9, 0xc7, 0x23, 0xdf, 0xda, 0x8f, 0xb7, 0x1f, 0xe2, 0xf5, - 0xaf, 0x8e, 0xdd, 0x48, 0x62, 0xa3, 0x3a, 0x47, 0xe7, 0xba, 0xb8, 0x87, 0x6a, 0x0e, 0xb5, 0x23, - 0x7f, 0x94, 0x7f, 0xf6, 0x9a, 0x76, 0x33, 0xdd, 0xf2, 0xa3, 0xc3, 0x0c, 0x23, 0x8b, 0x28, 0x7e, - 0x07, 0x95, 0x23, 0xee, 0xe6, 0x5f, 0x98, 0x6a, 0x12, 0x1b, 0xe5, 0xaf, 0xc9, 0x09, 0x49, 0x31, - 0x7b, 0xff, 0xf2, 0x4a, 0x2f, 0x3d, 0xbf, 0xd2, 0x4b, 0x2f, 0xae, 0xf4, 0xd2, 0x0f, 0x89, 0xae, - 0x5d, 0x26, 0xba, 0xf6, 0x3c, 0xd1, 0xb5, 0x17, 0x89, 0xae, 0xfd, 0x99, 0xe8, 0xda, 0x4f, 0x7f, - 0xe9, 0xa5, 0x6f, 0xaa, 0x79, 0x6b, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x78, 0x57, 0x76, 0x28, - 0x10, 0x0a, 0x00, 0x00, + // 872 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x54, 0xcf, 0x8f, 0xdb, 0x44, + 0x14, 0x8e, 0x9b, 0xac, 0x92, 0x4c, 0x12, 0xd1, 0x1d, 0x40, 0x0a, 0xab, 0xca, 0x8e, 0x72, 0x40, + 0x91, 0x50, 0x6d, 0xb2, 0x20, 0x84, 0x10, 0x08, 0xad, 0x57, 0x2a, 0xac, 0xb4, 0x6d, 0xc3, 0x2c, + 0xb4, 0x12, 0xe2, 0xc0, 0xc4, 0x79, 0xeb, 0x0c, 0xf1, 0x2f, 0x8d, 0xc7, 0x29, 0x7b, 0x43, 0xe2, + 0x1f, 0x40, 0xe2, 0x8f, 0xe0, 0xaf, 0xe0, 0xbe, 0x37, 0x7a, 0x41, 0xf4, 0x64, 0xb1, 0xe6, 0xcc, + 0x81, 0x6b, 0x4f, 0x68, 0xec, 0x49, 0x9c, 0x6c, 0xba, 0x69, 0x7a, 0xe1, 0xc0, 0xcd, 0xf3, 0xbd, + 0xf9, 0xbe, 0xf7, 0xbe, 0xe7, 0xf7, 0x06, 0x7d, 0x31, 0xfb, 0x30, 0x36, 0x59, 0x68, 0xcd, 0x92, + 0x31, 0xf0, 0x00, 0x04, 0xc4, 0xd6, 0x1c, 0x82, 0x49, 0xc8, 0x2d, 0x15, 0xa0, 0x11, 0xb3, 0xe8, + 0xc4, 0x67, 0x71, 0xcc, 0xc2, 0x80, 0x83, 0xcb, 0x62, 0xc1, 0xa9, 0x60, 0x61, 0x60, 0xcd, 0x87, + 0x63, 0x10, 0x74, 0x68, 0xb9, 0x10, 0x00, 0xa7, 0x02, 0x26, 0x66, 0xc4, 0x43, 0x11, 0xe2, 0x41, + 0xc1, 0x34, 0x69, 0xc4, 0xcc, 0x17, 0x32, 0x4d, 0xc5, 0x3c, 0xb8, 0xeb, 0x32, 0x31, 0x4d, 0xc6, + 0xa6, 0x13, 0xfa, 0x96, 0x1b, 0xba, 0xa1, 0x95, 0x0b, 0x8c, 0x93, 0xf3, 0xfc, 0x94, 0x1f, 0xf2, + 0xaf, 0x42, 0xf8, 0xe0, 0xfd, 0xb2, 0x24, 0x9f, 0x3a, 0x53, 0x16, 0x00, 0xbf, 0xb0, 0xa2, 0x99, + 0x2b, 0x81, 0xd8, 0xf2, 0x41, 0x50, 0x6b, 0xbe, 0x51, 0xce, 0x81, 0x75, 0x13, 0x8b, 0x27, 0x81, + 0x60, 0x3e, 0x6c, 0x10, 0x3e, 0x78, 0x19, 0x21, 0x76, 0xa6, 0xe0, 0xd3, 0xeb, 0xbc, 0xfe, 0xef, + 0x1a, 0xba, 0x73, 0x3f, 0x11, 0x54, 0xb0, 0xc0, 0x7d, 0x0c, 0xe3, 0x69, 0x18, 0xce, 0x8e, 0xc3, + 0xe0, 0x9c, 0xb9, 0x49, 0x61, 0x1b, 0x7f, 0x8b, 0x1a, 0xb2, 0xc8, 0x09, 0x15, 0xb4, 0xab, 0xf5, + 0xb4, 0x41, 0xeb, 0xf0, 0x5d, 0xb3, 0xec, 0xd5, 0x32, 0x97, 0x19, 0xcd, 0x5c, 0x09, 0xc4, 0xa6, + 0xbc, 0x6d, 0xce, 0x87, 0xe6, 0xc3, 0xf1, 0x77, 0xe0, 0x88, 0xfb, 0x20, 0xa8, 0x8d, 0x2f, 0x53, + 0xa3, 0x92, 0xa5, 0x06, 0x2a, 0x31, 0xb2, 0x54, 0xc5, 0x67, 0xa8, 0xa1, 0x32, 0xc7, 0xdd, 0x5b, + 0xbd, 0xea, 0xa0, 0x75, 0x38, 0x34, 0x77, 0xfd, 0x1b, 0xa6, 0x62, 0xda, 0x35, 0x99, 0x82, 0x34, + 0x9e, 0x28, 0xa1, 0xfe, 0xdf, 0x1a, 0xea, 0x6d, 0xf3, 0x75, 0xca, 0x62, 0x81, 0xbf, 0xd9, 0xf0, + 0x66, 0xee, 0xe6, 0x4d, 0xb2, 0x73, 0x67, 0xb7, 0x95, 0xb3, 0xc6, 0x02, 0x59, 0xf1, 0x35, 0x43, + 0x7b, 0x4c, 0x80, 0xbf, 0x30, 0x75, 0x6f, 0x77, 0x53, 0xdb, 0x0a, 0xb7, 0x3b, 0x2a, 0xe5, 0xde, + 0x89, 0x14, 0x27, 0x45, 0x8e, 0xfe, 0xcf, 0x1a, 0xaa, 0x91, 0xc4, 0x03, 0xfc, 0x0e, 0x6a, 0xd2, + 0x88, 0x7d, 0xc6, 0xc3, 0x24, 0x8a, 0xbb, 0x5a, 0xaf, 0x3a, 0x68, 0xda, 0x9d, 0x2c, 0x35, 0x9a, + 0x47, 0xa3, 0x93, 0x02, 0x24, 0x65, 0x1c, 0x0f, 0x51, 0x8b, 0x46, 0xec, 0x11, 0x70, 0x59, 0x4a, + 0x51, 0x68, 0xd3, 0x7e, 0x2d, 0x4b, 0x8d, 0xd6, 0xd1, 0xe8, 0x64, 0x01, 0x93, 0xd5, 0x3b, 0x52, + 0x9f, 0x43, 0x1c, 0x26, 0xdc, 0x81, 0xb8, 0x5b, 0x2d, 0xf5, 0xc9, 0x02, 0x24, 0x65, 0xbc, 0xff, + 0x8b, 0x86, 0xb0, 0xac, 0xea, 0x31, 0x13, 0xd3, 0x87, 0x11, 0x14, 0x0e, 0x62, 0xfc, 0x29, 0x42, + 0xe1, 0xf2, 0xa4, 0x8a, 0x34, 0xf2, 0xf9, 0x58, 0xa2, 0xcf, 0x53, 0xa3, 0xb3, 0x3c, 0x7d, 0x79, + 0x11, 0x01, 0x59, 0xa1, 0xe0, 0x11, 0xaa, 0xf1, 0xc4, 0x83, 0xee, 0xad, 0x8d, 0x9f, 0xf6, 0x92, + 0xce, 0xca, 0x62, 0xec, 0xb6, 0xea, 0x60, 0xde, 0x30, 0x92, 0x2b, 0xf5, 0x7f, 0xd4, 0xd0, 0xed, + 0x33, 0xe0, 0x73, 0xe6, 0x00, 0x81, 0x73, 0xe0, 0x10, 0x38, 0x80, 0x2d, 0xd4, 0x0c, 0xa8, 0x0f, + 0x71, 0x44, 0x1d, 0xc8, 0x07, 0xa4, 0x69, 0xef, 0x2b, 0x6e, 0xf3, 0xc1, 0x22, 0x40, 0xca, 0x3b, + 0xb8, 0x87, 0x6a, 0xf2, 0x90, 0xd7, 0xd5, 0x2c, 0xf3, 0xc8, 0xbb, 0x24, 0x8f, 0xe0, 0x3b, 0xa8, + 0x16, 0x51, 0x31, 0xed, 0x56, 0xf3, 0x1b, 0x0d, 0x19, 0x1d, 0x51, 0x31, 0x25, 0x39, 0xda, 0xff, + 0x43, 0x43, 0xfa, 0x23, 0xea, 0xb1, 0xc9, 0xff, 0x6e, 0x1f, 0xff, 0xd1, 0x50, 0x7f, 0xbb, 0xb3, + 0xff, 0x60, 0x23, 0xfd, 0xf5, 0x8d, 0xfc, 0x7c, 0x77, 0x5b, 0xdb, 0x4b, 0xbf, 0x61, 0x27, 0x7f, + 0xab, 0xa2, 0xba, 0xba, 0xbe, 0x9c, 0x0c, 0xed, 0xc6, 0xc9, 0x78, 0x82, 0xda, 0x8e, 0xc7, 0x20, + 0x10, 0x85, 0xb4, 0x9a, 0xed, 0x4f, 0x5e, 0xb9, 0xf5, 0xc7, 0x2b, 0x22, 0xf6, 0x1b, 0x2a, 0x51, + 0x7b, 0x15, 0x25, 0x6b, 0x89, 0x30, 0x45, 0x7b, 0x72, 0x05, 0x8a, 0x6d, 0x6e, 0x1d, 0x7e, 0xfc, + 0x6a, 0xdb, 0xb4, 0xbe, 0xda, 0x65, 0x27, 0x64, 0x2c, 0x26, 0x85, 0x32, 0x3e, 0x45, 0x9d, 0x73, + 0xca, 0xbc, 0x84, 0xc3, 0x28, 0xf4, 0x98, 0x73, 0xd1, 0xad, 0xe5, 0x6d, 0x78, 0x3b, 0x4b, 0x8d, + 0xce, 0xbd, 0xd5, 0xc0, 0xf3, 0xd4, 0xd8, 0x5f, 0x03, 0xf2, 0xd5, 0x5f, 0x27, 0xe3, 0xef, 0xd1, + 0xfe, 0x72, 0xe5, 0xce, 0xc0, 0x03, 0x47, 0x84, 0xbc, 0xbb, 0x97, 0xb7, 0xeb, 0xbd, 0x1d, 0xa7, + 0x85, 0x8e, 0xc1, 0x5b, 0x50, 0xed, 0x37, 0xb3, 0xd4, 0xd8, 0x7f, 0x70, 0x5d, 0x91, 0x6c, 0x26, + 0xe9, 0xff, 0xaa, 0xa1, 0xd7, 0x5f, 0xd0, 0x66, 0x4c, 0x51, 0x3d, 0x2e, 0x1e, 0x0f, 0x35, 0xb5, + 0x1f, 0xed, 0xde, 0xc4, 0xeb, 0xaf, 0x8e, 0xdd, 0xca, 0x52, 0xa3, 0xbe, 0x40, 0x17, 0xba, 0x78, + 0x80, 0x1a, 0x0e, 0xb5, 0x93, 0x60, 0xa2, 0x9e, 0xbd, 0xb6, 0xdd, 0x96, 0x53, 0x7e, 0x7c, 0x54, + 0x60, 0x64, 0x19, 0xc5, 0x6f, 0xa1, 0x6a, 0xc2, 0x3d, 0xf5, 0xc2, 0xd4, 0xb3, 0xd4, 0xa8, 0x7e, + 0x45, 0x4e, 0x89, 0xc4, 0xec, 0xbb, 0x97, 0x57, 0x7a, 0xe5, 0xe9, 0x95, 0x5e, 0x79, 0x76, 0xa5, + 0x57, 0x7e, 0xc8, 0x74, 0xed, 0x32, 0xd3, 0xb5, 0xa7, 0x99, 0xae, 0x3d, 0xcb, 0x74, 0xed, 0xcf, + 0x4c, 0xd7, 0x7e, 0xfa, 0x4b, 0xaf, 0x7c, 0x5d, 0x57, 0xa5, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, + 0xeb, 0x1f, 0xdb, 0x50, 0x68, 0x09, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/generated.proto index 3d6cbc1e6..2866b8738 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,12 +21,9 @@ syntax = 'proto2'; package k8s.io.api.admissionregistration.v1beta1; -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; @@ -250,9 +247,7 @@ message WebhookClientConfig { // // If the webhook is running within the cluster, then you should use `service`. // - // If there is only one port open for the service, that port will be - // used. If there are multiple ports open, port 443 will be used if it - // is open, otherwise it is an error. + // Port 443 will be used if it is open, otherwise it is an error. // // +optional optional ServiceReference service = 1; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/types.go index 9a4a1ddb4..f209e7acc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/types.go @@ -254,9 +254,7 @@ type WebhookClientConfig struct { // // If the webhook is running within the cluster, then you should use `service`. // - // If there is only one port open for the service, that port will be - // used. If there are multiple ports open, port 443 will be used if it - // is open, otherwise it is an error. + // Port 443 will be used if it is open, otherwise it is an error. // // +optional Service *ServiceReference `json:"service" protobuf:"bytes,1,opt,name=service"` diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go index b32051424..e90bdc911 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_MutatingWebhookConfiguration = map[string]string{ "": "MutatingWebhookConfiguration describes the configuration of and admission webhook that accept or reject and may change the object.", "metadata": "Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata.", @@ -114,7 +114,7 @@ func (Webhook) SwaggerDoc() map[string]string { var map_WebhookClientConfig = map[string]string{ "": "WebhookClientConfig contains the information to make a TLS connection with the webhook", "url": "`url` gives the location of the webhook, in standard URL form (`[scheme://]host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.", - "service": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nIf there is only one port open for the service, that port will be used. If there are multiple ports open, port 443 will be used if it is open, otherwise it is an error.", + "service": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nPort 443 will be used if it is open, otherwise it is an error.", "caBundle": "`caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate. Required.", } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/zz_generated.deepcopy.go index d8345d209..d8c1e4f62 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/admissionregistration/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/generated.pb.go index 02123859b..eac6ef2a1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -61,7 +61,6 @@ import fmt "fmt" import math "math" import k8s_io_api_core_v1 "k8s.io/api/core/v1" - import k8s_io_apimachinery_pkg_apis_meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" import k8s_io_apimachinery_pkg_util_intstr "k8s.io/apimachinery/pkg/util/intstr" @@ -6812,134 +6811,133 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2051 bytes of a gzipped FileDescriptorProto + // 2037 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcd, 0x6f, 0x24, 0x47, 0x1d, 0x75, 0xcf, 0x87, 0x3d, 0x2e, 0xaf, 0xed, 0xdd, 0xb2, 0xb1, 0x27, 0xbb, 0x64, 0x66, 0x19, - 0x60, 0xe3, 0xcd, 0x66, 0x7b, 0xf0, 0x66, 0x13, 0xa1, 0x2c, 0x02, 0x79, 0xc6, 0x21, 0x84, 0x78, - 0x6c, 0x53, 0x5e, 0xef, 0x61, 0x09, 0x12, 0x35, 0x33, 0xb5, 0xe3, 0x8e, 0xfb, 0x4b, 0xdd, 0xd5, - 0xc3, 0x8e, 0xb8, 0x20, 0x24, 0x38, 0x71, 0xe0, 0x3f, 0x41, 0x08, 0xc1, 0x0d, 0x45, 0x88, 0xcb, - 0x5e, 0x90, 0x22, 0x2e, 0xe4, 0x64, 0xb1, 0x93, 0x13, 0x42, 0x39, 0x72, 0xc9, 0x05, 0x54, 0xd5, - 0xd5, 0xdf, 0xd5, 0x9e, 0xb1, 0x37, 0xeb, 0xa0, 0x68, 0x6f, 0x9e, 0xaa, 0xf7, 0x7b, 0xfd, 0xab, - 0xaa, 0x5f, 0xd5, 0x7b, 0x5d, 0x6d, 0x70, 0xef, 0xf8, 0xdb, 0xae, 0xaa, 0x59, 0xcd, 0x63, 0xaf, - 0x4b, 0x1c, 0x93, 0x50, 0xe2, 0x36, 0x87, 0xc4, 0xec, 0x5b, 0x4e, 0x53, 0x74, 0x60, 0x5b, 0x6b, - 0x62, 0xdb, 0x76, 0x9b, 0xc3, 0xcd, 0xe6, 0x80, 0x98, 0xc4, 0xc1, 0x94, 0xf4, 0x55, 0xdb, 0xb1, - 0xa8, 0x05, 0xa1, 0x8f, 0x51, 0xb1, 0xad, 0xa9, 0x0c, 0xa3, 0x0e, 0x37, 0xaf, 0xde, 0x1e, 0x68, - 0xf4, 0xc8, 0xeb, 0xaa, 0x3d, 0xcb, 0x68, 0x0e, 0xac, 0x81, 0xd5, 0xe4, 0xd0, 0xae, 0xf7, 0x88, - 0xff, 0xe2, 0x3f, 0xf8, 0x5f, 0x3e, 0xc5, 0xd5, 0x46, 0xec, 0x31, 0x3d, 0xcb, 0x21, 0x92, 0xc7, - 0x5c, 0xbd, 0x19, 0xc3, 0xd8, 0x96, 0xae, 0xf5, 0x46, 0xcd, 0xe1, 0x66, 0x97, 0x50, 0x9c, 0x85, - 0xde, 0x8d, 0xa0, 0x06, 0xee, 0x1d, 0x69, 0x26, 0x71, 0x46, 0x4d, 0xfb, 0x78, 0xc0, 0x1a, 0xdc, - 0xa6, 0x41, 0x28, 0x96, 0x3d, 0xa0, 0x99, 0x17, 0xe5, 0x78, 0x26, 0xd5, 0x0c, 0x92, 0x09, 0x78, - 0x73, 0x52, 0x80, 0xdb, 0x3b, 0x22, 0x06, 0xce, 0xc4, 0xbd, 0x9e, 0x17, 0xe7, 0x51, 0x4d, 0x6f, - 0x6a, 0x26, 0x75, 0xa9, 0x93, 0x0e, 0x6a, 0xfc, 0x47, 0x01, 0xb0, 0x6d, 0x99, 0xd4, 0xb1, 0x74, - 0x9d, 0x38, 0x88, 0x0c, 0x35, 0x57, 0xb3, 0x4c, 0xf8, 0x53, 0x50, 0x61, 0xe3, 0xe9, 0x63, 0x8a, - 0xab, 0xca, 0x75, 0x65, 0x63, 0xe1, 0xce, 0xb7, 0xd4, 0x68, 0x3d, 0x42, 0x7a, 0xd5, 0x3e, 0x1e, - 0xb0, 0x06, 0x57, 0x65, 0x68, 0x75, 0xb8, 0xa9, 0xee, 0x75, 0x3f, 0x20, 0x3d, 0xda, 0x21, 0x14, - 0xb7, 0xe0, 0x93, 0x93, 0xfa, 0xcc, 0xf8, 0xa4, 0x0e, 0xa2, 0x36, 0x14, 0xb2, 0xc2, 0x3d, 0x50, - 0xe2, 0xec, 0x05, 0xce, 0x7e, 0x3b, 0x97, 0x5d, 0x0c, 0x5a, 0x45, 0xf8, 0x67, 0x6f, 0x3f, 0xa6, - 0xc4, 0x64, 0xe9, 0xb5, 0x2e, 0x09, 0xea, 0xd2, 0x36, 0xa6, 0x18, 0x71, 0x22, 0xf8, 0x1a, 0xa8, - 0x38, 0x22, 0xfd, 0x6a, 0xf1, 0xba, 0xb2, 0x51, 0x6c, 0x5d, 0x16, 0xa8, 0x4a, 0x30, 0x2c, 0x14, - 0x22, 0x1a, 0x7f, 0x55, 0xc0, 0x5a, 0x76, 0xdc, 0x3b, 0x9a, 0x4b, 0xe1, 0xfb, 0x99, 0xb1, 0xab, - 0xd3, 0x8d, 0x9d, 0x45, 0xf3, 0x91, 0x87, 0x0f, 0x0e, 0x5a, 0x62, 0xe3, 0x7e, 0x0f, 0x94, 0x35, - 0x4a, 0x0c, 0xb7, 0x5a, 0xb8, 0x5e, 0xdc, 0x58, 0xb8, 0x73, 0x43, 0xcd, 0x96, 0xb9, 0x9a, 0x4d, - 0xac, 0xb5, 0x28, 0x28, 0xcb, 0xef, 0xb2, 0x60, 0xe4, 0x73, 0x34, 0xfe, 0xab, 0x80, 0xf9, 0x6d, - 0x4c, 0x0c, 0xcb, 0x3c, 0x20, 0xf4, 0x02, 0x16, 0xad, 0x0d, 0x4a, 0xae, 0x4d, 0x7a, 0x62, 0xd1, - 0xbe, 0x26, 0xcb, 0x3d, 0x4c, 0xe7, 0xc0, 0x26, 0xbd, 0x68, 0xa1, 0xd8, 0x2f, 0xc4, 0x83, 0xe1, - 0x7b, 0x60, 0xd6, 0xa5, 0x98, 0x7a, 0x2e, 0x5f, 0xa6, 0x85, 0x3b, 0x5f, 0x3f, 0x9d, 0x86, 0x43, - 0x5b, 0x4b, 0x82, 0x68, 0xd6, 0xff, 0x8d, 0x04, 0x45, 0xe3, 0x5f, 0x05, 0x00, 0x43, 0x6c, 0xdb, - 0x32, 0xfb, 0x1a, 0x65, 0xf5, 0xfb, 0x16, 0x28, 0xd1, 0x91, 0x4d, 0xf8, 0x34, 0xcc, 0xb7, 0x6e, - 0x04, 0x59, 0xdc, 0x1f, 0xd9, 0xe4, 0xb3, 0x93, 0xfa, 0x5a, 0x36, 0x82, 0xf5, 0x20, 0x1e, 0x03, - 0x77, 0xc2, 0xfc, 0x0a, 0x3c, 0xfa, 0x6e, 0xf2, 0xd1, 0x9f, 0x9d, 0xd4, 0x25, 0xe7, 0x8a, 0x1a, - 0x32, 0x25, 0x13, 0x84, 0x43, 0x00, 0x75, 0xec, 0xd2, 0xfb, 0x0e, 0x36, 0x5d, 0xff, 0x49, 0x9a, - 0x41, 0xc4, 0xc8, 0x5f, 0x9d, 0x6e, 0x79, 0x58, 0x44, 0xeb, 0xaa, 0xc8, 0x02, 0xee, 0x64, 0xd8, - 0x90, 0xe4, 0x09, 0xf0, 0x06, 0x98, 0x75, 0x08, 0x76, 0x2d, 0xb3, 0x5a, 0xe2, 0xa3, 0x08, 0x27, - 0x10, 0xf1, 0x56, 0x24, 0x7a, 0xe1, 0x4d, 0x30, 0x67, 0x10, 0xd7, 0xc5, 0x03, 0x52, 0x2d, 0x73, - 0xe0, 0xb2, 0x00, 0xce, 0x75, 0xfc, 0x66, 0x14, 0xf4, 0x37, 0x7e, 0xaf, 0x80, 0xc5, 0x70, 0xe6, - 0x2e, 0x60, 0xab, 0xb4, 0x92, 0x5b, 0xe5, 0xe5, 0x53, 0xeb, 0x24, 0x67, 0x87, 0x7c, 0x58, 0x8c, - 0xe5, 0xcc, 0x8a, 0x10, 0xfe, 0x04, 0x54, 0x5c, 0xa2, 0x93, 0x1e, 0xb5, 0x1c, 0x91, 0xf3, 0xeb, - 0x53, 0xe6, 0x8c, 0xbb, 0x44, 0x3f, 0x10, 0xa1, 0xad, 0x4b, 0x2c, 0xe9, 0xe0, 0x17, 0x0a, 0x29, - 0xe1, 0x8f, 0x40, 0x85, 0x12, 0xc3, 0xd6, 0x31, 0x25, 0x62, 0x9b, 0x24, 0xea, 0x9b, 0x95, 0x0b, - 0x23, 0xdb, 0xb7, 0xfa, 0xf7, 0x05, 0x8c, 0x6f, 0x94, 0x70, 0x1e, 0x82, 0x56, 0x14, 0xd2, 0xc0, - 0x63, 0xb0, 0xe4, 0xd9, 0x7d, 0x86, 0xa4, 0xec, 0xe8, 0x1e, 0x8c, 0x44, 0xf9, 0xdc, 0x3a, 0x75, - 0x42, 0x0e, 0x13, 0x21, 0xad, 0x35, 0xf1, 0x80, 0xa5, 0x64, 0x3b, 0x4a, 0x51, 0xc3, 0x2d, 0xb0, - 0x6c, 0x68, 0x26, 0x22, 0xb8, 0x3f, 0x3a, 0x20, 0x3d, 0xcb, 0xec, 0xbb, 0xbc, 0x80, 0xca, 0xad, - 0x75, 0x41, 0xb0, 0xdc, 0x49, 0x76, 0xa3, 0x34, 0x1e, 0xee, 0x80, 0xd5, 0xe0, 0x9c, 0xfd, 0x81, - 0xe6, 0x52, 0xcb, 0x19, 0xed, 0x68, 0x86, 0x46, 0xab, 0xb3, 0x9c, 0xa7, 0x3a, 0x3e, 0xa9, 0xaf, - 0x22, 0x49, 0x3f, 0x92, 0x46, 0x35, 0x7e, 0x33, 0x0b, 0x96, 0x53, 0xa7, 0x01, 0x7c, 0x00, 0xd6, - 0x7a, 0x9e, 0xe3, 0x10, 0x93, 0xee, 0x7a, 0x46, 0x97, 0x38, 0x07, 0xbd, 0x23, 0xd2, 0xf7, 0x74, - 0xd2, 0xe7, 0x2b, 0x5a, 0x6e, 0xd5, 0x44, 0xae, 0x6b, 0x6d, 0x29, 0x0a, 0xe5, 0x44, 0xc3, 0x1f, - 0x02, 0x68, 0xf2, 0xa6, 0x8e, 0xe6, 0xba, 0x21, 0x67, 0x81, 0x73, 0x86, 0x1b, 0x70, 0x37, 0x83, - 0x40, 0x92, 0x28, 0x96, 0x63, 0x9f, 0xb8, 0x9a, 0x43, 0xfa, 0xe9, 0x1c, 0x8b, 0xc9, 0x1c, 0xb7, - 0xa5, 0x28, 0x94, 0x13, 0x0d, 0xdf, 0x00, 0x0b, 0xfe, 0xd3, 0xf8, 0x9c, 0x8b, 0xc5, 0x59, 0x11, - 0x64, 0x0b, 0xbb, 0x51, 0x17, 0x8a, 0xe3, 0xd8, 0xd0, 0xac, 0xae, 0x4b, 0x9c, 0x21, 0xe9, 0xbf, - 0xe3, 0x7b, 0x00, 0x26, 0x94, 0x65, 0x2e, 0x94, 0xe1, 0xd0, 0xf6, 0x32, 0x08, 0x24, 0x89, 0x62, - 0x43, 0xf3, 0xab, 0x26, 0x33, 0xb4, 0xd9, 0xe4, 0xd0, 0x0e, 0xa5, 0x28, 0x94, 0x13, 0xcd, 0x6a, - 0xcf, 0x4f, 0x79, 0x6b, 0x88, 0x35, 0x1d, 0x77, 0x75, 0x52, 0x9d, 0x4b, 0xd6, 0xde, 0x6e, 0xb2, - 0x1b, 0xa5, 0xf1, 0xf0, 0x1d, 0x70, 0xc5, 0x6f, 0x3a, 0x34, 0x71, 0x48, 0x52, 0xe1, 0x24, 0x2f, - 0x09, 0x92, 0x2b, 0xbb, 0x69, 0x00, 0xca, 0xc6, 0xc0, 0xb7, 0xc0, 0x52, 0xcf, 0xd2, 0x75, 0x5e, - 0x8f, 0x6d, 0xcb, 0x33, 0x69, 0x75, 0x9e, 0xb3, 0x40, 0xb6, 0x87, 0xda, 0x89, 0x1e, 0x94, 0x42, - 0xc2, 0x87, 0x00, 0xf4, 0x02, 0x39, 0x70, 0xab, 0x20, 0x5f, 0xe8, 0xb3, 0x3a, 0x14, 0x09, 0x70, - 0xd8, 0xe4, 0xa2, 0x18, 0x5b, 0xe3, 0x43, 0x05, 0xac, 0xe7, 0xec, 0x71, 0xf8, 0xbd, 0x84, 0xea, - 0xdd, 0x4a, 0xa9, 0xde, 0xb5, 0x9c, 0xb0, 0x98, 0xf4, 0xf5, 0xc0, 0x22, 0xf3, 0x1d, 0x9a, 0x39, - 0xf0, 0x21, 0xe2, 0x04, 0x7b, 0x55, 0x96, 0x3b, 0x8a, 0x03, 0xa3, 0x63, 0xf8, 0xca, 0xf8, 0xa4, - 0xbe, 0x98, 0xe8, 0x43, 0x49, 0xce, 0xc6, 0x2f, 0x0b, 0x00, 0x6c, 0x13, 0x5b, 0xb7, 0x46, 0x06, - 0x31, 0x2f, 0xc2, 0xb5, 0x6c, 0x27, 0x5c, 0x4b, 0x43, 0xba, 0x10, 0x61, 0x3e, 0xb9, 0xb6, 0x65, - 0x27, 0x65, 0x5b, 0xbe, 0x31, 0x81, 0xe7, 0x74, 0xdf, 0xf2, 0x8f, 0x22, 0x58, 0x89, 0xc0, 0x91, - 0x71, 0xb9, 0x97, 0x58, 0xc2, 0x57, 0x52, 0x4b, 0xb8, 0x2e, 0x09, 0x79, 0x6e, 0xce, 0xe5, 0xf3, - 0x77, 0x10, 0xf0, 0x03, 0xb0, 0xc4, 0xac, 0x8a, 0x5f, 0x08, 0xdc, 0x08, 0xcd, 0x9e, 0xd9, 0x08, - 0x85, 0x42, 0xb6, 0x93, 0x60, 0x42, 0x29, 0xe6, 0x1c, 0xe3, 0x35, 0xf7, 0xbc, 0x8d, 0x57, 0xe3, - 0x0f, 0x0a, 0x58, 0x8a, 0x96, 0xe9, 0x02, 0x6c, 0x52, 0x3b, 0x69, 0x93, 0x6a, 0xa7, 0xd7, 0x65, - 0x8e, 0x4f, 0xfa, 0x7b, 0x29, 0x9e, 0x35, 0x37, 0x4a, 0x1b, 0xec, 0x85, 0xca, 0xd6, 0xb5, 0x1e, - 0x76, 0x85, 0xac, 0x5e, 0xf2, 0x5f, 0xa6, 0xfc, 0x36, 0x14, 0xf6, 0x26, 0x2c, 0x55, 0xe1, 0xf9, - 0x5a, 0xaa, 0xe2, 0xe7, 0x63, 0xa9, 0xee, 0x83, 0x8a, 0x1b, 0x98, 0xa9, 0x12, 0xa7, 0xbc, 0x31, - 0x69, 0x3b, 0x0b, 0x1f, 0x15, 0xb2, 0x86, 0x0e, 0x2a, 0x64, 0x92, 0x79, 0xa7, 0xf2, 0x17, 0xe9, - 0x9d, 0xd8, 0x16, 0xb6, 0xb1, 0xe7, 0x92, 0x3e, 0xaf, 0xfb, 0x4a, 0xb4, 0x85, 0xf7, 0x79, 0x2b, - 0x12, 0xbd, 0xf0, 0x10, 0xac, 0xdb, 0x8e, 0x35, 0x70, 0x88, 0xeb, 0x6e, 0x13, 0xdc, 0xd7, 0x35, - 0x93, 0x04, 0x03, 0xf0, 0x55, 0xef, 0xda, 0xf8, 0xa4, 0xbe, 0xbe, 0x2f, 0x87, 0xa0, 0xbc, 0xd8, - 0xc6, 0x9f, 0x4b, 0xe0, 0x72, 0xfa, 0x44, 0xcc, 0x31, 0x22, 0xca, 0xb9, 0x8c, 0xc8, 0x6b, 0xb1, - 0x12, 0xf5, 0x5d, 0x5a, 0xec, 0x9d, 0x3f, 0x53, 0xa6, 0x5b, 0x60, 0x59, 0x18, 0x8f, 0xa0, 0x53, - 0x58, 0xb1, 0x70, 0x79, 0x0e, 0x93, 0xdd, 0x28, 0x8d, 0x67, 0xf6, 0x22, 0x72, 0x0d, 0x01, 0x49, - 0x29, 0x69, 0x2f, 0xb6, 0xd2, 0x00, 0x94, 0x8d, 0x81, 0x1d, 0xb0, 0xe2, 0x99, 0x59, 0x2a, 0xbf, - 0x5c, 0xae, 0x09, 0xaa, 0x95, 0xc3, 0x2c, 0x04, 0xc9, 0xe2, 0xe0, 0x8f, 0x13, 0x8e, 0x63, 0x96, - 0x1f, 0x04, 0xaf, 0x9c, 0x5e, 0xd1, 0x53, 0x5b, 0x0e, 0x78, 0x0f, 0x2c, 0x3a, 0xdc, 0x50, 0x06, - 0x59, 0xfa, 0xa6, 0xec, 0x2b, 0x22, 0x6c, 0x11, 0xc5, 0x3b, 0x51, 0x12, 0x2b, 0xf1, 0x51, 0x95, - 0x69, 0x7d, 0x54, 0xe3, 0x4f, 0x0a, 0x80, 0xd9, 0x2d, 0x38, 0xf1, 0xe5, 0x3e, 0x13, 0x11, 0x93, - 0xc8, 0xbe, 0xdc, 0xe1, 0xdc, 0x9a, 0xec, 0x70, 0xa2, 0x13, 0x74, 0x3a, 0x8b, 0x23, 0x66, 0xe0, - 0x62, 0x2e, 0x66, 0xa6, 0xb0, 0x38, 0x51, 0x3e, 0xcf, 0x66, 0x71, 0x62, 0x3c, 0xa7, 0x5b, 0x9c, - 0x7f, 0x17, 0xc0, 0x4a, 0x04, 0x9e, 0xda, 0xe2, 0x48, 0x42, 0x5e, 0x5c, 0xce, 0x4c, 0xbe, 0x9c, - 0x61, 0xb6, 0x23, 0x9a, 0xba, 0xff, 0x13, 0xdb, 0x11, 0x25, 0x94, 0x63, 0x3b, 0x7e, 0x57, 0x88, - 0x67, 0xfd, 0xa5, 0xb7, 0x1d, 0xcf, 0x7e, 0xb9, 0xd2, 0xf8, 0x4b, 0x11, 0x5c, 0x4e, 0x6f, 0xc1, - 0x84, 0x0e, 0x2a, 0x13, 0x75, 0x70, 0x1f, 0xac, 0x3e, 0xf2, 0x74, 0x7d, 0xc4, 0xa7, 0x21, 0x26, - 0x86, 0xbe, 0x82, 0x7e, 0x55, 0x44, 0xae, 0x7e, 0x5f, 0x82, 0x41, 0xd2, 0xc8, 0x1c, 0x4d, 0x2f, - 0x9e, 0x4b, 0xd3, 0x33, 0x6a, 0x53, 0x3a, 0x83, 0xda, 0x48, 0xf5, 0xb9, 0x7c, 0x0e, 0x7d, 0x9e, - 0x5a, 0x50, 0x25, 0xc7, 0xd5, 0xc4, 0x77, 0xf8, 0x5f, 0x2b, 0x60, 0x4d, 0xfe, 0xfa, 0x0c, 0x75, - 0xb0, 0x64, 0xe0, 0xc7, 0xf1, 0xcb, 0x8b, 0x49, 0x82, 0xe1, 0x51, 0x4d, 0x57, 0xfd, 0xaf, 0x3b, - 0xea, 0xbb, 0x26, 0xdd, 0x73, 0x0e, 0xa8, 0xa3, 0x99, 0x03, 0x5f, 0x60, 0x3b, 0x09, 0x2e, 0x94, - 0xe2, 0x6e, 0x7c, 0xa2, 0x80, 0xf5, 0x1c, 0x95, 0xbb, 0xd8, 0x4c, 0xe0, 0x43, 0x50, 0x31, 0xf0, - 0xe3, 0x03, 0xcf, 0x19, 0x04, 0x92, 0x7c, 0xf6, 0xe7, 0xf0, 0x8d, 0xdc, 0x11, 0x2c, 0x28, 0xe4, - 0x6b, 0xec, 0x81, 0xeb, 0x89, 0x41, 0xb2, 0x4d, 0x43, 0x1e, 0x79, 0x3a, 0xdf, 0x3f, 0xc2, 0x53, - 0xdc, 0x02, 0xf3, 0x36, 0x76, 0xa8, 0x16, 0x9a, 0xd1, 0x72, 0x6b, 0x71, 0x7c, 0x52, 0x9f, 0xdf, - 0x0f, 0x1a, 0x51, 0xd4, 0xdf, 0xf8, 0x55, 0x01, 0x2c, 0xc4, 0x48, 0x2e, 0x40, 0xdf, 0xdf, 0x4e, - 0xe8, 0xbb, 0xf4, 0x8b, 0x49, 0x7c, 0x54, 0x79, 0x02, 0xdf, 0x49, 0x09, 0xfc, 0x37, 0x27, 0x11, - 0x9d, 0xae, 0xf0, 0x9f, 0x16, 0xc0, 0x6a, 0x0c, 0x1d, 0x49, 0xfc, 0x77, 0x12, 0x12, 0xbf, 0x91, - 0x92, 0xf8, 0xaa, 0x2c, 0xe6, 0x85, 0xc6, 0x4f, 0xd6, 0xf8, 0x3f, 0x2a, 0x60, 0x39, 0x36, 0x77, - 0x17, 0x20, 0xf2, 0xdb, 0x49, 0x91, 0xaf, 0x4f, 0xa8, 0x97, 0x1c, 0x95, 0x7f, 0x52, 0x4e, 0xe4, - 0xfd, 0xa5, 0x97, 0xf9, 0x9f, 0x83, 0xd5, 0xa1, 0xa5, 0x7b, 0x06, 0x69, 0xeb, 0x58, 0x33, 0x02, - 0x00, 0x53, 0x32, 0x36, 0x89, 0x37, 0xa5, 0xf4, 0xc4, 0x71, 0x35, 0x97, 0x12, 0x93, 0x3e, 0x88, - 0x22, 0x23, 0x2d, 0x7e, 0x20, 0xa1, 0x43, 0xd2, 0x87, 0xc0, 0x37, 0xc0, 0x02, 0xd3, 0x54, 0xad, - 0x47, 0x76, 0xb1, 0x11, 0xd4, 0x54, 0xf8, 0x7d, 0xe0, 0x20, 0xea, 0x42, 0x71, 0x1c, 0x3c, 0x02, - 0x2b, 0xb6, 0xd5, 0xef, 0x60, 0x13, 0x0f, 0x08, 0x3b, 0xff, 0xf7, 0xf9, 0xff, 0x42, 0xf0, 0x7b, - 0x87, 0xf9, 0xd6, 0x9b, 0xc1, 0x0b, 0xe9, 0x7e, 0x16, 0xc2, 0x3c, 0xbb, 0xa4, 0x99, 0xef, 0x67, - 0x19, 0x25, 0x34, 0x32, 0x9f, 0xb3, 0xe6, 0x32, 0xff, 0x03, 0x20, 0x2b, 0xae, 0x73, 0x7e, 0xd0, - 0xca, 0xbb, 0x51, 0xa9, 0x9c, 0xeb, 0x6b, 0xd4, 0xa7, 0x25, 0x70, 0x25, 0x73, 0x40, 0x7e, 0x81, - 0x77, 0x1a, 0x19, 0xb7, 0x54, 0x3c, 0x83, 0x5b, 0xda, 0x02, 0xcb, 0xe2, 0x43, 0x58, 0xca, 0x6c, - 0x85, 0x76, 0xb4, 0x9d, 0xec, 0x46, 0x69, 0xbc, 0xec, 0x4e, 0xa5, 0x7c, 0xc6, 0x3b, 0x95, 0x78, - 0x16, 0xe2, 0xff, 0x37, 0xfc, 0xaa, 0xcb, 0x66, 0x21, 0xfe, 0x8d, 0x23, 0x8d, 0x87, 0xdf, 0x0d, - 0x4a, 0x2a, 0x64, 0x98, 0xe3, 0x0c, 0xa9, 0x1a, 0x09, 0x09, 0x52, 0xe8, 0x67, 0xfa, 0xd8, 0xf3, - 0xbe, 0xe4, 0x63, 0xcf, 0xc6, 0x84, 0x52, 0x9e, 0xde, 0x2a, 0xfe, 0x4d, 0x01, 0x2f, 0xe5, 0xee, - 0x01, 0xb8, 0x95, 0xd0, 0xd9, 0xdb, 0x29, 0x9d, 0x7d, 0x39, 0x37, 0x30, 0x26, 0xb6, 0x86, 0xfc, - 0x42, 0xe4, 0xee, 0xc4, 0x0b, 0x11, 0x89, 0x8b, 0x9a, 0x7c, 0x33, 0xd2, 0xda, 0x78, 0xf2, 0xb4, - 0x36, 0xf3, 0xd1, 0xd3, 0xda, 0xcc, 0xc7, 0x4f, 0x6b, 0x33, 0xbf, 0x18, 0xd7, 0x94, 0x27, 0xe3, - 0x9a, 0xf2, 0xd1, 0xb8, 0xa6, 0x7c, 0x3c, 0xae, 0x29, 0xff, 0x1c, 0xd7, 0x94, 0xdf, 0x7e, 0x52, - 0x9b, 0x79, 0x58, 0x18, 0x6e, 0xfe, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x70, 0x5f, 0xbf, 0x58, 0x3d, - 0x26, 0x00, 0x00, + 0x60, 0xe3, 0x64, 0xb3, 0x3d, 0xec, 0x66, 0x13, 0xa1, 0x2c, 0x02, 0x79, 0xc6, 0x21, 0x84, 0x78, + 0x6c, 0x53, 0x5e, 0xef, 0x61, 0x09, 0x12, 0xe5, 0xe9, 0xda, 0x71, 0xc7, 0xfd, 0xa5, 0xee, 0xea, + 0x61, 0x47, 0x5c, 0x10, 0x12, 0x9c, 0x38, 0xf0, 0x9f, 0x20, 0x84, 0xe0, 0x86, 0x22, 0xc4, 0x65, + 0x2f, 0x48, 0x11, 0x17, 0x72, 0xb2, 0xd8, 0xc9, 0x09, 0xa1, 0x1c, 0xb9, 0xe4, 0x02, 0xaa, 0xea, + 0xea, 0xef, 0x6a, 0xcf, 0xd8, 0x9b, 0x75, 0x50, 0x94, 0x9b, 0xa7, 0xea, 0xfd, 0x5e, 0xff, 0xaa, + 0xea, 0x57, 0xf5, 0x5e, 0x57, 0x1b, 0xdc, 0x3b, 0xfe, 0xb6, 0xa7, 0xea, 0x76, 0xfb, 0xd8, 0x3f, + 0x24, 0xae, 0x45, 0x28, 0xf1, 0xda, 0x43, 0x62, 0x69, 0xb6, 0xdb, 0x16, 0x1d, 0xd8, 0xd1, 0xdb, + 0xd8, 0x71, 0xbc, 0xf6, 0xf0, 0x76, 0x7b, 0x40, 0x2c, 0xe2, 0x62, 0x4a, 0x34, 0xd5, 0x71, 0x6d, + 0x6a, 0x43, 0x18, 0x60, 0x54, 0xec, 0xe8, 0x2a, 0xc3, 0xa8, 0xc3, 0xdb, 0x57, 0x6f, 0x0d, 0x74, + 0x7a, 0xe4, 0x1f, 0xaa, 0x7d, 0xdb, 0x6c, 0x0f, 0xec, 0x81, 0xdd, 0xe6, 0xd0, 0x43, 0xff, 0x11, + 0xff, 0xc5, 0x7f, 0xf0, 0xbf, 0x02, 0x8a, 0xab, 0xad, 0xc4, 0x63, 0xfa, 0xb6, 0x4b, 0x24, 0x8f, + 0xb9, 0x7a, 0x37, 0xc6, 0x98, 0xb8, 0x7f, 0xa4, 0x5b, 0xc4, 0x1d, 0xb5, 0x9d, 0xe3, 0x01, 0x6b, + 0xf0, 0xda, 0x26, 0xa1, 0x58, 0x16, 0xd5, 0x2e, 0x8a, 0x72, 0x7d, 0x8b, 0xea, 0x26, 0xc9, 0x05, + 0xbc, 0x31, 0x29, 0xc0, 0xeb, 0x1f, 0x11, 0x13, 0xe7, 0xe2, 0x5e, 0x2b, 0x8a, 0xf3, 0xa9, 0x6e, + 0xb4, 0x75, 0x8b, 0x7a, 0xd4, 0xcd, 0x06, 0xb5, 0xfe, 0xa3, 0x00, 0xd8, 0xb5, 0x2d, 0xea, 0xda, + 0x86, 0x41, 0x5c, 0x44, 0x86, 0xba, 0xa7, 0xdb, 0x16, 0xfc, 0x29, 0xa8, 0xb1, 0xf1, 0x68, 0x98, + 0xe2, 0xba, 0x72, 0x5d, 0xd9, 0x58, 0xb8, 0xf3, 0x2d, 0x35, 0x9e, 0xe4, 0x88, 0x5e, 0x75, 0x8e, + 0x07, 0xac, 0xc1, 0x53, 0x19, 0x5a, 0x1d, 0xde, 0x56, 0x77, 0x0f, 0xdf, 0x27, 0x7d, 0xda, 0x23, + 0x14, 0x77, 0xe0, 0x93, 0x93, 0xe6, 0xcc, 0xf8, 0xa4, 0x09, 0xe2, 0x36, 0x14, 0xb1, 0xc2, 0x5d, + 0x50, 0xe1, 0xec, 0x25, 0xce, 0x7e, 0xab, 0x90, 0x5d, 0x0c, 0x5a, 0x45, 0xf8, 0x67, 0x6f, 0x3d, + 0xa6, 0xc4, 0x62, 0xe9, 0x75, 0x2e, 0x09, 0xea, 0xca, 0x16, 0xa6, 0x18, 0x71, 0x22, 0xf8, 0x2a, + 0xa8, 0xb9, 0x22, 0xfd, 0x7a, 0xf9, 0xba, 0xb2, 0x51, 0xee, 0x5c, 0x16, 0xa8, 0x5a, 0x38, 0x2c, + 0x14, 0x21, 0x5a, 0x7f, 0x55, 0xc0, 0x5a, 0x7e, 0xdc, 0xdb, 0xba, 0x47, 0xe1, 0x7b, 0xb9, 0xb1, + 0xab, 0xd3, 0x8d, 0x9d, 0x45, 0xf3, 0x91, 0x47, 0x0f, 0x0e, 0x5b, 0x12, 0xe3, 0x7e, 0x17, 0x54, + 0x75, 0x4a, 0x4c, 0xaf, 0x5e, 0xba, 0x5e, 0xde, 0x58, 0xb8, 0x73, 0x43, 0xcd, 0xd7, 0xae, 0x9a, + 0x4f, 0xac, 0xb3, 0x28, 0x28, 0xab, 0xef, 0xb0, 0x60, 0x14, 0x70, 0xb4, 0xfe, 0xab, 0x80, 0xf9, + 0x2d, 0x4c, 0x4c, 0xdb, 0xda, 0x27, 0xf4, 0x02, 0x16, 0xad, 0x0b, 0x2a, 0x9e, 0x43, 0xfa, 0x62, + 0xd1, 0xbe, 0x26, 0xcb, 0x3d, 0x4a, 0x67, 0xdf, 0x21, 0xfd, 0x78, 0xa1, 0xd8, 0x2f, 0xc4, 0x83, + 0xe1, 0xbb, 0x60, 0xd6, 0xa3, 0x98, 0xfa, 0x1e, 0x5f, 0xa6, 0x85, 0x3b, 0x5f, 0x3f, 0x9d, 0x86, + 0x43, 0x3b, 0x4b, 0x82, 0x68, 0x36, 0xf8, 0x8d, 0x04, 0x45, 0xeb, 0x5f, 0x25, 0x00, 0x23, 0x6c, + 0xd7, 0xb6, 0x34, 0x9d, 0xb2, 0xfa, 0x7d, 0x13, 0x54, 0xe8, 0xc8, 0x21, 0x7c, 0x1a, 0xe6, 0x3b, + 0x37, 0xc2, 0x2c, 0xee, 0x8f, 0x1c, 0xf2, 0xe9, 0x49, 0x73, 0x2d, 0x1f, 0xc1, 0x7a, 0x10, 0x8f, + 0x81, 0xdb, 0x51, 0x7e, 0x25, 0x1e, 0x7d, 0x37, 0xfd, 0xe8, 0x4f, 0x4f, 0x9a, 0x92, 0xc3, 0x42, + 0x8d, 0x98, 0xd2, 0x09, 0xc2, 0x21, 0x80, 0x06, 0xf6, 0xe8, 0x7d, 0x17, 0x5b, 0x5e, 0xf0, 0x24, + 0xdd, 0x24, 0x62, 0xe4, 0xaf, 0x4c, 0xb7, 0x3c, 0x2c, 0xa2, 0x73, 0x55, 0x64, 0x01, 0xb7, 0x73, + 0x6c, 0x48, 0xf2, 0x04, 0x78, 0x03, 0xcc, 0xba, 0x04, 0x7b, 0xb6, 0x55, 0xaf, 0xf0, 0x51, 0x44, + 0x13, 0x88, 0x78, 0x2b, 0x12, 0xbd, 0xf0, 0x65, 0x30, 0x67, 0x12, 0xcf, 0xc3, 0x03, 0x52, 0xaf, + 0x72, 0xe0, 0xb2, 0x00, 0xce, 0xf5, 0x82, 0x66, 0x14, 0xf6, 0xb7, 0x7e, 0xaf, 0x80, 0xc5, 0x68, + 0xe6, 0x2e, 0x60, 0xab, 0x74, 0xd2, 0x5b, 0xe5, 0xc5, 0x53, 0xeb, 0xa4, 0x60, 0x87, 0x7c, 0x50, + 0x4e, 0xe4, 0xcc, 0x8a, 0x10, 0xfe, 0x04, 0xd4, 0x3c, 0x62, 0x90, 0x3e, 0xb5, 0x5d, 0x91, 0xf3, + 0x6b, 0x53, 0xe6, 0x8c, 0x0f, 0x89, 0xb1, 0x2f, 0x42, 0x3b, 0x97, 0x58, 0xd2, 0xe1, 0x2f, 0x14, + 0x51, 0xc2, 0x1f, 0x81, 0x1a, 0x25, 0xa6, 0x63, 0x60, 0x4a, 0xc4, 0x36, 0x49, 0xd5, 0x37, 0x2b, + 0x17, 0x46, 0xb6, 0x67, 0x6b, 0xf7, 0x05, 0x8c, 0x6f, 0x94, 0x68, 0x1e, 0xc2, 0x56, 0x14, 0xd1, + 0xc0, 0x63, 0xb0, 0xe4, 0x3b, 0x1a, 0x43, 0x52, 0x76, 0x74, 0x0f, 0x46, 0xa2, 0x7c, 0x6e, 0x9e, + 0x3a, 0x21, 0x07, 0xa9, 0x90, 0xce, 0x9a, 0x78, 0xc0, 0x52, 0xba, 0x1d, 0x65, 0xa8, 0xe1, 0x26, + 0x58, 0x36, 0x75, 0x0b, 0x11, 0xac, 0x8d, 0xf6, 0x49, 0xdf, 0xb6, 0x34, 0x8f, 0x17, 0x50, 0xb5, + 0xb3, 0x2e, 0x08, 0x96, 0x7b, 0xe9, 0x6e, 0x94, 0xc5, 0xc3, 0x6d, 0xb0, 0x1a, 0x9e, 0xb3, 0x3f, + 0xd0, 0x3d, 0x6a, 0xbb, 0xa3, 0x6d, 0xdd, 0xd4, 0x69, 0x7d, 0x96, 0xf3, 0xd4, 0xc7, 0x27, 0xcd, + 0x55, 0x24, 0xe9, 0x47, 0xd2, 0xa8, 0xd6, 0x6f, 0x66, 0xc1, 0x72, 0xe6, 0x34, 0x80, 0x0f, 0xc0, + 0x5a, 0xdf, 0x77, 0x5d, 0x62, 0xd1, 0x1d, 0xdf, 0x3c, 0x24, 0xee, 0x7e, 0xff, 0x88, 0x68, 0xbe, + 0x41, 0x34, 0xbe, 0xa2, 0xd5, 0x4e, 0x43, 0xe4, 0xba, 0xd6, 0x95, 0xa2, 0x50, 0x41, 0x34, 0xfc, + 0x21, 0x80, 0x16, 0x6f, 0xea, 0xe9, 0x9e, 0x17, 0x71, 0x96, 0x38, 0x67, 0xb4, 0x01, 0x77, 0x72, + 0x08, 0x24, 0x89, 0x62, 0x39, 0x6a, 0xc4, 0xd3, 0x5d, 0xa2, 0x65, 0x73, 0x2c, 0xa7, 0x73, 0xdc, + 0x92, 0xa2, 0x50, 0x41, 0x34, 0x7c, 0x1d, 0x2c, 0x04, 0x4f, 0xe3, 0x73, 0x2e, 0x16, 0x67, 0x45, + 0x90, 0x2d, 0xec, 0xc4, 0x5d, 0x28, 0x89, 0x63, 0x43, 0xb3, 0x0f, 0x3d, 0xe2, 0x0e, 0x89, 0xf6, + 0x76, 0xe0, 0x01, 0x98, 0x50, 0x56, 0xb9, 0x50, 0x46, 0x43, 0xdb, 0xcd, 0x21, 0x90, 0x24, 0x8a, + 0x0d, 0x2d, 0xa8, 0x9a, 0xdc, 0xd0, 0x66, 0xd3, 0x43, 0x3b, 0x90, 0xa2, 0x50, 0x41, 0x34, 0xab, + 0xbd, 0x20, 0xe5, 0xcd, 0x21, 0xd6, 0x0d, 0x7c, 0x68, 0x90, 0xfa, 0x5c, 0xba, 0xf6, 0x76, 0xd2, + 0xdd, 0x28, 0x8b, 0x87, 0x6f, 0x83, 0x2b, 0x41, 0xd3, 0x81, 0x85, 0x23, 0x92, 0x1a, 0x27, 0x79, + 0x41, 0x90, 0x5c, 0xd9, 0xc9, 0x02, 0x50, 0x3e, 0x06, 0xbe, 0x09, 0x96, 0xfa, 0xb6, 0x61, 0xf0, + 0x7a, 0xec, 0xda, 0xbe, 0x45, 0xeb, 0xf3, 0x9c, 0x05, 0xb2, 0x3d, 0xd4, 0x4d, 0xf5, 0xa0, 0x0c, + 0x12, 0x3e, 0x04, 0xa0, 0x1f, 0xca, 0x81, 0x57, 0x07, 0xc5, 0x42, 0x9f, 0xd7, 0xa1, 0x58, 0x80, + 0xa3, 0x26, 0x0f, 0x25, 0xd8, 0x5a, 0x1f, 0x28, 0x60, 0xbd, 0x60, 0x8f, 0xc3, 0xef, 0xa5, 0x54, + 0xef, 0x66, 0x46, 0xf5, 0xae, 0x15, 0x84, 0x25, 0xa4, 0xaf, 0x0f, 0x16, 0x99, 0xef, 0xd0, 0xad, + 0x41, 0x00, 0x11, 0x27, 0xd8, 0x2b, 0xb2, 0xdc, 0x51, 0x12, 0x18, 0x1f, 0xc3, 0x57, 0xc6, 0x27, + 0xcd, 0xc5, 0x54, 0x1f, 0x4a, 0x73, 0xb6, 0x7e, 0x59, 0x02, 0x60, 0x8b, 0x38, 0x86, 0x3d, 0x32, + 0x89, 0x75, 0x11, 0xae, 0x65, 0x2b, 0xe5, 0x5a, 0x5a, 0xd2, 0x85, 0x88, 0xf2, 0x29, 0xb4, 0x2d, + 0xdb, 0x19, 0xdb, 0xf2, 0x8d, 0x09, 0x3c, 0xa7, 0xfb, 0x96, 0x7f, 0x94, 0xc1, 0x4a, 0x0c, 0x8e, + 0x8d, 0xcb, 0xbd, 0xd4, 0x12, 0xbe, 0x94, 0x59, 0xc2, 0x75, 0x49, 0xc8, 0x73, 0x73, 0x2e, 0x9f, + 0xbd, 0x83, 0x80, 0xef, 0x83, 0x25, 0x66, 0x55, 0x82, 0x42, 0xe0, 0x46, 0x68, 0xf6, 0xcc, 0x46, + 0x28, 0x12, 0xb2, 0xed, 0x14, 0x13, 0xca, 0x30, 0x17, 0x18, 0xaf, 0xb9, 0xe7, 0x6d, 0xbc, 0x5a, + 0x7f, 0x50, 0xc0, 0x52, 0xbc, 0x4c, 0x17, 0x60, 0x93, 0xba, 0x69, 0x9b, 0xd4, 0x38, 0xbd, 0x2e, + 0x0b, 0x7c, 0xd2, 0xdf, 0x2b, 0xc9, 0xac, 0xb9, 0x51, 0xda, 0x60, 0x2f, 0x54, 0x8e, 0xa1, 0xf7, + 0xb1, 0x27, 0x64, 0xf5, 0x52, 0xf0, 0x32, 0x15, 0xb4, 0xa1, 0xa8, 0x37, 0x65, 0xa9, 0x4a, 0xcf, + 0xd7, 0x52, 0x95, 0x3f, 0x1b, 0x4b, 0x75, 0x1f, 0xd4, 0xbc, 0xd0, 0x4c, 0x55, 0x38, 0xe5, 0x8d, + 0x49, 0xdb, 0x59, 0xf8, 0xa8, 0x88, 0x35, 0x72, 0x50, 0x11, 0x93, 0xcc, 0x3b, 0x55, 0x3f, 0x4f, + 0xef, 0xc4, 0xb6, 0xb0, 0x83, 0x7d, 0x8f, 0x68, 0xbc, 0xee, 0x6b, 0xf1, 0x16, 0xde, 0xe3, 0xad, + 0x48, 0xf4, 0xc2, 0x03, 0xb0, 0xee, 0xb8, 0xf6, 0xc0, 0x25, 0x9e, 0xb7, 0x45, 0xb0, 0x66, 0xe8, + 0x16, 0x09, 0x07, 0x10, 0xa8, 0xde, 0xb5, 0xf1, 0x49, 0x73, 0x7d, 0x4f, 0x0e, 0x41, 0x45, 0xb1, + 0xad, 0x3f, 0x57, 0xc0, 0xe5, 0xec, 0x89, 0x58, 0x60, 0x44, 0x94, 0x73, 0x19, 0x91, 0x57, 0x13, + 0x25, 0x1a, 0xb8, 0xb4, 0xc4, 0x3b, 0x7f, 0xae, 0x4c, 0x37, 0xc1, 0xb2, 0x30, 0x1e, 0x61, 0xa7, + 0xb0, 0x62, 0xd1, 0xf2, 0x1c, 0xa4, 0xbb, 0x51, 0x16, 0xcf, 0xec, 0x45, 0xec, 0x1a, 0x42, 0x92, + 0x4a, 0xda, 0x5e, 0x6c, 0x66, 0x01, 0x28, 0x1f, 0x03, 0x7b, 0x60, 0xc5, 0xb7, 0xf2, 0x54, 0x41, + 0xb9, 0x5c, 0x13, 0x54, 0x2b, 0x07, 0x79, 0x08, 0x92, 0xc5, 0xc1, 0x1f, 0xa7, 0x1c, 0xc7, 0x2c, + 0x3f, 0x08, 0x5e, 0x3a, 0xbd, 0xa2, 0xa7, 0xb6, 0x1c, 0xf0, 0x1e, 0x58, 0x74, 0xb9, 0xa1, 0x0c, + 0xb3, 0x0c, 0x4c, 0xd9, 0x57, 0x44, 0xd8, 0x22, 0x4a, 0x76, 0xa2, 0x34, 0x56, 0xe2, 0xa3, 0x6a, + 0xd3, 0xfa, 0xa8, 0xd6, 0x9f, 0x14, 0x00, 0xf3, 0x5b, 0x70, 0xe2, 0xcb, 0x7d, 0x2e, 0x22, 0x21, + 0x91, 0x9a, 0xdc, 0xe1, 0xdc, 0x9c, 0xec, 0x70, 0xe2, 0x13, 0x74, 0x3a, 0x8b, 0x23, 0x66, 0xe0, + 0x62, 0x2e, 0x66, 0xa6, 0xb0, 0x38, 0x71, 0x3e, 0xcf, 0x66, 0x71, 0x12, 0x3c, 0xa7, 0x5b, 0x9c, + 0x7f, 0x97, 0xc0, 0x4a, 0x0c, 0x9e, 0xda, 0xe2, 0x48, 0x42, 0xbe, 0xbc, 0x9c, 0x99, 0x7c, 0x39, + 0xc3, 0x6c, 0x47, 0x3c, 0x75, 0xff, 0x27, 0xb6, 0x23, 0x4e, 0xa8, 0xc0, 0x76, 0xfc, 0xae, 0x94, + 0xcc, 0xfa, 0x0b, 0x6f, 0x3b, 0x9e, 0xfd, 0x72, 0xa5, 0xf5, 0x97, 0x32, 0xb8, 0x9c, 0xdd, 0x82, + 0x29, 0x1d, 0x54, 0x26, 0xea, 0xe0, 0x1e, 0x58, 0x7d, 0xe4, 0x1b, 0xc6, 0x88, 0x4f, 0x43, 0x42, + 0x0c, 0x03, 0x05, 0xfd, 0xaa, 0x88, 0x5c, 0xfd, 0xbe, 0x04, 0x83, 0xa4, 0x91, 0x05, 0x9a, 0x5e, + 0x3e, 0x97, 0xa6, 0xe7, 0xd4, 0xa6, 0x72, 0x06, 0xb5, 0x91, 0xea, 0x73, 0xf5, 0x1c, 0xfa, 0x3c, + 0xb5, 0xa0, 0x4a, 0x8e, 0xab, 0x89, 0xef, 0xf0, 0xbf, 0x56, 0xc0, 0x9a, 0xfc, 0xf5, 0x19, 0x1a, + 0x60, 0xc9, 0xc4, 0x8f, 0x93, 0x97, 0x17, 0x93, 0x04, 0xc3, 0xa7, 0xba, 0xa1, 0x06, 0x5f, 0x77, + 0xd4, 0x77, 0x2c, 0xba, 0xeb, 0xee, 0x53, 0x57, 0xb7, 0x06, 0x81, 0xc0, 0xf6, 0x52, 0x5c, 0x28, + 0xc3, 0xdd, 0xfa, 0x58, 0x01, 0xeb, 0x05, 0x2a, 0x77, 0xb1, 0x99, 0xc0, 0x87, 0xa0, 0x66, 0xe2, + 0xc7, 0xfb, 0xbe, 0x3b, 0x08, 0x25, 0xf9, 0xec, 0xcf, 0xe1, 0x1b, 0xb9, 0x27, 0x58, 0x50, 0xc4, + 0xd7, 0xda, 0x05, 0xd7, 0x53, 0x83, 0x64, 0x9b, 0x86, 0x3c, 0xf2, 0x0d, 0xbe, 0x7f, 0x84, 0xa7, + 0xb8, 0x09, 0xe6, 0x1d, 0xec, 0x52, 0x3d, 0x32, 0xa3, 0xd5, 0xce, 0xe2, 0xf8, 0xa4, 0x39, 0xbf, + 0x17, 0x36, 0xa2, 0xb8, 0xbf, 0xf5, 0xab, 0x12, 0x58, 0x48, 0x90, 0x5c, 0x80, 0xbe, 0xbf, 0x95, + 0xd2, 0x77, 0xe9, 0x17, 0x93, 0xe4, 0xa8, 0x8a, 0x04, 0xbe, 0x97, 0x11, 0xf8, 0x6f, 0x4e, 0x22, + 0x3a, 0x5d, 0xe1, 0x3f, 0x29, 0x81, 0xd5, 0x04, 0x3a, 0x96, 0xf8, 0xef, 0xa4, 0x24, 0x7e, 0x23, + 0x23, 0xf1, 0x75, 0x59, 0xcc, 0x97, 0x1a, 0x3f, 0x59, 0xe3, 0xff, 0xa8, 0x80, 0xe5, 0xc4, 0xdc, + 0x5d, 0x80, 0xc8, 0x6f, 0xa5, 0x45, 0xbe, 0x39, 0xa1, 0x5e, 0x0a, 0x54, 0xfe, 0x49, 0x35, 0x95, + 0xf7, 0x17, 0x5e, 0xe6, 0x7f, 0x0e, 0x56, 0x87, 0xb6, 0xe1, 0x9b, 0xa4, 0x6b, 0x60, 0xdd, 0x0c, + 0x01, 0x4c, 0xc9, 0xd8, 0x24, 0xbe, 0x2c, 0xa5, 0x27, 0xae, 0xa7, 0x7b, 0x94, 0x58, 0xf4, 0x41, + 0x1c, 0x19, 0x6b, 0xf1, 0x03, 0x09, 0x1d, 0x92, 0x3e, 0x04, 0xbe, 0x0e, 0x16, 0x98, 0xa6, 0xea, + 0x7d, 0xb2, 0x83, 0xcd, 0xb0, 0xa6, 0xa2, 0xef, 0x03, 0xfb, 0x71, 0x17, 0x4a, 0xe2, 0xe0, 0x11, + 0x58, 0x71, 0x6c, 0xad, 0x87, 0x2d, 0x3c, 0x20, 0xec, 0xfc, 0xdf, 0xb3, 0x0d, 0xbd, 0x3f, 0xe2, + 0xf7, 0x0e, 0xf3, 0x9d, 0x37, 0xc2, 0x17, 0xd2, 0xbd, 0x3c, 0x84, 0x79, 0x76, 0x49, 0x33, 0xdf, + 0xcf, 0x32, 0x4a, 0x68, 0xe6, 0x3e, 0x67, 0xcd, 0xe5, 0xfe, 0x07, 0x40, 0x56, 0x5c, 0xe7, 0xfc, + 0xa0, 0x55, 0x74, 0xa3, 0x52, 0x3b, 0xd7, 0xd7, 0xa8, 0x4f, 0x2a, 0xe0, 0x4a, 0xee, 0x80, 0xfc, + 0x1c, 0xef, 0x34, 0x72, 0x6e, 0xa9, 0x7c, 0x06, 0xb7, 0xb4, 0x09, 0x96, 0xc5, 0x87, 0xb0, 0x8c, + 0xd9, 0x8a, 0xec, 0x68, 0x37, 0xdd, 0x8d, 0xb2, 0x78, 0xd9, 0x9d, 0x4a, 0xf5, 0x8c, 0x77, 0x2a, + 0xc9, 0x2c, 0xc4, 0xff, 0x6f, 0x04, 0x55, 0x97, 0xcf, 0x42, 0xfc, 0x1b, 0x47, 0x16, 0x0f, 0xbf, + 0x1b, 0x96, 0x54, 0xc4, 0x30, 0xc7, 0x19, 0x32, 0x35, 0x12, 0x11, 0x64, 0xd0, 0xcf, 0xf4, 0xb1, + 0xe7, 0x3d, 0xc9, 0xc7, 0x9e, 0x8d, 0x09, 0xa5, 0x3c, 0xbd, 0x55, 0xfc, 0x9b, 0x02, 0x5e, 0x28, + 0xdc, 0x03, 0x70, 0x33, 0xa5, 0xb3, 0xb7, 0x32, 0x3a, 0xfb, 0x62, 0x61, 0x60, 0x42, 0x6c, 0x4d, + 0xf9, 0x85, 0xc8, 0xdd, 0x89, 0x17, 0x22, 0x12, 0x17, 0x35, 0xf9, 0x66, 0xa4, 0xb3, 0xf1, 0xe4, + 0x69, 0x63, 0xe6, 0xc3, 0xa7, 0x8d, 0x99, 0x8f, 0x9e, 0x36, 0x66, 0x7e, 0x31, 0x6e, 0x28, 0x4f, + 0xc6, 0x0d, 0xe5, 0xc3, 0x71, 0x43, 0xf9, 0x68, 0xdc, 0x50, 0xfe, 0x39, 0x6e, 0x28, 0xbf, 0xfd, + 0xb8, 0x31, 0xf3, 0xb0, 0x34, 0xbc, 0xfd, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x6b, 0x01, + 0x7b, 0x12, 0x26, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/generated.proto index 46473baa8..c8a957ac6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,7 +22,6 @@ syntax = 'proto2'; package k8s.io.api.apps.v1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; @@ -501,9 +500,9 @@ message RollingUpdateDeployment { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -515,10 +514,10 @@ message RollingUpdateDeployment { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is at most 130% of desired pods. // +optional optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/types.go index b5df22c6f..4431ca2c3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/types.go @@ -307,8 +307,8 @@ type DeploymentSpec struct { const ( // DefaultDeploymentUniqueLabelKey is the default key of the selector that is added - // to existing RCs (and label key that is added to its pods) to prevent the existing RCs - // to select new pods (and old pods being select by new RC). + // to existing ReplicaSets (and label key that is added to its pods) to prevent the existing ReplicaSets + // to select new pods (and old pods being select by new ReplicaSet). DefaultDeploymentUniqueLabelKey string = "pod-template-hash" ) @@ -333,7 +333,7 @@ const ( // Kill all existing pods before creating new ones. RecreateDeploymentStrategyType DeploymentStrategyType = "Recreate" - // Replace the old RCs by new one using rolling update i.e gradually scale down the old RCs and scale up the new one. + // Replace the old ReplicaSets by new one using rolling update i.e gradually scale down the old ReplicaSets and scale up the new one. RollingUpdateDeploymentStrategyType DeploymentStrategyType = "RollingUpdate" ) @@ -344,9 +344,9 @@ type RollingUpdateDeployment struct { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -358,10 +358,10 @@ type RollingUpdateDeployment struct { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is at most 130% of desired pods. // +optional MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/types_swagger_doc_generated.go index 4dec6f2f8..85fb159dd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_ControllerRevision = map[string]string{ "": "ControllerRevision implements an immutable snapshot of state data. Clients are responsible for serializing and deserializing the objects that contain their internal state. Once a ControllerRevision has been successfully created, it can not be updated. The API Server will fail validation of all requests that attempt to mutate the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, it may be subject to name and representation changes in future releases, and clients should not depend on its stability. It is primarily for internal use by controllers.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -271,8 +271,8 @@ func (RollingUpdateDaemonSet) SwaggerDoc() map[string]string { var map_RollingUpdateDeployment = map[string]string{ "": "Spec to control the desired behavior of rolling update.", - "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", - "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.", + "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.", } func (RollingUpdateDeployment) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/zz_generated.deepcopy.go index 62984cb89..ccbb29061 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/generated.pb.go index 04183fc2d..ef9aa8e09 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -54,7 +54,6 @@ import fmt "fmt" import math "math" import k8s_io_api_core_v1 "k8s.io/api/core/v1" - import k8s_io_apimachinery_pkg_apis_meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" import k8s_io_apimachinery_pkg_util_intstr "k8s.io/apimachinery/pkg/util/intstr" @@ -5170,122 +5169,122 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1871 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0x4f, 0x6f, 0x1b, 0xc7, - 0x15, 0xd7, 0x52, 0xa4, 0x44, 0x3d, 0x45, 0x94, 0x3d, 0x52, 0x2d, 0x46, 0x69, 0x29, 0x61, 0x1b, - 0x24, 0x72, 0x12, 0x2d, 0x63, 0x25, 0x0d, 0x12, 0xbb, 0x08, 0x2a, 0xca, 0x6e, 0xe2, 0x40, 0xaa, - 0x94, 0xa1, 0x94, 0xa2, 0x69, 0x0b, 0x64, 0xb8, 0x1c, 0xd3, 0x1b, 0xed, 0x3f, 0xec, 0x0e, 0x59, - 0x13, 0xbd, 0xf4, 0x03, 0x14, 0x48, 0xcf, 0xfd, 0x14, 0x3d, 0x16, 0xed, 0xad, 0x27, 0x5f, 0x0a, - 0x04, 0xbd, 0x34, 0x27, 0xa1, 0xa6, 0xaf, 0x6d, 0x6f, 0xbd, 0x18, 0x28, 0x50, 0xcc, 0xec, 0xec, - 0xff, 0x5d, 0x89, 0x2a, 0x20, 0x1d, 0x72, 0xe3, 0xce, 0x7b, 0xef, 0xf7, 0xde, 0xcc, 0xbc, 0xf7, - 0xe6, 0xfd, 0x08, 0x3f, 0x3a, 0x7d, 0xdf, 0xd7, 0x0c, 0xa7, 0x7d, 0x3a, 0xec, 0x51, 0xcf, 0xa6, - 0x8c, 0xfa, 0xed, 0x11, 0xb5, 0xfb, 0x8e, 0xd7, 0x96, 0x02, 0xe2, 0x1a, 0x6d, 0xe2, 0xba, 0x7e, - 0x7b, 0x74, 0xa7, 0x47, 0x19, 0xb9, 0xd3, 0x1e, 0x50, 0x9b, 0x7a, 0x84, 0xd1, 0xbe, 0xe6, 0x7a, - 0x0e, 0x73, 0xd0, 0x5a, 0xa0, 0xa8, 0x11, 0xd7, 0xd0, 0xb8, 0xa2, 0x26, 0x15, 0xd7, 0xb7, 0x07, - 0x06, 0x7b, 0x3c, 0xec, 0x69, 0xba, 0x63, 0xb5, 0x07, 0xce, 0xc0, 0x69, 0x0b, 0xfd, 0xde, 0xf0, - 0x91, 0xf8, 0x12, 0x1f, 0xe2, 0x57, 0x80, 0xb3, 0xae, 0x26, 0x1c, 0xea, 0x8e, 0x47, 0xdb, 0xa3, - 0x9c, 0xaf, 0xf5, 0xdb, 0x09, 0x1d, 0xd7, 0x31, 0x0d, 0x7d, 0x5c, 0x16, 0xd6, 0xfa, 0xbb, 0xb1, - 0xaa, 0x45, 0xf4, 0xc7, 0x86, 0x4d, 0xbd, 0x71, 0xdb, 0x3d, 0x1d, 0xf0, 0x05, 0xbf, 0x6d, 0x51, - 0x46, 0x8a, 0x1c, 0xb4, 0xcb, 0xac, 0xbc, 0xa1, 0xcd, 0x0c, 0x8b, 0xe6, 0x0c, 0xde, 0xbb, 0xc8, - 0xc0, 0xd7, 0x1f, 0x53, 0x8b, 0xe4, 0xec, 0xde, 0x29, 0xb3, 0x1b, 0x32, 0xc3, 0x6c, 0x1b, 0x36, - 0xf3, 0x99, 0x97, 0x35, 0x52, 0xff, 0xa3, 0x00, 0xda, 0x73, 0x6c, 0xe6, 0x39, 0xa6, 0x49, 0x3d, - 0x4c, 0x47, 0x86, 0x6f, 0x38, 0x36, 0xfa, 0x02, 0xea, 0x7c, 0x3f, 0x7d, 0xc2, 0x48, 0x53, 0xd9, - 0x54, 0xb6, 0x16, 0x77, 0xde, 0xd6, 0xe2, 0x4b, 0x89, 0xe0, 0x35, 0xf7, 0x74, 0xc0, 0x17, 0x7c, - 0x8d, 0x6b, 0x6b, 0xa3, 0x3b, 0xda, 0x61, 0xef, 0x4b, 0xaa, 0xb3, 0x03, 0xca, 0x48, 0x07, 0x3d, - 0x3d, 0xdb, 0x98, 0x99, 0x9c, 0x6d, 0x40, 0xbc, 0x86, 0x23, 0x54, 0x74, 0x08, 0x55, 0x81, 0x5e, - 0x11, 0xe8, 0xdb, 0xa5, 0xe8, 0x72, 0xd3, 0x1a, 0x26, 0xbf, 0x7a, 0xf0, 0x84, 0x51, 0x9b, 0x87, - 0xd7, 0x79, 0x49, 0x42, 0x57, 0xef, 0x13, 0x46, 0xb0, 0x00, 0x42, 0x6f, 0x41, 0xdd, 0x93, 0xe1, - 0x37, 0x67, 0x37, 0x95, 0xad, 0xd9, 0xce, 0x0d, 0xa9, 0x55, 0x0f, 0xb7, 0x85, 0x23, 0x0d, 0xf5, - 0xa9, 0x02, 0xb7, 0xf2, 0xfb, 0xde, 0x37, 0x7c, 0x86, 0x7e, 0x91, 0xdb, 0xbb, 0x36, 0xdd, 0xde, - 0xb9, 0xb5, 0xd8, 0x79, 0xe4, 0x38, 0x5c, 0x49, 0xec, 0xfb, 0x08, 0x6a, 0x06, 0xa3, 0x96, 0xdf, - 0xac, 0x6c, 0xce, 0x6e, 0x2d, 0xee, 0xbc, 0xa9, 0x95, 0xe4, 0xba, 0x96, 0x8f, 0xae, 0xb3, 0x24, - 0x71, 0x6b, 0x0f, 0x39, 0x02, 0x0e, 0x80, 0xd4, 0xdf, 0x56, 0x00, 0xee, 0x53, 0xd7, 0x74, 0xc6, - 0x16, 0xb5, 0xd9, 0x35, 0x5c, 0xdd, 0x43, 0xa8, 0xfa, 0x2e, 0xd5, 0xe5, 0xd5, 0xbd, 0x5e, 0xba, - 0x83, 0x38, 0xa8, 0xae, 0x4b, 0xf5, 0xf8, 0xd2, 0xf8, 0x17, 0x16, 0x10, 0xe8, 0x53, 0x98, 0xf3, - 0x19, 0x61, 0x43, 0x5f, 0x5c, 0xd9, 0xe2, 0xce, 0xed, 0x69, 0xc0, 0x84, 0x41, 0xa7, 0x21, 0xe1, - 0xe6, 0x82, 0x6f, 0x2c, 0x81, 0xd4, 0xbf, 0xcf, 0xc2, 0x4a, 0xac, 0xbc, 0xe7, 0xd8, 0x7d, 0x83, - 0xf1, 0x94, 0xbe, 0x07, 0x55, 0x36, 0x76, 0xa9, 0x38, 0x93, 0x85, 0xce, 0xeb, 0x61, 0x30, 0xc7, - 0x63, 0x97, 0xbe, 0x38, 0xdb, 0x58, 0x2b, 0x30, 0xe1, 0x22, 0x2c, 0x8c, 0xd0, 0x7e, 0x14, 0x67, - 0x45, 0x98, 0xbf, 0x9b, 0x76, 0xfe, 0xe2, 0x6c, 0xa3, 0xa0, 0xd7, 0x68, 0x11, 0x52, 0x3a, 0x44, - 0xf4, 0x1a, 0xcc, 0x79, 0x94, 0xf8, 0x8e, 0xdd, 0xac, 0x0a, 0xb4, 0x68, 0x2b, 0x58, 0xac, 0x62, - 0x29, 0x45, 0xb7, 0x61, 0xde, 0xa2, 0xbe, 0x4f, 0x06, 0xb4, 0x59, 0x13, 0x8a, 0xcb, 0x52, 0x71, - 0xfe, 0x20, 0x58, 0xc6, 0xa1, 0x1c, 0x7d, 0x09, 0x0d, 0x93, 0xf8, 0xec, 0xc4, 0xed, 0x13, 0x46, - 0x8f, 0x0d, 0x8b, 0x36, 0xe7, 0xc4, 0x81, 0xbe, 0x31, 0xdd, 0xdd, 0x73, 0x8b, 0xce, 0x2d, 0x89, - 0xde, 0xd8, 0x4f, 0x21, 0xe1, 0x0c, 0x32, 0x1a, 0x01, 0xe2, 0x2b, 0xc7, 0x1e, 0xb1, 0xfd, 0xe0, - 0xa0, 0xb8, 0xbf, 0xf9, 0x4b, 0xfb, 0x5b, 0x97, 0xfe, 0xd0, 0x7e, 0x0e, 0x0d, 0x17, 0x78, 0x50, - 0xff, 0xa8, 0x40, 0x23, 0xbe, 0xa6, 0x6b, 0xa8, 0xd5, 0x8f, 0xd3, 0xb5, 0xfa, 0xfd, 0x29, 0x92, - 0xb3, 0xa4, 0x46, 0xff, 0x59, 0x01, 0x14, 0x2b, 0x61, 0xc7, 0x34, 0x7b, 0x44, 0x3f, 0x45, 0x9b, - 0x50, 0xb5, 0x89, 0x15, 0xe6, 0x64, 0x54, 0x20, 0x3f, 0x21, 0x16, 0xc5, 0x42, 0x82, 0xbe, 0x52, - 0x00, 0x0d, 0xc5, 0xd1, 0xf7, 0x77, 0x6d, 0xdb, 0x61, 0x84, 0x9f, 0x46, 0x18, 0xd0, 0xde, 0x14, - 0x01, 0x85, 0xbe, 0xb4, 0x93, 0x1c, 0xca, 0x03, 0x9b, 0x79, 0xe3, 0xf8, 0x16, 0xf2, 0x0a, 0xb8, - 0xc0, 0x35, 0xfa, 0x39, 0x80, 0x27, 0x31, 0x8f, 0x1d, 0x59, 0xb6, 0xe5, 0x3d, 0x20, 0x74, 0xbf, - 0xe7, 0xd8, 0x8f, 0x8c, 0x41, 0xdc, 0x58, 0x70, 0x04, 0x81, 0x13, 0x70, 0xeb, 0x0f, 0x60, 0xad, - 0x24, 0x4e, 0x74, 0x03, 0x66, 0x4f, 0xe9, 0x38, 0x38, 0x2a, 0xcc, 0x7f, 0xa2, 0x55, 0xa8, 0x8d, - 0x88, 0x39, 0xa4, 0x41, 0x4d, 0xe2, 0xe0, 0xe3, 0x6e, 0xe5, 0x7d, 0x45, 0xfd, 0x43, 0x2d, 0x99, - 0x29, 0xbc, 0xdf, 0xa0, 0x2d, 0xfe, 0x3c, 0xb8, 0xa6, 0xa1, 0x13, 0x5f, 0x60, 0xd4, 0x3a, 0x2f, - 0x05, 0x4f, 0x43, 0xb0, 0x86, 0x23, 0x29, 0xfa, 0x25, 0xd4, 0x7d, 0x6a, 0x52, 0x9d, 0x39, 0x9e, - 0x6c, 0x71, 0xef, 0x4c, 0x99, 0x53, 0xa4, 0x47, 0xcd, 0xae, 0x34, 0x0d, 0xe0, 0xc3, 0x2f, 0x1c, - 0x41, 0xa2, 0x4f, 0xa1, 0xce, 0xa8, 0xe5, 0x9a, 0x84, 0x51, 0x79, 0x7a, 0xa9, 0xbc, 0xe2, 0xbd, - 0x83, 0x83, 0x1d, 0x39, 0xfd, 0x63, 0xa9, 0x26, 0xba, 0x67, 0x94, 0xa7, 0xe1, 0x2a, 0x8e, 0x60, - 0xd0, 0xcf, 0xa0, 0xee, 0x33, 0xfe, 0xaa, 0x0f, 0xc6, 0xa2, 0xa3, 0x9c, 0xf7, 0xac, 0x24, 0xfb, - 0x68, 0x60, 0x12, 0x43, 0x87, 0x2b, 0x38, 0x82, 0x43, 0xbb, 0xb0, 0x6c, 0x19, 0x36, 0xa6, 0xa4, - 0x3f, 0xee, 0x52, 0xdd, 0xb1, 0xfb, 0xbe, 0x68, 0x45, 0xb5, 0xce, 0x9a, 0x34, 0x5a, 0x3e, 0x48, - 0x8b, 0x71, 0x56, 0x1f, 0xed, 0xc3, 0x6a, 0xf8, 0xec, 0x7e, 0x6c, 0xf8, 0xcc, 0xf1, 0xc6, 0xfb, - 0x86, 0x65, 0x30, 0xd1, 0xa0, 0x6a, 0x9d, 0xe6, 0xe4, 0x6c, 0x63, 0x15, 0x17, 0xc8, 0x71, 0xa1, - 0x15, 0xef, 0x9d, 0x2e, 0x19, 0xfa, 0xb4, 0x2f, 0x1a, 0x4e, 0x3d, 0xee, 0x9d, 0x47, 0x62, 0x15, - 0x4b, 0x29, 0xfa, 0x69, 0x2a, 0x4d, 0xeb, 0x97, 0x4b, 0xd3, 0x46, 0x79, 0x8a, 0xa2, 0x13, 0x58, - 0x73, 0x3d, 0x67, 0xe0, 0x51, 0xdf, 0xbf, 0x4f, 0x49, 0xdf, 0x34, 0x6c, 0x1a, 0x9e, 0xcc, 0x82, - 0xd8, 0xd1, 0x2b, 0x93, 0xb3, 0x8d, 0xb5, 0xa3, 0x62, 0x15, 0x5c, 0x66, 0xab, 0xfe, 0xa5, 0x0a, - 0x37, 0xb2, 0x6f, 0x1c, 0xfa, 0x04, 0x90, 0xd3, 0xf3, 0xa9, 0x37, 0xa2, 0xfd, 0x8f, 0x82, 0xc1, - 0x8d, 0x4f, 0x37, 0x8a, 0x98, 0x6e, 0xa2, 0xba, 0x3d, 0xcc, 0x69, 0xe0, 0x02, 0xab, 0x60, 0x3e, - 0x92, 0x05, 0x50, 0x11, 0x81, 0x26, 0xe6, 0xa3, 0x5c, 0x11, 0xec, 0xc2, 0xb2, 0xac, 0xfd, 0x50, - 0x28, 0x92, 0x35, 0x71, 0xef, 0x27, 0x69, 0x31, 0xce, 0xea, 0xa3, 0x8f, 0xe0, 0x26, 0x19, 0x11, - 0xc3, 0x24, 0x3d, 0x93, 0x46, 0x20, 0x55, 0x01, 0xf2, 0xb2, 0x04, 0xb9, 0xb9, 0x9b, 0x55, 0xc0, - 0x79, 0x1b, 0x74, 0x00, 0x2b, 0x43, 0x3b, 0x0f, 0x15, 0xe4, 0xe1, 0x2b, 0x12, 0x6a, 0xe5, 0x24, - 0xaf, 0x82, 0x8b, 0xec, 0xd0, 0x17, 0x00, 0x7a, 0xf8, 0x30, 0xfb, 0xcd, 0x39, 0xd1, 0x49, 0xdf, - 0x9a, 0xa2, 0x5e, 0xa2, 0xd7, 0x3c, 0xee, 0x62, 0xd1, 0x92, 0x8f, 0x13, 0x98, 0xe8, 0x1e, 0x2c, - 0x79, 0xbc, 0x02, 0xa2, 0x50, 0xe7, 0x45, 0xa8, 0xdf, 0x91, 0x66, 0x4b, 0x38, 0x29, 0xc4, 0x69, - 0x5d, 0x74, 0x17, 0x1a, 0xba, 0x63, 0x9a, 0x22, 0xf3, 0xf7, 0x9c, 0xa1, 0xcd, 0x44, 0xf2, 0xd6, - 0x3a, 0x88, 0xbf, 0xcc, 0x7b, 0x29, 0x09, 0xce, 0x68, 0xaa, 0x7f, 0x56, 0x92, 0xcf, 0x4c, 0x58, - 0xce, 0xe8, 0x6e, 0x6a, 0xf4, 0x79, 0x2d, 0x33, 0xfa, 0xdc, 0xca, 0x5b, 0x24, 0x26, 0x1f, 0x03, - 0x96, 0x78, 0xf2, 0x1b, 0xf6, 0x20, 0xb8, 0x70, 0xd9, 0x12, 0xdf, 0x3e, 0xb7, 0x94, 0x22, 0xed, - 0xc4, 0xc3, 0x78, 0x53, 0xec, 0x3c, 0x29, 0xc4, 0x69, 0x64, 0xf5, 0x43, 0x68, 0xa4, 0xeb, 0x30, - 0x35, 0xd3, 0x2b, 0x17, 0xce, 0xf4, 0xcf, 0x15, 0x58, 0x2b, 0xf1, 0x8e, 0x4c, 0x68, 0x58, 0xe4, - 0x49, 0x22, 0x47, 0x2e, 0x9c, 0x8d, 0x39, 0x6b, 0xd2, 0x02, 0xd6, 0xa4, 0x3d, 0xb4, 0xd9, 0xa1, - 0xd7, 0x65, 0x9e, 0x61, 0x0f, 0x82, 0x7b, 0x38, 0x48, 0x61, 0xe1, 0x0c, 0x36, 0xfa, 0x1c, 0xea, - 0x16, 0x79, 0xd2, 0x1d, 0x7a, 0x83, 0xa2, 0xf3, 0x9a, 0xce, 0x8f, 0x78, 0x3f, 0x0e, 0x24, 0x0a, - 0x8e, 0xf0, 0xd4, 0x43, 0xd8, 0x4c, 0x6d, 0x92, 0xb7, 0x0a, 0xfa, 0x68, 0x68, 0x76, 0x69, 0x7c, - 0xe1, 0x6f, 0xc2, 0x82, 0x4b, 0x3c, 0x66, 0x44, 0xed, 0xa2, 0xd6, 0x59, 0x9a, 0x9c, 0x6d, 0x2c, - 0x1c, 0x85, 0x8b, 0x38, 0x96, 0xab, 0xff, 0x55, 0xa0, 0xd6, 0xd5, 0x89, 0x49, 0xaf, 0x81, 0x3a, - 0xdc, 0x4f, 0x51, 0x07, 0xb5, 0x34, 0x89, 0x44, 0x3c, 0xa5, 0xac, 0x61, 0x3f, 0xc3, 0x1a, 0x5e, - 0xbd, 0x00, 0xe7, 0x7c, 0xc2, 0xf0, 0x01, 0x2c, 0x44, 0xee, 0x52, 0x5d, 0x52, 0xb9, 0xa8, 0x4b, - 0xaa, 0xbf, 0xaf, 0xc0, 0x62, 0xc2, 0xc5, 0xe5, 0xac, 0xf9, 0x71, 0x27, 0x06, 0x0d, 0xde, 0x86, - 0x76, 0xa6, 0xd9, 0x88, 0x16, 0x0e, 0x15, 0xc1, 0xfc, 0x16, 0xbf, 0xde, 0xf9, 0x59, 0xe3, 0x43, - 0x68, 0x30, 0xe2, 0x0d, 0x28, 0x0b, 0x65, 0xe2, 0xc0, 0x16, 0xe2, 0x49, 0xff, 0x38, 0x25, 0xc5, - 0x19, 0xed, 0xf5, 0x7b, 0xb0, 0x94, 0x72, 0x76, 0xa9, 0x21, 0xec, 0x2b, 0x7e, 0x38, 0x71, 0x72, - 0x5e, 0x43, 0x76, 0x7d, 0x92, 0xca, 0xae, 0xad, 0xf2, 0xc3, 0x4c, 0x94, 0x4c, 0x59, 0x8e, 0xe1, - 0x4c, 0x8e, 0xbd, 0x31, 0x15, 0xda, 0xf9, 0x99, 0xf6, 0xaf, 0x0a, 0xac, 0x26, 0xb4, 0x63, 0x6e, - 0xfa, 0xc3, 0x54, 0x83, 0xde, 0xca, 0x34, 0xe8, 0x66, 0x91, 0xcd, 0x95, 0x91, 0xd3, 0x62, 0x76, - 0x37, 0x7b, 0xd5, 0xec, 0xee, 0x0a, 0x48, 0xb1, 0xfa, 0x27, 0x05, 0x96, 0x13, 0x67, 0x77, 0x0d, - 0x8c, 0xf1, 0x61, 0x9a, 0x31, 0xbe, 0x3a, 0x4d, 0xd2, 0x94, 0x50, 0xc6, 0xbf, 0xd6, 0x52, 0xc1, - 0x7f, 0xeb, 0x49, 0xcc, 0xaf, 0x61, 0x75, 0xe4, 0x98, 0x43, 0x8b, 0xee, 0x99, 0xc4, 0xb0, 0x42, - 0x05, 0x3e, 0x31, 0xce, 0x66, 0xff, 0x18, 0x8a, 0xe0, 0xa9, 0xe7, 0x1b, 0x3e, 0xa3, 0x36, 0xfb, - 0x2c, 0xb6, 0xec, 0x7c, 0x57, 0x3a, 0x59, 0xfd, 0xac, 0x00, 0x0e, 0x17, 0x3a, 0x41, 0x3f, 0x80, - 0x45, 0x3e, 0x30, 0x1b, 0x3a, 0xe5, 0xdc, 0x5b, 0x26, 0xd6, 0x8a, 0x04, 0x5a, 0xec, 0xc6, 0x22, - 0x9c, 0xd4, 0x43, 0x8f, 0x61, 0xc5, 0x75, 0xfa, 0x07, 0xc4, 0x26, 0x03, 0xca, 0xc7, 0x8c, 0x23, - 0xf1, 0x07, 0xb2, 0x60, 0x36, 0x0b, 0x9d, 0xf7, 0xc2, 0xc9, 0xf4, 0x28, 0xaf, 0xf2, 0x82, 0x53, - 0x84, 0xfc, 0xb2, 0x28, 0xea, 0x22, 0x48, 0xe4, 0x41, 0x63, 0x28, 0x9f, 0x7b, 0x49, 0xf4, 0x82, - 0xff, 0x5b, 0x76, 0xa6, 0xc9, 0xb0, 0x93, 0x94, 0x65, 0xdc, 0xfd, 0xd3, 0xeb, 0x38, 0xe3, 0xa1, - 0x94, 0xb8, 0xd5, 0xff, 0x1f, 0xe2, 0xa6, 0xfe, 0xbb, 0x0a, 0x37, 0x73, 0xad, 0x12, 0xfd, 0xf8, - 0x1c, 0x86, 0x73, 0xeb, 0xca, 0xd8, 0x4d, 0x6e, 0x40, 0x9f, 0xbd, 0xc4, 0x80, 0xbe, 0x0b, 0xcb, - 0xfa, 0xd0, 0xf3, 0xa8, 0xcd, 0x32, 0xac, 0x26, 0xa2, 0x46, 0x7b, 0x69, 0x31, 0xce, 0xea, 0x17, - 0xb1, 0xab, 0xda, 0x25, 0xd9, 0x55, 0x32, 0x0a, 0x39, 0x21, 0x07, 0x69, 0x97, 0x8f, 0x42, 0x0e, - 0xca, 0x59, 0x7d, 0x3e, 0x1d, 0x04, 0xa8, 0x11, 0xc2, 0x7c, 0x7a, 0x3a, 0x38, 0x49, 0x49, 0x71, - 0x46, 0xbb, 0x80, 0xa9, 0x2c, 0x4c, 0xcb, 0x54, 0x10, 0x49, 0x91, 0x30, 0x10, 0x35, 0xbe, 0x3d, - 0x4d, 0x2e, 0x4f, 0xcd, 0xc2, 0xd4, 0xbf, 0x29, 0xf0, 0x72, 0x69, 0x11, 0xa0, 0xdd, 0xd4, 0x93, - 0xbb, 0x9d, 0x79, 0x72, 0xbf, 0x57, 0x6a, 0x98, 0x78, 0x77, 0xbd, 0x62, 0x6a, 0xf4, 0xc1, 0x74, - 0xd4, 0xa8, 0x60, 0x6e, 0xbf, 0x98, 0x23, 0x75, 0xb6, 0x9f, 0x3e, 0x6b, 0xcd, 0x7c, 0xfd, 0xac, - 0x35, 0xf3, 0xcd, 0xb3, 0xd6, 0xcc, 0x6f, 0x26, 0x2d, 0xe5, 0xe9, 0xa4, 0xa5, 0x7c, 0x3d, 0x69, - 0x29, 0xdf, 0x4c, 0x5a, 0xca, 0x3f, 0x26, 0x2d, 0xe5, 0x77, 0xcf, 0x5b, 0x33, 0x9f, 0xcf, 0x4b, - 0x8f, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x5d, 0x9e, 0x04, 0x8c, 0x1b, 0x00, 0x00, + // 1859 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0xcd, 0x6f, 0x24, 0x47, + 0x15, 0x77, 0x8f, 0x67, 0xec, 0xf1, 0x73, 0x3c, 0xde, 0x2d, 0x9b, 0xf5, 0xc4, 0x81, 0xb1, 0xd5, + 0x44, 0x89, 0xf3, 0xe1, 0x9e, 0xac, 0x13, 0xa2, 0x64, 0x17, 0x45, 0x78, 0xbc, 0x4b, 0xb2, 0x91, + 0x8d, 0x9d, 0xb2, 0x1d, 0x44, 0x00, 0x29, 0x35, 0x3d, 0xb5, 0xb3, 0x1d, 0xf7, 0x97, 0xba, 0x6b, + 0x86, 0x1d, 0x71, 0xe1, 0x0f, 0x40, 0x0a, 0x67, 0xfe, 0x0a, 0x8e, 0x08, 0x6e, 0x9c, 0xf6, 0x82, + 0x14, 0x71, 0x21, 0x27, 0x8b, 0x9d, 0x5c, 0x81, 0x1b, 0x97, 0x95, 0x90, 0x50, 0x55, 0x57, 0x7f, + 0x77, 0xdb, 0x6d, 0xa4, 0xf5, 0x21, 0xb7, 0xe9, 0x7a, 0xef, 0xfd, 0x5e, 0x7d, 0xbc, 0xaf, 0xdf, + 0xc0, 0x8f, 0xce, 0xde, 0xf3, 0x35, 0xc3, 0xe9, 0x9e, 0x8d, 0xfa, 0xd4, 0xb3, 0x29, 0xa3, 0x7e, + 0x77, 0x4c, 0xed, 0x81, 0xe3, 0x75, 0xa5, 0x80, 0xb8, 0x46, 0x97, 0xb8, 0xae, 0xdf, 0x1d, 0xdf, + 0xee, 0x53, 0x46, 0x6e, 0x77, 0x87, 0xd4, 0xa6, 0x1e, 0x61, 0x74, 0xa0, 0xb9, 0x9e, 0xc3, 0x1c, + 0xb4, 0x16, 0x28, 0x6a, 0xc4, 0x35, 0x34, 0xae, 0xa8, 0x49, 0xc5, 0xf5, 0xed, 0xa1, 0xc1, 0x1e, + 0x8d, 0xfa, 0x9a, 0xee, 0x58, 0xdd, 0xa1, 0x33, 0x74, 0xba, 0x42, 0xbf, 0x3f, 0x7a, 0x28, 0xbe, + 0xc4, 0x87, 0xf8, 0x15, 0xe0, 0xac, 0xab, 0x09, 0x87, 0xba, 0xe3, 0xd1, 0xee, 0x38, 0xe7, 0x6b, + 0xfd, 0x9d, 0x58, 0xc7, 0x22, 0xfa, 0x23, 0xc3, 0xa6, 0xde, 0xa4, 0xeb, 0x9e, 0x0d, 0xf9, 0x82, + 0xdf, 0xb5, 0x28, 0x23, 0x45, 0x56, 0xdd, 0x32, 0x2b, 0x6f, 0x64, 0x33, 0xc3, 0xa2, 0x39, 0x83, + 0x77, 0x2f, 0x33, 0xf0, 0xf5, 0x47, 0xd4, 0x22, 0x39, 0xbb, 0xb7, 0xcb, 0xec, 0x46, 0xcc, 0x30, + 0xbb, 0x86, 0xcd, 0x7c, 0xe6, 0x65, 0x8d, 0xd4, 0xff, 0x28, 0x80, 0xf6, 0x1c, 0x9b, 0x79, 0x8e, + 0x69, 0x52, 0x0f, 0xd3, 0xb1, 0xe1, 0x1b, 0x8e, 0x8d, 0x3e, 0x87, 0x26, 0x3f, 0xcf, 0x80, 0x30, + 0xd2, 0x56, 0x36, 0x95, 0xad, 0xc5, 0x9d, 0xb7, 0xb4, 0xf8, 0xa6, 0x23, 0x78, 0xcd, 0x3d, 0x1b, + 0xf2, 0x05, 0x5f, 0xe3, 0xda, 0xda, 0xf8, 0xb6, 0x76, 0xd8, 0xff, 0x82, 0xea, 0xec, 0x80, 0x32, + 0xd2, 0x43, 0x4f, 0xce, 0x37, 0x66, 0xa6, 0xe7, 0x1b, 0x10, 0xaf, 0xe1, 0x08, 0x15, 0x1d, 0x42, + 0x5d, 0xa0, 0xd7, 0x04, 0xfa, 0x76, 0x29, 0xba, 0x3c, 0xb4, 0x86, 0xc9, 0xaf, 0xee, 0x3f, 0x66, + 0xd4, 0xe6, 0xdb, 0xeb, 0xbd, 0x20, 0xa1, 0xeb, 0xf7, 0x08, 0x23, 0x58, 0x00, 0xa1, 0x37, 0xa1, + 0xe9, 0xc9, 0xed, 0xb7, 0x67, 0x37, 0x95, 0xad, 0xd9, 0xde, 0x0d, 0xa9, 0xd5, 0x0c, 0x8f, 0x85, + 0x23, 0x0d, 0xf5, 0x89, 0x02, 0xb7, 0xf2, 0xe7, 0xde, 0x37, 0x7c, 0x86, 0x7e, 0x91, 0x3b, 0xbb, + 0x56, 0xed, 0xec, 0xdc, 0x5a, 0x9c, 0x3c, 0x72, 0x1c, 0xae, 0x24, 0xce, 0x7d, 0x04, 0x0d, 0x83, + 0x51, 0xcb, 0x6f, 0xd7, 0x36, 0x67, 0xb7, 0x16, 0x77, 0xde, 0xd0, 0x4a, 0x02, 0x58, 0xcb, 0xef, + 0xae, 0xb7, 0x24, 0x71, 0x1b, 0x0f, 0x38, 0x02, 0x0e, 0x80, 0xd4, 0xdf, 0xd6, 0x00, 0xee, 0x51, + 0xd7, 0x74, 0x26, 0x16, 0xb5, 0xd9, 0x35, 0x3c, 0xdd, 0x03, 0xa8, 0xfb, 0x2e, 0xd5, 0xe5, 0xd3, + 0xbd, 0x5a, 0x7a, 0x82, 0x78, 0x53, 0xc7, 0x2e, 0xd5, 0xe3, 0x47, 0xe3, 0x5f, 0x58, 0x40, 0xa0, + 0x4f, 0x60, 0xce, 0x67, 0x84, 0x8d, 0x7c, 0xf1, 0x64, 0x8b, 0x3b, 0xaf, 0x55, 0x01, 0x13, 0x06, + 0xbd, 0x96, 0x84, 0x9b, 0x0b, 0xbe, 0xb1, 0x04, 0x52, 0xff, 0x3e, 0x0b, 0x2b, 0xb1, 0xf2, 0x9e, + 0x63, 0x0f, 0x0c, 0xc6, 0x43, 0xfa, 0x2e, 0xd4, 0xd9, 0xc4, 0xa5, 0xe2, 0x4e, 0x16, 0x7a, 0xaf, + 0x86, 0x9b, 0x39, 0x99, 0xb8, 0xf4, 0xd9, 0xf9, 0xc6, 0x5a, 0x81, 0x09, 0x17, 0x61, 0x61, 0x84, + 0xf6, 0xa3, 0x7d, 0xd6, 0x84, 0xf9, 0x3b, 0x69, 0xe7, 0xcf, 0xce, 0x37, 0x0a, 0x0a, 0x88, 0x16, + 0x21, 0xa5, 0xb7, 0x88, 0x5e, 0x81, 0x39, 0x8f, 0x12, 0xdf, 0xb1, 0xdb, 0x75, 0x81, 0x16, 0x1d, + 0x05, 0x8b, 0x55, 0x2c, 0xa5, 0xe8, 0x35, 0x98, 0xb7, 0xa8, 0xef, 0x93, 0x21, 0x6d, 0x37, 0x84, + 0xe2, 0xb2, 0x54, 0x9c, 0x3f, 0x08, 0x96, 0x71, 0x28, 0x47, 0x5f, 0x40, 0xcb, 0x24, 0x3e, 0x3b, + 0x75, 0x07, 0x84, 0xd1, 0x13, 0xc3, 0xa2, 0xed, 0x39, 0x71, 0xa1, 0xaf, 0x57, 0x7b, 0x7b, 0x6e, + 0xd1, 0xbb, 0x25, 0xd1, 0x5b, 0xfb, 0x29, 0x24, 0x9c, 0x41, 0x46, 0x63, 0x40, 0x7c, 0xe5, 0xc4, + 0x23, 0xb6, 0x1f, 0x5c, 0x14, 0xf7, 0x37, 0x7f, 0x65, 0x7f, 0xeb, 0xd2, 0x1f, 0xda, 0xcf, 0xa1, + 0xe1, 0x02, 0x0f, 0xea, 0x1f, 0x15, 0x68, 0xc5, 0xcf, 0x74, 0x0d, 0xb9, 0xfa, 0x51, 0x3a, 0x57, + 0xbf, 0x5f, 0x21, 0x38, 0x4b, 0x72, 0xf4, 0x9f, 0x35, 0x40, 0xb1, 0x12, 0x76, 0x4c, 0xb3, 0x4f, + 0xf4, 0x33, 0xb4, 0x09, 0x75, 0x9b, 0x58, 0x61, 0x4c, 0x46, 0x09, 0xf2, 0x13, 0x62, 0x51, 0x2c, + 0x24, 0xe8, 0x4b, 0x05, 0xd0, 0x48, 0x5c, 0xfd, 0x60, 0xd7, 0xb6, 0x1d, 0x46, 0xf8, 0x6d, 0x84, + 0x1b, 0xda, 0xab, 0xb0, 0xa1, 0xd0, 0x97, 0x76, 0x9a, 0x43, 0xb9, 0x6f, 0x33, 0x6f, 0x12, 0xbf, + 0x42, 0x5e, 0x01, 0x17, 0xb8, 0x46, 0x3f, 0x07, 0xf0, 0x24, 0xe6, 0x89, 0x23, 0xd3, 0xb6, 0xbc, + 0x06, 0x84, 0xee, 0xf7, 0x1c, 0xfb, 0xa1, 0x31, 0x8c, 0x0b, 0x0b, 0x8e, 0x20, 0x70, 0x02, 0x6e, + 0xfd, 0x3e, 0xac, 0x95, 0xec, 0x13, 0xdd, 0x80, 0xd9, 0x33, 0x3a, 0x09, 0xae, 0x0a, 0xf3, 0x9f, + 0x68, 0x15, 0x1a, 0x63, 0x62, 0x8e, 0x68, 0x90, 0x93, 0x38, 0xf8, 0xb8, 0x53, 0x7b, 0x4f, 0x51, + 0xff, 0xd0, 0x48, 0x46, 0x0a, 0xaf, 0x37, 0x68, 0x8b, 0xb7, 0x07, 0xd7, 0x34, 0x74, 0xe2, 0x0b, + 0x8c, 0x46, 0xef, 0x85, 0xa0, 0x35, 0x04, 0x6b, 0x38, 0x92, 0xa2, 0x5f, 0x42, 0xd3, 0xa7, 0x26, + 0xd5, 0x99, 0xe3, 0xc9, 0x12, 0xf7, 0x76, 0xc5, 0x98, 0x22, 0x7d, 0x6a, 0x1e, 0x4b, 0xd3, 0x00, + 0x3e, 0xfc, 0xc2, 0x11, 0x24, 0xfa, 0x04, 0x9a, 0x8c, 0x5a, 0xae, 0x49, 0x18, 0x95, 0xb7, 0x97, + 0x8a, 0x2b, 0x5e, 0x3b, 0x38, 0xd8, 0x91, 0x33, 0x38, 0x91, 0x6a, 0xa2, 0x7a, 0x46, 0x71, 0x1a, + 0xae, 0xe2, 0x08, 0x06, 0xfd, 0x0c, 0x9a, 0x3e, 0xe3, 0x5d, 0x7d, 0x38, 0x11, 0x15, 0xe5, 0xa2, + 0xb6, 0x92, 0xac, 0xa3, 0x81, 0x49, 0x0c, 0x1d, 0xae, 0xe0, 0x08, 0x0e, 0xed, 0xc2, 0xb2, 0x65, + 0xd8, 0x98, 0x92, 0xc1, 0xe4, 0x98, 0xea, 0x8e, 0x3d, 0xf0, 0x45, 0x29, 0x6a, 0xf4, 0xd6, 0xa4, + 0xd1, 0xf2, 0x41, 0x5a, 0x8c, 0xb3, 0xfa, 0x68, 0x1f, 0x56, 0xc3, 0xb6, 0xfb, 0x91, 0xe1, 0x33, + 0xc7, 0x9b, 0xec, 0x1b, 0x96, 0xc1, 0x44, 0x81, 0x6a, 0xf4, 0xda, 0xd3, 0xf3, 0x8d, 0x55, 0x5c, + 0x20, 0xc7, 0x85, 0x56, 0xbc, 0x76, 0xba, 0x64, 0xe4, 0xd3, 0x81, 0x28, 0x38, 0xcd, 0xb8, 0x76, + 0x1e, 0x89, 0x55, 0x2c, 0xa5, 0xe8, 0xa7, 0xa9, 0x30, 0x6d, 0x5e, 0x2d, 0x4c, 0x5b, 0xe5, 0x21, + 0x8a, 0x4e, 0x61, 0xcd, 0xf5, 0x9c, 0xa1, 0x47, 0x7d, 0xff, 0x1e, 0x25, 0x03, 0xd3, 0xb0, 0x69, + 0x78, 0x33, 0x0b, 0xe2, 0x44, 0x2f, 0x4d, 0xcf, 0x37, 0xd6, 0x8e, 0x8a, 0x55, 0x70, 0x99, 0xad, + 0xfa, 0x97, 0x3a, 0xdc, 0xc8, 0xf6, 0x38, 0xf4, 0x31, 0x20, 0xa7, 0xef, 0x53, 0x6f, 0x4c, 0x07, + 0x1f, 0x06, 0x83, 0x1b, 0x9f, 0x6e, 0x14, 0x31, 0xdd, 0x44, 0x79, 0x7b, 0x98, 0xd3, 0xc0, 0x05, + 0x56, 0xc1, 0x7c, 0x24, 0x13, 0xa0, 0x26, 0x36, 0x9a, 0x98, 0x8f, 0x72, 0x49, 0xb0, 0x0b, 0xcb, + 0x32, 0xf7, 0x43, 0xa1, 0x08, 0xd6, 0xc4, 0xbb, 0x9f, 0xa6, 0xc5, 0x38, 0xab, 0x8f, 0x3e, 0x84, + 0x9b, 0x64, 0x4c, 0x0c, 0x93, 0xf4, 0x4d, 0x1a, 0x81, 0xd4, 0x05, 0xc8, 0x8b, 0x12, 0xe4, 0xe6, + 0x6e, 0x56, 0x01, 0xe7, 0x6d, 0xd0, 0x01, 0xac, 0x8c, 0xec, 0x3c, 0x54, 0x10, 0x87, 0x2f, 0x49, + 0xa8, 0x95, 0xd3, 0xbc, 0x0a, 0x2e, 0xb2, 0x43, 0x9f, 0x03, 0xe8, 0x61, 0x63, 0xf6, 0xdb, 0x73, + 0xa2, 0x92, 0xbe, 0x59, 0x21, 0x5f, 0xa2, 0x6e, 0x1e, 0x57, 0xb1, 0x68, 0xc9, 0xc7, 0x09, 0x4c, + 0x74, 0x17, 0x96, 0x3c, 0x9e, 0x01, 0xd1, 0x56, 0xe7, 0xc5, 0x56, 0xbf, 0x23, 0xcd, 0x96, 0x70, + 0x52, 0x88, 0xd3, 0xba, 0xe8, 0x0e, 0xb4, 0x74, 0xc7, 0x34, 0x45, 0xe4, 0xef, 0x39, 0x23, 0x9b, + 0x89, 0xe0, 0x6d, 0xf4, 0x10, 0xef, 0xcc, 0x7b, 0x29, 0x09, 0xce, 0x68, 0xaa, 0x7f, 0x56, 0x92, + 0x6d, 0x26, 0x4c, 0x67, 0x74, 0x27, 0x35, 0xfa, 0xbc, 0x92, 0x19, 0x7d, 0x6e, 0xe5, 0x2d, 0x12, + 0x93, 0x8f, 0x01, 0x4b, 0x3c, 0xf8, 0x0d, 0x7b, 0x18, 0x3c, 0xb8, 0x2c, 0x89, 0x6f, 0x5d, 0x98, + 0x4a, 0x91, 0x76, 0xa2, 0x31, 0xde, 0x14, 0x27, 0x4f, 0x0a, 0x71, 0x1a, 0x59, 0xfd, 0x00, 0x5a, + 0xe9, 0x3c, 0x4c, 0xcd, 0xf4, 0xca, 0xa5, 0x33, 0xfd, 0x37, 0x0a, 0xac, 0x95, 0x78, 0x47, 0x26, + 0xb4, 0x2c, 0xf2, 0x38, 0x11, 0x23, 0x97, 0xce, 0xc6, 0x9c, 0x35, 0x69, 0x01, 0x6b, 0xd2, 0x1e, + 0xd8, 0xec, 0xd0, 0x3b, 0x66, 0x9e, 0x61, 0x0f, 0x83, 0x77, 0x38, 0x48, 0x61, 0xe1, 0x0c, 0x36, + 0xfa, 0x0c, 0x9a, 0x16, 0x79, 0x7c, 0x3c, 0xf2, 0x86, 0x45, 0xf7, 0x55, 0xcd, 0x8f, 0xe8, 0x1f, + 0x07, 0x12, 0x05, 0x47, 0x78, 0xea, 0x21, 0x6c, 0xa6, 0x0e, 0xc9, 0x4b, 0x05, 0x7d, 0x38, 0x32, + 0x8f, 0x69, 0xfc, 0xe0, 0x6f, 0xc0, 0x82, 0x4b, 0x3c, 0x66, 0x44, 0xe5, 0xa2, 0xd1, 0x5b, 0x9a, + 0x9e, 0x6f, 0x2c, 0x1c, 0x85, 0x8b, 0x38, 0x96, 0xab, 0xff, 0x55, 0xa0, 0x71, 0xac, 0x13, 0x93, + 0x5e, 0x03, 0x75, 0xb8, 0x97, 0xa2, 0x0e, 0x6a, 0x69, 0x10, 0x89, 0xfd, 0x94, 0xb2, 0x86, 0xfd, + 0x0c, 0x6b, 0x78, 0xf9, 0x12, 0x9c, 0x8b, 0x09, 0xc3, 0xfb, 0xb0, 0x10, 0xb9, 0x4b, 0x55, 0x49, + 0xe5, 0xb2, 0x2a, 0xa9, 0xfe, 0xbe, 0x06, 0x8b, 0x09, 0x17, 0x57, 0xb3, 0xe6, 0xd7, 0x9d, 0x18, + 0x34, 0x78, 0x19, 0xda, 0xa9, 0x72, 0x10, 0x2d, 0x1c, 0x2a, 0x82, 0xf9, 0x2d, 0xee, 0xde, 0xf9, + 0x59, 0xe3, 0x03, 0x68, 0x31, 0xe2, 0x0d, 0x29, 0x0b, 0x65, 0xe2, 0xc2, 0x16, 0xe2, 0x49, 0xff, + 0x24, 0x25, 0xc5, 0x19, 0xed, 0xf5, 0xbb, 0xb0, 0x94, 0x72, 0x76, 0xa5, 0x21, 0xec, 0x4b, 0x7e, + 0x39, 0x71, 0x70, 0x5e, 0x43, 0x74, 0x7d, 0x9c, 0x8a, 0xae, 0xad, 0xf2, 0xcb, 0x4c, 0xa4, 0x4c, + 0x59, 0x8c, 0xe1, 0x4c, 0x8c, 0xbd, 0x5e, 0x09, 0xed, 0xe2, 0x48, 0xfb, 0x57, 0x0d, 0x56, 0x13, + 0xda, 0x31, 0x37, 0xfd, 0x61, 0xaa, 0x40, 0x6f, 0x65, 0x0a, 0x74, 0xbb, 0xc8, 0xe6, 0xb9, 0x91, + 0xd3, 0x62, 0x76, 0x37, 0xfb, 0xbc, 0xd9, 0xdd, 0x73, 0x20, 0xc5, 0xea, 0x9f, 0x14, 0x58, 0x4e, + 0xdc, 0xdd, 0x35, 0x30, 0xc6, 0x07, 0x69, 0xc6, 0xf8, 0x72, 0x95, 0xa0, 0x29, 0xa1, 0x8c, 0x7f, + 0x6d, 0xa4, 0x36, 0xff, 0xad, 0x27, 0x31, 0xbf, 0x86, 0xd5, 0xb1, 0x63, 0x8e, 0x2c, 0xba, 0x67, + 0x12, 0xc3, 0x0a, 0x15, 0xf8, 0xc4, 0x38, 0x9b, 0xfd, 0x63, 0x28, 0x82, 0xa7, 0x9e, 0x6f, 0xf8, + 0x8c, 0xda, 0xec, 0xd3, 0xd8, 0xb2, 0xf7, 0x5d, 0xe9, 0x64, 0xf5, 0xd3, 0x02, 0x38, 0x5c, 0xe8, + 0x04, 0xfd, 0x00, 0x16, 0xf9, 0xc0, 0x6c, 0xe8, 0x94, 0x73, 0x6f, 0x19, 0x58, 0x2b, 0x12, 0x68, + 0xf1, 0x38, 0x16, 0xe1, 0xa4, 0x1e, 0x7a, 0x04, 0x2b, 0xae, 0x33, 0x38, 0x20, 0x36, 0x19, 0x52, + 0x3e, 0x66, 0x1c, 0x39, 0xa6, 0xa1, 0x4f, 0x04, 0xb3, 0x59, 0xe8, 0xbd, 0x1b, 0x4e, 0xa6, 0x47, + 0x79, 0x95, 0x67, 0x9c, 0x22, 0xe4, 0x97, 0x45, 0x52, 0x17, 0x41, 0x22, 0x0f, 0x5a, 0x23, 0xd9, + 0xee, 0x25, 0xd1, 0x0b, 0xfe, 0x6f, 0xd9, 0xa9, 0x12, 0x61, 0xa7, 0x29, 0xcb, 0xb8, 0xfa, 0xa7, + 0xd7, 0x71, 0xc6, 0x43, 0x29, 0x71, 0x6b, 0xfe, 0x3f, 0xc4, 0x4d, 0xfd, 0x77, 0x1d, 0x6e, 0xe6, + 0x4a, 0x25, 0xfa, 0xf1, 0x05, 0x0c, 0xe7, 0xd6, 0x73, 0x63, 0x37, 0xb9, 0x01, 0x7d, 0xf6, 0x0a, + 0x03, 0xfa, 0x2e, 0x2c, 0xeb, 0x23, 0xcf, 0xa3, 0x36, 0xcb, 0xb0, 0x9a, 0x88, 0x1a, 0xed, 0xa5, + 0xc5, 0x38, 0xab, 0x5f, 0xc4, 0xae, 0x1a, 0x57, 0x64, 0x57, 0xc9, 0x5d, 0xc8, 0x09, 0x39, 0x08, + 0xbb, 0xfc, 0x2e, 0xe4, 0xa0, 0x9c, 0xd5, 0xe7, 0xd3, 0x41, 0x80, 0x1a, 0x21, 0xcc, 0xa7, 0xa7, + 0x83, 0xd3, 0x94, 0x14, 0x67, 0xb4, 0x0b, 0x98, 0xca, 0x42, 0x55, 0xa6, 0x82, 0x48, 0x8a, 0x84, + 0x81, 0xc8, 0xf1, 0xed, 0x2a, 0xb1, 0x5c, 0x99, 0x85, 0xa9, 0x7f, 0x53, 0xe0, 0xc5, 0xd2, 0x24, + 0x40, 0xbb, 0xa9, 0x96, 0xbb, 0x9d, 0x69, 0xb9, 0xdf, 0x2b, 0x35, 0x4c, 0xf4, 0x5d, 0xaf, 0x98, + 0x1a, 0xbd, 0x5f, 0x8d, 0x1a, 0x15, 0xcc, 0xed, 0x97, 0x73, 0xa4, 0xde, 0xf6, 0x93, 0xa7, 0x9d, + 0x99, 0xaf, 0x9e, 0x76, 0x66, 0xbe, 0x7e, 0xda, 0x99, 0xf9, 0xcd, 0xb4, 0xa3, 0x3c, 0x99, 0x76, + 0x94, 0xaf, 0xa6, 0x1d, 0xe5, 0xeb, 0x69, 0x47, 0xf9, 0xc7, 0xb4, 0xa3, 0xfc, 0xee, 0x9b, 0xce, + 0xcc, 0x67, 0xf3, 0xd2, 0xe3, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe9, 0x89, 0x29, 0x5c, 0x61, + 0x1b, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/generated.proto index da160922d..6f41f06bc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,7 +22,6 @@ syntax = 'proto2'; package k8s.io.api.apps.v1beta1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; @@ -245,9 +244,9 @@ message RollingUpdateDeployment { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -259,10 +258,10 @@ message RollingUpdateDeployment { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is atmost 130% of desired pods. // +optional optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/types.go index dd9e97e10..d462604d7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/types.go @@ -379,8 +379,8 @@ type RollbackConfig struct { const ( // DefaultDeploymentUniqueLabelKey is the default key of the selector that is added - // to existing RCs (and label key that is added to its pods) to prevent the existing RCs - // to select new pods (and old pods being select by new RC). + // to existing ReplicaSets (and label key that is added to its pods) to prevent the existing ReplicaSets + // to select new pods (and old pods being select by new ReplicaSet). DefaultDeploymentUniqueLabelKey string = "pod-template-hash" ) @@ -405,7 +405,7 @@ const ( // Kill all existing pods before creating new ones. RecreateDeploymentStrategyType DeploymentStrategyType = "Recreate" - // Replace the old RCs by new one using rolling update i.e gradually scale down the old RCs and scale up the new one. + // Replace the old ReplicaSets by new one using rolling update i.e gradually scale down the old ReplicaSets and scale up the new one. RollingUpdateDeploymentStrategyType DeploymentStrategyType = "RollingUpdate" ) @@ -416,9 +416,9 @@ type RollingUpdateDeployment struct { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -430,10 +430,10 @@ type RollingUpdateDeployment struct { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is atmost 130% of desired pods. // +optional MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/types_swagger_doc_generated.go index d12baf39f..68ebef348 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_ControllerRevision = map[string]string{ "": "DEPRECATED - This group version of ControllerRevision is deprecated by apps/v1beta2/ControllerRevision. See the release notes for more information. ControllerRevision implements an immutable snapshot of state data. Clients are responsible for serializing and deserializing the objects that contain their internal state. Once a ControllerRevision has been successfully created, it can not be updated. The API Server will fail validation of all requests that attempt to mutate the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, it may be subject to name and representation changes in future releases, and clients should not depend on its stability. It is primarily for internal use by controllers.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -148,8 +148,8 @@ func (RollbackConfig) SwaggerDoc() map[string]string { var map_RollingUpdateDeployment = map[string]string{ "": "Spec to control the desired behavior of rolling update.", - "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", - "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", + "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", } func (RollingUpdateDeployment) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/zz_generated.deepcopy.go index b06032e1e..dd37f8dd8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/generated.pb.go index cfd422edb..72d832c34 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -64,7 +64,6 @@ import fmt "fmt" import math "math" import k8s_io_api_core_v1 "k8s.io/api/core/v1" - import k8s_io_apimachinery_pkg_apis_meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" import k8s_io_apimachinery_pkg_util_intstr "k8s.io/apimachinery/pkg/util/intstr" @@ -7445,142 +7444,141 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2186 bytes of a gzipped FileDescriptorProto + // 2176 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcb, 0x6f, 0x1c, 0xb7, - 0x19, 0xf7, 0xec, 0x43, 0x5a, 0x51, 0x96, 0x64, 0x53, 0xaa, 0xb4, 0x91, 0xdb, 0x95, 0xb1, 0x09, - 0x1c, 0x39, 0xb6, 0x66, 0x6d, 0xe5, 0x81, 0xc4, 0x2e, 0xda, 0x6a, 0xa5, 0xd4, 0x76, 0xa0, 0x57, + 0x19, 0xd7, 0xec, 0x43, 0x5a, 0x51, 0x91, 0x64, 0x53, 0xaa, 0xb4, 0x91, 0xdb, 0x95, 0xb1, 0x09, + 0x1c, 0x25, 0xb6, 0x66, 0x6d, 0xe5, 0x81, 0xc4, 0x2e, 0xda, 0x6a, 0xa5, 0xd4, 0x76, 0xa0, 0x57, 0x28, 0xcb, 0x40, 0x83, 0x16, 0x35, 0xb5, 0x4b, 0xaf, 0x26, 0x9a, 0x17, 0x66, 0x38, 0x5b, 0x2f, 0x7a, 0xe9, 0xa9, 0x40, 0x81, 0x02, 0x6d, 0xaf, 0xfd, 0x27, 0x7a, 0x2b, 0x8a, 0xf6, 0x56, 0x04, 0x85, 0x2f, 0x05, 0x82, 0x5e, 0x92, 0x93, 0x50, 0x6f, 0x4e, 0x45, 0xd1, 0x4b, 0x81, 0x5e, 0x02, 0x14, 0x28, 0xc8, 0xe1, 0x3c, 0x38, 0x0f, 0xef, 0x48, 0xb1, 0x95, 0x22, 0xc8, 0x6d, 0x87, 0xfc, - 0x7d, 0x3f, 0x7e, 0x24, 0xbf, 0x8f, 0xdf, 0x6f, 0x38, 0x0b, 0xbe, 0x77, 0xf4, 0xb6, 0xab, 0x6a, - 0x56, 0xeb, 0xc8, 0x3b, 0x20, 0x8e, 0x49, 0x28, 0x71, 0x5b, 0x7d, 0x62, 0x76, 0x2d, 0xa7, 0x25, - 0x3a, 0xb0, 0xad, 0xb5, 0xb0, 0x6d, 0xbb, 0xad, 0xfe, 0xcd, 0x03, 0x42, 0xf1, 0x6a, 0xab, 0x47, - 0x4c, 0xe2, 0x60, 0x4a, 0xba, 0xaa, 0xed, 0x58, 0xd4, 0x82, 0x0b, 0x3e, 0x50, 0xc5, 0xb6, 0xa6, - 0x32, 0xa0, 0x2a, 0x80, 0x8b, 0x2b, 0x3d, 0x8d, 0x1e, 0x7a, 0x07, 0x6a, 0xc7, 0x32, 0x5a, 0x3d, - 0xab, 0x67, 0xb5, 0x38, 0xfe, 0xc0, 0x7b, 0xc4, 0x9f, 0xf8, 0x03, 0xff, 0xe5, 0xf3, 0x2c, 0x36, - 0x63, 0x03, 0x76, 0x2c, 0x87, 0xb4, 0xfa, 0x37, 0x93, 0x63, 0x2d, 0x5e, 0x8d, 0x61, 0x6c, 0x4b, - 0xd7, 0x3a, 0x03, 0xe1, 0x56, 0x1a, 0xfa, 0x46, 0x04, 0x35, 0x70, 0xe7, 0x50, 0x33, 0x89, 0x33, - 0x68, 0xd9, 0x47, 0x3d, 0xd6, 0xe0, 0xb6, 0x0c, 0x42, 0x71, 0xd6, 0x00, 0xad, 0x3c, 0x2b, 0xc7, - 0x33, 0xa9, 0x66, 0x90, 0x94, 0xc1, 0x5b, 0xa3, 0x0c, 0xdc, 0xce, 0x21, 0x31, 0x70, 0xca, 0xee, - 0xf5, 0x3c, 0x3b, 0x8f, 0x6a, 0x7a, 0x4b, 0x33, 0xa9, 0x4b, 0x9d, 0xa4, 0x51, 0xf3, 0x3f, 0x0a, - 0x80, 0xeb, 0x96, 0x49, 0x1d, 0x4b, 0xd7, 0x89, 0x83, 0x48, 0x5f, 0x73, 0x35, 0xcb, 0x84, 0x0f, - 0x41, 0x8d, 0xcd, 0xa7, 0x8b, 0x29, 0xae, 0x2b, 0x97, 0x95, 0xe5, 0xc9, 0xd5, 0x1b, 0x6a, 0xb4, - 0x29, 0x21, 0xbd, 0x6a, 0x1f, 0xf5, 0x58, 0x83, 0xab, 0x32, 0xb4, 0xda, 0xbf, 0xa9, 0xee, 0x1c, - 0x7c, 0x48, 0x3a, 0x74, 0x8b, 0x50, 0xdc, 0x86, 0x4f, 0x8e, 0x97, 0xce, 0x0d, 0x8f, 0x97, 0x40, - 0xd4, 0x86, 0x42, 0x56, 0xb8, 0x03, 0x2a, 0x9c, 0xbd, 0xc4, 0xd9, 0x57, 0x72, 0xd9, 0xc5, 0xa4, - 0x55, 0x84, 0x7f, 0xf2, 0xee, 0x63, 0x4a, 0x4c, 0xe6, 0x5e, 0xfb, 0xbc, 0xa0, 0xae, 0x6c, 0x60, - 0x8a, 0x11, 0x27, 0x82, 0xd7, 0x41, 0xcd, 0x11, 0xee, 0xd7, 0xcb, 0x97, 0x95, 0xe5, 0x72, 0xfb, - 0x82, 0x40, 0xd5, 0x82, 0x69, 0xa1, 0x10, 0xd1, 0x7c, 0xa2, 0x80, 0xf9, 0xf4, 0xbc, 0x37, 0x35, - 0x97, 0xc2, 0x1f, 0xa6, 0xe6, 0xae, 0x16, 0x9b, 0x3b, 0xb3, 0xe6, 0x33, 0x0f, 0x07, 0x0e, 0x5a, - 0x62, 0xf3, 0xde, 0x05, 0x55, 0x8d, 0x12, 0xc3, 0xad, 0x97, 0x2e, 0x97, 0x97, 0x27, 0x57, 0xaf, - 0xa9, 0x39, 0xb1, 0xae, 0xa6, 0xbd, 0x6b, 0x4f, 0x09, 0xde, 0xea, 0x3d, 0xc6, 0x80, 0x7c, 0xa2, - 0xe6, 0x2f, 0x4a, 0x60, 0x62, 0x03, 0x13, 0xc3, 0x32, 0xf7, 0x08, 0x3d, 0x83, 0x9d, 0xbb, 0x0b, - 0x2a, 0xae, 0x4d, 0x3a, 0x62, 0xe7, 0xae, 0xe4, 0x4e, 0x20, 0xf4, 0x69, 0xcf, 0x26, 0x9d, 0x68, - 0xcb, 0xd8, 0x13, 0xe2, 0x0c, 0x70, 0x17, 0x8c, 0xb9, 0x14, 0x53, 0xcf, 0xe5, 0x1b, 0x36, 0xb9, - 0xba, 0x5c, 0x80, 0x8b, 0xe3, 0xdb, 0xd3, 0x82, 0x6d, 0xcc, 0x7f, 0x46, 0x82, 0xa7, 0xf9, 0x8f, - 0x12, 0x80, 0x21, 0x76, 0xdd, 0x32, 0xbb, 0x1a, 0x65, 0xe1, 0x7c, 0x0b, 0x54, 0xe8, 0xc0, 0x26, - 0x7c, 0x41, 0x26, 0xda, 0x57, 0x02, 0x57, 0xee, 0x0f, 0x6c, 0xf2, 0xf9, 0xf1, 0xd2, 0x7c, 0xda, - 0x82, 0xf5, 0x20, 0x6e, 0x03, 0x37, 0x43, 0x27, 0x4b, 0xdc, 0xfa, 0x0d, 0x79, 0xe8, 0xcf, 0x8f, - 0x97, 0x32, 0x8e, 0x19, 0x35, 0x64, 0x92, 0x1d, 0x84, 0x7d, 0x00, 0x75, 0xec, 0xd2, 0xfb, 0x0e, - 0x36, 0x5d, 0x7f, 0x24, 0xcd, 0x20, 0x62, 0xfa, 0xaf, 0x15, 0xdb, 0x28, 0x66, 0xd1, 0x5e, 0x14, - 0x5e, 0xc0, 0xcd, 0x14, 0x1b, 0xca, 0x18, 0x01, 0x5e, 0x01, 0x63, 0x0e, 0xc1, 0xae, 0x65, 0xd6, - 0x2b, 0x7c, 0x16, 0xe1, 0x02, 0x22, 0xde, 0x8a, 0x44, 0x2f, 0xbc, 0x0a, 0xc6, 0x0d, 0xe2, 0xba, - 0xb8, 0x47, 0xea, 0x55, 0x0e, 0x9c, 0x11, 0xc0, 0xf1, 0x2d, 0xbf, 0x19, 0x05, 0xfd, 0xcd, 0xdf, - 0x2b, 0x60, 0x2a, 0x5c, 0xb9, 0x33, 0xc8, 0x9c, 0x3b, 0x72, 0xe6, 0x34, 0x47, 0x07, 0x4b, 0x4e, - 0xc2, 0x7c, 0x54, 0x8e, 0x39, 0xce, 0xc2, 0x11, 0xfe, 0x08, 0xd4, 0x5c, 0xa2, 0x93, 0x0e, 0xb5, - 0x1c, 0xe1, 0xf8, 0xeb, 0x05, 0x1d, 0xc7, 0x07, 0x44, 0xdf, 0x13, 0xa6, 0xed, 0xf3, 0xcc, 0xf3, - 0xe0, 0x09, 0x85, 0x94, 0xf0, 0x7d, 0x50, 0xa3, 0xc4, 0xb0, 0x75, 0x4c, 0x89, 0xc8, 0x9a, 0x97, - 0xe3, 0xce, 0xb3, 0x98, 0x61, 0x64, 0xbb, 0x56, 0xf7, 0xbe, 0x80, 0xf1, 0x94, 0x09, 0x17, 0x23, - 0x68, 0x45, 0x21, 0x0d, 0xb4, 0xc1, 0xb4, 0x67, 0x77, 0x19, 0x92, 0xb2, 0xe3, 0xbc, 0x37, 0x10, - 0x31, 0x74, 0x63, 0xf4, 0xaa, 0xec, 0x4b, 0x76, 0xed, 0x79, 0x31, 0xca, 0xb4, 0xdc, 0x8e, 0x12, - 0xfc, 0x70, 0x0d, 0xcc, 0x18, 0x9a, 0x89, 0x08, 0xee, 0x0e, 0xf6, 0x48, 0xc7, 0x32, 0xbb, 0x2e, - 0x0f, 0xa5, 0x6a, 0x7b, 0x41, 0x10, 0xcc, 0x6c, 0xc9, 0xdd, 0x28, 0x89, 0x87, 0x9b, 0x60, 0x2e, - 0x38, 0x80, 0xef, 0x6a, 0x2e, 0xb5, 0x9c, 0xc1, 0xa6, 0x66, 0x68, 0xb4, 0x3e, 0xc6, 0x79, 0xea, - 0xc3, 0xe3, 0xa5, 0x39, 0x94, 0xd1, 0x8f, 0x32, 0xad, 0x9a, 0xbf, 0x19, 0x03, 0x33, 0x89, 0x73, - 0x01, 0x3e, 0x00, 0xf3, 0x1d, 0xcf, 0x71, 0x88, 0x49, 0xb7, 0x3d, 0xe3, 0x80, 0x38, 0x7b, 0x9d, - 0x43, 0xd2, 0xf5, 0x74, 0xd2, 0xe5, 0xdb, 0x5a, 0x6d, 0x37, 0x84, 0xaf, 0xf3, 0xeb, 0x99, 0x28, - 0x94, 0x63, 0x0d, 0xdf, 0x03, 0xd0, 0xe4, 0x4d, 0x5b, 0x9a, 0xeb, 0x86, 0x9c, 0x25, 0xce, 0x19, - 0xa6, 0xe2, 0x76, 0x0a, 0x81, 0x32, 0xac, 0x98, 0x8f, 0x5d, 0xe2, 0x6a, 0x0e, 0xe9, 0x26, 0x7d, - 0x2c, 0xcb, 0x3e, 0x6e, 0x64, 0xa2, 0x50, 0x8e, 0x35, 0x7c, 0x13, 0x4c, 0xfa, 0xa3, 0xf1, 0x35, - 0x17, 0x9b, 0x33, 0x2b, 0xc8, 0x26, 0xb7, 0xa3, 0x2e, 0x14, 0xc7, 0xb1, 0xa9, 0x59, 0x07, 0x2e, - 0x71, 0xfa, 0xa4, 0x7b, 0xc7, 0x17, 0x07, 0xac, 0x82, 0x56, 0x79, 0x05, 0x0d, 0xa7, 0xb6, 0x93, - 0x42, 0xa0, 0x0c, 0x2b, 0x36, 0x35, 0x3f, 0x6a, 0x52, 0x53, 0x1b, 0x93, 0xa7, 0xb6, 0x9f, 0x89, - 0x42, 0x39, 0xd6, 0x2c, 0xf6, 0x7c, 0x97, 0xd7, 0xfa, 0x58, 0xd3, 0xf1, 0x81, 0x4e, 0xea, 0xe3, - 0x72, 0xec, 0x6d, 0xcb, 0xdd, 0x28, 0x89, 0x87, 0x77, 0xc0, 0x45, 0xbf, 0x69, 0xdf, 0xc4, 0x21, - 0x49, 0x8d, 0x93, 0xbc, 0x24, 0x48, 0x2e, 0x6e, 0x27, 0x01, 0x28, 0x6d, 0x03, 0x6f, 0x81, 0xe9, - 0x8e, 0xa5, 0xeb, 0x3c, 0x1e, 0xd7, 0x2d, 0xcf, 0xa4, 0xf5, 0x09, 0xce, 0x02, 0x59, 0x0e, 0xad, - 0x4b, 0x3d, 0x28, 0x81, 0x84, 0x3f, 0x06, 0xa0, 0x13, 0x14, 0x06, 0xb7, 0x0e, 0x46, 0x28, 0x80, - 0x74, 0x59, 0x8a, 0x2a, 0x73, 0xd8, 0xe4, 0xa2, 0x18, 0x65, 0xf3, 0x23, 0x05, 0x2c, 0xe4, 0x24, - 0x3a, 0xfc, 0xae, 0x54, 0x04, 0xaf, 0x25, 0x8a, 0xe0, 0xa5, 0x1c, 0xb3, 0x58, 0x25, 0x3c, 0x04, - 0x53, 0x4c, 0x90, 0x68, 0x66, 0xcf, 0x87, 0x88, 0xb3, 0xac, 0x95, 0x3b, 0x01, 0x14, 0x47, 0x47, - 0xa7, 0xf2, 0xc5, 0xe1, 0xf1, 0xd2, 0x94, 0xd4, 0x87, 0x64, 0xe2, 0xe6, 0x2f, 0x4b, 0x00, 0x6c, - 0x10, 0x5b, 0xb7, 0x06, 0x06, 0x31, 0xcf, 0x42, 0xd3, 0xdc, 0x93, 0x34, 0xcd, 0xab, 0xf9, 0x5b, - 0x12, 0x3a, 0x95, 0x2b, 0x6a, 0xde, 0x4f, 0x88, 0x9a, 0xab, 0x45, 0xc8, 0x9e, 0xad, 0x6a, 0x3e, - 0x29, 0x83, 0xd9, 0x08, 0x1c, 0xc9, 0x9a, 0xdb, 0xd2, 0x8e, 0xbe, 0x9a, 0xd8, 0xd1, 0x85, 0x0c, - 0x93, 0x17, 0xa6, 0x6b, 0x9e, 0xbf, 0xbe, 0x80, 0x1f, 0x82, 0x69, 0x26, 0x64, 0xfc, 0x90, 0xe0, - 0x32, 0x69, 0xec, 0xc4, 0x32, 0x29, 0x2c, 0x6e, 0x9b, 0x12, 0x13, 0x4a, 0x30, 0xe7, 0xc8, 0xb2, - 0xf1, 0x17, 0x2d, 0xcb, 0x9a, 0x7f, 0x50, 0xc0, 0x74, 0xb4, 0x4d, 0x67, 0x20, 0xa2, 0xee, 0xca, - 0x22, 0xea, 0xe5, 0x02, 0xc1, 0x99, 0xa3, 0xa2, 0x3e, 0xa9, 0xc4, 0x5d, 0xe7, 0x32, 0x6a, 0x99, - 0xbd, 0x82, 0xd9, 0xba, 0xd6, 0xc1, 0xae, 0xa8, 0xb7, 0xe7, 0xfd, 0xd7, 0x2f, 0xbf, 0x0d, 0x85, - 0xbd, 0x92, 0xe0, 0x2a, 0xbd, 0x58, 0xc1, 0x55, 0x7e, 0x3e, 0x82, 0xeb, 0x07, 0xa0, 0xe6, 0x06, - 0x52, 0xab, 0xc2, 0x29, 0xaf, 0x15, 0x4a, 0x6c, 0xa1, 0xb2, 0x42, 0xea, 0x50, 0x5f, 0x85, 0x74, - 0x59, 0xca, 0xaa, 0xfa, 0x65, 0x2a, 0x2b, 0x96, 0xcc, 0x36, 0xf6, 0x5c, 0xd2, 0xe5, 0x19, 0x50, - 0x8b, 0x92, 0x79, 0x97, 0xb7, 0x22, 0xd1, 0x0b, 0xf7, 0xc1, 0x82, 0xed, 0x58, 0x3d, 0x87, 0xb8, - 0xee, 0x06, 0xc1, 0x5d, 0x5d, 0x33, 0x49, 0x30, 0x01, 0xbf, 0x26, 0x5e, 0x1a, 0x1e, 0x2f, 0x2d, - 0xec, 0x66, 0x43, 0x50, 0x9e, 0x6d, 0xf3, 0xcf, 0x15, 0x70, 0x21, 0x79, 0x36, 0xe6, 0xc8, 0x14, - 0xe5, 0x54, 0x32, 0xe5, 0x7a, 0x2c, 0x4e, 0x7d, 0x0d, 0x17, 0xbb, 0x2a, 0x48, 0xc5, 0xea, 0x1a, - 0x98, 0x11, 0xb2, 0x24, 0xe8, 0x14, 0x42, 0x2d, 0xdc, 0x9e, 0x7d, 0xb9, 0x1b, 0x25, 0xf1, 0x4c, - 0x7c, 0x44, 0x9a, 0x22, 0x20, 0xa9, 0xc8, 0xe2, 0x63, 0x2d, 0x09, 0x40, 0x69, 0x1b, 0xb8, 0x05, - 0x66, 0x3d, 0x33, 0x4d, 0xe5, 0x87, 0xcb, 0x25, 0x41, 0x35, 0xbb, 0x9f, 0x86, 0xa0, 0x2c, 0x3b, - 0xf8, 0x50, 0xd2, 0x23, 0x63, 0xfc, 0x48, 0xb8, 0x5e, 0x20, 0xac, 0x0b, 0x0b, 0x12, 0x78, 0x1b, - 0x4c, 0x39, 0x5c, 0x73, 0x06, 0xae, 0xfa, 0xba, 0xed, 0x1b, 0xc2, 0x6c, 0x0a, 0xc5, 0x3b, 0x91, - 0x8c, 0xcd, 0x90, 0x5a, 0xb5, 0xa2, 0x52, 0xab, 0xf9, 0x27, 0x05, 0xc0, 0x74, 0x1e, 0x8e, 0xbc, - 0x09, 0x48, 0x59, 0xc4, 0x2a, 0xa6, 0x96, 0xad, 0x7f, 0x6e, 0x14, 0xd4, 0x3f, 0xd1, 0x81, 0x5a, - 0x4c, 0x00, 0x89, 0x65, 0x38, 0x9b, 0x4b, 0x9d, 0xa2, 0x02, 0x28, 0x72, 0xea, 0x39, 0x08, 0xa0, - 0x18, 0xd9, 0xb3, 0x05, 0xd0, 0x3f, 0x4b, 0x60, 0x36, 0x02, 0x17, 0x16, 0x40, 0x19, 0x26, 0x5f, - 0x5f, 0xec, 0x8c, 0xbe, 0xd8, 0x61, 0xa2, 0x24, 0x5a, 0xba, 0xff, 0x27, 0x51, 0x12, 0x79, 0x95, - 0x23, 0x4a, 0x7e, 0x57, 0x8a, 0xbb, 0xfe, 0x95, 0x17, 0x25, 0x5f, 0xfc, 0x4e, 0xa6, 0xf9, 0x97, - 0x32, 0xb8, 0x90, 0xcc, 0x43, 0xa9, 0x40, 0x2a, 0x23, 0x0b, 0xe4, 0x2e, 0x98, 0x7b, 0xe4, 0xe9, - 0xfa, 0x80, 0x2f, 0x43, 0xac, 0x4a, 0xfa, 0xa5, 0xf5, 0x9b, 0xc2, 0x72, 0xee, 0xfb, 0x19, 0x18, - 0x94, 0x69, 0x99, 0x53, 0xec, 0xcb, 0xa7, 0x2a, 0xf6, 0xa9, 0x0a, 0x54, 0x39, 0x41, 0x05, 0xca, - 0x2c, 0xdc, 0xd5, 0x53, 0x14, 0xee, 0x93, 0x55, 0xda, 0x8c, 0x83, 0x6b, 0xe4, 0xab, 0xff, 0xcf, - 0x15, 0x30, 0x9f, 0xfd, 0xc2, 0x0d, 0x75, 0x30, 0x6d, 0xe0, 0xc7, 0xf1, 0x8b, 0x8f, 0x51, 0x45, - 0xc4, 0xa3, 0x9a, 0xae, 0xfa, 0x9f, 0x8c, 0xd4, 0x7b, 0x26, 0xdd, 0x71, 0xf6, 0xa8, 0xa3, 0x99, - 0x3d, 0xbf, 0xf2, 0x6e, 0x49, 0x5c, 0x28, 0xc1, 0xdd, 0xfc, 0x4c, 0x01, 0x0b, 0x39, 0x95, 0xef, - 0x6c, 0x3d, 0x81, 0x1f, 0x80, 0x9a, 0x81, 0x1f, 0xef, 0x79, 0x4e, 0x2f, 0xab, 0x56, 0x17, 0x1b, - 0x87, 0x67, 0xf3, 0x96, 0x60, 0x41, 0x21, 0x5f, 0x73, 0x07, 0x5c, 0x96, 0x26, 0xc9, 0x32, 0x87, - 0x3c, 0xf2, 0x74, 0x9e, 0x44, 0x42, 0x6c, 0x5c, 0x03, 0x13, 0x36, 0x76, 0xa8, 0x16, 0x4a, 0xd5, - 0x6a, 0x7b, 0x6a, 0x78, 0xbc, 0x34, 0xb1, 0x1b, 0x34, 0xa2, 0xa8, 0xbf, 0xf9, 0x5f, 0x05, 0x54, - 0xf7, 0x3a, 0x58, 0x27, 0x67, 0x50, 0xed, 0x37, 0xa4, 0x6a, 0x9f, 0x7f, 0x93, 0xce, 0xfd, 0xc9, - 0x2d, 0xf4, 0x9b, 0x89, 0x42, 0xff, 0xca, 0x08, 0x9e, 0x67, 0xd7, 0xf8, 0x77, 0xc0, 0x44, 0x38, - 0xdc, 0xc9, 0x0e, 0xa0, 0xe6, 0x6f, 0x4b, 0x60, 0x32, 0x36, 0xc4, 0x09, 0x8f, 0xaf, 0x87, 0xd2, - 0xb1, 0xcf, 0x12, 0x73, 0xb5, 0xc8, 0x44, 0xd4, 0xe0, 0x88, 0x7f, 0xd7, 0xa4, 0x4e, 0xfc, 0x05, - 0x2f, 0x7d, 0xf2, 0x7f, 0x07, 0x4c, 0x53, 0xec, 0xf4, 0x08, 0x0d, 0xfa, 0xf8, 0x82, 0x4d, 0x44, - 0xb7, 0x13, 0xf7, 0xa5, 0x5e, 0x94, 0x40, 0x2f, 0xde, 0x06, 0x53, 0xd2, 0x60, 0xf0, 0x02, 0x28, - 0x1f, 0x91, 0x81, 0x2f, 0x7b, 0x10, 0xfb, 0x09, 0xe7, 0x40, 0xb5, 0x8f, 0x75, 0xcf, 0x8f, 0xf3, - 0x09, 0xe4, 0x3f, 0xdc, 0x2a, 0xbd, 0xad, 0x34, 0x7f, 0xc5, 0x16, 0x27, 0x0a, 0xce, 0x33, 0x88, - 0xae, 0xf7, 0xa4, 0xe8, 0xca, 0xff, 0xa8, 0x17, 0x4f, 0x99, 0xbc, 0x18, 0x43, 0x89, 0x18, 0x7b, - 0xad, 0x10, 0xdb, 0xb3, 0x23, 0xed, 0x5f, 0x25, 0x30, 0x17, 0x43, 0x47, 0x72, 0xf2, 0xdb, 0x92, - 0x9c, 0x5c, 0x4e, 0xc8, 0xc9, 0x7a, 0x96, 0xcd, 0xd7, 0x7a, 0x72, 0xb4, 0x9e, 0xfc, 0xa3, 0x02, - 0x66, 0x62, 0x6b, 0x77, 0x06, 0x82, 0xf2, 0x9e, 0x2c, 0x28, 0x5f, 0x29, 0x12, 0x34, 0x39, 0x8a, - 0xf2, 0xaf, 0x55, 0xc9, 0xf9, 0xaf, 0xbc, 0xa4, 0xfc, 0x29, 0x98, 0xeb, 0x5b, 0xba, 0x67, 0x90, - 0x75, 0x1d, 0x6b, 0x46, 0x00, 0x60, 0xaa, 0xa9, 0x9c, 0x7c, 0x97, 0x0b, 0xe9, 0x89, 0xe3, 0x6a, - 0x2e, 0x25, 0x26, 0x7d, 0x10, 0x59, 0x46, 0xba, 0xef, 0x41, 0x06, 0x1d, 0xca, 0x1c, 0x04, 0xbe, - 0x09, 0x26, 0x99, 0x7e, 0xd3, 0x3a, 0x64, 0x1b, 0x1b, 0x41, 0x60, 0x85, 0x9f, 0xb0, 0xf6, 0xa2, - 0x2e, 0x14, 0xc7, 0xc1, 0x43, 0x30, 0x6b, 0x5b, 0xdd, 0x2d, 0x6c, 0xe2, 0x1e, 0x61, 0x32, 0x63, - 0x97, 0xff, 0x8f, 0x87, 0x5f, 0x7e, 0x4d, 0xb4, 0xdf, 0x0a, 0x6e, 0x45, 0x76, 0xd3, 0x10, 0xf6, - 0x92, 0x98, 0xd1, 0xcc, 0x93, 0x3a, 0x8b, 0x12, 0x3a, 0xa9, 0xcf, 0xae, 0xfe, 0x1d, 0xf1, 0x6a, - 0x91, 0x08, 0x3b, 0xe5, 0x87, 0xd7, 0xbc, 0xbb, 0xbd, 0xda, 0xa9, 0xbe, 0x9a, 0xfe, 0xbb, 0x02, - 0x2e, 0xa6, 0x8e, 0xca, 0x2f, 0xf1, 0x76, 0x2d, 0x25, 0xcf, 0xcb, 0x27, 0x90, 0xe7, 0x6b, 0x60, - 0x46, 0x7c, 0xb0, 0x4d, 0xa8, 0xfb, 0xf0, 0xfd, 0x67, 0x5d, 0xee, 0x46, 0x49, 0x7c, 0xd6, 0xed, - 0x5e, 0xf5, 0x84, 0xb7, 0x7b, 0x71, 0x2f, 0xc4, 0x1f, 0x90, 0xfc, 0xd0, 0x4b, 0x7b, 0x21, 0xfe, - 0x87, 0x94, 0xc4, 0x33, 0x85, 0xe0, 0xb3, 0x86, 0x0c, 0xe3, 0xb2, 0x42, 0xd8, 0x97, 0x7a, 0x51, - 0x02, 0xfd, 0x85, 0x3e, 0x4a, 0xe2, 0x8c, 0x8f, 0x92, 0x2b, 0x45, 0xe2, 0xb9, 0xf8, 0xbb, 0xc9, - 0xdf, 0x14, 0xf0, 0x52, 0x6e, 0x22, 0xc0, 0x35, 0xa9, 0xec, 0xae, 0x24, 0xca, 0xee, 0xb7, 0x72, - 0x0d, 0x63, 0xb5, 0xd7, 0xc9, 0xbe, 0x9a, 0x7b, 0xa7, 0xd8, 0xd5, 0x5c, 0x86, 0x76, 0x1f, 0x7d, - 0x47, 0xd7, 0x5e, 0x79, 0xf2, 0xb4, 0x71, 0xee, 0xe3, 0xa7, 0x8d, 0x73, 0x9f, 0x3e, 0x6d, 0x9c, - 0xfb, 0xd9, 0xb0, 0xa1, 0x3c, 0x19, 0x36, 0x94, 0x8f, 0x87, 0x0d, 0xe5, 0xd3, 0x61, 0x43, 0xf9, - 0xfb, 0xb0, 0xa1, 0xfc, 0xfa, 0xb3, 0xc6, 0xb9, 0x0f, 0xc6, 0xc5, 0x88, 0xff, 0x0b, 0x00, 0x00, - 0xff, 0xff, 0xe4, 0x8f, 0x6a, 0x57, 0x17, 0x29, 0x00, 0x00, + 0x7d, 0x3f, 0x7e, 0x24, 0xbf, 0x8f, 0xdf, 0x6f, 0x38, 0x0b, 0xbe, 0x77, 0xfc, 0xb6, 0xab, 0x6a, + 0x56, 0xeb, 0xd8, 0x3b, 0x24, 0x8e, 0x49, 0x28, 0x71, 0x5b, 0x7d, 0x62, 0x76, 0x2d, 0xa7, 0x25, + 0x3a, 0xb0, 0xad, 0xb5, 0xb0, 0x6d, 0xbb, 0xad, 0xfe, 0x8d, 0x43, 0x42, 0xf1, 0x5a, 0xab, 0x47, + 0x4c, 0xe2, 0x60, 0x4a, 0xba, 0xaa, 0xed, 0x58, 0xd4, 0x82, 0x8b, 0x3e, 0x50, 0xc5, 0xb6, 0xa6, + 0x32, 0xa0, 0x2a, 0x80, 0x4b, 0xab, 0x3d, 0x8d, 0x1e, 0x79, 0x87, 0x6a, 0xc7, 0x32, 0x5a, 0x3d, + 0xab, 0x67, 0xb5, 0x38, 0xfe, 0xd0, 0x7b, 0xc8, 0x9f, 0xf8, 0x03, 0xff, 0xe5, 0xf3, 0x2c, 0x35, + 0x63, 0x03, 0x76, 0x2c, 0x87, 0xb4, 0xfa, 0x37, 0x92, 0x63, 0x2d, 0xbd, 0x11, 0x61, 0x0c, 0xdc, + 0x39, 0xd2, 0x4c, 0xe2, 0x0c, 0x5a, 0xf6, 0x71, 0x8f, 0x35, 0xb8, 0x2d, 0x83, 0x50, 0x9c, 0x65, + 0xd5, 0xca, 0xb3, 0x72, 0x3c, 0x93, 0x6a, 0x06, 0x49, 0x19, 0xbc, 0x35, 0xca, 0xc0, 0xed, 0x1c, + 0x11, 0x03, 0xa7, 0xec, 0x5e, 0xcf, 0xb3, 0xf3, 0xa8, 0xa6, 0xb7, 0x34, 0x93, 0xba, 0xd4, 0x49, + 0x1a, 0x35, 0xff, 0xa3, 0x00, 0xb8, 0x61, 0x99, 0xd4, 0xb1, 0x74, 0x9d, 0x38, 0x88, 0xf4, 0x35, + 0x57, 0xb3, 0x4c, 0xf8, 0x00, 0xd4, 0xd8, 0x7c, 0xba, 0x98, 0xe2, 0xba, 0x72, 0x59, 0x59, 0x99, + 0x5a, 0xbb, 0xae, 0x46, 0x2b, 0x1d, 0xd2, 0xab, 0xf6, 0x71, 0x8f, 0x35, 0xb8, 0x2a, 0x43, 0xab, + 0xfd, 0x1b, 0xea, 0xee, 0xe1, 0x87, 0xa4, 0x43, 0xb7, 0x09, 0xc5, 0x6d, 0xf8, 0xf8, 0x64, 0x79, + 0x6c, 0x78, 0xb2, 0x0c, 0xa2, 0x36, 0x14, 0xb2, 0xc2, 0x5d, 0x50, 0xe1, 0xec, 0x25, 0xce, 0xbe, + 0x9a, 0xcb, 0x2e, 0x26, 0xad, 0x22, 0xfc, 0x93, 0x77, 0x1f, 0x51, 0x62, 0x32, 0xf7, 0xda, 0x2f, + 0x08, 0xea, 0xca, 0x26, 0xa6, 0x18, 0x71, 0x22, 0x78, 0x0d, 0xd4, 0x1c, 0xe1, 0x7e, 0xbd, 0x7c, + 0x59, 0x59, 0x29, 0xb7, 0x2f, 0x08, 0x54, 0x2d, 0x98, 0x16, 0x0a, 0x11, 0xcd, 0xc7, 0x0a, 0x58, + 0x48, 0xcf, 0x7b, 0x4b, 0x73, 0x29, 0xfc, 0x61, 0x6a, 0xee, 0x6a, 0xb1, 0xb9, 0x33, 0x6b, 0x3e, + 0xf3, 0x70, 0xe0, 0xa0, 0x25, 0x36, 0xef, 0x3d, 0x50, 0xd5, 0x28, 0x31, 0xdc, 0x7a, 0xe9, 0x72, + 0x79, 0x65, 0x6a, 0xed, 0xaa, 0x9a, 0x13, 0xc0, 0x6a, 0xda, 0xbb, 0xf6, 0xb4, 0xe0, 0xad, 0xde, + 0x65, 0x0c, 0xc8, 0x27, 0x6a, 0xfe, 0xa2, 0x04, 0x26, 0x37, 0x31, 0x31, 0x2c, 0x73, 0x9f, 0xd0, + 0x73, 0xd8, 0xb9, 0x3b, 0xa0, 0xe2, 0xda, 0xa4, 0x23, 0x76, 0xee, 0x4a, 0xee, 0x04, 0x42, 0x9f, + 0xf6, 0x6d, 0xd2, 0x89, 0xb6, 0x8c, 0x3d, 0x21, 0xce, 0x00, 0xf7, 0xc0, 0xb8, 0x4b, 0x31, 0xf5, + 0x5c, 0xbe, 0x61, 0x53, 0x6b, 0x2b, 0x05, 0xb8, 0x38, 0xbe, 0x3d, 0x23, 0xd8, 0xc6, 0xfd, 0x67, + 0x24, 0x78, 0x9a, 0xff, 0x28, 0x01, 0x18, 0x62, 0x37, 0x2c, 0xb3, 0xab, 0x51, 0x16, 0xce, 0x37, + 0x41, 0x85, 0x0e, 0x6c, 0xc2, 0x17, 0x64, 0xb2, 0x7d, 0x25, 0x70, 0xe5, 0xde, 0xc0, 0x26, 0x9f, + 0x9f, 0x2c, 0x2f, 0xa4, 0x2d, 0x58, 0x0f, 0xe2, 0x36, 0x70, 0x2b, 0x74, 0xb2, 0xc4, 0xad, 0xdf, + 0x90, 0x87, 0xfe, 0xfc, 0x64, 0x39, 0xe3, 0xec, 0x50, 0x43, 0x26, 0xd9, 0x41, 0xd8, 0x07, 0x50, + 0xc7, 0x2e, 0xbd, 0xe7, 0x60, 0xd3, 0xf5, 0x47, 0xd2, 0x0c, 0x22, 0xa6, 0xff, 0x5a, 0xb1, 0x8d, + 0x62, 0x16, 0xed, 0x25, 0xe1, 0x05, 0xdc, 0x4a, 0xb1, 0xa1, 0x8c, 0x11, 0xe0, 0x15, 0x30, 0xee, + 0x10, 0xec, 0x5a, 0x66, 0xbd, 0xc2, 0x67, 0x11, 0x2e, 0x20, 0xe2, 0xad, 0x48, 0xf4, 0xc2, 0x57, + 0xc1, 0x84, 0x41, 0x5c, 0x17, 0xf7, 0x48, 0xbd, 0xca, 0x81, 0xb3, 0x02, 0x38, 0xb1, 0xed, 0x37, + 0xa3, 0xa0, 0xbf, 0xf9, 0x7b, 0x05, 0x4c, 0x87, 0x2b, 0x77, 0x0e, 0x99, 0x73, 0x5b, 0xce, 0x9c, + 0xe6, 0xe8, 0x60, 0xc9, 0x49, 0x98, 0x8f, 0xca, 0x31, 0xc7, 0x59, 0x38, 0xc2, 0x1f, 0x81, 0x9a, + 0x4b, 0x74, 0xd2, 0xa1, 0x96, 0x23, 0x1c, 0x7f, 0xbd, 0xa0, 0xe3, 0xf8, 0x90, 0xe8, 0xfb, 0xc2, + 0xb4, 0xfd, 0x02, 0xf3, 0x3c, 0x78, 0x42, 0x21, 0x25, 0x7c, 0x1f, 0xd4, 0x28, 0x31, 0x6c, 0x1d, + 0x53, 0x22, 0xb2, 0xe6, 0xa5, 0xb8, 0xf3, 0x2c, 0x66, 0x18, 0xd9, 0x9e, 0xd5, 0xbd, 0x27, 0x60, + 0x3c, 0x65, 0xc2, 0xc5, 0x08, 0x5a, 0x51, 0x48, 0x03, 0x6d, 0x30, 0xe3, 0xd9, 0x5d, 0x86, 0xa4, + 0xec, 0x38, 0xef, 0x0d, 0x44, 0x0c, 0x5d, 0x1f, 0xbd, 0x2a, 0x07, 0x92, 0x5d, 0x7b, 0x41, 0x8c, + 0x32, 0x23, 0xb7, 0xa3, 0x04, 0x3f, 0x5c, 0x07, 0xb3, 0x86, 0x66, 0x22, 0x82, 0xbb, 0x83, 0x7d, + 0xd2, 0xb1, 0xcc, 0xae, 0xcb, 0x43, 0xa9, 0xda, 0x5e, 0x14, 0x04, 0xb3, 0xdb, 0x72, 0x37, 0x4a, + 0xe2, 0xe1, 0x16, 0x98, 0x0f, 0x0e, 0xe0, 0x3b, 0x9a, 0x4b, 0x2d, 0x67, 0xb0, 0xa5, 0x19, 0x1a, + 0xad, 0x8f, 0x73, 0x9e, 0xfa, 0xf0, 0x64, 0x79, 0x1e, 0x65, 0xf4, 0xa3, 0x4c, 0xab, 0xe6, 0x6f, + 0xc6, 0xc1, 0x6c, 0xe2, 0x5c, 0x80, 0xf7, 0xc1, 0x42, 0xc7, 0x73, 0x1c, 0x62, 0xd2, 0x1d, 0xcf, + 0x38, 0x24, 0xce, 0x7e, 0xe7, 0x88, 0x74, 0x3d, 0x9d, 0x74, 0xf9, 0xb6, 0x56, 0xdb, 0x0d, 0xe1, + 0xeb, 0xc2, 0x46, 0x26, 0x0a, 0xe5, 0x58, 0xc3, 0xf7, 0x00, 0x34, 0x79, 0xd3, 0xb6, 0xe6, 0xba, + 0x21, 0x67, 0x89, 0x73, 0x86, 0xa9, 0xb8, 0x93, 0x42, 0xa0, 0x0c, 0x2b, 0xe6, 0x63, 0x97, 0xb8, + 0x9a, 0x43, 0xba, 0x49, 0x1f, 0xcb, 0xb2, 0x8f, 0x9b, 0x99, 0x28, 0x94, 0x63, 0x0d, 0xdf, 0x04, + 0x53, 0xfe, 0x68, 0x7c, 0xcd, 0xc5, 0xe6, 0xcc, 0x09, 0xb2, 0xa9, 0x9d, 0xa8, 0x0b, 0xc5, 0x71, + 0x6c, 0x6a, 0xd6, 0xa1, 0x4b, 0x9c, 0x3e, 0xe9, 0xde, 0xf6, 0xc5, 0x01, 0xab, 0xa0, 0x55, 0x5e, + 0x41, 0xc3, 0xa9, 0xed, 0xa6, 0x10, 0x28, 0xc3, 0x8a, 0x4d, 0xcd, 0x8f, 0x9a, 0xd4, 0xd4, 0xc6, + 0xe5, 0xa9, 0x1d, 0x64, 0xa2, 0x50, 0x8e, 0x35, 0x8b, 0x3d, 0xdf, 0xe5, 0xf5, 0x3e, 0xd6, 0x74, + 0x7c, 0xa8, 0x93, 0xfa, 0x84, 0x1c, 0x7b, 0x3b, 0x72, 0x37, 0x4a, 0xe2, 0xe1, 0x6d, 0x70, 0xd1, + 0x6f, 0x3a, 0x30, 0x71, 0x48, 0x52, 0xe3, 0x24, 0x2f, 0x0a, 0x92, 0x8b, 0x3b, 0x49, 0x00, 0x4a, + 0xdb, 0xc0, 0x9b, 0x60, 0xa6, 0x63, 0xe9, 0x3a, 0x8f, 0xc7, 0x0d, 0xcb, 0x33, 0x69, 0x7d, 0x92, + 0xb3, 0x40, 0x96, 0x43, 0x1b, 0x52, 0x0f, 0x4a, 0x20, 0xe1, 0x8f, 0x01, 0xe8, 0x04, 0x85, 0xc1, + 0xad, 0x83, 0x11, 0x0a, 0x20, 0x5d, 0x96, 0xa2, 0xca, 0x1c, 0x36, 0xb9, 0x28, 0x46, 0xd9, 0xfc, + 0x48, 0x01, 0x8b, 0x39, 0x89, 0x0e, 0xbf, 0x2b, 0x15, 0xc1, 0xab, 0x89, 0x22, 0x78, 0x29, 0xc7, + 0x2c, 0x56, 0x09, 0x8f, 0xc0, 0x34, 0x13, 0x24, 0x9a, 0xd9, 0xf3, 0x21, 0xe2, 0x2c, 0x6b, 0xe5, + 0x4e, 0x00, 0xc5, 0xd1, 0xd1, 0xa9, 0x7c, 0x71, 0x78, 0xb2, 0x3c, 0x2d, 0xf5, 0x21, 0x99, 0xb8, + 0xf9, 0xcb, 0x12, 0x00, 0x9b, 0xc4, 0xd6, 0xad, 0x81, 0x41, 0xcc, 0xf3, 0xd0, 0x34, 0x77, 0x25, + 0x4d, 0xf3, 0x4a, 0xfe, 0x96, 0x84, 0x4e, 0xe5, 0x8a, 0x9a, 0xf7, 0x13, 0xa2, 0xe6, 0xd5, 0x22, + 0x64, 0x4f, 0x57, 0x35, 0x9f, 0x94, 0xc1, 0x5c, 0x04, 0x8e, 0x64, 0xcd, 0x2d, 0x69, 0x47, 0x5f, + 0x49, 0xec, 0xe8, 0x62, 0x86, 0xc9, 0x73, 0xd3, 0x35, 0xcf, 0x5e, 0x5f, 0xc0, 0x0f, 0xc1, 0x0c, + 0x13, 0x32, 0x7e, 0x48, 0x70, 0x99, 0x34, 0x7e, 0x6a, 0x99, 0x14, 0x16, 0xb7, 0x2d, 0x89, 0x09, + 0x25, 0x98, 0x73, 0x64, 0xd9, 0xc4, 0xf3, 0x96, 0x65, 0xcd, 0x3f, 0x28, 0x60, 0x26, 0xda, 0xa6, + 0x73, 0x10, 0x51, 0x77, 0x64, 0x11, 0xf5, 0x52, 0x81, 0xe0, 0xcc, 0x51, 0x51, 0x9f, 0x54, 0xe2, + 0xae, 0x73, 0x19, 0xb5, 0xc2, 0x5e, 0xc1, 0x6c, 0x5d, 0xeb, 0x60, 0x57, 0xd4, 0xdb, 0x17, 0xfc, + 0xd7, 0x2f, 0xbf, 0x0d, 0x85, 0xbd, 0x92, 0xe0, 0x2a, 0x3d, 0x5f, 0xc1, 0x55, 0x7e, 0x36, 0x82, + 0xeb, 0x07, 0xa0, 0xe6, 0x06, 0x52, 0xab, 0xc2, 0x29, 0xaf, 0x16, 0x4a, 0x6c, 0xa1, 0xb2, 0x42, + 0xea, 0x50, 0x5f, 0x85, 0x74, 0x59, 0xca, 0xaa, 0xfa, 0x65, 0x2a, 0x2b, 0x96, 0xcc, 0x36, 0xf6, + 0x5c, 0xd2, 0xe5, 0x19, 0x50, 0x8b, 0x92, 0x79, 0x8f, 0xb7, 0x22, 0xd1, 0x0b, 0x0f, 0xc0, 0xa2, + 0xed, 0x58, 0x3d, 0x87, 0xb8, 0xee, 0x26, 0xc1, 0x5d, 0x5d, 0x33, 0x49, 0x30, 0x01, 0xbf, 0x26, + 0x5e, 0x1a, 0x9e, 0x2c, 0x2f, 0xee, 0x65, 0x43, 0x50, 0x9e, 0x6d, 0xf3, 0xcf, 0x15, 0x70, 0x21, + 0x79, 0x36, 0xe6, 0xc8, 0x14, 0xe5, 0x4c, 0x32, 0xe5, 0x5a, 0x2c, 0x4e, 0x7d, 0x0d, 0x17, 0xbb, + 0x2a, 0x48, 0xc5, 0xea, 0x3a, 0x98, 0x15, 0xb2, 0x24, 0xe8, 0x14, 0x42, 0x2d, 0xdc, 0x9e, 0x03, + 0xb9, 0x1b, 0x25, 0xf1, 0x4c, 0x7c, 0x44, 0x9a, 0x22, 0x20, 0xa9, 0xc8, 0xe2, 0x63, 0x3d, 0x09, + 0x40, 0x69, 0x1b, 0xb8, 0x0d, 0xe6, 0x3c, 0x33, 0x4d, 0xe5, 0x87, 0xcb, 0x25, 0x41, 0x35, 0x77, + 0x90, 0x86, 0xa0, 0x2c, 0x3b, 0xf8, 0x40, 0xd2, 0x23, 0xe3, 0xfc, 0x48, 0xb8, 0x56, 0x20, 0xac, + 0x0b, 0x0b, 0x12, 0x78, 0x0b, 0x4c, 0x3b, 0x5c, 0x73, 0x06, 0xae, 0xfa, 0xba, 0xed, 0x1b, 0xc2, + 0x6c, 0x1a, 0xc5, 0x3b, 0x91, 0x8c, 0xcd, 0x90, 0x5a, 0xb5, 0xa2, 0x52, 0xab, 0xf9, 0x27, 0x05, + 0xc0, 0x74, 0x1e, 0x8e, 0xbc, 0x09, 0x48, 0x59, 0xc4, 0x2a, 0xa6, 0x96, 0xad, 0x7f, 0xae, 0x17, + 0xd4, 0x3f, 0xd1, 0x81, 0x5a, 0x4c, 0x00, 0x89, 0x65, 0x38, 0x9f, 0x4b, 0x9d, 0xa2, 0x02, 0x28, + 0x72, 0xea, 0x19, 0x08, 0xa0, 0x18, 0xd9, 0xd3, 0x05, 0xd0, 0x3f, 0x4b, 0x60, 0x2e, 0x02, 0x17, + 0x16, 0x40, 0x19, 0x26, 0x5f, 0x5f, 0xec, 0x8c, 0xbe, 0xd8, 0x61, 0xa2, 0x24, 0x5a, 0xba, 0xff, + 0x27, 0x51, 0x12, 0x79, 0x95, 0x23, 0x4a, 0x7e, 0x57, 0x8a, 0xbb, 0xfe, 0x95, 0x17, 0x25, 0x5f, + 0xfc, 0x4e, 0xa6, 0xf9, 0x97, 0x32, 0xb8, 0x90, 0xcc, 0x43, 0xa9, 0x40, 0x2a, 0x23, 0x0b, 0xe4, + 0x1e, 0x98, 0x7f, 0xe8, 0xe9, 0xfa, 0x80, 0x2f, 0x43, 0xac, 0x4a, 0xfa, 0xa5, 0xf5, 0x9b, 0xc2, + 0x72, 0xfe, 0xfb, 0x19, 0x18, 0x94, 0x69, 0x99, 0x53, 0xec, 0xcb, 0x67, 0x2a, 0xf6, 0xa9, 0x0a, + 0x54, 0x39, 0x45, 0x05, 0xca, 0x2c, 0xdc, 0xd5, 0x33, 0x14, 0xee, 0xd3, 0x55, 0xda, 0x8c, 0x83, + 0x6b, 0xe4, 0xab, 0xff, 0xcf, 0x15, 0xb0, 0x90, 0xfd, 0xc2, 0x0d, 0x75, 0x30, 0x63, 0xe0, 0x47, + 0xf1, 0x8b, 0x8f, 0x51, 0x45, 0xc4, 0xa3, 0x9a, 0xae, 0xfa, 0x9f, 0x8c, 0xd4, 0xbb, 0x26, 0xdd, + 0x75, 0xf6, 0xa9, 0xa3, 0x99, 0x3d, 0xbf, 0xf2, 0x6e, 0x4b, 0x5c, 0x28, 0xc1, 0xdd, 0xfc, 0x4c, + 0x01, 0x8b, 0x39, 0x95, 0xef, 0x7c, 0x3d, 0x81, 0x1f, 0x80, 0x9a, 0x81, 0x1f, 0xed, 0x7b, 0x4e, + 0x2f, 0xab, 0x56, 0x17, 0x1b, 0x87, 0x67, 0xf3, 0xb6, 0x60, 0x41, 0x21, 0x5f, 0x73, 0x17, 0x5c, + 0x96, 0x26, 0xc9, 0x32, 0x87, 0x3c, 0xf4, 0x74, 0x9e, 0x44, 0x42, 0x6c, 0x5c, 0x05, 0x93, 0x36, + 0x76, 0xa8, 0x16, 0x4a, 0xd5, 0x6a, 0x7b, 0x7a, 0x78, 0xb2, 0x3c, 0xb9, 0x17, 0x34, 0xa2, 0xa8, + 0xbf, 0xf9, 0x5f, 0x05, 0x54, 0xf7, 0x3b, 0x58, 0x27, 0xe7, 0x50, 0xed, 0x37, 0xa5, 0x6a, 0x9f, + 0x7f, 0x93, 0xce, 0xfd, 0xc9, 0x2d, 0xf4, 0x5b, 0x89, 0x42, 0xff, 0xf2, 0x08, 0x9e, 0xa7, 0xd7, + 0xf8, 0x77, 0xc0, 0x64, 0x38, 0xdc, 0xe9, 0x0e, 0xa0, 0xe6, 0x6f, 0x4b, 0x60, 0x2a, 0x36, 0xc4, + 0x29, 0x8f, 0xaf, 0x07, 0xd2, 0xb1, 0xcf, 0x12, 0x73, 0xad, 0xc8, 0x44, 0xd4, 0xe0, 0x88, 0x7f, + 0xd7, 0xa4, 0x4e, 0xfc, 0x05, 0x2f, 0x7d, 0xf2, 0x7f, 0x07, 0xcc, 0x50, 0xec, 0xf4, 0x08, 0x0d, + 0xfa, 0xf8, 0x82, 0x4d, 0x46, 0xb7, 0x13, 0xf7, 0xa4, 0x5e, 0x94, 0x40, 0x2f, 0xdd, 0x02, 0xd3, + 0xd2, 0x60, 0xf0, 0x02, 0x28, 0x1f, 0x93, 0x81, 0x2f, 0x7b, 0x10, 0xfb, 0x09, 0xe7, 0x41, 0xb5, + 0x8f, 0x75, 0xcf, 0x8f, 0xf3, 0x49, 0xe4, 0x3f, 0xdc, 0x2c, 0xbd, 0xad, 0x34, 0x7f, 0xc5, 0x16, + 0x27, 0x0a, 0xce, 0x73, 0x88, 0xae, 0xf7, 0xa4, 0xe8, 0xca, 0xff, 0xa8, 0x17, 0x4f, 0x99, 0xbc, + 0x18, 0x43, 0x89, 0x18, 0x7b, 0xad, 0x10, 0xdb, 0xd3, 0x23, 0xed, 0x5f, 0x25, 0x30, 0x1f, 0x43, + 0x47, 0x72, 0xf2, 0xdb, 0x92, 0x9c, 0x5c, 0x49, 0xc8, 0xc9, 0x7a, 0x96, 0xcd, 0xd7, 0x7a, 0x72, + 0xb4, 0x9e, 0xfc, 0xa3, 0x02, 0x66, 0x63, 0x6b, 0x77, 0x0e, 0x82, 0xf2, 0xae, 0x2c, 0x28, 0x5f, + 0x2e, 0x12, 0x34, 0x39, 0x8a, 0xf2, 0xaf, 0x55, 0xc9, 0xf9, 0xaf, 0xbc, 0xa4, 0xfc, 0x29, 0x98, + 0xef, 0x5b, 0xba, 0x67, 0x90, 0x0d, 0x1d, 0x6b, 0x46, 0x00, 0x60, 0xaa, 0xa9, 0x9c, 0x7c, 0x97, + 0x0b, 0xe9, 0x89, 0xe3, 0x6a, 0x2e, 0x25, 0x26, 0xbd, 0x1f, 0x59, 0x46, 0xba, 0xef, 0x7e, 0x06, + 0x1d, 0xca, 0x1c, 0x04, 0xbe, 0x09, 0xa6, 0x98, 0x7e, 0xd3, 0x3a, 0x64, 0x07, 0x1b, 0x41, 0x60, + 0x85, 0x9f, 0xb0, 0xf6, 0xa3, 0x2e, 0x14, 0xc7, 0xc1, 0x23, 0x30, 0x67, 0x5b, 0xdd, 0x6d, 0x6c, + 0xe2, 0x1e, 0x61, 0x32, 0x63, 0xcf, 0xd2, 0xb5, 0xce, 0x80, 0x5f, 0x7e, 0x4d, 0xb6, 0xdf, 0x0a, + 0x6e, 0x45, 0xf6, 0xd2, 0x10, 0xf6, 0x92, 0x98, 0xd1, 0xcc, 0x93, 0x3a, 0x8b, 0x12, 0x3a, 0xa9, + 0xcf, 0xae, 0xfe, 0x1d, 0xf1, 0x5a, 0x91, 0x08, 0x3b, 0xe3, 0x87, 0xd7, 0xbc, 0xbb, 0xbd, 0xda, + 0x99, 0xbe, 0x9a, 0xfe, 0xbb, 0x02, 0x2e, 0xa6, 0x8e, 0xca, 0x2f, 0xf1, 0x76, 0x2d, 0x25, 0xcf, + 0xcb, 0xa7, 0x90, 0xe7, 0xeb, 0x60, 0x56, 0x7c, 0xb0, 0x4d, 0xa8, 0xfb, 0xf0, 0xfd, 0x67, 0x43, + 0xee, 0x46, 0x49, 0x7c, 0xd6, 0xed, 0x5e, 0xf5, 0x94, 0xb7, 0x7b, 0x71, 0x2f, 0xc4, 0x1f, 0x90, + 0xfc, 0xd0, 0x4b, 0x7b, 0x21, 0xfe, 0x87, 0x94, 0xc4, 0x33, 0x85, 0xe0, 0xb3, 0x86, 0x0c, 0x13, + 0xb2, 0x42, 0x38, 0x90, 0x7a, 0x51, 0x02, 0xfd, 0x85, 0x3e, 0x4a, 0xe2, 0x8c, 0x8f, 0x92, 0xab, + 0x45, 0xe2, 0xb9, 0xf8, 0xbb, 0xc9, 0xdf, 0x14, 0xf0, 0x62, 0x6e, 0x22, 0xc0, 0x75, 0xa9, 0xec, + 0xae, 0x26, 0xca, 0xee, 0xb7, 0x72, 0x0d, 0x63, 0xb5, 0xd7, 0xc9, 0xbe, 0x9a, 0x7b, 0xa7, 0xd8, + 0xd5, 0x5c, 0x86, 0x76, 0x1f, 0x7d, 0x47, 0xd7, 0x5e, 0x7d, 0xfc, 0xa4, 0x31, 0xf6, 0xf1, 0x93, + 0xc6, 0xd8, 0xa7, 0x4f, 0x1a, 0x63, 0x3f, 0x1b, 0x36, 0x94, 0xc7, 0xc3, 0x86, 0xf2, 0xf1, 0xb0, + 0xa1, 0x7c, 0x3a, 0x6c, 0x28, 0x7f, 0x1f, 0x36, 0x94, 0x5f, 0x7f, 0xd6, 0x18, 0xfb, 0x60, 0x42, + 0x8c, 0xf8, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x85, 0x43, 0x0a, 0xec, 0x28, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/generated.proto index 4a8b28c15..cc3656d28 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,7 +22,6 @@ syntax = 'proto2'; package k8s.io.api.apps.v1beta2; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; @@ -509,9 +508,9 @@ message RollingUpdateDeployment { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -523,10 +522,10 @@ message RollingUpdateDeployment { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is atmost 130% of desired pods. // +optional optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/types.go index c8be2aaca..e5525222a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/types.go @@ -359,8 +359,8 @@ type DeploymentSpec struct { const ( // DefaultDeploymentUniqueLabelKey is the default key of the selector that is added - // to existing RCs (and label key that is added to its pods) to prevent the existing RCs - // to select new pods (and old pods being select by new RC). + // to existing ReplicaSets (and label key that is added to its pods) to prevent the existing ReplicaSets + // to select new pods (and old pods being select by new ReplicaSet). DefaultDeploymentUniqueLabelKey string = "pod-template-hash" ) @@ -385,7 +385,7 @@ const ( // Kill all existing pods before creating new ones. RecreateDeploymentStrategyType DeploymentStrategyType = "Recreate" - // Replace the old RCs by new one using rolling update i.e gradually scale down the old RCs and scale up the new one. + // Replace the old ReplicaSets by new one using rolling update i.e gradually scale down the old ReplicaSets and scale up the new one. RollingUpdateDeploymentStrategyType DeploymentStrategyType = "RollingUpdate" ) @@ -396,9 +396,9 @@ type RollingUpdateDeployment struct { // Absolute number is calculated from percentage by rounding down. // This can not be 0 if MaxSurge is 0. // Defaults to 25%. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring + // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods + // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet + // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring // that the total number of pods available at all times during the update is at // least 70% of desired pods. // +optional @@ -410,10 +410,10 @@ type RollingUpdateDeployment struct { // This can not be 0 if MaxUnavailable is 0. // Absolute number is calculated from percentage by rounding up. // Defaults to 25%. - // Example: when this is set to 30%, the new RC can be scaled up immediately when + // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when // the rolling update starts, such that the total number of old and new pods do not exceed // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running + // new ReplicaSet can be scaled up further, ensuring that total number of pods running // at any time during the update is atmost 130% of desired pods. // +optional MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/types_swagger_doc_generated.go index e2f133b51..627df3ab7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta2 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_ControllerRevision = map[string]string{ "": "DEPRECATED - This group version of ControllerRevision is deprecated by apps/v1/ControllerRevision. See the release notes for more information. ControllerRevision implements an immutable snapshot of state data. Clients are responsible for serializing and deserializing the objects that contain their internal state. Once a ControllerRevision has been successfully created, it can not be updated. The API Server will fail validation of all requests that attempt to mutate the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, it may be subject to name and representation changes in future releases, and clients should not depend on its stability. It is primarily for internal use by controllers.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -271,8 +271,8 @@ func (RollingUpdateDaemonSet) SwaggerDoc() map[string]string { var map_RollingUpdateDeployment = map[string]string{ "": "Spec to control the desired behavior of rolling update.", - "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", - "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new RC can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", + "maxUnavailable": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "maxSurge": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is atmost 130% of desired pods.", } func (RollingUpdateDeployment) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/zz_generated.deepcopy.go index 3db38527d..a3bd8afdc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/apps/v1beta2/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/generated.pb.go index d090ce579..2ce2e2d78 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2087,62 +2087,61 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 905 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xcf, 0x6f, 0x1b, 0x45, - 0x14, 0xf6, 0xfa, 0x47, 0x64, 0x8f, 0x9b, 0x90, 0x4c, 0xa9, 0x64, 0x05, 0xb0, 0x8d, 0x91, 0x90, - 0x05, 0x74, 0xb7, 0x36, 0xa8, 0x54, 0x45, 0x42, 0xca, 0x12, 0x0b, 0x2c, 0x04, 0xad, 0xa6, 0x4d, - 0x40, 0x9c, 0x18, 0xdb, 0x2f, 0xce, 0xe0, 0xee, 0xec, 0x32, 0x3b, 0x6b, 0xea, 0x5b, 0xff, 0x04, - 0x8e, 0x20, 0x71, 0xe0, 0x8f, 0x40, 0xe2, 0xc8, 0x35, 0xc7, 0x8a, 0x53, 0x0f, 0xc8, 0x22, 0xcb, - 0xbf, 0xc0, 0x89, 0x13, 0x9a, 0xd9, 0x89, 0xd7, 0x3f, 0x12, 0xc7, 0xa7, 0xde, 0x3c, 0xef, 0x7d, - 0xef, 0x9b, 0xf7, 0xbe, 0xf9, 0xfc, 0x16, 0x75, 0x46, 0xf7, 0x42, 0x9b, 0xf9, 0xce, 0x28, 0xea, - 0x81, 0xe0, 0x20, 0x21, 0x74, 0xc6, 0xc0, 0x07, 0xbe, 0x70, 0x4c, 0x82, 0x06, 0xcc, 0xa1, 0x91, - 0x3c, 0x05, 0x2e, 0x59, 0x9f, 0x4a, 0xe6, 0x73, 0x67, 0xdc, 0x72, 0x86, 0xc0, 0x41, 0x50, 0x09, - 0x03, 0x3b, 0x10, 0xbe, 0xf4, 0xf1, 0xeb, 0x09, 0xda, 0xa6, 0x01, 0xb3, 0x17, 0xd1, 0xf6, 0xb8, - 0xb5, 0x7f, 0x7b, 0xc8, 0xe4, 0x69, 0xd4, 0xb3, 0xfb, 0xbe, 0xe7, 0x0c, 0xfd, 0xa1, 0xef, 0xe8, - 0xa2, 0x5e, 0x74, 0xa2, 0x4f, 0xfa, 0xa0, 0x7f, 0x25, 0x64, 0xfb, 0x1f, 0xa4, 0x57, 0x7b, 0xb4, - 0x7f, 0xca, 0x38, 0x88, 0x89, 0x13, 0x8c, 0x86, 0x2a, 0x10, 0x3a, 0x1e, 0x48, 0x7a, 0x49, 0x0b, - 0xfb, 0xce, 0x55, 0x55, 0x22, 0xe2, 0x92, 0x79, 0xb0, 0x52, 0x70, 0xf7, 0xba, 0x82, 0xb0, 0x7f, - 0x0a, 0x1e, 0x5d, 0xa9, 0x7b, 0xff, 0xaa, 0xba, 0x48, 0xb2, 0x27, 0x0e, 0xe3, 0x32, 0x94, 0x62, - 0xb9, 0xa8, 0xf1, 0xa7, 0x85, 0x5e, 0x75, 0xfd, 0x88, 0x0f, 0x1e, 0xf4, 0xbe, 0x83, 0xbe, 0x24, - 0x70, 0x02, 0x02, 0x78, 0x1f, 0x70, 0x1d, 0xe5, 0x47, 0x8c, 0x0f, 0x2a, 0x56, 0xdd, 0x6a, 0x96, - 0xdc, 0x1b, 0x67, 0xd3, 0x5a, 0x26, 0x9e, 0xd6, 0xf2, 0x9f, 0x33, 0x3e, 0x20, 0x3a, 0x83, 0xdb, - 0x08, 0xd1, 0x87, 0xdd, 0x63, 0x10, 0x21, 0xf3, 0x79, 0x25, 0xab, 0x71, 0xd8, 0xe0, 0xd0, 0xc1, - 0x2c, 0x43, 0xe6, 0x50, 0x8a, 0x95, 0x53, 0x0f, 0x2a, 0xb9, 0x45, 0xd6, 0x2f, 0xa9, 0x07, 0x44, - 0x67, 0xb0, 0x8b, 0x72, 0x51, 0xf7, 0xb0, 0x92, 0xd7, 0x80, 0x3b, 0x06, 0x90, 0x3b, 0xea, 0x1e, - 0xfe, 0x37, 0xad, 0xbd, 0x79, 0xd5, 0x84, 0x72, 0x12, 0x40, 0x68, 0x1f, 0x75, 0x0f, 0x89, 0x2a, - 0x6e, 0x7c, 0x88, 0x50, 0xe7, 0xa9, 0x14, 0xf4, 0x98, 0x3e, 0x89, 0x00, 0xd7, 0x50, 0x81, 0x49, - 0xf0, 0xc2, 0x8a, 0x55, 0xcf, 0x35, 0x4b, 0x6e, 0x29, 0x9e, 0xd6, 0x0a, 0x5d, 0x15, 0x20, 0x49, - 0xfc, 0x7e, 0xf1, 0xa7, 0x5f, 0x6b, 0x99, 0x67, 0x7f, 0xd5, 0x33, 0x8d, 0x5f, 0xb2, 0xe8, 0xc6, - 0x63, 0x7f, 0x04, 0x9c, 0xc0, 0xf7, 0x11, 0x84, 0x12, 0x7f, 0x8b, 0x8a, 0xea, 0x5d, 0x07, 0x54, - 0x52, 0xad, 0x44, 0xb9, 0x7d, 0xc7, 0x4e, 0x2d, 0x35, 0x6b, 0xc2, 0x0e, 0x46, 0x43, 0x15, 0x08, - 0x6d, 0x85, 0xb6, 0xc7, 0x2d, 0x3b, 0x91, 0xf3, 0x0b, 0x90, 0x34, 0xd5, 0x24, 0x8d, 0x91, 0x19, - 0x2b, 0x7e, 0x88, 0xf2, 0x61, 0x00, 0x7d, 0xad, 0x5f, 0xb9, 0x6d, 0xdb, 0xeb, 0x0c, 0x6b, 0xcf, - 0xf7, 0xf6, 0x28, 0x80, 0x7e, 0xaa, 0xa0, 0x3a, 0x11, 0xcd, 0x84, 0xbf, 0x46, 0x5b, 0xa1, 0xa4, - 0x32, 0x0a, 0xb5, 0xca, 0x8b, 0x1d, 0x5f, 0xc7, 0xa9, 0xeb, 0xdc, 0x1d, 0xc3, 0xba, 0x95, 0x9c, - 0x89, 0xe1, 0x6b, 0xfc, 0x6b, 0xa1, 0xdd, 0xe5, 0x16, 0xf0, 0xbb, 0xa8, 0x44, 0xa3, 0x01, 0x53, - 0xa6, 0xb9, 0x90, 0x78, 0x3b, 0x9e, 0xd6, 0x4a, 0x07, 0x17, 0x41, 0x92, 0xe6, 0x31, 0x47, 0x3b, - 0xbd, 0x05, 0xb7, 0x99, 0x1e, 0xdb, 0xeb, 0x7b, 0xbc, 0xcc, 0xa1, 0x2e, 0x8e, 0xa7, 0xb5, 0x9d, - 0xc5, 0x0c, 0x59, 0x62, 0xc7, 0x9f, 0xa0, 0x3d, 0x78, 0x1a, 0x30, 0xa1, 0x99, 0x1e, 0x41, 0xdf, - 0xe7, 0x83, 0x50, 0x7b, 0x2b, 0xe7, 0xde, 0x8a, 0xa7, 0xb5, 0xbd, 0xce, 0x72, 0x92, 0xac, 0xe2, - 0x1b, 0xbf, 0x59, 0x08, 0xaf, 0xaa, 0x84, 0xdf, 0x42, 0x05, 0xa9, 0xa2, 0xe6, 0x2f, 0xb2, 0x6d, - 0x44, 0x2b, 0x24, 0xd0, 0x24, 0x87, 0x27, 0xe8, 0x66, 0x4a, 0xf8, 0x98, 0x79, 0x10, 0x4a, 0xea, - 0x05, 0xe6, 0xb5, 0xdf, 0xd9, 0xcc, 0x4b, 0xaa, 0xcc, 0x7d, 0xcd, 0xd0, 0xdf, 0xec, 0xac, 0xd2, - 0x91, 0xcb, 0xee, 0x68, 0xfc, 0x9c, 0x45, 0x65, 0xd3, 0xf6, 0x98, 0xc1, 0x0f, 0x2f, 0xc1, 0xcb, - 0x0f, 0x16, 0xbc, 0x7c, 0x7b, 0x23, 0xdf, 0xa9, 0xd6, 0xae, 0xb4, 0xf2, 0x57, 0x4b, 0x56, 0x76, - 0x36, 0xa7, 0x5c, 0xef, 0xe4, 0xbb, 0xe8, 0x95, 0xa5, 0xfb, 0x37, 0x7a, 0xce, 0xc6, 0x1f, 0x16, - 0xda, 0x5b, 0xb9, 0x05, 0x7f, 0x84, 0xb6, 0xe7, 0x9a, 0x81, 0x64, 0x69, 0x16, 0xdd, 0x5b, 0x86, - 0x62, 0xfb, 0x60, 0x3e, 0x49, 0x16, 0xb1, 0xf8, 0x33, 0x94, 0x8f, 0x42, 0x10, 0x46, 0xb4, 0xb7, - 0xd7, 0x4f, 0x78, 0x14, 0x82, 0xe8, 0xf2, 0x13, 0x3f, 0x55, 0x4b, 0x45, 0x88, 0x66, 0x50, 0x13, - 0x80, 0x10, 0xbe, 0x30, 0xdb, 0x75, 0x36, 0x41, 0x47, 0x05, 0x49, 0x92, 0x6b, 0xfc, 0x9e, 0x45, - 0xc5, 0x0b, 0x16, 0xfc, 0x1e, 0x2a, 0xaa, 0x4a, 0xbd, 0x92, 0x93, 0xb1, 0x77, 0x4d, 0x91, 0xc6, - 0xa8, 0x38, 0x99, 0x21, 0xf0, 0x1b, 0x28, 0x17, 0xb1, 0x81, 0xd9, 0xf4, 0xe5, 0xb9, 0xd5, 0x4c, - 0x54, 0x1c, 0x37, 0xd0, 0xd6, 0x50, 0xf8, 0x51, 0xa0, 0x1e, 0x4b, 0x6d, 0x01, 0xa4, 0x74, 0xff, - 0x54, 0x47, 0x88, 0xc9, 0xe0, 0x63, 0x54, 0x00, 0xb5, 0x99, 0x2b, 0xf9, 0x7a, 0xae, 0x59, 0x6e, - 0xb7, 0x36, 0x9b, 0xd6, 0xd6, 0xdb, 0xbc, 0xc3, 0xa5, 0x98, 0xcc, 0x4d, 0xa5, 0x62, 0x24, 0xa1, - 0xdb, 0xef, 0x99, 0x8d, 0xaf, 0x31, 0x78, 0x17, 0xe5, 0x46, 0x30, 0x49, 0x26, 0x22, 0xea, 0x27, - 0xfe, 0x18, 0x15, 0xc6, 0xea, 0x63, 0x60, 0x54, 0x6e, 0xae, 0xbf, 0x37, 0xfd, 0x78, 0x90, 0xa4, - 0xec, 0x7e, 0xf6, 0x9e, 0xe5, 0x36, 0xcf, 0xce, 0xab, 0x99, 0xe7, 0xe7, 0xd5, 0xcc, 0x8b, 0xf3, - 0x6a, 0xe6, 0x59, 0x5c, 0xb5, 0xce, 0xe2, 0xaa, 0xf5, 0x3c, 0xae, 0x5a, 0x2f, 0xe2, 0xaa, 0xf5, - 0x77, 0x5c, 0xb5, 0x7e, 0xfc, 0xa7, 0x9a, 0xf9, 0x26, 0x3b, 0x6e, 0xfd, 0x1f, 0x00, 0x00, 0xff, - 0xff, 0x5f, 0x39, 0x60, 0xb1, 0xbd, 0x08, 0x00, 0x00, + // 892 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xcf, 0x8f, 0xdb, 0x44, + 0x14, 0x8e, 0xf3, 0x63, 0xb5, 0x99, 0x74, 0x97, 0xdd, 0x29, 0x95, 0xa2, 0x05, 0xec, 0x60, 0x24, + 0x14, 0x01, 0xb5, 0x9b, 0x08, 0x95, 0xaa, 0x48, 0x48, 0x6b, 0x36, 0x82, 0x08, 0x41, 0xab, 0x69, + 0x77, 0x41, 0x9c, 0x98, 0xd8, 0x6f, 0xb3, 0x26, 0x78, 0x6c, 0xec, 0x71, 0x68, 0x6e, 0xfd, 0x13, + 0x38, 0x82, 0xc4, 0x81, 0x3f, 0x02, 0x89, 0x23, 0xd7, 0x3d, 0x56, 0x9c, 0x7a, 0x40, 0x11, 0x6b, + 0xfe, 0x05, 0x4e, 0x9c, 0xd0, 0x8c, 0x67, 0xe3, 0xfc, 0xd8, 0x4d, 0x73, 0xea, 0x2d, 0xf3, 0xde, + 0xf7, 0xbe, 0x79, 0xef, 0x9b, 0x2f, 0xcf, 0xa8, 0x37, 0xba, 0x97, 0x58, 0x7e, 0x68, 0x8f, 0xd2, + 0x01, 0xc4, 0x0c, 0x38, 0x24, 0xf6, 0x18, 0x98, 0x17, 0xc6, 0xb6, 0x4a, 0xd0, 0xc8, 0xb7, 0x69, + 0xca, 0xcf, 0x80, 0x71, 0xdf, 0xa5, 0xdc, 0x0f, 0x99, 0x3d, 0xee, 0xd8, 0x43, 0x60, 0x10, 0x53, + 0x0e, 0x9e, 0x15, 0xc5, 0x21, 0x0f, 0xf1, 0xeb, 0x39, 0xda, 0xa2, 0x91, 0x6f, 0x2d, 0xa2, 0xad, + 0x71, 0xe7, 0xe0, 0xf6, 0xd0, 0xe7, 0x67, 0xe9, 0xc0, 0x72, 0xc3, 0xc0, 0x1e, 0x86, 0xc3, 0xd0, + 0x96, 0x45, 0x83, 0xf4, 0x54, 0x9e, 0xe4, 0x41, 0xfe, 0xca, 0xc9, 0x0e, 0xde, 0x2f, 0xae, 0x0e, + 0xa8, 0x7b, 0xe6, 0x33, 0x88, 0x27, 0x76, 0x34, 0x1a, 0x8a, 0x40, 0x62, 0x07, 0xc0, 0xe9, 0x15, + 0x2d, 0x1c, 0xd8, 0xd7, 0x55, 0xc5, 0x29, 0xe3, 0x7e, 0x00, 0x2b, 0x05, 0x77, 0x5f, 0x54, 0x90, + 0xb8, 0x67, 0x10, 0xd0, 0xe5, 0x3a, 0xf3, 0x4f, 0x0d, 0xbd, 0xea, 0x84, 0x29, 0xf3, 0x1e, 0x0c, + 0xbe, 0x05, 0x97, 0x13, 0x38, 0x85, 0x18, 0x98, 0x0b, 0xb8, 0x85, 0xaa, 0x23, 0x9f, 0x79, 0x4d, + 0xad, 0xa5, 0xb5, 0xeb, 0xce, 0x8d, 0xf3, 0xa9, 0x51, 0xca, 0xa6, 0x46, 0xf5, 0x33, 0x9f, 0x79, + 0x44, 0x66, 0x70, 0x17, 0x21, 0xfa, 0xb0, 0x7f, 0x02, 0x71, 0xe2, 0x87, 0xac, 0x59, 0x96, 0x38, + 0xac, 0x70, 0xe8, 0x70, 0x96, 0x21, 0x73, 0x28, 0xc1, 0xca, 0x68, 0x00, 0xcd, 0xca, 0x22, 0xeb, + 0x17, 0x34, 0x00, 0x22, 0x33, 0xd8, 0x41, 0x95, 0xb4, 0x7f, 0xd4, 0xac, 0x4a, 0xc0, 0x1d, 0x05, + 0xa8, 0x1c, 0xf7, 0x8f, 0xfe, 0x9b, 0x1a, 0x6f, 0x5e, 0x37, 0x24, 0x9f, 0x44, 0x90, 0x58, 0xc7, + 0xfd, 0x23, 0x22, 0x8a, 0xcd, 0x0f, 0x10, 0xea, 0x3d, 0xe1, 0x31, 0x3d, 0xa1, 0xdf, 0xa5, 0x80, + 0x0d, 0x54, 0xf3, 0x39, 0x04, 0x49, 0x53, 0x6b, 0x55, 0xda, 0x75, 0xa7, 0x9e, 0x4d, 0x8d, 0x5a, + 0x5f, 0x04, 0x48, 0x1e, 0xbf, 0xbf, 0xfd, 0xd3, 0xaf, 0x46, 0xe9, 0xe9, 0x5f, 0xad, 0x92, 0xf9, + 0x4b, 0x19, 0xdd, 0x78, 0x1c, 0x8e, 0x80, 0x11, 0xf8, 0x3e, 0x85, 0x84, 0xe3, 0x6f, 0xd0, 0xb6, + 0x78, 0x22, 0x8f, 0x72, 0x2a, 0x95, 0x68, 0x74, 0xef, 0x58, 0x85, 0x3b, 0x66, 0x4d, 0x58, 0xd1, + 0x68, 0x28, 0x02, 0x89, 0x25, 0xd0, 0xd6, 0xb8, 0x63, 0xe5, 0x72, 0x7e, 0x0e, 0x9c, 0x16, 0x9a, + 0x14, 0x31, 0x32, 0x63, 0xc5, 0x0f, 0x51, 0x35, 0x89, 0xc0, 0x95, 0xfa, 0x35, 0xba, 0x96, 0xb5, + 0xce, 0x7b, 0xd6, 0x7c, 0x6f, 0x8f, 0x22, 0x70, 0x0b, 0x05, 0xc5, 0x89, 0x48, 0x26, 0xfc, 0x15, + 0xda, 0x4a, 0x38, 0xe5, 0x69, 0x22, 0x55, 0x5e, 0xec, 0xf8, 0x45, 0x9c, 0xb2, 0xce, 0xd9, 0x55, + 0xac, 0x5b, 0xf9, 0x99, 0x28, 0x3e, 0xf3, 0x5f, 0x0d, 0xed, 0x2d, 0xb7, 0x80, 0xdf, 0x45, 0x75, + 0x9a, 0x7a, 0xbe, 0x30, 0xcd, 0xa5, 0xc4, 0x3b, 0xd9, 0xd4, 0xa8, 0x1f, 0x5e, 0x06, 0x49, 0x91, + 0xc7, 0x0c, 0xed, 0x0e, 0x16, 0xdc, 0xa6, 0x7a, 0xec, 0xae, 0xef, 0xf1, 0x2a, 0x87, 0x3a, 0x38, + 0x9b, 0x1a, 0xbb, 0x8b, 0x19, 0xb2, 0xc4, 0x8e, 0x3f, 0x46, 0xfb, 0xf0, 0x24, 0xf2, 0x63, 0xc9, + 0xf4, 0x08, 0xdc, 0x90, 0x79, 0x89, 0xf4, 0x56, 0xc5, 0xb9, 0x95, 0x4d, 0x8d, 0xfd, 0xde, 0x72, + 0x92, 0xac, 0xe2, 0xcd, 0xdf, 0x34, 0x84, 0x57, 0x55, 0xc2, 0x6f, 0xa1, 0x1a, 0x17, 0x51, 0xf5, + 0x17, 0xd9, 0x51, 0xa2, 0xd5, 0x72, 0x68, 0x9e, 0xc3, 0x13, 0x74, 0xb3, 0x20, 0x7c, 0xec, 0x07, + 0x90, 0x70, 0x1a, 0x44, 0xea, 0xb5, 0xdf, 0xd9, 0xcc, 0x4b, 0xa2, 0xcc, 0x79, 0x4d, 0xd1, 0xdf, + 0xec, 0xad, 0xd2, 0x91, 0xab, 0xee, 0x30, 0x7f, 0x2e, 0xa3, 0x86, 0x6a, 0x7b, 0xec, 0xc3, 0x0f, + 0x2f, 0xc1, 0xcb, 0x0f, 0x16, 0xbc, 0x7c, 0x7b, 0x23, 0xdf, 0x89, 0xd6, 0xae, 0xb5, 0xf2, 0x97, + 0x4b, 0x56, 0xb6, 0x37, 0xa7, 0x5c, 0xef, 0xe4, 0xbb, 0xe8, 0x95, 0xa5, 0xfb, 0x37, 0x7a, 0x4e, + 0xf3, 0x0f, 0x0d, 0xed, 0xaf, 0xdc, 0x82, 0x3f, 0x44, 0x3b, 0x73, 0xcd, 0x40, 0xbe, 0x34, 0xb7, + 0x9d, 0x5b, 0x8a, 0x62, 0xe7, 0x70, 0x3e, 0x49, 0x16, 0xb1, 0xf8, 0x53, 0x54, 0x4d, 0x13, 0x88, + 0x95, 0x68, 0x6f, 0xaf, 0x9f, 0xf0, 0x38, 0x81, 0xb8, 0xcf, 0x4e, 0xc3, 0x42, 0x2d, 0x11, 0x21, + 0x92, 0x41, 0x4c, 0x00, 0x71, 0x1c, 0xc6, 0x6a, 0xbb, 0xce, 0x26, 0xe8, 0x89, 0x20, 0xc9, 0x73, + 0xe6, 0xef, 0x65, 0xb4, 0x7d, 0xc9, 0x82, 0xdf, 0x43, 0xdb, 0xa2, 0x52, 0xae, 0xe4, 0x7c, 0xec, + 0x3d, 0x55, 0x24, 0x31, 0x22, 0x4e, 0x66, 0x08, 0xfc, 0x06, 0xaa, 0xa4, 0xbe, 0xa7, 0x36, 0x7d, + 0x63, 0x6e, 0x35, 0x13, 0x11, 0xc7, 0x26, 0xda, 0x1a, 0xc6, 0x61, 0x1a, 0x89, 0xc7, 0x12, 0x5b, + 0x00, 0x09, 0xdd, 0x3f, 0x91, 0x11, 0xa2, 0x32, 0xf8, 0x04, 0xd5, 0x40, 0x6c, 0xe6, 0x66, 0xb5, + 0x55, 0x69, 0x37, 0xba, 0x9d, 0xcd, 0xa6, 0xb5, 0xe4, 0x36, 0xef, 0x31, 0x1e, 0x4f, 0xe6, 0xa6, + 0x12, 0x31, 0x92, 0xd3, 0x1d, 0x0c, 0xd4, 0xc6, 0x97, 0x18, 0xbc, 0x87, 0x2a, 0x23, 0x98, 0xe4, + 0x13, 0x11, 0xf1, 0x13, 0x7f, 0x84, 0x6a, 0x63, 0xf1, 0x31, 0x50, 0x2a, 0xb7, 0xd7, 0xdf, 0x5b, + 0x7c, 0x3c, 0x48, 0x5e, 0x76, 0xbf, 0x7c, 0x4f, 0x73, 0xda, 0xe7, 0x17, 0x7a, 0xe9, 0xd9, 0x85, + 0x5e, 0x7a, 0x7e, 0xa1, 0x97, 0x9e, 0x66, 0xba, 0x76, 0x9e, 0xe9, 0xda, 0xb3, 0x4c, 0xd7, 0x9e, + 0x67, 0xba, 0xf6, 0x77, 0xa6, 0x6b, 0x3f, 0xfe, 0xa3, 0x97, 0xbe, 0x2e, 0x8f, 0x3b, 0xff, 0x07, + 0x00, 0x00, 0xff, 0xff, 0x5e, 0x8d, 0x94, 0x78, 0x88, 0x08, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/generated.proto index 1fd432a70..10c792171 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.authentication.v1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/types_swagger_doc_generated.go index 68ecea8ea..6632a5dd5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_BoundObjectReference = map[string]string{ "": "BoundObjectReference is a reference to an object that a token is bound to.", "kind": "Kind of the referent. Valid kinds are 'Pod' and 'Secret'.", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/zz_generated.deepcopy.go index ad0df8ff4..4b9b94105 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/generated.pb.go index 86e362b87..8503d212b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1257,46 +1257,45 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 650 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x4d, 0x4f, 0x14, 0x4d, - 0x10, 0xc7, 0x67, 0xf6, 0x85, 0x67, 0xb7, 0xf7, 0x41, 0xb1, 0x13, 0x93, 0xcd, 0x26, 0xce, 0xae, - 0xeb, 0x85, 0x44, 0xe9, 0x11, 0x24, 0x48, 0xf0, 0xe4, 0x28, 0x31, 0x98, 0x10, 0x93, 0x16, 0x3c, - 0xa8, 0x07, 0x7b, 0x67, 0x8b, 0xd9, 0x76, 0x99, 0x97, 0xf4, 0xf4, 0xac, 0x72, 0xe3, 0x23, 0x78, - 0xf4, 0x68, 0xe2, 0x27, 0x31, 0xf1, 0xc0, 0x91, 0x23, 0x07, 0x43, 0x64, 0xfc, 0x22, 0xa6, 0x7b, - 0x5a, 0x76, 0x61, 0x43, 0x80, 0xdb, 0xf4, 0xbf, 0xea, 0xff, 0x9b, 0xaa, 0xea, 0x2e, 0xf4, 0x72, - 0xb8, 0x9a, 0x12, 0x1e, 0xbb, 0xc3, 0xac, 0x07, 0x22, 0x02, 0x09, 0xa9, 0x3b, 0x82, 0xa8, 0x1f, - 0x0b, 0xd7, 0x04, 0x58, 0xc2, 0x5d, 0x96, 0xc9, 0x01, 0x44, 0x92, 0xfb, 0x4c, 0xf2, 0x38, 0x72, - 0x47, 0x8b, 0x3d, 0x90, 0x6c, 0xd1, 0x0d, 0x20, 0x02, 0xc1, 0x24, 0xf4, 0x49, 0x22, 0x62, 0x19, - 0xe3, 0xbb, 0x85, 0x85, 0xb0, 0x84, 0x93, 0xb3, 0x16, 0x62, 0x2c, 0xad, 0x85, 0x80, 0xcb, 0x41, - 0xd6, 0x23, 0x7e, 0x1c, 0xba, 0x41, 0x1c, 0xc4, 0xae, 0x76, 0xf6, 0xb2, 0x1d, 0x7d, 0xd2, 0x07, - 0xfd, 0x55, 0x10, 0x5b, 0xcb, 0xe3, 0x22, 0x42, 0xe6, 0x0f, 0x78, 0x04, 0x62, 0xcf, 0x4d, 0x86, - 0x81, 0x12, 0x52, 0x37, 0x04, 0xc9, 0xdc, 0xd1, 0x54, 0x1d, 0x2d, 0xf7, 0x22, 0x97, 0xc8, 0x22, - 0xc9, 0x43, 0x98, 0x32, 0xac, 0x5c, 0x66, 0x48, 0xfd, 0x01, 0x84, 0x6c, 0xca, 0xf7, 0xe8, 0x22, - 0x5f, 0x26, 0xf9, 0xae, 0xcb, 0x23, 0x99, 0x4a, 0x71, 0xde, 0xd4, 0x7d, 0x8c, 0xd0, 0xfa, 0x67, - 0x29, 0xd8, 0x1b, 0xb6, 0x9b, 0x01, 0x6e, 0xa3, 0x2a, 0x97, 0x10, 0xa6, 0x4d, 0xbb, 0x53, 0x9e, - 0xaf, 0x7b, 0xf5, 0xfc, 0xb8, 0x5d, 0xdd, 0x50, 0x02, 0x2d, 0xf4, 0xb5, 0xda, 0xd7, 0x6f, 0x6d, - 0x6b, 0xff, 0x57, 0xc7, 0xea, 0x7e, 0x2f, 0xa1, 0xc6, 0x56, 0x3c, 0x84, 0x88, 0xc2, 0x88, 0xc3, - 0x27, 0xfc, 0x01, 0xd5, 0xd4, 0x04, 0xfa, 0x4c, 0xb2, 0xa6, 0xdd, 0xb1, 0xe7, 0x1b, 0x4b, 0x0f, - 0xc9, 0xf8, 0x06, 0x4e, 0x0b, 0x22, 0xc9, 0x30, 0x50, 0x42, 0x4a, 0x54, 0x36, 0x19, 0x2d, 0x92, - 0x57, 0xbd, 0x8f, 0xe0, 0xcb, 0x4d, 0x90, 0xcc, 0xc3, 0x07, 0xc7, 0x6d, 0x2b, 0x3f, 0x6e, 0xa3, - 0xb1, 0x46, 0x4f, 0xa9, 0x78, 0x0b, 0x55, 0xd2, 0x04, 0xfc, 0x66, 0x49, 0xd3, 0x97, 0xc8, 0xa5, - 0xf7, 0x4b, 0x26, 0xea, 0x7b, 0x9d, 0x80, 0xef, 0xfd, 0x6f, 0xf8, 0x15, 0x75, 0xa2, 0x9a, 0x86, - 0xdf, 0xa3, 0x99, 0x54, 0x32, 0x99, 0xa5, 0xcd, 0xb2, 0xe6, 0x2e, 0x5f, 0x93, 0xab, 0xbd, 0xde, - 0x0d, 0x43, 0x9e, 0x29, 0xce, 0xd4, 0x30, 0xbb, 0x2b, 0xe8, 0xe6, 0xb9, 0x22, 0xf0, 0x3d, 0x54, - 0x95, 0x4a, 0xd2, 0x53, 0xaa, 0x7b, 0xb3, 0xc6, 0x59, 0x2d, 0xf2, 0x8a, 0x58, 0xf7, 0xa7, 0x8d, - 0x6e, 0x4d, 0xfd, 0x05, 0x3f, 0x41, 0xb3, 0x13, 0x15, 0x41, 0x5f, 0x23, 0x6a, 0xde, 0x6d, 0x83, - 0x98, 0x7d, 0x3a, 0x19, 0xa4, 0x67, 0x73, 0xf1, 0x26, 0xaa, 0x64, 0x29, 0x08, 0x33, 0xbe, 0xfb, - 0x57, 0x68, 0x73, 0x3b, 0x05, 0xb1, 0x11, 0xed, 0xc4, 0xe3, 0xb9, 0x29, 0x85, 0x6a, 0x8c, 0x6a, - 0x03, 0x84, 0x88, 0x85, 0x1e, 0xdb, 0x44, 0x1b, 0xeb, 0x4a, 0xa4, 0x45, 0xac, 0xfb, 0xa3, 0x84, - 0x6a, 0xff, 0x28, 0xf8, 0x01, 0xaa, 0x29, 0x67, 0xc4, 0x42, 0x30, 0xbd, 0xcf, 0x19, 0x93, 0xce, - 0x51, 0x3a, 0x3d, 0xcd, 0xc0, 0x77, 0x50, 0x39, 0xe3, 0x7d, 0x5d, 0x6d, 0xdd, 0x6b, 0x98, 0xc4, - 0xf2, 0xf6, 0xc6, 0x73, 0xaa, 0x74, 0xdc, 0x45, 0x33, 0x81, 0x88, 0xb3, 0x44, 0x5d, 0x9b, 0x7a, - 0xaa, 0x48, 0x0d, 0xff, 0x85, 0x56, 0xa8, 0x89, 0xe0, 0x77, 0xa8, 0x0a, 0xea, 0x6d, 0x37, 0x2b, - 0x9d, 0xf2, 0x7c, 0x63, 0x69, 0xe5, 0x1a, 0x2d, 0x13, 0xbd, 0x14, 0xeb, 0x91, 0x14, 0x7b, 0x13, - 0xad, 0x29, 0x8d, 0x16, 0xcc, 0x56, 0x60, 0x16, 0x47, 0xe7, 0xe0, 0x39, 0x54, 0x1e, 0xc2, 0x5e, - 0xd1, 0x16, 0x55, 0x9f, 0xf8, 0x19, 0xaa, 0x8e, 0xd4, 0x4e, 0x99, 0x79, 0x2f, 0x5c, 0xe1, 0xe7, - 0xe3, 0x45, 0xa4, 0x85, 0x77, 0xad, 0xb4, 0x6a, 0x7b, 0x0b, 0x07, 0x27, 0x8e, 0x75, 0x78, 0xe2, - 0x58, 0x47, 0x27, 0x8e, 0xb5, 0x9f, 0x3b, 0xf6, 0x41, 0xee, 0xd8, 0x87, 0xb9, 0x63, 0x1f, 0xe5, - 0x8e, 0xfd, 0x3b, 0x77, 0xec, 0x2f, 0x7f, 0x1c, 0xeb, 0xed, 0x7f, 0x06, 0xf2, 0x37, 0x00, 0x00, - 0xff, 0xff, 0x36, 0x0e, 0x35, 0x2a, 0x43, 0x05, 0x00, 0x00, + // 635 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xcf, 0x4f, 0xd4, 0x40, + 0x14, 0x6e, 0xf7, 0x07, 0xee, 0xce, 0x8a, 0xe2, 0x24, 0x26, 0x9b, 0x4d, 0xec, 0xae, 0xeb, 0x85, + 0x44, 0x99, 0x0a, 0x21, 0x48, 0xf0, 0x64, 0x95, 0x18, 0x4c, 0x88, 0xc9, 0x08, 0x1e, 0xd4, 0x83, + 0xb3, 0xdd, 0x47, 0xb7, 0xae, 0xed, 0x34, 0xd3, 0x69, 0x95, 0x1b, 0x7f, 0x82, 0x47, 0x8f, 0x26, + 0xfe, 0x25, 0x26, 0x1e, 0x38, 0x72, 0xe4, 0x60, 0x88, 0xd4, 0x7f, 0xc4, 0xcc, 0x74, 0x64, 0x17, + 0x88, 0x01, 0x6e, 0xf3, 0xbe, 0xf7, 0xbe, 0x6f, 0xde, 0xf7, 0x66, 0x1e, 0x7a, 0x31, 0x5e, 0x4d, + 0x49, 0xc8, 0xdd, 0x71, 0x36, 0x00, 0x11, 0x83, 0x84, 0xd4, 0xcd, 0x21, 0x1e, 0x72, 0xe1, 0x9a, + 0x04, 0x4b, 0x42, 0x97, 0x65, 0x72, 0x04, 0xb1, 0x0c, 0x7d, 0x26, 0x43, 0x1e, 0xbb, 0xf9, 0xe2, + 0x00, 0x24, 0x5b, 0x74, 0x03, 0x88, 0x41, 0x30, 0x09, 0x43, 0x92, 0x08, 0x2e, 0x39, 0xbe, 0x5b, + 0x52, 0x08, 0x4b, 0x42, 0x72, 0x9a, 0x42, 0x0c, 0xa5, 0xb3, 0x10, 0x84, 0x72, 0x94, 0x0d, 0x88, + 0xcf, 0x23, 0x37, 0xe0, 0x01, 0x77, 0x35, 0x73, 0x90, 0xed, 0xe8, 0x48, 0x07, 0xfa, 0x54, 0x2a, + 0x76, 0x96, 0x27, 0x4d, 0x44, 0xcc, 0x1f, 0x85, 0x31, 0x88, 0x5d, 0x37, 0x19, 0x07, 0x0a, 0x48, + 0xdd, 0x08, 0x24, 0x73, 0xf3, 0x73, 0x7d, 0x74, 0xdc, 0xff, 0xb1, 0x44, 0x16, 0xcb, 0x30, 0x82, + 0x73, 0x84, 0x95, 0x8b, 0x08, 0xa9, 0x3f, 0x82, 0x88, 0x9d, 0xe5, 0xf5, 0x1f, 0x21, 0xb4, 0xfe, + 0x59, 0x0a, 0xf6, 0x9a, 0x7d, 0xcc, 0x00, 0x77, 0x51, 0x3d, 0x94, 0x10, 0xa5, 0x6d, 0xbb, 0x57, + 0x9d, 0x6f, 0x7a, 0xcd, 0xe2, 0xa8, 0x5b, 0xdf, 0x50, 0x00, 0x2d, 0xf1, 0xb5, 0xc6, 0xd7, 0x6f, + 0x5d, 0x6b, 0xef, 0x57, 0xcf, 0xea, 0x7f, 0xaf, 0xa0, 0xd6, 0x16, 0x1f, 0x43, 0x4c, 0x21, 0x0f, + 0xe1, 0x13, 0x7e, 0x8f, 0x1a, 0xca, 0xcc, 0x90, 0x49, 0xd6, 0xb6, 0x7b, 0xf6, 0x7c, 0x6b, 0xe9, + 0x21, 0x99, 0x0c, 0xf3, 0xa4, 0x27, 0x92, 0x8c, 0x03, 0x05, 0xa4, 0x44, 0x55, 0x93, 0x7c, 0x91, + 0xbc, 0x1c, 0x7c, 0x00, 0x5f, 0x6e, 0x82, 0x64, 0x1e, 0xde, 0x3f, 0xea, 0x5a, 0xc5, 0x51, 0x17, + 0x4d, 0x30, 0x7a, 0xa2, 0x8a, 0xb7, 0x50, 0x2d, 0x4d, 0xc0, 0x6f, 0x57, 0xb4, 0xfa, 0x12, 0xb9, + 0xf0, 0xa9, 0xc8, 0x54, 0x7f, 0xaf, 0x12, 0xf0, 0xbd, 0xeb, 0x46, 0xbf, 0xa6, 0x22, 0xaa, 0xd5, + 0xf0, 0x3b, 0x34, 0x93, 0x4a, 0x26, 0xb3, 0xb4, 0x5d, 0xd5, 0xba, 0xcb, 0x57, 0xd4, 0xd5, 0x5c, + 0xef, 0x86, 0x51, 0x9e, 0x29, 0x63, 0x6a, 0x34, 0xfb, 0x2b, 0xe8, 0xe6, 0x99, 0x26, 0xf0, 0x3d, + 0x54, 0x97, 0x0a, 0xd2, 0x53, 0x6a, 0x7a, 0xb3, 0x86, 0x59, 0x2f, 0xeb, 0xca, 0x5c, 0xff, 0xa7, + 0x8d, 0x6e, 0x9d, 0xbb, 0x05, 0x3f, 0x46, 0xb3, 0x53, 0x1d, 0xc1, 0x50, 0x4b, 0x34, 0xbc, 0xdb, + 0x46, 0x62, 0xf6, 0xc9, 0x74, 0x92, 0x9e, 0xae, 0xc5, 0x9b, 0xa8, 0x96, 0xa5, 0x20, 0xcc, 0xf8, + 0xee, 0x5f, 0xc2, 0xe6, 0x76, 0x0a, 0x62, 0x23, 0xde, 0xe1, 0x93, 0xb9, 0x29, 0x84, 0x6a, 0x19, + 0x65, 0x03, 0x84, 0xe0, 0x42, 0x8f, 0x6d, 0xca, 0xc6, 0xba, 0x02, 0x69, 0x99, 0xeb, 0xff, 0xa8, + 0xa0, 0xc6, 0x3f, 0x15, 0xfc, 0x00, 0x35, 0x14, 0x33, 0x66, 0x11, 0x18, 0xef, 0x73, 0x86, 0xa4, + 0x6b, 0x14, 0x4e, 0x4f, 0x2a, 0xf0, 0x1d, 0x54, 0xcd, 0xc2, 0xa1, 0xee, 0xb6, 0xe9, 0xb5, 0x4c, + 0x61, 0x75, 0x7b, 0xe3, 0x19, 0x55, 0x38, 0xee, 0xa3, 0x99, 0x40, 0xf0, 0x2c, 0x51, 0xcf, 0xa6, + 0xbe, 0x2a, 0x52, 0xc3, 0x7f, 0xae, 0x11, 0x6a, 0x32, 0xf8, 0x2d, 0xaa, 0x83, 0xfa, 0xdb, 0xed, + 0x5a, 0xaf, 0x3a, 0xdf, 0x5a, 0x5a, 0xb9, 0x82, 0x65, 0xa2, 0x97, 0x62, 0x3d, 0x96, 0x62, 0x77, + 0xca, 0x9a, 0xc2, 0x68, 0xa9, 0xd9, 0x09, 0xcc, 0xe2, 0xe8, 0x1a, 0x3c, 0x87, 0xaa, 0x63, 0xd8, + 0x2d, 0x6d, 0x51, 0x75, 0xc4, 0x4f, 0x51, 0x3d, 0x57, 0x3b, 0x65, 0xe6, 0xbd, 0x70, 0x89, 0xcb, + 0x27, 0x8b, 0x48, 0x4b, 0xee, 0x5a, 0x65, 0xd5, 0xf6, 0x16, 0xf6, 0x8f, 0x1d, 0xeb, 0xe0, 0xd8, + 0xb1, 0x0e, 0x8f, 0x1d, 0x6b, 0xaf, 0x70, 0xec, 0xfd, 0xc2, 0xb1, 0x0f, 0x0a, 0xc7, 0x3e, 0x2c, + 0x1c, 0xfb, 0x77, 0xe1, 0xd8, 0x5f, 0xfe, 0x38, 0xd6, 0x9b, 0x6b, 0x46, 0xe4, 0x6f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x39, 0x00, 0xe7, 0xfa, 0x0e, 0x05, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/generated.proto index 3d0abd15d..a057bc591 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.authentication.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/types_swagger_doc_generated.go index f910bea6f..968999d1e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_TokenReview = map[string]string{ "": "TokenReview attempts to authenticate a token to a known user. Note: TokenReview requests may be cached by the webhook token authenticator plugin in the kube-apiserver.", "spec": "Spec holds information about the request being evaluated", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/zz_generated.deepcopy.go index 57d878e9a..bb552ff63 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authentication/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/generated.pb.go index bdb606c0b..e9145af02 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -3452,77 +3452,77 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1152 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xf7, 0xae, 0xed, 0xd4, 0x1e, 0x37, 0x24, 0x9d, 0x28, 0xcd, 0x36, 0x15, 0x76, 0xb4, 0x48, - 0x90, 0x8a, 0xb2, 0x4b, 0x4c, 0xdb, 0x44, 0x95, 0x2a, 0x14, 0x2b, 0x11, 0x8a, 0xd4, 0x96, 0x6a, - 0xa2, 0x44, 0xa2, 0x08, 0xc4, 0x78, 0x3d, 0xb1, 0x97, 0xd8, 0xbb, 0xcb, 0xcc, 0xac, 0x43, 0x38, - 0x55, 0xe2, 0x0b, 0x70, 0xe4, 0xc0, 0x81, 0x6f, 0xc0, 0x05, 0x89, 0x1b, 0x07, 0x0e, 0x28, 0xc7, - 0x1e, 0x8b, 0x84, 0x2c, 0xb2, 0x9c, 0xf9, 0x0e, 0x68, 0x66, 0xc7, 0xde, 0x75, 0xb2, 0x76, 0x13, - 0x0e, 0xf4, 0xd2, 0xdb, 0xee, 0xfb, 0xfd, 0xde, 0x9f, 0x79, 0x7f, 0x66, 0x1e, 0xd8, 0x3a, 0xdc, - 0x60, 0x96, 0xeb, 0xdb, 0x87, 0x61, 0x93, 0x50, 0x8f, 0x70, 0xc2, 0xec, 0x3e, 0xf1, 0x5a, 0x3e, - 0xb5, 0x15, 0x80, 0x03, 0xd7, 0xc6, 0x21, 0xef, 0xf8, 0xd4, 0xfd, 0x06, 0x73, 0xd7, 0xf7, 0xec, - 0xfe, 0x9a, 0xdd, 0x26, 0x1e, 0xa1, 0x98, 0x93, 0x96, 0x15, 0x50, 0x9f, 0xfb, 0xf0, 0x66, 0x4c, - 0xb6, 0x70, 0xe0, 0x5a, 0x63, 0x64, 0xab, 0xbf, 0xb6, 0xfc, 0x5e, 0xdb, 0xe5, 0x9d, 0xb0, 0x69, - 0x39, 0x7e, 0xcf, 0x6e, 0xfb, 0x6d, 0xdf, 0x96, 0x3a, 0xcd, 0xf0, 0x40, 0xfe, 0xc9, 0x1f, 0xf9, - 0x15, 0xdb, 0x5a, 0xbe, 0x93, 0x38, 0xee, 0x61, 0xa7, 0xe3, 0x7a, 0x84, 0x1e, 0xdb, 0xc1, 0x61, - 0x5b, 0x08, 0x98, 0xdd, 0x23, 0x1c, 0x67, 0x44, 0xb0, 0x6c, 0x4f, 0xd2, 0xa2, 0xa1, 0xc7, 0xdd, - 0x1e, 0x39, 0xa7, 0x70, 0xef, 0x65, 0x0a, 0xcc, 0xe9, 0x90, 0x1e, 0x3e, 0xa7, 0xf7, 0xc1, 0x24, - 0xbd, 0x90, 0xbb, 0x5d, 0xdb, 0xf5, 0x38, 0xe3, 0xf4, 0xac, 0x92, 0xb9, 0x0e, 0xc0, 0xf6, 0xd7, - 0x9c, 0xe2, 0x7d, 0xdc, 0x0d, 0x09, 0xac, 0x81, 0xa2, 0xcb, 0x49, 0x8f, 0x19, 0xda, 0x4a, 0x7e, - 0xb5, 0xdc, 0x28, 0x47, 0x83, 0x5a, 0x71, 0x47, 0x08, 0x50, 0x2c, 0xbf, 0x5f, 0xfa, 0xfe, 0xc7, - 0x5a, 0xee, 0xd9, 0x9f, 0x2b, 0x39, 0xf3, 0x67, 0x1d, 0x18, 0x0f, 0x7d, 0x07, 0x77, 0x77, 0xc3, - 0xe6, 0x97, 0xc4, 0xe1, 0x9b, 0x8e, 0x43, 0x18, 0x43, 0xa4, 0xef, 0x92, 0x23, 0xf8, 0x05, 0x28, - 0x89, 0x74, 0xb4, 0x30, 0xc7, 0x86, 0xb6, 0xa2, 0xad, 0x56, 0xea, 0xef, 0x5b, 0x49, 0x21, 0x46, - 0xd1, 0x59, 0xc1, 0x61, 0x5b, 0x08, 0x98, 0x25, 0xd8, 0x56, 0x7f, 0xcd, 0xfa, 0x58, 0xda, 0x7a, - 0x44, 0x38, 0x6e, 0xc0, 0x93, 0x41, 0x2d, 0x17, 0x0d, 0x6a, 0x20, 0x91, 0xa1, 0x91, 0x55, 0xb8, - 0x0f, 0x0a, 0x2c, 0x20, 0x8e, 0xa1, 0x4b, 0xeb, 0x77, 0xac, 0x29, 0x65, 0xb6, 0x32, 0x22, 0xdc, - 0x0d, 0x88, 0xd3, 0xb8, 0xaa, 0x3c, 0x14, 0xc4, 0x1f, 0x92, 0xf6, 0xe0, 0xe7, 0x60, 0x86, 0x71, - 0xcc, 0x43, 0x66, 0xe4, 0xa5, 0xe5, 0x7b, 0x97, 0xb6, 0x2c, 0xb5, 0x1b, 0x6f, 0x28, 0xdb, 0x33, - 0xf1, 0x3f, 0x52, 0x56, 0xcd, 0x4f, 0xc1, 0xe2, 0x63, 0xdf, 0x43, 0x84, 0xf9, 0x21, 0x75, 0xc8, - 0x26, 0xe7, 0xd4, 0x6d, 0x86, 0x9c, 0x30, 0xb8, 0x02, 0x0a, 0x01, 0xe6, 0x1d, 0x99, 0xae, 0x72, - 0x12, 0xda, 0x13, 0xcc, 0x3b, 0x48, 0x22, 0x82, 0xd1, 0x27, 0xb4, 0x29, 0x8f, 0x9c, 0x62, 0xec, - 0x13, 0xda, 0x44, 0x12, 0x31, 0xbf, 0x02, 0x73, 0x29, 0xe3, 0x28, 0xec, 0xca, 0x8a, 0x0a, 0x68, - 0xac, 0xa2, 0x42, 0x83, 0xa1, 0x58, 0x0e, 0x1f, 0x80, 0x39, 0x2f, 0xd1, 0xd9, 0x43, 0x0f, 0x99, - 0xa1, 0x4b, 0xea, 0x42, 0x34, 0xa8, 0xa5, 0xcd, 0x09, 0x08, 0x9d, 0xe5, 0x9a, 0xbf, 0xea, 0x00, - 0x66, 0x9c, 0xc6, 0x06, 0x65, 0x0f, 0xf7, 0x08, 0x0b, 0xb0, 0x43, 0xd4, 0x91, 0xae, 0xa9, 0x80, - 0xcb, 0x8f, 0x87, 0x00, 0x4a, 0x38, 0x2f, 0x3f, 0x1c, 0x7c, 0x0b, 0x14, 0xdb, 0xd4, 0x0f, 0x03, - 0x59, 0x98, 0x72, 0x63, 0x56, 0x51, 0x8a, 0x1f, 0x09, 0x21, 0x8a, 0x31, 0x78, 0x0b, 0x5c, 0xe9, - 0x13, 0xca, 0x5c, 0xdf, 0x33, 0x0a, 0x92, 0x36, 0xa7, 0x68, 0x57, 0xf6, 0x63, 0x31, 0x1a, 0xe2, - 0xf0, 0x36, 0x28, 0x51, 0x15, 0xb8, 0x51, 0x94, 0xdc, 0x79, 0xc5, 0x2d, 0x8d, 0x32, 0x38, 0x62, - 0xc0, 0xbb, 0xa0, 0xc2, 0xc2, 0xe6, 0x48, 0x61, 0x46, 0x2a, 0x2c, 0x28, 0x85, 0xca, 0x6e, 0x02, - 0xa1, 0x34, 0x4f, 0x1c, 0x4b, 0x9c, 0xd1, 0xb8, 0x32, 0x7e, 0x2c, 0x91, 0x02, 0x24, 0x11, 0xf3, - 0x37, 0x0d, 0x5c, 0xbd, 0x5c, 0xc5, 0xde, 0x05, 0x65, 0x1c, 0xb8, 0xf2, 0xd8, 0xc3, 0x5a, 0xcd, - 0x8a, 0xbc, 0x6e, 0x3e, 0xd9, 0x89, 0x85, 0x28, 0xc1, 0x05, 0x79, 0x18, 0x8c, 0x68, 0xe9, 0x11, - 0x79, 0xe8, 0x92, 0xa1, 0x04, 0x87, 0xeb, 0x60, 0x76, 0xf8, 0x23, 0x8b, 0x64, 0x14, 0xa4, 0xc2, - 0xb5, 0x68, 0x50, 0x9b, 0x45, 0x69, 0x00, 0x8d, 0xf3, 0xcc, 0x5f, 0x74, 0xb0, 0xb4, 0x4b, 0xba, - 0x07, 0xaf, 0xe6, 0x2e, 0x78, 0x3a, 0x76, 0x17, 0x6c, 0x4c, 0x9f, 0xd8, 0xec, 0x28, 0x5f, 0xd9, - 0x7d, 0xf0, 0x83, 0x0e, 0x6e, 0x4e, 0x89, 0x09, 0x1e, 0x01, 0x48, 0xcf, 0x8d, 0x97, 0xca, 0xa3, - 0x3d, 0x35, 0x96, 0xf3, 0x53, 0xd9, 0xb8, 0x1e, 0x0d, 0x6a, 0x19, 0xd3, 0x8a, 0x32, 0x5c, 0xc0, - 0x6f, 0x35, 0xb0, 0xe8, 0x65, 0xdd, 0x54, 0x2a, 0xcd, 0xf5, 0xa9, 0xce, 0x33, 0xef, 0xb8, 0xc6, - 0x8d, 0x68, 0x50, 0xcb, 0xbe, 0xfe, 0x50, 0xb6, 0x2f, 0xf1, 0xca, 0x5c, 0x4f, 0xa5, 0x47, 0x0c, - 0xc8, 0xff, 0xd7, 0x57, 0x9f, 0x8c, 0xf5, 0xd5, 0xfa, 0x45, 0xfb, 0x2a, 0x15, 0xe4, 0xc4, 0xb6, - 0xfa, 0xec, 0x4c, 0x5b, 0xdd, 0xbd, 0x48, 0x5b, 0xa5, 0x0d, 0x4f, 0xef, 0xaa, 0x47, 0x60, 0x79, - 0x72, 0x40, 0x97, 0xbe, 0x9c, 0xcd, 0x9f, 0x74, 0xb0, 0xf0, 0xfa, 0x99, 0xbf, 0xcc, 0x58, 0xff, - 0x5e, 0x00, 0x4b, 0xaf, 0x47, 0x7a, 0xd2, 0xa2, 0x13, 0x32, 0x42, 0xd5, 0x33, 0x3e, 0x2a, 0xce, - 0x1e, 0x23, 0x14, 0x49, 0x04, 0x9a, 0x60, 0xa6, 0x1d, 0xbf, 0x6e, 0xf1, 0xfb, 0x03, 0x44, 0x82, - 0xd5, 0xd3, 0xa6, 0x10, 0xd8, 0x02, 0x45, 0x22, 0xf6, 0x56, 0xa3, 0xb8, 0x92, 0x5f, 0xad, 0xd4, - 0x3f, 0xfc, 0x2f, 0x9d, 0x61, 0xc9, 0xcd, 0x77, 0xdb, 0xe3, 0xf4, 0x38, 0x59, 0x27, 0xa4, 0x0c, - 0xc5, 0xc6, 0xe1, 0x9b, 0x20, 0x1f, 0xba, 0x2d, 0xf5, 0xda, 0x57, 0x14, 0x25, 0xbf, 0xb7, 0xb3, - 0x85, 0x84, 0x7c, 0x19, 0xab, 0xe5, 0x59, 0x9a, 0x80, 0xf3, 0x20, 0x7f, 0x48, 0x8e, 0xe3, 0x81, - 0x42, 0xe2, 0x13, 0x3e, 0x00, 0xc5, 0xbe, 0xd8, 0xab, 0x55, 0x7e, 0xdf, 0x99, 0x1a, 0x64, 0xb2, - 0x86, 0xa3, 0x58, 0xeb, 0xbe, 0xbe, 0xa1, 0x99, 0x7f, 0x68, 0xe0, 0xc6, 0xc4, 0xf6, 0x13, 0xeb, - 0x0e, 0xee, 0x76, 0xfd, 0x23, 0xd2, 0x92, 0x6e, 0x4b, 0xc9, 0xba, 0xb3, 0x19, 0x8b, 0xd1, 0x10, - 0x87, 0x6f, 0x83, 0x19, 0x4a, 0x30, 0xf3, 0x3d, 0xb5, 0x62, 0x8d, 0x3a, 0x17, 0x49, 0x29, 0x52, - 0x28, 0xdc, 0x04, 0x73, 0x44, 0xb8, 0x97, 0x71, 0x6d, 0x53, 0xea, 0x0f, 0x2b, 0xb5, 0xa4, 0x14, - 0xe6, 0xb6, 0xc7, 0x61, 0x74, 0x96, 0x2f, 0x5c, 0xb5, 0x88, 0xe7, 0x92, 0x96, 0xdc, 0xc1, 0x4a, - 0x89, 0xab, 0x2d, 0x29, 0x45, 0x0a, 0x35, 0xff, 0xd1, 0x81, 0x31, 0xe9, 0x6a, 0x83, 0x07, 0xc9, - 0x2e, 0x22, 0x41, 0xb9, 0x0e, 0x55, 0xea, 0xb7, 0x2e, 0x34, 0x20, 0x42, 0xa3, 0xb1, 0xa8, 0xdc, - 0xce, 0xa6, 0xa5, 0xa9, 0xd5, 0x45, 0xfe, 0x42, 0x0a, 0xe6, 0xbd, 0xf1, 0x9d, 0x39, 0x5e, 0xaa, - 0x2a, 0xf5, 0xdb, 0x17, 0x1d, 0x07, 0xe9, 0xcd, 0x50, 0xde, 0xe6, 0xcf, 0x00, 0x0c, 0x9d, 0xb3, - 0x0f, 0xeb, 0x00, 0xb8, 0x9e, 0xe3, 0xf7, 0x82, 0x2e, 0xe1, 0x44, 0xa6, 0xb7, 0x94, 0xdc, 0x83, - 0x3b, 0x23, 0x04, 0xa5, 0x58, 0x59, 0x75, 0x29, 0x5c, 0xae, 0x2e, 0x8d, 0xd5, 0x93, 0xd3, 0x6a, - 0xee, 0xf9, 0x69, 0x35, 0xf7, 0xe2, 0xb4, 0x9a, 0x7b, 0x16, 0x55, 0xb5, 0x93, 0xa8, 0xaa, 0x3d, - 0x8f, 0xaa, 0xda, 0x8b, 0xa8, 0xaa, 0xfd, 0x15, 0x55, 0xb5, 0xef, 0xfe, 0xae, 0xe6, 0x9e, 0xea, - 0xfd, 0xb5, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd6, 0x0e, 0xab, 0x82, 0x7c, 0x0f, 0x00, 0x00, + // 1140 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4d, 0x6f, 0x1b, 0xc5, + 0x1b, 0xf7, 0xae, 0xed, 0xc4, 0x1e, 0x37, 0xff, 0xa4, 0x13, 0xa5, 0xd9, 0xa6, 0xfa, 0xdb, 0xd1, + 0x22, 0x41, 0x2a, 0xca, 0x2e, 0xb1, 0xda, 0x26, 0xaa, 0x54, 0xa1, 0x58, 0x89, 0x50, 0xa4, 0xb6, + 0x54, 0x13, 0x25, 0x12, 0x45, 0x20, 0xc6, 0xeb, 0x89, 0xbd, 0xc4, 0xde, 0x5d, 0x66, 0x66, 0x1d, + 0xc2, 0xa9, 0x12, 0x5f, 0x80, 0x23, 0x07, 0x0e, 0x7c, 0x03, 0x2e, 0x48, 0xdc, 0x38, 0x70, 0x40, + 0x39, 0xf6, 0x58, 0x24, 0x64, 0x91, 0xe5, 0xcc, 0x77, 0x40, 0x33, 0x3b, 0xf6, 0xae, 0x93, 0xb5, + 0x9b, 0x70, 0xa0, 0x97, 0xde, 0x76, 0x9f, 0xdf, 0xef, 0x79, 0x99, 0xe7, 0x65, 0xe6, 0x01, 0xdb, + 0x47, 0x9b, 0xcc, 0x72, 0x7d, 0xfb, 0x28, 0x6c, 0x12, 0xea, 0x11, 0x4e, 0x98, 0xdd, 0x27, 0x5e, + 0xcb, 0xa7, 0xb6, 0x02, 0x70, 0xe0, 0xda, 0x38, 0xe4, 0x1d, 0x9f, 0xba, 0x5f, 0x63, 0xee, 0xfa, + 0x9e, 0xdd, 0x5f, 0xb7, 0xdb, 0xc4, 0x23, 0x14, 0x73, 0xd2, 0xb2, 0x02, 0xea, 0x73, 0x1f, 0xde, + 0x8a, 0xc9, 0x16, 0x0e, 0x5c, 0x6b, 0x8c, 0x6c, 0xf5, 0xd7, 0x57, 0xde, 0x6b, 0xbb, 0xbc, 0x13, + 0x36, 0x2d, 0xc7, 0xef, 0xd9, 0x6d, 0xbf, 0xed, 0xdb, 0x52, 0xa7, 0x19, 0x1e, 0xca, 0x3f, 0xf9, + 0x23, 0xbf, 0x62, 0x5b, 0x2b, 0x77, 0x13, 0xc7, 0x3d, 0xec, 0x74, 0x5c, 0x8f, 0xd0, 0x13, 0x3b, + 0x38, 0x6a, 0x0b, 0x01, 0xb3, 0x7b, 0x84, 0xe3, 0x8c, 0x08, 0x56, 0xec, 0x49, 0x5a, 0x34, 0xf4, + 0xb8, 0xdb, 0x23, 0x17, 0x14, 0xee, 0xbf, 0x4a, 0x81, 0x39, 0x1d, 0xd2, 0xc3, 0xe7, 0xf5, 0xcc, + 0x0d, 0x00, 0x76, 0xbe, 0xe2, 0x14, 0x1f, 0xe0, 0x6e, 0x48, 0x60, 0x0d, 0x14, 0x5d, 0x4e, 0x7a, + 0xcc, 0xd0, 0x56, 0xf3, 0x6b, 0xe5, 0x46, 0x39, 0x1a, 0xd4, 0x8a, 0xbb, 0x42, 0x80, 0x62, 0xf9, + 0x83, 0xd2, 0x77, 0x3f, 0xd4, 0x72, 0xcf, 0xff, 0x58, 0xcd, 0x99, 0x3f, 0xe9, 0xc0, 0x78, 0xe4, + 0x3b, 0xb8, 0xbb, 0x17, 0x36, 0xbf, 0x20, 0x0e, 0xdf, 0x72, 0x1c, 0xc2, 0x18, 0x22, 0x7d, 0x97, + 0x1c, 0xc3, 0xcf, 0x41, 0x49, 0x9c, 0xac, 0x85, 0x39, 0x36, 0xb4, 0x55, 0x6d, 0xad, 0x52, 0x7f, + 0xdf, 0x4a, 0x72, 0x3a, 0x0a, 0xd0, 0x0a, 0x8e, 0xda, 0x42, 0xc0, 0x2c, 0xc1, 0xb6, 0xfa, 0xeb, + 0xd6, 0x47, 0xd2, 0xd6, 0x63, 0xc2, 0x71, 0x03, 0x9e, 0x0e, 0x6a, 0xb9, 0x68, 0x50, 0x03, 0x89, + 0x0c, 0x8d, 0xac, 0xc2, 0x03, 0x50, 0x60, 0x01, 0x71, 0x0c, 0x5d, 0x5a, 0xbf, 0x6b, 0x4d, 0xa9, + 0x98, 0x95, 0x11, 0xe1, 0x5e, 0x40, 0x9c, 0xc6, 0x35, 0xe5, 0xa1, 0x20, 0xfe, 0x90, 0xb4, 0x07, + 0x3f, 0x03, 0x33, 0x8c, 0x63, 0x1e, 0x32, 0x23, 0x2f, 0x2d, 0xdf, 0xbf, 0xb2, 0x65, 0xa9, 0xdd, + 0xf8, 0x9f, 0xb2, 0x3d, 0x13, 0xff, 0x23, 0x65, 0xd5, 0xfc, 0x04, 0x2c, 0x3d, 0xf1, 0x3d, 0x44, + 0x98, 0x1f, 0x52, 0x87, 0x6c, 0x71, 0x4e, 0xdd, 0x66, 0xc8, 0x09, 0x83, 0xab, 0xa0, 0x10, 0x60, + 0xde, 0x91, 0xe9, 0x2a, 0x27, 0xa1, 0x3d, 0xc5, 0xbc, 0x83, 0x24, 0x22, 0x18, 0x7d, 0x42, 0x9b, + 0xf2, 0xc8, 0x29, 0xc6, 0x01, 0xa1, 0x4d, 0x24, 0x11, 0xf3, 0x4b, 0x30, 0x9f, 0x32, 0x8e, 0xc2, + 0xae, 0xac, 0xa8, 0x80, 0xc6, 0x2a, 0x2a, 0x34, 0x18, 0x8a, 0xe5, 0xf0, 0x21, 0x98, 0xf7, 0x12, + 0x9d, 0x7d, 0xf4, 0x88, 0x19, 0xba, 0xa4, 0x2e, 0x46, 0x83, 0x5a, 0xda, 0x9c, 0x80, 0xd0, 0x79, + 0xae, 0xf9, 0x8b, 0x0e, 0x60, 0xc6, 0x69, 0x6c, 0x50, 0xf6, 0x70, 0x8f, 0xb0, 0x00, 0x3b, 0x44, + 0x1d, 0xe9, 0xba, 0x0a, 0xb8, 0xfc, 0x64, 0x08, 0xa0, 0x84, 0xf3, 0xea, 0xc3, 0xc1, 0xb7, 0x40, + 0xb1, 0x4d, 0xfd, 0x30, 0x90, 0x85, 0x29, 0x37, 0xe6, 0x14, 0xa5, 0xf8, 0xa1, 0x10, 0xa2, 0x18, + 0x83, 0xb7, 0xc1, 0x6c, 0x9f, 0x50, 0xe6, 0xfa, 0x9e, 0x51, 0x90, 0xb4, 0x79, 0x45, 0x9b, 0x3d, + 0x88, 0xc5, 0x68, 0x88, 0xc3, 0x3b, 0xa0, 0x44, 0x55, 0xe0, 0x46, 0x51, 0x72, 0x17, 0x14, 0xb7, + 0x34, 0xca, 0xe0, 0x88, 0x01, 0xef, 0x81, 0x0a, 0x0b, 0x9b, 0x23, 0x85, 0x19, 0xa9, 0xb0, 0xa8, + 0x14, 0x2a, 0x7b, 0x09, 0x84, 0xd2, 0x3c, 0x71, 0x2c, 0x71, 0x46, 0x63, 0x76, 0xfc, 0x58, 0x22, + 0x05, 0x48, 0x22, 0xe6, 0xaf, 0x1a, 0xb8, 0x76, 0xb5, 0x8a, 0xbd, 0x0b, 0xca, 0x38, 0x70, 0xe5, + 0xb1, 0x87, 0xb5, 0x9a, 0x13, 0x79, 0xdd, 0x7a, 0xba, 0x1b, 0x0b, 0x51, 0x82, 0x0b, 0xf2, 0x30, + 0x18, 0xd1, 0xd2, 0x23, 0xf2, 0xd0, 0x25, 0x43, 0x09, 0x0e, 0x37, 0xc0, 0xdc, 0xf0, 0x47, 0x16, + 0xc9, 0x28, 0x48, 0x85, 0xeb, 0xd1, 0xa0, 0x36, 0x87, 0xd2, 0x00, 0x1a, 0xe7, 0x99, 0x3f, 0xeb, + 0x60, 0x79, 0x8f, 0x74, 0x0f, 0x5f, 0xcf, 0x5d, 0xf0, 0x6c, 0xec, 0x2e, 0xd8, 0x9c, 0x3e, 0xb1, + 0xd9, 0x51, 0xbe, 0xb6, 0xfb, 0xe0, 0x7b, 0x1d, 0xdc, 0x9a, 0x12, 0x13, 0x3c, 0x06, 0x90, 0x5e, + 0x18, 0x2f, 0x95, 0x47, 0x7b, 0x6a, 0x2c, 0x17, 0xa7, 0xb2, 0x71, 0x23, 0x1a, 0xd4, 0x32, 0xa6, + 0x15, 0x65, 0xb8, 0x80, 0xdf, 0x68, 0x60, 0xc9, 0xcb, 0xba, 0xa9, 0x54, 0x9a, 0xeb, 0x53, 0x9d, + 0x67, 0xde, 0x71, 0x8d, 0x9b, 0xd1, 0xa0, 0x96, 0x7d, 0xfd, 0xa1, 0x6c, 0x5f, 0xe2, 0x95, 0xb9, + 0x91, 0x4a, 0x8f, 0x18, 0x90, 0xff, 0xae, 0xaf, 0x3e, 0x1e, 0xeb, 0xab, 0x8d, 0xcb, 0xf6, 0x55, + 0x2a, 0xc8, 0x89, 0x6d, 0xf5, 0xe9, 0xb9, 0xb6, 0xba, 0x77, 0x99, 0xb6, 0x4a, 0x1b, 0x9e, 0xde, + 0x55, 0x8f, 0xc1, 0xca, 0xe4, 0x80, 0xae, 0x7c, 0x39, 0x9b, 0x3f, 0xea, 0x60, 0xf1, 0xcd, 0x33, + 0x7f, 0x95, 0xb1, 0xfe, 0xad, 0x00, 0x96, 0xdf, 0x8c, 0xf4, 0xa4, 0x45, 0x27, 0x64, 0x84, 0xaa, + 0x67, 0x7c, 0x54, 0x9c, 0x7d, 0x46, 0x28, 0x92, 0x08, 0x34, 0xc1, 0x4c, 0x3b, 0x7e, 0xdd, 0xe2, + 0xf7, 0x07, 0x88, 0x04, 0xab, 0xa7, 0x4d, 0x21, 0xb0, 0x05, 0x8a, 0x44, 0xec, 0xad, 0x46, 0x71, + 0x35, 0xbf, 0x56, 0xa9, 0x7f, 0xf0, 0x6f, 0x3a, 0xc3, 0x92, 0x9b, 0xef, 0x8e, 0xc7, 0xe9, 0x49, + 0xb2, 0x4e, 0x48, 0x19, 0x8a, 0x8d, 0xc3, 0xff, 0x83, 0x7c, 0xe8, 0xb6, 0xd4, 0x6b, 0x5f, 0x51, + 0x94, 0xfc, 0xfe, 0xee, 0x36, 0x12, 0xf2, 0x15, 0xac, 0x96, 0x67, 0x69, 0x02, 0x2e, 0x80, 0xfc, + 0x11, 0x39, 0x89, 0x07, 0x0a, 0x89, 0x4f, 0xf8, 0x10, 0x14, 0xfb, 0x62, 0xaf, 0x56, 0xf9, 0x7d, + 0x67, 0x6a, 0x90, 0xc9, 0x1a, 0x8e, 0x62, 0xad, 0x07, 0xfa, 0xa6, 0x66, 0xfe, 0xae, 0x81, 0x9b, + 0x13, 0xdb, 0x4f, 0xac, 0x3b, 0xb8, 0xdb, 0xf5, 0x8f, 0x49, 0x4b, 0xba, 0x2d, 0x25, 0xeb, 0xce, + 0x56, 0x2c, 0x46, 0x43, 0x1c, 0xbe, 0x0d, 0x66, 0x28, 0xc1, 0xcc, 0xf7, 0xd4, 0x8a, 0x35, 0xea, + 0x5c, 0x24, 0xa5, 0x48, 0xa1, 0x70, 0x0b, 0xcc, 0x13, 0xe1, 0x5e, 0xc6, 0xb5, 0x43, 0xa9, 0x3f, + 0xac, 0xd4, 0xb2, 0x52, 0x98, 0xdf, 0x19, 0x87, 0xd1, 0x79, 0xbe, 0x70, 0xd5, 0x22, 0x9e, 0x4b, + 0x5a, 0x72, 0x07, 0x2b, 0x25, 0xae, 0xb6, 0xa5, 0x14, 0x29, 0xd4, 0xfc, 0x5b, 0x07, 0xc6, 0xa4, + 0xab, 0x0d, 0x1e, 0x26, 0xbb, 0x88, 0x04, 0xe5, 0x3a, 0x54, 0xa9, 0xdf, 0xbe, 0xd4, 0x80, 0x08, + 0x8d, 0xc6, 0x92, 0x72, 0x3b, 0x97, 0x96, 0xa6, 0x56, 0x17, 0xf9, 0x0b, 0x29, 0x58, 0xf0, 0xc6, + 0x77, 0xe6, 0x78, 0xa9, 0xaa, 0xd4, 0xef, 0x5c, 0x76, 0x1c, 0xa4, 0x37, 0x43, 0x79, 0x5b, 0x38, + 0x07, 0x30, 0x74, 0xc1, 0x3e, 0xac, 0x03, 0xe0, 0x7a, 0x8e, 0xdf, 0x0b, 0xba, 0x84, 0x13, 0x99, + 0xde, 0x52, 0x72, 0x0f, 0xee, 0x8e, 0x10, 0x94, 0x62, 0x65, 0xd5, 0xa5, 0x70, 0xb5, 0xba, 0x34, + 0xd6, 0x4e, 0xcf, 0xaa, 0xb9, 0x17, 0x67, 0xd5, 0xdc, 0xcb, 0xb3, 0x6a, 0xee, 0x79, 0x54, 0xd5, + 0x4e, 0xa3, 0xaa, 0xf6, 0x22, 0xaa, 0x6a, 0x2f, 0xa3, 0xaa, 0xf6, 0x67, 0x54, 0xd5, 0xbe, 0xfd, + 0xab, 0x9a, 0x7b, 0xa6, 0xf7, 0xd7, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x9f, 0x85, 0x45, 0x74, + 0x47, 0x0f, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/generated.proto index 2cd4af0c0..f68a04e49 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.authorization.v1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/types_swagger_doc_generated.go index 85503660c..8445f7116 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_LocalSubjectAccessReview = map[string]string{ "": "LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions checking.", "spec": "Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace you made the request against. If empty, it is defaulted.", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/zz_generated.deepcopy.go index 3df85934a..999933d74 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/generated.pb.go index a9a8116b3..75ee6cf91 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -3452,78 +3452,77 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1154 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4d, 0x6f, 0x1b, 0xc5, - 0x1b, 0xf7, 0xfa, 0x25, 0xb1, 0xc7, 0xcd, 0x3f, 0xe9, 0x44, 0x69, 0xb6, 0xf9, 0x0b, 0xdb, 0x32, - 0x12, 0x0a, 0xa2, 0xdd, 0x25, 0xa1, 0x90, 0x12, 0xe8, 0x21, 0x56, 0x22, 0x14, 0xa9, 0x2d, 0xd5, - 0x44, 0xc9, 0x81, 0x4a, 0xc0, 0x78, 0x3d, 0xb1, 0x17, 0xdb, 0xbb, 0xcb, 0xcc, 0xac, 0x43, 0x10, - 0x87, 0x1e, 0x39, 0x72, 0xe4, 0xc8, 0x89, 0xef, 0xc0, 0x05, 0x09, 0x4e, 0x39, 0xf6, 0x18, 0x24, - 0x64, 0x91, 0xe5, 0x43, 0x70, 0x45, 0x33, 0x3b, 0xf6, 0xae, 0xe3, 0x75, 0x1c, 0xe7, 0x40, 0x2f, - 0xbd, 0xed, 0x3c, 0xbf, 0xe7, 0x6d, 0x9e, 0x97, 0xd9, 0x1f, 0xd8, 0x6f, 0x3f, 0x64, 0x86, 0xed, - 0x9a, 0x6d, 0xbf, 0x4e, 0xa8, 0x43, 0x38, 0x61, 0x66, 0x8f, 0x38, 0x0d, 0x97, 0x9a, 0x0a, 0xc0, - 0x9e, 0x6d, 0x62, 0x9f, 0xb7, 0x5c, 0x6a, 0x7f, 0x8b, 0xb9, 0xed, 0x3a, 0x66, 0x6f, 0xa3, 0x4e, - 0x38, 0xde, 0x30, 0x9b, 0xc4, 0x21, 0x14, 0x73, 0xd2, 0x30, 0x3c, 0xea, 0x72, 0x17, 0x56, 0x42, - 0x0b, 0x03, 0x7b, 0xb6, 0x31, 0x62, 0x61, 0x28, 0x8b, 0xb5, 0xfb, 0x4d, 0x9b, 0xb7, 0xfc, 0xba, - 0x61, 0xb9, 0x5d, 0xb3, 0xe9, 0x36, 0x5d, 0x53, 0x1a, 0xd6, 0xfd, 0x63, 0x79, 0x92, 0x07, 0xf9, - 0x15, 0x3a, 0x5c, 0x7b, 0x10, 0xa5, 0xd0, 0xc5, 0x56, 0xcb, 0x76, 0x08, 0x3d, 0x35, 0xbd, 0x76, - 0x53, 0x08, 0x98, 0xd9, 0x25, 0x1c, 0x9b, 0xbd, 0xb1, 0x34, 0xd6, 0xcc, 0x49, 0x56, 0xd4, 0x77, - 0xb8, 0xdd, 0x25, 0x63, 0x06, 0x1f, 0x4c, 0x33, 0x60, 0x56, 0x8b, 0x74, 0xf1, 0x98, 0xdd, 0x7b, - 0x93, 0xec, 0x7c, 0x6e, 0x77, 0x4c, 0xdb, 0xe1, 0x8c, 0xd3, 0xcb, 0x46, 0xd5, 0x2d, 0x00, 0xf6, - 0xbe, 0xe1, 0x14, 0x1f, 0xe1, 0x8e, 0x4f, 0x60, 0x19, 0xe4, 0x6c, 0x4e, 0xba, 0x4c, 0xd7, 0x2a, - 0x99, 0xf5, 0x42, 0xad, 0x10, 0xf4, 0xcb, 0xb9, 0x7d, 0x21, 0x40, 0xa1, 0x7c, 0x3b, 0xff, 0xe3, - 0x4f, 0xe5, 0xd4, 0x8b, 0x3f, 0x2b, 0xa9, 0xea, 0xaf, 0x69, 0xa0, 0x3f, 0x76, 0x2d, 0xdc, 0x39, - 0xf0, 0xeb, 0x5f, 0x11, 0x8b, 0xef, 0x58, 0x16, 0x61, 0x0c, 0x91, 0x9e, 0x4d, 0x4e, 0xe0, 0x97, - 0x20, 0x2f, 0xca, 0xd1, 0xc0, 0x1c, 0xeb, 0x5a, 0x45, 0x5b, 0x2f, 0x6e, 0xbe, 0x6b, 0x44, 0xdd, - 0x18, 0x66, 0x67, 0x78, 0xed, 0xa6, 0x10, 0x30, 0x43, 0x68, 0x1b, 0xbd, 0x0d, 0xe3, 0x53, 0xe9, - 0xeb, 0x09, 0xe1, 0xb8, 0x06, 0xcf, 0xfa, 0xe5, 0x54, 0xd0, 0x2f, 0x83, 0x48, 0x86, 0x86, 0x5e, - 0xe1, 0x73, 0x90, 0x65, 0x1e, 0xb1, 0xf4, 0xb4, 0xf4, 0xfe, 0xa1, 0x31, 0xad, 0xd7, 0x46, 0x42, - 0x9a, 0x07, 0x1e, 0xb1, 0x6a, 0xb7, 0x54, 0x98, 0xac, 0x38, 0x21, 0xe9, 0x14, 0x5a, 0x60, 0x8e, - 0x71, 0xcc, 0x7d, 0xa6, 0x67, 0xa4, 0xfb, 0x8f, 0x6e, 0xe6, 0x5e, 0xba, 0xa8, 0xfd, 0x4f, 0x05, - 0x98, 0x0b, 0xcf, 0x48, 0xb9, 0xae, 0x3e, 0x07, 0x2b, 0x4f, 0x5d, 0x07, 0x11, 0xe6, 0xfa, 0xd4, - 0x22, 0x3b, 0x9c, 0x53, 0xbb, 0xee, 0x73, 0xc2, 0x60, 0x05, 0x64, 0x3d, 0xcc, 0x5b, 0xb2, 0x70, - 0x85, 0x28, 0xbf, 0x67, 0x98, 0xb7, 0x90, 0x44, 0x84, 0x46, 0x8f, 0xd0, 0xba, 0xbc, 0x7c, 0x4c, - 0xe3, 0x88, 0xd0, 0x3a, 0x92, 0x48, 0xf5, 0x6b, 0xb0, 0x18, 0x73, 0x8e, 0xfc, 0x8e, 0xec, 0xad, - 0x80, 0x46, 0x7a, 0x2b, 0x2c, 0x18, 0x0a, 0xe5, 0xf0, 0x11, 0x58, 0x74, 0x22, 0x9b, 0x43, 0xf4, - 0x98, 0xe9, 0x69, 0xa9, 0xba, 0x1c, 0xf4, 0xcb, 0x71, 0x77, 0x02, 0x42, 0x97, 0x75, 0xc5, 0x40, - 0xc0, 0x84, 0xdb, 0x98, 0xa0, 0xe0, 0xe0, 0x2e, 0x61, 0x1e, 0xb6, 0x88, 0xba, 0xd2, 0x6d, 0x95, - 0x70, 0xe1, 0xe9, 0x00, 0x40, 0x91, 0xce, 0xf4, 0xcb, 0xc1, 0x37, 0x41, 0xae, 0x49, 0x5d, 0xdf, - 0x93, 0xdd, 0x29, 0xd4, 0x16, 0x94, 0x4a, 0xee, 0x13, 0x21, 0x44, 0x21, 0x06, 0xdf, 0x06, 0xf3, - 0x3d, 0x42, 0x99, 0xed, 0x3a, 0x7a, 0x56, 0xaa, 0x2d, 0x2a, 0xb5, 0xf9, 0xa3, 0x50, 0x8c, 0x06, - 0x38, 0xbc, 0x07, 0xf2, 0x54, 0x25, 0xae, 0xe7, 0xa4, 0xee, 0x92, 0xd2, 0xcd, 0x0f, 0x2b, 0x38, - 0xd4, 0x80, 0xef, 0x83, 0x22, 0xf3, 0xeb, 0x43, 0x83, 0x39, 0x69, 0xb0, 0xac, 0x0c, 0x8a, 0x07, - 0x11, 0x84, 0xe2, 0x7a, 0xe2, 0x5a, 0xe2, 0x8e, 0xfa, 0xfc, 0xe8, 0xb5, 0x44, 0x09, 0x90, 0x44, - 0xaa, 0xbf, 0x6b, 0xe0, 0xd6, 0x6c, 0x1d, 0x7b, 0x07, 0x14, 0xb0, 0x67, 0xcb, 0x6b, 0x0f, 0x7a, - 0xb5, 0x20, 0xea, 0xba, 0xf3, 0x6c, 0x3f, 0x14, 0xa2, 0x08, 0x17, 0xca, 0x83, 0x64, 0xc4, 0x5c, - 0x0f, 0x95, 0x07, 0x21, 0x19, 0x8a, 0x70, 0xb8, 0x05, 0x16, 0x06, 0x07, 0xd9, 0x24, 0x3d, 0x2b, - 0x0d, 0x6e, 0x07, 0xfd, 0xf2, 0x02, 0x8a, 0x03, 0x68, 0x54, 0xaf, 0xfa, 0x5b, 0x1a, 0xac, 0x1e, - 0x90, 0xce, 0xf1, 0xab, 0x79, 0x15, 0xbe, 0x18, 0x79, 0x15, 0x1e, 0x5d, 0x63, 0x6d, 0x93, 0x53, - 0x7d, 0xb5, 0x2f, 0xc3, 0xcf, 0x69, 0xf0, 0xff, 0x2b, 0x12, 0x83, 0xdf, 0x01, 0x48, 0xc7, 0x16, - 0x4d, 0x55, 0xf4, 0xc1, 0xf4, 0x84, 0xc6, 0x97, 0xb4, 0x76, 0x27, 0xe8, 0x97, 0x13, 0x96, 0x17, - 0x25, 0xc4, 0x81, 0xdf, 0x6b, 0x60, 0xc5, 0x49, 0x7a, 0xb8, 0x54, 0xd5, 0xb7, 0xa6, 0x67, 0x90, - 0xf8, 0xee, 0xd5, 0xee, 0x06, 0xfd, 0x72, 0xf2, 0x93, 0x88, 0x92, 0x03, 0x8a, 0x27, 0xe7, 0x4e, - 0xac, 0x50, 0x62, 0x69, 0xfe, 0xbb, 0x59, 0xfb, 0x7c, 0x64, 0xd6, 0x3e, 0x9e, 0x69, 0xd6, 0x62, - 0x99, 0x4e, 0x1c, 0xb5, 0xfa, 0xa5, 0x51, 0xdb, 0xbe, 0xf6, 0xa8, 0xc5, 0xbd, 0x5f, 0x3d, 0x69, - 0x4f, 0xc0, 0xda, 0xe4, 0xac, 0x66, 0x7e, 0xba, 0xab, 0xbf, 0xa4, 0xc1, 0xf2, 0x6b, 0x3a, 0x70, - 0xb3, 0xa5, 0x3f, 0xcf, 0x82, 0xd5, 0xd7, 0x0b, 0x7f, 0xf5, 0xc2, 0x8b, 0x9f, 0xa8, 0xcf, 0x08, - 0x55, 0x3f, 0xfe, 0x61, 0xaf, 0x0e, 0x19, 0xa1, 0x48, 0x22, 0xb0, 0x32, 0xe0, 0x06, 0xe1, 0x0f, - 0x0b, 0x88, 0x4a, 0xab, 0x7f, 0xa1, 0x22, 0x06, 0x36, 0xc8, 0x11, 0xc1, 0x78, 0xf5, 0x5c, 0x25, - 0xb3, 0x5e, 0xdc, 0xdc, 0xbd, 0xf1, 0xac, 0x18, 0x92, 0x38, 0xef, 0x39, 0x9c, 0x9e, 0x46, 0x1c, - 0x44, 0xca, 0x50, 0x18, 0x01, 0xbe, 0x01, 0x32, 0xbe, 0xdd, 0x50, 0x14, 0xa1, 0xa8, 0x54, 0x32, - 0x87, 0xfb, 0xbb, 0x48, 0xc8, 0xd7, 0x8e, 0x15, 0xf7, 0x96, 0x2e, 0xe0, 0x12, 0xc8, 0xb4, 0xc9, - 0x69, 0xb8, 0x67, 0x48, 0x7c, 0xc2, 0x1a, 0xc8, 0xf5, 0x04, 0x2d, 0x57, 0x75, 0xbe, 0x37, 0x3d, - 0xd3, 0x88, 0xca, 0xa3, 0xd0, 0x74, 0x3b, 0xfd, 0x50, 0xab, 0xfe, 0xa1, 0x81, 0xbb, 0x13, 0x07, - 0x52, 0x10, 0x25, 0xdc, 0xe9, 0xb8, 0x27, 0xa4, 0x21, 0x63, 0xe7, 0x23, 0xa2, 0xb4, 0x13, 0x8a, - 0xd1, 0x00, 0x87, 0x6f, 0x81, 0x39, 0x4a, 0x30, 0x73, 0x1d, 0x45, 0xce, 0x86, 0xb3, 0x8c, 0xa4, - 0x14, 0x29, 0x14, 0xee, 0x80, 0x45, 0x22, 0xc2, 0xcb, 0xe4, 0xf6, 0x28, 0x75, 0x07, 0x1d, 0x5b, - 0x55, 0x06, 0x8b, 0x7b, 0xa3, 0x30, 0xba, 0xac, 0x2f, 0x42, 0x35, 0x88, 0x63, 0x93, 0x86, 0x64, - 0x6f, 0xf9, 0x28, 0xd4, 0xae, 0x94, 0x22, 0x85, 0x56, 0xff, 0x49, 0x03, 0x7d, 0xd2, 0xb3, 0x07, - 0xdb, 0x11, 0x8b, 0x91, 0xa0, 0x24, 0x52, 0xc5, 0x4d, 0xe3, 0xfa, 0x2b, 0x23, 0xcc, 0x6a, 0x2b, - 0x2a, 0xf6, 0x42, 0x5c, 0x1a, 0x63, 0x3e, 0xf2, 0x08, 0x4f, 0xc0, 0x92, 0x33, 0x4a, 0xb9, 0x43, - 0x4e, 0x56, 0xdc, 0xdc, 0x98, 0x69, 0x41, 0x64, 0x48, 0x5d, 0x85, 0x5c, 0xba, 0x04, 0x30, 0x34, - 0x16, 0x04, 0x6e, 0x02, 0x60, 0x3b, 0x96, 0xdb, 0xf5, 0x3a, 0x84, 0x13, 0x59, 0xe8, 0x7c, 0xf4, - 0x5a, 0xee, 0x0f, 0x11, 0x14, 0xd3, 0x4a, 0xea, 0x50, 0x76, 0xb6, 0x0e, 0xd5, 0xee, 0x9f, 0x5d, - 0x94, 0x52, 0x2f, 0x2f, 0x4a, 0xa9, 0xf3, 0x8b, 0x52, 0xea, 0x45, 0x50, 0xd2, 0xce, 0x82, 0x92, - 0xf6, 0x32, 0x28, 0x69, 0xe7, 0x41, 0x49, 0xfb, 0x2b, 0x28, 0x69, 0x3f, 0xfc, 0x5d, 0x4a, 0x7d, - 0x36, 0xaf, 0x6e, 0xf8, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xb3, 0x5e, 0x05, 0xd9, 0x0f, - 0x00, 0x00, + // 1137 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0xcb, 0x6f, 0x1b, 0x45, + 0x18, 0xf7, 0xfa, 0x91, 0xd8, 0xe3, 0x86, 0xa4, 0x13, 0xa5, 0xd9, 0x06, 0x61, 0x5b, 0x46, 0x42, + 0x41, 0xb4, 0xbb, 0x24, 0x2a, 0xa4, 0x04, 0x7a, 0x88, 0x95, 0x08, 0x45, 0x6a, 0x4b, 0x35, 0x51, + 0x72, 0xa0, 0x12, 0x30, 0xbb, 0x9e, 0xd8, 0x8b, 0xed, 0xdd, 0x65, 0x66, 0xd6, 0x21, 0x88, 0x43, + 0x8f, 0x1c, 0x39, 0x72, 0xe4, 0xc4, 0xff, 0xc0, 0x05, 0x09, 0x4e, 0x39, 0xf6, 0x18, 0x24, 0x64, + 0x91, 0xe5, 0x8f, 0xe0, 0x8a, 0x66, 0x76, 0xec, 0x5d, 0x27, 0x9b, 0x38, 0xce, 0x81, 0x5e, 0x7a, + 0xdb, 0xf9, 0x7e, 0xdf, 0xfb, 0xb5, 0x1f, 0xd8, 0xed, 0x3c, 0x64, 0x86, 0xe3, 0x99, 0x9d, 0xc0, + 0x22, 0xd4, 0x25, 0x9c, 0x30, 0xb3, 0x4f, 0xdc, 0xa6, 0x47, 0x4d, 0x05, 0x60, 0xdf, 0x31, 0x71, + 0xc0, 0xdb, 0x1e, 0x75, 0xbe, 0xc3, 0xdc, 0xf1, 0x5c, 0xb3, 0xbf, 0x66, 0x11, 0x8e, 0xd7, 0xcc, + 0x16, 0x71, 0x09, 0xc5, 0x9c, 0x34, 0x0d, 0x9f, 0x7a, 0xdc, 0x83, 0xb5, 0x48, 0xc2, 0xc0, 0xbe, + 0x63, 0x8c, 0x49, 0x18, 0x4a, 0x62, 0xe5, 0x7e, 0xcb, 0xe1, 0xed, 0xc0, 0x32, 0x6c, 0xaf, 0x67, + 0xb6, 0xbc, 0x96, 0x67, 0x4a, 0x41, 0x2b, 0x38, 0x94, 0x2f, 0xf9, 0x90, 0x5f, 0x91, 0xc2, 0x95, + 0x07, 0xb1, 0x0b, 0x3d, 0x6c, 0xb7, 0x1d, 0x97, 0xd0, 0x63, 0xd3, 0xef, 0xb4, 0x04, 0x81, 0x99, + 0x3d, 0xc2, 0xb1, 0xd9, 0xbf, 0xe0, 0xc6, 0x8a, 0x79, 0x99, 0x14, 0x0d, 0x5c, 0xee, 0xf4, 0xc8, + 0x05, 0x81, 0x0f, 0x27, 0x09, 0x30, 0xbb, 0x4d, 0x7a, 0xf8, 0xbc, 0x5c, 0x7d, 0x03, 0x80, 0x9d, + 0x6f, 0x39, 0xc5, 0x07, 0xb8, 0x1b, 0x10, 0x58, 0x05, 0x05, 0x87, 0x93, 0x1e, 0xd3, 0xb5, 0x5a, + 0x6e, 0xb5, 0xd4, 0x28, 0x85, 0x83, 0x6a, 0x61, 0x57, 0x10, 0x50, 0x44, 0xdf, 0x2c, 0xfe, 0xf4, + 0x73, 0x35, 0xf3, 0xe2, 0xaf, 0x5a, 0xa6, 0xfe, 0x5b, 0x16, 0xe8, 0x8f, 0x3d, 0x1b, 0x77, 0xf7, + 0x02, 0xeb, 0x6b, 0x62, 0xf3, 0x2d, 0xdb, 0x26, 0x8c, 0x21, 0xd2, 0x77, 0xc8, 0x11, 0xfc, 0x0a, + 0x14, 0x45, 0x64, 0x4d, 0xcc, 0xb1, 0xae, 0xd5, 0xb4, 0xd5, 0xf2, 0xfa, 0xfb, 0x46, 0x9c, 0xd8, + 0x91, 0x83, 0x86, 0xdf, 0x69, 0x09, 0x02, 0x33, 0x04, 0xb7, 0xd1, 0x5f, 0x33, 0x3e, 0x93, 0xba, + 0x9e, 0x10, 0x8e, 0x1b, 0xf0, 0x64, 0x50, 0xcd, 0x84, 0x83, 0x2a, 0x88, 0x69, 0x68, 0xa4, 0x15, + 0x3e, 0x07, 0x79, 0xe6, 0x13, 0x5b, 0xcf, 0x4a, 0xed, 0x1f, 0x19, 0x93, 0xca, 0x66, 0xa4, 0xb8, + 0xb9, 0xe7, 0x13, 0xbb, 0x71, 0x4b, 0x99, 0xc9, 0x8b, 0x17, 0x92, 0x4a, 0xa1, 0x0d, 0x66, 0x18, + 0xc7, 0x3c, 0x60, 0x7a, 0x4e, 0xaa, 0xff, 0xf8, 0x66, 0xea, 0xa5, 0x8a, 0xc6, 0x1b, 0xca, 0xc0, + 0x4c, 0xf4, 0x46, 0x4a, 0x75, 0xfd, 0x39, 0x58, 0x7a, 0xea, 0xb9, 0x88, 0x30, 0x2f, 0xa0, 0x36, + 0xd9, 0xe2, 0x9c, 0x3a, 0x56, 0xc0, 0x09, 0x83, 0x35, 0x90, 0xf7, 0x31, 0x6f, 0xcb, 0xc4, 0x95, + 0x62, 0xff, 0x9e, 0x61, 0xde, 0x46, 0x12, 0x11, 0x1c, 0x7d, 0x42, 0x2d, 0x19, 0x7c, 0x82, 0xe3, + 0x80, 0x50, 0x0b, 0x49, 0xa4, 0xfe, 0x0d, 0x98, 0x4f, 0x28, 0x47, 0x41, 0x57, 0xd6, 0x56, 0x40, + 0x63, 0xb5, 0x15, 0x12, 0x0c, 0x45, 0x74, 0xf8, 0x08, 0xcc, 0xbb, 0xb1, 0xcc, 0x3e, 0x7a, 0xcc, + 0xf4, 0xac, 0x64, 0x5d, 0x0c, 0x07, 0xd5, 0xa4, 0x3a, 0x01, 0xa1, 0xf3, 0xbc, 0xa2, 0x21, 0x60, + 0x4a, 0x34, 0x26, 0x28, 0xb9, 0xb8, 0x47, 0x98, 0x8f, 0x6d, 0xa2, 0x42, 0xba, 0xad, 0x1c, 0x2e, + 0x3d, 0x1d, 0x02, 0x28, 0xe6, 0x99, 0x1c, 0x1c, 0x7c, 0x1b, 0x14, 0x5a, 0xd4, 0x0b, 0x7c, 0x59, + 0x9d, 0x52, 0x63, 0x4e, 0xb1, 0x14, 0x3e, 0x15, 0x44, 0x14, 0x61, 0xf0, 0x5d, 0x30, 0xdb, 0x27, + 0x94, 0x39, 0x9e, 0xab, 0xe7, 0x25, 0xdb, 0xbc, 0x62, 0x9b, 0x3d, 0x88, 0xc8, 0x68, 0x88, 0xc3, + 0x7b, 0xa0, 0x48, 0x95, 0xe3, 0x7a, 0x41, 0xf2, 0x2e, 0x28, 0xde, 0xe2, 0x28, 0x83, 0x23, 0x0e, + 0xf8, 0x01, 0x28, 0xb3, 0xc0, 0x1a, 0x09, 0xcc, 0x48, 0x81, 0x45, 0x25, 0x50, 0xde, 0x8b, 0x21, + 0x94, 0xe4, 0x13, 0x61, 0x89, 0x18, 0xf5, 0xd9, 0xf1, 0xb0, 0x44, 0x0a, 0x90, 0x44, 0xea, 0x7f, + 0x68, 0xe0, 0xd6, 0x74, 0x15, 0x7b, 0x0f, 0x94, 0xb0, 0xef, 0xc8, 0xb0, 0x87, 0xb5, 0x9a, 0x13, + 0x79, 0xdd, 0x7a, 0xb6, 0x1b, 0x11, 0x51, 0x8c, 0x0b, 0xe6, 0xa1, 0x33, 0xa2, 0xaf, 0x47, 0xcc, + 0x43, 0x93, 0x0c, 0xc5, 0x38, 0xdc, 0x00, 0x73, 0xc3, 0x87, 0x2c, 0x92, 0x9e, 0x97, 0x02, 0xb7, + 0xc3, 0x41, 0x75, 0x0e, 0x25, 0x01, 0x34, 0xce, 0x57, 0xff, 0x3d, 0x0b, 0x96, 0xf7, 0x48, 0xf7, + 0xf0, 0xd5, 0x6c, 0x85, 0x2f, 0xc7, 0xb6, 0xc2, 0xa3, 0x6b, 0x8c, 0x6d, 0xba, 0xab, 0xaf, 0x76, + 0x33, 0xfc, 0x92, 0x05, 0x6f, 0x5e, 0xe1, 0x18, 0xfc, 0x1e, 0x40, 0x7a, 0x61, 0xd0, 0x54, 0x46, + 0x1f, 0x4c, 0x76, 0xe8, 0xe2, 0x90, 0x36, 0xee, 0x84, 0x83, 0x6a, 0xca, 0xf0, 0xa2, 0x14, 0x3b, + 0xf0, 0x07, 0x0d, 0x2c, 0xb9, 0x69, 0x8b, 0x4b, 0x65, 0x7d, 0x63, 0xb2, 0x07, 0xa9, 0x7b, 0xaf, + 0x71, 0x37, 0x1c, 0x54, 0xd3, 0x57, 0x22, 0x4a, 0x37, 0x28, 0x56, 0xce, 0x9d, 0x44, 0xa2, 0xc4, + 0xd0, 0xfc, 0x7f, 0xbd, 0xf6, 0xc5, 0x58, 0xaf, 0x7d, 0x32, 0x55, 0xaf, 0x25, 0x3c, 0xbd, 0xb4, + 0xd5, 0xac, 0x73, 0xad, 0xb6, 0x79, 0xed, 0x56, 0x4b, 0x6a, 0xbf, 0xba, 0xd3, 0x9e, 0x80, 0x95, + 0xcb, 0xbd, 0x9a, 0x7a, 0x75, 0xd7, 0x7f, 0xcd, 0x82, 0xc5, 0xd7, 0xe7, 0xc0, 0xcd, 0x86, 0xfe, + 0x34, 0x0f, 0x96, 0x5f, 0x0f, 0xfc, 0xd5, 0x03, 0x2f, 0x7e, 0xa2, 0x01, 0x23, 0x54, 0xfd, 0xf8, + 0x47, 0xb5, 0xda, 0x67, 0x84, 0x22, 0x89, 0xc0, 0xda, 0xf0, 0x36, 0x88, 0x7e, 0x58, 0x40, 0x64, + 0x5a, 0xfd, 0x0b, 0xd5, 0x61, 0xe0, 0x80, 0x02, 0x11, 0x17, 0xaf, 0x5e, 0xa8, 0xe5, 0x56, 0xcb, + 0xeb, 0xdb, 0x37, 0xee, 0x15, 0x43, 0x1e, 0xce, 0x3b, 0x2e, 0xa7, 0xc7, 0xf1, 0x0d, 0x22, 0x69, + 0x28, 0xb2, 0x00, 0xdf, 0x02, 0xb9, 0xc0, 0x69, 0xaa, 0x13, 0xa1, 0xac, 0x58, 0x72, 0xfb, 0xbb, + 0xdb, 0x48, 0xd0, 0x57, 0x0e, 0xd5, 0xed, 0x2d, 0x55, 0xc0, 0x05, 0x90, 0xeb, 0x90, 0xe3, 0x68, + 0xce, 0x90, 0xf8, 0x84, 0x0d, 0x50, 0xe8, 0x8b, 0xb3, 0x5c, 0xe5, 0xf9, 0xde, 0x64, 0x4f, 0xe3, + 0x53, 0x1e, 0x45, 0xa2, 0x9b, 0xd9, 0x87, 0x5a, 0xfd, 0x4f, 0x0d, 0xdc, 0xbd, 0xb4, 0x21, 0xc5, + 0xa1, 0x84, 0xbb, 0x5d, 0xef, 0x88, 0x34, 0xa5, 0xed, 0x62, 0x7c, 0x28, 0x6d, 0x45, 0x64, 0x34, + 0xc4, 0xe1, 0x3b, 0x60, 0x86, 0x12, 0xcc, 0x3c, 0x57, 0x1d, 0x67, 0xa3, 0x5e, 0x46, 0x92, 0x8a, + 0x14, 0x0a, 0xb7, 0xc0, 0x3c, 0x11, 0xe6, 0xa5, 0x73, 0x3b, 0x94, 0x7a, 0xc3, 0x8a, 0x2d, 0x2b, + 0x81, 0xf9, 0x9d, 0x71, 0x18, 0x9d, 0xe7, 0x17, 0xa6, 0x9a, 0xc4, 0x75, 0x48, 0x53, 0x5e, 0x6f, + 0xc5, 0xd8, 0xd4, 0xb6, 0xa4, 0x22, 0x85, 0xd6, 0xff, 0xcd, 0x02, 0xfd, 0xb2, 0xb5, 0x07, 0x3b, + 0xf1, 0x15, 0x23, 0x41, 0x79, 0x48, 0x95, 0xd7, 0x8d, 0xeb, 0x8f, 0x8c, 0x10, 0x6b, 0x2c, 0x29, + 0xdb, 0x73, 0x49, 0x6a, 0xe2, 0xf2, 0x91, 0x4f, 0x78, 0x04, 0x16, 0xdc, 0xf1, 0x93, 0x3b, 0xba, + 0xc9, 0xca, 0xeb, 0x6b, 0x53, 0x0d, 0x88, 0x34, 0xa9, 0x2b, 0x93, 0x0b, 0xe7, 0x00, 0x86, 0x2e, + 0x18, 0x81, 0xeb, 0x00, 0x38, 0xae, 0xed, 0xf5, 0xfc, 0x2e, 0xe1, 0x44, 0x26, 0xba, 0x18, 0x6f, + 0xcb, 0xdd, 0x11, 0x82, 0x12, 0x5c, 0x69, 0x15, 0xca, 0x4f, 0x57, 0xa1, 0xc6, 0xfd, 0x93, 0xb3, + 0x4a, 0xe6, 0xe5, 0x59, 0x25, 0x73, 0x7a, 0x56, 0xc9, 0xbc, 0x08, 0x2b, 0xda, 0x49, 0x58, 0xd1, + 0x5e, 0x86, 0x15, 0xed, 0x34, 0xac, 0x68, 0x7f, 0x87, 0x15, 0xed, 0xc7, 0x7f, 0x2a, 0x99, 0xcf, + 0x67, 0x55, 0x84, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xc5, 0xba, 0xf8, 0x96, 0xa4, 0x0f, 0x00, + 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/generated.proto index b64c0642c..3876a3eeb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.authorization.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go index 2371b21c6..3ae6e7206 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_LocalSubjectAccessReview = map[string]string{ "": "LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions checking.", "spec": "Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace you made the request against. If empty, it is defaulted.", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/zz_generated.deepcopy.go index 7c76b183b..eb14973cd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/authorization/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/generated.pb.go index 9e2b235eb..8d67ef976 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -4323,98 +4323,97 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1485 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcb, 0x6f, 0x14, 0x47, - 0x13, 0xf7, 0x3e, 0x6c, 0xec, 0x5e, 0x63, 0xf3, 0x35, 0x08, 0x8c, 0xf9, 0xd8, 0xb1, 0xe6, 0x43, - 0x88, 0x2f, 0x09, 0x33, 0xb1, 0x21, 0x88, 0x1c, 0xbd, 0x9b, 0x10, 0x50, 0xbc, 0x60, 0xda, 0x86, - 0x90, 0x87, 0x22, 0xda, 0xb3, 0xcd, 0xba, 0xf1, 0xce, 0xcc, 0xaa, 0xa7, 0x77, 0x85, 0x91, 0x22, - 0x25, 0x87, 0x9c, 0x13, 0x45, 0x4a, 0x94, 0x63, 0xfe, 0x81, 0x9c, 0x39, 0x27, 0x52, 0x24, 0x8e, - 0x1c, 0x72, 0xe0, 0x34, 0x0a, 0x93, 0x63, 0xfe, 0x03, 0x4e, 0x51, 0x3f, 0x76, 0x76, 0x66, 0x77, - 0x67, 0xfd, 0xc0, 0x58, 0xc9, 0x6d, 0x7a, 0xaa, 0xea, 0x57, 0xdd, 0x55, 0xd5, 0xf5, 0x68, 0x50, - 0xd9, 0xba, 0x1a, 0x58, 0xd4, 0xb7, 0xb7, 0xda, 0x1b, 0x84, 0x79, 0x84, 0x93, 0xc0, 0xee, 0x10, - 0xaf, 0xee, 0x33, 0x5b, 0x13, 0x70, 0x8b, 0xda, 0xb8, 0xcd, 0xfd, 0xc0, 0xc1, 0x4d, 0xea, 0x35, - 0xec, 0xce, 0xa2, 0xdd, 0x20, 0x1e, 0x61, 0x98, 0x93, 0xba, 0xd5, 0x62, 0x3e, 0xf7, 0xe1, 0x69, - 0xc5, 0x6a, 0xe1, 0x16, 0xb5, 0x12, 0xac, 0x56, 0x67, 0x71, 0xfe, 0x62, 0x83, 0xf2, 0xcd, 0xf6, - 0x86, 0xe5, 0xf8, 0xae, 0xdd, 0xf0, 0x1b, 0xbe, 0x2d, 0x25, 0x36, 0xda, 0x0f, 0xe4, 0x4a, 0x2e, - 0xe4, 0x97, 0x42, 0x9a, 0x37, 0x13, 0x4a, 0x1d, 0x9f, 0x91, 0x21, 0xda, 0xe6, 0x2f, 0xf7, 0x78, - 0x5c, 0xec, 0x6c, 0x52, 0x8f, 0xb0, 0x6d, 0xbb, 0xb5, 0xd5, 0x90, 0x42, 0x8c, 0x04, 0x7e, 0x9b, - 0x39, 0x64, 0x4f, 0x52, 0x81, 0xed, 0x12, 0x8e, 0x87, 0xe9, 0xb2, 0xb3, 0xa4, 0x58, 0xdb, 0xe3, - 0xd4, 0x1d, 0x54, 0x73, 0x65, 0x27, 0x81, 0xc0, 0xd9, 0x24, 0x2e, 0x1e, 0x90, 0xbb, 0x94, 0x25, - 0xd7, 0xe6, 0xb4, 0x69, 0x53, 0x8f, 0x07, 0x9c, 0xf5, 0x0b, 0x99, 0xdf, 0xe7, 0xc0, 0x99, 0x2a, - 0xf3, 0x83, 0xe0, 0x2e, 0x61, 0x01, 0xf5, 0xbd, 0x5b, 0x1b, 0x0f, 0x89, 0xc3, 0x11, 0x79, 0x40, - 0x18, 0xf1, 0x1c, 0x02, 0x17, 0x40, 0x71, 0x8b, 0x7a, 0xf5, 0xb9, 0xdc, 0x42, 0xee, 0xc2, 0x54, - 0x65, 0xfa, 0x69, 0x68, 0x8c, 0x45, 0xa1, 0x51, 0xfc, 0x90, 0x7a, 0x75, 0x24, 0x29, 0x82, 0xc3, - 0xc3, 0x2e, 0x99, 0xcb, 0xa7, 0x39, 0x6e, 0x62, 0x97, 0x20, 0x49, 0x81, 0x4b, 0x00, 0xe0, 0x16, - 0xd5, 0x0a, 0xe6, 0x0a, 0x92, 0x0f, 0x6a, 0x3e, 0xb0, 0xbc, 0x7a, 0x43, 0x53, 0x50, 0x82, 0xcb, - 0xfc, 0xa1, 0x00, 0x4e, 0xbc, 0xff, 0x88, 0x13, 0xe6, 0xe1, 0x66, 0x8d, 0x70, 0x46, 0x9d, 0x35, - 0xe9, 0x14, 0x01, 0xe6, 0xca, 0xb5, 0x50, 0xa0, 0xb7, 0x15, 0x83, 0xd5, 0x62, 0x0a, 0x4a, 0x70, - 0x41, 0x1f, 0xcc, 0xa8, 0xd5, 0x1a, 0x69, 0x12, 0x87, 0xfb, 0x4c, 0x6e, 0xb6, 0xb4, 0x74, 0xc9, - 0xea, 0x45, 0x5d, 0x6c, 0x32, 0xab, 0xb5, 0xd5, 0x10, 0x3f, 0x02, 0x4b, 0x78, 0xd4, 0xea, 0x2c, - 0x5a, 0x2b, 0x78, 0x83, 0x34, 0xbb, 0xa2, 0x15, 0x18, 0x85, 0xc6, 0x4c, 0x2d, 0x05, 0x87, 0xfa, - 0xe0, 0x21, 0x06, 0x25, 0x8e, 0x59, 0x83, 0xf0, 0xbb, 0xb8, 0xd9, 0x26, 0xf2, 0xc8, 0xa5, 0x25, - 0x6b, 0x94, 0x36, 0xab, 0x1b, 0x75, 0xd6, 0xed, 0x36, 0xf6, 0x38, 0xe5, 0xdb, 0x95, 0xd9, 0x28, - 0x34, 0x4a, 0xeb, 0x3d, 0x18, 0x94, 0xc4, 0x84, 0x1d, 0x00, 0xd5, 0x72, 0xb9, 0x43, 0x18, 0x6e, - 0x10, 0xa5, 0xa9, 0xb8, 0x2f, 0x4d, 0x27, 0xa3, 0xd0, 0x80, 0xeb, 0x03, 0x68, 0x68, 0x88, 0x06, - 0xf3, 0xa7, 0x41, 0xc7, 0x70, 0xcc, 0xdb, 0xc1, 0xbf, 0xc3, 0x31, 0x9b, 0x60, 0xda, 0x69, 0x33, - 0x46, 0xbc, 0x57, 0xf2, 0xcc, 0x09, 0x7d, 0xac, 0xe9, 0x6a, 0x02, 0x0b, 0xa5, 0x90, 0xe1, 0x36, - 0x38, 0xae, 0xd7, 0x07, 0xe0, 0xa0, 0x53, 0x51, 0x68, 0x1c, 0xaf, 0x0e, 0xc2, 0xa1, 0x61, 0x3a, - 0xcc, 0x27, 0x79, 0x70, 0xea, 0xba, 0xcf, 0xe8, 0x63, 0xdf, 0xe3, 0xb8, 0xb9, 0xea, 0xd7, 0x97, - 0x75, 0x42, 0x25, 0x0c, 0xde, 0x07, 0x93, 0xc2, 0x7a, 0x75, 0xcc, 0xb1, 0xf4, 0x51, 0x69, 0xe9, - 0xed, 0xdd, 0xd9, 0x5a, 0x25, 0x86, 0x1a, 0xe1, 0xb8, 0xe7, 0xd5, 0xde, 0x3f, 0x14, 0xa3, 0xc2, - 0x7b, 0xa0, 0x18, 0xb4, 0x88, 0xa3, 0x3d, 0x79, 0xc5, 0xca, 0x4c, 0xec, 0x56, 0xc6, 0x1e, 0xd7, - 0x5a, 0xc4, 0xe9, 0xe5, 0x11, 0xb1, 0x42, 0x12, 0x11, 0xde, 0x07, 0x13, 0x81, 0x8c, 0x35, 0xed, - 0xb6, 0xab, 0xfb, 0xc0, 0x96, 0xf2, 0x95, 0x19, 0x8d, 0x3e, 0xa1, 0xd6, 0x48, 0xe3, 0x9a, 0x5f, - 0x17, 0xc0, 0x42, 0x86, 0x64, 0xd5, 0xf7, 0xea, 0x94, 0x53, 0xdf, 0x83, 0xd7, 0x41, 0x91, 0x6f, - 0xb7, 0xba, 0x21, 0x7e, 0xb9, 0xbb, 0xd1, 0xf5, 0xed, 0x16, 0x79, 0x19, 0x1a, 0xe7, 0x76, 0x92, - 0x17, 0x7c, 0x48, 0x22, 0xc0, 0x95, 0xf8, 0x40, 0xf9, 0x14, 0x96, 0xde, 0xd6, 0xcb, 0xd0, 0x18, - 0x52, 0xcc, 0xac, 0x18, 0x29, 0xbd, 0x79, 0x91, 0x11, 0x9a, 0x38, 0xe0, 0xeb, 0x0c, 0x7b, 0x81, - 0xd2, 0x44, 0xdd, 0x6e, 0x84, 0xbf, 0xb1, 0x3b, 0x27, 0x0b, 0x89, 0xca, 0xbc, 0xde, 0x05, 0x5c, - 0x19, 0x40, 0x43, 0x43, 0x34, 0xc0, 0xf3, 0x60, 0x82, 0x11, 0x1c, 0xf8, 0x9e, 0x0c, 0xee, 0xa9, - 0x9e, 0x71, 0x91, 0xfc, 0x8b, 0x34, 0x15, 0xfe, 0x1f, 0x1c, 0x71, 0x49, 0x10, 0xe0, 0x06, 0x99, - 0x1b, 0x97, 0x8c, 0xb3, 0x9a, 0xf1, 0x48, 0x4d, 0xfd, 0x46, 0x5d, 0xba, 0xf9, 0x7b, 0x0e, 0x9c, - 0xc9, 0xb0, 0xe3, 0x0a, 0x0d, 0x38, 0xfc, 0x6c, 0x20, 0x8a, 0xad, 0x5d, 0x66, 0x0c, 0x1a, 0xa8, - 0x18, 0x3e, 0xa6, 0x75, 0x4f, 0x76, 0xff, 0x24, 0x22, 0xf8, 0x23, 0x30, 0x4e, 0x39, 0x71, 0x85, - 0x57, 0x0a, 0x17, 0x4a, 0x4b, 0x4b, 0x7b, 0x0f, 0xb3, 0xca, 0x51, 0x0d, 0x3f, 0x7e, 0x43, 0x00, - 0x21, 0x85, 0x67, 0xfe, 0x95, 0xcf, 0x3c, 0x96, 0x08, 0x73, 0xd8, 0x01, 0x33, 0x72, 0xa5, 0x52, - 0x31, 0x22, 0x0f, 0xf4, 0xe1, 0x46, 0x5d, 0xa2, 0x11, 0xc5, 0xbb, 0x72, 0x52, 0xef, 0x62, 0x66, - 0x2d, 0x85, 0x8a, 0xfa, 0xb4, 0xc0, 0x45, 0x50, 0x72, 0xa9, 0x87, 0x48, 0xab, 0x49, 0x1d, 0xac, - 0x82, 0x71, 0x5c, 0x95, 0x9f, 0x5a, 0xef, 0x37, 0x4a, 0xf2, 0xc0, 0x77, 0x40, 0xc9, 0xc5, 0x8f, - 0x62, 0x91, 0x82, 0x14, 0x39, 0xae, 0xf5, 0x95, 0x6a, 0x3d, 0x12, 0x4a, 0xf2, 0xc1, 0x87, 0xa0, - 0xac, 0x6a, 0x4a, 0x75, 0xf5, 0xce, 0x1d, 0x4e, 0x9b, 0xf4, 0x31, 0x16, 0x71, 0xb4, 0x4a, 0x98, - 0x43, 0x3c, 0x2e, 0x42, 0xa3, 0x28, 0x91, 0xcc, 0x28, 0x34, 0xca, 0xeb, 0x23, 0x39, 0xd1, 0x0e, - 0x48, 0xe6, 0x2f, 0x05, 0x70, 0x76, 0x64, 0x1a, 0x80, 0xd7, 0x00, 0xf4, 0x37, 0x02, 0xc2, 0x3a, - 0xa4, 0xfe, 0x81, 0xea, 0x8b, 0x44, 0x83, 0x22, 0x6c, 0x5e, 0x50, 0x35, 0xf1, 0xd6, 0x00, 0x15, - 0x0d, 0x91, 0x80, 0x0e, 0x38, 0x2a, 0xee, 0x85, 0xb2, 0x32, 0xd5, 0xbd, 0xd0, 0xde, 0x2e, 0xdd, - 0x7f, 0xa2, 0xd0, 0x38, 0xba, 0x92, 0x04, 0x41, 0x69, 0x4c, 0xb8, 0x0c, 0x66, 0x75, 0xb2, 0xef, - 0xb3, 0xfa, 0x29, 0x6d, 0xf5, 0xd9, 0x6a, 0x9a, 0x8c, 0xfa, 0xf9, 0x05, 0x44, 0x9d, 0x04, 0x94, - 0x91, 0x7a, 0x0c, 0x51, 0x4c, 0x43, 0xbc, 0x97, 0x26, 0xa3, 0x7e, 0x7e, 0xe8, 0x02, 0x43, 0xa3, - 0x66, 0x7a, 0x70, 0x5c, 0x42, 0xfe, 0x2f, 0x0a, 0x0d, 0xa3, 0x3a, 0x9a, 0x15, 0xed, 0x84, 0x25, - 0xda, 0x40, 0xdd, 0x3b, 0xc8, 0x0b, 0x72, 0x39, 0x95, 0x7a, 0x17, 0xfa, 0x52, 0xef, 0xb1, 0x64, - 0xa3, 0x98, 0x48, 0xb3, 0xb7, 0xc1, 0x84, 0x2f, 0x6f, 0x86, 0xf6, 0xcb, 0xc5, 0x11, 0xd7, 0x29, - 0x2e, 0x69, 0x31, 0x50, 0x05, 0x88, 0x5c, 0xa6, 0xaf, 0x96, 0x06, 0x82, 0x37, 0x40, 0xb1, 0xe5, - 0xd7, 0xbb, 0x85, 0xe8, 0xcd, 0x11, 0x80, 0xab, 0x7e, 0x3d, 0x48, 0xc1, 0x4d, 0x8a, 0x1d, 0x8b, - 0xbf, 0x48, 0x42, 0xc0, 0x8f, 0xc1, 0x64, 0xb7, 0xe0, 0xeb, 0xee, 0xc0, 0x1e, 0x01, 0x87, 0x34, - 0x6b, 0x0a, 0x72, 0x5a, 0x24, 0xb2, 0x2e, 0x05, 0xc5, 0x70, 0x02, 0x9a, 0xe8, 0x56, 0x4d, 0x7a, - 0x65, 0x34, 0xf4, 0xb0, 0x76, 0x5b, 0x41, 0x77, 0x29, 0x28, 0x86, 0x33, 0x7f, 0x2c, 0x80, 0xe9, - 0x54, 0xfb, 0x77, 0xc8, 0xae, 0x51, 0x75, 0xfc, 0xc0, 0x5c, 0xa3, 0xe0, 0x0e, 0xd4, 0x35, 0x0a, - 0xf2, 0xb5, 0xb8, 0x26, 0x01, 0x3d, 0xc4, 0x35, 0xdf, 0xe4, 0x01, 0x1c, 0x0c, 0x63, 0xf8, 0x39, - 0x98, 0x50, 0x09, 0xf3, 0x15, 0x8b, 0x4a, 0x5c, 0xde, 0x75, 0xfd, 0xd0, 0xa8, 0x7d, 0xfd, 0x7f, - 0x7e, 0x57, 0xfd, 0x3f, 0x39, 0x88, 0x39, 0x29, 0xae, 0x3a, 0x59, 0xb3, 0x92, 0xf9, 0x5d, 0xbf, - 0x45, 0x54, 0xc8, 0xfe, 0x13, 0x2d, 0x72, 0x68, 0x03, 0x8a, 0xf9, 0x6b, 0x0e, 0x1c, 0xeb, 0x4f, - 0x4e, 0xfb, 0x1a, 0xe2, 0x1e, 0x0f, 0x9d, 0x44, 0xf3, 0xfb, 0xda, 0x78, 0xdc, 0x7b, 0xee, 0x72, - 0x1a, 0xfd, 0x2d, 0x7d, 0x88, 0xfd, 0x4f, 0xa2, 0x5f, 0x0c, 0x1f, 0xd7, 0xf6, 0x77, 0x8a, 0x33, - 0x5a, 0xd9, 0xee, 0x47, 0xb6, 0x9f, 0xf3, 0xe0, 0xc4, 0xb0, 0xd4, 0x0e, 0xab, 0xfa, 0x75, 0x45, - 0x9d, 0xc2, 0x4e, 0xbe, 0xae, 0xbc, 0x0c, 0x0d, 0x63, 0xc8, 0x78, 0xd0, 0x85, 0x49, 0x3c, 0xc0, - 0xdc, 0x03, 0x73, 0x29, 0xdb, 0x25, 0x6a, 0xad, 0x6e, 0xf6, 0xfe, 0x1b, 0x85, 0xc6, 0xdc, 0x7a, - 0x06, 0x0f, 0xca, 0x94, 0xce, 0x78, 0x85, 0x28, 0xbc, 0xf6, 0x57, 0x88, 0x27, 0x83, 0xf6, 0x52, - 0xbe, 0x3f, 0x10, 0x7b, 0x7d, 0x0a, 0x4e, 0xa7, 0x9d, 0x34, 0x68, 0xb0, 0xb3, 0x51, 0x68, 0x9c, - 0xae, 0x66, 0x31, 0xa1, 0x6c, 0xf9, 0xac, 0x48, 0x2b, 0x1c, 0x52, 0xa4, 0x7d, 0x95, 0x07, 0xe3, - 0xb2, 0xa9, 0x3c, 0x84, 0xa7, 0x80, 0x6b, 0xa9, 0xa7, 0x80, 0x73, 0x23, 0xd2, 0xab, 0xdc, 0x51, - 0xe6, 0xe0, 0x7f, 0xb3, 0x6f, 0xf0, 0x3f, 0xbf, 0x23, 0xd2, 0xe8, 0x31, 0xff, 0x5d, 0x30, 0x15, - 0x2b, 0x84, 0x6f, 0x89, 0x22, 0xaf, 0xbb, 0xe1, 0x9c, 0xf4, 0x6d, 0x3c, 0x1b, 0xc6, 0x6d, 0x70, - 0xcc, 0x61, 0x52, 0x50, 0x4a, 0x68, 0xd8, 0x9b, 0xb0, 0xe0, 0x0e, 0x92, 0x0f, 0x5d, 0x53, 0x3d, - 0xee, 0xf8, 0xc5, 0x2a, 0xe6, 0xa8, 0x5c, 0x78, 0xfa, 0xa2, 0x3c, 0xf6, 0xec, 0x45, 0x79, 0xec, - 0xf9, 0x8b, 0xf2, 0xd8, 0x97, 0x51, 0x39, 0xf7, 0x34, 0x2a, 0xe7, 0x9e, 0x45, 0xe5, 0xdc, 0xf3, - 0xa8, 0x9c, 0xfb, 0x23, 0x2a, 0xe7, 0xbe, 0xfd, 0xb3, 0x3c, 0xf6, 0x49, 0xbe, 0xb3, 0xf8, 0x77, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x61, 0x55, 0xfd, 0xeb, 0x81, 0x17, 0x00, 0x00, + // 1471 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0x4b, 0x6f, 0x14, 0xc7, + 0x13, 0xf7, 0x3e, 0x6c, 0xec, 0x5e, 0x63, 0xf3, 0x6f, 0x10, 0x18, 0xf3, 0x67, 0xc7, 0x9a, 0x20, + 0x44, 0x1e, 0xcc, 0xc6, 0x0e, 0x41, 0xe4, 0xe8, 0xdd, 0x84, 0x80, 0xe2, 0x05, 0xd3, 0x36, 0x84, + 0x3c, 0x14, 0xd1, 0x9e, 0x6d, 0xd6, 0x8d, 0x77, 0x66, 0x56, 0x3d, 0xbd, 0x2b, 0x8c, 0x14, 0x29, + 0x39, 0xe4, 0x9c, 0x28, 0x52, 0xa2, 0x1c, 0xf3, 0x05, 0x72, 0xe6, 0x9c, 0x48, 0x91, 0x38, 0x72, + 0xc8, 0x81, 0xd3, 0x28, 0x4c, 0x8e, 0xf9, 0x06, 0x9c, 0xa2, 0x7e, 0xec, 0xec, 0xcc, 0xee, 0xcc, + 0xfa, 0x81, 0xb1, 0x92, 0xdb, 0xf4, 0x54, 0xd5, 0xaf, 0xba, 0xab, 0xaa, 0xeb, 0xd1, 0xa0, 0xba, + 0x75, 0xc5, 0xb7, 0xa8, 0x57, 0xd9, 0xea, 0x6c, 0x10, 0xe6, 0x12, 0x4e, 0xfc, 0x4a, 0x97, 0xb8, + 0x0d, 0x8f, 0x55, 0x34, 0x01, 0xb7, 0x69, 0x05, 0x77, 0xb8, 0xe7, 0xdb, 0xb8, 0x45, 0xdd, 0x66, + 0xa5, 0xbb, 0x58, 0x69, 0x12, 0x97, 0x30, 0xcc, 0x49, 0xc3, 0x6a, 0x33, 0x8f, 0x7b, 0xf0, 0xb4, + 0x62, 0xb5, 0x70, 0x9b, 0x5a, 0x31, 0x56, 0xab, 0xbb, 0x38, 0x7f, 0xb1, 0x49, 0xf9, 0x66, 0x67, + 0xc3, 0xb2, 0x3d, 0xa7, 0xd2, 0xf4, 0x9a, 0x5e, 0x45, 0x4a, 0x6c, 0x74, 0xee, 0xcb, 0x95, 0x5c, + 0xc8, 0x2f, 0x85, 0x34, 0x6f, 0xc6, 0x94, 0xda, 0x1e, 0x23, 0x29, 0xda, 0xe6, 0x2f, 0xf5, 0x79, + 0x1c, 0x6c, 0x6f, 0x52, 0x97, 0xb0, 0xed, 0x4a, 0x7b, 0xab, 0x29, 0x85, 0x18, 0xf1, 0xbd, 0x0e, + 0xb3, 0xc9, 0x9e, 0xa4, 0xfc, 0x8a, 0x43, 0x38, 0x4e, 0xd3, 0x55, 0xc9, 0x92, 0x62, 0x1d, 0x97, + 0x53, 0x67, 0x58, 0xcd, 0xe5, 0x9d, 0x04, 0x7c, 0x7b, 0x93, 0x38, 0x78, 0x50, 0xce, 0xfc, 0x21, + 0x07, 0xce, 0xd4, 0x98, 0xe7, 0xfb, 0x77, 0x08, 0xf3, 0xa9, 0xe7, 0xde, 0xdc, 0x78, 0x40, 0x6c, + 0x8e, 0xc8, 0x7d, 0xc2, 0x88, 0x6b, 0x13, 0xb8, 0x00, 0x8a, 0x5b, 0xd4, 0x6d, 0xcc, 0xe5, 0x16, + 0x72, 0x17, 0xa6, 0xaa, 0xd3, 0x4f, 0x02, 0x63, 0x2c, 0x0c, 0x8c, 0xe2, 0x47, 0xd4, 0x6d, 0x20, + 0x49, 0x11, 0x1c, 0x2e, 0x76, 0xc8, 0x5c, 0x3e, 0xc9, 0x71, 0x03, 0x3b, 0x04, 0x49, 0x0a, 0x5c, + 0x02, 0x00, 0xb7, 0xa9, 0x56, 0x30, 0x57, 0x90, 0x7c, 0x50, 0xf3, 0x81, 0xe5, 0xd5, 0xeb, 0x9a, + 0x82, 0x62, 0x5c, 0xe6, 0x8f, 0x05, 0x70, 0xe2, 0x83, 0x87, 0x9c, 0x30, 0x17, 0xb7, 0xea, 0x84, + 0x33, 0x6a, 0xaf, 0x49, 0xfb, 0x0a, 0x30, 0x47, 0xae, 0x85, 0x02, 0xbd, 0xad, 0x08, 0xac, 0x1e, + 0x51, 0x50, 0x8c, 0x0b, 0x7a, 0x60, 0x46, 0xad, 0xd6, 0x48, 0x8b, 0xd8, 0xdc, 0x63, 0x72, 0xb3, + 0xa5, 0xa5, 0x77, 0xac, 0x7e, 0x00, 0x45, 0x56, 0xb3, 0xda, 0x5b, 0x4d, 0xf1, 0xc3, 0xb7, 0x84, + 0x73, 0xac, 0xee, 0xa2, 0xb5, 0x82, 0x37, 0x48, 0xab, 0x27, 0x5a, 0x85, 0x61, 0x60, 0xcc, 0xd4, + 0x13, 0x70, 0x68, 0x00, 0x1e, 0x62, 0x50, 0xe2, 0x98, 0x35, 0x09, 0xbf, 0x83, 0x5b, 0x1d, 0x22, + 0x8f, 0x5c, 0x5a, 0xb2, 0x46, 0x69, 0xb3, 0x7a, 0x01, 0x64, 0xdd, 0xea, 0x60, 0x97, 0x53, 0xbe, + 0x5d, 0x9d, 0x0d, 0x03, 0xa3, 0xb4, 0xde, 0x87, 0x41, 0x71, 0x4c, 0xd8, 0x05, 0x50, 0x2d, 0x97, + 0xbb, 0x84, 0xe1, 0x26, 0x51, 0x9a, 0x8a, 0xfb, 0xd2, 0x74, 0x32, 0x0c, 0x0c, 0xb8, 0x3e, 0x84, + 0x86, 0x52, 0x34, 0x98, 0x3f, 0x0f, 0x3b, 0x86, 0x63, 0xde, 0xf1, 0xff, 0x1b, 0x8e, 0xd9, 0x04, + 0xd3, 0x76, 0x87, 0x31, 0xe2, 0xbe, 0x94, 0x67, 0x4e, 0xe8, 0x63, 0x4d, 0xd7, 0x62, 0x58, 0x28, + 0x81, 0x0c, 0xb7, 0xc1, 0x71, 0xbd, 0x3e, 0x00, 0x07, 0x9d, 0x0a, 0x03, 0xe3, 0x78, 0x6d, 0x18, + 0x0e, 0xa5, 0xe9, 0x30, 0x1f, 0xe7, 0xc1, 0xa9, 0x6b, 0x1e, 0xa3, 0x8f, 0x3c, 0x97, 0xe3, 0xd6, + 0xaa, 0xd7, 0x58, 0xd6, 0xb9, 0x91, 0x30, 0x78, 0x0f, 0x4c, 0x0a, 0xeb, 0x35, 0x30, 0xc7, 0xd2, + 0x47, 0xa5, 0xa5, 0xb7, 0x77, 0x67, 0x6b, 0x95, 0x18, 0xea, 0x84, 0xe3, 0xbe, 0x57, 0xfb, 0xff, + 0x50, 0x84, 0x0a, 0xef, 0x82, 0xa2, 0xdf, 0x26, 0xb6, 0xf6, 0xe4, 0x65, 0x2b, 0x33, 0x47, 0x5b, + 0x19, 0x7b, 0x5c, 0x6b, 0x13, 0xbb, 0x9f, 0x47, 0xc4, 0x0a, 0x49, 0x44, 0x78, 0x0f, 0x4c, 0xf8, + 0x32, 0xd6, 0xb4, 0xdb, 0xae, 0xec, 0x03, 0x5b, 0xca, 0x57, 0x67, 0x34, 0xfa, 0x84, 0x5a, 0x23, + 0x8d, 0x6b, 0x7e, 0x53, 0x00, 0x0b, 0x19, 0x92, 0x35, 0xcf, 0x6d, 0x50, 0x4e, 0x3d, 0x17, 0x5e, + 0x03, 0x45, 0xbe, 0xdd, 0xee, 0x85, 0xf8, 0xa5, 0xde, 0x46, 0xd7, 0xb7, 0xdb, 0xe4, 0x45, 0x60, + 0x9c, 0xdb, 0x49, 0x5e, 0xf0, 0x21, 0x89, 0x00, 0x57, 0xa2, 0x03, 0xe5, 0x13, 0x58, 0x7a, 0x5b, + 0x2f, 0x02, 0x23, 0xa5, 0x2e, 0x59, 0x11, 0x52, 0x72, 0xf3, 0x22, 0x23, 0xb4, 0xb0, 0xcf, 0xd7, + 0x19, 0x76, 0x7d, 0xa5, 0x89, 0x3a, 0xbd, 0x08, 0x7f, 0x63, 0x77, 0x4e, 0x16, 0x12, 0xd5, 0x79, + 0xbd, 0x0b, 0xb8, 0x32, 0x84, 0x86, 0x52, 0x34, 0xc0, 0xf3, 0x60, 0x82, 0x11, 0xec, 0x7b, 0xae, + 0x0c, 0xee, 0xa9, 0xbe, 0x71, 0x91, 0xfc, 0x8b, 0x34, 0x15, 0xbe, 0x0e, 0x8e, 0x38, 0xc4, 0xf7, + 0x71, 0x93, 0xcc, 0x8d, 0x4b, 0xc6, 0x59, 0xcd, 0x78, 0xa4, 0xae, 0x7e, 0xa3, 0x1e, 0xdd, 0xfc, + 0x23, 0x07, 0xce, 0x64, 0xd8, 0x71, 0x85, 0xfa, 0x1c, 0x7e, 0x3e, 0x14, 0xc5, 0xd6, 0x2e, 0x33, + 0x06, 0xf5, 0x55, 0x0c, 0x1f, 0xd3, 0xba, 0x27, 0x7b, 0x7f, 0x62, 0x11, 0xfc, 0x31, 0x18, 0xa7, + 0x9c, 0x38, 0xc2, 0x2b, 0x85, 0x0b, 0xa5, 0xa5, 0xa5, 0xbd, 0x87, 0x59, 0xf5, 0xa8, 0x86, 0x1f, + 0xbf, 0x2e, 0x80, 0x90, 0xc2, 0x33, 0xff, 0xce, 0x67, 0x1e, 0x4b, 0x84, 0x39, 0xec, 0x82, 0x19, + 0xb9, 0x52, 0xa9, 0x18, 0x91, 0xfb, 0xfa, 0x70, 0xa3, 0x2e, 0xd1, 0x88, 0xe2, 0x5d, 0x3d, 0xa9, + 0x77, 0x31, 0xb3, 0x96, 0x40, 0x45, 0x03, 0x5a, 0xe0, 0x22, 0x28, 0x39, 0xd4, 0x45, 0xa4, 0xdd, + 0xa2, 0x36, 0x56, 0xc1, 0x38, 0xae, 0xca, 0x4f, 0xbd, 0xff, 0x1b, 0xc5, 0x79, 0xe0, 0xbb, 0xa0, + 0xe4, 0xe0, 0x87, 0x91, 0x48, 0x41, 0x8a, 0x1c, 0xd7, 0xfa, 0x4a, 0xf5, 0x3e, 0x09, 0xc5, 0xf9, + 0xe0, 0x03, 0x50, 0x56, 0x35, 0xa5, 0xb6, 0x7a, 0xfb, 0x36, 0xa7, 0x2d, 0xfa, 0x08, 0x8b, 0x38, + 0x5a, 0x25, 0xcc, 0x26, 0x2e, 0x17, 0xa1, 0x51, 0x94, 0x48, 0x66, 0x18, 0x18, 0xe5, 0xf5, 0x91, + 0x9c, 0x68, 0x07, 0x24, 0xf3, 0xd7, 0x02, 0x38, 0x3b, 0x32, 0x0d, 0xc0, 0xab, 0x00, 0x7a, 0x1b, + 0x3e, 0x61, 0x5d, 0xd2, 0xf8, 0x50, 0xf5, 0x45, 0xa2, 0x41, 0x11, 0x36, 0x2f, 0xa8, 0x9a, 0x78, + 0x73, 0x88, 0x8a, 0x52, 0x24, 0xa0, 0x0d, 0x8e, 0x8a, 0x7b, 0xa1, 0xac, 0x4c, 0x75, 0x2f, 0xb4, + 0xb7, 0x4b, 0xf7, 0xbf, 0x30, 0x30, 0x8e, 0xae, 0xc4, 0x41, 0x50, 0x12, 0x13, 0x2e, 0x83, 0x59, + 0x9d, 0xec, 0x07, 0xac, 0x7e, 0x4a, 0x5b, 0x7d, 0xb6, 0x96, 0x24, 0xa3, 0x41, 0x7e, 0x01, 0xd1, + 0x20, 0x3e, 0x65, 0xa4, 0x11, 0x41, 0x14, 0x93, 0x10, 0xef, 0x27, 0xc9, 0x68, 0x90, 0x1f, 0x3a, + 0xc0, 0xd0, 0xa8, 0x99, 0x1e, 0x1c, 0x97, 0x90, 0xaf, 0x85, 0x81, 0x61, 0xd4, 0x46, 0xb3, 0xa2, + 0x9d, 0xb0, 0x44, 0x1b, 0xa8, 0x7b, 0x07, 0x79, 0x41, 0x2e, 0x25, 0x52, 0xef, 0xc2, 0x40, 0xea, + 0x3d, 0x16, 0x6f, 0x14, 0x63, 0x69, 0xf6, 0x16, 0x98, 0xf0, 0xe4, 0xcd, 0xd0, 0x7e, 0xb9, 0x38, + 0xe2, 0x3a, 0x45, 0x25, 0x2d, 0x02, 0xaa, 0x02, 0x91, 0xcb, 0xf4, 0xd5, 0xd2, 0x40, 0xf0, 0x3a, + 0x28, 0xb6, 0xbd, 0x46, 0xaf, 0x10, 0xbd, 0x39, 0x02, 0x70, 0xd5, 0x6b, 0xf8, 0x09, 0xb8, 0x49, + 0xb1, 0x63, 0xf1, 0x17, 0x49, 0x08, 0xf8, 0x09, 0x98, 0xec, 0x15, 0x7c, 0xdd, 0x1d, 0x54, 0x46, + 0xc0, 0x21, 0xcd, 0x9a, 0x80, 0x9c, 0x16, 0x89, 0xac, 0x47, 0x41, 0x11, 0x9c, 0x80, 0x26, 0xba, + 0x55, 0x93, 0x5e, 0x19, 0x0d, 0x9d, 0xd6, 0x6e, 0x2b, 0xe8, 0x1e, 0x05, 0x45, 0x70, 0xe6, 0x4f, + 0x05, 0x30, 0x9d, 0x68, 0xff, 0x0e, 0xd9, 0x35, 0xaa, 0x8e, 0x1f, 0x98, 0x6b, 0x14, 0xdc, 0x81, + 0xba, 0x46, 0x41, 0xbe, 0x12, 0xd7, 0xc4, 0xa0, 0x53, 0x5c, 0xf3, 0x6d, 0x1e, 0xc0, 0xe1, 0x30, + 0x86, 0x5f, 0x80, 0x09, 0x95, 0x30, 0x5f, 0xb2, 0xa8, 0x44, 0xe5, 0x5d, 0xd7, 0x0f, 0x8d, 0x3a, + 0xd0, 0xff, 0xe7, 0x77, 0xd5, 0xff, 0x93, 0x83, 0x98, 0x93, 0xa2, 0xaa, 0x93, 0x35, 0x2b, 0x99, + 0xdf, 0x0f, 0x5a, 0x44, 0x85, 0xec, 0xbf, 0xd1, 0x22, 0x87, 0x36, 0xa0, 0x98, 0xbf, 0xe5, 0xc0, + 0xb1, 0xc1, 0xe4, 0xb4, 0xaf, 0x21, 0xee, 0x51, 0xea, 0x24, 0x9a, 0xdf, 0xd7, 0xc6, 0xa3, 0xde, + 0x73, 0x97, 0xd3, 0xe8, 0xef, 0xc9, 0x43, 0xec, 0x7f, 0x12, 0xfd, 0x32, 0x7d, 0x5c, 0xdb, 0xdf, + 0x29, 0xce, 0x68, 0x65, 0xbb, 0x1f, 0xd9, 0x7e, 0xc9, 0x83, 0x13, 0x69, 0xa9, 0x1d, 0xd6, 0xf4, + 0xeb, 0x8a, 0x3a, 0x45, 0x25, 0xfe, 0xba, 0xf2, 0x22, 0x30, 0x8c, 0x94, 0xf1, 0xa0, 0x07, 0x13, + 0x7b, 0x80, 0xb9, 0x0b, 0xe6, 0x12, 0xb6, 0x8b, 0xd5, 0x5a, 0xdd, 0xec, 0xfd, 0x3f, 0x0c, 0x8c, + 0xb9, 0xf5, 0x0c, 0x1e, 0x94, 0x29, 0x9d, 0xf1, 0x0a, 0x51, 0x78, 0xe5, 0xaf, 0x10, 0x8f, 0x87, + 0xed, 0xa5, 0x7c, 0x7f, 0x20, 0xf6, 0xfa, 0x0c, 0x9c, 0x4e, 0x3a, 0x69, 0xd8, 0x60, 0x67, 0xc3, + 0xc0, 0x38, 0x5d, 0xcb, 0x62, 0x42, 0xd9, 0xf2, 0x59, 0x91, 0x56, 0x38, 0xa4, 0x48, 0xfb, 0x3a, + 0x0f, 0xc6, 0x65, 0x53, 0x79, 0x08, 0x4f, 0x01, 0x57, 0x13, 0x4f, 0x01, 0xe7, 0x46, 0xa4, 0x57, + 0xb9, 0xa3, 0xcc, 0xc1, 0xff, 0xc6, 0xc0, 0xe0, 0x7f, 0x7e, 0x47, 0xa4, 0xd1, 0x63, 0xfe, 0x7b, + 0x60, 0x2a, 0x52, 0x08, 0xdf, 0x12, 0x45, 0x5e, 0x77, 0xc3, 0x39, 0xe9, 0xdb, 0x68, 0x36, 0x8c, + 0xda, 0xe0, 0x88, 0xc3, 0xa4, 0xa0, 0x14, 0xd3, 0xb0, 0x37, 0x61, 0xc1, 0xed, 0xc7, 0x1f, 0xba, + 0xa6, 0xfa, 0xdc, 0xd1, 0x8b, 0x55, 0xc4, 0x51, 0xbd, 0xf0, 0xe4, 0x79, 0x79, 0xec, 0xe9, 0xf3, + 0xf2, 0xd8, 0xb3, 0xe7, 0xe5, 0xb1, 0xaf, 0xc2, 0x72, 0xee, 0x49, 0x58, 0xce, 0x3d, 0x0d, 0xcb, + 0xb9, 0x67, 0x61, 0x39, 0xf7, 0x67, 0x58, 0xce, 0x7d, 0xf7, 0x57, 0x79, 0xec, 0xd3, 0x7c, 0x77, + 0xf1, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4d, 0x5f, 0x69, 0x0c, 0x4c, 0x17, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/generated.proto index 64f01f477..a3c542de2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/types_swagger_doc_generated.go index ec364f53e..e84909269 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CrossVersionObjectReference = map[string]string{ "": "CrossVersionObjectReference contains enough information to let you identify the referred resource.", "kind": "Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds\"", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/zz_generated.deepcopy.go index 011275be4..ee9ac01de 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/generated.pb.go index 784e4be2b..33f67913a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -3941,96 +3941,95 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1441 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcd, 0x8f, 0x1b, 0xc5, - 0x12, 0x5f, 0x7f, 0xec, 0x66, 0xd3, 0xde, 0xec, 0xe6, 0x75, 0xa2, 0xc4, 0xd9, 0xbc, 0xd8, 0xab, - 0xd1, 0xd3, 0x53, 0x88, 0xc8, 0x4c, 0xe2, 0x2c, 0x1f, 0x12, 0x42, 0x62, 0x6d, 0x20, 0x89, 0x58, - 0x27, 0xa1, 0x77, 0x13, 0x21, 0x08, 0x88, 0xf6, 0xb8, 0xe3, 0x6d, 0xd6, 0x33, 0x63, 0x75, 0xb7, - 0xad, 0x6c, 0x10, 0x12, 0x17, 0xee, 0x1c, 0xf8, 0xb8, 0x72, 0x46, 0x70, 0x85, 0x33, 0x48, 0x48, - 0x39, 0xe6, 0x18, 0x84, 0x64, 0x91, 0xe1, 0xbf, 0xc8, 0x09, 0x4d, 0x77, 0xcf, 0x78, 0xc6, 0xf6, - 0xac, 0x1d, 0xb3, 0x09, 0x70, 0x9b, 0xee, 0xaa, 0xfa, 0x55, 0x75, 0x55, 0x75, 0x75, 0xd5, 0x80, - 0xcb, 0xbb, 0x2f, 0x73, 0x93, 0x7a, 0xd6, 0x6e, 0xb7, 0x41, 0x98, 0x4b, 0x04, 0xe1, 0x56, 0x8f, - 0xb8, 0x4d, 0x8f, 0x59, 0x9a, 0x80, 0x3b, 0xd4, 0xc2, 0x5d, 0xe1, 0x71, 0x1b, 0xb7, 0xa9, 0xdb, - 0xb2, 0x7a, 0x95, 0x06, 0x11, 0xf8, 0xa2, 0xd5, 0x22, 0x2e, 0x61, 0x58, 0x90, 0xa6, 0xd9, 0x61, - 0x9e, 0xf0, 0x60, 0x49, 0xf1, 0x9b, 0xb8, 0x43, 0xcd, 0x18, 0xbf, 0xa9, 0xf9, 0x57, 0xcf, 0xb7, - 0xa8, 0xd8, 0xe9, 0x36, 0x4c, 0xdb, 0x73, 0xac, 0x96, 0xd7, 0xf2, 0x2c, 0x29, 0xd6, 0xe8, 0xde, - 0x91, 0x2b, 0xb9, 0x90, 0x5f, 0x0a, 0x6e, 0xd5, 0x88, 0xa9, 0xb7, 0x3d, 0x46, 0xac, 0xde, 0x88, - 0xca, 0xd5, 0xf5, 0x01, 0x8f, 0x83, 0xed, 0x1d, 0xea, 0x12, 0xb6, 0x67, 0x75, 0x76, 0x5b, 0x52, - 0x88, 0x11, 0xee, 0x75, 0x99, 0x4d, 0x9e, 0x48, 0x8a, 0x5b, 0x0e, 0x11, 0x78, 0x9c, 0x2e, 0x2b, - 0x4d, 0x8a, 0x75, 0x5d, 0x41, 0x9d, 0x51, 0x35, 0x2f, 0x4e, 0x12, 0xe0, 0xf6, 0x0e, 0x71, 0xf0, - 0x88, 0xdc, 0xa5, 0x34, 0xb9, 0xae, 0xa0, 0x6d, 0x8b, 0xba, 0x82, 0x0b, 0x36, 0x2c, 0x64, 0x7c, - 0x99, 0x01, 0xa7, 0x6b, 0xcc, 0xe3, 0xfc, 0x16, 0x61, 0x9c, 0x7a, 0xee, 0xf5, 0xc6, 0x47, 0xc4, - 0x16, 0x88, 0xdc, 0x21, 0x8c, 0xb8, 0x36, 0x81, 0x6b, 0x20, 0xbf, 0x4b, 0xdd, 0x66, 0x31, 0xb3, - 0x96, 0x39, 0x7b, 0xb8, 0xba, 0x74, 0xbf, 0x5f, 0x9e, 0xf3, 0xfb, 0xe5, 0xfc, 0x5b, 0xd4, 0x6d, - 0x22, 0x49, 0x09, 0x38, 0x5c, 0xec, 0x90, 0x62, 0x36, 0xc9, 0x71, 0x0d, 0x3b, 0x04, 0x49, 0x0a, - 0xac, 0x00, 0x80, 0x3b, 0x54, 0x2b, 0x28, 0xe6, 0x24, 0x1f, 0xd4, 0x7c, 0x60, 0xe3, 0xc6, 0x55, - 0x4d, 0x41, 0x31, 0x2e, 0xe3, 0xab, 0x1c, 0x38, 0xfe, 0xc6, 0x5d, 0x41, 0x98, 0x8b, 0xdb, 0x75, - 0x22, 0x18, 0xb5, 0xb7, 0x64, 0x50, 0x02, 0x30, 0x47, 0xae, 0x03, 0x05, 0xda, 0xac, 0x08, 0xac, - 0x1e, 0x51, 0x50, 0x8c, 0x0b, 0x7a, 0x60, 0x59, 0xad, 0xb6, 0x48, 0x9b, 0xd8, 0xc2, 0x63, 0xd2, - 0xd8, 0x42, 0xe5, 0x92, 0x39, 0x48, 0xbd, 0xc8, 0x65, 0x66, 0x67, 0xb7, 0x15, 0x6c, 0x70, 0x33, - 0x88, 0xa8, 0xd9, 0xbb, 0x68, 0x6e, 0xe2, 0x06, 0x69, 0x87, 0xa2, 0x55, 0xe8, 0xf7, 0xcb, 0xcb, - 0xf5, 0x04, 0x1c, 0x1a, 0x82, 0x87, 0x18, 0x14, 0x04, 0x66, 0x2d, 0x22, 0x6e, 0xe1, 0x76, 0x97, - 0xc8, 0x23, 0x17, 0x2a, 0xe6, 0x7e, 0xda, 0xcc, 0x30, 0xeb, 0xcc, 0xb7, 0xbb, 0xd8, 0x15, 0x54, - 0xec, 0x55, 0x57, 0xfc, 0x7e, 0xb9, 0xb0, 0x3d, 0x80, 0x41, 0x71, 0x4c, 0xd8, 0x03, 0x50, 0x2d, - 0x37, 0x7a, 0x84, 0xe1, 0x16, 0x51, 0x9a, 0xf2, 0x33, 0x69, 0x3a, 0xe1, 0xf7, 0xcb, 0x70, 0x7b, - 0x04, 0x0d, 0x8d, 0xd1, 0x60, 0x7c, 0x33, 0x1a, 0x18, 0x81, 0x45, 0x97, 0xff, 0x3b, 0x02, 0xb3, - 0x03, 0x96, 0xec, 0x2e, 0x63, 0xc4, 0xfd, 0x4b, 0x91, 0x39, 0xae, 0x8f, 0xb5, 0x54, 0x8b, 0x61, - 0xa1, 0x04, 0x32, 0xdc, 0x03, 0xc7, 0xf4, 0xfa, 0x00, 0x02, 0x74, 0xd2, 0xef, 0x97, 0x8f, 0xd5, - 0x46, 0xe1, 0xd0, 0x38, 0x1d, 0xc6, 0x4f, 0x59, 0x70, 0xf2, 0x8a, 0xc7, 0xe8, 0x3d, 0xcf, 0x15, - 0xb8, 0x7d, 0xc3, 0x6b, 0x6e, 0xe8, 0xaa, 0x4a, 0x18, 0xfc, 0x10, 0x2c, 0x06, 0xde, 0x6b, 0x62, - 0x81, 0x65, 0x8c, 0x0a, 0x95, 0x0b, 0xd3, 0xf9, 0x5a, 0x15, 0x86, 0x3a, 0x11, 0x78, 0x10, 0xd5, - 0xc1, 0x1e, 0x8a, 0x50, 0xe1, 0xfb, 0x20, 0xcf, 0x3b, 0xc4, 0xd6, 0x91, 0x7c, 0xc5, 0xdc, 0xbf, - 0xba, 0x9b, 0x29, 0x86, 0x6e, 0x75, 0x88, 0x3d, 0x28, 0x26, 0xc1, 0x0a, 0x49, 0x58, 0x48, 0xc0, - 0x02, 0x97, 0x09, 0xa7, 0x63, 0xf7, 0xea, 0xac, 0x0a, 0x24, 0x48, 0x75, 0x59, 0xab, 0x58, 0x50, - 0x6b, 0xa4, 0xc1, 0x8d, 0xcf, 0x72, 0x60, 0x2d, 0x45, 0xb2, 0xe6, 0xb9, 0x4d, 0x2a, 0xa8, 0xe7, - 0xc2, 0x2b, 0x20, 0x2f, 0xf6, 0x3a, 0x61, 0xb2, 0xaf, 0x87, 0xd6, 0x6e, 0xef, 0x75, 0xc8, 0xe3, - 0x7e, 0xf9, 0x7f, 0x93, 0xe4, 0x03, 0x3e, 0x24, 0x11, 0xe0, 0x66, 0x74, 0xaa, 0x6c, 0x02, 0x4b, - 0x9b, 0xf5, 0xb8, 0x5f, 0x1e, 0xf3, 0xac, 0x99, 0x11, 0x52, 0xd2, 0xf8, 0xa0, 0x36, 0xb4, 0x31, - 0x17, 0xdb, 0x0c, 0xbb, 0x5c, 0x69, 0xa2, 0x4e, 0x98, 0xeb, 0xe7, 0xa6, 0x0b, 0x77, 0x20, 0x51, - 0x5d, 0xd5, 0x56, 0xc0, 0xcd, 0x11, 0x34, 0x34, 0x46, 0x03, 0xfc, 0x3f, 0x58, 0x60, 0x04, 0x73, - 0xcf, 0x95, 0x69, 0x7e, 0x78, 0xe0, 0x5c, 0x24, 0x77, 0x91, 0xa6, 0xc2, 0xe7, 0xc0, 0x21, 0x87, - 0x70, 0x8e, 0x5b, 0xa4, 0x38, 0x2f, 0x19, 0x57, 0x34, 0xe3, 0xa1, 0xba, 0xda, 0x46, 0x21, 0xdd, - 0xf8, 0x35, 0x03, 0x4e, 0xa7, 0xf8, 0x71, 0x93, 0x72, 0x01, 0x6f, 0x8f, 0xe4, 0xb3, 0x39, 0x65, - 0xed, 0xa0, 0x5c, 0x65, 0xf3, 0x51, 0xad, 0x7b, 0x31, 0xdc, 0x89, 0xe5, 0xf2, 0x6d, 0x30, 0x4f, - 0x05, 0x71, 0x82, 0xa8, 0xe4, 0xce, 0x16, 0x2a, 0x2f, 0xcd, 0x98, 0x6b, 0xd5, 0x23, 0x5a, 0xc7, - 0xfc, 0xd5, 0x00, 0x0d, 0x29, 0x50, 0xe3, 0xb7, 0x6c, 0xea, 0xd9, 0x82, 0x84, 0x87, 0x1f, 0x83, - 0x65, 0xb9, 0x52, 0x95, 0x19, 0x91, 0x3b, 0xfa, 0x84, 0x13, 0xef, 0xd4, 0x3e, 0x0f, 0x7a, 0xf5, - 0x84, 0x36, 0x65, 0x79, 0x2b, 0x01, 0x8d, 0x86, 0x54, 0xc1, 0x8b, 0xa0, 0xe0, 0x50, 0x17, 0x91, - 0x4e, 0x9b, 0xda, 0x58, 0xa5, 0xe5, 0xbc, 0x7a, 0x92, 0xea, 0x83, 0x6d, 0x14, 0xe7, 0x81, 0x2f, - 0x80, 0x82, 0x83, 0xef, 0x46, 0x22, 0x39, 0x29, 0x72, 0x4c, 0xeb, 0x2b, 0xd4, 0x07, 0x24, 0x14, - 0xe7, 0x83, 0x37, 0x83, 0x6c, 0x08, 0xaa, 0x34, 0x2f, 0xe6, 0xa5, 0x9b, 0xcf, 0x4d, 0x3a, 0x9f, - 0x2e, 0xf2, 0x41, 0x89, 0x88, 0x65, 0x8e, 0x84, 0x40, 0x21, 0x96, 0xf1, 0x43, 0x1e, 0x9c, 0xd9, - 0xf7, 0xee, 0xc3, 0x37, 0x01, 0xf4, 0x1a, 0x9c, 0xb0, 0x1e, 0x69, 0x5e, 0x56, 0x6d, 0x51, 0xd0, - 0x9f, 0x04, 0x3e, 0xce, 0xa9, 0x27, 0xf1, 0xfa, 0x08, 0x15, 0x8d, 0x91, 0x80, 0x36, 0x38, 0x12, - 0x5c, 0x06, 0xe5, 0x50, 0xaa, 0x5b, 0xa1, 0x27, 0xbb, 0x69, 0xff, 0xf1, 0xfb, 0xe5, 0x23, 0x9b, - 0x71, 0x10, 0x94, 0xc4, 0x84, 0x1b, 0x60, 0x45, 0xd7, 0xfa, 0x21, 0x07, 0x9f, 0xd4, 0x1e, 0x58, - 0xa9, 0x25, 0xc9, 0x68, 0x98, 0x3f, 0x80, 0x68, 0x12, 0x4e, 0x19, 0x69, 0x46, 0x10, 0xf9, 0x24, - 0xc4, 0xeb, 0x49, 0x32, 0x1a, 0xe6, 0x87, 0x6d, 0xb0, 0xac, 0x51, 0xb5, 0xbf, 0x8b, 0xf3, 0x32, - 0x64, 0xcf, 0x4f, 0x19, 0x32, 0x55, 0x74, 0xa3, 0x1c, 0xac, 0x25, 0xb0, 0xd0, 0x10, 0x36, 0x14, - 0x00, 0xd8, 0x61, 0x89, 0xe3, 0xc5, 0x05, 0xa9, 0xe9, 0xb5, 0x19, 0xef, 0x60, 0x54, 0x2b, 0x07, - 0xcf, 0x57, 0xb4, 0xc5, 0x51, 0x4c, 0x8f, 0xf1, 0x6d, 0x0e, 0x80, 0x41, 0x86, 0xc1, 0xf5, 0x44, - 0x91, 0x5f, 0x1b, 0x2a, 0xf2, 0x47, 0xe3, 0xcd, 0x69, 0xac, 0xa0, 0xdf, 0x02, 0x0b, 0x9e, 0xbc, - 0x79, 0x3a, 0x19, 0x2a, 0x93, 0xcc, 0x8e, 0xde, 0xd2, 0x08, 0xad, 0x0a, 0x82, 0xd2, 0xa9, 0xef, - 0xaf, 0x46, 0x83, 0xd7, 0x40, 0xbe, 0xe3, 0x35, 0xc3, 0xc7, 0xef, 0xc2, 0x24, 0xd4, 0x1b, 0x5e, - 0x93, 0x27, 0x30, 0x17, 0x03, 0xdb, 0x83, 0x5d, 0x24, 0x71, 0xe0, 0x07, 0x60, 0x31, 0x6c, 0x37, - 0x74, 0x6f, 0xb2, 0x3e, 0x09, 0x13, 0x69, 0xfe, 0x04, 0xee, 0x52, 0x50, 0x41, 0x43, 0x0a, 0x8a, - 0x30, 0x03, 0x7c, 0xa2, 0xbb, 0x45, 0x59, 0xeb, 0xa7, 0xc0, 0x1f, 0xd7, 0xf6, 0x2b, 0xfc, 0x90, - 0x82, 0x22, 0x4c, 0xe3, 0xbb, 0x1c, 0x58, 0x4a, 0xb4, 0xa1, 0x7f, 0x47, 0xb8, 0x54, 0x56, 0x1f, - 0x6c, 0xb8, 0x14, 0xe6, 0xc1, 0x87, 0x4b, 0xe1, 0x3e, 0xbd, 0x70, 0xc5, 0xf0, 0xc7, 0x84, 0xeb, - 0x8b, 0x2c, 0x80, 0xa3, 0x99, 0x0e, 0x6d, 0xb0, 0xa0, 0x46, 0x8d, 0x83, 0x78, 0xe1, 0xa2, 0xae, - 0x43, 0x3f, 0x66, 0x1a, 0x7a, 0x68, 0x40, 0xc9, 0x4e, 0x35, 0xa0, 0x90, 0x83, 0x18, 0xe4, 0xa2, - 0x27, 0x30, 0x6d, 0x98, 0x33, 0xbe, 0x1e, 0x76, 0x8b, 0xca, 0xe5, 0x7f, 0xac, 0x5b, 0x9e, 0xd9, - 0x18, 0x65, 0xfc, 0x9c, 0x01, 0x47, 0x87, 0x8b, 0xd8, 0x4c, 0xa3, 0xe6, 0xbd, 0xb1, 0xf3, 0x72, - 0x76, 0x26, 0xc3, 0xa3, 0xbe, 0x78, 0xca, 0x99, 0xf9, 0x97, 0xe4, 0x21, 0x66, 0x9f, 0x97, 0x3f, - 0x19, 0x3f, 0x54, 0xce, 0x76, 0x8a, 0xd3, 0x5a, 0xd9, 0xf4, 0x83, 0xe5, 0xf7, 0x59, 0x70, 0x7c, - 0x5c, 0xf5, 0x87, 0x35, 0xfd, 0x0f, 0x48, 0x9d, 0xc2, 0x8a, 0xff, 0x03, 0x7a, 0xdc, 0x2f, 0x97, - 0xc7, 0x8c, 0x2e, 0x21, 0x4c, 0xec, 0x37, 0xd1, 0x3b, 0xa0, 0x98, 0xf0, 0xdd, 0x4d, 0x41, 0xdb, - 0xf4, 0x9e, 0x6a, 0xca, 0x54, 0xfb, 0xf9, 0x5f, 0xbf, 0x5f, 0x2e, 0x6e, 0xa7, 0xf0, 0xa0, 0x54, - 0xe9, 0x94, 0x7f, 0x25, 0xb9, 0xa7, 0xfe, 0xaf, 0xe4, 0xc7, 0x51, 0x7f, 0xa9, 0xd8, 0x1f, 0x88, - 0xbf, 0xde, 0x03, 0xa7, 0x92, 0x41, 0x1a, 0x75, 0xd8, 0x19, 0xbf, 0x5f, 0x3e, 0x55, 0x4b, 0x63, - 0x42, 0xe9, 0xf2, 0x69, 0x99, 0x96, 0x7b, 0x36, 0x99, 0x56, 0x3d, 0x7f, 0xff, 0x51, 0x69, 0xee, - 0xc1, 0xa3, 0xd2, 0xdc, 0xc3, 0x47, 0xa5, 0xb9, 0x4f, 0xfd, 0x52, 0xe6, 0xbe, 0x5f, 0xca, 0x3c, - 0xf0, 0x4b, 0x99, 0x87, 0x7e, 0x29, 0xf3, 0xbb, 0x5f, 0xca, 0x7c, 0xfe, 0x47, 0x69, 0xee, 0xdd, - 0x43, 0xba, 0xee, 0xfd, 0x19, 0x00, 0x00, 0xff, 0xff, 0x91, 0x09, 0xa9, 0x38, 0x8c, 0x16, 0x00, - 0x00, + // 1426 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcb, 0x8f, 0x1b, 0x45, + 0x13, 0x5f, 0x3f, 0x76, 0xb3, 0x69, 0x6f, 0x76, 0xf3, 0x75, 0xa2, 0xc4, 0xd9, 0x7c, 0xf1, 0xac, + 0x46, 0x08, 0x85, 0x88, 0xcc, 0x24, 0x66, 0x79, 0x48, 0x08, 0x89, 0xb5, 0x81, 0x24, 0x62, 0x9d, + 0x84, 0xde, 0x4d, 0x84, 0x20, 0x20, 0xda, 0xe3, 0x8e, 0xb7, 0x59, 0xcf, 0x8c, 0x35, 0xdd, 0xb6, + 0xb2, 0x41, 0x48, 0x5c, 0xb8, 0x73, 0xe0, 0x71, 0xe5, 0x8c, 0xe0, 0x0a, 0x67, 0x90, 0x90, 0x72, + 0xcc, 0x31, 0x08, 0xc9, 0x22, 0xc3, 0x7f, 0x91, 0x13, 0xea, 0xc7, 0x8c, 0x67, 0xfc, 0x58, 0x3b, + 0x66, 0x13, 0xe0, 0x36, 0xdd, 0x55, 0xf5, 0xab, 0xea, 0xaa, 0xea, 0xea, 0xaa, 0x01, 0x97, 0x76, + 0x5f, 0x61, 0x16, 0xf5, 0xed, 0xdd, 0x4e, 0x9d, 0x04, 0x1e, 0xe1, 0x84, 0xd9, 0x5d, 0xe2, 0x35, + 0xfc, 0xc0, 0xd6, 0x04, 0xdc, 0xa6, 0x36, 0xee, 0x70, 0x9f, 0x39, 0xb8, 0x45, 0xbd, 0xa6, 0xdd, + 0x2d, 0xd7, 0x09, 0xc7, 0x17, 0xed, 0x26, 0xf1, 0x48, 0x80, 0x39, 0x69, 0x58, 0xed, 0xc0, 0xe7, + 0x3e, 0x2c, 0x29, 0x7e, 0x0b, 0xb7, 0xa9, 0x95, 0xe0, 0xb7, 0x34, 0xff, 0xea, 0xf9, 0x26, 0xe5, + 0x3b, 0x9d, 0xba, 0xe5, 0xf8, 0xae, 0xdd, 0xf4, 0x9b, 0xbe, 0x2d, 0xc5, 0xea, 0x9d, 0xdb, 0x72, + 0x25, 0x17, 0xf2, 0x4b, 0xc1, 0xad, 0x9a, 0x09, 0xf5, 0x8e, 0x1f, 0x10, 0xbb, 0x3b, 0xa4, 0x72, + 0x75, 0xbd, 0xcf, 0xe3, 0x62, 0x67, 0x87, 0x7a, 0x24, 0xd8, 0xb3, 0xdb, 0xbb, 0x4d, 0x29, 0x14, + 0x10, 0xe6, 0x77, 0x02, 0x87, 0x3c, 0x96, 0x14, 0xb3, 0x5d, 0xc2, 0xf1, 0x28, 0x5d, 0xf6, 0x38, + 0xa9, 0xa0, 0xe3, 0x71, 0xea, 0x0e, 0xab, 0x79, 0x69, 0x92, 0x00, 0x73, 0x76, 0x88, 0x8b, 0x07, + 0xe5, 0xcc, 0xaf, 0x32, 0xe0, 0x74, 0x35, 0xf0, 0x19, 0xbb, 0x49, 0x02, 0x46, 0x7d, 0xef, 0x5a, + 0xfd, 0x63, 0xe2, 0x70, 0x44, 0x6e, 0x93, 0x80, 0x78, 0x0e, 0x81, 0x6b, 0x20, 0xbf, 0x4b, 0xbd, + 0x46, 0x31, 0xb3, 0x96, 0x39, 0x7b, 0xb8, 0xb2, 0x74, 0xaf, 0x67, 0xcc, 0x85, 0x3d, 0x23, 0xff, + 0x36, 0xf5, 0x1a, 0x48, 0x52, 0x04, 0x87, 0x87, 0x5d, 0x52, 0xcc, 0xa6, 0x39, 0xae, 0x62, 0x97, + 0x20, 0x49, 0x81, 0x65, 0x00, 0x70, 0x9b, 0x6a, 0x05, 0xc5, 0x9c, 0xe4, 0x83, 0x9a, 0x0f, 0x6c, + 0x5c, 0xbf, 0xa2, 0x29, 0x28, 0xc1, 0x65, 0x7e, 0x9d, 0x03, 0xc7, 0xdf, 0xbc, 0xc3, 0x49, 0xe0, + 0xe1, 0x56, 0x8d, 0xf0, 0x80, 0x3a, 0x5b, 0xd2, 0xbf, 0x02, 0xcc, 0x95, 0x6b, 0xa1, 0x40, 0x9b, + 0x15, 0x83, 0xd5, 0x62, 0x0a, 0x4a, 0x70, 0x41, 0x1f, 0x2c, 0xab, 0xd5, 0x16, 0x69, 0x11, 0x87, + 0xfb, 0x81, 0x34, 0xb6, 0x50, 0x7e, 0xc1, 0xea, 0x67, 0x51, 0xec, 0x35, 0xab, 0xbd, 0xdb, 0x14, + 0x1b, 0xcc, 0x12, 0xc1, 0xb1, 0xba, 0x17, 0xad, 0x4d, 0x5c, 0x27, 0xad, 0x48, 0xb4, 0x02, 0xc3, + 0x9e, 0xb1, 0x5c, 0x4b, 0xc1, 0xa1, 0x01, 0x78, 0x88, 0x41, 0x81, 0xe3, 0xa0, 0x49, 0xf8, 0x4d, + 0xdc, 0xea, 0x10, 0x79, 0xe4, 0x42, 0xd9, 0xda, 0x4f, 0x9b, 0x15, 0x25, 0x90, 0xf5, 0x4e, 0x07, + 0x7b, 0x9c, 0xf2, 0xbd, 0xca, 0x4a, 0xd8, 0x33, 0x0a, 0xdb, 0x7d, 0x18, 0x94, 0xc4, 0x84, 0x5d, + 0x00, 0xd5, 0x72, 0xa3, 0x4b, 0x02, 0xdc, 0x24, 0x4a, 0x53, 0x7e, 0x26, 0x4d, 0x27, 0xc2, 0x9e, + 0x01, 0xb7, 0x87, 0xd0, 0xd0, 0x08, 0x0d, 0xe6, 0xb7, 0xc3, 0x81, 0xe1, 0x98, 0x77, 0xd8, 0x7f, + 0x23, 0x30, 0x3b, 0x60, 0xc9, 0xe9, 0x04, 0x01, 0xf1, 0xfe, 0x56, 0x64, 0x8e, 0xeb, 0x63, 0x2d, + 0x55, 0x13, 0x58, 0x28, 0x85, 0x0c, 0xf7, 0xc0, 0x31, 0xbd, 0x3e, 0x80, 0x00, 0x9d, 0x0c, 0x7b, + 0xc6, 0xb1, 0xea, 0x30, 0x1c, 0x1a, 0xa5, 0xc3, 0xfc, 0x39, 0x0b, 0x4e, 0x5e, 0xf6, 0x03, 0x7a, + 0xd7, 0xf7, 0x38, 0x6e, 0x5d, 0xf7, 0x1b, 0x1b, 0xba, 0x40, 0x92, 0x00, 0x7e, 0x04, 0x16, 0x85, + 0xf7, 0x1a, 0x98, 0x63, 0x19, 0xa3, 0x42, 0xf9, 0xc2, 0x74, 0xbe, 0x56, 0x85, 0xa1, 0x46, 0x38, + 0xee, 0x47, 0xb5, 0xbf, 0x87, 0x62, 0x54, 0xf8, 0x01, 0xc8, 0xb3, 0x36, 0x71, 0x74, 0x24, 0x5f, + 0xb5, 0xf6, 0x2f, 0xd4, 0xd6, 0x18, 0x43, 0xb7, 0xda, 0xc4, 0xe9, 0x17, 0x13, 0xb1, 0x42, 0x12, + 0x16, 0x12, 0xb0, 0xc0, 0x64, 0xc2, 0xe9, 0xd8, 0xbd, 0x36, 0xab, 0x02, 0x09, 0x52, 0x59, 0xd6, + 0x2a, 0x16, 0xd4, 0x1a, 0x69, 0x70, 0xf3, 0xf3, 0x1c, 0x58, 0x1b, 0x23, 0x59, 0xf5, 0xbd, 0x06, + 0xe5, 0xd4, 0xf7, 0xe0, 0x65, 0x90, 0xe7, 0x7b, 0xed, 0x28, 0xd9, 0xd7, 0x23, 0x6b, 0xb7, 0xf7, + 0xda, 0xe4, 0x51, 0xcf, 0x78, 0x66, 0x92, 0xbc, 0xe0, 0x43, 0x12, 0x01, 0x6e, 0xc6, 0xa7, 0xca, + 0xa6, 0xb0, 0xb4, 0x59, 0x8f, 0x7a, 0xc6, 0x88, 0x17, 0xca, 0x8a, 0x91, 0xd2, 0xc6, 0x8b, 0xda, + 0xd0, 0xc2, 0x8c, 0x6f, 0x07, 0xd8, 0x63, 0x4a, 0x13, 0x75, 0xa3, 0x5c, 0x3f, 0x37, 0x5d, 0xb8, + 0x85, 0x44, 0x65, 0x55, 0x5b, 0x01, 0x37, 0x87, 0xd0, 0xd0, 0x08, 0x0d, 0xf0, 0x59, 0xb0, 0x10, + 0x10, 0xcc, 0x7c, 0x4f, 0xa6, 0xf9, 0xe1, 0xbe, 0x73, 0x91, 0xdc, 0x45, 0x9a, 0x0a, 0x9f, 0x03, + 0x87, 0x5c, 0xc2, 0x18, 0x6e, 0x92, 0xe2, 0xbc, 0x64, 0x5c, 0xd1, 0x8c, 0x87, 0x6a, 0x6a, 0x1b, + 0x45, 0x74, 0xf3, 0xb7, 0x0c, 0x38, 0x3d, 0xc6, 0x8f, 0x9b, 0x94, 0x71, 0x78, 0x6b, 0x28, 0x9f, + 0xad, 0x29, 0x6b, 0x07, 0x65, 0x2a, 0x9b, 0x8f, 0x6a, 0xdd, 0x8b, 0xd1, 0x4e, 0x22, 0x97, 0x6f, + 0x81, 0x79, 0xca, 0x89, 0x2b, 0xa2, 0x92, 0x3b, 0x5b, 0x28, 0xbf, 0x3c, 0x63, 0xae, 0x55, 0x8e, + 0x68, 0x1d, 0xf3, 0x57, 0x04, 0x1a, 0x52, 0xa0, 0xe6, 0xef, 0xd9, 0xb1, 0x67, 0x13, 0x09, 0x0f, + 0x3f, 0x01, 0xcb, 0x72, 0xa5, 0x2a, 0x33, 0x22, 0xb7, 0xf5, 0x09, 0x27, 0xde, 0xa9, 0x7d, 0x1e, + 0xf4, 0xca, 0x09, 0x6d, 0xca, 0xf2, 0x56, 0x0a, 0x1a, 0x0d, 0xa8, 0x82, 0x17, 0x41, 0xc1, 0xa5, + 0x1e, 0x22, 0xed, 0x16, 0x75, 0xb0, 0x4a, 0xcb, 0x79, 0xf5, 0x24, 0xd5, 0xfa, 0xdb, 0x28, 0xc9, + 0x03, 0x5f, 0x04, 0x05, 0x17, 0xdf, 0x89, 0x45, 0x72, 0x52, 0xe4, 0x98, 0xd6, 0x57, 0xa8, 0xf5, + 0x49, 0x28, 0xc9, 0x07, 0x6f, 0x88, 0x6c, 0x10, 0x55, 0x9a, 0x15, 0xf3, 0xd2, 0xcd, 0xe7, 0x26, + 0x9d, 0x4f, 0x17, 0x79, 0x51, 0x22, 0x12, 0x99, 0x23, 0x21, 0x50, 0x84, 0x65, 0xfe, 0x98, 0x07, + 0x67, 0xf6, 0xbd, 0xfb, 0xf0, 0x2d, 0x00, 0xfd, 0x3a, 0x23, 0x41, 0x97, 0x34, 0x2e, 0xa9, 0xb6, + 0x48, 0xf4, 0x27, 0xc2, 0xc7, 0x39, 0xf5, 0x24, 0x5e, 0x1b, 0xa2, 0xa2, 0x11, 0x12, 0xd0, 0x01, + 0x47, 0xc4, 0x65, 0x50, 0x0e, 0xa5, 0xba, 0x15, 0x7a, 0xbc, 0x9b, 0xf6, 0xbf, 0xb0, 0x67, 0x1c, + 0xd9, 0x4c, 0x82, 0xa0, 0x34, 0x26, 0xdc, 0x00, 0x2b, 0xba, 0xd6, 0x0f, 0x38, 0xf8, 0xa4, 0xf6, + 0xc0, 0x4a, 0x35, 0x4d, 0x46, 0x83, 0xfc, 0x02, 0xa2, 0x41, 0x18, 0x0d, 0x48, 0x23, 0x86, 0xc8, + 0xa7, 0x21, 0xde, 0x48, 0x93, 0xd1, 0x20, 0x3f, 0x6c, 0x81, 0x65, 0x8d, 0xaa, 0xfd, 0x5d, 0x9c, + 0x97, 0x21, 0x7b, 0x7e, 0xca, 0x90, 0xa9, 0xa2, 0x1b, 0xe7, 0x60, 0x35, 0x85, 0x85, 0x06, 0xb0, + 0x21, 0x07, 0xc0, 0x89, 0x4a, 0x1c, 0x2b, 0x2e, 0x48, 0x4d, 0xaf, 0xcf, 0x78, 0x07, 0xe3, 0x5a, + 0xd9, 0x7f, 0xbe, 0xe2, 0x2d, 0x86, 0x12, 0x7a, 0xcc, 0xef, 0x72, 0x00, 0xf4, 0x33, 0x0c, 0xae, + 0xa7, 0x8a, 0xfc, 0xda, 0x40, 0x91, 0x3f, 0x9a, 0x6c, 0x4e, 0x13, 0x05, 0xfd, 0x26, 0x58, 0xf0, + 0xe5, 0xcd, 0xd3, 0xc9, 0x50, 0x9e, 0x64, 0x76, 0xfc, 0x96, 0xc6, 0x68, 0x15, 0x20, 0x4a, 0xa7, + 0xbe, 0xbf, 0x1a, 0x0d, 0x5e, 0x05, 0xf9, 0xb6, 0xdf, 0x88, 0x1e, 0xbf, 0x0b, 0x93, 0x50, 0xaf, + 0xfb, 0x0d, 0x96, 0xc2, 0x5c, 0x14, 0xb6, 0x8b, 0x5d, 0x24, 0x71, 0xe0, 0x87, 0x60, 0x31, 0x6a, + 0x37, 0x74, 0x6f, 0xb2, 0x3e, 0x09, 0x13, 0x69, 0xfe, 0x14, 0xee, 0x92, 0xa8, 0xa0, 0x11, 0x05, + 0xc5, 0x98, 0x02, 0x9f, 0xe8, 0x6e, 0x51, 0xd6, 0xfa, 0x29, 0xf0, 0x47, 0xb5, 0xfd, 0x0a, 0x3f, + 0xa2, 0xa0, 0x18, 0xd3, 0xfc, 0x3e, 0x07, 0x96, 0x52, 0x6d, 0xe8, 0x3f, 0x11, 0x2e, 0x95, 0xd5, + 0x07, 0x1b, 0x2e, 0x85, 0x79, 0xf0, 0xe1, 0x52, 0xb8, 0x4f, 0x2e, 0x5c, 0x09, 0xfc, 0x11, 0xe1, + 0xfa, 0x32, 0x0b, 0xe0, 0x70, 0xa6, 0x43, 0x07, 0x2c, 0xa8, 0x51, 0xe3, 0x20, 0x5e, 0xb8, 0xb8, + 0xeb, 0xd0, 0x8f, 0x99, 0x86, 0x1e, 0x18, 0x50, 0xb2, 0x53, 0x0d, 0x28, 0xe4, 0x20, 0x06, 0xb9, + 0xf8, 0x09, 0x1c, 0x37, 0xcc, 0x99, 0xdf, 0x0c, 0xba, 0x45, 0xe5, 0xf2, 0xbf, 0xd6, 0x2d, 0x4f, + 0x6d, 0x8c, 0x32, 0x7f, 0xc9, 0x80, 0xa3, 0x83, 0x45, 0x6c, 0xa6, 0x51, 0xf3, 0xee, 0xc8, 0x79, + 0x39, 0x3b, 0x93, 0xe1, 0x71, 0x5f, 0x3c, 0xe5, 0xcc, 0xfc, 0x6b, 0xfa, 0x10, 0xb3, 0xcf, 0xcb, + 0x9f, 0x8e, 0x1e, 0x2a, 0x67, 0x3b, 0xc5, 0x69, 0xad, 0x6c, 0xfa, 0xc1, 0xf2, 0x87, 0x2c, 0x38, + 0x3e, 0xaa, 0xfa, 0xc3, 0xaa, 0xfe, 0x07, 0xa4, 0x4e, 0x61, 0x27, 0xff, 0x01, 0x3d, 0xea, 0x19, + 0xc6, 0x88, 0xd1, 0x25, 0x82, 0x49, 0xfc, 0x26, 0x7a, 0x17, 0x14, 0x53, 0xbe, 0xbb, 0xc1, 0x69, + 0x8b, 0xde, 0x55, 0x4d, 0x99, 0x6a, 0x3f, 0xff, 0x1f, 0xf6, 0x8c, 0xe2, 0xf6, 0x18, 0x1e, 0x34, + 0x56, 0x7a, 0xcc, 0xbf, 0x92, 0xdc, 0x13, 0xff, 0x57, 0xf2, 0xd3, 0xb0, 0xbf, 0x54, 0xec, 0x0f, + 0xc4, 0x5f, 0xef, 0x83, 0x53, 0xe9, 0x20, 0x0d, 0x3b, 0xec, 0x4c, 0xd8, 0x33, 0x4e, 0x55, 0xc7, + 0x31, 0xa1, 0xf1, 0xf2, 0xe3, 0x32, 0x2d, 0xf7, 0x74, 0x32, 0xad, 0x72, 0xfe, 0xde, 0xc3, 0xd2, + 0xdc, 0xfd, 0x87, 0xa5, 0xb9, 0x07, 0x0f, 0x4b, 0x73, 0x9f, 0x85, 0xa5, 0xcc, 0xbd, 0xb0, 0x94, + 0xb9, 0x1f, 0x96, 0x32, 0x0f, 0xc2, 0x52, 0xe6, 0x8f, 0xb0, 0x94, 0xf9, 0xe2, 0xcf, 0xd2, 0xdc, + 0x7b, 0x87, 0x74, 0xdd, 0xfb, 0x2b, 0x00, 0x00, 0xff, 0xff, 0xe1, 0xb1, 0xdd, 0xcd, 0x57, 0x16, + 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/generated.proto index b565920c3..5cc6063d0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v2beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/types_swagger_doc_generated.go index 12cfa7649..6fa9385c2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v2beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CrossVersionObjectReference = map[string]string{ "": "CrossVersionObjectReference contains enough information to let you identify the referred resource.", "kind": "Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds\"", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/zz_generated.deepcopy.go index dc59dc2d3..fd46bd892 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/autoscaling/v2beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/generated.pb.go index 8599b6733..aa5cdf89b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1554,62 +1554,61 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 907 bytes of a gzipped FileDescriptorProto + // 893 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x41, 0x6f, 0xe3, 0x44, - 0x18, 0x8d, 0x9b, 0xa6, 0x4d, 0x26, 0x69, 0x77, 0x19, 0x54, 0x29, 0x54, 0xc8, 0x59, 0x82, 0x84, - 0x0a, 0x12, 0x36, 0xe9, 0x56, 0x08, 0x21, 0x40, 0xc2, 0x45, 0x2b, 0x51, 0xa5, 0xda, 0x32, 0x29, - 0x42, 0x42, 0x20, 0x31, 0xb6, 0xbf, 0xa4, 0x43, 0x6c, 0x8f, 0xe5, 0x99, 0x44, 0xea, 0x8d, 0x9f, - 0xc0, 0x8f, 0x40, 0xfc, 0x14, 0xd4, 0xe3, 0x1e, 0xf7, 0x14, 0x51, 0xc3, 0x9d, 0xfb, 0x9e, 0xd0, - 0x8c, 0x1d, 0xdb, 0x69, 0x13, 0xd1, 0xe5, 0x66, 0xbf, 0x79, 0xef, 0x7d, 0x33, 0xf3, 0xbd, 0xf9, - 0xd0, 0x67, 0xd3, 0x4f, 0x84, 0xc5, 0xb8, 0x3d, 0x9d, 0xb9, 0x90, 0x44, 0x20, 0x41, 0xd8, 0x73, - 0x88, 0x7c, 0x9e, 0xd8, 0xf9, 0x02, 0x8d, 0x99, 0xed, 0x52, 0xe9, 0x5d, 0xd9, 0xf3, 0x81, 0x3d, - 0x81, 0x08, 0x12, 0x2a, 0xc1, 0xb7, 0xe2, 0x84, 0x4b, 0x8e, 0xdf, 0xcc, 0x48, 0x16, 0x8d, 0x99, - 0xa5, 0x49, 0xd6, 0x7c, 0x70, 0xf8, 0xe1, 0x84, 0xc9, 0xab, 0x99, 0x6b, 0x79, 0x3c, 0xb4, 0x27, - 0x7c, 0xc2, 0x6d, 0xcd, 0x75, 0x67, 0x63, 0xfd, 0xa7, 0x7f, 0xf4, 0x57, 0xe6, 0x71, 0xd8, 0xaf, - 0x14, 0xf2, 0x78, 0x02, 0x6b, 0xea, 0x1c, 0x9e, 0x94, 0x9c, 0x90, 0x7a, 0x57, 0x2c, 0x82, 0xe4, - 0xda, 0x8e, 0xa7, 0x13, 0x05, 0x08, 0x3b, 0x04, 0x49, 0xd7, 0xa9, 0xec, 0x4d, 0xaa, 0x64, 0x16, - 0x49, 0x16, 0xc2, 0x3d, 0xc1, 0xc7, 0xff, 0x25, 0x10, 0xde, 0x15, 0x84, 0xf4, 0x9e, 0xee, 0xe9, - 0x26, 0xdd, 0x4c, 0xb2, 0xc0, 0x66, 0x91, 0x14, 0x32, 0xb9, 0x2b, 0xea, 0xff, 0x63, 0xa0, 0xfa, - 0x19, 0x77, 0xf1, 0x4f, 0xa8, 0xa9, 0x0e, 0xe0, 0x53, 0x49, 0xbb, 0xc6, 0x13, 0xe3, 0xa8, 0x7d, - 0xfc, 0x91, 0x55, 0x5e, 0x6b, 0xe1, 0x67, 0xc5, 0xd3, 0x89, 0x02, 0x84, 0xa5, 0xd8, 0xd6, 0x7c, - 0x60, 0x3d, 0x77, 0x7f, 0x06, 0x4f, 0x9e, 0x83, 0xa4, 0x0e, 0xbe, 0x59, 0xf4, 0x6a, 0xe9, 0xa2, - 0x87, 0x4a, 0x8c, 0x14, 0xae, 0xf8, 0x0b, 0xb4, 0x2d, 0x62, 0xf0, 0xba, 0x5b, 0xda, 0xfd, 0x6d, - 0x6b, 0x4d, 0xd3, 0xac, 0x33, 0xee, 0x8e, 0x62, 0xf0, 0x9c, 0x4e, 0xee, 0xb4, 0xad, 0xfe, 0x88, - 0xd6, 0xe1, 0x67, 0x68, 0x47, 0x48, 0x2a, 0x67, 0xa2, 0x5b, 0xd7, 0x0e, 0xe6, 0x46, 0x07, 0xcd, - 0x72, 0xf6, 0x73, 0x8f, 0x9d, 0xec, 0x9f, 0xe4, 0xea, 0xfe, 0x1f, 0x75, 0xd4, 0x39, 0xe3, 0xee, - 0x29, 0x8f, 0x7c, 0x26, 0x19, 0x8f, 0xf0, 0x09, 0xda, 0x96, 0xd7, 0x31, 0xe8, 0x63, 0xb7, 0x9c, - 0x27, 0xcb, 0xd2, 0x97, 0xd7, 0x31, 0xbc, 0x5a, 0xf4, 0x1e, 0x57, 0xb9, 0x0a, 0x23, 0x9a, 0x8d, - 0x87, 0xc5, 0x76, 0xb6, 0xb4, 0xee, 0x64, 0xb5, 0xdc, 0xab, 0x45, 0x6f, 0x4d, 0xa4, 0xac, 0xc2, - 0x69, 0x75, 0x53, 0x78, 0x82, 0xf6, 0x02, 0x2a, 0xe4, 0x45, 0xc2, 0x5d, 0xb8, 0x64, 0x21, 0xe4, - 0x67, 0xfc, 0xe0, 0x61, 0x3d, 0x50, 0x0a, 0xe7, 0x20, 0xdf, 0xc0, 0xde, 0xb0, 0x6a, 0x44, 0x56, - 0x7d, 0xf1, 0x1c, 0x61, 0x05, 0x5c, 0x26, 0x34, 0x12, 0xd9, 0x91, 0x54, 0xb5, 0xed, 0xd7, 0xae, - 0x76, 0x98, 0x57, 0xc3, 0xc3, 0x7b, 0x6e, 0x64, 0x4d, 0x05, 0xfc, 0x1e, 0xda, 0x49, 0x80, 0x0a, - 0x1e, 0x75, 0x1b, 0xfa, 0xba, 0x8a, 0xee, 0x10, 0x8d, 0x92, 0x7c, 0x15, 0xbf, 0x8f, 0x76, 0x43, - 0x10, 0x82, 0x4e, 0xa0, 0xbb, 0xa3, 0x89, 0x8f, 0x72, 0xe2, 0xee, 0x79, 0x06, 0x93, 0xe5, 0x7a, - 0xff, 0x77, 0x03, 0xed, 0x9e, 0x71, 0x77, 0xc8, 0x84, 0xc4, 0x3f, 0xdc, 0x8b, 0xaf, 0xf5, 0xb0, - 0xc3, 0x28, 0xb5, 0x0e, 0xef, 0xe3, 0xbc, 0x4e, 0x73, 0x89, 0x54, 0xa2, 0xfb, 0x39, 0x6a, 0x30, - 0x09, 0xa1, 0x6a, 0x75, 0xfd, 0xa8, 0x7d, 0xdc, 0xdd, 0x94, 0x3c, 0x67, 0x2f, 0x37, 0x69, 0x7c, - 0xad, 0xe8, 0x24, 0x53, 0xf5, 0xff, 0xae, 0xeb, 0x8d, 0xaa, 0x2c, 0xe3, 0x01, 0x6a, 0xc7, 0x34, - 0xa1, 0x41, 0x00, 0x01, 0x13, 0xa1, 0xde, 0x6b, 0xc3, 0x79, 0x94, 0x2e, 0x7a, 0xed, 0x8b, 0x12, - 0x26, 0x55, 0x8e, 0x92, 0x78, 0x3c, 0x8c, 0x03, 0x50, 0x97, 0x99, 0xc5, 0x2d, 0x97, 0x9c, 0x96, - 0x30, 0xa9, 0x72, 0xf0, 0x73, 0x74, 0x40, 0x3d, 0xc9, 0xe6, 0xf0, 0x15, 0x50, 0x3f, 0x60, 0x11, - 0x8c, 0xc0, 0xe3, 0x91, 0x9f, 0x3d, 0x9d, 0xba, 0xf3, 0x56, 0xba, 0xe8, 0x1d, 0x7c, 0xb9, 0x8e, - 0x40, 0xd6, 0xeb, 0xf0, 0x8f, 0xa8, 0x29, 0x20, 0x00, 0x4f, 0xf2, 0x24, 0x0f, 0xcb, 0xd3, 0x07, - 0xde, 0x2f, 0x75, 0x21, 0x18, 0xe5, 0x52, 0xa7, 0xa3, 0x2e, 0x78, 0xf9, 0x47, 0x0a, 0x4b, 0xfc, - 0x29, 0xda, 0x0f, 0x69, 0x34, 0xa3, 0x05, 0x53, 0xa7, 0xa4, 0xe9, 0xe0, 0x74, 0xd1, 0xdb, 0x3f, - 0x5f, 0x59, 0x21, 0x77, 0x98, 0xf8, 0x1b, 0xd4, 0x94, 0x10, 0xc6, 0x01, 0x95, 0x59, 0x64, 0xda, - 0xc7, 0xef, 0x56, 0xfb, 0xa3, 0x5e, 0x9e, 0xda, 0xc8, 0x05, 0xf7, 0x2f, 0x73, 0x9a, 0x1e, 0x31, - 0x45, 0xbf, 0x97, 0x28, 0x29, 0x6c, 0xf0, 0x09, 0xea, 0xb8, 0xd4, 0x9b, 0xf2, 0xf1, 0x78, 0xc8, - 0x42, 0x26, 0xbb, 0xbb, 0xfa, 0xca, 0x1f, 0xa7, 0x8b, 0x5e, 0xc7, 0xa9, 0xe0, 0x64, 0x85, 0xd5, - 0xff, 0xad, 0x8e, 0x5a, 0xc5, 0xf8, 0xc1, 0xdf, 0x22, 0xe4, 0x2d, 0x1f, 0xbb, 0xe8, 0x1a, 0x3a, - 0x38, 0xef, 0x6c, 0x0a, 0x4e, 0x31, 0x16, 0xca, 0x19, 0x5a, 0x40, 0x82, 0x54, 0x8c, 0xf0, 0x77, - 0xa8, 0x25, 0x24, 0x4d, 0xa4, 0x7e, 0xb6, 0x5b, 0xaf, 0xfd, 0x6c, 0xf7, 0xd2, 0x45, 0xaf, 0x35, - 0x5a, 0x1a, 0x90, 0xd2, 0x0b, 0x8f, 0xd1, 0x7e, 0x99, 0xa0, 0xff, 0x39, 0x82, 0x74, 0xbb, 0x4e, - 0x57, 0x5c, 0xc8, 0x1d, 0x57, 0x35, 0x08, 0xb2, 0x88, 0xe9, 0x1c, 0x35, 0xca, 0x41, 0x90, 0xe5, - 0x91, 0xe4, 0xab, 0xd8, 0x46, 0x2d, 0x31, 0xf3, 0x3c, 0x00, 0x1f, 0x7c, 0x9d, 0x86, 0x86, 0xf3, - 0x46, 0x4e, 0x6d, 0x8d, 0x96, 0x0b, 0xa4, 0xe4, 0x28, 0xe3, 0x31, 0x65, 0x01, 0xf8, 0x3a, 0x05, - 0x15, 0xe3, 0x67, 0x1a, 0x25, 0xf9, 0xaa, 0x73, 0x74, 0x73, 0x6b, 0xd6, 0x5e, 0xdc, 0x9a, 0xb5, - 0x97, 0xb7, 0x66, 0xed, 0x97, 0xd4, 0x34, 0x6e, 0x52, 0xd3, 0x78, 0x91, 0x9a, 0xc6, 0xcb, 0xd4, - 0x34, 0xfe, 0x4c, 0x4d, 0xe3, 0xd7, 0xbf, 0xcc, 0xda, 0xf7, 0x5b, 0xf3, 0xc1, 0xbf, 0x01, 0x00, - 0x00, 0xff, 0xff, 0xce, 0x80, 0xf2, 0xbe, 0x96, 0x08, 0x00, 0x00, + 0x18, 0x8d, 0x9b, 0xa6, 0x4d, 0x26, 0x69, 0xb7, 0x0c, 0xaa, 0x14, 0x2a, 0xe4, 0x2c, 0x41, 0x42, + 0x05, 0x09, 0x9b, 0x94, 0x0a, 0x21, 0x04, 0x48, 0xb8, 0x68, 0x25, 0xaa, 0x54, 0x5b, 0x26, 0x45, + 0x48, 0x08, 0x24, 0xc6, 0xf6, 0x97, 0xd4, 0xc4, 0xf6, 0x58, 0x9e, 0x49, 0xa4, 0xde, 0xf8, 0x09, + 0xfc, 0x08, 0xc4, 0x4f, 0x41, 0x3d, 0xee, 0x71, 0x4f, 0x11, 0x35, 0xdc, 0xb9, 0xef, 0x09, 0xcd, + 0x78, 0x62, 0x3b, 0x6d, 0x2a, 0xda, 0xbd, 0x79, 0xde, 0xbc, 0xf7, 0xbe, 0xf1, 0x37, 0x6f, 0x3e, + 0xf4, 0xf9, 0xf4, 0x53, 0x6e, 0x05, 0xcc, 0x9e, 0xce, 0x5c, 0x48, 0x63, 0x10, 0xc0, 0xed, 0x39, + 0xc4, 0x3e, 0x4b, 0x6d, 0xbd, 0x41, 0x93, 0xc0, 0x76, 0xa9, 0xf0, 0x2e, 0xed, 0xf9, 0xc0, 0x9e, + 0x40, 0x0c, 0x29, 0x15, 0xe0, 0x5b, 0x49, 0xca, 0x04, 0xc3, 0x6f, 0xe6, 0x24, 0x8b, 0x26, 0x81, + 0xa5, 0x48, 0xd6, 0x7c, 0x70, 0xf0, 0xe1, 0x24, 0x10, 0x97, 0x33, 0xd7, 0xf2, 0x58, 0x64, 0x4f, + 0xd8, 0x84, 0xd9, 0x8a, 0xeb, 0xce, 0xc6, 0x6a, 0xa5, 0x16, 0xea, 0x2b, 0xf7, 0x38, 0xe8, 0x57, + 0x0a, 0x79, 0x2c, 0x85, 0x35, 0x75, 0x0e, 0x8e, 0x4b, 0x4e, 0x44, 0xbd, 0xcb, 0x20, 0x86, 0xf4, + 0xca, 0x4e, 0xa6, 0x13, 0x09, 0x70, 0x3b, 0x02, 0x41, 0xd7, 0xa9, 0xec, 0xfb, 0x54, 0xe9, 0x2c, + 0x16, 0x41, 0x04, 0x77, 0x04, 0x9f, 0xfc, 0x9f, 0x80, 0x7b, 0x97, 0x10, 0xd1, 0xdb, 0xba, 0xfe, + 0xbf, 0x06, 0xaa, 0x9f, 0x32, 0x17, 0xff, 0x8c, 0x9a, 0xf2, 0x2c, 0x3e, 0x15, 0xb4, 0x6b, 0x3c, + 0x35, 0x0e, 0xdb, 0x47, 0x1f, 0x59, 0x65, 0x87, 0x0a, 0x4b, 0x2b, 0x99, 0x4e, 0x24, 0xc0, 0x2d, + 0xc9, 0xb6, 0xe6, 0x03, 0xeb, 0xb9, 0xfb, 0x0b, 0x78, 0xe2, 0x0c, 0x04, 0x75, 0xf0, 0xf5, 0xa2, + 0x57, 0xcb, 0x16, 0x3d, 0x54, 0x62, 0xa4, 0x70, 0xc5, 0x5f, 0xa2, 0x4d, 0x9e, 0x80, 0xd7, 0xdd, + 0x50, 0xee, 0x6f, 0x5b, 0x6b, 0xfa, 0x6f, 0x9d, 0x32, 0x77, 0x94, 0x80, 0xe7, 0x74, 0xb4, 0xd3, + 0xa6, 0x5c, 0x11, 0xa5, 0xc3, 0xcf, 0xd0, 0x16, 0x17, 0x54, 0xcc, 0x78, 0xb7, 0xae, 0x1c, 0xcc, + 0x7b, 0x1d, 0x14, 0xcb, 0xd9, 0xd5, 0x1e, 0x5b, 0xf9, 0x9a, 0x68, 0x75, 0xff, 0xcf, 0x3a, 0xea, + 0x9c, 0x32, 0xf7, 0x84, 0xc5, 0x7e, 0x20, 0x02, 0x16, 0xe3, 0x63, 0xb4, 0x29, 0xae, 0x12, 0x50, + 0xbf, 0xdd, 0x72, 0x9e, 0x2e, 0x4b, 0x5f, 0x5c, 0x25, 0xf0, 0x6a, 0xd1, 0xdb, 0xab, 0x72, 0x25, + 0x46, 0x14, 0x1b, 0x0f, 0x8b, 0xe3, 0x6c, 0x28, 0xdd, 0xf1, 0x6a, 0xb9, 0x57, 0x8b, 0xde, 0x9a, + 0x74, 0x58, 0x85, 0xd3, 0xea, 0xa1, 0xf0, 0x04, 0xed, 0x84, 0x94, 0x8b, 0xf3, 0x94, 0xb9, 0x70, + 0x11, 0x44, 0xa0, 0xff, 0xf1, 0x83, 0x87, 0xdd, 0x81, 0x54, 0x38, 0xfb, 0xfa, 0x00, 0x3b, 0xc3, + 0xaa, 0x11, 0x59, 0xf5, 0xc5, 0x73, 0x84, 0x25, 0x70, 0x91, 0xd2, 0x98, 0xe7, 0xbf, 0x24, 0xab, + 0x6d, 0x3e, 0xba, 0xda, 0x81, 0xae, 0x86, 0x87, 0x77, 0xdc, 0xc8, 0x9a, 0x0a, 0xf8, 0x3d, 0xb4, + 0x95, 0x02, 0xe5, 0x2c, 0xee, 0x36, 0x54, 0xbb, 0x8a, 0xdb, 0x21, 0x0a, 0x25, 0x7a, 0x17, 0xbf, + 0x8f, 0xb6, 0x23, 0xe0, 0x9c, 0x4e, 0xa0, 0xbb, 0xa5, 0x88, 0x4f, 0x34, 0x71, 0xfb, 0x2c, 0x87, + 0xc9, 0x72, 0xbf, 0xff, 0x87, 0x81, 0xb6, 0x4f, 0x99, 0x3b, 0x0c, 0xb8, 0xc0, 0x3f, 0xde, 0x89, + 0xaf, 0xf5, 0xb0, 0x9f, 0x91, 0x6a, 0x15, 0xde, 0x3d, 0x5d, 0xa7, 0xb9, 0x44, 0x2a, 0xd1, 0xfd, + 0x02, 0x35, 0x02, 0x01, 0x91, 0xbc, 0xea, 0xfa, 0x61, 0xfb, 0xa8, 0x7b, 0x5f, 0xf2, 0x9c, 0x1d, + 0x6d, 0xd2, 0xf8, 0x46, 0xd2, 0x49, 0xae, 0xea, 0xff, 0x53, 0x57, 0x07, 0x95, 0x59, 0xc6, 0x03, + 0xd4, 0x4e, 0x68, 0x4a, 0xc3, 0x10, 0xc2, 0x80, 0x47, 0xea, 0xac, 0x0d, 0xe7, 0x49, 0xb6, 0xe8, + 0xb5, 0xcf, 0x4b, 0x98, 0x54, 0x39, 0x52, 0xe2, 0xb1, 0x28, 0x09, 0x41, 0x36, 0x33, 0x8f, 0x9b, + 0x96, 0x9c, 0x94, 0x30, 0xa9, 0x72, 0xf0, 0x73, 0xb4, 0x4f, 0x3d, 0x11, 0xcc, 0xe1, 0x6b, 0xa0, + 0x7e, 0x18, 0xc4, 0x30, 0x02, 0x8f, 0xc5, 0x7e, 0xfe, 0x74, 0xea, 0xce, 0x5b, 0xd9, 0xa2, 0xb7, + 0xff, 0xd5, 0x3a, 0x02, 0x59, 0xaf, 0xc3, 0x3f, 0xa1, 0x26, 0x87, 0x10, 0x3c, 0xc1, 0x52, 0x1d, + 0x96, 0x8f, 0x1f, 0xd8, 0x5f, 0xea, 0x42, 0x38, 0xd2, 0x52, 0xa7, 0x23, 0x1b, 0xbc, 0x5c, 0x91, + 0xc2, 0x12, 0x7f, 0x86, 0x76, 0x23, 0x1a, 0xcf, 0x68, 0xc1, 0x54, 0x29, 0x69, 0x3a, 0x38, 0x5b, + 0xf4, 0x76, 0xcf, 0x56, 0x76, 0xc8, 0x2d, 0x26, 0xfe, 0x16, 0x35, 0x05, 0x44, 0x49, 0x48, 0x45, + 0x1e, 0x99, 0xf6, 0xd1, 0xbb, 0xd5, 0xfb, 0x91, 0x2f, 0x4f, 0x1e, 0xe4, 0x9c, 0xf9, 0x17, 0x9a, + 0xa6, 0x46, 0x4c, 0x71, 0xdf, 0x4b, 0x94, 0x14, 0x36, 0xf8, 0x18, 0x75, 0x5c, 0xea, 0x4d, 0xd9, + 0x78, 0x3c, 0x0c, 0xa2, 0x40, 0x74, 0xb7, 0x55, 0xcb, 0xf7, 0xb2, 0x45, 0xaf, 0xe3, 0x54, 0x70, + 0xb2, 0xc2, 0xea, 0xff, 0x5e, 0x47, 0xad, 0x62, 0xfc, 0xe0, 0xef, 0x10, 0xf2, 0x96, 0x8f, 0x9d, + 0x77, 0x0d, 0x15, 0x9c, 0x77, 0xee, 0x0b, 0x4e, 0x31, 0x16, 0xca, 0x19, 0x5a, 0x40, 0x9c, 0x54, + 0x8c, 0xf0, 0xf7, 0xa8, 0xc5, 0x05, 0x4d, 0x85, 0x7a, 0xb6, 0x1b, 0x8f, 0x7e, 0xb6, 0x3b, 0xd9, + 0xa2, 0xd7, 0x1a, 0x2d, 0x0d, 0x48, 0xe9, 0x85, 0xc7, 0x68, 0xb7, 0x4c, 0xd0, 0x6b, 0x8e, 0x20, + 0x75, 0x5d, 0x27, 0x2b, 0x2e, 0xe4, 0x96, 0xab, 0x1c, 0x04, 0x79, 0xc4, 0x54, 0x8e, 0x1a, 0xe5, + 0x20, 0xc8, 0xf3, 0x48, 0xf4, 0x2e, 0xb6, 0x51, 0x8b, 0xcf, 0x3c, 0x0f, 0xc0, 0x07, 0x5f, 0xa5, + 0xa1, 0xe1, 0xbc, 0xa1, 0xa9, 0xad, 0xd1, 0x72, 0x83, 0x94, 0x1c, 0x69, 0x3c, 0xa6, 0x41, 0x08, + 0xbe, 0x4a, 0x41, 0xc5, 0xf8, 0x99, 0x42, 0x89, 0xde, 0x75, 0x0e, 0xaf, 0x6f, 0xcc, 0xda, 0x8b, + 0x1b, 0xb3, 0xf6, 0xf2, 0xc6, 0xac, 0xfd, 0x9a, 0x99, 0xc6, 0x75, 0x66, 0x1a, 0x2f, 0x32, 0xd3, + 0x78, 0x99, 0x99, 0xc6, 0x5f, 0x99, 0x69, 0xfc, 0xf6, 0xb7, 0x59, 0xfb, 0x61, 0x63, 0x3e, 0xf8, + 0x2f, 0x00, 0x00, 0xff, 0xff, 0xdd, 0xcc, 0x84, 0xd1, 0x61, 0x08, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/generated.proto index b0306f3bc..91858b019 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/types_swagger_doc_generated.go index 0ddf4b116..2bb794a5f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_Job = map[string]string{ "": "Job represents the configuration of a single job.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/zz_generated.deepcopy.go index a7179849b..3e5250f37 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/generated.pb.go index 6544184db..ece2204f9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1456,54 +1456,54 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 784 bytes of a gzipped FileDescriptorProto + // 771 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0xcf, 0x6f, 0xe3, 0x44, 0x14, 0xc7, 0xe3, 0x34, 0xbf, 0x76, 0xc2, 0x42, 0xd7, 0xa0, 0x5d, 0x2b, 0x20, 0x27, 0x64, 0xb5, - 0x22, 0x20, 0x76, 0x4c, 0x0b, 0x42, 0x9c, 0x90, 0xd6, 0x8b, 0x16, 0x28, 0x45, 0x8b, 0x9c, 0x22, - 0x24, 0x54, 0xa1, 0x8e, 0xc7, 0x2f, 0xc9, 0x34, 0xb6, 0xc7, 0xf2, 0x8c, 0x23, 0xe5, 0xc6, 0x85, - 0x3b, 0xff, 0x08, 0x27, 0xfe, 0x89, 0x88, 0x53, 0x8f, 0x3d, 0x45, 0xd4, 0xfc, 0x17, 0x9c, 0x90, - 0x27, 0xce, 0x8f, 0xe6, 0x47, 0x5b, 0x2e, 0xbd, 0x79, 0x9e, 0xbf, 0xdf, 0xcf, 0xbc, 0x79, 0xef, - 0xcd, 0xa0, 0x17, 0xc3, 0x2f, 0x04, 0x66, 0xdc, 0x1a, 0x26, 0x2e, 0xc4, 0x21, 0x48, 0x10, 0xd6, - 0x08, 0x42, 0x8f, 0xc7, 0x56, 0xfe, 0x83, 0x44, 0xcc, 0x72, 0x89, 0xa4, 0x03, 0x6b, 0x74, 0xe0, - 0x82, 0x24, 0x07, 0x56, 0x1f, 0x42, 0x88, 0x89, 0x04, 0x0f, 0x47, 0x31, 0x97, 0x5c, 0x37, 0x66, - 0x4a, 0x4c, 0x22, 0x86, 0x95, 0x12, 0xe7, 0xca, 0xc6, 0xf3, 0x3e, 0x93, 0x83, 0xc4, 0xc5, 0x94, - 0x07, 0x56, 0x9f, 0xf7, 0xb9, 0xa5, 0x0c, 0x6e, 0xd2, 0x53, 0x2b, 0xb5, 0x50, 0x5f, 0x33, 0x50, - 0xe3, 0xe9, 0x96, 0x2d, 0xd7, 0x77, 0x6b, 0xb4, 0x57, 0x44, 0x94, 0xc7, 0xb0, 0x4d, 0xf3, 0xd9, - 0x52, 0x13, 0x10, 0x3a, 0x60, 0x21, 0xc4, 0x63, 0x2b, 0x1a, 0xf6, 0xb3, 0x80, 0xb0, 0x02, 0x90, - 0x64, 0x9b, 0xcb, 0xda, 0xe5, 0x8a, 0x93, 0x50, 0xb2, 0x00, 0x36, 0x0c, 0x9f, 0xdf, 0x66, 0x10, - 0x74, 0x00, 0x01, 0xd9, 0xf0, 0x7d, 0xba, 0xcb, 0x97, 0x48, 0xe6, 0x5b, 0x2c, 0x94, 0x42, 0xc6, - 0xeb, 0xa6, 0xf6, 0x6f, 0x45, 0x54, 0x7d, 0x19, 0xf3, 0xf0, 0x88, 0xbb, 0xfa, 0x19, 0xaa, 0x65, - 0x87, 0xf0, 0x88, 0x24, 0x86, 0xd6, 0xd2, 0x3a, 0xf5, 0xc3, 0x4f, 0xf0, 0xb2, 0x09, 0x0b, 0x26, - 0x8e, 0x86, 0xfd, 0x2c, 0x20, 0x70, 0xa6, 0xc6, 0xa3, 0x03, 0xfc, 0xda, 0x3d, 0x07, 0x2a, 0xbf, - 0x07, 0x49, 0x6c, 0x7d, 0x32, 0x6d, 0x16, 0xd2, 0x69, 0x13, 0x2d, 0x63, 0xce, 0x82, 0xaa, 0x7f, - 0x8d, 0x4a, 0x22, 0x02, 0x6a, 0x14, 0x15, 0xfd, 0x19, 0xde, 0xd5, 0x62, 0x9c, 0xa7, 0xd4, 0x8d, - 0x80, 0xda, 0x6f, 0xe4, 0xc8, 0x52, 0xb6, 0x72, 0x14, 0x40, 0x7f, 0x8d, 0x2a, 0x42, 0x12, 0x99, - 0x08, 0x63, 0x4f, 0xa1, 0x3e, 0xb8, 0x1d, 0xa5, 0xe4, 0xf6, 0x9b, 0x39, 0xac, 0x32, 0x5b, 0x3b, - 0x39, 0xa6, 0xfd, 0xa7, 0x86, 0xea, 0xb9, 0xf2, 0x98, 0x09, 0xa9, 0x9f, 0x6e, 0xd4, 0x02, 0xdf, - 0xad, 0x16, 0x99, 0x5b, 0x55, 0x62, 0x3f, 0xdf, 0xa9, 0x36, 0x8f, 0xac, 0xd4, 0xe1, 0x15, 0x2a, - 0x33, 0x09, 0x81, 0x30, 0x8a, 0xad, 0xbd, 0x4e, 0xfd, 0xf0, 0xfd, 0x5b, 0xb3, 0xb7, 0x1f, 0xe6, - 0xb4, 0xf2, 0xb7, 0x99, 0xcf, 0x99, 0xd9, 0xdb, 0x7f, 0x94, 0x16, 0x59, 0x67, 0xc5, 0xd1, 0x3f, - 0x46, 0xb5, 0x6c, 0x38, 0xbc, 0xc4, 0x07, 0x95, 0xf5, 0x83, 0x65, 0x16, 0xdd, 0x3c, 0xee, 0x2c, - 0x14, 0xfa, 0x8f, 0xe8, 0x89, 0x90, 0x24, 0x96, 0x2c, 0xec, 0x7f, 0x05, 0xc4, 0xf3, 0x59, 0x08, - 0x5d, 0xa0, 0x3c, 0xf4, 0x84, 0x6a, 0xd0, 0x9e, 0xfd, 0x6e, 0x3a, 0x6d, 0x3e, 0xe9, 0x6e, 0x97, - 0x38, 0xbb, 0xbc, 0xfa, 0x29, 0x7a, 0x44, 0x79, 0x48, 0x93, 0x38, 0x86, 0x90, 0x8e, 0x7f, 0xe0, - 0x3e, 0xa3, 0x63, 0xd5, 0xa6, 0x07, 0x36, 0xce, 0xb3, 0x79, 0xf4, 0x72, 0x5d, 0xf0, 0xef, 0xb6, - 0xa0, 0xb3, 0x09, 0xd2, 0x9f, 0xa1, 0xaa, 0x48, 0x44, 0x04, 0xa1, 0x67, 0x94, 0x5a, 0x5a, 0xa7, - 0x66, 0xd7, 0xd3, 0x69, 0xb3, 0xda, 0x9d, 0x85, 0x9c, 0xf9, 0x3f, 0xfd, 0x0c, 0xd5, 0xcf, 0xb9, - 0x7b, 0x02, 0x41, 0xe4, 0x13, 0x09, 0x46, 0x59, 0xb5, 0xf0, 0xc3, 0xdd, 0x75, 0x3e, 0x5a, 0x8a, - 0xd5, 0xd0, 0xbd, 0x9d, 0x67, 0x5a, 0x5f, 0xf9, 0xe1, 0xac, 0x22, 0xf5, 0x5f, 0x50, 0x43, 0x24, - 0x94, 0x82, 0x10, 0xbd, 0xc4, 0x3f, 0xe2, 0xae, 0xf8, 0x86, 0x09, 0xc9, 0xe3, 0xf1, 0x31, 0x0b, - 0x98, 0x34, 0x2a, 0x2d, 0xad, 0x53, 0xb6, 0xcd, 0x74, 0xda, 0x6c, 0x74, 0x77, 0xaa, 0x9c, 0x1b, - 0x08, 0xba, 0x83, 0x1e, 0xf7, 0x08, 0xf3, 0xc1, 0xdb, 0x60, 0x57, 0x15, 0xbb, 0x91, 0x4e, 0x9b, - 0x8f, 0x5f, 0x6d, 0x55, 0x38, 0x3b, 0x9c, 0xed, 0xbf, 0x34, 0xf4, 0xf0, 0xda, 0x7d, 0xd0, 0xbf, - 0x43, 0x15, 0x42, 0x25, 0x1b, 0x65, 0xf3, 0x92, 0x8d, 0xe2, 0xd3, 0xd5, 0x12, 0x65, 0x0f, 0xe1, - 0xf2, 0x7e, 0x3b, 0xd0, 0x83, 0xac, 0x13, 0xb0, 0xbc, 0x44, 0x2f, 0x94, 0xd5, 0xc9, 0x11, 0xba, - 0x8f, 0xf6, 0x7d, 0x22, 0xe4, 0x7c, 0xd4, 0x4e, 0x58, 0x00, 0xaa, 0x49, 0xf5, 0xc3, 0x8f, 0xee, - 0x76, 0x79, 0x32, 0x87, 0xfd, 0x4e, 0x3a, 0x6d, 0xee, 0x1f, 0xaf, 0x71, 0x9c, 0x0d, 0x72, 0x7b, - 0xa2, 0xa1, 0xd5, 0xee, 0xdc, 0xc3, 0xf3, 0xf5, 0x13, 0xaa, 0xc9, 0xf9, 0x44, 0x15, 0xff, 0xef, - 0x44, 0x2d, 0x6e, 0xe2, 0x62, 0x9c, 0x16, 0xb0, 0xec, 0xf5, 0x79, 0x6b, 0x4d, 0x7f, 0x0f, 0xc7, - 0xf9, 0xf2, 0xda, 0x6b, 0xfc, 0xde, 0xb6, 0xa3, 0xe0, 0x1b, 0x1e, 0x61, 0xfb, 0xf9, 0xe4, 0xca, - 0x2c, 0x5c, 0x5c, 0x99, 0x85, 0xcb, 0x2b, 0xb3, 0xf0, 0x6b, 0x6a, 0x6a, 0x93, 0xd4, 0xd4, 0x2e, - 0x52, 0x53, 0xbb, 0x4c, 0x4d, 0xed, 0xef, 0xd4, 0xd4, 0x7e, 0xff, 0xc7, 0x2c, 0xfc, 0x5c, 0xcd, - 0x0b, 0xf2, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x78, 0xe4, 0x62, 0x14, 0x08, 0x00, 0x00, + 0x22, 0x20, 0x76, 0x4c, 0x2b, 0x84, 0x38, 0x21, 0xad, 0x17, 0x2d, 0x50, 0x8a, 0x16, 0x39, 0x45, + 0x48, 0xa8, 0x42, 0x1d, 0x8f, 0x5f, 0x92, 0x69, 0x6c, 0x8f, 0xe5, 0x19, 0x47, 0xca, 0x8d, 0x0b, + 0x77, 0xfe, 0x11, 0x4e, 0xfc, 0x13, 0x11, 0xa7, 0x1e, 0x7b, 0x8a, 0xa8, 0xf9, 0x2f, 0x38, 0x21, + 0x4f, 0x9c, 0x1f, 0xcd, 0x8f, 0xb6, 0x7b, 0xe9, 0xcd, 0xf3, 0xe6, 0xfb, 0xfd, 0xcc, 0xf3, 0x7b, + 0x6f, 0x06, 0xbd, 0x18, 0x7e, 0x29, 0x30, 0xe3, 0xd6, 0x30, 0x71, 0x21, 0x0e, 0x41, 0x82, 0xb0, + 0x46, 0x10, 0x7a, 0x3c, 0xb6, 0xf2, 0x0d, 0x12, 0x31, 0xcb, 0x25, 0x92, 0x0e, 0xac, 0xd1, 0x81, + 0x0b, 0x92, 0x1c, 0x58, 0x7d, 0x08, 0x21, 0x26, 0x12, 0x3c, 0x1c, 0xc5, 0x5c, 0x72, 0xdd, 0x98, + 0x29, 0x31, 0x89, 0x18, 0x56, 0x4a, 0x9c, 0x2b, 0x1b, 0xcf, 0xfb, 0x4c, 0x0e, 0x12, 0x17, 0x53, + 0x1e, 0x58, 0x7d, 0xde, 0xe7, 0x96, 0x32, 0xb8, 0x49, 0x4f, 0xad, 0xd4, 0x42, 0x7d, 0xcd, 0x40, + 0x8d, 0xa7, 0x5b, 0x8e, 0x5c, 0x3f, 0xad, 0xd1, 0x5e, 0x11, 0x51, 0x1e, 0xc3, 0x36, 0xcd, 0xe7, + 0x4b, 0x4d, 0x40, 0xe8, 0x80, 0x85, 0x10, 0x8f, 0xad, 0x68, 0xd8, 0xcf, 0x02, 0xc2, 0x0a, 0x40, + 0x92, 0x6d, 0x2e, 0x6b, 0x97, 0x2b, 0x4e, 0x42, 0xc9, 0x02, 0xd8, 0x30, 0x7c, 0x71, 0x9b, 0x41, + 0xd0, 0x01, 0x04, 0x64, 0xdd, 0xd7, 0xfe, 0xbd, 0x88, 0xaa, 0x2f, 0x63, 0x1e, 0x1e, 0x71, 0x57, + 0x3f, 0x43, 0xb5, 0x2c, 0x1f, 0x8f, 0x48, 0x62, 0x68, 0x2d, 0xad, 0x53, 0x3f, 0xfc, 0x0c, 0x2f, + 0xeb, 0xb9, 0xc0, 0xe2, 0x68, 0xd8, 0xcf, 0x02, 0x02, 0x67, 0x6a, 0x3c, 0x3a, 0xc0, 0xaf, 0xdd, + 0x73, 0xa0, 0xf2, 0x07, 0x90, 0xc4, 0xd6, 0x27, 0xd3, 0x66, 0x21, 0x9d, 0x36, 0xd1, 0x32, 0xe6, + 0x2c, 0xa8, 0xfa, 0x37, 0xa8, 0x24, 0x22, 0xa0, 0x46, 0x51, 0xd1, 0x9f, 0xe1, 0x5d, 0xdd, 0xc2, + 0x79, 0x4a, 0xdd, 0x08, 0xa8, 0xfd, 0x56, 0x8e, 0x2c, 0x65, 0x2b, 0x47, 0x01, 0xf4, 0xd7, 0xa8, + 0x22, 0x24, 0x91, 0x89, 0x30, 0xf6, 0x14, 0xea, 0xa3, 0xdb, 0x51, 0x4a, 0x6e, 0xbf, 0x9d, 0xc3, + 0x2a, 0xb3, 0xb5, 0x93, 0x63, 0xda, 0x7f, 0x69, 0xa8, 0x9e, 0x2b, 0x8f, 0x99, 0x90, 0xfa, 0xe9, + 0x46, 0x2d, 0xf0, 0xdd, 0x6a, 0x91, 0xb9, 0x55, 0x25, 0xf6, 0xf3, 0x93, 0x6a, 0xf3, 0xc8, 0x4a, + 0x1d, 0x5e, 0xa1, 0x32, 0x93, 0x10, 0x08, 0xa3, 0xd8, 0xda, 0xeb, 0xd4, 0x0f, 0x3f, 0xbc, 0x35, + 0x7b, 0xfb, 0x61, 0x4e, 0x2b, 0x7f, 0x97, 0xf9, 0x9c, 0x99, 0xbd, 0xfd, 0x67, 0x69, 0x91, 0x75, + 0x56, 0x1c, 0xfd, 0x53, 0x54, 0xcb, 0xfa, 0xec, 0x25, 0x3e, 0xa8, 0xac, 0x1f, 0x2c, 0xb3, 0xe8, + 0xe6, 0x71, 0x67, 0xa1, 0xd0, 0x7f, 0x42, 0x4f, 0x84, 0x24, 0xb1, 0x64, 0x61, 0xff, 0x6b, 0x20, + 0x9e, 0xcf, 0x42, 0xe8, 0x02, 0xe5, 0xa1, 0x27, 0x54, 0x83, 0xf6, 0xec, 0xf7, 0xd3, 0x69, 0xf3, + 0x49, 0x77, 0xbb, 0xc4, 0xd9, 0xe5, 0xd5, 0x4f, 0xd1, 0x23, 0xca, 0x43, 0x9a, 0xc4, 0x31, 0x84, + 0x74, 0xfc, 0x23, 0xf7, 0x19, 0x1d, 0xab, 0x36, 0x3d, 0xb0, 0x71, 0x9e, 0xcd, 0xa3, 0x97, 0xeb, + 0x82, 0xff, 0xb6, 0x05, 0x9d, 0x4d, 0x90, 0xfe, 0x0c, 0x55, 0x45, 0x22, 0x22, 0x08, 0x3d, 0xa3, + 0xd4, 0xd2, 0x3a, 0x35, 0xbb, 0x9e, 0x4e, 0x9b, 0xd5, 0xee, 0x2c, 0xe4, 0xcc, 0xf7, 0xf4, 0x33, + 0x54, 0x3f, 0xe7, 0xee, 0x09, 0x04, 0x91, 0x4f, 0x24, 0x18, 0x65, 0xd5, 0xc2, 0x8f, 0x77, 0xd7, + 0xf9, 0x68, 0x29, 0x56, 0x43, 0xf7, 0x6e, 0x9e, 0x69, 0x7d, 0x65, 0xc3, 0x59, 0x45, 0xea, 0xbf, + 0xa2, 0x86, 0x48, 0x28, 0x05, 0x21, 0x7a, 0x89, 0x7f, 0xc4, 0x5d, 0xf1, 0x2d, 0x13, 0x92, 0xc7, + 0xe3, 0x63, 0x16, 0x30, 0x69, 0x54, 0x5a, 0x5a, 0xa7, 0x6c, 0x9b, 0xe9, 0xb4, 0xd9, 0xe8, 0xee, + 0x54, 0x39, 0x37, 0x10, 0x74, 0x07, 0x3d, 0xee, 0x11, 0xe6, 0x83, 0xb7, 0xc1, 0xae, 0x2a, 0x76, + 0x23, 0x9d, 0x36, 0x1f, 0xbf, 0xda, 0xaa, 0x70, 0x76, 0x38, 0xdb, 0x7f, 0x6b, 0xe8, 0xe1, 0xb5, + 0xfb, 0xa0, 0x7f, 0x8f, 0x2a, 0x84, 0x4a, 0x36, 0xca, 0xe6, 0x25, 0x1b, 0xc5, 0xa7, 0xab, 0x25, + 0xca, 0xde, 0xb4, 0xe5, 0xfd, 0x76, 0xa0, 0x07, 0x59, 0x27, 0x60, 0x79, 0x89, 0x5e, 0x28, 0xab, + 0x93, 0x23, 0x74, 0x1f, 0xed, 0xfb, 0x44, 0xc8, 0xf9, 0xa8, 0x9d, 0xb0, 0x00, 0x54, 0x93, 0xea, + 0x87, 0x9f, 0xdc, 0xed, 0xf2, 0x64, 0x0e, 0xfb, 0xbd, 0x74, 0xda, 0xdc, 0x3f, 0x5e, 0xe3, 0x38, + 0x1b, 0xe4, 0xf6, 0x44, 0x43, 0xab, 0xdd, 0xb9, 0x87, 0xe7, 0xeb, 0x67, 0x54, 0x93, 0xf3, 0x89, + 0x2a, 0xbe, 0xe9, 0x44, 0x2d, 0x6e, 0xe2, 0x62, 0x9c, 0x16, 0xb0, 0xec, 0xf5, 0x79, 0x67, 0x4d, + 0x7f, 0x0f, 0xbf, 0xf3, 0xd5, 0xb5, 0xd7, 0xf8, 0x83, 0x6d, 0xbf, 0x82, 0x6f, 0x78, 0x84, 0xed, + 0xe7, 0x93, 0x2b, 0xb3, 0x70, 0x71, 0x65, 0x16, 0x2e, 0xaf, 0xcc, 0xc2, 0x6f, 0xa9, 0xa9, 0x4d, + 0x52, 0x53, 0xbb, 0x48, 0x4d, 0xed, 0x32, 0x35, 0xb5, 0x7f, 0x52, 0x53, 0xfb, 0xe3, 0x5f, 0xb3, + 0xf0, 0x4b, 0x35, 0x2f, 0xc8, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf6, 0x9f, 0xb3, 0xdd, 0xdf, + 0x07, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/generated.proto index 9278a3d9b..043b3551b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/types_swagger_doc_generated.go index 3b53ac08a..abbdfec01 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CronJob = map[string]string{ "": "CronJob represents the configuration of a single cron job.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/zz_generated.deepcopy.go index 78e361aba..a33f4ffcf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/generated.pb.go index 2560953eb..6ab41ebbc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1456,55 +1456,54 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 787 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0xcf, 0x6f, 0xe3, 0x44, - 0x14, 0xc7, 0xe3, 0x34, 0xbf, 0x3a, 0xa1, 0xd0, 0x1a, 0xd4, 0x86, 0x80, 0x9c, 0xc8, 0x15, 0x28, - 0x42, 0x30, 0xa6, 0x05, 0x21, 0x4e, 0x48, 0xb8, 0x08, 0x4a, 0x29, 0xa2, 0x72, 0x8a, 0x84, 0x50, - 0xb5, 0xda, 0xf1, 0x78, 0x92, 0x4c, 0x63, 0x7b, 0x2c, 0xcf, 0x38, 0x52, 0x6e, 0x7b, 0xdb, 0xeb, - 0xfe, 0x25, 0x7b, 0xd9, 0xfd, 0x23, 0xba, 0x7b, 0xea, 0xb1, 0xa7, 0x68, 0xeb, 0xfd, 0x2f, 0xf6, - 0xb4, 0xf2, 0xc4, 0xf9, 0xd1, 0x38, 0x69, 0xbb, 0x97, 0xde, 0x3c, 0xcf, 0xdf, 0xef, 0x67, 0xde, - 0xbc, 0xf7, 0x66, 0x80, 0xd9, 0xff, 0x99, 0x43, 0xca, 0x8c, 0x7e, 0x64, 0x93, 0xd0, 0x27, 0x82, - 0x70, 0x63, 0x40, 0x7c, 0x87, 0x85, 0x46, 0xfa, 0x03, 0x05, 0xd4, 0xb0, 0x91, 0xc0, 0x3d, 0x63, - 0xb0, 0x8f, 0xdc, 0xa0, 0x87, 0xf6, 0x8c, 0x2e, 0xf1, 0x49, 0x88, 0x04, 0x71, 0x60, 0x10, 0x32, - 0xc1, 0xd4, 0xcf, 0xc7, 0x52, 0x88, 0x02, 0x0a, 0xa5, 0x14, 0x4e, 0xa4, 0xf5, 0xef, 0xba, 0x54, - 0xf4, 0x22, 0x1b, 0x62, 0xe6, 0x19, 0x5d, 0xd6, 0x65, 0x86, 0x74, 0xd8, 0x51, 0x47, 0xae, 0xe4, - 0x42, 0x7e, 0x8d, 0x49, 0xf5, 0xdd, 0xec, 0xa6, 0x99, 0xed, 0xea, 0xfa, 0x9c, 0x08, 0xb3, 0x90, - 0x2c, 0xd3, 0xfc, 0x38, 0xd3, 0x78, 0x08, 0xf7, 0xa8, 0x4f, 0xc2, 0xa1, 0x11, 0xf4, 0xbb, 0x49, - 0x80, 0x1b, 0x1e, 0x11, 0x68, 0x99, 0xcb, 0x58, 0xe5, 0x0a, 0x23, 0x5f, 0x50, 0x8f, 0x64, 0x0c, - 0x3f, 0xdd, 0x65, 0xe0, 0xb8, 0x47, 0x3c, 0x94, 0xf1, 0xfd, 0xb0, 0xca, 0x17, 0x09, 0xea, 0x1a, - 0xd4, 0x17, 0x5c, 0x84, 0x8b, 0x26, 0xfd, 0x69, 0x1e, 0x94, 0x0f, 0x42, 0xe6, 0x1f, 0x31, 0x5b, - 0x7d, 0x0c, 0x2a, 0xc9, 0x21, 0x1c, 0x24, 0x50, 0x4d, 0x69, 0x2a, 0xad, 0xea, 0xfe, 0xf7, 0x70, - 0xd6, 0x85, 0x29, 0x13, 0x06, 0xfd, 0x6e, 0x12, 0xe0, 0x30, 0x51, 0xc3, 0xc1, 0x1e, 0xfc, 0xc7, - 0x3e, 0x27, 0x58, 0xfc, 0x4d, 0x04, 0x32, 0xd5, 0x8b, 0x51, 0x23, 0x17, 0x8f, 0x1a, 0x60, 0x16, - 0xb3, 0xa6, 0x54, 0xf5, 0x10, 0x14, 0x78, 0x40, 0x70, 0x2d, 0x2f, 0xe9, 0x5f, 0xc3, 0x95, 0x3d, - 0x86, 0x69, 0x4e, 0xed, 0x80, 0x60, 0xf3, 0xa3, 0x94, 0x59, 0x48, 0x56, 0x96, 0x24, 0xa8, 0x27, - 0xa0, 0xc4, 0x05, 0x12, 0x11, 0xaf, 0xad, 0x49, 0x56, 0xeb, 0x1e, 0x2c, 0xa9, 0x37, 0x3f, 0x4e, - 0x69, 0xa5, 0xf1, 0xda, 0x4a, 0x39, 0xfa, 0x4b, 0x05, 0x54, 0x53, 0xe5, 0x31, 0xe5, 0x42, 0x3d, - 0xcb, 0x54, 0x03, 0xde, 0xaf, 0x1a, 0x89, 0x5b, 0xd6, 0x62, 0x33, 0xdd, 0xa9, 0x32, 0x89, 0xcc, - 0x55, 0xe2, 0x0f, 0x50, 0xa4, 0x82, 0x78, 0xbc, 0x96, 0x6f, 0xae, 0xb5, 0xaa, 0xfb, 0xfa, 0xdd, - 0xe9, 0x9b, 0x1b, 0x29, 0xae, 0xf8, 0x67, 0x62, 0xb4, 0xc6, 0x7e, 0xfd, 0x79, 0x61, 0x9a, 0x76, - 0x52, 0x1e, 0xf5, 0x5b, 0x50, 0x49, 0xe6, 0xc3, 0x89, 0x5c, 0x22, 0xd3, 0x5e, 0x9f, 0xa5, 0xd1, - 0x4e, 0xe3, 0xd6, 0x54, 0xa1, 0xfe, 0x0b, 0x76, 0xb8, 0x40, 0xa1, 0xa0, 0x7e, 0xf7, 0x37, 0x82, - 0x1c, 0x97, 0xfa, 0xa4, 0x4d, 0x30, 0xf3, 0x1d, 0x2e, 0x7b, 0xb4, 0x66, 0x7e, 0x11, 0x8f, 0x1a, - 0x3b, 0xed, 0xe5, 0x12, 0x6b, 0x95, 0x57, 0x3d, 0x03, 0x5b, 0x98, 0xf9, 0x38, 0x0a, 0x43, 0xe2, - 0xe3, 0xe1, 0x09, 0x73, 0x29, 0x1e, 0xca, 0x46, 0xad, 0x9b, 0x30, 0xcd, 0x66, 0xeb, 0x60, 0x51, - 0xf0, 0x6e, 0x59, 0xd0, 0xca, 0x82, 0xd4, 0xaf, 0x40, 0x99, 0x47, 0x3c, 0x20, 0xbe, 0x53, 0x2b, - 0x34, 0x95, 0x56, 0xc5, 0xac, 0xc6, 0xa3, 0x46, 0xb9, 0x3d, 0x0e, 0x59, 0x93, 0x7f, 0x2a, 0x02, - 0xd5, 0x73, 0x66, 0x9f, 0x12, 0x2f, 0x70, 0x91, 0x20, 0xb5, 0xa2, 0xec, 0xe1, 0x37, 0xb7, 0x14, - 0xfa, 0x68, 0xa6, 0x96, 0x73, 0xf7, 0x69, 0x9a, 0x6a, 0x75, 0xee, 0x87, 0x35, 0xcf, 0x54, 0x1f, - 0x81, 0x3a, 0x8f, 0x30, 0x26, 0x9c, 0x77, 0x22, 0xf7, 0x88, 0xd9, 0xfc, 0x90, 0x72, 0xc1, 0xc2, - 0xe1, 0x31, 0xf5, 0xa8, 0xa8, 0x95, 0x9a, 0x4a, 0xab, 0x68, 0x6a, 0xf1, 0xa8, 0x51, 0x6f, 0xaf, - 0x54, 0x59, 0xb7, 0x10, 0x54, 0x0b, 0x6c, 0x77, 0x10, 0x75, 0x89, 0x93, 0x61, 0x97, 0x25, 0xbb, - 0x1e, 0x8f, 0x1a, 0xdb, 0xbf, 0x2f, 0x55, 0x58, 0x2b, 0x9c, 0xfa, 0x6b, 0x05, 0x6c, 0xdc, 0xb8, - 0x11, 0xea, 0x5f, 0xa0, 0x84, 0xb0, 0xa0, 0x83, 0x64, 0x60, 0x92, 0x61, 0xdc, 0x9d, 0xaf, 0x51, - 0xf2, 0x18, 0xce, 0xee, 0xb8, 0x45, 0x3a, 0x24, 0x69, 0x05, 0x99, 0x5d, 0xa3, 0x5f, 0xa5, 0xd5, - 0x4a, 0x11, 0xaa, 0x0b, 0x36, 0x5d, 0xc4, 0xc5, 0x64, 0xd6, 0x4e, 0xa9, 0x47, 0x64, 0x97, 0x6e, - 0x96, 0xfe, 0x96, 0xeb, 0x93, 0x38, 0xcc, 0xcf, 0xe2, 0x51, 0x63, 0xf3, 0x78, 0x81, 0x63, 0x65, - 0xc8, 0xfa, 0x2b, 0x05, 0xcc, 0x77, 0xe7, 0x01, 0x9e, 0xb0, 0xff, 0x40, 0x45, 0x4c, 0x46, 0x2a, - 0xff, 0xc1, 0x23, 0x35, 0xbd, 0x8b, 0xd3, 0x79, 0x9a, 0xd2, 0xf4, 0x17, 0x0a, 0xf8, 0x64, 0x41, - 0xff, 0x00, 0xe7, 0xf9, 0xe5, 0xc6, 0x93, 0xfc, 0xe5, 0x92, 0xb3, 0xc8, 0x53, 0xac, 0x7a, 0x88, - 0x4d, 0x78, 0x71, 0xad, 0xe5, 0x2e, 0xaf, 0xb5, 0xdc, 0xd5, 0xb5, 0x96, 0x7b, 0x12, 0x6b, 0xca, - 0x45, 0xac, 0x29, 0x97, 0xb1, 0xa6, 0x5c, 0xc5, 0x9a, 0xf2, 0x26, 0xd6, 0x94, 0x67, 0x6f, 0xb5, - 0xdc, 0xff, 0x95, 0x49, 0x45, 0xde, 0x07, 0x00, 0x00, 0xff, 0xff, 0x02, 0x60, 0xaa, 0x00, 0x1c, - 0x08, 0x00, 0x00, + // 774 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0x4d, 0x6f, 0xdb, 0x36, + 0x18, 0xc7, 0x2d, 0xc7, 0x6f, 0xa1, 0x97, 0x2d, 0xd1, 0x86, 0xc4, 0xf3, 0x06, 0xd9, 0x50, 0xb0, + 0xc1, 0x18, 0x36, 0x6a, 0x09, 0x86, 0x61, 0xa7, 0x01, 0x53, 0x86, 0x36, 0x4d, 0x53, 0x34, 0x90, + 0x53, 0xa0, 0x28, 0x82, 0xa2, 0x14, 0x45, 0xdb, 0x8c, 0x25, 0x51, 0x10, 0x29, 0x03, 0xbe, 0xf5, + 0xd6, 0x6b, 0x3f, 0x49, 0x2f, 0xed, 0x87, 0x48, 0x7b, 0xca, 0x31, 0x27, 0xa3, 0x51, 0xbf, 0x45, + 0x4f, 0x85, 0x68, 0xf9, 0x25, 0x7e, 0x49, 0xd2, 0x4b, 0x6e, 0xe2, 0xa3, 0xff, 0xff, 0xc7, 0x87, + 0xcf, 0xf3, 0x90, 0xc0, 0xec, 0xfe, 0xc3, 0x21, 0x65, 0x46, 0x37, 0xb2, 0x49, 0xe8, 0x13, 0x41, + 0xb8, 0xd1, 0x23, 0xbe, 0xc3, 0x42, 0x23, 0xfd, 0x81, 0x02, 0x6a, 0xd8, 0x48, 0xe0, 0x8e, 0xd1, + 0xdb, 0x45, 0x6e, 0xd0, 0x41, 0x3b, 0x46, 0x9b, 0xf8, 0x24, 0x44, 0x82, 0x38, 0x30, 0x08, 0x99, + 0x60, 0xea, 0x8f, 0x43, 0x29, 0x44, 0x01, 0x85, 0x52, 0x0a, 0x47, 0xd2, 0xea, 0x1f, 0x6d, 0x2a, + 0x3a, 0x91, 0x0d, 0x31, 0xf3, 0x8c, 0x36, 0x6b, 0x33, 0x43, 0x3a, 0xec, 0xa8, 0x25, 0x57, 0x72, + 0x21, 0xbf, 0x86, 0xa4, 0xea, 0xf6, 0xfc, 0xa6, 0x73, 0xdb, 0x55, 0xf5, 0x29, 0x11, 0x66, 0x21, + 0x59, 0xa4, 0xf9, 0x6b, 0xa2, 0xf1, 0x10, 0xee, 0x50, 0x9f, 0x84, 0x7d, 0x23, 0xe8, 0xb6, 0x93, + 0x00, 0x37, 0x3c, 0x22, 0xd0, 0x22, 0x97, 0xb1, 0xcc, 0x15, 0x46, 0xbe, 0xa0, 0x1e, 0x99, 0x33, + 0xfc, 0x7d, 0x93, 0x81, 0xe3, 0x0e, 0xf1, 0xd0, 0xac, 0x4f, 0x7f, 0x95, 0x05, 0xc5, 0xbd, 0x90, + 0xf9, 0x07, 0xcc, 0x56, 0x5f, 0x80, 0x52, 0x92, 0x8f, 0x83, 0x04, 0xaa, 0x28, 0x75, 0xa5, 0x51, + 0xde, 0xfd, 0x13, 0x4e, 0x0a, 0x3a, 0xc6, 0xc2, 0xa0, 0xdb, 0x4e, 0x02, 0x1c, 0x26, 0x6a, 0xd8, + 0xdb, 0x81, 0x8f, 0xed, 0x53, 0x82, 0xc5, 0x23, 0x22, 0x90, 0xa9, 0x9e, 0x0d, 0x6a, 0x99, 0x78, + 0x50, 0x03, 0x93, 0x98, 0x35, 0xa6, 0xaa, 0xfb, 0x20, 0xc7, 0x03, 0x82, 0x2b, 0x59, 0x49, 0xff, + 0x15, 0x2e, 0x6d, 0x17, 0x4c, 0x73, 0x6a, 0x06, 0x04, 0x9b, 0xdf, 0xa4, 0xcc, 0x5c, 0xb2, 0xb2, + 0x24, 0x41, 0x3d, 0x02, 0x05, 0x2e, 0x90, 0x88, 0x78, 0x65, 0x45, 0xb2, 0x1a, 0xb7, 0x60, 0x49, + 0xbd, 0xf9, 0x6d, 0x4a, 0x2b, 0x0c, 0xd7, 0x56, 0xca, 0xd1, 0xdf, 0x29, 0xa0, 0x9c, 0x2a, 0x0f, + 0x29, 0x17, 0xea, 0xc9, 0x5c, 0x35, 0xe0, 0xed, 0xaa, 0x91, 0xb8, 0x65, 0x2d, 0xd6, 0xd3, 0x9d, + 0x4a, 0xa3, 0xc8, 0x54, 0x25, 0xee, 0x83, 0x3c, 0x15, 0xc4, 0xe3, 0x95, 0x6c, 0x7d, 0xa5, 0x51, + 0xde, 0xd5, 0x6f, 0x4e, 0xdf, 0x5c, 0x4b, 0x71, 0xf9, 0x07, 0x89, 0xd1, 0x1a, 0xfa, 0xf5, 0x37, + 0xb9, 0x71, 0xda, 0x49, 0x79, 0xd4, 0xdf, 0x41, 0x29, 0x69, 0xb5, 0x13, 0xb9, 0x44, 0xa6, 0xbd, + 0x3a, 0x49, 0xa3, 0x99, 0xc6, 0xad, 0xb1, 0x42, 0x7d, 0x02, 0xb6, 0xb8, 0x40, 0xa1, 0xa0, 0x7e, + 0xfb, 0x7f, 0x82, 0x1c, 0x97, 0xfa, 0xa4, 0x49, 0x30, 0xf3, 0x1d, 0x2e, 0x7b, 0xb4, 0x62, 0xfe, + 0x14, 0x0f, 0x6a, 0x5b, 0xcd, 0xc5, 0x12, 0x6b, 0x99, 0x57, 0x3d, 0x01, 0x1b, 0x98, 0xf9, 0x38, + 0x0a, 0x43, 0xe2, 0xe3, 0xfe, 0x11, 0x73, 0x29, 0xee, 0xcb, 0x46, 0xad, 0x9a, 0x30, 0xcd, 0x66, + 0x63, 0x6f, 0x56, 0xf0, 0x79, 0x51, 0xd0, 0x9a, 0x07, 0xa9, 0xbf, 0x80, 0x22, 0x8f, 0x78, 0x40, + 0x7c, 0xa7, 0x92, 0xab, 0x2b, 0x8d, 0x92, 0x59, 0x8e, 0x07, 0xb5, 0x62, 0x73, 0x18, 0xb2, 0x46, + 0xff, 0x54, 0x04, 0xca, 0xa7, 0xcc, 0x3e, 0x26, 0x5e, 0xe0, 0x22, 0x41, 0x2a, 0x79, 0xd9, 0xc3, + 0xdf, 0xae, 0x29, 0xf4, 0xc1, 0x44, 0x2d, 0xe7, 0xee, 0xfb, 0x34, 0xd5, 0xf2, 0xd4, 0x0f, 0x6b, + 0x9a, 0xa9, 0x3e, 0x07, 0x55, 0x1e, 0x61, 0x4c, 0x38, 0x6f, 0x45, 0xee, 0x01, 0xb3, 0xf9, 0x3e, + 0xe5, 0x82, 0x85, 0xfd, 0x43, 0xea, 0x51, 0x51, 0x29, 0xd4, 0x95, 0x46, 0xde, 0xd4, 0xe2, 0x41, + 0xad, 0xda, 0x5c, 0xaa, 0xb2, 0xae, 0x21, 0xa8, 0x16, 0xd8, 0x6c, 0x21, 0xea, 0x12, 0x67, 0x8e, + 0x5d, 0x94, 0xec, 0x6a, 0x3c, 0xa8, 0x6d, 0xde, 0x5b, 0xa8, 0xb0, 0x96, 0x38, 0xf5, 0x0f, 0x0a, + 0x58, 0xbb, 0x72, 0x23, 0xd4, 0x87, 0xa0, 0x80, 0xb0, 0xa0, 0xbd, 0x64, 0x60, 0x92, 0x61, 0xdc, + 0x9e, 0xae, 0x51, 0xf2, 0xae, 0x4d, 0xee, 0xb8, 0x45, 0x5a, 0x24, 0x69, 0x05, 0x99, 0x5c, 0xa3, + 0xff, 0xa4, 0xd5, 0x4a, 0x11, 0xaa, 0x0b, 0xd6, 0x5d, 0xc4, 0xc5, 0x68, 0xd6, 0x8e, 0xa9, 0x47, + 0x64, 0x97, 0xae, 0x96, 0xfe, 0x9a, 0xeb, 0x93, 0x38, 0xcc, 0x1f, 0xe2, 0x41, 0x6d, 0xfd, 0x70, + 0x86, 0x63, 0xcd, 0x91, 0xf5, 0xf7, 0x0a, 0x98, 0xee, 0xce, 0x1d, 0x3c, 0x61, 0x4f, 0x41, 0x49, + 0x8c, 0x46, 0x2a, 0xfb, 0xd5, 0x23, 0x35, 0xbe, 0x8b, 0xe3, 0x79, 0x1a, 0xd3, 0xf4, 0xb7, 0x0a, + 0xf8, 0x6e, 0x46, 0x7f, 0x07, 0xe7, 0xf9, 0xf7, 0xca, 0x93, 0xfc, 0xf3, 0x82, 0xb3, 0xc8, 0x53, + 0x2c, 0x7b, 0x88, 0x4d, 0x78, 0x76, 0xa9, 0x65, 0xce, 0x2f, 0xb5, 0xcc, 0xc5, 0xa5, 0x96, 0x79, + 0x19, 0x6b, 0xca, 0x59, 0xac, 0x29, 0xe7, 0xb1, 0xa6, 0x5c, 0xc4, 0x9a, 0xf2, 0x31, 0xd6, 0x94, + 0xd7, 0x9f, 0xb4, 0xcc, 0xb3, 0xd2, 0xa8, 0x22, 0x5f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x20, 0x1c, + 0xcf, 0x94, 0xe7, 0x07, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/generated.proto index e4de3644c..4321c3361 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v2alpha1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/types_swagger_doc_generated.go index d166b807f..f448a92cf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v2alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CronJob = map[string]string{ "": "CronJob represents the configuration of a single cron job.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/zz_generated.deepcopy.go index d8352bfbe..bf0da8bf4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/batch/v2alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/generated.pb.go index 7f704bf82..eda159900 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1638,56 +1638,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 816 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x6f, 0x1b, 0x45, - 0x18, 0xf6, 0xfa, 0x2b, 0xf6, 0x38, 0xa4, 0xd5, 0x08, 0x55, 0x4b, 0xa4, 0xee, 0x46, 0x2b, 0x40, - 0xe1, 0xa3, 0xb3, 0xa4, 0x20, 0x88, 0x72, 0x40, 0xb0, 0xa1, 0x82, 0x88, 0x56, 0x48, 0xd3, 0x86, - 0x03, 0x42, 0xa2, 0xe3, 0xf5, 0xdb, 0xcd, 0xd4, 0xd9, 0x0f, 0x76, 0x66, 0x0d, 0xbe, 0xf5, 0x27, - 0x70, 0xe4, 0x82, 0xc4, 0x2f, 0xe1, 0x1c, 0x0e, 0x48, 0x3d, 0xf6, 0x80, 0x2c, 0x62, 0xfe, 0x45, - 0x4f, 0x68, 0x66, 0xc7, 0x5e, 0x63, 0xcb, 0x75, 0xd5, 0xdc, 0xf6, 0x7d, 0xde, 0xf7, 0x79, 0xde, - 0xcf, 0x59, 0xf4, 0xd5, 0xf0, 0x50, 0x10, 0x9e, 0xfa, 0xc3, 0xa2, 0x0f, 0x79, 0x02, 0x12, 0x84, - 0x3f, 0x82, 0x64, 0x90, 0xe6, 0xbe, 0x71, 0xb0, 0x8c, 0xfb, 0x21, 0xe4, 0x92, 0x3f, 0xe2, 0x21, - 0xd3, 0xee, 0x83, 0x3e, 0x48, 0x76, 0xe0, 0x47, 0x90, 0x40, 0xce, 0x24, 0x0c, 0x48, 0x96, 0xa7, - 0x32, 0xc5, 0x6e, 0x49, 0x20, 0x2c, 0xe3, 0x64, 0x91, 0x40, 0x0c, 0x61, 0xf7, 0x56, 0xc4, 0xe5, - 0x59, 0xd1, 0x27, 0x61, 0x1a, 0xfb, 0x51, 0x1a, 0xa5, 0xbe, 0xe6, 0xf5, 0x8b, 0x47, 0xda, 0xd2, - 0x86, 0xfe, 0x2a, 0xf5, 0x76, 0x3f, 0xaa, 0x0a, 0x88, 0x59, 0x78, 0xc6, 0x13, 0xc8, 0xc7, 0x7e, - 0x36, 0x8c, 0x14, 0x20, 0xfc, 0x18, 0x24, 0xf3, 0x47, 0x2b, 0x55, 0xec, 0xfa, 0xeb, 0x58, 0x79, - 0x91, 0x48, 0x1e, 0xc3, 0x0a, 0xe1, 0xe3, 0x4d, 0x04, 0x11, 0x9e, 0x41, 0xcc, 0x56, 0x78, 0x1f, - 0xae, 0xe3, 0x15, 0x92, 0x9f, 0xfb, 0x3c, 0x91, 0x42, 0xe6, 0xcb, 0x24, 0xef, 0xcf, 0x3a, 0x7a, - 0xe3, 0xb8, 0x9a, 0xcd, 0x7d, 0x1e, 0x25, 0x3c, 0x89, 0x28, 0xfc, 0x58, 0x80, 0x90, 0xf8, 0x21, - 0xea, 0xa8, 0xb6, 0x06, 0x4c, 0x32, 0xdb, 0xda, 0xb3, 0xf6, 0x7b, 0xb7, 0x3f, 0x20, 0xd5, 0x50, - 0xe7, 0x59, 0x48, 0x36, 0x8c, 0x14, 0x20, 0x88, 0x8a, 0x26, 0xa3, 0x03, 0xf2, 0x4d, 0xff, 0x31, - 0x84, 0xf2, 0x1e, 0x48, 0x16, 0xe0, 0x8b, 0x89, 0x5b, 0x9b, 0x4e, 0x5c, 0x54, 0x61, 0x74, 0xae, - 0x8a, 0x1f, 0xa2, 0xa6, 0xc8, 0x20, 0xb4, 0xeb, 0x5a, 0xfd, 0x53, 0xb2, 0x61, 0x65, 0x64, 0x6d, - 0xad, 0xf7, 0x33, 0x08, 0x83, 0x6d, 0x93, 0xab, 0xa9, 0x2c, 0xaa, 0x95, 0xf1, 0x19, 0x6a, 0x0b, - 0xc9, 0x64, 0x21, 0xec, 0x86, 0xce, 0xf1, 0xd9, 0x15, 0x72, 0x68, 0x9d, 0x60, 0xc7, 0x64, 0x69, - 0x97, 0x36, 0x35, 0xfa, 0xde, 0x6f, 0x75, 0xe4, 0xad, 0xe5, 0x1e, 0xa7, 0xc9, 0x80, 0x4b, 0x9e, - 0x26, 0xf8, 0x10, 0x35, 0xe5, 0x38, 0x03, 0x3d, 0xd0, 0x6e, 0xf0, 0xe6, 0xac, 0xe4, 0x07, 0xe3, - 0x0c, 0x9e, 0x4f, 0xdc, 0xd7, 0x97, 0xe3, 0x15, 0x4e, 0x35, 0x03, 0xbf, 0x8d, 0xda, 0x39, 0x30, - 0x91, 0x26, 0x7a, 0x5c, 0xdd, 0xaa, 0x10, 0xaa, 0x51, 0x6a, 0xbc, 0xf8, 0x1d, 0xb4, 0x15, 0x83, - 0x10, 0x2c, 0x02, 0xdd, 0x73, 0x37, 0xb8, 0x66, 0x02, 0xb7, 0xee, 0x95, 0x30, 0x9d, 0xf9, 0xf1, - 0x63, 0xb4, 0x73, 0xce, 0x84, 0x3c, 0xcd, 0x06, 0x4c, 0xc2, 0x03, 0x1e, 0x83, 0xdd, 0xd4, 0x53, - 0x7a, 0xf7, 0xe5, 0xf6, 0xac, 0x18, 0xc1, 0x0d, 0xa3, 0xbe, 0x73, 0xf7, 0x7f, 0x4a, 0x74, 0x49, - 0xd9, 0x9b, 0x58, 0xe8, 0xe6, 0xda, 0xf9, 0xdc, 0xe5, 0x42, 0xe2, 0xef, 0x57, 0xee, 0x8d, 0xbc, - 0x5c, 0x1d, 0x8a, 0xad, 0xaf, 0xed, 0xba, 0xa9, 0xa5, 0x33, 0x43, 0x16, 0x6e, 0xed, 0x07, 0xd4, - 0xe2, 0x12, 0x62, 0x61, 0xd7, 0xf7, 0x1a, 0xfb, 0xbd, 0xdb, 0x47, 0xaf, 0x7e, 0x08, 0xc1, 0x6b, - 0x26, 0x4d, 0xeb, 0x44, 0x09, 0xd2, 0x52, 0xd7, 0xfb, 0xa3, 0xf1, 0x82, 0x06, 0xd5, 0x49, 0xe2, - 0xb7, 0xd0, 0x56, 0x5e, 0x9a, 0xba, 0xbf, 0xed, 0xa0, 0xa7, 0xb6, 0x62, 0x22, 0xe8, 0xcc, 0x87, - 0xdf, 0x47, 0x9d, 0x42, 0x40, 0x9e, 0xb0, 0x18, 0xcc, 0xaa, 0xe7, 0x7d, 0x9d, 0x1a, 0x9c, 0xce, - 0x23, 0xf0, 0x4d, 0xd4, 0x28, 0xf8, 0xc0, 0xac, 0xba, 0x67, 0x02, 0x1b, 0xa7, 0x27, 0x5f, 0x50, - 0x85, 0x63, 0x0f, 0xb5, 0xa3, 0x3c, 0x2d, 0x32, 0x61, 0x37, 0xf7, 0x1a, 0xfb, 0xdd, 0x00, 0xa9, - 0x8b, 0xf9, 0x52, 0x23, 0xd4, 0x78, 0x30, 0x41, 0xed, 0x42, 0xdd, 0x83, 0xb0, 0x5b, 0x3a, 0xe6, - 0x86, 0x8a, 0x39, 0xd5, 0xc8, 0xf3, 0x89, 0xdb, 0xf9, 0x1a, 0xc6, 0xda, 0xa0, 0x26, 0x0a, 0x27, - 0xa8, 0x05, 0x3f, 0xcb, 0x9c, 0xd9, 0x6d, 0x3d, 0xca, 0x93, 0xab, 0xbd, 0x5b, 0x72, 0x47, 0x69, - 0xdd, 0x49, 0x64, 0x3e, 0xae, 0x26, 0xab, 0x31, 0x5a, 0xa6, 0xd9, 0x05, 0x84, 0xaa, 0x18, 0x7c, - 0x1d, 0x35, 0x86, 0x30, 0x2e, 0x1f, 0x10, 0x55, 0x9f, 0xf8, 0x73, 0xd4, 0x1a, 0xb1, 0xf3, 0x02, - 0xcc, 0x7f, 0xe4, 0xbd, 0x8d, 0xf5, 0x68, 0xb5, 0x6f, 0x15, 0x85, 0x96, 0xcc, 0xa3, 0xfa, 0xa1, - 0xe5, 0xfd, 0x65, 0x21, 0x77, 0xc3, 0xeb, 0xc7, 0x3f, 0x21, 0x14, 0xce, 0xde, 0xa6, 0xb0, 0x2d, - 0xdd, 0xff, 0xf1, 0xab, 0xf7, 0x3f, 0x7f, 0xe7, 0xd5, 0x8f, 0x72, 0x0e, 0x09, 0xba, 0x90, 0x0a, - 0x1f, 0xa0, 0xde, 0x82, 0xb4, 0xee, 0x74, 0x3b, 0xb8, 0x36, 0x9d, 0xb8, 0xbd, 0x05, 0x71, 0xba, - 0x18, 0xe3, 0x7d, 0x62, 0xc6, 0xa6, 0x1b, 0xc5, 0xee, 0xec, 0xfe, 0x2d, 0xbd, 0xe3, 0xee, 0xf2, - 0xfd, 0x1e, 0x75, 0x7e, 0xfd, 0xdd, 0xad, 0x3d, 0xf9, 0x7b, 0xaf, 0x16, 0xdc, 0xba, 0xb8, 0x74, - 0x6a, 0x4f, 0x2f, 0x9d, 0xda, 0xb3, 0x4b, 0xa7, 0xf6, 0x64, 0xea, 0x58, 0x17, 0x53, 0xc7, 0x7a, - 0x3a, 0x75, 0xac, 0x67, 0x53, 0xc7, 0xfa, 0x67, 0xea, 0x58, 0xbf, 0xfc, 0xeb, 0xd4, 0xbe, 0xdb, - 0x32, 0xdd, 0xfd, 0x17, 0x00, 0x00, 0xff, 0xff, 0x73, 0x7d, 0xca, 0x2a, 0xb4, 0x07, 0x00, 0x00, + // 804 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x8f, 0xdb, 0x44, + 0x18, 0x8e, 0xf3, 0xb5, 0xc9, 0x64, 0xd9, 0x56, 0x23, 0x54, 0x99, 0x95, 0x6a, 0xaf, 0x2c, 0x40, + 0xcb, 0x47, 0xc7, 0x6c, 0x85, 0x60, 0xb5, 0x07, 0x04, 0x5e, 0x2a, 0x58, 0xd1, 0x0a, 0x69, 0xda, + 0x70, 0x40, 0x48, 0x74, 0xe2, 0xbc, 0x75, 0xa6, 0xa9, 0x3f, 0xf0, 0x8c, 0x03, 0xb9, 0xf5, 0x27, + 0x70, 0xe4, 0x82, 0xc4, 0x2f, 0xe1, 0xbc, 0x1c, 0x90, 0x7a, 0xec, 0x01, 0x45, 0x6c, 0xf8, 0x17, + 0x3d, 0xa1, 0x19, 0x4f, 0xe2, 0x90, 0x55, 0x48, 0xd5, 0xbd, 0x79, 0x9e, 0xf7, 0x79, 0x9e, 0xf7, + 0x63, 0xde, 0x31, 0xfa, 0x72, 0x7c, 0x2c, 0x08, 0x4f, 0xfd, 0x71, 0x31, 0x80, 0x3c, 0x01, 0x09, + 0xc2, 0x9f, 0x40, 0x32, 0x4c, 0x73, 0xdf, 0x04, 0x58, 0xc6, 0xfd, 0x10, 0x72, 0xc9, 0x1f, 0xf1, + 0x90, 0xe9, 0xf0, 0xd1, 0x00, 0x24, 0x3b, 0xf2, 0x23, 0x48, 0x20, 0x67, 0x12, 0x86, 0x24, 0xcb, + 0x53, 0x99, 0x62, 0xb7, 0x14, 0x10, 0x96, 0x71, 0xb2, 0x2a, 0x20, 0x46, 0xb0, 0x7f, 0x2b, 0xe2, + 0x72, 0x54, 0x0c, 0x48, 0x98, 0xc6, 0x7e, 0x94, 0x46, 0xa9, 0xaf, 0x75, 0x83, 0xe2, 0x91, 0x3e, + 0xe9, 0x83, 0xfe, 0x2a, 0xfd, 0xf6, 0x3f, 0xac, 0x0a, 0x88, 0x59, 0x38, 0xe2, 0x09, 0xe4, 0x53, + 0x3f, 0x1b, 0x47, 0x0a, 0x10, 0x7e, 0x0c, 0x92, 0xf9, 0x93, 0x4b, 0x55, 0xec, 0xfb, 0x9b, 0x54, + 0x79, 0x91, 0x48, 0x1e, 0xc3, 0x25, 0xc1, 0x47, 0xdb, 0x04, 0x22, 0x1c, 0x41, 0xcc, 0xd6, 0x75, + 0xde, 0x1f, 0x75, 0xf4, 0xc6, 0x69, 0xd5, 0xe6, 0x7d, 0x1e, 0x25, 0x3c, 0x89, 0x28, 0xfc, 0x50, + 0x80, 0x90, 0xf8, 0x21, 0xea, 0xa8, 0x0a, 0x87, 0x4c, 0x32, 0xdb, 0x3a, 0xb0, 0x0e, 0x7b, 0xb7, + 0x3f, 0x20, 0xd5, 0x7c, 0x96, 0x89, 0x48, 0x36, 0x8e, 0x14, 0x20, 0x88, 0x62, 0x93, 0xc9, 0x11, + 0xf9, 0x7a, 0xf0, 0x18, 0x42, 0x79, 0x0f, 0x24, 0x0b, 0xf0, 0xf9, 0xcc, 0xad, 0xcd, 0x67, 0x2e, + 0xaa, 0x30, 0xba, 0x74, 0xc5, 0x0f, 0x51, 0x53, 0x64, 0x10, 0xda, 0x75, 0xed, 0xfe, 0x09, 0xd9, + 0x32, 0x7d, 0xb2, 0xb1, 0xd6, 0xfb, 0x19, 0x84, 0xc1, 0xae, 0xc9, 0xd5, 0x54, 0x27, 0xaa, 0x9d, + 0xf1, 0x08, 0xb5, 0x85, 0x64, 0xb2, 0x10, 0x76, 0x43, 0xe7, 0xf8, 0xf4, 0x0a, 0x39, 0xb4, 0x4f, + 0xb0, 0x67, 0xb2, 0xb4, 0xcb, 0x33, 0x35, 0xfe, 0xde, 0xaf, 0x75, 0xe4, 0x6d, 0xd4, 0x9e, 0xa6, + 0xc9, 0x90, 0x4b, 0x9e, 0x26, 0xf8, 0x18, 0x35, 0xe5, 0x34, 0x03, 0x3d, 0xd0, 0x6e, 0xf0, 0xe6, + 0xa2, 0xe4, 0x07, 0xd3, 0x0c, 0x5e, 0xcc, 0xdc, 0xd7, 0xd7, 0xf9, 0x0a, 0xa7, 0x5a, 0x81, 0xdf, + 0x46, 0xed, 0x1c, 0x98, 0x48, 0x13, 0x3d, 0xae, 0x6e, 0x55, 0x08, 0xd5, 0x28, 0x35, 0x51, 0xfc, + 0x0e, 0xda, 0x89, 0x41, 0x08, 0x16, 0x81, 0xee, 0xb9, 0x1b, 0x5c, 0x33, 0xc4, 0x9d, 0x7b, 0x25, + 0x4c, 0x17, 0x71, 0xfc, 0x18, 0xed, 0x3d, 0x61, 0x42, 0xf6, 0xb3, 0x21, 0x93, 0xf0, 0x80, 0xc7, + 0x60, 0x37, 0xf5, 0x94, 0xde, 0x7d, 0xb9, 0x7b, 0x56, 0x8a, 0xe0, 0x86, 0x71, 0xdf, 0xbb, 0xfb, + 0x1f, 0x27, 0xba, 0xe6, 0xec, 0xcd, 0x2c, 0x74, 0x73, 0xe3, 0x7c, 0xee, 0x72, 0x21, 0xf1, 0x77, + 0x97, 0xf6, 0x8d, 0xbc, 0x5c, 0x1d, 0x4a, 0xad, 0xb7, 0xed, 0xba, 0xa9, 0xa5, 0xb3, 0x40, 0x56, + 0x76, 0xed, 0x7b, 0xd4, 0xe2, 0x12, 0x62, 0x61, 0xd7, 0x0f, 0x1a, 0x87, 0xbd, 0xdb, 0x27, 0xaf, + 0xbe, 0x08, 0xc1, 0x6b, 0x26, 0x4d, 0xeb, 0x4c, 0x19, 0xd2, 0xd2, 0xd7, 0xfb, 0xbd, 0xf1, 0x3f, + 0x0d, 0xaa, 0x95, 0xc4, 0x6f, 0xa1, 0x9d, 0xbc, 0x3c, 0xea, 0xfe, 0x76, 0x83, 0x9e, 0xba, 0x15, + 0xc3, 0xa0, 0x8b, 0x18, 0x7e, 0x1f, 0x75, 0x0a, 0x01, 0x79, 0xc2, 0x62, 0x30, 0x57, 0xbd, 0xec, + 0xab, 0x6f, 0x70, 0xba, 0x64, 0xe0, 0x9b, 0xa8, 0x51, 0xf0, 0xa1, 0xb9, 0xea, 0x9e, 0x21, 0x36, + 0xfa, 0x67, 0x9f, 0x53, 0x85, 0x63, 0x0f, 0xb5, 0xa3, 0x3c, 0x2d, 0x32, 0x61, 0x37, 0x0f, 0x1a, + 0x87, 0xdd, 0x00, 0xa9, 0x8d, 0xf9, 0x42, 0x23, 0xd4, 0x44, 0x30, 0x41, 0xed, 0x42, 0xed, 0x83, + 0xb0, 0x5b, 0x9a, 0x73, 0x43, 0x71, 0xfa, 0x1a, 0x79, 0x31, 0x73, 0x3b, 0x5f, 0xc1, 0x54, 0x1f, + 0xa8, 0x61, 0xe1, 0x04, 0xb5, 0xe0, 0x27, 0x99, 0x33, 0xbb, 0xad, 0x47, 0x79, 0x76, 0xb5, 0x77, + 0x4b, 0xee, 0x28, 0xaf, 0x3b, 0x89, 0xcc, 0xa7, 0xd5, 0x64, 0x35, 0x46, 0xcb, 0x34, 0xfb, 0x80, + 0x50, 0xc5, 0xc1, 0xd7, 0x51, 0x63, 0x0c, 0xd3, 0xf2, 0x01, 0x51, 0xf5, 0x89, 0x3f, 0x43, 0xad, + 0x09, 0x7b, 0x52, 0x80, 0xf9, 0x8f, 0xbc, 0xb7, 0xb5, 0x1e, 0xed, 0xf6, 0x8d, 0x92, 0xd0, 0x52, + 0x79, 0x52, 0x3f, 0xb6, 0xbc, 0x3f, 0x2d, 0xe4, 0x6e, 0x79, 0xfd, 0xf8, 0x47, 0x84, 0xc2, 0xc5, + 0xdb, 0x14, 0xb6, 0xa5, 0xfb, 0x3f, 0x7d, 0xf5, 0xfe, 0x97, 0xef, 0xbc, 0xfa, 0x51, 0x2e, 0x21, + 0x41, 0x57, 0x52, 0xe1, 0x23, 0xd4, 0x5b, 0xb1, 0xd6, 0x9d, 0xee, 0x06, 0xd7, 0xe6, 0x33, 0xb7, + 0xb7, 0x62, 0x4e, 0x57, 0x39, 0xde, 0xc7, 0x66, 0x6c, 0xba, 0x51, 0xec, 0x2e, 0xf6, 0xdf, 0xd2, + 0x77, 0xdc, 0x5d, 0xdf, 0xdf, 0x93, 0xce, 0x2f, 0xbf, 0xb9, 0xb5, 0xa7, 0x7f, 0x1d, 0xd4, 0x82, + 0x5b, 0xe7, 0x17, 0x4e, 0xed, 0xd9, 0x85, 0x53, 0x7b, 0x7e, 0xe1, 0xd4, 0x9e, 0xce, 0x1d, 0xeb, + 0x7c, 0xee, 0x58, 0xcf, 0xe6, 0x8e, 0xf5, 0x7c, 0xee, 0x58, 0x7f, 0xcf, 0x1d, 0xeb, 0xe7, 0x7f, + 0x9c, 0xda, 0xb7, 0x3b, 0xa6, 0xbb, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x6b, 0x5b, 0xf9, + 0x7f, 0x07, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/generated.proto index e3cd9000f..5200224a2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.certificates.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/types_swagger_doc_generated.go index 4fd91df06..f6a7e16ac 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_CertificateSigningRequest = map[string]string{ "": "Describes a certificate signing request", "spec": "The certificate request itself and any additional information.", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/zz_generated.deepcopy.go index 5848a255b..ffd24c30f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/certificates/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/BUILD index 560ff5bd7..369c7e425 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/BUILD @@ -21,7 +21,6 @@ go_library( "annotation_key_constants.go", "doc.go", "generated.pb.go", - "meta.go", "objectreference.go", "register.go", "resource.go", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/annotation_key_constants.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/annotation_key_constants.go index de4e3cee4..16a0cfced 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/annotation_key_constants.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/annotation_key_constants.go @@ -45,24 +45,17 @@ const ( // to one container of a pod. SeccompContainerAnnotationKeyPrefix string = "container.seccomp.security.alpha.kubernetes.io/" + // SeccompProfileRuntimeDefault represents the default seccomp profile used by container runtime. + SeccompProfileRuntimeDefault string = "runtime/default" + + // DeprecatedSeccompProfileDockerDefault represents the default seccomp profile used by docker. + // This is now deprecated and should be replaced by SeccompProfileRuntimeDefault. + DeprecatedSeccompProfileDockerDefault string = "docker/default" + // PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized) // in the Annotations of a Node. PreferAvoidPodsAnnotationKey string = "scheduler.alpha.kubernetes.io/preferAvoidPods" - // SysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Only a limited set of whitelisted and isolated sysctls is supported by - // the kubelet. Pods with other sysctls will fail to launch. - SysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/sysctls" - - // UnsafeSysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Unsafe sysctls must be explicitly enabled for a kubelet. They are properly - // namespaced to a pod or a container, but their isolation is usually unclear or weak. Their use - // is at-your-own-risk. Pods that attempt to set an unsafe sysctl that is not enabled for a kubelet - // will fail to launch. - UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls" - // ObjectTTLAnnotations represents a suggestion for kubelet for how long it can cache // an object (e.g. secret, config map) before fetching it again from apiserver. // This annotation can be attached to node. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/generated.pb.go index 85c7b634b..a809ceb0a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -37,6 +37,7 @@ limitations under the License. Capabilities CephFSPersistentVolumeSource CephFSVolumeSource + CinderPersistentVolumeSource CinderVolumeSource ClientIPConfig ComponentCondition @@ -46,6 +47,7 @@ limitations under the License. ConfigMapEnvSource ConfigMapKeySelector ConfigMapList + ConfigMapNodeConfigSource ConfigMapProjection ConfigMapVolumeSource Container @@ -57,7 +59,6 @@ limitations under the License. ContainerStateWaiting ContainerStatus DaemonEndpoint - DeleteOptions DownwardAPIProjection DownwardAPIVolumeFile DownwardAPIVolumeSource @@ -96,7 +97,6 @@ limitations under the License. LimitRangeList LimitRangeSpec List - ListOptions LoadBalancerIngress LoadBalancerStatus LocalObjectReference @@ -111,6 +111,7 @@ limitations under the License. NodeAffinity NodeCondition NodeConfigSource + NodeConfigStatus NodeDaemonEndpoints NodeList NodeProxyOptions @@ -122,7 +123,6 @@ limitations under the License. NodeStatus NodeSystemInfo ObjectFieldSelector - ObjectMeta ObjectReference PersistentVolume PersistentVolumeClaim @@ -149,6 +149,7 @@ limitations under the License. PodLogOptions PodPortForwardOptions PodProxyOptions + PodReadinessGate PodSecurityContext PodSignature PodSpec @@ -181,6 +182,8 @@ limitations under the License. SELinuxOptions ScaleIOPersistentVolumeSource ScaleIOVolumeSource + ScopeSelector + ScopedResourceSelectorRequirement Secret SecretEnvSource SecretKeySelector @@ -193,6 +196,7 @@ limitations under the License. Service ServiceAccount ServiceAccountList + ServiceAccountTokenProjection ServiceList ServicePort ServiceProxyOptions @@ -205,6 +209,8 @@ limitations under the License. TCPSocketAction Taint Toleration + TopologySelectorLabelRequirement + TopologySelectorTerm Volume VolumeDevice VolumeMount @@ -300,255 +306,259 @@ func (m *CephFSVolumeSource) Reset() { *m = CephFSVolumeSourc func (*CephFSVolumeSource) ProtoMessage() {} func (*CephFSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } +func (m *CinderPersistentVolumeSource) Reset() { *m = CinderPersistentVolumeSource{} } +func (*CinderPersistentVolumeSource) ProtoMessage() {} +func (*CinderPersistentVolumeSource) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{12} +} + func (m *CinderVolumeSource) Reset() { *m = CinderVolumeSource{} } func (*CinderVolumeSource) ProtoMessage() {} -func (*CinderVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } +func (*CinderVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (m *ClientIPConfig) Reset() { *m = ClientIPConfig{} } func (*ClientIPConfig) ProtoMessage() {} -func (*ClientIPConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } +func (*ClientIPConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } func (m *ComponentCondition) Reset() { *m = ComponentCondition{} } func (*ComponentCondition) ProtoMessage() {} -func (*ComponentCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } +func (*ComponentCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } func (m *ComponentStatus) Reset() { *m = ComponentStatus{} } func (*ComponentStatus) ProtoMessage() {} -func (*ComponentStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } +func (*ComponentStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } func (m *ComponentStatusList) Reset() { *m = ComponentStatusList{} } func (*ComponentStatusList) ProtoMessage() {} -func (*ComponentStatusList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } +func (*ComponentStatusList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } func (m *ConfigMap) Reset() { *m = ConfigMap{} } func (*ConfigMap) ProtoMessage() {} -func (*ConfigMap) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } +func (*ConfigMap) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } func (m *ConfigMapEnvSource) Reset() { *m = ConfigMapEnvSource{} } func (*ConfigMapEnvSource) ProtoMessage() {} -func (*ConfigMapEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } +func (*ConfigMapEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } func (m *ConfigMapKeySelector) Reset() { *m = ConfigMapKeySelector{} } func (*ConfigMapKeySelector) ProtoMessage() {} -func (*ConfigMapKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } +func (*ConfigMapKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } func (m *ConfigMapList) Reset() { *m = ConfigMapList{} } func (*ConfigMapList) ProtoMessage() {} -func (*ConfigMapList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } +func (*ConfigMapList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } + +func (m *ConfigMapNodeConfigSource) Reset() { *m = ConfigMapNodeConfigSource{} } +func (*ConfigMapNodeConfigSource) ProtoMessage() {} +func (*ConfigMapNodeConfigSource) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{22} +} func (m *ConfigMapProjection) Reset() { *m = ConfigMapProjection{} } func (*ConfigMapProjection) ProtoMessage() {} -func (*ConfigMapProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } +func (*ConfigMapProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } func (m *ConfigMapVolumeSource) Reset() { *m = ConfigMapVolumeSource{} } func (*ConfigMapVolumeSource) ProtoMessage() {} -func (*ConfigMapVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} } +func (*ConfigMapVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } func (m *Container) Reset() { *m = Container{} } func (*Container) ProtoMessage() {} -func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } +func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } func (m *ContainerImage) Reset() { *m = ContainerImage{} } func (*ContainerImage) ProtoMessage() {} -func (*ContainerImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } +func (*ContainerImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } func (m *ContainerPort) Reset() { *m = ContainerPort{} } func (*ContainerPort) ProtoMessage() {} -func (*ContainerPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } +func (*ContainerPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } func (m *ContainerState) Reset() { *m = ContainerState{} } func (*ContainerState) ProtoMessage() {} -func (*ContainerState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } +func (*ContainerState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } func (m *ContainerStateRunning) Reset() { *m = ContainerStateRunning{} } func (*ContainerStateRunning) ProtoMessage() {} -func (*ContainerStateRunning) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } +func (*ContainerStateRunning) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } func (m *ContainerStateTerminated) Reset() { *m = ContainerStateTerminated{} } func (*ContainerStateTerminated) ProtoMessage() {} func (*ContainerStateTerminated) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{28} + return fileDescriptorGenerated, []int{30} } func (m *ContainerStateWaiting) Reset() { *m = ContainerStateWaiting{} } func (*ContainerStateWaiting) ProtoMessage() {} -func (*ContainerStateWaiting) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } +func (*ContainerStateWaiting) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } func (m *ContainerStatus) Reset() { *m = ContainerStatus{} } func (*ContainerStatus) ProtoMessage() {} -func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } +func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } func (m *DaemonEndpoint) Reset() { *m = DaemonEndpoint{} } func (*DaemonEndpoint) ProtoMessage() {} -func (*DaemonEndpoint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } - -func (m *DeleteOptions) Reset() { *m = DeleteOptions{} } -func (*DeleteOptions) ProtoMessage() {} -func (*DeleteOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } +func (*DaemonEndpoint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } func (m *DownwardAPIProjection) Reset() { *m = DownwardAPIProjection{} } func (*DownwardAPIProjection) ProtoMessage() {} -func (*DownwardAPIProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } +func (*DownwardAPIProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } func (m *DownwardAPIVolumeFile) Reset() { *m = DownwardAPIVolumeFile{} } func (*DownwardAPIVolumeFile) ProtoMessage() {} -func (*DownwardAPIVolumeFile) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } +func (*DownwardAPIVolumeFile) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{35} } func (m *DownwardAPIVolumeSource) Reset() { *m = DownwardAPIVolumeSource{} } func (*DownwardAPIVolumeSource) ProtoMessage() {} func (*DownwardAPIVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{35} + return fileDescriptorGenerated, []int{36} } func (m *EmptyDirVolumeSource) Reset() { *m = EmptyDirVolumeSource{} } func (*EmptyDirVolumeSource) ProtoMessage() {} -func (*EmptyDirVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{36} } +func (*EmptyDirVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{37} } func (m *EndpointAddress) Reset() { *m = EndpointAddress{} } func (*EndpointAddress) ProtoMessage() {} -func (*EndpointAddress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{37} } +func (*EndpointAddress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{38} } func (m *EndpointPort) Reset() { *m = EndpointPort{} } func (*EndpointPort) ProtoMessage() {} -func (*EndpointPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{38} } +func (*EndpointPort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{39} } func (m *EndpointSubset) Reset() { *m = EndpointSubset{} } func (*EndpointSubset) ProtoMessage() {} -func (*EndpointSubset) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{39} } +func (*EndpointSubset) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{40} } func (m *Endpoints) Reset() { *m = Endpoints{} } func (*Endpoints) ProtoMessage() {} -func (*Endpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{40} } +func (*Endpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{41} } func (m *EndpointsList) Reset() { *m = EndpointsList{} } func (*EndpointsList) ProtoMessage() {} -func (*EndpointsList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{41} } +func (*EndpointsList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{42} } func (m *EnvFromSource) Reset() { *m = EnvFromSource{} } func (*EnvFromSource) ProtoMessage() {} -func (*EnvFromSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{42} } +func (*EnvFromSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{43} } func (m *EnvVar) Reset() { *m = EnvVar{} } func (*EnvVar) ProtoMessage() {} -func (*EnvVar) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{43} } +func (*EnvVar) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{44} } func (m *EnvVarSource) Reset() { *m = EnvVarSource{} } func (*EnvVarSource) ProtoMessage() {} -func (*EnvVarSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{44} } +func (*EnvVarSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{45} } func (m *Event) Reset() { *m = Event{} } func (*Event) ProtoMessage() {} -func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{45} } +func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{46} } func (m *EventList) Reset() { *m = EventList{} } func (*EventList) ProtoMessage() {} -func (*EventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{46} } +func (*EventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{47} } func (m *EventSeries) Reset() { *m = EventSeries{} } func (*EventSeries) ProtoMessage() {} -func (*EventSeries) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{47} } +func (*EventSeries) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{48} } func (m *EventSource) Reset() { *m = EventSource{} } func (*EventSource) ProtoMessage() {} -func (*EventSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{48} } +func (*EventSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{49} } func (m *ExecAction) Reset() { *m = ExecAction{} } func (*ExecAction) ProtoMessage() {} -func (*ExecAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{49} } +func (*ExecAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{50} } func (m *FCVolumeSource) Reset() { *m = FCVolumeSource{} } func (*FCVolumeSource) ProtoMessage() {} -func (*FCVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{50} } +func (*FCVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{51} } func (m *FlexPersistentVolumeSource) Reset() { *m = FlexPersistentVolumeSource{} } func (*FlexPersistentVolumeSource) ProtoMessage() {} func (*FlexPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{51} + return fileDescriptorGenerated, []int{52} } func (m *FlexVolumeSource) Reset() { *m = FlexVolumeSource{} } func (*FlexVolumeSource) ProtoMessage() {} -func (*FlexVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{52} } +func (*FlexVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{53} } func (m *FlockerVolumeSource) Reset() { *m = FlockerVolumeSource{} } func (*FlockerVolumeSource) ProtoMessage() {} -func (*FlockerVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{53} } +func (*FlockerVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{54} } func (m *GCEPersistentDiskVolumeSource) Reset() { *m = GCEPersistentDiskVolumeSource{} } func (*GCEPersistentDiskVolumeSource) ProtoMessage() {} func (*GCEPersistentDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{54} + return fileDescriptorGenerated, []int{55} } func (m *GitRepoVolumeSource) Reset() { *m = GitRepoVolumeSource{} } func (*GitRepoVolumeSource) ProtoMessage() {} -func (*GitRepoVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{55} } +func (*GitRepoVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{56} } func (m *GlusterfsVolumeSource) Reset() { *m = GlusterfsVolumeSource{} } func (*GlusterfsVolumeSource) ProtoMessage() {} -func (*GlusterfsVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{56} } +func (*GlusterfsVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{57} } func (m *HTTPGetAction) Reset() { *m = HTTPGetAction{} } func (*HTTPGetAction) ProtoMessage() {} -func (*HTTPGetAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{57} } +func (*HTTPGetAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{58} } func (m *HTTPHeader) Reset() { *m = HTTPHeader{} } func (*HTTPHeader) ProtoMessage() {} -func (*HTTPHeader) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{58} } +func (*HTTPHeader) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{59} } func (m *Handler) Reset() { *m = Handler{} } func (*Handler) ProtoMessage() {} -func (*Handler) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{59} } +func (*Handler) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{60} } func (m *HostAlias) Reset() { *m = HostAlias{} } func (*HostAlias) ProtoMessage() {} -func (*HostAlias) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{60} } +func (*HostAlias) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{61} } func (m *HostPathVolumeSource) Reset() { *m = HostPathVolumeSource{} } func (*HostPathVolumeSource) ProtoMessage() {} -func (*HostPathVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{61} } +func (*HostPathVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{62} } func (m *ISCSIPersistentVolumeSource) Reset() { *m = ISCSIPersistentVolumeSource{} } func (*ISCSIPersistentVolumeSource) ProtoMessage() {} func (*ISCSIPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{62} + return fileDescriptorGenerated, []int{63} } func (m *ISCSIVolumeSource) Reset() { *m = ISCSIVolumeSource{} } func (*ISCSIVolumeSource) ProtoMessage() {} -func (*ISCSIVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{63} } +func (*ISCSIVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{64} } func (m *KeyToPath) Reset() { *m = KeyToPath{} } func (*KeyToPath) ProtoMessage() {} -func (*KeyToPath) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{64} } +func (*KeyToPath) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{65} } func (m *Lifecycle) Reset() { *m = Lifecycle{} } func (*Lifecycle) ProtoMessage() {} -func (*Lifecycle) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{65} } +func (*Lifecycle) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{66} } func (m *LimitRange) Reset() { *m = LimitRange{} } func (*LimitRange) ProtoMessage() {} -func (*LimitRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{66} } +func (*LimitRange) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{67} } func (m *LimitRangeItem) Reset() { *m = LimitRangeItem{} } func (*LimitRangeItem) ProtoMessage() {} -func (*LimitRangeItem) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{67} } +func (*LimitRangeItem) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{68} } func (m *LimitRangeList) Reset() { *m = LimitRangeList{} } func (*LimitRangeList) ProtoMessage() {} -func (*LimitRangeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{68} } +func (*LimitRangeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{69} } func (m *LimitRangeSpec) Reset() { *m = LimitRangeSpec{} } func (*LimitRangeSpec) ProtoMessage() {} -func (*LimitRangeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{69} } +func (*LimitRangeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{70} } func (m *List) Reset() { *m = List{} } func (*List) ProtoMessage() {} -func (*List) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{70} } - -func (m *ListOptions) Reset() { *m = ListOptions{} } -func (*ListOptions) ProtoMessage() {} -func (*ListOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{71} } +func (*List) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{71} } func (m *LoadBalancerIngress) Reset() { *m = LoadBalancerIngress{} } func (*LoadBalancerIngress) ProtoMessage() {} @@ -606,55 +616,55 @@ func (m *NodeConfigSource) Reset() { *m = NodeConfigSource{} func (*NodeConfigSource) ProtoMessage() {} func (*NodeConfigSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{85} } +func (m *NodeConfigStatus) Reset() { *m = NodeConfigStatus{} } +func (*NodeConfigStatus) ProtoMessage() {} +func (*NodeConfigStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{86} } + func (m *NodeDaemonEndpoints) Reset() { *m = NodeDaemonEndpoints{} } func (*NodeDaemonEndpoints) ProtoMessage() {} -func (*NodeDaemonEndpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{86} } +func (*NodeDaemonEndpoints) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{87} } func (m *NodeList) Reset() { *m = NodeList{} } func (*NodeList) ProtoMessage() {} -func (*NodeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{87} } +func (*NodeList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{88} } func (m *NodeProxyOptions) Reset() { *m = NodeProxyOptions{} } func (*NodeProxyOptions) ProtoMessage() {} -func (*NodeProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{88} } +func (*NodeProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{89} } func (m *NodeResources) Reset() { *m = NodeResources{} } func (*NodeResources) ProtoMessage() {} -func (*NodeResources) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{89} } +func (*NodeResources) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{90} } func (m *NodeSelector) Reset() { *m = NodeSelector{} } func (*NodeSelector) ProtoMessage() {} -func (*NodeSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{90} } +func (*NodeSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{91} } func (m *NodeSelectorRequirement) Reset() { *m = NodeSelectorRequirement{} } func (*NodeSelectorRequirement) ProtoMessage() {} func (*NodeSelectorRequirement) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{91} + return fileDescriptorGenerated, []int{92} } func (m *NodeSelectorTerm) Reset() { *m = NodeSelectorTerm{} } func (*NodeSelectorTerm) ProtoMessage() {} -func (*NodeSelectorTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{92} } +func (*NodeSelectorTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{93} } func (m *NodeSpec) Reset() { *m = NodeSpec{} } func (*NodeSpec) ProtoMessage() {} -func (*NodeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{93} } +func (*NodeSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{94} } func (m *NodeStatus) Reset() { *m = NodeStatus{} } func (*NodeStatus) ProtoMessage() {} -func (*NodeStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{94} } +func (*NodeStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{95} } func (m *NodeSystemInfo) Reset() { *m = NodeSystemInfo{} } func (*NodeSystemInfo) ProtoMessage() {} -func (*NodeSystemInfo) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{95} } +func (*NodeSystemInfo) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{96} } func (m *ObjectFieldSelector) Reset() { *m = ObjectFieldSelector{} } func (*ObjectFieldSelector) ProtoMessage() {} -func (*ObjectFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{96} } - -func (m *ObjectMeta) Reset() { *m = ObjectMeta{} } -func (*ObjectMeta) ProtoMessage() {} -func (*ObjectMeta) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{97} } +func (*ObjectFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{97} } func (m *ObjectReference) Reset() { *m = ObjectReference{} } func (*ObjectReference) ProtoMessage() {} @@ -776,280 +786,310 @@ func (m *PodProxyOptions) Reset() { *m = PodProxyOptions{} } func (*PodProxyOptions) ProtoMessage() {} func (*PodProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{123} } +func (m *PodReadinessGate) Reset() { *m = PodReadinessGate{} } +func (*PodReadinessGate) ProtoMessage() {} +func (*PodReadinessGate) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{124} } + func (m *PodSecurityContext) Reset() { *m = PodSecurityContext{} } func (*PodSecurityContext) ProtoMessage() {} -func (*PodSecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{124} } +func (*PodSecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{125} } func (m *PodSignature) Reset() { *m = PodSignature{} } func (*PodSignature) ProtoMessage() {} -func (*PodSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{125} } +func (*PodSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{126} } func (m *PodSpec) Reset() { *m = PodSpec{} } func (*PodSpec) ProtoMessage() {} -func (*PodSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{126} } +func (*PodSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{127} } func (m *PodStatus) Reset() { *m = PodStatus{} } func (*PodStatus) ProtoMessage() {} -func (*PodStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{127} } +func (*PodStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{128} } func (m *PodStatusResult) Reset() { *m = PodStatusResult{} } func (*PodStatusResult) ProtoMessage() {} -func (*PodStatusResult) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{128} } +func (*PodStatusResult) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{129} } func (m *PodTemplate) Reset() { *m = PodTemplate{} } func (*PodTemplate) ProtoMessage() {} -func (*PodTemplate) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{129} } +func (*PodTemplate) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{130} } func (m *PodTemplateList) Reset() { *m = PodTemplateList{} } func (*PodTemplateList) ProtoMessage() {} -func (*PodTemplateList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{130} } +func (*PodTemplateList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{131} } func (m *PodTemplateSpec) Reset() { *m = PodTemplateSpec{} } func (*PodTemplateSpec) ProtoMessage() {} -func (*PodTemplateSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{131} } +func (*PodTemplateSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{132} } func (m *PortworxVolumeSource) Reset() { *m = PortworxVolumeSource{} } func (*PortworxVolumeSource) ProtoMessage() {} -func (*PortworxVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{132} } +func (*PortworxVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{133} } func (m *Preconditions) Reset() { *m = Preconditions{} } func (*Preconditions) ProtoMessage() {} -func (*Preconditions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{133} } +func (*Preconditions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{134} } func (m *PreferAvoidPodsEntry) Reset() { *m = PreferAvoidPodsEntry{} } func (*PreferAvoidPodsEntry) ProtoMessage() {} -func (*PreferAvoidPodsEntry) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{134} } +func (*PreferAvoidPodsEntry) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{135} } func (m *PreferredSchedulingTerm) Reset() { *m = PreferredSchedulingTerm{} } func (*PreferredSchedulingTerm) ProtoMessage() {} func (*PreferredSchedulingTerm) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{135} + return fileDescriptorGenerated, []int{136} } func (m *Probe) Reset() { *m = Probe{} } func (*Probe) ProtoMessage() {} -func (*Probe) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{136} } +func (*Probe) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{137} } func (m *ProjectedVolumeSource) Reset() { *m = ProjectedVolumeSource{} } func (*ProjectedVolumeSource) ProtoMessage() {} -func (*ProjectedVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{137} } +func (*ProjectedVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{138} } func (m *QuobyteVolumeSource) Reset() { *m = QuobyteVolumeSource{} } func (*QuobyteVolumeSource) ProtoMessage() {} -func (*QuobyteVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{138} } +func (*QuobyteVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{139} } func (m *RBDPersistentVolumeSource) Reset() { *m = RBDPersistentVolumeSource{} } func (*RBDPersistentVolumeSource) ProtoMessage() {} func (*RBDPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{139} + return fileDescriptorGenerated, []int{140} } func (m *RBDVolumeSource) Reset() { *m = RBDVolumeSource{} } func (*RBDVolumeSource) ProtoMessage() {} -func (*RBDVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{140} } +func (*RBDVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{141} } func (m *RangeAllocation) Reset() { *m = RangeAllocation{} } func (*RangeAllocation) ProtoMessage() {} -func (*RangeAllocation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{141} } +func (*RangeAllocation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{142} } func (m *ReplicationController) Reset() { *m = ReplicationController{} } func (*ReplicationController) ProtoMessage() {} -func (*ReplicationController) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{142} } +func (*ReplicationController) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{143} } func (m *ReplicationControllerCondition) Reset() { *m = ReplicationControllerCondition{} } func (*ReplicationControllerCondition) ProtoMessage() {} func (*ReplicationControllerCondition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{143} + return fileDescriptorGenerated, []int{144} } func (m *ReplicationControllerList) Reset() { *m = ReplicationControllerList{} } func (*ReplicationControllerList) ProtoMessage() {} func (*ReplicationControllerList) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{144} + return fileDescriptorGenerated, []int{145} } func (m *ReplicationControllerSpec) Reset() { *m = ReplicationControllerSpec{} } func (*ReplicationControllerSpec) ProtoMessage() {} func (*ReplicationControllerSpec) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{145} + return fileDescriptorGenerated, []int{146} } func (m *ReplicationControllerStatus) Reset() { *m = ReplicationControllerStatus{} } func (*ReplicationControllerStatus) ProtoMessage() {} func (*ReplicationControllerStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{146} + return fileDescriptorGenerated, []int{147} } func (m *ResourceFieldSelector) Reset() { *m = ResourceFieldSelector{} } func (*ResourceFieldSelector) ProtoMessage() {} -func (*ResourceFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{147} } +func (*ResourceFieldSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{148} } func (m *ResourceQuota) Reset() { *m = ResourceQuota{} } func (*ResourceQuota) ProtoMessage() {} -func (*ResourceQuota) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{148} } +func (*ResourceQuota) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{149} } func (m *ResourceQuotaList) Reset() { *m = ResourceQuotaList{} } func (*ResourceQuotaList) ProtoMessage() {} -func (*ResourceQuotaList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{149} } +func (*ResourceQuotaList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{150} } func (m *ResourceQuotaSpec) Reset() { *m = ResourceQuotaSpec{} } func (*ResourceQuotaSpec) ProtoMessage() {} -func (*ResourceQuotaSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{150} } +func (*ResourceQuotaSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{151} } func (m *ResourceQuotaStatus) Reset() { *m = ResourceQuotaStatus{} } func (*ResourceQuotaStatus) ProtoMessage() {} -func (*ResourceQuotaStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{151} } +func (*ResourceQuotaStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{152} } func (m *ResourceRequirements) Reset() { *m = ResourceRequirements{} } func (*ResourceRequirements) ProtoMessage() {} -func (*ResourceRequirements) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{152} } +func (*ResourceRequirements) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{153} } func (m *SELinuxOptions) Reset() { *m = SELinuxOptions{} } func (*SELinuxOptions) ProtoMessage() {} -func (*SELinuxOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{153} } +func (*SELinuxOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{154} } func (m *ScaleIOPersistentVolumeSource) Reset() { *m = ScaleIOPersistentVolumeSource{} } func (*ScaleIOPersistentVolumeSource) ProtoMessage() {} func (*ScaleIOPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{154} + return fileDescriptorGenerated, []int{155} } func (m *ScaleIOVolumeSource) Reset() { *m = ScaleIOVolumeSource{} } func (*ScaleIOVolumeSource) ProtoMessage() {} -func (*ScaleIOVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{155} } +func (*ScaleIOVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{156} } + +func (m *ScopeSelector) Reset() { *m = ScopeSelector{} } +func (*ScopeSelector) ProtoMessage() {} +func (*ScopeSelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{157} } + +func (m *ScopedResourceSelectorRequirement) Reset() { *m = ScopedResourceSelectorRequirement{} } +func (*ScopedResourceSelectorRequirement) ProtoMessage() {} +func (*ScopedResourceSelectorRequirement) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{158} +} func (m *Secret) Reset() { *m = Secret{} } func (*Secret) ProtoMessage() {} -func (*Secret) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{156} } +func (*Secret) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{159} } func (m *SecretEnvSource) Reset() { *m = SecretEnvSource{} } func (*SecretEnvSource) ProtoMessage() {} -func (*SecretEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{157} } +func (*SecretEnvSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{160} } func (m *SecretKeySelector) Reset() { *m = SecretKeySelector{} } func (*SecretKeySelector) ProtoMessage() {} -func (*SecretKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{158} } +func (*SecretKeySelector) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{161} } func (m *SecretList) Reset() { *m = SecretList{} } func (*SecretList) ProtoMessage() {} -func (*SecretList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{159} } +func (*SecretList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{162} } func (m *SecretProjection) Reset() { *m = SecretProjection{} } func (*SecretProjection) ProtoMessage() {} -func (*SecretProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{160} } +func (*SecretProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{163} } func (m *SecretReference) Reset() { *m = SecretReference{} } func (*SecretReference) ProtoMessage() {} -func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{161} } +func (*SecretReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{164} } func (m *SecretVolumeSource) Reset() { *m = SecretVolumeSource{} } func (*SecretVolumeSource) ProtoMessage() {} -func (*SecretVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{162} } +func (*SecretVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{165} } func (m *SecurityContext) Reset() { *m = SecurityContext{} } func (*SecurityContext) ProtoMessage() {} -func (*SecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{163} } +func (*SecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{166} } func (m *SerializedReference) Reset() { *m = SerializedReference{} } func (*SerializedReference) ProtoMessage() {} -func (*SerializedReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{164} } +func (*SerializedReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{167} } func (m *Service) Reset() { *m = Service{} } func (*Service) ProtoMessage() {} -func (*Service) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{165} } +func (*Service) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{168} } func (m *ServiceAccount) Reset() { *m = ServiceAccount{} } func (*ServiceAccount) ProtoMessage() {} -func (*ServiceAccount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{166} } +func (*ServiceAccount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{169} } func (m *ServiceAccountList) Reset() { *m = ServiceAccountList{} } func (*ServiceAccountList) ProtoMessage() {} -func (*ServiceAccountList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{167} } +func (*ServiceAccountList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{170} } + +func (m *ServiceAccountTokenProjection) Reset() { *m = ServiceAccountTokenProjection{} } +func (*ServiceAccountTokenProjection) ProtoMessage() {} +func (*ServiceAccountTokenProjection) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{171} +} func (m *ServiceList) Reset() { *m = ServiceList{} } func (*ServiceList) ProtoMessage() {} -func (*ServiceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{168} } +func (*ServiceList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{172} } func (m *ServicePort) Reset() { *m = ServicePort{} } func (*ServicePort) ProtoMessage() {} -func (*ServicePort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{169} } +func (*ServicePort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{173} } func (m *ServiceProxyOptions) Reset() { *m = ServiceProxyOptions{} } func (*ServiceProxyOptions) ProtoMessage() {} -func (*ServiceProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{170} } +func (*ServiceProxyOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{174} } func (m *ServiceSpec) Reset() { *m = ServiceSpec{} } func (*ServiceSpec) ProtoMessage() {} -func (*ServiceSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{171} } +func (*ServiceSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{175} } func (m *ServiceStatus) Reset() { *m = ServiceStatus{} } func (*ServiceStatus) ProtoMessage() {} -func (*ServiceStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{172} } +func (*ServiceStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{176} } func (m *SessionAffinityConfig) Reset() { *m = SessionAffinityConfig{} } func (*SessionAffinityConfig) ProtoMessage() {} -func (*SessionAffinityConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{173} } +func (*SessionAffinityConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{177} } func (m *StorageOSPersistentVolumeSource) Reset() { *m = StorageOSPersistentVolumeSource{} } func (*StorageOSPersistentVolumeSource) ProtoMessage() {} func (*StorageOSPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{174} + return fileDescriptorGenerated, []int{178} } func (m *StorageOSVolumeSource) Reset() { *m = StorageOSVolumeSource{} } func (*StorageOSVolumeSource) ProtoMessage() {} -func (*StorageOSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{175} } +func (*StorageOSVolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{179} } func (m *Sysctl) Reset() { *m = Sysctl{} } func (*Sysctl) ProtoMessage() {} -func (*Sysctl) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{176} } +func (*Sysctl) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{180} } func (m *TCPSocketAction) Reset() { *m = TCPSocketAction{} } func (*TCPSocketAction) ProtoMessage() {} -func (*TCPSocketAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{177} } +func (*TCPSocketAction) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{181} } func (m *Taint) Reset() { *m = Taint{} } func (*Taint) ProtoMessage() {} -func (*Taint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{178} } +func (*Taint) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{182} } func (m *Toleration) Reset() { *m = Toleration{} } func (*Toleration) ProtoMessage() {} -func (*Toleration) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{179} } +func (*Toleration) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{183} } + +func (m *TopologySelectorLabelRequirement) Reset() { *m = TopologySelectorLabelRequirement{} } +func (*TopologySelectorLabelRequirement) ProtoMessage() {} +func (*TopologySelectorLabelRequirement) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{184} +} + +func (m *TopologySelectorTerm) Reset() { *m = TopologySelectorTerm{} } +func (*TopologySelectorTerm) ProtoMessage() {} +func (*TopologySelectorTerm) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{185} } func (m *Volume) Reset() { *m = Volume{} } func (*Volume) ProtoMessage() {} -func (*Volume) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{180} } +func (*Volume) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{186} } func (m *VolumeDevice) Reset() { *m = VolumeDevice{} } func (*VolumeDevice) ProtoMessage() {} -func (*VolumeDevice) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{181} } +func (*VolumeDevice) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{187} } func (m *VolumeMount) Reset() { *m = VolumeMount{} } func (*VolumeMount) ProtoMessage() {} -func (*VolumeMount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{182} } +func (*VolumeMount) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{188} } func (m *VolumeNodeAffinity) Reset() { *m = VolumeNodeAffinity{} } func (*VolumeNodeAffinity) ProtoMessage() {} -func (*VolumeNodeAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{183} } +func (*VolumeNodeAffinity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{189} } func (m *VolumeProjection) Reset() { *m = VolumeProjection{} } func (*VolumeProjection) ProtoMessage() {} -func (*VolumeProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{184} } +func (*VolumeProjection) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{190} } func (m *VolumeSource) Reset() { *m = VolumeSource{} } func (*VolumeSource) ProtoMessage() {} -func (*VolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{185} } +func (*VolumeSource) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{191} } func (m *VsphereVirtualDiskVolumeSource) Reset() { *m = VsphereVirtualDiskVolumeSource{} } func (*VsphereVirtualDiskVolumeSource) ProtoMessage() {} func (*VsphereVirtualDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{186} + return fileDescriptorGenerated, []int{192} } func (m *WeightedPodAffinityTerm) Reset() { *m = WeightedPodAffinityTerm{} } func (*WeightedPodAffinityTerm) ProtoMessage() {} func (*WeightedPodAffinityTerm) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{187} + return fileDescriptorGenerated, []int{193} } func init() { @@ -1065,6 +1105,7 @@ func init() { proto.RegisterType((*Capabilities)(nil), "k8s.io.api.core.v1.Capabilities") proto.RegisterType((*CephFSPersistentVolumeSource)(nil), "k8s.io.api.core.v1.CephFSPersistentVolumeSource") proto.RegisterType((*CephFSVolumeSource)(nil), "k8s.io.api.core.v1.CephFSVolumeSource") + proto.RegisterType((*CinderPersistentVolumeSource)(nil), "k8s.io.api.core.v1.CinderPersistentVolumeSource") proto.RegisterType((*CinderVolumeSource)(nil), "k8s.io.api.core.v1.CinderVolumeSource") proto.RegisterType((*ClientIPConfig)(nil), "k8s.io.api.core.v1.ClientIPConfig") proto.RegisterType((*ComponentCondition)(nil), "k8s.io.api.core.v1.ComponentCondition") @@ -1074,6 +1115,7 @@ func init() { proto.RegisterType((*ConfigMapEnvSource)(nil), "k8s.io.api.core.v1.ConfigMapEnvSource") proto.RegisterType((*ConfigMapKeySelector)(nil), "k8s.io.api.core.v1.ConfigMapKeySelector") proto.RegisterType((*ConfigMapList)(nil), "k8s.io.api.core.v1.ConfigMapList") + proto.RegisterType((*ConfigMapNodeConfigSource)(nil), "k8s.io.api.core.v1.ConfigMapNodeConfigSource") proto.RegisterType((*ConfigMapProjection)(nil), "k8s.io.api.core.v1.ConfigMapProjection") proto.RegisterType((*ConfigMapVolumeSource)(nil), "k8s.io.api.core.v1.ConfigMapVolumeSource") proto.RegisterType((*Container)(nil), "k8s.io.api.core.v1.Container") @@ -1085,7 +1127,6 @@ func init() { proto.RegisterType((*ContainerStateWaiting)(nil), "k8s.io.api.core.v1.ContainerStateWaiting") proto.RegisterType((*ContainerStatus)(nil), "k8s.io.api.core.v1.ContainerStatus") proto.RegisterType((*DaemonEndpoint)(nil), "k8s.io.api.core.v1.DaemonEndpoint") - proto.RegisterType((*DeleteOptions)(nil), "k8s.io.api.core.v1.DeleteOptions") proto.RegisterType((*DownwardAPIProjection)(nil), "k8s.io.api.core.v1.DownwardAPIProjection") proto.RegisterType((*DownwardAPIVolumeFile)(nil), "k8s.io.api.core.v1.DownwardAPIVolumeFile") proto.RegisterType((*DownwardAPIVolumeSource)(nil), "k8s.io.api.core.v1.DownwardAPIVolumeSource") @@ -1124,7 +1165,6 @@ func init() { proto.RegisterType((*LimitRangeList)(nil), "k8s.io.api.core.v1.LimitRangeList") proto.RegisterType((*LimitRangeSpec)(nil), "k8s.io.api.core.v1.LimitRangeSpec") proto.RegisterType((*List)(nil), "k8s.io.api.core.v1.List") - proto.RegisterType((*ListOptions)(nil), "k8s.io.api.core.v1.ListOptions") proto.RegisterType((*LoadBalancerIngress)(nil), "k8s.io.api.core.v1.LoadBalancerIngress") proto.RegisterType((*LoadBalancerStatus)(nil), "k8s.io.api.core.v1.LoadBalancerStatus") proto.RegisterType((*LocalObjectReference)(nil), "k8s.io.api.core.v1.LocalObjectReference") @@ -1139,6 +1179,7 @@ func init() { proto.RegisterType((*NodeAffinity)(nil), "k8s.io.api.core.v1.NodeAffinity") proto.RegisterType((*NodeCondition)(nil), "k8s.io.api.core.v1.NodeCondition") proto.RegisterType((*NodeConfigSource)(nil), "k8s.io.api.core.v1.NodeConfigSource") + proto.RegisterType((*NodeConfigStatus)(nil), "k8s.io.api.core.v1.NodeConfigStatus") proto.RegisterType((*NodeDaemonEndpoints)(nil), "k8s.io.api.core.v1.NodeDaemonEndpoints") proto.RegisterType((*NodeList)(nil), "k8s.io.api.core.v1.NodeList") proto.RegisterType((*NodeProxyOptions)(nil), "k8s.io.api.core.v1.NodeProxyOptions") @@ -1150,7 +1191,6 @@ func init() { proto.RegisterType((*NodeStatus)(nil), "k8s.io.api.core.v1.NodeStatus") proto.RegisterType((*NodeSystemInfo)(nil), "k8s.io.api.core.v1.NodeSystemInfo") proto.RegisterType((*ObjectFieldSelector)(nil), "k8s.io.api.core.v1.ObjectFieldSelector") - proto.RegisterType((*ObjectMeta)(nil), "k8s.io.api.core.v1.ObjectMeta") proto.RegisterType((*ObjectReference)(nil), "k8s.io.api.core.v1.ObjectReference") proto.RegisterType((*PersistentVolume)(nil), "k8s.io.api.core.v1.PersistentVolume") proto.RegisterType((*PersistentVolumeClaim)(nil), "k8s.io.api.core.v1.PersistentVolumeClaim") @@ -1177,6 +1217,7 @@ func init() { proto.RegisterType((*PodLogOptions)(nil), "k8s.io.api.core.v1.PodLogOptions") proto.RegisterType((*PodPortForwardOptions)(nil), "k8s.io.api.core.v1.PodPortForwardOptions") proto.RegisterType((*PodProxyOptions)(nil), "k8s.io.api.core.v1.PodProxyOptions") + proto.RegisterType((*PodReadinessGate)(nil), "k8s.io.api.core.v1.PodReadinessGate") proto.RegisterType((*PodSecurityContext)(nil), "k8s.io.api.core.v1.PodSecurityContext") proto.RegisterType((*PodSignature)(nil), "k8s.io.api.core.v1.PodSignature") proto.RegisterType((*PodSpec)(nil), "k8s.io.api.core.v1.PodSpec") @@ -1209,6 +1250,8 @@ func init() { proto.RegisterType((*SELinuxOptions)(nil), "k8s.io.api.core.v1.SELinuxOptions") proto.RegisterType((*ScaleIOPersistentVolumeSource)(nil), "k8s.io.api.core.v1.ScaleIOPersistentVolumeSource") proto.RegisterType((*ScaleIOVolumeSource)(nil), "k8s.io.api.core.v1.ScaleIOVolumeSource") + proto.RegisterType((*ScopeSelector)(nil), "k8s.io.api.core.v1.ScopeSelector") + proto.RegisterType((*ScopedResourceSelectorRequirement)(nil), "k8s.io.api.core.v1.ScopedResourceSelectorRequirement") proto.RegisterType((*Secret)(nil), "k8s.io.api.core.v1.Secret") proto.RegisterType((*SecretEnvSource)(nil), "k8s.io.api.core.v1.SecretEnvSource") proto.RegisterType((*SecretKeySelector)(nil), "k8s.io.api.core.v1.SecretKeySelector") @@ -1221,6 +1264,7 @@ func init() { proto.RegisterType((*Service)(nil), "k8s.io.api.core.v1.Service") proto.RegisterType((*ServiceAccount)(nil), "k8s.io.api.core.v1.ServiceAccount") proto.RegisterType((*ServiceAccountList)(nil), "k8s.io.api.core.v1.ServiceAccountList") + proto.RegisterType((*ServiceAccountTokenProjection)(nil), "k8s.io.api.core.v1.ServiceAccountTokenProjection") proto.RegisterType((*ServiceList)(nil), "k8s.io.api.core.v1.ServiceList") proto.RegisterType((*ServicePort)(nil), "k8s.io.api.core.v1.ServicePort") proto.RegisterType((*ServiceProxyOptions)(nil), "k8s.io.api.core.v1.ServiceProxyOptions") @@ -1233,6 +1277,8 @@ func init() { proto.RegisterType((*TCPSocketAction)(nil), "k8s.io.api.core.v1.TCPSocketAction") proto.RegisterType((*Taint)(nil), "k8s.io.api.core.v1.Taint") proto.RegisterType((*Toleration)(nil), "k8s.io.api.core.v1.Toleration") + proto.RegisterType((*TopologySelectorLabelRequirement)(nil), "k8s.io.api.core.v1.TopologySelectorLabelRequirement") + proto.RegisterType((*TopologySelectorTerm)(nil), "k8s.io.api.core.v1.TopologySelectorTerm") proto.RegisterType((*Volume)(nil), "k8s.io.api.core.v1.Volume") proto.RegisterType((*VolumeDevice)(nil), "k8s.io.api.core.v1.VolumeDevice") proto.RegisterType((*VolumeMount)(nil), "k8s.io.api.core.v1.VolumeMount") @@ -1809,6 +1855,50 @@ func (m *CephFSVolumeSource) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *CinderPersistentVolumeSource) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CinderPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.VolumeID))) + i += copy(dAtA[i:], m.VolumeID) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.FSType))) + i += copy(dAtA[i:], m.FSType) + dAtA[i] = 0x18 + i++ + if m.ReadOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + if m.SecretRef != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) + n11, err := m.SecretRef.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n11 + } + return i, nil +} + func (m *CinderVolumeSource) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1840,6 +1930,16 @@ func (m *CinderVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0 } i++ + if m.SecretRef != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) + n12, err := m.SecretRef.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n12 + } return i, nil } @@ -1918,11 +2018,11 @@ func (m *ComponentStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n11, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n13, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n11 + i += n13 if len(m.Conditions) > 0 { for _, msg := range m.Conditions { dAtA[i] = 0x12 @@ -1956,11 +2056,11 @@ func (m *ComponentStatusList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n12, err := m.ListMeta.MarshalTo(dAtA[i:]) + n14, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n12 + i += n14 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -1994,11 +2094,11 @@ func (m *ConfigMap) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n13, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n15, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n13 + i += n15 if len(m.Data) > 0 { keysForData := make([]string, 0, len(m.Data)) for k := range m.Data { @@ -2070,11 +2170,11 @@ func (m *ConfigMapEnvSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n14, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n16, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n14 + i += n16 if m.Optional != nil { dAtA[i] = 0x10 i++ @@ -2106,11 +2206,11 @@ func (m *ConfigMapKeySelector) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n15, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n17, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n15 + i += n17 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) @@ -2146,11 +2246,11 @@ func (m *ConfigMapList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n16, err := m.ListMeta.MarshalTo(dAtA[i:]) + n18, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n16 + i += n18 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -2166,6 +2266,44 @@ func (m *ConfigMapList) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ConfigMapNodeConfigSource) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConfigMapNodeConfigSource) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Namespace))) + i += copy(dAtA[i:], m.Namespace) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.UID))) + i += copy(dAtA[i:], m.UID) + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ResourceVersion))) + i += copy(dAtA[i:], m.ResourceVersion) + dAtA[i] = 0x2a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.KubeletConfigKey))) + i += copy(dAtA[i:], m.KubeletConfigKey) + return i, nil +} + func (m *ConfigMapProjection) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2184,11 +2322,11 @@ func (m *ConfigMapProjection) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n17, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n19, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n17 + i += n19 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -2232,11 +2370,11 @@ func (m *ConfigMapVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n18, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n20, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n18 + i += n20 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -2351,11 +2489,11 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x42 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Resources.Size())) - n19, err := m.Resources.MarshalTo(dAtA[i:]) + n21, err := m.Resources.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n19 + i += n21 if len(m.VolumeMounts) > 0 { for _, msg := range m.VolumeMounts { dAtA[i] = 0x4a @@ -2372,31 +2510,31 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LivenessProbe.Size())) - n20, err := m.LivenessProbe.MarshalTo(dAtA[i:]) + n22, err := m.LivenessProbe.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n20 + i += n22 } if m.ReadinessProbe != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ReadinessProbe.Size())) - n21, err := m.ReadinessProbe.MarshalTo(dAtA[i:]) + n23, err := m.ReadinessProbe.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n21 + i += n23 } if m.Lifecycle != nil { dAtA[i] = 0x62 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Lifecycle.Size())) - n22, err := m.Lifecycle.MarshalTo(dAtA[i:]) + n24, err := m.Lifecycle.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n22 + i += n24 } dAtA[i] = 0x6a i++ @@ -2410,11 +2548,11 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x7a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecurityContext.Size())) - n23, err := m.SecurityContext.MarshalTo(dAtA[i:]) + n25, err := m.SecurityContext.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n23 + i += n25 } dAtA[i] = 0x80 i++ @@ -2574,31 +2712,31 @@ func (m *ContainerState) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Waiting.Size())) - n24, err := m.Waiting.MarshalTo(dAtA[i:]) + n26, err := m.Waiting.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n24 + i += n26 } if m.Running != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Running.Size())) - n25, err := m.Running.MarshalTo(dAtA[i:]) + n27, err := m.Running.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n25 + i += n27 } if m.Terminated != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Terminated.Size())) - n26, err := m.Terminated.MarshalTo(dAtA[i:]) + n28, err := m.Terminated.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n26 + i += n28 } return i, nil } @@ -2621,11 +2759,11 @@ func (m *ContainerStateRunning) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StartedAt.Size())) - n27, err := m.StartedAt.MarshalTo(dAtA[i:]) + n29, err := m.StartedAt.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n27 + i += n29 return i, nil } @@ -2661,19 +2799,19 @@ func (m *ContainerStateTerminated) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StartedAt.Size())) - n28, err := m.StartedAt.MarshalTo(dAtA[i:]) + n30, err := m.StartedAt.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n28 + i += n30 dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FinishedAt.Size())) - n29, err := m.FinishedAt.MarshalTo(dAtA[i:]) + n31, err := m.FinishedAt.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n29 + i += n31 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.ContainerID))) @@ -2729,19 +2867,19 @@ func (m *ContainerStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.State.Size())) - n30, err := m.State.MarshalTo(dAtA[i:]) + n32, err := m.State.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n30 + i += n32 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTerminationState.Size())) - n31, err := m.LastTerminationState.MarshalTo(dAtA[i:]) + n33, err := m.LastTerminationState.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n31 + i += n33 dAtA[i] = 0x20 i++ if m.Ready { @@ -2789,55 +2927,6 @@ func (m *DaemonEndpoint) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *DeleteOptions) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *DeleteOptions) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.GracePeriodSeconds != nil { - dAtA[i] = 0x8 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(*m.GracePeriodSeconds)) - } - if m.Preconditions != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Preconditions.Size())) - n32, err := m.Preconditions.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n32 - } - if m.OrphanDependents != nil { - dAtA[i] = 0x18 - i++ - if *m.OrphanDependents { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - } - if m.PropagationPolicy != nil { - dAtA[i] = 0x22 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(*m.PropagationPolicy))) - i += copy(dAtA[i:], *m.PropagationPolicy) - } - return i, nil -} - func (m *DownwardAPIProjection) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2891,21 +2980,21 @@ func (m *DownwardAPIVolumeFile) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FieldRef.Size())) - n33, err := m.FieldRef.MarshalTo(dAtA[i:]) + n34, err := m.FieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n33 + i += n34 } if m.ResourceFieldRef != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ResourceFieldRef.Size())) - n34, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) + n35, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n34 + i += n35 } if m.Mode != nil { dAtA[i] = 0x20 @@ -2973,11 +3062,11 @@ func (m *EmptyDirVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SizeLimit.Size())) - n35, err := m.SizeLimit.MarshalTo(dAtA[i:]) + n36, err := m.SizeLimit.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n36 } return i, nil } @@ -3005,11 +3094,11 @@ func (m *EndpointAddress) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TargetRef.Size())) - n36, err := m.TargetRef.MarshalTo(dAtA[i:]) + n37, err := m.TargetRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n37 } dAtA[i] = 0x1a i++ @@ -3125,11 +3214,11 @@ func (m *Endpoints) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n37, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n38, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n38 if len(m.Subsets) > 0 { for _, msg := range m.Subsets { dAtA[i] = 0x12 @@ -3163,11 +3252,11 @@ func (m *EndpointsList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n38, err := m.ListMeta.MarshalTo(dAtA[i:]) + n39, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n39 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -3206,21 +3295,21 @@ func (m *EnvFromSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMapRef.Size())) - n39, err := m.ConfigMapRef.MarshalTo(dAtA[i:]) + n40, err := m.ConfigMapRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n40 } if m.SecretRef != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n40, err := m.SecretRef.MarshalTo(dAtA[i:]) + n41, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n41 } return i, nil } @@ -3252,11 +3341,11 @@ func (m *EnvVar) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ValueFrom.Size())) - n41, err := m.ValueFrom.MarshalTo(dAtA[i:]) + n42, err := m.ValueFrom.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n41 + i += n42 } return i, nil } @@ -3280,41 +3369,41 @@ func (m *EnvVarSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FieldRef.Size())) - n42, err := m.FieldRef.MarshalTo(dAtA[i:]) + n43, err := m.FieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n42 + i += n43 } if m.ResourceFieldRef != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ResourceFieldRef.Size())) - n43, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) + n44, err := m.ResourceFieldRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n43 + i += n44 } if m.ConfigMapKeyRef != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMapKeyRef.Size())) - n44, err := m.ConfigMapKeyRef.MarshalTo(dAtA[i:]) + n45, err := m.ConfigMapKeyRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n44 + i += n45 } if m.SecretKeyRef != nil { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretKeyRef.Size())) - n45, err := m.SecretKeyRef.MarshalTo(dAtA[i:]) + n46, err := m.SecretKeyRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n45 + i += n46 } return i, nil } @@ -3337,19 +3426,19 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n46, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n47, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n46 + i += n47 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.InvolvedObject.Size())) - n47, err := m.InvolvedObject.MarshalTo(dAtA[i:]) + n48, err := m.InvolvedObject.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n47 + i += n48 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -3361,27 +3450,27 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Source.Size())) - n48, err := m.Source.MarshalTo(dAtA[i:]) + n49, err := m.Source.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n48 + i += n49 dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FirstTimestamp.Size())) - n49, err := m.FirstTimestamp.MarshalTo(dAtA[i:]) + n50, err := m.FirstTimestamp.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n49 + i += n50 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTimestamp.Size())) - n50, err := m.LastTimestamp.MarshalTo(dAtA[i:]) + n51, err := m.LastTimestamp.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n50 + i += n51 dAtA[i] = 0x40 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Count)) @@ -3392,20 +3481,20 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.EventTime.Size())) - n51, err := m.EventTime.MarshalTo(dAtA[i:]) + n52, err := m.EventTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n51 + i += n52 if m.Series != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Series.Size())) - n52, err := m.Series.MarshalTo(dAtA[i:]) + n53, err := m.Series.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n52 + i += n53 } dAtA[i] = 0x62 i++ @@ -3415,11 +3504,11 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x6a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Related.Size())) - n53, err := m.Related.MarshalTo(dAtA[i:]) + n54, err := m.Related.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n53 + i += n54 } dAtA[i] = 0x72 i++ @@ -3450,11 +3539,11 @@ func (m *EventList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n54, err := m.ListMeta.MarshalTo(dAtA[i:]) + n55, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n54 + i += n55 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -3491,11 +3580,11 @@ func (m *EventSeries) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastObservedTime.Size())) - n55, err := m.LastObservedTime.MarshalTo(dAtA[i:]) + n56, err := m.LastObservedTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n55 + i += n56 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.State))) @@ -3654,11 +3743,11 @@ func (m *FlexPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n56, err := m.SecretRef.MarshalTo(dAtA[i:]) + n57, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n56 + i += n57 } dAtA[i] = 0x20 i++ @@ -3720,11 +3809,11 @@ func (m *FlexVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n57, err := m.SecretRef.MarshalTo(dAtA[i:]) + n58, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n57 + i += n58 } dAtA[i] = 0x20 i++ @@ -3908,11 +3997,11 @@ func (m *HTTPGetAction) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Port.Size())) - n58, err := m.Port.MarshalTo(dAtA[i:]) + n59, err := m.Port.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n58 + i += n59 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Host))) @@ -3981,31 +4070,31 @@ func (m *Handler) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Exec.Size())) - n59, err := m.Exec.MarshalTo(dAtA[i:]) + n60, err := m.Exec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n59 + i += n60 } if m.HTTPGet != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.HTTPGet.Size())) - n60, err := m.HTTPGet.MarshalTo(dAtA[i:]) + n61, err := m.HTTPGet.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n60 + i += n61 } if m.TCPSocket != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TCPSocket.Size())) - n61, err := m.TCPSocket.MarshalTo(dAtA[i:]) + n62, err := m.TCPSocket.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n61 + i += n62 } return i, nil } @@ -4144,11 +4233,11 @@ func (m *ISCSIPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n62, err := m.SecretRef.MarshalTo(dAtA[i:]) + n63, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n62 + i += n63 } dAtA[i] = 0x58 i++ @@ -4236,11 +4325,11 @@ func (m *ISCSIVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n63, err := m.SecretRef.MarshalTo(dAtA[i:]) + n64, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n63 + i += n64 } dAtA[i] = 0x58 i++ @@ -4309,21 +4398,21 @@ func (m *Lifecycle) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PostStart.Size())) - n64, err := m.PostStart.MarshalTo(dAtA[i:]) + n65, err := m.PostStart.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n64 + i += n65 } if m.PreStop != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PreStop.Size())) - n65, err := m.PreStop.MarshalTo(dAtA[i:]) + n66, err := m.PreStop.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n65 + i += n66 } return i, nil } @@ -4346,19 +4435,19 @@ func (m *LimitRange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n66, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n67, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n66 + i += n67 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n67, err := m.Spec.MarshalTo(dAtA[i:]) + n68, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n67 + i += n68 return i, nil } @@ -4405,37 +4494,6 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n68, err := (&v).MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n68 - } - } - if len(m.Min) > 0 { - keysForMin := make([]string, 0, len(m.Min)) - for k := range m.Min { - keysForMin = append(keysForMin, string(k)) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForMin) - for _, k := range keysForMin { - dAtA[i] = 0x1a - i++ - v := m.Min[ResourceName(k)] - msgSize := 0 - if (&v) != nil { - msgSize = (&v).Size() - msgSize += 1 + sovGenerated(uint64(msgSize)) - } - mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + msgSize - i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(k))) - i += copy(dAtA[i:], k) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) n69, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err @@ -4443,6 +4501,37 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { i += n69 } } + if len(m.Min) > 0 { + keysForMin := make([]string, 0, len(m.Min)) + for k := range m.Min { + keysForMin = append(keysForMin, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForMin) + for _, k := range keysForMin { + dAtA[i] = 0x1a + i++ + v := m.Min[ResourceName(k)] + msgSize := 0 + if (&v) != nil { + msgSize = (&v).Size() + msgSize += 1 + sovGenerated(uint64(msgSize)) + } + mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + msgSize + i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) + n70, err := (&v).MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n70 + } + } if len(m.Default) > 0 { keysForDefault := make([]string, 0, len(m.Default)) for k := range m.Default { @@ -4467,11 +4556,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n70, err := (&v).MarshalTo(dAtA[i:]) + n71, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n70 + i += n71 } } if len(m.DefaultRequest) > 0 { @@ -4498,11 +4587,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n71, err := (&v).MarshalTo(dAtA[i:]) + n72, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n71 + i += n72 } } if len(m.MaxLimitRequestRatio) > 0 { @@ -4529,11 +4618,11 @@ func (m *LimitRangeItem) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n72, err := (&v).MarshalTo(dAtA[i:]) + n73, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n72 + i += n73 } } return i, nil @@ -4557,11 +4646,11 @@ func (m *LimitRangeList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n73, err := m.ListMeta.MarshalTo(dAtA[i:]) + n74, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n73 + i += n74 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -4625,11 +4714,11 @@ func (m *List) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n74, err := m.ListMeta.MarshalTo(dAtA[i:]) + n75, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n74 + i += n75 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -4645,57 +4734,6 @@ func (m *List) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *ListOptions) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ListOptions) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.LabelSelector))) - i += copy(dAtA[i:], m.LabelSelector) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.FieldSelector))) - i += copy(dAtA[i:], m.FieldSelector) - dAtA[i] = 0x18 - i++ - if m.Watch { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - dAtA[i] = 0x22 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.ResourceVersion))) - i += copy(dAtA[i:], m.ResourceVersion) - if m.TimeoutSeconds != nil { - dAtA[i] = 0x28 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(*m.TimeoutSeconds)) - } - dAtA[i] = 0x30 - i++ - if m.IncludeUninitialized { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - return i, nil -} - func (m *LoadBalancerIngress) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -4848,27 +4886,27 @@ func (m *Namespace) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n75, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n76, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n75 + i += n76 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n76, err := m.Spec.MarshalTo(dAtA[i:]) + n77, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n76 + i += n77 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n77, err := m.Status.MarshalTo(dAtA[i:]) + n78, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n77 + i += n78 return i, nil } @@ -4890,11 +4928,11 @@ func (m *NamespaceList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n78, err := m.ListMeta.MarshalTo(dAtA[i:]) + n79, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n78 + i += n79 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -4983,27 +5021,27 @@ func (m *Node) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n79, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n80, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n79 + i += n80 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n80, err := m.Spec.MarshalTo(dAtA[i:]) + n81, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n80 + i += n81 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n81, err := m.Status.MarshalTo(dAtA[i:]) + n82, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n81 + i += n82 return i, nil } @@ -5052,11 +5090,11 @@ func (m *NodeAffinity) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.RequiredDuringSchedulingIgnoredDuringExecution.Size())) - n82, err := m.RequiredDuringSchedulingIgnoredDuringExecution.MarshalTo(dAtA[i:]) + n83, err := m.RequiredDuringSchedulingIgnoredDuringExecution.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n82 + i += n83 } if len(m.PreferredDuringSchedulingIgnoredDuringExecution) > 0 { for _, msg := range m.PreferredDuringSchedulingIgnoredDuringExecution { @@ -5099,19 +5137,19 @@ func (m *NodeCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastHeartbeatTime.Size())) - n83, err := m.LastHeartbeatTime.MarshalTo(dAtA[i:]) + n84, err := m.LastHeartbeatTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n83 + i += n84 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n84, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n85, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n84 + i += n85 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -5138,16 +5176,68 @@ func (m *NodeConfigSource) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.ConfigMapRef != nil { + if m.ConfigMap != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMap.Size())) + n86, err := m.ConfigMap.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n86 + } + return i, nil +} + +func (m *NodeConfigStatus) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NodeConfigStatus) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Assigned != nil { dAtA[i] = 0xa i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMapRef.Size())) - n85, err := m.ConfigMapRef.MarshalTo(dAtA[i:]) + i = encodeVarintGenerated(dAtA, i, uint64(m.Assigned.Size())) + n87, err := m.Assigned.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n87 + } + if m.Active != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Active.Size())) + n88, err := m.Active.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n88 + } + if m.LastKnownGood != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.LastKnownGood.Size())) + n89, err := m.LastKnownGood.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n85 + i += n89 } + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Error))) + i += copy(dAtA[i:], m.Error) return i, nil } @@ -5169,11 +5259,11 @@ func (m *NodeDaemonEndpoints) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.KubeletEndpoint.Size())) - n86, err := m.KubeletEndpoint.MarshalTo(dAtA[i:]) + n90, err := m.KubeletEndpoint.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n86 + i += n90 return i, nil } @@ -5195,11 +5285,11 @@ func (m *NodeList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n87, err := m.ListMeta.MarshalTo(dAtA[i:]) + n91, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n87 + i += n91 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -5276,11 +5366,11 @@ func (m *NodeResources) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n88, err := (&v).MarshalTo(dAtA[i:]) + n92, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n88 + i += n92 } } return i, nil @@ -5384,6 +5474,18 @@ func (m *NodeSelectorTerm) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.MatchFields) > 0 { + for _, msg := range m.MatchFields { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -5408,8 +5510,8 @@ func (m *NodeSpec) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], m.PodCIDR) dAtA[i] = 0x12 i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.ExternalID))) - i += copy(dAtA[i:], m.ExternalID) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.DoNotUse_ExternalID))) + i += copy(dAtA[i:], m.DoNotUse_ExternalID) dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.ProviderID))) @@ -5438,11 +5540,11 @@ func (m *NodeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigSource.Size())) - n89, err := m.ConfigSource.MarshalTo(dAtA[i:]) + n93, err := m.ConfigSource.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n89 + i += n93 } return i, nil } @@ -5486,11 +5588,11 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n90, err := (&v).MarshalTo(dAtA[i:]) + n94, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n90 + i += n94 } } if len(m.Allocatable) > 0 { @@ -5517,11 +5619,11 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n91, err := (&v).MarshalTo(dAtA[i:]) + n95, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n91 + i += n95 } } dAtA[i] = 0x1a @@ -5555,19 +5657,19 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DaemonEndpoints.Size())) - n92, err := m.DaemonEndpoints.MarshalTo(dAtA[i:]) + n96, err := m.DaemonEndpoints.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n92 + i += n96 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NodeInfo.Size())) - n93, err := m.NodeInfo.MarshalTo(dAtA[i:]) + n97, err := m.NodeInfo.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n93 + i += n97 if len(m.Images) > 0 { for _, msg := range m.Images { dAtA[i] = 0x42 @@ -5607,6 +5709,16 @@ func (m *NodeStatus) MarshalTo(dAtA []byte) (int, error) { i += n } } + if m.Config != nil { + dAtA[i] = 0x5a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Config.Size())) + n98, err := m.Config.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n98 + } return i, nil } @@ -5694,161 +5806,6 @@ func (m *ObjectFieldSelector) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *ObjectMeta) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ObjectMeta) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) - i += copy(dAtA[i:], m.Name) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.GenerateName))) - i += copy(dAtA[i:], m.GenerateName) - dAtA[i] = 0x1a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Namespace))) - i += copy(dAtA[i:], m.Namespace) - dAtA[i] = 0x22 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.SelfLink))) - i += copy(dAtA[i:], m.SelfLink) - dAtA[i] = 0x2a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.UID))) - i += copy(dAtA[i:], m.UID) - dAtA[i] = 0x32 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.ResourceVersion))) - i += copy(dAtA[i:], m.ResourceVersion) - dAtA[i] = 0x38 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Generation)) - dAtA[i] = 0x42 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.CreationTimestamp.Size())) - n94, err := m.CreationTimestamp.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n94 - if m.DeletionTimestamp != nil { - dAtA[i] = 0x4a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.DeletionTimestamp.Size())) - n95, err := m.DeletionTimestamp.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n95 - } - if m.DeletionGracePeriodSeconds != nil { - dAtA[i] = 0x50 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(*m.DeletionGracePeriodSeconds)) - } - if len(m.Labels) > 0 { - keysForLabels := make([]string, 0, len(m.Labels)) - for k := range m.Labels { - keysForLabels = append(keysForLabels, string(k)) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) - for _, k := range keysForLabels { - dAtA[i] = 0x5a - i++ - v := m.Labels[string(k)] - mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) - i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(k))) - i += copy(dAtA[i:], k) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(v))) - i += copy(dAtA[i:], v) - } - } - if len(m.Annotations) > 0 { - keysForAnnotations := make([]string, 0, len(m.Annotations)) - for k := range m.Annotations { - keysForAnnotations = append(keysForAnnotations, string(k)) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations) - for _, k := range keysForAnnotations { - dAtA[i] = 0x62 - i++ - v := m.Annotations[string(k)] - mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) - i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) - dAtA[i] = 0xa - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(k))) - i += copy(dAtA[i:], k) - dAtA[i] = 0x12 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(v))) - i += copy(dAtA[i:], v) - } - } - if len(m.OwnerReferences) > 0 { - for _, msg := range m.OwnerReferences { - dAtA[i] = 0x6a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n - } - } - if len(m.Finalizers) > 0 { - for _, s := range m.Finalizers { - dAtA[i] = 0x72 - i++ - l = len(s) - for l >= 1<<7 { - dAtA[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - dAtA[i] = uint8(l) - i++ - i += copy(dAtA[i:], s) - } - } - dAtA[i] = 0x7a - i++ - i = encodeVarintGenerated(dAtA, i, uint64(len(m.ClusterName))) - i += copy(dAtA[i:], m.ClusterName) - if m.Initializers != nil { - dAtA[i] = 0x82 - i++ - dAtA[i] = 0x1 - i++ - i = encodeVarintGenerated(dAtA, i, uint64(m.Initializers.Size())) - n96, err := m.Initializers.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n96 - } - return i, nil -} - func (m *ObjectReference) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -5913,27 +5870,27 @@ func (m *PersistentVolume) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n97, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n99, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n97 + i += n99 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n98, err := m.Spec.MarshalTo(dAtA[i:]) + n100, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n98 + i += n100 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n99, err := m.Status.MarshalTo(dAtA[i:]) + n101, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n99 + i += n101 return i, nil } @@ -5955,27 +5912,27 @@ func (m *PersistentVolumeClaim) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n100, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n102, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n100 + i += n102 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n101, err := m.Spec.MarshalTo(dAtA[i:]) + n103, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n101 + i += n103 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n102, err := m.Status.MarshalTo(dAtA[i:]) + n104, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n102 + i += n104 return i, nil } @@ -6005,19 +5962,19 @@ func (m *PersistentVolumeClaimCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastProbeTime.Size())) - n103, err := m.LastProbeTime.MarshalTo(dAtA[i:]) + n105, err := m.LastProbeTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n103 + i += n105 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n104, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n106, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n104 + i += n106 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -6047,11 +6004,11 @@ func (m *PersistentVolumeClaimList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n105, err := m.ListMeta.MarshalTo(dAtA[i:]) + n107, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n105 + i += n107 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -6100,11 +6057,11 @@ func (m *PersistentVolumeClaimSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Resources.Size())) - n106, err := m.Resources.MarshalTo(dAtA[i:]) + n108, err := m.Resources.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n106 + i += n108 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.VolumeName))) @@ -6113,11 +6070,11 @@ func (m *PersistentVolumeClaimSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Selector.Size())) - n107, err := m.Selector.MarshalTo(dAtA[i:]) + n109, err := m.Selector.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n107 + i += n109 } if m.StorageClassName != nil { dAtA[i] = 0x2a @@ -6192,11 +6149,11 @@ func (m *PersistentVolumeClaimStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n108, err := (&v).MarshalTo(dAtA[i:]) + n110, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n108 + i += n110 } } if len(m.Conditions) > 0 { @@ -6262,11 +6219,11 @@ func (m *PersistentVolumeList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n109, err := m.ListMeta.MarshalTo(dAtA[i:]) + n111, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n109 + i += n111 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -6301,151 +6258,151 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.GCEPersistentDisk.Size())) - n110, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) + n112, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n110 + i += n112 } if m.AWSElasticBlockStore != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AWSElasticBlockStore.Size())) - n111, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) + n113, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n111 + i += n113 } if m.HostPath != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.HostPath.Size())) - n112, err := m.HostPath.MarshalTo(dAtA[i:]) + n114, err := m.HostPath.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n112 + i += n114 } if m.Glusterfs != nil { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Glusterfs.Size())) - n113, err := m.Glusterfs.MarshalTo(dAtA[i:]) + n115, err := m.Glusterfs.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n113 + i += n115 } if m.NFS != nil { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NFS.Size())) - n114, err := m.NFS.MarshalTo(dAtA[i:]) + n116, err := m.NFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n114 + i += n116 } if m.RBD != nil { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.RBD.Size())) - n115, err := m.RBD.MarshalTo(dAtA[i:]) + n117, err := m.RBD.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n115 + i += n117 } if m.ISCSI != nil { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ISCSI.Size())) - n116, err := m.ISCSI.MarshalTo(dAtA[i:]) + n118, err := m.ISCSI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n116 + i += n118 } if m.Cinder != nil { dAtA[i] = 0x42 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Cinder.Size())) - n117, err := m.Cinder.MarshalTo(dAtA[i:]) + n119, err := m.Cinder.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n117 + i += n119 } if m.CephFS != nil { dAtA[i] = 0x4a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.CephFS.Size())) - n118, err := m.CephFS.MarshalTo(dAtA[i:]) + n120, err := m.CephFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n118 + i += n120 } if m.FC != nil { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FC.Size())) - n119, err := m.FC.MarshalTo(dAtA[i:]) + n121, err := m.FC.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n119 + i += n121 } if m.Flocker != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Flocker.Size())) - n120, err := m.Flocker.MarshalTo(dAtA[i:]) + n122, err := m.Flocker.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n120 + i += n122 } if m.FlexVolume != nil { dAtA[i] = 0x62 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FlexVolume.Size())) - n121, err := m.FlexVolume.MarshalTo(dAtA[i:]) + n123, err := m.FlexVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n121 + i += n123 } if m.AzureFile != nil { dAtA[i] = 0x6a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureFile.Size())) - n122, err := m.AzureFile.MarshalTo(dAtA[i:]) + n124, err := m.AzureFile.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n122 + i += n124 } if m.VsphereVolume != nil { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.VsphereVolume.Size())) - n123, err := m.VsphereVolume.MarshalTo(dAtA[i:]) + n125, err := m.VsphereVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n123 + i += n125 } if m.Quobyte != nil { dAtA[i] = 0x7a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Quobyte.Size())) - n124, err := m.Quobyte.MarshalTo(dAtA[i:]) + n126, err := m.Quobyte.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n124 + i += n126 } if m.AzureDisk != nil { dAtA[i] = 0x82 @@ -6453,11 +6410,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureDisk.Size())) - n125, err := m.AzureDisk.MarshalTo(dAtA[i:]) + n127, err := m.AzureDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n125 + i += n127 } if m.PhotonPersistentDisk != nil { dAtA[i] = 0x8a @@ -6465,11 +6422,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PhotonPersistentDisk.Size())) - n126, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) + n128, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n126 + i += n128 } if m.PortworxVolume != nil { dAtA[i] = 0x92 @@ -6477,11 +6434,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PortworxVolume.Size())) - n127, err := m.PortworxVolume.MarshalTo(dAtA[i:]) + n129, err := m.PortworxVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n127 + i += n129 } if m.ScaleIO != nil { dAtA[i] = 0x9a @@ -6489,11 +6446,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ScaleIO.Size())) - n128, err := m.ScaleIO.MarshalTo(dAtA[i:]) + n130, err := m.ScaleIO.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n128 + i += n130 } if m.Local != nil { dAtA[i] = 0xa2 @@ -6501,11 +6458,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Local.Size())) - n129, err := m.Local.MarshalTo(dAtA[i:]) + n131, err := m.Local.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n129 + i += n131 } if m.StorageOS != nil { dAtA[i] = 0xaa @@ -6513,11 +6470,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StorageOS.Size())) - n130, err := m.StorageOS.MarshalTo(dAtA[i:]) + n132, err := m.StorageOS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n130 + i += n132 } if m.CSI != nil { dAtA[i] = 0xb2 @@ -6525,11 +6482,11 @@ func (m *PersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.CSI.Size())) - n131, err := m.CSI.MarshalTo(dAtA[i:]) + n133, err := m.CSI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n131 + i += n133 } return i, nil } @@ -6573,21 +6530,21 @@ func (m *PersistentVolumeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n132, err := (&v).MarshalTo(dAtA[i:]) + n134, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n132 + i += n134 } } dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PersistentVolumeSource.Size())) - n133, err := m.PersistentVolumeSource.MarshalTo(dAtA[i:]) + n135, err := m.PersistentVolumeSource.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n133 + i += n135 if len(m.AccessModes) > 0 { for _, s := range m.AccessModes { dAtA[i] = 0x1a @@ -6607,11 +6564,11 @@ func (m *PersistentVolumeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ClaimRef.Size())) - n134, err := m.ClaimRef.MarshalTo(dAtA[i:]) + n136, err := m.ClaimRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n134 + i += n136 } dAtA[i] = 0x2a i++ @@ -6646,11 +6603,11 @@ func (m *PersistentVolumeSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x4a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NodeAffinity.Size())) - n135, err := m.NodeAffinity.MarshalTo(dAtA[i:]) + n137, err := m.NodeAffinity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n135 + i += n137 } return i, nil } @@ -6729,27 +6686,27 @@ func (m *Pod) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n136, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n138, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n136 + i += n138 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n137, err := m.Spec.MarshalTo(dAtA[i:]) + n139, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n137 + i += n139 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n138, err := m.Status.MarshalTo(dAtA[i:]) + n140, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n138 + i += n140 return i, nil } @@ -6814,11 +6771,11 @@ func (m *PodAffinityTerm) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LabelSelector.Size())) - n139, err := m.LabelSelector.MarshalTo(dAtA[i:]) + n141, err := m.LabelSelector.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n139 + i += n141 } if len(m.Namespaces) > 0 { for _, s := range m.Namespaces { @@ -6964,19 +6921,19 @@ func (m *PodCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastProbeTime.Size())) - n140, err := m.LastProbeTime.MarshalTo(dAtA[i:]) + n142, err := m.LastProbeTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n140 + i += n142 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n141, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n143, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n141 + i += n143 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -7163,11 +7120,11 @@ func (m *PodList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n142, err := m.ListMeta.MarshalTo(dAtA[i:]) + n144, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n142 + i += n144 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -7227,11 +7184,11 @@ func (m *PodLogOptions) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SinceTime.Size())) - n143, err := m.SinceTime.MarshalTo(dAtA[i:]) + n145, err := m.SinceTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n143 + i += n145 } dAtA[i] = 0x30 i++ @@ -7301,6 +7258,28 @@ func (m *PodProxyOptions) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *PodReadinessGate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodReadinessGate) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ConditionType))) + i += copy(dAtA[i:], m.ConditionType) + return i, nil +} + func (m *PodSecurityContext) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7320,11 +7299,11 @@ func (m *PodSecurityContext) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SELinuxOptions.Size())) - n144, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) + n146, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n144 + i += n146 } if m.RunAsUser != nil { dAtA[i] = 0x10 @@ -7358,6 +7337,18 @@ func (m *PodSecurityContext) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintGenerated(dAtA, i, uint64(*m.RunAsGroup)) } + if len(m.Sysctls) > 0 { + for _, msg := range m.Sysctls { + dAtA[i] = 0x3a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -7380,11 +7371,11 @@ func (m *PodSignature) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PodController.Size())) - n145, err := m.PodController.MarshalTo(dAtA[i:]) + n147, err := m.PodController.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n145 + i += n147 } return i, nil } @@ -7508,11 +7499,11 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecurityContext.Size())) - n146, err := m.SecurityContext.MarshalTo(dAtA[i:]) + n148, err := m.SecurityContext.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n146 + i += n148 } if len(m.ImagePullSecrets) > 0 { for _, msg := range m.ImagePullSecrets { @@ -7544,11 +7535,11 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Affinity.Size())) - n147, err := m.Affinity.MarshalTo(dAtA[i:]) + n149, err := m.Affinity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n147 + i += n149 } dAtA[i] = 0x9a i++ @@ -7629,11 +7620,11 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DNSConfig.Size())) - n148, err := m.DNSConfig.MarshalTo(dAtA[i:]) + n150, err := m.DNSConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n148 + i += n150 } if m.ShareProcessNamespace != nil { dAtA[i] = 0xd8 @@ -7647,6 +7638,20 @@ func (m *PodSpec) MarshalTo(dAtA []byte) (int, error) { } i++ } + if len(m.ReadinessGates) > 0 { + for _, msg := range m.ReadinessGates { + dAtA[i] = 0xe2 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -7701,11 +7706,11 @@ func (m *PodStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StartTime.Size())) - n149, err := m.StartTime.MarshalTo(dAtA[i:]) + n151, err := m.StartTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n149 + i += n151 } if len(m.ContainerStatuses) > 0 { for _, msg := range m.ContainerStatuses { @@ -7760,19 +7765,19 @@ func (m *PodStatusResult) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n150, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n152, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n150 + i += n152 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n151, err := m.Status.MarshalTo(dAtA[i:]) + n153, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n151 + i += n153 return i, nil } @@ -7794,19 +7799,19 @@ func (m *PodTemplate) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n152, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n154, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n152 + i += n154 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Template.Size())) - n153, err := m.Template.MarshalTo(dAtA[i:]) + n155, err := m.Template.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n153 + i += n155 return i, nil } @@ -7828,11 +7833,11 @@ func (m *PodTemplateList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n154, err := m.ListMeta.MarshalTo(dAtA[i:]) + n156, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n154 + i += n156 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -7866,19 +7871,19 @@ func (m *PodTemplateSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n155, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n157, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n155 + i += n157 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n156, err := m.Spec.MarshalTo(dAtA[i:]) + n158, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n156 + i += n158 return i, nil } @@ -7958,19 +7963,19 @@ func (m *PreferAvoidPodsEntry) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PodSignature.Size())) - n157, err := m.PodSignature.MarshalTo(dAtA[i:]) + n159, err := m.PodSignature.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n157 + i += n159 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.EvictionTime.Size())) - n158, err := m.EvictionTime.MarshalTo(dAtA[i:]) + n160, err := m.EvictionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n158 + i += n160 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -8003,11 +8008,11 @@ func (m *PreferredSchedulingTerm) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Preference.Size())) - n159, err := m.Preference.MarshalTo(dAtA[i:]) + n161, err := m.Preference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n159 + i += n161 return i, nil } @@ -8029,11 +8034,11 @@ func (m *Probe) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Handler.Size())) - n160, err := m.Handler.MarshalTo(dAtA[i:]) + n162, err := m.Handler.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n160 + i += n162 dAtA[i] = 0x10 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.InitialDelaySeconds)) @@ -8183,11 +8188,11 @@ func (m *RBDPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n161, err := m.SecretRef.MarshalTo(dAtA[i:]) + n163, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n161 + i += n163 } dAtA[i] = 0x40 i++ @@ -8254,11 +8259,11 @@ func (m *RBDVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n162, err := m.SecretRef.MarshalTo(dAtA[i:]) + n164, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n162 + i += n164 } dAtA[i] = 0x40 i++ @@ -8289,11 +8294,11 @@ func (m *RangeAllocation) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n163, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n165, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n163 + i += n165 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Range))) @@ -8325,27 +8330,27 @@ func (m *ReplicationController) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n164, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n166, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n164 + i += n166 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n165, err := m.Spec.MarshalTo(dAtA[i:]) + n167, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n165 + i += n167 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n166, err := m.Status.MarshalTo(dAtA[i:]) + n168, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n166 + i += n168 return i, nil } @@ -8375,11 +8380,11 @@ func (m *ReplicationControllerCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n167, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n169, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n167 + i += n169 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -8409,11 +8414,11 @@ func (m *ReplicationControllerList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n168, err := m.ListMeta.MarshalTo(dAtA[i:]) + n170, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n168 + i += n170 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -8475,11 +8480,11 @@ func (m *ReplicationControllerSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Template.Size())) - n169, err := m.Template.MarshalTo(dAtA[i:]) + n171, err := m.Template.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n169 + i += n171 } dAtA[i] = 0x20 i++ @@ -8558,11 +8563,11 @@ func (m *ResourceFieldSelector) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Divisor.Size())) - n170, err := m.Divisor.MarshalTo(dAtA[i:]) + n172, err := m.Divisor.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n170 + i += n172 return i, nil } @@ -8584,27 +8589,27 @@ func (m *ResourceQuota) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n171, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n173, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n171 + i += n173 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n172, err := m.Spec.MarshalTo(dAtA[i:]) + n174, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n172 + i += n174 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n173, err := m.Status.MarshalTo(dAtA[i:]) + n175, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n173 + i += n175 return i, nil } @@ -8626,11 +8631,11 @@ func (m *ResourceQuotaList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n174, err := m.ListMeta.MarshalTo(dAtA[i:]) + n176, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n174 + i += n176 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -8685,11 +8690,11 @@ func (m *ResourceQuotaSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n175, err := (&v).MarshalTo(dAtA[i:]) + n177, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n175 + i += n177 } } if len(m.Scopes) > 0 { @@ -8707,6 +8712,16 @@ func (m *ResourceQuotaSpec) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], s) } } + if m.ScopeSelector != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ScopeSelector.Size())) + n178, err := m.ScopeSelector.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n178 + } return i, nil } @@ -8749,11 +8764,11 @@ func (m *ResourceQuotaStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n176, err := (&v).MarshalTo(dAtA[i:]) + n179, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n176 + i += n179 } } if len(m.Used) > 0 { @@ -8780,11 +8795,11 @@ func (m *ResourceQuotaStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n177, err := (&v).MarshalTo(dAtA[i:]) + n180, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n177 + i += n180 } } return i, nil @@ -8829,11 +8844,11 @@ func (m *ResourceRequirements) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n178, err := (&v).MarshalTo(dAtA[i:]) + n181, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n178 + i += n181 } } if len(m.Requests) > 0 { @@ -8860,11 +8875,11 @@ func (m *ResourceRequirements) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) - n179, err := (&v).MarshalTo(dAtA[i:]) + n182, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n179 + i += n182 } } return i, nil @@ -8931,11 +8946,11 @@ func (m *ScaleIOPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n180, err := m.SecretRef.MarshalTo(dAtA[i:]) + n183, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n180 + i += n183 } dAtA[i] = 0x20 i++ @@ -9003,11 +9018,11 @@ func (m *ScaleIOVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n181, err := m.SecretRef.MarshalTo(dAtA[i:]) + n184, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n181 + i += n184 } dAtA[i] = 0x20 i++ @@ -9048,6 +9063,77 @@ func (m *ScaleIOVolumeSource) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ScopeSelector) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ScopeSelector) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.MatchExpressions) > 0 { + for _, msg := range m.MatchExpressions { + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *ScopedResourceSelectorRequirement) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ScopedResourceSelectorRequirement) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ScopeName))) + i += copy(dAtA[i:], m.ScopeName) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Operator))) + i += copy(dAtA[i:], m.Operator) + if len(m.Values) > 0 { + for _, s := range m.Values { + dAtA[i] = 0x1a + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + func (m *Secret) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -9066,11 +9152,11 @@ func (m *Secret) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n182, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n185, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n182 + i += n185 if len(m.Data) > 0 { keysForData := make([]string, 0, len(m.Data)) for k := range m.Data { @@ -9146,11 +9232,11 @@ func (m *SecretEnvSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n183, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n186, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n183 + i += n186 if m.Optional != nil { dAtA[i] = 0x10 i++ @@ -9182,11 +9268,11 @@ func (m *SecretKeySelector) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n184, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n187, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n184 + i += n187 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) @@ -9222,11 +9308,11 @@ func (m *SecretList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n185, err := m.ListMeta.MarshalTo(dAtA[i:]) + n188, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n185 + i += n188 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9260,11 +9346,11 @@ func (m *SecretProjection) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LocalObjectReference.Size())) - n186, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) + n189, err := m.LocalObjectReference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n186 + i += n189 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9384,11 +9470,11 @@ func (m *SecurityContext) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Capabilities.Size())) - n187, err := m.Capabilities.MarshalTo(dAtA[i:]) + n190, err := m.Capabilities.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n187 + i += n190 } if m.Privileged != nil { dAtA[i] = 0x10 @@ -9404,11 +9490,11 @@ func (m *SecurityContext) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SELinuxOptions.Size())) - n188, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) + n191, err := m.SELinuxOptions.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n188 + i += n191 } if m.RunAsUser != nil { dAtA[i] = 0x20 @@ -9471,11 +9557,11 @@ func (m *SerializedReference) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Reference.Size())) - n189, err := m.Reference.MarshalTo(dAtA[i:]) + n192, err := m.Reference.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n189 + i += n192 return i, nil } @@ -9497,27 +9583,27 @@ func (m *Service) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n190, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n193, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n190 + i += n193 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) - n191, err := m.Spec.MarshalTo(dAtA[i:]) + n194, err := m.Spec.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n191 + i += n194 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n192, err := m.Status.MarshalTo(dAtA[i:]) + n195, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n192 + i += n195 return i, nil } @@ -9539,11 +9625,11 @@ func (m *ServiceAccount) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n193, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n196, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n193 + i += n196 if len(m.Secrets) > 0 { for _, msg := range m.Secrets { dAtA[i] = 0x12 @@ -9599,11 +9685,11 @@ func (m *ServiceAccountList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n194, err := m.ListMeta.MarshalTo(dAtA[i:]) + n197, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n194 + i += n197 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9619,6 +9705,37 @@ func (m *ServiceAccountList) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ServiceAccountTokenProjection) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ServiceAccountTokenProjection) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Audience))) + i += copy(dAtA[i:], m.Audience) + if m.ExpirationSeconds != nil { + dAtA[i] = 0x10 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(*m.ExpirationSeconds)) + } + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Path))) + i += copy(dAtA[i:], m.Path) + return i, nil +} + func (m *ServiceList) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -9637,11 +9754,11 @@ func (m *ServiceList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n195, err := m.ListMeta.MarshalTo(dAtA[i:]) + n198, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n195 + i += n198 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -9686,11 +9803,11 @@ func (m *ServicePort) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TargetPort.Size())) - n196, err := m.TargetPort.MarshalTo(dAtA[i:]) + n199, err := m.TargetPort.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n196 + i += n199 dAtA[i] = 0x28 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NodePort)) @@ -9837,11 +9954,11 @@ func (m *ServiceSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SessionAffinityConfig.Size())) - n197, err := m.SessionAffinityConfig.MarshalTo(dAtA[i:]) + n200, err := m.SessionAffinityConfig.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n197 + i += n200 } return i, nil } @@ -9864,11 +9981,11 @@ func (m *ServiceStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LoadBalancer.Size())) - n198, err := m.LoadBalancer.MarshalTo(dAtA[i:]) + n201, err := m.LoadBalancer.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n198 + i += n201 return i, nil } @@ -9891,11 +10008,11 @@ func (m *SessionAffinityConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ClientIP.Size())) - n199, err := m.ClientIP.MarshalTo(dAtA[i:]) + n202, err := m.ClientIP.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n199 + i += n202 } return i, nil } @@ -9939,11 +10056,11 @@ func (m *StorageOSPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n200, err := m.SecretRef.MarshalTo(dAtA[i:]) + n203, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n200 + i += n203 } return i, nil } @@ -9987,11 +10104,11 @@ func (m *StorageOSVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SecretRef.Size())) - n201, err := m.SecretRef.MarshalTo(dAtA[i:]) + n204, err := m.SecretRef.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n201 + i += n204 } return i, nil } @@ -10040,11 +10157,11 @@ func (m *TCPSocketAction) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Port.Size())) - n202, err := m.Port.MarshalTo(dAtA[i:]) + n205, err := m.Port.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n202 + i += n205 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Host))) @@ -10083,11 +10200,11 @@ func (m *Taint) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.TimeAdded.Size())) - n203, err := m.TimeAdded.MarshalTo(dAtA[i:]) + n206, err := m.TimeAdded.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n203 + i += n206 } return i, nil } @@ -10131,6 +10248,73 @@ func (m *Toleration) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *TopologySelectorLabelRequirement) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TopologySelectorLabelRequirement) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key))) + i += copy(dAtA[i:], m.Key) + if len(m.Values) > 0 { + for _, s := range m.Values { + dAtA[i] = 0x12 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + +func (m *TopologySelectorTerm) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TopologySelectorTerm) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.MatchLabelExpressions) > 0 { + for _, msg := range m.MatchLabelExpressions { + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + func (m *Volume) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -10153,11 +10337,11 @@ func (m *Volume) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.VolumeSource.Size())) - n204, err := m.VolumeSource.MarshalTo(dAtA[i:]) + n207, err := m.VolumeSource.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n204 + i += n207 return i, nil } @@ -10250,11 +10434,11 @@ func (m *VolumeNodeAffinity) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Required.Size())) - n205, err := m.Required.MarshalTo(dAtA[i:]) + n208, err := m.Required.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n205 + i += n208 } return i, nil } @@ -10278,31 +10462,41 @@ func (m *VolumeProjection) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Secret.Size())) - n206, err := m.Secret.MarshalTo(dAtA[i:]) + n209, err := m.Secret.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n206 + i += n209 } if m.DownwardAPI != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DownwardAPI.Size())) - n207, err := m.DownwardAPI.MarshalTo(dAtA[i:]) + n210, err := m.DownwardAPI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n207 + i += n210 } if m.ConfigMap != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMap.Size())) - n208, err := m.ConfigMap.MarshalTo(dAtA[i:]) + n211, err := m.ConfigMap.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n208 + i += n211 + } + if m.ServiceAccountToken != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ServiceAccountToken.Size())) + n212, err := m.ServiceAccountToken.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n212 } return i, nil } @@ -10326,151 +10520,151 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.HostPath.Size())) - n209, err := m.HostPath.MarshalTo(dAtA[i:]) + n213, err := m.HostPath.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n209 + i += n213 } if m.EmptyDir != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.EmptyDir.Size())) - n210, err := m.EmptyDir.MarshalTo(dAtA[i:]) + n214, err := m.EmptyDir.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n210 + i += n214 } if m.GCEPersistentDisk != nil { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.GCEPersistentDisk.Size())) - n211, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) + n215, err := m.GCEPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n211 + i += n215 } if m.AWSElasticBlockStore != nil { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AWSElasticBlockStore.Size())) - n212, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) + n216, err := m.AWSElasticBlockStore.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n212 + i += n216 } if m.GitRepo != nil { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.GitRepo.Size())) - n213, err := m.GitRepo.MarshalTo(dAtA[i:]) + n217, err := m.GitRepo.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n213 + i += n217 } if m.Secret != nil { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Secret.Size())) - n214, err := m.Secret.MarshalTo(dAtA[i:]) + n218, err := m.Secret.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n214 + i += n218 } if m.NFS != nil { dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.NFS.Size())) - n215, err := m.NFS.MarshalTo(dAtA[i:]) + n219, err := m.NFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n215 + i += n219 } if m.ISCSI != nil { dAtA[i] = 0x42 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ISCSI.Size())) - n216, err := m.ISCSI.MarshalTo(dAtA[i:]) + n220, err := m.ISCSI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n216 + i += n220 } if m.Glusterfs != nil { dAtA[i] = 0x4a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Glusterfs.Size())) - n217, err := m.Glusterfs.MarshalTo(dAtA[i:]) + n221, err := m.Glusterfs.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n217 + i += n221 } if m.PersistentVolumeClaim != nil { dAtA[i] = 0x52 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PersistentVolumeClaim.Size())) - n218, err := m.PersistentVolumeClaim.MarshalTo(dAtA[i:]) + n222, err := m.PersistentVolumeClaim.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n218 + i += n222 } if m.RBD != nil { dAtA[i] = 0x5a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.RBD.Size())) - n219, err := m.RBD.MarshalTo(dAtA[i:]) + n223, err := m.RBD.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n219 + i += n223 } if m.FlexVolume != nil { dAtA[i] = 0x62 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FlexVolume.Size())) - n220, err := m.FlexVolume.MarshalTo(dAtA[i:]) + n224, err := m.FlexVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n220 + i += n224 } if m.Cinder != nil { dAtA[i] = 0x6a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Cinder.Size())) - n221, err := m.Cinder.MarshalTo(dAtA[i:]) + n225, err := m.Cinder.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n221 + i += n225 } if m.CephFS != nil { dAtA[i] = 0x72 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.CephFS.Size())) - n222, err := m.CephFS.MarshalTo(dAtA[i:]) + n226, err := m.CephFS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n222 + i += n226 } if m.Flocker != nil { dAtA[i] = 0x7a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Flocker.Size())) - n223, err := m.Flocker.MarshalTo(dAtA[i:]) + n227, err := m.Flocker.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n223 + i += n227 } if m.DownwardAPI != nil { dAtA[i] = 0x82 @@ -10478,11 +10672,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.DownwardAPI.Size())) - n224, err := m.DownwardAPI.MarshalTo(dAtA[i:]) + n228, err := m.DownwardAPI.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n224 + i += n228 } if m.FC != nil { dAtA[i] = 0x8a @@ -10490,11 +10684,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.FC.Size())) - n225, err := m.FC.MarshalTo(dAtA[i:]) + n229, err := m.FC.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n225 + i += n229 } if m.AzureFile != nil { dAtA[i] = 0x92 @@ -10502,11 +10696,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureFile.Size())) - n226, err := m.AzureFile.MarshalTo(dAtA[i:]) + n230, err := m.AzureFile.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n226 + i += n230 } if m.ConfigMap != nil { dAtA[i] = 0x9a @@ -10514,11 +10708,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ConfigMap.Size())) - n227, err := m.ConfigMap.MarshalTo(dAtA[i:]) + n231, err := m.ConfigMap.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n227 + i += n231 } if m.VsphereVolume != nil { dAtA[i] = 0xa2 @@ -10526,11 +10720,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.VsphereVolume.Size())) - n228, err := m.VsphereVolume.MarshalTo(dAtA[i:]) + n232, err := m.VsphereVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n228 + i += n232 } if m.Quobyte != nil { dAtA[i] = 0xaa @@ -10538,11 +10732,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Quobyte.Size())) - n229, err := m.Quobyte.MarshalTo(dAtA[i:]) + n233, err := m.Quobyte.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n229 + i += n233 } if m.AzureDisk != nil { dAtA[i] = 0xb2 @@ -10550,11 +10744,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.AzureDisk.Size())) - n230, err := m.AzureDisk.MarshalTo(dAtA[i:]) + n234, err := m.AzureDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n230 + i += n234 } if m.PhotonPersistentDisk != nil { dAtA[i] = 0xba @@ -10562,11 +10756,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PhotonPersistentDisk.Size())) - n231, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) + n235, err := m.PhotonPersistentDisk.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n231 + i += n235 } if m.PortworxVolume != nil { dAtA[i] = 0xc2 @@ -10574,11 +10768,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PortworxVolume.Size())) - n232, err := m.PortworxVolume.MarshalTo(dAtA[i:]) + n236, err := m.PortworxVolume.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n232 + i += n236 } if m.ScaleIO != nil { dAtA[i] = 0xca @@ -10586,11 +10780,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ScaleIO.Size())) - n233, err := m.ScaleIO.MarshalTo(dAtA[i:]) + n237, err := m.ScaleIO.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n233 + i += n237 } if m.Projected != nil { dAtA[i] = 0xd2 @@ -10598,11 +10792,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Projected.Size())) - n234, err := m.Projected.MarshalTo(dAtA[i:]) + n238, err := m.Projected.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n234 + i += n238 } if m.StorageOS != nil { dAtA[i] = 0xda @@ -10610,11 +10804,11 @@ func (m *VolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.StorageOS.Size())) - n235, err := m.StorageOS.MarshalTo(dAtA[i:]) + n239, err := m.StorageOS.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n235 + i += n239 } return i, nil } @@ -10674,11 +10868,11 @@ func (m *WeightedPodAffinityTerm) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.PodAffinityTerm.Size())) - n236, err := m.PodAffinityTerm.MarshalTo(dAtA[i:]) + n240, err := m.PodAffinityTerm.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n236 + i += n240 return i, nil } @@ -10919,6 +11113,21 @@ func (m *CephFSVolumeSource) Size() (n int) { return n } +func (m *CinderPersistentVolumeSource) Size() (n int) { + var l int + _ = l + l = len(m.VolumeID) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.FSType) + n += 1 + l + sovGenerated(uint64(l)) + n += 2 + if m.SecretRef != nil { + l = m.SecretRef.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *CinderVolumeSource) Size() (n int) { var l int _ = l @@ -10927,6 +11136,10 @@ func (m *CinderVolumeSource) Size() (n int) { l = len(m.FSType) n += 1 + l + sovGenerated(uint64(l)) n += 2 + if m.SecretRef != nil { + l = m.SecretRef.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -11047,6 +11260,22 @@ func (m *ConfigMapList) Size() (n int) { return n } +func (m *ConfigMapNodeConfigSource) Size() (n int) { + var l int + _ = l + l = len(m.Namespace) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.UID) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.ResourceVersion) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.KubeletConfigKey) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *ConfigMapProjection) Size() (n int) { var l int _ = l @@ -11273,26 +11502,6 @@ func (m *DaemonEndpoint) Size() (n int) { return n } -func (m *DeleteOptions) Size() (n int) { - var l int - _ = l - if m.GracePeriodSeconds != nil { - n += 1 + sovGenerated(uint64(*m.GracePeriodSeconds)) - } - if m.Preconditions != nil { - l = m.Preconditions.Size() - n += 1 + l + sovGenerated(uint64(l)) - } - if m.OrphanDependents != nil { - n += 2 - } - if m.PropagationPolicy != nil { - l = len(*m.PropagationPolicy) - n += 1 + l + sovGenerated(uint64(l)) - } - return n -} - func (m *DownwardAPIProjection) Size() (n int) { var l int _ = l @@ -11953,23 +12162,6 @@ func (m *List) Size() (n int) { return n } -func (m *ListOptions) Size() (n int) { - var l int - _ = l - l = len(m.LabelSelector) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.FieldSelector) - n += 1 + l + sovGenerated(uint64(l)) - n += 2 - l = len(m.ResourceVersion) - n += 1 + l + sovGenerated(uint64(l)) - if m.TimeoutSeconds != nil { - n += 1 + sovGenerated(uint64(*m.TimeoutSeconds)) - } - n += 2 - return n -} - func (m *LoadBalancerIngress) Size() (n int) { var l int _ = l @@ -12124,10 +12316,30 @@ func (m *NodeCondition) Size() (n int) { func (m *NodeConfigSource) Size() (n int) { var l int _ = l - if m.ConfigMapRef != nil { - l = m.ConfigMapRef.Size() + if m.ConfigMap != nil { + l = m.ConfigMap.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + +func (m *NodeConfigStatus) Size() (n int) { + var l int + _ = l + if m.Assigned != nil { + l = m.Assigned.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.Active != nil { + l = m.Active.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.LastKnownGood != nil { + l = m.LastKnownGood.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + l = len(m.Error) + n += 1 + l + sovGenerated(uint64(l)) return n } @@ -12213,6 +12425,12 @@ func (m *NodeSelectorTerm) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if len(m.MatchFields) > 0 { + for _, e := range m.MatchFields { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -12221,7 +12439,7 @@ func (m *NodeSpec) Size() (n int) { _ = l l = len(m.PodCIDR) n += 1 + l + sovGenerated(uint64(l)) - l = len(m.ExternalID) + l = len(m.DoNotUse_ExternalID) n += 1 + l + sovGenerated(uint64(l)) l = len(m.ProviderID) n += 1 + l + sovGenerated(uint64(l)) @@ -12296,6 +12514,10 @@ func (m *NodeStatus) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if m.Config != nil { + l = m.Config.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -12335,68 +12557,6 @@ func (m *ObjectFieldSelector) Size() (n int) { return n } -func (m *ObjectMeta) Size() (n int) { - var l int - _ = l - l = len(m.Name) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.GenerateName) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.Namespace) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.SelfLink) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.UID) - n += 1 + l + sovGenerated(uint64(l)) - l = len(m.ResourceVersion) - n += 1 + l + sovGenerated(uint64(l)) - n += 1 + sovGenerated(uint64(m.Generation)) - l = m.CreationTimestamp.Size() - n += 1 + l + sovGenerated(uint64(l)) - if m.DeletionTimestamp != nil { - l = m.DeletionTimestamp.Size() - n += 1 + l + sovGenerated(uint64(l)) - } - if m.DeletionGracePeriodSeconds != nil { - n += 1 + sovGenerated(uint64(*m.DeletionGracePeriodSeconds)) - } - if len(m.Labels) > 0 { - for k, v := range m.Labels { - _ = k - _ = v - mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) - n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) - } - } - if len(m.Annotations) > 0 { - for k, v := range m.Annotations { - _ = k - _ = v - mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) - n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) - } - } - if len(m.OwnerReferences) > 0 { - for _, e := range m.OwnerReferences { - l = e.Size() - n += 1 + l + sovGenerated(uint64(l)) - } - } - if len(m.Finalizers) > 0 { - for _, s := range m.Finalizers { - l = len(s) - n += 1 + l + sovGenerated(uint64(l)) - } - } - l = len(m.ClusterName) - n += 1 + l + sovGenerated(uint64(l)) - if m.Initializers != nil { - l = m.Initializers.Size() - n += 2 + l + sovGenerated(uint64(l)) - } - return n -} - func (m *ObjectReference) Size() (n int) { var l int _ = l @@ -12921,6 +13081,14 @@ func (m *PodProxyOptions) Size() (n int) { return n } +func (m *PodReadinessGate) Size() (n int) { + var l int + _ = l + l = len(m.ConditionType) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *PodSecurityContext) Size() (n int) { var l int _ = l @@ -12945,6 +13113,12 @@ func (m *PodSecurityContext) Size() (n int) { if m.RunAsGroup != nil { n += 1 + sovGenerated(uint64(*m.RunAsGroup)) } + if len(m.Sysctls) > 0 { + for _, e := range m.Sysctls { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -13053,6 +13227,12 @@ func (m *PodSpec) Size() (n int) { if m.ShareProcessNamespace != nil { n += 3 } + if len(m.ReadinessGates) > 0 { + for _, e := range m.ReadinessGates { + l = e.Size() + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -13434,6 +13614,10 @@ func (m *ResourceQuotaSpec) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if m.ScopeSelector != nil { + l = m.ScopeSelector.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -13551,6 +13735,34 @@ func (m *ScaleIOVolumeSource) Size() (n int) { return n } +func (m *ScopeSelector) Size() (n int) { + var l int + _ = l + if len(m.MatchExpressions) > 0 { + for _, e := range m.MatchExpressions { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *ScopedResourceSelectorRequirement) Size() (n int) { + var l int + _ = l + l = len(m.ScopeName) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Operator) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Values) > 0 { + for _, s := range m.Values { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + func (m *Secret) Size() (n int) { var l int _ = l @@ -13755,6 +13967,19 @@ func (m *ServiceAccountList) Size() (n int) { return n } +func (m *ServiceAccountTokenProjection) Size() (n int) { + var l int + _ = l + l = len(m.Audience) + n += 1 + l + sovGenerated(uint64(l)) + if m.ExpirationSeconds != nil { + n += 1 + sovGenerated(uint64(*m.ExpirationSeconds)) + } + l = len(m.Path) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *ServiceList) Size() (n int) { var l int _ = l @@ -13946,6 +14171,32 @@ func (m *Toleration) Size() (n int) { return n } +func (m *TopologySelectorLabelRequirement) Size() (n int) { + var l int + _ = l + l = len(m.Key) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Values) > 0 { + for _, s := range m.Values { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *TopologySelectorTerm) Size() (n int) { + var l int + _ = l + if len(m.MatchLabelExpressions) > 0 { + for _, e := range m.MatchLabelExpressions { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + func (m *Volume) Size() (n int) { var l int _ = l @@ -14008,6 +14259,10 @@ func (m *VolumeProjection) Size() (n int) { l = m.ConfigMap.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.ServiceAccountToken != nil { + l = m.ServiceAccountToken.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -14326,6 +14581,19 @@ func (this *CephFSVolumeSource) String() string { }, "") return s } +func (this *CinderPersistentVolumeSource) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CinderPersistentVolumeSource{`, + `VolumeID:` + fmt.Sprintf("%v", this.VolumeID) + `,`, + `FSType:` + fmt.Sprintf("%v", this.FSType) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, + `SecretRef:` + strings.Replace(fmt.Sprintf("%v", this.SecretRef), "SecretReference", "SecretReference", 1) + `,`, + `}`, + }, "") + return s +} func (this *CinderVolumeSource) String() string { if this == nil { return "nil" @@ -14334,6 +14602,7 @@ func (this *CinderVolumeSource) String() string { `VolumeID:` + fmt.Sprintf("%v", this.VolumeID) + `,`, `FSType:` + fmt.Sprintf("%v", this.FSType) + `,`, `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, + `SecretRef:` + strings.Replace(fmt.Sprintf("%v", this.SecretRef), "LocalObjectReference", "LocalObjectReference", 1) + `,`, `}`, }, "") return s @@ -14449,6 +14718,20 @@ func (this *ConfigMapList) String() string { }, "") return s } +func (this *ConfigMapNodeConfigSource) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ConfigMapNodeConfigSource{`, + `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `UID:` + fmt.Sprintf("%v", this.UID) + `,`, + `ResourceVersion:` + fmt.Sprintf("%v", this.ResourceVersion) + `,`, + `KubeletConfigKey:` + fmt.Sprintf("%v", this.KubeletConfigKey) + `,`, + `}`, + }, "") + return s +} func (this *ConfigMapProjection) String() string { if this == nil { return "nil" @@ -14605,19 +14888,6 @@ func (this *DaemonEndpoint) String() string { }, "") return s } -func (this *DeleteOptions) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&DeleteOptions{`, - `GracePeriodSeconds:` + valueToStringGenerated(this.GracePeriodSeconds) + `,`, - `Preconditions:` + strings.Replace(fmt.Sprintf("%v", this.Preconditions), "Preconditions", "Preconditions", 1) + `,`, - `OrphanDependents:` + valueToStringGenerated(this.OrphanDependents) + `,`, - `PropagationPolicy:` + valueToStringGenerated(this.PropagationPolicy) + `,`, - `}`, - }, "") - return s -} func (this *DownwardAPIProjection) String() string { if this == nil { return "nil" @@ -15167,21 +15437,6 @@ func (this *List) String() string { }, "") return s } -func (this *ListOptions) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&ListOptions{`, - `LabelSelector:` + fmt.Sprintf("%v", this.LabelSelector) + `,`, - `FieldSelector:` + fmt.Sprintf("%v", this.FieldSelector) + `,`, - `Watch:` + fmt.Sprintf("%v", this.Watch) + `,`, - `ResourceVersion:` + fmt.Sprintf("%v", this.ResourceVersion) + `,`, - `TimeoutSeconds:` + valueToStringGenerated(this.TimeoutSeconds) + `,`, - `IncludeUninitialized:` + fmt.Sprintf("%v", this.IncludeUninitialized) + `,`, - `}`, - }, "") - return s -} func (this *LoadBalancerIngress) String() string { if this == nil { return "nil" @@ -15332,7 +15587,20 @@ func (this *NodeConfigSource) String() string { return "nil" } s := strings.Join([]string{`&NodeConfigSource{`, - `ConfigMapRef:` + strings.Replace(fmt.Sprintf("%v", this.ConfigMapRef), "ObjectReference", "ObjectReference", 1) + `,`, + `ConfigMap:` + strings.Replace(fmt.Sprintf("%v", this.ConfigMap), "ConfigMapNodeConfigSource", "ConfigMapNodeConfigSource", 1) + `,`, + `}`, + }, "") + return s +} +func (this *NodeConfigStatus) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&NodeConfigStatus{`, + `Assigned:` + strings.Replace(fmt.Sprintf("%v", this.Assigned), "NodeConfigSource", "NodeConfigSource", 1) + `,`, + `Active:` + strings.Replace(fmt.Sprintf("%v", this.Active), "NodeConfigSource", "NodeConfigSource", 1) + `,`, + `LastKnownGood:` + strings.Replace(fmt.Sprintf("%v", this.LastKnownGood), "NodeConfigSource", "NodeConfigSource", 1) + `,`, + `Error:` + fmt.Sprintf("%v", this.Error) + `,`, `}`, }, "") return s @@ -15416,6 +15684,7 @@ func (this *NodeSelectorTerm) String() string { } s := strings.Join([]string{`&NodeSelectorTerm{`, `MatchExpressions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchExpressions), "NodeSelectorRequirement", "NodeSelectorRequirement", 1), `&`, ``, 1) + `,`, + `MatchFields:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchFields), "NodeSelectorRequirement", "NodeSelectorRequirement", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -15426,7 +15695,7 @@ func (this *NodeSpec) String() string { } s := strings.Join([]string{`&NodeSpec{`, `PodCIDR:` + fmt.Sprintf("%v", this.PodCIDR) + `,`, - `ExternalID:` + fmt.Sprintf("%v", this.ExternalID) + `,`, + `DoNotUse_ExternalID:` + fmt.Sprintf("%v", this.DoNotUse_ExternalID) + `,`, `ProviderID:` + fmt.Sprintf("%v", this.ProviderID) + `,`, `Unschedulable:` + fmt.Sprintf("%v", this.Unschedulable) + `,`, `Taints:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Taints), "Taint", "Taint", 1), `&`, ``, 1) + `,`, @@ -15470,6 +15739,7 @@ func (this *NodeStatus) String() string { `Images:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Images), "ContainerImage", "ContainerImage", 1), `&`, ``, 1) + `,`, `VolumesInUse:` + fmt.Sprintf("%v", this.VolumesInUse) + `,`, `VolumesAttached:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.VolumesAttached), "AttachedVolume", "AttachedVolume", 1), `&`, ``, 1) + `,`, + `Config:` + strings.Replace(fmt.Sprintf("%v", this.Config), "NodeConfigStatus", "NodeConfigStatus", 1) + `,`, `}`, }, "") return s @@ -15504,51 +15774,6 @@ func (this *ObjectFieldSelector) String() string { }, "") return s } -func (this *ObjectMeta) String() string { - if this == nil { - return "nil" - } - keysForLabels := make([]string, 0, len(this.Labels)) - for k := range this.Labels { - keysForLabels = append(keysForLabels, k) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) - mapStringForLabels := "map[string]string{" - for _, k := range keysForLabels { - mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) - } - mapStringForLabels += "}" - keysForAnnotations := make([]string, 0, len(this.Annotations)) - for k := range this.Annotations { - keysForAnnotations = append(keysForAnnotations, k) - } - github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations) - mapStringForAnnotations := "map[string]string{" - for _, k := range keysForAnnotations { - mapStringForAnnotations += fmt.Sprintf("%v: %v,", k, this.Annotations[k]) - } - mapStringForAnnotations += "}" - s := strings.Join([]string{`&ObjectMeta{`, - `Name:` + fmt.Sprintf("%v", this.Name) + `,`, - `GenerateName:` + fmt.Sprintf("%v", this.GenerateName) + `,`, - `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, - `SelfLink:` + fmt.Sprintf("%v", this.SelfLink) + `,`, - `UID:` + fmt.Sprintf("%v", this.UID) + `,`, - `ResourceVersion:` + fmt.Sprintf("%v", this.ResourceVersion) + `,`, - `Generation:` + fmt.Sprintf("%v", this.Generation) + `,`, - `CreationTimestamp:` + strings.Replace(strings.Replace(this.CreationTimestamp.String(), "Time", "k8s_io_apimachinery_pkg_apis_meta_v1.Time", 1), `&`, ``, 1) + `,`, - `DeletionTimestamp:` + strings.Replace(fmt.Sprintf("%v", this.DeletionTimestamp), "Time", "k8s_io_apimachinery_pkg_apis_meta_v1.Time", 1) + `,`, - `DeletionGracePeriodSeconds:` + valueToStringGenerated(this.DeletionGracePeriodSeconds) + `,`, - `Labels:` + mapStringForLabels + `,`, - `Annotations:` + mapStringForAnnotations + `,`, - `OwnerReferences:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.OwnerReferences), "OwnerReference", "k8s_io_apimachinery_pkg_apis_meta_v1.OwnerReference", 1), `&`, ``, 1) + `,`, - `Finalizers:` + fmt.Sprintf("%v", this.Finalizers) + `,`, - `ClusterName:` + fmt.Sprintf("%v", this.ClusterName) + `,`, - `Initializers:` + strings.Replace(fmt.Sprintf("%v", this.Initializers), "Initializers", "k8s_io_apimachinery_pkg_apis_meta_v1.Initializers", 1) + `,`, - `}`, - }, "") - return s -} func (this *ObjectReference) String() string { if this == nil { return "nil" @@ -15687,7 +15912,7 @@ func (this *PersistentVolumeSource) String() string { `NFS:` + strings.Replace(fmt.Sprintf("%v", this.NFS), "NFSVolumeSource", "NFSVolumeSource", 1) + `,`, `RBD:` + strings.Replace(fmt.Sprintf("%v", this.RBD), "RBDPersistentVolumeSource", "RBDPersistentVolumeSource", 1) + `,`, `ISCSI:` + strings.Replace(fmt.Sprintf("%v", this.ISCSI), "ISCSIPersistentVolumeSource", "ISCSIPersistentVolumeSource", 1) + `,`, - `Cinder:` + strings.Replace(fmt.Sprintf("%v", this.Cinder), "CinderVolumeSource", "CinderVolumeSource", 1) + `,`, + `Cinder:` + strings.Replace(fmt.Sprintf("%v", this.Cinder), "CinderPersistentVolumeSource", "CinderPersistentVolumeSource", 1) + `,`, `CephFS:` + strings.Replace(fmt.Sprintf("%v", this.CephFS), "CephFSPersistentVolumeSource", "CephFSPersistentVolumeSource", 1) + `,`, `FC:` + strings.Replace(fmt.Sprintf("%v", this.FC), "FCVolumeSource", "FCVolumeSource", 1) + `,`, `Flocker:` + strings.Replace(fmt.Sprintf("%v", this.Flocker), "FlockerVolumeSource", "FlockerVolumeSource", 1) + `,`, @@ -15918,6 +16143,16 @@ func (this *PodProxyOptions) String() string { }, "") return s } +func (this *PodReadinessGate) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodReadinessGate{`, + `ConditionType:` + fmt.Sprintf("%v", this.ConditionType) + `,`, + `}`, + }, "") + return s +} func (this *PodSecurityContext) String() string { if this == nil { return "nil" @@ -15929,6 +16164,7 @@ func (this *PodSecurityContext) String() string { `SupplementalGroups:` + fmt.Sprintf("%v", this.SupplementalGroups) + `,`, `FSGroup:` + valueToStringGenerated(this.FSGroup) + `,`, `RunAsGroup:` + valueToStringGenerated(this.RunAsGroup) + `,`, + `Sysctls:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Sysctls), "Sysctl", "Sysctl", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -15985,6 +16221,7 @@ func (this *PodSpec) String() string { `Priority:` + valueToStringGenerated(this.Priority) + `,`, `DNSConfig:` + strings.Replace(fmt.Sprintf("%v", this.DNSConfig), "PodDNSConfig", "PodDNSConfig", 1) + `,`, `ShareProcessNamespace:` + valueToStringGenerated(this.ShareProcessNamespace) + `,`, + `ReadinessGates:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ReadinessGates), "PodReadinessGate", "PodReadinessGate", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -16312,6 +16549,7 @@ func (this *ResourceQuotaSpec) String() string { s := strings.Join([]string{`&ResourceQuotaSpec{`, `Hard:` + mapStringForHard + `,`, `Scopes:` + fmt.Sprintf("%v", this.Scopes) + `,`, + `ScopeSelector:` + strings.Replace(fmt.Sprintf("%v", this.ScopeSelector), "ScopeSelector", "ScopeSelector", 1) + `,`, `}`, }, "") return s @@ -16429,6 +16667,28 @@ func (this *ScaleIOVolumeSource) String() string { }, "") return s } +func (this *ScopeSelector) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ScopeSelector{`, + `MatchExpressions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchExpressions), "ScopedResourceSelectorRequirement", "ScopedResourceSelectorRequirement", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *ScopedResourceSelectorRequirement) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ScopedResourceSelectorRequirement{`, + `ScopeName:` + fmt.Sprintf("%v", this.ScopeName) + `,`, + `Operator:` + fmt.Sprintf("%v", this.Operator) + `,`, + `Values:` + fmt.Sprintf("%v", this.Values) + `,`, + `}`, + }, "") + return s +} func (this *Secret) String() string { if this == nil { return "nil" @@ -16595,6 +16855,18 @@ func (this *ServiceAccountList) String() string { }, "") return s } +func (this *ServiceAccountTokenProjection) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ServiceAccountTokenProjection{`, + `Audience:` + fmt.Sprintf("%v", this.Audience) + `,`, + `ExpirationSeconds:` + valueToStringGenerated(this.ExpirationSeconds) + `,`, + `Path:` + fmt.Sprintf("%v", this.Path) + `,`, + `}`, + }, "") + return s +} func (this *ServiceList) String() string { if this == nil { return "nil" @@ -16759,6 +17031,27 @@ func (this *Toleration) String() string { }, "") return s } +func (this *TopologySelectorLabelRequirement) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&TopologySelectorLabelRequirement{`, + `Key:` + fmt.Sprintf("%v", this.Key) + `,`, + `Values:` + fmt.Sprintf("%v", this.Values) + `,`, + `}`, + }, "") + return s +} +func (this *TopologySelectorTerm) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&TopologySelectorTerm{`, + `MatchLabelExpressions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.MatchLabelExpressions), "TopologySelectorLabelRequirement", "TopologySelectorLabelRequirement", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} func (this *Volume) String() string { if this == nil { return "nil" @@ -16813,6 +17106,7 @@ func (this *VolumeProjection) String() string { `Secret:` + strings.Replace(fmt.Sprintf("%v", this.Secret), "SecretProjection", "SecretProjection", 1) + `,`, `DownwardAPI:` + strings.Replace(fmt.Sprintf("%v", this.DownwardAPI), "DownwardAPIProjection", "DownwardAPIProjection", 1) + `,`, `ConfigMap:` + strings.Replace(fmt.Sprintf("%v", this.ConfigMap), "ConfigMapProjection", "ConfigMapProjection", 1) + `,`, + `ServiceAccountToken:` + strings.Replace(fmt.Sprintf("%v", this.ServiceAccountToken), "ServiceAccountTokenProjection", "ServiceAccountTokenProjection", 1) + `,`, `}`, }, "") return s @@ -18903,7 +19197,7 @@ func (m *CephFSVolumeSource) Unmarshal(dAtA []byte) error { } return nil } -func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { +func (m *CinderPersistentVolumeSource) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -18926,10 +19220,10 @@ func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CinderVolumeSource: wiretype end group for non-group") + return fmt.Errorf("proto: CinderPersistentVolumeSource: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CinderVolumeSource: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CinderPersistentVolumeSource: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -19010,61 +19304,11 @@ func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { } } m.ReadOnly = bool(v != 0) - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ClientIPConfig) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ClientIPConfig: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientIPConfig: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TimeoutSeconds", wireType) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecretRef", wireType) } - var v int32 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -19074,12 +19318,256 @@ func (m *ClientIPConfig) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int32(b) & 0x7F) << shift + msglen |= (int(b) & 0x7F) << shift if b < 0x80 { break } } - m.TimeoutSeconds = &v + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SecretRef == nil { + m.SecretRef = &SecretReference{} + } + if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CinderVolumeSource: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CinderVolumeSource: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VolumeID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VolumeID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FSType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FSType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecretRef", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SecretRef == nil { + m.SecretRef = &LocalObjectReference{} + } + if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ClientIPConfig) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClientIPConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClientIPConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeoutSeconds", wireType) + } + var v int32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.TimeoutSeconds = &v default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -20144,7 +20632,7 @@ func (m *ConfigMapList) Unmarshal(dAtA []byte) error { } return nil } -func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { +func (m *ConfigMapNodeConfigSource) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -20167,17 +20655,17 @@ func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ConfigMapProjection: wiretype end group for non-group") + return fmt.Errorf("proto: ConfigMapNodeConfigSource: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ConfigMapProjection: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ConfigMapNodeConfigSource: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LocalObjectReference", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -20187,27 +20675,26 @@ func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.LocalObjectReference.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Namespace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -20217,28 +20704,55 @@ func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - m.Items = append(m.Items, KeyToPath{}) - if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UID = k8s_io_apimachinery_pkg_types.UID(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Optional", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceVersion", wireType) } - var v int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -20248,13 +20762,182 @@ func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - b := bool(v != 0) - m.Optional = &b + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ResourceVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field KubeletConfigKey", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.KubeletConfigKey = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ConfigMapProjection) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConfigMapProjection: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConfigMapProjection: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalObjectReference", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LocalObjectReference.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, KeyToPath{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Optional", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.Optional = &b default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -22266,160 +22949,6 @@ func (m *DaemonEndpoint) Unmarshal(dAtA []byte) error { } return nil } -func (m *DeleteOptions) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: DeleteOptions: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteOptions: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field GracePeriodSeconds", wireType) - } - var v int64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.GracePeriodSeconds = &v - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Preconditions", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Preconditions == nil { - m.Preconditions = &Preconditions{} - } - if err := m.Preconditions.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OrphanDependents", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - b := bool(v != 0) - m.OrphanDependents = &b - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PropagationPolicy", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - s := DeletionPropagation(dAtA[iNdEx:postIndex]) - m.PropagationPolicy = &s - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *DownwardAPIProjection) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -28863,203 +29392,6 @@ func (m *List) Unmarshal(dAtA []byte) error { } return nil } -func (m *ListOptions) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ListOptions: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ListOptions: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LabelSelector", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.LabelSelector = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field FieldSelector", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.FieldSelector = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Watch", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.Watch = bool(v != 0) - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ResourceVersion", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ResourceVersion = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TimeoutSeconds", wireType) - } - var v int64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.TimeoutSeconds = &v - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IncludeUninitialized", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.IncludeUninitialized = bool(v != 0) - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *LoadBalancerIngress) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -30561,9 +30893,9 @@ func (m *NodeConfigSource) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: NodeConfigSource: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConfigMapRef", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ConfigMap", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -30587,10 +30919,10 @@ func (m *NodeConfigSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.ConfigMapRef == nil { - m.ConfigMapRef = &ObjectReference{} + if m.ConfigMap == nil { + m.ConfigMap = &ConfigMapNodeConfigSource{} } - if err := m.ConfigMapRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.ConfigMap.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -30615,7 +30947,7 @@ func (m *NodeConfigSource) Unmarshal(dAtA []byte) error { } return nil } -func (m *NodeDaemonEndpoints) Unmarshal(dAtA []byte) error { +func (m *NodeConfigStatus) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -30638,15 +30970,15 @@ func (m *NodeDaemonEndpoints) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: NodeDaemonEndpoints: wiretype end group for non-group") + return fmt.Errorf("proto: NodeConfigStatus: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: NodeDaemonEndpoints: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: NodeConfigStatus: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field KubeletEndpoint", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Assigned", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -30670,63 +31002,16 @@ func (m *NodeDaemonEndpoints) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.KubeletEndpoint.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + if m.Assigned == nil { + m.Assigned = &NodeConfigSource{} } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { + if err := m.Assigned.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *NodeList) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: NodeList: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: NodeList: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + iNdEx = postIndex + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Active", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -30750,13 +31035,238 @@ func (m *NodeList) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if m.Active == nil { + m.Active = &NodeConfigSource{} + } + if err := m.Active.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 2: + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field LastKnownGood", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LastKnownGood == nil { + m.LastKnownGood = &NodeConfigSource{} + } + if err := m.LastKnownGood.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NodeDaemonEndpoints) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NodeDaemonEndpoints: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NodeDaemonEndpoints: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field KubeletEndpoint", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.KubeletEndpoint.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NodeList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NodeList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NodeList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -31334,6 +31844,37 @@ func (m *NodeSelectorTerm) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchFields", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MatchFields = append(m.MatchFields, NodeSelectorRequirement{}) + if err := m.MatchFields[len(m.MatchFields)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -31415,7 +31956,7 @@ func (m *NodeSpec) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ExternalID", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DoNotUse_ExternalID", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -31440,7 +31981,7 @@ func (m *NodeSpec) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ExternalID = string(dAtA[iNdEx:postIndex]) + m.DoNotUse_ExternalID = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { @@ -32089,6 +32630,39 @@ func (m *NodeStatus) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Config", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Config == nil { + m.Config = &NodeConfigStatus{} + } + if err := m.Config.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -32558,686 +33132,6 @@ func (m *ObjectFieldSelector) Unmarshal(dAtA []byte) error { } return nil } -func (m *ObjectMeta) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ObjectMeta: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ObjectMeta: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field GenerateName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.GenerateName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Namespace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SelfLink", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SelfLink = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UID", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.UID = k8s_io_apimachinery_pkg_types.UID(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ResourceVersion", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ResourceVersion = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 7: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Generation", wireType) - } - m.Generation = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Generation |= (int64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CreationTimestamp", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.CreationTimestamp.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DeletionTimestamp", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.DeletionTimestamp == nil { - m.DeletionTimestamp = &k8s_io_apimachinery_pkg_apis_meta_v1.Time{} - } - if err := m.DeletionTimestamp.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 10: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DeletionGracePeriodSeconds", wireType) - } - var v int64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.DeletionGracePeriodSeconds = &v - case 11: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - if m.Labels == nil { - m.Labels = make(map[string]string) - } - if iNdEx < postIndex { - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Labels[mapkey] = mapvalue - } else { - var mapvalue string - m.Labels[mapkey] = mapvalue - } - iNdEx = postIndex - case 12: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - if m.Annotations == nil { - m.Annotations = make(map[string]string) - } - if iNdEx < postIndex { - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Annotations[mapkey] = mapvalue - } else { - var mapvalue string - m.Annotations[mapkey] = mapvalue - } - iNdEx = postIndex - case 13: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OwnerReferences", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.OwnerReferences = append(m.OwnerReferences, k8s_io_apimachinery_pkg_apis_meta_v1.OwnerReference{}) - if err := m.OwnerReferences[len(m.OwnerReferences)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 14: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Finalizers", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Finalizers = append(m.Finalizers, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 15: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClusterName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ClusterName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 16: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Initializers", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Initializers == nil { - m.Initializers = &k8s_io_apimachinery_pkg_apis_meta_v1.Initializers{} - } - if err := m.Initializers.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *ObjectReference) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -35096,7 +34990,7 @@ func (m *PersistentVolumeSource) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Cinder == nil { - m.Cinder = &CinderVolumeSource{} + m.Cinder = &CinderPersistentVolumeSource{} } if err := m.Cinder.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -38103,6 +37997,85 @@ func (m *PodProxyOptions) Unmarshal(dAtA []byte) error { } return nil } +func (m *PodReadinessGate) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodReadinessGate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodReadinessGate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConditionType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConditionType = PodConditionType(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *PodSecurityContext) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -38308,6 +38281,37 @@ func (m *PodSecurityContext) Unmarshal(dAtA []byte) error { } } m.RunAsGroup = &v + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sysctls", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sysctls = append(m.Sysctls, Sysctl{}) + if err := m.Sysctls[len(m.Sysctls)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -38955,13 +38959,247 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Hostname = string(dAtA[iNdEx:postIndex]) + m.Hostname = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subdomain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Subdomain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 18: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Affinity", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Affinity == nil { + m.Affinity = &Affinity{} + } + if err := m.Affinity.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SchedulerName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SchedulerName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitContainers", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.InitContainers = append(m.InitContainers, Container{}) + if err := m.InitContainers[len(m.InitContainers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 21: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AutomountServiceAccountToken", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.AutomountServiceAccountToken = &b + case 22: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tolerations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tolerations = append(m.Tolerations, Toleration{}) + if err := m.Tolerations[len(m.Tolerations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 23: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostAliases", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostAliases = append(m.HostAliases, HostAlias{}) + if err := m.HostAliases[len(m.HostAliases)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 24: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PriorityClassName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PriorityClassName = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 17: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Subdomain", wireType) + case 25: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) } - var stringLen uint64 + var v int32 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -38971,24 +39209,15 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift + v |= (int32(b) & 0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Subdomain = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 18: + m.Priority = &v + case 26: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Affinity", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DNSConfig", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -39012,76 +39241,16 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Affinity == nil { - m.Affinity = &Affinity{} - } - if err := m.Affinity.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 19: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SchedulerName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SchedulerName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 20: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field InitContainers", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF + if m.DNSConfig == nil { + m.DNSConfig = &PodDNSConfig{} } - m.InitContainers = append(m.InitContainers, Container{}) - if err := m.InitContainers[len(m.InitContainers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.DNSConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 21: + case 27: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AutomountServiceAccountToken", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ShareProcessNamespace", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -39099,121 +39268,10 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { } } b := bool(v != 0) - m.AutomountServiceAccountToken = &b - case 22: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tolerations", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Tolerations = append(m.Tolerations, Toleration{}) - if err := m.Tolerations[len(m.Tolerations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 23: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HostAliases", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.HostAliases = append(m.HostAliases, HostAlias{}) - if err := m.HostAliases[len(m.HostAliases)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 24: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PriorityClassName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.PriorityClassName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 25: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) - } - var v int32 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.Priority = &v - case 26: + m.ShareProcessNamespace = &b + case 28: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DNSConfig", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ReadinessGates", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -39237,34 +39295,11 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.DNSConfig == nil { - m.DNSConfig = &PodDNSConfig{} - } - if err := m.DNSConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.ReadinessGates = append(m.ReadinessGates, PodReadinessGate{}) + if err := m.ReadinessGates[len(m.ReadinessGates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 27: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ShareProcessNamespace", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - b := bool(v != 0) - m.ShareProcessNamespace = &b default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -43166,6 +43201,39 @@ func (m *ResourceQuotaSpec) Unmarshal(dAtA []byte) error { } m.Scopes = append(m.Scopes, ResourceQuotaScope(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ScopeSelector", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ScopeSelector == nil { + m.ScopeSelector = &ScopeSelector{} + } + if err := m.ScopeSelector.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -44376,94 +44444,332 @@ func (m *ScaleIOVolumeSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.SecretRef == nil { - m.SecretRef = &LocalObjectReference{} - } - if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if m.SecretRef == nil { + m.SecretRef = &LocalObjectReference{} + } + if err := m.SecretRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SSLEnabled", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.SSLEnabled = bool(v != 0) + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProtectionDomain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProtectionDomain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StoragePool", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StoragePool = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StorageMode", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StorageMode = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VolumeName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VolumeName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FSType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FSType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ScopeSelector) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ScopeSelector: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ScopeSelector: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchExpressions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MatchExpressions = append(m.MatchExpressions, ScopedResourceSelectorRequirement{}) + if err := m.MatchExpressions[len(m.MatchExpressions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field SSLEnabled", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.SSLEnabled = bool(v != 0) - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProtectionDomain", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err } - intStringLen := int(stringLen) - if intStringLen < 0 { + if skippy < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + intStringLen - if postIndex > l { + if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } - m.ProtectionDomain = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field StoragePool", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ScopedResourceSelectorRequirement) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated } - postIndex := iNdEx + intStringLen - if postIndex > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - m.StoragePool = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 7: + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ScopedResourceSelectorRequirement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ScopedResourceSelectorRequirement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field StorageMode", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ScopeName", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -44488,11 +44794,11 @@ func (m *ScaleIOVolumeSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.StorageMode = string(dAtA[iNdEx:postIndex]) + m.ScopeName = ResourceQuotaScope(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 8: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field VolumeName", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Operator", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -44517,11 +44823,11 @@ func (m *ScaleIOVolumeSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.VolumeName = string(dAtA[iNdEx:postIndex]) + m.Operator = ScopeSelectorOperator(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 9: + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field FSType", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Values", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -44546,28 +44852,8 @@ func (m *ScaleIOVolumeSource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.FSType = string(dAtA[iNdEx:postIndex]) + m.Values = append(m.Values, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 10: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.ReadOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -46310,17 +46596,128 @@ func (m *ServiceAccountList) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ServiceAccountList: wiretype end group for non-group") + return fmt.Errorf("proto: ServiceAccountList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ServiceAccountList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, ServiceAccount{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ServiceAccountTokenProjection) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ServiceAccountTokenProjection: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ServiceAccountList: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ServiceAccountTokenProjection: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Audience", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -46330,27 +46727,46 @@ func (m *ServiceAccountList) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Audience = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpirationSeconds", wireType) + } + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ExpirationSeconds = &v + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -46360,22 +46776,20 @@ func (m *ServiceAccountList) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - m.Items = append(m.Items, ServiceAccount{}) - if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Path = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -48381,6 +48795,195 @@ func (m *Toleration) Unmarshal(dAtA []byte) error { } return nil } +func (m *TopologySelectorLabelRequirement) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TopologySelectorLabelRequirement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TopologySelectorLabelRequirement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Values", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Values = append(m.Values, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TopologySelectorTerm) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TopologySelectorTerm: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TopologySelectorTerm: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MatchLabelExpressions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MatchLabelExpressions = append(m.MatchLabelExpressions, TopologySelectorLabelRequirement{}) + if err := m.MatchLabelExpressions[len(m.MatchLabelExpressions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Volume) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -48996,6 +49599,39 @@ func (m *VolumeProjection) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ServiceAccountToken", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ServiceAccountToken == nil { + m.ServiceAccountToken = &ServiceAccountTokenProjection{} + } + if err := m.ServiceAccountToken.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -50333,797 +50969,797 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 12666 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x70, 0x24, 0x49, - 0x56, 0xd8, 0x55, 0xb7, 0xbe, 0xfa, 0xe9, 0x3b, 0x67, 0x66, 0x57, 0xa3, 0xdd, 0x9d, 0x9e, 0xad, - 0xbd, 0x9b, 0x9b, 0xfd, 0x92, 0x6e, 0x67, 0x77, 0x6f, 0x97, 0xdb, 0xbb, 0x05, 0x49, 0x2d, 0xcd, - 0xf4, 0xce, 0x48, 0xd3, 0x9b, 0xad, 0x99, 0xb9, 0x5b, 0x96, 0xf3, 0x95, 0xba, 0x53, 0xad, 0x5a, - 0x95, 0xaa, 0x7a, 0xab, 0xaa, 0x35, 0xa3, 0x0d, 0x88, 0xb0, 0x8f, 0x0f, 0x1b, 0xc3, 0x8f, 0x0b, - 0x43, 0xd8, 0x18, 0x08, 0x1c, 0x61, 0xe3, 0x80, 0x33, 0xb6, 0x23, 0x30, 0x18, 0xf0, 0x81, 0x6d, - 0x8c, 0xfd, 0x03, 0xfe, 0x60, 0xf0, 0x9f, 0x23, 0x82, 0xb0, 0x0c, 0x82, 0xb0, 0x83, 0x1f, 0x76, - 0x38, 0x4c, 0x84, 0x23, 0x90, 0xb1, 0x71, 0xe4, 0x67, 0x65, 0x56, 0x57, 0x75, 0xb7, 0x66, 0x35, - 0xda, 0x85, 0xb8, 0x7f, 0xdd, 0xf9, 0x5e, 0xbe, 0xcc, 0xca, 0x8f, 0x97, 0x2f, 0x5f, 0xbe, 0x0f, - 0x78, 0x63, 0xf7, 0xf5, 0x68, 0xc1, 0x0d, 0x16, 0x77, 0x3b, 0x5b, 0x24, 0xf4, 0x49, 0x4c, 0xa2, - 0xc5, 0x7d, 0xe2, 0x37, 0x83, 0x70, 0x51, 0x00, 0x9c, 0xb6, 0xbb, 0xd8, 0x08, 0x42, 0xb2, 0xb8, - 0xff, 0xd2, 0x62, 0x8b, 0xf8, 0x24, 0x74, 0x62, 0xd2, 0x5c, 0x68, 0x87, 0x41, 0x1c, 0x20, 0xc4, - 0x71, 0x16, 0x9c, 0xb6, 0xbb, 0x40, 0x71, 0x16, 0xf6, 0x5f, 0x9a, 0x7f, 0xb1, 0xe5, 0xc6, 0x3b, - 0x9d, 0xad, 0x85, 0x46, 0xb0, 0xb7, 0xd8, 0x0a, 0x5a, 0xc1, 0x22, 0x43, 0xdd, 0xea, 0x6c, 0xb3, - 0x7f, 0xec, 0x0f, 0xfb, 0xc5, 0x49, 0xcc, 0xaf, 0x27, 0xcd, 0x90, 0x07, 0x31, 0xf1, 0x23, 0x37, - 0xf0, 0xa3, 0x17, 0x9d, 0xb6, 0x1b, 0x91, 0x70, 0x9f, 0x84, 0x8b, 0xed, 0xdd, 0x16, 0x85, 0x45, - 0x26, 0xc2, 0xe2, 0xfe, 0x4b, 0x5b, 0x24, 0x76, 0xba, 0x7a, 0x34, 0xff, 0x4a, 0x42, 0x6e, 0xcf, - 0x69, 0xec, 0xb8, 0x3e, 0x09, 0x0f, 0x24, 0x8d, 0xc5, 0x90, 0x44, 0x41, 0x27, 0x6c, 0x90, 0x13, - 0xd5, 0x8a, 0x16, 0xf7, 0x48, 0xec, 0x64, 0x7c, 0xfd, 0xfc, 0x62, 0x5e, 0xad, 0xb0, 0xe3, 0xc7, - 0xee, 0x5e, 0x77, 0x33, 0x9f, 0xed, 0x57, 0x21, 0x6a, 0xec, 0x90, 0x3d, 0xa7, 0xab, 0xde, 0xcb, - 0x79, 0xf5, 0x3a, 0xb1, 0xeb, 0x2d, 0xba, 0x7e, 0x1c, 0xc5, 0x61, 0xba, 0x92, 0xfd, 0x4d, 0x0b, - 0x2e, 0x2f, 0xdd, 0xab, 0xaf, 0x7a, 0x4e, 0x14, 0xbb, 0x8d, 0x65, 0x2f, 0x68, 0xec, 0xd6, 0xe3, - 0x20, 0x24, 0x77, 0x03, 0xaf, 0xb3, 0x47, 0xea, 0x6c, 0x20, 0xd0, 0x0b, 0x30, 0xb6, 0xcf, 0xfe, - 0x57, 0x2b, 0x73, 0xd6, 0x65, 0xeb, 0x6a, 0x69, 0x79, 0xe6, 0x37, 0x0f, 0xcb, 0x9f, 0x38, 0x3a, - 0x2c, 0x8f, 0xdd, 0x15, 0xe5, 0x58, 0x61, 0xa0, 0x2b, 0x30, 0xb2, 0x1d, 0x6d, 0x1e, 0xb4, 0xc9, - 0x5c, 0x81, 0xe1, 0x4e, 0x09, 0xdc, 0x91, 0xb5, 0x3a, 0x2d, 0xc5, 0x02, 0x8a, 0x16, 0xa1, 0xd4, - 0x76, 0xc2, 0xd8, 0x8d, 0xdd, 0xc0, 0x9f, 0x2b, 0x5e, 0xb6, 0xae, 0x0e, 0x2f, 0xcf, 0x0a, 0xd4, - 0x52, 0x4d, 0x02, 0x70, 0x82, 0x43, 0xbb, 0x11, 0x12, 0xa7, 0x79, 0xdb, 0xf7, 0x0e, 0xe6, 0x86, - 0x2e, 0x5b, 0x57, 0xc7, 0x92, 0x6e, 0x60, 0x51, 0x8e, 0x15, 0x86, 0xfd, 0xe3, 0x05, 0x18, 0x5b, - 0xda, 0xde, 0x76, 0x7d, 0x37, 0x3e, 0x40, 0x77, 0x61, 0xc2, 0x0f, 0x9a, 0x44, 0xfe, 0x67, 0x5f, - 0x31, 0x7e, 0xed, 0xf2, 0x42, 0xf7, 0xca, 0x5c, 0xd8, 0xd0, 0xf0, 0x96, 0x67, 0x8e, 0x0e, 0xcb, - 0x13, 0x7a, 0x09, 0x36, 0xe8, 0x20, 0x0c, 0xe3, 0xed, 0xa0, 0xa9, 0xc8, 0x16, 0x18, 0xd9, 0x72, - 0x16, 0xd9, 0x5a, 0x82, 0xb6, 0x3c, 0x7d, 0x74, 0x58, 0x1e, 0xd7, 0x0a, 0xb0, 0x4e, 0x04, 0x6d, - 0xc1, 0x34, 0xfd, 0xeb, 0xc7, 0xae, 0xa2, 0x5b, 0x64, 0x74, 0x9f, 0xc9, 0xa3, 0xab, 0xa1, 0x2e, - 0x9f, 0x3b, 0x3a, 0x2c, 0x4f, 0xa7, 0x0a, 0x71, 0x9a, 0xa0, 0xfd, 0x01, 0x4c, 0x2d, 0xc5, 0xb1, - 0xd3, 0xd8, 0x21, 0x4d, 0x3e, 0x83, 0xe8, 0x15, 0x18, 0xf2, 0x9d, 0x3d, 0x22, 0xe6, 0xf7, 0xb2, - 0x18, 0xd8, 0xa1, 0x0d, 0x67, 0x8f, 0x1c, 0x1f, 0x96, 0x67, 0xee, 0xf8, 0xee, 0xfb, 0x1d, 0xb1, - 0x2a, 0x68, 0x19, 0x66, 0xd8, 0xe8, 0x1a, 0x40, 0x93, 0xec, 0xbb, 0x0d, 0x52, 0x73, 0xe2, 0x1d, - 0x31, 0xdf, 0x48, 0xd4, 0x85, 0x8a, 0x82, 0x60, 0x0d, 0xcb, 0x7e, 0x00, 0xa5, 0xa5, 0xfd, 0xc0, - 0x6d, 0xd6, 0x82, 0x66, 0x84, 0x76, 0x61, 0xba, 0x1d, 0x92, 0x6d, 0x12, 0xaa, 0xa2, 0x39, 0xeb, - 0x72, 0xf1, 0xea, 0xf8, 0xb5, 0xab, 0x99, 0x1f, 0x6b, 0xa2, 0xae, 0xfa, 0x71, 0x78, 0xb0, 0xfc, - 0xb8, 0x68, 0x6f, 0x3a, 0x05, 0xc5, 0x69, 0xca, 0xf6, 0x7f, 0x28, 0xc0, 0x85, 0xa5, 0x0f, 0x3a, - 0x21, 0xa9, 0xb8, 0xd1, 0x6e, 0x7a, 0x85, 0x37, 0xdd, 0x68, 0x77, 0x23, 0x19, 0x01, 0xb5, 0xb4, - 0x2a, 0xa2, 0x1c, 0x2b, 0x0c, 0xf4, 0x22, 0x8c, 0xd2, 0xdf, 0x77, 0x70, 0x55, 0x7c, 0xf2, 0x39, - 0x81, 0x3c, 0x5e, 0x71, 0x62, 0xa7, 0xc2, 0x41, 0x58, 0xe2, 0xa0, 0x75, 0x18, 0x6f, 0xb0, 0x0d, - 0xd9, 0x5a, 0x0f, 0x9a, 0x84, 0x4d, 0x66, 0x69, 0xf9, 0x79, 0x8a, 0xbe, 0x92, 0x14, 0x1f, 0x1f, - 0x96, 0xe7, 0x78, 0xdf, 0x04, 0x09, 0x0d, 0x86, 0xf5, 0xfa, 0xc8, 0x56, 0xfb, 0x6b, 0x88, 0x51, - 0x82, 0x8c, 0xbd, 0x75, 0x55, 0xdb, 0x2a, 0xc3, 0x6c, 0xab, 0x4c, 0x64, 0x6f, 0x13, 0xf4, 0x12, - 0x0c, 0xed, 0xba, 0x7e, 0x73, 0x6e, 0x84, 0xd1, 0x7a, 0x8a, 0xce, 0xf9, 0x4d, 0xd7, 0x6f, 0x1e, - 0x1f, 0x96, 0x67, 0x8d, 0xee, 0xd0, 0x42, 0xcc, 0x50, 0xed, 0x3f, 0xb5, 0xa0, 0xcc, 0x60, 0x6b, - 0xae, 0x47, 0x6a, 0x24, 0x8c, 0xdc, 0x28, 0x26, 0x7e, 0x6c, 0x0c, 0xe8, 0x35, 0x80, 0x88, 0x34, - 0x42, 0x12, 0x6b, 0x43, 0xaa, 0x16, 0x46, 0x5d, 0x41, 0xb0, 0x86, 0x45, 0x19, 0x42, 0xb4, 0xe3, - 0x84, 0x6c, 0x7d, 0x89, 0x81, 0x55, 0x0c, 0xa1, 0x2e, 0x01, 0x38, 0xc1, 0x31, 0x18, 0x42, 0xb1, - 0x1f, 0x43, 0x40, 0x5f, 0x80, 0xe9, 0xa4, 0xb1, 0xa8, 0xed, 0x34, 0xe4, 0x00, 0xb2, 0x2d, 0x53, - 0x37, 0x41, 0x38, 0x8d, 0x6b, 0xff, 0x13, 0x4b, 0x2c, 0x1e, 0xfa, 0xd5, 0x1f, 0xf3, 0x6f, 0xb5, - 0x7f, 0xc5, 0x82, 0xd1, 0x65, 0xd7, 0x6f, 0xba, 0x7e, 0x0b, 0x7d, 0x05, 0xc6, 0xe8, 0xd9, 0xd4, - 0x74, 0x62, 0x47, 0xf0, 0xbd, 0xcf, 0x68, 0x7b, 0x4b, 0x1d, 0x15, 0x0b, 0xed, 0xdd, 0x16, 0x2d, - 0x88, 0x16, 0x28, 0x36, 0xdd, 0x6d, 0xb7, 0xb7, 0xde, 0x23, 0x8d, 0x78, 0x9d, 0xc4, 0x4e, 0xf2, - 0x39, 0x49, 0x19, 0x56, 0x54, 0xd1, 0x4d, 0x18, 0x89, 0x9d, 0xb0, 0x45, 0x62, 0xc1, 0x00, 0x33, - 0x19, 0x15, 0xaf, 0x89, 0xe9, 0x8e, 0x24, 0x7e, 0x83, 0x24, 0xc7, 0xc2, 0x26, 0xab, 0x8a, 0x05, - 0x09, 0xfb, 0x6f, 0x8f, 0xc0, 0xc5, 0x95, 0x7a, 0x35, 0x67, 0x5d, 0x5d, 0x81, 0x91, 0x66, 0xe8, - 0xee, 0x93, 0x50, 0x8c, 0xb3, 0xa2, 0x52, 0x61, 0xa5, 0x58, 0x40, 0xd1, 0xeb, 0x30, 0xc1, 0x0f, - 0xa4, 0x1b, 0x8e, 0xdf, 0xf4, 0xe4, 0x10, 0x9f, 0x17, 0xd8, 0x13, 0x77, 0x35, 0x18, 0x36, 0x30, - 0x4f, 0xb8, 0xa8, 0xae, 0xa4, 0x36, 0x63, 0xde, 0x61, 0xf7, 0x83, 0x16, 0xcc, 0xf0, 0x66, 0x96, - 0xe2, 0x38, 0x74, 0xb7, 0x3a, 0x31, 0x89, 0xe6, 0x86, 0x19, 0xa7, 0x5b, 0xc9, 0x1a, 0xad, 0xdc, - 0x11, 0x58, 0xb8, 0x9b, 0xa2, 0xc2, 0x99, 0xe0, 0x9c, 0x68, 0x77, 0x26, 0x0d, 0xc6, 0x5d, 0xcd, - 0xa2, 0xef, 0xb5, 0x60, 0xbe, 0x11, 0xf8, 0x71, 0x18, 0x78, 0x1e, 0x09, 0x6b, 0x9d, 0x2d, 0xcf, - 0x8d, 0x76, 0xf8, 0x3a, 0xc5, 0x64, 0x9b, 0x71, 0x82, 0x9c, 0x39, 0x54, 0x48, 0x62, 0x0e, 0x2f, - 0x1d, 0x1d, 0x96, 0xe7, 0x57, 0x72, 0x49, 0xe1, 0x1e, 0xcd, 0xa0, 0x5d, 0x40, 0xf4, 0x28, 0xad, - 0xc7, 0x4e, 0x8b, 0x24, 0x8d, 0x8f, 0x0e, 0xde, 0xf8, 0x63, 0x47, 0x87, 0x65, 0xb4, 0xd1, 0x45, - 0x02, 0x67, 0x90, 0x45, 0xef, 0xc3, 0x79, 0x5a, 0xda, 0xf5, 0xad, 0x63, 0x83, 0x37, 0x37, 0x77, - 0x74, 0x58, 0x3e, 0xbf, 0x91, 0x41, 0x04, 0x67, 0x92, 0x9e, 0x5f, 0x81, 0x0b, 0x99, 0x53, 0x85, - 0x66, 0xa0, 0xb8, 0x4b, 0xb8, 0x08, 0x52, 0xc2, 0xf4, 0x27, 0x3a, 0x0f, 0xc3, 0xfb, 0x8e, 0xd7, - 0x11, 0xab, 0x14, 0xf3, 0x3f, 0x9f, 0x2b, 0xbc, 0x6e, 0xd9, 0x0d, 0x98, 0x58, 0x71, 0xda, 0xce, - 0x96, 0xeb, 0xb9, 0xb1, 0x4b, 0x22, 0xf4, 0x69, 0x28, 0x3a, 0xcd, 0x26, 0x3b, 0x22, 0x4b, 0xcb, - 0x17, 0x8e, 0x0e, 0xcb, 0xc5, 0xa5, 0x26, 0xe5, 0xd5, 0xa0, 0xb0, 0x0e, 0x30, 0xc5, 0x40, 0xcf, - 0xc1, 0x50, 0x33, 0x0c, 0xda, 0x73, 0x05, 0x86, 0x49, 0x87, 0x6a, 0xa8, 0x12, 0x06, 0xed, 0x14, - 0x2a, 0xc3, 0xb1, 0x7f, 0xbd, 0x00, 0x4f, 0xae, 0x90, 0xf6, 0xce, 0x5a, 0x3d, 0x67, 0xd3, 0x5d, - 0x85, 0xb1, 0xbd, 0xc0, 0x77, 0xe3, 0x20, 0x8c, 0x44, 0xd3, 0xec, 0x34, 0x59, 0x17, 0x65, 0x58, - 0x41, 0xd1, 0x65, 0x18, 0x6a, 0x27, 0x92, 0xc0, 0x84, 0x94, 0x22, 0x98, 0x0c, 0xc0, 0x20, 0x14, - 0xa3, 0x13, 0x91, 0x50, 0x9c, 0x82, 0x0a, 0xe3, 0x4e, 0x44, 0x42, 0xcc, 0x20, 0x09, 0x3b, 0xa5, - 0x8c, 0x56, 0x6c, 0xab, 0x14, 0x3b, 0xa5, 0x10, 0xac, 0x61, 0xa1, 0x1a, 0x94, 0x22, 0x35, 0xa9, - 0xc3, 0x83, 0x4f, 0xea, 0x24, 0xe3, 0xb7, 0x6a, 0x26, 0x13, 0x22, 0x06, 0x1b, 0x18, 0xe9, 0xcb, - 0x6f, 0x7f, 0xb5, 0x00, 0x88, 0x0f, 0xe1, 0x5f, 0xb2, 0x81, 0xbb, 0xd3, 0x3d, 0x70, 0x99, 0x92, - 0xd7, 0xad, 0xa0, 0xe1, 0x78, 0x69, 0x16, 0x7e, 0x5a, 0xa3, 0xf7, 0x63, 0x16, 0xa0, 0x15, 0xd7, - 0x6f, 0x92, 0xf0, 0x0c, 0xae, 0x1d, 0x27, 0x3b, 0x48, 0x6f, 0xc1, 0xd4, 0x8a, 0xe7, 0x12, 0x3f, - 0xae, 0xd6, 0x56, 0x02, 0x7f, 0xdb, 0x6d, 0xa1, 0xcf, 0xc1, 0x14, 0xbd, 0x85, 0x05, 0x9d, 0xb8, - 0x4e, 0x1a, 0x81, 0xcf, 0x04, 0x56, 0x7a, 0x77, 0x41, 0x47, 0x87, 0xe5, 0xa9, 0x4d, 0x03, 0x82, - 0x53, 0x98, 0xf6, 0xef, 0xd3, 0x0f, 0x0d, 0xf6, 0xda, 0x81, 0x4f, 0xfc, 0x78, 0x25, 0xf0, 0x9b, - 0xfc, 0x62, 0xf3, 0x39, 0x18, 0x8a, 0x69, 0xc7, 0xf9, 0x47, 0x5e, 0x91, 0x53, 0x4b, 0xbb, 0x7b, - 0x7c, 0x58, 0x7e, 0xac, 0xbb, 0x06, 0xfb, 0x20, 0x56, 0x07, 0x7d, 0x1b, 0x8c, 0x44, 0xb1, 0x13, - 0x77, 0x22, 0xf1, 0xd9, 0x4f, 0xcb, 0xcf, 0xae, 0xb3, 0xd2, 0xe3, 0xc3, 0xf2, 0xb4, 0xaa, 0xc6, - 0x8b, 0xb0, 0xa8, 0x80, 0x9e, 0x85, 0xd1, 0x3d, 0x12, 0x45, 0x4e, 0x4b, 0xca, 0xa4, 0xd3, 0xa2, - 0xee, 0xe8, 0x3a, 0x2f, 0xc6, 0x12, 0x8e, 0x9e, 0x81, 0x61, 0x12, 0x86, 0x41, 0x28, 0x56, 0xd5, - 0xa4, 0x40, 0x1c, 0x5e, 0xa5, 0x85, 0x98, 0xc3, 0xec, 0xff, 0x68, 0xc1, 0xb4, 0xea, 0x2b, 0x6f, - 0xeb, 0x0c, 0x84, 0x8f, 0x77, 0x00, 0x1a, 0xf2, 0x03, 0x23, 0xc6, 0xef, 0xc6, 0xaf, 0x5d, 0xc9, - 0x3c, 0x52, 0xbb, 0x86, 0x31, 0xa1, 0xac, 0x8a, 0x22, 0xac, 0x51, 0xb3, 0xff, 0xb5, 0x05, 0xe7, - 0x52, 0x5f, 0x74, 0xcb, 0x8d, 0x62, 0xf4, 0x6e, 0xd7, 0x57, 0x2d, 0x0c, 0xf6, 0x55, 0xb4, 0x36, - 0xfb, 0x26, 0xb5, 0xe6, 0x64, 0x89, 0xf6, 0x45, 0x37, 0x60, 0xd8, 0x8d, 0xc9, 0x9e, 0xfc, 0x98, - 0x67, 0x7a, 0x7e, 0x0c, 0xef, 0x55, 0x32, 0x23, 0x55, 0x5a, 0x13, 0x73, 0x02, 0xf6, 0x8f, 0x14, - 0xa1, 0xc4, 0x97, 0xed, 0xba, 0xd3, 0x3e, 0x83, 0xb9, 0xa8, 0xc2, 0x10, 0xa3, 0xce, 0x3b, 0xfe, - 0xe9, 0xec, 0x8e, 0x8b, 0xee, 0x2c, 0xd0, 0x9b, 0x05, 0x17, 0x5e, 0x14, 0x33, 0xa3, 0x45, 0x98, - 0x91, 0x40, 0x0e, 0xc0, 0x96, 0xeb, 0x3b, 0xe1, 0x01, 0x2d, 0x9b, 0x2b, 0x32, 0x82, 0x2f, 0xf6, - 0x26, 0xb8, 0xac, 0xf0, 0x39, 0x59, 0xd5, 0xd7, 0x04, 0x80, 0x35, 0xa2, 0xf3, 0xaf, 0x41, 0x49, - 0x21, 0x9f, 0xe4, 0x54, 0x9e, 0xff, 0x02, 0x4c, 0xa7, 0xda, 0xea, 0x57, 0x7d, 0x42, 0x3f, 0xd4, - 0xbf, 0xc1, 0xb8, 0x80, 0xe8, 0xf5, 0xaa, 0xbf, 0x2f, 0xd8, 0xdd, 0x07, 0x70, 0xde, 0xcb, 0xe0, - 0xb2, 0x62, 0xaa, 0x06, 0xe7, 0xca, 0x4f, 0x8a, 0xcf, 0x3e, 0x9f, 0x05, 0xc5, 0x99, 0x6d, 0xd0, - 0x83, 0x2a, 0x68, 0xd3, 0x35, 0xef, 0x78, 0xac, 0xbf, 0xe2, 0xbe, 0x78, 0x5b, 0x94, 0x61, 0x05, - 0xa5, 0x2c, 0xec, 0xbc, 0xea, 0xfc, 0x4d, 0x72, 0x50, 0x27, 0x1e, 0x69, 0xc4, 0x41, 0xf8, 0x91, - 0x76, 0xff, 0x29, 0x3e, 0xfa, 0x9c, 0x03, 0x8e, 0x0b, 0x02, 0xc5, 0x9b, 0xe4, 0x80, 0x4f, 0x85, - 0xfe, 0x75, 0xc5, 0x9e, 0x5f, 0xf7, 0xf3, 0x16, 0x4c, 0xaa, 0xaf, 0x3b, 0x83, 0xad, 0xbe, 0x6c, - 0x6e, 0xf5, 0xa7, 0x7a, 0x2e, 0xf0, 0x9c, 0x4d, 0xfe, 0x17, 0x8c, 0x49, 0x09, 0x9c, 0x5a, 0x18, - 0xd0, 0xa1, 0xa1, 0xa7, 0xca, 0x47, 0x39, 0x21, 0x83, 0x7c, 0xd7, 0x4d, 0x72, 0xb0, 0x19, 0x50, - 0x01, 0x27, 0xfb, 0xbb, 0x8c, 0x59, 0x1b, 0xea, 0x39, 0x6b, 0xbf, 0x58, 0x80, 0x0b, 0x6a, 0x04, - 0x0c, 0x11, 0xe2, 0x2f, 0xfb, 0x18, 0xbc, 0x04, 0xe3, 0x4d, 0xb2, 0xed, 0x74, 0xbc, 0x58, 0xa9, - 0x8e, 0x86, 0xb9, 0xfa, 0xb0, 0x92, 0x14, 0x63, 0x1d, 0xe7, 0x04, 0xc3, 0xf6, 0xd3, 0xe3, 0xec, - 0x74, 0x88, 0x1d, 0xba, 0x82, 0xa9, 0x7c, 0xa9, 0x29, 0x00, 0x27, 0x74, 0x05, 0xa0, 0x50, 0xf6, - 0x3d, 0x03, 0xc3, 0xee, 0x1e, 0x95, 0x16, 0x0a, 0xa6, 0x10, 0x50, 0xa5, 0x85, 0x98, 0xc3, 0xd0, - 0xa7, 0x60, 0xb4, 0x11, 0xec, 0xed, 0x39, 0x7e, 0x93, 0x31, 0xed, 0xd2, 0xf2, 0x38, 0x15, 0x28, - 0x56, 0x78, 0x11, 0x96, 0x30, 0xf4, 0x24, 0x0c, 0x39, 0x61, 0x2b, 0x9a, 0x1b, 0x62, 0x38, 0x63, - 0xb4, 0xa5, 0xa5, 0xb0, 0x15, 0x61, 0x56, 0x4a, 0x25, 0xd9, 0xfb, 0x41, 0xb8, 0xeb, 0xfa, 0xad, - 0x8a, 0x1b, 0x32, 0xb1, 0x54, 0x93, 0x64, 0xef, 0x29, 0x08, 0xd6, 0xb0, 0xd0, 0x1a, 0x0c, 0xb7, - 0x83, 0x30, 0x8e, 0xe6, 0x46, 0xd8, 0x70, 0x3f, 0x9d, 0xb3, 0x95, 0xf8, 0xd7, 0xd6, 0x82, 0x30, - 0x4e, 0x3e, 0x80, 0xfe, 0x8b, 0x30, 0xaf, 0x8e, 0xbe, 0x0d, 0x8a, 0xc4, 0xdf, 0x9f, 0x1b, 0x65, - 0x54, 0xe6, 0xb3, 0xa8, 0xac, 0xfa, 0xfb, 0x77, 0x9d, 0x30, 0xe1, 0x33, 0xab, 0xfe, 0x3e, 0xa6, - 0x75, 0xd0, 0x97, 0xa0, 0x24, 0x1f, 0x0f, 0x22, 0x71, 0xb5, 0xcc, 0x5c, 0x62, 0x58, 0x20, 0x61, - 0xf2, 0x7e, 0xc7, 0x0d, 0xc9, 0x1e, 0xf1, 0xe3, 0x28, 0x51, 0xff, 0x48, 0x68, 0x84, 0x13, 0x6a, - 0xe8, 0x4b, 0x52, 0x9f, 0xb1, 0x1e, 0x74, 0xfc, 0x38, 0x9a, 0x2b, 0xb1, 0xee, 0x65, 0x6a, 0x9a, - 0xef, 0x26, 0x78, 0x69, 0x85, 0x07, 0xaf, 0x8c, 0x0d, 0x52, 0x08, 0xc3, 0xa4, 0xe7, 0xee, 0x13, - 0x9f, 0x44, 0x51, 0x2d, 0x0c, 0xb6, 0xc8, 0x1c, 0xb0, 0x9e, 0x5f, 0xcc, 0x56, 0xc0, 0x06, 0x5b, - 0x64, 0x79, 0xf6, 0xe8, 0xb0, 0x3c, 0x79, 0x4b, 0xaf, 0x83, 0x4d, 0x12, 0xe8, 0x0e, 0x4c, 0x51, - 0x11, 0xda, 0x4d, 0x88, 0x8e, 0xf7, 0x23, 0xca, 0xe4, 0x67, 0x6c, 0x54, 0xc2, 0x29, 0x22, 0xe8, - 0x2d, 0x28, 0x79, 0xee, 0x36, 0x69, 0x1c, 0x34, 0x3c, 0x32, 0x37, 0xc1, 0x28, 0x66, 0x6e, 0xab, - 0x5b, 0x12, 0x89, 0x5f, 0x51, 0xd4, 0x5f, 0x9c, 0x54, 0x47, 0x77, 0xe1, 0xb1, 0x98, 0x84, 0x7b, - 0xae, 0xef, 0xd0, 0xed, 0x20, 0x24, 0x5e, 0xa6, 0xc6, 0x9e, 0x64, 0xeb, 0xed, 0x92, 0x18, 0xba, - 0xc7, 0x36, 0x33, 0xb1, 0x70, 0x4e, 0x6d, 0x74, 0x1b, 0xa6, 0xd9, 0x4e, 0xa8, 0x75, 0x3c, 0xaf, - 0x16, 0x78, 0x6e, 0xe3, 0x60, 0x6e, 0x8a, 0x11, 0xfc, 0x94, 0xd4, 0x53, 0x57, 0x4d, 0x30, 0xbd, - 0x93, 0x27, 0xff, 0x70, 0xba, 0x36, 0xda, 0x62, 0x7a, 0xcb, 0x4e, 0xe8, 0xc6, 0x07, 0x74, 0xfd, - 0x92, 0x07, 0xf1, 0xdc, 0x74, 0xcf, 0x1b, 0xae, 0x8e, 0xaa, 0x94, 0x9b, 0x7a, 0x21, 0x4e, 0x13, - 0xa4, 0x5b, 0x3b, 0x8a, 0x9b, 0xae, 0x3f, 0x37, 0xc3, 0x38, 0x86, 0xda, 0x19, 0x75, 0x5a, 0x88, - 0x39, 0x8c, 0xe9, 0x2c, 0xe9, 0x8f, 0xdb, 0x94, 0x83, 0xce, 0x32, 0xc4, 0x44, 0x67, 0x29, 0x01, - 0x38, 0xc1, 0xa1, 0xc7, 0x72, 0x1c, 0x1f, 0xcc, 0x21, 0x86, 0xaa, 0xb6, 0xcb, 0xe6, 0xe6, 0x97, - 0x30, 0x2d, 0x47, 0xb7, 0x60, 0x94, 0xf8, 0xfb, 0x6b, 0x61, 0xb0, 0x37, 0x77, 0x2e, 0x7f, 0xcf, - 0xae, 0x72, 0x14, 0xce, 0xd0, 0x93, 0x2b, 0x8a, 0x28, 0xc6, 0x92, 0x04, 0x7a, 0x00, 0x73, 0x19, - 0x33, 0xc2, 0x27, 0xe0, 0x3c, 0x9b, 0x80, 0xcf, 0x8b, 0xba, 0x73, 0x9b, 0x39, 0x78, 0xc7, 0x3d, - 0x60, 0x38, 0x97, 0x3a, 0xfa, 0x2e, 0x98, 0xe4, 0x1b, 0x8a, 0x3f, 0x78, 0x44, 0x73, 0x17, 0xd8, - 0xd7, 0x5c, 0xce, 0xdf, 0x9c, 0x1c, 0x71, 0xf9, 0x82, 0xe8, 0xd0, 0xa4, 0x5e, 0x1a, 0x61, 0x93, - 0x9a, 0xbd, 0x05, 0x53, 0x8a, 0x6f, 0xb1, 0xa5, 0x83, 0xca, 0x30, 0x4c, 0x19, 0xb2, 0xd4, 0x29, - 0x94, 0xe8, 0x4c, 0x31, 0x45, 0x35, 0xe6, 0xe5, 0x6c, 0xa6, 0xdc, 0x0f, 0xc8, 0xf2, 0x41, 0x4c, - 0xf8, 0xbd, 0xb0, 0xa8, 0xcd, 0x94, 0x04, 0xe0, 0x04, 0xc7, 0xfe, 0x7f, 0x5c, 0xee, 0x49, 0x98, - 0xe3, 0x00, 0xc7, 0xc1, 0x0b, 0x30, 0xb6, 0x13, 0x44, 0x31, 0xc5, 0x66, 0x6d, 0x0c, 0x27, 0x92, - 0xce, 0x0d, 0x51, 0x8e, 0x15, 0x06, 0x7a, 0x03, 0x26, 0x1b, 0x7a, 0x03, 0xe2, 0x2c, 0x53, 0x43, - 0x60, 0xb4, 0x8e, 0x4d, 0x5c, 0xf4, 0x3a, 0x8c, 0xb1, 0xe7, 0xca, 0x46, 0xe0, 0x89, 0x1b, 0xa8, - 0x3c, 0x90, 0xc7, 0x6a, 0xa2, 0xfc, 0x58, 0xfb, 0x8d, 0x15, 0x36, 0xba, 0x02, 0x23, 0xb4, 0x0b, - 0xd5, 0x9a, 0x38, 0x45, 0x94, 0x56, 0xe0, 0x06, 0x2b, 0xc5, 0x02, 0x6a, 0xff, 0x9d, 0x82, 0x36, - 0xca, 0xf4, 0x4e, 0x45, 0x50, 0x0d, 0x46, 0xef, 0x3b, 0x6e, 0xec, 0xfa, 0x2d, 0x21, 0x2e, 0x3c, - 0xdb, 0xf3, 0x48, 0x61, 0x95, 0xee, 0xf1, 0x0a, 0xfc, 0xd0, 0x13, 0x7f, 0xb0, 0x24, 0x43, 0x29, - 0x86, 0x1d, 0xdf, 0xa7, 0x14, 0x0b, 0x83, 0x52, 0xc4, 0xbc, 0x02, 0xa7, 0x28, 0xfe, 0x60, 0x49, - 0x06, 0xbd, 0x0b, 0x20, 0x97, 0x25, 0x69, 0x8a, 0x67, 0xc2, 0x17, 0xfa, 0x13, 0xdd, 0x54, 0x75, - 0x96, 0xa7, 0xe8, 0x91, 0x9a, 0xfc, 0xc7, 0x1a, 0x3d, 0x3b, 0x66, 0x62, 0x55, 0x77, 0x67, 0xd0, - 0x77, 0x52, 0x4e, 0xe0, 0x84, 0x31, 0x69, 0x2e, 0xc5, 0x62, 0x70, 0x9e, 0x1b, 0x4c, 0x2a, 0xde, - 0x74, 0xf7, 0x88, 0xce, 0x35, 0x04, 0x11, 0x9c, 0xd0, 0xb3, 0x7f, 0xb9, 0x08, 0x73, 0x79, 0xdd, - 0xa5, 0x8b, 0x8e, 0x3c, 0x70, 0xe3, 0x15, 0x2a, 0x0d, 0x59, 0xe6, 0xa2, 0x5b, 0x15, 0xe5, 0x58, - 0x61, 0xd0, 0xd9, 0x8f, 0xdc, 0x96, 0xbc, 0xd4, 0x0c, 0x27, 0xb3, 0x5f, 0x67, 0xa5, 0x58, 0x40, - 0x29, 0x5e, 0x48, 0x9c, 0x48, 0xbc, 0x43, 0x6b, 0xab, 0x04, 0xb3, 0x52, 0x2c, 0xa0, 0xba, 0xc6, - 0x64, 0xa8, 0x8f, 0xc6, 0xc4, 0x18, 0xa2, 0xe1, 0xd3, 0x1d, 0x22, 0xf4, 0x65, 0x80, 0x6d, 0xd7, - 0x77, 0xa3, 0x1d, 0x46, 0x7d, 0xe4, 0xc4, 0xd4, 0x95, 0x2c, 0xb5, 0xa6, 0xa8, 0x60, 0x8d, 0x22, - 0x7a, 0x15, 0xc6, 0xd5, 0x06, 0xac, 0x56, 0x98, 0x52, 0x5e, 0x7b, 0xe4, 0x4c, 0xb8, 0x51, 0x05, - 0xeb, 0x78, 0xf6, 0x7b, 0xe9, 0xf5, 0x22, 0x76, 0x80, 0x36, 0xbe, 0xd6, 0xa0, 0xe3, 0x5b, 0xe8, - 0x3d, 0xbe, 0xf6, 0x6f, 0x14, 0x61, 0xda, 0x68, 0xac, 0x13, 0x0d, 0xc0, 0xb3, 0xae, 0xd3, 0x73, - 0xce, 0x89, 0x89, 0xd8, 0x7f, 0x76, 0xff, 0xad, 0xa2, 0x9f, 0x85, 0x74, 0x07, 0xf0, 0xfa, 0xe8, - 0xcb, 0x50, 0xf2, 0x9c, 0x88, 0x69, 0x5f, 0x88, 0xd8, 0x77, 0x83, 0x10, 0x4b, 0xee, 0x11, 0x4e, - 0x14, 0x6b, 0x47, 0x0d, 0xa7, 0x9d, 0x90, 0xa4, 0x07, 0x32, 0x95, 0x7d, 0xa4, 0xa1, 0x83, 0xea, - 0x04, 0x15, 0x90, 0x0e, 0x30, 0x87, 0xa1, 0xd7, 0x61, 0x22, 0x24, 0x6c, 0x55, 0xac, 0x50, 0x51, - 0x8e, 0x2d, 0xb3, 0xe1, 0x44, 0xe6, 0xc3, 0x1a, 0x0c, 0x1b, 0x98, 0x89, 0x28, 0x3f, 0xd2, 0x43, - 0x94, 0x7f, 0x16, 0x46, 0xd9, 0x0f, 0xb5, 0x02, 0xd4, 0x6c, 0x54, 0x79, 0x31, 0x96, 0xf0, 0xf4, - 0x82, 0x19, 0x1b, 0x70, 0xc1, 0x3c, 0x07, 0x53, 0x15, 0x87, 0xec, 0x05, 0xfe, 0xaa, 0xdf, 0x6c, - 0x07, 0xae, 0x1f, 0xa3, 0x39, 0x18, 0x62, 0xa7, 0x03, 0xdf, 0xdb, 0x43, 0x94, 0x02, 0x1e, 0xa2, - 0x82, 0xb9, 0xfd, 0xbb, 0x05, 0x98, 0xac, 0x10, 0x8f, 0xc4, 0x84, 0x5f, 0x65, 0x22, 0xb4, 0x06, - 0xa8, 0x15, 0x3a, 0x0d, 0x52, 0x23, 0xa1, 0x1b, 0x34, 0x75, 0x6d, 0x6c, 0x91, 0x3f, 0x0e, 0x5d, - 0xef, 0x82, 0xe2, 0x8c, 0x1a, 0xe8, 0x1d, 0x98, 0x6c, 0x87, 0xc4, 0x50, 0x22, 0x5a, 0x79, 0xd2, - 0x48, 0x4d, 0x47, 0xe4, 0x82, 0xb0, 0x51, 0x84, 0x4d, 0x52, 0xe8, 0x3b, 0x60, 0x26, 0x08, 0xdb, - 0x3b, 0x8e, 0x5f, 0x21, 0x6d, 0xe2, 0x37, 0xa9, 0xa4, 0x2f, 0x54, 0x10, 0xe7, 0x8f, 0x0e, 0xcb, - 0x33, 0xb7, 0x53, 0x30, 0xdc, 0x85, 0x8d, 0xde, 0x81, 0xd9, 0x76, 0x18, 0xb4, 0x9d, 0x16, 0x5b, - 0x28, 0x42, 0xa0, 0xe1, 0xdc, 0xe7, 0x85, 0xa3, 0xc3, 0xf2, 0x6c, 0x2d, 0x0d, 0x3c, 0x3e, 0x2c, - 0x9f, 0x63, 0x03, 0x45, 0x4b, 0x12, 0x20, 0xee, 0x26, 0x63, 0xb7, 0xe0, 0x42, 0x25, 0xb8, 0xef, - 0xdf, 0x77, 0xc2, 0xe6, 0x52, 0xad, 0xaa, 0xe9, 0x0e, 0x36, 0xe4, 0xdd, 0x95, 0x1b, 0x63, 0x64, - 0x9e, 0x53, 0x5a, 0x4d, 0x2e, 0xbf, 0xac, 0xb9, 0x1e, 0xc9, 0xd1, 0x51, 0xfc, 0xbd, 0x82, 0xd1, - 0x52, 0x82, 0xaf, 0x1e, 0x3e, 0xac, 0xdc, 0x87, 0x8f, 0xb7, 0x61, 0x6c, 0xdb, 0x25, 0x5e, 0x13, - 0x93, 0x6d, 0x31, 0x33, 0x9f, 0xce, 0x7f, 0x5f, 0x5e, 0xa3, 0x98, 0x52, 0x27, 0xc5, 0x6f, 0xbe, - 0x6b, 0xa2, 0x32, 0x56, 0x64, 0xd0, 0x2e, 0xcc, 0xc8, 0xab, 0x95, 0x84, 0x8a, 0x4d, 0xfc, 0x6c, - 0xaf, 0xfb, 0x9a, 0x49, 0x9c, 0x4d, 0x20, 0x4e, 0x91, 0xc1, 0x5d, 0x84, 0xe9, 0x55, 0x77, 0x8f, - 0x1e, 0x57, 0x43, 0x6c, 0x49, 0xb3, 0xab, 0x2e, 0xbb, 0xb5, 0xb3, 0x52, 0xfb, 0x27, 0x2d, 0x78, - 0xbc, 0x6b, 0x64, 0x84, 0xf6, 0xe2, 0x94, 0x67, 0x21, 0xad, 0x4d, 0x28, 0xf4, 0xd7, 0x26, 0xd8, - 0xff, 0xd4, 0x82, 0xf3, 0xab, 0x7b, 0xed, 0xf8, 0xa0, 0xe2, 0x9a, 0x8f, 0x33, 0xaf, 0xc1, 0xc8, - 0x1e, 0x69, 0xba, 0x9d, 0x3d, 0x31, 0x73, 0x65, 0xc9, 0xd2, 0xd7, 0x59, 0xe9, 0xf1, 0x61, 0x79, - 0xb2, 0x1e, 0x07, 0xa1, 0xd3, 0x22, 0xbc, 0x00, 0x0b, 0x74, 0x76, 0x30, 0xba, 0x1f, 0x90, 0x5b, - 0xee, 0x9e, 0x2b, 0xed, 0x05, 0x7a, 0x6a, 0xd4, 0x16, 0xe4, 0x80, 0x2e, 0xbc, 0xdd, 0x71, 0xfc, - 0xd8, 0x8d, 0x0f, 0xc4, 0xbb, 0x93, 0x24, 0x82, 0x13, 0x7a, 0xf6, 0x37, 0x2d, 0x98, 0x96, 0xbc, - 0x64, 0xa9, 0xd9, 0x0c, 0x49, 0x14, 0xa1, 0x79, 0x28, 0xb8, 0x6d, 0xd1, 0x4b, 0x10, 0xbd, 0x2c, - 0x54, 0x6b, 0xb8, 0xe0, 0xb6, 0x51, 0x0d, 0x4a, 0xdc, 0xec, 0x20, 0x59, 0x5c, 0x03, 0x19, 0x2f, - 0xb0, 0x1e, 0x6c, 0xca, 0x9a, 0x38, 0x21, 0x22, 0xa5, 0x62, 0x76, 0x0e, 0x15, 0xcd, 0x47, 0xab, - 0x1b, 0xa2, 0x1c, 0x2b, 0x0c, 0x74, 0x15, 0xc6, 0xfc, 0xa0, 0xc9, 0xad, 0x40, 0xf8, 0x9e, 0x66, - 0x4b, 0x76, 0x43, 0x94, 0x61, 0x05, 0xb5, 0x7f, 0xd8, 0x82, 0x09, 0xf9, 0x65, 0x03, 0x0a, 0xe8, - 0x74, 0x6b, 0x25, 0xc2, 0x79, 0xb2, 0xb5, 0xa8, 0x80, 0xcd, 0x20, 0x86, 0x5c, 0x5d, 0x3c, 0x89, - 0x5c, 0x6d, 0xff, 0x44, 0x01, 0xa6, 0x64, 0x77, 0xea, 0x9d, 0xad, 0x88, 0xc4, 0x68, 0x13, 0x4a, - 0x0e, 0x1f, 0x72, 0x22, 0x57, 0xec, 0x33, 0xd9, 0x17, 0x3a, 0x63, 0x7e, 0x12, 0x51, 0x67, 0x49, - 0xd6, 0xc6, 0x09, 0x21, 0xe4, 0xc1, 0xac, 0x1f, 0xc4, 0xec, 0xd8, 0x53, 0xf0, 0x5e, 0x0f, 0x23, - 0x69, 0xea, 0x17, 0x05, 0xf5, 0xd9, 0x8d, 0x34, 0x15, 0xdc, 0x4d, 0x18, 0xad, 0x4a, 0x25, 0x52, - 0x31, 0xff, 0x0a, 0xa7, 0xcf, 0x42, 0xb6, 0x0e, 0xc9, 0xfe, 0x35, 0x0b, 0x4a, 0x12, 0xed, 0x2c, - 0xde, 0xc0, 0xd6, 0x61, 0x34, 0x62, 0x93, 0x20, 0x87, 0xc6, 0xee, 0xd5, 0x71, 0x3e, 0x5f, 0xc9, - 0x69, 0xce, 0xff, 0x47, 0x58, 0xd2, 0x60, 0x5a, 0x70, 0xd5, 0xfd, 0x8f, 0x89, 0x16, 0x5c, 0xf5, - 0x27, 0xe7, 0x84, 0xf9, 0x6f, 0xac, 0xcf, 0x9a, 0xaa, 0x80, 0x0a, 0x9d, 0xed, 0x90, 0x6c, 0xbb, - 0x0f, 0xd2, 0x42, 0x67, 0x8d, 0x95, 0x62, 0x01, 0x45, 0xef, 0xc2, 0x44, 0x43, 0x2a, 0x8f, 0x13, - 0x36, 0x70, 0xa5, 0xa7, 0x2a, 0x5e, 0xbd, 0xda, 0x70, 0x0b, 0xd1, 0x15, 0xad, 0x3e, 0x36, 0xa8, - 0x99, 0x96, 0x09, 0xc5, 0x7e, 0x96, 0x09, 0x09, 0xdd, 0xdc, 0xb7, 0x75, 0xfb, 0xa7, 0x2c, 0x18, - 0xe1, 0x2a, 0xc8, 0xc1, 0x74, 0xb6, 0xda, 0x23, 0x56, 0x32, 0x76, 0x77, 0x69, 0xa1, 0x78, 0x94, - 0x42, 0xeb, 0x50, 0x62, 0x3f, 0x98, 0x2a, 0xa6, 0x98, 0x6f, 0x1a, 0xcb, 0x5b, 0xd5, 0x3b, 0x78, - 0x57, 0x56, 0xc3, 0x09, 0x05, 0xfb, 0x47, 0x8b, 0x94, 0x55, 0x25, 0xa8, 0xc6, 0x09, 0x6e, 0x3d, - 0xba, 0x13, 0xbc, 0xf0, 0xa8, 0x4e, 0xf0, 0x16, 0x4c, 0x37, 0xb4, 0x27, 0xaf, 0x64, 0x26, 0xaf, - 0xf6, 0x5c, 0x24, 0xda, 0xeb, 0x18, 0x57, 0xc3, 0xad, 0x98, 0x44, 0x70, 0x9a, 0x2a, 0xfa, 0x4e, - 0x98, 0xe0, 0xf3, 0x2c, 0x5a, 0x19, 0x62, 0xad, 0x7c, 0x2a, 0x7f, 0xbd, 0xe8, 0x4d, 0xb0, 0x95, - 0x58, 0xd7, 0xaa, 0x63, 0x83, 0x98, 0xfd, 0xcb, 0x63, 0x30, 0xbc, 0xba, 0x4f, 0xfc, 0xf8, 0x0c, - 0x18, 0x52, 0x03, 0xa6, 0x5c, 0x7f, 0x3f, 0xf0, 0xf6, 0x49, 0x93, 0xc3, 0x4f, 0x72, 0xb8, 0x3e, - 0x26, 0x48, 0x4f, 0x55, 0x0d, 0x12, 0x38, 0x45, 0xf2, 0x51, 0xdc, 0xda, 0xaf, 0xc3, 0x08, 0x9f, - 0x7b, 0x71, 0x65, 0xcf, 0x54, 0xb0, 0xb3, 0x41, 0x14, 0xbb, 0x20, 0xd1, 0x28, 0x70, 0x8d, 0xbe, - 0xa8, 0x8e, 0xde, 0x83, 0xa9, 0x6d, 0x37, 0x8c, 0x62, 0x7a, 0xdd, 0x8e, 0x62, 0x67, 0xaf, 0xfd, - 0x10, 0xb7, 0x74, 0x35, 0x0e, 0x6b, 0x06, 0x25, 0x9c, 0xa2, 0x8c, 0x5a, 0x30, 0x49, 0x2f, 0x8e, - 0x49, 0x53, 0xa3, 0x27, 0x6e, 0x4a, 0xa9, 0xe1, 0x6e, 0xe9, 0x84, 0xb0, 0x49, 0x97, 0x32, 0x93, - 0x06, 0xbb, 0x68, 0x8e, 0x31, 0x89, 0x42, 0x31, 0x13, 0x7e, 0xc3, 0xe4, 0x30, 0xca, 0x93, 0x98, - 0x31, 0x4b, 0xc9, 0xe4, 0x49, 0x9a, 0xc9, 0xca, 0x57, 0xa0, 0x44, 0xe8, 0x10, 0x52, 0xc2, 0xe2, - 0xb1, 0x61, 0x71, 0xb0, 0xbe, 0xae, 0xbb, 0x8d, 0x30, 0x30, 0xf5, 0x23, 0xab, 0x92, 0x12, 0x4e, - 0x88, 0xa2, 0x15, 0x18, 0x89, 0x48, 0xe8, 0x92, 0x48, 0x3c, 0x3b, 0xf4, 0x98, 0x46, 0x86, 0xc6, - 0x6d, 0xa8, 0xf9, 0x6f, 0x2c, 0xaa, 0xd2, 0xe5, 0xe5, 0xb0, 0xdb, 0x10, 0x7b, 0x69, 0xd0, 0x96, - 0xd7, 0x12, 0x2b, 0xc5, 0x02, 0x8a, 0xde, 0x82, 0xd1, 0x90, 0x78, 0x4c, 0x01, 0x37, 0x39, 0xf8, - 0x22, 0xe7, 0xfa, 0x3c, 0x5e, 0x0f, 0x4b, 0x02, 0xe8, 0x26, 0xa0, 0x90, 0x50, 0x19, 0xc2, 0xf5, - 0x5b, 0xca, 0xc4, 0x43, 0xbc, 0x1f, 0x3c, 0x21, 0xda, 0x3f, 0x87, 0x13, 0x0c, 0x69, 0x5d, 0x89, - 0x33, 0xaa, 0xa1, 0xeb, 0x30, 0xab, 0x4a, 0xab, 0x7e, 0x14, 0x3b, 0x7e, 0x83, 0xb0, 0xa7, 0x83, - 0x52, 0x22, 0x15, 0xe1, 0x34, 0x02, 0xee, 0xae, 0x63, 0x7f, 0x9d, 0x8a, 0x33, 0x74, 0xb4, 0xce, - 0x40, 0x16, 0x78, 0xd3, 0x94, 0x05, 0x2e, 0xe6, 0xce, 0x5c, 0x8e, 0x1c, 0x70, 0x64, 0xc1, 0xb8, - 0x36, 0xb3, 0xc9, 0x9a, 0xb5, 0x7a, 0xac, 0xd9, 0x0e, 0xcc, 0xd0, 0x95, 0x7e, 0x7b, 0x8b, 0xb9, - 0x13, 0x35, 0xd9, 0xc2, 0x2c, 0x3c, 0xdc, 0xc2, 0x54, 0x86, 0xb8, 0xb7, 0x52, 0x04, 0x71, 0x57, - 0x13, 0xe8, 0x35, 0xa9, 0x8d, 0x2a, 0x1a, 0xa6, 0x5b, 0x5c, 0xd3, 0x74, 0x7c, 0x58, 0x9e, 0xd1, - 0x3e, 0x44, 0xd7, 0x3e, 0xd9, 0x5f, 0x91, 0xdf, 0xc8, 0x99, 0xcd, 0x22, 0x94, 0x1a, 0x6a, 0xb1, - 0x58, 0xa6, 0x31, 0xb9, 0x5a, 0x0e, 0x38, 0xc1, 0xa1, 0x7b, 0x94, 0x5e, 0x41, 0xd2, 0xd6, 0x86, - 0xf4, 0x82, 0x82, 0x19, 0xc4, 0x7e, 0x19, 0x60, 0xf5, 0x01, 0x69, 0xf0, 0xa5, 0xae, 0x3f, 0xea, - 0x5a, 0xf9, 0x8f, 0xba, 0xf6, 0x7f, 0xb2, 0x60, 0x6a, 0x6d, 0xc5, 0xb8, 0x26, 0x2e, 0x00, 0xf0, - 0xbb, 0xd1, 0xbd, 0x7b, 0x1b, 0xf2, 0xbd, 0x82, 0xab, 0x9c, 0x55, 0x29, 0xd6, 0x30, 0xd0, 0x45, - 0x28, 0x7a, 0x1d, 0x5f, 0x5c, 0x59, 0x46, 0x8f, 0x0e, 0xcb, 0xc5, 0x5b, 0x1d, 0x1f, 0xd3, 0x32, - 0xcd, 0xc0, 0xaf, 0x38, 0xb0, 0x81, 0x5f, 0x5f, 0x37, 0x21, 0x54, 0x86, 0xe1, 0xfb, 0xf7, 0xdd, - 0x26, 0x37, 0xc6, 0x16, 0x6f, 0x29, 0xf7, 0xee, 0x55, 0x2b, 0x11, 0xe6, 0xe5, 0xf6, 0xd7, 0x8a, - 0x30, 0xbf, 0xe6, 0x91, 0x07, 0x1f, 0xd2, 0x20, 0x7d, 0x50, 0xf3, 0xc4, 0x93, 0xc9, 0x8b, 0x27, - 0xb5, 0xc5, 0xec, 0x3f, 0x1e, 0xdb, 0x30, 0xca, 0x0d, 0x04, 0xa4, 0x79, 0xfa, 0x1b, 0x59, 0xad, - 0xe7, 0x0f, 0xc8, 0x82, 0xd0, 0xce, 0x71, 0x13, 0x2c, 0x75, 0xd2, 0x8a, 0x52, 0x2c, 0x89, 0xcf, - 0x7f, 0x0e, 0x26, 0x74, 0xcc, 0x13, 0x59, 0x45, 0xff, 0x8d, 0x22, 0xcc, 0xd0, 0x1e, 0x3c, 0xd2, - 0x89, 0xb8, 0xd3, 0x3d, 0x11, 0xa7, 0x6d, 0x19, 0xdb, 0x7f, 0x36, 0xde, 0x4d, 0xcf, 0xc6, 0x4b, - 0x79, 0xb3, 0x71, 0xd6, 0x73, 0xf0, 0xbd, 0x16, 0x9c, 0x5b, 0xf3, 0x82, 0xc6, 0x6e, 0xca, 0x68, - 0xf7, 0x55, 0x18, 0xa7, 0x7c, 0x3c, 0x32, 0xbc, 0x61, 0x0c, 0xff, 0x28, 0x01, 0xc2, 0x3a, 0x9e, - 0x56, 0xed, 0xce, 0x9d, 0x6a, 0x25, 0xcb, 0xad, 0x4a, 0x80, 0xb0, 0x8e, 0x67, 0xff, 0xb6, 0x05, - 0x4f, 0x5d, 0x5f, 0x59, 0x4d, 0x96, 0x62, 0x97, 0x67, 0x17, 0xbd, 0x05, 0x36, 0xb5, 0xae, 0x24, - 0xb7, 0xc0, 0x0a, 0xeb, 0x85, 0x80, 0x7e, 0x5c, 0xbc, 0x16, 0x7f, 0xd6, 0x82, 0x73, 0xd7, 0xdd, - 0x98, 0x1e, 0xcb, 0x69, 0x1f, 0x23, 0x7a, 0x2e, 0x47, 0x6e, 0x1c, 0x84, 0x07, 0x69, 0x1f, 0x23, - 0xac, 0x20, 0x58, 0xc3, 0xe2, 0x2d, 0xef, 0xbb, 0x11, 0xed, 0x69, 0xc1, 0x54, 0x45, 0x61, 0x51, - 0x8e, 0x15, 0x06, 0xfd, 0xb0, 0xa6, 0x1b, 0xb2, 0xab, 0xc4, 0x81, 0xe0, 0xb0, 0xea, 0xc3, 0x2a, - 0x12, 0x80, 0x13, 0x1c, 0xfb, 0x27, 0x2d, 0xb8, 0x70, 0xdd, 0xeb, 0x44, 0x31, 0x09, 0xb7, 0x23, - 0xa3, 0xb3, 0x2f, 0x43, 0x89, 0xc8, 0xeb, 0xba, 0xe8, 0xab, 0x12, 0x30, 0xd5, 0x3d, 0x9e, 0x3b, - 0x38, 0x29, 0xbc, 0x01, 0x2c, 0xe0, 0x4f, 0x66, 0xb9, 0xfd, 0x0b, 0x05, 0x98, 0xbc, 0xb1, 0xb9, - 0x59, 0xbb, 0x4e, 0x62, 0x71, 0x8a, 0xf5, 0x57, 0x35, 0x63, 0x4d, 0x63, 0xd6, 0xeb, 0x52, 0xd4, - 0x89, 0x5d, 0x6f, 0x81, 0x7b, 0xd4, 0x2e, 0x54, 0xfd, 0xf8, 0x76, 0x58, 0x8f, 0x43, 0xd7, 0x6f, - 0x65, 0xea, 0xd8, 0xe4, 0x59, 0x5b, 0xcc, 0x3b, 0x6b, 0xd1, 0xcb, 0x30, 0xc2, 0x5c, 0x7a, 0xe5, - 0xf5, 0xe4, 0x09, 0x75, 0xa7, 0x60, 0xa5, 0xc7, 0x87, 0xe5, 0xd2, 0x1d, 0x5c, 0xe5, 0x7f, 0xb0, - 0x40, 0x45, 0x77, 0x60, 0x7c, 0x27, 0x8e, 0xdb, 0x37, 0x88, 0xd3, 0x24, 0xa1, 0xe4, 0x0e, 0x97, - 0xb2, 0xb8, 0x03, 0x1d, 0x04, 0x8e, 0x96, 0x6c, 0xa8, 0xa4, 0x2c, 0xc2, 0x3a, 0x1d, 0xbb, 0x0e, - 0x90, 0xc0, 0x4e, 0x49, 0xbf, 0x60, 0xff, 0x91, 0x05, 0xa3, 0xdc, 0xbb, 0x2a, 0x44, 0x9f, 0x87, - 0x21, 0xf2, 0x80, 0x34, 0x84, 0xe4, 0x98, 0xd9, 0xe1, 0x44, 0xf0, 0xe0, 0xda, 0x72, 0xfa, 0x1f, - 0xb3, 0x5a, 0xe8, 0x06, 0x8c, 0xd2, 0xde, 0x5e, 0x57, 0xae, 0x66, 0x4f, 0xe7, 0x7d, 0xb1, 0x9a, - 0x76, 0x2e, 0xab, 0x88, 0x22, 0x2c, 0xab, 0x33, 0xcd, 0x6f, 0xa3, 0x5d, 0xa7, 0x0c, 0x2c, 0xee, - 0x75, 0xce, 0x6e, 0xae, 0xd4, 0x38, 0x92, 0xa0, 0xc6, 0x35, 0xbf, 0xb2, 0x10, 0x27, 0x44, 0xec, - 0x4d, 0x28, 0xd1, 0x49, 0x5d, 0xf2, 0x5c, 0xa7, 0xb7, 0xd2, 0xf9, 0x79, 0x28, 0x49, 0x05, 0x70, - 0x24, 0x1c, 0x74, 0x18, 0x55, 0xa9, 0x1f, 0x8e, 0x70, 0x02, 0xb7, 0xb7, 0xe1, 0x3c, 0xb3, 0xa6, - 0x70, 0xe2, 0x1d, 0x63, 0x8f, 0xf5, 0x5f, 0xcc, 0x2f, 0x88, 0x8b, 0x18, 0x9f, 0x99, 0x39, 0xcd, - 0xa3, 0x60, 0x42, 0x52, 0x4c, 0x2e, 0x65, 0xf6, 0x9f, 0x0c, 0xc1, 0x13, 0xd5, 0x7a, 0xbe, 0xe3, - 0xdd, 0xeb, 0x30, 0xc1, 0xc5, 0x34, 0xba, 0xb4, 0x1d, 0x4f, 0xb4, 0xab, 0xde, 0x1a, 0x37, 0x35, - 0x18, 0x36, 0x30, 0xd1, 0x53, 0x50, 0x74, 0xdf, 0xf7, 0xd3, 0xc6, 0xb9, 0xd5, 0xb7, 0x37, 0x30, - 0x2d, 0xa7, 0x60, 0x2a, 0xf1, 0x71, 0x56, 0xaa, 0xc0, 0x4a, 0xea, 0x7b, 0x13, 0xa6, 0xdc, 0xa8, - 0x11, 0xb9, 0x55, 0x9f, 0xf2, 0x99, 0xc4, 0x69, 0x33, 0x51, 0x12, 0xd0, 0x4e, 0x2b, 0x28, 0x4e, - 0x61, 0x6b, 0x7c, 0x7d, 0x78, 0x60, 0xa9, 0xb1, 0xaf, 0xc7, 0x0a, 0x15, 0x88, 0xdb, 0xec, 0xeb, - 0x22, 0x66, 0x28, 0x28, 0x04, 0x62, 0xfe, 0xc1, 0x11, 0x96, 0x30, 0x7a, 0x03, 0x6b, 0xec, 0x38, - 0xed, 0xa5, 0x4e, 0xbc, 0x53, 0x71, 0xa3, 0x46, 0xb0, 0x4f, 0xc2, 0x03, 0x76, 0x79, 0x1e, 0x4b, - 0x6e, 0x60, 0x0a, 0xb0, 0x72, 0x63, 0xa9, 0x46, 0x31, 0x71, 0x77, 0x1d, 0x53, 0x2a, 0x84, 0xd3, - 0x90, 0x0a, 0x97, 0x60, 0x5a, 0x36, 0x53, 0x27, 0x11, 0x3b, 0x23, 0xc6, 0x59, 0xc7, 0x94, 0x3b, - 0xb5, 0x28, 0x56, 0xdd, 0x4a, 0xe3, 0xa3, 0xd7, 0x60, 0xd2, 0xf5, 0xdd, 0xd8, 0x75, 0xe2, 0x20, - 0x64, 0x27, 0x2c, 0xbf, 0x27, 0xb3, 0x47, 0xd1, 0xaa, 0x0e, 0xc0, 0x26, 0x9e, 0xfd, 0xc7, 0x43, - 0x30, 0xcb, 0xa6, 0xed, 0x5b, 0x2b, 0xec, 0x63, 0xb3, 0xc2, 0xee, 0x74, 0xaf, 0xb0, 0xd3, 0x10, - 0x77, 0x3f, 0xca, 0x65, 0xf6, 0x1e, 0x94, 0x94, 0x7d, 0xb5, 0x74, 0x11, 0xb0, 0x72, 0x5c, 0x04, - 0xfa, 0x4b, 0x1f, 0xf2, 0x19, 0xb7, 0x98, 0xf9, 0x8c, 0xfb, 0xf7, 0x2d, 0x48, 0xcc, 0x4c, 0xd1, - 0x0d, 0x28, 0xb5, 0x03, 0x66, 0xca, 0x11, 0x4a, 0xfb, 0xa8, 0x27, 0x32, 0x0f, 0x2a, 0x7e, 0x28, - 0xf2, 0xf1, 0xab, 0xc9, 0x1a, 0x38, 0xa9, 0x8c, 0x96, 0x61, 0xb4, 0x1d, 0x92, 0x7a, 0xcc, 0x5c, - 0x39, 0xfb, 0xd2, 0xe1, 0x6b, 0x84, 0xe3, 0x63, 0x59, 0xd1, 0xfe, 0x45, 0x0b, 0x80, 0xbf, 0x94, - 0x3a, 0x7e, 0x8b, 0x9c, 0x81, 0xf6, 0xb7, 0x02, 0x43, 0x51, 0x9b, 0x34, 0x7a, 0x19, 0xd9, 0x24, - 0xfd, 0xa9, 0xb7, 0x49, 0x23, 0x19, 0x70, 0xfa, 0x0f, 0xb3, 0xda, 0xf6, 0xf7, 0x03, 0x4c, 0x25, - 0x68, 0xd5, 0x98, 0xec, 0xa1, 0x17, 0x0d, 0x47, 0xb9, 0x8b, 0x29, 0x47, 0xb9, 0x12, 0xc3, 0xd6, - 0x14, 0x8d, 0xef, 0x41, 0x71, 0xcf, 0x79, 0x20, 0x34, 0x49, 0xcf, 0xf7, 0xee, 0x06, 0xa5, 0xbf, - 0xb0, 0xee, 0x3c, 0xe0, 0x77, 0xa6, 0xe7, 0xe5, 0x02, 0x59, 0x77, 0x1e, 0x1c, 0x73, 0x53, 0x1a, - 0xc6, 0xa4, 0x6e, 0xb9, 0x51, 0xfc, 0xd5, 0xff, 0x92, 0xfc, 0x67, 0xcb, 0x8e, 0x36, 0xc2, 0xda, - 0x72, 0x7d, 0xf1, 0x6e, 0x38, 0x50, 0x5b, 0xae, 0x9f, 0x6e, 0xcb, 0xf5, 0x07, 0x68, 0xcb, 0xf5, - 0xd1, 0x07, 0x30, 0x2a, 0xde, 0xe8, 0x99, 0xfd, 0xbc, 0xa9, 0xa5, 0xca, 0x6b, 0x4f, 0x3c, 0xf1, - 0xf3, 0x36, 0x17, 0xe5, 0x9d, 0x50, 0x94, 0xf6, 0x6d, 0x57, 0x36, 0x88, 0xfe, 0xae, 0x05, 0x53, - 0xe2, 0x37, 0x26, 0xef, 0x77, 0x48, 0x14, 0x0b, 0xd9, 0xf3, 0xb3, 0x83, 0xf7, 0x41, 0x54, 0xe4, - 0x5d, 0xf9, 0xac, 0x64, 0xb3, 0x26, 0xb0, 0x6f, 0x8f, 0x52, 0xbd, 0x40, 0xff, 0xdc, 0x82, 0xf3, - 0x7b, 0xce, 0x03, 0xde, 0x22, 0x2f, 0xc3, 0x4e, 0xec, 0x06, 0xc2, 0x1f, 0xe0, 0xf3, 0x83, 0x4d, - 0x7f, 0x57, 0x75, 0xde, 0x49, 0x69, 0x3a, 0x7c, 0x3e, 0x0b, 0xa5, 0x6f, 0x57, 0x33, 0xfb, 0x35, - 0xbf, 0x0d, 0x63, 0x72, 0xbd, 0x65, 0xdc, 0xbc, 0x2b, 0xba, 0x60, 0x7d, 0x62, 0x13, 0x09, 0xdd, - 0x5b, 0x8d, 0xb6, 0x23, 0xd6, 0xda, 0x23, 0x6d, 0xe7, 0x3d, 0x98, 0xd0, 0xd7, 0xd8, 0x23, 0x6d, - 0xeb, 0x7d, 0x38, 0x97, 0xb1, 0x96, 0x1e, 0x69, 0x93, 0xf7, 0xe1, 0x62, 0xee, 0xfa, 0x78, 0x94, - 0x0d, 0xdb, 0xbf, 0x60, 0xe9, 0x7c, 0xf0, 0x0c, 0x54, 0xf0, 0x2b, 0xa6, 0x0a, 0xfe, 0x52, 0xef, - 0x9d, 0x93, 0xa3, 0x87, 0x7f, 0x57, 0xef, 0x34, 0xe5, 0xea, 0xe8, 0x2d, 0x18, 0xf1, 0x68, 0x89, - 0x34, 0x0e, 0xb1, 0xfb, 0xef, 0xc8, 0x44, 0x96, 0x62, 0xe5, 0x11, 0x16, 0x14, 0xec, 0x5f, 0xb1, - 0x60, 0xe8, 0x0c, 0x46, 0x02, 0x9b, 0x23, 0xf1, 0x62, 0x2e, 0x69, 0x11, 0x9a, 0x6b, 0x01, 0x3b, - 0xf7, 0x57, 0x65, 0xf8, 0xb1, 0x9c, 0x81, 0xf9, 0xbf, 0x05, 0x18, 0xa7, 0x4d, 0x49, 0x2b, 0xc6, - 0x37, 0x60, 0xd2, 0x73, 0xb6, 0x88, 0x27, 0xdf, 0x71, 0xd3, 0x0a, 0x93, 0x5b, 0x3a, 0x10, 0x9b, - 0xb8, 0xb4, 0xf2, 0xb6, 0xfe, 0xa4, 0x2d, 0xe4, 0x17, 0x55, 0xd9, 0x78, 0xef, 0xc6, 0x26, 0x2e, - 0xbd, 0xbb, 0xdf, 0x77, 0xe2, 0xc6, 0x8e, 0x50, 0xa6, 0xa8, 0xee, 0xde, 0xa3, 0x85, 0x98, 0xc3, - 0xa8, 0x00, 0x27, 0x57, 0xe7, 0x5d, 0x7a, 0x33, 0x0c, 0x7c, 0x21, 0x1e, 0x2b, 0x01, 0x0e, 0x9b, - 0x60, 0x9c, 0xc6, 0xcf, 0xf0, 0x98, 0x1f, 0x66, 0x36, 0x9a, 0x03, 0x78, 0xcc, 0xa3, 0x1a, 0x9c, - 0x77, 0xfd, 0x86, 0xd7, 0x69, 0x92, 0x3b, 0x3e, 0x97, 0xee, 0x3c, 0xf7, 0x03, 0xd2, 0x14, 0x02, - 0xb4, 0x32, 0xa7, 0xad, 0x66, 0xe0, 0xe0, 0xcc, 0x9a, 0xf6, 0x5f, 0x83, 0x73, 0xb7, 0x02, 0xa7, - 0xb9, 0xec, 0x78, 0x8e, 0xdf, 0x20, 0x61, 0xd5, 0x6f, 0xf5, 0xb5, 0x12, 0xd3, 0x6d, 0xba, 0x0a, - 0xfd, 0x6c, 0xba, 0xec, 0x1d, 0x40, 0x7a, 0x03, 0xc2, 0x36, 0x19, 0xc3, 0xa8, 0xcb, 0x9b, 0x12, - 0xcb, 0xff, 0xd3, 0xd9, 0xd2, 0x75, 0x57, 0xcf, 0x34, 0xab, 0x5b, 0x5e, 0x80, 0x25, 0x21, 0xfb, - 0x75, 0xc8, 0xf4, 0x47, 0xec, 0xaf, 0xb6, 0xb1, 0x5f, 0x85, 0x59, 0x56, 0xf3, 0x64, 0x2a, 0x05, - 0xfb, 0x07, 0x2d, 0x98, 0xde, 0x48, 0xc5, 0xb8, 0xb8, 0xc2, 0xde, 0x5a, 0x33, 0xf4, 0xee, 0x75, - 0x56, 0x8a, 0x05, 0xf4, 0xd4, 0xf5, 0x7b, 0x7f, 0x61, 0x41, 0x49, 0x45, 0x67, 0x3a, 0x03, 0xa1, - 0x76, 0xc5, 0x10, 0x6a, 0x33, 0xf5, 0x4e, 0xaa, 0x3b, 0x79, 0x32, 0x2d, 0xba, 0xa9, 0xa2, 0x35, - 0xf4, 0x50, 0x39, 0x25, 0x64, 0xb8, 0x6f, 0xff, 0x94, 0x19, 0xd2, 0x41, 0xc6, 0x6f, 0x60, 0x66, - 0x5a, 0x0a, 0xf7, 0x63, 0x62, 0xa6, 0xa5, 0xfa, 0x93, 0xc3, 0xfd, 0x6a, 0x5a, 0x97, 0xd9, 0xa9, - 0xf0, 0xed, 0xcc, 0x95, 0x81, 0xed, 0x4d, 0x15, 0x24, 0xa5, 0x2c, 0x5c, 0x13, 0x44, 0xe9, 0x31, - 0x63, 0x64, 0xe2, 0x1f, 0x8f, 0xa4, 0x95, 0x54, 0xb1, 0x6f, 0xc0, 0x74, 0x6a, 0xc0, 0xd0, 0xab, - 0x30, 0xdc, 0xde, 0x71, 0x22, 0x92, 0x32, 0x4d, 0x1d, 0xae, 0xd1, 0xc2, 0xe3, 0xc3, 0xf2, 0x94, - 0xaa, 0xc0, 0x4a, 0x30, 0xc7, 0xb6, 0xff, 0xa7, 0x05, 0x43, 0x1b, 0x41, 0xf3, 0x2c, 0x16, 0xd3, - 0x9b, 0xc6, 0x62, 0x7a, 0x32, 0x2f, 0x0e, 0x61, 0xee, 0x3a, 0x5a, 0x4b, 0xad, 0xa3, 0x4b, 0xb9, - 0x14, 0x7a, 0x2f, 0xa1, 0x3d, 0x18, 0x67, 0xd1, 0x0d, 0x85, 0xa9, 0xec, 0xcb, 0xc6, 0xfd, 0xaa, - 0x9c, 0xba, 0x5f, 0x4d, 0x6b, 0xa8, 0xda, 0x2d, 0xeb, 0x59, 0x18, 0x15, 0xe6, 0x9a, 0x69, 0xa7, - 0x0d, 0x81, 0x8b, 0x25, 0xdc, 0xfe, 0xa9, 0x22, 0x18, 0xd1, 0x14, 0xd1, 0xaf, 0x59, 0xb0, 0x10, - 0x72, 0x2f, 0xd8, 0x66, 0xa5, 0x13, 0xba, 0x7e, 0xab, 0xde, 0xd8, 0x21, 0xcd, 0x8e, 0xe7, 0xfa, - 0xad, 0x6a, 0xcb, 0x0f, 0x54, 0xf1, 0xea, 0x03, 0xd2, 0xe8, 0xb0, 0x37, 0x97, 0x3e, 0xa1, 0x1b, - 0x95, 0x39, 0xd4, 0xb5, 0xa3, 0xc3, 0xf2, 0x02, 0x3e, 0x11, 0x6d, 0x7c, 0xc2, 0xbe, 0xa0, 0xdf, - 0xb6, 0x60, 0x91, 0x07, 0x19, 0x1c, 0xbc, 0xff, 0x3d, 0x6e, 0xa3, 0x35, 0x49, 0x2a, 0x21, 0xb2, - 0x49, 0xc2, 0xbd, 0xe5, 0xd7, 0xc4, 0x80, 0x2e, 0xd6, 0x4e, 0xd6, 0x16, 0x3e, 0x69, 0xe7, 0xec, - 0x7f, 0x57, 0x84, 0x49, 0x3a, 0x8a, 0x49, 0x6c, 0x9a, 0x57, 0x8d, 0x25, 0xf1, 0x74, 0x6a, 0x49, - 0xcc, 0x1a, 0xc8, 0xa7, 0x13, 0x96, 0x26, 0x82, 0x59, 0xcf, 0x89, 0xe2, 0x1b, 0xc4, 0x09, 0xe3, - 0x2d, 0xe2, 0x70, 0x33, 0xa1, 0xe2, 0x89, 0x4d, 0x9a, 0x94, 0xfa, 0xeb, 0x56, 0x9a, 0x18, 0xee, - 0xa6, 0x8f, 0xf6, 0x01, 0x31, 0x5b, 0xa7, 0xd0, 0xf1, 0x23, 0xfe, 0x2d, 0xae, 0x78, 0x8f, 0x39, - 0x59, 0xab, 0xf3, 0xa2, 0x55, 0x74, 0xab, 0x8b, 0x1a, 0xce, 0x68, 0x41, 0xb3, 0x61, 0x1b, 0x1e, - 0xd4, 0x86, 0x6d, 0xa4, 0x8f, 0x67, 0xd4, 0x1e, 0xcc, 0x88, 0x59, 0xd9, 0x76, 0x5b, 0xe2, 0x90, - 0xfe, 0x52, 0xca, 0xc6, 0xd5, 0x1a, 0xdc, 0x50, 0xa9, 0x8f, 0x81, 0xab, 0xfd, 0xdd, 0x70, 0x8e, - 0x36, 0x67, 0xfa, 0xf1, 0x44, 0x88, 0xc0, 0xf4, 0x6e, 0x67, 0x8b, 0x78, 0x24, 0x96, 0x65, 0xa2, - 0xd1, 0x4c, 0xb1, 0xdf, 0xac, 0x9d, 0xc8, 0x96, 0x37, 0x4d, 0x12, 0x38, 0x4d, 0xd3, 0xfe, 0x19, - 0x0b, 0x98, 0xb5, 0xfc, 0x19, 0x1c, 0x7f, 0x5f, 0x30, 0x8f, 0xbf, 0xb9, 0x3c, 0x0e, 0x94, 0x73, - 0xf2, 0xbd, 0xc2, 0xa7, 0xa5, 0x16, 0x06, 0x0f, 0x0e, 0xa4, 0xec, 0xdf, 0x5f, 0xe2, 0xfa, 0x3f, - 0x16, 0xdf, 0x90, 0x2a, 0x28, 0x00, 0xfa, 0x1e, 0x18, 0x6b, 0x38, 0x6d, 0xa7, 0xc1, 0xc3, 0xd8, - 0xe6, 0x6a, 0x7f, 0x8c, 0x4a, 0x0b, 0x2b, 0xa2, 0x06, 0xd7, 0x66, 0x7c, 0x46, 0x7e, 0xa5, 0x2c, - 0xee, 0xab, 0xc1, 0x50, 0x4d, 0xce, 0xef, 0xc2, 0xa4, 0x41, 0xec, 0x91, 0x5e, 0x7d, 0xbf, 0x87, - 0x1f, 0x17, 0xea, 0xc6, 0xb2, 0x07, 0xb3, 0xbe, 0xf6, 0x9f, 0x32, 0x47, 0x29, 0x4e, 0x7f, 0xb2, - 0xdf, 0x81, 0xc0, 0x38, 0xa9, 0xe6, 0x0d, 0x90, 0x22, 0x83, 0xbb, 0x29, 0xdb, 0xff, 0xd0, 0x82, - 0xc7, 0x75, 0x44, 0x2d, 0x5e, 0x43, 0x3f, 0x7d, 0x72, 0x05, 0xc6, 0x82, 0x36, 0x09, 0x9d, 0xe4, - 0x4e, 0x76, 0x55, 0x0e, 0xfa, 0x6d, 0x51, 0x7e, 0x2c, 0xe2, 0x09, 0x4a, 0xea, 0xb2, 0x1c, 0xab, - 0x9a, 0xc8, 0x86, 0x11, 0x36, 0x18, 0x91, 0x88, 0xa5, 0xc1, 0xcc, 0x14, 0xd9, 0xd3, 0x6a, 0x84, - 0x05, 0xc4, 0xfe, 0x7e, 0x8b, 0x2f, 0x2c, 0xbd, 0xeb, 0xe8, 0x7d, 0x98, 0xd9, 0xa3, 0xd7, 0xb7, - 0xd5, 0x07, 0xed, 0x90, 0xab, 0xd1, 0xe5, 0x38, 0x3d, 0xdf, 0x6f, 0x9c, 0xb4, 0x8f, 0x4c, 0x8c, - 0xd9, 0xd6, 0x53, 0xc4, 0x70, 0x17, 0x79, 0xfb, 0xcf, 0x0a, 0x7c, 0x27, 0x32, 0xa9, 0xee, 0x59, - 0x18, 0x6d, 0x07, 0xcd, 0x95, 0x6a, 0x05, 0x8b, 0x11, 0x52, 0xec, 0xaa, 0xc6, 0x8b, 0xb1, 0x84, - 0xa3, 0x6b, 0x00, 0xe4, 0x41, 0x4c, 0x42, 0xdf, 0xf1, 0x94, 0xe1, 0x87, 0x12, 0x9e, 0x56, 0x15, - 0x04, 0x6b, 0x58, 0xb4, 0x4e, 0x3b, 0x0c, 0xf6, 0xdd, 0x26, 0xf3, 0x36, 0x2c, 0x9a, 0x75, 0x6a, - 0x0a, 0x82, 0x35, 0x2c, 0x7a, 0x55, 0xee, 0xf8, 0x11, 0x3f, 0x00, 0x9d, 0x2d, 0x11, 0x20, 0x6f, - 0x2c, 0xb9, 0x2a, 0xdf, 0xd1, 0x81, 0xd8, 0xc4, 0x45, 0x4b, 0x30, 0x12, 0x3b, 0xcc, 0x9c, 0x61, - 0x38, 0xdf, 0x2c, 0x71, 0x93, 0x62, 0xe8, 0x71, 0x4d, 0x69, 0x05, 0x2c, 0x2a, 0xa2, 0x77, 0x24, - 0x0b, 0xe6, 0x2c, 0x59, 0xd8, 0x03, 0xe7, 0x2e, 0x5b, 0x9d, 0x7d, 0xeb, 0x3c, 0x58, 0xd8, 0x19, - 0x1b, 0xb4, 0xec, 0xef, 0x2b, 0x01, 0x24, 0xd2, 0x1e, 0xfa, 0xa0, 0x8b, 0x45, 0xbc, 0xd0, 0x5b, - 0x3e, 0x3c, 0x3d, 0xfe, 0x80, 0x7e, 0xc0, 0x82, 0x71, 0xc7, 0xf3, 0x82, 0x86, 0x13, 0xb3, 0x51, - 0x2e, 0xf4, 0x66, 0x51, 0xa2, 0xfd, 0xa5, 0xa4, 0x06, 0xef, 0xc2, 0xcb, 0xd2, 0x52, 0x41, 0x83, - 0xf4, 0xed, 0x85, 0xde, 0x30, 0xfa, 0x8c, 0xbc, 0x04, 0xf0, 0xe5, 0x31, 0x9f, 0xbe, 0x04, 0x94, - 0x18, 0x37, 0xd6, 0xe4, 0x7f, 0x74, 0xc7, 0x88, 0x24, 0x37, 0x94, 0x1f, 0x92, 0xc2, 0x10, 0x7a, - 0xfa, 0x05, 0x91, 0x43, 0x35, 0xdd, 0x2f, 0x6a, 0x38, 0x3f, 0x6e, 0x8b, 0x26, 0x5d, 0xf7, 0xf1, - 0x89, 0x7a, 0x0f, 0xa6, 0x9b, 0xe6, 0x71, 0x2b, 0x56, 0xd3, 0xa7, 0xf3, 0xe8, 0xa6, 0x4e, 0xe7, - 0xe4, 0x80, 0x4d, 0x01, 0x70, 0x9a, 0x30, 0xaa, 0x71, 0x0f, 0xb5, 0xaa, 0xbf, 0x1d, 0x08, 0xbb, - 0x72, 0x3b, 0x77, 0x2e, 0x0f, 0xa2, 0x98, 0xec, 0x51, 0xcc, 0xe4, 0x1c, 0xdd, 0x10, 0x75, 0xb1, - 0xa2, 0x82, 0xde, 0x82, 0x11, 0xe6, 0x36, 0x1c, 0xcd, 0x8d, 0xe5, 0xeb, 0x01, 0xcd, 0x88, 0x17, - 0xc9, 0xa6, 0x62, 0x7f, 0x23, 0x2c, 0x28, 0xa0, 0x1b, 0x32, 0x2c, 0x4e, 0x54, 0xf5, 0xef, 0x44, - 0x84, 0x85, 0xc5, 0x29, 0x2d, 0x7f, 0x32, 0x89, 0x78, 0xc3, 0xcb, 0x33, 0x23, 0x98, 0x1b, 0x35, - 0xa9, 0xbc, 0x22, 0xfe, 0xcb, 0xc0, 0xe8, 0x73, 0x90, 0xdf, 0x3d, 0x33, 0x78, 0x7a, 0x32, 0x9c, - 0x77, 0x4d, 0x12, 0x38, 0x4d, 0xf3, 0x4c, 0x8f, 0xcf, 0x79, 0x1f, 0x66, 0xd2, 0x1b, 0xeb, 0x91, - 0x1e, 0xd7, 0x7f, 0x34, 0x04, 0x53, 0xe6, 0x42, 0x40, 0x8b, 0x50, 0x12, 0x44, 0x54, 0x10, 0x4f, - 0xb5, 0xb6, 0xd7, 0x25, 0x00, 0x27, 0x38, 0x2c, 0x88, 0x29, 0xab, 0xae, 0xd9, 0x01, 0x26, 0x41, - 0x4c, 0x15, 0x04, 0x6b, 0x58, 0x54, 0x88, 0xde, 0x0a, 0x82, 0x58, 0x1d, 0x05, 0x6a, 0xb5, 0x2c, - 0xb3, 0x52, 0x2c, 0xa0, 0xf4, 0x08, 0xd8, 0x25, 0xa1, 0x4f, 0x3c, 0x53, 0x93, 0xa9, 0x8e, 0x80, - 0x9b, 0x3a, 0x10, 0x9b, 0xb8, 0xf4, 0x48, 0x0b, 0x22, 0xb6, 0xfc, 0x84, 0xa8, 0x9e, 0xd8, 0x55, - 0xd6, 0xb9, 0xdb, 0xbc, 0x84, 0xa3, 0x2f, 0xc1, 0xe3, 0xca, 0xcb, 0x1d, 0x73, 0xcd, 0xb0, 0x6c, - 0x71, 0xc4, 0xb8, 0x59, 0x3f, 0xbe, 0x92, 0x8d, 0x86, 0xf3, 0xea, 0xa3, 0x37, 0x61, 0x4a, 0x88, - 0xc0, 0x92, 0xe2, 0xa8, 0x69, 0xac, 0x70, 0xd3, 0x80, 0xe2, 0x14, 0x36, 0xaa, 0xc0, 0x0c, 0x2d, - 0x61, 0x52, 0xa8, 0xa4, 0xc0, 0xbd, 0xf5, 0xd5, 0x59, 0x7f, 0x33, 0x05, 0xc7, 0x5d, 0x35, 0xd0, - 0x12, 0x4c, 0x73, 0x19, 0x85, 0xde, 0x29, 0xd9, 0x3c, 0x08, 0x77, 0x0f, 0xb5, 0x11, 0x6e, 0x9b, - 0x60, 0x9c, 0xc6, 0x47, 0xaf, 0xc3, 0x84, 0x13, 0x36, 0x76, 0xdc, 0x98, 0x34, 0xe2, 0x4e, 0xc8, - 0xfd, 0x40, 0x34, 0x6b, 0x8f, 0x25, 0x0d, 0x86, 0x0d, 0x4c, 0xfb, 0x03, 0x38, 0x97, 0xe1, 0x29, - 0x46, 0x17, 0x8e, 0xd3, 0x76, 0xe5, 0x37, 0xa5, 0x2c, 0x24, 0x97, 0x6a, 0x55, 0xf9, 0x35, 0x1a, - 0x16, 0x5d, 0x9d, 0x4c, 0x25, 0xae, 0x65, 0x2f, 0x50, 0xab, 0x73, 0x4d, 0x02, 0x70, 0x82, 0x63, - 0xff, 0x16, 0x80, 0xa6, 0xd0, 0x19, 0xc0, 0x3e, 0xee, 0x75, 0x98, 0x90, 0x29, 0x37, 0xb4, 0x50, - 0xef, 0xea, 0x33, 0xaf, 0x6b, 0x30, 0x6c, 0x60, 0xd2, 0xbe, 0xf9, 0x2a, 0x50, 0x7d, 0xca, 0x1e, - 0x33, 0x09, 0x53, 0x9f, 0xe0, 0xa0, 0x17, 0x60, 0x2c, 0x22, 0xde, 0xf6, 0x2d, 0xd7, 0xdf, 0x15, - 0x0b, 0x5b, 0x71, 0xe1, 0xba, 0x28, 0xc7, 0x0a, 0x03, 0x2d, 0x43, 0xb1, 0xe3, 0x36, 0xc5, 0x52, - 0x96, 0x07, 0x7e, 0xf1, 0x4e, 0xb5, 0x72, 0x7c, 0x58, 0x7e, 0x3a, 0x2f, 0x93, 0x08, 0xbd, 0xda, - 0x47, 0x0b, 0x74, 0xfb, 0xd1, 0xca, 0x59, 0x6f, 0x03, 0x23, 0x27, 0x7c, 0x1b, 0xb8, 0x06, 0x20, - 0xbe, 0x5a, 0xae, 0xe5, 0x62, 0x32, 0x6b, 0xd7, 0x15, 0x04, 0x6b, 0x58, 0x28, 0x82, 0xd9, 0x46, - 0x48, 0x1c, 0x79, 0x87, 0xe6, 0x3e, 0x4f, 0x63, 0x0f, 0xaf, 0x20, 0x58, 0x49, 0x13, 0xc3, 0xdd, - 0xf4, 0x51, 0x00, 0xb3, 0x4d, 0x11, 0x54, 0x21, 0x69, 0xb4, 0x74, 0x72, 0x47, 0x2b, 0x66, 0x90, - 0x93, 0x26, 0x84, 0xbb, 0x69, 0xa3, 0x2f, 0xc3, 0xbc, 0x2c, 0xec, 0x8e, 0x63, 0xc1, 0xb6, 0x4b, - 0x91, 0xc7, 0x5f, 0xaf, 0xe4, 0x62, 0xe1, 0x1e, 0x14, 0x10, 0x86, 0x11, 0xf6, 0x96, 0x14, 0xcd, - 0x8d, 0xb3, 0x73, 0xee, 0xb9, 0x7c, 0x65, 0x00, 0x5d, 0xeb, 0x0b, 0xec, 0x1d, 0x4a, 0x98, 0x94, - 0x27, 0xcf, 0x72, 0xac, 0x10, 0x0b, 0x4a, 0x68, 0x1b, 0xc6, 0x1d, 0xdf, 0x0f, 0x62, 0x87, 0x8b, - 0x50, 0x13, 0xf9, 0xb2, 0x9f, 0x46, 0x78, 0x29, 0xa9, 0xc1, 0xa9, 0x2b, 0x2b, 0x55, 0x0d, 0x82, - 0x75, 0xc2, 0xe8, 0x3e, 0x4c, 0x07, 0xf7, 0x29, 0x73, 0x94, 0x5a, 0x8a, 0x68, 0x6e, 0x92, 0xb5, - 0xf5, 0xca, 0x80, 0x7a, 0x5a, 0xa3, 0xb2, 0xc6, 0xb5, 0x4c, 0xa2, 0x38, 0xdd, 0x0a, 0x5a, 0x30, - 0xb4, 0xd5, 0x53, 0x89, 0x3b, 0x4b, 0xa2, 0xad, 0xd6, 0x95, 0xd3, 0x2c, 0x2e, 0x0a, 0x37, 0x91, - 0x66, 0xbb, 0x7f, 0x3a, 0x15, 0x17, 0x25, 0x01, 0x61, 0x1d, 0x0f, 0xed, 0xc0, 0x44, 0xf2, 0x64, - 0x15, 0x46, 0x2c, 0x2a, 0xdb, 0xf8, 0xb5, 0x6b, 0x83, 0x7d, 0x5c, 0x55, 0xab, 0xc9, 0x6f, 0x0e, - 0x7a, 0x09, 0x36, 0x28, 0xcf, 0x7f, 0x1b, 0x8c, 0x6b, 0x13, 0x7b, 0xa2, 0x28, 0xb8, 0x6f, 0xc2, - 0x4c, 0x7a, 0xea, 0x4e, 0xe4, 0x41, 0xf0, 0xbf, 0x0a, 0x30, 0x9d, 0xf1, 0x72, 0xc5, 0xb2, 0x91, - 0xa4, 0x18, 0x6a, 0x92, 0x7c, 0xc4, 0x64, 0x8b, 0x85, 0x01, 0xd8, 0xa2, 0xe4, 0xd1, 0xc5, 0x5c, - 0x1e, 0x2d, 0x58, 0xe1, 0xd0, 0x87, 0x61, 0x85, 0xe6, 0xe9, 0x33, 0x3c, 0xd0, 0xe9, 0x73, 0x0a, - 0xec, 0xd3, 0x38, 0xc0, 0x46, 0x07, 0x38, 0xc0, 0x7e, 0xb4, 0x00, 0x33, 0x69, 0x0b, 0xdf, 0x33, - 0x78, 0xef, 0x78, 0xcb, 0x78, 0xef, 0xc8, 0xce, 0xed, 0x93, 0xb6, 0x3b, 0xce, 0x7b, 0xfb, 0xc0, - 0xa9, 0xb7, 0x8f, 0xe7, 0x06, 0xa2, 0xd6, 0xfb, 0x1d, 0xe4, 0x1f, 0x15, 0xe0, 0x42, 0xba, 0xca, - 0x8a, 0xe7, 0xb8, 0x7b, 0x67, 0x30, 0x36, 0xb7, 0x8d, 0xb1, 0x79, 0x71, 0x90, 0xaf, 0x61, 0x5d, - 0xcb, 0x1d, 0xa0, 0x7b, 0xa9, 0x01, 0x5a, 0x1c, 0x9c, 0x64, 0xef, 0x51, 0xfa, 0x66, 0x11, 0x2e, - 0x65, 0xd6, 0x4b, 0x9e, 0x0b, 0xd6, 0x8c, 0xe7, 0x82, 0x6b, 0xa9, 0xe7, 0x02, 0xbb, 0x77, 0xed, - 0xd3, 0x79, 0x3f, 0x10, 0xee, 0xd0, 0x2c, 0x62, 0xe8, 0x43, 0xbe, 0x1d, 0x18, 0xee, 0xd0, 0x8a, - 0x10, 0x36, 0xe9, 0xfe, 0x55, 0x7a, 0x33, 0xf8, 0x2d, 0x0b, 0x2e, 0x66, 0xce, 0xcd, 0x19, 0xe8, - 0xd5, 0x37, 0x4c, 0xbd, 0xfa, 0xb3, 0x03, 0xaf, 0xd6, 0x1c, 0x45, 0xfb, 0x1f, 0x17, 0x73, 0xbe, - 0x85, 0x69, 0x26, 0x6f, 0xc3, 0xb8, 0xd3, 0x68, 0x90, 0x28, 0x5a, 0x0f, 0x9a, 0x2a, 0x82, 0xe6, - 0x8b, 0x4c, 0xda, 0x48, 0x8a, 0x8f, 0x0f, 0xcb, 0xf3, 0x69, 0x12, 0x09, 0x18, 0xeb, 0x14, 0xcc, - 0xa0, 0xbf, 0x85, 0x53, 0x0d, 0xfa, 0x7b, 0x0d, 0x60, 0x5f, 0xe9, 0x2b, 0xd2, 0x6a, 0x4e, 0x4d, - 0x93, 0xa1, 0x61, 0xa1, 0xef, 0x62, 0xb7, 0x00, 0x6e, 0x0c, 0xc4, 0x97, 0xe2, 0xcb, 0x03, 0xce, - 0x95, 0x6e, 0x58, 0xc4, 0xe3, 0x6e, 0x28, 0x95, 0xb0, 0x22, 0x89, 0xbe, 0x03, 0x66, 0x22, 0x1e, - 0xd6, 0x69, 0xc5, 0x73, 0x22, 0xe6, 0xc4, 0x25, 0x56, 0x21, 0x0b, 0xa6, 0x51, 0x4f, 0xc1, 0x70, - 0x17, 0x36, 0x5a, 0x93, 0x1f, 0xc5, 0x62, 0x50, 0xf1, 0x85, 0x79, 0x25, 0xf9, 0x20, 0x91, 0x0b, - 0xed, 0x7c, 0x7a, 0xf8, 0xd9, 0xc0, 0x6b, 0x35, 0xed, 0x1f, 0x1d, 0x82, 0x27, 0x7a, 0x30, 0x31, - 0xb4, 0x64, 0x1a, 0x01, 0x3c, 0x9f, 0xd6, 0xff, 0xcd, 0x67, 0x56, 0x36, 0x14, 0x82, 0xa9, 0xb5, - 0x52, 0xf8, 0xd0, 0x6b, 0xe5, 0x87, 0x2c, 0x4d, 0x33, 0xcb, 0x4d, 0x85, 0xbf, 0x70, 0x42, 0xe6, - 0x7c, 0x8a, 0xaa, 0xda, 0xed, 0x0c, 0x7d, 0xe7, 0xb5, 0x81, 0xbb, 0x33, 0xb0, 0x02, 0xf4, 0x6c, - 0x9f, 0x8c, 0xbe, 0x6a, 0xc1, 0xd3, 0x99, 0xfd, 0x35, 0x8c, 0x96, 0x16, 0xa1, 0xd4, 0xa0, 0x85, - 0x9a, 0x63, 0x68, 0xe2, 0x31, 0x2f, 0x01, 0x38, 0xc1, 0x31, 0x6c, 0x93, 0x0a, 0x7d, 0x6d, 0x93, - 0xfe, 0xad, 0x05, 0x5d, 0x0b, 0xf8, 0x0c, 0x38, 0x69, 0xd5, 0xe4, 0xa4, 0x9f, 0x1c, 0x64, 0x2e, - 0x73, 0x98, 0xe8, 0xef, 0x4f, 0xc3, 0x63, 0x39, 0x9e, 0x60, 0xfb, 0x30, 0xdb, 0x6a, 0x10, 0xd3, - 0xe5, 0x56, 0x7c, 0x4c, 0xa6, 0x77, 0x72, 0x4f, 0xff, 0x5c, 0x7e, 0x21, 0xee, 0x42, 0xc1, 0xdd, - 0x4d, 0xa0, 0xaf, 0x5a, 0x70, 0xde, 0xb9, 0x1f, 0x75, 0xa5, 0x2a, 0x15, 0x6b, 0xe6, 0x95, 0x4c, - 0x3d, 0x6d, 0x9f, 0xd4, 0xa6, 0x3c, 0xab, 0x57, 0x16, 0x16, 0xce, 0x6c, 0x0b, 0x61, 0x11, 0xf4, - 0x98, 0xca, 0xdb, 0x3d, 0x9c, 0xc2, 0xb3, 0x5c, 0xf6, 0x38, 0x4f, 0x95, 0x10, 0xac, 0xe8, 0xa0, - 0xbb, 0x50, 0x6a, 0x49, 0x3f, 0x5a, 0xc1, 0xb3, 0x33, 0x0f, 0xc1, 0x4c, 0x67, 0x5b, 0xee, 0x3b, - 0xa2, 0x40, 0x38, 0x21, 0x85, 0xde, 0x84, 0xa2, 0xbf, 0x1d, 0xf5, 0x4a, 0x87, 0x95, 0xb2, 0xe5, - 0xe3, 0x01, 0x17, 0x36, 0xd6, 0xea, 0x98, 0x56, 0x44, 0x37, 0xa0, 0x18, 0x6e, 0x35, 0xc5, 0xd3, - 0x42, 0xa6, 0x5c, 0x8a, 0x97, 0x2b, 0xd9, 0x8b, 0x84, 0x53, 0xc2, 0xcb, 0x15, 0x4c, 0x49, 0xa0, - 0x1a, 0x0c, 0x33, 0xa7, 0x29, 0xf1, 0x82, 0x90, 0x29, 0x90, 0xf6, 0x70, 0x3e, 0xe4, 0x51, 0x19, - 0x18, 0x02, 0xe6, 0x84, 0xd0, 0x5b, 0x30, 0xd2, 0x60, 0x19, 0xa3, 0x84, 0xe2, 0x27, 0x3b, 0x5c, - 0x57, 0x57, 0x4e, 0x29, 0xfe, 0x82, 0xca, 0xcb, 0xb1, 0xa0, 0x80, 0x36, 0x61, 0xa4, 0x41, 0xda, - 0x3b, 0xdb, 0x91, 0xd0, 0xe7, 0x7c, 0x26, 0x93, 0x56, 0x8f, 0x04, 0x69, 0x82, 0x2a, 0xc3, 0xc0, - 0x82, 0x16, 0xfa, 0x1c, 0x14, 0xb6, 0x1b, 0xc2, 0x93, 0x2a, 0xf3, 0x0d, 0xc1, 0x8c, 0x94, 0xb1, - 0x3c, 0x72, 0x74, 0x58, 0x2e, 0xac, 0xad, 0xe0, 0xc2, 0x76, 0x03, 0x6d, 0xc0, 0xe8, 0x36, 0xf7, - 0xad, 0x17, 0x01, 0x6c, 0x3e, 0x9d, 0xed, 0xf6, 0xdf, 0xe5, 0x7e, 0xcf, 0x3d, 0x80, 0x04, 0x00, - 0x4b, 0x22, 0x2c, 0x5e, 0xb0, 0x8a, 0x11, 0x20, 0x02, 0xe7, 0x2f, 0x9c, 0x2c, 0xae, 0x83, 0x50, - 0x73, 0x28, 0x2a, 0x58, 0xa3, 0x88, 0xbe, 0x02, 0x25, 0x47, 0xa6, 0xc6, 0x14, 0x41, 0x70, 0x5e, - 0xce, 0xdc, 0x8e, 0xbd, 0xb3, 0x86, 0xf2, 0xb5, 0xac, 0x90, 0x70, 0x42, 0x14, 0xed, 0xc2, 0xe4, - 0x7e, 0xd4, 0xde, 0x21, 0x72, 0xfb, 0xb2, 0x98, 0x38, 0x39, 0xc7, 0xd5, 0x5d, 0x81, 0xe8, 0x86, - 0x71, 0xc7, 0xf1, 0xba, 0x38, 0x0e, 0x73, 0x1c, 0xbb, 0xab, 0x13, 0xc3, 0x26, 0x6d, 0x3a, 0xfc, - 0xef, 0x77, 0x82, 0xad, 0x83, 0x98, 0x88, 0x48, 0xfb, 0x99, 0xc3, 0xff, 0x36, 0x47, 0xe9, 0x1e, - 0x7e, 0x01, 0xc0, 0x92, 0x08, 0xdd, 0xe0, 0x8e, 0x4c, 0x3b, 0x2b, 0x74, 0x39, 0xcf, 0xe6, 0x0e, - 0x4f, 0x57, 0x7f, 0x93, 0x41, 0x61, 0x9c, 0x31, 0x21, 0xc5, 0x38, 0x62, 0x7b, 0x27, 0x88, 0x03, - 0x3f, 0xc5, 0x8d, 0x67, 0xf3, 0x39, 0x62, 0x2d, 0x03, 0xbf, 0x9b, 0x23, 0x66, 0x61, 0xe1, 0xcc, - 0xb6, 0x50, 0x13, 0xa6, 0xda, 0x41, 0x18, 0xdf, 0x0f, 0x42, 0xb9, 0xbe, 0x50, 0x8f, 0x4b, 0xbe, - 0x81, 0x29, 0x5a, 0x64, 0x76, 0xe0, 0x26, 0x04, 0xa7, 0x68, 0xa2, 0x2f, 0xc2, 0x68, 0xd4, 0x70, - 0x3c, 0x52, 0xbd, 0x3d, 0x77, 0x2e, 0xff, 0xa8, 0xa9, 0x73, 0x94, 0x9c, 0xd5, 0xc5, 0x26, 0x47, - 0xa0, 0x60, 0x49, 0x0e, 0xad, 0xc1, 0x30, 0x4b, 0xdf, 0xc2, 0x92, 0x04, 0xe4, 0x04, 0x5b, 0xeb, - 0xb2, 0x95, 0xe6, 0x1c, 0x89, 0x15, 0x63, 0x5e, 0x9d, 0xee, 0x01, 0x21, 0xeb, 0x06, 0xd1, 0xdc, - 0x85, 0xfc, 0x3d, 0x20, 0x44, 0xe4, 0xdb, 0xf5, 0x5e, 0x7b, 0x40, 0x21, 0xe1, 0x84, 0x28, 0xe5, - 0xc7, 0x94, 0x87, 0x3e, 0x96, 0xcf, 0x8f, 0xf3, 0x39, 0x28, 0xe3, 0xc7, 0x94, 0x7f, 0x52, 0x12, - 0xf6, 0x1f, 0x8c, 0x76, 0xcb, 0x27, 0xec, 0x76, 0xf4, 0x7d, 0x56, 0x97, 0xe9, 0xc0, 0x67, 0x07, - 0x55, 0xd6, 0x9c, 0xa2, 0x64, 0xfa, 0x55, 0x0b, 0x1e, 0x6b, 0x67, 0x7e, 0x88, 0x38, 0xec, 0x07, - 0xd3, 0xf9, 0xf0, 0x4f, 0x57, 0x89, 0x3c, 0xb2, 0xe1, 0x38, 0xa7, 0xa5, 0xb4, 0xf4, 0x5f, 0xfc, - 0xd0, 0xd2, 0xff, 0x3a, 0x8c, 0x31, 0x81, 0x32, 0x89, 0xec, 0x37, 0x90, 0x01, 0x1e, 0x13, 0x1b, - 0x56, 0x44, 0x45, 0xac, 0x48, 0xa0, 0x1f, 0xb6, 0xe0, 0xa9, 0x74, 0xd7, 0x31, 0x61, 0x60, 0x11, - 0x25, 0x9a, 0x5f, 0xcc, 0xd6, 0xc4, 0xf7, 0x3f, 0x55, 0xeb, 0x85, 0x7c, 0xdc, 0x0f, 0x01, 0xf7, - 0x6e, 0x0c, 0x55, 0x32, 0x6e, 0x86, 0x23, 0xe6, 0xcb, 0xe2, 0x00, 0xb7, 0xc3, 0x57, 0x60, 0x62, - 0x2f, 0xe8, 0xf8, 0xd2, 0x3b, 0x46, 0xf8, 0x3e, 0x33, 0x2d, 0xf6, 0xba, 0x56, 0x8e, 0x0d, 0xac, - 0xd4, 0x9d, 0x72, 0xec, 0x61, 0xef, 0x94, 0xe8, 0xdd, 0x54, 0x9a, 0xf8, 0x52, 0xbe, 0x6c, 0x21, - 0xae, 0xdf, 0x27, 0x48, 0x16, 0x7f, 0xb6, 0xf7, 0xa0, 0xaf, 0x5b, 0x19, 0x02, 0x3c, 0xbf, 0x19, - 0x7f, 0xde, 0xbc, 0x19, 0x5f, 0x49, 0xdf, 0x8c, 0xbb, 0x34, 0xa1, 0xc6, 0xa5, 0x78, 0xf0, 0x18, - 0xfd, 0x83, 0x06, 0x68, 0xb4, 0x3d, 0xb8, 0xdc, 0xef, 0x58, 0x62, 0xa6, 0x92, 0x4d, 0x65, 0x43, - 0x90, 0x98, 0x4a, 0x36, 0xab, 0x15, 0xcc, 0x20, 0x83, 0x46, 0xf0, 0xb1, 0xff, 0xbb, 0x05, 0xc5, - 0x5a, 0xd0, 0x3c, 0x03, 0xcd, 0xee, 0x17, 0x0c, 0xcd, 0xee, 0x13, 0x39, 0xe9, 0xfb, 0x73, 0xf5, - 0xb8, 0xab, 0x29, 0x3d, 0xee, 0x53, 0x79, 0x04, 0x7a, 0x6b, 0x6d, 0x7f, 0xba, 0x08, 0xe3, 0xb5, - 0xa0, 0xa9, 0x6c, 0xee, 0xff, 0xfd, 0xc3, 0xd8, 0xdc, 0xe7, 0xc6, 0x5b, 0xd6, 0x28, 0x33, 0x0b, - 0x4b, 0xe9, 0xce, 0xfb, 0x97, 0xcc, 0xf4, 0xfe, 0x1e, 0x71, 0x5b, 0x3b, 0x31, 0x69, 0xa6, 0x3f, - 0xe7, 0xec, 0x4c, 0xef, 0xff, 0xab, 0x05, 0xd3, 0xa9, 0xd6, 0x91, 0x97, 0xe5, 0x1b, 0xf8, 0x90, - 0x1a, 0xbd, 0xd9, 0xbe, 0xce, 0x84, 0x0b, 0x00, 0xea, 0xd9, 0x4c, 0x6a, 0xbb, 0x98, 0xd4, 0xaf, - 0xde, 0xd5, 0x22, 0xac, 0x61, 0xa0, 0x57, 0x61, 0x3c, 0x0e, 0xda, 0x81, 0x17, 0xb4, 0x0e, 0x6e, - 0x12, 0x19, 0x33, 0x4a, 0x3d, 0x6e, 0x6e, 0x26, 0x20, 0xac, 0xe3, 0xd9, 0x3f, 0x5b, 0xe4, 0x1f, - 0xea, 0xc7, 0xee, 0xb7, 0xd6, 0xe4, 0xc7, 0x7b, 0x4d, 0x7e, 0xd3, 0x82, 0x19, 0xda, 0x3a, 0xb3, - 0x5e, 0x93, 0x87, 0xad, 0xca, 0x15, 0x66, 0xf5, 0xc8, 0x15, 0x76, 0x85, 0xf2, 0xae, 0x66, 0xd0, - 0x89, 0x85, 0xb6, 0x4c, 0x63, 0x4e, 0xb4, 0x14, 0x0b, 0xa8, 0xc0, 0x23, 0x61, 0x28, 0x3c, 0xfe, - 0x74, 0x3c, 0x12, 0x86, 0x58, 0x40, 0x65, 0x2a, 0xb1, 0xa1, 0x9c, 0x54, 0x62, 0x2c, 0x02, 0xa6, - 0xb0, 0x98, 0x12, 0x62, 0x8f, 0x16, 0x01, 0x53, 0x9a, 0x52, 0x25, 0x38, 0xf6, 0x2f, 0x14, 0x61, - 0xa2, 0x16, 0x34, 0x93, 0x87, 0xab, 0x57, 0x8c, 0x87, 0xab, 0xcb, 0xa9, 0x87, 0xab, 0x19, 0x1d, - 0xf7, 0x5b, 0xcf, 0x54, 0x1f, 0xd5, 0x33, 0xd5, 0xbf, 0xb1, 0xd8, 0xac, 0x55, 0x36, 0xea, 0x22, - 0x19, 0xf7, 0x4b, 0x30, 0xce, 0x18, 0x12, 0x73, 0x31, 0x95, 0xaf, 0x39, 0x2c, 0xa3, 0xc5, 0x46, - 0x52, 0x8c, 0x75, 0x1c, 0x74, 0x15, 0xc6, 0x22, 0xe2, 0x84, 0x8d, 0x1d, 0xc5, 0xe3, 0xc4, 0x5b, - 0x07, 0x2f, 0xc3, 0x0a, 0x8a, 0xde, 0x4e, 0x82, 0x2f, 0x16, 0xf3, 0xd3, 0x4a, 0xeb, 0xfd, 0xe1, - 0x5b, 0x24, 0x3f, 0xe2, 0xa2, 0x7d, 0x0f, 0x50, 0x37, 0xfe, 0x00, 0x66, 0x64, 0x65, 0x33, 0xcc, - 0x5a, 0xa9, 0x2b, 0xc4, 0xda, 0x9f, 0x5b, 0x30, 0x55, 0x0b, 0x9a, 0x74, 0xeb, 0xfe, 0x55, 0xda, - 0xa7, 0x7a, 0xe4, 0xd9, 0x91, 0x1e, 0x91, 0x67, 0xff, 0xb1, 0x05, 0xa3, 0xb5, 0xa0, 0x79, 0x06, - 0x3a, 0xf6, 0xcf, 0x9b, 0x3a, 0xf6, 0xc7, 0x73, 0x96, 0x44, 0x8e, 0x5a, 0xfd, 0x97, 0x8a, 0x30, - 0x49, 0xfb, 0x19, 0xb4, 0xe4, 0x2c, 0x19, 0x23, 0x62, 0x0d, 0x30, 0x22, 0x54, 0xcc, 0x0d, 0x3c, - 0x2f, 0xb8, 0x9f, 0x9e, 0xb1, 0x35, 0x56, 0x8a, 0x05, 0x14, 0xbd, 0x00, 0x63, 0xed, 0x90, 0xec, - 0xbb, 0x41, 0x27, 0x4a, 0x7b, 0x53, 0xd7, 0x44, 0x39, 0x56, 0x18, 0xf4, 0xde, 0x15, 0xb9, 0x7e, - 0x83, 0x48, 0xfb, 0xb2, 0x21, 0x66, 0x5f, 0xc6, 0x43, 0xca, 0x6b, 0xe5, 0xd8, 0xc0, 0x42, 0xf7, - 0xa0, 0xc4, 0xfe, 0x33, 0x8e, 0x72, 0xf2, 0x24, 0x67, 0x22, 0x8f, 0x8b, 0x20, 0x80, 0x13, 0x5a, - 0xe8, 0x1a, 0x40, 0x2c, 0x2d, 0xe1, 0x22, 0xe1, 0xec, 0xaf, 0x64, 0x6d, 0x65, 0x23, 0x17, 0x61, - 0x0d, 0x0b, 0x3d, 0x0f, 0xa5, 0xd8, 0x71, 0xbd, 0x5b, 0xae, 0x4f, 0x22, 0x61, 0x49, 0x28, 0xd2, - 0xb4, 0x88, 0x42, 0x9c, 0xc0, 0xa9, 0xac, 0xc3, 0x42, 0x49, 0xf0, 0x14, 0x89, 0x63, 0x0c, 0x9b, - 0xc9, 0x3a, 0xb7, 0x54, 0x29, 0xd6, 0x30, 0xec, 0xd7, 0xe1, 0x42, 0x2d, 0x68, 0xd6, 0x82, 0x30, - 0x5e, 0x0b, 0xc2, 0xfb, 0x4e, 0xd8, 0x94, 0xf3, 0x57, 0x96, 0x19, 0x43, 0x28, 0xef, 0x19, 0xe6, - 0x3b, 0xd3, 0xc8, 0x05, 0xf2, 0x32, 0x93, 0x76, 0x4e, 0xe8, 0xf6, 0xf5, 0xbf, 0x0b, 0x8c, 0x51, - 0xa4, 0xf2, 0x76, 0xa2, 0x2f, 0xc3, 0x54, 0x44, 0x6e, 0xb9, 0x7e, 0xe7, 0x81, 0xbc, 0x1f, 0xf7, - 0xf0, 0xa9, 0xab, 0xaf, 0xea, 0x98, 0x5c, 0xcb, 0x66, 0x96, 0xe1, 0x14, 0x35, 0x3a, 0x84, 0x61, - 0xc7, 0x5f, 0x8a, 0xee, 0x44, 0x24, 0x14, 0x79, 0x23, 0xd9, 0x10, 0x62, 0x59, 0x88, 0x13, 0x38, - 0x5d, 0x32, 0xec, 0xcf, 0x46, 0xe0, 0xe3, 0x20, 0x88, 0xe5, 0x22, 0x63, 0x99, 0xc7, 0xb4, 0x72, - 0x6c, 0x60, 0xa1, 0x35, 0x40, 0x51, 0xa7, 0xdd, 0xf6, 0xd8, 0x03, 0xb8, 0xe3, 0x5d, 0x0f, 0x83, - 0x4e, 0x9b, 0x3f, 0x3e, 0x8a, 0xa4, 0x5d, 0xf5, 0x2e, 0x28, 0xce, 0xa8, 0x41, 0x19, 0xc3, 0x76, - 0xc4, 0x7e, 0x8b, 0x68, 0x12, 0x5c, 0xf3, 0x5d, 0x67, 0x45, 0x58, 0xc2, 0xe8, 0x3c, 0xb3, 0xe6, - 0x39, 0xe6, 0x48, 0x32, 0xcf, 0x58, 0x95, 0x62, 0x0d, 0xc3, 0xfe, 0x1e, 0x76, 0xc0, 0xb0, 0xf4, - 0x80, 0x71, 0x27, 0x24, 0x68, 0x0f, 0x26, 0xdb, 0xec, 0xe8, 0x17, 0x81, 0xd6, 0xc5, 0x80, 0x3f, - 0x9c, 0x9d, 0x21, 0x4f, 0x17, 0xa6, 0x93, 0xc3, 0x26, 0x75, 0xfb, 0xa7, 0x67, 0x18, 0x1f, 0xab, - 0xf3, 0xeb, 0xdf, 0xa8, 0xf0, 0x1e, 0x10, 0xb2, 0xee, 0x7c, 0xbe, 0x1e, 0x22, 0x39, 0x72, 0x84, - 0x07, 0x02, 0x96, 0x75, 0xd1, 0xdb, 0xec, 0x95, 0x97, 0x33, 0x8f, 0x7e, 0x79, 0xc6, 0x39, 0x96, - 0xf1, 0xa0, 0x2b, 0x2a, 0x62, 0x8d, 0x08, 0xba, 0x05, 0x93, 0x22, 0x9b, 0x9c, 0x50, 0x34, 0x15, - 0x0d, 0x45, 0xc2, 0x24, 0xd6, 0x81, 0xc7, 0xe9, 0x02, 0x6c, 0x56, 0x46, 0x2d, 0x78, 0x4a, 0x4b, - 0xad, 0x9a, 0x61, 0xeb, 0xca, 0x79, 0xd1, 0xd3, 0x47, 0x87, 0xe5, 0xa7, 0x36, 0x7b, 0x21, 0xe2, - 0xde, 0x74, 0xd0, 0x6d, 0xb8, 0xe0, 0x34, 0x62, 0x77, 0x9f, 0x54, 0x88, 0xd3, 0xf4, 0x5c, 0x9f, - 0x98, 0xe1, 0x48, 0x2e, 0x1e, 0x1d, 0x96, 0x2f, 0x2c, 0x65, 0x21, 0xe0, 0xec, 0x7a, 0xe8, 0xf3, - 0x50, 0x6a, 0xfa, 0x91, 0x18, 0x83, 0x11, 0x23, 0x6b, 0x70, 0xa9, 0xb2, 0x51, 0x57, 0xdf, 0x9f, - 0xfc, 0xc1, 0x49, 0x05, 0xd4, 0xe2, 0xca, 0x26, 0x75, 0xb7, 0x1b, 0xed, 0x8a, 0x31, 0x93, 0xd6, - 0x12, 0x18, 0x7e, 0x7a, 0x5c, 0xcb, 0xaa, 0x2c, 0xc9, 0x0d, 0x17, 0x3e, 0x83, 0x30, 0x7a, 0x0b, - 0x10, 0x15, 0x7e, 0xdc, 0x06, 0x59, 0x6a, 0xb0, 0x78, 0xf7, 0x4c, 0x37, 0x37, 0x66, 0xb8, 0x45, - 0xa1, 0x7a, 0x17, 0x06, 0xce, 0xa8, 0x85, 0x6e, 0x50, 0x0e, 0xa4, 0x97, 0x0a, 0xc3, 0x7f, 0x29, - 0x30, 0xcf, 0x55, 0x48, 0x3b, 0x24, 0x0d, 0x27, 0x26, 0x4d, 0x93, 0x22, 0x4e, 0xd5, 0xa3, 0xe7, - 0x93, 0x4a, 0x7d, 0x05, 0xa6, 0xb9, 0x7a, 0x77, 0xfa, 0x2b, 0x7a, 0xd7, 0xdc, 0x09, 0xa2, 0x78, - 0x83, 0xc4, 0xf7, 0x83, 0x70, 0x57, 0xc4, 0x10, 0x4c, 0xc2, 0xd9, 0x26, 0x20, 0xac, 0xe3, 0x51, - 0xd9, 0x92, 0x3d, 0xb3, 0x56, 0x2b, 0xec, 0xd5, 0x6b, 0x2c, 0xd9, 0x27, 0x37, 0x78, 0x31, 0x96, - 0x70, 0x89, 0x5a, 0xad, 0xad, 0xb0, 0x17, 0xac, 0x14, 0x6a, 0xb5, 0xb6, 0x82, 0x25, 0x1c, 0x91, - 0xee, 0x8c, 0xcc, 0x53, 0xf9, 0x9a, 0xc2, 0x6e, 0x3e, 0x3e, 0x60, 0x52, 0x66, 0x1f, 0x66, 0x54, - 0x2e, 0x68, 0x1e, 0x5c, 0x31, 0x9a, 0x9b, 0x66, 0x8b, 0x64, 0xf0, 0xc8, 0x8c, 0x4a, 0xf7, 0x5a, - 0x4d, 0x51, 0xc2, 0x5d, 0xb4, 0x8d, 0x30, 0x37, 0x33, 0x7d, 0x53, 0x97, 0x2d, 0x42, 0x29, 0xea, - 0x6c, 0x35, 0x83, 0x3d, 0xc7, 0xf5, 0xd9, 0x83, 0x93, 0x26, 0xb8, 0xd4, 0x25, 0x00, 0x27, 0x38, - 0x68, 0x0d, 0xc6, 0x1c, 0xa9, 0x58, 0x45, 0xf9, 0x71, 0x2f, 0x94, 0x3a, 0x95, 0x89, 0xe5, 0x4a, - 0x95, 0xaa, 0xea, 0xa2, 0x37, 0x60, 0x52, 0xb8, 0x66, 0x0a, 0xab, 0xea, 0x73, 0xa6, 0x17, 0x4f, - 0x5d, 0x07, 0x62, 0x13, 0x17, 0x7d, 0x17, 0x4c, 0x51, 0x2a, 0x09, 0x63, 0x9b, 0x3b, 0x3f, 0x08, - 0x47, 0xd4, 0x52, 0xd2, 0xe8, 0x95, 0x71, 0x8a, 0x18, 0x6a, 0xc2, 0x93, 0x4e, 0x27, 0x0e, 0x98, - 0x72, 0xda, 0x5c, 0xff, 0x9b, 0xc1, 0x2e, 0xf1, 0xd9, 0xbb, 0xd0, 0xd8, 0xf2, 0xe5, 0xa3, 0xc3, - 0xf2, 0x93, 0x4b, 0x3d, 0xf0, 0x70, 0x4f, 0x2a, 0xe8, 0x0e, 0x8c, 0xc7, 0x81, 0x27, 0xdc, 0x21, - 0xa2, 0xb9, 0xc7, 0xf2, 0xc3, 0x74, 0x6d, 0x2a, 0x34, 0x5d, 0x31, 0xa3, 0xaa, 0x62, 0x9d, 0x0e, - 0xda, 0xe4, 0x7b, 0x8c, 0x05, 0x30, 0x26, 0xd1, 0xdc, 0xe3, 0xf9, 0x03, 0xa3, 0xe2, 0x1c, 0x9b, - 0x5b, 0x50, 0xd4, 0xc4, 0x3a, 0x19, 0x74, 0x1d, 0x66, 0xdb, 0xa1, 0x1b, 0xb0, 0x85, 0xad, 0x1e, - 0x06, 0xe6, 0xcc, 0x2c, 0x24, 0xb5, 0x34, 0x02, 0xee, 0xae, 0x43, 0x2f, 0x6e, 0xb2, 0x70, 0xee, - 0x22, 0x4f, 0x69, 0xc7, 0x85, 0x59, 0x5e, 0x86, 0x15, 0x14, 0xad, 0x33, 0xbe, 0xcc, 0xaf, 0x58, - 0x73, 0xf3, 0xf9, 0xf1, 0x42, 0xf4, 0xab, 0x18, 0x17, 0x74, 0xd4, 0x5f, 0x9c, 0x50, 0xa0, 0xe7, - 0x46, 0xb4, 0xe3, 0x84, 0xa4, 0x16, 0x06, 0x0d, 0xc2, 0x3b, 0xc3, 0xcd, 0xcf, 0x9f, 0xe0, 0x71, - 0x56, 0xe9, 0xb9, 0x51, 0xcf, 0x42, 0xc0, 0xd9, 0xf5, 0xe6, 0xbf, 0x1d, 0x66, 0xbb, 0x38, 0xf9, - 0x89, 0x4c, 0xe7, 0xff, 0x6c, 0x18, 0x4a, 0x4a, 0xf1, 0x8b, 0x16, 0x4d, 0x7d, 0xfe, 0xc5, 0xb4, - 0x3e, 0x7f, 0x8c, 0xca, 0x9f, 0xba, 0x0a, 0x7f, 0xd3, 0x30, 0xfc, 0x2a, 0xe4, 0xa7, 0xba, 0xd3, - 0xb5, 0x1e, 0x7d, 0xfd, 0x5c, 0xb5, 0x7b, 0x7c, 0x71, 0xe0, 0x87, 0x81, 0xa1, 0x9e, 0xaa, 0x81, - 0x01, 0xb3, 0x77, 0xd3, 0xab, 0x6e, 0x3b, 0x68, 0x56, 0x6b, 0xe9, 0x74, 0xb6, 0x35, 0x5a, 0x88, - 0x39, 0x8c, 0x5d, 0x56, 0xa8, 0xd8, 0xc1, 0x2e, 0x2b, 0xa3, 0x0f, 0x79, 0x59, 0x91, 0x04, 0x70, - 0x42, 0x0b, 0x79, 0x30, 0xdb, 0x30, 0x33, 0x11, 0x2b, 0xdf, 0xd6, 0x67, 0xfa, 0xe6, 0x04, 0xee, - 0x68, 0x29, 0x0a, 0x57, 0xd2, 0x54, 0x70, 0x37, 0x61, 0xf4, 0x06, 0x8c, 0xbd, 0x1f, 0x44, 0x6c, - 0x5b, 0x88, 0xb3, 0x57, 0x7a, 0x13, 0x8e, 0xbd, 0x7d, 0xbb, 0xce, 0xca, 0x8f, 0x0f, 0xcb, 0xe3, - 0xb5, 0xa0, 0x29, 0xff, 0x62, 0x55, 0x01, 0x3d, 0x80, 0x0b, 0x06, 0xc7, 0x52, 0xdd, 0x85, 0xc1, - 0xbb, 0xfb, 0x94, 0x68, 0xee, 0x42, 0x35, 0x8b, 0x12, 0xce, 0x6e, 0x80, 0xb2, 0x01, 0x3f, 0x10, - 0x59, 0xbc, 0xe5, 0xf9, 0xce, 0x8e, 0xf1, 0x92, 0x1e, 0x94, 0x21, 0x85, 0x80, 0xbb, 0xeb, 0xd8, - 0xdf, 0xe0, 0x7a, 0x72, 0xa1, 0x4d, 0x23, 0x51, 0xc7, 0x3b, 0x8b, 0x84, 0x66, 0xab, 0x86, 0xa2, - 0xef, 0xa1, 0xdf, 0x62, 0x7e, 0xc3, 0x62, 0x6f, 0x31, 0x9b, 0x64, 0xaf, 0xed, 0x39, 0xf1, 0x59, - 0x78, 0x5e, 0xbc, 0x0d, 0x63, 0xb1, 0x68, 0xad, 0x57, 0x0e, 0x36, 0xad, 0x53, 0xec, 0x3d, 0x4a, - 0x9d, 0xfc, 0xb2, 0x14, 0x2b, 0x32, 0xf6, 0xbf, 0xe4, 0x33, 0x20, 0x21, 0x67, 0xa0, 0x74, 0xa9, - 0x98, 0x4a, 0x97, 0x72, 0x9f, 0x2f, 0xc8, 0x51, 0xbe, 0xfc, 0x0b, 0xb3, 0xdf, 0xec, 0x92, 0xf5, - 0x71, 0x7f, 0x04, 0xb4, 0x7f, 0xdc, 0x82, 0xf3, 0x59, 0x56, 0x33, 0x54, 0x5a, 0xe3, 0x57, 0x3c, - 0xf5, 0x28, 0xaa, 0x46, 0xf0, 0xae, 0x28, 0xc7, 0x0a, 0x63, 0xe0, 0xf4, 0x26, 0x27, 0x8b, 0xc1, - 0x77, 0x1b, 0xcc, 0xec, 0xd7, 0xe8, 0x4d, 0xee, 0x4a, 0x65, 0xa9, 0xf4, 0xd4, 0x27, 0x73, 0xa3, - 0xb2, 0x7f, 0xae, 0x00, 0xe7, 0xf9, 0xab, 0xc6, 0xd2, 0x7e, 0xe0, 0x36, 0x6b, 0x41, 0x53, 0x38, - 0x96, 0xbd, 0x03, 0x13, 0x6d, 0xed, 0x5e, 0xde, 0x2b, 0x0a, 0x98, 0x7e, 0x7f, 0x4f, 0xee, 0x47, - 0x7a, 0x29, 0x36, 0x68, 0xa1, 0x26, 0x4c, 0x90, 0x7d, 0xb7, 0xa1, 0x54, 0xe3, 0x85, 0x13, 0x9f, - 0x0d, 0xaa, 0x95, 0x55, 0x8d, 0x0e, 0x36, 0xa8, 0x3e, 0x82, 0x6c, 0x85, 0xf6, 0x4f, 0x58, 0xf0, - 0x78, 0x4e, 0xcc, 0x30, 0xda, 0xdc, 0x7d, 0xf6, 0x7e, 0x24, 0x12, 0x9f, 0xa9, 0xe6, 0xf8, 0xab, - 0x12, 0x16, 0x50, 0xf4, 0x45, 0x00, 0xfe, 0x2a, 0x44, 0xaf, 0x0b, 0xe2, 0xd3, 0x07, 0x8b, 0xa5, - 0xa3, 0x05, 0x5c, 0x91, 0xf5, 0xb1, 0x46, 0xcb, 0xfe, 0x99, 0x22, 0x0c, 0xb3, 0x57, 0x08, 0xb4, - 0x06, 0xa3, 0x3b, 0x3c, 0x42, 0xf9, 0x20, 0xc1, 0xd0, 0x93, 0x7b, 0x17, 0x2f, 0xc0, 0xb2, 0x32, - 0x5a, 0x87, 0x73, 0xc2, 0x79, 0xb1, 0x42, 0x3c, 0xe7, 0x40, 0x5e, 0xdf, 0x79, 0xb2, 0x30, 0x95, - 0x1e, 0xaf, 0xda, 0x8d, 0x82, 0xb3, 0xea, 0xa1, 0x37, 0xbb, 0xe2, 0x92, 0xf2, 0xd8, 0xee, 0x4a, - 0xd8, 0xef, 0x13, 0x9b, 0xf4, 0x0d, 0x98, 0x6c, 0x77, 0x29, 0x2a, 0x86, 0x93, 0x8b, 0x88, 0xa9, - 0x9c, 0x30, 0x71, 0x99, 0xb9, 0x4c, 0x87, 0x19, 0x07, 0x6d, 0xee, 0x84, 0x24, 0xda, 0x09, 0xbc, - 0xa6, 0xc8, 0xdf, 0x9f, 0x98, 0xcb, 0xa4, 0xe0, 0xb8, 0xab, 0x06, 0xa5, 0xb2, 0xed, 0xb8, 0x5e, - 0x27, 0x24, 0x09, 0x95, 0x11, 0x93, 0xca, 0x5a, 0x0a, 0x8e, 0xbb, 0x6a, 0xd0, 0x75, 0x74, 0x41, - 0x24, 0x7f, 0x97, 0x21, 0x2d, 0x94, 0x0d, 0xd4, 0xa8, 0x74, 0x6d, 0xe9, 0x11, 0x66, 0x49, 0x58, - 0x89, 0xa8, 0xf4, 0xf1, 0x5a, 0x6a, 0x61, 0xe1, 0xd4, 0x22, 0xa9, 0x3c, 0x4c, 0x0a, 0xf2, 0x3f, - 0xb0, 0xe0, 0x5c, 0x86, 0xad, 0x25, 0x67, 0x55, 0x2d, 0x37, 0x8a, 0x55, 0x42, 0x24, 0x8d, 0x55, - 0xf1, 0x72, 0xac, 0x30, 0xe8, 0x7e, 0xe0, 0xcc, 0x30, 0xcd, 0x00, 0x85, 0x2d, 0x93, 0x80, 0x9e, - 0x8c, 0x01, 0xa2, 0xcb, 0x30, 0xd4, 0x89, 0x48, 0x28, 0x73, 0x77, 0x4b, 0xfe, 0xcd, 0x54, 0xa5, - 0x0c, 0x42, 0x45, 0xd3, 0x96, 0xd2, 0x52, 0x6a, 0xa2, 0x29, 0x57, 0x3d, 0x72, 0x98, 0xfd, 0xb5, - 0x22, 0x5c, 0xcc, 0xb5, 0xa5, 0xa6, 0x5d, 0xda, 0x0b, 0x7c, 0x37, 0x0e, 0xd4, 0x0b, 0x17, 0x8f, - 0x07, 0x44, 0xda, 0x3b, 0xeb, 0xa2, 0x1c, 0x2b, 0x0c, 0x74, 0x05, 0x86, 0xd9, 0xcd, 0xbe, 0x2b, - 0xe5, 0xd3, 0x72, 0x85, 0x87, 0xa9, 0xe0, 0xe0, 0x81, 0xd3, 0xe9, 0x3d, 0x03, 0x43, 0xed, 0x20, - 0xf0, 0xd2, 0xcc, 0x88, 0x76, 0x37, 0x08, 0x3c, 0xcc, 0x80, 0xe8, 0x53, 0x62, 0x1c, 0x52, 0x4f, - 0x3a, 0xd8, 0x69, 0x06, 0x91, 0x36, 0x18, 0xcf, 0xc2, 0xe8, 0x2e, 0x39, 0x08, 0x5d, 0xbf, 0x95, - 0x7e, 0xea, 0xbb, 0xc9, 0x8b, 0xb1, 0x84, 0x9b, 0x19, 0x4f, 0x46, 0x4f, 0x3b, 0x0f, 0xde, 0x58, - 0xdf, 0xa3, 0xed, 0x87, 0x8a, 0x30, 0x8d, 0x97, 0x2b, 0xdf, 0x9a, 0x88, 0x3b, 0xdd, 0x13, 0x71, - 0xda, 0x79, 0xf0, 0xfa, 0xcf, 0xc6, 0x2f, 0x59, 0x30, 0xcd, 0xa2, 0x82, 0x8b, 0x78, 0x36, 0x6e, - 0xe0, 0x9f, 0x81, 0xe8, 0xf6, 0x0c, 0x0c, 0x87, 0xb4, 0xd1, 0x74, 0x72, 0x2b, 0xd6, 0x13, 0xcc, - 0x61, 0xe8, 0x49, 0x18, 0x62, 0x5d, 0xa0, 0x93, 0x37, 0xc1, 0xf3, 0x82, 0x54, 0x9c, 0xd8, 0xc1, - 0xac, 0x94, 0x39, 0x16, 0x63, 0xd2, 0xf6, 0x5c, 0xde, 0xe9, 0x44, 0xd5, 0xff, 0xf1, 0x70, 0x2c, - 0xce, 0xec, 0xda, 0x87, 0x73, 0x2c, 0xce, 0x26, 0xd9, 0xfb, 0x5a, 0xf4, 0x3f, 0x0a, 0x70, 0x29, - 0xb3, 0xde, 0xc0, 0x8e, 0xc5, 0xbd, 0x6b, 0x9f, 0x8e, 0xc5, 0x46, 0xb6, 0x21, 0x45, 0xf1, 0x0c, - 0x0d, 0x29, 0x86, 0x06, 0x95, 0x1c, 0x87, 0x07, 0xf0, 0xf7, 0xcd, 0x1c, 0xb2, 0x8f, 0x89, 0xbf, - 0x6f, 0x66, 0xdf, 0x72, 0xae, 0x75, 0x7f, 0x51, 0xc8, 0xf9, 0x16, 0x76, 0xc1, 0xbb, 0x4a, 0xf9, - 0x0c, 0x03, 0x46, 0x42, 0x12, 0x9e, 0xe0, 0x3c, 0x86, 0x97, 0x61, 0x05, 0x45, 0xae, 0xe6, 0x39, - 0x5b, 0xc8, 0x4f, 0x7d, 0x9a, 0xdb, 0xd4, 0x82, 0xf9, 0x32, 0xa3, 0x07, 0xdf, 0x49, 0x7b, 0xd1, - 0xae, 0x6b, 0x97, 0xf2, 0xe2, 0xe0, 0x97, 0xf2, 0x89, 0xec, 0x0b, 0x39, 0x5a, 0x82, 0xe9, 0x3d, - 0xd7, 0xa7, 0x6c, 0xf3, 0xc0, 0x14, 0x45, 0x55, 0x20, 0x89, 0x75, 0x13, 0x8c, 0xd3, 0xf8, 0xf3, - 0x6f, 0xc0, 0xe4, 0xc3, 0xab, 0x23, 0xbf, 0x59, 0x84, 0x27, 0x7a, 0x6c, 0x7b, 0xce, 0xeb, 0x8d, - 0x39, 0xd0, 0x78, 0x7d, 0xd7, 0x3c, 0xd4, 0xe0, 0xfc, 0x76, 0xc7, 0xf3, 0x0e, 0x98, 0xad, 0x22, - 0x69, 0x4a, 0x0c, 0x21, 0x2b, 0xaa, 0x90, 0xff, 0x6b, 0x19, 0x38, 0x38, 0xb3, 0x26, 0x7a, 0x0b, - 0x50, 0x20, 0xf2, 0x2e, 0x27, 0x21, 0x85, 0xd8, 0xc0, 0x17, 0x93, 0xcd, 0x78, 0xbb, 0x0b, 0x03, - 0x67, 0xd4, 0xa2, 0x42, 0x3f, 0x3d, 0x95, 0x0e, 0x54, 0xb7, 0x52, 0x42, 0x3f, 0xd6, 0x81, 0xd8, - 0xc4, 0x45, 0xd7, 0x61, 0xd6, 0xd9, 0x77, 0x5c, 0x1e, 0x62, 0x52, 0x12, 0xe0, 0x52, 0xbf, 0x52, - 0x82, 0x2d, 0xa5, 0x11, 0x70, 0x77, 0x9d, 0x94, 0xeb, 0xee, 0x48, 0xbe, 0xeb, 0x6e, 0x6f, 0xbe, - 0xd8, 0x4f, 0xa7, 0x6b, 0xff, 0x67, 0x8b, 0x1e, 0x5f, 0x5c, 0x78, 0x37, 0xc3, 0x6d, 0xbd, 0x01, - 0x93, 0x4a, 0x37, 0xa9, 0x79, 0xd1, 0xaa, 0x71, 0x58, 0xd1, 0x81, 0xd8, 0xc4, 0xe5, 0x0b, 0x22, - 0x4a, 0x1c, 0x3a, 0x0c, 0xd1, 0x5d, 0xb8, 0xc9, 0x2b, 0x0c, 0xf4, 0x25, 0x18, 0x6d, 0xba, 0xfb, - 0x6e, 0x14, 0x84, 0x62, 0xb3, 0x9c, 0xd0, 0x2c, 0x3e, 0xe1, 0x83, 0x15, 0x4e, 0x06, 0x4b, 0x7a, - 0xf6, 0x0f, 0x15, 0x60, 0x52, 0xb6, 0xf8, 0x76, 0x27, 0x88, 0x9d, 0x33, 0x38, 0x96, 0xaf, 0x1b, - 0xc7, 0xf2, 0xa7, 0x7a, 0xc5, 0x0a, 0x60, 0x5d, 0xca, 0x3d, 0x8e, 0x6f, 0xa7, 0x8e, 0xe3, 0x4f, - 0xf7, 0x27, 0xd5, 0xfb, 0x18, 0xfe, 0x57, 0x16, 0xcc, 0x1a, 0xf8, 0x67, 0x70, 0x1a, 0xac, 0x99, - 0xa7, 0xc1, 0xd3, 0x7d, 0xbf, 0x21, 0xe7, 0x14, 0xf8, 0x7a, 0x21, 0xd5, 0x77, 0xc6, 0xfd, 0xdf, - 0x87, 0xa1, 0x1d, 0x27, 0x6c, 0xf6, 0x0a, 0x94, 0xdc, 0x55, 0x69, 0xe1, 0x86, 0x13, 0x36, 0x39, - 0x0f, 0x7f, 0x41, 0x65, 0x6b, 0x75, 0xc2, 0x66, 0x5f, 0xff, 0x25, 0xd6, 0x14, 0x7a, 0x1d, 0x46, - 0xa2, 0x46, 0xd0, 0x56, 0xd6, 0x85, 0x97, 0x79, 0x26, 0x57, 0x5a, 0x72, 0x7c, 0x58, 0x46, 0x66, - 0x73, 0xb4, 0x18, 0x0b, 0xfc, 0xf9, 0x16, 0x94, 0x54, 0xd3, 0x8f, 0xd4, 0x37, 0xe4, 0x77, 0x8b, - 0x70, 0x2e, 0x63, 0x5d, 0xa0, 0xc8, 0x18, 0xad, 0x97, 0x06, 0x5c, 0x4e, 0x1f, 0x72, 0xbc, 0x22, - 0x76, 0x63, 0x69, 0x8a, 0xf9, 0x1f, 0xb8, 0xd1, 0x3b, 0x11, 0x49, 0x37, 0x4a, 0x8b, 0xfa, 0x37, - 0x4a, 0x1b, 0x3b, 0xb3, 0xa1, 0xa6, 0x0d, 0xa9, 0x9e, 0x3e, 0xd2, 0x39, 0xfd, 0xd3, 0x22, 0x9c, - 0xcf, 0x0a, 0x31, 0x82, 0xbe, 0x3b, 0x95, 0x76, 0xe9, 0x95, 0x41, 0x83, 0x93, 0xf0, 0x5c, 0x4c, - 0x22, 0x26, 0xdb, 0x82, 0x99, 0x88, 0xa9, 0xef, 0x30, 0x8b, 0x36, 0x99, 0x43, 0x61, 0xc8, 0xd3, - 0x65, 0xc9, 0x2d, 0xfe, 0xd9, 0x81, 0x3b, 0x20, 0xf2, 0x6c, 0x45, 0x29, 0x87, 0x42, 0x59, 0xdc, - 0xdf, 0xa1, 0x50, 0xb6, 0x3c, 0xef, 0xc2, 0xb8, 0xf6, 0x35, 0x8f, 0x74, 0xc6, 0x77, 0xe9, 0x89, - 0xa2, 0xf5, 0xfb, 0x91, 0xce, 0xfa, 0x4f, 0x58, 0x90, 0xb2, 0xe9, 0x53, 0x2a, 0x29, 0x2b, 0x57, - 0x25, 0x75, 0x19, 0x86, 0xc2, 0xc0, 0x23, 0xe9, 0x4c, 0x3c, 0x38, 0xf0, 0x08, 0x66, 0x10, 0x8a, - 0x11, 0x27, 0x0a, 0x89, 0x09, 0xfd, 0xb2, 0x25, 0xae, 0x51, 0xcf, 0xc0, 0xb0, 0x47, 0xf6, 0x89, - 0xd4, 0x46, 0x28, 0x9e, 0x7c, 0x8b, 0x16, 0x62, 0x0e, 0xb3, 0x7f, 0x69, 0x08, 0x9e, 0xea, 0xe9, - 0x92, 0x4b, 0xaf, 0x2c, 0x2d, 0x27, 0x26, 0xf7, 0x9d, 0x83, 0x74, 0x9c, 0xf0, 0xeb, 0xbc, 0x18, - 0x4b, 0x38, 0xb3, 0x40, 0xe6, 0xa1, 0x46, 0x53, 0x0a, 0x3c, 0x11, 0x61, 0x54, 0x40, 0x4d, 0xc5, - 0x51, 0xf1, 0x34, 0x14, 0x47, 0xd7, 0x00, 0xa2, 0xc8, 0x5b, 0xf5, 0xa9, 0x04, 0xd6, 0x14, 0xa6, - 0xcd, 0x49, 0x48, 0xda, 0xfa, 0x2d, 0x01, 0xc1, 0x1a, 0x16, 0xaa, 0xc0, 0x4c, 0x3b, 0x0c, 0x62, - 0xae, 0x0f, 0xad, 0x70, 0x23, 0x99, 0x61, 0xd3, 0x1b, 0xb2, 0x96, 0x82, 0xe3, 0xae, 0x1a, 0xe8, - 0x55, 0x18, 0x17, 0x1e, 0x92, 0xb5, 0x20, 0xf0, 0x84, 0xaa, 0x46, 0x99, 0x5c, 0xd4, 0x13, 0x10, - 0xd6, 0xf1, 0xb4, 0x6a, 0x4c, 0xc9, 0x3a, 0x9a, 0x59, 0x8d, 0x2b, 0x5a, 0x35, 0xbc, 0x54, 0xb8, - 0xa1, 0xb1, 0x81, 0xc2, 0x0d, 0x25, 0xca, 0xab, 0xd2, 0xc0, 0xef, 0x4a, 0xd0, 0x57, 0xdd, 0xf3, - 0xf3, 0x43, 0x70, 0x4e, 0x2c, 0x9c, 0x47, 0xbd, 0x5c, 0xee, 0x74, 0x2f, 0x97, 0xd3, 0x50, 0x6f, - 0x7d, 0x6b, 0xcd, 0x9c, 0xf5, 0x9a, 0xf9, 0x46, 0x11, 0x46, 0xf8, 0x54, 0x9c, 0x81, 0x0c, 0xbf, - 0x26, 0x94, 0x7e, 0x3d, 0x02, 0xed, 0xf0, 0xbe, 0x2c, 0x54, 0x9c, 0xd8, 0xe1, 0xe7, 0x97, 0x62, - 0xa3, 0x89, 0x7a, 0x10, 0x2d, 0x18, 0x8c, 0x76, 0x3e, 0xa5, 0xd5, 0x02, 0x4e, 0x43, 0x63, 0xbb, - 0x5f, 0x06, 0x88, 0xe2, 0xd0, 0xf5, 0x5b, 0x94, 0x86, 0x08, 0xd9, 0xf4, 0x5c, 0x8f, 0xd6, 0xeb, - 0x0a, 0x99, 0xf7, 0x21, 0x59, 0x82, 0x0a, 0x80, 0x35, 0x8a, 0xf3, 0xaf, 0x41, 0x49, 0x21, 0xf7, - 0x53, 0x01, 0x4c, 0xe8, 0xa7, 0xde, 0x17, 0x60, 0x3a, 0xd5, 0xd6, 0x89, 0x34, 0x08, 0xbf, 0x6c, - 0xc1, 0x34, 0xef, 0xf2, 0xaa, 0xbf, 0x2f, 0x36, 0xfb, 0x07, 0x70, 0xde, 0xcb, 0xd8, 0x74, 0x62, - 0x46, 0x07, 0xdf, 0xa4, 0x4a, 0x63, 0x90, 0x05, 0xc5, 0x99, 0x6d, 0xa0, 0xab, 0x30, 0xc6, 0x5d, - 0x76, 0x1c, 0x4f, 0xb8, 0x59, 0x4c, 0xf0, 0xd4, 0x1d, 0xbc, 0x0c, 0x2b, 0xa8, 0xfd, 0x7b, 0x16, - 0xcc, 0xf2, 0x9e, 0xdf, 0x24, 0x07, 0xea, 0x76, 0xfc, 0x51, 0xf6, 0x5d, 0x64, 0x26, 0x29, 0xe4, - 0x64, 0x26, 0xd1, 0x3f, 0xad, 0xd8, 0xf3, 0xd3, 0x7e, 0xce, 0x02, 0xb1, 0x02, 0xcf, 0xe0, 0x1e, - 0xf8, 0xed, 0xe6, 0x3d, 0x70, 0x3e, 0x7f, 0x51, 0xe7, 0x5c, 0x00, 0xff, 0xdc, 0x82, 0x19, 0x8e, - 0x90, 0x3c, 0x44, 0x7e, 0xa4, 0xf3, 0x30, 0x48, 0xba, 0x3c, 0x95, 0x9f, 0x3c, 0xfb, 0xa3, 0x8c, - 0xc9, 0x1a, 0xea, 0x39, 0x59, 0x4d, 0xb9, 0x81, 0x4e, 0x90, 0x06, 0xf2, 0xc4, 0xc1, 0x74, 0xed, - 0x3f, 0xb1, 0x00, 0xf1, 0x66, 0x8c, 0x73, 0x99, 0x9e, 0x76, 0xac, 0x54, 0xd3, 0x04, 0x25, 0xac, - 0x46, 0x41, 0xb0, 0x86, 0x75, 0x2a, 0xc3, 0x93, 0x7a, 0x4d, 0x2e, 0xf6, 0x7f, 0x4d, 0x3e, 0xc1, - 0x88, 0x7e, 0x63, 0x08, 0xd2, 0x36, 0xda, 0xe8, 0x2e, 0x4c, 0x34, 0x9c, 0xb6, 0xb3, 0xe5, 0x7a, - 0x6e, 0xec, 0x92, 0xa8, 0x97, 0x19, 0xca, 0x8a, 0x86, 0x27, 0xde, 0x09, 0xb5, 0x12, 0x6c, 0xd0, - 0x41, 0x0b, 0x00, 0xed, 0xd0, 0xdd, 0x77, 0x3d, 0xd2, 0x62, 0x57, 0x61, 0xe6, 0xd8, 0xc5, 0x6d, - 0x2b, 0x64, 0x29, 0xd6, 0x30, 0x32, 0x1c, 0x81, 0x8a, 0x8f, 0xce, 0x11, 0x68, 0xe8, 0x84, 0x8e, - 0x40, 0xc3, 0x03, 0x39, 0x02, 0x61, 0x78, 0x4c, 0x9e, 0xdd, 0xf4, 0xff, 0x9a, 0xeb, 0x11, 0x21, - 0xb0, 0x71, 0x77, 0xaf, 0xf9, 0xa3, 0xc3, 0xf2, 0x63, 0x38, 0x13, 0x03, 0xe7, 0xd4, 0x44, 0x5f, - 0x84, 0x39, 0xc7, 0xf3, 0x82, 0xfb, 0x6a, 0xd4, 0x56, 0xa3, 0x86, 0xe3, 0x25, 0xb1, 0xe5, 0xc7, - 0x96, 0x9f, 0x3c, 0x3a, 0x2c, 0xcf, 0x2d, 0xe5, 0xe0, 0xe0, 0xdc, 0xda, 0x29, 0x3f, 0xa2, 0xb1, - 0xbe, 0x7e, 0x44, 0xbb, 0x70, 0xae, 0x4e, 0x42, 0x99, 0x89, 0x56, 0x6d, 0xc9, 0x4d, 0x28, 0x85, - 0x29, 0x26, 0x34, 0x50, 0x0c, 0x18, 0x2d, 0x4e, 0xa8, 0x64, 0x3a, 0x09, 0x21, 0xfb, 0xcf, 0x2c, - 0x18, 0x15, 0x76, 0xe2, 0x67, 0x20, 0xfb, 0x2c, 0x19, 0xfa, 0xcb, 0x72, 0x36, 0xa3, 0x66, 0x9d, - 0xc9, 0xd5, 0x5c, 0x56, 0x53, 0x9a, 0xcb, 0xa7, 0x7b, 0x11, 0xe9, 0xad, 0xb3, 0xfc, 0xb1, 0x22, - 0x4c, 0x99, 0x36, 0xf2, 0x67, 0x30, 0x04, 0x1b, 0x30, 0x1a, 0x09, 0x87, 0x8c, 0x42, 0xbe, 0xe1, - 0x6c, 0x7a, 0x12, 0x13, 0xab, 0x18, 0xe1, 0x82, 0x21, 0x89, 0x64, 0x7a, 0x7a, 0x14, 0x1f, 0xa1, - 0xa7, 0x47, 0x3f, 0x37, 0x85, 0xa1, 0xd3, 0x70, 0x53, 0xb0, 0x7f, 0x95, 0x1d, 0x16, 0x7a, 0xf9, - 0x19, 0xc8, 0x11, 0xd7, 0xcd, 0x63, 0xc5, 0xee, 0xb1, 0xb2, 0x44, 0xa7, 0x72, 0xe4, 0x89, 0x7f, - 0x66, 0xc1, 0xb8, 0x40, 0x3c, 0x83, 0x6e, 0x7f, 0x87, 0xd9, 0xed, 0x27, 0x7a, 0x74, 0x3b, 0xa7, - 0xbf, 0xff, 0xa0, 0xa0, 0xfa, 0x5b, 0x0b, 0xc2, 0x78, 0xa0, 0xdc, 0x24, 0x63, 0xf4, 0xf6, 0x18, - 0x34, 0x02, 0x4f, 0x1c, 0xfe, 0x4f, 0x26, 0x1e, 0xc2, 0xbc, 0xfc, 0x58, 0xfb, 0x8d, 0x15, 0x36, - 0x73, 0x60, 0x0d, 0xc2, 0x58, 0x1c, 0xb8, 0x89, 0x03, 0x6b, 0x10, 0xc6, 0x98, 0x41, 0x50, 0x13, - 0x20, 0x76, 0xc2, 0x16, 0x89, 0x69, 0x99, 0x08, 0x36, 0x90, 0xbf, 0x0b, 0x3b, 0xb1, 0xeb, 0x2d, - 0xb8, 0x7e, 0x1c, 0xc5, 0xe1, 0x42, 0xd5, 0x8f, 0x6f, 0x87, 0xfc, 0x2e, 0xa1, 0xb9, 0xfc, 0x2a, - 0x5a, 0x58, 0xa3, 0x2b, 0x7d, 0xc8, 0x58, 0x1b, 0xc3, 0xe6, 0xc3, 0xe2, 0x86, 0x28, 0xc7, 0x0a, - 0xc3, 0x7e, 0x8d, 0xf1, 0x64, 0x36, 0x40, 0x27, 0xf3, 0xc6, 0xfd, 0xed, 0x31, 0x35, 0xb4, 0xec, - 0x55, 0xa1, 0xa2, 0xfb, 0xfc, 0xf6, 0x66, 0x81, 0xb4, 0x61, 0xdd, 0x1f, 0x21, 0x71, 0x0c, 0x46, - 0xdf, 0xd9, 0xf5, 0xde, 0xfc, 0x62, 0x1f, 0x5e, 0x7a, 0x82, 0x17, 0x66, 0x16, 0xe0, 0x96, 0x05, - 0x02, 0xad, 0xd6, 0xd2, 0xd9, 0x63, 0x56, 0x24, 0x00, 0x27, 0x38, 0x68, 0x51, 0xdc, 0x44, 0xb9, - 0x3e, 0xef, 0x89, 0xd4, 0x4d, 0x54, 0x7e, 0xbe, 0x76, 0x15, 0x7d, 0x09, 0xc6, 0x55, 0x46, 0xbe, - 0x1a, 0x4f, 0x6c, 0x26, 0x42, 0x2f, 0xac, 0x26, 0xc5, 0x58, 0xc7, 0x41, 0x9b, 0x30, 0x1d, 0xf1, - 0x74, 0x81, 0x2a, 0xc2, 0x16, 0xd7, 0x33, 0x3c, 0x27, 0xdf, 0xa9, 0xeb, 0x26, 0xf8, 0x98, 0x15, - 0xf1, 0xcd, 0x2a, 0x1d, 0xc1, 0xd2, 0x24, 0xd0, 0x9b, 0x30, 0xe5, 0xe9, 0x69, 0xd3, 0x6b, 0x42, - 0x0d, 0xa1, 0xcc, 0x38, 0x8d, 0xa4, 0xea, 0x35, 0x9c, 0xc2, 0xa6, 0x42, 0x83, 0x5e, 0x22, 0xa2, - 0xc2, 0x39, 0x7e, 0x8b, 0x44, 0x22, 0x9f, 0x18, 0x13, 0x1a, 0x6e, 0xe5, 0xe0, 0xe0, 0xdc, 0xda, - 0xe8, 0x75, 0x98, 0x90, 0x9f, 0xaf, 0xb9, 0x39, 0x26, 0xc6, 0xc2, 0x1a, 0x0c, 0x1b, 0x98, 0xe8, - 0x3e, 0x5c, 0x90, 0xff, 0x37, 0x43, 0x67, 0x7b, 0xdb, 0x6d, 0x08, 0x2f, 0x53, 0xee, 0x31, 0xb1, - 0x24, 0x5d, 0x30, 0x56, 0xb3, 0x90, 0x8e, 0x0f, 0xcb, 0x97, 0xc5, 0xa8, 0x65, 0xc2, 0xd9, 0x24, - 0x66, 0xd3, 0x47, 0xeb, 0x70, 0x6e, 0x87, 0x38, 0x5e, 0xbc, 0xb3, 0xb2, 0x43, 0x1a, 0xbb, 0x72, - 0x13, 0x31, 0xe7, 0x49, 0xcd, 0xc4, 0xf6, 0x46, 0x37, 0x0a, 0xce, 0xaa, 0x87, 0xde, 0x85, 0xb9, - 0x76, 0x67, 0xcb, 0x73, 0xa3, 0x9d, 0x8d, 0x20, 0x66, 0x4f, 0xe3, 0x2a, 0xa1, 0x9d, 0xf0, 0xb2, - 0x54, 0x8e, 0xa3, 0xb5, 0x1c, 0x3c, 0x9c, 0x4b, 0x01, 0x7d, 0x00, 0x17, 0x52, 0x8b, 0x41, 0xf8, - 0x7c, 0x4d, 0xe5, 0xc7, 0xd8, 0xac, 0x67, 0x55, 0x10, 0x3e, 0x5c, 0x59, 0x20, 0x9c, 0xdd, 0xc4, - 0x87, 0x33, 0x98, 0x78, 0x9f, 0x56, 0xd6, 0xa4, 0x1b, 0xf4, 0x15, 0x98, 0xd0, 0x57, 0x91, 0x38, - 0x60, 0xae, 0x64, 0x1f, 0xfe, 0xda, 0x6a, 0xe3, 0xb2, 0x91, 0x5a, 0x51, 0x3a, 0x0c, 0x1b, 0x14, - 0x6d, 0x02, 0xd9, 0xdf, 0x87, 0x6e, 0xc1, 0x58, 0xc3, 0x73, 0x89, 0x1f, 0x57, 0x6b, 0xbd, 0xa2, - 0x09, 0xac, 0x08, 0x1c, 0x31, 0x60, 0x22, 0x28, 0x21, 0x2f, 0xc3, 0x8a, 0x82, 0xfd, 0xeb, 0x05, - 0x28, 0xf7, 0x89, 0x70, 0x99, 0xd2, 0x19, 0x5a, 0x03, 0xe9, 0x0c, 0x97, 0x64, 0x7a, 0xbe, 0x8d, - 0xd4, 0x7d, 0x35, 0x95, 0x7a, 0x2f, 0xb9, 0xb5, 0xa6, 0xf1, 0x07, 0xb6, 0xb3, 0xd4, 0xd5, 0x8e, - 0x43, 0x7d, 0x2d, 0x80, 0x8d, 0xe7, 0x86, 0xe1, 0xc1, 0x25, 0xfa, 0x5c, 0xd5, 0xb1, 0xfd, 0xab, - 0x05, 0xb8, 0xa0, 0x86, 0xf0, 0xaf, 0xee, 0xc0, 0xdd, 0xe9, 0x1e, 0xb8, 0x53, 0x50, 0xbc, 0xdb, - 0xb7, 0x61, 0xa4, 0x7e, 0x10, 0x35, 0x62, 0x6f, 0x00, 0x01, 0xe8, 0x19, 0x33, 0xaa, 0x8e, 0x3a, - 0xa6, 0x8d, 0xc8, 0x3a, 0x7f, 0xd3, 0x82, 0xe9, 0xcd, 0x95, 0x5a, 0x3d, 0x68, 0xec, 0x92, 0x78, - 0x89, 0xab, 0x95, 0xb0, 0x90, 0x7f, 0xac, 0x87, 0x94, 0x6b, 0xb2, 0x24, 0xa6, 0xcb, 0x30, 0xb4, - 0x13, 0x44, 0x71, 0xfa, 0x55, 0xee, 0x46, 0x10, 0xc5, 0x98, 0x41, 0xec, 0xdf, 0xb7, 0x60, 0x98, - 0x25, 0x95, 0xed, 0x97, 0x7c, 0x78, 0x90, 0xef, 0x42, 0xaf, 0xc2, 0x08, 0xd9, 0xde, 0x26, 0x8d, - 0x58, 0xcc, 0xaa, 0x74, 0xeb, 0x1b, 0x59, 0x65, 0xa5, 0xf4, 0xd0, 0x67, 0x8d, 0xf1, 0xbf, 0x58, - 0x20, 0xa3, 0x7b, 0x50, 0x8a, 0xdd, 0x3d, 0xb2, 0xd4, 0x6c, 0x8a, 0x77, 0x8d, 0x87, 0xf0, 0xa2, - 0xdc, 0x94, 0x04, 0x70, 0x42, 0xcb, 0xfe, 0x5a, 0x01, 0x20, 0x71, 0x4d, 0xee, 0xf7, 0x89, 0xcb, - 0x5d, 0xf9, 0x95, 0xaf, 0x64, 0xe4, 0x57, 0x46, 0x09, 0xc1, 0x8c, 0xec, 0xca, 0x6a, 0x98, 0x8a, - 0x03, 0x0d, 0xd3, 0xd0, 0x49, 0x86, 0x69, 0x05, 0x66, 0x13, 0xd7, 0x6a, 0x33, 0xce, 0x04, 0x8b, - 0x78, 0xbf, 0x99, 0x06, 0xe2, 0x6e, 0x7c, 0xfb, 0x07, 0x2c, 0x10, 0xee, 0x09, 0x03, 0x2c, 0xe6, - 0x77, 0x64, 0x2a, 0x54, 0x23, 0x50, 0xee, 0xe5, 0x7c, 0x7f, 0x0d, 0x11, 0x1e, 0x57, 0x1d, 0x1e, - 0x46, 0x50, 0x5c, 0x83, 0x96, 0xdd, 0x04, 0x01, 0xad, 0x10, 0xa6, 0x64, 0xe8, 0xdf, 0x9b, 0x6b, - 0x00, 0x4d, 0x86, 0xab, 0xa5, 0x56, 0x54, 0xac, 0xaa, 0xa2, 0x20, 0x58, 0xc3, 0xb2, 0x7f, 0xa4, - 0x00, 0xe3, 0x32, 0x30, 0x2b, 0xbd, 0xc7, 0xf7, 0x6f, 0xe5, 0x44, 0x59, 0x19, 0x58, 0x2e, 0x52, - 0x4a, 0x58, 0x05, 0xef, 0xd7, 0x73, 0x91, 0x4a, 0x00, 0x4e, 0x70, 0xd0, 0xb3, 0x30, 0x1a, 0x75, - 0xb6, 0x18, 0x7a, 0xca, 0xe8, 0xbe, 0xce, 0x8b, 0xb1, 0x84, 0xa3, 0x2f, 0xc2, 0x0c, 0xaf, 0x17, - 0x06, 0x6d, 0xa7, 0xc5, 0x35, 0x4e, 0xc3, 0xca, 0x0b, 0x6e, 0x66, 0x3d, 0x05, 0x3b, 0x3e, 0x2c, - 0x9f, 0x4f, 0x97, 0x31, 0x5d, 0x65, 0x17, 0x15, 0xfb, 0x2b, 0x80, 0xba, 0x63, 0xcd, 0xa2, 0xb7, - 0xb8, 0x59, 0x85, 0x1b, 0x92, 0x66, 0x2f, 0x25, 0xa4, 0xee, 0xb4, 0x25, 0x0d, 0x5f, 0x79, 0x2d, - 0xac, 0xea, 0xd3, 0x9d, 0x37, 0x93, 0x76, 0xe1, 0x41, 0x37, 0x60, 0x84, 0x33, 0x55, 0x41, 0xbe, - 0xc7, 0x1b, 0x97, 0xe6, 0xf8, 0xc3, 0x02, 0xe1, 0x0b, 0xbe, 0x2c, 0xea, 0xa3, 0x77, 0x61, 0xbc, - 0x19, 0xdc, 0xf7, 0xef, 0x3b, 0x61, 0x73, 0xa9, 0x56, 0x15, 0xeb, 0x32, 0x53, 0x36, 0xab, 0x24, - 0x68, 0xba, 0x33, 0x11, 0xd3, 0xe7, 0x26, 0x20, 0xac, 0x93, 0x43, 0x9b, 0x2c, 0x7e, 0xd6, 0xb6, - 0xdb, 0x5a, 0x77, 0xda, 0xbd, 0xec, 0xe0, 0x56, 0x24, 0x92, 0x46, 0x79, 0x52, 0x04, 0xd9, 0xe2, - 0x00, 0x9c, 0x10, 0xb2, 0xbf, 0x7a, 0x0e, 0x8c, 0xfd, 0x60, 0xe4, 0x7d, 0xb0, 0x4e, 0x29, 0xef, - 0x03, 0x86, 0x31, 0xb2, 0xd7, 0x8e, 0x0f, 0x2a, 0x6e, 0xd8, 0x2b, 0x71, 0xd0, 0xaa, 0xc0, 0xe9, - 0xa6, 0x29, 0x21, 0x58, 0xd1, 0xc9, 0x4e, 0xce, 0x51, 0xfc, 0x08, 0x93, 0x73, 0x0c, 0x9d, 0x61, - 0x72, 0x8e, 0x0d, 0x18, 0x6d, 0xb9, 0x31, 0x26, 0xed, 0x40, 0x08, 0x14, 0x99, 0x2b, 0xe1, 0x3a, - 0x47, 0xe9, 0x0e, 0x0d, 0x2f, 0x00, 0x58, 0x12, 0x41, 0x6f, 0xa9, 0x3d, 0x30, 0x92, 0x2f, 0x8f, - 0x77, 0x3f, 0x87, 0x64, 0xee, 0x02, 0x91, 0x8c, 0x63, 0xf4, 0x61, 0x93, 0x71, 0xac, 0xc9, 0x14, - 0x1a, 0x63, 0xf9, 0x66, 0xa3, 0x2c, 0x43, 0x46, 0x9f, 0xc4, 0x19, 0x46, 0xb2, 0x91, 0xd2, 0xe9, - 0x25, 0x1b, 0xf9, 0x01, 0x0b, 0x2e, 0xb4, 0xb3, 0xf2, 0xee, 0x88, 0x14, 0x18, 0xaf, 0x0e, 0x9c, - 0x58, 0xc8, 0x68, 0x90, 0x5d, 0xcc, 0x32, 0xd1, 0x70, 0x76, 0x73, 0x74, 0xa0, 0xc3, 0xad, 0xa6, - 0xc8, 0x9b, 0xf1, 0x4c, 0x4e, 0xd6, 0x92, 0x1e, 0xb9, 0x4a, 0x36, 0x33, 0x72, 0x65, 0x7c, 0x32, - 0x2f, 0x57, 0xc6, 0xc0, 0x19, 0x32, 0x92, 0x7c, 0x25, 0x93, 0x1f, 0x3a, 0x5f, 0xc9, 0x5b, 0x2a, - 0x5f, 0x49, 0x8f, 0xa8, 0x43, 0x3c, 0x1b, 0x49, 0xdf, 0x2c, 0x25, 0x5a, 0xa6, 0x91, 0xe9, 0xd3, - 0xc9, 0x34, 0x62, 0x30, 0x7b, 0x9e, 0xec, 0xe2, 0xf9, 0x3e, 0xcc, 0xde, 0xa0, 0xdb, 0x9b, 0xdd, - 0xf3, 0xac, 0x2a, 0xb3, 0x0f, 0x95, 0x55, 0xe5, 0xae, 0x9e, 0xa5, 0x04, 0xf5, 0x49, 0xc3, 0x41, - 0x91, 0x06, 0xcc, 0x4d, 0x72, 0x57, 0x3f, 0x82, 0xce, 0xe5, 0xd3, 0x55, 0x27, 0x4d, 0x37, 0xdd, - 0xac, 0x43, 0xa8, 0x3b, 0xe7, 0xc9, 0xf9, 0xb3, 0xc9, 0x79, 0x72, 0xe1, 0xd4, 0x73, 0x9e, 0x3c, - 0x76, 0x06, 0x39, 0x4f, 0x1e, 0xff, 0x48, 0x73, 0x9e, 0xcc, 0x3d, 0x82, 0x9c, 0x27, 0x1b, 0x49, - 0xce, 0x93, 0x8b, 0xf9, 0x53, 0x92, 0x61, 0x27, 0x97, 0x93, 0xe9, 0xe4, 0x2e, 0x94, 0xda, 0xd2, - 0xcb, 0x5b, 0x84, 0x45, 0xca, 0x4e, 0xb6, 0x98, 0xe5, 0x0a, 0xce, 0xa7, 0x44, 0x81, 0x70, 0x42, - 0x8a, 0xd2, 0x4d, 0x32, 0x9f, 0x3c, 0xd1, 0x43, 0xf5, 0x96, 0xa5, 0xd4, 0xc8, 0xcf, 0x77, 0x62, - 0xff, 0xad, 0x02, 0x5c, 0xea, 0xbd, 0xae, 0x13, 0x8d, 0x48, 0x2d, 0xd1, 0xe0, 0xa7, 0x34, 0x22, - 0xfc, 0x9a, 0x91, 0x60, 0x0d, 0x1c, 0x0a, 0xe3, 0x3a, 0xcc, 0x2a, 0x03, 0x39, 0xcf, 0x6d, 0x1c, - 0x68, 0x49, 0x18, 0x95, 0xb3, 0x4e, 0x3d, 0x8d, 0x80, 0xbb, 0xeb, 0xa0, 0x25, 0x98, 0x36, 0x0a, - 0xab, 0x15, 0x71, 0x9d, 0x50, 0x2a, 0x98, 0xba, 0x09, 0xc6, 0x69, 0x7c, 0xfb, 0xeb, 0x16, 0x3c, - 0x9e, 0x13, 0x0e, 0x7c, 0xe0, 0x48, 0x0f, 0xdb, 0x30, 0xdd, 0x36, 0xab, 0xf6, 0x09, 0x08, 0x63, - 0x04, 0x1d, 0x57, 0x7d, 0x4d, 0x01, 0x70, 0x9a, 0xe8, 0xf2, 0xd5, 0xdf, 0xfc, 0xc3, 0x4b, 0x9f, - 0xf8, 0x9d, 0x3f, 0xbc, 0xf4, 0x89, 0xdf, 0xfb, 0xc3, 0x4b, 0x9f, 0xf8, 0xeb, 0x47, 0x97, 0xac, - 0xdf, 0x3c, 0xba, 0x64, 0xfd, 0xce, 0xd1, 0x25, 0xeb, 0xf7, 0x8e, 0x2e, 0x59, 0x7f, 0x70, 0x74, - 0xc9, 0xfa, 0xda, 0x1f, 0x5d, 0xfa, 0xc4, 0x3b, 0x85, 0xfd, 0x97, 0xfe, 0x7f, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0x93, 0x27, 0x7c, 0x56, 0xe4, 0x00, 0x00, + // 12669 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6b, 0x6c, 0x24, 0x57, + 0x76, 0x18, 0xbc, 0xd5, 0xdd, 0x7c, 0xf4, 0xe1, 0xfb, 0xce, 0x43, 0x1c, 0x4a, 0x33, 0x3d, 0x2a, + 0xed, 0x8e, 0x46, 0x2b, 0x89, 0xb3, 0x1a, 0x49, 0x2b, 0x79, 0xb5, 0x2b, 0x9b, 0x64, 0x93, 0x33, + 0xd4, 0x0c, 0x39, 0xad, 0xdb, 0x9c, 0xd1, 0xae, 0xac, 0x5d, 0x6f, 0xb1, 0xfb, 0xb2, 0x59, 0x62, + 0xb1, 0xaa, 0x55, 0x55, 0xcd, 0x19, 0xea, 0xb3, 0x81, 0x2f, 0xeb, 0xd8, 0x89, 0x1f, 0x08, 0x16, + 0xb1, 0x91, 0x87, 0x6d, 0x38, 0x80, 0xe3, 0xc0, 0x76, 0x9c, 0x04, 0x71, 0xec, 0xd8, 0xce, 0xae, + 0x9d, 0x38, 0x4e, 0x7e, 0x38, 0x7f, 0x36, 0x4e, 0x80, 0x60, 0x0d, 0x18, 0x61, 0x6c, 0xda, 0x49, + 0xe0, 0x1f, 0x79, 0x20, 0xce, 0x1f, 0x33, 0x46, 0x1c, 0xdc, 0x67, 0xdd, 0x5b, 0x5d, 0xd5, 0xdd, + 0x1c, 0x71, 0x28, 0xd9, 0xd8, 0x7f, 0xdd, 0xf7, 0x9c, 0x7b, 0xee, 0xad, 0xfb, 0x3c, 0xe7, 0xdc, + 0xf3, 0x80, 0xd7, 0x76, 0x5e, 0x8d, 0xe6, 0xdd, 0xe0, 0xda, 0x4e, 0x67, 0x93, 0x84, 0x3e, 0x89, + 0x49, 0x74, 0x6d, 0x8f, 0xf8, 0xcd, 0x20, 0xbc, 0x26, 0x00, 0x4e, 0xdb, 0xbd, 0xd6, 0x08, 0x42, + 0x72, 0x6d, 0xef, 0x85, 0x6b, 0x2d, 0xe2, 0x93, 0xd0, 0x89, 0x49, 0x73, 0xbe, 0x1d, 0x06, 0x71, + 0x80, 0x10, 0xc7, 0x99, 0x77, 0xda, 0xee, 0x3c, 0xc5, 0x99, 0xdf, 0x7b, 0x61, 0xee, 0xf9, 0x96, + 0x1b, 0x6f, 0x77, 0x36, 0xe7, 0x1b, 0xc1, 0xee, 0xb5, 0x56, 0xd0, 0x0a, 0xae, 0x31, 0xd4, 0xcd, + 0xce, 0x16, 0xfb, 0xc7, 0xfe, 0xb0, 0x5f, 0x9c, 0xc4, 0xdc, 0x4b, 0x49, 0x33, 0xbb, 0x4e, 0x63, + 0xdb, 0xf5, 0x49, 0xb8, 0x7f, 0xad, 0xbd, 0xd3, 0x62, 0xed, 0x86, 0x24, 0x0a, 0x3a, 0x61, 0x83, + 0xa4, 0x1b, 0xee, 0x59, 0x2b, 0xba, 0xb6, 0x4b, 0x62, 0x27, 0xa3, 0xbb, 0x73, 0xd7, 0xf2, 0x6a, + 0x85, 0x1d, 0x3f, 0x76, 0x77, 0xbb, 0x9b, 0xf9, 0x74, 0xbf, 0x0a, 0x51, 0x63, 0x9b, 0xec, 0x3a, + 0x5d, 0xf5, 0x5e, 0xcc, 0xab, 0xd7, 0x89, 0x5d, 0xef, 0x9a, 0xeb, 0xc7, 0x51, 0x1c, 0xa6, 0x2b, + 0xd9, 0xdf, 0xb4, 0xe0, 0xf2, 0xc2, 0x5b, 0xf5, 0x65, 0xcf, 0x89, 0x62, 0xb7, 0xb1, 0xe8, 0x05, + 0x8d, 0x9d, 0x7a, 0x1c, 0x84, 0xe4, 0x5e, 0xe0, 0x75, 0x76, 0x49, 0x9d, 0x0d, 0x04, 0x7a, 0x0e, + 0x46, 0xf7, 0xd8, 0xff, 0xd5, 0xea, 0xac, 0x75, 0xd9, 0xba, 0x5a, 0x5e, 0x9c, 0xfe, 0xad, 0x83, + 0xca, 0xc7, 0x0e, 0x0f, 0x2a, 0xa3, 0xf7, 0x44, 0x39, 0x56, 0x18, 0xe8, 0x0a, 0x0c, 0x6f, 0x45, + 0x1b, 0xfb, 0x6d, 0x32, 0x5b, 0x60, 0xb8, 0x93, 0x02, 0x77, 0x78, 0xa5, 0x4e, 0x4b, 0xb1, 0x80, + 0xa2, 0x6b, 0x50, 0x6e, 0x3b, 0x61, 0xec, 0xc6, 0x6e, 0xe0, 0xcf, 0x16, 0x2f, 0x5b, 0x57, 0x87, + 0x16, 0x67, 0x04, 0x6a, 0xb9, 0x26, 0x01, 0x38, 0xc1, 0xa1, 0xdd, 0x08, 0x89, 0xd3, 0xbc, 0xe3, + 0x7b, 0xfb, 0xb3, 0xa5, 0xcb, 0xd6, 0xd5, 0xd1, 0xa4, 0x1b, 0x58, 0x94, 0x63, 0x85, 0x61, 0xff, + 0x58, 0x01, 0x46, 0x17, 0xb6, 0xb6, 0x5c, 0xdf, 0x8d, 0xf7, 0xd1, 0x3d, 0x18, 0xf7, 0x83, 0x26, + 0x91, 0xff, 0xd9, 0x57, 0x8c, 0x5d, 0xbf, 0x3c, 0xdf, 0xbd, 0x94, 0xe6, 0xd7, 0x35, 0xbc, 0xc5, + 0xe9, 0xc3, 0x83, 0xca, 0xb8, 0x5e, 0x82, 0x0d, 0x3a, 0x08, 0xc3, 0x58, 0x3b, 0x68, 0x2a, 0xb2, + 0x05, 0x46, 0xb6, 0x92, 0x45, 0xb6, 0x96, 0xa0, 0x2d, 0x4e, 0x1d, 0x1e, 0x54, 0xc6, 0xb4, 0x02, + 0xac, 0x13, 0x41, 0x9b, 0x30, 0x45, 0xff, 0xfa, 0xb1, 0xab, 0xe8, 0x16, 0x19, 0xdd, 0xa7, 0xf2, + 0xe8, 0x6a, 0xa8, 0x8b, 0x67, 0x0e, 0x0f, 0x2a, 0x53, 0xa9, 0x42, 0x9c, 0x26, 0x68, 0xbf, 0x0f, + 0x93, 0x0b, 0x71, 0xec, 0x34, 0xb6, 0x49, 0x93, 0xcf, 0x20, 0x7a, 0x09, 0x4a, 0xbe, 0xb3, 0x4b, + 0xc4, 0xfc, 0x5e, 0x16, 0x03, 0x5b, 0x5a, 0x77, 0x76, 0xc9, 0xd1, 0x41, 0x65, 0xfa, 0xae, 0xef, + 0xbe, 0xd7, 0x11, 0xab, 0x82, 0x96, 0x61, 0x86, 0x8d, 0xae, 0x03, 0x34, 0xc9, 0x9e, 0xdb, 0x20, + 0x35, 0x27, 0xde, 0x16, 0xf3, 0x8d, 0x44, 0x5d, 0xa8, 0x2a, 0x08, 0xd6, 0xb0, 0xec, 0x07, 0x50, + 0x5e, 0xd8, 0x0b, 0xdc, 0x66, 0x2d, 0x68, 0x46, 0x68, 0x07, 0xa6, 0xda, 0x21, 0xd9, 0x22, 0xa1, + 0x2a, 0x9a, 0xb5, 0x2e, 0x17, 0xaf, 0x8e, 0x5d, 0xbf, 0x9a, 0xf9, 0xb1, 0x26, 0xea, 0xb2, 0x1f, + 0x87, 0xfb, 0x8b, 0x8f, 0x89, 0xf6, 0xa6, 0x52, 0x50, 0x9c, 0xa6, 0x6c, 0xff, 0xeb, 0x02, 0x9c, + 0x5b, 0x78, 0xbf, 0x13, 0x92, 0xaa, 0x1b, 0xed, 0xa4, 0x57, 0x78, 0xd3, 0x8d, 0x76, 0xd6, 0x93, + 0x11, 0x50, 0x4b, 0xab, 0x2a, 0xca, 0xb1, 0xc2, 0x40, 0xcf, 0xc3, 0x08, 0xfd, 0x7d, 0x17, 0xaf, + 0x8a, 0x4f, 0x3e, 0x23, 0x90, 0xc7, 0xaa, 0x4e, 0xec, 0x54, 0x39, 0x08, 0x4b, 0x1c, 0xb4, 0x06, + 0x63, 0x0d, 0xb6, 0x21, 0x5b, 0x6b, 0x41, 0x93, 0xb0, 0xc9, 0x2c, 0x2f, 0x3e, 0x4b, 0xd1, 0x97, + 0x92, 0xe2, 0xa3, 0x83, 0xca, 0x2c, 0xef, 0x9b, 0x20, 0xa1, 0xc1, 0xb0, 0x5e, 0x1f, 0xd9, 0x6a, + 0x7f, 0x95, 0x18, 0x25, 0xc8, 0xd8, 0x5b, 0x57, 0xb5, 0xad, 0x32, 0xc4, 0xb6, 0xca, 0x78, 0xf6, + 0x36, 0x41, 0x2f, 0x40, 0x69, 0xc7, 0xf5, 0x9b, 0xb3, 0xc3, 0x8c, 0xd6, 0x45, 0x3a, 0xe7, 0xb7, + 0x5c, 0xbf, 0x79, 0x74, 0x50, 0x99, 0x31, 0xba, 0x43, 0x0b, 0x31, 0x43, 0xb5, 0xff, 0xd8, 0x82, + 0x0a, 0x83, 0xad, 0xb8, 0x1e, 0xa9, 0x91, 0x30, 0x72, 0xa3, 0x98, 0xf8, 0xb1, 0x31, 0xa0, 0xd7, + 0x01, 0x22, 0xd2, 0x08, 0x49, 0xac, 0x0d, 0xa9, 0x5a, 0x18, 0x75, 0x05, 0xc1, 0x1a, 0x16, 0x3d, + 0x10, 0xa2, 0x6d, 0x27, 0x64, 0xeb, 0x4b, 0x0c, 0xac, 0x3a, 0x10, 0xea, 0x12, 0x80, 0x13, 0x1c, + 0xe3, 0x40, 0x28, 0xf6, 0x3b, 0x10, 0xd0, 0xe7, 0x60, 0x2a, 0x69, 0x2c, 0x6a, 0x3b, 0x0d, 0x39, + 0x80, 0x6c, 0xcb, 0xd4, 0x4d, 0x10, 0x4e, 0xe3, 0xda, 0x7f, 0xdf, 0x12, 0x8b, 0x87, 0x7e, 0xf5, + 0x47, 0xfc, 0x5b, 0xed, 0x5f, 0xb5, 0x60, 0x64, 0xd1, 0xf5, 0x9b, 0xae, 0xdf, 0x42, 0x5f, 0x86, + 0x51, 0x7a, 0x37, 0x35, 0x9d, 0xd8, 0x11, 0xe7, 0xde, 0xa7, 0xb4, 0xbd, 0xa5, 0xae, 0x8a, 0xf9, + 0xf6, 0x4e, 0x8b, 0x16, 0x44, 0xf3, 0x14, 0x9b, 0xee, 0xb6, 0x3b, 0x9b, 0xef, 0x92, 0x46, 0xbc, + 0x46, 0x62, 0x27, 0xf9, 0x9c, 0xa4, 0x0c, 0x2b, 0xaa, 0xe8, 0x16, 0x0c, 0xc7, 0x4e, 0xd8, 0x22, + 0xb1, 0x38, 0x00, 0x33, 0x0f, 0x2a, 0x5e, 0x13, 0xd3, 0x1d, 0x49, 0xfc, 0x06, 0x49, 0xae, 0x85, + 0x0d, 0x56, 0x15, 0x0b, 0x12, 0xf6, 0x0f, 0x0e, 0xc3, 0x85, 0xa5, 0xfa, 0x6a, 0xce, 0xba, 0xba, + 0x02, 0xc3, 0xcd, 0xd0, 0xdd, 0x23, 0xa1, 0x18, 0x67, 0x45, 0xa5, 0xca, 0x4a, 0xb1, 0x80, 0xa2, + 0x57, 0x61, 0x9c, 0x5f, 0x48, 0x37, 0x1d, 0xbf, 0xe9, 0xc9, 0x21, 0x3e, 0x2b, 0xb0, 0xc7, 0xef, + 0x69, 0x30, 0x6c, 0x60, 0x1e, 0x73, 0x51, 0x5d, 0x49, 0x6d, 0xc6, 0xbc, 0xcb, 0xee, 0x07, 0x2c, + 0x98, 0xe6, 0xcd, 0x2c, 0xc4, 0x71, 0xe8, 0x6e, 0x76, 0x62, 0x12, 0xcd, 0x0e, 0xb1, 0x93, 0x6e, + 0x29, 0x6b, 0xb4, 0x72, 0x47, 0x60, 0xfe, 0x5e, 0x8a, 0x0a, 0x3f, 0x04, 0x67, 0x45, 0xbb, 0xd3, + 0x69, 0x30, 0xee, 0x6a, 0x16, 0x7d, 0xaf, 0x05, 0x73, 0x8d, 0xc0, 0x8f, 0xc3, 0xc0, 0xf3, 0x48, + 0x58, 0xeb, 0x6c, 0x7a, 0x6e, 0xb4, 0xcd, 0xd7, 0x29, 0x26, 0x5b, 0xec, 0x24, 0xc8, 0x99, 0x43, + 0x85, 0x24, 0xe6, 0xf0, 0xd2, 0xe1, 0x41, 0x65, 0x6e, 0x29, 0x97, 0x14, 0xee, 0xd1, 0x0c, 0xda, + 0x01, 0x44, 0xaf, 0xd2, 0x7a, 0xec, 0xb4, 0x48, 0xd2, 0xf8, 0xc8, 0xe0, 0x8d, 0x9f, 0x3f, 0x3c, + 0xa8, 0xa0, 0xf5, 0x2e, 0x12, 0x38, 0x83, 0x2c, 0x7a, 0x0f, 0xce, 0xd2, 0xd2, 0xae, 0x6f, 0x1d, + 0x1d, 0xbc, 0xb9, 0xd9, 0xc3, 0x83, 0xca, 0xd9, 0xf5, 0x0c, 0x22, 0x38, 0x93, 0xf4, 0xdc, 0x12, + 0x9c, 0xcb, 0x9c, 0x2a, 0x34, 0x0d, 0xc5, 0x1d, 0xc2, 0x59, 0x90, 0x32, 0xa6, 0x3f, 0xd1, 0x59, + 0x18, 0xda, 0x73, 0xbc, 0x8e, 0x58, 0xa5, 0x98, 0xff, 0xf9, 0x4c, 0xe1, 0x55, 0xcb, 0x6e, 0xc0, + 0xf8, 0x92, 0xd3, 0x76, 0x36, 0x5d, 0xcf, 0x8d, 0x5d, 0x12, 0xa1, 0xa7, 0xa1, 0xe8, 0x34, 0x9b, + 0xec, 0x8a, 0x2c, 0x2f, 0x9e, 0x3b, 0x3c, 0xa8, 0x14, 0x17, 0x9a, 0xf4, 0xac, 0x06, 0x85, 0xb5, + 0x8f, 0x29, 0x06, 0xfa, 0x24, 0x94, 0x9a, 0x61, 0xd0, 0x9e, 0x2d, 0x30, 0x4c, 0x3a, 0x54, 0xa5, + 0x6a, 0x18, 0xb4, 0x53, 0xa8, 0x0c, 0xc7, 0xfe, 0x8d, 0x02, 0x3c, 0xb1, 0x44, 0xda, 0xdb, 0x2b, + 0xf5, 0x9c, 0x4d, 0x77, 0x15, 0x46, 0x77, 0x03, 0xdf, 0x8d, 0x83, 0x30, 0x12, 0x4d, 0xb3, 0xdb, + 0x64, 0x4d, 0x94, 0x61, 0x05, 0x45, 0x97, 0xa1, 0xd4, 0x4e, 0x38, 0x81, 0x71, 0xc9, 0x45, 0x30, + 0x1e, 0x80, 0x41, 0x28, 0x46, 0x27, 0x22, 0xa1, 0xb8, 0x05, 0x15, 0xc6, 0xdd, 0x88, 0x84, 0x98, + 0x41, 0x92, 0xe3, 0x94, 0x1e, 0xb4, 0x62, 0x5b, 0xa5, 0x8e, 0x53, 0x0a, 0xc1, 0x1a, 0x16, 0xaa, + 0x41, 0x39, 0x52, 0x93, 0x3a, 0x34, 0xf8, 0xa4, 0x4e, 0xb0, 0xf3, 0x56, 0xcd, 0x64, 0x42, 0xc4, + 0x38, 0x06, 0x86, 0xfb, 0x9e, 0xb7, 0x5f, 0x2f, 0x00, 0xe2, 0x43, 0xf8, 0xe7, 0x6c, 0xe0, 0xee, + 0x76, 0x0f, 0x5c, 0x26, 0xe7, 0x75, 0x3b, 0x68, 0x38, 0x5e, 0xfa, 0x08, 0x3f, 0xa9, 0xd1, 0xfb, + 0xdf, 0x16, 0x3c, 0xb1, 0xe4, 0xfa, 0x4d, 0x12, 0xe6, 0x2c, 0xc0, 0x47, 0x23, 0x80, 0x1c, 0xef, + 0xa4, 0x37, 0x96, 0x58, 0xe9, 0x04, 0x96, 0x98, 0xfd, 0x3f, 0x2c, 0x40, 0xfc, 0xb3, 0x3f, 0x72, + 0x1f, 0x7b, 0xb7, 0xfb, 0x63, 0x4f, 0x60, 0x59, 0xd8, 0xb7, 0x61, 0x72, 0xc9, 0x73, 0x89, 0x1f, + 0xaf, 0xd6, 0x96, 0x02, 0x7f, 0xcb, 0x6d, 0xa1, 0xcf, 0xc0, 0x24, 0x95, 0x69, 0x83, 0x4e, 0x5c, + 0x27, 0x8d, 0xc0, 0x67, 0xec, 0x3f, 0x95, 0x04, 0xd1, 0xe1, 0x41, 0x65, 0x72, 0xc3, 0x80, 0xe0, + 0x14, 0xa6, 0xfd, 0xbb, 0x74, 0xfc, 0x82, 0xdd, 0x76, 0xe0, 0x13, 0x3f, 0x5e, 0x0a, 0xfc, 0x26, + 0x17, 0x13, 0x3f, 0x03, 0xa5, 0x98, 0x8e, 0x07, 0x1f, 0xbb, 0x2b, 0x72, 0xa3, 0xd0, 0x51, 0x38, + 0x3a, 0xa8, 0x9c, 0xef, 0xae, 0xc1, 0xc6, 0x89, 0xd5, 0x41, 0xdf, 0x06, 0xc3, 0x51, 0xec, 0xc4, + 0x9d, 0x48, 0x8c, 0xe6, 0x93, 0x72, 0x34, 0xeb, 0xac, 0xf4, 0xe8, 0xa0, 0x32, 0xa5, 0xaa, 0xf1, + 0x22, 0x2c, 0x2a, 0xa0, 0x67, 0x60, 0x64, 0x97, 0x44, 0x91, 0xd3, 0x92, 0x1c, 0xfe, 0x94, 0xa8, + 0x3b, 0xb2, 0xc6, 0x8b, 0xb1, 0x84, 0xa3, 0xa7, 0x60, 0x88, 0x84, 0x61, 0x10, 0x8a, 0x3d, 0x3a, + 0x21, 0x10, 0x87, 0x96, 0x69, 0x21, 0xe6, 0x30, 0xfb, 0xdf, 0x5a, 0x30, 0xa5, 0xfa, 0xca, 0xdb, + 0x3a, 0x05, 0x56, 0xee, 0x6d, 0x80, 0x86, 0xfc, 0xc0, 0x88, 0xdd, 0x1e, 0x63, 0xd7, 0xaf, 0x64, + 0x32, 0x28, 0x5d, 0xc3, 0x98, 0x50, 0x56, 0x45, 0x11, 0xd6, 0xa8, 0xd9, 0xbf, 0x6e, 0xc1, 0x99, + 0xd4, 0x17, 0xdd, 0x76, 0xa3, 0x18, 0xbd, 0xd3, 0xf5, 0x55, 0xf3, 0x83, 0x7d, 0x15, 0xad, 0xcd, + 0xbe, 0x49, 0x2d, 0x65, 0x59, 0xa2, 0x7d, 0xd1, 0x4d, 0x18, 0x72, 0x63, 0xb2, 0x2b, 0x3f, 0xe6, + 0xa9, 0x9e, 0x1f, 0xc3, 0x7b, 0x95, 0xcc, 0xc8, 0x2a, 0xad, 0x89, 0x39, 0x01, 0xfb, 0x47, 0x8a, + 0x50, 0xe6, 0xcb, 0x76, 0xcd, 0x69, 0x9f, 0xc2, 0x5c, 0xac, 0x42, 0x89, 0x51, 0xe7, 0x1d, 0x7f, + 0x3a, 0xbb, 0xe3, 0xa2, 0x3b, 0xf3, 0x54, 0x4e, 0xe3, 0xac, 0xa0, 0xba, 0x1a, 0x68, 0x11, 0x66, + 0x24, 0x90, 0x03, 0xb0, 0xe9, 0xfa, 0x4e, 0xb8, 0x4f, 0xcb, 0x66, 0x8b, 0x8c, 0xe0, 0xf3, 0xbd, + 0x09, 0x2e, 0x2a, 0x7c, 0x4e, 0x56, 0xf5, 0x35, 0x01, 0x60, 0x8d, 0xe8, 0xdc, 0x2b, 0x50, 0x56, + 0xc8, 0xc7, 0xe1, 0x71, 0xe6, 0x3e, 0x07, 0x53, 0xa9, 0xb6, 0xfa, 0x55, 0x1f, 0xd7, 0x59, 0xa4, + 0xaf, 0xb1, 0x53, 0x40, 0xf4, 0x7a, 0xd9, 0xdf, 0x13, 0xa7, 0xe8, 0xfb, 0x70, 0xd6, 0xcb, 0x38, + 0x9c, 0xc4, 0x54, 0x0d, 0x7e, 0x98, 0x3d, 0x21, 0x3e, 0xfb, 0x6c, 0x16, 0x14, 0x67, 0xb6, 0x41, + 0xaf, 0xfd, 0xa0, 0x4d, 0xd7, 0xbc, 0xe3, 0xb1, 0xfe, 0x0a, 0xe9, 0xfb, 0x8e, 0x28, 0xc3, 0x0a, + 0x4a, 0x8f, 0xb0, 0xb3, 0xaa, 0xf3, 0xb7, 0xc8, 0x7e, 0x9d, 0x78, 0xa4, 0x11, 0x07, 0xe1, 0x87, + 0xda, 0xfd, 0x8b, 0x7c, 0xf4, 0xf9, 0x09, 0x38, 0x26, 0x08, 0x14, 0x6f, 0x91, 0x7d, 0x3e, 0x15, + 0xfa, 0xd7, 0x15, 0x7b, 0x7e, 0xdd, 0x2f, 0x58, 0x30, 0xa1, 0xbe, 0xee, 0x14, 0xb6, 0xfa, 0xa2, + 0xb9, 0xd5, 0x2f, 0xf6, 0x5c, 0xe0, 0x39, 0x9b, 0xfc, 0xeb, 0x05, 0xb8, 0xa0, 0x70, 0x28, 0xbb, + 0xcf, 0xff, 0x88, 0x55, 0x75, 0x0d, 0xca, 0xbe, 0xd2, 0x1e, 0x58, 0xa6, 0xd8, 0x9e, 0xe8, 0x0e, + 0x12, 0x1c, 0xca, 0xb5, 0xf9, 0x89, 0x88, 0x3f, 0xae, 0xab, 0xd5, 0x84, 0x0a, 0x6d, 0x11, 0x8a, + 0x1d, 0xb7, 0x29, 0xee, 0x8c, 0x4f, 0xc9, 0xd1, 0xbe, 0xbb, 0x5a, 0x3d, 0x3a, 0xa8, 0x3c, 0x99, + 0xa7, 0xd2, 0xa5, 0x97, 0x55, 0x34, 0x7f, 0x77, 0xb5, 0x8a, 0x69, 0x65, 0xb4, 0x00, 0x53, 0x52, + 0x6b, 0x7d, 0x8f, 0x72, 0x50, 0x81, 0x2f, 0xae, 0x16, 0xa5, 0x1b, 0xc3, 0x26, 0x18, 0xa7, 0xf1, + 0x51, 0x15, 0xa6, 0x77, 0x3a, 0x9b, 0xc4, 0x23, 0x31, 0xff, 0xe0, 0x5b, 0x84, 0x6b, 0x8e, 0xca, + 0x89, 0x68, 0x79, 0x2b, 0x05, 0xc7, 0x5d, 0x35, 0xec, 0x3f, 0x63, 0x47, 0xbc, 0x18, 0xbd, 0x5a, + 0x18, 0xd0, 0x85, 0x45, 0xa9, 0x7f, 0x98, 0xcb, 0x79, 0x90, 0x55, 0x71, 0x8b, 0xec, 0x6f, 0x04, + 0x94, 0xd9, 0xce, 0x5e, 0x15, 0xc6, 0x9a, 0x2f, 0xf5, 0x5c, 0xf3, 0xbf, 0x54, 0x80, 0x73, 0x6a, + 0x04, 0x0c, 0xbe, 0xee, 0xcf, 0xfb, 0x18, 0xbc, 0x00, 0x63, 0x4d, 0xb2, 0xe5, 0x74, 0xbc, 0x58, + 0xa9, 0x31, 0x87, 0xb8, 0x2a, 0xbb, 0x9a, 0x14, 0x63, 0x1d, 0xe7, 0x18, 0xc3, 0xf6, 0xd3, 0x63, + 0xec, 0x6e, 0x8d, 0x1d, 0xba, 0xc6, 0xd5, 0xae, 0xb1, 0x72, 0x77, 0xcd, 0x53, 0x30, 0xe4, 0xee, + 0x52, 0x5e, 0xab, 0x60, 0xb2, 0x50, 0xab, 0xb4, 0x10, 0x73, 0x18, 0xfa, 0x04, 0x8c, 0x34, 0x82, + 0xdd, 0x5d, 0xc7, 0x6f, 0xb2, 0x2b, 0xaf, 0xbc, 0x38, 0x46, 0xd9, 0xb1, 0x25, 0x5e, 0x84, 0x25, + 0x0c, 0x3d, 0x01, 0x25, 0x27, 0x6c, 0x45, 0xb3, 0x25, 0x86, 0x33, 0x4a, 0x5b, 0x5a, 0x08, 0x5b, + 0x11, 0x66, 0xa5, 0x54, 0xaa, 0xba, 0x1f, 0x84, 0x3b, 0xae, 0xdf, 0xaa, 0xba, 0xa1, 0xd8, 0x12, + 0xea, 0x2e, 0x7c, 0x4b, 0x41, 0xb0, 0x86, 0x85, 0x56, 0x60, 0xa8, 0x1d, 0x84, 0x71, 0x34, 0x3b, + 0xcc, 0x86, 0xfb, 0xc9, 0x9c, 0x83, 0x88, 0x7f, 0x6d, 0x2d, 0x08, 0xe3, 0xe4, 0x03, 0xe8, 0xbf, + 0x08, 0xf3, 0xea, 0xe8, 0xdb, 0xa0, 0x48, 0xfc, 0xbd, 0xd9, 0x11, 0x46, 0x65, 0x2e, 0x8b, 0xca, + 0xb2, 0xbf, 0x77, 0xcf, 0x09, 0x93, 0x53, 0x7a, 0xd9, 0xdf, 0xc3, 0xb4, 0x0e, 0xfa, 0x02, 0x94, + 0xe5, 0x16, 0x8f, 0x84, 0x9a, 0x23, 0x73, 0x89, 0xc9, 0x83, 0x01, 0x93, 0xf7, 0x3a, 0x6e, 0x48, + 0x76, 0x89, 0x1f, 0x47, 0xc9, 0x99, 0x26, 0xa1, 0x11, 0x4e, 0xa8, 0xa1, 0x2f, 0x48, 0xdd, 0xda, + 0x5a, 0xd0, 0xf1, 0xe3, 0x68, 0xb6, 0xcc, 0xba, 0x97, 0xf9, 0xea, 0x71, 0x2f, 0xc1, 0x4b, 0x2b, + 0xdf, 0x78, 0x65, 0x6c, 0x90, 0x42, 0x18, 0x26, 0x3c, 0x77, 0x8f, 0xf8, 0x24, 0x8a, 0x6a, 0x61, + 0xb0, 0x49, 0x66, 0x81, 0xf5, 0xfc, 0x42, 0xf6, 0x63, 0x40, 0xb0, 0x49, 0x16, 0x67, 0x0e, 0x0f, + 0x2a, 0x13, 0xb7, 0xf5, 0x3a, 0xd8, 0x24, 0x81, 0xee, 0xc2, 0x24, 0x95, 0x6b, 0xdc, 0x84, 0xe8, + 0x58, 0x3f, 0xa2, 0x4c, 0xfa, 0xc0, 0x46, 0x25, 0x9c, 0x22, 0x82, 0xde, 0x80, 0xb2, 0xe7, 0x6e, + 0x91, 0xc6, 0x7e, 0xc3, 0x23, 0xb3, 0xe3, 0x8c, 0x62, 0xe6, 0xb6, 0xba, 0x2d, 0x91, 0xb8, 0x5c, + 0xa4, 0xfe, 0xe2, 0xa4, 0x3a, 0xba, 0x07, 0xe7, 0x63, 0x12, 0xee, 0xba, 0xbe, 0x43, 0xb7, 0x83, + 0x90, 0x17, 0xd8, 0x93, 0xca, 0x04, 0x5b, 0x6f, 0x97, 0xc4, 0xd0, 0x9d, 0xdf, 0xc8, 0xc4, 0xc2, + 0x39, 0xb5, 0xd1, 0x1d, 0x98, 0x62, 0x3b, 0xa1, 0xd6, 0xf1, 0xbc, 0x5a, 0xe0, 0xb9, 0x8d, 0xfd, + 0xd9, 0x49, 0x46, 0xf0, 0x13, 0xf2, 0x5e, 0x58, 0x35, 0xc1, 0x47, 0x07, 0x15, 0x48, 0xfe, 0xe1, + 0x74, 0x6d, 0xb4, 0xc9, 0x74, 0xe8, 0x9d, 0xd0, 0x8d, 0xf7, 0xe9, 0xfa, 0x25, 0x0f, 0xe2, 0xd9, + 0xa9, 0x9e, 0xa2, 0xb0, 0x8e, 0xaa, 0x14, 0xed, 0x7a, 0x21, 0x4e, 0x13, 0xa4, 0x5b, 0x3b, 0x8a, + 0x9b, 0xae, 0x3f, 0x3b, 0xcd, 0x4e, 0x0c, 0xb5, 0x33, 0xea, 0xb4, 0x10, 0x73, 0x18, 0xd3, 0x9f, + 0xd3, 0x1f, 0x77, 0xe8, 0x09, 0x3a, 0xc3, 0x10, 0x13, 0xfd, 0xb9, 0x04, 0xe0, 0x04, 0x87, 0x32, + 0x35, 0x71, 0xbc, 0x3f, 0x8b, 0x18, 0xaa, 0xda, 0x2e, 0x1b, 0x1b, 0x5f, 0xc0, 0xb4, 0x1c, 0xdd, + 0x86, 0x11, 0xe2, 0xef, 0xad, 0x84, 0xc1, 0xee, 0xec, 0x99, 0xfc, 0x3d, 0xbb, 0xcc, 0x51, 0xf8, + 0x81, 0x9e, 0x08, 0x78, 0xa2, 0x18, 0x4b, 0x12, 0xe8, 0x01, 0xcc, 0x66, 0xcc, 0x08, 0x9f, 0x80, + 0xb3, 0x6c, 0x02, 0x3e, 0x2b, 0xea, 0xce, 0x6e, 0xe4, 0xe0, 0x1d, 0xf5, 0x80, 0xe1, 0x5c, 0xea, + 0xe8, 0x8b, 0x30, 0xc1, 0x37, 0x14, 0x7f, 0x7c, 0x8b, 0x66, 0xcf, 0xb1, 0xaf, 0xb9, 0x9c, 0xbf, + 0x39, 0x39, 0xe2, 0xe2, 0x39, 0xd1, 0xa1, 0x09, 0xbd, 0x34, 0xc2, 0x26, 0x35, 0x7b, 0x13, 0x26, + 0xd5, 0xb9, 0xc5, 0x96, 0x0e, 0xaa, 0xc0, 0x10, 0xe3, 0x76, 0x84, 0x7e, 0xab, 0x4c, 0x67, 0x8a, + 0x71, 0x42, 0x98, 0x97, 0xb3, 0x99, 0x72, 0xdf, 0x27, 0x8b, 0xfb, 0x31, 0xe1, 0x52, 0x75, 0x51, + 0x9b, 0x29, 0x09, 0xc0, 0x09, 0x8e, 0xfd, 0x7f, 0x39, 0xd7, 0x98, 0x1c, 0x8e, 0x03, 0x5c, 0x07, + 0xcf, 0xc1, 0xe8, 0x76, 0x10, 0xc5, 0x14, 0x9b, 0xb5, 0x31, 0x94, 0xf0, 0x89, 0x37, 0x45, 0x39, + 0x56, 0x18, 0xe8, 0x35, 0x98, 0x68, 0xe8, 0x0d, 0x88, 0xbb, 0x4c, 0x0d, 0x81, 0xd1, 0x3a, 0x36, + 0x71, 0xd1, 0xab, 0x30, 0xca, 0x9e, 0xce, 0x1b, 0x81, 0x27, 0x98, 0x2c, 0x79, 0x21, 0x8f, 0xd6, + 0x44, 0xf9, 0x91, 0xf6, 0x1b, 0x2b, 0x6c, 0x74, 0x05, 0x86, 0x69, 0x17, 0x56, 0x6b, 0xe2, 0x16, + 0x51, 0xaa, 0x9a, 0x9b, 0xac, 0x14, 0x0b, 0xa8, 0xfd, 0xd7, 0x0b, 0xda, 0x28, 0x53, 0x89, 0x94, + 0xa0, 0x1a, 0x8c, 0xdc, 0x77, 0xdc, 0xd8, 0xf5, 0x5b, 0x82, 0x5d, 0x78, 0xa6, 0xe7, 0x95, 0xc2, + 0x2a, 0xbd, 0xc5, 0x2b, 0xf0, 0x4b, 0x4f, 0xfc, 0xc1, 0x92, 0x0c, 0xa5, 0x18, 0x76, 0x7c, 0x9f, + 0x52, 0x2c, 0x0c, 0x4a, 0x11, 0xf3, 0x0a, 0x9c, 0xa2, 0xf8, 0x83, 0x25, 0x19, 0xf4, 0x0e, 0x80, + 0x5c, 0x96, 0xa4, 0x29, 0x9e, 0xac, 0x9f, 0xeb, 0x4f, 0x74, 0x43, 0xd5, 0x59, 0x9c, 0xa4, 0x57, + 0x6a, 0xf2, 0x1f, 0x6b, 0xf4, 0xec, 0x98, 0xb1, 0x55, 0xdd, 0x9d, 0x41, 0xdf, 0x49, 0x4f, 0x02, + 0x27, 0x8c, 0x49, 0x73, 0x21, 0x16, 0x83, 0xf3, 0xc9, 0xc1, 0x64, 0x8a, 0x0d, 0x77, 0x97, 0xe8, + 0xa7, 0x86, 0x20, 0x82, 0x13, 0x7a, 0xf6, 0xaf, 0x14, 0x61, 0x36, 0xaf, 0xbb, 0x74, 0xd1, 0x91, + 0x07, 0x6e, 0xbc, 0x44, 0xb9, 0x21, 0xcb, 0x5c, 0x74, 0xcb, 0xa2, 0x1c, 0x2b, 0x0c, 0x3a, 0xfb, + 0x91, 0xdb, 0x92, 0x22, 0xe1, 0x50, 0x32, 0xfb, 0x75, 0x56, 0x8a, 0x05, 0x94, 0xe2, 0x85, 0xc4, + 0x89, 0x84, 0x4d, 0x84, 0xb6, 0x4a, 0x30, 0x2b, 0xc5, 0x02, 0xaa, 0xeb, 0x9b, 0x4a, 0x7d, 0xf4, + 0x4d, 0xc6, 0x10, 0x0d, 0x9d, 0xec, 0x10, 0xa1, 0x2f, 0x01, 0x6c, 0xb9, 0xbe, 0x1b, 0x6d, 0x33, + 0xea, 0xc3, 0xc7, 0xa6, 0xae, 0x78, 0xa9, 0x15, 0x45, 0x05, 0x6b, 0x14, 0xd1, 0xcb, 0x30, 0xa6, + 0x36, 0xe0, 0x6a, 0x95, 0x3d, 0x10, 0x69, 0x0f, 0xee, 0xc9, 0x69, 0x54, 0xc5, 0x3a, 0x9e, 0xfd, + 0x6e, 0x7a, 0xbd, 0x88, 0x1d, 0xa0, 0x8d, 0xaf, 0x35, 0xe8, 0xf8, 0x16, 0x7a, 0x8f, 0xaf, 0xfd, + 0x9b, 0x45, 0x98, 0x32, 0x1a, 0xeb, 0x44, 0x03, 0x9c, 0x59, 0x37, 0xe8, 0x3d, 0xe7, 0xc4, 0x44, + 0xec, 0x3f, 0xbb, 0xff, 0x56, 0xd1, 0xef, 0x42, 0xba, 0x03, 0x78, 0x7d, 0xf4, 0x25, 0x28, 0x7b, + 0x4e, 0xc4, 0x74, 0x57, 0x44, 0xec, 0xbb, 0x41, 0x88, 0x25, 0x72, 0x84, 0x13, 0xc5, 0xda, 0x55, + 0xc3, 0x69, 0x27, 0x24, 0xe9, 0x85, 0x4c, 0x79, 0x1f, 0x69, 0x74, 0xa3, 0x3a, 0x41, 0x19, 0xa4, + 0x7d, 0xcc, 0x61, 0xe8, 0x55, 0x18, 0x0f, 0x09, 0x5b, 0x15, 0x4b, 0x94, 0x95, 0x63, 0xcb, 0x6c, + 0x28, 0xe1, 0xf9, 0xb0, 0x06, 0xc3, 0x06, 0x66, 0xc2, 0xca, 0x0f, 0xf7, 0x60, 0xe5, 0x9f, 0x81, + 0x11, 0xf6, 0x43, 0xad, 0x00, 0x35, 0x1b, 0xab, 0xbc, 0x18, 0x4b, 0x78, 0x7a, 0xc1, 0x8c, 0x0e, + 0xb8, 0x60, 0x3e, 0x09, 0x93, 0x55, 0x87, 0xec, 0x06, 0xfe, 0xb2, 0xdf, 0x6c, 0x07, 0xae, 0x1f, + 0xa3, 0x59, 0x28, 0xb1, 0xdb, 0x81, 0xef, 0xed, 0x12, 0xa5, 0x80, 0x4b, 0x94, 0x31, 0xb7, 0x5b, + 0x70, 0xae, 0x1a, 0xdc, 0xf7, 0xef, 0x3b, 0x61, 0x73, 0xa1, 0xb6, 0xaa, 0xc9, 0xb9, 0xeb, 0x52, + 0xce, 0xe2, 0x46, 0x2c, 0x99, 0x67, 0xaa, 0x56, 0x93, 0xdf, 0xb5, 0x2b, 0xae, 0x47, 0x72, 0xb4, + 0x11, 0x7f, 0xb3, 0x60, 0xb4, 0x94, 0xe0, 0xab, 0x07, 0x23, 0x2b, 0xf7, 0xc1, 0xe8, 0x4d, 0x18, + 0xdd, 0x72, 0x89, 0xd7, 0xc4, 0x64, 0x4b, 0x2c, 0xb1, 0xa7, 0xf3, 0xdf, 0xe5, 0x57, 0x28, 0xa6, + 0xd4, 0x3e, 0x71, 0x29, 0x6d, 0x45, 0x54, 0xc6, 0x8a, 0x0c, 0xda, 0x81, 0x69, 0x29, 0x06, 0x48, + 0xa8, 0x58, 0x70, 0xcf, 0xf4, 0x92, 0x2d, 0x4c, 0xe2, 0x67, 0x0f, 0x0f, 0x2a, 0xd3, 0x38, 0x45, + 0x06, 0x77, 0x11, 0xa6, 0x62, 0xd9, 0x2e, 0x3d, 0x5a, 0x4b, 0x6c, 0xf8, 0x99, 0x58, 0xc6, 0x24, + 0x4c, 0x56, 0x6a, 0xff, 0x84, 0x05, 0x8f, 0x75, 0x8d, 0x8c, 0x90, 0xb4, 0x4f, 0x78, 0x16, 0xd2, + 0x92, 0x6f, 0xa1, 0xbf, 0xe4, 0x6b, 0xff, 0x03, 0x0b, 0xce, 0x2e, 0xef, 0xb6, 0xe3, 0xfd, 0xaa, + 0x6b, 0xbe, 0xee, 0xbc, 0x02, 0xc3, 0xbb, 0xa4, 0xe9, 0x76, 0x76, 0xc5, 0xcc, 0x55, 0xe4, 0xf1, + 0xb3, 0xc6, 0x4a, 0x8f, 0x0e, 0x2a, 0x13, 0xf5, 0x38, 0x08, 0x9d, 0x16, 0xe1, 0x05, 0x58, 0xa0, + 0xb3, 0x43, 0xdc, 0x7d, 0x9f, 0xdc, 0x76, 0x77, 0x5d, 0x69, 0x67, 0xd1, 0x53, 0x77, 0x36, 0x2f, + 0x07, 0x74, 0xfe, 0xcd, 0x8e, 0xe3, 0xc7, 0x6e, 0xbc, 0x2f, 0x1e, 0x66, 0x24, 0x11, 0x9c, 0xd0, + 0xb3, 0xbf, 0x69, 0xc1, 0x94, 0x5c, 0xf7, 0x0b, 0xcd, 0x66, 0x48, 0xa2, 0x08, 0xcd, 0x41, 0xc1, + 0x6d, 0x8b, 0x5e, 0x82, 0xe8, 0x65, 0x61, 0xb5, 0x86, 0x0b, 0x6e, 0x1b, 0xd5, 0xa0, 0xcc, 0xcd, + 0x35, 0x92, 0xc5, 0x35, 0x90, 0xd1, 0x07, 0xeb, 0xc1, 0x86, 0xac, 0x89, 0x13, 0x22, 0x92, 0x83, + 0x63, 0x67, 0x66, 0xd1, 0x7c, 0xf5, 0xba, 0x29, 0xca, 0xb1, 0xc2, 0x40, 0x57, 0x61, 0xd4, 0x0f, + 0x9a, 0xdc, 0x7a, 0x86, 0xdf, 0x7e, 0x6c, 0xc9, 0xae, 0x8b, 0x32, 0xac, 0xa0, 0xf6, 0x0f, 0x5b, + 0x30, 0x2e, 0xbf, 0x6c, 0x40, 0x66, 0x92, 0x6e, 0xad, 0x84, 0x91, 0x4c, 0xb6, 0x16, 0x65, 0x06, + 0x19, 0xc4, 0xe0, 0x01, 0x8b, 0xc7, 0xe1, 0x01, 0xed, 0x1f, 0x2f, 0xc0, 0xa4, 0xec, 0x4e, 0xbd, + 0xb3, 0x19, 0x91, 0x18, 0x6d, 0x40, 0xd9, 0xe1, 0x43, 0x4e, 0xe4, 0x8a, 0x7d, 0x2a, 0x5b, 0xf8, + 0x30, 0xe6, 0x27, 0xb9, 0x96, 0x17, 0x64, 0x6d, 0x9c, 0x10, 0x42, 0x1e, 0xcc, 0xf8, 0x41, 0xcc, + 0x8e, 0x68, 0x05, 0xef, 0xf5, 0x04, 0x92, 0xa6, 0x7e, 0x41, 0x50, 0x9f, 0x59, 0x4f, 0x53, 0xc1, + 0xdd, 0x84, 0xd1, 0xb2, 0x54, 0x78, 0x14, 0xf3, 0xc5, 0x0d, 0x7d, 0x16, 0xb2, 0xf5, 0x1d, 0xf6, + 0xaf, 0x59, 0x50, 0x96, 0x68, 0xa7, 0xf1, 0xda, 0xb5, 0x06, 0x23, 0x11, 0x9b, 0x04, 0x39, 0x34, + 0x76, 0xaf, 0x8e, 0xf3, 0xf9, 0x4a, 0x6e, 0x1e, 0xfe, 0x3f, 0xc2, 0x92, 0x06, 0xd3, 0x77, 0xab, + 0xee, 0x7f, 0x44, 0xf4, 0xdd, 0xaa, 0x3f, 0x39, 0x37, 0xcc, 0x7f, 0x65, 0x7d, 0xd6, 0xc4, 0x5a, + 0xca, 0x20, 0xb5, 0x43, 0xb2, 0xe5, 0x3e, 0x48, 0x33, 0x48, 0x35, 0x56, 0x8a, 0x05, 0x14, 0xbd, + 0x03, 0xe3, 0x0d, 0xa9, 0xe8, 0x4c, 0x8e, 0x81, 0x2b, 0x3d, 0x95, 0xee, 0xea, 0x7d, 0x86, 0x5b, + 0xd6, 0x2e, 0x69, 0xf5, 0xb1, 0x41, 0xcd, 0x7c, 0x6e, 0x2f, 0xf6, 0x7b, 0x6e, 0x4f, 0xe8, 0xe6, + 0x3f, 0x3e, 0xff, 0xa4, 0x05, 0xc3, 0x5c, 0x5d, 0x36, 0x98, 0x7e, 0x51, 0x7b, 0xae, 0x4a, 0xc6, + 0xee, 0x1e, 0x2d, 0x14, 0xcf, 0x4f, 0x68, 0x0d, 0xca, 0xec, 0x07, 0x53, 0x1b, 0x14, 0xf3, 0x4d, + 0x8a, 0x79, 0xab, 0x7a, 0x07, 0xef, 0xc9, 0x6a, 0x38, 0xa1, 0x60, 0xff, 0x68, 0x91, 0x1e, 0x55, + 0x09, 0xaa, 0x71, 0x83, 0x5b, 0x8f, 0xee, 0x06, 0x2f, 0x3c, 0xaa, 0x1b, 0xbc, 0x05, 0x53, 0x0d, + 0xed, 0x71, 0x2b, 0x99, 0xc9, 0xab, 0x3d, 0x17, 0x89, 0xf6, 0x0e, 0xc6, 0x55, 0x46, 0x4b, 0x26, + 0x11, 0x9c, 0xa6, 0x8a, 0xbe, 0x13, 0xc6, 0xf9, 0x3c, 0x8b, 0x56, 0xb8, 0xc5, 0xc2, 0x27, 0xf2, + 0xd7, 0x8b, 0xde, 0x04, 0x5b, 0x89, 0x75, 0xad, 0x3a, 0x36, 0x88, 0xd9, 0xbf, 0x32, 0x0a, 0x43, + 0xcb, 0x7b, 0xc4, 0x8f, 0x4f, 0xe1, 0x40, 0x6a, 0xc0, 0xa4, 0xeb, 0xef, 0x05, 0xde, 0x1e, 0x69, + 0x72, 0xf8, 0x71, 0x2e, 0xd7, 0xf3, 0x82, 0xf4, 0xe4, 0xaa, 0x41, 0x02, 0xa7, 0x48, 0x3e, 0x0a, + 0x09, 0xf3, 0x06, 0x0c, 0xf3, 0xb9, 0x17, 0xe2, 0x65, 0xa6, 0x32, 0x98, 0x0d, 0xa2, 0xd8, 0x05, + 0x89, 0xf4, 0xcb, 0xb5, 0xcf, 0xa2, 0x3a, 0x7a, 0x17, 0x26, 0xb7, 0xdc, 0x30, 0x8a, 0xa9, 0x68, + 0x18, 0xc5, 0xce, 0x6e, 0xfb, 0x21, 0x24, 0x4a, 0x35, 0x0e, 0x2b, 0x06, 0x25, 0x9c, 0xa2, 0x8c, + 0x5a, 0x30, 0x41, 0x85, 0x9c, 0xa4, 0xa9, 0x91, 0x63, 0x37, 0xa5, 0x54, 0x46, 0xb7, 0x75, 0x42, + 0xd8, 0xa4, 0x4b, 0x0f, 0x93, 0x06, 0x13, 0x8a, 0x46, 0x19, 0x47, 0xa1, 0x0e, 0x13, 0x2e, 0x0d, + 0x71, 0x18, 0x3d, 0x93, 0x98, 0xd9, 0x4a, 0xd9, 0x3c, 0x93, 0x34, 0xe3, 0x94, 0x2f, 0x43, 0x99, + 0xd0, 0x21, 0xa4, 0x84, 0x85, 0x62, 0xfc, 0xda, 0x60, 0x7d, 0x5d, 0x73, 0x1b, 0x61, 0x60, 0xca, + 0xf2, 0xcb, 0x92, 0x12, 0x4e, 0x88, 0xa2, 0x25, 0x18, 0x8e, 0x48, 0xe8, 0x92, 0x48, 0xa8, 0xc8, + 0x7b, 0x4c, 0x23, 0x43, 0xe3, 0xb6, 0xe7, 0xfc, 0x37, 0x16, 0x55, 0xe9, 0xf2, 0x72, 0x98, 0x34, + 0xc4, 0xb4, 0xe2, 0xda, 0xf2, 0x5a, 0x60, 0xa5, 0x58, 0x40, 0xd1, 0x1b, 0x30, 0x12, 0x12, 0x8f, + 0x29, 0x8b, 0x26, 0x06, 0x5f, 0xe4, 0x5c, 0xf7, 0xc4, 0xeb, 0x61, 0x49, 0x00, 0xdd, 0x02, 0x14, + 0x12, 0xca, 0x43, 0xb8, 0x7e, 0x4b, 0x19, 0x73, 0x08, 0x5d, 0xf7, 0xe3, 0xa2, 0xfd, 0x33, 0x38, + 0xc1, 0x90, 0x56, 0xa9, 0x38, 0xa3, 0x1a, 0xba, 0x01, 0x33, 0xaa, 0x74, 0xd5, 0x8f, 0x62, 0xc7, + 0x6f, 0x10, 0xa6, 0xe6, 0x2e, 0x27, 0x5c, 0x11, 0x4e, 0x23, 0xe0, 0xee, 0x3a, 0xf6, 0xcf, 0x51, + 0x76, 0x86, 0x8e, 0xd6, 0x29, 0xf0, 0x02, 0xaf, 0x9b, 0xbc, 0xc0, 0x85, 0xdc, 0x99, 0xcb, 0xe1, + 0x03, 0x0e, 0x2d, 0x18, 0xd3, 0x66, 0x36, 0x59, 0xb3, 0x56, 0x8f, 0x35, 0xdb, 0x81, 0x69, 0xba, + 0xd2, 0xef, 0x6c, 0x46, 0x24, 0xdc, 0x23, 0x4d, 0xb6, 0x30, 0x0b, 0x0f, 0xb7, 0x30, 0xd5, 0x2b, + 0xf3, 0xed, 0x14, 0x41, 0xdc, 0xd5, 0x04, 0x7a, 0x45, 0x6a, 0x4e, 0x8a, 0x86, 0x91, 0x16, 0xd7, + 0x8a, 0x1c, 0x1d, 0x54, 0xa6, 0xb5, 0x0f, 0xd1, 0x35, 0x25, 0xf6, 0x97, 0xe5, 0x37, 0xaa, 0xd7, + 0xfc, 0x86, 0x5a, 0x2c, 0xa9, 0xd7, 0x7c, 0xb5, 0x1c, 0x70, 0x82, 0x43, 0xf7, 0x28, 0x15, 0x41, + 0xd2, 0xaf, 0xf9, 0x54, 0x40, 0xc1, 0x0c, 0x62, 0xbf, 0x08, 0xb0, 0xfc, 0x80, 0x34, 0xf8, 0x52, + 0xd7, 0x1f, 0x20, 0xad, 0xfc, 0x07, 0x48, 0xfb, 0xdf, 0x5b, 0x30, 0xb9, 0xb2, 0x64, 0x88, 0x89, + 0xf3, 0x00, 0x5c, 0x36, 0x7a, 0xeb, 0xad, 0x75, 0xa9, 0x5b, 0xe7, 0xea, 0x51, 0x55, 0x8a, 0x35, + 0x0c, 0x74, 0x01, 0x8a, 0x5e, 0xc7, 0x17, 0x22, 0xcb, 0xc8, 0xe1, 0x41, 0xa5, 0x78, 0xbb, 0xe3, + 0x63, 0x5a, 0xa6, 0x59, 0x08, 0x16, 0x07, 0xb6, 0x10, 0xec, 0xeb, 0x5e, 0x85, 0x2a, 0x30, 0x74, + 0xff, 0xbe, 0xdb, 0xe4, 0x46, 0xec, 0x42, 0xef, 0xff, 0xd6, 0x5b, 0xab, 0xd5, 0x08, 0xf3, 0x72, + 0xfb, 0xab, 0x45, 0x98, 0x5b, 0xf1, 0xc8, 0x83, 0x0f, 0x68, 0xc8, 0x3f, 0xa8, 0x7d, 0xe3, 0xf1, + 0xf8, 0xc5, 0xe3, 0xda, 0xb0, 0xf6, 0x1f, 0x8f, 0x2d, 0x18, 0xe1, 0x8f, 0xd9, 0xd2, 0xac, 0xff, + 0xb5, 0xac, 0xd6, 0xf3, 0x07, 0x64, 0x9e, 0x3f, 0x8a, 0x0b, 0x73, 0x7e, 0x75, 0xd3, 0x8a, 0x52, + 0x2c, 0x89, 0xcf, 0x7d, 0x06, 0xc6, 0x75, 0xcc, 0x63, 0x59, 0x93, 0xff, 0xa5, 0x22, 0x4c, 0xd3, + 0x1e, 0x3c, 0xd2, 0x89, 0xb8, 0xdb, 0x3d, 0x11, 0x27, 0x6d, 0x51, 0xdc, 0x7f, 0x36, 0xde, 0x49, + 0xcf, 0xc6, 0x0b, 0x79, 0xb3, 0x71, 0xda, 0x73, 0xf0, 0xbd, 0x16, 0x9c, 0x59, 0xf1, 0x82, 0xc6, + 0x4e, 0xca, 0xea, 0xf7, 0x65, 0x18, 0xa3, 0xe7, 0x78, 0x64, 0x78, 0x11, 0x19, 0x7e, 0x65, 0x02, + 0x84, 0x75, 0x3c, 0xad, 0xda, 0xdd, 0xbb, 0xab, 0xd5, 0x2c, 0x77, 0x34, 0x01, 0xc2, 0x3a, 0x9e, + 0xfd, 0x0d, 0x0b, 0x2e, 0xde, 0x58, 0x5a, 0x4e, 0x96, 0x62, 0x97, 0x47, 0x1c, 0x95, 0x02, 0x9b, + 0x5a, 0x57, 0x12, 0x29, 0xb0, 0xca, 0x7a, 0x21, 0xa0, 0x1f, 0x15, 0x6f, 0xcf, 0x9f, 0xb5, 0xe0, + 0xcc, 0x0d, 0x37, 0xa6, 0xd7, 0x72, 0xda, 0x37, 0x8b, 0xde, 0xcb, 0x91, 0x1b, 0x07, 0xe1, 0x7e, + 0xda, 0x37, 0x0b, 0x2b, 0x08, 0xd6, 0xb0, 0x78, 0xcb, 0x7b, 0x2e, 0x33, 0xa3, 0x2a, 0x98, 0xaa, + 0x28, 0x2c, 0xca, 0xb1, 0xc2, 0xa0, 0x1f, 0xd6, 0x74, 0x43, 0x26, 0x4a, 0xec, 0x8b, 0x13, 0x56, + 0x7d, 0x58, 0x55, 0x02, 0x70, 0x82, 0x63, 0xff, 0x84, 0x05, 0xe7, 0x6e, 0x78, 0x9d, 0x28, 0x26, + 0xe1, 0x56, 0x64, 0x74, 0xf6, 0x45, 0x28, 0x13, 0x29, 0xae, 0x8b, 0xbe, 0x2a, 0x06, 0x53, 0xc9, + 0xf1, 0xdc, 0x31, 0x4c, 0xe1, 0x0d, 0xe0, 0x39, 0x70, 0x3c, 0xd7, 0xb1, 0x5f, 0x2c, 0xc0, 0xc4, + 0xcd, 0x8d, 0x8d, 0xda, 0x0d, 0x12, 0x8b, 0x5b, 0xac, 0xbf, 0xaa, 0x19, 0x6b, 0x1a, 0xb3, 0x5e, + 0x42, 0x51, 0x27, 0x76, 0xbd, 0x79, 0xee, 0x89, 0x3c, 0xbf, 0xea, 0xc7, 0x77, 0xc2, 0x7a, 0x1c, + 0xba, 0x7e, 0x2b, 0x53, 0xc7, 0x26, 0xef, 0xda, 0x62, 0xde, 0x5d, 0x8b, 0x5e, 0x84, 0x61, 0xe6, + 0x0a, 0x2d, 0xc5, 0x93, 0xc7, 0x95, 0x4c, 0xc1, 0x4a, 0x8f, 0x0e, 0x2a, 0xe5, 0xbb, 0x78, 0x95, + 0xff, 0xc1, 0x02, 0x15, 0xdd, 0x85, 0xb1, 0xed, 0x38, 0x6e, 0xdf, 0x24, 0x4e, 0x93, 0x84, 0xf2, + 0x74, 0xb8, 0x94, 0x75, 0x3a, 0xd0, 0x41, 0xe0, 0x68, 0xc9, 0x86, 0x4a, 0xca, 0x22, 0xac, 0xd3, + 0xb1, 0xeb, 0x00, 0x09, 0xec, 0x84, 0xf4, 0x0b, 0xf6, 0x1f, 0x58, 0x30, 0xc2, 0xbd, 0xd2, 0x42, + 0xf4, 0x59, 0x28, 0x91, 0x07, 0xa4, 0x21, 0x38, 0xc7, 0xcc, 0x0e, 0x27, 0x8c, 0x07, 0xd7, 0x96, + 0xd3, 0xff, 0x98, 0xd5, 0x42, 0x37, 0x61, 0x84, 0xf6, 0xf6, 0x86, 0x72, 0xd1, 0x7b, 0x32, 0xef, + 0x8b, 0xd5, 0xb4, 0x73, 0x5e, 0x45, 0x14, 0x61, 0x59, 0x9d, 0x69, 0x7e, 0x1b, 0xed, 0x3a, 0x3d, + 0xc0, 0xe2, 0x5e, 0xf7, 0xec, 0xc6, 0x52, 0x8d, 0x23, 0x09, 0x6a, 0x5c, 0xf3, 0x2b, 0x0b, 0x71, + 0x42, 0xc4, 0xde, 0x80, 0x32, 0x9d, 0xd4, 0x05, 0xcf, 0x75, 0x7a, 0x2b, 0x9d, 0x9f, 0x85, 0xb2, + 0x54, 0x00, 0x47, 0xc2, 0xb1, 0x89, 0x51, 0x95, 0xfa, 0xe1, 0x08, 0x27, 0x70, 0x7b, 0x0b, 0xce, + 0xb2, 0x97, 0x7f, 0x27, 0xde, 0x36, 0xf6, 0x58, 0xff, 0xc5, 0xfc, 0x9c, 0x10, 0xc4, 0xf8, 0xcc, + 0xcc, 0x6a, 0xbe, 0x03, 0xe3, 0x92, 0x62, 0x22, 0x94, 0xd9, 0x7f, 0x54, 0x82, 0xc7, 0x57, 0xeb, + 0xf9, 0x0e, 0x8b, 0xaf, 0xc2, 0x38, 0x67, 0xd3, 0xe8, 0xd2, 0x76, 0x3c, 0xd1, 0xae, 0x7a, 0x17, + 0xdb, 0xd0, 0x60, 0xd8, 0xc0, 0x44, 0x17, 0xa1, 0xe8, 0xbe, 0xe7, 0xa7, 0xcd, 0x70, 0x57, 0xdf, + 0x5c, 0xc7, 0xb4, 0x9c, 0x82, 0x29, 0xc7, 0xc7, 0x8f, 0x52, 0x05, 0x56, 0x5c, 0xdf, 0xeb, 0x30, + 0xe9, 0x46, 0x8d, 0xc8, 0x5d, 0xf5, 0xe9, 0x39, 0x93, 0x38, 0xbb, 0x26, 0x4a, 0x02, 0xda, 0x69, + 0x05, 0xc5, 0x29, 0x6c, 0xed, 0x5c, 0x1f, 0x1a, 0x98, 0x6b, 0xec, 0xeb, 0xe9, 0x43, 0x19, 0xe2, + 0x36, 0xfb, 0xba, 0x88, 0x19, 0xb5, 0x09, 0x86, 0x98, 0x7f, 0x70, 0x84, 0x25, 0x8c, 0x4a, 0x60, + 0x8d, 0x6d, 0xa7, 0xbd, 0xd0, 0x89, 0xb7, 0xab, 0x6e, 0xd4, 0x08, 0xf6, 0x48, 0xb8, 0xcf, 0x84, + 0xe7, 0xd1, 0x44, 0x02, 0x53, 0x80, 0xa5, 0x9b, 0x0b, 0x35, 0x8a, 0x89, 0xbb, 0xeb, 0x98, 0x5c, + 0x21, 0x9c, 0x04, 0x57, 0xb8, 0x00, 0x53, 0xb2, 0x99, 0x3a, 0x89, 0xd8, 0x1d, 0x31, 0xc6, 0x3a, + 0xa6, 0x4c, 0x6d, 0x45, 0xb1, 0xea, 0x56, 0x1a, 0x1f, 0xbd, 0x02, 0x13, 0xae, 0xef, 0xc6, 0xae, + 0x13, 0x07, 0x21, 0xbb, 0x61, 0xb9, 0x9c, 0xcc, 0x2c, 0xd9, 0x56, 0x75, 0x00, 0x36, 0xf1, 0xec, + 0x3f, 0x2c, 0xc1, 0x0c, 0x9b, 0xb6, 0x6f, 0xad, 0xb0, 0x8f, 0xcc, 0x0a, 0xbb, 0xdb, 0xbd, 0xc2, + 0x4e, 0x82, 0xdd, 0xfd, 0x30, 0x97, 0xd9, 0xbb, 0x50, 0x56, 0xb6, 0xc0, 0xd2, 0x19, 0xc0, 0xca, + 0x71, 0x06, 0xe8, 0xcf, 0x7d, 0xc8, 0x67, 0xdc, 0x62, 0xe6, 0x33, 0xee, 0xdf, 0xb6, 0x20, 0x31, + 0x89, 0x44, 0x37, 0xa1, 0xdc, 0x0e, 0x98, 0xd9, 0x41, 0x28, 0x6d, 0x79, 0x1e, 0xcf, 0xbc, 0xa8, + 0xf8, 0xa5, 0xc8, 0xc7, 0xaf, 0x26, 0x6b, 0xe0, 0xa4, 0x32, 0x5a, 0x84, 0x91, 0x76, 0x48, 0xea, + 0x31, 0x73, 0x81, 0xed, 0x4b, 0x87, 0xaf, 0x11, 0x8e, 0x8f, 0x65, 0x45, 0xfb, 0x97, 0x2c, 0x00, + 0xfe, 0x52, 0xea, 0xf8, 0x2d, 0x72, 0x0a, 0xda, 0xdf, 0x2a, 0x94, 0xa2, 0x36, 0x69, 0xf4, 0x32, + 0x08, 0x49, 0xfa, 0x53, 0x6f, 0x93, 0x46, 0x32, 0xe0, 0xf4, 0x1f, 0x66, 0xb5, 0xed, 0xef, 0x03, + 0x98, 0x4c, 0xd0, 0x56, 0x63, 0xb2, 0x8b, 0x9e, 0x37, 0x5c, 0xe2, 0x2e, 0xa4, 0x5c, 0xe2, 0xca, + 0x0c, 0x5b, 0x53, 0x34, 0xbe, 0x0b, 0xc5, 0x5d, 0xe7, 0x81, 0xd0, 0x24, 0x3d, 0xdb, 0xbb, 0x1b, + 0x94, 0xfe, 0xfc, 0x9a, 0xf3, 0x80, 0xcb, 0x4c, 0xcf, 0xca, 0x05, 0xb2, 0xe6, 0x3c, 0x38, 0xe2, + 0x66, 0x1f, 0xec, 0x90, 0xba, 0xed, 0x46, 0xf1, 0x57, 0xfe, 0x53, 0xf2, 0x9f, 0x2d, 0x3b, 0xda, + 0x08, 0x6b, 0xcb, 0xf5, 0xc5, 0xbb, 0xe1, 0x40, 0x6d, 0xb9, 0x7e, 0xba, 0x2d, 0xd7, 0x1f, 0xa0, + 0x2d, 0xd7, 0x47, 0xef, 0xc3, 0x88, 0x78, 0xa3, 0x67, 0xb6, 0xde, 0xa6, 0x96, 0x2a, 0xaf, 0x3d, + 0xf1, 0xc4, 0xcf, 0xdb, 0xbc, 0x26, 0x65, 0x42, 0x51, 0xda, 0xb7, 0x5d, 0xd9, 0x20, 0xfa, 0x1b, + 0x16, 0x4c, 0x8a, 0xdf, 0x98, 0xbc, 0xd7, 0x21, 0x51, 0x2c, 0x78, 0xcf, 0x4f, 0x0f, 0xde, 0x07, + 0x51, 0x91, 0x77, 0xe5, 0xd3, 0xf2, 0x98, 0x35, 0x81, 0x7d, 0x7b, 0x94, 0xea, 0x05, 0xfa, 0x47, + 0x16, 0x9c, 0xdd, 0x75, 0x1e, 0xf0, 0x16, 0x79, 0x19, 0x76, 0x62, 0x37, 0x10, 0xb6, 0xeb, 0x9f, + 0x1d, 0x6c, 0xfa, 0xbb, 0xaa, 0xf3, 0x4e, 0x4a, 0x33, 0xd7, 0xb3, 0x59, 0x28, 0x7d, 0xbb, 0x9a, + 0xd9, 0xaf, 0xb9, 0x2d, 0x18, 0x95, 0xeb, 0x2d, 0x43, 0xf2, 0xae, 0xea, 0x8c, 0xf5, 0xb1, 0x4d, + 0x24, 0x74, 0xbf, 0x34, 0xda, 0x8e, 0x58, 0x6b, 0x8f, 0xb4, 0x9d, 0x77, 0x61, 0x5c, 0x5f, 0x63, + 0x8f, 0xb4, 0xad, 0xf7, 0xe0, 0x4c, 0xc6, 0x5a, 0x7a, 0xa4, 0x4d, 0xde, 0x87, 0x0b, 0xb9, 0xeb, + 0xe3, 0x51, 0x36, 0x6c, 0xff, 0xa2, 0xa5, 0x9f, 0x83, 0xa7, 0xa0, 0x82, 0x5f, 0x32, 0x55, 0xf0, + 0x97, 0x7a, 0xef, 0x9c, 0x1c, 0x3d, 0xfc, 0x3b, 0x7a, 0xa7, 0xe9, 0xa9, 0x8e, 0xde, 0x80, 0x61, + 0x8f, 0x96, 0x48, 0xe3, 0x10, 0xbb, 0xff, 0x8e, 0x4c, 0x78, 0x29, 0x56, 0x1e, 0x61, 0x41, 0xc1, + 0xfe, 0x55, 0x0b, 0x4a, 0xa7, 0x30, 0x12, 0xd8, 0x1c, 0x89, 0xe7, 0x73, 0x49, 0x8b, 0x90, 0x66, + 0xf3, 0xd8, 0xb9, 0xbf, 0xfc, 0x20, 0x26, 0x7e, 0xc4, 0x44, 0xc5, 0xcc, 0x81, 0xf9, 0x2e, 0x38, + 0x73, 0x3b, 0x70, 0x9a, 0x8b, 0x8e, 0xe7, 0xf8, 0x0d, 0x12, 0xae, 0xfa, 0xad, 0xbe, 0x56, 0x4a, + 0xba, 0x4d, 0x51, 0xa1, 0x9f, 0x4d, 0x91, 0xbd, 0x0d, 0x48, 0x6f, 0x40, 0xd8, 0x71, 0x62, 0x18, + 0x71, 0x79, 0x53, 0x62, 0xf8, 0x9f, 0xce, 0xe6, 0xee, 0xba, 0x7a, 0xa6, 0x59, 0x28, 0xf2, 0x02, + 0x2c, 0x09, 0xd9, 0xaf, 0x42, 0xa6, 0xef, 0x56, 0x7f, 0xb5, 0x81, 0xfd, 0x32, 0xcc, 0xb0, 0x9a, + 0xc7, 0x13, 0x69, 0xed, 0x1f, 0xb0, 0x60, 0x6a, 0x3d, 0x15, 0x9b, 0xe2, 0x0a, 0x7b, 0xeb, 0xcb, + 0xd0, 0xfb, 0xd6, 0x59, 0x29, 0x16, 0xd0, 0x13, 0xd7, 0x2f, 0xfd, 0x99, 0x05, 0x89, 0xab, 0xe4, + 0x29, 0x30, 0x55, 0x4b, 0x06, 0x53, 0x95, 0xa9, 0xf7, 0x50, 0xdd, 0xc9, 0xe3, 0xa9, 0xd0, 0x2d, + 0x15, 0x17, 0xa0, 0x87, 0xca, 0x23, 0x21, 0xc3, 0xbd, 0xc8, 0x27, 0xcd, 0xe0, 0x01, 0x32, 0x52, + 0x00, 0x33, 0x13, 0x52, 0xb8, 0x1f, 0x11, 0x33, 0x21, 0xd5, 0x9f, 0x9c, 0xdd, 0x57, 0xd3, 0xba, + 0xcc, 0x4e, 0xa5, 0x6f, 0x67, 0x66, 0xdf, 0x8e, 0xe7, 0xbe, 0x4f, 0x54, 0x70, 0x93, 0x8a, 0x30, + 0xe3, 0x16, 0xa5, 0x47, 0x07, 0x95, 0x09, 0xf5, 0x8f, 0x47, 0xc0, 0x4a, 0xaa, 0xd8, 0x37, 0x61, + 0x2a, 0x35, 0x60, 0xe8, 0x65, 0x18, 0x6a, 0x6f, 0x3b, 0x11, 0x49, 0x99, 0x46, 0x0e, 0xd5, 0x68, + 0xe1, 0xd1, 0x41, 0x65, 0x52, 0x55, 0x60, 0x25, 0x98, 0x63, 0xdb, 0xff, 0xd3, 0x82, 0xd2, 0x7a, + 0xd0, 0x3c, 0x8d, 0xc5, 0xf4, 0xba, 0xb1, 0x98, 0x9e, 0xc8, 0x8b, 0x1f, 0x98, 0xbb, 0x8e, 0x56, + 0x52, 0xeb, 0xe8, 0x52, 0x2e, 0x85, 0xde, 0x4b, 0x68, 0x17, 0xc6, 0x58, 0x54, 0x42, 0x61, 0xaa, + 0xf9, 0xa2, 0xc1, 0xdf, 0x57, 0x52, 0xfc, 0xfd, 0x94, 0x86, 0xaa, 0x71, 0xf9, 0xcf, 0xc0, 0x88, + 0x30, 0x17, 0x4c, 0x1b, 0xb8, 0x0b, 0x5c, 0x2c, 0xe1, 0xf6, 0x4f, 0x16, 0xc1, 0x88, 0x82, 0x88, + 0x7e, 0xcd, 0x82, 0xf9, 0x90, 0x7b, 0x0c, 0x36, 0xab, 0x9d, 0xd0, 0xf5, 0x5b, 0xf5, 0xc6, 0x36, + 0x69, 0x76, 0x3c, 0xd7, 0x6f, 0xad, 0xb6, 0xfc, 0x40, 0x15, 0x2f, 0x3f, 0x20, 0x8d, 0x0e, 0xd3, + 0xf9, 0xf7, 0x09, 0xb9, 0xa8, 0xcc, 0x71, 0xae, 0x1f, 0x1e, 0x54, 0xe6, 0xf1, 0xb1, 0x68, 0xe3, + 0x63, 0xf6, 0x05, 0x7d, 0xc3, 0x82, 0x6b, 0x3c, 0x38, 0xe0, 0xe0, 0xfd, 0xef, 0x21, 0x0d, 0xd5, + 0x24, 0xa9, 0x84, 0xc8, 0x06, 0x09, 0x77, 0x17, 0x5f, 0x11, 0x03, 0x7a, 0xad, 0x76, 0xbc, 0xb6, + 0xf0, 0x71, 0x3b, 0x67, 0xff, 0xcb, 0x22, 0x4c, 0x08, 0x67, 0x75, 0x11, 0x05, 0xe5, 0x65, 0x63, + 0x49, 0x3c, 0x99, 0x5a, 0x12, 0x33, 0x06, 0xf2, 0xc9, 0x04, 0x40, 0x89, 0x60, 0xc6, 0x73, 0xa2, + 0xf8, 0x26, 0x71, 0xc2, 0x78, 0x93, 0x38, 0xdc, 0x4c, 0xa5, 0x78, 0x6c, 0x93, 0x1a, 0xa5, 0x7e, + 0xb9, 0x9d, 0x26, 0x86, 0xbb, 0xe9, 0xa3, 0x3d, 0x40, 0xcc, 0xd6, 0x26, 0x74, 0xfc, 0x88, 0x7f, + 0x8b, 0x2b, 0xde, 0x03, 0x8e, 0xd7, 0xea, 0x9c, 0x68, 0x15, 0xdd, 0xee, 0xa2, 0x86, 0x33, 0x5a, + 0xd0, 0x6c, 0xa8, 0x86, 0x06, 0xb5, 0xa1, 0x1a, 0xee, 0xe3, 0x45, 0xe2, 0xc3, 0x74, 0x57, 0xbc, + 0x81, 0xb7, 0xa1, 0xac, 0x6c, 0xdd, 0xc4, 0xa1, 0xd3, 0x3b, 0x6c, 0x47, 0x9a, 0x02, 0x57, 0x91, + 0x24, 0x76, 0x96, 0x09, 0x39, 0xfb, 0x1f, 0x17, 0x8c, 0x06, 0xf9, 0x24, 0xae, 0xc3, 0xa8, 0x13, + 0x45, 0x6e, 0xcb, 0x27, 0x4d, 0xb1, 0x63, 0x3f, 0x9e, 0xb7, 0x63, 0x8d, 0x66, 0x98, 0xbd, 0xe1, + 0x82, 0xa8, 0x89, 0x15, 0x0d, 0x74, 0x93, 0x1b, 0x03, 0xed, 0x49, 0x7e, 0x7e, 0x30, 0x6a, 0x20, + 0xcd, 0x85, 0xf6, 0x08, 0x16, 0xf5, 0xd1, 0x17, 0xb9, 0xb5, 0xd6, 0x2d, 0x3f, 0xb8, 0xef, 0xdf, + 0x08, 0x02, 0xe9, 0x61, 0x36, 0x18, 0xc1, 0x19, 0x69, 0xa3, 0xa5, 0xaa, 0x63, 0x93, 0xda, 0x60, + 0x31, 0x79, 0xbe, 0x1b, 0xce, 0x50, 0xd2, 0xa6, 0x9f, 0x48, 0x84, 0x08, 0x4c, 0x89, 0x48, 0x08, + 0xb2, 0x4c, 0x8c, 0x5d, 0x26, 0xab, 0x6e, 0xd6, 0x4e, 0x14, 0x7a, 0xb7, 0x4c, 0x12, 0x38, 0x4d, + 0xd3, 0xfe, 0x19, 0x0b, 0x98, 0x85, 0xfb, 0x29, 0xb0, 0x0c, 0x9f, 0x33, 0x59, 0x86, 0xd9, 0xbc, + 0x41, 0xce, 0xe1, 0x16, 0x5e, 0xe2, 0x2b, 0xab, 0x16, 0x06, 0x0f, 0xf6, 0xc5, 0x4b, 0xf9, 0x00, + 0x5c, 0xea, 0xff, 0xb1, 0xf8, 0x21, 0xa6, 0x9c, 0xce, 0xd1, 0xf7, 0xc0, 0x68, 0xc3, 0x69, 0x3b, + 0x0d, 0x1e, 0xb2, 0x37, 0x57, 0x63, 0x63, 0x54, 0x9a, 0x5f, 0x12, 0x35, 0xb8, 0x06, 0x42, 0x46, + 0xd4, 0x18, 0x95, 0xc5, 0x7d, 0xb5, 0x0e, 0xaa, 0xc9, 0xb9, 0x1d, 0x98, 0x30, 0x88, 0x3d, 0x52, + 0x71, 0xf5, 0x7b, 0xf8, 0x15, 0xab, 0x22, 0xc0, 0xec, 0xc2, 0x8c, 0xaf, 0xfd, 0xa7, 0x17, 0x8a, + 0x14, 0x41, 0x3e, 0xde, 0xef, 0x12, 0x65, 0xb7, 0x8f, 0x66, 0xc1, 0x9f, 0x22, 0x83, 0xbb, 0x29, + 0xdb, 0x3f, 0x65, 0xc1, 0x63, 0x3a, 0xa2, 0x16, 0x0f, 0xa0, 0x9f, 0x0e, 0xb8, 0x0a, 0xa3, 0x41, + 0x9b, 0x84, 0x4e, 0x1c, 0x84, 0xe2, 0xd6, 0xb8, 0x2a, 0x07, 0xfd, 0x8e, 0x28, 0x3f, 0x12, 0xb1, + 0x13, 0x25, 0x75, 0x59, 0x8e, 0x55, 0x4d, 0x64, 0xc3, 0x30, 0x1b, 0x8c, 0x48, 0xc4, 0x6a, 0x60, + 0x67, 0x00, 0x7b, 0x0e, 0x8d, 0xb0, 0x80, 0xd8, 0x7f, 0x64, 0xf1, 0x85, 0xa5, 0x77, 0x1d, 0xbd, + 0x07, 0xd3, 0xbb, 0x4e, 0xdc, 0xd8, 0x5e, 0x7e, 0xd0, 0x0e, 0xb9, 0xea, 0x5b, 0x8e, 0xd3, 0xb3, + 0xfd, 0xc6, 0x49, 0xfb, 0xc8, 0xc4, 0x00, 0x6d, 0x2d, 0x45, 0x0c, 0x77, 0x91, 0x47, 0x9b, 0x30, + 0xc6, 0xca, 0x98, 0xa5, 0x73, 0xd4, 0x8b, 0x35, 0xc8, 0x6b, 0x4d, 0xbd, 0x28, 0xaf, 0x25, 0x74, + 0xb0, 0x4e, 0xd4, 0xfe, 0x4a, 0x91, 0xef, 0x76, 0xc6, 0x6d, 0x3f, 0x03, 0x23, 0xed, 0xa0, 0xb9, + 0xb4, 0x5a, 0xc5, 0x62, 0x16, 0xd4, 0x35, 0x52, 0xe3, 0xc5, 0x58, 0xc2, 0xd1, 0x6b, 0x00, 0xe4, + 0x41, 0x4c, 0x42, 0xdf, 0xf1, 0x94, 0x41, 0x88, 0x32, 0x81, 0xac, 0x06, 0xeb, 0x41, 0x7c, 0x37, + 0x22, 0xdf, 0xb5, 0xac, 0x50, 0xb0, 0x86, 0x8e, 0xae, 0x03, 0xb4, 0xc3, 0x60, 0xcf, 0x6d, 0x32, + 0xd7, 0xb9, 0xa2, 0x69, 0x2e, 0x51, 0x53, 0x10, 0xac, 0x61, 0xa1, 0xd7, 0x60, 0xa2, 0xe3, 0x47, + 0x9c, 0x43, 0x71, 0x36, 0x45, 0xe4, 0xc1, 0xd1, 0xc4, 0x72, 0xe1, 0xae, 0x0e, 0xc4, 0x26, 0x2e, + 0x5a, 0x80, 0xe1, 0xd8, 0x61, 0xf6, 0x0e, 0x43, 0xf9, 0x76, 0x8b, 0x1b, 0x14, 0x43, 0x0f, 0x18, + 0x4b, 0x2b, 0x60, 0x51, 0x11, 0xbd, 0x2d, 0xfd, 0x10, 0xf8, 0x59, 0x2f, 0x0c, 0x86, 0x07, 0xbb, + 0x17, 0x34, 0x2f, 0x04, 0x61, 0x88, 0x6c, 0xd0, 0xb2, 0xbf, 0x51, 0x06, 0x48, 0xd8, 0x71, 0xf4, + 0x7e, 0xd7, 0x79, 0xf4, 0x5c, 0x6f, 0x06, 0xfe, 0xe4, 0x0e, 0x23, 0xf4, 0xfd, 0x16, 0x8c, 0x39, + 0x9e, 0x17, 0x34, 0x9c, 0x98, 0x8d, 0x72, 0xa1, 0xf7, 0x79, 0x28, 0xda, 0x5f, 0x48, 0x6a, 0xf0, + 0x2e, 0xbc, 0x28, 0x17, 0x9e, 0x06, 0xe9, 0xdb, 0x0b, 0xbd, 0x61, 0xf4, 0x29, 0x29, 0xa5, 0xf1, + 0xe5, 0x31, 0x97, 0x96, 0xd2, 0xca, 0xec, 0xe8, 0xd7, 0x04, 0x34, 0x74, 0xd7, 0x08, 0x2a, 0x57, + 0xca, 0x8f, 0xaf, 0x60, 0x70, 0xa5, 0xfd, 0xe2, 0xc9, 0xa1, 0x9a, 0xee, 0x38, 0x35, 0x94, 0x1f, + 0x84, 0x44, 0x13, 0x7f, 0xfa, 0x38, 0x4d, 0xbd, 0x0b, 0x53, 0x4d, 0xf3, 0x6e, 0x17, 0xab, 0xe9, + 0xe9, 0x3c, 0xba, 0x29, 0x56, 0x20, 0xb9, 0xcd, 0x53, 0x00, 0x9c, 0x26, 0x8c, 0x6a, 0xdc, 0x85, + 0x6d, 0xd5, 0xdf, 0x0a, 0x84, 0xe1, 0xb9, 0x9d, 0x3b, 0x97, 0xfb, 0x51, 0x4c, 0x76, 0x29, 0x66, + 0x72, 0x69, 0xaf, 0x8b, 0xba, 0x58, 0x51, 0x41, 0x6f, 0xc0, 0x30, 0xf3, 0x81, 0x8d, 0x66, 0x47, + 0xf3, 0x15, 0x85, 0x66, 0xf8, 0x86, 0x64, 0x53, 0xb1, 0xbf, 0x11, 0x16, 0x14, 0xd0, 0x4d, 0x19, + 0xe3, 0x25, 0x5a, 0xf5, 0xef, 0x46, 0x84, 0xc5, 0x78, 0x29, 0x2f, 0x7e, 0x3c, 0x09, 0xdf, 0xc2, + 0xcb, 0x33, 0x43, 0xc3, 0x1b, 0x35, 0x29, 0x73, 0x24, 0xfe, 0xcb, 0x88, 0xf3, 0xb3, 0x90, 0xdf, + 0x3d, 0x33, 0x2a, 0x7d, 0x32, 0x9c, 0xf7, 0x4c, 0x12, 0x38, 0x4d, 0x93, 0x32, 0x9a, 0x7c, 0xe7, + 0x0a, 0xd3, 0xf5, 0x7e, 0xfb, 0x9f, 0xcb, 0xd7, 0xec, 0x92, 0xe1, 0x25, 0x58, 0xd4, 0x3f, 0xd5, + 0x5b, 0x7f, 0xce, 0x87, 0xe9, 0xf4, 0x16, 0x7d, 0xa4, 0x5c, 0xc6, 0x1f, 0x94, 0x60, 0xd2, 0x5c, + 0x52, 0xe8, 0x1a, 0x94, 0x05, 0x11, 0x15, 0x70, 0x54, 0xed, 0x92, 0x35, 0x09, 0xc0, 0x09, 0x0e, + 0x8b, 0x33, 0xcb, 0xaa, 0x6b, 0x26, 0x87, 0x49, 0x9c, 0x59, 0x05, 0xc1, 0x1a, 0x16, 0x95, 0x97, + 0x36, 0x83, 0x20, 0x56, 0x97, 0x8a, 0x5a, 0x77, 0x8b, 0xac, 0x14, 0x0b, 0x28, 0xbd, 0x4c, 0x76, + 0x48, 0xe8, 0x13, 0xcf, 0x8c, 0x63, 0xa6, 0x2e, 0x93, 0x5b, 0x3a, 0x10, 0x9b, 0xb8, 0xf4, 0x96, + 0x0c, 0x22, 0xb6, 0x90, 0x85, 0x54, 0x96, 0x98, 0x70, 0xd6, 0xb9, 0x37, 0xb9, 0x84, 0xa3, 0x2f, + 0xc0, 0x63, 0xca, 0xf9, 0x1b, 0x73, 0x25, 0xb4, 0x6c, 0x71, 0xd8, 0x50, 0xa2, 0x3c, 0xb6, 0x94, + 0x8d, 0x86, 0xf3, 0xea, 0xa3, 0xd7, 0x61, 0x52, 0x70, 0xee, 0x92, 0xe2, 0x88, 0x69, 0x17, 0x71, + 0xcb, 0x80, 0xe2, 0x14, 0xb6, 0x8c, 0xc4, 0xc6, 0x98, 0x67, 0x49, 0x61, 0xb4, 0x3b, 0x12, 0x9b, + 0x0e, 0xc7, 0x5d, 0x35, 0xd0, 0x02, 0x4c, 0x71, 0xd6, 0xca, 0xf5, 0x5b, 0x7c, 0x4e, 0x84, 0x67, + 0x89, 0xda, 0x52, 0x77, 0x4c, 0x30, 0x4e, 0xe3, 0xa3, 0x57, 0x61, 0xdc, 0x09, 0x1b, 0xdb, 0x6e, + 0x4c, 0x1a, 0x71, 0x27, 0xe4, 0x2e, 0x27, 0x9a, 0x61, 0xc9, 0x82, 0x06, 0xc3, 0x06, 0xa6, 0xfd, + 0x3e, 0x9c, 0xc9, 0x70, 0x4a, 0xa3, 0x0b, 0xc7, 0x69, 0xbb, 0xf2, 0x9b, 0x52, 0xc6, 0x98, 0x0b, + 0xb5, 0x55, 0xf9, 0x35, 0x1a, 0x16, 0x5d, 0x9d, 0xcc, 0x79, 0x4d, 0x4b, 0x30, 0xa1, 0x56, 0xe7, + 0x8a, 0x04, 0xe0, 0x04, 0xc7, 0xfe, 0x5f, 0x05, 0x98, 0xca, 0x50, 0xac, 0xb3, 0x24, 0x07, 0x29, + 0xd9, 0x23, 0xc9, 0x69, 0x60, 0x06, 0xf6, 0x2b, 0x1c, 0x23, 0xb0, 0x5f, 0xb1, 0x5f, 0x60, 0xbf, + 0xd2, 0x07, 0x09, 0xec, 0x67, 0x8e, 0xd8, 0xd0, 0x40, 0x23, 0x96, 0x11, 0x0c, 0x70, 0xf8, 0x98, + 0xc1, 0x00, 0x8d, 0x41, 0x1f, 0x19, 0x60, 0xd0, 0x7f, 0xb4, 0x00, 0xd3, 0x69, 0x03, 0xb8, 0x53, + 0x50, 0xc7, 0xbe, 0x61, 0xa8, 0x63, 0xb3, 0x53, 0x86, 0xa4, 0xcd, 0xf2, 0xf2, 0x54, 0xb3, 0x38, + 0xa5, 0x9a, 0xfd, 0xe4, 0x40, 0xd4, 0x7a, 0xab, 0x69, 0xff, 0x6e, 0x01, 0xce, 0xa5, 0xab, 0x2c, + 0x79, 0x8e, 0xbb, 0x7b, 0x0a, 0x63, 0x73, 0xc7, 0x18, 0x9b, 0xe7, 0x07, 0xf9, 0x1a, 0xd6, 0xb5, + 0xdc, 0x01, 0x7a, 0x2b, 0x35, 0x40, 0xd7, 0x06, 0x27, 0xd9, 0x7b, 0x94, 0xbe, 0x59, 0x84, 0x4b, + 0x99, 0xf5, 0x12, 0x6d, 0xe6, 0x8a, 0xa1, 0xcd, 0xbc, 0x9e, 0xd2, 0x66, 0xda, 0xbd, 0x6b, 0x9f, + 0x8c, 0x7a, 0x53, 0x78, 0x0b, 0xb2, 0xe0, 0x6f, 0x0f, 0xa9, 0xda, 0x34, 0xbc, 0x05, 0x15, 0x21, + 0x6c, 0xd2, 0xfd, 0x8b, 0xa4, 0xd2, 0xfc, 0x37, 0x16, 0x5c, 0xc8, 0x9c, 0x9b, 0x53, 0x50, 0x61, + 0xad, 0x9b, 0x2a, 0xac, 0x67, 0x06, 0x5e, 0xad, 0x39, 0x3a, 0xad, 0x3f, 0x2c, 0xe6, 0x7c, 0x0b, + 0x13, 0xd0, 0xef, 0xc0, 0x98, 0xd3, 0x68, 0x90, 0x28, 0x5a, 0x0b, 0x9a, 0x2a, 0x18, 0xda, 0xf3, + 0x4c, 0xce, 0x4a, 0x8a, 0x8f, 0x0e, 0x2a, 0x73, 0x69, 0x12, 0x09, 0x18, 0xeb, 0x14, 0xcc, 0xf8, + 0x8d, 0x85, 0x13, 0x8d, 0xdf, 0x78, 0x1d, 0x60, 0x4f, 0x71, 0xeb, 0x69, 0x21, 0x5f, 0xe3, 0xe3, + 0x35, 0x2c, 0xf4, 0x45, 0x18, 0x8d, 0xc4, 0x35, 0x2e, 0x96, 0xe2, 0x8b, 0x03, 0xce, 0x95, 0xb3, + 0x49, 0x3c, 0xd3, 0x2d, 0x5d, 0xe9, 0x43, 0x14, 0x49, 0xf4, 0x1d, 0x30, 0x1d, 0xf1, 0xa8, 0x27, + 0x4b, 0x9e, 0x13, 0x31, 0x1f, 0x07, 0xb1, 0x0a, 0x99, 0xaf, 0x79, 0x3d, 0x05, 0xc3, 0x5d, 0xd8, + 0x68, 0x45, 0x7e, 0x14, 0x0b, 0xd1, 0xc2, 0x17, 0xe6, 0x95, 0xe4, 0x83, 0x44, 0x8a, 0xa5, 0xb3, + 0xe9, 0xe1, 0x67, 0x03, 0xaf, 0xd5, 0xb4, 0x7f, 0xb4, 0x04, 0x8f, 0xf7, 0x38, 0xc4, 0xd0, 0x82, + 0xf9, 0x46, 0xf9, 0x6c, 0x5a, 0xfa, 0x9d, 0xcb, 0xac, 0x6c, 0x88, 0xc3, 0xa9, 0xb5, 0x52, 0xf8, + 0xc0, 0x6b, 0xe5, 0x87, 0x2c, 0x4d, 0x2f, 0xc1, 0x2d, 0xe9, 0x3e, 0x77, 0xcc, 0xc3, 0xf9, 0x04, + 0x15, 0x15, 0x5b, 0x19, 0xd2, 0xfe, 0xf5, 0x81, 0xbb, 0x33, 0xb0, 0xf8, 0x7f, 0xba, 0xda, 0xd9, + 0xaf, 0x58, 0xf0, 0x64, 0x66, 0x7f, 0x0d, 0x9b, 0x8a, 0x6b, 0x50, 0x6e, 0xd0, 0x42, 0xcd, 0x6f, + 0x2a, 0x71, 0x28, 0x95, 0x00, 0x9c, 0xe0, 0x18, 0xa6, 0x13, 0x85, 0xbe, 0xa6, 0x13, 0xff, 0xc2, + 0x82, 0xae, 0x05, 0x7c, 0x0a, 0x27, 0xe9, 0xaa, 0x79, 0x92, 0x7e, 0x7c, 0x90, 0xb9, 0xcc, 0x39, + 0x44, 0xff, 0xf3, 0x14, 0x9c, 0xcf, 0x71, 0x94, 0xd8, 0x83, 0x99, 0x56, 0x83, 0x98, 0x1e, 0x69, + 0xe2, 0x63, 0x32, 0x9d, 0xf7, 0x7a, 0xba, 0xaf, 0xb1, 0xdc, 0x38, 0x33, 0x5d, 0x28, 0xb8, 0xbb, + 0x09, 0xf4, 0x15, 0x0b, 0xce, 0x3a, 0xf7, 0xa3, 0xae, 0x0c, 0x88, 0x62, 0xcd, 0xbc, 0x94, 0xa9, + 0xa5, 0xe8, 0x93, 0x31, 0x91, 0x27, 0x0b, 0xca, 0xc2, 0xc2, 0x99, 0x6d, 0x21, 0x2c, 0xe2, 0x57, + 0x52, 0x7e, 0xbb, 0x87, 0xcf, 0x64, 0x96, 0x47, 0x0b, 0x3f, 0x53, 0x25, 0x04, 0x2b, 0x3a, 0xe8, + 0x1e, 0x94, 0x5b, 0xd2, 0xcd, 0x4c, 0x9c, 0xd9, 0x99, 0x97, 0x60, 0xa6, 0x2f, 0x1a, 0x7f, 0x37, + 0x54, 0x20, 0x9c, 0x90, 0x42, 0xaf, 0x43, 0xd1, 0xdf, 0x8a, 0x7a, 0x65, 0xd9, 0x49, 0x99, 0x1a, + 0x71, 0x7f, 0xe4, 0xf5, 0x95, 0x3a, 0xa6, 0x15, 0xd1, 0x4d, 0x28, 0x86, 0x9b, 0x4d, 0xa1, 0x58, + 0xcb, 0xe4, 0x4b, 0xf1, 0x62, 0x35, 0x7b, 0x91, 0x70, 0x4a, 0x78, 0xb1, 0x8a, 0x29, 0x09, 0x54, + 0x83, 0x21, 0xe6, 0x53, 0x20, 0xf4, 0x67, 0x99, 0x0c, 0x69, 0x0f, 0xdf, 0x1c, 0xee, 0xb4, 0xcc, + 0x10, 0x30, 0x27, 0x84, 0x36, 0x60, 0xb8, 0xc1, 0x32, 0xb2, 0x88, 0x90, 0xc9, 0x9f, 0xca, 0x54, + 0xa1, 0xf5, 0x48, 0x55, 0x23, 0x34, 0x4a, 0x0c, 0x03, 0x0b, 0x5a, 0x8c, 0x2a, 0x69, 0x6f, 0x6f, + 0x45, 0x4c, 0x04, 0xcf, 0xa3, 0xda, 0x23, 0x03, 0x93, 0xa0, 0xca, 0x30, 0xb0, 0xa0, 0x85, 0x3e, + 0x03, 0x85, 0xad, 0x86, 0x70, 0x39, 0xc8, 0xd4, 0xa5, 0x99, 0x2e, 0xe5, 0x8b, 0xc3, 0x87, 0x07, + 0x95, 0xc2, 0xca, 0x12, 0x2e, 0x6c, 0x35, 0xd0, 0x3a, 0x8c, 0x6c, 0x71, 0x27, 0x54, 0xa1, 0x2e, + 0x7b, 0x3a, 0xdb, 0x3f, 0xb6, 0xcb, 0x4f, 0x95, 0x9b, 0xca, 0x0b, 0x00, 0x96, 0x44, 0x58, 0x10, + 0x48, 0xe5, 0x4c, 0x2b, 0xa2, 0x21, 0xcf, 0x1f, 0xcf, 0x01, 0x9a, 0xbb, 0xb7, 0x27, 0x2e, 0xb9, + 0x58, 0xa3, 0x88, 0xbe, 0x0c, 0x65, 0x47, 0xe6, 0xde, 0x13, 0xd1, 0x22, 0x5e, 0xcc, 0xdc, 0x98, + 0xbd, 0xd3, 0x12, 0xf2, 0x55, 0xad, 0x90, 0x70, 0x42, 0x14, 0xed, 0xc0, 0xc4, 0x5e, 0xd4, 0xde, + 0x26, 0x72, 0x23, 0xb3, 0xe0, 0x11, 0x39, 0x17, 0xd7, 0x3d, 0x81, 0xe8, 0x86, 0x71, 0xc7, 0xf1, + 0xba, 0xce, 0x1e, 0xf6, 0xd8, 0x7c, 0x4f, 0x27, 0x86, 0x4d, 0xda, 0x74, 0xf8, 0xdf, 0xeb, 0x04, + 0x9b, 0xfb, 0x31, 0x11, 0xe1, 0x93, 0x33, 0x87, 0xff, 0x4d, 0x8e, 0xd2, 0x3d, 0xfc, 0x02, 0x80, + 0x25, 0x11, 0xba, 0xd5, 0x1d, 0x99, 0xd7, 0x92, 0x85, 0x4d, 0xce, 0xd9, 0xea, 0x99, 0xc9, 0x2f, + 0xb5, 0x41, 0x61, 0x67, 0x64, 0x42, 0x8a, 0x9d, 0x8d, 0xed, 0xed, 0x20, 0x0e, 0xfc, 0xd4, 0xb9, + 0x3c, 0x93, 0x7f, 0x36, 0xd6, 0x32, 0xf0, 0xbb, 0xcf, 0xc6, 0x2c, 0x2c, 0x9c, 0xd9, 0x16, 0x6a, + 0xc2, 0x64, 0x3b, 0x08, 0xe3, 0xfb, 0x41, 0x28, 0xd7, 0x17, 0xea, 0x21, 0xee, 0x1b, 0x98, 0xa2, + 0x45, 0x16, 0xce, 0xdb, 0x84, 0xe0, 0x14, 0x4d, 0xf4, 0x79, 0x18, 0x89, 0x1a, 0x8e, 0x47, 0x56, + 0xef, 0xcc, 0x9e, 0xc9, 0xbf, 0x74, 0xea, 0x1c, 0x25, 0x67, 0x75, 0xb1, 0xc9, 0x11, 0x28, 0x58, + 0x92, 0x43, 0x2b, 0x30, 0xc4, 0x62, 0xf2, 0xb3, 0xc8, 0xcf, 0x39, 0x51, 0x89, 0xba, 0x8c, 0x3a, + 0xf9, 0xd9, 0xc4, 0x8a, 0x31, 0xaf, 0x4e, 0xf7, 0x80, 0xe0, 0x7a, 0x83, 0x68, 0xf6, 0x5c, 0xfe, + 0x1e, 0x10, 0xcc, 0xf2, 0x9d, 0x7a, 0xaf, 0x3d, 0xa0, 0x90, 0x70, 0x42, 0x94, 0x9e, 0xcc, 0xf4, + 0x34, 0x3d, 0xdf, 0xc3, 0xce, 0x24, 0xf7, 0x2c, 0x65, 0x27, 0x33, 0x3d, 0x49, 0x29, 0x09, 0xfb, + 0xf7, 0x46, 0xba, 0x39, 0x15, 0x26, 0x27, 0xfd, 0x65, 0xab, 0xeb, 0x09, 0xed, 0xd3, 0x83, 0xaa, + 0x6d, 0x4e, 0x90, 0x47, 0xfd, 0x8a, 0x05, 0xe7, 0xdb, 0x99, 0x1f, 0x22, 0xae, 0xfd, 0xc1, 0xb4, + 0x3f, 0xfc, 0xd3, 0x55, 0x74, 0xf6, 0x6c, 0x38, 0xce, 0x69, 0x29, 0x2d, 0x07, 0x14, 0x3f, 0xb0, + 0x1c, 0xb0, 0x06, 0xa3, 0x8c, 0xb5, 0xec, 0x93, 0xa1, 0x2c, 0xed, 0x85, 0xc6, 0x18, 0x88, 0x25, + 0x51, 0x11, 0x2b, 0x12, 0xe8, 0x87, 0x2d, 0xb8, 0x98, 0xee, 0x3a, 0x26, 0x0c, 0x2c, 0x62, 0x99, + 0x73, 0x11, 0x6d, 0x45, 0x7c, 0xff, 0xc5, 0x5a, 0x2f, 0xe4, 0xa3, 0x7e, 0x08, 0xb8, 0x77, 0x63, + 0xa8, 0x9a, 0x21, 0x23, 0x0e, 0x9b, 0x7a, 0xf1, 0x01, 0xe4, 0xc4, 0x97, 0x60, 0x7c, 0x37, 0xe8, + 0xf8, 0xb1, 0x30, 0x4b, 0x11, 0x4e, 0x82, 0xec, 0x1d, 0x78, 0x4d, 0x2b, 0xc7, 0x06, 0x56, 0x4a, + 0xba, 0x1c, 0x7d, 0x58, 0xe9, 0x12, 0xbd, 0x93, 0xca, 0x43, 0x5d, 0xce, 0x8f, 0x99, 0x27, 0x04, + 0xf1, 0x63, 0x64, 0xa3, 0x3e, 0x5d, 0x89, 0xe8, 0xe7, 0xac, 0x0c, 0x56, 0x9e, 0xcb, 0xc8, 0x9f, + 0x35, 0x65, 0xe4, 0x2b, 0x69, 0x19, 0xb9, 0x4b, 0x27, 0x6a, 0x88, 0xc7, 0x83, 0x07, 0x5e, 0x1e, + 0x34, 0x92, 0x99, 0xed, 0xc1, 0xe5, 0x7e, 0xd7, 0x12, 0xb3, 0x4f, 0x6a, 0xaa, 0x17, 0xb0, 0xc4, + 0x3e, 0xa9, 0xb9, 0x5a, 0xc5, 0x0c, 0x32, 0x68, 0xa8, 0x0b, 0xfb, 0xbf, 0x59, 0x50, 0xac, 0x05, + 0xcd, 0x53, 0xd0, 0xf1, 0x7e, 0xce, 0xd0, 0xf1, 0x3e, 0x9e, 0x93, 0x1f, 0x3c, 0x57, 0xa3, 0xbb, + 0x9c, 0xd2, 0xe8, 0x5e, 0xcc, 0x23, 0xd0, 0x5b, 0x7f, 0xfb, 0xd3, 0x45, 0xd0, 0xb3, 0x99, 0xa3, + 0x7f, 0xf5, 0x30, 0xc6, 0xc1, 0xc5, 0x5e, 0x09, 0xce, 0x05, 0x65, 0x66, 0xd6, 0x24, 0xfd, 0xde, + 0xfe, 0x9c, 0xd9, 0x08, 0xbf, 0x45, 0xdc, 0xd6, 0x76, 0x4c, 0x9a, 0xe9, 0xcf, 0x39, 0x3d, 0x1b, + 0xe1, 0xff, 0x62, 0xc1, 0x54, 0xaa, 0x75, 0xe4, 0xc1, 0x84, 0xa7, 0x2b, 0xe8, 0xc4, 0x3a, 0x7d, + 0x28, 0xdd, 0x9e, 0xb0, 0xb1, 0xd4, 0x8a, 0xb0, 0x49, 0x1c, 0xcd, 0x03, 0xa8, 0x07, 0x34, 0xa9, + 0xf7, 0x62, 0x5c, 0xbf, 0x7a, 0x61, 0x8b, 0xb0, 0x86, 0x81, 0x5e, 0x86, 0xb1, 0x38, 0x68, 0x07, + 0x5e, 0xd0, 0xda, 0xbf, 0x45, 0x64, 0x70, 0x15, 0x65, 0x39, 0xb5, 0x91, 0x80, 0xb0, 0x8e, 0x67, + 0xff, 0x6c, 0x11, 0xd2, 0x19, 0xf0, 0xbf, 0xb5, 0x26, 0x3f, 0x9a, 0x6b, 0xf2, 0x9b, 0x16, 0x4c, + 0xd3, 0xd6, 0x99, 0x15, 0x87, 0xbc, 0x6c, 0x55, 0x02, 0x18, 0xab, 0x47, 0x02, 0x98, 0x2b, 0xf4, + 0xec, 0x6a, 0x06, 0x9d, 0x58, 0xe8, 0xcd, 0xb4, 0xc3, 0x89, 0x96, 0x62, 0x01, 0x15, 0x78, 0x24, + 0x0c, 0x85, 0x6b, 0x92, 0x8e, 0x47, 0xc2, 0x10, 0x0b, 0xa8, 0xcc, 0x0f, 0x53, 0xca, 0xc9, 0x0f, + 0xc3, 0x42, 0xc5, 0x89, 0xf7, 0x7e, 0xc1, 0xf6, 0x68, 0xa1, 0xe2, 0xa4, 0x21, 0x40, 0x82, 0x63, + 0xff, 0x62, 0x11, 0xc6, 0x6b, 0x41, 0x33, 0x79, 0xc2, 0x7a, 0xc9, 0x78, 0xc2, 0xba, 0x9c, 0x7a, + 0xc2, 0x9a, 0xd6, 0x71, 0xbf, 0xf5, 0x60, 0xf5, 0x61, 0x3d, 0x58, 0xfd, 0x73, 0x8b, 0xcd, 0x5a, + 0x75, 0xbd, 0x2e, 0xf2, 0xd3, 0xbe, 0x00, 0x63, 0xec, 0x40, 0x62, 0xbe, 0x70, 0xf2, 0x5d, 0x87, + 0x85, 0x7e, 0x5f, 0x4f, 0x8a, 0xb1, 0x8e, 0x83, 0xae, 0xc2, 0x68, 0x44, 0x9c, 0xb0, 0xb1, 0xad, + 0xce, 0x38, 0xf1, 0xea, 0xc1, 0xcb, 0xb0, 0x82, 0xa2, 0x37, 0x93, 0x28, 0x65, 0xc5, 0xfc, 0x4c, + 0xab, 0x7a, 0x7f, 0xf8, 0x16, 0xc9, 0x0f, 0x4d, 0x66, 0xbf, 0x05, 0xa8, 0x1b, 0x7f, 0x80, 0x78, + 0x44, 0x15, 0x33, 0x1e, 0x51, 0xb9, 0x2b, 0x16, 0xd1, 0x9f, 0x5a, 0x30, 0x59, 0x0b, 0x9a, 0x74, + 0xeb, 0xfe, 0x45, 0xda, 0xa7, 0x7a, 0x88, 0xc6, 0xe1, 0x1e, 0x21, 0x1a, 0xff, 0x9e, 0x05, 0x23, + 0xb5, 0xa0, 0x79, 0x0a, 0xda, 0xf6, 0xcf, 0x9a, 0xda, 0xf6, 0xc7, 0x72, 0x96, 0x44, 0x8e, 0x82, + 0xfd, 0x97, 0x8b, 0x30, 0x41, 0xfb, 0x19, 0xb4, 0xe4, 0x2c, 0x19, 0x23, 0x62, 0x0d, 0x30, 0x22, + 0x94, 0xcd, 0x0d, 0x3c, 0x2f, 0xb8, 0x9f, 0x9e, 0xb1, 0x15, 0x56, 0x8a, 0x05, 0x14, 0x3d, 0x07, + 0xa3, 0xed, 0x90, 0xec, 0xb9, 0x81, 0xe0, 0x1f, 0xb5, 0xb7, 0x8b, 0x9a, 0x28, 0xc7, 0x0a, 0x83, + 0xca, 0x5d, 0x91, 0xeb, 0x37, 0x88, 0x4c, 0xf3, 0x5c, 0x62, 0x99, 0xa0, 0x78, 0xec, 0x65, 0xad, + 0x1c, 0x1b, 0x58, 0xe8, 0x2d, 0x28, 0xb3, 0xff, 0xec, 0x44, 0x39, 0x7e, 0xe6, 0x1a, 0x91, 0xf0, + 0x40, 0x10, 0xc0, 0x09, 0x2d, 0x74, 0x1d, 0x20, 0x96, 0xf1, 0x79, 0x23, 0x11, 0x56, 0x46, 0xf1, + 0xda, 0x2a, 0x72, 0x6f, 0x84, 0x35, 0x2c, 0xf4, 0x2c, 0x94, 0x63, 0xc7, 0xf5, 0x6e, 0xbb, 0x3e, + 0x89, 0x98, 0xca, 0xb9, 0x28, 0xf3, 0x19, 0x88, 0x42, 0x9c, 0xc0, 0x29, 0xaf, 0xc3, 0x7c, 0xae, + 0x79, 0xde, 0xab, 0x51, 0x86, 0xcd, 0x78, 0x9d, 0xdb, 0xaa, 0x14, 0x6b, 0x18, 0xf6, 0xab, 0x70, + 0xae, 0x16, 0x34, 0x6b, 0x41, 0x18, 0xaf, 0x04, 0xe1, 0x7d, 0x27, 0x6c, 0xca, 0xf9, 0xab, 0xc8, + 0xd0, 0xfa, 0xf4, 0xec, 0x19, 0xe2, 0x3b, 0xd3, 0x08, 0x9a, 0xff, 0x22, 0xe3, 0x76, 0x8e, 0xe9, + 0x6b, 0xd1, 0x60, 0xf7, 0xae, 0x4a, 0x71, 0x77, 0xc3, 0x89, 0x09, 0xba, 0xc3, 0xd2, 0x62, 0x25, + 0x57, 0x90, 0xa8, 0xfe, 0x8c, 0x96, 0x16, 0x2b, 0x01, 0x66, 0xde, 0x59, 0x66, 0x7d, 0xfb, 0xd7, + 0x8b, 0xec, 0x34, 0x4a, 0x65, 0x7c, 0x43, 0x5f, 0x82, 0xc9, 0x88, 0xdc, 0x76, 0xfd, 0xce, 0x03, + 0x29, 0x84, 0xf7, 0xf0, 0x96, 0xa9, 0x2f, 0xeb, 0x98, 0x5c, 0x95, 0x67, 0x96, 0xe1, 0x14, 0x35, + 0x3a, 0x4f, 0x61, 0xc7, 0x5f, 0x88, 0xee, 0x46, 0x24, 0x14, 0x19, 0xc7, 0xd8, 0x3c, 0x61, 0x59, + 0x88, 0x13, 0x38, 0x5d, 0x97, 0xec, 0xcf, 0x7a, 0xe0, 0xe3, 0x20, 0x88, 0xe5, 0x4a, 0x66, 0x39, + 0x6b, 0xb4, 0x72, 0x6c, 0x60, 0xa1, 0x15, 0x40, 0x51, 0xa7, 0xdd, 0xf6, 0xd8, 0x7b, 0xbb, 0xe3, + 0xdd, 0x08, 0x83, 0x4e, 0x9b, 0xbf, 0x75, 0x16, 0x17, 0xcf, 0xd3, 0x2b, 0xac, 0xde, 0x05, 0xc5, + 0x19, 0x35, 0xe8, 0xe9, 0xb3, 0x15, 0xb1, 0xdf, 0x6c, 0x75, 0x17, 0x85, 0x7a, 0xbd, 0xce, 0x8a, + 0xb0, 0x84, 0xd1, 0xc5, 0xc4, 0x9a, 0xe7, 0x98, 0xc3, 0xc9, 0x62, 0xc2, 0xaa, 0x14, 0x6b, 0x18, + 0x68, 0x19, 0x46, 0xa2, 0xfd, 0xa8, 0x11, 0x8b, 0x20, 0x48, 0x39, 0xb9, 0x23, 0xeb, 0x0c, 0x45, + 0xcb, 0x67, 0xc0, 0xab, 0x60, 0x59, 0xd7, 0xfe, 0x1e, 0x76, 0x19, 0xb2, 0xfc, 0x54, 0x71, 0x27, + 0x24, 0x68, 0x17, 0x26, 0xda, 0x6c, 0xca, 0x45, 0xf4, 0x64, 0x31, 0x6f, 0x2f, 0x0d, 0x28, 0xd5, + 0xde, 0xa7, 0x07, 0x8d, 0xd2, 0x3a, 0x31, 0x71, 0xa1, 0xa6, 0x93, 0xc3, 0x26, 0x75, 0xfb, 0x07, + 0x67, 0xd8, 0x99, 0x5b, 0xe7, 0xa2, 0xea, 0x88, 0xb0, 0xf8, 0x15, 0x7c, 0xf9, 0x5c, 0xbe, 0xce, + 0x24, 0xf9, 0x22, 0x61, 0x35, 0x8c, 0x65, 0x5d, 0xf4, 0x26, 0x7b, 0x9b, 0xe6, 0x07, 0x5d, 0xbf, + 0x34, 0xc1, 0x1c, 0xcb, 0x78, 0x86, 0x16, 0x15, 0xb1, 0x46, 0x04, 0xdd, 0x86, 0x09, 0x91, 0xce, + 0x48, 0x28, 0xc5, 0x8a, 0x86, 0xd2, 0x63, 0x02, 0xeb, 0xc0, 0xa3, 0x74, 0x01, 0x36, 0x2b, 0xa3, + 0x16, 0x5c, 0xd4, 0x72, 0xfb, 0xdd, 0x08, 0x1d, 0xf6, 0x5e, 0xe9, 0xb2, 0x4d, 0xa4, 0x9d, 0x9b, + 0x4f, 0x1e, 0x1e, 0x54, 0x2e, 0x6e, 0xf4, 0x42, 0xc4, 0xbd, 0xe9, 0xa0, 0x3b, 0x70, 0x8e, 0x3b, + 0xd6, 0x55, 0x89, 0xd3, 0xf4, 0x5c, 0x5f, 0x1d, 0xcc, 0x7c, 0x1d, 0x5e, 0x38, 0x3c, 0xa8, 0x9c, + 0x5b, 0xc8, 0x42, 0xc0, 0xd9, 0xf5, 0xd0, 0x67, 0xa1, 0xdc, 0xf4, 0x23, 0x31, 0x06, 0xc3, 0x46, + 0xda, 0xca, 0x72, 0x75, 0xbd, 0xae, 0xbe, 0x3f, 0xf9, 0x83, 0x93, 0x0a, 0xa8, 0xc5, 0x15, 0x63, + 0x4a, 0x0e, 0x1d, 0xc9, 0x4f, 0x51, 0x2e, 0x96, 0x84, 0xe1, 0x5a, 0xc3, 0x35, 0xc2, 0xca, 0x34, + 0xd5, 0xf0, 0xba, 0x31, 0x08, 0xa3, 0x37, 0x00, 0x51, 0x46, 0xcd, 0x6d, 0x90, 0x85, 0x06, 0x0b, + 0x62, 0xcd, 0xf4, 0x88, 0xa3, 0x86, 0x2b, 0x03, 0xaa, 0x77, 0x61, 0xe0, 0x8c, 0x5a, 0xe8, 0x26, + 0x3d, 0xc8, 0xf4, 0x52, 0x61, 0x62, 0x2b, 0x99, 0xfb, 0xd9, 0x2a, 0x69, 0x87, 0xa4, 0xe1, 0xc4, + 0xa4, 0x69, 0x52, 0xc4, 0xa9, 0x7a, 0xf4, 0x2e, 0x55, 0xf9, 0x6c, 0xc0, 0x8c, 0x54, 0xd1, 0x9d, + 0xd3, 0x86, 0xca, 0xc5, 0xdb, 0x41, 0x14, 0xaf, 0x93, 0xf8, 0x7e, 0x10, 0xee, 0x88, 0xc0, 0x60, + 0x49, 0x8c, 0xca, 0x04, 0x84, 0x75, 0x3c, 0xca, 0x07, 0xb3, 0xc7, 0xe1, 0xd5, 0x2a, 0x7b, 0xa1, + 0x1b, 0x4d, 0xf6, 0xc9, 0x4d, 0x5e, 0x8c, 0x25, 0x5c, 0xa2, 0xae, 0xd6, 0x96, 0xd8, 0x6b, 0x5b, + 0x0a, 0x75, 0xb5, 0xb6, 0x84, 0x25, 0x1c, 0x91, 0xee, 0x94, 0xa0, 0x93, 0xf9, 0x5a, 0xcd, 0xee, + 0xeb, 0x60, 0xc0, 0xac, 0xa0, 0x3e, 0x4c, 0xab, 0x64, 0xa4, 0x3c, 0x62, 0x5a, 0x34, 0x3b, 0xc5, + 0x16, 0xc9, 0xe0, 0xe1, 0xd6, 0x94, 0x9e, 0x78, 0x35, 0x45, 0x09, 0x77, 0xd1, 0x36, 0x62, 0x87, + 0x4c, 0xf7, 0xcd, 0x47, 0x74, 0x0d, 0xca, 0x51, 0x67, 0xb3, 0x19, 0xec, 0x3a, 0xae, 0xcf, 0x1e, + 0xc7, 0x34, 0x26, 0xab, 0x2e, 0x01, 0x38, 0xc1, 0x41, 0x2b, 0x30, 0xea, 0x48, 0x25, 0x30, 0xca, + 0x0f, 0x26, 0xa0, 0x54, 0xbf, 0xdc, 0xbf, 0x56, 0xaa, 0x7d, 0x55, 0x5d, 0xf4, 0x1a, 0x4c, 0x08, + 0x77, 0x2a, 0x1e, 0x62, 0x81, 0x3d, 0x5e, 0x69, 0xf6, 0xf2, 0x75, 0x1d, 0x88, 0x4d, 0x5c, 0xf4, + 0x45, 0x98, 0xa4, 0x54, 0x92, 0x83, 0x6d, 0xf6, 0xec, 0x20, 0x27, 0xa2, 0x96, 0x67, 0x42, 0xaf, + 0x8c, 0x53, 0xc4, 0x50, 0x13, 0x9e, 0x70, 0x3a, 0x71, 0xc0, 0x14, 0xe9, 0xe6, 0xfa, 0xdf, 0x08, + 0x76, 0x88, 0xcf, 0xde, 0xb0, 0x46, 0x17, 0x2f, 0x1f, 0x1e, 0x54, 0x9e, 0x58, 0xe8, 0x81, 0x87, + 0x7b, 0x52, 0x41, 0x77, 0x61, 0x2c, 0x0e, 0x3c, 0x66, 0xb9, 0x4e, 0x59, 0x89, 0xf3, 0xf9, 0xb1, + 0x77, 0x36, 0x14, 0x9a, 0xae, 0x44, 0x52, 0x55, 0xb1, 0x4e, 0x07, 0x6d, 0xf0, 0x3d, 0xc6, 0xa2, + 0x92, 0x92, 0x68, 0xf6, 0xb1, 0xfc, 0x81, 0x51, 0xc1, 0x4b, 0xcd, 0x2d, 0x28, 0x6a, 0x62, 0x9d, + 0x0c, 0xba, 0x01, 0x33, 0xed, 0xd0, 0x0d, 0xd8, 0xc2, 0x56, 0x8f, 0x18, 0xb3, 0x66, 0x6a, 0x81, + 0x5a, 0x1a, 0x01, 0x77, 0xd7, 0xa1, 0x42, 0xa6, 0x2c, 0x9c, 0xbd, 0xc0, 0xf3, 0x54, 0x71, 0xc6, + 0x9b, 0x97, 0x61, 0x05, 0x45, 0x6b, 0xec, 0x5c, 0xe6, 0xe2, 0xe0, 0xec, 0x5c, 0x7e, 0x10, 0x06, + 0x5d, 0x6c, 0xe4, 0xfc, 0x92, 0xfa, 0x8b, 0x13, 0x0a, 0xf4, 0xde, 0x88, 0xb6, 0x9d, 0x90, 0xd4, + 0xc2, 0xa0, 0x41, 0x78, 0x67, 0xb8, 0xd1, 0xfc, 0xe3, 0x3c, 0x78, 0x22, 0xbd, 0x37, 0xea, 0x59, + 0x08, 0x38, 0xbb, 0x1e, 0x6a, 0x6a, 0xe9, 0x99, 0x29, 0x1b, 0x1a, 0xcd, 0x3e, 0xd1, 0xc3, 0xcc, + 0x28, 0xc5, 0xb3, 0x26, 0x6b, 0xd1, 0x28, 0x8e, 0x70, 0x8a, 0xe6, 0xdc, 0xb7, 0xc3, 0x4c, 0xd7, + 0x7d, 0x71, 0xac, 0xb8, 0xdd, 0x7f, 0x32, 0x04, 0x65, 0xa5, 0x0a, 0x47, 0xd7, 0xcc, 0x17, 0x8e, + 0x0b, 0xe9, 0x17, 0x8e, 0x51, 0xca, 0x91, 0xeb, 0x8f, 0x1a, 0x1b, 0x86, 0x51, 0x5c, 0x21, 0x3f, + 0x4b, 0x96, 0xce, 0x53, 0xf7, 0xf5, 0x80, 0xd3, 0x34, 0x1b, 0xc5, 0x81, 0x9f, 0x4a, 0x4a, 0x3d, + 0x95, 0x25, 0x03, 0x26, 0xa9, 0xa5, 0xc2, 0x7f, 0x3b, 0x68, 0xae, 0xd6, 0xd2, 0x59, 0x1b, 0x6b, + 0xb4, 0x10, 0x73, 0x18, 0x13, 0xdf, 0x28, 0x73, 0xc3, 0xc4, 0xb7, 0x91, 0x87, 0x14, 0xdf, 0x24, + 0x01, 0x9c, 0xd0, 0x42, 0x1e, 0xcc, 0x34, 0xcc, 0x84, 0x9b, 0xca, 0xeb, 0xed, 0xa9, 0xbe, 0xa9, + 0x2f, 0x3b, 0x5a, 0x76, 0xb3, 0xa5, 0x34, 0x15, 0xdc, 0x4d, 0x18, 0xbd, 0x06, 0xa3, 0xef, 0x05, + 0x11, 0xdb, 0x7c, 0xe2, 0x86, 0x97, 0xde, 0x41, 0xa3, 0x6f, 0xde, 0xa9, 0xb3, 0xf2, 0xa3, 0x83, + 0xca, 0x58, 0x2d, 0x68, 0xca, 0xbf, 0x58, 0x55, 0x40, 0x0f, 0xe0, 0x9c, 0x71, 0x2e, 0xaa, 0xee, + 0xc2, 0xe0, 0xdd, 0xbd, 0x28, 0x9a, 0x3b, 0xb7, 0x9a, 0x45, 0x09, 0x67, 0x37, 0x40, 0x0f, 0x1b, + 0x3f, 0x10, 0xc9, 0x6a, 0x25, 0x17, 0xc1, 0x98, 0x85, 0xb2, 0xee, 0x1b, 0x9e, 0x42, 0xc0, 0xdd, + 0x75, 0xec, 0xaf, 0xf1, 0x97, 0x03, 0xa1, 0x5f, 0x24, 0x51, 0xc7, 0x3b, 0x8d, 0x5c, 0x48, 0xcb, + 0x86, 0xea, 0xf3, 0xa1, 0x5f, 0xa7, 0x7e, 0xd3, 0x62, 0xaf, 0x53, 0x1b, 0x64, 0xb7, 0xed, 0x51, + 0x29, 0xf7, 0xd1, 0x77, 0xfc, 0x4d, 0x18, 0x8d, 0x45, 0x6b, 0xbd, 0xd2, 0x37, 0x69, 0x9d, 0x62, + 0x2f, 0x74, 0x8a, 0xbf, 0x90, 0xa5, 0x58, 0x91, 0xb1, 0xff, 0x29, 0x9f, 0x01, 0x09, 0x39, 0x05, + 0x35, 0x54, 0xd5, 0x54, 0x43, 0x55, 0xfa, 0x7c, 0x41, 0x8e, 0x3a, 0xea, 0x9f, 0x98, 0xfd, 0x66, + 0xa2, 0xdc, 0x47, 0xfd, 0x59, 0xd4, 0xfe, 0x31, 0x0b, 0xce, 0x66, 0xd9, 0x11, 0x51, 0x9e, 0x90, + 0x0b, 0x92, 0xea, 0x99, 0x58, 0x8d, 0xe0, 0x3d, 0x51, 0x8e, 0x15, 0xc6, 0xc0, 0x99, 0x11, 0x8e, + 0x17, 0x3e, 0xed, 0x0e, 0x4c, 0xd4, 0x42, 0xa2, 0xdd, 0x01, 0xaf, 0x73, 0x37, 0x33, 0xde, 0x9f, + 0xe7, 0x8e, 0xed, 0x62, 0x66, 0xff, 0x7c, 0x01, 0xce, 0xf2, 0x77, 0x9e, 0x85, 0xbd, 0xc0, 0x6d, + 0xd6, 0x82, 0xa6, 0xc8, 0x6a, 0xf1, 0x36, 0x8c, 0xb7, 0x35, 0xe9, 0xbf, 0x57, 0x00, 0x27, 0x5d, + 0x4b, 0x90, 0x48, 0x61, 0x7a, 0x29, 0x36, 0x68, 0xa1, 0x26, 0x8c, 0x93, 0x3d, 0xb7, 0xa1, 0x1e, + 0x0b, 0x0a, 0xc7, 0xbe, 0x1b, 0x54, 0x2b, 0xcb, 0x1a, 0x1d, 0x6c, 0x50, 0x7d, 0x04, 0x89, 0xce, + 0xec, 0x1f, 0xb7, 0xe0, 0xb1, 0x9c, 0x70, 0x4f, 0xb4, 0xb9, 0xfb, 0xec, 0x45, 0x4d, 0xe4, 0x4c, + 0x52, 0xcd, 0xf1, 0x77, 0x36, 0x2c, 0xa0, 0xe8, 0xf3, 0x00, 0xfc, 0x9d, 0x8c, 0x0a, 0x25, 0xfd, + 0xe2, 0xe2, 0x18, 0x21, 0x3d, 0xb4, 0x50, 0x0c, 0xb2, 0x3e, 0xd6, 0x68, 0xd9, 0x3f, 0x53, 0x84, + 0x21, 0xf6, 0x2e, 0x83, 0x56, 0x60, 0x64, 0x9b, 0x07, 0x37, 0x1e, 0x24, 0x8e, 0x72, 0x22, 0xdd, + 0xf1, 0x02, 0x2c, 0x2b, 0xa3, 0x35, 0x38, 0xc3, 0x83, 0x43, 0x7b, 0x55, 0xe2, 0x39, 0xfb, 0x52, + 0x49, 0xc0, 0xf3, 0x0c, 0xa9, 0xb0, 0x12, 0xab, 0xdd, 0x28, 0x38, 0xab, 0x1e, 0x7a, 0x1d, 0x26, + 0x63, 0x77, 0x97, 0x04, 0x9d, 0x58, 0x52, 0xe2, 0x61, 0xa1, 0x15, 0x1b, 0xb7, 0x61, 0x40, 0x71, + 0x0a, 0x9b, 0x8a, 0x3b, 0xed, 0x2e, 0x75, 0x88, 0x96, 0xb9, 0xdf, 0x54, 0x81, 0x98, 0xb8, 0xcc, + 0x80, 0xa8, 0xc3, 0xcc, 0xa5, 0x36, 0xb6, 0x43, 0x12, 0x6d, 0x07, 0x5e, 0x53, 0xa4, 0xa9, 0x4e, + 0x0c, 0x88, 0x52, 0x70, 0xdc, 0x55, 0x83, 0x52, 0xd9, 0x72, 0x5c, 0xaf, 0x13, 0x92, 0x84, 0xca, + 0xb0, 0x49, 0x65, 0x25, 0x05, 0xc7, 0x5d, 0x35, 0xe8, 0x3a, 0x3a, 0x27, 0xf2, 0x46, 0x4b, 0x67, + 0x77, 0x65, 0x15, 0x36, 0x22, 0xdd, 0x7e, 0x7a, 0x44, 0x7b, 0x11, 0x76, 0x33, 0x2a, 0xf3, 0xb4, + 0xa6, 0xc5, 0x13, 0x0e, 0x3f, 0x92, 0xca, 0xc3, 0x64, 0x2f, 0xfe, 0x3d, 0x0b, 0xce, 0x64, 0x58, + 0x9f, 0xf2, 0xa3, 0xaa, 0xe5, 0x46, 0xb1, 0xca, 0xa5, 0xa2, 0x1d, 0x55, 0xbc, 0x1c, 0x2b, 0x0c, + 0xba, 0x1f, 0xf8, 0x61, 0x98, 0x3e, 0x00, 0x85, 0x75, 0x97, 0x80, 0x1e, 0xef, 0x00, 0x44, 0x97, + 0xa1, 0xd4, 0x89, 0x88, 0x8c, 0xd3, 0xa4, 0xce, 0x6f, 0xa6, 0xd7, 0x65, 0x10, 0xca, 0x9a, 0xb6, + 0x94, 0x4a, 0x55, 0x63, 0x4d, 0xb9, 0x9e, 0x94, 0xc3, 0xec, 0xaf, 0x16, 0xe1, 0x42, 0xae, 0x9d, + 0x39, 0xed, 0xd2, 0x6e, 0xe0, 0xbb, 0x71, 0xa0, 0xde, 0xfc, 0x78, 0xa4, 0x10, 0xd2, 0xde, 0x5e, + 0x13, 0xe5, 0x58, 0x61, 0xa0, 0x2b, 0x32, 0x83, 0x79, 0x3a, 0x5b, 0xcc, 0x62, 0xd5, 0x48, 0x62, + 0x3e, 0x68, 0x26, 0xae, 0xa7, 0xa0, 0xd4, 0x0e, 0x02, 0x2f, 0x7d, 0x18, 0xd1, 0xee, 0x06, 0x81, + 0x87, 0x19, 0x10, 0x7d, 0x42, 0x8c, 0x43, 0xea, 0x91, 0x0b, 0x3b, 0xcd, 0x20, 0xd2, 0x06, 0xe3, + 0x19, 0x18, 0xd9, 0x21, 0xfb, 0xa1, 0xeb, 0xb7, 0xd2, 0x8f, 0x9f, 0xb7, 0x78, 0x31, 0x96, 0x70, + 0x33, 0x59, 0xc2, 0xc8, 0x49, 0xa7, 0xd0, 0x1a, 0xed, 0x7b, 0xb5, 0xfd, 0x50, 0x11, 0xa6, 0xf0, + 0x62, 0xf5, 0x5b, 0x13, 0x71, 0xb7, 0x7b, 0x22, 0x4e, 0x3a, 0x85, 0x56, 0xff, 0xd9, 0xf8, 0x65, + 0x0b, 0xa6, 0x58, 0x40, 0x61, 0x11, 0x9f, 0xc2, 0x0d, 0xfc, 0x53, 0x60, 0xdd, 0x9e, 0x82, 0xa1, + 0x90, 0x36, 0x9a, 0xce, 0x8b, 0xc3, 0x7a, 0x82, 0x39, 0x0c, 0x3d, 0x01, 0x25, 0xd6, 0x05, 0x3a, + 0x79, 0xe3, 0x3c, 0xa5, 0x40, 0xd5, 0x89, 0x1d, 0xcc, 0x4a, 0x99, 0xd3, 0x35, 0x26, 0x6d, 0xcf, + 0xe5, 0x9d, 0x4e, 0x1e, 0x14, 0x3e, 0x1a, 0x4e, 0xd7, 0x99, 0x5d, 0xfb, 0x60, 0x4e, 0xd7, 0xd9, + 0x24, 0x7b, 0x8b, 0x45, 0xff, 0xbd, 0x00, 0x97, 0x32, 0xeb, 0x0d, 0xec, 0x74, 0xdd, 0xbb, 0xf6, + 0xc9, 0xd8, 0xb0, 0x64, 0x9b, 0x96, 0x14, 0x4f, 0xd1, 0xb4, 0xa4, 0x34, 0x28, 0xe7, 0x38, 0x34, + 0x80, 0x2f, 0x74, 0xe6, 0x90, 0x7d, 0x44, 0x7c, 0xa1, 0x33, 0xfb, 0x96, 0x23, 0xd6, 0xfd, 0x59, + 0x21, 0xe7, 0x5b, 0x98, 0x80, 0x77, 0x95, 0x9e, 0x33, 0x0c, 0x18, 0x09, 0x4e, 0x78, 0x9c, 0x9f, + 0x31, 0xbc, 0x0c, 0x2b, 0x28, 0x72, 0x35, 0xaf, 0xe2, 0x42, 0x7e, 0xd6, 0xc4, 0xdc, 0xa6, 0xe6, + 0xcd, 0xf7, 0x1f, 0x35, 0x04, 0x19, 0x1e, 0xc6, 0x6b, 0x9a, 0x50, 0x5e, 0x1c, 0x5c, 0x28, 0x1f, + 0xcf, 0x16, 0xc8, 0xd1, 0x02, 0x4c, 0xed, 0xba, 0x3e, 0xcb, 0x82, 0x6f, 0xb2, 0xa2, 0x2a, 0xc8, + 0xc6, 0x9a, 0x09, 0xc6, 0x69, 0xfc, 0xb9, 0xd7, 0x60, 0xe2, 0xe1, 0xd5, 0x91, 0xdf, 0x2c, 0xc2, + 0xe3, 0x3d, 0xb6, 0x3d, 0x3f, 0xeb, 0x8d, 0x39, 0xd0, 0xce, 0xfa, 0xae, 0x79, 0xa8, 0xc1, 0xd9, + 0xad, 0x8e, 0xe7, 0xed, 0x33, 0xeb, 0x4d, 0xd2, 0x94, 0x18, 0x82, 0x57, 0x7c, 0x42, 0x26, 0x71, + 0x58, 0xc9, 0xc0, 0xc1, 0x99, 0x35, 0xd1, 0x1b, 0x80, 0x02, 0x91, 0xb2, 0xf5, 0x06, 0xf1, 0x85, + 0x56, 0x9d, 0x0d, 0x7c, 0x31, 0xd9, 0x8c, 0x77, 0xba, 0x30, 0x70, 0x46, 0x2d, 0xca, 0xf4, 0xd3, + 0x5b, 0x69, 0x5f, 0x75, 0x2b, 0xc5, 0xf4, 0x63, 0x1d, 0x88, 0x4d, 0x5c, 0x74, 0x03, 0x66, 0x9c, + 0x3d, 0xc7, 0xe5, 0xc1, 0xe7, 0x24, 0x01, 0xce, 0xf5, 0x2b, 0x25, 0xd8, 0x42, 0x1a, 0x01, 0x77, + 0xd7, 0x49, 0xb9, 0x35, 0x0f, 0xe7, 0xbb, 0x35, 0xf7, 0x3e, 0x17, 0xfb, 0xe9, 0x74, 0xed, 0xff, + 0x68, 0xd1, 0xeb, 0x2b, 0x23, 0xed, 0x3a, 0x1d, 0x07, 0xa5, 0x9b, 0xd4, 0x3c, 0x8c, 0xcf, 0x69, + 0xf6, 0x19, 0x09, 0x10, 0x9b, 0xb8, 0x7c, 0x41, 0x44, 0x89, 0x8b, 0x8b, 0xc1, 0xba, 0x8b, 0x10, + 0x02, 0x0a, 0x03, 0x7d, 0x01, 0x46, 0x9a, 0xee, 0x9e, 0x1b, 0x05, 0xa1, 0xd8, 0x2c, 0xc7, 0x74, + 0x14, 0x48, 0xce, 0xc1, 0x2a, 0x27, 0x83, 0x25, 0x3d, 0xfb, 0x87, 0x0a, 0x30, 0x21, 0x5b, 0x7c, + 0xb3, 0x13, 0xc4, 0xce, 0x29, 0x5c, 0xcb, 0x37, 0x8c, 0x6b, 0xf9, 0x13, 0xbd, 0xe2, 0x28, 0xb0, + 0x2e, 0xe5, 0x5e, 0xc7, 0x77, 0x52, 0xd7, 0xf1, 0xd3, 0xfd, 0x49, 0xf5, 0xbe, 0x86, 0xff, 0x99, + 0x05, 0x33, 0x06, 0xfe, 0x29, 0xdc, 0x06, 0x2b, 0xe6, 0x6d, 0xf0, 0x64, 0xdf, 0x6f, 0xc8, 0xb9, + 0x05, 0xbe, 0xaf, 0x98, 0xea, 0x3b, 0x3b, 0xfd, 0xdf, 0x83, 0xd2, 0xb6, 0x13, 0x36, 0x7b, 0xc5, + 0x6b, 0xed, 0xaa, 0x34, 0x7f, 0xd3, 0x09, 0x9b, 0xfc, 0x0c, 0x7f, 0x4e, 0x25, 0x7a, 0x74, 0xc2, + 0x66, 0x5f, 0x8f, 0x2e, 0xd6, 0x14, 0x7a, 0x15, 0x86, 0xa3, 0x46, 0xd0, 0x56, 0xf6, 0x96, 0x97, + 0x79, 0x12, 0x48, 0x5a, 0x72, 0x74, 0x50, 0x41, 0x66, 0x73, 0xb4, 0x18, 0x0b, 0x7c, 0xf4, 0x36, + 0x4c, 0xb0, 0x5f, 0xca, 0xee, 0xa0, 0x98, 0x9f, 0x25, 0xa0, 0xae, 0x23, 0x72, 0xf3, 0x15, 0xa3, + 0x08, 0x9b, 0xa4, 0xe6, 0x5a, 0x50, 0x56, 0x9f, 0xf5, 0x48, 0x3d, 0x71, 0xfe, 0x5d, 0x11, 0xce, + 0x64, 0xac, 0x39, 0x14, 0x19, 0x33, 0xf1, 0xc2, 0x80, 0x4b, 0xf5, 0x03, 0xce, 0x45, 0xc4, 0xa4, + 0xa1, 0xa6, 0x58, 0x5b, 0x03, 0x37, 0x7a, 0x37, 0x22, 0xe9, 0x46, 0x69, 0x51, 0xff, 0x46, 0x69, + 0x63, 0xa7, 0x36, 0xd4, 0xb4, 0x21, 0xd5, 0xd3, 0x47, 0x3a, 0xa7, 0x7f, 0x5c, 0x84, 0xb3, 0x59, + 0xa1, 0x5d, 0xd0, 0x77, 0xa7, 0xb2, 0xc1, 0xbc, 0x34, 0x68, 0x50, 0x18, 0x9e, 0x22, 0x46, 0xe4, + 0x36, 0x9e, 0x37, 0xf3, 0xc3, 0xf4, 0x1d, 0x66, 0xd1, 0x26, 0x73, 0xdf, 0x0c, 0x79, 0x16, 0x1f, + 0x79, 0x7c, 0x7c, 0x7a, 0xe0, 0x0e, 0x88, 0xf4, 0x3f, 0x51, 0xca, 0x7d, 0x53, 0x16, 0xf7, 0x77, + 0xdf, 0x94, 0x2d, 0xcf, 0xb9, 0x30, 0xa6, 0x7d, 0xcd, 0x23, 0x9d, 0xf1, 0x1d, 0x7a, 0x5b, 0x69, + 0xfd, 0x7e, 0xa4, 0xb3, 0xfe, 0xe3, 0x16, 0xa4, 0x8c, 0x1b, 0x95, 0xba, 0xcb, 0xca, 0x55, 0x77, + 0x5d, 0x86, 0x52, 0x18, 0x78, 0x24, 0x9d, 0xa0, 0x05, 0x07, 0x1e, 0xc1, 0x0c, 0x42, 0x31, 0xe2, + 0x44, 0xd9, 0x31, 0xae, 0x0b, 0x72, 0x42, 0x44, 0x7b, 0x0a, 0x86, 0x3c, 0xb2, 0x47, 0xbc, 0x74, + 0xf4, 0xf3, 0xdb, 0xb4, 0x10, 0x73, 0x98, 0xfd, 0xcb, 0x25, 0xb8, 0xd8, 0xd3, 0x01, 0x9a, 0x8a, + 0x43, 0x2d, 0x27, 0x26, 0xf7, 0x9d, 0xfd, 0x74, 0x98, 0xe2, 0x1b, 0xbc, 0x18, 0x4b, 0x38, 0xb3, + 0xf7, 0xe6, 0x61, 0x09, 0x53, 0xca, 0x41, 0x11, 0x8d, 0x50, 0x40, 0x1f, 0x41, 0x5e, 0xf7, 0xeb, + 0x00, 0x51, 0xe4, 0x2d, 0xfb, 0x94, 0xbb, 0x6b, 0x0a, 0x43, 0xf2, 0x24, 0x7c, 0x65, 0xfd, 0xb6, + 0x80, 0x60, 0x0d, 0x0b, 0x55, 0x61, 0xba, 0x1d, 0x06, 0x31, 0xd7, 0xb5, 0x56, 0xb9, 0x99, 0xcf, + 0x90, 0xe9, 0x7b, 0x5a, 0x4b, 0xc1, 0x71, 0x57, 0x0d, 0xf4, 0x32, 0x8c, 0x09, 0x7f, 0xd4, 0x5a, + 0x10, 0x78, 0x42, 0x0d, 0xa4, 0x8c, 0x46, 0xea, 0x09, 0x08, 0xeb, 0x78, 0x5a, 0x35, 0xa6, 0xc0, + 0x1d, 0xc9, 0xac, 0xc6, 0x95, 0xb8, 0x1a, 0x5e, 0x2a, 0xcc, 0xd3, 0xe8, 0x40, 0x61, 0x9e, 0x12, + 0xc5, 0x58, 0x79, 0xe0, 0x37, 0x2b, 0xe8, 0xab, 0x4a, 0xfa, 0x85, 0x12, 0x9c, 0x11, 0x0b, 0xe7, + 0x51, 0x2f, 0x97, 0x47, 0x94, 0x7d, 0xfe, 0x5b, 0x6b, 0xe6, 0xb4, 0xd7, 0xcc, 0x0f, 0x5b, 0x60, + 0xb2, 0x57, 0xe8, 0xff, 0xcb, 0x8d, 0xf3, 0xfe, 0x72, 0x2e, 0xbb, 0xd6, 0x94, 0x17, 0xc8, 0x07, + 0x8c, 0xf8, 0x6e, 0xff, 0x07, 0x0b, 0x9e, 0xec, 0x4b, 0x11, 0x2d, 0x43, 0x99, 0xf1, 0x80, 0x9a, + 0x74, 0xf6, 0xb4, 0x32, 0x03, 0x94, 0x80, 0x1c, 0x96, 0x34, 0xa9, 0x89, 0x96, 0xbb, 0x02, 0xea, + 0x3f, 0x93, 0x11, 0x50, 0xff, 0x9c, 0x31, 0x3c, 0x0f, 0x19, 0x51, 0xff, 0x6b, 0x45, 0x18, 0xe6, + 0x2b, 0xfe, 0x14, 0xc4, 0xb0, 0x15, 0xa1, 0xb7, 0xed, 0x11, 0x47, 0x8a, 0xf7, 0x65, 0xbe, 0xea, + 0xc4, 0x0e, 0x67, 0x13, 0xd4, 0x6d, 0x95, 0x68, 0x78, 0xd1, 0xbc, 0x71, 0x9f, 0xcd, 0xa5, 0x14, + 0x93, 0xc0, 0x69, 0x68, 0xb7, 0xdb, 0x97, 0x00, 0x22, 0x96, 0x68, 0x9e, 0xd2, 0x10, 0x11, 0xc9, + 0x3e, 0xd9, 0xa3, 0xf5, 0xba, 0x42, 0xe6, 0x7d, 0x48, 0x76, 0xba, 0x02, 0x60, 0x8d, 0xe2, 0xdc, + 0x2b, 0x50, 0x56, 0xc8, 0xfd, 0xb4, 0x38, 0xe3, 0x3a, 0x73, 0xf1, 0x39, 0x98, 0x4a, 0xb5, 0x75, + 0x2c, 0x25, 0xd0, 0xaf, 0x58, 0x30, 0xc5, 0xbb, 0xbc, 0xec, 0xef, 0x89, 0x33, 0xf5, 0x7d, 0x38, + 0xeb, 0x65, 0x9c, 0x6d, 0x62, 0x46, 0x07, 0x3f, 0x0b, 0x95, 0xd2, 0x27, 0x0b, 0x8a, 0x33, 0xdb, + 0x40, 0x57, 0xe9, 0xba, 0xa5, 0x67, 0x97, 0xe3, 0x09, 0xdf, 0xa1, 0x71, 0xbe, 0x66, 0x79, 0x19, + 0x56, 0x50, 0xfb, 0x77, 0x2c, 0x98, 0xe1, 0x3d, 0xbf, 0x45, 0xf6, 0xd5, 0x0e, 0xff, 0x30, 0xfb, + 0x2e, 0x72, 0x5c, 0x14, 0x72, 0x72, 0x5c, 0xe8, 0x9f, 0x56, 0xec, 0xf9, 0x69, 0x3f, 0x6f, 0x81, + 0x58, 0x81, 0xa7, 0x20, 0xca, 0x7f, 0xbb, 0x29, 0xca, 0xcf, 0xe5, 0x2f, 0xea, 0x1c, 0x19, 0xfe, + 0x4f, 0x2d, 0x98, 0xe6, 0x08, 0xc9, 0x5b, 0xf2, 0x87, 0x3a, 0x0f, 0x83, 0x24, 0xab, 0x53, 0xd9, + 0xa9, 0xb3, 0x3f, 0xca, 0x98, 0xac, 0x52, 0xcf, 0xc9, 0x6a, 0xca, 0x0d, 0x74, 0x8c, 0x24, 0x8c, + 0xc7, 0x8e, 0x15, 0x6d, 0xff, 0x91, 0x05, 0x88, 0x37, 0x63, 0xb0, 0x3f, 0x94, 0xa9, 0x60, 0xa5, + 0xda, 0x75, 0x91, 0x1c, 0x35, 0x0a, 0x82, 0x35, 0xac, 0x13, 0x19, 0x9e, 0x94, 0x41, 0x40, 0xb1, + 0xbf, 0x41, 0xc0, 0x31, 0x46, 0xf4, 0x6b, 0x25, 0x48, 0x1b, 0xf3, 0xa3, 0x7b, 0x30, 0xde, 0x70, + 0xda, 0xce, 0xa6, 0xeb, 0xb9, 0xb1, 0x4b, 0xa2, 0x5e, 0x96, 0x44, 0x4b, 0x1a, 0x9e, 0x78, 0xea, + 0xd5, 0x4a, 0xb0, 0x41, 0x07, 0xcd, 0x03, 0xb4, 0x43, 0x77, 0xcf, 0xf5, 0x48, 0x8b, 0x69, 0x1c, + 0x98, 0xb7, 0x22, 0x37, 0x8f, 0x91, 0xa5, 0x58, 0xc3, 0xc8, 0x70, 0x3c, 0x2b, 0x3e, 0x3a, 0xc7, + 0xb3, 0xd2, 0x31, 0x1d, 0xcf, 0x86, 0x06, 0x72, 0x3c, 0xc3, 0x70, 0x5e, 0xb2, 0x48, 0xf4, 0xff, + 0x8a, 0xeb, 0x11, 0xc1, 0x17, 0x73, 0x1f, 0xc6, 0xb9, 0xc3, 0x83, 0xca, 0x79, 0x9c, 0x89, 0x81, + 0x73, 0x6a, 0xa2, 0xcf, 0xc3, 0xac, 0xe3, 0x79, 0xc1, 0x7d, 0x35, 0x6a, 0xcb, 0x51, 0xc3, 0xf1, + 0xb8, 0xc6, 0x7e, 0x84, 0x51, 0x7d, 0xe2, 0xf0, 0xa0, 0x32, 0xbb, 0x90, 0x83, 0x83, 0x73, 0x6b, + 0xa7, 0xfc, 0xd6, 0x46, 0xfb, 0xf9, 0xad, 0xd9, 0x3b, 0x70, 0xa6, 0x4e, 0x42, 0x97, 0xa5, 0x88, + 0x6c, 0x26, 0x5b, 0x72, 0x03, 0xca, 0x61, 0xea, 0x10, 0x1a, 0x28, 0xb0, 0x91, 0x16, 0x06, 0x57, + 0x1e, 0x3a, 0x09, 0x21, 0xfb, 0x4f, 0x2c, 0x18, 0x11, 0x0e, 0x05, 0xa7, 0xc0, 0xfb, 0x2c, 0x18, + 0x2a, 0xe8, 0x4a, 0xf6, 0x41, 0xcd, 0x3a, 0x93, 0xab, 0x7c, 0x5e, 0x4d, 0x29, 0x9f, 0x9f, 0xec, + 0x45, 0xa4, 0xb7, 0xda, 0xf9, 0x6f, 0x15, 0x61, 0xd2, 0x74, 0xa6, 0x38, 0x85, 0x21, 0x58, 0x87, + 0x91, 0x48, 0x78, 0xee, 0x14, 0xf2, 0x6d, 0x9f, 0xd3, 0x93, 0x98, 0x18, 0x36, 0x09, 0x5f, 0x1d, + 0x49, 0x24, 0xd3, 0x25, 0xa8, 0xf8, 0x08, 0x5d, 0x82, 0xfa, 0xf9, 0xb3, 0x94, 0x4e, 0xc2, 0x9f, + 0xc5, 0xfe, 0x3a, 0xbb, 0x2c, 0xf4, 0xf2, 0x53, 0xe0, 0x23, 0x6e, 0x98, 0xd7, 0x8a, 0xdd, 0x63, + 0x65, 0x89, 0x4e, 0xe5, 0xf0, 0x13, 0xbf, 0x64, 0xc1, 0xc5, 0x8c, 0xaf, 0xd2, 0x98, 0x8b, 0xe7, + 0x60, 0xd4, 0xe9, 0x34, 0x5d, 0xb5, 0x97, 0xb5, 0x87, 0xa8, 0x05, 0x51, 0x8e, 0x15, 0x06, 0x5a, + 0x82, 0x19, 0xf2, 0xa0, 0xed, 0xf2, 0x97, 0x40, 0xdd, 0xfa, 0xb0, 0xc8, 0x43, 0xbc, 0x2e, 0xa7, + 0x81, 0xb8, 0x1b, 0x5f, 0xb9, 0x43, 0x17, 0x73, 0xdd, 0xa1, 0xff, 0xa1, 0x05, 0x63, 0xa2, 0xdb, + 0xa7, 0x30, 0xda, 0xdf, 0x61, 0x8e, 0xf6, 0xe3, 0x3d, 0x46, 0x3b, 0x67, 0x98, 0xff, 0x4e, 0x41, + 0xf5, 0xb7, 0x16, 0x84, 0xf1, 0x00, 0x4c, 0xcb, 0xab, 0x30, 0xda, 0x0e, 0x83, 0x38, 0x68, 0x04, + 0x9e, 0xe0, 0x59, 0x9e, 0x48, 0xbc, 0xf5, 0x79, 0xf9, 0x91, 0xf6, 0x1b, 0x2b, 0x6c, 0x36, 0x7a, + 0x41, 0x18, 0x0b, 0x3e, 0x21, 0x19, 0xbd, 0x20, 0x8c, 0x31, 0x83, 0xa0, 0x26, 0x40, 0xec, 0x84, + 0x2d, 0x12, 0xd3, 0x32, 0x11, 0xf8, 0x23, 0xff, 0xf0, 0xe8, 0xc4, 0xae, 0x37, 0xef, 0xfa, 0x71, + 0x14, 0x87, 0xf3, 0xab, 0x7e, 0x7c, 0x27, 0xe4, 0x22, 0x90, 0xe6, 0x7e, 0xaf, 0x68, 0x61, 0x8d, + 0xae, 0xf4, 0x91, 0x64, 0x6d, 0x0c, 0x99, 0x4f, 0xda, 0xeb, 0xa2, 0x1c, 0x2b, 0x0c, 0xfb, 0x15, + 0x76, 0x95, 0xb0, 0x01, 0x3a, 0x9e, 0x67, 0xfc, 0x37, 0x46, 0xd5, 0xd0, 0xb2, 0xf7, 0xac, 0xaa, + 0xee, 0x7f, 0xdf, 0xfb, 0xe4, 0xa6, 0x0d, 0xeb, 0x9e, 0x30, 0x89, 0x93, 0x3e, 0xfa, 0xce, 0x2e, + 0x4b, 0x87, 0xe7, 0xfb, 0x5c, 0x01, 0xc7, 0xb0, 0x6d, 0x60, 0x61, 0xa7, 0x59, 0x78, 0xde, 0xd5, + 0x9a, 0x58, 0xe4, 0x5a, 0xd8, 0x69, 0x01, 0xc0, 0x09, 0x0e, 0xba, 0x26, 0x04, 0xe8, 0x92, 0x91, + 0x1d, 0x4e, 0x0a, 0xd0, 0xf2, 0xf3, 0x35, 0x09, 0xfa, 0x05, 0x18, 0x53, 0x59, 0xe2, 0x6a, 0x3c, + 0xd9, 0x96, 0x08, 0x83, 0xb2, 0x9c, 0x14, 0x63, 0x1d, 0x07, 0x6d, 0xc0, 0x54, 0xc4, 0xb5, 0x27, + 0x2a, 0xda, 0x1d, 0xd7, 0x42, 0x7d, 0x52, 0x5a, 0x48, 0xd4, 0x4d, 0xf0, 0x11, 0x2b, 0xe2, 0x47, + 0x87, 0x74, 0x74, 0x4c, 0x93, 0x40, 0xaf, 0xc3, 0xa4, 0xa7, 0xe7, 0x5a, 0xaf, 0x09, 0x25, 0x95, + 0x32, 0x20, 0x36, 0x32, 0xb1, 0xd7, 0x70, 0x0a, 0x9b, 0xf2, 0x3a, 0x7a, 0x89, 0x88, 0xd0, 0xe8, + 0xf8, 0x2d, 0x12, 0x89, 0x1c, 0x57, 0x8c, 0xd7, 0xb9, 0x9d, 0x83, 0x83, 0x73, 0x6b, 0xa3, 0x57, + 0x61, 0x5c, 0x7e, 0xbe, 0xe6, 0xc6, 0x9b, 0x98, 0xa9, 0x6b, 0x30, 0x6c, 0x60, 0xa2, 0xfb, 0x70, + 0x4e, 0xfe, 0xdf, 0x08, 0x9d, 0xad, 0x2d, 0xb7, 0x21, 0xbc, 0xa8, 0xb9, 0xaf, 0xce, 0x82, 0x74, + 0xfe, 0x59, 0xce, 0x42, 0x3a, 0x3a, 0xa8, 0x5c, 0x16, 0xa3, 0x96, 0x09, 0x67, 0x93, 0x98, 0x4d, + 0x1f, 0xad, 0xc1, 0x99, 0x6d, 0xe2, 0x78, 0xf1, 0xf6, 0xd2, 0x36, 0x69, 0xec, 0xc8, 0x4d, 0xc4, + 0x9c, 0x83, 0x35, 0xe3, 0xee, 0x9b, 0xdd, 0x28, 0x38, 0xab, 0x1e, 0x7a, 0x07, 0x66, 0xdb, 0x9d, + 0x4d, 0xcf, 0x8d, 0xb6, 0xd7, 0x83, 0x98, 0x19, 0x65, 0xa8, 0x24, 0x6b, 0xc2, 0x8b, 0x58, 0x39, + 0x46, 0xd7, 0x72, 0xf0, 0x70, 0x2e, 0x05, 0xf4, 0x3e, 0x9c, 0x4b, 0x2d, 0x06, 0xe1, 0xd3, 0x38, + 0x99, 0x1f, 0xef, 0xb6, 0x9e, 0x55, 0x41, 0xf8, 0x28, 0x66, 0x81, 0x70, 0x76, 0x13, 0x1f, 0xcc, + 0x54, 0xe7, 0x3d, 0x5a, 0x59, 0x63, 0xca, 0xd0, 0x97, 0x61, 0x5c, 0x5f, 0x45, 0xe2, 0x82, 0xb9, + 0x92, 0xcd, 0xb3, 0x68, 0xab, 0x8d, 0xb3, 0x74, 0x6a, 0x45, 0xe9, 0x30, 0x6c, 0x50, 0xb4, 0x09, + 0x64, 0x7f, 0x1f, 0xba, 0x0d, 0xa3, 0x0d, 0xcf, 0x25, 0x7e, 0xbc, 0x5a, 0xeb, 0x15, 0x74, 0x63, + 0x49, 0xe0, 0x88, 0x01, 0x13, 0x01, 0x42, 0x79, 0x19, 0x56, 0x14, 0xec, 0xdf, 0x28, 0x40, 0xa5, + 0x4f, 0xb4, 0xd9, 0x94, 0x46, 0xd9, 0x1a, 0x48, 0xa3, 0xbc, 0x20, 0x53, 0xc6, 0xad, 0xa7, 0xc4, + 0xec, 0x54, 0x3a, 0xb8, 0x44, 0xd8, 0x4e, 0xe3, 0x0f, 0x6c, 0xe1, 0xab, 0x2b, 0xa5, 0x4b, 0x7d, + 0x6d, 0xcf, 0x8d, 0xc7, 0xa8, 0xa1, 0xc1, 0x05, 0x91, 0xdc, 0x87, 0x05, 0xfb, 0xeb, 0x05, 0x38, + 0xa7, 0x86, 0xf0, 0x2f, 0xee, 0xc0, 0xdd, 0xed, 0x1e, 0xb8, 0x13, 0x78, 0x96, 0xb1, 0xef, 0xc0, + 0x30, 0x0f, 0x5a, 0x32, 0x00, 0x03, 0xf4, 0x94, 0x19, 0xe1, 0x4a, 0x5d, 0xd3, 0x46, 0x94, 0xab, + 0xbf, 0x62, 0xc1, 0xd4, 0xc6, 0x52, 0xad, 0x1e, 0x34, 0x76, 0x48, 0xbc, 0xc0, 0x19, 0x56, 0x2c, + 0xf8, 0x1f, 0xeb, 0x21, 0xf9, 0x9a, 0x2c, 0x8e, 0xe9, 0x32, 0x94, 0xb6, 0x83, 0x28, 0x4e, 0xbf, + 0xd9, 0xde, 0x0c, 0xa2, 0x18, 0x33, 0x88, 0xfd, 0xbb, 0x16, 0x0c, 0xb1, 0x44, 0xa7, 0xfd, 0xb2, + 0xef, 0x0e, 0xf2, 0x5d, 0xe8, 0x65, 0x18, 0x26, 0x5b, 0x5b, 0xa4, 0x11, 0x8b, 0x59, 0x95, 0x0e, + 0xa5, 0xc3, 0xcb, 0xac, 0x94, 0x5e, 0xfa, 0xac, 0x31, 0xfe, 0x17, 0x0b, 0x64, 0xf4, 0x16, 0x94, + 0x63, 0x77, 0x97, 0x2c, 0x34, 0x9b, 0xe2, 0xd5, 0xeb, 0x21, 0xfc, 0x77, 0x37, 0x24, 0x01, 0x9c, + 0xd0, 0xb2, 0xbf, 0x5a, 0x00, 0x48, 0x5c, 0xef, 0xfb, 0x7d, 0xe2, 0x62, 0xd7, 0x7b, 0xc8, 0x95, + 0x8c, 0xf7, 0x10, 0x94, 0x10, 0xcc, 0x78, 0x0c, 0x51, 0xc3, 0x54, 0x1c, 0x68, 0x98, 0x4a, 0xc7, + 0x19, 0xa6, 0x25, 0x98, 0x49, 0x42, 0x07, 0x98, 0x71, 0x54, 0x98, 0x90, 0xb2, 0x91, 0x06, 0xe2, + 0x6e, 0x7c, 0x9b, 0xc0, 0x65, 0x19, 0xd1, 0x52, 0xde, 0x35, 0xcc, 0xa8, 0xf2, 0x18, 0x89, 0x98, + 0x93, 0x07, 0x9f, 0x42, 0xee, 0x83, 0xcf, 0x4f, 0x59, 0x70, 0x36, 0xdd, 0x0e, 0xf3, 0x5e, 0xfb, + 0x01, 0x0b, 0xce, 0xb1, 0x67, 0x2f, 0xd6, 0x6a, 0xf7, 0x23, 0xdb, 0x4b, 0xd9, 0x21, 0x15, 0x7a, + 0xf7, 0x38, 0xf1, 0x5c, 0x5e, 0xcb, 0x22, 0x8d, 0xb3, 0x5b, 0xb4, 0xbf, 0xdf, 0x02, 0xe1, 0x24, + 0x34, 0xc0, 0xc6, 0x7e, 0x5b, 0xa6, 0x2a, 0x35, 0x02, 0x78, 0x5f, 0xce, 0xf7, 0x9a, 0x12, 0x61, + 0xbb, 0xd5, 0x45, 0x6a, 0x04, 0xeb, 0x36, 0x68, 0xd9, 0x4d, 0x10, 0xd0, 0x2a, 0x61, 0x7a, 0xa2, + 0xfe, 0xbd, 0xb9, 0x0e, 0xd0, 0x64, 0xb8, 0x5a, 0xc2, 0x42, 0x75, 0x6c, 0x57, 0x15, 0x04, 0x6b, + 0x58, 0xf6, 0x8f, 0x14, 0x60, 0x4c, 0x06, 0x8c, 0xee, 0xf8, 0x83, 0x48, 0x73, 0xc7, 0xca, 0x1b, + 0xc3, 0x32, 0x7c, 0x52, 0xc2, 0xb5, 0x44, 0x08, 0x4e, 0x32, 0x7c, 0x4a, 0x00, 0x4e, 0x70, 0xd0, + 0x33, 0x30, 0x12, 0x75, 0x36, 0x19, 0x7a, 0xca, 0xf5, 0xa5, 0xce, 0x8b, 0xb1, 0x84, 0xa3, 0xcf, + 0xc3, 0x34, 0xaf, 0x17, 0x06, 0x6d, 0xa7, 0xc5, 0x95, 0x86, 0x43, 0xca, 0x17, 0x75, 0x7a, 0x2d, + 0x05, 0x3b, 0x3a, 0xa8, 0x9c, 0x4d, 0x97, 0x31, 0x75, 0x73, 0x17, 0x15, 0xfb, 0xcb, 0x80, 0xba, + 0x63, 0x60, 0xa3, 0x37, 0xb8, 0x01, 0x92, 0x1b, 0x92, 0x66, 0x2f, 0x3d, 0xb2, 0xee, 0x3a, 0x29, + 0xcd, 0xcf, 0x79, 0x2d, 0xac, 0xea, 0xdb, 0x7f, 0xad, 0x08, 0xd3, 0x69, 0x47, 0x3a, 0x74, 0x13, + 0x86, 0xf9, 0x05, 0x23, 0xc8, 0xf7, 0x78, 0xa6, 0xd4, 0xdc, 0xef, 0xd8, 0x56, 0x13, 0x77, 0x94, + 0xa8, 0x8f, 0xde, 0x81, 0xb1, 0x66, 0x70, 0xdf, 0xbf, 0xef, 0x84, 0xcd, 0x85, 0xda, 0xaa, 0x58, + 0x97, 0x99, 0x7c, 0x6a, 0x35, 0x41, 0xd3, 0x5d, 0xfa, 0x98, 0x4a, 0x3e, 0x01, 0x61, 0x9d, 0x1c, + 0xda, 0x60, 0x71, 0xfd, 0xb6, 0xdc, 0xd6, 0x9a, 0xd3, 0xee, 0x65, 0x8d, 0xba, 0x24, 0x91, 0x34, + 0xca, 0x13, 0x22, 0xf8, 0x1f, 0x07, 0xe0, 0x84, 0x10, 0xfa, 0x6e, 0x38, 0x13, 0xe5, 0xa8, 0xb6, + 0xf2, 0x52, 0x22, 0xf4, 0xd2, 0xf6, 0x2c, 0x3e, 0x46, 0x25, 0x88, 0x2c, 0x25, 0x58, 0x56, 0x33, + 0xf6, 0x57, 0xce, 0x80, 0xb1, 0x1b, 0x8d, 0xbc, 0x38, 0xd6, 0x09, 0xe5, 0xc5, 0xc1, 0x30, 0x4a, + 0x76, 0xdb, 0xf1, 0x7e, 0xd5, 0x0d, 0x7b, 0x25, 0x56, 0x5b, 0x16, 0x38, 0xdd, 0x34, 0x25, 0x04, + 0x2b, 0x3a, 0xd9, 0xc9, 0x8b, 0x8a, 0x1f, 0x62, 0xf2, 0xa2, 0xd2, 0x29, 0x26, 0x2f, 0x5a, 0x87, + 0x91, 0x96, 0x1b, 0x63, 0xd2, 0x0e, 0x04, 0x6b, 0x97, 0xb9, 0x0e, 0x6f, 0x70, 0x94, 0xee, 0x84, + 0x19, 0x02, 0x80, 0x25, 0x11, 0xf4, 0x86, 0xda, 0x81, 0xc3, 0xf9, 0x92, 0x51, 0xf7, 0x7b, 0x5a, + 0xe6, 0x1e, 0x14, 0xc9, 0x8a, 0x46, 0x1e, 0x36, 0x59, 0xd1, 0x8a, 0x4c, 0x31, 0x34, 0x9a, 0x6f, + 0x3a, 0xce, 0x32, 0x08, 0xf5, 0x49, 0x2c, 0x64, 0x24, 0x63, 0x2a, 0x9f, 0x5c, 0x32, 0xa6, 0xef, + 0xb7, 0xe0, 0x5c, 0x3b, 0x2b, 0x2f, 0x99, 0x48, 0x0c, 0xf4, 0xf2, 0xc0, 0x89, 0xd7, 0x8c, 0x06, + 0x99, 0x88, 0x9c, 0x89, 0x86, 0xb3, 0x9b, 0xa3, 0x03, 0x1d, 0x6e, 0x36, 0x45, 0x36, 0xa1, 0xa7, + 0x72, 0xb2, 0x3a, 0xf5, 0xc8, 0xe5, 0xb4, 0x91, 0x91, 0x41, 0xe8, 0xe3, 0x79, 0x19, 0x84, 0x06, + 0xce, 0x1b, 0xf4, 0x86, 0xca, 0xe7, 0x34, 0x91, 0xbf, 0x94, 0x78, 0xb6, 0xa6, 0xbe, 0x59, 0x9c, + 0xde, 0x50, 0x59, 0x9c, 0x7a, 0xc4, 0x37, 0xe3, 0x39, 0x9a, 0xfa, 0xe6, 0x6e, 0xd2, 0xf2, 0x2f, + 0x4d, 0x9d, 0x4c, 0xfe, 0x25, 0xe3, 0xaa, 0xe1, 0x29, 0x80, 0x9e, 0xed, 0x73, 0xd5, 0x18, 0x74, + 0x7b, 0x5f, 0x36, 0x3c, 0xd7, 0xd4, 0xcc, 0x43, 0xe5, 0x9a, 0xba, 0xa7, 0xe7, 0x6e, 0x42, 0x7d, + 0x92, 0x13, 0x51, 0xa4, 0x01, 0x33, 0x36, 0xdd, 0xd3, 0x2f, 0xc0, 0x33, 0xf9, 0x74, 0xd5, 0x3d, + 0xd7, 0x4d, 0x37, 0xf3, 0x0a, 0xec, 0xca, 0x04, 0x75, 0xf6, 0x74, 0x32, 0x41, 0x9d, 0x3b, 0xf1, + 0x4c, 0x50, 0xe7, 0x4f, 0x21, 0x13, 0xd4, 0x63, 0x1f, 0x6a, 0x26, 0xa8, 0xd9, 0x47, 0x90, 0x09, + 0x6a, 0x3d, 0xc9, 0x04, 0x75, 0x21, 0x7f, 0x4a, 0x32, 0xec, 0x59, 0x73, 0xf2, 0x3f, 0xdd, 0x83, + 0x72, 0x5b, 0x46, 0x7a, 0x10, 0x01, 0xd8, 0xb2, 0x93, 0xd1, 0x66, 0x85, 0x83, 0xe0, 0x53, 0xa2, + 0x40, 0x38, 0x21, 0x45, 0xe9, 0x26, 0xf9, 0xa0, 0x1e, 0xef, 0xa1, 0x04, 0xcd, 0x52, 0x2f, 0xe5, + 0x67, 0x81, 0xb2, 0xff, 0x6a, 0x01, 0x2e, 0xf5, 0x5e, 0xd7, 0x89, 0x6e, 0xaa, 0x96, 0xbc, 0xa5, + 0xa4, 0x74, 0x53, 0x5c, 0xc8, 0x49, 0xb0, 0x06, 0x0e, 0x87, 0x73, 0x03, 0x66, 0x94, 0x21, 0xab, + 0xe7, 0x36, 0xf6, 0xb5, 0x24, 0xb5, 0xca, 0x61, 0xaf, 0x9e, 0x46, 0xc0, 0xdd, 0x75, 0xd0, 0x02, + 0x4c, 0x19, 0x85, 0xab, 0x55, 0x21, 0xcc, 0x28, 0x65, 0x58, 0xdd, 0x04, 0xe3, 0x34, 0xbe, 0xfd, + 0x73, 0x16, 0x3c, 0x96, 0x93, 0x24, 0x61, 0xe0, 0x68, 0x2f, 0x5b, 0x30, 0xd5, 0x36, 0xab, 0xf6, + 0x09, 0x0a, 0x65, 0xa4, 0x62, 0x50, 0x7d, 0x4d, 0x01, 0x70, 0x9a, 0xe8, 0xe2, 0xd5, 0xdf, 0xfa, + 0xfd, 0x4b, 0x1f, 0xfb, 0xed, 0xdf, 0xbf, 0xf4, 0xb1, 0xdf, 0xf9, 0xfd, 0x4b, 0x1f, 0xfb, 0xff, + 0x0f, 0x2f, 0x59, 0xbf, 0x75, 0x78, 0xc9, 0xfa, 0xed, 0xc3, 0x4b, 0xd6, 0xef, 0x1c, 0x5e, 0xb2, + 0x7e, 0xef, 0xf0, 0x92, 0xf5, 0xd5, 0x3f, 0xb8, 0xf4, 0xb1, 0xb7, 0x0b, 0x7b, 0x2f, 0xfc, 0xbf, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x41, 0x99, 0x07, 0x31, 0x7e, 0xe5, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/generated.proto index 845db97b1..9efa19621 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,7 +21,6 @@ syntax = 'proto2'; package k8s.io.api.core.v1; -import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; @@ -188,7 +187,7 @@ message CSIPersistentVolumeSource { // Filesystem type to mount. // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // Ex. "ext4", "xfs", "ntfs". // +optional optional string fsType = 4; @@ -298,6 +297,34 @@ message CephFSVolumeSource { optional bool readOnly = 6; } +// Represents a cinder volume resource in Openstack. +// A Cinder volume must exist before mounting to a container. +// The volume must also be in the same region as the kubelet. +// Cinder volumes support ownership management and SELinux relabeling. +message CinderPersistentVolumeSource { + // volume id used to identify the volume in cinder + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + optional string volumeID = 1; + + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + optional string fsType = 2; + + // Optional: Defaults to false (read/write). ReadOnly here will force + // the ReadOnly setting in VolumeMounts. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + optional bool readOnly = 3; + + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + optional SecretReference secretRef = 4; +} + // Represents a cinder volume resource in Openstack. // A Cinder volume must exist before mounting to a container. // The volume must also be in the same region as the kubelet. @@ -319,6 +346,11 @@ message CinderVolumeSource { // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional optional bool readOnly = 3; + + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + optional LocalObjectReference secretRef = 4; } // ClientIPConfig represents the configurations of Client IP based session affinity. @@ -439,6 +471,31 @@ message ConfigMapList { repeated ConfigMap items = 2; } +// ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node. +message ConfigMapNodeConfigSource { + // Namespace is the metadata.namespace of the referenced ConfigMap. + // This field is required in all cases. + optional string namespace = 1; + + // Name is the metadata.name of the referenced ConfigMap. + // This field is required in all cases. + optional string name = 2; + + // UID is the metadata.UID of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + optional string uid = 3; + + // ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + optional string resourceVersion = 4; + + // KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure + // This field is required in all cases. + optional string kubeletConfigKey = 5; +} + // Adapts a ConfigMap into a projected volume. // // The contents of the target ConfigMap's Data field will be presented in a @@ -809,41 +866,6 @@ message DaemonEndpoint { optional int32 Port = 1; } -// DeleteOptions may be provided when deleting an API object -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -// +k8s:openapi-gen=false -message DeleteOptions { - // The duration in seconds before the object should be deleted. Value must be non-negative integer. - // The value zero indicates delete immediately. If this value is nil, the default grace period for the - // specified type will be used. - // Defaults to a per object value if not specified. zero means delete immediately. - // +optional - optional int64 gracePeriodSeconds = 1; - - // Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be - // returned. - // +optional - optional Preconditions preconditions = 2; - - // Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. - // Should the dependent objects be orphaned. If true/false, the "orphan" - // finalizer will be added to/removed from the object's finalizers list. - // Either this field or PropagationPolicy may be set, but not both. - // +optional - optional bool orphanDependents = 3; - - // Whether and how garbage collection will be performed. - // Either this field or OrphanDependents may be set, but not both. - // The default policy is decided by the existing finalizer set in the - // metadata.finalizers and the resource-specific default policy. - // Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - - // allow the garbage collector to delete the dependents in the background; - // 'Foreground' - a cascading policy that deletes all dependents in the - // foreground. - // +optional - optional string propagationPolicy = 4; -} - // Represents downward API info for projecting into a projected volume. // Note that this is identical to a downwardAPI volume source without the default // mode. @@ -1328,6 +1350,10 @@ message GCEPersistentDiskVolumeSource { // Represents a volume that is populated with the contents of a git repository. // Git repo volumes do not support ownership management. // Git repo volumes support SELinux relabeling. +// +// DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an +// EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir +// into the Pod's container. message GitRepoVolumeSource { // Repository URL optional string repository = 1; @@ -1662,43 +1688,6 @@ message List { repeated k8s.io.apimachinery.pkg.runtime.RawExtension items = 2; } -// ListOptions is the query options to a standard REST list call. -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -// +k8s:openapi-gen=false -message ListOptions { - // A selector to restrict the list of returned objects by their labels. - // Defaults to everything. - // +optional - optional string labelSelector = 1; - - // A selector to restrict the list of returned objects by their fields. - // Defaults to everything. - // +optional - optional string fieldSelector = 2; - - // If true, partially initialized resources are included in the response. - // +optional - optional bool includeUninitialized = 6; - - // Watch for changes to the described resources and return them as a stream of - // add, update, and remove notifications. Specify resourceVersion. - // +optional - optional bool watch = 3; - - // When specified with a watch call, shows changes that occur after that particular version of a resource. - // Defaults to changes from the beginning of history. - // When specified for list: - // - if unset, then the result is returned from remote storage based on quorum-read flag; - // - if it's 0, then we simply return what we currently have in cache, no guarantee; - // - if set to non zero, then the result is at least as fresh as given rv. - // +optional - optional string resourceVersion = 4; - - // Timeout for the list/watch call. - // +optional - optional int64 timeoutSeconds = 5; -} - // LoadBalancerIngress represents the status of a load-balancer ingress point: // traffic intended for the service should be sent to an ingress point. message LoadBalancerIngress { @@ -1731,11 +1720,13 @@ message LocalObjectReference { optional string name = 1; } -// Local represents directly-attached storage with node affinity +// Local represents directly-attached storage with node affinity (Beta feature) message LocalVolumeSource { - // The full path to the volume on the node - // For alpha, this path must be a directory - // Once block as a source is supported, then this path can point to a block device + // The full path to the volume on the node. + // It can be either a directory or block device (disk, partition, ...). + // Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. + // Block devices can be represented only by VolumeMode=Block, which also requires the + // BlockVolume alpha feature gate to be enabled. optional string path = 1; } @@ -1885,7 +1876,58 @@ message NodeCondition { // NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil. message NodeConfigSource { - optional ObjectReference configMapRef = 1; + // ConfigMap is a reference to a Node's ConfigMap + optional ConfigMapNodeConfigSource configMap = 2; +} + +// NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource. +message NodeConfigStatus { + // Assigned reports the checkpointed config the node will try to use. + // When Node.Spec.ConfigSource is updated, the node checkpoints the associated + // config payload to local disk, along with a record indicating intended + // config. The node refers to this record to choose its config checkpoint, and + // reports this record in Assigned. Assigned only updates in the status after + // the record has been checkpointed to disk. When the Kubelet is restarted, + // it tries to make the Assigned config the Active config by loading and + // validating the checkpointed payload identified by Assigned. + // +optional + optional NodeConfigSource assigned = 1; + + // Active reports the checkpointed config the node is actively using. + // Active will represent either the current version of the Assigned config, + // or the current LastKnownGood config, depending on whether attempting to use the + // Assigned config results in an error. + // +optional + optional NodeConfigSource active = 2; + + // LastKnownGood reports the checkpointed config the node will fall back to + // when it encounters an error attempting to use the Assigned config. + // The Assigned config becomes the LastKnownGood config when the node determines + // that the Assigned config is stable and correct. + // This is currently implemented as a 10-minute soak period starting when the local + // record of Assigned config is updated. If the Assigned config is Active at the end + // of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is + // reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, + // because the local default config is always assumed good. + // You should not make assumptions about the node's method of determining config stability + // and correctness, as this may change or become configurable in the future. + // +optional + optional NodeConfigSource lastKnownGood = 3; + + // Error describes any problems reconciling the Spec.ConfigSource to the Active config. + // Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned + // record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting + // to load or validate the Assigned config, etc. + // Errors may occur at different points while syncing config. Earlier errors (e.g. download or + // checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across + // Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in + // a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error + // by fixing the config assigned in Spec.ConfigSource. + // You can find additional information for debugging by searching the error message in the Kubelet log. + // Error is a human-readable description of the error state; machines can check whether or not Error + // is empty, but should not rely on the stability of the Error text across Kubelet versions. + // +optional + optional string error = 4; } // NodeDaemonEndpoints lists ports opened by daemons running on the Node. @@ -1947,10 +1989,17 @@ message NodeSelectorRequirement { repeated string values = 3; } -// A null or empty node selector term matches no objects. +// A null or empty node selector term matches no objects. The requirements of +// them are ANDed. +// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. message NodeSelectorTerm { - // Required. A list of node selector requirements. The requirements are ANDed. + // A list of node selector requirements by node's labels. + // +optional repeated NodeSelectorRequirement matchExpressions = 1; + + // A list of node selector requirements by node's fields. + // +optional + repeated NodeSelectorRequirement matchFields = 2; } // NodeSpec describes the attributes that a node is created with. @@ -1959,11 +2008,6 @@ message NodeSpec { // +optional optional string podCIDR = 1; - // External ID of the node assigned by some machine database (e.g. a cloud provider). - // Deprecated. - // +optional - optional string externalID = 2; - // ID of the node assigned by the cloud provider in the format: :// // +optional optional string providerID = 3; @@ -1981,6 +2025,11 @@ message NodeSpec { // The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field // +optional optional NodeConfigSource configSource = 6; + + // Deprecated. Not all kubelets will set this field. Remove field after 1.13. + // see: https://issues.k8s.io/61966 + // +optional + optional string externalID = 2; } // NodeStatus is information about the current status of a node. @@ -2036,6 +2085,10 @@ message NodeStatus { // List of volumes that are attached to the node. // +optional repeated AttachedVolume volumesAttached = 10; + + // Status of the config assigned to the node via the dynamic Kubelet config feature. + // +optional + optional NodeConfigStatus config = 11; } // NodeSystemInfo is a set of ids/uuids to uniquely identify the node. @@ -2085,170 +2138,6 @@ message ObjectFieldSelector { optional string fieldPath = 2; } -// ObjectMeta is metadata that all persisted resources must have, which includes all objects -// users must create. -// DEPRECATED: Use k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta instead - this type will be removed soon. -// +k8s:openapi-gen=false -message ObjectMeta { - // Name must be unique within a namespace. Is required when creating resources, although - // some resources may allow a client to request the generation of an appropriate name - // automatically. Name is primarily intended for creation idempotence and configuration - // definition. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - // +optional - optional string name = 1; - - // GenerateName is an optional prefix, used by the server, to generate a unique - // name ONLY IF the Name field has not been provided. - // If this field is used, the name returned to the client will be different - // than the name passed. This value will also be combined with a unique suffix. - // The provided value has the same validation rules as the Name field, - // and may be truncated by the length of the suffix required to make the value - // unique on the server. - // - // If this field is specified and the generated name exists, the server will - // NOT return a 409 - instead, it will either return 201 Created or 500 with Reason - // ServerTimeout indicating a unique name could not be found in the time allotted, and the client - // should retry (optionally after the time indicated in the Retry-After header). - // - // Applied only if Name is not specified. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency - // +optional - optional string generateName = 2; - - // Namespace defines the space within each name must be unique. An empty namespace is - // equivalent to the "default" namespace, but "default" is the canonical representation. - // Not all objects are required to be scoped to a namespace - the value of this field for - // those objects will be empty. - // - // Must be a DNS_LABEL. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - // +optional - optional string namespace = 3; - - // SelfLink is a URL representing this object. - // Populated by the system. - // Read-only. - // +optional - optional string selfLink = 4; - - // UID is the unique in time and space value for this object. It is typically generated by - // the server on successful creation of a resource and is not allowed to change on PUT - // operations. - // - // Populated by the system. - // Read-only. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - // +optional - optional string uid = 5; - - // An opaque value that represents the internal version of this object that can - // be used by clients to determine when objects have changed. May be used for optimistic - // concurrency, change detection, and the watch operation on a resource or set of resources. - // Clients must treat these values as opaque and passed unmodified back to the server. - // They may only be valid for a particular resource or set of resources. - // - // Populated by the system. - // Read-only. - // Value must be treated as opaque by clients and . - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency - // +optional - optional string resourceVersion = 6; - - // A sequence number representing a specific generation of the desired state. - // Populated by the system. Read-only. - // +optional - optional int64 generation = 7; - - // CreationTimestamp is a timestamp representing the server time when this object was - // created. It is not guaranteed to be set in happens-before order across separate operations. - // Clients may not set this value. It is represented in RFC3339 form and is in UTC. - // - // Populated by the system. - // Read-only. - // Null for lists. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time creationTimestamp = 8; - - // DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This - // field is set by the server when a graceful deletion is requested by the user, and is not - // directly settable by a client. The resource is expected to be deleted (no longer visible - // from resource lists, and not reachable by name) after the time in this field. Once set, - // this value may not be unset or be set further into the future, although it may be shortened - // or the resource may be deleted prior to this time. For example, a user may request that - // a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination - // signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard - // termination signal (SIGKILL) to the container and after cleanup, remove the pod from the - // API. In the presence of network partitions, this object may still exist after this - // timestamp, until an administrator or automated process can determine the resource is - // fully terminated. - // If not set, graceful deletion of the object has not been requested. - // - // Populated by the system when a graceful deletion is requested. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time deletionTimestamp = 9; - - // Number of seconds allowed for this object to gracefully terminate before - // it will be removed from the system. Only set when deletionTimestamp is also set. - // May only be shortened. - // Read-only. - // +optional - optional int64 deletionGracePeriodSeconds = 10; - - // Map of string keys and values that can be used to organize and categorize - // (scope and select) objects. May match selectors of replication controllers - // and services. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - // +optional - map labels = 11; - - // Annotations is an unstructured key value map stored with a resource that may be - // set by external tools to store and retrieve arbitrary metadata. They are not - // queryable and should be preserved when modifying objects. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ - // +optional - map annotations = 12; - - // List of objects depended by this object. If ALL objects in the list have - // been deleted, this object will be garbage collected. If this object is managed by a controller, - // then an entry in this list will point to this controller, with the controller field set to true. - // There cannot be more than one managing controller. - // +optional - // +patchMergeKey=uid - // +patchStrategy=merge - repeated k8s.io.apimachinery.pkg.apis.meta.v1.OwnerReference ownerReferences = 13; - - // An initializer is a controller which enforces some system invariant at object creation time. - // This field is a list of initializers that have not yet acted on this object. If nil or empty, - // this object has been completely initialized. Otherwise, the object is considered uninitialized - // and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to - // observe uninitialized objects. - // - // When an object is created, the system will populate this list with the current set of initializers. - // Only privileged users may set or modify this list. Once it is empty, it may not be modified further - // by any user. - optional k8s.io.apimachinery.pkg.apis.meta.v1.Initializers initializers = 16; - - // Must be empty before the object is deleted from the registry. Each entry - // is an identifier for the responsible component that will remove the entry - // from the list. If the deletionTimestamp of the object is non-nil, entries - // in this list can only be removed. - // +optional - // +patchStrategy=merge - repeated string finalizers = 14; - - // The name of the cluster which the object belongs to. - // This is used to distinguish resources with same name and namespace in different clusters. - // This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. - // +optional - optional string clusterName = 15; -} - // ObjectReference contains enough information to let you inspect or modify the referred object. // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object message ObjectReference { @@ -2502,7 +2391,7 @@ message PersistentVolumeSource { // Cinder represents a cinder volume attached and mounted on kubelets host machine // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional - optional CinderVolumeSource cinder = 8; + optional CinderPersistentVolumeSource cinder = 8; // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime // +optional @@ -2775,7 +2664,6 @@ message PodAttachOptions { // PodCondition contains details for the current condition of this pod. message PodCondition { // Type is the type of the condition. - // Currently only Ready. // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions optional string type = 1; @@ -2944,6 +2832,12 @@ message PodProxyOptions { optional string path = 1; } +// PodReadinessGate contains the reference to a pod condition +message PodReadinessGate { + // ConditionType refers to a condition in the pod's condition list with matching type. + optional string conditionType = 1; +} + // PodSecurityContext holds pod-level security attributes and common container settings. // Some fields are also present in container.securityContext. Field values of // container.securityContext take precedence over field values of PodSecurityContext. @@ -2998,6 +2892,11 @@ message PodSecurityContext { // If unset, the Kubelet will not modify the ownership and permissions of any volume. // +optional optional int64 fsGroup = 5; + + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // +optional + repeated Sysctl sysctls = 7; } // Describes the class of pods that should avoid this node. @@ -3196,12 +3095,36 @@ message PodSpec { // configuration based on DNSPolicy. // +optional optional PodDNSConfig dnsConfig = 26; + + // If specified, all readiness gates will be evaluated for pod readiness. + // A pod is ready when all its containers are ready AND + // all conditions specified in the readiness gates have status equal to "True" + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md + // +optional + repeated PodReadinessGate readinessGates = 28; } // PodStatus represents information about the status of a pod. Status may trail the actual -// state of a system. +// state of a system, especially if the node that hosts the pod cannot contact the control +// plane. message PodStatus { - // Current condition of the pod. + // The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. + // The conditions array, the reason and message fields, and the individual container status + // arrays contain more detail about the pod's status. + // There are five possible phase values: + // + // Pending: The pod has been accepted by the Kubernetes system, but one or more of the + // container images has not been created. This includes time before being scheduled as + // well as time spent downloading images over the network, which could take a while. + // Running: The pod has been bound to a node, and all of the containers have been created. + // At least one container is still running, or is in the process of starting or restarting. + // Succeeded: All containers in the pod have terminated in success, and will not be restarted. + // Failed: All containers in the pod have terminated, and at least one container has + // terminated in failure. The container either exited with non-zero status or was terminated + // by the system. + // Unknown: For some reason the state of the pod could not be obtained, typically due to an + // error in communicating with the host of the pod. + // // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase // +optional optional string phase = 1; @@ -3721,7 +3644,7 @@ message ResourceQuotaList { // ResourceQuotaSpec defines the desired hard limits to enforce for Quota. message ResourceQuotaSpec { - // Hard is the set of desired hard limits for each named resource. + // hard is the set of desired hard limits for each named resource. // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ // +optional map hard = 1; @@ -3730,6 +3653,12 @@ message ResourceQuotaSpec { // If not specified, the quota matches all objects. // +optional repeated string scopes = 2; + + // scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota + // but expressed using ScopeSelectorOperator in combination with possible values. + // For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched. + // +optional + optional ScopeSelector scopeSelector = 3; } // ResourceQuotaStatus defines the enforced hard limits and observed use. @@ -3866,6 +3795,32 @@ message ScaleIOVolumeSource { optional bool readOnly = 10; } +// A scope selector represents the AND of the selectors represented +// by the scoped-resource selector requirements. +message ScopeSelector { + // A list of scope selector requirements by scope of the resources. + // +optional + repeated ScopedResourceSelectorRequirement matchExpressions = 1; +} + +// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator +// that relates the scope name and values. +message ScopedResourceSelectorRequirement { + // The name of the scope that the selector applies to. + optional string scopeName = 1; + + // Represents a scope's relationship to a set of values. + // Valid operators are In, NotIn, Exists, DoesNotExist. + optional string operator = 2; + + // An array of string values. If the operator is In or NotIn, + // the values array must be non-empty. If the operator is Exists or DoesNotExist, + // the values array must be empty. + // This array is replaced during a strategic merge patch. + // +optional + repeated string values = 3; +} + // Secret holds secret data of a certain type. The total bytes of the values in // the Data field must be less than MaxSecretSize bytes. message Secret { @@ -4134,6 +4089,32 @@ message ServiceAccountList { repeated ServiceAccount items = 2; } +// ServiceAccountTokenProjection represents a projected service account token +// volume. This projection can be used to insert a service account token into +// the pods runtime filesystem for use against APIs (Kubernetes API Server or +// otherwise). +message ServiceAccountTokenProjection { + // Audience is the intended audience of the token. A recipient of a token + // must identify itself with an identifier specified in the audience of the + // token, and otherwise should reject the token. The audience defaults to the + // identifier of the apiserver. + // +optional + optional string audience = 1; + + // ExpirationSeconds is the requested duration of validity of the service + // account token. As the token approaches expiration, the kubelet volume + // plugin will proactively rotate the service account token. The kubelet will + // start trying to rotate the token if the token is older than 80 percent of + // its time to live or if the token is older than 24 hours.Defaults to 1 hour + // and must be at least 10 minutes. + // +optional + optional int64 expirationSeconds = 2; + + // Path is the path relative to the mount point of the file to project the + // token into. + optional string path = 3; +} + // ServiceList holds a list of services. message ServiceList { // Standard list metadata. @@ -4300,9 +4281,6 @@ message ServiceSpec { // The primary use case for setting this field is to use a StatefulSet's Headless Service // to propagate SRV records for its Pods without respect to their readiness for purpose // of peer discovery. - // This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints - // when that annotation is deprecated and all clients have been converted to use this - // field. // +optional optional bool publishNotReadyAddresses = 13; @@ -4465,6 +4443,28 @@ message Toleration { optional int64 tolerationSeconds = 5; } +// A topology selector requirement is a selector that matches given label. +// This is an alpha feature and may change in the future. +message TopologySelectorLabelRequirement { + // The label key that the selector applies to. + optional string key = 1; + + // An array of string values. One value must match the label to be selected. + // Each entry in Values is ORed. + repeated string values = 2; +} + +// A topology selector term represents the result of label queries. +// A null or empty topology selector term matches no objects. +// The requirements of them are ANDed. +// It provides a subset of functionality as NodeSelectorTerm. +// This is an alpha feature and may change in the future. +message TopologySelectorTerm { + // A list of topology selector requirements by labels. + // +optional + repeated TopologySelectorLabelRequirement matchLabelExpressions = 1; +} + // Volume represents a named volume in a pod that may be accessed by any container in the pod. message Volume { // Volume's name. @@ -4508,7 +4508,7 @@ message VolumeMount { // mountPropagation determines how mounts are propagated from the host // to container and the other way around. - // When not set, MountPropagationHostToContainer is used. + // When not set, MountPropagationNone is used. // This field is beta in 1.10. // +optional optional string mountPropagation = 5; @@ -4523,13 +4523,20 @@ message VolumeNodeAffinity { // Projection that may be projected along with other supported volume types message VolumeProjection { // information about the secret data to project + // +optional optional SecretProjection secret = 1; // information about the downwardAPI data to project + // +optional optional DownwardAPIProjection downwardAPI = 2; // information about the configMap data to project + // +optional optional ConfigMapProjection configMap = 3; + + // information about the serviceAccountToken data to project + // +optional + optional ServiceAccountTokenProjection serviceAccountToken = 4; } // Represents the source of a volume to mount. @@ -4564,6 +4571,9 @@ message VolumeSource { optional AWSElasticBlockStoreVolumeSource awsElasticBlockStore = 4; // GitRepo represents a git repository at a particular revision. + // DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an + // EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir + // into the Pod's container. // +optional optional GitRepoVolumeSource gitRepo = 5; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/meta.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/meta.go deleted file mode 100644 index 0e3f5d920..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/meta.go +++ /dev/null @@ -1,108 +0,0 @@ -/* -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 ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" -) - -func (obj *ObjectMeta) GetObjectMeta() metav1.Object { return obj } - -// Namespace implements metav1.Object for any object with an ObjectMeta typed field. Allows -// fast, direct access to metadata fields for API objects. -func (meta *ObjectMeta) GetNamespace() string { return meta.Namespace } -func (meta *ObjectMeta) SetNamespace(namespace string) { meta.Namespace = namespace } -func (meta *ObjectMeta) GetName() string { return meta.Name } -func (meta *ObjectMeta) SetName(name string) { meta.Name = name } -func (meta *ObjectMeta) GetGenerateName() string { return meta.GenerateName } -func (meta *ObjectMeta) SetGenerateName(generateName string) { meta.GenerateName = generateName } -func (meta *ObjectMeta) GetUID() types.UID { return meta.UID } -func (meta *ObjectMeta) SetUID(uid types.UID) { meta.UID = uid } -func (meta *ObjectMeta) GetResourceVersion() string { return meta.ResourceVersion } -func (meta *ObjectMeta) SetResourceVersion(version string) { meta.ResourceVersion = version } -func (meta *ObjectMeta) GetGeneration() int64 { return meta.Generation } -func (meta *ObjectMeta) SetGeneration(generation int64) { meta.Generation = generation } -func (meta *ObjectMeta) GetSelfLink() string { return meta.SelfLink } -func (meta *ObjectMeta) SetSelfLink(selfLink string) { meta.SelfLink = selfLink } -func (meta *ObjectMeta) GetCreationTimestamp() metav1.Time { return meta.CreationTimestamp } -func (meta *ObjectMeta) SetCreationTimestamp(creationTimestamp metav1.Time) { - meta.CreationTimestamp = creationTimestamp -} -func (meta *ObjectMeta) GetDeletionTimestamp() *metav1.Time { return meta.DeletionTimestamp } -func (meta *ObjectMeta) SetDeletionTimestamp(deletionTimestamp *metav1.Time) { - meta.DeletionTimestamp = deletionTimestamp -} -func (meta *ObjectMeta) GetDeletionGracePeriodSeconds() *int64 { return meta.DeletionGracePeriodSeconds } -func (meta *ObjectMeta) SetDeletionGracePeriodSeconds(deletionGracePeriodSeconds *int64) { - meta.DeletionGracePeriodSeconds = deletionGracePeriodSeconds -} -func (meta *ObjectMeta) GetLabels() map[string]string { return meta.Labels } -func (meta *ObjectMeta) SetLabels(labels map[string]string) { meta.Labels = labels } -func (meta *ObjectMeta) GetAnnotations() map[string]string { return meta.Annotations } -func (meta *ObjectMeta) SetAnnotations(annotations map[string]string) { meta.Annotations = annotations } -func (meta *ObjectMeta) GetInitializers() *metav1.Initializers { return meta.Initializers } -func (meta *ObjectMeta) SetInitializers(initializers *metav1.Initializers) { - meta.Initializers = initializers -} -func (meta *ObjectMeta) GetFinalizers() []string { return meta.Finalizers } -func (meta *ObjectMeta) SetFinalizers(finalizers []string) { meta.Finalizers = finalizers } - -func (meta *ObjectMeta) GetOwnerReferences() []metav1.OwnerReference { - ret := make([]metav1.OwnerReference, len(meta.OwnerReferences)) - for i := 0; i < len(meta.OwnerReferences); i++ { - ret[i].Kind = meta.OwnerReferences[i].Kind - ret[i].Name = meta.OwnerReferences[i].Name - ret[i].UID = meta.OwnerReferences[i].UID - ret[i].APIVersion = meta.OwnerReferences[i].APIVersion - if meta.OwnerReferences[i].Controller != nil { - value := *meta.OwnerReferences[i].Controller - ret[i].Controller = &value - } - if meta.OwnerReferences[i].BlockOwnerDeletion != nil { - value := *meta.OwnerReferences[i].BlockOwnerDeletion - ret[i].BlockOwnerDeletion = &value - } - } - return ret -} - -func (meta *ObjectMeta) SetOwnerReferences(references []metav1.OwnerReference) { - newReferences := make([]metav1.OwnerReference, len(references)) - for i := 0; i < len(references); i++ { - newReferences[i].Kind = references[i].Kind - newReferences[i].Name = references[i].Name - newReferences[i].UID = references[i].UID - newReferences[i].APIVersion = references[i].APIVersion - if references[i].Controller != nil { - value := *references[i].Controller - newReferences[i].Controller = &value - } - if references[i].BlockOwnerDeletion != nil { - value := *references[i].BlockOwnerDeletion - newReferences[i].BlockOwnerDeletion = &value - } - } - meta.OwnerReferences = newReferences -} - -func (meta *ObjectMeta) GetClusterName() string { - return meta.ClusterName -} -func (meta *ObjectMeta) SetClusterName(clusterName string) { - meta.ClusterName = clusterName -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/register.go index 526e1320a..1aac0cb41 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/register.go @@ -57,7 +57,6 @@ func addKnownTypes(scheme *runtime.Scheme) error { &Endpoints{}, &EndpointsList{}, &Node{}, - &NodeConfigSource{}, &NodeList{}, &NodeProxyOptions{}, &Binding{}, diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/resource.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/resource.go index 3bd6fec62..bb8041254 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/resource.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/resource.go @@ -48,13 +48,6 @@ func (self *ResourceList) Pods() *resource.Quantity { return &resource.Quantity{} } -func (self *ResourceList) NvidiaGPU() *resource.Quantity { - if val, ok := (*self)[ResourceNvidiaGPU]; ok { - return &val - } - return &resource.Quantity{} -} - func (self *ResourceList) StorageEphemeral() *resource.Quantity { if val, ok := (*self)[ResourceEphemeralStorage]; ok { return &val diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/types.go index 8a69833f5..d9f4869fb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/types.go @@ -23,209 +23,6 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" ) -// The comments for the structs and fields can be used from go-restful to -// generate Swagger API documentation for its models. Please read this PR for more -// information on the implementation: https://github.com/emicklei/go-restful/pull/215 -// -// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if -// they are on one line! For multiple line or blocks that you want to ignore use ---. -// Any context after a --- is ignored and not exported to the SwaggerAPI. -// -// The aforementioned methods can be generated by hack/update-generated-swagger-docs.sh - -// Common string formats -// --------------------- -// Many fields in this API have formatting requirements. The commonly used -// formats are defined here. -// -// C_IDENTIFIER: This is a string that conforms to the definition of an "identifier" -// in the C language. This is captured by the following regex: -// [A-Za-z_][A-Za-z0-9_]* -// This defines the format, but not the length restriction, which should be -// specified at the definition of any field of this type. -// -// DNS_LABEL: This is a string, no more than 63 characters long, that conforms -// to the definition of a "label" in RFCs 1035 and 1123. This is captured -// by the following regex: -// [a-z0-9]([-a-z0-9]*[a-z0-9])? -// -// DNS_SUBDOMAIN: This is a string, no more than 253 characters long, that conforms -// to the definition of a "subdomain" in RFCs 1035 and 1123. This is captured -// by the following regex: -// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* -// or more simply: -// DNS_LABEL(\.DNS_LABEL)* -// -// IANA_SVC_NAME: This is a string, no more than 15 characters long, that -// conforms to the definition of IANA service name in RFC 6335. -// It must contains at least one letter [a-z] and it must contains only [a-z0-9-]. -// Hypens ('-') cannot be leading or trailing character of the string -// and cannot be adjacent to other hyphens. - -// ObjectMeta is metadata that all persisted resources must have, which includes all objects -// users must create. -// DEPRECATED: Use k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta instead - this type will be removed soon. -// +k8s:openapi-gen=false -type ObjectMeta struct { - // Name must be unique within a namespace. Is required when creating resources, although - // some resources may allow a client to request the generation of an appropriate name - // automatically. Name is primarily intended for creation idempotence and configuration - // definition. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - // +optional - Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"` - - // GenerateName is an optional prefix, used by the server, to generate a unique - // name ONLY IF the Name field has not been provided. - // If this field is used, the name returned to the client will be different - // than the name passed. This value will also be combined with a unique suffix. - // The provided value has the same validation rules as the Name field, - // and may be truncated by the length of the suffix required to make the value - // unique on the server. - // - // If this field is specified and the generated name exists, the server will - // NOT return a 409 - instead, it will either return 201 Created or 500 with Reason - // ServerTimeout indicating a unique name could not be found in the time allotted, and the client - // should retry (optionally after the time indicated in the Retry-After header). - // - // Applied only if Name is not specified. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency - // +optional - GenerateName string `json:"generateName,omitempty" protobuf:"bytes,2,opt,name=generateName"` - - // Namespace defines the space within each name must be unique. An empty namespace is - // equivalent to the "default" namespace, but "default" is the canonical representation. - // Not all objects are required to be scoped to a namespace - the value of this field for - // those objects will be empty. - // - // Must be a DNS_LABEL. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - // +optional - Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"` - - // SelfLink is a URL representing this object. - // Populated by the system. - // Read-only. - // +optional - SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,4,opt,name=selfLink"` - - // UID is the unique in time and space value for this object. It is typically generated by - // the server on successful creation of a resource and is not allowed to change on PUT - // operations. - // - // Populated by the system. - // Read-only. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - // +optional - UID types.UID `json:"uid,omitempty" protobuf:"bytes,5,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"` - - // An opaque value that represents the internal version of this object that can - // be used by clients to determine when objects have changed. May be used for optimistic - // concurrency, change detection, and the watch operation on a resource or set of resources. - // Clients must treat these values as opaque and passed unmodified back to the server. - // They may only be valid for a particular resource or set of resources. - // - // Populated by the system. - // Read-only. - // Value must be treated as opaque by clients and . - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency - // +optional - ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,6,opt,name=resourceVersion"` - - // A sequence number representing a specific generation of the desired state. - // Populated by the system. Read-only. - // +optional - Generation int64 `json:"generation,omitempty" protobuf:"varint,7,opt,name=generation"` - - // CreationTimestamp is a timestamp representing the server time when this object was - // created. It is not guaranteed to be set in happens-before order across separate operations. - // Clients may not set this value. It is represented in RFC3339 form and is in UTC. - // - // Populated by the system. - // Read-only. - // Null for lists. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - CreationTimestamp metav1.Time `json:"creationTimestamp,omitempty" protobuf:"bytes,8,opt,name=creationTimestamp"` - - // DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This - // field is set by the server when a graceful deletion is requested by the user, and is not - // directly settable by a client. The resource is expected to be deleted (no longer visible - // from resource lists, and not reachable by name) after the time in this field. Once set, - // this value may not be unset or be set further into the future, although it may be shortened - // or the resource may be deleted prior to this time. For example, a user may request that - // a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination - // signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard - // termination signal (SIGKILL) to the container and after cleanup, remove the pod from the - // API. In the presence of network partitions, this object may still exist after this - // timestamp, until an administrator or automated process can determine the resource is - // fully terminated. - // If not set, graceful deletion of the object has not been requested. - // - // Populated by the system when a graceful deletion is requested. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - DeletionTimestamp *metav1.Time `json:"deletionTimestamp,omitempty" protobuf:"bytes,9,opt,name=deletionTimestamp"` - - // Number of seconds allowed for this object to gracefully terminate before - // it will be removed from the system. Only set when deletionTimestamp is also set. - // May only be shortened. - // Read-only. - // +optional - DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty" protobuf:"varint,10,opt,name=deletionGracePeriodSeconds"` - - // Map of string keys and values that can be used to organize and categorize - // (scope and select) objects. May match selectors of replication controllers - // and services. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - // +optional - Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,11,rep,name=labels"` - - // Annotations is an unstructured key value map stored with a resource that may be - // set by external tools to store and retrieve arbitrary metadata. They are not - // queryable and should be preserved when modifying objects. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ - // +optional - Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,rep,name=annotations"` - - // List of objects depended by this object. If ALL objects in the list have - // been deleted, this object will be garbage collected. If this object is managed by a controller, - // then an entry in this list will point to this controller, with the controller field set to true. - // There cannot be more than one managing controller. - // +optional - // +patchMergeKey=uid - // +patchStrategy=merge - OwnerReferences []metav1.OwnerReference `json:"ownerReferences,omitempty" patchStrategy:"merge" patchMergeKey:"uid" protobuf:"bytes,13,rep,name=ownerReferences"` - - // An initializer is a controller which enforces some system invariant at object creation time. - // This field is a list of initializers that have not yet acted on this object. If nil or empty, - // this object has been completely initialized. Otherwise, the object is considered uninitialized - // and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to - // observe uninitialized objects. - // - // When an object is created, the system will populate this list with the current set of initializers. - // Only privileged users may set or modify this list. Once it is empty, it may not be modified further - // by any user. - Initializers *metav1.Initializers `json:"initializers,omitempty" patchStrategy:"merge" protobuf:"bytes,16,rep,name=initializers"` - - // Must be empty before the object is deleted from the registry. Each entry - // is an identifier for the responsible component that will remove the entry - // from the list. If the deletionTimestamp of the object is non-nil, entries - // in this list can only be removed. - // +optional - // +patchStrategy=merge - Finalizers []string `json:"finalizers,omitempty" patchStrategy:"merge" protobuf:"bytes,14,rep,name=finalizers"` - - // The name of the cluster which the object belongs to. - // This is used to distinguish resources with same name and namespace in different clusters. - // This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. - // +optional - ClusterName string `json:"clusterName,omitempty" protobuf:"bytes,15,opt,name=clusterName"` -} - const ( // NamespaceDefault means the object is in the default namespace which is applied when not specified by clients NamespaceDefault string = "default" @@ -273,6 +70,9 @@ type VolumeSource struct { // +optional AWSElasticBlockStore *AWSElasticBlockStoreVolumeSource `json:"awsElasticBlockStore,omitempty" protobuf:"bytes,4,opt,name=awsElasticBlockStore"` // GitRepo represents a git repository at a particular revision. + // DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an + // EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir + // into the Pod's container. // +optional GitRepo *GitRepoVolumeSource `json:"gitRepo,omitempty" protobuf:"bytes,5,opt,name=gitRepo"` // Secret represents a secret that should populate this volume. @@ -405,7 +205,7 @@ type PersistentVolumeSource struct { // Cinder represents a cinder volume attached and mounted on kubelets host machine // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional - Cinder *CinderVolumeSource `json:"cinder,omitempty" protobuf:"bytes,8,opt,name=cinder"` + Cinder *CinderPersistentVolumeSource `json:"cinder,omitempty" protobuf:"bytes,8,opt,name=cinder"` // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime // +optional CephFS *CephFSPersistentVolumeSource `json:"cephfs,omitempty" protobuf:"bytes,9,opt,name=cephfs"` @@ -458,10 +258,6 @@ const ( // MountOptionAnnotation defines mount option annotation used in PVs MountOptionAnnotation = "volume.beta.kubernetes.io/mount-options" - - // AlphaStorageNodeAffinityAnnotation defines node affinity policies for a PersistentVolume. - // Value is a string of the json representation of type NodeAffinity - AlphaStorageNodeAffinityAnnotation = "volume.alpha.kubernetes.io/node-affinity" ) // +genclient @@ -935,6 +731,35 @@ type CinderVolumeSource struct { // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md // +optional ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *LocalObjectReference `json:"secretRef,omitempty" protobuf:"bytes,4,opt,name=secretRef"` +} + +// Represents a cinder volume resource in Openstack. +// A Cinder volume must exist before mounting to a container. +// The volume must also be in the same region as the kubelet. +// Cinder volumes support ownership management and SELinux relabeling. +type CinderPersistentVolumeSource struct { + // volume id used to identify the volume in cinder + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + VolumeID string `json:"volumeID" protobuf:"bytes,1,opt,name=volumeID"` + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + FSType string `json:"fsType,omitempty" protobuf:"bytes,2,opt,name=fsType"` + // Optional: Defaults to false (read/write). ReadOnly here will force + // the ReadOnly setting in VolumeMounts. + // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md + // +optional + ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` + // Optional: points to a secret object containing parameters used to connect + // to OpenStack. + // +optional + SecretRef *SecretReference `json:"secretRef,omitempty" protobuf:"bytes,4,opt,name=secretRef"` } // Represents a Ceph Filesystem mount that lasts the lifetime of a pod @@ -1179,6 +1004,10 @@ type AWSElasticBlockStoreVolumeSource struct { // Represents a volume that is populated with the contents of a git repository. // Git repo volumes do not support ownership management. // Git repo volumes support SELinux relabeling. +// +// DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an +// EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir +// into the Pod's container. type GitRepoVolumeSource struct { // Repository URL Repository string `json:"repository" protobuf:"bytes,1,opt,name=repository"` @@ -1673,6 +1502,30 @@ type ConfigMapProjection struct { Optional *bool `json:"optional,omitempty" protobuf:"varint,4,opt,name=optional"` } +// ServiceAccountTokenProjection represents a projected service account token +// volume. This projection can be used to insert a service account token into +// the pods runtime filesystem for use against APIs (Kubernetes API Server or +// otherwise). +type ServiceAccountTokenProjection struct { + // Audience is the intended audience of the token. A recipient of a token + // must identify itself with an identifier specified in the audience of the + // token, and otherwise should reject the token. The audience defaults to the + // identifier of the apiserver. + //+optional + Audience string `json:"audience,omitempty" protobuf:"bytes,1,rep,name=audience"` + // ExpirationSeconds is the requested duration of validity of the service + // account token. As the token approaches expiration, the kubelet volume + // plugin will proactively rotate the service account token. The kubelet will + // start trying to rotate the token if the token is older than 80 percent of + // its time to live or if the token is older than 24 hours.Defaults to 1 hour + // and must be at least 10 minutes. + //+optional + ExpirationSeconds *int64 `json:"expirationSeconds,omitempty" protobuf:"varint,2,opt,name=expirationSeconds"` + // Path is the path relative to the mount point of the file to project the + // token into. + Path string `json:"path" protobuf:"bytes,3,opt,name=path"` +} + // Represents a projected volume source type ProjectedVolumeSource struct { // list of volume projections @@ -1691,11 +1544,17 @@ type VolumeProjection struct { // all types below are the supported types for projection into the same volume // information about the secret data to project + // +optional Secret *SecretProjection `json:"secret,omitempty" protobuf:"bytes,1,opt,name=secret"` // information about the downwardAPI data to project + // +optional DownwardAPI *DownwardAPIProjection `json:"downwardAPI,omitempty" protobuf:"bytes,2,opt,name=downwardAPI"` // information about the configMap data to project + // +optional ConfigMap *ConfigMapProjection `json:"configMap,omitempty" protobuf:"bytes,3,opt,name=configMap"` + // information about the serviceAccountToken data to project + // +optional + ServiceAccountToken *ServiceAccountTokenProjection `json:"serviceAccountToken,omitempty" protobuf:"bytes,4,opt,name=serviceAccountToken"` } const ( @@ -1720,11 +1579,13 @@ type KeyToPath struct { Mode *int32 `json:"mode,omitempty" protobuf:"varint,3,opt,name=mode"` } -// Local represents directly-attached storage with node affinity +// Local represents directly-attached storage with node affinity (Beta feature) type LocalVolumeSource struct { - // The full path to the volume on the node - // For alpha, this path must be a directory - // Once block as a source is supported, then this path can point to a block device + // The full path to the volume on the node. + // It can be either a directory or block device (disk, partition, ...). + // Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. + // Block devices can be represented only by VolumeMode=Block, which also requires the + // BlockVolume alpha feature gate to be enabled. Path string `json:"path" protobuf:"bytes,1,opt,name=path"` } @@ -1746,7 +1607,7 @@ type CSIPersistentVolumeSource struct { // Filesystem type to mount. // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // Ex. "ext4", "xfs", "ntfs". // +optional FSType string `json:"fsType,omitempty" protobuf:"bytes,4,opt,name=fsType"` @@ -1821,7 +1682,7 @@ type VolumeMount struct { SubPath string `json:"subPath,omitempty" protobuf:"bytes,4,opt,name=subPath"` // mountPropagation determines how mounts are propagated from the host // to container and the other way around. - // When not set, MountPropagationHostToContainer is used. + // When not set, MountPropagationNone is used. // This field is beta in 1.10. // +optional MountPropagation *MountPropagationMode `json:"mountPropagation,omitempty" protobuf:"bytes,5,opt,name=mountPropagation,casttype=MountPropagationMode"` @@ -2451,12 +2312,13 @@ const ( // PodReasonUnschedulable reason in PodScheduled PodCondition means that the scheduler // can't schedule the pod right now, for example due to insufficient resources in the cluster. PodReasonUnschedulable = "Unschedulable" + // ContainersReady indicates whether all containers in the pod are ready. + ContainersReady PodConditionType = "ContainersReady" ) // PodCondition contains details for the current condition of this pod. type PodCondition struct { // Type is the type of the condition. - // Currently only Ready. // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions Type PodConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=PodConditionType"` // Status is the status of the condition. @@ -2527,10 +2389,16 @@ type NodeSelector struct { NodeSelectorTerms []NodeSelectorTerm `json:"nodeSelectorTerms" protobuf:"bytes,1,rep,name=nodeSelectorTerms"` } -// A null or empty node selector term matches no objects. +// A null or empty node selector term matches no objects. The requirements of +// them are ANDed. +// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. type NodeSelectorTerm struct { - //Required. A list of node selector requirements. The requirements are ANDed. - MatchExpressions []NodeSelectorRequirement `json:"matchExpressions" protobuf:"bytes,1,rep,name=matchExpressions"` + // A list of node selector requirements by node's labels. + // +optional + MatchExpressions []NodeSelectorRequirement `json:"matchExpressions,omitempty" protobuf:"bytes,1,rep,name=matchExpressions"` + // A list of node selector requirements by node's fields. + // +optional + MatchFields []NodeSelectorRequirement `json:"matchFields,omitempty" protobuf:"bytes,2,rep,name=matchFields"` } // A node selector requirement is a selector that contains values, a key, and an operator @@ -2563,6 +2431,27 @@ const ( NodeSelectorOpLt NodeSelectorOperator = "Lt" ) +// A topology selector term represents the result of label queries. +// A null or empty topology selector term matches no objects. +// The requirements of them are ANDed. +// It provides a subset of functionality as NodeSelectorTerm. +// This is an alpha feature and may change in the future. +type TopologySelectorTerm struct { + // A list of topology selector requirements by labels. + // +optional + MatchLabelExpressions []TopologySelectorLabelRequirement `json:"matchLabelExpressions,omitempty" protobuf:"bytes,1,rep,name=matchLabelExpressions"` +} + +// A topology selector requirement is a selector that matches given label. +// This is an alpha feature and may change in the future. +type TopologySelectorLabelRequirement struct { + // The label key that the selector applies to. + Key string `json:"key" protobuf:"bytes,1,opt,name=key"` + // An array of string values. One value must match the label to be selected. + // Each entry in Values is ORed. + Values []string `json:"values" protobuf:"bytes,2,rep,name=values"` +} + // Affinity is a group of affinity scheduling rules. type Affinity struct { // Describes node affinity scheduling rules for the pod. @@ -2795,6 +2684,12 @@ const ( TolerationOpEqual TolerationOperator = "Equal" ) +// PodReadinessGate contains the reference to a pod condition +type PodReadinessGate struct { + // ConditionType refers to a condition in the pod's condition list with matching type. + ConditionType PodConditionType `json:"conditionType" protobuf:"bytes,1,opt,name=conditionType,casttype=PodConditionType"` +} + // PodSpec is a description of a pod. type PodSpec struct { // List of volumes that can be mounted by containers belonging to the pod. @@ -2959,6 +2854,13 @@ type PodSpec struct { // configuration based on DNSPolicy. // +optional DNSConfig *PodDNSConfig `json:"dnsConfig,omitempty" protobuf:"bytes,26,opt,name=dnsConfig"` + + // If specified, all readiness gates will be evaluated for pod readiness. + // A pod is ready when all its containers are ready AND + // all conditions specified in the readiness gates have status equal to "True" + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md + // +optional + ReadinessGates []PodReadinessGate `json:"readinessGates,omitempty" protobuf:"bytes,28,opt,name=readinessGates"` } // HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the @@ -3019,6 +2921,10 @@ type PodSecurityContext struct { // If unset, the Kubelet will not modify the ownership and permissions of any volume. // +optional FSGroup *int64 `json:"fsGroup,omitempty" protobuf:"varint,5,opt,name=fsGroup"` + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // +optional + Sysctls []Sysctl `json:"sysctls,omitempty" protobuf:"bytes,7,rep,name=sysctls"` } // PodQOSClass defines the supported qos classes of Pods. @@ -3063,9 +2969,26 @@ type PodDNSConfigOption struct { } // PodStatus represents information about the status of a pod. Status may trail the actual -// state of a system. +// state of a system, especially if the node that hosts the pod cannot contact the control +// plane. type PodStatus struct { - // Current condition of the pod. + // The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. + // The conditions array, the reason and message fields, and the individual container status + // arrays contain more detail about the pod's status. + // There are five possible phase values: + // + // Pending: The pod has been accepted by the Kubernetes system, but one or more of the + // container images has not been created. This includes time before being scheduled as + // well as time spent downloading images over the network, which could take a while. + // Running: The pod has been bound to a node, and all of the containers have been created. + // At least one container is still running, or is in the process of starting or restarting. + // Succeeded: All containers in the pod have terminated in success, and will not be restarted. + // Failed: All containers in the pod have terminated, and at least one container has + // terminated in failure. The container either exited with non-zero status or was terminated + // by the system. + // Unknown: For some reason the state of the pod could not be obtained, typically due to an + // error in communicating with the host of the pod. + // // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase // +optional Phase PodPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=PodPhase"` @@ -3562,9 +3485,6 @@ type ServiceSpec struct { // The primary use case for setting this field is to use a StatefulSet's Headless Service // to propagate SRV records for its Pods without respect to their readiness for purpose // of peer discovery. - // This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints - // when that annotation is deprecated and all clients have been converted to use this - // field. // +optional PublishNotReadyAddresses bool `json:"publishNotReadyAddresses,omitempty" protobuf:"varint,13,opt,name=publishNotReadyAddresses"` // sessionAffinityConfig contains the configurations of session affinity. @@ -3610,6 +3530,7 @@ type ServicePort struct { } // +genclient +// +genclient:skipVerbs=deleteCollection // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Service is a named abstraction of software service (for example, mysql) consisting of local port @@ -3819,10 +3740,6 @@ type NodeSpec struct { // PodCIDR represents the pod IP range assigned to the node. // +optional PodCIDR string `json:"podCIDR,omitempty" protobuf:"bytes,1,opt,name=podCIDR"` - // External ID of the node assigned by some machine database (e.g. a cloud provider). - // Deprecated. - // +optional - ExternalID string `json:"externalID,omitempty" protobuf:"bytes,2,opt,name=externalID"` // ID of the node assigned by the cloud provider in the format: :// // +optional ProviderID string `json:"providerID,omitempty" protobuf:"bytes,3,opt,name=providerID"` @@ -3837,14 +3754,53 @@ type NodeSpec struct { // The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field // +optional ConfigSource *NodeConfigSource `json:"configSource,omitempty" protobuf:"bytes,6,opt,name=configSource"` -} -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + // Deprecated. Not all kubelets will set this field. Remove field after 1.13. + // see: https://issues.k8s.io/61966 + // +optional + DoNotUse_ExternalID string `json:"externalID,omitempty" protobuf:"bytes,2,opt,name=externalID"` +} // NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil. type NodeConfigSource struct { - metav1.TypeMeta `json:",inline"` - ConfigMapRef *ObjectReference `json:"configMapRef,omitempty" protobuf:"bytes,1,opt,name=configMapRef"` + // For historical context, regarding the below kind, apiVersion, and configMapRef deprecation tags: + // 1. kind/apiVersion were used by the kubelet to persist this struct to disk (they had no protobuf tags) + // 2. configMapRef and proto tag 1 were used by the API to refer to a configmap, + // but used a generic ObjectReference type that didn't really have the fields we needed + // All uses/persistence of the NodeConfigSource struct prior to 1.11 were gated by alpha feature flags, + // so there was no persisted data for these fields that needed to be migrated/handled. + + // +k8s:deprecated=kind + // +k8s:deprecated=apiVersion + // +k8s:deprecated=configMapRef,protobuf=1 + + // ConfigMap is a reference to a Node's ConfigMap + ConfigMap *ConfigMapNodeConfigSource `json:"configMap,omitempty" protobuf:"bytes,2,opt,name=configMap"` +} + +// ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node. +type ConfigMapNodeConfigSource struct { + // Namespace is the metadata.namespace of the referenced ConfigMap. + // This field is required in all cases. + Namespace string `json:"namespace" protobuf:"bytes,1,opt,name=namespace"` + + // Name is the metadata.name of the referenced ConfigMap. + // This field is required in all cases. + Name string `json:"name" protobuf:"bytes,2,opt,name=name"` + + // UID is the metadata.UID of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + UID types.UID `json:"uid,omitempty" protobuf:"bytes,3,opt,name=uid"` + + // ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. + // This field is forbidden in Node.Spec, and required in Node.Status. + // +optional + ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,4,opt,name=resourceVersion"` + + // KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure + // This field is required in all cases. + KubeletConfigKey string `json:"kubeletConfigKey" protobuf:"bytes,5,opt,name=kubeletConfigKey"` } // DaemonEndpoint contains information about a single Daemon endpoint. @@ -3894,6 +3850,53 @@ type NodeSystemInfo struct { Architecture string `json:"architecture" protobuf:"bytes,10,opt,name=architecture"` } +// NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource. +type NodeConfigStatus struct { + // Assigned reports the checkpointed config the node will try to use. + // When Node.Spec.ConfigSource is updated, the node checkpoints the associated + // config payload to local disk, along with a record indicating intended + // config. The node refers to this record to choose its config checkpoint, and + // reports this record in Assigned. Assigned only updates in the status after + // the record has been checkpointed to disk. When the Kubelet is restarted, + // it tries to make the Assigned config the Active config by loading and + // validating the checkpointed payload identified by Assigned. + // +optional + Assigned *NodeConfigSource `json:"assigned,omitempty" protobuf:"bytes,1,opt,name=assigned"` + // Active reports the checkpointed config the node is actively using. + // Active will represent either the current version of the Assigned config, + // or the current LastKnownGood config, depending on whether attempting to use the + // Assigned config results in an error. + // +optional + Active *NodeConfigSource `json:"active,omitempty" protobuf:"bytes,2,opt,name=active"` + // LastKnownGood reports the checkpointed config the node will fall back to + // when it encounters an error attempting to use the Assigned config. + // The Assigned config becomes the LastKnownGood config when the node determines + // that the Assigned config is stable and correct. + // This is currently implemented as a 10-minute soak period starting when the local + // record of Assigned config is updated. If the Assigned config is Active at the end + // of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is + // reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, + // because the local default config is always assumed good. + // You should not make assumptions about the node's method of determining config stability + // and correctness, as this may change or become configurable in the future. + // +optional + LastKnownGood *NodeConfigSource `json:"lastKnownGood,omitempty" protobuf:"bytes,3,opt,name=lastKnownGood"` + // Error describes any problems reconciling the Spec.ConfigSource to the Active config. + // Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned + // record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting + // to load or validate the Assigned config, etc. + // Errors may occur at different points while syncing config. Earlier errors (e.g. download or + // checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across + // Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in + // a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error + // by fixing the config assigned in Spec.ConfigSource. + // You can find additional information for debugging by searching the error message in the Kubelet log. + // Error is a human-readable description of the error state; machines can check whether or not Error + // is empty, but should not rely on the stability of the Error text across Kubelet versions. + // +optional + Error string `json:"error,omitempty" protobuf:"bytes,4,opt,name=error"` +} + // NodeStatus is information about the current status of a node. type NodeStatus struct { // Capacity represents the total resources of a node. @@ -3938,6 +3941,9 @@ type NodeStatus struct { // List of volumes that are attached to the node. // +optional VolumesAttached []AttachedVolume `json:"volumesAttached,omitempty" protobuf:"bytes,10,rep,name=volumesAttached"` + // Status of the config assigned to the node via the dynamic Kubelet config feature. + // +optional + Config *NodeConfigStatus `json:"config,omitempty" protobuf:"bytes,11,opt,name=config"` } type UniqueVolumeName string @@ -4025,8 +4031,6 @@ const ( NodePIDPressure NodeConditionType = "PIDPressure" // NodeNetworkUnavailable means that network for the node is not correctly configured. NodeNetworkUnavailable NodeConditionType = "NetworkUnavailable" - // NodeKubeletConfigOk indicates whether the kubelet is correctly configured - NodeKubeletConfigOk NodeConditionType = "KubeletConfigOk" ) // NodeCondition contains condition information for a node. @@ -4086,8 +4090,6 @@ const ( // Local ephemeral storage, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024) // The resource name for ResourceEphemeralStorage is alpha and it can change across releases. ResourceEphemeralStorage ResourceName = "ephemeral-storage" - // NVIDIA GPU, in devices. Alpha, might change: although fractional and allowing values >1, only one whole device per node is assigned. - ResourceNvidiaGPU ResourceName = "alpha.kubernetes.io/nvidia-gpu" ) const ( @@ -4095,6 +4097,8 @@ const ( ResourceDefaultNamespacePrefix = "kubernetes.io/" // Name prefix for huge page resources (alpha). ResourceHugePagesPrefix = "hugepages-" + // Name prefix for storage resource limits + ResourceAttachableVolumesPrefix = "attachable-volumes-" ) // ResourceList is a set of (resource name, quantity) pairs. @@ -4177,6 +4181,7 @@ const ( // +genclient // +genclient:nonNamespaced +// +genclient:skipVerbs=deleteCollection // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Namespace provides a scope for Names. @@ -4237,95 +4242,6 @@ type Preconditions struct { UID *types.UID `json:"uid,omitempty" protobuf:"bytes,1,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"` } -// DeletionPropagation decides if a deletion will propagate to the dependents of the object, and how the garbage collector will handle the propagation. -type DeletionPropagation string - -const ( - // Orphans the dependents. - DeletePropagationOrphan DeletionPropagation = "Orphan" - // Deletes the object from the key-value store, the garbage collector will delete the dependents in the background. - DeletePropagationBackground DeletionPropagation = "Background" - // The object exists in the key-value store until the garbage collector deletes all the dependents whose ownerReference.blockOwnerDeletion=true from the key-value store. - // API sever will put the "DeletingDependents" finalizer on the object, and sets its deletionTimestamp. - // This policy is cascading, i.e., the dependents will be deleted with Foreground. - DeletePropagationForeground DeletionPropagation = "Foreground" -) - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// DeleteOptions may be provided when deleting an API object -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -// +k8s:openapi-gen=false -type DeleteOptions struct { - metav1.TypeMeta `json:",inline"` - - // The duration in seconds before the object should be deleted. Value must be non-negative integer. - // The value zero indicates delete immediately. If this value is nil, the default grace period for the - // specified type will be used. - // Defaults to a per object value if not specified. zero means delete immediately. - // +optional - GracePeriodSeconds *int64 `json:"gracePeriodSeconds,omitempty" protobuf:"varint,1,opt,name=gracePeriodSeconds"` - - // Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be - // returned. - // +optional - Preconditions *Preconditions `json:"preconditions,omitempty" protobuf:"bytes,2,opt,name=preconditions"` - - // Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. - // Should the dependent objects be orphaned. If true/false, the "orphan" - // finalizer will be added to/removed from the object's finalizers list. - // Either this field or PropagationPolicy may be set, but not both. - // +optional - OrphanDependents *bool `json:"orphanDependents,omitempty" protobuf:"varint,3,opt,name=orphanDependents"` - - // Whether and how garbage collection will be performed. - // Either this field or OrphanDependents may be set, but not both. - // The default policy is decided by the existing finalizer set in the - // metadata.finalizers and the resource-specific default policy. - // Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - - // allow the garbage collector to delete the dependents in the background; - // 'Foreground' - a cascading policy that deletes all dependents in the - // foreground. - // +optional - PropagationPolicy *DeletionPropagation `protobuf:"bytes,4,opt,name=propagationPolicy,casttype=DeletionPropagation"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// ListOptions is the query options to a standard REST list call. -// DEPRECATED: This type has been moved to meta/v1 and will be removed soon. -// +k8s:openapi-gen=false -type ListOptions struct { - metav1.TypeMeta `json:",inline"` - - // A selector to restrict the list of returned objects by their labels. - // Defaults to everything. - // +optional - LabelSelector string `json:"labelSelector,omitempty" protobuf:"bytes,1,opt,name=labelSelector"` - // A selector to restrict the list of returned objects by their fields. - // Defaults to everything. - // +optional - FieldSelector string `json:"fieldSelector,omitempty" protobuf:"bytes,2,opt,name=fieldSelector"` - // If true, partially initialized resources are included in the response. - // +optional - IncludeUninitialized bool `json:"includeUninitialized,omitempty" protobuf:"varint,6,opt,name=includeUninitialized"` - // Watch for changes to the described resources and return them as a stream of - // add, update, and remove notifications. Specify resourceVersion. - // +optional - Watch bool `json:"watch,omitempty" protobuf:"varint,3,opt,name=watch"` - // When specified with a watch call, shows changes that occur after that particular version of a resource. - // Defaults to changes from the beginning of history. - // When specified for list: - // - if unset, then the result is returned from remote storage based on quorum-read flag; - // - if it's 0, then we simply return what we currently have in cache, no guarantee; - // - if set to non zero, then the result is at least as fresh as given rv. - // +optional - ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,4,opt,name=resourceVersion"` - // Timeout for the list/watch call. - // +optional - TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty" protobuf:"varint,5,opt,name=timeoutSeconds"` -} - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // PodLogOptions is the query options for a Pod's logs REST call. @@ -4810,11 +4726,13 @@ const ( ResourceQuotaScopeBestEffort ResourceQuotaScope = "BestEffort" // Match all pod objects that do not have best effort quality of service ResourceQuotaScopeNotBestEffort ResourceQuotaScope = "NotBestEffort" + // Match all pod objects that have priority class mentioned + ResourceQuotaScopePriorityClass ResourceQuotaScope = "PriorityClass" ) // ResourceQuotaSpec defines the desired hard limits to enforce for Quota. type ResourceQuotaSpec struct { - // Hard is the set of desired hard limits for each named resource. + // hard is the set of desired hard limits for each named resource. // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ // +optional Hard ResourceList `json:"hard,omitempty" protobuf:"bytes,1,rep,name=hard,casttype=ResourceList,castkey=ResourceName"` @@ -4822,8 +4740,48 @@ type ResourceQuotaSpec struct { // If not specified, the quota matches all objects. // +optional Scopes []ResourceQuotaScope `json:"scopes,omitempty" protobuf:"bytes,2,rep,name=scopes,casttype=ResourceQuotaScope"` + // scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota + // but expressed using ScopeSelectorOperator in combination with possible values. + // For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched. + // +optional + ScopeSelector *ScopeSelector `json:"scopeSelector,omitempty" protobuf:"bytes,3,opt,name=scopeSelector"` +} + +// A scope selector represents the AND of the selectors represented +// by the scoped-resource selector requirements. +type ScopeSelector struct { + // A list of scope selector requirements by scope of the resources. + // +optional + MatchExpressions []ScopedResourceSelectorRequirement `json:"matchExpressions,omitempty" protobuf:"bytes,1,rep,name=matchExpressions"` } +// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator +// that relates the scope name and values. +type ScopedResourceSelectorRequirement struct { + // The name of the scope that the selector applies to. + ScopeName ResourceQuotaScope `json:"scopeName" protobuf:"bytes,1,opt,name=scopeName"` + // Represents a scope's relationship to a set of values. + // Valid operators are In, NotIn, Exists, DoesNotExist. + Operator ScopeSelectorOperator `json:"operator" protobuf:"bytes,2,opt,name=operator,casttype=ScopedResourceSelectorOperator"` + // An array of string values. If the operator is In or NotIn, + // the values array must be non-empty. If the operator is Exists or DoesNotExist, + // the values array must be empty. + // This array is replaced during a strategic merge patch. + // +optional + Values []string `json:"values,omitempty" protobuf:"bytes,3,rep,name=values"` +} + +// A scope selector operator is the set of operators that can be used in +// a scope selector requirement. +type ScopeSelectorOperator string + +const ( + ScopeSelectorOpIn ScopeSelectorOperator = "In" + ScopeSelectorOpNotIn ScopeSelectorOperator = "NotIn" + ScopeSelectorOpExists ScopeSelectorOperator = "Exists" + ScopeSelectorOpDoesNotExist ScopeSelectorOperator = "DoesNotExist" +) + // ResourceQuotaStatus defines the enforced hard limits and observed use. type ResourceQuotaStatus struct { // Hard is the set of enforced hard limits for each named resource. @@ -5251,9 +5209,9 @@ const ( // Sysctl defines a kernel parameter to be set type Sysctl struct { // Name of a property to set - Name string `protobuf:"bytes,1,opt,name=name"` + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` // Value of a property to set - Value string `protobuf:"bytes,2,opt,name=value"` + Value string `json:"value" protobuf:"bytes,2,opt,name=value"` } // NodeResources is an object for conveying resource information about a node. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index 7b41f018a..59f1d1e7d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AWSElasticBlockStoreVolumeSource = map[string]string{ "": "Represents a Persistent Disk resource in AWS.\n\nAn AWS EBS disk must exist before mounting to a container. The disk must also be in the same AWS zone as the kubelet. An AWS EBS disk can only be mounted as read/write once. AWS EBS volumes support ownership management and SELinux relabeling.", "volumeID": "Unique ID of the persistent disk resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", @@ -121,7 +121,7 @@ var map_CSIPersistentVolumeSource = map[string]string{ "driver": "Driver is the name of the driver to use for this volume. Required.", "volumeHandle": "VolumeHandle is the unique volume name returned by the CSI volume plugin’s CreateVolume to refer to the volume on all subsequent calls. Required.", "readOnly": "Optional: The value to pass to ControllerPublishVolumeRequest. Defaults to false (read/write).", - "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\".", "volumeAttributes": "Attributes of the volume to publish.", "controllerPublishSecretRef": "ControllerPublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI ControllerPublishVolume and ControllerUnpublishVolume calls. This field is optional, and may be empty if no secret is required. If the secret object contains more than one secret, all secrets are passed.", "nodeStageSecretRef": "NodeStageSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodeStageVolume and NodeStageVolume and NodeUnstageVolume calls. This field is optional, and may be empty if no secret is required. If the secret object contains more than one secret, all secrets are passed.", @@ -170,11 +170,24 @@ func (CephFSVolumeSource) SwaggerDoc() map[string]string { return map_CephFSVolumeSource } +var map_CinderPersistentVolumeSource = map[string]string{ + "": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "volumeID": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "readOnly": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "secretRef": "Optional: points to a secret object containing parameters used to connect to OpenStack.", +} + +func (CinderPersistentVolumeSource) SwaggerDoc() map[string]string { + return map_CinderPersistentVolumeSource +} + var map_CinderVolumeSource = map[string]string{ - "": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", - "volumeID": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - "readOnly": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.", + "volumeID": "volume id used to identify the volume in cinder More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "readOnly": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", + "secretRef": "Optional: points to a secret object containing parameters used to connect to OpenStack.", } func (CinderVolumeSource) SwaggerDoc() map[string]string { @@ -262,6 +275,19 @@ func (ConfigMapList) SwaggerDoc() map[string]string { return map_ConfigMapList } +var map_ConfigMapNodeConfigSource = map[string]string{ + "": "ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.", + "namespace": "Namespace is the metadata.namespace of the referenced ConfigMap. This field is required in all cases.", + "name": "Name is the metadata.name of the referenced ConfigMap. This field is required in all cases.", + "uid": "UID is the metadata.UID of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status.", + "resourceVersion": "ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. This field is forbidden in Node.Spec, and required in Node.Status.", + "kubeletConfigKey": "KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure This field is required in all cases.", +} + +func (ConfigMapNodeConfigSource) SwaggerDoc() map[string]string { + return map_ConfigMapNodeConfigSource +} + var map_ConfigMapProjection = map[string]string{ "": "Adapts a ConfigMap into a projected volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a projected volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. Note that this is identical to a configmap volume source without the default mode.", "items": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", @@ -405,18 +431,6 @@ func (DaemonEndpoint) SwaggerDoc() map[string]string { return map_DaemonEndpoint } -var map_DeleteOptions = map[string]string{ - "": "DeleteOptions may be provided when deleting an API object DEPRECATED: This type has been moved to meta/v1 and will be removed soon.", - "gracePeriodSeconds": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", - "preconditions": "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned.", - "orphanDependents": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", - "PropagationPolicy": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", -} - -func (DeleteOptions) SwaggerDoc() map[string]string { - return map_DeleteOptions -} - var map_DownwardAPIProjection = map[string]string{ "": "Represents downward API info for projecting into a projected volume. Note that this is identical to a downwardAPI volume source without the default mode.", "items": "Items is a list of DownwardAPIVolume file", @@ -671,7 +685,7 @@ func (GCEPersistentDiskVolumeSource) SwaggerDoc() map[string]string { } var map_GitRepoVolumeSource = map[string]string{ - "": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.", + "": "Represents a volume that is populated with the contents of a git repository. Git repo volumes do not support ownership management. Git repo volumes support SELinux relabeling.\n\nDEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "repository": "Repository URL", "revision": "Commit hash for the specified revision.", "directory": "Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name.", @@ -848,20 +862,6 @@ func (LimitRangeSpec) SwaggerDoc() map[string]string { return map_LimitRangeSpec } -var map_ListOptions = map[string]string{ - "": "ListOptions is the query options to a standard REST list call. DEPRECATED: This type has been moved to meta/v1 and will be removed soon.", - "labelSelector": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", - "fieldSelector": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", - "includeUninitialized": "If true, partially initialized resources are included in the response.", - "watch": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", - "resourceVersion": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", - "timeoutSeconds": "Timeout for the list/watch call.", -} - -func (ListOptions) SwaggerDoc() map[string]string { - return map_ListOptions -} - var map_LoadBalancerIngress = map[string]string{ "": "LoadBalancerIngress represents the status of a load-balancer ingress point: traffic intended for the service should be sent to an ingress point.", "ip": "IP is set for load-balancer ingress points that are IP based (typically GCE or OpenStack load-balancers)", @@ -891,8 +891,8 @@ func (LocalObjectReference) SwaggerDoc() map[string]string { } var map_LocalVolumeSource = map[string]string{ - "": "Local represents directly-attached storage with node affinity", - "path": "The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device", + "": "Local represents directly-attached storage with node affinity (Beta feature)", + "path": "The full path to the volume on the node. It can be either a directory or block device (disk, partition, ...). Directories can be represented only by PersistentVolume with VolumeMode=Filesystem. Block devices can be represented only by VolumeMode=Block, which also requires the BlockVolume alpha feature gate to be enabled.", } func (LocalVolumeSource) SwaggerDoc() map[string]string { @@ -995,13 +995,26 @@ func (NodeCondition) SwaggerDoc() map[string]string { } var map_NodeConfigSource = map[string]string{ - "": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.", + "": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.", + "configMap": "ConfigMap is a reference to a Node's ConfigMap", } func (NodeConfigSource) SwaggerDoc() map[string]string { return map_NodeConfigSource } +var map_NodeConfigStatus = map[string]string{ + "": "NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource.", + "assigned": "Assigned reports the checkpointed config the node will try to use. When Node.Spec.ConfigSource is updated, the node checkpoints the associated config payload to local disk, along with a record indicating intended config. The node refers to this record to choose its config checkpoint, and reports this record in Assigned. Assigned only updates in the status after the record has been checkpointed to disk. When the Kubelet is restarted, it tries to make the Assigned config the Active config by loading and validating the checkpointed payload identified by Assigned.", + "active": "Active reports the checkpointed config the node is actively using. Active will represent either the current version of the Assigned config, or the current LastKnownGood config, depending on whether attempting to use the Assigned config results in an error.", + "lastKnownGood": "LastKnownGood reports the checkpointed config the node will fall back to when it encounters an error attempting to use the Assigned config. The Assigned config becomes the LastKnownGood config when the node determines that the Assigned config is stable and correct. This is currently implemented as a 10-minute soak period starting when the local record of Assigned config is updated. If the Assigned config is Active at the end of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, because the local default config is always assumed good. You should not make assumptions about the node's method of determining config stability and correctness, as this may change or become configurable in the future.", + "error": "Error describes any problems reconciling the Spec.ConfigSource to the Active config. Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting to load or validate the Assigned config, etc. Errors may occur at different points while syncing config. Earlier errors (e.g. download or checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error by fixing the config assigned in Spec.ConfigSource. You can find additional information for debugging by searching the error message in the Kubelet log. Error is a human-readable description of the error state; machines can check whether or not Error is empty, but should not rely on the stability of the Error text across Kubelet versions.", +} + +func (NodeConfigStatus) SwaggerDoc() map[string]string { + return map_NodeConfigStatus +} + var map_NodeDaemonEndpoints = map[string]string{ "": "NodeDaemonEndpoints lists ports opened by daemons running on the Node.", "kubeletEndpoint": "Endpoint on which Kubelet is listening.", @@ -1060,8 +1073,9 @@ func (NodeSelectorRequirement) SwaggerDoc() map[string]string { } var map_NodeSelectorTerm = map[string]string{ - "": "A null or empty node selector term matches no objects.", - "matchExpressions": "Required. A list of node selector requirements. The requirements are ANDed.", + "": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.", + "matchExpressions": "A list of node selector requirements by node's labels.", + "matchFields": "A list of node selector requirements by node's fields.", } func (NodeSelectorTerm) SwaggerDoc() map[string]string { @@ -1071,11 +1085,11 @@ func (NodeSelectorTerm) SwaggerDoc() map[string]string { var map_NodeSpec = map[string]string{ "": "NodeSpec describes the attributes that a node is created with.", "podCIDR": "PodCIDR represents the pod IP range assigned to the node.", - "externalID": "External ID of the node assigned by some machine database (e.g. a cloud provider). Deprecated.", "providerID": "ID of the node assigned by the cloud provider in the format: ://", "unschedulable": "Unschedulable controls node schedulability of new pods. By default, node is schedulable. More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration", "taints": "If specified, the node's taints.", "configSource": "If specified, the source to get node configuration from The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field", + "externalID": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966", } func (NodeSpec) SwaggerDoc() map[string]string { @@ -1094,6 +1108,7 @@ var map_NodeStatus = map[string]string{ "images": "List of container images on this node", "volumesInUse": "List of attachable volumes in use (mounted) by the node.", "volumesAttached": "List of volumes that are attached to the node.", + "config": "Status of the config assigned to the node via the dynamic Kubelet config feature.", } func (NodeStatus) SwaggerDoc() map[string]string { @@ -1128,30 +1143,6 @@ func (ObjectFieldSelector) SwaggerDoc() map[string]string { return map_ObjectFieldSelector } -var map_ObjectMeta = map[string]string{ - "": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create. DEPRECATED: Use k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta instead - this type will be removed soon.", - "name": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", - "generateName": "GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.\n\nIf this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).\n\nApplied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency", - "namespace": "Namespace defines the space within each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", - "selfLink": "SelfLink is a URL representing this object. Populated by the system. Read-only.", - "uid": "UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.\n\nPopulated by the system. Read-only. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids", - "resourceVersion": "An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.\n\nPopulated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency", - "generation": "A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.", - "creationTimestamp": "CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "deletionTimestamp": "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field. Once set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "deletionGracePeriodSeconds": "Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.", - "labels": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/", - "annotations": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/", - "ownerReferences": "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.", - "initializers": "An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to observe uninitialized objects.\n\nWhen an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user.", - "finalizers": "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed.", - "clusterName": "The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.", -} - -func (ObjectMeta) SwaggerDoc() map[string]string { - return map_ObjectMeta -} - var map_ObjectReference = map[string]string{ "": "ObjectReference contains enough information to let you inspect or modify the referred object.", "kind": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", @@ -1381,7 +1372,7 @@ func (PodAttachOptions) SwaggerDoc() map[string]string { var map_PodCondition = map[string]string{ "": "PodCondition contains details for the current condition of this pod.", - "type": "Type is the type of the condition. Currently only Ready. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", + "type": "Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "status": "Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "lastProbeTime": "Last time we probed the condition.", "lastTransitionTime": "Last time the condition transitioned from one status to another.", @@ -1471,6 +1462,15 @@ func (PodProxyOptions) SwaggerDoc() map[string]string { return map_PodProxyOptions } +var map_PodReadinessGate = map[string]string{ + "": "PodReadinessGate contains the reference to a pod condition", + "conditionType": "ConditionType refers to a condition in the pod's condition list with matching type.", +} + +func (PodReadinessGate) SwaggerDoc() map[string]string { + return map_PodReadinessGate +} + var map_PodSecurityContext = map[string]string{ "": "PodSecurityContext holds pod-level security attributes and common container settings. Some fields are also present in container.securityContext. Field values of container.securityContext take precedence over field values of PodSecurityContext.", "seLinuxOptions": "The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.", @@ -1479,6 +1479,7 @@ var map_PodSecurityContext = map[string]string{ "runAsNonRoot": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", "supplementalGroups": "A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container.", "fsGroup": "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod:\n\n1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw ", + "sysctls": "Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.", } func (PodSecurityContext) SwaggerDoc() map[string]string { @@ -1523,6 +1524,7 @@ var map_PodSpec = map[string]string{ "priorityClassName": "If specified, indicates the pod's priority. \"system-node-critical\" and \"system-cluster-critical\" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.", "priority": "The priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.", "dnsConfig": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.", + "readinessGates": "If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md", } func (PodSpec) SwaggerDoc() map[string]string { @@ -1530,8 +1532,8 @@ func (PodSpec) SwaggerDoc() map[string]string { } var map_PodStatus = map[string]string{ - "": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system.", - "phase": "Current condition of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", + "": "PodStatus represents information about the status of a pod. Status may trail the actual state of a system, especially if the node that hosts the pod cannot contact the control plane.", + "phase": "The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod's status. There are five possible phase values:\n\nPending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.\n\nMore info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase", "conditions": "Current service state of pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions", "message": "A human readable message indicating details about why the pod is in this condition.", "reason": "A brief CamelCase message indicating details about why the pod is in this state. e.g. 'Evicted'", @@ -1802,9 +1804,10 @@ func (ResourceQuotaList) SwaggerDoc() map[string]string { } var map_ResourceQuotaSpec = map[string]string{ - "": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", - "hard": "Hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", - "scopes": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", + "": "ResourceQuotaSpec defines the desired hard limits to enforce for Quota.", + "hard": "hard is the set of desired hard limits for each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/", + "scopes": "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", + "scopeSelector": "scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota but expressed using ScopeSelectorOperator in combination with possible values. For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched.", } func (ResourceQuotaSpec) SwaggerDoc() map[string]string { @@ -1879,6 +1882,26 @@ func (ScaleIOVolumeSource) SwaggerDoc() map[string]string { return map_ScaleIOVolumeSource } +var map_ScopeSelector = map[string]string{ + "": "A scope selector represents the AND of the selectors represented by the scoped-resource selector requirements.", + "matchExpressions": "A list of scope selector requirements by scope of the resources.", +} + +func (ScopeSelector) SwaggerDoc() map[string]string { + return map_ScopeSelector +} + +var map_ScopedResourceSelectorRequirement = map[string]string{ + "": "A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.", + "scopeName": "The name of the scope that the selector applies to.", + "operator": "Represents a scope's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist.", + "values": "An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", +} + +func (ScopedResourceSelectorRequirement) SwaggerDoc() map[string]string { + return map_ScopedResourceSelectorRequirement +} + var map_Secret = map[string]string{ "": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -2010,6 +2033,17 @@ func (ServiceAccountList) SwaggerDoc() map[string]string { return map_ServiceAccountList } +var map_ServiceAccountTokenProjection = map[string]string{ + "": "ServiceAccountTokenProjection represents a projected service account token volume. This projection can be used to insert a service account token into the pods runtime filesystem for use against APIs (Kubernetes API Server or otherwise).", + "audience": "Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver.", + "expirationSeconds": "ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes.", + "path": "Path is the path relative to the mount point of the file to project the token into.", +} + +func (ServiceAccountTokenProjection) SwaggerDoc() map[string]string { + return map_ServiceAccountTokenProjection +} + var map_ServiceList = map[string]string{ "": "ServiceList holds a list of services.", "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", @@ -2055,7 +2089,7 @@ var map_ServiceSpec = map[string]string{ "externalName": "externalName is the external reference that kubedns or equivalent will return as a CNAME record for this service. No proxying will be involved. Must be a valid RFC-1123 hostname (https://tools.ietf.org/html/rfc1123) and requires Type to be ExternalName.", "externalTrafficPolicy": "externalTrafficPolicy denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints. \"Local\" preserves the client source IP and avoids a second hop for LoadBalancer and Nodeport type services, but risks potentially imbalanced traffic spreading. \"Cluster\" obscures the client source IP and may cause a second hop to another node, but should have good overall load-spreading.", "healthCheckNodePort": "healthCheckNodePort specifies the healthcheck nodePort for the service. If not specified, HealthCheckNodePort is created by the service api backend with the allocated nodePort. Will use user-specified nodePort value if specified by the client. Only effects when Type is set to LoadBalancer and ExternalTrafficPolicy is set to Local.", - "publishNotReadyAddresses": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery. This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints when that annotation is deprecated and all clients have been converted to use this field.", + "publishNotReadyAddresses": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery.", "sessionAffinityConfig": "sessionAffinityConfig contains the configurations of session affinity.", } @@ -2109,8 +2143,8 @@ func (StorageOSVolumeSource) SwaggerDoc() map[string]string { var map_Sysctl = map[string]string{ "": "Sysctl defines a kernel parameter to be set", - "Name": "Name of a property to set", - "Value": "Value of a property to set", + "name": "Name of a property to set", + "value": "Value of a property to set", } func (Sysctl) SwaggerDoc() map[string]string { @@ -2152,6 +2186,25 @@ func (Toleration) SwaggerDoc() map[string]string { return map_Toleration } +var map_TopologySelectorLabelRequirement = map[string]string{ + "": "A topology selector requirement is a selector that matches given label. This is an alpha feature and may change in the future.", + "key": "The label key that the selector applies to.", + "values": "An array of string values. One value must match the label to be selected. Each entry in Values is ORed.", +} + +func (TopologySelectorLabelRequirement) SwaggerDoc() map[string]string { + return map_TopologySelectorLabelRequirement +} + +var map_TopologySelectorTerm = map[string]string{ + "": "A topology selector term represents the result of label queries. A null or empty topology selector term matches no objects. The requirements of them are ANDed. It provides a subset of functionality as NodeSelectorTerm. This is an alpha feature and may change in the future.", + "matchLabelExpressions": "A list of topology selector requirements by labels.", +} + +func (TopologySelectorTerm) SwaggerDoc() map[string]string { + return map_TopologySelectorTerm +} + var map_Volume = map[string]string{ "": "Volume represents a named volume in a pod that may be accessed by any container in the pod.", "name": "Volume's name. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", @@ -2177,7 +2230,7 @@ var map_VolumeMount = map[string]string{ "readOnly": "Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false.", "mountPath": "Path within the container at which the volume should be mounted. Must not contain ':'.", "subPath": "Path within the volume from which the container's volume should be mounted. Defaults to \"\" (volume's root).", - "mountPropagation": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationHostToContainer is used. This field is beta in 1.10.", + "mountPropagation": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.", } func (VolumeMount) SwaggerDoc() map[string]string { @@ -2194,10 +2247,11 @@ func (VolumeNodeAffinity) SwaggerDoc() map[string]string { } var map_VolumeProjection = map[string]string{ - "": "Projection that may be projected along with other supported volume types", - "secret": "information about the secret data to project", - "downwardAPI": "information about the downwardAPI data to project", - "configMap": "information about the configMap data to project", + "": "Projection that may be projected along with other supported volume types", + "secret": "information about the secret data to project", + "downwardAPI": "information about the downwardAPI data to project", + "configMap": "information about the configMap data to project", + "serviceAccountToken": "information about the serviceAccountToken data to project", } func (VolumeProjection) SwaggerDoc() map[string]string { @@ -2210,7 +2264,7 @@ var map_VolumeSource = map[string]string{ "emptyDir": "EmptyDir represents a temporary directory that shares a pod's lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir", "gcePersistentDisk": "GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk", "awsElasticBlockStore": "AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore", - "gitRepo": "GitRepo represents a git repository at a particular revision.", + "gitRepo": "GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", "secret": "Secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret", "nfs": "NFS represents an NFS mount on the host that shares a pod's lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs", "iscsi": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://releases.k8s.io/HEAD/examples/volumes/iscsi/README.md", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go index ebdcb890d..0501bbcb5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -380,9 +380,43 @@ func (in *CephFSVolumeSource) DeepCopy() *CephFSVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CinderPersistentVolumeSource) DeepCopyInto(out *CinderPersistentVolumeSource) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(SecretReference) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CinderPersistentVolumeSource. +func (in *CinderPersistentVolumeSource) DeepCopy() *CinderPersistentVolumeSource { + if in == nil { + return nil + } + out := new(CinderPersistentVolumeSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CinderVolumeSource) DeepCopyInto(out *CinderVolumeSource) { *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + if *in == nil { + *out = nil + } else { + *out = new(LocalObjectReference) + **out = **in + } + } return } @@ -631,6 +665,22 @@ func (in *ConfigMapList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigMapNodeConfigSource) DeepCopyInto(out *ConfigMapNodeConfigSource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapNodeConfigSource. +func (in *ConfigMapNodeConfigSource) DeepCopy() *ConfigMapNodeConfigSource { + if in == nil { + return nil + } + out := new(ConfigMapNodeConfigSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConfigMapProjection) DeepCopyInto(out *ConfigMapProjection) { *out = *in @@ -965,67 +1015,6 @@ func (in *DaemonEndpoint) DeepCopy() *DaemonEndpoint { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DeleteOptions) DeepCopyInto(out *DeleteOptions) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.GracePeriodSeconds != nil { - in, out := &in.GracePeriodSeconds, &out.GracePeriodSeconds - if *in == nil { - *out = nil - } else { - *out = new(int64) - **out = **in - } - } - if in.Preconditions != nil { - in, out := &in.Preconditions, &out.Preconditions - if *in == nil { - *out = nil - } else { - *out = new(Preconditions) - (*in).DeepCopyInto(*out) - } - } - if in.OrphanDependents != nil { - in, out := &in.OrphanDependents, &out.OrphanDependents - if *in == nil { - *out = nil - } else { - *out = new(bool) - **out = **in - } - } - if in.PropagationPolicy != nil { - in, out := &in.PropagationPolicy, &out.PropagationPolicy - if *in == nil { - *out = nil - } else { - *out = new(DeletionPropagation) - **out = **in - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeleteOptions. -func (in *DeleteOptions) DeepCopy() *DeleteOptions { - if in == nil { - return nil - } - out := new(DeleteOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *DeleteOptions) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DownwardAPIProjection) DeepCopyInto(out *DownwardAPIProjection) { *out = *in @@ -2141,40 +2130,6 @@ func (in *List) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ListOptions) DeepCopyInto(out *ListOptions) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.TimeoutSeconds != nil { - in, out := &in.TimeoutSeconds, &out.TimeoutSeconds - if *in == nil { - *out = nil - } else { - *out = new(int64) - **out = **in - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListOptions. -func (in *ListOptions) DeepCopy() *ListOptions { - if in == nil { - return nil - } - out := new(ListOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ListOptions) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancerIngress) DeepCopyInto(out *LoadBalancerIngress) { *out = *in @@ -2455,13 +2410,12 @@ func (in *NodeCondition) DeepCopy() *NodeCondition { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeConfigSource) DeepCopyInto(out *NodeConfigSource) { *out = *in - out.TypeMeta = in.TypeMeta - if in.ConfigMapRef != nil { - in, out := &in.ConfigMapRef, &out.ConfigMapRef + if in.ConfigMap != nil { + in, out := &in.ConfigMap, &out.ConfigMap if *in == nil { *out = nil } else { - *out = new(ObjectReference) + *out = new(ConfigMapNodeConfigSource) **out = **in } } @@ -2478,12 +2432,47 @@ func (in *NodeConfigSource) DeepCopy() *NodeConfigSource { return out } -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NodeConfigSource) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeConfigStatus) DeepCopyInto(out *NodeConfigStatus) { + *out = *in + if in.Assigned != nil { + in, out := &in.Assigned, &out.Assigned + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigSource) + (*in).DeepCopyInto(*out) + } } - return nil + if in.Active != nil { + in, out := &in.Active, &out.Active + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigSource) + (*in).DeepCopyInto(*out) + } + } + if in.LastKnownGood != nil { + in, out := &in.LastKnownGood, &out.LastKnownGood + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigSource) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeConfigStatus. +func (in *NodeConfigStatus) DeepCopy() *NodeConfigStatus { + if in == nil { + return nil + } + out := new(NodeConfigStatus) + in.DeepCopyInto(out) + return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -2638,6 +2627,13 @@ func (in *NodeSelectorTerm) DeepCopyInto(out *NodeSelectorTerm) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.MatchFields != nil { + in, out := &in.MatchFields, &out.MatchFields + *out = make([]NodeSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -2731,6 +2727,15 @@ func (in *NodeStatus) DeepCopyInto(out *NodeStatus) { *out = make([]AttachedVolume, len(*in)) copy(*out, *in) } + if in.Config != nil { + in, out := &in.Config, &out.Config + if *in == nil { + *out = nil + } else { + *out = new(NodeConfigStatus) + (*in).DeepCopyInto(*out) + } + } return } @@ -2776,75 +2781,6 @@ func (in *ObjectFieldSelector) DeepCopy() *ObjectFieldSelector { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ObjectMeta) DeepCopyInto(out *ObjectMeta) { - *out = *in - in.CreationTimestamp.DeepCopyInto(&out.CreationTimestamp) - if in.DeletionTimestamp != nil { - in, out := &in.DeletionTimestamp, &out.DeletionTimestamp - if *in == nil { - *out = nil - } else { - *out = (*in).DeepCopy() - } - } - if in.DeletionGracePeriodSeconds != nil { - in, out := &in.DeletionGracePeriodSeconds, &out.DeletionGracePeriodSeconds - if *in == nil { - *out = nil - } else { - *out = new(int64) - **out = **in - } - } - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Annotations != nil { - in, out := &in.Annotations, &out.Annotations - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.OwnerReferences != nil { - in, out := &in.OwnerReferences, &out.OwnerReferences - *out = make([]meta_v1.OwnerReference, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Initializers != nil { - in, out := &in.Initializers, &out.Initializers - if *in == nil { - *out = nil - } else { - *out = new(meta_v1.Initializers) - (*in).DeepCopyInto(*out) - } - } - if in.Finalizers != nil { - in, out := &in.Finalizers, &out.Finalizers - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectMeta. -func (in *ObjectMeta) DeepCopy() *ObjectMeta { - if in == nil { - return nil - } - out := new(ObjectMeta) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { *out = *in @@ -3180,8 +3116,8 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) { if *in == nil { *out = nil } else { - *out = new(CinderVolumeSource) - **out = **in + *out = new(CinderPersistentVolumeSource) + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { @@ -3813,6 +3749,22 @@ func (in *PodProxyOptions) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodReadinessGate) DeepCopyInto(out *PodReadinessGate) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodReadinessGate. +func (in *PodReadinessGate) DeepCopy() *PodReadinessGate { + if in == nil { + return nil + } + out := new(PodReadinessGate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { *out = *in @@ -3866,6 +3818,11 @@ func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) { **out = **in } } + if in.Sysctls != nil { + in, out := &in.Sysctls, &out.Sysctls + *out = make([]Sysctl, len(*in)) + copy(*out, *in) + } return } @@ -4026,6 +3983,11 @@ func (in *PodSpec) DeepCopyInto(out *PodSpec) { (*in).DeepCopyInto(*out) } } + if in.ReadinessGates != nil { + in, out := &in.ReadinessGates, &out.ReadinessGates + *out = make([]PodReadinessGate, len(*in)) + copy(*out, *in) + } return } @@ -4678,6 +4640,15 @@ func (in *ResourceQuotaSpec) DeepCopyInto(out *ResourceQuotaSpec) { *out = make([]ResourceQuotaScope, len(*in)) copy(*out, *in) } + if in.ScopeSelector != nil { + in, out := &in.ScopeSelector, &out.ScopeSelector + if *in == nil { + *out = nil + } else { + *out = new(ScopeSelector) + (*in).DeepCopyInto(*out) + } + } return } @@ -4817,6 +4788,50 @@ func (in *ScaleIOVolumeSource) DeepCopy() *ScaleIOVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopeSelector) DeepCopyInto(out *ScopeSelector) { + *out = *in + if in.MatchExpressions != nil { + in, out := &in.MatchExpressions, &out.MatchExpressions + *out = make([]ScopedResourceSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopeSelector. +func (in *ScopeSelector) DeepCopy() *ScopeSelector { + if in == nil { + return nil + } + out := new(ScopeSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopedResourceSelectorRequirement) DeepCopyInto(out *ScopedResourceSelectorRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopedResourceSelectorRequirement. +func (in *ScopedResourceSelectorRequirement) DeepCopy() *ScopedResourceSelectorRequirement { + if in == nil { + return nil + } + out := new(ScopedResourceSelectorRequirement) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Secret) DeepCopyInto(out *Secret) { *out = *in @@ -5257,6 +5272,31 @@ func (in *ServiceAccountList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAccountTokenProjection) DeepCopyInto(out *ServiceAccountTokenProjection) { + *out = *in + if in.ExpirationSeconds != nil { + in, out := &in.ExpirationSeconds, &out.ExpirationSeconds + if *in == nil { + *out = nil + } else { + *out = new(int64) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountTokenProjection. +func (in *ServiceAccountTokenProjection) DeepCopy() *ServiceAccountTokenProjection { + if in == nil { + return nil + } + out := new(ServiceAccountTokenProjection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceList) DeepCopyInto(out *ServiceList) { *out = *in @@ -5553,6 +5593,50 @@ func (in *Toleration) DeepCopy() *Toleration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorLabelRequirement) DeepCopyInto(out *TopologySelectorLabelRequirement) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorLabelRequirement. +func (in *TopologySelectorLabelRequirement) DeepCopy() *TopologySelectorLabelRequirement { + if in == nil { + return nil + } + out := new(TopologySelectorLabelRequirement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TopologySelectorTerm) DeepCopyInto(out *TopologySelectorTerm) { + *out = *in + if in.MatchLabelExpressions != nil { + in, out := &in.MatchLabelExpressions, &out.MatchLabelExpressions + *out = make([]TopologySelectorLabelRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologySelectorTerm. +func (in *TopologySelectorTerm) DeepCopy() *TopologySelectorTerm { + if in == nil { + return nil + } + out := new(TopologySelectorTerm) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Volume) DeepCopyInto(out *Volume) { *out = *in @@ -5666,6 +5750,15 @@ func (in *VolumeProjection) DeepCopyInto(out *VolumeProjection) { (*in).DeepCopyInto(*out) } } + if in.ServiceAccountToken != nil { + in, out := &in.ServiceAccountToken, &out.ServiceAccountToken + if *in == nil { + *out = nil + } else { + *out = new(ServiceAccountTokenProjection) + (*in).DeepCopyInto(*out) + } + } return } @@ -5796,7 +5889,7 @@ func (in *VolumeSource) DeepCopyInto(out *VolumeSource) { *out = nil } else { *out = new(CinderVolumeSource) - **out = **in + (*in).DeepCopyInto(*out) } } if in.CephFS != nil { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/generated.pb.go index 9aac8420f..e24a82ab1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1251,56 +1251,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 814 bytes of a gzipped FileDescriptorProto + // 801 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcd, 0x6e, 0xdb, 0x46, - 0x10, 0x16, 0x13, 0x4b, 0xb6, 0x56, 0x49, 0x2c, 0x6f, 0x0e, 0xde, 0xb8, 0x00, 0xa5, 0x3a, 0x40, - 0x60, 0x14, 0x08, 0x59, 0xa7, 0x45, 0xdb, 0x6b, 0x18, 0xbb, 0x45, 0x02, 0xbb, 0x01, 0xd6, 0x3e, - 0x15, 0x3d, 0x64, 0x45, 0x4d, 0xe8, 0xad, 0xa5, 0x5d, 0x62, 0x77, 0x29, 0xc0, 0xb7, 0x5e, 0x0a, - 0xf4, 0xd8, 0x67, 0xe8, 0x13, 0xf4, 0x31, 0x7c, 0xcc, 0x31, 0x27, 0xa1, 0x66, 0xdf, 0xa2, 0xa7, - 0x82, 0xcb, 0x95, 0x28, 0x8b, 0x16, 0xec, 0x22, 0x37, 0x72, 0xe6, 0xfb, 0x99, 0x19, 0x0e, 0x07, - 0x45, 0xe7, 0xdf, 0xe9, 0x80, 0xcb, 0xf0, 0x3c, 0x1b, 0x80, 0x12, 0x60, 0x40, 0x87, 0x13, 0x10, - 0x43, 0xa9, 0x42, 0x97, 0x60, 0x29, 0x0f, 0x61, 0x02, 0xc2, 0xe8, 0x70, 0xb2, 0x3f, 0x00, 0xc3, - 0xf6, 0xc3, 0x04, 0x04, 0x28, 0x66, 0x60, 0x18, 0xa4, 0x4a, 0x1a, 0x89, 0x9f, 0x94, 0xd0, 0x80, - 0xa5, 0x3c, 0x28, 0xa1, 0x81, 0x83, 0xee, 0x3c, 0x4f, 0xb8, 0x39, 0xcb, 0x06, 0x41, 0x2c, 0xc7, - 0x61, 0x22, 0x13, 0x19, 0x5a, 0xc6, 0x20, 0x7b, 0x6f, 0xdf, 0xec, 0x8b, 0x7d, 0x2a, 0x95, 0x76, - 0x76, 0x17, 0x4c, 0x63, 0xa9, 0x20, 0x9c, 0xd4, 0xdc, 0x76, 0xbe, 0xae, 0x30, 0x63, 0x16, 0x9f, - 0x71, 0x01, 0xea, 0x22, 0x4c, 0xcf, 0x93, 0x22, 0xa0, 0xc3, 0x31, 0x18, 0x76, 0x13, 0x2b, 0x5c, - 0xc5, 0x52, 0x99, 0x30, 0x7c, 0x0c, 0x35, 0xc2, 0x37, 0xb7, 0x11, 0x74, 0x7c, 0x06, 0x63, 0x56, - 0xe3, 0x7d, 0xb5, 0x8a, 0x97, 0x19, 0x3e, 0x0a, 0xb9, 0x30, 0xda, 0xa8, 0x65, 0xd2, 0xee, 0x9f, - 0x6d, 0xd4, 0x3c, 0x2c, 0x26, 0x87, 0xdf, 0xa1, 0x8d, 0xa2, 0x85, 0x21, 0x33, 0x8c, 0x78, 0x7d, - 0x6f, 0xaf, 0xf3, 0xe2, 0xcb, 0xa0, 0x1a, 0xef, 0x5c, 0x31, 0x48, 0xcf, 0x93, 0x22, 0xa0, 0x83, - 0x02, 0x1d, 0x4c, 0xf6, 0x83, 0xb7, 0x83, 0x5f, 0x20, 0x36, 0xc7, 0x60, 0x58, 0x84, 0x2f, 0xa7, - 0xbd, 0x46, 0x3e, 0xed, 0xa1, 0x2a, 0x46, 0xe7, 0xaa, 0xf8, 0x1d, 0x6a, 0xdb, 0x8f, 0x74, 0xca, - 0xc7, 0x40, 0xee, 0x59, 0x8b, 0xf0, 0x6e, 0x16, 0xc7, 0x3c, 0x56, 0xb2, 0xa0, 0x45, 0x5b, 0xce, - 0xa1, 0x7d, 0x38, 0x53, 0xa2, 0x95, 0x28, 0x7e, 0x83, 0x5a, 0x1a, 0x14, 0x07, 0x4d, 0xee, 0x5b, - 0xf9, 0x67, 0xc1, 0xca, 0x05, 0x09, 0xac, 0xc0, 0x89, 0x45, 0x47, 0x28, 0x9f, 0xf6, 0x5a, 0xe5, - 0x33, 0x75, 0x0a, 0xf8, 0x18, 0x3d, 0x56, 0x90, 0x4a, 0x65, 0xb8, 0x48, 0x5e, 0x49, 0x61, 0x94, - 0x1c, 0x8d, 0x40, 0x91, 0xb5, 0xbe, 0xb7, 0xd7, 0x8e, 0x3e, 0x73, 0x65, 0x3c, 0xa6, 0x75, 0x08, - 0xbd, 0x89, 0x87, 0x7f, 0x40, 0x5b, 0xf3, 0xf0, 0x6b, 0xa1, 0x0d, 0x13, 0x31, 0x90, 0xa6, 0x15, - 0x7b, 0xe2, 0xc4, 0xb6, 0xe8, 0x32, 0x80, 0xd6, 0x39, 0xf8, 0x19, 0x6a, 0xb1, 0xd8, 0x70, 0x29, - 0x48, 0xcb, 0xb2, 0x1f, 0x39, 0x76, 0xeb, 0xa5, 0x8d, 0x52, 0x97, 0x2d, 0x70, 0x0a, 0x98, 0x96, - 0x82, 0xac, 0x5f, 0xc7, 0x51, 0x1b, 0xa5, 0x2e, 0x8b, 0x4f, 0x51, 0x5b, 0x41, 0xc2, 0xd4, 0x90, - 0x8b, 0x84, 0x6c, 0xd8, 0xb1, 0x3d, 0x5d, 0x1c, 0x5b, 0xf1, 0x37, 0x54, 0x9f, 0x99, 0xc2, 0x7b, - 0x50, 0x20, 0xe2, 0x85, 0x2f, 0x41, 0x67, 0x6c, 0x5a, 0x09, 0xe1, 0x37, 0x68, 0x5d, 0xc1, 0xa8, - 0x58, 0x34, 0xd2, 0xbe, 0xbb, 0x66, 0x27, 0x9f, 0xf6, 0xd6, 0x69, 0xc9, 0xa3, 0x33, 0x01, 0xdc, - 0x47, 0x6b, 0x42, 0x1a, 0x20, 0xc8, 0xf6, 0xf1, 0xc0, 0xf9, 0xae, 0xfd, 0x28, 0x0d, 0x50, 0x9b, - 0x29, 0x10, 0xe6, 0x22, 0x05, 0xd2, 0xb9, 0x8e, 0x38, 0xbd, 0x48, 0x81, 0xda, 0x0c, 0x06, 0xd4, - 0x1d, 0x42, 0xaa, 0x20, 0x2e, 0x14, 0x4f, 0x64, 0xa6, 0x62, 0x20, 0x0f, 0x6c, 0x61, 0xbd, 0x9b, - 0x0a, 0x2b, 0x97, 0xc3, 0xc2, 0x22, 0xe2, 0xe4, 0xba, 0x07, 0x4b, 0x02, 0xb4, 0x26, 0x89, 0x7f, - 0xf7, 0x10, 0xa9, 0x82, 0xdf, 0x73, 0xa5, 0xed, 0x62, 0x6a, 0xc3, 0xc6, 0x29, 0x79, 0x68, 0xfd, - 0xbe, 0xb8, 0xdb, 0xca, 0xdb, 0x6d, 0xef, 0x3b, 0x6b, 0x72, 0xb0, 0x42, 0x93, 0xae, 0x74, 0xc3, - 0xbf, 0x79, 0x68, 0xbb, 0x4a, 0x1e, 0xb1, 0xc5, 0x4a, 0x1e, 0xfd, 0xef, 0x4a, 0x7a, 0xae, 0x92, - 0xed, 0x83, 0x9b, 0x25, 0xe9, 0x2a, 0x2f, 0xfc, 0x12, 0x6d, 0x56, 0xa9, 0x57, 0x32, 0x13, 0x86, - 0x6c, 0xf6, 0xbd, 0xbd, 0x66, 0xb4, 0xed, 0x24, 0x37, 0x0f, 0xae, 0xa7, 0xe9, 0x32, 0x7e, 0xf7, - 0x2f, 0x0f, 0x95, 0xff, 0xfb, 0x11, 0xd7, 0x06, 0xff, 0x5c, 0x3b, 0x54, 0xc1, 0xdd, 0x1a, 0x29, - 0xd8, 0xf6, 0x4c, 0x75, 0x9d, 0xf3, 0xc6, 0x2c, 0xb2, 0x70, 0xa4, 0x0e, 0x51, 0x93, 0x1b, 0x18, - 0x6b, 0x72, 0xaf, 0x7f, 0x7f, 0xaf, 0xf3, 0xa2, 0x7f, 0xdb, 0x05, 0x89, 0x1e, 0x3a, 0xb1, 0xe6, - 0xeb, 0x82, 0x46, 0x4b, 0xf6, 0x6e, 0xee, 0xa1, 0xce, 0xc2, 0x85, 0xc1, 0x4f, 0x51, 0x33, 0xb6, - 0xbd, 0x7b, 0xb6, 0xf7, 0x39, 0xa9, 0xec, 0xb8, 0xcc, 0xe1, 0x0c, 0x75, 0x47, 0x4c, 0x9b, 0xb7, - 0x03, 0x0d, 0x6a, 0x02, 0xc3, 0x4f, 0xb9, 0x93, 0xf3, 0xa5, 0x3d, 0x5a, 0x12, 0xa4, 0x35, 0x0b, - 0xfc, 0x2d, 0x6a, 0x6a, 0xc3, 0x0c, 0xd8, 0xa3, 0xd9, 0x8e, 0x3e, 0x9f, 0xd5, 0x76, 0x52, 0x04, - 0xff, 0x9d, 0xf6, 0xba, 0x0b, 0x8d, 0xd8, 0x18, 0x2d, 0xf1, 0xd1, 0xf3, 0xcb, 0x2b, 0xbf, 0xf1, - 0xe1, 0xca, 0x6f, 0x7c, 0xbc, 0xf2, 0x1b, 0xbf, 0xe6, 0xbe, 0x77, 0x99, 0xfb, 0xde, 0x87, 0xdc, - 0xf7, 0x3e, 0xe6, 0xbe, 0xf7, 0x77, 0xee, 0x7b, 0x7f, 0xfc, 0xe3, 0x37, 0x7e, 0x5a, 0x77, 0xf3, - 0xfa, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x69, 0xa9, 0x7b, 0x6e, 0xf2, 0x07, 0x00, 0x00, + 0x10, 0x16, 0x13, 0x4b, 0xb2, 0x56, 0x49, 0x2c, 0x6f, 0x0e, 0xde, 0xb8, 0x00, 0xa5, 0x2a, 0x40, + 0x20, 0x14, 0x08, 0x59, 0x07, 0x45, 0xdb, 0x6b, 0x18, 0xb9, 0x45, 0x02, 0xbb, 0x01, 0xd6, 0x3e, + 0x15, 0x3d, 0x64, 0x45, 0x4d, 0x68, 0x56, 0xe2, 0x2e, 0xb1, 0xbb, 0x12, 0xe0, 0x5b, 0x2f, 0x05, + 0x7a, 0xec, 0x33, 0xf4, 0x09, 0xfa, 0x18, 0x3e, 0xe6, 0x98, 0x93, 0x50, 0xb3, 0x6f, 0xd1, 0x53, + 0xc1, 0xe5, 0x4a, 0x94, 0xf5, 0x83, 0xa8, 0xe8, 0x4d, 0x9c, 0xf9, 0x7e, 0x66, 0x66, 0x47, 0x83, + 0x82, 0xd1, 0xb7, 0xca, 0x8b, 0x85, 0x3f, 0x9a, 0x0c, 0x40, 0x72, 0xd0, 0xa0, 0xfc, 0x29, 0xf0, + 0xa1, 0x90, 0xbe, 0x4d, 0xb0, 0x34, 0xf6, 0x61, 0x0a, 0x5c, 0x2b, 0x7f, 0x7a, 0x32, 0x00, 0xcd, + 0x4e, 0xfc, 0x08, 0x38, 0x48, 0xa6, 0x61, 0xe8, 0xa5, 0x52, 0x68, 0x81, 0x9f, 0x14, 0x50, 0x8f, + 0xa5, 0xb1, 0x57, 0x40, 0x3d, 0x0b, 0x3d, 0x7e, 0x1e, 0xc5, 0xfa, 0x6a, 0x32, 0xf0, 0x42, 0x91, + 0xf8, 0x91, 0x88, 0x84, 0x6f, 0x18, 0x83, 0xc9, 0x7b, 0xf3, 0x65, 0x3e, 0xcc, 0xaf, 0x42, 0xe9, + 0xb8, 0xbb, 0x64, 0x1a, 0x0a, 0x09, 0xfe, 0x74, 0xcd, 0xed, 0xf8, 0xab, 0x12, 0x93, 0xb0, 0xf0, + 0x2a, 0xe6, 0x20, 0xaf, 0xfd, 0x74, 0x14, 0xe5, 0x01, 0xe5, 0x27, 0xa0, 0xd9, 0x26, 0x96, 0xbf, + 0x8d, 0x25, 0x27, 0x5c, 0xc7, 0x09, 0xac, 0x11, 0xbe, 0xfe, 0x14, 0x41, 0x85, 0x57, 0x90, 0xb0, + 0x55, 0x5e, 0xf7, 0x8f, 0x06, 0xaa, 0x9e, 0xe6, 0x43, 0xc0, 0xef, 0xd0, 0x7e, 0x5e, 0xcd, 0x90, + 0x69, 0x46, 0x9c, 0x8e, 0xd3, 0x6b, 0xbe, 0xf8, 0xd2, 0x2b, 0x27, 0xb5, 0x10, 0xf5, 0xd2, 0x51, + 0x94, 0x07, 0x94, 0x97, 0xa3, 0xbd, 0xe9, 0x89, 0xf7, 0x76, 0xf0, 0x33, 0x84, 0xfa, 0x1c, 0x34, + 0x0b, 0xf0, 0xcd, 0xac, 0x5d, 0xc9, 0x66, 0x6d, 0x54, 0xc6, 0xe8, 0x42, 0x15, 0xbf, 0x43, 0x0d, + 0x33, 0xef, 0xcb, 0x38, 0x01, 0x72, 0xcf, 0x58, 0xf8, 0xbb, 0x59, 0x9c, 0xc7, 0xa1, 0x14, 0x39, + 0x2d, 0x38, 0xb4, 0x0e, 0x8d, 0xd3, 0xb9, 0x12, 0x2d, 0x45, 0xf1, 0x1b, 0x54, 0x53, 0x20, 0x63, + 0x50, 0xe4, 0xbe, 0x91, 0x7f, 0xe6, 0x6d, 0x7d, 0x6b, 0xcf, 0x08, 0x5c, 0x18, 0x74, 0x80, 0xb2, + 0x59, 0xbb, 0x56, 0xfc, 0xa6, 0x56, 0x01, 0x9f, 0xa3, 0xc7, 0x12, 0x52, 0x21, 0x75, 0xcc, 0xa3, + 0x57, 0x82, 0x6b, 0x29, 0xc6, 0x63, 0x90, 0x64, 0xaf, 0xe3, 0xf4, 0x1a, 0xc1, 0x67, 0xb6, 0x8c, + 0xc7, 0x74, 0x1d, 0x42, 0x37, 0xf1, 0xf0, 0xf7, 0xe8, 0x70, 0x11, 0x7e, 0xcd, 0x95, 0x66, 0x3c, + 0x04, 0x52, 0x35, 0x62, 0x4f, 0xac, 0xd8, 0x21, 0x5d, 0x05, 0xd0, 0x75, 0x0e, 0x7e, 0x86, 0x6a, + 0x2c, 0xd4, 0xb1, 0xe0, 0xa4, 0x66, 0xd8, 0x8f, 0x2c, 0xbb, 0xf6, 0xd2, 0x44, 0xa9, 0xcd, 0xe6, + 0x38, 0x09, 0x4c, 0x09, 0x4e, 0xea, 0x77, 0x71, 0xd4, 0x44, 0xa9, 0xcd, 0xe2, 0x4b, 0xd4, 0x90, + 0x10, 0x31, 0x39, 0x8c, 0x79, 0x44, 0xf6, 0xcd, 0xd8, 0x9e, 0x2e, 0x8f, 0x2d, 0x5f, 0xec, 0xf2, + 0x99, 0x29, 0xbc, 0x07, 0x09, 0x3c, 0x5c, 0x7a, 0x09, 0x3a, 0x67, 0xd3, 0x52, 0x08, 0xbf, 0x41, + 0x75, 0x09, 0xe3, 0x7c, 0xd1, 0x48, 0x63, 0x77, 0xcd, 0x66, 0x36, 0x6b, 0xd7, 0x69, 0xc1, 0xa3, + 0x73, 0x01, 0xdc, 0x41, 0x7b, 0x5c, 0x68, 0x20, 0xc8, 0xf4, 0xf1, 0xc0, 0xfa, 0xee, 0xfd, 0x20, + 0x34, 0x50, 0x93, 0xc9, 0x11, 0xfa, 0x3a, 0x05, 0xd2, 0xbc, 0x8b, 0xb8, 0xbc, 0x4e, 0x81, 0x9a, + 0x0c, 0x06, 0xd4, 0x1a, 0x42, 0x2a, 0x21, 0xcc, 0x15, 0x2f, 0xc4, 0x44, 0x86, 0x40, 0x1e, 0x98, + 0xc2, 0xda, 0x9b, 0x0a, 0x2b, 0x96, 0xc3, 0xc0, 0x02, 0x62, 0xe5, 0x5a, 0xfd, 0x15, 0x01, 0xba, + 0x26, 0x89, 0x7f, 0x73, 0x10, 0x29, 0x83, 0xdf, 0xc5, 0x52, 0x99, 0xc5, 0x54, 0x9a, 0x25, 0x29, + 0x79, 0x68, 0xfc, 0xbe, 0xd8, 0x6d, 0xe5, 0xcd, 0xb6, 0x77, 0xac, 0x35, 0xe9, 0x6f, 0xd1, 0xa4, + 0x5b, 0xdd, 0xf0, 0xaf, 0x0e, 0x3a, 0x2a, 0x93, 0x67, 0x6c, 0xb9, 0x92, 0x47, 0xff, 0xb9, 0x92, + 0xb6, 0xad, 0xe4, 0xa8, 0xbf, 0x59, 0x92, 0x6e, 0xf3, 0xc2, 0x2f, 0xd1, 0x41, 0x99, 0x7a, 0x25, + 0x26, 0x5c, 0x93, 0x83, 0x8e, 0xd3, 0xab, 0x06, 0x47, 0x56, 0xf2, 0xa0, 0x7f, 0x37, 0x4d, 0x57, + 0xf1, 0xdd, 0x3f, 0x1d, 0x54, 0xfc, 0xdf, 0xcf, 0x62, 0xa5, 0xf1, 0x4f, 0x6b, 0x87, 0xca, 0xdb, + 0xad, 0x91, 0x9c, 0x6d, 0xce, 0x54, 0xcb, 0x3a, 0xef, 0xcf, 0x23, 0x4b, 0x47, 0xea, 0x14, 0x55, + 0x63, 0x0d, 0x89, 0x22, 0xf7, 0x3a, 0xf7, 0x7b, 0xcd, 0x17, 0x9d, 0x4f, 0x5d, 0x90, 0xe0, 0xa1, + 0x15, 0xab, 0xbe, 0xce, 0x69, 0xb4, 0x60, 0x77, 0x33, 0x07, 0x35, 0x97, 0x2e, 0x0c, 0x7e, 0x8a, + 0xaa, 0xa1, 0xe9, 0xdd, 0x31, 0xbd, 0x2f, 0x48, 0x45, 0xc7, 0x45, 0x0e, 0x4f, 0x50, 0x6b, 0xcc, + 0x94, 0x7e, 0x3b, 0x50, 0x20, 0xa7, 0x30, 0xfc, 0x3f, 0x77, 0x72, 0xb1, 0xb4, 0x67, 0x2b, 0x82, + 0x74, 0xcd, 0x02, 0x7f, 0x83, 0xaa, 0x4a, 0x33, 0x0d, 0xe6, 0x68, 0x36, 0x82, 0xcf, 0xe7, 0xb5, + 0x5d, 0xe4, 0xc1, 0x7f, 0x66, 0xed, 0xd6, 0x52, 0x23, 0x26, 0x46, 0x0b, 0x7c, 0xf0, 0xfc, 0xe6, + 0xd6, 0xad, 0x7c, 0xb8, 0x75, 0x2b, 0x1f, 0x6f, 0xdd, 0xca, 0x2f, 0x99, 0xeb, 0xdc, 0x64, 0xae, + 0xf3, 0x21, 0x73, 0x9d, 0x8f, 0x99, 0xeb, 0xfc, 0x95, 0xb9, 0xce, 0xef, 0x7f, 0xbb, 0x95, 0x1f, + 0xeb, 0x76, 0x5e, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x25, 0x9b, 0x14, 0x4d, 0xbd, 0x07, 0x00, + 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/generated.proto index 0637f780a..b3e565e67 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/types_swagger_doc_generated.go index 17ec3d777..a15672c19 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_Event = map[string]string{ "": "Event is a report of an event somewhere in the cluster. It generally denotes some state change in the system.", "eventTime": "Required. Time when this Event was first observed.", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/zz_generated.deepcopy.go index 546d69e7e..9652044b3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/events/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/generated.pb.go index fcb80615f..9d76a5b93 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -465,6 +465,14 @@ func (m *AllowedHostPath) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.PathPrefix))) i += copy(dAtA[i:], m.PathPrefix) + dAtA[i] = 0x10 + i++ + if m.ReadOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -2249,6 +2257,40 @@ func (m *PodSecurityPolicySpec) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + dAtA[i] = 0x9a + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + dAtA[i] = 0xa2 + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } return i, nil } @@ -2818,6 +2860,7 @@ func (m *AllowedHostPath) Size() (n int) { _ = l l = len(m.PathPrefix) n += 1 + l + sovGenerated(uint64(l)) + n += 2 return n } @@ -3457,6 +3500,18 @@ func (m *PodSecurityPolicySpec) Size() (n int) { n += 2 + l + sovGenerated(uint64(l)) } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -3677,6 +3732,7 @@ func (this *AllowedHostPath) String() string { } s := strings.Join([]string{`&AllowedHostPath{`, `PathPrefix:` + fmt.Sprintf("%v", this.PathPrefix) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, `}`, }, "") return s @@ -4189,6 +4245,8 @@ func (this *PodSecurityPolicySpec) String() string { `AllowPrivilegeEscalation:` + valueToStringGenerated(this.AllowPrivilegeEscalation) + `,`, `AllowedHostPaths:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedHostPaths), "AllowedHostPath", "AllowedHostPath", 1), `&`, ``, 1) + `,`, `AllowedFlexVolumes:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedFlexVolumes), "AllowedFlexVolume", "AllowedFlexVolume", 1), `&`, ``, 1) + `,`, + `AllowedUnsafeSysctls:` + fmt.Sprintf("%v", this.AllowedUnsafeSysctls) + `,`, + `ForbiddenSysctls:` + fmt.Sprintf("%v", this.ForbiddenSysctls) + `,`, `}`, }, "") return s @@ -4520,6 +4578,26 @@ func (m *AllowedHostPath) Unmarshal(dAtA []byte) error { } m.PathPrefix = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -10306,6 +10384,64 @@ func (m *PodSecurityPolicySpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedUnsafeSysctls", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedUnsafeSysctls = append(m.AllowedUnsafeSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ForbiddenSysctls", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ForbiddenSysctls = append(m.ForbiddenSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -12285,229 +12421,232 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 3571 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0xcd, 0x6f, 0x1c, 0x47, - 0x76, 0x57, 0xcf, 0x0c, 0x39, 0xc3, 0x47, 0xf1, 0xab, 0x28, 0x93, 0x63, 0xca, 0xe2, 0xc8, 0x6d, - 0x40, 0x91, 0x1c, 0x69, 0xc6, 0x92, 0x2d, 0x59, 0xb1, 0x10, 0x3b, 0x1c, 0x52, 0x1f, 0x74, 0xf8, - 0xa5, 0x1a, 0x52, 0x71, 0x8c, 0xc8, 0x71, 0x73, 0xa6, 0x38, 0x6c, 0xb1, 0xa7, 0xbb, 0xdd, 0x5d, - 0x4d, 0x73, 0x80, 0x20, 0xc8, 0x21, 0x08, 0x10, 0x20, 0x41, 0x92, 0x83, 0xf3, 0x71, 0x8b, 0x2f, - 0x39, 0x25, 0x48, 0x6e, 0xc9, 0xc1, 0x30, 0x10, 0xc0, 0x0b, 0x08, 0x0b, 0x2f, 0xe0, 0xdb, 0xfa, - 0x44, 0xac, 0xe9, 0xd3, 0x62, 0xff, 0x81, 0x85, 0x0e, 0x8b, 0x45, 0x55, 0x57, 0x7f, 0x77, 0x73, - 0x66, 0x68, 0x89, 0x58, 0x2c, 0xf6, 0xc6, 0xa9, 0xf7, 0xde, 0xef, 0xbd, 0x7a, 0xf5, 0xea, 0xbd, - 0xd7, 0x55, 0x45, 0xb8, 0xb7, 0x77, 0xdb, 0xae, 0xaa, 0x46, 0x6d, 0xcf, 0xd9, 0x26, 0x96, 0x4e, - 0x28, 0xb1, 0x6b, 0xfb, 0x44, 0x6f, 0x19, 0x56, 0x4d, 0x10, 0x14, 0x53, 0xad, 0x91, 0x03, 0x4a, - 0x74, 0x5b, 0x35, 0x74, 0xbb, 0xb6, 0x7f, 0x7d, 0x9b, 0x50, 0xe5, 0x7a, 0xad, 0x4d, 0x74, 0x62, - 0x29, 0x94, 0xb4, 0xaa, 0xa6, 0x65, 0x50, 0x03, 0x5d, 0x70, 0xd9, 0xab, 0x8a, 0xa9, 0x56, 0x03, - 0xf6, 0xaa, 0x60, 0x9f, 0xbb, 0xd6, 0x56, 0xe9, 0xae, 0xb3, 0x5d, 0x6d, 0x1a, 0x9d, 0x5a, 0xdb, - 0x68, 0x1b, 0x35, 0x2e, 0xb5, 0xed, 0xec, 0xf0, 0x5f, 0xfc, 0x07, 0xff, 0xcb, 0x45, 0x9b, 0x93, - 0x43, 0xca, 0x9b, 0x86, 0x45, 0x6a, 0xfb, 0x09, 0x8d, 0x73, 0x57, 0x42, 0x3c, 0xa6, 0xa1, 0xa9, - 0xcd, 0x6e, 0x96, 0x71, 0x73, 0x6f, 0x05, 0xac, 0x1d, 0xa5, 0xb9, 0xab, 0xea, 0xc4, 0xea, 0xd6, - 0xcc, 0xbd, 0x36, 0x97, 0xb5, 0x88, 0x6d, 0x38, 0x56, 0x93, 0x0c, 0x24, 0x65, 0xd7, 0x3a, 0x84, - 0x2a, 0x69, 0x66, 0xd5, 0xb2, 0xa4, 0x2c, 0x47, 0xa7, 0x6a, 0x27, 0xa9, 0xe6, 0x56, 0x2f, 0x01, - 0xbb, 0xb9, 0x4b, 0x3a, 0x4a, 0x42, 0xee, 0xcd, 0x2c, 0x39, 0x87, 0xaa, 0x5a, 0x4d, 0xd5, 0xa9, - 0x4d, 0xad, 0xb8, 0x90, 0x7c, 0x07, 0xa6, 0x16, 0x34, 0xcd, 0xf8, 0x94, 0xb4, 0xee, 0x69, 0xe4, - 0xe0, 0x91, 0xa1, 0x39, 0x1d, 0x82, 0x2e, 0xc1, 0x70, 0xcb, 0x52, 0xf7, 0x89, 0x55, 0x96, 0x2e, - 0x4a, 0x97, 0x47, 0xea, 0xe3, 0x4f, 0x0f, 0x2b, 0x67, 0x8e, 0x0e, 0x2b, 0xc3, 0x4b, 0x7c, 0x14, - 0x0b, 0xaa, 0x7c, 0x17, 0x26, 0x84, 0xf0, 0x03, 0xc3, 0xa6, 0x1b, 0x0a, 0xdd, 0x45, 0x37, 0x00, - 0x4c, 0x85, 0xee, 0x6e, 0x58, 0x64, 0x47, 0x3d, 0x10, 0xe2, 0x48, 0x88, 0xc3, 0x86, 0x4f, 0xc1, - 0x21, 0x2e, 0xf9, 0xdf, 0x24, 0x78, 0x79, 0xd1, 0xb1, 0xa9, 0xd1, 0x59, 0x25, 0xd4, 0x52, 0x9b, - 0x8b, 0x8e, 0x65, 0x11, 0x9d, 0x36, 0xa8, 0x42, 0x1d, 0x1b, 0x5d, 0x84, 0x82, 0xae, 0x74, 0x88, - 0xc0, 0x3a, 0x2b, 0xb0, 0x0a, 0x6b, 0x4a, 0x87, 0x60, 0x4e, 0x41, 0x1f, 0xc2, 0xd0, 0xbe, 0xa2, - 0x39, 0xa4, 0x9c, 0xbb, 0x28, 0x5d, 0x1e, 0xbd, 0x51, 0xad, 0x06, 0xa1, 0xe7, 0x3b, 0xa2, 0x6a, - 0xee, 0xb5, 0x79, 0x2c, 0x7a, 0xab, 0x5b, 0x7d, 0xe8, 0x28, 0x3a, 0x55, 0x69, 0xb7, 0x7e, 0x4e, - 0x40, 0x9e, 0x15, 0x7a, 0x1f, 0x31, 0x2c, 0xec, 0x42, 0xca, 0x7f, 0x09, 0x17, 0x32, 0x4d, 0x5b, - 0x51, 0x6d, 0x8a, 0x1e, 0xc3, 0x90, 0x4a, 0x49, 0xc7, 0x2e, 0x4b, 0x17, 0xf3, 0x97, 0x47, 0x6f, - 0xdc, 0xae, 0x1e, 0x1b, 0xf7, 0xd5, 0x4c, 0xb0, 0xfa, 0x98, 0x30, 0x63, 0x68, 0x99, 0xc1, 0x61, - 0x17, 0x55, 0xfe, 0x27, 0x09, 0x50, 0x58, 0x66, 0x53, 0xb1, 0xda, 0x84, 0xf6, 0xe1, 0x94, 0x3f, - 0xfd, 0x61, 0x4e, 0x99, 0x16, 0x90, 0xa3, 0xae, 0xc2, 0x88, 0x4f, 0x4c, 0x98, 0x49, 0x9a, 0xc4, - 0x9d, 0xf1, 0x28, 0xea, 0x8c, 0xeb, 0x03, 0x38, 0xc3, 0x45, 0xc9, 0xf0, 0xc2, 0x67, 0x39, 0x18, - 0x59, 0x52, 0x48, 0xc7, 0xd0, 0x1b, 0x84, 0xa2, 0x8f, 0xa1, 0xc4, 0x36, 0x5b, 0x4b, 0xa1, 0x0a, - 0x77, 0xc0, 0xe8, 0x8d, 0x37, 0x8e, 0x9b, 0x9d, 0x5d, 0x65, 0xdc, 0xd5, 0xfd, 0xeb, 0xd5, 0xf5, - 0xed, 0x27, 0xa4, 0x49, 0x57, 0x09, 0x55, 0x82, 0x98, 0x0c, 0xc6, 0xb0, 0x8f, 0x8a, 0xd6, 0xa0, - 0x60, 0x9b, 0xa4, 0x29, 0x7c, 0x77, 0xb5, 0xc7, 0x34, 0x7c, 0xcb, 0x1a, 0x26, 0x69, 0x06, 0x8b, - 0xc1, 0x7e, 0x61, 0x8e, 0x83, 0x1e, 0xc1, 0xb0, 0xcd, 0x57, 0xb9, 0x9c, 0x4f, 0xac, 0xc6, 0xf1, - 0x88, 0x6e, 0x6c, 0xf8, 0x1b, 0xd0, 0xfd, 0x8d, 0x05, 0x9a, 0xfc, 0xf3, 0x1c, 0x20, 0x9f, 0x77, - 0xd1, 0xd0, 0x5b, 0x2a, 0x55, 0x0d, 0x1d, 0xbd, 0x03, 0x05, 0xda, 0x35, 0xbd, 0xe8, 0xb8, 0xe4, - 0x19, 0xb4, 0xd9, 0x35, 0xc9, 0xb3, 0xc3, 0xca, 0x4c, 0x52, 0x82, 0x51, 0x30, 0x97, 0x41, 0x2b, - 0xbe, 0xa9, 0x39, 0x2e, 0xfd, 0x56, 0x54, 0xf5, 0xb3, 0xc3, 0x4a, 0x4a, 0x2e, 0xae, 0xfa, 0x48, - 0x51, 0x03, 0xd1, 0x3e, 0x20, 0x4d, 0xb1, 0xe9, 0xa6, 0xa5, 0xe8, 0xb6, 0xab, 0x49, 0xed, 0x10, - 0xe1, 0x84, 0xd7, 0xfb, 0x5b, 0x34, 0x26, 0x51, 0x9f, 0x13, 0x56, 0xa0, 0x95, 0x04, 0x1a, 0x4e, - 0xd1, 0xc0, 0x32, 0x98, 0x45, 0x14, 0xdb, 0xd0, 0xcb, 0x85, 0x68, 0x06, 0xc3, 0x7c, 0x14, 0x0b, - 0x2a, 0xba, 0x02, 0xc5, 0x0e, 0xb1, 0x6d, 0xa5, 0x4d, 0xca, 0x43, 0x9c, 0x71, 0x42, 0x30, 0x16, - 0x57, 0xdd, 0x61, 0xec, 0xd1, 0xe5, 0x2f, 0x24, 0x18, 0xf3, 0x3d, 0xc7, 0xa3, 0xfd, 0xcf, 0x12, - 0x71, 0x58, 0xed, 0x6f, 0x4a, 0x4c, 0x9a, 0x47, 0xe1, 0xa4, 0xd0, 0x56, 0xf2, 0x46, 0x42, 0x31, - 0xb8, 0xea, 0xed, 0xa5, 0x1c, 0xdf, 0x4b, 0x97, 0xfb, 0x0d, 0x99, 0x8c, 0x2d, 0xf4, 0xcf, 0x85, - 0x90, 0xf9, 0x2c, 0x34, 0xd1, 0x63, 0x28, 0xd9, 0x44, 0x23, 0x4d, 0x6a, 0x58, 0xc2, 0xfc, 0x37, - 0xfb, 0x34, 0x5f, 0xd9, 0x26, 0x5a, 0x43, 0x88, 0xd6, 0xcf, 0x32, 0xfb, 0xbd, 0x5f, 0xd8, 0x87, - 0x44, 0x0f, 0xa1, 0x44, 0x49, 0xc7, 0xd4, 0x14, 0xea, 0xe5, 0xa0, 0xd7, 0xc2, 0x53, 0x60, 0x91, - 0xc3, 0xc0, 0x36, 0x8c, 0xd6, 0xa6, 0x60, 0xe3, 0xdb, 0xc7, 0x77, 0x89, 0x37, 0x8a, 0x7d, 0x18, - 0xb4, 0x0f, 0xe3, 0x8e, 0xd9, 0x62, 0x9c, 0x94, 0xd5, 0xb0, 0x76, 0x57, 0x44, 0xd2, 0xad, 0x7e, - 0x7d, 0xb3, 0x15, 0x91, 0xae, 0xcf, 0x08, 0x5d, 0xe3, 0xd1, 0x71, 0x1c, 0xd3, 0x82, 0x16, 0x60, - 0xa2, 0xa3, 0xea, 0x98, 0x28, 0xad, 0x6e, 0x83, 0x34, 0x0d, 0xbd, 0x65, 0xf3, 0xb0, 0x1a, 0xaa, - 0xcf, 0x0a, 0x80, 0x89, 0xd5, 0x28, 0x19, 0xc7, 0xf9, 0xd1, 0xfb, 0x80, 0xbc, 0x69, 0xdc, 0x77, - 0x4b, 0xb0, 0x6a, 0xe8, 0x3c, 0xe6, 0xf2, 0x41, 0x70, 0x6f, 0x26, 0x38, 0x70, 0x8a, 0x14, 0x5a, - 0x81, 0x73, 0x16, 0xd9, 0x57, 0xd9, 0x1c, 0x1f, 0xa8, 0x36, 0x35, 0xac, 0xee, 0x8a, 0xda, 0x51, - 0x69, 0x79, 0x98, 0xdb, 0x54, 0x3e, 0x3a, 0xac, 0x9c, 0xc3, 0x29, 0x74, 0x9c, 0x2a, 0x25, 0xff, - 0xcb, 0x30, 0x4c, 0xc4, 0xf2, 0x0d, 0x7a, 0x04, 0x33, 0x4d, 0xb7, 0x38, 0xad, 0x39, 0x9d, 0x6d, - 0x62, 0x35, 0x9a, 0xbb, 0xa4, 0xe5, 0x68, 0xa4, 0xc5, 0x03, 0x65, 0xa8, 0x3e, 0x2f, 0x2c, 0x9e, - 0x59, 0x4c, 0xe5, 0xc2, 0x19, 0xd2, 0xcc, 0x0b, 0x3a, 0x1f, 0x5a, 0x55, 0x6d, 0xdb, 0xc7, 0xcc, - 0x71, 0x4c, 0xdf, 0x0b, 0x6b, 0x09, 0x0e, 0x9c, 0x22, 0xc5, 0x6c, 0x6c, 0x11, 0x5b, 0xb5, 0x48, - 0x2b, 0x6e, 0x63, 0x3e, 0x6a, 0xe3, 0x52, 0x2a, 0x17, 0xce, 0x90, 0x46, 0x37, 0x61, 0xd4, 0xd5, - 0xc6, 0xd7, 0x4f, 0x2c, 0xb4, 0x5f, 0x0e, 0xd7, 0x02, 0x12, 0x0e, 0xf3, 0xb1, 0xa9, 0x19, 0xdb, - 0x36, 0xb1, 0xf6, 0x49, 0x2b, 0x7b, 0x81, 0xd7, 0x13, 0x1c, 0x38, 0x45, 0x8a, 0x4d, 0xcd, 0x8d, - 0xc0, 0xc4, 0xd4, 0x86, 0xa3, 0x53, 0xdb, 0x4a, 0xe5, 0xc2, 0x19, 0xd2, 0x2c, 0x8e, 0x5d, 0x93, - 0x17, 0xf6, 0x15, 0x55, 0x53, 0xb6, 0x35, 0x52, 0x2e, 0x46, 0xe3, 0x78, 0x2d, 0x4a, 0xc6, 0x71, - 0x7e, 0x74, 0x1f, 0xa6, 0xdc, 0xa1, 0x2d, 0x5d, 0xf1, 0x41, 0x4a, 0x1c, 0xe4, 0x65, 0x01, 0x32, - 0xb5, 0x16, 0x67, 0xc0, 0x49, 0x19, 0xf4, 0x0e, 0x8c, 0x37, 0x0d, 0x4d, 0xe3, 0xf1, 0xb8, 0x68, - 0x38, 0x3a, 0x2d, 0x8f, 0x70, 0x14, 0xc4, 0xf6, 0xe3, 0x62, 0x84, 0x82, 0x63, 0x9c, 0x88, 0x00, - 0x34, 0xbd, 0x82, 0x63, 0x97, 0xa1, 0xaf, 0x5e, 0x23, 0x59, 0xf4, 0x82, 0x1e, 0xc0, 0x1f, 0xb2, - 0x71, 0x08, 0x58, 0xfe, 0xb1, 0x04, 0xb3, 0x19, 0xa9, 0x03, 0xbd, 0x17, 0x29, 0xb1, 0xbf, 0x1f, - 0x2b, 0xb1, 0xe7, 0x33, 0xc4, 0x42, 0x75, 0x56, 0x87, 0x31, 0x8b, 0xcd, 0x4a, 0x6f, 0xbb, 0x2c, - 0x22, 0x47, 0xde, 0xec, 0x31, 0x0d, 0x1c, 0x96, 0x09, 0x72, 0xfe, 0xd4, 0xd1, 0x61, 0x65, 0x2c, - 0x42, 0xc3, 0x51, 0x78, 0xf9, 0x5f, 0x73, 0x00, 0x4b, 0xc4, 0xd4, 0x8c, 0x6e, 0x87, 0xe8, 0xa7, - 0xd1, 0x43, 0xad, 0x47, 0x7a, 0xa8, 0x6b, 0xbd, 0x96, 0xc7, 0x37, 0x2d, 0xb3, 0x89, 0xfa, 0x93, - 0x58, 0x13, 0x55, 0xeb, 0x1f, 0xf2, 0xf8, 0x2e, 0xea, 0xa7, 0x79, 0x98, 0x0e, 0x98, 0x83, 0x36, - 0xea, 0x4e, 0x64, 0x8d, 0x7f, 0x2f, 0xb6, 0xc6, 0xb3, 0x29, 0x22, 0x2f, 0xac, 0x8f, 0x7a, 0xfe, - 0xfd, 0x0c, 0x7a, 0x02, 0xe3, 0xac, 0x71, 0x72, 0xc3, 0x83, 0xb7, 0x65, 0xc3, 0x03, 0xb7, 0x65, - 0x7e, 0x01, 0x5d, 0x89, 0x20, 0xe1, 0x18, 0x72, 0x46, 0x1b, 0x58, 0x7c, 0xd1, 0x6d, 0xa0, 0xfc, - 0xa5, 0x04, 0xe3, 0xc1, 0x32, 0x9d, 0x42, 0xd3, 0xb6, 0x16, 0x6d, 0xda, 0xae, 0xf4, 0x1d, 0xa2, - 0x19, 0x5d, 0xdb, 0x2f, 0x59, 0x83, 0xef, 0x33, 0xb1, 0x0d, 0xbe, 0xad, 0x34, 0xf7, 0xfa, 0xf8, - 0xfc, 0xfb, 0x4c, 0x02, 0x24, 0xaa, 0xc0, 0x82, 0xae, 0x1b, 0x54, 0x71, 0x73, 0xa5, 0x6b, 0xd6, - 0x72, 0xdf, 0x66, 0x79, 0x1a, 0xab, 0x5b, 0x09, 0xac, 0xbb, 0x3a, 0xb5, 0xba, 0xc1, 0x8a, 0x24, - 0x19, 0x70, 0x8a, 0x01, 0x48, 0x01, 0xb0, 0x04, 0xe6, 0xa6, 0x21, 0x36, 0xf2, 0xb5, 0x3e, 0x72, - 0x1e, 0x13, 0x58, 0x34, 0xf4, 0x1d, 0xb5, 0x1d, 0xa4, 0x1d, 0xec, 0x03, 0xe1, 0x10, 0xe8, 0xdc, - 0x5d, 0x98, 0xcd, 0xb0, 0x16, 0x4d, 0x42, 0x7e, 0x8f, 0x74, 0x5d, 0xb7, 0x61, 0xf6, 0x27, 0x3a, - 0x17, 0xfe, 0x4c, 0x1e, 0x11, 0x5f, 0xb8, 0xef, 0xe4, 0x6e, 0x4b, 0xf2, 0x17, 0x43, 0xe1, 0xd8, - 0xe1, 0x1d, 0xf3, 0x65, 0x28, 0x59, 0xc4, 0xd4, 0xd4, 0xa6, 0x62, 0x8b, 0x46, 0x88, 0x37, 0xbf, - 0x58, 0x8c, 0x61, 0x9f, 0x1a, 0xe9, 0xad, 0x73, 0x2f, 0xb6, 0xb7, 0xce, 0x3f, 0x9f, 0xde, 0xfa, - 0xcf, 0xa1, 0x64, 0x7b, 0x5d, 0x75, 0x81, 0x43, 0x5e, 0x1f, 0x20, 0xbf, 0x8a, 0x86, 0xda, 0x57, - 0xe0, 0xb7, 0xd2, 0x3e, 0x68, 0x5a, 0x13, 0x3d, 0x34, 0x60, 0x13, 0xfd, 0x5c, 0x1b, 0x5f, 0x96, - 0x53, 0x4d, 0xc5, 0xb1, 0x49, 0x8b, 0x27, 0xa2, 0x52, 0x90, 0x53, 0x37, 0xf8, 0x28, 0x16, 0x54, - 0xf4, 0x38, 0x12, 0xb2, 0xa5, 0x93, 0x84, 0xec, 0x78, 0x76, 0xb8, 0xa2, 0x2d, 0x98, 0x35, 0x2d, - 0xa3, 0x6d, 0x11, 0xdb, 0x5e, 0x22, 0x4a, 0x4b, 0x53, 0x75, 0xe2, 0xf9, 0xc7, 0xed, 0x88, 0xce, - 0x1f, 0x1d, 0x56, 0x66, 0x37, 0xd2, 0x59, 0x70, 0x96, 0xac, 0xfc, 0xb4, 0x00, 0x93, 0xf1, 0x0a, - 0x98, 0xd1, 0xa4, 0x4a, 0x27, 0x6a, 0x52, 0xaf, 0x86, 0x36, 0x83, 0xdb, 0xc1, 0xfb, 0xab, 0x9f, - 0xb2, 0x21, 0x16, 0x60, 0x42, 0x64, 0x03, 0x8f, 0x28, 0xda, 0x74, 0x7f, 0xf5, 0xb7, 0xa2, 0x64, - 0x1c, 0xe7, 0x67, 0xad, 0x67, 0xd0, 0x51, 0x7a, 0x20, 0x85, 0x68, 0xeb, 0xb9, 0x10, 0x67, 0xc0, - 0x49, 0x19, 0xb4, 0x0a, 0xd3, 0x8e, 0x9e, 0x84, 0x72, 0xa3, 0xf1, 0xbc, 0x80, 0x9a, 0xde, 0x4a, - 0xb2, 0xe0, 0x34, 0x39, 0xb4, 0x13, 0xe9, 0x46, 0x87, 0x79, 0x86, 0xbd, 0xd1, 0xf7, 0xde, 0xe9, - 0xbb, 0x1d, 0x45, 0x77, 0x60, 0xcc, 0xe2, 0xdf, 0x1d, 0x9e, 0xc1, 0x6e, 0xef, 0xfe, 0x92, 0x10, - 0x1b, 0xc3, 0x61, 0x22, 0x8e, 0xf2, 0xa6, 0xb4, 0xdb, 0xa5, 0x7e, 0xdb, 0x6d, 0xf9, 0xff, 0xa5, - 0x70, 0x11, 0xf2, 0x5b, 0xe0, 0x5e, 0xa7, 0x4c, 0x09, 0x89, 0x50, 0x77, 0x64, 0xa4, 0x77, 0xbf, - 0xb7, 0x06, 0xea, 0x7e, 0x83, 0xe2, 0xd9, 0xbb, 0xfd, 0xfd, 0x5c, 0x82, 0x99, 0x7b, 0x8d, 0xfb, - 0x96, 0xe1, 0x98, 0x9e, 0x39, 0xeb, 0xa6, 0xeb, 0xd7, 0xb7, 0xa1, 0x60, 0x39, 0x9a, 0x37, 0x8f, - 0xd7, 0xbc, 0x79, 0x60, 0x47, 0x63, 0xf3, 0x98, 0x8e, 0x49, 0xb9, 0x93, 0x60, 0x02, 0x68, 0x0d, - 0x86, 0x2d, 0x45, 0x6f, 0x13, 0xaf, 0xac, 0x5e, 0xea, 0x61, 0xfd, 0xf2, 0x12, 0x66, 0xec, 0xa1, - 0xe6, 0x8d, 0x4b, 0x63, 0x81, 0x22, 0xff, 0xbd, 0x04, 0x13, 0x0f, 0x36, 0x37, 0x37, 0x96, 0x75, - 0xbe, 0xa3, 0xf9, 0x79, 0xfa, 0x45, 0x28, 0x98, 0x0a, 0xdd, 0x8d, 0x57, 0x7a, 0x46, 0xc3, 0x9c, - 0x82, 0x3e, 0x80, 0x22, 0xcb, 0x24, 0x44, 0x6f, 0xf5, 0xd9, 0x6a, 0x0b, 0xf8, 0xba, 0x2b, 0x14, - 0x74, 0x88, 0x62, 0x00, 0x7b, 0x70, 0xf2, 0x1e, 0x9c, 0x0b, 0x99, 0xc3, 0xfc, 0xc1, 0x8f, 0x81, - 0x51, 0x03, 0x86, 0x98, 0x66, 0xef, 0x94, 0xb7, 0xd7, 0x61, 0x66, 0x6c, 0x4a, 0x41, 0xa7, 0xc3, - 0x7e, 0xd9, 0xd8, 0xc5, 0x92, 0x57, 0x61, 0x8c, 0x5f, 0x22, 0x18, 0x16, 0xe5, 0x6e, 0x41, 0x17, - 0x20, 0xdf, 0x51, 0x75, 0x51, 0x67, 0x47, 0x85, 0x4c, 0x9e, 0xd5, 0x08, 0x36, 0xce, 0xc9, 0xca, - 0x81, 0xc8, 0x3c, 0x01, 0x59, 0x39, 0xc0, 0x6c, 0x5c, 0xbe, 0x0f, 0x45, 0xe1, 0xee, 0x30, 0x50, - 0xfe, 0x78, 0xa0, 0x7c, 0x0a, 0xd0, 0x3a, 0x14, 0x97, 0x37, 0xea, 0x9a, 0xe1, 0x76, 0x5d, 0x4d, - 0xb5, 0x65, 0xc5, 0xd7, 0x62, 0x71, 0x79, 0x09, 0x63, 0x4e, 0x41, 0x32, 0x0c, 0x93, 0x83, 0x26, - 0x31, 0x29, 0x8f, 0x88, 0x91, 0x3a, 0xb0, 0x55, 0xbe, 0xcb, 0x47, 0xb0, 0xa0, 0xc8, 0xff, 0x90, - 0x83, 0xa2, 0x70, 0xc7, 0x29, 0x7c, 0x85, 0xad, 0x44, 0xbe, 0xc2, 0x5e, 0xef, 0x2f, 0x34, 0x32, - 0x3f, 0xc1, 0x36, 0x63, 0x9f, 0x60, 0x57, 0xfb, 0xc4, 0x3b, 0xfe, 0xfb, 0xeb, 0x7f, 0x24, 0x18, - 0x8f, 0x06, 0x25, 0xba, 0x09, 0xa3, 0xac, 0xe0, 0xa8, 0x4d, 0xb2, 0x16, 0xf4, 0xb9, 0xfe, 0x21, - 0x4c, 0x23, 0x20, 0xe1, 0x30, 0x1f, 0x6a, 0xfb, 0x62, 0x2c, 0x8e, 0xc4, 0xa4, 0xb3, 0x5d, 0xea, - 0x50, 0x55, 0xab, 0xba, 0x17, 0x63, 0xd5, 0x65, 0x9d, 0xae, 0x5b, 0x0d, 0x6a, 0xa9, 0x7a, 0x3b, - 0xa1, 0x88, 0x07, 0x65, 0x18, 0x59, 0xfe, 0x3f, 0x09, 0x46, 0x85, 0xc9, 0xa7, 0xf0, 0x55, 0xf1, - 0xc7, 0xd1, 0xaf, 0x8a, 0x4b, 0x7d, 0x6e, 0xf0, 0xf4, 0x4f, 0x8a, 0xff, 0x08, 0x4c, 0x67, 0x5b, - 0x9a, 0x45, 0xf5, 0xae, 0x61, 0xd3, 0x78, 0x54, 0xb3, 0xcd, 0x88, 0x39, 0x05, 0x39, 0x30, 0xa9, - 0xc6, 0x72, 0x80, 0x70, 0x6d, 0xad, 0x3f, 0x4b, 0x7c, 0xb1, 0x7a, 0x59, 0xc0, 0x4f, 0xc6, 0x29, - 0x38, 0xa1, 0x42, 0x26, 0x90, 0xe0, 0x42, 0x0f, 0xa1, 0xb0, 0x4b, 0xa9, 0x99, 0x72, 0x5e, 0xdd, - 0x23, 0xf3, 0x04, 0x26, 0x94, 0xf8, 0xec, 0x36, 0x37, 0x37, 0x30, 0x87, 0x92, 0x7f, 0x15, 0xf8, - 0xa3, 0xe1, 0xc6, 0xb8, 0x9f, 0x4f, 0xa5, 0x93, 0xe4, 0xd3, 0xd1, 0xb4, 0x5c, 0x8a, 0x1e, 0x40, - 0x9e, 0x6a, 0xfd, 0x7e, 0x16, 0x0a, 0xc4, 0xcd, 0x95, 0x46, 0x90, 0x90, 0x36, 0x57, 0x1a, 0x98, - 0x41, 0xa0, 0x75, 0x18, 0x62, 0xd5, 0x87, 0x6d, 0xc1, 0x7c, 0xff, 0x5b, 0x9a, 0xcd, 0x3f, 0x08, - 0x08, 0xf6, 0xcb, 0xc6, 0x2e, 0x8e, 0xfc, 0x09, 0x8c, 0x45, 0xf6, 0x29, 0xfa, 0x18, 0xce, 0x6a, - 0x86, 0xd2, 0xaa, 0x2b, 0x9a, 0xa2, 0x37, 0x89, 0x77, 0x39, 0x70, 0x29, 0xed, 0x0b, 0x63, 0x25, - 0xc4, 0x27, 0x76, 0xb9, 0x7f, 0x9d, 0x1a, 0xa6, 0xe1, 0x08, 0xa2, 0xac, 0x00, 0x04, 0x73, 0x44, - 0x15, 0x18, 0x62, 0x71, 0xe6, 0xd6, 0x93, 0x91, 0xfa, 0x08, 0xb3, 0x90, 0x85, 0x9f, 0x8d, 0xdd, - 0x71, 0x74, 0x03, 0xc0, 0x26, 0x4d, 0x8b, 0x50, 0x9e, 0x0c, 0x72, 0xd1, 0x4b, 0xe5, 0x86, 0x4f, - 0xc1, 0x21, 0x2e, 0xf9, 0x47, 0x12, 0x8c, 0xad, 0x11, 0xfa, 0xa9, 0x61, 0xed, 0x6d, 0xf0, 0xc7, - 0x00, 0xa7, 0x90, 0x6c, 0x71, 0x24, 0xd9, 0xbe, 0xd1, 0x63, 0x65, 0x22, 0xd6, 0x65, 0xa5, 0x5c, - 0xf9, 0x4b, 0x09, 0x66, 0x23, 0x9c, 0x77, 0x83, 0xad, 0xbb, 0x05, 0x43, 0xa6, 0x61, 0x51, 0xaf, - 0x10, 0x0f, 0xa4, 0x90, 0xa5, 0xb1, 0x50, 0x29, 0x66, 0x30, 0xd8, 0x45, 0x43, 0x2b, 0x90, 0xa3, - 0x86, 0x08, 0xd5, 0xc1, 0x30, 0x09, 0xb1, 0xea, 0x20, 0x30, 0x73, 0x9b, 0x06, 0xce, 0x51, 0x83, - 0x2d, 0x44, 0x39, 0xc2, 0x15, 0x4e, 0x3e, 0x2f, 0x68, 0x06, 0x18, 0x0a, 0x3b, 0x96, 0xd1, 0x39, - 0xf1, 0x1c, 0xfc, 0x85, 0xb8, 0x67, 0x19, 0x1d, 0xcc, 0xb1, 0xe4, 0xaf, 0x24, 0x98, 0x8a, 0x70, - 0x9e, 0x42, 0xe2, 0x7f, 0x18, 0x4d, 0xfc, 0x57, 0x07, 0x99, 0x48, 0x46, 0xfa, 0xff, 0x2a, 0x17, - 0x9b, 0x06, 0x9b, 0x30, 0xda, 0x81, 0x51, 0xd3, 0x68, 0x35, 0x9e, 0xc3, 0x75, 0xe0, 0x04, 0xab, - 0x9b, 0x1b, 0x01, 0x16, 0x0e, 0x03, 0xa3, 0x03, 0x98, 0xd2, 0x95, 0x0e, 0xb1, 0x4d, 0xa5, 0x49, - 0x1a, 0xcf, 0xe1, 0x80, 0xe4, 0x25, 0x7e, 0xdf, 0x10, 0x47, 0xc4, 0x49, 0x25, 0x68, 0x15, 0x8a, - 0xaa, 0xc9, 0xfb, 0x38, 0xd1, 0xbb, 0xf4, 0xac, 0xa2, 0x6e, 0xd7, 0xe7, 0xe6, 0x73, 0xf1, 0x03, - 0x7b, 0x18, 0xf2, 0x7f, 0xc6, 0xa3, 0x81, 0xc5, 0x1f, 0xba, 0x0f, 0x25, 0xfe, 0xac, 0xa6, 0x69, - 0x68, 0xde, 0xcd, 0x00, 0x5b, 0xd9, 0x0d, 0x31, 0xf6, 0xec, 0xb0, 0x72, 0x3e, 0xe5, 0xd0, 0xd7, - 0x23, 0x63, 0x5f, 0x18, 0xad, 0x41, 0xc1, 0xfc, 0x21, 0x1d, 0x0c, 0x2f, 0x72, 0xbc, 0x6d, 0xe1, - 0x38, 0xf2, 0x5f, 0xe7, 0x63, 0xe6, 0xf2, 0x52, 0xf7, 0xe4, 0xb9, 0xad, 0xba, 0xdf, 0x31, 0x65, - 0xae, 0xfc, 0x36, 0x14, 0x45, 0x85, 0x17, 0xc1, 0xfc, 0xf6, 0x20, 0xc1, 0x1c, 0xae, 0x62, 0xfe, - 0x07, 0x8b, 0x37, 0xe8, 0x01, 0xa3, 0x8f, 0x60, 0x98, 0xb8, 0x2a, 0xdc, 0xda, 0x78, 0x6b, 0x10, - 0x15, 0x41, 0x5e, 0x0d, 0x1a, 0x55, 0x31, 0x26, 0x50, 0xd1, 0x7b, 0xcc, 0x5f, 0x8c, 0x97, 0x7d, - 0x04, 0xda, 0xe5, 0x02, 0x2f, 0x57, 0x17, 0xdc, 0x69, 0xfb, 0xc3, 0xcf, 0x0e, 0x2b, 0x10, 0xfc, - 0xc4, 0x61, 0x09, 0xf9, 0x27, 0x12, 0x4c, 0x71, 0x0f, 0x35, 0x1d, 0x4b, 0xa5, 0xdd, 0x53, 0x2b, - 0x4c, 0x8f, 0x22, 0x85, 0xe9, 0xad, 0x1e, 0x6e, 0x49, 0x58, 0x98, 0x59, 0x9c, 0xbe, 0x96, 0xe0, - 0xa5, 0x04, 0xf7, 0x29, 0xe4, 0xc5, 0xad, 0x68, 0x5e, 0x7c, 0x63, 0xd0, 0x09, 0x65, 0xbd, 0x91, - 0x18, 0x4b, 0x99, 0x0e, 0xdf, 0x29, 0x37, 0x00, 0x4c, 0x4b, 0xdd, 0x57, 0x35, 0xd2, 0x16, 0x97, - 0xe0, 0xa5, 0xd0, 0xb3, 0x36, 0x9f, 0x82, 0x43, 0x5c, 0xc8, 0x86, 0x99, 0x16, 0xd9, 0x51, 0x1c, - 0x8d, 0x2e, 0xb4, 0x5a, 0x8b, 0x8a, 0xa9, 0x6c, 0xab, 0x9a, 0x4a, 0x55, 0x71, 0x5c, 0x30, 0x52, - 0xbf, 0xe3, 0x5e, 0x4e, 0xa7, 0x71, 0x3c, 0x3b, 0xac, 0x5c, 0x48, 0xbb, 0x1d, 0xf2, 0x58, 0xba, - 0x38, 0x03, 0x1a, 0x75, 0xa1, 0x6c, 0x91, 0x4f, 0x1c, 0xd5, 0x22, 0xad, 0x25, 0xcb, 0x30, 0x23, - 0x6a, 0xf3, 0x5c, 0xed, 0x1f, 0x1e, 0x1d, 0x56, 0xca, 0x38, 0x83, 0xa7, 0xb7, 0xe2, 0x4c, 0x78, - 0xf4, 0x04, 0xa6, 0x15, 0xf7, 0x35, 0x60, 0x44, 0xab, 0xbb, 0x4b, 0x6e, 0x1f, 0x1d, 0x56, 0xa6, - 0x17, 0x92, 0xe4, 0xde, 0x0a, 0xd3, 0x40, 0x51, 0x0d, 0x8a, 0xfb, 0xfc, 0xad, 0xa2, 0x5d, 0x1e, - 0xe2, 0xf8, 0xac, 0x10, 0x14, 0xdd, 0xe7, 0x8b, 0x0c, 0x73, 0xf8, 0x5e, 0x83, 0xef, 0x3e, 0x8f, - 0x8b, 0x7d, 0x50, 0xb2, 0x5e, 0x52, 0xec, 0x78, 0x7e, 0x62, 0x5c, 0x0a, 0xb2, 0xd6, 0x83, 0x80, - 0x84, 0xc3, 0x7c, 0xe8, 0x31, 0x8c, 0xec, 0x8a, 0x53, 0x09, 0xbb, 0x5c, 0xec, 0xab, 0x08, 0x47, - 0x4e, 0x31, 0xea, 0x53, 0x42, 0xc5, 0x88, 0x37, 0x6c, 0xe3, 0x00, 0x11, 0x5d, 0x81, 0x22, 0xff, - 0xb1, 0xbc, 0xc4, 0x8f, 0xe3, 0x4a, 0x41, 0x6e, 0x7b, 0xe0, 0x0e, 0x63, 0x8f, 0xee, 0xb1, 0x2e, - 0x6f, 0x2c, 0xf2, 0x63, 0xe1, 0x18, 0xeb, 0xf2, 0xc6, 0x22, 0xf6, 0xe8, 0xe8, 0x63, 0x28, 0xda, - 0x64, 0x45, 0xd5, 0x9d, 0x83, 0x32, 0xf4, 0x75, 0xa9, 0xdc, 0xb8, 0xcb, 0xb9, 0x63, 0x07, 0x63, - 0x81, 0x06, 0x41, 0xc7, 0x1e, 0x2c, 0xda, 0x85, 0x11, 0xcb, 0xd1, 0x17, 0xec, 0x2d, 0x9b, 0x58, - 0xe5, 0x51, 0xae, 0xa3, 0x57, 0x3a, 0xc7, 0x1e, 0x7f, 0x5c, 0x8b, 0xef, 0x21, 0x9f, 0x03, 0x07, - 0xe0, 0xe8, 0xef, 0x24, 0x40, 0xb6, 0x63, 0x9a, 0x1a, 0xe9, 0x10, 0x9d, 0x2a, 0x1a, 0x3f, 0x8b, - 0xb3, 0xcb, 0x67, 0xb9, 0xce, 0x3f, 0xea, 0x35, 0xaf, 0x84, 0x60, 0x5c, 0xb9, 0x7f, 0xe8, 0x9d, - 0x64, 0xc5, 0x29, 0x7a, 0x99, 0x6b, 0x77, 0x6c, 0xfe, 0x77, 0x79, 0xac, 0x2f, 0xd7, 0xa6, 0x9f, - 0x39, 0x06, 0xae, 0x15, 0x74, 0xec, 0xc1, 0xa2, 0x47, 0x30, 0x63, 0x11, 0xa5, 0xb5, 0xae, 0x6b, - 0x5d, 0x6c, 0x18, 0xf4, 0x9e, 0xaa, 0x11, 0xbb, 0x6b, 0x53, 0xd2, 0x29, 0x8f, 0xf3, 0x65, 0xf7, - 0xdf, 0x7e, 0xe0, 0x54, 0x2e, 0x9c, 0x21, 0x8d, 0x3a, 0x50, 0xf1, 0x52, 0x06, 0xdb, 0x4f, 0x7e, - 0xce, 0xba, 0x6b, 0x37, 0x15, 0xcd, 0xbd, 0x07, 0x98, 0xe0, 0x0a, 0x5e, 0x3b, 0x3a, 0xac, 0x54, - 0x96, 0x8e, 0x67, 0xc5, 0xbd, 0xb0, 0xd0, 0x07, 0x50, 0x56, 0xb2, 0xf4, 0x4c, 0x72, 0x3d, 0xaf, - 0xb0, 0x3c, 0x94, 0xa9, 0x20, 0x53, 0x1a, 0x51, 0x98, 0x54, 0xa2, 0x8f, 0x8e, 0xed, 0xf2, 0x54, - 0x5f, 0x07, 0x91, 0xb1, 0xb7, 0xca, 0xc1, 0x61, 0x44, 0x8c, 0x60, 0xe3, 0x84, 0x06, 0xf4, 0x17, - 0x80, 0x94, 0xf8, 0x3b, 0x69, 0xbb, 0x8c, 0xfa, 0x2a, 0x3f, 0x89, 0x07, 0xd6, 0x41, 0xd8, 0x25, - 0x48, 0x36, 0x4e, 0xd1, 0xc3, 0x1f, 0x6f, 0x88, 0xa3, 0xfc, 0xd3, 0x79, 0x00, 0x3b, 0xd8, 0xe3, - 0x8d, 0xc0, 0xb4, 0xe7, 0xf6, 0x78, 0x23, 0x04, 0x79, 0xfc, 0xe1, 0xe1, 0x2f, 0x72, 0x30, 0x1d, - 0x30, 0xf7, 0xfd, 0x78, 0x23, 0x45, 0xe4, 0x77, 0x8f, 0x60, 0x7b, 0x3f, 0x82, 0xfd, 0x52, 0x82, - 0xf1, 0xc0, 0x75, 0xbf, 0x79, 0x0f, 0x2a, 0x02, 0xdb, 0x32, 0x5a, 0xbc, 0xff, 0xce, 0x85, 0x27, - 0xf0, 0x5b, 0x7f, 0xab, 0xff, 0xc3, 0x5f, 0xae, 0xca, 0x5f, 0xe7, 0x61, 0x32, 0xbe, 0x1b, 0x23, - 0x97, 0xbf, 0x52, 0xcf, 0xcb, 0xdf, 0x0d, 0x38, 0xb7, 0xe3, 0x68, 0x5a, 0x97, 0xbb, 0x21, 0x74, - 0x03, 0xec, 0x5e, 0xde, 0xbc, 0x22, 0x24, 0xcf, 0xdd, 0x4b, 0xe1, 0xc1, 0xa9, 0x92, 0x19, 0x17, - 0xd9, 0xf9, 0x13, 0x5d, 0x64, 0x27, 0xee, 0x55, 0x0b, 0x03, 0xdc, 0xab, 0xa6, 0x5e, 0x4a, 0x0f, - 0x9d, 0xe0, 0x52, 0xfa, 0x24, 0xb7, 0xc8, 0x29, 0x49, 0xac, 0xe7, 0xa3, 0xc6, 0x57, 0x60, 0x4e, - 0x88, 0x51, 0x7e, 0xc1, 0xab, 0x53, 0xcb, 0xd0, 0x34, 0x62, 0x2d, 0x39, 0x9d, 0x4e, 0x57, 0x7e, - 0x17, 0xc6, 0xa3, 0x4f, 0x17, 0xdc, 0x95, 0x76, 0x5f, 0x4f, 0x88, 0x2b, 0xb4, 0xd0, 0x4a, 0xbb, - 0xe3, 0xd8, 0xe7, 0x90, 0xff, 0x46, 0x82, 0x99, 0xf4, 0x27, 0x8a, 0x48, 0x83, 0xf1, 0x8e, 0x72, - 0x10, 0x7e, 0x36, 0x2a, 0x9d, 0xf0, 0x70, 0x83, 0xdf, 0x59, 0xaf, 0x46, 0xb0, 0x70, 0x0c, 0x5b, - 0xfe, 0x5e, 0x82, 0xd9, 0x8c, 0xdb, 0xe2, 0xd3, 0xb5, 0x04, 0x7d, 0x08, 0xa5, 0x8e, 0x72, 0xd0, - 0x70, 0xac, 0x36, 0x39, 0xf1, 0x71, 0x0e, 0xcf, 0x18, 0xab, 0x02, 0x05, 0xfb, 0x78, 0xf2, 0xe7, - 0x12, 0x94, 0xb3, 0x1a, 0x6b, 0x74, 0x33, 0x72, 0xaf, 0xfd, 0x6a, 0xec, 0x5e, 0x7b, 0x2a, 0x21, - 0xf7, 0x82, 0x6e, 0xb5, 0xff, 0x4b, 0x82, 0x99, 0xf4, 0x0f, 0x0c, 0xf4, 0x66, 0xc4, 0xc2, 0x4a, - 0xcc, 0xc2, 0x89, 0x98, 0x94, 0xb0, 0xef, 0x23, 0x18, 0x17, 0x9f, 0x21, 0x02, 0x46, 0x78, 0x55, - 0x4e, 0xcb, 0x95, 0x02, 0xc2, 0x6b, 0xbb, 0xf9, 0x7a, 0x45, 0xc7, 0x70, 0x0c, 0x4d, 0xfe, 0xdb, - 0x1c, 0x0c, 0x35, 0x9a, 0x8a, 0x46, 0x4e, 0xa1, 0xcd, 0x7a, 0x3f, 0xd2, 0x66, 0xf5, 0xfa, 0x17, - 0x0f, 0x6e, 0x55, 0x66, 0x87, 0x85, 0x63, 0x1d, 0xd6, 0xeb, 0x7d, 0xa1, 0x1d, 0xdf, 0x5c, 0xfd, - 0x01, 0x8c, 0xf8, 0x4a, 0x07, 0xcb, 0xf9, 0xf2, 0xbf, 0xe7, 0x60, 0x34, 0xa4, 0x62, 0xc0, 0x8a, - 0xb1, 0x13, 0xa9, 0xb4, 0xfd, 0xfc, 0x63, 0x5d, 0x48, 0x57, 0xd5, 0xab, 0xad, 0xee, 0x13, 0xc5, - 0xe0, 0x51, 0x5a, 0xb2, 0xe4, 0xbe, 0x0b, 0xe3, 0x94, 0xff, 0xe3, 0x99, 0x7f, 0x08, 0x9a, 0xe7, - 0xb1, 0xe8, 0x3f, 0x6c, 0xdd, 0x8c, 0x50, 0x71, 0x8c, 0x7b, 0xee, 0x0e, 0x8c, 0x45, 0x94, 0x0d, - 0xf4, 0xc2, 0xf0, 0x7f, 0x25, 0x78, 0xb5, 0xe7, 0x27, 0x2a, 0xaa, 0x47, 0x36, 0x49, 0x35, 0xb6, - 0x49, 0xe6, 0xb3, 0x01, 0x5e, 0xdc, 0x4b, 0x95, 0xfa, 0xb5, 0xa7, 0xdf, 0xcd, 0x9f, 0xf9, 0xe6, - 0xbb, 0xf9, 0x33, 0xdf, 0x7e, 0x37, 0x7f, 0xe6, 0xaf, 0x8e, 0xe6, 0xa5, 0xa7, 0x47, 0xf3, 0xd2, - 0x37, 0x47, 0xf3, 0xd2, 0xb7, 0x47, 0xf3, 0xd2, 0xcf, 0x8e, 0xe6, 0xa5, 0x7f, 0xfc, 0x7e, 0xfe, - 0xcc, 0x87, 0x45, 0x01, 0xf7, 0xeb, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb1, 0xb3, 0xc8, 0xe2, 0x54, - 0x3c, 0x00, 0x00, + // 3627 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0xcd, 0x6f, 0x1c, 0xc7, + 0x72, 0xd7, 0xec, 0x2e, 0xb9, 0xcb, 0xa2, 0xf8, 0xd5, 0xa4, 0xc9, 0xb5, 0x64, 0x71, 0xe5, 0x31, + 0xa0, 0xc8, 0x8e, 0xb4, 0x6b, 0xc9, 0x96, 0xac, 0x58, 0x88, 0x6d, 0x2e, 0x29, 0x4a, 0x74, 0xf8, + 0xa5, 0x5e, 0x52, 0x71, 0x8c, 0xc8, 0xf1, 0x70, 0xb7, 0xb9, 0x1c, 0x71, 0x76, 0x66, 0x3c, 0xd3, + 0x43, 0x73, 0x81, 0x20, 0xc8, 0x21, 0x08, 0x10, 0x20, 0x41, 0x92, 0x83, 0xf3, 0x71, 0x8b, 0x2f, + 0x39, 0x25, 0x48, 0x6e, 0xc9, 0xc1, 0x30, 0x10, 0xc0, 0x01, 0x84, 0xc0, 0x01, 0x7c, 0x8b, 0x4f, + 0x44, 0x4c, 0x9f, 0x82, 0xfc, 0x03, 0x0f, 0x3a, 0x3c, 0x3c, 0x74, 0x4f, 0xcf, 0xf7, 0x0c, 0x77, + 0x97, 0x96, 0x88, 0x87, 0x87, 0x77, 0xe3, 0x76, 0x55, 0xfd, 0xaa, 0xba, 0xba, 0xba, 0xaa, 0xa6, + 0xbb, 0x09, 0xcb, 0xfb, 0x77, 0xec, 0xaa, 0x6a, 0xd4, 0xf6, 0x9d, 0x1d, 0x62, 0xe9, 0x84, 0x12, + 0xbb, 0x76, 0x40, 0xf4, 0x96, 0x61, 0xd5, 0x04, 0x41, 0x31, 0xd5, 0x1a, 0x39, 0xa4, 0x44, 0xb7, + 0x55, 0x43, 0xb7, 0x6b, 0x07, 0x37, 0x76, 0x08, 0x55, 0x6e, 0xd4, 0xda, 0x44, 0x27, 0x96, 0x42, + 0x49, 0xab, 0x6a, 0x5a, 0x06, 0x35, 0xd0, 0x25, 0x97, 0xbd, 0xaa, 0x98, 0x6a, 0x35, 0x60, 0xaf, + 0x0a, 0xf6, 0x0b, 0xd7, 0xdb, 0x2a, 0xdd, 0x73, 0x76, 0xaa, 0x4d, 0xa3, 0x53, 0x6b, 0x1b, 0x6d, + 0xa3, 0xc6, 0xa5, 0x76, 0x9c, 0x5d, 0xfe, 0x8b, 0xff, 0xe0, 0x7f, 0xb9, 0x68, 0x17, 0xe4, 0x90, + 0xf2, 0xa6, 0x61, 0x91, 0xda, 0x41, 0x42, 0xe3, 0x85, 0xb7, 0x03, 0x9e, 0x8e, 0xd2, 0xdc, 0x53, + 0x75, 0x62, 0x75, 0x6b, 0xe6, 0x7e, 0x9b, 0x0b, 0x59, 0xc4, 0x36, 0x1c, 0xab, 0x49, 0x06, 0x92, + 0xb2, 0x6b, 0x1d, 0x42, 0x95, 0x34, 0x5d, 0xb5, 0x2c, 0x29, 0xcb, 0xd1, 0xa9, 0xda, 0x49, 0xaa, + 0xb9, 0xdd, 0x4b, 0xc0, 0x6e, 0xee, 0x91, 0x8e, 0x92, 0x90, 0x7b, 0x2b, 0x4b, 0xce, 0xa1, 0xaa, + 0x56, 0x53, 0x75, 0x6a, 0x53, 0x2b, 0x2e, 0x24, 0xdf, 0x85, 0xa9, 0x05, 0x4d, 0x33, 0x3e, 0x27, + 0xad, 0x65, 0x8d, 0x1c, 0x3e, 0x32, 0x34, 0xa7, 0x43, 0xd0, 0x15, 0x18, 0x6e, 0x59, 0xea, 0x01, + 0xb1, 0xca, 0xd2, 0x65, 0xe9, 0xea, 0x48, 0x7d, 0xfc, 0xe9, 0x51, 0xe5, 0xdc, 0xf1, 0x51, 0x65, + 0x78, 0x89, 0x8f, 0x62, 0x41, 0x95, 0x6d, 0x98, 0x10, 0xc2, 0x0f, 0x0c, 0x9b, 0x6e, 0x2a, 0x74, + 0x0f, 0xdd, 0x04, 0x30, 0x15, 0xba, 0xb7, 0x69, 0x91, 0x5d, 0xf5, 0x50, 0x88, 0x23, 0x21, 0x0e, + 0x9b, 0x3e, 0x05, 0x87, 0xb8, 0xd0, 0x35, 0x28, 0x59, 0x44, 0x69, 0x6d, 0xe8, 0x5a, 0xb7, 0x9c, + 0xbb, 0x2c, 0x5d, 0x2d, 0xd5, 0x27, 0x85, 0x44, 0x09, 0x8b, 0x71, 0xec, 0x73, 0xc8, 0x7f, 0x2f, + 0xc1, 0xcb, 0x8b, 0x8e, 0x4d, 0x8d, 0xce, 0x1a, 0xa1, 0x96, 0xda, 0x5c, 0x74, 0x2c, 0x8b, 0xe8, + 0xb4, 0x41, 0x15, 0xea, 0xd8, 0xe8, 0x32, 0x14, 0x74, 0xa5, 0x43, 0x84, 0xe6, 0xf3, 0x02, 0xa7, + 0xb0, 0xae, 0x74, 0x08, 0xe6, 0x14, 0xf4, 0x31, 0x0c, 0x1d, 0x28, 0x9a, 0x43, 0xb8, 0xaa, 0xd1, + 0x9b, 0xd5, 0x6a, 0x10, 0x7d, 0xbe, 0xdb, 0xaa, 0xe6, 0x7e, 0x9b, 0x87, 0xa3, 0x17, 0x0b, 0xd5, + 0x87, 0x8e, 0xa2, 0x53, 0x95, 0x76, 0xeb, 0x33, 0x02, 0xf2, 0xbc, 0xd0, 0xfb, 0x88, 0x61, 0x61, + 0x17, 0x52, 0xfe, 0x23, 0xb8, 0x94, 0x69, 0xda, 0xaa, 0x6a, 0x53, 0xf4, 0x18, 0x86, 0x54, 0x4a, + 0x3a, 0x76, 0x59, 0xba, 0x9c, 0xbf, 0x3a, 0x7a, 0xf3, 0x4e, 0xf5, 0xc4, 0xd0, 0xaf, 0x66, 0x82, + 0xd5, 0xc7, 0x84, 0x19, 0x43, 0x2b, 0x0c, 0x0e, 0xbb, 0xa8, 0xf2, 0x5f, 0x4b, 0x80, 0xc2, 0x32, + 0x5b, 0x8a, 0xd5, 0x26, 0xb4, 0x0f, 0xa7, 0xfc, 0xde, 0x4f, 0x73, 0xca, 0xb4, 0x80, 0x1c, 0x75, + 0x15, 0x46, 0x7c, 0x62, 0xc2, 0x6c, 0xd2, 0x24, 0xee, 0x8c, 0x47, 0x51, 0x67, 0xdc, 0x18, 0xc0, + 0x19, 0x2e, 0x4a, 0x86, 0x17, 0xbe, 0xc8, 0xc1, 0xc8, 0x92, 0x42, 0x3a, 0x86, 0xde, 0x20, 0x14, + 0x7d, 0x0a, 0x25, 0xb6, 0x35, 0x5b, 0x0a, 0x55, 0xb8, 0x03, 0x46, 0x6f, 0xbe, 0x79, 0xd2, 0xec, + 0xec, 0x2a, 0xe3, 0xae, 0x1e, 0xdc, 0xa8, 0x6e, 0xec, 0x3c, 0x21, 0x4d, 0xba, 0x46, 0xa8, 0x12, + 0x44, 0x70, 0x30, 0x86, 0x7d, 0x54, 0xb4, 0x0e, 0x05, 0xdb, 0x24, 0x4d, 0xe1, 0xbb, 0x6b, 0x3d, + 0xa6, 0xe1, 0x5b, 0xd6, 0x30, 0x49, 0x33, 0x58, 0x0c, 0xf6, 0x0b, 0x73, 0x1c, 0xf4, 0x08, 0x86, + 0x6d, 0xbe, 0xca, 0xe5, 0x7c, 0x62, 0x35, 0x4e, 0x46, 0x74, 0x63, 0xc3, 0xdf, 0xae, 0xee, 0x6f, + 0x2c, 0xd0, 0xe4, 0xff, 0xcb, 0x01, 0xf2, 0x79, 0x17, 0x0d, 0xbd, 0xa5, 0x52, 0xd5, 0xd0, 0xd1, + 0xbb, 0x50, 0xa0, 0x5d, 0xd3, 0x8b, 0x8e, 0x2b, 0x9e, 0x41, 0x5b, 0x5d, 0x93, 0x3c, 0x3b, 0xaa, + 0xcc, 0x26, 0x25, 0x18, 0x05, 0x73, 0x19, 0xb4, 0xea, 0x9b, 0x9a, 0xe3, 0xd2, 0x6f, 0x47, 0x55, + 0x3f, 0x3b, 0xaa, 0xa4, 0xa4, 0xe3, 0xaa, 0x8f, 0x14, 0x35, 0x10, 0x1d, 0x00, 0xd2, 0x14, 0x9b, + 0x6e, 0x59, 0x8a, 0x6e, 0xbb, 0x9a, 0xd4, 0x0e, 0x11, 0x4e, 0x78, 0xa3, 0xbf, 0x45, 0x63, 0x12, + 0xf5, 0x0b, 0xc2, 0x0a, 0xb4, 0x9a, 0x40, 0xc3, 0x29, 0x1a, 0x58, 0xbe, 0xb3, 0x88, 0x62, 0x1b, + 0x7a, 0xb9, 0x10, 0xcd, 0x77, 0x98, 0x8f, 0x62, 0x41, 0x45, 0xaf, 0x43, 0xb1, 0x43, 0x6c, 0x5b, + 0x69, 0x93, 0xf2, 0x10, 0x67, 0x9c, 0x10, 0x8c, 0xc5, 0x35, 0x77, 0x18, 0x7b, 0x74, 0xf9, 0x2b, + 0x09, 0xc6, 0x7c, 0xcf, 0xf1, 0x68, 0xff, 0xfd, 0x44, 0x1c, 0x56, 0xfb, 0x9b, 0x12, 0x93, 0xe6, + 0x51, 0xe8, 0x67, 0x45, 0x6f, 0x24, 0x14, 0x83, 0x6b, 0xde, 0x5e, 0xca, 0xf1, 0xbd, 0x74, 0xb5, + 0xdf, 0x90, 0xc9, 0xd8, 0x42, 0x7f, 0x53, 0x08, 0x99, 0xcf, 0x42, 0x13, 0x3d, 0x86, 0x92, 0x4d, + 0x34, 0xd2, 0xa4, 0x86, 0x25, 0xcc, 0x7f, 0xab, 0x4f, 0xf3, 0x95, 0x1d, 0xa2, 0x35, 0x84, 0x68, + 0xfd, 0x3c, 0xb3, 0xdf, 0xfb, 0x85, 0x7d, 0x48, 0xf4, 0x10, 0x4a, 0x94, 0x74, 0x4c, 0x4d, 0xa1, + 0x5e, 0x0e, 0x7a, 0x2d, 0x3c, 0x05, 0x16, 0x39, 0x0c, 0x6c, 0xd3, 0x68, 0x6d, 0x09, 0x36, 0xbe, + 0x7d, 0x7c, 0x97, 0x78, 0xa3, 0xd8, 0x87, 0x41, 0x07, 0x30, 0xee, 0x98, 0x2d, 0xc6, 0x49, 0x59, + 0xc5, 0x6b, 0x77, 0x45, 0x24, 0xdd, 0xee, 0xd7, 0x37, 0xdb, 0x11, 0xe9, 0xfa, 0xac, 0xd0, 0x35, + 0x1e, 0x1d, 0xc7, 0x31, 0x2d, 0x68, 0x01, 0x26, 0x3a, 0xaa, 0xce, 0x2a, 0x57, 0xb7, 0x41, 0x9a, + 0x86, 0xde, 0xb2, 0x79, 0x58, 0x0d, 0xd5, 0xe7, 0x04, 0xc0, 0xc4, 0x5a, 0x94, 0x8c, 0xe3, 0xfc, + 0xe8, 0x43, 0x40, 0xde, 0x34, 0xee, 0xbb, 0x05, 0x5b, 0x35, 0x74, 0x1e, 0x73, 0xf9, 0x20, 0xb8, + 0xb7, 0x12, 0x1c, 0x38, 0x45, 0x0a, 0xad, 0xc2, 0x8c, 0x45, 0x0e, 0x54, 0x36, 0xc7, 0x07, 0xaa, + 0x4d, 0x0d, 0xab, 0xbb, 0xaa, 0x76, 0x54, 0x5a, 0x1e, 0xe6, 0x36, 0x95, 0x8f, 0x8f, 0x2a, 0x33, + 0x38, 0x85, 0x8e, 0x53, 0xa5, 0xe4, 0xbf, 0x1d, 0x86, 0x89, 0x58, 0xbe, 0x41, 0x8f, 0x60, 0xb6, + 0xe9, 0x16, 0xa7, 0x75, 0xa7, 0xb3, 0x43, 0xac, 0x46, 0x73, 0x8f, 0xb4, 0x1c, 0x8d, 0xb4, 0x78, + 0xa0, 0x0c, 0xd5, 0xe7, 0x85, 0xc5, 0xb3, 0x8b, 0xa9, 0x5c, 0x38, 0x43, 0x9a, 0x79, 0x41, 0xe7, + 0x43, 0x6b, 0xaa, 0x6d, 0xfb, 0x98, 0x39, 0x8e, 0xe9, 0x7b, 0x61, 0x3d, 0xc1, 0x81, 0x53, 0xa4, + 0x98, 0x8d, 0x2d, 0x62, 0xab, 0x16, 0x69, 0xc5, 0x6d, 0xcc, 0x47, 0x6d, 0x5c, 0x4a, 0xe5, 0xc2, + 0x19, 0xd2, 0xe8, 0x16, 0x8c, 0xba, 0xda, 0xf8, 0xfa, 0x89, 0x85, 0xf6, 0xcb, 0xe1, 0x7a, 0x40, + 0xc2, 0x61, 0x3e, 0x36, 0x35, 0x63, 0xc7, 0x26, 0xd6, 0x01, 0x69, 0x65, 0x2f, 0xf0, 0x46, 0x82, + 0x03, 0xa7, 0x48, 0xb1, 0xa9, 0xb9, 0x11, 0x98, 0x98, 0xda, 0x70, 0x74, 0x6a, 0xdb, 0xa9, 0x5c, + 0x38, 0x43, 0x9a, 0xc5, 0xb1, 0x6b, 0xf2, 0xc2, 0x81, 0xa2, 0x6a, 0xca, 0x8e, 0x46, 0xca, 0xc5, + 0x68, 0x1c, 0xaf, 0x47, 0xc9, 0x38, 0xce, 0x8f, 0xee, 0xc3, 0x94, 0x3b, 0xb4, 0xad, 0x2b, 0x3e, + 0x48, 0x89, 0x83, 0xbc, 0x2c, 0x40, 0xa6, 0xd6, 0xe3, 0x0c, 0x38, 0x29, 0x83, 0xde, 0x85, 0xf1, + 0xa6, 0xa1, 0x69, 0x3c, 0x1e, 0x17, 0x0d, 0x47, 0xa7, 0xe5, 0x11, 0x8e, 0x82, 0xd8, 0x7e, 0x5c, + 0x8c, 0x50, 0x70, 0x8c, 0x13, 0x11, 0x80, 0xa6, 0x57, 0x70, 0xec, 0x32, 0xf4, 0xd5, 0x6b, 0x24, + 0x8b, 0x5e, 0xd0, 0x03, 0xf8, 0x43, 0x36, 0x0e, 0x01, 0xcb, 0xff, 0x25, 0xc1, 0x5c, 0x46, 0xea, + 0x40, 0xef, 0x47, 0x4a, 0xec, 0x6f, 0xc6, 0x4a, 0xec, 0xc5, 0x0c, 0xb1, 0x50, 0x9d, 0xd5, 0x61, + 0xcc, 0x62, 0xb3, 0xd2, 0xdb, 0x2e, 0x8b, 0xc8, 0x91, 0xb7, 0x7a, 0x4c, 0x03, 0x87, 0x65, 0x82, + 0x9c, 0x3f, 0x75, 0x7c, 0x54, 0x19, 0x8b, 0xd0, 0x70, 0x14, 0x5e, 0xfe, 0xbb, 0x1c, 0xc0, 0x12, + 0x31, 0x35, 0xa3, 0xdb, 0x21, 0xfa, 0x59, 0xf4, 0x50, 0x1b, 0x91, 0x1e, 0xea, 0x7a, 0xaf, 0xe5, + 0xf1, 0x4d, 0xcb, 0x6c, 0xa2, 0x7e, 0x37, 0xd6, 0x44, 0xd5, 0xfa, 0x87, 0x3c, 0xb9, 0x8b, 0xfa, + 0x9f, 0x3c, 0x4c, 0x07, 0xcc, 0x41, 0x1b, 0x75, 0x37, 0xb2, 0xc6, 0xbf, 0x11, 0x5b, 0xe3, 0xb9, + 0x14, 0x91, 0x17, 0xd6, 0x47, 0x3d, 0xff, 0x7e, 0x06, 0x3d, 0x81, 0x71, 0xd6, 0x38, 0xb9, 0xe1, + 0xc1, 0xdb, 0xb2, 0xe1, 0x81, 0xdb, 0x32, 0xbf, 0x80, 0xae, 0x46, 0x90, 0x70, 0x0c, 0x39, 0xa3, + 0x0d, 0x2c, 0xbe, 0xe8, 0x36, 0x50, 0xfe, 0x5a, 0x82, 0xf1, 0x60, 0x99, 0xce, 0xa0, 0x69, 0x5b, + 0x8f, 0x36, 0x6d, 0xaf, 0xf7, 0x1d, 0xa2, 0x19, 0x5d, 0xdb, 0xcf, 0x58, 0x83, 0xef, 0x33, 0xb1, + 0x0d, 0xbe, 0xa3, 0x34, 0xf7, 0xfb, 0xf8, 0xfc, 0xfb, 0x42, 0x02, 0x24, 0xaa, 0xc0, 0x82, 0xae, + 0x1b, 0x54, 0x71, 0x73, 0xa5, 0x6b, 0xd6, 0x4a, 0xdf, 0x66, 0x79, 0x1a, 0xab, 0xdb, 0x09, 0xac, + 0x7b, 0x3a, 0xb5, 0xba, 0xc1, 0x8a, 0x24, 0x19, 0x70, 0x8a, 0x01, 0x48, 0x01, 0xb0, 0x04, 0xe6, + 0x96, 0x21, 0x36, 0xf2, 0xf5, 0x3e, 0x72, 0x1e, 0x13, 0x58, 0x34, 0xf4, 0x5d, 0xb5, 0x1d, 0xa4, + 0x1d, 0xec, 0x03, 0xe1, 0x10, 0xe8, 0x85, 0x7b, 0x30, 0x97, 0x61, 0x2d, 0x9a, 0x84, 0xfc, 0x3e, + 0xe9, 0xba, 0x6e, 0xc3, 0xec, 0x4f, 0x34, 0x13, 0xfe, 0x4c, 0x1e, 0x11, 0x5f, 0xb8, 0xef, 0xe6, + 0xee, 0x48, 0xf2, 0x57, 0x43, 0xe1, 0xd8, 0xe1, 0x1d, 0xf3, 0x55, 0x28, 0x59, 0xc4, 0xd4, 0xd4, + 0xa6, 0x62, 0x8b, 0x46, 0xe8, 0xbc, 0x7b, 0xa4, 0xe1, 0x8e, 0x61, 0x9f, 0x1a, 0xe9, 0xad, 0x73, + 0x2f, 0xb6, 0xb7, 0xce, 0x3f, 0x9f, 0xde, 0xfa, 0x0f, 0xa0, 0x64, 0x7b, 0x5d, 0x75, 0x81, 0x43, + 0xde, 0x18, 0x20, 0xbf, 0x8a, 0x86, 0xda, 0x57, 0xe0, 0xb7, 0xd2, 0x3e, 0x68, 0x5a, 0x13, 0x3d, + 0x34, 0x60, 0x13, 0xfd, 0x5c, 0x1b, 0x5f, 0x96, 0x53, 0x4d, 0xc5, 0xb1, 0x49, 0x8b, 0x27, 0xa2, + 0x52, 0x90, 0x53, 0x37, 0xf9, 0x28, 0x16, 0x54, 0xf4, 0x38, 0x12, 0xb2, 0xa5, 0xd3, 0x84, 0xec, + 0x78, 0x76, 0xb8, 0xa2, 0x6d, 0x98, 0x33, 0x2d, 0xa3, 0x6d, 0x11, 0xdb, 0x5e, 0x22, 0x4a, 0x4b, + 0x53, 0x75, 0xe2, 0xf9, 0xc7, 0xed, 0x88, 0x2e, 0x1e, 0x1f, 0x55, 0xe6, 0x36, 0xd3, 0x59, 0x70, + 0x96, 0xac, 0xfc, 0xb4, 0x00, 0x93, 0xf1, 0x0a, 0x98, 0xd1, 0xa4, 0x4a, 0xa7, 0x6a, 0x52, 0xaf, + 0x85, 0x36, 0x83, 0xdb, 0xc1, 0x87, 0xce, 0xf8, 0x12, 0x1b, 0x62, 0x01, 0x26, 0x44, 0x36, 0xf0, + 0x88, 0xa2, 0x4d, 0xf7, 0x57, 0x7f, 0x3b, 0x4a, 0xc6, 0x71, 0x7e, 0xd6, 0x7a, 0x06, 0x1d, 0xa5, + 0x07, 0x52, 0x88, 0xb6, 0x9e, 0x0b, 0x71, 0x06, 0x9c, 0x94, 0x41, 0x6b, 0x30, 0xed, 0xe8, 0x49, + 0x28, 0x37, 0x1a, 0x2f, 0x0a, 0xa8, 0xe9, 0xed, 0x24, 0x0b, 0x4e, 0x93, 0x43, 0xbb, 0x91, 0x6e, + 0x74, 0x98, 0x67, 0xd8, 0x9b, 0x7d, 0xef, 0x9d, 0xbe, 0xdb, 0x51, 0x74, 0x17, 0xc6, 0x2c, 0xfe, + 0xdd, 0xe1, 0x19, 0xec, 0xf6, 0xee, 0x2f, 0x09, 0xb1, 0x31, 0x1c, 0x26, 0xe2, 0x28, 0x6f, 0x4a, + 0xbb, 0x5d, 0xea, 0xb7, 0xdd, 0x96, 0xff, 0x43, 0x0a, 0x17, 0x21, 0xbf, 0x05, 0xee, 0x75, 0xca, + 0x94, 0x90, 0x08, 0x75, 0x47, 0x46, 0x7a, 0xf7, 0x7b, 0x7b, 0xa0, 0xee, 0x37, 0x28, 0x9e, 0xbd, + 0xdb, 0xdf, 0x2f, 0x25, 0x98, 0x5d, 0x6e, 0xdc, 0xb7, 0x0c, 0xc7, 0xf4, 0xcc, 0xd9, 0x30, 0x5d, + 0xbf, 0xbe, 0x03, 0x05, 0xcb, 0xd1, 0xbc, 0x79, 0xbc, 0xe6, 0xcd, 0x03, 0x3b, 0x1a, 0x9b, 0xc7, + 0x74, 0x4c, 0xca, 0x9d, 0x04, 0x13, 0x40, 0xeb, 0x30, 0x6c, 0x29, 0x7a, 0x9b, 0x78, 0x65, 0xf5, + 0x4a, 0x0f, 0xeb, 0x57, 0x96, 0x30, 0x63, 0x0f, 0x35, 0x6f, 0x5c, 0x1a, 0x0b, 0x14, 0xf9, 0x2f, + 0x24, 0x98, 0x78, 0xb0, 0xb5, 0xb5, 0xb9, 0xa2, 0xf3, 0x1d, 0xcd, 0x4f, 0xdf, 0x2f, 0x43, 0xc1, + 0x54, 0xe8, 0x5e, 0xbc, 0xd2, 0x33, 0x1a, 0xe6, 0x14, 0xf4, 0x11, 0x14, 0x59, 0x26, 0x21, 0x7a, + 0xab, 0xcf, 0x56, 0x5b, 0xc0, 0xd7, 0x5d, 0xa1, 0xa0, 0x43, 0x14, 0x03, 0xd8, 0x83, 0x93, 0xf7, + 0x61, 0x26, 0x64, 0x0e, 0xf3, 0x07, 0x3f, 0x06, 0x46, 0x0d, 0x18, 0x62, 0x9a, 0xbd, 0x53, 0xde, + 0x5e, 0x87, 0x99, 0xb1, 0x29, 0x05, 0x9d, 0x0e, 0xfb, 0x65, 0x63, 0x17, 0x4b, 0x5e, 0x83, 0x31, + 0x7e, 0xe5, 0x60, 0x58, 0x94, 0xbb, 0x05, 0x5d, 0x82, 0x7c, 0x47, 0xd5, 0x45, 0x9d, 0x1d, 0x15, + 0x32, 0x79, 0x56, 0x23, 0xd8, 0x38, 0x27, 0x2b, 0x87, 0x22, 0xf3, 0x04, 0x64, 0xe5, 0x10, 0xb3, + 0x71, 0xf9, 0x3e, 0x14, 0x85, 0xbb, 0xc3, 0x40, 0xf9, 0x93, 0x81, 0xf2, 0x29, 0x40, 0x1b, 0x50, + 0x5c, 0xd9, 0xac, 0x6b, 0x86, 0xdb, 0x75, 0x35, 0xd5, 0x96, 0x15, 0x5f, 0x8b, 0xc5, 0x95, 0x25, + 0x8c, 0x39, 0x05, 0xc9, 0x30, 0x4c, 0x0e, 0x9b, 0xc4, 0xa4, 0x3c, 0x22, 0x46, 0xea, 0xc0, 0x56, + 0xf9, 0x1e, 0x1f, 0xc1, 0x82, 0x22, 0xff, 0x65, 0x0e, 0x8a, 0xc2, 0x1d, 0x67, 0xf0, 0x15, 0xb6, + 0x1a, 0xf9, 0x0a, 0x7b, 0xa3, 0xbf, 0xd0, 0xc8, 0xfc, 0x04, 0xdb, 0x8a, 0x7d, 0x82, 0x5d, 0xeb, + 0x13, 0xef, 0xe4, 0xef, 0xaf, 0x7f, 0x95, 0x60, 0x3c, 0x1a, 0x94, 0xe8, 0x16, 0x8c, 0xb2, 0x82, + 0xa3, 0x36, 0xc9, 0x7a, 0xd0, 0xe7, 0xfa, 0x87, 0x30, 0x8d, 0x80, 0x84, 0xc3, 0x7c, 0xa8, 0xed, + 0x8b, 0xb1, 0x38, 0x12, 0x93, 0xce, 0x76, 0xa9, 0x43, 0x55, 0xad, 0xea, 0x5e, 0xa3, 0x55, 0x57, + 0x74, 0xba, 0x61, 0x35, 0xa8, 0xa5, 0xea, 0xed, 0x84, 0x22, 0x1e, 0x94, 0x61, 0x64, 0xf9, 0xdf, + 0x25, 0x18, 0x15, 0x26, 0x9f, 0xc1, 0x57, 0xc5, 0xef, 0x44, 0xbf, 0x2a, 0xae, 0xf4, 0xb9, 0xc1, + 0xd3, 0x3f, 0x29, 0xfe, 0x31, 0x30, 0x9d, 0x6d, 0x69, 0x16, 0xd5, 0x7b, 0x86, 0x4d, 0xe3, 0x51, + 0xcd, 0x36, 0x23, 0xe6, 0x14, 0xe4, 0xc0, 0xa4, 0x1a, 0xcb, 0x01, 0xc2, 0xb5, 0xb5, 0xfe, 0x2c, + 0xf1, 0xc5, 0xea, 0x65, 0x01, 0x3f, 0x19, 0xa7, 0xe0, 0x84, 0x0a, 0x99, 0x40, 0x82, 0x0b, 0x3d, + 0x84, 0xc2, 0x1e, 0xa5, 0x66, 0xca, 0x79, 0x75, 0x8f, 0xcc, 0x13, 0x98, 0x50, 0xe2, 0xb3, 0xdb, + 0xda, 0xda, 0xc4, 0x1c, 0x4a, 0xfe, 0x79, 0xe0, 0x8f, 0x86, 0x1b, 0xe3, 0x7e, 0x3e, 0x95, 0x4e, + 0x93, 0x4f, 0x47, 0xd3, 0x72, 0x29, 0x7a, 0x00, 0x79, 0xaa, 0xf5, 0xfb, 0x59, 0x28, 0x10, 0xb7, + 0x56, 0x1b, 0x41, 0x42, 0xda, 0x5a, 0x6d, 0x60, 0x06, 0x81, 0x36, 0x60, 0x88, 0x55, 0x1f, 0xb6, + 0x05, 0xf3, 0xfd, 0x6f, 0x69, 0x36, 0xff, 0x20, 0x20, 0xd8, 0x2f, 0x1b, 0xbb, 0x38, 0xf2, 0x67, + 0x30, 0x16, 0xd9, 0xa7, 0xe8, 0x53, 0x38, 0xaf, 0x19, 0x4a, 0xab, 0xae, 0x68, 0x8a, 0xde, 0x24, + 0xde, 0xe5, 0xc0, 0x95, 0xb4, 0x2f, 0x8c, 0xd5, 0x10, 0x9f, 0xd8, 0xe5, 0xfe, 0x75, 0x6a, 0x98, + 0x86, 0x23, 0x88, 0xb2, 0x02, 0x10, 0xcc, 0x11, 0x55, 0x60, 0x88, 0xc5, 0x99, 0x5b, 0x4f, 0x46, + 0xea, 0x23, 0xcc, 0x42, 0x16, 0x7e, 0x36, 0x76, 0xc7, 0xd1, 0x4d, 0x00, 0x9b, 0x34, 0x2d, 0x42, + 0x79, 0x32, 0xc8, 0x45, 0xaf, 0xa0, 0x1b, 0x3e, 0x05, 0x87, 0xb8, 0xe4, 0xff, 0x94, 0x60, 0x6c, + 0x9d, 0xd0, 0xcf, 0x0d, 0x6b, 0x7f, 0xd3, 0xd0, 0xd4, 0x66, 0xf7, 0x0c, 0x92, 0x2d, 0x8e, 0x24, + 0xdb, 0x37, 0x7b, 0xac, 0x4c, 0xc4, 0xba, 0xac, 0x94, 0x2b, 0x7f, 0x2d, 0xc1, 0x5c, 0x84, 0xf3, + 0x5e, 0xb0, 0x75, 0xb7, 0x61, 0xc8, 0x34, 0x2c, 0xea, 0x15, 0xe2, 0x81, 0x14, 0xb2, 0x34, 0x16, + 0x2a, 0xc5, 0x0c, 0x06, 0xbb, 0x68, 0x68, 0x15, 0x72, 0xd4, 0x10, 0xa1, 0x3a, 0x18, 0x26, 0x21, + 0x56, 0x1d, 0x04, 0x66, 0x6e, 0xcb, 0xc0, 0x39, 0x6a, 0xb0, 0x85, 0x28, 0x47, 0xb8, 0xc2, 0xc9, + 0xe7, 0x05, 0xcd, 0x00, 0x43, 0x61, 0xd7, 0x32, 0x3a, 0xa7, 0x9e, 0x83, 0xbf, 0x10, 0xcb, 0x96, + 0xd1, 0xc1, 0x1c, 0x4b, 0xfe, 0x46, 0x82, 0xa9, 0x08, 0xe7, 0x19, 0x24, 0xfe, 0x87, 0xd1, 0xc4, + 0x7f, 0x6d, 0x90, 0x89, 0x64, 0xa4, 0xff, 0x6f, 0x72, 0xb1, 0x69, 0xb0, 0x09, 0xa3, 0x5d, 0x18, + 0x35, 0x8d, 0x56, 0xe3, 0x39, 0x5c, 0x07, 0x4e, 0xb0, 0xba, 0xb9, 0x19, 0x60, 0xe1, 0x30, 0x30, + 0x3a, 0x84, 0x29, 0x5d, 0xe9, 0x10, 0xdb, 0x54, 0x9a, 0xa4, 0xf1, 0x1c, 0x0e, 0x48, 0x5e, 0xe2, + 0xf7, 0x0d, 0x71, 0x44, 0x9c, 0x54, 0x82, 0xd6, 0xa0, 0xa8, 0x9a, 0xbc, 0x8f, 0x13, 0xbd, 0x4b, + 0xcf, 0x2a, 0xea, 0x76, 0x7d, 0x6e, 0x3e, 0x17, 0x3f, 0xb0, 0x87, 0x21, 0xff, 0x53, 0x3c, 0x1a, + 0x58, 0xfc, 0xa1, 0xfb, 0x50, 0xe2, 0x8f, 0x70, 0x9a, 0x86, 0xe6, 0xdd, 0x0c, 0xb0, 0x95, 0xdd, + 0x14, 0x63, 0xcf, 0x8e, 0x2a, 0x17, 0x53, 0x0e, 0x7d, 0x3d, 0x32, 0xf6, 0x85, 0xd1, 0x3a, 0x14, + 0xcc, 0x9f, 0xd2, 0xc1, 0xf0, 0x22, 0xc7, 0xdb, 0x16, 0x8e, 0x23, 0xff, 0x49, 0x3e, 0x66, 0x2e, + 0x2f, 0x75, 0x4f, 0x9e, 0xdb, 0xaa, 0xfb, 0x1d, 0x53, 0xe6, 0xca, 0xef, 0x40, 0x51, 0x54, 0x78, + 0x11, 0xcc, 0xef, 0x0c, 0x12, 0xcc, 0xe1, 0x2a, 0xe6, 0x7f, 0xb0, 0x78, 0x83, 0x1e, 0x30, 0xfa, + 0x04, 0x86, 0x89, 0xab, 0xc2, 0xad, 0x8d, 0xb7, 0x07, 0x51, 0x11, 0xe4, 0xd5, 0xa0, 0x51, 0x15, + 0x63, 0x02, 0x15, 0xbd, 0xcf, 0xfc, 0xc5, 0x78, 0xd9, 0x47, 0xa0, 0x5d, 0x2e, 0xf0, 0x72, 0x75, + 0xc9, 0x9d, 0xb6, 0x3f, 0xfc, 0xec, 0xa8, 0x02, 0xc1, 0x4f, 0x1c, 0x96, 0x90, 0xff, 0x5b, 0x82, + 0x29, 0xee, 0xa1, 0xa6, 0x63, 0xa9, 0xb4, 0x7b, 0x66, 0x85, 0xe9, 0x51, 0xa4, 0x30, 0xbd, 0xdd, + 0xc3, 0x2d, 0x09, 0x0b, 0x33, 0x8b, 0xd3, 0xb7, 0x12, 0xbc, 0x94, 0xe0, 0x3e, 0x83, 0xbc, 0xb8, + 0x1d, 0xcd, 0x8b, 0x6f, 0x0e, 0x3a, 0xa1, 0xac, 0xd6, 0x78, 0x3c, 0x65, 0x3a, 0x7c, 0xa7, 0xdc, + 0x04, 0x30, 0x2d, 0xf5, 0x40, 0xd5, 0x48, 0x5b, 0x5c, 0x82, 0x97, 0x42, 0x8f, 0xe0, 0x7c, 0x0a, + 0x0e, 0x71, 0x21, 0x1b, 0x66, 0x5b, 0x64, 0x57, 0x71, 0x34, 0xba, 0xd0, 0x6a, 0x2d, 0x2a, 0xa6, + 0xb2, 0xa3, 0x6a, 0x2a, 0x55, 0xc5, 0x71, 0xc1, 0x48, 0xfd, 0xae, 0x7b, 0x39, 0x9d, 0xc6, 0xf1, + 0xec, 0xa8, 0x72, 0x29, 0xed, 0x76, 0xc8, 0x63, 0xe9, 0xe2, 0x0c, 0x68, 0xd4, 0x85, 0xb2, 0x45, + 0x3e, 0x73, 0x54, 0x8b, 0xb4, 0x96, 0x2c, 0xc3, 0x8c, 0xa8, 0xcd, 0x73, 0xb5, 0xbf, 0x7d, 0x7c, + 0x54, 0x29, 0xe3, 0x0c, 0x9e, 0xde, 0x8a, 0x33, 0xe1, 0xd1, 0x13, 0x98, 0x56, 0xdc, 0xb7, 0x83, + 0x11, 0xad, 0xee, 0x2e, 0xb9, 0x73, 0x7c, 0x54, 0x99, 0x5e, 0x48, 0x92, 0x7b, 0x2b, 0x4c, 0x03, + 0x45, 0x35, 0x28, 0x1e, 0xf0, 0x97, 0x8d, 0x76, 0x79, 0x88, 0xe3, 0xb3, 0x42, 0x50, 0x74, 0x1f, + 0x3b, 0x32, 0xcc, 0xe1, 0xe5, 0x06, 0xdf, 0x7d, 0x1e, 0x17, 0xfb, 0xa0, 0x64, 0xbd, 0xa4, 0xd8, + 0xf1, 0xfc, 0xc4, 0xb8, 0x14, 0x64, 0xad, 0x07, 0x01, 0x09, 0x87, 0xf9, 0xd0, 0x63, 0x18, 0xd9, + 0x13, 0xa7, 0x12, 0x76, 0xb9, 0xd8, 0x57, 0x11, 0x8e, 0x9c, 0x62, 0xd4, 0xa7, 0x84, 0x8a, 0x11, + 0x6f, 0xd8, 0xc6, 0x01, 0x22, 0x7a, 0x1d, 0x8a, 0xfc, 0xc7, 0xca, 0x12, 0x3f, 0x8e, 0x2b, 0x05, + 0xb9, 0xed, 0x81, 0x3b, 0x8c, 0x3d, 0xba, 0xc7, 0xba, 0xb2, 0xb9, 0xc8, 0x8f, 0x85, 0x63, 0xac, + 0x2b, 0x9b, 0x8b, 0xd8, 0xa3, 0xa3, 0x4f, 0xa1, 0x68, 0x93, 0x55, 0x55, 0x77, 0x0e, 0xcb, 0xd0, + 0xd7, 0xa5, 0x72, 0xe3, 0x1e, 0xe7, 0x8e, 0x1d, 0x8c, 0x05, 0x1a, 0x04, 0x1d, 0x7b, 0xb0, 0x68, + 0x0f, 0x46, 0x2c, 0x47, 0x5f, 0xb0, 0xb7, 0x6d, 0x62, 0x95, 0x47, 0xb9, 0x8e, 0x5e, 0xe9, 0x1c, + 0x7b, 0xfc, 0x71, 0x2d, 0xbe, 0x87, 0x7c, 0x0e, 0x1c, 0x80, 0xa3, 0x3f, 0x97, 0x00, 0xd9, 0x8e, + 0x69, 0x6a, 0xa4, 0x43, 0x74, 0xaa, 0x68, 0xfc, 0x2c, 0xce, 0x2e, 0x9f, 0xe7, 0x3a, 0x3f, 0xe8, + 0x35, 0xaf, 0x84, 0x60, 0x5c, 0xb9, 0x7f, 0xe8, 0x9d, 0x64, 0xc5, 0x29, 0x7a, 0x99, 0x6b, 0x77, + 0x6d, 0xfe, 0x77, 0x79, 0xac, 0x2f, 0xd7, 0xa6, 0x9f, 0x39, 0x06, 0xae, 0x15, 0x74, 0xec, 0xc1, + 0xa2, 0x47, 0x30, 0xeb, 0x3d, 0x8c, 0xc5, 0x86, 0x41, 0x97, 0x55, 0x8d, 0xd8, 0x5d, 0x9b, 0x92, + 0x4e, 0x79, 0x9c, 0x2f, 0xbb, 0xff, 0xf6, 0x03, 0xa7, 0x72, 0xe1, 0x0c, 0x69, 0xd4, 0x81, 0x8a, + 0x97, 0x32, 0xd8, 0x7e, 0xf2, 0x73, 0xd6, 0x3d, 0xbb, 0xa9, 0x68, 0xee, 0x3d, 0xc0, 0x04, 0x57, + 0xf0, 0xda, 0xf1, 0x51, 0xa5, 0xb2, 0x74, 0x32, 0x2b, 0xee, 0x85, 0x85, 0x3e, 0x82, 0xb2, 0x92, + 0xa5, 0x67, 0x92, 0xeb, 0x79, 0x85, 0xe5, 0xa1, 0x4c, 0x05, 0x99, 0xd2, 0x88, 0xc2, 0xa4, 0x12, + 0x7d, 0xa2, 0x6c, 0x97, 0xa7, 0xfa, 0x3a, 0x88, 0x8c, 0xbd, 0x6c, 0x0e, 0x0e, 0x23, 0x62, 0x04, + 0x1b, 0x27, 0x34, 0xa0, 0x3f, 0x04, 0xa4, 0xc4, 0x5f, 0x55, 0xdb, 0x65, 0xd4, 0x57, 0xf9, 0x49, + 0x3c, 0xc7, 0x0e, 0xc2, 0x2e, 0x41, 0xb2, 0x71, 0x8a, 0x1e, 0xb4, 0x0a, 0x33, 0x62, 0x74, 0x5b, + 0xb7, 0x95, 0x5d, 0xd2, 0xe8, 0xda, 0x4d, 0xaa, 0xd9, 0xe5, 0x69, 0x9e, 0xfb, 0xf8, 0xc5, 0xd7, + 0x42, 0x0a, 0x1d, 0xa7, 0x4a, 0xa1, 0x0f, 0x60, 0x72, 0xd7, 0xb0, 0x76, 0xd4, 0x56, 0x8b, 0xe8, + 0x1e, 0xd2, 0x0c, 0x47, 0x9a, 0x61, 0xde, 0x58, 0x8e, 0xd1, 0x70, 0x82, 0x9b, 0x3f, 0x26, 0x11, + 0x57, 0x0b, 0x67, 0xf3, 0x20, 0x77, 0xb0, 0xc7, 0x24, 0x81, 0x69, 0xcf, 0xed, 0x31, 0x49, 0x08, + 0xf2, 0xe4, 0xc3, 0xcc, 0xff, 0xcf, 0xc1, 0x74, 0xc0, 0xdc, 0xf7, 0x63, 0x92, 0x14, 0x91, 0x5f, + 0x3f, 0xca, 0xed, 0xfd, 0x28, 0xf7, 0x6b, 0x09, 0xc6, 0x03, 0xd7, 0xfd, 0xf2, 0x3d, 0xf0, 0x08, + 0x6c, 0xcb, 0x68, 0x39, 0xff, 0x25, 0x17, 0x9e, 0xc0, 0xaf, 0xfc, 0x2b, 0x83, 0x9f, 0xfe, 0x92, + 0x56, 0xfe, 0x36, 0x0f, 0x93, 0xf1, 0xdd, 0x18, 0xb9, 0x8c, 0x96, 0x7a, 0x5e, 0x46, 0x6f, 0xc2, + 0xcc, 0xae, 0xa3, 0x69, 0x5d, 0xee, 0x86, 0xd0, 0x8d, 0xb4, 0x7b, 0x99, 0xf4, 0x8a, 0x90, 0x9c, + 0x59, 0x4e, 0xe1, 0xc1, 0xa9, 0x92, 0x19, 0x17, 0xeb, 0xf9, 0x53, 0x5d, 0xac, 0x27, 0xee, 0x79, + 0x0b, 0x03, 0xdc, 0xf3, 0xa6, 0x5e, 0x92, 0x0f, 0x9d, 0xe2, 0x92, 0xfc, 0x34, 0xb7, 0xda, 0x29, + 0x49, 0xac, 0xe7, 0x23, 0xcb, 0x57, 0xe0, 0x82, 0x10, 0xa3, 0xfc, 0xc2, 0x59, 0xa7, 0x96, 0xa1, + 0x69, 0xc4, 0x5a, 0x72, 0x3a, 0x9d, 0xae, 0xfc, 0x1e, 0x8c, 0x47, 0x9f, 0x52, 0xb8, 0x2b, 0xed, + 0xbe, 0xe6, 0x10, 0x57, 0x7a, 0xa1, 0x95, 0x76, 0xc7, 0xb1, 0xcf, 0x21, 0xff, 0xa9, 0x04, 0xb3, + 0xe9, 0x4f, 0x26, 0x91, 0x06, 0xe3, 0x1d, 0xe5, 0x30, 0xfc, 0x8c, 0x55, 0x3a, 0xe5, 0x61, 0x0b, + 0xbf, 0x43, 0x5f, 0x8b, 0x60, 0xe1, 0x18, 0xb6, 0xfc, 0xa3, 0x04, 0x73, 0x19, 0xb7, 0xd7, 0x67, + 0x6b, 0x09, 0xfa, 0x18, 0x4a, 0x1d, 0xe5, 0xb0, 0xe1, 0x58, 0x6d, 0x72, 0xea, 0xe3, 0x25, 0x9e, + 0x31, 0xd6, 0x04, 0x0a, 0xf6, 0xf1, 0xe4, 0x2f, 0x25, 0x28, 0x67, 0x35, 0xfa, 0xe8, 0x56, 0xe4, + 0x9e, 0xfd, 0xd5, 0xd8, 0x3d, 0xfb, 0x54, 0x42, 0xee, 0x05, 0xdd, 0xb2, 0xff, 0xb3, 0x04, 0xb3, + 0xe9, 0x1f, 0x3c, 0xe8, 0xad, 0x88, 0x85, 0x95, 0x98, 0x85, 0x13, 0x31, 0x29, 0x61, 0xdf, 0x27, + 0x30, 0x2e, 0x3e, 0x8b, 0x04, 0x8c, 0xf0, 0xaa, 0x9c, 0x96, 0x2b, 0x05, 0x84, 0xf7, 0x19, 0xc0, + 0xd7, 0x2b, 0x3a, 0x86, 0x63, 0x68, 0xf2, 0x9f, 0xe5, 0x60, 0xa8, 0xd1, 0x54, 0x34, 0x72, 0x06, + 0x6d, 0xd6, 0x87, 0x91, 0x36, 0xab, 0xd7, 0xbf, 0x9c, 0x70, 0xab, 0x32, 0x3b, 0x2c, 0x1c, 0xeb, + 0xb0, 0xde, 0xe8, 0x0b, 0xed, 0xe4, 0xe6, 0xea, 0xb7, 0x60, 0xc4, 0x57, 0x3a, 0x58, 0xce, 0x97, + 0xff, 0x21, 0x07, 0xa3, 0x21, 0x15, 0x03, 0x56, 0x8c, 0xdd, 0x48, 0xa5, 0xed, 0xe7, 0x1f, 0xfd, + 0x42, 0xba, 0xaa, 0x5e, 0x6d, 0x75, 0x9f, 0x4c, 0x06, 0x8f, 0xe4, 0x92, 0x25, 0xf7, 0x3d, 0x18, + 0xa7, 0xfc, 0x1f, 0xe1, 0xfc, 0x43, 0xd9, 0x3c, 0x8f, 0x45, 0xff, 0xa1, 0xed, 0x56, 0x84, 0x8a, + 0x63, 0xdc, 0x17, 0xee, 0xc2, 0x58, 0x44, 0xd9, 0x40, 0x2f, 0x1e, 0xff, 0x4d, 0x82, 0x57, 0x7b, + 0x7e, 0x32, 0xa3, 0x7a, 0x64, 0x93, 0x54, 0x63, 0x9b, 0x64, 0x3e, 0x1b, 0xe0, 0xc5, 0xbd, 0x9c, + 0xa9, 0x5f, 0x7f, 0xfa, 0xc3, 0xfc, 0xb9, 0xef, 0x7e, 0x98, 0x3f, 0xf7, 0xfd, 0x0f, 0xf3, 0xe7, + 0xfe, 0xf8, 0x78, 0x5e, 0x7a, 0x7a, 0x3c, 0x2f, 0x7d, 0x77, 0x3c, 0x2f, 0x7d, 0x7f, 0x3c, 0x2f, + 0xfd, 0xef, 0xf1, 0xbc, 0xf4, 0x57, 0x3f, 0xce, 0x9f, 0xfb, 0xb8, 0x28, 0xe0, 0x7e, 0x11, 0x00, + 0x00, 0xff, 0xff, 0x26, 0xef, 0x73, 0xa6, 0xe7, 0x3c, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/generated.proto index 8308786d1..1e0769f58 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,7 +22,6 @@ syntax = 'proto2'; package k8s.io.api.extensions.v1beta1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; @@ -33,15 +32,17 @@ import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; option go_package = "v1beta1"; // AllowedFlexVolume represents a single Flexvolume that is allowed to be used. +// Deprecated: use AllowedFlexVolume from policy API Group instead. message AllowedFlexVolume { - // Driver is the name of the Flexvolume driver. + // driver is the name of the Flexvolume driver. optional string driver = 1; } -// defines the host volume conditions that will be enabled by a policy +// AllowedHostPath defines the host volume conditions that will be enabled by a policy // for pods to use. It requires the path prefix to be defined. +// Deprecated: use AllowedHostPath from policy API Group instead. message AllowedHostPath { - // is the path prefix that the host volume must match. + // pathPrefix is the path prefix that the host volume must match. // It does not support `*`. // Trailing slashes are trimmed when validating the path prefix with a host path. // @@ -49,6 +50,10 @@ message AllowedHostPath { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` optional string pathPrefix = 1; + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + optional bool readOnly = 2; } message CustomMetricCurrentStatus { @@ -409,13 +414,14 @@ message DeploymentStrategy { } // FSGroupStrategyOptions defines the strategy type and options used to create the strategy. +// Deprecated: use FSGroupStrategyOptions from policy API Group instead. message FSGroupStrategyOptions { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. // +optional optional string rule = 1; - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. + // ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } @@ -448,8 +454,9 @@ message HTTPIngressRuleValue { repeated HTTPIngressPath paths = 1; } -// Host Port Range defines a range of host ports that will be enabled by a policy +// HostPortRange defines a range of host ports that will be enabled by a policy // for pods to use. It requires both the start and end to be defined. +// Deprecated: use HostPortRange from policy API Group instead. message HostPortRange { // min is the start of the range, inclusive. optional int32 min = 1; @@ -458,12 +465,13 @@ message HostPortRange { optional int32 max = 2; } -// ID Range provides a min/max of an allowed range of IDs. +// IDRange provides a min/max of an allowed range of IDs. +// Deprecated: use IDRange from policy API Group instead. message IDRange { - // Min is the start of the range, inclusive. + // min is the start of the range, inclusive. optional int64 min = 1; - // Max is the end of the range, inclusive. + // max is the end of the range, inclusive. optional int64 max = 2; } @@ -678,20 +686,26 @@ message NetworkPolicyList { // DEPRECATED 1.9 - This group version of NetworkPolicyPeer is deprecated by networking/v1/NetworkPolicyPeer. message NetworkPolicyPeer { - // This is a label selector which selects Pods in this namespace. - // This field follows standard label selector semantics. - // If present but empty, this selector selects all pods in this namespace. + // This is a label selector which selects Pods. This field follows standard label + // selector semantics; if present but empty, it selects all pods. + // + // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector podSelector = 1; - // Selects Namespaces using cluster scoped-labels. This - // matches all pods in all namespaces selected by this label selector. - // This field follows standard label selector semantics. - // If present but empty, this selector selects all namespaces. + // Selects Namespaces using cluster-scoped labels. This field follows standard label + // selector semantics; if present but empty, it selects all namespaces. + // + // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector namespaceSelector = 2; - // IPBlock defines policy on a particular IPBlock + // IPBlock defines policy on a particular IPBlock. If this field is set then + // neither of the other fields can be. // +optional optional IPBlock ipBlock = 3; } @@ -755,8 +769,9 @@ message NetworkPolicySpec { repeated string policyTypes = 4; } -// Pod Security Policy governs the ability to make requests that affect the Security Context +// PodSecurityPolicy governs the ability to make requests that affect the Security Context // that will be applied to a pod and container. +// Deprecated: use PodSecurityPolicy from policy API Group instead. message PodSecurityPolicy { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata @@ -768,43 +783,45 @@ message PodSecurityPolicy { optional PodSecurityPolicySpec spec = 2; } -// Pod Security Policy List is a list of PodSecurityPolicy objects. +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. +// Deprecated: use PodSecurityPolicyList from policy API Group instead. message PodSecurityPolicyList { // Standard list metadata. // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - // Items is a list of schema objects. + // items is a list of schema objects. repeated PodSecurityPolicy items = 2; } -// Pod Security Policy Spec defines the policy enforced. +// PodSecurityPolicySpec defines the policy enforced. +// Deprecated: use PodSecurityPolicySpec from policy API Group instead. message PodSecurityPolicySpec { // privileged determines if a pod can request to be run as privileged. // +optional optional bool privileged = 1; - // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // defaultAddCapabilities is the default set of capabilities that will be added to the container // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. + // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the allowedCapabilities list. // +optional repeated string defaultAddCapabilities = 2; - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // requiredDropCapabilities are the capabilities that will be dropped from the container. These // are required to be dropped and cannot be added. // +optional repeated string requiredDropCapabilities = 3; - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // allowedCapabilities is a list of capabilities that can be requested to add to the container. // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. // +optional repeated string allowedCapabilities = 4; - // volumes is a white list of allowed volume plugins. Empty indicates that all plugins - // may be used. + // volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. // +optional repeated string volumes = 5; @@ -830,13 +847,13 @@ message PodSecurityPolicySpec { // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. optional RunAsUserStrategyOptions runAsUser = 11; - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. optional SupplementalGroupsStrategyOptions supplementalGroups = 12; - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. optional FSGroupStrategyOptions fsGroup = 13; - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // readOnlyRootFilesystem when set to true will force containers to run with a read only root file // system. If the container specifically requests to run with a non-read only root file system // the PSP should deny the pod. // If set to false the container may run with a read only root file system if it wishes but it @@ -844,25 +861,47 @@ message PodSecurityPolicySpec { // +optional optional bool readOnlyRootFilesystem = 14; - // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // defaultAllowPrivilegeEscalation controls the default setting for whether a // process can gain more privileges than its parent process. // +optional optional bool defaultAllowPrivilegeEscalation = 15; - // AllowPrivilegeEscalation determines if a pod can request to allow + // allowPrivilegeEscalation determines if a pod can request to allow // privilege escalation. If unspecified, defaults to true. // +optional optional bool allowPrivilegeEscalation = 16; - // is a white list of allowed host paths. Empty indicates that all host paths may be used. + // allowedHostPaths is a white list of allowed host paths. Empty indicates + // that all host paths may be used. // +optional repeated AllowedHostPath allowedHostPaths = 17; - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. + // is allowed in the "volumes" field. // +optional repeated AllowedFlexVolume allowedFlexVolumes = 18; + + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + repeated string allowedUnsafeSysctls = 19; + + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + repeated string forbiddenSysctls = 20; } // DEPRECATED - This group version of ReplicaSet is deprecated by apps/v1beta2/ReplicaSet. See the release notes for @@ -1041,19 +1080,22 @@ message RollingUpdateDeployment { optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; } -// Run A sUser Strategy Options defines the strategy type and any options used to create the strategy. +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. +// Deprecated: use RunAsUserStrategyOptions from policy API Group instead. message RunAsUserStrategyOptions { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + // rule is the strategy that will dictate the allowable RunAsUser values that may be set. optional string rule = 1; - // Ranges are the allowed ranges of uids that may be used. + // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } -// SELinux Strategy Options defines the strategy type and any options used to create the strategy. +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. +// Deprecated: use SELinuxStrategyOptions from policy API Group instead. message SELinuxStrategyOptions { - // type is the strategy that will dictate the allowable labels that may be set. + // rule is the strategy that will dictate the allowable labels that may be set. optional string rule = 1; // seLinuxOptions required to run as; required for MustRunAs @@ -1104,13 +1146,14 @@ message ScaleStatus { } // SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. +// Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead. message SupplementalGroupsStrategyOptions { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. // +optional optional string rule = 1; - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. + // ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/types.go index c3d9f72d7..3a86ef43a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/types.go @@ -862,8 +862,9 @@ type ReplicaSetCondition struct { // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Pod Security Policy governs the ability to make requests that affect the Security Context +// PodSecurityPolicy governs the ability to make requests that affect the Security Context // that will be applied to a pod and container. +// Deprecated: use PodSecurityPolicy from policy API Group instead. type PodSecurityPolicy struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -876,28 +877,29 @@ type PodSecurityPolicy struct { Spec PodSecurityPolicySpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` } -// Pod Security Policy Spec defines the policy enforced. +// PodSecurityPolicySpec defines the policy enforced. +// Deprecated: use PodSecurityPolicySpec from policy API Group instead. type PodSecurityPolicySpec struct { // privileged determines if a pod can request to be run as privileged. // +optional Privileged bool `json:"privileged,omitempty" protobuf:"varint,1,opt,name=privileged"` - // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // defaultAddCapabilities is the default set of capabilities that will be added to the container // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. + // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the allowedCapabilities list. // +optional DefaultAddCapabilities []v1.Capability `json:"defaultAddCapabilities,omitempty" protobuf:"bytes,2,rep,name=defaultAddCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // requiredDropCapabilities are the capabilities that will be dropped from the container. These // are required to be dropped and cannot be added. // +optional RequiredDropCapabilities []v1.Capability `json:"requiredDropCapabilities,omitempty" protobuf:"bytes,3,rep,name=requiredDropCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // allowedCapabilities is a list of capabilities that can be requested to add to the container. // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. // +optional AllowedCapabilities []v1.Capability `json:"allowedCapabilities,omitempty" protobuf:"bytes,4,rep,name=allowedCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // volumes is a white list of allowed volume plugins. Empty indicates that all plugins - // may be used. + // volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. // +optional Volumes []FSType `json:"volumes,omitempty" protobuf:"bytes,5,rep,name=volumes,casttype=FSType"` // hostNetwork determines if the policy allows the use of HostNetwork in the pod spec. @@ -916,39 +918,60 @@ type PodSecurityPolicySpec struct { SELinux SELinuxStrategyOptions `json:"seLinux" protobuf:"bytes,10,opt,name=seLinux"` // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. RunAsUser RunAsUserStrategyOptions `json:"runAsUser" protobuf:"bytes,11,opt,name=runAsUser"` - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. SupplementalGroups SupplementalGroupsStrategyOptions `json:"supplementalGroups" protobuf:"bytes,12,opt,name=supplementalGroups"` - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. FSGroup FSGroupStrategyOptions `json:"fsGroup" protobuf:"bytes,13,opt,name=fsGroup"` - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // readOnlyRootFilesystem when set to true will force containers to run with a read only root file // system. If the container specifically requests to run with a non-read only root file system // the PSP should deny the pod. // If set to false the container may run with a read only root file system if it wishes but it // will not be forced to. // +optional ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem,omitempty" protobuf:"varint,14,opt,name=readOnlyRootFilesystem"` - // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // defaultAllowPrivilegeEscalation controls the default setting for whether a // process can gain more privileges than its parent process. // +optional DefaultAllowPrivilegeEscalation *bool `json:"defaultAllowPrivilegeEscalation,omitempty" protobuf:"varint,15,opt,name=defaultAllowPrivilegeEscalation"` - // AllowPrivilegeEscalation determines if a pod can request to allow + // allowPrivilegeEscalation determines if a pod can request to allow // privilege escalation. If unspecified, defaults to true. // +optional AllowPrivilegeEscalation *bool `json:"allowPrivilegeEscalation,omitempty" protobuf:"varint,16,opt,name=allowPrivilegeEscalation"` - // is a white list of allowed host paths. Empty indicates that all host paths may be used. + // allowedHostPaths is a white list of allowed host paths. Empty indicates + // that all host paths may be used. // +optional AllowedHostPaths []AllowedHostPath `json:"allowedHostPaths,omitempty" protobuf:"bytes,17,rep,name=allowedHostPaths"` - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. + // is allowed in the "volumes" field. // +optional AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"` + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + AllowedUnsafeSysctls []string `json:"allowedUnsafeSysctls,omitempty" protobuf:"bytes,19,rep,name=allowedUnsafeSysctls"` + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + ForbiddenSysctls []string `json:"forbiddenSysctls,omitempty" protobuf:"bytes,20,rep,name=forbiddenSysctls"` } -// defines the host volume conditions that will be enabled by a policy +// AllowedHostPath defines the host volume conditions that will be enabled by a policy // for pods to use. It requires the path prefix to be defined. +// Deprecated: use AllowedHostPath from policy API Group instead. type AllowedHostPath struct { - // is the path prefix that the host volume must match. + // pathPrefix is the path prefix that the host volume must match. // It does not support `*`. // Trailing slashes are trimmed when validating the path prefix with a host path. // @@ -956,9 +979,14 @@ type AllowedHostPath struct { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` PathPrefix string `json:"pathPrefix,omitempty" protobuf:"bytes,1,rep,name=pathPrefix"` + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,2,opt,name=readOnly"` } -// FS Type gives strong typing to different file systems that are used by volumes. +// FSType gives strong typing to different file systems that are used by volumes. +// Deprecated: use FSType from policy API Group instead. type FSType string var ( @@ -987,13 +1015,15 @@ var ( ) // AllowedFlexVolume represents a single Flexvolume that is allowed to be used. +// Deprecated: use AllowedFlexVolume from policy API Group instead. type AllowedFlexVolume struct { - // Driver is the name of the Flexvolume driver. + // driver is the name of the Flexvolume driver. Driver string `json:"driver" protobuf:"bytes,1,opt,name=driver"` } -// Host Port Range defines a range of host ports that will be enabled by a policy +// HostPortRange defines a range of host ports that will be enabled by a policy // for pods to use. It requires both the start and end to be defined. +// Deprecated: use HostPortRange from policy API Group instead. type HostPortRange struct { // min is the start of the range, inclusive. Min int32 `json:"min" protobuf:"varint,1,opt,name=min"` @@ -1001,9 +1031,10 @@ type HostPortRange struct { Max int32 `json:"max" protobuf:"varint,2,opt,name=max"` } -// SELinux Strategy Options defines the strategy type and any options used to create the strategy. +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. +// Deprecated: use SELinuxStrategyOptions from policy API Group instead. type SELinuxStrategyOptions struct { - // type is the strategy that will dictate the allowable labels that may be set. + // rule is the strategy that will dictate the allowable labels that may be set. Rule SELinuxStrategy `json:"rule" protobuf:"bytes,1,opt,name=rule,casttype=SELinuxStrategy"` // seLinuxOptions required to run as; required for MustRunAs // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ @@ -1013,92 +1044,111 @@ type SELinuxStrategyOptions struct { // SELinuxStrategy denotes strategy types for generating SELinux options for a // Security Context. +// Deprecated: use SELinuxStrategy from policy API Group instead. type SELinuxStrategy string const ( - // container must have SELinux labels of X applied. + // SELinuxStrategyMustRunAs means that container must have SELinux labels of X applied. + // Deprecated: use SELinuxStrategyMustRunAs from policy API Group instead. SELinuxStrategyMustRunAs SELinuxStrategy = "MustRunAs" - // container may make requests for any SELinux context labels. + // SELinuxStrategyRunAsAny means that container may make requests for any SELinux context labels. + // Deprecated: use SELinuxStrategyRunAsAny from policy API Group instead. SELinuxStrategyRunAsAny SELinuxStrategy = "RunAsAny" ) -// Run A sUser Strategy Options defines the strategy type and any options used to create the strategy. +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. +// Deprecated: use RunAsUserStrategyOptions from policy API Group instead. type RunAsUserStrategyOptions struct { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + // rule is the strategy that will dictate the allowable RunAsUser values that may be set. Rule RunAsUserStrategy `json:"rule" protobuf:"bytes,1,opt,name=rule,casttype=RunAsUserStrategy"` - // Ranges are the allowed ranges of uids that may be used. + // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } -// ID Range provides a min/max of an allowed range of IDs. +// IDRange provides a min/max of an allowed range of IDs. +// Deprecated: use IDRange from policy API Group instead. type IDRange struct { - // Min is the start of the range, inclusive. + // min is the start of the range, inclusive. Min int64 `json:"min" protobuf:"varint,1,opt,name=min"` - // Max is the end of the range, inclusive. + // max is the end of the range, inclusive. Max int64 `json:"max" protobuf:"varint,2,opt,name=max"` } // RunAsUserStrategy denotes strategy types for generating RunAsUser values for a // Security Context. +// Deprecated: use RunAsUserStrategy from policy API Group instead. type RunAsUserStrategy string const ( - // container must run as a particular uid. + // RunAsUserStrategyMustRunAs means that container must run as a particular uid. + // Deprecated: use RunAsUserStrategyMustRunAs from policy API Group instead. RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs" - // container must run as a non-root uid + // RunAsUserStrategyMustRunAsNonRoot means that container must run as a non-root uid. + // Deprecated: use RunAsUserStrategyMustRunAsNonRoot from policy API Group instead. RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot" - // container may make requests for any uid. + // RunAsUserStrategyRunAsAny means that container may make requests for any uid. + // Deprecated: use RunAsUserStrategyRunAsAny from policy API Group instead. RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny" ) // FSGroupStrategyOptions defines the strategy type and options used to create the strategy. +// Deprecated: use FSGroupStrategyOptions from policy API Group instead. type FSGroupStrategyOptions struct { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. // +optional Rule FSGroupStrategyType `json:"rule,omitempty" protobuf:"bytes,1,opt,name=rule,casttype=FSGroupStrategyType"` - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. + // ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } // FSGroupStrategyType denotes strategy types for generating FSGroup values for a // SecurityContext +// Deprecated: use FSGroupStrategyType from policy API Group instead. type FSGroupStrategyType string const ( - // container must have FSGroup of X applied. + // FSGroupStrategyMustRunAs meant that container must have FSGroup of X applied. + // Deprecated: use FSGroupStrategyMustRunAs from policy API Group instead. FSGroupStrategyMustRunAs FSGroupStrategyType = "MustRunAs" - // container may make requests for any FSGroup labels. + // FSGroupStrategyRunAsAny means that container may make requests for any FSGroup labels. + // Deprecated: use FSGroupStrategyRunAsAny from policy API Group instead. FSGroupStrategyRunAsAny FSGroupStrategyType = "RunAsAny" ) // SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. +// Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead. type SupplementalGroupsStrategyOptions struct { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. // +optional Rule SupplementalGroupsStrategyType `json:"rule,omitempty" protobuf:"bytes,1,opt,name=rule,casttype=SupplementalGroupsStrategyType"` - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. + // ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } // SupplementalGroupsStrategyType denotes strategy types for determining valid supplemental // groups for a SecurityContext. +// Deprecated: use SupplementalGroupsStrategyType from policy API Group instead. type SupplementalGroupsStrategyType string const ( - // container must run as a particular gid. + // SupplementalGroupsStrategyMustRunAs means that container must run as a particular gid. + // Deprecated: use SupplementalGroupsStrategyMustRunAs from policy API Group instead. SupplementalGroupsStrategyMustRunAs SupplementalGroupsStrategyType = "MustRunAs" - // container may make requests for any gid. + // SupplementalGroupsStrategyRunAsAny means that container may make requests for any gid. + // Deprecated: use SupplementalGroupsStrategyRunAsAny from policy API Group instead. SupplementalGroupsStrategyRunAsAny SupplementalGroupsStrategyType = "RunAsAny" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Pod Security Policy List is a list of PodSecurityPolicy objects. +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. +// Deprecated: use PodSecurityPolicyList from policy API Group instead. type PodSecurityPolicyList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata. @@ -1106,7 +1156,7 @@ type PodSecurityPolicyList struct { // +optional metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` - // Items is a list of schema objects. + // items is a list of schema objects. Items []PodSecurityPolicy `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -1256,22 +1306,26 @@ type IPBlock struct { // DEPRECATED 1.9 - This group version of NetworkPolicyPeer is deprecated by networking/v1/NetworkPolicyPeer. type NetworkPolicyPeer struct { - // Exactly one of the following must be specified. - - // This is a label selector which selects Pods in this namespace. - // This field follows standard label selector semantics. - // If present but empty, this selector selects all pods in this namespace. + // This is a label selector which selects Pods. This field follows standard label + // selector semantics; if present but empty, it selects all pods. + // + // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. // +optional PodSelector *metav1.LabelSelector `json:"podSelector,omitempty" protobuf:"bytes,1,opt,name=podSelector"` - // Selects Namespaces using cluster scoped-labels. This - // matches all pods in all namespaces selected by this label selector. - // This field follows standard label selector semantics. - // If present but empty, this selector selects all namespaces. + // Selects Namespaces using cluster-scoped labels. This field follows standard label + // selector semantics; if present but empty, it selects all namespaces. + // + // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. // +optional NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty" protobuf:"bytes,2,opt,name=namespaceSelector"` - // IPBlock defines policy on a particular IPBlock + // IPBlock defines policy on a particular IPBlock. If this field is set then + // neither of the other fields can be. // +optional IPBlock *IPBlock `json:"ipBlock,omitempty" protobuf:"bytes,3,rep,name=ipBlock"` } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go index 236d934fa..d261b4247 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,10 +26,10 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AllowedFlexVolume = map[string]string{ - "": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used.", - "driver": "Driver is the name of the Flexvolume driver.", + "": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used. Deprecated: use AllowedFlexVolume from policy API Group instead.", + "driver": "driver is the name of the Flexvolume driver.", } func (AllowedFlexVolume) SwaggerDoc() map[string]string { @@ -37,8 +37,9 @@ func (AllowedFlexVolume) SwaggerDoc() map[string]string { } var map_AllowedHostPath = map[string]string{ - "": "defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", - "pathPrefix": "is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined. Deprecated: use AllowedHostPath from policy API Group instead.", + "pathPrefix": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "readOnly": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", } func (AllowedHostPath) SwaggerDoc() map[string]string { @@ -229,9 +230,9 @@ func (DeploymentStrategy) SwaggerDoc() map[string]string { } var map_FSGroupStrategyOptions = map[string]string{ - "": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy.", - "rule": "Rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", - "ranges": "Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end.", + "": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use FSGroupStrategyOptions from policy API Group instead.", + "rule": "rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", + "ranges": "ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs.", } func (FSGroupStrategyOptions) SwaggerDoc() map[string]string { @@ -258,7 +259,7 @@ func (HTTPIngressRuleValue) SwaggerDoc() map[string]string { } var map_HostPortRange = map[string]string{ - "": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", + "": "HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined. Deprecated: use HostPortRange from policy API Group instead.", "min": "min is the start of the range, inclusive.", "max": "max is the end of the range, inclusive.", } @@ -268,9 +269,9 @@ func (HostPortRange) SwaggerDoc() map[string]string { } var map_IDRange = map[string]string{ - "": "ID Range provides a min/max of an allowed range of IDs.", - "min": "Min is the start of the range, inclusive.", - "max": "Max is the end of the range, inclusive.", + "": "IDRange provides a min/max of an allowed range of IDs. Deprecated: use IDRange from policy API Group instead.", + "min": "min is the start of the range, inclusive.", + "max": "max is the end of the range, inclusive.", } func (IDRange) SwaggerDoc() map[string]string { @@ -407,9 +408,9 @@ func (NetworkPolicyList) SwaggerDoc() map[string]string { var map_NetworkPolicyPeer = map[string]string{ "": "DEPRECATED 1.9 - This group version of NetworkPolicyPeer is deprecated by networking/v1/NetworkPolicyPeer.", - "podSelector": "This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace.", - "namespaceSelector": "Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces.", - "ipBlock": "IPBlock defines policy on a particular IPBlock", + "podSelector": "This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.\n\nIf NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy's own Namespace.", + "namespaceSelector": "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector.", + "ipBlock": "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.", } func (NetworkPolicyPeer) SwaggerDoc() map[string]string { @@ -439,7 +440,7 @@ func (NetworkPolicySpec) SwaggerDoc() map[string]string { } var map_PodSecurityPolicy = map[string]string{ - "": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", + "": "PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container. Deprecated: use PodSecurityPolicy from policy API Group instead.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "spec": "spec defines the policy enforced.", } @@ -449,9 +450,9 @@ func (PodSecurityPolicy) SwaggerDoc() map[string]string { } var map_PodSecurityPolicyList = map[string]string{ - "": "Pod Security Policy List is a list of PodSecurityPolicy objects.", + "": "PodSecurityPolicyList is a list of PodSecurityPolicy objects. Deprecated: use PodSecurityPolicyList from policy API Group instead.", "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "items": "Items is a list of schema objects.", + "items": "items is a list of schema objects.", } func (PodSecurityPolicyList) SwaggerDoc() map[string]string { @@ -459,25 +460,27 @@ func (PodSecurityPolicyList) SwaggerDoc() map[string]string { } var map_PodSecurityPolicySpec = map[string]string{ - "": "Pod Security Policy Spec defines the policy enforced.", + "": "PodSecurityPolicySpec defines the policy enforced. Deprecated: use PodSecurityPolicySpec from policy API Group instead.", "privileged": "privileged determines if a pod can request to be run as privileged.", - "defaultAddCapabilities": "DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list.", - "requiredDropCapabilities": "RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", - "allowedCapabilities": "AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities.", - "volumes": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.", + "defaultAddCapabilities": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.", + "requiredDropCapabilities": "requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", + "allowedCapabilities": "allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities.", + "volumes": "volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use '*'.", "hostNetwork": "hostNetwork determines if the policy allows the use of HostNetwork in the pod spec.", "hostPorts": "hostPorts determines which host port ranges are allowed to be exposed.", "hostPID": "hostPID determines if the policy allows the use of HostPID in the pod spec.", "hostIPC": "hostIPC determines if the policy allows the use of HostIPC in the pod spec.", "seLinux": "seLinux is the strategy that will dictate the allowable labels that may be set.", "runAsUser": "runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set.", - "supplementalGroups": "SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", - "fsGroup": "FSGroup is the strategy that will dictate what fs group is used by the SecurityContext.", - "readOnlyRootFilesystem": "ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", - "defaultAllowPrivilegeEscalation": "DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", - "allowPrivilegeEscalation": "AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", - "allowedHostPaths": "is a white list of allowed host paths. Empty indicates that all host paths may be used.", - "allowedFlexVolumes": "AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"Volumes\" field.", + "supplementalGroups": "supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", + "fsGroup": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.", + "readOnlyRootFilesystem": "readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", + "defaultAllowPrivilegeEscalation": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", + "allowPrivilegeEscalation": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", + "allowedHostPaths": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.", + "allowedFlexVolumes": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field.", + "allowedUnsafeSysctls": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "forbiddenSysctls": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", } func (PodSecurityPolicySpec) SwaggerDoc() map[string]string { @@ -581,9 +584,9 @@ func (RollingUpdateDeployment) SwaggerDoc() map[string]string { } var map_RunAsUserStrategyOptions = map[string]string{ - "": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.", - "rule": "Rule is the strategy that will dictate the allowable RunAsUser values that may be set.", - "ranges": "Ranges are the allowed ranges of uids that may be used.", + "": "RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use RunAsUserStrategyOptions from policy API Group instead.", + "rule": "rule is the strategy that will dictate the allowable RunAsUser values that may be set.", + "ranges": "ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs.", } func (RunAsUserStrategyOptions) SwaggerDoc() map[string]string { @@ -591,8 +594,8 @@ func (RunAsUserStrategyOptions) SwaggerDoc() map[string]string { } var map_SELinuxStrategyOptions = map[string]string{ - "": "SELinux Strategy Options defines the strategy type and any options used to create the strategy.", - "rule": "type is the strategy that will dictate the allowable labels that may be set.", + "": "SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. Deprecated: use SELinuxStrategyOptions from policy API Group instead.", + "rule": "rule is the strategy that will dictate the allowable labels that may be set.", "seLinuxOptions": "seLinuxOptions required to run as; required for MustRunAs More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/", } @@ -632,9 +635,9 @@ func (ScaleStatus) SwaggerDoc() map[string]string { } var map_SupplementalGroupsStrategyOptions = map[string]string{ - "": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy.", - "rule": "Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", - "ranges": "Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end.", + "": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead.", + "rule": "rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", + "ranges": "ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs.", } func (SupplementalGroupsStrategyOptions) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go index de1970c8f..8ec2b1ff7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1204,6 +1204,16 @@ func (in *PodSecurityPolicySpec) DeepCopyInto(out *PodSecurityPolicySpec) { *out = make([]AllowedFlexVolume, len(*in)) copy(*out, *in) } + if in.AllowedUnsafeSysctls != nil { + in, out := &in.AllowedUnsafeSysctls, &out.AllowedUnsafeSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ForbiddenSysctls != nil { + in, out := &in.ForbiddenSysctls, &out.ForbiddenSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go index f521979b7..ef2275443 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1036,41 +1036,41 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 575 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xcf, 0x6e, 0xd4, 0x30, - 0x10, 0xc6, 0x37, 0xdb, 0xbf, 0xeb, 0x05, 0xda, 0x1a, 0x0e, 0xab, 0x3d, 0xa4, 0xd5, 0x22, 0xa1, - 0x72, 0xc0, 0xa6, 0x05, 0xa1, 0xc2, 0x01, 0xd4, 0x20, 0x24, 0x38, 0x00, 0x92, 0xb9, 0xf5, 0x84, - 0x37, 0x3b, 0xcd, 0x9a, 0x4d, 0xec, 0x28, 0x76, 0x52, 0xf6, 0xc6, 0x23, 0xf0, 0x06, 0xbc, 0x4e, - 0x8f, 0x3d, 0xf6, 0x54, 0xd1, 0x70, 0xe4, 0x25, 0x50, 0x9c, 0x6c, 0x13, 0xba, 0x54, 0x68, 0x6f, - 0x9e, 0x19, 0x7f, 0xbf, 0x19, 0x7f, 0x63, 0xf4, 0x76, 0x72, 0xa0, 0x89, 0x50, 0x74, 0x92, 0x0e, - 0x21, 0x91, 0x60, 0x40, 0xd3, 0x0c, 0xe4, 0x48, 0x25, 0xb4, 0x2a, 0xf0, 0x58, 0x50, 0x11, 0xf1, - 0x00, 0x62, 0x15, 0x0a, 0x7f, 0x4a, 0xb3, 0x3d, 0x1e, 0xc6, 0x63, 0xbe, 0x47, 0x03, 0x90, 0x90, - 0x70, 0x03, 0x23, 0x12, 0x27, 0xca, 0x28, 0xbc, 0x5d, 0x0a, 0x08, 0x8f, 0x05, 0x69, 0x08, 0xc8, - 0x4c, 0xd0, 0x7f, 0x14, 0x08, 0x33, 0x4e, 0x87, 0xc4, 0x57, 0x11, 0x0d, 0x54, 0xa0, 0xa8, 0xd5, - 0x0d, 0xd3, 0x63, 0x1b, 0xd9, 0xc0, 0x9e, 0x4a, 0x5e, 0xff, 0x69, 0x3d, 0x40, 0xc4, 0xfd, 0xb1, - 0x90, 0x90, 0x4c, 0x69, 0x3c, 0x09, 0x8a, 0x84, 0xa6, 0x11, 0x18, 0x4e, 0xb3, 0xb9, 0x29, 0xfa, - 0xf4, 0x26, 0x55, 0x92, 0x4a, 0x23, 0x22, 0x98, 0x13, 0x3c, 0xfb, 0x9f, 0x40, 0xfb, 0x63, 0x88, - 0xf8, 0x9c, 0xee, 0xc9, 0x4d, 0xba, 0xd4, 0x88, 0x90, 0x0a, 0x69, 0xb4, 0x49, 0xae, 0x8b, 0x06, - 0x3f, 0xda, 0xa8, 0xfb, 0xae, 0xf0, 0x86, 0x41, 0x26, 0xe0, 0x04, 0x7f, 0x46, 0xeb, 0xc5, 0x43, - 0x46, 0xdc, 0xf0, 0x9e, 0xb3, 0xe3, 0xec, 0x76, 0xf7, 0x1f, 0x93, 0xda, 0xc6, 0x2b, 0x2e, 0x89, - 0x27, 0x41, 0x91, 0xd0, 0xa4, 0xb8, 0x4d, 0xb2, 0x3d, 0xf2, 0x71, 0xf8, 0x05, 0x7c, 0xf3, 0x1e, - 0x0c, 0xf7, 0xf0, 0xe9, 0xc5, 0x76, 0x2b, 0xbf, 0xd8, 0x46, 0x75, 0x8e, 0x5d, 0x51, 0x31, 0x43, - 0xcb, 0x3a, 0x06, 0xbf, 0xd7, 0x9e, 0xa3, 0xff, 0x73, 0x49, 0xa4, 0x31, 0xdd, 0xa7, 0x18, 0x7c, - 0xef, 0x56, 0x45, 0x5f, 0x2e, 0x22, 0x66, 0x59, 0xf8, 0x08, 0xad, 0x6a, 0xc3, 0x4d, 0xaa, 0x7b, - 0x4b, 0x96, 0xba, 0xbf, 0x10, 0xd5, 0x2a, 0xbd, 0x3b, 0x15, 0x77, 0xb5, 0x8c, 0x59, 0x45, 0x1c, - 0xbc, 0x42, 0xbd, 0xc6, 0xe5, 0xd7, 0x4a, 0x1a, 0x5e, 0x58, 0x50, 0x74, 0xc7, 0xf7, 0xd1, 0x8a, - 0xa5, 0x5b, 0xab, 0x3a, 0xde, 0xed, 0x0a, 0xb1, 0x52, 0x0a, 0xca, 0xda, 0xe0, 0x77, 0x1b, 0x6d, - 0x5c, 0x7b, 0x04, 0x8e, 0x10, 0xf2, 0x67, 0x24, 0xdd, 0x73, 0x76, 0x96, 0x76, 0xbb, 0xfb, 0xcf, - 0x17, 0x19, 0xfa, 0xaf, 0x39, 0x6a, 0xc7, 0xaf, 0xd2, 0x9a, 0x35, 0x1a, 0xe0, 0xaf, 0xa8, 0xcb, - 0xa5, 0x54, 0x86, 0x1b, 0xa1, 0xa4, 0xee, 0xb5, 0x6d, 0xbf, 0xc3, 0x45, 0xad, 0x27, 0x87, 0x35, - 0xe3, 0x8d, 0x34, 0xc9, 0xd4, 0xbb, 0x5b, 0xf5, 0xed, 0x36, 0x2a, 0xac, 0xd9, 0x0a, 0x53, 0xd4, - 0x91, 0x3c, 0x02, 0x1d, 0x73, 0x1f, 0xec, 0x72, 0x3a, 0xde, 0x56, 0x25, 0xea, 0x7c, 0x98, 0x15, - 0x58, 0x7d, 0xa7, 0xff, 0x12, 0x6d, 0x5e, 0x6f, 0x83, 0x37, 0xd1, 0xd2, 0x04, 0xa6, 0xa5, 0xc9, - 0xac, 0x38, 0xe2, 0x7b, 0x68, 0x25, 0xe3, 0x61, 0x0a, 0xf6, 0x17, 0x75, 0x58, 0x19, 0xbc, 0x68, - 0x1f, 0x38, 0x83, 0x63, 0xb4, 0x35, 0xb7, 0x5b, 0xfc, 0x10, 0xad, 0xf1, 0x30, 0x54, 0x27, 0x30, - 0xb2, 0x90, 0x75, 0x6f, 0xa3, 0x9a, 0x61, 0xed, 0xb0, 0x4c, 0xb3, 0x59, 0x1d, 0x3f, 0x40, 0xab, - 0x09, 0x70, 0xad, 0x64, 0x89, 0xae, 0xbf, 0x05, 0xb3, 0x59, 0x56, 0x55, 0x3d, 0x72, 0x7a, 0xe9, - 0xb6, 0xce, 0x2e, 0xdd, 0xd6, 0xf9, 0xa5, 0xdb, 0xfa, 0x96, 0xbb, 0xce, 0x69, 0xee, 0x3a, 0x67, - 0xb9, 0xeb, 0x9c, 0xe7, 0xae, 0xf3, 0x33, 0x77, 0x9d, 0xef, 0xbf, 0xdc, 0xd6, 0xd1, 0xfa, 0xcc, - 0xcb, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x2d, 0x62, 0x44, 0xd7, 0x04, 0x00, 0x00, + // 562 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x4f, 0x6f, 0xd3, 0x30, + 0x18, 0xc6, 0x9b, 0xee, 0x6f, 0x5d, 0x60, 0x9b, 0xe1, 0x10, 0xf5, 0x90, 0x4d, 0x45, 0x42, 0xe3, + 0x80, 0xcd, 0x26, 0x84, 0x06, 0x07, 0x50, 0x83, 0x90, 0xe0, 0x00, 0x48, 0xe6, 0xb6, 0x13, 0x6e, + 0xfa, 0x2e, 0x0d, 0x6d, 0xec, 0x28, 0x76, 0x32, 0x7a, 0xe3, 0x23, 0xf0, 0x0d, 0xf8, 0x3a, 0x3d, + 0xee, 0xb8, 0xd3, 0x44, 0xc3, 0x91, 0x2f, 0x81, 0xe2, 0xa4, 0x4d, 0x68, 0x41, 0xa8, 0xb7, 0xbc, + 0xef, 0xeb, 0xe7, 0xf7, 0x3e, 0x79, 0x6c, 0xf4, 0x66, 0x74, 0xa6, 0x48, 0x20, 0xe9, 0x28, 0xe9, + 0x43, 0x2c, 0x40, 0x83, 0xa2, 0x29, 0x88, 0x81, 0x8c, 0x69, 0x39, 0xe0, 0x51, 0x40, 0x83, 0x90, + 0xfb, 0x10, 0xc9, 0x71, 0xe0, 0x4d, 0x68, 0x7a, 0xc2, 0xc7, 0xd1, 0x90, 0x9f, 0x50, 0x1f, 0x04, + 0xc4, 0x5c, 0xc3, 0x80, 0x44, 0xb1, 0xd4, 0x12, 0x1f, 0x16, 0x02, 0xc2, 0xa3, 0x80, 0xd4, 0x04, + 0x64, 0x2e, 0xe8, 0x3c, 0xf2, 0x03, 0x3d, 0x4c, 0xfa, 0xc4, 0x93, 0x21, 0xf5, 0xa5, 0x2f, 0xa9, + 0xd1, 0xf5, 0x93, 0x0b, 0x53, 0x99, 0xc2, 0x7c, 0x15, 0xbc, 0xce, 0x93, 0xca, 0x40, 0xc8, 0xbd, + 0x61, 0x20, 0x20, 0x9e, 0xd0, 0x68, 0xe4, 0xe7, 0x0d, 0x45, 0x43, 0xd0, 0x9c, 0xa6, 0x2b, 0x2e, + 0x3a, 0xf4, 0x5f, 0xaa, 0x38, 0x11, 0x3a, 0x08, 0x61, 0x45, 0xf0, 0xf4, 0x7f, 0x02, 0xe5, 0x0d, + 0x21, 0xe4, 0xcb, 0xba, 0xee, 0xf7, 0x26, 0x6a, 0xbf, 0xcd, 0x7f, 0x93, 0x41, 0x1a, 0xc0, 0x25, + 0xfe, 0x84, 0x76, 0x73, 0x4f, 0x03, 0xae, 0xb9, 0x6d, 0x1d, 0x59, 0xc7, 0xed, 0xd3, 0xc7, 0xa4, + 0x4a, 0x64, 0x81, 0x26, 0xd1, 0xc8, 0xcf, 0x1b, 0x8a, 0xe4, 0xa7, 0x49, 0x7a, 0x42, 0x3e, 0xf4, + 0x3f, 0x83, 0xa7, 0xdf, 0x81, 0xe6, 0x2e, 0x9e, 0xde, 0x1c, 0x36, 0xb2, 0x9b, 0x43, 0x54, 0xf5, + 0xd8, 0x82, 0x8a, 0x19, 0xda, 0x54, 0x11, 0x78, 0x76, 0x73, 0x85, 0xfe, 0xd7, 0xbc, 0x49, 0xcd, + 0xdd, 0xc7, 0x08, 0x3c, 0xf7, 0x56, 0x49, 0xdf, 0xcc, 0x2b, 0x66, 0x58, 0xf8, 0x1c, 0x6d, 0x2b, + 0xcd, 0x75, 0xa2, 0xec, 0x0d, 0x43, 0x3d, 0x5d, 0x8b, 0x6a, 0x94, 0xee, 0x9d, 0x92, 0xbb, 0x5d, + 0xd4, 0xac, 0x24, 0x76, 0x5f, 0x22, 0xbb, 0x76, 0xf8, 0x95, 0x14, 0x9a, 0xe7, 0x11, 0xe4, 0xdb, + 0xf1, 0x7d, 0xb4, 0x65, 0xe8, 0x26, 0xaa, 0x96, 0x7b, 0xbb, 0x44, 0x6c, 0x15, 0x82, 0x62, 0xd6, + 0xfd, 0xd5, 0x44, 0x7b, 0x4b, 0x3f, 0x81, 0x43, 0x84, 0xbc, 0x39, 0x49, 0xd9, 0xd6, 0xd1, 0xc6, + 0x71, 0xfb, 0xf4, 0xd9, 0x3a, 0xa6, 0xff, 0xf0, 0x51, 0x25, 0xbe, 0x68, 0x2b, 0x56, 0x5b, 0x80, + 0xbf, 0xa0, 0x36, 0x17, 0x42, 0x6a, 0xae, 0x03, 0x29, 0x94, 0xdd, 0x34, 0xfb, 0x7a, 0xeb, 0x46, + 0x4f, 0x7a, 0x15, 0xe3, 0xb5, 0xd0, 0xf1, 0xc4, 0xbd, 0x5b, 0xee, 0x6d, 0xd7, 0x26, 0xac, 0xbe, + 0x0a, 0x53, 0xd4, 0x12, 0x3c, 0x04, 0x15, 0x71, 0x0f, 0xcc, 0xe5, 0xb4, 0xdc, 0x83, 0x52, 0xd4, + 0x7a, 0x3f, 0x1f, 0xb0, 0xea, 0x4c, 0xe7, 0x05, 0xda, 0x5f, 0x5e, 0x83, 0xf7, 0xd1, 0xc6, 0x08, + 0x26, 0x45, 0xc8, 0x2c, 0xff, 0xc4, 0xf7, 0xd0, 0x56, 0xca, 0xc7, 0x09, 0x98, 0x57, 0xd4, 0x62, + 0x45, 0xf1, 0xbc, 0x79, 0x66, 0x75, 0x2f, 0xd0, 0xc1, 0xca, 0xdd, 0xe2, 0x87, 0x68, 0x87, 0x8f, + 0xc7, 0xf2, 0x12, 0x06, 0x06, 0xb2, 0xeb, 0xee, 0x95, 0x1e, 0x76, 0x7a, 0x45, 0x9b, 0xcd, 0xe7, + 0xf8, 0x01, 0xda, 0x8e, 0x81, 0x2b, 0x29, 0x0a, 0x74, 0xf5, 0x2c, 0x98, 0xe9, 0xb2, 0x72, 0xea, + 0x92, 0xe9, 0xcc, 0x69, 0x5c, 0xcd, 0x9c, 0xc6, 0xf5, 0xcc, 0x69, 0x7c, 0xcd, 0x1c, 0x6b, 0x9a, + 0x39, 0xd6, 0x55, 0xe6, 0x58, 0xd7, 0x99, 0x63, 0xfd, 0xc8, 0x1c, 0xeb, 0xdb, 0x4f, 0xa7, 0x71, + 0xbe, 0x3b, 0xcf, 0xf2, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdb, 0xb6, 0xff, 0xb4, 0xa2, 0x04, + 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/generated.proto index a19967cbe..ffd9512a9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.imagepolicy.v1alpha1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go index f4b26f5e8..129d63d08 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_ImageReview = map[string]string{ "": "ImageReview checks if the set of images in a pod are allowed.", "spec": "Spec holds information about the pod being evaluated", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go index 50f314886..a41d89700 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/generated.pb.go index 05aaf1d9a..7b1c04b29 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1813,57 +1813,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 829 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x4d, 0x6f, 0x1b, 0x45, - 0x18, 0xf6, 0x3a, 0xce, 0x47, 0x27, 0x94, 0x92, 0x41, 0x08, 0x2b, 0x88, 0x75, 0xd8, 0x0b, 0x41, - 0x55, 0x67, 0x71, 0x8b, 0x10, 0x37, 0xc4, 0x42, 0x29, 0x96, 0x9a, 0xc4, 0x9a, 0xf4, 0x02, 0x02, - 0x89, 0xf5, 0xfa, 0xcd, 0x66, 0x6a, 0xef, 0xce, 0x6a, 0x66, 0x6c, 0x92, 0x1b, 0x3f, 0x81, 0x1f, - 0xc2, 0x91, 0x1b, 0x87, 0x72, 0xcc, 0xb1, 0xc7, 0x9e, 0x56, 0x64, 0xf9, 0x17, 0x39, 0xa1, 0x99, - 0x1d, 0x7b, 0xfd, 0x51, 0x0b, 0xb7, 0xa2, 0x37, 0xcf, 0x3b, 0xcf, 0xf3, 0xbc, 0x1f, 0xf3, 0xf8, - 0x5d, 0xf4, 0xd5, 0xe0, 0x0b, 0x49, 0x18, 0xf7, 0x07, 0xa3, 0x1e, 0x88, 0x14, 0x14, 0x48, 0x7f, - 0x0c, 0x69, 0x9f, 0x0b, 0xdf, 0x5e, 0x84, 0x19, 0xf3, 0x53, 0x50, 0xbf, 0x70, 0x31, 0x60, 0x69, - 0xec, 0x8f, 0xdb, 0x7e, 0x0c, 0x29, 0x88, 0x50, 0x41, 0x9f, 0x64, 0x82, 0x2b, 0x8e, 0x9b, 0x25, - 0x92, 0x84, 0x19, 0x23, 0x15, 0x92, 0x8c, 0xdb, 0xfb, 0xf7, 0x62, 0xa6, 0xce, 0x47, 0x3d, 0x12, - 0xf1, 0xc4, 0x8f, 0x79, 0xcc, 0x7d, 0x43, 0xe8, 0x8d, 0xce, 0xcc, 0xc9, 0x1c, 0xcc, 0xaf, 0x52, - 0x68, 0xdf, 0x9b, 0x49, 0x19, 0x71, 0x01, 0x2f, 0x49, 0xb6, 0x7f, 0x6f, 0x06, 0x03, 0x17, 0x0a, - 0x52, 0xc9, 0x78, 0x2a, 0xfd, 0x71, 0xbb, 0x07, 0x2a, 0x5c, 0x86, 0x7f, 0x32, 0x03, 0xcf, 0xf8, - 0x90, 0x45, 0x97, 0x2b, 0xa1, 0x9f, 0x55, 0xd0, 0x24, 0x8c, 0xce, 0x59, 0x0a, 0xe2, 0xd2, 0xcf, - 0x06, 0xb1, 0x0e, 0x48, 0x3f, 0x01, 0x15, 0xbe, 0xac, 0x1e, 0x7f, 0x15, 0x4b, 0x8c, 0x52, 0xc5, - 0x12, 0x58, 0x22, 0x7c, 0xfe, 0x5f, 0x04, 0x19, 0x9d, 0x43, 0x12, 0x2e, 0xf1, 0x1e, 0xac, 0xe2, - 0x8d, 0x14, 0x1b, 0xfa, 0x2c, 0x55, 0x52, 0x89, 0x45, 0x92, 0x77, 0x82, 0xb6, 0x3b, 0xdd, 0x60, - 0xc8, 0xa3, 0x01, 0x3e, 0x40, 0x8d, 0x88, 0xf5, 0x45, 0xd3, 0x39, 0x70, 0x0e, 0x6f, 0x05, 0x6f, - 0x5d, 0xe5, 0xad, 0x5a, 0x91, 0xb7, 0x1a, 0x5f, 0x77, 0xbe, 0xa1, 0xd4, 0xdc, 0x60, 0x0f, 0x6d, - 0xc1, 0x45, 0x04, 0x99, 0x6a, 0xd6, 0x0f, 0x36, 0x0e, 0x6f, 0x05, 0xa8, 0xc8, 0x5b, 0x5b, 0x0f, - 0x4d, 0x84, 0xda, 0x1b, 0xef, 0x2f, 0x07, 0xdd, 0x3e, 0x2e, 0xdf, 0xb8, 0x6b, 0xc6, 0x89, 0x7f, - 0x46, 0x3b, 0x7a, 0x36, 0xfd, 0x50, 0x85, 0x46, 0x7b, 0xf7, 0xfe, 0xa7, 0xa4, 0x32, 0xc4, 0xb4, - 0x54, 0x92, 0x0d, 0x62, 0x1d, 0x90, 0x44, 0xa3, 0xc9, 0xb8, 0x4d, 0x4e, 0x7a, 0x4f, 0x21, 0x52, - 0x47, 0xa0, 0xc2, 0x00, 0xdb, 0x6a, 0x50, 0x15, 0xa3, 0x53, 0x55, 0x7c, 0x84, 0x1a, 0x32, 0x83, - 0xa8, 0x59, 0x37, 0xea, 0x77, 0xc9, 0x2a, 0xbb, 0x91, 0xb9, 0xc2, 0x4e, 0x33, 0x88, 0xaa, 0x36, - 0xf5, 0x89, 0x1a, 0x19, 0xef, 0x0f, 0x07, 0xbd, 0x3f, 0x87, 0x7c, 0x18, 0x0b, 0x90, 0x92, 0x8e, - 0x86, 0x80, 0xbb, 0x68, 0x33, 0xe3, 0x42, 0xc9, 0xa6, 0x73, 0xb0, 0xf1, 0x0a, 0xb9, 0xba, 0x5c, - 0xa8, 0xe0, 0xb6, 0xcd, 0xb5, 0xa9, 0x4f, 0x92, 0x96, 0x42, 0xf8, 0x11, 0xaa, 0x2b, 0x6e, 0x06, - 0xfa, 0x0a, 0x72, 0x00, 0x22, 0x40, 0x56, 0xae, 0xfe, 0x84, 0xd3, 0xba, 0xe2, 0xde, 0x9f, 0x0e, - 0x6a, 0xce, 0xa1, 0x3a, 0xe9, 0x9b, 0xac, 0xfb, 0x08, 0x35, 0xce, 0x04, 0x4f, 0x5e, 0xa7, 0xf2, - 0xe9, 0xd0, 0xbf, 0x15, 0x3c, 0xa1, 0x46, 0xc6, 0x7b, 0xe6, 0xa0, 0xbd, 0x39, 0xe4, 0x63, 0x26, - 0x15, 0xfe, 0x71, 0xc9, 0x3b, 0x64, 0x3d, 0xef, 0x68, 0xb6, 0x71, 0xce, 0x3b, 0x36, 0xd7, 0xce, - 0x24, 0x32, 0xe3, 0x9b, 0xc7, 0x68, 0x93, 0x29, 0x48, 0xa4, 0xed, 0xe1, 0xe3, 0x35, 0x7b, 0xa8, - 0x06, 0xd2, 0xd1, 0x6c, 0x5a, 0x8a, 0x78, 0xcf, 0xea, 0x0b, 0x1d, 0xe8, 0x5e, 0xf1, 0x19, 0xda, - 0xcd, 0x78, 0xff, 0x14, 0x86, 0x10, 0x29, 0x2e, 0x6c, 0x13, 0x0f, 0xd6, 0x6c, 0x22, 0xec, 0xc1, - 0x70, 0x42, 0x0d, 0xee, 0x14, 0x79, 0x6b, 0xb7, 0x5b, 0x69, 0xd1, 0x59, 0x61, 0x7c, 0x81, 0xf6, - 0xd2, 0x30, 0x01, 0x99, 0x85, 0x11, 0x4c, 0xb3, 0xd5, 0x5f, 0x3f, 0xdb, 0x7b, 0x45, 0xde, 0xda, - 0x3b, 0x5e, 0x54, 0xa4, 0xcb, 0x49, 0xf0, 0x77, 0x68, 0x9b, 0x65, 0x66, 0x85, 0x34, 0x37, 0x4c, - 0xbe, 0x8f, 0x56, 0xcf, 0xd1, 0xee, 0x9a, 0x60, 0xb7, 0xc8, 0x5b, 0x93, 0xc5, 0x43, 0x27, 0x74, - 0xef, 0xf7, 0x45, 0x0f, 0x68, 0xc3, 0xe1, 0x47, 0x68, 0xc7, 0xec, 0xaa, 0x88, 0x0f, 0xed, 0x6e, - 0xba, 0xab, 0xdf, 0xb3, 0x6b, 0x63, 0x37, 0x79, 0xeb, 0x83, 0xe5, 0xcf, 0x02, 0x99, 0x5c, 0xd3, - 0x29, 0x19, 0x1f, 0xa3, 0x86, 0xb6, 0xae, 0x9d, 0xca, 0xea, 0x25, 0xa4, 0xf7, 0x25, 0x29, 0xf7, - 0x25, 0xe9, 0xa4, 0xea, 0x44, 0x9c, 0x2a, 0xc1, 0xd2, 0x38, 0xd8, 0xd1, 0x96, 0xd5, 0x25, 0x51, - 0xa3, 0xe3, 0xdd, 0x2c, 0x3e, 0xb8, 0xde, 0x21, 0xf8, 0xe9, 0xff, 0xf6, 0xe0, 0xef, 0x5a, 0x9b, - 0xad, 0x7e, 0xf4, 0x9f, 0xd0, 0x36, 0x2b, 0xff, 0xe4, 0xd6, 0xc2, 0xf7, 0xd7, 0xb4, 0xf0, 0xcc, - 0x6a, 0x08, 0xee, 0xd8, 0x34, 0xdb, 0x93, 0xe0, 0x44, 0x13, 0x7f, 0x8f, 0xb6, 0xa0, 0x54, 0xdf, - 0x30, 0xea, 0xed, 0x35, 0xd5, 0xab, 0x7d, 0x19, 0xbc, 0x6d, 0xc5, 0xb7, 0x6c, 0xcc, 0x0a, 0xe2, - 0x2f, 0xf5, 0x94, 0x34, 0xf6, 0xc9, 0x65, 0x06, 0xb2, 0xd9, 0x30, 0xdf, 0x93, 0x0f, 0xcb, 0x66, - 0xa7, 0xe1, 0x9b, 0xbc, 0x85, 0xaa, 0x23, 0x9d, 0x65, 0x04, 0x87, 0x57, 0xd7, 0x6e, 0xed, 0xf9, - 0xb5, 0x5b, 0x7b, 0x71, 0xed, 0xd6, 0x7e, 0x2d, 0x5c, 0xe7, 0xaa, 0x70, 0x9d, 0xe7, 0x85, 0xeb, - 0xbc, 0x28, 0x5c, 0xe7, 0xef, 0xc2, 0x75, 0x7e, 0xfb, 0xc7, 0xad, 0xfd, 0x50, 0x1f, 0xb7, 0xff, - 0x0d, 0x00, 0x00, 0xff, 0xff, 0x48, 0x47, 0x24, 0xc9, 0xc1, 0x08, 0x00, 0x00, + // 804 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xcf, 0x8f, 0xdb, 0x44, + 0x14, 0x8e, 0x9d, 0x6c, 0x92, 0x4e, 0x28, 0x65, 0x07, 0x21, 0xac, 0x45, 0xd8, 0xc1, 0x17, 0x56, + 0xaa, 0x18, 0x93, 0x16, 0x21, 0x6e, 0x08, 0x43, 0x29, 0x91, 0xba, 0xbb, 0xd1, 0x6c, 0x2f, 0x20, + 0x90, 0x70, 0x9c, 0x59, 0xef, 0x34, 0xb1, 0xc7, 0x1a, 0x4f, 0x42, 0xf7, 0xc6, 0x9f, 0xc0, 0x1f, + 0xc2, 0x91, 0x1b, 0x87, 0x72, 0xdc, 0x63, 0x8f, 0x3d, 0x59, 0xac, 0xf9, 0x2f, 0xf6, 0x84, 0x66, + 0x3c, 0x89, 0xf3, 0xa3, 0x11, 0xd9, 0x15, 0xbd, 0x65, 0xde, 0xbc, 0xef, 0x7b, 0xf3, 0xde, 0xfb, + 0xf2, 0x19, 0x7c, 0x35, 0xfe, 0x22, 0x43, 0x94, 0x79, 0xe3, 0xe9, 0x90, 0xf0, 0x84, 0x08, 0x92, + 0x79, 0x33, 0x92, 0x8c, 0x18, 0xf7, 0xf4, 0x45, 0x90, 0x52, 0x2f, 0x21, 0xe2, 0x17, 0xc6, 0xc7, + 0x34, 0x89, 0xbc, 0x59, 0xcf, 0x8b, 0x48, 0x42, 0x78, 0x20, 0xc8, 0x08, 0xa5, 0x9c, 0x09, 0x06, + 0xad, 0x32, 0x13, 0x05, 0x29, 0x45, 0x55, 0x26, 0x9a, 0xf5, 0x0e, 0x3e, 0x89, 0xa8, 0x38, 0x9f, + 0x0e, 0x51, 0xc8, 0x62, 0x2f, 0x62, 0x11, 0xf3, 0x14, 0x60, 0x38, 0x3d, 0x53, 0x27, 0x75, 0x50, + 0xbf, 0x4a, 0xa2, 0x03, 0x77, 0xa9, 0x64, 0xc8, 0x38, 0x79, 0x4d, 0xb1, 0x83, 0xcf, 0xaa, 0x9c, + 0x38, 0x08, 0xcf, 0x69, 0x42, 0xf8, 0x85, 0x97, 0x8e, 0x23, 0x19, 0xc8, 0xbc, 0x98, 0x88, 0xe0, + 0x75, 0x28, 0x6f, 0x1b, 0x8a, 0x4f, 0x13, 0x41, 0x63, 0xb2, 0x01, 0xf8, 0xfc, 0xbf, 0x00, 0x59, + 0x78, 0x4e, 0xe2, 0x60, 0x03, 0xf7, 0x70, 0x1b, 0x6e, 0x2a, 0xe8, 0xc4, 0xa3, 0x89, 0xc8, 0x04, + 0x5f, 0x07, 0xb9, 0x27, 0xa0, 0xd5, 0x1f, 0xf8, 0x13, 0x16, 0x8e, 0x61, 0x17, 0x34, 0x42, 0x3a, + 0xe2, 0x96, 0xd1, 0x35, 0x0e, 0xef, 0xf8, 0x6f, 0x5d, 0xe6, 0x4e, 0xad, 0xc8, 0x9d, 0xc6, 0xd7, + 0xfd, 0x6f, 0x30, 0x56, 0x37, 0xd0, 0x05, 0x4d, 0xf2, 0x3c, 0x24, 0xa9, 0xb0, 0xcc, 0x6e, 0xfd, + 0xf0, 0x8e, 0x0f, 0x8a, 0xdc, 0x69, 0x3e, 0x52, 0x11, 0xac, 0x6f, 0xdc, 0xbf, 0x0c, 0x70, 0xf7, + 0xb8, 0xdc, 0xc4, 0x80, 0x4d, 0x68, 0x78, 0x01, 0x7f, 0x06, 0x6d, 0x39, 0x9b, 0x51, 0x20, 0x02, + 0xc5, 0xdd, 0x79, 0xf0, 0x29, 0xaa, 0xd6, 0xb6, 0x78, 0x2a, 0x4a, 0xc7, 0x91, 0x0c, 0x64, 0x48, + 0x66, 0xa3, 0x59, 0x0f, 0x9d, 0x0c, 0x9f, 0x91, 0x50, 0x1c, 0x11, 0x11, 0xf8, 0x50, 0xbf, 0x06, + 0x54, 0x31, 0xbc, 0x60, 0x85, 0x47, 0xa0, 0x91, 0xa5, 0x24, 0xb4, 0x4c, 0xc5, 0x7e, 0x1f, 0x6d, + 0x13, 0x05, 0x5a, 0x79, 0xd8, 0x69, 0x4a, 0xc2, 0xaa, 0x4d, 0x79, 0xc2, 0x8a, 0xc6, 0xfd, 0xc3, + 0x00, 0xef, 0xaf, 0x64, 0x3e, 0x8a, 0x38, 0xc9, 0x32, 0x3c, 0x9d, 0x10, 0x38, 0x00, 0x7b, 0x29, + 0xe3, 0x22, 0xb3, 0x8c, 0x6e, 0xfd, 0x06, 0xb5, 0x06, 0x8c, 0x0b, 0xff, 0xae, 0xae, 0xb5, 0x27, + 0x4f, 0x19, 0x2e, 0x89, 0xe0, 0x63, 0x60, 0x0a, 0xa6, 0x06, 0x7a, 0x03, 0x3a, 0x42, 0xb8, 0x0f, + 0x34, 0x9d, 0xf9, 0x94, 0x61, 0x53, 0x30, 0xf7, 0x4f, 0x03, 0x58, 0x2b, 0x59, 0xfd, 0xe4, 0x4d, + 0xbe, 0xfb, 0x08, 0x34, 0xce, 0x38, 0x8b, 0x6f, 0xf3, 0xf2, 0xc5, 0xd0, 0xbf, 0xe5, 0x2c, 0xc6, + 0x8a, 0xc6, 0x7d, 0x61, 0x80, 0xfd, 0x95, 0xcc, 0x27, 0x34, 0x13, 0xf0, 0xc7, 0x0d, 0xed, 0xa0, + 0xdd, 0xb4, 0x23, 0xd1, 0x4a, 0x39, 0xef, 0xe8, 0x5a, 0xed, 0x79, 0x64, 0x49, 0x37, 0x4f, 0xc0, + 0x1e, 0x15, 0x24, 0xce, 0x74, 0x0f, 0x1f, 0xef, 0xd8, 0x43, 0x35, 0x90, 0xbe, 0x44, 0xe3, 0x92, + 0xc4, 0x7d, 0x61, 0xae, 0x75, 0x20, 0x7b, 0x85, 0x67, 0xa0, 0x93, 0xb2, 0xd1, 0x29, 0x99, 0x90, + 0x50, 0x30, 0xae, 0x9b, 0x78, 0xb8, 0x63, 0x13, 0xc1, 0x90, 0x4c, 0xe6, 0x50, 0xff, 0x5e, 0x91, + 0x3b, 0x9d, 0x41, 0xc5, 0x85, 0x97, 0x89, 0xe1, 0x73, 0xb0, 0x9f, 0x04, 0x31, 0xc9, 0xd2, 0x20, + 0x24, 0x8b, 0x6a, 0xe6, 0xed, 0xab, 0xbd, 0x57, 0xe4, 0xce, 0xfe, 0xf1, 0x3a, 0x23, 0xde, 0x2c, + 0x02, 0xbf, 0x03, 0x2d, 0x9a, 0x2a, 0x0b, 0xb1, 0xea, 0xaa, 0xde, 0x47, 0xdb, 0xe7, 0xa8, 0xbd, + 0xc6, 0xef, 0x14, 0xb9, 0x33, 0x37, 0x1e, 0x3c, 0x87, 0xbb, 0xbf, 0xaf, 0x6b, 0x40, 0x0a, 0x0e, + 0x3e, 0x06, 0x6d, 0xe5, 0x55, 0x21, 0x9b, 0x68, 0x6f, 0xba, 0x2f, 0xf7, 0x39, 0xd0, 0xb1, 0xeb, + 0xdc, 0xf9, 0x60, 0xd3, 0xbc, 0xd1, 0xfc, 0x1a, 0x2f, 0xc0, 0xf0, 0x18, 0x34, 0xa4, 0x74, 0xf5, + 0x54, 0xb6, 0x9b, 0x90, 0xf4, 0x4b, 0x54, 0xfa, 0x25, 0xea, 0x27, 0xe2, 0x84, 0x9f, 0x0a, 0x4e, + 0x93, 0xc8, 0x6f, 0x4b, 0xc9, 0xca, 0x27, 0x61, 0xc5, 0xe3, 0x5e, 0xaf, 0x2f, 0x5c, 0x7a, 0x08, + 0x7c, 0xf6, 0xbf, 0x2d, 0xfc, 0x5d, 0x2d, 0xb3, 0xed, 0x4b, 0xff, 0x09, 0xb4, 0x68, 0xf9, 0x27, + 0xd7, 0x12, 0x7e, 0xb0, 0xa3, 0x84, 0x97, 0xac, 0xc1, 0xbf, 0xa7, 0xcb, 0xb4, 0xe6, 0xc1, 0x39, + 0x27, 0xfc, 0x1e, 0x34, 0x49, 0xc9, 0x5e, 0x57, 0xec, 0xbd, 0x1d, 0xd9, 0x2b, 0xbf, 0xf4, 0xdf, + 0xd6, 0xe4, 0x4d, 0x1d, 0xd3, 0x84, 0xf0, 0x4b, 0x39, 0x25, 0x99, 0xfb, 0xf4, 0x22, 0x25, 0x99, + 0xd5, 0x50, 0xdf, 0x93, 0x0f, 0xcb, 0x66, 0x17, 0xe1, 0xeb, 0xdc, 0x01, 0xd5, 0x11, 0x2f, 0x23, + 0xfc, 0xc3, 0xcb, 0x2b, 0xbb, 0xf6, 0xf2, 0xca, 0xae, 0xbd, 0xba, 0xb2, 0x6b, 0xbf, 0x16, 0xb6, + 0x71, 0x59, 0xd8, 0xc6, 0xcb, 0xc2, 0x36, 0x5e, 0x15, 0xb6, 0xf1, 0x77, 0x61, 0x1b, 0xbf, 0xfd, + 0x63, 0xd7, 0x7e, 0x30, 0x67, 0xbd, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x7b, 0xc9, 0x59, + 0x67, 0x08, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/generated.proto index 06365ebe3..eacf0ed90 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,8 +22,6 @@ syntax = 'proto2'; package k8s.io.api.networking.v1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/api/extensions/v1beta1/generated.proto"; -import "k8s.io/api/policy/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; @@ -111,22 +109,29 @@ message NetworkPolicyList { repeated NetworkPolicy items = 2; } -// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields -// must be specified. +// NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of +// fields are allowed message NetworkPolicyPeer { - // This is a label selector which selects Pods in this namespace. This field - // follows standard label selector semantics. If present but empty, this selector - // selects all pods in this namespace. + // This is a label selector which selects Pods. This field follows standard label + // selector semantics; if present but empty, it selects all pods. + // + // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector podSelector = 1; - // Selects Namespaces using cluster scoped-labels. This matches all pods in all - // namespaces selected by this label selector. This field follows standard label - // selector semantics. If present but empty, this selector selects all namespaces. + // Selects Namespaces using cluster-scoped labels. This field follows standard label + // selector semantics; if present but empty, it selects all namespaces. + // + // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector namespaceSelector = 2; - // IPBlock defines policy on a particular IPBlock + // IPBlock defines policy on a particular IPBlock. If this field is set then + // neither of the other fields can be. // +optional optional IPBlock ipBlock = 3; } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/types.go index 57bc8005e..e1b81fdc7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/types.go @@ -161,22 +161,29 @@ type IPBlock struct { Except []string `json:"except,omitempty" protobuf:"bytes,2,rep,name=except"` } -// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields -// must be specified. +// NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of +// fields are allowed type NetworkPolicyPeer struct { - // This is a label selector which selects Pods in this namespace. This field - // follows standard label selector semantics. If present but empty, this selector - // selects all pods in this namespace. + // This is a label selector which selects Pods. This field follows standard label + // selector semantics; if present but empty, it selects all pods. + // + // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. // +optional PodSelector *metav1.LabelSelector `json:"podSelector,omitempty" protobuf:"bytes,1,opt,name=podSelector"` - // Selects Namespaces using cluster scoped-labels. This matches all pods in all - // namespaces selected by this label selector. This field follows standard label - // selector semantics. If present but empty, this selector selects all namespaces. + // Selects Namespaces using cluster-scoped labels. This field follows standard label + // selector semantics; if present but empty, it selects all namespaces. + // + // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects + // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. + // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. // +optional NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty" protobuf:"bytes,2,opt,name=namespaceSelector"` - // IPBlock defines policy on a particular IPBlock + // IPBlock defines policy on a particular IPBlock. If this field is set then + // neither of the other fields can be. // +optional IPBlock *IPBlock `json:"ipBlock,omitempty" protobuf:"bytes,3,rep,name=ipBlock"` } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/types_swagger_doc_generated.go index ad0bafeac..af2553a9d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_IPBlock = map[string]string{ "": "IPBlock describes a particular CIDR (Ex. \"192.168.1.1/24\") that is allowed to the pods matched by a NetworkPolicySpec's podSelector. The except entry describes CIDRs that should not be included within this rule.", "cidr": "CIDR is a string representing the IP Block Valid examples are \"192.168.1.1/24\"", @@ -78,10 +78,10 @@ func (NetworkPolicyList) SwaggerDoc() map[string]string { } var map_NetworkPolicyPeer = map[string]string{ - "": "NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields must be specified.", - "podSelector": "This is a label selector which selects Pods in this namespace. This field follows standard label selector semantics. If present but empty, this selector selects all pods in this namespace.", - "namespaceSelector": "Selects Namespaces using cluster scoped-labels. This matches all pods in all namespaces selected by this label selector. This field follows standard label selector semantics. If present but empty, this selector selects all namespaces.", - "ipBlock": "IPBlock defines policy on a particular IPBlock", + "": "NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of fields are allowed", + "podSelector": "This is a label selector which selects Pods. This field follows standard label selector semantics; if present but empty, it selects all pods.\n\nIf NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects the Pods matching PodSelector in the policy's own Namespace.", + "namespaceSelector": "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector.", + "ipBlock": "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.", } func (NetworkPolicyPeer) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/zz_generated.deepcopy.go index 8a7c1530e..0037638a8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/networking/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/generated.pb.go index 24bbe8975..505fb0e03 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -200,6 +200,14 @@ func (m *AllowedHostPath) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.PathPrefix))) i += copy(dAtA[i:], m.PathPrefix) + dAtA[i] = 0x10 + i++ + if m.ReadOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -794,6 +802,40 @@ func (m *PodSecurityPolicySpec) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + dAtA[i] = 0x9a + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + dAtA[i] = 0xa2 + i++ + dAtA[i] = 0x1 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } return i, nil } @@ -937,6 +979,7 @@ func (m *AllowedHostPath) Size() (n int) { _ = l l = len(m.PathPrefix) n += 1 + l + sovGenerated(uint64(l)) + n += 2 return n } @@ -1134,6 +1177,18 @@ func (m *PodSecurityPolicySpec) Size() (n int) { n += 2 + l + sovGenerated(uint64(l)) } } + if len(m.AllowedUnsafeSysctls) > 0 { + for _, s := range m.AllowedUnsafeSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } + if len(m.ForbiddenSysctls) > 0 { + for _, s := range m.ForbiddenSysctls { + l = len(s) + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -1206,6 +1261,7 @@ func (this *AllowedHostPath) String() string { } s := strings.Join([]string{`&AllowedHostPath{`, `PathPrefix:` + fmt.Sprintf("%v", this.PathPrefix) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, `}`, }, "") return s @@ -1359,6 +1415,8 @@ func (this *PodSecurityPolicySpec) String() string { `AllowPrivilegeEscalation:` + valueToStringGenerated(this.AllowPrivilegeEscalation) + `,`, `AllowedHostPaths:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedHostPaths), "AllowedHostPath", "AllowedHostPath", 1), `&`, ``, 1) + `,`, `AllowedFlexVolumes:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedFlexVolumes), "AllowedFlexVolume", "AllowedFlexVolume", 1), `&`, ``, 1) + `,`, + `AllowedUnsafeSysctls:` + fmt.Sprintf("%v", this.AllowedUnsafeSysctls) + `,`, + `ForbiddenSysctls:` + fmt.Sprintf("%v", this.ForbiddenSysctls) + `,`, `}`, }, "") return s @@ -1541,6 +1599,26 @@ func (m *AllowedHostPath) Unmarshal(dAtA []byte) error { } m.PathPrefix = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.ReadOnly = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -3348,6 +3426,64 @@ func (m *PodSecurityPolicySpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedUnsafeSysctls", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedUnsafeSysctls = append(m.AllowedUnsafeSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ForbiddenSysctls", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ForbiddenSysctls = append(m.ForbiddenSysctls, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -3811,106 +3947,110 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1605 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4f, 0x6f, 0x1b, 0xb9, - 0x15, 0xf7, 0x58, 0xb6, 0x65, 0xd3, 0xf2, 0x3f, 0xba, 0x76, 0x27, 0x46, 0x23, 0x35, 0x0a, 0x50, - 0xa4, 0x41, 0x33, 0x8a, 0x9d, 0xa4, 0x35, 0x9a, 0xb6, 0xa8, 0xc7, 0xf2, 0xbf, 0x20, 0xae, 0x55, - 0x2a, 0x09, 0xda, 0x22, 0x2d, 0x4a, 0x69, 0x68, 0x89, 0xf1, 0x68, 0x66, 0x4a, 0x72, 0x14, 0xe9, - 0xd6, 0x43, 0x0f, 0x3d, 0xf6, 0x0b, 0xf4, 0x13, 0x14, 0x3d, 0xed, 0x97, 0xf0, 0x02, 0x8b, 0x45, - 0x8e, 0xc1, 0x1e, 0x84, 0x8d, 0x16, 0xfb, 0x25, 0x72, 0x5a, 0x0c, 0xc5, 0x91, 0x34, 0x33, 0x92, - 0x1c, 0x07, 0x48, 0x6e, 0x1a, 0xbe, 0xdf, 0xef, 0xf7, 0x1e, 0x1f, 0xc9, 0xc7, 0x47, 0x01, 0xf3, - 0x62, 0x97, 0x1b, 0xd4, 0x2d, 0x5c, 0xf8, 0x15, 0xc2, 0x1c, 0x22, 0x08, 0x2f, 0x34, 0x89, 0x63, - 0xb9, 0xac, 0xa0, 0x0c, 0xd8, 0xa3, 0x05, 0xcf, 0xb5, 0x69, 0xb5, 0x5d, 0x68, 0x6e, 0x57, 0x88, - 0xc0, 0xdb, 0x85, 0x1a, 0x71, 0x08, 0xc3, 0x82, 0x58, 0x86, 0xc7, 0x5c, 0xe1, 0xc2, 0x1b, 0x3d, - 0xa8, 0x81, 0x3d, 0x6a, 0xf4, 0xa0, 0x86, 0x82, 0x6e, 0xdd, 0xab, 0x51, 0x51, 0xf7, 0x2b, 0x46, - 0xd5, 0x6d, 0x14, 0x6a, 0x6e, 0xcd, 0x2d, 0x48, 0x46, 0xc5, 0x3f, 0x97, 0x5f, 0xf2, 0x43, 0xfe, - 0xea, 0x29, 0x6d, 0xe5, 0x87, 0x9c, 0x56, 0x5d, 0x46, 0x0a, 0xcd, 0x84, 0xb7, 0xad, 0x87, 0x03, - 0x4c, 0x03, 0x57, 0xeb, 0xd4, 0x21, 0xac, 0x5d, 0xf0, 0x2e, 0x6a, 0xc1, 0x00, 0x2f, 0x34, 0x88, - 0xc0, 0xa3, 0x58, 0x85, 0x71, 0x2c, 0xe6, 0x3b, 0x82, 0x36, 0x48, 0x82, 0xf0, 0xcb, 0xab, 0x08, - 0xbc, 0x5a, 0x27, 0x0d, 0x9c, 0xe0, 0x3d, 0x18, 0xc7, 0xf3, 0x05, 0xb5, 0x0b, 0xd4, 0x11, 0x5c, - 0xb0, 0x38, 0x29, 0xff, 0x18, 0xac, 0xed, 0xd9, 0xb6, 0xfb, 0x9a, 0x58, 0x87, 0x36, 0x69, 0xbd, - 0x70, 0x6d, 0xbf, 0x41, 0xe0, 0xcf, 0xc0, 0x9c, 0xc5, 0x68, 0x93, 0x30, 0x5d, 0xfb, 0xa9, 0x76, - 0x67, 0xc1, 0x5c, 0xbe, 0xec, 0xe4, 0xa6, 0xba, 0x9d, 0xdc, 0x5c, 0x51, 0x8e, 0x22, 0x65, 0xcd, - 0x1f, 0x80, 0x15, 0x45, 0x3e, 0x76, 0xb9, 0x28, 0x61, 0x51, 0x87, 0x3b, 0x00, 0x78, 0x58, 0xd4, - 0x4b, 0x8c, 0x9c, 0xd3, 0x96, 0xa2, 0x43, 0x45, 0x07, 0xa5, 0xbe, 0x05, 0x0d, 0xa1, 0xf2, 0xdf, - 0x68, 0x60, 0xfe, 0xa0, 0x49, 0xab, 0x82, 0xba, 0x0e, 0xfc, 0x3b, 0x98, 0x0f, 0x32, 0x69, 0x61, - 0x81, 0x25, 0x7d, 0x71, 0xe7, 0xbe, 0x31, 0x58, 0xe5, 0xfe, 0xc4, 0x0c, 0xef, 0xa2, 0x16, 0x0c, - 0x70, 0x23, 0x40, 0x1b, 0xcd, 0x6d, 0xe3, 0xac, 0xf2, 0x8a, 0x54, 0xc5, 0x29, 0x11, 0x78, 0xe0, - 0x70, 0x30, 0x86, 0xfa, 0xaa, 0xd0, 0x06, 0x4b, 0x16, 0xb1, 0x89, 0x20, 0x67, 0x5e, 0xe0, 0x91, - 0xeb, 0xd3, 0xd2, 0xcd, 0x83, 0x0f, 0x73, 0x53, 0x1c, 0xa6, 0x9a, 0x6b, 0xdd, 0x4e, 0x6e, 0x29, - 0x32, 0x84, 0xa2, 0xe2, 0xf9, 0xff, 0x6a, 0x60, 0xf3, 0xb0, 0x7c, 0xc4, 0x5c, 0xdf, 0x2b, 0x8b, - 0x20, 0xf3, 0xb5, 0xb6, 0x32, 0xc1, 0x5f, 0x81, 0x19, 0xe6, 0xdb, 0x44, 0x65, 0xe9, 0xb6, 0x0a, - 0x7a, 0x06, 0xf9, 0x36, 0x79, 0xdf, 0xc9, 0xad, 0xc7, 0x58, 0xcf, 0xda, 0x1e, 0x41, 0x92, 0x00, - 0x9f, 0x80, 0x39, 0x86, 0x9d, 0x1a, 0x09, 0x42, 0x4f, 0xdd, 0x59, 0xdc, 0xc9, 0x1b, 0x63, 0xcf, - 0x81, 0x71, 0x52, 0x44, 0x01, 0x74, 0xb0, 0x86, 0xf2, 0x93, 0x23, 0xa5, 0x90, 0x3f, 0x05, 0x4b, - 0x72, 0xf1, 0x5c, 0x26, 0xa4, 0x05, 0xde, 0x04, 0xa9, 0x06, 0x75, 0x64, 0x50, 0xb3, 0xe6, 0xa2, - 0x62, 0xa5, 0x4e, 0xa9, 0x83, 0x82, 0x71, 0x69, 0xc6, 0x2d, 0x99, 0xb3, 0x61, 0x33, 0x6e, 0xa1, - 0x60, 0x3c, 0x7f, 0x04, 0xd2, 0xca, 0xe3, 0xb0, 0x50, 0x6a, 0xb2, 0x50, 0x6a, 0x84, 0xd0, 0xff, - 0xa6, 0xc1, 0x7a, 0xc9, 0xb5, 0x8a, 0x94, 0x33, 0x5f, 0xe6, 0xcb, 0xf4, 0xad, 0x1a, 0x11, 0x9f, - 0x61, 0x7f, 0x3c, 0x03, 0x33, 0xdc, 0x23, 0x55, 0xb5, 0x2d, 0x76, 0x26, 0xe4, 0x76, 0x44, 0x7c, - 0x65, 0x8f, 0x54, 0xcd, 0x4c, 0xb8, 0x94, 0xc1, 0x17, 0x92, 0x6a, 0xf0, 0x25, 0x98, 0xe3, 0x02, - 0x0b, 0x9f, 0xeb, 0x29, 0xa9, 0xfb, 0xf0, 0x9a, 0xba, 0x92, 0x3b, 0x58, 0xc5, 0xde, 0x37, 0x52, - 0x9a, 0xf9, 0xaf, 0x34, 0xf0, 0xe3, 0x11, 0xac, 0xa7, 0x94, 0x0b, 0xf8, 0x32, 0x91, 0x31, 0xe3, - 0xc3, 0x32, 0x16, 0xb0, 0x65, 0xbe, 0x56, 0x95, 0xd7, 0xf9, 0x70, 0x64, 0x28, 0x5b, 0x65, 0x30, - 0x4b, 0x05, 0x69, 0x84, 0x5b, 0xd1, 0xb8, 0xde, 0xb4, 0xcc, 0x25, 0x25, 0x3d, 0x7b, 0x12, 0x88, - 0xa0, 0x9e, 0x56, 0xfe, 0xeb, 0xe9, 0x91, 0xd3, 0x09, 0xd2, 0x09, 0xcf, 0x41, 0xa6, 0x41, 0x9d, - 0xbd, 0x26, 0xa6, 0x36, 0xae, 0xa8, 0xd3, 0x33, 0x69, 0x13, 0x04, 0xd5, 0xcf, 0xe8, 0x55, 0x3f, - 0xe3, 0xc4, 0x11, 0x67, 0xac, 0x2c, 0x18, 0x75, 0x6a, 0xe6, 0x6a, 0xb7, 0x93, 0xcb, 0x9c, 0x0e, - 0x29, 0xa1, 0x88, 0x2e, 0xfc, 0x2b, 0x98, 0xe7, 0xc4, 0x26, 0x55, 0xe1, 0xb2, 0xeb, 0x55, 0x88, - 0xa7, 0xb8, 0x42, 0xec, 0xb2, 0xa2, 0x9a, 0x99, 0x20, 0x6f, 0xe1, 0x17, 0xea, 0x4b, 0x42, 0x1b, - 0x2c, 0x37, 0x70, 0xeb, 0xb9, 0x83, 0xfb, 0x13, 0x49, 0x7d, 0xe4, 0x44, 0x60, 0xb7, 0x93, 0x5b, - 0x3e, 0x8d, 0x68, 0xa1, 0x98, 0x76, 0xfe, 0xfb, 0x19, 0x70, 0x63, 0xec, 0xae, 0x82, 0x4f, 0x00, - 0x74, 0x2b, 0x9c, 0xb0, 0x26, 0xb1, 0x8e, 0x7a, 0xf7, 0x03, 0x75, 0xc3, 0x83, 0xbb, 0xa5, 0x16, - 0x08, 0x9e, 0x25, 0x10, 0x68, 0x04, 0x0b, 0xfe, 0x4b, 0x03, 0x4b, 0x56, 0xcf, 0x0d, 0xb1, 0x4a, - 0xae, 0x15, 0x6e, 0x8c, 0xa3, 0x8f, 0xd9, 0xef, 0x46, 0x71, 0x58, 0xe9, 0xc0, 0x11, 0xac, 0x6d, - 0x6e, 0xa8, 0x80, 0x96, 0x22, 0x36, 0x14, 0x75, 0x0a, 0x4f, 0x01, 0xb4, 0xfa, 0x92, 0x5c, 0xdd, - 0x52, 0x32, 0xc5, 0xb3, 0xe6, 0x4d, 0xa5, 0xb0, 0x11, 0xf1, 0x1b, 0x82, 0xd0, 0x08, 0x22, 0xfc, - 0x1d, 0x58, 0xae, 0xfa, 0x8c, 0x11, 0x47, 0x1c, 0x13, 0x6c, 0x8b, 0x7a, 0x5b, 0x9f, 0x91, 0x52, - 0x9b, 0x4a, 0x6a, 0x79, 0x3f, 0x62, 0x45, 0x31, 0x74, 0xc0, 0xb7, 0x08, 0xa7, 0x8c, 0x58, 0x21, - 0x7f, 0x36, 0xca, 0x2f, 0x46, 0xac, 0x28, 0x86, 0x86, 0xbb, 0x20, 0x43, 0x5a, 0x1e, 0xa9, 0x86, - 0x39, 0x9d, 0x93, 0xec, 0x1f, 0x29, 0x76, 0xe6, 0x60, 0xc8, 0x86, 0x22, 0xc8, 0x2d, 0x1b, 0xc0, - 0x64, 0x12, 0xe1, 0x2a, 0x48, 0x5d, 0x90, 0x76, 0xef, 0xe6, 0x41, 0xc1, 0x4f, 0xf8, 0x7b, 0x30, - 0xdb, 0xc4, 0xb6, 0x4f, 0xd4, 0x5e, 0xbf, 0xfb, 0x61, 0x7b, 0xfd, 0x19, 0x6d, 0x10, 0xd4, 0x23, - 0xfe, 0x7a, 0x7a, 0x57, 0xcb, 0x7f, 0xa9, 0x81, 0xb5, 0x92, 0x6b, 0x95, 0x49, 0xd5, 0x67, 0x54, - 0xb4, 0x4b, 0x72, 0x9d, 0x3f, 0x43, 0xcd, 0x46, 0x91, 0x9a, 0x7d, 0x7f, 0xf2, 0x5e, 0x8b, 0x46, - 0x37, 0xae, 0x62, 0xe7, 0x2f, 0x35, 0xb0, 0x91, 0x40, 0x7f, 0x86, 0x8a, 0xfa, 0xc7, 0x68, 0x45, - 0xfd, 0xc5, 0x75, 0x26, 0x33, 0xa6, 0x9e, 0xbe, 0xcf, 0x8c, 0x98, 0x8a, 0xac, 0xa6, 0x41, 0xbf, - 0xc6, 0x68, 0x93, 0xda, 0xa4, 0x46, 0x2c, 0x39, 0x99, 0xf9, 0xa1, 0x7e, 0xad, 0x6f, 0x41, 0x43, - 0x28, 0xc8, 0xc1, 0xa6, 0x45, 0xce, 0xb1, 0x6f, 0x8b, 0x3d, 0xcb, 0xda, 0xc7, 0x1e, 0xae, 0x50, - 0x9b, 0x0a, 0xaa, 0xda, 0x91, 0x05, 0xf3, 0x71, 0xb7, 0x93, 0xdb, 0x2c, 0x8e, 0x44, 0xbc, 0xef, - 0xe4, 0x6e, 0x26, 0x3b, 0x6d, 0xa3, 0x0f, 0x69, 0xa3, 0x31, 0xd2, 0xb0, 0x0d, 0x74, 0x46, 0xfe, - 0xe1, 0x07, 0x87, 0xa2, 0xc8, 0x5c, 0x2f, 0xe2, 0x36, 0x25, 0xdd, 0xfe, 0xb6, 0xdb, 0xc9, 0xe9, - 0x68, 0x0c, 0xe6, 0x6a, 0xc7, 0x63, 0xe5, 0xe1, 0x2b, 0xb0, 0x8e, 0x7b, 0x75, 0x20, 0xe2, 0x75, - 0x46, 0x7a, 0xdd, 0xed, 0x76, 0x72, 0xeb, 0x7b, 0x49, 0xf3, 0xd5, 0x0e, 0x47, 0x89, 0xc2, 0x02, - 0x48, 0x37, 0x65, 0x13, 0xce, 0xf5, 0x59, 0xa9, 0xbf, 0xd1, 0xed, 0xe4, 0xd2, 0xbd, 0xbe, 0x3c, - 0xd0, 0x9c, 0x3b, 0x2c, 0xcb, 0x46, 0x30, 0x44, 0xc1, 0x47, 0x60, 0xb1, 0xee, 0x72, 0xf1, 0x07, - 0x22, 0x5e, 0xbb, 0xec, 0x42, 0x16, 0x86, 0x79, 0x73, 0x5d, 0xad, 0xe0, 0xe2, 0xf1, 0xc0, 0x84, - 0x86, 0x71, 0xf0, 0xcf, 0x60, 0xa1, 0xae, 0xda, 0x3e, 0xae, 0xa7, 0xe5, 0x46, 0xbb, 0x33, 0x61, - 0xa3, 0x45, 0x5a, 0x44, 0x73, 0x4d, 0xc9, 0x2f, 0x84, 0xc3, 0x1c, 0x0d, 0xd4, 0xe0, 0xcf, 0x41, - 0x5a, 0x7e, 0x9c, 0x14, 0xf5, 0x79, 0x19, 0xcd, 0x8a, 0x82, 0xa7, 0x8f, 0x7b, 0xc3, 0x28, 0xb4, - 0x87, 0xd0, 0x93, 0xd2, 0xbe, 0xbe, 0x90, 0x84, 0x9e, 0x94, 0xf6, 0x51, 0x68, 0x87, 0x2f, 0x41, - 0x9a, 0x93, 0xa7, 0xd4, 0xf1, 0x5b, 0x3a, 0x90, 0x47, 0x6e, 0x7b, 0x42, 0xb8, 0xe5, 0x03, 0x89, - 0x8c, 0x35, 0xdc, 0x03, 0x75, 0x65, 0x47, 0xa1, 0x24, 0xb4, 0xc0, 0x02, 0xf3, 0x9d, 0x3d, 0xfe, - 0x9c, 0x13, 0xa6, 0x2f, 0x26, 0x6e, 0xfb, 0xb8, 0x3e, 0x0a, 0xb1, 0x71, 0x0f, 0xfd, 0xcc, 0xf4, - 0x11, 0x68, 0x20, 0x0c, 0xff, 0xad, 0x01, 0xc8, 0x7d, 0xcf, 0xb3, 0x49, 0x83, 0x38, 0x02, 0xdb, - 0xb2, 0xbf, 0xe7, 0x7a, 0x46, 0xfa, 0xfb, 0xcd, 0xa4, 0xf9, 0x24, 0x48, 0x71, 0xc7, 0xfd, 0x6b, - 0x3a, 0x09, 0x45, 0x23, 0x7c, 0x06, 0xe9, 0x3c, 0xe7, 0xf2, 0xb7, 0xbe, 0x74, 0x65, 0x3a, 0x47, - 0xbf, 0x5f, 0x06, 0xe9, 0x54, 0x76, 0x14, 0x4a, 0xc2, 0x17, 0x60, 0x93, 0x11, 0x6c, 0x9d, 0x39, - 0x76, 0x1b, 0xb9, 0xae, 0x38, 0xa4, 0x36, 0xe1, 0x6d, 0x2e, 0x48, 0x43, 0x5f, 0x96, 0xcb, 0x9c, - 0x55, 0xcc, 0x4d, 0x34, 0x12, 0x85, 0xc6, 0xb0, 0x61, 0x03, 0xe4, 0xc2, 0xf2, 0x10, 0x9c, 0x9d, - 0x7e, 0x7d, 0x3a, 0xe0, 0x55, 0x6c, 0xf7, 0xba, 0x96, 0x15, 0xe9, 0xe0, 0x76, 0xb7, 0x93, 0xcb, - 0x15, 0x27, 0x43, 0xd1, 0x55, 0x5a, 0xf0, 0x4f, 0x40, 0xc7, 0xe3, 0xfc, 0xac, 0x4a, 0x3f, 0x3f, - 0x09, 0x6a, 0xce, 0x58, 0x07, 0x63, 0xd9, 0xd0, 0x03, 0xab, 0x38, 0xfa, 0x72, 0xe6, 0xfa, 0x9a, - 0x3c, 0x85, 0x77, 0x27, 0xac, 0x43, 0xec, 0xb1, 0x6d, 0xea, 0x2a, 0x8d, 0xab, 0x31, 0x03, 0x47, - 0x09, 0x75, 0xd8, 0x02, 0x10, 0xc7, 0x1f, 0xfa, 0x5c, 0x87, 0x57, 0x5e, 0x31, 0x89, 0x7f, 0x07, - 0x06, 0x5b, 0x2d, 0x61, 0xe2, 0x68, 0x84, 0x8f, 0xe0, 0x05, 0xac, 0x8f, 0x3b, 0x30, 0xf0, 0x51, - 0xe4, 0x0d, 0x7c, 0x2b, 0xf6, 0x06, 0x5e, 0x4b, 0xf0, 0x3e, 0xc1, 0x0b, 0xf8, 0xff, 0x1a, 0xd8, - 0x1c, 0x5d, 0x30, 0xe0, 0x83, 0x48, 0x74, 0xb9, 0x58, 0x74, 0x2b, 0x31, 0x96, 0x8a, 0xed, 0x6f, - 0x60, 0x59, 0x95, 0x95, 0xe8, 0x1f, 0x0c, 0x91, 0x18, 0x83, 0xfb, 0x20, 0xe8, 0x08, 0x94, 0x44, - 0x78, 0xa4, 0x64, 0x2f, 0x1f, 0x1d, 0x43, 0x31, 0xb5, 0xfc, 0x17, 0x1a, 0xb8, 0x75, 0x65, 0x41, - 0x80, 0x66, 0x24, 0x74, 0x23, 0x16, 0x7a, 0x76, 0xbc, 0xc0, 0xa7, 0xf9, 0x9f, 0xc1, 0xbc, 0x77, - 0xf9, 0x2e, 0x3b, 0xf5, 0xe6, 0x5d, 0x76, 0xea, 0xed, 0xbb, 0xec, 0xd4, 0x3f, 0xbb, 0x59, 0xed, - 0xb2, 0x9b, 0xd5, 0xde, 0x74, 0xb3, 0xda, 0xdb, 0x6e, 0x56, 0xfb, 0xb6, 0x9b, 0xd5, 0xfe, 0xf3, - 0x5d, 0x76, 0xea, 0x2f, 0x69, 0x25, 0xf7, 0x43, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x7d, 0x0b, - 0x1d, 0x1e, 0x14, 0x00, 0x00, + // 1679 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4f, 0x6f, 0x23, 0xb7, + 0x15, 0xf7, 0xac, 0x6c, 0x4b, 0xa6, 0x6d, 0xad, 0x4d, 0x7b, 0xdd, 0x89, 0xd1, 0xd5, 0x24, 0x0a, + 0x50, 0x6c, 0x83, 0x64, 0x14, 0x7b, 0x93, 0xd6, 0x68, 0xda, 0x22, 0x1e, 0xcb, 0xff, 0x02, 0xbb, + 0x56, 0xa9, 0xdd, 0xa0, 0x2d, 0xb6, 0x45, 0x29, 0x0d, 0x2d, 0x31, 0x1e, 0xcd, 0x4c, 0x49, 0x8e, + 0x22, 0xdd, 0x7a, 0xe8, 0xa1, 0xe8, 0xa9, 0x5f, 0xa0, 0x9f, 0xa0, 0xe8, 0xa9, 0x5f, 0xc2, 0x05, + 0x8a, 0x22, 0xc7, 0xa0, 0x07, 0xa1, 0xab, 0xa2, 0x5f, 0x22, 0xa7, 0x62, 0x28, 0x8e, 0xa4, 0xf9, + 0x23, 0x79, 0x1d, 0x60, 0xf7, 0xa6, 0xe1, 0xfb, 0xfd, 0x7e, 0xef, 0xf1, 0xf1, 0xf1, 0x91, 0x14, + 0xb0, 0x6e, 0x0e, 0xb8, 0x49, 0xbd, 0xca, 0x4d, 0xd0, 0x20, 0xcc, 0x25, 0x82, 0xf0, 0x4a, 0x97, + 0xb8, 0xb6, 0xc7, 0x2a, 0xca, 0x80, 0x7d, 0x5a, 0xf1, 0x3d, 0x87, 0x36, 0xfb, 0x95, 0xee, 0x5e, + 0x83, 0x08, 0xbc, 0x57, 0x69, 0x11, 0x97, 0x30, 0x2c, 0x88, 0x6d, 0xfa, 0xcc, 0x13, 0x1e, 0x7c, + 0x6b, 0x04, 0x35, 0xb1, 0x4f, 0xcd, 0x11, 0xd4, 0x54, 0xd0, 0xdd, 0x0f, 0x5a, 0x54, 0xb4, 0x83, + 0x86, 0xd9, 0xf4, 0x3a, 0x95, 0x96, 0xd7, 0xf2, 0x2a, 0x92, 0xd1, 0x08, 0xae, 0xe5, 0x97, 0xfc, + 0x90, 0xbf, 0x46, 0x4a, 0xbb, 0xe5, 0x29, 0xa7, 0x4d, 0x8f, 0x91, 0x4a, 0x37, 0xe5, 0x6d, 0xf7, + 0xa3, 0x09, 0xa6, 0x83, 0x9b, 0x6d, 0xea, 0x12, 0xd6, 0xaf, 0xf8, 0x37, 0xad, 0x70, 0x80, 0x57, + 0x3a, 0x44, 0xe0, 0x2c, 0x56, 0x65, 0x16, 0x8b, 0x05, 0xae, 0xa0, 0x1d, 0x92, 0x22, 0xfc, 0xe0, + 0x2e, 0x02, 0x6f, 0xb6, 0x49, 0x07, 0xa7, 0x78, 0x4f, 0x67, 0xf1, 0x02, 0x41, 0x9d, 0x0a, 0x75, + 0x05, 0x17, 0x2c, 0x49, 0x2a, 0x7f, 0x02, 0x36, 0x0f, 0x1d, 0xc7, 0xfb, 0x92, 0xd8, 0x27, 0x0e, + 0xe9, 0x7d, 0xee, 0x39, 0x41, 0x87, 0xc0, 0xef, 0x81, 0x65, 0x9b, 0xd1, 0x2e, 0x61, 0xba, 0xf6, + 0xb6, 0xf6, 0x64, 0xc5, 0x2a, 0xde, 0x0e, 0x8c, 0x85, 0xe1, 0xc0, 0x58, 0xae, 0xca, 0x51, 0xa4, + 0xac, 0x65, 0x0e, 0x1e, 0x2a, 0xf2, 0x99, 0xc7, 0x45, 0x0d, 0x8b, 0x36, 0xdc, 0x07, 0xc0, 0xc7, + 0xa2, 0x5d, 0x63, 0xe4, 0x9a, 0xf6, 0x14, 0x1d, 0x2a, 0x3a, 0xa8, 0x8d, 0x2d, 0x68, 0x0a, 0x05, + 0xdf, 0x07, 0x05, 0x46, 0xb0, 0x7d, 0xe5, 0x3a, 0x7d, 0xfd, 0xc1, 0xdb, 0xda, 0x93, 0x82, 0xb5, + 0xa1, 0x18, 0x05, 0xa4, 0xc6, 0xd1, 0x18, 0x51, 0xfe, 0xb7, 0x06, 0x0a, 0xc7, 0x5d, 0xda, 0x14, + 0xd4, 0x73, 0xe1, 0x6f, 0x41, 0x21, 0xcc, 0xbb, 0x8d, 0x05, 0x96, 0xce, 0x56, 0xf7, 0x3f, 0x34, + 0x27, 0x35, 0x31, 0x4e, 0x83, 0xe9, 0xdf, 0xb4, 0xc2, 0x01, 0x6e, 0x86, 0x68, 0xb3, 0xbb, 0x67, + 0x5e, 0x35, 0xbe, 0x20, 0x4d, 0x71, 0x49, 0x04, 0x9e, 0x84, 0x37, 0x19, 0x43, 0x63, 0x55, 0xe8, + 0x80, 0x75, 0x9b, 0x38, 0x44, 0x90, 0x2b, 0x3f, 0xf4, 0xc8, 0x65, 0x84, 0xab, 0xfb, 0x4f, 0x5f, + 0xcd, 0x4d, 0x75, 0x9a, 0x6a, 0x6d, 0x0e, 0x07, 0xc6, 0x7a, 0x6c, 0x08, 0xc5, 0xc5, 0xcb, 0x7f, + 0xd1, 0xc0, 0xce, 0x49, 0xfd, 0x94, 0x79, 0x81, 0x5f, 0x17, 0xe1, 0x3a, 0xb5, 0xfa, 0xca, 0x04, + 0x7f, 0x08, 0x16, 0x59, 0xe0, 0x10, 0x95, 0xd3, 0x77, 0x55, 0xd0, 0x8b, 0x28, 0x70, 0xc8, 0x37, + 0x03, 0x63, 0x2b, 0xc1, 0x7a, 0xd6, 0xf7, 0x09, 0x92, 0x04, 0xf8, 0x19, 0x58, 0x66, 0xd8, 0x6d, + 0x91, 0x30, 0xf4, 0xdc, 0x93, 0xd5, 0xfd, 0xb2, 0x39, 0x73, 0xd7, 0x98, 0xe7, 0x55, 0x14, 0x42, + 0x27, 0x2b, 0x2e, 0x3f, 0x39, 0x52, 0x0a, 0xe5, 0x4b, 0xb0, 0x2e, 0x97, 0xda, 0x63, 0x42, 0x5a, + 0xe0, 0x63, 0x90, 0xeb, 0x50, 0x57, 0x06, 0xb5, 0x64, 0xad, 0x2a, 0x56, 0xee, 0x92, 0xba, 0x28, + 0x1c, 0x97, 0x66, 0xdc, 0x93, 0x39, 0x9b, 0x36, 0xe3, 0x1e, 0x0a, 0xc7, 0xcb, 0xa7, 0x20, 0xaf, + 0x3c, 0x4e, 0x0b, 0xe5, 0xe6, 0x0b, 0xe5, 0x32, 0x84, 0xfe, 0xfa, 0x00, 0x6c, 0xd5, 0x3c, 0xbb, + 0x4a, 0x39, 0x0b, 0x64, 0xbe, 0xac, 0xc0, 0x6e, 0x11, 0xf1, 0x06, 0xea, 0xe3, 0x19, 0x58, 0xe4, + 0x3e, 0x69, 0xaa, 0xb2, 0xd8, 0x9f, 0x93, 0xdb, 0x8c, 0xf8, 0xea, 0x3e, 0x69, 0x5a, 0x6b, 0xd1, + 0x52, 0x86, 0x5f, 0x48, 0xaa, 0xc1, 0x17, 0x60, 0x99, 0x0b, 0x2c, 0x02, 0xae, 0xe7, 0xa4, 0xee, + 0x47, 0xf7, 0xd4, 0x95, 0xdc, 0xc9, 0x2a, 0x8e, 0xbe, 0x91, 0xd2, 0x2c, 0xff, 0x53, 0x03, 0xdf, + 0xc9, 0x60, 0x5d, 0x50, 0x2e, 0xe0, 0x8b, 0x54, 0xc6, 0xcc, 0x57, 0xcb, 0x58, 0xc8, 0x96, 0xf9, + 0x1a, 0x6f, 0xde, 0x68, 0x64, 0x2a, 0x5b, 0x75, 0xb0, 0x44, 0x05, 0xe9, 0x44, 0xa5, 0x68, 0xde, + 0x6f, 0x5a, 0xd6, 0xba, 0x92, 0x5e, 0x3a, 0x0f, 0x45, 0xd0, 0x48, 0xab, 0xfc, 0xaf, 0x07, 0x99, + 0xd3, 0x09, 0xd3, 0x09, 0xaf, 0xc1, 0x5a, 0x87, 0xba, 0x87, 0x5d, 0x4c, 0x1d, 0xdc, 0x50, 0xbb, + 0x67, 0x5e, 0x11, 0x84, 0xbd, 0xd2, 0x1c, 0xf5, 0x4a, 0xf3, 0xdc, 0x15, 0x57, 0xac, 0x2e, 0x18, + 0x75, 0x5b, 0xd6, 0xc6, 0x70, 0x60, 0xac, 0x5d, 0x4e, 0x29, 0xa1, 0x98, 0x2e, 0xfc, 0x35, 0x28, + 0x70, 0xe2, 0x90, 0xa6, 0xf0, 0xd8, 0xfd, 0x3a, 0xc4, 0x05, 0x6e, 0x10, 0xa7, 0xae, 0xa8, 0xd6, + 0x5a, 0x98, 0xb7, 0xe8, 0x0b, 0x8d, 0x25, 0xa1, 0x03, 0x8a, 0x1d, 0xdc, 0x7b, 0xee, 0xe2, 0xf1, + 0x44, 0x72, 0xdf, 0x72, 0x22, 0x70, 0x38, 0x30, 0x8a, 0x97, 0x31, 0x2d, 0x94, 0xd0, 0x2e, 0xff, + 0x6f, 0x11, 0xbc, 0x35, 0xb3, 0xaa, 0xe0, 0x67, 0x00, 0x7a, 0x0d, 0x4e, 0x58, 0x97, 0xd8, 0xa7, + 0xa3, 0xd3, 0x84, 0x7a, 0xd1, 0xc6, 0xdd, 0x55, 0x0b, 0x04, 0xaf, 0x52, 0x08, 0x94, 0xc1, 0x82, + 0x7f, 0xd0, 0xc0, 0xba, 0x3d, 0x72, 0x43, 0xec, 0x9a, 0x67, 0x47, 0x85, 0x71, 0xfa, 0x6d, 0xea, + 0xdd, 0xac, 0x4e, 0x2b, 0x1d, 0xbb, 0x82, 0xf5, 0xad, 0x47, 0x2a, 0xa0, 0xf5, 0x98, 0x0d, 0xc5, + 0x9d, 0xc2, 0x4b, 0x00, 0xed, 0xb1, 0x24, 0x57, 0x67, 0x9a, 0x4c, 0xf1, 0x92, 0xf5, 0x58, 0x29, + 0x3c, 0x8a, 0xf9, 0x8d, 0x40, 0x28, 0x83, 0x08, 0x7f, 0x0a, 0x8a, 0xcd, 0x80, 0x31, 0xe2, 0x8a, + 0x33, 0x82, 0x1d, 0xd1, 0xee, 0xeb, 0x8b, 0x52, 0x6a, 0x47, 0x49, 0x15, 0x8f, 0x62, 0x56, 0x94, + 0x40, 0x87, 0x7c, 0x9b, 0x70, 0xca, 0x88, 0x1d, 0xf1, 0x97, 0xe2, 0xfc, 0x6a, 0xcc, 0x8a, 0x12, + 0x68, 0x78, 0x00, 0xd6, 0x48, 0xcf, 0x27, 0xcd, 0x28, 0xa7, 0xcb, 0x92, 0xbd, 0xad, 0xd8, 0x6b, + 0xc7, 0x53, 0x36, 0x14, 0x43, 0xee, 0x3a, 0x00, 0xa6, 0x93, 0x08, 0x37, 0x40, 0xee, 0x86, 0xf4, + 0x47, 0x27, 0x0f, 0x0a, 0x7f, 0xc2, 0x4f, 0xc1, 0x52, 0x17, 0x3b, 0x01, 0x51, 0xb5, 0xfe, 0xde, + 0xab, 0xd5, 0xfa, 0x33, 0xda, 0x21, 0x68, 0x44, 0xfc, 0xd1, 0x83, 0x03, 0xad, 0xfc, 0x0f, 0x0d, + 0x6c, 0xd6, 0x3c, 0xbb, 0x4e, 0x9a, 0x01, 0xa3, 0xa2, 0x5f, 0x93, 0xeb, 0xfc, 0x06, 0x7a, 0x36, + 0x8a, 0xf5, 0xec, 0x0f, 0xe7, 0xd7, 0x5a, 0x3c, 0xba, 0x59, 0x1d, 0xbb, 0x7c, 0xab, 0x81, 0x47, + 0x29, 0xf4, 0x1b, 0xe8, 0xa8, 0x3f, 0x8f, 0x77, 0xd4, 0xf7, 0xef, 0x33, 0x99, 0x19, 0xfd, 0xf4, + 0x4f, 0xc5, 0x8c, 0xa9, 0xc8, 0x6e, 0x1a, 0xde, 0xee, 0x18, 0xed, 0x52, 0x87, 0xb4, 0x88, 0x2d, + 0x27, 0x53, 0x98, 0xba, 0xdd, 0x8d, 0x2d, 0x68, 0x0a, 0x05, 0x39, 0xd8, 0xb1, 0xc9, 0x35, 0x0e, + 0x1c, 0x71, 0x68, 0xdb, 0x47, 0xd8, 0xc7, 0x0d, 0xea, 0x50, 0x41, 0xd5, 0x75, 0x64, 0xc5, 0xfa, + 0x64, 0x38, 0x30, 0x76, 0xaa, 0x99, 0x88, 0x6f, 0x06, 0xc6, 0xe3, 0xf4, 0xbd, 0xdc, 0x1c, 0x43, + 0xfa, 0x68, 0x86, 0x34, 0xec, 0x03, 0x9d, 0x91, 0xdf, 0x05, 0xe1, 0xa6, 0xa8, 0x32, 0xcf, 0x8f, + 0xb9, 0xcd, 0x49, 0xb7, 0x3f, 0x19, 0x0e, 0x0c, 0x1d, 0xcd, 0xc0, 0xdc, 0xed, 0x78, 0xa6, 0x3c, + 0xfc, 0x02, 0x6c, 0xe1, 0x51, 0x1f, 0x88, 0x79, 0x5d, 0x94, 0x5e, 0x0f, 0x86, 0x03, 0x63, 0xeb, + 0x30, 0x6d, 0xbe, 0xdb, 0x61, 0x96, 0x28, 0xac, 0x80, 0x7c, 0x57, 0x5e, 0xd9, 0xb9, 0xbe, 0x24, + 0xf5, 0x1f, 0x0d, 0x07, 0x46, 0x7e, 0x74, 0x8b, 0x0f, 0x35, 0x97, 0x4f, 0xea, 0xf2, 0x22, 0x18, + 0xa1, 0xe0, 0xc7, 0x60, 0xb5, 0xed, 0x71, 0xf1, 0x33, 0x22, 0xbe, 0xf4, 0xd8, 0x8d, 0x6c, 0x0c, + 0x05, 0x6b, 0x4b, 0xad, 0xe0, 0xea, 0xd9, 0xc4, 0x84, 0xa6, 0x71, 0xf0, 0x97, 0x60, 0xa5, 0xad, + 0xae, 0x7d, 0x5c, 0xcf, 0xcb, 0x42, 0x7b, 0x32, 0xa7, 0xd0, 0x62, 0x57, 0x44, 0x6b, 0x53, 0xc9, + 0xaf, 0x44, 0xc3, 0x1c, 0x4d, 0xd4, 0xe0, 0xf7, 0x41, 0x5e, 0x7e, 0x9c, 0x57, 0xf5, 0x82, 0x8c, + 0xe6, 0xa1, 0x82, 0xe7, 0xcf, 0x46, 0xc3, 0x28, 0xb2, 0x47, 0xd0, 0xf3, 0xda, 0x91, 0xbe, 0x92, + 0x86, 0x9e, 0xd7, 0x8e, 0x50, 0x64, 0x87, 0x2f, 0x40, 0x9e, 0x93, 0x0b, 0xea, 0x06, 0x3d, 0x1d, + 0xc8, 0x2d, 0xb7, 0x37, 0x27, 0xdc, 0xfa, 0xb1, 0x44, 0x26, 0x2e, 0xdc, 0x13, 0x75, 0x65, 0x47, + 0x91, 0x24, 0xb4, 0xc1, 0x0a, 0x0b, 0xdc, 0x43, 0xfe, 0x9c, 0x13, 0xa6, 0xaf, 0xa6, 0x4e, 0xfb, + 0xa4, 0x3e, 0x8a, 0xb0, 0x49, 0x0f, 0xe3, 0xcc, 0x8c, 0x11, 0x68, 0x22, 0x0c, 0xff, 0xa8, 0x01, + 0xc8, 0x03, 0xdf, 0x77, 0x48, 0x87, 0xb8, 0x02, 0x3b, 0xf2, 0x7e, 0xcf, 0xf5, 0x35, 0xe9, 0xef, + 0xc7, 0xf3, 0xe6, 0x93, 0x22, 0x25, 0x1d, 0x8f, 0x8f, 0xe9, 0x34, 0x14, 0x65, 0xf8, 0x0c, 0xd3, + 0x79, 0xcd, 0xe5, 0x6f, 0x7d, 0xfd, 0xce, 0x74, 0x66, 0xbf, 0x5f, 0x26, 0xe9, 0x54, 0x76, 0x14, + 0x49, 0xc2, 0xcf, 0xc1, 0x4e, 0xf4, 0xba, 0x43, 0x9e, 0x27, 0x4e, 0xa8, 0x43, 0x78, 0x9f, 0x0b, + 0xd2, 0xd1, 0x8b, 0x72, 0x99, 0x4b, 0x8a, 0xb9, 0x83, 0x32, 0x51, 0x68, 0x06, 0x1b, 0x76, 0x80, + 0x11, 0xb5, 0x87, 0x70, 0xef, 0x8c, 0xfb, 0xd3, 0x31, 0x6f, 0x62, 0x67, 0x74, 0x6b, 0x79, 0x28, + 0x1d, 0xbc, 0x3b, 0x1c, 0x18, 0x46, 0x75, 0x3e, 0x14, 0xdd, 0xa5, 0x05, 0x7f, 0x01, 0x74, 0x3c, + 0xcb, 0xcf, 0x86, 0xf4, 0xf3, 0xdd, 0xb0, 0xe7, 0xcc, 0x74, 0x30, 0x93, 0x0d, 0x7d, 0xb0, 0x81, + 0xe3, 0xef, 0x6c, 0xae, 0x6f, 0xca, 0x5d, 0xf8, 0xde, 0x9c, 0x75, 0x48, 0x3c, 0xcd, 0x2d, 0x5d, + 0xa5, 0x71, 0x23, 0x61, 0xe0, 0x28, 0xa5, 0x0e, 0x7b, 0x00, 0xe2, 0xe4, 0xdf, 0x02, 0x5c, 0x87, + 0x77, 0x1e, 0x31, 0xa9, 0xff, 0x12, 0x26, 0xa5, 0x96, 0x32, 0x71, 0x94, 0xe1, 0x03, 0x5e, 0x80, + 0x6d, 0x35, 0xfa, 0xdc, 0xe5, 0xf8, 0x9a, 0xd4, 0xfb, 0xbc, 0x29, 0x1c, 0xae, 0x6f, 0xc9, 0xfe, + 0xa6, 0x0f, 0x07, 0xc6, 0xf6, 0x61, 0x86, 0x1d, 0x65, 0xb2, 0xe0, 0xa7, 0x60, 0xe3, 0xda, 0x63, + 0x0d, 0x6a, 0xdb, 0xc4, 0x8d, 0x94, 0xb6, 0xa5, 0xd2, 0x76, 0x98, 0x89, 0x93, 0x84, 0x0d, 0xa5, + 0xd0, 0xe1, 0x8b, 0x5c, 0x9f, 0xb5, 0x81, 0xe1, 0xc7, 0xb1, 0x37, 0xf9, 0x3b, 0x89, 0x37, 0xf9, + 0x66, 0x8a, 0xf7, 0x1a, 0x5e, 0xe4, 0x7f, 0xd3, 0xc0, 0x4e, 0x76, 0x03, 0x83, 0x4f, 0x63, 0xd1, + 0x19, 0x89, 0xe8, 0x1e, 0x26, 0x58, 0x2a, 0xb6, 0xdf, 0x80, 0xa2, 0x6a, 0x73, 0xf1, 0x3f, 0x3c, + 0x62, 0x31, 0x86, 0xe7, 0x53, 0x78, 0x43, 0x51, 0x12, 0xd1, 0x16, 0x97, 0x6f, 0x8b, 0xf8, 0x18, + 0x4a, 0xa8, 0x95, 0xff, 0xae, 0x81, 0x77, 0xee, 0x6c, 0x50, 0xd0, 0x8a, 0x85, 0x6e, 0x26, 0x42, + 0x2f, 0xcd, 0x16, 0x78, 0x3d, 0xff, 0x7b, 0x58, 0x1f, 0xdc, 0xbe, 0x2c, 0x2d, 0x7c, 0xf5, 0xb2, + 0xb4, 0xf0, 0xf5, 0xcb, 0xd2, 0xc2, 0xef, 0x87, 0x25, 0xed, 0x76, 0x58, 0xd2, 0xbe, 0x1a, 0x96, + 0xb4, 0xaf, 0x87, 0x25, 0xed, 0x3f, 0xc3, 0x92, 0xf6, 0xe7, 0xff, 0x96, 0x16, 0x7e, 0x95, 0x57, + 0x72, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x91, 0xe5, 0x7f, 0xdc, 0x14, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/generated.proto index 514868a9f..1a14d946f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,14 +32,14 @@ option go_package = "v1beta1"; // AllowedFlexVolume represents a single Flexvolume that is allowed to be used. message AllowedFlexVolume { - // Driver is the name of the Flexvolume driver. + // driver is the name of the Flexvolume driver. optional string driver = 1; } -// defines the host volume conditions that will be enabled by a policy +// AllowedHostPath defines the host volume conditions that will be enabled by a policy // for pods to use. It requires the path prefix to be defined. message AllowedHostPath { - // is the path prefix that the host volume must match. + // pathPrefix is the path prefix that the host volume must match. // It does not support `*`. // Trailing slashes are trimmed when validating the path prefix with a host path. // @@ -47,6 +47,10 @@ message AllowedHostPath { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` optional string pathPrefix = 1; + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + optional bool readOnly = 2; } // Eviction evicts a pod from its node subject to certain policies and safety constraints. @@ -62,17 +66,17 @@ message Eviction { // FSGroupStrategyOptions defines the strategy type and options used to create the strategy. message FSGroupStrategyOptions { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. // +optional optional string rule = 1; - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. + // ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } -// Host Port Range defines a range of host ports that will be enabled by a policy +// HostPortRange defines a range of host ports that will be enabled by a policy // for pods to use. It requires both the start and end to be defined. message HostPortRange { // min is the start of the range, inclusive. @@ -82,12 +86,12 @@ message HostPortRange { optional int32 max = 2; } -// ID Range provides a min/max of an allowed range of IDs. +// IDRange provides a min/max of an allowed range of IDs. message IDRange { - // Min is the start of the range, inclusive. + // min is the start of the range, inclusive. optional int64 min = 1; - // Max is the end of the range, inclusive. + // max is the end of the range, inclusive. optional int64 max = 2; } @@ -162,7 +166,7 @@ message PodDisruptionBudgetStatus { optional int32 expectedPods = 6; } -// Pod Security Policy governs the ability to make requests that affect the Security Context +// PodSecurityPolicy governs the ability to make requests that affect the Security Context // that will be applied to a pod and container. message PodSecurityPolicy { // Standard object's metadata. @@ -175,43 +179,43 @@ message PodSecurityPolicy { optional PodSecurityPolicySpec spec = 2; } -// Pod Security Policy List is a list of PodSecurityPolicy objects. +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. message PodSecurityPolicyList { // Standard list metadata. // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - // Items is a list of schema objects. + // items is a list of schema objects. repeated PodSecurityPolicy items = 2; } -// Pod Security Policy Spec defines the policy enforced. +// PodSecurityPolicySpec defines the policy enforced. message PodSecurityPolicySpec { // privileged determines if a pod can request to be run as privileged. // +optional optional bool privileged = 1; - // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // defaultAddCapabilities is the default set of capabilities that will be added to the container // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. + // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the allowedCapabilities list. // +optional repeated string defaultAddCapabilities = 2; - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // requiredDropCapabilities are the capabilities that will be dropped from the container. These // are required to be dropped and cannot be added. // +optional repeated string requiredDropCapabilities = 3; - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // allowedCapabilities is a list of capabilities that can be requested to add to the container. // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. // +optional repeated string allowedCapabilities = 4; - // volumes is a white list of allowed volume plugins. Empty indicates that all plugins - // may be used. + // volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. // +optional repeated string volumes = 5; @@ -237,13 +241,13 @@ message PodSecurityPolicySpec { // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. optional RunAsUserStrategyOptions runAsUser = 11; - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. optional SupplementalGroupsStrategyOptions supplementalGroups = 12; - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. optional FSGroupStrategyOptions fsGroup = 13; - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // readOnlyRootFilesystem when set to true will force containers to run with a read only root file // system. If the container specifically requests to run with a non-read only root file system // the PSP should deny the pod. // If set to false the container may run with a read only root file system if it wishes but it @@ -251,40 +255,63 @@ message PodSecurityPolicySpec { // +optional optional bool readOnlyRootFilesystem = 14; - // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // defaultAllowPrivilegeEscalation controls the default setting for whether a // process can gain more privileges than its parent process. // +optional optional bool defaultAllowPrivilegeEscalation = 15; - // AllowPrivilegeEscalation determines if a pod can request to allow + // allowPrivilegeEscalation determines if a pod can request to allow // privilege escalation. If unspecified, defaults to true. // +optional optional bool allowPrivilegeEscalation = 16; - // is a white list of allowed host paths. Empty indicates that all host paths may be used. + // allowedHostPaths is a white list of allowed host paths. Empty indicates + // that all host paths may be used. // +optional repeated AllowedHostPath allowedHostPaths = 17; - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. + // is allowed in the "volumes" field. // +optional repeated AllowedFlexVolume allowedFlexVolumes = 18; + + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + repeated string allowedUnsafeSysctls = 19; + + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + repeated string forbiddenSysctls = 20; } -// Run A sUser Strategy Options defines the strategy type and any options used to create the strategy. +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. message RunAsUserStrategyOptions { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + // rule is the strategy that will dictate the allowable RunAsUser values that may be set. optional string rule = 1; - // Ranges are the allowed ranges of uids that may be used. + // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } -// SELinux Strategy Options defines the strategy type and any options used to create the strategy. +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. message SELinuxStrategyOptions { - // type is the strategy that will dictate the allowable labels that may be set. + // rule is the strategy that will dictate the allowable labels that may be set. optional string rule = 1; // seLinuxOptions required to run as; required for MustRunAs @@ -295,12 +322,12 @@ message SELinuxStrategyOptions { // SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. message SupplementalGroupsStrategyOptions { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. // +optional optional string rule = 1; - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. + // ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. // +optional repeated IDRange ranges = 2; } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/types.go index 6cea9615f..ba1e4ff31 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/types.go @@ -119,7 +119,7 @@ type Eviction struct { // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Pod Security Policy governs the ability to make requests that affect the Security Context +// PodSecurityPolicy governs the ability to make requests that affect the Security Context // that will be applied to a pod and container. type PodSecurityPolicy struct { metav1.TypeMeta `json:",inline"` @@ -133,28 +133,28 @@ type PodSecurityPolicy struct { Spec PodSecurityPolicySpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` } -// Pod Security Policy Spec defines the policy enforced. +// PodSecurityPolicySpec defines the policy enforced. type PodSecurityPolicySpec struct { // privileged determines if a pod can request to be run as privileged. // +optional Privileged bool `json:"privileged,omitempty" protobuf:"varint,1,opt,name=privileged"` - // DefaultAddCapabilities is the default set of capabilities that will be added to the container + // defaultAddCapabilities is the default set of capabilities that will be added to the container // unless the pod spec specifically drops the capability. You may not list a capability in both - // DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the AllowedCapabilities list. + // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly + // allowed, and need not be included in the allowedCapabilities list. // +optional DefaultAddCapabilities []v1.Capability `json:"defaultAddCapabilities,omitempty" protobuf:"bytes,2,rep,name=defaultAddCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // RequiredDropCapabilities are the capabilities that will be dropped from the container. These + // requiredDropCapabilities are the capabilities that will be dropped from the container. These // are required to be dropped and cannot be added. // +optional RequiredDropCapabilities []v1.Capability `json:"requiredDropCapabilities,omitempty" protobuf:"bytes,3,rep,name=requiredDropCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // AllowedCapabilities is a list of capabilities that can be requested to add to the container. + // allowedCapabilities is a list of capabilities that can be requested to add to the container. // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities. + // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. // +optional AllowedCapabilities []v1.Capability `json:"allowedCapabilities,omitempty" protobuf:"bytes,4,rep,name=allowedCapabilities,casttype=k8s.io/api/core/v1.Capability"` - // volumes is a white list of allowed volume plugins. Empty indicates that all plugins - // may be used. + // volumes is a white list of allowed volume plugins. Empty indicates that + // no volumes may be used. To allow all volumes you may use '*'. // +optional Volumes []FSType `json:"volumes,omitempty" protobuf:"bytes,5,rep,name=volumes,casttype=FSType"` // hostNetwork determines if the policy allows the use of HostNetwork in the pod spec. @@ -173,39 +173,59 @@ type PodSecurityPolicySpec struct { SELinux SELinuxStrategyOptions `json:"seLinux" protobuf:"bytes,10,opt,name=seLinux"` // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. RunAsUser RunAsUserStrategyOptions `json:"runAsUser" protobuf:"bytes,11,opt,name=runAsUser"` - // SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. + // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. SupplementalGroups SupplementalGroupsStrategyOptions `json:"supplementalGroups" protobuf:"bytes,12,opt,name=supplementalGroups"` - // FSGroup is the strategy that will dictate what fs group is used by the SecurityContext. + // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. FSGroup FSGroupStrategyOptions `json:"fsGroup" protobuf:"bytes,13,opt,name=fsGroup"` - // ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file + // readOnlyRootFilesystem when set to true will force containers to run with a read only root file // system. If the container specifically requests to run with a non-read only root file system // the PSP should deny the pod. // If set to false the container may run with a read only root file system if it wishes but it // will not be forced to. // +optional ReadOnlyRootFilesystem bool `json:"readOnlyRootFilesystem,omitempty" protobuf:"varint,14,opt,name=readOnlyRootFilesystem"` - // DefaultAllowPrivilegeEscalation controls the default setting for whether a + // defaultAllowPrivilegeEscalation controls the default setting for whether a // process can gain more privileges than its parent process. // +optional DefaultAllowPrivilegeEscalation *bool `json:"defaultAllowPrivilegeEscalation,omitempty" protobuf:"varint,15,opt,name=defaultAllowPrivilegeEscalation"` - // AllowPrivilegeEscalation determines if a pod can request to allow + // allowPrivilegeEscalation determines if a pod can request to allow // privilege escalation. If unspecified, defaults to true. // +optional AllowPrivilegeEscalation *bool `json:"allowPrivilegeEscalation,omitempty" protobuf:"varint,16,opt,name=allowPrivilegeEscalation"` - // is a white list of allowed host paths. Empty indicates that all host paths may be used. + // allowedHostPaths is a white list of allowed host paths. Empty indicates + // that all host paths may be used. // +optional AllowedHostPaths []AllowedHostPath `json:"allowedHostPaths,omitempty" protobuf:"bytes,17,rep,name=allowedHostPaths"` - // AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all + // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "Volumes" field. + // is allowed in the "volumes" field. // +optional AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"` + // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. + // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. + // + // Examples: + // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. + // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. + // +optional + AllowedUnsafeSysctls []string `json:"allowedUnsafeSysctls,omitempty" protobuf:"bytes,19,rep,name=allowedUnsafeSysctls"` + // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. + // Each entry is either a plain sysctl name or ends in "*" in which case it is considered + // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. + // + // Examples: + // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. + // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. + // +optional + ForbiddenSysctls []string `json:"forbiddenSysctls,omitempty" protobuf:"bytes,20,rep,name=forbiddenSysctls"` } -// defines the host volume conditions that will be enabled by a policy +// AllowedHostPath defines the host volume conditions that will be enabled by a policy // for pods to use. It requires the path prefix to be defined. type AllowedHostPath struct { - // is the path prefix that the host volume must match. + // pathPrefix is the path prefix that the host volume must match. // It does not support `*`. // Trailing slashes are trimmed when validating the path prefix with a host path. // @@ -213,9 +233,13 @@ type AllowedHostPath struct { // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` // `/foo` would not allow `/food` or `/etc/foo` PathPrefix string `json:"pathPrefix,omitempty" protobuf:"bytes,1,rep,name=pathPrefix"` + + // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. + // +optional + ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,2,opt,name=readOnly"` } -// FS Type gives strong typing to different file systems that are used by volumes. +// FSType gives strong typing to different file systems that are used by volumes. type FSType string var ( @@ -245,11 +269,11 @@ var ( // AllowedFlexVolume represents a single Flexvolume that is allowed to be used. type AllowedFlexVolume struct { - // Driver is the name of the Flexvolume driver. + // driver is the name of the Flexvolume driver. Driver string `json:"driver" protobuf:"bytes,1,opt,name=driver"` } -// Host Port Range defines a range of host ports that will be enabled by a policy +// HostPortRange defines a range of host ports that will be enabled by a policy // for pods to use. It requires both the start and end to be defined. type HostPortRange struct { // min is the start of the range, inclusive. @@ -258,9 +282,9 @@ type HostPortRange struct { Max int32 `json:"max" protobuf:"varint,2,opt,name=max"` } -// SELinux Strategy Options defines the strategy type and any options used to create the strategy. +// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. type SELinuxStrategyOptions struct { - // type is the strategy that will dictate the allowable labels that may be set. + // rule is the strategy that will dictate the allowable labels that may be set. Rule SELinuxStrategy `json:"rule" protobuf:"bytes,1,opt,name=rule,casttype=SELinuxStrategy"` // seLinuxOptions required to run as; required for MustRunAs // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ @@ -273,26 +297,27 @@ type SELinuxStrategyOptions struct { type SELinuxStrategy string const ( - // container must have SELinux labels of X applied. + // SELinuxStrategyMustRunAs means that container must have SELinux labels of X applied. SELinuxStrategyMustRunAs SELinuxStrategy = "MustRunAs" - // container may make requests for any SELinux context labels. + // SELinuxStrategyRunAsAny means that container may make requests for any SELinux context labels. SELinuxStrategyRunAsAny SELinuxStrategy = "RunAsAny" ) -// Run A sUser Strategy Options defines the strategy type and any options used to create the strategy. +// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. type RunAsUserStrategyOptions struct { - // Rule is the strategy that will dictate the allowable RunAsUser values that may be set. + // rule is the strategy that will dictate the allowable RunAsUser values that may be set. Rule RunAsUserStrategy `json:"rule" protobuf:"bytes,1,opt,name=rule,casttype=RunAsUserStrategy"` - // Ranges are the allowed ranges of uids that may be used. + // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid + // then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } -// ID Range provides a min/max of an allowed range of IDs. +// IDRange provides a min/max of an allowed range of IDs. type IDRange struct { - // Min is the start of the range, inclusive. + // min is the start of the range, inclusive. Min int64 `json:"min" protobuf:"varint,1,opt,name=min"` - // Max is the end of the range, inclusive. + // max is the end of the range, inclusive. Max int64 `json:"max" protobuf:"varint,2,opt,name=max"` } @@ -301,21 +326,21 @@ type IDRange struct { type RunAsUserStrategy string const ( - // container must run as a particular uid. + // RunAsUserStrategyMustRunAs means that container must run as a particular uid. RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs" - // container must run as a non-root uid + // RunAsUserStrategyMustRunAsNonRoot means that container must run as a non-root uid. RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot" - // container may make requests for any uid. + // RunAsUserStrategyRunAsAny means that container may make requests for any uid. RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny" ) // FSGroupStrategyOptions defines the strategy type and options used to create the strategy. type FSGroupStrategyOptions struct { - // Rule is the strategy that will dictate what FSGroup is used in the SecurityContext. + // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. // +optional Rule FSGroupStrategyType `json:"rule,omitempty" protobuf:"bytes,1,opt,name=rule,casttype=FSGroupStrategyType"` - // Ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. + // ranges are the allowed ranges of fs groups. If you would like to force a single + // fs group then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } @@ -325,19 +350,19 @@ type FSGroupStrategyOptions struct { type FSGroupStrategyType string const ( - // container must have FSGroup of X applied. + // FSGroupStrategyMustRunAs meant that container must have FSGroup of X applied. FSGroupStrategyMustRunAs FSGroupStrategyType = "MustRunAs" - // container may make requests for any FSGroup labels. + // FSGroupStrategyRunAsAny means that container may make requests for any FSGroup labels. FSGroupStrategyRunAsAny FSGroupStrategyType = "RunAsAny" ) // SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. type SupplementalGroupsStrategyOptions struct { - // Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. + // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. // +optional Rule SupplementalGroupsStrategyType `json:"rule,omitempty" protobuf:"bytes,1,opt,name=rule,casttype=SupplementalGroupsStrategyType"` - // Ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. + // ranges are the allowed ranges of supplemental groups. If you would like to force a single + // supplemental group then supply a single range with the same start and end. Required for MustRunAs. // +optional Ranges []IDRange `json:"ranges,omitempty" protobuf:"bytes,2,rep,name=ranges"` } @@ -347,15 +372,15 @@ type SupplementalGroupsStrategyOptions struct { type SupplementalGroupsStrategyType string const ( - // container must run as a particular gid. + // SupplementalGroupsStrategyMustRunAs means that container must run as a particular gid. SupplementalGroupsStrategyMustRunAs SupplementalGroupsStrategyType = "MustRunAs" - // container may make requests for any gid. + // SupplementalGroupsStrategyRunAsAny means that container may make requests for any gid. SupplementalGroupsStrategyRunAsAny SupplementalGroupsStrategyType = "RunAsAny" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Pod Security Policy List is a list of PodSecurityPolicy objects. +// PodSecurityPolicyList is a list of PodSecurityPolicy objects. type PodSecurityPolicyList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata. @@ -363,6 +388,6 @@ type PodSecurityPolicyList struct { // +optional metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` - // Items is a list of schema objects. + // items is a list of schema objects. Items []PodSecurityPolicy `json:"items" protobuf:"bytes,2,rep,name=items"` } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go index 8c51518d4..122287645 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,10 +26,10 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AllowedFlexVolume = map[string]string{ "": "AllowedFlexVolume represents a single Flexvolume that is allowed to be used.", - "driver": "Driver is the name of the Flexvolume driver.", + "driver": "driver is the name of the Flexvolume driver.", } func (AllowedFlexVolume) SwaggerDoc() map[string]string { @@ -37,8 +37,9 @@ func (AllowedFlexVolume) SwaggerDoc() map[string]string { } var map_AllowedHostPath = map[string]string{ - "": "defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", - "pathPrefix": "is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "": "AllowedHostPath defines the host volume conditions that will be enabled by a policy for pods to use. It requires the path prefix to be defined.", + "pathPrefix": "pathPrefix is the path prefix that the host volume must match. It does not support `*`. Trailing slashes are trimmed when validating the path prefix with a host path.\n\nExamples: `/foo` would allow `/foo`, `/foo/` and `/foo/bar` `/foo` would not allow `/food` or `/etc/foo`", + "readOnly": "when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly.", } func (AllowedHostPath) SwaggerDoc() map[string]string { @@ -57,8 +58,8 @@ func (Eviction) SwaggerDoc() map[string]string { var map_FSGroupStrategyOptions = map[string]string{ "": "FSGroupStrategyOptions defines the strategy type and options used to create the strategy.", - "rule": "Rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", - "ranges": "Ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end.", + "rule": "rule is the strategy that will dictate what FSGroup is used in the SecurityContext.", + "ranges": "ranges are the allowed ranges of fs groups. If you would like to force a single fs group then supply a single range with the same start and end. Required for MustRunAs.", } func (FSGroupStrategyOptions) SwaggerDoc() map[string]string { @@ -66,7 +67,7 @@ func (FSGroupStrategyOptions) SwaggerDoc() map[string]string { } var map_HostPortRange = map[string]string{ - "": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", + "": "HostPortRange defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.", "min": "min is the start of the range, inclusive.", "max": "max is the end of the range, inclusive.", } @@ -76,9 +77,9 @@ func (HostPortRange) SwaggerDoc() map[string]string { } var map_IDRange = map[string]string{ - "": "ID Range provides a min/max of an allowed range of IDs.", - "min": "Min is the start of the range, inclusive.", - "max": "Max is the end of the range, inclusive.", + "": "IDRange provides a min/max of an allowed range of IDs.", + "min": "min is the start of the range, inclusive.", + "max": "max is the end of the range, inclusive.", } func (IDRange) SwaggerDoc() map[string]string { @@ -129,7 +130,7 @@ func (PodDisruptionBudgetStatus) SwaggerDoc() map[string]string { } var map_PodSecurityPolicy = map[string]string{ - "": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", + "": "PodSecurityPolicy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "spec": "spec defines the policy enforced.", } @@ -139,9 +140,9 @@ func (PodSecurityPolicy) SwaggerDoc() map[string]string { } var map_PodSecurityPolicyList = map[string]string{ - "": "Pod Security Policy List is a list of PodSecurityPolicy objects.", + "": "PodSecurityPolicyList is a list of PodSecurityPolicy objects.", "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "items": "Items is a list of schema objects.", + "items": "items is a list of schema objects.", } func (PodSecurityPolicyList) SwaggerDoc() map[string]string { @@ -149,25 +150,27 @@ func (PodSecurityPolicyList) SwaggerDoc() map[string]string { } var map_PodSecurityPolicySpec = map[string]string{ - "": "Pod Security Policy Spec defines the policy enforced.", + "": "PodSecurityPolicySpec defines the policy enforced.", "privileged": "privileged determines if a pod can request to be run as privileged.", - "defaultAddCapabilities": "DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both DefaultAddCapabilities and RequiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the AllowedCapabilities list.", - "requiredDropCapabilities": "RequiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", - "allowedCapabilities": "AllowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities.", - "volumes": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.", + "defaultAddCapabilities": "defaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capability in both defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly allowed, and need not be included in the allowedCapabilities list.", + "requiredDropCapabilities": "requiredDropCapabilities are the capabilities that will be dropped from the container. These are required to be dropped and cannot be added.", + "allowedCapabilities": "allowedCapabilities is a list of capabilities that can be requested to add to the container. Capabilities in this field may be added at the pod author's discretion. You must not list a capability in both allowedCapabilities and requiredDropCapabilities.", + "volumes": "volumes is a white list of allowed volume plugins. Empty indicates that no volumes may be used. To allow all volumes you may use '*'.", "hostNetwork": "hostNetwork determines if the policy allows the use of HostNetwork in the pod spec.", "hostPorts": "hostPorts determines which host port ranges are allowed to be exposed.", "hostPID": "hostPID determines if the policy allows the use of HostPID in the pod spec.", "hostIPC": "hostIPC determines if the policy allows the use of HostIPC in the pod spec.", "seLinux": "seLinux is the strategy that will dictate the allowable labels that may be set.", "runAsUser": "runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set.", - "supplementalGroups": "SupplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", - "fsGroup": "FSGroup is the strategy that will dictate what fs group is used by the SecurityContext.", - "readOnlyRootFilesystem": "ReadOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", - "defaultAllowPrivilegeEscalation": "DefaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", - "allowPrivilegeEscalation": "AllowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", - "allowedHostPaths": "is a white list of allowed host paths. Empty indicates that all host paths may be used.", - "allowedFlexVolumes": "AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"Volumes\" field.", + "supplementalGroups": "supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext.", + "fsGroup": "fsGroup is the strategy that will dictate what fs group is used by the SecurityContext.", + "readOnlyRootFilesystem": "readOnlyRootFilesystem when set to true will force containers to run with a read only root file system. If the container specifically requests to run with a non-read only root file system the PSP should deny the pod. If set to false the container may run with a read only root file system if it wishes but it will not be forced to.", + "defaultAllowPrivilegeEscalation": "defaultAllowPrivilegeEscalation controls the default setting for whether a process can gain more privileges than its parent process.", + "allowPrivilegeEscalation": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.", + "allowedHostPaths": "allowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.", + "allowedFlexVolumes": "allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field.", + "allowedUnsafeSysctls": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.", + "forbiddenSysctls": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.", } func (PodSecurityPolicySpec) SwaggerDoc() map[string]string { @@ -175,9 +178,9 @@ func (PodSecurityPolicySpec) SwaggerDoc() map[string]string { } var map_RunAsUserStrategyOptions = map[string]string{ - "": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.", - "rule": "Rule is the strategy that will dictate the allowable RunAsUser values that may be set.", - "ranges": "Ranges are the allowed ranges of uids that may be used.", + "": "RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy.", + "rule": "rule is the strategy that will dictate the allowable RunAsUser values that may be set.", + "ranges": "ranges are the allowed ranges of uids that may be used. If you would like to force a single uid then supply a single range with the same start and end. Required for MustRunAs.", } func (RunAsUserStrategyOptions) SwaggerDoc() map[string]string { @@ -185,8 +188,8 @@ func (RunAsUserStrategyOptions) SwaggerDoc() map[string]string { } var map_SELinuxStrategyOptions = map[string]string{ - "": "SELinux Strategy Options defines the strategy type and any options used to create the strategy.", - "rule": "type is the strategy that will dictate the allowable labels that may be set.", + "": "SELinuxStrategyOptions defines the strategy type and any options used to create the strategy.", + "rule": "rule is the strategy that will dictate the allowable labels that may be set.", "seLinuxOptions": "seLinuxOptions required to run as; required for MustRunAs More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/", } @@ -196,8 +199,8 @@ func (SELinuxStrategyOptions) SwaggerDoc() map[string]string { var map_SupplementalGroupsStrategyOptions = map[string]string{ "": "SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy.", - "rule": "Rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", - "ranges": "Ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end.", + "rule": "rule is the strategy that will dictate what supplemental groups is used in the SecurityContext.", + "ranges": "ranges are the allowed ranges of supplemental groups. If you would like to force a single supplemental group then supply a single range with the same start and end. Required for MustRunAs.", } func (SupplementalGroupsStrategyOptions) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go index 8a770b2f0..1980bd161 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/policy/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -394,6 +394,16 @@ func (in *PodSecurityPolicySpec) DeepCopyInto(out *PodSecurityPolicySpec) { *out = make([]AllowedFlexVolume, len(*in)) copy(*out, *in) } + if in.AllowedUnsafeSysctls != nil { + in, out := &in.AllowedUnsafeSysctls, &out.AllowedUnsafeSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ForbiddenSysctls != nil { + in, out := &in.ForbiddenSysctls, &out.ForbiddenSysctls + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/generated.pb.go index 5343731cc..21010fbee 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2693,57 +2693,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 827 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x55, 0xcf, 0x8b, 0x23, 0x45, - 0x18, 0x4d, 0x65, 0x12, 0x26, 0x5d, 0x31, 0xc4, 0x2d, 0x17, 0x69, 0xa2, 0x74, 0x86, 0x16, 0x24, - 0xa0, 0x76, 0x9b, 0x5d, 0x51, 0x41, 0xf6, 0xb0, 0xbd, 0xa2, 0x0c, 0x3b, 0x8e, 0x4b, 0x2d, 0x7a, - 0x10, 0x0f, 0x56, 0x77, 0x6a, 0x3b, 0x65, 0xfa, 0x17, 0x55, 0xd5, 0x81, 0xc5, 0x8b, 0x08, 0x1e, - 0xbc, 0x79, 0xd4, 0xbf, 0xc0, 0x8b, 0x1e, 0xfd, 0x0b, 0xbc, 0xcc, 0x71, 0x8f, 0x7b, 0x0a, 0x4e, - 0xfb, 0x87, 0x28, 0xfd, 0x2b, 0x9d, 0xa4, 0x3b, 0x4e, 0x4e, 0x01, 0xf1, 0x34, 0x53, 0xdf, 0xf7, - 0xde, 0xfb, 0x5e, 0xbf, 0xa9, 0xaf, 0x06, 0x7e, 0xb0, 0x78, 0x5f, 0x18, 0x2c, 0x34, 0x17, 0xb1, - 0x4d, 0x79, 0x40, 0x25, 0x15, 0xe6, 0x92, 0x06, 0xb3, 0x90, 0x9b, 0x45, 0x83, 0x44, 0xcc, 0xe4, - 0x36, 0x71, 0xcc, 0xe5, 0xd4, 0x74, 0x69, 0x40, 0x39, 0x91, 0x74, 0x66, 0x44, 0x3c, 0x94, 0x21, - 0x42, 0x39, 0xc6, 0x20, 0x11, 0x33, 0x52, 0x8c, 0xb1, 0x9c, 0x8e, 0xde, 0x72, 0x99, 0x9c, 0xc7, - 0xb6, 0xe1, 0x84, 0xbe, 0xe9, 0x86, 0x6e, 0x68, 0x66, 0x50, 0x3b, 0x7e, 0x92, 0x9d, 0xb2, 0x43, - 0xf6, 0x5b, 0x2e, 0x31, 0x9a, 0xd4, 0xc7, 0x10, 0x2f, 0x9a, 0x93, 0xda, 0xb0, 0xd1, 0x3b, 0x15, - 0xd2, 0x27, 0xce, 0x9c, 0x05, 0x94, 0x3f, 0x35, 0xa3, 0x85, 0x9b, 0x16, 0x84, 0xe9, 0x53, 0x49, - 0x1a, 0x2c, 0x8e, 0xcc, 0x7d, 0x2c, 0x1e, 0x07, 0x92, 0xf9, 0xb4, 0x46, 0x78, 0xf7, 0x26, 0x82, - 0x70, 0xe6, 0xd4, 0x27, 0x35, 0xde, 0xdd, 0x7d, 0xbc, 0x58, 0x32, 0xcf, 0x64, 0x81, 0x14, 0x92, - 0xef, 0x92, 0xf4, 0x9f, 0x01, 0x1c, 0xde, 0x77, 0x5d, 0x4e, 0x5d, 0x22, 0x59, 0x18, 0xe0, 0xd8, - 0xa3, 0xe8, 0x7b, 0x00, 0x6f, 0x3b, 0x5e, 0x2c, 0x24, 0xe5, 0x38, 0xf4, 0xe8, 0x63, 0xea, 0x51, - 0x47, 0x86, 0x5c, 0xa8, 0xe0, 0xec, 0x64, 0xd2, 0xbf, 0x73, 0xd7, 0xa8, 0x42, 0x5f, 0x0f, 0x32, - 0xa2, 0x85, 0x9b, 0x16, 0x84, 0x91, 0xe6, 0x60, 0x2c, 0xa7, 0xc6, 0x05, 0xb1, 0xa9, 0x57, 0x72, - 0xad, 0x57, 0xaf, 0x56, 0xe3, 0x56, 0xb2, 0x1a, 0xdf, 0x7e, 0xd0, 0x20, 0x8c, 0x1b, 0xc7, 0xe9, - 0x3f, 0xb5, 0x61, 0x7f, 0x03, 0x8e, 0xbe, 0x82, 0xbd, 0x54, 0x7c, 0x46, 0x24, 0x51, 0xc1, 0x19, - 0x98, 0xf4, 0xef, 0xbc, 0x7d, 0x98, 0x95, 0x4f, 0xed, 0xaf, 0xa9, 0x23, 0x3f, 0xa1, 0x92, 0x58, - 0xa8, 0xf0, 0x01, 0xab, 0x1a, 0x5e, 0xab, 0xa2, 0x07, 0xb0, 0xcb, 0x63, 0x8f, 0x0a, 0xb5, 0x9d, - 0x7d, 0xa9, 0x66, 0xd4, 0xaf, 0x97, 0xf1, 0x28, 0xf4, 0x98, 0xf3, 0x34, 0x0d, 0xca, 0x1a, 0x14, - 0x62, 0xdd, 0xf4, 0x24, 0x70, 0xce, 0x45, 0x36, 0x1c, 0x92, 0xed, 0x44, 0xd5, 0x93, 0xcc, 0xed, - 0x6b, 0x4d, 0x72, 0x3b, 0xe1, 0x5b, 0x2f, 0x25, 0xab, 0xf1, 0xee, 0x5f, 0x04, 0xef, 0x0a, 0xea, - 0x3f, 0xb4, 0x21, 0xda, 0x88, 0xc6, 0x62, 0xc1, 0x8c, 0x05, 0xee, 0x11, 0x12, 0x3a, 0x87, 0x3d, - 0x11, 0x67, 0x8d, 0x32, 0xa4, 0x57, 0x9a, 0xbe, 0xea, 0x71, 0x8e, 0xb1, 0x5e, 0x2c, 0xc4, 0x7a, - 0x45, 0x41, 0xe0, 0x35, 0x1d, 0x7d, 0x04, 0x4f, 0x79, 0xe8, 0x51, 0x4c, 0x9f, 0x14, 0xf9, 0x34, - 0x2a, 0xe1, 0x1c, 0x62, 0x0d, 0x0b, 0xa5, 0xd3, 0xa2, 0x80, 0x4b, 0xb2, 0xfe, 0x07, 0x80, 0x2f, - 0xd7, 0xb3, 0xb8, 0x60, 0x42, 0xa2, 0x2f, 0x6b, 0x79, 0x18, 0x07, 0x5e, 0x5e, 0x26, 0xf2, 0x34, - 0xd6, 0x1f, 0x50, 0x56, 0x36, 0xb2, 0x78, 0x08, 0xbb, 0x4c, 0x52, 0xbf, 0x0c, 0xe2, 0xf5, 0x26, - 0xfb, 0x75, 0x63, 0xd5, 0xad, 0x39, 0x4f, 0xc9, 0x38, 0xd7, 0xd0, 0x7f, 0x07, 0x70, 0xb8, 0x01, - 0x3e, 0x82, 0xfd, 0x0f, 0xb7, 0xed, 0x8f, 0x6f, 0xb2, 0xdf, 0xec, 0xfb, 0x6f, 0x00, 0x61, 0xb5, - 0x12, 0x68, 0x0c, 0xbb, 0x4b, 0xca, 0xed, 0xfc, 0xad, 0x50, 0x2c, 0x25, 0xc5, 0x7f, 0x9e, 0x16, - 0x70, 0x5e, 0x47, 0x6f, 0x40, 0x85, 0x44, 0xec, 0x63, 0x1e, 0xc6, 0x51, 0x3e, 0x59, 0xb1, 0x06, - 0xc9, 0x6a, 0xac, 0xdc, 0x7f, 0x74, 0x9e, 0x17, 0x71, 0xd5, 0x4f, 0xc1, 0x9c, 0x8a, 0x30, 0xe6, - 0x0e, 0x15, 0xea, 0x49, 0x05, 0xc6, 0x65, 0x11, 0x57, 0x7d, 0xf4, 0x1e, 0x1c, 0x94, 0x87, 0x4b, - 0xe2, 0x53, 0xa1, 0x76, 0x32, 0xc2, 0xad, 0x64, 0x35, 0x1e, 0xe0, 0xcd, 0x06, 0xde, 0xc6, 0xa1, - 0x7b, 0x70, 0x18, 0x84, 0x41, 0x09, 0xf9, 0x0c, 0x5f, 0x08, 0xb5, 0x9b, 0x51, 0xb3, 0x5d, 0xbc, - 0xdc, 0x6e, 0xe1, 0x5d, 0xac, 0xfe, 0x1b, 0x80, 0x9d, 0xff, 0xd0, 0xfb, 0xa4, 0x7f, 0xd7, 0x86, - 0xfd, 0xff, 0xfd, 0xa3, 0x91, 0xae, 0xdb, 0x71, 0x5f, 0x8b, 0x43, 0xd6, 0xed, 0xe6, 0x67, 0xe2, - 0x17, 0x00, 0x7b, 0x47, 0x7a, 0x1f, 0xee, 0x6d, 0x1b, 0x56, 0xf7, 0x1a, 0x6e, 0x76, 0xfa, 0x0d, - 0x2c, 0x53, 0x47, 0x6f, 0xc2, 0x5e, 0xb9, 0xd3, 0x99, 0x4f, 0xa5, 0x9a, 0x5b, 0xae, 0x3d, 0x5e, - 0x23, 0xd0, 0x19, 0xec, 0x2c, 0x58, 0x30, 0x53, 0xdb, 0x19, 0xf2, 0x85, 0x02, 0xd9, 0x79, 0xc8, - 0x82, 0x19, 0xce, 0x3a, 0x29, 0x22, 0x20, 0x7e, 0xfe, 0x6f, 0x75, 0x03, 0x91, 0x6e, 0x33, 0xce, - 0x3a, 0xfa, 0xaf, 0x00, 0x9e, 0x16, 0xb7, 0x67, 0xad, 0x07, 0xf6, 0xea, 0x6d, 0xfa, 0x6b, 0x1f, - 0xe2, 0xef, 0xdf, 0xa7, 0x23, 0x13, 0x2a, 0xe9, 0x4f, 0x11, 0x11, 0x87, 0xaa, 0x9d, 0x0c, 0x76, - 0xab, 0x80, 0x29, 0x97, 0x65, 0x03, 0x57, 0x18, 0x6b, 0x72, 0x75, 0xad, 0xb5, 0x9e, 0x5d, 0x6b, - 0xad, 0xe7, 0xd7, 0x5a, 0xeb, 0xdb, 0x44, 0x03, 0x57, 0x89, 0x06, 0x9e, 0x25, 0x1a, 0x78, 0x9e, - 0x68, 0xe0, 0xcf, 0x44, 0x03, 0x3f, 0xfe, 0xa5, 0xb5, 0xbe, 0x68, 0x2f, 0xa7, 0xff, 0x04, 0x00, - 0x00, 0xff, 0xff, 0x32, 0xe3, 0x23, 0xf8, 0x2e, 0x0b, 0x00, 0x00, + // 807 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x55, 0xcf, 0x6f, 0xe3, 0x44, + 0x14, 0xce, 0xa4, 0x89, 0x1a, 0x4f, 0x88, 0x42, 0x87, 0x0a, 0x59, 0x05, 0x39, 0x95, 0x91, 0x50, + 0x25, 0xc0, 0x26, 0x05, 0x01, 0x12, 0xea, 0xa1, 0x2e, 0x02, 0x55, 0x2d, 0xa5, 0x9a, 0x0a, 0x0e, + 0x88, 0x03, 0x63, 0x67, 0xea, 0x0e, 0xf1, 0x2f, 0xcd, 0xd8, 0x91, 0x2a, 0x2e, 0x08, 0x89, 0x03, + 0xb7, 0x3d, 0xee, 0xfe, 0x05, 0x7b, 0xd9, 0x3d, 0xee, 0x5f, 0xb0, 0x97, 0x1e, 0x7b, 0xec, 0x29, + 0xda, 0x7a, 0xff, 0x90, 0x5d, 0xf9, 0x57, 0x9c, 0x1f, 0xee, 0x36, 0xa7, 0x48, 0xab, 0x3d, 0xb5, + 0xf3, 0xde, 0xf7, 0xbe, 0xf7, 0xcd, 0xe7, 0x79, 0x2f, 0xf0, 0xfb, 0xe1, 0x77, 0x42, 0x63, 0xbe, + 0x3e, 0x8c, 0x4c, 0xca, 0x3d, 0x1a, 0x52, 0xa1, 0x8f, 0xa8, 0x37, 0xf0, 0xb9, 0x9e, 0x27, 0x48, + 0xc0, 0x74, 0x6e, 0x12, 0x4b, 0x1f, 0xf5, 0x75, 0x9b, 0x7a, 0x94, 0x93, 0x90, 0x0e, 0xb4, 0x80, + 0xfb, 0xa1, 0x8f, 0x50, 0x86, 0xd1, 0x48, 0xc0, 0xb4, 0x04, 0xa3, 0x8d, 0xfa, 0x5b, 0x5f, 0xd8, + 0x2c, 0xbc, 0x88, 0x4c, 0xcd, 0xf2, 0x5d, 0xdd, 0xf6, 0x6d, 0x5f, 0x4f, 0xa1, 0x66, 0x74, 0x9e, + 0x9e, 0xd2, 0x43, 0xfa, 0x5f, 0x46, 0xb1, 0xf5, 0x75, 0xd9, 0xc6, 0x25, 0xd6, 0x05, 0xf3, 0x28, + 0xbf, 0xd4, 0x83, 0xa1, 0x9d, 0x04, 0x84, 0xee, 0xd2, 0x90, 0x54, 0x34, 0xde, 0xd2, 0xef, 0xaa, + 0xe2, 0x91, 0x17, 0x32, 0x97, 0x2e, 0x14, 0x7c, 0x73, 0x5f, 0x81, 0xb0, 0x2e, 0xa8, 0x4b, 0xe6, + 0xeb, 0xd4, 0x47, 0x00, 0x76, 0xf7, 0x6d, 0x9b, 0x53, 0x9b, 0x84, 0xcc, 0xf7, 0x70, 0xe4, 0x50, + 0xf4, 0x1f, 0x80, 0x9b, 0x96, 0x13, 0x89, 0x90, 0x72, 0xec, 0x3b, 0xf4, 0x8c, 0x3a, 0xd4, 0x0a, + 0x7d, 0x2e, 0x64, 0xb0, 0xbd, 0xb6, 0xd3, 0xde, 0xfd, 0x4a, 0x2b, 0x5d, 0x99, 0xf4, 0xd2, 0x82, + 0xa1, 0x9d, 0x04, 0x84, 0x96, 0x5c, 0x49, 0x1b, 0xf5, 0xb5, 0x63, 0x62, 0x52, 0xa7, 0xa8, 0x35, + 0x3e, 0xbe, 0x1a, 0xf7, 0x6a, 0xf1, 0xb8, 0xb7, 0x79, 0x50, 0x41, 0x8c, 0x2b, 0xdb, 0xa9, 0x0f, + 0xeb, 0xb0, 0x3d, 0x05, 0x47, 0x7f, 0xc2, 0x56, 0x42, 0x3e, 0x20, 0x21, 0x91, 0xc1, 0x36, 0xd8, + 0x69, 0xef, 0x7e, 0xb9, 0x9c, 0x94, 0x5f, 0xcc, 0xbf, 0xa8, 0x15, 0xfe, 0x4c, 0x43, 0x62, 0xa0, + 0x5c, 0x07, 0x2c, 0x63, 0x78, 0xc2, 0x8a, 0x0e, 0x60, 0x93, 0x47, 0x0e, 0x15, 0x72, 0x3d, 0xbd, + 0xa9, 0xa2, 0x2d, 0x7e, 0x7f, 0xed, 0xd4, 0x77, 0x98, 0x75, 0x99, 0x18, 0x65, 0x74, 0x72, 0xb2, + 0x66, 0x72, 0x12, 0x38, 0xab, 0x45, 0x26, 0xec, 0x92, 0x59, 0x47, 0xe5, 0xb5, 0x54, 0xed, 0x27, + 0x55, 0x74, 0x73, 0xe6, 0x1b, 0x1f, 0xc4, 0xe3, 0xde, 0xfc, 0x17, 0xc1, 0xf3, 0x84, 0xea, 0xff, + 0x75, 0x88, 0xa6, 0xac, 0x31, 0x98, 0x37, 0x60, 0x9e, 0xbd, 0x02, 0x87, 0x0e, 0x61, 0x4b, 0x44, + 0x69, 0xa2, 0x30, 0xe9, 0xa3, 0xaa, 0x5b, 0x9d, 0x65, 0x18, 0xe3, 0xfd, 0x9c, 0xac, 0x95, 0x07, + 0x04, 0x9e, 0x94, 0xa3, 0x1f, 0xe1, 0x3a, 0xf7, 0x1d, 0x8a, 0xe9, 0x79, 0xee, 0x4f, 0x25, 0x13, + 0xce, 0x20, 0x46, 0x37, 0x67, 0x5a, 0xcf, 0x03, 0xb8, 0x28, 0x56, 0x9f, 0x03, 0xf8, 0xe1, 0xa2, + 0x17, 0xc7, 0x4c, 0x84, 0xe8, 0x8f, 0x05, 0x3f, 0xb4, 0x25, 0x1f, 0x2f, 0x13, 0x99, 0x1b, 0x93, + 0x0b, 0x14, 0x91, 0x29, 0x2f, 0x8e, 0x60, 0x93, 0x85, 0xd4, 0x2d, 0x8c, 0xf8, 0xb4, 0x4a, 0xfe, + 0xa2, 0xb0, 0xf2, 0xd5, 0x1c, 0x26, 0xc5, 0x38, 0xe3, 0x50, 0x9f, 0x01, 0xd8, 0x9d, 0x02, 0xaf, + 0x40, 0xfe, 0x0f, 0xb3, 0xf2, 0x7b, 0xf7, 0xc9, 0xaf, 0xd6, 0xfd, 0x0a, 0x40, 0x58, 0x8e, 0x04, + 0xea, 0xc1, 0xe6, 0x88, 0x72, 0x33, 0xdb, 0x15, 0x92, 0x21, 0x25, 0xf8, 0xdf, 0x92, 0x00, 0xce, + 0xe2, 0xe8, 0x33, 0x28, 0x91, 0x80, 0xfd, 0xc4, 0xfd, 0x28, 0xc8, 0x3a, 0x4b, 0x46, 0x27, 0x1e, + 0xf7, 0xa4, 0xfd, 0xd3, 0xc3, 0x2c, 0x88, 0xcb, 0x7c, 0x02, 0xe6, 0x54, 0xf8, 0x11, 0xb7, 0xa8, + 0x90, 0xd7, 0x4a, 0x30, 0x2e, 0x82, 0xb8, 0xcc, 0xa3, 0x6f, 0x61, 0xa7, 0x38, 0x9c, 0x10, 0x97, + 0x0a, 0xb9, 0x91, 0x16, 0x6c, 0xc4, 0xe3, 0x5e, 0x07, 0x4f, 0x27, 0xf0, 0x2c, 0x0e, 0xed, 0xc1, + 0xae, 0xe7, 0x7b, 0x05, 0xe4, 0x57, 0x7c, 0x2c, 0xe4, 0x66, 0x5a, 0x9a, 0xce, 0xe2, 0xc9, 0x6c, + 0x0a, 0xcf, 0x63, 0xd5, 0xa7, 0x00, 0x36, 0xde, 0xa2, 0xfd, 0xa4, 0xfe, 0x5b, 0x87, 0xed, 0x77, + 0x7e, 0x69, 0x24, 0xe3, 0xb6, 0xda, 0x6d, 0xb1, 0xcc, 0xb8, 0xdd, 0xbf, 0x26, 0x1e, 0x03, 0xd8, + 0x5a, 0xd1, 0x7e, 0xd8, 0x9b, 0x15, 0x2c, 0xdf, 0x29, 0xb8, 0x5a, 0xe9, 0xdf, 0xb0, 0x70, 0x1d, + 0x7d, 0x0e, 0x5b, 0xc5, 0x4c, 0xa7, 0x3a, 0xa5, 0xb2, 0x6f, 0x31, 0xf6, 0x78, 0x82, 0x40, 0xdb, + 0xb0, 0x31, 0x64, 0xde, 0x40, 0xae, 0xa7, 0xc8, 0xf7, 0x72, 0x64, 0xe3, 0x88, 0x79, 0x03, 0x9c, + 0x66, 0x12, 0x84, 0x47, 0xdc, 0xec, 0x67, 0x75, 0x0a, 0x91, 0x4c, 0x33, 0x4e, 0x33, 0xea, 0x13, + 0x00, 0xd7, 0xf3, 0xd7, 0x33, 0xe1, 0x03, 0x77, 0xf2, 0x4d, 0xeb, 0xab, 0x2f, 0xa3, 0xef, 0xcd, + 0xdd, 0x91, 0x0e, 0xa5, 0xe4, 0xaf, 0x08, 0x88, 0x45, 0xe5, 0x46, 0x0a, 0xdb, 0xc8, 0x61, 0xd2, + 0x49, 0x91, 0xc0, 0x25, 0xc6, 0xd8, 0xb9, 0xba, 0x55, 0x6a, 0xd7, 0xb7, 0x4a, 0xed, 0xe6, 0x56, + 0xa9, 0xfd, 0x13, 0x2b, 0xe0, 0x2a, 0x56, 0xc0, 0x75, 0xac, 0x80, 0x9b, 0x58, 0x01, 0x2f, 0x62, + 0x05, 0x3c, 0x78, 0xa9, 0xd4, 0x7e, 0xaf, 0x8f, 0xfa, 0xaf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x24, + 0xa1, 0x47, 0x98, 0xcf, 0x0a, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/generated.proto index 2f8d863df..4b321a7c2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,11 +21,9 @@ syntax = 'proto2'; package k8s.io.api.rbac.v1; -import "k8s.io/api/rbac/v1alpha1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; @@ -62,6 +60,7 @@ message ClusterRoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can only reference a ClusterRole in the global namespace. @@ -134,6 +133,7 @@ message RoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/types.go index 91990548b..17163cbb2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/types.go @@ -124,7 +124,8 @@ type RoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. @@ -199,7 +200,8 @@ type ClusterRoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can only reference a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/types_swagger_doc_generated.go index 280ae5a82..0ec20c88e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AggregationRule = map[string]string{ "": "AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole", "clusterRoleSelectors": "ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. If any of the selectors match, then the ClusterRole's permissions will be added", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/zz_generated.deepcopy.go index 0a2a4d08e..be1592f77 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/generated.pb.go index c07cdc75d..71eced8d4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2693,58 +2693,57 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 844 bytes of a gzipped FileDescriptorProto + // 830 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x55, 0xbf, 0x8f, 0xe3, 0x44, - 0x14, 0xce, 0x64, 0x13, 0x36, 0x99, 0x65, 0x15, 0x6e, 0x38, 0x21, 0x6b, 0x85, 0x9c, 0xc5, 0x02, - 0xe9, 0x10, 0x87, 0xcd, 0xee, 0x21, 0xa0, 0xa1, 0x58, 0x5f, 0x81, 0x16, 0x96, 0xbd, 0x65, 0x4e, - 0x5c, 0x81, 0x28, 0x98, 0x38, 0x73, 0xce, 0x10, 0xdb, 0x63, 0xcd, 0x8c, 0x23, 0x9d, 0x68, 0x68, - 0x68, 0x11, 0x0d, 0x05, 0x3d, 0x2d, 0x0d, 0x94, 0xfc, 0x03, 0x4b, 0x77, 0xe5, 0x56, 0x11, 0x6b, - 0xfe, 0x10, 0x90, 0xc7, 0x76, 0xec, 0xfc, 0x22, 0xa9, 0x22, 0x21, 0x51, 0x25, 0xf3, 0xde, 0xf7, - 0xbe, 0xf7, 0xde, 0x37, 0xf3, 0x9e, 0xe1, 0xd9, 0xf8, 0x03, 0x69, 0x33, 0xee, 0x8c, 0x93, 0x01, - 0x15, 0x11, 0x55, 0x54, 0x3a, 0x13, 0x1a, 0x0d, 0xb9, 0x70, 0x0a, 0x07, 0x89, 0x99, 0x23, 0x06, - 0xc4, 0x73, 0x26, 0x27, 0x24, 0x88, 0x47, 0xe4, 0xc4, 0xf1, 0x69, 0x44, 0x05, 0x51, 0x74, 0x68, - 0xc7, 0x82, 0x2b, 0x8e, 0x8c, 0x1c, 0x69, 0x93, 0x98, 0xd9, 0x19, 0xd2, 0x2e, 0x91, 0x47, 0x6f, - 0xfb, 0x4c, 0x8d, 0x92, 0x81, 0xed, 0xf1, 0xd0, 0xf1, 0xb9, 0xcf, 0x1d, 0x1d, 0x30, 0x48, 0x9e, - 0xea, 0x93, 0x3e, 0xe8, 0x7f, 0x39, 0xd1, 0xd1, 0xbb, 0x55, 0xca, 0x90, 0x78, 0x23, 0x16, 0x51, - 0xf1, 0xcc, 0x89, 0xc7, 0x7e, 0x66, 0x90, 0x4e, 0x48, 0x15, 0x71, 0x26, 0x4b, 0xe9, 0x8f, 0x9c, - 0x75, 0x51, 0x22, 0x89, 0x14, 0x0b, 0xe9, 0x52, 0xc0, 0x7b, 0x9b, 0x02, 0xa4, 0x37, 0xa2, 0x21, - 0x59, 0x8a, 0x7b, 0xb0, 0x2e, 0x2e, 0x51, 0x2c, 0x70, 0x58, 0xa4, 0xa4, 0x12, 0x8b, 0x41, 0xd6, - 0x4f, 0x00, 0xf6, 0xce, 0x7c, 0x5f, 0x50, 0x9f, 0x28, 0xc6, 0x23, 0x9c, 0x04, 0x14, 0x7d, 0x07, - 0xe0, 0x5d, 0x2f, 0x48, 0xa4, 0xa2, 0x02, 0xf3, 0x80, 0x3e, 0xa6, 0x01, 0xf5, 0x14, 0x17, 0xd2, - 0x00, 0xc7, 0x7b, 0xf7, 0x0e, 0x4e, 0x1f, 0xd8, 0x95, 0xa0, 0xb3, 0x44, 0x76, 0x3c, 0xf6, 0x33, - 0x83, 0xb4, 0x33, 0x1d, 0xec, 0xc9, 0x89, 0x7d, 0x41, 0x06, 0x34, 0x28, 0x63, 0xdd, 0x57, 0xaf, - 0xa7, 0xfd, 0x46, 0x3a, 0xed, 0xdf, 0x7d, 0xb8, 0x82, 0x18, 0xaf, 0x4c, 0x67, 0xfd, 0xdc, 0x84, - 0x07, 0x35, 0x38, 0xfa, 0x0a, 0x76, 0x32, 0xf2, 0x21, 0x51, 0xc4, 0x00, 0xc7, 0xe0, 0xde, 0xc1, - 0xe9, 0x3b, 0xdb, 0x95, 0xf2, 0x68, 0xf0, 0x35, 0xf5, 0xd4, 0xa7, 0x54, 0x11, 0x17, 0x15, 0x75, - 0xc0, 0xca, 0x86, 0x67, 0xac, 0xe8, 0x1c, 0xb6, 0x45, 0x12, 0x50, 0x69, 0x34, 0x75, 0xa7, 0xaf, - 0xdb, 0xeb, 0x9e, 0x8e, 0x7d, 0xc5, 0x03, 0xe6, 0x3d, 0xcb, 0xe4, 0x72, 0x0f, 0x0b, 0xca, 0x76, - 0x76, 0x92, 0x38, 0x67, 0x40, 0x23, 0xd8, 0x23, 0xf3, 0xba, 0x1a, 0x7b, 0xba, 0xe6, 0x37, 0xd7, - 0x93, 0x2e, 0x5c, 0x84, 0xfb, 0x72, 0x3a, 0xed, 0x2f, 0xde, 0x0e, 0x5e, 0xa4, 0xb5, 0x7e, 0x6c, - 0x42, 0x54, 0x93, 0xc9, 0x65, 0xd1, 0x90, 0x45, 0xfe, 0x0e, 0xd4, 0x7a, 0x04, 0x3b, 0x32, 0xd1, - 0x8e, 0x52, 0xb0, 0xd7, 0xd6, 0xf7, 0xf6, 0x38, 0x47, 0xba, 0x2f, 0x15, 0x94, 0x9d, 0xc2, 0x20, - 0xf1, 0x8c, 0x04, 0x5d, 0xc0, 0x7d, 0xc1, 0x03, 0x8a, 0xe9, 0xd3, 0x42, 0xab, 0x7f, 0xe1, 0xc3, - 0x39, 0xd0, 0xed, 0x15, 0x7c, 0xfb, 0x85, 0x01, 0x97, 0x14, 0xd6, 0x1f, 0x00, 0xbe, 0xb2, 0xac, - 0xcb, 0x05, 0x93, 0x0a, 0x7d, 0xb9, 0xa4, 0x8d, 0xbd, 0xe5, 0xa3, 0x66, 0x32, 0x57, 0x66, 0xd6, - 0x46, 0x69, 0xa9, 0xe9, 0xf2, 0x19, 0x6c, 0x33, 0x45, 0xc3, 0x52, 0x94, 0xfb, 0xeb, 0x9b, 0x58, - 0x2e, 0xaf, 0x7a, 0x4d, 0xe7, 0x19, 0x05, 0xce, 0x99, 0xac, 0xdf, 0x01, 0xec, 0xd5, 0xc0, 0x3b, - 0x68, 0xe2, 0xe3, 0xf9, 0x26, 0xde, 0xd8, 0xae, 0x89, 0xd5, 0xd5, 0xff, 0x0d, 0x20, 0xac, 0x06, - 0x06, 0xf5, 0x61, 0x7b, 0x42, 0xc5, 0x20, 0xdf, 0x27, 0x5d, 0xb7, 0x9b, 0xe1, 0x9f, 0x64, 0x06, - 0x9c, 0xdb, 0xd1, 0x5b, 0xb0, 0x4b, 0x62, 0xf6, 0x91, 0xe0, 0x49, 0x2c, 0x8d, 0x3d, 0x0d, 0x3a, - 0x4c, 0xa7, 0xfd, 0xee, 0xd9, 0xd5, 0x79, 0x6e, 0xc4, 0x95, 0x3f, 0x03, 0x0b, 0x2a, 0x79, 0x22, - 0x3c, 0x2a, 0x8d, 0x56, 0x05, 0xc6, 0xa5, 0x11, 0x57, 0x7e, 0xf4, 0x3e, 0x3c, 0x2c, 0x0f, 0x97, - 0x24, 0xa4, 0xd2, 0x68, 0xeb, 0x80, 0x3b, 0xe9, 0xb4, 0x7f, 0x88, 0xeb, 0x0e, 0x3c, 0x8f, 0x43, - 0x1f, 0xc2, 0x5e, 0xc4, 0xa3, 0x12, 0xf2, 0x39, 0xbe, 0x90, 0xc6, 0x0b, 0x3a, 0x54, 0xcf, 0xe8, - 0xe5, 0xbc, 0x0b, 0x2f, 0x62, 0xad, 0xdf, 0x00, 0x6c, 0xfd, 0xe7, 0x76, 0x98, 0xf5, 0x7d, 0x13, - 0x1e, 0xfc, 0xbf, 0x52, 0x6a, 0x2b, 0x25, 0x1b, 0xc3, 0xdd, 0xee, 0x92, 0xed, 0xc7, 0x70, 0xf3, - 0x12, 0xf9, 0x05, 0xc0, 0xce, 0x8e, 0xb6, 0xc7, 0xc3, 0xf9, 0xb2, 0xcd, 0x0d, 0x65, 0xaf, 0xae, - 0xf7, 0x1b, 0x58, 0xde, 0x00, 0xba, 0x0f, 0x3b, 0xe5, 0xc4, 0xeb, 0x6a, 0xbb, 0x55, 0xf6, 0x72, - 0x29, 0xe0, 0x19, 0x02, 0x1d, 0xc3, 0xd6, 0x98, 0x45, 0x43, 0xa3, 0xa9, 0x91, 0x2f, 0x16, 0xc8, - 0xd6, 0x27, 0x2c, 0x1a, 0x62, 0xed, 0xc9, 0x10, 0x11, 0x09, 0xf3, 0x4f, 0x72, 0x0d, 0x91, 0xcd, - 0x3a, 0xd6, 0x1e, 0xeb, 0x57, 0x00, 0xf7, 0x8b, 0xf7, 0x34, 0xe3, 0x03, 0x6b, 0xf9, 0x4e, 0x21, - 0x24, 0x31, 0x7b, 0x42, 0x85, 0x64, 0x3c, 0x2a, 0xf2, 0xce, 0x5e, 0xfa, 0xd9, 0xd5, 0x79, 0xe1, - 0xc1, 0x35, 0xd4, 0xe6, 0x1a, 0x90, 0x03, 0xbb, 0xd9, 0xaf, 0x8c, 0x89, 0x47, 0x8d, 0x96, 0x86, - 0xdd, 0x29, 0x60, 0xdd, 0xcb, 0xd2, 0x81, 0x2b, 0x8c, 0x6b, 0x5f, 0xdf, 0x9a, 0x8d, 0xe7, 0xb7, - 0x66, 0xe3, 0xe6, 0xd6, 0x6c, 0x7c, 0x9b, 0x9a, 0xe0, 0x3a, 0x35, 0xc1, 0xf3, 0xd4, 0x04, 0x37, - 0xa9, 0x09, 0xfe, 0x4c, 0x4d, 0xf0, 0xc3, 0x5f, 0x66, 0xe3, 0x8b, 0x4e, 0x29, 0xfe, 0x3f, 0x01, - 0x00, 0x00, 0xff, 0xff, 0xeb, 0xcc, 0xe2, 0x61, 0x5e, 0x0b, 0x00, 0x00, + 0x14, 0xce, 0x64, 0x13, 0x36, 0x99, 0x25, 0x0a, 0x37, 0x9c, 0x90, 0xb5, 0x42, 0xce, 0x62, 0x81, + 0x74, 0x88, 0xc3, 0x66, 0x17, 0x04, 0x34, 0x14, 0xf1, 0x15, 0x28, 0x10, 0xf6, 0x96, 0x39, 0x71, + 0x05, 0xa2, 0x60, 0xe2, 0xcc, 0x39, 0x43, 0x6c, 0x8f, 0x35, 0x63, 0x47, 0x3a, 0xd1, 0xd0, 0xd0, + 0x22, 0x1a, 0x0a, 0x7a, 0x5a, 0x1a, 0x28, 0xf9, 0x07, 0x96, 0xee, 0xca, 0xad, 0x22, 0xd6, 0xfc, + 0x21, 0x20, 0x8f, 0xed, 0xd8, 0xf9, 0x45, 0x52, 0x45, 0x42, 0xba, 0x2a, 0x99, 0xf7, 0xbe, 0xf7, + 0xbd, 0xf7, 0xbe, 0x99, 0xf7, 0x0c, 0xfb, 0xd3, 0x0f, 0xa5, 0xc9, 0xb8, 0x35, 0x8d, 0x47, 0x54, + 0x04, 0x34, 0xa2, 0xd2, 0x9a, 0xd1, 0x60, 0xcc, 0x85, 0x95, 0x3b, 0x48, 0xc8, 0x2c, 0x31, 0x22, + 0x8e, 0x35, 0x3b, 0x27, 0x5e, 0x38, 0x21, 0xe7, 0x96, 0x4b, 0x03, 0x2a, 0x48, 0x44, 0xc7, 0x66, + 0x28, 0x78, 0xc4, 0x91, 0x96, 0x21, 0x4d, 0x12, 0x32, 0x33, 0x45, 0x9a, 0x05, 0xf2, 0xf4, 0x6d, + 0x97, 0x45, 0x93, 0x78, 0x64, 0x3a, 0xdc, 0xb7, 0x5c, 0xee, 0x72, 0x4b, 0x05, 0x8c, 0xe2, 0x27, + 0xea, 0xa4, 0x0e, 0xea, 0x5f, 0x46, 0x74, 0xfa, 0x5e, 0x99, 0xd2, 0x27, 0xce, 0x84, 0x05, 0x54, + 0x3c, 0xb5, 0xc2, 0xa9, 0x9b, 0x1a, 0xa4, 0xe5, 0xd3, 0x88, 0x58, 0xb3, 0xb5, 0xf4, 0xa7, 0xd6, + 0xb6, 0x28, 0x11, 0x07, 0x11, 0xf3, 0xe9, 0x5a, 0xc0, 0xfb, 0xbb, 0x02, 0xa4, 0x33, 0xa1, 0x3e, + 0x59, 0x8d, 0x33, 0x7e, 0x06, 0xb0, 0xdb, 0x77, 0x5d, 0x41, 0x5d, 0x12, 0x31, 0x1e, 0xe0, 0xd8, + 0xa3, 0xe8, 0x7b, 0x00, 0xef, 0x3a, 0x5e, 0x2c, 0x23, 0x2a, 0x30, 0xf7, 0xe8, 0x23, 0xea, 0x51, + 0x27, 0xe2, 0x42, 0x6a, 0xe0, 0xec, 0xe8, 0xde, 0xc9, 0xc5, 0xbb, 0x66, 0xa9, 0xcd, 0x22, 0x97, + 0x19, 0x4e, 0xdd, 0xd4, 0x20, 0xcd, 0xb4, 0x25, 0x73, 0x76, 0x6e, 0x0e, 0xc9, 0x88, 0x7a, 0x45, + 0xac, 0xfd, 0xea, 0xf5, 0xbc, 0x57, 0x4b, 0xe6, 0xbd, 0xbb, 0x0f, 0x36, 0x10, 0xe3, 0x8d, 0xe9, + 0x8c, 0x5f, 0xea, 0xf0, 0xa4, 0x02, 0x47, 0x5f, 0xc3, 0x56, 0x4a, 0x3e, 0x26, 0x11, 0xd1, 0xc0, + 0x19, 0xb8, 0x77, 0x72, 0xf1, 0xce, 0x7e, 0xa5, 0x3c, 0x1c, 0x7d, 0x43, 0x9d, 0xe8, 0x33, 0x1a, + 0x11, 0x1b, 0xe5, 0x75, 0xc0, 0xd2, 0x86, 0x17, 0xac, 0x68, 0x00, 0x9b, 0x22, 0xf6, 0xa8, 0xd4, + 0xea, 0xaa, 0xd3, 0xd7, 0xcd, 0x6d, 0xaf, 0xc0, 0xbc, 0xe2, 0x1e, 0x73, 0x9e, 0xa6, 0x72, 0xd9, + 0x9d, 0x9c, 0xb2, 0x99, 0x9e, 0x24, 0xce, 0x18, 0xd0, 0x04, 0x76, 0xc9, 0xb2, 0xae, 0xda, 0x91, + 0xaa, 0xf9, 0xcd, 0xed, 0xa4, 0x2b, 0x17, 0x61, 0xbf, 0x9c, 0xcc, 0x7b, 0xab, 0xb7, 0x83, 0x57, + 0x69, 0x8d, 0x9f, 0xea, 0x10, 0x55, 0x64, 0xb2, 0x59, 0x30, 0x66, 0x81, 0x7b, 0x00, 0xb5, 0x1e, + 0xc2, 0x96, 0x8c, 0x95, 0xa3, 0x10, 0xec, 0xb5, 0xed, 0xbd, 0x3d, 0xca, 0x90, 0xf6, 0x4b, 0x39, + 0x65, 0x2b, 0x37, 0x48, 0xbc, 0x20, 0x41, 0x43, 0x78, 0x2c, 0xb8, 0x47, 0x31, 0x7d, 0x92, 0x6b, + 0xf5, 0x1f, 0x7c, 0x38, 0x03, 0xda, 0xdd, 0x9c, 0xef, 0x38, 0x37, 0xe0, 0x82, 0xc2, 0xf8, 0x13, + 0xc0, 0x57, 0xd6, 0x75, 0x19, 0x32, 0x19, 0xa1, 0xaf, 0xd6, 0xb4, 0x31, 0xf7, 0x7c, 0xd4, 0x4c, + 0x66, 0xca, 0x2c, 0xda, 0x28, 0x2c, 0x15, 0x5d, 0x3e, 0x87, 0x4d, 0x16, 0x51, 0xbf, 0x10, 0xe5, + 0xfe, 0xf6, 0x26, 0xd6, 0xcb, 0x2b, 0x5f, 0xd3, 0x20, 0xa5, 0xc0, 0x19, 0x93, 0xf1, 0x07, 0x80, + 0xdd, 0x0a, 0xf8, 0x00, 0x4d, 0x7c, 0xb2, 0xdc, 0xc4, 0x1b, 0xfb, 0x35, 0xb1, 0xb9, 0xfa, 0x7f, + 0x00, 0x84, 0xe5, 0xc0, 0xa0, 0x1e, 0x6c, 0xce, 0xa8, 0x18, 0x65, 0xfb, 0xa4, 0x6d, 0xb7, 0x53, + 0xfc, 0xe3, 0xd4, 0x80, 0x33, 0x3b, 0x7a, 0x0b, 0xb6, 0x49, 0xc8, 0x3e, 0x16, 0x3c, 0x0e, 0xa5, + 0x76, 0xa4, 0x40, 0x9d, 0x64, 0xde, 0x6b, 0xf7, 0xaf, 0x06, 0x99, 0x11, 0x97, 0xfe, 0x14, 0x2c, + 0xa8, 0xe4, 0xb1, 0x70, 0xa8, 0xd4, 0x1a, 0x25, 0x18, 0x17, 0x46, 0x5c, 0xfa, 0xd1, 0x07, 0xb0, + 0x53, 0x1c, 0x2e, 0x89, 0x4f, 0xa5, 0xd6, 0x54, 0x01, 0x77, 0x92, 0x79, 0xaf, 0x83, 0xab, 0x0e, + 0xbc, 0x8c, 0x43, 0x1f, 0xc1, 0x6e, 0xc0, 0x83, 0x02, 0xf2, 0x05, 0x1e, 0x4a, 0xed, 0x05, 0x15, + 0xaa, 0x66, 0xf4, 0x72, 0xd9, 0x85, 0x57, 0xb1, 0xc6, 0xef, 0x00, 0x36, 0xfe, 0x77, 0x3b, 0xcc, + 0xf8, 0xa1, 0x0e, 0x4f, 0x9e, 0xaf, 0x94, 0xca, 0x4a, 0x49, 0xc7, 0xf0, 0xb0, 0xbb, 0x64, 0xff, + 0x31, 0xdc, 0xbd, 0x44, 0x7e, 0x05, 0xb0, 0x75, 0xa0, 0xed, 0xf1, 0x60, 0xb9, 0x6c, 0x7d, 0x47, + 0xd9, 0x9b, 0xeb, 0xfd, 0x16, 0x16, 0x37, 0x80, 0xee, 0xc3, 0x56, 0x31, 0xf1, 0xaa, 0xda, 0x76, + 0x99, 0xbd, 0x58, 0x0a, 0x78, 0x81, 0x40, 0x67, 0xb0, 0x31, 0x65, 0xc1, 0x58, 0xab, 0x2b, 0xe4, + 0x8b, 0x39, 0xb2, 0xf1, 0x29, 0x0b, 0xc6, 0x58, 0x79, 0x52, 0x44, 0x40, 0xfc, 0xec, 0x93, 0x5c, + 0x41, 0xa4, 0xb3, 0x8e, 0x95, 0xc7, 0xf8, 0x0d, 0xc0, 0xe3, 0xfc, 0x3d, 0x2d, 0xf8, 0xc0, 0x56, + 0xbe, 0x0b, 0x08, 0x49, 0xc8, 0x1e, 0x53, 0x21, 0x19, 0x0f, 0xf2, 0xbc, 0x8b, 0x97, 0xde, 0xbf, + 0x1a, 0xe4, 0x1e, 0x5c, 0x41, 0xed, 0xae, 0x01, 0x59, 0xb0, 0x9d, 0xfe, 0xca, 0x90, 0x38, 0x54, + 0x6b, 0x28, 0xd8, 0x9d, 0x1c, 0xd6, 0xbe, 0x2c, 0x1c, 0xb8, 0xc4, 0xd8, 0xe6, 0xf5, 0xad, 0x5e, + 0x7b, 0x76, 0xab, 0xd7, 0x6e, 0x6e, 0xf5, 0xda, 0x77, 0x89, 0x0e, 0xae, 0x13, 0x1d, 0x3c, 0x4b, + 0x74, 0x70, 0x93, 0xe8, 0xe0, 0xaf, 0x44, 0x07, 0x3f, 0xfe, 0xad, 0xd7, 0xbe, 0x6c, 0x15, 0xe2, + 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xb0, 0x73, 0x15, 0x10, 0x29, 0x0b, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/generated.proto index 41a193f55..cde3aaac9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.rbac.v1alpha1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; @@ -61,6 +60,7 @@ message ClusterRoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can only reference a ClusterRole in the global namespace. @@ -134,6 +134,7 @@ message RoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/types.go index 843d998ec..398d6a169 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/types.go @@ -126,7 +126,8 @@ type RoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. @@ -201,7 +202,8 @@ type ClusterRoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can only reference a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/types_swagger_doc_generated.go index e56cd0f10..1d6ef30b0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AggregationRule = map[string]string{ "": "AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole", "clusterRoleSelectors": "ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. If any of the selectors match, then the ClusterRole's permissions will be added", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/zz_generated.deepcopy.go index 562451cd6..1d29acff3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/generated.pb.go index c2525e0df..71e5799e3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2693,58 +2693,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 833 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x55, 0xbf, 0x8f, 0xe3, 0x44, - 0x14, 0xce, 0x64, 0x13, 0x6d, 0x3c, 0xcb, 0x2a, 0xdc, 0x70, 0x02, 0x6b, 0x05, 0xce, 0x2a, 0x50, - 0x44, 0x3a, 0xce, 0x66, 0xef, 0x10, 0xd0, 0x20, 0x71, 0xa6, 0x80, 0xd5, 0x2d, 0x61, 0x35, 0x27, - 0x28, 0x10, 0x05, 0x63, 0x67, 0xce, 0x19, 0xe2, 0x5f, 0x9a, 0x19, 0x47, 0x3a, 0xd1, 0xd0, 0xd0, - 0x51, 0x20, 0x51, 0xd1, 0x52, 0x53, 0x51, 0xf2, 0x17, 0xa4, 0xbc, 0xf2, 0xaa, 0x88, 0x35, 0x7f, - 0x08, 0x68, 0xfc, 0x23, 0x4e, 0xe2, 0xf8, 0x2e, 0x55, 0x24, 0xa4, 0xab, 0x76, 0xe7, 0xbd, 0xef, - 0x7d, 0xef, 0x7b, 0x9f, 0x67, 0x5e, 0xe0, 0x27, 0xb3, 0x8f, 0x84, 0xc9, 0x22, 0x6b, 0x96, 0x38, - 0x94, 0x87, 0x54, 0x52, 0x61, 0xcd, 0x69, 0x38, 0x89, 0xb8, 0x55, 0x24, 0x48, 0xcc, 0x2c, 0xee, - 0x10, 0xd7, 0x9a, 0x5f, 0x38, 0x54, 0x92, 0x0b, 0xcb, 0xa3, 0x21, 0xe5, 0x44, 0xd2, 0x89, 0x19, - 0xf3, 0x48, 0x46, 0xe8, 0x8d, 0x1c, 0x68, 0x92, 0x98, 0x99, 0x0a, 0x68, 0x16, 0xc0, 0xb3, 0xbb, - 0x1e, 0x93, 0xd3, 0xc4, 0x31, 0xdd, 0x28, 0xb0, 0xbc, 0xc8, 0x8b, 0xac, 0x0c, 0xef, 0x24, 0x8f, - 0xb3, 0x53, 0x76, 0xc8, 0xfe, 0xcb, 0x79, 0xce, 0x46, 0xf5, 0x86, 0xc4, 0x8f, 0xa7, 0xf5, 0x8e, - 0x67, 0xef, 0x57, 0xc8, 0x80, 0xb8, 0x53, 0x16, 0x52, 0xfe, 0xc4, 0x8a, 0x67, 0x9e, 0x0a, 0x08, - 0x2b, 0xa0, 0x92, 0x58, 0xf3, 0x7a, 0x95, 0xd5, 0x54, 0xc5, 0x93, 0x50, 0xb2, 0x80, 0xd6, 0x0a, - 0x3e, 0x78, 0x51, 0x81, 0x70, 0xa7, 0x34, 0x20, 0xb5, 0xba, 0xfb, 0x4d, 0x75, 0x89, 0x64, 0xbe, - 0xc5, 0x42, 0x29, 0x24, 0xdf, 0x2e, 0x1a, 0xfe, 0x06, 0x60, 0xff, 0x81, 0xe7, 0x71, 0xea, 0x11, - 0xc9, 0xa2, 0x10, 0x27, 0x3e, 0x45, 0x3f, 0x01, 0x78, 0xdb, 0xf5, 0x13, 0x21, 0x29, 0xc7, 0x91, - 0x4f, 0x1f, 0x51, 0x9f, 0xba, 0x32, 0xe2, 0x42, 0x07, 0xe7, 0x47, 0xa3, 0x93, 0x7b, 0xf7, 0xcd, - 0xca, 0xf9, 0x55, 0x23, 0x33, 0x9e, 0x79, 0x2a, 0x20, 0x4c, 0xe5, 0x83, 0x39, 0xbf, 0x30, 0xaf, - 0x88, 0x43, 0xfd, 0xb2, 0xd6, 0x7e, 0x73, 0xb1, 0x1c, 0xb4, 0xd2, 0xe5, 0xe0, 0xf6, 0xa7, 0x3b, - 0x88, 0xf1, 0xce, 0x76, 0xc3, 0xdf, 0xdb, 0xf0, 0x64, 0x0d, 0x8e, 0xbe, 0x83, 0x3d, 0x45, 0x3e, - 0x21, 0x92, 0xe8, 0xe0, 0x1c, 0x8c, 0x4e, 0xee, 0xbd, 0xb7, 0x9f, 0x94, 0x2f, 0x9d, 0xef, 0xa9, - 0x2b, 0xbf, 0xa0, 0x92, 0xd8, 0xa8, 0xd0, 0x01, 0xab, 0x18, 0x5e, 0xb1, 0xa2, 0xcf, 0x61, 0x97, - 0x27, 0x3e, 0x15, 0x7a, 0x3b, 0x9b, 0xf4, 0x6d, 0xb3, 0xe1, 0x8e, 0x99, 0xd7, 0x91, 0xcf, 0xdc, - 0x27, 0xca, 0x2d, 0xfb, 0xb4, 0x60, 0xec, 0xaa, 0x93, 0xc0, 0x39, 0x01, 0xf2, 0x60, 0x9f, 0x6c, - 0xda, 0xaa, 0x1f, 0x65, 0x92, 0x47, 0x8d, 0x9c, 0x5b, 0x9f, 0xc1, 0x7e, 0x2d, 0x5d, 0x0e, 0xb6, - 0xbf, 0x0d, 0xde, 0x66, 0x1d, 0xfe, 0xda, 0x86, 0x68, 0xcd, 0x24, 0x9b, 0x85, 0x13, 0x16, 0x7a, - 0x07, 0xf0, 0x6a, 0x0c, 0x7b, 0x22, 0xc9, 0x12, 0xa5, 0x5d, 0xe7, 0x8d, 0xa3, 0x3d, 0xca, 0x81, - 0xf6, 0xab, 0x05, 0x63, 0xaf, 0x08, 0x08, 0xbc, 0xe2, 0x40, 0x0f, 0xe1, 0x31, 0x8f, 0x7c, 0x8a, - 0xe9, 0xe3, 0xc2, 0xa9, 0x66, 0x3a, 0x9c, 0xe3, 0xec, 0x7e, 0x41, 0x77, 0x5c, 0x04, 0x70, 0xc9, - 0x30, 0x5c, 0x00, 0xf8, 0x7a, 0xdd, 0x95, 0x2b, 0x26, 0x24, 0xfa, 0xb6, 0xe6, 0x8c, 0xb9, 0xe7, - 0x85, 0x66, 0x22, 0xf7, 0x65, 0x35, 0x45, 0x19, 0x59, 0x73, 0xe5, 0x1a, 0x76, 0x99, 0xa4, 0x41, - 0x69, 0xc9, 0x9d, 0xc6, 0x19, 0xea, 0xea, 0xaa, 0x9b, 0x74, 0xa9, 0x18, 0x70, 0x4e, 0x34, 0xfc, - 0x0b, 0xc0, 0xfe, 0x1a, 0xf8, 0x00, 0x33, 0x5c, 0x6e, 0xce, 0xf0, 0xce, 0x5e, 0x33, 0xec, 0x16, - 0xff, 0x2f, 0x80, 0xb0, 0x7a, 0x2b, 0x68, 0x00, 0xbb, 0x73, 0xca, 0x9d, 0x7c, 0x93, 0x68, 0xb6, - 0xa6, 0xf0, 0x5f, 0xab, 0x00, 0xce, 0xe3, 0xe8, 0x0e, 0xd4, 0x48, 0xcc, 0x3e, 0xe3, 0x51, 0x12, - 0xe7, 0xed, 0x35, 0xfb, 0x34, 0x5d, 0x0e, 0xb4, 0x07, 0xd7, 0x97, 0x79, 0x10, 0x57, 0x79, 0x05, - 0xe6, 0x54, 0x44, 0x09, 0x77, 0xa9, 0xd0, 0x8f, 0x2a, 0x30, 0x2e, 0x83, 0xb8, 0xca, 0xa3, 0x0f, - 0xe1, 0x69, 0x79, 0x18, 0x93, 0x80, 0x0a, 0xbd, 0x93, 0x15, 0xdc, 0x4a, 0x97, 0x83, 0x53, 0xbc, - 0x9e, 0xc0, 0x9b, 0x38, 0xf4, 0x31, 0xec, 0x87, 0x51, 0x58, 0x42, 0xbe, 0xc2, 0x57, 0x42, 0xef, - 0x66, 0xa5, 0xd9, 0xfb, 0x1c, 0x6f, 0xa6, 0xf0, 0x36, 0x76, 0xf8, 0x27, 0x80, 0x9d, 0xff, 0xdb, - 0xf6, 0x1a, 0xfe, 0xdc, 0x86, 0x27, 0x2f, 0xb7, 0xc9, 0x6a, 0x9b, 0xa8, 0x27, 0x78, 0xd8, 0x35, - 0xb2, 0xf7, 0x13, 0x7c, 0xf1, 0xfe, 0xf8, 0x03, 0xc0, 0xde, 0x81, 0x16, 0x87, 0xbd, 0xa9, 0xfa, - 0xad, 0xe7, 0xab, 0xde, 0x2d, 0xf7, 0x07, 0x58, 0xfa, 0x8f, 0xde, 0x85, 0xbd, 0xf2, 0xb1, 0x67, - 0x62, 0xb5, 0xaa, 0x79, 0xb9, 0x0f, 0xf0, 0x0a, 0x81, 0xce, 0x61, 0x67, 0xc6, 0xc2, 0x89, 0xde, - 0xce, 0x90, 0xaf, 0x14, 0xc8, 0xce, 0x43, 0x16, 0x4e, 0x70, 0x96, 0x51, 0x88, 0x90, 0x04, 0xf9, - 0x0f, 0xf1, 0x1a, 0x42, 0x3d, 0x73, 0x9c, 0x65, 0x94, 0x57, 0xc7, 0xc5, 0x65, 0x5a, 0xf1, 0x81, - 0x46, 0xbe, 0x75, 0x7d, 0xed, 0x7d, 0xf4, 0x3d, 0xbf, 0x3b, 0xb2, 0xa0, 0xa6, 0xfe, 0x8a, 0x98, - 0xb8, 0x54, 0xef, 0x64, 0xb0, 0x5b, 0x05, 0x4c, 0x1b, 0x97, 0x09, 0x5c, 0x61, 0xec, 0xbb, 0x8b, - 0x1b, 0xa3, 0xf5, 0xf4, 0xc6, 0x68, 0x3d, 0xbb, 0x31, 0x5a, 0x3f, 0xa6, 0x06, 0x58, 0xa4, 0x06, - 0x78, 0x9a, 0x1a, 0xe0, 0x59, 0x6a, 0x80, 0xbf, 0x53, 0x03, 0xfc, 0xf2, 0x8f, 0xd1, 0xfa, 0xe6, - 0xb8, 0x70, 0xfd, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd1, 0x99, 0xaf, 0xff, 0x74, 0x0b, 0x00, - 0x00, + // 808 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x55, 0xbd, 0x6f, 0xfb, 0x44, + 0x18, 0xce, 0xa5, 0x89, 0x12, 0x5f, 0x88, 0xc2, 0xef, 0xa8, 0xc0, 0xaa, 0xc0, 0x89, 0x02, 0x43, + 0xa5, 0x52, 0x9b, 0x16, 0x04, 0x2c, 0x48, 0xd4, 0x0c, 0x50, 0xb5, 0x84, 0xea, 0x2a, 0x18, 0x10, + 0x03, 0x67, 0xe7, 0xea, 0x1e, 0xf1, 0x97, 0xee, 0xec, 0x48, 0x15, 0x0b, 0x0b, 0x1b, 0x03, 0x12, + 0x13, 0x2b, 0x33, 0x13, 0x23, 0x7f, 0x41, 0xc6, 0x8e, 0x9d, 0x22, 0x6a, 0xfe, 0x10, 0xd0, 0xf9, + 0x23, 0xce, 0x67, 0x9b, 0x29, 0x12, 0x12, 0x53, 0x7b, 0xef, 0xfb, 0xbc, 0xcf, 0xfb, 0xbc, 0x8f, + 0xef, 0xde, 0xc0, 0x8f, 0x47, 0x1f, 0x0a, 0x9d, 0x05, 0xc6, 0x28, 0xb6, 0x28, 0xf7, 0x69, 0x44, + 0x85, 0x31, 0xa6, 0xfe, 0x30, 0xe0, 0x46, 0x9e, 0x20, 0x21, 0x33, 0xb8, 0x45, 0x6c, 0x63, 0x7c, + 0x62, 0xd1, 0x88, 0x9c, 0x18, 0x0e, 0xf5, 0x29, 0x27, 0x11, 0x1d, 0xea, 0x21, 0x0f, 0xa2, 0x00, + 0xbd, 0x96, 0x01, 0x75, 0x12, 0x32, 0x5d, 0x02, 0xf5, 0x1c, 0x78, 0x70, 0xec, 0xb0, 0xe8, 0x36, + 0xb6, 0x74, 0x3b, 0xf0, 0x0c, 0x27, 0x70, 0x02, 0x23, 0xc5, 0x5b, 0xf1, 0x4d, 0x7a, 0x4a, 0x0f, + 0xe9, 0x7f, 0x19, 0xcf, 0xc1, 0x7b, 0x65, 0x43, 0x8f, 0xd8, 0xb7, 0xcc, 0xa7, 0xfc, 0xce, 0x08, + 0x47, 0x8e, 0x0c, 0x08, 0xc3, 0xa3, 0x11, 0x31, 0xc6, 0x2b, 0xdd, 0x0f, 0x8c, 0x4d, 0x55, 0x3c, + 0xf6, 0x23, 0xe6, 0xd1, 0x95, 0x82, 0xf7, 0x9f, 0x2b, 0x10, 0xf6, 0x2d, 0xf5, 0xc8, 0x72, 0x5d, + 0xff, 0x57, 0x00, 0x3b, 0x67, 0x8e, 0xc3, 0xa9, 0x43, 0x22, 0x16, 0xf8, 0x38, 0x76, 0x29, 0xfa, + 0x11, 0xc0, 0x7d, 0xdb, 0x8d, 0x45, 0x44, 0x39, 0x0e, 0x5c, 0x7a, 0x4d, 0x5d, 0x6a, 0x47, 0x01, + 0x17, 0x2a, 0xe8, 0xed, 0x1d, 0xb6, 0x4e, 0xdf, 0xd5, 0x4b, 0x6b, 0x66, 0xbd, 0xf4, 0x70, 0xe4, + 0xc8, 0x80, 0xd0, 0xe5, 0x48, 0xfa, 0xf8, 0x44, 0xbf, 0x24, 0x16, 0x75, 0x8b, 0x5a, 0xf3, 0xf5, + 0xc9, 0xb4, 0x5b, 0x49, 0xa6, 0xdd, 0xfd, 0x4f, 0xd6, 0x10, 0xe3, 0xb5, 0xed, 0xfa, 0xbf, 0x55, + 0x61, 0x6b, 0x0e, 0x8e, 0xbe, 0x85, 0x4d, 0x49, 0x3e, 0x24, 0x11, 0x51, 0x41, 0x0f, 0x1c, 0xb6, + 0x4e, 0xdf, 0xd9, 0x4e, 0xca, 0x17, 0xd6, 0x77, 0xd4, 0x8e, 0x3e, 0xa7, 0x11, 0x31, 0x51, 0xae, + 0x03, 0x96, 0x31, 0x3c, 0x63, 0x45, 0x9f, 0xc1, 0x3a, 0x8f, 0x5d, 0x2a, 0xd4, 0x6a, 0x3a, 0xe9, + 0x9b, 0xfa, 0x86, 0x4b, 0xa0, 0x5f, 0x05, 0x2e, 0xb3, 0xef, 0xa4, 0x5b, 0x66, 0x3b, 0x67, 0xac, + 0xcb, 0x93, 0xc0, 0x19, 0x01, 0x72, 0x60, 0x87, 0x2c, 0xda, 0xaa, 0xee, 0xa5, 0x92, 0x0f, 0x37, + 0x72, 0x2e, 0x7d, 0x06, 0xf3, 0x95, 0x64, 0xda, 0x5d, 0xfe, 0x36, 0x78, 0x99, 0xb5, 0xff, 0x4b, + 0x15, 0xa2, 0x39, 0x93, 0x4c, 0xe6, 0x0f, 0x99, 0xef, 0xec, 0xc0, 0xab, 0x01, 0x6c, 0x8a, 0x38, + 0x4d, 0x14, 0x76, 0xf5, 0x36, 0x8e, 0x76, 0x9d, 0x01, 0xcd, 0x97, 0x73, 0xc6, 0x66, 0x1e, 0x10, + 0x78, 0xc6, 0x81, 0x2e, 0x60, 0x83, 0x07, 0x2e, 0xc5, 0xf4, 0x26, 0x77, 0x6a, 0x33, 0x1d, 0xce, + 0x70, 0x66, 0x27, 0xa7, 0x6b, 0xe4, 0x01, 0x5c, 0x30, 0xf4, 0x27, 0x00, 0xbe, 0xba, 0xea, 0xca, + 0x25, 0x13, 0x11, 0xfa, 0x66, 0xc5, 0x19, 0x7d, 0xcb, 0x0b, 0xcd, 0x44, 0xe6, 0xcb, 0x6c, 0x8a, + 0x22, 0x32, 0xe7, 0xca, 0x15, 0xac, 0xb3, 0x88, 0x7a, 0x85, 0x25, 0x47, 0x1b, 0x67, 0x58, 0x55, + 0x57, 0xde, 0xa4, 0x73, 0xc9, 0x80, 0x33, 0xa2, 0xfe, 0x9f, 0x00, 0x76, 0xe6, 0xc0, 0x3b, 0x98, + 0xe1, 0x7c, 0x71, 0x86, 0xb7, 0xb6, 0x9a, 0x61, 0xbd, 0xf8, 0x7f, 0x00, 0x84, 0xe5, 0x5b, 0x41, + 0x5d, 0x58, 0x1f, 0x53, 0x6e, 0x65, 0x9b, 0x44, 0x31, 0x15, 0x89, 0xff, 0x4a, 0x06, 0x70, 0x16, + 0x47, 0x47, 0x50, 0x21, 0x21, 0xfb, 0x94, 0x07, 0x71, 0x98, 0xb5, 0x57, 0xcc, 0x76, 0x32, 0xed, + 0x2a, 0x67, 0x57, 0xe7, 0x59, 0x10, 0x97, 0x79, 0x09, 0xe6, 0x54, 0x04, 0x31, 0xb7, 0xa9, 0x50, + 0xf7, 0x4a, 0x30, 0x2e, 0x82, 0xb8, 0xcc, 0xa3, 0x0f, 0x60, 0xbb, 0x38, 0x0c, 0x88, 0x47, 0x85, + 0x5a, 0x4b, 0x0b, 0x5e, 0x24, 0xd3, 0x6e, 0x1b, 0xcf, 0x27, 0xf0, 0x22, 0x0e, 0x7d, 0x04, 0x3b, + 0x7e, 0xe0, 0x17, 0x90, 0x2f, 0xf1, 0xa5, 0x50, 0xeb, 0x69, 0x69, 0xfa, 0x3e, 0x07, 0x8b, 0x29, + 0xbc, 0x8c, 0xed, 0xff, 0x01, 0x60, 0xed, 0xbf, 0xb6, 0xbd, 0xfa, 0x3f, 0x55, 0x61, 0xeb, 0xff, + 0x6d, 0x32, 0xdb, 0x26, 0xf2, 0x09, 0xee, 0x76, 0x8d, 0x6c, 0xfd, 0x04, 0x9f, 0xdf, 0x1f, 0xbf, + 0x03, 0xd8, 0xdc, 0xd1, 0xe2, 0x30, 0x17, 0x55, 0xbf, 0xf1, 0xb4, 0xea, 0xf5, 0x72, 0xbf, 0x87, + 0x85, 0xff, 0xe8, 0x6d, 0xd8, 0x2c, 0x1e, 0x7b, 0x2a, 0x56, 0x29, 0x9b, 0x17, 0xfb, 0x00, 0xcf, + 0x10, 0xa8, 0x07, 0x6b, 0x23, 0xe6, 0x0f, 0xd5, 0x6a, 0x8a, 0x7c, 0x29, 0x47, 0xd6, 0x2e, 0x98, + 0x3f, 0xc4, 0x69, 0x46, 0x22, 0x7c, 0xe2, 0x65, 0x3f, 0xc4, 0x73, 0x08, 0xf9, 0xcc, 0x71, 0x9a, + 0x91, 0x5e, 0x35, 0xf2, 0xcb, 0x34, 0xe3, 0x03, 0x1b, 0xf9, 0xe6, 0xf5, 0x55, 0xb7, 0xd1, 0xf7, + 0x74, 0x77, 0x64, 0x40, 0x45, 0xfe, 0x15, 0x21, 0xb1, 0xa9, 0x5a, 0x4b, 0x61, 0x2f, 0x72, 0x98, + 0x32, 0x28, 0x12, 0xb8, 0xc4, 0x98, 0xc7, 0x93, 0x47, 0xad, 0x72, 0xff, 0xa8, 0x55, 0x1e, 0x1e, + 0xb5, 0xca, 0x0f, 0x89, 0x06, 0x26, 0x89, 0x06, 0xee, 0x13, 0x0d, 0x3c, 0x24, 0x1a, 0xf8, 0x2b, + 0xd1, 0xc0, 0xcf, 0x7f, 0x6b, 0x95, 0xaf, 0x1b, 0xb9, 0xeb, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, + 0x37, 0x8f, 0x77, 0xcd, 0x15, 0x0b, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/generated.proto index aa9960b8e..27bd30ce9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,11 +21,9 @@ syntax = 'proto2'; package k8s.io.api.rbac.v1beta1; -import "k8s.io/api/rbac/v1alpha1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; @@ -62,6 +60,7 @@ message ClusterRoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can only reference a ClusterRole in the global namespace. @@ -135,6 +134,7 @@ message RoleBinding { optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Subjects holds references to the objects the role applies to. + // +optional repeated Subject subjects = 2; // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/types.go index 091fc1dc9..857b67a6f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/types.go @@ -125,7 +125,8 @@ type RoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. @@ -199,7 +200,8 @@ type ClusterRoleBinding struct { metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Subjects holds references to the objects the role applies to. - Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"` + // +optional + Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"` // RoleRef can only reference a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/types_swagger_doc_generated.go index 6180d6d43..66dba6ca1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_AggregationRule = map[string]string{ "": "AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole", "clusterRoleSelectors": "ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. If any of the selectors match, then the ClusterRole's permissions will be added", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/zz_generated.deepcopy.go index 0ef823a07..86fadd170 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/rbac/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/roundtrip_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/roundtrip_test.go new file mode 100644 index 000000000..5b82feb84 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/roundtrip_test.go @@ -0,0 +1,150 @@ +/* +Copyright 2018 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 testing + +import ( + "math/rand" + "testing" + + admissionv1beta1 "k8s.io/api/admission/v1beta1" + admissionregv1alpha1 "k8s.io/api/admissionregistration/v1alpha1" + admissionregv1beta1 "k8s.io/api/admissionregistration/v1beta1" + appsv1 "k8s.io/api/apps/v1" + appsv1beta1 "k8s.io/api/apps/v1beta1" + appsv1beta2 "k8s.io/api/apps/v1beta2" + authenticationv1 "k8s.io/api/authentication/v1" + authenticationv1beta1 "k8s.io/api/authentication/v1beta1" + authorizationv1 "k8s.io/api/authorization/v1" + authorizationv1beta1 "k8s.io/api/authorization/v1beta1" + autoscalingv1 "k8s.io/api/autoscaling/v1" + autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" + batchv2alpha1 "k8s.io/api/batch/v2alpha1" + certificatesv1beta1 "k8s.io/api/certificates/v1beta1" + corev1 "k8s.io/api/core/v1" + eventsv1beta1 "k8s.io/api/events/v1beta1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + imagepolicyv1alpha1 "k8s.io/api/imagepolicy/v1alpha1" + networkingv1 "k8s.io/api/networking/v1" + policyv1beta1 "k8s.io/api/policy/v1beta1" + rbacv1 "k8s.io/api/rbac/v1" + rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" + rbacv1beta1 "k8s.io/api/rbac/v1beta1" + schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" + settingsv1alpha1 "k8s.io/api/settings/v1alpha1" + storagev1 "k8s.io/api/storage/v1" + storagev1alpha1 "k8s.io/api/storage/v1alpha1" + storagev1beta1 "k8s.io/api/storage/v1beta1" + + "k8s.io/apimachinery/pkg/api/testing/fuzzer" + "k8s.io/apimachinery/pkg/api/testing/roundtrip" + genericfuzzer "k8s.io/apimachinery/pkg/apis/meta/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" +) + +var groups = []runtime.SchemeBuilder{ + admissionv1beta1.SchemeBuilder, + admissionregv1alpha1.SchemeBuilder, + admissionregv1beta1.SchemeBuilder, + appsv1beta1.SchemeBuilder, + appsv1beta2.SchemeBuilder, + appsv1.SchemeBuilder, + authenticationv1beta1.SchemeBuilder, + authenticationv1.SchemeBuilder, + authorizationv1beta1.SchemeBuilder, + authorizationv1.SchemeBuilder, + autoscalingv1.SchemeBuilder, + autoscalingv2beta1.SchemeBuilder, + batchv2alpha1.SchemeBuilder, + batchv1beta1.SchemeBuilder, + batchv1.SchemeBuilder, + certificatesv1beta1.SchemeBuilder, + corev1.SchemeBuilder, + eventsv1beta1.SchemeBuilder, + extensionsv1beta1.SchemeBuilder, + imagepolicyv1alpha1.SchemeBuilder, + networkingv1.SchemeBuilder, + policyv1beta1.SchemeBuilder, + rbacv1alpha1.SchemeBuilder, + rbacv1beta1.SchemeBuilder, + rbacv1.SchemeBuilder, + schedulingv1alpha1.SchemeBuilder, + schedulingv1beta1.SchemeBuilder, + settingsv1alpha1.SchemeBuilder, + storagev1alpha1.SchemeBuilder, + storagev1beta1.SchemeBuilder, + storagev1.SchemeBuilder, +} + +func TestRoundTripExternalTypes(t *testing.T) { + for _, builder := range groups { + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + + builder.AddToScheme(scheme) + seed := rand.Int63() + // I'm only using the generic fuzzer funcs, but at some point in time we might need to + // switch to specialized. For now we're happy with the current serialization test. + fuzzer := fuzzer.FuzzerFor(genericfuzzer.Funcs, rand.NewSource(seed), codecs) + + roundtrip.RoundTripExternalTypes(t, scheme, codecs, fuzzer, nil) + } +} + +func TestFailRoundTrip(t *testing.T) { + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + groupVersion := schema.GroupVersion{Group: "broken", Version: "v1"} + builder := runtime.NewSchemeBuilder(func(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(groupVersion, &BrokenType{}) + metav1.AddToGroupVersion(scheme, groupVersion) + return nil + }) + builder.AddToScheme(scheme) + seed := rand.Int63() + fuzzer := fuzzer.FuzzerFor(genericfuzzer.Funcs, rand.NewSource(seed), codecs) + tmpT := new(testing.T) + roundtrip.RoundTripExternalTypes(tmpT, scheme, codecs, fuzzer, nil) + // It's very hacky way of making sure the DeepCopy is actually invoked inside RoundTripExternalTypes + // used in the other test. If for some reason this tests starts passing we need to fail b/c we're not testing + // the DeepCopy in the other method which we care so much about. + if !tmpT.Failed() { + t.Log("RoundTrip should've failed on DeepCopy but it did not!") + t.FailNow() + } +} + +type BrokenType struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Field1 string `json:"field1,omitempty"` + Field2 string `json:"field2,omitempty"` +} + +func (in *BrokenType) DeepCopy() *BrokenType { + return new(BrokenType) +} + +func (in *BrokenType) DeepCopyObject() runtime.Object { + return in.DeepCopy() +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/generated.pb.go index 39c0b9e6a..97c07c984 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -608,34 +608,33 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 460 bytes of a gzipped FileDescriptorProto + // 447 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x4f, 0x8b, 0xd3, 0x40, 0x18, 0xc6, 0x33, 0x5d, 0x0b, 0x75, 0x4a, 0x41, 0x23, 0x42, 0xe8, 0x61, 0x36, 0xac, 0x97, 0x5c, - 0x76, 0xc6, 0xae, 0x7f, 0x10, 0xbc, 0xc5, 0x85, 0x45, 0x50, 0x94, 0x1c, 0x3c, 0x88, 0x07, 0x27, - 0xc9, 0x6c, 0x3a, 0x36, 0xc9, 0x84, 0x99, 0x37, 0x81, 0xbd, 0x79, 0xf6, 0xe4, 0x97, 0x12, 0x7a, - 0xdc, 0xe3, 0x9e, 0x16, 0x1b, 0xbf, 0x88, 0x24, 0x4d, 0x37, 0xad, 0x65, 0xd5, 0x5b, 0xe6, 0x79, - 0x9f, 0xdf, 0x33, 0xf3, 0x3e, 0x04, 0x9f, 0x2d, 0x5e, 0x18, 0x2a, 0x15, 0x5b, 0x94, 0xa1, 0xd0, - 0xb9, 0x00, 0x61, 0x58, 0x25, 0xf2, 0x58, 0x69, 0xd6, 0x0d, 0x78, 0x21, 0x99, 0x89, 0xe6, 0x22, - 0x2e, 0x53, 0x99, 0x27, 0xac, 0x9a, 0xf1, 0xb4, 0x98, 0xf3, 0x19, 0x4b, 0x44, 0x2e, 0x34, 0x07, - 0x11, 0xd3, 0x42, 0x2b, 0x50, 0x36, 0x59, 0xfb, 0x29, 0x2f, 0x24, 0xed, 0xfd, 0x74, 0xe3, 0x9f, - 0x1e, 0x27, 0x12, 0xe6, 0x65, 0x48, 0x23, 0x95, 0xb1, 0x44, 0x25, 0x8a, 0xb5, 0x58, 0x58, 0x9e, - 0xb7, 0xa7, 0xf6, 0xd0, 0x7e, 0xad, 0xe3, 0xa6, 0x4f, 0xfb, 0xeb, 0x33, 0x1e, 0xcd, 0x65, 0x2e, - 0xf4, 0x05, 0x2b, 0x16, 0x49, 0x23, 0x18, 0x96, 0x09, 0xe0, 0xac, 0xda, 0x7b, 0xc4, 0x94, 0xdd, - 0x46, 0xe9, 0x32, 0x07, 0x99, 0x89, 0x3d, 0xe0, 0xf9, 0xbf, 0x80, 0x66, 0x95, 0x8c, 0xef, 0x71, - 0x4f, 0x6e, 0xe3, 0x4a, 0x90, 0x29, 0x93, 0x39, 0x18, 0xd0, 0x7f, 0x42, 0x47, 0xdf, 0x06, 0x78, - 0xf2, 0x5e, 0x4b, 0xa5, 0x25, 0x5c, 0xbc, 0x4a, 0xb9, 0x31, 0xf6, 0x67, 0x3c, 0x6a, 0x56, 0x89, - 0x39, 0x70, 0x07, 0xb9, 0xc8, 0x1b, 0x9f, 0x3c, 0xa6, 0x7d, 0x8f, 0x37, 0xc9, 0xb4, 0x58, 0x24, - 0x8d, 0x60, 0x68, 0xe3, 0xa6, 0xd5, 0x8c, 0xbe, 0x0b, 0xbf, 0x88, 0x08, 0xde, 0x0a, 0xe0, 0xbe, - 0xbd, 0xbc, 0x3e, 0xb4, 0xea, 0xeb, 0x43, 0xdc, 0x6b, 0xc1, 0x4d, 0xaa, 0xfd, 0x08, 0x0f, 0x2b, - 0x9e, 0x96, 0xc2, 0x19, 0xb8, 0xc8, 0x1b, 0xfa, 0x93, 0xce, 0x3c, 0xfc, 0xd0, 0x88, 0xc1, 0x7a, - 0x66, 0xbf, 0xc4, 0x93, 0x24, 0x55, 0x21, 0x4f, 0x4f, 0xc5, 0x39, 0x2f, 0x53, 0x70, 0x0e, 0x5c, - 0xe4, 0x8d, 0xfc, 0x87, 0x9d, 0x79, 0x72, 0xb6, 0x3d, 0x0c, 0x76, 0xbd, 0xf6, 0x33, 0x3c, 0x8e, - 0x85, 0x89, 0xb4, 0x2c, 0x40, 0xaa, 0xdc, 0xb9, 0xe3, 0x22, 0xef, 0xae, 0xff, 0xa0, 0x43, 0xc7, - 0xa7, 0xfd, 0x28, 0xd8, 0xf6, 0x1d, 0xfd, 0x40, 0xf8, 0xfe, 0x4e, 0x19, 0x6f, 0xa4, 0x01, 0xfb, - 0xd3, 0x5e, 0x21, 0xf4, 0xff, 0x0a, 0x69, 0xe8, 0xb6, 0x8e, 0x7b, 0xdd, 0xcd, 0xa3, 0x8d, 0xb2, - 0x55, 0x46, 0x80, 0x87, 0x12, 0x44, 0x66, 0x9c, 0x81, 0x7b, 0xe0, 0x8d, 0x4f, 0x8e, 0xe9, 0xdf, - 0xff, 0x59, 0xba, 0xf3, 0xbe, 0xbe, 0xbb, 0xd7, 0x4d, 0x46, 0xb0, 0x8e, 0xf2, 0xe9, 0x72, 0x45, - 0xac, 0xcb, 0x15, 0xb1, 0xae, 0x56, 0xc4, 0xfa, 0x5a, 0x13, 0xb4, 0xac, 0x09, 0xba, 0xac, 0x09, - 0xba, 0xaa, 0x09, 0xfa, 0x59, 0x13, 0xf4, 0xfd, 0x17, 0xb1, 0x3e, 0x8e, 0x36, 0x99, 0xbf, 0x03, - 0x00, 0x00, 0xff, 0xff, 0x44, 0x05, 0xba, 0x7b, 0x71, 0x03, 0x00, 0x00, + 0x76, 0xc6, 0x2e, 0x2a, 0x82, 0xb7, 0xb8, 0xb0, 0x08, 0x8a, 0x92, 0x83, 0x07, 0xf1, 0xe0, 0x24, + 0x79, 0x37, 0x1d, 0x9b, 0x64, 0xc2, 0xcc, 0x24, 0xb0, 0x37, 0xcf, 0x9e, 0xfc, 0x52, 0x42, 0x8f, + 0x7b, 0xdc, 0xd3, 0x62, 0xe3, 0x17, 0x91, 0xa4, 0x69, 0xd3, 0x5a, 0xfc, 0x73, 0xcb, 0x3c, 0xef, + 0xef, 0x79, 0xe6, 0xcd, 0xc3, 0xe0, 0x8b, 0xc5, 0x73, 0x4d, 0x85, 0x64, 0x8b, 0x32, 0x04, 0x95, + 0x83, 0x01, 0xcd, 0x2a, 0xc8, 0x63, 0xa9, 0x58, 0x37, 0xe0, 0x85, 0x60, 0x3a, 0x9a, 0x43, 0x5c, + 0xa6, 0x22, 0x4f, 0x58, 0x35, 0xe3, 0x69, 0x31, 0xe7, 0x33, 0x96, 0x40, 0x0e, 0x8a, 0x1b, 0x88, + 0x69, 0xa1, 0xa4, 0x91, 0x36, 0x59, 0xf3, 0x94, 0x17, 0x82, 0xf6, 0x3c, 0xdd, 0xf0, 0xd3, 0xd3, + 0x44, 0x98, 0x79, 0x19, 0xd2, 0x48, 0x66, 0x2c, 0x91, 0x89, 0x64, 0xad, 0x2d, 0x2c, 0x2f, 0xdb, + 0x53, 0x7b, 0x68, 0xbf, 0xd6, 0x71, 0xd3, 0x27, 0xfd, 0xf5, 0x19, 0x8f, 0xe6, 0x22, 0x07, 0x75, + 0xc5, 0x8a, 0x45, 0xd2, 0x08, 0x9a, 0x65, 0x60, 0x38, 0xab, 0x0e, 0x96, 0x98, 0xb2, 0x3f, 0xb9, + 0x54, 0x99, 0x1b, 0x91, 0xc1, 0x81, 0xe1, 0xd9, 0xbf, 0x0c, 0xcd, 0xaf, 0x64, 0xfc, 0x77, 0xdf, + 0xc9, 0xd7, 0x01, 0x9e, 0xbc, 0x53, 0x42, 0x2a, 0x61, 0xae, 0x5e, 0xa6, 0x5c, 0x6b, 0xfb, 0x13, + 0x1e, 0x35, 0x5b, 0xc5, 0xdc, 0x70, 0x07, 0xb9, 0xc8, 0x1b, 0x9f, 0x3d, 0xa6, 0x7d, 0x25, 0xdb, + 0x70, 0x5a, 0x2c, 0x92, 0x46, 0xd0, 0xb4, 0xa1, 0x69, 0x35, 0xa3, 0x6f, 0xc3, 0xcf, 0x10, 0x99, + 0x37, 0x60, 0xb8, 0x6f, 0x2f, 0x6f, 0x8f, 0xad, 0xfa, 0xf6, 0x18, 0xf7, 0x5a, 0xb0, 0x4d, 0xb5, + 0x1f, 0xe1, 0x61, 0xc5, 0xd3, 0x12, 0x9c, 0x81, 0x8b, 0xbc, 0xa1, 0x3f, 0xe9, 0xe0, 0xe1, 0xfb, + 0x46, 0x0c, 0xd6, 0x33, 0xfb, 0x05, 0x9e, 0x24, 0xa9, 0x0c, 0x79, 0x7a, 0x0e, 0x97, 0xbc, 0x4c, + 0x8d, 0x73, 0xe4, 0x22, 0x6f, 0xe4, 0x3f, 0xec, 0xe0, 0xc9, 0xc5, 0xee, 0x30, 0xd8, 0x67, 0xed, + 0xa7, 0x78, 0x1c, 0x83, 0x8e, 0x94, 0x28, 0x8c, 0x90, 0xb9, 0x73, 0xc7, 0x45, 0xde, 0x5d, 0xff, + 0x41, 0x67, 0x1d, 0x9f, 0xf7, 0xa3, 0x60, 0x97, 0x3b, 0xf9, 0x8e, 0xf0, 0xfd, 0xbd, 0x32, 0x5e, + 0x0b, 0x6d, 0xec, 0x8f, 0x07, 0x85, 0xd0, 0xff, 0x2b, 0xa4, 0x71, 0xb7, 0x75, 0xdc, 0xeb, 0x6e, + 0x1e, 0x6d, 0x94, 0x9d, 0x32, 0x02, 0x3c, 0x14, 0x06, 0x32, 0xed, 0x0c, 0xdc, 0x23, 0x6f, 0x7c, + 0x76, 0x4a, 0xff, 0xfe, 0xfc, 0xe8, 0xde, 0x7e, 0x7d, 0x77, 0xaf, 0x9a, 0x8c, 0x60, 0x1d, 0xe5, + 0xd3, 0xe5, 0x8a, 0x58, 0xd7, 0x2b, 0x62, 0xdd, 0xac, 0x88, 0xf5, 0xa5, 0x26, 0x68, 0x59, 0x13, + 0x74, 0x5d, 0x13, 0x74, 0x53, 0x13, 0xf4, 0xa3, 0x26, 0xe8, 0xdb, 0x4f, 0x62, 0x7d, 0x18, 0x6d, + 0x32, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0xab, 0x20, 0x12, 0x63, 0x3c, 0x03, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/generated.proto index e964a76dd..5fb547211 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.api.scheduling.v1alpha1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go index 9080dd9d6..f406f4402 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_PriorityClass = map[string]string{ "": "PriorityClass defines mapping from a priority class name to the priority integer value. The value can be any valid integer.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/zz_generated.deepcopy.go index 51f8d0473..fe0c86040 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/BUILD new file mode 100644 index 000000000..5dc69ac1e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/BUILD @@ -0,0 +1,44 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "generated.pb.go", + "register.go", + "types.go", + "types_swagger_doc_generated.go", + "zz_generated.deepcopy.go", + ], + importpath = "k8s.io/api/scheduling/v1beta1", + deps = [ + "//vendor/github.com/gogo/protobuf/proto:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) + +filegroup( + name = "go_default_library_protos", + srcs = ["generated.proto"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/doc.go new file mode 100644 index 000000000..f2dd1cfac --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2018 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. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:openapi-gen=true + +// +groupName=scheduling.k8s.io +package v1beta1 // import "k8s.io/api/scheduling/v1beta1" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/generated.pb.go new file mode 100644 index 000000000..ea8f8d5e6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/generated.pb.go @@ -0,0 +1,640 @@ +/* +Copyright 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. +*/ + +// Code generated by protoc-gen-gogo. +// source: k8s.io/kubernetes/vendor/k8s.io/api/scheduling/v1beta1/generated.proto +// DO NOT EDIT! + +/* + Package v1beta1 is a generated protocol buffer package. + + It is generated from these files: + k8s.io/kubernetes/vendor/k8s.io/api/scheduling/v1beta1/generated.proto + + It has these top-level messages: + PriorityClass + PriorityClassList +*/ +package v1beta1 + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" + +import strings "strings" +import reflect "reflect" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +func (m *PriorityClass) Reset() { *m = PriorityClass{} } +func (*PriorityClass) ProtoMessage() {} +func (*PriorityClass) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} } + +func (m *PriorityClassList) Reset() { *m = PriorityClassList{} } +func (*PriorityClassList) ProtoMessage() {} +func (*PriorityClassList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} } + +func init() { + proto.RegisterType((*PriorityClass)(nil), "k8s.io.api.scheduling.v1beta1.PriorityClass") + proto.RegisterType((*PriorityClassList)(nil), "k8s.io.api.scheduling.v1beta1.PriorityClassList") +} +func (m *PriorityClass) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PriorityClass) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) + n1, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + dAtA[i] = 0x10 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Value)) + dAtA[i] = 0x18 + i++ + if m.GlobalDefault { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Description))) + i += copy(dAtA[i:], m.Description) + return i, nil +} + +func (m *PriorityClassList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PriorityClassList) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) + n2, err := m.ListMeta.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n2 + if len(m.Items) > 0 { + for _, msg := range m.Items { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *PriorityClass) Size() (n int) { + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + n += 1 + sovGenerated(uint64(m.Value)) + n += 2 + l = len(m.Description) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *PriorityClassList) Size() (n int) { + var l int + _ = l + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func sovGenerated(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozGenerated(x uint64) (n int) { + return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *PriorityClass) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PriorityClass{`, + `ObjectMeta:` + strings.Replace(strings.Replace(this.ObjectMeta.String(), "ObjectMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `GlobalDefault:` + fmt.Sprintf("%v", this.GlobalDefault) + `,`, + `Description:` + fmt.Sprintf("%v", this.Description) + `,`, + `}`, + }, "") + return s +} +func (this *PriorityClassList) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PriorityClassList{`, + `ListMeta:` + strings.Replace(strings.Replace(this.ListMeta.String(), "ListMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Items), "PriorityClass", "PriorityClass", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func valueToStringGenerated(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *PriorityClass) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PriorityClass: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PriorityClass: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + m.Value = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Value |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GlobalDefault", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.GlobalDefault = bool(v != 0) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PriorityClassList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PriorityClassList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PriorityClassList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, PriorityClass{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenerated(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthGenerated + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipGenerated(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow") +) + +func init() { + proto.RegisterFile("k8s.io/kubernetes/vendor/k8s.io/api/scheduling/v1beta1/generated.proto", fileDescriptorGenerated) +} + +var fileDescriptorGenerated = []byte{ + // 448 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x8b, 0xd3, 0x40, + 0x18, 0xc5, 0x33, 0x5d, 0x8b, 0x75, 0x4a, 0x41, 0x23, 0x42, 0x28, 0x38, 0x1b, 0xd6, 0x4b, 0x0e, + 0xee, 0x8c, 0x5d, 0x54, 0x04, 0x6f, 0x71, 0x51, 0x04, 0x45, 0xcd, 0xc1, 0x83, 0x78, 0x70, 0x92, + 0x7c, 0x9b, 0x8e, 0x4d, 0x32, 0x61, 0x66, 0x12, 0xd8, 0x9b, 0x67, 0x4f, 0xfe, 0x51, 0x1e, 0x7a, + 0xdc, 0xe3, 0x9e, 0x16, 0x1b, 0xff, 0x11, 0x49, 0x1a, 0x37, 0xad, 0x45, 0xdd, 0x5b, 0xe6, 0x7d, + 0xbf, 0xf7, 0xe6, 0xcb, 0x63, 0xf0, 0xf3, 0xc5, 0x13, 0x4d, 0x85, 0x64, 0x8b, 0x32, 0x04, 0x95, + 0x83, 0x01, 0xcd, 0x2a, 0xc8, 0x63, 0xa9, 0x58, 0x37, 0xe0, 0x85, 0x60, 0x3a, 0x9a, 0x43, 0x5c, + 0xa6, 0x22, 0x4f, 0x58, 0x35, 0x0b, 0xc1, 0xf0, 0x19, 0x4b, 0x20, 0x07, 0xc5, 0x0d, 0xc4, 0xb4, + 0x50, 0xd2, 0x48, 0xfb, 0xee, 0x1a, 0xa7, 0xbc, 0x10, 0xb4, 0xc7, 0x69, 0x87, 0x4f, 0x0f, 0x13, + 0x61, 0xe6, 0x65, 0x48, 0x23, 0x99, 0xb1, 0x44, 0x26, 0x92, 0xb5, 0xae, 0xb0, 0x3c, 0x69, 0x4f, + 0xed, 0xa1, 0xfd, 0x5a, 0xa7, 0x4d, 0x1f, 0xf6, 0x97, 0x67, 0x3c, 0x9a, 0x8b, 0x1c, 0xd4, 0x29, + 0x2b, 0x16, 0x49, 0x23, 0x68, 0x96, 0x81, 0xe1, 0xac, 0xda, 0xd9, 0x61, 0xca, 0xfe, 0xe6, 0x52, + 0x65, 0x6e, 0x44, 0x06, 0x3b, 0x86, 0xc7, 0xff, 0x33, 0x34, 0x7f, 0x92, 0xf1, 0x3f, 0x7d, 0x07, + 0x5f, 0x07, 0x78, 0xf2, 0x56, 0x09, 0xa9, 0x84, 0x39, 0x7d, 0x96, 0x72, 0xad, 0xed, 0x4f, 0x78, + 0xd4, 0x6c, 0x15, 0x73, 0xc3, 0x1d, 0xe4, 0x22, 0x6f, 0x7c, 0xf4, 0x80, 0xf6, 0x8d, 0x5c, 0x86, + 0xd3, 0x62, 0x91, 0x34, 0x82, 0xa6, 0x0d, 0x4d, 0xab, 0x19, 0x7d, 0x13, 0x7e, 0x86, 0xc8, 0xbc, + 0x06, 0xc3, 0x7d, 0x7b, 0x79, 0xb1, 0x6f, 0xd5, 0x17, 0xfb, 0xb8, 0xd7, 0x82, 0xcb, 0x54, 0xfb, + 0x1e, 0x1e, 0x56, 0x3c, 0x2d, 0xc1, 0x19, 0xb8, 0xc8, 0x1b, 0xfa, 0x93, 0x0e, 0x1e, 0xbe, 0x6f, + 0xc4, 0x60, 0x3d, 0xb3, 0x9f, 0xe2, 0x49, 0x92, 0xca, 0x90, 0xa7, 0xc7, 0x70, 0xc2, 0xcb, 0xd4, + 0x38, 0x7b, 0x2e, 0xf2, 0x46, 0xfe, 0x9d, 0x0e, 0x9e, 0xbc, 0xd8, 0x1c, 0x06, 0xdb, 0xac, 0xfd, + 0x08, 0x8f, 0x63, 0xd0, 0x91, 0x12, 0x85, 0x11, 0x32, 0x77, 0xae, 0xb9, 0xc8, 0xbb, 0xe1, 0xdf, + 0xee, 0xac, 0xe3, 0xe3, 0x7e, 0x14, 0x6c, 0x72, 0x07, 0xdf, 0x11, 0xbe, 0xb5, 0x55, 0xc6, 0x2b, + 0xa1, 0x8d, 0xfd, 0x71, 0xa7, 0x10, 0x7a, 0xb5, 0x42, 0x1a, 0x77, 0x5b, 0xc7, 0xcd, 0xee, 0xe6, + 0xd1, 0x6f, 0x65, 0xa3, 0x8c, 0x77, 0x78, 0x28, 0x0c, 0x64, 0xda, 0x19, 0xb8, 0x7b, 0xde, 0xf8, + 0xe8, 0x3e, 0xfd, 0xe7, 0xeb, 0xa3, 0x5b, 0xeb, 0xf5, 0xd5, 0xbd, 0x6c, 0x22, 0x82, 0x75, 0x92, + 0x7f, 0xb8, 0x5c, 0x11, 0xeb, 0x6c, 0x45, 0xac, 0xf3, 0x15, 0xb1, 0xbe, 0xd4, 0x04, 0x2d, 0x6b, + 0x82, 0xce, 0x6a, 0x82, 0xce, 0x6b, 0x82, 0x7e, 0xd4, 0x04, 0x7d, 0xfb, 0x49, 0xac, 0x0f, 0xd7, + 0xbb, 0xc8, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x41, 0x74, 0x8a, 0x60, 0x38, 0x03, 0x00, 0x00, +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/generated.proto new file mode 100644 index 000000000..0a9575503 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/generated.proto @@ -0,0 +1,67 @@ +/* +Copyright 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. +*/ + + +// This file was autogenerated by go-to-protobuf. Do not edit it manually! + +syntax = 'proto2'; + +package k8s.io.api.scheduling.v1beta1; + +import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; + +// Package-wide variables from generator "generated". +option go_package = "v1beta1"; + +// PriorityClass defines mapping from a priority class name to the priority +// integer value. The value can be any valid integer. +message PriorityClass { + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // The value of this priority class. This is the actual priority that pods + // receive when they have the name of this class in their pod spec. + optional int32 value = 2; + + // globalDefault specifies whether this PriorityClass should be considered as + // the default priority for pods that do not have any priority class. + // Only one PriorityClass can be marked as `globalDefault`. However, if more than + // one PriorityClasses exists with their `globalDefault` field set to true, + // the smallest value of such global default PriorityClasses will be used as the default priority. + // +optional + optional bool globalDefault = 3; + + // description is an arbitrary string that usually provides guidelines on + // when this priority class should be used. + // +optional + optional string description = 4; +} + +// PriorityClassList is a collection of priority classes. +message PriorityClassList { + // Standard list metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + // items is the list of PriorityClasses + repeated PriorityClass items = 2; +} + diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/register.go new file mode 100644 index 000000000..fb26557bb --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/register.go @@ -0,0 +1,52 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "scheduling.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + localSchemeBuilder = &SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +// Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &PriorityClass{}, + &PriorityClassList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/types.go new file mode 100644 index 000000000..a9aaa8665 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/types.go @@ -0,0 +1,66 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PriorityClass defines mapping from a priority class name to the priority +// integer value. The value can be any valid integer. +type PriorityClass struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // The value of this priority class. This is the actual priority that pods + // receive when they have the name of this class in their pod spec. + Value int32 `json:"value" protobuf:"bytes,2,opt,name=value"` + + // globalDefault specifies whether this PriorityClass should be considered as + // the default priority for pods that do not have any priority class. + // Only one PriorityClass can be marked as `globalDefault`. However, if more than + // one PriorityClasses exists with their `globalDefault` field set to true, + // the smallest value of such global default PriorityClasses will be used as the default priority. + // +optional + GlobalDefault bool `json:"globalDefault,omitempty" protobuf:"bytes,3,opt,name=globalDefault"` + + // description is an arbitrary string that usually provides guidelines on + // when this priority class should be used. + // +optional + Description string `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PriorityClassList is a collection of priority classes. +type PriorityClassList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // items is the list of PriorityClasses + Items []PriorityClass `json:"items" protobuf:"bytes,2,rep,name=items"` +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go new file mode 100644 index 000000000..c18f54a82 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go @@ -0,0 +1,52 @@ +/* +Copyright 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 v1beta1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-generated-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. +var map_PriorityClass = map[string]string{ + "": "PriorityClass defines mapping from a priority class name to the priority integer value. The value can be any valid integer.", + "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "value": "The value of this priority class. This is the actual priority that pods receive when they have the name of this class in their pod spec.", + "globalDefault": "globalDefault specifies whether this PriorityClass should be considered as the default priority for pods that do not have any priority class. Only one PriorityClass can be marked as `globalDefault`. However, if more than one PriorityClasses exists with their `globalDefault` field set to true, the smallest value of such global default PriorityClasses will be used as the default priority.", + "description": "description is an arbitrary string that usually provides guidelines on when this priority class should be used.", +} + +func (PriorityClass) SwaggerDoc() map[string]string { + return map_PriorityClass +} + +var map_PriorityClassList = map[string]string{ + "": "PriorityClassList is a collection of priority classes.", + "metadata": "Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "items": "items is the list of PriorityClasses", +} + +func (PriorityClassList) SwaggerDoc() map[string]string { + return map_PriorityClassList +} + +// AUTO-GENERATED FUNCTIONS END HERE diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 000000000..6f68e4ac5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,84 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PriorityClass) DeepCopyInto(out *PriorityClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PriorityClass. +func (in *PriorityClass) DeepCopy() *PriorityClass { + if in == nil { + return nil + } + out := new(PriorityClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PriorityClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PriorityClassList) DeepCopyInto(out *PriorityClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]PriorityClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PriorityClassList. +func (in *PriorityClassList) DeepCopy() *PriorityClassList { + if in == nil { + return nil + } + out := new(PriorityClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PriorityClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/generated.pb.go index bfc6a5a11..15285bae5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -891,40 +891,39 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 556 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x8e, 0xd2, 0x4e, - 0x1c, 0xc7, 0xe9, 0xb2, 0x04, 0xfe, 0x03, 0x9b, 0xbf, 0x69, 0x3c, 0x34, 0xc4, 0x94, 0x95, 0x8b, - 0x9b, 0x18, 0x67, 0x64, 0xd7, 0x18, 0xbd, 0x36, 0xc1, 0xc4, 0x04, 0xe2, 0xa6, 0x24, 0x9b, 0x68, - 0x3c, 0x38, 0x94, 0x9f, 0xa5, 0x42, 0x67, 0x9a, 0x99, 0x69, 0x13, 0x6f, 0x3e, 0x82, 0x2f, 0xe0, - 0x93, 0xe8, 0x03, 0x70, 0xdc, 0xe3, 0x9e, 0x36, 0x52, 0x5f, 0xc4, 0x4c, 0x99, 0x02, 0x8a, 0x28, - 0xb7, 0xce, 0x8f, 0xef, 0xe7, 0x33, 0xbf, 0x2f, 0x2d, 0xea, 0xcf, 0x9e, 0x49, 0x1c, 0x71, 0x32, - 0x4b, 0xc7, 0x20, 0x18, 0x28, 0x90, 0x24, 0x03, 0x36, 0xe1, 0x82, 0x98, 0x1f, 0x68, 0x12, 0x11, - 0x09, 0x4a, 0x45, 0x2c, 0x94, 0x24, 0xeb, 0xd1, 0x79, 0x32, 0xa5, 0x3d, 0x12, 0x02, 0x03, 0x41, - 0x15, 0x4c, 0x70, 0x22, 0xb8, 0xe2, 0xf6, 0xbd, 0x55, 0x1a, 0xd3, 0x24, 0xc2, 0x65, 0x1a, 0x97, - 0xe9, 0xf6, 0xa3, 0x30, 0x52, 0xd3, 0x74, 0x8c, 0x03, 0x1e, 0x93, 0x90, 0x87, 0x9c, 0x14, 0xd0, - 0x38, 0x7d, 0x5f, 0x9c, 0x8a, 0x43, 0xf1, 0xb4, 0x92, 0xb5, 0xbb, 0x5b, 0x57, 0x07, 0x5c, 0x00, - 0xc9, 0x76, 0x2e, 0x6c, 0x3f, 0xd9, 0x64, 0x62, 0x1a, 0x4c, 0x23, 0x06, 0xe2, 0x23, 0x49, 0x66, - 0xa1, 0x1e, 0x48, 0x12, 0x83, 0xa2, 0x7f, 0xa2, 0xc8, 0x3e, 0x4a, 0xa4, 0x4c, 0x45, 0x31, 0xec, - 0x00, 0x4f, 0xff, 0x05, 0xc8, 0x60, 0x0a, 0x31, 0xdd, 0xe1, 0x2e, 0xf6, 0x71, 0xa9, 0x8a, 0xe6, - 0x24, 0x62, 0x4a, 0x2a, 0xf1, 0x3b, 0xd4, 0xfd, 0x66, 0xa1, 0xff, 0x2e, 0xf9, 0xe4, 0x52, 0x80, - 0x04, 0x65, 0xbf, 0x43, 0x0d, 0x5d, 0x63, 0x42, 0x15, 0x75, 0xac, 0x53, 0xeb, 0xac, 0x79, 0xfe, - 0x18, 0x6f, 0xfe, 0xe5, 0xb5, 0x15, 0x27, 0xb3, 0x50, 0x0f, 0x24, 0xd6, 0x69, 0x9c, 0xf5, 0xf0, - 0xab, 0xf1, 0x07, 0x08, 0xd4, 0x10, 0x14, 0xf5, 0xec, 0xc5, 0x6d, 0xa7, 0x92, 0xdf, 0x76, 0xd0, - 0x66, 0xe6, 0xaf, 0xad, 0xf6, 0x10, 0x1d, 0xcb, 0x04, 0x02, 0xe7, 0xa8, 0xb0, 0x3f, 0xc4, 0x7f, - 0x7b, 0x87, 0x78, 0xbd, 0xd8, 0x28, 0x81, 0xc0, 0x6b, 0x19, 0xf1, 0xb1, 0x3e, 0xf9, 0x85, 0xa6, - 0xfb, 0xd5, 0x42, 0x27, 0xeb, 0xd4, 0x20, 0x92, 0xca, 0x7e, 0xbb, 0x53, 0x01, 0x1f, 0x56, 0x41, - 0xd3, 0x45, 0x81, 0x3b, 0xe6, 0x9e, 0x46, 0x39, 0xd9, 0x5a, 0x7f, 0x80, 0x6a, 0x91, 0x82, 0x58, - 0x3a, 0x47, 0xa7, 0xd5, 0xb3, 0xe6, 0xf9, 0x83, 0x03, 0xf7, 0xf7, 0x4e, 0x8c, 0xb3, 0xf6, 0x52, - 0xd3, 0xfe, 0x4a, 0xd2, 0xfd, 0x52, 0xdd, 0xda, 0x5e, 0xb7, 0xb2, 0x29, 0x6a, 0x48, 0x98, 0x43, - 0xa0, 0xb8, 0x30, 0xdb, 0x5f, 0x1c, 0xb8, 0x3d, 0x1d, 0xc3, 0x7c, 0x64, 0xd0, 0x4d, 0x85, 0x72, - 0xe2, 0xaf, 0xb5, 0xf6, 0x73, 0x54, 0x05, 0x96, 0x99, 0x02, 0xed, 0xed, 0x02, 0xfa, 0xbb, 0xd7, - 0xae, 0x3e, 0xcb, 0xae, 0xa8, 0xf0, 0x9a, 0x46, 0x52, 0xed, 0xb3, 0xcc, 0xd7, 0x8c, 0x3d, 0x40, - 0x75, 0x60, 0xd9, 0x0b, 0xc1, 0x63, 0xa7, 0x5a, 0xe0, 0xf7, 0xf7, 0xe0, 0x3a, 0x32, 0xe2, 0xa9, - 0x08, 0xc0, 0xfb, 0xdf, 0x58, 0xea, 0x66, 0xec, 0x97, 0x0a, 0xbb, 0x8f, 0xea, 0x19, 0x9f, 0xa7, - 0x31, 0x48, 0xe7, 0x78, 0xff, 0x32, 0x57, 0x45, 0x64, 0xa3, 0x59, 0x9d, 0xa5, 0x5f, 0xb2, 0xf6, - 0x6b, 0xd4, 0x5a, 0x3d, 0x0e, 0x79, 0xca, 0x94, 0x74, 0x6a, 0x85, 0xab, 0xb3, 0xdf, 0x55, 0xe4, - 0xbc, 0xbb, 0x46, 0xd8, 0xda, 0x1a, 0x4a, 0xff, 0x17, 0x95, 0x87, 0x17, 0x4b, 0xb7, 0x72, 0xbd, - 0x74, 0x2b, 0x37, 0x4b, 0xb7, 0xf2, 0x29, 0x77, 0xad, 0x45, 0xee, 0x5a, 0xd7, 0xb9, 0x6b, 0xdd, - 0xe4, 0xae, 0xf5, 0x3d, 0x77, 0xad, 0xcf, 0x3f, 0xdc, 0xca, 0x9b, 0x46, 0xf9, 0xbe, 0x7f, 0x06, - 0x00, 0x00, 0xff, 0xff, 0x0e, 0x35, 0x98, 0xb5, 0xd9, 0x04, 0x00, 0x00, + // 542 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x8e, 0xd2, 0x40, + 0x1c, 0xc6, 0xe9, 0xb2, 0x04, 0x1c, 0xd8, 0x68, 0x1a, 0x0f, 0x0d, 0x31, 0x65, 0xe5, 0xe2, 0x26, + 0xc6, 0x19, 0x59, 0x8d, 0xd1, 0x6b, 0x13, 0x4c, 0x4c, 0x20, 0x6e, 0x4a, 0xb2, 0x89, 0xc6, 0x83, + 0x43, 0xf9, 0x5b, 0x2a, 0xb4, 0xd3, 0xcc, 0x4c, 0x9b, 0x78, 0xf3, 0x11, 0x7c, 0x01, 0x9f, 0x44, + 0x1f, 0x80, 0xe3, 0x1e, 0xf7, 0xb4, 0x91, 0xfa, 0x22, 0x66, 0x86, 0x29, 0xa0, 0x88, 0x72, 0x9b, + 0xff, 0x9f, 0xef, 0xfb, 0xcd, 0xf7, 0x31, 0x45, 0xfd, 0xd9, 0x73, 0x81, 0x23, 0x46, 0x66, 0xd9, + 0x18, 0x78, 0x02, 0x12, 0x04, 0xc9, 0x21, 0x99, 0x30, 0x4e, 0xcc, 0x0f, 0x34, 0x8d, 0x88, 0x00, + 0x29, 0xa3, 0x24, 0x14, 0x24, 0xef, 0xd1, 0x79, 0x3a, 0xa5, 0x3d, 0x12, 0x42, 0x02, 0x9c, 0x4a, + 0x98, 0xe0, 0x94, 0x33, 0xc9, 0xec, 0x7b, 0x2b, 0x35, 0xa6, 0x69, 0x84, 0x4b, 0x35, 0x2e, 0xd5, + 0xed, 0x47, 0x61, 0x24, 0xa7, 0xd9, 0x18, 0x07, 0x2c, 0x26, 0x21, 0x0b, 0x19, 0xd1, 0xa6, 0x71, + 0xf6, 0x41, 0x4f, 0x7a, 0xd0, 0xa7, 0x15, 0xac, 0xdd, 0xdd, 0xba, 0x3a, 0x60, 0x1c, 0x48, 0xbe, + 0x73, 0x61, 0xfb, 0xe9, 0x46, 0x13, 0xd3, 0x60, 0x1a, 0x25, 0xc0, 0x3f, 0x91, 0x74, 0x16, 0xaa, + 0x85, 0x20, 0x31, 0x48, 0xfa, 0x37, 0x17, 0xd9, 0xe7, 0xe2, 0x59, 0x22, 0xa3, 0x18, 0x76, 0x0c, + 0xcf, 0xfe, 0x67, 0x10, 0xc1, 0x14, 0x62, 0xfa, 0xa7, 0xaf, 0xfb, 0xdd, 0x42, 0xb7, 0x2e, 0xd8, + 0xe4, 0x82, 0x83, 0x00, 0x69, 0xbf, 0x47, 0x0d, 0x95, 0x68, 0x42, 0x25, 0x75, 0xac, 0x53, 0xeb, + 0xac, 0x79, 0xfe, 0x18, 0x6f, 0xfe, 0xb0, 0x35, 0x18, 0xa7, 0xb3, 0x50, 0x2d, 0x04, 0x56, 0x6a, + 0x9c, 0xf7, 0xf0, 0xeb, 0xf1, 0x47, 0x08, 0xe4, 0x10, 0x24, 0xf5, 0xec, 0xc5, 0x4d, 0xa7, 0x52, + 0xdc, 0x74, 0xd0, 0x66, 0xe7, 0xaf, 0xa9, 0xf6, 0x10, 0x1d, 0x8b, 0x14, 0x02, 0xe7, 0x48, 0xd3, + 0x1f, 0xe2, 0x7f, 0x3d, 0x07, 0x5e, 0x07, 0x1b, 0xa5, 0x10, 0x78, 0x2d, 0x03, 0x3e, 0x56, 0x93, + 0xaf, 0x31, 0xdd, 0x6f, 0x16, 0x3a, 0x59, 0xab, 0x06, 0x91, 0x90, 0xf6, 0xbb, 0x9d, 0x0a, 0xf8, + 0xb0, 0x0a, 0xca, 0xad, 0x0b, 0xdc, 0x31, 0xf7, 0x34, 0xca, 0xcd, 0x56, 0xfc, 0x01, 0xaa, 0x45, + 0x12, 0x62, 0xe1, 0x1c, 0x9d, 0x56, 0xcf, 0x9a, 0xe7, 0x0f, 0x0e, 0xcc, 0xef, 0x9d, 0x18, 0x66, + 0xed, 0x95, 0x72, 0xfb, 0x2b, 0x48, 0xf7, 0x6b, 0x75, 0x2b, 0xbd, 0x6a, 0x65, 0x53, 0xd4, 0x10, + 0x30, 0x87, 0x40, 0x32, 0x6e, 0xd2, 0x3f, 0x39, 0x30, 0x3d, 0x1d, 0xc3, 0x7c, 0x64, 0xac, 0x9b, + 0x0a, 0xe5, 0xc6, 0x5f, 0x63, 0xed, 0x17, 0xa8, 0x0a, 0x49, 0x6e, 0x0a, 0xb4, 0xb7, 0x0b, 0xa8, + 0x4f, 0x58, 0xb1, 0xfa, 0x49, 0x7e, 0x49, 0xb9, 0xd7, 0x34, 0x90, 0x6a, 0x3f, 0xc9, 0x7d, 0xe5, + 0xb1, 0x07, 0xa8, 0x0e, 0x49, 0xfe, 0x92, 0xb3, 0xd8, 0xa9, 0x6a, 0xfb, 0xfd, 0x3d, 0x76, 0x25, + 0x19, 0xb1, 0x8c, 0x07, 0xe0, 0xdd, 0x36, 0x94, 0xba, 0x59, 0xfb, 0x25, 0xc2, 0xee, 0xa3, 0x7a, + 0xce, 0xe6, 0x59, 0x0c, 0xc2, 0x39, 0xde, 0x1f, 0xe6, 0x52, 0x4b, 0x36, 0x98, 0xd5, 0x2c, 0xfc, + 0xd2, 0x6b, 0xbf, 0x41, 0xad, 0xd5, 0x71, 0xc8, 0xb2, 0x44, 0x0a, 0xa7, 0xa6, 0x59, 0x9d, 0xfd, + 0x2c, 0xad, 0xf3, 0xee, 0x1a, 0x60, 0x6b, 0x6b, 0x29, 0xfc, 0xdf, 0x50, 0x1e, 0x5e, 0x2c, 0xdd, + 0xca, 0xd5, 0xd2, 0xad, 0x5c, 0x2f, 0xdd, 0xca, 0xe7, 0xc2, 0xb5, 0x16, 0x85, 0x6b, 0x5d, 0x15, + 0xae, 0x75, 0x5d, 0xb8, 0xd6, 0x8f, 0xc2, 0xb5, 0xbe, 0xfc, 0x74, 0x2b, 0x6f, 0x1b, 0xe5, 0x7b, + 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x46, 0x15, 0xf2, 0x97, 0xa4, 0x04, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/generated.proto index 098e8dd9b..d5534c4de 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/types_swagger_doc_generated.go index 2a89e5566..508c452f1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_PodPreset = map[string]string{ "": "PodPreset is a policy resource that defines additional runtime requirements for a Pod.", } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/zz_generated.deepcopy.go index 3fe7f6ca4..6397a88ab 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/settings/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/generated.pb.go index 31988b70d..d43a98298 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -152,6 +152,18 @@ func (m *StorageClass) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(len(*m.VolumeBindingMode))) i += copy(dAtA[i:], *m.VolumeBindingMode) } + if len(m.AllowedTopologies) > 0 { + for _, msg := range m.AllowedTopologies { + dAtA[i] = 0x42 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -252,6 +264,12 @@ func (m *StorageClass) Size() (n int) { l = len(*m.VolumeBindingMode) n += 1 + l + sovGenerated(uint64(l)) } + if len(m.AllowedTopologies) > 0 { + for _, e := range m.AllowedTopologies { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -304,6 +322,7 @@ func (this *StorageClass) String() string { `MountOptions:` + fmt.Sprintf("%v", this.MountOptions) + `,`, `AllowVolumeExpansion:` + valueToStringGenerated(this.AllowVolumeExpansion) + `,`, `VolumeBindingMode:` + valueToStringGenerated(this.VolumeBindingMode) + `,`, + `AllowedTopologies:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedTopologies), "TopologySelectorTerm", "k8s_io_api_core_v1.TopologySelectorTerm", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -641,6 +660,37 @@ func (m *StorageClass) Unmarshal(dAtA []byte) error { s := VolumeBindingMode(dAtA[iNdEx:postIndex]) m.VolumeBindingMode = &s iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedTopologies", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedTopologies = append(m.AllowedTopologies, k8s_io_api_core_v1.TopologySelectorTerm{}) + if err := m.AllowedTopologies[len(m.AllowedTopologies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -883,44 +933,46 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 623 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x4f, 0x6f, 0xd3, 0x3c, - 0x18, 0x6f, 0xda, 0xb7, 0x2f, 0x9b, 0xbb, 0x89, 0x2e, 0x0c, 0x29, 0xea, 0x21, 0xa9, 0xc6, 0xa5, - 0x9a, 0x84, 0xb3, 0x6e, 0x03, 0x4d, 0x48, 0x20, 0x11, 0x34, 0x09, 0xa4, 0x4d, 0xab, 0x82, 0x34, - 0x21, 0xc4, 0x01, 0x37, 0x7d, 0xc8, 0x4c, 0x13, 0x3b, 0xb2, 0x9d, 0x40, 0x6f, 0x7c, 0x04, 0xce, - 0x7c, 0x14, 0x3e, 0xc1, 0x8e, 0x3b, 0xee, 0x14, 0xb1, 0xf0, 0x2d, 0x76, 0x42, 0x49, 0xca, 0x9a, - 0xad, 0x9d, 0xd8, 0x2d, 0xfe, 0xfd, 0xb3, 0x9f, 0x27, 0x3f, 0xf4, 0x62, 0xbc, 0x27, 0x31, 0xe5, - 0xf6, 0x38, 0x1e, 0x82, 0x60, 0xa0, 0x40, 0xda, 0x09, 0xb0, 0x11, 0x17, 0xf6, 0x94, 0x20, 0x11, - 0xb5, 0xa5, 0xe2, 0x82, 0xf8, 0x60, 0x27, 0x7d, 0xdb, 0x07, 0x06, 0x82, 0x28, 0x18, 0xe1, 0x48, - 0x70, 0xc5, 0xf5, 0x87, 0xa5, 0x0c, 0x93, 0x88, 0xe2, 0xa9, 0x0c, 0x27, 0xfd, 0xce, 0x63, 0x9f, - 0xaa, 0x93, 0x78, 0x88, 0x3d, 0x1e, 0xda, 0x3e, 0xf7, 0xb9, 0x5d, 0xa8, 0x87, 0xf1, 0xa7, 0xe2, - 0x54, 0x1c, 0x8a, 0xaf, 0x32, 0xa5, 0xb3, 0xb9, 0xf0, 0xb2, 0x21, 0x28, 0x32, 0x77, 0x63, 0x67, - 0x77, 0xa6, 0x0d, 0x89, 0x77, 0x42, 0x19, 0x88, 0x89, 0x1d, 0x8d, 0xfd, 0x1c, 0x90, 0x76, 0x08, - 0x8a, 0x2c, 0x78, 0x67, 0xc7, 0xbe, 0xcd, 0x25, 0x62, 0xa6, 0x68, 0x08, 0x73, 0x86, 0xa7, 0xff, - 0x32, 0x48, 0xef, 0x04, 0x42, 0x32, 0xe7, 0xdb, 0xb9, 0xcd, 0x17, 0x2b, 0x1a, 0xd8, 0x94, 0x29, - 0xa9, 0xc4, 0x4d, 0xd3, 0xc6, 0x8f, 0x26, 0x5a, 0x79, 0x5b, 0xce, 0xfd, 0x2a, 0x20, 0x52, 0xea, - 0x1f, 0xd1, 0x52, 0x3e, 0xc9, 0x88, 0x28, 0x62, 0x68, 0x5d, 0xad, 0xd7, 0xda, 0xde, 0xc2, 0xb3, - 0x4d, 0x5f, 0x05, 0xe3, 0x68, 0xec, 0xe7, 0x80, 0xc4, 0xb9, 0x1a, 0x27, 0x7d, 0x7c, 0x34, 0xfc, - 0x0c, 0x9e, 0x3a, 0x04, 0x45, 0x1c, 0xfd, 0x34, 0xb5, 0x6a, 0x59, 0x6a, 0xa1, 0x19, 0xe6, 0x5e, - 0xa5, 0xea, 0x4f, 0x50, 0x2b, 0x12, 0x3c, 0xa1, 0x92, 0x72, 0x06, 0xc2, 0xa8, 0x77, 0xb5, 0xde, - 0xb2, 0xf3, 0x60, 0x6a, 0x69, 0x0d, 0x66, 0x94, 0x5b, 0xd5, 0xe9, 0x3e, 0x42, 0x11, 0x11, 0x24, - 0x04, 0x05, 0x42, 0x1a, 0x8d, 0x6e, 0xa3, 0xd7, 0xda, 0xde, 0xc1, 0x0b, 0x4b, 0x80, 0xab, 0x13, - 0xe1, 0xc1, 0x95, 0x6b, 0x9f, 0x29, 0x31, 0x99, 0xbd, 0x6e, 0x46, 0xb8, 0x95, 0x68, 0x7d, 0x8c, - 0x56, 0x05, 0x78, 0x01, 0xa1, 0xe1, 0x80, 0x07, 0xd4, 0x9b, 0x18, 0xff, 0x15, 0x2f, 0xdc, 0xcf, - 0x52, 0x6b, 0xd5, 0xad, 0x12, 0x97, 0xa9, 0xb5, 0x55, 0xa9, 0x8f, 0xc7, 0x45, 0xde, 0x1d, 0x3c, - 0x00, 0x21, 0xa9, 0x54, 0xc0, 0xd4, 0x31, 0x0f, 0xe2, 0x10, 0xae, 0x79, 0xdc, 0xeb, 0xd9, 0xfa, - 0x2e, 0x5a, 0x09, 0x79, 0xcc, 0xd4, 0x51, 0xa4, 0x28, 0x67, 0xd2, 0x68, 0x76, 0x1b, 0xbd, 0x65, - 0xa7, 0x9d, 0xa5, 0xd6, 0xca, 0x61, 0x05, 0x77, 0xaf, 0xa9, 0xf4, 0x03, 0xb4, 0x4e, 0x82, 0x80, - 0x7f, 0x29, 0x2f, 0xd8, 0xff, 0x1a, 0x11, 0x96, 0x6f, 0xc9, 0xf8, 0xbf, 0xab, 0xf5, 0x96, 0x1c, - 0x23, 0x4b, 0xad, 0xf5, 0x97, 0x0b, 0x78, 0x77, 0xa1, 0x4b, 0x7f, 0x87, 0xd6, 0x92, 0x02, 0x72, - 0x28, 0x1b, 0x51, 0xe6, 0x1f, 0xf2, 0x11, 0x18, 0xf7, 0x8a, 0xa1, 0x37, 0xb3, 0xd4, 0x5a, 0x3b, - 0xbe, 0x49, 0x5e, 0x2e, 0x02, 0xdd, 0xf9, 0x90, 0xce, 0x73, 0x74, 0xff, 0xc6, 0xf6, 0xf5, 0x36, - 0x6a, 0x8c, 0x61, 0x52, 0x54, 0x6b, 0xd9, 0xcd, 0x3f, 0xf5, 0x75, 0xd4, 0x4c, 0x48, 0x10, 0x43, - 0xd9, 0x04, 0xb7, 0x3c, 0x3c, 0xab, 0xef, 0x69, 0x1b, 0x3f, 0x35, 0xd4, 0xae, 0xfe, 0xca, 0x03, - 0x2a, 0x95, 0xfe, 0x61, 0xae, 0xa0, 0xf8, 0x6e, 0x05, 0xcd, 0xdd, 0x45, 0x3d, 0xdb, 0xd3, 0x02, - 0x2c, 0xfd, 0x45, 0x2a, 0xe5, 0x7c, 0x8d, 0x9a, 0x54, 0x41, 0x28, 0x8d, 0x7a, 0x51, 0xb0, 0x47, - 0x77, 0x28, 0x98, 0xb3, 0x3a, 0xcd, 0x6b, 0xbe, 0xc9, 0x9d, 0x6e, 0x19, 0xe0, 0xf4, 0x4e, 0x2f, - 0xcc, 0xda, 0xd9, 0x85, 0x59, 0x3b, 0xbf, 0x30, 0x6b, 0xdf, 0x32, 0x53, 0x3b, 0xcd, 0x4c, 0xed, - 0x2c, 0x33, 0xb5, 0xf3, 0xcc, 0xd4, 0x7e, 0x65, 0xa6, 0xf6, 0xfd, 0xb7, 0x59, 0x7b, 0x5f, 0x4f, - 0xfa, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xee, 0x56, 0xcc, 0xfd, 0x0a, 0x05, 0x00, 0x00, + // 656 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xcd, 0x6e, 0xd3, 0x4a, + 0x14, 0x8e, 0x93, 0x9b, 0xde, 0x74, 0xd2, 0xea, 0x26, 0xbe, 0xbd, 0x92, 0x6f, 0x16, 0x4e, 0x54, + 0x36, 0x11, 0x12, 0xe3, 0xa6, 0x14, 0x54, 0x21, 0x81, 0x54, 0xa3, 0x4a, 0x20, 0xb5, 0x6a, 0xe4, + 0x56, 0x15, 0x42, 0x2c, 0x98, 0x38, 0x07, 0x77, 0x88, 0xed, 0x31, 0x33, 0x63, 0x43, 0x76, 0xbc, + 0x00, 0x12, 0xcf, 0xc3, 0x13, 0x74, 0xd9, 0x65, 0x57, 0x16, 0x35, 0x6f, 0xd1, 0x15, 0xf2, 0x0f, + 0x8d, 0x9b, 0x04, 0xd1, 0xdd, 0xcc, 0x77, 0xbe, 0xef, 0x3b, 0x33, 0xe7, 0x07, 0x3d, 0x9b, 0xec, + 0x0a, 0x4c, 0x99, 0x31, 0x09, 0x47, 0xc0, 0x7d, 0x90, 0x20, 0x8c, 0x08, 0xfc, 0x31, 0xe3, 0x46, + 0x11, 0x20, 0x01, 0x35, 0x84, 0x64, 0x9c, 0x38, 0x60, 0x44, 0x03, 0xc3, 0x01, 0x1f, 0x38, 0x91, + 0x30, 0xc6, 0x01, 0x67, 0x92, 0xa9, 0xff, 0xe5, 0x34, 0x4c, 0x02, 0x8a, 0x0b, 0x1a, 0x8e, 0x06, + 0x9d, 0x07, 0x0e, 0x95, 0x67, 0xe1, 0x08, 0xdb, 0xcc, 0x33, 0x1c, 0xe6, 0x30, 0x23, 0x63, 0x8f, + 0xc2, 0x77, 0xd9, 0x2d, 0xbb, 0x64, 0xa7, 0xdc, 0xa5, 0xb3, 0x59, 0x4a, 0x66, 0x33, 0xbe, 0x2c, + 0x53, 0x67, 0x67, 0xc6, 0xf1, 0x88, 0x7d, 0x46, 0x7d, 0xe0, 0x53, 0x23, 0x98, 0x38, 0x29, 0x20, + 0x0c, 0x0f, 0x24, 0x59, 0xa6, 0x32, 0x7e, 0xa7, 0xe2, 0xa1, 0x2f, 0xa9, 0x07, 0x0b, 0x82, 0xc7, + 0x7f, 0x12, 0x08, 0xfb, 0x0c, 0x3c, 0x32, 0xaf, 0xdb, 0xfc, 0xb2, 0x82, 0xd6, 0x8e, 0xf3, 0x02, + 0x3c, 0x77, 0x89, 0x10, 0xea, 0x5b, 0xd4, 0x48, 0x1f, 0x35, 0x26, 0x92, 0x68, 0x4a, 0x4f, 0xe9, + 0x37, 0xb7, 0xb7, 0xf0, 0xac, 0x58, 0x37, 0xde, 0x38, 0x98, 0x38, 0x29, 0x20, 0x70, 0xca, 0xc6, + 0xd1, 0x00, 0x1f, 0x8d, 0xde, 0x83, 0x2d, 0x0f, 0x41, 0x12, 0x53, 0x3d, 0x8f, 0xbb, 0x95, 0x24, + 0xee, 0xa2, 0x19, 0x66, 0xdd, 0xb8, 0xaa, 0x8f, 0x50, 0x33, 0xe0, 0x2c, 0xa2, 0x82, 0x32, 0x1f, + 0xb8, 0x56, 0xed, 0x29, 0xfd, 0x55, 0xf3, 0xdf, 0x42, 0xd2, 0x1c, 0xce, 0x42, 0x56, 0x99, 0xa7, + 0x3a, 0x08, 0x05, 0x84, 0x13, 0x0f, 0x24, 0x70, 0xa1, 0xd5, 0x7a, 0xb5, 0x7e, 0x73, 0xfb, 0x21, + 0x5e, 0xda, 0x47, 0x5c, 0xfe, 0x11, 0x1e, 0xde, 0xa8, 0xf6, 0x7d, 0xc9, 0xa7, 0xb3, 0xd7, 0xcd, + 0x02, 0x56, 0xc9, 0x5a, 0x9d, 0xa0, 0x75, 0x0e, 0xb6, 0x4b, 0xa8, 0x37, 0x64, 0x2e, 0xb5, 0xa7, + 0xda, 0x5f, 0xd9, 0x0b, 0xf7, 0x93, 0xb8, 0xbb, 0x6e, 0x95, 0x03, 0xd7, 0x71, 0x77, 0x6b, 0x71, + 0x02, 0xf0, 0x10, 0xb8, 0xa0, 0x42, 0x82, 0x2f, 0x4f, 0x99, 0x1b, 0x7a, 0x70, 0x4b, 0x63, 0xdd, + 0xf6, 0x56, 0x77, 0xd0, 0x9a, 0xc7, 0x42, 0x5f, 0x1e, 0x05, 0x92, 0x32, 0x5f, 0x68, 0xf5, 0x5e, + 0xad, 0xbf, 0x6a, 0xb6, 0x92, 0xb8, 0xbb, 0x76, 0x58, 0xc2, 0xad, 0x5b, 0x2c, 0xf5, 0x00, 0x6d, + 0x10, 0xd7, 0x65, 0x1f, 0xf3, 0x04, 0xfb, 0x9f, 0x02, 0xe2, 0xa7, 0x55, 0xd2, 0x56, 0x7a, 0x4a, + 0xbf, 0x61, 0x6a, 0x49, 0xdc, 0xdd, 0xd8, 0x5b, 0x12, 0xb7, 0x96, 0xaa, 0xd4, 0x57, 0xa8, 0x1d, + 0x65, 0x90, 0x49, 0xfd, 0x31, 0xf5, 0x9d, 0x43, 0x36, 0x06, 0xed, 0xef, 0xec, 0xd3, 0xf7, 0x93, + 0xb8, 0xdb, 0x3e, 0x9d, 0x0f, 0x5e, 0x2f, 0x03, 0xad, 0x45, 0x13, 0xf5, 0x03, 0x6a, 0x67, 0x19, + 0x61, 0x7c, 0xc2, 0x02, 0xe6, 0x32, 0x87, 0x82, 0xd0, 0x1a, 0x59, 0xeb, 0xfa, 0xe5, 0xd6, 0xa5, + 0xa5, 0x4b, 0xfb, 0x56, 0xb0, 0xa6, 0xc7, 0xe0, 0x82, 0x2d, 0x19, 0x3f, 0x01, 0xee, 0x99, 0xff, + 0x17, 0xfd, 0x6a, 0xef, 0xcd, 0x5b, 0x59, 0x8b, 0xee, 0x9d, 0xa7, 0xe8, 0x9f, 0xb9, 0x86, 0xab, + 0x2d, 0x54, 0x9b, 0xc0, 0x34, 0x9b, 0xe6, 0x55, 0x2b, 0x3d, 0xaa, 0x1b, 0xa8, 0x1e, 0x11, 0x37, + 0x84, 0x7c, 0xf8, 0xac, 0xfc, 0xf2, 0xa4, 0xba, 0xab, 0x6c, 0x7e, 0x53, 0x50, 0xab, 0x3c, 0x3d, + 0x07, 0x54, 0x48, 0xf5, 0xcd, 0xc2, 0x4e, 0xe0, 0xbb, 0xed, 0x44, 0xaa, 0xce, 0x36, 0xa2, 0x55, + 0xfc, 0xa1, 0xf1, 0x0b, 0x29, 0xed, 0xc3, 0x0b, 0x54, 0xa7, 0x12, 0x3c, 0xa1, 0x55, 0xb3, 0xc2, + 0xdc, 0xbb, 0xc3, 0x4c, 0x9b, 0xeb, 0x85, 0x5f, 0xfd, 0x65, 0xaa, 0xb4, 0x72, 0x03, 0xb3, 0x7f, + 0x7e, 0xa5, 0x57, 0x2e, 0xae, 0xf4, 0xca, 0xe5, 0x95, 0x5e, 0xf9, 0x9c, 0xe8, 0xca, 0x79, 0xa2, + 0x2b, 0x17, 0x89, 0xae, 0x5c, 0x26, 0xba, 0xf2, 0x3d, 0xd1, 0x95, 0xaf, 0x3f, 0xf4, 0xca, 0xeb, + 0x6a, 0x34, 0xf8, 0x19, 0x00, 0x00, 0xff, 0xff, 0x0d, 0x64, 0x41, 0x83, 0x40, 0x05, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/generated.proto index 72b3ceb83..df9f1dc45 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,11 +21,10 @@ syntax = 'proto2'; package k8s.io.api.storage.v1; -import "k8s.io/api/storage/v1beta1/generated.proto"; +import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; @@ -70,6 +69,14 @@ message StorageClass { // the VolumeScheduling feature. // +optional optional string volumeBindingMode = 7; + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + repeated k8s.io.api.core.v1.TopologySelectorTerm allowedTopologies = 8; } // StorageClassList is a collection of storage classes. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/types.go index 288d40abb..45bfa7681 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/types.go @@ -66,6 +66,14 @@ type StorageClass struct { // the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode `json:"volumeBindingMode,omitempty" protobuf:"bytes,7,opt,name=volumeBindingMode"` + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + AllowedTopologies []v1.TopologySelectorTerm `json:"allowedTopologies,omitempty" protobuf:"bytes,8,rep,name=allowedTopologies"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/types_swagger_doc_generated.go index 3eb9bdab7..1d6587047 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_StorageClass = map[string]string{ "": "StorageClass describes the parameters for a class of storage for which PersistentVolumes can be dynamically provisioned.\n\nStorageClasses are non-namespaced; the name of the storage class according to etcd is in ObjectMeta.Name.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -36,6 +36,7 @@ var map_StorageClass = map[string]string{ "mountOptions": "Dynamically provisioned PersistentVolumes of this storage class are created with these mountOptions, e.g. [\"ro\", \"soft\"]. Not validated - mount of the PVs will simply fail if one is invalid.", "allowVolumeExpansion": "AllowVolumeExpansion shows whether the storage class allow volume expand", "volumeBindingMode": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature.", + "allowedTopologies": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", } func (StorageClass) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/zz_generated.deepcopy.go index ccab05ccc..a1050134c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -69,6 +69,13 @@ func (in *StorageClass) DeepCopyInto(out *StorageClass) { **out = **in } } + if in.AllowedTopologies != nil { + in, out := &in.AllowedTopologies, &out.AllowedTopologies + *out = make([]core_v1.TopologySelectorTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/generated.pb.go index 586a1b672..507b5c1d5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1472,52 +1472,49 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 745 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0x3d, 0x6f, 0xdb, 0x46, - 0x18, 0xc7, 0x45, 0x49, 0xb6, 0xe5, 0x53, 0x5f, 0x8c, 0x83, 0xd0, 0x0a, 0x2a, 0x40, 0x19, 0x9a, - 0xdc, 0xa2, 0x3e, 0x56, 0x76, 0x51, 0x18, 0xdd, 0x44, 0xd8, 0x43, 0x51, 0xcb, 0x2d, 0xe8, 0xa2, - 0x43, 0xdb, 0xa1, 0x27, 0xf2, 0x31, 0x45, 0x4b, 0x7c, 0xc1, 0xdd, 0x51, 0x88, 0xb7, 0x4c, 0x99, - 0xb3, 0xe5, 0x1b, 0xe4, 0xb3, 0x68, 0x8b, 0x47, 0x4f, 0x42, 0xcc, 0x7c, 0x8b, 0x2c, 0x09, 0x78, - 0x3c, 0x89, 0xb2, 0x29, 0x25, 0xb6, 0x37, 0x3e, 0xcf, 0x3d, 0xff, 0xdf, 0xf3, 0x76, 0x47, 0x74, - 0x3c, 0x3a, 0xe2, 0xc4, 0x0b, 0x8d, 0x51, 0x3c, 0x00, 0x16, 0x80, 0x00, 0x6e, 0x4c, 0x20, 0x70, - 0x42, 0x66, 0xa8, 0x03, 0x1a, 0x79, 0x06, 0x17, 0x21, 0xa3, 0x2e, 0x18, 0x93, 0x2e, 0x1d, 0x47, - 0x43, 0xda, 0x35, 0x5c, 0x08, 0x80, 0x51, 0x01, 0x0e, 0x89, 0x58, 0x28, 0x42, 0xfc, 0x5d, 0x16, - 0x4c, 0x68, 0xe4, 0x11, 0x15, 0x4c, 0xe6, 0xc1, 0xad, 0x7d, 0xd7, 0x13, 0xc3, 0x78, 0x40, 0xec, - 0xd0, 0x37, 0xdc, 0xd0, 0x0d, 0x0d, 0xa9, 0x19, 0xc4, 0x17, 0xd2, 0x92, 0x86, 0xfc, 0xca, 0x58, - 0xad, 0x7e, 0x9e, 0x18, 0x9e, 0x09, 0x08, 0xb8, 0x17, 0x06, 0x7c, 0x9f, 0x46, 0x1e, 0x07, 0x36, - 0x01, 0x66, 0x44, 0x23, 0x37, 0x3d, 0xe3, 0x77, 0x03, 0x8c, 0x49, 0x77, 0x00, 0xa2, 0x58, 0x5a, - 0xeb, 0xe7, 0x1c, 0xe7, 0x53, 0x7b, 0xe8, 0x05, 0xc0, 0xae, 0x72, 0x86, 0x0f, 0x82, 0x1a, 0x93, - 0xa2, 0xca, 0x58, 0xa7, 0x62, 0x71, 0x20, 0x3c, 0x1f, 0x0a, 0x82, 0x5f, 0x3e, 0x27, 0xe0, 0xf6, - 0x10, 0x7c, 0x5a, 0xd0, 0x1d, 0xae, 0xd3, 0xc5, 0xc2, 0x1b, 0x1b, 0x5e, 0x20, 0xb8, 0x60, 0xf7, - 0x45, 0x9d, 0xd7, 0x65, 0xb4, 0xf3, 0x77, 0x38, 0x8e, 0x7d, 0xe8, 0x09, 0x41, 0xed, 0xa1, 0x0f, - 0x81, 0xc0, 0xff, 0xa3, 0x5a, 0xda, 0x8d, 0x43, 0x05, 0x6d, 0x6a, 0xbb, 0xda, 0x5e, 0xfd, 0xe0, - 0x27, 0x92, 0xaf, 0x65, 0x01, 0x27, 0xd1, 0xc8, 0x4d, 0x1d, 0x9c, 0xa4, 0xd1, 0x64, 0xd2, 0x25, - 0x7f, 0x0c, 0x2e, 0xc1, 0x16, 0x7d, 0x10, 0xd4, 0xc4, 0xd3, 0x59, 0xbb, 0x94, 0xcc, 0xda, 0x28, - 0xf7, 0x59, 0x0b, 0x2a, 0x3e, 0x47, 0x55, 0x1e, 0x81, 0xdd, 0x2c, 0x4b, 0x7a, 0x97, 0x7c, 0x62, - 0xe9, 0xe4, 0x7e, 0x79, 0xe7, 0x11, 0xd8, 0xe6, 0x17, 0x0a, 0x5f, 0x4d, 0x2d, 0x4b, 0xc2, 0xf0, - 0xbf, 0x68, 0x93, 0x0b, 0x2a, 0x62, 0xde, 0xac, 0x48, 0xec, 0xe1, 0xe3, 0xb0, 0x52, 0x6a, 0x7e, - 0xa5, 0xc0, 0x9b, 0x99, 0x6d, 0x29, 0x64, 0x67, 0xaa, 0xa1, 0xc6, 0x7d, 0xc9, 0xa9, 0xc7, 0x05, - 0xfe, 0xaf, 0x30, 0x2c, 0xf2, 0xb0, 0x61, 0xa5, 0x6a, 0x39, 0xaa, 0x1d, 0x95, 0xb2, 0x36, 0xf7, - 0x2c, 0x0d, 0xca, 0x42, 0x1b, 0x9e, 0x00, 0x9f, 0x37, 0xcb, 0xbb, 0x95, 0xbd, 0xfa, 0xc1, 0xfe, - 0xa3, 0x5a, 0x32, 0xbf, 0x54, 0xe4, 0x8d, 0xdf, 0x52, 0x86, 0x95, 0xa1, 0x3a, 0x17, 0xe8, 0x9b, - 0x42, 0xf3, 0x61, 0xcc, 0x6c, 0xc0, 0xa7, 0xa8, 0x11, 0x01, 0xe3, 0x1e, 0x17, 0x10, 0x88, 0x2c, - 0xe6, 0x8c, 0xfa, 0x20, 0xfb, 0xda, 0x36, 0x9b, 0xc9, 0xac, 0xdd, 0xf8, 0x73, 0xc5, 0xb9, 0xb5, - 0x52, 0xd5, 0x79, 0xb3, 0x62, 0x64, 0xe9, 0xba, 0xf0, 0x8f, 0xa8, 0x46, 0xa5, 0x07, 0x98, 0x42, - 0x2f, 0x46, 0xd0, 0x53, 0x7e, 0x6b, 0x11, 0x21, 0xd7, 0x2a, 0xcb, 0x53, 0xb7, 0xe5, 0x91, 0x6b, - 0x95, 0xd2, 0xa5, 0xb5, 0x4a, 0xdb, 0x52, 0xc8, 0xb4, 0x94, 0x20, 0x74, 0xb2, 0x2e, 0x2b, 0x77, - 0x4b, 0x39, 0x53, 0x7e, 0x6b, 0x11, 0xd1, 0xf9, 0x50, 0x59, 0x31, 0x3a, 0x79, 0x3f, 0x96, 0x7a, - 0x72, 0x64, 0x4f, 0xb5, 0x42, 0x4f, 0xce, 0xa2, 0x27, 0x07, 0xbf, 0xd2, 0x10, 0xa6, 0x0b, 0x44, - 0x7f, 0x7e, 0x7f, 0xb2, 0x25, 0xff, 0xfe, 0x84, 0x7b, 0x4b, 0x7a, 0x05, 0xda, 0x49, 0x20, 0xd8, - 0x95, 0xd9, 0x52, 0x55, 0xe0, 0x62, 0x80, 0xb5, 0xa2, 0x04, 0x7c, 0x89, 0xea, 0x99, 0xf7, 0x84, - 0xb1, 0x90, 0xa9, 0x97, 0xb4, 0xf7, 0x80, 0x8a, 0x64, 0xbc, 0xa9, 0x27, 0xb3, 0x76, 0xbd, 0x97, - 0x03, 0xde, 0xcf, 0xda, 0xf5, 0xa5, 0x73, 0x6b, 0x19, 0x9e, 0xe6, 0x72, 0x20, 0xcf, 0x55, 0x7d, - 0x4a, 0xae, 0x63, 0x58, 0x9f, 0x6b, 0x09, 0xde, 0x3a, 0x41, 0xdf, 0xae, 0x19, 0x11, 0xde, 0x41, - 0x95, 0x11, 0x5c, 0x65, 0x37, 0xd1, 0x4a, 0x3f, 0x71, 0x03, 0x6d, 0x4c, 0xe8, 0x38, 0xce, 0x6e, - 0xdc, 0xb6, 0x95, 0x19, 0xbf, 0x96, 0x8f, 0xb4, 0xce, 0x0b, 0x0d, 0x2d, 0xe7, 0xc0, 0xa7, 0xa8, - 0x9a, 0xfe, 0x93, 0xd5, 0xcb, 0xff, 0xe1, 0x61, 0x2f, 0xff, 0x2f, 0xcf, 0x87, 0xfc, 0x0f, 0x96, - 0x5a, 0x96, 0xa4, 0xe0, 0xef, 0xd1, 0x96, 0x0f, 0x9c, 0x53, 0x57, 0x65, 0x36, 0xbf, 0x56, 0x41, - 0x5b, 0xfd, 0xcc, 0x6d, 0xcd, 0xcf, 0x4d, 0x32, 0xbd, 0xd5, 0x4b, 0xd7, 0xb7, 0x7a, 0xe9, 0xe6, - 0x56, 0x2f, 0x3d, 0x4f, 0x74, 0x6d, 0x9a, 0xe8, 0xda, 0x75, 0xa2, 0x6b, 0x37, 0x89, 0xae, 0xbd, - 0x4d, 0x74, 0xed, 0xe5, 0x3b, 0xbd, 0xf4, 0x4f, 0x6d, 0x3e, 0xb8, 0x8f, 0x01, 0x00, 0x00, 0xff, - 0xff, 0x68, 0x82, 0x7b, 0x73, 0x9e, 0x07, 0x00, 0x00, + // 704 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0x4d, 0x6f, 0xd3, 0x4c, + 0x10, 0xc7, 0xe3, 0x24, 0x6d, 0xd3, 0xcd, 0xf3, 0x52, 0xad, 0xa2, 0xe7, 0x89, 0x82, 0xe4, 0x54, + 0x39, 0x15, 0x44, 0xd7, 0xa4, 0x20, 0x54, 0x71, 0x8b, 0xd5, 0x1e, 0x10, 0x6d, 0x41, 0x5b, 0xc4, + 0x01, 0x38, 0xb0, 0xb1, 0xa7, 0x8e, 0x9b, 0xfa, 0x45, 0xbb, 0xeb, 0x48, 0xbd, 0x71, 0xe2, 0xcc, + 0x8d, 0x6f, 0xc0, 0x67, 0xc9, 0x8d, 0x1e, 0x7b, 0x8a, 0xa8, 0xf9, 0x16, 0x5c, 0x40, 0x5e, 0x6f, + 0x5e, 0x68, 0x52, 0x68, 0x7b, 0xf3, 0xcc, 0xce, 0xfc, 0x66, 0xe6, 0xbf, 0xb3, 0x46, 0x3b, 0xfd, + 0x6d, 0x41, 0xfc, 0xc8, 0xea, 0x27, 0x5d, 0xe0, 0x21, 0x48, 0x10, 0xd6, 0x00, 0x42, 0x37, 0xe2, + 0x96, 0x3e, 0x60, 0xb1, 0x6f, 0x09, 0x19, 0x71, 0xe6, 0x81, 0x35, 0x68, 0xb3, 0x93, 0xb8, 0xc7, + 0xda, 0x96, 0x07, 0x21, 0x70, 0x26, 0xc1, 0x25, 0x31, 0x8f, 0x64, 0x84, 0xef, 0xe4, 0xc1, 0x84, + 0xc5, 0x3e, 0xd1, 0xc1, 0x64, 0x1c, 0xdc, 0xd8, 0xf4, 0x7c, 0xd9, 0x4b, 0xba, 0xc4, 0x89, 0x02, + 0xcb, 0x8b, 0xbc, 0xc8, 0x52, 0x39, 0xdd, 0xe4, 0x48, 0x59, 0xca, 0x50, 0x5f, 0x39, 0xab, 0xf1, + 0x68, 0x5a, 0x38, 0x60, 0x4e, 0xcf, 0x0f, 0x81, 0x9f, 0x5a, 0x71, 0xdf, 0xcb, 0x1c, 0xc2, 0x0a, + 0x40, 0x32, 0x6b, 0x30, 0xd7, 0x41, 0xc3, 0xba, 0x2a, 0x8b, 0x27, 0xa1, 0xf4, 0x03, 0x98, 0x4b, + 0x78, 0xfc, 0xa7, 0x04, 0xe1, 0xf4, 0x20, 0x60, 0x97, 0xf3, 0x5a, 0x9f, 0x8b, 0x68, 0xed, 0x55, + 0x74, 0x92, 0x04, 0xd0, 0x91, 0x92, 0x39, 0xbd, 0x00, 0x42, 0x89, 0xdf, 0xa1, 0x4a, 0xd6, 0x98, + 0xcb, 0x24, 0xab, 0x1b, 0xeb, 0xc6, 0x46, 0x75, 0xeb, 0x01, 0x99, 0x4a, 0x32, 0xe1, 0x93, 0xb8, + 0xef, 0x65, 0x0e, 0x41, 0xb2, 0x68, 0x32, 0x68, 0x93, 0xe7, 0xdd, 0x63, 0x70, 0xe4, 0x3e, 0x48, + 0x66, 0xe3, 0xe1, 0xa8, 0x59, 0x48, 0x47, 0x4d, 0x34, 0xf5, 0xd1, 0x09, 0x15, 0x1f, 0xa2, 0xb2, + 0x88, 0xc1, 0xa9, 0x17, 0x15, 0xbd, 0x4d, 0x7e, 0x23, 0x38, 0xb9, 0xdc, 0xde, 0x61, 0x0c, 0x8e, + 0xfd, 0x97, 0xc6, 0x97, 0x33, 0x8b, 0x2a, 0x18, 0x7e, 0x83, 0x96, 0x85, 0x64, 0x32, 0x11, 0xf5, + 0x92, 0xc2, 0x3e, 0xbc, 0x19, 0x56, 0xa5, 0xda, 0xff, 0x68, 0xf0, 0x72, 0x6e, 0x53, 0x8d, 0x6c, + 0x0d, 0x0d, 0x54, 0xbb, 0x9c, 0xb2, 0xe7, 0x0b, 0x89, 0xdf, 0xce, 0x89, 0x45, 0xae, 0x27, 0x56, + 0x96, 0xad, 0xa4, 0x5a, 0xd3, 0x25, 0x2b, 0x63, 0xcf, 0x8c, 0x50, 0x14, 0x2d, 0xf9, 0x12, 0x02, + 0x51, 0x2f, 0xae, 0x97, 0x36, 0xaa, 0x5b, 0x9b, 0x37, 0x1a, 0xc9, 0xfe, 0x5b, 0x93, 0x97, 0x9e, + 0x66, 0x0c, 0x9a, 0xa3, 0x5a, 0x47, 0xe8, 0xbf, 0xb9, 0xe1, 0xa3, 0x84, 0x3b, 0x80, 0xf7, 0x50, + 0x2d, 0x06, 0x2e, 0x7c, 0x21, 0x21, 0x94, 0x79, 0xcc, 0x01, 0x0b, 0x40, 0xcd, 0xb5, 0x6a, 0xd7, + 0xd3, 0x51, 0xb3, 0xf6, 0x62, 0xc1, 0x39, 0x5d, 0x98, 0xd5, 0xfa, 0xb2, 0x40, 0xb2, 0xec, 0xba, + 0xf0, 0x7d, 0x54, 0x61, 0xca, 0x03, 0x5c, 0xa3, 0x27, 0x12, 0x74, 0xb4, 0x9f, 0x4e, 0x22, 0xd4, + 0xb5, 0xaa, 0xf6, 0xf4, 0xb6, 0xdc, 0xf0, 0x5a, 0x55, 0xea, 0xcc, 0xb5, 0x2a, 0x9b, 0x6a, 0x64, + 0xd6, 0x4a, 0x18, 0xb9, 0xf9, 0x94, 0xa5, 0x5f, 0x5b, 0x39, 0xd0, 0x7e, 0x3a, 0x89, 0x68, 0xfd, + 0x28, 0x2d, 0x90, 0x4e, 0xed, 0xc7, 0xcc, 0x4c, 0xae, 0x9a, 0xa9, 0x32, 0x37, 0x93, 0x3b, 0x99, + 0xc9, 0xc5, 0x9f, 0x0c, 0x84, 0xd9, 0x04, 0xb1, 0x3f, 0xde, 0x9f, 0xfc, 0x92, 0x9f, 0xdd, 0x62, + 0x6f, 0x49, 0x67, 0x8e, 0xb6, 0x1b, 0x4a, 0x7e, 0x6a, 0x37, 0x74, 0x17, 0x78, 0x3e, 0x80, 0x2e, + 0x68, 0x01, 0x1f, 0xa3, 0x6a, 0xee, 0xdd, 0xe5, 0x3c, 0xe2, 0xfa, 0x25, 0x6d, 0x5c, 0xa3, 0x23, + 0x15, 0x6f, 0x9b, 0xe9, 0xa8, 0x59, 0xed, 0x4c, 0x01, 0xdf, 0x47, 0xcd, 0xea, 0xcc, 0x39, 0x9d, + 0x85, 0x67, 0xb5, 0x5c, 0x98, 0xd6, 0x2a, 0xdf, 0xa6, 0xd6, 0x0e, 0x5c, 0x5d, 0x6b, 0x06, 0xde, + 0xd8, 0x45, 0xff, 0x5f, 0x21, 0x11, 0x5e, 0x43, 0xa5, 0x3e, 0x9c, 0xe6, 0x9b, 0x48, 0xb3, 0x4f, + 0x5c, 0x43, 0x4b, 0x03, 0x76, 0x92, 0xe4, 0x1b, 0xb7, 0x4a, 0x73, 0xe3, 0x49, 0x71, 0xdb, 0x68, + 0x7d, 0x30, 0xd0, 0x6c, 0x0d, 0xbc, 0x87, 0xca, 0xd9, 0xef, 0x55, 0xbf, 0xfc, 0x7b, 0xd7, 0x7b, + 0xf9, 0x2f, 0xfd, 0x00, 0xa6, 0x7f, 0xb0, 0xcc, 0xa2, 0x8a, 0x82, 0xef, 0xa2, 0x95, 0x00, 0x84, + 0x60, 0x9e, 0xae, 0x6c, 0xff, 0xab, 0x83, 0x56, 0xf6, 0x73, 0x37, 0x1d, 0x9f, 0xdb, 0x64, 0x78, + 0x61, 0x16, 0xce, 0x2e, 0xcc, 0xc2, 0xf9, 0x85, 0x59, 0x78, 0x9f, 0x9a, 0xc6, 0x30, 0x35, 0x8d, + 0xb3, 0xd4, 0x34, 0xce, 0x53, 0xd3, 0xf8, 0x9a, 0x9a, 0xc6, 0xc7, 0x6f, 0x66, 0xe1, 0x75, 0x65, + 0x2c, 0xdc, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x42, 0xba, 0xdb, 0x12, 0x1a, 0x07, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/generated.proto index 289ef5f3e..ccb947540 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,11 +21,9 @@ syntax = 'proto2'; package k8s.io.api.storage.v1alpha1; -import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/types_swagger_doc_generated.go index faca8e939..32d7dcc52 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1alpha1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_VolumeAttachment = map[string]string{ "": "VolumeAttachment captures the intent to attach or detach the specified volume to/from the specified node.\n\nVolumeAttachment objects are non-namespaced.", "metadata": "Standard object metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/zz_generated.deepcopy.go index 04221c67c..d1a53755b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/generated.pb.go index 425d0e717..fed8c7a63 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -188,6 +188,18 @@ func (m *StorageClass) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(len(*m.VolumeBindingMode))) i += copy(dAtA[i:], *m.VolumeBindingMode) } + if len(m.AllowedTopologies) > 0 { + for _, msg := range m.AllowedTopologies { + dAtA[i] = 0x42 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -524,6 +536,12 @@ func (m *StorageClass) Size() (n int) { l = len(*m.VolumeBindingMode) n += 1 + l + sovGenerated(uint64(l)) } + if len(m.AllowedTopologies) > 0 { + for _, e := range m.AllowedTopologies { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -657,6 +675,7 @@ func (this *StorageClass) String() string { `MountOptions:` + fmt.Sprintf("%v", this.MountOptions) + `,`, `AllowVolumeExpansion:` + valueToStringGenerated(this.AllowVolumeExpansion) + `,`, `VolumeBindingMode:` + valueToStringGenerated(this.VolumeBindingMode) + `,`, + `AllowedTopologies:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AllowedTopologies), "TopologySelectorTerm", "k8s_io_api_core_v1.TopologySelectorTerm", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -1073,6 +1092,37 @@ func (m *StorageClass) Unmarshal(dAtA []byte) error { s := VolumeBindingMode(dAtA[iNdEx:postIndex]) m.VolumeBindingMode = &s iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedTopologies", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedTopologies = append(m.AllowedTopologies, k8s_io_api_core_v1.TopologySelectorTerm{}) + if err := m.AllowedTopologies[len(m.AllowedTopologies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -2145,67 +2195,67 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 977 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6f, 0x1b, 0x45, - 0x14, 0xcf, 0xc6, 0xf9, 0x1c, 0x27, 0x34, 0x1d, 0x22, 0xb0, 0x7c, 0x58, 0x47, 0xbe, 0x60, 0xaa, - 0x66, 0xb7, 0x09, 0x05, 0x45, 0x48, 0x1c, 0xb2, 0x25, 0x07, 0x50, 0xdc, 0x86, 0x29, 0xaa, 0x50, - 0xc5, 0x81, 0xc9, 0xee, 0xab, 0x33, 0xd8, 0xfb, 0xa1, 0x99, 0x59, 0xd3, 0xdc, 0x38, 0x71, 0xe6, - 0xc4, 0x95, 0x0b, 0xff, 0x07, 0x47, 0x72, 0x42, 0x3d, 0xf6, 0x64, 0x91, 0xe5, 0xbf, 0x88, 0x38, - 0xa0, 0x99, 0x9d, 0x78, 0xd7, 0x5e, 0x5b, 0x4d, 0x7a, 0xe8, 0x2d, 0xf3, 0xde, 0xfb, 0xfd, 0xde, - 0xd7, 0xef, 0xad, 0x83, 0x1e, 0xf5, 0x0f, 0x84, 0xc3, 0x62, 0xb7, 0x9f, 0x9e, 0x02, 0x8f, 0x40, - 0x82, 0x70, 0x87, 0x10, 0x05, 0x31, 0x77, 0x8d, 0x83, 0x26, 0xcc, 0x15, 0x32, 0xe6, 0xb4, 0x07, - 0xee, 0x70, 0xef, 0x14, 0x24, 0xdd, 0x73, 0x7b, 0x10, 0x01, 0xa7, 0x12, 0x02, 0x27, 0xe1, 0xb1, - 0x8c, 0x71, 0x33, 0x8f, 0x75, 0x68, 0xc2, 0x1c, 0x13, 0xeb, 0x98, 0xd8, 0xe6, 0x6e, 0x8f, 0xc9, - 0xb3, 0xf4, 0xd4, 0xf1, 0xe3, 0xd0, 0xed, 0xc5, 0xbd, 0xd8, 0xd5, 0x90, 0xd3, 0xf4, 0x85, 0x7e, - 0xe9, 0x87, 0xfe, 0x2b, 0xa7, 0x6a, 0xb6, 0x4b, 0x69, 0xfd, 0x98, 0xab, 0x9c, 0xd3, 0xe9, 0x9a, - 0xdd, 0x22, 0x06, 0x5e, 0x4a, 0x88, 0x04, 0x8b, 0x23, 0xb1, 0x4b, 0x13, 0x26, 0x80, 0x0f, 0x81, - 0xbb, 0x49, 0xbf, 0xa7, 0x7c, 0x62, 0x32, 0x60, 0x5e, 0xf5, 0xcd, 0x87, 0x05, 0x5d, 0x48, 0xfd, - 0x33, 0x16, 0x01, 0x3f, 0x2f, 0x38, 0x42, 0x90, 0x74, 0x56, 0x11, 0xee, 0x3c, 0x14, 0x4f, 0x23, - 0xc9, 0x42, 0xa8, 0x00, 0x3e, 0x7b, 0x13, 0x40, 0xf8, 0x67, 0x10, 0xd2, 0x0a, 0xee, 0x93, 0x79, - 0xb8, 0x54, 0xb2, 0x81, 0xcb, 0x22, 0x29, 0x24, 0x9f, 0x06, 0xb5, 0x7f, 0x5f, 0x46, 0x1b, 0x4f, - 0xf3, 0x4d, 0x3c, 0x1a, 0x50, 0x21, 0xf0, 0x0f, 0x68, 0x4d, 0x75, 0x12, 0x50, 0x49, 0x1b, 0xd6, - 0x8e, 0xd5, 0xa9, 0xef, 0x3f, 0x70, 0x8a, 0xad, 0x8d, 0x89, 0x9d, 0xa4, 0xdf, 0x53, 0x06, 0xe1, - 0xa8, 0x68, 0x67, 0xb8, 0xe7, 0x3c, 0x39, 0xfd, 0x11, 0x7c, 0xd9, 0x05, 0x49, 0x3d, 0x7c, 0x31, - 0x6a, 0x2d, 0x64, 0xa3, 0x16, 0x2a, 0x6c, 0x64, 0xcc, 0x8a, 0x3f, 0x45, 0xf5, 0x84, 0xc7, 0x43, - 0xa6, 0x86, 0x0d, 0xbc, 0xb1, 0xb8, 0x63, 0x75, 0xd6, 0xbd, 0xf7, 0x0d, 0xa4, 0x7e, 0x52, 0xb8, - 0x48, 0x39, 0x0e, 0x0f, 0x10, 0x4a, 0x28, 0xa7, 0x21, 0x48, 0xe0, 0xa2, 0x51, 0xdb, 0xa9, 0x75, - 0xea, 0xfb, 0x07, 0xce, 0x7c, 0x41, 0x39, 0xe5, 0xb6, 0x9c, 0x93, 0x31, 0xf4, 0x28, 0x92, 0xfc, - 0xbc, 0x28, 0xb1, 0x70, 0x90, 0x12, 0x3f, 0xee, 0xa3, 0x4d, 0x0e, 0xfe, 0x80, 0xb2, 0xf0, 0x24, - 0x1e, 0x30, 0xff, 0xbc, 0xb1, 0xa4, 0xcb, 0x3c, 0xca, 0x46, 0xad, 0x4d, 0x52, 0x76, 0x5c, 0x8d, - 0x5a, 0x0f, 0xaa, 0x52, 0x74, 0x4e, 0x80, 0x0b, 0x26, 0x24, 0x44, 0xf2, 0x59, 0x3c, 0x48, 0x43, - 0x98, 0xc0, 0x90, 0x49, 0x6e, 0xfc, 0x10, 0x6d, 0x84, 0x71, 0x1a, 0xc9, 0x27, 0x89, 0x54, 0x02, - 0x6c, 0x2c, 0xef, 0xd4, 0x3a, 0xeb, 0xde, 0x56, 0x36, 0x6a, 0x6d, 0x74, 0x4b, 0x76, 0x32, 0x11, - 0x85, 0x8f, 0xd1, 0x36, 0x1d, 0x0c, 0xe2, 0x9f, 0xf2, 0x04, 0x47, 0x2f, 0x13, 0xaa, 0xf5, 0xdb, - 0x58, 0xd9, 0xb1, 0x3a, 0x6b, 0x5e, 0x23, 0x1b, 0xb5, 0xb6, 0x0f, 0x67, 0xf8, 0xc9, 0x4c, 0x14, - 0xfe, 0x0e, 0xdd, 0x1d, 0x6a, 0x93, 0xc7, 0xa2, 0x80, 0x45, 0xbd, 0x6e, 0x1c, 0x40, 0x63, 0x55, - 0x37, 0x7d, 0x2f, 0x1b, 0xb5, 0xee, 0x3e, 0x9b, 0x76, 0x5e, 0xcd, 0x32, 0x92, 0x2a, 0x49, 0xf3, - 0x0b, 0x74, 0x67, 0x6a, 0xfa, 0x78, 0x0b, 0xd5, 0xfa, 0x70, 0xae, 0xf5, 0xb5, 0x4e, 0xd4, 0x9f, - 0x78, 0x1b, 0x2d, 0x0f, 0xe9, 0x20, 0x85, 0x5c, 0x0e, 0x24, 0x7f, 0x7c, 0xbe, 0x78, 0x60, 0xb5, - 0xff, 0xb4, 0xd0, 0x56, 0x79, 0x95, 0xc7, 0x4c, 0x48, 0xfc, 0x7d, 0x45, 0xa5, 0xce, 0xcd, 0x54, - 0xaa, 0xd0, 0x5a, 0xa3, 0x5b, 0x46, 0x00, 0x6b, 0xd7, 0x96, 0x92, 0x42, 0xbb, 0x68, 0x99, 0x49, - 0x08, 0x45, 0x63, 0x51, 0xab, 0xac, 0x73, 0x53, 0x95, 0x79, 0x9b, 0x86, 0x74, 0xf9, 0x2b, 0x05, - 0x27, 0x39, 0x4b, 0xfb, 0x8f, 0x45, 0xb4, 0x95, 0x4f, 0xea, 0x50, 0x4a, 0xea, 0x9f, 0x85, 0x10, - 0xc9, 0x77, 0x70, 0x67, 0x04, 0x2d, 0x89, 0x04, 0x7c, 0x3d, 0xd1, 0x49, 0xf6, 0x4a, 0x13, 0xd3, - 0xd5, 0x3d, 0x4d, 0xc0, 0xf7, 0x36, 0x0c, 0xfb, 0x92, 0x7a, 0x11, 0xcd, 0x85, 0x9f, 0xa3, 0x15, - 0x21, 0xa9, 0x4c, 0xd5, 0x01, 0x2a, 0xd6, 0xfd, 0x5b, 0xb1, 0x6a, 0xa4, 0xf7, 0x9e, 0xe1, 0x5d, - 0xc9, 0xdf, 0xc4, 0x30, 0xb6, 0xff, 0xb2, 0xd0, 0xf6, 0x34, 0xe4, 0x1d, 0x2c, 0xfb, 0x9b, 0xc9, - 0x65, 0xdf, 0xbf, 0x4d, 0x47, 0x73, 0x16, 0xfe, 0x02, 0x7d, 0x50, 0xe9, 0x3d, 0x4e, 0xb9, 0x0f, - 0xea, 0x66, 0x93, 0xa9, 0x2f, 0xc3, 0x63, 0x1a, 0x42, 0x7e, 0x09, 0xf9, 0xcd, 0x9e, 0xcc, 0xf0, - 0x93, 0x99, 0xa8, 0xf6, 0xdf, 0x33, 0x26, 0xa6, 0x96, 0x85, 0xef, 0xa3, 0x35, 0xaa, 0x2d, 0xc0, - 0x0d, 0xf5, 0x78, 0x02, 0x87, 0xc6, 0x4e, 0xc6, 0x11, 0x7a, 0xa9, 0xba, 0x3c, 0x23, 0x95, 0xdb, - 0x2d, 0x55, 0x23, 0x4b, 0x4b, 0xd5, 0x6f, 0x62, 0x18, 0x55, 0x25, 0x51, 0x1c, 0xe4, 0x4d, 0xd6, - 0x26, 0x2b, 0x79, 0x6c, 0xec, 0x64, 0x1c, 0xd1, 0xfe, 0xaf, 0x36, 0x63, 0x72, 0x5a, 0x1d, 0xa5, - 0x96, 0x02, 0xdd, 0xd2, 0x5a, 0xa5, 0xa5, 0x60, 0xdc, 0x52, 0x80, 0x7f, 0xb3, 0x10, 0xa6, 0x63, - 0x8a, 0xee, 0xb5, 0x7a, 0xf2, 0x15, 0x7f, 0x7d, 0x7b, 0xd1, 0x3a, 0x87, 0x15, 0xb2, 0xfc, 0x77, - 0xa4, 0x69, 0x8a, 0xc0, 0xd5, 0x00, 0x32, 0xa3, 0x02, 0xcc, 0x50, 0x3d, 0xb7, 0x1e, 0x71, 0x1e, - 0x73, 0x73, 0x45, 0x1f, 0xbd, 0xb9, 0x20, 0x1d, 0xee, 0xd9, 0xea, 0x17, 0xf2, 0xb0, 0xc0, 0x5f, - 0x8d, 0x5a, 0xf5, 0x92, 0x9f, 0x94, 0xb9, 0x55, 0xaa, 0x00, 0x8a, 0x54, 0x4b, 0x6f, 0x91, 0xea, - 0x4b, 0x98, 0x9f, 0xaa, 0xc4, 0xdd, 0x3c, 0x42, 0x1f, 0xce, 0x19, 0xd0, 0xad, 0x3e, 0xf5, 0xbf, - 0x58, 0xa8, 0x9c, 0x03, 0x1f, 0xa3, 0x25, 0xf5, 0x0f, 0x8f, 0x39, 0xfa, 0x7b, 0x37, 0x3b, 0xfa, - 0x6f, 0x59, 0x08, 0xc5, 0xb7, 0x4b, 0xbd, 0x88, 0x66, 0xc1, 0x1f, 0xa3, 0xd5, 0x10, 0x84, 0xa0, - 0x3d, 0x93, 0xd9, 0xbb, 0x63, 0x82, 0x56, 0xbb, 0xb9, 0x99, 0x5c, 0xfb, 0xbd, 0xdd, 0x8b, 0x4b, - 0x7b, 0xe1, 0xd5, 0xa5, 0xbd, 0xf0, 0xfa, 0xd2, 0x5e, 0xf8, 0x39, 0xb3, 0xad, 0x8b, 0xcc, 0xb6, - 0x5e, 0x65, 0xb6, 0xf5, 0x3a, 0xb3, 0xad, 0x7f, 0x32, 0xdb, 0xfa, 0xf5, 0x5f, 0x7b, 0xe1, 0xf9, - 0xaa, 0x99, 0xdb, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x4b, 0x7f, 0x8a, 0x3b, 0x1c, 0x0b, 0x00, - 0x00, + // 988 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4d, 0x6f, 0x1b, 0x45, + 0x18, 0xce, 0xc6, 0xf9, 0x70, 0xc6, 0x09, 0x4d, 0x86, 0x08, 0x8c, 0x0f, 0x76, 0xe4, 0x0b, 0xa6, + 0x6a, 0x77, 0x9b, 0xa8, 0xa0, 0x08, 0x89, 0x83, 0xb7, 0xe4, 0x00, 0x8a, 0xdb, 0x30, 0x89, 0x2a, + 0x54, 0x71, 0x60, 0xb2, 0xfb, 0x76, 0xb3, 0x78, 0x77, 0x67, 0x99, 0x19, 0x1b, 0x72, 0xe3, 0xc4, + 0x19, 0x71, 0xe0, 0x17, 0xf0, 0x3f, 0x38, 0x92, 0x13, 0xea, 0xb1, 0x27, 0x8b, 0x2c, 0xff, 0x22, + 0xe2, 0x80, 0x66, 0x76, 0x62, 0xaf, 0xbd, 0x0e, 0x6d, 0x7a, 0xe8, 0xcd, 0xef, 0xc7, 0xf3, 0xbc, + 0xdf, 0xb3, 0x46, 0x8f, 0xfa, 0xfb, 0xc2, 0x0e, 0x99, 0xd3, 0x1f, 0x9c, 0x02, 0x4f, 0x40, 0x82, + 0x70, 0x86, 0x90, 0xf8, 0x8c, 0x3b, 0xc6, 0x40, 0xd3, 0xd0, 0x11, 0x92, 0x71, 0x1a, 0x80, 0x33, + 0xdc, 0x3d, 0x05, 0x49, 0x77, 0x9d, 0x00, 0x12, 0xe0, 0x54, 0x82, 0x6f, 0xa7, 0x9c, 0x49, 0x86, + 0x1b, 0xb9, 0xaf, 0x4d, 0xd3, 0xd0, 0x36, 0xbe, 0xb6, 0xf1, 0x6d, 0xdc, 0x0f, 0x42, 0x79, 0x36, + 0x38, 0xb5, 0x3d, 0x16, 0x3b, 0x01, 0x0b, 0x98, 0xa3, 0x21, 0xa7, 0x83, 0xe7, 0x5a, 0xd2, 0x82, + 0xfe, 0x95, 0x53, 0x35, 0xda, 0x85, 0xb0, 0x1e, 0xe3, 0x2a, 0xe6, 0x6c, 0xb8, 0xc6, 0xc3, 0x89, + 0x4f, 0x4c, 0xbd, 0xb3, 0x30, 0x01, 0x7e, 0xee, 0xa4, 0xfd, 0x40, 0x29, 0x84, 0x13, 0x83, 0xa4, + 0xf3, 0x50, 0xce, 0x4d, 0x28, 0x3e, 0x48, 0x64, 0x18, 0x43, 0x09, 0xf0, 0xc9, 0xab, 0x00, 0xc2, + 0x3b, 0x83, 0x98, 0xce, 0xe2, 0xda, 0xbf, 0xae, 0xa0, 0xf5, 0xe3, 0xbc, 0x0b, 0x8f, 0x22, 0x2a, + 0x04, 0xfe, 0x16, 0x55, 0x55, 0x52, 0x3e, 0x95, 0xb4, 0x6e, 0xed, 0x58, 0x9d, 0xda, 0xde, 0x03, + 0x7b, 0xd2, 0xb1, 0x31, 0xb7, 0x9d, 0xf6, 0x03, 0xa5, 0x10, 0xb6, 0xf2, 0xb6, 0x87, 0xbb, 0xf6, + 0x93, 0xd3, 0xef, 0xc0, 0x93, 0x3d, 0x90, 0xd4, 0xc5, 0x17, 0xa3, 0xd6, 0x42, 0x36, 0x6a, 0xa1, + 0x89, 0x8e, 0x8c, 0x59, 0xf1, 0xc7, 0xa8, 0x96, 0x72, 0x36, 0x0c, 0x45, 0xc8, 0x12, 0xe0, 0xf5, + 0xc5, 0x1d, 0xab, 0xb3, 0xe6, 0xbe, 0x6b, 0x20, 0xb5, 0xa3, 0x89, 0x89, 0x14, 0xfd, 0x70, 0x84, + 0x50, 0x4a, 0x39, 0x8d, 0x41, 0x02, 0x17, 0xf5, 0xca, 0x4e, 0xa5, 0x53, 0xdb, 0xdb, 0xb7, 0x6f, + 0x1e, 0xa6, 0x5d, 0x2c, 0xcb, 0x3e, 0x1a, 0x43, 0x0f, 0x12, 0xc9, 0xcf, 0x27, 0x29, 0x4e, 0x0c, + 0xa4, 0xc0, 0x8f, 0xfb, 0x68, 0x83, 0x83, 0x17, 0xd1, 0x30, 0x3e, 0x62, 0x51, 0xe8, 0x9d, 0xd7, + 0x97, 0x74, 0x9a, 0x07, 0xd9, 0xa8, 0xb5, 0x41, 0x8a, 0x86, 0xab, 0x51, 0xeb, 0x41, 0x79, 0x0d, + 0xec, 0x23, 0xe0, 0x22, 0x14, 0x12, 0x12, 0xf9, 0x94, 0x45, 0x83, 0x18, 0xa6, 0x30, 0x64, 0x9a, + 0x1b, 0x3f, 0x44, 0xeb, 0x31, 0x1b, 0x24, 0xf2, 0x49, 0x2a, 0x43, 0x96, 0x88, 0xfa, 0xf2, 0x4e, + 0xa5, 0xb3, 0xe6, 0x6e, 0x66, 0xa3, 0xd6, 0x7a, 0xaf, 0xa0, 0x27, 0x53, 0x5e, 0xf8, 0x10, 0x6d, + 0xd3, 0x28, 0x62, 0x3f, 0xe4, 0x01, 0x0e, 0x7e, 0x4c, 0x69, 0xa2, 0x5a, 0x55, 0x5f, 0xd9, 0xb1, + 0x3a, 0x55, 0xb7, 0x9e, 0x8d, 0x5a, 0xdb, 0xdd, 0x39, 0x76, 0x32, 0x17, 0x85, 0xbf, 0x46, 0x5b, + 0x43, 0xad, 0x72, 0xc3, 0xc4, 0x0f, 0x93, 0xa0, 0xc7, 0x7c, 0xa8, 0xaf, 0xea, 0xa2, 0xef, 0x66, + 0xa3, 0xd6, 0xd6, 0xd3, 0x59, 0xe3, 0xd5, 0x3c, 0x25, 0x29, 0x93, 0xe0, 0xef, 0xd1, 0x96, 0x8e, + 0x08, 0xfe, 0x09, 0x4b, 0x59, 0xc4, 0x82, 0x10, 0x44, 0xbd, 0xaa, 0xe7, 0xd7, 0x29, 0xce, 0x4f, + 0xb5, 0x4e, 0x2d, 0x92, 0xf1, 0x3a, 0x3f, 0x86, 0x08, 0x3c, 0xc9, 0xf8, 0x09, 0xf0, 0xd8, 0xfd, + 0xc0, 0xcc, 0x6b, 0xab, 0x3b, 0x4b, 0x45, 0xca, 0xec, 0x8d, 0xcf, 0xd0, 0x9d, 0x99, 0x81, 0xe3, + 0x4d, 0x54, 0xe9, 0xc3, 0xb9, 0x5e, 0xe9, 0x35, 0xa2, 0x7e, 0xe2, 0x6d, 0xb4, 0x3c, 0xa4, 0xd1, + 0x00, 0xf2, 0x0d, 0x24, 0xb9, 0xf0, 0xe9, 0xe2, 0xbe, 0xd5, 0xfe, 0xc3, 0x42, 0x9b, 0xc5, 0xed, + 0x39, 0x0c, 0x85, 0xc4, 0xdf, 0x94, 0x0e, 0xc3, 0x7e, 0xbd, 0xc3, 0x50, 0x68, 0x7d, 0x16, 0x9b, + 0xa6, 0x86, 0xea, 0xb5, 0xa6, 0x70, 0x14, 0x3d, 0xb4, 0x1c, 0x4a, 0x88, 0x45, 0x7d, 0xb1, 0xdc, + 0x98, 0xff, 0x5b, 0x6c, 0x77, 0xc3, 0x90, 0x2e, 0x7f, 0xa1, 0xe0, 0x24, 0x67, 0x69, 0xff, 0xbe, + 0x88, 0x36, 0xf3, 0xe1, 0x74, 0xa5, 0xa4, 0xde, 0x59, 0x0c, 0x89, 0x7c, 0x0b, 0xa7, 0x4d, 0xd0, + 0x92, 0x48, 0xc1, 0xd3, 0x1d, 0x9d, 0x66, 0x2f, 0x15, 0x31, 0x9b, 0xdd, 0x71, 0x0a, 0x9e, 0xbb, + 0x6e, 0xd8, 0x97, 0x94, 0x44, 0x34, 0x17, 0x7e, 0x86, 0x56, 0x84, 0xa4, 0x72, 0xa0, 0x6e, 0x5e, + 0xb1, 0xee, 0xdd, 0x8a, 0x55, 0x23, 0xdd, 0x77, 0x0c, 0xef, 0x4a, 0x2e, 0x13, 0xc3, 0xd8, 0xfe, + 0xd3, 0x42, 0xdb, 0xb3, 0x90, 0xb7, 0x30, 0xec, 0xaf, 0xa6, 0x87, 0x7d, 0xef, 0x36, 0x15, 0xdd, + 0x30, 0xf0, 0xe7, 0xe8, 0xbd, 0x52, 0xed, 0x6c, 0xc0, 0x3d, 0x50, 0xcf, 0x44, 0x3a, 0xf3, 0x18, + 0x3d, 0xa6, 0x31, 0xe4, 0x97, 0x90, 0x3f, 0x13, 0x47, 0x73, 0xec, 0x64, 0x2e, 0xaa, 0xfd, 0xd7, + 0x9c, 0x8e, 0xa9, 0x61, 0xe1, 0x7b, 0xa8, 0x4a, 0xb5, 0x06, 0xb8, 0xa1, 0x1e, 0x77, 0xa0, 0x6b, + 0xf4, 0x64, 0xec, 0xa1, 0x87, 0xaa, 0xd3, 0x33, 0xab, 0x72, 0xbb, 0xa1, 0x6a, 0x64, 0x61, 0xa8, + 0x5a, 0x26, 0x86, 0x51, 0x65, 0x92, 0x30, 0x3f, 0x2f, 0xb2, 0x32, 0x9d, 0xc9, 0x63, 0xa3, 0x27, + 0x63, 0x8f, 0xf6, 0xbf, 0x95, 0x39, 0x9d, 0xd3, 0xdb, 0x51, 0x28, 0xc9, 0xd7, 0x25, 0x55, 0x4b, + 0x25, 0xf9, 0xe3, 0x92, 0x7c, 0xfc, 0x9b, 0x85, 0x30, 0x1d, 0x53, 0xf4, 0xae, 0xb7, 0x27, 0x1f, + 0xf1, 0x97, 0xb7, 0x5f, 0x5a, 0xbb, 0x5b, 0x22, 0xcb, 0x3f, 0x5d, 0x0d, 0x93, 0x04, 0x2e, 0x3b, + 0x90, 0x39, 0x19, 0xe0, 0x10, 0xd5, 0x72, 0xed, 0x01, 0xe7, 0x8c, 0x9b, 0x2b, 0xfa, 0xf0, 0xd5, + 0x09, 0x69, 0x77, 0xb7, 0xa9, 0x3e, 0xca, 0xdd, 0x09, 0xfe, 0x6a, 0xd4, 0xaa, 0x15, 0xec, 0xa4, + 0xc8, 0xad, 0x42, 0xf9, 0x30, 0x09, 0xb5, 0xf4, 0x06, 0xa1, 0x3e, 0x87, 0x9b, 0x43, 0x15, 0xb8, + 0x1b, 0x07, 0xe8, 0xfd, 0x1b, 0x1a, 0x74, 0xab, 0xa7, 0xfe, 0x67, 0x0b, 0x15, 0x63, 0xe0, 0x43, + 0xb4, 0xa4, 0xfe, 0x2e, 0x99, 0xa3, 0xbf, 0xfb, 0x7a, 0x47, 0x7f, 0x12, 0xc6, 0x30, 0x79, 0xbb, + 0x94, 0x44, 0x34, 0x0b, 0xfe, 0x08, 0xad, 0xc6, 0x20, 0x04, 0x0d, 0x4c, 0x64, 0xf7, 0x8e, 0x71, + 0x5a, 0xed, 0xe5, 0x6a, 0x72, 0x6d, 0x77, 0xef, 0x5f, 0x5c, 0x36, 0x17, 0x5e, 0x5c, 0x36, 0x17, + 0x5e, 0x5e, 0x36, 0x17, 0x7e, 0xca, 0x9a, 0xd6, 0x45, 0xd6, 0xb4, 0x5e, 0x64, 0x4d, 0xeb, 0x65, + 0xd6, 0xb4, 0xfe, 0xce, 0x9a, 0xd6, 0x2f, 0xff, 0x34, 0x17, 0x9e, 0xad, 0x9a, 0xbe, 0xfd, 0x17, + 0x00, 0x00, 0xff, 0xff, 0xb4, 0x63, 0x7e, 0xa7, 0x0b, 0x0b, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/generated.proto index 1c6db8d41..359b68634 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -22,11 +22,9 @@ syntax = 'proto2'; package k8s.io.api.storage.v1beta1; import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; @@ -71,6 +69,14 @@ message StorageClass { // the VolumeScheduling feature. // +optional optional string volumeBindingMode = 7; + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + repeated k8s.io.api.core.v1.TopologySelectorTerm allowedTopologies = 8; } // StorageClassList is a collection of storage classes. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/types.go index 99c9e4594..7ec1e908f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/types.go @@ -66,6 +66,14 @@ type StorageClass struct { // the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode `json:"volumeBindingMode,omitempty" protobuf:"bytes,7,opt,name=volumeBindingMode"` + + // Restrict the node topologies where volumes can be dynamically provisioned. + // Each volume plugin defines its own supported topology specifications. + // An empty TopologySelectorTerm list means there is no topology restriction. + // This field is alpha-level and is only honored by servers that enable + // the DynamicProvisioningScheduling feature. + // +optional + AllowedTopologies []v1.TopologySelectorTerm `json:"allowedTopologies,omitempty" protobuf:"bytes,8,rep,name=allowedTopologies"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go index c9c20c453..423e7f271 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_StorageClass = map[string]string{ "": "StorageClass describes the parameters for a class of storage for which PersistentVolumes can be dynamically provisioned.\n\nStorageClasses are non-namespaced; the name of the storage class according to etcd is in ObjectMeta.Name.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -36,6 +36,7 @@ var map_StorageClass = map[string]string{ "mountOptions": "Dynamically provisioned PersistentVolumes of this storage class are created with these mountOptions, e.g. [\"ro\", \"soft\"]. Not validated - mount of the PVs will simply fail if one is invalid.", "allowVolumeExpansion": "AllowVolumeExpansion shows whether the storage class allow volume expand", "volumeBindingMode": "VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound. When unset, VolumeBindingImmediate is used. This field is alpha-level and is only honored by servers that enable the VolumeScheduling feature.", + "allowedTopologies": "Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is alpha-level and is only honored by servers that enable the DynamicProvisioningScheduling feature.", } func (StorageClass) SwaggerDoc() map[string]string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go index 9a6a7266d..7c7c8fde5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/api/storage/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -69,6 +69,13 @@ func (in *StorageClass) DeepCopyInto(out *StorageClass) { **out = **in } } + if in.AllowedTopologies != nil { + in, out := &in.AllowedTopologies, &out.AllowedTopologies + *out = make([]v1.TopologySelectorTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/BUILD index 8092fcb82..31d0de0ae 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/BUILD @@ -44,6 +44,7 @@ filegroup( "//staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server:all-srcs", + "//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/finalizer:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/features:all-srcs", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json index b917bb241..0dc76fa09 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "k8s.io/apiextensions-apiserver", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], @@ -372,7 +372,7 @@ }, { "ImportPath": "github.com/evanphx/json-patch", - "Rev": "944e07253867aacae43c04b2e6a239005443f33a" + "Rev": "94e38aa1586e8a6c8a75770bddf5ff84c48a106b" }, { "ImportPath": "github.com/ghodss/yaml", @@ -436,35 +436,35 @@ }, { "ImportPath": "github.com/golang/protobuf/jsonpb", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/struct", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -486,6 +486,14 @@ "ImportPath": "github.com/googleapis/gnostic/extensions", "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, { "ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus", "Rev": "2500245aa6110c562d17020fb31a2c133d737799" @@ -510,10 +518,6 @@ "ImportPath": "github.com/hashicorp/golang-lru/simplelru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" }, - { - "ImportPath": "github.com/howeyc/gopass", - "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" - }, { "ImportPath": "github.com/imdario/mergo", "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" @@ -528,7 +532,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/mailru/easyjson/buffer", @@ -546,10 +550,22 @@ "ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil", "Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a" }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, { "ImportPath": "github.com/pborman/uuid", "Rev": "ca53cad383cad2479bbba7f7a1a05797ec1386e4" }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" + }, { "ImportPath": "github.com/pmezard/go-difflib/difflib", "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d" @@ -584,7 +600,7 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Rev": "6644d46b81fa1831979c4cded0106e774e0ef0ab" + "Rev": "c439c4fa093711d42e1b01acb1235b52004753c1" }, { "ImportPath": "github.com/spf13/pflag", @@ -592,11 +608,11 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/stretchr/testify/require", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/ugorji/go/codec", @@ -608,15 +624,15 @@ }, { "ImportPath": "golang.org/x/crypto/bcrypt", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/blowfish", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/net/context", @@ -898,6 +914,10 @@ "ImportPath": "k8s.io/api/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -946,18 +966,6 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/validation/path", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1174,6 +1182,10 @@ "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/generic", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1194,10 +1206,6 @@ "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/validating", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/versioned", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apiserver/pkg/apis/apiserver", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1458,6 +1466,10 @@ "ImportPath": "k8s.io/apiserver/pkg/util/flushwriter", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apiserver/pkg/util/openapi", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apiserver/pkg/util/trace", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1638,6 +1650,10 @@ "ImportPath": "k8s.io/client-go/informers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/settings", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1766,6 +1782,10 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1862,6 +1882,10 @@ "ImportPath": "k8s.io/client-go/listers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1886,6 +1910,10 @@ "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/pkg/version", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1986,6 +2014,10 @@ "ImportPath": "k8s.io/client-go/util/cert", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/connrotation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -2004,23 +2036,23 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/equality", @@ -2055,11 +2087,7 @@ "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered", + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, { @@ -2234,10 +2262,6 @@ "ImportPath": "k8s.io/apiserver/pkg/util/feature", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apiserver/pkg/util/feature/testing", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apiserver/pkg/util/logs", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -2254,10 +2278,18 @@ "ImportPath": "k8s.io/client-go/dynamic", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/scheme", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/rest", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/restmapper", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/scale", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/OWNERS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/OWNERS index e0cd3186f..d9cb557fc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/OWNERS +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/OWNERS @@ -2,6 +2,7 @@ reviewers: - deads2k - sttts - enisoc +- mbohlool approvers: - deads2k - lavalamp diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/artifacts/example/rc.yaml b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/artifacts/example/rc.yaml index 629abf870..86b5d3070 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/artifacts/example/rc.yaml +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/artifacts/example/rc.yaml @@ -23,4 +23,4 @@ spec: - "--etcd-servers=http://localhost:2379" - "--audit-log-path=-" - name: etcd - image: quay.io/coreos/etcd:v3.1.12 + image: quay.io/coreos/etcd:v3.2.18 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh index 3659ad330..ea26ad63c 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/verify-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/verify-codegen.sh index 9cc02a5a4..d02a6fa39 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/verify-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1/zz_generated.deepcopy.go index a0399a5ca..50828809d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/BUILD index 0698e1f9a..86620f31f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/BUILD @@ -9,7 +9,6 @@ go_library( importpath = "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/clientset.go index 45745dd27..92ff15819 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,10 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package versioned import ( - glog "github.com/golang/glog" crv1 "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" @@ -72,7 +73,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/doc.go index 7d2f4d80d..41721ca52 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // This package has the automatically generated clientset. package versioned diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/clientset_generated.go index 2a03c770e..28089890d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package fake import ( @@ -39,11 +41,20 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil)) + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/doc.go index 3fd8e1e2c..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // This package has the automatically generated fake clientset. package fake diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/register.go index 4e6435d2a..fdcedd4c5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package fake import ( @@ -49,5 +51,4 @@ func init() { // correctly. func AddToScheme(scheme *runtime.Scheme) { crv1.AddToScheme(scheme) - } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/doc.go index 3ec2200d0..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // This package contains the scheme of the automatically generated clientset. package scheme diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/register.go index 311152e38..74d8fa4d0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package scheme import ( @@ -49,5 +51,4 @@ func init() { // correctly. func AddToScheme(scheme *runtime.Scheme) { crv1.AddToScheme(scheme) - } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/cr_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/cr_client.go index 8c662905c..04e3930e1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/cr_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/cr_client.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package v1 import ( @@ -28,7 +30,7 @@ type CrV1Interface interface { ExamplesGetter } -// CrV1Client is used to interact with features provided by the cr.client-go.k8s.io group. +// CrV1Client is used to interact with features provided by the cr.example.apiextensions.k8s.io group. type CrV1Client struct { restClient rest.Interface } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/doc.go index b6a2a4672..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // This package has the automatically generated typed clients. package v1 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/example.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/example.go index 66e0e1cff..a0cc33852 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/example.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/example.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package v1 import ( diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/doc.go index c58fac35e..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,5 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + // Package fake has the automatically generated clients. package fake diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_cr_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_cr_client.go index b3f6247c4..5ce902313 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_cr_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_cr_client.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package fake import ( diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_example.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_example.go index 7a8dd94b9..2db7f5c1e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_example.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/fake/fake_example.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package fake import ( @@ -32,9 +34,9 @@ type FakeExamples struct { ns string } -var examplesResource = schema.GroupVersionResource{Group: "cr.client-go.k8s.io", Version: "v1", Resource: "examples"} +var examplesResource = schema.GroupVersionResource{Group: "cr.example.apiextensions.k8s.io", Version: "v1", Resource: "examples"} -var examplesKind = schema.GroupVersionKind{Group: "cr.client-go.k8s.io", Version: "v1", Kind: "Example"} +var examplesKind = schema.GroupVersionKind{Group: "cr.example.apiextensions.k8s.io", Version: "v1", Kind: "Example"} // Get takes name of the example, and returns the corresponding example object, and an error if there is any. func (c *FakeExamples) Get(name string, options v1.GetOptions) (result *cr_v1.Example, err error) { @@ -60,7 +62,7 @@ func (c *FakeExamples) List(opts v1.ListOptions) (result *cr_v1.ExampleList, err if label == nil { label = labels.Everything() } - list := &cr_v1.ExampleList{} + list := &cr_v1.ExampleList{ListMeta: obj.(*cr_v1.ExampleList).ListMeta} for _, item := range obj.(*cr_v1.ExampleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/generated_expansion.go index 70b162feb..755021ec4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned/typed/cr/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Code generated by client-gen. DO NOT EDIT. + package v1 type ExampleExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/BUILD index cd892cb07..4a89d1248 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/BUILD @@ -13,6 +13,7 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/client-go/tools/cache:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/interface.go index 9366da3be..0c633e3ef 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package cr @@ -30,15 +30,17 @@ type Interface interface { } type group struct { - internalinterfaces.SharedInformerFactory + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc } // New returns a new Interface. -func New(f internalinterfaces.SharedInformerFactory) Interface { - return &group{f} +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } // V1 returns a new v1.Interface. func (g *group) V1() v1.Interface { - return v1.New(g.SharedInformerFactory) + return v1.New(g.factory, g.namespace, g.tweakListOptions) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/example.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/example.go index 39918ff5a..50b563d39 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/example.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/example.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,11 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package v1 import ( + time "time" + cr_v1 "k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1" versioned "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned" internalinterfaces "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces" @@ -27,7 +29,6 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" - time "time" ) // ExampleInformer provides access to a shared informer and lister for @@ -38,19 +39,34 @@ type ExampleInformer interface { } type exampleInformer struct { - factory internalinterfaces.SharedInformerFactory + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string } // NewExampleInformer constructs a new informer for Example type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewExampleInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredExampleInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredExampleInformer constructs a new informer for Example type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredExampleInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } return client.CrV1().Examples(namespace).List(options) }, WatchFunc: func(options meta_v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } return client.CrV1().Examples(namespace).Watch(options) }, }, @@ -60,12 +76,12 @@ func NewExampleInformer(client versioned.Interface, namespace string, resyncPeri ) } -func defaultExampleInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewExampleInformer(client, meta_v1.NamespaceAll, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) +func (f *exampleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredExampleInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } func (f *exampleInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&cr_v1.Example{}, defaultExampleInformer) + return f.factory.InformerFor(&cr_v1.Example{}, f.defaultInformer) } func (f *exampleInformer) Lister() v1.ExampleLister { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/interface.go index 0612ce3bd..96ee1514c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package v1 @@ -29,15 +29,17 @@ type Interface interface { } type version struct { - internalinterfaces.SharedInformerFactory + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc } // New returns a new Interface. -func New(f internalinterfaces.SharedInformerFactory) Interface { - return &version{f} +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } // Examples returns a ExampleInformer. func (v *version) Examples() ExampleInformer { - return &exampleInformer{factory: v.SharedInformerFactory} + return &exampleInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go index f9ae8be12..67c55af39 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,26 +14,34 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package externalversions import ( + reflect "reflect" + sync "sync" + time "time" + versioned "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned" cr "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/cr" internalinterfaces "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" - reflect "reflect" - sync "sync" - time "time" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { - client versioned.Interface - lock sync.Mutex - defaultResync time.Duration + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -41,14 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -97,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer @@ -114,5 +176,5 @@ type SharedInformerFactory interface { } func (f *sharedInformerFactory) Cr() cr.Interface { - return cr.New(f) + return cr.New(f, f.namespace, f.tweakListOptions) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/generic.go index 12390b7a9..2bf6c5a47 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,12 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package externalversions import ( "fmt" + v1 "k8s.io/apiextensions-apiserver/examples/client-go/pkg/apis/cr/v1" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" @@ -51,7 +52,7 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=Cr, Version=V1 + // Group=cr.example.apiextensions.k8s.io, Version=v1 case v1.SchemeGroupVersion.WithResource("examples"): return &genericInformer{resource: resource.GroupResource(), informer: f.Cr().V1().Examples().Informer()}, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/BUILD index 20b878299..e57a5a05a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/BUILD @@ -7,6 +7,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//vendor/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index d8f00586b..5b81f037b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,15 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by informer-gen +// Code generated by informer-gen. DO NOT EDIT. package internalinterfaces import ( + time "time" + versioned "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/clientset/versioned" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" cache "k8s.io/client-go/tools/cache" - time "time" ) type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer @@ -32,3 +34,5 @@ type SharedInformerFactory interface { Start(stopCh <-chan struct{}) InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer } + +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/example.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/example.go index 554c9f2db..8a64d09cc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/example.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/example.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by lister-gen +// Code generated by lister-gen. DO NOT EDIT. package v1 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/expansion_generated.go index 7397d6f6c..5291ebaec 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/listers/cr/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was automatically generated by lister-gen +// Code generated by lister-gen. DO NOT EDIT. package v1 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/boilerplate.go.txt b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/boilerplate.go.txt index 59e740c1e..b7c650da4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/boilerplate.go.txt +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright YEAR The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/build-image.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/build-image.sh index c9152a4de..d0d129078 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/build-image.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/build-image.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/update-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/update-codegen.sh index 9c98ebf4d..a586b48e0 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/update-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh index f5835c425..ab43ba23d 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/main.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/main.go index 7723e6513..09143ab6e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/main.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/main.go @@ -19,7 +19,6 @@ package main import ( "flag" "os" - "runtime" "github.com/golang/glog" @@ -32,10 +31,6 @@ func main() { logs.InitLogs() defer logs.FlushLogs() - if len(os.Getenv("GOMAXPROCS")) == 0 { - runtime.GOMAXPROCS(runtime.NumCPU()) - } - stopCh := genericapiserver.SetupSignalHandler() cmd := server.NewCommandStartCustomResourceDefinitionsServer(os.Stdout, os.Stderr, stopCh) cmd.Flags().AddGoFlagSet(flag.CommandLine) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go index dd9680c36..37b4d1df9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go @@ -16,6 +16,8 @@ limitations under the License. package apiextensions +import "k8s.io/apimachinery/pkg/runtime" + // TODO: Update this after a tag is created for interface fields in DeepCopy func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { if in == nil { @@ -26,14 +28,14 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { *out = *in if in.Default != nil { - defaultJSON := JSON(deepCopyJSON(*(in.Default))) + defaultJSON := JSON(runtime.DeepCopyJSONValue(*(in.Default))) out.Default = &(defaultJSON) } else { out.Default = nil } if in.Example != nil { - exampleJSON := JSON(deepCopyJSON(*(in.Example))) + exampleJSON := JSON(runtime.DeepCopyJSONValue(*(in.Example))) out.Example = &(exampleJSON) } else { out.Example = nil @@ -121,7 +123,7 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { if in.Enum != nil { out.Enum = make([]JSON, len(in.Enum)) for i := range in.Enum { - out.Enum[i] = deepCopyJSON(in.Enum[i]) + out.Enum[i] = runtime.DeepCopyJSONValue(in.Enum[i]) } } @@ -258,22 +260,3 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { return out } - -func deepCopyJSON(x interface{}) interface{} { - switch x := x.(type) { - case map[string]interface{}: - clone := make(map[string]interface{}, len(x)) - for k, v := range x { - clone[k] = deepCopyJSON(v) - } - return clone - case []interface{}: - clone := make([]interface{}, len(x)) - for i := range x { - clone[i] = deepCopyJSON(x[i]) - } - return clone - default: - return x - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/BUILD index a6e5ed9df..983bb2bbc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/BUILD @@ -12,6 +12,7 @@ go_library( deps = [ "//vendor/github.com/google/gofuzz:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go index a7cfb0ae7..ff8cc0334 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go @@ -23,9 +23,12 @@ import ( "github.com/google/gofuzz" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" ) +var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() + // Funcs returns the fuzzer functions for the apiextensions apis. func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ @@ -42,6 +45,33 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 { obj.Names.ListKind = obj.Names.Kind + "List" } + if len(obj.Versions) == 0 && len(obj.Version) != 0 { + obj.Versions = []apiextensions.CustomResourceDefinitionVersion{ + { + Name: obj.Version, + Served: true, + Storage: true, + }, + } + } else if len(obj.Versions) != 0 { + obj.Version = obj.Versions[0].Name + } + if len(obj.AdditionalPrinterColumns) == 0 { + obj.AdditionalPrinterColumns = []apiextensions.CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"}, + } + } + }, + func(obj *apiextensions.CustomResourceDefinition, c fuzz.Continue) { + c.FuzzNoCustom(obj) + + if len(obj.Status.StoredVersions) == 0 { + for _, v := range obj.Spec.Versions { + if v.Storage && !apiextensions.IsStoredVersion(obj, v.Name) { + obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name) + } + } + } }, func(obj *apiextensions.JSONSchemaProps, c fuzz.Continue) { // we cannot use c.FuzzNoCustom because of the interface{} fields. So let's loop with reflection. @@ -81,6 +111,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { }, func(obj *apiextensions.JSONSchemaPropsOrBool, c fuzz.Continue) { if c.RandBool() { + obj.Allows = true obj.Schema = &apiextensions.JSONSchemaProps{} c.Fuzz(obj.Schema) } else { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go index 8dc7f72d6..92cad7d9b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go @@ -17,6 +17,7 @@ limitations under the License. package apiextensions import ( + "fmt" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -116,3 +117,33 @@ func CRDRemoveFinalizer(crd *CustomResourceDefinition, needle string) { } crd.Finalizers = newFinalizers } + +// HasServedCRDVersion returns true if `version` is in the list of CRD's versions and the Served flag is set. +func HasServedCRDVersion(crd *CustomResourceDefinition, version string) bool { + for _, v := range crd.Spec.Versions { + if v.Name == version { + return v.Served + } + } + return false +} + +// GetCRDStorageVersion returns the storage version for given CRD. +func GetCRDStorageVersion(crd *CustomResourceDefinition) (string, error) { + for _, v := range crd.Spec.Versions { + if v.Storage { + return v.Name, nil + } + } + // This should not happened if crd is valid + return "", fmt.Errorf("invalid CustomResourceDefinition, no storage version") +} + +func IsStoredVersion(crd *CustomResourceDefinition, version string) bool { + for _, v := range crd.Status.StoredVersions { + if version == v { + return true + } + } + return false +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go index 1abb49815..df58a7cbf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go @@ -19,6 +19,7 @@ package apiextensions import ( "reflect" "testing" + "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -88,3 +89,333 @@ func TestCRDRemoveFinalizer(t *testing.T) { } } } + +func TestSetCRDCondition(t *testing.T) { + tests := []struct { + name string + crdCondition []CustomResourceDefinitionCondition + newCondition CustomResourceDefinitionCondition + expectedcrdCondition []CustomResourceDefinitionCondition + }{ + { + name: "test setCRDcondition when one condition", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + newCondition: CustomResourceDefinitionCondition{ + Type: Established, + Status: ConditionFalse, + Reason: "NotAccepted", + Message: "Not accepted", + LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC), + }, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionFalse, + Reason: "NotAccepted", + Message: "Not accepted", + LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC), + }, + }, + }, + { + name: "test setCRDcondition when two condition", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + newCondition: CustomResourceDefinitionCondition{ + Type: NamesAccepted, + Status: ConditionFalse, + Reason: "Conflicts", + Message: "conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC), + }, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionFalse, + Reason: "Conflicts", + Message: "conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC), + }, + }, + }, + { + name: "test setCRDcondition when condition needs to be appended", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + newCondition: CustomResourceDefinitionCondition{ + Type: Terminating, + Status: ConditionFalse, + Reason: "NeverEstablished", + Message: "resource was never established", + LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC), + }, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: Terminating, + Status: ConditionFalse, + Reason: "NeverEstablished", + Message: "resource was never established", + LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC), + }, + }, + }, + } + for _, tc := range tests { + crd := generateCRDwithCondition(tc.crdCondition) + SetCRDCondition(crd, tc.newCondition) + if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) { + t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions) + } + for i := range tc.expectedcrdCondition { + if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) { + t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions) + } + } + } +} + +func TestRemoveCRDCondition(t *testing.T) { + tests := []struct { + name string + crdCondition []CustomResourceDefinitionCondition + conditionType CustomResourceDefinitionConditionType + expectedcrdCondition []CustomResourceDefinitionCondition + }{ + { + name: "test remove CRDCondition when the conditionType meets", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: NamesAccepted, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2011, 1, 2, 0, 0, 0, 0, time.UTC), + }, + }, + }, + { + name: "test remove CRDCondition when the conditionType not meets", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: Terminating, + expectedcrdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + }, + } + for _, tc := range tests { + crd := generateCRDwithCondition(tc.crdCondition) + RemoveCRDCondition(crd, tc.conditionType) + if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) { + t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions) + } + for i := range tc.expectedcrdCondition { + if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) { + t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions) + } + } + } +} + +func TestIsCRDConditionPresentAndEqual(t *testing.T) { + tests := []struct { + name string + crdCondition []CustomResourceDefinitionCondition + conditionType CustomResourceDefinitionConditionType + status ConditionStatus + expectresult bool + }{ + { + name: "test CRDCondition is not Present", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: Terminating, + status: ConditionTrue, + expectresult: false, + }, + { + name: "test CRDCondition is Present but not Equal", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: Established, + status: ConditionFalse, + expectresult: false, + }, + { + name: "test CRDCondition is Present and Equal", + crdCondition: []CustomResourceDefinitionCondition{ + { + Type: Established, + Status: ConditionTrue, + Reason: "Accepted", + Message: "the initial names have been accepted", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + { + Type: NamesAccepted, + Status: ConditionTrue, + Reason: "NoConflicts", + Message: "no conflicts found", + LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + conditionType: NamesAccepted, + status: ConditionTrue, + expectresult: true, + }, + } + for _, tc := range tests { + crd := generateCRDwithCondition(tc.crdCondition) + res := IsCRDConditionPresentAndEqual(crd, tc.conditionType, tc.status) + if res != tc.expectresult { + t.Errorf("%v expected %t, got %t", tc.name, tc.expectresult, res) + } + } +} + +func generateCRDwithCondition(conditions []CustomResourceDefinitionCondition) *CustomResourceDefinition { + testCRDObjectMeta := metav1.ObjectMeta{ + Name: "plural.group.com", + ResourceVersion: "12", + } + testCRDSpec := CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Scope: ResourceScope("Cluster"), + Names: CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + } + testCRDAcceptedNames := CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + } + return &CustomResourceDefinition{ + ObjectMeta: testCRDObjectMeta, + Spec: testCRDSpec, + Status: CustomResourceDefinitionStatus{ + AcceptedNames: testCRDAcceptedNames, + Conditions: conditions, + }, + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/BUILD index e7403207c..26acfd2c2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/BUILD @@ -23,10 +23,8 @@ go_library( deps = [ "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go index 25cee84d2..2fd04b77d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go @@ -19,25 +19,13 @@ package install import ( "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: apiextensions.GroupName, - RootScopedKinds: sets.NewString("CustomResourceDefinition"), - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: apiextensions.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(apiextensions.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go index 0deb7cbd0..6fc75154f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go @@ -25,6 +25,9 @@ type CustomResourceDefinitionSpec struct { // Group is the group this resource belongs in Group string // Version is the version this resource belongs in + // Should be always first item in Versions field if provided. + // Optional, but at least one of Version or Versions must be set. + // Deprecated: Please use `Versions`. Version string // Names are the names used to describe this custom resource Names CustomResourceDefinitionNames @@ -34,6 +37,52 @@ type CustomResourceDefinitionSpec struct { Validation *CustomResourceValidation // Subresources describes the subresources for CustomResources Subresources *CustomResourceSubresources + // Versions is the list of all supported versions for this resource. + // If Version field is provided, this field is optional. + // Validation: All versions must use the same validation schema for now. i.e., top + // level Validation field is applied to all of these versions. + // Order: The version name will be used to compute the order. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing + // major version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. + Versions []CustomResourceDefinitionVersion + // AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column. + AdditionalPrinterColumns []CustomResourceColumnDefinition +} + +type CustomResourceDefinitionVersion struct { + // Name is the version name, e.g. “v1”, “v2beta1”, etc. + Name string + // Served is a flag enabling/disabling this version from being served via REST APIs + Served bool + // Storage flags the version as storage version. There must be exactly one flagged + // as storage version. + Storage bool +} + +// CustomResourceColumnDefinition specifies a column for server side printing. +type CustomResourceColumnDefinition struct { + // name is a human readable name for the column. + Name string + // type is an OpenAPI type definition for this column. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Type string + // format is an optional OpenAPI type definition for this column. The 'name' format is applied + // to the primary identifier column to assist in clients identifying column is the resource name. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Format string + // description is a human readable description of this column. + Description string + // priority is an integer defining the relative importance of this column compared to others. Lower + // numbers are considered higher priority. Columns that may be omitted in limited space scenarios + // should be given a higher priority. + Priority int32 + + // JSONPath is a simple JSON path, i.e. without array notation. + JSONPath string } // CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition @@ -115,6 +164,14 @@ type CustomResourceDefinitionStatus struct { // AcceptedNames are the names that are actually being used to serve discovery // They may be different than the names in spec. AcceptedNames CustomResourceDefinitionNames + + // StoredVersions are all versions of CustomResources that were ever persisted. Tracking these + // versions allows a migration path for stored versions in etcd. The field is mutable + // so the migration controller can first finish a migration to another version (i.e. + // that no old objects are left in the storage), and then remove the rest of the + // versions from this list. + // None of the versions in this list can be removed from the spec.Versions field. + StoredVersions []string } // CustomResourceCleanupFinalizer is the name of the finalizer which will delete instances of diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go index 903773ae2..f6a114e2b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go @@ -236,22 +236,3 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps { return out } - -func deepCopyJSON(x interface{}) interface{} { - switch x := x.(type) { - case map[string]interface{}: - clone := make(map[string]interface{}, len(x)) - for k, v := range x { - clone[k] = deepCopyJSON(v) - } - return clone - case []interface{}: - clone := make([]interface{}, len(x)) - for i := range x { - clone[i] = deepCopyJSON(x[i]) - } - return clone - default: - return x - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go index edffaed55..e3235e870 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go @@ -19,9 +19,12 @@ package v1beta1 import ( "strings" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) +var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() + func addDefaultingFuncs(scheme *runtime.Scheme) error { scheme.AddTypeDefaultingFunc(&CustomResourceDefinition{}, func(obj interface{}) { SetDefaults_CustomResourceDefinition(obj.(*CustomResourceDefinition)) }) // TODO figure out why I can't seem to get my defaulter generated @@ -31,6 +34,14 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { func SetDefaults_CustomResourceDefinition(obj *CustomResourceDefinition) { SetDefaults_CustomResourceDefinitionSpec(&obj.Spec) + if len(obj.Status.StoredVersions) == 0 { + for _, v := range obj.Spec.Versions { + if v.Storage { + obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name) + break + } + } + } } func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) { @@ -43,4 +54,21 @@ func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 { obj.Names.ListKind = obj.Names.Kind + "List" } + // If there is no list of versions, create on using deprecated Version field. + if len(obj.Versions) == 0 && len(obj.Version) != 0 { + obj.Versions = []CustomResourceDefinitionVersion{{ + Name: obj.Version, + Storage: true, + Served: true, + }} + } + // For backward compatibility set the version field to the first item in versions list. + if len(obj.Version) == 0 && len(obj.Versions) != 0 { + obj.Version = obj.Versions[0].Name + } + if len(obj.AdditionalPrinterColumns) == 0 { + obj.AdditionalPrinterColumns = []CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"}, + } + } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go index e7325da23..c771e61cb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,12 +25,14 @@ limitations under the License. k8s.io/kubernetes/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto It has these top-level messages: + CustomResourceColumnDefinition CustomResourceDefinition CustomResourceDefinitionCondition CustomResourceDefinitionList CustomResourceDefinitionNames CustomResourceDefinitionSpec CustomResourceDefinitionStatus + CustomResourceDefinitionVersion CustomResourceSubresourceScale CustomResourceSubresourceStatus CustomResourceSubresources @@ -66,99 +68,113 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +func (m *CustomResourceColumnDefinition) Reset() { *m = CustomResourceColumnDefinition{} } +func (*CustomResourceColumnDefinition) ProtoMessage() {} +func (*CustomResourceColumnDefinition) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{0} +} + func (m *CustomResourceDefinition) Reset() { *m = CustomResourceDefinition{} } func (*CustomResourceDefinition) ProtoMessage() {} func (*CustomResourceDefinition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{0} + return fileDescriptorGenerated, []int{1} } func (m *CustomResourceDefinitionCondition) Reset() { *m = CustomResourceDefinitionCondition{} } func (*CustomResourceDefinitionCondition) ProtoMessage() {} func (*CustomResourceDefinitionCondition) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{1} + return fileDescriptorGenerated, []int{2} } func (m *CustomResourceDefinitionList) Reset() { *m = CustomResourceDefinitionList{} } func (*CustomResourceDefinitionList) ProtoMessage() {} func (*CustomResourceDefinitionList) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{2} + return fileDescriptorGenerated, []int{3} } func (m *CustomResourceDefinitionNames) Reset() { *m = CustomResourceDefinitionNames{} } func (*CustomResourceDefinitionNames) ProtoMessage() {} func (*CustomResourceDefinitionNames) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{3} + return fileDescriptorGenerated, []int{4} } func (m *CustomResourceDefinitionSpec) Reset() { *m = CustomResourceDefinitionSpec{} } func (*CustomResourceDefinitionSpec) ProtoMessage() {} func (*CustomResourceDefinitionSpec) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{4} + return fileDescriptorGenerated, []int{5} } func (m *CustomResourceDefinitionStatus) Reset() { *m = CustomResourceDefinitionStatus{} } func (*CustomResourceDefinitionStatus) ProtoMessage() {} func (*CustomResourceDefinitionStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{5} + return fileDescriptorGenerated, []int{6} +} + +func (m *CustomResourceDefinitionVersion) Reset() { *m = CustomResourceDefinitionVersion{} } +func (*CustomResourceDefinitionVersion) ProtoMessage() {} +func (*CustomResourceDefinitionVersion) Descriptor() ([]byte, []int) { + return fileDescriptorGenerated, []int{7} } func (m *CustomResourceSubresourceScale) Reset() { *m = CustomResourceSubresourceScale{} } func (*CustomResourceSubresourceScale) ProtoMessage() {} func (*CustomResourceSubresourceScale) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{6} + return fileDescriptorGenerated, []int{8} } func (m *CustomResourceSubresourceStatus) Reset() { *m = CustomResourceSubresourceStatus{} } func (*CustomResourceSubresourceStatus) ProtoMessage() {} func (*CustomResourceSubresourceStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{7} + return fileDescriptorGenerated, []int{9} } func (m *CustomResourceSubresources) Reset() { *m = CustomResourceSubresources{} } func (*CustomResourceSubresources) ProtoMessage() {} func (*CustomResourceSubresources) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{8} + return fileDescriptorGenerated, []int{10} } func (m *CustomResourceValidation) Reset() { *m = CustomResourceValidation{} } func (*CustomResourceValidation) ProtoMessage() {} func (*CustomResourceValidation) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{9} + return fileDescriptorGenerated, []int{11} } func (m *ExternalDocumentation) Reset() { *m = ExternalDocumentation{} } func (*ExternalDocumentation) ProtoMessage() {} -func (*ExternalDocumentation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} } +func (*ExternalDocumentation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } func (m *JSON) Reset() { *m = JSON{} } func (*JSON) ProtoMessage() {} -func (*JSON) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } +func (*JSON) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (m *JSONSchemaProps) Reset() { *m = JSONSchemaProps{} } func (*JSONSchemaProps) ProtoMessage() {} -func (*JSONSchemaProps) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } +func (*JSONSchemaProps) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } func (m *JSONSchemaPropsOrArray) Reset() { *m = JSONSchemaPropsOrArray{} } func (*JSONSchemaPropsOrArray) ProtoMessage() {} -func (*JSONSchemaPropsOrArray) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } +func (*JSONSchemaPropsOrArray) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } func (m *JSONSchemaPropsOrBool) Reset() { *m = JSONSchemaPropsOrBool{} } func (*JSONSchemaPropsOrBool) ProtoMessage() {} -func (*JSONSchemaPropsOrBool) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } +func (*JSONSchemaPropsOrBool) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } func (m *JSONSchemaPropsOrStringArray) Reset() { *m = JSONSchemaPropsOrStringArray{} } func (*JSONSchemaPropsOrStringArray) ProtoMessage() {} func (*JSONSchemaPropsOrStringArray) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{15} + return fileDescriptorGenerated, []int{17} } func init() { + proto.RegisterType((*CustomResourceColumnDefinition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition") proto.RegisterType((*CustomResourceDefinition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition") proto.RegisterType((*CustomResourceDefinitionCondition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition") proto.RegisterType((*CustomResourceDefinitionList)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionList") proto.RegisterType((*CustomResourceDefinitionNames)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionNames") proto.RegisterType((*CustomResourceDefinitionSpec)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionSpec") proto.RegisterType((*CustomResourceDefinitionStatus)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus") + proto.RegisterType((*CustomResourceDefinitionVersion)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionVersion") proto.RegisterType((*CustomResourceSubresourceScale)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceScale") proto.RegisterType((*CustomResourceSubresourceStatus)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresourceStatus") proto.RegisterType((*CustomResourceSubresources)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceSubresources") @@ -170,6 +186,47 @@ func init() { proto.RegisterType((*JSONSchemaPropsOrBool)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool") proto.RegisterType((*JSONSchemaPropsOrStringArray)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray") } +func (m *CustomResourceColumnDefinition) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CustomResourceColumnDefinition) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Type))) + i += copy(dAtA[i:], m.Type) + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Format))) + i += copy(dAtA[i:], m.Format) + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Description))) + i += copy(dAtA[i:], m.Description) + dAtA[i] = 0x28 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Priority)) + dAtA[i] = 0x32 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.JSONPath))) + i += copy(dAtA[i:], m.JSONPath) + return i, nil +} + func (m *CustomResourceDefinition) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -411,6 +468,30 @@ func (m *CustomResourceDefinitionSpec) MarshalTo(dAtA []byte) (int, error) { } i += n8 } + if len(m.Versions) > 0 { + for _, msg := range m.Versions { + dAtA[i] = 0x3a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.AdditionalPrinterColumns) > 0 { + for _, msg := range m.AdditionalPrinterColumns { + dAtA[i] = 0x42 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } return i, nil } @@ -449,6 +530,59 @@ func (m *CustomResourceDefinitionStatus) MarshalTo(dAtA []byte) (int, error) { return 0, err } i += n9 + if len(m.StoredVersions) > 0 { + for _, s := range m.StoredVersions { + dAtA[i] = 0x1a + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + return i, nil +} + +func (m *CustomResourceDefinitionVersion) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CustomResourceDefinitionVersion) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + dAtA[i] = 0x10 + i++ + if m.Served { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + dAtA[i] = 0x18 + i++ + if m.Storage { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ return i, nil } @@ -1184,6 +1318,23 @@ func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return offset + 1 } +func (m *CustomResourceColumnDefinition) Size() (n int) { + var l int + _ = l + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Type) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Format) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Description) + n += 1 + l + sovGenerated(uint64(l)) + n += 1 + sovGenerated(uint64(m.Priority)) + l = len(m.JSONPath) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *CustomResourceDefinition) Size() (n int) { var l int _ = l @@ -1271,6 +1422,18 @@ func (m *CustomResourceDefinitionSpec) Size() (n int) { l = m.Subresources.Size() n += 1 + l + sovGenerated(uint64(l)) } + if len(m.Versions) > 0 { + for _, e := range m.Versions { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + if len(m.AdditionalPrinterColumns) > 0 { + for _, e := range m.AdditionalPrinterColumns { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -1285,6 +1448,22 @@ func (m *CustomResourceDefinitionStatus) Size() (n int) { } l = m.AcceptedNames.Size() n += 1 + l + sovGenerated(uint64(l)) + if len(m.StoredVersions) > 0 { + for _, s := range m.StoredVersions { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *CustomResourceDefinitionVersion) Size() (n int) { + var l int + _ = l + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + n += 2 + n += 2 return n } @@ -1556,6 +1735,21 @@ func sovGenerated(x uint64) (n int) { func sozGenerated(x uint64) (n int) { return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (this *CustomResourceColumnDefinition) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CustomResourceColumnDefinition{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `Format:` + fmt.Sprintf("%v", this.Format) + `,`, + `Description:` + fmt.Sprintf("%v", this.Description) + `,`, + `Priority:` + fmt.Sprintf("%v", this.Priority) + `,`, + `JSONPath:` + fmt.Sprintf("%v", this.JSONPath) + `,`, + `}`, + }, "") + return s +} func (this *CustomResourceDefinition) String() string { if this == nil { return "nil" @@ -1619,6 +1813,8 @@ func (this *CustomResourceDefinitionSpec) String() string { `Scope:` + fmt.Sprintf("%v", this.Scope) + `,`, `Validation:` + strings.Replace(fmt.Sprintf("%v", this.Validation), "CustomResourceValidation", "CustomResourceValidation", 1) + `,`, `Subresources:` + strings.Replace(fmt.Sprintf("%v", this.Subresources), "CustomResourceSubresources", "CustomResourceSubresources", 1) + `,`, + `Versions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Versions), "CustomResourceDefinitionVersion", "CustomResourceDefinitionVersion", 1), `&`, ``, 1) + `,`, + `AdditionalPrinterColumns:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AdditionalPrinterColumns), "CustomResourceColumnDefinition", "CustomResourceColumnDefinition", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -1630,6 +1826,19 @@ func (this *CustomResourceDefinitionStatus) String() string { s := strings.Join([]string{`&CustomResourceDefinitionStatus{`, `Conditions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Conditions), "CustomResourceDefinitionCondition", "CustomResourceDefinitionCondition", 1), `&`, ``, 1) + `,`, `AcceptedNames:` + strings.Replace(strings.Replace(this.AcceptedNames.String(), "CustomResourceDefinitionNames", "CustomResourceDefinitionNames", 1), `&`, ``, 1) + `,`, + `StoredVersions:` + fmt.Sprintf("%v", this.StoredVersions) + `,`, + `}`, + }, "") + return s +} +func (this *CustomResourceDefinitionVersion) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CustomResourceDefinitionVersion{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Served:` + fmt.Sprintf("%v", this.Served) + `,`, + `Storage:` + fmt.Sprintf("%v", this.Storage) + `,`, `}`, }, "") return s @@ -1823,7 +2032,7 @@ func valueToStringGenerated(v interface{}) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("*%v", pv) } -func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { +func (m *CustomResourceColumnDefinition) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1846,17 +2055,17 @@ func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CustomResourceDefinition: wiretype end group for non-group") + return fmt.Errorf("proto: CustomResourceColumnDefinition: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CustomResourceDefinition: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CustomResourceColumnDefinition: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -1866,27 +2075,26 @@ func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Name = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -1896,27 +2104,26 @@ func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Type = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -1926,47 +2133,263 @@ func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Format = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) } - if skippy < 0 { + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - if (iNdEx + skippy) > l { + postIndex := iNdEx + intStringLen + if postIndex > l { return io.ErrUnexpectedEOF } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *CustomResourceDefinitionCondition) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) + } + m.Priority = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Priority |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field JSONPath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.JSONPath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CustomResourceDefinition: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CustomResourceDefinition: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CustomResourceDefinitionCondition) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { preIndex := iNdEx var wire uint64 for shift := uint(0); ; shift += 7 { @@ -2706,6 +3129,68 @@ func (m *CustomResourceDefinitionSpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Versions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Versions = append(m.Versions, CustomResourceDefinitionVersion{}) + if err := m.Versions[len(m.Versions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AdditionalPrinterColumns", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AdditionalPrinterColumns = append(m.AdditionalPrinterColumns, CustomResourceColumnDefinition{}) + if err := m.AdditionalPrinterColumns[len(m.AdditionalPrinterColumns)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -2817,6 +3302,154 @@ func (m *CustomResourceDefinitionStatus) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StoredVersions", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StoredVersions = append(m.StoredVersions, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CustomResourceDefinitionVersion) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CustomResourceDefinitionVersion: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CustomResourceDefinitionVersion: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Served", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Served = bool(v != 0) + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Storage", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Storage = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -5241,137 +5874,149 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2102 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0xcb, 0x6f, 0x63, 0x49, - 0xd5, 0x4f, 0xd9, 0x79, 0x56, 0x92, 0x49, 0x52, 0xdd, 0xe9, 0xef, 0x76, 0xbe, 0x6e, 0x3b, 0xf1, - 0x30, 0xa3, 0x00, 0xd3, 0x36, 0x3d, 0x0f, 0x66, 0x40, 0x62, 0x11, 0x27, 0x01, 0xf5, 0x90, 0x74, - 0xa2, 0x72, 0x77, 0x23, 0x98, 0x67, 0xe5, 0xba, 0xec, 0x54, 0xe7, 0xbe, 0xfa, 0x56, 0x5d, 0x77, - 0x22, 0x01, 0xe2, 0xa1, 0x11, 0x12, 0x12, 0x0f, 0x41, 0x6f, 0x90, 0xd8, 0x80, 0xc4, 0x06, 0x21, - 0x58, 0xc0, 0x92, 0x25, 0x8b, 0x5e, 0x8e, 0xc4, 0x66, 0x56, 0x16, 0x6d, 0xfe, 0x05, 0x24, 0xa4, - 0xac, 0x50, 0x3d, 0xee, 0xcb, 0x8e, 0x67, 0x5a, 0x1a, 0x7b, 0x7a, 0xe7, 0x7b, 0x5e, 0xbf, 0x5f, - 0x9d, 0x3a, 0x75, 0xea, 0x94, 0x61, 0xeb, 0xe4, 0x0d, 0x5e, 0x65, 0x7e, 0xed, 0x24, 0x3a, 0xa2, - 0xa1, 0x47, 0x05, 0xe5, 0xb5, 0x0e, 0xf5, 0x9a, 0x7e, 0x58, 0x33, 0x0a, 0x12, 0x30, 0x7a, 0x2a, - 0xa8, 0xc7, 0x99, 0xef, 0xf1, 0x1b, 0x24, 0x60, 0x9c, 0x86, 0x1d, 0x1a, 0xd6, 0x82, 0x93, 0xb6, - 0xd4, 0xf1, 0xbc, 0x41, 0xad, 0x73, 0xf3, 0x88, 0x0a, 0x72, 0xb3, 0xd6, 0xa6, 0x1e, 0x0d, 0x89, - 0xa0, 0xcd, 0x6a, 0x10, 0xfa, 0xc2, 0x47, 0x5f, 0xd3, 0xe1, 0xaa, 0x39, 0xeb, 0xf7, 0x92, 0x70, - 0xd5, 0xe0, 0xa4, 0x2d, 0x75, 0x3c, 0x6f, 0x50, 0x35, 0xe1, 0xd6, 0x6e, 0xb4, 0x99, 0x38, 0x8e, - 0x8e, 0xaa, 0xb6, 0xef, 0xd6, 0xda, 0x7e, 0xdb, 0xaf, 0xa9, 0xa8, 0x47, 0x51, 0x4b, 0x7d, 0xa9, - 0x0f, 0xf5, 0x4b, 0xa3, 0xad, 0xbd, 0x9a, 0x92, 0x77, 0x89, 0x7d, 0xcc, 0x3c, 0x1a, 0x9e, 0xa5, - 0x8c, 0x5d, 0x2a, 0x48, 0xad, 0x33, 0xc0, 0x71, 0xad, 0x36, 0xcc, 0x2b, 0x8c, 0x3c, 0xc1, 0x5c, - 0x3a, 0xe0, 0xf0, 0xe5, 0x4f, 0x72, 0xe0, 0xf6, 0x31, 0x75, 0xc9, 0x80, 0xdf, 0x2b, 0xc3, 0xfc, - 0x22, 0xc1, 0x9c, 0x1a, 0xf3, 0x04, 0x17, 0x61, 0xbf, 0x53, 0xe5, 0xc7, 0x45, 0x68, 0x6d, 0x47, - 0x5c, 0xf8, 0x2e, 0xa6, 0xdc, 0x8f, 0x42, 0x9b, 0xee, 0xd0, 0x16, 0xf3, 0x98, 0x60, 0xbe, 0x87, - 0xde, 0x87, 0xb3, 0x72, 0x55, 0x4d, 0x22, 0x88, 0x05, 0xd6, 0xc1, 0xe6, 0xfc, 0xcb, 0x5f, 0xaa, - 0xa6, 0x19, 0x4f, 0x40, 0xd2, 0x34, 0x4b, 0xeb, 0x6a, 0xe7, 0x66, 0xf5, 0xe0, 0xe8, 0x3e, 0xb5, - 0xc5, 0x3e, 0x15, 0xa4, 0x8e, 0x1e, 0x77, 0xcb, 0x13, 0xbd, 0x6e, 0x19, 0xa6, 0x32, 0x9c, 0x44, - 0x45, 0xdf, 0x83, 0x93, 0x3c, 0xa0, 0xb6, 0x55, 0x50, 0xd1, 0xdf, 0xaa, 0x7e, 0xaa, 0xfd, 0xac, - 0x0e, 0x5b, 0x48, 0x23, 0xa0, 0x76, 0x7d, 0xc1, 0x10, 0x99, 0x94, 0x5f, 0x58, 0xc1, 0xa2, 0x0f, - 0x00, 0x9c, 0xe6, 0x82, 0x88, 0x88, 0x5b, 0x45, 0xc5, 0xe0, 0x9d, 0x71, 0x31, 0x50, 0x20, 0xf5, - 0xe7, 0x0c, 0x87, 0x69, 0xfd, 0x8d, 0x0d, 0x78, 0xe5, 0x3f, 0x05, 0xb8, 0x31, 0xcc, 0x75, 0xdb, - 0xf7, 0x9a, 0x7a, 0x3b, 0x6e, 0xc1, 0x49, 0x71, 0x16, 0x50, 0xb5, 0x15, 0x73, 0xf5, 0xd7, 0xe2, - 0xf5, 0xdc, 0x39, 0x0b, 0xe8, 0x79, 0xb7, 0xfc, 0xc2, 0x27, 0x06, 0x90, 0x86, 0x58, 0x85, 0x40, - 0x5f, 0x49, 0xd6, 0x5d, 0x50, 0xc1, 0x36, 0xf2, 0xc4, 0xce, 0xbb, 0xe5, 0xa5, 0xc4, 0x2d, 0xcf, - 0x15, 0x75, 0x20, 0x72, 0x08, 0x17, 0x77, 0x42, 0xe2, 0x71, 0x1d, 0x96, 0xb9, 0xd4, 0xa4, 0xef, - 0x0b, 0x4f, 0x57, 0x1e, 0xd2, 0xa3, 0xbe, 0x66, 0x20, 0xd1, 0xde, 0x40, 0x34, 0x7c, 0x01, 0x02, - 0x7a, 0x11, 0x4e, 0x87, 0x94, 0x70, 0xdf, 0xb3, 0x26, 0x15, 0xe5, 0x24, 0x97, 0x58, 0x49, 0xb1, - 0xd1, 0xa2, 0xcf, 0xc3, 0x19, 0x97, 0x72, 0x4e, 0xda, 0xd4, 0x9a, 0x52, 0x86, 0x4b, 0xc6, 0x70, - 0x66, 0x5f, 0x8b, 0x71, 0xac, 0xaf, 0x9c, 0x03, 0x78, 0x6d, 0x58, 0xd6, 0xf6, 0x18, 0x17, 0xe8, - 0xed, 0x81, 0x03, 0x50, 0x7d, 0xba, 0x15, 0x4a, 0x6f, 0x55, 0xfe, 0xcb, 0x06, 0x7c, 0x36, 0x96, - 0x64, 0x8a, 0xff, 0xbb, 0x70, 0x8a, 0x09, 0xea, 0xca, 0x3d, 0x28, 0x6e, 0xce, 0xbf, 0xfc, 0xad, - 0x31, 0xd5, 0x5e, 0x7d, 0xd1, 0x70, 0x98, 0xba, 0x25, 0xd1, 0xb0, 0x06, 0xad, 0xfc, 0xa1, 0x00, - 0xaf, 0x0f, 0x73, 0xb9, 0x4d, 0x5c, 0xca, 0x65, 0xc6, 0x03, 0x27, 0x0a, 0x89, 0x63, 0x2a, 0x2e, - 0xc9, 0xf8, 0xa1, 0x92, 0x62, 0xa3, 0x45, 0x2f, 0xc1, 0x59, 0xce, 0xbc, 0x76, 0xe4, 0x90, 0xd0, - 0x94, 0x53, 0xb2, 0xea, 0x86, 0x91, 0xe3, 0xc4, 0x02, 0x55, 0x21, 0xe4, 0xc7, 0x7e, 0x28, 0x14, - 0x86, 0x55, 0x5c, 0x2f, 0xca, 0xc8, 0xb2, 0x41, 0x34, 0x12, 0x29, 0xce, 0x58, 0xa0, 0x75, 0x38, - 0x79, 0xc2, 0xbc, 0xa6, 0xd9, 0xf5, 0xe4, 0x14, 0x7f, 0x93, 0x79, 0x4d, 0xac, 0x34, 0x12, 0xdf, - 0x61, 0x5c, 0x48, 0x89, 0xd9, 0xf2, 0x5c, 0xd6, 0x95, 0x65, 0x62, 0x21, 0xf1, 0x6d, 0x22, 0x68, - 0xdb, 0x0f, 0x19, 0xe5, 0xd6, 0x74, 0x8a, 0xbf, 0x9d, 0x48, 0x71, 0xc6, 0xa2, 0xf2, 0x8f, 0xc9, - 0xe1, 0x45, 0x22, 0x5b, 0x09, 0x7a, 0x1e, 0x4e, 0xb5, 0x43, 0x3f, 0x0a, 0x4c, 0x96, 0x92, 0x6c, - 0x7f, 0x43, 0x0a, 0xb1, 0xd6, 0xc9, 0xaa, 0xec, 0xd0, 0x50, 0x6e, 0x98, 0x49, 0x51, 0x52, 0x95, - 0xf7, 0xb4, 0x18, 0xc7, 0x7a, 0xf4, 0x43, 0x00, 0xa7, 0x3c, 0x93, 0x1c, 0x59, 0x72, 0x6f, 0x8f, - 0xa9, 0x2e, 0x54, 0x7a, 0x53, 0xba, 0x3a, 0xf3, 0x1a, 0x19, 0xbd, 0x0a, 0xa7, 0xb8, 0xed, 0x07, - 0xd4, 0x64, 0xbd, 0x14, 0x1b, 0x35, 0xa4, 0xf0, 0xbc, 0x5b, 0x5e, 0x8c, 0xc3, 0x29, 0x01, 0xd6, - 0xc6, 0xe8, 0x27, 0x00, 0xc2, 0x0e, 0x71, 0x58, 0x93, 0xc8, 0xf8, 0x6a, 0x2f, 0x46, 0x5d, 0xd6, - 0xf7, 0x92, 0xf0, 0x7a, 0xd3, 0xd2, 0x6f, 0x9c, 0x81, 0x46, 0xbf, 0x00, 0x70, 0x81, 0x47, 0x47, - 0xa1, 0xf1, 0x92, 0xfb, 0x2c, 0xb9, 0x7c, 0x7b, 0xa4, 0x5c, 0x1a, 0x19, 0x80, 0xfa, 0x72, 0xaf, - 0x5b, 0x5e, 0xc8, 0x4a, 0x70, 0x8e, 0x40, 0xe5, 0x9f, 0x05, 0x58, 0xfa, 0xf8, 0xdb, 0x01, 0x3d, - 0x02, 0x10, 0xda, 0x71, 0xd7, 0xe5, 0x16, 0x50, 0x5d, 0xe1, 0xfd, 0x31, 0xed, 0x7e, 0xd2, 0xde, - 0xd3, 0x1b, 0x3a, 0x11, 0xc9, 0x03, 0x90, 0xfc, 0x46, 0xbf, 0x01, 0x70, 0x91, 0xd8, 0x36, 0x0d, - 0x04, 0x6d, 0xea, 0x43, 0x5b, 0xf8, 0x0c, 0xea, 0x72, 0xd5, 0xb0, 0x5a, 0xdc, 0xca, 0x42, 0xe3, - 0x3c, 0x93, 0xca, 0x7f, 0x41, 0x7f, 0x56, 0x33, 0x5b, 0xd0, 0xb0, 0x89, 0x43, 0xd1, 0x0e, 0x5c, - 0x96, 0x77, 0x3d, 0xa6, 0x81, 0xc3, 0x6c, 0xc2, 0x0f, 0x89, 0x38, 0x36, 0x27, 0xd5, 0x32, 0x10, - 0xcb, 0x8d, 0x3e, 0x3d, 0x1e, 0xf0, 0x40, 0x6f, 0x42, 0xa4, 0xef, 0xbf, 0x5c, 0x1c, 0x7d, 0x94, - 0x93, 0x9b, 0xac, 0x31, 0x60, 0x81, 0x2f, 0xf0, 0x42, 0xdb, 0x70, 0xc5, 0x21, 0x47, 0xd4, 0x69, - 0x50, 0x87, 0xda, 0xc2, 0x0f, 0x55, 0xa8, 0xa2, 0x0a, 0xb5, 0xda, 0xeb, 0x96, 0x57, 0xf6, 0xfa, - 0x95, 0x78, 0xd0, 0xbe, 0xb2, 0x01, 0xcb, 0xc3, 0x17, 0xae, 0xa7, 0x8a, 0xdf, 0x15, 0xe0, 0xda, - 0xf0, 0x8a, 0x45, 0x3f, 0x4a, 0x87, 0x1f, 0x7d, 0xb7, 0xbd, 0x3b, 0xae, 0xd3, 0x61, 0xa6, 0x1f, - 0x38, 0x38, 0xf9, 0xa0, 0xef, 0xcb, 0x46, 0x43, 0x1c, 0x6a, 0x6a, 0xea, 0x9d, 0xb1, 0x51, 0x90, - 0x20, 0xf5, 0x39, 0xdd, 0xc3, 0x88, 0xa3, 0x5a, 0x16, 0x71, 0x68, 0xe5, 0x8f, 0xa0, 0x7f, 0xfe, - 0x4d, 0x3b, 0x0a, 0xfa, 0x19, 0x80, 0x4b, 0x7e, 0x40, 0xbd, 0xad, 0xc3, 0x5b, 0xf7, 0x5e, 0x69, - 0xa8, 0xa9, 0xdb, 0xa4, 0xea, 0xf6, 0xa7, 0xe4, 0xf9, 0x66, 0xe3, 0xe0, 0xb6, 0x0e, 0x78, 0x18, - 0xfa, 0x01, 0xaf, 0x5f, 0xea, 0x75, 0xcb, 0x4b, 0x07, 0x79, 0x28, 0xdc, 0x8f, 0x5d, 0x71, 0xe1, - 0xea, 0xee, 0xa9, 0xa0, 0xa1, 0x47, 0x9c, 0x1d, 0xdf, 0x8e, 0x5c, 0xea, 0x09, 0x4d, 0xf4, 0x35, - 0x38, 0xdf, 0xa4, 0xdc, 0x0e, 0x59, 0xa0, 0x1a, 0xaf, 0x2e, 0xef, 0x4b, 0xa6, 0x2c, 0xe7, 0x77, - 0x52, 0x15, 0xce, 0xda, 0xa1, 0xeb, 0xb0, 0x18, 0x85, 0x8e, 0xa9, 0xe2, 0x79, 0x63, 0x5e, 0xbc, - 0x8b, 0xf7, 0xb0, 0x94, 0x57, 0x36, 0xe0, 0xa4, 0xe4, 0x89, 0xae, 0xc2, 0x62, 0x48, 0x1e, 0xaa, - 0xa8, 0x0b, 0xf5, 0x19, 0x69, 0x82, 0xc9, 0x43, 0x2c, 0x65, 0x95, 0x3f, 0x5d, 0x83, 0x4b, 0x7d, - 0x6b, 0x41, 0x6b, 0xb0, 0xc0, 0x9a, 0x86, 0x03, 0x34, 0x41, 0x0b, 0xb7, 0x76, 0x70, 0x81, 0x35, - 0xd1, 0xeb, 0x70, 0x5a, 0xbf, 0x5e, 0x0c, 0x68, 0x39, 0x99, 0x3b, 0x95, 0x54, 0xde, 0x2c, 0x69, - 0x38, 0x49, 0xc4, 0x98, 0x2b, 0x0e, 0xb4, 0x65, 0x4e, 0x89, 0xe6, 0x40, 0x5b, 0x58, 0xca, 0xfa, - 0x17, 0x3f, 0xf9, 0x94, 0x8b, 0x5f, 0x37, 0xd3, 0xf4, 0x54, 0x7e, 0xae, 0xc8, 0x0c, 0xc9, 0x2f, - 0xc2, 0xe9, 0x96, 0x1f, 0xba, 0x44, 0xa8, 0xdb, 0x23, 0x33, 0xff, 0x7c, 0x5d, 0x49, 0xb1, 0xd1, - 0xca, 0x01, 0x40, 0x30, 0xe1, 0x50, 0x6b, 0x26, 0x3f, 0x00, 0xdc, 0x91, 0x42, 0xac, 0x75, 0xe8, - 0x3e, 0x9c, 0x69, 0xd2, 0x16, 0x89, 0x1c, 0x61, 0xcd, 0xaa, 0x12, 0xda, 0x1e, 0x41, 0x09, 0xd5, - 0xe7, 0xe5, 0x04, 0xb1, 0xa3, 0xe3, 0xe2, 0x18, 0x00, 0xbd, 0x00, 0x67, 0x5c, 0x72, 0xca, 0xdc, - 0xc8, 0xb5, 0xe6, 0xd6, 0xc1, 0x26, 0xd0, 0x66, 0xfb, 0x5a, 0x84, 0x63, 0x9d, 0xec, 0x8c, 0xf4, - 0xd4, 0x76, 0x22, 0xce, 0x3a, 0xd4, 0x28, 0x2d, 0xb8, 0x0e, 0x36, 0x67, 0xd3, 0xce, 0xb8, 0xdb, - 0xa7, 0xc7, 0x03, 0x1e, 0x0a, 0x8c, 0x79, 0xca, 0x79, 0x3e, 0x03, 0xa6, 0x45, 0x38, 0xd6, 0xe5, - 0xc1, 0x8c, 0xfd, 0xc2, 0x30, 0x30, 0xe3, 0x3c, 0xe0, 0x81, 0xbe, 0x08, 0xe7, 0x5c, 0x72, 0xba, - 0x47, 0xbd, 0xb6, 0x38, 0xb6, 0x16, 0xd7, 0xc1, 0x66, 0xb1, 0xbe, 0xd8, 0xeb, 0x96, 0xe7, 0xf6, - 0x63, 0x21, 0x4e, 0xf5, 0xca, 0x98, 0x79, 0xc6, 0xf8, 0xb9, 0x8c, 0x71, 0x2c, 0xc4, 0xa9, 0x5e, - 0x0e, 0x68, 0x01, 0x11, 0xf2, 0x70, 0x59, 0x4b, 0xf9, 0x01, 0xed, 0x50, 0x8b, 0x71, 0xac, 0x47, - 0x9b, 0x70, 0xd6, 0x25, 0xa7, 0x6a, 0x98, 0xb6, 0x96, 0x55, 0xd8, 0x05, 0x39, 0x6b, 0xee, 0x1b, - 0x19, 0x4e, 0xb4, 0xca, 0x92, 0x79, 0xda, 0x72, 0x25, 0x63, 0x69, 0x64, 0x38, 0xd1, 0xca, 0x22, - 0x8e, 0x3c, 0xf6, 0x20, 0xa2, 0xda, 0x18, 0xa9, 0xcc, 0x24, 0x45, 0x7c, 0x37, 0x55, 0xe1, 0xac, - 0x9d, 0x1c, 0x66, 0xdd, 0xc8, 0x11, 0x2c, 0x70, 0xe8, 0x41, 0xcb, 0xba, 0xa4, 0xf2, 0xaf, 0xe6, - 0xa2, 0xfd, 0x44, 0x8a, 0x33, 0x16, 0x88, 0xc2, 0x49, 0xea, 0x45, 0xae, 0x75, 0x59, 0xcd, 0x16, - 0x23, 0x29, 0xc1, 0xe4, 0xe4, 0xec, 0x7a, 0x91, 0x8b, 0x55, 0x78, 0xf4, 0x3a, 0x5c, 0x74, 0xc9, - 0xa9, 0x6c, 0x07, 0x34, 0x14, 0x72, 0xcc, 0x5e, 0x55, 0x8b, 0x5f, 0x91, 0xf7, 0xf9, 0x7e, 0x56, - 0x81, 0xf3, 0x76, 0xca, 0x91, 0x79, 0x19, 0xc7, 0x2b, 0x19, 0xc7, 0xac, 0x02, 0xe7, 0xed, 0x64, - 0xa6, 0x43, 0xfa, 0x20, 0x62, 0x21, 0x6d, 0x5a, 0xff, 0xa7, 0x66, 0x7a, 0x95, 0x69, 0x6c, 0x64, - 0x38, 0xd1, 0xa2, 0x4e, 0xfc, 0xea, 0xb2, 0xd4, 0x31, 0xbc, 0x3b, 0xda, 0x4e, 0x7e, 0x10, 0x6e, - 0x85, 0x21, 0x39, 0xd3, 0x37, 0x4d, 0xf6, 0xbd, 0x85, 0x38, 0x9c, 0x22, 0x8e, 0x73, 0xd0, 0xb2, - 0xae, 0xaa, 0xdc, 0x8f, 0xfa, 0x06, 0x49, 0xba, 0xce, 0x96, 0x04, 0xc1, 0x1a, 0x4b, 0x82, 0xfa, - 0x9e, 0x2c, 0x8d, 0xb5, 0xf1, 0x82, 0x1e, 0x48, 0x10, 0xac, 0xb1, 0xd4, 0x4a, 0xbd, 0xb3, 0x83, - 0x96, 0xf5, 0xff, 0x63, 0x5e, 0xa9, 0x04, 0xc1, 0x1a, 0x0b, 0x31, 0x58, 0xf4, 0x7c, 0x61, 0x5d, - 0x1b, 0xcb, 0xf5, 0xac, 0x2e, 0x9c, 0xdb, 0xbe, 0xc0, 0x12, 0x03, 0xfd, 0x0a, 0x40, 0x18, 0xa4, - 0x25, 0x7a, 0x5d, 0xad, 0xf2, 0xdd, 0xd1, 0x42, 0x56, 0xd3, 0xda, 0xde, 0xf5, 0x44, 0x78, 0x96, - 0x4e, 0xe9, 0x99, 0x33, 0x90, 0x61, 0x81, 0x7e, 0x0f, 0xe0, 0x65, 0xd2, 0xd4, 0x33, 0x3b, 0x71, - 0x32, 0x27, 0xa8, 0xa4, 0x32, 0x72, 0x67, 0xd4, 0x65, 0x5e, 0xf7, 0x7d, 0xa7, 0x6e, 0xf5, 0xba, - 0xe5, 0xcb, 0x5b, 0x17, 0xa0, 0xe2, 0x0b, 0xb9, 0xa0, 0x3f, 0x03, 0xb8, 0x62, 0xba, 0x68, 0x86, - 0x61, 0x59, 0x25, 0x90, 0x8e, 0x3a, 0x81, 0xfd, 0x38, 0x3a, 0x8f, 0x57, 0x4d, 0x1e, 0x57, 0x06, - 0xf4, 0x78, 0x90, 0x1a, 0xfa, 0x1b, 0x80, 0x0b, 0x4d, 0x1a, 0x50, 0xaf, 0x49, 0x3d, 0x5b, 0x72, - 0x5d, 0x1f, 0xc9, 0xa3, 0xac, 0x9f, 0xeb, 0x4e, 0x06, 0x42, 0xd3, 0xac, 0x1a, 0x9a, 0x0b, 0x59, - 0xd5, 0x79, 0xb7, 0x7c, 0x25, 0x75, 0xcd, 0x6a, 0x70, 0x8e, 0x25, 0xfa, 0x35, 0x80, 0x4b, 0xe9, - 0x06, 0xe8, 0x2b, 0x65, 0x63, 0x8c, 0x75, 0xa0, 0xc6, 0xd7, 0xad, 0x3c, 0x20, 0xee, 0x67, 0x80, - 0xfe, 0x02, 0xe4, 0xa4, 0x16, 0x3f, 0xf3, 0xb8, 0x55, 0x51, 0xb9, 0x7c, 0x6f, 0xe4, 0xb9, 0x4c, - 0x10, 0x74, 0x2a, 0x5f, 0x4a, 0x47, 0xc1, 0x44, 0x73, 0xde, 0x2d, 0xaf, 0x66, 0x33, 0x99, 0x28, - 0x70, 0x96, 0x21, 0xfa, 0x29, 0x80, 0x0b, 0x34, 0x9d, 0xb8, 0xb9, 0xf5, 0xfc, 0x48, 0x92, 0x78, - 0xe1, 0x10, 0xaf, 0xff, 0x41, 0xc8, 0xa8, 0x38, 0xce, 0x61, 0xcb, 0x09, 0x92, 0x9e, 0x12, 0x37, - 0x70, 0xa8, 0xf5, 0xb9, 0x11, 0x4f, 0x90, 0xbb, 0x3a, 0x2e, 0x8e, 0x01, 0xd6, 0xe4, 0xcb, 0xa7, - 0xef, 0xe4, 0xa0, 0x65, 0x58, 0x3c, 0xa1, 0x67, 0x7a, 0xb0, 0xc7, 0xf2, 0x27, 0x6a, 0xc2, 0xa9, - 0x0e, 0x71, 0xa2, 0xf8, 0xf1, 0x36, 0xe2, 0xae, 0x8b, 0x75, 0xf0, 0xaf, 0x16, 0xde, 0x00, 0x6b, - 0x8f, 0x00, 0xbc, 0x72, 0xf1, 0x81, 0x7e, 0xa6, 0xb4, 0x7e, 0x0b, 0xe0, 0xca, 0xc0, 0xd9, 0xbd, - 0x80, 0xd1, 0x83, 0x3c, 0xa3, 0xb7, 0x46, 0x7d, 0x08, 0x1b, 0x22, 0x64, 0x5e, 0x5b, 0x4d, 0x1e, - 0x59, 0x7a, 0x3f, 0x07, 0x70, 0xb9, 0xff, 0x38, 0x3c, 0xcb, 0x7c, 0x55, 0x1e, 0x15, 0xe0, 0x95, - 0x8b, 0x07, 0x26, 0x14, 0x26, 0x2f, 0xc3, 0xf1, 0xbc, 0xb0, 0x61, 0xfa, 0xca, 0x4c, 0x1e, 0x95, - 0x1f, 0x00, 0x38, 0x7f, 0x3f, 0xb1, 0x8b, 0xff, 0x87, 0x1f, 0xf9, 0xdb, 0x3e, 0xee, 0x3f, 0xa9, - 0x82, 0xe3, 0x2c, 0x6e, 0xe5, 0xaf, 0x00, 0xae, 0x5e, 0xd8, 0x58, 0xe5, 0x13, 0x94, 0x38, 0x8e, - 0xff, 0x50, 0xff, 0x45, 0x33, 0x9b, 0x3e, 0x41, 0xb7, 0x94, 0x14, 0x1b, 0x6d, 0x26, 0x7b, 0x85, - 0xcf, 0x2a, 0x7b, 0x95, 0xbf, 0x03, 0x78, 0xed, 0xe3, 0x2a, 0xf1, 0x99, 0x6c, 0xe9, 0x26, 0x9c, - 0x35, 0x43, 0xd1, 0x99, 0xda, 0x4e, 0xf3, 0x0e, 0x30, 0x4d, 0xe3, 0x0c, 0x27, 0xda, 0xfa, 0x8d, - 0xc7, 0x4f, 0x4a, 0x13, 0x1f, 0x3e, 0x29, 0x4d, 0x7c, 0xf4, 0xa4, 0x34, 0xf1, 0x83, 0x5e, 0x09, - 0x3c, 0xee, 0x95, 0xc0, 0x87, 0xbd, 0x12, 0xf8, 0xa8, 0x57, 0x02, 0xff, 0xea, 0x95, 0xc0, 0x2f, - 0xff, 0x5d, 0x9a, 0xf8, 0xce, 0x8c, 0x01, 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x6f, - 0x04, 0x49, 0xd3, 0x1e, 0x00, 0x00, + // 2292 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6f, 0x5b, 0x49, + 0x15, 0xef, 0xd8, 0x71, 0xe2, 0x8c, 0x93, 0x26, 0x99, 0x6d, 0xca, 0x6d, 0x68, 0xed, 0xd4, 0x65, + 0x57, 0x01, 0xb6, 0x0e, 0x2d, 0xbb, 0xec, 0xb2, 0x12, 0x0f, 0x71, 0x52, 0x50, 0x97, 0xa6, 0x89, + 0xc6, 0x6d, 0x11, 0xec, 0xe7, 0xc4, 0x9e, 0x38, 0xb7, 0xb9, 0x5f, 0xbd, 0x33, 0xd7, 0x4d, 0x24, + 0x40, 0x7c, 0x68, 0x85, 0x84, 0x80, 0x05, 0xb6, 0x42, 0x42, 0xe2, 0x05, 0x24, 0x5e, 0x10, 0x82, + 0x07, 0x78, 0x83, 0x3f, 0xa0, 0x8f, 0xfb, 0xb8, 0x4f, 0x16, 0x35, 0xff, 0x02, 0x12, 0x52, 0x9e, + 0xd0, 0x7c, 0xdc, 0xb9, 0x1f, 0x4e, 0xb6, 0x11, 0x6b, 0x6f, 0xdf, 0x7c, 0xcf, 0x39, 0x73, 0x7e, + 0xbf, 0x39, 0x73, 0xe6, 0xcc, 0x39, 0x09, 0xdc, 0xdd, 0x7f, 0x95, 0x35, 0x6c, 0x7f, 0x75, 0x3f, + 0xda, 0xa1, 0xa1, 0x47, 0x39, 0x65, 0xab, 0x3d, 0xea, 0x75, 0xfc, 0x70, 0x55, 0x2b, 0x48, 0x60, + 0xd3, 0x03, 0x4e, 0x3d, 0x66, 0xfb, 0x1e, 0xbb, 0x4a, 0x02, 0x9b, 0xd1, 0xb0, 0x47, 0xc3, 0xd5, + 0x60, 0xbf, 0x2b, 0x74, 0x2c, 0x6b, 0xb0, 0xda, 0xbb, 0xb6, 0x43, 0x39, 0xb9, 0xb6, 0xda, 0xa5, + 0x1e, 0x0d, 0x09, 0xa7, 0x9d, 0x46, 0x10, 0xfa, 0xdc, 0x47, 0x5f, 0x53, 0xee, 0x1a, 0x19, 0xeb, + 0x77, 0x8c, 0xbb, 0x46, 0xb0, 0xdf, 0x15, 0x3a, 0x96, 0x35, 0x68, 0x68, 0x77, 0x4b, 0x57, 0xbb, + 0x36, 0xdf, 0x8b, 0x76, 0x1a, 0x6d, 0xdf, 0x5d, 0xed, 0xfa, 0x5d, 0x7f, 0x55, 0x7a, 0xdd, 0x89, + 0x76, 0xe5, 0x97, 0xfc, 0x90, 0xbf, 0x14, 0xda, 0xd2, 0x4b, 0x09, 0x79, 0x97, 0xb4, 0xf7, 0x6c, + 0x8f, 0x86, 0x87, 0x09, 0x63, 0x97, 0x72, 0xb2, 0xda, 0x1b, 0xe2, 0xb8, 0xb4, 0x7a, 0xd2, 0xaa, + 0x30, 0xf2, 0xb8, 0xed, 0xd2, 0xa1, 0x05, 0x5f, 0x79, 0xda, 0x02, 0xd6, 0xde, 0xa3, 0x2e, 0xc9, + 0xaf, 0xab, 0x7f, 0x50, 0x80, 0xd5, 0xf5, 0x88, 0x71, 0xdf, 0xc5, 0x94, 0xf9, 0x51, 0xd8, 0xa6, + 0xeb, 0xbe, 0x13, 0xb9, 0xde, 0x06, 0xdd, 0xb5, 0x3d, 0x9b, 0xdb, 0xbe, 0x87, 0x96, 0xe1, 0x84, + 0x47, 0x5c, 0x6a, 0x81, 0x65, 0xb0, 0x32, 0xdd, 0x9c, 0x79, 0xdc, 0xaf, 0x9d, 0x19, 0xf4, 0x6b, + 0x13, 0xb7, 0x89, 0x4b, 0xb1, 0xd4, 0x08, 0x0b, 0x7e, 0x18, 0x50, 0xab, 0x90, 0xb5, 0xb8, 0x73, + 0x18, 0x50, 0x2c, 0x35, 0xe8, 0x05, 0x38, 0xb9, 0xeb, 0x87, 0x2e, 0xe1, 0x56, 0x51, 0xda, 0x9c, + 0xd5, 0x36, 0x93, 0x5f, 0x97, 0x52, 0xac, 0xb5, 0xe8, 0x65, 0x58, 0xe9, 0x50, 0xd6, 0x0e, 0xed, + 0x40, 0x40, 0x5b, 0x13, 0xd2, 0xf8, 0x39, 0x6d, 0x5c, 0xd9, 0x48, 0x54, 0x38, 0x6d, 0x87, 0x5e, + 0x84, 0xe5, 0x20, 0xb4, 0xfd, 0xd0, 0xe6, 0x87, 0x56, 0x69, 0x19, 0xac, 0x94, 0x9a, 0xf3, 0x7a, + 0x4d, 0x79, 0x5b, 0xcb, 0xb1, 0xb1, 0x40, 0xcb, 0xb0, 0xfc, 0x7a, 0x6b, 0xeb, 0xf6, 0x36, 0xe1, + 0x7b, 0xd6, 0xa4, 0x44, 0x98, 0x10, 0xd6, 0xb8, 0x7c, 0x5f, 0x4b, 0xeb, 0x3f, 0x2e, 0x42, 0x2b, + 0x1b, 0x95, 0x54, 0x3c, 0xde, 0x85, 0x65, 0x71, 0x6c, 0x1d, 0xc2, 0x89, 0x8c, 0x49, 0xe5, 0xfa, + 0x97, 0x1a, 0x49, 0x4a, 0x99, 0xe8, 0x27, 0x79, 0x24, 0xac, 0x1b, 0xbd, 0x6b, 0x8d, 0xad, 0x9d, + 0xfb, 0xb4, 0xcd, 0x37, 0x29, 0x27, 0x4d, 0xa4, 0xe9, 0xc1, 0x44, 0x86, 0x8d, 0x57, 0xf4, 0x3d, + 0x38, 0xc1, 0x02, 0xda, 0x96, 0xf1, 0xac, 0x5c, 0x7f, 0xa3, 0xf1, 0x89, 0x12, 0xb6, 0x71, 0xd2, + 0x46, 0x5a, 0x01, 0x6d, 0x27, 0x87, 0x25, 0xbe, 0xb0, 0x84, 0x45, 0xef, 0x01, 0x38, 0xc9, 0x38, + 0xe1, 0x11, 0x93, 0xa7, 0x55, 0xb9, 0xfe, 0xd6, 0xb8, 0x18, 0x48, 0x90, 0x24, 0x19, 0xd4, 0x37, + 0xd6, 0xe0, 0xf5, 0xff, 0x14, 0xe0, 0xe5, 0x93, 0x96, 0xae, 0xfb, 0x5e, 0x47, 0x1d, 0xc7, 0x4d, + 0x9d, 0x7c, 0x2a, 0x3d, 0x5f, 0x4e, 0x27, 0xdf, 0x51, 0xbf, 0xf6, 0xfc, 0x53, 0x1d, 0xa4, 0xb2, + 0xf4, 0xab, 0x66, 0xdf, 0x2a, 0x93, 0x2f, 0x67, 0x89, 0x1d, 0xf5, 0x6b, 0x73, 0x66, 0x59, 0x96, + 0x2b, 0xea, 0x41, 0xe4, 0x10, 0xc6, 0xef, 0x84, 0xc4, 0x63, 0xca, 0xad, 0xed, 0x52, 0x1d, 0xbe, + 0x2f, 0x9c, 0x2e, 0x3d, 0xc4, 0x8a, 0xe6, 0x92, 0x86, 0x44, 0xb7, 0x86, 0xbc, 0xe1, 0x63, 0x10, + 0xc4, 0xc5, 0x0a, 0x29, 0x61, 0xe6, 0xae, 0x98, 0x58, 0x62, 0x29, 0xc5, 0x5a, 0x8b, 0x3e, 0x0f, + 0xa7, 0x5c, 0xca, 0x18, 0xe9, 0x52, 0x79, 0x41, 0xa6, 0x9b, 0x73, 0xda, 0x70, 0x6a, 0x53, 0x89, + 0x71, 0xac, 0xaf, 0x1f, 0x01, 0x78, 0xf1, 0xa4, 0xa8, 0xdd, 0xb2, 0x19, 0x47, 0x6f, 0x0e, 0x5d, + 0x80, 0xc6, 0xe9, 0x76, 0x28, 0x56, 0xcb, 0xf4, 0x37, 0xb7, 0x33, 0x96, 0xa4, 0x92, 0xff, 0xbb, + 0xb0, 0x64, 0x73, 0xea, 0x8a, 0x33, 0x28, 0xae, 0x54, 0xae, 0x7f, 0x6b, 0x4c, 0xb9, 0xd7, 0x9c, + 0xd5, 0x1c, 0x4a, 0x37, 0x05, 0x1a, 0x56, 0xa0, 0xf5, 0x3f, 0x16, 0xe0, 0xa5, 0x93, 0x96, 0x88, + 0x8a, 0xc7, 0x44, 0xc4, 0x03, 0x27, 0x0a, 0x89, 0xa3, 0x33, 0xce, 0x44, 0x7c, 0x5b, 0x4a, 0xb1, + 0xd6, 0x8a, 0x9a, 0xc4, 0x6c, 0xaf, 0x1b, 0x39, 0x24, 0xd4, 0xe9, 0x64, 0x76, 0xdd, 0xd2, 0x72, + 0x6c, 0x2c, 0x50, 0x03, 0x42, 0xb6, 0xe7, 0x87, 0x5c, 0x62, 0x58, 0xc5, 0xe5, 0xa2, 0xf0, 0x2c, + 0x0a, 0x44, 0xcb, 0x48, 0x71, 0xca, 0x42, 0x94, 0xdc, 0x7d, 0xdb, 0xeb, 0xe8, 0x53, 0x37, 0xb7, + 0xf8, 0x9b, 0xb6, 0xd7, 0xc1, 0x52, 0x23, 0xf0, 0x1d, 0x9b, 0x71, 0x21, 0xd1, 0x47, 0x9e, 0x89, + 0xba, 0xb4, 0x34, 0x16, 0x02, 0xbf, 0x4d, 0x38, 0xed, 0xfa, 0xa1, 0x4d, 0x99, 0x35, 0x99, 0xe0, + 0xaf, 0x1b, 0x29, 0x4e, 0x59, 0xd4, 0x7f, 0x35, 0x75, 0x72, 0x92, 0x88, 0x52, 0x82, 0xae, 0xc0, + 0x52, 0x37, 0xf4, 0xa3, 0x40, 0x47, 0xc9, 0x44, 0xfb, 0x1b, 0x42, 0x88, 0x95, 0x4e, 0x64, 0x65, + 0x8f, 0x86, 0xe2, 0xc0, 0x74, 0x88, 0x4c, 0x56, 0xde, 0x53, 0x62, 0x1c, 0xeb, 0xd1, 0x0f, 0x01, + 0x2c, 0x79, 0x3a, 0x38, 0x22, 0xe5, 0xde, 0x1c, 0x53, 0x5e, 0xc8, 0xf0, 0x26, 0x74, 0x55, 0xe4, + 0x15, 0x32, 0x7a, 0x09, 0x96, 0x58, 0xdb, 0x0f, 0xa8, 0x8e, 0x7a, 0x35, 0x36, 0x6a, 0x09, 0xe1, + 0x51, 0xbf, 0x36, 0x1b, 0xbb, 0x93, 0x02, 0xac, 0x8c, 0xd1, 0x4f, 0x00, 0x84, 0x3d, 0xe2, 0xd8, + 0x1d, 0x22, 0xdf, 0xb4, 0x92, 0xa4, 0x3f, 0xda, 0xb4, 0xbe, 0x67, 0xdc, 0xab, 0x43, 0x4b, 0xbe, + 0x71, 0x0a, 0x1a, 0xbd, 0x0f, 0xe0, 0x0c, 0x8b, 0x76, 0x42, 0xbd, 0x8a, 0xc9, 0xd7, 0xaf, 0x72, + 0xfd, 0xdb, 0x23, 0xe5, 0xd2, 0x4a, 0x01, 0x34, 0xe7, 0x07, 0xfd, 0xda, 0x4c, 0x5a, 0x82, 0x33, + 0x04, 0xd0, 0xcf, 0x00, 0x2c, 0xeb, 0x13, 0x66, 0xd6, 0x94, 0xbc, 0xf0, 0x6f, 0x8f, 0xe9, 0x60, + 0x75, 0x46, 0x25, 0xb7, 0x40, 0x0b, 0x18, 0x36, 0x0c, 0xd0, 0x3f, 0x00, 0xb4, 0x48, 0x47, 0x15, + 0x78, 0xe2, 0x6c, 0x87, 0xb6, 0xc7, 0x69, 0xa8, 0x1a, 0x22, 0x66, 0x95, 0x25, 0xbd, 0xd1, 0xbe, + 0x85, 0xf9, 0x66, 0xab, 0xb9, 0xac, 0xd9, 0x59, 0x6b, 0x27, 0xd0, 0xc0, 0x27, 0x12, 0xac, 0xbf, + 0x5f, 0xcc, 0xf7, 0x72, 0xf9, 0xa7, 0x16, 0x3d, 0x02, 0x10, 0xb6, 0xe3, 0x27, 0x8c, 0x59, 0x40, + 0x6e, 0xe9, 0xdd, 0x31, 0x45, 0xdc, 0xbc, 0x95, 0x49, 0xbb, 0x63, 0x44, 0xa2, 0x9a, 0x98, 0xdf, + 0xe8, 0xb7, 0x00, 0xce, 0x92, 0x76, 0x9b, 0x06, 0x9c, 0x76, 0x54, 0x05, 0x2c, 0x7c, 0x0a, 0x97, + 0x7c, 0x51, 0xb3, 0x9a, 0x5d, 0x4b, 0x43, 0xe3, 0x2c, 0x13, 0xf4, 0x1a, 0x3c, 0xcb, 0xb8, 0x1f, + 0xd2, 0x4e, 0x9c, 0x2f, 0xba, 0x3a, 0xa3, 0x41, 0xbf, 0x76, 0xb6, 0x95, 0xd1, 0xe0, 0x9c, 0x65, + 0xfd, 0x37, 0x00, 0xd6, 0x9e, 0x92, 0x8f, 0xa7, 0x68, 0xaf, 0x5f, 0x80, 0x93, 0x72, 0xbb, 0x1d, + 0x19, 0x95, 0x72, 0xaa, 0x5f, 0x92, 0x52, 0xac, 0xb5, 0xa2, 0x9a, 0x0a, 0x7c, 0xf1, 0xc6, 0x17, + 0xa5, 0xa1, 0xa9, 0xa6, 0x2d, 0x25, 0xc6, 0xb1, 0xbe, 0xfe, 0x5f, 0x90, 0x4f, 0x95, 0xd4, 0x25, + 0x6d, 0xb5, 0x89, 0x43, 0xd1, 0x06, 0x9c, 0x17, 0xdd, 0x20, 0xa6, 0x81, 0x63, 0xb7, 0x09, 0x93, + 0xdd, 0xb2, 0xe2, 0x68, 0x69, 0xb7, 0xf3, 0xad, 0x9c, 0x1e, 0x0f, 0xad, 0x40, 0xaf, 0x43, 0xa4, + 0x3a, 0xa4, 0x8c, 0x1f, 0x55, 0xec, 0x4d, 0xaf, 0xd3, 0x1a, 0xb2, 0xc0, 0xc7, 0xac, 0x42, 0xeb, + 0x70, 0xc1, 0x21, 0x3b, 0xd4, 0x69, 0x51, 0x87, 0xb6, 0xb9, 0x1f, 0x4a, 0x57, 0x6a, 0x9e, 0x58, + 0x1c, 0xf4, 0x6b, 0x0b, 0xb7, 0xf2, 0x4a, 0x3c, 0x6c, 0x5f, 0xbf, 0x9c, 0x3f, 0x91, 0xf4, 0xc6, + 0x55, 0xdf, 0xf9, 0xfb, 0x02, 0x5c, 0x3a, 0xb9, 0xa6, 0xa1, 0x1f, 0x25, 0xed, 0xb1, 0xea, 0x7e, + 0xde, 0x1e, 0x57, 0xfd, 0xd4, 0xfd, 0x31, 0x1c, 0xee, 0x8d, 0xd1, 0xf7, 0xc5, 0x53, 0x44, 0x1c, + 0xaa, 0x2f, 0xca, 0x5b, 0x63, 0xa3, 0x20, 0x40, 0x9a, 0xd3, 0xea, 0x95, 0x23, 0x8e, 0x7c, 0xd4, + 0x88, 0x43, 0xeb, 0x7f, 0x02, 0xf9, 0x09, 0x29, 0x79, 0x73, 0xd0, 0xcf, 0x01, 0x9c, 0xf3, 0x03, + 0xea, 0xad, 0x6d, 0xdf, 0xbc, 0xf7, 0xe5, 0x96, 0x1c, 0x3c, 0x75, 0xa8, 0x6e, 0x7f, 0x42, 0x9e, + 0x62, 0x6e, 0x53, 0x0e, 0xb7, 0x43, 0x3f, 0x60, 0xcd, 0xe7, 0x06, 0xfd, 0xda, 0xdc, 0x56, 0x16, + 0x0a, 0xe7, 0xb1, 0xeb, 0x2e, 0x5c, 0xbc, 0x71, 0xc0, 0x69, 0xe8, 0x11, 0x67, 0xc3, 0x6f, 0x47, + 0x2e, 0xf5, 0xb8, 0x22, 0x9a, 0x1b, 0x37, 0xc1, 0x29, 0xc7, 0xcd, 0x4b, 0xb0, 0x18, 0x85, 0x8e, + 0xce, 0xe2, 0x8a, 0x36, 0x2f, 0xde, 0xc5, 0xb7, 0xb0, 0x90, 0xd7, 0x2f, 0xc3, 0x09, 0xc1, 0x13, + 0x5d, 0x80, 0xc5, 0x90, 0x3c, 0x94, 0x5e, 0x67, 0x9a, 0x53, 0xc2, 0x04, 0x93, 0x87, 0x58, 0xc8, + 0xea, 0x7f, 0xbe, 0x08, 0xe7, 0x72, 0x7b, 0x41, 0x4b, 0xb0, 0x60, 0x77, 0x34, 0x07, 0xa8, 0x9d, + 0x16, 0x6e, 0x6e, 0xe0, 0x82, 0xdd, 0x41, 0xaf, 0xc0, 0x49, 0x35, 0xc0, 0x6b, 0xd0, 0x9a, 0x29, + 0x01, 0x52, 0x2a, 0x7a, 0x8f, 0xc4, 0x9d, 0x20, 0xa2, 0xcd, 0x25, 0x07, 0xba, 0xab, 0x6f, 0x89, + 0xe2, 0x40, 0x77, 0xb1, 0x90, 0xfd, 0xbf, 0xb3, 0x76, 0x3c, 0xec, 0x97, 0x4e, 0x31, 0xec, 0x4f, + 0x7e, 0xec, 0xb0, 0x7f, 0x05, 0x96, 0xb8, 0xcd, 0x1d, 0x6a, 0x4d, 0x65, 0x5b, 0xc4, 0x3b, 0x42, + 0x88, 0x95, 0x0e, 0xdd, 0x87, 0x53, 0x1d, 0xba, 0x4b, 0x22, 0x87, 0x5b, 0x65, 0x99, 0x42, 0xeb, + 0x23, 0x48, 0xa1, 0x66, 0x45, 0x54, 0xc5, 0x0d, 0xe5, 0x17, 0xc7, 0x00, 0xe8, 0x79, 0x38, 0xe5, + 0x92, 0x03, 0xdb, 0x8d, 0x5c, 0x6b, 0x7a, 0x19, 0xac, 0x00, 0x65, 0xb6, 0xa9, 0x44, 0x38, 0xd6, + 0x89, 0xca, 0x48, 0x0f, 0xda, 0x4e, 0xc4, 0xec, 0x1e, 0xd5, 0x4a, 0x0b, 0xca, 0x82, 0x6b, 0x2a, + 0xe3, 0x8d, 0x9c, 0x1e, 0x0f, 0xad, 0x90, 0x60, 0xb6, 0x27, 0x17, 0x57, 0x52, 0x60, 0x4a, 0x84, + 0x63, 0x5d, 0x16, 0x4c, 0xdb, 0xcf, 0x9c, 0x04, 0xa6, 0x17, 0x0f, 0xad, 0x40, 0x5f, 0x84, 0xd3, + 0x2e, 0x39, 0xb8, 0x45, 0xbd, 0x2e, 0xdf, 0xb3, 0x66, 0x97, 0xc1, 0x4a, 0xb1, 0x39, 0x3b, 0xe8, + 0xd7, 0xa6, 0x37, 0x63, 0x21, 0x4e, 0xf4, 0xd2, 0xd8, 0xf6, 0xb4, 0xf1, 0xd9, 0x94, 0x71, 0x2c, + 0xc4, 0x89, 0x5e, 0x3c, 0x3a, 0x01, 0xe1, 0xe2, 0x72, 0x59, 0x73, 0xd9, 0x16, 0x7e, 0x5b, 0x89, + 0x71, 0xac, 0x47, 0x2b, 0xb0, 0xec, 0x92, 0x03, 0x39, 0x6e, 0x59, 0xf3, 0xd2, 0xed, 0x8c, 0xe8, + 0xc3, 0x36, 0xb5, 0x0c, 0x1b, 0xad, 0xb4, 0xb4, 0x3d, 0x65, 0xb9, 0x90, 0xb2, 0xd4, 0x32, 0x6c, + 0xb4, 0x22, 0x89, 0x23, 0xcf, 0x7e, 0x10, 0x51, 0x65, 0x8c, 0x64, 0x64, 0x4c, 0x12, 0xdf, 0x4d, + 0x54, 0x38, 0x6d, 0x27, 0xc6, 0x1d, 0x37, 0x72, 0xb8, 0x1d, 0x38, 0x74, 0x6b, 0xd7, 0x7a, 0x4e, + 0xc6, 0x5f, 0x76, 0xce, 0x9b, 0x46, 0x8a, 0x53, 0x16, 0x88, 0xc2, 0x09, 0xea, 0x45, 0xae, 0x75, + 0x4e, 0x36, 0x4c, 0x23, 0x49, 0x41, 0x73, 0x73, 0x6e, 0x78, 0x91, 0x8b, 0xa5, 0x7b, 0xf4, 0x0a, + 0x9c, 0x75, 0xc9, 0x81, 0x28, 0x07, 0x34, 0xe4, 0x62, 0x10, 0x5b, 0x94, 0x9b, 0x5f, 0x10, 0x4d, + 0xca, 0x66, 0x5a, 0x81, 0xb3, 0x76, 0x72, 0xa1, 0xed, 0xa5, 0x16, 0x9e, 0x4f, 0x2d, 0x4c, 0x2b, + 0x70, 0xd6, 0x4e, 0x44, 0x3a, 0xa4, 0x0f, 0x22, 0x3b, 0xa4, 0x1d, 0xeb, 0x33, 0xb2, 0xaf, 0x91, + 0x91, 0xc6, 0x5a, 0x86, 0x8d, 0x16, 0xf5, 0xe2, 0xb9, 0xdc, 0x92, 0xd7, 0xf0, 0xee, 0x68, 0x2b, + 0xf9, 0x56, 0xb8, 0x16, 0x86, 0xe4, 0x50, 0xbd, 0x34, 0xe9, 0x89, 0x1c, 0x31, 0x58, 0x22, 0x8e, + 0xb3, 0xb5, 0x6b, 0x5d, 0x90, 0xb1, 0x1f, 0xf5, 0x0b, 0x62, 0xaa, 0xce, 0x9a, 0x00, 0xc1, 0x0a, + 0x4b, 0x80, 0xfa, 0x9e, 0x48, 0x8d, 0xa5, 0xf1, 0x82, 0x6e, 0x09, 0x10, 0xac, 0xb0, 0xe4, 0x4e, + 0xbd, 0xc3, 0xad, 0x5d, 0xeb, 0xb3, 0x63, 0xde, 0xa9, 0x00, 0xc1, 0x0a, 0x0b, 0xd9, 0xb0, 0xe8, + 0xf9, 0xdc, 0xba, 0x38, 0x96, 0xe7, 0x59, 0x3e, 0x38, 0xb7, 0x7d, 0x8e, 0x05, 0x06, 0xfa, 0x35, + 0x80, 0x30, 0x48, 0x52, 0xf4, 0xd2, 0x48, 0xc6, 0xbd, 0x1c, 0x64, 0x23, 0xc9, 0xed, 0x1b, 0x1e, + 0x0f, 0x0f, 0x93, 0xd1, 0x23, 0x75, 0x07, 0x52, 0x2c, 0xd0, 0x1f, 0x00, 0x3c, 0x97, 0x9e, 0xa8, + 0x0c, 0xbd, 0xaa, 0x8c, 0xc8, 0x9d, 0x51, 0xa7, 0x79, 0xd3, 0xf7, 0x9d, 0xa6, 0x35, 0xe8, 0xd7, + 0xce, 0xad, 0x1d, 0x83, 0x8a, 0x8f, 0xe5, 0x82, 0xfe, 0x02, 0xe0, 0x82, 0xae, 0xa2, 0x29, 0x86, + 0x35, 0x19, 0x40, 0x3a, 0xea, 0x00, 0xe6, 0x71, 0x54, 0x1c, 0x2f, 0xe8, 0x38, 0x2e, 0x0c, 0xe9, + 0xf1, 0x30, 0x35, 0xf4, 0x77, 0x00, 0x67, 0x3a, 0x34, 0xa0, 0x5e, 0x87, 0x7a, 0x6d, 0xc1, 0x75, + 0x79, 0x24, 0x93, 0x66, 0x9e, 0xeb, 0x46, 0x0a, 0x42, 0xd1, 0x6c, 0x68, 0x9a, 0x33, 0x69, 0xd5, + 0x51, 0xbf, 0x76, 0x3e, 0x59, 0x9a, 0xd6, 0xe0, 0x0c, 0x4b, 0xf4, 0x01, 0x80, 0x73, 0xc9, 0x01, + 0xa8, 0x27, 0xe5, 0xf2, 0x18, 0xf3, 0x40, 0xb6, 0xaf, 0x6b, 0x59, 0x40, 0x9c, 0x67, 0x80, 0xfe, + 0x0a, 0x44, 0xa7, 0x16, 0xcf, 0x8d, 0xcc, 0xaa, 0xcb, 0x58, 0xbe, 0x33, 0xf2, 0x58, 0x1a, 0x04, + 0x15, 0xca, 0x17, 0x93, 0x56, 0xd0, 0x68, 0x8e, 0xfa, 0xb5, 0xc5, 0x74, 0x24, 0x8d, 0x02, 0xa7, + 0x19, 0xa2, 0x9f, 0x02, 0x38, 0x43, 0x93, 0x8e, 0x9b, 0x59, 0x57, 0x46, 0x12, 0xc4, 0x63, 0x9b, + 0x78, 0xf5, 0x37, 0xa6, 0x94, 0x8a, 0xe1, 0x0c, 0xb6, 0xe8, 0x20, 0xe9, 0x01, 0x71, 0x03, 0x87, + 0x5a, 0x9f, 0x1b, 0x71, 0x07, 0x79, 0x43, 0xf9, 0xc5, 0x31, 0xc0, 0x92, 0x98, 0x7c, 0x72, 0x37, + 0x07, 0xcd, 0xc3, 0xe2, 0x3e, 0x3d, 0x54, 0x8d, 0x3d, 0x16, 0x3f, 0x51, 0x07, 0x96, 0x7a, 0xc4, + 0x89, 0xe2, 0xe1, 0x6d, 0xc4, 0x55, 0x17, 0x2b, 0xe7, 0xaf, 0x15, 0x5e, 0x05, 0x4b, 0x8f, 0x00, + 0x3c, 0x7f, 0xfc, 0x85, 0x7e, 0xa6, 0xb4, 0x7e, 0x07, 0xe0, 0xc2, 0xd0, 0xdd, 0x3d, 0x86, 0xd1, + 0x83, 0x2c, 0xa3, 0x37, 0x46, 0x7d, 0x09, 0x5b, 0x3c, 0xb4, 0xbd, 0xae, 0xec, 0x3c, 0xd2, 0xf4, + 0x7e, 0x01, 0xe0, 0x7c, 0xfe, 0x3a, 0x3c, 0xcb, 0x78, 0xd5, 0x1f, 0x15, 0xe0, 0xf9, 0xe3, 0x1b, + 0x26, 0x14, 0x9a, 0xc9, 0x70, 0x3c, 0x13, 0x36, 0x4c, 0xa6, 0x4c, 0x33, 0x54, 0xbe, 0x07, 0x60, + 0xe5, 0xbe, 0xb1, 0x8b, 0xff, 0x53, 0x33, 0xf2, 0xd9, 0x3e, 0xae, 0x3f, 0x89, 0x82, 0xe1, 0x34, + 0x6e, 0xfd, 0x6f, 0x00, 0x2e, 0x1e, 0x5b, 0x58, 0xc5, 0x08, 0x4a, 0x1c, 0xc7, 0x7f, 0xa8, 0xfe, + 0x44, 0x93, 0xfa, 0x93, 0xd9, 0x9a, 0x94, 0x62, 0xad, 0x4d, 0x45, 0xaf, 0xf0, 0x69, 0x45, 0xaf, + 0xfe, 0x4f, 0x00, 0x2f, 0x7e, 0x5c, 0x26, 0x3e, 0x93, 0x23, 0x5d, 0x81, 0x65, 0xdd, 0x14, 0x1d, + 0xca, 0xe3, 0xd4, 0x73, 0x80, 0x2e, 0x1a, 0xf2, 0xbf, 0xe7, 0xea, 0x57, 0xf3, 0xea, 0xe3, 0x27, + 0xd5, 0x33, 0x1f, 0x3e, 0xa9, 0x9e, 0xf9, 0xe8, 0x49, 0xf5, 0xcc, 0x0f, 0x06, 0x55, 0xf0, 0x78, + 0x50, 0x05, 0x1f, 0x0e, 0xaa, 0xe0, 0xa3, 0x41, 0x15, 0xfc, 0x6b, 0x50, 0x05, 0xbf, 0xfc, 0x77, + 0xf5, 0xcc, 0x77, 0xa6, 0x34, 0xf8, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x5b, 0x62, 0x04, + 0xd6, 0x21, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto index 46cfd1ca7..4cdaf2289 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,11 +24,36 @@ package k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; +// CustomResourceColumnDefinition specifies a column for server side printing. +message CustomResourceColumnDefinition { + // name is a human readable name for the column. + optional string name = 1; + + // type is an OpenAPI type definition for this column. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + optional string type = 2; + + // format is an optional OpenAPI type definition for this column. The 'name' format is applied + // to the primary identifier column to assist in clients identifying column is the resource name. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + optional string format = 3; + + // description is a human readable description of this column. + optional string description = 4; + + // priority is an integer defining the relative importance of this column compared to others. Lower + // numbers are considered higher priority. Columns that may be omitted in limited space scenarios + // should be given a higher priority. + optional int32 priority = 5; + + // JSONPath is a simple JSON path, i.e. with array notation. + optional string JSONPath = 6; +} + // CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format // <.spec.name>.<.spec.group>. message CustomResourceDefinition { @@ -100,6 +125,10 @@ message CustomResourceDefinitionSpec { optional string group = 1; // Version is the version this resource belongs in + // Should be always first item in Versions field if provided. + // Optional, but at least one of Version or Versions must be set. + // Deprecated: Please use `Versions`. + // +optional optional string version = 2; // Names are the names used to describe this custom resource @@ -113,10 +142,24 @@ message CustomResourceDefinitionSpec { optional CustomResourceValidation validation = 5; // Subresources describes the subresources for CustomResources - // This field is alpha-level and should only be sent to servers that enable - // subresources via the CustomResourceSubresources feature gate. // +optional optional CustomResourceSubresources subresources = 6; + + // Versions is the list of all supported versions for this resource. + // If Version field is provided, this field is optional. + // Validation: All versions must use the same validation schema for now. i.e., top + // level Validation field is applied to all of these versions. + // Order: The version name will be used to compute the order. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing + // major version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. + repeated CustomResourceDefinitionVersion versions = 7; + + // AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column. + repeated CustomResourceColumnDefinition additionalPrinterColumns = 8; } // CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition @@ -127,6 +170,26 @@ message CustomResourceDefinitionStatus { // AcceptedNames are the names that are actually being used to serve discovery // They may be different than the names in spec. optional CustomResourceDefinitionNames acceptedNames = 2; + + // StoredVersions are all versions of CustomResources that were ever persisted. Tracking these + // versions allows a migration path for stored versions in etcd. The field is mutable + // so the migration controller can first finish a migration to another version (i.e. + // that no old objects are left in the storage), and then remove the rest of the + // versions from this list. + // None of the versions in this list can be removed from the spec.Versions field. + repeated string storedVersions = 3; +} + +message CustomResourceDefinitionVersion { + // Name is the version name, e.g. “v1”, “v2beta1”, etc. + optional string name = 1; + + // Served is a flag enabling/disabling this version from being served via REST APIs + optional bool served = 2; + + // Storage flags the version as storage version. There must be exactly one + // flagged as storage version. + optional bool storage = 3; } // CustomResourceSubresourceScale defines how to serve the scale subresource for CustomResources. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go index d8f9f164e..9a8fad3b7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go @@ -45,6 +45,7 @@ func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &sch); err != nil { return err } + nw.Allows = true nw.Schema = &sch case len(data) == 4 && string(data) == "true": nw.Allows = true diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go index 0c6d4d4b5..99065ff95 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go @@ -34,13 +34,13 @@ func TestJSONSchemaPropsOrBoolUnmarshalJSON(t *testing.T) { }{ {`{}`, JSONSchemaPropsOrBoolHolder{}}, - {`{"val1": {}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{}}}}, - {`{"val1": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{Type: "string"}}}}, + {`{"val1": {}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{}}}}, + {`{"val1": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{Type: "string"}}}}, {`{"val1": false}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{}}}, {`{"val1": true}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true}}}, - {`{"val2": {}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{}}}}, - {`{"val2": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{Type: "string"}}}}, + {`{"val2": {}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{}}}}, + {`{"val2": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{Type: "string"}}}}, {`{"val2": false}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{}}}, {`{"val2": true}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true}}}, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go index 3a4da9aea..2080cc821 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go @@ -25,7 +25,11 @@ type CustomResourceDefinitionSpec struct { // Group is the group this resource belongs in Group string `json:"group" protobuf:"bytes,1,opt,name=group"` // Version is the version this resource belongs in - Version string `json:"version" protobuf:"bytes,2,opt,name=version"` + // Should be always first item in Versions field if provided. + // Optional, but at least one of Version or Versions must be set. + // Deprecated: Please use `Versions`. + // +optional + Version string `json:"version,omitempty" protobuf:"bytes,2,opt,name=version"` // Names are the names used to describe this custom resource Names CustomResourceDefinitionNames `json:"names" protobuf:"bytes,3,opt,name=names"` // Scope indicates whether this resource is cluster or namespace scoped. Default is namespaced @@ -34,10 +38,54 @@ type CustomResourceDefinitionSpec struct { // +optional Validation *CustomResourceValidation `json:"validation,omitempty" protobuf:"bytes,5,opt,name=validation"` // Subresources describes the subresources for CustomResources - // This field is alpha-level and should only be sent to servers that enable - // subresources via the CustomResourceSubresources feature gate. // +optional Subresources *CustomResourceSubresources `json:"subresources,omitempty" protobuf:"bytes,6,opt,name=subresources"` + // Versions is the list of all supported versions for this resource. + // If Version field is provided, this field is optional. + // Validation: All versions must use the same validation schema for now. i.e., top + // level Validation field is applied to all of these versions. + // Order: The version name will be used to compute the order. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing + // major version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. + Versions []CustomResourceDefinitionVersion `json:"versions,omitempty" protobuf:"bytes,7,rep,name=versions"` + // AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column. + AdditionalPrinterColumns []CustomResourceColumnDefinition `json:"additionalPrinterColumns,omitempty" protobuf:"bytes,8,rep,name=additionalPrinterColumns"` +} + +type CustomResourceDefinitionVersion struct { + // Name is the version name, e.g. “v1”, “v2beta1”, etc. + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` + // Served is a flag enabling/disabling this version from being served via REST APIs + Served bool `json:"served" protobuf:"varint,2,opt,name=served"` + // Storage flags the version as storage version. There must be exactly one + // flagged as storage version. + Storage bool `json:"storage" protobuf:"varint,3,opt,name=storage"` +} + +// CustomResourceColumnDefinition specifies a column for server side printing. +type CustomResourceColumnDefinition struct { + // name is a human readable name for the column. + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` + // type is an OpenAPI type definition for this column. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Type string `json:"type" protobuf:"bytes,2,opt,name=type"` + // format is an optional OpenAPI type definition for this column. The 'name' format is applied + // to the primary identifier column to assist in clients identifying column is the resource name. + // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more. + Format string `json:"format,omitempty" protobuf:"bytes,3,opt,name=format"` + // description is a human readable description of this column. + Description string `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"` + // priority is an integer defining the relative importance of this column compared to others. Lower + // numbers are considered higher priority. Columns that may be omitted in limited space scenarios + // should be given a higher priority. + Priority int32 `json:"priority,omitempty" protobuf:"bytes,5,opt,name=priority"` + + // JSONPath is a simple JSON path, i.e. with array notation. + JSONPath string `json:"JSONPath" protobuf:"bytes,6,opt,name=JSONPath"` } // CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition @@ -119,6 +167,14 @@ type CustomResourceDefinitionStatus struct { // AcceptedNames are the names that are actually being used to serve discovery // They may be different than the names in spec. AcceptedNames CustomResourceDefinitionNames `json:"acceptedNames" protobuf:"bytes,2,opt,name=acceptedNames"` + + // StoredVersions are all versions of CustomResources that were ever persisted. Tracking these + // versions allows a migration path for stored versions in etcd. The field is mutable + // so the migration controller can first finish a migration to another version (i.e. + // that no old objects are left in the storage), and then remove the rest of the + // versions from this list. + // None of the versions in this list can be removed from the spec.Versions field. + StoredVersions []string `json:"storedVersions" protobuf:"bytes,3,rep,name=storedVersions"` } // CustomResourceCleanupFinalizer is the name of the finalizer which will delete instances of diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go index 9edd276d8..9776731cf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go @@ -62,6 +62,19 @@ type JSON struct { Raw []byte `protobuf:"bytes,1,opt,name=raw"` } +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ JSON) OpenAPISchemaType() []string { + // TODO: return actual types when anyOf is supported + return []string{} +} + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +func (_ JSON) OpenAPISchemaFormat() string { return "" } + // JSONSchemaURL represents a schema url. type JSONSchemaURL string @@ -72,6 +85,19 @@ type JSONSchemaPropsOrArray struct { JSONSchemas []JSONSchemaProps `protobuf:"bytes,2,rep,name=jSONSchemas"` } +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ JSONSchemaPropsOrArray) OpenAPISchemaType() []string { + // TODO: return actual types when anyOf is supported + return []string{} +} + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +func (_ JSONSchemaPropsOrArray) OpenAPISchemaFormat() string { return "" } + // JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value. // Defaults to true for the boolean property. type JSONSchemaPropsOrBool struct { @@ -79,6 +105,19 @@ type JSONSchemaPropsOrBool struct { Schema *JSONSchemaProps `protobuf:"bytes,2,opt,name=schema"` } +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ JSONSchemaPropsOrBool) OpenAPISchemaType() []string { + // TODO: return actual types when anyOf is supported + return []string{} +} + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +func (_ JSONSchemaPropsOrBool) OpenAPISchemaFormat() string { return "" } + // JSONSchemaDependencies represent a dependencies property. type JSONSchemaDependencies map[string]JSONSchemaPropsOrStringArray @@ -88,6 +127,19 @@ type JSONSchemaPropsOrStringArray struct { Property []string `protobuf:"bytes,2,rep,name=property"` } +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaType() []string { + // TODO: return actual types when anyOf is supported + return []string{} +} + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaFormat() string { return "" } + // JSONSchemaDefinitions contains the models explicitly defined in this spec. type JSONSchemaDefinitions map[string]JSONSchemaProps diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go index 6cd42fe5b..bcb2527c8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -36,6 +36,8 @@ func init() { // Public to allow building arbitrary schemes. func RegisterConversions(scheme *runtime.Scheme) error { return scheme.AddGeneratedConversionFuncs( + Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition, + Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition, Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition, Convert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition, Convert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition, @@ -48,6 +50,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomResourceDefinitionSpec, Convert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomResourceDefinitionStatus, Convert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus, + Convert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion, + Convert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion, Convert_v1beta1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale, Convert_apiextensions_CustomResourceSubresourceScale_To_v1beta1_CustomResourceSubresourceScale, Convert_v1beta1_CustomResourceSubresourceStatus_To_apiextensions_CustomResourceSubresourceStatus, @@ -71,6 +75,36 @@ func RegisterConversions(scheme *runtime.Scheme) error { ) } +func autoConvert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in *CustomResourceColumnDefinition, out *apiextensions.CustomResourceColumnDefinition, s conversion.Scope) error { + out.Name = in.Name + out.Type = in.Type + out.Format = in.Format + out.Description = in.Description + out.Priority = in.Priority + out.JSONPath = in.JSONPath + return nil +} + +// Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition is an autogenerated conversion function. +func Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in *CustomResourceColumnDefinition, out *apiextensions.CustomResourceColumnDefinition, s conversion.Scope) error { + return autoConvert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in, out, s) +} + +func autoConvert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in *apiextensions.CustomResourceColumnDefinition, out *CustomResourceColumnDefinition, s conversion.Scope) error { + out.Name = in.Name + out.Type = in.Type + out.Format = in.Format + out.Description = in.Description + out.Priority = in.Priority + out.JSONPath = in.JSONPath + return nil +} + +// Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition is an autogenerated conversion function. +func Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in *apiextensions.CustomResourceColumnDefinition, out *CustomResourceColumnDefinition, s conversion.Scope) error { + return autoConvert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in, out, s) +} + func autoConvert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(in *CustomResourceDefinition, out *apiextensions.CustomResourceDefinition, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(&in.Spec, &out.Spec, s); err != nil { @@ -220,6 +254,8 @@ func autoConvert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomRes out.Validation = nil } out.Subresources = (*apiextensions.CustomResourceSubresources)(unsafe.Pointer(in.Subresources)) + out.Versions = *(*[]apiextensions.CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions)) + out.AdditionalPrinterColumns = *(*[]apiextensions.CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns)) return nil } @@ -245,6 +281,8 @@ func autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomRes out.Validation = nil } out.Subresources = (*CustomResourceSubresources)(unsafe.Pointer(in.Subresources)) + out.Versions = *(*[]CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions)) + out.AdditionalPrinterColumns = *(*[]CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns)) return nil } @@ -258,6 +296,7 @@ func autoConvert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomR if err := Convert_v1beta1_CustomResourceDefinitionNames_To_apiextensions_CustomResourceDefinitionNames(&in.AcceptedNames, &out.AcceptedNames, s); err != nil { return err } + out.StoredVersions = *(*[]string)(unsafe.Pointer(&in.StoredVersions)) return nil } @@ -271,6 +310,7 @@ func autoConvert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomR if err := Convert_apiextensions_CustomResourceDefinitionNames_To_v1beta1_CustomResourceDefinitionNames(&in.AcceptedNames, &out.AcceptedNames, s); err != nil { return err } + out.StoredVersions = *(*[]string)(unsafe.Pointer(&in.StoredVersions)) return nil } @@ -279,6 +319,30 @@ func Convert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResou return autoConvert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus(in, out, s) } +func autoConvert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion(in *CustomResourceDefinitionVersion, out *apiextensions.CustomResourceDefinitionVersion, s conversion.Scope) error { + out.Name = in.Name + out.Served = in.Served + out.Storage = in.Storage + return nil +} + +// Convert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion is an autogenerated conversion function. +func Convert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion(in *CustomResourceDefinitionVersion, out *apiextensions.CustomResourceDefinitionVersion, s conversion.Scope) error { + return autoConvert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion(in, out, s) +} + +func autoConvert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion(in *apiextensions.CustomResourceDefinitionVersion, out *CustomResourceDefinitionVersion, s conversion.Scope) error { + out.Name = in.Name + out.Served = in.Served + out.Storage = in.Storage + return nil +} + +// Convert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion is an autogenerated conversion function. +func Convert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion(in *apiextensions.CustomResourceDefinitionVersion, out *CustomResourceDefinitionVersion, s conversion.Scope) error { + return autoConvert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion(in, out, s) +} + func autoConvert_v1beta1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale(in *CustomResourceSubresourceScale, out *apiextensions.CustomResourceSubresourceScale, s conversion.Scope) error { out.SpecReplicasPath = in.SpecReplicasPath out.StatusReplicasPath = in.StatusReplicasPath diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go index 35c3a0b75..d2c1cebf2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,22 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceColumnDefinition) DeepCopyInto(out *CustomResourceColumnDefinition) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceColumnDefinition. +func (in *CustomResourceColumnDefinition) DeepCopy() *CustomResourceColumnDefinition { + if in == nil { + return nil + } + out := new(CustomResourceColumnDefinition) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) { *out = *in @@ -150,6 +166,16 @@ func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefiniti (*in).DeepCopyInto(*out) } } + if in.Versions != nil { + in, out := &in.Versions, &out.Versions + *out = make([]CustomResourceDefinitionVersion, len(*in)) + copy(*out, *in) + } + if in.AdditionalPrinterColumns != nil { + in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns + *out = make([]CustomResourceColumnDefinition, len(*in)) + copy(*out, *in) + } return } @@ -174,6 +200,11 @@ func (in *CustomResourceDefinitionStatus) DeepCopyInto(out *CustomResourceDefini } } in.AcceptedNames.DeepCopyInto(&out.AcceptedNames) + if in.StoredVersions != nil { + in, out := &in.StoredVersions, &out.StoredVersions + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -187,6 +218,22 @@ func (in *CustomResourceDefinitionStatus) DeepCopy() *CustomResourceDefinitionSt return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceDefinitionVersion) DeepCopyInto(out *CustomResourceDefinitionVersion) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionVersion. +func (in *CustomResourceDefinitionVersion) DeepCopy() *CustomResourceDefinitionVersion { + if in == nil { + return nil + } + out := new(CustomResourceDefinitionVersion) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceSubresourceScale) DeepCopyInto(out *CustomResourceSubresourceScale) { *out = *in diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go index 546f33eda..f65f47a03 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/BUILD index b641b6093..c43365fe0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/BUILD @@ -15,6 +15,7 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/validation:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/features:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go index 713fcfa90..1179226dd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go @@ -22,6 +22,7 @@ import ( "strings" genericvalidation "k8s.io/apimachinery/pkg/api/validation" + "k8s.io/apimachinery/pkg/util/sets" validationutil "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -31,6 +32,11 @@ import ( apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" ) +var ( + printerColumnDatatypes = sets.NewString("integer", "number", "string", "boolean", "date") + customResourceColumnDefinitionFormats = sets.NewString("int32", "int64", "float", "double", "byte", "date", "date-time", "password") +) + // ValidateCustomResourceDefinition statically validates func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinition) field.ErrorList { nameValidationFn := func(name string, prefix bool) []string { @@ -45,6 +51,7 @@ func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinitio allErrs := genericvalidation.ValidateObjectMeta(&obj.ObjectMeta, false, nameValidationFn, field.NewPath("metadata")) allErrs = append(allErrs, ValidateCustomResourceDefinitionSpec(&obj.Spec, field.NewPath("spec"))...) allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...) + allErrs = append(allErrs, ValidateCustomResourceDefinitionStoredVersions(obj.Status.StoredVersions, obj.Spec.Versions, field.NewPath("status").Child("storedVersions"))...) return allErrs } @@ -53,6 +60,34 @@ func ValidateCustomResourceDefinitionUpdate(obj, oldObj *apiextensions.CustomRes allErrs := genericvalidation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &oldObj.ObjectMeta, field.NewPath("metadata")) allErrs = append(allErrs, ValidateCustomResourceDefinitionSpecUpdate(&obj.Spec, &oldObj.Spec, apiextensions.IsCRDConditionTrue(oldObj, apiextensions.Established), field.NewPath("spec"))...) allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...) + allErrs = append(allErrs, ValidateCustomResourceDefinitionStoredVersions(obj.Status.StoredVersions, obj.Spec.Versions, field.NewPath("status").Child("storedVersions"))...) + return allErrs +} + +// ValidateCustomResourceDefinitionStoredVersions statically validates +func ValidateCustomResourceDefinitionStoredVersions(storedVersions []string, versions []apiextensions.CustomResourceDefinitionVersion, fldPath *field.Path) field.ErrorList { + if len(storedVersions) == 0 { + return field.ErrorList{field.Invalid(fldPath, storedVersions, "must have at least one stored version")} + } + allErrs := field.ErrorList{} + storedVersionsMap := map[string]int{} + for i, v := range storedVersions { + storedVersionsMap[v] = i + } + for _, v := range versions { + _, ok := storedVersionsMap[v.Name] + if v.Storage && !ok { + allErrs = append(allErrs, field.Invalid(fldPath, v, "must have the storage version "+v.Name)) + } + if ok { + delete(storedVersionsMap, v.Name) + } + } + + for v, i := range storedVersionsMap { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i), v, "must appear in spec.versions")) + } + return allErrs } @@ -75,12 +110,6 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi allErrs = append(allErrs, field.Invalid(fldPath.Child("group"), spec.Group, "should be a domain with at least one dot")) } - if len(spec.Version) == 0 { - allErrs = append(allErrs, field.Required(fldPath.Child("version"), "")) - } else if errs := validationutil.IsDNS1035Label(spec.Version); len(errs) > 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, strings.Join(errs, ","))) - } - switch spec.Scope { case "": allErrs = append(allErrs, field.Required(fldPath.Child("scope"), "")) @@ -89,6 +118,37 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi allErrs = append(allErrs, field.NotSupported(fldPath.Child("scope"), spec.Scope, []string{string(apiextensions.ClusterScoped), string(apiextensions.NamespaceScoped)})) } + storageFlagCount := 0 + versionsMap := map[string]bool{} + uniqueNames := true + for i, version := range spec.Versions { + if version.Storage { + storageFlagCount++ + } + if versionsMap[version.Name] { + uniqueNames = false + } else { + versionsMap[version.Name] = true + } + if errs := validationutil.IsDNS1035Label(version.Name); len(errs) > 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("versions").Index(i).Child("name"), spec.Versions[i].Name, strings.Join(errs, ","))) + } + } + if !uniqueNames { + allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "must contain unique version names")) + } + if storageFlagCount != 1 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "must have exactly one version marked as storage version")) + } + if len(spec.Version) != 0 { + if errs := validationutil.IsDNS1035Label(spec.Version); len(errs) > 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, strings.Join(errs, ","))) + } + if len(spec.Versions) >= 1 && spec.Versions[0].Name != spec.Version { + allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, "must match the first version in spec.versions")) + } + } + // in addition to the basic name restrictions, some names are required for spec, but not for status if len(spec.Names.Plural) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("names", "plural"), "")) @@ -106,7 +166,11 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi allErrs = append(allErrs, ValidateCustomResourceDefinitionNames(&spec.Names, fldPath.Child("names"))...) if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) { - allErrs = append(allErrs, ValidateCustomResourceDefinitionValidation(spec.Validation, fldPath.Child("validation"))...) + statusEnabled := false + if spec.Subresources != nil && spec.Subresources.Status != nil { + statusEnabled = true + } + allErrs = append(allErrs, ValidateCustomResourceDefinitionValidation(spec.Validation, statusEnabled, fldPath.Child("validation"))...) } else if spec.Validation != nil { allErrs = append(allErrs, field.Forbidden(fldPath.Child("validation"), "disabled by feature-gate CustomResourceValidation")) } @@ -117,6 +181,12 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi allErrs = append(allErrs, field.Forbidden(fldPath.Child("subresources"), "disabled by feature-gate CustomResourceSubresources")) } + for i := range spec.AdditionalPrinterColumns { + if errs := ValidateCustomResourceColumnDefinition(&spec.AdditionalPrinterColumns[i], fldPath.Child("columns").Index(i)); len(errs) > 0 { + allErrs = append(allErrs, errs...) + } + } + return allErrs } @@ -126,7 +196,6 @@ func ValidateCustomResourceDefinitionSpecUpdate(spec, oldSpec *apiextensions.Cus if established { // these effect the storage and cannot be changed therefore - allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Version, oldSpec.Version, fldPath.Child("version"))...) allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Scope, oldSpec.Scope, fldPath.Child("scope"))...) allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Names.Kind, oldSpec.Names.Kind, fldPath.Child("names", "kind"))...) } @@ -181,13 +250,40 @@ func ValidateCustomResourceDefinitionNames(names *apiextensions.CustomResourceDe return allErrs } +// ValidateCustomResourceColumnDefinition statically validates a printer column. +func ValidateCustomResourceColumnDefinition(col *apiextensions.CustomResourceColumnDefinition, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if len(col.Name) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("header"), "")) + } + + if len(col.Type) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("type"), fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ",")))) + } else if !printerColumnDatatypes.Has(col.Type) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), col.Type, fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ",")))) + } + + if len(col.Format) > 0 && !customResourceColumnDefinitionFormats.Has(col.Format) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("format"), col.Format, fmt.Sprintf("must be one of %s", strings.Join(customResourceColumnDefinitionFormats.List(), ",")))) + } + + if len(col.JSONPath) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("path"), "")) + } else if errs := validateSimpleJSONPath(col.JSONPath, fldPath.Child("path")); len(errs) > 0 { + allErrs = append(allErrs, errs...) + } + + return allErrs +} + // specStandardValidator applies validations for different OpenAPI specification versions. type specStandardValidator interface { validate(spec *apiextensions.JSONSchemaProps, fldPath *field.Path) field.ErrorList } // ValidateCustomResourceDefinitionValidation statically validates -func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiextensions.CustomResourceValidation, fldPath *field.Path) field.ErrorList { +func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiextensions.CustomResourceValidation, statusSubresourceEnabled bool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if customResourceValidation == nil { @@ -195,21 +291,19 @@ func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiext } if schema := customResourceValidation.OpenAPIV3Schema; schema != nil { - // if subresources are enabled, only properties is allowed inside the root schema - if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) { + // if subresources are enabled, only "properties", "required" and "description" are allowed inside the root schema + if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && statusSubresourceEnabled { v := reflect.ValueOf(schema).Elem() - fieldsPresent := 0 - for i := 0; i < v.NumField(); i++ { - field := v.Field(i).Interface() - if !reflect.DeepEqual(field, reflect.Zero(reflect.TypeOf(field)).Interface()) { - fieldsPresent++ + // skip zero values + if value := v.Field(i).Interface(); reflect.DeepEqual(value, reflect.Zero(reflect.TypeOf(value)).Interface()) { + continue } - } - if fieldsPresent > 1 || (fieldsPresent == 1 && v.FieldByName("Properties").IsNil()) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), *schema, fmt.Sprintf("if subresources for custom resources are enabled, only properties can be used at the root of the schema"))) - return allErrs + if name := v.Type().Field(i).Name; name != "Properties" && name != "Required" && name != "Description" { + allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), *schema, fmt.Sprintf(`must only have "properties", "required" or "description" at the root if the status subresource is enabled`))) + break + } } } @@ -240,14 +334,36 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch allErrs = append(allErrs, field.Forbidden(fldPath.Child("uniqueItems"), "uniqueItems cannot be set to true since the runtime complexity becomes quadratic")) } - // additionalProperties contradicts Kubernetes API convention to ignore unknown fields + // additionalProperties and properties are mutual exclusive because otherwise they + // contradict Kubernetes' API convention to ignore unknown fields. + // + // In other words: + // - properties are for structs, + // - additionalProperties are for map[string]interface{} + // + // Note: when patternProperties is added to OpenAPI some day, this will have to be + // restricted like additionalProperties. if schema.AdditionalProperties != nil { - if schema.AdditionalProperties.Allows == false { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalProperties"), "additionalProperties cannot be set to false")) + if len(schema.Properties) != 0 { + if schema.AdditionalProperties.Allows == false || schema.AdditionalProperties.Schema != nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalProperties"), "additionalProperties and properties are mutual exclusive")) + } } allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.AdditionalProperties.Schema, fldPath.Child("additionalProperties"), ssv)...) } + if len(schema.Properties) != 0 { + for property, jsonSchema := range schema.Properties { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("properties").Key(property), ssv)...) + } + } + + if len(schema.PatternProperties) != 0 { + for property, jsonSchema := range schema.PatternProperties { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("patternProperties").Key(property), ssv)...) + } + } + if schema.AdditionalItems != nil { allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.AdditionalItems.Schema, fldPath.Child("additionalItems"), ssv)...) } @@ -255,32 +371,20 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.Not, fldPath.Child("not"), ssv)...) if len(schema.AllOf) != 0 { - for _, jsonSchema := range schema.AllOf { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("allOf"), ssv)...) + for i, jsonSchema := range schema.AllOf { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("allOf").Index(i), ssv)...) } } if len(schema.OneOf) != 0 { - for _, jsonSchema := range schema.OneOf { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("oneOf"), ssv)...) + for i, jsonSchema := range schema.OneOf { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("oneOf").Index(i), ssv)...) } } if len(schema.AnyOf) != 0 { - for _, jsonSchema := range schema.AnyOf { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("anyOf"), ssv)...) - } - } - - if len(schema.Properties) != 0 { - for property, jsonSchema := range schema.Properties { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("properties").Key(property), ssv)...) - } - } - - if len(schema.PatternProperties) != 0 { - for property, jsonSchema := range schema.PatternProperties { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("patternProperties").Key(property), ssv)...) + for i, jsonSchema := range schema.AnyOf { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("anyOf").Index(i), ssv)...) } } @@ -293,8 +397,8 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch if schema.Items != nil { allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.Items.Schema, fldPath.Child("items"), ssv)...) if len(schema.Items.JSONSchemas) != 0 { - for _, jsonSchema := range schema.Items.JSONSchemas { - allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("items"), ssv)...) + for i, jsonSchema := range schema.Items.JSONSchemas { + allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("items").Index(i), ssv)...) } } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go index dd712c94f..68dc8aaed 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go @@ -41,17 +41,159 @@ func unsupported(path ...string) validationMatch { func immutable(path ...string) validationMatch { return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeInvalid} } +func forbidden(path ...string) validationMatch { + return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeForbidden} +} func (v validationMatch) matches(err *field.Error) bool { return err.Type == v.errorType && err.Field == v.path.String() } func TestValidateCustomResourceDefinition(t *testing.T) { + singleVersionList := []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + } tests := []struct { name string resource *apiextensions.CustomResourceDefinition errors []validationMatch }{ + { + name: "no_storage_version", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: false, + }, + { + Name: "version2", + Served: true, + Storage: false, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{ + invalid("spec", "versions"), + }, + }, + { + name: "multiple_storage_version", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + { + Name: "version2", + Served: true, + Storage: true, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{ + invalid("spec", "versions"), + invalid("status", "storedVersions"), + }, + }, + { + name: "missing_storage_version_in_stored_versions", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: false, + }, + { + Name: "version2", + Served: true, + Storage: true, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{ + invalid("status", "storedVersions"), + }, + }, + { + name: "empty_stored_version", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{}, + }, + }, + errors: []validationMatch{ + invalid("status", "storedVersions"), + }, + }, { name: "mismatched name", resource: &apiextensions.CustomResourceDefinition{ @@ -64,8 +206,9 @@ func TestValidateCustomResourceDefinition(t *testing.T) { }, }, errors: []validationMatch{ + invalid("status", "storedVersions"), invalid("metadata", "name"), - required("spec", "version"), + invalid("spec", "versions"), required("spec", "scope"), required("spec", "names", "singular"), required("spec", "names", "kind"), @@ -78,9 +221,10 @@ func TestValidateCustomResourceDefinition(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, }, errors: []validationMatch{ + invalid("status", "storedVersions"), invalid("metadata", "name"), + invalid("spec", "versions"), required("spec", "group"), - required("spec", "version"), required("spec", "scope"), required("spec", "names", "plural"), required("spec", "names", "singular"), @@ -113,9 +257,9 @@ func TestValidateCustomResourceDefinition(t *testing.T) { }, }, errors: []validationMatch{ + invalid("status", "storedVersions"), invalid("metadata", "name"), invalid("spec", "group"), - invalid("spec", "version"), unsupported("spec", "scope"), invalid("spec", "names", "plural"), invalid("spec", "names", "singular"), @@ -127,6 +271,8 @@ func TestValidateCustomResourceDefinition(t *testing.T) { invalid("status", "acceptedNames", "kind"), invalid("status", "acceptedNames", "listKind"), // invalid format invalid("status", "acceptedNames", "listKind"), // kind == listKind + invalid("spec", "versions"), + invalid("spec", "version"), }, }, { @@ -134,8 +280,9 @@ func TestValidateCustomResourceDefinition(t *testing.T) { resource: &apiextensions.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "plural.group"}, Spec: apiextensions.CustomResourceDefinitionSpec{ - Group: "group.c(*&om", - Version: "version", + Group: "group.c(*&om", + Version: "version", + Versions: singleVersionList, Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -150,6 +297,7 @@ func TestValidateCustomResourceDefinition(t *testing.T) { Kind: "matching", ListKind: "matching", }, + StoredVersions: []string{"version"}, }, }, errors: []validationMatch{ @@ -160,6 +308,70 @@ func TestValidateCustomResourceDefinition(t *testing.T) { invalid("status", "acceptedNames", "listKind"), }, }, + { + name: "additionalProperties and properties forbidden", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Versions: singleVersionList, + Scope: apiextensions.NamespaceScoped, + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Validation: &apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + Properties: map[string]apiextensions.JSONSchemaProps{ + "foo": {}, + }, + AdditionalProperties: &apiextensions.JSONSchemaPropsOrBool{Allows: false}, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{ + forbidden("spec", "validation", "openAPIV3Schema", "additionalProperties"), + }, + }, + { + name: "additionalProperties without properties allowed (map[string]string)", + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Versions: singleVersionList, + Scope: apiextensions.NamespaceScoped, + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "Plural", + ListKind: "PluralList", + }, + Validation: &apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + AdditionalProperties: &apiextensions.JSONSchemaPropsOrBool{ + Allows: true, + Schema: &apiextensions.JSONSchemaProps{ + Type: "string", + }, + }, + }, + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + StoredVersions: []string{"version"}, + }, + }, + errors: []validationMatch{}, + }, } for _, tc := range tests { @@ -206,7 +418,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -231,7 +450,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -246,6 +472,7 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Kind: "kind", ListKind: "listkind", }, + StoredVersions: []string{"version"}, }, }, errors: []validationMatch{}, @@ -260,7 +487,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -288,7 +522,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -303,10 +544,91 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Kind: "kind", ListKind: "listkind", }, + StoredVersions: []string{"version"}, }, }, errors: []validationMatch{}, }, + { + name: "version-deleted", + old: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "plural.group.com", + ResourceVersion: "42", + }, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + { + Name: "version2", + Served: true, + Storage: false, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + AcceptedNames: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + StoredVersions: []string{"version", "version2"}, + Conditions: []apiextensions.CustomResourceDefinitionCondition{ + {Type: apiextensions.Established, Status: apiextensions.ConditionTrue}, + }, + }, + }, + resource: &apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "plural.group.com", + ResourceVersion: "42", + }, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "group.com", + Version: "version", + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + }, + Status: apiextensions.CustomResourceDefinitionStatus{ + AcceptedNames: apiextensions.CustomResourceDefinitionNames{ + Plural: "plural", + Singular: "singular", + Kind: "kind", + ListKind: "listkind", + }, + StoredVersions: []string{"version", "version2"}, + }, + }, + errors: []validationMatch{ + invalid("status", "storedVersions[1]"), + }, + }, { name: "changes", old: &apiextensions.CustomResourceDefinition{ @@ -317,7 +639,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -345,7 +674,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "abc.com", Version: "version2", - Scope: apiextensions.ResourceScope("Namespaced"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version2", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Namespaced"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural2", Singular: "singular2", @@ -360,6 +696,7 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Kind: "kind2", ListKind: "listkind2", }, + StoredVersions: []string{"version2"}, }, }, errors: []validationMatch{ @@ -377,7 +714,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "group.com", Version: "version", - Scope: apiextensions.ResourceScope("Cluster"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Cluster"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural", Singular: "singular", @@ -405,7 +749,14 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Spec: apiextensions.CustomResourceDefinitionSpec{ Group: "abc.com", Version: "version2", - Scope: apiextensions.ResourceScope("Namespaced"), + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "version2", + Served: true, + Storage: true, + }, + }, + Scope: apiextensions.ResourceScope("Namespaced"), Names: apiextensions.CustomResourceDefinitionNames{ Plural: "plural2", Singular: "singular2", @@ -420,11 +771,11 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { Kind: "kind2", ListKind: "listkind2", }, + StoredVersions: []string{"version2"}, }, }, errors: []validationMatch{ immutable("spec", "group"), - immutable("spec", "version"), immutable("spec", "scope"), immutable("spec", "names", "kind"), immutable("spec", "names", "plural"), @@ -458,3 +809,69 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) { } } } + +func TestValidateCustomResourceDefinitionValidation(t *testing.T) { + tests := []struct { + name string + input apiextensions.CustomResourceValidation + statusEnabled bool + wantError bool + }{ + { + name: "empty", + input: apiextensions.CustomResourceValidation{}, + wantError: false, + }, + { + name: "empty with status", + input: apiextensions.CustomResourceValidation{}, + statusEnabled: true, + wantError: false, + }, + { + name: "root type without status", + input: apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + Type: "object", + }, + }, + statusEnabled: false, + wantError: false, + }, + { + name: "root type with status", + input: apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + Type: "object", + }, + }, + statusEnabled: true, + wantError: true, + }, + { + name: "properties, required and description with status", + input: apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{ + Properties: map[string]apiextensions.JSONSchemaProps{ + "spec": {}, + "status": {}, + }, + Required: []string{"spec", "status"}, + Description: "This is a description", + }, + }, + statusEnabled: true, + wantError: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := ValidateCustomResourceDefinitionValidation(&tt.input, tt.statusEnabled, field.NewPath("spec", "validation")) + if !tt.wantError && len(got) > 0 { + t.Errorf("Expected no error, but got: %v", got) + } else if tt.wantError && len(got) == 0 { + t.Error("Expected error, but got none") + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go index ea3af6976..145b3c5d7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,22 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceColumnDefinition) DeepCopyInto(out *CustomResourceColumnDefinition) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceColumnDefinition. +func (in *CustomResourceColumnDefinition) DeepCopy() *CustomResourceColumnDefinition { + if in == nil { + return nil + } + out := new(CustomResourceColumnDefinition) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) { *out = *in @@ -150,6 +166,16 @@ func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefiniti (*in).DeepCopyInto(*out) } } + if in.Versions != nil { + in, out := &in.Versions, &out.Versions + *out = make([]CustomResourceDefinitionVersion, len(*in)) + copy(*out, *in) + } + if in.AdditionalPrinterColumns != nil { + in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns + *out = make([]CustomResourceColumnDefinition, len(*in)) + copy(*out, *in) + } return } @@ -174,6 +200,11 @@ func (in *CustomResourceDefinitionStatus) DeepCopyInto(out *CustomResourceDefini } } in.AcceptedNames.DeepCopyInto(&out.AcceptedNames) + if in.StoredVersions != nil { + in, out := &in.StoredVersions, &out.StoredVersions + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -187,6 +218,22 @@ func (in *CustomResourceDefinitionStatus) DeepCopy() *CustomResourceDefinitionSt return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceDefinitionVersion) DeepCopyInto(out *CustomResourceDefinitionVersion) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionVersion. +func (in *CustomResourceDefinitionVersion) DeepCopy() *CustomResourceDefinitionVersion { + if in == nil { + return nil + } + out := new(CustomResourceDefinitionVersion) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomResourceSubresourceScale) DeepCopyInto(out *CustomResourceSubresourceScale) { *out = *in diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/BUILD index 09d21156d..e405af28e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/BUILD @@ -15,6 +15,7 @@ go_library( "customresource_handler.go", ], importpath = "k8s.io/apiextensions-apiserver/pkg/apiserver", + visibility = ["//visibility:public"], deps = [ "//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/github.com/go-openapi/strfmt:go_default_library", @@ -24,6 +25,7 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/validation:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset:go_default_library", @@ -31,6 +33,7 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/controller/establish:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/controller/finalizer:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/controller/status:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/features:go_default_library", @@ -40,8 +43,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", @@ -75,6 +76,30 @@ go_library( ], ) +go_test( + name = "go_default_test", + srcs = [ + "customresource_handler_test.go", + "jsonpath_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", + ], +) + filegroup( name = "package-srcs", srcs = glob(["**"]), @@ -86,14 +111,9 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion:all-srcs", "//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation:all-srcs", ], tags = ["automanaged"], -) - -go_test( - name = "go_default_test", - srcs = ["customresource_handler_test.go"], - embed = [":go_default_library"], - deps = ["//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library"], + visibility = ["//visibility:public"], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go index 1415ff8d9..f1fc89ba9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go @@ -19,13 +19,8 @@ package apiserver import ( "fmt" "net/http" - "os" "time" - "github.com/golang/glog" - - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -42,21 +37,19 @@ import ( "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset" internalinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion" + "k8s.io/apiextensions-apiserver/pkg/controller/establish" "k8s.io/apiextensions-apiserver/pkg/controller/finalizer" "k8s.io/apiextensions-apiserver/pkg/controller/status" "k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition" - // make sure the generated client works _ "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" _ "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions" _ "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion" ) var ( - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - Registry = registered.NewOrDie("") - Scheme = runtime.NewScheme() - Codecs = serializer.NewCodecFactory(Scheme) + Scheme = runtime.NewScheme() + Codecs = serializer.NewCodecFactory(Scheme) // if you modify this, make sure you update the crEncoder unversionedVersion = schema.GroupVersion{Group: "", Version: "v1"} @@ -71,7 +64,7 @@ var ( ) func init() { - install.Install(groupFactoryRegistry, Registry, Scheme) + install.Install(Scheme) // we need to add the options to empty v1 metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Group: "", Version: "v1"}) @@ -81,6 +74,10 @@ func init() { type ExtraConfig struct { CRDRESTOptionsGetter genericregistry.RESTOptionsGetter + + // MasterCount is used to detect whether cluster is HA, and if it is + // the CRD Establishing will be hold by 5 seconds. + MasterCount int } type Config struct { @@ -133,9 +130,8 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) } apiResourceConfig := c.GenericConfig.MergedResourceConfig - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiextensions.GroupName, Registry, Scheme, metav1.ParameterCodec, Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiextensions.GroupName, Scheme, metav1.ParameterCodec, Codecs) if apiResourceConfig.VersionEnabled(v1beta1.SchemeGroupVersion) { - apiGroupInfo.GroupMeta.GroupVersion = v1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} // customresourcedefinitions customResourceDefintionStorage := customresourcedefinition.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter) @@ -153,16 +149,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) if err != nil { // it's really bad that this is leaking here, but until we can fix the test (which I'm pretty sure isn't even testing what it wants to test), // we need to be able to move forward - kubeAPIVersions := os.Getenv("KUBE_API_VERSIONS") - if len(kubeAPIVersions) == 0 { - return nil, fmt.Errorf("failed to create clientset: %v", err) - } - - // KUBE_API_VERSIONS is used in test-update-storage-objects.sh, disabling a number of API - // groups. This leads to a nil client above and undefined behaviour further down. - // - // TODO: get rid of KUBE_API_VERSIONS or define sane behaviour if set - glog.Errorf("Failed to create clientset with KUBE_API_VERSIONS=%q. KUBE_API_VERSIONS is only for testing. Things will break.", kubeAPIVersions) + return nil, fmt.Errorf("failed to create clientset: %v", err) } s.Informers = internalinformers.NewSharedInformerFactory(crdClient, 5*time.Minute) @@ -179,24 +166,21 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) discovery: map[string]*discovery.APIGroupHandler{}, delegate: delegateHandler, } + establishingController := establish.NewEstablishingController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), crdClient.Apiextensions()) crdHandler := NewCustomResourceDefinitionHandler( versionDiscoveryHandler, groupDiscoveryHandler, - s.GenericAPIServer.RequestContextMapper(), s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), delegateHandler, c.ExtraConfig.CRDRESTOptionsGetter, c.GenericConfig.AdmissionControl, + establishingController, + c.ExtraConfig.MasterCount, ) s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", crdHandler) s.GenericAPIServer.Handler.NonGoRestfulMux.HandlePrefix("/apis/", crdHandler) - // this only happens when KUBE_API_VERSIONS is set. We must return without adding controllers or poststarthooks which would affect healthz - if crdClient == nil { - return s, nil - } - - crdController := NewDiscoveryController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), versionDiscoveryHandler, groupDiscoveryHandler, c.GenericConfig.RequestContextMapper) + crdController := NewDiscoveryController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), versionDiscoveryHandler, groupDiscoveryHandler) namingController := status.NewNamingConditionController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), crdClient.Apiextensions()) finalizingController := finalizer.NewCRDFinalizer( s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), @@ -211,6 +195,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) s.GenericAPIServer.AddPostStartHook("start-apiextensions-controllers", func(context genericapiserver.PostStartHookContext) error { go crdController.Run(context.StopCh) go namingController.Run(context.StopCh) + go establishingController.Run(context.StopCh) go finalizingController.Run(5, context.StopCh) return nil }) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/BUILD new file mode 100644 index 000000000..6eff75181 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "converter.go", + "nop_converter.go", + ], + importpath = "k8s.io/apiextensions-apiserver/pkg/apiserver/conversion", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/converter.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/converter.go new file mode 100644 index 000000000..69f5340a9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/converter.go @@ -0,0 +1,117 @@ +/* +Copyright 2018 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 conversion + +import ( + "fmt" + + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// NewCRDConverter returns a new CRD converter based on the conversion settings in crd object. +func NewCRDConverter(crd *apiextensions.CustomResourceDefinition) (safe, unsafe runtime.ObjectConvertor) { + validVersions := map[schema.GroupVersion]bool{} + for _, version := range crd.Spec.Versions { + validVersions[schema.GroupVersion{Group: crd.Spec.Group, Version: version.Name}] = true + } + + // The only converter right now is nopConverter. More converters will be returned based on the + // CRD object when they introduced. + unsafe = &crdConverter{ + clusterScoped: crd.Spec.Scope == apiextensions.ClusterScoped, + delegate: &nopConverter{ + validVersions: validVersions, + }, + } + return &safeConverterWrapper{unsafe}, unsafe +} + +var _ runtime.ObjectConvertor = &crdConverter{} + +// crdConverter extends the delegate with generic CRD conversion behaviour. The delegate will implement the +// user defined conversion strategy given in the CustomResourceDefinition. +type crdConverter struct { + delegate runtime.ObjectConvertor + clusterScoped bool +} + +func (c *crdConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + // We currently only support metadata.namespace and metadata.name. + switch { + case label == "metadata.name": + return label, value, nil + case !c.clusterScoped && label == "metadata.namespace": + return label, value, nil + default: + return "", "", fmt.Errorf("field label not supported: %s", label) + } +} + +func (c *crdConverter) Convert(in, out, context interface{}) error { + return c.delegate.Convert(in, out, context) +} + +// ConvertToVersion converts in object to the given gvk in place and returns the same `in` object. +func (c *crdConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { + // Run the converter on the list items instead of list itself + if list, ok := in.(*unstructured.UnstructuredList); ok { + for i := range list.Items { + obj, err := c.delegate.ConvertToVersion(&list.Items[i], target) + if err != nil { + return nil, err + } + + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return nil, fmt.Errorf("output type %T in not valid for unstructured conversion", obj) + } + list.Items[i] = *u + } + return list, nil + } + + return c.delegate.ConvertToVersion(in, target) +} + +// safeConverterWrapper is a wrapper over an unsafe object converter that makes copy of the input and then delegate to the unsafe converter. +type safeConverterWrapper struct { + unsafe runtime.ObjectConvertor +} + +var _ runtime.ObjectConvertor = &nopConverter{} + +// ConvertFieldLabel delegate the call to the unsafe converter. +func (c *safeConverterWrapper) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + return c.unsafe.ConvertFieldLabel(version, kind, label, value) +} + +// Convert makes a copy of in object and then delegate the call to the unsafe converter. +func (c *safeConverterWrapper) Convert(in, out, context interface{}) error { + inObject, ok := in.(runtime.Object) + if !ok { + return fmt.Errorf("input type %T in not valid for object conversion", in) + } + return c.unsafe.Convert(inObject.DeepCopyObject(), out, context) +} + +// ConvertToVersion makes a copy of in object and then delegate the call to the unsafe converter. +func (c *safeConverterWrapper) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { + return c.unsafe.ConvertToVersion(in.DeepCopyObject(), target) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/nop_converter.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/nop_converter.go new file mode 100644 index 000000000..716930bfb --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/nop_converter.go @@ -0,0 +1,79 @@ +/* +Copyright 2018 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 conversion + +import ( + "errors" + "fmt" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// nopConverter is a converter that only sets the apiVersion fields, but does not real conversion. +type nopConverter struct { + validVersions map[schema.GroupVersion]bool +} + +var _ runtime.ObjectConvertor = &nopConverter{} + +func (nopConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + return "", "", errors.New("unstructured cannot convert field labels") +} + +func (c *nopConverter) Convert(in, out, context interface{}) error { + unstructIn, ok := in.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("input type %T in not valid for unstructured conversion", in) + } + + unstructOut, ok := out.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("output type %T in not valid for unstructured conversion", out) + } + + outGVK := unstructOut.GroupVersionKind() + if !c.validVersions[outGVK.GroupVersion()] { + return fmt.Errorf("request to convert CRD from an invalid group/version: %s", outGVK.String()) + } + inGVK := unstructIn.GroupVersionKind() + if !c.validVersions[inGVK.GroupVersion()] { + return fmt.Errorf("request to convert CRD to an invalid group/version: %s", inGVK.String()) + } + + unstructOut.SetUnstructuredContent(unstructIn.UnstructuredContent()) + _, err := c.ConvertToVersion(unstructOut, outGVK.GroupVersion()) + if err != nil { + return err + } + return nil +} + +func (c *nopConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { + kind := in.GetObjectKind().GroupVersionKind() + gvk, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{kind}) + if !ok { + // TODO: should this be a typed error? + return nil, fmt.Errorf("%v is unstructured and is not suitable for converting to %q", kind, target) + } + if !c.validVersions[gvk.GroupVersion()] { + return nil, fmt.Errorf("request to convert CRD to an invalid group/version: %s", gvk.String()) + } + in.GetObjectKind().SetGroupVersionKind(gvk) + return in, nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go index b180e105b..e3b3d0a44 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go @@ -18,6 +18,7 @@ package apiserver import ( "fmt" + "sort" "time" "github.com/golang/glog" @@ -28,8 +29,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/version" "k8s.io/apiserver/pkg/endpoints/discovery" - "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" @@ -41,7 +42,6 @@ import ( type DiscoveryController struct { versionHandler *versionDiscoveryHandler groupHandler *groupDiscoveryHandler - contextMapper request.RequestContextMapper crdLister listers.CustomResourceDefinitionLister crdsSynced cache.InformerSynced @@ -52,13 +52,12 @@ type DiscoveryController struct { queue workqueue.RateLimitingInterface } -func NewDiscoveryController(crdInformer informers.CustomResourceDefinitionInformer, versionHandler *versionDiscoveryHandler, groupHandler *groupDiscoveryHandler, contextMapper request.RequestContextMapper) *DiscoveryController { +func NewDiscoveryController(crdInformer informers.CustomResourceDefinitionInformer, versionHandler *versionDiscoveryHandler, groupHandler *groupDiscoveryHandler) *DiscoveryController { c := &DiscoveryController{ versionHandler: versionHandler, groupHandler: groupHandler, crdLister: crdInformer.Lister(), crdsSynced: crdInformer.Informer().HasSynced, - contextMapper: contextMapper, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "DiscoveryController"), } @@ -78,6 +77,7 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error { apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{} apiResourcesForDiscovery := []metav1.APIResource{} + versionsForDiscoveryMap := map[metav1.GroupVersion]bool{} crds, err := c.crdLister.List(labels.Everything()) if err != nil { @@ -93,13 +93,29 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error { if crd.Spec.Group != version.Group { continue } - foundGroup = true - apiVersionsForDiscovery = append(apiVersionsForDiscovery, metav1.GroupVersionForDiscovery{ - GroupVersion: crd.Spec.Group + "/" + crd.Spec.Version, - Version: crd.Spec.Version, - }) - if crd.Spec.Version != version.Version { + foundThisVersion := false + for _, v := range crd.Spec.Versions { + if !v.Served { + continue + } + // If there is any Served version, that means the group should show up in discovery + foundGroup = true + + gv := metav1.GroupVersion{Group: crd.Spec.Group, Version: v.Name} + if !versionsForDiscoveryMap[gv] { + versionsForDiscoveryMap[gv] = true + apiVersionsForDiscovery = append(apiVersionsForDiscovery, metav1.GroupVersionForDiscovery{ + GroupVersion: crd.Spec.Group + "/" + v.Name, + Version: v.Name, + }) + } + if v.Name == version.Version { + foundThisVersion = true + } + } + + if !foundThisVersion { continue } foundVersion = true @@ -147,13 +163,16 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error { return nil } + sortGroupDiscoveryByKubeAwareVersion(apiVersionsForDiscovery) + apiGroup := metav1.APIGroup{ Name: version.Group, Versions: apiVersionsForDiscovery, - // the preferred versions for a group is arbitrary since there cannot be duplicate resources + // the preferred versions for a group is the first item in + // apiVersionsForDiscovery after it put in the right ordered PreferredVersion: apiVersionsForDiscovery[0], } - c.groupHandler.setDiscovery(version.Group, discovery.NewAPIGroupHandler(Codecs, apiGroup, c.contextMapper)) + c.groupHandler.setDiscovery(version.Group, discovery.NewAPIGroupHandler(Codecs, apiGroup)) if !foundVersion { c.versionHandler.unsetDiscovery(version) @@ -161,11 +180,17 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error { } c.versionHandler.setDiscovery(version, discovery.NewAPIVersionHandler(Codecs, version, discovery.APIResourceListerFunc(func() []metav1.APIResource { return apiResourcesForDiscovery - }), c.contextMapper)) + }))) return nil } +func sortGroupDiscoveryByKubeAwareVersion(gd []metav1.GroupVersionForDiscovery) { + sort.Slice(gd, func(i, j int) bool { + return version.CompareKubeAwareVersionStrings(gd[i].Version, gd[j].Version) > 0 + }) +} + func (c *DiscoveryController) Run(stopCh <-chan struct{}) { defer utilruntime.HandleCrash() defer c.queue.ShutDown() @@ -210,7 +235,9 @@ func (c *DiscoveryController) processNextWorkItem() bool { } func (c *DiscoveryController) enqueue(obj *apiextensions.CustomResourceDefinition) { - c.queue.Add(schema.GroupVersion{Group: obj.Spec.Group, Version: obj.Spec.Version}) + for _, v := range obj.Spec.Versions { + c.queue.Add(schema.GroupVersion{Group: obj.Spec.Group, Version: v.Name}) + } } func (c *DiscoveryController) addCustomResourceDefinition(obj interface{}) { @@ -219,10 +246,14 @@ func (c *DiscoveryController) addCustomResourceDefinition(obj interface{}) { c.enqueue(castObj) } -func (c *DiscoveryController) updateCustomResourceDefinition(obj, _ interface{}) { - castObj := obj.(*apiextensions.CustomResourceDefinition) - glog.V(4).Infof("Updating customresourcedefinition %s", castObj.Name) - c.enqueue(castObj) +func (c *DiscoveryController) updateCustomResourceDefinition(oldObj, newObj interface{}) { + castNewObj := newObj.(*apiextensions.CustomResourceDefinition) + castOldObj := oldObj.(*apiextensions.CustomResourceDefinition) + glog.V(4).Infof("Updating customresourcedefinition %s", castOldObj.Name) + // Enqueue both old and new object to make sure we remove and add appropriate Versions. + // The working queue will resolve any duplicates and only changes will stay in the queue. + c.enqueue(castNewObj) + c.enqueue(castOldObj) } func (c *DiscoveryController) deleteCustomResourceDefinition(obj interface{}) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go index e427f4c11..7be3711dc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go @@ -58,9 +58,11 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + "k8s.io/apiextensions-apiserver/pkg/apiserver/conversion" apiservervalidation "k8s.io/apiextensions-apiserver/pkg/apiserver/validation" informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion" listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion" + "k8s.io/apiextensions-apiserver/pkg/controller/establish" "k8s.io/apiextensions-apiserver/pkg/controller/finalizer" apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" "k8s.io/apiextensions-apiserver/pkg/registry/customresource" @@ -80,13 +82,17 @@ type crdHandler struct { // which is suited for most read and rarely write cases customStorage atomic.Value - requestContextMapper apirequest.RequestContextMapper - crdLister listers.CustomResourceDefinitionLister delegate http.Handler restOptionsGetter generic.RESTOptionsGetter admission admission.Interface + + establishingController *establish.EstablishingController + + // MasterCount is used to implement sleep to improve + // CRD establishing process for HA clusters. + masterCount int } // crdInfo stores enough information to serve the storage for the custom resource @@ -96,11 +102,20 @@ type crdInfo struct { spec *apiextensions.CustomResourceDefinitionSpec acceptedNames *apiextensions.CustomResourceDefinitionNames - storage customresource.CustomResourceStorage + // Storage per version + storages map[string]customresource.CustomResourceStorage + + // Request scope per version + requestScopes map[string]handlers.RequestScope + + // Scale scope per version + scaleRequestScopes map[string]handlers.RequestScope - requestScope handlers.RequestScope - scaleRequestScope handlers.RequestScope - statusRequestScope handlers.RequestScope + // Status scope per version + statusRequestScopes map[string]handlers.RequestScope + + // storageVersion is the CRD version used when storing the object in etcd. + storageVersion string } // crdStorageMap goes from customresourcedefinition to its storage @@ -109,22 +124,23 @@ type crdStorageMap map[types.UID]*crdInfo func NewCustomResourceDefinitionHandler( versionDiscoveryHandler *versionDiscoveryHandler, groupDiscoveryHandler *groupDiscoveryHandler, - requestContextMapper apirequest.RequestContextMapper, crdInformer informers.CustomResourceDefinitionInformer, delegate http.Handler, restOptionsGetter generic.RESTOptionsGetter, - admission admission.Interface) *crdHandler { + admission admission.Interface, + establishingController *establish.EstablishingController, + masterCount int) *crdHandler { ret := &crdHandler{ versionDiscoveryHandler: versionDiscoveryHandler, groupDiscoveryHandler: groupDiscoveryHandler, customStorage: atomic.Value{}, - requestContextMapper: requestContextMapper, crdLister: crdInformer.Lister(), delegate: delegate, restOptionsGetter: restOptionsGetter, admission: admission, + establishingController: establishingController, + masterCount: masterCount, } - crdInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: ret.updateCustomResourceDefinition, DeleteFunc: func(obj interface{}) { @@ -138,11 +154,7 @@ func NewCustomResourceDefinitionHandler( } func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - ctx, ok := r.requestContextMapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, fmt.Errorf("no context found for request")) - return - } + ctx := req.Context() requestInfo, ok := apirequest.RequestInfoFrom(ctx) if !ok { responsewriters.InternalError(w, req, fmt.Errorf("no RequestInfo found in the context")) @@ -176,11 +188,16 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - if crd.Spec.Version != requestInfo.APIVersion { + if !apiextensions.HasServedCRDVersion(crd, requestInfo.APIVersion) { r.delegate.ServeHTTP(w, req) return } - if !apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) { + // There is a small chance that a CRD is being served because NamesAccepted condition is true, + // but it becomes "unserved" because another names update leads to a conflict + // and EstablishingController wasn't fast enough to put the CRD into the Established condition. + // We accept this as the problem is small and self-healing. + if !apiextensions.IsCRDConditionTrue(crd, apiextensions.NamesAccepted) && + !apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) { r.delegate.ServeHTTP(w, req) return } @@ -222,8 +239,8 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { } func (r *crdHandler) serveResource(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc { - requestScope := crdInfo.requestScope - storage := crdInfo.storage.CustomResource + requestScope := crdInfo.requestScopes[requestInfo.APIVersion] + storage := crdInfo.storages[requestInfo.APIVersion].CustomResource minRequestTimeout := 1 * time.Minute switch requestInfo.Verb { @@ -240,11 +257,11 @@ func (r *crdHandler) serveResource(w http.ResponseWriter, req *http.Request, req http.Error(w, fmt.Sprintf("%v not allowed while CustomResourceDefinition is terminating", requestInfo.Verb), http.StatusMethodNotAllowed) return nil } - return handlers.CreateResource(storage, requestScope, discovery.NewUnstructuredObjectTyper(nil), r.admission) + return handlers.CreateResource(storage, requestScope, r.admission) case "update": - return handlers.UpdateResource(storage, requestScope, discovery.NewUnstructuredObjectTyper(nil), r.admission) + return handlers.UpdateResource(storage, requestScope, r.admission) case "patch": - return handlers.PatchResource(storage, requestScope, r.admission, unstructured.UnstructuredObjectConverter{}, supportedTypes) + return handlers.PatchResource(storage, requestScope, r.admission, supportedTypes) case "delete": allowsOptions := true return handlers.DeleteResource(storage, allowsOptions, requestScope, r.admission) @@ -258,16 +275,16 @@ func (r *crdHandler) serveResource(w http.ResponseWriter, req *http.Request, req } func (r *crdHandler) serveStatus(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc { - requestScope := crdInfo.statusRequestScope - storage := crdInfo.storage.Status + requestScope := crdInfo.statusRequestScopes[requestInfo.APIVersion] + storage := crdInfo.storages[requestInfo.APIVersion].Status switch requestInfo.Verb { case "get": return handlers.GetResource(storage, nil, requestScope) case "update": - return handlers.UpdateResource(storage, requestScope, discovery.NewUnstructuredObjectTyper(nil), r.admission) + return handlers.UpdateResource(storage, requestScope, r.admission) case "patch": - return handlers.PatchResource(storage, requestScope, r.admission, unstructured.UnstructuredObjectConverter{}, supportedTypes) + return handlers.PatchResource(storage, requestScope, r.admission, supportedTypes) default: http.Error(w, fmt.Sprintf("unhandled verb %q", requestInfo.Verb), http.StatusMethodNotAllowed) return nil @@ -275,16 +292,16 @@ func (r *crdHandler) serveStatus(w http.ResponseWriter, req *http.Request, reque } func (r *crdHandler) serveScale(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc { - requestScope := crdInfo.scaleRequestScope - storage := crdInfo.storage.Scale + requestScope := crdInfo.scaleRequestScopes[requestInfo.APIVersion] + storage := crdInfo.storages[requestInfo.APIVersion].Scale switch requestInfo.Verb { case "get": return handlers.GetResource(storage, nil, requestScope) case "update": - return handlers.UpdateResource(storage, requestScope, discovery.NewUnstructuredObjectTyper(nil), r.admission) + return handlers.UpdateResource(storage, requestScope, r.admission) case "patch": - return handlers.PatchResource(storage, requestScope, r.admission, unstructured.UnstructuredObjectConverter{}, supportedTypes) + return handlers.PatchResource(storage, requestScope, r.admission, supportedTypes) default: http.Error(w, fmt.Sprintf("unhandled verb %q", requestInfo.Verb), http.StatusMethodNotAllowed) return nil @@ -298,6 +315,19 @@ func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{}) r.customStorageLock.Lock() defer r.customStorageLock.Unlock() + // Add CRD to the establishing controller queue. + // For HA clusters, we want to prevent race conditions when changing status to Established, + // so we want to be sure that CRD is Installing at least for 5 seconds before Establishing it. + // TODO: find a real HA safe checkpointing mechanism instead of an arbitrary wait. + if !apiextensions.IsCRDConditionTrue(newCRD, apiextensions.Established) && + apiextensions.IsCRDConditionTrue(newCRD, apiextensions.NamesAccepted) { + if r.masterCount > 1 { + r.establishingController.QueueCRD(newCRD.Name, 5*time.Second) + } else { + r.establishingController.QueueCRD(newCRD.Name, 0) + } + } + storageMap := r.customStorage.Load().(crdStorageMap) oldInfo, found := storageMap[newCRD.UID] if !found { @@ -314,8 +344,10 @@ func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{}) // as it is used without locking elsewhere. storageMap2 := storageMap.clone() if oldInfo, ok := storageMap2[types.UID(oldCRD.UID)]; ok { - // destroy only the main storage. Those for the subresources share cacher and etcd clients. - oldInfo.storage.CustomResource.DestroyFunc() + for _, storage := range oldInfo.storages { + // destroy only the main storage. Those for the subresources share cacher and etcd clients. + storage.CustomResource.DestroyFunc() + } delete(storageMap2, types.UID(oldCRD.UID)) } @@ -346,9 +378,11 @@ func (r *crdHandler) removeDeadStorage() { } } if !found { - glog.V(4).Infof("Removing dead CRD storage for %v", s.requestScope.Resource) - // destroy only the main storage. Those for the subresources share cacher and etcd clients. - s.storage.CustomResource.DestroyFunc() + glog.V(4).Infof("Removing dead CRD storage for %s/%s", s.spec.Group, s.spec.Names.Kind) + for _, storage := range s.storages { + // destroy only the main storage. Those for the subresources share cacher and etcd clients. + storage.CustomResource.DestroyFunc() + } delete(storageMap2, uid) } } @@ -362,9 +396,11 @@ func (r *crdHandler) GetCustomResourceListerCollectionDeleter(crd *apiextensions if err != nil { return nil, err } - return info.storage.CustomResource, nil + return info.storages[info.storageVersion].CustomResource, nil } +var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() + func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResourceDefinition) (*crdInfo, error) { storageMap := r.customStorage.Load().(crdStorageMap) if ret, ok := storageMap[crd.UID]; ok { @@ -379,153 +415,157 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource return ret, nil } - // In addition to Unstructured objects (Custom Resources), we also may sometimes need to - // decode unversioned Options objects, so we delegate to parameterScheme for such types. - parameterScheme := runtime.NewScheme() - parameterScheme.AddUnversionedTypes(schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version}, - &metav1.ListOptions{}, - &metav1.ExportOptions{}, - &metav1.GetOptions{}, - &metav1.DeleteOptions{}, - ) - parameterCodec := runtime.NewParameterCodec(parameterScheme) - - kind := schema.GroupVersionKind{Group: crd.Spec.Group, Version: crd.Spec.Version, Kind: crd.Status.AcceptedNames.Kind} - typer := UnstructuredObjectTyper{ - Delegate: parameterScheme, - UnstructuredTyper: discovery.NewUnstructuredObjectTyper(nil), - } - creator := unstructuredCreator{} - - validator, _, err := apiservervalidation.NewSchemaValidator(crd.Spec.Validation) + storageVersion, err := apiextensions.GetCRDStorageVersion(crd) if err != nil { return nil, err } - var statusSpec *apiextensions.CustomResourceSubresourceStatus - var statusValidator *validate.SchemaValidator - if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Status != nil { - statusSpec = crd.Spec.Subresources.Status + // Scope/Storages per version. + requestScopes := map[string]handlers.RequestScope{} + storages := map[string]customresource.CustomResourceStorage{} + statusScopes := map[string]handlers.RequestScope{} + scaleScopes := map[string]handlers.RequestScope{} + + for _, v := range crd.Spec.Versions { + safeConverter, unsafeConverter := conversion.NewCRDConverter(crd) + // In addition to Unstructured objects (Custom Resources), we also may sometimes need to + // decode unversioned Options objects, so we delegate to parameterScheme for such types. + parameterScheme := runtime.NewScheme() + parameterScheme.AddUnversionedTypes(schema.GroupVersion{Group: crd.Spec.Group, Version: v.Name}, + &metav1.ListOptions{}, + &metav1.ExportOptions{}, + &metav1.GetOptions{}, + &metav1.DeleteOptions{}, + ) + parameterCodec := runtime.NewParameterCodec(parameterScheme) + + kind := schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.Kind} + typer := newUnstructuredObjectTyper(parameterScheme) + creator := unstructuredCreator{} + + validator, _, err := apiservervalidation.NewSchemaValidator(crd.Spec.Validation) + if err != nil { + return nil, err + } - // for the status subresource, validate only against the status schema - if crd.Spec.Validation != nil && crd.Spec.Validation.OpenAPIV3Schema != nil && crd.Spec.Validation.OpenAPIV3Schema.Properties != nil { - if statusSchema, ok := crd.Spec.Validation.OpenAPIV3Schema.Properties["status"]; ok { - openapiSchema := &spec.Schema{} - if err := apiservervalidation.ConvertJSONSchemaProps(&statusSchema, openapiSchema); err != nil { - return nil, err + var statusSpec *apiextensions.CustomResourceSubresourceStatus + var statusValidator *validate.SchemaValidator + if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Status != nil { + statusSpec = crd.Spec.Subresources.Status + + // for the status subresource, validate only against the status schema + if crd.Spec.Validation != nil && crd.Spec.Validation.OpenAPIV3Schema != nil && crd.Spec.Validation.OpenAPIV3Schema.Properties != nil { + if statusSchema, ok := crd.Spec.Validation.OpenAPIV3Schema.Properties["status"]; ok { + openapiSchema := &spec.Schema{} + if err := apiservervalidation.ConvertJSONSchemaProps(&statusSchema, openapiSchema); err != nil { + return nil, err + } + statusValidator = validate.NewSchemaValidator(openapiSchema, nil, "", strfmt.Default) } - statusValidator = validate.NewSchemaValidator(openapiSchema, nil, "", strfmt.Default) } } - } - var scaleSpec *apiextensions.CustomResourceSubresourceScale - if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil { - scaleSpec = crd.Spec.Subresources.Scale - } + var scaleSpec *apiextensions.CustomResourceSubresourceScale + if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil { + scaleSpec = crd.Spec.Subresources.Scale + } - // TODO: identify how to pass printer specification from the CRD - table, err := tableconvertor.New(nil) - if err != nil { - glog.V(2).Infof("The CRD for %v has an invalid printer specification, falling back to default printing: %v", kind, err) - } - - customResourceStorage := customresource.NewStorage( - schema.GroupResource{Group: crd.Spec.Group, Resource: crd.Status.AcceptedNames.Plural}, - schema.GroupVersionKind{Group: crd.Spec.Group, Version: crd.Spec.Version, Kind: crd.Status.AcceptedNames.ListKind}, - customresource.NewStrategy( - typer, - crd.Spec.Scope == apiextensions.NamespaceScoped, - kind, - validator, - statusValidator, - statusSpec, - scaleSpec, - ), - r.restOptionsGetter, - crd.Status.AcceptedNames.Categories, - table, - ) - - selfLinkPrefix := "" - switch crd.Spec.Scope { - case apiextensions.ClusterScoped: - selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, crd.Spec.Version) + "/" + crd.Status.AcceptedNames.Plural + "/" - case apiextensions.NamespaceScoped: - selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, crd.Spec.Version, "namespaces") + "/" - } - - clusterScoped := crd.Spec.Scope == apiextensions.ClusterScoped - - var ctxFn handlers.ContextFunc - ctxFn = func(req *http.Request) apirequest.Context { - ret, _ := r.requestContextMapper.Get(req) - return ret - } - - requestScope := handlers.RequestScope{ - Namer: handlers.ContextBasedNaming{ - GetContext: ctxFn, - SelfLinker: meta.NewAccessor(), - ClusterScoped: clusterScoped, - SelfLinkPathPrefix: selfLinkPrefix, - }, - ContextFunc: func(req *http.Request) apirequest.Context { - ret, _ := r.requestContextMapper.Get(req) - return ret - }, + table, err := tableconvertor.New(crd.Spec.AdditionalPrinterColumns) + if err != nil { + glog.V(2).Infof("The CRD for %v has an invalid printer specification, falling back to default printing: %v", kind, err) + } - Serializer: unstructuredNegotiatedSerializer{typer: typer, creator: creator}, - ParameterCodec: parameterCodec, + storages[v.Name] = customresource.NewStorage( + schema.GroupResource{Group: crd.Spec.Group, Resource: crd.Status.AcceptedNames.Plural}, + schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.ListKind}, + customresource.NewStrategy( + typer, + crd.Spec.Scope == apiextensions.NamespaceScoped, + kind, + validator, + statusValidator, + statusSpec, + scaleSpec, + ), + crdConversionRESTOptionsGetter{ + RESTOptionsGetter: r.restOptionsGetter, + converter: safeConverter, + decoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: v.Name}, + encoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: storageVersion}, + }, + crd.Status.AcceptedNames.Categories, + table, + ) + + selfLinkPrefix := "" + switch crd.Spec.Scope { + case apiextensions.ClusterScoped: + selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, v.Name) + "/" + crd.Status.AcceptedNames.Plural + "/" + case apiextensions.NamespaceScoped: + selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, v.Name, "namespaces") + "/" + } - Creater: creator, - Convertor: crdObjectConverter{ - UnstructuredObjectConverter: unstructured.UnstructuredObjectConverter{}, - clusterScoped: clusterScoped, - }, - Defaulter: unstructuredDefaulter{parameterScheme}, - Typer: typer, - UnsafeConvertor: unstructured.UnstructuredObjectConverter{}, + clusterScoped := crd.Spec.Scope == apiextensions.ClusterScoped + + requestScopes[v.Name] = handlers.RequestScope{ + Namer: handlers.ContextBasedNaming{ + SelfLinker: meta.NewAccessor(), + ClusterScoped: clusterScoped, + SelfLinkPathPrefix: selfLinkPrefix, + }, + Serializer: unstructuredNegotiatedSerializer{typer: typer, creator: creator, converter: safeConverter}, + ParameterCodec: parameterCodec, - Resource: schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Status.AcceptedNames.Plural}, - Kind: kind, + Creater: creator, + Convertor: safeConverter, + Defaulter: unstructuredDefaulter{parameterScheme}, + Typer: typer, + UnsafeConvertor: unsafeConverter, - MetaGroupVersion: metav1.SchemeGroupVersion, + Resource: schema.GroupVersionResource{Group: crd.Spec.Group, Version: v.Name, Resource: crd.Status.AcceptedNames.Plural}, + Kind: kind, - TableConvertor: customResourceStorage.CustomResource, + MetaGroupVersion: metav1.SchemeGroupVersion, + + TableConvertor: storages[v.Name].CustomResource, + } + + // override scaleSpec subresource values + // shallow copy + scaleScope := requestScopes[v.Name] + scaleConverter := scale.NewScaleConverter() + scaleScope.Subresource = "scale" + scaleScope.Serializer = serializer.NewCodecFactory(scaleConverter.Scheme()) + scaleScope.Kind = autoscalingv1.SchemeGroupVersion.WithKind("Scale") + scaleScope.Namer = handlers.ContextBasedNaming{ + SelfLinker: meta.NewAccessor(), + ClusterScoped: clusterScoped, + SelfLinkPathPrefix: selfLinkPrefix, + SelfLinkPathSuffix: "/scale", + } + scaleScopes[v.Name] = scaleScope + + // override status subresource values + // shallow copy + statusScope := requestScopes[v.Name] + statusScope.Subresource = "status" + statusScope.Namer = handlers.ContextBasedNaming{ + SelfLinker: meta.NewAccessor(), + ClusterScoped: clusterScoped, + SelfLinkPathPrefix: selfLinkPrefix, + SelfLinkPathSuffix: "/status", + } + statusScopes[v.Name] = statusScope } ret := &crdInfo{ - spec: &crd.Spec, - acceptedNames: &crd.Status.AcceptedNames, - - storage: customResourceStorage, - requestScope: requestScope, - scaleRequestScope: requestScope, // shallow copy - statusRequestScope: requestScope, // shallow copy - } - - // override scaleSpec subresource values - scaleConverter := scale.NewScaleConverter() - ret.scaleRequestScope.Subresource = "scale" - ret.scaleRequestScope.Serializer = serializer.NewCodecFactory(scaleConverter.Scheme()) - ret.scaleRequestScope.Kind = autoscalingv1.SchemeGroupVersion.WithKind("Scale") - ret.scaleRequestScope.Namer = handlers.ContextBasedNaming{ - GetContext: ctxFn, - SelfLinker: meta.NewAccessor(), - ClusterScoped: clusterScoped, - SelfLinkPathPrefix: selfLinkPrefix, - SelfLinkPathSuffix: "/scale", - } - - // override status subresource values - ret.statusRequestScope.Subresource = "status" - ret.statusRequestScope.Namer = handlers.ContextBasedNaming{ - GetContext: ctxFn, - SelfLinker: meta.NewAccessor(), - ClusterScoped: clusterScoped, - SelfLinkPathPrefix: selfLinkPrefix, - SelfLinkPathSuffix: "/status", + spec: &crd.Spec, + acceptedNames: &crd.Status.AcceptedNames, + storages: storages, + requestScopes: requestScopes, + scaleRequestScopes: scaleScopes, + statusRequestScopes: statusScopes, + storageVersion: storageVersion, } // Copy because we cannot write to storageMap without a race @@ -538,27 +578,10 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource return ret, nil } -// crdObjectConverter is a converter that supports field selectors for CRDs. -type crdObjectConverter struct { - unstructured.UnstructuredObjectConverter - clusterScoped bool -} - -func (c crdObjectConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { - // We currently only support metadata.namespace and metadata.name. - switch { - case label == "metadata.name": - return label, value, nil - case !c.clusterScoped && label == "metadata.namespace": - return label, value, nil - default: - return "", "", fmt.Errorf("field label not supported: %s", label) - } -} - type unstructuredNegotiatedSerializer struct { - typer runtime.ObjectTyper - creator runtime.ObjectCreater + typer runtime.ObjectTyper + creator runtime.ObjectCreater + converter runtime.ObjectConvertor } func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { @@ -583,11 +606,12 @@ func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.Serial } func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { - return versioning.NewDefaultingCodecForScheme(Scheme, encoder, nil, gv, nil) + return versioning.NewCodec(encoder, nil, s.converter, Scheme, Scheme, Scheme, gv, nil) } func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { - return versioning.NewDefaultingCodecForScheme(Scheme, nil, decoder, nil, gv) + d := schemaCoercingDecoder{delegate: decoder, validator: unstructuredSchemaCoercer{}} + return versioning.NewDefaultingCodecForScheme(Scheme, nil, d, nil, gv) } type UnstructuredObjectTyper struct { @@ -595,6 +619,13 @@ type UnstructuredObjectTyper struct { UnstructuredTyper runtime.ObjectTyper } +func newUnstructuredObjectTyper(Delegate runtime.ObjectTyper) UnstructuredObjectTyper { + return UnstructuredObjectTyper{ + Delegate: Delegate, + UnstructuredTyper: discovery.NewUnstructuredObjectTyper(), + } +} + func (t UnstructuredObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { // Delegate for things other than Unstructured. if _, ok := obj.(runtime.Unstructured); !ok { @@ -661,3 +692,192 @@ func (in crdStorageMap) clone() crdStorageMap { } return out } + +// crdConversionRESTOptionsGetter overrides the codec with one using the +// provided custom converter and custom encoder and decoder version. +type crdConversionRESTOptionsGetter struct { + generic.RESTOptionsGetter + converter runtime.ObjectConvertor + encoderVersion schema.GroupVersion + decoderVersion schema.GroupVersion +} + +func (t crdConversionRESTOptionsGetter) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) { + ret, err := t.RESTOptionsGetter.GetRESTOptions(resource) + if err == nil { + d := schemaCoercingDecoder{delegate: ret.StorageConfig.Codec, validator: unstructuredSchemaCoercer{ + // drop invalid fields while decoding old CRs (before we had any ObjectMeta validation) + dropInvalidMetadata: true, + }} + c := schemaCoercingConverter{delegate: t.converter, validator: unstructuredSchemaCoercer{}} + ret.StorageConfig.Codec = versioning.NewCodec(ret.StorageConfig.Codec, d, c, &unstructuredCreator{}, discovery.NewUnstructuredObjectTyper(), &unstructuredDefaulter{delegate: Scheme}, t.encoderVersion, t.decoderVersion) + } + return ret, err +} + +// schemaCoercingDecoder calls the delegate decoder, and then applies the Unstructured schema validator +// to coerce the schema. +type schemaCoercingDecoder struct { + delegate runtime.Decoder + validator unstructuredSchemaCoercer +} + +var _ runtime.Decoder = schemaCoercingDecoder{} + +func (d schemaCoercingDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { + obj, gvk, err := d.delegate.Decode(data, defaults, into) + if err != nil { + return nil, gvk, err + } + if u, ok := obj.(*unstructured.Unstructured); ok { + if err := d.validator.apply(u); err != nil { + return nil, gvk, err + } + } + + return obj, gvk, nil +} + +// schemaCoercingConverter calls the delegate converter and applies the Unstructured validator to +// coerce the schema. +type schemaCoercingConverter struct { + delegate runtime.ObjectConvertor + validator unstructuredSchemaCoercer +} + +var _ runtime.ObjectConvertor = schemaCoercingConverter{} + +func (v schemaCoercingConverter) Convert(in, out, context interface{}) error { + if err := v.delegate.Convert(in, out, context); err != nil { + return err + } + + if u, ok := out.(*unstructured.Unstructured); ok { + if err := v.validator.apply(u); err != nil { + return err + } + } + + return nil +} + +func (v schemaCoercingConverter) ConvertToVersion(in runtime.Object, gv runtime.GroupVersioner) (runtime.Object, error) { + out, err := v.delegate.ConvertToVersion(in, gv) + if err != nil { + return nil, err + } + + if u, ok := out.(*unstructured.Unstructured); ok { + if err := v.validator.apply(u); err != nil { + return nil, err + } + } + + return out, nil +} + +func (v schemaCoercingConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + return v.ConvertFieldLabel(version, kind, label, value) +} + +// unstructuredSchemaCoercer does the validation for Unstructured that json.Unmarshal +// does for native types. This includes: +// - validating and pruning ObjectMeta (here with optional error instead of pruning) +// - TODO: application of an OpenAPI validator (against the whole object or a top-level field of it). +// - TODO: optionally application of post-validation algorithms like defaulting and/or OpenAPI based pruning. +type unstructuredSchemaCoercer struct { + dropInvalidMetadata bool +} + +func (v *unstructuredSchemaCoercer) apply(u *unstructured.Unstructured) error { + // save implicit meta fields that don't have to be specified in the validation spec + kind, foundKind, err := unstructured.NestedString(u.UnstructuredContent(), "kind") + if err != nil { + return err + } + apiVersion, foundApiVersion, err := unstructured.NestedString(u.UnstructuredContent(), "apiVersion") + if err != nil { + return err + } + objectMeta, foundObjectMeta, err := getObjectMeta(u, v.dropInvalidMetadata) + if err != nil { + return err + } + + // restore meta fields, starting clean + if foundKind { + u.SetKind(kind) + } + if foundApiVersion { + u.SetAPIVersion(apiVersion) + } + if foundObjectMeta { + if err := setObjectMeta(u, objectMeta); err != nil { + return err + } + } + + return nil +} + +var encodingjson = json.CaseSensitiveJsonIterator() + +func getObjectMeta(u *unstructured.Unstructured, dropMalformedFields bool) (*metav1.ObjectMeta, bool, error) { + metadata, found := u.UnstructuredContent()["metadata"] + if !found { + return nil, false, nil + } + + // round-trip through JSON first, hoping that unmarshaling just works + objectMeta := &metav1.ObjectMeta{} + metadataBytes, err := encodingjson.Marshal(metadata) + if err != nil { + return nil, false, err + } + if err = encodingjson.Unmarshal(metadataBytes, objectMeta); err == nil { + // if successful, return + return objectMeta, true, nil + } + if !dropMalformedFields { + // if we're not trying to drop malformed fields, return the error + return nil, true, err + } + + metadataMap, ok := metadata.(map[string]interface{}) + if !ok { + return nil, false, fmt.Errorf("invalid metadata: expected object, got %T", metadata) + } + + // Go field by field accumulating into the metadata object. + // This takes advantage of the fact that you can repeatedly unmarshal individual fields into a single struct, + // each iteration preserving the old key-values. + accumulatedObjectMeta := &metav1.ObjectMeta{} + testObjectMeta := &metav1.ObjectMeta{} + for k, v := range metadataMap { + // serialize a single field + if singleFieldBytes, err := encodingjson.Marshal(map[string]interface{}{k: v}); err == nil { + // do a test unmarshal + if encodingjson.Unmarshal(singleFieldBytes, testObjectMeta) == nil { + // if that succeeds, unmarshal for real + encodingjson.Unmarshal(singleFieldBytes, accumulatedObjectMeta) + } + } + } + + return accumulatedObjectMeta, true, nil +} + +func setObjectMeta(u *unstructured.Unstructured, objectMeta *metav1.ObjectMeta) error { + if objectMeta == nil { + unstructured.RemoveNestedField(u.UnstructuredContent(), "metadata") + return nil + } + + metadata, err := runtime.DefaultUnstructuredConverter.ToUnstructured(objectMeta) + if err != nil { + return err + } + + u.UnstructuredContent()["metadata"] = metadata + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go index 81c3ac705..a6d6e23a1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go @@ -17,9 +17,23 @@ limitations under the License. package apiserver import ( + "math/rand" + "reflect" "testing" + corev1 "k8s.io/api/core/v1" + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + "k8s.io/apiextensions-apiserver/pkg/apiserver/conversion" + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/testing/fuzzer" + metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/apimachinery/pkg/util/diff" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" ) func TestConvertFieldLabel(t *testing.T) { @@ -64,10 +78,14 @@ func TestConvertFieldLabel(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - c := crdObjectConverter{ - UnstructuredObjectConverter: unstructured.UnstructuredObjectConverter{}, - clusterScoped: test.clusterScoped, + crd := apiextensions.CustomResourceDefinition{} + + if test.clusterScoped { + crd.Spec.Scope = apiextensions.ClusterScoped + } else { + crd.Spec.Scope = apiextensions.NamespaceScoped } + _, c := conversion.NewCRDConverter(&crd) label, value, err := c.ConvertFieldLabel("", "", test.label, "value") if e, a := test.expectError, err != nil; e != a { @@ -89,3 +107,202 @@ func TestConvertFieldLabel(t *testing.T) { }) } } + +func TestRoundtripObjectMeta(t *testing.T) { + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + codec := json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false) + seed := rand.Int63() + fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(seed), codecs) + + N := 1000 + for i := 0; i < N; i++ { + u := &unstructured.Unstructured{Object: map[string]interface{}{}} + original := &metav1.ObjectMeta{} + fuzzer.Fuzz(original) + if err := setObjectMeta(u, original); err != nil { + t.Fatalf("unexpected error setting ObjectMeta: %v", err) + } + o, _, err := getObjectMeta(u, false) + if err != nil { + t.Fatalf("unexpected error getting the Objectmeta: %v", err) + } + + if !equality.Semantic.DeepEqual(original, o) { + t.Errorf("diff: %v\nCodec: %#v", diff.ObjectReflectDiff(original, o), codec) + } + } +} + +// TestMalformedObjectMetaFields sets a number of different random values and types for all +// metadata fields. If json.Unmarshal accepts them, compare that getObjectMeta +// gives the same result. Otherwise, drop malformed fields. +func TestMalformedObjectMetaFields(t *testing.T) { + fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(rand.Int63()), serializer.NewCodecFactory(runtime.NewScheme())) + spuriousValues := func() []interface{} { + return []interface{}{ + // primitives + nil, + int64(1), + float64(1.5), + true, + "a", + // well-formed complex values + []interface{}{"a", "b"}, + map[string]interface{}{"a": "1", "b": "2"}, + []interface{}{int64(1), int64(2)}, + []interface{}{float64(1.5), float64(2.5)}, + // known things json decoding tolerates + map[string]interface{}{"a": "1", "b": nil}, + // malformed things + map[string]interface{}{"a": "1", "b": []interface{}{"nested"}}, + []interface{}{"a", int64(1), float64(1.5), true, []interface{}{"nested"}}, + } + } + N := 100 + for i := 0; i < N; i++ { + fuzzedObjectMeta := &metav1.ObjectMeta{} + fuzzer.Fuzz(fuzzedObjectMeta) + goodMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy()) + if err != nil { + t.Fatal(err) + } + for _, pth := range jsonPaths(nil, goodMetaMap) { + for _, v := range spuriousValues() { + // skip values of same type, because they can only cause decoding errors further insides + orig, err := JsonPathValue(goodMetaMap, pth, 0) + if err != nil { + t.Fatalf("unexpected to not find something at %v: %v", pth, err) + } + if reflect.TypeOf(v) == reflect.TypeOf(orig) { + continue + } + + // make a spurious map + spuriousMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy()) + if err != nil { + t.Fatal(err) + } + if err := SetJsonPath(spuriousMetaMap, pth, 0, v); err != nil { + t.Fatal(err) + } + + // See if it can unmarshal to object meta + spuriousJSON, err := encodingjson.Marshal(spuriousMetaMap) + if err != nil { + t.Fatalf("error on %v=%#v: %v", pth, v, err) + } + expectedObjectMeta := &metav1.ObjectMeta{} + if err := encodingjson.Unmarshal(spuriousJSON, expectedObjectMeta); err != nil { + // if standard json unmarshal would fail decoding this field, drop the field entirely + truncatedMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy()) + if err != nil { + t.Fatal(err) + } + + // we expect this logic for the different fields: + switch { + default: + // delete complete top-level field by default + DeleteJsonPath(truncatedMetaMap, pth[:1], 0) + } + + truncatedJSON, err := encodingjson.Marshal(truncatedMetaMap) + if err != nil { + t.Fatalf("error on %v=%#v: %v", pth, v, err) + } + expectedObjectMeta = &metav1.ObjectMeta{} + if err := encodingjson.Unmarshal(truncatedJSON, expectedObjectMeta); err != nil { + t.Fatalf("error on %v=%#v: %v", pth, v, err) + } + } + + // make sure dropInvalidTypedFields+getObjectMeta matches what we expect + u := &unstructured.Unstructured{Object: map[string]interface{}{"metadata": spuriousMetaMap}} + actualObjectMeta, _, err := getObjectMeta(u, true) + if err != nil { + t.Errorf("got unexpected error after dropping invalid typed fields on %v=%#v: %v", pth, v, err) + continue + } + + if !equality.Semantic.DeepEqual(expectedObjectMeta, actualObjectMeta) { + t.Errorf("%v=%#v, diff: %v\n", pth, v, diff.ObjectReflectDiff(expectedObjectMeta, actualObjectMeta)) + t.Errorf("expectedObjectMeta %#v", expectedObjectMeta) + } + } + } + } +} + +func TestGetObjectMetaNils(t *testing.T) { + u := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "kind": "Pod", + "apiVersion": "v1", + "metadata": map[string]interface{}{ + "generateName": nil, + "labels": map[string]interface{}{ + "foo": nil, + }, + }, + }, + } + + o, _, err := getObjectMeta(u, true) + if err != nil { + t.Fatal(err) + } + if o.GenerateName != "" { + t.Errorf("expected null json value to be read as \"\" string, but got: %q", o.GenerateName) + } + if got, expected := o.Labels, map[string]string{"foo": ""}; !reflect.DeepEqual(got, expected) { + t.Errorf("unexpected labels, expected=%#v, got=%#v", expected, got) + } + + // double check this what the kube JSON decode is doing + bs, _ := encodingjson.Marshal(u.UnstructuredContent()) + kubeObj, _, err := clientgoscheme.Codecs.UniversalDecoder(corev1.SchemeGroupVersion).Decode(bs, nil, nil) + if err != nil { + t.Fatal(err) + } + pod, ok := kubeObj.(*corev1.Pod) + if !ok { + t.Fatalf("expected v1 Pod, got: %T", pod) + } + if got, expected := o.GenerateName, pod.ObjectMeta.GenerateName; got != expected { + t.Errorf("expected generatedName to be %q, got %q", expected, got) + } + if got, expected := o.Labels, pod.ObjectMeta.Labels; !reflect.DeepEqual(got, expected) { + t.Errorf("expected labels to be %v, got %v", expected, got) + } +} + +func TestGetObjectMeta(t *testing.T) { + for i := 0; i < 100; i++ { + u := &unstructured.Unstructured{Object: map[string]interface{}{ + "metadata": map[string]interface{}{ + "name": "good", + "Name": "bad1", + "nAme": "bad2", + "naMe": "bad3", + "namE": "bad4", + + "namespace": "good", + "Namespace": "bad1", + "nAmespace": "bad2", + "naMespace": "bad3", + "namEspace": "bad4", + + "creationTimestamp": "a", + }, + }} + + meta, _, err := getObjectMeta(u, true) + if err != nil { + t.Fatal(err) + } + if meta.Name != "good" || meta.Namespace != "good" { + t.Fatalf("got %#v", meta) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go new file mode 100644 index 000000000..8d9bb24f8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go @@ -0,0 +1,235 @@ +/* +Copyright 2018 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 apiserver + +import ( + "bytes" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" +) + +type ( + jsonPathNode struct { + index *int + field string + } + JsonPath []jsonPathNode +) + +func (p JsonPath) String() string { + var buf bytes.Buffer + for _, n := range p { + if n.index == nil { + buf.WriteString("." + n.field) + } else { + buf.WriteString(fmt.Sprintf("[%d]", *n.index)) + } + } + return buf.String() +} + +func jsonPaths(base JsonPath, j map[string]interface{}) []JsonPath { + res := make([]JsonPath, 0, len(j)) + for k, old := range j { + kPth := append(append([]jsonPathNode(nil), base...), jsonPathNode{field: k}) + res = append(res, kPth) + + switch old := old.(type) { + case map[string]interface{}: + res = append(res, jsonPaths(kPth, old)...) + case []interface{}: + res = append(res, jsonIterSlice(kPth, old)...) + } + } + return res +} + +func jsonIterSlice(base JsonPath, j []interface{}) []JsonPath { + res := make([]JsonPath, 0, len(j)) + for i, old := range j { + index := i + iPth := append(append([]jsonPathNode(nil), base...), jsonPathNode{index: &index}) + res = append(res, iPth) + + switch old := old.(type) { + case map[string]interface{}: + res = append(res, jsonPaths(iPth, old)...) + case []interface{}: + res = append(res, jsonIterSlice(iPth, old)...) + } + } + return res +} + +func JsonPathValue(j map[string]interface{}, pth JsonPath, base int) (interface{}, error) { + if len(pth) == base { + return nil, fmt.Errorf("empty json path is invalid for object") + } + if pth[base].index != nil { + return nil, fmt.Errorf("index json path is invalid for object") + } + field, ok := j[pth[base].field] + if !ok || len(pth) == base+1 { + if len(pth) > base+1 { + return nil, fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth) + } + return j[pth[base].field], nil + } + switch field := field.(type) { + case map[string]interface{}: + return JsonPathValue(field, pth, base+1) + case []interface{}: + return jsonPathValueSlice(field, pth, base+1) + default: + return nil, fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1]) + } +} + +func jsonPathValueSlice(j []interface{}, pth JsonPath, base int) (interface{}, error) { + if len(pth) == base { + return nil, fmt.Errorf("empty json path %q is invalid for object", pth) + } + if pth[base].index == nil { + return nil, fmt.Errorf("field json path %q is invalid for object", pth[:base+1]) + } + if *pth[base].index >= len(j) { + return nil, fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j)) + } + if len(pth) == base+1 { + return j[*pth[base].index], nil + } + switch item := j[*pth[base].index].(type) { + case map[string]interface{}: + return JsonPathValue(item, pth, base+1) + case []interface{}: + return jsonPathValueSlice(item, pth, base+1) + default: + return nil, fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1]) + } +} + +func SetJsonPath(j map[string]interface{}, pth JsonPath, base int, value interface{}) error { + if len(pth) == base { + return fmt.Errorf("empty json path is invalid for object") + } + if pth[base].index != nil { + return fmt.Errorf("index json path is invalid for object") + } + field, ok := j[pth[base].field] + if !ok || len(pth) == base+1 { + if len(pth) > base+1 { + return fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth) + } + j[pth[base].field] = runtime.DeepCopyJSONValue(value) + return nil + } + switch field := field.(type) { + case map[string]interface{}: + return SetJsonPath(field, pth, base+1, value) + case []interface{}: + return setJsonPathSlice(field, pth, base+1, value) + default: + return fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1]) + } +} + +func setJsonPathSlice(j []interface{}, pth JsonPath, base int, value interface{}) error { + if len(pth) == base { + return fmt.Errorf("empty json path %q is invalid for object", pth) + } + if pth[base].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth[:base+1]) + } + if *pth[base].index >= len(j) { + return fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j)) + } + if len(pth) == base+1 { + j[*pth[base].index] = runtime.DeepCopyJSONValue(value) + return nil + } + switch item := j[*pth[base].index].(type) { + case map[string]interface{}: + return SetJsonPath(item, pth, base+1, value) + case []interface{}: + return setJsonPathSlice(item, pth, base+1, value) + default: + return fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1]) + } +} + +func DeleteJsonPath(j map[string]interface{}, pth JsonPath, base int) error { + if len(pth) == base { + return fmt.Errorf("empty json path is invalid for object") + } + if pth[base].index != nil { + return fmt.Errorf("index json path is invalid for object") + } + field, ok := j[pth[base].field] + if !ok || len(pth) == base+1 { + if len(pth) > base+1 { + return fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth) + } + delete(j, pth[base].field) + return nil + } + switch field := field.(type) { + case map[string]interface{}: + return DeleteJsonPath(field, pth, base+1) + case []interface{}: + if len(pth) == base+2 { + if pth[base+1].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth) + } + j[pth[base].field] = append(field[:*pth[base+1].index], field[*pth[base+1].index+1:]...) + return nil + } + return deleteJsonPathSlice(field, pth, base+1) + default: + return fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1]) + } +} + +func deleteJsonPathSlice(j []interface{}, pth JsonPath, base int) error { + if len(pth) == base { + return fmt.Errorf("empty json path %q is invalid for object", pth) + } + if pth[base].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth[:base+1]) + } + if *pth[base].index >= len(j) { + return fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j)) + } + if len(pth) == base+1 { + return fmt.Errorf("cannot delete item at index %q in-place", pth[:base]) + } + switch item := j[*pth[base].index].(type) { + case map[string]interface{}: + return DeleteJsonPath(item, pth, base+1) + case []interface{}: + if len(pth) == base+2 { + if pth[base+1].index == nil { + return fmt.Errorf("field json path %q is invalid for object", pth) + } + j[*pth[base].index] = append(item[:*pth[base+1].index], item[*pth[base+1].index+1:]) + return nil + } + return deleteJsonPathSlice(item, pth, base+1) + default: + return fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1]) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/BUILD index c6312b730..6473cfa5d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/BUILD @@ -13,7 +13,6 @@ go_library( ], importpath = "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset", deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go index 444418888..63fcb510a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package clientset import ( - glog "github.com/golang/glog" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" @@ -74,7 +73,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go index 3421911a7..ee865e56d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go index 9988cd0b4..e65fe63ea 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -41,9 +41,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -53,7 +54,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go index 3113c1a6d..f37309186 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go index bc08c37e1..bd73f1179 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go index 7da7276b7..a1fd337f9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go index 3a2513caf..f25a6ce34 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go index 39327a9c3..288683ef9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go index 10fd3cc15..11aefe869 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeCustomResourceDefinitions) List(opts v1.ListOptions) (result *v1bet if label == nil { label = labels.Everything() } - list := &v1beta1.CustomResourceDefinitionList{} + list := &v1beta1.CustomResourceDefinitionList{ListMeta: obj.(*v1beta1.CustomResourceDefinitionList).ListMeta} for _, item := range obj.(*v1beta1.CustomResourceDefinitionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go index 07a7c1dce..2a989d4be 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/BUILD index a31718d05..247ed04de 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/BUILD @@ -13,7 +13,6 @@ go_library( ], importpath = "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset", deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go index 9519b78f1..152a9fea0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package internalclientset import ( - glog "github.com/golang/glog" apiextensionsinternalversion "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" @@ -66,7 +65,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go index 22ccee919..01b3d5e0f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go index 3c0f41dba..72ab169e9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -41,9 +41,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -53,7 +54,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go index 5c17a1003..89093fd9f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/BUILD index ae5835d47..aca5e1147 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/BUILD @@ -14,8 +14,6 @@ go_library( importpath = "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme", deps = [ "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go index f9de21961..01df98a6b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,11 +19,7 @@ limitations under the License. package scheme import ( - os "os" - apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install" - announced "k8s.io/apimachinery/pkg/apimachinery/announced" - registered "k8s.io/apimachinery/pkg/apimachinery/registered" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -34,15 +30,12 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) -var Registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) -var GroupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - func init() { v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - Install(GroupFactoryRegistry, Registry, Scheme) + Install(Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - apiextensions.Install(groupFactoryRegistry, registry, scheme) +func Install(scheme *runtime.Scheme) { + apiextensions.Install(scheme) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go index 9e08a905a..31b34404c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *ApiextensionsClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("apiextensions.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("apiextensions.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("apiextensions.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go index 322454cdf..f3ddc8044 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_apiextensions_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_apiextensions_client.go index 32bb913c0..1a601e5b0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_apiextensions_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_apiextensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_customresourcedefinition.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_customresourcedefinition.go index c5cd1da48..74016362d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_customresourcedefinition.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/fake_customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeCustomResourceDefinitions) List(opts v1.ListOptions) (result *apiex if label == nil { label = labels.Everything() } - list := &apiextensions.CustomResourceDefinitionList{} + list := &apiextensions.CustomResourceDefinitionList{ListMeta: obj.(*apiextensions.CustomResourceDefinitionList).ListMeta} for _, item := range obj.(*apiextensions.CustomResourceDefinitionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go index 74c295f6c..a88821021 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go index e88c53087..7b48c57ca 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go index 9d9b12787..589b4b20c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go index 331dad83e..f78edbb59 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go index 6e7141621..94d039c72 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,12 +32,16 @@ import ( cache "k8s.io/client-go/tools/cache" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client clientset.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -45,23 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client clientset.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client clientset.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client clientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -110,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go index a742bbd25..da8a2ab0c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index 2048b744f..3b17f5a1a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go index f096df135..8236e2acc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go index 08587b732..2c54f3ce5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go index 15c7e9f14..d9444144b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go index b1d07527d..84b04523d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,12 +32,16 @@ import ( cache "k8s.io/client-go/tools/cache" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client internalclientset.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -45,23 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client internalclientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -110,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go index 77a9e1b0b..c12c44074 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go index d41da2418..5854db0ca 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go index c736b3db8..f64f01d9d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go index 05a413aee..5e3ae381d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go index 468f5a664..87633217b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go index 65b786659..429782deb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server/start.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server/start.go index df3cf3e60..c36071d8d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server/start.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/cmd/server/start.go @@ -51,7 +51,7 @@ func NewCustomResourceDefinitionsServerOptions(out, errOut io.Writer) *CustomRes StdErr: errOut, } - // the shared informer is not needed for kube-aggregator. Disable the kubeconfig flag and the client creation. + // the shared informer is not needed for apiextentions apiserver. Disable the kubeconfig flag and the client creation. o.RecommendedOptions.CoreAPI = nil return o @@ -86,7 +86,7 @@ func NewCommandStartCustomResourceDefinitionsServer(out, errOut io.Writer, stopC func (o CustomResourceDefinitionsServerOptions) Validate(args []string) error { errors := []error{} errors = append(errors, o.RecommendedOptions.Validate()...) - errors = append(errors, o.APIEnablement.Validate(apiserver.Registry)...) + errors = append(errors, o.APIEnablement.Validate(apiserver.Scheme)...) return utilerrors.NewAggregate(errors) } @@ -104,7 +104,7 @@ func (o CustomResourceDefinitionsServerOptions) Config() (*apiserver.Config, err if err := o.RecommendedOptions.ApplyTo(serverConfig, apiserver.Scheme); err != nil { return nil, err } - if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Registry); err != nil { + if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Scheme); err != nil { return nil, err } @@ -137,7 +137,7 @@ func (o CustomResourceDefinitionsServerOptions) RunCustomResourceDefinitionsServ return err } - server, err := config.Complete().New(genericapiserver.EmptyDelegate) + server, err := config.Complete().New(genericapiserver.NewEmptyDelegate()) if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/BUILD new file mode 100644 index 000000000..fa3e5dfa1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/BUILD @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["establishing_controller.go"], + importpath = "k8s.io/apiextensions-apiserver/pkg/controller/establish", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", + "//vendor/k8s.io/client-go/util/workqueue:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go new file mode 100644 index 000000000..5c2ebbcaa --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go @@ -0,0 +1,142 @@ +/* +Copyright 2018 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 establish + +import ( + "fmt" + "time" + + "github.com/golang/glog" + apierrors "k8s.io/apimachinery/pkg/api/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + client "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion" + informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion" + listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion" +) + +// EstablishingController controls how and when CRD is established. +type EstablishingController struct { + crdClient client.CustomResourceDefinitionsGetter + crdLister listers.CustomResourceDefinitionLister + crdSynced cache.InformerSynced + + // To allow injection for testing. + syncFn func(key string) error + + queue workqueue.RateLimitingInterface +} + +// NewEstablishingController creates new EstablishingController. +func NewEstablishingController(crdInformer informers.CustomResourceDefinitionInformer, + crdClient client.CustomResourceDefinitionsGetter) *EstablishingController { + ec := &EstablishingController{ + crdClient: crdClient, + crdLister: crdInformer.Lister(), + crdSynced: crdInformer.Informer().HasSynced, + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "crdEstablishing"), + } + + ec.syncFn = ec.sync + + return ec +} + +// QueueCRD adds CRD into the establishing queue. +func (ec *EstablishingController) QueueCRD(key string, timeout time.Duration) { + ec.queue.AddAfter(key, timeout) +} + +// Run starts the EstablishingController. +func (ec *EstablishingController) Run(stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer ec.queue.ShutDown() + + glog.Infof("Starting EstablishingController") + defer glog.Infof("Shutting down EstablishingController") + + if !cache.WaitForCacheSync(stopCh, ec.crdSynced) { + return + } + + // only start one worker thread since its a slow moving API + go wait.Until(ec.runWorker, time.Second, stopCh) + + <-stopCh +} + +func (ec *EstablishingController) runWorker() { + for ec.processNextWorkItem() { + } +} + +// processNextWorkItem deals with one key off the queue. +// It returns false when it's time to quit. +func (ec *EstablishingController) processNextWorkItem() bool { + key, quit := ec.queue.Get() + if quit { + return false + } + defer ec.queue.Done(key) + + err := ec.syncFn(key.(string)) + if err == nil { + return true + } + + utilruntime.HandleError(fmt.Errorf("%v failed with: %v", key, err)) + ec.queue.AddRateLimited(key) + + return true +} + +// sync is used to turn CRDs into the Established state. +func (ec *EstablishingController) sync(key string) error { + cachedCRD, err := ec.crdLister.Get(key) + if apierrors.IsNotFound(err) { + return nil + } + if err != nil { + return err + } + + if !apiextensions.IsCRDConditionTrue(cachedCRD, apiextensions.NamesAccepted) || + apiextensions.IsCRDConditionTrue(cachedCRD, apiextensions.Established) { + return nil + } + + crd := cachedCRD.DeepCopy() + establishedCondition := apiextensions.CustomResourceDefinitionCondition{ + Type: apiextensions.Established, + Status: apiextensions.ConditionTrue, + Reason: "InitialNamesAccepted", + Message: "the initial names have been accepted", + } + apiextensions.SetCRDCondition(crd, establishedCondition) + + // Update server with new CRD condition. + _, err = ec.crdClient.CustomResourceDefinitions().UpdateStatus(crd) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/BUILD index c408cf487..0489e9fcc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/BUILD @@ -28,6 +28,7 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go index 16016e493..f00def4b1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go @@ -24,6 +24,7 @@ import ( "github.com/golang/glog" + "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -191,7 +192,10 @@ func (c *NamingConditionController) calculateNamesAndConditions(in *apiextension namesAcceptedCondition.Message = "no conflicts found" } - // set EstablishedCondition to true if all names are accepted. Never set it back to false. + // set EstablishedCondition initially to false, then set it to true in establishing controller. + // The Establishing Controller will see the NamesAccepted condition when it arrives through the shared informer. + // At that time the API endpoint handler will serve the endpoint, avoiding a race + // which we had if we set Established to true here. establishedCondition := apiextensions.CustomResourceDefinitionCondition{ Type: apiextensions.Established, Status: apiextensions.ConditionFalse, @@ -204,8 +208,8 @@ func (c *NamingConditionController) calculateNamesAndConditions(in *apiextension if establishedCondition.Status != apiextensions.ConditionTrue && namesAcceptedCondition.Status == apiextensions.ConditionTrue { establishedCondition = apiextensions.CustomResourceDefinitionCondition{ Type: apiextensions.Established, - Status: apiextensions.ConditionTrue, - Reason: "InitialNamesAccepted", + Status: apiextensions.ConditionFalse, + Reason: "Installing", Message: "the initial names have been accepted", } } @@ -238,12 +242,16 @@ func (c *NamingConditionController) sync(key string) error { return err } + // Skip checking names if Spec and Status names are same. + if equality.Semantic.DeepEqual(inCustomResourceDefinition.Spec.Names, inCustomResourceDefinition.Status.AcceptedNames) { + return nil + } + acceptedNames, namingCondition, establishedCondition := c.calculateNamesAndConditions(inCustomResourceDefinition) // nothing to do if accepted names and NamesAccepted condition didn't change if reflect.DeepEqual(inCustomResourceDefinition.Status.AcceptedNames, acceptedNames) && - apiextensions.IsCRDConditionEquivalent(&namingCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.NamesAccepted)) && - apiextensions.IsCRDConditionEquivalent(&establishedCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.Established)) { + apiextensions.IsCRDConditionEquivalent(&namingCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.NamesAccepted)) { return nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go index 615c5dd85..717e52884 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go @@ -95,19 +95,17 @@ var acceptedCondition = apiextensions.CustomResourceDefinitionCondition{ Message: "no conflicts found", } -func nameConflictCondition(reason, message string) apiextensions.CustomResourceDefinitionCondition { - return apiextensions.CustomResourceDefinitionCondition{ - Type: apiextensions.NamesAccepted, - Status: apiextensions.ConditionFalse, - Reason: reason, - Message: message, - } +var notAcceptedCondition = apiextensions.CustomResourceDefinitionCondition{ + Type: apiextensions.NamesAccepted, + Status: apiextensions.ConditionFalse, + Reason: "NotAccepted", + Message: "not all names are accepted", } -var establishedCondition = apiextensions.CustomResourceDefinitionCondition{ +var installingCondition = apiextensions.CustomResourceDefinitionCondition{ Type: apiextensions.Established, - Status: apiextensions.ConditionTrue, - Reason: "InitialNamesAccepted", + Status: apiextensions.ConditionFalse, + Reason: "Installing", Message: "the initial names have been accepted", } @@ -118,6 +116,15 @@ var notEstablishedCondition = apiextensions.CustomResourceDefinitionCondition{ Message: "not all names are accepted", } +func nameConflictCondition(reason, message string) apiextensions.CustomResourceDefinitionCondition { + return apiextensions.CustomResourceDefinitionCondition{ + Type: apiextensions.NamesAccepted, + Status: apiextensions.ConditionFalse, + Reason: reason, + Message: message, + } +} + func TestSync(t *testing.T) { tests := []struct { name string @@ -136,7 +143,7 @@ func TestSync(t *testing.T) { Plural: "alfa", }, expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "different groups", @@ -146,7 +153,7 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "conflict plural to singular", @@ -206,7 +213,7 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "merge on conflicts", @@ -248,7 +255,7 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { name: "no conflicts on self, remove shortname", @@ -264,44 +271,44 @@ func TestSync(t *testing.T) { }, expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1"), expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { - name: "established before with true condition", - in: newCRD("alfa.bravo.com").Condition(establishedCondition).NewOrDie(), + name: "installing before with true condition", + in: newCRD("alfa.bravo.com").Condition(acceptedCondition).NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{}, expectedNames: apiextensions.CustomResourceDefinitionNames{ Plural: "alfa", }, expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { - name: "not established before with false condition", - in: newCRD("alfa.bravo.com").Condition(notEstablishedCondition).NewOrDie(), + name: "not installing before with false condition", + in: newCRD("alfa.bravo.com").Condition(notAcceptedCondition).NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{}, expectedNames: apiextensions.CustomResourceDefinitionNames{ Plural: "alfa", }, expectedNameConflictCondition: acceptedCondition, - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: installingCondition, }, { - name: "conflicting, established before with true condition", + name: "conflicting, installing before with true condition", in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"). - Condition(establishedCondition). + Condition(acceptedCondition). NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{ newCRD("india.bravo.com").StatusNames("india", "alfa", "", "").NewOrDie(), }, expectedNames: names("", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"), expectedNameConflictCondition: nameConflictCondition("PluralConflict", `"alfa" is already in use`), - expectedEstablishedCondition: establishedCondition, + expectedEstablishedCondition: notEstablishedCondition, }, { - name: "conflicting, not established before with false condition", + name: "conflicting, not installing before with false condition", in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"). - Condition(notEstablishedCondition). + Condition(notAcceptedCondition). NewOrDie(), existing: []*apiextensions.CustomResourceDefinition{ newCRD("india.bravo.com").StatusNames("india", "alfa", "", "").NewOrDie(), @@ -322,7 +329,7 @@ func TestSync(t *testing.T) { crdLister: listers.NewCustomResourceDefinitionLister(crdIndexer), crdMutationCache: cache.NewIntegerResourceVersionMutationCache(crdIndexer, crdIndexer, 60*time.Second, false), } - actualNames, actualNameConflictCondition, actualEstablishedCondition := c.calculateNamesAndConditions(tc.in) + actualNames, actualNameConflictCondition, establishedCondition := c.calculateNamesAndConditions(tc.in) if e, a := tc.expectedNames, actualNames; !reflect.DeepEqual(e, a) { t.Errorf("%v expected %v, got %#v", tc.name, e, a) @@ -330,7 +337,7 @@ func TestSync(t *testing.T) { if e, a := tc.expectedNameConflictCondition, actualNameConflictCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) { t.Errorf("%v expected %v, got %v", tc.name, e, a) } - if e, a := tc.expectedEstablishedCondition, actualEstablishedCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) { + if e, a := tc.expectedEstablishedCondition, establishedCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) { t.Errorf("%v expected %v, got %v", tc.name, e, a) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/features/OWNERS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/features/OWNERS new file mode 100644 index 000000000..fe7b0144e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/features/OWNERS @@ -0,0 +1,2 @@ +approvers: +- feature-approvers diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go index b80e80ac3..24e72f91e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go @@ -36,6 +36,7 @@ const ( // owner: @sttts, @nikhita // alpha: v1.10 + // beta: v1.11 // // CustomResourceSubresources defines the subresources for CustomResources CustomResourceSubresources utilfeature.Feature = "CustomResourceSubresources" @@ -50,5 +51,5 @@ func init() { // available throughout Kubernetes binaries. var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureSpec{ CustomResourceValidation: {Default: true, PreRelease: utilfeature.Beta}, - CustomResourceSubresources: {Default: false, PreRelease: utilfeature.Alpha}, + CustomResourceSubresources: {Default: true, PreRelease: utilfeature.Beta}, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/BUILD index 8f6c52cbd..cebbd87bf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/BUILD @@ -35,7 +35,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", @@ -72,8 +71,10 @@ go_test( "//vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1: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/util/diff:go_default_library", @@ -90,8 +91,5 @@ go_test( name = "go_default_test", srcs = ["status_strategy_test.go"], embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", - ], + deps = ["//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library"], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go index bf54fe33b..d9e8fd97c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go @@ -17,16 +17,17 @@ limitations under the License. package customresource import ( + "context" "fmt" "strings" autoscalingv1 "k8s.io/api/autoscaling/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -106,6 +107,59 @@ func newREST(resource schema.GroupResource, listKind schema.GroupVersionKind, st // Implement CategoriesProvider var _ rest.CategoriesProvider = &REST{} +// List returns a list of items matching labels and field according to the store's PredicateFunc. +func (e *REST) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { + l, err := e.Store.List(ctx, options) + if err != nil { + return nil, err + } + + // Shallow copy ObjectMeta in returned list for each item. Native types have `Items []Item` fields and therefore + // implicitly shallow copy ObjectMeta. The generic store sets the self-link for each item. So this is necessary + // to avoid mutation of the objects from the cache. + if ul, ok := l.(*unstructured.UnstructuredList); ok { + for i := range ul.Items { + shallowCopyObjectMeta(&ul.Items[i]) + } + } + + return l, nil +} + +func (r *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + o, err := r.Store.Get(ctx, name, options) + if err != nil { + return nil, err + } + if u, ok := o.(*unstructured.Unstructured); ok { + shallowCopyObjectMeta(u) + } + return o, nil +} + +func shallowCopyObjectMeta(u runtime.Unstructured) { + obj := shallowMapDeepCopy(u.UnstructuredContent()) + if metadata, ok := obj["metadata"]; ok { + if metadata, ok := metadata.(map[string]interface{}); ok { + obj["metadata"] = shallowMapDeepCopy(metadata) + u.SetUnstructuredContent(obj) + } + } +} + +func shallowMapDeepCopy(in map[string]interface{}) map[string]interface{} { + if in == nil { + return nil + } + + out := make(map[string]interface{}, len(in)) + for k, v := range in { + out[k] = v + } + + return out +} + // Categories implements the CategoriesProvider interface. Returns a list of categories a resource is part of. func (r *REST) Categories() []string { return r.categories @@ -116,17 +170,19 @@ type StatusREST struct { store *genericregistry.Store } +var _ = rest.Patcher(&StatusREST{}) + func (r *StatusREST) New() runtime.Object { return &unstructured.Unstructured{} } // Get retrieves the object from the storage. It is required to support Patch. -func (r *StatusREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) } // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } @@ -150,7 +206,7 @@ func (r *ScaleREST) New() runtime.Object { return &autoscalingv1.Scale{} } -func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (r *ScaleREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { cr, err := r.registry.GetCustomResource(ctx, name, options) if err != nil { return nil, err @@ -166,7 +222,7 @@ func (r *ScaleREST) Get(ctx genericapirequest.Context, name string, options *met return scaleObject, err } -func (r *ScaleREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { cr, err := r.registry.GetCustomResource(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, err diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go index 8bee3396c..15a242e44 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go @@ -21,12 +21,15 @@ import ( "reflect" "strings" "testing" + "time" autoscalingv1 "k8s.io/api/autoscaling/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" + metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" @@ -58,7 +61,7 @@ func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcdtestin typer := apiserver.UnstructuredObjectTyper{ Delegate: parameterScheme, - UnstructuredTyper: discovery.NewUnstructuredObjectTyper(nil), + UnstructuredTyper: discovery.NewUnstructuredObjectTyper(), } kind := schema.GroupVersionKind{Group: "mygroup.example.com", Version: "v1beta1", Kind: "Noxu"} @@ -72,8 +75,19 @@ func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcdtestin status := &apiextensions.CustomResourceSubresourceStatus{} - // TODO: identify how to pass printer specification from the CRD - table, _ := tableconvertor.New(nil) + headers := []apiextensions.CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"}, + {Name: "Replicas", Type: "integer", JSONPath: ".spec.replicas"}, + {Name: "Missing", Type: "string", JSONPath: ".spec.missing"}, + {Name: "Invalid", Type: "integer", JSONPath: ".spec.string"}, + {Name: "String", Type: "string", JSONPath: ".spec.string"}, + {Name: "StringFloat64", Type: "string", JSONPath: ".spec.float64"}, + {Name: "StringInt64", Type: "string", JSONPath: ".spec.replicas"}, + {Name: "StringBool", Type: "string", JSONPath: ".spec.bool"}, + {Name: "Float64", Type: "number", JSONPath: ".spec.float64"}, + {Name: "Bool", Type: "boolean", JSONPath: ".spec.bool"}, + } + table, _ := tableconvertor.New(headers) storage := customresource.NewStorage( schema.GroupResource{Group: "mygroup.example.com", Resource: "noxus"}, @@ -112,11 +126,18 @@ func validNewCustomResource() *unstructured.Unstructured { "apiVersion": "mygroup.example.com/v1beta1", "kind": "Noxu", "metadata": map[string]interface{}{ - "namespace": "default", - "name": "foo", + "namespace": "default", + "name": "foo", + "creationTimestamp": time.Now().Add(-time.Hour*12 - 30*time.Minute).UTC().Format(time.RFC3339), }, "spec": map[string]interface{}{ - "replicas": int64(7), + "replicas": int64(7), + "string": "string", + "float64": float64(3.1415926), + "bool": true, + "stringList": []interface{}{"foo", "bar"}, + "mixedList": []interface{}{"foo", int64(42)}, + "nonPrimitiveList": []interface{}{"foo", []interface{}{int64(1), int64(2)}}, }, }, } @@ -160,6 +181,58 @@ func TestDelete(t *testing.T) { test.TestDelete(validNewCustomResource()) } +func TestGenerationNumber(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.CustomResource.Store.DestroyFunc() + modifiedRno := *validNewCustomResource() + modifiedRno.SetGeneration(10) + ctx := genericapirequest.NewDefaultContext() + cr, err := createCustomResource(storage.CustomResource, modifiedRno, t) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + etcdCR, err := storage.CustomResource.Get(ctx, cr.GetName(), &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + storedCR, _ := etcdCR.(*unstructured.Unstructured) + + // Generation initialization + if storedCR.GetGeneration() != 1 { + t.Fatalf("Unexpected generation number %v", storedCR.GetGeneration()) + } + + // Updates to spec should increment the generation number + setSpecReplicas(storedCR, getSpecReplicas(storedCR)+1) + if _, _, err := storage.CustomResource.Update(ctx, storedCR.GetName(), rest.DefaultUpdatedObjectInfo(storedCR), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc); err != nil { + t.Errorf("unexpected error: %v", err) + } + etcdCR, err = storage.CustomResource.Get(ctx, cr.GetName(), &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + storedCR, _ = etcdCR.(*unstructured.Unstructured) + if storedCR.GetGeneration() != 2 { + t.Fatalf("Unexpected generation, spec: %v", storedCR.GetGeneration()) + } + + // Updates to status should not increment the generation number + setStatusReplicas(storedCR, getStatusReplicas(storedCR)+1) + if _, _, err := storage.CustomResource.Update(ctx, storedCR.GetName(), rest.DefaultUpdatedObjectInfo(storedCR), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc); err != nil { + t.Errorf("unexpected error: %v", err) + } + etcdCR, err = storage.CustomResource.Get(ctx, cr.GetName(), &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + storedCR, _ = etcdCR.(*unstructured.Unstructured) + if storedCR.GetGeneration() != 2 { + t.Fatalf("Unexpected generation, spec: %v", storedCR.GetGeneration()) + } + +} + func TestCategories(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) @@ -173,6 +246,77 @@ func TestCategories(t *testing.T) { } } +func TestColumns(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.CustomResource.Store.DestroyFunc() + + ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault) + key := "/noxus/" + metav1.NamespaceDefault + "/foo" + validCustomResource := validNewCustomResource() + if err := storage.CustomResource.Storage.Create(ctx, key, validCustomResource, nil, 0); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + gottenList, err := storage.CustomResource.List(ctx, &metainternal.ListOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + tbl, err := storage.CustomResource.ConvertToTable(ctx, gottenList, &metav1beta1.TableOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expectedColumns := []struct { + Name, Type string + }{ + {"Name", "string"}, + {"Age", "date"}, + {"Replicas", "integer"}, + {"Missing", "string"}, + {"Invalid", "integer"}, + {"String", "string"}, + {"StringFloat64", "string"}, + {"StringInt64", "string"}, + {"StringBool", "string"}, + {"Float64", "number"}, + {"Bool", "boolean"}, + } + if len(tbl.ColumnDefinitions) != len(expectedColumns) { + t.Fatalf("got %d columns, expected %d. Got: %+v", len(tbl.ColumnDefinitions), len(expectedColumns), tbl.ColumnDefinitions) + } + for i, d := range tbl.ColumnDefinitions { + if d.Name != expectedColumns[i].Name { + t.Errorf("got column %d name %q, expected %q", i, d.Name, expectedColumns[i].Name) + } + if d.Type != expectedColumns[i].Type { + t.Errorf("got column %d type %q, expected %q", i, d.Type, expectedColumns[i].Type) + } + } + + expectedRows := [][]interface{}{ + { + "foo", + "12h", + int64(7), + nil, + nil, + "string", + "3.1415926", + "7", + "true", + float64(3.1415926), + true, + }, + } + for i, r := range tbl.Rows { + if !reflect.DeepEqual(r.Cells, expectedRows[i]) { + t.Errorf("got row %d with cells %#v, expected %#v", i, r.Cells, expectedRows[i]) + } + } +} + func TestStatusUpdate(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) @@ -398,3 +542,34 @@ func (c unstructuredJsonCodec) Encode(obj runtime.Object, w io.Writer) error { w.Write(bs) return nil } + +func setSpecReplicas(u *unstructured.Unstructured, replicas int64) { + setNestedField(u, replicas, "spec", "replicas") +} + +func getSpecReplicas(u *unstructured.Unstructured) int64 { + val, found, err := unstructured.NestedInt64(u.Object, "spec", "replicas") + if !found || err != nil { + return 0 + } + return val +} + +func setStatusReplicas(u *unstructured.Unstructured, replicas int64) { + setNestedField(u, replicas, "status", "replicas") +} + +func getStatusReplicas(u *unstructured.Unstructured) int64 { + val, found, err := unstructured.NestedInt64(u.Object, "status", "replicas") + if !found || err != nil { + return 0 + } + return val +} + +func setNestedField(u *unstructured.Unstructured, value interface{}, fields ...string) { + if u.Object == nil { + u.Object = make(map[string]interface{}) + } + unstructured.SetNestedField(u.Object, value, fields...) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go index a0fd086d0..e3d468036 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go @@ -17,6 +17,7 @@ limitations under the License. package customresource import ( + "context" "fmt" "strings" @@ -26,18 +27,17 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" ) // Registry is an interface for things that know how to store CustomResources. type Registry interface { - ListCustomResources(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error) - WatchCustomResources(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) - GetCustomResource(ctx genericapirequest.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error) - CreateCustomResource(ctx genericapirequest.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error) - UpdateCustomResource(ctx genericapirequest.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error) - DeleteCustomResource(ctx genericapirequest.Context, customResourceID string) error + ListCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error) + WatchCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetCustomResource(ctx context.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error) + CreateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error) + UpdateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error) + DeleteCustomResource(ctx context.Context, customResourceID string) error } // storage puts strong typing around storage calls @@ -51,7 +51,7 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListCustomResources(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error) { +func (s *storage) ListCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error) { if options != nil && options.FieldSelector != nil && !options.FieldSelector.Empty() { return nil, fmt.Errorf("field selector not supported yet") } @@ -62,11 +62,11 @@ func (s *storage) ListCustomResources(ctx genericapirequest.Context, options *me return obj.(*unstructured.UnstructuredList), err } -func (s *storage) WatchCustomResources(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (s *storage) WatchCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { return s.Watch(ctx, options) } -func (s *storage) GetCustomResource(ctx genericapirequest.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error) { +func (s *storage) GetCustomResource(ctx context.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error) { obj, err := s.Get(ctx, customResourceID, options) customResource, ok := obj.(*unstructured.Unstructured) if !ok { @@ -82,7 +82,7 @@ func (s *storage) GetCustomResource(ctx genericapirequest.Context, customResourc return customResource, nil } -func (s *storage) CreateCustomResource(ctx genericapirequest.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error) { +func (s *storage) CreateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error) { obj, err := s.Create(ctx, customResource, rest.ValidateAllObjectFunc, false) if err != nil { return nil, err @@ -90,7 +90,7 @@ func (s *storage) CreateCustomResource(ctx genericapirequest.Context, customReso return obj.(*unstructured.Unstructured), nil } -func (s *storage) UpdateCustomResource(ctx genericapirequest.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error) { +func (s *storage) UpdateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error) { obj, _, err := s.Update(ctx, customResource.GetName(), rest.DefaultUpdatedObjectInfo(customResource), createValidation, updateValidation) if err != nil { return nil, err @@ -98,7 +98,7 @@ func (s *storage) UpdateCustomResource(ctx genericapirequest.Context, customReso return obj.(*unstructured.Unstructured), nil } -func (s *storage) DeleteCustomResource(ctx genericapirequest.Context, customResourceID string) error { +func (s *storage) DeleteCustomResource(ctx context.Context, customResourceID string) error { _, _, err := s.Delete(ctx, customResourceID, nil) return err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go index 4aeaf5efe..1710eb2e1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go @@ -17,10 +17,11 @@ limitations under the License. package customresource import ( + "context" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) type statusStrategy struct { @@ -31,7 +32,7 @@ func NewStatusStrategy(strategy customResourceStrategy) statusStrategy { return statusStrategy{strategy} } -func (a statusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (a statusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { // update is only allowed to set status newCustomResourceObject := obj.(*unstructured.Unstructured) newCustomResource := newCustomResourceObject.UnstructuredContent() @@ -53,6 +54,6 @@ func (a statusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old } // ValidateUpdate is the default update validation for an end user updating status. -func (a statusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return a.customResourceStrategy.validator.ValidateStatusUpdate(ctx, obj, old, a.scale) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go index 79b0235f0..8a651d12b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go @@ -17,11 +17,11 @@ limitations under the License. package customresource import ( + "context" "reflect" "testing" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) func TestPrepareForUpdate(t *testing.T) { @@ -130,7 +130,7 @@ func TestPrepareForUpdate(t *testing.T) { }, } for index, tc := range tcs { - strategy.PrepareForUpdate(genericapirequest.NewContext(), tc.obj, tc.old) + strategy.PrepareForUpdate(context.TODO(), tc.obj, tc.old) if !reflect.DeepEqual(tc.obj, tc.expected) { t.Errorf("test %d failed: expected: %v, got %v", index, tc.expected, tc.obj) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go index 092bfc89c..4895e287a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go @@ -17,6 +17,8 @@ limitations under the License. package customresource import ( + "context" + "github.com/go-openapi/validate" apiequality "k8s.io/apimachinery/pkg/api/equality" @@ -28,7 +30,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" apiserverstorage "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -69,7 +70,7 @@ func (a customResourceStrategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a CustomResource before creation. -func (a customResourceStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (a customResourceStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && a.status != nil { customResourceObject := obj.(*unstructured.Unstructured) customResource := customResourceObject.UnstructuredContent() @@ -85,7 +86,7 @@ func (a customResourceStrategy) PrepareForCreate(ctx genericapirequest.Context, } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (a customResourceStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (a customResourceStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) || a.status == nil { return } @@ -126,7 +127,7 @@ func (a customResourceStrategy) PrepareForUpdate(ctx genericapirequest.Context, } // Validate validates a new CustomResource. -func (a customResourceStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (a customResourceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return a.validator.Validate(ctx, obj, a.scale) } @@ -146,7 +147,7 @@ func (customResourceStrategy) AllowUnconditionalUpdate() bool { } // ValidateUpdate is the default update validation for an end user updating status. -func (a customResourceStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (a customResourceStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return a.validator.ValidateUpdate(ctx, obj, old, a.scale) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/BUILD index e6150d203..9f8a352d3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/BUILD @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -6,13 +6,12 @@ go_library( importpath = "k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/go-openapi/spec:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta/table:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/client-go/util/jsonpath:go_default_library", ], @@ -31,3 +30,9 @@ filegroup( tags = ["automanaged"], visibility = ["//visibility:public"], ) + +go_test( + name = "go_default_test", + srcs = ["tableconvertor_test.go"], + embed = [":go_default_library"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go index 4eb62da6b..e1bed809d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go @@ -18,74 +18,64 @@ package tableconvertor import ( "bytes" + "context" + "encoding/json" "fmt" - "strings" - - "github.com/go-openapi/spec" + "reflect" + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apimachinery/pkg/api/meta" metatable "k8s.io/apimachinery/pkg/api/meta/table" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/client-go/util/jsonpath" ) -const printColumnsKey = "x-kubernetes-print-columns" - var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() -// New creates a new table convertor for the provided OpenAPI schema. If the printer definition cannot be parsed, +// New creates a new table convertor for the provided CRD column definition. If the printer definition cannot be parsed, // error will be returned along with a default table convertor. -func New(extensions spec.Extensions) (rest.TableConvertor, error) { +func New(crdColumns []apiextensions.CustomResourceColumnDefinition) (rest.TableConvertor, error) { headers := []metav1beta1.TableColumnDefinition{ {Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]}, - {Name: "Created At", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"]}, } c := &convertor{ headers: headers, } - format, ok := extensions.GetString(printColumnsKey) - if !ok { - return c, nil - } - // "x-kubernetes-print-columns": "custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion" - parts := strings.SplitN(format, "=", 2) - if len(parts) != 2 || parts[0] != "custom-columns" { - return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns', only support 'custom-columns=NAME=JSONPATH[,NAME=JSONPATH]'") - } - columnSpecs := strings.Split(parts[1], ",") - var columns []*jsonpath.JSONPath - for _, spec := range columnSpecs { - parts := strings.SplitN(spec, ":", 2) - if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 { - return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns', must specify NAME=JSONPATH: %s", spec) - } - path := jsonpath.New(parts[0]) - if err := path.Parse(parts[1]); err != nil { - return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns': %v", spec) + + for _, col := range crdColumns { + path := jsonpath.New(col.Name) + if err := path.Parse(fmt.Sprintf("{%s}", col.JSONPath)); err != nil { + return c, fmt.Errorf("unrecognized column definition %q", col.JSONPath) } path.AllowMissingKeys(true) - columns = append(columns, path) - headers = append(headers, metav1beta1.TableColumnDefinition{ - Name: parts[0], - Type: "string", - Description: fmt.Sprintf("Custom resource definition column from OpenAPI (in JSONPath format): %s", parts[1]), + + desc := fmt.Sprintf("Custom resource definition column (in JSONPath format): %s", col.JSONPath) + if len(col.Description) > 0 { + desc = col.Description + } + + c.additionalColumns = append(c.additionalColumns, path) + c.headers = append(c.headers, metav1beta1.TableColumnDefinition{ + Name: col.Name, + Type: col.Type, + Format: col.Format, + Description: desc, + Priority: col.Priority, }) } - c.columns = columns - c.headers = headers + return c, nil } type convertor struct { - headers []metav1beta1.TableColumnDefinition - columns []*jsonpath.JSONPath + headers []metav1beta1.TableColumnDefinition + additionalColumns []*jsonpath.JSONPath } -func (c *convertor) ConvertToTable(ctx genericapirequest.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { +func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { table := &metav1beta1.Table{ ColumnDefinitions: c.headers, } @@ -103,18 +93,80 @@ func (c *convertor) ConvertToTable(ctx genericapirequest.Context, obj runtime.Ob var err error buf := &bytes.Buffer{} table.Rows, err = metatable.MetaToTableRow(obj, func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) { - cells := make([]interface{}, 2, 2+len(c.columns)) + cells := make([]interface{}, 1, 1+len(c.additionalColumns)) cells[0] = name - cells[1] = age - for _, column := range c.columns { - if err := column.Execute(buf, obj); err != nil { + customHeaders := c.headers[1:] + for i, column := range c.additionalColumns { + results, err := column.FindResults(obj.(runtime.Unstructured).UnstructuredContent()) + if err != nil || len(results) == 0 || len(results[0]) == 0 { cells = append(cells, nil) continue } - cells = append(cells, buf.String()) - buf.Reset() + + // as we only support simple JSON path, we can assume to have only one result (or none, filtered out above) + value := results[0][0].Interface() + if customHeaders[i].Type == "string" { + if err := column.PrintResults(buf, []reflect.Value{reflect.ValueOf(value)}); err == nil { + cells = append(cells, buf.String()) + buf.Reset() + } else { + cells = append(cells, nil) + } + } else { + cells = append(cells, cellForJSONValue(customHeaders[i].Type, value)) + } } return cells, nil }) return table, err } + +func cellForJSONValue(headerType string, value interface{}) interface{} { + if value == nil { + return nil + } + + switch headerType { + case "integer": + switch typed := value.(type) { + case int64: + return typed + case float64: + return int64(typed) + case json.Number: + if i64, err := typed.Int64(); err == nil { + return i64 + } + } + case "number": + switch typed := value.(type) { + case int64: + return float64(typed) + case float64: + return typed + case json.Number: + if f, err := typed.Float64(); err == nil { + return f + } + } + case "boolean": + if b, ok := value.(bool); ok { + return b + } + case "string": + if s, ok := value.(string); ok { + return s + } + case "date": + if typed, ok := value.(string); ok { + var timestamp metav1.Time + err := timestamp.UnmarshalQueryParameter(typed) + if err != nil { + return "" + } + return metatable.ConvertToHumanReadableDateType(timestamp) + } + } + + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go new file mode 100644 index 000000000..179aabb8a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2018 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 tableconvertor + +import ( + "fmt" + "reflect" + "testing" + "time" +) + +func Test_cellForJSONValue(t *testing.T) { + tests := []struct { + headerType string + value interface{} + want interface{} + }{ + {"integer", int64(42), int64(42)}, + {"integer", float64(3.14), int64(3)}, + {"integer", true, nil}, + {"integer", "foo", nil}, + + {"number", int64(42), float64(42)}, + {"number", float64(3.14), float64(3.14)}, + {"number", true, nil}, + {"number", "foo", nil}, + + {"boolean", int64(42), nil}, + {"boolean", float64(3.14), nil}, + {"boolean", true, true}, + {"boolean", "foo", nil}, + + {"string", int64(42), nil}, + {"string", float64(3.14), nil}, + {"string", true, nil}, + {"string", "foo", "foo"}, + + {"date", int64(42), nil}, + {"date", float64(3.14), nil}, + {"date", true, nil}, + {"date", time.Now().Add(-time.Hour*12 - 30*time.Minute).UTC().Format(time.RFC3339), "12h"}, + {"date", time.Now().Add(+time.Hour*12 + 30*time.Minute).UTC().Format(time.RFC3339), ""}, + {"date", "", ""}, + + {"unknown", "foo", nil}, + } + for _, tt := range tests { + t.Run(fmt.Sprintf("%#v of type %s", tt.value, tt.headerType), func(t *testing.T) { + if got := cellForJSONValue(tt.headerType, tt.value); !reflect.DeepEqual(got, tt.want) { + t.Errorf("cellForJSONValue() = %#v, want %#v", got, tt.want) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go index ef5023dc6..5206a17eb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go @@ -17,6 +17,7 @@ limitations under the License. package customresource import ( + "context" "fmt" "math" "strings" @@ -29,7 +30,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" apiservervalidation "k8s.io/apiextensions-apiserver/pkg/apiserver/validation" @@ -42,74 +42,37 @@ type customResourceValidator struct { statusSchemaValidator *validate.SchemaValidator } -func (a customResourceValidator) Validate(ctx genericapirequest.Context, obj runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { +func (a customResourceValidator) Validate(ctx context.Context, obj runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} + } accessor, err := meta.Accessor(obj) if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} } - typeAccessor, err := meta.TypeAccessor(obj) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath("kind"), nil, err.Error())} - } - if typeAccessor.GetKind() != a.kind.Kind { - return field.ErrorList{field.Invalid(field.NewPath("kind"), typeAccessor.GetKind(), fmt.Sprintf("must be %v", a.kind.Kind))} - } - if typeAccessor.GetAPIVersion() != a.kind.Group+"/"+a.kind.Version { - return field.ErrorList{field.Invalid(field.NewPath("apiVersion"), typeAccessor.GetAPIVersion(), fmt.Sprintf("must be %v", a.kind.Group+"/"+a.kind.Version))} - } - customResourceObject, ok := obj.(*unstructured.Unstructured) - // this will never happen. - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), customResourceObject, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", customResourceObject))} + if errs := a.ValidateTypeMeta(ctx, u); len(errs) > 0 { + return errs } - customResource := customResourceObject.UnstructuredContent() - if err = apiservervalidation.ValidateCustomResource(customResource, a.schemaValidator); err != nil { - return field.ErrorList{field.Invalid(field.NewPath(""), customResource, err.Error())} - } + var allErrs field.ErrorList - if scale != nil { - // validate specReplicas - specReplicasPath := strings.TrimPrefix(scale.SpecReplicasPath, ".") // ignore leading period - specReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(specReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, err.Error())} - } - if specReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, "should be a non-negative integer")} - } - if specReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } - - // validate statusReplicas - statusReplicasPath := strings.TrimPrefix(scale.StatusReplicasPath, ".") // ignore leading period - statusReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(statusReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, err.Error())} - } - if statusReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, "should be a non-negative integer")} - } - if statusReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } - - // validate labelSelector - if scale.LabelSelectorPath != nil { - labelSelectorPath := strings.TrimPrefix(*scale.LabelSelectorPath, ".") // ignore leading period - labelSelector, _, err := unstructured.NestedString(customResource, strings.Split(labelSelectorPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(*scale.LabelSelectorPath), labelSelector, err.Error())} - } - } + allErrs = append(allErrs, validation.ValidateObjectMetaAccessor(accessor, a.namespaceScoped, validation.NameIsDNSSubdomain, field.NewPath("metadata"))...) + if err = apiservervalidation.ValidateCustomResource(u.UnstructuredContent(), a.schemaValidator); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(""), u.UnstructuredContent(), err.Error())) } + allErrs = append(allErrs, a.ValidateScaleSpec(ctx, u, scale)...) + allErrs = append(allErrs, a.ValidateScaleStatus(ctx, u, scale)...) - return validation.ValidateObjectMetaAccessor(accessor, a.namespaceScoped, validation.NameIsDNSSubdomain, field.NewPath("metadata")) + return allErrs } -func (a customResourceValidator) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { +func (a customResourceValidator) ValidateUpdate(ctx context.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} + } objAccessor, err := meta.Accessor(obj) if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} @@ -118,69 +81,28 @@ func (a customResourceValidator) ValidateUpdate(ctx genericapirequest.Context, o if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} } - typeAccessor, err := meta.TypeAccessor(obj) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath("kind"), nil, err.Error())} - } - if typeAccessor.GetKind() != a.kind.Kind { - return field.ErrorList{field.Invalid(field.NewPath("kind"), typeAccessor.GetKind(), fmt.Sprintf("must be %v", a.kind.Kind))} - } - if typeAccessor.GetAPIVersion() != a.kind.Group+"/"+a.kind.Version { - return field.ErrorList{field.Invalid(field.NewPath("apiVersion"), typeAccessor.GetAPIVersion(), fmt.Sprintf("must be %v", a.kind.Group+"/"+a.kind.Version))} - } - customResourceObject, ok := obj.(*unstructured.Unstructured) - // this will never happen. - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), customResourceObject, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", customResourceObject))} + if errs := a.ValidateTypeMeta(ctx, u); len(errs) > 0 { + return errs } - customResource := customResourceObject.UnstructuredContent() - if err = apiservervalidation.ValidateCustomResource(customResource, a.schemaValidator); err != nil { - return field.ErrorList{field.Invalid(field.NewPath(""), customResource, err.Error())} - } + var allErrs field.ErrorList - if scale != nil { - // validate specReplicas - specReplicasPath := strings.TrimPrefix(scale.SpecReplicasPath, ".") // ignore leading period - specReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(specReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, err.Error())} - } - if specReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, "should be a non-negative integer")} - } - if specReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } - - // validate statusReplicas - statusReplicasPath := strings.TrimPrefix(scale.StatusReplicasPath, ".") // ignore leading period - statusReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(statusReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, err.Error())} - } - if statusReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, "should be a non-negative integer")} - } - if statusReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } - - // validate labelSelector - if scale.LabelSelectorPath != nil { - labelSelectorPath := strings.TrimPrefix(*scale.LabelSelectorPath, ".") // ignore leading period - labelSelector, _, err := unstructured.NestedString(customResource, strings.Split(labelSelectorPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(*scale.LabelSelectorPath), labelSelector, err.Error())} - } - } + allErrs = append(allErrs, validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata"))...) + if err = apiservervalidation.ValidateCustomResource(u.UnstructuredContent(), a.schemaValidator); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(""), u.UnstructuredContent(), err.Error())) } + allErrs = append(allErrs, a.ValidateScaleSpec(ctx, u, scale)...) + allErrs = append(allErrs, a.ValidateScaleStatus(ctx, u, scale)...) - return validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata")) + return allErrs } -func (a customResourceValidator) ValidateStatusUpdate(ctx genericapirequest.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { +func (a customResourceValidator) ValidateStatusUpdate(ctx context.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} + } objAccessor, err := meta.Accessor(obj) if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} @@ -189,53 +111,85 @@ func (a customResourceValidator) ValidateStatusUpdate(ctx genericapirequest.Cont if err != nil { return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} } + + if errs := a.ValidateTypeMeta(ctx, u); len(errs) > 0 { + return errs + } + + var allErrs field.ErrorList + + allErrs = append(allErrs, validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata"))...) + if err = apiservervalidation.ValidateCustomResource(u.UnstructuredContent(), a.schemaValidator); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(""), u.UnstructuredContent(), err.Error())) + } + allErrs = append(allErrs, a.ValidateScaleStatus(ctx, u, scale)...) + + return allErrs +} + +func (a customResourceValidator) ValidateTypeMeta(ctx context.Context, obj *unstructured.Unstructured) field.ErrorList { typeAccessor, err := meta.TypeAccessor(obj) if err != nil { return field.ErrorList{field.Invalid(field.NewPath("kind"), nil, err.Error())} } + + var allErrs field.ErrorList if typeAccessor.GetKind() != a.kind.Kind { - return field.ErrorList{field.Invalid(field.NewPath("kind"), typeAccessor.GetKind(), fmt.Sprintf("must be %v", a.kind.Kind))} + allErrs = append(allErrs, field.Invalid(field.NewPath("kind"), typeAccessor.GetKind(), fmt.Sprintf("must be %v", a.kind.Kind))) } if typeAccessor.GetAPIVersion() != a.kind.Group+"/"+a.kind.Version { - return field.ErrorList{field.Invalid(field.NewPath("apiVersion"), typeAccessor.GetAPIVersion(), fmt.Sprintf("must be %v", a.kind.Group+"/"+a.kind.Version))} + allErrs = append(allErrs, field.Invalid(field.NewPath("apiVersion"), typeAccessor.GetAPIVersion(), fmt.Sprintf("must be %v", a.kind.Group+"/"+a.kind.Version))) } + return allErrs +} - customResourceObject, ok := obj.(*unstructured.Unstructured) - // this will never happen. - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), customResourceObject, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", customResourceObject))} +func (a customResourceValidator) ValidateScaleSpec(ctx context.Context, obj *unstructured.Unstructured, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + if scale == nil { + return nil } - customResource := customResourceObject.UnstructuredContent() - // validate only the status - customResourceStatus := customResource["status"] - if err = apiservervalidation.ValidateCustomResource(customResourceStatus, a.statusSchemaValidator); err != nil { - return field.ErrorList{field.Invalid(field.NewPath("status"), customResourceStatus, err.Error())} + var allErrs field.ErrorList + + // validate specReplicas + specReplicasPath := strings.TrimPrefix(scale.SpecReplicasPath, ".") // ignore leading period + specReplicas, _, err := unstructured.NestedInt64(obj.UnstructuredContent(), strings.Split(specReplicasPath, ".")...) + if err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, err.Error())) + } else if specReplicas < 0 { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, "should be a non-negative integer")) + } else if specReplicas > math.MaxInt32 { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.SpecReplicasPath), specReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))) } - if scale != nil { - // validate statusReplicas - statusReplicasPath := strings.TrimPrefix(scale.StatusReplicasPath, ".") // ignore leading period - statusReplicas, _, err := unstructured.NestedInt64(customResource, strings.Split(statusReplicasPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, err.Error())} - } - if statusReplicas < 0 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, "should be a non-negative integer")} - } - if statusReplicas > math.MaxInt32 { - return field.ErrorList{field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))} - } + return allErrs +} + +func (a customResourceValidator) ValidateScaleStatus(ctx context.Context, obj *unstructured.Unstructured, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + if scale == nil { + return nil + } + + var allErrs field.ErrorList - // validate labelSelector - if scale.LabelSelectorPath != nil { - labelSelectorPath := strings.TrimPrefix(*scale.LabelSelectorPath, ".") // ignore leading period - labelSelector, _, err := unstructured.NestedString(customResource, strings.Split(labelSelectorPath, ".")...) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath(*scale.LabelSelectorPath), labelSelector, err.Error())} - } + // validate statusReplicas + statusReplicasPath := strings.TrimPrefix(scale.StatusReplicasPath, ".") // ignore leading period + statusReplicas, _, err := unstructured.NestedInt64(obj.UnstructuredContent(), strings.Split(statusReplicasPath, ".")...) + if err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, err.Error())) + } else if statusReplicas < 0 { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, "should be a non-negative integer")) + } else if statusReplicas > math.MaxInt32 { + allErrs = append(allErrs, field.Invalid(field.NewPath(scale.StatusReplicasPath), statusReplicas, fmt.Sprintf("should be less than or equal to %v", math.MaxInt32))) + } + + // validate labelSelector + if scale.LabelSelectorPath != nil { + labelSelectorPath := strings.TrimPrefix(*scale.LabelSelectorPath, ".") // ignore leading period + labelSelector, _, err := unstructured.NestedString(obj.UnstructuredContent(), strings.Split(labelSelectorPath, ".")...) + if err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath(*scale.LabelSelectorPath), labelSelector, err.Error())) } } - return validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata")) + return allErrs } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/BUILD index 2a77d83b3..f2088ab88 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/BUILD @@ -23,7 +23,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go index c501c6a08..8d272ad77 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/etcd.go @@ -17,13 +17,13 @@ limitations under the License. package customresourcedefinition import ( + "context" "fmt" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -66,7 +66,7 @@ func (r *REST) ShortNames() []string { } // Delete adds the CRD finalizer to the list -func (r *REST) Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { +func (r *REST) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { obj, err := r.Get(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, false, err @@ -160,13 +160,18 @@ type StatusREST struct { store *genericregistry.Store } -var _ = rest.Updater(&StatusREST{}) +var _ = rest.Patcher(&StatusREST{}) func (r *StatusREST) New() runtime.Object { return &apiextensions.CustomResourceDefinition{} } +// Get retrieves the object from the storage. It is required to support Patch. +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + return r.store.Get(ctx, name, options) +} + // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go index 7e44fa4c2..a0bebb7a7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go @@ -17,6 +17,7 @@ limitations under the License. package customresourcedefinition import ( + "context" "fmt" apiequality "k8s.io/apimachinery/pkg/api/equality" @@ -24,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" @@ -50,7 +50,7 @@ func (strategy) NamespaceScoped() bool { } // PrepareForCreate clears the status of a CustomResourceDefinition before creation. -func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { crd := obj.(*apiextensions.CustomResourceDefinition) crd.Status = apiextensions.CustomResourceDefinitionStatus{} crd.Generation = 1 @@ -62,10 +62,19 @@ func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Obje if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) { crd.Spec.Subresources = nil } + + for _, v := range crd.Spec.Versions { + if v.Storage { + if !apiextensions.IsStoredVersion(crd, v.Name) { + crd.Status.StoredVersions = append(crd.Status.StoredVersions, v.Name) + } + break + } + } } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. -func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newCRD := obj.(*apiextensions.CustomResourceDefinition) oldCRD := old.(*apiextensions.CustomResourceDefinition) newCRD.Status = oldCRD.Status @@ -90,10 +99,19 @@ func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime newCRD.Spec.Subresources = nil oldCRD.Spec.Subresources = nil } + + for _, v := range newCRD.Spec.Versions { + if v.Storage { + if !apiextensions.IsStoredVersion(newCRD, v.Name) { + newCRD.Status.StoredVersions = append(newCRD.Status.StoredVersions, v.Name) + } + break + } + } } // Validate validates a new CustomResourceDefinition. -func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return validation.ValidateCustomResourceDefinition(obj.(*apiextensions.CustomResourceDefinition)) } @@ -113,7 +131,7 @@ func (strategy) Canonicalize(obj runtime.Object) { } // ValidateUpdate is the default update validation for an end user updating status. -func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateCustomResourceDefinitionUpdate(obj.(*apiextensions.CustomResourceDefinition), old.(*apiextensions.CustomResourceDefinition)) } @@ -130,7 +148,7 @@ func (statusStrategy) NamespaceScoped() bool { return false } -func (statusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (statusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newObj := obj.(*apiextensions.CustomResourceDefinition) oldObj := old.(*apiextensions.CustomResourceDefinition) newObj.Spec = oldObj.Spec @@ -155,7 +173,7 @@ func (statusStrategy) AllowUnconditionalUpdate() bool { func (statusStrategy) Canonicalize(obj runtime.Object) { } -func (statusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateUpdateCustomResourceDefinitionStatus(obj.(*apiextensions.CustomResourceDefinition), old.(*apiextensions.CustomResourceDefinition)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/BUILD index b9617e41a..e2a418f15 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/BUILD @@ -2,6 +2,7 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", + "go_library", "go_test", ) @@ -10,34 +11,41 @@ go_test( srcs = [ "basic_test.go", "finalization_test.go", + "objectmeta_test.go", "registration_test.go", "subresources_test.go", + "table_test.go", "validation_test.go", + "versioning_test.go", "yaml_test.go", ], + embed = [":go_default_library"], tags = ["integration"], deps = [ "//vendor/github.com/coreos/etcd/clientv3:go_default_library", + "//vendor/github.com/coreos/etcd/pkg/transport:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/k8s.io/api/autoscaling/v1:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library", - "//vendor/k8s.io/apiextensions-apiserver/pkg/features:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/test/integration/testserver:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1: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:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//vendor/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", ], ) @@ -56,3 +64,19 @@ filegroup( ], tags = ["automanaged"], ) + +go_library( + name = "go_default_library", + srcs = ["helpers.go"], + importpath = "k8s.io/apiextensions-apiserver/test/integration", + deps = [ + "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library", + "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/dynamic:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go index e373a178a..888675438 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go @@ -17,8 +17,10 @@ limitations under the License. package integration import ( + "fmt" "reflect" "sort" + "strings" "testing" "time" @@ -43,177 +45,217 @@ func TestServerUp(t *testing.T) { } func TestNamespaceScopedCRUD(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - testSimpleCRUD(t, ns, noxuDefinition, noxuVersionClient) - testFieldSelector(t, ns, noxuDefinition, noxuVersionClient) + + testSimpleCRUD(t, ns, noxuDefinition, dynamicClient) + testFieldSelector(t, ns, noxuDefinition, dynamicClient) } func TestClusterScopedCRUD(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "" - testSimpleCRUD(t, ns, noxuDefinition, noxuVersionClient) - testFieldSelector(t, ns, noxuDefinition, noxuVersionClient) + testSimpleCRUD(t, ns, noxuDefinition, dynamicClient) + testFieldSelector(t, ns, noxuDefinition, dynamicClient) } -func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, noxuVersionClient dynamic.Interface) { - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - initialList, err := noxuResourceClient.List(metav1.ListOptions{}) - if err != nil { - t.Fatal(err) - } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { - t.Errorf("expected %v, got %v", e, a) - } - initialListTypeMeta, err := meta.TypeAccessor(initialList) - if err != nil { - t.Fatal(err) - } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, initialListTypeMeta.GetAPIVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := noxuDefinition.Spec.Names.ListKind, initialListTypeMeta.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - initialListListMeta, err := meta.ListAccessor(initialList) - if err != nil { - t.Fatal(err) +func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) { + noxuResourceClients := map[string]dynamic.ResourceInterface{} + noxuWatchs := map[string]watch.Interface{} + disabledVersions := map[string]bool{} + for _, v := range noxuDefinition.Spec.Versions { + disabledVersions[v.Name] = !v.Served } - noxuWatch, err := noxuResourceClient.Watch(metav1.ListOptions{ResourceVersion: initialListListMeta.GetResourceVersion()}) - if err != nil { - t.Fatal(err) - } - defer noxuWatch.Stop() + for _, v := range noxuDefinition.Spec.Versions { + noxuResourceClients[v.Name] = newNamespacedCustomResourceVersionedClient(ns, dynamicClient, noxuDefinition, v.Name) - createdNoxuInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, "foo"), noxuResourceClient, noxuDefinition) - if err != nil { - t.Fatalf("unable to create noxu Instance:%v", err) - } - - select { - case watchEvent := <-noxuWatch.ResultChan(): - if e, a := watch.Added, watchEvent.Type; e != a { - t.Errorf("expected %v, got %v", e, a) - break - } - createdObjectMeta, err := meta.Accessor(watchEvent.Object) - if err != nil { - t.Fatal(err) + noxuWatch, err := noxuResourceClients[v.Name].Watch(metav1.ListOptions{}) + if disabledVersions[v.Name] { + if err == nil { + t.Errorf("expected the watch creation fail for disabled version %s", v.Name) + } + } else { + if err != nil { + t.Fatal(err) + } + noxuWatchs[v.Name] = noxuWatch } - // it should have a UUID - if len(createdObjectMeta.GetUID()) == 0 { - t.Errorf("missing uuid: %#v", watchEvent.Object) + } + defer func() { + for _, w := range noxuWatchs { + w.Stop() } - if e, a := ns, createdObjectMeta.GetNamespace(); e != a { - t.Errorf("expected %v, got %v", e, a) + }() + + for version, noxuResourceClient := range noxuResourceClients { + createdNoxuInstance, err := instantiateVersionedCustomResource(t, testserver.NewVersionedNoxuInstance(ns, "foo", version), noxuResourceClient, noxuDefinition, version) + if disabledVersions[version] { + if err == nil { + t.Errorf("expected the CR creation fail for disabled version %s", version) + } + continue } - createdTypeMeta, err := meta.TypeAccessor(watchEvent.Object) if err != nil { - t.Fatal(err) + t.Fatalf("unable to create noxu Instance:%v", err) } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a { + if e, a := noxuDefinition.Spec.Group+"/"+version, createdNoxuInstance.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) + for watchVersion, noxuWatch := range noxuWatchs { + select { + case watchEvent := <-noxuWatch.ResultChan(): + if e, a := watch.Added, watchEvent.Type; e != a { + t.Errorf("expected %v, got %v", e, a) + break + } + createdObjectMeta, err := meta.Accessor(watchEvent.Object) + if err != nil { + t.Fatal(err) + } + // it should have a UUID + if len(createdObjectMeta.GetUID()) == 0 { + t.Errorf("missing uuid: %#v", watchEvent.Object) + } + if e, a := ns, createdObjectMeta.GetNamespace(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + createdTypeMeta, err := meta.TypeAccessor(watchEvent.Object) + if err != nil { + t.Fatal(err) + } + if e, a := noxuDefinition.Spec.Group+"/"+watchVersion, createdTypeMeta.GetAPIVersion(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + case <-time.After(5 * time.Second): + t.Errorf("missing watch event") + } } - case <-time.After(5 * time.Second): - t.Errorf("missing watch event") - } + // Check get for all versions + for version2, noxuResourceClient2 := range noxuResourceClients { + // Get test + gottenNoxuInstance, err := noxuResourceClient2.Get("foo", metav1.GetOptions{}) - gottenNoxuInstance, err := noxuResourceClient.Get("foo", metav1.GetOptions{}) - if err != nil { - t.Fatal(err) - } - if e, a := createdNoxuInstance, gottenNoxuInstance; !reflect.DeepEqual(e, a) { - t.Errorf("expected %v, got %v", e, a) - } + if disabledVersions[version2] { + if err == nil { + t.Errorf("expected the get operation fail for disabled version %s", version2) + } + } else { + if err != nil { + t.Fatal(err) + } - listWithItem, err := noxuResourceClient.List(metav1.ListOptions{}) - if err != nil { - t.Fatal(err) - } - if e, a := 1, len(listWithItem.(*unstructured.UnstructuredList).Items); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := *createdNoxuInstance, listWithItem.(*unstructured.UnstructuredList).Items[0]; !reflect.DeepEqual(e, a) { - t.Errorf("expected %v, got %v", e, a) - } - - if err := noxuResourceClient.Delete("foo", nil); err != nil { - t.Fatal(err) - } - - listWithoutItem, err := noxuResourceClient.List(metav1.ListOptions{}) - if err != nil { - t.Fatal(err) - } - if e, a := 0, len(listWithoutItem.(*unstructured.UnstructuredList).Items); e != a { - t.Errorf("expected %v, got %v", e, a) - } + if e, a := version2, gottenNoxuInstance.GroupVersionKind().Version; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + } - select { - case watchEvent := <-noxuWatch.ResultChan(): - if e, a := watch.Deleted, watchEvent.Type; e != a { - t.Errorf("expected %v, got %v", e, a) - break + // List test + listWithItem, err := noxuResourceClient2.List(metav1.ListOptions{}) + if disabledVersions[version2] { + if err == nil { + t.Errorf("expected the list operation fail for disabled version %s", version2) + } + } else { + if err != nil { + t.Fatal(err) + } + if e, a := 1, len(listWithItem.Items); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := version2, listWithItem.GroupVersionKind().Version; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := version2, listWithItem.Items[0].GroupVersionKind().Version; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + } } - deletedObjectMeta, err := meta.Accessor(watchEvent.Object) - if err != nil { + + // Delete test + if err := noxuResourceClient.Delete("foo", metav1.NewDeleteOptions(0)); err != nil { t.Fatal(err) } - // it should have a UUID - createdObjectMeta, err := meta.Accessor(createdNoxuInstance) + + listWithoutItem, err := noxuResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) } - if e, a := createdObjectMeta.GetUID(), deletedObjectMeta.GetUID(); e != a { + if e, a := 0, len(listWithoutItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } - case <-time.After(5 * time.Second): - t.Errorf("missing watch event") + for _, noxuWatch := range noxuWatchs { + select { + case watchEvent := <-noxuWatch.ResultChan(): + if e, a := watch.Deleted, watchEvent.Type; e != a { + t.Errorf("expected %v, got %v", e, a) + break + } + deletedObjectMeta, err := meta.Accessor(watchEvent.Object) + if err != nil { + t.Fatal(err) + } + // it should have a UUID + createdObjectMeta, err := meta.Accessor(createdNoxuInstance) + if err != nil { + t.Fatal(err) + } + if e, a := createdObjectMeta.GetUID(), deletedObjectMeta.GetUID(); e != a { + t.Errorf("expected equal UID for (expected) %v, and (actual) %v", createdNoxuInstance, watchEvent.Object) + } + + case <-time.After(5 * time.Second): + t.Errorf("missing watch event") + } + } + + // Delete test + if err := noxuResourceClient.DeleteCollection(metav1.NewDeleteOptions(0), metav1.ListOptions{}); err != nil { + t.Fatal(err) + } } } -func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, noxuVersionClient dynamic.Interface) { - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) +func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) { + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) initialList, err := noxuResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(initialList.Items); e != a { t.Errorf("expected %v, got %v", e, a) } initialListTypeMeta, err := meta.TypeAccessor(initialList) if err != nil { t.Fatal(err) } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, initialListTypeMeta.GetAPIVersion(); e != a { + if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Versions[0].Name, initialListTypeMeta.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := noxuDefinition.Spec.Names.ListKind, initialListTypeMeta.GetKind(); e != a { @@ -268,7 +310,7 @@ func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1b if err != nil { t.Fatal(err) } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a { + if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Versions[0].Name, createdTypeMeta.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { @@ -291,10 +333,10 @@ func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1b if err != nil { t.Fatal(err) } - if e, a := 1, len(listWithItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 1, len(listWithItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := *createdNoxuInstanceFoo, listWithItem.(*unstructured.UnstructuredList).Items[0]; !reflect.DeepEqual(e, a) { + if e, a := *createdNoxuInstanceFoo, listWithItem.Items[0]; !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } @@ -309,7 +351,7 @@ func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1b if err != nil { t.Fatal(err) } - if e, a := 0, len(listWithoutItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(listWithoutItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -347,7 +389,7 @@ func TestDiscovery(t *testing.T) { group := "mygroup.example.com" version := "v1beta1" - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -355,7 +397,7 @@ func TestDiscovery(t *testing.T) { scope := apiextensionsv1beta1.NamespaceScoped noxuDefinition := testserver.NewNoxuCustomResourceDefinition(scope) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -395,25 +437,25 @@ func TestDiscovery(t *testing.T) { } func TestNoNamespaceReject(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) initialList, err := noxuResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(initialList.Items); e != a { t.Errorf("expected %v, got %v", e, a) } initialListTypeMeta, err := meta.TypeAccessor(initialList) @@ -434,27 +476,27 @@ func TestNoNamespaceReject(t *testing.T) { } func TestSameNameDiffNamespace(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns1 := "namespace-1" - testSimpleCRUD(t, ns1, noxuDefinition, noxuVersionClient) + testSimpleCRUD(t, ns1, noxuDefinition, dynamicClient) ns2 := "namespace-2" - testSimpleCRUD(t, ns2, noxuDefinition, noxuVersionClient) + testSimpleCRUD(t, ns2, noxuDefinition, dynamicClient) } func TestSelfLink(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -462,16 +504,13 @@ func TestSelfLink(t *testing.T) { // namespace scoped noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuNamespacedResourceClient := noxuVersionClient.Resource(&metav1.APIResource{ - Name: noxuDefinition.Spec.Names.Plural, - Namespaced: noxuDefinition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuInstanceToCreate := testserver.NewNoxuInstance(ns, "foo") createdNoxuInstance, err := noxuNamespacedResourceClient.Create(noxuInstanceToCreate) @@ -485,15 +524,12 @@ func TestSelfLink(t *testing.T) { // cluster scoped curletDefinition := testserver.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - curletVersionClient, err := testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, clientPool) + curletDefinition, err = testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - curletResourceClient := curletVersionClient.Resource(&metav1.APIResource{ - Name: curletDefinition.Spec.Names.Plural, - Namespaced: curletDefinition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) + curletResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, curletDefinition) curletInstanceToCreate := testserver.NewCurletInstance(ns, "foo") createdCurletInstance, err := curletResourceClient.Create(curletInstanceToCreate) @@ -507,23 +543,20 @@ func TestSelfLink(t *testing.T) { } func TestPreserveInt(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuNamespacedResourceClient := noxuVersionClient.Resource(&metav1.APIResource{ - Name: noxuDefinition.Spec.Names.Plural, - Namespaced: true, - }, ns) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuInstanceToCreate := testserver.NewNoxuInstance(ns, "foo") createdNoxuInstance, err := noxuNamespacedResourceClient.Create(noxuInstanceToCreate) @@ -552,60 +585,64 @@ func TestPreserveInt(t *testing.T) { } func TestPatch(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuNamespacedResourceClient := noxuVersionClient.Resource(&metav1.APIResource{ - Name: noxuDefinition.Spec.Names.Plural, - Namespaced: true, - }, ns) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) + t.Logf("Creating foo") noxuInstanceToCreate := testserver.NewNoxuInstance(ns, "foo") - createdNoxuInstance, err := noxuNamespacedResourceClient.Create(noxuInstanceToCreate) + _, err = noxuNamespacedResourceClient.Create(noxuInstanceToCreate) if err != nil { t.Fatal(err) } + t.Logf("Patching .num.num2 to 999") patch := []byte(`{"num": {"num2":999}}`) - createdNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, patch) + patchedNoxuInstance, err := noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, patch) if err != nil { t.Fatalf("unexpected error: %v", err) } - - // this call waits for the resourceVersion to be reached in the cache before returning. - // We need to do this because the patch gets its initial object from the storage, and the cache serves that. - // If it is out of date, then our initial patch is applied to an old resource version, which conflicts - // and then the updated object shows a conflicting diff, which permanently fails the patch. - // This gives expected stability in the patch without retrying on an known number of conflicts below in the test. - // See https://issue.k8s.io/42644 - _, err = noxuNamespacedResourceClient.Get("foo", metav1.GetOptions{ResourceVersion: createdNoxuInstance.GetResourceVersion()}) + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "num", "num2") + rv, found, err := unstructured.NestedString(patchedNoxuInstance.UnstructuredContent(), "metadata", "resourceVersion") if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Fatal(err) + } + if !found { + t.Fatalf("metadata.resourceVersion not found") } // a patch with no change - createdNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, patch) + t.Logf("Patching .num.num2 again to 999") + patchedNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, patch) if err != nil { t.Fatalf("unexpected error: %v", err) } + // make sure no-op patch does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "num", "num2") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") // an empty patch - createdNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) + t.Logf("Applying empty patch") + patchedNoxuInstance, err = noxuNamespacedResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) if err != nil { t.Fatalf("unexpected error: %v", err) } + // an empty patch is a no-op patch. make sure it does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "num", "num2") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") - originalJSON, err := runtime.Encode(unstructured.UnstructuredJSONScheme, createdNoxuInstance) + originalJSON, err := runtime.Encode(unstructured.UnstructuredJSONScheme, patchedNoxuInstance) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -626,25 +663,25 @@ func TestPatch(t *testing.T) { } func TestCrossNamespaceListWatch(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) initialList, err := noxuResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(initialList.Items); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -661,13 +698,13 @@ func TestCrossNamespaceListWatch(t *testing.T) { instances := make(map[string]*unstructured.Unstructured) ns1 := "namespace-1" - noxuNamespacedResourceClient1 := NewNamespacedCustomResourceClient(ns1, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient1 := newNamespacedCustomResourceClient(ns1, dynamicClient, noxuDefinition) instances[ns1] = createInstanceWithNamespaceHelper(t, ns1, "foo1", noxuNamespacedResourceClient1, noxuDefinition) noxuNamespacesWatch1, err := noxuNamespacedResourceClient1.Watch(metav1.ListOptions{ResourceVersion: initialListListMeta.GetResourceVersion()}) defer noxuNamespacesWatch1.Stop() ns2 := "namespace-2" - noxuNamespacedResourceClient2 := NewNamespacedCustomResourceClient(ns2, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient2 := newNamespacedCustomResourceClient(ns2, dynamicClient, noxuDefinition) instances[ns2] = createInstanceWithNamespaceHelper(t, ns2, "foo2", noxuNamespacedResourceClient2, noxuDefinition) noxuNamespacesWatch2, err := noxuNamespacedResourceClient2.Watch(metav1.ListOptions{ResourceVersion: initialListListMeta.GetResourceVersion()}) defer noxuNamespacesWatch2.Stop() @@ -677,11 +714,11 @@ func TestCrossNamespaceListWatch(t *testing.T) { t.Fatal(err) } - if e, a := 2, len(createdList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 2, len(createdList.Items); e != a { t.Errorf("expected %v, got %v", e, a) } - for _, a := range createdList.(*unstructured.UnstructuredList).Items { + for _, a := range createdList.Items { if e := instances[a.GetNamespace()]; !reflect.DeepEqual(e, &a) { t.Errorf("expected %v, got %v", e, a) } @@ -762,27 +799,27 @@ func checkNamespacesWatchHelper(t *testing.T, ns string, namespacedwatch watch.I } func TestNameConflict(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } noxu2Definition := testserver.NewNoxu2CustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - _, err = apiExtensionClient.Apiextensions().CustomResourceDefinitions().Create(noxu2Definition) + _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(noxu2Definition) if err != nil { t.Fatal(err) } // A NameConflict occurs err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - crd, err := testserver.GetCustomResourceDefinition(noxu2Definition, apiExtensionClient) + crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxu2Definition.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -805,7 +842,7 @@ func TestNameConflict(t *testing.T) { // Names are now accepted err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - crd, err := testserver.GetCustomResourceDefinition(noxu2Definition, apiExtensionClient) + crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxu2Definition.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -821,3 +858,57 @@ func TestNameConflict(t *testing.T) { t.Fatal(err) } } + +func TestStatusGetAndPatch(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + // make sure we don't get 405 Method Not Allowed from Getting CRD/status subresource + result := &apiextensionsv1beta1.CustomResourceDefinition{} + err = apiExtensionClient.ApiextensionsV1beta1().RESTClient().Get(). + Resource("customresourcedefinitions"). + Name(noxuDefinition.Name). + SubResource("status"). + Do(). + Into(result) + if err != nil { + t.Fatal(err) + } + + // make sure we don't get 405 Method Not Allowed from Patching CRD/status subresource + _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions(). + Patch(noxuDefinition.Name, types.StrategicMergePatchType, + []byte(fmt.Sprintf(`{"labels":{"test-label":"dummy"}}`)), + "status") + if err != nil { + t.Fatal(err) + } +} + +func expectInt64(t *testing.T, obj map[string]interface{}, value int64, pth ...string) { + if v, found, err := unstructured.NestedInt64(obj, pth...); err != nil { + t.Fatalf("failed to access .%s: %v", strings.Join(pth, "."), err) + } else if !found { + t.Fatalf("failed to find .%s", strings.Join(pth, ".")) + } else if v != value { + t.Fatalf("wanted %d at .%s, got %d", value, strings.Join(pth, "."), v) + } +} +func expectString(t *testing.T, obj map[string]interface{}, value string, pth ...string) { + if v, found, err := unstructured.NestedString(obj, pth...); err != nil { + t.Fatalf("failed to access .%s: %v", strings.Join(pth, "."), err) + } else if !found { + t.Fatalf("failed to find .%s", strings.Join(pth, ".")) + } else if v != value { + t.Fatalf("wanted %q at .%s, got %q", value, strings.Join(pth, "."), v) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go index 57b04884b..4dcf8d727 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go @@ -18,27 +18,30 @@ package integration import ( "testing" + "time" "github.com/stretchr/testify/require" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/test/integration/testserver" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" ) func TestFinalization(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() require.NoError(t, err) defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) require.NoError(t, err) ns := "not-the-default" name := "foo123" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) instance := testserver.NewNoxuInstance(ns, name) instance.SetFinalizers([]string{"noxu.example.com/finalizer"}) @@ -89,3 +92,74 @@ func TestFinalization(t *testing.T) { require.Error(t, err) require.True(t, errors.IsNotFound(err), "%#v", err) } + +func TestFinalizationAndDeletion(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + require.NoError(t, err) + defer close(stopCh) + + // Create a CRD. + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + require.NoError(t, err) + + // Create a CR with a finalizer. + ns := "not-the-default" + name := "foo123" + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) + + instance := testserver.NewNoxuInstance(ns, name) + instance.SetFinalizers([]string{"noxu.example.com/finalizer"}) + createdNoxuInstance, err := instantiateCustomResource(t, instance, noxuResourceClient, noxuDefinition) + require.NoError(t, err) + + // Delete a CR. Because there's a finalizer, it will not get deleted now. + uid := createdNoxuInstance.GetUID() + err = noxuResourceClient.Delete(name, &metav1.DeleteOptions{ + Preconditions: &metav1.Preconditions{ + UID: &uid, + }, + }) + require.NoError(t, err) + + // Check is the CR scheduled for deletion. + gottenNoxuInstance, err := noxuResourceClient.Get(name, metav1.GetOptions{}) + require.NoError(t, err) + require.NotNil(t, gottenNoxuInstance.GetDeletionTimestamp()) + + // Delete the CRD. + testserver.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient) + + // Check is CR still there after the CRD deletion. + gottenNoxuInstance, err = noxuResourceClient.Get(name, metav1.GetOptions{}) + require.NoError(t, err) + + // Update the CR to remove the finalizer. + for { + gottenNoxuInstance.SetFinalizers(nil) + _, err = noxuResourceClient.Update(gottenNoxuInstance) + if err == nil { + break + } + if !errors.IsConflict(err) { + require.NoError(t, err) // Fail on unexpected error + } + gottenNoxuInstance, err = noxuResourceClient.Get(name, metav1.GetOptions{}) + require.NoError(t, err) + } + + // Verify the CR is gone. + // It should return the NonFound error. + _, err = noxuResourceClient.Get(name, metav1.GetOptions{}) + if !errors.IsNotFound(err) { + t.Fatalf("unable to delete cr: %v", err) + } + + err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { + _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}) + return errors.IsNotFound(err), err + }) + if !errors.IsNotFound(err) { + t.Fatalf("unable to delete crd: %v", err) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/helpers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/helpers.go new file mode 100644 index 000000000..5aa231d45 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/helpers.go @@ -0,0 +1,94 @@ +/* +Copyright 2018 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 integration + +import ( + "fmt" + "testing" + + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" +) + +func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) { + return instantiateVersionedCustomResource(t, instanceToCreate, client, definition, definition.Spec.Versions[0].Name) +} + +func instantiateVersionedCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition, version string) (*unstructured.Unstructured, error) { + createdInstance, err := client.Create(instanceToCreate) + if err != nil { + t.Logf("%#v", createdInstance) + return nil, err + } + createdObjectMeta, err := meta.Accessor(createdInstance) + if err != nil { + t.Fatal(err) + } + // it should have a UUID + if len(createdObjectMeta.GetUID()) == 0 { + t.Errorf("missing uuid: %#v", createdInstance) + } + createdTypeMeta, err := meta.TypeAccessor(createdInstance) + if err != nil { + t.Fatal(err) + } + if e, a := definition.Spec.Group+"/"+version, createdTypeMeta.GetAPIVersion(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := definition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + return createdInstance, nil +} + +func newNamespacedCustomResourceVersionedClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition, version string) dynamic.ResourceInterface { + gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: version, Resource: crd.Spec.Names.Plural} + + if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { + return client.Resource(gvr).Namespace(ns) + } + return client.Resource(gvr) +} + +func newNamespacedCustomResourceClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { + return newNamespacedCustomResourceVersionedClient(ns, client, crd, crd.Spec.Versions[0].Name) +} + +// updateCustomResourceDefinitionWithRetry updates a CRD, retrying up to 5 times on version conflict errors. +func updateCustomResourceDefinitionWithRetry(client clientset.Interface, name string, update func(*apiextensionsv1beta1.CustomResourceDefinition)) (*apiextensionsv1beta1.CustomResourceDefinition, error) { + for i := 0; i < 5; i++ { + crd, err := client.ApiextensionsV1beta1().CustomResourceDefinitions().Get(name, metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to get CustomResourceDefinition %q: %v", name, err) + } + update(crd) + crd, err = client.ApiextensionsV1beta1().CustomResourceDefinitions().Update(crd) + if err == nil { + return crd, nil + } + if !errors.IsConflict(err) { + return nil, fmt.Errorf("failed to update CustomResourceDefinition %q: %v", name, err) + } + } + return nil, fmt.Errorf("too many retries after conflicts updating CustomResourceDefinition %q", name) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go new file mode 100644 index 000000000..50f656bf1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go @@ -0,0 +1,166 @@ +/* +Copyright 2018 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 integration + +import ( + "path" + "reflect" + "strings" + "testing" + + "github.com/coreos/etcd/clientv3" + "github.com/coreos/etcd/pkg/transport" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apiextensions-apiserver/test/integration/testserver" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/json" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/client-go/dynamic" +) + +func TestPostInvalidObjectMeta(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + noxuResourceClient := newNamespacedCustomResourceClient("default", dynamicClient, noxuDefinition) + + obj := testserver.NewNoxuInstance("default", "foo") + unstructured.SetNestedField(obj.UnstructuredContent(), int64(42), "metadata", "unknown") + unstructured.SetNestedField(obj.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "labels") + _, err = instantiateCustomResource(t, obj, noxuResourceClient, noxuDefinition) + if err == nil { + t.Fatalf("unexpected non-error, expected invalid labels to be rejected: %v", err) + } + if status, ok := err.(errors.APIStatus); !ok { + t.Fatalf("expected APIStatus error, but got: %#v", err) + } else if !errors.IsBadRequest(err) { + t.Fatalf("expected BadRequst error, but got: %v", errors.ReasonForError(err)) + } else if !strings.Contains(status.Status().Message, "cannot be handled") { + t.Fatalf("expected 'cannot be handled' error message, got: %v", status.Status().Message) + } + + unstructured.SetNestedField(obj.UnstructuredContent(), map[string]interface{}{"bar": "abc"}, "metadata", "labels") + obj, err = instantiateCustomResource(t, obj, noxuResourceClient, noxuDefinition) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if unknown, found, err := unstructured.NestedInt64(obj.UnstructuredContent(), "metadata", "unknown"); err != nil { + t.Errorf("unexpected error getting metadata.unknown: %v", err) + } else if found { + t.Errorf("unexpected metadata.unknown=%#v: expected this to be pruned", unknown) + } +} + +func TestInvalidObjectMetaInStorage(t *testing.T) { + serverConfig, err := testserver.DefaultServerConfig() + if err != nil { + t.Fatal(err) + } + + stopCh, config, err := testserver.StartServer(serverConfig) + defer close(stopCh) + if err != nil { + t.Fatal(err) + } + + apiExtensionClient, err := clientset.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + restOptions, err := serverConfig.GenericConfig.RESTOptionsGetter.GetRESTOptions(schema.GroupResource{Group: noxuDefinition.Spec.Group, Resource: noxuDefinition.Spec.Names.Plural}) + if err != nil { + t.Fatal(err) + } + tlsInfo := transport.TLSInfo{ + CertFile: restOptions.StorageConfig.CertFile, + KeyFile: restOptions.StorageConfig.KeyFile, + CAFile: restOptions.StorageConfig.CAFile, + } + tlsConfig, err := tlsInfo.ClientConfig() + if err != nil { + t.Fatal(err) + } + etcdConfig := clientv3.Config{ + Endpoints: restOptions.StorageConfig.ServerList, + TLS: tlsConfig, + } + etcdclient, err := clientv3.New(etcdConfig) + if err != nil { + t.Fatal(err) + } + + t.Logf("Creating object with invalid labels manually in etcd") + + original := testserver.NewNoxuInstance("default", "foo") + unstructured.SetNestedField(original.UnstructuredContent(), int64(42), "metadata", "unknown") + unstructured.SetNestedField(original.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "labels") + + ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault) + key := path.Join("/", restOptions.StorageConfig.Prefix, noxuDefinition.Spec.Group, "noxus/default/foo") + val, _ := json.Marshal(original.UnstructuredContent()) + if _, err := etcdclient.Put(ctx, key, string(val)); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + t.Logf("Checking that ObjectMeta is pruned from unknown fields") + + noxuResourceClient := newNamespacedCustomResourceClient("default", dynamicClient, noxuDefinition) + obj, err := noxuResourceClient.Get("foo", metav1.GetOptions{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if unknown, found, err := unstructured.NestedFieldNoCopy(obj.UnstructuredContent(), "metadata", "unknown"); err != nil { + t.Errorf("unexpected error: %v", err) + } else if found { + t.Errorf("unexpected to find metadata.unknown=%#v", unknown) + } + + t.Logf("Checking that ObjectMeta is pruned from invalid typed fields") + + if labels, found, err := unstructured.NestedStringMap(obj.UnstructuredContent(), "metadata", "labels"); err != nil { + t.Errorf("unexpected error: %v", err) + } else if found && !reflect.DeepEqual(labels, map[string]string{"bar": "abc"}) { + t.Errorf("unexpected to find metadata.lables=%#v", labels) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/registration_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/registration_test.go index 7cdd2bc7c..9cb33ac70 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/registration_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/registration_test.go @@ -40,56 +40,8 @@ import ( "k8s.io/client-go/dynamic" ) -func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) { - createdInstance, err := client.Create(instanceToCreate) - if err != nil { - t.Logf("%#v", createdInstance) - return nil, err - } - createdObjectMeta, err := meta.Accessor(createdInstance) - if err != nil { - t.Fatal(err) - } - // it should have a UUID - if len(createdObjectMeta.GetUID()) == 0 { - t.Errorf("missing uuid: %#v", createdInstance) - } - createdTypeMeta, err := meta.TypeAccessor(createdInstance) - if err != nil { - t.Fatal(err) - } - if e, a := definition.Spec.Group+"/"+definition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := definition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - return createdInstance, nil -} - -func NewNamespacedCustomResourceClient(ns string, client dynamic.Interface, definition *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { - return client.Resource(&metav1.APIResource{ - Name: definition.Spec.Names.Plural, - Namespaced: definition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) -} - -func NewNamespacedCustomResourceStatusClient(ns string, client dynamic.Interface, definition *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { - return client.Resource(&metav1.APIResource{ - Name: definition.Spec.Names.Plural + "/status", - Namespaced: definition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) -} - -func NewNamespacedCustomResourceScaleClient(ns string, client dynamic.Interface, definition *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { - return client.Resource(&metav1.APIResource{ - Name: definition.Spec.Names.Plural + "/scale", - Namespaced: definition.Spec.Scope == apiextensionsv1beta1.NamespaceScoped, - }, ns) -} - func TestMultipleResourceInstances(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -97,11 +49,11 @@ func TestMultipleResourceInstances(t *testing.T) { ns := "not-the-default" noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuList, err := noxuNamespacedResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) @@ -168,10 +120,10 @@ func TestMultipleResourceInstances(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := len(instances), len(listWithItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := len(instances), len(listWithItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } - for _, a := range listWithItem.(*unstructured.UnstructuredList).Items { + for _, a := range listWithItem.Items { if e := instances[a.GetName()].Instance; !reflect.DeepEqual(e, &a) { t.Errorf("expected %v, got %v", e, a) } @@ -185,7 +137,7 @@ func TestMultipleResourceInstances(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := 0, len(listWithoutItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(listWithoutItem.Items); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -213,7 +165,7 @@ func TestMultipleResourceInstances(t *testing.T) { } func TestMultipleRegistration(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -222,11 +174,11 @@ func TestMultipleRegistration(t *testing.T) { ns := "not-the-default" sameInstanceName := "foo" noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) createdNoxuInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu Instance:%v", err) @@ -241,11 +193,11 @@ func TestMultipleRegistration(t *testing.T) { } curletDefinition := testserver.NewCurletCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - curletVersionClient, err := testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, clientPool) + curletDefinition, err = testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - curletNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, curletVersionClient, curletDefinition) + curletNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, curletDefinition) createdCurletInstance, err := instantiateCustomResource(t, testserver.NewCurletInstance(ns, sameInstanceName), curletNamespacedResourceClient, curletDefinition) if err != nil { t.Fatalf("unable to create noxu Instance:%v", err) @@ -269,7 +221,7 @@ func TestMultipleRegistration(t *testing.T) { } func TestDeRegistrationAndReRegistration(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -278,18 +230,18 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { ns := "not-the-default" sameInstanceName := "foo" func() { - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) if _, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition); err != nil { t.Fatal(err) } if err := testserver.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } - if _, err := testserver.GetCustomResourceDefinition(noxuDefinition, apiExtensionClient); err == nil || !errors.IsNotFound(err) { + if _, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { t.Fatalf("expected a NotFound error, got:%v", err) } if _, err = noxuNamespacedResourceClient.List(metav1.ListOptions{}); err == nil || !errors.IsNotFound(err) { @@ -301,14 +253,14 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { }() func() { - if _, err := testserver.GetCustomResourceDefinition(noxuDefinition, apiExtensionClient); err == nil || !errors.IsNotFound(err) { + if _, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { t.Fatalf("expected a NotFound error, got:%v", err) } - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) initialList, err := noxuNamespacedResourceClient.List(metav1.ListOptions{}) if err != nil { t.Fatal(err) @@ -316,7 +268,7 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { if _, err = noxuNamespacedResourceClient.Get(sameInstanceName, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { t.Fatalf("expected a NotFound error, got:%v", err) } - if e, a := 0, len(initialList.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(initialList.Items); e != a { t.Fatalf("expected %v, got %v", e, a) } createdNoxuInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition) @@ -334,10 +286,10 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := 1, len(listWithItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 1, len(listWithItem.Items); e != a { t.Fatalf("expected %v, got %v", e, a) } - if e, a := *createdNoxuInstance, listWithItem.(*unstructured.UnstructuredList).Items[0]; !reflect.DeepEqual(e, a) { + if e, a := *createdNoxuInstance, listWithItem.Items[0]; !reflect.DeepEqual(e, a) { t.Fatalf("expected %v, got %v", e, a) } @@ -351,7 +303,7 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := 0, len(listWithoutItem.(*unstructured.UnstructuredList).Items); e != a { + if e, a := 0, len(listWithoutItem.Items); e != a { t.Fatalf("expected %v, got %v", e, a) } }() @@ -372,28 +324,31 @@ func TestEtcdStorage(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(clientConfig) + dynamicClient, err := dynamic.NewForConfig(clientConfig) + if err != nil { + t.Fatal(err) + } etcdPrefix := getPrefixFromConfig(t, config) ns1 := "another-default-is-possible" curletDefinition := testserver.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - curletVersionClient, err := testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, clientPool) + curletDefinition, err = testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - curletNamespacedResourceClient := NewNamespacedCustomResourceClient(ns1, curletVersionClient, curletDefinition) + curletNamespacedResourceClient := newNamespacedCustomResourceClient(ns1, dynamicClient, curletDefinition) if _, err := instantiateCustomResource(t, testserver.NewCurletInstance(ns1, "bar"), curletNamespacedResourceClient, curletDefinition); err != nil { t.Fatalf("unable to create curlet cluster scoped Instance:%v", err) } ns2 := "the-cruel-default" noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns2, noxuVersionClient, noxuDefinition) + noxuNamespacedResourceClient := newNamespacedCustomResourceClient(ns2, dynamicClient, noxuDefinition) if _, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns2, "foo"), noxuNamespacedResourceClient, noxuDefinition); err != nil { t.Fatalf("unable to create noxu namespace scoped Instance:%v", err) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go index 7f04c8215..4421d840d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go @@ -22,7 +22,6 @@ import ( "sort" "strings" "testing" - "time" autoscaling "k8s.io/api/autoscaling/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -30,14 +29,10 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/dynamic" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "k8s.io/apiextensions-apiserver/pkg/features" "k8s.io/apiextensions-apiserver/test/integration/testserver" ) @@ -90,24 +85,20 @@ func NewNoxuSubresourceInstance(namespace, name string) *unstructured.Unstructur } func TestStatusSubresource(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -137,7 +128,7 @@ func TestStatusSubresource(t *testing.T) { // UpdateStatus should not update spec. // Check that .spec.num = 10 and .status.num = 20 - updatedStatusInstance, err := noxuStatusResourceClient.Update(gottenNoxuInstance) + updatedStatusInstance, err := noxuResourceClient.UpdateStatus(gottenNoxuInstance) if err != nil { t.Fatalf("unable to update status: %v", err) } @@ -200,9 +191,6 @@ func TestStatusSubresource(t *testing.T) { } func TestScaleSubresource(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - groupResource := schema.GroupResource{ Group: "mygroup.example.com", Resource: "noxus", @@ -218,26 +206,28 @@ func TestScaleSubresource(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) // set invalid json path for specReplicasPath noxuDefinition.Spec.Subresources.Scale.SpecReplicasPath = "foo,bar" - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatalf("unexpected non-error: specReplicasPath should be a valid json path under .spec") } noxuDefinition.Spec.Subresources.Scale.SpecReplicasPath = ".spec.replicas" - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -257,7 +247,7 @@ func TestScaleSubresource(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - _, err = noxuStatusResourceClient.Update(gottenNoxuInstance) + _, err = noxuResourceClient.UpdateStatus(gottenNoxuInstance) if err != nil { t.Fatalf("unable to update status: %v", err) } @@ -332,9 +322,6 @@ func TestScaleSubresource(t *testing.T) { } func TestValidationSchema(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - stopCh, config, err := testserver.StartDefaultServer() if err != nil { t.Fatal(err) @@ -345,13 +332,19 @@ func TestValidationSchema(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } // fields other than properties in root schema are not allowed noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition.Spec.Subresources = &apiextensionsv1beta1.CustomResourceSubresources{ + Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, + } + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { - t.Fatalf("unexpected non-error: if subresources for custom resources are enabled, only properties can be used at the root of the schema") + t.Fatalf(`unexpected non-error, expected: must only have "properties" or "required" at the root if the status subresource is enabled`) } // make sure we are not restricting fields to properties even in subschemas @@ -366,18 +359,17 @@ func TestValidationSchema(t *testing.T) { }, }, }, + Required: []string{"spec"}, + Description: "This is a description at the root of the schema", } - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatalf("unable to created crd %v: %v", noxuDefinition.Name, err) } } func TestValidateOnlyStatus(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -386,9 +378,8 @@ func TestValidateOnlyStatus(t *testing.T) { // UpdateStatus should validate only status // 1. create a crd with max value of .spec.num = 10 and .status.num = 10 // 2. create a cr with .spec.num = 10 and .status.num = 10 (valid) - // 3. update the crd so that max value of .spec.num = 5 and .status.num = 10 - // 4. update the status of the cr with .status.num = 5 (spec is invalid) - // validation passes becauses spec is not validated + // 3. update the spec of the cr with .spec.num = 15 (spec is invalid), expect no error + // 4. update the spec of the cr with .spec.num = 15 (spec is invalid), expect error // max value of spec.num = 10 and status.num = 10 schema := &apiextensionsv1beta1.JSONSchemaProps{ @@ -417,13 +408,12 @@ func TestValidateOnlyStatus(t *testing.T) { OpenAPIV3Schema: schema, } - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) // set .spec.num = 10 and .status.num = 10 noxuInstance := NewNoxuSubresourceInstance(ns, "foo") @@ -437,65 +427,35 @@ func TestValidateOnlyStatus(t *testing.T) { t.Fatalf("unable to create noxu instance: %v", err) } - gottenCRD, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get("noxus.mygroup.example.com", metav1.GetOptions{}) + // update the spec with .spec.num = 15, expecting no error + err = unstructured.SetNestedField(createdNoxuInstance.Object, int64(15), "spec", "num") if err != nil { - t.Fatal(err) + t.Fatalf("unexpected error setting .spec.num: %v", err) } - - // update the crd so that max value of spec.num = 5 and status.num = 10 - gottenCRD.Spec.Validation.OpenAPIV3Schema = &apiextensionsv1beta1.JSONSchemaProps{ - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ - "spec": { - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ - "num": { - Type: "integer", - Maximum: float64Ptr(5), - }, - }, - }, - "status": { - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ - "num": { - Type: "integer", - Maximum: float64Ptr(10), - }, - }, - }, - }, - } - - if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(gottenCRD); err != nil { - t.Fatal(err) - } - - // update the status with .status.num = 5 - err = unstructured.SetNestedField(createdNoxuInstance.Object, int64(5), "status", "num") + createdNoxuInstance, err = noxuResourceClient.UpdateStatus(createdNoxuInstance) if err != nil { - t.Fatalf("unexpected error: %v", err) + t.Errorf("unexpected error: %v", err) } - // cr is updated even though spec is invalid - err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - _, err := noxuStatusResourceClient.Update(createdNoxuInstance) - if statusError, isStatus := err.(*apierrors.StatusError); isStatus { - if strings.Contains(statusError.Error(), "is invalid") { - return false, nil - } - } - if err != nil { - return false, err - } - return true, nil - }) + // update with .status.num = 15, expecting an error + err = unstructured.SetNestedField(createdNoxuInstance.Object, int64(15), "status", "num") if err != nil { - t.Fatal(err) + t.Fatalf("unexpected error setting .status.num: %v", err) + } + createdNoxuInstance, err = noxuResourceClient.UpdateStatus(createdNoxuInstance) + if err == nil { + t.Fatal("expected error, but got none") + } + statusError, isStatus := err.(*apierrors.StatusError) + if !isStatus || statusError == nil { + t.Fatalf("expected status error, got %T: %v", err, err) + } + if !strings.Contains(statusError.Error(), "Invalid value") { + t.Fatalf("expected 'Invalid value' in error, got: %v", err) } } func TestSubresourcesDiscovery(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - stopCh, config, err := testserver.StartDefaultServer() if err != nil { t.Fatal(err) @@ -506,10 +466,13 @@ func TestSubresourcesDiscovery(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -577,24 +540,20 @@ func TestSubresourcesDiscovery(t *testing.T) { } func TestGeneration(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -616,7 +575,7 @@ func TestGeneration(t *testing.T) { } // UpdateStatus does not increment generation - updatedStatusInstance, err := noxuStatusResourceClient.Update(gottenNoxuInstance) + updatedStatusInstance, err := noxuResourceClient.UpdateStatus(gottenNoxuInstance) if err != nil { t.Fatalf("unable to update status: %v", err) } @@ -646,9 +605,6 @@ func TestGeneration(t *testing.T) { } func TestSubresourcePatch(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - groupResource := schema.GroupResource{ Group: "mygroup.example.com", Resource: "noxus", @@ -664,18 +620,21 @@ func TestSubresourcePatch(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) - noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, noxuVersionClient, noxuDefinition) - noxuScaleResourceClient := NewNamespacedCustomResourceScaleClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) + + t.Logf("Creating foo") _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -686,28 +645,21 @@ func TestSubresourcePatch(t *testing.T) { t.Fatal(err) } + t.Logf("Patching .status.num to 999") patch := []byte(`{"spec": {"num":999}, "status": {"num":999}}`) - patchedNoxuInstance, err := noxuStatusResourceClient.Patch("foo", types.MergePatchType, patch) + patchedNoxuInstance, err := noxuResourceClient.Patch("foo", types.MergePatchType, patch, "status") if err != nil { t.Fatalf("unexpected error: %v", err) } - // .spec.num should remain 10 - specNum, found, err := unstructured.NestedInt64(patchedNoxuInstance.Object, "spec", "num") - if !found || err != nil { - t.Fatalf("unable to get .spec.num") - } - if specNum != 10 { - t.Fatalf(".spec.num: expected: %v, got: %v", 10, specNum) - } - - // .status.num should be 999 - statusNum, found, err := unstructured.NestedInt64(patchedNoxuInstance.Object, "status", "num") - if !found || err != nil { - t.Fatalf("unable to get .status.num") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "status", "num") // .status.num should be 999 + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 10, "spec", "num") // .spec.num should remain 10 + rv, found, err := unstructured.NestedString(patchedNoxuInstance.UnstructuredContent(), "metadata", "resourceVersion") + if err != nil { + t.Fatal(err) } - if statusNum != 999 { - t.Fatalf(".status.num: expected: %v, got: %v", 999, statusNum) + if !found { + t.Fatalf("metadata.resourceVersion not found") } // this call waits for the resourceVersion to be reached in the cache before returning. @@ -722,23 +674,44 @@ func TestSubresourcePatch(t *testing.T) { } // no-op patch - _, err = noxuStatusResourceClient.Patch("foo", types.MergePatchType, patch) + t.Logf("Patching .status.num again to 999") + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "status") if err != nil { t.Fatalf("unexpected error: %v", err) } + // make sure no-op patch does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "status", "num") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 10, "spec", "num") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") // empty patch - _, err = noxuStatusResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) + t.Logf("Applying empty patch") + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`), "status") if err != nil { t.Fatalf("unexpected error: %v", err) } + // an empty patch is a no-op patch. make sure it does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "status", "num") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 10, "spec", "num") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") + t.Logf("Patching .spec.replicas to 7") patch = []byte(`{"spec": {"replicas":7}, "status": {"replicas":7}}`) - patchedNoxuInstance, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, patch) + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "scale") if err != nil { t.Fatalf("unexpected error: %v", err) } + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 7, "spec", "replicas") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 0, "status", "replicas") // .status.replicas should remain 0 + rv, found, err = unstructured.NestedString(patchedNoxuInstance.UnstructuredContent(), "metadata", "resourceVersion") + if err != nil { + t.Fatal(err) + } + if !found { + t.Fatalf("metadata.resourceVersion not found") + } + // this call waits for the resourceVersion to be reached in the cache before returning. // We need to do this because the patch gets its initial object from the storage, and the cache serves that. // If it is out of date, then our initial patch is applied to an old resource version, which conflicts @@ -750,7 +723,7 @@ func TestSubresourcePatch(t *testing.T) { t.Fatalf("unexpected error: %v", err) } - // Scale.Spec.Replicas = 7 but Scale.Status.Replicas should remain 7 + // Scale.Spec.Replicas = 7 but Scale.Status.Replicas should remain 0 gottenScale, err := scaleClient.Scales("not-the-default").Get(groupResource, "foo") if err != nil { t.Fatal(err) @@ -763,24 +736,34 @@ func TestSubresourcePatch(t *testing.T) { } // no-op patch - _, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, patch) + t.Logf("Patching .spec.replicas again to 7") + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "scale") if err != nil { t.Fatalf("unexpected error: %v", err) } + // make sure no-op patch does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 7, "spec", "replicas") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 0, "status", "replicas") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") // empty patch - _, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) + t.Logf("Applying empty patch") + patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`), "scale") if err != nil { t.Fatalf("unexpected error: %v", err) } + // an empty patch is a no-op patch. make sure it does not increment resourceVersion + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 7, "spec", "replicas") + expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 0, "status", "replicas") + expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") // make sure strategic merge patch is not supported for both status and scale - _, err = noxuStatusResourceClient.Patch("foo", types.StrategicMergePatchType, patch) + _, err = noxuResourceClient.Patch("foo", types.StrategicMergePatchType, patch, "status") if err == nil { t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources") } - _, err = noxuScaleResourceClient.Patch("foo", types.StrategicMergePatchType, patch) + _, err = noxuResourceClient.Patch("foo", types.StrategicMergePatchType, patch, "scale") if err == nil { t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources") } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go new file mode 100644 index 000000000..0c3ac609a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go @@ -0,0 +1,185 @@ +/* +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 integration + +import ( + "fmt" + "testing" + + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/test/integration/testserver" +) + +func newTableCRD() *apiextensionsv1beta1.CustomResourceDefinition { + return &apiextensionsv1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "tables.mygroup.example.com"}, + Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Version: "v1beta1", + Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Plural: "tables", + Singular: "table", + Kind: "Table", + ListKind: "TablemList", + }, + Scope: apiextensionsv1beta1.ClusterScoped, + AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{ + {Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"}, + {Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"}, + {Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"}, + {Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values", JSONPath: ".spec.gamma"}, + }, + }, + } +} + +func newTableInstance(name string) *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "mygroup.example.com/v1beta1", + "kind": "Table", + "metadata": map[string]interface{}{ + "name": name, + }, + "spec": map[string]interface{}{ + "alpha": "foo_123", + "beta": 10, + "gamma": "bar", + "delta": "hello", + }, + }, + } +} + +func TestTableGet(t *testing.T) { + stopCh, config, err := testserver.StartDefaultServer() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + apiExtensionClient, err := clientset.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + crd := newTableCRD() + crd, err = testserver.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crd.Name, metav1.GetOptions{}) + if err != nil { + t.Fatal(err) + } + t.Logf("table crd created: %#v", crd) + + crClient := newNamespacedCustomResourceClient("", dynamicClient, crd) + foo, err := crClient.Create(newTableInstance("foo")) + if err != nil { + t.Fatalf("unable to create noxu instance: %v", err) + } + t.Logf("foo created: %#v", foo.UnstructuredContent()) + + gv := schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version} + gvk := gv.WithKind(crd.Spec.Names.Kind) + + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + parameterCodec := runtime.NewParameterCodec(scheme) + metav1.AddToGroupVersion(scheme, gv) + scheme.AddKnownTypes(gv, &metav1beta1.Table{}, &metav1beta1.TableOptions{}) + scheme.AddKnownTypes(metav1beta1.SchemeGroupVersion, &metav1beta1.Table{}, &metav1beta1.TableOptions{}) + + crConfig := *config + crConfig.GroupVersion = &gv + crConfig.APIPath = "/apis" + crConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: codecs} + crRestClient, err := rest.RESTClientFor(&crConfig) + if err != nil { + t.Fatal(err) + } + + ret, err := crRestClient.Get(). + Resource(crd.Spec.Names.Plural). + SetHeader("Accept", fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName)). + VersionedParams(&metav1beta1.TableOptions{}, parameterCodec). + Do(). + Get() + if err != nil { + t.Fatalf("failed to list %v resources: %v", gvk, err) + } + + tbl, ok := ret.(*metav1beta1.Table) + if !ok { + t.Fatalf("expected metav1beta1.Table, got %T", ret) + } + t.Logf("%v table list: %#v", gvk, tbl) + + if got, expected := len(tbl.ColumnDefinitions), 5; got != expected { + t.Errorf("expected %d headers, got %d", expected, got) + } else { + alpha := metav1beta1.TableColumnDefinition{Name: "Alpha", Type: "string", Format: "", Description: "Custom resource definition column (in JSONPath format): .spec.alpha", Priority: 0} + if got, expected := tbl.ColumnDefinitions[2], alpha; got != expected { + t.Errorf("expected column definition %#v, got %#v", expected, got) + } + + beta := metav1beta1.TableColumnDefinition{Name: "Beta", Type: "integer", Format: "int64", Description: "the beta field", Priority: 42} + if got, expected := tbl.ColumnDefinitions[3], beta; got != expected { + t.Errorf("expected column definition %#v, got %#v", expected, got) + } + + gamma := metav1beta1.TableColumnDefinition{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values"} + if got, expected := tbl.ColumnDefinitions[4], gamma; got != expected { + t.Errorf("expected column definition %#v, got %#v", expected, got) + } + } + if got, expected := len(tbl.Rows), 1; got != expected { + t.Errorf("expected %d rows, got %d", expected, got) + } else if got, expected := len(tbl.Rows[0].Cells), 5; got != expected { + t.Errorf("expected %d cells, got %d", expected, got) + } else { + if got, expected := tbl.Rows[0].Cells[0], "foo"; got != expected { + t.Errorf("expected cell[0] to equal %q, got %q", expected, got) + } + if got, expected := tbl.Rows[0].Cells[2], "foo_123"; got != expected { + t.Errorf("expected cell[2] to equal %q, got %q", expected, got) + } + if got, expected := tbl.Rows[0].Cells[3], int64(10); got != expected { + t.Errorf("expected cell[3] to equal %#v, got %#v", expected, got) + } + if got, expected := tbl.Rows[0].Cells[4], interface{}(nil); got != expected { + t.Errorf("expected cell[3] to equal %#v although the type does not match the column, got %#v", expected, got) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/BUILD index 8c12d58d3..3e55438bd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/BUILD @@ -19,7 +19,6 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", @@ -31,6 +30,7 @@ go_library( "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", "//vendor/k8s.io/client-go/scale:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go index bf54e1490..f341b002f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/resources.go @@ -23,7 +23,6 @@ import ( apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" @@ -33,6 +32,7 @@ import ( "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" "k8s.io/client-go/scale" ) @@ -79,10 +79,10 @@ func NewNoxuCustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) * } } -func NewNoxuInstance(namespace, name string) *unstructured.Unstructured { +func NewVersionedNoxuInstance(namespace, name, version string) *unstructured.Unstructured { return &unstructured.Unstructured{ Object: map[string]interface{}{ - "apiVersion": "mygroup.example.com/v1beta1", + "apiVersion": "mygroup.example.com/" + version, "kind": "WishIHadChosenNoxu", "metadata": map[string]interface{}{ "namespace": namespace, @@ -99,6 +99,46 @@ func NewNoxuInstance(namespace, name string) *unstructured.Unstructured { } } +func NewNoxuInstance(namespace, name string) *unstructured.Unstructured { + return NewVersionedNoxuInstance(namespace, name, "v1beta1") +} + +func NewMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { + return &apiextensionsv1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, + Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Version: "v1beta1", + Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Plural: "noxus", + Singular: "nonenglishnoxu", + Kind: "WishIHadChosenNoxu", + ShortNames: []string{"foo", "bar", "abc", "def"}, + ListKind: "NoxuItemList", + Categories: []string{"all"}, + }, + Scope: scope, + Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: false, + }, + { + Name: "v1beta2", + Served: true, + Storage: true, + }, + { + Name: "v0", + Served: false, + Storage: false, + }, + }, + }, + } +} + func NewNoxu2CustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { return &apiextensionsv1beta1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "noxus2.mygroup.example.com"}, @@ -150,38 +190,60 @@ func NewCurletInstance(namespace, name string) *unstructured.Unstructured { } } +func servedVersions(crd *apiextensionsv1beta1.CustomResourceDefinition) []string { + if len(crd.Spec.Versions) == 0 { + return []string{crd.Spec.Version} + } + var versions []string + for _, v := range crd.Spec.Versions { + if v.Served { + versions = append(versions, v.Name) + } + } + return versions +} + +func existsInDiscovery(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, version string) (bool, error) { + groupResource, err := apiExtensionsClient.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + version) + if err != nil { + if errors.IsNotFound(err) { + return false, nil + } + return false, err + } + for _, g := range groupResource.APIResources { + if g.Name == crd.Spec.Names.Plural { + return true, nil + } + } + return false, nil +} + // CreateNewCustomResourceDefinitionWatchUnsafe creates the CRD and makes sure // the apiextension apiserver has installed the CRD. But it's not safe to watch // the created CR. Please call CreateNewCustomResourceDefinition if you need to // watch the CR. -func CreateNewCustomResourceDefinitionWatchUnsafe(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, clientPool dynamic.ClientPool) (dynamic.Interface, error) { - _, err := apiExtensionsClient.Apiextensions().CustomResourceDefinitions().Create(crd) +func CreateNewCustomResourceDefinitionWatchUnsafe(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) (*apiextensionsv1beta1.CustomResourceDefinition, error) { + crd, err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd) if err != nil { return nil, err } - // wait until the resource appears in discovery - err = wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - resourceList, err := apiExtensionsClient.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + crd.Spec.Version) + // wait until all resources appears in discovery + for _, version := range servedVersions(crd) { + err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { + return existsInDiscovery(crd, apiExtensionsClient, version) + }) if err != nil { - return false, nil - } - for _, resource := range resourceList.APIResources { - if resource.Name == crd.Spec.Names.Plural { - return true, nil - } + return nil, err } - return false, nil - }) - if err != nil { - return nil, err } - return clientPool.ClientForGroupVersionResource(schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}) + return crd, err } -func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, clientPool dynamic.ClientPool) (dynamic.Interface, error) { - dynamicClient, err := CreateNewCustomResourceDefinitionWatchUnsafe(crd, apiExtensionsClient, clientPool) +func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, dynamicClientSet dynamic.Interface) (*apiextensionsv1beta1.CustomResourceDefinition, error) { + crd, err := CreateNewCustomResourceDefinitionWatchUnsafe(crd, apiExtensionsClient) if err != nil { return nil, err } @@ -196,43 +258,35 @@ func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceD // For this test, we'll actually cycle, "list/watch/create/delete" until we get an RV from list that observes the create and not an error. // This way all the tests that are checking for watches don't have to worry about RV too old problems because crazy things *could* happen // before like the created RV could be too old to watch. - var primingErr error - wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - primingErr = checkForWatchCachePrimed(crd, dynamicClient) - if primingErr == nil { - return true, nil + for _, version := range servedVersions(crd) { + err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { + return isWatchCachePrimed(crd, dynamicClientSet, version) + }) + if err != nil { + return nil, err } - return false, nil - }) - if primingErr != nil { - return nil, primingErr } - - return dynamicClient, nil + return crd, nil } -func checkForWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) error { +// isWatchCachePrimed returns true if the watch is primed for an specified version of CRD watch +func isWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition, dynamicClientSet dynamic.Interface, version string) (bool, error) { ns := "" if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { ns = "aval" } - resourceClient := dynamicClient.Resource(&metav1.APIResource{ - Name: crd.Spec.Names.Plural, - Namespaced: crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped, - }, ns) - initialList, err := resourceClient.List(metav1.ListOptions{}) - if err != nil { - return err - } - initialListListMeta, err := meta.ListAccessor(initialList) - if err != nil { - return err - } + gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: version, Resource: crd.Spec.Names.Plural} + var resourceClient dynamic.ResourceInterface + if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { + resourceClient = dynamicClientSet.Resource(gvr).Namespace(ns) + } else { + resourceClient = dynamicClientSet.Resource(gvr) + } instanceName := "setup-instance" instance := &unstructured.Unstructured{ Object: map[string]interface{}{ - "apiVersion": crd.Spec.Group + "/" + crd.Spec.Version, + "apiVersion": crd.Spec.Group + "/" + version, "kind": crd.Spec.Names.Kind, "metadata": map[string]interface{}{ "namespace": ns, @@ -243,31 +297,35 @@ func checkForWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition "gamma": "bar", "delta": "hello", "epsilon": "foobar", + "spec": map[string]interface{}{}, }, } - if _, err := resourceClient.Create(instance); err != nil { - return err + createdInstance, err := resourceClient.Create(instance) + if err != nil { + return false, err + } + err = resourceClient.Delete(createdInstance.GetName(), nil) + if err != nil { + return false, err } - // we created something, clean it up - defer func() { - resourceClient.Delete(instanceName, nil) - }() - noxuWatch, err := resourceClient.Watch(metav1.ListOptions{ResourceVersion: initialListListMeta.GetResourceVersion()}) + noxuWatch, err := resourceClient.Watch(metav1.ListOptions{ResourceVersion: createdInstance.GetResourceVersion()}) if err != nil { - return err + return false, err } defer noxuWatch.Stop() select { case watchEvent := <-noxuWatch.ResultChan(): - if watch.Added == watchEvent.Type { - return nil + if watch.Error == watchEvent.Type { + return false, nil } - return fmt.Errorf("expected add, but got %#v", watchEvent) - + if watch.Deleted != watchEvent.Type { + return false, fmt.Errorf("expected DELETE, but got %#v", watchEvent) + } + return true, nil case <-time.After(5 * time.Second): - return fmt.Errorf("gave up waiting for watch event") + return false, fmt.Errorf("gave up waiting for watch event") } } @@ -275,27 +333,16 @@ func DeleteCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefi if err := apiExtensionsClient.Apiextensions().CustomResourceDefinitions().Delete(crd.Name, nil); err != nil { return err } - err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - groupResource, err := apiExtensionsClient.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + crd.Spec.Version) + for _, version := range servedVersions(crd) { + err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { + exists, err := existsInDiscovery(crd, apiExtensionsClient, version) + return !exists, err + }) if err != nil { - if errors.IsNotFound(err) { - return true, nil - - } - return false, err - } - for _, g := range groupResource.APIResources { - if g.Name == crd.Spec.Names.Plural { - return false, nil - } + return err } - return true, nil - }) - return err -} - -func GetCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) (*apiextensionsv1beta1.CustomResourceDefinition, error) { - return apiExtensionsClient.Apiextensions().CustomResourceDefinitions().Get(crd.Name, metav1.GetOptions{}) + } + return nil } func CreateNewScaleClient(crd *apiextensionsv1beta1.CustomResourceDefinition, config *rest.Config) (scale.ScalesGetter, error) { @@ -308,7 +355,7 @@ func CreateNewScaleClient(crd *apiextensionsv1beta1.CustomResourceDefinition, co return nil, err } - resources := []*discovery.APIGroupResources{ + resources := []*restmapper.APIGroupResources{ { Group: metav1.APIGroup{ Name: crd.Spec.Group, @@ -323,7 +370,7 @@ func CreateNewScaleClient(crd *apiextensionsv1beta1.CustomResourceDefinition, co }, } - restMapper := discovery.NewRESTMapper(resources, nil) + restMapper := restmapper.NewDiscoveryRESTMapper(resources) resolver := scale.NewDiscoveryScaleKindResolver(discoveryClient) return scale.NewForConfig(config, restMapper, dynamic.LegacyAPIPathResolverFunc, resolver) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/start.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/start.go index c0a60bfc7..22b9fa286 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/start.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/testserver/start.go @@ -64,7 +64,7 @@ func DefaultServerConfig() (*extensionsapiserver.Config, error) { if err := options.RecommendedOptions.ApplyTo(genericConfig, nil); err != nil { return nil, err } - if err := options.APIEnablement.ApplyTo(&genericConfig.Config, extensionsapiserver.DefaultAPIResourceConfigSource(), extensionsapiserver.Registry); err != nil { + if err := options.APIEnablement.ApplyTo(&genericConfig.Config, extensionsapiserver.DefaultAPIResourceConfigSource(), extensionsapiserver.Scheme); err != nil { return nil, err } @@ -90,7 +90,7 @@ func DefaultServerConfig() (*extensionsapiserver.Config, error) { func StartServer(config *extensionsapiserver.Config) (chan struct{}, *rest.Config, error) { stopCh := make(chan struct{}) - server, err := config.Complete().New(genericapiserver.EmptyDelegate) + server, err := config.Complete().New(genericapiserver.NewEmptyDelegate()) if err != nil { return nil, nil, err } @@ -139,7 +139,7 @@ func StartDefaultServer() (chan struct{}, *rest.Config, error) { return StartServer(config) } -func StartDefaultServerWithClients() (chan struct{}, clientset.Interface, dynamic.ClientPool, error) { +func StartDefaultServerWithClients() (chan struct{}, clientset.Interface, dynamic.Interface, error) { stopCh, config, err := StartDefaultServer() if err != nil { return nil, nil, nil, err @@ -151,5 +151,11 @@ func StartDefaultServerWithClients() (chan struct{}, clientset.Interface, dynami return nil, nil, nil, err } - return stopCh, apiExtensionsClient, dynamic.NewDynamicClientPool(config), nil + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + close(stopCh) + return nil, nil, nil, err + } + + return stopCh, apiExtensionsClient, dynamicClient, nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/validation_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/validation_test.go index 3ef47b658..cb761330d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/validation_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/validation_test.go @@ -31,20 +31,20 @@ import ( ) func TestForProperValidationErrors(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) tests := []struct { name string @@ -54,8 +54,7 @@ func TestForProperValidationErrors(t *testing.T) { { name: "bad version", instanceFn: func() *unstructured.Unstructured { - instance := testserver.NewNoxuInstance(ns, "foo") - instance.Object["apiVersion"] = "mygroup.example.com/v2" + instance := testserver.NewVersionedNoxuInstance(ns, "foo", "v2") return instance }, expectedError: "the API version in the data (mygroup.example.com/v2) does not match the expected API version (mygroup.example.com/v1beta1)", @@ -169,20 +168,20 @@ func newNoxuValidationInstance(namespace, name string) *unstructured.Unstructure } func TestCustomResourceValidation(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, newNoxuValidationInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -190,20 +189,20 @@ func TestCustomResourceValidation(t *testing.T) { } func TestCustomResourceUpdateValidation(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) _, err = instantiateCustomResource(t, newNoxuValidationInstance(ns, "foo"), noxuResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu instance: %v", err) @@ -233,20 +232,20 @@ func TestCustomResourceUpdateValidation(t *testing.T) { } func TestCustomResourceValidationErrors(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } defer close(stopCh) noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) tests := []struct { name string @@ -324,7 +323,7 @@ func TestCustomResourceValidationErrors(t *testing.T) { } func TestCRValidationOnCRDUpdate(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -335,12 +334,12 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { // set stricter schema noxuDefinition.Spec.Validation.OpenAPIV3Schema.Required = []string{"alpha", "beta", "epsilon"} - noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" - noxuResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition) + noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) // CR is rejected _, err = instantiateCustomResource(t, newNoxuValidationInstance(ns, "foo"), noxuResourceClient, noxuDefinition) @@ -348,14 +347,11 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { t.Fatalf("unexpected non-error: CR should be rejected") } - gottenCRD, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get("noxus.mygroup.example.com", metav1.GetOptions{}) - if err != nil { - t.Fatal(err) - } - // update the CRD to a less stricter schema - gottenCRD.Spec.Validation.OpenAPIV3Schema.Required = []string{"alpha", "beta"} - if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(gottenCRD); err != nil { + _, err = updateCustomResourceDefinitionWithRetry(apiExtensionClient, "noxus.mygroup.example.com", func(crd *apiextensionsv1beta1.CustomResourceDefinition) { + crd.Spec.Validation.OpenAPIV3Schema.Required = []string{"alpha", "beta"} + }) + if err != nil { t.Fatal(err) } @@ -378,7 +374,7 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { } func TestForbiddenFieldsInSchema(t *testing.T) { - stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServerWithClients() + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() if err != nil { t.Fatal(err) } @@ -387,7 +383,7 @@ func TestForbiddenFieldsInSchema(t *testing.T) { noxuDefinition := newNoxuValidationCRD(apiextensionsv1beta1.NamespaceScoped) noxuDefinition.Spec.Validation.OpenAPIV3Schema.AdditionalProperties.Allows = false - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatalf("unexpected non-error: additionalProperties cannot be set to false") } @@ -398,7 +394,7 @@ func TestForbiddenFieldsInSchema(t *testing.T) { } noxuDefinition.Spec.Validation.OpenAPIV3Schema.AdditionalProperties.Allows = true - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatalf("unexpected non-error: uniqueItems cannot be set to true") } @@ -409,14 +405,14 @@ func TestForbiddenFieldsInSchema(t *testing.T) { UniqueItems: false, } - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatal("unexpected non-error: $ref cannot be non-empty string") } noxuDefinition.Spec.Validation.OpenAPIV3Schema.Ref = nil - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go new file mode 100644 index 000000000..55d0c17af --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go @@ -0,0 +1,138 @@ +/* +Copyright 2018 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 integration + +import ( + "reflect" + "testing" + + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/test/integration/testserver" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestVersionedNamspacedScopedCRD(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + ns := "not-the-default" + testSimpleCRUD(t, ns, noxuDefinition, dynamicClient) +} + +func TestVersionedClusterScopedCRD(t *testing.T) { + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + ns := "" + testSimpleCRUD(t, ns, noxuDefinition, dynamicClient) +} + +func TestStoragedVersionInNamespacedCRDStatus(t *testing.T) { + noxuDefinition := testserver.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped) + ns := "not-the-default" + testStoragedVersionInCRDStatus(t, ns, noxuDefinition) +} + +func TestStoragedVersionInClusterScopedCRDStatus(t *testing.T) { + noxuDefinition := testserver.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped) + ns := "" + testStoragedVersionInCRDStatus(t, ns, noxuDefinition) +} + +func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition) { + versionsV1Beta1Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: true, + }, + { + Name: "v1beta2", + Served: true, + Storage: false, + }, + } + versionsV1Beta2Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: false, + }, + { + Name: "v1beta2", + Served: true, + Storage: true, + }, + } + stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition.Spec.Versions = versionsV1Beta1Storage + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + // The storage version list should be initilized to storage version + crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}) + if err != nil { + t.Fatal(err) + } + if e, a := []string{"v1beta1"}, crd.Status.StoredVersions; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + + // Changing CRD storage version should be reflected immediately + crd.Spec.Versions = versionsV1Beta2Storage + _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(crd) + if err != nil { + t.Fatal(err) + } + crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(noxuDefinition.Name, metav1.GetOptions{}) + if err != nil { + t.Fatal(err) + } + if e, a := []string{"v1beta1", "v1beta2"}, crd.Status.StoredVersions; !reflect.DeepEqual(e, a) { + t.Errorf("expected %v, got %v", e, a) + } + + err = testserver.DeleteCustomResourceDefinition(crd, apiExtensionClient) + if err != nil { + t.Fatal(err) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go index 9f23427f0..2dc279559 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go @@ -27,13 +27,10 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/dynamic" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "k8s.io/apiextensions-apiserver/pkg/features" "k8s.io/apiextensions-apiserver/test/integration/testserver" ) @@ -48,10 +45,13 @@ func TestYAML(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -354,9 +354,6 @@ values: } func TestYAMLSubresource(t *testing.T) { - // enable alpha feature CustomResourceSubresources - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CustomResourceSubresources, true)() - stopCh, config, err := testserver.StartDefaultServer() if err != nil { t.Fatal(err) @@ -367,10 +364,13 @@ func TestYAMLSubresource(t *testing.T) { if err != nil { t.Fatal(err) } - clientPool := dynamic.NewDynamicClientPool(config) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } noxuDefinition := NewNoxuSubresourcesCRD(apiextensionsv1beta1.ClusterScoped) - _, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/Godeps/Godeps.json index 148ceafb7..b580e4b31 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "k8s.io/apimachinery", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], @@ -24,7 +24,7 @@ }, { "ImportPath": "github.com/evanphx/json-patch", - "Rev": "944e07253867aacae43c04b2e6a239005443f33a" + "Rev": "94e38aa1586e8a6c8a75770bddf5ff84c48a106b" }, { "ImportPath": "github.com/ghodss/yaml", @@ -48,23 +48,23 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/gofuzz", @@ -92,7 +92,15 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" + }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" }, { "ImportPath": "github.com/mxk/go-flowrate/flowrate", @@ -112,11 +120,11 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/stretchr/testify/require", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "golang.org/x/net/html", @@ -172,7 +180,7 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/BUILD index a02a1fb5b..987eb1c06 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/BUILD @@ -19,7 +19,6 @@ go_test( "//vendor/github.com/google/gofuzz:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1: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/util/diff:go_default_library", ], @@ -38,13 +37,11 @@ go_library( "multirestmapper.go", "priority.go", "restmapper.go", - "unstructured.go", ], importpath = "k8s.io/apimachinery/pkg/api/meta", deps = [ "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", @@ -67,6 +64,7 @@ filegroup( srcs = [ ":package-srcs", "//staging/src/k8s.io/apimachinery/pkg/api/meta/table:all-srcs", + "//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:all-srcs", ], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/interfaces.go index 5dc9d89e6..42eac3af0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/interfaces.go @@ -23,12 +23,6 @@ import ( "k8s.io/apimachinery/pkg/types" ) -// VersionInterfaces contains the interfaces one should use for dealing with types of a particular version. -type VersionInterfaces struct { - runtime.ObjectConvertor - MetadataAccessor -} - type ListMetaAccessor interface { GetListMeta() List } @@ -92,28 +86,19 @@ const ( type RESTScope interface { // Name of the scope Name() RESTScopeName - // ParamName is the optional name of the parameter that should be inserted in the resource url - // If empty, no param will be inserted - ParamName() string - // ArgumentName is the optional name that should be used for the variable holding the value. - ArgumentName() string - // ParamDescription is the optional description to use to document the parameter in api documentation - ParamDescription() string } // RESTMapping contains the information needed to deal with objects of a specific // resource and kind in a RESTful manner. type RESTMapping struct { - // Resource is a string representing the name of this resource as a REST client would see it - Resource string + // Resource is the GroupVersionResource (location) for this endpoint + Resource schema.GroupVersionResource + // GroupVersionKind is the GroupVersionKind (data format) to submit to this endpoint GroupVersionKind schema.GroupVersionKind // Scope contains the information needed to deal with REST Resources that are in a resource hierarchy Scope RESTScope - - runtime.ObjectConvertor - MetadataAccessor } // RESTMapper allows clients to map resources to kind, and map kind and version diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/lazy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/lazy.go index 7f92f39a4..431a0a635 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/lazy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/lazy.go @@ -19,27 +19,25 @@ package meta import ( "sync" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) // lazyObject defers loading the mapper and typer until necessary. type lazyObject struct { - loader func() (RESTMapper, runtime.ObjectTyper, error) + loader func() (RESTMapper, error) lock sync.Mutex loaded bool err error mapper RESTMapper - typer runtime.ObjectTyper } // NewLazyObjectLoader handles unrecoverable errors when creating a RESTMapper / ObjectTyper by // returning those initialization errors when the interface methods are invoked. This defers the // initialization and any server calls until a client actually needs to perform the action. -func NewLazyObjectLoader(fn func() (RESTMapper, runtime.ObjectTyper, error)) (RESTMapper, runtime.ObjectTyper) { +func NewLazyRESTMapperLoader(fn func() (RESTMapper, error)) RESTMapper { obj := &lazyObject{loader: fn} - return obj, obj + return obj } // init lazily loads the mapper and typer, returning an error if initialization has failed. @@ -49,13 +47,12 @@ func (o *lazyObject) init() error { if o.loaded { return o.err } - o.mapper, o.typer, o.err = o.loader() + o.mapper, o.err = o.loader() o.loaded = true return o.err } var _ RESTMapper = &lazyObject{} -var _ runtime.ObjectTyper = &lazyObject{} func (o *lazyObject) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { if err := o.init(); err != nil { @@ -105,17 +102,3 @@ func (o *lazyObject) ResourceSingularizer(resource string) (singular string, err } return o.mapper.ResourceSingularizer(resource) } - -func (o *lazyObject) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { - if err := o.init(); err != nil { - return nil, false, err - } - return o.typer.ObjectKinds(obj) -} - -func (o *lazyObject) Recognizes(gvk schema.GroupVersionKind) bool { - if err := o.init(); err != nil { - return false - } - return o.typer.Recognizes(gvk) -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/meta.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/meta.go index b9670071c..1c2a83cfa 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/meta.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/meta.go @@ -38,7 +38,6 @@ var errNotCommon = fmt.Errorf("object does not implement the common interface fo // CommonAccessor returns a Common interface for the provided object or an error if the object does // not provide List. -// TODO: return bool instead of error func CommonAccessor(obj interface{}) (metav1.Common, error) { switch t := obj.(type) { case List: @@ -71,7 +70,6 @@ func CommonAccessor(obj interface{}) (metav1.Common, error) { // not provide List. // IMPORTANT: Objects are NOT a superset of lists. Do not use this check to determine whether an // object *is* a List. -// TODO: return bool instead of error func ListAccessor(obj interface{}) (List, error) { switch t := obj.(type) { case List: @@ -101,7 +99,6 @@ var errNotObject = fmt.Errorf("object does not implement the Object interfaces") // obj must be a pointer to an API type. An error is returned if the minimum // required fields are missing. Fields that are not required return the default // value and are a no-op if set. -// TODO: return bool instead of error func Accessor(obj interface{}) (metav1.Object, error) { switch t := obj.(type) { case metav1.Object: diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/priority.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/priority.go index df28e64ff..fa11c580f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/priority.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/priority.go @@ -54,12 +54,12 @@ func (m PriorityRESTMapper) String() string { // ResourceFor finds all resources, then passes them through the ResourcePriority patterns to find a single matching hit. func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupVersionResource) (schema.GroupVersionResource, error) { - originalGVRs, err := m.Delegate.ResourcesFor(partiallySpecifiedResource) - if err != nil { - return schema.GroupVersionResource{}, err + originalGVRs, originalErr := m.Delegate.ResourcesFor(partiallySpecifiedResource) + if originalErr != nil && len(originalGVRs) == 0 { + return schema.GroupVersionResource{}, originalErr } if len(originalGVRs) == 1 { - return originalGVRs[0], nil + return originalGVRs[0], originalErr } remainingGVRs := append([]schema.GroupVersionResource{}, originalGVRs...) @@ -77,7 +77,7 @@ func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupV continue case 1: // one match, return - return matchedGVRs[0], nil + return matchedGVRs[0], originalErr default: // more than one match, use the matched hits as the list moving to the next pattern. // this way you can have a series of selection criteria @@ -90,12 +90,12 @@ func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupV // KindFor finds all kinds, then passes them through the KindPriority patterns to find a single matching hit. func (m PriorityRESTMapper) KindFor(partiallySpecifiedResource schema.GroupVersionResource) (schema.GroupVersionKind, error) { - originalGVKs, err := m.Delegate.KindsFor(partiallySpecifiedResource) - if err != nil { - return schema.GroupVersionKind{}, err + originalGVKs, originalErr := m.Delegate.KindsFor(partiallySpecifiedResource) + if originalErr != nil && len(originalGVKs) == 0 { + return schema.GroupVersionKind{}, originalErr } if len(originalGVKs) == 1 { - return originalGVKs[0], nil + return originalGVKs[0], originalErr } remainingGVKs := append([]schema.GroupVersionKind{}, originalGVKs...) @@ -113,7 +113,7 @@ func (m PriorityRESTMapper) KindFor(partiallySpecifiedResource schema.GroupVersi continue case 1: // one match, return - return matchedGVKs[0], nil + return matchedGVKs[0], originalErr default: // more than one match, use the matched hits as the list moving to the next pattern. // this way you can have a series of selection criteria @@ -153,9 +153,9 @@ func kindMatches(pattern schema.GroupVersionKind, kind schema.GroupVersionKind) } func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (mapping *RESTMapping, err error) { - mappings, err := m.Delegate.RESTMappings(gk, versions...) - if err != nil { - return nil, err + mappings, originalErr := m.Delegate.RESTMappings(gk, versions...) + if originalErr != nil && len(mappings) == 0 { + return nil, originalErr } // any versions the user provides take priority @@ -187,7 +187,7 @@ func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) continue case 1: // one match, return - return matching[0], nil + return matching[0], originalErr default: // more than one match, use the matched hits as the list moving to the next pattern. // this way you can have a series of selection criteria @@ -195,7 +195,7 @@ func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) } } if len(remaining) == 1 { - return remaining[0], nil + return remaining[0], originalErr } var kinds []schema.GroupVersionKind diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/priority_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/priority_test.go index 098d53bd5..fff1afd17 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/priority_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/priority_test.go @@ -34,6 +34,30 @@ func TestPriorityRESTMapperResourceForErrorHandling(t *testing.T) { result schema.GroupVersionResource err string }{ + { + name: "error", + delegate: fixedRESTMapper{err: errors.New("delegateError")}, + err: "delegateError", + }, + { + name: "single hit + error", + delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "single-hit"}}, err: errors.New("delegateError")}, + result: schema.GroupVersionResource{Resource: "single-hit"}, + err: "delegateError", + }, + { + name: "group selection + error", + delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{ + {Group: "one", Version: "a", Resource: "first"}, + {Group: "two", Version: "b", Resource: "second"}, + }, err: errors.New("delegateError")}, + resourcePatterns: []schema.GroupVersionResource{ + {Group: "one", Version: AnyVersion, Resource: AnyResource}, + }, + result: schema.GroupVersionResource{Group: "one", Version: "a", Resource: "first"}, + err: "delegateError", + }, + { name: "single hit", delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "single-hit"}}}, @@ -106,6 +130,10 @@ func TestPriorityRESTMapperResourceForErrorHandling(t *testing.T) { if len(tc.err) == 0 && actualErr == nil { continue } + if len(tc.err) == 0 && actualErr != nil { + t.Errorf("%s: unexpected err: %v", tc.name, actualErr) + continue + } if len(tc.err) > 0 && actualErr == nil { t.Errorf("%s: missing expected err: %v", tc.name, tc.err) continue @@ -125,6 +153,30 @@ func TestPriorityRESTMapperKindForErrorHandling(t *testing.T) { result schema.GroupVersionKind err string }{ + { + name: "error", + delegate: fixedRESTMapper{err: errors.New("delegateErr")}, + err: "delegateErr", + }, + { + name: "single hit + error", + delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "single-hit"}}, err: errors.New("delegateErr")}, + result: schema.GroupVersionKind{Kind: "single-hit"}, + err: "delegateErr", + }, + { + name: "group selection + error", + delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{ + {Group: "one", Version: "a", Kind: "first"}, + {Group: "two", Version: "b", Kind: "second"}, + }, err: errors.New("delegateErr")}, + kindPatterns: []schema.GroupVersionKind{ + {Group: "one", Version: AnyVersion, Kind: AnyKind}, + }, + result: schema.GroupVersionKind{Group: "one", Version: "a", Kind: "first"}, + err: "delegateErr", + }, + { name: "single hit", delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "single-hit"}}}, @@ -197,6 +249,10 @@ func TestPriorityRESTMapperKindForErrorHandling(t *testing.T) { if len(tc.err) == 0 && actualErr == nil { continue } + if len(tc.err) == 0 && actualErr != nil { + t.Errorf("%s: unexpected err: %v", tc.name, actualErr) + continue + } if len(tc.err) > 0 && actualErr == nil { t.Errorf("%s: missing expected err: %v", tc.name, tc.err) continue @@ -248,6 +304,13 @@ func TestPriorityRESTMapperRESTMapping(t *testing.T) { input: schema.GroupKind{Kind: "Foo"}, err: errors.New("fail on this"), }, + { + name: "result + error", + mapper: PriorityRESTMapper{Delegate: fixedRESTMapper{mappings: []*RESTMapping{mapping1}, err: errors.New("fail on this")}}, + input: schema.GroupKind{Kind: "Foo"}, + result: mapping1, + err: errors.New("fail on this"), + }, { name: "return error for ambiguous", mapper: PriorityRESTMapper{ diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/restmapper.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/restmapper.go index ff945acd1..41b60d731 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/restmapper.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/restmapper.go @@ -28,30 +28,15 @@ import ( // Implements RESTScope interface type restScope struct { - name RESTScopeName - paramName string - argumentName string - paramDescription string + name RESTScopeName } func (r *restScope) Name() RESTScopeName { return r.name } -func (r *restScope) ParamName() string { - return r.paramName -} -func (r *restScope) ArgumentName() string { - return r.argumentName -} -func (r *restScope) ParamDescription() string { - return r.paramDescription -} var RESTScopeNamespace = &restScope{ - name: RESTScopeNameNamespace, - paramName: "namespaces", - argumentName: "namespace", - paramDescription: "object name and auth scope, such as for teams and projects", + name: RESTScopeNameNamespace, } var RESTScopeRoot = &restScope{ @@ -77,8 +62,6 @@ type DefaultRESTMapper struct { kindToScope map[schema.GroupVersionKind]RESTScope singularToPlural map[schema.GroupVersionResource]schema.GroupVersionResource pluralToSingular map[schema.GroupVersionResource]schema.GroupVersionResource - - interfacesFunc VersionInterfacesFunc } func (m *DefaultRESTMapper) String() string { @@ -87,16 +70,12 @@ func (m *DefaultRESTMapper) String() string { var _ RESTMapper = &DefaultRESTMapper{} -// VersionInterfacesFunc returns the appropriate typer, and metadata accessor for a -// given api version, or an error if no such api version exists. -type VersionInterfacesFunc func(version schema.GroupVersion) (*VersionInterfaces, error) - // NewDefaultRESTMapper initializes a mapping between Kind and APIVersion // to a resource name and back based on the objects in a runtime.Scheme // and the Kubernetes API conventions. Takes a group name, a priority list of the versions // to search when an object has no default version (set empty to return an error), // and a function that retrieves the correct metadata for a given version. -func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion, f VersionInterfacesFunc) *DefaultRESTMapper { +func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion) *DefaultRESTMapper { resourceToKind := make(map[schema.GroupVersionResource]schema.GroupVersionKind) kindToPluralResource := make(map[schema.GroupVersionKind]schema.GroupVersionResource) kindToScope := make(map[schema.GroupVersionKind]RESTScope) @@ -111,7 +90,6 @@ func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion, f VersionI defaultGroupVersions: defaultGroupVersions, singularToPlural: singularToPlural, pluralToSingular: pluralToSingular, - interfacesFunc: f, } } @@ -526,18 +504,10 @@ func (m *DefaultRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported scope", gvk.GroupVersion(), gvk.Kind) } - interfaces, err := m.interfacesFunc(gvk.GroupVersion()) - if err != nil { - return nil, fmt.Errorf("the provided version %q has no relevant versions: %v", gvk.GroupVersion().String(), err) - } - mappings = append(mappings, &RESTMapping{ - Resource: res.Resource, + Resource: res, GroupVersionKind: gvk, Scope: scope, - - ObjectConvertor: interfaces.ObjectConvertor, - MetadataAccessor: interfaces.MetadataAccessor, }) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/restmapper_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/restmapper_test.go index 1b1c70d65..853404ad6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/restmapper_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/restmapper_test.go @@ -17,42 +17,13 @@ limitations under the License. package meta import ( - "errors" "reflect" "strings" "testing" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) -type fakeConvertor struct{} - -func (fakeConvertor) Convert(in, out, context interface{}) error { - return nil -} - -func (fakeConvertor) ConvertToVersion(in runtime.Object, _ runtime.GroupVersioner) (runtime.Object, error) { - return in, nil -} - -func (fakeConvertor) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { - return label, value, nil -} - -var validAccessor = resourceAccessor{} -var validConvertor = fakeConvertor{} - -func fakeInterfaces(version schema.GroupVersion) (*VersionInterfaces, error) { - return &VersionInterfaces{ObjectConvertor: validConvertor, MetadataAccessor: validAccessor}, nil -} - -var unmatchedErr = errors.New("no version") - -func unmatchedVersionInterfaces(version schema.GroupVersion) (*VersionInterfaces, error) { - return nil, unmatchedErr -} - func TestRESTMapperVersionAndKindForResource(t *testing.T) { testGroup := "test.group" testVersion := "test" @@ -71,7 +42,7 @@ func TestRESTMapperVersionAndKindForResource(t *testing.T) { {Resource: schema.GroupVersionResource{Resource: "internalobjects"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}, fakeInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}) if len(testCase.ExpectedGVK.Kind) != 0 { mapper.Add(testCase.ExpectedGVK, RESTScopeNamespace) } @@ -104,7 +75,7 @@ func TestRESTMapperGroupForResource(t *testing.T) { {Resource: schema.GroupVersionResource{Resource: "myobje"}, Err: true, GroupVersionKind: schema.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}}, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper([]schema.GroupVersion{testCase.GroupVersionKind.GroupVersion()}, fakeInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{testCase.GroupVersionKind.GroupVersion()}) mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace) actualGVK, err := mapper.KindFor(testCase.Resource) @@ -249,7 +220,7 @@ func TestRESTMapperKindsFor(t *testing.T) { } for _, testCase := range testCases { tcName := testCase.Name - mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces) + mapper := NewDefaultRESTMapper(testCase.PreferredOrder) for _, kind := range testCase.KindsToRegister { mapper.Add(kind, RESTScopeNamespace) } @@ -426,7 +397,7 @@ func TestRESTMapperResourcesFor(t *testing.T) { tcName := testCase.Name for _, partialResource := range []schema.GroupVersionResource{testCase.PluralPartialResourceToRequest, testCase.SingularPartialResourceToRequest} { - mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces) + mapper := NewDefaultRESTMapper(testCase.PreferredOrder) for _, kind := range testCase.KindsToRegister { mapper.Add(kind, RESTScopeNamespace) } @@ -511,7 +482,7 @@ func TestRESTMapperResourceSingularizer(t *testing.T) { {Kind: "lowercases", Plural: "lowercaseses", Singular: "lowercases"}, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}, fakeInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}) // create singular/plural mapping mapper.Add(testGroupVersion.WithKind(testCase.Kind), RESTScopeNamespace) @@ -535,7 +506,7 @@ func TestRESTMapperRESTMapping(t *testing.T) { APIGroupVersions []schema.GroupVersion DefaultVersions []schema.GroupVersion - Resource string + Resource schema.GroupVersionResource ExpectedGroupVersion *schema.GroupVersion Err bool }{ @@ -544,19 +515,19 @@ func TestRESTMapperRESTMapping(t *testing.T) { {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "Unknown", Err: true}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{}, Resource: "internalobjects", ExpectedGroupVersion: &schema.GroupVersion{Group: testGroup, Version: "test"}}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{}, Resource: internalGroupVersion.WithResource("internalobjects"), ExpectedGroupVersion: &schema.GroupVersion{Group: testGroup, Version: "test"}}, - {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")}, // TODO: add test for a resource that exists in one version but not another } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces) + mapper := NewDefaultRESTMapper(testCase.DefaultVersions) mapper.Add(internalGroupVersion.WithKind("InternalObject"), RESTScopeNamespace) preferredVersions := []string{} @@ -577,10 +548,6 @@ func TestRESTMapperRESTMapping(t *testing.T) { t.Errorf("%d: unexpected resource: %#v", i, mapping) } - if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil { - t.Errorf("%d: missing codec and accessor: %#v", i, mapping) - } - groupVersion := testCase.ExpectedGroupVersion if groupVersion == nil { groupVersion = &testCase.APIGroupVersions[0] @@ -599,7 +566,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { internalObjectGK := schema.GroupKind{Group: "tgroup", Kind: "InternalObject"} otherObjectGK := schema.GroupKind{Group: "tgroup", Kind: "OtherObject"} - mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, fakeInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}) mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace) mapper.Add(expectedGroupVersion2.WithKind("OtherObject"), RESTScopeNamespace) @@ -608,7 +575,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { + if mapping.Resource != expectedGroupVersion2.WithResource("otherobjects") || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { t.Errorf("unexpected mapping: %#v", mapping) } @@ -616,7 +583,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.Resource != "internalobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion1 { + if mapping.Resource != expectedGroupVersion1.WithResource("internalobjects") || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion1 { t.Errorf("unexpected mapping: %#v", mapping) } @@ -646,7 +613,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { + if mapping.Resource != expectedGroupVersion2.WithResource("otherobjects") || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { t.Errorf("unexpected mapping: %#v", mapping) } } @@ -678,7 +645,7 @@ func TestRESTMapperRESTMappings(t *testing.T) { Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "v2"}}, AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")}, - ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, + ExpectedRESTMappings: []*RESTMapping{{Resource: schema.GroupVersionResource{Group: testGroup, Version: "v2", Resource: "internalobjects"}, GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, }, // ask for specific versions - only one available - check ExpectedRESTMappings @@ -687,20 +654,29 @@ func TestRESTMapperRESTMappings(t *testing.T) { Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "v3"}, {Group: testGroup, Version: "v2"}}, AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")}, - ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, + ExpectedRESTMappings: []*RESTMapping{{Resource: schema.GroupVersionResource{Group: testGroup, Version: "v2", Resource: "internalobjects"}, GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, }, // do not ask for specific version - search through default versions - check ExpectedRESTMappings { - DefaultVersions: []schema.GroupVersion{testGroupVersion, {Group: testGroup, Version: "v2"}}, - Kind: "InternalObject", - AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v1"}.WithKind("InternalObject"), schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")}, - ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v1", Kind: "InternalObject"}}, {Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}}, + DefaultVersions: []schema.GroupVersion{testGroupVersion, {Group: testGroup, Version: "v2"}}, + Kind: "InternalObject", + AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v1"}.WithKind("InternalObject"), schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")}, + ExpectedRESTMappings: []*RESTMapping{ + { + Resource: schema.GroupVersionResource{Group: testGroup, Version: "v1", Resource: "internalobjects"}, + GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v1", Kind: "InternalObject"}, + }, + { + Resource: schema.GroupVersionResource{Group: testGroup, Version: "v2", Resource: "internalobjects"}, + GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}, + }, + }, }, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces) + mapper := NewDefaultRESTMapper(testCase.DefaultVersions) for _, gvk := range testCase.AddGroupVersionKind { mapper.Add(gvk, RESTScopeNamespace) } @@ -727,9 +703,6 @@ func TestRESTMapperRESTMappings(t *testing.T) { if mapping.Resource != exp.Resource { t.Errorf("%d - %d: unexpected resource: %#v", i, j, mapping) } - if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil { - t.Errorf("%d - %d: missing codec and accessor: %#v", i, j, mapping) - } if mapping.GroupVersionKind != exp.GroupVersionKind { t.Errorf("%d - %d: unexpected GroupVersionKind: %#v", i, j, mapping) } @@ -742,9 +715,9 @@ func TestRESTMapperReportsErrorOnBadVersion(t *testing.T) { expectedGroupVersion2 := schema.GroupVersion{Group: "tgroup", Version: "test2"} internalObjectGK := schema.GroupKind{Group: "tgroup", Kind: "InternalObject"} - mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, unmatchedVersionInterfaces) + mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}) mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace) - _, err := mapper.RESTMapping(internalObjectGK, expectedGroupVersion1.Version) + _, err := mapper.RESTMapping(internalObjectGK, "test3") if err == nil { t.Errorf("unexpected non-error") } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/table/table.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/table/table.go index a0097a4e2..2144a77cb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/table/table.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/table/table.go @@ -53,7 +53,7 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1. row := metav1beta1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells, err = rowFn(obj, m, m.GetName(), translateTimestamp(m.GetCreationTimestamp())) + row.Cells, err = rowFn(obj, m, m.GetName(), ConvertToHumanReadableDateType(m.GetCreationTimestamp())) if err != nil { return nil, err } @@ -61,9 +61,9 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1. return rows, nil } -// translateTimestamp returns the elapsed time since timestamp in +// ConvertToHumanReadableDateType returns the elapsed time since timestamp in // human-readable approximation. -func translateTimestamp(timestamp metav1.Time) string { +func ConvertToHumanReadableDateType(timestamp metav1.Time) string { if timestamp.IsZero() { return "" } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/BUILD new file mode 100644 index 000000000..5380d155b --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/BUILD @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["test_restmapper.go"], + importpath = "k8s.io/apimachinery/pkg/api/meta/testrestmapper", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/api/meta: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/util/sets:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/test_restmapper.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/test_restmapper.go new file mode 100644 index 000000000..a08b42b82 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/test_restmapper.go @@ -0,0 +1,171 @@ +/* +Copyright 2018 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 testrestmapper + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/sets" +) + +// TestOnlyStaticRESTMapper returns a union RESTMapper of all known types with priorities chosen in the following order: +// 1. legacy kube group preferred version, extensions preferred version, metrics perferred version, legacy +// kube any version, extensions any version, metrics any version, all other groups alphabetical preferred version, +// all other groups alphabetical. +// TODO callers of this method should be updated to build their own specific restmapper based on their scheme for their tests +// TODO the things being tested are related to whether various cases are handled, not tied to the particular types being checked. +func TestOnlyStaticRESTMapper(scheme *runtime.Scheme, versionPatterns ...schema.GroupVersion) meta.RESTMapper { + unionMapper := meta.MultiRESTMapper{} + unionedGroups := sets.NewString() + for _, enabledVersion := range scheme.PrioritizedVersionsAllGroups() { + if !unionedGroups.Has(enabledVersion.Group) { + unionedGroups.Insert(enabledVersion.Group) + unionMapper = append(unionMapper, newRESTMapper(enabledVersion.Group, scheme)) + } + } + + if len(versionPatterns) != 0 { + resourcePriority := []schema.GroupVersionResource{} + kindPriority := []schema.GroupVersionKind{} + for _, versionPriority := range versionPatterns { + resourcePriority = append(resourcePriority, versionPriority.WithResource(meta.AnyResource)) + kindPriority = append(kindPriority, versionPriority.WithKind(meta.AnyKind)) + } + + return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} + } + + prioritizedGroups := []string{"", "extensions", "metrics"} + resourcePriority, kindPriority := prioritiesForGroups(scheme, prioritizedGroups...) + + prioritizedGroupsSet := sets.NewString(prioritizedGroups...) + remainingGroups := sets.String{} + for _, enabledVersion := range scheme.PrioritizedVersionsAllGroups() { + if !prioritizedGroupsSet.Has(enabledVersion.Group) { + remainingGroups.Insert(enabledVersion.Group) + } + } + + remainingResourcePriority, remainingKindPriority := prioritiesForGroups(scheme, remainingGroups.List()...) + resourcePriority = append(resourcePriority, remainingResourcePriority...) + kindPriority = append(kindPriority, remainingKindPriority...) + + return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} +} + +// prioritiesForGroups returns the resource and kind priorities for a PriorityRESTMapper, preferring the preferred version of each group first, +// then any non-preferred version of the group second. +func prioritiesForGroups(scheme *runtime.Scheme, groups ...string) ([]schema.GroupVersionResource, []schema.GroupVersionKind) { + resourcePriority := []schema.GroupVersionResource{} + kindPriority := []schema.GroupVersionKind{} + + for _, group := range groups { + availableVersions := scheme.PrioritizedVersionsForGroup(group) + if len(availableVersions) > 0 { + resourcePriority = append(resourcePriority, availableVersions[0].WithResource(meta.AnyResource)) + kindPriority = append(kindPriority, availableVersions[0].WithKind(meta.AnyKind)) + } + } + for _, group := range groups { + resourcePriority = append(resourcePriority, schema.GroupVersionResource{Group: group, Version: meta.AnyVersion, Resource: meta.AnyResource}) + kindPriority = append(kindPriority, schema.GroupVersionKind{Group: group, Version: meta.AnyVersion, Kind: meta.AnyKind}) + } + + return resourcePriority, kindPriority +} + +func newRESTMapper(group string, scheme *runtime.Scheme) meta.RESTMapper { + mapper := meta.NewDefaultRESTMapper(scheme.PrioritizedVersionsForGroup(group)) + for _, gv := range scheme.PrioritizedVersionsForGroup(group) { + for kind := range scheme.KnownTypes(gv) { + if ignoredKinds.Has(kind) { + continue + } + scope := meta.RESTScopeNamespace + if rootScopedKinds[gv.WithKind(kind).GroupKind()] { + scope = meta.RESTScopeRoot + } + mapper.Add(gv.WithKind(kind), scope) + } + } + + return mapper +} + +// hardcoded is good enough for the test we're running +var rootScopedKinds = map[schema.GroupKind]bool{ + {Group: "admission.k8s.io", Kind: "AdmissionReview"}: true, + + {Group: "admissionregistration.k8s.io", Kind: "InitializerConfiguration"}: true, + {Group: "admissionregistration.k8s.io", Kind: "ValidatingWebhookConfiguration"}: true, + {Group: "admissionregistration.k8s.io", Kind: "MutatingWebhookConfiguration"}: true, + + {Group: "authentication.k8s.io", Kind: "TokenReview"}: true, + + {Group: "authorization.k8s.io", Kind: "SubjectAccessReview"}: true, + {Group: "authorization.k8s.io", Kind: "SelfSubjectAccessReview"}: true, + {Group: "authorization.k8s.io", Kind: "SelfSubjectRulesReview"}: true, + + {Group: "certificates.k8s.io", Kind: "CertificateSigningRequest"}: true, + + {Group: "", Kind: "Node"}: true, + {Group: "", Kind: "Namespace"}: true, + {Group: "", Kind: "PersistentVolume"}: true, + {Group: "", Kind: "ComponentStatus"}: true, + + {Group: "extensions", Kind: "PodSecurityPolicy"}: true, + + {Group: "policy", Kind: "PodSecurityPolicy"}: true, + + {Group: "extensions", Kind: "PodSecurityPolicy"}: true, + + {Group: "rbac.authorization.k8s.io", Kind: "ClusterRole"}: true, + {Group: "rbac.authorization.k8s.io", Kind: "ClusterRoleBinding"}: true, + + {Group: "scheduling.k8s.io", Kind: "PriorityClass"}: true, + + {Group: "storage.k8s.io", Kind: "StorageClass"}: true, + {Group: "storage.k8s.io", Kind: "VolumeAttachment"}: true, + + {Group: "apiextensions.k8s.io", Kind: "CustomResourceDefinition"}: true, + + {Group: "apiserver.k8s.io", Kind: "AdmissionConfiguration"}: true, + + {Group: "audit.k8s.io", Kind: "Event"}: true, + {Group: "audit.k8s.io", Kind: "Policy"}: true, + + {Group: "apiregistration.k8s.io", Kind: "APIService"}: true, + + {Group: "metrics.k8s.io", Kind: "NodeMetrics"}: true, + + {Group: "wardle.k8s.io", Kind: "Fischer"}: true, +} + +// hardcoded is good enough for the test we're running +var ignoredKinds = sets.NewString( + "ListOptions", + "DeleteOptions", + "Status", + "PodLogOptions", + "PodExecOptions", + "PodAttachOptions", + "PodPortForwardOptions", + "PodProxyOptions", + "NodeProxyOptions", + "ServiceProxyOptions", +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/unstructured.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/unstructured.go deleted file mode 100644 index 4e13efea3..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/meta/unstructured.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -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 meta - -import ( - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// InterfacesForUnstructuredConversion returns VersionInterfaces suitable for -// dealing with unstructured.Unstructured objects and supports conversion -// from typed objects (provided by parent) to untyped objects. -func InterfacesForUnstructuredConversion(parent VersionInterfacesFunc) VersionInterfacesFunc { - return func(version schema.GroupVersion) (*VersionInterfaces, error) { - if i, err := parent(version); err == nil { - return &VersionInterfaces{ - ObjectConvertor: i.ObjectConvertor, - MetadataAccessor: NewAccessor(), - }, nil - } - return InterfacesForUnstructured(version) - } -} - -// InterfacesForUnstructured returns VersionInterfaces suitable for -// dealing with unstructured.Unstructured objects. It will return errors for -// other conversions. -func InterfacesForUnstructured(schema.GroupVersion) (*VersionInterfaces, error) { - return &VersionInterfaces{ - ObjectConvertor: &unstructured.UnstructuredObjectConverter{}, - MetadataAccessor: NewAccessor(), - }, nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/BUILD index 57f85fb24..7d2c84c92 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/BUILD @@ -18,7 +18,6 @@ go_test( embed = [":go_default_library"], deps = [ "//vendor/github.com/google/gofuzz:go_default_library", - "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/gopkg.in/inf.v0:go_default_library", ], ) @@ -38,7 +37,6 @@ go_library( importpath = "k8s.io/apimachinery/pkg/api/resource", deps = [ "//vendor/github.com/gogo/protobuf/proto:go_default_library", - "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/gopkg.in/inf.v0:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/generated.pb.go index 6de71e508..802f22a63 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,13 +19,13 @@ limitations under the License. // DO NOT EDIT! /* - Package resource is a generated protocol buffer package. +Package resource is a generated protocol buffer package. - It is generated from these files: - k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto +It is generated from these files: + k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto - It has these top-level messages: - Quantity +It has these top-level messages: + Quantity */ package resource @@ -57,21 +57,20 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 255 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x8f, 0xa1, 0x4e, 0x03, 0x41, - 0x10, 0x86, 0x77, 0x0d, 0x29, 0x95, 0x0d, 0x21, 0xa4, 0x62, 0xaf, 0x21, 0x08, 0x0c, 0x3b, 0x02, - 0xd3, 0x20, 0xf1, 0x08, 0x90, 0xb8, 0xbb, 0xeb, 0xb0, 0xdd, 0x1c, 0xdd, 0xbd, 0xcc, 0xce, 0x92, - 0xd4, 0x55, 0x22, 0x2b, 0x91, 0xbd, 0xb7, 0xa9, 0xac, 0xac, 0x40, 0x70, 0xcb, 0x8b, 0x90, 0x5e, - 0xdb, 0x84, 0x90, 0xe0, 0xe6, 0xfb, 0x27, 0xdf, 0xe4, 0x9f, 0xfe, 0x43, 0x35, 0x0e, 0xda, 0x7a, - 0xa8, 0x62, 0x81, 0xe4, 0x90, 0x31, 0xc0, 0x1b, 0xba, 0x89, 0x27, 0x38, 0x2c, 0xf2, 0xda, 0xce, - 0xf2, 0x72, 0x6a, 0x1d, 0xd2, 0x1c, 0xea, 0xca, 0xec, 0x02, 0x20, 0x0c, 0x3e, 0x52, 0x89, 0x60, - 0xd0, 0x21, 0xe5, 0x8c, 0x13, 0x5d, 0x93, 0x67, 0x3f, 0xb8, 0xda, 0x5b, 0xfa, 0xb7, 0xa5, 0xeb, - 0xca, 0xec, 0x02, 0x7d, 0xb4, 0x86, 0x37, 0xc6, 0xf2, 0x34, 0x16, 0xba, 0xf4, 0x33, 0x30, 0xde, - 0x78, 0xe8, 0xe4, 0x22, 0xbe, 0x74, 0xd4, 0x41, 0x37, 0xed, 0x8f, 0x0e, 0x6f, 0xff, 0xab, 0x12, - 0xd9, 0xbe, 0x82, 0x75, 0x1c, 0x98, 0xfe, 0x36, 0xb9, 0x1c, 0xf7, 0x7b, 0x8f, 0x31, 0x77, 0x6c, - 0x79, 0x3e, 0x38, 0xef, 0x9f, 0x04, 0x26, 0xeb, 0xcc, 0x85, 0x1c, 0xc9, 0xeb, 0xd3, 0xa7, 0x03, - 0xdd, 0x9d, 0x7d, 0xac, 0x32, 0xf1, 0xde, 0x64, 0x62, 0xd9, 0x64, 0x62, 0xd5, 0x64, 0x62, 0xf1, - 0x39, 0x12, 0xf7, 0x7a, 0xdd, 0x2a, 0xb1, 0x69, 0x95, 0xd8, 0xb6, 0x4a, 0x2c, 0x92, 0x92, 0xeb, - 0xa4, 0xe4, 0x26, 0x29, 0xb9, 0x4d, 0x4a, 0x7e, 0x25, 0x25, 0x97, 0xdf, 0x4a, 0x3c, 0xf7, 0x8e, - 0xdf, 0xfc, 0x04, 0x00, 0x00, 0xff, 0xff, 0x5f, 0x5e, 0xda, 0xf9, 0x43, 0x01, 0x00, 0x00, + // 237 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x8e, 0xb1, 0x4e, 0xc3, 0x30, + 0x10, 0x40, 0xcf, 0x0b, 0x2a, 0x19, 0x2b, 0x84, 0x10, 0xc3, 0xa5, 0x42, 0x0c, 0x2c, 0xd8, 0x6b, + 0xc5, 0xc8, 0xce, 0x00, 0x23, 0x5b, 0x92, 0x1e, 0xae, 0x15, 0xd5, 0x8e, 0x2e, 0x36, 0x52, 0xb7, + 0x8e, 0x8c, 0x1d, 0x19, 0x9b, 0xbf, 0xe9, 0xd8, 0xb1, 0x03, 0x03, 0x31, 0x3f, 0x82, 0xea, 0x36, + 0x52, 0xb7, 0x7b, 0xef, 0xf4, 0x4e, 0x97, 0xbd, 0xd4, 0xd3, 0x56, 0x1a, 0xa7, 0xea, 0x50, 0x12, + 0x5b, 0xf2, 0xd4, 0xaa, 0x4f, 0xb2, 0x33, 0xc7, 0xea, 0xb4, 0x28, 0x1a, 0xb3, 0x28, 0xaa, 0xb9, + 0xb1, 0xc4, 0x4b, 0xd5, 0xd4, 0xfa, 0x20, 0x14, 0x53, 0xeb, 0x02, 0x57, 0xa4, 0x34, 0x59, 0xe2, + 0xc2, 0xd3, 0x4c, 0x36, 0xec, 0xbc, 0x1b, 0xdf, 0x1f, 0x2b, 0x79, 0x5e, 0xc9, 0xa6, 0xd6, 0x07, + 0x21, 0x87, 0xea, 0xf6, 0x51, 0x1b, 0x3f, 0x0f, 0xa5, 0xac, 0xdc, 0x42, 0x69, 0xa7, 0x9d, 0x4a, + 0x71, 0x19, 0x3e, 0x12, 0x25, 0x48, 0xd3, 0xf1, 0xe8, 0xdd, 0x34, 0x1b, 0xbd, 0x86, 0xc2, 0x7a, + 0xe3, 0x97, 0xe3, 0xeb, 0xec, 0xa2, 0xf5, 0x6c, 0xac, 0xbe, 0x11, 0x13, 0xf1, 0x70, 0xf9, 0x76, + 0xa2, 0xa7, 0xab, 0xef, 0x4d, 0x0e, 0x5f, 0x5d, 0x0e, 0xeb, 0x2e, 0x87, 0x4d, 0x97, 0xc3, 0xea, + 0x67, 0x02, 0xcf, 0x72, 0xdb, 0x23, 0xec, 0x7a, 0x84, 0x7d, 0x8f, 0xb0, 0x8a, 0x28, 0xb6, 0x11, + 0xc5, 0x2e, 0xa2, 0xd8, 0x47, 0x14, 0xbf, 0x11, 0xc5, 0xfa, 0x0f, 0xe1, 0x7d, 0x34, 0x3c, 0xf6, + 0x1f, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x08, 0x88, 0x49, 0x0e, 0x01, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/generated.proto index 40185777e..2c0aaa45b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,8 +21,6 @@ syntax = 'proto2'; package k8s.io.apimachinery.pkg.api.resource; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - // Package-wide variables from generator "generated". option go_package = "resource"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go index 6a8bb9972..c3cd13960 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go @@ -25,8 +25,6 @@ import ( "strconv" "strings" - flag "github.com/spf13/pflag" - inf "gopkg.in/inf.v0" ) @@ -747,43 +745,3 @@ func (q *Quantity) Copy() *Quantity { Format: q.Format, } } - -// qFlag is a helper type for the Flag function -type qFlag struct { - dest *Quantity -} - -// Sets the value of the internal Quantity. (used by flag & pflag) -func (qf qFlag) Set(val string) error { - q, err := ParseQuantity(val) - if err != nil { - return err - } - // This copy is OK because q will not be referenced again. - *qf.dest = q - return nil -} - -// Converts the value of the internal Quantity to a string. (used by flag & pflag) -func (qf qFlag) String() string { - return qf.dest.String() -} - -// States the type of flag this is (Quantity). (used by pflag) -func (qf qFlag) Type() string { - return "quantity" -} - -// QuantityFlag is a helper that makes a quantity flag (using standard flag package). -// Will panic if defaultValue is not a valid quantity. -func QuantityFlag(flagName, defaultValue, description string) *Quantity { - q := MustParse(defaultValue) - flag.Var(NewQuantityFlagValue(&q), flagName, description) - return &q -} - -// NewQuantityFlagValue returns an object that can be used to back a flag, -// pointing at the given Quantity variable. -func NewQuantityFlagValue(q *Quantity) flag.Value { - return qFlag{q} -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_test.go index 74f091a38..915b2444e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_test.go @@ -24,7 +24,6 @@ import ( "unicode" fuzz "github.com/google/gofuzz" - "github.com/spf13/pflag" inf "gopkg.in/inf.v0" ) @@ -1059,21 +1058,6 @@ func TestCopy(t *testing.T) { } } -func TestQFlagSet(t *testing.T) { - qf := qFlag{&Quantity{}} - qf.Set("1Ki") - if e, a := "1Ki", qf.String(); e != a { - t.Errorf("Unexpected result %v != %v", e, a) - } -} - -func TestQFlagIsPFlag(t *testing.T) { - var pfv pflag.Value = qFlag{} - if e, a := "quantity", pfv.Type(); e != a { - t.Errorf("Unexpected result %v != %v", e, a) - } -} - func TestSub(t *testing.T) { tests := []struct { a Quantity diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go index fc36d9811..ab4740790 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip/BUILD index af01af51b..9c201c91f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip/BUILD @@ -18,8 +18,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip/roundtrip.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip/roundtrip.go index 0c032b815..f8b12aa85 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip/roundtrip.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip/roundtrip.go @@ -33,8 +33,6 @@ import ( apimeta "k8s.io/apimachinery/pkg/api/meta" apitesting "k8s.io/apimachinery/pkg/api/testing" "k8s.io/apimachinery/pkg/api/testing/fuzzer" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,15 +43,13 @@ import ( "k8s.io/apimachinery/pkg/util/sets" ) -type InstallFunc func(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) +type InstallFunc func(scheme *runtime.Scheme) // RoundTripTestForAPIGroup is convenient to call from your install package to make sure that a "bare" install of your group provides // enough information to round trip func RoundTripTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs fuzzer.FuzzerFuncs) { - groupFactoryRegistry := make(announced.APIGroupFactoryRegistry) - registry := registered.NewOrDie("") scheme := runtime.NewScheme() - installFn(groupFactoryRegistry, registry, scheme) + installFn(scheme) RoundTripTestForScheme(t, scheme, fuzzingFuncs) } @@ -72,10 +68,8 @@ func RoundTripTestForScheme(t *testing.T, scheme *runtime.Scheme, fuzzingFuncs f // RoundTripProtobufTestForAPIGroup is convenient to call from your install package to make sure that a "bare" install of your group provides // enough information to round trip func RoundTripProtobufTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs fuzzer.FuzzerFuncs) { - groupFactoryRegistry := make(announced.APIGroupFactoryRegistry) - registry := registered.NewOrDie("") scheme := runtime.NewScheme() - installFn(groupFactoryRegistry, registry, scheme) + installFn(scheme) RoundTripProtobufTestForScheme(t, scheme, fuzzingFuncs) } @@ -138,6 +132,24 @@ func roundTripTypes(t *testing.T, scheme *runtime.Scheme, codecFactory runtimese } } +// RoundTripExternalTypes applies the round-trip test to all external round-trippable Kinds +// in the scheme. It will skip all the GroupVersionKinds in the nonRoundTripExternalTypes list . +func RoundTripExternalTypes(t *testing.T, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) { + kinds := scheme.AllKnownTypes() + for gvk := range kinds { + if gvk.Version == runtime.APIVersionInternal || globalNonRoundTrippableTypes.Has(gvk.Kind) { + continue + } + + // FIXME: this is explicitly testing w/o protobuf which was failing if enabled + // the reason for that is that protobuf is not setting Kind and APIVersion fields + // during obj2 decode, the same then applies to DecodeInto obj3. My guess is we + // should be setting these two fields accordingly when protobuf is passed as codec + // to roundTrip method. + roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true) + } +} + func RoundTripSpecificKindWithoutProtobuf(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) { roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta.go index 3c32a937a..44b9b1600 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta.go @@ -30,10 +30,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ) -// TODO: delete this global variable when we enable the validation of common -// fields by default. -var RepairMalformedUpdates bool = true - const FieldImmutableErrorMsg string = `field is immutable` const totalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB @@ -254,39 +250,6 @@ func ValidateObjectMetaUpdate(newMeta, oldMeta *metav1.ObjectMeta, fldPath *fiel func ValidateObjectMetaAccessorUpdate(newMeta, oldMeta metav1.Object, fldPath *field.Path) field.ErrorList { var allErrs field.ErrorList - if !RepairMalformedUpdates && newMeta.GetUID() != oldMeta.GetUID() { - allErrs = append(allErrs, field.Invalid(fldPath.Child("uid"), newMeta.GetUID(), "field is immutable")) - } - // in the event it is left empty, set it, to allow clients more flexibility - // TODO: remove the following code that repairs the update request when we retire the clients that modify the immutable fields. - // Please do not copy this pattern elsewhere; validation functions should not be modifying the objects they are passed! - if RepairMalformedUpdates { - if len(newMeta.GetUID()) == 0 { - newMeta.SetUID(oldMeta.GetUID()) - } - // ignore changes to timestamp - if oldCreationTime := oldMeta.GetCreationTimestamp(); oldCreationTime.IsZero() { - oldMeta.SetCreationTimestamp(newMeta.GetCreationTimestamp()) - } else { - newMeta.SetCreationTimestamp(oldMeta.GetCreationTimestamp()) - } - // an object can never remove a deletion timestamp or clear/change grace period seconds - if !oldMeta.GetDeletionTimestamp().IsZero() { - newMeta.SetDeletionTimestamp(oldMeta.GetDeletionTimestamp()) - } - if oldMeta.GetDeletionGracePeriodSeconds() != nil && newMeta.GetDeletionGracePeriodSeconds() == nil { - newMeta.SetDeletionGracePeriodSeconds(oldMeta.GetDeletionGracePeriodSeconds()) - } - } - - // TODO: needs to check if newMeta==nil && oldMeta !=nil after the repair logic is removed. - if newMeta.GetDeletionGracePeriodSeconds() != nil && (oldMeta.GetDeletionGracePeriodSeconds() == nil || *newMeta.GetDeletionGracePeriodSeconds() != *oldMeta.GetDeletionGracePeriodSeconds()) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("deletionGracePeriodSeconds"), newMeta.GetDeletionGracePeriodSeconds(), "field is immutable; may only be changed via deletion")) - } - if newMeta.GetDeletionTimestamp() != nil && (oldMeta.GetDeletionTimestamp() == nil || !newMeta.GetDeletionTimestamp().Equal(oldMeta.GetDeletionTimestamp())) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("deletionTimestamp"), newMeta.GetDeletionTimestamp(), "field is immutable; may only be changed via deletion")) - } - // Finalizers cannot be added if the object is already being deleted. if oldMeta.GetDeletionTimestamp() != nil { allErrs = append(allErrs, ValidateNoNewFinalizers(newMeta.GetFinalizers(), oldMeta.GetFinalizers(), fldPath.Child("finalizers"))...) @@ -308,6 +271,8 @@ func ValidateObjectMetaAccessorUpdate(newMeta, oldMeta metav1.Object, fldPath *f allErrs = append(allErrs, ValidateImmutableField(newMeta.GetNamespace(), oldMeta.GetNamespace(), fldPath.Child("namespace"))...) allErrs = append(allErrs, ValidateImmutableField(newMeta.GetUID(), oldMeta.GetUID(), fldPath.Child("uid"))...) allErrs = append(allErrs, ValidateImmutableField(newMeta.GetCreationTimestamp(), oldMeta.GetCreationTimestamp(), fldPath.Child("creationTimestamp"))...) + allErrs = append(allErrs, ValidateImmutableField(newMeta.GetDeletionTimestamp(), oldMeta.GetDeletionTimestamp(), fldPath.Child("deletionTimestamp"))...) + allErrs = append(allErrs, ValidateImmutableField(newMeta.GetDeletionGracePeriodSeconds(), oldMeta.GetDeletionGracePeriodSeconds(), fldPath.Child("deletionGracePeriodSeconds"))...) allErrs = append(allErrs, ValidateImmutableField(newMeta.GetClusterName(), oldMeta.GetClusterName(), fldPath.Child("clusterName"))...) allErrs = append(allErrs, v1validation.ValidateLabels(newMeta.GetLabels(), fldPath.Child("labels"))...) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta_test.go index 9ec73b040..ebd6c7e7c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta_test.go @@ -219,21 +219,21 @@ func TestValidateObjectMetaUpdateIgnoresCreationTimestamp(t *testing.T) { &metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, &metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))}, field.NewPath("field"), - ); len(errs) != 0 { + ); len(errs) != 1 { t.Fatalf("unexpected errors: %v", errs) } if errs := ValidateObjectMetaUpdate( &metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))}, &metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, field.NewPath("field"), - ); len(errs) != 0 { + ); len(errs) != 1 { t.Fatalf("unexpected errors: %v", errs) } if errs := ValidateObjectMetaUpdate( &metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))}, &metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(11, 0))}, field.NewPath("field"), - ); len(errs) != 0 { + ); len(errs) != 1 { t.Fatalf("unexpected errors: %v", errs) } } @@ -328,38 +328,38 @@ func TestValidateObjectMetaUpdatePreventsDeletionFieldMutation(t *testing.T) { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: 1970-01-01 00:16:40 +0000 UTC: field is immutable; may only be changed via deletion"}, + ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: 1970-01-01 00:16:40 +0000 UTC: field is immutable"}, }, "invalid clear deletionTimestamp": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, - ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedErrs: []string{}, // no errors, validation copies the old value + ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, + ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: \"null\": field is immutable"}, }, "invalid change deletionTimestamp": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &later}, - ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedErrs: []string{}, // no errors, validation copies the old value + ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &later}, + ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: 1970-01-01 00:33:20 +0000 UTC: field is immutable"}, }, "invalid set deletionGracePeriodSeconds": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, - ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 30: field is immutable; may only be changed via deletion"}, + ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 30: field is immutable"}, }, "invalid clear deletionGracePeriodSeconds": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, - ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, - ExpectedErrs: []string{}, // no errors, validation copies the old value + ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"}, + ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: \"null\": field is immutable"}, }, "invalid change deletionGracePeriodSeconds": { Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong}, ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong}, - ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 40: field is immutable; may only be changed via deletion"}, + ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 40: field is immutable"}, }, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/BUILD deleted file mode 100644 index b1071fb46..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["types_test.go"], - embed = [":go_default_library"], - deps = ["//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "types.go", - ], - importpath = "k8s.io/apimachinery/pkg/apimachinery", - deps = [ - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/apimachinery/pkg/apimachinery/announced:all-srcs", - "//staging/src/k8s.io/apimachinery/pkg/apimachinery/registered:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/BUILD deleted file mode 100644 index ea31914f7..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["announced_test.go"], - embed = [":go_default_library"], - deps = ["//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = [ - "announced.go", - "group_factory.go", - ], - importpath = "k8s.io/apimachinery/pkg/apimachinery/announced", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered: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/util/sets:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/announced.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/announced.go deleted file mode 100644 index 4e38cc8c5..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/announced.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -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 announced contains tools for announcing API group factories. This is -// distinct from registration (in the 'registered' package) in that it's safe -// to announce every possible group linked in, but only groups requested at -// runtime should be registered. This package contains both a registry, and -// factory code (which was formerly copy-pasta in every install package). -package announced - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/apimachinery/registered" - "k8s.io/apimachinery/pkg/runtime" -) - -// APIGroupFactoryRegistry allows for groups and versions to announce themselves, -// which simply makes them available and doesn't take other actions. Later, -// users of the registry can select which groups and versions they'd actually -// like to register with an APIRegistrationManager. -// -// (Right now APIRegistrationManager has separate 'registration' and 'enabled' -// concepts-- APIGroupFactory is going to take over the former function; -// they will overlap until the refactoring is finished.) -// -// The key is the group name. After initialization, this should be treated as -// read-only. It is implemented as a map from group name to group factory, and -// it is safe to use this knowledge to manually pick out groups to register -// (e.g., for testing). -type APIGroupFactoryRegistry map[string]*GroupMetaFactory - -func (gar APIGroupFactoryRegistry) group(groupName string) *GroupMetaFactory { - gmf, ok := gar[groupName] - if !ok { - gmf = &GroupMetaFactory{VersionArgs: map[string]*GroupVersionFactoryArgs{}} - gar[groupName] = gmf - } - return gmf -} - -// AnnounceGroupVersion adds the particular arguments for this group version to the group factory. -func (gar APIGroupFactoryRegistry) AnnounceGroupVersion(gvf *GroupVersionFactoryArgs) error { - gmf := gar.group(gvf.GroupName) - if _, ok := gmf.VersionArgs[gvf.VersionName]; ok { - return fmt.Errorf("version %q in group %q has already been announced", gvf.VersionName, gvf.GroupName) - } - gmf.VersionArgs[gvf.VersionName] = gvf - return nil -} - -// AnnounceGroup adds the group-wide arguments to the group factory. -func (gar APIGroupFactoryRegistry) AnnounceGroup(args *GroupMetaFactoryArgs) error { - gmf := gar.group(args.GroupName) - if gmf.GroupArgs != nil { - return fmt.Errorf("group %q has already been announced", args.GroupName) - } - gmf.GroupArgs = args - return nil -} - -// RegisterAndEnableAll throws every factory at the specified API registration -// manager, and lets it decide which to register. (If you want to do this a la -// cart, you may look through gar itself-- it's just a map.) -func (gar APIGroupFactoryRegistry) RegisterAndEnableAll(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error { - for groupName, gmf := range gar { - if err := gmf.Register(m); err != nil { - return fmt.Errorf("error registering %v: %v", groupName, err) - } - if err := gmf.Enable(m, scheme); err != nil { - return fmt.Errorf("error enabling %v: %v", groupName, err) - } - } - return nil -} - -// AnnouncePreconstructedFactory announces a factory which you've manually assembled. -// You may call this instead of calling AnnounceGroup and AnnounceGroupVersion. -func (gar APIGroupFactoryRegistry) AnnouncePreconstructedFactory(gmf *GroupMetaFactory) error { - name := gmf.GroupArgs.GroupName - if _, exists := gar[name]; exists { - return fmt.Errorf("the group %q has already been announced.", name) - } - gar[name] = gmf - return nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/announced_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/announced_test.go deleted file mode 100644 index 95882e5df..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/announced_test.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -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 announced - -import ( - "reflect" - "testing" - - "k8s.io/apimachinery/pkg/util/sets" -) - -func TestFactoryRegistry(t *testing.T) { - regA := make(APIGroupFactoryRegistry) - regB := make(APIGroupFactoryRegistry) - - if err := regA.AnnounceGroup(&GroupMetaFactoryArgs{ - GroupName: "foo", - VersionPreferenceOrder: []string{"v2", "v1"}, - RootScopedKinds: sets.NewString("namespaces"), - }); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if err := regA.AnnounceGroupVersion(&GroupVersionFactoryArgs{ - GroupName: "foo", - VersionName: "v1", - }); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if err := regA.AnnounceGroupVersion(&GroupVersionFactoryArgs{ - GroupName: "foo", - VersionName: "v2", - }); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - if err := regB.AnnouncePreconstructedFactory(NewGroupMetaFactory( - &GroupMetaFactoryArgs{ - GroupName: "foo", - VersionPreferenceOrder: []string{"v2", "v1"}, - RootScopedKinds: sets.NewString("namespaces"), - }, - VersionToSchemeFunc{"v1": nil, "v2": nil}, - )); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - if !reflect.DeepEqual(regA, regB) { - t.Errorf("Expected both ways of registering to be equivalent, but they were not.\n\n%#v\n\n%#v\n", regA, regB) - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go deleted file mode 100644 index 154ed08f5..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go +++ /dev/null @@ -1,255 +0,0 @@ -/* -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 announced - -import ( - "fmt" - - "github.com/golang/glog" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/apimachinery" - "k8s.io/apimachinery/pkg/apimachinery/registered" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/sets" -) - -type SchemeFunc func(*runtime.Scheme) error -type VersionToSchemeFunc map[string]SchemeFunc - -// GroupVersionFactoryArgs contains all the per-version parts of a GroupMetaFactory. -type GroupVersionFactoryArgs struct { - GroupName string - VersionName string - - AddToScheme SchemeFunc -} - -// GroupMetaFactoryArgs contains the group-level args of a GroupMetaFactory. -type GroupMetaFactoryArgs struct { - // GroupName is the name of the API-Group - // - // example: 'servicecatalog.k8s.io' - GroupName string - VersionPreferenceOrder []string - // RootScopedKinds are resources that are not namespaced. - RootScopedKinds sets.String // nil is allowed - IgnoredKinds sets.String // nil is allowed - - // May be nil if there are no internal objects. - AddInternalObjectsToScheme SchemeFunc -} - -// NewGroupMetaFactory builds the args for you. This is for if you're -// constructing a factory all at once and not using the registry. -func NewGroupMetaFactory(groupArgs *GroupMetaFactoryArgs, versions VersionToSchemeFunc) *GroupMetaFactory { - gmf := &GroupMetaFactory{ - GroupArgs: groupArgs, - VersionArgs: map[string]*GroupVersionFactoryArgs{}, - } - for v, f := range versions { - gmf.VersionArgs[v] = &GroupVersionFactoryArgs{ - GroupName: groupArgs.GroupName, - VersionName: v, - AddToScheme: f, - } - } - return gmf -} - -// Announce adds this Group factory to the global factory registry. It should -// only be called if you constructed the GroupMetaFactory yourself via -// NewGroupMetaFactory. -// Note that this will panic on an error, since it's expected that you'll be -// calling this at initialization time and any error is a result of a -// programmer importing the wrong set of packages. If this assumption doesn't -// work for you, just call DefaultGroupFactoryRegistry.AnnouncePreconstructedFactory -// yourself. -func (gmf *GroupMetaFactory) Announce(groupFactoryRegistry APIGroupFactoryRegistry) *GroupMetaFactory { - if err := groupFactoryRegistry.AnnouncePreconstructedFactory(gmf); err != nil { - panic(err) - } - return gmf -} - -// GroupMetaFactory has the logic for actually assembling and registering a group. -// -// There are two ways of obtaining one of these. -// 1. You can announce your group and versions separately, and then let the -// GroupFactoryRegistry assemble this object for you. (This allows group and -// versions to be imported separately, without referencing each other, to -// keep import trees small.) -// 2. You can call NewGroupMetaFactory(), which is mostly a drop-in replacement -// for the old, bad way of doing things. You can then call .Announce() to -// announce your constructed factory to any code that would like to do -// things the new, better way. -// -// Note that GroupMetaFactory actually does construct GroupMeta objects, but -// currently it does so in a way that's very entangled with an -// APIRegistrationManager. It's a TODO item to cleanly separate that interface. -type GroupMetaFactory struct { - GroupArgs *GroupMetaFactoryArgs - // map of version name to version factory - VersionArgs map[string]*GroupVersionFactoryArgs - - // assembled by Register() - prioritizedVersionList []schema.GroupVersion -} - -// Register constructs the finalized prioritized version list and sanity checks -// the announced group & versions. Then it calls register. -func (gmf *GroupMetaFactory) Register(m *registered.APIRegistrationManager) error { - if gmf.GroupArgs == nil { - return fmt.Errorf("partially announced groups are not allowed, only got versions: %#v", gmf.VersionArgs) - } - if len(gmf.VersionArgs) == 0 { - return fmt.Errorf("group %v announced but no versions announced", gmf.GroupArgs.GroupName) - } - - pvSet := sets.NewString(gmf.GroupArgs.VersionPreferenceOrder...) - if pvSet.Len() != len(gmf.GroupArgs.VersionPreferenceOrder) { - return fmt.Errorf("preference order for group %v has duplicates: %v", gmf.GroupArgs.GroupName, gmf.GroupArgs.VersionPreferenceOrder) - } - prioritizedVersions := []schema.GroupVersion{} - for _, v := range gmf.GroupArgs.VersionPreferenceOrder { - prioritizedVersions = append( - prioritizedVersions, - schema.GroupVersion{ - Group: gmf.GroupArgs.GroupName, - Version: v, - }, - ) - } - - // Go through versions that weren't explicitly prioritized. - unprioritizedVersions := []schema.GroupVersion{} - for _, v := range gmf.VersionArgs { - if v.GroupName != gmf.GroupArgs.GroupName { - return fmt.Errorf("found %v/%v in group %v?", v.GroupName, v.VersionName, gmf.GroupArgs.GroupName) - } - if pvSet.Has(v.VersionName) { - pvSet.Delete(v.VersionName) - continue - } - unprioritizedVersions = append(unprioritizedVersions, schema.GroupVersion{Group: v.GroupName, Version: v.VersionName}) - } - if len(unprioritizedVersions) > 1 { - glog.Warningf("group %v has multiple unprioritized versions: %#v. They will have an arbitrary preference order!", gmf.GroupArgs.GroupName, unprioritizedVersions) - } - if pvSet.Len() != 0 { - return fmt.Errorf("group %v has versions in the priority list that were never announced: %s", gmf.GroupArgs.GroupName, pvSet) - } - prioritizedVersions = append(prioritizedVersions, unprioritizedVersions...) - m.RegisterVersions(prioritizedVersions) - gmf.prioritizedVersionList = prioritizedVersions - return nil -} - -func (gmf *GroupMetaFactory) newRESTMapper(scheme *runtime.Scheme, externalVersions []schema.GroupVersion, groupMeta *apimachinery.GroupMeta) meta.RESTMapper { - // the list of kinds that are scoped at the root of the api hierarchy - // if a kind is not enumerated here, it is assumed to have a namespace scope - rootScoped := sets.NewString() - if gmf.GroupArgs.RootScopedKinds != nil { - rootScoped = gmf.GroupArgs.RootScopedKinds - } - ignoredKinds := sets.NewString() - if gmf.GroupArgs.IgnoredKinds != nil { - ignoredKinds = gmf.GroupArgs.IgnoredKinds - } - - mapper := meta.NewDefaultRESTMapper(externalVersions, groupMeta.InterfacesFor) - for _, gv := range externalVersions { - for kind := range scheme.KnownTypes(gv) { - if ignoredKinds.Has(kind) { - continue - } - scope := meta.RESTScopeNamespace - if rootScoped.Has(kind) { - scope = meta.RESTScopeRoot - } - mapper.Add(gv.WithKind(kind), scope) - } - } - - return mapper -} - -// Enable enables group versions that are allowed, adds methods to the scheme, etc. -func (gmf *GroupMetaFactory) Enable(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error { - externalVersions := []schema.GroupVersion{} - for _, v := range gmf.prioritizedVersionList { - if !m.IsAllowedVersion(v) { - continue - } - externalVersions = append(externalVersions, v) - if err := m.EnableVersions(v); err != nil { - return err - } - gmf.VersionArgs[v.Version].AddToScheme(scheme) - } - if len(externalVersions) == 0 { - glog.V(4).Infof("No version is registered for group %v", gmf.GroupArgs.GroupName) - return nil - } - - if gmf.GroupArgs.AddInternalObjectsToScheme != nil { - gmf.GroupArgs.AddInternalObjectsToScheme(scheme) - } - - preferredExternalVersion := externalVersions[0] - accessor := meta.NewAccessor() - - groupMeta := &apimachinery.GroupMeta{ - GroupVersion: preferredExternalVersion, - GroupVersions: externalVersions, - SelfLinker: runtime.SelfLinker(accessor), - } - for _, v := range externalVersions { - gvf := gmf.VersionArgs[v.Version] - if err := groupMeta.AddVersionInterfaces( - schema.GroupVersion{Group: gvf.GroupName, Version: gvf.VersionName}, - &meta.VersionInterfaces{ - ObjectConvertor: scheme, - MetadataAccessor: accessor, - }, - ); err != nil { - return err - } - } - groupMeta.InterfacesFor = groupMeta.DefaultInterfacesFor - groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta) - - if err := m.RegisterGroup(*groupMeta); err != nil { - return err - } - return nil -} - -// RegisterAndEnable is provided only to allow this code to get added in multiple steps. -// It's really bad that this is called in init() methods, but supporting this -// temporarily lets us do the change incrementally. -func (gmf *GroupMetaFactory) RegisterAndEnable(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) error { - if err := gmf.Register(registry); err != nil { - return err - } - if err := gmf.Enable(registry, scheme); err != nil { - return err - } - - return nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/doc.go deleted file mode 100644 index b238454b2..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -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 apimachinery contains the generic API machinery code that -// is common to both server and clients. -// This package should never import specific API objects. -package apimachinery // import "k8s.io/apimachinery/pkg/apimachinery" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/BUILD deleted file mode 100644 index ba02a0938..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["registered_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - ], -) - -go_library( - name = "go_default_library", - srcs = ["registered.go"], - importpath = "k8s.io/apimachinery/pkg/apimachinery/registered", - deps = [ - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go deleted file mode 100644 index 0da94f50f..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go +++ /dev/null @@ -1,336 +0,0 @@ -/* -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 to keep track of API Versions that can be registered and are enabled in a Scheme. -package registered - -import ( - "fmt" - "sort" - "strings" - - "github.com/golang/glog" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/apimachinery" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/sets" -) - -// APIRegistrationManager provides the concept of what API groups are enabled. -// -// TODO: currently, it also provides a "registered" concept. But it's wrong to -// have both concepts in the same object. Therefore the "announced" package is -// going to take over the registered concept. After all the install packages -// are switched to using the announce package instead of this package, then we -// can combine the registered/enabled concepts in this object. Simplifying this -// isn't easy right now because there are so many callers of this package. -type APIRegistrationManager struct { - // registeredGroupVersions stores all API group versions for which RegisterGroup is called. - registeredVersions map[schema.GroupVersion]struct{} - - // enabledVersions represents all enabled API versions. It should be a - // subset of registeredVersions. Please call EnableVersions() to add - // enabled versions. - enabledVersions map[schema.GroupVersion]struct{} - - // map of group meta for all groups. - groupMetaMap map[string]*apimachinery.GroupMeta - - // envRequestedVersions represents the versions requested via the - // KUBE_API_VERSIONS environment variable. The install package of each group - // checks this list before add their versions to the latest package and - // Scheme. This list is small and order matters, so represent as a slice - envRequestedVersions []schema.GroupVersion -} - -// NewAPIRegistrationManager constructs a new manager. The argument ought to be -// the value of the KUBE_API_VERSIONS env var, or a value of this which you -// wish to test. -func NewAPIRegistrationManager(kubeAPIVersions string) (*APIRegistrationManager, error) { - m := &APIRegistrationManager{ - registeredVersions: map[schema.GroupVersion]struct{}{}, - enabledVersions: map[schema.GroupVersion]struct{}{}, - groupMetaMap: map[string]*apimachinery.GroupMeta{}, - envRequestedVersions: []schema.GroupVersion{}, - } - - if len(kubeAPIVersions) != 0 { - for _, version := range strings.Split(kubeAPIVersions, ",") { - gv, err := schema.ParseGroupVersion(version) - if err != nil { - return nil, fmt.Errorf("invalid api version: %s in KUBE_API_VERSIONS: %s.", - version, kubeAPIVersions) - } - m.envRequestedVersions = append(m.envRequestedVersions, gv) - } - } - return m, nil -} - -func NewOrDie(kubeAPIVersions string) *APIRegistrationManager { - m, err := NewAPIRegistrationManager(kubeAPIVersions) - if err != nil { - glog.Fatalf("Could not construct version manager: %v (KUBE_API_VERSIONS=%q)", err, kubeAPIVersions) - } - return m -} - -// RegisterVersions adds the given group versions to the list of registered group versions. -func (m *APIRegistrationManager) RegisterVersions(availableVersions []schema.GroupVersion) { - for _, v := range availableVersions { - m.registeredVersions[v] = struct{}{} - } -} - -// RegisterGroup adds the given group to the list of registered groups. -func (m *APIRegistrationManager) RegisterGroup(groupMeta apimachinery.GroupMeta) error { - groupName := groupMeta.GroupVersion.Group - if _, found := m.groupMetaMap[groupName]; found { - return fmt.Errorf("group %q is already registered in groupsMap: %v", groupName, m.groupMetaMap) - } - m.groupMetaMap[groupName] = &groupMeta - return nil -} - -// EnableVersions adds the versions for the given group to the list of enabled versions. -// Note that the caller should call RegisterGroup before calling this method. -// The caller of this function is responsible to add the versions to scheme and RESTMapper. -func (m *APIRegistrationManager) EnableVersions(versions ...schema.GroupVersion) error { - var unregisteredVersions []schema.GroupVersion - for _, v := range versions { - if _, found := m.registeredVersions[v]; !found { - unregisteredVersions = append(unregisteredVersions, v) - } - m.enabledVersions[v] = struct{}{} - } - if len(unregisteredVersions) != 0 { - return fmt.Errorf("Please register versions before enabling them: %v", unregisteredVersions) - } - return nil -} - -// IsAllowedVersion returns if the version is allowed by the KUBE_API_VERSIONS -// environment variable. If the environment variable is empty, then it always -// returns true. -func (m *APIRegistrationManager) IsAllowedVersion(v schema.GroupVersion) bool { - if len(m.envRequestedVersions) == 0 { - return true - } - for _, envGV := range m.envRequestedVersions { - if v == envGV { - return true - } - } - return false -} - -// IsEnabledVersion returns if a version is enabled. -func (m *APIRegistrationManager) IsEnabledVersion(v schema.GroupVersion) bool { - _, found := m.enabledVersions[v] - return found -} - -// EnabledVersions returns all enabled versions. Groups are randomly ordered, but versions within groups -// are priority order from best to worst -func (m *APIRegistrationManager) EnabledVersions() []schema.GroupVersion { - ret := []schema.GroupVersion{} - for _, groupMeta := range m.groupMetaMap { - for _, version := range groupMeta.GroupVersions { - if m.IsEnabledVersion(version) { - ret = append(ret, version) - } - } - } - return ret -} - -// EnabledVersionsForGroup returns all enabled versions for a group in order of best to worst -func (m *APIRegistrationManager) EnabledVersionsForGroup(group string) []schema.GroupVersion { - groupMeta, ok := m.groupMetaMap[group] - if !ok { - return []schema.GroupVersion{} - } - - ret := []schema.GroupVersion{} - for _, version := range groupMeta.GroupVersions { - if m.IsEnabledVersion(version) { - ret = append(ret, version) - } - } - return ret -} - -// Group returns the metadata of a group if the group is registered, otherwise -// an error is returned. -func (m *APIRegistrationManager) Group(group string) (*apimachinery.GroupMeta, error) { - groupMeta, found := m.groupMetaMap[group] - if !found { - return nil, fmt.Errorf("group %v has not been registered", group) - } - groupMetaCopy := *groupMeta - return &groupMetaCopy, nil -} - -// IsRegistered takes a string and determines if it's one of the registered groups -func (m *APIRegistrationManager) IsRegistered(group string) bool { - _, found := m.groupMetaMap[group] - return found -} - -// IsRegisteredVersion returns if a version is registered. -func (m *APIRegistrationManager) IsRegisteredVersion(v schema.GroupVersion) bool { - _, found := m.registeredVersions[v] - return found -} - -// RegisteredGroupVersions returns all registered group versions. -func (m *APIRegistrationManager) RegisteredGroupVersions() []schema.GroupVersion { - ret := []schema.GroupVersion{} - for groupVersion := range m.registeredVersions { - ret = append(ret, groupVersion) - } - return ret -} - -// InterfacesFor is a union meta.VersionInterfacesFunc func for all registered types -func (m *APIRegistrationManager) InterfacesFor(version schema.GroupVersion) (*meta.VersionInterfaces, error) { - groupMeta, err := m.Group(version.Group) - if err != nil { - return nil, err - } - return groupMeta.InterfacesFor(version) -} - -// TODO: This is an expedient function, because we don't check if a Group is -// supported throughout the code base. We will abandon this function and -// checking the error returned by the Group() function. -func (m *APIRegistrationManager) GroupOrDie(group string) *apimachinery.GroupMeta { - groupMeta, found := m.groupMetaMap[group] - if !found { - if group == "" { - panic("The legacy v1 API is not registered.") - } else { - panic(fmt.Sprintf("Group %s is not registered.", group)) - } - } - groupMetaCopy := *groupMeta - return &groupMetaCopy -} - -// RESTMapper returns a union RESTMapper of all known types with priorities chosen in the following order: -// 1. if KUBE_API_VERSIONS is specified, then KUBE_API_VERSIONS in order, OR -// 1. legacy kube group preferred version, extensions preferred version, metrics perferred version, legacy -// kube any version, extensions any version, metrics any version, all other groups alphabetical preferred version, -// all other groups alphabetical. -func (m *APIRegistrationManager) RESTMapper(versionPatterns ...schema.GroupVersion) meta.RESTMapper { - unionMapper := meta.MultiRESTMapper{} - unionedGroups := sets.NewString() - for enabledVersion := range m.enabledVersions { - if !unionedGroups.Has(enabledVersion.Group) { - unionedGroups.Insert(enabledVersion.Group) - groupMeta := m.groupMetaMap[enabledVersion.Group] - unionMapper = append(unionMapper, groupMeta.RESTMapper) - } - } - - if len(versionPatterns) != 0 { - resourcePriority := []schema.GroupVersionResource{} - kindPriority := []schema.GroupVersionKind{} - for _, versionPriority := range versionPatterns { - resourcePriority = append(resourcePriority, versionPriority.WithResource(meta.AnyResource)) - kindPriority = append(kindPriority, versionPriority.WithKind(meta.AnyKind)) - } - - return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} - } - - if len(m.envRequestedVersions) != 0 { - resourcePriority := []schema.GroupVersionResource{} - kindPriority := []schema.GroupVersionKind{} - - for _, versionPriority := range m.envRequestedVersions { - resourcePriority = append(resourcePriority, versionPriority.WithResource(meta.AnyResource)) - kindPriority = append(kindPriority, versionPriority.WithKind(meta.AnyKind)) - } - - return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} - } - - prioritizedGroups := []string{"", "extensions", "metrics"} - resourcePriority, kindPriority := m.prioritiesForGroups(prioritizedGroups...) - - prioritizedGroupsSet := sets.NewString(prioritizedGroups...) - remainingGroups := sets.String{} - for enabledVersion := range m.enabledVersions { - if !prioritizedGroupsSet.Has(enabledVersion.Group) { - remainingGroups.Insert(enabledVersion.Group) - } - } - - remainingResourcePriority, remainingKindPriority := m.prioritiesForGroups(remainingGroups.List()...) - resourcePriority = append(resourcePriority, remainingResourcePriority...) - kindPriority = append(kindPriority, remainingKindPriority...) - - return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority} -} - -// prioritiesForGroups returns the resource and kind priorities for a PriorityRESTMapper, preferring the preferred version of each group first, -// then any non-preferred version of the group second. -func (m *APIRegistrationManager) prioritiesForGroups(groups ...string) ([]schema.GroupVersionResource, []schema.GroupVersionKind) { - resourcePriority := []schema.GroupVersionResource{} - kindPriority := []schema.GroupVersionKind{} - - for _, group := range groups { - availableVersions := m.EnabledVersionsForGroup(group) - if len(availableVersions) > 0 { - resourcePriority = append(resourcePriority, availableVersions[0].WithResource(meta.AnyResource)) - kindPriority = append(kindPriority, availableVersions[0].WithKind(meta.AnyKind)) - } - } - for _, group := range groups { - resourcePriority = append(resourcePriority, schema.GroupVersionResource{Group: group, Version: meta.AnyVersion, Resource: meta.AnyResource}) - kindPriority = append(kindPriority, schema.GroupVersionKind{Group: group, Version: meta.AnyVersion, Kind: meta.AnyKind}) - } - - return resourcePriority, kindPriority -} - -// AllPreferredGroupVersions returns the preferred versions of all registered -// groups in the form of "group1/version1,group2/version2,..." -func (m *APIRegistrationManager) AllPreferredGroupVersions() string { - if len(m.groupMetaMap) == 0 { - return "" - } - var defaults []string - for _, groupMeta := range m.groupMetaMap { - defaults = append(defaults, groupMeta.GroupVersion.String()) - } - sort.Strings(defaults) - return strings.Join(defaults, ",") -} - -// ValidateEnvRequestedVersions returns a list of versions that are requested in -// the KUBE_API_VERSIONS environment variable, but not enabled. -func (m *APIRegistrationManager) ValidateEnvRequestedVersions() []schema.GroupVersion { - var missingVersions []schema.GroupVersion - for _, v := range m.envRequestedVersions { - if _, found := m.enabledVersions[v]; !found { - missingVersions = append(missingVersions, v) - } - } - return missingVersions -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered_test.go deleted file mode 100644 index 58fc0173e..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered_test.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -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 registered - -import ( - "testing" - - "k8s.io/apimachinery/pkg/apimachinery" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestAllPreferredGroupVersions(t *testing.T) { - testCases := []struct { - groupMetas []apimachinery.GroupMeta - expect string - }{ - { - groupMetas: []apimachinery.GroupMeta{ - { - GroupVersion: schema.GroupVersion{Group: "group1", Version: "v1"}, - }, - { - GroupVersion: schema.GroupVersion{Group: "group2", Version: "v2"}, - }, - { - GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, - }, - }, - expect: "group1/v1,group2/v2,v1", - }, - { - groupMetas: []apimachinery.GroupMeta{ - { - GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, - }, - }, - expect: "v1", - }, - { - groupMetas: []apimachinery.GroupMeta{}, - expect: "", - }, - } - for _, testCase := range testCases { - m, err := NewAPIRegistrationManager("") - if err != nil { - t.Fatalf("Unexpected failure to make a manager: %v", err) - } - for _, groupMeta := range testCase.groupMetas { - m.RegisterGroup(groupMeta) - } - output := m.AllPreferredGroupVersions() - if testCase.expect != output { - t.Errorf("Error. expect: %s, got: %s", testCase.expect, output) - } - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/types.go deleted file mode 100644 index baca784fa..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/types.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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 apimachinery - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// GroupMeta stores the metadata of a group. -type GroupMeta struct { - // GroupVersion represents the preferred version of the group. - GroupVersion schema.GroupVersion - - // GroupVersions is Group + all versions in that group. - GroupVersions []schema.GroupVersion - - // SelfLinker can set or get the SelfLink field of all API types. - // TODO: when versioning changes, make this part of each API definition. - // TODO(lavalamp): Combine SelfLinker & ResourceVersioner interfaces, force all uses - // to go through the InterfacesFor method below. - SelfLinker runtime.SelfLinker - - // RESTMapper provides the default mapping between REST paths and the objects declared in a Scheme and all known - // versions. - RESTMapper meta.RESTMapper - - // InterfacesFor returns the default Codec and ResourceVersioner for a given version - // string, or an error if the version is not known. - // TODO: make this stop being a func pointer and always use the default - // function provided below once every place that populates this field has been changed. - InterfacesFor func(version schema.GroupVersion) (*meta.VersionInterfaces, error) - - // InterfacesByVersion stores the per-version interfaces. - InterfacesByVersion map[schema.GroupVersion]*meta.VersionInterfaces -} - -// DefaultInterfacesFor returns the default Codec and ResourceVersioner for a given version -// string, or an error if the version is not known. -// TODO: Remove the "Default" prefix. -func (gm *GroupMeta) DefaultInterfacesFor(version schema.GroupVersion) (*meta.VersionInterfaces, error) { - if v, ok := gm.InterfacesByVersion[version]; ok { - return v, nil - } - return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, gm.GroupVersions) -} - -// AddVersionInterfaces adds the given version to the group. Only call during -// init, after that GroupMeta objects should be immutable. Not thread safe. -// (If you use this, be sure to set .InterfacesFor = .DefaultInterfacesFor) -// TODO: remove the "Interfaces" suffix and make this also maintain the -// .GroupVersions member. -func (gm *GroupMeta) AddVersionInterfaces(version schema.GroupVersion, interfaces *meta.VersionInterfaces) error { - if e, a := gm.GroupVersion.Group, version.Group; a != e { - return fmt.Errorf("got a version in group %v, but am in group %v", a, e) - } - if gm.InterfacesByVersion == nil { - gm.InterfacesByVersion = make(map[schema.GroupVersion]*meta.VersionInterfaces) - } - gm.InterfacesByVersion[version] = interfaces - - // TODO: refactor to make the below error not possible, this function - // should *set* GroupVersions rather than depend on it. - for _, v := range gm.GroupVersions { - if v == version { - return nil - } - } - return fmt.Errorf("added a version interface without the corresponding version %v being in the list %#v", version, gm.GroupVersions) -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/types_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/types_test.go deleted file mode 100644 index ca858788e..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apimachinery/types_test.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -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 apimachinery - -import ( - "testing" - - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestAdd(t *testing.T) { - gm := GroupMeta{ - GroupVersion: schema.GroupVersion{ - Group: "test", - Version: "v1", - }, - GroupVersions: []schema.GroupVersion{{Group: "test", Version: "v1"}}, - } - - gm.AddVersionInterfaces(schema.GroupVersion{Group: "test", Version: "v1"}, nil) - if e, a := 1, len(gm.InterfacesByVersion); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - // GroupVersions is unchanged - if e, a := 1, len(gm.GroupVersions); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go index 54fab9c02..3a28f7431 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer/fuzzer.go @@ -181,16 +181,45 @@ func v1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} { j.Kind = "" }, func(j *metav1.ObjectMeta, c fuzz.Continue) { - j.Name = c.RandString() + c.FuzzNoCustom(j) + j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) - j.SelfLink = c.RandString() j.UID = types.UID(c.RandString()) - j.GenerateName = c.RandString() var sec, nsec int64 c.Fuzz(&sec) c.Fuzz(&nsec) j.CreationTimestamp = metav1.Unix(sec, nsec).Rfc3339Copy() + + if j.DeletionTimestamp != nil { + c.Fuzz(&sec) + c.Fuzz(&nsec) + t := metav1.Unix(sec, nsec).Rfc3339Copy() + j.DeletionTimestamp = &t + } + + if len(j.Labels) == 0 { + j.Labels = nil + } else { + delete(j.Labels, "") + } + if len(j.Annotations) == 0 { + j.Annotations = nil + } else { + delete(j.Annotations, "") + } + if len(j.OwnerReferences) == 0 { + j.OwnerReferences = nil + } + if len(j.Finalizers) == 0 { + j.Finalizers = nil + } + }, + func(j *metav1.Initializers, c fuzz.Continue) { + c.FuzzNoCustom(j) + if len(j.Pending) == 0 { + j.Pending = nil + } }, func(j *metav1.ListMeta, c fuzz.Continue) { j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) @@ -268,7 +297,7 @@ func v1alpha1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} { case 0: r.Cells[i] = c.RandString() case 1: - r.Cells[i] = c.Uint64() + r.Cells[i] = c.Int63() case 2: r.Cells[i] = c.RandBool() case 3: @@ -280,7 +309,7 @@ func v1alpha1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} { case 4: x := make([]interface{}, c.Intn(10)) for i := range x { - x[i] = c.Uint64() + x[i] = c.Int63() } r.Cells[i] = x default: diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.conversion.go index c3fd40a90..a63b3fc2c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go index e4e5b017b..77bd9a6b4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/BUILD index 186db1871..b4f04f884 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/BUILD @@ -21,9 +21,9 @@ go_test( embed = [":go_default_library"], deps = [ "//vendor/github.com/ghodss/yaml:go_default_library", - "//vendor/github.com/json-iterator/go:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go index cd651bcd5..c36fc6556 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go @@ -75,6 +75,8 @@ func AddConversionFuncs(scheme *runtime.Scheme) error { Convert_unversioned_LabelSelector_to_map, Convert_Slice_string_To_Slice_int32, + + Convert_Slice_string_To_v1_DeletionPropagation, ) } @@ -304,3 +306,13 @@ func Convert_Slice_string_To_Slice_int32(in *[]string, out *[]int32, s conversio } return nil } + +// Convert_Slice_string_To_v1_DeletionPropagation allows converting a URL query parameter propagationPolicy +func Convert_Slice_string_To_v1_DeletionPropagation(input *[]string, out *DeletionPropagation, s conversion.Scope) error { + if len(*input) > 0 { + *out = DeletionPropagation((*input)[0]) + } else { + *out = "" + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/conversion_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/conversion_test.go index bc591584e..4ff57fd8d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/conversion_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/conversion_test.go @@ -47,3 +47,38 @@ func TestMapToLabelSelectorRoundTrip(t *testing.T) { } } } + +func TestConvertSliceStringToDeletionPropagation(t *testing.T) { + tcs := []struct { + Input []string + Output v1.DeletionPropagation + }{ + { + Input: nil, + Output: "", + }, + { + Input: []string{}, + Output: "", + }, + { + Input: []string{"foo"}, + Output: "foo", + }, + { + Input: []string{"bar", "foo"}, + Output: "bar", + }, + } + + for _, tc := range tcs { + var dp v1.DeletionPropagation + if err := v1.Convert_Slice_string_To_v1_DeletionPropagation(&tc.Input, &dp, nil); err != nil { + t.Errorf("Convert_Slice_string_To_v1_DeletionPropagation(%#v): %v", tc.Input, err) + continue + } + if !apiequality.Semantic.DeepEqual(dp, tc.Output) { + t.Errorf("slice string to DeletionPropagation conversion failed: got %v; want %v", dp, tc.Output) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go index fea458dfb..2eaabf079 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go @@ -31,7 +31,10 @@ type Duration struct { // UnmarshalJSON implements the json.Unmarshaller interface. func (d *Duration) UnmarshalJSON(b []byte) error { var str string - json.Unmarshal(b, &str) + err := json.Unmarshal(b, &str) + if err != nil { + return err + } pd, err := time.ParseDuration(str) if err != nil { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go index 1fa478f5a..d987058ef 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -7804,158 +7804,157 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2435 bytes of a gzipped FileDescriptorProto + // 2422 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x59, 0x4d, 0x6c, 0x23, 0x49, 0x15, 0x4e, 0xdb, 0xb1, 0x63, 0x3f, 0xc7, 0xf9, 0xa9, 0xcd, 0x80, 0x37, 0x02, 0x3b, 0xdb, 0x8b, - 0x56, 0x59, 0x98, 0xb5, 0x49, 0x16, 0x56, 0xc3, 0x00, 0x03, 0xe9, 0x38, 0x33, 0x8a, 0x76, 0x32, - 0x63, 0x55, 0x76, 0x06, 0x31, 0x8c, 0x10, 0x9d, 0x76, 0xc5, 0x69, 0xd2, 0xee, 0xf6, 0x56, 0x95, - 0x33, 0x09, 0x1c, 0xd8, 0x03, 0x48, 0x1c, 0x10, 0x9a, 0x23, 0x27, 0xb4, 0x23, 0xb8, 0x70, 0xe5, - 0xc4, 0x05, 0x4e, 0x48, 0xcc, 0x71, 0x24, 0x2e, 0x7b, 0x40, 0xd6, 0x8e, 0xf7, 0xc0, 0x09, 0x71, - 0xcf, 0x09, 0x55, 0x75, 0xf5, 0x9f, 0x1d, 0x4f, 0xda, 0x3b, 0x0b, 0xe2, 0x14, 0xf7, 0xfb, 0xf9, - 0xde, 0xab, 0x57, 0xaf, 0x5e, 0xbd, 0x7a, 0x81, 0xbd, 0xe3, 0x6b, 0xac, 0x6e, 0x7b, 0x8d, 0xe3, - 0xfe, 0x01, 0xa1, 0x2e, 0xe1, 0x84, 0x35, 0x4e, 0x88, 0xdb, 0xf6, 0x68, 0x43, 0x31, 0xcc, 0x9e, - 0xdd, 0x35, 0xad, 0x23, 0xdb, 0x25, 0xf4, 0xac, 0xd1, 0x3b, 0xee, 0x08, 0x02, 0x6b, 0x74, 0x09, - 0x37, 0x1b, 0x27, 0x1b, 0x8d, 0x0e, 0x71, 0x09, 0x35, 0x39, 0x69, 0xd7, 0x7b, 0xd4, 0xe3, 0x1e, - 0xfa, 0x92, 0xaf, 0x55, 0x8f, 0x6b, 0xd5, 0x7b, 0xc7, 0x1d, 0x41, 0x60, 0x75, 0xa1, 0x55, 0x3f, - 0xd9, 0x58, 0x7d, 0xab, 0x63, 0xf3, 0xa3, 0xfe, 0x41, 0xdd, 0xf2, 0xba, 0x8d, 0x8e, 0xd7, 0xf1, - 0x1a, 0x52, 0xf9, 0xa0, 0x7f, 0x28, 0xbf, 0xe4, 0x87, 0xfc, 0xe5, 0x83, 0xae, 0x4e, 0x74, 0x85, - 0xf6, 0x5d, 0x6e, 0x77, 0xc9, 0xa8, 0x17, 0xab, 0xef, 0x5c, 0xa6, 0xc0, 0xac, 0x23, 0xd2, 0x35, - 0xc7, 0xf4, 0xde, 0x9e, 0xa4, 0xd7, 0xe7, 0xb6, 0xd3, 0xb0, 0x5d, 0xce, 0x38, 0x1d, 0x55, 0xd2, - 0xff, 0x96, 0x85, 0xc2, 0x56, 0x6b, 0xf7, 0x16, 0xf5, 0xfa, 0x3d, 0xb4, 0x06, 0xb3, 0xae, 0xd9, - 0x25, 0x15, 0x6d, 0x4d, 0x5b, 0x2f, 0x1a, 0xf3, 0x4f, 0x07, 0xb5, 0x99, 0xe1, 0xa0, 0x36, 0x7b, - 0xc7, 0xec, 0x12, 0x2c, 0x39, 0xc8, 0x81, 0xc2, 0x09, 0xa1, 0xcc, 0xf6, 0x5c, 0x56, 0xc9, 0xac, - 0x65, 0xd7, 0x4b, 0x9b, 0x37, 0xea, 0x69, 0x82, 0x56, 0x97, 0x06, 0xee, 0xfb, 0xaa, 0x37, 0x3d, - 0xda, 0xb4, 0x99, 0xe5, 0x9d, 0x10, 0x7a, 0x66, 0x2c, 0x29, 0x2b, 0x05, 0xc5, 0x64, 0x38, 0xb4, - 0x80, 0x7e, 0xae, 0xc1, 0x52, 0x8f, 0x92, 0x43, 0x42, 0x29, 0x69, 0x2b, 0x7e, 0x25, 0xbb, 0xa6, - 0x7d, 0x06, 0x66, 0x2b, 0xca, 0xec, 0x52, 0x6b, 0x04, 0x1f, 0x8f, 0x59, 0x44, 0xbf, 0xd3, 0x60, - 0x95, 0x11, 0x7a, 0x42, 0xe8, 0x56, 0xbb, 0x4d, 0x09, 0x63, 0xc6, 0xd9, 0xb6, 0x63, 0x13, 0x97, - 0x6f, 0xef, 0x36, 0x31, 0xab, 0xcc, 0xca, 0x38, 0x7c, 0x27, 0x9d, 0x43, 0xfb, 0x93, 0x70, 0x0c, - 0x5d, 0x79, 0xb4, 0x3a, 0x51, 0x84, 0xe1, 0x17, 0xb8, 0xa1, 0x1f, 0xc2, 0x7c, 0xb0, 0x91, 0xb7, - 0x6d, 0xc6, 0xd1, 0x7d, 0xc8, 0x77, 0xc4, 0x07, 0xab, 0x68, 0xd2, 0xc1, 0x7a, 0x3a, 0x07, 0x03, - 0x0c, 0x63, 0x41, 0xf9, 0x93, 0x97, 0x9f, 0x0c, 0x2b, 0x34, 0xfd, 0xcf, 0x59, 0x28, 0x6d, 0xb5, - 0x76, 0x31, 0x61, 0x5e, 0x9f, 0x5a, 0x24, 0x45, 0xd2, 0x6c, 0x02, 0x88, 0xbf, 0xac, 0x67, 0x5a, - 0xa4, 0x5d, 0xc9, 0xac, 0x69, 0xeb, 0x05, 0x03, 0x29, 0x39, 0xb8, 0x13, 0x72, 0x70, 0x4c, 0x4a, - 0xa0, 0x1e, 0xdb, 0x6e, 0x5b, 0xee, 0x76, 0x0c, 0xf5, 0x5d, 0xdb, 0x6d, 0x63, 0xc9, 0x41, 0xb7, - 0x21, 0x77, 0x42, 0xe8, 0x81, 0x88, 0xbf, 0x48, 0x88, 0xaf, 0xa4, 0x5b, 0xde, 0x7d, 0xa1, 0x62, - 0x14, 0x87, 0x83, 0x5a, 0x4e, 0xfe, 0xc4, 0x3e, 0x08, 0xaa, 0x03, 0xb0, 0x23, 0x8f, 0x72, 0xe9, - 0x4e, 0x25, 0xb7, 0x96, 0x5d, 0x2f, 0x1a, 0x0b, 0xc2, 0xbf, 0xfd, 0x90, 0x8a, 0x63, 0x12, 0xe8, - 0x1a, 0xcc, 0x33, 0xdb, 0xed, 0xf4, 0x1d, 0x93, 0x0a, 0x42, 0x25, 0x2f, 0xfd, 0x5c, 0x51, 0x7e, - 0xce, 0xef, 0xc7, 0x78, 0x38, 0x21, 0x29, 0x2c, 0x59, 0x26, 0x27, 0x1d, 0x8f, 0xda, 0x84, 0x55, - 0xe6, 0x22, 0x4b, 0xdb, 0x21, 0x15, 0xc7, 0x24, 0xd0, 0xeb, 0x90, 0x93, 0x91, 0xaf, 0x14, 0xa4, - 0x89, 0xb2, 0x32, 0x91, 0x93, 0xdb, 0x82, 0x7d, 0x1e, 0x7a, 0x13, 0xe6, 0xd4, 0xa9, 0xa9, 0x14, - 0xa5, 0xd8, 0xa2, 0x12, 0x9b, 0x0b, 0xd2, 0x3a, 0xe0, 0xeb, 0x7f, 0xd4, 0x60, 0x31, 0xb6, 0x7f, - 0x32, 0x57, 0xae, 0xc1, 0x7c, 0x27, 0x76, 0x52, 0xd4, 0x5e, 0x86, 0xab, 0x89, 0x9f, 0x22, 0x9c, - 0x90, 0x44, 0x04, 0x8a, 0x54, 0x21, 0x05, 0x15, 0x61, 0x23, 0x75, 0xa2, 0x05, 0x3e, 0x44, 0x96, - 0x62, 0x44, 0x86, 0x23, 0x64, 0xfd, 0x9f, 0x9a, 0x4c, 0xba, 0xa0, 0x46, 0xa0, 0xf5, 0x58, 0x1d, - 0xd2, 0x64, 0x08, 0xe7, 0x27, 0xd4, 0x90, 0x4b, 0x0e, 0x6f, 0xe6, 0xff, 0xe2, 0xf0, 0x5e, 0x2f, - 0xfc, 0xe6, 0xc3, 0xda, 0xcc, 0x07, 0xff, 0x58, 0x9b, 0xd1, 0x3f, 0xc9, 0x40, 0xb9, 0x49, 0x1c, - 0xc2, 0xc9, 0xdd, 0x1e, 0x97, 0x2b, 0xb8, 0x09, 0xa8, 0x43, 0x4d, 0x8b, 0xb4, 0x08, 0xb5, 0xbd, - 0xf6, 0x3e, 0xb1, 0x3c, 0xb7, 0xcd, 0xe4, 0x16, 0x65, 0x8d, 0xcf, 0x0d, 0x07, 0x35, 0x74, 0x6b, - 0x8c, 0x8b, 0x2f, 0xd0, 0x40, 0x0e, 0x94, 0x7b, 0x54, 0xfe, 0xb6, 0xb9, 0x2a, 0xe0, 0xe2, 0xe0, - 0xbc, 0x9d, 0x6e, 0xed, 0xad, 0xb8, 0xaa, 0xb1, 0x3c, 0x1c, 0xd4, 0xca, 0x09, 0x12, 0x4e, 0x82, - 0xa3, 0xef, 0xc2, 0x92, 0x47, 0x7b, 0x47, 0xa6, 0xdb, 0x24, 0x3d, 0xe2, 0xb6, 0x89, 0xcb, 0x99, - 0x3c, 0xcc, 0x05, 0x63, 0x45, 0x94, 0xdd, 0xbb, 0x23, 0x3c, 0x3c, 0x26, 0x8d, 0x1e, 0xc0, 0x72, - 0x8f, 0x7a, 0x3d, 0xb3, 0x63, 0x0a, 0xc4, 0x96, 0xe7, 0xd8, 0xd6, 0x99, 0x3c, 0xec, 0x45, 0xe3, - 0xea, 0x70, 0x50, 0x5b, 0x6e, 0x8d, 0x32, 0xcf, 0x07, 0xb5, 0x57, 0x64, 0xe8, 0x04, 0x25, 0x62, - 0xe2, 0x71, 0x18, 0x7d, 0x17, 0x0a, 0xcd, 0x3e, 0x95, 0x14, 0xf4, 0x6d, 0x28, 0xb4, 0xd5, 0x6f, - 0x15, 0xd5, 0xd7, 0x82, 0x3b, 0x29, 0x90, 0x39, 0x1f, 0xd4, 0xca, 0xe2, 0xea, 0xad, 0x07, 0x04, - 0x1c, 0xaa, 0xe8, 0x0f, 0xa1, 0xbc, 0x73, 0xda, 0xf3, 0x28, 0x0f, 0xf6, 0xeb, 0x0d, 0xc8, 0x13, - 0x49, 0x90, 0x68, 0x85, 0xa8, 0x90, 0xfa, 0x62, 0x58, 0x71, 0xc5, 0xc1, 0x26, 0xa7, 0xa6, 0xc5, - 0x55, 0x45, 0x0c, 0x0f, 0xf6, 0x8e, 0x20, 0x62, 0x9f, 0xa7, 0x3f, 0xd1, 0x00, 0x6e, 0x91, 0x10, - 0x7b, 0x0b, 0x16, 0x83, 0x43, 0x91, 0x3c, 0xab, 0x9f, 0x57, 0xda, 0x8b, 0x38, 0xc9, 0xc6, 0xa3, - 0xf2, 0xa8, 0x05, 0x2b, 0xb6, 0x6b, 0x39, 0xfd, 0x36, 0xb9, 0xe7, 0xda, 0xae, 0xcd, 0x6d, 0xd3, - 0xb1, 0x7f, 0x12, 0xd6, 0xe5, 0x2f, 0x28, 0x9c, 0x95, 0xdd, 0x0b, 0x64, 0xf0, 0x85, 0x9a, 0xfa, - 0x43, 0x28, 0xca, 0x0a, 0x21, 0x8a, 0x73, 0x54, 0xae, 0xb4, 0x17, 0x94, 0xab, 0xa0, 0xba, 0x67, - 0x26, 0x55, 0xf7, 0xd8, 0x81, 0x70, 0xa0, 0xec, 0xeb, 0x06, 0x17, 0x4e, 0x2a, 0x0b, 0x57, 0xa1, - 0x10, 0x2c, 0x5c, 0x59, 0x09, 0x1b, 0x8d, 0x00, 0x08, 0x87, 0x12, 0x31, 0x6b, 0x47, 0x90, 0xa8, - 0x76, 0xe9, 0x8c, 0xc5, 0xaa, 0x6f, 0xe6, 0xc5, 0xd5, 0x37, 0x66, 0xe9, 0x67, 0x50, 0x99, 0xd4, - 0x9d, 0xbc, 0x44, 0x3d, 0x4e, 0xef, 0x8a, 0xfe, 0x6b, 0x0d, 0x96, 0xe2, 0x48, 0xe9, 0xb7, 0x2f, - 0xbd, 0x91, 0xcb, 0xef, 0xf1, 0x58, 0x44, 0x7e, 0xab, 0xc1, 0x4a, 0x62, 0x69, 0x53, 0xed, 0xf8, - 0x14, 0x4e, 0xc5, 0x93, 0x23, 0x3b, 0x45, 0x72, 0x34, 0xa0, 0xb4, 0x1b, 0xe6, 0x3d, 0xbd, 0xbc, - 0xf3, 0xd1, 0xff, 0xa2, 0xc1, 0x7c, 0x4c, 0x83, 0xa1, 0x87, 0x30, 0x27, 0xea, 0x9b, 0xed, 0x76, - 0x54, 0x57, 0x96, 0xf2, 0xb2, 0x8c, 0x81, 0x44, 0xeb, 0x6a, 0xf9, 0x48, 0x38, 0x80, 0x44, 0x2d, - 0xc8, 0x53, 0xc2, 0xfa, 0x0e, 0x57, 0xa5, 0xfd, 0x6a, 0xca, 0x6b, 0x8d, 0x9b, 0xbc, 0xcf, 0x0c, - 0x10, 0x35, 0x0a, 0x4b, 0x7d, 0xac, 0x70, 0xf4, 0xbf, 0x67, 0xa0, 0x7c, 0xdb, 0x3c, 0x20, 0xce, - 0x3e, 0x71, 0x88, 0xc5, 0x3d, 0x8a, 0x7e, 0x0a, 0xa5, 0xae, 0xc9, 0xad, 0x23, 0x49, 0x0d, 0x7a, - 0xcb, 0x66, 0x3a, 0x43, 0x09, 0xa4, 0xfa, 0x5e, 0x04, 0xb3, 0xe3, 0x72, 0x7a, 0x66, 0xbc, 0xa2, - 0x16, 0x56, 0x8a, 0x71, 0x70, 0xdc, 0x9a, 0x7c, 0x10, 0xc8, 0xef, 0x9d, 0xd3, 0x9e, 0xb8, 0x44, - 0xa7, 0x7f, 0x87, 0x24, 0x5c, 0xc0, 0xe4, 0xfd, 0xbe, 0x4d, 0x49, 0x97, 0xb8, 0x3c, 0x7a, 0x10, - 0xec, 0x8d, 0xe0, 0xe3, 0x31, 0x8b, 0xab, 0x37, 0x60, 0x69, 0xd4, 0x79, 0xb4, 0x04, 0xd9, 0x63, - 0x72, 0xe6, 0xe7, 0x02, 0x16, 0x3f, 0xd1, 0x0a, 0xe4, 0x4e, 0x4c, 0xa7, 0xaf, 0xea, 0x0f, 0xf6, - 0x3f, 0xae, 0x67, 0xae, 0x69, 0xfa, 0xef, 0x35, 0xa8, 0x4c, 0x72, 0x04, 0x7d, 0x31, 0x06, 0x64, - 0x94, 0x94, 0x57, 0xd9, 0x77, 0xc9, 0x99, 0x8f, 0xba, 0x03, 0x05, 0xaf, 0x27, 0x9e, 0x70, 0x1e, - 0x55, 0x79, 0xfe, 0x66, 0x90, 0xbb, 0x77, 0x15, 0xfd, 0x7c, 0x50, 0xbb, 0x92, 0x80, 0x0f, 0x18, - 0x38, 0x54, 0x45, 0x3a, 0xe4, 0xa5, 0x3f, 0xe2, 0x52, 0x16, 0xed, 0x93, 0xdc, 0xfc, 0xfb, 0x92, - 0x82, 0x15, 0x47, 0xff, 0x93, 0x06, 0xb3, 0xb2, 0x3d, 0x7c, 0x08, 0x05, 0x11, 0xbf, 0xb6, 0xc9, - 0x4d, 0xe9, 0x57, 0xea, 0xc7, 0x84, 0xd0, 0xde, 0x23, 0xdc, 0x8c, 0xce, 0x57, 0x40, 0xc1, 0x21, - 0x22, 0xc2, 0x90, 0xb3, 0x39, 0xe9, 0x06, 0x1b, 0xf9, 0xd6, 0x44, 0x68, 0xf5, 0xfe, 0xad, 0x63, - 0xf3, 0xd1, 0xce, 0x29, 0x27, 0xae, 0xd8, 0x8c, 0xa8, 0x18, 0xec, 0x0a, 0x0c, 0xec, 0x43, 0xe9, - 0x7f, 0xd0, 0x20, 0x34, 0x25, 0x8e, 0x3b, 0x23, 0xce, 0xe1, 0x6d, 0xdb, 0x3d, 0x56, 0x61, 0x0d, - 0xdd, 0xd9, 0x57, 0x74, 0x1c, 0x4a, 0x5c, 0x74, 0xc5, 0x66, 0xa6, 0xbc, 0x62, 0xaf, 0x42, 0xc1, - 0xf2, 0x5c, 0x6e, 0xbb, 0xfd, 0xb1, 0xfa, 0xb2, 0xad, 0xe8, 0x38, 0x94, 0xd0, 0x9f, 0x65, 0xa1, - 0x24, 0x7c, 0x0d, 0xee, 0xf8, 0x6f, 0x42, 0xd9, 0x89, 0xef, 0x9e, 0xf2, 0xf9, 0x8a, 0x82, 0x48, - 0x9e, 0x47, 0x9c, 0x94, 0x15, 0xca, 0x87, 0x36, 0x71, 0xda, 0xa1, 0x72, 0x26, 0xa9, 0x7c, 0x33, - 0xce, 0xc4, 0x49, 0x59, 0x51, 0x67, 0x1f, 0x89, 0xbc, 0x56, 0x8d, 0x5a, 0x18, 0xda, 0xef, 0x09, - 0x22, 0xf6, 0x79, 0x17, 0xc5, 0x67, 0x76, 0xca, 0xf8, 0x5c, 0x87, 0x05, 0xb1, 0x91, 0x5e, 0x9f, - 0x07, 0xdd, 0x6c, 0x4e, 0xf6, 0x5d, 0x68, 0x38, 0xa8, 0x2d, 0xbc, 0x97, 0xe0, 0xe0, 0x11, 0xc9, - 0x89, 0xed, 0x4b, 0xfe, 0xd3, 0xb6, 0x2f, 0x62, 0xd5, 0x8e, 0xdd, 0xb5, 0x79, 0x65, 0x4e, 0x3a, - 0x11, 0xae, 0xfa, 0xb6, 0x20, 0x62, 0x9f, 0x97, 0xd8, 0xd2, 0xc2, 0xa5, 0x5b, 0xfa, 0x3e, 0x14, - 0xf7, 0x6c, 0x8b, 0x7a, 0x62, 0x2d, 0xe2, 0x62, 0x62, 0x89, 0xa6, 0x3d, 0x2c, 0xe0, 0xc1, 0x1a, - 0x03, 0xbe, 0x70, 0xc5, 0x35, 0x5d, 0xcf, 0x6f, 0xcd, 0x73, 0x91, 0x2b, 0x77, 0x04, 0x11, 0xfb, - 0xbc, 0xeb, 0x2b, 0xe2, 0x3e, 0xfa, 0xe5, 0x93, 0xda, 0xcc, 0xe3, 0x27, 0xb5, 0x99, 0x0f, 0x9f, - 0xa8, 0xbb, 0xe9, 0x5f, 0x00, 0x70, 0xf7, 0xe0, 0xc7, 0xc4, 0xf2, 0x73, 0xfe, 0xf2, 0x57, 0xb9, - 0xe8, 0x31, 0xd4, 0x30, 0x48, 0xbe, 0x60, 0x33, 0x23, 0x3d, 0x46, 0x8c, 0x87, 0x13, 0x92, 0xa8, - 0x01, 0xc5, 0xf0, 0xa5, 0xae, 0xf2, 0x7b, 0x59, 0xa9, 0x15, 0xc3, 0xe7, 0x3c, 0x8e, 0x64, 0x12, - 0x07, 0x70, 0xf6, 0xd2, 0x03, 0x68, 0x40, 0xb6, 0x6f, 0xb7, 0x65, 0x4a, 0x14, 0x8d, 0xaf, 0x06, - 0x05, 0xf0, 0xde, 0x6e, 0xf3, 0x7c, 0x50, 0x7b, 0x6d, 0xd2, 0x8c, 0x8b, 0x9f, 0xf5, 0x08, 0xab, - 0xdf, 0xdb, 0x6d, 0x62, 0xa1, 0x7c, 0x51, 0x92, 0xe6, 0xa7, 0x4c, 0xd2, 0x4d, 0x00, 0xb5, 0x6a, - 0xa1, 0xed, 0xe7, 0x46, 0x38, 0xb5, 0xb8, 0x15, 0x72, 0x70, 0x4c, 0x0a, 0x31, 0x58, 0xb6, 0x28, - 0x91, 0xbf, 0xc5, 0xd6, 0x33, 0x6e, 0x76, 0xfd, 0x77, 0x7b, 0x69, 0xf3, 0xcb, 0xe9, 0x2a, 0xa6, - 0x50, 0x33, 0x5e, 0x55, 0x66, 0x96, 0xb7, 0x47, 0xc1, 0xf0, 0x38, 0x3e, 0xf2, 0x60, 0xb9, 0xad, - 0x5e, 0x3d, 0x91, 0xd1, 0xe2, 0xd4, 0x46, 0xaf, 0x08, 0x83, 0xcd, 0x51, 0x20, 0x3c, 0x8e, 0x8d, - 0x7e, 0x08, 0xab, 0x01, 0x71, 0xfc, 0xe9, 0x59, 0x01, 0x19, 0xa9, 0xaa, 0x78, 0x0c, 0x37, 0x27, - 0x4a, 0xe1, 0x17, 0x20, 0xa0, 0x36, 0xe4, 0x1d, 0xbf, 0xbb, 0x28, 0xc9, 0x1b, 0xe1, 0x5b, 0xe9, - 0x56, 0x11, 0x65, 0x7f, 0x3d, 0xde, 0x55, 0x84, 0xcf, 0x2f, 0xd5, 0x50, 0x28, 0x6c, 0x74, 0x0a, - 0x25, 0xd3, 0x75, 0x3d, 0x6e, 0xfa, 0x8f, 0xe1, 0x79, 0x69, 0x6a, 0x6b, 0x6a, 0x53, 0x5b, 0x11, - 0xc6, 0x48, 0x17, 0x13, 0xe3, 0xe0, 0xb8, 0x29, 0xf4, 0x08, 0x16, 0xbd, 0x47, 0x2e, 0xa1, 0x98, - 0x1c, 0x12, 0x4a, 0x5c, 0x8b, 0xb0, 0x4a, 0x59, 0x5a, 0xff, 0x5a, 0x4a, 0xeb, 0x09, 0xe5, 0x28, - 0xa5, 0x93, 0x74, 0x86, 0x47, 0xad, 0xa0, 0x3a, 0xc0, 0xa1, 0xed, 0xaa, 0x5e, 0xb4, 0xb2, 0x10, - 0x8d, 0x9e, 0x6e, 0x86, 0x54, 0x1c, 0x93, 0x40, 0x5f, 0x87, 0x92, 0xe5, 0xf4, 0x19, 0x27, 0xfe, - 0x8c, 0x6b, 0x51, 0x9e, 0xa0, 0x70, 0x7d, 0xdb, 0x11, 0x0b, 0xc7, 0xe5, 0xd0, 0x11, 0xcc, 0xdb, - 0xb1, 0xa6, 0xb7, 0xb2, 0x24, 0x73, 0x71, 0x73, 0xea, 0x4e, 0x97, 0x19, 0x4b, 0xa2, 0x12, 0xc5, - 0x29, 0x38, 0x81, 0xbc, 0xfa, 0x0d, 0x28, 0x7d, 0xca, 0x1e, 0x4c, 0xf4, 0x70, 0xa3, 0x5b, 0x37, - 0x55, 0x0f, 0xf7, 0xd7, 0x0c, 0x2c, 0x24, 0x03, 0x1e, 0xbe, 0x75, 0xb4, 0x89, 0x33, 0xcb, 0xa0, - 0x2a, 0x67, 0x27, 0x56, 0x65, 0x55, 0xfc, 0x66, 0x5f, 0xa6, 0xf8, 0x6d, 0x02, 0x98, 0x3d, 0x3b, - 0xa8, 0x7b, 0x7e, 0x1d, 0x0d, 0x2b, 0x57, 0x34, 0x45, 0xc3, 0x31, 0x29, 0x39, 0x95, 0xf4, 0x5c, - 0x4e, 0x3d, 0xc7, 0x21, 0x54, 0x5d, 0xa6, 0xfe, 0x54, 0x32, 0xa4, 0xe2, 0x98, 0x04, 0xba, 0x09, - 0xe8, 0xc0, 0xf1, 0xac, 0x63, 0x19, 0x82, 0xe0, 0x9c, 0xcb, 0x2a, 0x59, 0xf0, 0x87, 0x52, 0xc6, - 0x18, 0x17, 0x5f, 0xa0, 0xa1, 0xcf, 0x41, 0xae, 0x25, 0xda, 0x0a, 0xfd, 0x2e, 0x24, 0xe7, 0x49, - 0xe8, 0x86, 0x1f, 0x09, 0x2d, 0x1c, 0xf8, 0x4c, 0x17, 0x05, 0xfd, 0x2a, 0x14, 0xb1, 0xe7, 0xf1, - 0x96, 0xc9, 0x8f, 0x18, 0xaa, 0x41, 0xae, 0x27, 0x7e, 0xa8, 0x61, 0xa1, 0x9c, 0xff, 0x4a, 0x0e, - 0xf6, 0xe9, 0xfa, 0xaf, 0x34, 0x78, 0x75, 0xe2, 0xec, 0x4e, 0x44, 0xd4, 0x0a, 0xbf, 0x94, 0x4b, - 0x61, 0x44, 0x23, 0x39, 0x1c, 0x93, 0x12, 0x9d, 0x58, 0x62, 0xe0, 0x37, 0xda, 0x89, 0x25, 0xac, - 0xe1, 0xa4, 0xac, 0xfe, 0xef, 0x0c, 0xe4, 0xfd, 0x67, 0xd9, 0x7f, 0xb9, 0xf9, 0x7e, 0x03, 0xf2, - 0x4c, 0xda, 0x51, 0xee, 0x85, 0xd5, 0xd2, 0xb7, 0x8e, 0x15, 0x57, 0x34, 0x31, 0x5d, 0xc2, 0x98, - 0xd9, 0x09, 0x92, 0x37, 0x6c, 0x62, 0xf6, 0x7c, 0x32, 0x0e, 0xf8, 0xe8, 0x1d, 0xf1, 0x0a, 0x35, - 0x59, 0xd8, 0x17, 0x56, 0x03, 0x48, 0x2c, 0xa9, 0xe7, 0x83, 0xda, 0xbc, 0x02, 0x97, 0xdf, 0x58, - 0x49, 0xa3, 0x07, 0x30, 0xd7, 0x26, 0xdc, 0xb4, 0x1d, 0xbf, 0x1d, 0x4c, 0x3d, 0x99, 0xf4, 0xc1, - 0x9a, 0xbe, 0xaa, 0x51, 0x12, 0x3e, 0xa9, 0x0f, 0x1c, 0x00, 0x8a, 0x83, 0x67, 0x79, 0x6d, 0x7f, - 0x4c, 0x9f, 0x8b, 0x0e, 0xde, 0xb6, 0xd7, 0x26, 0x58, 0x72, 0xf4, 0xc7, 0x1a, 0x94, 0x7c, 0xa4, - 0x6d, 0xb3, 0xcf, 0x08, 0xda, 0x08, 0x57, 0xe1, 0x6f, 0x77, 0x70, 0x27, 0xcf, 0xbe, 0x77, 0xd6, - 0x23, 0xe7, 0x83, 0x5a, 0x51, 0x8a, 0x89, 0x8f, 0x70, 0x01, 0xb1, 0x18, 0x65, 0x2e, 0x89, 0xd1, - 0xeb, 0x90, 0x93, 0xad, 0xb7, 0x0a, 0x66, 0xd8, 0xe8, 0xc9, 0xf6, 0x1c, 0xfb, 0x3c, 0xfd, 0xe3, - 0x0c, 0x94, 0x13, 0x8b, 0x4b, 0xd1, 0xd5, 0x85, 0xa3, 0x92, 0x4c, 0x8a, 0xf1, 0xdb, 0xe4, 0x7f, - 0xae, 0x7c, 0x1f, 0xf2, 0x96, 0x58, 0x5f, 0xf0, 0xdf, 0xad, 0x8d, 0x69, 0xb6, 0x42, 0x46, 0x26, - 0xca, 0x24, 0xf9, 0xc9, 0xb0, 0x02, 0x44, 0xb7, 0x60, 0x99, 0x12, 0x4e, 0xcf, 0xb6, 0x0e, 0x39, - 0xa1, 0xf1, 0xfe, 0x3f, 0x17, 0xf5, 0x3d, 0x78, 0x54, 0x00, 0x8f, 0xeb, 0x04, 0xa5, 0x32, 0xff, - 0x12, 0xa5, 0x52, 0x77, 0x60, 0xf6, 0x7f, 0xd8, 0xa3, 0xff, 0x00, 0x8a, 0x51, 0x17, 0xf5, 0x19, - 0x9b, 0xd4, 0x7f, 0x04, 0x05, 0x91, 0x8d, 0x41, 0xf7, 0x7f, 0xc9, 0x4d, 0x94, 0xbc, 0x23, 0x32, - 0x69, 0xee, 0x08, 0x7d, 0x13, 0xfc, 0xff, 0x99, 0x89, 0x6a, 0xea, 0xbf, 0xd8, 0x63, 0xd5, 0x34, - 0xfe, 0xfc, 0x8e, 0x8d, 0xcc, 0x7e, 0xa1, 0x01, 0xc8, 0xe7, 0xe3, 0xce, 0x09, 0x71, 0xb9, 0x70, - 0x4c, 0xec, 0xc0, 0xa8, 0x63, 0xf2, 0x18, 0x49, 0x0e, 0xba, 0x07, 0x79, 0x4f, 0x76, 0x57, 0x6a, - 0x86, 0x35, 0xe5, 0x38, 0x20, 0xcc, 0x3a, 0xbf, 0x45, 0xc3, 0x0a, 0xcc, 0x58, 0x7f, 0xfa, 0xbc, - 0x3a, 0xf3, 0xec, 0x79, 0x75, 0xe6, 0xa3, 0xe7, 0xd5, 0x99, 0x0f, 0x86, 0x55, 0xed, 0xe9, 0xb0, - 0xaa, 0x3d, 0x1b, 0x56, 0xb5, 0x8f, 0x86, 0x55, 0xed, 0xe3, 0x61, 0x55, 0x7b, 0xfc, 0x49, 0x75, - 0xe6, 0x41, 0xe6, 0x64, 0xe3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6c, 0xc5, 0x28, 0xb2, 0x54, - 0x20, 0x00, 0x00, + 0x56, 0x59, 0x98, 0xb5, 0x49, 0x80, 0xd5, 0x30, 0xc0, 0x40, 0x3a, 0xce, 0x8c, 0xa2, 0x9d, 0xcc, + 0x58, 0x95, 0x9d, 0x41, 0x0c, 0x23, 0x44, 0xa7, 0x5d, 0x71, 0x9a, 0xb4, 0xbb, 0xbd, 0x55, 0xed, + 0x4c, 0x02, 0x07, 0xf6, 0x00, 0x12, 0x07, 0x84, 0xe6, 0xc8, 0x09, 0xed, 0x08, 0x2e, 0x5c, 0x39, + 0x71, 0x81, 0x13, 0x12, 0x73, 0x1c, 0x89, 0xcb, 0x1e, 0x90, 0xb5, 0xe3, 0x3d, 0x70, 0x42, 0xdc, + 0x73, 0x42, 0x55, 0x5d, 0xdd, 0x5d, 0x6d, 0xc7, 0x93, 0xf6, 0xce, 0x82, 0xf6, 0x14, 0xf7, 0xfb, + 0xf9, 0xde, 0xab, 0xaa, 0xf7, 0x5e, 0xbd, 0x7a, 0x81, 0xbd, 0xe3, 0x6b, 0xac, 0x6e, 0x7b, 0x8d, + 0xe3, 0xfe, 0x01, 0xa1, 0x2e, 0xf1, 0x09, 0x6b, 0x9c, 0x10, 0xb7, 0xed, 0xd1, 0x86, 0x64, 0x98, + 0x3d, 0xbb, 0x6b, 0x5a, 0x47, 0xb6, 0x4b, 0xe8, 0x59, 0xa3, 0x77, 0xdc, 0xe1, 0x04, 0xd6, 0xe8, + 0x12, 0xdf, 0x6c, 0x9c, 0x6c, 0x34, 0x3a, 0xc4, 0x25, 0xd4, 0xf4, 0x49, 0xbb, 0xde, 0xa3, 0x9e, + 0xef, 0xa1, 0x2f, 0x05, 0x5a, 0x75, 0x55, 0xab, 0xde, 0x3b, 0xee, 0x70, 0x02, 0xab, 0x73, 0xad, + 0xfa, 0xc9, 0xc6, 0xea, 0x5b, 0x1d, 0xdb, 0x3f, 0xea, 0x1f, 0xd4, 0x2d, 0xaf, 0xdb, 0xe8, 0x78, + 0x1d, 0xaf, 0x21, 0x94, 0x0f, 0xfa, 0x87, 0xe2, 0x4b, 0x7c, 0x88, 0x5f, 0x01, 0xe8, 0xea, 0x44, + 0x57, 0x68, 0xdf, 0xf5, 0xed, 0x2e, 0x19, 0xf5, 0x62, 0xf5, 0xed, 0xcb, 0x14, 0x98, 0x75, 0x44, + 0xba, 0xe6, 0xa8, 0x9e, 0xfe, 0xf7, 0x2c, 0x14, 0xb6, 0x5a, 0xbb, 0xb7, 0xa8, 0xd7, 0xef, 0xa1, + 0x35, 0x98, 0x75, 0xcd, 0x2e, 0xa9, 0x68, 0x6b, 0xda, 0x7a, 0xd1, 0x98, 0x7f, 0x3a, 0xa8, 0xcd, + 0x0c, 0x07, 0xb5, 0xd9, 0x3b, 0x66, 0x97, 0x60, 0xc1, 0x41, 0x0e, 0x14, 0x4e, 0x08, 0x65, 0xb6, + 0xe7, 0xb2, 0x4a, 0x66, 0x2d, 0xbb, 0x5e, 0xda, 0xbc, 0x51, 0x4f, 0xb3, 0xfe, 0xba, 0x30, 0x70, + 0x3f, 0x50, 0xbd, 0xe9, 0xd1, 0xa6, 0xcd, 0x2c, 0xef, 0x84, 0xd0, 0x33, 0x63, 0x49, 0x5a, 0x29, + 0x48, 0x26, 0xc3, 0x91, 0x05, 0xf4, 0x0b, 0x0d, 0x96, 0x7a, 0x94, 0x1c, 0x12, 0x4a, 0x49, 0x5b, + 0xf2, 0x2b, 0xd9, 0x35, 0xed, 0x53, 0x30, 0x5b, 0x91, 0x66, 0x97, 0x5a, 0x23, 0xf8, 0x78, 0xcc, + 0x22, 0xfa, 0xbd, 0x06, 0xab, 0x8c, 0xd0, 0x13, 0x42, 0xb7, 0xda, 0x6d, 0x4a, 0x18, 0x33, 0xce, + 0xb6, 0x1d, 0x9b, 0xb8, 0xfe, 0xf6, 0x6e, 0x13, 0xb3, 0xca, 0xac, 0xd8, 0x87, 0xef, 0xa6, 0x73, + 0x68, 0x7f, 0x12, 0x8e, 0xa1, 0x4b, 0x8f, 0x56, 0x27, 0x8a, 0x30, 0xfc, 0x02, 0x37, 0xf4, 0x43, + 0x98, 0x0f, 0x0f, 0xf2, 0xb6, 0xcd, 0x7c, 0x74, 0x1f, 0xf2, 0x1d, 0xfe, 0xc1, 0x2a, 0x9a, 0x70, + 0xb0, 0x9e, 0xce, 0xc1, 0x10, 0xc3, 0x58, 0x90, 0xfe, 0xe4, 0xc5, 0x27, 0xc3, 0x12, 0x4d, 0xff, + 0x4b, 0x16, 0x4a, 0x5b, 0xad, 0x5d, 0x4c, 0x98, 0xd7, 0xa7, 0x16, 0x49, 0x11, 0x34, 0x9b, 0x00, + 0xfc, 0x2f, 0xeb, 0x99, 0x16, 0x69, 0x57, 0x32, 0x6b, 0xda, 0x7a, 0xc1, 0x40, 0x52, 0x0e, 0xee, + 0x44, 0x1c, 0xac, 0x48, 0x71, 0xd4, 0x63, 0xdb, 0x6d, 0x8b, 0xd3, 0x56, 0x50, 0xdf, 0xb1, 0xdd, + 0x36, 0x16, 0x1c, 0x74, 0x1b, 0x72, 0x27, 0x84, 0x1e, 0xf0, 0xfd, 0xe7, 0x01, 0xf1, 0x95, 0x74, + 0xcb, 0xbb, 0xcf, 0x55, 0x8c, 0xe2, 0x70, 0x50, 0xcb, 0x89, 0x9f, 0x38, 0x00, 0x41, 0x75, 0x00, + 0x76, 0xe4, 0x51, 0x5f, 0xb8, 0x53, 0xc9, 0xad, 0x65, 0xd7, 0x8b, 0xc6, 0x02, 0xf7, 0x6f, 0x3f, + 0xa2, 0x62, 0x45, 0x02, 0x5d, 0x83, 0x79, 0x66, 0xbb, 0x9d, 0xbe, 0x63, 0x52, 0x4e, 0xa8, 0xe4, + 0x85, 0x9f, 0x2b, 0xd2, 0xcf, 0xf9, 0x7d, 0x85, 0x87, 0x13, 0x92, 0xdc, 0x92, 0x65, 0xfa, 0xa4, + 0xe3, 0x51, 0x9b, 0xb0, 0xca, 0x5c, 0x6c, 0x69, 0x3b, 0xa2, 0x62, 0x45, 0x02, 0xbd, 0x0e, 0x39, + 0xb1, 0xf3, 0x95, 0x82, 0x30, 0x51, 0x96, 0x26, 0x72, 0xe2, 0x58, 0x70, 0xc0, 0x43, 0x6f, 0xc2, + 0x9c, 0xcc, 0x9a, 0x4a, 0x51, 0x88, 0x2d, 0x4a, 0xb1, 0xb9, 0x30, 0xac, 0x43, 0xbe, 0xfe, 0x27, + 0x0d, 0x16, 0x95, 0xf3, 0x13, 0xb1, 0x72, 0x0d, 0xe6, 0x3b, 0x4a, 0xa6, 0xc8, 0xb3, 0x8c, 0x56, + 0xa3, 0x66, 0x11, 0x4e, 0x48, 0x22, 0x02, 0x45, 0x2a, 0x91, 0xc2, 0x8a, 0xb0, 0x91, 0x3a, 0xd0, + 0x42, 0x1f, 0x62, 0x4b, 0x0a, 0x91, 0xe1, 0x18, 0x59, 0xff, 0x97, 0x26, 0x82, 0x2e, 0xac, 0x11, + 0x68, 0x5d, 0xa9, 0x43, 0x9a, 0xd8, 0xc2, 0xf9, 0x09, 0x35, 0xe4, 0x92, 0xe4, 0xcd, 0x7c, 0x26, + 0x92, 0xf7, 0x7a, 0xe1, 0xb7, 0x1f, 0xd4, 0x66, 0xde, 0xff, 0xe7, 0xda, 0x8c, 0xfe, 0x71, 0x06, + 0xca, 0x4d, 0xe2, 0x10, 0x9f, 0xdc, 0xed, 0xf9, 0x62, 0x05, 0x37, 0x01, 0x75, 0xa8, 0x69, 0x91, + 0x16, 0xa1, 0xb6, 0xd7, 0xde, 0x27, 0x96, 0xe7, 0xb6, 0x99, 0x38, 0xa2, 0xac, 0xf1, 0xb9, 0xe1, + 0xa0, 0x86, 0x6e, 0x8d, 0x71, 0xf1, 0x05, 0x1a, 0xc8, 0x81, 0x72, 0x8f, 0x8a, 0xdf, 0xb6, 0x2f, + 0x0b, 0x38, 0x4f, 0x9c, 0xaf, 0xa5, 0x5b, 0x7b, 0x4b, 0x55, 0x35, 0x96, 0x87, 0x83, 0x5a, 0x39, + 0x41, 0xc2, 0x49, 0x70, 0xf4, 0x3d, 0x58, 0xf2, 0x68, 0xef, 0xc8, 0x74, 0x9b, 0xa4, 0x47, 0xdc, + 0x36, 0x71, 0x7d, 0x26, 0x92, 0xb9, 0x60, 0xac, 0xf0, 0xb2, 0x7b, 0x77, 0x84, 0x87, 0xc7, 0xa4, + 0xd1, 0x03, 0x58, 0xee, 0x51, 0xaf, 0x67, 0x76, 0x4c, 0x8e, 0xd8, 0xf2, 0x1c, 0xdb, 0x3a, 0x13, + 0xc9, 0x5e, 0x34, 0xae, 0x0e, 0x07, 0xb5, 0xe5, 0xd6, 0x28, 0xf3, 0x7c, 0x50, 0x7b, 0x45, 0x6c, + 0x1d, 0xa7, 0xc4, 0x4c, 0x3c, 0x0e, 0xa3, 0xef, 0x42, 0xa1, 0xd9, 0xa7, 0x82, 0x82, 0xbe, 0x03, + 0x85, 0xb6, 0xfc, 0x2d, 0x77, 0xf5, 0xb5, 0xf0, 0x4e, 0x0a, 0x65, 0xce, 0x07, 0xb5, 0x32, 0xbf, + 0x45, 0xeb, 0x21, 0x01, 0x47, 0x2a, 0xfa, 0x43, 0x28, 0xef, 0x9c, 0xf6, 0x3c, 0xea, 0x87, 0xe7, + 0xf5, 0x06, 0xe4, 0x89, 0x20, 0x08, 0xb4, 0x42, 0x5c, 0x48, 0x03, 0x31, 0x2c, 0xb9, 0x3c, 0xb1, + 0xc9, 0xa9, 0x69, 0xf9, 0xb2, 0x22, 0x46, 0x89, 0xbd, 0xc3, 0x89, 0x38, 0xe0, 0xe9, 0x4f, 0x34, + 0x80, 0x5b, 0x24, 0xc2, 0xde, 0x82, 0xc5, 0x30, 0x29, 0x92, 0xb9, 0xfa, 0x79, 0xa9, 0xbd, 0x88, + 0x93, 0x6c, 0x3c, 0x2a, 0x8f, 0x5a, 0xb0, 0x62, 0xbb, 0x96, 0xd3, 0x6f, 0x93, 0x7b, 0xae, 0xed, + 0xda, 0xbe, 0x6d, 0x3a, 0xf6, 0x4f, 0xa3, 0xba, 0xfc, 0x05, 0x89, 0xb3, 0xb2, 0x7b, 0x81, 0x0c, + 0xbe, 0x50, 0x53, 0x7f, 0x08, 0x45, 0x51, 0x21, 0x78, 0x71, 0x8e, 0xcb, 0x95, 0xf6, 0x82, 0x72, + 0x15, 0x56, 0xf7, 0xcc, 0xa4, 0xea, 0xae, 0x24, 0x84, 0x03, 0xe5, 0x40, 0x37, 0xbc, 0x70, 0x52, + 0x59, 0xb8, 0x0a, 0x85, 0x70, 0xe1, 0xd2, 0x4a, 0xd4, 0x68, 0x84, 0x40, 0x38, 0x92, 0x50, 0xac, + 0x1d, 0x41, 0xa2, 0xda, 0xa5, 0x33, 0xa6, 0x54, 0xdf, 0xcc, 0x8b, 0xab, 0xaf, 0x62, 0xe9, 0xe7, + 0x50, 0x99, 0xd4, 0x9d, 0xbc, 0x44, 0x3d, 0x4e, 0xef, 0x8a, 0xfe, 0x1b, 0x0d, 0x96, 0x54, 0xa4, + 0xf4, 0xc7, 0x97, 0xde, 0xc8, 0xe5, 0xf7, 0xb8, 0xb2, 0x23, 0xbf, 0xd3, 0x60, 0x25, 0xb1, 0xb4, + 0xa9, 0x4e, 0x7c, 0x0a, 0xa7, 0xd4, 0xe0, 0xc8, 0x4e, 0x11, 0x1c, 0x0d, 0x28, 0xed, 0x46, 0x71, + 0x4f, 0x2f, 0xef, 0x7c, 0xf4, 0xbf, 0x6a, 0x30, 0xaf, 0x68, 0x30, 0xf4, 0x10, 0xe6, 0x78, 0x7d, + 0xb3, 0xdd, 0x8e, 0xec, 0xca, 0x52, 0x5e, 0x96, 0x0a, 0x48, 0xbc, 0xae, 0x56, 0x80, 0x84, 0x43, + 0x48, 0xd4, 0x82, 0x3c, 0x25, 0xac, 0xef, 0xf8, 0xb2, 0xb4, 0x5f, 0x4d, 0x79, 0xad, 0xf9, 0xa6, + 0xdf, 0x67, 0x06, 0xf0, 0x1a, 0x85, 0x85, 0x3e, 0x96, 0x38, 0xfa, 0x3f, 0x32, 0x50, 0xbe, 0x6d, + 0x1e, 0x10, 0x67, 0x9f, 0x38, 0xc4, 0xf2, 0x3d, 0x8a, 0x7e, 0x06, 0xa5, 0xae, 0xe9, 0x5b, 0x47, + 0x82, 0x1a, 0xf6, 0x96, 0xcd, 0x74, 0x86, 0x12, 0x48, 0xf5, 0xbd, 0x18, 0x66, 0xc7, 0xf5, 0xe9, + 0x99, 0xf1, 0x8a, 0x5c, 0x58, 0x49, 0xe1, 0x60, 0xd5, 0x9a, 0x78, 0x10, 0x88, 0xef, 0x9d, 0xd3, + 0x1e, 0xbf, 0x44, 0xa7, 0x7f, 0x87, 0x24, 0x5c, 0xc0, 0xe4, 0xbd, 0xbe, 0x4d, 0x49, 0x97, 0xb8, + 0x7e, 0xfc, 0x20, 0xd8, 0x1b, 0xc1, 0xc7, 0x63, 0x16, 0x57, 0x6f, 0xc0, 0xd2, 0xa8, 0xf3, 0x68, + 0x09, 0xb2, 0xc7, 0xe4, 0x2c, 0x88, 0x05, 0xcc, 0x7f, 0xa2, 0x15, 0xc8, 0x9d, 0x98, 0x4e, 0x5f, + 0xd6, 0x1f, 0x1c, 0x7c, 0x5c, 0xcf, 0x5c, 0xd3, 0xf4, 0x3f, 0x68, 0x50, 0x99, 0xe4, 0x08, 0xfa, + 0xa2, 0x02, 0x64, 0x94, 0xa4, 0x57, 0xd9, 0x77, 0xc8, 0x59, 0x80, 0xba, 0x03, 0x05, 0xaf, 0xc7, + 0x9f, 0x70, 0x1e, 0x95, 0x71, 0xfe, 0x66, 0x18, 0xbb, 0x77, 0x25, 0xfd, 0x7c, 0x50, 0xbb, 0x92, + 0x80, 0x0f, 0x19, 0x38, 0x52, 0x45, 0x3a, 0xe4, 0x85, 0x3f, 0xfc, 0x52, 0xe6, 0xed, 0x93, 0x38, + 0xfc, 0xfb, 0x82, 0x82, 0x25, 0x47, 0xff, 0xb3, 0x06, 0xb3, 0xa2, 0x3d, 0x7c, 0x08, 0x05, 0xbe, + 0x7f, 0x6d, 0xd3, 0x37, 0x85, 0x5f, 0xa9, 0x1f, 0x13, 0x5c, 0x7b, 0x8f, 0xf8, 0x66, 0x9c, 0x5f, + 0x21, 0x05, 0x47, 0x88, 0x08, 0x43, 0xce, 0xf6, 0x49, 0x37, 0x3c, 0xc8, 0xb7, 0x26, 0x42, 0xcb, + 0xa7, 0x6c, 0x1d, 0x9b, 0x8f, 0x76, 0x4e, 0x7d, 0xe2, 0xf2, 0xc3, 0x88, 0x8b, 0xc1, 0x2e, 0xc7, + 0xc0, 0x01, 0x94, 0xfe, 0x47, 0x0d, 0x22, 0x53, 0x3c, 0xdd, 0x19, 0x71, 0x0e, 0x6f, 0xdb, 0xee, + 0xb1, 0xdc, 0xd6, 0xc8, 0x9d, 0x7d, 0x49, 0xc7, 0x91, 0xc4, 0x45, 0x57, 0x6c, 0x66, 0xca, 0x2b, + 0xf6, 0x2a, 0x14, 0x2c, 0xcf, 0xf5, 0x6d, 0xb7, 0x3f, 0x56, 0x5f, 0xb6, 0x25, 0x1d, 0x47, 0x12, + 0xfa, 0xb3, 0x2c, 0x94, 0xb8, 0xaf, 0xe1, 0x1d, 0xff, 0x2d, 0x28, 0x3b, 0xea, 0xe9, 0x49, 0x9f, + 0xaf, 0x48, 0x88, 0x64, 0x3e, 0xe2, 0xa4, 0x2c, 0x57, 0x3e, 0xb4, 0x89, 0xd3, 0x8e, 0x94, 0x33, + 0x49, 0xe5, 0x9b, 0x2a, 0x13, 0x27, 0x65, 0x79, 0x9d, 0x7d, 0xc4, 0xe3, 0x5a, 0x36, 0x6a, 0xd1, + 0xd6, 0x7e, 0x9f, 0x13, 0x71, 0xc0, 0xbb, 0x68, 0x7f, 0x66, 0xa7, 0xdc, 0x9f, 0xeb, 0xb0, 0xc0, + 0x0f, 0xd2, 0xeb, 0xfb, 0x61, 0x37, 0x9b, 0x13, 0x7d, 0x17, 0x1a, 0x0e, 0x6a, 0x0b, 0xef, 0x26, + 0x38, 0x78, 0x44, 0x72, 0x62, 0xfb, 0x92, 0xff, 0xa4, 0xed, 0x0b, 0x5f, 0xb5, 0x63, 0x77, 0x6d, + 0xbf, 0x32, 0x27, 0x9c, 0x88, 0x56, 0x7d, 0x9b, 0x13, 0x71, 0xc0, 0x4b, 0x1c, 0x69, 0xe1, 0xd2, + 0x23, 0x7d, 0x0f, 0x8a, 0x7b, 0xb6, 0x45, 0x3d, 0xbe, 0x16, 0x7e, 0x31, 0xb1, 0x44, 0xd3, 0x1e, + 0x15, 0xf0, 0x70, 0x8d, 0x21, 0x9f, 0xbb, 0xe2, 0x9a, 0xae, 0x17, 0xb4, 0xe6, 0xb9, 0xd8, 0x95, + 0x3b, 0x9c, 0x88, 0x03, 0xde, 0xf5, 0x15, 0x7e, 0x1f, 0xfd, 0xea, 0x49, 0x6d, 0xe6, 0xf1, 0x93, + 0xda, 0xcc, 0x07, 0x4f, 0xe4, 0xdd, 0xf4, 0x6f, 0x00, 0xb8, 0x7b, 0xf0, 0x13, 0x62, 0x05, 0x31, + 0x7f, 0xf9, 0xab, 0x9c, 0xf7, 0x18, 0x72, 0x18, 0x24, 0x5e, 0xb0, 0x99, 0x91, 0x1e, 0x43, 0xe1, + 0xe1, 0x84, 0x24, 0x6a, 0x40, 0x31, 0x7a, 0xa9, 0xcb, 0xf8, 0x5e, 0x96, 0x6a, 0xc5, 0xe8, 0x39, + 0x8f, 0x63, 0x99, 0x44, 0x02, 0xce, 0x5e, 0x9a, 0x80, 0x06, 0x64, 0xfb, 0x76, 0x5b, 0x84, 0x44, + 0xd1, 0xf8, 0x6a, 0x58, 0x00, 0xef, 0xed, 0x36, 0xcf, 0x07, 0xb5, 0xd7, 0x26, 0x8d, 0xb9, 0xfc, + 0xb3, 0x1e, 0x61, 0xf5, 0x7b, 0xbb, 0x4d, 0xcc, 0x95, 0x2f, 0x0a, 0xd2, 0xfc, 0x94, 0x41, 0xba, + 0x09, 0x20, 0x57, 0xcd, 0xb5, 0x83, 0xd8, 0x88, 0xa6, 0x16, 0xb7, 0x22, 0x0e, 0x56, 0xa4, 0x10, + 0x83, 0x65, 0x8b, 0x12, 0xf1, 0x9b, 0x1f, 0x3d, 0xf3, 0xcd, 0x6e, 0xf0, 0x6e, 0x2f, 0x6d, 0x7e, + 0x39, 0x5d, 0xc5, 0xe4, 0x6a, 0xc6, 0xab, 0xd2, 0xcc, 0xf2, 0xf6, 0x28, 0x18, 0x1e, 0xc7, 0x47, + 0x1e, 0x2c, 0xb7, 0xe5, 0xab, 0x27, 0x36, 0x5a, 0x9c, 0xda, 0xe8, 0x15, 0x6e, 0xb0, 0x39, 0x0a, + 0x84, 0xc7, 0xb1, 0xd1, 0x8f, 0x60, 0x35, 0x24, 0x8e, 0x3f, 0x3d, 0x2b, 0x20, 0x76, 0xaa, 0xca, + 0x1f, 0xc3, 0xcd, 0x89, 0x52, 0xf8, 0x05, 0x08, 0xa8, 0x0d, 0x79, 0x27, 0xe8, 0x2e, 0x4a, 0xe2, + 0x46, 0xf8, 0x76, 0xba, 0x55, 0xc4, 0xd1, 0x5f, 0x57, 0xbb, 0x8a, 0xe8, 0xf9, 0x25, 0x1b, 0x0a, + 0x89, 0x8d, 0x4e, 0xa1, 0x64, 0xba, 0xae, 0xe7, 0x9b, 0xc1, 0x63, 0x78, 0x5e, 0x98, 0xda, 0x9a, + 0xda, 0xd4, 0x56, 0x8c, 0x31, 0xd2, 0xc5, 0x28, 0x1c, 0xac, 0x9a, 0x42, 0x8f, 0x60, 0xd1, 0x7b, + 0xe4, 0x12, 0x8a, 0xc9, 0x21, 0xa1, 0xc4, 0xb5, 0x08, 0xab, 0x94, 0x85, 0xf5, 0xaf, 0xa7, 0xb4, + 0x9e, 0x50, 0x8e, 0x43, 0x3a, 0x49, 0x67, 0x78, 0xd4, 0x0a, 0xaa, 0x03, 0x1c, 0xda, 0xae, 0xec, + 0x45, 0x2b, 0x0b, 0xf1, 0xe8, 0xe9, 0x66, 0x44, 0xc5, 0x8a, 0x04, 0xfa, 0x06, 0x94, 0x2c, 0xa7, + 0xcf, 0x7c, 0x12, 0xcc, 0xb8, 0x16, 0x45, 0x06, 0x45, 0xeb, 0xdb, 0x8e, 0x59, 0x58, 0x95, 0x43, + 0x47, 0x30, 0x6f, 0x2b, 0x4d, 0x6f, 0x65, 0x49, 0xc4, 0xe2, 0xe6, 0xd4, 0x9d, 0x2e, 0x33, 0x96, + 0x78, 0x25, 0x52, 0x29, 0x38, 0x81, 0xbc, 0xfa, 0x4d, 0x28, 0x7d, 0xc2, 0x1e, 0x8c, 0xf7, 0x70, + 0xa3, 0x47, 0x37, 0x55, 0x0f, 0xf7, 0xb7, 0x0c, 0x2c, 0x24, 0x37, 0x3c, 0x7a, 0xeb, 0x68, 0x13, + 0x67, 0x96, 0x61, 0x55, 0xce, 0x4e, 0xac, 0xca, 0xb2, 0xf8, 0xcd, 0xbe, 0x4c, 0xf1, 0xdb, 0x04, + 0x30, 0x7b, 0x76, 0x58, 0xf7, 0x82, 0x3a, 0x1a, 0x55, 0xae, 0x78, 0x8a, 0x86, 0x15, 0x29, 0x31, + 0x95, 0xf4, 0x5c, 0x9f, 0x7a, 0x8e, 0x43, 0xa8, 0xbc, 0x4c, 0x83, 0xa9, 0x64, 0x44, 0xc5, 0x8a, + 0x04, 0xba, 0x09, 0xe8, 0xc0, 0xf1, 0xac, 0x63, 0xb1, 0x05, 0x61, 0x9e, 0x8b, 0x2a, 0x59, 0x08, + 0x86, 0x52, 0xc6, 0x18, 0x17, 0x5f, 0xa0, 0xa1, 0xcf, 0x41, 0xae, 0xc5, 0xdb, 0x0a, 0xfd, 0x2e, + 0x24, 0xe7, 0x49, 0xe8, 0x46, 0xb0, 0x13, 0x5a, 0x34, 0xf0, 0x99, 0x6e, 0x17, 0xf4, 0xab, 0x50, + 0xc4, 0x9e, 0xe7, 0xb7, 0x4c, 0xff, 0x88, 0xa1, 0x1a, 0xe4, 0x7a, 0xfc, 0x87, 0x1c, 0x16, 0x8a, + 0xf9, 0xaf, 0xe0, 0xe0, 0x80, 0xae, 0xff, 0x5a, 0x83, 0x57, 0x27, 0xce, 0xee, 0xf8, 0x8e, 0x5a, + 0xd1, 0x97, 0x74, 0x29, 0xda, 0xd1, 0x58, 0x0e, 0x2b, 0x52, 0xbc, 0x13, 0x4b, 0x0c, 0xfc, 0x46, + 0x3b, 0xb1, 0x84, 0x35, 0x9c, 0x94, 0xd5, 0xff, 0x93, 0x81, 0x7c, 0xf0, 0x2c, 0xfb, 0x1f, 0x37, + 0xdf, 0x6f, 0x40, 0x9e, 0x09, 0x3b, 0xd2, 0xbd, 0xa8, 0x5a, 0x06, 0xd6, 0xb1, 0xe4, 0xf2, 0x26, + 0xa6, 0x4b, 0x18, 0x33, 0x3b, 0x61, 0xf0, 0x46, 0x4d, 0xcc, 0x5e, 0x40, 0xc6, 0x21, 0x1f, 0xbd, + 0xcd, 0x5f, 0xa1, 0x26, 0x8b, 0xfa, 0xc2, 0x6a, 0x08, 0x89, 0x05, 0xf5, 0x7c, 0x50, 0x9b, 0x97, + 0xe0, 0xe2, 0x1b, 0x4b, 0x69, 0xf4, 0x00, 0xe6, 0xda, 0xc4, 0x37, 0x6d, 0x27, 0x68, 0x07, 0x53, + 0x4f, 0x26, 0x03, 0xb0, 0x66, 0xa0, 0x6a, 0x94, 0xb8, 0x4f, 0xf2, 0x03, 0x87, 0x80, 0x3c, 0xf1, + 0x2c, 0xaf, 0x1d, 0x8c, 0xe9, 0x73, 0x71, 0xe2, 0x6d, 0x7b, 0x6d, 0x82, 0x05, 0x47, 0x7f, 0xac, + 0x41, 0x29, 0x40, 0xda, 0x36, 0xfb, 0x8c, 0xa0, 0x8d, 0x68, 0x15, 0xc1, 0x71, 0x87, 0x77, 0xf2, + 0xec, 0xbb, 0x67, 0x3d, 0x72, 0x3e, 0xa8, 0x15, 0x85, 0x18, 0xff, 0x88, 0x16, 0xa0, 0xec, 0x51, + 0xe6, 0x92, 0x3d, 0x7a, 0x1d, 0x72, 0xa2, 0xf5, 0x96, 0x9b, 0x19, 0x35, 0x7a, 0xa2, 0x3d, 0xc7, + 0x01, 0x4f, 0xff, 0x28, 0x03, 0xe5, 0xc4, 0xe2, 0x52, 0x74, 0x75, 0xd1, 0xa8, 0x24, 0x93, 0x62, + 0xfc, 0x36, 0xf9, 0x9f, 0x2b, 0x3f, 0x80, 0xbc, 0xc5, 0xd7, 0x17, 0xfe, 0x77, 0x6b, 0x63, 0x9a, + 0xa3, 0x10, 0x3b, 0x13, 0x47, 0x92, 0xf8, 0x64, 0x58, 0x02, 0xa2, 0x5b, 0xb0, 0x4c, 0x89, 0x4f, + 0xcf, 0xb6, 0x0e, 0x7d, 0x42, 0xd5, 0xfe, 0x3f, 0x17, 0xf7, 0x3d, 0x78, 0x54, 0x00, 0x8f, 0xeb, + 0x84, 0xa5, 0x32, 0xff, 0x12, 0xa5, 0x52, 0x77, 0x60, 0xf6, 0xff, 0xd8, 0xa3, 0xff, 0x10, 0x8a, + 0x71, 0x17, 0xf5, 0x29, 0x9b, 0xd4, 0x7f, 0x0c, 0x05, 0x1e, 0x8d, 0x61, 0xf7, 0x7f, 0xc9, 0x4d, + 0x94, 0xbc, 0x23, 0x32, 0x69, 0xee, 0x08, 0x7d, 0x13, 0x82, 0xff, 0x99, 0xf1, 0x6a, 0x1a, 0xbc, + 0xd8, 0x95, 0x6a, 0xaa, 0x3e, 0xbf, 0x95, 0x91, 0xd9, 0x2f, 0x35, 0x00, 0xf1, 0x7c, 0xdc, 0x39, + 0x21, 0xae, 0xcf, 0x1d, 0xe3, 0x27, 0x30, 0xea, 0x98, 0x48, 0x23, 0xc1, 0x41, 0xf7, 0x20, 0xef, + 0x89, 0xee, 0x4a, 0xce, 0xb0, 0xa6, 0x1c, 0x07, 0x44, 0x51, 0x17, 0xb4, 0x68, 0x58, 0x82, 0x19, + 0xeb, 0x4f, 0x9f, 0x57, 0x67, 0x9e, 0x3d, 0xaf, 0xce, 0x7c, 0xf8, 0xbc, 0x3a, 0xf3, 0xfe, 0xb0, + 0xaa, 0x3d, 0x1d, 0x56, 0xb5, 0x67, 0xc3, 0xaa, 0xf6, 0xe1, 0xb0, 0xaa, 0x7d, 0x34, 0xac, 0x6a, + 0x8f, 0x3f, 0xae, 0xce, 0x3c, 0xc8, 0x9c, 0x6c, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, 0x0e, 0xc8, + 0x1d, 0xca, 0x1f, 0x20, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto index bd5abcb79..df386bc9a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -23,7 +23,6 @@ package k8s.io.apimachinery.pkg.apis.meta.v1; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; @@ -49,6 +48,7 @@ message APIGroup { // The server returns only those CIDRs that it thinks that the client can match. // For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. // Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP. + // +optional repeated ServerAddressByClientCIDR serverAddressByClientCIDRs = 4; } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go index 1f7f07e81..ab62ff424 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go @@ -21,7 +21,7 @@ import ( "reflect" "testing" - jsoniter "github.com/json-iterator/go" + k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json" ) type GroupVersionHolder struct { @@ -47,7 +47,8 @@ func TestGroupVersionUnmarshalJSON(t *testing.T) { t.Errorf("JSON codec failed to unmarshal input '%s': expected %+v, got %+v", c.input, c.expect, result.GV) } // test the json-iterator codec - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(c.input, &result); err != nil { + iter := k8s_json.CaseSensitiveJsonIterator() + if err := iter.Unmarshal(c.input, &result); err != nil { t.Errorf("json-iterator codec failed to unmarshal input '%v': %v", c.input, err) } if !reflect.DeepEqual(result.GV, c.expect) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/helpers_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/helpers_test.go index fba6b158e..fa4249300 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/helpers_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/helpers_test.go @@ -17,6 +17,7 @@ limitations under the License. package v1 import ( + "fmt" "reflect" "strings" "testing" @@ -70,15 +71,21 @@ func TestLabelSelectorAsSelector(t *testing.T) { } for i, tc := range tc { + inCopy := tc.in.DeepCopy() out, err := LabelSelectorAsSelector(tc.in) + // after calling LabelSelectorAsSelector, tc.in shouldn't be modified + if !reflect.DeepEqual(inCopy, tc.in) { + t.Errorf("[%v]expected:\n\t%#v\nbut got:\n\t%#v", i, inCopy, tc.in) + } if err == nil && tc.expectErr { t.Errorf("[%v]expected error but got none.", i) } if err != nil && !tc.expectErr { t.Errorf("[%v]did not expect error but got: %v", i, err) } - if !reflect.DeepEqual(out, tc.out) { - t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out) + // fmt.Sprint() over String() as nil.String() will panic + if fmt.Sprint(out) != fmt.Sprint(tc.out) { + t.Errorf("[%v]expected:\n\t%s\nbut got:\n\t%s", i, fmt.Sprint(tc.out), fmt.Sprint(out)) } } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go index 7e5bc2d4e..6f6c5111b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go @@ -104,7 +104,10 @@ func (t *MicroTime) UnmarshalJSON(b []byte) error { } var str string - json.Unmarshal(b, &str) + err := json.Unmarshal(b, &str) + if err != nil { + return err + } pt, err := time.Parse(RFC3339Micro, str) if err != nil { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/time.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/time.go index 5041954f7..efff656e1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/time.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/time.go @@ -106,7 +106,10 @@ func (t *Time) UnmarshalJSON(b []byte) error { } var str string - json.Unmarshal(b, &str) + err := json.Unmarshal(b, &str) + if err != nil { + return err + } pt, err := time.Parse(time.RFC3339, str) if err != nil { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go index 917efb37f..e93df1846 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go @@ -799,7 +799,8 @@ type APIGroup struct { // The server returns only those CIDRs that it thinks that the client can match. // For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. // Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP. - ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs" protobuf:"bytes,4,rep,name=serverAddressByClientCIDRs"` + // +optional + ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs,omitempty" protobuf:"bytes,4,rep,name=serverAddressByClientCIDRs"` } // ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go index caf929ee0..f91d8a81f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_APIGroup = map[string]string{ "": "APIGroup contains the name, the supported versions, and the preferred version of a group.", "name": "name is the name of the group.", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go index 116f7505a..ed5f20c40 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_test.go @@ -21,7 +21,7 @@ import ( "reflect" "testing" - jsoniter "github.com/json-iterator/go" + k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json" ) func TestVerbsUgorjiMarshalJSON(t *testing.T) { @@ -45,7 +45,7 @@ func TestVerbsUgorjiMarshalJSON(t *testing.T) { } } -func TestVerbsUgorjiUnmarshalJSON(t *testing.T) { +func TestVerbsUJsonIterUnmarshalJSON(t *testing.T) { cases := []struct { input string result APIResource @@ -56,9 +56,10 @@ func TestVerbsUgorjiUnmarshalJSON(t *testing.T) { {`{"verbs":["delete"]}`, APIResource{Verbs: Verbs([]string{"delete"})}}, } + iter := k8s_json.CaseSensitiveJsonIterator() for i, c := range cases { var result APIResource - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(c.input), &result); err != nil { + if err := iter.Unmarshal([]byte(c.input), &result); err != nil { t.Errorf("[%d] Failed to unmarshal input '%v': %v", i, c.input, err) } if !reflect.DeepEqual(result, c.result) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/BUILD index 22c1acee0..2dba6fdb7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/BUILD @@ -11,6 +11,7 @@ go_test( srcs = [ "helpers_test.go", "unstructured_list_test.go", + "unstructured_test.go", ], embed = [":go_default_library"], deps = [ @@ -48,6 +49,9 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme:all-srcs", + ], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go index 08705ac84..fc138e75a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go @@ -18,7 +18,6 @@ package unstructured import ( gojson "encoding/json" - "errors" "fmt" "io" "strings" @@ -34,14 +33,17 @@ import ( // Returns false if the value is missing. // No error is returned for a nil field. func NestedFieldCopy(obj map[string]interface{}, fields ...string) (interface{}, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return nil, found, err } return runtime.DeepCopyJSONValue(val), true, nil } -func nestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{}, bool, error) { +// NestedFieldNoCopy returns a reference to a nested field. +// Returns false if value is not found and an error if unable +// to traverse obj. +func NestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{}, bool, error) { var val interface{} = obj for i, field := range fields { @@ -60,7 +62,7 @@ func nestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{ // NestedString returns the string value of a nested field. // Returns false if value is not found and an error if not a string. func NestedString(obj map[string]interface{}, fields ...string) (string, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return "", found, err } @@ -74,7 +76,7 @@ func NestedString(obj map[string]interface{}, fields ...string) (string, bool, e // NestedBool returns the bool value of a nested field. // Returns false if value is not found and an error if not a bool. func NestedBool(obj map[string]interface{}, fields ...string) (bool, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return false, found, err } @@ -88,7 +90,7 @@ func NestedBool(obj map[string]interface{}, fields ...string) (bool, bool, error // NestedFloat64 returns the float64 value of a nested field. // Returns false if value is not found and an error if not a float64. func NestedFloat64(obj map[string]interface{}, fields ...string) (float64, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return 0, found, err } @@ -102,7 +104,7 @@ func NestedFloat64(obj map[string]interface{}, fields ...string) (float64, bool, // NestedInt64 returns the int64 value of a nested field. // Returns false if value is not found and an error if not an int64. func NestedInt64(obj map[string]interface{}, fields ...string) (int64, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return 0, found, err } @@ -116,7 +118,7 @@ func NestedInt64(obj map[string]interface{}, fields ...string) (int64, bool, err // NestedStringSlice returns a copy of []string value of a nested field. // Returns false if value is not found and an error if not a []interface{} or contains non-string items in the slice. func NestedStringSlice(obj map[string]interface{}, fields ...string) ([]string, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return nil, found, err } @@ -138,7 +140,7 @@ func NestedStringSlice(obj map[string]interface{}, fields ...string) ([]string, // NestedSlice returns a deep copy of []interface{} value of a nested field. // Returns false if value is not found and an error if not a []interface{}. func NestedSlice(obj map[string]interface{}, fields ...string) ([]interface{}, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return nil, found, err } @@ -180,7 +182,7 @@ func NestedMap(obj map[string]interface{}, fields ...string) (map[string]interfa // nestedMapNoCopy returns a map[string]interface{} value of a nested field. // Returns false if value is not found and an error if not a map[string]interface{}. func nestedMapNoCopy(obj map[string]interface{}, fields ...string) (map[string]interface{}, bool, error) { - val, found, err := nestedFieldNoCopy(obj, fields...) + val, found, err := NestedFieldNoCopy(obj, fields...) if !found || err != nil { return nil, found, err } @@ -433,43 +435,17 @@ func (s unstructuredJSONScheme) decodeToList(data []byte, list *UnstructuredList return nil } -// UnstructuredObjectConverter is an ObjectConverter for use with -// Unstructured objects. Since it has no schema or type information, -// it will only succeed for no-op conversions. This is provided as a -// sane implementation for APIs that require an object converter. -type UnstructuredObjectConverter struct{} - -func (UnstructuredObjectConverter) Convert(in, out, context interface{}) error { - unstructIn, ok := in.(*Unstructured) - if !ok { - return fmt.Errorf("input type %T in not valid for unstructured conversion", in) - } - - unstructOut, ok := out.(*Unstructured) - if !ok { - return fmt.Errorf("output type %T in not valid for unstructured conversion", out) - } - - // maybe deep copy the map? It is documented in the - // ObjectConverter interface that this function is not - // guaranteed to not mutate the input. Or maybe set the input - // object to nil. - unstructOut.Object = unstructIn.Object - return nil +type JSONFallbackEncoder struct { + runtime.Encoder } -func (UnstructuredObjectConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { - if kind := in.GetObjectKind().GroupVersionKind(); !kind.Empty() { - gvk, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{kind}) - if !ok { - // TODO: should this be a typed error? - return nil, fmt.Errorf("%v is unstructured and is not suitable for converting to %q", kind, target) +func (c JSONFallbackEncoder) Encode(obj runtime.Object, w io.Writer) error { + err := c.Encoder.Encode(obj, w) + if runtime.IsNotRegisteredError(err) { + switch obj.(type) { + case *Unstructured, *UnstructuredList: + return UnstructuredJSONScheme.Encode(obj, w) } - in.GetObjectKind().SetGroupVersionKind(gvk) } - return in, nil -} - -func (UnstructuredObjectConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { - return "", "", errors.New("unstructured cannot convert field labels") + return err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers_test.go index 9e774d1c1..d97996211 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers_test.go @@ -58,3 +58,79 @@ func TestRemoveNestedField(t *testing.T) { RemoveNestedField(obj, "x") // Remove of a non-existent field assert.Empty(t, obj) } + +func TestNestedFieldNoCopy(t *testing.T) { + target := map[string]interface{}{"foo": "bar"} + + obj := map[string]interface{}{ + "a": map[string]interface{}{ + "b": target, + "c": nil, + "d": []interface{}{"foo"}, + }, + } + + // case 1: field exists and is non-nil + res, exists, err := NestedFieldNoCopy(obj, "a", "b") + assert.True(t, exists) + assert.Nil(t, err) + assert.Equal(t, target, res) + target["foo"] = "baz" + assert.Equal(t, target["foo"], res.(map[string]interface{})["foo"], "result should be a reference to the expected item") + + // case 2: field exists and is nil + res, exists, err = NestedFieldNoCopy(obj, "a", "c") + assert.True(t, exists) + assert.Nil(t, err) + assert.Nil(t, res) + + // case 3: error traversing obj + res, exists, err = NestedFieldNoCopy(obj, "a", "d", "foo") + assert.False(t, exists) + assert.NotNil(t, err) + assert.Nil(t, res) + + // case 4: field does not exist + res, exists, err = NestedFieldNoCopy(obj, "a", "e") + assert.False(t, exists) + assert.Nil(t, err) + assert.Nil(t, res) +} + +func TestNestedFieldCopy(t *testing.T) { + target := map[string]interface{}{"foo": "bar"} + + obj := map[string]interface{}{ + "a": map[string]interface{}{ + "b": target, + "c": nil, + "d": []interface{}{"foo"}, + }, + } + + // case 1: field exists and is non-nil + res, exists, err := NestedFieldCopy(obj, "a", "b") + assert.True(t, exists) + assert.Nil(t, err) + assert.Equal(t, target, res) + target["foo"] = "baz" + assert.NotEqual(t, target["foo"], res.(map[string]interface{})["foo"], "result should be a copy of the expected item") + + // case 2: field exists and is nil + res, exists, err = NestedFieldCopy(obj, "a", "c") + assert.True(t, exists) + assert.Nil(t, err) + assert.Nil(t, res) + + // case 3: error traversing obj + res, exists, err = NestedFieldCopy(obj, "a", "d", "foo") + assert.False(t, exists) + assert.NotNil(t, err) + assert.Nil(t, res) + + // case 4: field does not exist + res, exists, err = NestedFieldCopy(obj, "a", "e") + assert.False(t, exists) + assert.Nil(t, err) + assert.Nil(t, res) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go index 2a1333049..548a01e59 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go @@ -58,6 +58,26 @@ func (obj *Unstructured) IsList() bool { _, ok = field.([]interface{}) return ok } +func (obj *Unstructured) ToList() (*UnstructuredList, error) { + if !obj.IsList() { + // return an empty list back + return &UnstructuredList{Object: obj.Object}, nil + } + + ret := &UnstructuredList{} + ret.Object = obj.Object + + err := obj.EachListItem(func(item runtime.Object) error { + castItem := item.(*Unstructured) + ret.Items = append(ret.Items, *castItem) + return nil + }) + if err != nil { + return nil, err + } + + return ret, nil +} func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { field, ok := obj.Object["items"] @@ -82,7 +102,7 @@ func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { func (obj *Unstructured) UnstructuredContent() map[string]interface{} { if obj.Object == nil { - obj.Object = make(map[string]interface{}) + return make(map[string]interface{}) } return obj.Object } @@ -138,7 +158,7 @@ func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) { } func (u *Unstructured) GetOwnerReferences() []metav1.OwnerReference { - field, found, err := nestedFieldNoCopy(u.Object, "metadata", "ownerReferences") + field, found, err := NestedFieldNoCopy(u.Object, "metadata", "ownerReferences") if !found || err != nil { return nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go index 57d78a09d..bf3fd023f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go @@ -53,19 +53,18 @@ func (u *UnstructuredList) EachListItem(fn func(runtime.Object) error) error { } // UnstructuredContent returns a map contain an overlay of the Items field onto -// the Object field. Items always overwrites overlay. Changing "items" in the -// returned object will affect items in the underlying Items field, but changing -// the "items" slice itself will have no effect. -// TODO: expose SetUnstructuredContent on runtime.Unstructured that allows -// items to be changed. +// the Object field. Items always overwrites overlay. func (u *UnstructuredList) UnstructuredContent() map[string]interface{} { - out := u.Object - if out == nil { - out = make(map[string]interface{}) + out := make(map[string]interface{}, len(u.Object)+1) + + // shallow copy every property + for k, v := range u.Object { + out[k] = v } + items := make([]interface{}, len(u.Items)) for i, item := range u.Items { - items[i] = item.Object + items[i] = item.UnstructuredContent() } out["items"] = items return out diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_test.go new file mode 100644 index 000000000..cbcbbcef3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_test.go @@ -0,0 +1,32 @@ +/* +Copyright 2018 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 unstructured + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNilUnstructuredContent(t *testing.T) { + var u Unstructured + uCopy := u.DeepCopy() + content := u.UnstructuredContent() + expContent := make(map[string]interface{}) + assert.EqualValues(t, expContent, content) + assert.Equal(t, uCopy, &u) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/BUILD new file mode 100644 index 000000000..7021cdae1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["scheme.go"], + importpath = "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go new file mode 100644 index 000000000..ab2574e82 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go @@ -0,0 +1,129 @@ +/* +Copyright 2018 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 unstructuredscheme + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/apimachinery/pkg/runtime/serializer/versioning" +) + +var ( + scheme = runtime.NewScheme() + codecs = serializer.NewCodecFactory(scheme) +) + +// NewUnstructuredNegotiatedSerializer returns a simple, negotiated serializer +func NewUnstructuredNegotiatedSerializer() runtime.NegotiatedSerializer { + return unstructuredNegotiatedSerializer{ + scheme: scheme, + typer: NewUnstructuredObjectTyper(), + creator: NewUnstructuredCreator(), + } +} + +type unstructuredNegotiatedSerializer struct { + scheme *runtime.Scheme + typer runtime.ObjectTyper + creator runtime.ObjectCreater +} + +func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { + return []runtime.SerializerInfo{ + { + MediaType: "application/json", + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false), + PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, true), + StreamSerializer: &runtime.StreamSerializerInfo{ + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false), + Framer: json.Framer, + }, + }, + { + MediaType: "application/yaml", + EncodesAsText: true, + Serializer: json.NewYAMLSerializer(json.DefaultMetaFactory, s.creator, s.typer), + }, + } +} + +func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { + return versioning.NewDefaultingCodecForScheme(s.scheme, encoder, nil, gv, nil) +} + +func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { + return versioning.NewDefaultingCodecForScheme(s.scheme, nil, decoder, nil, gv) +} + +type unstructuredObjectTyper struct { +} + +// NewUnstructuredObjectTyper returns an object typer that can deal with unstructured things +func NewUnstructuredObjectTyper() runtime.ObjectTyper { + return unstructuredObjectTyper{} +} + +func (t unstructuredObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { + // Delegate for things other than Unstructured. + if _, ok := obj.(runtime.Unstructured); !ok { + return nil, false, fmt.Errorf("cannot type %T", obj) + } + gvk := obj.GetObjectKind().GroupVersionKind() + if len(gvk.Kind) == 0 { + return nil, false, runtime.NewMissingKindErr("object has no kind field ") + } + if len(gvk.Version) == 0 { + return nil, false, runtime.NewMissingVersionErr("object has no apiVersion field") + } + + return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil +} + +func (t unstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool { + return true +} + +type unstructuredCreator struct{} + +// NewUnstructuredCreator returns a simple object creator that always returns an unstructured +func NewUnstructuredCreator() runtime.ObjectCreater { + return unstructuredCreator{} +} + +func (c unstructuredCreator) New(kind schema.GroupVersionKind) (runtime.Object, error) { + ret := &unstructured.Unstructured{} + ret.SetGroupVersionKind(kind) + return ret, nil +} + +type unstructuredDefaulter struct { +} + +// NewUnstructuredDefaulter returns defaulter suitable for unstructured types that doesn't default anything +func NewUnstructuredDefaulter() runtime.ObjectDefaulter { + return unstructuredDefaulter{} +} + +func (d unstructuredDefaulter) Default(in runtime.Object) { +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go index 1c185139f..9a9f25e8f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go index 26c5a0cdc..96e5f42b7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go @@ -17,8 +17,6 @@ limitations under the License. package validation import ( - "fmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" @@ -78,13 +76,13 @@ func ValidateLabels(labels map[string]string, fldPath *field.Path) field.ErrorLi func ValidateDeleteOptions(options *metav1.DeleteOptions) field.ErrorList { allErrs := field.ErrorList{} if options.OrphanDependents != nil && options.PropagationPolicy != nil { - allErrs = append(allErrs, field.Invalid(field.NewPath(""), options, "OrphanDependents and DeletionPropagation cannot be both set")) + allErrs = append(allErrs, field.Invalid(field.NewPath("propagationPolicy"), options.PropagationPolicy, "orphanDependents and deletionPropagation cannot be both set")) } if options.PropagationPolicy != nil && *options.PropagationPolicy != metav1.DeletePropagationForeground && *options.PropagationPolicy != metav1.DeletePropagationBackground && *options.PropagationPolicy != metav1.DeletePropagationOrphan { - allErrs = append(allErrs, field.Invalid(field.NewPath(""), options, fmt.Sprintf("DeletionPropagation need to be one of %q, %q, %q or nil", metav1.DeletePropagationForeground, metav1.DeletePropagationBackground, metav1.DeletePropagationOrphan))) + allErrs = append(allErrs, field.NotSupported(field.NewPath("propagationPolicy"), options.PropagationPolicy, []string{string(metav1.DeletePropagationForeground), string(metav1.DeletePropagationBackground), string(metav1.DeletePropagationOrphan), "nil"})) } return allErrs } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go index 73308d86e..98dfea095 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/deepcopy.go index 2dd440bb7..3b2bedd92 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/deepcopy.go @@ -16,6 +16,8 @@ limitations under the License. package v1beta1 +import "k8s.io/apimachinery/pkg/runtime" + func (in *TableRow) DeepCopy() *TableRow { if in == nil { return nil @@ -26,7 +28,7 @@ func (in *TableRow) DeepCopy() *TableRow { if in.Cells != nil { out.Cells = make([]interface{}, len(in.Cells)) for i := range in.Cells { - out.Cells[i] = deepCopyJSON(in.Cells[i]) + out.Cells[i] = runtime.DeepCopyJSONValue(in.Cells[i]) } } @@ -40,22 +42,3 @@ func (in *TableRow) DeepCopy() *TableRow { in.Object.DeepCopyInto(&out.Object) return out } - -func deepCopyJSON(x interface{}) interface{} { - switch x := x.(type) { - case map[string]interface{}: - clone := make(map[string]interface{}, len(x)) - for k, v := range x { - clone[k] = deepCopyJSON(v) - } - return clone - case []interface{}: - clone := make([]interface{}, len(x)) - for i := range x { - clone[i] = deepCopyJSON(x[i]) - } - return clone - default: - return x - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go index dda05bea4..fe3df6916 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -604,30 +604,29 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 391 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xbd, 0x6e, 0xd4, 0x40, - 0x10, 0xc7, 0xbd, 0x42, 0x11, 0x64, 0x43, 0x1a, 0x23, 0xa4, 0x70, 0xc5, 0x3a, 0xba, 0x2a, 0x48, - 0x64, 0x97, 0x04, 0x84, 0x28, 0x91, 0xbb, 0x48, 0xa0, 0x44, 0x16, 0x15, 0x15, 0x6b, 0x7b, 0xf0, - 0x2d, 0xb6, 0x77, 0xad, 0xdd, 0x71, 0xa4, 0x6b, 0x10, 0x8f, 0xc0, 0x63, 0x5d, 0x99, 0x32, 0x95, - 0xc5, 0x99, 0xb7, 0xa0, 0x42, 0xfe, 0x10, 0xf9, 0xb8, 0x3b, 0xe5, 0xba, 0x99, 0xff, 0xe8, 0xf7, - 0xf3, 0x8c, 0x97, 0x46, 0xf9, 0x7b, 0xc7, 0x95, 0x11, 0x79, 0x1d, 0x83, 0xd5, 0x80, 0xe0, 0xc4, - 0x25, 0xe8, 0xd4, 0x58, 0x31, 0x0e, 0x64, 0xa5, 0x4a, 0x99, 0xcc, 0x94, 0x06, 0x3b, 0x17, 0x55, - 0x9e, 0x75, 0x81, 0x13, 0x25, 0xa0, 0x14, 0x97, 0x27, 0x31, 0xa0, 0x3c, 0x11, 0x19, 0x68, 0xb0, - 0x12, 0x21, 0xe5, 0x95, 0x35, 0x68, 0xfc, 0x97, 0x03, 0xca, 0x6f, 0xa3, 0xbc, 0xca, 0xb3, 0x2e, - 0x70, 0xbc, 0x43, 0xf9, 0x88, 0x4e, 0x8e, 0x33, 0x85, 0xb3, 0x3a, 0xe6, 0x89, 0x29, 0x45, 0x66, - 0x32, 0x23, 0x7a, 0x43, 0x5c, 0x7f, 0xeb, 0xbb, 0xbe, 0xe9, 0xab, 0xc1, 0x3c, 0x79, 0xbb, 0xcd, - 0x52, 0xf7, 0xf7, 0x99, 0x6c, 0x3c, 0xc5, 0xd6, 0x1a, 0x55, 0x09, 0x2b, 0xc0, 0xbb, 0x87, 0x00, - 0x97, 0xcc, 0xa0, 0x94, 0x2b, 0xdc, 0x9b, 0x4d, 0x5c, 0x8d, 0xaa, 0x10, 0x4a, 0xa3, 0x43, 0x7b, - 0x1f, 0x9a, 0xce, 0xe9, 0xf3, 0x0b, 0x69, 0x51, 0xc9, 0xe2, 0x3c, 0xfe, 0x0e, 0x09, 0x7e, 0x02, - 0x94, 0xa9, 0x44, 0xe9, 0x7f, 0xa5, 0x4f, 0xca, 0xb1, 0x3e, 0x20, 0x87, 0xe4, 0x68, 0xef, 0xf4, - 0x35, 0xdf, 0xe6, 0xcf, 0xf2, 0x1b, 0x4f, 0xe8, 0x2f, 0x9a, 0xc0, 0x6b, 0x9b, 0x80, 0xde, 0x64, - 0xd1, 0x7f, 0xeb, 0xf4, 0x07, 0x7d, 0xb1, 0xf6, 0xd3, 0x1f, 0x95, 0x43, 0x5f, 0xd2, 0x1d, 0x85, - 0x50, 0xba, 0x03, 0x72, 0xf8, 0xe8, 0x68, 0xef, 0xf4, 0x03, 0xdf, 0xfa, 0x55, 0xf9, 0x5a, 0x69, - 0xb8, 0xdb, 0x36, 0xc1, 0xce, 0x59, 0xa7, 0x8c, 0x06, 0xf3, 0x34, 0xa6, 0x4f, 0x3f, 0xcb, 0xb8, - 0x80, 0xf3, 0x0a, 0x95, 0xd1, 0xce, 0x8f, 0xe8, 0xbe, 0xd2, 0x49, 0x51, 0xa7, 0x30, 0xa0, 0xfd, - 0xd9, 0xbb, 0xe1, 0xab, 0xf1, 0x88, 0xfd, 0xb3, 0xdb, 0xc3, 0xbf, 0x4d, 0xf0, 0xec, 0x4e, 0x70, - 0x61, 0x0a, 0x95, 0xcc, 0xa3, 0xbb, 0x8a, 0xf0, 0x78, 0xb1, 0x64, 0xde, 0xd5, 0x92, 0x79, 0xd7, - 0x4b, 0xe6, 0xfd, 0x6c, 0x19, 0x59, 0xb4, 0x8c, 0x5c, 0xb5, 0x8c, 0x5c, 0xb7, 0x8c, 0xfc, 0x6e, - 0x19, 0xf9, 0xf5, 0x87, 0x79, 0x5f, 0x1e, 0x8f, 0xab, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x73, - 0xdf, 0x3a, 0x0c, 0x10, 0x03, 0x00, 0x00, + // 375 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xcd, 0x0a, 0xd3, 0x40, + 0x10, 0xc7, 0xb3, 0x48, 0xd1, 0x6e, 0xed, 0x25, 0x22, 0xd4, 0x1e, 0x36, 0xa5, 0xa7, 0x0a, 0x76, + 0xd7, 0x16, 0x11, 0x8f, 0x92, 0x5b, 0x41, 0x69, 0x09, 0x9e, 0x3c, 0xb9, 0x49, 0xc6, 0x74, 0xcd, + 0xc7, 0x86, 0xec, 0xa6, 0xd0, 0x8b, 0xf8, 0x08, 0x3e, 0x56, 0x8f, 0x3d, 0xf6, 0x14, 0x6c, 0x7c, + 0x0b, 0x4f, 0x92, 0x0f, 0xec, 0x87, 0x15, 0x7b, 0x9b, 0xf9, 0x0f, 0xbf, 0x5f, 0x66, 0xb2, 0xd8, + 0x09, 0xdf, 0x28, 0x2a, 0x24, 0x0b, 0x73, 0x17, 0xb2, 0x04, 0x34, 0x28, 0xb6, 0x81, 0xc4, 0x97, + 0x19, 0x6b, 0x07, 0x3c, 0x15, 0x31, 0xf7, 0xd6, 0x22, 0x81, 0x6c, 0xcb, 0xd2, 0x30, 0xa8, 0x02, + 0xc5, 0x62, 0xd0, 0x9c, 0x6d, 0x66, 0x2e, 0x68, 0x3e, 0x63, 0x01, 0x24, 0x90, 0x71, 0x0d, 0x3e, + 0x4d, 0x33, 0xa9, 0xa5, 0xf9, 0xbc, 0x41, 0xe9, 0x39, 0x4a, 0xd3, 0x30, 0xa8, 0x02, 0x45, 0x2b, + 0x94, 0xb6, 0xe8, 0x70, 0x1a, 0x08, 0xbd, 0xce, 0x5d, 0xea, 0xc9, 0x98, 0x05, 0x32, 0x90, 0xac, + 0x36, 0xb8, 0xf9, 0xe7, 0xba, 0xab, 0x9b, 0xba, 0x6a, 0xcc, 0xc3, 0x57, 0xf7, 0x2c, 0x75, 0xbd, + 0xcf, 0xf0, 0x9f, 0xa7, 0x64, 0x79, 0xa2, 0x45, 0x0c, 0x7f, 0x01, 0xaf, 0xff, 0x07, 0x28, 0x6f, + 0x0d, 0x31, 0xbf, 0xe6, 0xc6, 0x5b, 0xfc, 0x74, 0xc5, 0x33, 0x2d, 0x78, 0xb4, 0x74, 0xbf, 0x80, + 0xa7, 0xdf, 0x83, 0xe6, 0x3e, 0xd7, 0xdc, 0xfc, 0x84, 0x1f, 0xc5, 0x6d, 0x3d, 0x40, 0x23, 0x34, + 0xe9, 0xcd, 0x5f, 0xd2, 0x7b, 0x7e, 0x12, 0x3d, 0x79, 0x6c, 0x73, 0x57, 0x58, 0x46, 0x59, 0x58, + 0xf8, 0x94, 0x39, 0x7f, 0xac, 0xe3, 0xaf, 0xf8, 0xd9, 0xcd, 0x4f, 0xbf, 0x13, 0x4a, 0x9b, 0x1c, + 0x77, 0x84, 0x86, 0x58, 0x0d, 0xd0, 0xe8, 0xc1, 0xa4, 0x37, 0x7f, 0x4b, 0xef, 0x7e, 0x20, 0x7a, + 0x53, 0x6a, 0x77, 0xcb, 0xc2, 0xea, 0x2c, 0x2a, 0xa5, 0xd3, 0x98, 0xc7, 0x2e, 0x7e, 0xfc, 0x81, + 0xbb, 0x11, 0x2c, 0x53, 0x2d, 0x64, 0xa2, 0x4c, 0x07, 0xf7, 0x45, 0xe2, 0x45, 0xb9, 0x0f, 0x0d, + 0x5a, 0x9f, 0xdd, 0xb5, 0x5f, 0xb4, 0x47, 0xf4, 0x17, 0xe7, 0xc3, 0x5f, 0x85, 0xf5, 0xe4, 0x22, + 0x58, 0xc9, 0x48, 0x78, 0x5b, 0xe7, 0x52, 0x61, 0x4f, 0x77, 0x47, 0x62, 0xec, 0x8f, 0xc4, 0x38, + 0x1c, 0x89, 0xf1, 0xad, 0x24, 0x68, 0x57, 0x12, 0xb4, 0x2f, 0x09, 0x3a, 0x94, 0x04, 0xfd, 0x28, + 0x09, 0xfa, 0xfe, 0x93, 0x18, 0x1f, 0x1f, 0xb6, 0xab, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xf3, + 0xe1, 0xde, 0x86, 0xdb, 0x02, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto index a9060bf96..83be99790 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.apimachinery.pkg.apis.meta.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go index 7b7c47d82..344c533e1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types.go @@ -66,8 +66,8 @@ type TableColumnDefinition struct { // TableRow is an individual row in a table. // +protobuf=false type TableRow struct { - // cells will be as wide as headers and may contain strings, numbers, booleans, simple maps, or lists, or - // null. See the type field of the column definition for a more detailed description. + // cells will be as wide as headers and may contain strings, numbers (float64 or int64), booleans, simple + // maps, or lists, or null. See the type field of the column definition for a more detailed description. Cells []interface{} `json:"cells"` // conditions describe additional status of a row that are relevant for a human user. // +optional diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go index 2680fbf7e..7394535d9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/types_swagger_doc_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,7 @@ package v1beta1 // // Those methods can be generated by using hack/update-generated-swagger-docs.sh -// AUTO-GENERATED FUNCTIONS START HERE +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. var map_PartialObjectMetadata = map[string]string{ "": "PartialObjectMetadata is a generic representation of any object with ObjectMeta. It allows clients to get access to a particular ObjectMeta schema without knowing the details of the version.", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", @@ -80,7 +80,7 @@ func (TableOptions) SwaggerDoc() map[string]string { var map_TableRow = map[string]string{ "": "TableRow is an individual row in a table.", - "cells": "cells will be as wide as headers and may contain strings, numbers, booleans, simple maps, or lists, or null. See the type field of the column definition for a more detailed description.", + "cells": "cells will be as wide as headers and may contain strings, numbers (float64 or int64), booleans, simple maps, or lists, or null. See the type field of the column definition for a more detailed description.", "conditions": "conditions describe additional status of a row that are relevant for a human user.", "object": "This field contains the requested additional information about each object based on the includeObject policy when requesting the Table. If \"None\", this field is empty, if \"Object\" this will be the default serialization of the object for the current API version, and if \"Metadata\" (the default) will contain the object metadata. Check the returned kind and apiVersion of the object before parsing.", } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.deepcopy.go index 226995a21..2e79a131f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.defaults.go index 544e569dc..73e63fc11 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/install/BUILD index 7e3e76d5d..c5d6e0d78 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/install/BUILD @@ -11,11 +11,10 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/apimachinery/pkg/apis/testapigroup/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/testapigroup:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/install/install.go index c7ada70f9..6fc079f51 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/apis/testapigroup" "k8s.io/apimachinery/pkg/apis/testapigroup/v1" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: testapigroup.GroupName, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: testapigroup.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(testapigroup.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.pb.go index 4ad2352e5..5fd3c3f97 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1938,72 +1938,71 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1062 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcf, 0x6e, 0xdb, 0xc6, - 0x13, 0x36, 0x2d, 0xc9, 0x96, 0xd6, 0x56, 0x62, 0x6f, 0x62, 0x80, 0x3f, 0x03, 0x91, 0x1c, 0x1f, - 0x0c, 0xff, 0x8a, 0x94, 0x8c, 0xdd, 0x26, 0x70, 0x9b, 0x43, 0x11, 0xda, 0x45, 0xed, 0xc2, 0x71, - 0x84, 0x95, 0x8b, 0x14, 0x45, 0x0f, 0x59, 0x51, 0x53, 0x99, 0x95, 0xc8, 0x25, 0x76, 0x97, 0x2a, - 0x74, 0x2b, 0xfa, 0x04, 0x7d, 0x88, 0xde, 0x7a, 0xee, 0x03, 0xf4, 0x50, 0xc0, 0xc7, 0x1c, 0x73, - 0x12, 0x6a, 0xf5, 0x2d, 0x7c, 0x2a, 0x76, 0xf9, 0x47, 0x94, 0xe5, 0xa8, 0x51, 0x6e, 0xdc, 0x99, - 0xef, 0xfb, 0x66, 0x76, 0x67, 0x38, 0x83, 0xbe, 0xe9, 0x1e, 0x08, 0xcb, 0x63, 0x76, 0x37, 0x6a, - 0x01, 0x0f, 0x40, 0x82, 0xb0, 0xfb, 0x10, 0xb4, 0x19, 0xb7, 0x13, 0x07, 0x0d, 0x3d, 0x9f, 0xba, - 0x17, 0x5e, 0x00, 0x7c, 0x60, 0x87, 0xdd, 0x8e, 0x32, 0x08, 0x5b, 0x82, 0x90, 0x34, 0xf4, 0x3a, - 0x9c, 0x45, 0xa1, 0xdd, 0xdf, 0xb3, 0x3b, 0x10, 0x00, 0xa7, 0x12, 0xda, 0x56, 0xc8, 0x99, 0x64, - 0xf8, 0x51, 0xcc, 0xb6, 0xf2, 0x6c, 0x2b, 0xec, 0x76, 0x94, 0x41, 0x58, 0x79, 0xb6, 0xd5, 0xdf, - 0xdb, 0xfc, 0xb8, 0xe3, 0xc9, 0x8b, 0xa8, 0x65, 0xb9, 0xcc, 0xb7, 0x3b, 0xac, 0xc3, 0x6c, 0x2d, - 0xd2, 0x8a, 0x7e, 0xd0, 0x27, 0x7d, 0xd0, 0x5f, 0xb1, 0xf8, 0xe6, 0xa7, 0x33, 0x53, 0xf3, 0x41, - 0xd2, 0x5b, 0x52, 0xda, 0x7c, 0xe7, 0x85, 0x78, 0x14, 0x48, 0xcf, 0x87, 0x29, 0xc2, 0xd3, 0xff, - 0x22, 0x08, 0xf7, 0x02, 0x7c, 0x3a, 0xc5, 0xfb, 0xe4, 0x5d, 0xbc, 0x48, 0x7a, 0x3d, 0xdb, 0x0b, - 0xa4, 0x90, 0xfc, 0x26, 0x69, 0xfb, 0xb7, 0x45, 0x54, 0x3c, 0xa4, 0x3c, 0xc4, 0xaf, 0x51, 0x59, - 0xdd, 0xa0, 0x4d, 0x25, 0x35, 0x8d, 0x2d, 0x63, 0x77, 0x65, 0xff, 0xb1, 0x35, 0xf3, 0x31, 0x15, - 0xda, 0xea, 0xef, 0x59, 0x2f, 0x5b, 0x3f, 0x82, 0x2b, 0x5f, 0x80, 0xa4, 0x0e, 0xbe, 0x1c, 0xd6, - 0x17, 0x46, 0xc3, 0x3a, 0x1a, 0xdb, 0x48, 0xa6, 0x8a, 0xbf, 0x45, 0x45, 0x11, 0x82, 0x6b, 0x2e, - 0x6a, 0xf5, 0xa7, 0xd6, 0x3c, 0xa5, 0xb2, 0x54, 0x8e, 0xcd, 0x10, 0x5c, 0x67, 0x35, 0x89, 0x51, - 0x54, 0x27, 0xa2, 0x15, 0xf1, 0x6b, 0xb4, 0x24, 0x24, 0x95, 0x91, 0x30, 0x0b, 0x5a, 0xfb, 0xe0, - 0x03, 0xb4, 0x35, 0xdf, 0xb9, 0x93, 0xa8, 0x2f, 0xc5, 0x67, 0x92, 0xe8, 0x6e, 0xff, 0x51, 0x40, - 0x55, 0x05, 0x3b, 0x64, 0x41, 0xdb, 0x93, 0x1e, 0x0b, 0xf0, 0x13, 0x54, 0x94, 0x83, 0x10, 0xf4, - 0x5b, 0x55, 0x9c, 0x87, 0x69, 0x56, 0xe7, 0x83, 0x10, 0xae, 0x87, 0xf5, 0xf5, 0x09, 0xb0, 0x32, - 0x12, 0x0d, 0xc7, 0x9f, 0x65, 0xa9, 0x2e, 0x4e, 0x10, 0x93, 0x80, 0xd7, 0xc3, 0xfa, 0xdd, 0x8c, - 0x36, 0x99, 0x03, 0xee, 0xa0, 0x6a, 0x8f, 0x0a, 0xd9, 0xe0, 0xac, 0x05, 0xe7, 0x9e, 0x0f, 0xc9, - 0x65, 0x3f, 0x7a, 0xbf, 0x32, 0x29, 0x86, 0xb3, 0x91, 0x44, 0xab, 0x9e, 0xe6, 0x85, 0xc8, 0xa4, - 0x2e, 0xee, 0x23, 0xac, 0x0c, 0xe7, 0x9c, 0x06, 0x22, 0xce, 0x5f, 0x45, 0x2b, 0xce, 0x1d, 0x6d, - 0x33, 0x89, 0x86, 0x4f, 0xa7, 0xd4, 0xc8, 0x2d, 0x11, 0xf0, 0x0e, 0x5a, 0xe2, 0x40, 0x05, 0x0b, - 0xcc, 0x92, 0x7e, 0x9b, 0xac, 0x18, 0x44, 0x5b, 0x49, 0xe2, 0xc5, 0xff, 0x47, 0xcb, 0x3e, 0x08, - 0x41, 0x3b, 0x60, 0x2e, 0x69, 0xe0, 0xdd, 0x04, 0xb8, 0xfc, 0x22, 0x36, 0x93, 0xd4, 0xbf, 0xfd, - 0xa7, 0x81, 0xca, 0xaa, 0x14, 0xa7, 0x9e, 0x90, 0xf8, 0xfb, 0xa9, 0x16, 0xb7, 0xde, 0xef, 0x36, - 0x8a, 0xad, 0x1b, 0x7c, 0x2d, 0x09, 0x54, 0x4e, 0x2d, 0xb9, 0xf6, 0x7e, 0x85, 0x4a, 0x9e, 0x04, - 0x5f, 0x15, 0xb6, 0xb0, 0xbb, 0xb2, 0xbf, 0x3f, 0x7f, 0x0f, 0x3a, 0xd5, 0x44, 0xbe, 0x74, 0xa2, - 0x84, 0x48, 0xac, 0xb7, 0xfd, 0xd7, 0x72, 0x7c, 0x07, 0xd5, 0xf0, 0xf8, 0x14, 0x55, 0xb9, 0xa2, - 0x72, 0xd9, 0x60, 0x3d, 0xcf, 0x1d, 0xe8, 0x26, 0xa8, 0x38, 0x3b, 0x69, 0x61, 0x49, 0xde, 0x79, - 0x7d, 0xd3, 0x40, 0x26, 0xc9, 0xb8, 0x83, 0x1e, 0x48, 0xe0, 0xbe, 0x17, 0x50, 0x55, 0x84, 0xaf, - 0x38, 0x75, 0xa1, 0x01, 0xdc, 0x63, 0xed, 0x26, 0xb8, 0x2c, 0x68, 0x0b, 0x5d, 0xf4, 0x82, 0xf3, - 0x70, 0x34, 0xac, 0x3f, 0x38, 0x9f, 0x05, 0x24, 0xb3, 0x75, 0xf0, 0x4b, 0xb4, 0x41, 0x5d, 0xe9, - 0xf5, 0xe1, 0x08, 0x68, 0xbb, 0xe7, 0x05, 0x90, 0x06, 0x28, 0xe9, 0x00, 0xff, 0x1b, 0x0d, 0xeb, - 0x1b, 0xcf, 0x6f, 0x03, 0x90, 0xdb, 0x79, 0xf8, 0x17, 0x03, 0xad, 0x06, 0xac, 0x0d, 0x4d, 0xe8, - 0x81, 0x2b, 0x19, 0x37, 0x97, 0xf5, 0xab, 0x1f, 0x7f, 0xd8, 0x54, 0xb1, 0xce, 0x72, 0x52, 0x5f, - 0x06, 0x92, 0x0f, 0x9c, 0xfb, 0xc9, 0x8b, 0xae, 0xe6, 0x5d, 0x64, 0x22, 0x26, 0xfe, 0x1a, 0x61, - 0x01, 0xbc, 0xef, 0xb9, 0xf0, 0xdc, 0x75, 0x59, 0x14, 0xc8, 0x33, 0xea, 0x83, 0x59, 0xd6, 0x15, - 0xc9, 0x9a, 0xbf, 0x39, 0x85, 0x20, 0xb7, 0xb0, 0xf0, 0x31, 0xba, 0x33, 0x69, 0x35, 0x2b, 0x5a, - 0x67, 0x2b, 0xd1, 0x31, 0x8f, 0x20, 0xe4, 0xe0, 0xaa, 0xd1, 0x3d, 0xa9, 0x48, 0x6e, 0xf0, 0xf0, - 0x23, 0x54, 0x56, 0x59, 0xea, 0x5c, 0x90, 0xd6, 0xc8, 0xda, 0xf6, 0x2c, 0xb1, 0x93, 0x0c, 0x81, - 0x9f, 0xa0, 0x95, 0x0b, 0x26, 0xe4, 0x19, 0xc8, 0x9f, 0x18, 0xef, 0x9a, 0x2b, 0x5b, 0xc6, 0x6e, - 0xd9, 0xb9, 0x97, 0x10, 0x56, 0x8e, 0xc7, 0x2e, 0x92, 0xc7, 0xa9, 0x7f, 0x50, 0x1d, 0x1b, 0x27, - 0x47, 0xe6, 0xaa, 0xa6, 0x64, 0xff, 0xe0, 0x71, 0x6c, 0x26, 0xa9, 0x3f, 0x85, 0x9e, 0x34, 0x0e, - 0xcd, 0xea, 0x34, 0xf4, 0xa4, 0x71, 0x48, 0x52, 0xbf, 0x4a, 0x5d, 0x7d, 0x06, 0x2a, 0xf5, 0xb5, - 0xc9, 0xd4, 0x8f, 0x13, 0x3b, 0xc9, 0x10, 0xd8, 0x46, 0x15, 0x11, 0xb5, 0xda, 0xcc, 0xa7, 0x5e, - 0x60, 0xae, 0x6b, 0xf8, 0x7a, 0x02, 0xaf, 0x34, 0x53, 0x07, 0x19, 0x63, 0xf0, 0x33, 0x54, 0x55, - 0xbb, 0xb3, 0x1d, 0xf5, 0x80, 0xeb, 0x18, 0xf7, 0x34, 0x29, 0x9b, 0x8a, 0xcd, 0xd4, 0xa9, 0xdf, - 0x68, 0x12, 0xbb, 0xf9, 0x05, 0x5a, 0x9f, 0xea, 0x12, 0xbc, 0x86, 0x0a, 0x5d, 0x18, 0xc4, 0x4b, - 0x80, 0xa8, 0x4f, 0x7c, 0x1f, 0x95, 0xfa, 0xb4, 0x17, 0x41, 0x3c, 0xdf, 0x49, 0x7c, 0xf8, 0x7c, - 0xf1, 0xc0, 0xd8, 0xfe, 0xbd, 0x80, 0xd0, 0x78, 0xd5, 0xe0, 0xc7, 0xa8, 0x14, 0x5e, 0x50, 0x91, - 0x6e, 0x90, 0xb4, 0x5f, 0x4a, 0x0d, 0x65, 0xbc, 0x1e, 0xd6, 0x2b, 0x0a, 0xab, 0x0f, 0x24, 0x06, - 0x62, 0x86, 0x90, 0x9b, 0xee, 0x86, 0x74, 0xcc, 0x3c, 0x9b, 0xbf, 0xe1, 0xb3, 0xfd, 0x32, 0xde, - 0xd7, 0x99, 0x49, 0x90, 0x5c, 0x88, 0xfc, 0xa0, 0x2d, 0xcc, 0x1e, 0xb4, 0xb9, 0xd9, 0x5d, 0x9c, - 0x39, 0xbb, 0x77, 0xd0, 0x52, 0x5c, 0xec, 0x9b, 0x33, 0x3e, 0xee, 0x05, 0x92, 0x78, 0x15, 0xce, - 0xa5, 0x3c, 0x3c, 0x69, 0x24, 0x23, 0x3e, 0xc3, 0x1d, 0x6a, 0x2b, 0x49, 0xbc, 0xf8, 0x15, 0xaa, - 0xe8, 0x81, 0xa6, 0x57, 0xd4, 0xf2, 0xdc, 0x2b, 0xaa, 0xaa, 0x7b, 0x25, 0x15, 0x20, 0x63, 0x2d, - 0x67, 0xf7, 0xf2, 0xaa, 0xb6, 0xf0, 0xe6, 0xaa, 0xb6, 0xf0, 0xf6, 0xaa, 0xb6, 0xf0, 0xf3, 0xa8, - 0x66, 0x5c, 0x8e, 0x6a, 0xc6, 0x9b, 0x51, 0xcd, 0x78, 0x3b, 0xaa, 0x19, 0x7f, 0x8f, 0x6a, 0xc6, - 0xaf, 0xff, 0xd4, 0x16, 0xbe, 0x5b, 0xec, 0xef, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xc2, 0xaa, - 0x9e, 0x7b, 0xcb, 0x0a, 0x00, 0x00, + // 1048 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xc1, 0x6e, 0xdb, 0x46, + 0x10, 0x35, 0x2d, 0xc9, 0x96, 0xd6, 0x56, 0x62, 0x6f, 0x62, 0x80, 0x35, 0x10, 0xc9, 0xf1, 0xc1, + 0x70, 0x8b, 0x94, 0x8a, 0x8d, 0x26, 0x70, 0x9b, 0x43, 0x11, 0xda, 0x45, 0xed, 0xc2, 0x71, 0x84, + 0x95, 0x8b, 0x14, 0x45, 0x0f, 0x59, 0x51, 0x53, 0x99, 0x95, 0xc8, 0x25, 0x76, 0x57, 0x2a, 0x74, + 0x2b, 0xfa, 0x05, 0xfd, 0x88, 0xde, 0x7a, 0xee, 0x07, 0xf4, 0x50, 0xc0, 0xc7, 0x1c, 0x73, 0x12, + 0x6a, 0xf5, 0x2f, 0x7c, 0x2a, 0x76, 0xb9, 0xa4, 0x28, 0xcb, 0x55, 0xa2, 0xdc, 0xb8, 0x33, 0xef, + 0xbd, 0x99, 0xdd, 0x19, 0xce, 0xa0, 0x6f, 0x3b, 0x07, 0xc2, 0xf1, 0x59, 0xad, 0xd3, 0x6b, 0x02, + 0x0f, 0x41, 0x82, 0xa8, 0xf5, 0x21, 0x6c, 0x31, 0x5e, 0x33, 0x0e, 0x1a, 0xf9, 0x01, 0xf5, 0x2e, + 0xfc, 0x10, 0xf8, 0xa0, 0x16, 0x75, 0xda, 0xca, 0x20, 0x6a, 0x12, 0x84, 0xa4, 0x91, 0xdf, 0xe6, + 0xac, 0x17, 0xd5, 0xfa, 0x7b, 0xb5, 0x36, 0x84, 0xc0, 0xa9, 0x84, 0x96, 0x13, 0x71, 0x26, 0x19, + 0x7e, 0x14, 0xb3, 0x9d, 0x2c, 0xdb, 0x89, 0x3a, 0x6d, 0x65, 0x10, 0x4e, 0x96, 0xed, 0xf4, 0xf7, + 0x36, 0x3f, 0x6d, 0xfb, 0xf2, 0xa2, 0xd7, 0x74, 0x3c, 0x16, 0xd4, 0xda, 0xac, 0xcd, 0x6a, 0x5a, + 0xa4, 0xd9, 0xfb, 0x51, 0x9f, 0xf4, 0x41, 0x7f, 0xc5, 0xe2, 0x9b, 0x9f, 0xcd, 0x4c, 0x2d, 0x00, + 0x49, 0x6f, 0x49, 0x69, 0xf3, 0x7f, 0x2f, 0xc4, 0x7b, 0xa1, 0xf4, 0x03, 0x98, 0x22, 0x3c, 0x7d, + 0x17, 0x41, 0x78, 0x17, 0x10, 0xd0, 0x9b, 0xbc, 0xed, 0xdf, 0x17, 0x51, 0xfe, 0x90, 0xf2, 0x08, + 0xbf, 0x46, 0x45, 0x95, 0x4c, 0x8b, 0x4a, 0x6a, 0x5b, 0x5b, 0xd6, 0xee, 0xca, 0xfe, 0x63, 0x67, + 0xe6, 0xbb, 0x28, 0xb4, 0xd3, 0xdf, 0x73, 0x5e, 0x36, 0x7f, 0x02, 0x4f, 0xbe, 0x00, 0x49, 0x5d, + 0x7c, 0x39, 0xac, 0x2e, 0x8c, 0x86, 0x55, 0x34, 0xb6, 0x91, 0x54, 0x15, 0x7f, 0x87, 0xf2, 0x22, + 0x02, 0xcf, 0x5e, 0xd4, 0xea, 0x4f, 0x9d, 0x79, 0x5e, 0xdd, 0x51, 0x39, 0x36, 0x22, 0xf0, 0xdc, + 0x55, 0x13, 0x23, 0xaf, 0x4e, 0x44, 0x2b, 0xe2, 0xd7, 0x68, 0x49, 0x48, 0x2a, 0x7b, 0xc2, 0xce, + 0x69, 0xed, 0x83, 0x0f, 0xd0, 0xd6, 0x7c, 0xf7, 0x8e, 0x51, 0x5f, 0x8a, 0xcf, 0xc4, 0xe8, 0x6e, + 0xff, 0x99, 0x43, 0x65, 0x05, 0x3b, 0x64, 0x61, 0xcb, 0x97, 0x3e, 0x0b, 0xf1, 0x13, 0x94, 0x97, + 0x83, 0x08, 0xf4, 0x5b, 0x95, 0xdc, 0x87, 0x49, 0x56, 0xe7, 0x83, 0x08, 0xae, 0x87, 0xd5, 0xf5, + 0x09, 0xb0, 0x32, 0x12, 0x0d, 0xc7, 0x9f, 0xa7, 0xa9, 0x2e, 0x4e, 0x10, 0x4d, 0xc0, 0xeb, 0x61, + 0xf5, 0x6e, 0x4a, 0x9b, 0xcc, 0x01, 0xb7, 0x51, 0xb9, 0x4b, 0x85, 0xac, 0x73, 0xd6, 0x84, 0x73, + 0x3f, 0x00, 0x73, 0xd9, 0x4f, 0xde, 0xaf, 0x4c, 0x8a, 0xe1, 0x6e, 0x98, 0x68, 0xe5, 0xd3, 0xac, + 0x10, 0x99, 0xd4, 0xc5, 0x7d, 0x84, 0x95, 0xe1, 0x9c, 0xd3, 0x50, 0xc4, 0xf9, 0xab, 0x68, 0xf9, + 0xb9, 0xa3, 0x6d, 0x9a, 0x68, 0xf8, 0x74, 0x4a, 0x8d, 0xdc, 0x12, 0x01, 0xef, 0xa0, 0x25, 0x0e, + 0x54, 0xb0, 0xd0, 0x2e, 0xe8, 0xb7, 0x49, 0x8b, 0x41, 0xb4, 0x95, 0x18, 0x2f, 0xfe, 0x18, 0x2d, + 0x07, 0x20, 0x04, 0x6d, 0x83, 0xbd, 0xa4, 0x81, 0x77, 0x0d, 0x70, 0xf9, 0x45, 0x6c, 0x26, 0x89, + 0x7f, 0xfb, 0x2f, 0x0b, 0x15, 0x55, 0x29, 0x4e, 0x7d, 0x21, 0xf1, 0x0f, 0x53, 0x2d, 0xee, 0xbc, + 0xdf, 0x6d, 0x14, 0x5b, 0x37, 0xf8, 0x9a, 0x09, 0x54, 0x4c, 0x2c, 0x99, 0xf6, 0x7e, 0x85, 0x0a, + 0xbe, 0x84, 0x40, 0x15, 0x36, 0xb7, 0xbb, 0xb2, 0xbf, 0x3f, 0x7f, 0x0f, 0xba, 0x65, 0x23, 0x5f, + 0x38, 0x51, 0x42, 0x24, 0xd6, 0xdb, 0xfe, 0x7b, 0x39, 0xbe, 0x83, 0x6a, 0x78, 0x7c, 0x8a, 0xca, + 0x5c, 0x51, 0xb9, 0xac, 0xb3, 0xae, 0xef, 0x0d, 0x74, 0x13, 0x94, 0xdc, 0x9d, 0xa4, 0xb0, 0x24, + 0xeb, 0xbc, 0xbe, 0x69, 0x20, 0x93, 0x64, 0xdc, 0x46, 0x0f, 0x24, 0xf0, 0xc0, 0x0f, 0xa9, 0x2a, + 0xc2, 0xd7, 0x9c, 0x7a, 0x50, 0x07, 0xee, 0xb3, 0x56, 0x03, 0x3c, 0x16, 0xb6, 0x84, 0x2e, 0x7a, + 0xce, 0x7d, 0x38, 0x1a, 0x56, 0x1f, 0x9c, 0xcf, 0x02, 0x92, 0xd9, 0x3a, 0xf8, 0x25, 0xda, 0xa0, + 0x9e, 0xf4, 0xfb, 0x70, 0x04, 0xb4, 0xd5, 0xf5, 0x43, 0x48, 0x02, 0x14, 0x74, 0x80, 0x8f, 0x46, + 0xc3, 0xea, 0xc6, 0xf3, 0xdb, 0x00, 0xe4, 0x76, 0x1e, 0xfe, 0xd5, 0x42, 0xab, 0x21, 0x6b, 0x41, + 0x03, 0xba, 0xe0, 0x49, 0xc6, 0xed, 0x65, 0xfd, 0xea, 0xc7, 0x1f, 0x36, 0x55, 0x9c, 0xb3, 0x8c, + 0xd4, 0x57, 0xa1, 0xe4, 0x03, 0xf7, 0xbe, 0x79, 0xd1, 0xd5, 0xac, 0x8b, 0x4c, 0xc4, 0xc4, 0xdf, + 0x20, 0x2c, 0x80, 0xf7, 0x7d, 0x0f, 0x9e, 0x7b, 0x1e, 0xeb, 0x85, 0xf2, 0x8c, 0x06, 0x60, 0x17, + 0x75, 0x45, 0xd2, 0xe6, 0x6f, 0x4c, 0x21, 0xc8, 0x2d, 0x2c, 0x7c, 0x8c, 0xee, 0x4c, 0x5a, 0xed, + 0x92, 0xd6, 0xd9, 0x32, 0x3a, 0xf6, 0x11, 0x44, 0x1c, 0x3c, 0x35, 0xba, 0x27, 0x15, 0xc9, 0x0d, + 0x1e, 0x7e, 0x84, 0x8a, 0x2a, 0x4b, 0x9d, 0x0b, 0xd2, 0x1a, 0x69, 0xdb, 0x9e, 0x19, 0x3b, 0x49, + 0x11, 0xf8, 0x09, 0x5a, 0xb9, 0x60, 0x42, 0x9e, 0x81, 0xfc, 0x99, 0xf1, 0x8e, 0xbd, 0xb2, 0x65, + 0xed, 0x16, 0xdd, 0x7b, 0x86, 0xb0, 0x72, 0x3c, 0x76, 0x91, 0x2c, 0x4e, 0xfd, 0x83, 0xea, 0x58, + 0x3f, 0x39, 0xb2, 0x57, 0x35, 0x25, 0xfd, 0x07, 0x8f, 0x63, 0x33, 0x49, 0xfc, 0x09, 0xf4, 0xa4, + 0x7e, 0x68, 0x97, 0xa7, 0xa1, 0x27, 0xf5, 0x43, 0x92, 0xf8, 0x55, 0xea, 0xea, 0x33, 0x54, 0xa9, + 0xaf, 0x4d, 0xa6, 0x7e, 0x6c, 0xec, 0x24, 0x45, 0xe0, 0x1a, 0x2a, 0x89, 0x5e, 0xb3, 0xc5, 0x02, + 0xea, 0x87, 0xf6, 0xba, 0x86, 0xaf, 0x1b, 0x78, 0xa9, 0x91, 0x38, 0xc8, 0x18, 0x83, 0x9f, 0xa1, + 0xb2, 0x5a, 0x83, 0xad, 0x5e, 0x17, 0xb8, 0x8e, 0x71, 0x4f, 0x93, 0xd2, 0xa9, 0xd8, 0x48, 0x9c, + 0xfa, 0x8d, 0x26, 0xb1, 0x9b, 0x5f, 0xa2, 0xf5, 0xa9, 0x2e, 0xc1, 0x6b, 0x28, 0xd7, 0x81, 0x41, + 0xbc, 0x04, 0x88, 0xfa, 0xc4, 0xf7, 0x51, 0xa1, 0x4f, 0xbb, 0x3d, 0x88, 0xe7, 0x3b, 0x89, 0x0f, + 0x5f, 0x2c, 0x1e, 0x58, 0xdb, 0x7f, 0xe4, 0x10, 0x1a, 0xaf, 0x1a, 0xfc, 0x18, 0x15, 0xa2, 0x0b, + 0x2a, 0x92, 0x0d, 0x92, 0xf4, 0x4b, 0xa1, 0xae, 0x8c, 0xd7, 0xc3, 0x6a, 0x49, 0x61, 0xf5, 0x81, + 0xc4, 0x40, 0xcc, 0x10, 0xf2, 0x92, 0xdd, 0x90, 0x8c, 0x99, 0x67, 0xf3, 0x37, 0x7c, 0xba, 0x5f, + 0xc6, 0xfb, 0x3a, 0x35, 0x09, 0x92, 0x09, 0x91, 0x1d, 0xb4, 0xb9, 0xd9, 0x83, 0x36, 0x33, 0xbb, + 0xf3, 0x33, 0x67, 0xf7, 0x0e, 0x5a, 0x8a, 0x8b, 0x7d, 0x73, 0xc6, 0xc7, 0xbd, 0x40, 0x8c, 0x57, + 0xe1, 0x3c, 0xca, 0xa3, 0x93, 0xba, 0x19, 0xf1, 0x29, 0xee, 0x50, 0x5b, 0x89, 0xf1, 0xe2, 0x57, + 0xa8, 0xa4, 0x07, 0x9a, 0x5e, 0x51, 0xcb, 0x73, 0xaf, 0xa8, 0xb2, 0xee, 0x95, 0x44, 0x80, 0x8c, + 0xb5, 0xdc, 0xdd, 0xcb, 0xab, 0xca, 0xc2, 0x9b, 0xab, 0xca, 0xc2, 0xdb, 0xab, 0xca, 0xc2, 0x2f, + 0xa3, 0x8a, 0x75, 0x39, 0xaa, 0x58, 0x6f, 0x46, 0x15, 0xeb, 0xed, 0xa8, 0x62, 0xfd, 0x33, 0xaa, + 0x58, 0xbf, 0xfd, 0x5b, 0x59, 0xf8, 0x7e, 0xb1, 0xbf, 0xf7, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xd7, 0x22, 0x1b, 0x36, 0x96, 0x0a, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.proto index 70f3408d9..0b058c5f7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.apimachinery.pkg.apis.testapigroup.v1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.conversion.go index 117a75f32..33d8012c2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.deepcopy.go index 4b2a9b4f4..ec9acd61a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/zz_generated.deepcopy.go index 341030abd..e107585e3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go index 17b366617..b3804aa42 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go @@ -174,6 +174,9 @@ func convertStruct(result url.Values, st reflect.Type, sv reflect.Value) { kind = ft.Kind() if !field.IsNil() { field = reflect.Indirect(field) + // If the field is non-nil, it should be added to params + // and the omitempty should be overwite to false + omitempty = false } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert_test.go index b075debf1..1eed5e1fe 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert_test.go @@ -70,6 +70,7 @@ type childStructs struct { Follow bool `json:"follow,omitempty"` Previous bool `json:"previous,omitempty"` SinceSeconds *int64 `json:"sinceSeconds,omitempty"` + TailLines *int64 `json:"tailLines,omitempty"` SinceTime *metav1.Time `json:"sinceTime,omitempty"` EmptyTime *metav1.Time `json:"emptyTime"` NonPointerTime metav1.Time `json:"nonPointerTime"` @@ -99,6 +100,7 @@ func validateResult(t *testing.T, input interface{}, actual, expected url.Values func TestConvert(t *testing.T) { sinceSeconds := int64(123) + tailLines := int64(0) sinceTime := metav1.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC) tests := []struct { @@ -182,6 +184,7 @@ func TestConvert(t *testing.T) { Follow: true, Previous: true, SinceSeconds: &sinceSeconds, + TailLines: nil, SinceTime: &sinceTime, // test a custom marshaller EmptyTime: nil, // test a nil custom marshaller without omitempty NonPointerTime: sinceTime, @@ -194,10 +197,11 @@ func TestConvert(t *testing.T) { Follow: true, Previous: true, SinceSeconds: &sinceSeconds, + TailLines: &tailLines, SinceTime: nil, // test a nil custom marshaller with omitempty NonPointerTime: sinceTime, }, - expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "emptyTime": {""}, "nonPointerTime": {"2000-01-01T12:34:56Z"}}, + expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "tailLines": {"0"}, "emptyTime": {""}, "nonPointerTime": {"2000-01-01T12:34:56Z"}}, }, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/fields/selector.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/fields/selector.go index 3785d8c2f..e3e4453b6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/fields/selector.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/fields/selector.go @@ -55,6 +55,21 @@ type Selector interface { DeepCopySelector() Selector } +type nothingSelector struct{} + +func (n nothingSelector) Matches(_ Fields) bool { return false } +func (n nothingSelector) Empty() bool { return false } +func (n nothingSelector) String() string { return "" } +func (n nothingSelector) Requirements() Requirements { return nil } +func (n nothingSelector) DeepCopySelector() Selector { return n } +func (n nothingSelector) RequiresExactMatch(field string) (value string, found bool) { return "", false } +func (n nothingSelector) Transform(fn TransformFunc) (Selector, error) { return n, nil } + +// Nothing returns a selector that matches no fields +func Nothing() Selector { + return nothingSelector{} +} + // Everything returns a selector that matches all fields. func Everything() Selector { return andTerm{} @@ -449,6 +464,12 @@ func OneTermEqualSelector(k, v string) Selector { return &hasTerm{field: k, value: v} } +// OneTermNotEqualSelector returns an object that matches objects where one field/field does not equal one value. +// Cannot return an error. +func OneTermNotEqualSelector(k, v string) Selector { + return ¬HasTerm{field: k, value: v} +} + // AndSelectors creates a selector that is the logical AND of all the given selectors func AndSelectors(selectors ...Selector) Selector { return andTerm(selectors) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/selector.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/selector.go index b301b4284..374d2ef13 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/selector.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/selector.go @@ -166,7 +166,6 @@ func NewRequirement(key string, op selection.Operator, vals []string) (*Requirem return nil, err } } - sort.Strings(vals) return &Requirement{key: key, operator: op, strValues: vals}, nil } @@ -299,7 +298,9 @@ func (r *Requirement) String() string { if len(r.strValues) == 1 { buffer.WriteString(r.strValues[0]) } else { // only > 1 since == 0 prohibited by NewRequirement - buffer.WriteString(strings.Join(r.strValues, ",")) + // normalizes value order on output, without mutating the in-memory selector representation + // also avoids normalization when it is not required, and ensures we do not mutate shared data + buffer.WriteString(strings.Join(safeSort(r.strValues), ",")) } switch r.operator { @@ -309,6 +310,17 @@ func (r *Requirement) String() string { return buffer.String() } +// safeSort sort input strings without modification +func safeSort(in []string) []string { + if sort.StringsAreSorted(in) { + return in + } + out := make([]string, len(in)) + copy(out, in) + sort.Strings(out) + return out +} + // Add adds requirements to the selector. It copies the current selector returning a new one func (lsel internalSelector) Add(reqs ...Requirement) Selector { var sel internalSelector diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/selector_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/selector_test.go index 995317bd1..a2702989b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/selector_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/selector_test.go @@ -573,3 +573,47 @@ func TestAdd(t *testing.T) { } } } + +func TestSafeSort(t *testing.T) { + tests := []struct { + name string + in []string + inCopy []string + want []string + }{ + { + name: "nil strings", + in: nil, + inCopy: nil, + want: nil, + }, + { + name: "ordered strings", + in: []string{"bar", "foo"}, + inCopy: []string{"bar", "foo"}, + want: []string{"bar", "foo"}, + }, + { + name: "unordered strings", + in: []string{"foo", "bar"}, + inCopy: []string{"foo", "bar"}, + want: []string{"bar", "foo"}, + }, + { + name: "duplicated strings", + in: []string{"foo", "bar", "foo", "bar"}, + inCopy: []string{"foo", "bar", "foo", "bar"}, + want: []string{"bar", "bar", "foo", "foo"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := safeSort(tt.in); !reflect.DeepEqual(got, tt.want) { + t.Errorf("safeSort() = %v, want %v", got, tt.want) + } + if !reflect.DeepEqual(tt.in, tt.inCopy) { + t.Errorf("after safeSort(), input = %v, want %v", tt.in, tt.inCopy) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go index a536f9ec9..4d482947f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/BUILD index 7a53fbc41..a2c2eb308 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/BUILD @@ -8,8 +8,15 @@ load( go_test( name = "go_default_test", - srcs = ["swagger_doc_generator_test.go"], + srcs = [ + "local_scheme_test.go", + "swagger_doc_generator_test.go", + ], embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", + ], ) go_library( @@ -44,6 +51,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go index f6f7c10de..291d7a4e8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go @@ -73,7 +73,6 @@ var ( mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{}) stringType = reflect.TypeOf(string("")) int64Type = reflect.TypeOf(int64(0)) - uint64Type = reflect.TypeOf(uint64(0)) float64Type = reflect.TypeOf(float64(0)) boolType = reflect.TypeOf(bool(false)) fieldCache = newFieldsCache() @@ -411,8 +410,7 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte var u map[string]interface{} var err error if unstr, ok := obj.(Unstructured); ok { - // UnstructuredContent() mutates the object so we need to make a copy first - u = unstr.DeepCopyObject().(Unstructured).UnstructuredContent() + u = unstr.UnstructuredContent() } else { t := reflect.TypeOf(obj) value := reflect.ValueOf(obj) @@ -439,22 +437,32 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte } // DeepCopyJSON deep copies the passed value, assuming it is a valid JSON representation i.e. only contains -// types produced by json.Unmarshal(). +// types produced by json.Unmarshal() and also int64. +// bool, int64, float64, string, []interface{}, map[string]interface{}, json.Number and nil func DeepCopyJSON(x map[string]interface{}) map[string]interface{} { return DeepCopyJSONValue(x).(map[string]interface{}) } // DeepCopyJSONValue deep copies the passed value, assuming it is a valid JSON representation i.e. only contains -// types produced by json.Unmarshal(). +// types produced by json.Unmarshal() and also int64. +// bool, int64, float64, string, []interface{}, map[string]interface{}, json.Number and nil func DeepCopyJSONValue(x interface{}) interface{} { switch x := x.(type) { case map[string]interface{}: + if x == nil { + // Typed nil - an interface{} that contains a type map[string]interface{} with a value of nil + return x + } clone := make(map[string]interface{}, len(x)) for k, v := range x { clone[k] = DeepCopyJSONValue(v) } return clone case []interface{}: + if x == nil { + // Typed nil - an interface{} that contains a type []interface{} with a value of nil + return x + } clone := make([]interface{}, len(x)) for i, v := range x { clone[i] = DeepCopyJSONValue(v) @@ -584,10 +592,14 @@ func toUnstructured(sv, dv reflect.Value) error { dv.Set(reflect.ValueOf(sv.Int())) return nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + uVal := sv.Uint() + if uVal > math.MaxInt64 { + return fmt.Errorf("unsigned value %d does not fit into int64 (overflow)", uVal) + } if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 { - dv.Set(reflect.New(uint64Type)) + dv.Set(reflect.New(int64Type)) } - dv.Set(reflect.ValueOf(sv.Uint())) + dv.Set(reflect.ValueOf(int64(uVal))) return nil case reflect.Float32, reflect.Float64: if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/error.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/error.go index 86b24840f..778796602 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/error.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/error.go @@ -41,10 +41,18 @@ func NewNotRegisteredErrForTarget(t reflect.Type, target GroupVersioner) error { return ¬RegisteredErr{t: t, target: target} } +func NewNotRegisteredGVKErrForTarget(gvk schema.GroupVersionKind, target GroupVersioner) error { + return ¬RegisteredErr{gvk: gvk, target: target} +} + func (k *notRegisteredErr) Error() string { if k.t != nil && k.target != nil { return fmt.Sprintf("%v is not suitable for converting to %q", k.t, k.target) } + nullGVK := schema.GroupVersionKind{} + if k.gvk != nullGVK && k.target != nil { + return fmt.Sprintf("%q is not suitable for converting to %q", k.gvk.GroupVersion(), k.target) + } if k.t != nil { return fmt.Sprintf("no kind is registered for the type %v", k.t) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/generated.pb.go index f561fd476..967e0f530 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -744,30 +744,29 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 395 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0x4f, 0x6f, 0xd3, 0x30, - 0x18, 0xc6, 0xe3, 0xb5, 0x52, 0x87, 0x5b, 0x69, 0xc8, 0x1c, 0x08, 0x3b, 0x38, 0x53, 0x4f, 0xec, - 0x30, 0x5b, 0x1a, 0x42, 0xe2, 0xba, 0x4c, 0x93, 0x40, 0x08, 0x09, 0x59, 0xfc, 0x91, 0x38, 0xe1, - 0x26, 0x26, 0xb3, 0x42, 0x5f, 0x47, 0x8e, 0x43, 0xd8, 0x8d, 0x8f, 0xc0, 0xc7, 0xea, 0x71, 0xc7, - 0x9e, 0x2a, 0x1a, 0x3e, 0x04, 0x57, 0x54, 0xd7, 0x2d, 0xa5, 0x08, 0xed, 0x16, 0xbf, 0xcf, 0xf3, - 0x7b, 0xde, 0xe7, 0x0d, 0x7e, 0x5e, 0x3e, 0xab, 0x99, 0x36, 0xbc, 0x6c, 0x26, 0xca, 0x82, 0x72, - 0xaa, 0xe6, 0x5f, 0x14, 0xe4, 0xc6, 0xf2, 0x20, 0xc8, 0x4a, 0x4f, 0x65, 0x76, 0xad, 0x41, 0xd9, - 0x1b, 0x5e, 0x95, 0x05, 0xb7, 0x0d, 0x38, 0x3d, 0x55, 0xbc, 0x50, 0xa0, 0xac, 0x74, 0x2a, 0x67, - 0x95, 0x35, 0xce, 0x90, 0x64, 0x0d, 0xb0, 0x5d, 0x80, 0x55, 0x65, 0xc1, 0x02, 0x70, 0x7c, 0x56, - 0x68, 0x77, 0xdd, 0x4c, 0x58, 0x66, 0xa6, 0xbc, 0x30, 0x85, 0xe1, 0x9e, 0x9b, 0x34, 0x9f, 0xfc, - 0xcb, 0x3f, 0xfc, 0xd7, 0x3a, 0xef, 0xf8, 0xc9, 0xff, 0x0a, 0x34, 0x4e, 0x7f, 0xe6, 0x1a, 0x5c, - 0xed, 0xec, 0x7e, 0x89, 0xf1, 0x29, 0x1e, 0x09, 0xd9, 0x5e, 0x7d, 0x75, 0x0a, 0x6a, 0x6d, 0x80, - 0x3c, 0xc2, 0x3d, 0x2b, 0xdb, 0x18, 0x9d, 0xa0, 0xc7, 0xa3, 0x74, 0xd0, 0x2d, 0x92, 0x9e, 0x90, - 0xad, 0x58, 0xcd, 0xc6, 0x1f, 0xf1, 0xe1, 0x9b, 0x9b, 0x4a, 0xbd, 0x52, 0x4e, 0x92, 0x73, 0x8c, - 0x65, 0xa5, 0xdf, 0x29, 0xbb, 0x82, 0xbc, 0xfb, 0x5e, 0x4a, 0x66, 0x8b, 0x24, 0xea, 0x16, 0x09, - 0xbe, 0x78, 0xfd, 0x22, 0x28, 0x62, 0xc7, 0x45, 0x4e, 0x70, 0xbf, 0xd4, 0x90, 0xc7, 0x07, 0xde, - 0x3d, 0x0a, 0xee, 0xfe, 0x4b, 0x0d, 0xb9, 0xf0, 0xca, 0xf8, 0x17, 0xc2, 0x83, 0xb7, 0x50, 0x82, - 0x69, 0x81, 0xbc, 0xc7, 0x87, 0x2e, 0x6c, 0xf3, 0xf9, 0xc3, 0xf3, 0x53, 0x76, 0xc7, 0x0f, 0x63, - 0x9b, 0x7a, 0xe9, 0xfd, 0x10, 0xbe, 0x2d, 0x2c, 0xb6, 0x61, 0x9b, 0x0b, 0x0f, 0xfe, 0xbd, 0x90, - 0x5c, 0xe0, 0xa3, 0xcc, 0x80, 0x53, 0xe0, 0xae, 0x20, 0x33, 0xb9, 0x86, 0x22, 0xee, 0xf9, 0xb2, - 0x0f, 0x43, 0xde, 0xd1, 0xe5, 0xdf, 0xb2, 0xd8, 0xf7, 0x93, 0xa7, 0x78, 0x18, 0x46, 0xab, 0xd5, - 0x71, 0xdf, 0xe3, 0x0f, 0x02, 0x3e, 0xbc, 0xfc, 0x23, 0x89, 0x5d, 0x5f, 0x7a, 0x36, 0x5b, 0xd2, - 0xe8, 0x76, 0x49, 0xa3, 0xf9, 0x92, 0x46, 0xdf, 0x3a, 0x8a, 0x66, 0x1d, 0x45, 0xb7, 0x1d, 0x45, - 0xf3, 0x8e, 0xa2, 0x1f, 0x1d, 0x45, 0xdf, 0x7f, 0xd2, 0xe8, 0xc3, 0x20, 0x1c, 0xfa, 0x3b, 0x00, - 0x00, 0xff, 0xff, 0x3f, 0x1e, 0x24, 0x09, 0x85, 0x02, 0x00, 0x00, + // 378 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x8f, 0x4f, 0xab, 0x13, 0x31, + 0x14, 0xc5, 0x27, 0xaf, 0x85, 0x3e, 0xd3, 0xc2, 0x93, 0xb8, 0x70, 0x74, 0x91, 0x79, 0x74, 0xe5, + 0x5b, 0xbc, 0x04, 0x1e, 0x08, 0x6e, 0x3b, 0xa5, 0xa0, 0x88, 0x20, 0xc1, 0x3f, 0xe0, 0xca, 0x74, + 0x26, 0x4e, 0xc3, 0xd0, 0x9b, 0x21, 0xcd, 0x38, 0x76, 0xe7, 0x47, 0xf0, 0x63, 0x75, 0xd9, 0x65, + 0x57, 0xc5, 0x8e, 0x1f, 0xc2, 0xad, 0x34, 0x4d, 0x6b, 0xd5, 0x85, 0xbb, 0xe4, 0x9e, 0xf3, 0x3b, + 0xf7, 0x1e, 0xfc, 0xbc, 0x7c, 0xb6, 0x60, 0xda, 0xf0, 0xb2, 0x9e, 0x2a, 0x0b, 0xca, 0xa9, 0x05, + 0xff, 0xac, 0x20, 0x37, 0x96, 0x07, 0x41, 0x56, 0x7a, 0x2e, 0xb3, 0x99, 0x06, 0x65, 0x97, 0xbc, + 0x2a, 0x0b, 0x6e, 0x6b, 0x70, 0x7a, 0xae, 0x78, 0xa1, 0x40, 0x59, 0xe9, 0x54, 0xce, 0x2a, 0x6b, + 0x9c, 0x21, 0xc9, 0x01, 0x60, 0xe7, 0x00, 0xab, 0xca, 0x82, 0x05, 0xe0, 0xf1, 0x6d, 0xa1, 0xdd, + 0xac, 0x9e, 0xb2, 0xcc, 0xcc, 0x79, 0x61, 0x0a, 0xc3, 0x3d, 0x37, 0xad, 0x3f, 0xf9, 0x9f, 0xff, + 0xf8, 0xd7, 0x21, 0x6f, 0x78, 0x83, 0x07, 0x42, 0x36, 0x93, 0x2f, 0x4e, 0xc1, 0x42, 0x1b, 0x20, + 0x8f, 0x70, 0xc7, 0xca, 0x26, 0x46, 0xd7, 0xe8, 0xc9, 0x20, 0xed, 0xb5, 0xdb, 0xa4, 0x23, 0x64, + 0x23, 0xf6, 0xb3, 0xe1, 0x47, 0x7c, 0xf9, 0x66, 0x59, 0xa9, 0x57, 0xca, 0x49, 0x72, 0x87, 0xb1, + 0xac, 0xf4, 0x3b, 0x65, 0xf7, 0x90, 0x77, 0xdf, 0x4b, 0xc9, 0x6a, 0x9b, 0x44, 0xed, 0x36, 0xc1, + 0xa3, 0xd7, 0x2f, 0x82, 0x22, 0xce, 0x5c, 0xe4, 0x1a, 0x77, 0x4b, 0x0d, 0x79, 0x7c, 0xe1, 0xdd, + 0x83, 0xe0, 0xee, 0xbe, 0xd4, 0x90, 0x0b, 0xaf, 0x0c, 0x7f, 0x22, 0xdc, 0x7b, 0x0b, 0x25, 0x98, + 0x06, 0xc8, 0x7b, 0x7c, 0xe9, 0xc2, 0x36, 0x9f, 0xdf, 0xbf, 0xbb, 0x61, 0xff, 0xe9, 0xce, 0x8e, + 0xe7, 0xa5, 0xf7, 0x43, 0xf8, 0xe9, 0x60, 0x71, 0x0a, 0x3b, 0x36, 0xbc, 0xf8, 0xb7, 0x21, 0x19, + 0xe1, 0xab, 0xcc, 0x80, 0x53, 0xe0, 0x26, 0x90, 0x99, 0x5c, 0x43, 0x11, 0x77, 0xfc, 0xb1, 0x0f, + 0x43, 0xde, 0xd5, 0xf8, 0x4f, 0x59, 0xfc, 0xed, 0x27, 0x4f, 0x71, 0x3f, 0x8c, 0xf6, 0xab, 0xe3, + 0xae, 0xc7, 0x1f, 0x04, 0xbc, 0x3f, 0xfe, 0x2d, 0x89, 0x73, 0x5f, 0x7a, 0xbb, 0xda, 0xd1, 0x68, + 0xbd, 0xa3, 0xd1, 0x66, 0x47, 0xa3, 0xaf, 0x2d, 0x45, 0xab, 0x96, 0xa2, 0x75, 0x4b, 0xd1, 0xa6, + 0xa5, 0xe8, 0x7b, 0x4b, 0xd1, 0xb7, 0x1f, 0x34, 0xfa, 0xd0, 0x0b, 0x45, 0x7f, 0x05, 0x00, 0x00, + 0xff, 0xff, 0xe3, 0x33, 0x18, 0x0b, 0x50, 0x02, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/generated.proto index 02e388e90..fb61ac96a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,8 +21,6 @@ syntax = 'proto2'; package k8s.io.apimachinery.pkg.runtime; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - // Package-wide variables from generator "generated". option go_package = "runtime"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go index 9d00f1650..ba48e6146 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go @@ -174,13 +174,16 @@ type ObjectVersioner interface { // ObjectConvertor converts an object to a different version. type ObjectConvertor interface { - // Convert attempts to convert one object into another, or returns an error. This method does - // not guarantee the in object is not mutated. The context argument will be passed to - // all nested conversions. + // Convert attempts to convert one object into another, or returns an error. This + // method does not mutate the in object, but the in and out object might share data structures, + // i.e. the out object cannot be mutated without mutating the in object as well. + // The context argument will be passed to all nested conversions. Convert(in, out, context interface{}) error // ConvertToVersion takes the provided object and converts it the provided version. This - // method does not guarantee that the in object is not mutated. This method is similar to - // Convert() but handles specific details of choosing the correct output version. + // method does not mutate the in object, but the in and out object might share data structures, + // i.e. the out object cannot be mutated without mutating the in object as well. + // This method is similar to Convert() but handles specific details of choosing the correct + // output version. ConvertToVersion(in Object, gv GroupVersioner) (out Object, err error) ConvertFieldLabel(version, kind, label, value string) (string, string, error) } @@ -234,9 +237,9 @@ type Object interface { // to JSON allowed. type Unstructured interface { Object - // UnstructuredContent returns a non-nil, mutable map of the contents of this object. Values may be + // UnstructuredContent returns a non-nil map with this object's contents. Values may be // []interface{}, map[string]interface{}, or any primitive type. Contents are typically serialized to - // and from JSON. + // and from JSON. SetUnstructuredContent should be used to mutate the contents. UnstructuredContent() map[string]interface{} // SetUnstructuredContent updates the object content to match the provided map. SetUnstructuredContent(map[string]interface{}) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/local_scheme_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/local_scheme_test.go new file mode 100644 index 000000000..45a0dde5e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/local_scheme_test.go @@ -0,0 +1,150 @@ +/* +Copyright 2018 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 runtime + +import ( + "testing" + + "reflect" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/diff" +) + +func TestPreferredVersionsAllGroups(t *testing.T) { + tests := []struct { + name string + versionPriority map[string][]string + observedVersions []schema.GroupVersion + expectedPrioritized map[string][]schema.GroupVersion + expectedPreferred map[schema.GroupVersion]bool + }{ + { + name: "observedOnly", + observedVersions: []schema.GroupVersion{ + {Group: "", Version: "v3"}, + {Group: "foo", Version: "v1"}, + {Group: "foo", Version: "v2"}, + {Group: "", Version: "v1"}, + }, + expectedPrioritized: map[string][]schema.GroupVersion{ + "": { + {Group: "", Version: "v3"}, + {Group: "", Version: "v1"}, + }, + "foo": { + {Group: "foo", Version: "v1"}, + {Group: "foo", Version: "v2"}, + }, + }, + expectedPreferred: map[schema.GroupVersion]bool{ + {Group: "", Version: "v3"}: true, + {Group: "foo", Version: "v1"}: true, + }, + }, + { + name: "specifiedOnly", + versionPriority: map[string][]string{ + "": {"v3", "v1"}, + "foo": {"v1", "v2"}, + }, + expectedPrioritized: map[string][]schema.GroupVersion{ + "": { + {Group: "", Version: "v3"}, + {Group: "", Version: "v1"}, + }, + "foo": { + {Group: "foo", Version: "v1"}, + {Group: "foo", Version: "v2"}, + }, + }, + expectedPreferred: map[schema.GroupVersion]bool{ + {Group: "", Version: "v3"}: true, + {Group: "foo", Version: "v1"}: true, + }, + }, + { + name: "both", + versionPriority: map[string][]string{ + "": {"v3", "v1"}, + "foo": {"v1", "v2"}, + }, + observedVersions: []schema.GroupVersion{ + {Group: "", Version: "v1"}, + {Group: "", Version: "v3"}, + {Group: "", Version: "v4"}, + {Group: "", Version: "v5"}, + {Group: "bar", Version: "v1"}, + {Group: "bar", Version: "v2"}, + }, + expectedPrioritized: map[string][]schema.GroupVersion{ + "": { + {Group: "", Version: "v3"}, + {Group: "", Version: "v1"}, + {Group: "", Version: "v4"}, + {Group: "", Version: "v5"}, + }, + "foo": { + {Group: "foo", Version: "v1"}, + {Group: "foo", Version: "v2"}, + }, + "bar": { + {Group: "bar", Version: "v1"}, + {Group: "bar", Version: "v2"}, + }, + }, + expectedPreferred: map[schema.GroupVersion]bool{ + {Group: "", Version: "v3"}: true, + {Group: "foo", Version: "v1"}: true, + {Group: "bar", Version: "v1"}: true, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + scheme := NewScheme() + scheme.versionPriority = test.versionPriority + scheme.observedVersions = test.observedVersions + + for group, expected := range test.expectedPrioritized { + actual := scheme.PrioritizedVersionsForGroup(group) + if !reflect.DeepEqual(expected, actual) { + t.Error(diff.ObjectDiff(expected, actual)) + } + } + + prioritizedAll := scheme.PrioritizedVersionsAllGroups() + actualPrioritizedAll := map[string][]schema.GroupVersion{} + for _, actual := range prioritizedAll { + actualPrioritizedAll[actual.Group] = append(actualPrioritizedAll[actual.Group], actual) + } + if !reflect.DeepEqual(test.expectedPrioritized, actualPrioritizedAll) { + t.Error(diff.ObjectDiff(test.expectedPrioritized, actualPrioritizedAll)) + } + + preferredAll := scheme.PreferredVersionAllGroups() + actualPreferredAll := map[schema.GroupVersion]bool{} + for _, actual := range preferredAll { + actualPreferredAll[actual] = true + } + if !reflect.DeepEqual(test.expectedPreferred, actualPreferredAll) { + t.Error(diff.ObjectDiff(test.expectedPreferred, actualPreferredAll)) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go index 5357628ad..5c9934c73 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,12 +19,12 @@ limitations under the License. // DO NOT EDIT! /* - Package schema is a generated protocol buffer package. +Package schema is a generated protocol buffer package. - It is generated from these files: - k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto +It is generated from these files: + k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto - It has these top-level messages: +It has these top-level messages: */ package schema @@ -48,18 +48,17 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 202 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0xce, 0xaf, 0x4e, 0x04, 0x31, - 0x10, 0xc7, 0xf1, 0xd6, 0x20, 0x90, 0xc8, 0x13, 0x23, 0x51, 0xd0, 0x11, 0x18, 0x34, 0x2f, 0x80, - 0xc7, 0x75, 0xf7, 0x86, 0x6e, 0x53, 0xfa, 0x27, 0xed, 0x94, 0x04, 0xc7, 0x23, 0xf0, 0x58, 0x27, - 0x4f, 0xae, 0x64, 0xcb, 0x8b, 0x90, 0xb4, 0x2b, 0x08, 0xc9, 0xb9, 0xfe, 0xd2, 0x7c, 0x26, 0xdf, - 0xeb, 0x67, 0xf7, 0x58, 0x94, 0x8d, 0xe8, 0xea, 0x44, 0x39, 0x10, 0x53, 0xc1, 0x77, 0x0a, 0xc7, - 0x98, 0x71, 0xff, 0xd0, 0xc9, 0x7a, 0x3d, 0x2f, 0x36, 0x50, 0xfe, 0xc0, 0xe4, 0x0c, 0xe6, 0x1a, - 0xd8, 0x7a, 0xc2, 0x32, 0x2f, 0xe4, 0x35, 0x1a, 0x0a, 0x94, 0x35, 0xd3, 0x51, 0xa5, 0x1c, 0x39, - 0xde, 0xdc, 0x0e, 0xa7, 0xfe, 0x3a, 0x95, 0x9c, 0x51, 0xbb, 0x53, 0xc3, 0x1d, 0xee, 0x8d, 0xe5, - 0xa5, 0x4e, 0x6a, 0x8e, 0x1e, 0x4d, 0x34, 0x11, 0x3b, 0x9f, 0xea, 0x6b, 0x5f, 0x7d, 0xf4, 0xd7, - 0x38, 0x7b, 0x78, 0xb8, 0x94, 0x53, 0xd9, 0xbe, 0xa1, 0x0d, 0x5c, 0x38, 0xff, 0x6f, 0x79, 0xba, - 0x3b, 0x6d, 0x20, 0xce, 0x1b, 0x88, 0x75, 0x03, 0xf1, 0xd9, 0x40, 0x9e, 0x1a, 0xc8, 0x73, 0x03, - 0xb9, 0x36, 0x90, 0xdf, 0x0d, 0xe4, 0xd7, 0x0f, 0x88, 0x97, 0xab, 0x51, 0xf4, 0x1b, 0x00, 0x00, - 0xff, 0xff, 0xfd, 0x59, 0x57, 0x93, 0x0b, 0x01, 0x00, 0x00, + // 185 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0xcc, 0xaf, 0x6e, 0xc3, 0x30, + 0x10, 0xc7, 0x71, 0x9b, 0x0c, 0x0c, 0x0e, 0x0e, 0x1c, 0x1c, 0xda, 0x7c, 0x74, 0xb8, 0x2f, 0x50, + 0x5e, 0xe6, 0x24, 0x57, 0xc7, 0xb2, 0xfc, 0x47, 0x8e, 0x5d, 0xa9, 0xac, 0x8f, 0xd0, 0xc7, 0x0a, + 0x0c, 0x0c, 0x6c, 0xdc, 0x17, 0xa9, 0x64, 0x07, 0x94, 0xdd, 0x4f, 0xa7, 0xcf, 0xf7, 0xf3, 0x68, + 0xfe, 0x27, 0xa1, 0x3d, 0x9a, 0xdc, 0x51, 0x74, 0x94, 0x68, 0xc2, 0x0b, 0xb9, 0xc1, 0x47, 0xdc, + 0x1f, 0x32, 0x68, 0x2b, 0xfb, 0x51, 0x3b, 0x8a, 0x57, 0x0c, 0x46, 0x61, 0xcc, 0x2e, 0x69, 0x4b, + 0x38, 0xf5, 0x23, 0x59, 0x89, 0x8a, 0x1c, 0x45, 0x99, 0x68, 0x10, 0x21, 0xfa, 0xe4, 0xbf, 0x7e, + 0x9a, 0x13, 0xef, 0x4e, 0x04, 0xa3, 0xc4, 0xee, 0x44, 0x73, 0xdf, 0x7f, 0x4a, 0xa7, 0x31, 0x77, + 0xa2, 0xf7, 0x16, 0x95, 0x57, 0x1e, 0x2b, 0xef, 0xf2, 0xb9, 0xae, 0x3a, 0xea, 0xd5, 0xb2, 0x87, + 0xdf, 0x79, 0x03, 0xb6, 0x6c, 0xc0, 0xd6, 0x0d, 0xd8, 0xad, 0x00, 0x9f, 0x0b, 0xf0, 0xa5, 0x00, + 0x5f, 0x0b, 0xf0, 0x47, 0x01, 0x7e, 0x7f, 0x02, 0x3b, 0x7d, 0xb4, 0xf8, 0x2b, 0x00, 0x00, 0xff, + 0xff, 0xba, 0x7e, 0x65, 0xf4, 0xd6, 0x00, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/generated.proto index 50c2f2a63..5aeeaa100 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,8 +21,6 @@ syntax = 'proto2'; package k8s.io.apimachinery.pkg.runtime.schema; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - // Package-wide variables from generator "generated". option go_package = "schema"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/group_version_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/group_version_test.go index 51f26df7f..3934bc45a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/group_version_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/schema/group_version_test.go @@ -134,3 +134,47 @@ func TestKindForGroupVersionKinds(t *testing.T) { } } } + +func TestParseKindArg(t *testing.T) { + tests := []struct { + input string + gvk *GroupVersionKind + gk GroupKind + }{ + {input: "Pod", gk: GroupKind{Kind: "Pod"}}, + {input: ".apps", gk: GroupKind{Group: "apps"}}, + {input: "Pod.", gk: GroupKind{Kind: "Pod"}}, + {input: "StatefulSet.apps", gk: GroupKind{Group: "apps", Kind: "StatefulSet"}}, + {input: "StatefulSet.v1.apps", gvk: &GroupVersionKind{Group: "apps", Version: "v1", Kind: "StatefulSet"}, gk: GroupKind{Group: "v1.apps", Kind: "StatefulSet"}}, + } + for i, test := range tests { + t.Run(test.input, func(t *testing.T) { + gvk, gk := ParseKindArg(test.input) + if (gvk != nil && test.gvk == nil) || (gvk == nil && test.gvk != nil) || (test.gvk != nil && *gvk != *test.gvk) { + t.Errorf("%d: expected output: %#v, got: %#v", i, test.gvk, gvk) + } + if gk != test.gk { + t.Errorf("%d: expected output: %#v, got: %#v", i, test.gk, gk) + } + }) + } +} + +func TestParseGroupKind(t *testing.T) { + tests := []struct { + input string + out GroupKind + }{ + {input: "Pod", out: GroupKind{Kind: "Pod"}}, + {input: ".StatefulSet", out: GroupKind{Group: "StatefulSet"}}, + {input: "StatefulSet.apps", out: GroupKind{Group: "apps", Kind: "StatefulSet"}}, + } + for i, test := range tests { + t.Run(test.input, func(t *testing.T) { + out := ParseGroupKind(test.input) + if out != test.out { + t.Errorf("%d: expected output: %#v, got: %#v", i, test.out, out) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go index 3d94a3041..59163d777 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go @@ -21,8 +21,11 @@ import ( "net/url" "reflect" + "strings" + "k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/sets" ) // Scheme defines methods for serializing and deserializing API objects, a type @@ -68,6 +71,13 @@ type Scheme struct { // converter stores all registered conversion functions. It also has // default coverting behavior. converter *conversion.Converter + + // versionPriority is a map of groups to ordered lists of versions for those groups indicating the + // default priorities of these versions as registered in the scheme + versionPriority map[string][]string + + // observedVersions keeps track of the order we've seen versions during type registration + observedVersions []schema.GroupVersion } // Function to convert a field selector to internal representation. @@ -82,6 +92,7 @@ func NewScheme() *Scheme { unversionedKinds: map[string]reflect.Type{}, fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{}, defaulterFuncs: map[reflect.Type]func(interface{}){}, + versionPriority: map[string][]string{}, } s.converter = conversion.NewConverter(s.nameFunc) @@ -111,7 +122,7 @@ func (s *Scheme) nameFunc(t reflect.Type) string { for _, gvk := range gvks { internalGV := gvk.GroupVersion() - internalGV.Version = "__internal" // this is hacky and maybe should be passed in + internalGV.Version = APIVersionInternal // this is hacky and maybe should be passed in internalGVK := internalGV.WithKind(gvk.Kind) if internalType, exists := s.gvkToType[internalGVK]; exists { @@ -141,6 +152,7 @@ func (s *Scheme) Converter() *conversion.Converter { // TODO: there is discussion about removing unversioned and replacing it with objects that are manifest into // every version with particular schemas. Resolve this method at that point. func (s *Scheme) AddUnversionedTypes(version schema.GroupVersion, types ...Object) { + s.addObservedVersion(version) s.AddKnownTypes(version, types...) for _, obj := range types { t := reflect.TypeOf(obj).Elem() @@ -158,6 +170,7 @@ func (s *Scheme) AddUnversionedTypes(version schema.GroupVersion, types ...Objec // the struct becomes the "kind" field when encoding. Version may not be empty - use the // APIVersionInternal constant if you have a type that does not have a formal version. func (s *Scheme) AddKnownTypes(gv schema.GroupVersion, types ...Object) { + s.addObservedVersion(gv) for _, obj := range types { t := reflect.TypeOf(obj) if t.Kind() != reflect.Ptr { @@ -173,6 +186,7 @@ func (s *Scheme) AddKnownTypes(gv schema.GroupVersion, types ...Object) { // your structs. Version may not be empty - use the APIVersionInternal constant if you have a // type that does not have a formal version. func (s *Scheme) AddKnownTypeWithName(gvk schema.GroupVersionKind, obj Object) { + s.addObservedVersion(gvk.GroupVersion()) t := reflect.TypeOf(obj) if len(gvk.Version) == 0 { panic(fmt.Sprintf("version is required on all types: %s %v", gvk, t)) @@ -620,3 +634,133 @@ func setTargetKind(obj Object, kind schema.GroupVersionKind) { } obj.GetObjectKind().SetGroupVersionKind(kind) } + +// SetVersionPriority allows specifying a precise order of priority. All specified versions must be in the same group, +// and the specified order overwrites any previously specified order for this group +func (s *Scheme) SetVersionPriority(versions ...schema.GroupVersion) error { + groups := sets.String{} + order := []string{} + for _, version := range versions { + if len(version.Version) == 0 || version.Version == APIVersionInternal { + return fmt.Errorf("internal versions cannot be prioritized: %v", version) + } + + groups.Insert(version.Group) + order = append(order, version.Version) + } + if len(groups) != 1 { + return fmt.Errorf("must register versions for exactly one group: %v", strings.Join(groups.List(), ", ")) + } + + s.versionPriority[groups.List()[0]] = order + return nil +} + +// PrioritizedVersionsForGroup returns versions for a single group in priority order +func (s *Scheme) PrioritizedVersionsForGroup(group string) []schema.GroupVersion { + ret := []schema.GroupVersion{} + for _, version := range s.versionPriority[group] { + ret = append(ret, schema.GroupVersion{Group: group, Version: version}) + } + for _, observedVersion := range s.observedVersions { + if observedVersion.Group != group { + continue + } + found := false + for _, existing := range ret { + if existing == observedVersion { + found = true + break + } + } + if !found { + ret = append(ret, observedVersion) + } + } + + return ret +} + +// PrioritizedVersionsAllGroups returns all known versions in their priority order. Groups are random, but +// versions for a single group are prioritized +func (s *Scheme) PrioritizedVersionsAllGroups() []schema.GroupVersion { + ret := []schema.GroupVersion{} + for group, versions := range s.versionPriority { + for _, version := range versions { + ret = append(ret, schema.GroupVersion{Group: group, Version: version}) + } + } + for _, observedVersion := range s.observedVersions { + found := false + for _, existing := range ret { + if existing == observedVersion { + found = true + break + } + } + if !found { + ret = append(ret, observedVersion) + } + } + return ret +} + +// PreferredVersionAllGroups returns the most preferred version for every group. +// group ordering is random. +func (s *Scheme) PreferredVersionAllGroups() []schema.GroupVersion { + ret := []schema.GroupVersion{} + for group, versions := range s.versionPriority { + for _, version := range versions { + ret = append(ret, schema.GroupVersion{Group: group, Version: version}) + break + } + } + for _, observedVersion := range s.observedVersions { + found := false + for _, existing := range ret { + if existing.Group == observedVersion.Group { + found = true + break + } + } + if !found { + ret = append(ret, observedVersion) + } + } + + return ret +} + +// IsGroupRegistered returns true if types for the group have been registered with the scheme +func (s *Scheme) IsGroupRegistered(group string) bool { + for _, observedVersion := range s.observedVersions { + if observedVersion.Group == group { + return true + } + } + return false +} + +// IsVersionRegistered returns true if types for the version have been registered with the scheme +func (s *Scheme) IsVersionRegistered(version schema.GroupVersion) bool { + for _, observedVersion := range s.observedVersions { + if observedVersion == version { + return true + } + } + + return false +} + +func (s *Scheme) addObservedVersion(version schema.GroupVersion) { + if len(version.Version) == 0 || version.Version == APIVersionInternal { + return + } + for _, observedVersion := range s.observedVersions { + if observedVersion == version { + return + } + } + + s.observedVersions = append(s.observedVersions, version) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/BUILD index bc4cf8ec1..663050b22 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/BUILD @@ -8,12 +8,16 @@ load( go_test( name = "go_default_test", - srcs = ["codec_test.go"], + srcs = [ + "codec_test.go", + "sparse_test.go", + ], embed = [":go_default_library"], deps = [ "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/github.com/google/gofuzz:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/equality: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/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go index 2b795b5b8..068d3f708 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go @@ -75,11 +75,6 @@ func init() { case jsoniter.NumberValue: var number json.Number iter.ReadVal(&number) - u64, err := strconv.ParseUint(string(number), 10, 64) - if err == nil { - *(*interface{})(ptr) = u64 - return - } i64, err := strconv.ParseInt(string(number), 10, 64) if err == nil { *(*interface{})(ptr) = i64 @@ -98,6 +93,20 @@ func init() { jsoniter.RegisterTypeDecoderFunc("interface {}", decodeNumberAsInt64IfPossible) } +// CaseSensitiveJsonIterator returns a jsoniterator API that's configured to be +// case-sensitive when unmarshalling, and otherwise compatible with +// the encoding/json standard library. +func CaseSensitiveJsonIterator() jsoniter.API { + return jsoniter.Config{ + EscapeHTML: true, + SortMapKeys: true, + ValidateJsonRawMessage: true, + CaseSensitive: true, + }.Froze() +} + +var caseSensitiveJsonIterator = CaseSensitiveJsonIterator() + // gvkWithDefaults returns group kind and version defaulting from provided default func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind { if len(actual.Kind) == 0 { @@ -162,7 +171,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i types, _, err := s.typer.ObjectKinds(into) switch { case runtime.IsNotRegisteredError(err), isUnstructured: - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, into); err != nil { + if err := caseSensitiveJsonIterator.Unmarshal(data, into); err != nil { return nil, actual, err } return into, actual, nil @@ -186,7 +195,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i return nil, actual, err } - if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, obj); err != nil { + if err := caseSensitiveJsonIterator.Unmarshal(data, obj); err != nil { return nil, actual, err } return obj, actual, nil @@ -195,7 +204,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i // Encode serializes the provided object to the given writer. func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error { if s.yaml { - json, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(obj) + json, err := caseSensitiveJsonIterator.Marshal(obj) if err != nil { return err } @@ -208,7 +217,7 @@ func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error { } if s.pretty { - data, err := jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent(obj, "", " ") + data, err := caseSensitiveJsonIterator.MarshalIndent(obj, "", " ") if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go index c8ae5550c..b3d629a06 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json/json_test.go @@ -30,10 +30,31 @@ import ( type testDecodable struct { Other string - Value int `json:"value"` + Value int `json:"value"` + Spec DecodableSpec `json:"spec"` gvk schema.GroupVersionKind } +// DecodableSpec has 15 fields. json-iterator treats struct with more than 10 +// fields differently from struct that has less than 10 fields. +type DecodableSpec struct { + A int `json:"A"` + B int `json:"B"` + C int `json:"C"` + D int `json:"D"` + E int `json:"E"` + F int `json:"F"` + G int `json:"G"` + H int `json:"h"` + I int `json:"i"` + J int `json:"j"` + K int `json:"k"` + L int `json:"l"` + M int `json:"m"` + N int `json:"n"` + O int `json:"o"` +} + func (d *testDecodable) GetObjectKind() schema.ObjectKind { return d } func (d *testDecodable) SetGroupVersionKind(gvk schema.GroupVersionKind) { d.gvk = gvk } func (d *testDecodable) GroupVersionKind() schema.GroupVersionKind { return d.gvk } @@ -221,6 +242,28 @@ func TestDecode(t *testing.T) { }, }, }, + // Unmarshalling is case-sensitive + { + // "VaLue" should have been "value" + data: []byte(`{"kind":"Test","apiVersion":"other/blah","VaLue":1,"Other":"test"}`), + into: &testDecodable{}, + typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})}, + expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, + expectedObject: &testDecodable{ + Other: "test", + }, + }, + // Unmarshalling is case-sensitive for big struct. + { + // "b" should have been "B", "I" should have been "i" + data: []byte(`{"kind":"Test","apiVersion":"other/blah","spec": {"A": 1, "b": 2, "h": 3, "I": 4}}`), + into: &testDecodable{}, + typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})}, + expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, + expectedObject: &testDecodable{ + Spec: DecodableSpec{A: 1, H: 3}, + }, + }, } for i, test := range testCases { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/sparse_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/sparse_test.go new file mode 100644 index 000000000..3bc9d13bb --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/sparse_test.go @@ -0,0 +1,91 @@ +/* +Copyright 2018 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 serializer + +import ( + "testing" + + "k8s.io/apimachinery/pkg/api/equality" + 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" +) + +type FakeV1Obj struct { + metav1.TypeMeta + metav1.ObjectMeta +} + +func (*FakeV1Obj) DeepCopyObject() runtime.Object { + panic("not supported") +} + +type FakeV2DifferentObj struct { + metav1.TypeMeta + metav1.ObjectMeta +} + +func (*FakeV2DifferentObj) DeepCopyObject() runtime.Object { + panic("not supported") +} +func TestSparse(t *testing.T) { + v1 := schema.GroupVersion{Group: "mygroup", Version: "v1"} + v2 := schema.GroupVersion{Group: "mygroup", Version: "v2"} + + scheme := runtime.NewScheme() + scheme.AddKnownTypes(v1, &FakeV1Obj{}) + scheme.AddKnownTypes(v2, &FakeV2DifferentObj{}) + codecs := NewCodecFactory(scheme) + + srcObj1 := &FakeV1Obj{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + srcObj2 := &FakeV2DifferentObj{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + + encoder := codecs.LegacyCodec(v2, v1) + decoder := codecs.UniversalDecoder(v2, v1) + + srcObj1Bytes, err := runtime.Encode(encoder, srcObj1) + if err != nil { + t.Fatal(err) + } + t.Log(string(srcObj1Bytes)) + srcObj2Bytes, err := runtime.Encode(encoder, srcObj2) + if err != nil { + t.Fatal(err) + } + t.Log(string(srcObj2Bytes)) + + uncastDstObj1, err := runtime.Decode(decoder, srcObj1Bytes) + if err != nil { + t.Fatal(err) + } + uncastDstObj2, err := runtime.Decode(decoder, srcObj2Bytes) + if err != nil { + t.Fatal(err) + } + + // clear typemeta + uncastDstObj1.(*FakeV1Obj).TypeMeta = metav1.TypeMeta{} + uncastDstObj2.(*FakeV2DifferentObj).TypeMeta = metav1.TypeMeta{} + + if !equality.Semantic.DeepEqual(srcObj1, uncastDstObj1) { + t.Fatal(diff.ObjectDiff(srcObj1, uncastDstObj1)) + } + if !equality.Semantic.DeepEqual(srcObj2, uncastDstObj2) { + t.Fatal(diff.ObjectDiff(srcObj2, uncastDstObj2)) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/testing/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/testing/zz_generated.deepcopy.go index 200e92468..8796679dc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/testing/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/testing/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/BUILD index 32e6863c9..95aa6d961 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/BUILD @@ -22,6 +22,7 @@ go_library( srcs = ["versioning.go"], importpath = "k8s.io/apimachinery/pkg/runtime/serializer/versioning", deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go index b717fe8fe..7716cc421 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go @@ -19,6 +19,7 @@ package versioning import ( "io" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -166,9 +167,27 @@ func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into ru // Encode ensures the provided object is output in the appropriate group and version, invoking // conversion if necessary. Unversioned objects (according to the ObjectTyper) are output as is. func (c *codec) Encode(obj runtime.Object, w io.Writer) error { - switch obj.(type) { - case *runtime.Unknown, runtime.Unstructured: + switch obj := obj.(type) { + case *runtime.Unknown: return c.encoder.Encode(obj, w) + case runtime.Unstructured: + // An unstructured list can contain objects of multiple group version kinds. don't short-circuit just + // because the top-level type matches our desired destination type. actually send the object to the converter + // to give it a chance to convert the list items if needed. + if _, ok := obj.(*unstructured.UnstructuredList); !ok { + // avoid conversion roundtrip if GVK is the right one already or is empty (yes, this is a hack, but the old behaviour we rely on in kubectl) + objGVK := obj.GetObjectKind().GroupVersionKind() + if len(objGVK.Version) == 0 { + return c.encoder.Encode(obj, w) + } + targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK}) + if !ok { + return runtime.NewNotRegisteredGVKErrForTarget(objGVK, c.encodeVersion) + } + if targetGVK == objGVK { + return c.encoder.Encode(obj, w) + } + } } gvks, isUnversioned, err := c.typer.ObjectKinds(obj) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go index 43c242657..f79b2a7cb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go @@ -129,25 +129,25 @@ func TestDecode(t *testing.T) { }{ { serializer: &mockSerializer{actual: gvk1}, - convertor: &checkConvertor{groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}}, + convertor: &checkConvertor{groupVersion: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}}, expectedGVK: gvk1, - decodes: schema.GroupVersion{Group: "other", Version: "__internal"}, + decodes: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}, }, { serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}}, + convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}}, expectedGVK: gvk1, sameObject: decodable2, - decodes: schema.GroupVersion{Group: "other", Version: "__internal"}, + decodes: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}, }, // defaultGVK.Group is allowed to force a conversion to the destination group { serializer: &mockSerializer{actual: gvk1, obj: decodable1}, defaultGVK: &schema.GroupVersionKind{Group: "force"}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "force", Version: "__internal"}}, + convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "force", Version: runtime.APIVersionInternal}}, expectedGVK: gvk1, sameObject: decodable2, - decodes: schema.GroupVersion{Group: "force", Version: "__internal"}, + decodes: schema.GroupVersion{Group: "force", Version: runtime.APIVersionInternal}, }, // uses direct conversion for into when objects differ { @@ -184,10 +184,10 @@ func TestDecode(t *testing.T) { into: &runtime.VersionedObjects{Objects: []runtime.Object{}}, serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}}, + convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}}, expectedGVK: gvk1, expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1, decodable2}}, - decodes: schema.GroupVersion{Group: "other", Version: "__internal"}, + decodes: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}, }, // decode into the same version as the serialized object diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/testing/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/testing/types.go index 0694e7011..b8d67061d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/testing/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/testing/types.go @@ -263,7 +263,7 @@ func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { func (obj *Unstructured) UnstructuredContent() map[string]interface{} { if obj.Object == nil { - obj.Object = make(map[string]interface{}) + return make(map[string]interface{}) } return obj.Object } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/testing/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/testing/zz_generated.deepcopy.go index 787bffe56..957cbf9ee 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/testing/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/testing/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go index ba89cd235..167de6104 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/test/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/test/zz_generated.deepcopy.go index 1a080acc7..6cdf98394 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/test/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/test/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/types/namespacedname.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/types/namespacedname.go index 1e2130da0..88f0de36d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/types/namespacedname.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/types/namespacedname.go @@ -18,7 +18,6 @@ package types import ( "fmt" - "strings" ) // NamespacedName comprises a resource name, with a mandatory namespace, @@ -42,19 +41,3 @@ const ( func (n NamespacedName) String() string { return fmt.Sprintf("%s%c%s", n.Namespace, Separator, n.Name) } - -// NewNamespacedNameFromString parses the provided string and returns a NamespacedName. -// The expected format is as per String() above. -// If the input string is invalid, the returned NamespacedName has all empty string field values. -// This allows a single-value return from this function, while still allowing error checks in the caller. -// Note that an input string which does not include exactly one Separator is not a valid input (as it could never -// have neem returned by String() ) -func NewNamespacedNameFromString(s string) NamespacedName { - nn := NamespacedName{} - result := strings.Split(s, string(Separator)) - if len(result) == 2 { - nn.Namespace = result[0] - nn.Name = result[1] - } - return nn -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/clock/clock.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/clock/clock.go index c303a212a..9567f9006 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/clock/clock.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/clock/clock.go @@ -26,18 +26,12 @@ import ( type Clock interface { Now() time.Time Since(time.Time) time.Duration - After(d time.Duration) <-chan time.Time - NewTimer(d time.Duration) Timer - Sleep(d time.Duration) - Tick(d time.Duration) <-chan time.Time + After(time.Duration) <-chan time.Time + NewTimer(time.Duration) Timer + Sleep(time.Duration) + NewTicker(time.Duration) Ticker } -var ( - _ = Clock(RealClock{}) - _ = Clock(&FakeClock{}) - _ = Clock(&IntervalClock{}) -) - // RealClock really calls time.Now() type RealClock struct{} @@ -62,8 +56,10 @@ func (RealClock) NewTimer(d time.Duration) Timer { } } -func (RealClock) Tick(d time.Duration) <-chan time.Time { - return time.Tick(d) +func (RealClock) NewTicker(d time.Duration) Ticker { + return &realTicker{ + ticker: time.NewTicker(d), + } } func (RealClock) Sleep(d time.Duration) { @@ -137,7 +133,7 @@ func (f *FakeClock) NewTimer(d time.Duration) Timer { return timer } -func (f *FakeClock) Tick(d time.Duration) <-chan time.Time { +func (f *FakeClock) NewTicker(d time.Duration) Ticker { f.lock.Lock() defer f.lock.Unlock() tickTime := f.time.Add(d) @@ -149,7 +145,9 @@ func (f *FakeClock) Tick(d time.Duration) <-chan time.Time { destChan: ch, }) - return ch + return &fakeTicker{ + c: ch, + } } // Move clock by Duration, notify anyone that's called After, Tick, or NewTimer @@ -242,8 +240,8 @@ func (*IntervalClock) NewTimer(d time.Duration) Timer { // Unimplemented, will panic. // TODO: make interval clock use FakeClock so this can be implemented. -func (*IntervalClock) Tick(d time.Duration) <-chan time.Time { - panic("IntervalClock doesn't implement Tick") +func (*IntervalClock) NewTicker(d time.Duration) Ticker { + panic("IntervalClock doesn't implement NewTicker") } func (*IntervalClock) Sleep(d time.Duration) { @@ -258,11 +256,6 @@ type Timer interface { Reset(d time.Duration) bool } -var ( - _ = Timer(&realTimer{}) - _ = Timer(&fakeTimer{}) -) - // realTimer is backed by an actual time.Timer. type realTimer struct { timer *time.Timer @@ -325,3 +318,31 @@ func (f *fakeTimer) Reset(d time.Duration) bool { return active } + +type Ticker interface { + C() <-chan time.Time + Stop() +} + +type realTicker struct { + ticker *time.Ticker +} + +func (t *realTicker) C() <-chan time.Time { + return t.ticker.C +} + +func (t *realTicker) Stop() { + t.ticker.Stop() +} + +type fakeTicker struct { + c <-chan time.Time +} + +func (t *fakeTicker) C() <-chan time.Time { + return t.c +} + +func (t *fakeTicker) Stop() { +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/clock/clock_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/clock/clock_test.go index 27d34605f..c7b371fc6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/clock/clock_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/clock/clock_test.go @@ -21,6 +21,18 @@ import ( "time" ) +var ( + _ = Clock(RealClock{}) + _ = Clock(&FakeClock{}) + _ = Clock(&IntervalClock{}) + + _ = Timer(&realTimer{}) + _ = Timer(&fakeTimer{}) + + _ = Ticker(&realTicker{}) + _ = Ticker(&fakeTicker{}) +) + func TestFakeClock(t *testing.T) { startTime := time.Now() tc := NewFakeClock(startTime) @@ -110,13 +122,13 @@ func TestFakeTick(t *testing.T) { if tc.HasWaiters() { t.Errorf("unexpected waiter?") } - oneSec := tc.Tick(time.Second) + oneSec := tc.NewTicker(time.Second).C() if !tc.HasWaiters() { t.Errorf("unexpected lack of waiter?") } - oneOhOneSec := tc.Tick(time.Second + time.Millisecond) - twoSec := tc.Tick(2 * time.Second) + oneOhOneSec := tc.NewTicker(time.Second + time.Millisecond).C() + twoSec := tc.NewTicker(2 * time.Second).C() select { case <-oneSec: t.Errorf("unexpected channel read") diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/diff/diff.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/diff/diff.go index 3d5ec14bf..bce95baf1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/diff/diff.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/diff/diff.go @@ -89,20 +89,52 @@ func ObjectReflectDiff(a, b interface{}) string { } out := []string{""} for _, d := range diffs { + elidedA, elidedB := limit(d.a, d.b, 80) out = append(out, fmt.Sprintf("%s:", d.path), - limit(fmt.Sprintf(" a: %#v", d.a), 80), - limit(fmt.Sprintf(" b: %#v", d.b), 80), + fmt.Sprintf(" a: %s", elidedA), + fmt.Sprintf(" b: %s", elidedB), ) } return strings.Join(out, "\n") } -func limit(s string, max int) string { - if len(s) > max { - return s[:max] +// limit: +// 1. stringifies aObj and bObj +// 2. elides identical prefixes if either is too long +// 3. elides remaining content from the end if either is too long +func limit(aObj, bObj interface{}, max int) (string, string) { + elidedPrefix := "" + elidedASuffix := "" + elidedBSuffix := "" + a, b := fmt.Sprintf("%#v", aObj), fmt.Sprintf("%#v", bObj) + for { + switch { + case len(a) > max && len(a) > 4 && len(b) > 4 && a[:4] == b[:4]: + // a is too long, b has data, and the first several characters are the same + elidedPrefix = "..." + a = a[2:] + b = b[2:] + + case len(b) > max && len(b) > 4 && len(a) > 4 && a[:4] == b[:4]: + // b is too long, a has data, and the first several characters are the same + elidedPrefix = "..." + a = a[2:] + b = b[2:] + + case len(a) > max: + a = a[:max] + elidedASuffix = "..." + + case len(b) > max: + b = b[:max] + elidedBSuffix = "..." + + default: + // both are short enough + return elidedPrefix + a + elidedASuffix, elidedPrefix + b + elidedBSuffix + } } - return s } func public(s string) bool { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/diff/diff_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/diff/diff_test.go index 2b72c2f53..d26dba818 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/diff/diff_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/diff/diff_test.go @@ -94,3 +94,50 @@ func TestStringDiff(t *testing.T) { t.Errorf("diff returned %v", diff) } } + +func TestLimit(t *testing.T) { + testcases := []struct { + a interface{} + b interface{} + expectA string + expectB string + }{ + { + a: `short a`, + b: `short b`, + expectA: `"short a"`, + expectB: `"short b"`, + }, + { + a: `short a`, + b: `long b needs truncating`, + expectA: `"short a"`, + expectB: `"long b ne...`, + }, + { + a: `long a needs truncating`, + b: `long b needs truncating`, + expectA: `...g a needs ...`, + expectB: `...g b needs ...`, + }, + { + a: `long common prefix with different stuff at the end of a`, + b: `long common prefix with different stuff at the end of b`, + expectA: `...end of a"`, + expectB: `...end of b"`, + }, + { + a: `long common prefix with different stuff at the end of a`, + b: `long common prefix with different stuff at the end of b which continues`, + expectA: `...of a"`, + expectB: `...of b which...`, + }, + } + + for _, tc := range testcases { + a, b := limit(tc.a, tc.b, 10) + if a != tc.expectA || b != tc.expectB { + t.Errorf("limit(%q, %q)\n\texpected: %s, %s\n\tgot: %s, %s", tc.a, tc.b, tc.expectA, tc.expectB, a, b) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go index d2d3ad8cb..dd781cbc8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go @@ -19,6 +19,7 @@ package spdy import ( "bufio" "bytes" + "context" "crypto/tls" "encoding/base64" "fmt" @@ -118,7 +119,7 @@ func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { } if proxyURL == nil { - return s.dialWithoutProxy(req.URL) + return s.dialWithoutProxy(req.Context(), req.URL) } // ensure we use a canonical host with proxyReq @@ -136,7 +137,7 @@ func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { proxyReq.Header.Set("Proxy-Authorization", pa) } - proxyDialConn, err := s.dialWithoutProxy(proxyURL) + proxyDialConn, err := s.dialWithoutProxy(req.Context(), proxyURL) if err != nil { return nil, err } @@ -187,14 +188,15 @@ func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { } // dialWithoutProxy dials the host specified by url, using TLS if appropriate. -func (s *SpdyRoundTripper) dialWithoutProxy(url *url.URL) (net.Conn, error) { +func (s *SpdyRoundTripper) dialWithoutProxy(ctx context.Context, url *url.URL) (net.Conn, error) { dialAddr := netutil.CanonicalAddr(url) if url.Scheme == "http" { if s.Dialer == nil { - return net.Dial("tcp", dialAddr) + var d net.Dialer + return d.DialContext(ctx, "tcp", dialAddr) } else { - return s.Dialer.Dial("tcp", dialAddr) + return s.Dialer.DialContext(ctx, "tcp", dialAddr) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go index 887adbe8f..fb396bca5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go @@ -399,7 +399,7 @@ func TestRoundTripRedirects(t *testing.T) { var redirects int32 = 0 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if redirects < test.redirects { - redirects = atomic.AddInt32(&redirects, 1) + atomic.AddInt32(&redirects, 1) http.Redirect(w, req, "redirect", http.StatusFound) return } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go index 161e9a6f8..5c2ac4f23 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/intstr/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/intstr/generated.proto index 6819d468d..1c3ec732e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/intstr/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/intstr/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch.go index e81e4f23a..82e4b4b57 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch.go @@ -116,10 +116,26 @@ func keepOrDeleteNullInObj(m map[string]interface{}, keepNull bool) (map[string] case val != nil: switch typedVal := val.(type) { case map[string]interface{}: - filteredMap[key], err = keepOrDeleteNullInObj(typedVal, keepNull) + // Explicitly-set empty maps are treated as values instead of empty patches + if len(typedVal) == 0 { + if !keepNull { + filteredMap[key] = typedVal + } + continue + } + + var filteredSubMap map[string]interface{} + filteredSubMap, err = keepOrDeleteNullInObj(typedVal, keepNull) if err != nil { return nil, err } + + // If the returned filtered submap was empty, this is an empty patch for the entire subdict, so the key + // should not be set + if len(filteredSubMap) != 0 { + filteredMap[key] = filteredSubMap + } + case []interface{}, string, float64, bool, int, int64, nil: // Lists are always replaced in Json, no need to check each entry in the list. if !keepNull { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch_test.go index f462bf915..9672deaad 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch/patch_test.go @@ -62,12 +62,12 @@ testCases: expectedWithoutNull: {} - description: simple map with all non-nil values originalObj: - nonNilKey: foo - nonNilKey: bar + nonNilKey1: foo + nonNilKey2: bar expectedWithNull: {} expectedWithoutNull: - nonNilKey: foo - nonNilKey: bar + nonNilKey1: foo + nonNilKey2: bar - description: nested map originalObj: mapKey: @@ -88,19 +88,52 @@ testCases: mapKey: nilKey1: null nilKey2: null + expectedWithoutNull: {} + - description: nested map that all subkeys are non-nil + originalObj: + mapKey: + nonNilKey1: foo + nonNilKey2: bar + expectedWithNull: {} expectedWithoutNull: + mapKey: + nonNilKey1: foo + nonNilKey2: bar + - description: explicitly empty map as value + originalObj: mapKey: {} - - description: nested map that all subkeys are non-nil + expectedWithNull: {} + expectedWithoutNull: + mapKey: {} + - description: explicitly empty nested map originalObj: mapKey: - nonNilKey: foo - nonNilKey: bar + nonNilKey: {} + expectedWithNull: {} + expectedWithoutNull: + mapKey: + nonNilKey: {} + - description: multiple expliclty empty nested maps + originalObj: + mapKey: + nonNilKey1: {} + nonNilKey2: {} + expectedWithNull: {} + expectedWithoutNull: + mapKey: + nonNilKey1: {} + nonNilKey2: {} + - description: nested map with non-null value as empty map + originalObj: + mapKey: + nonNilKey: {} + nilKey: null expectedWithNull: - mapKey: {} + mapKey: + nilKey: null expectedWithoutNull: mapKey: - nonNilKey: foo - nonNilKey: bar + nonNilKey: {} - description: empty list originalObj: listKey: [] diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/http.go index 76eb8b4fa..7ea2df226 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/http.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/http.go @@ -19,6 +19,7 @@ package net import ( "bufio" "bytes" + "context" "crypto/tls" "fmt" "io" @@ -90,8 +91,8 @@ func SetOldTransportDefaults(t *http.Transport) *http.Transport { // ProxierWithNoProxyCIDR allows CIDR rules in NO_PROXY t.Proxy = NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment) } - if t.Dial == nil { - t.Dial = defaultTransport.Dial + if t.DialContext == nil { + t.DialContext = defaultTransport.DialContext } if t.TLSHandshakeTimeout == 0 { t.TLSHandshakeTimeout = defaultTransport.TLSHandshakeTimeout @@ -119,7 +120,7 @@ type RoundTripperWrapper interface { WrappedRoundTripper() http.RoundTripper } -type DialFunc func(net, addr string) (net.Conn, error) +type DialFunc func(ctx context.Context, net, addr string) (net.Conn, error) func DialerFor(transport http.RoundTripper) (DialFunc, error) { if transport == nil { @@ -128,7 +129,7 @@ func DialerFor(transport http.RoundTripper) (DialFunc, error) { switch transport := transport.(type) { case *http.Transport: - return transport.Dial, nil + return transport.DialContext, nil case RoundTripperWrapper: return DialerFor(transport.WrappedRoundTripper()) default: diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/port_range.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/port_range.go index 6a50e6186..7b6eca893 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/port_range.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/port_range.go @@ -43,14 +43,19 @@ func (pr PortRange) String() string { return fmt.Sprintf("%d-%d", pr.Base, pr.Base+pr.Size-1) } -// Set parses a string of the form "min-max", inclusive at both ends, and +// Set parses a string of the form "value", "min-max", or "min+offset", inclusive at both ends, and // sets the PortRange from it. This is part of the flag.Value and pflag.Value // interfaces. func (pr *PortRange) Set(value string) error { - value = strings.TrimSpace(value) + const ( + SinglePortNotation = 1 << iota + HyphenNotation + PlusNotation + ) - // TODO: Accept "80" syntax - // TODO: Accept "80+8" syntax + value = strings.TrimSpace(value) + hyphenIndex := strings.Index(value, "-") + plusIndex := strings.Index(value, "+") if value == "" { pr.Base = 0 @@ -58,20 +63,51 @@ func (pr *PortRange) Set(value string) error { return nil } - hyphenIndex := strings.Index(value, "-") - if hyphenIndex == -1 { - return fmt.Errorf("expected hyphen in port range") + var err error + var low, high int + var notation int + + if plusIndex == -1 && hyphenIndex == -1 { + notation |= SinglePortNotation + } + if hyphenIndex != -1 { + notation |= HyphenNotation + } + if plusIndex != -1 { + notation |= PlusNotation } - var err error - var low int - var high int - low, err = strconv.Atoi(value[:hyphenIndex]) - if err == nil { + switch notation { + case SinglePortNotation: + var port int + port, err = strconv.Atoi(value) + if err != nil { + return err + } + low = port + high = port + case HyphenNotation: + low, err = strconv.Atoi(value[:hyphenIndex]) + if err != nil { + return err + } high, err = strconv.Atoi(value[hyphenIndex+1:]) - } - if err != nil { - return fmt.Errorf("unable to parse port range: %s: %v", value, err) + if err != nil { + return err + } + case PlusNotation: + var offset int + low, err = strconv.Atoi(value[:plusIndex]) + if err != nil { + return err + } + offset, err = strconv.Atoi(value[plusIndex+1:]) + if err != nil { + return err + } + high = low + offset + default: + return fmt.Errorf("unable to parse port range: %s", value) } if low > 65535 || high > 65535 { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/port_range_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/port_range_test.go index 897b8df61..b4cbe8245 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/port_range_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/net/port_range_test.go @@ -34,13 +34,21 @@ func TestPortRange(t *testing.T) { {" 100-200 ", true, "100-200", 200, 201}, {"0-0", true, "0-0", 0, 1}, {"", true, "", -1, 0}, - {"100", false, "", -1, -1}, + {"100", true, "100-100", 100, 101}, {"100 - 200", false, "", -1, -1}, {"-100", false, "", -1, -1}, {"100-", false, "", -1, -1}, {"200-100", false, "", -1, -1}, {"60000-70000", false, "", -1, -1}, {"70000-80000", false, "", -1, -1}, + {"70000+80000", false, "", -1, -1}, + {"1+0", true, "1-1", 1, 2}, + {"0+0", true, "0-0", 0, 1}, + {"1+-1", false, "", -1, -1}, + {"1-+1", false, "", -1, -1}, + {"100+200", true, "100-300", 300, 301}, + {"1+65535", false, "", -1, -1}, + {"0+65535", true, "0-65535", 65535, 65536}, } for i := range testCases { @@ -52,7 +60,7 @@ func TestPortRange(t *testing.T) { t.Errorf("expected success, got %q", err) continue } else if err == nil && tc.success == false { - t.Errorf("expected failure") + t.Errorf("expected failure %#v", testCases[i]) continue } else if tc.success { if f.String() != tc.expected { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/dial.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/dial.go index 3da7e965f..37a5be487 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/dial.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/dial.go @@ -17,6 +17,7 @@ limitations under the License. package proxy import ( + "context" "crypto/tls" "fmt" "net" @@ -29,7 +30,7 @@ import ( "k8s.io/apimachinery/third_party/forked/golang/netutil" ) -func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { +func DialURL(ctx context.Context, url *url.URL, transport http.RoundTripper) (net.Conn, error) { dialAddr := netutil.CanonicalAddr(url) dialer, err := utilnet.DialerFor(transport) @@ -40,9 +41,10 @@ func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { switch url.Scheme { case "http": if dialer != nil { - return dialer("tcp", dialAddr) + return dialer(ctx, "tcp", dialAddr) } - return net.Dial("tcp", dialAddr) + var d net.Dialer + return d.DialContext(ctx, "tcp", dialAddr) case "https": // Get the tls config from the transport if we recognize it var tlsConfig *tls.Config @@ -56,7 +58,7 @@ func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { if dialer != nil { // We have a dialer; use it to open the connection, then // create a tls client using the connection. - netConn, err := dialer("tcp", dialAddr) + netConn, err := dialer(ctx, "tcp", dialAddr) if err != nil { return nil, err } @@ -86,7 +88,7 @@ func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { } } else { - // Dial + // Dial. This Dial method does not allow to pass a context unfortunately tlsConn, err = tls.Dial("tcp", dialAddr, tlsConfig) if err != nil { return nil, err diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/dial_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/dial_test.go index 8b9f78e4d..6ee594174 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/dial_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/dial_test.go @@ -17,6 +17,7 @@ limitations under the License. package proxy import ( + "context" "crypto/tls" "crypto/x509" "fmt" @@ -42,6 +43,7 @@ func TestDialURL(t *testing.T) { if err != nil { t.Fatal(err) } + var d net.Dialer testcases := map[string]struct { TLSConfig *tls.Config @@ -68,25 +70,25 @@ func TestDialURL(t *testing.T) { "insecure, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: true}, - Dial: net.Dial, + Dial: d.DialContext, }, "secure, no roots, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: false}, - Dial: net.Dial, + Dial: d.DialContext, ExpectError: "unknown authority", }, "secure with roots, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots}, - Dial: net.Dial, + Dial: d.DialContext, }, "secure with mismatched server, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots, ServerName: "bogus.com"}, - Dial: net.Dial, + Dial: d.DialContext, ExpectError: "not bogus.com", }, "secure with matched server, custom dial": { TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots, ServerName: "example.com"}, - Dial: net.Dial, + Dial: d.DialContext, }, } @@ -102,7 +104,7 @@ func TestDialURL(t *testing.T) { // Clone() mutates the receiver (!), so also call it on the copy tlsConfigCopy.Clone() transport := &http.Transport{ - Dial: tc.Dial, + DialContext: tc.Dial, TLSClientConfig: tlsConfigCopy, } @@ -125,7 +127,7 @@ func TestDialURL(t *testing.T) { u, _ := url.Parse(ts.URL) _, p, _ := net.SplitHostPort(u.Host) u.Host = net.JoinHostPort("127.0.0.1", p) - conn, err := DialURL(u, transport) + conn, err := DialURL(context.Background(), u, transport) // Make sure dialing doesn't mutate the transport's TLSConfig if !reflect.DeepEqual(tc.TLSConfig, tlsConfigCopy) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go index 2bc19655e..d725b228e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go @@ -347,7 +347,7 @@ func (h *UpgradeAwareHandler) DialForUpgrade(req *http.Request) (net.Conn, error // dial dials the backend at req.URL and writes req to it. func dial(req *http.Request, transport http.RoundTripper) (net.Conn, error) { - conn, err := DialURL(req.URL, transport) + conn, err := DialURL(req.Context(), req.URL, transport) if err != nil { return nil, fmt.Errorf("error dialing backend: %v", err) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go index a33b10e58..c5dfde90d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go @@ -19,6 +19,7 @@ package proxy import ( "bytes" "compress/gzip" + "context" "crypto/tls" "crypto/x509" "errors" @@ -341,6 +342,7 @@ func TestProxyUpgrade(t *testing.T) { if !localhostPool.AppendCertsFromPEM(localhostCert) { t.Errorf("error setting up localhostCert pool") } + var d net.Dialer testcases := map[string]struct { ServerFunc func(http.Handler) *httptest.Server @@ -395,7 +397,7 @@ func TestProxyUpgrade(t *testing.T) { ts.StartTLS() return ts }, - ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), + ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{DialContext: d.DialContext, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), }, "https (valid hostname + RootCAs + custom dialer + bearer token)": { ServerFunc: func(h http.Handler) *httptest.Server { @@ -410,9 +412,9 @@ func TestProxyUpgrade(t *testing.T) { ts.StartTLS() return ts }, - ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), + ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{DialContext: d.DialContext, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), UpgradeTransport: NewUpgradeRequestRoundTripper( - utilnet.SetOldTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), + utilnet.SetOldTransportDefaults(&http.Transport{DialContext: d.DialContext, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), RoundTripperFunc(func(req *http.Request) (*http.Response, error) { req = utilnet.CloneRequest(req) req.Header.Set("Authorization", "Bearer 1234") @@ -496,9 +498,15 @@ func TestProxyUpgradeErrorResponse(t *testing.T) { expectedErr = errors.New("EXPECTED") ) proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - transport := http.DefaultTransport.(*http.Transport) - transport.Dial = func(network, addr string) (net.Conn, error) { - return &fakeConn{err: expectedErr}, nil + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return &fakeConn{err: expectedErr}, nil + }, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, } responder = &fakeResponder{t: t, w: w} proxyHandler := NewUpgradeAwareHandler( diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/runtime/runtime.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/runtime/runtime.go index d4cec0b88..da32fe12f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/runtime/runtime.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/runtime/runtime.go @@ -128,9 +128,8 @@ func (r *rudimentaryErrorBackoff) OnError(error) { r.lastErrorTimeLock.Lock() defer r.lastErrorTimeLock.Unlock() d := time.Since(r.lastErrorTime) - if d < r.minPeriod && d >= 0 { + if d < r.minPeriod { // If the time moves backwards for any reason, do nothing - // TODO: remove check "d >= 0" after go 1.8 is no longer supported time.Sleep(r.minPeriod - d) } r.lastErrorTime = time.Now() @@ -161,3 +160,10 @@ func RecoverFromPanic(err *error) { callers) } } + +// Must panics on non-nil errors. Useful to handling programmer level errors. +func Must(err error) { + if err != nil { + panic(err) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/BUILD index ec2f23476..aaccd789b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/BUILD @@ -23,7 +23,7 @@ go_library( go_genrule( name = "set-gen", srcs = [ - "//hack/boilerplate:boilerplate.go.txt", + "//hack/boilerplate:boilerplate.generatego.txt", ], outs = [ "byte.go", @@ -37,7 +37,7 @@ go_genrule( $(location //vendor/k8s.io/code-generator/cmd/set-gen) \ --input-dirs ./vendor/k8s.io/apimachinery/pkg/util/sets/types \ --output-base $$(dirname $$(dirname $(location :byte.go))) \ - --go-header-file $(location //hack/boilerplate:boilerplate.go.txt) \ + --go-header-file $(location //hack/boilerplate:boilerplate.generatego.txt) \ --output-package sets """, go_deps = [ diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/byte.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/byte.go index a460e4b1f..766f4501e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/byte.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/byte.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets @@ -26,7 +26,7 @@ import ( // sets.Byte is a set of bytes, implemented via map[byte]struct{} for minimal memory consumption. type Byte map[byte]Empty -// New creates a Byte from a list of values. +// NewByte creates a Byte from a list of values. func NewByte(items ...byte) Byte { ss := Byte{} ss.Insert(items...) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/doc.go index 28a6a7d5c..b152a0bf0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. // Package sets has auto-generated set types. package sets diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/empty.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/empty.go index cd22b953a..e11e622c5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/empty.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/empty.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/int.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/int.go index 0614e9fb0..a0a513cd9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/int.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/int.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets @@ -26,7 +26,7 @@ import ( // sets.Int is a set of ints, implemented via map[int]struct{} for minimal memory consumption. type Int map[int]Empty -// New creates a Int from a list of values. +// NewInt creates a Int from a list of values. func NewInt(items ...int) Int { ss := Int{} ss.Insert(items...) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/int64.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/int64.go index 82e1ba782..9ca9af0c5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/int64.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/int64.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets @@ -26,7 +26,7 @@ import ( // sets.Int64 is a set of int64s, implemented via map[int64]struct{} for minimal memory consumption. type Int64 map[int64]Empty -// New creates a Int64 from a list of values. +// NewInt64 creates a Int64 from a list of values. func NewInt64(items ...int64) Int64 { ss := Int64{} ss.Insert(items...) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/string.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/string.go index baef7a6a2..ba00ad7df 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/string.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/sets/string.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets @@ -26,7 +26,7 @@ import ( // sets.String is a set of strings, implemented via map[string]struct{} for minimal memory consumption. type String map[string]Empty -// New creates a String from a list of values. +// NewString creates a String from a list of values. func NewString(items ...string) String { ss := String{} ss.Insert(items...) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go index 2f6ade2be..6be328f74 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go @@ -880,6 +880,29 @@ func StrategicMergeMapPatchUsingLookupPatchMeta(original, patch JSONMap, schema return mergeMap(original, patch, schema, mergeOptions) } +// MergeStrategicMergeMapPatchUsingLookupPatchMeta merges strategic merge +// patches retaining `null` fields and parallel lists. If 2 patches change the +// same fields and the latter one will override the former one. If you don't +// want that happen, you need to run func MergingMapsHaveConflicts before +// merging these patches. Applying the resulting merged merge patch to a JSONMap +// yields the same as merging each strategic merge patch to the JSONMap in +// succession. +func MergeStrategicMergeMapPatchUsingLookupPatchMeta(schema LookupPatchMeta, patches ...JSONMap) (JSONMap, error) { + mergeOptions := MergeOptions{ + MergeParallelList: false, + IgnoreUnmatchedNulls: false, + } + merged := JSONMap{} + var err error + for _, patch := range patches { + merged, err = mergeMap(merged, patch, schema, mergeOptions) + if err != nil { + return nil, err + } + } + return merged, nil +} + // handleDirectiveInMergeMap handles the patch directive when merging 2 maps. func handleDirectiveInMergeMap(directive interface{}, patch map[string]interface{}) (map[string]interface{}, error) { if directive == replaceDirective { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go index 0997de806..a25e92465 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go @@ -284,12 +284,32 @@ func PollImmediateInfinite(interval time.Duration, condition ConditionFunc) erro // PollUntil tries a condition func until it returns true, an error or stopCh is // closed. // -// PolUntil always waits interval before the first run of 'condition'. +// PollUntil always waits interval before the first run of 'condition'. // 'condition' will always be invoked at least once. func PollUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error { return WaitFor(poller(interval, 0), condition, stopCh) } +// PollImmediateUntil tries a condition func until it returns true, an error or stopCh is closed. +// +// PollImmediateUntil runs the 'condition' before waiting for the interval. +// 'condition' will always be invoked at least once. +func PollImmediateUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error { + done, err := condition() + if err != nil { + return err + } + if done { + return nil + } + select { + case <-stopCh: + return ErrWaitTimeout + default: + return PollUntil(interval, condition, stopCh) + } +} + // WaitFunc creates a channel that receives an item every time a test // should be executed and is closed when the last test should be invoked. type WaitFunc func(done <-chan struct{}) <-chan struct{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/BUILD index bdccf7b3a..fc803ec6f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/BUILD @@ -3,12 +3,14 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( name = "go_default_library", srcs = [ "doc.go", + "helpers.go", "types.go", ], importpath = "k8s.io/apimachinery/pkg/version", @@ -26,3 +28,9 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["helpers_test.go"], + embed = [":go_default_library"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/helpers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/helpers.go new file mode 100644 index 000000000..5e041d6f3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/helpers.go @@ -0,0 +1,88 @@ +/* +Copyright 2018 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 version + +import ( + "regexp" + "strconv" + "strings" +) + +type versionType int + +const ( + // Bigger the version type number, higher priority it is + versionTypeAlpha versionType = iota + versionTypeBeta + versionTypeGA +) + +var kubeVersionRegex = regexp.MustCompile("^v([\\d]+)(?:(alpha|beta)([\\d]+))?$") + +func parseKubeVersion(v string) (majorVersion int, vType versionType, minorVersion int, ok bool) { + var err error + submatches := kubeVersionRegex.FindStringSubmatch(v) + if len(submatches) != 4 { + return 0, 0, 0, false + } + switch submatches[2] { + case "alpha": + vType = versionTypeAlpha + case "beta": + vType = versionTypeBeta + case "": + vType = versionTypeGA + default: + return 0, 0, 0, false + } + if majorVersion, err = strconv.Atoi(submatches[1]); err != nil { + return 0, 0, 0, false + } + if vType != versionTypeGA { + if minorVersion, err = strconv.Atoi(submatches[3]); err != nil { + return 0, 0, 0, false + } + } + return majorVersion, vType, minorVersion, true +} + +// CompareKubeAwareVersionStrings compares two kube-like version strings. +// Kube-like version strings are starting with a v, followed by a major version, optional "alpha" or "beta" strings +// followed by a minor version (e.g. v1, v2beta1). Versions will be sorted based on GA/alpha/beta first and then major +// and minor versions. e.g. v2, v1, v1beta2, v1beta1, v1alpha1. +func CompareKubeAwareVersionStrings(v1, v2 string) int { + if v1 == v2 { + return 0 + } + v1major, v1type, v1minor, ok1 := parseKubeVersion(v1) + v2major, v2type, v2minor, ok2 := parseKubeVersion(v2) + switch { + case !ok1 && !ok2: + return strings.Compare(v2, v1) + case !ok1 && ok2: + return -1 + case ok1 && !ok2: + return 1 + } + if v1type != v2type { + return int(v1type) - int(v2type) + } + if v1major != v2major { + return v1major - v2major + } + return v1minor - v2minor +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/helpers_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/helpers_test.go new file mode 100644 index 000000000..863a53697 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/version/helpers_test.go @@ -0,0 +1,52 @@ +/* +Copyright 2018 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 version + +import ( + "testing" +) + +func TestCompareKubeAwareVersionStrings(t *testing.T) { + tests := []*struct { + v1, v2 string + expectedGreater bool + }{ + {"v1", "v2", false}, + {"v2", "v1", true}, + {"v10", "v2", true}, + {"v1", "v2alpha1", true}, + {"v1", "v2beta1", true}, + {"v1alpha2", "v1alpha1", true}, + {"v1beta1", "v2alpha3", true}, + {"v1alpha10", "v1alpha2", true}, + {"v1beta10", "v1beta2", true}, + {"foo", "v1beta2", false}, + {"bar", "foo", true}, + {"version1", "version2", true}, // Non kube-like versions are sorted alphabetically + {"version1", "version10", true}, // Non kube-like versions are sorted alphabetically + } + + for _, tc := range tests { + if e, a := tc.expectedGreater, CompareKubeAwareVersionStrings(tc.v1, tc.v2) > 0; e != a { + if e { + t.Errorf("expected %s to be greater than %s", tc.v1, tc.v2) + } else { + t.Errorf("expected %s to be less than than %s", tc.v1, tc.v2) + } + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/filter.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/filter.go index 3ca27f22c..22c9449f5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/filter.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/filter.go @@ -62,11 +62,7 @@ func (fw *filteredWatch) Stop() { // loop waits for new values, filters them, and resends them. func (fw *filteredWatch) loop() { defer close(fw.result) - for { - event, ok := <-fw.incoming.ResultChan() - if !ok { - break - } + for event := range fw.incoming.ResultChan() { filtered, keep := fw.f(event) if keep { fw.result <- filtered diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/mux.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/mux.go index a65088c1c..0ac8dc4ef 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/mux.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/mux.go @@ -204,11 +204,7 @@ func (m *Broadcaster) Shutdown() { func (m *Broadcaster) loop() { // Deliberately not catching crashes here. Yes, bring down the process if there's a // bug in watch.Broadcaster. - for { - event, ok := <-m.incoming - if !ok { - break - } + for event := range m.incoming { if event.Type == internalRunFunctionMarker { event.Object.(functionFakeRuntimeObject)() continue diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go index b1b19d118..0d266ffb6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/third_party/forked/golang/reflect/deep_equal.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/third_party/forked/golang/reflect/deep_equal.go index 9e45dbe1d..7ed1d1cff 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/third_party/forked/golang/reflect/deep_equal.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/third_party/forked/golang/reflect/deep_equal.go @@ -44,7 +44,7 @@ func (e Equalities) AddFunc(eqFunc interface{}) error { return fmt.Errorf("expected func, got: %v", ft) } if ft.NumIn() != 2 { - return fmt.Errorf("expected three 'in' params, got: %v", ft) + return fmt.Errorf("expected two 'in' params, got: %v", ft) } if ft.NumOut() != 1 { return fmt.Errorf("expected one 'out' param, got: %v", ft) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/CONTRIBUTING.md b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/CONTRIBUTING.md new file mode 100644 index 000000000..94a288993 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/CONTRIBUTING.md @@ -0,0 +1,7 @@ +# Contributing guidelines + +Do not open pull requests directly against this repository, they will be ignored. Instead, please open pull requests against [kubernetes/kubernetes](https://git.k8s.io/kubernetes/). Please follow the same [contributing guide](https://git.k8s.io/kubernetes/CONTRIBUTING.md) you would follow for any other pull request made to kubernetes/kubernetes. + +This repository is published from [kubernetes/kubernetes/staging/src/k8s.io/apiserver](https://git.k8s.io/kubernetes/staging/src/k8s.io/apiserver) by the [kubernetes publishing-bot](https://git.k8s.io/publishing-bot). + +Please see [Staging Directory and Publishing](https://git.k8s.io/community/contributors/devel/staging.md) for more information diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/Godeps/Godeps.json index 78b274011..8a777ef75 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "k8s.io/apiserver", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], @@ -372,7 +372,7 @@ }, { "ImportPath": "github.com/evanphx/json-patch", - "Rev": "944e07253867aacae43c04b2e6a239005443f33a" + "Rev": "94e38aa1586e8a6c8a75770bddf5ff84c48a106b" }, { "ImportPath": "github.com/ghodss/yaml", @@ -412,35 +412,35 @@ }, { "ImportPath": "github.com/golang/protobuf/jsonpb", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/struct", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/google/btree", @@ -462,6 +462,14 @@ "ImportPath": "github.com/googleapis/gnostic/extensions", "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, { "ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus", "Rev": "2500245aa6110c562d17020fb31a2c133d737799" @@ -486,10 +494,6 @@ "ImportPath": "github.com/hashicorp/golang-lru/simplelru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" }, - { - "ImportPath": "github.com/howeyc/gopass", - "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" - }, { "ImportPath": "github.com/imdario/mergo", "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" @@ -500,7 +504,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/mailru/easyjson/buffer", @@ -518,10 +522,22 @@ "ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil", "Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a" }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, { "ImportPath": "github.com/pborman/uuid", "Rev": "ca53cad383cad2479bbba7f7a1a05797ec1386e4" }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" + }, { "ImportPath": "github.com/pmezard/go-difflib/difflib", "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d" @@ -568,11 +584,11 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/stretchr/testify/require", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/ugorji/go/codec", @@ -584,35 +600,35 @@ }, { "ImportPath": "golang.org/x/crypto/bcrypt", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/blowfish", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/ed25519", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/ed25519/internal/edwards25519", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/nacl/secretbox", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/poly1305", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/salsa20/salsa", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/net/context", @@ -914,6 +930,10 @@ "ImportPath": "k8s.io/api/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -966,18 +986,6 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/validation/path", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1290,6 +1298,10 @@ "ImportPath": "k8s.io/client-go/informers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/settings", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1514,6 +1526,14 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1626,6 +1646,10 @@ "ImportPath": "k8s.io/client-go/listers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1650,6 +1674,10 @@ "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/pkg/version", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1714,6 +1742,10 @@ "ImportPath": "k8s.io/client-go/util/cert", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/connrotation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1732,23 +1764,23 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/client-go/discovery", @@ -1758,10 +1790,6 @@ "ImportPath": "k8s.io/client-go/informers", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/client-go/informers/admissionregistration/v1beta1", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/client-go/kubernetes", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/OWNERS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/OWNERS index bc61d5ffa..a77fd665a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/OWNERS +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/OWNERS @@ -15,3 +15,5 @@ reviewers: - ncdc - tallclair - enj +- hzxuzhonghu +- CaoShuFeng diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/BUILD index 78aed4c7e..dd4f25641 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/BUILD @@ -9,6 +9,8 @@ load( go_test( name = "go_default_test", srcs = [ + "attributes_test.go", + "audit_test.go", "chain_test.go", "config_test.go", "errors_test.go", @@ -16,12 +18,15 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/util/json:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", ], ) @@ -29,6 +34,7 @@ go_library( name = "go_default_library", srcs = [ "attributes.go", + "audit.go", "chain.go", "config.go", "decorator.go", @@ -48,8 +54,11 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", + "//vendor/k8s.io/apiserver/pkg/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", ], ) @@ -72,12 +81,14 @@ filegroup( "//staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:all-srcs", + "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/initializer:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/rules:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts:all-srcs", + "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:all-srcs", "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned:all-srcs", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/attributes.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/attributes.go index 406235dd0..7272e888b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/attributes.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/attributes.go @@ -17,8 +17,13 @@ limitations under the License. package admission import ( + "fmt" + "strings" + "sync" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apiserver/pkg/authentication/user" ) @@ -32,6 +37,11 @@ type attributesRecord struct { object runtime.Object oldObject runtime.Object userInfo user.Info + + // other elements are always accessed in single goroutine. + // But ValidatingAdmissionWebhook add annotations concurrently. + annotations map[string]string + annotationsLock sync.RWMutex } func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind schema.GroupVersionKind, namespace, name string, resource schema.GroupVersionResource, subresource string, operation Operation, userInfo user.Info) Attributes { @@ -83,3 +93,48 @@ func (record *attributesRecord) GetOldObject() runtime.Object { func (record *attributesRecord) GetUserInfo() user.Info { return record.userInfo } + +// getAnnotations implements privateAnnotationsGetter.It's a private method used +// by WithAudit decorator. +func (record *attributesRecord) getAnnotations() map[string]string { + record.annotationsLock.RLock() + defer record.annotationsLock.RUnlock() + + if record.annotations == nil { + return nil + } + cp := make(map[string]string, len(record.annotations)) + for key, value := range record.annotations { + cp[key] = value + } + return cp +} + +func (record *attributesRecord) AddAnnotation(key, value string) error { + if err := checkKeyFormat(key); err != nil { + return err + } + + record.annotationsLock.Lock() + defer record.annotationsLock.Unlock() + + if record.annotations == nil { + record.annotations = make(map[string]string) + } + if v, ok := record.annotations[key]; ok && v != value { + return fmt.Errorf("admission annotations are not allowd to be overwritten, key:%q, old value: %q, new value:%q", key, record.annotations[key], value) + } + record.annotations[key] = value + return nil +} + +func checkKeyFormat(key string) error { + parts := strings.Split(key, "/") + if len(parts) != 2 { + return fmt.Errorf("annotation key has invalid format, the right format is a DNS subdomain prefix and '/' and key name. (e.g. 'podsecuritypolicy.admission.k8s.io/admit-policy')") + } + if msgs := validation.IsQualifiedName(key); len(msgs) != 0 { + return fmt.Errorf("annotation key has invalid format %s. A qualified name like 'podsecuritypolicy.admission.k8s.io/admit-policy' is required.", strings.Join(msgs, ",")) + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/attributes_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/attributes_test.go new file mode 100644 index 000000000..d54780d99 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/attributes_test.go @@ -0,0 +1,64 @@ +/* +Copyright 2018 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 admission + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAddAnnotation(t *testing.T) { + attr := &attributesRecord{} + + // test AddAnnotation + attr.AddAnnotation("podsecuritypolicy.admission.k8s.io/validate-policy", "privileged") + attr.AddAnnotation("podsecuritypolicy.admission.k8s.io/admit-policy", "privileged") + annotations := attr.getAnnotations() + assert.Equal(t, annotations["podsecuritypolicy.admission.k8s.io/validate-policy"], "privileged") + + // test overwrite + assert.Error(t, attr.AddAnnotation("podsecuritypolicy.admission.k8s.io/validate-policy", "privileged-overwrite"), + "admission annotations should not be allowd to be overwritten") + annotations = attr.getAnnotations() + assert.Equal(t, annotations["podsecuritypolicy.admission.k8s.io/validate-policy"], "privileged", "admission annotations should not be overwritten") + + // test invalid plugin names + var testCases map[string]string = map[string]string{ + "invalid dns subdomain": "INVALID-DNS-Subdomain/policy", + "no plugin name": "policy", + "no key name": "podsecuritypolicy.admission.k8s.io", + "empty key": "", + } + for name, invalidKey := range testCases { + err := attr.AddAnnotation(invalidKey, "value-foo") + assert.Error(t, err) + annotations = attr.getAnnotations() + assert.Equal(t, annotations[invalidKey], "", name+": invalid pluginName is not allowed ") + } + + // test all saved annotations + assert.Equal( + t, + annotations, + map[string]string{ + "podsecuritypolicy.admission.k8s.io/validate-policy": "privileged", + "podsecuritypolicy.admission.k8s.io/admit-policy": "privileged", + }, + "unexpected final annotations", + ) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/audit.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/audit.go new file mode 100644 index 000000000..13d86b33b --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/audit.go @@ -0,0 +1,95 @@ +/* +Copyright 2018 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 admission + +import ( + "fmt" + + auditinternal "k8s.io/apiserver/pkg/apis/audit" + "k8s.io/apiserver/pkg/audit" +) + +// auditHandler logs annotations set by other admission handlers +type auditHandler struct { + Interface + ae *auditinternal.Event +} + +var _ Interface = &auditHandler{} +var _ MutationInterface = &auditHandler{} +var _ ValidationInterface = &auditHandler{} + +// WithAudit is a decorator for a admission phase. It saves annotations +// of attribute into the audit event. Attributes passed to the Admit and +// Validate function must be instance of privateAnnotationsGetter or +// AnnotationsGetter, otherwise an error is returned. +func WithAudit(i Interface, ae *auditinternal.Event) Interface { + if i == nil { + return i + } + return &auditHandler{i, ae} +} + +func (handler auditHandler) Admit(a Attributes) error { + if !handler.Interface.Handles(a.GetOperation()) { + return nil + } + if err := ensureAnnotationGetter(a); err != nil { + return err + } + var err error + if mutator, ok := handler.Interface.(MutationInterface); ok { + err = mutator.Admit(a) + handler.logAnnotations(a) + } + return err +} + +func (handler auditHandler) Validate(a Attributes) error { + if !handler.Interface.Handles(a.GetOperation()) { + return nil + } + if err := ensureAnnotationGetter(a); err != nil { + return err + } + var err error + if validator, ok := handler.Interface.(ValidationInterface); ok { + err = validator.Validate(a) + handler.logAnnotations(a) + } + return err +} + +func ensureAnnotationGetter(a Attributes) error { + _, okPrivate := a.(privateAnnotationsGetter) + _, okPublic := a.(AnnotationsGetter) + if okPrivate || okPublic { + return nil + } + return fmt.Errorf("attributes must be an instance of privateAnnotationsGetter or AnnotationsGetter") +} + +func (handler auditHandler) logAnnotations(a Attributes) { + switch a := a.(type) { + case privateAnnotationsGetter: + audit.LogAnnotations(handler.ae, a.getAnnotations()) + case AnnotationsGetter: + audit.LogAnnotations(handler.ae, a.GetAnnotations()) + default: + // this will never happen, because we have already checked it in ensureAnnotationGetter + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go new file mode 100644 index 000000000..31f3b5881 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/audit_test.go @@ -0,0 +1,173 @@ +/* +Copyright 2018 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 admission + +import ( + "fmt" + "testing" + + "k8s.io/apimachinery/pkg/runtime/schema" + auditinternal "k8s.io/apiserver/pkg/apis/audit" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// fakeHandler implements Interface +type fakeHandler struct { + // return value of Admit() + admit error + // annotations add to attributesRecord during Admit() phase + admitAnnotations map[string]string + // return value of Validate() + validate error + // annotations add to attributesRecord during Validate() phase + validateAnnotations map[string]string + // return value of Handles() + handles bool +} + +var _ Interface = &fakeHandler{} +var _ MutationInterface = &fakeHandler{} +var _ ValidationInterface = &fakeHandler{} + +func (h fakeHandler) Admit(a Attributes) error { + for k, v := range h.admitAnnotations { + a.AddAnnotation(k, v) + } + return h.admit +} + +func (h fakeHandler) Validate(a Attributes) error { + for k, v := range h.validateAnnotations { + a.AddAnnotation(k, v) + } + return h.validate +} + +func (h fakeHandler) Handles(o Operation) bool { + return h.handles +} + +func attributes() Attributes { + return NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", "", nil) +} + +func TestWithAudit(t *testing.T) { + var testCases = map[string]struct { + admit error + admitAnnotations map[string]string + validate error + validateAnnotations map[string]string + handles bool + }{ + "not handle": { + nil, + nil, + nil, + nil, + false, + }, + "allow": { + nil, + nil, + nil, + nil, + true, + }, + "allow with annotations": { + nil, + map[string]string{ + "plugin.example.com/foo": "bar", + }, + nil, + nil, + true, + }, + "allow with annotations overwrite": { + nil, + map[string]string{ + "plugin.example.com/foo": "bar", + }, + nil, + map[string]string{ + "plugin.example.com/foo": "bar", + }, + true, + }, + "forbidden error": { + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + nil, + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + nil, + true, + }, + "forbidden error with annotations": { + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + nil, + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + map[string]string{ + "plugin.example.com/foo": "bar", + }, + true, + }, + "forbidden error with annotations overwrite": { + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + map[string]string{ + "plugin.example.com/foo": "bar", + }, + NewForbidden(attributes(), fmt.Errorf("quota exceeded")), + map[string]string{ + "plugin.example.com/foo": "bar", + }, + true, + }, + } + for tcName, tc := range testCases { + var handler Interface = fakeHandler{tc.admit, tc.admitAnnotations, tc.validate, tc.validateAnnotations, tc.handles} + ae := &auditinternal.Event{Level: auditinternal.LevelMetadata} + auditHandler := WithAudit(handler, ae) + a := attributes() + + assert.Equal(t, handler.Handles(Create), auditHandler.Handles(Create), tcName+": WithAudit decorator should not effect the return value") + + mutator, ok := handler.(MutationInterface) + require.True(t, ok) + auditMutator, ok := auditHandler.(MutationInterface) + require.True(t, ok) + assert.Equal(t, mutator.Admit(a), auditMutator.Admit(a), tcName+": WithAudit decorator should not effect the return value") + + validator, ok := handler.(ValidationInterface) + require.True(t, ok) + auditValidator, ok := auditHandler.(ValidationInterface) + require.True(t, ok) + assert.Equal(t, validator.Validate(a), auditValidator.Validate(a), tcName+": WithAudit decorator should not effect the return value") + + annotations := make(map[string]string, len(tc.admitAnnotations)+len(tc.validateAnnotations)) + for k, v := range tc.admitAnnotations { + annotations[k] = v + } + for k, v := range tc.validateAnnotations { + annotations[k] = v + } + if len(annotations) == 0 { + assert.Nil(t, ae.Annotations, tcName+": unexptected annotations set in audit event") + } else { + assert.Equal(t, annotations, ae.Annotations, tcName+": unexptected annotations set in audit event") + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/BUILD index 95d8f6545..162e21d45 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/BUILD @@ -20,12 +20,11 @@ go_test( "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels: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/util/wait:go_default_library", - "//vendor/k8s.io/client-go/listers/admissionregistration/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", ], ) @@ -48,7 +47,8 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/client-go/informers/admissionregistration/v1beta1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/listers/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager.go index 3c0990699..4b2256e11 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager.go @@ -24,21 +24,27 @@ import ( "k8s.io/api/admissionregistration/v1beta1" "k8s.io/apimachinery/pkg/labels" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - admissionregistrationinformers "k8s.io/client-go/informers/admissionregistration/v1beta1" + "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" + "k8s.io/client-go/informers" admissionregistrationlisters "k8s.io/client-go/listers/admissionregistration/v1beta1" "k8s.io/client-go/tools/cache" ) -// MutatingWebhookConfigurationManager collects the mutating webhook objects so that they can be called. -type MutatingWebhookConfigurationManager struct { +// mutatingWebhookConfigurationManager collects the mutating webhook objects so that they can be called. +type mutatingWebhookConfigurationManager struct { configuration *atomic.Value lister admissionregistrationlisters.MutatingWebhookConfigurationLister + hasSynced func() bool } -func NewMutatingWebhookConfigurationManager(informer admissionregistrationinformers.MutatingWebhookConfigurationInformer) *MutatingWebhookConfigurationManager { - manager := &MutatingWebhookConfigurationManager{ +var _ generic.Source = &mutatingWebhookConfigurationManager{} + +func NewMutatingWebhookConfigurationManager(f informers.SharedInformerFactory) generic.Source { + informer := f.Admissionregistration().V1beta1().MutatingWebhookConfigurations() + manager := &mutatingWebhookConfigurationManager{ configuration: &atomic.Value{}, lister: informer.Lister(), + hasSynced: informer.Informer().HasSynced, } // Start with an empty list @@ -55,11 +61,15 @@ func NewMutatingWebhookConfigurationManager(informer admissionregistrationinform } // Webhooks returns the merged MutatingWebhookConfiguration. -func (m *MutatingWebhookConfigurationManager) Webhooks() *v1beta1.MutatingWebhookConfiguration { - return m.configuration.Load().(*v1beta1.MutatingWebhookConfiguration) +func (m *mutatingWebhookConfigurationManager) Webhooks() []v1beta1.Webhook { + return m.configuration.Load().(*v1beta1.MutatingWebhookConfiguration).Webhooks +} + +func (m *mutatingWebhookConfigurationManager) HasSynced() bool { + return m.hasSynced() } -func (m *MutatingWebhookConfigurationManager) updateConfiguration() { +func (m *mutatingWebhookConfigurationManager) updateConfiguration() { configurations, err := m.lister.List(labels.Everything()) if err != nil { utilruntime.HandleError(fmt.Errorf("error updating configuration: %v", err)) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager_test.go index d6f4f1a45..9bc037f5a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager_test.go @@ -17,107 +17,47 @@ limitations under the License. package configuration import ( - "fmt" "reflect" "testing" - "time" "k8s.io/api/admissionregistration/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - admissionregistrationlisters "k8s.io/client-go/listers/admissionregistration/v1beta1" - "k8s.io/client-go/tools/cache" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" ) -type fakeMutatingWebhookConfigSharedInformer struct { - informer *fakeMutatingWebhookConfigInformer - lister *fakeMutatingWebhookConfigLister -} - -func (f *fakeMutatingWebhookConfigSharedInformer) Informer() cache.SharedIndexInformer { - return f.informer -} -func (f *fakeMutatingWebhookConfigSharedInformer) Lister() admissionregistrationlisters.MutatingWebhookConfigurationLister { - return f.lister -} - -type fakeMutatingWebhookConfigInformer struct { - eventHandler cache.ResourceEventHandler -} - -func (f *fakeMutatingWebhookConfigInformer) AddEventHandler(handler cache.ResourceEventHandler) { - fmt.Println("added handler") - f.eventHandler = handler -} -func (f *fakeMutatingWebhookConfigInformer) AddEventHandlerWithResyncPeriod(handler cache.ResourceEventHandler, resyncPeriod time.Duration) { - panic("unsupported") -} -func (f *fakeMutatingWebhookConfigInformer) GetStore() cache.Store { - panic("unsupported") -} -func (f *fakeMutatingWebhookConfigInformer) GetController() cache.Controller { - panic("unsupported") -} -func (f *fakeMutatingWebhookConfigInformer) Run(stopCh <-chan struct{}) { - panic("unsupported") -} -func (f *fakeMutatingWebhookConfigInformer) HasSynced() bool { - panic("unsupported") -} -func (f *fakeMutatingWebhookConfigInformer) LastSyncResourceVersion() string { - panic("unsupported") -} -func (f *fakeMutatingWebhookConfigInformer) AddIndexers(indexers cache.Indexers) error { - panic("unsupported") -} -func (f *fakeMutatingWebhookConfigInformer) GetIndexer() cache.Indexer { panic("unsupported") } - -type fakeMutatingWebhookConfigLister struct { - list []*v1beta1.MutatingWebhookConfiguration - err error -} - -func (f *fakeMutatingWebhookConfigLister) List(selector labels.Selector) (ret []*v1beta1.MutatingWebhookConfiguration, err error) { - return f.list, f.err -} - -func (f *fakeMutatingWebhookConfigLister) Get(name string) (*v1beta1.MutatingWebhookConfiguration, error) { - panic("unsupported") -} - func TestGetMutatingWebhookConfig(t *testing.T) { - informer := &fakeMutatingWebhookConfigSharedInformer{ - informer: &fakeMutatingWebhookConfigInformer{}, - lister: &fakeMutatingWebhookConfigLister{}, - } + // Build a test client that the admission plugin can use to look up the MutatingWebhookConfiguration + client := fake.NewSimpleClientset() + informerFactory := informers.NewSharedInformerFactory(client, 0) + stop := make(chan struct{}) + defer close(stop) + informerFactory.Start(stop) + informerFactory.WaitForCacheSync(stop) + + configManager := NewMutatingWebhookConfigurationManager(informerFactory).(*mutatingWebhookConfigurationManager) + configManager.updateConfiguration() // no configurations - informer.lister.list = nil - manager := NewMutatingWebhookConfigurationManager(informer) - if configurations := manager.Webhooks(); len(configurations.Webhooks) != 0 { - t.Errorf("expected empty webhooks, but got %v", configurations.Webhooks) + if configurations := configManager.Webhooks(); len(configurations) != 0 { + t.Errorf("expected empty webhooks, but got %v", configurations) } - // list err webhookConfiguration := &v1beta1.MutatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{Name: "webhook1"}, Webhooks: []v1beta1.Webhook{{Name: "webhook1.1"}}, } - informer.lister.list = []*v1beta1.MutatingWebhookConfiguration{webhookConfiguration.DeepCopy()} - informer.lister.err = fmt.Errorf("mutating webhook configuration list error") - informer.informer.eventHandler.OnAdd(webhookConfiguration.DeepCopy()) - if configurations := manager.Webhooks(); len(configurations.Webhooks) != 0 { - t.Errorf("expected empty webhooks, but got %v", configurations.Webhooks) - } + + mutatingInformer := informerFactory.Admissionregistration().V1beta1().MutatingWebhookConfigurations() + mutatingInformer.Informer().GetIndexer().Add(webhookConfiguration) + configManager.updateConfiguration() // configuration populated - informer.lister.err = nil - informer.informer.eventHandler.OnAdd(webhookConfiguration.DeepCopy()) - configurations := manager.Webhooks() - if len(configurations.Webhooks) == 0 { + configurations := configManager.Webhooks() + if len(configurations) == 0 { t.Errorf("expected non empty webhooks") } - if !reflect.DeepEqual(configurations.Webhooks, webhookConfiguration.Webhooks) { - t.Errorf("Expected\n%#v\ngot\n%#v", webhookConfiguration.Webhooks, configurations.Webhooks) + if !reflect.DeepEqual(configurations, webhookConfiguration.Webhooks) { + t.Errorf("Expected\n%#v\ngot\n%#v", webhookConfiguration.Webhooks, configurations) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager.go index 33644f57f..9258258f6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager.go @@ -24,21 +24,27 @@ import ( "k8s.io/api/admissionregistration/v1beta1" "k8s.io/apimachinery/pkg/labels" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - admissionregistrationinformers "k8s.io/client-go/informers/admissionregistration/v1beta1" + "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" + "k8s.io/client-go/informers" admissionregistrationlisters "k8s.io/client-go/listers/admissionregistration/v1beta1" "k8s.io/client-go/tools/cache" ) -// ValidatingWebhookConfigurationManager collects the validating webhook objects so that they can be called. -type ValidatingWebhookConfigurationManager struct { +// validatingWebhookConfigurationManager collects the validating webhook objects so that they can be called. +type validatingWebhookConfigurationManager struct { configuration *atomic.Value lister admissionregistrationlisters.ValidatingWebhookConfigurationLister + hasSynced func() bool } -func NewValidatingWebhookConfigurationManager(informer admissionregistrationinformers.ValidatingWebhookConfigurationInformer) *ValidatingWebhookConfigurationManager { - manager := &ValidatingWebhookConfigurationManager{ +var _ generic.Source = &validatingWebhookConfigurationManager{} + +func NewValidatingWebhookConfigurationManager(f informers.SharedInformerFactory) generic.Source { + informer := f.Admissionregistration().V1beta1().ValidatingWebhookConfigurations() + manager := &validatingWebhookConfigurationManager{ configuration: &atomic.Value{}, lister: informer.Lister(), + hasSynced: informer.Informer().HasSynced, } // Start with an empty list @@ -55,11 +61,16 @@ func NewValidatingWebhookConfigurationManager(informer admissionregistrationinfo } // Webhooks returns the merged ValidatingWebhookConfiguration. -func (v *ValidatingWebhookConfigurationManager) Webhooks() *v1beta1.ValidatingWebhookConfiguration { - return v.configuration.Load().(*v1beta1.ValidatingWebhookConfiguration) +func (v *validatingWebhookConfigurationManager) Webhooks() []v1beta1.Webhook { + return v.configuration.Load().(*v1beta1.ValidatingWebhookConfiguration).Webhooks +} + +// HasSynced returns true if the shared informers have synced. +func (v *validatingWebhookConfigurationManager) HasSynced() bool { + return v.hasSynced() } -func (v *ValidatingWebhookConfigurationManager) updateConfiguration() { +func (v *validatingWebhookConfigurationManager) updateConfiguration() { configurations, err := v.lister.List(labels.Everything()) if err != nil { utilruntime.HandleError(fmt.Errorf("error updating configuration: %v", err)) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager_test.go index 6505b2b9b..153b4df48 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager_test.go @@ -17,107 +17,49 @@ limitations under the License. package configuration import ( - "fmt" "reflect" "testing" - "time" "k8s.io/api/admissionregistration/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - admissionregistrationlisters "k8s.io/client-go/listers/admissionregistration/v1beta1" - "k8s.io/client-go/tools/cache" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" ) -type fakeValidatingWebhookConfigSharedInformer struct { - informer *fakeValidatingWebhookConfigInformer - lister *fakeValidatingWebhookConfigLister -} - -func (f *fakeValidatingWebhookConfigSharedInformer) Informer() cache.SharedIndexInformer { - return f.informer -} -func (f *fakeValidatingWebhookConfigSharedInformer) Lister() admissionregistrationlisters.ValidatingWebhookConfigurationLister { - return f.lister -} - -type fakeValidatingWebhookConfigInformer struct { - eventHandler cache.ResourceEventHandler -} - -func (f *fakeValidatingWebhookConfigInformer) AddEventHandler(handler cache.ResourceEventHandler) { - fmt.Println("added handler") - f.eventHandler = handler -} -func (f *fakeValidatingWebhookConfigInformer) AddEventHandlerWithResyncPeriod(handler cache.ResourceEventHandler, resyncPeriod time.Duration) { - panic("unsupported") -} -func (f *fakeValidatingWebhookConfigInformer) GetStore() cache.Store { - panic("unsupported") -} -func (f *fakeValidatingWebhookConfigInformer) GetController() cache.Controller { - panic("unsupported") -} -func (f *fakeValidatingWebhookConfigInformer) Run(stopCh <-chan struct{}) { - panic("unsupported") -} -func (f *fakeValidatingWebhookConfigInformer) HasSynced() bool { - panic("unsupported") -} -func (f *fakeValidatingWebhookConfigInformer) LastSyncResourceVersion() string { - panic("unsupported") -} -func (f *fakeValidatingWebhookConfigInformer) AddIndexers(indexers cache.Indexers) error { - panic("unsupported") -} -func (f *fakeValidatingWebhookConfigInformer) GetIndexer() cache.Indexer { panic("unsupported") } - -type fakeValidatingWebhookConfigLister struct { - list []*v1beta1.ValidatingWebhookConfiguration - err error -} - -func (f *fakeValidatingWebhookConfigLister) List(selector labels.Selector) (ret []*v1beta1.ValidatingWebhookConfiguration, err error) { - return f.list, f.err -} - -func (f *fakeValidatingWebhookConfigLister) Get(name string) (*v1beta1.ValidatingWebhookConfiguration, error) { - panic("unsupported") -} - -func TestGettValidatingWebhookConfig(t *testing.T) { - informer := &fakeValidatingWebhookConfigSharedInformer{ - informer: &fakeValidatingWebhookConfigInformer{}, - lister: &fakeValidatingWebhookConfigLister{}, +func TestGetValidatingWebhookConfig(t *testing.T) { + // Build a test client that the admission plugin can use to look up the ValidatingWebhookConfiguration + client := fake.NewSimpleClientset() + informerFactory := informers.NewSharedInformerFactory(client, 0) + stop := make(chan struct{}) + defer close(stop) + informerFactory.Start(stop) + informerFactory.WaitForCacheSync(stop) + + manager := NewValidatingWebhookConfigurationManager(informerFactory) + if validatingConfig, ok := manager.(*validatingWebhookConfigurationManager); ok { + validatingConfig.updateConfiguration() } - // no configurations - informer.lister.list = nil - manager := NewValidatingWebhookConfigurationManager(informer) - if configurations := manager.Webhooks(); len(configurations.Webhooks) != 0 { - t.Errorf("expected empty webhooks, but got %v", configurations.Webhooks) + if configurations := manager.Webhooks(); len(configurations) != 0 { + t.Errorf("expected empty webhooks, but got %v", configurations) } - // list error webhookConfiguration := &v1beta1.ValidatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{Name: "webhook1"}, Webhooks: []v1beta1.Webhook{{Name: "webhook1.1"}}, } - informer.lister.list = []*v1beta1.ValidatingWebhookConfiguration{webhookConfiguration.DeepCopy()} - informer.lister.err = fmt.Errorf("validating webhook configuration list error") - informer.informer.eventHandler.OnAdd(webhookConfiguration.DeepCopy()) - if configurations := manager.Webhooks(); len(configurations.Webhooks) != 0 { - t.Errorf("expected empty webhooks, but got %v", configurations.Webhooks) - } + validatingInformer := informerFactory.Admissionregistration().V1beta1().ValidatingWebhookConfigurations() + validatingInformer.Informer().GetIndexer().Add(webhookConfiguration) + if validatingConfig, ok := manager.(*validatingWebhookConfigurationManager); ok { + validatingConfig.updateConfiguration() + } // configuration populated - informer.lister.err = nil - informer.informer.eventHandler.OnAdd(webhookConfiguration.DeepCopy()) configurations := manager.Webhooks() - if len(configurations.Webhooks) == 0 { + if len(configurations) == 0 { t.Errorf("expected non empty webhooks") } - if !reflect.DeepEqual(configurations.Webhooks, webhookConfiguration.Webhooks) { - t.Errorf("Expected\n%#v\ngot\n%#v", webhookConfiguration.Webhooks, configurations.Webhooks) + if !reflect.DeepEqual(configurations, webhookConfiguration.Webhooks) { + t.Errorf("Expected\n%#v\ngot\n%#v", webhookConfiguration.Webhooks, configurations) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go index 76d3864e2..68ef558da 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/interfaces.go @@ -49,6 +49,23 @@ type Attributes interface { GetKind() schema.GroupVersionKind // GetUserInfo is information about the requesting user GetUserInfo() user.Info + + // AddAnnotation sets annotation according to key-value pair. The key should be qualified, e.g., podsecuritypolicy.admission.k8s.io/admit-policy, where + // "podsecuritypolicy" is the name of the plugin, "admission.k8s.io" is the name of the organization, "admit-policy" is the key name. + // An error is returned if the format of key is invalid. When trying to overwrite annotation with a new value, an error is returned. + // Both ValidationInterface and MutationInterface are allowed to add Annotations. + AddAnnotation(key, value string) error +} + +// privateAnnotationsGetter is a private interface which allows users to get annotations from Attributes. +type privateAnnotationsGetter interface { + getAnnotations() map[string]string +} + +// AnnotationsGetter allows users to get annotations from Attributes. An alternate Attribute should implement +// this interface. +type AnnotationsGetter interface { + GetAnnotations() map[string]string } // Interface is an abstract, pluggable interface for Admission Control decisions. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install/BUILD index 867b0a9aa..c6a9e7c18 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install/BUILD @@ -6,9 +6,8 @@ go_library( importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install", visibility = ["//visibility:public"], deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install/install.go index bbb3eaf62..b08fe72ea 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission" "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: webhookadmission.GroupName, - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: webhookadmission.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(webhookadmission.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.conversion.go index 190d47744..3fb2e24ce 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.deepcopy.go index f89cef9d3..a59d62d6c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/zz_generated.deepcopy.go index 4ec1eade1..90b7e0ae6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/client.go index 1be5503ae..d520fd032 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/client.go @@ -17,6 +17,7 @@ limitations under the License. package config import ( + "context" "encoding/json" "errors" "fmt" @@ -50,7 +51,7 @@ type ClientManager struct { cache *lru.Cache } -// NewClientManager creates a ClientManager. +// NewClientManager creates a clientManager. func NewClientManager() (ClientManager, error) { cache, err := lru.New(defaultCacheSize) if err != nil { @@ -90,13 +91,13 @@ func (cm *ClientManager) SetServiceResolver(sr ServiceResolver) { func (cm *ClientManager) Validate() error { var errs []error if cm.negotiatedSerializer == nil { - errs = append(errs, fmt.Errorf("the ClientManager requires a negotiatedSerializer")) + errs = append(errs, fmt.Errorf("the clientManager requires a negotiatedSerializer")) } if cm.serviceResolver == nil { - errs = append(errs, fmt.Errorf("the ClientManager requires a serviceResolver")) + errs = append(errs, fmt.Errorf("the clientManager requires a serviceResolver")) } if cm.authInfoResolver == nil { - errs = append(errs, fmt.Errorf("the ClientManager requires an authInfoResolver")) + errs = append(errs, fmt.Errorf("the clientManager requires an authInfoResolver")) } return utilerrors.NewAggregate(errs) } @@ -147,9 +148,10 @@ func (cm *ClientManager) HookClient(h *v1beta1.Webhook) (*rest.RESTClient, error delegateDialer := cfg.Dial if delegateDialer == nil { - delegateDialer = net.Dial + var d net.Dialer + delegateDialer = d.DialContext } - cfg.Dial = func(network, addr string) (net.Conn, error) { + cfg.Dial = func(ctx context.Context, network, addr string) (net.Conn, error) { if addr == host { u, err := cm.serviceResolver.ResolveEndpoint(svc.Namespace, svc.Name) if err != nil { @@ -157,7 +159,7 @@ func (cm *ClientManager) HookClient(h *v1beta1.Webhook) (*rest.RESTClient, error } addr = u.Host } - return delegateDialer(network, addr) + return delegateDialer(ctx, network, addr) } return complete(cfg) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/BUILD new file mode 100644 index 000000000..bc1468332 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/BUILD @@ -0,0 +1,54 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "conversion.go", + "interfaces.go", + "webhook.go", + ], + importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/generic", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors: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/apiserver/pkg/admission:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/rules:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["conversion_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/apiserver/pkg/apis/example:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/example/v1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/example2/v1:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion.go new file mode 100644 index 000000000..a75c63fa9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion.go @@ -0,0 +1,55 @@ +/* +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 generic + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// convertor converts objects to the desired version. +type convertor struct { + Scheme *runtime.Scheme +} + +// ConvertToGVK converts object to the desired gvk. +func (c *convertor) ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind) (runtime.Object, error) { + // Unlike other resources, custom resources do not have internal version, so + // if obj is a custom resource, it should not need conversion. + if obj.GetObjectKind().GroupVersionKind() == gvk { + return obj, nil + } + out, err := c.Scheme.New(gvk) + if err != nil { + return nil, err + } + err = c.Scheme.Convert(obj, out, nil) + if err != nil { + return nil, err + } + return out, nil +} + +// Validate checks if the conversion has a scheme. +func (c *convertor) Validate() error { + if c.Scheme == nil { + return fmt.Errorf("the convertor requires a scheme") + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion_test.go new file mode 100644 index 000000000..704c24638 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/conversion_test.go @@ -0,0 +1,151 @@ +/* +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 generic + +import ( + "reflect" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apiserver/pkg/apis/example" + examplev1 "k8s.io/apiserver/pkg/apis/example/v1" + example2v1 "k8s.io/apiserver/pkg/apis/example2/v1" +) + +func initiateScheme() *runtime.Scheme { + s := runtime.NewScheme() + example.AddToScheme(s) + examplev1.AddToScheme(s) + example2v1.AddToScheme(s) + return s +} + +func TestConvertToGVK(t *testing.T) { + scheme := initiateScheme() + c := convertor{Scheme: scheme} + table := map[string]struct { + obj runtime.Object + gvk schema.GroupVersionKind + expectedObj runtime.Object + }{ + "convert example#Pod to example/v1#Pod": { + obj: &example.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Labels: map[string]string{ + "key": "value", + }, + }, + Spec: example.PodSpec{ + RestartPolicy: example.RestartPolicy("never"), + }, + }, + gvk: examplev1.SchemeGroupVersion.WithKind("Pod"), + expectedObj: &examplev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Labels: map[string]string{ + "key": "value", + }, + }, + Spec: examplev1.PodSpec{ + RestartPolicy: examplev1.RestartPolicy("never"), + }, + }, + }, + "convert example#replicaset to example2/v1#replicaset": { + obj: &example.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "rs1", + Labels: map[string]string{ + "key": "value", + }, + }, + Spec: example.ReplicaSetSpec{ + Replicas: 1, + }, + }, + gvk: example2v1.SchemeGroupVersion.WithKind("ReplicaSet"), + expectedObj: &example2v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "rs1", + Labels: map[string]string{ + "key": "value", + }, + }, + Spec: example2v1.ReplicaSetSpec{ + Replicas: func() *int32 { var i int32; i = 1; return &i }(), + }, + }, + }, + "no conversion for Unstructured object whose gvk matches the desired gvk": { + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "mygroup.k8s.io/v1", + "kind": "Flunder", + "data": map[string]interface{}{ + "Key": "Value", + }, + }, + }, + gvk: schema.GroupVersionKind{Group: "mygroup.k8s.io", Version: "v1", Kind: "Flunder"}, + expectedObj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "mygroup.k8s.io/v1", + "kind": "Flunder", + "data": map[string]interface{}{ + "Key": "Value", + }, + }, + }, + }, + } + + for name, test := range table { + t.Run(name, func(t *testing.T) { + actual, err := c.ConvertToGVK(test.obj, test.gvk) + if err != nil { + t.Error(err) + } + if !reflect.DeepEqual(actual, test.expectedObj) { + t.Errorf("\nexpected:\n%#v\ngot:\n %#v\n", test.expectedObj, actual) + } + }) + } +} + +// TestRuntimeSchemeConvert verifies that scheme.Convert(x, x, nil) for an unstructured x is a no-op. +// This did not use to be like that and we had to wrap scheme.Convert before. +func TestRuntimeSchemeConvert(t *testing.T) { + scheme := initiateScheme() + obj := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "foo": "bar", + }, + } + clone := obj.DeepCopy() + + if err := scheme.Convert(obj, obj, nil); err != nil { + t.Fatalf("unexpected convert error: %v", err) + } + if !reflect.DeepEqual(obj, clone) { + t.Errorf("unexpected mutation of self-converted Unstructured: obj=%#v, clone=%#v", obj, clone) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/interfaces.go new file mode 100644 index 000000000..3a7edb526 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/interfaces.go @@ -0,0 +1,45 @@ +/* +Copyright 2018 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 generic + +import ( + "context" + + "k8s.io/api/admissionregistration/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/admission" +) + +// Source can list dynamic webhook plugins. +type Source interface { + Webhooks() []v1beta1.Webhook + HasSynced() bool +} + +// VersionedAttributes is a wrapper around the original admission attributes, adding versioned +// variants of the object and old object. +type VersionedAttributes struct { + admission.Attributes + VersionedOldObject runtime.Object + VersionedObject runtime.Object +} + +// Dispatcher dispatches webhook call to a list of webhooks with admission attributes as argument. +type Dispatcher interface { + // Dispatch a request to the webhooks using the given webhooks. A non-nil error means the request is rejected. + Dispatch(ctx context.Context, a *VersionedAttributes, hooks []*v1beta1.Webhook) error +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go new file mode 100644 index 000000000..fdcbdd9e1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go @@ -0,0 +1,202 @@ +/* +Copyright 2018 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 generic + +import ( + "context" + "fmt" + "io" + + "k8s.io/api/admissionregistration/v1beta1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/admission" + genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer" + "k8s.io/apiserver/pkg/admission/plugin/webhook/config" + "k8s.io/apiserver/pkg/admission/plugin/webhook/namespace" + "k8s.io/apiserver/pkg/admission/plugin/webhook/rules" + "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" +) + +// Webhook is an abstract admission plugin with all the infrastructure to define Admit or Validate on-top. +type Webhook struct { + *admission.Handler + + sourceFactory sourceFactory + + hookSource Source + clientManager *config.ClientManager + convertor *convertor + namespaceMatcher *namespace.Matcher + dispatcher Dispatcher +} + +var ( + _ genericadmissioninit.WantsExternalKubeClientSet = &Webhook{} + _ admission.Interface = &Webhook{} +) + +type sourceFactory func(f informers.SharedInformerFactory) Source +type dispatcherFactory func(cm *config.ClientManager) Dispatcher + +// NewWebhook creates a new generic admission webhook. +func NewWebhook(handler *admission.Handler, configFile io.Reader, sourceFactory sourceFactory, dispatcherFactory dispatcherFactory) (*Webhook, error) { + kubeconfigFile, err := config.LoadConfig(configFile) + if err != nil { + return nil, err + } + + cm, err := config.NewClientManager() + if err != nil { + return nil, err + } + authInfoResolver, err := config.NewDefaultAuthenticationInfoResolver(kubeconfigFile) + if err != nil { + return nil, err + } + // Set defaults which may be overridden later. + cm.SetAuthenticationInfoResolver(authInfoResolver) + cm.SetServiceResolver(config.NewDefaultServiceResolver()) + + return &Webhook{ + Handler: handler, + sourceFactory: sourceFactory, + clientManager: &cm, + convertor: &convertor{}, + namespaceMatcher: &namespace.Matcher{}, + dispatcher: dispatcherFactory(&cm), + }, nil +} + +// SetAuthenticationInfoResolverWrapper sets the +// AuthenticationInfoResolverWrapper. +// TODO find a better way wire this, but keep this pull small for now. +func (a *Webhook) SetAuthenticationInfoResolverWrapper(wrapper config.AuthenticationInfoResolverWrapper) { + a.clientManager.SetAuthenticationInfoResolverWrapper(wrapper) +} + +// SetServiceResolver sets a service resolver for the webhook admission plugin. +// Passing a nil resolver does not have an effect, instead a default one will be used. +func (a *Webhook) SetServiceResolver(sr config.ServiceResolver) { + a.clientManager.SetServiceResolver(sr) +} + +// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme +func (a *Webhook) SetScheme(scheme *runtime.Scheme) { + if scheme != nil { + a.convertor.Scheme = scheme + } +} + +// SetExternalKubeClientSet implements the WantsExternalKubeInformerFactory interface. +// It sets external ClientSet for admission plugins that need it +func (a *Webhook) SetExternalKubeClientSet(client clientset.Interface) { + a.namespaceMatcher.Client = client +} + +// SetExternalKubeInformerFactory implements the WantsExternalKubeInformerFactory interface. +func (a *Webhook) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) { + namespaceInformer := f.Core().V1().Namespaces() + a.namespaceMatcher.NamespaceLister = namespaceInformer.Lister() + a.hookSource = a.sourceFactory(f) + a.SetReadyFunc(func() bool { + return namespaceInformer.Informer().HasSynced() && a.hookSource.HasSynced() + }) +} + +// ValidateInitialization implements the InitializationValidator interface. +func (a *Webhook) ValidateInitialization() error { + if a.hookSource == nil { + return fmt.Errorf("kubernetes client is not properly setup") + } + if err := a.namespaceMatcher.Validate(); err != nil { + return fmt.Errorf("namespaceMatcher is not properly setup: %v", err) + } + if err := a.clientManager.Validate(); err != nil { + return fmt.Errorf("clientManager is not properly setup: %v", err) + } + if err := a.convertor.Validate(); err != nil { + return fmt.Errorf("convertor is not properly setup: %v", err) + } + return nil +} + +// ShouldCallHook makes a decision on whether to call the webhook or not by the attribute. +func (a *Webhook) ShouldCallHook(h *v1beta1.Webhook, attr admission.Attributes) (bool, *apierrors.StatusError) { + var matches bool + for _, r := range h.Rules { + m := rules.Matcher{Rule: r, Attr: attr} + if m.Matches() { + matches = true + break + } + } + if !matches { + return false, nil + } + + return a.namespaceMatcher.MatchNamespaceSelector(h, attr) +} + +// Dispatch is called by the downstream Validate or Admit methods. +func (a *Webhook) Dispatch(attr admission.Attributes) error { + if rules.IsWebhookConfigurationResource(attr) { + return nil + } + if !a.WaitForReady() { + return admission.NewForbidden(attr, fmt.Errorf("not yet ready to handle request")) + } + hooks := a.hookSource.Webhooks() + ctx := context.TODO() + + var relevantHooks []*v1beta1.Webhook + for i := range hooks { + call, err := a.ShouldCallHook(&hooks[i], attr) + if err != nil { + return err + } + if call { + relevantHooks = append(relevantHooks, &hooks[i]) + } + } + + if len(relevantHooks) == 0 { + // no matching hooks + return nil + } + + // convert the object to the external version before sending it to the webhook + versionedAttr := VersionedAttributes{ + Attributes: attr, + } + if oldObj := attr.GetOldObject(); oldObj != nil { + out, err := a.convertor.ConvertToGVK(oldObj, attr.GetKind()) + if err != nil { + return apierrors.NewInternalError(err) + } + versionedAttr.VersionedOldObject = out + } + if obj := attr.GetObject(); obj != nil { + out, err := a.convertor.ConvertToGVK(obj, attr.GetKind()) + if err != nil { + return apierrors.NewInternalError(err) + } + versionedAttr.VersionedObject = out + } + return a.dispatcher.Dispatch(ctx, &versionedAttr, relevantHooks) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD index 36f81528c..460ecab2a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/BUILD @@ -3,8 +3,9 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "admission.go", + "dispatcher.go", "doc.go", + "plugin.go", ], importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating", visibility = ["//visibility:public"], @@ -14,41 +15,41 @@ go_library( "//vendor/k8s.io/api/admission/v1beta1:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/configuration:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/metrics:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/request:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/rules:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned:go_default_library", - "//vendor/k8s.io/client-go/informers:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) go_test( name = "go_default_test", - srcs = ["admission_test.go"], + srcs = [ + "dispatcher_test.go", + "plugin_test.go", + ], embed = [":go_default_library"], deps = [ "//vendor/k8s.io/api/admission/v1beta1:go_default_library", - "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/apiserver/pkg/admission:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts:go_default_library", - "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/testing:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/example:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/example/v1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/example2/v1:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/admission.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/admission.go deleted file mode 100644 index 57f82d4d5..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/admission.go +++ /dev/null @@ -1,311 +0,0 @@ -/* -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 mutating delegates admission checks to dynamically configured -// mutating webhooks. -package mutating - -import ( - "context" - "fmt" - "io" - "time" - - jsonpatch "github.com/evanphx/json-patch" - "github.com/golang/glog" - - admissionv1beta1 "k8s.io/api/admission/v1beta1" - "k8s.io/api/admissionregistration/v1beta1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/serializer/json" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apiserver/pkg/admission" - "k8s.io/apiserver/pkg/admission/configuration" - genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer" - admissionmetrics "k8s.io/apiserver/pkg/admission/metrics" - "k8s.io/apiserver/pkg/admission/plugin/webhook/config" - webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors" - "k8s.io/apiserver/pkg/admission/plugin/webhook/namespace" - "k8s.io/apiserver/pkg/admission/plugin/webhook/request" - "k8s.io/apiserver/pkg/admission/plugin/webhook/rules" - "k8s.io/apiserver/pkg/admission/plugin/webhook/versioned" - "k8s.io/client-go/informers" - clientset "k8s.io/client-go/kubernetes" -) - -const ( - // Name of admission plug-in - PluginName = "MutatingAdmissionWebhook" -) - -// Register registers a plugin -func Register(plugins *admission.Plugins) { - plugins.Register(PluginName, func(configFile io.Reader) (admission.Interface, error) { - plugin, err := NewMutatingWebhook(configFile) - if err != nil { - return nil, err - } - - return plugin, nil - }) -} - -// WebhookSource can list dynamic webhook plugins. -type WebhookSource interface { - Webhooks() *v1beta1.MutatingWebhookConfiguration -} - -// NewMutatingWebhook returns a generic admission webhook plugin. -func NewMutatingWebhook(configFile io.Reader) (*MutatingWebhook, error) { - kubeconfigFile, err := config.LoadConfig(configFile) - if err != nil { - return nil, err - } - - cm, err := config.NewClientManager() - if err != nil { - return nil, err - } - authInfoResolver, err := config.NewDefaultAuthenticationInfoResolver(kubeconfigFile) - if err != nil { - return nil, err - } - // Set defaults which may be overridden later. - cm.SetAuthenticationInfoResolver(authInfoResolver) - cm.SetServiceResolver(config.NewDefaultServiceResolver()) - - return &MutatingWebhook{ - Handler: admission.NewHandler( - admission.Connect, - admission.Create, - admission.Delete, - admission.Update, - ), - clientManager: cm, - }, nil -} - -var _ admission.MutationInterface = &MutatingWebhook{} - -// MutatingWebhook is an implementation of admission.Interface. -type MutatingWebhook struct { - *admission.Handler - hookSource WebhookSource - namespaceMatcher namespace.Matcher - clientManager config.ClientManager - convertor versioned.Convertor - defaulter runtime.ObjectDefaulter - jsonSerializer runtime.Serializer -} - -var ( - _ = genericadmissioninit.WantsExternalKubeClientSet(&MutatingWebhook{}) -) - -// TODO find a better way wire this, but keep this pull small for now. -func (a *MutatingWebhook) SetAuthenticationInfoResolverWrapper(wrapper config.AuthenticationInfoResolverWrapper) { - a.clientManager.SetAuthenticationInfoResolverWrapper(wrapper) -} - -// SetServiceResolver sets a service resolver for the webhook admission plugin. -// Passing a nil resolver does not have an effect, instead a default one will be used. -func (a *MutatingWebhook) SetServiceResolver(sr config.ServiceResolver) { - a.clientManager.SetServiceResolver(sr) -} - -// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme -func (a *MutatingWebhook) SetScheme(scheme *runtime.Scheme) { - if scheme != nil { - a.convertor.Scheme = scheme - a.defaulter = scheme - a.jsonSerializer = json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false) - } -} - -// WantsExternalKubeClientSet defines a function which sets external ClientSet for admission plugins that need it -func (a *MutatingWebhook) SetExternalKubeClientSet(client clientset.Interface) { - a.namespaceMatcher.Client = client -} - -// SetExternalKubeInformerFactory implements the WantsExternalKubeInformerFactory interface. -func (a *MutatingWebhook) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) { - namespaceInformer := f.Core().V1().Namespaces() - a.namespaceMatcher.NamespaceLister = namespaceInformer.Lister() - mutatingWebhookConfigurationsInformer := f.Admissionregistration().V1beta1().MutatingWebhookConfigurations() - a.hookSource = configuration.NewMutatingWebhookConfigurationManager(mutatingWebhookConfigurationsInformer) - a.SetReadyFunc(func() bool { - return namespaceInformer.Informer().HasSynced() && mutatingWebhookConfigurationsInformer.Informer().HasSynced() - }) -} - -// ValidateInitialization implements the InitializationValidator interface. -func (a *MutatingWebhook) ValidateInitialization() error { - if a.hookSource == nil { - return fmt.Errorf("MutatingWebhook admission plugin requires a Kubernetes client to be provided") - } - if a.jsonSerializer == nil { - return fmt.Errorf("MutatingWebhook admission plugin's jsonSerializer is not properly setup") - } - if err := a.namespaceMatcher.Validate(); err != nil { - return fmt.Errorf("MutatingWebhook.namespaceMatcher is not properly setup: %v", err) - } - if err := a.clientManager.Validate(); err != nil { - return fmt.Errorf("MutatingWebhook.clientManager is not properly setup: %v", err) - } - if err := a.convertor.Validate(); err != nil { - return fmt.Errorf("MutatingWebhook.convertor is not properly setup: %v", err) - } - if a.defaulter == nil { - return fmt.Errorf("MutatingWebhook.defaulter is not properly setup") - } - return nil -} - -func (a *MutatingWebhook) loadConfiguration(attr admission.Attributes) *v1beta1.MutatingWebhookConfiguration { - hookConfig := a.hookSource.Webhooks() - return hookConfig -} - -// Admit makes an admission decision based on the request attributes. -func (a *MutatingWebhook) Admit(attr admission.Attributes) error { - if rules.IsWebhookConfigurationResource(attr) { - return nil - } - - if !a.WaitForReady() { - return admission.NewForbidden(attr, fmt.Errorf("not yet ready to handle request")) - } - - hookConfig := a.loadConfiguration(attr) - hooks := hookConfig.Webhooks - ctx := context.TODO() - - var relevantHooks []*v1beta1.Webhook - for i := range hooks { - call, err := a.shouldCallHook(&hooks[i], attr) - if err != nil { - return err - } - if call { - relevantHooks = append(relevantHooks, &hooks[i]) - } - } - - if len(relevantHooks) == 0 { - // no matching hooks - return nil - } - - // convert the object to the external version before sending it to the webhook - versionedAttr := versioned.Attributes{ - Attributes: attr, - } - if oldObj := attr.GetOldObject(); oldObj != nil { - out, err := a.convertor.ConvertToGVK(oldObj, attr.GetKind()) - if err != nil { - return apierrors.NewInternalError(err) - } - versionedAttr.OldObject = out - } - if obj := attr.GetObject(); obj != nil { - out, err := a.convertor.ConvertToGVK(obj, attr.GetKind()) - if err != nil { - return apierrors.NewInternalError(err) - } - versionedAttr.Object = out - } - - for _, hook := range relevantHooks { - t := time.Now() - err := a.callAttrMutatingHook(ctx, hook, versionedAttr) - admissionmetrics.Metrics.ObserveWebhook(time.Since(t), err != nil, attr, "admit", hook.Name) - if err == nil { - continue - } - - ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore - if callErr, ok := err.(*webhookerrors.ErrCallingWebhook); ok { - if ignoreClientCallFailures { - glog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr) - utilruntime.HandleError(callErr) - continue - } - glog.Warningf("Failed calling webhook, failing closed %v: %v", hook.Name, err) - } - return apierrors.NewInternalError(err) - } - - // convert attr.Object to the internal version - return a.convertor.Convert(versionedAttr.Object, attr.GetObject()) -} - -// TODO: factor into a common place along with the validating webhook version. -func (a *MutatingWebhook) shouldCallHook(h *v1beta1.Webhook, attr admission.Attributes) (bool, *apierrors.StatusError) { - var matches bool - for _, r := range h.Rules { - m := rules.Matcher{Rule: r, Attr: attr} - if m.Matches() { - matches = true - break - } - } - if !matches { - return false, nil - } - - return a.namespaceMatcher.MatchNamespaceSelector(h, attr) -} - -// note that callAttrMutatingHook updates attr -func (a *MutatingWebhook) callAttrMutatingHook(ctx context.Context, h *v1beta1.Webhook, attr versioned.Attributes) error { - // Make the webhook request - request := request.CreateAdmissionReview(attr) - client, err := a.clientManager.HookClient(h) - if err != nil { - return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err} - } - response := &admissionv1beta1.AdmissionReview{} - if err := client.Post().Context(ctx).Body(&request).Do().Into(response); err != nil { - return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err} - } - - if !response.Response.Allowed { - return webhookerrors.ToStatusErr(h.Name, response.Response.Result) - } - - patchJS := response.Response.Patch - if len(patchJS) == 0 { - return nil - } - patchObj, err := jsonpatch.DecodePatch(patchJS) - if err != nil { - return apierrors.NewInternalError(err) - } - objJS, err := runtime.Encode(a.jsonSerializer, attr.Object) - if err != nil { - return apierrors.NewInternalError(err) - } - patchedJS, err := patchObj.Apply(objJS) - if err != nil { - return apierrors.NewInternalError(err) - } - if _, _, err := a.jsonSerializer.Decode(patchedJS, nil, attr.Object); err != nil { - return apierrors.NewInternalError(err) - } - a.defaulter.Default(attr.Object) - return nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/admission_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/admission_test.go deleted file mode 100644 index 523e03762..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/admission_test.go +++ /dev/null @@ -1,653 +0,0 @@ -/* -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 mutating - -import ( - "crypto/tls" - "crypto/x509" - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "strings" - "sync/atomic" - "testing" - - "k8s.io/api/admission/v1beta1" - registrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apiserver/pkg/admission" - "k8s.io/apiserver/pkg/admission/plugin/webhook/config" - "k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts" - "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/client-go/rest" -) - -type fakeHookSource struct { - hooks []registrationv1beta1.Webhook - err error -} - -func (f *fakeHookSource) Webhooks() *registrationv1beta1.MutatingWebhookConfiguration { - if f.err != nil { - return nil - } - for i, h := range f.hooks { - if h.NamespaceSelector == nil { - f.hooks[i].NamespaceSelector = &metav1.LabelSelector{} - } - } - return ®istrationv1beta1.MutatingWebhookConfiguration{Webhooks: f.hooks} -} - -func (f *fakeHookSource) Run(stopCh <-chan struct{}) {} - -type fakeServiceResolver struct { - base url.URL -} - -func (f fakeServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { - if namespace == "failResolve" { - return nil, fmt.Errorf("couldn't resolve service location") - } - u := f.base - return &u, nil -} - -type fakeNamespaceLister struct { - namespaces map[string]*corev1.Namespace -} - -func (f fakeNamespaceLister) List(selector labels.Selector) (ret []*corev1.Namespace, err error) { - return nil, nil -} -func (f fakeNamespaceLister) Get(name string) (*corev1.Namespace, error) { - ns, ok := f.namespaces[name] - if ok { - return ns, nil - } - return nil, errors.NewNotFound(corev1.Resource("namespaces"), name) -} - -// ccfgSVC returns a client config using the service reference mechanism. -func ccfgSVC(urlPath string) registrationv1beta1.WebhookClientConfig { - return registrationv1beta1.WebhookClientConfig{ - Service: ®istrationv1beta1.ServiceReference{ - Name: "webhook-test", - Namespace: "default", - Path: &urlPath, - }, - CABundle: testcerts.CACert, - } -} - -type urlConfigGenerator struct { - baseURL *url.URL -} - -// ccfgURL returns a client config using the URL mechanism. -func (c urlConfigGenerator) ccfgURL(urlPath string) registrationv1beta1.WebhookClientConfig { - u2 := *c.baseURL - u2.Path = urlPath - urlString := u2.String() - return registrationv1beta1.WebhookClientConfig{ - URL: &urlString, - CABundle: testcerts.CACert, - } -} - -// TestAdmit tests that MutatingWebhook#Admit works as expected -func TestAdmit(t *testing.T) { - scheme := runtime.NewScheme() - v1beta1.AddToScheme(scheme) - corev1.AddToScheme(scheme) - - testServer := newTestServer(t) - testServer.StartTLS() - defer testServer.Close() - serverURL, err := url.ParseRequestURI(testServer.URL) - if err != nil { - t.Fatalf("this should never happen? %v", err) - } - wh, err := NewMutatingWebhook(nil) - if err != nil { - t.Fatal(err) - } - cm, err := config.NewClientManager() - if err != nil { - t.Fatalf("cannot create client manager: %v", err) - } - cm.SetAuthenticationInfoResolver(newFakeAuthenticationInfoResolver(new(int32))) - cm.SetServiceResolver(fakeServiceResolver{base: *serverURL}) - wh.clientManager = cm - wh.SetScheme(scheme) - if err = wh.clientManager.Validate(); err != nil { - t.Fatal(err) - } - namespace := "webhook-test" - wh.namespaceMatcher.NamespaceLister = fakeNamespaceLister{map[string]*corev1.Namespace{ - namespace: { - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "runlevel": "0", - }, - }, - }, - }, - } - - // Set up a test object for the call - kind := corev1.SchemeGroupVersion.WithKind("Pod") - name := "my-pod" - object := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "pod.name": name, - }, - Name: name, - Namespace: namespace, - }, - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Pod", - }, - } - oldObject := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}, - } - operation := admission.Update - resource := corev1.Resource("pods").WithVersion("v1") - subResource := "" - userInfo := user.DefaultInfo{ - Name: "webhook-test", - UID: "webhook-test", - } - - ccfgURL := urlConfigGenerator{serverURL}.ccfgURL - - type test struct { - hookSource fakeHookSource - path string - expectAllow bool - errorContains string - } - - matchEverythingRules := []registrationv1beta1.RuleWithOperations{{ - Operations: []registrationv1beta1.OperationType{registrationv1beta1.OperationAll}, - Rule: registrationv1beta1.Rule{ - APIGroups: []string{"*"}, - APIVersions: []string{"*"}, - Resources: []string{"*/*"}, - }, - }} - - policyFail := registrationv1beta1.Fail - policyIgnore := registrationv1beta1.Ignore - - table := map[string]test{ - "no match": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "nomatch", - ClientConfig: ccfgSVC("disallow"), - Rules: []registrationv1beta1.RuleWithOperations{{ - Operations: []registrationv1beta1.OperationType{registrationv1beta1.Create}, - }}, - }}, - }, - expectAllow: true, - }, - "match & allow": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "allow", - ClientConfig: ccfgSVC("allow"), - Rules: matchEverythingRules, - }}, - }, - expectAllow: true, - }, - "match & disallow": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallow", - ClientConfig: ccfgSVC("disallow"), - Rules: matchEverythingRules, - }}, - }, - errorContains: "without explanation", - }, - "match & disallow ii": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallowReason", - ClientConfig: ccfgSVC("disallowReason"), - Rules: matchEverythingRules, - }}, - }, - errorContains: "you shall not pass", - }, - "match & disallow & but allowed because namespaceSelector exempt the namespace": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallow", - ClientConfig: ccfgSVC("disallow"), - Rules: newMatchEverythingRules(), - NamespaceSelector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{{ - Key: "runlevel", - Values: []string{"1"}, - Operator: metav1.LabelSelectorOpIn, - }}, - }, - }}, - }, - expectAllow: true, - }, - "match & disallow & but allowed because namespaceSelector exempt the namespace ii": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallow", - ClientConfig: ccfgSVC("disallow"), - Rules: newMatchEverythingRules(), - NamespaceSelector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{{ - Key: "runlevel", - Values: []string{"0"}, - Operator: metav1.LabelSelectorOpNotIn, - }}, - }, - }}, - }, - expectAllow: true, - }, - "match & fail (but allow because fail open)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "internalErr A", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyIgnore, - }, { - Name: "internalErr B", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyIgnore, - }, { - Name: "internalErr C", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - }, - "match & fail (but disallow because fail closed on nil)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "internalErr A", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - }, { - Name: "internalErr B", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - }, { - Name: "internalErr C", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - }}, - }, - expectAllow: false, - }, - "match & fail (but fail because fail closed)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "internalErr A", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyFail, - }, { - Name: "internalErr B", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyFail, - }, { - Name: "internalErr C", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyFail, - }}, - }, - expectAllow: false, - }, - "match & allow (url)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "allow", - ClientConfig: ccfgURL("allow"), - Rules: matchEverythingRules, - }}, - }, - expectAllow: true, - }, - "match & disallow (url)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallow", - ClientConfig: ccfgURL("disallow"), - Rules: matchEverythingRules, - }}, - }, - errorContains: "without explanation", - }, - // No need to test everything with the url case, since only the - // connection is different. - } - - for name, tt := range table { - if !strings.Contains(name, "no match") { - continue - } - t.Run(name, func(t *testing.T) { - wh.hookSource = &tt.hookSource - err = wh.Admit(admission.NewAttributesRecord(&object, &oldObject, kind, namespace, name, resource, subResource, operation, &userInfo)) - if tt.expectAllow != (err == nil) { - t.Errorf("expected allowed=%v, but got err=%v", tt.expectAllow, err) - } - // ErrWebhookRejected is not an error for our purposes - if tt.errorContains != "" { - if err == nil || !strings.Contains(err.Error(), tt.errorContains) { - t.Errorf(" expected an error saying %q, but got %v", tt.errorContains, err) - } - } - if _, isStatusErr := err.(*errors.StatusError); err != nil && !isStatusErr { - t.Errorf("%s: expected a StatusError, got %T", name, err) - } - }) - } -} - -// TestAdmitCachedClient tests that MutatingWebhook#Admit should cache restClient -func TestAdmitCachedClient(t *testing.T) { - scheme := runtime.NewScheme() - v1beta1.AddToScheme(scheme) - corev1.AddToScheme(scheme) - - testServer := newTestServer(t) - testServer.StartTLS() - defer testServer.Close() - serverURL, err := url.ParseRequestURI(testServer.URL) - if err != nil { - t.Fatalf("this should never happen? %v", err) - } - wh, err := NewMutatingWebhook(nil) - if err != nil { - t.Fatal(err) - } - cm, err := config.NewClientManager() - if err != nil { - t.Fatalf("cannot create client manager: %v", err) - } - cm.SetServiceResolver(fakeServiceResolver{base: *serverURL}) - wh.clientManager = cm - wh.SetScheme(scheme) - namespace := "webhook-test" - wh.namespaceMatcher.NamespaceLister = fakeNamespaceLister{map[string]*corev1.Namespace{ - namespace: { - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "runlevel": "0", - }, - }, - }, - }, - } - - // Set up a test object for the call - kind := corev1.SchemeGroupVersion.WithKind("Pod") - name := "my-pod" - object := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "pod.name": name, - }, - Name: name, - Namespace: namespace, - }, - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Pod", - }, - } - oldObject := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}, - } - operation := admission.Update - resource := corev1.Resource("pods").WithVersion("v1") - subResource := "" - userInfo := user.DefaultInfo{ - Name: "webhook-test", - UID: "webhook-test", - } - ccfgURL := urlConfigGenerator{serverURL}.ccfgURL - - type test struct { - name string - hookSource fakeHookSource - expectAllow bool - expectCache bool - } - - policyIgnore := registrationv1beta1.Ignore - cases := []test{ - { - name: "cache 1", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache1", - ClientConfig: ccfgSVC("allow"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: true, - }, - { - name: "cache 2", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache2", - ClientConfig: ccfgSVC("internalErr"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: true, - }, - { - name: "cache 3", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache3", - ClientConfig: ccfgSVC("allow"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: false, - }, - { - name: "cache 4", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache4", - ClientConfig: ccfgURL("allow"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: true, - }, - { - name: "cache 5", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache5", - ClientConfig: ccfgURL("allow"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: false, - }, - } - - for _, testcase := range cases { - t.Run(testcase.name, func(t *testing.T) { - wh.hookSource = &testcase.hookSource - authInfoResolverCount := new(int32) - r := newFakeAuthenticationInfoResolver(authInfoResolverCount) - wh.clientManager.SetAuthenticationInfoResolver(r) - if err = wh.clientManager.Validate(); err != nil { - t.Fatal(err) - } - - err = wh.Admit(admission.NewAttributesRecord(&object, &oldObject, kind, namespace, testcase.name, resource, subResource, operation, &userInfo)) - if testcase.expectAllow != (err == nil) { - t.Errorf("expected allowed=%v, but got err=%v", testcase.expectAllow, err) - } - - if testcase.expectCache && *authInfoResolverCount != 1 { - t.Errorf("expected cacheclient, but got none") - } - - if !testcase.expectCache && *authInfoResolverCount != 0 { - t.Errorf("expected not cacheclient, but got cache") - } - }) - } - -} - -func newTestServer(t *testing.T) *httptest.Server { - // Create the test webhook server - sCert, err := tls.X509KeyPair(testcerts.ServerCert, testcerts.ServerKey) - if err != nil { - t.Fatal(err) - } - rootCAs := x509.NewCertPool() - rootCAs.AppendCertsFromPEM(testcerts.CACert) - testServer := httptest.NewUnstartedServer(http.HandlerFunc(webhookHandler)) - testServer.TLS = &tls.Config{ - Certificates: []tls.Certificate{sCert}, - ClientCAs: rootCAs, - ClientAuth: tls.RequireAndVerifyClientCert, - } - return testServer -} - -func webhookHandler(w http.ResponseWriter, r *http.Request) { - fmt.Printf("got req: %v\n", r.URL.Path) - switch r.URL.Path { - case "/internalErr": - http.Error(w, "webhook internal server error", http.StatusInternalServerError) - return - case "/invalidReq": - w.WriteHeader(http.StatusSwitchingProtocols) - w.Write([]byte("webhook invalid request")) - return - case "/invalidResp": - w.Header().Set("Content-Type", "application/json") - w.Write([]byte("webhook invalid response")) - case "/disallow": - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ - Response: &v1beta1.AdmissionResponse{ - Allowed: false, - }, - }) - case "/disallowReason": - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ - Response: &v1beta1.AdmissionResponse{ - Allowed: false, - Result: &metav1.Status{ - Message: "you shall not pass", - }, - }, - }) - case "/allow": - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ - Response: &v1beta1.AdmissionResponse{ - Allowed: true, - }, - }) - default: - http.NotFound(w, r) - } -} - -func newFakeAuthenticationInfoResolver(count *int32) *fakeAuthenticationInfoResolver { - return &fakeAuthenticationInfoResolver{ - restConfig: &rest.Config{ - TLSClientConfig: rest.TLSClientConfig{ - CAData: testcerts.CACert, - CertData: testcerts.ClientCert, - KeyData: testcerts.ClientKey, - }, - }, - cachedCount: count, - } -} - -type fakeAuthenticationInfoResolver struct { - restConfig *rest.Config - cachedCount *int32 -} - -func (c *fakeAuthenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) { - atomic.AddInt32(c.cachedCount, 1) - return c.restConfig, nil -} - -func (c *fakeAuthenticationInfoResolver) ClientConfigForService(serviceName, serviceNamespace string) (*rest.Config, error) { - atomic.AddInt32(c.cachedCount, 1) - return c.restConfig, nil -} - -func newMatchEverythingRules() []registrationv1beta1.RuleWithOperations { - return []registrationv1beta1.RuleWithOperations{{ - Operations: []registrationv1beta1.OperationType{registrationv1beta1.OperationAll}, - Rule: registrationv1beta1.Rule{ - APIGroups: []string{"*"}, - APIVersions: []string{"*"}, - Resources: []string{"*/*"}, - }, - }} -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go new file mode 100644 index 000000000..88e23c25d --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher.go @@ -0,0 +1,149 @@ +/* +Copyright 2018 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 mutating delegates admission checks to dynamically configured +// mutating webhooks. +package mutating + +import ( + "context" + "fmt" + "time" + + jsonpatch "github.com/evanphx/json-patch" + "github.com/golang/glog" + + admissionv1beta1 "k8s.io/api/admission/v1beta1" + "k8s.io/api/admissionregistration/v1beta1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + admissionmetrics "k8s.io/apiserver/pkg/admission/metrics" + "k8s.io/apiserver/pkg/admission/plugin/webhook/config" + webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors" + "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" + "k8s.io/apiserver/pkg/admission/plugin/webhook/request" +) + +type mutatingDispatcher struct { + cm *config.ClientManager + plugin *Plugin +} + +func newMutatingDispatcher(p *Plugin) func(cm *config.ClientManager) generic.Dispatcher { + return func(cm *config.ClientManager) generic.Dispatcher { + return &mutatingDispatcher{cm, p} + } +} + +var _ generic.Dispatcher = &mutatingDispatcher{} + +func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, relevantHooks []*v1beta1.Webhook) error { + for _, hook := range relevantHooks { + t := time.Now() + err := a.callAttrMutatingHook(ctx, hook, attr) + admissionmetrics.Metrics.ObserveWebhook(time.Since(t), err != nil, attr.Attributes, "admit", hook.Name) + if err == nil { + continue + } + + ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore + if callErr, ok := err.(*webhookerrors.ErrCallingWebhook); ok { + if ignoreClientCallFailures { + glog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr) + utilruntime.HandleError(callErr) + continue + } + glog.Warningf("Failed calling webhook, failing closed %v: %v", hook.Name, err) + } + return apierrors.NewInternalError(err) + } + + // convert attr.VersionedObject to the internal version in the underlying admission.Attributes + if attr.VersionedObject != nil { + return a.plugin.scheme.Convert(attr.VersionedObject, attr.Attributes.GetObject(), nil) + } + return nil +} + +// note that callAttrMutatingHook updates attr +func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes) error { + // Make the webhook request + request := request.CreateAdmissionReview(attr) + client, err := a.cm.HookClient(h) + if err != nil { + return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err} + } + response := &admissionv1beta1.AdmissionReview{} + if err := client.Post().Context(ctx).Body(&request).Do().Into(response); err != nil { + return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err} + } + + if response.Response == nil { + return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")} + } + + if !response.Response.Allowed { + return webhookerrors.ToStatusErr(h.Name, response.Response.Result) + } + + patchJS := response.Response.Patch + if len(patchJS) == 0 { + return nil + } + patchObj, err := jsonpatch.DecodePatch(patchJS) + if err != nil { + return apierrors.NewInternalError(err) + } + if len(patchObj) == 0 { + return nil + } + + // if a non-empty patch was provided, and we have no object we can apply it to (e.g. a DELETE admission operation), error + if attr.VersionedObject == nil { + return apierrors.NewInternalError(fmt.Errorf("admission webhook %q attempted to modify the object, which is not supported for this operation", h.Name)) + } + + objJS, err := runtime.Encode(a.plugin.jsonSerializer, attr.VersionedObject) + if err != nil { + return apierrors.NewInternalError(err) + } + patchedJS, err := patchObj.Apply(objJS) + if err != nil { + return apierrors.NewInternalError(err) + } + + var newVersionedObject runtime.Object + if _, ok := attr.VersionedObject.(*unstructured.Unstructured); ok { + // Custom Resources don't have corresponding Go struct's. + // They are represented as Unstructured. + newVersionedObject = &unstructured.Unstructured{} + } else { + newVersionedObject, err = a.plugin.scheme.New(attr.GetKind()) + if err != nil { + return apierrors.NewInternalError(err) + } + } + // TODO: if we have multiple mutating webhooks, we can remember the json + // instead of encoding and decoding for each one. + if _, _, err := a.plugin.jsonSerializer.Decode(patchedJS, nil, newVersionedObject); err != nil { + return apierrors.NewInternalError(err) + } + attr.VersionedObject = newVersionedObject + a.plugin.scheme.Default(attr.VersionedObject) + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher_test.go new file mode 100644 index 000000000..874f43a71 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/dispatcher_test.go @@ -0,0 +1,136 @@ +/* +Copyright 2018 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 mutating + +import ( + "context" + "reflect" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" + "k8s.io/apiserver/pkg/apis/example" + examplev1 "k8s.io/apiserver/pkg/apis/example/v1" + example2v1 "k8s.io/apiserver/pkg/apis/example2/v1" +) + +var sampleCRD = unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "mygroup.k8s.io/v1", + "kind": "Flunder", + "data": map[string]interface{}{ + "Key": "Value", + }, + }, +} + +func TestDispatch(t *testing.T) { + scheme := runtime.NewScheme() + example.AddToScheme(scheme) + examplev1.AddToScheme(scheme) + example2v1.AddToScheme(scheme) + + tests := []struct { + name string + in runtime.Object + out runtime.Object + expectedObj runtime.Object + }{ + { + name: "convert example/v1#Pod to example#Pod", + in: &examplev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Labels: map[string]string{ + "key": "value", + }, + }, + Spec: examplev1.PodSpec{ + RestartPolicy: examplev1.RestartPolicy("never"), + }, + }, + out: &example.Pod{}, + expectedObj: &example.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Labels: map[string]string{ + "key": "value", + }, + }, + Spec: example.PodSpec{ + RestartPolicy: example.RestartPolicy("never"), + }, + }, + }, + { + name: "convert example2/v1#replicaset to example#replicaset", + in: &example2v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "rs1", + Labels: map[string]string{ + "key": "value", + }, + }, + Spec: example2v1.ReplicaSetSpec{ + Replicas: func() *int32 { var i int32; i = 1; return &i }(), + }, + }, + out: &example.ReplicaSet{}, + expectedObj: &example.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "rs1", + Labels: map[string]string{ + "key": "value", + }, + }, + Spec: example.ReplicaSetSpec{ + Replicas: 1, + }, + }, + }, + { + name: "no conversion if the object is the same", + in: &sampleCRD, + out: &sampleCRD, + expectedObj: &sampleCRD, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + a := &mutatingDispatcher{ + plugin: &Plugin{ + scheme: scheme, + }, + } + attr := generic.VersionedAttributes{ + Attributes: admission.NewAttributesRecord(test.out, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", admission.Operation(""), nil), + VersionedOldObject: nil, + VersionedObject: test.in, + } + if err := a.Dispatch(context.TODO(), &attr, nil); err != nil { + t.Fatalf("%s: unexpected error: %v", test.name, err) + } + if !reflect.DeepEqual(attr.Attributes.GetObject(), test.expectedObj) { + t.Errorf("\nexpected:\n%#v\ngot:\n %#v\n", test.expectedObj, test.out) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin.go new file mode 100644 index 000000000..f03b1b342 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin.go @@ -0,0 +1,96 @@ +/* +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 mutating + +import ( + "fmt" + "io" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/admission/configuration" + "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" +) + +const ( + // Name of admission plug-in + PluginName = "MutatingAdmissionWebhook" +) + +// Register registers a plugin +func Register(plugins *admission.Plugins) { + plugins.Register(PluginName, func(configFile io.Reader) (admission.Interface, error) { + plugin, err := NewMutatingWebhook(configFile) + if err != nil { + return nil, err + } + + return plugin, nil + }) +} + +// Plugin is an implementation of admission.Interface. +type Plugin struct { + *generic.Webhook + + scheme *runtime.Scheme + jsonSerializer *json.Serializer +} + +var _ admission.MutationInterface = &Plugin{} + +// NewMutatingWebhook returns a generic admission webhook plugin. +func NewMutatingWebhook(configFile io.Reader) (*Plugin, error) { + handler := admission.NewHandler(admission.Connect, admission.Create, admission.Delete, admission.Update) + p := &Plugin{} + var err error + p.Webhook, err = generic.NewWebhook(handler, configFile, configuration.NewMutatingWebhookConfigurationManager, newMutatingDispatcher(p)) + if err != nil { + return nil, err + } + + return p, nil +} + +// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme +func (a *Plugin) SetScheme(scheme *runtime.Scheme) { + a.Webhook.SetScheme(scheme) + if scheme != nil { + a.scheme = scheme + a.jsonSerializer = json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false) + } +} + +// ValidateInitialization implements the InitializationValidator interface. +func (a *Plugin) ValidateInitialization() error { + if err := a.Webhook.ValidateInitialization(); err != nil { + return err + } + if a.scheme == nil { + return fmt.Errorf("scheme is not properly setup") + } + if a.jsonSerializer == nil { + return fmt.Errorf("jsonSerializer is not properly setup") + } + return nil +} + +// Admit makes an admission decision based on the request attributes. +func (a *Plugin) Admit(attr admission.Attributes) error { + return a.Webhook.Dispatch(attr) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go new file mode 100644 index 000000000..b60a62f3b --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/plugin_test.go @@ -0,0 +1,158 @@ +/* +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 mutating + +import ( + "net/url" + "reflect" + "strings" + "testing" + + "k8s.io/api/admission/v1beta1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/admission" + webhooktesting "k8s.io/apiserver/pkg/admission/plugin/webhook/testing" +) + +// TestAdmit tests that MutatingWebhook#Admit works as expected +func TestAdmit(t *testing.T) { + scheme := runtime.NewScheme() + v1beta1.AddToScheme(scheme) + corev1.AddToScheme(scheme) + + testServer := webhooktesting.NewTestServer(t) + testServer.StartTLS() + defer testServer.Close() + serverURL, err := url.ParseRequestURI(testServer.URL) + if err != nil { + t.Fatalf("this should never happen? %v", err) + } + + stopCh := make(chan struct{}) + defer close(stopCh) + + for _, tt := range webhooktesting.NewTestCases(serverURL) { + wh, err := NewMutatingWebhook(nil) + if err != nil { + t.Errorf("%s: failed to create mutating webhook: %v", tt.Name, err) + continue + } + + ns := "webhook-test" + client, informer := webhooktesting.NewFakeDataSource(ns, tt.Webhooks, true, stopCh) + + wh.SetAuthenticationInfoResolverWrapper(webhooktesting.Wrapper(webhooktesting.NewAuthenticationInfoResolver(new(int32)))) + wh.SetServiceResolver(webhooktesting.NewServiceResolver(*serverURL)) + wh.SetScheme(scheme) + wh.SetExternalKubeClientSet(client) + wh.SetExternalKubeInformerFactory(informer) + + informer.Start(stopCh) + informer.WaitForCacheSync(stopCh) + + if err = wh.ValidateInitialization(); err != nil { + t.Errorf("%s: failed to validate initialization: %v", tt.Name, err) + continue + } + + var attr admission.Attributes + if tt.IsCRD { + attr = webhooktesting.NewAttributeUnstructured(ns, tt.AdditionalLabels) + } else { + attr = webhooktesting.NewAttribute(ns, tt.AdditionalLabels) + } + + err = wh.Admit(attr) + if tt.ExpectAllow != (err == nil) { + t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) + } + if tt.ExpectLabels != nil { + if !reflect.DeepEqual(tt.ExpectLabels, attr.GetObject().(metav1.Object).GetLabels()) { + t.Errorf("%s: expected labels '%v', but got '%v'", tt.Name, tt.ExpectLabels, attr.GetObject().(metav1.Object).GetLabels()) + } + } + // ErrWebhookRejected is not an error for our purposes + if tt.ErrorContains != "" { + if err == nil || !strings.Contains(err.Error(), tt.ErrorContains) { + t.Errorf("%s: expected an error saying %q, but got: %v", tt.Name, tt.ErrorContains, err) + } + } + if _, isStatusErr := err.(*errors.StatusError); err != nil && !isStatusErr { + t.Errorf("%s: expected a StatusError, got %T", tt.Name, err) + } + } +} + +// TestAdmitCachedClient tests that MutatingWebhook#Admit should cache restClient +func TestAdmitCachedClient(t *testing.T) { + scheme := runtime.NewScheme() + v1beta1.AddToScheme(scheme) + corev1.AddToScheme(scheme) + + testServer := webhooktesting.NewTestServer(t) + testServer.StartTLS() + defer testServer.Close() + serverURL, err := url.ParseRequestURI(testServer.URL) + if err != nil { + t.Fatalf("this should never happen? %v", err) + } + + stopCh := make(chan struct{}) + defer close(stopCh) + + wh, err := NewMutatingWebhook(nil) + if err != nil { + t.Fatalf("Failed to create mutating webhook: %v", err) + } + wh.SetServiceResolver(webhooktesting.NewServiceResolver(*serverURL)) + wh.SetScheme(scheme) + + for _, tt := range webhooktesting.NewCachedClientTestcases(serverURL) { + ns := "webhook-test" + client, informer := webhooktesting.NewFakeDataSource(ns, tt.Webhooks, true, stopCh) + + // override the webhook source. The client cache will stay the same. + cacheMisses := new(int32) + wh.SetAuthenticationInfoResolverWrapper(webhooktesting.Wrapper(webhooktesting.NewAuthenticationInfoResolver(cacheMisses))) + wh.SetExternalKubeClientSet(client) + wh.SetExternalKubeInformerFactory(informer) + + informer.Start(stopCh) + informer.WaitForCacheSync(stopCh) + + if err = wh.ValidateInitialization(); err != nil { + t.Errorf("%s: failed to validate initialization: %v", tt.Name, err) + continue + } + + err = wh.Admit(webhooktesting.NewAttribute(ns, nil)) + if tt.ExpectAllow != (err == nil) { + t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) + } + + if tt.ExpectCacheMiss && *cacheMisses == 0 { + t.Errorf("%s: expected cache miss, but got no AuthenticationInfoResolver call", tt.Name) + } + + if !tt.ExpectCacheMiss && *cacheMisses > 0 { + t.Errorf("%s: expected client to be cached, but got %d AuthenticationInfoResolver calls", tt.Name, *cacheMisses) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/BUILD index 036015274..af94f1688 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/BUILD @@ -14,7 +14,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/admissionreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/admissionreview.go index 5b8a41db2..663349a4e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/admissionreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request/admissionreview.go @@ -22,11 +22,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" ) // CreateAdmissionReview creates an AdmissionReview for the provided admission.Attributes -func CreateAdmissionReview(attr admission.Attributes) admissionv1beta1.AdmissionReview { +func CreateAdmissionReview(attr *generic.VersionedAttributes) admissionv1beta1.AdmissionReview { gvk := attr.GetKind() gvr := attr.GetResource() aUserInfo := attr.GetUserInfo() @@ -61,10 +61,10 @@ func CreateAdmissionReview(attr admission.Attributes) admissionv1beta1.Admission Operation: admissionv1beta1.Operation(attr.GetOperation()), UserInfo: userInfo, Object: runtime.RawExtension{ - Object: attr.GetObject(), + Object: attr.VersionedObject, }, OldObject: runtime.RawExtension{ - Object: attr.GetOldObject(), + Object: attr.VersionedOldObject, }, }, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts/gencerts.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts/gencerts.sh index d4145c606..98503f69f 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts/gencerts.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts/gencerts.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/BUILD new file mode 100644 index 000000000..fcb3ce096 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/BUILD @@ -0,0 +1,44 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "authentication_info_resolver.go", + "service_resolver.go", + "testcase.go", + "webhook_server.go", + ], + importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/testing", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/api/admission/v1beta1:go_default_library", + "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/apiserver/pkg/admission:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts:go_default_library", + "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/authentication_info_resolver.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/authentication_info_resolver.go new file mode 100644 index 000000000..0178f4182 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/authentication_info_resolver.go @@ -0,0 +1,63 @@ +/* +Copyright 2018 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 testing + +import ( + "sync/atomic" + + "k8s.io/apiserver/pkg/admission/plugin/webhook/config" + "k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts" + "k8s.io/client-go/rest" +) + +// Wrapper turns an AuthenticationInfoResolver into a AuthenticationInfoResolverWrapper that unconditionally +// returns the given AuthenticationInfoResolver. +func Wrapper(r config.AuthenticationInfoResolver) func(config.AuthenticationInfoResolver) config.AuthenticationInfoResolver { + return func(config.AuthenticationInfoResolver) config.AuthenticationInfoResolver { + return r + } +} + +// NewAuthenticationInfoResolver creates a fake AuthenticationInfoResolver that counts cache misses on +// every call to its methods. +func NewAuthenticationInfoResolver(cacheMisses *int32) config.AuthenticationInfoResolver { + return &authenticationInfoResolver{ + restConfig: &rest.Config{ + TLSClientConfig: rest.TLSClientConfig{ + CAData: testcerts.CACert, + CertData: testcerts.ClientCert, + KeyData: testcerts.ClientKey, + }, + }, + cacheMisses: cacheMisses, + } +} + +type authenticationInfoResolver struct { + restConfig *rest.Config + cacheMisses *int32 +} + +func (a *authenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) { + atomic.AddInt32(a.cacheMisses, 1) + return a.restConfig, nil +} + +func (a *authenticationInfoResolver) ClientConfigForService(serviceName, serviceNamespace string) (*rest.Config, error) { + atomic.AddInt32(a.cacheMisses, 1) + return a.restConfig, nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/service_resolver.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/service_resolver.go new file mode 100644 index 000000000..312535cea --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/service_resolver.go @@ -0,0 +1,42 @@ +/* +Copyright 2018 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 testing + +import ( + "fmt" + "net/url" + + "k8s.io/apiserver/pkg/admission/plugin/webhook/config" +) + +type serviceResolver struct { + base url.URL +} + +// NewServiceResolver returns a static service resolve that return the given URL or +// an error for the failResolve namespace. +func NewServiceResolver(base url.URL) config.ServiceResolver { + return &serviceResolver{base} +} + +func (f serviceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { + if namespace == "failResolve" { + return nil, fmt.Errorf("couldn't resolve service location") + } + u := f.base + return &u, nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go new file mode 100644 index 000000000..96d696788 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/testcase.go @@ -0,0 +1,510 @@ +/* +Copyright 2018 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 testing + +import ( + "net/url" + + registrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts" + "k8s.io/apiserver/pkg/authentication/user" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + fakeclientset "k8s.io/client-go/kubernetes/fake" +) + +var matchEverythingRules = []registrationv1beta1.RuleWithOperations{{ + Operations: []registrationv1beta1.OperationType{registrationv1beta1.OperationAll}, + Rule: registrationv1beta1.Rule{ + APIGroups: []string{"*"}, + APIVersions: []string{"*"}, + Resources: []string{"*/*"}, + }, +}} + +// NewFakeDataSource returns a mock client and informer returning the given webhooks. +func NewFakeDataSource(name string, webhooks []registrationv1beta1.Webhook, mutating bool, stopCh <-chan struct{}) (clientset kubernetes.Interface, factory informers.SharedInformerFactory) { + var objs = []runtime.Object{ + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "runlevel": "0", + }, + }, + }, + } + if mutating { + objs = append(objs, ®istrationv1beta1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-webhooks", + }, + Webhooks: webhooks, + }) + } else { + objs = append(objs, ®istrationv1beta1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-webhooks", + }, + Webhooks: webhooks, + }) + } + + client := fakeclientset.NewSimpleClientset(objs...) + informerFactory := informers.NewSharedInformerFactory(client, 0) + + return client, informerFactory +} + +func newAttributesRecord(object metav1.Object, oldObject metav1.Object, kind schema.GroupVersionKind, namespace string, name string, resource string, labels map[string]string) admission.Attributes { + object.SetName(name) + object.SetNamespace(namespace) + objectLabels := map[string]string{resource + ".name": name} + for k, v := range labels { + objectLabels[k] = v + } + object.SetLabels(objectLabels) + + oldObject.SetName(name) + oldObject.SetNamespace(namespace) + + gvr := kind.GroupVersion().WithResource(resource) + subResource := "" + userInfo := user.DefaultInfo{ + Name: "webhook-test", + UID: "webhook-test", + } + + return admission.NewAttributesRecord(object.(runtime.Object), oldObject.(runtime.Object), kind, namespace, name, gvr, subResource, admission.Update, &userInfo) +} + +// NewAttribute returns static admission Attributes for testing. +func NewAttribute(namespace string, labels map[string]string) admission.Attributes { + // Set up a test object for the call + object := corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Pod", + }, + } + oldObject := corev1.Pod{} + kind := corev1.SchemeGroupVersion.WithKind("Pod") + name := "my-pod" + + return newAttributesRecord(&object, &oldObject, kind, namespace, name, "pod", labels) +} + +// NewAttributeUnstructured returns static admission Attributes for testing with custom resources. +func NewAttributeUnstructured(namespace string, labels map[string]string) admission.Attributes { + // Set up a test object for the call + object := unstructured.Unstructured{} + object.SetKind("TestCRD") + object.SetAPIVersion("custom.resource/v1") + oldObject := unstructured.Unstructured{} + oldObject.SetKind("TestCRD") + oldObject.SetAPIVersion("custom.resource/v1") + kind := object.GroupVersionKind() + name := "my-test-crd" + + return newAttributesRecord(&object, &oldObject, kind, namespace, name, "crd", labels) +} + +type urlConfigGenerator struct { + baseURL *url.URL +} + +func (c urlConfigGenerator) ccfgURL(urlPath string) registrationv1beta1.WebhookClientConfig { + u2 := *c.baseURL + u2.Path = urlPath + urlString := u2.String() + return registrationv1beta1.WebhookClientConfig{ + URL: &urlString, + CABundle: testcerts.CACert, + } +} + +// Test is a webhook test case. +type Test struct { + Name string + Webhooks []registrationv1beta1.Webhook + Path string + IsCRD bool + AdditionalLabels map[string]string + ExpectLabels map[string]string + ExpectAllow bool + ErrorContains string +} + +// NewTestCases returns test cases with a given base url. +func NewTestCases(url *url.URL) []Test { + policyFail := registrationv1beta1.Fail + policyIgnore := registrationv1beta1.Ignore + ccfgURL := urlConfigGenerator{url}.ccfgURL + + return []Test{ + { + Name: "no match", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "nomatch", + ClientConfig: ccfgSVC("disallow"), + Rules: []registrationv1beta1.RuleWithOperations{{ + Operations: []registrationv1beta1.OperationType{registrationv1beta1.Create}, + }}, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ExpectAllow: true, + }, + { + Name: "match & allow", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "allow", + ClientConfig: ccfgSVC("allow"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ExpectAllow: true, + }, + { + Name: "match & remove label", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "removeLabel", + ClientConfig: ccfgSVC("removeLabel"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ExpectAllow: true, + AdditionalLabels: map[string]string{"remove": "me"}, + ExpectLabels: map[string]string{"pod.name": "my-pod"}, + }, + { + Name: "match & add label", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "addLabel", + ClientConfig: ccfgSVC("addLabel"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ExpectAllow: true, + ExpectLabels: map[string]string{"pod.name": "my-pod", "added": "test"}, + }, + { + Name: "match CRD & add label", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "addLabel", + ClientConfig: ccfgSVC("addLabel"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + IsCRD: true, + ExpectAllow: true, + ExpectLabels: map[string]string{"crd.name": "my-test-crd", "added": "test"}, + }, + { + Name: "match CRD & remove label", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "removeLabel", + ClientConfig: ccfgSVC("removeLabel"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + IsCRD: true, + ExpectAllow: true, + AdditionalLabels: map[string]string{"remove": "me"}, + ExpectLabels: map[string]string{"crd.name": "my-test-crd"}, + }, + { + Name: "match & invalid mutation", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "invalidMutation", + ClientConfig: ccfgSVC("invalidMutation"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ErrorContains: "invalid character", + }, + { + Name: "match & disallow", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "disallow", + ClientConfig: ccfgSVC("disallow"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ErrorContains: "without explanation", + }, + { + Name: "match & disallow ii", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "disallowReason", + ClientConfig: ccfgSVC("disallowReason"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + + ErrorContains: "you shall not pass", + }, + { + Name: "match & disallow & but allowed because namespaceSelector exempt the ns", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "disallow", + ClientConfig: ccfgSVC("disallow"), + Rules: newMatchEverythingRules(), + NamespaceSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{{ + Key: "runlevel", + Values: []string{"1"}, + Operator: metav1.LabelSelectorOpIn, + }}, + }, + }}, + + ExpectAllow: true, + }, + { + Name: "match & disallow & but allowed because namespaceSelector exempt the ns ii", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "disallow", + ClientConfig: ccfgSVC("disallow"), + Rules: newMatchEverythingRules(), + NamespaceSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{{ + Key: "runlevel", + Values: []string{"0"}, + Operator: metav1.LabelSelectorOpNotIn, + }}, + }, + }}, + ExpectAllow: true, + }, + { + Name: "match & fail (but allow because fail open)", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "internalErr A", + ClientConfig: ccfgSVC("internalErr"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyIgnore, + }, { + Name: "internalErr B", + ClientConfig: ccfgSVC("internalErr"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyIgnore, + }, { + Name: "internalErr C", + ClientConfig: ccfgSVC("internalErr"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyIgnore, + }}, + + ExpectAllow: true, + }, + { + Name: "match & fail (but disallow because fail close on nil FailurePolicy)", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "internalErr A", + ClientConfig: ccfgSVC("internalErr"), + NamespaceSelector: &metav1.LabelSelector{}, + Rules: matchEverythingRules, + }, { + Name: "internalErr B", + ClientConfig: ccfgSVC("internalErr"), + NamespaceSelector: &metav1.LabelSelector{}, + Rules: matchEverythingRules, + }, { + Name: "internalErr C", + ClientConfig: ccfgSVC("internalErr"), + NamespaceSelector: &metav1.LabelSelector{}, + Rules: matchEverythingRules, + }}, + ExpectAllow: false, + }, + { + Name: "match & fail (but fail because fail closed)", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "internalErr A", + ClientConfig: ccfgSVC("internalErr"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyFail, + }, { + Name: "internalErr B", + ClientConfig: ccfgSVC("internalErr"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyFail, + }, { + Name: "internalErr C", + ClientConfig: ccfgSVC("internalErr"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyFail, + }}, + ExpectAllow: false, + }, + { + Name: "match & allow (url)", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "allow", + ClientConfig: ccfgURL("allow"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ExpectAllow: true, + }, + { + Name: "match & disallow (url)", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "disallow", + ClientConfig: ccfgURL("disallow"), + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ErrorContains: "without explanation", + }, { + Name: "absent response and fail open", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "nilResponse", + ClientConfig: ccfgURL("nilResponse"), + FailurePolicy: &policyIgnore, + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ExpectAllow: true, + }, + { + Name: "absent response and fail closed", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "nilResponse", + ClientConfig: ccfgURL("nilResponse"), + FailurePolicy: &policyFail, + Rules: matchEverythingRules, + NamespaceSelector: &metav1.LabelSelector{}, + }}, + ErrorContains: "Webhook response was absent", + }, + // No need to test everything with the url case, since only the + // connection is different. + } +} + +// CachedTest is a test case for the client manager. +type CachedTest struct { + Name string + Webhooks []registrationv1beta1.Webhook + ExpectAllow bool + ExpectCacheMiss bool +} + +// NewCachedClientTestcases returns a set of client manager test cases. +func NewCachedClientTestcases(url *url.URL) []CachedTest { + policyIgnore := registrationv1beta1.Ignore + ccfgURL := urlConfigGenerator{url}.ccfgURL + + return []CachedTest{ + { + Name: "uncached: service webhook, path 'allow'", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "cache1", + ClientConfig: ccfgSVC("allow"), + Rules: newMatchEverythingRules(), + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyIgnore, + }}, + ExpectAllow: true, + ExpectCacheMiss: true, + }, + { + Name: "uncached: service webhook, path 'internalErr'", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "cache2", + ClientConfig: ccfgSVC("internalErr"), + Rules: newMatchEverythingRules(), + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyIgnore, + }}, + ExpectAllow: true, + ExpectCacheMiss: true, + }, + { + Name: "cached: service webhook, path 'allow'", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "cache3", + ClientConfig: ccfgSVC("allow"), + Rules: newMatchEverythingRules(), + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyIgnore, + }}, + ExpectAllow: true, + ExpectCacheMiss: false, + }, + { + Name: "uncached: url webhook, path 'allow'", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "cache4", + ClientConfig: ccfgURL("allow"), + Rules: newMatchEverythingRules(), + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyIgnore, + }}, + ExpectAllow: true, + ExpectCacheMiss: true, + }, + { + Name: "cached: service webhook, path 'allow'", + Webhooks: []registrationv1beta1.Webhook{{ + Name: "cache5", + ClientConfig: ccfgURL("allow"), + Rules: newMatchEverythingRules(), + NamespaceSelector: &metav1.LabelSelector{}, + FailurePolicy: &policyIgnore, + }}, + ExpectAllow: true, + ExpectCacheMiss: false, + }, + } +} + +// ccfgSVC returns a client config using the service reference mechanism. +func ccfgSVC(urlPath string) registrationv1beta1.WebhookClientConfig { + return registrationv1beta1.WebhookClientConfig{ + Service: ®istrationv1beta1.ServiceReference{ + Name: "webhook-test", + Namespace: "default", + Path: &urlPath, + }, + CABundle: testcerts.CACert, + } +} + +func newMatchEverythingRules() []registrationv1beta1.RuleWithOperations { + return []registrationv1beta1.RuleWithOperations{{ + Operations: []registrationv1beta1.OperationType{registrationv1beta1.OperationAll}, + Rule: registrationv1beta1.Rule{ + APIGroups: []string{"*"}, + APIVersions: []string{"*"}, + Resources: []string{"*/*"}, + }, + }} +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/webhook_server.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/webhook_server.go new file mode 100644 index 000000000..a8bb1ac82 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing/webhook_server.go @@ -0,0 +1,124 @@ +/* +Copyright 2018 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 testing + +import ( + "crypto/tls" + "crypto/x509" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "k8s.io/api/admission/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts" +) + +// NewTestServer returns a webhook test HTTPS server with fixed webhook test certs. +func NewTestServer(t *testing.T) *httptest.Server { + // Create the test webhook server + sCert, err := tls.X509KeyPair(testcerts.ServerCert, testcerts.ServerKey) + if err != nil { + t.Fatal(err) + } + rootCAs := x509.NewCertPool() + rootCAs.AppendCertsFromPEM(testcerts.CACert) + testServer := httptest.NewUnstartedServer(http.HandlerFunc(webhookHandler)) + testServer.TLS = &tls.Config{ + Certificates: []tls.Certificate{sCert}, + ClientCAs: rootCAs, + ClientAuth: tls.RequireAndVerifyClientCert, + } + return testServer +} + +func webhookHandler(w http.ResponseWriter, r *http.Request) { + fmt.Printf("got req: %v\n", r.URL.Path) + switch r.URL.Path { + case "/internalErr": + http.Error(w, "webhook internal server error", http.StatusInternalServerError) + return + case "/invalidReq": + w.WriteHeader(http.StatusSwitchingProtocols) + w.Write([]byte("webhook invalid request")) + return + case "/invalidResp": + w.Header().Set("Content-Type", "application/json") + w.Write([]byte("webhook invalid response")) + case "/disallow": + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ + Response: &v1beta1.AdmissionResponse{ + Allowed: false, + }, + }) + case "/disallowReason": + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ + Response: &v1beta1.AdmissionResponse{ + Allowed: false, + Result: &metav1.Status{ + Message: "you shall not pass", + }, + }, + }) + case "/allow": + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ + Response: &v1beta1.AdmissionResponse{ + Allowed: true, + }, + }) + case "/removeLabel": + w.Header().Set("Content-Type", "application/json") + pt := v1beta1.PatchTypeJSONPatch + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ + Response: &v1beta1.AdmissionResponse{ + Allowed: true, + PatchType: &pt, + Patch: []byte(`[{"op": "remove", "path": "/metadata/labels/remove"}]`), + }, + }) + case "/addLabel": + w.Header().Set("Content-Type", "application/json") + pt := v1beta1.PatchTypeJSONPatch + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ + Response: &v1beta1.AdmissionResponse{ + Allowed: true, + PatchType: &pt, + Patch: []byte(`[{"op": "add", "path": "/metadata/labels/added", "value": "test"}]`), + }, + }) + case "/invalidMutation": + w.Header().Set("Content-Type", "application/json") + pt := v1beta1.PatchTypeJSONPatch + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ + Response: &v1beta1.AdmissionResponse{ + Allowed: true, + PatchType: &pt, + Patch: []byte(`[{"op": "add", "CORRUPTED_KEY":}]`), + }, + }) + case "/nilResponse": + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{}) + default: + http.NotFound(w, r) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/BUILD index 01f2f57c7..70024b76e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/BUILD @@ -3,8 +3,9 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "admission.go", + "dispatcher.go", "doc.go", + "plugin.go", ], importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/validating", visibility = ["//visibility:public"], @@ -13,40 +14,27 @@ go_library( "//vendor/k8s.io/api/admission/v1beta1:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/configuration:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/metrics:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/request:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/rules:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned:go_default_library", - "//vendor/k8s.io/client-go/informers:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) go_test( name = "go_default_test", - srcs = ["admission_test.go"], + srcs = ["plugin_test.go"], embed = [":go_default_library"], deps = [ "//vendor/k8s.io/api/admission/v1beta1:go_default_library", - "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts:go_default_library", - "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/testing:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/admission.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/admission.go deleted file mode 100644 index d3bcb3389..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/admission.go +++ /dev/null @@ -1,305 +0,0 @@ -/* -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 validating delegates admission checks to dynamically configured -// validating webhooks. -package validating - -import ( - "context" - "fmt" - "io" - "sync" - "time" - - "github.com/golang/glog" - - admissionv1beta1 "k8s.io/api/admission/v1beta1" - "k8s.io/api/admissionregistration/v1beta1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apiserver/pkg/admission" - "k8s.io/apiserver/pkg/admission/configuration" - genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer" - admissionmetrics "k8s.io/apiserver/pkg/admission/metrics" - "k8s.io/apiserver/pkg/admission/plugin/webhook/config" - webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors" - "k8s.io/apiserver/pkg/admission/plugin/webhook/namespace" - "k8s.io/apiserver/pkg/admission/plugin/webhook/request" - "k8s.io/apiserver/pkg/admission/plugin/webhook/rules" - "k8s.io/apiserver/pkg/admission/plugin/webhook/versioned" - "k8s.io/client-go/informers" - clientset "k8s.io/client-go/kubernetes" -) - -const ( - // Name of admission plug-in - PluginName = "ValidatingAdmissionWebhook" -) - -// Register registers a plugin -func Register(plugins *admission.Plugins) { - plugins.Register(PluginName, func(configFile io.Reader) (admission.Interface, error) { - plugin, err := NewValidatingAdmissionWebhook(configFile) - if err != nil { - return nil, err - } - - return plugin, nil - }) -} - -// WebhookSource can list dynamic webhook plugins. -type WebhookSource interface { - Webhooks() *v1beta1.ValidatingWebhookConfiguration -} - -// NewValidatingAdmissionWebhook returns a generic admission webhook plugin. -func NewValidatingAdmissionWebhook(configFile io.Reader) (*ValidatingAdmissionWebhook, error) { - kubeconfigFile, err := config.LoadConfig(configFile) - if err != nil { - return nil, err - } - - cm, err := config.NewClientManager() - if err != nil { - return nil, err - } - authInfoResolver, err := config.NewDefaultAuthenticationInfoResolver(kubeconfigFile) - if err != nil { - return nil, err - } - // Set defaults which may be overridden later. - cm.SetAuthenticationInfoResolver(authInfoResolver) - cm.SetServiceResolver(config.NewDefaultServiceResolver()) - - return &ValidatingAdmissionWebhook{ - Handler: admission.NewHandler( - admission.Connect, - admission.Create, - admission.Delete, - admission.Update, - ), - clientManager: cm, - }, nil -} - -var _ admission.ValidationInterface = &ValidatingAdmissionWebhook{} - -// ValidatingAdmissionWebhook is an implementation of admission.Interface. -type ValidatingAdmissionWebhook struct { - *admission.Handler - hookSource WebhookSource - namespaceMatcher namespace.Matcher - clientManager config.ClientManager - convertor versioned.Convertor -} - -var ( - _ = genericadmissioninit.WantsExternalKubeClientSet(&ValidatingAdmissionWebhook{}) -) - -// TODO find a better way wire this, but keep this pull small for now. -func (a *ValidatingAdmissionWebhook) SetAuthenticationInfoResolverWrapper(wrapper config.AuthenticationInfoResolverWrapper) { - a.clientManager.SetAuthenticationInfoResolverWrapper(wrapper) -} - -// SetServiceResolver sets a service resolver for the webhook admission plugin. -// Passing a nil resolver does not have an effect, instead a default one will be used. -func (a *ValidatingAdmissionWebhook) SetServiceResolver(sr config.ServiceResolver) { - a.clientManager.SetServiceResolver(sr) -} - -// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme -func (a *ValidatingAdmissionWebhook) SetScheme(scheme *runtime.Scheme) { - if scheme != nil { - a.convertor.Scheme = scheme - } -} - -// WantsExternalKubeClientSet defines a function which sets external ClientSet for admission plugins that need it -func (a *ValidatingAdmissionWebhook) SetExternalKubeClientSet(client clientset.Interface) { - a.namespaceMatcher.Client = client -} - -// SetExternalKubeInformerFactory implements the WantsExternalKubeInformerFactory interface. -func (a *ValidatingAdmissionWebhook) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) { - namespaceInformer := f.Core().V1().Namespaces() - a.namespaceMatcher.NamespaceLister = namespaceInformer.Lister() - validatingWebhookConfigurationsInformer := f.Admissionregistration().V1beta1().ValidatingWebhookConfigurations() - a.hookSource = configuration.NewValidatingWebhookConfigurationManager(validatingWebhookConfigurationsInformer) - a.SetReadyFunc(func() bool { - return namespaceInformer.Informer().HasSynced() && validatingWebhookConfigurationsInformer.Informer().HasSynced() - }) -} - -// ValidateInitialization implements the InitializationValidator interface. -func (a *ValidatingAdmissionWebhook) ValidateInitialization() error { - if a.hookSource == nil { - return fmt.Errorf("ValidatingAdmissionWebhook admission plugin requires a Kubernetes informer to be provided") - } - if err := a.namespaceMatcher.Validate(); err != nil { - return fmt.Errorf("ValidatingAdmissionWebhook.namespaceMatcher is not properly setup: %v", err) - } - if err := a.clientManager.Validate(); err != nil { - return fmt.Errorf("ValidatingAdmissionWebhook.clientManager is not properly setup: %v", err) - } - if err := a.convertor.Validate(); err != nil { - return fmt.Errorf("ValidatingAdmissionWebhook.convertor is not properly setup: %v", err) - } - return nil -} - -func (a *ValidatingAdmissionWebhook) loadConfiguration(attr admission.Attributes) *v1beta1.ValidatingWebhookConfiguration { - return a.hookSource.Webhooks() -} - -// Validate makes an admission decision based on the request attributes. -func (a *ValidatingAdmissionWebhook) Validate(attr admission.Attributes) error { - if rules.IsWebhookConfigurationResource(attr) { - return nil - } - - if !a.WaitForReady() { - return admission.NewForbidden(attr, fmt.Errorf("not yet ready to handle request")) - } - hookConfig := a.loadConfiguration(attr) - hooks := hookConfig.Webhooks - ctx := context.TODO() - - var relevantHooks []*v1beta1.Webhook - for i := range hooks { - call, err := a.shouldCallHook(&hooks[i], attr) - if err != nil { - return err - } - if call { - relevantHooks = append(relevantHooks, &hooks[i]) - } - } - - if len(relevantHooks) == 0 { - // no matching hooks - return nil - } - - // convert the object to the external version before sending it to the webhook - versionedAttr := versioned.Attributes{ - Attributes: attr, - } - if oldObj := attr.GetOldObject(); oldObj != nil { - out, err := a.convertor.ConvertToGVK(oldObj, attr.GetKind()) - if err != nil { - return apierrors.NewInternalError(err) - } - versionedAttr.OldObject = out - } - if obj := attr.GetObject(); obj != nil { - out, err := a.convertor.ConvertToGVK(obj, attr.GetKind()) - if err != nil { - return apierrors.NewInternalError(err) - } - versionedAttr.Object = out - } - - wg := sync.WaitGroup{} - errCh := make(chan error, len(relevantHooks)) - wg.Add(len(relevantHooks)) - for i := range relevantHooks { - go func(hook *v1beta1.Webhook) { - defer wg.Done() - - t := time.Now() - err := a.callHook(ctx, hook, versionedAttr) - admissionmetrics.Metrics.ObserveWebhook(time.Since(t), err != nil, attr, "validating", hook.Name) - if err == nil { - return - } - - ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore - if callErr, ok := err.(*webhookerrors.ErrCallingWebhook); ok { - if ignoreClientCallFailures { - glog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr) - utilruntime.HandleError(callErr) - return - } - - glog.Warningf("Failed calling webhook, failing closed %v: %v", hook.Name, err) - errCh <- apierrors.NewInternalError(err) - return - } - - glog.Warningf("rejected by webhook %q: %#v", hook.Name, err) - errCh <- err - }(relevantHooks[i]) - } - wg.Wait() - close(errCh) - - var errs []error - for e := range errCh { - errs = append(errs, e) - } - if len(errs) == 0 { - return nil - } - if len(errs) > 1 { - for i := 1; i < len(errs); i++ { - // TODO: merge status errors; until then, just return the first one. - utilruntime.HandleError(errs[i]) - } - } - return errs[0] -} - -// TODO: factor into a common place along with the mutating webhook version. -func (a *ValidatingAdmissionWebhook) shouldCallHook(h *v1beta1.Webhook, attr admission.Attributes) (bool, *apierrors.StatusError) { - var matches bool - for _, r := range h.Rules { - m := rules.Matcher{Rule: r, Attr: attr} - if m.Matches() { - matches = true - break - } - } - if !matches { - return false, nil - } - - return a.namespaceMatcher.MatchNamespaceSelector(h, attr) -} - -func (a *ValidatingAdmissionWebhook) callHook(ctx context.Context, h *v1beta1.Webhook, attr admission.Attributes) error { - // Make the webhook request - request := request.CreateAdmissionReview(attr) - client, err := a.clientManager.HookClient(h) - if err != nil { - return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err} - } - response := &admissionv1beta1.AdmissionReview{} - if err := client.Post().Context(ctx).Body(&request).Do().Into(response); err != nil { - return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err} - } - - if response.Response == nil { - return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")} - } - if response.Response.Allowed { - return nil - } - return webhookerrors.ToStatusErr(h.Name, response.Response.Result) -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/admission_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/admission_test.go deleted file mode 100644 index 77871f019..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/admission_test.go +++ /dev/null @@ -1,678 +0,0 @@ -/* -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 validating - -import ( - "crypto/tls" - "crypto/x509" - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "strings" - "sync/atomic" - "testing" - - "k8s.io/api/admission/v1beta1" - registrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apiserver/pkg/admission" - "k8s.io/apiserver/pkg/admission/plugin/webhook/config" - "k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts" - "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/client-go/rest" -) - -type fakeHookSource struct { - hooks []registrationv1beta1.Webhook - err error -} - -func (f *fakeHookSource) Webhooks() *registrationv1beta1.ValidatingWebhookConfiguration { - if f.err != nil { - return nil - } - for i, h := range f.hooks { - if h.NamespaceSelector == nil { - f.hooks[i].NamespaceSelector = &metav1.LabelSelector{} - } - } - return ®istrationv1beta1.ValidatingWebhookConfiguration{Webhooks: f.hooks} -} - -func (f *fakeHookSource) Run(stopCh <-chan struct{}) {} - -type fakeServiceResolver struct { - base url.URL -} - -func (f fakeServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { - if namespace == "failResolve" { - return nil, fmt.Errorf("couldn't resolve service location") - } - u := f.base - return &u, nil -} - -type fakeNamespaceLister struct { - namespaces map[string]*corev1.Namespace -} - -func (f fakeNamespaceLister) List(selector labels.Selector) (ret []*corev1.Namespace, err error) { - return nil, nil -} -func (f fakeNamespaceLister) Get(name string) (*corev1.Namespace, error) { - ns, ok := f.namespaces[name] - if ok { - return ns, nil - } - return nil, errors.NewNotFound(corev1.Resource("namespaces"), name) -} - -// ccfgSVC returns a client config using the service reference mechanism. -func ccfgSVC(urlPath string) registrationv1beta1.WebhookClientConfig { - return registrationv1beta1.WebhookClientConfig{ - Service: ®istrationv1beta1.ServiceReference{ - Name: "webhook-test", - Namespace: "default", - Path: &urlPath, - }, - CABundle: testcerts.CACert, - } -} - -type urlConfigGenerator struct { - baseURL *url.URL -} - -// ccfgURL returns a client config using the URL mechanism. -func (c urlConfigGenerator) ccfgURL(urlPath string) registrationv1beta1.WebhookClientConfig { - u2 := *c.baseURL - u2.Path = urlPath - urlString := u2.String() - return registrationv1beta1.WebhookClientConfig{ - URL: &urlString, - CABundle: testcerts.CACert, - } -} - -// TestValidate tests that ValidatingAdmissionWebhook#Validate works as expected -func TestValidate(t *testing.T) { - scheme := runtime.NewScheme() - v1beta1.AddToScheme(scheme) - corev1.AddToScheme(scheme) - - testServer := newTestServer(t) - testServer.StartTLS() - defer testServer.Close() - serverURL, err := url.ParseRequestURI(testServer.URL) - if err != nil { - t.Fatalf("this should never happen? %v", err) - } - wh, err := NewValidatingAdmissionWebhook(nil) - if err != nil { - t.Fatal(err) - } - cm, err := config.NewClientManager() - if err != nil { - t.Fatalf("cannot create client manager: %v", err) - } - cm.SetAuthenticationInfoResolver(newFakeAuthenticationInfoResolver(new(int32))) - cm.SetServiceResolver(fakeServiceResolver{base: *serverURL}) - wh.clientManager = cm - wh.SetScheme(scheme) - if err = wh.clientManager.Validate(); err != nil { - t.Fatal(err) - } - namespace := "webhook-test" - wh.namespaceMatcher.NamespaceLister = fakeNamespaceLister{map[string]*corev1.Namespace{ - namespace: { - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "runlevel": "0", - }, - }, - }, - }, - } - - // Set up a test object for the call - kind := corev1.SchemeGroupVersion.WithKind("Pod") - name := "my-pod" - object := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "pod.name": name, - }, - Name: name, - Namespace: namespace, - }, - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Pod", - }, - } - oldObject := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}, - } - operation := admission.Update - resource := corev1.Resource("pods").WithVersion("v1") - subResource := "" - userInfo := user.DefaultInfo{ - Name: "webhook-test", - UID: "webhook-test", - } - - ccfgURL := urlConfigGenerator{serverURL}.ccfgURL - - type test struct { - hookSource fakeHookSource - path string - expectAllow bool - errorContains string - } - - matchEverythingRules := []registrationv1beta1.RuleWithOperations{{ - Operations: []registrationv1beta1.OperationType{registrationv1beta1.OperationAll}, - Rule: registrationv1beta1.Rule{ - APIGroups: []string{"*"}, - APIVersions: []string{"*"}, - Resources: []string{"*/*"}, - }, - }} - - policyFail := registrationv1beta1.Fail - policyIgnore := registrationv1beta1.Ignore - - table := map[string]test{ - "no match": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "nomatch", - ClientConfig: ccfgSVC("disallow"), - Rules: []registrationv1beta1.RuleWithOperations{{ - Operations: []registrationv1beta1.OperationType{registrationv1beta1.Create}, - }}, - }}, - }, - expectAllow: true, - }, - "match & allow": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "allow", - ClientConfig: ccfgSVC("allow"), - Rules: matchEverythingRules, - }}, - }, - expectAllow: true, - }, - "match & disallow": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallow", - ClientConfig: ccfgSVC("disallow"), - Rules: matchEverythingRules, - }}, - }, - errorContains: "without explanation", - }, - "match & disallow ii": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallowReason", - ClientConfig: ccfgSVC("disallowReason"), - Rules: matchEverythingRules, - }}, - }, - errorContains: "you shall not pass", - }, - "match & disallow & but allowed because namespaceSelector exempt the namespace": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallow", - ClientConfig: ccfgSVC("disallow"), - Rules: newMatchEverythingRules(), - NamespaceSelector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{{ - Key: "runlevel", - Values: []string{"1"}, - Operator: metav1.LabelSelectorOpIn, - }}, - }, - }}, - }, - expectAllow: true, - }, - "match & disallow & but allowed because namespaceSelector exempt the namespace ii": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallow", - ClientConfig: ccfgSVC("disallow"), - Rules: newMatchEverythingRules(), - NamespaceSelector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{{ - Key: "runlevel", - Values: []string{"0"}, - Operator: metav1.LabelSelectorOpNotIn, - }}, - }, - }}, - }, - expectAllow: true, - }, - "match & fail (but allow because fail open)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "internalErr A", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyIgnore, - }, { - Name: "internalErr B", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyIgnore, - }, { - Name: "internalErr C", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - }, - "match & fail (but disallow because fail closed on nil)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "internalErr A", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - }, { - Name: "internalErr B", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - }, { - Name: "internalErr C", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - }}, - }, - expectAllow: false, - }, - "match & fail (but fail because fail closed)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "internalErr A", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyFail, - }, { - Name: "internalErr B", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyFail, - }, { - Name: "internalErr C", - ClientConfig: ccfgSVC("internalErr"), - Rules: matchEverythingRules, - FailurePolicy: &policyFail, - }}, - }, - expectAllow: false, - }, - "match & allow (url)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "allow", - ClientConfig: ccfgURL("allow"), - Rules: matchEverythingRules, - }}, - }, - expectAllow: true, - }, - "match & disallow (url)": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "disallow", - ClientConfig: ccfgURL("disallow"), - Rules: matchEverythingRules, - }}, - }, - errorContains: "without explanation", - }, - "absent response and fail open": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "nilResponse", - ClientConfig: ccfgURL("nilResponse"), - FailurePolicy: &policyIgnore, - Rules: matchEverythingRules, - }}, - }, - expectAllow: true, - }, - "absent response and fail closed": { - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "nilResponse", - ClientConfig: ccfgURL("nilResponse"), - FailurePolicy: &policyFail, - Rules: matchEverythingRules, - }}, - }, - errorContains: "Webhook response was absent", - }, - // No need to test everything with the url case, since only the - // connection is different. - } - - for name, tt := range table { - if !strings.Contains(name, "no match") { - continue - } - t.Run(name, func(t *testing.T) { - wh.hookSource = &tt.hookSource - err = wh.Validate(admission.NewAttributesRecord(&object, &oldObject, kind, namespace, name, resource, subResource, operation, &userInfo)) - if tt.expectAllow != (err == nil) { - t.Errorf("expected allowed=%v, but got err=%v", tt.expectAllow, err) - } - // ErrWebhookRejected is not an error for our purposes - if tt.errorContains != "" { - if err == nil || !strings.Contains(err.Error(), tt.errorContains) { - t.Errorf(" expected an error saying %q, but got %v", tt.errorContains, err) - } - } - if _, isStatusErr := err.(*errors.StatusError); err != nil && !isStatusErr { - t.Errorf("%s: expected a StatusError, got %T", name, err) - } - }) - } -} - -// TestValidateCachedClient tests that ValidatingAdmissionWebhook#Validate should cache restClient -func TestValidateCachedClient(t *testing.T) { - scheme := runtime.NewScheme() - v1beta1.AddToScheme(scheme) - corev1.AddToScheme(scheme) - - testServer := newTestServer(t) - testServer.StartTLS() - defer testServer.Close() - serverURL, err := url.ParseRequestURI(testServer.URL) - if err != nil { - t.Fatalf("this should never happen? %v", err) - } - wh, err := NewValidatingAdmissionWebhook(nil) - if err != nil { - t.Fatal(err) - } - cm, err := config.NewClientManager() - if err != nil { - t.Fatalf("cannot create client manager: %v", err) - } - cm.SetServiceResolver(fakeServiceResolver{base: *serverURL}) - wh.clientManager = cm - wh.SetScheme(scheme) - namespace := "webhook-test" - wh.namespaceMatcher.NamespaceLister = fakeNamespaceLister{map[string]*corev1.Namespace{ - namespace: { - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "runlevel": "0", - }, - }, - }, - }, - } - - // Set up a test object for the call - kind := corev1.SchemeGroupVersion.WithKind("Pod") - name := "my-pod" - object := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "pod.name": name, - }, - Name: name, - Namespace: namespace, - }, - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Pod", - }, - } - oldObject := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}, - } - operation := admission.Update - resource := corev1.Resource("pods").WithVersion("v1") - subResource := "" - userInfo := user.DefaultInfo{ - Name: "webhook-test", - UID: "webhook-test", - } - ccfgURL := urlConfigGenerator{serverURL}.ccfgURL - - type test struct { - name string - hookSource fakeHookSource - expectAllow bool - expectCache bool - } - - policyIgnore := registrationv1beta1.Ignore - cases := []test{ - { - name: "cache 1", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache1", - ClientConfig: ccfgSVC("allow"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: true, - }, - { - name: "cache 2", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache2", - ClientConfig: ccfgSVC("internalErr"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: true, - }, - { - name: "cache 3", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache3", - ClientConfig: ccfgSVC("allow"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: false, - }, - { - name: "cache 4", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache4", - ClientConfig: ccfgURL("allow"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: true, - }, - { - name: "cache 5", - hookSource: fakeHookSource{ - hooks: []registrationv1beta1.Webhook{{ - Name: "cache5", - ClientConfig: ccfgURL("allow"), - Rules: newMatchEverythingRules(), - FailurePolicy: &policyIgnore, - }}, - }, - expectAllow: true, - expectCache: false, - }, - } - - for _, testcase := range cases { - t.Run(testcase.name, func(t *testing.T) { - wh.hookSource = &testcase.hookSource - authInfoResolverCount := new(int32) - r := newFakeAuthenticationInfoResolver(authInfoResolverCount) - wh.clientManager.SetAuthenticationInfoResolver(r) - if err = wh.clientManager.Validate(); err != nil { - t.Fatal(err) - } - - err = wh.Validate(admission.NewAttributesRecord(&object, &oldObject, kind, namespace, testcase.name, resource, subResource, operation, &userInfo)) - if testcase.expectAllow != (err == nil) { - t.Errorf("expected allowed=%v, but got err=%v", testcase.expectAllow, err) - } - - if testcase.expectCache && *authInfoResolverCount != 1 { - t.Errorf("expected cacheclient, but got none") - } - - if !testcase.expectCache && *authInfoResolverCount != 0 { - t.Errorf("expected not cacheclient, but got cache") - } - }) - } - -} - -func newTestServer(t *testing.T) *httptest.Server { - // Create the test webhook server - sCert, err := tls.X509KeyPair(testcerts.ServerCert, testcerts.ServerKey) - if err != nil { - t.Fatal(err) - } - rootCAs := x509.NewCertPool() - rootCAs.AppendCertsFromPEM(testcerts.CACert) - testServer := httptest.NewUnstartedServer(http.HandlerFunc(webhookHandler)) - testServer.TLS = &tls.Config{ - Certificates: []tls.Certificate{sCert}, - ClientCAs: rootCAs, - ClientAuth: tls.RequireAndVerifyClientCert, - } - return testServer -} - -func webhookHandler(w http.ResponseWriter, r *http.Request) { - fmt.Printf("got req: %v\n", r.URL.Path) - switch r.URL.Path { - case "/internalErr": - http.Error(w, "webhook internal server error", http.StatusInternalServerError) - return - case "/invalidReq": - w.WriteHeader(http.StatusSwitchingProtocols) - w.Write([]byte("webhook invalid request")) - return - case "/invalidResp": - w.Header().Set("Content-Type", "application/json") - w.Write([]byte("webhook invalid response")) - case "/disallow": - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ - Response: &v1beta1.AdmissionResponse{ - Allowed: false, - }, - }) - case "/disallowReason": - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ - Response: &v1beta1.AdmissionResponse{ - Allowed: false, - Result: &metav1.Status{ - Message: "you shall not pass", - }, - }, - }) - case "/allow": - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{ - Response: &v1beta1.AdmissionResponse{ - Allowed: true, - }, - }) - case "/nilResposne": - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{}) - default: - http.NotFound(w, r) - } -} - -func newFakeAuthenticationInfoResolver(count *int32) *fakeAuthenticationInfoResolver { - return &fakeAuthenticationInfoResolver{ - restConfig: &rest.Config{ - TLSClientConfig: rest.TLSClientConfig{ - CAData: testcerts.CACert, - CertData: testcerts.ClientCert, - KeyData: testcerts.ClientKey, - }, - }, - cachedCount: count, - } -} - -type fakeAuthenticationInfoResolver struct { - restConfig *rest.Config - cachedCount *int32 -} - -func (c *fakeAuthenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) { - atomic.AddInt32(c.cachedCount, 1) - return c.restConfig, nil -} - -func (c *fakeAuthenticationInfoResolver) ClientConfigForService(serviceName, serviceNamespace string) (*rest.Config, error) { - atomic.AddInt32(c.cachedCount, 1) - return c.restConfig, nil -} - -func newMatchEverythingRules() []registrationv1beta1.RuleWithOperations { - return []registrationv1beta1.RuleWithOperations{{ - Operations: []registrationv1beta1.OperationType{registrationv1beta1.OperationAll}, - Rule: registrationv1beta1.Rule{ - APIGroups: []string{"*"}, - APIVersions: []string{"*"}, - Resources: []string{"*/*"}, - }, - }} -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go new file mode 100644 index 000000000..528d79a87 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/dispatcher.go @@ -0,0 +1,118 @@ +/* +Copyright 2018 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 validating + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/golang/glog" + "k8s.io/apiserver/pkg/admission/plugin/webhook/config" + "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" + + admissionv1beta1 "k8s.io/api/admission/v1beta1" + "k8s.io/api/admissionregistration/v1beta1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + admissionmetrics "k8s.io/apiserver/pkg/admission/metrics" + webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors" + "k8s.io/apiserver/pkg/admission/plugin/webhook/request" +) + +type validatingDispatcher struct { + cm *config.ClientManager +} + +func newValidatingDispatcher(cm *config.ClientManager) generic.Dispatcher { + return &validatingDispatcher{cm} +} + +var _ generic.Dispatcher = &validatingDispatcher{} + +func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, relevantHooks []*v1beta1.Webhook) error { + wg := sync.WaitGroup{} + errCh := make(chan error, len(relevantHooks)) + wg.Add(len(relevantHooks)) + for i := range relevantHooks { + go func(hook *v1beta1.Webhook) { + defer wg.Done() + + t := time.Now() + err := d.callHook(ctx, hook, attr) + admissionmetrics.Metrics.ObserveWebhook(time.Since(t), err != nil, attr.Attributes, "validating", hook.Name) + if err == nil { + return + } + + ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore + if callErr, ok := err.(*webhookerrors.ErrCallingWebhook); ok { + if ignoreClientCallFailures { + glog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr) + utilruntime.HandleError(callErr) + return + } + + glog.Warningf("Failed calling webhook, failing closed %v: %v", hook.Name, err) + errCh <- apierrors.NewInternalError(err) + return + } + + glog.Warningf("rejected by webhook %q: %#v", hook.Name, err) + errCh <- err + }(relevantHooks[i]) + } + wg.Wait() + close(errCh) + + var errs []error + for e := range errCh { + errs = append(errs, e) + } + if len(errs) == 0 { + return nil + } + if len(errs) > 1 { + for i := 1; i < len(errs); i++ { + // TODO: merge status errors; until then, just return the first one. + utilruntime.HandleError(errs[i]) + } + } + return errs[0] +} + +func (d *validatingDispatcher) callHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes) error { + // Make the webhook request + request := request.CreateAdmissionReview(attr) + client, err := d.cm.HookClient(h) + if err != nil { + return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err} + } + response := &admissionv1beta1.AdmissionReview{} + if err := client.Post().Context(ctx).Body(&request).Do().Into(response); err != nil { + return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err} + } + + if response.Response == nil { + return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")} + } + if response.Response.Allowed { + return nil + } + return webhookerrors.ToStatusErr(h.Name, response.Response.Result) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin.go new file mode 100644 index 000000000..8417ccffb --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin.go @@ -0,0 +1,64 @@ +/* +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 validating + +import ( + "io" + + "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/admission/configuration" + "k8s.io/apiserver/pkg/admission/plugin/webhook/generic" +) + +const ( + // Name of admission plug-in + PluginName = "ValidatingAdmissionWebhook" +) + +// Register registers a plugin +func Register(plugins *admission.Plugins) { + plugins.Register(PluginName, func(configFile io.Reader) (admission.Interface, error) { + plugin, err := NewValidatingAdmissionWebhook(configFile) + if err != nil { + return nil, err + } + + return plugin, nil + }) +} + +// Plugin is an implementation of admission.Interface. +type Plugin struct { + *generic.Webhook +} + +var _ admission.ValidationInterface = &Plugin{} + +// NewValidatingAdmissionWebhook returns a generic admission webhook plugin. +func NewValidatingAdmissionWebhook(configFile io.Reader) (*Plugin, error) { + handler := admission.NewHandler(admission.Connect, admission.Create, admission.Delete, admission.Update) + webhook, err := generic.NewWebhook(handler, configFile, configuration.NewValidatingWebhookConfigurationManager, newValidatingDispatcher) + if err != nil { + return nil, err + } + return &Plugin{webhook}, nil +} + +// Validate makes an admission decision based on the request attributes. +func (a *Plugin) Validate(attr admission.Attributes) error { + return a.Webhook.Dispatch(attr) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go new file mode 100644 index 000000000..1cc031c57 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/plugin_test.go @@ -0,0 +1,149 @@ +/* +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 validating + +import ( + "net/url" + "strings" + "testing" + + "k8s.io/api/admission/v1beta1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + webhooktesting "k8s.io/apiserver/pkg/admission/plugin/webhook/testing" +) + +// TestValidate tests that ValidatingWebhook#Validate works as expected +func TestValidate(t *testing.T) { + scheme := runtime.NewScheme() + v1beta1.AddToScheme(scheme) + corev1.AddToScheme(scheme) + + testServer := webhooktesting.NewTestServer(t) + testServer.StartTLS() + defer testServer.Close() + + serverURL, err := url.ParseRequestURI(testServer.URL) + if err != nil { + t.Fatalf("this should never happen? %v", err) + } + + stopCh := make(chan struct{}) + defer close(stopCh) + + for _, tt := range webhooktesting.NewTestCases(serverURL) { + // TODO: re-enable all tests + if !strings.Contains(tt.Name, "no match") { + continue + } + + wh, err := NewValidatingAdmissionWebhook(nil) + if err != nil { + t.Errorf("%s: failed to create validating webhook: %v", tt.Name, err) + continue + } + + ns := "webhook-test" + client, informer := webhooktesting.NewFakeDataSource(ns, tt.Webhooks, false, stopCh) + + wh.SetAuthenticationInfoResolverWrapper(webhooktesting.Wrapper(webhooktesting.NewAuthenticationInfoResolver(new(int32)))) + wh.SetServiceResolver(webhooktesting.NewServiceResolver(*serverURL)) + wh.SetScheme(scheme) + wh.SetExternalKubeClientSet(client) + wh.SetExternalKubeInformerFactory(informer) + + informer.Start(stopCh) + informer.WaitForCacheSync(stopCh) + + if err = wh.ValidateInitialization(); err != nil { + t.Errorf("%s: failed to validate initialization: %v", tt.Name, err) + continue + } + + err = wh.Validate(webhooktesting.NewAttribute(ns, nil)) + if tt.ExpectAllow != (err == nil) { + t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) + } + // ErrWebhookRejected is not an error for our purposes + if tt.ErrorContains != "" { + if err == nil || !strings.Contains(err.Error(), tt.ErrorContains) { + t.Errorf("%s: expected an error saying %q, but got %v", tt.Name, tt.ErrorContains, err) + } + } + if _, isStatusErr := err.(*errors.StatusError); err != nil && !isStatusErr { + t.Errorf("%s: expected a StatusError, got %T", tt.Name, err) + } + } +} + +// TestValidateCachedClient tests that ValidatingWebhook#Validate should cache restClient +func TestValidateCachedClient(t *testing.T) { + scheme := runtime.NewScheme() + v1beta1.AddToScheme(scheme) + corev1.AddToScheme(scheme) + + testServer := webhooktesting.NewTestServer(t) + testServer.StartTLS() + defer testServer.Close() + serverURL, err := url.ParseRequestURI(testServer.URL) + if err != nil { + t.Fatalf("this should never happen? %v", err) + } + + stopCh := make(chan struct{}) + defer close(stopCh) + + wh, err := NewValidatingAdmissionWebhook(nil) + if err != nil { + t.Fatalf("Failed to create validating webhook: %v", err) + } + wh.SetServiceResolver(webhooktesting.NewServiceResolver(*serverURL)) + wh.SetScheme(scheme) + + for _, tt := range webhooktesting.NewCachedClientTestcases(serverURL) { + ns := "webhook-test" + client, informer := webhooktesting.NewFakeDataSource(ns, tt.Webhooks, false, stopCh) + + // override the webhook source. The client cache will stay the same. + cacheMisses := new(int32) + wh.SetAuthenticationInfoResolverWrapper(webhooktesting.Wrapper(webhooktesting.NewAuthenticationInfoResolver(cacheMisses))) + wh.SetExternalKubeClientSet(client) + wh.SetExternalKubeInformerFactory(informer) + + informer.Start(stopCh) + informer.WaitForCacheSync(stopCh) + + if err = wh.ValidateInitialization(); err != nil { + t.Errorf("%s: failed to validate initialization: %v", tt.Name, err) + continue + } + + err = wh.Validate(webhooktesting.NewAttribute(ns, nil)) + if tt.ExpectAllow != (err == nil) { + t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err) + } + + if tt.ExpectCacheMiss && *cacheMisses == 0 { + t.Errorf("%s: expected cache miss, but got no AuthenticationInfoResolver call", tt.Name) + } + + if !tt.ExpectCacheMiss && *cacheMisses > 0 { + t.Errorf("%s: expected client to be cached, but got %d AuthenticationInfoResolver calls", tt.Name, *cacheMisses) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/BUILD index f3446c1c4..6df04e38c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/BUILD @@ -1,36 +1,3 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "attributes.go", - "conversion.go", - "doc.go", - ], - importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/versioned", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["conversion_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/apiserver/pkg/apis/example:go_default_library", - "//vendor/k8s.io/apiserver/pkg/apis/example/v1:go_default_library", - "//vendor/k8s.io/apiserver/pkg/apis/example2/v1:go_default_library", - ], -) - filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/attributes.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/attributes.go deleted file mode 100644 index 58f8ae6aa..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/attributes.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -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 versioned - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apiserver/pkg/admission" -) - -// Attributes is a wrapper around the original admission attributes. It allows -// override the internal objects with the versioned ones. -type Attributes struct { - admission.Attributes - OldObject runtime.Object - Object runtime.Object -} - -// GetObject overrides the original GetObjects() and it returns the versioned -// object. -func (v Attributes) GetObject() runtime.Object { - return v.Object -} - -// GetOldObject overrides the original GetOldObjects() and it returns the -// versioned oldObject. -func (v Attributes) GetOldObject() runtime.Object { - return v.OldObject -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/conversion.go deleted file mode 100644 index a1ba712fc..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/conversion.go +++ /dev/null @@ -1,67 +0,0 @@ -/* -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 versioned - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// Convertor converts objects to the desired version. -type Convertor struct { - Scheme *runtime.Scheme -} - -// Convert converts the in object to the out object and returns an error if the -// conversion fails. -func (c Convertor) Convert(in runtime.Object, out runtime.Object) error { - // For custom resources, because ConvertToGVK reuses the passed in object as - // the output. c.Scheme.Convert resets the objects to empty if in == out, so - // we skip the conversion if that's the case. - if in == out { - return nil - } - return c.Scheme.Convert(in, out, nil) -} - -// ConvertToGVK converts object to the desired gvk. -func (c Convertor) ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind) (runtime.Object, error) { - // Unlike other resources, custom resources do not have internal version, so - // if obj is a custom resource, it should not need conversion. - if obj.GetObjectKind().GroupVersionKind() == gvk { - return obj, nil - } - out, err := c.Scheme.New(gvk) - if err != nil { - return nil, err - } - err = c.Scheme.Convert(obj, out, nil) - if err != nil { - return nil, err - } - return out, nil -} - -// Validate checks if the conversion has a scheme. -func (c *Convertor) Validate() error { - if c.Scheme == nil { - return fmt.Errorf("the Convertor requires a scheme") - } - return nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/conversion_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/conversion_test.go deleted file mode 100644 index 1429c71e1..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/conversion_test.go +++ /dev/null @@ -1,219 +0,0 @@ -/* -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 versioned - -import ( - "reflect" - "testing" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apiserver/pkg/apis/example" - examplev1 "k8s.io/apiserver/pkg/apis/example/v1" - example2v1 "k8s.io/apiserver/pkg/apis/example2/v1" -) - -func initiateScheme() *runtime.Scheme { - s := runtime.NewScheme() - example.AddToScheme(s) - examplev1.AddToScheme(s) - example2v1.AddToScheme(s) - return s -} - -func TestConvertToGVK(t *testing.T) { - scheme := initiateScheme() - c := Convertor{Scheme: scheme} - table := map[string]struct { - obj runtime.Object - gvk schema.GroupVersionKind - expectedObj runtime.Object - }{ - "convert example#Pod to example/v1#Pod": { - obj: &example.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod1", - Labels: map[string]string{ - "key": "value", - }, - }, - Spec: example.PodSpec{ - RestartPolicy: example.RestartPolicy("never"), - }, - }, - gvk: examplev1.SchemeGroupVersion.WithKind("Pod"), - expectedObj: &examplev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod1", - Labels: map[string]string{ - "key": "value", - }, - }, - Spec: examplev1.PodSpec{ - RestartPolicy: examplev1.RestartPolicy("never"), - }, - }, - }, - "convert example#replicaset to example2/v1#replicaset": { - obj: &example.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: "rs1", - Labels: map[string]string{ - "key": "value", - }, - }, - Spec: example.ReplicaSetSpec{ - Replicas: 1, - }, - }, - gvk: example2v1.SchemeGroupVersion.WithKind("ReplicaSet"), - expectedObj: &example2v1.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: "rs1", - Labels: map[string]string{ - "key": "value", - }, - }, - Spec: example2v1.ReplicaSetSpec{ - Replicas: func() *int32 { var i int32; i = 1; return &i }(), - }, - }, - }, - "no conversion for Unstructured object whose gvk matches the desired gvk": { - obj: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "mygroup.k8s.io/v1", - "kind": "Flunder", - "data": map[string]interface{}{ - "Key": "Value", - }, - }, - }, - gvk: schema.GroupVersionKind{Group: "mygroup.k8s.io", Version: "v1", Kind: "Flunder"}, - expectedObj: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "mygroup.k8s.io/v1", - "kind": "Flunder", - "data": map[string]interface{}{ - "Key": "Value", - }, - }, - }, - }, - } - - for name, test := range table { - t.Run(name, func(t *testing.T) { - actual, err := c.ConvertToGVK(test.obj, test.gvk) - if err != nil { - t.Error(err) - } - if !reflect.DeepEqual(actual, test.expectedObj) { - t.Errorf("\nexpected:\n%#v\ngot:\n %#v\n", test.expectedObj, actual) - } - }) - } -} - -func TestConvert(t *testing.T) { - scheme := initiateScheme() - c := Convertor{Scheme: scheme} - sampleCRD := unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "mygroup.k8s.io/v1", - "kind": "Flunder", - "data": map[string]interface{}{ - "Key": "Value", - }, - }, - } - - table := map[string]struct { - in runtime.Object - out runtime.Object - expectedObj runtime.Object - }{ - "convert example/v1#Pod to example#Pod": { - in: &examplev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod1", - Labels: map[string]string{ - "key": "value", - }, - }, - Spec: examplev1.PodSpec{ - RestartPolicy: examplev1.RestartPolicy("never"), - }, - }, - out: &example.Pod{}, - expectedObj: &example.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod1", - Labels: map[string]string{ - "key": "value", - }, - }, - Spec: example.PodSpec{ - RestartPolicy: example.RestartPolicy("never"), - }, - }, - }, - "convert example2/v1#replicaset to example#replicaset": { - in: &example2v1.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: "rs1", - Labels: map[string]string{ - "key": "value", - }, - }, - Spec: example2v1.ReplicaSetSpec{ - Replicas: func() *int32 { var i int32; i = 1; return &i }(), - }, - }, - out: &example.ReplicaSet{}, - expectedObj: &example.ReplicaSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: "rs1", - Labels: map[string]string{ - "key": "value", - }, - }, - Spec: example.ReplicaSetSpec{ - Replicas: 1, - }, - }, - }, - "no conversion if the object is the same": { - in: &sampleCRD, - out: &sampleCRD, - expectedObj: &sampleCRD, - }, - } - for name, test := range table { - t.Run(name, func(t *testing.T) { - err := c.Convert(test.in, test.out) - if err != nil { - t.Error(err) - } - if !reflect.DeepEqual(test.out, test.expectedObj) { - t.Errorf("\nexpected:\n%#v\ngot:\n %#v\n", test.expectedObj, test.out) - } - }) - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/doc.go deleted file mode 100644 index d557a9fec..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/versioned/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -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 versioned provides tools for making sure the objects sent to a -// webhook are in a version the webhook understands. -package versioned // import "k8s.io/apiserver/pkg/admission/plugin/webhook/versioned" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugins.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugins.go index 50139780f..c17d62cd4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugins.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugins.go @@ -127,6 +127,8 @@ func splitStream(config io.Reader) (io.Reader, io.Reader, error) { // the given plugins. func (ps *Plugins) NewFromPlugins(pluginNames []string, configProvider ConfigProvider, pluginInitializer PluginInitializer, decorator Decorator) (Interface, error) { handlers := []Interface{} + mutationPlugins := []string{} + validationPlugins := []string{} for _, pluginName := range pluginNames { pluginConfig, err := configProvider.ConfigFor(pluginName) if err != nil { @@ -143,10 +145,20 @@ func (ps *Plugins) NewFromPlugins(pluginNames []string, configProvider ConfigPro } else { handlers = append(handlers, plugin) } + + if _, ok := plugin.(MutationInterface); ok { + mutationPlugins = append(mutationPlugins, pluginName) + } + if _, ok := plugin.(ValidationInterface); ok { + validationPlugins = append(validationPlugins, pluginName) + } } } - if len(pluginNames) != 0 { - glog.Infof("Loaded %d admission controller(s) successfully in the following order: %s.", len(pluginNames), strings.Join(pluginNames, ",")) + if len(mutationPlugins) != 0 { + glog.Infof("Loaded %d mutating admission controller(s) successfully in the following order: %s.", len(mutationPlugins), strings.Join(mutationPlugins, ",")) + } + if len(validationPlugins) != 0 { + glog.Infof("Loaded %d validating admission controller(s) successfully in the following order: %s.", len(validationPlugins), strings.Join(validationPlugins, ",")) } return chainAdmissionHandler(handlers), nil } @@ -160,16 +172,16 @@ func (ps *Plugins) InitPlugin(name string, config io.Reader, pluginInitializer P plugin, found, err := ps.getPlugin(name, config) if err != nil { - return nil, fmt.Errorf("Couldn't init admission plugin %q: %v", name, err) + return nil, fmt.Errorf("couldn't init admission plugin %q: %v", name, err) } if !found { - return nil, fmt.Errorf("Unknown admission plugin: %s", name) + return nil, fmt.Errorf("unknown admission plugin: %s", name) } pluginInitializer.Initialize(plugin) // ensure that plugins have been properly initialized if err := ValidateInitialization(plugin); err != nil { - return nil, err + return nil, fmt.Errorf("failed to initialize admission plugin %q: %v", name, err) } return plugin, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/install/BUILD index e92ce5e57..2084b4615 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/install/BUILD @@ -10,10 +10,8 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/apiserver/pkg/apis/apiserver/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/install/install.go index ce52be0a2..4b58a9710 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/install/install.go @@ -17,27 +17,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: apiserver.GroupName, - RootScopedKinds: sets.NewString("APIService"), - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: apiserver.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(apiserver.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.conversion.go index 3468b998b..464775337 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.deepcopy.go index 0bc0606d9..d7ff897db 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/zz_generated.deepcopy.go index e6bc8e2c9..475eb2861 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/apiserver/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/install/BUILD index 2da7015f5..796866c59 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/install/BUILD @@ -11,10 +11,8 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/apiserver/pkg/apis/audit/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/v1alpha1:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/install/install.go index 6acf7c5d1..026f82225 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/install/install.go @@ -19,30 +19,17 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/apis/audit" "k8s.io/apiserver/pkg/apis/audit/v1alpha1" "k8s.io/apiserver/pkg/apis/audit/v1beta1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: audit.GroupName, - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version, v1alpha1.SchemeGroupVersion.Version}, - // Any Kind that is not namespaced must be cluster scoped. - RootScopedKinds: sets.NewString("Event", "Policy"), - AddInternalObjectsToScheme: audit.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(audit.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.pb.go index 5f21dfaf2..816246c08 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2782,84 +2782,83 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1258 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x6f, 0x1b, 0xc5, - 0x17, 0xcf, 0xd6, 0x71, 0x63, 0x8f, 0x1b, 0xc7, 0x99, 0x56, 0xdf, 0xae, 0x72, 0xb0, 0xfd, 0x35, - 0x12, 0xb2, 0x20, 0xec, 0x26, 0x21, 0xd0, 0x80, 0x04, 0x22, 0x56, 0x2b, 0xb0, 0x94, 0x86, 0x30, - 0x89, 0x2b, 0xf1, 0xe3, 0xc0, 0xda, 0x7e, 0xb1, 0x17, 0xdb, 0xbb, 0xcb, 0xcc, 0xac, 0xab, 0xdc, - 0x38, 0x70, 0x45, 0xe2, 0xce, 0x1f, 0x53, 0x71, 0xcb, 0xb1, 0xc7, 0x9e, 0x2c, 0x62, 0xfe, 0x8b, - 0x1c, 0x2a, 0x34, 0xb3, 0xb3, 0x3b, 0x6b, 0xa7, 0x16, 0x0e, 0x87, 0xde, 0x76, 0xde, 0xfb, 0xbc, - 0xcf, 0x7b, 0xf3, 0xf6, 0xfd, 0x18, 0xf4, 0xcd, 0xe0, 0x80, 0x59, 0xae, 0x6f, 0x0f, 0xc2, 0x36, - 0x50, 0x0f, 0x38, 0x30, 0x7b, 0x0c, 0x5e, 0xd7, 0xa7, 0xb6, 0x52, 0x38, 0x81, 0xcb, 0x80, 0x8e, - 0x81, 0xda, 0xc1, 0xa0, 0x27, 0x4f, 0xb6, 0x13, 0x76, 0x5d, 0x6e, 0x8f, 0x77, 0x9d, 0x61, 0xd0, - 0x77, 0x76, 0xed, 0x1e, 0x78, 0x40, 0x1d, 0x0e, 0x5d, 0x2b, 0xa0, 0x3e, 0xf7, 0x71, 0x3d, 0xb2, - 0xb4, 0x12, 0x4b, 0x2b, 0x18, 0xf4, 0xe4, 0xc9, 0x92, 0x96, 0x56, 0x6c, 0xb9, 0xf5, 0x41, 0xcf, - 0xe5, 0xfd, 0xb0, 0x6d, 0x75, 0xfc, 0x91, 0xdd, 0xf3, 0x7b, 0xbe, 0x2d, 0x09, 0xda, 0xe1, 0xb9, - 0x3c, 0xc9, 0x83, 0xfc, 0x8a, 0x88, 0xb7, 0xb6, 0x75, 0x48, 0xb6, 0x13, 0xf2, 0x3e, 0x78, 0xdc, - 0xed, 0x38, 0xdc, 0xf5, 0x3d, 0x7b, 0x7c, 0x23, 0x8c, 0xad, 0x7d, 0x8d, 0x1e, 0x39, 0x9d, 0xbe, - 0xeb, 0x01, 0xbd, 0xd0, 0x77, 0x18, 0x01, 0x77, 0xde, 0x64, 0x65, 0x2f, 0xb2, 0xa2, 0xa1, 0xc7, - 0xdd, 0x11, 0xdc, 0x30, 0xf8, 0xf8, 0xdf, 0x0c, 0x58, 0xa7, 0x0f, 0x23, 0xe7, 0x86, 0xdd, 0x87, - 0x8b, 0xec, 0x42, 0xee, 0x0e, 0x6d, 0xd7, 0xe3, 0x8c, 0xd3, 0x79, 0xa3, 0xda, 0xeb, 0x02, 0xca, - 0x3e, 0x19, 0x83, 0xc7, 0xf1, 0x8f, 0x28, 0x27, 0xae, 0xd0, 0x75, 0xb8, 0x63, 0x1a, 0x55, 0xa3, - 0x5e, 0xd8, 0xdb, 0xb1, 0x74, 0xde, 0x13, 0x46, 0x9d, 0x7a, 0x81, 0xb6, 0xc6, 0xbb, 0xd6, 0xd7, - 0xed, 0x9f, 0xa0, 0xc3, 0x9f, 0x02, 0x77, 0x1a, 0xf8, 0x72, 0x52, 0x59, 0x99, 0x4e, 0x2a, 0x48, - 0xcb, 0x48, 0xc2, 0x8a, 0xb7, 0x51, 0x76, 0x08, 0x63, 0x18, 0x9a, 0x77, 0xaa, 0x46, 0x3d, 0xdf, - 0xf8, 0x9f, 0x02, 0x67, 0x8f, 0x84, 0xf0, 0x3a, 0xfe, 0x20, 0x11, 0x08, 0x7f, 0x8f, 0xf2, 0xe2, - 0xb6, 0x8c, 0x3b, 0xa3, 0xc0, 0xcc, 0xc8, 0x80, 0xde, 0x5b, 0x2e, 0xa0, 0x33, 0x77, 0x04, 0x8d, - 0x4d, 0xc5, 0x9e, 0x3f, 0x8b, 0x49, 0x88, 0xe6, 0xc3, 0xc7, 0x68, 0x4d, 0x56, 0x4e, 0xf3, 0xb1, - 0xb9, 0x2a, 0x83, 0xd9, 0x57, 0xf0, 0xb5, 0xc3, 0x48, 0x7c, 0x3d, 0xa9, 0xfc, 0x7f, 0x51, 0x3e, - 0xf9, 0x45, 0x00, 0xcc, 0x6a, 0x35, 0x1f, 0x93, 0x98, 0x44, 0x5c, 0x8d, 0x71, 0xa7, 0x07, 0x66, - 0x76, 0xf6, 0x6a, 0xa7, 0x42, 0x78, 0x1d, 0x7f, 0x90, 0x08, 0x84, 0xf7, 0x10, 0xa2, 0xf0, 0x73, - 0x08, 0x8c, 0xb7, 0x48, 0xd3, 0xbc, 0x2b, 0x4d, 0x92, 0xd4, 0x91, 0x44, 0x43, 0x52, 0x28, 0x5c, - 0x45, 0xab, 0x63, 0xa0, 0x6d, 0x73, 0x4d, 0xa2, 0xef, 0x29, 0xf4, 0xea, 0x33, 0xa0, 0x6d, 0x22, - 0x35, 0xf8, 0x2b, 0xb4, 0x1a, 0x32, 0xa0, 0x66, 0x4e, 0xe6, 0xea, 0xdd, 0x54, 0xae, 0xac, 0xd9, - 0xda, 0x16, 0x39, 0x6a, 0x31, 0xa0, 0x4d, 0xef, 0xdc, 0xd7, 0x4c, 0x42, 0x42, 0x24, 0x03, 0xee, - 0xa3, 0x92, 0x3b, 0x0a, 0x80, 0x32, 0xdf, 0x13, 0xa5, 0x22, 0x34, 0x66, 0xfe, 0x56, 0xac, 0x0f, - 0xa6, 0x93, 0x4a, 0xa9, 0x39, 0xc7, 0x41, 0x6e, 0xb0, 0xe2, 0xf7, 0x51, 0x9e, 0xf9, 0x21, 0xed, - 0x40, 0xf3, 0x84, 0x99, 0xa8, 0x9a, 0xa9, 0xe7, 0x1b, 0xeb, 0xe2, 0xa7, 0x9d, 0xc6, 0x42, 0xa2, - 0xf5, 0xf8, 0x1c, 0xe5, 0x7d, 0x59, 0x57, 0x04, 0xce, 0xcd, 0x82, 0x8c, 0xe7, 0x13, 0x6b, 0xd9, - 0xd1, 0xa0, 0xca, 0x94, 0xc0, 0x39, 0x50, 0xf0, 0x3a, 0x10, 0xf9, 0x49, 0x84, 0x44, 0x53, 0xe3, - 0x3e, 0x2a, 0x52, 0x60, 0x81, 0xef, 0x31, 0x38, 0xe5, 0x0e, 0x0f, 0x99, 0x79, 0x4f, 0x3a, 0xdb, - 0x5e, 0xae, 0xfc, 0x22, 0x9b, 0x06, 0x9e, 0x4e, 0x2a, 0x45, 0x32, 0xc3, 0x43, 0xe6, 0x78, 0xb1, - 0x83, 0xd6, 0xd5, 0x2f, 0x8e, 0x02, 0x31, 0xd7, 0xa5, 0xa3, 0xfa, 0x42, 0x47, 0x6a, 0x04, 0x58, - 0x2d, 0x6f, 0xe0, 0xf9, 0xcf, 0xbd, 0xc6, 0xe6, 0x74, 0x52, 0x59, 0x27, 0x69, 0x0a, 0x32, 0xcb, - 0x88, 0xbb, 0xfa, 0x32, 0xca, 0x47, 0xf1, 0x96, 0x3e, 0x66, 0x2e, 0xa2, 0x9c, 0xcc, 0x71, 0xe2, - 0xdf, 0x0c, 0x64, 0x2a, 0xbf, 0x04, 0x3a, 0xe0, 0x8e, 0xa1, 0x9b, 0xf4, 0x9d, 0xb9, 0x21, 0x1d, - 0xda, 0xcb, 0x65, 0xef, 0xa9, 0xdb, 0xa1, 0xbe, 0xec, 0xe0, 0xaa, 0xaa, 0x4c, 0x93, 0x2c, 0x20, - 0x26, 0x0b, 0x5d, 0x62, 0x1f, 0x15, 0x65, 0xab, 0xe9, 0x20, 0x4a, 0xff, 0x2d, 0x88, 0xb8, 0x93, - 0x8b, 0xa7, 0x33, 0x74, 0x64, 0x8e, 0x1e, 0x3f, 0x47, 0x05, 0xc7, 0xf3, 0x7c, 0x2e, 0x5b, 0x81, - 0x99, 0x9b, 0xd5, 0x4c, 0xbd, 0xb0, 0xf7, 0xc5, 0xf2, 0xd5, 0x29, 0x67, 0xb0, 0x75, 0xa8, 0x29, - 0x9e, 0x78, 0x9c, 0x5e, 0x34, 0xee, 0x2b, 0xf7, 0x85, 0x94, 0x86, 0xa4, 0x3d, 0x6d, 0x7d, 0x8e, - 0x4a, 0xf3, 0x56, 0xb8, 0x84, 0x32, 0x03, 0xb8, 0x90, 0x53, 0x3c, 0x4f, 0xc4, 0x27, 0x7e, 0x80, - 0xb2, 0x63, 0x67, 0x18, 0x42, 0x34, 0x7a, 0x49, 0x74, 0xf8, 0xf4, 0xce, 0x81, 0x51, 0x7b, 0x61, - 0xa0, 0xbc, 0x74, 0x7e, 0xe4, 0x32, 0x8e, 0x7f, 0xb8, 0xb1, 0x04, 0xac, 0xe5, 0x32, 0x26, 0xac, - 0xe5, 0x0a, 0x28, 0xa9, 0x88, 0x73, 0xb1, 0x24, 0xb5, 0x00, 0xce, 0x50, 0xd6, 0xe5, 0x30, 0x62, - 0xe6, 0x1d, 0x99, 0x1e, 0xfb, 0x96, 0xe9, 0x69, 0xac, 0xc7, 0x63, 0xb5, 0x29, 0x58, 0x48, 0x44, - 0x56, 0xfb, 0xc3, 0x40, 0xc5, 0x2f, 0xa9, 0x1f, 0x06, 0x04, 0xa2, 0x59, 0xc1, 0xf0, 0x3b, 0x28, - 0xdb, 0x13, 0x92, 0x28, 0x05, 0xda, 0x2e, 0x82, 0x45, 0x3a, 0x31, 0x7b, 0x68, 0x6c, 0x21, 0x23, - 0x52, 0xb3, 0x27, 0xa1, 0x21, 0x5a, 0x8f, 0x1f, 0x89, 0x4e, 0x8d, 0x0e, 0xc7, 0xce, 0x08, 0x98, - 0x99, 0x91, 0x06, 0xaa, 0xff, 0x52, 0x0a, 0x32, 0x8b, 0xab, 0xfd, 0x9a, 0x41, 0x1b, 0x73, 0xa3, - 0x07, 0x6f, 0xa3, 0x5c, 0x0c, 0x52, 0x11, 0x26, 0x59, 0x8b, 0xb9, 0x48, 0x82, 0xc0, 0x36, 0xca, - 0x7b, 0x82, 0x2a, 0x70, 0x3a, 0xea, 0xff, 0xe9, 0xe5, 0x76, 0x1c, 0x2b, 0x88, 0xc6, 0x88, 0x55, - 0x21, 0x0e, 0x72, 0x69, 0xa6, 0x56, 0x85, 0xc0, 0x12, 0xa9, 0xc1, 0x0d, 0x94, 0x09, 0xdd, 0xae, - 0x5a, 0x7d, 0x3b, 0x0a, 0x90, 0x69, 0x2d, 0xbb, 0xf6, 0x84, 0xb1, 0x58, 0x62, 0x4e, 0xe0, 0x3e, - 0x03, 0xca, 0x5c, 0xdf, 0x53, 0x7b, 0x2f, 0x59, 0x62, 0x87, 0x27, 0x4d, 0xa5, 0x21, 0x29, 0x14, - 0x3e, 0x44, 0x1b, 0xf1, 0xb5, 0x62, 0xc3, 0x68, 0xfb, 0x3d, 0x54, 0x86, 0x1b, 0x64, 0x56, 0x4d, - 0xe6, 0xf1, 0xf8, 0x23, 0x54, 0x60, 0x61, 0x3b, 0x49, 0x5f, 0xb4, 0x0e, 0x93, 0x36, 0x39, 0xd5, - 0x2a, 0x92, 0xc6, 0xd5, 0x5e, 0x1b, 0xe8, 0xee, 0x89, 0x3f, 0x74, 0x3b, 0x17, 0x6f, 0xe1, 0xa1, - 0xf3, 0x2d, 0xca, 0xd2, 0x70, 0x08, 0x71, 0x9d, 0xef, 0x2f, 0x5f, 0xe7, 0x51, 0x88, 0x24, 0x1c, - 0x82, 0x2e, 0x5a, 0x71, 0x62, 0x24, 0x62, 0xc4, 0x8f, 0x10, 0xf2, 0x47, 0x2e, 0x97, 0xd3, 0x28, - 0x2e, 0xc2, 0x87, 0x32, 0x90, 0x44, 0xaa, 0x9f, 0x1b, 0x29, 0x68, 0xed, 0x4f, 0x03, 0xa1, 0x88, - 0xfd, 0x2d, 0x34, 0x7a, 0x6b, 0xb6, 0xd1, 0x77, 0x6e, 0x9b, 0x80, 0x05, 0x9d, 0xfe, 0x22, 0x13, - 0xdf, 0x41, 0xe4, 0x44, 0xbf, 0x27, 0x8d, 0x65, 0xde, 0x93, 0x15, 0x94, 0x15, 0x8f, 0x9b, 0xb8, - 0xd5, 0xf3, 0x02, 0x29, 0xde, 0x20, 0x8c, 0x44, 0x72, 0x6c, 0x21, 0x24, 0x3e, 0xe4, 0x8c, 0x88, - 0x53, 0x5b, 0x14, 0xa9, 0x6d, 0x25, 0x52, 0x92, 0x42, 0x08, 0x42, 0xf1, 0xee, 0x62, 0xe6, 0xaa, - 0x26, 0x14, 0xcf, 0x31, 0x46, 0x22, 0x39, 0x76, 0xd3, 0x03, 0x26, 0x2b, 0x33, 0x71, 0xb0, 0x7c, - 0x26, 0x66, 0x47, 0x9a, 0x6e, 0xf9, 0x37, 0x8e, 0x27, 0x0b, 0xa1, 0xa4, 0xff, 0x99, 0x79, 0x57, - 0xc7, 0x9e, 0x0c, 0x08, 0x46, 0x52, 0x08, 0xfc, 0x19, 0xda, 0xf0, 0x7c, 0x2f, 0xa6, 0x6a, 0x91, - 0x23, 0x66, 0xae, 0x49, 0xa3, 0xfb, 0xa2, 0x09, 0x8f, 0x67, 0x55, 0x64, 0x1e, 0x3b, 0x57, 0x85, - 0xb9, 0xa5, 0xab, 0xb0, 0x61, 0x5d, 0x5e, 0x95, 0x57, 0x5e, 0x5e, 0x95, 0x57, 0x5e, 0x5d, 0x95, - 0x57, 0x7e, 0x99, 0x96, 0x8d, 0xcb, 0x69, 0xd9, 0x78, 0x39, 0x2d, 0x1b, 0xaf, 0xa6, 0x65, 0xe3, - 0xaf, 0x69, 0xd9, 0xf8, 0xfd, 0xef, 0xf2, 0xca, 0x77, 0xb9, 0x38, 0x09, 0xff, 0x04, 0x00, 0x00, - 0xff, 0xff, 0x3e, 0x3d, 0x28, 0x0e, 0x4d, 0x0e, 0x00, 0x00, + // 1242 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xd6, 0x71, 0x63, 0x8f, 0x1b, 0xc7, 0x99, 0x56, 0x74, 0x95, 0x83, 0x6d, 0x8c, 0x84, + 0x2c, 0x08, 0xbb, 0x49, 0x14, 0x68, 0x40, 0x02, 0x11, 0xab, 0x15, 0x58, 0x4a, 0x43, 0x98, 0xc4, + 0x95, 0xf8, 0x38, 0xb0, 0xb6, 0x5f, 0xec, 0xc5, 0xf6, 0xee, 0xb2, 0x33, 0xeb, 0x2a, 0x37, 0x0e, + 0x5c, 0x91, 0xb8, 0xf3, 0xc7, 0x54, 0xdc, 0x72, 0xec, 0xb1, 0x27, 0x8b, 0x98, 0xff, 0x22, 0x87, + 0x0a, 0xcd, 0xc7, 0xee, 0xac, 0x9d, 0x5a, 0x38, 0x1c, 0x7a, 0xdb, 0x79, 0xef, 0xf7, 0x7e, 0xef, + 0xcd, 0xdb, 0xf7, 0x31, 0xe8, 0xdb, 0xc1, 0x01, 0xb5, 0x5c, 0xdf, 0x1e, 0x44, 0x6d, 0x08, 0x3d, + 0x60, 0x40, 0xed, 0x31, 0x78, 0x5d, 0x3f, 0xb4, 0x95, 0xc2, 0x09, 0x5c, 0x0a, 0xe1, 0x18, 0x42, + 0x3b, 0x18, 0xf4, 0xc4, 0xc9, 0x76, 0xa2, 0xae, 0xcb, 0xec, 0xf1, 0xae, 0x33, 0x0c, 0xfa, 0xce, + 0xae, 0xdd, 0x03, 0x0f, 0x42, 0x87, 0x41, 0xd7, 0x0a, 0x42, 0x9f, 0xf9, 0xb8, 0x2e, 0x2d, 0xad, + 0xc4, 0xd2, 0x0a, 0x06, 0x3d, 0x71, 0xb2, 0x84, 0xa5, 0x15, 0x5b, 0x6e, 0x7d, 0xd4, 0x73, 0x59, + 0x3f, 0x6a, 0x5b, 0x1d, 0x7f, 0x64, 0xf7, 0xfc, 0x9e, 0x6f, 0x0b, 0x82, 0x76, 0x74, 0x2e, 0x4e, + 0xe2, 0x20, 0xbe, 0x24, 0xf1, 0xd6, 0xb6, 0x0e, 0xc9, 0x76, 0x22, 0xd6, 0x07, 0x8f, 0xb9, 0x1d, + 0x87, 0xb9, 0xbe, 0x67, 0x8f, 0x6f, 0x84, 0xb1, 0xb5, 0xaf, 0xd1, 0x23, 0xa7, 0xd3, 0x77, 0x3d, + 0x08, 0x2f, 0xf4, 0x1d, 0x46, 0xc0, 0x9c, 0x37, 0x59, 0xd9, 0x8b, 0xac, 0xc2, 0xc8, 0x63, 0xee, + 0x08, 0x6e, 0x18, 0x7c, 0xf2, 0x5f, 0x06, 0xb4, 0xd3, 0x87, 0x91, 0x33, 0x6f, 0x57, 0x7b, 0x5d, + 0x40, 0xd9, 0x27, 0x63, 0xf0, 0x18, 0xfe, 0x09, 0xe5, 0x78, 0x34, 0x5d, 0x87, 0x39, 0xa6, 0x51, + 0x35, 0xea, 0x85, 0xbd, 0x1d, 0x4b, 0xa7, 0x30, 0x21, 0xd5, 0x59, 0xe4, 0x68, 0x6b, 0xbc, 0x6b, + 0x7d, 0xd3, 0xfe, 0x19, 0x3a, 0xec, 0x29, 0x30, 0xa7, 0x81, 0x2f, 0x27, 0x95, 0x95, 0xe9, 0xa4, + 0x82, 0xb4, 0x8c, 0x24, 0xac, 0x78, 0x1b, 0x65, 0x87, 0x30, 0x86, 0xa1, 0x79, 0xa7, 0x6a, 0xd4, + 0xf3, 0x8d, 0x77, 0x14, 0x38, 0x7b, 0xc4, 0x85, 0xd7, 0xf1, 0x07, 0x91, 0x20, 0xfc, 0x03, 0xca, + 0xf3, 0xc0, 0x29, 0x73, 0x46, 0x81, 0x99, 0x11, 0x01, 0x7d, 0xb0, 0x5c, 0x40, 0x67, 0xee, 0x08, + 0x1a, 0x9b, 0x8a, 0x3d, 0x7f, 0x16, 0x93, 0x10, 0xcd, 0x87, 0x8f, 0xd1, 0x9a, 0x28, 0x82, 0xe6, + 0x63, 0x73, 0x55, 0x04, 0xb3, 0xaf, 0xe0, 0x6b, 0x87, 0x52, 0x7c, 0x3d, 0xa9, 0xbc, 0xbb, 0x28, + 0xa5, 0xec, 0x22, 0x00, 0x6a, 0xb5, 0x9a, 0x8f, 0x49, 0x4c, 0xc2, 0xaf, 0x46, 0x99, 0xd3, 0x03, + 0x33, 0x3b, 0x7b, 0xb5, 0x53, 0x2e, 0xbc, 0x8e, 0x3f, 0x88, 0x04, 0xe1, 0x3d, 0x84, 0x42, 0xf8, + 0x25, 0x02, 0xca, 0x5a, 0xa4, 0x69, 0xde, 0x15, 0x26, 0x49, 0xea, 0x48, 0xa2, 0x21, 0x29, 0x14, + 0xae, 0xa2, 0xd5, 0x31, 0x84, 0x6d, 0x73, 0x4d, 0xa0, 0xef, 0x29, 0xf4, 0xea, 0x33, 0x08, 0xdb, + 0x44, 0x68, 0xf0, 0xd7, 0x68, 0x35, 0xa2, 0x10, 0x9a, 0x39, 0x91, 0xab, 0xf7, 0x53, 0xb9, 0xb2, + 0x66, 0xcb, 0x94, 0xe7, 0xa8, 0x45, 0x21, 0x6c, 0x7a, 0xe7, 0xbe, 0x66, 0xe2, 0x12, 0x22, 0x18, + 0x70, 0x1f, 0x95, 0xdc, 0x51, 0x00, 0x21, 0xf5, 0x3d, 0x5e, 0x2a, 0x5c, 0x63, 0xe6, 0x6f, 0xc5, + 0xfa, 0x60, 0x3a, 0xa9, 0x94, 0x9a, 0x73, 0x1c, 0xe4, 0x06, 0x2b, 0xfe, 0x10, 0xe5, 0xa9, 0x1f, + 0x85, 0x1d, 0x68, 0x9e, 0x50, 0x13, 0x55, 0x33, 0xf5, 0x7c, 0x63, 0x9d, 0xff, 0xb4, 0xd3, 0x58, + 0x48, 0xb4, 0x1e, 0x9f, 0xa3, 0xbc, 0x2f, 0xea, 0x8a, 0xc0, 0xb9, 0x59, 0x10, 0xf1, 0x7c, 0x6a, + 0x2d, 0xdb, 0xe5, 0xaa, 0x4c, 0x09, 0x9c, 0x43, 0x08, 0x5e, 0x07, 0xa4, 0x9f, 0x44, 0x48, 0x34, + 0x35, 0xee, 0xa3, 0x62, 0x08, 0x34, 0xf0, 0x3d, 0x0a, 0xa7, 0xcc, 0x61, 0x11, 0x35, 0xef, 0x09, + 0x67, 0xdb, 0xcb, 0x95, 0x9f, 0xb4, 0x69, 0xe0, 0xe9, 0xa4, 0x52, 0x24, 0x33, 0x3c, 0x64, 0x8e, + 0x17, 0x3b, 0x68, 0x5d, 0xfd, 0x62, 0x19, 0x88, 0xb9, 0x2e, 0x1c, 0xd5, 0x17, 0x3a, 0x52, 0xdd, + 0x6c, 0xb5, 0xbc, 0x81, 0xe7, 0x3f, 0xf7, 0x1a, 0x9b, 0xd3, 0x49, 0x65, 0x9d, 0xa4, 0x29, 0xc8, + 0x2c, 0x23, 0xee, 0xea, 0xcb, 0x28, 0x1f, 0xc5, 0x5b, 0xfa, 0x98, 0xb9, 0x88, 0x72, 0x32, 0xc7, + 0x89, 0x7f, 0x37, 0x90, 0xa9, 0xfc, 0x12, 0xe8, 0x80, 0x3b, 0x86, 0x6e, 0xd2, 0x77, 0xe6, 0x86, + 0x70, 0x68, 0x2f, 0x97, 0xbd, 0xa7, 0x6e, 0x27, 0xf4, 0x45, 0x07, 0x57, 0x55, 0x65, 0x9a, 0x64, + 0x01, 0x31, 0x59, 0xe8, 0x12, 0xfb, 0xa8, 0x28, 0x5a, 0x4d, 0x07, 0x51, 0xfa, 0x7f, 0x41, 0xc4, + 0x9d, 0x5c, 0x3c, 0x9d, 0xa1, 0x23, 0x73, 0xf4, 0xf8, 0x39, 0x2a, 0x38, 0x9e, 0xe7, 0x33, 0xd1, + 0x0a, 0xd4, 0xdc, 0xac, 0x66, 0xea, 0x85, 0xbd, 0x2f, 0x97, 0xaf, 0x4e, 0x31, 0x83, 0xad, 0x43, + 0x4d, 0xf1, 0xc4, 0x63, 0xe1, 0x45, 0xe3, 0xbe, 0x72, 0x5f, 0x48, 0x69, 0x48, 0xda, 0xd3, 0xd6, + 0x17, 0xa8, 0x34, 0x6f, 0x85, 0x4b, 0x28, 0x33, 0x80, 0x0b, 0x31, 0xc5, 0xf3, 0x84, 0x7f, 0xe2, + 0x07, 0x28, 0x3b, 0x76, 0x86, 0x11, 0xc8, 0xd1, 0x4b, 0xe4, 0xe1, 0xb3, 0x3b, 0x07, 0x46, 0xed, + 0x85, 0x81, 0xf2, 0xc2, 0xf9, 0x91, 0x4b, 0x19, 0xfe, 0xf1, 0xc6, 0x12, 0xb0, 0x96, 0xcb, 0x18, + 0xb7, 0x16, 0x2b, 0xa0, 0xa4, 0x22, 0xce, 0xc5, 0x92, 0xd4, 0x02, 0x38, 0x43, 0x59, 0x97, 0xc1, + 0x88, 0x9a, 0x77, 0x44, 0x7a, 0xec, 0x5b, 0xa6, 0xa7, 0xb1, 0x1e, 0x8f, 0xd5, 0x26, 0x67, 0x21, + 0x92, 0xac, 0xf6, 0xa7, 0x81, 0x8a, 0x5f, 0x85, 0x7e, 0x14, 0x10, 0x90, 0xb3, 0x82, 0xe2, 0xf7, + 0x50, 0xb6, 0xc7, 0x25, 0x32, 0x05, 0xda, 0x4e, 0xc2, 0xa4, 0x8e, 0xcf, 0x9e, 0x30, 0xb6, 0x10, + 0x11, 0xa9, 0xd9, 0x93, 0xd0, 0x10, 0xad, 0xc7, 0x8f, 0x78, 0xa7, 0xca, 0xc3, 0xb1, 0x33, 0x02, + 0x6a, 0x66, 0x84, 0x81, 0xea, 0xbf, 0x94, 0x82, 0xcc, 0xe2, 0x6a, 0xbf, 0x65, 0xd0, 0xc6, 0xdc, + 0xe8, 0xc1, 0xdb, 0x28, 0x17, 0x83, 0x54, 0x84, 0x49, 0xd6, 0x62, 0x2e, 0x92, 0x20, 0xb0, 0x8d, + 0xf2, 0x1e, 0xa7, 0x0a, 0x9c, 0x8e, 0xfa, 0x7f, 0x7a, 0xb9, 0x1d, 0xc7, 0x0a, 0xa2, 0x31, 0x7c, + 0x55, 0xf0, 0x83, 0x58, 0x9a, 0xa9, 0x55, 0xc1, 0xb1, 0x44, 0x68, 0x70, 0x03, 0x65, 0x22, 0xb7, + 0xab, 0x56, 0xdf, 0x8e, 0x02, 0x64, 0x5a, 0xcb, 0xae, 0x3d, 0x6e, 0xcc, 0x97, 0x98, 0x13, 0xb8, + 0xcf, 0x20, 0xa4, 0xae, 0xef, 0xa9, 0xbd, 0x97, 0x2c, 0xb1, 0xc3, 0x93, 0xa6, 0xd2, 0x90, 0x14, + 0x0a, 0x1f, 0xa2, 0x8d, 0xf8, 0x5a, 0xb1, 0xa1, 0xdc, 0x7e, 0x0f, 0x95, 0xe1, 0x06, 0x99, 0x55, + 0x93, 0x79, 0x3c, 0xfe, 0x18, 0x15, 0x68, 0xd4, 0x4e, 0xd2, 0x27, 0xd7, 0x61, 0xd2, 0x26, 0xa7, + 0x5a, 0x45, 0xd2, 0xb8, 0xda, 0x6b, 0x03, 0xdd, 0x3d, 0xf1, 0x87, 0x6e, 0xe7, 0xe2, 0x2d, 0x3c, + 0x74, 0xbe, 0x43, 0xd9, 0x30, 0x1a, 0x42, 0x5c, 0xe7, 0xfb, 0xcb, 0xd7, 0xb9, 0x0c, 0x91, 0x44, + 0x43, 0xd0, 0x45, 0xcb, 0x4f, 0x94, 0x48, 0x46, 0xfc, 0x08, 0x21, 0x7f, 0xe4, 0x32, 0x31, 0x8d, + 0xe2, 0x22, 0x7c, 0x28, 0x02, 0x49, 0xa4, 0xfa, 0xb9, 0x91, 0x82, 0xd6, 0xfe, 0x32, 0x10, 0x92, + 0xec, 0x6f, 0xa1, 0xd1, 0x5b, 0xb3, 0x8d, 0xbe, 0x73, 0xdb, 0x04, 0x2c, 0xe8, 0xf4, 0x17, 0x99, + 0xf8, 0x0e, 0x3c, 0x27, 0xfa, 0x3d, 0x69, 0x2c, 0xf3, 0x9e, 0xac, 0xa0, 0x2c, 0x7f, 0xdc, 0xc4, + 0xad, 0x9e, 0xe7, 0x48, 0xfe, 0x06, 0xa1, 0x44, 0xca, 0xb1, 0x85, 0x10, 0xff, 0x10, 0x33, 0x22, + 0x4e, 0x6d, 0x91, 0xa7, 0xb6, 0x95, 0x48, 0x49, 0x0a, 0xc1, 0x09, 0xf9, 0xbb, 0x8b, 0x9a, 0xab, + 0x9a, 0x90, 0x3f, 0xc7, 0x28, 0x91, 0x72, 0xec, 0xa6, 0x07, 0x4c, 0x56, 0x64, 0xe2, 0x60, 0xf9, + 0x4c, 0xcc, 0x8e, 0x34, 0xdd, 0xf2, 0x6f, 0x1c, 0x4f, 0x16, 0x42, 0x49, 0xff, 0x53, 0xf3, 0xae, + 0x8e, 0x3d, 0x19, 0x10, 0x94, 0xa4, 0x10, 0xf8, 0x73, 0xb4, 0xe1, 0xf9, 0x5e, 0x4c, 0xd5, 0x22, + 0x47, 0xd4, 0x5c, 0x13, 0x46, 0xf7, 0x79, 0x13, 0x1e, 0xcf, 0xaa, 0xc8, 0x3c, 0x76, 0xae, 0x0a, + 0x73, 0x4b, 0x57, 0x61, 0xc3, 0xba, 0xbc, 0x2a, 0xaf, 0xbc, 0xbc, 0x2a, 0xaf, 0xbc, 0xba, 0x2a, + 0xaf, 0xfc, 0x3a, 0x2d, 0x1b, 0x97, 0xd3, 0xb2, 0xf1, 0x72, 0x5a, 0x36, 0x5e, 0x4d, 0xcb, 0xc6, + 0xdf, 0xd3, 0xb2, 0xf1, 0xc7, 0x3f, 0xe5, 0x95, 0xef, 0x73, 0x71, 0x12, 0xfe, 0x0d, 0x00, 0x00, + 0xff, 0xff, 0x17, 0x35, 0x5f, 0x9f, 0x18, 0x0e, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.proto index 2043e9ea8..b7cf491f7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/api/authentication/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.conversion.go index d12466044..4421bb6b9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.deepcopy.go index ab3c5320c..b59717231 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/generated.pb.go index 5cfab75fa..55ab3b259 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -2818,86 +2818,84 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1283 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x41, 0x6f, 0x1b, 0x45, - 0x14, 0xce, 0xd6, 0x71, 0x63, 0x8f, 0x1b, 0xc7, 0x9d, 0x56, 0x74, 0x95, 0x83, 0x6d, 0x8c, 0x04, - 0x11, 0xa4, 0xbb, 0x6d, 0x5a, 0x48, 0x84, 0x04, 0x28, 0x56, 0x2b, 0xb0, 0x94, 0x86, 0x68, 0x1c, - 0x57, 0x08, 0x38, 0xb0, 0xb6, 0x5f, 0xec, 0xc5, 0xf6, 0xee, 0x32, 0x33, 0x6b, 0x94, 0x1b, 0x7f, - 0x00, 0x89, 0x3b, 0xff, 0x82, 0x1f, 0x50, 0x71, 0xcc, 0xb1, 0xc7, 0x9e, 0x2c, 0x62, 0xfe, 0x45, - 0x04, 0x12, 0x9a, 0xd9, 0xd9, 0x9d, 0xb5, 0x5d, 0xab, 0x0e, 0x87, 0xde, 0x66, 0xde, 0xfb, 0xbe, - 0xef, 0xbd, 0x79, 0x33, 0xf3, 0x66, 0xd0, 0xc9, 0xe0, 0x80, 0x59, 0xae, 0x6f, 0x0f, 0xc2, 0x36, - 0x50, 0x0f, 0x38, 0x30, 0x7b, 0x0c, 0x5e, 0xd7, 0xa7, 0xb6, 0x72, 0x38, 0x81, 0xcb, 0x80, 0x8e, - 0x81, 0xda, 0xc1, 0xa0, 0x27, 0x67, 0xb6, 0x13, 0x76, 0x5d, 0x6e, 0x8f, 0x1f, 0xb6, 0x81, 0x3b, - 0x0f, 0xed, 0x1e, 0x78, 0x40, 0x1d, 0x0e, 0x5d, 0x2b, 0xa0, 0x3e, 0xf7, 0xf1, 0x07, 0x11, 0xd1, - 0x4a, 0x88, 0x56, 0x30, 0xe8, 0xc9, 0x99, 0x25, 0x89, 0x96, 0x22, 0x6e, 0xdf, 0xef, 0xb9, 0xbc, - 0x1f, 0xb6, 0xad, 0x8e, 0x3f, 0xb2, 0x7b, 0x7e, 0xcf, 0xb7, 0x25, 0xbf, 0x1d, 0x9e, 0xc9, 0x99, - 0x9c, 0xc8, 0x51, 0xa4, 0xbb, 0xbd, 0xab, 0x13, 0xb2, 0x9d, 0x90, 0xf7, 0xc1, 0xe3, 0x6e, 0xc7, - 0xe1, 0xae, 0xef, 0xd9, 0xe3, 0x85, 0x2c, 0xb6, 0x1f, 0x6b, 0xf4, 0xc8, 0xe9, 0xf4, 0x5d, 0x0f, - 0xe8, 0xb9, 0x5e, 0xc1, 0x08, 0xb8, 0xf3, 0x3a, 0x96, 0xbd, 0x8c, 0x45, 0x43, 0x8f, 0xbb, 0x23, - 0x58, 0x20, 0x7c, 0xf2, 0x26, 0x02, 0xeb, 0xf4, 0x61, 0xe4, 0x2c, 0xf0, 0x1e, 0x2d, 0xe3, 0x85, - 0xdc, 0x1d, 0xda, 0xae, 0xc7, 0x19, 0xa7, 0x0b, 0xa4, 0x83, 0x37, 0x6f, 0x89, 0x33, 0x0c, 0xfa, - 0x8b, 0x7b, 0x52, 0xfb, 0xa7, 0x80, 0xb2, 0x4f, 0xc7, 0xe0, 0x71, 0xfc, 0x03, 0xca, 0x89, 0xc5, - 0x77, 0x1d, 0xee, 0x98, 0x46, 0xd5, 0xd8, 0x29, 0xec, 0x3d, 0xb0, 0xf4, 0x86, 0x25, 0xb9, 0xe8, - 0x3d, 0x13, 0x68, 0x6b, 0xfc, 0xd0, 0xfa, 0xba, 0xfd, 0x23, 0x74, 0xf8, 0x33, 0xe0, 0x4e, 0x1d, - 0x5f, 0x4c, 0x2a, 0x6b, 0xd3, 0x49, 0x05, 0x69, 0x1b, 0x49, 0x54, 0xf1, 0x2e, 0xca, 0x0e, 0x61, - 0x0c, 0x43, 0xf3, 0x46, 0xd5, 0xd8, 0xc9, 0xd7, 0xdf, 0x51, 0xe0, 0xec, 0x91, 0x30, 0x5e, 0xc5, - 0x03, 0x12, 0x81, 0xf0, 0x77, 0x28, 0x2f, 0xea, 0xc4, 0xb8, 0x33, 0x0a, 0xcc, 0x8c, 0x4c, 0xe8, - 0xc3, 0xd5, 0x12, 0x3a, 0x75, 0x47, 0x50, 0xbf, 0xad, 0xd4, 0xf3, 0xa7, 0xb1, 0x08, 0xd1, 0x7a, - 0xf8, 0x18, 0x6d, 0xc8, 0xc2, 0x34, 0x9e, 0x98, 0xeb, 0x32, 0x99, 0xc7, 0x0a, 0xbe, 0x71, 0x18, - 0x99, 0xaf, 0x26, 0x95, 0x77, 0x97, 0xed, 0x04, 0x3f, 0x0f, 0x80, 0x59, 0xad, 0xc6, 0x13, 0x12, - 0x8b, 0x88, 0xa5, 0x31, 0xee, 0xf4, 0xc0, 0xcc, 0xce, 0x2e, 0xad, 0x29, 0x8c, 0x57, 0xf1, 0x80, - 0x44, 0x20, 0xbc, 0x87, 0x10, 0x85, 0x9f, 0x42, 0x60, 0xbc, 0x45, 0x1a, 0xe6, 0x4d, 0x49, 0x49, - 0x4a, 0x47, 0x12, 0x0f, 0x49, 0xa1, 0x70, 0x15, 0xad, 0x8f, 0x81, 0xb6, 0xcd, 0x0d, 0x89, 0xbe, - 0xa5, 0xd0, 0xeb, 0xcf, 0x81, 0xb6, 0x89, 0xf4, 0xe0, 0xaf, 0xd0, 0x7a, 0xc8, 0x80, 0x9a, 0x39, - 0x59, 0xab, 0xf7, 0x53, 0xb5, 0xb2, 0x66, 0x6f, 0x85, 0xa8, 0x51, 0x8b, 0x01, 0x6d, 0x78, 0x67, - 0xbe, 0x56, 0x12, 0x16, 0x22, 0x15, 0x70, 0x1f, 0x95, 0xdc, 0x51, 0x00, 0x94, 0xf9, 0x9e, 0x38, - 0x2a, 0xc2, 0x63, 0xe6, 0xaf, 0xa5, 0x7a, 0x77, 0x3a, 0xa9, 0x94, 0x1a, 0x73, 0x1a, 0x64, 0x41, - 0x15, 0x7f, 0x84, 0xf2, 0xcc, 0x0f, 0x69, 0x07, 0x1a, 0x27, 0xcc, 0x44, 0xd5, 0xcc, 0x4e, 0xbe, - 0xbe, 0x29, 0x36, 0xad, 0x19, 0x1b, 0x89, 0xf6, 0x63, 0x40, 0x79, 0x5f, 0x9e, 0x2b, 0x02, 0x67, - 0x66, 0x41, 0xe6, 0x73, 0x60, 0xad, 0xd8, 0x53, 0xd4, 0x29, 0x25, 0x70, 0x06, 0x14, 0xbc, 0x0e, - 0x44, 0x61, 0x12, 0x23, 0xd1, 0xca, 0xb8, 0x8f, 0x8a, 0x14, 0x58, 0xe0, 0x7b, 0x0c, 0x9a, 0xdc, - 0xe1, 0x21, 0x33, 0x6f, 0xc9, 0x58, 0xbb, 0xab, 0x9d, 0xbe, 0x88, 0x53, 0xc7, 0xd3, 0x49, 0xa5, - 0x48, 0x66, 0x74, 0xc8, 0x9c, 0x2e, 0x76, 0xd0, 0xa6, 0xda, 0xe1, 0x28, 0x11, 0x73, 0x53, 0x06, - 0xda, 0x59, 0x1a, 0x48, 0xf5, 0x0e, 0xab, 0xe5, 0x0d, 0x3c, 0xff, 0x67, 0xaf, 0x7e, 0x7b, 0x3a, - 0xa9, 0x6c, 0x92, 0xb4, 0x04, 0x99, 0x55, 0xc4, 0x5d, 0xbd, 0x18, 0x15, 0xa3, 0x78, 0xcd, 0x18, - 0x33, 0x0b, 0x51, 0x41, 0xe6, 0x34, 0xf1, 0xaf, 0x06, 0x32, 0x55, 0x5c, 0x02, 0x1d, 0x70, 0xc7, - 0xd0, 0x4d, 0xae, 0x9d, 0xb9, 0x25, 0x03, 0xda, 0xab, 0x55, 0xef, 0x99, 0xdb, 0xa1, 0xbe, 0xbc, - 0xc0, 0x55, 0x75, 0x30, 0x4d, 0xb2, 0x44, 0x98, 0x2c, 0x0d, 0x89, 0x7d, 0x54, 0x94, 0x37, 0x4d, - 0x27, 0x51, 0xfa, 0x7f, 0x49, 0xc4, 0x17, 0xb9, 0xd8, 0x9c, 0x91, 0x23, 0x73, 0xf2, 0x78, 0x8c, - 0x0a, 0x8e, 0xe7, 0xf9, 0x5c, 0xde, 0x04, 0x66, 0xde, 0xae, 0x66, 0x76, 0x0a, 0x7b, 0x5f, 0xac, - 0x7c, 0x38, 0x65, 0x07, 0xb6, 0x0e, 0xb5, 0xc2, 0x53, 0x8f, 0xd3, 0xf3, 0xfa, 0x1d, 0x15, 0xbd, - 0x90, 0xf2, 0x90, 0x74, 0xa0, 0xed, 0xcf, 0x51, 0x69, 0x9e, 0x85, 0x4b, 0x28, 0x33, 0x80, 0x73, - 0xd9, 0xc3, 0xf3, 0x44, 0x0c, 0xf1, 0x5d, 0x94, 0x1d, 0x3b, 0xc3, 0x10, 0xa2, 0xc6, 0x4b, 0xa2, - 0xc9, 0xa7, 0x37, 0x0e, 0x8c, 0xda, 0x0b, 0x03, 0xe5, 0x65, 0xf0, 0x23, 0x97, 0x71, 0xfc, 0xfd, - 0xc2, 0x13, 0x60, 0xad, 0x56, 0x30, 0xc1, 0x96, 0x0f, 0x40, 0x49, 0x65, 0x9c, 0x8b, 0x2d, 0xa9, - 0xf6, 0xdf, 0x44, 0x59, 0x97, 0xc3, 0x88, 0x99, 0x37, 0x64, 0x75, 0xac, 0xeb, 0x55, 0xa7, 0xbe, - 0x19, 0xf7, 0xd4, 0x86, 0x10, 0x21, 0x91, 0x56, 0xed, 0x77, 0x03, 0x15, 0xbf, 0xa4, 0x7e, 0x18, - 0x10, 0x88, 0x1a, 0x05, 0xc3, 0xef, 0xa1, 0x6c, 0x4f, 0x58, 0xa2, 0x0a, 0x68, 0x5e, 0x04, 0x8b, - 0x7c, 0xa2, 0xf1, 0xd0, 0x98, 0x21, 0x13, 0x52, 0x8d, 0x27, 0x91, 0x21, 0xda, 0x8f, 0xf7, 0xc5, - 0x3d, 0x8d, 0x26, 0xc7, 0xce, 0x08, 0x98, 0x99, 0x91, 0x04, 0x75, 0xfb, 0x52, 0x0e, 0x32, 0x8b, - 0xab, 0xfd, 0x91, 0x41, 0x5b, 0x73, 0x8d, 0x07, 0xef, 0xa2, 0x5c, 0x0c, 0x52, 0x19, 0x26, 0x45, - 0x8b, 0xb5, 0x48, 0x82, 0xc0, 0x36, 0xca, 0x7b, 0x42, 0x2a, 0x70, 0x3a, 0x6a, 0xfb, 0xf4, 0xcb, - 0x76, 0x1c, 0x3b, 0x88, 0xc6, 0x88, 0x77, 0x42, 0x4c, 0xe4, 0x8b, 0x99, 0x7a, 0x27, 0x04, 0x96, - 0x48, 0x0f, 0xae, 0xa3, 0x4c, 0xe8, 0x76, 0xd5, 0xbb, 0xf7, 0x40, 0x01, 0x32, 0xad, 0x55, 0xdf, - 0x3c, 0x41, 0x16, 0x8b, 0x70, 0x02, 0x57, 0x56, 0x54, 0x3d, 0x79, 0xc9, 0x22, 0x0e, 0x4f, 0x1a, - 0x51, 0xa5, 0x13, 0x84, 0x78, 0xef, 0x9c, 0xc0, 0x7d, 0x0e, 0x94, 0xb9, 0xbe, 0x37, 0xff, 0xde, - 0x1d, 0x9e, 0x34, 0x94, 0x87, 0xa4, 0x50, 0xf8, 0x10, 0x6d, 0xc5, 0x45, 0x88, 0x89, 0xd1, 0xd3, - 0x77, 0x4f, 0x11, 0xb7, 0xc8, 0xac, 0x9b, 0xcc, 0xe3, 0xf1, 0xc7, 0xa8, 0xc0, 0xc2, 0x76, 0x52, - 0xec, 0x9c, 0xa4, 0x27, 0x77, 0xaa, 0xa9, 0x5d, 0x24, 0x8d, 0xab, 0xfd, 0x6b, 0xa0, 0x9b, 0x27, - 0xfe, 0xd0, 0xed, 0x9c, 0xbf, 0x85, 0x3f, 0xd1, 0x37, 0x28, 0x4b, 0xc3, 0x21, 0xc4, 0x97, 0xe2, - 0xd1, 0xca, 0x97, 0x22, 0xca, 0x90, 0x84, 0x43, 0xd0, 0x27, 0x5c, 0xcc, 0x18, 0x89, 0x04, 0xf1, - 0x3e, 0x42, 0xfe, 0xc8, 0xe5, 0xb2, 0x71, 0xc5, 0x27, 0xf6, 0x9e, 0xcc, 0x23, 0xb1, 0xea, 0x8f, - 0x49, 0x0a, 0x5a, 0xfb, 0xd3, 0x40, 0x28, 0x52, 0x7f, 0x0b, 0x4d, 0xe1, 0x74, 0xb6, 0x29, 0xd8, - 0xd7, 0x5c, 0xff, 0x92, 0xae, 0xf0, 0x22, 0x13, 0x2f, 0x41, 0x94, 0x44, 0x7f, 0x3c, 0x8d, 0x55, - 0x3e, 0x9e, 0x15, 0x94, 0x15, 0xbf, 0xa0, 0xb8, 0x2d, 0xe4, 0x05, 0x52, 0x7c, 0x56, 0x18, 0x89, - 0xec, 0xd8, 0x42, 0x48, 0x0c, 0xe4, 0xd9, 0x8e, 0x2b, 0x5b, 0x14, 0x95, 0x6d, 0x25, 0x56, 0x92, - 0x42, 0x08, 0x41, 0xf1, 0x41, 0x63, 0xe6, 0xba, 0x16, 0x14, 0xff, 0x36, 0x46, 0x22, 0x3b, 0xee, - 0xa7, 0x9b, 0x51, 0x56, 0x16, 0x62, 0x7f, 0xe5, 0x42, 0xcc, 0x76, 0x3f, 0xdd, 0x1d, 0x5e, 0xdb, - 0xc9, 0x2c, 0x84, 0x92, 0x56, 0xc1, 0xcc, 0x9b, 0x3a, 0xf5, 0xa4, 0x97, 0x30, 0x92, 0x42, 0xe0, - 0xcf, 0xd0, 0x96, 0xe7, 0x7b, 0xb1, 0x54, 0x8b, 0x1c, 0x31, 0x73, 0x43, 0x92, 0xee, 0x88, 0x1b, - 0x78, 0x3c, 0xeb, 0x22, 0xf3, 0xd8, 0xb9, 0x33, 0x98, 0x5b, 0xf9, 0x0c, 0xd6, 0xef, 0x5f, 0x5c, - 0x96, 0xd7, 0x5e, 0x5e, 0x96, 0xd7, 0x5e, 0x5d, 0x96, 0xd7, 0x7e, 0x99, 0x96, 0x8d, 0x8b, 0x69, - 0xd9, 0x78, 0x39, 0x2d, 0x1b, 0xaf, 0xa6, 0x65, 0xe3, 0xaf, 0x69, 0xd9, 0xf8, 0xed, 0xef, 0xf2, - 0xda, 0xb7, 0x1b, 0xaa, 0x06, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x5e, 0xf6, 0x8d, 0xaa, 0xac, - 0x0e, 0x00, 0x00, + // 1258 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xd6, 0x71, 0x62, 0x8f, 0x1b, 0xc7, 0x99, 0x56, 0x74, 0x95, 0x83, 0x6d, 0x8c, 0x04, + 0x11, 0xa4, 0xbb, 0x4d, 0x28, 0x24, 0x42, 0x02, 0x14, 0xab, 0x15, 0x58, 0x4a, 0x43, 0x34, 0x8e, + 0x2b, 0x04, 0x1c, 0x58, 0xdb, 0x2f, 0xf6, 0x62, 0x7b, 0x77, 0xd9, 0x99, 0x35, 0xca, 0x8d, 0x2f, + 0x80, 0xc4, 0x9d, 0x6f, 0xc1, 0x07, 0xa8, 0x38, 0xe6, 0xd8, 0x63, 0x4f, 0x16, 0x31, 0xdf, 0x22, + 0x02, 0x09, 0xcd, 0x9f, 0xdd, 0x59, 0x3b, 0xb5, 0x70, 0x38, 0xf4, 0xb6, 0xf3, 0xde, 0xef, 0xfd, + 0xde, 0x9b, 0xb7, 0xef, 0xcf, 0xa0, 0xd3, 0xc1, 0x21, 0xb5, 0x5c, 0xdf, 0x1e, 0x44, 0x6d, 0x08, + 0x3d, 0x60, 0x40, 0xed, 0x31, 0x78, 0x5d, 0x3f, 0xb4, 0x95, 0xc2, 0x09, 0x5c, 0x0a, 0xe1, 0x18, + 0x42, 0x3b, 0x18, 0xf4, 0xc4, 0xc9, 0x76, 0xa2, 0xae, 0xcb, 0xec, 0xf1, 0x5e, 0x1b, 0x98, 0xb3, + 0x67, 0xf7, 0xc0, 0x83, 0xd0, 0x61, 0xd0, 0xb5, 0x82, 0xd0, 0x67, 0x3e, 0x7e, 0x4f, 0x1a, 0x5a, + 0x89, 0xa1, 0x15, 0x0c, 0x7a, 0xe2, 0x64, 0x09, 0x43, 0x4b, 0x19, 0x6e, 0x3f, 0xec, 0xb9, 0xac, + 0x1f, 0xb5, 0xad, 0x8e, 0x3f, 0xb2, 0x7b, 0x7e, 0xcf, 0xb7, 0x85, 0x7d, 0x3b, 0x3a, 0x17, 0x27, + 0x71, 0x10, 0x5f, 0x92, 0x77, 0x7b, 0x57, 0x07, 0x64, 0x3b, 0x11, 0xeb, 0x83, 0xc7, 0xdc, 0x8e, + 0xc3, 0x5c, 0xdf, 0xb3, 0xc7, 0x37, 0xa2, 0xd8, 0x7e, 0xac, 0xd1, 0x23, 0xa7, 0xd3, 0x77, 0x3d, + 0x08, 0x2f, 0xf4, 0x0d, 0x46, 0xc0, 0x9c, 0xd7, 0x59, 0xd9, 0x8b, 0xac, 0xc2, 0xc8, 0x63, 0xee, + 0x08, 0x6e, 0x18, 0x7c, 0xfc, 0x5f, 0x06, 0xb4, 0xd3, 0x87, 0x91, 0x33, 0x6f, 0x57, 0xfb, 0xbb, + 0x80, 0xb2, 0x4f, 0xc7, 0xe0, 0x31, 0xfc, 0x3d, 0xca, 0xf1, 0x68, 0xba, 0x0e, 0x73, 0x4c, 0xa3, + 0x6a, 0xec, 0x14, 0xf6, 0x1f, 0x59, 0x3a, 0x83, 0x09, 0xa9, 0x4e, 0x22, 0x47, 0x5b, 0xe3, 0x3d, + 0xeb, 0xab, 0xf6, 0x0f, 0xd0, 0x61, 0xcf, 0x80, 0x39, 0x75, 0x7c, 0x39, 0xa9, 0xac, 0x4c, 0x27, + 0x15, 0xa4, 0x65, 0x24, 0x61, 0xc5, 0xbb, 0x28, 0x3b, 0x84, 0x31, 0x0c, 0xcd, 0x3b, 0x55, 0x63, + 0x27, 0x5f, 0x7f, 0x4b, 0x81, 0xb3, 0xc7, 0x5c, 0x78, 0x1d, 0x7f, 0x10, 0x09, 0xc2, 0xdf, 0xa2, + 0x3c, 0x0f, 0x9c, 0x32, 0x67, 0x14, 0x98, 0x19, 0x11, 0xd0, 0xfb, 0xcb, 0x05, 0x74, 0xe6, 0x8e, + 0xa0, 0xbe, 0xa5, 0xd8, 0xf3, 0x67, 0x31, 0x09, 0xd1, 0x7c, 0xf8, 0x04, 0xad, 0x8b, 0x1a, 0x68, + 0x3c, 0x31, 0x57, 0x45, 0x30, 0x8f, 0x15, 0x7c, 0xfd, 0x48, 0x8a, 0xaf, 0x27, 0x95, 0xb7, 0x17, + 0xa5, 0x94, 0x5d, 0x04, 0x40, 0xad, 0x56, 0xe3, 0x09, 0x89, 0x49, 0xf8, 0xd5, 0x28, 0x73, 0x7a, + 0x60, 0x66, 0x67, 0xaf, 0xd6, 0xe4, 0xc2, 0xeb, 0xf8, 0x83, 0x48, 0x10, 0xde, 0x47, 0x28, 0x84, + 0x1f, 0x23, 0xa0, 0xac, 0x45, 0x1a, 0xe6, 0x9a, 0x30, 0x49, 0x52, 0x47, 0x12, 0x0d, 0x49, 0xa1, + 0x70, 0x15, 0xad, 0x8e, 0x21, 0x6c, 0x9b, 0xeb, 0x02, 0x7d, 0x57, 0xa1, 0x57, 0x9f, 0x43, 0xd8, + 0x26, 0x42, 0x83, 0xbf, 0x44, 0xab, 0x11, 0x85, 0xd0, 0xcc, 0x89, 0x5c, 0xbd, 0x9b, 0xca, 0x95, + 0x35, 0x5b, 0xa6, 0x3c, 0x47, 0x2d, 0x0a, 0x61, 0xc3, 0x3b, 0xf7, 0x35, 0x13, 0x97, 0x10, 0xc1, + 0x80, 0xfb, 0xa8, 0xe4, 0x8e, 0x02, 0x08, 0xa9, 0xef, 0xf1, 0x52, 0xe1, 0x1a, 0x33, 0x7f, 0x2b, + 0xd6, 0xfb, 0xd3, 0x49, 0xa5, 0xd4, 0x98, 0xe3, 0x20, 0x37, 0x58, 0xf1, 0x07, 0x28, 0x4f, 0xfd, + 0x28, 0xec, 0x40, 0xe3, 0x94, 0x9a, 0xa8, 0x9a, 0xd9, 0xc9, 0xd7, 0x37, 0xf8, 0x4f, 0x6b, 0xc6, + 0x42, 0xa2, 0xf5, 0x18, 0x50, 0xde, 0x17, 0x75, 0x45, 0xe0, 0xdc, 0x2c, 0x88, 0x78, 0x0e, 0xad, + 0x25, 0x9b, 0x5c, 0x55, 0x29, 0x81, 0x73, 0x08, 0xc1, 0xeb, 0x80, 0x74, 0x93, 0x08, 0x89, 0x66, + 0xc6, 0x7d, 0x54, 0x0c, 0x81, 0x06, 0xbe, 0x47, 0xa1, 0xc9, 0x1c, 0x16, 0x51, 0xf3, 0xae, 0xf0, + 0xb5, 0xbb, 0x5c, 0xf5, 0x49, 0x9b, 0x3a, 0x9e, 0x4e, 0x2a, 0x45, 0x32, 0xc3, 0x43, 0xe6, 0x78, + 0xb1, 0x83, 0x36, 0xd4, 0x1f, 0x96, 0x81, 0x98, 0x1b, 0xc2, 0xd1, 0xce, 0x42, 0x47, 0xaa, 0x99, + 0xad, 0x96, 0x37, 0xf0, 0xfc, 0x9f, 0xbc, 0xfa, 0xd6, 0x74, 0x52, 0xd9, 0x20, 0x69, 0x0a, 0x32, + 0xcb, 0x88, 0xbb, 0xfa, 0x32, 0xca, 0x47, 0xf1, 0x96, 0x3e, 0x66, 0x2e, 0xa2, 0x9c, 0xcc, 0x71, + 0xe2, 0x5f, 0x0c, 0x64, 0x2a, 0xbf, 0x04, 0x3a, 0xe0, 0x8e, 0xa1, 0x9b, 0xb4, 0x9d, 0xb9, 0x29, + 0x1c, 0xda, 0xcb, 0x65, 0xef, 0x99, 0xdb, 0x09, 0x7d, 0xd1, 0xc0, 0x55, 0x55, 0x98, 0x26, 0x59, + 0x40, 0x4c, 0x16, 0xba, 0xc4, 0x3e, 0x2a, 0x8a, 0x4e, 0xd3, 0x41, 0x94, 0xfe, 0x5f, 0x10, 0x71, + 0x23, 0x17, 0x9b, 0x33, 0x74, 0x64, 0x8e, 0x1e, 0x8f, 0x51, 0xc1, 0xf1, 0x3c, 0x9f, 0x89, 0x4e, + 0xa0, 0xe6, 0x56, 0x35, 0xb3, 0x53, 0xd8, 0xff, 0x7c, 0xe9, 0xe2, 0x14, 0x13, 0xd8, 0x3a, 0xd2, + 0x0c, 0x4f, 0x3d, 0x16, 0x5e, 0xd4, 0xef, 0x29, 0xef, 0x85, 0x94, 0x86, 0xa4, 0x1d, 0x6d, 0x7f, + 0x86, 0x4a, 0xf3, 0x56, 0xb8, 0x84, 0x32, 0x03, 0xb8, 0x10, 0x33, 0x3c, 0x4f, 0xf8, 0x27, 0xbe, + 0x8f, 0xb2, 0x63, 0x67, 0x18, 0x81, 0x1c, 0xbc, 0x44, 0x1e, 0x3e, 0xb9, 0x73, 0x68, 0xd4, 0x5e, + 0x18, 0x28, 0x2f, 0x9c, 0x1f, 0xbb, 0x94, 0xe1, 0xef, 0x6e, 0xac, 0x00, 0x6b, 0xb9, 0x84, 0x71, + 0x6b, 0xb1, 0x00, 0x4a, 0x2a, 0xe2, 0x5c, 0x2c, 0x49, 0x8d, 0xff, 0x26, 0xca, 0xba, 0x0c, 0x46, + 0xd4, 0xbc, 0x23, 0xb2, 0x63, 0xdd, 0x2e, 0x3b, 0xf5, 0x8d, 0x78, 0xa6, 0x36, 0x38, 0x09, 0x91, + 0x5c, 0xb5, 0xdf, 0x0c, 0x54, 0xfc, 0x22, 0xf4, 0xa3, 0x80, 0x80, 0x1c, 0x14, 0x14, 0xbf, 0x83, + 0xb2, 0x3d, 0x2e, 0x91, 0x19, 0xd0, 0x76, 0x12, 0x26, 0x75, 0x7c, 0xf0, 0x84, 0xb1, 0x85, 0x08, + 0x48, 0x0d, 0x9e, 0x84, 0x86, 0x68, 0x3d, 0x3e, 0xe0, 0x7d, 0x2a, 0x0f, 0x27, 0xce, 0x08, 0xa8, + 0x99, 0x11, 0x06, 0xaa, 0xfb, 0x52, 0x0a, 0x32, 0x8b, 0xab, 0xfd, 0x9e, 0x41, 0x9b, 0x73, 0x83, + 0x07, 0xef, 0xa2, 0x5c, 0x0c, 0x52, 0x11, 0x26, 0x49, 0x8b, 0xb9, 0x48, 0x82, 0xc0, 0x36, 0xca, + 0x7b, 0x9c, 0x2a, 0x70, 0x3a, 0xea, 0xf7, 0xe9, 0xcd, 0x76, 0x12, 0x2b, 0x88, 0xc6, 0xf0, 0x3d, + 0xc1, 0x0f, 0x62, 0x63, 0xa6, 0xf6, 0x04, 0xc7, 0x12, 0xa1, 0xc1, 0x75, 0x94, 0x89, 0xdc, 0xae, + 0xda, 0x7b, 0x8f, 0x14, 0x20, 0xd3, 0x5a, 0x76, 0xe7, 0x71, 0x63, 0x7e, 0x09, 0x27, 0x70, 0x45, + 0x46, 0xd5, 0xca, 0x4b, 0x2e, 0x71, 0x74, 0xda, 0x90, 0x99, 0x4e, 0x10, 0x7c, 0xdf, 0x39, 0x81, + 0xfb, 0x1c, 0x42, 0xea, 0xfa, 0xde, 0xfc, 0xbe, 0x3b, 0x3a, 0x6d, 0x28, 0x0d, 0x49, 0xa1, 0xf0, + 0x11, 0xda, 0x8c, 0x93, 0x10, 0x1b, 0xca, 0xd5, 0xf7, 0x40, 0x19, 0x6e, 0x92, 0x59, 0x35, 0x99, + 0xc7, 0xe3, 0x8f, 0x50, 0x81, 0x46, 0xed, 0x24, 0xd9, 0x39, 0x61, 0x9e, 0xf4, 0x54, 0x53, 0xab, + 0x48, 0x1a, 0x57, 0xfb, 0xc7, 0x40, 0x6b, 0xa7, 0xfe, 0xd0, 0xed, 0x5c, 0xbc, 0x81, 0x37, 0xd1, + 0xd7, 0x28, 0x1b, 0x46, 0x43, 0x88, 0x9b, 0xe2, 0xc3, 0xa5, 0x9b, 0x42, 0x46, 0x48, 0xa2, 0x21, + 0xe8, 0x0a, 0xe7, 0x27, 0x4a, 0x24, 0x21, 0x3e, 0x40, 0xc8, 0x1f, 0xb9, 0x4c, 0x0c, 0xae, 0xb8, + 0x62, 0x1f, 0x88, 0x38, 0x12, 0xa9, 0x7e, 0x98, 0xa4, 0xa0, 0xb5, 0x3f, 0x0c, 0x84, 0x24, 0xfb, + 0x1b, 0x18, 0x0a, 0x67, 0xb3, 0x43, 0xc1, 0xbe, 0xe5, 0xfd, 0x17, 0x4c, 0x85, 0x17, 0x99, 0xf8, + 0x0a, 0x3c, 0x25, 0xfa, 0xe1, 0x69, 0x2c, 0xf3, 0xf0, 0xac, 0xa0, 0x2c, 0x7f, 0x05, 0xc5, 0x63, + 0x21, 0xcf, 0x91, 0xfc, 0xb1, 0x42, 0x89, 0x94, 0x63, 0x0b, 0x21, 0xfe, 0x21, 0x6a, 0x3b, 0xce, + 0x6c, 0x91, 0x67, 0xb6, 0x95, 0x48, 0x49, 0x0a, 0xc1, 0x09, 0xf9, 0x03, 0x8d, 0x9a, 0xab, 0x9a, + 0x90, 0xbf, 0xdb, 0x28, 0x91, 0x72, 0xdc, 0x4f, 0x0f, 0xa3, 0xac, 0x48, 0xc4, 0xc1, 0xd2, 0x89, + 0x98, 0x9d, 0x7e, 0x7a, 0x3a, 0xbc, 0x76, 0x92, 0x59, 0x08, 0x25, 0xa3, 0x82, 0x9a, 0x6b, 0x3a, + 0xf4, 0x64, 0x96, 0x50, 0x92, 0x42, 0xe0, 0x4f, 0xd1, 0xa6, 0xe7, 0x7b, 0x31, 0x55, 0x8b, 0x1c, + 0x53, 0x73, 0x5d, 0x18, 0xdd, 0xe3, 0x1d, 0x78, 0x32, 0xab, 0x22, 0xf3, 0xd8, 0xb9, 0x1a, 0xcc, + 0x2d, 0x5d, 0x83, 0xf5, 0x87, 0x97, 0x57, 0xe5, 0x95, 0x97, 0x57, 0xe5, 0x95, 0x57, 0x57, 0xe5, + 0x95, 0x9f, 0xa7, 0x65, 0xe3, 0x72, 0x5a, 0x36, 0x5e, 0x4e, 0xcb, 0xc6, 0xab, 0x69, 0xd9, 0xf8, + 0x73, 0x5a, 0x36, 0x7e, 0xfd, 0xab, 0xbc, 0xf2, 0xcd, 0xba, 0xca, 0xc1, 0xbf, 0x01, 0x00, 0x00, + 0xff, 0xff, 0x8e, 0x08, 0x0c, 0xa0, 0x3d, 0x0e, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/generated.proto index fcbf669ae..020fe8eab 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,8 +25,6 @@ import "k8s.io/api/authentication/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; -import "k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.conversion.go index 01e5d4a9d..6df889a6b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.deepcopy.go index e85589758..5ed9a99db 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.defaults.go index 544e569dc..73e63fc11 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/v1beta1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/zz_generated.deepcopy.go index 521b96a9b..f0f672257 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/audit/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/install/BUILD index 011bc1dff..a30a0ec94 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/install/BUILD @@ -11,9 +11,8 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/apiserver/pkg/apis/example/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/example:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/example/v1:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/install/install.go index 5352108e7..77cceff36 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/apis/example" examplev1 "k8s.io/apiserver/pkg/apis/example/v1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: example.GroupName, - VersionPreferenceOrder: []string{examplev1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: example.AddToScheme, - }, - announced.VersionToSchemeFunc{ - examplev1.SchemeGroupVersion.Version: examplev1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(example.AddToScheme(scheme)) + utilruntime.Must(examplev1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(examplev1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/generated.pb.go index d0055ba03..b2f517e55 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1938,72 +1938,71 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 1065 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xcd, 0x6e, 0xdb, 0x46, - 0x10, 0xb6, 0x2c, 0xcb, 0x92, 0xd6, 0x56, 0x62, 0x6f, 0x62, 0x80, 0x31, 0x10, 0xc9, 0x71, 0x0b, - 0xc3, 0x29, 0x1a, 0xb2, 0x76, 0xd3, 0x22, 0x6d, 0x0f, 0x41, 0x68, 0x17, 0xb5, 0x0b, 0xff, 0x10, - 0x2b, 0x03, 0x01, 0x8a, 0x1e, 0xba, 0x22, 0x27, 0x32, 0x2b, 0x91, 0x4b, 0xec, 0xae, 0xd4, 0xea, - 0xd6, 0x47, 0x68, 0x1f, 0xa0, 0x4f, 0xd1, 0x43, 0x81, 0x3e, 0x81, 0x8f, 0x39, 0xe6, 0x24, 0xd4, - 0xea, 0x5b, 0xf8, 0x54, 0xec, 0xf2, 0x47, 0xa2, 0xe5, 0x38, 0xf2, 0x6d, 0x77, 0xe6, 0xfb, 0xbe, - 0x19, 0xee, 0x0c, 0x67, 0xd0, 0x71, 0xe7, 0x85, 0x30, 0x7d, 0x66, 0x75, 0x7a, 0x2d, 0xe0, 0x21, - 0x48, 0x10, 0x56, 0x1f, 0x42, 0x8f, 0x71, 0x2b, 0x71, 0xd0, 0xc8, 0x17, 0xc0, 0xfb, 0xc0, 0xad, - 0xa8, 0xd3, 0xd6, 0x37, 0x0b, 0x7e, 0xa5, 0x41, 0xd4, 0x05, 0xab, 0xbf, 0x63, 0xb5, 0x21, 0x04, - 0x4e, 0x25, 0x78, 0x66, 0xc4, 0x99, 0x64, 0xf8, 0xe3, 0x98, 0x65, 0x66, 0x2c, 0x33, 0xea, 0xb4, - 0xf5, 0xcd, 0x4c, 0x58, 0x66, 0x7f, 0x67, 0xfd, 0x59, 0xdb, 0x97, 0xe7, 0xbd, 0x96, 0xe9, 0xb2, - 0xc0, 0x6a, 0xb3, 0x36, 0xb3, 0x34, 0xb9, 0xd5, 0x7b, 0xa3, 0x6f, 0xfa, 0xa2, 0x4f, 0xb1, 0xe8, - 0xfa, 0xf3, 0x71, 0x2a, 0x01, 0x75, 0xcf, 0xfd, 0x10, 0xf8, 0x60, 0x9c, 0x4d, 0x00, 0x92, 0xde, - 0x90, 0xca, 0xba, 0xf5, 0x3e, 0x16, 0xef, 0x85, 0xd2, 0x0f, 0x60, 0x8a, 0xf0, 0xe5, 0x87, 0x08, - 0xc2, 0x3d, 0x87, 0x80, 0x4e, 0xf1, 0x3e, 0x7f, 0x1f, 0xaf, 0x27, 0xfd, 0xae, 0xe5, 0x87, 0x52, - 0x48, 0x7e, 0x9d, 0xb4, 0xf9, 0xc7, 0x3c, 0x2a, 0x3a, 0xcc, 0xc3, 0x3f, 0xa1, 0x8a, 0xfa, 0x00, - 0x8f, 0x4a, 0x6a, 0x14, 0x36, 0x0a, 0xdb, 0x4b, 0xbb, 0x9f, 0x99, 0xe3, 0x37, 0xcc, 0xf4, 0xc6, - 0xcf, 0xa8, 0xd0, 0x66, 0x7f, 0xc7, 0x3c, 0x6d, 0xfd, 0x0c, 0xae, 0x3c, 0x06, 0x49, 0x6d, 0x7c, - 0x31, 0x6c, 0xcc, 0x8d, 0x86, 0x0d, 0x34, 0xb6, 0x91, 0x4c, 0x15, 0x9f, 0xa2, 0x05, 0x11, 0x81, - 0x6b, 0xcc, 0x6b, 0xf5, 0x67, 0xe6, 0x2c, 0x15, 0x32, 0x1d, 0xe6, 0x35, 0x23, 0x70, 0xed, 0xe5, - 0x44, 0x7a, 0x41, 0xdd, 0x88, 0x16, 0xc2, 0xaf, 0xd1, 0xa2, 0x90, 0x54, 0xf6, 0x84, 0x51, 0xd4, - 0x92, 0xd6, 0xec, 0x92, 0x9a, 0x66, 0xdf, 0x4b, 0x44, 0x17, 0xe3, 0x3b, 0x49, 0xe4, 0x36, 0xff, - 0x2a, 0xa2, 0x65, 0x87, 0x79, 0x7b, 0x2c, 0xf4, 0x7c, 0xe9, 0xb3, 0x10, 0x3f, 0x47, 0x0b, 0x72, - 0x10, 0x81, 0x7e, 0x98, 0xaa, 0xbd, 0x91, 0xe6, 0x72, 0x36, 0x88, 0xe0, 0x6a, 0xd8, 0x58, 0x99, - 0xc4, 0x2a, 0x1b, 0xd1, 0x68, 0xfc, 0x55, 0x96, 0xdf, 0xbc, 0xe6, 0x3d, 0xc9, 0x87, 0xbb, 0x1a, - 0x36, 0xee, 0x67, 0xb4, 0x7c, 0x06, 0xb8, 0x8d, 0x6a, 0x5d, 0x2a, 0xa4, 0xc3, 0x59, 0x0b, 0xce, - 0xfc, 0x00, 0x92, 0x2f, 0xfc, 0x64, 0xb6, 0x92, 0x28, 0x86, 0xbd, 0x96, 0x44, 0xab, 0x1d, 0x4d, - 0x0a, 0x91, 0xbc, 0x2e, 0xee, 0x23, 0xac, 0x0c, 0x67, 0x9c, 0x86, 0x22, 0xce, 0x5f, 0x45, 0x5b, - 0xb8, 0x73, 0xb4, 0xf5, 0x24, 0x1a, 0x3e, 0x9a, 0x52, 0x23, 0x37, 0x44, 0xc0, 0x5b, 0x68, 0x91, - 0x03, 0x15, 0x2c, 0x34, 0x4a, 0xfa, 0x6d, 0xb2, 0x52, 0x10, 0x6d, 0x25, 0x89, 0x17, 0x3f, 0x45, - 0xe5, 0x00, 0x84, 0xa0, 0x6d, 0x30, 0x16, 0x35, 0xf0, 0x7e, 0x02, 0x2c, 0x1f, 0xc7, 0x66, 0x92, - 0xfa, 0x37, 0xff, 0x2e, 0xa0, 0xb2, 0xc3, 0xbc, 0x23, 0x5f, 0x48, 0xfc, 0xe3, 0x54, 0x37, 0x9b, - 0xb3, 0x7d, 0x8c, 0x62, 0xeb, 0x5e, 0x5e, 0x49, 0xe2, 0x54, 0x52, 0xcb, 0x44, 0x27, 0x9f, 0xa0, - 0x92, 0x2f, 0x21, 0x50, 0x75, 0x2d, 0x6e, 0x2f, 0xed, 0x3e, 0x9d, 0xb9, 0xef, 0xec, 0x5a, 0xa2, - 0x5a, 0x3a, 0x54, 0x7c, 0x12, 0xcb, 0x6c, 0xfe, 0x53, 0xd6, 0x99, 0xab, 0xd6, 0xc6, 0x47, 0xa8, - 0xc6, 0x41, 0x48, 0xca, 0xa5, 0xc3, 0xba, 0xbe, 0x3b, 0xd0, 0x95, 0xaf, 0xda, 0x5b, 0x69, 0x35, - 0xc9, 0xa4, 0xf3, 0xea, 0xba, 0x81, 0xe4, 0xc9, 0xb8, 0x8d, 0x1e, 0x4b, 0xe0, 0x81, 0x1f, 0x52, - 0xf5, 0xf2, 0xdf, 0x71, 0xea, 0x82, 0x03, 0xdc, 0x67, 0x5e, 0x13, 0x5c, 0x16, 0x7a, 0x42, 0x57, - 0xba, 0x68, 0x3f, 0x19, 0x0d, 0x1b, 0x8f, 0xcf, 0x6e, 0x03, 0x92, 0xdb, 0x75, 0xf0, 0x29, 0x5a, - 0xa3, 0xae, 0xf4, 0xfb, 0xb0, 0x0f, 0xd4, 0xeb, 0xfa, 0x21, 0xa4, 0x01, 0x4a, 0x3a, 0xc0, 0xa3, - 0xd1, 0xb0, 0xb1, 0xf6, 0xea, 0x26, 0x00, 0xb9, 0x99, 0x87, 0x07, 0x68, 0x39, 0x64, 0x1e, 0x34, - 0xa1, 0x0b, 0xae, 0x64, 0xdc, 0x28, 0xeb, 0xa7, 0x7e, 0x79, 0xa7, 0xa9, 0x61, 0x9e, 0x4c, 0x28, - 0x7c, 0x1b, 0x4a, 0x3e, 0xb0, 0x1f, 0x26, 0xef, 0xb8, 0x3c, 0xe9, 0x22, 0xb9, 0x50, 0xf8, 0x7b, - 0x84, 0x95, 0xb6, 0xef, 0xc2, 0x2b, 0xd7, 0x65, 0xbd, 0x50, 0x9e, 0xd0, 0x00, 0x8c, 0x8a, 0xae, - 0x43, 0xd6, 0xe7, 0xcd, 0x29, 0x04, 0xb9, 0x81, 0x85, 0x0f, 0xd0, 0xbd, 0xbc, 0xd5, 0xa8, 0xe6, - 0x66, 0x88, 0xb1, 0x0f, 0x11, 0x07, 0x57, 0x0d, 0xe4, 0xbc, 0x22, 0xb9, 0xc6, 0xc3, 0x9f, 0xa2, - 0x8a, 0xca, 0x52, 0xe7, 0x82, 0xb4, 0x46, 0xd6, 0xa2, 0x27, 0x89, 0x9d, 0x64, 0x08, 0xfc, 0x05, - 0x5a, 0x3a, 0x67, 0x42, 0x9e, 0x80, 0xfc, 0x85, 0xf1, 0x8e, 0xb1, 0xb4, 0x51, 0xd8, 0xae, 0xd8, - 0x0f, 0x12, 0xc2, 0xd2, 0xc1, 0xd8, 0x45, 0x26, 0x71, 0xea, 0x77, 0x53, 0x57, 0xe7, 0x70, 0xdf, - 0x58, 0xd6, 0x94, 0xec, 0x77, 0x3b, 0x88, 0xcd, 0x24, 0xf5, 0xa7, 0xd0, 0x43, 0x67, 0xcf, 0xa8, - 0x4d, 0x43, 0x0f, 0x9d, 0x3d, 0x92, 0xfa, 0x55, 0xea, 0xea, 0x18, 0xaa, 0xd4, 0x57, 0xf2, 0xa9, - 0x1f, 0x24, 0x76, 0x92, 0x21, 0xb0, 0x85, 0xaa, 0xa2, 0xd7, 0xf2, 0x58, 0x40, 0xfd, 0xd0, 0x58, - 0xd5, 0xf0, 0xd5, 0x04, 0x5e, 0x6d, 0xa6, 0x0e, 0x32, 0xc6, 0xe0, 0x6f, 0x50, 0x4d, 0x6d, 0x44, - 0xaf, 0xd7, 0x05, 0xae, 0x63, 0x3c, 0xd0, 0xa4, 0x6c, 0x00, 0x36, 0x53, 0xa7, 0x7e, 0xa3, 0x3c, - 0x76, 0xfd, 0x25, 0x5a, 0x9d, 0xea, 0x12, 0xbc, 0x82, 0x8a, 0x1d, 0x18, 0xc4, 0xe3, 0x9e, 0xa8, - 0x23, 0x7e, 0x88, 0x4a, 0x7d, 0xda, 0xed, 0x41, 0x3c, 0xca, 0x49, 0x7c, 0xf9, 0x7a, 0xfe, 0x45, - 0x61, 0xf3, 0xcf, 0x22, 0xaa, 0x66, 0x2b, 0x05, 0x5b, 0xa8, 0x14, 0x9d, 0x53, 0x91, 0xae, 0x8a, - 0x47, 0xe9, 0xff, 0xee, 0x28, 0xe3, 0xd5, 0xb0, 0x51, 0x71, 0x98, 0xa7, 0xcf, 0x24, 0xc6, 0xe1, - 0x37, 0x08, 0xb9, 0xe9, 0x12, 0x48, 0x07, 0xca, 0xee, 0xcc, 0x5d, 0x9e, 0xed, 0x8f, 0xf1, 0xee, - 0xcd, 0x4c, 0x82, 0x4c, 0x28, 0x4f, 0x0e, 0xd2, 0xe2, 0xed, 0x83, 0x74, 0x62, 0x36, 0x2f, 0xdc, - 0x3a, 0x9b, 0xb7, 0xd0, 0x62, 0x5c, 0xe1, 0xeb, 0x33, 0x3c, 0x6e, 0x00, 0x92, 0x78, 0xf1, 0x47, - 0xa8, 0x14, 0x31, 0xef, 0xd0, 0x49, 0x26, 0x78, 0x36, 0x03, 0x1d, 0x65, 0x24, 0xb1, 0x0f, 0xbf, - 0x46, 0x55, 0x3d, 0xb8, 0xf4, 0xfe, 0x29, 0xdf, 0x79, 0xff, 0xd4, 0x74, 0x77, 0xa4, 0x02, 0x64, - 0xac, 0x65, 0x6f, 0x5f, 0x5c, 0xd6, 0xe7, 0xde, 0x5e, 0xd6, 0xe7, 0xde, 0x5d, 0xd6, 0xe7, 0x7e, - 0x1b, 0xd5, 0x0b, 0x17, 0xa3, 0x7a, 0xe1, 0xed, 0xa8, 0x5e, 0x78, 0x37, 0xaa, 0x17, 0xfe, 0x1d, - 0xd5, 0x0b, 0xbf, 0xff, 0x57, 0x9f, 0xfb, 0x61, 0xbe, 0xbf, 0xf3, 0x7f, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x55, 0x69, 0xbd, 0x27, 0x83, 0x0a, 0x00, 0x00, + // 1052 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xcf, 0x6e, 0xdb, 0xc6, + 0x13, 0x36, 0x2d, 0xcb, 0x92, 0xd6, 0x56, 0x62, 0x6f, 0x62, 0x80, 0x31, 0x10, 0xc9, 0xf1, 0xef, + 0x07, 0xc3, 0x29, 0x1a, 0xb2, 0x36, 0xd2, 0x22, 0x6d, 0x0f, 0x41, 0x68, 0x17, 0xb5, 0x0b, 0xff, + 0x21, 0x56, 0x06, 0x02, 0x14, 0x3d, 0x74, 0x45, 0x4e, 0x64, 0x56, 0x22, 0x97, 0x58, 0xae, 0xd4, + 0xea, 0xd6, 0x47, 0x68, 0x1f, 0xa0, 0x4f, 0xd1, 0x43, 0x81, 0x3e, 0x81, 0x8f, 0x39, 0xe6, 0x24, + 0xd4, 0xea, 0x5b, 0xf8, 0x54, 0xec, 0xf2, 0x8f, 0x48, 0x4b, 0x75, 0xe5, 0xdb, 0xee, 0xcc, 0xf7, + 0x7d, 0x33, 0x9c, 0x1d, 0xce, 0xa0, 0xd3, 0xee, 0xab, 0xc8, 0xf0, 0x98, 0xd9, 0xed, 0xb7, 0x81, + 0x07, 0x20, 0x20, 0x32, 0x07, 0x10, 0xb8, 0x8c, 0x9b, 0x89, 0x83, 0x86, 0x5e, 0x04, 0x7c, 0x00, + 0xdc, 0x0c, 0xbb, 0x1d, 0x75, 0x33, 0xe1, 0x27, 0xea, 0x87, 0x3d, 0x30, 0x07, 0x7b, 0x66, 0x07, + 0x02, 0xe0, 0x54, 0x80, 0x6b, 0x84, 0x9c, 0x09, 0x86, 0xff, 0x1f, 0xb3, 0x8c, 0x8c, 0x65, 0x84, + 0xdd, 0x8e, 0xba, 0x19, 0x09, 0xcb, 0x18, 0xec, 0x6d, 0xbe, 0xe8, 0x78, 0xe2, 0xb2, 0xdf, 0x36, + 0x1c, 0xe6, 0x9b, 0x1d, 0xd6, 0x61, 0xa6, 0x22, 0xb7, 0xfb, 0xef, 0xd4, 0x4d, 0x5d, 0xd4, 0x29, + 0x16, 0xdd, 0x7c, 0x39, 0x49, 0xc5, 0xa7, 0xce, 0xa5, 0x17, 0x00, 0x1f, 0x4e, 0xb2, 0xf1, 0x41, + 0xd0, 0x19, 0xa9, 0x6c, 0x9a, 0xff, 0xc6, 0xe2, 0xfd, 0x40, 0x78, 0x3e, 0x4c, 0x11, 0x3e, 0xfb, + 0x2f, 0x42, 0xe4, 0x5c, 0x82, 0x4f, 0x6f, 0xf3, 0xb6, 0x7f, 0x5d, 0x44, 0x25, 0x9b, 0xb9, 0xf8, + 0x7b, 0x54, 0x95, 0xb9, 0xb8, 0x54, 0x50, 0x5d, 0xdb, 0xd2, 0x76, 0x57, 0xf6, 0x3f, 0x31, 0x26, + 0xe5, 0xc8, 0x24, 0x27, 0x15, 0x91, 0x68, 0x63, 0xb0, 0x67, 0x9c, 0xb7, 0x7f, 0x00, 0x47, 0x9c, + 0x82, 0xa0, 0x16, 0xbe, 0x1a, 0x35, 0x17, 0xc6, 0xa3, 0x26, 0x9a, 0xd8, 0x48, 0xa6, 0x8a, 0xcf, + 0xd1, 0x52, 0x14, 0x82, 0xa3, 0x2f, 0x2a, 0xf5, 0x17, 0xc6, 0x3c, 0xc5, 0x36, 0x6c, 0xe6, 0xb6, + 0x42, 0x70, 0xac, 0xd5, 0x44, 0x7a, 0x49, 0xde, 0x88, 0x12, 0xc2, 0x6f, 0xd1, 0x72, 0x24, 0xa8, + 0xe8, 0x47, 0x7a, 0x49, 0x49, 0x9a, 0xf3, 0x4b, 0x2a, 0x9a, 0xf5, 0x20, 0x11, 0x5d, 0x8e, 0xef, + 0x24, 0x91, 0xdb, 0xfe, 0xbd, 0x84, 0x56, 0x6d, 0xe6, 0x1e, 0xb0, 0xc0, 0xf5, 0x84, 0xc7, 0x02, + 0xfc, 0x12, 0x2d, 0x89, 0x61, 0x08, 0xaa, 0x30, 0x35, 0x6b, 0x2b, 0xcd, 0xe5, 0x62, 0x18, 0xc2, + 0xcd, 0xa8, 0xb9, 0x96, 0xc7, 0x4a, 0x1b, 0x51, 0x68, 0xfc, 0x79, 0x96, 0xdf, 0xa2, 0xe2, 0x3d, + 0x2b, 0x86, 0xbb, 0x19, 0x35, 0x1f, 0x66, 0xb4, 0x62, 0x06, 0xb8, 0x83, 0xea, 0x3d, 0x1a, 0x09, + 0x9b, 0xb3, 0x36, 0x5c, 0x78, 0x3e, 0x24, 0x5f, 0xf8, 0xd1, 0x7c, 0x4f, 0x22, 0x19, 0xd6, 0x46, + 0x12, 0xad, 0x7e, 0x92, 0x17, 0x22, 0x45, 0x5d, 0x3c, 0x40, 0x58, 0x1a, 0x2e, 0x38, 0x0d, 0xa2, + 0x38, 0x7f, 0x19, 0x6d, 0xe9, 0xde, 0xd1, 0x36, 0x93, 0x68, 0xf8, 0x64, 0x4a, 0x8d, 0xcc, 0x88, + 0x80, 0x77, 0xd0, 0x32, 0x07, 0x1a, 0xb1, 0x40, 0x2f, 0xab, 0xda, 0x64, 0x4f, 0x41, 0x94, 0x95, + 0x24, 0x5e, 0xfc, 0x1c, 0x55, 0x7c, 0x88, 0x22, 0xda, 0x01, 0x7d, 0x59, 0x01, 0x1f, 0x26, 0xc0, + 0xca, 0x69, 0x6c, 0x26, 0xa9, 0x7f, 0xfb, 0x0f, 0x0d, 0x55, 0x6c, 0xe6, 0x9e, 0x78, 0x91, 0xc0, + 0xdf, 0x4d, 0x75, 0xb3, 0x31, 0xdf, 0xc7, 0x48, 0xb6, 0xea, 0xe5, 0xb5, 0x24, 0x4e, 0x35, 0xb5, + 0xe4, 0x3a, 0xf9, 0x0c, 0x95, 0x3d, 0x01, 0xbe, 0x7c, 0xd7, 0xd2, 0xee, 0xca, 0xfe, 0xf3, 0xb9, + 0xfb, 0xce, 0xaa, 0x27, 0xaa, 0xe5, 0x63, 0xc9, 0x27, 0xb1, 0xcc, 0xf6, 0x9f, 0x15, 0x95, 0xb9, + 0x6c, 0x6d, 0x7c, 0x82, 0xea, 0x1c, 0x22, 0x41, 0xb9, 0xb0, 0x59, 0xcf, 0x73, 0x86, 0xea, 0xe5, + 0x6b, 0xd6, 0x4e, 0xfa, 0x9a, 0x24, 0xef, 0xbc, 0xb9, 0x6d, 0x20, 0x45, 0x32, 0xee, 0xa0, 0xa7, + 0x02, 0xb8, 0xef, 0x05, 0x54, 0x56, 0xfe, 0x6b, 0x4e, 0x1d, 0xb0, 0x81, 0x7b, 0xcc, 0x6d, 0x81, + 0xc3, 0x02, 0x37, 0x52, 0x2f, 0x5d, 0xb2, 0x9e, 0x8d, 0x47, 0xcd, 0xa7, 0x17, 0x77, 0x01, 0xc9, + 0xdd, 0x3a, 0xf8, 0x1c, 0x6d, 0x50, 0x47, 0x78, 0x03, 0x38, 0x04, 0xea, 0xf6, 0xbc, 0x00, 0xd2, + 0x00, 0x65, 0x15, 0xe0, 0xc9, 0x78, 0xd4, 0xdc, 0x78, 0x33, 0x0b, 0x40, 0x66, 0xf3, 0xf0, 0x10, + 0xad, 0x06, 0xcc, 0x85, 0x16, 0xf4, 0xc0, 0x11, 0x8c, 0xeb, 0x15, 0x55, 0xea, 0xd7, 0xf7, 0x9a, + 0x1a, 0xc6, 0x59, 0x4e, 0xe1, 0xab, 0x40, 0xf0, 0xa1, 0xf5, 0x38, 0xa9, 0xe3, 0x6a, 0xde, 0x45, + 0x0a, 0xa1, 0xf0, 0x37, 0x08, 0x4b, 0x6d, 0xcf, 0x81, 0x37, 0x8e, 0xc3, 0xfa, 0x81, 0x38, 0xa3, + 0x3e, 0xe8, 0x55, 0xf5, 0x0e, 0x59, 0x9f, 0xb7, 0xa6, 0x10, 0x64, 0x06, 0x0b, 0x1f, 0xa1, 0x07, + 0x45, 0xab, 0x5e, 0x2b, 0xcc, 0x10, 0xfd, 0x10, 0x42, 0x0e, 0x8e, 0x1c, 0xc8, 0x45, 0x45, 0x72, + 0x8b, 0x87, 0x3f, 0x46, 0x55, 0x99, 0xa5, 0xca, 0x05, 0x29, 0x8d, 0xac, 0x45, 0xcf, 0x12, 0x3b, + 0xc9, 0x10, 0xf8, 0x53, 0xb4, 0x72, 0xc9, 0x22, 0x71, 0x06, 0xe2, 0x47, 0xc6, 0xbb, 0xfa, 0xca, + 0x96, 0xb6, 0x5b, 0xb5, 0x1e, 0x25, 0x84, 0x95, 0xa3, 0x89, 0x8b, 0xe4, 0x71, 0xf2, 0x77, 0x93, + 0x57, 0xfb, 0xf8, 0x50, 0x5f, 0x55, 0x94, 0xec, 0x77, 0x3b, 0x8a, 0xcd, 0x24, 0xf5, 0xa7, 0xd0, + 0x63, 0xfb, 0x40, 0xaf, 0x4f, 0x43, 0x8f, 0xed, 0x03, 0x92, 0xfa, 0x65, 0xea, 0xf2, 0x18, 0xc8, + 0xd4, 0xd7, 0x8a, 0xa9, 0x1f, 0x25, 0x76, 0x92, 0x21, 0xb0, 0x89, 0x6a, 0x51, 0xbf, 0xed, 0x32, + 0x9f, 0x7a, 0x81, 0xbe, 0xae, 0xe0, 0xeb, 0x09, 0xbc, 0xd6, 0x4a, 0x1d, 0x64, 0x82, 0xc1, 0x5f, + 0xa2, 0xba, 0x5c, 0x6e, 0x6e, 0xbf, 0x07, 0x5c, 0xc5, 0x78, 0xa4, 0x48, 0xd9, 0x00, 0x6c, 0xa5, + 0x4e, 0x55, 0xa3, 0x22, 0x76, 0xf3, 0x35, 0x5a, 0x9f, 0xea, 0x12, 0xbc, 0x86, 0x4a, 0x5d, 0x18, + 0xc6, 0xe3, 0x9e, 0xc8, 0x23, 0x7e, 0x8c, 0xca, 0x03, 0xda, 0xeb, 0x43, 0x3c, 0xca, 0x49, 0x7c, + 0xf9, 0x62, 0xf1, 0x95, 0xb6, 0xfd, 0x5b, 0x09, 0xd5, 0xb2, 0x95, 0x82, 0x4d, 0x54, 0x0e, 0x2f, + 0x69, 0x94, 0xae, 0x8a, 0x27, 0xe9, 0xff, 0x6e, 0x4b, 0xe3, 0xcd, 0xa8, 0x59, 0xb5, 0x99, 0xab, + 0xce, 0x24, 0xc6, 0xe1, 0x77, 0x08, 0x39, 0xe9, 0x12, 0x48, 0x07, 0xca, 0xfe, 0xdc, 0x5d, 0x9e, + 0xed, 0x8f, 0xc9, 0xee, 0xcd, 0x4c, 0x11, 0xc9, 0x29, 0xe7, 0x07, 0x69, 0xe9, 0xee, 0x41, 0x9a, + 0x9b, 0xcd, 0x4b, 0x77, 0xce, 0xe6, 0x1d, 0xb4, 0x1c, 0xbf, 0xf0, 0xed, 0x19, 0x1e, 0x37, 0x00, + 0x49, 0xbc, 0xf8, 0x7f, 0xa8, 0x1c, 0x32, 0xf7, 0xd8, 0x4e, 0x26, 0x78, 0x36, 0x03, 0x6d, 0x69, + 0x24, 0xb1, 0x0f, 0xbf, 0x45, 0x35, 0x35, 0xb8, 0xd4, 0xfe, 0xa9, 0xdc, 0x7b, 0xff, 0xd4, 0x55, + 0x77, 0xa4, 0x02, 0x64, 0xa2, 0x65, 0xed, 0x5e, 0x5d, 0x37, 0x16, 0xde, 0x5f, 0x37, 0x16, 0x3e, + 0x5c, 0x37, 0x16, 0x7e, 0x1e, 0x37, 0xb4, 0xab, 0x71, 0x43, 0x7b, 0x3f, 0x6e, 0x68, 0x1f, 0xc6, + 0x0d, 0xed, 0xaf, 0x71, 0x43, 0xfb, 0xe5, 0xef, 0xc6, 0xc2, 0xb7, 0x8b, 0x83, 0xbd, 0x7f, 0x02, + 0x00, 0x00, 0xff, 0xff, 0xdf, 0x7a, 0x1b, 0x54, 0x4e, 0x0a, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/generated.proto index dc78ca40e..821f82537 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.apiserver.pkg.apis.example.v1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.conversion.go index dbdbcabad..94dfbe69e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.deepcopy.go index c8d841365..599fc2a02 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/zz_generated.deepcopy.go index 9ae912746..0aef01200 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/install/BUILD index 2bcdf82d9..b5e80a034 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/install/BUILD @@ -11,11 +11,9 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/apiserver/pkg/apis/example2/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/example:go_default_library", - "//vendor/k8s.io/apiserver/pkg/apis/example2:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/example2/v1:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/install/install.go index 8980ecbef..473895998 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/install/install.go @@ -19,26 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/apis/example" - "k8s.io/apiserver/pkg/apis/example2" example2v1 "k8s.io/apiserver/pkg/apis/example2/v1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: example2.GroupName, - VersionPreferenceOrder: []string{example2v1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: example.AddToScheme, - }, - announced.VersionToSchemeFunc{ - example2v1.SchemeGroupVersion.Version: example2v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(example.AddToScheme(scheme)) + utilruntime.Must(example2v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(example2v1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/generated.pb.go index 310a41f6c..f1b385b1d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -651,32 +651,30 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 421 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xcf, 0x8e, 0xd3, 0x30, - 0x10, 0x87, 0x93, 0xb2, 0xac, 0x2a, 0xb3, 0x5a, 0xad, 0x72, 0xaa, 0x7a, 0x70, 0x51, 0x24, 0xa4, - 0x1e, 0xc0, 0x26, 0xcb, 0x5f, 0x71, 0x42, 0xb9, 0x03, 0x52, 0xf6, 0x80, 0xc4, 0x05, 0x1c, 0x77, - 0x48, 0x4d, 0x9a, 0xd8, 0xb2, 0x9d, 0x08, 0x6e, 0x3c, 0x02, 0x8f, 0xc1, 0xa3, 0xf4, 0xb8, 0xc7, - 0x3d, 0x55, 0x34, 0xbc, 0x08, 0xaa, 0x13, 0x12, 0xb1, 0xed, 0x0a, 0xb8, 0xe5, 0x67, 0xcf, 0xf7, - 0xcd, 0x64, 0x8c, 0x5e, 0xe7, 0xcf, 0x0d, 0x11, 0x92, 0xe6, 0x55, 0x0a, 0xba, 0x04, 0x0b, 0x86, - 0xd6, 0x50, 0x2e, 0xa4, 0xa6, 0xdd, 0x05, 0x53, 0xc2, 0x80, 0xae, 0x41, 0x53, 0x95, 0x67, 0x2e, - 0x51, 0xf8, 0xcc, 0x0a, 0xb5, 0x82, 0x73, 0x5a, 0x47, 0x34, 0x83, 0x12, 0x34, 0xb3, 0xb0, 0x20, - 0x4a, 0x4b, 0x2b, 0x83, 0x7b, 0x2d, 0x46, 0x7a, 0x8c, 0xa8, 0x3c, 0x73, 0x89, 0xfc, 0xc6, 0x48, - 0x1d, 0x4d, 0x1f, 0x64, 0xc2, 0x2e, 0xab, 0x94, 0x70, 0x59, 0xd0, 0x4c, 0x66, 0x92, 0x3a, 0x3a, - 0xad, 0x3e, 0xba, 0xe4, 0x82, 0xfb, 0x6a, 0xad, 0xd3, 0x70, 0x18, 0x86, 0x72, 0xa9, 0xe1, 0x40, - 0xe7, 0xe9, 0xe3, 0xa1, 0xa6, 0x60, 0x7c, 0x29, 0x4a, 0xd0, 0x5f, 0x86, 0x99, 0x0b, 0xb0, 0xec, - 0x10, 0x45, 0x6f, 0xa2, 0x74, 0x55, 0x5a, 0x51, 0xc0, 0x1e, 0xf0, 0xf4, 0x6f, 0x80, 0xe1, 0x4b, - 0x28, 0xd8, 0x1e, 0xf7, 0xe8, 0x26, 0xae, 0xb2, 0x62, 0x45, 0x45, 0x69, 0x8d, 0xd5, 0xd7, 0xa1, - 0xf0, 0xfb, 0x08, 0xa1, 0x04, 0xd4, 0x4a, 0x70, 0x76, 0x01, 0x36, 0xf8, 0x80, 0xc6, 0xbb, 0xff, - 0x58, 0x30, 0xcb, 0x26, 0xfe, 0x5d, 0x7f, 0x7e, 0xe7, 0xfc, 0x21, 0x19, 0xf6, 0xdd, 0x6b, 0x87, - 0x95, 0xef, 0xaa, 0x49, 0x1d, 0x91, 0x37, 0xe9, 0x27, 0xe0, 0xf6, 0x15, 0x58, 0x16, 0x07, 0xeb, - 0xcd, 0xcc, 0x6b, 0x36, 0x33, 0x34, 0x9c, 0x25, 0xbd, 0x35, 0x78, 0x8b, 0x8e, 0x8c, 0x02, 0x3e, - 0x19, 0x39, 0xfb, 0x13, 0xf2, 0x4f, 0xaf, 0x49, 0x86, 0x11, 0x2f, 0x14, 0xf0, 0xf8, 0xa4, 0x6b, - 0x71, 0xb4, 0x4b, 0x89, 0x13, 0x06, 0xef, 0xd1, 0xb1, 0xb1, 0xcc, 0x56, 0x66, 0x72, 0xcb, 0xa9, - 0x9f, 0xfd, 0xbf, 0xda, 0xe1, 0xf1, 0x69, 0x27, 0x3f, 0x6e, 0x73, 0xd2, 0x69, 0xc3, 0x17, 0xe8, - 0xf4, 0xcf, 0x31, 0x82, 0x39, 0x1a, 0xeb, 0xf6, 0xc4, 0xb8, 0x6d, 0xdd, 0x8e, 0x4f, 0x9a, 0xcd, - 0x6c, 0xdc, 0x55, 0x99, 0xa4, 0xbf, 0x0d, 0x5f, 0xa2, 0xb3, 0xeb, 0x7d, 0x82, 0xfb, 0x7b, 0xf4, - 0x59, 0xd7, 0xf9, 0x80, 0x21, 0x9e, 0xaf, 0xb7, 0xd8, 0xbb, 0xdc, 0x62, 0xef, 0x6a, 0x8b, 0xbd, - 0xaf, 0x0d, 0xf6, 0xd7, 0x0d, 0xf6, 0x2f, 0x1b, 0xec, 0x5f, 0x35, 0xd8, 0xff, 0xd1, 0x60, 0xff, - 0xdb, 0x4f, 0xec, 0xbd, 0x1b, 0xd5, 0xd1, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x69, 0x4a, 0x84, - 0xe4, 0x71, 0x03, 0x00, 0x00, + // 400 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x90, 0x3f, 0x8f, 0xda, 0x30, + 0x18, 0xc6, 0x13, 0x4a, 0x11, 0x72, 0x11, 0x42, 0x99, 0x10, 0x83, 0xa9, 0x90, 0x2a, 0x31, 0xb4, + 0x76, 0x83, 0xfa, 0x4f, 0x9d, 0xaa, 0xec, 0x6d, 0xa5, 0x30, 0x54, 0xea, 0xd2, 0x3a, 0xe1, 0x6d, + 0x48, 0x43, 0x12, 0xcb, 0x76, 0xa2, 0x76, 0xeb, 0x47, 0xe8, 0xc7, 0xb8, 0x8f, 0xc2, 0xc8, 0xc8, + 0x84, 0x8e, 0xdc, 0x17, 0x39, 0xe1, 0xe4, 0x12, 0x1d, 0x70, 0xba, 0xbb, 0xcd, 0x8f, 0xed, 0xdf, + 0xef, 0x7d, 0xf4, 0xa2, 0x2f, 0xd1, 0x07, 0x49, 0xc2, 0x94, 0x46, 0x99, 0x07, 0x22, 0x01, 0x05, + 0x92, 0xe6, 0x90, 0x2c, 0x52, 0x41, 0xab, 0x07, 0xc6, 0x43, 0x09, 0x22, 0x07, 0x41, 0x79, 0x14, + 0xe8, 0x44, 0xe1, 0x0f, 0x8b, 0xf9, 0x0a, 0x66, 0x34, 0xb7, 0x69, 0x00, 0x09, 0x08, 0xa6, 0x60, + 0x41, 0xb8, 0x48, 0x55, 0x6a, 0xbd, 0x28, 0x31, 0x52, 0x63, 0x84, 0x47, 0x81, 0x4e, 0xe4, 0x06, + 0x23, 0xb9, 0x3d, 0x7a, 0x15, 0x84, 0x6a, 0x99, 0x79, 0xc4, 0x4f, 0x63, 0x1a, 0xa4, 0x41, 0x4a, + 0x35, 0xed, 0x65, 0xbf, 0x74, 0xd2, 0x41, 0x9f, 0x4a, 0xeb, 0xe8, 0x4d, 0x53, 0x26, 0x66, 0xfe, + 0x32, 0x4c, 0x40, 0xfc, 0x6d, 0xfa, 0xc4, 0xa0, 0xd8, 0x99, 0x2e, 0x23, 0x7a, 0x17, 0x25, 0xb2, + 0x44, 0x85, 0x31, 0x9c, 0x00, 0xef, 0xee, 0x03, 0xa4, 0xbf, 0x84, 0x98, 0x1d, 0x73, 0x93, 0x8b, + 0x16, 0x42, 0x2e, 0xf0, 0x55, 0xe8, 0xb3, 0x39, 0x28, 0xeb, 0x27, 0xea, 0x1e, 0x2a, 0x2d, 0x98, + 0x62, 0x43, 0xf3, 0xb9, 0x39, 0x7d, 0x36, 0x7b, 0x4d, 0x9a, 0xb5, 0xd4, 0xe6, 0x66, 0x33, 0x87, + 0xdf, 0x24, 0xb7, 0xc9, 0x57, 0xef, 0x37, 0xf8, 0xea, 0x33, 0x28, 0xe6, 0x58, 0xeb, 0xdd, 0xd8, + 0x28, 0x76, 0x63, 0xd4, 0xdc, 0xb9, 0xb5, 0xd5, 0xfa, 0x86, 0xda, 0x92, 0x83, 0x3f, 0x6c, 0x69, + 0xfb, 0x5b, 0xf2, 0xa0, 0xa5, 0x93, 0xa6, 0xe2, 0x9c, 0x83, 0xef, 0xf4, 0xaa, 0x11, 0xed, 0x43, + 0x72, 0xb5, 0xd0, 0xfa, 0x81, 0x3a, 0x52, 0x31, 0x95, 0xc9, 0xe1, 0x13, 0xad, 0x7e, 0xff, 0x78, + 0xb5, 0xc6, 0x9d, 0x7e, 0x25, 0xef, 0x94, 0xd9, 0xad, 0xb4, 0x93, 0x8f, 0xa8, 0x7f, 0xbb, 0x86, + 0x35, 0x45, 0x5d, 0x51, 0xde, 0x48, 0xbd, 0xad, 0xa7, 0x4e, 0xaf, 0xd8, 0x8d, 0xbb, 0xd5, 0x2f, + 0xe9, 0xd6, 0xaf, 0x93, 0x4f, 0x68, 0x70, 0x3c, 0xc7, 0x7a, 0x79, 0x42, 0x0f, 0xaa, 0xc9, 0x67, + 0x0c, 0xce, 0x74, 0xbd, 0xc7, 0xc6, 0x66, 0x8f, 0x8d, 0xed, 0x1e, 0x1b, 0xff, 0x0a, 0x6c, 0xae, + 0x0b, 0x6c, 0x6e, 0x0a, 0x6c, 0x6e, 0x0b, 0x6c, 0x5e, 0x16, 0xd8, 0xfc, 0x7f, 0x85, 0x8d, 0xef, + 0xad, 0xdc, 0xbe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x03, 0x3d, 0xdb, 0x1b, 0x18, 0x03, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/generated.proto index e0bcac5e5..3501b3860 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,11 +21,9 @@ syntax = 'proto2'; package k8s.io.apiserver.pkg.apis.example2.v1; -import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.conversion.go index 551ab0154..206a264f7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.deepcopy.go index c8a37af45..79cd0a66a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/zz_generated.deepcopy.go index f4d4732ad..9c3b4480e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/apis/example2/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/audit/request.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/audit/request.go index 47c0fca80..25d6c33eb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/audit/request.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/audit/request.go @@ -171,7 +171,12 @@ func LogResponseObject(ae *auditinternal.Event, obj runtime.Object, gv schema.Gr return } if status, ok := obj.(*metav1.Status); ok { - ae.ResponseStatus = status + // selectively copy the bounded fields. + ae.ResponseStatus = &metav1.Status{ + Status: status.Status, + Reason: status.Reason, + Code: status.Code, + } } if ae.Level.Less(auditinternal.LevelRequestResponse) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go index 38f132b58..948478b80 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader.go @@ -21,6 +21,7 @@ import ( "fmt" "io/ioutil" "net/http" + "net/url" "strings" "k8s.io/apimachinery/pkg/util/sets" @@ -160,6 +161,14 @@ func allHeaderValues(h http.Header, headerNames []string) []string { return ret } +func unescapeExtraKey(encodedKey string) string { + key, err := url.PathUnescape(encodedKey) // Decode %-encoded bytes. + if err != nil { + return encodedKey // Always record extra strings, even if malformed/unencoded. + } + return key +} + func newExtra(h http.Header, headerPrefixes []string) map[string][]string { ret := map[string][]string{} @@ -170,7 +179,7 @@ func newExtra(h http.Header, headerPrefixes []string) map[string][]string { continue } - extraKey := strings.ToLower(headerName[len(prefix):]) + extraKey := unescapeExtraKey(strings.ToLower(headerName[len(prefix):])) ret[extraKey] = append(ret[extraKey], vv...) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader_test.go index d81d4ee64..28876dbc4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/headerrequest/requestheader_test.go @@ -152,6 +152,37 @@ func TestRequestHeader(t *testing.T) { }, expectedOk: true, }, + + "escaped extra keys": { + nameHeaders: []string{"X-Remote-User"}, + groupHeaders: []string{"X-Remote-Group"}, + extraPrefixHeaders: []string{"X-Remote-Extra-"}, + requestHeaders: http.Header{ + "X-Remote-User": {"Bob"}, + "X-Remote-Group": {"one-a", "one-b"}, + "X-Remote-Extra-Alpha": {"alphabetical"}, + "X-Remote-Extra-Alph4num3r1c": {"alphanumeric"}, + "X-Remote-Extra-Percent%20encoded": {"percent encoded"}, + "X-Remote-Extra-Almost%zzpercent%xxencoded": {"not quite percent encoded"}, + "X-Remote-Extra-Example.com%2fpercent%2520encoded": {"url with double percent encoding"}, + "X-Remote-Extra-Example.com%2F%E4%BB%8A%E6%97%A5%E3%81%AF": {"url with unicode"}, + "X-Remote-Extra-Abc123!#$+.-_*\\^`~|'": {"header key legal characters"}, + }, + expectedUser: &user.DefaultInfo{ + Name: "Bob", + Groups: []string{"one-a", "one-b"}, + Extra: map[string][]string{ + "alpha": {"alphabetical"}, + "alph4num3r1c": {"alphanumeric"}, + "percent encoded": {"percent encoded"}, + "almost%zzpercent%xxencoded": {"not quite percent encoded"}, + "example.com/percent%20encoded": {"url with double percent encoding"}, + "example.com/今日は": {"url with unicode"}, + "abc123!#$+.-_*\\^`~|'": {"header key legal characters"}, + }, + }, + expectedOk: true, + }, } for k, testcase := range testcases { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/BUILD index dd08b1e09..ebd5e7a76 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/BUILD @@ -12,6 +12,7 @@ go_test( "apiserver_test.go", "audit_test.go", "installer_test.go", + "patchhandler_test.go", "watch_test.go", ], embed = [":go_default_library"], @@ -64,21 +65,23 @@ go_library( importpath = "k8s.io/apiserver/pkg/endpoints", deps = [ "//vendor/github.com/emicklei/go-restful:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta: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/runtime:go_default_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/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/discovery:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/handlers:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/handlers/negotiation:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/openapi:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/builder:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/common:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go index 54172d70e..bffdf2b8c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go @@ -19,6 +19,7 @@ package endpoints import ( "bytes" "compress/gzip" + "context" "encoding/json" "errors" "fmt" @@ -70,18 +71,6 @@ import ( "k8s.io/apiserver/pkg/server/filters" ) -// alwaysAdmit is an implementation of admission.Interface which always says yes to an admit request. -// It is useful in tests and when using kubernetes in an open manner. -type alwaysAdmit struct{} - -func (alwaysAdmit) Admit(a admission.Attributes) (err error) { - return nil -} - -func (alwaysAdmit) Handles(operation admission.Operation) bool { - return true -} - type alwaysMutatingDeny struct{} func (alwaysMutatingDeny) Admit(a admission.Attributes) (err error) { @@ -128,9 +117,7 @@ var parameterCodec = runtime.NewParameterCodec(scheme) var accessor = meta.NewAccessor() var selfLinker runtime.SelfLinker = accessor -var mapper, namespaceMapper meta.RESTMapper // The mappers with namespace and with legacy namespace scopes. var admissionControl admission.Interface -var requestContextMapper request.RequestContextMapper func init() { metav1.AddToGroupVersion(scheme, metav1.SchemeGroupVersion) @@ -143,37 +130,6 @@ func init() { examplev1.AddToScheme(scheme) } -func interfacesFor(version schema.GroupVersion) (*meta.VersionInterfaces, error) { - switch version { - case testGroupVersion: - return &meta.VersionInterfaces{ - ObjectConvertor: scheme, - MetadataAccessor: accessor, - }, nil - case newGroupVersion: - return &meta.VersionInterfaces{ - ObjectConvertor: scheme, - MetadataAccessor: accessor, - }, nil - case grouplessGroupVersion: - return &meta.VersionInterfaces{ - ObjectConvertor: scheme, - MetadataAccessor: accessor, - }, nil - case testGroup2Version: - return &meta.VersionInterfaces{ - ObjectConvertor: scheme, - MetadataAccessor: accessor, - }, nil - default: - return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, groupVersions) - } -} - -func newMapper() *meta.DefaultRESTMapper { - return meta.NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion, newGroupVersion}, interfacesFor) -} - func addGrouplessTypes() { scheme.AddKnownTypes(grouplessGroupVersion, &genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &metav1.ListOptions{}, &metav1.ExportOptions{}, @@ -219,27 +175,6 @@ func init() { addTestTypes() addNewTestTypes() - nsMapper := newMapper() - - // enumerate all supported versions, get the kinds, and register with - // the mapper how to address our resources - for _, gv := range groupVersions { - for kind := range scheme.KnownTypes(gv) { - gvk := gv.WithKind(kind) - root := bool(kind == "SimpleRoot") - if root { - nsMapper.Add(gvk, meta.RESTScopeRoot) - } else { - nsMapper.Add(gvk, meta.RESTScopeNamespace) - } - } - } - - mapper = nsMapper - namespaceMapper = nsMapper - admissionControl = alwaysAdmit{} - requestContextMapper = request.NewRequestContextMapper() - scheme.AddFieldLabelConversionFunc(grouplessGroupVersion.String(), "Simple", func(label, value string) (string, string, error) { return label, value, nil @@ -268,11 +203,6 @@ func handle(storage map[string]rest.Storage) http.Handler { return handleInternal(storage, admissionControl, selfLinker, nil) } -// tests using the new namespace scope mechanism -func handleNamespaced(storage map[string]rest.Storage) http.Handler { - return handleInternal(storage, admissionControl, selfLinker, nil) -} - // tests using a custom self linker func handleLinker(storage map[string]rest.Storage, selfLinker runtime.SelfLinker) http.Handler { return handleInternal(storage, admissionControl, selfLinker, nil) @@ -286,17 +216,17 @@ func handleInternal(storage map[string]rest.Storage, admissionControl admission. template := APIGroupVersion{ Storage: storage, - Creater: scheme, - Convertor: scheme, - Defaulter: scheme, - Typer: scheme, - Linker: selfLinker, - Mapper: namespaceMapper, + Creater: scheme, + Convertor: scheme, + UnsafeConvertor: runtime.UnsafeObjectConvertor(scheme), + Defaulter: scheme, + Typer: scheme, + Linker: selfLinker, + RootScopedKinds: sets.NewString("SimpleRoot"), ParameterCodec: parameterCodec, - Admit: admissionControl, - Context: requestContextMapper, + Admit: admissionControl, } // groupless v1 version @@ -334,13 +264,11 @@ func handleInternal(storage map[string]rest.Storage, admissionControl admission. panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err)) } } - - handler := genericapifilters.WithAudit(mux, requestContextMapper, auditSink, auditpolicy.FakeChecker(auditinternal.LevelRequestResponse, nil), func(r *http.Request, requestInfo *request.RequestInfo) bool { + handler := genericapifilters.WithAudit(mux, auditSink, auditpolicy.FakeChecker(auditinternal.LevelRequestResponse, nil), func(r *http.Request, requestInfo *request.RequestInfo) bool { // simplified long-running check return requestInfo.Verb == "watch" || requestInfo.Verb == "proxy" }) - handler = genericapifilters.WithRequestInfo(handler, testRequestInfoResolver(), requestContextMapper) - handler = request.WithRequestContext(handler, requestContextMapper) + handler = genericapifilters.WithRequestInfo(handler, testRequestInfoResolver()) return &defaultAPIServer{handler, container} } @@ -419,7 +347,11 @@ type SimpleRESTStorage struct { injectedFunction func(obj runtime.Object) (returnObj runtime.Object, err error) } -func (storage *SimpleRESTStorage) Export(ctx request.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { +func (storage *SimpleRESTStorage) NamespaceScoped() bool { + return true +} + +func (storage *SimpleRESTStorage) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { obj, err := storage.Get(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, err @@ -434,11 +366,11 @@ func (storage *SimpleRESTStorage) Export(ctx request.Context, name string, opts return obj, storage.errors["export"] } -func (storage *SimpleRESTStorage) ConvertToTable(ctx request.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { +func (storage *SimpleRESTStorage) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { return rest.NewDefaultTableConvertor(schema.GroupResource{Resource: "simple"}).ConvertToTable(ctx, obj, tableOptions) } -func (storage *SimpleRESTStorage) List(ctx request.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { +func (storage *SimpleRESTStorage) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { storage.checkContext(ctx) result := &genericapitesting.SimpleList{ ListMeta: metav1.ListMeta{ @@ -493,7 +425,7 @@ func (h *OutputConnect) ServeHTTP(w http.ResponseWriter, req *http.Request) { w.Write([]byte(h.response)) } -func (storage *SimpleRESTStorage) Get(ctx request.Context, id string, options *metav1.GetOptions) (runtime.Object, error) { +func (storage *SimpleRESTStorage) Get(ctx context.Context, id string, options *metav1.GetOptions) (runtime.Object, error) { storage.checkContext(ctx) if id == "binary" { return storage.stream, storage.errors["get"] @@ -501,11 +433,11 @@ func (storage *SimpleRESTStorage) Get(ctx request.Context, id string, options *m return storage.item.DeepCopy(), storage.errors["get"] } -func (storage *SimpleRESTStorage) checkContext(ctx request.Context) { +func (storage *SimpleRESTStorage) checkContext(ctx context.Context) { storage.actualNamespace, storage.namespacePresent = request.NamespaceFrom(ctx) } -func (storage *SimpleRESTStorage) Delete(ctx request.Context, id string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { +func (storage *SimpleRESTStorage) Delete(ctx context.Context, id string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { storage.checkContext(ctx) storage.deleted = id storage.deleteOptions = options @@ -528,7 +460,7 @@ func (storage *SimpleRESTStorage) NewList() runtime.Object { return &genericapitesting.SimpleList{} } -func (storage *SimpleRESTStorage) Create(ctx request.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (storage *SimpleRESTStorage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { storage.checkContext(ctx) storage.created = obj.(*genericapitesting.Simple) if err := storage.errors["create"]; err != nil { @@ -544,7 +476,7 @@ func (storage *SimpleRESTStorage) Create(ctx request.Context, obj runtime.Object return obj, err } -func (storage *SimpleRESTStorage) Update(ctx request.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (storage *SimpleRESTStorage) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { storage.checkContext(ctx) obj, err := objInfo.UpdatedObject(ctx, &storage.item) if err != nil { @@ -564,7 +496,7 @@ func (storage *SimpleRESTStorage) Update(ctx request.Context, name string, objIn } // Implement ResourceWatcher. -func (storage *SimpleRESTStorage) Watch(ctx request.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (storage *SimpleRESTStorage) Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { storage.lock.Lock() defer storage.lock.Unlock() storage.checkContext(ctx) @@ -613,7 +545,7 @@ func (s *ConnecterRESTStorage) New() runtime.Object { return &genericapitesting.Simple{} } -func (s *ConnecterRESTStorage) Connect(ctx request.Context, id string, options runtime.Object, responder rest.Responder) (http.Handler, error) { +func (s *ConnecterRESTStorage) Connect(ctx context.Context, id string, options runtime.Object, responder rest.Responder) (http.Handler, error) { s.receivedConnectOptions = options s.receivedID = id s.receivedResponder = responder @@ -638,7 +570,7 @@ type LegacyRESTStorage struct { *SimpleRESTStorage } -func (storage LegacyRESTStorage) Delete(ctx request.Context, id string) (runtime.Object, error) { +func (storage LegacyRESTStorage) Delete(ctx context.Context, id string) (runtime.Object, error) { obj, _, err := storage.SimpleRESTStorage.Delete(ctx, id, nil) return obj, err } @@ -664,7 +596,7 @@ type GetWithOptionsRESTStorage struct { takesPath string } -func (r *GetWithOptionsRESTStorage) Get(ctx request.Context, name string, options runtime.Object) (runtime.Object, error) { +func (r *GetWithOptionsRESTStorage) Get(ctx context.Context, name string, options runtime.Object) (runtime.Object, error) { if _, ok := options.(*genericapitesting.SimpleGetOptions); !ok { return nil, fmt.Errorf("Unexpected options object: %#v", options) } @@ -687,7 +619,11 @@ type GetWithOptionsRootRESTStorage struct { takesPath string } -func (r *GetWithOptionsRootRESTStorage) Get(ctx request.Context, name string, options runtime.Object) (runtime.Object, error) { +func (r *GetWithOptionsRootRESTStorage) NamespaceScoped() bool { + return false +} + +func (r *GetWithOptionsRootRESTStorage) Get(ctx context.Context, name string, options runtime.Object) (runtime.Object, error) { if _, ok := options.(*genericapitesting.SimpleGetOptions); !ok { return nil, fmt.Errorf("Unexpected options object: %#v", options) } @@ -709,7 +645,7 @@ type NamedCreaterRESTStorage struct { createdName string } -func (storage *NamedCreaterRESTStorage) Create(ctx request.Context, name string, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (storage *NamedCreaterRESTStorage) Create(ctx context.Context, name string, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { storage.checkContext(ctx) storage.created = obj.(*genericapitesting.Simple) storage.createdName = name @@ -739,12 +675,12 @@ func (storage *SimpleTypedStorage) New() runtime.Object { return storage.baseType } -func (storage *SimpleTypedStorage) Get(ctx request.Context, id string, options *metav1.GetOptions) (runtime.Object, error) { +func (storage *SimpleTypedStorage) Get(ctx context.Context, id string, options *metav1.GetOptions) (runtime.Object, error) { storage.checkContext(ctx) return storage.item.DeepCopyObject(), storage.errors["get"] } -func (storage *SimpleTypedStorage) checkContext(ctx request.Context) { +func (storage *SimpleTypedStorage) checkContext(ctx context.Context) { storage.actualNamespace, storage.namespacePresent = request.NamespaceFrom(ctx) } @@ -867,13 +803,16 @@ func TestNotFound(t *testing.T) { if response.StatusCode != v.Status { t.Errorf("Expected %d for %s (%s), Got %#v", v.Status, v.Method, k, response) - t.Errorf("MAPPER: %v", mapper) } } } type UnimplementedRESTStorage struct{} +func (UnimplementedRESTStorage) NamespaceScoped() bool { + return true +} + func (UnimplementedRESTStorage) New() runtime.Object { return &genericapitesting.Simple{} } @@ -936,6 +875,71 @@ func TestUnimplementedRESTStorage(t *testing.T) { } } +type OnlyGetRESTStorage struct { + UnimplementedRESTStorage +} + +func (OnlyGetRESTStorage) Get(ctx context.Context, id string, options *metav1.GetOptions) (runtime.Object, error) { + return nil, nil +} + +func (OnlyGetRESTStorage) NewList() runtime.Object { + return &genericapitesting.SimpleList{} +} + +func (OnlyGetRESTStorage) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { + return nil, nil +} + +// TestSomeUnimplementedRESTStorage ensures that if a rest.Storage does +// not implement a given method, that it is literally not registered +// with the server. We need to have at least one verb supported inorder +// to get a MethodNotAllowed rather than NotFound error. +func TestSomeUnimplementedRESTStorage(t *testing.T) { + type T struct { + Method string + Path string + ErrCode int + } + + cases := map[string]T{ + "groupless POST list": {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed}, + "groupless PUT object": {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed}, + "groupless DELETE object": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed}, + "groupless DELETE collection": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed}, + "POST list": {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed}, + "PUT object": {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed}, + "DELETE object": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo/bar", http.StatusMethodNotAllowed}, + "DELETE collection": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo", http.StatusMethodNotAllowed}, + } + handler := handle(map[string]rest.Storage{ + "foo": OnlyGetRESTStorage{}, + }) + server := httptest.NewServer(handler) + defer server.Close() + client := http.Client{} + for k, v := range cases { + request, err := http.NewRequest(v.Method, server.URL+v.Path, bytes.NewReader([]byte(`{"kind":"Simple","apiVersion":"version"}`))) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + response, err := client.Do(request) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + defer response.Body.Close() + data, err := ioutil.ReadAll(response.Body) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if response.StatusCode != v.ErrCode { + t.Errorf("%s: expected %d for %s, Got %s", k, v.ErrCode, v.Method, string(data)) + continue + } + } +} + func TestList(t *testing.T) { testCases := []struct { url string @@ -1225,11 +1229,8 @@ func TestListCompression(t *testing.T) { } var handler = handleInternal(storage, admissionControl, selfLinker, nil) - requestContextMapper = request.NewRequestContextMapper() - - handler = filters.WithCompression(handler, requestContextMapper) - handler = genericapifilters.WithRequestInfo(handler, newTestRequestInfoResolver(), requestContextMapper) - handler = request.WithRequestContext(handler, requestContextMapper) + handler = filters.WithCompression(handler) + handler = genericapifilters.WithRequestInfo(handler, newTestRequestInfoResolver()) server := httptest.NewServer(handler) @@ -1635,13 +1636,10 @@ func TestGetCompression(t *testing.T) { namespace: "default", } - requestContextMapper = request.NewRequestContextMapper() - storage["simple"] = &simpleStorage handler := handleLinker(storage, selfLinker) - handler = filters.WithCompression(handler, requestContextMapper) - handler = genericapifilters.WithRequestInfo(handler, newTestRequestInfoResolver(), requestContextMapper) - handler = request.WithRequestContext(handler, requestContextMapper) + handler = filters.WithCompression(handler) + handler = genericapifilters.WithRequestInfo(handler, newTestRequestInfoResolver()) server := httptest.NewServer(handler) defer server.Close() @@ -2887,76 +2885,6 @@ func TestDeleteMissing(t *testing.T) { } } -func TestPatch(t *testing.T) { - storage := map[string]rest.Storage{} - ID := "id" - item := &genericapitesting.Simple{ - ObjectMeta: metav1.ObjectMeta{ - Name: ID, - Namespace: "", // update should allow the client to send an empty namespace - UID: "uid", - }, - Other: "bar", - } - simpleStorage := SimpleRESTStorage{item: *item} - storage["simple"] = &simpleStorage - selfLinker := &setTestSelfLinker{ - t: t, - expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + ID, - name: ID, - namespace: metav1.NamespaceDefault, - } - handler := handleLinker(storage, selfLinker) - server := httptest.NewServer(handler) - defer server.Close() - - client := http.Client{} - request, err := http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`))) - request.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8") - response, err := client.Do(request) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - dump, _ := httputil.DumpResponse(response, true) - t.Log(string(dump)) - - if simpleStorage.updated == nil || simpleStorage.updated.Labels["foo"] != "bar" { - t.Errorf("Unexpected update value %#v, expected %#v.", simpleStorage.updated, item) - } - if !selfLinker.called { - t.Errorf("Never set self link") - } -} - -func TestPatchRequiresMatchingName(t *testing.T) { - storage := map[string]rest.Storage{} - ID := "id" - item := &genericapitesting.Simple{ - ObjectMeta: metav1.ObjectMeta{ - Name: ID, - Namespace: "", // update should allow the client to send an empty namespace - UID: "uid", - }, - Other: "bar", - } - simpleStorage := SimpleRESTStorage{item: *item} - storage["simple"] = &simpleStorage - handler := handle(storage) - server := httptest.NewServer(handler) - defer server.Close() - - client := http.Client{} - request, err := http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"metadata":{"name":"idbar"}}`))) - request.Header.Set("Content-Type", "application/merge-patch+json") - response, err := client.Do(request) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if response.StatusCode != http.StatusBadRequest { - t.Errorf("Unexpected response %#v", response) - } -} - func TestUpdate(t *testing.T) { storage := map[string]rest.Storage{} simpleStorage := SimpleRESTStorage{} @@ -3290,16 +3218,16 @@ func TestParentResourceIsRequired(t *testing.T) { Storage: map[string]rest.Storage{ "simple/sub": storage, }, - Root: "/" + prefix, - Creater: scheme, - Convertor: scheme, - Defaulter: scheme, - Typer: scheme, - Linker: selfLinker, + Root: "/" + prefix, + Creater: scheme, + Convertor: scheme, + UnsafeConvertor: runtime.UnsafeObjectConvertor(scheme), + Defaulter: scheme, + Typer: scheme, + Linker: selfLinker, + RootScopedKinds: sets.NewString("SimpleRoot"), - Admit: admissionControl, - Context: requestContextMapper, - Mapper: namespaceMapper, + Admit: admissionControl, GroupVersion: newGroupVersion, OptionsExternalVersion: &newGroupVersion, @@ -3321,16 +3249,15 @@ func TestParentResourceIsRequired(t *testing.T) { "simple": &SimpleRESTStorage{}, "simple/sub": storage, }, - Root: "/" + prefix, - Creater: scheme, - Convertor: scheme, - Defaulter: scheme, - Typer: scheme, - Linker: selfLinker, + Root: "/" + prefix, + Creater: scheme, + Convertor: scheme, + UnsafeConvertor: runtime.UnsafeObjectConvertor(scheme), + Defaulter: scheme, + Typer: scheme, + Linker: selfLinker, - Admit: admissionControl, - Context: requestContextMapper, - Mapper: namespaceMapper, + Admit: admissionControl, GroupVersion: newGroupVersion, OptionsExternalVersion: &newGroupVersion, @@ -3343,8 +3270,7 @@ func TestParentResourceIsRequired(t *testing.T) { t.Fatal(err) } - handler := genericapifilters.WithRequestInfo(container, newTestRequestInfoResolver(), requestContextMapper) - handler = request.WithRequestContext(handler, requestContextMapper) + handler := genericapifilters.WithRequestInfo(container, newTestRequestInfoResolver()) // resource is NOT registered in the root scope w := httptest.NewRecorder() @@ -3744,7 +3670,7 @@ func (obj *UnregisteredAPIObject) DeepCopyObject() runtime.Object { func TestWriteJSONDecodeError(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - responsewriters.WriteObjectNegotiated(request.NewContext(), codecs, newGroupVersion, w, req, http.StatusOK, &UnregisteredAPIObject{"Undecodable"}) + responsewriters.WriteObjectNegotiated(codecs, newGroupVersion, w, req, http.StatusOK, &UnregisteredAPIObject{"Undecodable"}) })) defer server.Close() // We send a 200 status code before we encode the object, so we expect OK, but there will @@ -3906,20 +3832,110 @@ func TestUpdateChecksAPIVersion(t *testing.T) { } } +// runRequest is used by TestDryRun since it runs the test twice in a +// row with a slightly different URL (one has ?dryRun, one doesn't). +func runRequest(t *testing.T, path, verb string, data []byte, contentType string) *http.Response { + request, err := http.NewRequest(verb, path, bytes.NewBuffer(data)) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if contentType != "" { + request.Header.Set("Content-Type", contentType) + } + response, err := http.DefaultClient.Do(request) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + return response +} + +// encodeOrFatal is used by TestDryRun to parse an object and stop right +// away if it fails. +func encodeOrFatal(t *testing.T, obj runtime.Object) []byte { + data, err := runtime.Encode(testCodec, obj) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + return data +} + +type SimpleRESTStorageWithDeleteCollection struct { + SimpleRESTStorage +} + +// Delete collection doesn't do much, but let us test this path. +func (storage *SimpleRESTStorageWithDeleteCollection) DeleteCollection(ctx context.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) { + storage.checkContext(ctx) + return nil, nil +} + +func TestDryRun(t *testing.T) { + tests := []struct { + path string + verb string + data []byte + contentType string + }{ + {path: "/namespaces/default/simples", verb: "POST", data: encodeOrFatal(t, &genericapitesting.Simple{Other: "bar"})}, + {path: "/namespaces/default/simples/id", verb: "PUT", data: encodeOrFatal(t, &genericapitesting.Simple{ObjectMeta: metav1.ObjectMeta{Name: "id"}, Other: "bar"})}, + {path: "/namespaces/default/simples/id", verb: "PATCH", data: []byte(`{"labels":{"foo":"bar"}}`), contentType: "application/merge-patch+json; charset=UTF-8"}, + {path: "/namespaces/default/simples/id", verb: "DELETE"}, + {path: "/namespaces/default/simples", verb: "DELETE"}, + {path: "/namespaces/default/simples/id/subsimple", verb: "DELETE"}, + } + + server := httptest.NewServer(handle(map[string]rest.Storage{ + "simples": &SimpleRESTStorageWithDeleteCollection{ + SimpleRESTStorage{ + item: genericapitesting.Simple{ + ObjectMeta: metav1.ObjectMeta{ + Name: "id", + Namespace: "", + UID: "uid", + }, + Other: "bar", + }, + }, + }, + "simples/subsimple": &SimpleXGSubresourceRESTStorage{ + item: genericapitesting.SimpleXGSubresource{ + SubresourceInfo: "foo", + }, + itemGVK: testGroup2Version.WithKind("SimpleXGSubresource"), + }, + })) + defer server.Close() + for _, test := range tests { + baseUrl := server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + response := runRequest(t, baseUrl+test.path, test.verb, test.data, test.contentType) + if response.StatusCode == http.StatusBadRequest { + t.Fatalf("unexpected BadRequest: %#v", response) + } + response = runRequest(t, baseUrl+test.path+"?dryRun", test.verb, test.data, test.contentType) + if response.StatusCode != http.StatusBadRequest { + t.Fatalf("unexpected non BadRequest: %#v", response) + } + } +} + type SimpleXGSubresourceRESTStorage struct { item genericapitesting.SimpleXGSubresource itemGVK schema.GroupVersionKind } +var _ = rest.GroupVersionKindProvider(&SimpleXGSubresourceRESTStorage{}) + func (storage *SimpleXGSubresourceRESTStorage) New() runtime.Object { return &genericapitesting.SimpleXGSubresource{} } -func (storage *SimpleXGSubresourceRESTStorage) Get(ctx request.Context, id string, options *metav1.GetOptions) (runtime.Object, error) { +func (storage *SimpleXGSubresourceRESTStorage) Get(ctx context.Context, id string, options *metav1.GetOptions) (runtime.Object, error) { return storage.item.DeepCopyObject(), nil } -var _ = rest.GroupVersionKindProvider(&SimpleXGSubresourceRESTStorage{}) +func (storage *SimpleXGSubresourceRESTStorage) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { + return nil, true, nil +} func (storage *SimpleXGSubresourceRESTStorage) GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind { return storage.itemGVK @@ -3945,17 +3961,16 @@ func TestXGSubresource(t *testing.T) { group := APIGroupVersion{ Storage: storage, - Creater: scheme, - Convertor: scheme, - Defaulter: scheme, - Typer: scheme, - Linker: selfLinker, - Mapper: namespaceMapper, + Creater: scheme, + Convertor: scheme, + UnsafeConvertor: runtime.UnsafeObjectConvertor(scheme), + Defaulter: scheme, + Typer: scheme, + Linker: selfLinker, ParameterCodec: parameterCodec, - Admit: admissionControl, - Context: requestContextMapper, + Admit: admissionControl, Root: "/" + prefix, GroupVersion: testGroupVersion, @@ -4058,8 +4073,7 @@ func BenchmarkUpdateProtobuf(b *testing.B) { } func newTestServer(handler http.Handler) *httptest.Server { - handler = genericapifilters.WithRequestInfo(handler, newTestRequestInfoResolver(), requestContextMapper) - handler = request.WithRequestContext(handler, requestContextMapper) + handler = genericapifilters.WithRequestInfo(handler, newTestRequestInfoResolver()) return httptest.NewServer(handler) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/audit_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/audit_test.go index 728e93b2a..78bbe4464 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/audit_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/audit_test.go @@ -70,7 +70,7 @@ func TestAudit(t *testing.T) { if events[i].RequestObject == nil { return nil } - return fmt.Errorf("expected RequestBody to be nil, got non-nill '%s'", events[i].RequestObject.Raw) + return fmt.Errorf("expected RequestBody to be nil, got non-nil '%s'", events[i].RequestObject.Raw) } } requestBodyIs := func(i int, text string) eventCheck { @@ -100,7 +100,7 @@ func TestAudit(t *testing.T) { if events[i].ResponseObject == nil { return nil } - return fmt.Errorf("expected ResponseBody to be nil, got non-nill '%s'", events[i].ResponseObject.Raw) + return fmt.Errorf("expected ResponseBody to be nil, got non-nil '%s'", events[i].ResponseObject.Raw) } } responseBodyMatches := func(i int, pattern string) eventCheck { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/BUILD index cf2da3c32..421083cce 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/BUILD @@ -15,13 +15,12 @@ go_test( embed = [":go_default_library"], deps = [ "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", ], ) @@ -45,7 +44,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/handlers/negotiation:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/group.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/group.go index ea47a1046..02330e9f3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/group.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/group.go @@ -17,7 +17,6 @@ limitations under the License. package discovery import ( - "errors" "net/http" "github.com/emicklei/go-restful" @@ -27,18 +26,16 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" ) // APIGroupHandler creates a webservice serving the supported versions, preferred version, and name // of a group. E.g., such a web service will be registered at /apis/extensions. type APIGroupHandler struct { - serializer runtime.NegotiatedSerializer - contextMapper request.RequestContextMapper - group metav1.APIGroup + serializer runtime.NegotiatedSerializer + group metav1.APIGroup } -func NewAPIGroupHandler(serializer runtime.NegotiatedSerializer, group metav1.APIGroup, contextMapper request.RequestContextMapper) *APIGroupHandler { +func NewAPIGroupHandler(serializer runtime.NegotiatedSerializer, group metav1.APIGroup) *APIGroupHandler { if keepUnversioned(group.Name) { // Because in release 1.1, /apis/extensions returns response with empty // APIVersion, we use stripVersionNegotiatedSerializer to keep the @@ -47,9 +44,8 @@ func NewAPIGroupHandler(serializer runtime.NegotiatedSerializer, group metav1.AP } return &APIGroupHandler{ - serializer: serializer, - contextMapper: contextMapper, - group: group, + serializer: serializer, + group: group, } } @@ -73,10 +69,5 @@ func (s *APIGroupHandler) handle(req *restful.Request, resp *restful.Response) { } func (s *APIGroupHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - ctx, ok := s.contextMapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } - responsewriters.WriteObjectNegotiated(ctx, s.serializer, schema.GroupVersion{}, w, req, http.StatusOK, &s.group) + responsewriters.WriteObjectNegotiated(s.serializer, schema.GroupVersion{}, w, req, http.StatusOK, &s.group) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/legacy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/legacy.go index 3a98e6320..fb648e528 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/legacy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/legacy.go @@ -17,7 +17,6 @@ limitations under the License. package discovery import ( - "errors" "net/http" "github.com/emicklei/go-restful" @@ -28,31 +27,28 @@ import ( utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" ) // legacyRootAPIHandler creates a webservice serving api group discovery. type legacyRootAPIHandler struct { // addresses is used to build cluster IPs for discovery. - addresses Addresses - apiPrefix string - serializer runtime.NegotiatedSerializer - apiVersions []string - contextMapper request.RequestContextMapper + addresses Addresses + apiPrefix string + serializer runtime.NegotiatedSerializer + apiVersions []string } -func NewLegacyRootAPIHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, apiPrefix string, apiVersions []string, contextMapper request.RequestContextMapper) *legacyRootAPIHandler { +func NewLegacyRootAPIHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, apiPrefix string, apiVersions []string) *legacyRootAPIHandler { // Because in release 1.1, /apis returns response with empty APIVersion, we // use stripVersionNegotiatedSerializer to keep the response backwards // compatible. serializer = stripVersionNegotiatedSerializer{serializer} return &legacyRootAPIHandler{ - addresses: addresses, - apiPrefix: apiPrefix, - serializer: serializer, - apiVersions: apiVersions, - contextMapper: contextMapper, + addresses: addresses, + apiPrefix: apiPrefix, + serializer: serializer, + apiVersions: apiVersions, } } @@ -72,17 +68,11 @@ func (s *legacyRootAPIHandler) WebService() *restful.WebService { } func (s *legacyRootAPIHandler) handle(req *restful.Request, resp *restful.Response) { - ctx, ok := s.contextMapper.Get(req.Request) - if !ok { - responsewriters.InternalError(resp.ResponseWriter, req.Request, errors.New("no context found for request")) - return - } - clientIP := utilnet.GetClientIP(req.Request) apiVersions := &metav1.APIVersions{ ServerAddressByClientCIDRs: s.addresses.ServerAddressByClientCIDRs(clientIP), Versions: s.apiVersions, } - responsewriters.WriteObjectNegotiated(ctx, s.serializer, schema.GroupVersion{}, resp.ResponseWriter, req.Request, http.StatusOK, apiVersions) + responsewriters.WriteObjectNegotiated(s.serializer, schema.GroupVersion{}, resp.ResponseWriter, req.Request, http.StatusOK, apiVersions) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/root.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/root.go index c1a8ecf65..7ed64a9f5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/root.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/root.go @@ -17,7 +17,6 @@ limitations under the License. package discovery import ( - "errors" "net/http" "sync" @@ -29,7 +28,6 @@ import ( utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" ) // GroupManager is an interface that allows dynamic mutation of the existing webservice to handle @@ -48,8 +46,7 @@ type rootAPIsHandler struct { // addresses is used to build cluster IPs for discovery. addresses Addresses - serializer runtime.NegotiatedSerializer - contextMapper request.RequestContextMapper + serializer runtime.NegotiatedSerializer // Map storing information about all groups to be exposed in discovery response. // The map is from name to the group. @@ -59,17 +56,16 @@ type rootAPIsHandler struct { apiGroupNames []string } -func NewRootAPIsHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, contextMapper request.RequestContextMapper) *rootAPIsHandler { +func NewRootAPIsHandler(addresses Addresses, serializer runtime.NegotiatedSerializer) *rootAPIsHandler { // Because in release 1.1, /apis returns response with empty APIVersion, we // use stripVersionNegotiatedSerializer to keep the response backwards // compatible. serializer = stripVersionNegotiatedSerializer{serializer} return &rootAPIsHandler{ - addresses: addresses, - serializer: serializer, - apiGroups: map[string]metav1.APIGroup{}, - contextMapper: contextMapper, + addresses: addresses, + serializer: serializer, + apiGroups: map[string]metav1.APIGroup{}, } } @@ -99,12 +95,6 @@ func (s *rootAPIsHandler) RemoveGroup(groupName string) { } func (s *rootAPIsHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) { - ctx, ok := s.contextMapper.Get(req) - if !ok { - responsewriters.InternalError(resp, req, errors.New("no context found for request")) - return - } - s.lock.RLock() defer s.lock.RUnlock() @@ -121,7 +111,7 @@ func (s *rootAPIsHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) groups[i].ServerAddressByClientCIDRs = serverCIDR } - responsewriters.WriteObjectNegotiated(ctx, s.serializer, schema.GroupVersion{}, resp, req, http.StatusOK, &metav1.APIGroupList{Groups: groups}) + responsewriters.WriteObjectNegotiated(s.serializer, schema.GroupVersion{}, resp, req, http.StatusOK, &metav1.APIGroupList{Groups: groups}) } func (s *rootAPIsHandler) restfulHandle(req *restful.Request, resp *restful.Response) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/root_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/root_test.go index c8aeed93b..3e7c3c906 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/root_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/root_test.go @@ -26,21 +26,18 @@ import ( "github.com/stretchr/testify/assert" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" 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" utilnet "k8s.io/apimachinery/pkg/util/net" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apiserver/pkg/endpoints/request" ) var ( - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - registry = registered.NewOrDie("") - scheme = runtime.NewScheme() - codecs = serializer.NewCodecFactory(scheme) + scheme = runtime.NewScheme() + codecs = serializer.NewCodecFactory(scheme) ) func init() { @@ -83,11 +80,27 @@ func getGroupList(t *testing.T, server *httptest.Server) (*metav1.APIGroupList, return &groupList, err } +func contextHandler(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + ctx := req.Context() + resolver := &request.RequestInfoFactory{ + APIPrefixes: sets.NewString("api", "apis"), + GrouplessAPIPrefixes: sets.NewString("api"), + } + info, err := resolver.NewRequestInfo(req) + if err == nil { + ctx = request.WithRequestInfo(ctx, info) + } + req = req.WithContext(ctx) + handler.ServeHTTP(w, req) + }) +} + func TestDiscoveryAtAPIS(t *testing.T) { - mapper := request.NewRequestContextMapper() - handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs, mapper) + handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs) + + server := httptest.NewServer(contextHandler(handler)) - server := httptest.NewServer(request.WithRequestContext(handler, mapper)) groupList, err := getGroupList(t, server) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -135,10 +148,9 @@ func TestDiscoveryAtAPIS(t *testing.T) { } func TestDiscoveryOrdering(t *testing.T) { - mapper := request.NewRequestContextMapper() - handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs, mapper) + handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs) - server := httptest.NewServer(request.WithRequestContext(handler, mapper)) + server := httptest.NewServer(handler) groupList, err := getGroupList(t, server) if err != nil { t.Fatalf("unexpected error: %v", err) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/version.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/version.go index a6bd99998..aadfc7a5b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/version.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/version.go @@ -17,7 +17,6 @@ limitations under the License. package discovery import ( - "errors" "net/http" restful "github.com/emicklei/go-restful" @@ -27,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" ) type APIResourceLister interface { @@ -43,14 +41,13 @@ func (f APIResourceListerFunc) ListAPIResources() []metav1.APIResource { // APIVersionHandler creates a webservice serving the supported resources for the version // E.g., such a web service will be registered at /apis/extensions/v1beta1. type APIVersionHandler struct { - serializer runtime.NegotiatedSerializer - contextMapper request.RequestContextMapper + serializer runtime.NegotiatedSerializer groupVersion schema.GroupVersion apiResourceLister APIResourceLister } -func NewAPIVersionHandler(serializer runtime.NegotiatedSerializer, groupVersion schema.GroupVersion, apiResourceLister APIResourceLister, contextMapper request.RequestContextMapper) *APIVersionHandler { +func NewAPIVersionHandler(serializer runtime.NegotiatedSerializer, groupVersion schema.GroupVersion, apiResourceLister APIResourceLister) *APIVersionHandler { if keepUnversioned(groupVersion.Group) { // Because in release 1.1, /apis/extensions returns response with empty // APIVersion, we use stripVersionNegotiatedSerializer to keep the @@ -62,7 +59,6 @@ func NewAPIVersionHandler(serializer runtime.NegotiatedSerializer, groupVersion serializer: serializer, groupVersion: groupVersion, apiResourceLister: apiResourceLister, - contextMapper: contextMapper, } } @@ -82,12 +78,6 @@ func (s *APIVersionHandler) handle(req *restful.Request, resp *restful.Response) } func (s *APIVersionHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - ctx, ok := s.contextMapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } - - responsewriters.WriteObjectNegotiated(ctx, s.serializer, schema.GroupVersion{}, w, req, http.StatusOK, + responsewriters.WriteObjectNegotiated(s.serializer, schema.GroupVersion{}, w, req, http.StatusOK, &metav1.APIResourceList{GroupVersion: s.groupVersion.String(), APIResources: s.apiResourceLister.ListAPIResources()}) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/BUILD index 98dbb32b7..9dde2cc72 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/BUILD @@ -20,6 +20,7 @@ go_test( embed = [":go_default_library"], deps = [ "//vendor/github.com/pborman/uuid:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -33,7 +34,6 @@ go_test( "//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/audit.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/audit.go index 6b72bfb32..494634107 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/audit.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/audit.go @@ -38,17 +38,18 @@ import ( // requests coming to the server. Audit level is decided according to requests' // attributes and audit policy. Logs are emitted to the audit sink to // process events. If sink or audit policy is nil, no decoration takes place. -func WithAudit(handler http.Handler, requestContextMapper request.RequestContextMapper, sink audit.Sink, policy policy.Checker, longRunningCheck request.LongRunningRequestCheck) http.Handler { +func WithAudit(handler http.Handler, sink audit.Sink, policy policy.Checker, longRunningCheck request.LongRunningRequestCheck) http.Handler { if sink == nil || policy == nil { return handler } return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ctx, ev, omitStages, err := createAuditEventAndAttachToContext(requestContextMapper, req, policy) + req, ev, omitStages, err := createAuditEventAndAttachToContext(req, policy) if err != nil { utilruntime.HandleError(fmt.Errorf("failed to create audit event: %v", err)) responsewriters.InternalError(w, req, errors.New("failed to create audit event")) return } + ctx := req.Context() if ev == nil || ctx == nil { handler.ServeHTTP(w, req) return @@ -111,35 +112,29 @@ func WithAudit(handler http.Handler, requestContextMapper request.RequestContext // - context with audit event attached to it // - created audit event // - error if anything bad happened -func createAuditEventAndAttachToContext(requestContextMapper request.RequestContextMapper, req *http.Request, policy policy.Checker) (request.Context, *auditinternal.Event, []auditinternal.Stage, error) { - ctx, ok := requestContextMapper.Get(req) - if !ok { - return nil, nil, nil, fmt.Errorf("no context found for request") - } +func createAuditEventAndAttachToContext(req *http.Request, policy policy.Checker) (*http.Request, *auditinternal.Event, []auditinternal.Stage, error) { + ctx := req.Context() attribs, err := GetAuthorizerAttributes(ctx) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to GetAuthorizerAttributes: %v", err) + return req, nil, nil, fmt.Errorf("failed to GetAuthorizerAttributes: %v", err) } level, omitStages := policy.LevelAndStages(attribs) audit.ObservePolicyLevel(level) if level == auditinternal.LevelNone { // Don't audit. - return nil, nil, nil, nil + return req, nil, nil, nil } ev, err := audit.NewEventFromRequest(req, level, attribs) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to complete audit event from request: %v", err) + return req, nil, nil, fmt.Errorf("failed to complete audit event from request: %v", err) } - ctx = request.WithAuditEvent(ctx, ev) - if err := requestContextMapper.Update(req, ctx); err != nil { - return nil, nil, nil, fmt.Errorf("failed to attach audit event to context: %v", err) - } + req = req.WithContext(request.WithAuditEvent(ctx, ev)) - return ctx, ev, omitStages, nil + return req, ev, omitStages, nil } func processAuditEvent(sink audit.Sink, ev *auditinternal.Event, omitStages []auditinternal.Stage) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/audit_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/audit_test.go index a7c1486a7..e536b215d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/audit_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/audit_test.go @@ -667,14 +667,13 @@ func TestAudit(t *testing.T) { t.Run(test.desc, func(t *testing.T) { sink := &fakeAuditSink{} policyChecker := policy.FakeChecker(auditinternal.LevelRequestResponse, test.omitStages) - handler := WithAudit(http.HandlerFunc(test.handler), &fakeRequestContextMapper{ - user: &user.DefaultInfo{Name: "admin"}, - }, sink, policyChecker, func(r *http.Request, ri *request.RequestInfo) bool { + handler := WithAudit(http.HandlerFunc(test.handler), sink, policyChecker, func(r *http.Request, ri *request.RequestInfo) bool { // simplified long-running check return ri.Verb == "watch" }) req, _ := http.NewRequest(test.verb, test.path, nil) + req = withTestContext(req, &user.DefaultInfo{Name: "admin"}, nil) if test.auditID != "" { req.Header.Add("Audit-ID", test.auditID) } @@ -735,33 +734,11 @@ func TestAudit(t *testing.T) { } } -type fakeRequestContextMapper struct { - user *user.DefaultInfo -} - -func (m *fakeRequestContextMapper) Get(req *http.Request) (request.Context, bool) { - ctx := request.NewContext() - if m.user != nil { - ctx = request.WithUser(ctx, m.user) - } - - resolver := newTestRequestInfoResolver() - info, err := resolver.NewRequestInfo(req) - if err == nil { - ctx = request.WithRequestInfo(ctx, info) - } - - return ctx, true -} - -func (*fakeRequestContextMapper) Update(req *http.Request, context request.Context) error { - return nil -} - func TestAuditNoPanicOnNilUser(t *testing.T) { policyChecker := policy.FakeChecker(auditinternal.LevelRequestResponse, nil) - handler := WithAudit(&fakeHTTPHandler{}, &fakeRequestContextMapper{}, &fakeAuditSink{}, policyChecker, nil) + handler := WithAudit(&fakeHTTPHandler{}, &fakeAuditSink{}, policyChecker, nil) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) + req = withTestContext(req, nil, nil) req.RemoteAddr = "127.0.0.1" handler.ServeHTTP(httptest.NewRecorder(), req) } @@ -773,12 +750,11 @@ func TestAuditLevelNone(t *testing.T) { w.WriteHeader(200) }) policyChecker := policy.FakeChecker(auditinternal.LevelNone, nil) - handler = WithAudit(handler, &fakeRequestContextMapper{ - user: &user.DefaultInfo{Name: "admin"}, - }, sink, policyChecker, nil) + handler = WithAudit(handler, sink, policyChecker, nil) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) req.RemoteAddr = "127.0.0.1" + req = withTestContext(req, &user.DefaultInfo{Name: "admin"}, nil) handler.ServeHTTP(httptest.NewRecorder(), req) if len(sink.events) > 0 { @@ -824,12 +800,11 @@ func TestAuditIDHttpHeader(t *testing.T) { w.WriteHeader(200) }) policyChecker := policy.FakeChecker(test.level, nil) - handler = WithAudit(handler, &fakeRequestContextMapper{ - user: &user.DefaultInfo{Name: "admin"}, - }, sink, policyChecker, nil) + handler = WithAudit(handler, sink, policyChecker, nil) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) req.RemoteAddr = "127.0.0.1" + req = withTestContext(req, &user.DefaultInfo{Name: "admin"}, nil) if test.requestHeader != "" { req.Header.Add("Audit-ID", test.requestHeader) } @@ -853,3 +828,17 @@ func TestAuditIDHttpHeader(t *testing.T) { } } } + +func withTestContext(req *http.Request, user user.Info, audit *auditinternal.Event) *http.Request { + ctx := req.Context() + if user != nil { + ctx = request.WithUser(ctx, user) + } + if audit != nil { + ctx = request.WithAuditEvent(ctx, audit) + } + if info, err := newTestRequestInfoResolver().NewRequestInfo(req); err == nil { + ctx = request.WithRequestInfo(ctx, info) + } + return req.WithContext(ctx) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go index d07bab317..ba53fc609 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go @@ -50,47 +50,38 @@ func init() { // stores any such user found onto the provided context for the request. If authentication fails or returns an error // the failed handler is used. On success, "Authorization" header is removed from the request and handler // is invoked to serve the request. -func WithAuthentication(handler http.Handler, mapper genericapirequest.RequestContextMapper, auth authenticator.Request, failed http.Handler) http.Handler { +func WithAuthentication(handler http.Handler, auth authenticator.Request, failed http.Handler) http.Handler { if auth == nil { glog.Warningf("Authentication is disabled") return handler } - return genericapirequest.WithRequestContext( - http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - user, ok, err := auth.AuthenticateRequest(req) - if err != nil || !ok { - if err != nil { - glog.Errorf("Unable to authenticate the request due to an error: %v", err) - } - failed.ServeHTTP(w, req) - return + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + user, ok, err := auth.AuthenticateRequest(req) + if err != nil || !ok { + if err != nil { + glog.Errorf("Unable to authenticate the request due to an error: %v", err) } + failed.ServeHTTP(w, req) + return + } - // authorization header is not required anymore in case of a successful authentication. - req.Header.Del("Authorization") + // authorization header is not required anymore in case of a successful authentication. + req.Header.Del("Authorization") - if ctx, ok := mapper.Get(req); ok { - mapper.Update(req, genericapirequest.WithUser(ctx, user)) - } + req = req.WithContext(genericapirequest.WithUser(req.Context(), user)) - authenticatedUserCounter.WithLabelValues(compressUsername(user.GetName())).Inc() + authenticatedUserCounter.WithLabelValues(compressUsername(user.GetName())).Inc() - handler.ServeHTTP(w, req) - }), - mapper, - ) + handler.ServeHTTP(w, req) + }) } -func Unauthorized(requestContextMapper genericapirequest.RequestContextMapper, s runtime.NegotiatedSerializer, supportsBasicAuth bool) http.Handler { +func Unauthorized(s runtime.NegotiatedSerializer, supportsBasicAuth bool) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if supportsBasicAuth { w.Header().Set("WWW-Authenticate", `Basic realm="kubernetes-master"`) } - ctx, ok := requestContextMapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } + ctx := req.Context() requestInfo, found := genericapirequest.RequestInfoFrom(ctx) if !found { responsewriters.InternalError(w, req, errors.New("no RequestInfo found in the context")) @@ -98,7 +89,7 @@ func Unauthorized(requestContextMapper genericapirequest.RequestContextMapper, s } gv := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} - responsewriters.ErrorNegotiated(ctx, apierrors.NewUnauthorized("Unauthorized"), s, gv, w, req) + responsewriters.ErrorNegotiated(apierrors.NewUnauthorized("Unauthorized"), s, gv, w, req) }) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication_test.go index eae3f86c2..342ed6b95 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication_test.go @@ -29,13 +29,9 @@ import ( func TestAuthenticateRequest(t *testing.T) { success := make(chan struct{}) - contextMapper := genericapirequest.NewRequestContextMapper() auth := WithAuthentication( http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) { - ctx, ok := contextMapper.Get(req) - if ctx == nil || !ok { - t.Errorf("no context stored on contextMapper: %#v", contextMapper) - } + ctx := req.Context() user, ok := genericapirequest.UserFrom(ctx) if user == nil || !ok { t.Errorf("no user stored in context: %#v", ctx) @@ -45,7 +41,6 @@ func TestAuthenticateRequest(t *testing.T) { } close(success) }), - contextMapper, authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { if req.Header.Get("Authorization") == "Something" { return &user.DefaultInfo{Name: "user"}, true, nil @@ -60,23 +55,14 @@ func TestAuthenticateRequest(t *testing.T) { auth.ServeHTTP(httptest.NewRecorder(), &http.Request{Header: map[string][]string{"Authorization": {"Something"}}}) <-success - empty, err := genericapirequest.IsEmpty(contextMapper) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !empty { - t.Fatalf("contextMapper should have no stored requests: %v", contextMapper) - } } func TestAuthenticateRequestFailed(t *testing.T) { failed := make(chan struct{}) - contextMapper := genericapirequest.NewRequestContextMapper() auth := WithAuthentication( http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) { t.Errorf("unexpected call to handler") }), - contextMapper, authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { return nil, false, nil }), @@ -88,23 +74,14 @@ func TestAuthenticateRequestFailed(t *testing.T) { auth.ServeHTTP(httptest.NewRecorder(), &http.Request{}) <-failed - empty, err := genericapirequest.IsEmpty(contextMapper) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !empty { - t.Fatalf("contextMapper should have no stored requests: %v", contextMapper) - } } func TestAuthenticateRequestError(t *testing.T) { failed := make(chan struct{}) - contextMapper := genericapirequest.NewRequestContextMapper() auth := WithAuthentication( http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) { t.Errorf("unexpected call to handler") }), - contextMapper, authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { return nil, false, errors.New("failure") }), @@ -116,11 +93,4 @@ func TestAuthenticateRequestError(t *testing.T) { auth.ServeHTTP(httptest.NewRecorder(), &http.Request{}) <-failed - empty, err := genericapirequest.IsEmpty(contextMapper) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !empty { - t.Fatalf("contextMapper should have no stored requests: %v", contextMapper) - } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authn_audit.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authn_audit.go index 86aca9872..09d7db8cc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authn_audit.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authn_audit.go @@ -28,17 +28,16 @@ import ( "k8s.io/apiserver/pkg/audit" "k8s.io/apiserver/pkg/audit/policy" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" ) // WithFailedAuthenticationAudit decorates a failed http.Handler used in WithAuthentication handler. // It is meant to log only failed authentication requests. -func WithFailedAuthenticationAudit(failedHandler http.Handler, requestContextMapper request.RequestContextMapper, sink audit.Sink, policy policy.Checker) http.Handler { +func WithFailedAuthenticationAudit(failedHandler http.Handler, sink audit.Sink, policy policy.Checker) http.Handler { if sink == nil || policy == nil { return failedHandler } return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - _, ev, omitStages, err := createAuditEventAndAttachToContext(requestContextMapper, req, policy) + req, ev, omitStages, err := createAuditEventAndAttachToContext(req, policy) if err != nil { utilruntime.HandleError(fmt.Errorf("failed to create audit event: %v", err)) responsewriters.InternalError(w, req, errors.New("failed to create audit event")) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authn_audit_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authn_audit_test.go index a320a977d..05b004249 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authn_audit_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authn_audit_test.go @@ -35,9 +35,10 @@ func TestFailedAuthnAudit(t *testing.T) { http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) }), - &fakeRequestContextMapper{}, sink, policyChecker) + sink, policyChecker) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) req.RemoteAddr = "127.0.0.1" + req = withTestContext(req, nil, nil) req.SetBasicAuth("username", "password") handler.ServeHTTP(httptest.NewRecorder(), req) @@ -66,9 +67,10 @@ func TestFailedMultipleAuthnAudit(t *testing.T) { http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) }), - &fakeRequestContextMapper{}, sink, policyChecker) + sink, policyChecker) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) req.RemoteAddr = "127.0.0.1" + req = withTestContext(req, nil, nil) req.SetBasicAuth("username", "password") req.TLS = &tls.ConnectionState{PeerCertificates: []*x509.Certificate{{}}} handler.ServeHTTP(httptest.NewRecorder(), req) @@ -98,9 +100,10 @@ func TestFailedAuthnAuditWithoutAuthorization(t *testing.T) { http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) }), - &fakeRequestContextMapper{}, sink, policyChecker) + sink, policyChecker) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) req.RemoteAddr = "127.0.0.1" + req = withTestContext(req, nil, nil) handler.ServeHTTP(httptest.NewRecorder(), req) if len(sink.events) != 1 { @@ -128,9 +131,10 @@ func TestFailedAuthnAuditOmitted(t *testing.T) { http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) }), - &fakeRequestContextMapper{}, sink, policyChecker) + sink, policyChecker) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) req.RemoteAddr = "127.0.0.1" + req = withTestContext(req, nil, nil) handler.ServeHTTP(httptest.NewRecorder(), req) if len(sink.events) != 0 { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go index b4610dfce..4c9f140ca 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go @@ -17,29 +17,39 @@ limitations under the License. package filters import ( + "context" "errors" "net/http" "github.com/golang/glog" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/audit" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" "k8s.io/apiserver/pkg/endpoints/request" ) +const ( + // Annotation key names set in advanced audit + decisionAnnotationKey = "authorization.k8s.io/decision" + reasonAnnotationKey = "authorization.k8s.io/reason" + + // Annotation values set in advanced audit + decisionAllow = "allow" + decisionForbid = "forbid" + reasonError = "internal error" +) + // WithAuthorizationCheck passes all authorized requests on to handler, and returns a forbidden error otherwise. -func WithAuthorization(handler http.Handler, requestContextMapper request.RequestContextMapper, a authorizer.Authorizer, s runtime.NegotiatedSerializer) http.Handler { +func WithAuthorization(handler http.Handler, a authorizer.Authorizer, s runtime.NegotiatedSerializer) http.Handler { if a == nil { glog.Warningf("Authorization is disabled") return handler } return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ctx, ok := requestContextMapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } + ctx := req.Context() + ae := request.AuditEventFrom(ctx) attributes, err := GetAuthorizerAttributes(ctx) if err != nil { @@ -49,20 +59,25 @@ func WithAuthorization(handler http.Handler, requestContextMapper request.Reques authorized, reason, err := a.Authorize(attributes) // an authorizer like RBAC could encounter evaluation errors and still allow the request, so authorizer decision is checked before error here. if authorized == authorizer.DecisionAllow { + audit.LogAnnotation(ae, decisionAnnotationKey, decisionAllow) + audit.LogAnnotation(ae, reasonAnnotationKey, reason) handler.ServeHTTP(w, req) return } if err != nil { + audit.LogAnnotation(ae, reasonAnnotationKey, reasonError) responsewriters.InternalError(w, req, err) return } glog.V(4).Infof("Forbidden: %#v, Reason: %q", req.RequestURI, reason) + audit.LogAnnotation(ae, decisionAnnotationKey, decisionForbid) + audit.LogAnnotation(ae, reasonAnnotationKey, reason) responsewriters.Forbidden(ctx, attributes, w, req, reason, s) }) } -func GetAuthorizerAttributes(ctx request.Context) (authorizer.Attributes, error) { +func GetAuthorizerAttributes(ctx context.Context) (authorizer.Attributes, error) { attribs := authorizer.AttributesRecord{} user, ok := request.UserFrom(ctx) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization_test.go index 477e5d4e3..5b72cf944 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization_test.go @@ -23,15 +23,15 @@ import ( "reflect" "testing" + "github.com/stretchr/testify/assert" batch "k8s.io/api/batch/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + auditinternal "k8s.io/apiserver/pkg/apis/audit" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" ) func TestGetAuthorizerAttributes(t *testing.T) { - mapper := request.NewRequestContextMapper() - testcases := map[string]struct { Verb string Path string @@ -109,15 +109,10 @@ func TestGetAuthorizerAttributes(t *testing.T) { var attribs authorizer.Attributes var err error var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ctx, ok := mapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } + ctx := req.Context() attribs, err = GetAuthorizerAttributes(ctx) }) - handler = WithRequestInfo(handler, newTestRequestInfoResolver(), mapper) - handler = request.WithRequestContext(handler, mapper) + handler = WithRequestInfo(handler, newTestRequestInfoResolver()) handler.ServeHTTP(httptest.NewRecorder(), req) if err != nil { @@ -127,3 +122,65 @@ func TestGetAuthorizerAttributes(t *testing.T) { } } } + +type fakeAuthorizer struct { + decision authorizer.Decision + reason string + err error +} + +func (f fakeAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) { + return f.decision, f.reason, f.err +} + +func TestAuditAnnotation(t *testing.T) { + testcases := map[string]struct { + authorizer fakeAuthorizer + decisionAnnotation string + reasonAnnotation string + }{ + "decision allow": { + fakeAuthorizer{ + authorizer.DecisionAllow, + "RBAC: allowed to patch pod", + nil, + }, + "allow", + "RBAC: allowed to patch pod", + }, + "decision forbid": { + fakeAuthorizer{ + authorizer.DecisionDeny, + "RBAC: not allowed to patch pod", + nil, + }, + "forbid", + "RBAC: not allowed to patch pod", + }, + "error": { + fakeAuthorizer{ + authorizer.DecisionNoOpinion, + "", + errors.New("can't parse user info"), + }, + "", + reasonError, + }, + } + + scheme := runtime.NewScheme() + negotiatedSerializer := serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)} + for k, tc := range testcases { + audit := &auditinternal.Event{Level: auditinternal.LevelMetadata} + handler := WithAuthorization(&fakeHTTPHandler{}, tc.authorizer, negotiatedSerializer) + // TODO: fake audit injector + + req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) + req = withTestContext(req, nil, audit) + req.RemoteAddr = "127.0.0.1" + handler.ServeHTTP(httptest.NewRecorder(), req) + assert.Equal(t, tc.decisionAnnotation, audit.Annotations[decisionAnnotationKey], k+": unexpected decision annotation") + assert.Equal(t, tc.reasonAnnotation, audit.Annotations[reasonAnnotationKey], k+": unexpected reason annotation") + } + +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go index 9af292e1c..726cbe4d5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "net/http" + "net/url" "strings" "github.com/golang/glog" @@ -37,7 +38,7 @@ import ( ) // WithImpersonation is a filter that will inspect and check requests that attempt to change the user.Info for their requests -func WithImpersonation(handler http.Handler, requestContextMapper request.RequestContextMapper, a authorizer.Authorizer, s runtime.NegotiatedSerializer) http.Handler { +func WithImpersonation(handler http.Handler, a authorizer.Authorizer, s runtime.NegotiatedSerializer) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { impersonationRequests, err := buildImpersonationRequests(req.Header) if err != nil { @@ -50,11 +51,7 @@ func WithImpersonation(handler http.Handler, requestContextMapper request.Reques return } - ctx, exists := requestContextMapper.Get(req) - if !exists { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } + ctx := req.Context() requestor, exists := request.UserFrom(ctx) if !exists { responsewriters.InternalError(w, req, errors.New("no user found for request")) @@ -129,7 +126,7 @@ func WithImpersonation(handler http.Handler, requestContextMapper request.Reques Groups: groups, Extra: userExtra, } - requestContextMapper.Update(req, request.WithUser(ctx, newUser)) + req = req.WithContext(request.WithUser(ctx, newUser)) oldUser, _ := request.UserFrom(ctx) httplog.LogOf(req, w).Addf("%v is acting as %v", oldUser, newUser) @@ -150,6 +147,14 @@ func WithImpersonation(handler http.Handler, requestContextMapper request.Reques }) } +func unescapeExtraKey(encodedKey string) string { + key, err := url.PathUnescape(encodedKey) // Decode %-encoded bytes. + if err != nil { + return encodedKey // Always record extra strings, even if malformed/unencoded. + } + return key +} + // buildImpersonationRequests returns a list of objectreferences that represent the different things we're requesting to impersonate. // Also includes a map[string][]string representing user.Info.Extra // Each request must be authorized against the current user before switching contexts. @@ -179,7 +184,7 @@ func buildImpersonationRequests(headers http.Header) ([]v1.ObjectReference, erro } hasUserExtra = true - extraKey := strings.ToLower(headerName[len(authenticationv1.ImpersonateUserExtraHeaderPrefix):]) + extraKey := unescapeExtraKey(strings.ToLower(headerName[len(authenticationv1.ImpersonateUserExtraHeaderPrefix):])) // make a separate request for each extra value they're trying to set for _, value := range values { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go index 814de2a26..d309a2109 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go @@ -17,6 +17,7 @@ limitations under the License. package filters import ( + "context" "fmt" "net/http" "net/http/httptest" @@ -69,6 +70,10 @@ func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (authorized auth return authorizer.DecisionAllow, "", nil } + if len(user.GetGroups()) > 1 && (user.GetGroups()[1] == "escaped-scopes" || user.GetGroups()[1] == "almost-escaped-scopes") { + return authorizer.DecisionAllow, "", nil + } + if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-particular-scopes" && a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "scopes" && a.GetName() == "scope-a" { return authorizer.DecisionAllow, "", nil @@ -223,6 +228,36 @@ func TestImpersonationFilter(t *testing.T) { }, expectedCode: http.StatusOK, }, + { + name: "percent-escaped-userextras", + user: &user.DefaultInfo{ + Name: "dev", + Groups: []string{"wheel", "escaped-scopes"}, + }, + impersonationUser: "system:admin", + impersonationUserExtras: map[string][]string{"example.com%2fescaped%e1%9b%84scopes": {"scope-a", "scope-b"}}, + expectedUser: &user.DefaultInfo{ + Name: "system:admin", + Groups: []string{"system:authenticated"}, + Extra: map[string][]string{"example.com/escapedᛄscopes": {"scope-a", "scope-b"}}, + }, + expectedCode: http.StatusOK, + }, + { + name: "almost-percent-escaped-userextras", + user: &user.DefaultInfo{ + Name: "dev", + Groups: []string{"wheel", "almost-escaped-scopes"}, + }, + impersonationUser: "system:admin", + impersonationUserExtras: map[string][]string{"almost%zzpercent%xxencoded": {"scope-a", "scope-b"}}, + expectedUser: &user.DefaultInfo{ + Name: "system:admin", + Groups: []string{"system:authenticated"}, + Extra: map[string][]string{"almost%zzpercent%xxencoded": {"scope-a", "scope-b"}}, + }, + expectedCode: http.StatusOK, + }, { name: "allowed-users-impersonation", user: &user.DefaultInfo{ @@ -308,13 +343,12 @@ func TestImpersonationFilter(t *testing.T) { }, } - requestContextMapper := request.NewRequestContextMapper() - var ctx request.Context + var ctx context.Context var actualUser user.Info var lock sync.Mutex doNothingHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - currentCtx, _ := requestContextMapper.Get(req) + currentCtx := req.Context() user, exists := request.UserFrom(currentCtx) if !exists { actualUser = nil @@ -345,8 +379,8 @@ func TestImpersonationFilter(t *testing.T) { }() lock.Lock() defer lock.Unlock() - requestContextMapper.Update(req, ctx) - currentCtx, _ := requestContextMapper.Get(req) + req = req.WithContext(ctx) + currentCtx := req.Context() user, exists := request.UserFrom(currentCtx) if !exists { @@ -358,8 +392,7 @@ func TestImpersonationFilter(t *testing.T) { delegate.ServeHTTP(w, req) }) - }(WithImpersonation(doNothingHandler, requestContextMapper, impersonateAuthorizer{}, serializer.NewCodecFactory(runtime.NewScheme()))) - handler = request.WithRequestContext(handler, requestContextMapper) + }(WithImpersonation(doNothingHandler, impersonateAuthorizer{}, serializer.NewCodecFactory(runtime.NewScheme()))) server := httptest.NewServer(handler) defer server.Close() diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/legacy_audit.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/legacy_audit.go index 983b8822a..bdf13c58e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/legacy_audit.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/legacy_audit.go @@ -18,7 +18,6 @@ package filters import ( "bufio" - "errors" "fmt" "io" "net" @@ -32,7 +31,6 @@ import ( authenticationapi "k8s.io/api/authentication/v1" utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" ) var _ http.ResponseWriter = &legacyAuditResponseWriter{} @@ -96,16 +94,12 @@ var _ http.Hijacker = &fancyLegacyResponseWriterDelegator{} // 2. the response line containing: // - the unique id from 1 // - response code -func WithLegacyAudit(handler http.Handler, requestContextMapper request.RequestContextMapper, out io.Writer) http.Handler { +func WithLegacyAudit(handler http.Handler, out io.Writer) http.Handler { if out == nil { return handler } return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ctx, ok := requestContextMapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } + ctx := req.Context() attribs, err := GetAuthorizerAttributes(ctx) if err != nil { responsewriters.InternalError(w, req, err) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/legacy_audit_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/legacy_audit_test.go index 7a833a28e..9e1e1ee1e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/legacy_audit_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/legacy_audit_test.go @@ -48,12 +48,11 @@ func TestLegacyConstructResponseWriter(t *testing.T) { func TestLegacyAudit(t *testing.T) { var buf bytes.Buffer - handler := WithLegacyAudit(&fakeHTTPHandler{}, &fakeRequestContextMapper{ - user: &user.DefaultInfo{Name: "admin"}, - }, &buf) + handler := WithLegacyAudit(&fakeHTTPHandler{}, &buf) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) req.RemoteAddr = "127.0.0.1" + req = withTestContext(req, &user.DefaultInfo{Name: "admin"}, nil) handler.ServeHTTP(httptest.NewRecorder(), req) line := strings.Split(strings.TrimSpace(buf.String()), "\n") if len(line) != 2 { @@ -78,10 +77,11 @@ func TestLegacyAudit(t *testing.T) { func TestLegacyAuditNoPanicOnNilUser(t *testing.T) { var buf bytes.Buffer - handler := WithLegacyAudit(&fakeHTTPHandler{}, &fakeRequestContextMapper{}, &buf) + handler := WithLegacyAudit(&fakeHTTPHandler{}, &buf) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) req.RemoteAddr = "127.0.0.1" + req = withTestContext(req, nil, nil) handler.ServeHTTP(httptest.NewRecorder(), req) line := strings.Split(strings.TrimSpace(buf.String()), "\n") if len(line) != 2 { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/requestinfo.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/requestinfo.go index 4c79a8a28..9cc524d4e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/requestinfo.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/filters/requestinfo.go @@ -17,7 +17,6 @@ limitations under the License. package filters import ( - "errors" "fmt" "net/http" @@ -26,21 +25,16 @@ import ( ) // WithRequestInfo attaches a RequestInfo to the context. -func WithRequestInfo(handler http.Handler, resolver request.RequestInfoResolver, requestContextMapper request.RequestContextMapper) http.Handler { +func WithRequestInfo(handler http.Handler, resolver request.RequestInfoResolver) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ctx, ok := requestContextMapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } - + ctx := req.Context() info, err := resolver.NewRequestInfo(req) if err != nil { responsewriters.InternalError(w, req, fmt.Errorf("failed to create RequestInfo: %v", err)) return } - requestContextMapper.Update(req, request.WithRequestInfo(ctx, info)) + req = req.WithContext(request.WithRequestInfo(ctx, info)) handler.ServeHTTP(w, req) }) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/groupversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/groupversion.go index 4b8823758..23d13adc3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/groupversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/groupversion.go @@ -22,15 +22,15 @@ import ( "github.com/emicklei/go-restful" - "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" utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/endpoints/discovery" - "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" + openapicommon "k8s.io/kube-openapi/pkg/common" ) // APIGroupVersion is a helper for exposing rest.Storage objects as http.Handlers via go-restful @@ -56,7 +56,8 @@ type APIGroupVersion struct { // version (for when the inevitable meta/v2 group emerges). MetaGroupVersion *schema.GroupVersion - Mapper meta.RESTMapper + // RootScopedKinds are the root scoped kinds for the primary GroupVersion + RootScopedKinds sets.String // Serializer is used to determine how to convert responses from API methods into bytes to send over // the wire. @@ -70,14 +71,16 @@ type APIGroupVersion struct { Linker runtime.SelfLinker UnsafeConvertor runtime.ObjectConvertor - Admit admission.Interface - Context request.RequestContextMapper + Admit admission.Interface MinRequestTimeout time.Duration // EnableAPIResponseCompression indicates whether API Responses should support compression // if the client requests it via Accept-Encoding EnableAPIResponseCompression bool + + // OpenAPIConfig lets the individual handlers build a subset of the OpenAPI schema before they are installed. + OpenAPIConfig *openapicommon.Config } // InstallREST registers the REST handlers (storage, watch, proxy and redirect) into a restful Container. @@ -93,7 +96,7 @@ func (g *APIGroupVersion) InstallREST(container *restful.Container) error { } apiResources, ws, registrationErrors := installer.Install() - versionDiscoveryHandler := discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, staticLister{apiResources}, g.Context) + versionDiscoveryHandler := discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, staticLister{apiResources}) versionDiscoveryHandler.AddToWebService(ws) container.Add(ws) return utilerrors.NewAggregate(registrationErrors) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/BUILD index bb30cf273..55871a7c7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/BUILD @@ -80,6 +80,7 @@ go_library( "//vendor/k8s.io/apiserver/pkg/server/httplog:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/trace:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/wsstream:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go index 1d474267d..542760078 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go @@ -17,6 +17,7 @@ limitations under the License. package handlers import ( + "context" "fmt" "net/http" "time" @@ -34,12 +35,17 @@ import ( utiltrace "k8s.io/apiserver/pkg/util/trace" ) -func createHandler(r rest.NamedCreater, scope RequestScope, typer runtime.ObjectTyper, admit admission.Interface, includeName bool) http.HandlerFunc { +func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Interface, includeName bool) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { // For performance tracking purposes. trace := utiltrace.New("Create " + req.URL.Path) defer trace.LogIfLong(500 * time.Millisecond) + if isDryRun(req.URL) { + scope.err(errors.NewBadRequest("dryRun is not supported yet"), w, req) + return + } + // TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer) timeout := parseTimeout(req.URL.Query().Get("timeout")) @@ -57,7 +63,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, typer runtime.Object return } - ctx := scope.ContextFunc(req) + ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) gv := scope.Kind.GroupVersion() @@ -79,7 +85,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, typer runtime.Object trace.Step("About to convert to expected version") obj, gvk, err := decoder.Decode(body, &defaultGVK, original) if err != nil { - err = transformDecodeError(typer, err, original, gvk, body) + err = transformDecodeError(scope.Typer, err, original, gvk, body) scope.err(err, w, req) return } @@ -91,6 +97,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, typer runtime.Object trace.Step("Conversion done") ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) audit.LogRequestObject(ae, obj, scope.Resource, scope.Subresource, scope.Serializer) userInfo, _ := request.UserFrom(ctx) @@ -150,19 +157,19 @@ func createHandler(r rest.NamedCreater, scope RequestScope, typer runtime.Object } // CreateNamedResource returns a function that will handle a resource creation with name. -func CreateNamedResource(r rest.NamedCreater, scope RequestScope, typer runtime.ObjectTyper, admission admission.Interface) http.HandlerFunc { - return createHandler(r, scope, typer, admission, true) +func CreateNamedResource(r rest.NamedCreater, scope RequestScope, admission admission.Interface) http.HandlerFunc { + return createHandler(r, scope, admission, true) } // CreateResource returns a function that will handle a resource creation. -func CreateResource(r rest.Creater, scope RequestScope, typer runtime.ObjectTyper, admission admission.Interface) http.HandlerFunc { - return createHandler(&namedCreaterAdapter{r}, scope, typer, admission, false) +func CreateResource(r rest.Creater, scope RequestScope, admission admission.Interface) http.HandlerFunc { + return createHandler(&namedCreaterAdapter{r}, scope, admission, false) } type namedCreaterAdapter struct { rest.Creater } -func (c *namedCreaterAdapter) Create(ctx request.Context, name string, obj runtime.Object, createValidatingAdmission rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (c *namedCreaterAdapter) Create(ctx context.Context, name string, obj runtime.Object, createValidatingAdmission rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { return c.Creater.Create(ctx, obj, createValidatingAdmission, includeUninitialized) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go index b8ac281fa..03576d72a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go @@ -41,6 +41,11 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco trace := utiltrace.New("Delete " + req.URL.Path) defer trace.LogIfLong(500 * time.Millisecond) + if isDryRun(req.URL) { + scope.err(errors.NewBadRequest("dryRun is not supported yet"), w, req) + return + } + // TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer) timeout := parseTimeout(req.URL.Query().Get("timeout")) @@ -49,8 +54,10 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco scope.err(err, w, req) return } - ctx := scope.ContextFunc(req) + ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) options := &metav1.DeleteOptions{} if allowsOptions { @@ -167,6 +174,11 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco // DeleteCollection returns a function that will handle a collection deletion func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestScope, admit admission.Interface) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { + if isDryRun(req.URL) { + scope.err(errors.NewBadRequest("dryRun is not supported yet"), w, req) + return + } + // TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer) timeout := parseTimeout(req.URL.Query().Get("timeout")) @@ -176,26 +188,28 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco return } - ctx := scope.ContextFunc(req) + ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) - if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Delete) { + if admit != nil && admit.Handles(admission.Delete) { userInfo, _ := request.UserFrom(ctx) - - err = mutatingAdmission.Admit(admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, "", scope.Resource, scope.Subresource, admission.Delete, userInfo)) - if err != nil { - scope.err(err, w, req) - return + attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, "", scope.Resource, scope.Subresource, admission.Delete, userInfo) + if mutatingAdmission, ok := admit.(admission.MutationInterface); ok { + err = mutatingAdmission.Admit(attrs) + if err != nil { + scope.err(err, w, req) + return + } } - } - // TODO: avoid calling Handles twice - if validatingAdmission, ok := admit.(admission.ValidationInterface); ok && validatingAdmission.Handles(admission.Delete) { - userInfo, _ := request.UserFrom(ctx) - err = validatingAdmission.Validate(admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, "", scope.Resource, scope.Subresource, admission.Delete, userInfo)) - if err != nil { - scope.err(err, w, req) - return + if validatingAdmission, ok := admit.(admission.ValidationInterface); ok { + err = validatingAdmission.Validate(attrs) + if err != nil { + scope.err(err, w, req) + return + } } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go index 7461ece64..767285938 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go @@ -17,6 +17,7 @@ limitations under the License. package handlers import ( + "context" "fmt" "math/rand" "net/http" @@ -40,7 +41,7 @@ import ( // getterFunc performs a get request with the given context and object name. The request // may be used to deserialize an options object to pass to the getter. -type getterFunc func(ctx request.Context, name string, req *http.Request, trace *utiltrace.Trace) (runtime.Object, error) +type getterFunc func(ctx context.Context, name string, req *http.Request, trace *utiltrace.Trace) (runtime.Object, error) // getResourceHandler is an HTTP handler function for get requests. It delegates to the // passed-in getterFunc to perform the actual get. @@ -54,7 +55,7 @@ func getResourceHandler(scope RequestScope, getter getterFunc) http.HandlerFunc scope.err(err, w, req) return } - ctx := scope.ContextFunc(req) + ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) result, err := getter(ctx, name, req, trace) @@ -80,7 +81,7 @@ func getResourceHandler(scope RequestScope, getter getterFunc) http.HandlerFunc // GetResource returns a function that handles retrieving a single resource from a rest.Storage object. func GetResource(r rest.Getter, e rest.Exporter, scope RequestScope) http.HandlerFunc { return getResourceHandler(scope, - func(ctx request.Context, name string, req *http.Request, trace *utiltrace.Trace) (runtime.Object, error) { + func(ctx context.Context, name string, req *http.Request, trace *utiltrace.Trace) (runtime.Object, error) { // check for export options := metav1.GetOptions{} if values := req.URL.Query(); len(values) > 0 { @@ -110,7 +111,7 @@ func GetResource(r rest.Getter, e rest.Exporter, scope RequestScope) http.Handle // GetResourceWithOptions returns a function that handles retrieving a single resource from a rest.Storage object. func GetResourceWithOptions(r rest.GetterWithOptions, scope RequestScope, isSubresource bool) http.HandlerFunc { return getResourceHandler(scope, - func(ctx request.Context, name string, req *http.Request, trace *utiltrace.Trace) (runtime.Object, error) { + func(ctx context.Context, name string, req *http.Request, trace *utiltrace.Trace) (runtime.Object, error) { opts, subpath, subpathKey := r.NewGetOptions() trace.Step("About to process Get options") if err := getRequestOptions(req, scope, opts, subpath, subpathKey, isSubresource); err != nil { @@ -137,7 +138,7 @@ func getRequestOptions(req *http.Request, scope RequestScope, into runtime.Objec newQuery[k] = v } - ctx := scope.ContextFunc(req) + ctx := req.Context() requestInfo, _ := request.RequestInfoFrom(ctx) startingIndex := 2 if isSubresource { @@ -181,7 +182,7 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch hasName = false } - ctx := scope.ContextFunc(req) + ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) opts := metainternalversion.ListOptions{} @@ -207,19 +208,25 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch if hasName { // metadata.name is the canonical internal name. - // SelectionPredicate will notice that this is - // a request for a single object and optimize the - // storage query accordingly. + // SelectionPredicate will notice that this is a request for + // a single object and optimize the storage query accordingly. nameSelector := fields.OneTermEqualSelector("metadata.name", name) + + // Note that fieldSelector setting explicitly the "metadata.name" + // will result in reaching this branch (as the value of that field + // is propagated to requestInfo as the name parameter. + // That said, the allowed field selectors in this branch are: + // nil, fields.Everything and field selector matching metadata.name + // for our name. if opts.FieldSelector != nil && !opts.FieldSelector.Empty() { - // It doesn't make sense to ask for both a name - // and a field selector, since just the name is - // sufficient to narrow down the request to a - // single object. - scope.err(errors.NewBadRequest("both a name and a field selector provided; please provide one or the other."), w, req) - return + selectedName, ok := opts.FieldSelector.RequiresExactMatch("metadata.name") + if !ok || name != selectedName { + scope.err(errors.NewBadRequest("fieldSelector metadata.name doesn't match requested name"), w, req) + return + } + } else { + opts.FieldSelector = nameSelector } - opts.FieldSelector = nameSelector } if opts.Watch || forceWatch { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/namer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/namer.go index 8e7a4ef33..16b4199c2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/namer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/namer.go @@ -26,9 +26,6 @@ import ( "k8s.io/apiserver/pkg/endpoints/request" ) -// ContextFunc returns a Context given a request - a context must be returned -type ContextFunc func(req *http.Request) request.Context - // ScopeNamer handles accessing names from requests and objects type ScopeNamer interface { // Namespace returns the appropriate namespace value from the request (may be empty) or an @@ -51,7 +48,6 @@ type ScopeNamer interface { } type ContextBasedNaming struct { - GetContext ContextFunc SelfLinker runtime.SelfLinker ClusterScoped bool @@ -67,7 +63,7 @@ func (n ContextBasedNaming) SetSelfLink(obj runtime.Object, url string) error { } func (n ContextBasedNaming) Namespace(req *http.Request) (namespace string, err error) { - requestInfo, ok := request.RequestInfoFrom(n.GetContext(req)) + requestInfo, ok := request.RequestInfoFrom(req.Context()) if !ok { return "", fmt.Errorf("missing requestInfo") } @@ -75,7 +71,7 @@ func (n ContextBasedNaming) Namespace(req *http.Request) (namespace string, err } func (n ContextBasedNaming) Name(req *http.Request) (namespace, name string, err error) { - requestInfo, ok := request.RequestInfoFrom(n.GetContext(req)) + requestInfo, ok := request.RequestInfoFrom(req.Context()) if !ok { return "", "", fmt.Errorf("missing requestInfo") } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go index 00bebdd2d..0801dcef6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go @@ -17,16 +17,15 @@ limitations under the License. package handlers import ( + "context" "fmt" "net/http" "strings" "time" "github.com/evanphx/json-patch" - "github.com/golang/glog" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" @@ -42,14 +41,18 @@ import ( utiltrace "k8s.io/apiserver/pkg/util/trace" ) -// PatchResource returns a function that will handle a resource patch -// TODO: Eventually PatchResource should just use GuaranteedUpdate and this routine should be a bit cleaner -func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface, converter runtime.ObjectConvertor, patchTypes []string) http.HandlerFunc { +// PatchResource returns a function that will handle a resource patch. +func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface, patchTypes []string) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { // For performance tracking purposes. trace := utiltrace.New("Patch " + req.URL.Path) defer trace.LogIfLong(500 * time.Millisecond) + if isDryRun(req.URL) { + scope.err(errors.NewBadRequest("dryRun is not supported yet"), w, req) + return + } + // Do this first, otherwise name extraction can fail for unrecognized content types // TODO: handle this in negotiation contentType := req.Header.Get("Content-Type") @@ -76,15 +79,9 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface return } - ctx := scope.ContextFunc(req) + ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) - versionedObj, err := converter.ConvertToVersion(r.New(), scope.Kind.GroupVersion()) - if err != nil { - scope.err(err, w, req) - return - } - patchJS, err := readBody(req) if err != nil { scope.err(err, w, req) @@ -92,6 +89,8 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface } ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) + audit.LogRequestPatch(ae, patchJS) trace.Step("Recorded the audit event") @@ -108,24 +107,38 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface userInfo, _ := request.UserFrom(ctx) staticAdmissionAttributes := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, userInfo) - updateMutation := func(updatedObject runtime.Object, currentObject runtime.Object) error { + admissionCheck := func(updatedObject runtime.Object, currentObject runtime.Object) error { if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && admit.Handles(admission.Update) { return mutatingAdmission.Admit(admission.NewAttributesRecord(updatedObject, currentObject, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, userInfo)) } return nil } - result, err := patchResource( - ctx, - updateMutation, - rest.AdmissionToValidateObjectFunc(admit, staticAdmissionAttributes), - rest.AdmissionToValidateObjectUpdateFunc(admit, staticAdmissionAttributes), - timeout, versionedObj, - r, - name, - patchType, - patchJS, - scope.Namer, scope.Creater, scope.Defaulter, scope.UnsafeConvertor, scope.Kind, scope.Resource, codec, trace) + p := patcher{ + namer: scope.Namer, + creater: scope.Creater, + defaulter: scope.Defaulter, + unsafeConvertor: scope.UnsafeConvertor, + kind: scope.Kind, + resource: scope.Resource, + + createValidation: rest.AdmissionToValidateObjectFunc(admit, staticAdmissionAttributes), + updateValidation: rest.AdmissionToValidateObjectUpdateFunc(admit, staticAdmissionAttributes), + admissionCheck: admissionCheck, + + codec: codec, + + timeout: timeout, + + restPatcher: r, + name: name, + patchType: patchType, + patchJS: patchJS, + + trace: trace, + } + + result, err := p.patchResource(ctx) if err != nil { scope.err(err, w, req) return @@ -149,286 +162,124 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface type mutateObjectUpdateFunc func(obj, old runtime.Object) error -// patchResource divides PatchResource for easier unit testing -func patchResource( - ctx request.Context, - updateMutation mutateObjectUpdateFunc, - createValidation rest.ValidateObjectFunc, - updateValidation rest.ValidateObjectUpdateFunc, - timeout time.Duration, - versionedObj runtime.Object, - patcher rest.Patcher, - name string, - patchType types.PatchType, - patchJS []byte, - namer ScopeNamer, - creater runtime.ObjectCreater, - defaulter runtime.ObjectDefaulter, - unsafeConvertor runtime.ObjectConvertor, - kind schema.GroupVersionKind, - resource schema.GroupVersionResource, - codec runtime.Codec, - trace *utiltrace.Trace, -) (runtime.Object, error) { - - namespace := request.NamespaceValue(ctx) - - var ( - originalObjJS []byte - originalPatchedObjJS []byte - originalObjMap map[string]interface{} - getOriginalPatchMap func() (map[string]interface{}, error) - lastConflictErr error - originalResourceVersion string - ) - - // applyPatch is called every time GuaranteedUpdate asks for the updated object, - // and is given the currently persisted object as input. - applyPatch := func(_ request.Context, _, currentObject runtime.Object) (runtime.Object, error) { - // Make sure we actually have a persisted currentObject - trace.Step("About to apply patch") - if hasUID, err := hasUID(currentObject); err != nil { - return nil, err - } else if !hasUID { - return nil, errors.NewNotFound(resource.GroupResource(), name) - } - - currentResourceVersion := "" - if currentMetadata, err := meta.Accessor(currentObject); err == nil { - currentResourceVersion = currentMetadata.GetResourceVersion() - } - - switch { - case originalObjJS == nil && originalObjMap == nil: - // first time through, - // 1. apply the patch - // 2. save the original and patched to detect whether there were conflicting changes on retries - - originalResourceVersion = currentResourceVersion - objToUpdate := patcher.New() - - // For performance reasons, in case of strategicpatch, we avoid json - // marshaling and unmarshaling and operate just on map[string]interface{}. - // In case of other patch types, we still have to operate on JSON - // representations. - switch patchType { - case types.JSONPatchType, types.MergePatchType: - originalJS, patchedJS, err := patchObjectJSON(patchType, codec, currentObject, patchJS, objToUpdate, versionedObj) - if err != nil { - return nil, interpretPatchError(err) - } - originalObjJS, originalPatchedObjJS = originalJS, patchedJS - - // Make a getter that can return a fresh strategic patch map if needed for conflict retries - // We have to rebuild it each time we need it, because the map gets mutated when being applied - var originalPatchBytes []byte - getOriginalPatchMap = func() (map[string]interface{}, error) { - if originalPatchBytes == nil { - // Compute once - originalPatchBytes, err = strategicpatch.CreateTwoWayMergePatch(originalObjJS, originalPatchedObjJS, versionedObj) - if err != nil { - return nil, interpretPatchError(err) - } - } - // Return a fresh map every time - originalPatchMap := make(map[string]interface{}) - if err := json.Unmarshal(originalPatchBytes, &originalPatchMap); err != nil { - return nil, errors.NewBadRequest(err.Error()) - } - return originalPatchMap, nil - } - - case types.StrategicMergePatchType: - // Since the patch is applied on versioned objects, we need to convert the - // current object to versioned representation first. - currentVersionedObject, err := unsafeConvertor.ConvertToVersion(currentObject, kind.GroupVersion()) - if err != nil { - return nil, err - } - versionedObjToUpdate, err := creater.New(kind) - if err != nil { - return nil, err - } - // Capture the original object map and patch for possible retries. - originalMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(currentVersionedObject) - if err != nil { - return nil, err - } - if err := strategicPatchObject(codec, defaulter, currentVersionedObject, patchJS, versionedObjToUpdate, versionedObj); err != nil { - return nil, err - } - // Convert the object back to unversioned. - gvk := kind.GroupKind().WithVersion(runtime.APIVersionInternal) - unversionedObjToUpdate, err := unsafeConvertor.ConvertToVersion(versionedObjToUpdate, gvk.GroupVersion()) - if err != nil { - return nil, err - } - objToUpdate = unversionedObjToUpdate - // Store unstructured representation for possible retries. - originalObjMap = originalMap - // Make a getter that can return a fresh strategic patch map if needed for conflict retries - // We have to rebuild it each time we need it, because the map gets mutated when being applied - getOriginalPatchMap = func() (map[string]interface{}, error) { - patchMap := make(map[string]interface{}) - if err := json.Unmarshal(patchJS, &patchMap); err != nil { - return nil, errors.NewBadRequest(err.Error()) - } - return patchMap, nil - } - } - if err := checkName(objToUpdate, name, namespace, namer); err != nil { - return nil, err - } - return objToUpdate, nil - - default: - // on a conflict, - // 1. build a strategic merge patch from originalJS and the patchedJS. Different patch types can - // be specified, but a strategic merge patch should be expressive enough handle them. Build the - // patch with this type to handle those cases. - // 2. build a strategic merge patch from originalJS and the currentJS - // 3. ensure no conflicts between the two patches - // 4. apply the #1 patch to the currentJS object - - // Since the patch is applied on versioned objects, we need to convert the - // current object to versioned representation first. - currentVersionedObject, err := unsafeConvertor.ConvertToVersion(currentObject, kind.GroupVersion()) - if err != nil { - return nil, err - } - currentObjMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(currentVersionedObject) - if err != nil { - return nil, err - } - - var currentPatchMap map[string]interface{} - if originalObjMap != nil { - var err error - currentPatchMap, err = strategicpatch.CreateTwoWayMergeMapPatch(originalObjMap, currentObjMap, versionedObj) - if err != nil { - return nil, interpretPatchError(err) - } - } else { - // Compute current patch. - currentObjJS, err := runtime.Encode(codec, currentObject) - if err != nil { - return nil, err - } - currentPatch, err := strategicpatch.CreateTwoWayMergePatch(originalObjJS, currentObjJS, versionedObj) - if err != nil { - return nil, interpretPatchError(err) - } - currentPatchMap = make(map[string]interface{}) - if err := json.Unmarshal(currentPatch, ¤tPatchMap); err != nil { - return nil, errors.NewBadRequest(err.Error()) - } - } +// patcher breaks the process of patch application and retries into smaller +// pieces of functionality. +// TODO: Use builder pattern to construct this object? +// TODO: As part of that effort, some aspects of PatchResource above could be +// moved into this type. +type patcher struct { + // Pieces of RequestScope + namer ScopeNamer + creater runtime.ObjectCreater + defaulter runtime.ObjectDefaulter + unsafeConvertor runtime.ObjectConvertor + resource schema.GroupVersionResource + kind schema.GroupVersionKind + + // Validation functions + createValidation rest.ValidateObjectFunc + updateValidation rest.ValidateObjectUpdateFunc + admissionCheck mutateObjectUpdateFunc + + codec runtime.Codec + + timeout time.Duration + + // Operation information + restPatcher rest.Patcher + name string + patchType types.PatchType + patchJS []byte + + trace *utiltrace.Trace + + // Set at invocation-time (by applyPatch) and immutable thereafter + namespace string + updatedObjectInfo rest.UpdatedObjectInfo + mechanism patchMechanism +} - // Get a fresh copy of the original strategic patch each time through, since applying it mutates the map - originalPatchMap, err := getOriginalPatchMap() - if err != nil { - return nil, err - } +func (p *patcher) toUnversioned(versionedObj runtime.Object) (runtime.Object, error) { + gvk := p.kind.GroupKind().WithVersion(runtime.APIVersionInternal) + return p.unsafeConvertor.ConvertToVersion(versionedObj, gvk.GroupVersion()) +} - hasConflicts, err := mergepatch.HasConflicts(originalPatchMap, currentPatchMap) - if err != nil { - return nil, err - } +type patchMechanism interface { + applyPatchToCurrentObject(currentObject runtime.Object) (runtime.Object, error) +} - if hasConflicts { - diff1, _ := json.Marshal(currentPatchMap) - diff2, _ := json.Marshal(originalPatchMap) - patchDiffErr := fmt.Errorf("there is a meaningful conflict (firstResourceVersion: %q, currentResourceVersion: %q):\n diff1=%v\n, diff2=%v\n", originalResourceVersion, currentResourceVersion, string(diff1), string(diff2)) - glog.V(4).Infof("patchResource failed for resource %s, because there is a meaningful conflict(firstResourceVersion: %q, currentResourceVersion: %q):\n diff1=%v\n, diff2=%v\n", name, originalResourceVersion, currentResourceVersion, string(diff1), string(diff2)) - - // Return the last conflict error we got if we have one - if lastConflictErr != nil { - return nil, lastConflictErr - } - // Otherwise manufacture one of our own - return nil, errors.NewConflict(resource.GroupResource(), name, patchDiffErr) - } +type jsonPatcher struct { + *patcher +} - versionedObjToUpdate, err := creater.New(kind) - if err != nil { - return nil, err - } - if err := applyPatchToObject(codec, defaulter, currentObjMap, originalPatchMap, versionedObjToUpdate, versionedObj); err != nil { - return nil, err - } - // Convert the object back to unversioned. - gvk := kind.GroupKind().WithVersion(runtime.APIVersionInternal) - objToUpdate, err := unsafeConvertor.ConvertToVersion(versionedObjToUpdate, gvk.GroupVersion()) - if err != nil { - return nil, err - } +func (p *jsonPatcher) applyPatchToCurrentObject(currentObject runtime.Object) (runtime.Object, error) { + // Encode will convert & return a versioned object in JSON. + currentObjJS, err := runtime.Encode(p.codec, currentObject) + if err != nil { + return nil, err + } - return objToUpdate, nil - } + // Apply the patch. + patchedObjJS, err := p.applyJSPatch(currentObjJS) + if err != nil { + return nil, interpretPatchError(err) } - // applyAdmission is called every time GuaranteedUpdate asks for the updated object, - // and is given the currently persisted object and the patched object as input. - applyAdmission := func(ctx request.Context, patchedObject runtime.Object, currentObject runtime.Object) (runtime.Object, error) { - trace.Step("About to check admission control") - return patchedObject, updateMutation(patchedObject, currentObject) + // Construct the resulting typed, unversioned object. + objToUpdate := p.restPatcher.New() + if err := runtime.DecodeInto(p.codec, patchedObjJS, objToUpdate); err != nil { + return nil, err } - updatedObjectInfo := rest.DefaultUpdatedObjectInfo(nil, applyPatch, applyAdmission) - return finishRequest(timeout, func() (runtime.Object, error) { - updateObject, _, updateErr := patcher.Update(ctx, name, updatedObjectInfo, createValidation, updateValidation) - for i := 0; i < MaxRetryWhenPatchConflicts && (errors.IsConflict(updateErr)); i++ { - lastConflictErr = updateErr - updateObject, _, updateErr = patcher.Update(ctx, name, updatedObjectInfo, createValidation, updateValidation) - } - return updateObject, updateErr - }) + return objToUpdate, nil } -// patchObjectJSON patches the with and stores -// the result in . -// Currently it also returns the original and patched objects serialized to -// JSONs (this may not be needed once we can apply patches at the -// map[string]interface{} level). -func patchObjectJSON( - patchType types.PatchType, - codec runtime.Codec, - originalObject runtime.Object, - patchJS []byte, - objToUpdate runtime.Object, - versionedObj runtime.Object, -) (originalObjJS []byte, patchedObjJS []byte, retErr error) { - js, err := runtime.Encode(codec, originalObject) - if err != nil { - return nil, nil, err - } - originalObjJS = js - - switch patchType { +// patchJS applies the patch. Input and output objects must both have +// the external version, since that is what the patch must have been constructed against. +func (p *jsonPatcher) applyJSPatch(versionedJS []byte) (patchedJS []byte, retErr error) { + switch p.patchType { case types.JSONPatchType: - patchObj, err := jsonpatch.DecodePatch(patchJS) + patchObj, err := jsonpatch.DecodePatch(p.patchJS) if err != nil { - return nil, nil, err - } - if patchedObjJS, err = patchObj.Apply(originalObjJS); err != nil { - return nil, nil, err + return nil, err } + return patchObj.Apply(versionedJS) case types.MergePatchType: - if patchedObjJS, err = jsonpatch.MergePatch(originalObjJS, patchJS); err != nil { - return nil, nil, err - } - case types.StrategicMergePatchType: - if patchedObjJS, err = strategicpatch.StrategicMergePatch(originalObjJS, patchJS, versionedObj); err != nil { - return nil, nil, err - } + return jsonpatch.MergePatch(versionedJS, p.patchJS) default: // only here as a safety net - go-restful filters content-type - return nil, nil, fmt.Errorf("unknown Content-Type header for patch: %v", patchType) + return nil, fmt.Errorf("unknown Content-Type header for patch: %v", p.patchType) + } +} + +type smpPatcher struct { + *patcher + + // Schema + schemaReferenceObj runtime.Object +} + +func (p *smpPatcher) applyPatchToCurrentObject(currentObject runtime.Object) (runtime.Object, error) { + // Since the patch is applied on versioned objects, we need to convert the + // current object to versioned representation first. + currentVersionedObject, err := p.unsafeConvertor.ConvertToVersion(currentObject, p.kind.GroupVersion()) + if err != nil { + return nil, err + } + versionedObjToUpdate, err := p.creater.New(p.kind) + if err != nil { + return nil, err } - if err := runtime.DecodeInto(codec, patchedObjJS, objToUpdate); err != nil { - return nil, nil, err + if err := strategicPatchObject(p.codec, p.defaulter, currentVersionedObject, p.patchJS, versionedObjToUpdate, p.schemaReferenceObj); err != nil { + return nil, err } - return + // Convert the object back to unversioned (aka internal version). + unversionedObjToUpdate, err := p.toUnversioned(versionedObjToUpdate) + if err != nil { + return nil, err + } + + return unversionedObjToUpdate, nil } // strategicPatchObject applies a strategic merge patch of to @@ -442,7 +293,7 @@ func strategicPatchObject( originalObject runtime.Object, patchJS []byte, objToUpdate runtime.Object, - versionedObj runtime.Object, + schemaReferenceObj runtime.Object, ) error { originalObjMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(originalObject) if err != nil { @@ -454,12 +305,62 @@ func strategicPatchObject( return errors.NewBadRequest(err.Error()) } - if err := applyPatchToObject(codec, defaulter, originalObjMap, patchMap, objToUpdate, versionedObj); err != nil { + if err := applyPatchToObject(codec, defaulter, originalObjMap, patchMap, objToUpdate, schemaReferenceObj); err != nil { return err } return nil } +// applyPatch is called every time GuaranteedUpdate asks for the updated object, +// and is given the currently persisted object as input. +func (p *patcher) applyPatch(_ context.Context, _, currentObject runtime.Object) (runtime.Object, error) { + // Make sure we actually have a persisted currentObject + p.trace.Step("About to apply patch") + if hasUID, err := hasUID(currentObject); err != nil { + return nil, err + } else if !hasUID { + return nil, errors.NewNotFound(p.resource.GroupResource(), p.name) + } + + objToUpdate, err := p.mechanism.applyPatchToCurrentObject(currentObject) + if err != nil { + return nil, err + } + if err := checkName(objToUpdate, p.name, p.namespace, p.namer); err != nil { + return nil, err + } + return objToUpdate, nil +} + +// applyAdmission is called every time GuaranteedUpdate asks for the updated object, +// and is given the currently persisted object and the patched object as input. +func (p *patcher) applyAdmission(ctx context.Context, patchedObject runtime.Object, currentObject runtime.Object) (runtime.Object, error) { + p.trace.Step("About to check admission control") + return patchedObject, p.admissionCheck(patchedObject, currentObject) +} + +// patchResource divides PatchResource for easier unit testing +func (p *patcher) patchResource(ctx context.Context) (runtime.Object, error) { + p.namespace = request.NamespaceValue(ctx) + switch p.patchType { + case types.JSONPatchType, types.MergePatchType: + p.mechanism = &jsonPatcher{patcher: p} + case types.StrategicMergePatchType: + schemaReferenceObj, err := p.unsafeConvertor.ConvertToVersion(p.restPatcher.New(), p.kind.GroupVersion()) + if err != nil { + return nil, err + } + p.mechanism = &smpPatcher{patcher: p, schemaReferenceObj: schemaReferenceObj} + default: + return nil, fmt.Errorf("%v: unimplemented patch type", p.patchType) + } + p.updatedObjectInfo = rest.DefaultUpdatedObjectInfo(nil, p.applyPatch, p.applyAdmission) + return finishRequest(p.timeout, func() (runtime.Object, error) { + updateObject, _, updateErr := p.restPatcher.Update(ctx, p.name, p.updatedObjectInfo, p.createValidation, p.updateValidation) + return updateObject, updateErr + }) +} + // applyPatchToObject applies a strategic merge patch of to // and stores the result in . // NOTE: must be a versioned object. @@ -469,9 +370,9 @@ func applyPatchToObject( originalMap map[string]interface{}, patchMap map[string]interface{}, objToUpdate runtime.Object, - versionedObj runtime.Object, + schemaReferenceObj runtime.Object, ) error { - patchedObjMap, err := strategicpatch.StrategicMergeMapPatch(originalMap, patchMap, versionedObj) + patchedObjMap, err := strategicpatch.StrategicMergeMapPatch(originalMap, patchMap, schemaReferenceObj) if err != nil { return interpretPatchError(err) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/response.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/response.go index 508b0aede..8cee470a5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/response.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/response.go @@ -17,6 +17,7 @@ limitations under the License. package handlers import ( + "context" "fmt" "net/http" @@ -28,12 +29,11 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" ) // transformResponseObject takes an object loaded from storage and performs any necessary transformations. // Will write the complete response object. -func transformResponseObject(ctx request.Context, scope RequestScope, req *http.Request, w http.ResponseWriter, statusCode int, result runtime.Object) { +func transformResponseObject(ctx context.Context, scope RequestScope, req *http.Request, w http.ResponseWriter, statusCode int, result runtime.Object) { // TODO: fetch the media type much earlier in request processing and pass it into this method. mediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope) if err != nil { @@ -169,7 +169,7 @@ func transformResponseObject(ctx request.Context, scope RequestScope, req *http. } } - responsewriters.WriteObject(ctx, statusCode, scope.Kind.GroupVersion(), scope.Serializer, result, w, req) + responsewriters.WriteObject(statusCode, scope.Kind.GroupVersion(), scope.Serializer, result, w, req) } // errNotAcceptable indicates Accept negotiation has failed diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go index 9c49e2c61..007efe9d8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go @@ -17,6 +17,7 @@ limitations under the License. package responsewriters import ( + "context" "fmt" "net/http" "strings" @@ -26,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/apiserver/pkg/endpoints/request" ) // Avoid emitting errors that look like valid HTML. Quotes are okay. @@ -41,7 +41,7 @@ func BadGatewayError(w http.ResponseWriter, req *http.Request) { } // Forbidden renders a simple forbidden error -func Forbidden(ctx request.Context, attributes authorizer.Attributes, w http.ResponseWriter, req *http.Request, reason string, s runtime.NegotiatedSerializer) { +func Forbidden(ctx context.Context, attributes authorizer.Attributes, w http.ResponseWriter, req *http.Request, reason string, s runtime.NegotiatedSerializer) { msg := sanitizer.Replace(forbiddenMessage(attributes)) w.Header().Set("X-Content-Type-Options", "nosniff") @@ -53,7 +53,7 @@ func Forbidden(ctx request.Context, attributes authorizer.Attributes, w http.Res } gv := schema.GroupVersion{Group: attributes.GetAPIGroup(), Version: attributes.GetAPIVersion()} gr := schema.GroupResource{Group: attributes.GetAPIGroup(), Resource: attributes.GetResource()} - ErrorNegotiated(ctx, apierrors.NewForbidden(gr, attributes.GetName(), fmt.Errorf(errMsg)), s, gv, w, req) + ErrorNegotiated(apierrors.NewForbidden(gr, attributes.GetName(), fmt.Errorf(errMsg)), s, gv, w, req) } func forbiddenMessage(attributes authorizer.Attributes) string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status.go index e37a8ea47..99673077b 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status.go @@ -61,7 +61,7 @@ func ErrorToAPIStatus(err error) *metav1.Status { // by REST storage - these typically indicate programmer // error by not using pkg/api/errors, or unexpected failure // cases. - runtime.HandleError(fmt.Errorf("apiserver received an error that is not an metav1.Status: %v", err)) + runtime.HandleError(fmt.Errorf("apiserver received an error that is not an metav1.Status: %#+v", err)) return &metav1.Status{ TypeMeta: metav1.TypeMeta{ Kind: "Status", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go index 58dac561f..0add873d9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go @@ -40,25 +40,25 @@ import ( // response. The Accept header and current API version will be passed in, and the output will be copied // directly to the response body. If content type is returned it is used, otherwise the content type will // be "application/octet-stream". All other objects are sent to standard JSON serialization. -func WriteObject(ctx request.Context, statusCode int, gv schema.GroupVersion, s runtime.NegotiatedSerializer, object runtime.Object, w http.ResponseWriter, req *http.Request) { +func WriteObject(statusCode int, gv schema.GroupVersion, s runtime.NegotiatedSerializer, object runtime.Object, w http.ResponseWriter, req *http.Request) { stream, ok := object.(rest.ResourceStreamer) if ok { - requestInfo, _ := request.RequestInfoFrom(ctx) + requestInfo, _ := request.RequestInfoFrom(req.Context()) metrics.RecordLongRunning(req, requestInfo, func() { - StreamObject(ctx, statusCode, gv, s, stream, w, req) + StreamObject(statusCode, gv, s, stream, w, req) }) return } - WriteObjectNegotiated(ctx, s, gv, w, req, statusCode, object) + WriteObjectNegotiated(s, gv, w, req, statusCode, object) } // StreamObject performs input stream negotiation from a ResourceStreamer and writes that to the response. // If the client requests a websocket upgrade, negotiate for a websocket reader protocol (because many // browser clients cannot easily handle binary streaming protocols). -func StreamObject(ctx request.Context, statusCode int, gv schema.GroupVersion, s runtime.NegotiatedSerializer, stream rest.ResourceStreamer, w http.ResponseWriter, req *http.Request) { +func StreamObject(statusCode int, gv schema.GroupVersion, s runtime.NegotiatedSerializer, stream rest.ResourceStreamer, w http.ResponseWriter, req *http.Request) { out, flush, contentType, err := stream.InputStream(gv.String(), req.Header.Get("Accept")) if err != nil { - ErrorNegotiated(ctx, err, s, gv, w, req) + ErrorNegotiated(err, s, gv, w, req) return } if out == nil { @@ -101,7 +101,7 @@ func SerializeObject(mediaType string, encoder runtime.Encoder, w http.ResponseW // WriteObjectNegotiated renders an object in the content type negotiated by the client. // The context is optional and can be nil. -func WriteObjectNegotiated(ctx request.Context, s runtime.NegotiatedSerializer, gv schema.GroupVersion, w http.ResponseWriter, req *http.Request, statusCode int, object runtime.Object) { +func WriteObjectNegotiated(s runtime.NegotiatedSerializer, gv schema.GroupVersion, w http.ResponseWriter, req *http.Request, statusCode int, object runtime.Object) { serializer, err := negotiation.NegotiateOutputSerializer(req, s) if err != nil { // if original statusCode was not successful we need to return the original error @@ -115,7 +115,7 @@ func WriteObjectNegotiated(ctx request.Context, s runtime.NegotiatedSerializer, return } - if ae := request.AuditEventFrom(ctx); ae != nil { + if ae := request.AuditEventFrom(req.Context()); ae != nil { audit.LogResponseObject(ae, object, gv, s) } @@ -125,7 +125,7 @@ func WriteObjectNegotiated(ctx request.Context, s runtime.NegotiatedSerializer, // ErrorNegotiated renders an error to the response. Returns the HTTP status code of the error. // The context is optional and may be nil. -func ErrorNegotiated(ctx request.Context, err error, s runtime.NegotiatedSerializer, gv schema.GroupVersion, w http.ResponseWriter, req *http.Request) int { +func ErrorNegotiated(err error, s runtime.NegotiatedSerializer, gv schema.GroupVersion, w http.ResponseWriter, req *http.Request) int { status := ErrorToAPIStatus(err) code := int(status.Code) // when writing an error, check to see if the status indicates a retry after period @@ -139,7 +139,7 @@ func ErrorNegotiated(ctx request.Context, err error, s runtime.NegotiatedSeriali return code } - WriteObjectNegotiated(ctx, s, gv, w, req, code, status) + WriteObjectNegotiated(s, gv, w, req, code, status) return code } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go index 63135aaa8..d42c0194d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go @@ -17,10 +17,12 @@ limitations under the License. package handlers import ( + "context" "encoding/hex" "fmt" "io/ioutil" "net/http" + "net/url" "time" "github.com/golang/glog" @@ -37,12 +39,12 @@ import ( "k8s.io/apiserver/pkg/endpoints/metrics" "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" + openapiproto "k8s.io/kube-openapi/pkg/util/proto" ) // RequestScope encapsulates common fields across all RESTful handler methods. type RequestScope struct { Namer ScopeNamer - ContextFunc Serializer runtime.NegotiatedSerializer runtime.ParameterCodec @@ -54,6 +56,7 @@ type RequestScope struct { UnsafeConvertor runtime.ObjectConvertor TableConvertor rest.TableConvertor + OpenAPISchema openapiproto.Schema Resource schema.GroupVersionResource Kind schema.GroupVersionKind @@ -63,8 +66,7 @@ type RequestScope struct { } func (scope *RequestScope) err(err error, w http.ResponseWriter, req *http.Request) { - ctx := scope.ContextFunc(req) - responsewriters.ErrorNegotiated(ctx, err, scope.Serializer, scope.Kind.GroupVersion(), w, req) + responsewriters.ErrorNegotiated(err, scope.Serializer, scope.Kind.GroupVersion(), w, req) } func (scope *RequestScope) AllowsConversion(gvk schema.GroupVersionKind) bool { @@ -91,9 +93,6 @@ func (scope *RequestScope) AllowsStreamSchema(s string) bool { return s == "watch" } -// MaxRetryWhenPatchConflicts is the maximum number of conflicts retry during a patch operation before returning failure -const MaxRetryWhenPatchConflicts = 5 - // ConnectResource returns a function that handles a connect request on a rest.Storage object. func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admission.Interface, restPath string, isSubresource bool) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { @@ -102,8 +101,11 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi scope.err(err, w, req) return } - ctx := scope.ContextFunc(req) + ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + ae := request.AuditEventFrom(ctx) + admit = admission.WithAudit(admit, ae) + opts, subpath, subpathKey := connecter.NewConnectOptions() if err := getRequestOptions(req, scope, opts, subpath, subpathKey, isSubresource); err != nil { err = errors.NewBadRequest(err.Error()) @@ -118,15 +120,15 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi } userInfo, _ := request.UserFrom(ctx) // TODO: remove the mutating admission here as soon as we have ported all plugin that handle CONNECT - if mutatingAdmit, ok := admit.(admission.MutationInterface); ok { - err = mutatingAdmit.Admit(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, userInfo)) + if mutatingAdmission, ok := admit.(admission.MutationInterface); ok { + err = mutatingAdmission.Admit(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, userInfo)) if err != nil { scope.err(err, w, req) return } } - if mutatingAdmit, ok := admit.(admission.ValidationInterface); ok { - err = mutatingAdmit.Validate(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, userInfo)) + if validatingAdmission, ok := admit.(admission.ValidationInterface); ok { + err = validatingAdmission.Validate(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, userInfo)) if err != nil { scope.err(err, w, req) return @@ -153,8 +155,7 @@ type responder struct { } func (r *responder) Object(statusCode int, obj runtime.Object) { - ctx := r.scope.ContextFunc(r.req) - responsewriters.WriteObject(ctx, statusCode, r.scope.Kind.GroupVersion(), r.scope.Serializer, obj, r.w, r.req) + responsewriters.WriteObject(statusCode, r.scope.Kind.GroupVersion(), r.scope.Serializer, obj, r.w, r.req) } func (r *responder) Error(err error) { @@ -266,7 +267,7 @@ func checkName(obj runtime.Object, name, namespace string, namer ScopeNamer) err // setListSelfLink sets the self link of a list to the base URL, then sets the self links // on all child objects returned. Returns the number of items in the list. -func setListSelfLink(obj runtime.Object, ctx request.Context, req *http.Request, namer ScopeNamer) (int, error) { +func setListSelfLink(obj runtime.Object, ctx context.Context, req *http.Request, namer ScopeNamer) (int, error) { if !meta.IsListType(obj) { return 0, nil } @@ -323,3 +324,7 @@ func parseTimeout(str string) time.Duration { } return 30 * time.Second } + +func isDryRun(url *url.URL) bool { + return len(url.Query()["dryRun"]) != 0 +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go index d87d77006..549e45438 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go @@ -17,6 +17,7 @@ limitations under the License. package handlers import ( + "context" "errors" "fmt" "net/http" @@ -171,36 +172,50 @@ func (p *testPatcher) New() runtime.Object { return &example.Pod{} } -func (p *testPatcher) Update(ctx request.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { - currentPod := p.startingPod - if p.numUpdates > 0 { - currentPod = p.updatePod - } - p.numUpdates++ +func (p *testPatcher) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { + // Simulate GuaranteedUpdate behavior (retries internally on etcd changes if the incoming resource doesn't pin resourceVersion) + for { + currentPod := p.startingPod + if p.numUpdates > 0 { + currentPod = p.updatePod + } + p.numUpdates++ - obj, err := objInfo.UpdatedObject(ctx, currentPod) - if err != nil { - return nil, false, err - } - inPod := obj.(*example.Pod) - if inPod.ResourceVersion != p.updatePod.ResourceVersion { - return nil, false, apierrors.NewConflict(example.Resource("pods"), inPod.Name, fmt.Errorf("existing %v, new %v", p.updatePod.ResourceVersion, inPod.ResourceVersion)) - } + // Remember the current resource version + currentResourceVersion := currentPod.ResourceVersion - if currentPod == nil { - if err := createValidation(currentPod); err != nil { + obj, err := objInfo.UpdatedObject(ctx, currentPod) + if err != nil { return nil, false, err } - } else { - if err := updateValidation(currentPod, inPod); err != nil { - return nil, false, err + inPod := obj.(*example.Pod) + if inPod.ResourceVersion == "" || inPod.ResourceVersion == "0" { + inPod.ResourceVersion = p.updatePod.ResourceVersion + } + if inPod.ResourceVersion != p.updatePod.ResourceVersion { + // If the patch didn't have an opinion on the resource version, retry like GuaranteedUpdate does + if inPod.ResourceVersion == currentResourceVersion { + continue + } + // If the patch changed the resource version and it mismatches, conflict + return nil, false, apierrors.NewConflict(example.Resource("pods"), inPod.Name, fmt.Errorf("existing %v, new %v", p.updatePod.ResourceVersion, inPod.ResourceVersion)) + } + + if currentPod == nil { + if err := createValidation(currentPod); err != nil { + return nil, false, err + } + } else { + if err := updateValidation(currentPod, inPod); err != nil { + return nil, false, err + } } - } - return inPod, false, nil + return inPod, false, nil + } } -func (p *testPatcher) Get(ctx request.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (p *testPatcher) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { p.t.Fatal("Unexpected call to testPatcher.Get") return nil, errors.New("Unexpected call to testPatcher.Get") } @@ -251,15 +266,21 @@ type patchTestCase struct { // startingPod is used as the starting point for the first Update startingPod *example.Pod - // changedPod is the "destination" pod for the patch. The test will create a patch from the startingPod to the changedPod - // to use when calling the patch operation - changedPod *example.Pod + // changedPod can be set as the "destination" pod for the patch, and the test will compute a patch from the startingPod to the changedPod, + // or patches can be set directly using strategicMergePatch, mergePatch, and jsonPatch + changedPod *example.Pod + strategicMergePatch string + mergePatch string + jsonPatch string + // updatePod is the pod that is used for conflict comparison and as the starting point for the second Update updatePod *example.Pod // expectedPod is the pod that you expect to get back after the patch is complete expectedPod *example.Pod expectedError string + // if set, indicates the number of times patching was expected to be attempted + expectedTries int } func (tc *patchTestCase) Run(t *testing.T) { @@ -292,7 +313,7 @@ func (tc *patchTestCase) Run(t *testing.T) { convertor := runtime.UnsafeObjectConvertor(scheme) kind := examplev1.SchemeGroupVersion.WithKind("Pod") resource := examplev1.SchemeGroupVersion.WithResource("pods") - versionedObj := &examplev1.Pod{} + schemaReferenceObj := &examplev1.Pod{} for _, patchType := range []types.PatchType{types.JSONPatchType, types.MergePatchType, types.StrategicMergePatchType} { // This needs to be reset on each iteration. @@ -302,53 +323,86 @@ func (tc *patchTestCase) Run(t *testing.T) { updatePod: tc.updatePod, } - // TODO SUPPORT THIS! - if patchType == types.JSONPatchType { - continue - } t.Logf("Working with patchType %v", patchType) - originalObjJS, err := runtime.Encode(codec, tc.startingPod) - if err != nil { - t.Errorf("%s: unexpected error: %v", tc.name, err) - continue - } - changedJS, err := runtime.Encode(codec, tc.changedPod) - if err != nil { - t.Errorf("%s: unexpected error: %v", tc.name, err) - continue - } - patch := []byte{} switch patchType { case types.StrategicMergePatchType: - patch, err = strategicpatch.CreateTwoWayMergePatch(originalObjJS, changedJS, versionedObj) - if err != nil { - t.Errorf("%s: unexpected error: %v", tc.name, err) - continue + patch = []byte(tc.strategicMergePatch) + if len(patch) == 0 { + originalObjJS, err := runtime.Encode(codec, tc.startingPod) + if err != nil { + t.Errorf("%s: unexpected error: %v", tc.name, err) + continue + } + changedJS, err := runtime.Encode(codec, tc.changedPod) + if err != nil { + t.Errorf("%s: unexpected error: %v", tc.name, err) + continue + } + patch, err = strategicpatch.CreateTwoWayMergePatch(originalObjJS, changedJS, schemaReferenceObj) + if err != nil { + t.Errorf("%s: unexpected error: %v", tc.name, err) + continue + } } case types.MergePatchType: - patch, err = jsonpatch.CreateMergePatch(originalObjJS, changedJS) - if err != nil { - t.Errorf("%s: unexpected error: %v", tc.name, err) + patch = []byte(tc.mergePatch) + if len(patch) == 0 { + originalObjJS, err := runtime.Encode(codec, tc.startingPod) + if err != nil { + t.Errorf("%s: unexpected error: %v", tc.name, err) + continue + } + changedJS, err := runtime.Encode(codec, tc.changedPod) + if err != nil { + t.Errorf("%s: unexpected error: %v", tc.name, err) + continue + } + patch, err = jsonpatch.CreateMergePatch(originalObjJS, changedJS) + if err != nil { + t.Errorf("%s: unexpected error: %v", tc.name, err) + continue + } + } + + case types.JSONPatchType: + patch = []byte(tc.jsonPatch) + if len(patch) == 0 { + // TODO SUPPORT THIS! continue } + default: + t.Error("unsupported patch type") } - resultObj, err := patchResource( - ctx, - admissionMutation, - rest.ValidateAllObjectFunc, - admissionValidation, - 1*time.Second, - versionedObj, - testPatcher, - name, - patchType, - patch, - namer, creater, defaulter, convertor, kind, resource, codec, utiltrace.New("Patch"+name)) + p := patcher{ + namer: namer, + creater: creater, + defaulter: defaulter, + unsafeConvertor: convertor, + kind: kind, + resource: resource, + + createValidation: rest.ValidateAllObjectFunc, + updateValidation: admissionValidation, + admissionCheck: admissionMutation, + + codec: codec, + + timeout: 1 * time.Second, + + restPatcher: testPatcher, + name: name, + patchType: patchType, + patchJS: patch, + + trace: utiltrace.New("Patch" + name), + } + + resultObj, err := p.patchResource(ctx) if len(tc.expectedError) != 0 { if err == nil || err.Error() != tc.expectedError { t.Errorf("%s: expected error %v, but got %v", tc.name, tc.expectedError, err) @@ -361,6 +415,12 @@ func (tc *patchTestCase) Run(t *testing.T) { } } + if tc.expectedTries > 0 { + if tc.expectedTries != testPatcher.numUpdates { + t.Errorf("%s: expected %d tries, got %d", tc.name, tc.expectedTries, testPatcher.numUpdates) + } + } + if tc.expectedPod == nil { if resultObj != nil { t.Errorf("%s: unexpected result: %v", tc.name, resultObj) @@ -406,11 +466,11 @@ func TestNumberConversion(t *testing.T) { }, } versionedObjToUpdate := &examplev1.Pod{} - versionedObj := &examplev1.Pod{} + schemaReferenceObj := &examplev1.Pod{} patchJS := []byte(`{"spec":{"terminationGracePeriodSeconds":42,"activeDeadlineSeconds":120}}`) - err := strategicPatchObject(codec, defaulter, currentVersionedObject, patchJS, versionedObjToUpdate, versionedObj) + err := strategicPatchObject(codec, defaulter, currentVersionedObject, patchJS, versionedObjToUpdate, schemaReferenceObj) if err != nil { t.Fatal(err) } @@ -437,38 +497,17 @@ func TestPatchResourceNumberConversion(t *testing.T) { expectedPod: &example.Pod{}, } - tc.startingPod.Name = name - tc.startingPod.Namespace = namespace - tc.startingPod.UID = uid - tc.startingPod.ResourceVersion = "1" - tc.startingPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.startingPod.Spec.ActiveDeadlineSeconds = &fifteen + setTcPod(tc.startingPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), &fifteen, "") // Patch tries to change to 30. - tc.changedPod.Name = name - tc.changedPod.Namespace = namespace - tc.changedPod.UID = uid - tc.changedPod.ResourceVersion = "1" - tc.changedPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.changedPod.Spec.ActiveDeadlineSeconds = &thirty + setTcPod(tc.changedPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), &thirty, "") // Someone else already changed it to 30. // This should be fine since it's not a "meaningful conflict". // Previously this was detected as a meaningful conflict because int64(30) != float64(30). - tc.updatePod.Name = name - tc.updatePod.Namespace = namespace - tc.updatePod.UID = uid - tc.updatePod.ResourceVersion = "2" - tc.updatePod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.updatePod.Spec.ActiveDeadlineSeconds = &thirty - tc.updatePod.Spec.NodeName = "anywhere" + setTcPod(tc.updatePod, name, namespace, uid, "2", examplev1.SchemeGroupVersion.String(), &thirty, "anywhere") - tc.expectedPod.Name = name - tc.expectedPod.Namespace = namespace - tc.expectedPod.UID = uid - tc.expectedPod.ResourceVersion = "2" - tc.expectedPod.Spec.ActiveDeadlineSeconds = &thirty - tc.expectedPod.Spec.NodeName = "anywhere" + setTcPod(tc.expectedPod, name, namespace, uid, "2", "", &thirty, "anywhere") tc.Run(t) } @@ -490,34 +529,80 @@ func TestPatchResourceWithVersionConflict(t *testing.T) { expectedPod: &example.Pod{}, } + setTcPod(tc.startingPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), &fifteen, "") + + setTcPod(tc.changedPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), &thirty, "") + + setTcPod(tc.updatePod, name, namespace, uid, "2", examplev1.SchemeGroupVersion.String(), &fifteen, "anywhere") + + setTcPod(tc.expectedPod, name, namespace, uid, "2", "", &thirty, "anywhere") + + tc.Run(t) +} + +func TestPatchResourceWithStaleVersionConflict(t *testing.T) { + namespace := "bar" + name := "foo" + uid := types.UID("uid") + + tc := &patchTestCase{ + name: "TestPatchResourceWithStaleVersionConflict", + + startingPod: &example.Pod{}, + updatePod: &example.Pod{}, + + expectedError: `Operation cannot be fulfilled on pods.example.apiserver.k8s.io "foo": existing 2, new 1`, + expectedTries: 1, + } + + // starting pod is at rv=2 tc.startingPod.Name = name tc.startingPod.Namespace = namespace tc.startingPod.UID = uid - tc.startingPod.ResourceVersion = "1" + tc.startingPod.ResourceVersion = "2" tc.startingPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.startingPod.Spec.ActiveDeadlineSeconds = &fifteen + // same pod is still in place when attempting to persist the update + tc.updatePod = tc.startingPod - tc.changedPod.Name = name - tc.changedPod.Namespace = namespace - tc.changedPod.UID = uid - tc.changedPod.ResourceVersion = "1" - tc.changedPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.changedPod.Spec.ActiveDeadlineSeconds = &thirty + // patches are submitted with a stale rv=1 + tc.mergePatch = `{"metadata":{"resourceVersion":"1"},"spec":{"nodeName":"foo"}}` + tc.strategicMergePatch = `{"metadata":{"resourceVersion":"1"},"spec":{"nodeName":"foo"}}` + + tc.Run(t) +} +func TestPatchResourceWithRacingVersionConflict(t *testing.T) { + namespace := "bar" + name := "foo" + uid := types.UID("uid") + + tc := &patchTestCase{ + name: "TestPatchResourceWithRacingVersionConflict", + + startingPod: &example.Pod{}, + updatePod: &example.Pod{}, + + expectedError: `Operation cannot be fulfilled on pods.example.apiserver.k8s.io "foo": existing 3, new 2`, + expectedTries: 2, + } + + // starting pod is at rv=2 + tc.startingPod.Name = name + tc.startingPod.Namespace = namespace + tc.startingPod.UID = uid + tc.startingPod.ResourceVersion = "2" + tc.startingPod.APIVersion = examplev1.SchemeGroupVersion.String() + + // pod with rv=3 is found when attempting to persist the update tc.updatePod.Name = name tc.updatePod.Namespace = namespace tc.updatePod.UID = uid - tc.updatePod.ResourceVersion = "2" + tc.updatePod.ResourceVersion = "3" tc.updatePod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.updatePod.Spec.ActiveDeadlineSeconds = &fifteen - tc.updatePod.Spec.NodeName = "anywhere" - tc.expectedPod.Name = name - tc.expectedPod.Namespace = namespace - tc.expectedPod.UID = uid - tc.expectedPod.ResourceVersion = "2" - tc.expectedPod.Spec.ActiveDeadlineSeconds = &thirty - tc.expectedPod.Spec.NodeName = "anywhere" + // patches are submitted with a rv=2 + tc.mergePatch = `{"metadata":{"resourceVersion":"2"},"spec":{"nodeName":"foo"}}` + tc.strategicMergePatch = `{"metadata":{"resourceVersion":"2"},"spec":{"nodeName":"foo"}}` tc.Run(t) } @@ -533,30 +618,23 @@ func TestPatchResourceWithConflict(t *testing.T) { startingPod: &example.Pod{}, changedPod: &example.Pod{}, updatePod: &example.Pod{}, - - expectedError: `Operation cannot be fulfilled on pods.example.apiserver.k8s.io "foo": existing 2, new 1`, + expectedPod: &example.Pod{}, } - tc.startingPod.Name = name - tc.startingPod.Namespace = namespace - tc.startingPod.UID = uid - tc.startingPod.ResourceVersion = "1" - tc.startingPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.startingPod.Spec.NodeName = "here" + // See issue #63104 for discussion of how much sense this makes. - tc.changedPod.Name = name - tc.changedPod.Namespace = namespace - tc.changedPod.UID = uid - tc.changedPod.ResourceVersion = "1" - tc.changedPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.changedPod.Spec.NodeName = "there" + setTcPod(tc.startingPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), nil, "here") - tc.updatePod.Name = name - tc.updatePod.Namespace = namespace - tc.updatePod.UID = uid - tc.updatePod.ResourceVersion = "2" - tc.updatePod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.updatePod.Spec.NodeName = "anywhere" + setTcPod(tc.changedPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), nil, "there") + + setTcPod(tc.updatePod, name, namespace, uid, "2", examplev1.SchemeGroupVersion.String(), nil, "anywhere") + + tc.expectedPod.Name = name + tc.expectedPod.Namespace = namespace + tc.expectedPod.UID = uid + tc.expectedPod.ResourceVersion = "2" + tc.expectedPod.APIVersion = examplev1.SchemeGroupVersion.String() + tc.expectedPod.Spec.NodeName = "there" tc.Run(t) } @@ -615,26 +693,11 @@ func TestPatchWithAdmissionRejection(t *testing.T) { expectedError: test.expectedError, } - tc.startingPod.Name = name - tc.startingPod.Namespace = namespace - tc.startingPod.UID = uid - tc.startingPod.ResourceVersion = "1" - tc.startingPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.startingPod.Spec.ActiveDeadlineSeconds = &fifteen - - tc.changedPod.Name = name - tc.changedPod.Namespace = namespace - tc.changedPod.UID = uid - tc.changedPod.ResourceVersion = "1" - tc.changedPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.changedPod.Spec.ActiveDeadlineSeconds = &thirty - - tc.updatePod.Name = name - tc.updatePod.Namespace = namespace - tc.updatePod.UID = uid - tc.updatePod.ResourceVersion = "1" - tc.updatePod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.updatePod.Spec.ActiveDeadlineSeconds = &fifteen + setTcPod(tc.startingPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), &fifteen, "") + + setTcPod(tc.changedPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), &thirty, "") + + setTcPod(tc.updatePod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), &fifteen, "") tc.Run(t) } @@ -667,27 +730,11 @@ func TestPatchWithVersionConflictThenAdmissionFailure(t *testing.T) { expectedError: "admission failure", } - tc.startingPod.Name = name - tc.startingPod.Namespace = namespace - tc.startingPod.UID = uid - tc.startingPod.ResourceVersion = "1" - tc.startingPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.startingPod.Spec.ActiveDeadlineSeconds = &fifteen + setTcPod(tc.startingPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), &fifteen, "") - tc.changedPod.Name = name - tc.changedPod.Namespace = namespace - tc.changedPod.UID = uid - tc.changedPod.ResourceVersion = "1" - tc.changedPod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.changedPod.Spec.ActiveDeadlineSeconds = &thirty + setTcPod(tc.changedPod, name, namespace, uid, "1", examplev1.SchemeGroupVersion.String(), &thirty, "") - tc.updatePod.Name = name - tc.updatePod.Namespace = namespace - tc.updatePod.UID = uid - tc.updatePod.ResourceVersion = "2" - tc.updatePod.APIVersion = examplev1.SchemeGroupVersion.String() - tc.updatePod.Spec.ActiveDeadlineSeconds = &fifteen - tc.updatePod.Spec.NodeName = "anywhere" + setTcPod(tc.updatePod, name, namespace, uid, "2", examplev1.SchemeGroupVersion.String(), &fifteen, "anywhere") tc.Run(t) } @@ -785,3 +832,19 @@ func TestFinishRequest(t *testing.T) { } } } + +func setTcPod(tcPod *example.Pod, name string, namespace string, uid types.UID, resourceVersion string, apiVersion string, activeDeadlineSeconds *int64, nodeName string) { + tcPod.Name = name + tcPod.Namespace = namespace + tcPod.UID = uid + tcPod.ResourceVersion = resourceVersion + if len(apiVersion) != 0 { + tcPod.APIVersion = apiVersion + } + if activeDeadlineSeconds != nil { + tcPod.Spec.ActiveDeadlineSeconds = activeDeadlineSeconds + } + if len(nodeName) != 0 { + tcPod.Spec.NodeName = nodeName + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go index 0eac36660..de242771d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go @@ -17,6 +17,7 @@ limitations under the License. package handlers import ( + "context" "fmt" "net/http" "time" @@ -33,12 +34,17 @@ import ( ) // UpdateResource returns a function that will handle a resource update -func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectTyper, admit admission.Interface) http.HandlerFunc { +func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interface) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { // For performance tracking purposes. trace := utiltrace.New("Update " + req.URL.Path) defer trace.LogIfLong(500 * time.Millisecond) + if isDryRun(req.URL) { + scope.err(errors.NewBadRequest("dryRun is not supported yet"), w, req) + return + } + // TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer) timeout := parseTimeout(req.URL.Query().Get("timeout")) @@ -47,7 +53,7 @@ func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectType scope.err(err, w, req) return } - ctx := scope.ContextFunc(req) + ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) body, err := readBody(req) @@ -67,7 +73,7 @@ func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectType decoder := scope.Serializer.DecoderToVersion(s.Serializer, schema.GroupVersion{Group: defaultGVK.Group, Version: runtime.APIVersionInternal}) obj, gvk, err := decoder.Decode(body, &defaultGVK, original) if err != nil { - err = transformDecodeError(typer, err, original, gvk, body) + err = transformDecodeError(scope.Typer, err, original, gvk, body) scope.err(err, w, req) return } @@ -80,6 +86,7 @@ func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectType ae := request.AuditEventFrom(ctx) audit.LogRequestObject(ae, obj, scope.Resource, scope.Subresource, scope.Serializer) + admit = admission.WithAudit(admit, ae) if err := checkName(obj, name, namespace, scope.Namer); err != nil { scope.err(err, w, req) @@ -90,7 +97,7 @@ func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectType staticAdmissionAttributes := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, userInfo) var transformers []rest.TransformFunc if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Update) { - transformers = append(transformers, func(ctx request.Context, newObj, oldObj runtime.Object) (runtime.Object, error) { + transformers = append(transformers, func(ctx context.Context, newObj, oldObj runtime.Object) (runtime.Object, error) { return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, oldObj, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, userInfo)) }) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/watch.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/watch.go index 5e4497b0e..c1bc984e6 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/watch.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/watch.go @@ -30,6 +30,7 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/watch" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" + "k8s.io/apiserver/pkg/endpoints/metrics" "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/server/httplog" "k8s.io/apiserver/pkg/util/wsstream" @@ -89,7 +90,7 @@ func serveWatch(watcher watch.Interface, scope RequestScope, req *http.Request, mediaType += ";stream=watch" } - ctx := scope.ContextFunc(req) + ctx := req.Context() requestInfo, ok := request.RequestInfoFrom(ctx) if !ok { scope.err(fmt.Errorf("missing requestInfo"), w, req) @@ -140,6 +141,10 @@ type WatchServer struct { // ServeHTTP serves a series of encoded events via HTTP with Transfer-Encoding: chunked // or over a websocket connection. func (s *WatchServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { + kind := s.Scope.Kind + metrics.RegisteredWatchers.WithLabelValues(kind.Group, kind.Version, kind.Kind).Inc() + defer metrics.RegisteredWatchers.WithLabelValues(kind.Group, kind.Version, kind.Kind).Dec() + w = httplog.Unlogged(w) if wsstream.IsWebSocketRequest(req) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go index 934ee94f7..3edd09dcd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go @@ -28,7 +28,6 @@ import ( restful "github.com/emicklei/go-restful" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/runtime" @@ -38,9 +37,10 @@ import ( "k8s.io/apiserver/pkg/endpoints/handlers" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/metrics" - "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" genericfilters "k8s.io/apiserver/pkg/server/filters" + utilopenapi "k8s.io/apiserver/pkg/util/openapi" + openapibuilder "k8s.io/kube-openapi/pkg/builder" ) const ( @@ -160,38 +160,13 @@ func (a *APIInstaller) getResourceKind(path string, storage rest.Storage) (schem if fqKindToRegister.Empty() { return schema.GroupVersionKind{}, fmt.Errorf("unable to locate fully qualified kind for %v: found %v when registering for %v", reflect.TypeOf(object), fqKinds, a.group.GroupVersion) } - return fqKindToRegister, nil -} -// restMapping returns rest mapper for the resource. -// Example REST paths that this mapper maps. -// 1. Resource only, no subresource: -// Resource Type: batch/v1.Job (input args: resource = "jobs") -// REST path: /apis/batch/v1/namespaces/{namespace}/job/{name} -// 2. Subresource and its parent belong to different API groups and/or versions: -// Resource Type: extensions/v1beta1.ReplicaSet (input args: resource = "replicasets") -// Subresource Type: autoscaling/v1.Scale -// REST path: /apis/extensions/v1beta1/namespaces/{namespace}/replicaset/{name}/scale -func (a *APIInstaller) restMapping(resource string) (*meta.RESTMapping, error) { - // subresources must have parent resources, and follow the namespacing rules of their parent. - // So get the storage of the resource (which is the parent resource in case of subresources) - storage, ok := a.group.Storage[resource] - if !ok { - return nil, fmt.Errorf("unable to locate the storage object for resource: %s", resource) - } - fqKindToRegister, err := a.getResourceKind(resource, storage) - if err != nil { - return nil, fmt.Errorf("unable to locate fully qualified kind for mapper resource %s: %v", resource, err) - } - return a.group.Mapper.RESTMapping(fqKindToRegister.GroupKind(), fqKindToRegister.Version) + // group is guaranteed to match based on the check above + return fqKindToRegister, nil } func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storage, ws *restful.WebService) (*metav1.APIResource, error) { admit := a.group.Admit - context := a.group.Context - if context == nil { - return nil, fmt.Errorf("%v missing Context", a.group.GroupVersion) - } optionsExternalVersion := a.group.GroupVersion if a.group.OptionsExternalVersion != nil { @@ -203,11 +178,6 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag return nil, err } - mapping, err := a.restMapping(resource) - if err != nil { - return nil, err - } - fqKindToRegister, err := a.getResourceKind(path, storage) if err != nil { return nil, err @@ -219,7 +189,28 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag } defaultVersionedObject := indirectArbitraryPointer(versionedPtr) kind := fqKindToRegister.Kind - hasSubresource := len(subresource) > 0 + isSubresource := len(subresource) > 0 + + // If there is a subresource, namespace scoping is defined by the parent resource + namespaceScoped := true + if isSubresource { + parentStorage, ok := a.group.Storage[resource] + if !ok { + return nil, fmt.Errorf("missing parent storage: %q", resource) + } + scoper, ok := parentStorage.(rest.Scoper) + if !ok { + return nil, fmt.Errorf("%q must implement scoper", resource) + } + namespaceScoped = scoper.NamespaceScoped() + + } else { + scoper, ok := storage.(rest.Scoper) + if !ok { + return nil, fmt.Errorf("%q must implement scoper", resource) + } + namespaceScoped = scoper.NamespaceScoped() + } // what verbs are supported by the storage, used to know what verbs we support per path creater, isCreater := storage.(rest.Creater) @@ -342,16 +333,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag } } - var ctxFn handlers.ContextFunc - ctxFn = func(req *http.Request) request.Context { - if ctx, ok := context.Get(req); ok { - return request.WithUserAgent(ctx, req.Header.Get("User-Agent")) - } - return request.WithUserAgent(request.NewContext(), req.Header.Get("User-Agent")) - } - allowWatchList := isWatcher && isLister // watching on lists is allowed only for kinds that support both watch and list. - scope := mapping.Scope nameParam := ws.PathParameter("name", "name of the "+kind).DataType("string") pathParam := ws.PathParameter("path", "path to the resource").DataType("string") @@ -370,8 +352,8 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag var apiResource metav1.APIResource // Get the list of actions for the given scope. - switch scope.Name() { - case meta.RESTScopeNameRoot: + switch { + case !namespaceScoped: // Handle non-namespace scoped resources like nodes. resourcePath := resource resourceParams := params @@ -379,7 +361,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag nameParams := append(params, nameParam) proxyParams := append(nameParams, pathParam) suffix := "" - if hasSubresource { + if isSubresource { suffix = "/" + subresource itemPath = itemPath + suffix resourcePath = itemPath @@ -389,7 +371,6 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag apiResource.Namespaced = false apiResource.Kind = resourceKind namer := handlers.ContextBasedNaming{ - GetContext: ctxFn, SelfLinker: a.group.Linker, ClusterScoped: true, SelfLinkPathPrefix: gpath.Join(a.prefix, resource) + "/", @@ -416,10 +397,11 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer, false}, isConnecter) actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath) break - case meta.RESTScopeNameNamespace: + default: + namespaceParamName := "namespaces" // Handler for standard REST verbs (GET, PUT, POST and DELETE). - namespaceParam := ws.PathParameter(scope.ArgumentName(), scope.ParamDescription()).DataType("string") - namespacedPath := scope.ParamName() + "/{" + scope.ArgumentName() + "}/" + resource + namespaceParam := ws.PathParameter("namespace", "object name and auth scope, such as for teams and projects").DataType("string") + namespacedPath := namespaceParamName + "/{" + "namespace" + "}/" + resource namespaceParams := []*restful.Parameter{namespaceParam} resourcePath := namespacedPath @@ -428,7 +410,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag nameParams := append(namespaceParams, nameParam) proxyParams := append(nameParams, pathParam) itemPathSuffix := "" - if hasSubresource { + if isSubresource { itemPathSuffix = "/" + subresource itemPath = itemPath + itemPathSuffix resourcePath = itemPath @@ -438,10 +420,9 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag apiResource.Namespaced = true apiResource.Kind = resourceKind namer := handlers.ContextBasedNaming{ - GetContext: ctxFn, SelfLinker: a.group.Linker, ClusterScoped: false, - SelfLinkPathPrefix: gpath.Join(a.prefix, scope.ParamName()) + "/", + SelfLinkPathPrefix: gpath.Join(a.prefix, namespaceParamName) + "/", SelfLinkPathSuffix: itemPathSuffix, } @@ -465,13 +446,11 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag // list or post across namespace. // For ex: LIST all pods in all namespaces by sending a LIST request at /api/apiVersion/pods. // TODO: more strongly type whether a resource allows these actions on "all namespaces" (bulk delete) - if !hasSubresource { + if !isSubresource { actions = appendIf(actions, action{"LIST", resource, params, namer, true}, isLister) actions = appendIf(actions, action{"WATCHLIST", "watch/" + resource, params, namer, true}, allowWatchList) } break - default: - return nil, fmt.Errorf("unsupported restscope: %s", scope.Name()) } // Create Routes for the actions. @@ -497,7 +476,6 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag kubeVerbs := map[string]struct{}{} reqScope := handlers.RequestScope{ - ContextFunc: ctxFn, Serializer: a.group.Serializer, ParameterCodec: a.group.ParameterCodec, Creater: a.group.Creater, @@ -519,6 +497,16 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if a.group.MetaGroupVersion != nil { reqScope.MetaGroupVersion = *a.group.MetaGroupVersion } + if a.group.OpenAPIConfig != nil { + openAPIDefinitions, err := openapibuilder.BuildOpenAPIDefinitionsForResource(defaultVersionedObject, a.group.OpenAPIConfig) + if err != nil { + return nil, fmt.Errorf("unable to build openapi definitions for %v: %v", fqKindToRegister, err) + } + reqScope.OpenAPISchema, err = utilopenapi.ToProtoSchema(openAPIDefinitions, fqKindToRegister) + if err != nil { + return nil, fmt.Errorf("unable to get openapi schema for %v: %v", fqKindToRegister, err) + } + } for _, action := range actions { producedObject := storageMeta.ProducesObject(action.Verb) if producedObject == nil { @@ -554,8 +542,13 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag routes := []*restful.RouteBuilder{} // If there is a subresource, kind should be the parent's kind. - if hasSubresource { - fqParentKind, err := a.getResourceKind(resource, a.group.Storage[resource]) + if isSubresource { + parentStorage, ok := a.group.Storage[resource] + if !ok { + return nil, fmt.Errorf("missing parent storage: %q", resource) + } + + fqParentKind, err := a.getResourceKind(resource, parentStorage) if err != nil { return nil, err } @@ -568,7 +561,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag case "GET": // Get a resource. var handler restful.RouteFunction if isGetterWithOptions { - handler = restfulGetResourceWithOptions(getterWithOptions, reqScope, hasSubresource) + handler = restfulGetResourceWithOptions(getterWithOptions, reqScope, isSubresource) } else { handler = restfulGetResource(getter, exporter, reqScope) } @@ -581,10 +574,10 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag } if a.enableAPIResponseCompression { - handler = genericfilters.RestfulWithCompression(handler, a.group.Context) + handler = genericfilters.RestfulWithCompression(handler) } doc := "read the specified " + kind - if hasSubresource { + if isSubresource { doc = "read " + subresource + " of the specified " + kind } route := ws.GET(action.Path).To(handler). @@ -608,12 +601,12 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag routes = append(routes, route) case "LIST": // List all resources of a kind. doc := "list objects of kind " + kind - if hasSubresource { + if isSubresource { doc = "list " + subresource + " of objects of kind " + kind } handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, false, a.minRequestTimeout)) if a.enableAPIResponseCompression { - handler = genericfilters.RestfulWithCompression(handler, a.group.Context) + handler = genericfilters.RestfulWithCompression(handler) } route := ws.GET(action.Path).To(handler). Doc(doc). @@ -628,13 +621,13 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag switch { case isLister && isWatcher: doc := "list or watch objects of kind " + kind - if hasSubresource { + if isSubresource { doc = "list or watch " + subresource + " of objects of kind " + kind } route.Doc(doc) case isWatcher: doc := "watch objects of kind " + kind - if hasSubresource { + if isSubresource { doc = "watch " + subresource + "of objects of kind " + kind } route.Doc(doc) @@ -643,10 +636,10 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag routes = append(routes, route) case "PUT": // Update a resource. doc := "replace the specified " + kind - if hasSubresource { + if isSubresource { doc = "replace " + subresource + " of the specified " + kind } - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulUpdateResource(updater, reqScope, a.group.Typer, admit)) + handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulUpdateResource(updater, reqScope, admit)) route := ws.PUT(action.Path).To(handler). Doc(doc). Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). @@ -662,7 +655,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag routes = append(routes, route) case "PATCH": // Partially update a resource doc := "partially update the specified " + kind - if hasSubresource { + if isSubresource { doc = "partially update " + subresource + " of the specified " + kind } supportedTypes := []string{ @@ -670,7 +663,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag string(types.MergePatchType), string(types.StrategicMergePatchType), } - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulPatchResource(patcher, reqScope, admit, mapping.ObjectConvertor, supportedTypes)) + handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulPatchResource(patcher, reqScope, admit, supportedTypes)) route := ws.PATCH(action.Path).To(handler). Doc(doc). Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). @@ -685,14 +678,14 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag case "POST": // Create a resource. var handler restful.RouteFunction if isNamedCreater { - handler = restfulCreateNamedResource(namedCreater, reqScope, a.group.Typer, admit) + handler = restfulCreateNamedResource(namedCreater, reqScope, admit) } else { - handler = restfulCreateResource(creater, reqScope, a.group.Typer, admit) + handler = restfulCreateResource(creater, reqScope, admit) } handler = metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, handler) article := getArticleForNoun(kind, " ") doc := "create" + article + kind - if hasSubresource { + if isSubresource { doc = "create " + subresource + " of" + article + kind } route := ws.POST(action.Path).To(handler). @@ -712,7 +705,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag case "DELETE": // Delete a resource. article := getArticleForNoun(kind, " ") doc := "delete" + article + kind - if hasSubresource { + if isSubresource { doc = "delete " + subresource + " of" + article + kind } handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulDeleteResource(gracefulDeleter, isGracefulDeleter, reqScope, admit)) @@ -733,7 +726,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag routes = append(routes, route) case "DELETECOLLECTION": doc := "delete collection of " + kind - if hasSubresource { + if isSubresource { doc = "delete collection of " + subresource + " of a " + kind } handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulDeleteCollection(collectionDeleter, isCollectionDeleter, reqScope, admit)) @@ -752,7 +745,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag // TODO: deprecated case "WATCH": // Watch a resource. doc := "watch changes to an object of kind " + kind - if hasSubresource { + if isSubresource { doc = "watch changes to " + subresource + " of an object of kind " + kind } handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout)) @@ -771,7 +764,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag // TODO: deprecated case "WATCHLIST": // Watch all resources of a kind. doc := "watch individual changes to a list of " + kind - if hasSubresource { + if isSubresource { doc = "watch individual changes to a list of " + subresource + " of " + kind } handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout)) @@ -794,10 +787,10 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag connectProducedObject = "string" } doc := "connect " + method + " requests to " + kind - if hasSubresource { + if isSubresource { doc = "connect " + method + " requests to " + subresource + " of " + kind } - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulConnectResource(connecter, reqScope, admit, path, hasSubresource)) + handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulConnectResource(connecter, reqScope, admit, path, isSubresource)) route := ws.Method(method).Path(action.Path). To(handler). Doc(doc). @@ -1016,15 +1009,15 @@ func restfulListResource(r rest.Lister, rw rest.Watcher, scope handlers.RequestS } } -func restfulCreateNamedResource(r rest.NamedCreater, scope handlers.RequestScope, typer runtime.ObjectTyper, admit admission.Interface) restful.RouteFunction { +func restfulCreateNamedResource(r rest.NamedCreater, scope handlers.RequestScope, admit admission.Interface) restful.RouteFunction { return func(req *restful.Request, res *restful.Response) { - handlers.CreateNamedResource(r, scope, typer, admit)(res.ResponseWriter, req.Request) + handlers.CreateNamedResource(r, scope, admit)(res.ResponseWriter, req.Request) } } -func restfulCreateResource(r rest.Creater, scope handlers.RequestScope, typer runtime.ObjectTyper, admit admission.Interface) restful.RouteFunction { +func restfulCreateResource(r rest.Creater, scope handlers.RequestScope, admit admission.Interface) restful.RouteFunction { return func(req *restful.Request, res *restful.Response) { - handlers.CreateResource(r, scope, typer, admit)(res.ResponseWriter, req.Request) + handlers.CreateResource(r, scope, admit)(res.ResponseWriter, req.Request) } } @@ -1040,15 +1033,15 @@ func restfulDeleteCollection(r rest.CollectionDeleter, checkBody bool, scope han } } -func restfulUpdateResource(r rest.Updater, scope handlers.RequestScope, typer runtime.ObjectTyper, admit admission.Interface) restful.RouteFunction { +func restfulUpdateResource(r rest.Updater, scope handlers.RequestScope, admit admission.Interface) restful.RouteFunction { return func(req *restful.Request, res *restful.Response) { - handlers.UpdateResource(r, scope, typer, admit)(res.ResponseWriter, req.Request) + handlers.UpdateResource(r, scope, admit)(res.ResponseWriter, req.Request) } } -func restfulPatchResource(r rest.Patcher, scope handlers.RequestScope, admit admission.Interface, converter runtime.ObjectConvertor, supportedTypes []string) restful.RouteFunction { +func restfulPatchResource(r rest.Patcher, scope handlers.RequestScope, admit admission.Interface, supportedTypes []string) restful.RouteFunction { return func(req *restful.Request, res *restful.Response) { - handlers.PatchResource(r, scope, admit, converter, supportedTypes)(res.ResponseWriter, req.Request) + handlers.PatchResource(r, scope, admit, supportedTypes)(res.ResponseWriter, req.Request) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go index d3f155c11..516452e16 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go @@ -18,12 +18,12 @@ package metrics import ( "bufio" - //"fmt" "net" "net/http" "regexp" "strconv" "strings" + "sync" "time" utilnet "k8s.io/apimachinery/pkg/util/net" @@ -33,6 +33,13 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +// resettableCollector is the interface implemented by prometheus.MetricVec +// that can be used by Prometheus to collect metrics and reset their values. +type resettableCollector interface { + prometheus.Collector + Reset() +} + var ( // TODO(a-robinson): Add unit tests for the handling of these metrics once // the upstream library supports it. @@ -86,6 +93,14 @@ var ( }, []string{"requestKind"}, ) + // RegisteredWatchers is a number of currently registered watchers splitted by resource. + RegisteredWatchers = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "apiserver_registered_watchers", + Help: "Number of currently registered watchers for a given resources", + }, + []string{"group", "version", "kind"}, + ) // Because of volatality of the base metric this is pre-aggregated one. Instead of reporing current usage all the time // it reports maximal usage during the last second. currentInflightRequests = prometheus.NewGaugeVec( @@ -96,6 +111,17 @@ var ( []string{"requestKind"}, ) kubectlExeRegexp = regexp.MustCompile(`^.*((?i:kubectl\.exe))`) + + metrics = []resettableCollector{ + requestCounter, + longRunningRequestGauge, + requestLatencies, + requestLatenciesSummary, + responseSizes, + DroppedRequests, + RegisteredWatchers, + currentInflightRequests, + } ) const ( @@ -105,15 +131,22 @@ const ( MutatingKind = "mutating" ) -func init() { - // Register all metrics. - prometheus.MustRegister(requestCounter) - prometheus.MustRegister(longRunningRequestGauge) - prometheus.MustRegister(requestLatencies) - prometheus.MustRegister(requestLatenciesSummary) - prometheus.MustRegister(responseSizes) - prometheus.MustRegister(DroppedRequests) - prometheus.MustRegister(currentInflightRequests) +var registerMetrics sync.Once + +// Register all metrics. +func Register() { + registerMetrics.Do(func() { + for _, metric := range metrics { + prometheus.MustRegister(metric) + } + }) +} + +// Reset all metrics. +func Reset() { + for _, metric := range metrics { + metric.Reset() + } } func UpdateInflightRequestMetrics(nonmutating, mutating int) { @@ -170,13 +203,6 @@ func MonitorRequest(req *http.Request, verb, resource, subresource, scope, conte } } -func Reset() { - requestCounter.Reset() - requestLatencies.Reset() - requestLatenciesSummary.Reset() - responseSizes.Reset() -} - // InstrumentRouteFunc works like Prometheus' InstrumentHandlerFunc but wraps // the go-restful RouteFunction instead of a HandlerFunc plus some Kubernetes endpoint specific information. func InstrumentRouteFunc(verb, resource, subresource, scope string, routeFunc restful.RouteFunction) restful.RouteFunction { @@ -198,7 +224,7 @@ func InstrumentRouteFunc(verb, resource, subresource, scope string, routeFunc re routeFunc(request, response) - MonitorRequest(request.Request, verb, resource, subresource, scope, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Now().Sub(now)) + MonitorRequest(request.Request, verb, resource, subresource, scope, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now)) }) } @@ -220,7 +246,7 @@ func InstrumentHandlerFunc(verb, resource, subresource, scope string, handler ht handler(w, req) - MonitorRequest(req, verb, resource, subresource, scope, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Now().Sub(now)) + MonitorRequest(req, verb, resource, subresource, scope, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now)) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/openapi/openapi.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/openapi/openapi.go index 7b8f3589e..e512f29b3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/openapi/openapi.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/openapi/openapi.go @@ -143,12 +143,24 @@ func typeName(t reflect.Type) string { } // NewDefinitionNamer constructs a new DefinitionNamer to be used to customize OpenAPI spec. -func NewDefinitionNamer(s *runtime.Scheme) DefinitionNamer { - ret := DefinitionNamer{ +func NewDefinitionNamer(schemes ...*runtime.Scheme) *DefinitionNamer { + ret := &DefinitionNamer{ typeGroupVersionKinds: map[string]groupVersionKinds{}, } - for gvk, rtype := range s.AllKnownTypes() { - ret.typeGroupVersionKinds[typeName(rtype)] = append(ret.typeGroupVersionKinds[typeName(rtype)], gvkConvert(gvk)) + for _, s := range schemes { + for gvk, rtype := range s.AllKnownTypes() { + newGVK := gvkConvert(gvk) + exists := false + for _, existingGVK := range ret.typeGroupVersionKinds[typeName(rtype)] { + if newGVK == existingGVK { + exists = true + break + } + } + if !exists { + ret.typeGroupVersionKinds[typeName(rtype)] = append(ret.typeGroupVersionKinds[typeName(rtype)], newGVK) + } + } } for _, gvk := range ret.typeGroupVersionKinds { sort.Sort(gvk) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/openapi/testing/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/openapi/testing/zz_generated.deepcopy.go index fbc7e0d9d..63d386c50 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/openapi/testing/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/openapi/testing/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/patchhandler_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/patchhandler_test.go new file mode 100644 index 000000000..6d0475c77 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/patchhandler_test.go @@ -0,0 +1,99 @@ +/* +Copyright 2018 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 endpoints + +import ( + "bytes" + "net/http" + "net/http/httptest" + "net/http/httputil" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + genericapitesting "k8s.io/apiserver/pkg/endpoints/testing" + "k8s.io/apiserver/pkg/registry/rest" +) + +func TestPatch(t *testing.T) { + storage := map[string]rest.Storage{} + ID := "id" + item := &genericapitesting.Simple{ + ObjectMeta: metav1.ObjectMeta{ + Name: ID, + Namespace: "", // update should allow the client to send an empty namespace + UID: "uid", + }, + Other: "bar", + } + simpleStorage := SimpleRESTStorage{item: *item} + storage["simple"] = &simpleStorage + selfLinker := &setTestSelfLinker{ + t: t, + expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + ID, + name: ID, + namespace: metav1.NamespaceDefault, + } + handler := handleLinker(storage, selfLinker) + server := httptest.NewServer(handler) + defer server.Close() + + client := http.Client{} + request, err := http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`))) + request.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8") + response, err := client.Do(request) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + dump, _ := httputil.DumpResponse(response, true) + t.Log(string(dump)) + + if simpleStorage.updated == nil || simpleStorage.updated.Labels["foo"] != "bar" { + t.Errorf("Unexpected update value %#v, expected %#v.", simpleStorage.updated, item) + } + if !selfLinker.called { + t.Errorf("Never set self link") + } +} + +func TestPatchRequiresMatchingName(t *testing.T) { + storage := map[string]rest.Storage{} + ID := "id" + item := &genericapitesting.Simple{ + ObjectMeta: metav1.ObjectMeta{ + Name: ID, + Namespace: "", // update should allow the client to send an empty namespace + UID: "uid", + }, + Other: "bar", + } + simpleStorage := SimpleRESTStorage{item: *item} + storage["simple"] = &simpleStorage + handler := handle(storage) + server := httptest.NewServer(handler) + defer server.Close() + + client := http.Client{} + request, err := http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"metadata":{"name":"idbar"}}`))) + request.Header.Set("Content-Type", "application/merge-patch+json") + response, err := client.Do(request) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if response.StatusCode != http.StatusBadRequest { + t.Errorf("Unexpected response %#v", response) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/BUILD index bda772f4e..03f1db710 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/BUILD @@ -8,11 +8,15 @@ load( go_test( name = "go_default_test", - srcs = ["requestinfo_test.go"], + srcs = [ + "context_test.go", + "requestinfo_test.go", + ], embed = [":go_default_library"], deps = [ "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", ], ) @@ -21,32 +25,20 @@ go_library( srcs = [ "context.go", "doc.go", - "requestcontext.go", "requestinfo.go", ], importpath = "k8s.io/apiserver/pkg/endpoints/request", deps = [ "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/validation/path:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", ], ) -go_test( - name = "go_default_xtest", - srcs = ["context_test.go"], - deps = [ - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", - ], -) - filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/context.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/context.go index e64facc5c..95166f5c4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/context.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/context.go @@ -17,38 +17,13 @@ limitations under the License. package request import ( - stderrs "errors" - "time" + "context" - "golang.org/x/net/context" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/apis/audit" "k8s.io/apiserver/pkg/authentication/user" ) -// Context carries values across API boundaries. -// This context matches the context.Context interface -// (https://blog.golang.org/context), for the purposes -// of passing the api.Context through to the storage tier. -// TODO: Determine the extent that this abstraction+interface -// is used by the api, and whether we can remove. -type Context interface { - // Value returns the value associated with key or nil if none. - Value(key interface{}) interface{} - - // Deadline returns the time when this Context will be canceled, if any. - Deadline() (deadline time.Time, ok bool) - - // Done returns a channel that is closed when this Context is canceled - // or times out. - Done() <-chan struct{} - - // Err indicates why this context was canceled, after the Done channel - // is closed. - Err() error -} - // The key type is unexported to prevent collisions type key int @@ -59,101 +34,60 @@ const ( // userKey is the context key for the request user. userKey - // uidKey is the context key for the uid to assign to an object on create. - uidKey - - // userAgentKey is the context key for the request user agent. - userAgentKey - // auditKey is the context key for the audit event. auditKey ) // NewContext instantiates a base context object for request flows. -func NewContext() Context { +func NewContext() context.Context { return context.TODO() } // NewDefaultContext instantiates a base context object for request flows in the default namespace -func NewDefaultContext() Context { +func NewDefaultContext() context.Context { return WithNamespace(NewContext(), metav1.NamespaceDefault) } // WithValue returns a copy of parent in which the value associated with key is val. -func WithValue(parent Context, key interface{}, val interface{}) Context { - internalCtx, ok := parent.(context.Context) - if !ok { - panic(stderrs.New("Invalid context type")) - } - return context.WithValue(internalCtx, key, val) +func WithValue(parent context.Context, key interface{}, val interface{}) context.Context { + return context.WithValue(parent, key, val) } // WithNamespace returns a copy of parent in which the namespace value is set -func WithNamespace(parent Context, namespace string) Context { +func WithNamespace(parent context.Context, namespace string) context.Context { return WithValue(parent, namespaceKey, namespace) } // NamespaceFrom returns the value of the namespace key on the ctx -func NamespaceFrom(ctx Context) (string, bool) { +func NamespaceFrom(ctx context.Context) (string, bool) { namespace, ok := ctx.Value(namespaceKey).(string) return namespace, ok } // NamespaceValue returns the value of the namespace key on the ctx, or the empty string if none -func NamespaceValue(ctx Context) string { +func NamespaceValue(ctx context.Context) string { namespace, _ := NamespaceFrom(ctx) return namespace } -// WithNamespaceDefaultIfNone returns a context whose namespace is the default if and only if the parent context has no namespace value -func WithNamespaceDefaultIfNone(parent Context) Context { - namespace, ok := NamespaceFrom(parent) - if !ok || len(namespace) == 0 { - return WithNamespace(parent, metav1.NamespaceDefault) - } - return parent -} - // WithUser returns a copy of parent in which the user value is set -func WithUser(parent Context, user user.Info) Context { +func WithUser(parent context.Context, user user.Info) context.Context { return WithValue(parent, userKey, user) } // UserFrom returns the value of the user key on the ctx -func UserFrom(ctx Context) (user.Info, bool) { +func UserFrom(ctx context.Context) (user.Info, bool) { user, ok := ctx.Value(userKey).(user.Info) return user, ok } -// WithUID returns a copy of parent in which the uid value is set -func WithUID(parent Context, uid types.UID) Context { - return WithValue(parent, uidKey, uid) -} - -// UIDFrom returns the value of the uid key on the ctx -func UIDFrom(ctx Context) (types.UID, bool) { - uid, ok := ctx.Value(uidKey).(types.UID) - return uid, ok -} - -// WithUserAgent returns a copy of parent in which the user value is set -func WithUserAgent(parent Context, userAgent string) Context { - return WithValue(parent, userAgentKey, userAgent) -} - -// UserAgentFrom returns the value of the userAgent key on the ctx -func UserAgentFrom(ctx Context) (string, bool) { - userAgent, ok := ctx.Value(userAgentKey).(string) - return userAgent, ok -} - // WithAuditEvent returns set audit event struct. -func WithAuditEvent(parent Context, ev *audit.Event) Context { +func WithAuditEvent(parent context.Context, ev *audit.Event) context.Context { return WithValue(parent, auditKey, ev) } // AuditEventFrom returns the audit event struct on the ctx -func AuditEventFrom(ctx Context) *audit.Event { +func AuditEventFrom(ctx context.Context) *audit.Event { ev, _ := ctx.Value(auditKey).(*audit.Event) return ev } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/context_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/context_test.go index 365cb114e..72b3124b4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/context_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/context_test.go @@ -14,21 +14,19 @@ See the License for the specific language governing permissions and limitations under the License. */ -package request_test +package request import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/authentication/user" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) // TestNamespaceContext validates that a namespace can be get/set on a context object func TestNamespaceContext(t *testing.T) { - ctx := genericapirequest.NewDefaultContext() - result, ok := genericapirequest.NamespaceFrom(ctx) + ctx := NewDefaultContext() + result, ok := NamespaceFrom(ctx) if !ok { t.Fatalf("Error getting namespace") } @@ -36,8 +34,8 @@ func TestNamespaceContext(t *testing.T) { t.Fatalf("Expected: %s, Actual: %s", metav1.NamespaceDefault, result) } - ctx = genericapirequest.NewContext() - result, ok = genericapirequest.NamespaceFrom(ctx) + ctx = NewContext() + result, ok = NamespaceFrom(ctx) if ok { t.Fatalf("Should not be ok because there is no namespace on the context") } @@ -45,12 +43,12 @@ func TestNamespaceContext(t *testing.T) { //TestUserContext validates that a userinfo can be get/set on a context object func TestUserContext(t *testing.T) { - ctx := genericapirequest.NewContext() - _, ok := genericapirequest.UserFrom(ctx) + ctx := NewContext() + _, ok := UserFrom(ctx) if ok { t.Fatalf("Should not be ok because there is no user.Info on the context") } - ctx = genericapirequest.WithUser( + ctx = WithUser( ctx, &user.DefaultInfo{ Name: "bob", @@ -60,7 +58,7 @@ func TestUserContext(t *testing.T) { }, ) - result, ok := genericapirequest.UserFrom(ctx) + result, ok := UserFrom(ctx) if !ok { t.Fatalf("Error getting user info") } @@ -93,42 +91,3 @@ func TestUserContext(t *testing.T) { } } - -//TestUIDContext validates that a UID can be get/set on a context object -func TestUIDContext(t *testing.T) { - ctx := genericapirequest.NewContext() - _, ok := genericapirequest.UIDFrom(ctx) - if ok { - t.Fatalf("Should not be ok because there is no UID on the context") - } - ctx = genericapirequest.WithUID( - ctx, - types.UID("testUID"), - ) - _, ok = genericapirequest.UIDFrom(ctx) - if !ok { - t.Fatalf("Error getting UID") - } -} - -//TestUserAgentContext validates that a useragent can be get/set on a context object -func TestUserAgentContext(t *testing.T) { - ctx := genericapirequest.NewContext() - _, ok := genericapirequest.UserAgentFrom(ctx) - if ok { - t.Fatalf("Should not be ok because there is no UserAgent on the context") - } - - ctx = genericapirequest.WithUserAgent( - ctx, - "TestUserAgent", - ) - result, ok := genericapirequest.UserAgentFrom(ctx) - if !ok { - t.Fatalf("Error getting UserAgent") - } - expectedResult := "TestUserAgent" - if result != expectedResult { - t.Fatalf("Get user agent error, Expected: %s, Actual: %s", expectedResult, result) - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestcontext.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestcontext.go deleted file mode 100644 index 3dc771baf..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestcontext.go +++ /dev/null @@ -1,120 +0,0 @@ -/* -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 request - -import ( - "errors" - "net/http" - "sync" - - "github.com/golang/glog" -) - -// LongRunningRequestCheck is a predicate which is true for long-running http requests. -type LongRunningRequestCheck func(r *http.Request, requestInfo *RequestInfo) bool - -// RequestContextMapper keeps track of the context associated with a particular request -type RequestContextMapper interface { - // Get returns the context associated with the given request (if any), and true if the request has an associated context, and false if it does not. - Get(req *http.Request) (Context, bool) - // Update maps the request to the given context. If no context was previously associated with the request, an error is returned. - // Update should only be called with a descendant context of the previously associated context. - // Updating to an unrelated context may return an error in the future. - // The context associated with a request should only be updated by a limited set of callers. - // Valid examples include the authentication layer, or an audit/tracing layer. - Update(req *http.Request, context Context) error -} - -type requestContextMap struct { - contexts map[*http.Request]Context - lock sync.Mutex -} - -// NewRequestContextMapper returns a new RequestContextMapper. -// The returned mapper must be added as a request filter using NewRequestContextFilter. -func NewRequestContextMapper() RequestContextMapper { - return &requestContextMap{ - contexts: make(map[*http.Request]Context), - } -} - -// Get returns the context associated with the given request (if any), and true if the request has an associated context, and false if it does not. -// Get will only return a valid context when called from inside the filter chain set up by NewRequestContextFilter() -func (c *requestContextMap) Get(req *http.Request) (Context, bool) { - c.lock.Lock() - defer c.lock.Unlock() - context, ok := c.contexts[req] - return context, ok -} - -// Update maps the request to the given context. -// If no context was previously associated with the request, an error is returned and the context is ignored. -func (c *requestContextMap) Update(req *http.Request, context Context) error { - c.lock.Lock() - defer c.lock.Unlock() - if _, ok := c.contexts[req]; !ok { - return errors.New("No context associated") - } - // TODO: ensure the new context is a descendant of the existing one - c.contexts[req] = context - return nil -} - -// init maps the request to the given context and returns true if there was no context associated with the request already. -// if a context was already associated with the request, it ignores the given context and returns false. -// init is intentionally unexported to ensure that all init calls are paired with a remove after a request is handled -func (c *requestContextMap) init(req *http.Request, context Context) bool { - c.lock.Lock() - defer c.lock.Unlock() - if _, exists := c.contexts[req]; exists { - return false - } - c.contexts[req] = context - return true -} - -// remove is intentionally unexported to ensure that the context is not removed until a request is handled -func (c *requestContextMap) remove(req *http.Request) { - c.lock.Lock() - defer c.lock.Unlock() - delete(c.contexts, req) -} - -// WithRequestContext ensures there is a Context object associated with the request before calling the passed handler. -// After the passed handler runs, the context is cleaned up. -func WithRequestContext(handler http.Handler, mapper RequestContextMapper) http.Handler { - rcMap, ok := mapper.(*requestContextMap) - if !ok { - glog.Fatal("Unknown RequestContextMapper implementation.") - } - - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - if rcMap.init(req, NewContext()) { - // If we were the ones to successfully initialize, pair with a remove - defer rcMap.remove(req) - } - handler.ServeHTTP(w, req) - }) -} - -// IsEmpty returns true if there are no contexts registered, or an error if it could not be determined. Intended for use by tests. -func IsEmpty(requestsToContexts RequestContextMapper) (bool, error) { - if requestsToContexts, ok := requestsToContexts.(*requestContextMap); ok { - return len(requestsToContexts.contexts) == 0, nil - } - return true, errors.New("Unknown RequestContextMapper implementation") -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestinfo.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestinfo.go index ddbbde399..1520bb3c9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestinfo.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestinfo.go @@ -17,14 +17,22 @@ limitations under the License. package request import ( + "context" "fmt" "net/http" "strings" + "k8s.io/apimachinery/pkg/api/validation/path" + metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + + "github.com/golang/glog" ) +// LongRunningRequestCheck is a predicate which is true for long-running http requests. +type LongRunningRequestCheck func(r *http.Request, requestInfo *RequestInfo) bool + type RequestInfoResolver interface { NewRequestInfo(req *http.Request) (*RequestInfo, error) } @@ -199,19 +207,35 @@ func (r *RequestInfoFactory) NewRequestInfo(req *http.Request) (*RequestInfo, er // if there's no name on the request and we thought it was a get before, then the actual verb is a list or a watch if len(requestInfo.Name) == 0 && requestInfo.Verb == "get" { - // Assumes v1.ListOptions - // Any query value that is not 0 or false is considered true - // see apimachinery/pkg/runtime/conversion.go Convert_Slice_string_To_bool - if values := req.URL.Query()["watch"]; len(values) > 0 { - switch strings.ToLower(values[0]) { - case "false", "0": - requestInfo.Verb = "list" - default: - requestInfo.Verb = "watch" + opts := metainternalversion.ListOptions{} + if err := metainternalversion.ParameterCodec.DecodeParameters(req.URL.Query(), metav1.SchemeGroupVersion, &opts); err != nil { + // An error in parsing request will result in default to "list" and not setting "name" field. + glog.Errorf("Couldn't parse request %#v: %v", req.URL.Query(), err) + // Reset opts to not rely on partial results from parsing. + // However, if watch is set, let's report it. + opts = metainternalversion.ListOptions{} + if values := req.URL.Query()["watch"]; len(values) > 0 { + switch strings.ToLower(values[0]) { + case "false", "0": + default: + opts.Watch = true + } } + } + + if opts.Watch { + requestInfo.Verb = "watch" } else { requestInfo.Verb = "list" } + + if opts.FieldSelector != nil { + if name, ok := opts.FieldSelector.RequiresExactMatch("metadata.name"); ok { + if len(path.IsValidPathSegmentName(name)) == 0 { + requestInfo.Name = name + } + } + } } // if there's no name on the request and we thought it was a delete before, then the actual verb is deletecollection if len(requestInfo.Name) == 0 && requestInfo.Verb == "delete" { @@ -229,12 +253,12 @@ type requestInfoKeyType int const requestInfoKey requestInfoKeyType = iota // WithRequestInfo returns a copy of parent in which the request info value is set -func WithRequestInfo(parent Context, info *RequestInfo) Context { +func WithRequestInfo(parent context.Context, info *RequestInfo) context.Context { return WithValue(parent, requestInfoKey, info) } // RequestInfoFrom returns the value of the RequestInfo key on the ctx -func RequestInfoFrom(ctx Context) (*RequestInfo, bool) { +func RequestInfoFrom(ctx context.Context) (*RequestInfo, bool) { info, ok := ctx.Value(requestInfoKey).(*RequestInfo) return info, ok } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestinfo_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestinfo_test.go index 9d5a4dbf9..a5c521e5b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestinfo_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestinfo_test.go @@ -17,20 +17,16 @@ limitations under the License. package request import ( + "fmt" "net/http" "reflect" + "strings" "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" ) -type fakeRL bool - -func (fakeRL) Stop() {} -func (f fakeRL) TryAccept() bool { return bool(f) } -func (f fakeRL) Accept() {} - func TestGetAPIRequestInfo(t *testing.T) { namespaceAll := metav1.NamespaceAll successCases := []struct { @@ -193,3 +189,77 @@ func newTestRequestInfoResolver() *RequestInfoFactory { GrouplessAPIPrefixes: sets.NewString("api"), } } + +func TestFieldSelectorParsing(t *testing.T) { + tests := []struct { + name string + url string + expectedName string + expectedErr error + expectedVerb string + }{ + { + name: "no selector", + url: "/apis/group/version/resource", + expectedVerb: "list", + }, + { + name: "metadata.name selector", + url: "/apis/group/version/resource?fieldSelector=metadata.name=name1", + expectedName: "name1", + expectedVerb: "list", + }, + { + name: "metadata.name selector with watch", + url: "/apis/group/version/resource?watch=true&fieldSelector=metadata.name=name1", + expectedName: "name1", + expectedVerb: "watch", + }, + { + name: "random selector", + url: "/apis/group/version/resource?fieldSelector=foo=bar", + expectedName: "", + expectedVerb: "list", + }, + { + name: "invalid selector with metadata.name", + url: "/apis/group/version/resource?fieldSelector=metadata.name=name1,foo", + expectedName: "", + expectedErr: fmt.Errorf("invalid selector"), + expectedVerb: "list", + }, + { + name: "invalid selector with metadata.name with watch", + url: "/apis/group/version/resource?fieldSelector=metadata.name=name1,foo&watch=true", + expectedName: "", + expectedErr: fmt.Errorf("invalid selector"), + expectedVerb: "watch", + }, + { + name: "invalid selector with metadata.name with watch false", + url: "/apis/group/version/resource?fieldSelector=metadata.name=name1,foo&watch=false", + expectedName: "", + expectedErr: fmt.Errorf("invalid selector"), + expectedVerb: "list", + }, + } + + resolver := newTestRequestInfoResolver() + + for _, tc := range tests { + req, _ := http.NewRequest("GET", tc.url, nil) + + apiRequestInfo, err := resolver.NewRequestInfo(req) + if err != nil { + if tc.expectedErr == nil || !strings.Contains(err.Error(), tc.expectedErr.Error()) { + t.Errorf("%s: Unexpected error %v", tc.name, err) + } + } + if e, a := tc.expectedName, apiRequestInfo.Name; e != a { + t.Errorf("%s: expected %v, actual %v", tc.name, e, a) + } + if e, a := tc.expectedVerb, apiRequestInfo.Verb; e != a { + t.Errorf("%s: expected verb %v, actual %v", tc.name, e, a) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/testing/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/testing/zz_generated.deepcopy.go index e5e497716..ff3e39514 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/testing/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/testing/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/features/OWNERS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/features/OWNERS new file mode 100644 index 000000000..fe7b0144e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/features/OWNERS @@ -0,0 +1,2 @@ +approvers: +- feature-approvers diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/BUILD index f6f70d86c..f90f3df3a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/BUILD @@ -57,7 +57,6 @@ go_library( importpath = "k8s.io/apiserver/pkg/registry/generic/registry", deps = [ "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/validation/path:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/decorated_watcher.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/decorated_watcher.go index d131ba80e..f589dd1ec 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/decorated_watcher.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/decorated_watcher.go @@ -17,10 +17,9 @@ limitations under the License. package registry import ( + "context" "net/http" - "golang.org/x/net/context" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go index d7e449c25..1e799c6e2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go @@ -17,6 +17,7 @@ limitations under the License. package registry import ( + "context" "fmt" "reflect" "strings" @@ -99,14 +100,14 @@ type Store struct { // entire collection (listing and watching). // // KeyRootFunc and KeyFunc must be supplied together or not at all. - KeyRootFunc func(ctx genericapirequest.Context) string + KeyRootFunc func(ctx context.Context) string // KeyFunc returns the key for a specific object in the collection. // KeyFunc is called for Create/Update/Get/Delete. Note that 'namespace' // can be gotten from ctx. // // KeyFunc and KeyRootFunc must be supplied together or not at all. - KeyFunc func(ctx genericapirequest.Context, name string) (string, error) + KeyFunc func(ctx context.Context, name string) (string, error) // ObjectNameFunc returns the name of an object or an error. ObjectNameFunc func(obj runtime.Object) (string, error) @@ -190,7 +191,7 @@ const ( // NamespaceKeyRootFunc is the default function for constructing storage paths // to resource directories enforcing namespace rules. -func NamespaceKeyRootFunc(ctx genericapirequest.Context, prefix string) string { +func NamespaceKeyRootFunc(ctx context.Context, prefix string) string { key := prefix ns, ok := genericapirequest.NamespaceFrom(ctx) if ok && len(ns) > 0 { @@ -202,7 +203,7 @@ func NamespaceKeyRootFunc(ctx genericapirequest.Context, prefix string) string { // NamespaceKeyFunc is the default function for constructing storage paths to // a resource relative to the given prefix enforcing namespace rules. If the // context does not contain a namespace, it errors. -func NamespaceKeyFunc(ctx genericapirequest.Context, prefix string, name string) (string, error) { +func NamespaceKeyFunc(ctx context.Context, prefix string, name string) (string, error) { key := NamespaceKeyRootFunc(ctx, prefix) ns, ok := genericapirequest.NamespaceFrom(ctx) if !ok || len(ns) == 0 { @@ -220,7 +221,7 @@ func NamespaceKeyFunc(ctx genericapirequest.Context, prefix string, name string) // NoNamespaceKeyFunc is the default function for constructing storage paths // to a resource relative to the given prefix without a namespace. -func NoNamespaceKeyFunc(ctx genericapirequest.Context, prefix string, name string) (string, error) { +func NoNamespaceKeyFunc(ctx context.Context, prefix string, name string) (string, error) { if len(name) == 0 { return "", kubeerr.NewBadRequest("Name parameter required.") } @@ -241,6 +242,18 @@ func (e *Store) NewList() runtime.Object { return e.NewListFunc() } +// NamespaceScoped indicates whether the resource is namespaced +func (e *Store) NamespaceScoped() bool { + if e.CreateStrategy != nil { + return e.CreateStrategy.NamespaceScoped() + } + if e.UpdateStrategy != nil { + return e.UpdateStrategy.NamespaceScoped() + } + + panic("programmer error: no CRUD for resource, you're crazy, override NamespaceScoped too") +} + // GetCreateStrategy implements GenericStore. func (e *Store) GetCreateStrategy() rest.RESTCreateStrategy { return e.CreateStrategy @@ -263,7 +276,7 @@ func (e *Store) GetExportStrategy() rest.RESTExportStrategy { // List returns a list of items matching labels and field according to the // store's PredicateFunc. -func (e *Store) List(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { +func (e *Store) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) { label := labels.Everything() if options != nil && options.LabelSelector != nil { label = options.LabelSelector @@ -286,7 +299,7 @@ func (e *Store) List(ctx genericapirequest.Context, options *metainternalversion // ListPredicate returns a list of all the items matching the given // SelectionPredicate. -func (e *Store) ListPredicate(ctx genericapirequest.Context, p storage.SelectionPredicate, options *metainternalversion.ListOptions) (runtime.Object, error) { +func (e *Store) ListPredicate(ctx context.Context, p storage.SelectionPredicate, options *metainternalversion.ListOptions) (runtime.Object, error) { if options == nil { // By default we should serve the request from etcd. options = &metainternalversion.ListOptions{ResourceVersion: ""} @@ -309,7 +322,7 @@ func (e *Store) ListPredicate(ctx genericapirequest.Context, p storage.Selection } // Create inserts a new item according to the unique key from the object. -func (e *Store) Create(ctx genericapirequest.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { +func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) { if err := rest.BeforeCreate(e.CreateStrategy, ctx, obj); err != nil { return nil, err } @@ -360,7 +373,7 @@ func (e *Store) Create(ctx genericapirequest.Context, obj runtime.Object, create } } if e.Decorator != nil { - if err := e.Decorator(obj); err != nil { + if err := e.Decorator(out); err != nil { return nil, err } } @@ -372,7 +385,7 @@ func (e *Store) Create(ctx genericapirequest.Context, obj runtime.Object, create // WaitForInitialized holds until the object is initialized, or returns an error if the default limit expires. // This method is exposed publicly for consumers of generic rest tooling. -func (e *Store) WaitForInitialized(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { +func (e *Store) WaitForInitialized(ctx context.Context, obj runtime.Object) (runtime.Object, error) { // return early if we don't have initializers, or if they've completed already accessor, err := meta.Accessor(obj) if err != nil { @@ -445,6 +458,7 @@ func (e *Store) WaitForInitialized(ctx genericapirequest.Context, obj runtime.Ob } } case <-ctx.Done(): + return nil, ctx.Err() } } } @@ -452,7 +466,7 @@ func (e *Store) WaitForInitialized(ctx genericapirequest.Context, obj runtime.Ob // shouldDeleteDuringUpdate checks if a Update is removing all the object's // finalizers. If so, it further checks if the object's // DeletionGracePeriodSeconds is 0. -func (e *Store) shouldDeleteDuringUpdate(ctx genericapirequest.Context, key string, obj, existing runtime.Object) bool { +func (e *Store) shouldDeleteDuringUpdate(ctx context.Context, key string, obj, existing runtime.Object) bool { newMeta, err := meta.Accessor(obj) if err != nil { utilruntime.HandleError(err) @@ -468,7 +482,7 @@ func (e *Store) shouldDeleteDuringUpdate(ctx genericapirequest.Context, key stri // shouldDeleteForFailedInitialization returns true if the provided object is initializing and has // a failure recorded. -func (e *Store) shouldDeleteForFailedInitialization(ctx genericapirequest.Context, obj runtime.Object) bool { +func (e *Store) shouldDeleteForFailedInitialization(ctx context.Context, obj runtime.Object) bool { m, err := meta.Accessor(obj) if err != nil { utilruntime.HandleError(err) @@ -482,7 +496,7 @@ func (e *Store) shouldDeleteForFailedInitialization(ctx genericapirequest.Contex // deleteWithoutFinalizers handles deleting an object ignoring its finalizer list. // Used for objects that are either been finalized or have never initialized. -func (e *Store) deleteWithoutFinalizers(ctx genericapirequest.Context, name, key string, obj runtime.Object, preconditions *storage.Preconditions) (runtime.Object, bool, error) { +func (e *Store) deleteWithoutFinalizers(ctx context.Context, name, key string, obj runtime.Object, preconditions *storage.Preconditions) (runtime.Object, bool, error) { out := e.NewFunc() glog.V(6).Infof("going to delete %s from registry, triggered by update", name) if err := e.Storage.Delete(ctx, key, out, preconditions); err != nil { @@ -508,7 +522,7 @@ func (e *Store) deleteWithoutFinalizers(ctx genericapirequest.Context, name, key // Update performs an atomic update and set of the object. Returns the result of the update // or an error. If the registry allows create-on-update, the create flow will be executed. // A bool is returned along with the object and any errors, to indicate object creation. -func (e *Store) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { key, err := e.KeyFunc(ctx, name) if err != nil { return nil, false, err @@ -585,19 +599,15 @@ func (e *Store) Update(ctx genericapirequest.Context, name string, objInfo rest. } else { // Check if the object's resource version matches the latest // resource version. - newVersion, err := e.Storage.Versioner().ObjectResourceVersion(obj) - if err != nil { - return nil, nil, err - } - if newVersion == 0 { + if resourceVersion == 0 { // TODO: The Invalid error should have a field for Resource. // After that field is added, we should fill the Resource and // leave the Kind field empty. See the discussion in #18526. qualifiedKind := schema.GroupKind{Group: qualifiedResource.Group, Kind: qualifiedResource.Resource} - fieldErrList := field.ErrorList{field.Invalid(field.NewPath("metadata").Child("resourceVersion"), newVersion, "must be specified for an update")} + fieldErrList := field.ErrorList{field.Invalid(field.NewPath("metadata").Child("resourceVersion"), resourceVersion, "must be specified for an update")} return nil, nil, kubeerr.NewInvalid(qualifiedKind, name, fieldErrList) } - if newVersion != version { + if resourceVersion != version { return nil, nil, kubeerr.NewConflict(qualifiedResource, name, fmt.Errorf(OptimisticLockErrorMsg)) } } @@ -665,7 +675,7 @@ func (e *Store) Update(ctx genericapirequest.Context, name string, objInfo rest. } // Get retrieves the item from storage. -func (e *Store) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (e *Store) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { obj := e.NewFunc() key, err := e.KeyFunc(ctx, name) if err != nil { @@ -684,7 +694,7 @@ func (e *Store) Get(ctx genericapirequest.Context, name string, options *metav1. // qualifiedResourceFromContext attempts to retrieve a GroupResource from the context's request info. // If the context has no request info, DefaultQualifiedResource is used. -func (e *Store) qualifiedResourceFromContext(ctx genericapirequest.Context) schema.GroupResource { +func (e *Store) qualifiedResourceFromContext(ctx context.Context) schema.GroupResource { if info, ok := genericapirequest.RequestInfoFrom(ctx); ok { return schema.GroupResource{Group: info.APIGroup, Resource: info.Resource} } @@ -703,7 +713,7 @@ var ( // priority, there are three factors affect whether to add/remove the // FinalizerOrphanDependents: options, existing finalizers of the object, // and e.DeleteStrategy.DefaultGarbageCollectionPolicy. -func shouldOrphanDependents(ctx genericapirequest.Context, e *Store, accessor metav1.Object, options *metav1.DeleteOptions) bool { +func shouldOrphanDependents(ctx context.Context, e *Store, accessor metav1.Object, options *metav1.DeleteOptions) bool { // Get default GC policy from this REST object type gcStrategy, ok := e.DeleteStrategy.(rest.GarbageCollectionDeleteStrategy) var defaultGCPolicy rest.GarbageCollectionPolicy @@ -753,7 +763,7 @@ func shouldOrphanDependents(ctx genericapirequest.Context, e *Store, accessor me // priority, there are three factors affect whether to add/remove the // FinalizerDeleteDependents: options, existing finalizers of the object, and // e.DeleteStrategy.DefaultGarbageCollectionPolicy. -func shouldDeleteDependents(ctx genericapirequest.Context, e *Store, accessor metav1.Object, options *metav1.DeleteOptions) bool { +func shouldDeleteDependents(ctx context.Context, e *Store, accessor metav1.Object, options *metav1.DeleteOptions) bool { // Get default GC policy from this REST object type if gcStrategy, ok := e.DeleteStrategy.(rest.GarbageCollectionDeleteStrategy); ok && gcStrategy.DefaultGarbageCollectionPolicy(ctx) == rest.Unsupported { // return false to indicate that we should NOT delete in foreground @@ -796,7 +806,7 @@ func shouldDeleteDependents(ctx genericapirequest.Context, e *Store, accessor me // The finalizers returned are intended to be handled by the garbage collector. // If garbage collection is disabled for the store, this function returns false // to ensure finalizers aren't set which will never be cleared. -func deletionFinalizersForGarbageCollection(ctx genericapirequest.Context, e *Store, accessor metav1.Object, options *metav1.DeleteOptions) (bool, []string) { +func deletionFinalizersForGarbageCollection(ctx context.Context, e *Store, accessor metav1.Object, options *metav1.DeleteOptions) (bool, []string) { if !e.EnableGarbageCollection { return false, []string{} } @@ -860,7 +870,7 @@ func markAsDeleting(obj runtime.Object) (err error) { // should be deleted immediately // 4. a new output object with the state that was updated // 5. a copy of the last existing state of the object -func (e *Store) updateForGracefulDeletionAndFinalizers(ctx genericapirequest.Context, name, key string, options *metav1.DeleteOptions, preconditions storage.Preconditions, in runtime.Object) (err error, ignoreNotFound, deleteImmediately bool, out, lastExisting runtime.Object) { +func (e *Store) updateForGracefulDeletionAndFinalizers(ctx context.Context, name, key string, options *metav1.DeleteOptions, preconditions storage.Preconditions, in runtime.Object) (err error, ignoreNotFound, deleteImmediately bool, out, lastExisting runtime.Object) { lastGraceful := int64(0) var pendingFinalizers bool out = e.NewFunc() @@ -940,7 +950,7 @@ func (e *Store) updateForGracefulDeletionAndFinalizers(ctx genericapirequest.Con } // Delete removes the item from storage. -func (e *Store) Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { +func (e *Store) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) { key, err := e.KeyFunc(ctx, name) if err != nil { return nil, false, err @@ -1018,7 +1028,7 @@ func (e *Store) Delete(ctx genericapirequest.Context, name string, options *meta // are removing all objects of a given type) with the current API (it's technically // possibly with storage API, but watch is not delivered correctly then). // It will be possible to fix it with v3 etcd API. -func (e *Store) DeleteCollection(ctx genericapirequest.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) { +func (e *Store) DeleteCollection(ctx context.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) { if listOptions == nil { listOptions = &metainternalversion.ListOptions{} } else { @@ -1070,11 +1080,7 @@ func (e *Store) DeleteCollection(ctx genericapirequest.Context, options *metav1. }) defer wg.Done() - for { - index, ok := <-toProcess - if !ok { - return - } + for index := range toProcess { accessor, err := meta.Accessor(items[index]) if err != nil { errs <- err @@ -1099,7 +1105,7 @@ func (e *Store) DeleteCollection(ctx genericapirequest.Context, options *metav1. // finalizeDelete runs the Store's AfterDelete hook if runHooks is set and // returns the decorated deleted object if appropriate. -func (e *Store) finalizeDelete(ctx genericapirequest.Context, obj runtime.Object, runHooks bool) (runtime.Object, error) { +func (e *Store) finalizeDelete(ctx context.Context, obj runtime.Object, runHooks bool) (runtime.Object, error) { if runHooks && e.AfterDelete != nil { if err := e.AfterDelete(obj); err != nil { return nil, err @@ -1134,7 +1140,7 @@ func (e *Store) finalizeDelete(ctx genericapirequest.Context, obj runtime.Object // WatchPredicate. If possible, you should customize PredicateFunc to produce // a matcher that matches by key. SelectionPredicate does this for you // automatically. -func (e *Store) Watch(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { +func (e *Store) Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { label := labels.Everything() if options != nil && options.LabelSelector != nil { label = options.LabelSelector @@ -1154,7 +1160,7 @@ func (e *Store) Watch(ctx genericapirequest.Context, options *metainternalversio } // WatchPredicate starts a watch for the items that matches. -func (e *Store) WatchPredicate(ctx genericapirequest.Context, p storage.SelectionPredicate, resourceVersion string) (watch.Interface, error) { +func (e *Store) WatchPredicate(ctx context.Context, p storage.SelectionPredicate, resourceVersion string) (watch.Interface, error) { if name, ok := p.MatchesSingle(); ok { if key, err := e.KeyFunc(ctx, name); err == nil { w, err := e.Storage.Watch(ctx, key, resourceVersion, p) @@ -1216,7 +1222,7 @@ func exportObjectMeta(accessor metav1.Object, exact bool) { } // Export implements the rest.Exporter interface -func (e *Store) Export(ctx genericapirequest.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { +func (e *Store) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) { obj, err := e.Get(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, err @@ -1306,17 +1312,17 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error { // Set the default behavior for storage key generation if e.KeyRootFunc == nil && e.KeyFunc == nil { if isNamespaced { - e.KeyRootFunc = func(ctx genericapirequest.Context) string { + e.KeyRootFunc = func(ctx context.Context) string { return NamespaceKeyRootFunc(ctx, prefix) } - e.KeyFunc = func(ctx genericapirequest.Context, name string) (string, error) { + e.KeyFunc = func(ctx context.Context, name string) (string, error) { return NamespaceKeyFunc(ctx, prefix, name) } } else { - e.KeyRootFunc = func(ctx genericapirequest.Context) string { + e.KeyRootFunc = func(ctx context.Context) string { return prefix } - e.KeyFunc = func(ctx genericapirequest.Context, name string) (string, error) { + e.KeyFunc = func(ctx context.Context, name string) (string, error) { return NoNamespaceKeyFunc(ctx, prefix, name) } } @@ -1402,7 +1408,7 @@ func (e *Store) startObservingCount(period time.Duration) func() { return func() { close(stopCh) } } -func (e *Store) ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { +func (e *Store) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { if e.TableConvertor != nil { return e.TableConvertor.ConvertToTable(ctx, object, tableOptions) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go index 1e0a96b55..328ddca12 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go @@ -17,6 +17,7 @@ limitations under the License. package registry import ( + "context" "fmt" "path" "reflect" @@ -72,7 +73,7 @@ type testGracefulStrategy struct { testRESTStrategy } -func (t testGracefulStrategy) CheckGracefulDelete(ctx genericapirequest.Context, obj runtime.Object, options *metav1.DeleteOptions) bool { +func (t testGracefulStrategy) CheckGracefulDelete(ctx context.Context, obj runtime.Object, options *metav1.DeleteOptions) bool { return true } @@ -82,7 +83,7 @@ type testOrphanDeleteStrategy struct { *testRESTStrategy } -func (t *testOrphanDeleteStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (t *testOrphanDeleteStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { return rest.OrphanDependents } @@ -98,7 +99,7 @@ func (t *testRESTStrategy) NamespaceScoped() bool { return t.namespaceS func (t *testRESTStrategy) AllowCreateOnUpdate() bool { return t.allowCreateOnUpdate } func (t *testRESTStrategy) AllowUnconditionalUpdate() bool { return t.allowUnconditionalUpdate } -func (t *testRESTStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (t *testRESTStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { metaObj, err := meta.Accessor(obj) if err != nil { panic(err.Error()) @@ -111,11 +112,11 @@ func (t *testRESTStrategy) PrepareForCreate(ctx genericapirequest.Context, obj r metaObj.SetLabels(labels) } -func (t *testRESTStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {} -func (t *testRESTStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (t *testRESTStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {} +func (t *testRESTStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return nil } -func (t *testRESTStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (t *testRESTStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return nil } func (t *testRESTStrategy) Canonicalize(obj runtime.Object) {} @@ -172,7 +173,7 @@ func TestStoreList(t *testing.T) { in *example.PodList m storage.SelectionPredicate out runtime.Object - context genericapirequest.Context + context context.Context }{ "notFound": { in: nil, @@ -310,6 +311,11 @@ func TestStoreCreate(t *testing.T) { // re-define delete strategy to have graceful delete capability defaultDeleteStrategy := testRESTStrategy{scheme, names.SimpleNameGenerator, true, false, true} registry.DeleteStrategy = testGracefulStrategy{defaultDeleteStrategy} + registry.Decorator = func(obj runtime.Object) error { + pod := obj.(*example.Pod) + pod.Status.Phase = example.PodPhase("Testing") + return nil + } // create the object with denying admission objA, err := registry.Create(testContext, podA, denyCreateValidation, false) @@ -323,6 +329,11 @@ func TestStoreCreate(t *testing.T) { t.Errorf("Unexpected error: %v", err) } + // verify the decorator was called + if objA.(*example.Pod).Status.Phase != example.PodPhase("Testing") { + t.Errorf("Decorator was not called: %#v", objA) + } + // get the object checkobj, err := registry.Get(testContext, podA.Name, &metav1.GetOptions{}) if err != nil { @@ -579,7 +590,7 @@ func TestStoreCreateInitializedFailed(t *testing.T) { } } -func updateAndVerify(t *testing.T, ctx genericapirequest.Context, registry *Store, pod *example.Pod) bool { +func updateAndVerify(t *testing.T, ctx context.Context, registry *Store, pod *example.Pod) bool { obj, _, err := registry.Update(ctx, pod.Name, rest.DefaultUpdatedObjectInfo(pod), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -733,7 +744,7 @@ func TestNoOpUpdates(t *testing.T) { type testPodExport struct{} -func (t testPodExport) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error { +func (t testPodExport) Export(ctx context.Context, obj runtime.Object, exact bool) error { pod := obj.(*example.Pod) if pod.Labels == nil { pod.Labels = map[string]string{} @@ -1774,7 +1785,7 @@ func TestStoreWatch(t *testing.T) { table := map[string]struct { selectPred storage.SelectionPredicate - context genericapirequest.Context + context context.Context }{ "single": { selectPred: matchPodName("foo"), @@ -1865,10 +1876,10 @@ func newTestGenericStoreRegistry(t *testing.T, scheme *runtime.Scheme, hasCacheE CreateStrategy: strategy, UpdateStrategy: strategy, DeleteStrategy: strategy, - KeyRootFunc: func(ctx genericapirequest.Context) string { + KeyRootFunc: func(ctx context.Context) string { return podPrefix }, - KeyFunc: func(ctx genericapirequest.Context, id string) (string, error) { + KeyFunc: func(ctx context.Context, id string) (string, error) { if _, ok := genericapirequest.NamespaceFrom(ctx); !ok { return "", fmt.Errorf("namespace is required") } @@ -2011,7 +2022,7 @@ type fakeStrategy struct { names.NameGenerator } -func (fakeStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy { +func (fakeStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { appsv1beta1 := schema.GroupVersion{Group: "apps", Version: "v1beta1"} appsv1beta2 := schema.GroupVersion{Group: "apps", Version: "v1beta2"} extensionsv1beta1 := schema.GroupVersion{Group: "extensions", Version: "v1beta1"} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/testing/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/testing/BUILD index 088c78d67..68f55a691 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/testing/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/testing/BUILD @@ -12,7 +12,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest/resttest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/etcd:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/testing/tester.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/testing/tester.go index 25f096149..e1ac7c135 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/testing/tester.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/generic/testing/tester.go @@ -17,6 +17,7 @@ limitations under the License. package tester import ( + "context" "fmt" "testing" @@ -26,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest/resttest" etcdstorage "k8s.io/apiserver/pkg/storage/etcd" @@ -142,7 +142,7 @@ func (t *Tester) TestWatch(valid runtime.Object, labelsPass, labelsFail []labels // Helper functions -func (t *Tester) getObject(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { +func (t *Tester) getObject(ctx context.Context, obj runtime.Object) (runtime.Object, error) { accessor, err := meta.Accessor(obj) if err != nil { return nil, err @@ -155,7 +155,7 @@ func (t *Tester) getObject(ctx genericapirequest.Context, obj runtime.Object) (r return result, nil } -func (t *Tester) createObject(ctx genericapirequest.Context, obj runtime.Object) error { +func (t *Tester) createObject(ctx context.Context, obj runtime.Object) error { accessor, err := meta.Accessor(obj) if err != nil { return err diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/BUILD index e638251d1..14459c4a1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/BUILD @@ -13,7 +13,6 @@ go_test( deps = [ "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/example:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go index 1f998332e..59d9d200d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go @@ -17,6 +17,8 @@ limitations under the License. package rest import ( + "context" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" genericvalidation "k8s.io/apimachinery/pkg/api/validation" @@ -26,7 +28,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apiserver/pkg/admission" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/storage/names" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -52,12 +53,12 @@ type RESTCreateStrategy interface { // status. Clear the status because status changes are internal. External // callers of an api (users) should not be setting an initial status on // newly created objects. - PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) + PrepareForCreate(ctx context.Context, obj runtime.Object) // Validate returns an ErrorList with validation errors or nil. Validate // is invoked after default fields in the object have been filled in // before the object is persisted. This method should not mutate the // object. - Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList + Validate(ctx context.Context, obj runtime.Object) field.ErrorList // Canonicalize allows an object to be mutated into a canonical form. This // ensures that code that operates on these objects can rely on the common // form for things like comparison. Canonicalize is invoked after @@ -70,7 +71,7 @@ type RESTCreateStrategy interface { // BeforeCreate ensures that common operations for all resources are performed on creation. It only returns // errors that can be converted to api.Status. It invokes PrepareForCreate, then GenerateName, then Validate. // It returns nil if the object should be created. -func BeforeCreate(strategy RESTCreateStrategy, ctx genericapirequest.Context, obj runtime.Object) error { +func BeforeCreate(strategy RESTCreateStrategy, ctx context.Context, obj runtime.Object) error { objectMeta, kind, kerr := objectMetaAndKind(strategy, obj) if kerr != nil { return kerr @@ -80,13 +81,13 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx genericapirequest.Context, ob if !ValidNamespace(ctx, objectMeta) { return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request") } - } else { + } else if len(objectMeta.GetNamespace()) > 0 { objectMeta.SetNamespace(metav1.NamespaceNone) } objectMeta.SetDeletionTimestamp(nil) objectMeta.SetDeletionGracePeriodSeconds(nil) strategy.PrepareForCreate(ctx, obj) - FillObjectMetaSystemFields(ctx, objectMeta) + FillObjectMetaSystemFields(objectMeta) if len(objectMeta.GetGenerateName()) > 0 && len(objectMeta.GetName()) == 0 { objectMeta.SetName(strategy.GenerateName(objectMeta.GetGenerateName())) } @@ -97,7 +98,9 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx genericapirequest.Context, ob } // ClusterName is ignored and should not be saved - objectMeta.SetClusterName("") + if len(objectMeta.GetClusterName()) > 0 { + objectMeta.SetClusterName("") + } if errs := strategy.Validate(ctx, obj); len(errs) > 0 { return errors.NewInvalid(kind.GroupKind(), objectMeta.GetName(), errs) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go index 11a1474c8..7c39f6be1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go @@ -17,6 +17,7 @@ limitations under the License. package rest import ( + "context" "fmt" "time" @@ -25,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) // RESTDeleteStrategy defines deletion behavior on an object that follows Kubernetes @@ -48,7 +48,7 @@ const ( // orphan dependents by default. type GarbageCollectionDeleteStrategy interface { // DefaultGarbageCollectionPolicy returns the default garbage collection behavior. - DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) GarbageCollectionPolicy + DefaultGarbageCollectionPolicy(ctx context.Context) GarbageCollectionPolicy } // RESTGracefulDeleteStrategy must be implemented by the registry that supports @@ -56,7 +56,7 @@ type GarbageCollectionDeleteStrategy interface { type RESTGracefulDeleteStrategy interface { // CheckGracefulDelete should return true if the object can be gracefully deleted and set // any default values on the DeleteOptions. - CheckGracefulDelete(ctx genericapirequest.Context, obj runtime.Object, options *metav1.DeleteOptions) bool + CheckGracefulDelete(ctx context.Context, obj runtime.Object, options *metav1.DeleteOptions) bool } // BeforeDelete tests whether the object can be gracefully deleted. @@ -68,13 +68,13 @@ type RESTGracefulDeleteStrategy interface { // where we set deletionTimestamp is pkg/registry/generic/registry/store.go. // This function is responsible for setting deletionTimestamp during gracefulDeletion, // other one for cascading deletions. -func BeforeDelete(strategy RESTDeleteStrategy, ctx genericapirequest.Context, obj runtime.Object, options *metav1.DeleteOptions) (graceful, gracefulPending bool, err error) { +func BeforeDelete(strategy RESTDeleteStrategy, ctx context.Context, obj runtime.Object, options *metav1.DeleteOptions) (graceful, gracefulPending bool, err error) { objectMeta, gvk, kerr := objectMetaAndKind(strategy, obj) if kerr != nil { return false, false, kerr } if errs := validation.ValidateDeleteOptions(options); len(errs) > 0 { - return false, false, errors.NewInvalid(schema.GroupKind{}, "", errs) + return false, false, errors.NewInvalid(schema.GroupKind{Group: metav1.GroupName, Kind: "DeleteOptions"}, "", errs) } // Checking the Preconditions here to fail early. They'll be enforced later on when we actually do the deletion, too. if options.Preconditions != nil && options.Preconditions.UID != nil && *options.Preconditions.UID != objectMeta.GetUID() { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/export.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/export.go index b0fc292e2..b3fd8af30 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/export.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/export.go @@ -17,8 +17,9 @@ limitations under the License. package rest import ( + "context" + "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) // RESTExportStrategy is the interface that defines how to export a Kubernetes @@ -29,5 +30,5 @@ import ( type RESTExportStrategy interface { // Export strips fields that can not be set by the user. If 'exact' is false // fields specific to the cluster are also stripped - Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error + Export(ctx context.Context, obj runtime.Object, exact bool) error } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/meta.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/meta.go index 7257833ba..add6044ab 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/meta.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/meta.go @@ -17,30 +17,24 @@ limitations under the License. package rest import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) // FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta. -func FillObjectMetaSystemFields(ctx genericapirequest.Context, meta metav1.Object) { +func FillObjectMetaSystemFields(meta metav1.Object) { meta.SetCreationTimestamp(metav1.Now()) - // allows admission controllers to assign a UID earlier in the request processing - // to support tracking resources pending creation. - uid, found := genericapirequest.UIDFrom(ctx) - if !found { - uid = uuid.NewUUID() - } - meta.SetUID(uid) + meta.SetUID(uuid.NewUUID()) meta.SetSelfLink("") } // ValidNamespace returns false if the namespace on the context differs from // the resource. If the resource has no namespace, it is set to the value in // the context. -// -// TODO(sttts): move into pkg/genericapiserver/endpoints -func ValidNamespace(ctx genericapirequest.Context, resource metav1.Object) bool { +func ValidNamespace(ctx context.Context, resource metav1.Object) bool { ns, ok := genericapirequest.NamespaceFrom(ctx) if len(resource.GetNamespace()) == 0 { resource.SetNamespace(ns) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/meta_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/meta_test.go index a6710423b..cec33b67a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/meta_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/meta_test.go @@ -21,34 +21,26 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apiserver/pkg/apis/example" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) // TestFillObjectMetaSystemFields validates that system populated fields are set on an object func TestFillObjectMetaSystemFields(t *testing.T) { - ctx := genericapirequest.NewDefaultContext() resource := metav1.ObjectMeta{} - FillObjectMetaSystemFields(ctx, &resource) + FillObjectMetaSystemFields(&resource) if resource.CreationTimestamp.Time.IsZero() { t.Errorf("resource.CreationTimestamp is zero") } else if len(resource.UID) == 0 { t.Errorf("resource.UID missing") } - // verify we can inject a UID - uid := uuid.NewUUID() - ctx = genericapirequest.WithUID(ctx, uid) - resource = metav1.ObjectMeta{} - FillObjectMetaSystemFields(ctx, &resource) - if resource.UID != uid { - t.Errorf("resource.UID expected: %v, actual: %v", uid, resource.UID) + if len(resource.UID) == 0 { + t.Errorf("resource.UID missing") } } // TestHasObjectMetaSystemFieldValues validates that true is returned if and only if all fields are populated func TestHasObjectMetaSystemFieldValues(t *testing.T) { - ctx := genericapirequest.NewDefaultContext() resource := metav1.ObjectMeta{} objMeta, err := meta.Accessor(&resource) if err != nil { @@ -57,7 +49,7 @@ func TestHasObjectMetaSystemFieldValues(t *testing.T) { if metav1.HasObjectMetaSystemFieldValues(objMeta) { t.Errorf("the resource does not have all fields yet populated, but incorrectly reports it does") } - FillObjectMetaSystemFields(ctx, &resource) + FillObjectMetaSystemFields(&resource) if !metav1.HasObjectMetaSystemFieldValues(objMeta) { t.Errorf("the resource does have all fields populated, but incorrectly reports it does not") } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go index a2b0930f3..d84146fec 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/rest.go @@ -17,6 +17,7 @@ limitations under the License. package rest import ( + "context" "io" "net/http" "net/url" @@ -27,7 +28,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) //TODO: @@ -58,6 +58,13 @@ type Storage interface { New() runtime.Object } +// Scoper indicates what scope the resource is at. It must be specified. +// It is usually provided automatically based on your strategy. +type Scoper interface { + // NamespaceScoped returns true if the storage is namespaced + NamespaceScoped() bool +} + // KindProvider specifies a different kind for its API than for its internal storage. This is necessary for external // objects that are not compiled into the api server. For such objects, there is no in-memory representation for // the object, so they must be represented as generic objects (e.g. runtime.Unknown), but when we present the object as part of @@ -91,7 +98,7 @@ type Lister interface { // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) NewList() runtime.Object // List selects resources in the storage which match to the selector. 'options' can be nil. - List(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (runtime.Object, error) + List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) } // Exporter is an object that knows how to strip a RESTful resource for export. A store should implement this interface @@ -101,7 +108,7 @@ type Exporter interface { // Export an object. Fields that are not user specified (e.g. Status, ObjectMeta.ResourceVersion) are stripped out // Returns the stripped object. If 'exact' is true, fields that are specific to the cluster (e.g. namespace) are // retained, otherwise they are stripped also. - Export(ctx genericapirequest.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) + Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) } // Getter is an object that can retrieve a named RESTful resource. @@ -109,7 +116,7 @@ type Getter interface { // Get finds a resource in the storage by name and returns it. // Although it can return an arbitrary error value, IsNotFound(err) is true for the // returned error value err when the specified resource is not found. - Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) + Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) } // GetterWithOptions is an object that retrieve a named RESTful resource and takes @@ -122,7 +129,7 @@ type GetterWithOptions interface { // The options object passed to it is of the same type returned by the NewGetOptions // method. // TODO: Pass metav1.GetOptions. - Get(ctx genericapirequest.Context, name string, options runtime.Object) (runtime.Object, error) + Get(ctx context.Context, name string, options runtime.Object) (runtime.Object, error) // NewGetOptions returns an empty options object that will be used to pass // options to the Get method. It may return a bool and a string, if true, the @@ -134,7 +141,7 @@ type GetterWithOptions interface { } type TableConvertor interface { - ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) + ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) } // GracefulDeleter knows how to pass deletion options to allow delayed deletion of a @@ -149,7 +156,7 @@ type GracefulDeleter interface { // information about deletion. // It also returns a boolean which is set to true if the resource was instantly // deleted or false if it will be deleted asynchronously. - Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) + Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) } // CollectionDeleter is an object that can delete a collection @@ -160,7 +167,7 @@ type CollectionDeleter interface { // them or return an invalid request error. // DeleteCollection may not be atomic - i.e. it may delete some objects and still // return an error after it. On success, returns a list of deleted objects. - DeleteCollection(ctx genericapirequest.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) + DeleteCollection(ctx context.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) } // Creater is an object that can create an instance of a RESTful object. @@ -171,7 +178,7 @@ type Creater interface { // Create creates a new version of a resource. If includeUninitialized is set, the object may be returned // without completing initialization. - Create(ctx genericapirequest.Context, obj runtime.Object, createValidation ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) + Create(ctx context.Context, obj runtime.Object, createValidation ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) } // NamedCreater is an object that can create an instance of a RESTful object using a name parameter. @@ -184,7 +191,7 @@ type NamedCreater interface { // This is needed for create operations on subresources which include the name of the parent // resource in the path. If includeUninitialized is set, the object may be returned without // completing initialization. - Create(ctx genericapirequest.Context, name string, obj runtime.Object, createValidation ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) + Create(ctx context.Context, name string, obj runtime.Object, createValidation ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) } // UpdatedObjectInfo provides information about an updated object to an Updater. @@ -197,7 +204,7 @@ type UpdatedObjectInfo interface { // UpdatedObject returns the updated object, given a context and old object. // The only time an empty oldObj should be passed in is if a "create on update" is occurring (there is no oldObj). - UpdatedObject(ctx genericapirequest.Context, oldObj runtime.Object) (newObj runtime.Object, err error) + UpdatedObject(ctx context.Context, oldObj runtime.Object) (newObj runtime.Object, err error) } // ValidateObjectFunc is a function to act on a given object. An error may be returned @@ -229,14 +236,14 @@ type Updater interface { // Update finds a resource in the storage and updates it. Some implementations // may allow updates creates the object - they should set the created boolean // to true. - Update(ctx genericapirequest.Context, name string, objInfo UpdatedObjectInfo, createValidation ValidateObjectFunc, updateValidation ValidateObjectUpdateFunc) (runtime.Object, bool, error) + Update(ctx context.Context, name string, objInfo UpdatedObjectInfo, createValidation ValidateObjectFunc, updateValidation ValidateObjectUpdateFunc) (runtime.Object, bool, error) } // CreaterUpdater is a storage object that must support both create and update. // Go prevents embedded interfaces that implement the same method. type CreaterUpdater interface { Creater - Update(ctx genericapirequest.Context, name string, objInfo UpdatedObjectInfo, createValidation ValidateObjectFunc, updateValidation ValidateObjectUpdateFunc) (runtime.Object, bool, error) + Update(ctx context.Context, name string, objInfo UpdatedObjectInfo, createValidation ValidateObjectFunc, updateValidation ValidateObjectUpdateFunc) (runtime.Object, bool, error) } // CreaterUpdater must satisfy the Updater interface. @@ -255,7 +262,7 @@ type Watcher interface { // are supported; an error should be returned if 'field' tries to select on a field that // isn't supported. 'resourceVersion' allows for continuing/starting a watch at a // particular version. - Watch(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) } // StandardStorage is an interface covering the common verbs. Provided for testing whether a @@ -272,7 +279,7 @@ type StandardStorage interface { // Redirector know how to return a remote resource's location. type Redirector interface { // ResourceLocation should return the remote location of the given resource, and an optional transport to use to request it, or an error. - ResourceLocation(ctx genericapirequest.Context, id string) (remoteLocation *url.URL, transport http.RoundTripper, err error) + ResourceLocation(ctx context.Context, id string) (remoteLocation *url.URL, transport http.RoundTripper, err error) } // Responder abstracts the normal response behavior for a REST method and is passed to callers that @@ -292,7 +299,7 @@ type Connecter interface { // code and body, so the ServeHTTP method should exit after invoking the responder. The Handler will // be used for a single API request and then discarded. The Responder is guaranteed to write to the // same http.ResponseWriter passed to ServeHTTP. - Connect(ctx genericapirequest.Context, id string, options runtime.Object, r Responder) (http.Handler, error) + Connect(ctx context.Context, id string, options runtime.Object, r Responder) (http.Handler, error) // NewConnectOptions returns an empty options object that will be used to pass // options to the Connect method. If nil, then a nil options object is passed to diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/resttest/resttest.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/resttest/resttest.go index f7244e2b7..647b9401b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/resttest/resttest.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/resttest/resttest.go @@ -17,6 +17,7 @@ limitations under the License. package resttest import ( + "context" "fmt" "reflect" "strings" @@ -99,7 +100,7 @@ func (t *Tester) TestNamespace() string { // TestContext returns a namespaced context that will be used when making storage calls. // Namespace is determined by TestNamespace() -func (t *Tester) TestContext() genericapirequest.Context { +func (t *Tester) TestContext() context.Context { if t.clusterScope { return genericapirequest.NewContext() } @@ -128,11 +129,11 @@ func (t *Tester) setObjectMeta(obj runtime.Object, name string) { type AssignFunc func([]runtime.Object) []runtime.Object type EmitFunc func(runtime.Object, string) error -type GetFunc func(genericapirequest.Context, runtime.Object) (runtime.Object, error) +type GetFunc func(context.Context, runtime.Object) (runtime.Object, error) type InitWatchFunc func() type InjectErrFunc func(err error) type IsErrorFunc func(err error) bool -type CreateFunc func(genericapirequest.Context, runtime.Object) error +type CreateFunc func(context.Context, runtime.Object) error type SetRVFunc func(uint64) type UpdateFunc func(runtime.Object) runtime.Object @@ -219,7 +220,7 @@ func (t *Tester) TestWatch( // ============================================================================= // Creation tests. -func (t *Tester) delete(ctx genericapirequest.Context, obj runtime.Object) error { +func (t *Tester) delete(ctx context.Context, obj runtime.Object) error { objectMeta, err := meta.Accessor(obj) if err != nil { return err @@ -576,7 +577,7 @@ func (t *Tester) testUpdateRetrievesOldObject(obj runtime.Object, createFn Creat // Make sure a custom transform is called, and sees the expected updatedObject and oldObject // This tests the mechanism used to pass the old and new object to admission calledUpdatedObject := 0 - noopTransform := func(_ genericapirequest.Context, updatedObject runtime.Object, oldObject runtime.Object) (runtime.Object, error) { + noopTransform := func(_ context.Context, updatedObject runtime.Object, oldObject runtime.Object) (runtime.Object, error) { if !reflect.DeepEqual(storedFoo, oldObject) { t.Errorf("Expected\n\t%#v\ngot\n\t%#v", storedFoo, oldObject) } @@ -618,7 +619,7 @@ func (t *Tester) testUpdatePropagatesUpdatedObjectError(obj runtime.Object, crea // Make sure our transform is called, and sees the expected updatedObject and oldObject propagateErr := fmt.Errorf("custom updated object error for %v", foo) - noopTransform := func(_ genericapirequest.Context, updatedObject runtime.Object, oldObject runtime.Object) (runtime.Object, error) { + noopTransform := func(_ context.Context, updatedObject runtime.Object, oldObject runtime.Object) (runtime.Object, error) { return nil, propagateErr } @@ -1319,7 +1320,7 @@ func (t *Tester) testListTableConversion(obj runtime.Object, assignFn AssignFunc t.Errorf("column %d has no name", j) } switch column.Type { - case "string", "date", "integer": + case "string", "date", "integer", "number", "boolean": default: t.Errorf("column %d has unexpected type: %q", j, column.Type) } @@ -1341,13 +1342,14 @@ func (t *Tester) testListTableConversion(obj runtime.Object, assignFn AssignFunc } for i, row := range table.Rows { if len(row.Cells) != len(table.ColumnDefinitions) { - t.Errorf("row %d did not have the correct number of cells: %d in %v", i, len(table.ColumnDefinitions), row.Cells) + t.Errorf("row %d did not have the correct number of cells: %d in %v, expected %d", i, len(row.Cells), row.Cells, len(table.ColumnDefinitions)) } for j, cell := range row.Cells { // do not add to this test without discussion - may break clients switch cell.(type) { case float64, int64, int32, int, string, bool: case []interface{}: + case nil: default: t.Errorf("row %d, cell %d has an unrecognized type, only JSON serialization safe types are allowed: %T ", i, j, cell) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/table.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/table.go index 2f0d1df3b..bfcdcf58b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/table.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/table.go @@ -17,6 +17,7 @@ limitations under the License. package rest import ( + "context" "fmt" "net/http" "time" @@ -26,7 +27,6 @@ import ( metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) type defaultTableConvertor struct { @@ -40,7 +40,7 @@ func NewDefaultTableConvertor(resource schema.GroupResource) TableConvertor { var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() -func (c defaultTableConvertor) ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { +func (c defaultTableConvertor) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { var table metav1beta1.Table fn := func(obj runtime.Object) error { m, err := meta.Accessor(obj) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go index aaee5800c..d3e669e93 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go @@ -17,6 +17,7 @@ limitations under the License. package rest import ( + "context" "fmt" "k8s.io/apimachinery/pkg/api/errors" @@ -27,7 +28,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apiserver/pkg/admission" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/features" utilfeature "k8s.io/apiserver/pkg/util/feature" ) @@ -46,11 +46,11 @@ type RESTUpdateStrategy interface { // the object. For example: remove fields that are not to be persisted, // sort order-insensitive list fields, etc. This should not remove fields // whose presence would be considered a validation error. - PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) + PrepareForUpdate(ctx context.Context, obj, old runtime.Object) // ValidateUpdate is invoked after default fields in the object have been // filled in before the object is persisted. This method should not mutate // the object. - ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList + ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList // Canonicalize allows an object to be mutated into a canonical form. This // ensures that code that operates on these objects can rely on the common // form for things like comparison. Canonicalize is invoked after @@ -83,7 +83,8 @@ func validateCommonFields(obj, old runtime.Object, strategy RESTUpdateStrategy) // BeforeUpdate ensures that common operations for all resources are performed on update. It only returns // errors that can be converted to api.Status. It will invoke update validation with the provided existing // and updated objects. -func BeforeUpdate(strategy RESTUpdateStrategy, ctx genericapirequest.Context, obj, old runtime.Object) error { +// It sets zero values only if the object does not have a zero value for the respective field. +func BeforeUpdate(strategy RESTUpdateStrategy, ctx context.Context, obj, old runtime.Object) error { objectMeta, kind, kerr := objectMetaAndKind(strategy, obj) if kerr != nil { return kerr @@ -92,9 +93,10 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx genericapirequest.Context, ob if !ValidNamespace(ctx, objectMeta) { return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request") } - } else { + } else if len(objectMeta.GetNamespace()) > 0 { objectMeta.SetNamespace(metav1.NamespaceNone) } + // Ensure requests cannot update generation oldMeta, err := meta.Accessor(old) if err != nil { @@ -111,7 +113,25 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx genericapirequest.Context, ob strategy.PrepareForUpdate(ctx, obj, old) // ClusterName is ignored and should not be saved - objectMeta.SetClusterName("") + if len(objectMeta.GetClusterName()) > 0 { + objectMeta.SetClusterName("") + } + // Use the existing UID if none is provided + if len(objectMeta.GetUID()) == 0 { + objectMeta.SetUID(oldMeta.GetUID()) + } + // ignore changes to timestamp + if oldCreationTime := oldMeta.GetCreationTimestamp(); !oldCreationTime.IsZero() { + objectMeta.SetCreationTimestamp(oldMeta.GetCreationTimestamp()) + } + // an update can never remove/change a deletion timestamp + if !oldMeta.GetDeletionTimestamp().IsZero() { + objectMeta.SetDeletionTimestamp(oldMeta.GetDeletionTimestamp()) + } + // an update can never remove/change grace period seconds + if oldMeta.GetDeletionGracePeriodSeconds() != nil && objectMeta.GetDeletionGracePeriodSeconds() == nil { + objectMeta.SetDeletionGracePeriodSeconds(oldMeta.GetDeletionGracePeriodSeconds()) + } // Ensure some common fields, like UID, are validated for all resources. errs, err := validateCommonFields(obj, old, strategy) @@ -130,7 +150,7 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx genericapirequest.Context, ob } // TransformFunc is a function to transform and return newObj -type TransformFunc func(ctx genericapirequest.Context, newObj runtime.Object, oldObj runtime.Object) (transformedNewObj runtime.Object, err error) +type TransformFunc func(ctx context.Context, newObj runtime.Object, oldObj runtime.Object) (transformedNewObj runtime.Object, err error) // defaultUpdatedObjectInfo implements UpdatedObjectInfo type defaultUpdatedObjectInfo struct { @@ -167,7 +187,7 @@ func (i *defaultUpdatedObjectInfo) Preconditions() *metav1.Preconditions { // UpdatedObject satisfies the UpdatedObjectInfo interface. // It returns a copy of the held obj, passed through any configured transformers. -func (i *defaultUpdatedObjectInfo) UpdatedObject(ctx genericapirequest.Context, oldObj runtime.Object) (runtime.Object, error) { +func (i *defaultUpdatedObjectInfo) UpdatedObject(ctx context.Context, oldObj runtime.Object) (runtime.Object, error) { var err error // Start with the configured object newObj := i.obj @@ -214,7 +234,7 @@ func (i *wrappedUpdatedObjectInfo) Preconditions() *metav1.Preconditions { // UpdatedObject satisfies the UpdatedObjectInfo interface. // It delegates to the wrapped objInfo and passes the result through any configured transformers. -func (i *wrappedUpdatedObjectInfo) UpdatedObject(ctx genericapirequest.Context, oldObj runtime.Object) (runtime.Object, error) { +func (i *wrappedUpdatedObjectInfo) UpdatedObject(ctx context.Context, oldObj runtime.Object) (runtime.Object, error) { newObj, err := i.objInfo.UpdatedObject(ctx, oldObj) if err != nil { return newObj, err diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/zz_generated.deepcopy.go index f7250379c..1ddd11973 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/registry/rest/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/BUILD index c1073fc1d..1dfabf8fa 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/BUILD @@ -15,9 +15,8 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", @@ -26,17 +25,17 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/example:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/example/v1:go_default_library", - "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/discovery:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/filters:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/common:go_default_library", ], ) @@ -99,8 +98,7 @@ go_library( "//vendor/github.com/pborman/uuid:go_default_library", "//vendor/golang.org/x/net/http2:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/config.go index 2f4c48b45..41ae90af6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/config.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/config.go @@ -65,6 +65,7 @@ import ( openapicommon "k8s.io/kube-openapi/pkg/common" // install apis + "github.com/golang/glog" _ "k8s.io/apiserver/pkg/apis/apiserver/install" ) @@ -138,9 +139,6 @@ type Config struct { // LegacyAPIGroupPrefixes is used to set up URL parsing for authorization and for validating requests // to InstallLegacyAPIGroup. New API servers don't generally have legacy groups at all. LegacyAPIGroupPrefixes sets.String - // RequestContextMapper maps requests to contexts. Exported so downstream consumers can provider their own mappers - // TODO confirm that anyone downstream actually uses this and doesn't just need an accessor - RequestContextMapper apirequest.RequestContextMapper // RequestInfoResolver is used to assign attributes (used by admission and authorization) based on a request URL. // Use-cases that are like kubelets may need to customize this. RequestInfoResolver apirequest.RequestInfoResolver @@ -253,7 +251,6 @@ func NewConfig(codecs serializer.CodecFactory) *Config { return &Config{ Serializer: codecs, ReadWritePort: 443, - RequestContextMapper: apirequest.NewRequestContextMapper(), BuildHandlerChainFunc: DefaultBuildHandlerChain, HandlerChainWaitGroup: new(utilwaitgroup.SafeWaitGroup), LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix), @@ -262,6 +259,7 @@ func NewConfig(codecs serializer.CodecFactory) *Config { EnableIndex: true, EnableDiscovery: true, EnableProfiling: true, + EnableMetrics: true, MaxRequestsInFlight: 400, MaxMutatingRequestsInFlight: 200, RequestTimeout: time.Duration(60) * time.Second, @@ -281,8 +279,7 @@ func NewRecommendedConfig(codecs serializer.CodecFactory) *RecommendedConfig { } } -func DefaultOpenAPIConfig(getDefinitions openapicommon.GetOpenAPIDefinitions, scheme *runtime.Scheme) *openapicommon.Config { - defNamer := apiopenapi.NewDefinitionNamer(scheme) +func DefaultOpenAPIConfig(getDefinitions openapicommon.GetOpenAPIDefinitions, defNamer *apiopenapi.DefinitionNamer) *openapicommon.Config { return &openapicommon.Config{ ProtocolList: []string{"https"}, IgnorePrefixes: []string{"/swaggerapi"}, @@ -446,9 +443,8 @@ func (c *RecommendedConfig) Complete() CompletedConfig { // New creates a new server which logically combines the handling chain with the passed server. // name is used to differentiate for logging. The handler chain in particular can be difficult as it starts delgating. +// delegationTarget may not be nil. func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*GenericAPIServer, error) { - // The delegationTarget and the config must agree on the RequestContextMapper - if c.Serializer == nil { return nil, fmt.Errorf("Genericapiserver.New() called with config.Serializer == nil") } @@ -459,14 +455,13 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G handlerChainBuilder := func(handler http.Handler) http.Handler { return c.BuildHandlerChainFunc(handler, c.Config) } - apiServerHandler := NewAPIServerHandler(name, c.RequestContextMapper, c.Serializer, handlerChainBuilder, delegationTarget.UnprotectedHandler()) + apiServerHandler := NewAPIServerHandler(name, c.Serializer, handlerChainBuilder, delegationTarget.UnprotectedHandler()) s := &GenericAPIServer{ discoveryAddresses: c.DiscoveryAddresses, LoopbackClientConfig: c.LoopbackClientConfig, legacyAPIGroupPrefixes: c.LegacyAPIGroupPrefixes, admissionControl: c.AdmissionControl, - requestContextMapper: c.RequestContextMapper, Serializer: c.Serializer, AuditBackend: c.AuditBackend, delegationTarget: delegationTarget, @@ -491,7 +486,7 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G healthzChecks: c.HealthzChecks, - DiscoveryGroupManager: discovery.NewRootAPIsHandler(c.DiscoveryAddresses, c.Serializer, c.RequestContextMapper), + DiscoveryGroupManager: discovery.NewRootAPIsHandler(c.DiscoveryAddresses, c.Serializer), enableAPIResponseCompression: c.EnableAPIResponseCompression, } @@ -547,24 +542,23 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G } func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler { - handler := genericapifilters.WithAuthorization(apiHandler, c.RequestContextMapper, c.Authorization.Authorizer, c.Serializer) - handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.RequestContextMapper, c.LongRunningFunc) - handler = genericapifilters.WithImpersonation(handler, c.RequestContextMapper, c.Authorization.Authorizer, c.Serializer) + handler := genericapifilters.WithAuthorization(apiHandler, c.Authorization.Authorizer, c.Serializer) + handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.LongRunningFunc) + handler = genericapifilters.WithImpersonation(handler, c.Authorization.Authorizer, c.Serializer) if utilfeature.DefaultFeatureGate.Enabled(features.AdvancedAuditing) { - handler = genericapifilters.WithAudit(handler, c.RequestContextMapper, c.AuditBackend, c.AuditPolicyChecker, c.LongRunningFunc) + handler = genericapifilters.WithAudit(handler, c.AuditBackend, c.AuditPolicyChecker, c.LongRunningFunc) } else { - handler = genericapifilters.WithLegacyAudit(handler, c.RequestContextMapper, c.LegacyAuditWriter) + handler = genericapifilters.WithLegacyAudit(handler, c.LegacyAuditWriter) } - failedHandler := genericapifilters.Unauthorized(c.RequestContextMapper, c.Serializer, c.Authentication.SupportsBasicAuth) + failedHandler := genericapifilters.Unauthorized(c.Serializer, c.Authentication.SupportsBasicAuth) if utilfeature.DefaultFeatureGate.Enabled(features.AdvancedAuditing) { - failedHandler = genericapifilters.WithFailedAuthenticationAudit(failedHandler, c.RequestContextMapper, c.AuditBackend, c.AuditPolicyChecker) + failedHandler = genericapifilters.WithFailedAuthenticationAudit(failedHandler, c.AuditBackend, c.AuditPolicyChecker) } - handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authentication.Authenticator, failedHandler) + handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler) handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true") - handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc, c.RequestTimeout) - handler = genericfilters.WithWaitGroup(handler, c.RequestContextMapper, c.LongRunningFunc, c.HandlerChainWaitGroup) - handler = genericapifilters.WithRequestInfo(handler, c.RequestInfoResolver, c.RequestContextMapper) - handler = apirequest.WithRequestContext(handler, c.RequestContextMapper) + handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.LongRunningFunc, c.RequestTimeout) + handler = genericfilters.WithWaitGroup(handler, c.LongRunningFunc, c.HandlerChainWaitGroup) + handler = genericapifilters.WithRequestInfo(handler, c.RequestInfoResolver) handler = genericfilters.WithPanicRecovery(handler) return handler } @@ -581,6 +575,16 @@ func installAPI(s *GenericAPIServer, c *Config) { if c.EnableContentionProfiling { goruntime.SetBlockProfileRate(1) } + // so far, only logging related endpoints are considered valid to add for these debug flags. + routes.DebugFlags{}.Install(s.Handler.NonGoRestfulMux, "v", routes.StringFlagPutHandler( + routes.StringFlagSetterFunc(func(val string) (string, error) { + var level glog.Level + if err := level.Set(val); err != nil { + return "", fmt.Errorf("failed set glog.logging.verbosity %s: %v", val, err) + } + return "successfully set glog.logging.verbosity to " + val, nil + }), + )) } if c.EnableMetrics { if c.EnableProfiling { @@ -589,6 +593,7 @@ func installAPI(s *GenericAPIServer, c *Config) { routes.DefaultMetrics{}.Install(s.Handler.NonGoRestfulMux) } } + routes.Version{Version: c.Version}.Install(s.Handler.GoRestfulContainer) if c.EnableDiscovery { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/config_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/config_test.go index 381318c8d..e93a50df7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/config_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/config_test.go @@ -26,7 +26,6 @@ import ( "testing" "k8s.io/apimachinery/pkg/util/sets" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/server/healthz" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes/fake" @@ -36,7 +35,6 @@ import ( func TestNewWithDelegate(t *testing.T) { delegateConfig := NewConfig(codecs) delegateConfig.PublicAddress = net.ParseIP("192.168.10.4") - delegateConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper() delegateConfig.LegacyAPIGroupPrefixes = sets.NewString("/api") delegateConfig.LoopbackClientConfig = &rest.Config{} delegateConfig.SwaggerConfig = DefaultSwaggerConfig() @@ -50,7 +48,7 @@ func TestNewWithDelegate(t *testing.T) { })) sharedInformers := informers.NewSharedInformerFactory(clientset, delegateConfig.LoopbackClientConfig.Timeout) - delegateServer, err := delegateConfig.Complete(sharedInformers).New("test", EmptyDelegate) + delegateServer, err := delegateConfig.Complete(sharedInformers).New("test", NewEmptyDelegate()) if err != nil { t.Fatal(err) } @@ -67,7 +65,6 @@ func TestNewWithDelegate(t *testing.T) { wrappingConfig := NewConfig(codecs) wrappingConfig.PublicAddress = net.ParseIP("192.168.10.4") - wrappingConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper() wrappingConfig.LegacyAPIGroupPrefixes = sets.NewString("/api") wrappingConfig.LoopbackClientConfig = &rest.Config{} wrappingConfig.SwaggerConfig = DefaultSwaggerConfig() @@ -109,6 +106,7 @@ func TestNewWithDelegate(t *testing.T) { "/healthz/poststarthook/generic-apiserver-start-informers", "/healthz/poststarthook/wrapping-post-start-hook", "/healthz/wrapping-health", + "/metrics", "/swaggerapi" ] }`, t) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD index 6404a3953..6822469d4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD @@ -49,6 +49,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/waitgroup:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/httplog:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/compression.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/compression.go index 6bedfadea..625cd5c8d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/compression.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/compression.go @@ -46,9 +46,9 @@ const ( ) // WithCompression wraps an http.Handler with the Compression Handler -func WithCompression(handler http.Handler, ctxMapper request.RequestContextMapper) http.Handler { +func WithCompression(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - wantsCompression, encoding := wantsCompressedResponse(req, ctxMapper) + wantsCompression, encoding := wantsCompressedResponse(req) w.Header().Set("Vary", "Accept-Encoding") if wantsCompression { compressionWriter, err := NewCompressionResponseWriter(w, encoding) @@ -67,12 +67,9 @@ func WithCompression(handler http.Handler, ctxMapper request.RequestContextMappe } // wantsCompressedResponse reads the Accept-Encoding header to see if and which encoding is requested. -func wantsCompressedResponse(req *http.Request, ctxMapper request.RequestContextMapper) (bool, string) { +func wantsCompressedResponse(req *http.Request) (bool, string) { // don't compress watches - ctx, ok := ctxMapper.Get(req) - if !ok { - return false, "" - } + ctx := req.Context() info, ok := request.RequestInfoFrom(ctx) if !ok { return false, "" @@ -172,13 +169,13 @@ func (c *compressionResponseWriter) compressorClosed() bool { } // RestfulWithCompression wraps WithCompression to be compatible with go-restful -func RestfulWithCompression(function restful.RouteFunction, ctxMapper request.RequestContextMapper) restful.RouteFunction { +func RestfulWithCompression(function restful.RouteFunction) restful.RouteFunction { return restful.RouteFunction(func(request *restful.Request, response *restful.Response) { handler := WithCompression(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { response.ResponseWriter = w request.Request = req function(request, response) - }), ctxMapper) + })) handler.ServeHTTP(response.ResponseWriter, request.Request) }) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/compression_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/compression_test.go index 07d46d5bf..b179cff8e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/compression_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/compression_test.go @@ -42,17 +42,13 @@ func TestCompression(t *testing.T) { responseData := []byte("1234") - requestContextMapper := request.NewRequestContextMapper() - for _, test := range tests { handler := WithCompression( http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Write(responseData) }), - requestContextMapper, ) - handler = filters.WithRequestInfo(handler, newTestRequestInfoResolver(), requestContextMapper) - handler = request.WithRequestContext(handler, requestContextMapper) + handler = filters.WithRequestInfo(handler, newTestRequestInfoResolver()) server := httptest.NewServer(handler) defer server.Close() client := http.Client{ diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go index 84fa31c72..78700c33a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go @@ -98,7 +98,6 @@ func WithMaxInFlightLimit( handler http.Handler, nonMutatingLimit int, mutatingLimit int, - requestContextMapper apirequest.RequestContextMapper, longRunningRequestCheck apirequest.LongRunningRequestCheck, ) http.Handler { startOnce.Do(startRecordingUsage) @@ -115,11 +114,7 @@ func WithMaxInFlightLimit( } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx, ok := requestContextMapper.Get(r) - if !ok { - handleError(w, r, fmt.Errorf("no context found for request, handler chain must be wrong")) - return - } + ctx := r.Context() requestInfo, ok := apirequest.RequestInfoFrom(ctx) if !ok { handleError(w, r, fmt.Errorf("no RequestInfo found in context, handler chain must be wrong")) @@ -172,7 +167,7 @@ func WithMaxInFlightLimit( metrics.DroppedRequests.WithLabelValues(metrics.ReadOnlyKind).Inc() } // at this point we're about to return a 429, BUT not all actors should be rate limited. A system:master is so powerful - // that he should always get an answer. It's a super-admin or a loopback connection. + // that they should always get an answer. It's a super-admin or a loopback connection. if currUser, ok := apirequest.UserFrom(ctx); ok { for _, group := range currUser.GetGroups() { if group == user.SystemPrivilegedGroup { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight_test.go index fc302b22b..c3b4c53d3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight_test.go @@ -33,7 +33,6 @@ import ( func createMaxInflightServer(callsWg, blockWg *sync.WaitGroup, disableCallsWg *bool, disableCallsWgMutex *sync.Mutex, nonMutating, mutating int) *httptest.Server { longRunningRequestCheck := BasicLongRunningRequestCheck(sets.NewString("watch"), sets.NewString("proxy")) - requestContextMapper := apirequest.NewRequestContextMapper() requestInfoFactory := &apirequest.RequestInfoFactory{APIPrefixes: sets.NewString("apis", "api"), GrouplessAPIPrefixes: sets.NewString("api")} handler := WithMaxInFlightLimit( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -51,26 +50,18 @@ func createMaxInflightServer(callsWg, blockWg *sync.WaitGroup, disableCallsWg *b }), nonMutating, mutating, - requestContextMapper, longRunningRequestCheck, ) - handler = withFakeUser(handler, requestContextMapper) - handler = apifilters.WithRequestInfo(handler, requestInfoFactory, requestContextMapper) - handler = apirequest.WithRequestContext(handler, requestContextMapper) + handler = withFakeUser(handler) + handler = apifilters.WithRequestInfo(handler, requestInfoFactory) return httptest.NewServer(handler) } -func withFakeUser(handler http.Handler, requestContextMapper apirequest.RequestContextMapper) http.Handler { +func withFakeUser(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx, ok := requestContextMapper.Get(r) - if !ok { - handleError(w, r, fmt.Errorf("no context found for request, handler chain must be wrong")) - return - } - if len(r.Header["Groups"]) > 0 { - requestContextMapper.Update(r, apirequest.WithUser(ctx, &user.DefaultInfo{ + r = r.WithContext(apirequest.WithUser(r.Context(), &user.DefaultInfo{ Groups: r.Header["Groups"], })) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go index a1582627f..eaf767f4f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go @@ -18,6 +18,7 @@ package filters import ( "bufio" + "context" "encoding/json" "fmt" "net" @@ -33,35 +34,38 @@ import ( var errConnKilled = fmt.Errorf("killing connection/stream because serving request timed out and response had been started") // WithTimeoutForNonLongRunningRequests times out non-long-running requests after the time given by timeout. -func WithTimeoutForNonLongRunningRequests(handler http.Handler, requestContextMapper apirequest.RequestContextMapper, longRunning apirequest.LongRunningRequestCheck, timeout time.Duration) http.Handler { +func WithTimeoutForNonLongRunningRequests(handler http.Handler, longRunning apirequest.LongRunningRequestCheck, timeout time.Duration) http.Handler { if longRunning == nil { return handler } - timeoutFunc := func(req *http.Request) (<-chan time.Time, func(), *apierrors.StatusError) { + timeoutFunc := func(req *http.Request) (*http.Request, <-chan time.Time, func(), *apierrors.StatusError) { // TODO unify this with apiserver.MaxInFlightLimit - ctx, ok := requestContextMapper.Get(req) - if !ok { - // if this happens, the handler chain isn't setup correctly because there is no context mapper - return time.After(timeout), func() {}, apierrors.NewInternalError(fmt.Errorf("no context found for request during timeout")) - } + ctx := req.Context() requestInfo, ok := apirequest.RequestInfoFrom(ctx) if !ok { // if this happens, the handler chain isn't setup correctly because there is no request info - return time.After(timeout), func() {}, apierrors.NewInternalError(fmt.Errorf("no request info found for request during timeout")) + return req, time.After(timeout), func() {}, apierrors.NewInternalError(fmt.Errorf("no request info found for request during timeout")) } if longRunning(req, requestInfo) { - return nil, nil, nil + return req, nil, nil, nil } - metricFn := func() { + + ctx, cancel := context.WithCancel(ctx) + req = req.WithContext(ctx) + + postTimeoutFn := func() { + cancel() metrics.Record(req, requestInfo, "", http.StatusGatewayTimeout, 0, 0) } - return time.After(timeout), metricFn, apierrors.NewTimeoutError(fmt.Sprintf("request did not complete within %s", timeout), 0) + return req, time.After(timeout), postTimeoutFn, apierrors.NewTimeoutError(fmt.Sprintf("request did not complete within %s", timeout), 0) } return WithTimeout(handler, timeoutFunc) } +type timeoutFunc = func(*http.Request) (req *http.Request, timeout <-chan time.Time, postTimeoutFunc func(), err *apierrors.StatusError) + // WithTimeout returns an http.Handler that runs h with a timeout // determined by timeoutFunc. The new http.Handler calls h.ServeHTTP to handle // each request, but if a call runs for longer than its time limit, the @@ -71,17 +75,17 @@ func WithTimeoutForNonLongRunningRequests(handler http.Handler, requestContextMa // http.ErrHandlerTimeout. If timeoutFunc returns a nil timeout channel, no // timeout will be enforced. recordFn is a function that will be invoked whenever // a timeout happens. -func WithTimeout(h http.Handler, timeoutFunc func(*http.Request) (timeout <-chan time.Time, recordFn func(), err *apierrors.StatusError)) http.Handler { +func WithTimeout(h http.Handler, timeoutFunc timeoutFunc) http.Handler { return &timeoutHandler{h, timeoutFunc} } type timeoutHandler struct { handler http.Handler - timeout func(*http.Request) (<-chan time.Time, func(), *apierrors.StatusError) + timeout timeoutFunc } func (t *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - after, recordFn, err := t.timeout(r) + r, after, postTimeoutFn, err := t.timeout(r) if after == nil { t.handler.ServeHTTP(w, r) return @@ -97,7 +101,7 @@ func (t *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { case <-done: return case <-after: - recordFn() + postTimeoutFn() tw.timeout(err) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/timeout_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/timeout_test.go index 6283a6cc2..441ca3efd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/timeout_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/timeout_test.go @@ -63,8 +63,8 @@ func TestTimeout(t *testing.T) { _, err := w.Write([]byte(resp)) writeErrors <- err }), - func(*http.Request) (<-chan time.Time, func(), *apierrors.StatusError) { - return timeout, record.Record, timeoutErr + func(req *http.Request) (*http.Request, <-chan time.Time, func(), *apierrors.StatusError) { + return req, timeout, record.Record, timeoutErr })) defer ts.Close() diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/waitgroup.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/waitgroup.go index c73978e20..b40a42272 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/waitgroup.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/filters/waitgroup.go @@ -17,26 +17,22 @@ limitations under the License. package filters import ( + "errors" "net/http" utilwaitgroup "k8s.io/apimachinery/pkg/util/waitgroup" + "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" apirequest "k8s.io/apiserver/pkg/endpoints/request" ) // WithWaitGroup adds all non long-running requests to wait group, which is used for graceful shutdown. -func WithWaitGroup(handler http.Handler, requestContextMapper apirequest.RequestContextMapper, longRunning apirequest.LongRunningRequestCheck, wg *utilwaitgroup.SafeWaitGroup) http.Handler { +func WithWaitGroup(handler http.Handler, longRunning apirequest.LongRunningRequestCheck, wg *utilwaitgroup.SafeWaitGroup) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ctx, ok := requestContextMapper.Get(req) - if !ok { - // if this happens, the handler chain isn't setup correctly because there is no context mapper - handler.ServeHTTP(w, req) - return - } - + ctx := req.Context() requestInfo, ok := apirequest.RequestInfoFrom(ctx) if !ok { // if this happens, the handler chain isn't setup correctly because there is no request info - handler.ServeHTTP(w, req) + responsewriters.InternalError(w, req, errors.New("no RequestInfo found in the context")) return } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go index 38cd2e981..9beba735d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go @@ -27,8 +27,7 @@ import ( "github.com/emicklei/go-restful-swagger12" "github.com/golang/glog" - "k8s.io/apimachinery/pkg/apimachinery" - "k8s.io/apimachinery/pkg/apimachinery/registered" + "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" @@ -39,7 +38,6 @@ import ( "k8s.io/apiserver/pkg/audit" genericapi "k8s.io/apiserver/pkg/endpoints" "k8s.io/apiserver/pkg/endpoints/discovery" - apirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/routes" @@ -49,8 +47,8 @@ import ( // Info about an API group. type APIGroupInfo struct { - GroupMeta apimachinery.GroupMeta - // Info about the resources in this group. Its a map from version to resource to the storage. + PrioritizedVersions []schema.GroupVersion + // Info about the resources in this group. It's a map from version to resource to the storage. VersionedResourcesStorageMap map[string]map[string]rest.Storage // OptionsExternalVersion controls the APIVersion used for common objects in the // schema like api.Status, api.DeleteOptions, and metav1.ListOptions. Other implementors may @@ -95,9 +93,7 @@ type GenericAPIServer struct { // admissionControl is used to build the RESTStorage that backs an API Group. admissionControl admission.Interface - // requestContextMapper provides a way to get the context for a request. It may be nil. - requestContextMapper apirequest.RequestContextMapper - + // SecureServingInfo holds configuration of the TLS server. SecureServingInfo *SecureServingInfo // ExternalAddress is the address (hostname or IP and port) that should be used in @@ -146,7 +142,7 @@ type GenericAPIServer struct { // if the client requests it via Accept-Encoding enableAPIResponseCompression bool - // delegationTarget is the next delegate in the chain or nil + // delegationTarget is the next delegate in the chain. This is never nil. delegationTarget DelegationTarget // HandlerChainWaitGroup allows you to wait for all chain handlers finish after the server shutdown. @@ -159,10 +155,6 @@ type DelegationTarget interface { // UnprotectedHandler returns a handler that is NOT protected by a normal chain UnprotectedHandler() http.Handler - // RequestContextMapper returns the existing RequestContextMapper. Because we cannot rewire all existing - // uses of this function, this will be used in any delegating API server - RequestContextMapper() apirequest.RequestContextMapper - // PostStartHooks returns the post-start hooks that need to be combined PostStartHooks() map[string]postStartHookEntry @@ -200,12 +192,11 @@ func (s *GenericAPIServer) NextDelegate() DelegationTarget { return s.delegationTarget } -var EmptyDelegate = emptyDelegate{ - requestContextMapper: apirequest.NewRequestContextMapper(), +type emptyDelegate struct { } -type emptyDelegate struct { - requestContextMapper apirequest.RequestContextMapper +func NewEmptyDelegate() DelegationTarget { + return emptyDelegate{} } func (s emptyDelegate) UnprotectedHandler() http.Handler { @@ -223,25 +214,11 @@ func (s emptyDelegate) HealthzChecks() []healthz.HealthzChecker { func (s emptyDelegate) ListedPaths() []string { return []string{} } -func (s emptyDelegate) RequestContextMapper() apirequest.RequestContextMapper { - return s.requestContextMapper -} func (s emptyDelegate) NextDelegate() DelegationTarget { return nil } -// RequestContextMapper is exposed so that third party resource storage can be build in a different location. -// TODO refactor third party resource storage -func (s *GenericAPIServer) RequestContextMapper() apirequest.RequestContextMapper { - return s.requestContextMapper -} - -// MinRequestTimeout is exposed so that third party resource storage can be build in a different location. -// TODO refactor third party resource storage -func (s *GenericAPIServer) MinRequestTimeout() time.Duration { - return s.minRequestTimeout -} - +// preparedGenericAPIServer is a private wrapper that enforces a call of PrepareRun() before Run can be invoked. type preparedGenericAPIServer struct { *GenericAPIServer } @@ -259,12 +236,6 @@ func (s *GenericAPIServer) PrepareRun() preparedGenericAPIServer { s.installHealthz() - return preparedGenericAPIServer{s} -} - -// Run spawns the secure http server. It only returns if stopCh is closed -// or the secure port cannot be listened on initially. -func (s preparedGenericAPIServer) Run(stopCh <-chan struct{}) error { // Register audit backend preShutdownHook. if s.AuditBackend != nil { s.AddPreShutdownHook("audit-backend", func() error { @@ -273,6 +244,12 @@ func (s preparedGenericAPIServer) Run(stopCh <-chan struct{}) error { }) } + return preparedGenericAPIServer{s} +} + +// Run spawns the secure http server. It only returns if stopCh is closed +// or the secure port cannot be listened on initially. +func (s preparedGenericAPIServer) Run(stopCh <-chan struct{}) error { err := s.NonBlockingRun(stopCh) if err != nil { return err @@ -337,7 +314,7 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error { // installAPIResources is a private method for installing the REST storage backing each api groupversionresource func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *APIGroupInfo) error { - for _, groupVersion := range apiGroupInfo.GroupMeta.GroupVersions { + for _, groupVersion := range apiGroupInfo.PrioritizedVersions { if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 { glog.Warningf("Skipping API %v because it has no resources.", groupVersion) continue @@ -349,7 +326,7 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A } if err := apiGroupVersion.InstallREST(s.Handler.GoRestfulContainer); err != nil { - return fmt.Errorf("Unable to setup API %v: %v", apiGroupInfo, err) + return fmt.Errorf("unable to setup API %v: %v", apiGroupInfo, err) } } @@ -366,12 +343,13 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo // setup discovery apiVersions := []string{} - for _, groupVersion := range apiGroupInfo.GroupMeta.GroupVersions { + for _, groupVersion := range apiGroupInfo.PrioritizedVersions { apiVersions = append(apiVersions, groupVersion.Version) } // Install the version handler. // Add a handler at / to enumerate the supported api versions. - s.Handler.GoRestfulContainer.Add(discovery.NewLegacyRootAPIHandler(s.discoveryAddresses, s.Serializer, apiPrefix, apiVersions, s.requestContextMapper).WebService()) + s.Handler.GoRestfulContainer.Add(discovery.NewLegacyRootAPIHandler(s.discoveryAddresses, s.Serializer, apiPrefix, apiVersions).WebService()) + return nil } @@ -379,10 +357,10 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error { // Do not register empty group or empty version. Doing so claims /apis/ for the wrong entity to be returned. // Catching these here places the error much closer to its origin - if len(apiGroupInfo.GroupMeta.GroupVersion.Group) == 0 { + if len(apiGroupInfo.PrioritizedVersions[0].Group) == 0 { return fmt.Errorf("cannot register handler with an empty group for %#v", *apiGroupInfo) } - if len(apiGroupInfo.GroupMeta.GroupVersion.Version) == 0 { + if len(apiGroupInfo.PrioritizedVersions[0].Version) == 0 { return fmt.Errorf("cannot register handler with an empty version for %#v", *apiGroupInfo) } @@ -394,7 +372,7 @@ func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error { // Install the version handler. // Add a handler at /apis/ to enumerate all versions supported by this group. apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{} - for _, groupVersion := range apiGroupInfo.GroupMeta.GroupVersions { + for _, groupVersion := range apiGroupInfo.PrioritizedVersions { // Check the config to make sure that we elide versions that don't have any resources if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 { continue @@ -405,17 +383,17 @@ func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error { }) } preferredVersionForDiscovery := metav1.GroupVersionForDiscovery{ - GroupVersion: apiGroupInfo.GroupMeta.GroupVersion.String(), - Version: apiGroupInfo.GroupMeta.GroupVersion.Version, + GroupVersion: apiGroupInfo.PrioritizedVersions[0].String(), + Version: apiGroupInfo.PrioritizedVersions[0].Version, } apiGroup := metav1.APIGroup{ - Name: apiGroupInfo.GroupMeta.GroupVersion.Group, + Name: apiGroupInfo.PrioritizedVersions[0].Group, Versions: apiVersionsForDiscovery, PreferredVersion: preferredVersionForDiscovery, } s.DiscoveryGroupManager.AddGroup(apiGroup) - s.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(s.Serializer, apiGroup, s.requestContextMapper).WebService()) + s.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(s.Serializer, apiGroup).WebService()) return nil } @@ -443,23 +421,20 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV UnsafeConvertor: runtime.UnsafeObjectConvertor(apiGroupInfo.Scheme), Defaulter: apiGroupInfo.Scheme, Typer: apiGroupInfo.Scheme, - Linker: apiGroupInfo.GroupMeta.SelfLinker, - Mapper: apiGroupInfo.GroupMeta.RESTMapper, + Linker: runtime.SelfLinker(meta.NewAccessor()), Admit: s.admissionControl, - Context: s.RequestContextMapper(), MinRequestTimeout: s.minRequestTimeout, EnableAPIResponseCompression: s.enableAPIResponseCompression, + OpenAPIConfig: s.openAPIConfig, } } // NewDefaultAPIGroupInfo returns an APIGroupInfo stubbed with "normal" values // exposed for easier composition from other packages -func NewDefaultAPIGroupInfo(group string, registry *registered.APIRegistrationManager, scheme *runtime.Scheme, parameterCodec runtime.ParameterCodec, codecs serializer.CodecFactory) APIGroupInfo { - groupMeta := registry.GroupOrDie(group) - +func NewDefaultAPIGroupInfo(group string, scheme *runtime.Scheme, parameterCodec runtime.ParameterCodec, codecs serializer.CodecFactory) APIGroupInfo { return APIGroupInfo{ - GroupMeta: *groupMeta, + PrioritizedVersions: scheme.PrioritizedVersionsForGroup(group), VersionedResourcesStorageMap: map[string]map[string]rest.Storage{}, // TODO unhardcode this. It was hardcoded before, but we need to re-evaluate OptionsExternalVersion: &schema.GroupVersion{Version: "v1"}, diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go index 18761881b..00a9f87fe 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go @@ -17,6 +17,7 @@ limitations under the License. package server import ( + "context" "encoding/json" "fmt" "io" @@ -30,11 +31,9 @@ import ( "testing" "time" - // "github.com/go-openapi/spec" + openapi "github.com/go-openapi/spec" "github.com/stretchr/testify/assert" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/apimachinery" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -43,16 +42,16 @@ import ( "k8s.io/apimachinery/pkg/version" "k8s.io/apiserver/pkg/apis/example" examplev1 "k8s.io/apiserver/pkg/apis/example/v1" - "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/endpoints/discovery" genericapifilters "k8s.io/apiserver/pkg/endpoints/filters" - apirequest "k8s.io/apiserver/pkg/endpoints/request" + openapinamer "k8s.io/apiserver/pkg/endpoints/openapi" "k8s.io/apiserver/pkg/registry/rest" genericfilters "k8s.io/apiserver/pkg/server/filters" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes/fake" restclient "k8s.io/client-go/rest" + kubeopenapi "k8s.io/kube-openapi/pkg/common" ) const ( @@ -80,11 +79,52 @@ func init() { examplev1.AddToScheme(scheme) } +func buildTestOpenAPIDefinition() kubeopenapi.OpenAPIDefinition { + return kubeopenapi.OpenAPIDefinition{ + Schema: openapi.Schema{ + SchemaProps: openapi.SchemaProps{ + Description: "Description", + Properties: map[string]openapi.Schema{}, + }, + VendorExtensible: openapi.VendorExtensible{ + Extensions: openapi.Extensions{ + "x-kubernetes-group-version-kind": []map[string]string{ + { + "group": "", + "version": "v1", + "kind": "Getter", + }, + { + "group": "batch", + "version": "v1", + "kind": "Getter", + }, + { + "group": "extensions", + "version": "v1", + "kind": "Getter", + }, + }, + }, + }, + }, + } +} + +func testGetOpenAPIDefinitions(_ kubeopenapi.ReferenceCallback) map[string]kubeopenapi.OpenAPIDefinition { + return map[string]kubeopenapi.OpenAPIDefinition{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Status": {}, + "k8s.io/apimachinery/pkg/apis/meta/v1.APIVersions": {}, + "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroupList": {}, + "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroup": buildTestOpenAPIDefinition(), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIResourceList": {}, + } +} + // setUp is a convience function for setting up for (most) tests. func setUp(t *testing.T) (Config, *assert.Assertions) { config := NewConfig(codecs) config.PublicAddress = net.ParseIP("192.168.10.4") - config.RequestContextMapper = apirequest.NewRequestContextMapper() config.LegacyAPIGroupPrefixes = sets.NewString("/api") config.LoopbackClientConfig = &restclient.Config{} @@ -93,14 +133,8 @@ func setUp(t *testing.T) (Config, *assert.Assertions) { t.Fatal("unable to create fake client set") } - // TODO restore this test, but right now, eliminate our cycle - // config.OpenAPIConfig = DefaultOpenAPIConfig(testGetOpenAPIDefinitions, runtime.NewScheme()) - // config.OpenAPIConfig.Info = &spec.Info{ - // InfoProps: spec.InfoProps{ - // Title: "Kubernetes", - // Version: "unversioned", - // }, - // } + config.OpenAPIConfig = DefaultOpenAPIConfig(testGetOpenAPIDefinitions, openapinamer.NewDefinitionNamer(runtime.NewScheme())) + config.OpenAPIConfig.Info.Version = "unversioned" config.SwaggerConfig = DefaultSwaggerConfig() sharedInformers := informers.NewSharedInformerFactory(clientset, config.LoopbackClientConfig.Timeout) config.Complete(sharedInformers) @@ -111,7 +145,7 @@ func setUp(t *testing.T) (Config, *assert.Assertions) { func newMaster(t *testing.T) (*GenericAPIServer, Config, *assert.Assertions) { config, assert := setUp(t) - s, err := config.Complete(nil).New("test", EmptyDelegate) + s, err := config.Complete(nil).New("test", NewEmptyDelegate()) if err != nil { t.Fatalf("Error in bringing up the server: %v", err) } @@ -126,7 +160,6 @@ func TestNew(t *testing.T) { // Verify many of the variables match their config counterparts assert.Equal(s.legacyAPIGroupPrefixes, config.LegacyAPIGroupPrefixes) assert.Equal(s.admissionControl, config.AdmissionControl) - assert.Equal(s.RequestContextMapper(), config.RequestContextMapper) // these values get defaulted assert.Equal(net.JoinHostPort(config.PublicAddress.String(), "443"), s.ExternalAddress) @@ -141,7 +174,7 @@ func TestInstallAPIGroups(t *testing.T) { config.LegacyAPIGroupPrefixes = sets.NewString("/apiPrefix") config.DiscoveryAddresses = discovery.DefaultAddresses{DefaultAddress: "ExternalAddress"} - s, err := config.Complete(nil).New("test", EmptyDelegate) + s, err := config.Complete(nil).New("test", NewEmptyDelegate()) if err != nil { t.Fatalf("Error in bringing up the server: %v", err) } @@ -155,26 +188,8 @@ func TestInstallAPIGroups(t *testing.T) { scheme.AddKnownTypes(v1GroupVersion, &metav1.Status{}) metav1.AddToGroupVersion(scheme, v1GroupVersion) - interfacesFor := func(version schema.GroupVersion) (*meta.VersionInterfaces, error) { - return &meta.VersionInterfaces{ - ObjectConvertor: scheme, - MetadataAccessor: meta.NewAccessor(), - }, nil - } - - mapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{gv}, interfacesFor) - for kind := range scheme.KnownTypes(gv) { - mapper.Add(gv.WithKind(kind), meta.RESTScopeNamespace) - } - groupMeta := apimachinery.GroupMeta{ - GroupVersion: gv, - GroupVersions: []schema.GroupVersion{gv}, - RESTMapper: mapper, - InterfacesFor: interfacesFor, - } - return APIGroupInfo{ - GroupMeta: groupMeta, + PrioritizedVersions: []schema.GroupVersion{gv}, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ gv.Version: { "getter": &testGetterStorage{Version: gv.Version}, @@ -202,7 +217,7 @@ func TestInstallAPIGroups(t *testing.T) { for _, api := range apis[1:] { err = s.InstallAPIGroup(&api) assert.NoError(err) - groupPaths = append(groupPaths, APIGroupPrefix+"/"+api.GroupMeta.GroupVersion.Group) // /apis/ + groupPaths = append(groupPaths, APIGroupPrefix+"/"+api.PrioritizedVersions[0].Group) // /apis/ } server := httptest.NewServer(s.Handler) @@ -243,19 +258,19 @@ func TestInstallAPIGroups(t *testing.T) { continue } - if got, expected := group.Name, info.GroupMeta.GroupVersion.Group; got != expected { + if got, expected := group.Name, info.PrioritizedVersions[0].Group; got != expected { t.Errorf("[%d] unexpected group name at path %q: got=%q expected=%q", i, path, got, expected) continue } - if got, expected := group.PreferredVersion.Version, info.GroupMeta.GroupVersion.Version; got != expected { + if got, expected := group.PreferredVersion.Version, info.PrioritizedVersions[0].Version; got != expected { t.Errorf("[%d] unexpected group version at path %q: got=%q expected=%q", i, path, got, expected) continue } } // should serve APIResourceList at group path + / - path = path + "/" + info.GroupMeta.GroupVersion.Version + path = path + "/" + info.PrioritizedVersions[0].Version resp, err = http.Get(server.URL + path) if err != nil { t.Errorf("[%d] unexpected error getting path %q path: %v", i, path, err) @@ -277,7 +292,7 @@ func TestInstallAPIGroups(t *testing.T) { continue } - if got, expected := resources.GroupVersion, info.GroupMeta.GroupVersion.String(); got != expected { + if got, expected := resources.GroupVersion, info.PrioritizedVersions[0].String(); got != expected { t.Errorf("[%d] unexpected groupVersion at path %q: got=%q expected=%q", i, path, got, expected) continue } @@ -343,7 +358,7 @@ func TestCustomHandlerChain(t *testing.T) { called = true }) - s, err := config.Complete(nil).New("test", EmptyDelegate) + s, err := config.Complete(nil).New("test", NewEmptyDelegate()) if err != nil { t.Fatalf("Error in bringing up the server: %v", err) } @@ -397,7 +412,7 @@ func TestNotRestRoutesHaveAuth(t *testing.T) { kubeVersion := fakeVersion() config.Version = &kubeVersion - s, err := config.Complete(nil).New("test", EmptyDelegate) + s, err := config.Complete(nil).New("test", NewEmptyDelegate()) if err != nil { t.Fatalf("Error in bringing up the server: %v", err) } @@ -408,6 +423,7 @@ func TestNotRestRoutesHaveAuth(t *testing.T) { {"/"}, {"/swagger-ui/"}, {"/debug/pprof/"}, + {"/debug/flags/"}, {"/version"}, } { resp := httptest.NewRecorder() @@ -433,34 +449,14 @@ func (authz *mockAuthorizer) Authorize(a authorizer.Attributes) (authorized auth return authorizer.DecisionAllow, "", nil } -type mockAuthenticator struct { - lastURI string -} - -func (authn *mockAuthenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) { - authn.lastURI = req.RequestURI - return &user.DefaultInfo{ - Name: "foo", - }, true, nil -} - -func decodeResponse(resp *http.Response, obj interface{}) error { - defer resp.Body.Close() - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return err - } - if err := json.Unmarshal(data, obj); err != nil { - return err - } - return nil -} - type testGetterStorage struct { Version string } +func (p *testGetterStorage) NamespaceScoped() bool { + return true +} + func (p *testGetterStorage) New() runtime.Object { return &metav1.APIGroup{ TypeMeta: metav1.TypeMeta{ @@ -470,7 +466,7 @@ func (p *testGetterStorage) New() runtime.Object { } } -func (p *testGetterStorage) Get(ctx apirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { +func (p *testGetterStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { return nil, nil } @@ -478,6 +474,10 @@ type testNoVerbsStorage struct { Version string } +func (p *testNoVerbsStorage) NamespaceScoped() bool { + return true +} + func (p *testNoVerbsStorage) New() runtime.Object { return &metav1.APIGroup{ TypeMeta: metav1.TypeMeta{ @@ -510,9 +510,8 @@ func TestGracefulShutdown(t *testing.T) { wg.Add(1) config.BuildHandlerChainFunc = func(apiHandler http.Handler, c *Config) http.Handler { - handler := genericfilters.WithWaitGroup(apiHandler, c.RequestContextMapper, c.LongRunningFunc, c.HandlerChainWaitGroup) - handler = genericapifilters.WithRequestInfo(handler, c.RequestInfoResolver, c.RequestContextMapper) - handler = apirequest.WithRequestContext(handler, c.RequestContextMapper) + handler := genericfilters.WithWaitGroup(apiHandler, c.LongRunningFunc, c.HandlerChainWaitGroup) + handler = genericapifilters.WithRequestInfo(handler, c.RequestInfoResolver) return handler } @@ -523,7 +522,7 @@ func TestGracefulShutdown(t *testing.T) { graceShutdown = true }) - s, err := config.Complete(nil).New("test", EmptyDelegate) + s, err := config.Complete(nil).New("test", NewEmptyDelegate()) if err != nil { t.Fatalf("Error in bringing up the server: %v", err) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/handler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/handler.go index a92196cba..e4e7d9aee 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/handler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/handler.go @@ -18,7 +18,6 @@ package server import ( "bytes" - "errors" "fmt" "net/http" rt "runtime" @@ -32,7 +31,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/server/mux" ) @@ -72,7 +70,7 @@ type APIServerHandler struct { // It is normally used to apply filtering like authentication and authorization type HandlerChainBuilderFn func(apiHandler http.Handler) http.Handler -func NewAPIServerHandler(name string, contextMapper request.RequestContextMapper, s runtime.NegotiatedSerializer, handlerChainBuilder HandlerChainBuilderFn, notFoundHandler http.Handler) *APIServerHandler { +func NewAPIServerHandler(name string, s runtime.NegotiatedSerializer, handlerChainBuilder HandlerChainBuilderFn, notFoundHandler http.Handler) *APIServerHandler { nonGoRestfulMux := mux.NewPathRecorderMux(name) if notFoundHandler != nil { nonGoRestfulMux.NotFoundHandler(notFoundHandler) @@ -85,11 +83,7 @@ func NewAPIServerHandler(name string, contextMapper request.RequestContextMapper logStackOnRecover(s, panicReason, httpWriter) }) gorestfulContainer.ServiceErrorHandler(func(serviceErr restful.ServiceError, request *restful.Request, response *restful.Response) { - ctx, ok := contextMapper.Get(request.Request) - if !ok { - responsewriters.InternalError(response.ResponseWriter, request.Request, errors.New("no context found for request")) - } - serviceErrorHandler(ctx, s, serviceErr, request, response) + serviceErrorHandler(s, serviceErr, request, response) }) director := director{ @@ -177,13 +171,11 @@ func logStackOnRecover(s runtime.NegotiatedSerializer, panicReason interface{}, if ct := w.Header().Get("Content-Type"); len(ct) > 0 { headers.Set("Accept", ct) } - emptyContext := request.NewContext() // best we can do here: we don't know the request - responsewriters.ErrorNegotiated(emptyContext, apierrors.NewGenericServerResponse(http.StatusInternalServerError, "", schema.GroupResource{}, "", "", 0, false), s, schema.GroupVersion{}, w, &http.Request{Header: headers}) + responsewriters.ErrorNegotiated(apierrors.NewGenericServerResponse(http.StatusInternalServerError, "", schema.GroupResource{}, "", "", 0, false), s, schema.GroupVersion{}, w, &http.Request{Header: headers}) } -func serviceErrorHandler(ctx request.Context, s runtime.NegotiatedSerializer, serviceErr restful.ServiceError, request *restful.Request, resp *restful.Response) { +func serviceErrorHandler(s runtime.NegotiatedSerializer, serviceErr restful.ServiceError, request *restful.Request, resp *restful.Response) { responsewriters.ErrorNegotiated( - ctx, apierrors.NewGenericServerResponse(serviceErr.Code, "", schema.GroupResource{}, "", serviceErr.Message, 0, false), s, schema.GroupVersion{}, diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go index bd8bfe7b5..224f1eda2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go @@ -66,6 +66,15 @@ func NamedCheck(name string, check func(r *http.Request) error) HealthzChecker { // exactly one call to InstallHandler. Calling InstallHandler more // than once for the same mux will result in a panic. func InstallHandler(mux mux, checks ...HealthzChecker) { + InstallPathHandler(mux, "/healthz", checks...) +} + +// InstallPathHandler registers handlers for health checking on +// a specific path to mux. *All handlers* for the path must be +// specified in exactly one call to InstallPathHandler. Calling +// InstallPathHandler more than once for the same path and mux will +// result in a panic. +func InstallPathHandler(mux mux, path string, checks ...HealthzChecker) { if len(checks) == 0 { glog.V(5).Info("No default health checks specified. Installing the ping handler.") checks = []HealthzChecker{PingHealthz} @@ -73,9 +82,9 @@ func InstallHandler(mux mux, checks ...HealthzChecker) { glog.V(5).Info("Installing healthz checkers:", strings.Join(checkerNames(checks...), ", ")) - mux.Handle("/healthz", handleRootHealthz(checks...)) + mux.Handle(path, handleRootHealthz(checks...)) for _, check := range checks { - mux.Handle(fmt.Sprintf("/healthz/%v", check.Name()), adaptCheckToHandler(check.Check)) + mux.Handle(fmt.Sprintf("%s/%v", path, check.Name()), adaptCheckToHandler(check.Check)) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz_test.go index 99aae5a9e..a1f761b78 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz_test.go @@ -42,6 +42,38 @@ func TestInstallHandler(t *testing.T) { } } +func TestInstallPathHandler(t *testing.T) { + mux := http.NewServeMux() + InstallPathHandler(mux, "/healthz/test") + InstallPathHandler(mux, "/healthz/ready") + req, err := http.NewRequest("GET", "http://example.com/healthz/test", nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + w := httptest.NewRecorder() + mux.ServeHTTP(w, req) + if w.Code != http.StatusOK { + t.Errorf("expected %v, got %v", http.StatusOK, w.Code) + } + if w.Body.String() != "ok" { + t.Errorf("expected %v, got %v", "ok", w.Body.String()) + } + + req, err = http.NewRequest("GET", "http://example.com/healthz/ready", nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + w = httptest.NewRecorder() + mux.ServeHTTP(w, req) + if w.Code != http.StatusOK { + t.Errorf("expected %v, got %v", http.StatusOK, w.Code) + } + if w.Body.String() != "ok" { + t.Errorf("expected %v, got %v", "ok", w.Body.String()) + } + +} + func TestMulitipleChecks(t *testing.T) { tests := []struct { path string diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/httplog/httplog.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/httplog/httplog.go index 5939ccb04..ee8e05f10 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/httplog/httplog.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/httplog/httplog.go @@ -146,7 +146,7 @@ func (rl *respLogger) Addf(format string, data ...interface{}) { // Log is intended to be called once at the end of your request handler, via defer func (rl *respLogger) Log() { latency := time.Since(rl.startTime) - if glog.V(2) { + if glog.V(3) { if !rl.hijacked { glog.InfoDepth(1, fmt.Sprintf("%s %s: (%v) %v%v%v [%s %s]", rl.req.Method, rl.req.RequestURI, latency, rl.status, rl.statusStack, rl.addedInfo, rl.req.Header["User-Agent"], rl.req.RemoteAddr)) } else { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/BUILD index 1f6fab958..3d5348557 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/BUILD @@ -39,6 +39,7 @@ go_library( "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/apis/audit/v1alpha1:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library", "//vendor/k8s.io/apiserver/pkg/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/audit/policy:go_default_library", @@ -89,7 +90,6 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/admission_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/admission_test.go index 71961a8ff..13a8176a1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/admission_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/admission_test.go @@ -53,7 +53,7 @@ func TestEnabledPluginNames(t *testing.T) { setDefaultOffPlugins: sets.NewString(), }, - // scenario 3: use default off plugins and specified by enable-admission-plugin with RecommendedPluginOrder + // scenario 3: use default off plugins and specified by enable-admission-plugins with RecommendedPluginOrder { expectedPluginNames: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, @@ -61,7 +61,7 @@ func TestEnabledPluginNames(t *testing.T) { setEnablePlugins: []string{"pluginD", "pluginC"}, }, - // scenario 4: use default off plugins and specified by disable-admission-plugin with RecommendedPluginOrder + // scenario 4: use default off plugins and specified by disable-admission-plugins with RecommendedPluginOrder { expectedPluginNames: []string{"pluginB"}, setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, @@ -69,7 +69,7 @@ func TestEnabledPluginNames(t *testing.T) { setDisablePlugins: []string{"pluginA"}, }, - // scenario 5: use default off plugins and specified by enable-admission-plugin and disable-admission-plugin with RecommendedPluginOrder + // scenario 5: use default off plugins and specified by enable-admission-plugins and disable-admission-plugins with RecommendedPluginOrder { expectedPluginNames: []string{"pluginA", "pluginC"}, setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, @@ -142,39 +142,39 @@ func TestValidate(t *testing.T) { expectedResult: true, }, - // scenario 1: set both `--enable-admission-plugin` `--disable-admission-plugin` + // scenario 1: set both `--enable-admission-plugins` `--disable-admission-plugins` { setEnablePlugins: []string{"pluginA", "pluginB"}, setDisablePlugins: []string{"pluginC"}, expectedResult: true, }, - // scenario 2: set invalid `--enable-admission-plugin` `--disable-admission-plugin` + // scenario 2: set invalid `--enable-admission-plugins` `--disable-admission-plugins` { setEnablePlugins: []string{"pluginA", "pluginB"}, setDisablePlugins: []string{"pluginB"}, expectedResult: false, }, - // scenario 3: set only invalid `--enable-admission-plugin` + // scenario 3: set only invalid `--enable-admission-plugins` { setEnablePlugins: []string{"pluginA", "pluginE"}, expectedResult: false, }, - // scenario 4: set only invalid `--disable-admission-plugin` + // scenario 4: set only invalid `--disable-admission-plugins` { setDisablePlugins: []string{"pluginA", "pluginE"}, expectedResult: false, }, - // scenario 5: set valid `--enable-admission-plugin` + // scenario 5: set valid `--enable-admission-plugins` { setEnablePlugins: []string{"pluginA", "pluginB"}, expectedResult: true, }, - // scenario 6: set valid `--disable-admission-plugin` + // scenario 6: set valid `--disable-admission-plugins` { setDisablePlugins: []string{"pluginA"}, expectedResult: true, diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/api_enablement.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/api_enablement.go index 3901511f6..8c64beed8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/api_enablement.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/api_enablement.go @@ -97,7 +97,7 @@ func (s *APIEnablementOptions) ApplyTo(c *server.Config, defaultResourceConfig * func unknownGroups(groups []string, registry GroupRegisty) []string { unknownGroups := []string{} for _, group := range groups { - if !registry.IsRegistered(group) { + if !registry.IsGroupRegistered(group) { unknownGroups = append(unknownGroups, group) } } @@ -107,5 +107,5 @@ func unknownGroups(groups []string, registry GroupRegisty) []string { // GroupRegisty provides a method to check whether given group is registered. type GroupRegisty interface { // IsRegistered returns true if given group is registered. - IsRegistered(group string) bool + IsGroupRegistered(group string) bool } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/audit.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/audit.go index 566bcea02..ab7781216 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/audit.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/audit.go @@ -27,6 +27,8 @@ import ( "github.com/spf13/pflag" "gopkg.in/natefinch/lumberjack.v2" + "k8s.io/apimachinery/pkg/runtime/schema" + auditv1alpha1 "k8s.io/apiserver/pkg/apis/audit/v1alpha1" auditv1beta1 "k8s.io/apiserver/pkg/apis/audit/v1beta1" "k8s.io/apiserver/pkg/audit" "k8s.io/apiserver/pkg/audit/policy" @@ -78,9 +80,6 @@ var AllowedModes = []string{ ModeBlocking, } -// API group version used for serializing audit events. -var GroupVersion = auditv1beta1.SchemeGroupVersion - type AuditBatchOptions struct { // Should the backend asynchronous batch events to the webhook backend or // should the backend block responses? @@ -111,6 +110,9 @@ type AuditLogOptions struct { BatchOptions AuditBatchOptions TruncateOptions AuditTruncateOptions + + // API group version used for serializing audit events. + GroupVersionString string } // AuditWebhookOptions control the webhook configuration for audit events. @@ -120,6 +122,9 @@ type AuditWebhookOptions struct { BatchOptions AuditBatchOptions TruncateOptions AuditTruncateOptions + + // API group version used for serializing audit events. + GroupVersionString string } func NewAuditOptions() *AuditOptions { @@ -133,7 +138,8 @@ func NewAuditOptions() *AuditOptions { Mode: ModeBatch, BatchConfig: pluginbuffered.NewDefaultBatchConfig(), }, - TruncateOptions: NewAuditTruncateOptions(), + TruncateOptions: NewAuditTruncateOptions(), + GroupVersionString: "audit.k8s.io/v1beta1", }, LogOptions: AuditLogOptions{ Format: pluginlog.FormatJson, @@ -141,7 +147,8 @@ func NewAuditOptions() *AuditOptions { Mode: ModeBlocking, BatchConfig: defaultLogBatchConfig, }, - TruncateOptions: NewAuditTruncateOptions(), + TruncateOptions: NewAuditTruncateOptions(), + GroupVersionString: "audit.k8s.io/v1beta1", }, } } @@ -212,6 +219,31 @@ func validateBackendBatchOptions(pluginName string, options AuditBatchOptions) e return nil } +var knownGroupVersions = []schema.GroupVersion{ + auditv1alpha1.SchemeGroupVersion, + auditv1beta1.SchemeGroupVersion, +} + +func validateGroupVersionString(groupVersion string) error { + gv, err := schema.ParseGroupVersion(groupVersion) + if err != nil { + return err + } + if !knownGroupVersion(gv) { + return fmt.Errorf("invalid group version, allowed versions are %q", knownGroupVersions) + } + return nil +} + +func knownGroupVersion(gv schema.GroupVersion) bool { + for _, knownGv := range knownGroupVersions { + if gv == knownGv { + return true + } + } + return false +} + func (o *AuditOptions) AddFlags(fs *pflag.FlagSet) { if o == nil { return @@ -327,11 +359,11 @@ func (o *AuditTruncateOptions) AddFlags(pluginName string, fs *pflag.FlagSet) { "if this doesn't reduce the size enough, event is discarded.") } -func (o *AuditTruncateOptions) wrapBackend(delegate audit.Backend) audit.Backend { +func (o *AuditTruncateOptions) wrapBackend(delegate audit.Backend, gv schema.GroupVersion) audit.Backend { if !o.Enabled { return delegate } - return plugintruncate.NewBackend(delegate, o.TruncateConfig, GroupVersion) + return plugintruncate.NewBackend(delegate, o.TruncateConfig, gv) } func (o *AuditLogOptions) AddFlags(fs *pflag.FlagSet) { @@ -347,6 +379,8 @@ func (o *AuditLogOptions) AddFlags(fs *pflag.FlagSet) { "Format of saved audits. \"legacy\" indicates 1-line text format for each event."+ " \"json\" indicates structured json format. Requires the 'AdvancedAuditing' feature"+ " gate. Known formats are "+strings.Join(pluginlog.AllowedFormats, ",")+".") + fs.StringVar(&o.GroupVersionString, "audit-log-version", o.GroupVersionString, + "API group and version used for serializing audit events written to log.") } func (o *AuditLogOptions) Validate() []error { @@ -364,6 +398,10 @@ func (o *AuditLogOptions) Validate() []error { allErrors = append(allErrors, err) } + if err := validateGroupVersionString(o.GroupVersionString); err != nil { + allErrors = append(allErrors, err) + } + // Check log format validFormat := false for _, f := range pluginlog.AllowedFormats { @@ -415,9 +453,10 @@ func (o *AuditLogOptions) getWriter() io.Writer { func (o *AuditLogOptions) advancedApplyTo(c *server.Config) error { if w := o.getWriter(); w != nil { - log := pluginlog.NewBackend(w, o.Format, GroupVersion) + groupVersion, _ := schema.ParseGroupVersion(o.GroupVersionString) + log := pluginlog.NewBackend(w, o.Format, groupVersion) log = o.BatchOptions.wrapBackend(log) - log = o.TruncateOptions.wrapBackend(log) + log = o.TruncateOptions.wrapBackend(log, groupVersion) c.AuditBackend = appendBackend(c.AuditBackend, log) } return nil @@ -438,6 +477,8 @@ func (o *AuditWebhookOptions) AddFlags(fs *pflag.FlagSet) { o.InitialBackoff, "The amount of time to wait before retrying the first failed request.") fs.MarkDeprecated("audit-webhook-batch-initial-backoff", "Deprecated, use --audit-webhook-initial-backoff instead.") + fs.StringVar(&o.GroupVersionString, "audit-webhook-version", o.GroupVersionString, + "API group and version used for serializing audit events written to webhook.") } func (o *AuditWebhookOptions) Validate() []error { @@ -453,6 +494,10 @@ func (o *AuditWebhookOptions) Validate() []error { if err := o.TruncateOptions.Validate(pluginwebhook.PluginName); err != nil { allErrors = append(allErrors, err) } + + if err := validateGroupVersionString(o.GroupVersionString); err != nil { + allErrors = append(allErrors, err) + } } return allErrors } @@ -466,12 +511,13 @@ func (o *AuditWebhookOptions) applyTo(c *server.Config) error { return nil } - webhook, err := pluginwebhook.NewBackend(o.ConfigFile, GroupVersion, o.InitialBackoff) + groupVersion, _ := schema.ParseGroupVersion(o.GroupVersionString) + webhook, err := pluginwebhook.NewBackend(o.ConfigFile, groupVersion, o.InitialBackoff) if err != nil { return fmt.Errorf("initializing audit webhook: %v", err) } webhook = o.BatchOptions.wrapBackend(webhook) - webhook = o.TruncateOptions.wrapBackend(webhook) + webhook = o.TruncateOptions.wrapBackend(webhook, groupVersion) c.AuditBackend = appendBackend(c.AuditBackend, webhook) return nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go index 04e1ea815..2ec5024de 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go @@ -59,7 +59,8 @@ func (s *RequestHeaderAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.ClientCAFile, "requestheader-client-ca-file", s.ClientCAFile, ""+ "Root certificate bundle to use to verify client certificates on incoming requests "+ - "before trusting usernames in headers specified by --requestheader-username-headers") + "before trusting usernames in headers specified by --requestheader-username-headers. "+ + "WARNING: generally do not depend on authorization being already done for incoming requests.") fs.StringSliceVar(&s.AllowedNames, "requestheader-allowed-names", s.AllowedNames, ""+ "List of client certificate common names to allow to provide usernames in headers "+ @@ -159,7 +160,11 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.AuthenticationInfo, clientCA, err := s.getClientCA() if err != nil { - return err + if _, ignorable := err.(ignorableError); !ignorable { + return err + } else { + glog.Warning(err) + } } if err = c.ApplyClientCert(clientCA.ClientCA, servingInfo); err != nil { return fmt.Errorf("unable to load client CA file: %v", err) @@ -199,7 +204,11 @@ func (s *DelegatingAuthenticationOptions) ToAuthenticationConfig() (authenticato clientCA, err := s.getClientCA() if err != nil { - return authenticatorfactory.DelegatingAuthenticatorConfig{}, err + if _, ignorable := err.(ignorableError); !ignorable { + return authenticatorfactory.DelegatingAuthenticatorConfig{}, err + } else { + glog.Warning(err) + } } requestHeader, err := s.getRequestHeader() if err != nil { @@ -218,8 +227,12 @@ func (s *DelegatingAuthenticationOptions) ToAuthenticationConfig() (authenticato const ( authenticationConfigMapNamespace = metav1.NamespaceSystem - authenticationConfigMapName = "extension-apiserver-authentication" - authenticationRoleName = "extension-apiserver-authentication-reader" + // authenticationConfigMapName is the name of ConfigMap in the kube-system namespace holding the root certificate + // bundle to use to verify client certificates on incoming requests before trusting usernames in headers specified + // by --requestheader-username-headers. This is created in the cluster by the kube-apiserver. + // "WARNING: generally do not depend on authorization being already done for incoming requests.") + authenticationConfigMapName = "extension-apiserver-authentication" + authenticationRoleName = "extension-apiserver-authentication-reader" ) func (s *DelegatingAuthenticationOptions) getClientCA() (*ClientCertAuthenticationOptions, error) { @@ -235,7 +248,7 @@ func (s *DelegatingAuthenticationOptions) getClientCA() (*ClientCertAuthenticati return nil, err } if incluster == nil { - return nil, fmt.Errorf("cluster doesn't provide client-ca-file") + return &s.ClientCert, ignorableError{fmt.Errorf("cluster doesn't provide client-ca-file in configmap/%s in %s, so client certificate authentication to extension api-server won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)} } return incluster, nil } @@ -389,3 +402,5 @@ func (s *DelegatingAuthenticationOptions) newTokenAccessReview() (authentication return client.TokenReviews(), nil } + +type ignorableError struct{ error } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/authorization.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/authorization.go index fb8899bff..a845921f0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/authorization.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/authorization.go @@ -29,7 +29,10 @@ import ( ) // DelegatingAuthorizationOptions provides an easy way for composing API servers to delegate their authorization to -// the root kube API server +// the root kube API server. +// WARNING: never assume that every authenticated incoming request already does authorization. +// The aggregator in the kube API server does this today, but this behaviour is not +// guaranteed in the future. type DelegatingAuthorizationOptions struct { // RemoteKubeConfigFile is the file to use to connect to a "normal" kube API server which hosts the // SubjectAccessReview.authorization.k8s.io endpoint for checking tokens. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/etcd.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/etcd.go index 5b8f1b9bb..36f5ff536 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/etcd.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/etcd.go @@ -91,6 +91,21 @@ func (s *EtcdOptions) Validate() []error { allErrors = append(allErrors, fmt.Errorf("--storage-backend invalid, must be 'etcd3' or 'etcd2'. If not specified, it will default to 'etcd3'")) } + for _, override := range s.EtcdServersOverrides { + tokens := strings.Split(override, "#") + if len(tokens) != 2 { + allErrors = append(allErrors, fmt.Errorf("--etcd-servers-overrides invalid, must be of format: group/resource#servers, where servers are URLs, semicolon separated")) + continue + } + + apiresource := strings.Split(tokens[0], "/") + if len(apiresource) != 2 { + allErrors = append(allErrors, fmt.Errorf("--etcd-servers-overrides invalid, must be of format: group/resource#servers, where servers are URLs, semicolon separated")) + continue + } + + } + return allErrors } @@ -102,7 +117,7 @@ func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) { fs.StringSliceVar(&s.EtcdServersOverrides, "etcd-servers-overrides", s.EtcdServersOverrides, ""+ "Per-resource etcd servers overrides, comma separated. The individual override "+ - "format: group/resource#servers, where servers are http://ip:port, semicolon separated.") + "format: group/resource#servers, where servers are URLs, semicolon separated.") fs.StringVar(&s.DefaultStorageMediaType, "storage-media-type", s.DefaultStorageMediaType, ""+ "The media type to use to store objects in storage. "+ diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/server_run_options.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/server_run_options.go index 985a17967..fccb24e03 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/server_run_options.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/server_run_options.go @@ -103,6 +103,10 @@ func (s *ServerRunOptions) Validate() []error { errors = append(errors, fmt.Errorf("--request-timeout can not be negative value")) } + if s.MinRequestTimeout < 0 { + errors = append(errors, fmt.Errorf("--min-request-timeout can not be negative value")) + } + return errors } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving.go index c4c2bf986..5d21da261 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving.go @@ -22,6 +22,7 @@ import ( "net" "path" "strconv" + "strings" "github.com/golang/glog" "github.com/spf13/pflag" @@ -134,14 +135,16 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.ServerCert.CertKey.KeyFile, "tls-private-key-file", s.ServerCert.CertKey.KeyFile, "File containing the default x509 private key matching --tls-cert-file.") + tlsCipherPossibleValues := utilflag.TLSCipherPossibleValues() fs.StringSliceVar(&s.CipherSuites, "tls-cipher-suites", s.CipherSuites, "Comma-separated list of cipher suites for the server. "+ - "Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). "+ - "If omitted, the default Go cipher suites will be used") + "If omitted, the default Go cipher suites will be use. "+ + "Possible values: "+strings.Join(tlsCipherPossibleValues, ",")) + tlsPossibleVersions := utilflag.TLSPossibleVersions() fs.StringVar(&s.MinTLSVersion, "tls-min-version", s.MinTLSVersion, "Minimum TLS version supported. "+ - "Value must match version names from https://golang.org/pkg/crypto/tls/#pkg-constants.") + "Possible values: "+strings.Join(tlsPossibleVersions, ", ")) fs.Var(utilflag.NewNamedCertKeyArray(&s.SNICertKeys), "tls-sni-cert-key", ""+ "A pair of x509 certificate and private key file paths, optionally suffixed with a list of "+ @@ -156,11 +159,6 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) { "The limit that the server gives to clients for "+ "the maximum number of streams in an HTTP/2 connection. "+ "Zero means to use golang's default.") - - // TODO remove this flag in 1.11. The flag had no effect before this will prevent scripts from immediately failing on upgrade. - fs.String("tls-ca-file", "", "This flag has no effect.") - fs.MarkDeprecated("tls-ca-file", "This flag has no effect.") - } // ApplyTo fills up serving information in the server configuration. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go index 01a443a33..32659dc5b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go @@ -42,7 +42,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/version" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/server" . "k8s.io/apiserver/pkg/server" utilflag "k8s.io/apiserver/pkg/util/flag" @@ -55,7 +54,6 @@ func setUp(t *testing.T) Config { codecs := serializer.NewCodecFactory(scheme) config := NewConfig(codecs) - config.RequestContextMapper = genericapirequest.NewRequestContextMapper() return *config } @@ -497,7 +495,7 @@ NextTest: return } - s, err := config.Complete(nil).New("test", server.EmptyDelegate) + s, err := config.Complete(nil).New("test", server.NewEmptyDelegate()) if err != nil { t.Errorf("%q - failed creating the server: %v", title, err) return diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/BUILD index 5036ae75b..c28bc6c0b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/BUILD @@ -23,9 +23,7 @@ go_test( deps = [ "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go index 3ac79b74a..cb1c54e3f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go @@ -29,12 +29,12 @@ import ( // GroupVersionRegistry provides access to registered group versions. type GroupVersionRegistry interface { - // IsRegistered returns true if given group is registered. - IsRegistered(group string) bool - // IsRegisteredVersion returns true if given version is registered. - IsRegisteredVersion(v schema.GroupVersion) bool - // RegisteredGroupVersions returns all registered group versions. - RegisteredGroupVersions() []schema.GroupVersion + // IsGroupRegistered returns true if given group is registered. + IsGroupRegistered(group string) bool + // IsVersionRegistered returns true if given version is registered. + IsVersionRegistered(v schema.GroupVersion) bool + // PrioritizedVersionsAllGroups returns all registered group versions. + PrioritizedVersionsAllGroups() []schema.GroupVersion } // MergeResourceEncodingConfigs merges the given defaultResourceConfig with specific GroupVersionResource overrides. @@ -78,9 +78,9 @@ func MergeAPIResourceConfigs( if ok { if allAPIFlagValue == "false" { // Disable all group versions. - resourceConfig.DisableVersions(registry.RegisteredGroupVersions()...) + resourceConfig.DisableAll() } else if allAPIFlagValue == "true" { - resourceConfig.EnableVersions(registry.RegisteredGroupVersions()...) + resourceConfig.EnableAll() } } @@ -104,12 +104,12 @@ func MergeAPIResourceConfigs( } // Exclude group not registered into the registry. - if !registry.IsRegistered(groupVersion.Group) { + if !registry.IsGroupRegistered(groupVersion.Group) { continue } // Verify that the groupVersion is registered into registry. - if !registry.IsRegisteredVersion(groupVersion) { + if !registry.IsVersionRegistered(groupVersion) { return nil, fmt.Errorf("group version %s that has not been registered", groupVersion.String()) } enabled, err := getRuntimeConfigValue(overrides, key, false) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go index 801d78414..dd5d04c69 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go @@ -22,14 +22,12 @@ import ( apiv1 "k8s.io/api/core/v1" extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1" - "k8s.io/apimachinery/pkg/apimachinery" - "k8s.io/apimachinery/pkg/apimachinery/registered" - "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime" serverstore "k8s.io/apiserver/pkg/server/storage" ) func TestParseRuntimeConfig(t *testing.T) { - registry := newFakeRegistry() + scheme := newFakeScheme() apiv1GroupVersion := apiv1.SchemeGroupVersion testCases := []struct { runtimeConfig map[string]string @@ -116,7 +114,7 @@ func TestParseRuntimeConfig(t *testing.T) { }, expectedAPIConfig: func() *serverstore.ResourceConfig { config := newFakeAPIResourceConfigSource() - config.EnableVersions(registry.RegisteredGroupVersions()...) + config.EnableVersions(scheme.PrioritizedVersionsAllGroups()...) return config }, err: false, @@ -139,7 +137,8 @@ func TestParseRuntimeConfig(t *testing.T) { }, } for index, test := range testCases { - actualDisablers, err := MergeAPIResourceConfigs(test.defaultResourceConfig(), test.runtimeConfig, registry) + t.Log(scheme.PrioritizedVersionsAllGroups()) + actualDisablers, err := MergeAPIResourceConfigs(test.defaultResourceConfig(), test.runtimeConfig, scheme) if err == nil && test.err { t.Fatalf("expected error for test case: %v", index) } else if err != nil && !test.err { @@ -164,15 +163,13 @@ func newFakeAPIResourceConfigSource() *serverstore.ResourceConfig { return ret } -func newFakeRegistry() *registered.APIRegistrationManager { - registry := registered.NewOrDie("") +func newFakeScheme() *runtime.Scheme { + ret := runtime.NewScheme() + apiv1.AddToScheme(ret) + extensionsapiv1beta1.AddToScheme(ret) - registry.RegisterGroup(apimachinery.GroupMeta{ - GroupVersion: apiv1.SchemeGroupVersion, - }) - registry.RegisterGroup(apimachinery.GroupMeta{ - GroupVersion: extensionsapiv1beta1.SchemeGroupVersion, - }) - registry.RegisterVersions([]schema.GroupVersion{apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion}) - return registry + ret.SetVersionPriority(apiv1.SchemeGroupVersion) + ret.SetVersionPriority(extensionsapiv1beta1.SchemeGroupVersion) + + return ret } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/BUILD index e7ffd916b..9dd383956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/BUILD @@ -9,6 +9,7 @@ go_library( name = "go_default_library", srcs = [ "doc.go", + "flags.go", "index.go", "metrics.go", "openapi.go", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/data/swagger/datafile.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/data/swagger/datafile.go index 4accb69ce..619809ea0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/data/swagger/datafile.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/data/swagger/datafile.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 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. @@ -124,7 +124,7 @@ func third_partySwaggerUiLicense() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/LICENSE", size: 596, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/LICENSE", size: 596, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -165,7 +165,7 @@ func third_partySwaggerUiReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/README.md", size: 1032, mode: os.FileMode(436), modTime: time.Unix(1463153383, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/README.md", size: 1032, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -307,7 +307,7 @@ func third_partySwaggerUiCssResetCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/css/reset.css", size: 1066, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/css/reset.css", size: 1066, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1580,7 +1580,7 @@ func third_partySwaggerUiCssScreenCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/css/screen.css", size: 43042, mode: os.FileMode(436), modTime: time.Unix(1441894315, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/css/screen.css", size: 43042, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1623,7 +1623,7 @@ func third_partySwaggerUiCssTypographyCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/css/typography.css", size: 1474, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/css/typography.css", size: 1474, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1640,7 +1640,7 @@ func third_partySwaggerUiFontsDroidSansV6Latin700Eot() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.eot", size: 22924, mode: os.FileMode(436), modTime: time.Unix(1441894315, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.eot", size: 22924, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2068,7 +2068,7 @@ func third_partySwaggerUiFontsDroidSansV6Latin700Svg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.svg", size: 73575, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.svg", size: 73575, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2085,7 +2085,7 @@ func third_partySwaggerUiFontsDroidSansV6Latin700Ttf() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.ttf", size: 40516, mode: os.FileMode(436), modTime: time.Unix(1441894315, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.ttf", size: 40516, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2102,7 +2102,7 @@ func third_partySwaggerUiFontsDroidSansV6Latin700Woff() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.woff", size: 25992, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.woff", size: 25992, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2119,7 +2119,7 @@ func third_partySwaggerUiFontsDroidSansV6Latin700Woff2() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.woff2", size: 11480, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-700.woff2", size: 11480, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2136,7 +2136,7 @@ func third_partySwaggerUiFontsDroidSansV6LatinRegularEot() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.eot", size: 22008, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.eot", size: 22008, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2556,7 +2556,7 @@ func third_partySwaggerUiFontsDroidSansV6LatinRegularSvg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.svg", size: 72148, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.svg", size: 72148, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2573,7 +2573,7 @@ func third_partySwaggerUiFontsDroidSansV6LatinRegularTtf() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.ttf", size: 39072, mode: os.FileMode(436), modTime: time.Unix(1441894315, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.ttf", size: 39072, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2590,7 +2590,7 @@ func third_partySwaggerUiFontsDroidSansV6LatinRegularWoff() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.woff", size: 24868, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.woff", size: 24868, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2607,7 +2607,7 @@ func third_partySwaggerUiFontsDroidSansV6LatinRegularWoff2() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.woff2", size: 11304, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/fonts/droid-sans-v6-latin-regular.woff2", size: 11304, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2624,7 +2624,7 @@ func third_partySwaggerUiImagesExplorer_iconsPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/images/explorer_icons.png", size: 5763, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/images/explorer_icons.png", size: 5763, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2641,7 +2641,7 @@ func third_partySwaggerUiImagesLogo_smallPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/images/logo_small.png", size: 770, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/images/logo_small.png", size: 770, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2658,7 +2658,7 @@ func third_partySwaggerUiImagesPet_store_apiPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/images/pet_store_api.png", size: 824, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/images/pet_store_api.png", size: 824, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2675,7 +2675,7 @@ func third_partySwaggerUiImagesThrobberGif() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/images/throbber.gif", size: 9257, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/images/throbber.gif", size: 9257, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2692,7 +2692,7 @@ func third_partySwaggerUiImagesWordnik_apiPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/images/wordnik_api.png", size: 980, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/images/wordnik_api.png", size: 980, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2802,7 +2802,7 @@ func third_partySwaggerUiIndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/index.html", size: 3561, mode: os.FileMode(436), modTime: time.Unix(1468871087, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/index.html", size: 3561, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2833,7 +2833,7 @@ func third_partySwaggerUiLibBackboneMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/backbone-min.js", size: 20390, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/backbone-min.js", size: 20390, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -5128,7 +5128,7 @@ func third_partySwaggerUiLibHandlebars100Js() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/handlebars-1.0.0.js", size: 72766, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/handlebars-1.0.0.js", size: 72766, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -5172,7 +5172,7 @@ func third_partySwaggerUiLibHandlebars200Js() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/handlebars-2.0.0.js", size: 48517, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/handlebars-2.0.0.js", size: 48517, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -5189,7 +5189,7 @@ func third_partySwaggerUiLibHighlight73PackJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/highlight.7.3.pack.js", size: 7499, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/highlight.7.3.pack.js", size: 7499, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -5207,7 +5207,7 @@ func third_partySwaggerUiLibJquery180MinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/jquery-1.8.0.min.js", size: 92556, mode: os.FileMode(436), modTime: time.Unix(1441894315, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/jquery-1.8.0.min.js", size: 92556, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -5241,7 +5241,7 @@ func third_partySwaggerUiLibJqueryBaBbqMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/jquery.ba-bbq.min.js", size: 4119, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/jquery.ba-bbq.min.js", size: 4119, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -5259,7 +5259,7 @@ func third_partySwaggerUiLibJquerySlidetoMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/jquery.slideto.min.js", size: 369, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/jquery.slideto.min.js", size: 369, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -5283,7 +5283,7 @@ func third_partySwaggerUiLibJqueryWiggleMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/jquery.wiggle.min.js", size: 762, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/jquery.wiggle.min.js", size: 762, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -6498,7 +6498,7 @@ function marked(src, opt, callback) { } catch (e) { e.message += '\nPlease report this to https://github.com/chjj/marked.'; if ((opt || marked.defaults).silent) { - return '

    An error occurred:

    '
    +      return '

    An error occured:

    '
             + escape(e.message + '', true)
             + '
    '; } @@ -6571,7 +6571,7 @@ func third_partySwaggerUiLibMarkedJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/marked.js", size: 28156, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/marked.js", size: 28156, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -6780,7 +6780,7 @@ func third_partySwaggerUiLibShredContentJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/shred/content.js", size: 6862, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/shred/content.js", size: 6862, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -7152,7 +7152,7 @@ var Shred = function(options) { this.logCurl = options.logCurl || false; }; -// Most of the real work is done in the request and response classes. +// Most of the real work is done in the request and reponse classes. Shred.Request = require("./shred/request"); Shred.Response = require("./shred/response"); @@ -8351,7 +8351,7 @@ Changelog: a regress. I appologize for that. 2010.05.09 - 0.5: - - bug fix: 0 is now preceded with a + sign + - bug fix: 0 is now preceeded with a + sign - bug fix: the sign was not at the right position on padded results (Kamal Abdali) - switched from GPL to BSD license @@ -9561,7 +9561,7 @@ func third_partySwaggerUiLibShredBundleJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/shred.bundle.js", size: 88050, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/shred.bundle.js", size: 88050, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -12509,7 +12509,7 @@ func third_partySwaggerUiLibSwaggerClientJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/swagger-client.js", size: 86354, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/swagger-client.js", size: 86354, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -12800,7 +12800,7 @@ func third_partySwaggerUiLibSwaggerOauthJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/swagger-oauth.js", size: 8580, mode: os.FileMode(436), modTime: time.Unix(1441894315, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/swagger-oauth.js", size: 8580, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -14512,7 +14512,7 @@ func third_partySwaggerUiLibSwaggerJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/swagger.js", size: 53321, mode: os.FileMode(436), modTime: time.Unix(1421093375, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/swagger.js", size: 53321, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -14534,7 +14534,7 @@ func third_partySwaggerUiLibUnderscoreMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/lib/underscore-min.js", size: 15626, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/lib/underscore-min.js", size: 15626, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -14570,7 +14570,7 @@ func third_partySwaggerUiO2cHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/o2c.html", size: 449, mode: os.FileMode(436), modTime: time.Unix(1425500581, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/o2c.html", size: 449, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -16827,7 +16827,7 @@ func third_partySwaggerUiSwaggerUiJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/swagger-ui.js", size: 110246, mode: os.FileMode(436), modTime: time.Unix(1441894315, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/swagger-ui.js", size: 110246, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -16845,7 +16845,7 @@ func third_partySwaggerUiSwaggerUiMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "third_party/swagger-ui/swagger-ui.min.js", size: 63466, mode: os.FileMode(436), modTime: time.Unix(1441894315, 0)} + info := bindataFileInfo{name: "third_party/swagger-ui/swagger-ui.min.js", size: 63466, mode: os.FileMode(420), modTime: time.Unix(1503320355, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/flags.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/flags.go new file mode 100644 index 000000000..d40f11499 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/flags.go @@ -0,0 +1,126 @@ +/* +Copyright 2018 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 routes + +import ( + "fmt" + "html/template" + "io/ioutil" + "net/http" + "path" + "sync" + + "github.com/golang/glog" + + "k8s.io/apiserver/pkg/server/mux" +) + +var ( + lock = &sync.RWMutex{} + registeredFlags = map[string]debugFlag{} +) + +// DebugFlags adds handlers for flags under /debug/flags. +type DebugFlags struct { +} + +// Install registers the APIServer's flags handler. +func (f DebugFlags) Install(c *mux.PathRecorderMux, flag string, handler func(http.ResponseWriter, *http.Request)) { + c.UnlistedHandle("/debug/flags", http.HandlerFunc(f.Index)) + c.UnlistedHandlePrefix("/debug/flags/", http.HandlerFunc(f.Index)) + + url := path.Join("/debug/flags", flag) + c.UnlistedHandleFunc(url, handler) + + f.addFlag(flag) +} + +// Index responds with the `/debug/flags` request. +// For example, "/debug/flags/v" serves the "--v" flag. +// Index responds to a request for "/debug/flags/" with an HTML page +// listing the available flags. +func (f DebugFlags) Index(w http.ResponseWriter, r *http.Request) { + lock.RLock() + defer lock.RUnlock() + if err := indexTmpl.Execute(w, registeredFlags); err != nil { + glog.Error(err) + } +} + +var indexTmpl = template.Must(template.New("index").Parse(` + +/debug/flags/ + + +/debug/flags/
    +
    +flags:
    + +{{range .}} +{{.Flag}}
    +{{end}} +
    +
    +full flags configurable
    + + +`)) + +type debugFlag struct { + Flag string +} + +func (f DebugFlags) addFlag(flag string) { + lock.Lock() + defer lock.Unlock() + registeredFlags[flag] = debugFlag{flag} +} + +// StringFlagSetterFunc is a func used for setting string type flag. +type StringFlagSetterFunc func(string) (string, error) + +// StringFlagPutHandler wraps an http Handler to set string type flag. +func StringFlagPutHandler(setter StringFlagSetterFunc) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + switch { + case req.Method == "PUT": + body, err := ioutil.ReadAll(req.Body) + if err != nil { + writePlainText(http.StatusBadRequest, "error reading request body: "+err.Error(), w) + return + } + defer req.Body.Close() + response, err := setter(string(body)) + if err != nil { + writePlainText(http.StatusBadRequest, err.Error(), w) + return + } + writePlainText(http.StatusOK, response, w) + return + default: + writePlainText(http.StatusNotAcceptable, "unsupported http method", w) + return + } + }) +} + +// writePlainText renders a simple string response. +func writePlainText(statusCode int, text string, w http.ResponseWriter) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(statusCode) + fmt.Fprintln(w, text) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/metrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/metrics.go index 6d4e56edc..ee158c204 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/metrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/routes/metrics.go @@ -32,6 +32,7 @@ type DefaultMetrics struct{} // Install adds the DefaultMetrics handler func (m DefaultMetrics) Install(c *mux.PathRecorderMux) { + register() c.Handle("/metrics", prometheus.Handler()) } @@ -41,6 +42,7 @@ type MetricsWithReset struct{} // Install adds the MetricsWithReset handler func (m MetricsWithReset) Install(c *mux.PathRecorderMux) { + register() defaultMetricsHandler := prometheus.Handler().ServeHTTP c.HandleFunc("/metrics", func(w http.ResponseWriter, req *http.Request) { if req.Method == "DELETE" { @@ -52,3 +54,9 @@ func (m MetricsWithReset) Install(c *mux.PathRecorderMux) { defaultMetricsHandler(w, req) }) } + +// register apiserver and etcd metrics +func register() { + apimetrics.Register() + etcdmetrics.Register() +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/BUILD index d79f70527..1fe92504a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/BUILD @@ -14,8 +14,6 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", @@ -39,7 +37,6 @@ go_library( importpath = "k8s.io/apiserver/pkg/server/storage", deps = [ "//vendor/github.com/golang/glog:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered: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/recognizer:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go index 0a4470605..d16be4279 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go @@ -36,6 +36,18 @@ func NewResourceConfig() *ResourceConfig { return &ResourceConfig{GroupVersionConfigs: map[schema.GroupVersion]bool{}} } +func (o *ResourceConfig) DisableAll() { + for k := range o.GroupVersionConfigs { + o.GroupVersionConfigs[k] = false + } +} + +func (o *ResourceConfig) EnableAll() { + for k := range o.GroupVersionConfigs { + o.GroupVersionConfigs[k] = true + } +} + // DisableVersions disables the versions entirely. func (o *ResourceConfig) DisableVersions(versions ...schema.GroupVersion) { for _, version := range versions { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/resource_encoding_config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/resource_encoding_config.go index 78cb865b7..eff1fe8a4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/resource_encoding_config.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/resource_encoding_config.go @@ -17,7 +17,8 @@ limitations under the License. package storage import ( - "k8s.io/apimachinery/pkg/apimachinery/registered" + "fmt" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -33,8 +34,8 @@ type ResourceEncodingConfig interface { } type DefaultResourceEncodingConfig struct { - groups map[string]*GroupResourceEncodingConfig - registry *registered.APIRegistrationManager + groups map[string]*GroupResourceEncodingConfig + scheme *runtime.Scheme } type GroupResourceEncodingConfig struct { @@ -47,8 +48,8 @@ type GroupResourceEncodingConfig struct { var _ ResourceEncodingConfig = &DefaultResourceEncodingConfig{} -func NewDefaultResourceEncodingConfig(registry *registered.APIRegistrationManager) *DefaultResourceEncodingConfig { - return &DefaultResourceEncodingConfig{groups: map[string]*GroupResourceEncodingConfig{}, registry: registry} +func NewDefaultResourceEncodingConfig(scheme *runtime.Scheme) *DefaultResourceEncodingConfig { + return &DefaultResourceEncodingConfig{groups: map[string]*GroupResourceEncodingConfig{}, scheme: scheme} } func newGroupResourceEncodingConfig(defaultEncoding, defaultInternalVersion schema.GroupVersion) *GroupResourceEncodingConfig { @@ -80,16 +81,15 @@ func (o *DefaultResourceEncodingConfig) SetResourceEncoding(resourceBeingStored } func (o *DefaultResourceEncodingConfig) StorageEncodingFor(resource schema.GroupResource) (schema.GroupVersion, error) { - groupMeta, err := o.registry.Group(resource.Group) - if err != nil { - return schema.GroupVersion{}, err + if !o.scheme.IsGroupRegistered(resource.Group) { + return schema.GroupVersion{}, fmt.Errorf("group %q is not registered in scheme", resource.Group) } groupEncoding, groupExists := o.groups[resource.Group] if !groupExists { // return the most preferred external version for the group - return groupMeta.GroupVersion, nil + return o.scheme.PrioritizedVersionsForGroup(resource.Group)[0], nil } resourceOverride, resourceExists := groupEncoding.ExternalResourceEncodings[resource.Resource] @@ -101,8 +101,8 @@ func (o *DefaultResourceEncodingConfig) StorageEncodingFor(resource schema.Group } func (o *DefaultResourceEncodingConfig) InMemoryEncodingFor(resource schema.GroupResource) (schema.GroupVersion, error) { - if _, err := o.registry.Group(resource.Group); err != nil { - return schema.GroupVersion{}, err + if !o.scheme.IsGroupRegistered(resource.Group) { + return schema.GroupVersion{}, fmt.Errorf("group %q is not registered in scheme", resource.Group) } groupEncoding, groupExists := o.groups[resource.Group] diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory_test.go index abccce32f..197ff6b79 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory_test.go @@ -17,12 +17,9 @@ limitations under the License. package storage import ( - "os" "reflect" "testing" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -36,8 +33,6 @@ import ( var ( v1GroupVersion = schema.GroupVersion{Group: "", Version: "v1"} - registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) - announce = make(announced.APIGroupFactoryRegistry) scheme = runtime.NewScheme() codecs = serializer.NewCodecFactory(scheme) parameterCodec = runtime.NewParameterCodec(scheme) @@ -53,7 +48,7 @@ func init() { &metav1.APIResourceList{}, ) - exampleinstall.Install(announce, registry, scheme) + exampleinstall.Install(scheme) } type fakeNegotiater struct { @@ -94,7 +89,7 @@ func (n *fakeNegotiater) DecoderToVersion(serializer runtime.Decoder, gv runtime func TestConfigurableStorageFactory(t *testing.T) { ns := &fakeNegotiater{types: []string{"test/test"}} - f := NewDefaultStorageFactory(storagebackend.Config{}, "test/test", ns, NewDefaultResourceEncodingConfig(registry), NewResourceConfig(), nil) + f := NewDefaultStorageFactory(storagebackend.Config{}, "test/test", ns, NewDefaultResourceEncodingConfig(scheme), NewResourceConfig(), nil) f.AddCohabitatingResources(example.Resource("test"), schema.GroupResource{Resource: "test2", Group: "2"}) called := false testEncoderChain := func(e runtime.Encoder) runtime.Encoder { @@ -118,9 +113,7 @@ func TestConfigurableStorageFactory(t *testing.T) { } func TestUpdateEtcdOverrides(t *testing.T) { - registry := registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) - announced := make(announced.APIGroupFactoryRegistry) - exampleinstall.Install(announced, registry, scheme) + exampleinstall.Install(scheme) testCases := []struct { resource schema.GroupResource @@ -146,7 +139,7 @@ func TestUpdateEtcdOverrides(t *testing.T) { Prefix: "/registry", ServerList: defaultEtcdLocation, } - storageFactory := NewDefaultStorageFactory(defaultConfig, "", codecs, NewDefaultResourceEncodingConfig(registry), NewResourceConfig(), nil) + storageFactory := NewDefaultStorageFactory(defaultConfig, "", codecs, NewDefaultResourceEncodingConfig(scheme), NewResourceConfig(), nil) storageFactory.SetEtcdLocation(test.resource, test.servers) var err error diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/BUILD index 712544e2d..1218c4644 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/BUILD @@ -49,7 +49,6 @@ go_library( importpath = "k8s.io/apiserver/pkg/storage", deps = [ "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/validation/path:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/cacher.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/cacher.go index 9ffbbc5e9..ab4ab04f3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/cacher.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/cacher.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "context" "fmt" "net/http" "reflect" @@ -24,7 +25,6 @@ import ( "time" "github.com/golang/glog" - "golang.org/x/net/context" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/BUILD index 0269e4e1d..ccdf63e5c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/BUILD @@ -16,7 +16,6 @@ go_test( embed = [":go_default_library"], deps = [ "//vendor/github.com/coreos/etcd/client:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -50,7 +49,6 @@ go_library( deps = [ "//vendor/github.com/coreos/etcd/client:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_helper.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_helper.go index 7195ea8dd..2fe2bbada 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_helper.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_helper.go @@ -17,6 +17,7 @@ limitations under the License. package etcd import ( + "context" "errors" "fmt" "path" @@ -25,7 +26,6 @@ import ( etcd "github.com/coreos/etcd/client" "github.com/golang/glog" - "golang.org/x/net/context" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/conversion" @@ -101,10 +101,6 @@ type etcdHelper struct { cache utilcache.Cache } -func init() { - metrics.Register() -} - // Implements storage.Interface. func (h *etcdHelper) Versioner() storage.Versioner { return h.versioner diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_helper_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_helper_test.go index 8f217009b..277ad9ac7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_helper_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_helper_test.go @@ -17,6 +17,7 @@ limitations under the License. package etcd import ( + "context" "fmt" "path" "reflect" @@ -26,7 +27,6 @@ import ( "time" etcd "github.com/coreos/etcd/client" - "golang.org/x/net/context" apitesting "k8s.io/apimachinery/pkg/api/testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/conversion" @@ -99,14 +99,6 @@ func newEtcdHelper(client etcd.Client, codec runtime.Codec, prefix string) etcdH return *NewEtcdStorage(client, codec, prefix, false, etcdtest.DeserializationCacheSize, prefixTransformer{prefix: "test!"}).(*etcdHelper) } -// Returns an encoded version of example.Pod with the given name. -func getEncodedPod(name string, codec runtime.Codec) string { - pod, _ := runtime.Encode(codec, &examplev1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: name}, - }) - return string(pod) -} - func createObj(t *testing.T, helper etcdHelper, name string, obj, out runtime.Object, ttl uint64) error { err := helper.Create(context.TODO(), name, obj, out, ttl) if err != nil { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher.go index 7c300b430..21ffc42e5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher.go @@ -17,6 +17,7 @@ limitations under the License. package etcd import ( + "context" "fmt" "net/http" "reflect" @@ -32,7 +33,6 @@ import ( etcd "github.com/coreos/etcd/client" "github.com/golang/glog" - "golang.org/x/net/context" ) // Etcd watch event actions diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher_test.go index 4c4d038dc..b2aff1c27 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher_test.go @@ -17,6 +17,7 @@ limitations under the License. package etcd import ( + "context" rt "runtime" "testing" @@ -35,7 +36,6 @@ import ( etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" etcd "github.com/coreos/etcd/client" - "golang.org/x/net/context" ) var versioner = APIObjectVersioner{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/BUILD index 5d495404c..3da57302b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/BUILD @@ -20,7 +20,6 @@ go_library( "//vendor/github.com/coreos/etcd/pkg/transport:go_default_library", "//vendor/github.com/coreos/etcd/pkg/types:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/etcd/etcdtest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/etcd/testing/testingcert:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/utils.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/utils.go index 665662aaf..deafcfce9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/utils.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/utils.go @@ -32,6 +32,8 @@ import ( "k8s.io/apiserver/pkg/storage/etcd/testing/testingcert" "k8s.io/apiserver/pkg/storage/storagebackend" + "context" + etcd "github.com/coreos/etcd/client" "github.com/coreos/etcd/clientv3" "github.com/coreos/etcd/etcdserver" @@ -42,7 +44,6 @@ import ( "github.com/coreos/etcd/pkg/transport" "github.com/coreos/etcd/pkg/types" "github.com/golang/glog" - "golang.org/x/net/context" ) // EtcdTestServer encapsulates the datastructures needed to start local instance for testing diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/BUILD index 29f789950..2e95c4ace 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/BUILD @@ -10,6 +10,7 @@ go_test( name = "go_default_test", srcs = [ "compact_test.go", + "lease_manager_test.go", "store_test.go", "watcher_test.go", ], @@ -19,7 +20,6 @@ go_test( "//vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes:go_default_library", "//vendor/github.com/coreos/etcd/integration:go_default_library", "//vendor/github.com/coreos/pkg/capnslog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -45,6 +45,7 @@ go_library( "compact.go", "errors.go", "event.go", + "lease_manager.go", "store.go", "watcher.go", ], @@ -54,7 +55,6 @@ go_library( "//vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes:go_default_library", "//vendor/github.com/coreos/etcd/mvcc/mvccpb:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/compact.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/compact.go index 2bceacc8e..bdcd5bcb6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/compact.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/compact.go @@ -17,13 +17,13 @@ limitations under the License. package etcd3 import ( + "context" "strconv" "sync" "time" "github.com/coreos/etcd/clientv3" "github.com/golang/glog" - "golang.org/x/net/context" ) const ( diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/compact_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/compact_test.go index 021b8c451..72f21437d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/compact_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/compact_test.go @@ -17,12 +17,12 @@ limitations under the License. package etcd3 import ( + "context" "testing" "github.com/coreos/etcd/clientv3" etcdrpc "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" "github.com/coreos/etcd/integration" - "golang.org/x/net/context" ) func TestCompact(t *testing.T) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/lease_manager.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/lease_manager.go new file mode 100644 index 000000000..dc06ac520 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/lease_manager.go @@ -0,0 +1,102 @@ +/* +Copyright 2018 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 etcd3 + +import ( + "context" + "sync" + "time" + + "github.com/coreos/etcd/clientv3" +) + +// leaseManager is used to manage leases requested from etcd. If a new write +// needs a lease that has similar expiration time to the previous one, the old +// lease will be reused to reduce the overhead of etcd, since lease operations +// are expensive. In the implementation, we only store one previous lease, +// since all the events have the same ttl. +type leaseManager struct { + client *clientv3.Client // etcd client used to grant leases + leaseMu sync.Mutex + prevLeaseID clientv3.LeaseID + prevLeaseExpirationTime time.Time + // The period of time in seconds and percent of TTL that each lease is + // reused. The minimum of them is used to avoid unreasonably large + // numbers. We use var instead of const for testing purposes. + leaseReuseDurationSeconds int64 + leaseReuseDurationPercent float64 +} + +// newDefaultLeaseManager creates a new lease manager using default setting. +func newDefaultLeaseManager(client *clientv3.Client) *leaseManager { + return newLeaseManager(client, 60, 0.05) +} + +// newLeaseManager creates a new lease manager with the number of buffered +// leases, lease reuse duration in seconds and percentage. The percentage +// value x means x*100%. +func newLeaseManager(client *clientv3.Client, leaseReuseDurationSeconds int64, leaseReuseDurationPercent float64) *leaseManager { + return &leaseManager{ + client: client, + leaseReuseDurationSeconds: leaseReuseDurationSeconds, + leaseReuseDurationPercent: leaseReuseDurationPercent, + } +} + +// setLeaseReuseDurationSeconds is used for testing purpose. It is used to +// reduce the extra lease duration to avoid unnecessary timeout in testing. +func (l *leaseManager) setLeaseReuseDurationSeconds(duration int64) { + l.leaseMu.Lock() + defer l.leaseMu.Unlock() + l.leaseReuseDurationSeconds = duration +} + +// GetLease returns a lease based on requested ttl: if the cached previous +// lease can be reused, reuse it; otherwise request a new one from etcd. +func (l *leaseManager) GetLease(ctx context.Context, ttl int64) (clientv3.LeaseID, error) { + now := time.Now() + l.leaseMu.Lock() + defer l.leaseMu.Unlock() + // check if previous lease can be reused + reuseDurationSeconds := l.getReuseDurationSecondsLocked(ttl) + valid := now.Add(time.Duration(ttl) * time.Second).Before(l.prevLeaseExpirationTime) + sufficient := now.Add(time.Duration(ttl+reuseDurationSeconds) * time.Second).After(l.prevLeaseExpirationTime) + if valid && sufficient { + return l.prevLeaseID, nil + } + // request a lease with a little extra ttl from etcd + ttl += reuseDurationSeconds + lcr, err := l.client.Lease.Grant(ctx, ttl) + if err != nil { + return clientv3.LeaseID(0), err + } + // cache the new lease id + l.prevLeaseID = lcr.ID + l.prevLeaseExpirationTime = now.Add(time.Duration(ttl) * time.Second) + return lcr.ID, nil +} + +// getReuseDurationSecondsLocked returns the reusable duration in seconds +// based on the configuration. Lock has to be acquired before calling this +// function. +func (l *leaseManager) getReuseDurationSecondsLocked(ttl int64) int64 { + reuseDurationSeconds := int64(l.leaseReuseDurationPercent * float64(ttl)) + if reuseDurationSeconds > l.leaseReuseDurationSeconds { + reuseDurationSeconds = l.leaseReuseDurationSeconds + } + return reuseDurationSeconds +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/lease_manager_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/lease_manager_test.go new file mode 100644 index 000000000..e63a8e65e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/lease_manager_test.go @@ -0,0 +1,44 @@ +/* +Copyright 2018 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 etcd3 + +import ( + "testing" +) + +func TestGetReuseDurationSeconds(t *testing.T) { + testCases := []struct { + ttl int64 + duration int64 + }{ + { + ttl: 3600, + duration: 60, + }, + { + ttl: 1000, + duration: 50, + }, + } + lm := newDefaultLeaseManager(nil) + for i := 0; i < len(testCases); i++ { + dur := lm.getReuseDurationSecondsLocked(testCases[i].ttl) + if dur != testCases[i].duration { + t.Errorf("Duration error: ttl %v, expected duration %v, get %v\n", testCases[i].ttl, testCases[i].duration, dur) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/preflight/checks.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/preflight/checks.go index 899a6fa89..9c12c2090 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/preflight/checks.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/preflight/checks.go @@ -18,6 +18,7 @@ package preflight import ( "fmt" + "math/rand" "net" "net/url" "time" @@ -25,12 +26,6 @@ import ( const connectionTimeout = 1 * time.Second -type connection interface { - serverReachable(address string) bool - parseServerList(serverList []string) error - CheckEtcdServers() (bool, error) -} - // EtcdConnection holds the Etcd server list type EtcdConnection struct { ServerList []string @@ -59,9 +54,11 @@ func parseServerURI(serverURI string) (*url.URL, error) { // CheckEtcdServers will attempt to reach all etcd servers once. If any // can be reached, return true. func (con EtcdConnection) CheckEtcdServers() (done bool, err error) { - // Attempt to reach every Etcd server in order - for _, serverURI := range con.ServerList { - host, err := parseServerURI(serverURI) + // Attempt to reach every Etcd server randomly. + serverNumber := len(con.ServerList) + serverPerms := rand.Perm(serverNumber) + for _, index := range serverPerms { + host, err := parseServerURI(con.ServerList[index]) if err != nil { return false, err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go index 3fbee67bb..1513af8e7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go @@ -18,6 +18,7 @@ package etcd3 import ( "bytes" + "context" "encoding/base64" "encoding/json" "errors" @@ -29,7 +30,6 @@ import ( "github.com/coreos/etcd/clientv3" "github.com/golang/glog" - "golang.org/x/net/context" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -70,6 +70,7 @@ type store struct { pathPrefix string watcher *watcher pagingEnabled bool + leaseManager *leaseManager } type elemForDecode struct { @@ -107,8 +108,9 @@ func newStore(c *clientv3.Client, quorumRead, pagingEnabled bool, codec runtime. // for compatibility with etcd2 impl. // no-op for default prefix of '/registry'. // keeps compatibility with etcd2 impl for custom prefixes that don't start with '/' - pathPrefix: path.Join("/", prefix), - watcher: newWatcher(c, codec, versioner, transformer), + pathPrefix: path.Join("/", prefix), + watcher: newWatcher(c, codec, versioner, transformer), + leaseManager: newDefaultLeaseManager(c), } if !quorumRead { // In case of non-quorum reads, we can set WithSerializable() @@ -758,13 +760,11 @@ func (s *store) ttlOpts(ctx context.Context, ttl int64) ([]clientv3.OpOption, er if ttl == 0 { return nil, nil } - // TODO: one lease per ttl key is expensive. Based on current use case, we can have a long window to - // put keys within into same lease. We shall benchmark this and optimize the performance. - lcr, err := s.client.Lease.Grant(ctx, ttl) + id, err := s.leaseManager.GetLease(ctx, ttl) if err != nil { return nil, err } - return []clientv3.OpOption{clientv3.WithLease(clientv3.LeaseID(lcr.ID))}, nil + return []clientv3.OpOption{clientv3.WithLease(id)}, nil } // decode decodes value of bytes into object. It will also set the object resource version to rev. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go index 7a893126d..1624a6829 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go @@ -18,6 +18,7 @@ package etcd3 import ( "bytes" + "context" "encoding/base64" "encoding/json" "errors" @@ -30,7 +31,6 @@ import ( "github.com/coreos/etcd/clientv3" "github.com/coreos/etcd/integration" "github.com/coreos/pkg/capnslog" - "golang.org/x/net/context" apierrors "k8s.io/apimachinery/pkg/api/errors" apitesting "k8s.io/apimachinery/pkg/api/testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -1186,6 +1186,10 @@ func testSetup(t *testing.T) (context.Context, *store, *integration.ClusterV3) { cluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) store := newStore(cluster.RandClient(), false, true, codec, "", prefixTransformer{prefix: []byte(defaultTestPrefix)}) ctx := context.Background() + // As 30s is the default timeout for testing in glboal configuration, + // we cannot wait longer than that in a single time: change it to 10 + // for testing purposes. See apimachinery/pkg/util/wait/wait.go + store.leaseManager.setLeaseReuseDurationSeconds(1) return ctx, store, cluster } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go index 38aae2f1f..f09a00024 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go @@ -17,6 +17,7 @@ limitations under the License. package etcd3 import ( + "context" "errors" "fmt" "os" @@ -32,7 +33,6 @@ import ( "github.com/coreos/etcd/clientv3" "github.com/golang/glog" - "golang.org/x/net/context" ) const ( diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher_test.go index 6f01c4bd7..7b552e6ba 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher_test.go @@ -17,6 +17,7 @@ limitations under the License. package etcd3 import ( + "context" "fmt" "reflect" "sync" @@ -25,7 +26,6 @@ import ( "github.com/coreos/etcd/clientv3" "github.com/coreos/etcd/integration" - "golang.org/x/net/context" apitesting "k8s.io/apimachinery/pkg/api/testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/interfaces.go index 6241533be..227ab2b8e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/interfaces.go @@ -17,7 +17,8 @@ limitations under the License. package storage import ( - "golang.org/x/net/context" + "context" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/BUILD index 9b6666c8c..60af39c3c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/BUILD @@ -13,7 +13,6 @@ go_test( deps = [ "//vendor/github.com/coreos/etcd/integration:go_default_library", "//vendor/github.com/coreos/etcd/pkg/transport:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", @@ -37,7 +36,6 @@ go_library( "//vendor/github.com/coreos/etcd/client:go_default_library", "//vendor/github.com/coreos/etcd/clientv3:go_default_library", "//vendor/github.com/coreos/etcd/pkg/transport:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/etcd:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd2.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd2.go index 84b038104..41542ccbe 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd2.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd2.go @@ -69,10 +69,10 @@ func newTransportForETCD2(certFile, keyFile, caFile string) (*http.Transport, er // TODO: Determine if transport needs optimization tr := utilnet.SetTransportDefaults(&http.Transport{ Proxy: http.ProxyFromEnvironment, - Dial: (&net.Dialer{ + DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, - }).Dial, + }).DialContext, TLSHandshakeTimeout: 10 * time.Second, MaxIdleConnsPerHost: 500, TLSClientConfig: cfg, diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go index 90a0a28a1..06b935a8c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go @@ -17,11 +17,11 @@ limitations under the License. package factory import ( + "context" "time" "github.com/coreos/etcd/clientv3" "github.com/coreos/etcd/pkg/transport" - "golang.org/x/net/context" "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/etcd3" @@ -29,14 +29,15 @@ import ( "k8s.io/apiserver/pkg/storage/value" ) -var ( - // The short keepalive timeout and interval have been chosen to aggressively - // detect a failed etcd server without introducing much overhead. - keepaliveTime = 30 * time.Second - keepaliveTimeout = 10 * time.Second - // dialTimeout is the timeout for failing to establish a connection. - dialTimeout = 10 * time.Second -) +// The short keepalive timeout and interval have been chosen to aggressively +// detect a failed etcd server without introducing much overhead. +const keepaliveTime = 30 * time.Second +const keepaliveTimeout = 10 * time.Second + +// dialTimeout is the timeout for failing to establish a connection. +// It is set to 20 seconds as times shorter than that will cause TLS connections to fail +// on heavily loaded arm64 CPUs (issue #64649) +const dialTimeout = 20 * time.Second func newETCD3Storage(c storagebackend.Config) (storage.Interface, DestroyFunc, error) { tlsInfo := transport.TLSInfo{ diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/tls_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/tls_test.go index 6e63c0989..d16e25a51 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/tls_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/tls_test.go @@ -17,6 +17,7 @@ limitations under the License. package factory import ( + "context" "io/ioutil" "os" "path" @@ -25,7 +26,6 @@ import ( "github.com/coreos/etcd/integration" "github.com/coreos/etcd/pkg/transport" - "golang.org/x/net/context" apitesting "k8s.io/apimachinery/pkg/api/testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/BUILD index 37c0195ec..b18a1f031 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/BUILD @@ -15,7 +15,6 @@ go_library( ], importpath = "k8s.io/apiserver/pkg/storage/testing", deps = [ - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/utils.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/utils.go index f6718dd52..e226da6f6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/utils.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/utils.go @@ -17,9 +17,9 @@ limitations under the License. package testing import ( + "context" "path" - "golang.org/x/net/context" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/storage" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/zz_generated.deepcopy.go index 6ee90a90b..41c1941a7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/testing/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/tests/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/tests/BUILD index 856068439..0e68834a2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/tests/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/tests/BUILD @@ -11,7 +11,6 @@ go_test( srcs = ["cacher_test.go"], embed = [":go_default_library"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/tests/cacher_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/tests/cacher_test.go index cf984618e..e6e7eec64 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/tests/cacher_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/tests/cacher_test.go @@ -17,6 +17,7 @@ limitations under the License. package tests import ( + "context" "fmt" "reflect" goruntime "runtime" @@ -32,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" @@ -43,10 +45,6 @@ import ( etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" "k8s.io/apiserver/pkg/storage/etcd3" "k8s.io/apiserver/pkg/storage/value" - - "golang.org/x/net/context" - - "k8s.io/apimachinery/pkg/runtime/serializer" ) var ( diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/BUILD index 2e132c760..541bb5dfe 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/BUILD @@ -14,8 +14,12 @@ go_test( go_library( name = "go_default_library", - srcs = ["transformer.go"], + srcs = [ + "metrics.go", + "transformer.go", + ], importpath = "k8s.io/apiserver/pkg/storage/value", + deps = ["//vendor/github.com/prometheus/client_golang/prometheus:go_default_library"], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go index cb87f27b5..4d4f35676 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go @@ -149,14 +149,41 @@ func TestCBCKeyRotation(t *testing.T) { } } -func BenchmarkGCMRead_16_1024(b *testing.B) { benchmarkGCMRead(b, 16, 1024, false) } -func BenchmarkGCMRead_32_1024(b *testing.B) { benchmarkGCMRead(b, 32, 1024, false) } -func BenchmarkGCMRead_32_16384(b *testing.B) { benchmarkGCMRead(b, 32, 16384, false) } -func BenchmarkGCMRead_32_16384_Stale(b *testing.B) { benchmarkGCMRead(b, 32, 16384, true) } +func BenchmarkGCMRead(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + expectStale bool + }{ + {keyLength: 16, valueLength: 1024, expectStale: false}, + {keyLength: 32, valueLength: 1024, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: true}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength/%vExpectStale", t.keyLength, t.valueLength, t.expectStale) + b.Run(name, func(b *testing.B) { + benchmarkGCMRead(b, t.keyLength, t.valueLength, t.expectStale) + }) + } +} -func BenchmarkGCMWrite_16_1024(b *testing.B) { benchmarkGCMWrite(b, 16, 1024) } -func BenchmarkGCMWrite_32_1024(b *testing.B) { benchmarkGCMWrite(b, 32, 1024) } -func BenchmarkGCMWrite_32_16384(b *testing.B) { benchmarkGCMWrite(b, 32, 16384) } +func BenchmarkGCMWrite(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + }{ + {keyLength: 16, valueLength: 1024}, + {keyLength: 32, valueLength: 1024}, + {keyLength: 32, valueLength: 16384}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength", t.keyLength, t.valueLength) + b.Run(name, func(b *testing.B) { + benchmarkGCMWrite(b, t.keyLength, t.valueLength) + }) + } +} func benchmarkGCMRead(b *testing.B, keyLength int, valueLength int, expectStale bool) { block1, err := aes.NewCipher(bytes.Repeat([]byte("a"), keyLength)) @@ -227,12 +254,39 @@ func benchmarkGCMWrite(b *testing.B, keyLength int, valueLength int) { b.StopTimer() } -func BenchmarkCBCRead_32_1024(b *testing.B) { benchmarkCBCRead(b, 32, 1024, false) } -func BenchmarkCBCRead_32_16384(b *testing.B) { benchmarkCBCRead(b, 32, 16384, false) } -func BenchmarkCBCRead_32_16384_Stale(b *testing.B) { benchmarkCBCRead(b, 32, 16384, true) } +func BenchmarkCBCRead(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + expectStale bool + }{ + {keyLength: 32, valueLength: 1024, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: true}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength/%vExpectStale", t.keyLength, t.valueLength, t.expectStale) + b.Run(name, func(b *testing.B) { + benchmarkCBCRead(b, t.keyLength, t.valueLength, t.expectStale) + }) + } +} -func BenchmarkCBCWrite_32_1024(b *testing.B) { benchmarkCBCWrite(b, 32, 1024) } -func BenchmarkCBCWrite_32_16384(b *testing.B) { benchmarkCBCWrite(b, 32, 16384) } +func BenchmarkCBCWrite(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + }{ + {keyLength: 32, valueLength: 1024}, + {keyLength: 32, valueLength: 16384}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength", t.keyLength, t.valueLength) + b.Run(name, func(b *testing.B) { + benchmarkCBCWrite(b, t.keyLength, t.valueLength) + }) + } +} func benchmarkCBCRead(b *testing.B, keyLength int, valueLength int, expectStale bool) { block1, err := aes.NewCipher(bytes.Repeat([]byte("a"), keyLength)) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD index 32456390b..f9bfef60b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD @@ -16,7 +16,6 @@ go_library( deps = [ "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/hashicorp/golang-lru:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go index 90f1dca42..e5a8989d9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go @@ -24,6 +24,7 @@ import ( "encoding/base64" "encoding/binary" "fmt" + "time" "k8s.io/apiserver/pkg/storage/value" @@ -33,6 +34,10 @@ import ( // defaultCacheSize is the number of decrypted DEKs which would be cached by the transformer. const defaultCacheSize = 1000 +func init() { + value.RegisterMetrics() +} + // Service allows encrypting and decrypting data using an external Key Management Service. type Service interface { // Decrypt a given bytearray to obtain the original data as bytes. @@ -77,7 +82,7 @@ func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Co // length cannot fit in 8 bits (1 byte). Thus, we use 16 bits (2 bytes) to store the length. keyLen := int(binary.BigEndian.Uint16(data[:2])) if keyLen+2 > len(data) { - return nil, false, fmt.Errorf("invalid data encountered by genvelope transformer, length longer than available bytes: %q", data) + return nil, false, fmt.Errorf("invalid data encountered by envelope transformer, length longer than available bytes: %q", data) } encKey := data[2 : keyLen+2] encData := data[2+keyLen:] @@ -85,6 +90,7 @@ func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Co // Look up the decrypted DEK from cache or Envelope. transformer := t.getTransformer(encKey) if transformer == nil { + value.RecordCacheMiss() key, err := t.envelopeService.Decrypt(encKey) if err != nil { return nil, false, fmt.Errorf("error while decrypting key: %q", err) @@ -156,10 +162,12 @@ func (t *envelopeTransformer) getTransformer(encKey []byte) value.Transformer { } // generateKey generates a random key using system randomness. -func generateKey(length int) ([]byte, error) { - key := make([]byte, length) - _, err := rand.Read(key) - if err != nil { +func generateKey(length int) (key []byte, err error) { + defer func(start time.Time) { + value.RecordDataKeyGeneration(start, err) + }(time.Now()) + key = make([]byte, length) + if _, err = rand.Read(key); err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/grpc_service.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/grpc_service.go index ce910f856..a94e26f22 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/grpc_service.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/grpc_service.go @@ -18,6 +18,7 @@ limitations under the License. package envelope import ( + "context" "fmt" "net" "net/url" @@ -27,8 +28,6 @@ import ( "google.golang.org/grpc" - "golang.org/x/net/context" - kmsapi "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1" ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1/service.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1/service.pb.go index 52525fffc..888a03fa1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1/service.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1/service.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go index 1dd42bd4d..b19ccc306 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go @@ -77,12 +77,39 @@ func TestSecretboxKeyRotation(t *testing.T) { } } -func BenchmarkSecretboxRead_32_1024(b *testing.B) { benchmarkSecretboxRead(b, 32, 1024, false) } -func BenchmarkSecretboxRead_32_16384(b *testing.B) { benchmarkSecretboxRead(b, 32, 16384, false) } -func BenchmarkSecretboxRead_32_16384_Stale(b *testing.B) { benchmarkSecretboxRead(b, 32, 16384, true) } +func BenchmarkSecretboxRead(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + expectStale bool + }{ + {keyLength: 32, valueLength: 1024, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: false}, + {keyLength: 32, valueLength: 16384, expectStale: true}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength/%vExpectStale", t.keyLength, t.valueLength, t.expectStale) + b.Run(name, func(b *testing.B) { + benchmarkSecretboxRead(b, t.keyLength, t.valueLength, t.expectStale) + }) + } +} -func BenchmarkSecretboxWrite_32_1024(b *testing.B) { benchmarkSecretboxWrite(b, 32, 1024) } -func BenchmarkSecretboxWrite_32_16384(b *testing.B) { benchmarkSecretboxWrite(b, 32, 16384) } +func BenchmarkSecretboxWrite(b *testing.B) { + tests := []struct { + keyLength int + valueLength int + }{ + {keyLength: 32, valueLength: 1024}, + {keyLength: 32, valueLength: 16384}, + } + for _, t := range tests { + name := fmt.Sprintf("%vKeyLength/%vValueLength", t.keyLength, t.valueLength) + b.Run(name, func(b *testing.B) { + benchmarkSecretboxWrite(b, t.keyLength, t.valueLength) + }) + } +} func benchmarkSecretboxRead(b *testing.B, keyLength int, valueLength int, expectStale bool) { p := value.NewPrefixTransformers(nil, diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/metrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/metrics.go new file mode 100644 index 000000000..1fe316782 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/metrics.go @@ -0,0 +1,124 @@ +/* +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 value + +import ( + "sync" + "time" + + "github.com/prometheus/client_golang/prometheus" +) + +const ( + namespace = "apiserver" + subsystem = "storage" +) + +var ( + transformerLatencies = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "transformation_latencies_microseconds", + Help: "Latencies in microseconds of value transformation operations.", + // In-process transformations (ex. AES CBC) complete on the order of 20 microseconds. However, when + // external KMS is involved latencies may climb into milliseconds. + Buckets: prometheus.ExponentialBuckets(5, 2, 14), + }, + []string{"transformation_type"}, + ) + transformerFailuresTotal = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "transformation_failures_total", + Help: "Total number of failed transformation operations.", + }, + []string{"transformation_type"}, + ) + + envelopeTransformationCacheMissTotal = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "envelope_transformation_cache_misses_total", + Help: "Total number of cache misses while accessing key decryption key(KEK).", + }, + ) + + dataKeyGenerationLatencies = prometheus.NewHistogram( + prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "data_key_generation_latencies_microseconds", + Help: "Latencies in microseconds of data encryption key(DEK) generation operations.", + Buckets: prometheus.ExponentialBuckets(5, 2, 14), + }, + ) + dataKeyGenerationFailuresTotal = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "data_key_generation_failures_total", + Help: "Total number of failed data encryption key(DEK) generation operations.", + }, + ) +) + +var registerMetrics sync.Once + +func RegisterMetrics() { + registerMetrics.Do(func() { + prometheus.MustRegister(transformerLatencies) + prometheus.MustRegister(transformerFailuresTotal) + prometheus.MustRegister(envelopeTransformationCacheMissTotal) + prometheus.MustRegister(dataKeyGenerationLatencies) + prometheus.MustRegister(dataKeyGenerationFailuresTotal) + }) +} + +// RecordTransformation records latencies and count of TransformFromStorage and TransformToStorage operations. +func RecordTransformation(transformationType string, start time.Time, err error) { + if err != nil { + transformerFailuresTotal.WithLabelValues(transformationType).Inc() + return + } + + since := sinceInMicroseconds(start) + transformerLatencies.WithLabelValues(transformationType).Observe(float64(since)) +} + +// RecordCacheMiss records a miss on Key Encryption Key(KEK) - call to KMS was required to decrypt KEK. +func RecordCacheMiss() { + envelopeTransformationCacheMissTotal.Inc() +} + +// RecordDataKeyGeneration records latencies and count of Data Encryption Key generation operations. +func RecordDataKeyGeneration(start time.Time, err error) { + if err != nil { + dataKeyGenerationFailuresTotal.Inc() + return + } + + since := sinceInMicroseconds(start) + dataKeyGenerationLatencies.Observe(float64(since)) +} + +func sinceInMicroseconds(start time.Time) int64 { + elapsedNanoseconds := time.Since(start).Nanoseconds() + return elapsedNanoseconds / int64(time.Microsecond) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go index 04af5d6db..bad6ed58e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go @@ -21,8 +21,13 @@ import ( "bytes" "fmt" "sync" + "time" ) +func init() { + RegisterMetrics() +} + // Context is additional information that a storage transformation may need to verify the data at rest. type Context interface { // AuthenticatedData should return an array of bytes that describes the current value. If the value changes, @@ -80,12 +85,18 @@ func (t *MutableTransformer) Set(transformer Transformer) { } func (t *MutableTransformer) TransformFromStorage(data []byte, context Context) (out []byte, stale bool, err error) { + defer func(start time.Time) { + RecordTransformation("from_storage", start, err) + }(time.Now()) t.lock.RLock() transformer := t.transformer t.lock.RUnlock() return transformer.TransformFromStorage(data, context) } func (t *MutableTransformer) TransformToStorage(data []byte, context Context) (out []byte, err error) { + defer func(start time.Time) { + RecordTransformation("to_storage", start, err) + }(time.Now()) t.lock.RLock() transformer := t.transformer t.lock.RUnlock() diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go index 306877124..6b051a235 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go @@ -88,6 +88,10 @@ type FeatureGate interface { Add(features map[Feature]FeatureSpec) error // KnownFeatures returns a slice of strings describing the FeatureGate's known features. KnownFeatures() []string + // DeepCopy returns a deep copy of the FeatureGate object, such that gates can be + // set on the copy without mutating the original. This is useful for validating + // config against potential feature gate changes before committing those changes. + DeepCopy() FeatureGate } // featureGate implements FeatureGate as well as pflag.Value for flag parsing. @@ -187,7 +191,7 @@ func (f *featureGate) Set(value string) error { f.known.Store(known) f.enabled.Store(enabled) - glog.Infof("feature gates: %v", enabled) + glog.V(1).Infof("feature gates: %v", enabled) return nil } @@ -223,7 +227,7 @@ func (f *featureGate) SetFromMap(m map[string]bool) error { f.known.Store(known) f.enabled.Store(enabled) - glog.Infof("feature gates: %v", f.enabled) + glog.V(1).Infof("feature gates: %v", f.enabled) return nil } @@ -284,6 +288,10 @@ func (f *featureGate) Enabled(key Feature) bool { // AddFlag adds a flag for setting global feature gates to the specified FlagSet. func (f *featureGate) AddFlag(fs *pflag.FlagSet) { f.lock.Lock() + // TODO(mtaufen): Shouldn't we just close it on the first Set/SetFromMap instead? + // Not all components expose a feature gates flag using this AddFlag method, and + // in the future, all components will completely stop exposing a feature gates flag, + // in favor of componentconfig. f.closed = true f.lock.Unlock() @@ -306,3 +314,34 @@ func (f *featureGate) KnownFeatures() []string { sort.Strings(known) return known } + +// DeepCopy returns a deep copy of the FeatureGate object, such that gates can be +// set on the copy without mutating the original. This is useful for validating +// config against potential feature gate changes before committing those changes. +func (f *featureGate) DeepCopy() FeatureGate { + // Copy existing state. + known := map[Feature]FeatureSpec{} + for k, v := range f.known.Load().(map[Feature]FeatureSpec) { + known[k] = v + } + enabled := map[Feature]bool{} + for k, v := range f.enabled.Load().(map[Feature]bool) { + enabled[k] = v + } + + // Store copied state in new atomics. + knownValue := &atomic.Value{} + knownValue.Store(known) + enabledValue := &atomic.Value{} + enabledValue.Store(enabled) + + // Construct a new featureGate around the copied state. + // Note that specialFeatures is treated as immutable by convention, + // and we maintain the value of f.closed across the copy. + return &featureGate{ + special: specialFeatures, + known: knownValue, + enabled: enabledValue, + closed: f.closed, + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate_test.go index 392c875de..f26f3cb88 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate_test.go @@ -189,3 +189,132 @@ func TestFeatureGateFlagDefaults(t *testing.T) { t.Errorf("Expected true") } } + +func TestFeatureGateSetFromMap(t *testing.T) { + // gates for testing + const testAlphaGate Feature = "TestAlpha" + const testBetaGate Feature = "TestBeta" + + tests := []struct { + name string + setmap map[string]bool + expect map[Feature]bool + setmapError string + }{ + { + name: "set TestAlpha and TestBeta true", + setmap: map[string]bool{ + "TestAlpha": true, + "TestBeta": true, + }, + expect: map[Feature]bool{ + testAlphaGate: true, + testBetaGate: true, + }, + }, + { + name: "set TestBeta true", + setmap: map[string]bool{ + "TestBeta": true, + }, + expect: map[Feature]bool{ + testAlphaGate: false, + testBetaGate: true, + }, + }, + { + name: "set TestAlpha false", + setmap: map[string]bool{ + "TestAlpha": false, + }, + expect: map[Feature]bool{ + testAlphaGate: false, + testBetaGate: false, + }, + }, + { + name: "set TestInvaild true", + setmap: map[string]bool{ + "TestInvaild": true, + }, + expect: map[Feature]bool{ + testAlphaGate: false, + testBetaGate: false, + }, + setmapError: "unrecognized key:", + }, + } + for i, test := range tests { + t.Run(fmt.Sprintf("SetFromMap %s", test.name), func(t *testing.T) { + f := NewFeatureGate() + f.Add(map[Feature]FeatureSpec{ + testAlphaGate: {Default: false, PreRelease: Alpha}, + testBetaGate: {Default: false, PreRelease: Beta}, + }) + err := f.SetFromMap(test.setmap) + if test.setmapError != "" { + if !strings.Contains(err.Error(), test.setmapError) { + t.Errorf("%d: SetFromMap(%#v) Expected err:%v, Got err:%v", i, test.setmap, test.setmapError, err) + } + } else if err != nil { + t.Errorf("%d: SetFromMap(%#v) Expected success, Got err:%v", i, test.setmap, err) + } + for k, v := range test.expect { + if actual := f.Enabled(k); actual != v { + t.Errorf("%d: SetFromMap(%#v) Expected %s=%v, Got %s=%v", i, test.setmap, k, v, k, actual) + } + } + }) + } +} + +func TestFeatureGateString(t *testing.T) { + // gates for testing + const testAlphaGate Feature = "TestAlpha" + const testBetaGate Feature = "TestBeta" + const testGAGate Feature = "TestGA" + + featuremap := map[Feature]FeatureSpec{ + testGAGate: {Default: true, PreRelease: GA}, + testAlphaGate: {Default: false, PreRelease: Alpha}, + testBetaGate: {Default: true, PreRelease: Beta}, + } + + tests := []struct { + setmap map[string]bool + expect string + }{ + { + setmap: map[string]bool{ + "TestAlpha": false, + }, + expect: "TestAlpha=false", + }, + { + setmap: map[string]bool{ + "TestAlpha": false, + "TestBeta": true, + }, + expect: "TestAlpha=false,TestBeta=true", + }, + { + setmap: map[string]bool{ + "TestGA": true, + "TestAlpha": false, + "TestBeta": true, + }, + expect: "TestAlpha=false,TestBeta=true,TestGA=true", + }, + } + for i, test := range tests { + t.Run(fmt.Sprintf("SetFromMap %s", test.expect), func(t *testing.T) { + f := NewFeatureGate() + f.Add(featuremap) + f.SetFromMap(test.setmap) + result := f.String() + if result != test.expect { + t.Errorf("%d: SetFromMap(%#v) Expected %s, Got %s", i, test.setmap, test.expect, result) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/BUILD index 7a73ad0d5..1883510d5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/BUILD @@ -40,6 +40,7 @@ go_library( deps = [ "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/ciphersuites_flag.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/ciphersuites_flag.go index 73fd62c10..764747c25 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/ciphersuites_flag.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/ciphersuites_flag.go @@ -19,6 +19,8 @@ package flag import ( "crypto/tls" "fmt" + + "k8s.io/apimachinery/pkg/util/sets" ) // ciphers maps strings into tls package cipher constants in @@ -48,6 +50,14 @@ var ciphers = map[string]uint16{ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, } +func TLSCipherPossibleValues() []string { + cipherKeys := sets.NewString() + for key := range ciphers { + cipherKeys.Insert(key) + } + return cipherKeys.List() +} + func TLSCipherSuites(cipherNames []string) ([]uint16, error) { if len(cipherNames) == 0 { return nil, nil @@ -69,6 +79,14 @@ var versions = map[string]uint16{ "VersionTLS12": tls.VersionTLS12, } +func TLSPossibleVersions() []string { + versionsKeys := sets.NewString() + for key := range versions { + versionsKeys.Insert(key) + } + return versionsKeys.List() +} + func TLSVersion(versionName string) (uint16, error) { if len(versionName) == 0 { return DefaultTLSVersion(), nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_bool.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_bool.go index 46ed43836..e5a01805b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_bool.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_bool.go @@ -39,6 +39,9 @@ func NewMapStringBool(m *map[string]bool) *MapStringBool { // String implements github.com/spf13/pflag.Value func (m *MapStringBool) String() string { + if m == nil || m.Map == nil { + return "" + } pairs := []string{} for k, v := range *m.Map { pairs = append(pairs, fmt.Sprintf("%s=%t", k, v)) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_string.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_string.go index 48468a8dd..129470b3c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_string.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_string.go @@ -23,11 +23,14 @@ import ( ) // MapStringString can be set from the command line with the format `--flag "string=string"`. -// Multiple comma-separated key-value pairs in a single invocation are supported. For example: `--flag "a=foo,b=bar"`. -// Multiple flag invocations are supported. For example: `--flag "a=foo" --flag "b=bar"`. +// Multiple flag invocations are supported. For example: `--flag "a=foo" --flag "b=bar"`. If this is desired +// to be the only type invocation `NoSplit` should be set to true. +// Multiple comma-separated key-value pairs in a single invocation are supported if `NoSplit` +// is set to false. For example: `--flag "a=foo,b=bar"`. type MapStringString struct { Map *map[string]string initialized bool + NoSplit bool } // NewMapStringString takes a pointer to a map[string]string and returns the @@ -36,8 +39,20 @@ func NewMapStringString(m *map[string]string) *MapStringString { return &MapStringString{Map: m} } +// NewMapStringString takes a pointer to a map[string]string and sets `NoSplit` +// value to `true` and returns the MapStringString flag parsing shim for that map +func NewMapStringStringNoSplit(m *map[string]string) *MapStringString { + return &MapStringString{ + Map: m, + NoSplit: true, + } +} + // String implements github.com/spf13/pflag.Value func (m *MapStringString) String() string { + if m == nil || m.Map == nil { + return "" + } pairs := []string{} for k, v := range *m.Map { pairs = append(pairs, fmt.Sprintf("%s=%s", k, v)) @@ -56,19 +71,34 @@ func (m *MapStringString) Set(value string) error { *m.Map = make(map[string]string) m.initialized = true } - for _, s := range strings.Split(value, ",") { - if len(s) == 0 { - continue - } - arr := strings.SplitN(s, "=", 2) - if len(arr) != 2 { - return fmt.Errorf("malformed pair, expect string=string") + + // account for comma-separated key-value pairs in a single invocation + if !m.NoSplit { + for _, s := range strings.Split(value, ",") { + if len(s) == 0 { + continue + } + arr := strings.SplitN(s, "=", 2) + if len(arr) != 2 { + return fmt.Errorf("malformed pair, expect string=string") + } + k := strings.TrimSpace(arr[0]) + v := strings.TrimSpace(arr[1]) + (*m.Map)[k] = v } - k := strings.TrimSpace(arr[0]) - v := strings.TrimSpace(arr[1]) - (*m.Map)[k] = v + return nil + } + + // account for only one key-value pair in a single invocation + arr := strings.SplitN(value, "=", 2) + if len(arr) != 2 { + return fmt.Errorf("malformed pair, expect string=string") } + k := strings.TrimSpace(arr[0]) + v := strings.TrimSpace(arr[1]) + (*m.Map)[k] = v return nil + } // Type implements github.com/spf13/pflag.Value diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_string_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_string_test.go index 8feb62524..aba984e7a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_string_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/map_string_string_test.go @@ -58,6 +58,7 @@ func TestSetMapStringString(t *testing.T) { &MapStringString{ initialized: true, Map: &map[string]string{}, + NoSplit: false, }, ""}, // make sure we still allocate for "initialized" maps where Map was initially set to a nil map {"allocates map if currently nil", []string{""}, @@ -65,6 +66,7 @@ func TestSetMapStringString(t *testing.T) { &MapStringString{ initialized: true, Map: &map[string]string{}, + NoSplit: false, }, ""}, // for most cases, we just reuse nilMap, which should be allocated by Set, and is reset before each test case {"empty", []string{""}, @@ -72,36 +74,56 @@ func TestSetMapStringString(t *testing.T) { &MapStringString{ initialized: true, Map: &map[string]string{}, + NoSplit: false, }, ""}, {"one key", []string{"one=foo"}, NewMapStringString(&nilMap), &MapStringString{ initialized: true, Map: &map[string]string{"one": "foo"}, + NoSplit: false, }, ""}, {"two keys", []string{"one=foo,two=bar"}, NewMapStringString(&nilMap), &MapStringString{ initialized: true, Map: &map[string]string{"one": "foo", "two": "bar"}, + NoSplit: false, + }, ""}, + {"one key, multi flag invocation only", []string{"one=foo,bar"}, + NewMapStringStringNoSplit(&nilMap), + &MapStringString{ + initialized: true, + Map: &map[string]string{"one": "foo,bar"}, + NoSplit: true, + }, ""}, + {"two keys, multi flag invocation only", []string{"one=foo,bar", "two=foo,bar"}, + NewMapStringStringNoSplit(&nilMap), + &MapStringString{ + initialized: true, + Map: &map[string]string{"one": "foo,bar", "two": "foo,bar"}, + NoSplit: true, }, ""}, {"two keys, multiple Set invocations", []string{"one=foo", "two=bar"}, NewMapStringString(&nilMap), &MapStringString{ initialized: true, Map: &map[string]string{"one": "foo", "two": "bar"}, + NoSplit: false, }, ""}, {"two keys with space", []string{"one=foo, two=bar"}, NewMapStringString(&nilMap), &MapStringString{ initialized: true, Map: &map[string]string{"one": "foo", "two": "bar"}, + NoSplit: false, }, ""}, {"empty key", []string{"=foo"}, NewMapStringString(&nilMap), &MapStringString{ initialized: true, Map: &map[string]string{"": "foo"}, + NoSplit: false, }, ""}, {"missing value", []string{"one"}, NewMapStringString(&nilMap), diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/namedcertkey_flag_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/namedcertkey_flag_test.go index 76df0e868..542e221c9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/namedcertkey_flag_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/flag/namedcertkey_flag_test.go @@ -112,9 +112,8 @@ func TestNamedCertKeyArrayFlag(t *testing.T) { for i, test := range tests { fs := pflag.NewFlagSet("testNamedCertKeyArray", pflag.ContinueOnError) var nkcs []NamedCertKey - for _, d := range test.def { - nkcs = append(nkcs, d) - } + nkcs = append(nkcs, test.def...) + fs.Var(NewNamedCertKeyArray(&nkcs), "tls-sni-cert-key", "usage") args := []string{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/openapi/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/openapi/BUILD new file mode 100644 index 000000000..fd9dc89c8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/openapi/BUILD @@ -0,0 +1,41 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["proto.go"], + importpath = "k8s.io/apiserver/pkg/util/openapi", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/go-openapi/spec:go_default_library", + "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", + "//vendor/github.com/googleapis/gnostic/compiler:go_default_library", + "//vendor/gopkg.in/yaml.v2:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["proto_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/github.com/go-openapi/spec:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/openapi/proto.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/openapi/proto.go new file mode 100644 index 000000000..5641d1a14 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/openapi/proto.go @@ -0,0 +1,142 @@ +/* +Copyright 2018 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 openapi + +import ( + "encoding/json" + "fmt" + + "github.com/go-openapi/spec" + openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/googleapis/gnostic/compiler" + yaml "gopkg.in/yaml.v2" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kube-openapi/pkg/util/proto" +) + +const ( + // groupVersionKindExtensionKey is the key used to lookup the + // GroupVersionKind value for an object definition from the + // definition's "extensions" map. + groupVersionKindExtensionKey = "x-kubernetes-group-version-kind" +) + +// ToProtoSchema builds the proto formatted schema from an OpenAPI spec +func ToProtoSchema(openAPIDefinitions *spec.Definitions, gvk schema.GroupVersionKind) (proto.Schema, error) { + openAPISpec := newMinimalValidOpenAPISpec() + openAPISpec.Definitions = *openAPIDefinitions + + specBytes, err := json.MarshalIndent(openAPISpec, " ", " ") + if err != nil { + return nil, err + } + + var info yaml.MapSlice + err = yaml.Unmarshal(specBytes, &info) + if err != nil { + return nil, err + } + + doc, err := openapi_v2.NewDocument(info, compiler.NewContext("$root", nil)) + if err != nil { + return nil, err + } + + models, err := proto.NewOpenAPIData(doc) + if err != nil { + return nil, err + } + + for _, modelName := range models.ListModels() { + model := models.LookupModel(modelName) + if model == nil { + return nil, fmt.Errorf("the ListModels function returned a model that can't be looked-up") + } + gvkList := parseGroupVersionKind(model) + for _, modelGVK := range gvkList { + if modelGVK == gvk { + return model, nil + } + } + } + + return nil, fmt.Errorf("no model found with a %v tag matching %v", groupVersionKindExtensionKey, gvk) +} + +// newMinimalValidOpenAPISpec creates a minimal openapi spec with only the required fields filled in +func newMinimalValidOpenAPISpec() *spec.Swagger { + return &spec.Swagger{ + SwaggerProps: spec.SwaggerProps{ + Swagger: "2.0", + Info: &spec.Info{ + InfoProps: spec.InfoProps{ + Title: "Kubernetes", + Version: "0.0.0", + }, + }, + }, + } +} + +// parseGroupVersionKind gets and parses GroupVersionKind from the extension. Returns empty if it doesn't have one. +func parseGroupVersionKind(s proto.Schema) []schema.GroupVersionKind { + extensions := s.GetExtensions() + + gvkListResult := []schema.GroupVersionKind{} + + // Get the extensions + gvkExtension, ok := extensions[groupVersionKindExtensionKey] + if !ok { + return []schema.GroupVersionKind{} + } + + // gvk extension must be a list of at least 1 element. + gvkList, ok := gvkExtension.([]interface{}) + if !ok { + return []schema.GroupVersionKind{} + } + + for _, gvk := range gvkList { + // gvk extension list must be a map with group, version, and + // kind fields + gvkMap, ok := gvk.(map[interface{}]interface{}) + if !ok { + continue + } + group, ok := gvkMap["group"].(string) + if !ok { + continue + } + version, ok := gvkMap["version"].(string) + if !ok { + continue + } + kind, ok := gvkMap["kind"].(string) + if !ok { + continue + } + + gvkListResult = append(gvkListResult, schema.GroupVersionKind{ + Group: group, + Version: version, + Kind: kind, + }) + } + + return gvkListResult +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/openapi/proto_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/openapi/proto_test.go new file mode 100644 index 000000000..64421a7ff --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/openapi/proto_test.go @@ -0,0 +1,77 @@ +/* +Copyright 2018 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 openapi + +import ( + "reflect" + "testing" + + "github.com/go-openapi/spec" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kube-openapi/pkg/util/proto" +) + +// TestOpenAPIDefinitionsToProtoSchema tests the openapi parser +func TestOpenAPIDefinitionsToProtoSchema(t *testing.T) { + openAPIDefinitions := &spec.Definitions{ + "io.k8s.api.testgroup.v1.Foo": spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Description of Foos", + Properties: map[string]spec.Schema{}, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-group-version-kind": []map[string]string{ + { + "group": "testgroup.k8s.io", + "version": "v1", + "kind": "Foo", + }, + }, + }, + }, + }, + } + gvk := schema.GroupVersionKind{ + Group: "testgroup.k8s.io", + Version: "v1", + Kind: "Foo", + } + expectedSchema := &proto.Arbitrary{ + BaseSchema: proto.BaseSchema{ + Description: "Description of Foos", + Extensions: map[string]interface{}{ + "x-kubernetes-group-version-kind": []interface{}{ + map[interface{}]interface{}{ + "group": "testgroup.k8s.io", + "version": "v1", + "kind": "Foo", + }, + }, + }, + Path: proto.NewPath("io.k8s.api.testgroup.v1.Foo"), + }, + } + actualSchema, err := ToProtoSchema(openAPIDefinitions, gvk) + if err != nil { + t.Fatalf("expected ToProtoSchema not to return an error") + } + if !reflect.DeepEqual(expectedSchema, actualSchema) { + t.Fatalf("expected schema:\n%v\nbut got:\n%v", expectedSchema, actualSchema) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/BUILD index 4cacaf511..c96af1f9c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/BUILD @@ -12,7 +12,6 @@ go_library( importpath = "k8s.io/apiserver/pkg/util/webhook", deps = [ "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered: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:go_default_library", @@ -32,7 +31,7 @@ go_test( embed = [":go_default_library"], deps = [ "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered: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/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/gencerts.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/gencerts.sh index fdceb9571..a042ab62a 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/gencerts.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/gencerts.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go index 6893e834e..3b03fd3fd 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go @@ -22,7 +22,6 @@ import ( "time" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" @@ -42,13 +41,13 @@ type GenericWebhook struct { } // NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file. -func NewGenericWebhook(registry *registered.APIRegistrationManager, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration) (*GenericWebhook, error) { - return newGenericWebhook(registry, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout) +func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration) (*GenericWebhook, error) { + return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout) } -func newGenericWebhook(registry *registered.APIRegistrationManager, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration) (*GenericWebhook, error) { +func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration) (*GenericWebhook, error) { for _, groupVersion := range groupVersions { - if !registry.IsEnabledVersion(groupVersion) { + if !scheme.IsVersionRegistered(groupVersion) { return nil, fmt.Errorf("webhook plugin requires enabling extension resource: %s", groupVersion) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook_test.go index 8485e4f89..0399ed843 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook_test.go @@ -32,7 +32,7 @@ import ( "time" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/apimachinery/registered" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -70,25 +70,6 @@ var ( retryBackoff = time.Duration(500) * time.Millisecond ) -// TestDisabledGroupVersion ensures that requiring a group version works as expected -func TestDisabledGroupVersion(t *testing.T) { - gv := schema.GroupVersion{Group: "webhook.util.k8s.io", Version: "v1"} - gvs := []schema.GroupVersion{gv} - registry := registered.NewOrDie(gv.String()) - _, err := NewGenericWebhook(registry, scheme.Codecs, "/some/path", gvs, retryBackoff) - - if err == nil { - t.Errorf("expected an error") - } else { - aErrMsg := err.Error() - eErrMsg := fmt.Sprintf("webhook plugin requires enabling extension resource: %s", gv) - - if aErrMsg != eErrMsg { - t.Errorf("unexpected error message mismatch:\n Expected: %s\n Actual: %s", eErrMsg, aErrMsg) - } - } -} - // TestKubeConfigFile ensures that a kube config file, regardless of validity, is handled properly func TestKubeConfigFile(t *testing.T) { badCAPath := "/tmp/missing/ca.pem" @@ -277,7 +258,7 @@ func TestKubeConfigFile(t *testing.T) { if err == nil { defer os.Remove(kubeConfigFile) - _, err = NewGenericWebhook(registered.NewOrDie(""), scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff) + _, err = NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff) } return err @@ -300,7 +281,7 @@ func TestKubeConfigFile(t *testing.T) { // TestMissingKubeConfigFile ensures that a kube config path to a missing file is handled properly func TestMissingKubeConfigFile(t *testing.T) { kubeConfigPath := "/some/missing/path" - _, err := NewGenericWebhook(registered.NewOrDie(""), scheme.Codecs, kubeConfigPath, groupVersions, retryBackoff) + _, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigPath, groupVersions, retryBackoff) if err == nil { t.Errorf("creating the webhook should had failed") @@ -412,7 +393,7 @@ func TestTLSConfig(t *testing.T) { defer os.Remove(configFile) - wh, err := NewGenericWebhook(registered.NewOrDie(""), scheme.Codecs, configFile, groupVersions, retryBackoff) + wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff) if err == nil { err = wh.RestClient.Get().Do().Error() @@ -477,7 +458,7 @@ func TestRequestTimeout(t *testing.T) { var requestTimeout = 10 * time.Millisecond - wh, err := newGenericWebhook(registered.NewOrDie(""), scheme.Codecs, configFile, groupVersions, retryBackoff, requestTimeout) + wh, err := newGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, requestTimeout) if err != nil { t.Fatalf("failed to create the webhook: %v", err) } @@ -563,7 +544,7 @@ func TestWithExponentialBackoff(t *testing.T) { defer os.Remove(configFile) - wh, err := NewGenericWebhook(registered.NewOrDie(""), scheme.Codecs, configFile, groupVersions, retryBackoff) + wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff) if err != nil { t.Fatalf("failed to create the webhook: %v", err) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/buffered/buffered.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/buffered/buffered.go index c4a08f3b2..f50e5ad6d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/buffered/buffered.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/buffered/buffered.go @@ -54,7 +54,7 @@ type BatchConfig struct { ThrottleEnable bool // ThrottleQPS defines the allowed rate of batches per second sent to the delegate backend. ThrottleQPS float32 - // ThrottleBurst defines the maximum rate of batches per second sent to the delegate backend in case + // ThrottleBurst defines the maximum number of requests sent to the delegate backend at the same moment in case // the capacity defined by ThrottleQPS was not utilized. ThrottleBurst int } @@ -102,6 +102,7 @@ type bufferedBackend struct { var _ audit.Backend = &bufferedBackend{} // NewBackend returns a buffered audit backend that wraps delegate backend. +// Buffered backend automatically runs and shuts down the delegate backend. func NewBackend(delegate audit.Backend, config BatchConfig) audit.Backend { var throttle flowcontrol.RateLimiter if config.ThrottleEnable { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/BUILD index 13f4422db..9a43f94ba 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/BUILD @@ -37,11 +37,8 @@ go_test( embed = [":go_default_library"], deps = [ "//vendor/github.com/pborman/uuid:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/types:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/install:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend_test.go index 44f01a0c6..68932d931 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend_test.go @@ -18,7 +18,6 @@ package log import ( "bytes" - "fmt" "reflect" "regexp" "testing" @@ -26,11 +25,8 @@ import ( "github.com/pborman/uuid" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" auditinternal "k8s.io/apiserver/pkg/apis/audit" "k8s.io/apiserver/pkg/apis/audit/install" @@ -38,19 +34,8 @@ import ( "k8s.io/apiserver/pkg/audit" ) -// NOTE: Copied from webhook backend to register auditv1beta1 to scheme -var ( - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - registry = registered.NewOrDie("") -) - func init() { - allGVs := []schema.GroupVersion{auditv1beta1.SchemeGroupVersion} - registry.RegisterVersions(allGVs) - if err := registry.EnableVersions(allGVs...); err != nil { - panic(fmt.Sprintf("failed to enable version %v", allGVs)) - } - install.Install(groupFactoryRegistry, registry, audit.Scheme) + install.Install(audit.Scheme) } func TestLogEventsLegacy(t *testing.T) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/truncate/truncate.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/truncate/truncate.go index 79e6876ce..e06f1f2f0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/truncate/truncate.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/truncate/truncate.go @@ -62,6 +62,7 @@ type backend struct { var _ audit.Backend = &backend{} // NewBackend returns a new truncating backend, using configuration passed in the parameters. +// Truncate backend automatically runs and shut downs the delegate backend. func NewBackend(delegateBackend audit.Backend, config Config, groupVersion schema.GroupVersion) audit.Backend { return &backend{ delegateBackend: delegateBackend, @@ -128,12 +129,11 @@ func truncate(e *auditinternal.Event) *auditinternal.Event { } func (b *backend) Run(stopCh <-chan struct{}) error { - // Nothing to do here - return nil + return b.delegateBackend.Run(stopCh) } func (b *backend) Shutdown() { - // Nothing to do here + b.delegateBackend.Shutdown() } func (b *backend) calcSize(e *auditinternal.Event) (int64, error) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/BUILD index 1fd9312ff..62faa456f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/BUILD @@ -28,13 +28,9 @@ go_library( srcs = ["webhook.go"], importpath = "k8s.io/apiserver/plugin/pkg/audit/webhook", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/install:go_default_library", - "//vendor/k8s.io/apiserver/pkg/apis/audit/v1alpha1:go_default_library", - "//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library", "//vendor/k8s.io/apiserver/pkg/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/webhook:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go index eb2abada9..80b4842fd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go @@ -18,16 +18,11 @@ limitations under the License. package webhook import ( - "fmt" "time" - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime/schema" auditinternal "k8s.io/apiserver/pkg/apis/audit" "k8s.io/apiserver/pkg/apis/audit/install" - auditv1alpha1 "k8s.io/apiserver/pkg/apis/audit/v1alpha1" - auditv1beta1 "k8s.io/apiserver/pkg/apis/audit/v1beta1" "k8s.io/apiserver/pkg/audit" "k8s.io/apiserver/pkg/util/webhook" "k8s.io/client-go/rest" @@ -42,26 +37,12 @@ const ( DefaultInitialBackoff = 10 * time.Second ) -var ( - // NOTE: Copied from other webhook implementations - // - // Can we make these passable to NewGenericWebhook? - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - // TODO(audit): figure out a general way to let the client choose their preferred version - registry = registered.NewOrDie("") -) - func init() { - allGVs := []schema.GroupVersion{auditv1alpha1.SchemeGroupVersion, auditv1beta1.SchemeGroupVersion} - registry.RegisterVersions(allGVs) - if err := registry.EnableVersions(allGVs...); err != nil { - panic(fmt.Sprintf("failed to enable version %v", allGVs)) - } - install.Install(groupFactoryRegistry, registry, audit.Scheme) + install.Install(audit.Scheme) } func loadWebhook(configFile string, groupVersion schema.GroupVersion, initialBackoff time.Duration) (*webhook.GenericWebhook, error) { - return webhook.NewGenericWebhook(registry, audit.Codecs, configFile, + return webhook.NewGenericWebhook(audit.Scheme, audit.Codecs, configFile, []schema.GroupVersion{groupVersion}, initialBackoff) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/BUILD index ed1d41513..53b017a8d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/BUILD @@ -22,7 +22,6 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow:all-srcs", "//staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile:all-srcs", ], tags = ["automanaged"], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow/BUILD deleted file mode 100644 index ee53216ee..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = ["allow_test.go"], - embed = [":go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["allow.go"], - importpath = "k8s.io/apiserver/plugin/pkg/authenticator/password/allow", - deps = [ - "//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", - "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow/allow.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow/allow.go deleted file mode 100644 index 3ca0ee234..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow/allow.go +++ /dev/null @@ -1,38 +0,0 @@ -/* -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 allow - -import ( - "k8s.io/apiserver/pkg/authentication/authenticator" - "k8s.io/apiserver/pkg/authentication/user" -) - -type allowAuthenticator struct{} - -// NewAllow returns a password authenticator that allows any non-empty username -func NewAllow() authenticator.Password { - return allowAuthenticator{} -} - -// AuthenticatePassword implements authenticator.Password to allow any non-empty username, -// using the specified username as the name and UID -func (allowAuthenticator) AuthenticatePassword(username, password string) (user.Info, bool, error) { - if username == "" { - return nil, false, nil - } - return &user.DefaultInfo{Name: username, UID: username}, true, nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow/allow_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow/allow_test.go deleted file mode 100644 index 58d217091..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/allow/allow_test.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -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 allow - -import "testing" - -func TestAllowEmpty(t *testing.T) { - allow := NewAllow() - user, ok, err := allow.AuthenticatePassword("", "") - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if ok { - t.Fatalf("Unexpected success") - } - if user != nil { - t.Fatalf("Unexpected user: %v", user) - } -} - -func TestAllowPresent(t *testing.T) { - allow := NewAllow() - user, ok, err := allow.AuthenticatePassword("myuser", "") - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if !ok { - t.Fatalf("Unexpected failure") - } - if user.GetName() != "myuser" || user.GetUID() != "myuser" { - t.Fatalf("Unexpected user name or uid: %v", user) - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD index e62aba93a..f54e37229 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD @@ -8,11 +8,13 @@ load( go_test( name = "go_default_test", + size = "small", srcs = ["oidc_test.go"], data = glob(["testdata/**"]), embed = [":go_default_library"], deps = [ "//vendor/github.com/coreos/go-oidc:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", "//vendor/gopkg.in/square/go-jose.v2:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go index c33c540c0..38cd5bd5d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go @@ -34,9 +34,11 @@ import ( "encoding/json" "errors" "fmt" + "io/ioutil" "net/http" "net/url" "strings" + "sync" "sync/atomic" "time" @@ -48,6 +50,12 @@ import ( certutil "k8s.io/client-go/util/cert" ) +var ( + // synchronizeTokenIDVerifierForTest should be set to true to force a + // wait until the token ID verifiers are ready. + synchronizeTokenIDVerifierForTest = false +) + type Options struct { // IssuerURL is the URL the provider signs ID Tokens as. This will be the "iss" // field of all tokens produced by the provider and is used for configuration @@ -98,10 +106,78 @@ type Options struct { // https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation SupportedSigningAlgs []string + // RequiredClaims, if specified, causes the OIDCAuthenticator to verify that all the + // required claims key value pairs are present in the ID Token. + RequiredClaims map[string]string + // now is used for testing. It defaults to time.Now. now func() time.Time } +// initVerifier creates a new ID token verifier for the given configuration and issuer URL. On success, calls setVerifier with the +// resulting verifier. +func initVerifier(ctx context.Context, config *oidc.Config, iss string) (*oidc.IDTokenVerifier, error) { + provider, err := oidc.NewProvider(ctx, iss) + if err != nil { + return nil, fmt.Errorf("init verifier failed: %v", err) + } + return provider.Verifier(config), nil +} + +// asyncIDTokenVerifier is an ID token verifier that allows async initialization +// of the issuer check. Must be passed by reference as it wraps sync.Mutex. +type asyncIDTokenVerifier struct { + m sync.Mutex + + // v is the ID token verifier initialized asynchronously. It remains nil + // up until it is eventually initialized. + // Guarded by m + v *oidc.IDTokenVerifier +} + +// newAsyncIDTokenVerifier creates a new asynchronous token verifier. The +// verifier is available immediately, but may remain uninitialized for some time +// after creation. +func newAsyncIDTokenVerifier(ctx context.Context, c *oidc.Config, iss string) *asyncIDTokenVerifier { + t := &asyncIDTokenVerifier{} + + sync := make(chan struct{}) + // Polls indefinitely in an attempt to initialize the distributed claims + // verifier, or until context canceled. + initFn := func() (done bool, err error) { + glog.V(4).Infof("oidc authenticator: attempting init: iss=%v", iss) + v, err := initVerifier(ctx, c, iss) + if err != nil { + glog.Errorf("oidc authenticator: async token verifier for issuer: %q: %v", iss, err) + return false, nil + } + t.m.Lock() + defer t.m.Unlock() + t.v = v + close(sync) + return true, nil + } + + go func() { + if done, _ := initFn(); !done { + go wait.PollUntil(time.Second*10, initFn, ctx.Done()) + } + }() + + if synchronizeTokenIDVerifierForTest { + <-sync + } + + return t +} + +// verifier returns the underlying ID token verifier, or nil if one is not yet initialized. +func (a *asyncIDTokenVerifier) verifier() *oidc.IDTokenVerifier { + a.m.Lock() + defer a.m.Unlock() + return a.v +} + type Authenticator struct { issuerURL string @@ -109,12 +185,16 @@ type Authenticator struct { usernamePrefix string groupsClaim string groupsPrefix string + requiredClaims map[string]string // Contains an *oidc.IDTokenVerifier. Do not access directly use the // idTokenVerifier method. verifier atomic.Value cancel context.CancelFunc + + // resolver is used to resolve distributed claims. + resolver *claimResolver } func (a *Authenticator) setVerifier(v *oidc.IDTokenVerifier) { @@ -212,15 +292,6 @@ func newAuthenticator(opts Options, initVerifier func(ctx context.Context, a *Au ctx, cancel := context.WithCancel(context.Background()) ctx = oidc.ClientContext(ctx, client) - authenticator := &Authenticator{ - issuerURL: opts.IssuerURL, - usernameClaim: opts.UsernameClaim, - usernamePrefix: opts.UsernamePrefix, - groupsClaim: opts.GroupsClaim, - groupsPrefix: opts.GroupsPrefix, - cancel: cancel, - } - now := opts.now if now == nil { now = time.Now @@ -232,43 +303,237 @@ func newAuthenticator(opts Options, initVerifier func(ctx context.Context, a *Au Now: now, } + var resolver *claimResolver + if opts.GroupsClaim != "" { + resolver = newClaimResolver(opts.GroupsClaim, client, verifierConfig) + } + + authenticator := &Authenticator{ + issuerURL: opts.IssuerURL, + usernameClaim: opts.UsernameClaim, + usernamePrefix: opts.UsernamePrefix, + groupsClaim: opts.GroupsClaim, + groupsPrefix: opts.GroupsPrefix, + requiredClaims: opts.RequiredClaims, + cancel: cancel, + resolver: resolver, + } + initVerifier(ctx, authenticator, verifierConfig) return authenticator, nil } -func hasCorrectIssuer(iss, tokenData string) bool { - parts := strings.Split(tokenData, ".") +// untrustedIssuer extracts an untrusted "iss" claim from the given JWT token, +// or returns an error if the token can not be parsed. Since the JWT is not +// verified, the returned issuer should not be trusted. +func untrustedIssuer(token string) (string, error) { + parts := strings.Split(token, ".") if len(parts) != 3 { - return false + return "", fmt.Errorf("malformed token") } payload, err := base64.RawURLEncoding.DecodeString(parts[1]) if err != nil { - return false + return "", fmt.Errorf("error decoding token: %v", err) } claims := struct { // WARNING: this JWT is not verified. Do not trust these claims. Issuer string `json:"iss"` }{} if err := json.Unmarshal(payload, &claims); err != nil { + return "", fmt.Errorf("while unmarshaling token: %v", err) + } + return claims.Issuer, nil +} + +func hasCorrectIssuer(iss, tokenData string) bool { + uiss, err := untrustedIssuer(tokenData) + if err != nil { return false } - if claims.Issuer != iss { + if uiss != iss { return false } return true } +// endpoint represents an OIDC distributed claims endpoint. +type endpoint struct { + // URL to use to request the distributed claim. This URL is expected to be + // prefixed by one of the known issuer URLs. + URL string `json:"endpoint,omitempty"` + // AccessToken is the bearer token to use for access. If empty, it is + // not used. Access token is optional per the OIDC distributed claims + // specification. + // See: http://openid.net/specs/openid-connect-core-1_0.html#DistributedExample + AccessToken string `json:"access_token,omitempty"` + // JWT is the container for aggregated claims. Not supported at the moment. + // See: http://openid.net/specs/openid-connect-core-1_0.html#AggregatedExample + JWT string `json:"JWT,omitempty"` +} + +// claimResolver expands distributed claims by calling respective claim source +// endpoints. +type claimResolver struct { + // claim is the distributed claim that may be resolved. + claim string + + // client is the to use for resolving distributed claims + client *http.Client + + // config is the OIDC configuration used for resolving distributed claims. + config *oidc.Config + + // verifierPerIssuer contains, for each issuer, the appropriate verifier to use + // for this claim. It is assumed that there will be very few entries in + // this map. + // Guarded by m. + verifierPerIssuer map[string]*asyncIDTokenVerifier + + m sync.Mutex +} + +// newClaimResolver creates a new resolver for distributed claims. +func newClaimResolver(claim string, client *http.Client, config *oidc.Config) *claimResolver { + return &claimResolver{claim: claim, client: client, config: config, verifierPerIssuer: map[string]*asyncIDTokenVerifier{}} +} + +// Verifier returns either the verifier for the specified issuer, or error. +func (r *claimResolver) Verifier(iss string) (*oidc.IDTokenVerifier, error) { + r.m.Lock() + av := r.verifierPerIssuer[iss] + if av == nil { + // This lazy init should normally be very quick. + // TODO: Make this context cancelable. + ctx := oidc.ClientContext(context.Background(), r.client) + av = newAsyncIDTokenVerifier(ctx, r.config, iss) + r.verifierPerIssuer[iss] = av + } + r.m.Unlock() + + v := av.verifier() + if v == nil { + return nil, fmt.Errorf("verifier not initialized for issuer: %q", iss) + } + return v, nil +} + +// expand extracts the distributed claims from claim names and claim sources. +// The extracted claim value is pulled up into the supplied claims. +// +// Distributed claims are of the form as seen below, and are defined in the +// OIDC Connect Core 1.0, section 5.6.2. +// See: https://openid.net/specs/openid-connect-core-1_0.html#AggregatedDistributedClaims +// +// { +// ... (other normal claims)... +// "_claim_names": { +// "groups": "src1" +// }, +// "_claim_sources": { +// "src1": { +// "endpoint": "https://www.example.com", +// "access_token": "f005ba11" +// }, +// }, +// } +func (r *claimResolver) expand(c claims) error { + const ( + // The claim containing a map of endpoint references per claim. + // OIDC Connect Core 1.0, section 5.6.2. + claimNamesKey = "_claim_names" + // The claim containing endpoint specifications. + // OIDC Connect Core 1.0, section 5.6.2. + claimSourcesKey = "_claim_sources" + ) + + _, ok := c[r.claim] + if ok { + // There already is a normal claim, skip resolving. + return nil + } + names, ok := c[claimNamesKey] + if !ok { + // No _claim_names, no keys to look up. + return nil + } + + claimToSource := map[string]string{} + if err := json.Unmarshal([]byte(names), &claimToSource); err != nil { + return fmt.Errorf("oidc: error parsing distributed claim names: %v", err) + } + + rawSources, ok := c[claimSourcesKey] + if !ok { + // Having _claim_names claim, but no _claim_sources is not an expected + // state. + return fmt.Errorf("oidc: no claim sources") + } + + var sources map[string]endpoint + if err := json.Unmarshal([]byte(rawSources), &sources); err != nil { + // The claims sources claim is malformed, this is not an expected state. + return fmt.Errorf("oidc: could not parse claim sources: %v", err) + } + + src, ok := claimToSource[r.claim] + if !ok { + // No distributed claim present. + return nil + } + ep, ok := sources[src] + if !ok { + return fmt.Errorf("id token _claim_names contained a source %s missing in _claims_sources", src) + } + if ep.URL == "" { + // This is maybe an aggregated claim (ep.JWT != ""). + return nil + } + return r.resolve(ep, c) +} + +// resolve requests distributed claims from all endpoints passed in, +// and inserts the lookup results into allClaims. +func (r *claimResolver) resolve(endpoint endpoint, allClaims claims) error { + // TODO: cache resolved claims. + jwt, err := getClaimJWT(r.client, endpoint.URL, endpoint.AccessToken) + if err != nil { + return fmt.Errorf("while getting distributed claim %q: %v", r.claim, err) + } + untrustedIss, err := untrustedIssuer(jwt) + if err != nil { + return fmt.Errorf("getting untrusted issuer from endpoint %v failed for claim %q: %v", endpoint.URL, r.claim, err) + } + v, err := r.Verifier(untrustedIss) + if err != nil { + return fmt.Errorf("verifying untrusted issuer %v failed: %v", untrustedIss, err) + } + t, err := v.Verify(context.Background(), jwt) + if err != nil { + return fmt.Errorf("verify distributed claim token: %v", err) + } + var distClaims claims + if err := t.Claims(&distClaims); err != nil { + return fmt.Errorf("could not parse distributed claims for claim %v: %v", r.claim, err) + } + value, ok := distClaims[r.claim] + if !ok { + return fmt.Errorf("jwt returned by distributed claim endpoint %s did not contain claim: %v", endpoint, r.claim) + } + allClaims[r.claim] = value + return nil +} + func (a *Authenticator) AuthenticateToken(token string) (user.Info, bool, error) { if !hasCorrectIssuer(a.issuerURL, token) { return nil, false, nil } - ctx := context.Background() verifier, ok := a.idTokenVerifier() if !ok { return nil, false, fmt.Errorf("oidc: authenticator not initialized") } + ctx := context.Background() idToken, err := verifier.Verify(ctx, token) if err != nil { return nil, false, fmt.Errorf("oidc: verify token: %v", err) @@ -278,20 +543,30 @@ func (a *Authenticator) AuthenticateToken(token string) (user.Info, bool, error) if err := idToken.Claims(&c); err != nil { return nil, false, fmt.Errorf("oidc: parse claims: %v", err) } + if a.resolver != nil { + if err := a.resolver.expand(c); err != nil { + return nil, false, fmt.Errorf("oidc: could not expand distributed claims: %v", err) + } + } + var username string if err := c.unmarshalClaim(a.usernameClaim, &username); err != nil { return nil, false, fmt.Errorf("oidc: parse username claims %q: %v", a.usernameClaim, err) } if a.usernameClaim == "email" { - // Check the email_verified claim to ensure the email is valid. + // If the email_verified claim is present, ensure the email is valid. // https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims - var emailVerified bool - if err := c.unmarshalClaim("email_verified", &emailVerified); err != nil { - return nil, false, fmt.Errorf("oidc: parse 'email_verified' claim: %v", err) - } - if !emailVerified { - return nil, false, fmt.Errorf("oidc: email not verified") + if hasEmailVerified := c.hasClaim("email_verified"); hasEmailVerified { + var emailVerified bool + if err := c.unmarshalClaim("email_verified", &emailVerified); err != nil { + return nil, false, fmt.Errorf("oidc: parse 'email_verified' claim: %v", err) + } + + // If the email_verified claim is present we have to verify it is set to `true`. + if !emailVerified { + return nil, false, fmt.Errorf("oidc: email not verified") + } } } @@ -319,9 +594,59 @@ func (a *Authenticator) AuthenticateToken(token string) (user.Info, bool, error) info.Groups[i] = a.groupsPrefix + group } } + + // check to ensure all required claims are present in the ID token and have matching values. + for claim, value := range a.requiredClaims { + if !c.hasClaim(claim) { + return nil, false, fmt.Errorf("oidc: required claim %s not present in ID token", claim) + } + + // NOTE: Only string values are supported as valid required claim values. + var claimValue string + if err := c.unmarshalClaim(claim, &claimValue); err != nil { + return nil, false, fmt.Errorf("oidc: parse claim %s: %v", claim, err) + } + if claimValue != value { + return nil, false, fmt.Errorf("oidc: required claim %s value does not match. Got = %s, want = %s", claim, claimValue, value) + } + } + return info, true, nil } +// getClaimJWT gets a distributed claim JWT from url, using the supplied access +// token as bearer token. If the access token is "", the authorization header +// will not be set. +// TODO: Allow passing in JSON hints to the IDP. +func getClaimJWT(client *http.Client, url, accessToken string) (string, error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // TODO: Allow passing request body with configurable information. + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return "", fmt.Errorf("while calling %v: %v", url, err) + } + if accessToken != "" { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", accessToken)) + } + req = req.WithContext(ctx) + response, err := client.Do(req) + if err != nil { + return "", err + } + // Report non-OK status code as an error. + if response.StatusCode < http.StatusOK || response.StatusCode > http.StatusIMUsed { + return "", fmt.Errorf("error while getting distributed claim JWT: %v", response.Status) + } + defer response.Body.Close() + responseBytes, err := ioutil.ReadAll(response.Body) + if err != nil { + return "", fmt.Errorf("could not decode distributed claim response") + } + return string(responseBytes), nil +} + type stringOrArray []string func (s *stringOrArray) UnmarshalJSON(b []byte) error { @@ -347,3 +672,10 @@ func (c claims) unmarshalClaim(name string, v interface{}) error { } return json.Unmarshal([]byte(val), v) } + +func (c claims) hasClaim(name string) bool { + if _, ok := c[name]; !ok { + return false + } + return true +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc_test.go index 412c32a6f..53d849bdb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc_test.go @@ -17,6 +17,7 @@ limitations under the License. package oidc import ( + "bytes" "context" "crypto" "crypto/x509" @@ -25,12 +26,17 @@ import ( "encoding/pem" "fmt" "io/ioutil" + "net/http" + "net/http/httptest" + "os" "reflect" "strings" "testing" + "text/template" "time" oidc "github.com/coreos/go-oidc" + "github.com/golang/glog" jose "gopkg.in/square/go-jose.v2" "k8s.io/apiserver/pkg/authentication/user" ) @@ -122,22 +128,148 @@ var ( ) type claimsTest struct { - name string - options Options - now time.Time - signingKey *jose.JSONWebKey - pubKeys []*jose.JSONWebKey - claims string - want *user.DefaultInfo - wantSkip bool - wantErr bool - wantInitErr bool + name string + options Options + now time.Time + signingKey *jose.JSONWebKey + pubKeys []*jose.JSONWebKey + claims string + want *user.DefaultInfo + wantSkip bool + wantErr bool + wantInitErr bool + claimToResponseMap map[string]string + openIDConfig string +} + +// Replace formats the contents of v into the provided template. +func replace(tmpl string, v interface{}) string { + t := template.Must(template.New("test").Parse(tmpl)) + buf := bytes.NewBuffer(nil) + t.Execute(buf, &v) + ret := buf.String() + glog.V(4).Infof("Replaced: %v into: %v", tmpl, ret) + return ret +} + +// newClaimServer returns a new test HTTPS server, which is rigged to return +// OIDC responses to requests that resolve distributed claims. signer is the +// signer used for the served JWT tokens. claimToResponseMap is a map of +// responses that the server will return for each claim it is given. +func newClaimServer(t *testing.T, keys jose.JSONWebKeySet, signer jose.Signer, claimToResponseMap map[string]string, openIDConfig *string) *httptest.Server { + ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + glog.V(5).Infof("request: %+v", *r) + switch r.URL.Path { + case "/.testing/keys": + w.Header().Set("Content-Type", "application/json") + keyBytes, err := json.Marshal(keys) + if err != nil { + t.Fatalf("unexpected error while marshaling keys: %v", err) + } + glog.V(5).Infof("%v: returning: %+v", r.URL, string(keyBytes)) + w.Write(keyBytes) + + case "/.well-known/openid-configuration": + w.Header().Set("Content-Type", "application/json") + glog.V(5).Infof("%v: returning: %+v", r.URL, *openIDConfig) + w.Write([]byte(*openIDConfig)) + // These claims are tested in the unit tests. + case "/groups": + fallthrough + case "/rabbits": + if claimToResponseMap == nil { + t.Errorf("no claims specified in response") + } + claim := r.URL.Path[1:] // "/groups" -> "groups" + expectedAuth := fmt.Sprintf("Bearer %v_token", claim) + auth := r.Header.Get("Authorization") + if auth != expectedAuth { + t.Errorf("bearer token expected: %q, was %q", expectedAuth, auth) + } + jws, err := signer.Sign([]byte(claimToResponseMap[claim])) + if err != nil { + t.Errorf("while signing response token: %v", err) + } + token, err := jws.CompactSerialize() + if err != nil { + t.Errorf("while serializing response token: %v", err) + } + w.Write([]byte(token)) + default: + w.WriteHeader(http.StatusNotFound) + fmt.Fprintf(w, "unexpected URL: %v", r.URL) + } + })) + glog.V(4).Infof("Serving OIDC at: %v", ts.URL) + return ts +} + +// writeTempCert writes out the supplied certificate into a temporary file in +// PEM-encoded format. Returns the name of the temporary file used. The caller +// is responsible for cleaning the file up. +func writeTempCert(t *testing.T, cert []byte) string { + tempFile, err := ioutil.TempFile("", "ca.crt") + if err != nil { + t.Fatalf("could not open temp file: %v", err) + } + block := &pem.Block{ + Type: "CERTIFICATE", + Bytes: cert, + } + if err := pem.Encode(tempFile, block); err != nil { + t.Fatalf("could not write to temp file %v: %v", tempFile.Name(), err) + } + tempFile.Close() + return tempFile.Name() +} + +func toKeySet(keys []*jose.JSONWebKey) jose.JSONWebKeySet { + ret := jose.JSONWebKeySet{} + for _, k := range keys { + ret.Keys = append(ret.Keys, *k) + } + return ret } func (c *claimsTest) run(t *testing.T) { + var ( + signer jose.Signer + err error + ) + if c.signingKey != nil { + // Initialize the signer only in the tests that make use of it. We can + // not defer this initialization because the test server uses it too. + signer, err = jose.NewSigner(jose.SigningKey{ + Algorithm: jose.SignatureAlgorithm(c.signingKey.Algorithm), + Key: c.signingKey, + }, nil) + if err != nil { + t.Fatalf("initialize signer: %v", err) + } + } + // The HTTPS server used for requesting distributed groups claims. + ts := newClaimServer(t, toKeySet(c.pubKeys), signer, c.claimToResponseMap, &c.openIDConfig) + defer ts.Close() + + // Make the certificate of the helper server available to the authenticator + // by writing its root CA certificate into a temporary file. + tempFileName := writeTempCert(t, ts.TLS.Certificates[0].Certificate[0]) + defer os.Remove(tempFileName) + c.options.CAFile = tempFileName + + // Allow claims to refer to the serving URL of the test server. For this, + // substitute all references to {{.URL}} in appropriate places. + v := struct{ URL string }{URL: ts.URL} + c.claims = replace(c.claims, &v) + c.openIDConfig = replace(c.openIDConfig, &v) + c.options.IssuerURL = replace(c.options.IssuerURL, &v) + for claim, response := range c.claimToResponseMap { + c.claimToResponseMap[claim] = replace(response, &v) + } + + // Initialize the authenticator. a, err := newAuthenticator(c.options, func(ctx context.Context, a *Authenticator, config *oidc.Config) { - // Set the verifier to use the public key set instead of reading - // from a remote. + // Set the verifier to use the public key set instead of reading from a remote. a.setVerifier(oidc.NewVerifier( c.options.IssuerURL, &staticKeySet{keys: c.pubKeys}, @@ -155,13 +287,6 @@ func (c *claimsTest) run(t *testing.T) { } // Sign and serialize the claims in a JWT. - signer, err := jose.NewSigner(jose.SigningKey{ - Algorithm: jose.SignatureAlgorithm(c.signingKey.Algorithm), - Key: c.signingKey, - }, nil) - if err != nil { - t.Fatalf("initialize signer: %v", err) - } jws, err := signer.Sign([]byte(c.claims)) if err != nil { t.Fatalf("sign claims: %v", err) @@ -200,6 +325,7 @@ func (c *claimsTest) run(t *testing.T) { } func TestToken(t *testing.T) { + synchronizeTokenIDVerifierForTest = true tests := []claimsTest{ { name: "token", @@ -287,7 +413,7 @@ func TestToken(t *testing.T) { wantErr: true, }, { - // If "email_verified" isn't present, assume false + // If "email_verified" isn't present, assume true name: "no-email-verified-claim", options: Options{ IssuerURL: "https://auth.example.com", @@ -305,6 +431,30 @@ func TestToken(t *testing.T) { "email": "jane@example.com", "exp": %d }`, valid.Unix()), + want: &user.DefaultInfo{ + Name: "jane@example.com", + }, + }, + { + name: "invalid-email-verified-claim", + options: Options{ + IssuerURL: "https://auth.example.com", + ClientID: "my-client", + UsernameClaim: "email", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + // string value for "email_verified" + claims: fmt.Sprintf(`{ + "iss": "https://auth.example.com", + "aud": "my-client", + "email": "jane@example.com", + "email_verified": "false", + "exp": %d + }`, valid.Unix()), wantErr: true, }, { @@ -332,6 +482,353 @@ func TestToken(t *testing.T) { Groups: []string{"team1", "team2"}, }, }, + { + name: "groups-distributed", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "groups": "src1" + }, + "_claim_sources": { + "src1": { + "endpoint": "{{.URL}}/groups", + "access_token": "groups_token" + } + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + "groups": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "groups": ["team1", "team2"], + "exp": %d + }`, valid.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + want: &user.DefaultInfo{ + Name: "jane", + Groups: []string{"team1", "team2"}, + }, + }, + { + name: "groups-distributed-malformed-claim-names", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "groups": "nonexistent-claim-source" + }, + "_claim_sources": { + "src1": { + "endpoint": "{{.URL}}/groups", + "access_token": "groups_token" + } + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + "groups": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "groups": ["team1", "team2"], + "exp": %d + }`, valid.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + wantErr: true, + }, + { + name: "groups-distributed-malformed-names-and-sources", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "groups": "src1" + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + "groups": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "groups": ["team1", "team2"], + "exp": %d + }`, valid.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + wantErr: true, + }, + { + name: "groups-distributed-malformed-distributed-claim", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "groups": "src1" + }, + "_claim_sources": { + "src1": { + "endpoint": "{{.URL}}/groups", + "access_token": "groups_token" + } + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + // Doesn't contain the "groups" claim as it promises. + "groups": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "exp": %d + }`, valid.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + wantErr: true, + }, + { + name: "groups-distributed-unusual-name", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "rabbits", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "rabbits": "src1" + }, + "_claim_sources": { + "src1": { + "endpoint": "{{.URL}}/rabbits", + "access_token": "rabbits_token" + } + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + "rabbits": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "rabbits": ["team1", "team2"], + "exp": %d + }`, valid.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + want: &user.DefaultInfo{ + Name: "jane", + Groups: []string{"team1", "team2"}, + }, + }, + { + name: "groups-distributed-wrong-audience", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "groups": "src1" + }, + "_claim_sources": { + "src1": { + "endpoint": "{{.URL}}/groups", + "access_token": "groups_token" + } + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + // Note mismatching "aud" + "groups": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "your-client", + "groups": ["team1", "team2"], + "exp": %d + }`, valid.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + // "aud" was "your-client", not "my-client" + wantErr: true, + }, + { + name: "groups-distributed-wrong-audience", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "groups": "src1" + }, + "_claim_sources": { + "src1": { + "endpoint": "{{.URL}}/groups", + "access_token": "groups_token" + } + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + // Note expired timestamp. + "groups": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "groups": ["team1", "team2"], + "exp": %d + }`, expired.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + // The distributed token is expired. + wantErr: true, + }, + { + // Specs are unclear about this behavior. We adopt a behavior where + // normal claim wins over a distributed claim by the same name. + name: "groups-distributed-normal-claim-wins", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "groups": "team1", + "_claim_names": { + "groups": "src1" + }, + "_claim_sources": { + "src1": { + "endpoint": "{{.URL}}/groups", + "access_token": "groups_token" + } + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + "groups": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "groups": ["team2"], + "exp": %d + }`, valid.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + want: &user.DefaultInfo{ + Name: "jane", + // "team1" is from the normal "groups" claim. + Groups: []string{"team1"}, + }, + }, { // Groups should be able to be a single string, not just a slice. name: "group-string-claim", @@ -358,6 +855,83 @@ func TestToken(t *testing.T) { Groups: []string{"team1"}, }, }, + { + // Groups should be able to be a single string, not just a slice. + name: "group-string-claim-distributed", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "groups": "src1" + }, + "_claim_sources": { + "src1": { + "endpoint": "{{.URL}}/groups", + "access_token": "groups_token" + } + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + "groups": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "groups": "team1", + "exp": %d + }`, valid.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + want: &user.DefaultInfo{ + Name: "jane", + Groups: []string{"team1"}, + }, + }, + { + name: "group-string-claim-aggregated-not-supported", + options: Options{ + IssuerURL: "https://auth.example.com", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "https://auth.example.com", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "groups": "src1" + }, + "_claim_sources": { + "src1": { + "JWT": "some.jwt.token" + } + }, + "exp": %d + }`, valid.Unix()), + want: &user.DefaultInfo{ + Name: "jane", + }, + }, { // if the groups claim isn't provided, this shouldn't error out name: "no-groups-claim", @@ -404,6 +978,84 @@ func TestToken(t *testing.T) { }`, valid.Unix()), wantErr: true, }, + { + name: "required-claim", + options: Options{ + IssuerURL: "https://auth.example.com", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + RequiredClaims: map[string]string{ + "hd": "example.com", + "sub": "test", + }, + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "https://auth.example.com", + "aud": "my-client", + "username": "jane", + "hd": "example.com", + "sub": "test", + "exp": %d + }`, valid.Unix()), + want: &user.DefaultInfo{ + Name: "jane", + }, + }, + { + name: "no-required-claim", + options: Options{ + IssuerURL: "https://auth.example.com", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + RequiredClaims: map[string]string{ + "hd": "example.com", + }, + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "https://auth.example.com", + "aud": "my-client", + "username": "jane", + "exp": %d + }`, valid.Unix()), + wantErr: true, + }, + { + name: "invalid-required-claim", + options: Options{ + IssuerURL: "https://auth.example.com", + ClientID: "my-client", + UsernameClaim: "username", + GroupsClaim: "groups", + RequiredClaims: map[string]string{ + "hd": "example.com", + }, + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "https://auth.example.com", + "aud": "my-client", + "username": "jane", + "hd": "example.org", + "exp": %d + }`, valid.Unix()), + wantErr: true, + }, { name: "invalid-signature", options: Options{ @@ -559,6 +1211,53 @@ func TestToken(t *testing.T) { Groups: []string{"groups:team1", "groups:team2"}, }, }, + { + name: "groups-prefix-distributed", + options: Options{ + IssuerURL: "{{.URL}}", + ClientID: "my-client", + UsernameClaim: "username", + UsernamePrefix: "oidc:", + GroupsClaim: "groups", + GroupsPrefix: "groups:", + now: func() time.Time { return now }, + }, + signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256), + pubKeys: []*jose.JSONWebKey{ + loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256), + }, + claims: fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "username": "jane", + "_claim_names": { + "groups": "src1" + }, + "_claim_sources": { + "src1": { + "endpoint": "{{.URL}}/groups", + "access_token": "groups_token" + } + }, + "exp": %d + }`, valid.Unix()), + claimToResponseMap: map[string]string{ + "groups": fmt.Sprintf(`{ + "iss": "{{.URL}}", + "aud": "my-client", + "groups": ["team1", "team2"], + "exp": %d + }`, valid.Unix()), + }, + openIDConfig: `{ + "issuer": "{{.URL}}", + "jwks_uri": "{{.URL}}/.testing/keys" + }`, + want: &user.DefaultInfo{ + Name: "oidc:jane", + Groups: []string{"groups:team1", "groups:team2"}, + }, + }, { name: "invalid-signing-alg", options: Options{ diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/testdata/gen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/testdata/gen.sh index a3daa0fc4..922e64e5a 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/testdata/gen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/testdata/gen.sh @@ -1,4 +1,4 @@ -#!/bin/bash -e +#!/usr/bin/env bash -e # Copyright 2018 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/BUILD index 5da907a97..4cd60e841 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/BUILD @@ -26,10 +26,12 @@ go_library( srcs = ["webhook.go"], importpath = "k8s.io/apiserver/plugin/pkg/authenticator/token/webhook", deps = [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/authentication/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered: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/util/cache:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/webhook:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook.go index b1f6420ea..7aa1c0c0a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook.go @@ -18,13 +18,15 @@ limitations under the License. package webhook import ( - "fmt" "time" + "github.com/golang/glog" + authentication "k8s.io/api/authentication/v1beta1" - "k8s.io/apimachinery/pkg/apimachinery/registered" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/cache" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/util/webhook" @@ -84,6 +86,8 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(token string) (user.Info, return err }) if err != nil { + // An error here indicates bad configuration or an outage. Log for debugging. + glog.Errorf("Failed to make webhook authenticator request: %v", err) return nil, false, err } r.Status = result.Status @@ -109,24 +113,15 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(token string) (user.Info, }, true, nil } -// NOTE: client-go doesn't provide a registry. client-go does registers the -// authentication/v1beta1. We construct a registry that acknowledges -// authentication/v1beta1 as an enabled version to pass a check enforced in -// NewGenericWebhook. -var registry = registered.NewOrDie("") - -func init() { - registry.RegisterVersions(groupVersions) - if err := registry.EnableVersions(groupVersions...); err != nil { - panic(fmt.Sprintf("failed to enable version %v", groupVersions)) - } -} - // tokenReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file, // and returns a TokenReviewInterface that uses that client. Note that the client submits TokenReview // requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted. func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string) (authenticationclient.TokenReviewInterface, error) { - gw, err := webhook.NewGenericWebhook(registry, scheme.Codecs, kubeConfigFile, groupVersions, 0) + localScheme := runtime.NewScheme() + scheme.AddToScheme(localScheme) + utilruntime.Must(localScheme.SetVersionPriority(groupVersions...)) + + gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/BUILD index 08acf7b84..a1099d8e4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/BUILD @@ -30,7 +30,7 @@ go_library( deps = [ "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/authorization/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered: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/util/cache:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/gencerts.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/gencerts.sh index 8d7896fa5..1e5fb1fd5 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/gencerts.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/gencerts.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go index d00e65be5..83157c48c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go @@ -25,7 +25,7 @@ import ( "github.com/golang/glog" authorization "k8s.io/api/authorization/v1beta1" - "k8s.io/apimachinery/pkg/apimachinery/registered" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/cache" "k8s.io/apiserver/pkg/authentication/user" @@ -234,24 +234,15 @@ func convertToSARExtra(extra map[string][]string) map[string]authorization.Extra return ret } -// NOTE: client-go doesn't provide a registry. client-go does registers the -// authorization/v1beta1. We construct a registry that acknowledges -// authorization/v1beta1 as an enabled version to pass a check enforced in -// NewGenericWebhook. -var registry = registered.NewOrDie("") - -func init() { - registry.RegisterVersions(groupVersions) - if err := registry.EnableVersions(groupVersions...); err != nil { - panic(fmt.Sprintf("failed to enable version %v", groupVersions)) - } -} - // subjectAccessReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file, // and returns a SubjectAccessReviewInterface that uses that client. Note that the client submits SubjectAccessReview // requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted. func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string) (authorizationclient.SubjectAccessReviewInterface, error) { - gw, err := webhook.NewGenericWebhook(registry, scheme.Codecs, kubeConfigFile, groupVersions, 0) + localScheme := runtime.NewScheme() + scheme.AddToScheme(localScheme) + localScheme.SetVersionPriority(groupVersions...) + + gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md index e559c074b..6aed9889c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/.github/PULL_REQUEST_TEMPLATE.md @@ -1,2 +1,3 @@ -Sorry, we do not accept changes directly against this repository. Please see -CONTRIBUTING.md for information on where and how to contribute instead. +Sorry, we do not accept changes directly against this repository, unless the +change is to the `README.md` itself. Please see +`CONTRIBUTING.md` for information on where and how to contribute instead. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/Godeps/Godeps.json index a83dfa86b..edd6f7296 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "k8s.io/client-go", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], @@ -16,19 +16,19 @@ }, { "ImportPath": "github.com/Azure/go-autorest/autorest", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/adal", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/azure", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/Azure/go-autorest/autorest/date", - "Rev": "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab" + "Rev": "1ff28809256a84bb6966640ff3d0371af82ccba4" }, { "ImportPath": "github.com/davecgh/go-spew/spew", @@ -68,23 +68,27 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/google/btree", + "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" }, { "ImportPath": "github.com/google/gofuzz", @@ -104,31 +108,39 @@ }, { "ImportPath": "github.com/gophercloud/gophercloud", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/openstack/utils", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" }, { "ImportPath": "github.com/gophercloud/gophercloud/pagination", - "Rev": "6da026c32e2d622cc242d32984259c77237aefe1" + "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" + }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" }, { "ImportPath": "github.com/hashicorp/golang-lru", @@ -138,17 +150,25 @@ "ImportPath": "github.com/hashicorp/golang-lru/simplelru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" }, - { - "ImportPath": "github.com/howeyc/gopass", - "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" - }, { "ImportPath": "github.com/imdario/mergo", "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" + }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" }, { "ImportPath": "github.com/pmezard/go-difflib/difflib", @@ -160,11 +180,11 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/net/context", @@ -346,6 +366,10 @@ "ImportPath": "k8s.io/api/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -390,18 +414,6 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -576,7 +588,7 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/OWNERS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/OWNERS index 44a4c9e1f..b39916829 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/OWNERS +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/OWNERS @@ -1,44 +1,15 @@ approvers: - caesarxuchao - deads2k -- krousey - lavalamp +- liggitt - smarterclayton - sttts -- liggitt reviewers: -- thockin -- lavalamp -- smarterclayton -- wojtek-t -- deads2k -- yujuhong -- derekwaynecarr - caesarxuchao -- vishh -- mikedanese +- deads2k +- lavalamp - liggitt -- nikhiljindal -- gmarek -- erictune -- davidopp -- pmorie -- sttts -- dchen1107 -- saad-ali -- zmerlynn -- luxas -- janetkuo -- justinsb -- roberthbailey -- ncdc -- tallclair -- yifan-gu -- eparis -- mwielgus -- timothysc -- feiskyer -- jlowdermilk - soltysh -- piosz -- jsafrane +- sttts +- yliaog diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/BUILD new file mode 100644 index 000000000..530e34285 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/BUILD @@ -0,0 +1,56 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "bad_debt.go", + "client.go", + "client_pool.go", + ], + importpath = "k8s.io/client-go/deprecated-dynamic", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/dynamic:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["client_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/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/streaming:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/rest/watch:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/bad_debt.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/bad_debt.go new file mode 100644 index 000000000..51e4a5830 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/bad_debt.go @@ -0,0 +1,79 @@ +/* +Copyright 2018 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 deprecated_dynamic + +import ( + "encoding/json" + "io" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" +) + +// dynamicCodec is a codec that wraps the standard unstructured codec +// with special handling for Status objects. +// Deprecated only used by test code and its wrong +type dynamicCodec struct{} + +func (dynamicCodec) Decode(data []byte, gvk *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { + obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(data, gvk, obj) + if err != nil { + return nil, nil, err + } + + if _, ok := obj.(*metav1.Status); !ok && strings.ToLower(gvk.Kind) == "status" { + obj = &metav1.Status{} + err := json.Unmarshal(data, obj) + if err != nil { + return nil, nil, err + } + } + + return obj, gvk, nil +} + +func (dynamicCodec) Encode(obj runtime.Object, w io.Writer) error { + return unstructured.UnstructuredJSONScheme.Encode(obj, w) +} + +// ContentConfig returns a rest.ContentConfig for dynamic types. +// Deprecated only used by test code and its wrong +func ContentConfig() rest.ContentConfig { + var jsonInfo runtime.SerializerInfo + // TODO: scheme.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need + // to talk to a kubernetes server + for _, info := range scheme.Codecs.SupportedMediaTypes() { + if info.MediaType == runtime.ContentTypeJSON { + jsonInfo = info + break + } + } + + jsonInfo.Serializer = dynamicCodec{} + jsonInfo.PrettySerializer = nil + return rest.ContentConfig{ + AcceptContentTypes: runtime.ContentTypeJSON, + ContentType: runtime.ContentTypeJSON, + NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo), + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/client.go new file mode 100644 index 000000000..0974fe64d --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/client.go @@ -0,0 +1,131 @@ +/* +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 dynamic provides a client interface to arbitrary Kubernetes +// APIs that exposes common high level operations and exposes common +// metadata. +package deprecated_dynamic + +import ( + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/dynamic" + restclient "k8s.io/client-go/rest" +) + +// Interface is a Kubernetes client that allows you to access metadata +// and manipulate metadata of a Kubernetes API group. +type Interface interface { + // Resource returns an API interface to the specified resource for this client's + // group and version. If resource is not a namespaced resource, then namespace + // is ignored. The ResourceInterface inherits the parameter codec of this client. + Resource(resource *metav1.APIResource, namespace string) ResourceInterface +} + +// ResourceInterface is an API interface to a specific resource under a +// dynamic client. +type ResourceInterface interface { + // List returns a list of objects for this resource. + List(opts metav1.ListOptions) (runtime.Object, error) + // Get gets the resource with the specified name. + Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) + // Delete deletes the resource with the specified name. + Delete(name string, opts *metav1.DeleteOptions) error + // DeleteCollection deletes a collection of objects. + DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error + // Create creates the provided resource. + Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) + // Update updates the provided resource. + Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) + // Watch returns a watch.Interface that watches the resource. + Watch(opts metav1.ListOptions) (watch.Interface, error) + // Patch patches the provided resource. + Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) +} + +// Client is a Kubernetes client that allows you to access metadata +// and manipulate metadata of a Kubernetes API group, and implements Interface. +type Client struct { + version schema.GroupVersion + delegate dynamic.Interface +} + +// NewClient returns a new client based on the passed in config. The +// codec is ignored, as the dynamic client uses it's own codec. +func NewClient(conf *restclient.Config, version schema.GroupVersion) (*Client, error) { + delegate, err := dynamic.NewForConfig(conf) + if err != nil { + return nil, err + } + + return &Client{version: version, delegate: delegate}, nil +} + +// Resource returns an API interface to the specified resource for this client's +// group and version. If resource is not a namespaced resource, then namespace +// is ignored. The ResourceInterface inherits the parameter codec of c. +func (c *Client) Resource(resource *metav1.APIResource, namespace string) ResourceInterface { + resourceTokens := strings.SplitN(resource.Name, "/", 2) + subresources := []string{} + if len(resourceTokens) > 1 { + subresources = strings.Split(resourceTokens[1], "/") + } + + if len(namespace) == 0 { + return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])), subresources) + } + return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])).Namespace(namespace), subresources) +} + +// the old interfaces used the wrong type for lists. this fixes that +func oldResourceShim(in dynamic.ResourceInterface, subresources []string) ResourceInterface { + return oldResourceShimType{ResourceInterface: in, subresources: subresources} +} + +type oldResourceShimType struct { + dynamic.ResourceInterface + subresources []string +} + +func (s oldResourceShimType) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + return s.ResourceInterface.Create(obj, s.subresources...) +} + +func (s oldResourceShimType) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + return s.ResourceInterface.Update(obj, s.subresources...) +} + +func (s oldResourceShimType) Delete(name string, opts *metav1.DeleteOptions) error { + return s.ResourceInterface.Delete(name, opts, s.subresources...) +} + +func (s oldResourceShimType) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) { + return s.ResourceInterface.Get(name, opts, s.subresources...) +} + +func (s oldResourceShimType) List(opts metav1.ListOptions) (runtime.Object, error) { + return s.ResourceInterface.List(opts) +} + +func (s oldResourceShimType) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) { + return s.ResourceInterface.Patch(name, pt, data, s.subresources...) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/client_pool.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/client_pool.go new file mode 100644 index 000000000..36dc54ce4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/client_pool.go @@ -0,0 +1,122 @@ +/* +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 deprecated_dynamic + +import ( + "sync" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" + restclient "k8s.io/client-go/rest" +) + +// ClientPool manages a pool of dynamic clients. +type ClientPool interface { + // ClientForGroupVersionResource returns a client configured for the specified groupVersionResource. + // Resource may be empty. + ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error) + // ClientForGroupVersionKind returns a client configured for the specified groupVersionKind. + // Kind may be empty. + ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error) +} + +// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is +// optional. +type APIPathResolverFunc func(kind schema.GroupVersionKind) string + +// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API. +func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string { + if len(kind.Group) == 0 { + return "/api" + } + return "/apis" +} + +// clientPoolImpl implements ClientPool and caches clients for the resource group versions +// is asked to retrieve. This type is thread safe. +type clientPoolImpl struct { + lock sync.RWMutex + config *restclient.Config + clients map[schema.GroupVersion]*Client + apiPathResolverFunc APIPathResolverFunc + mapper meta.RESTMapper +} + +// NewClientPool returns a ClientPool from the specified config. It reuses clients for the same +// group version. It is expected this type may be wrapped by specific logic that special cases certain +// resources or groups. +func NewClientPool(config *restclient.Config, mapper meta.RESTMapper, apiPathResolverFunc APIPathResolverFunc) ClientPool { + confCopy := *config + + return &clientPoolImpl{ + config: &confCopy, + clients: map[schema.GroupVersion]*Client{}, + apiPathResolverFunc: apiPathResolverFunc, + mapper: mapper, + } +} + +// Instantiates a new dynamic client pool with the given config. +func NewDynamicClientPool(cfg *restclient.Config) ClientPool { + // restMapper is not needed when using LegacyAPIPathResolverFunc + emptyMapper := meta.MultiRESTMapper{} + return NewClientPool(cfg, emptyMapper, LegacyAPIPathResolverFunc) +} + +// ClientForGroupVersionResource uses the provided RESTMapper to identify the appropriate resource. Resource may +// be empty. If no matching kind is found the underlying client for that group is still returned. +func (c *clientPoolImpl) ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error) { + kinds, err := c.mapper.KindsFor(resource) + if err != nil { + if meta.IsNoMatchError(err) { + return c.ClientForGroupVersionKind(schema.GroupVersionKind{Group: resource.Group, Version: resource.Version}) + } + return nil, err + } + return c.ClientForGroupVersionKind(kinds[0]) +} + +// ClientForGroupVersion returns a client for the specified groupVersion, creates one if none exists. Kind +// in the GroupVersionKind may be empty. +func (c *clientPoolImpl) ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error) { + c.lock.Lock() + defer c.lock.Unlock() + + gv := kind.GroupVersion() + + // do we have a client already configured? + if existingClient, found := c.clients[gv]; found { + return existingClient, nil + } + + // avoid changing the original config + confCopy := *c.config + conf := &confCopy + + // we need to set the api path based on group version, if no group, default to legacy path + conf.APIPath = c.apiPathResolverFunc(kind) + + // we need to make a client + conf.GroupVersion = &gv + + dynamicClient, err := NewClient(conf, gv) + if err != nil { + return nil, err + } + c.clients[gv] = dynamicClient + return dynamicClient, nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/client_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/client_test.go new file mode 100644 index 000000000..790474522 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/deprecated-dynamic/client_test.go @@ -0,0 +1,623 @@ +/* +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 deprecated_dynamic + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "reflect" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer/streaming" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + restclient "k8s.io/client-go/rest" + restclientwatch "k8s.io/client-go/rest/watch" +) + +func getJSON(version, kind, name string) []byte { + return []byte(fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "metadata": {"name": %q}}`, version, kind, name)) +} + +func getListJSON(version, kind string, items ...[]byte) []byte { + json := fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "items": [%s]}`, + version, kind, bytes.Join(items, []byte(","))) + return []byte(json) +} + +func getObject(version, kind, name string) *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": version, + "kind": kind, + "metadata": map[string]interface{}{ + "name": name, + }, + }, + } +} + +func getClientServer(gv *schema.GroupVersion, h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) { + srv := httptest.NewServer(http.HandlerFunc(h)) + cl, err := NewClient(&restclient.Config{ + Host: srv.URL, + ContentConfig: restclient.ContentConfig{GroupVersion: gv}, + }, *gv) + if err != nil { + srv.Close() + return nil, nil, err + } + return cl, srv, nil +} + +func TestList(t *testing.T) { + tcs := []struct { + name string + namespace string + path string + resp []byte + want *unstructured.UnstructuredList + }{ + { + name: "normal_list", + path: "/apis/gtest/vtest/rtest", + resp: getListJSON("vTest", "rTestList", + getJSON("vTest", "rTest", "item1"), + getJSON("vTest", "rTest", "item2")), + want: &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "apiVersion": "vTest", + "kind": "rTestList", + }, + Items: []unstructured.Unstructured{ + *getObject("vTest", "rTest", "item1"), + *getObject("vTest", "rTest", "item2"), + }, + }, + }, + { + name: "namespaced_list", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + resp: getListJSON("vTest", "rTestList", + getJSON("vTest", "rTest", "item1"), + getJSON("vTest", "rTest", "item2")), + want: &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "apiVersion": "vTest", + "kind": "rTestList", + }, + Items: []unstructured.Unstructured{ + *getObject("vTest", "rTest", "item1"), + *getObject("vTest", "rTest", "item2"), + }, + }, + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("List(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + w.Write(tc.resp) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).List(metav1.ListOptions{}) + if err != nil { + t.Errorf("unexpected error when listing %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("List(%q) want: %v\ngot: %v", tc.name, tc.want, got) + } + } +} + +func TestGet(t *testing.T) { + tcs := []struct { + resource string + namespace string + name string + path string + resp []byte + want *unstructured.Unstructured + }{ + { + resource: "rtest", + name: "normal_get", + path: "/apis/gtest/vtest/rtest/normal_get", + resp: getJSON("vTest", "rTest", "normal_get"), + want: getObject("vTest", "rTest", "normal_get"), + }, + { + resource: "rtest", + namespace: "nstest", + name: "namespaced_get", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_get", + resp: getJSON("vTest", "rTest", "namespaced_get"), + want: getObject("vTest", "rTest", "namespaced_get"), + }, + { + resource: "rtest/srtest", + name: "normal_subresource_get", + path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest", + resp: getJSON("vTest", "srTest", "normal_subresource_get"), + want: getObject("vTest", "srTest", "normal_subresource_get"), + }, + { + resource: "rtest/srtest", + namespace: "nstest", + name: "namespaced_subresource_get", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest", + resp: getJSON("vTest", "srTest", "namespaced_subresource_get"), + want: getObject("vTest", "srTest", "namespaced_subresource_get"), + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Get(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + w.Write(tc.resp) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).Get(tc.name, metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error when getting %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("Get(%q) want: %v\ngot: %v", tc.name, tc.want, got) + } + } +} + +func TestDelete(t *testing.T) { + background := metav1.DeletePropagationBackground + uid := types.UID("uid") + + statusOK := &metav1.Status{ + TypeMeta: metav1.TypeMeta{Kind: "Status"}, + Status: metav1.StatusSuccess, + } + tcs := []struct { + namespace string + name string + path string + deleteOptions *metav1.DeleteOptions + }{ + { + name: "normal_delete", + path: "/apis/gtest/vtest/rtest/normal_delete", + }, + { + namespace: "nstest", + name: "namespaced_delete", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete", + }, + { + namespace: "nstest", + name: "namespaced_delete_with_options", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete_with_options", + deleteOptions: &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}, PropagationPolicy: &background}, + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "DELETE" { + t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Delete(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + unstructured.UnstructuredJSONScheme.Encode(statusOK, w) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + err = cl.Resource(resource, tc.namespace).Delete(tc.name, tc.deleteOptions) + if err != nil { + t.Errorf("unexpected error when deleting %q: %v", tc.name, err) + continue + } + } +} + +func TestDeleteCollection(t *testing.T) { + statusOK := &metav1.Status{ + TypeMeta: metav1.TypeMeta{Kind: "Status"}, + Status: metav1.StatusSuccess, + } + tcs := []struct { + namespace string + name string + path string + }{ + { + name: "normal_delete_collection", + path: "/apis/gtest/vtest/rtest", + }, + { + namespace: "nstest", + name: "namespaced_delete_collection", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "DELETE" { + t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("DeleteCollection(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + unstructured.UnstructuredJSONScheme.Encode(statusOK, w) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + err = cl.Resource(resource, tc.namespace).DeleteCollection(nil, metav1.ListOptions{}) + if err != nil { + t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err) + continue + } + } +} + +func TestCreate(t *testing.T) { + tcs := []struct { + resource string + name string + namespace string + obj *unstructured.Unstructured + path string + }{ + { + resource: "rtest", + name: "normal_create", + path: "/apis/gtest/vtest/rtest", + obj: getObject("gtest/vTest", "rTest", "normal_create"), + }, + { + resource: "rtest", + name: "namespaced_create", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + obj: getObject("gtest/vTest", "rTest", "namespaced_create"), + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "POST" { + t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Create(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + data, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Errorf("Create(%q) unexpected error reading body: %v", tc.name, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.Write(data) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).Create(tc.obj) + if err != nil { + t.Errorf("unexpected error when creating %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.obj) { + t.Errorf("Create(%q) want: %v\ngot: %v", tc.name, tc.obj, got) + } + } +} + +func TestUpdate(t *testing.T) { + tcs := []struct { + resource string + name string + namespace string + obj *unstructured.Unstructured + path string + }{ + { + resource: "rtest", + name: "normal_update", + path: "/apis/gtest/vtest/rtest/normal_update", + obj: getObject("gtest/vTest", "rTest", "normal_update"), + }, + { + resource: "rtest", + name: "namespaced_update", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update", + obj: getObject("gtest/vTest", "rTest", "namespaced_update"), + }, + { + resource: "rtest/srtest", + name: "normal_subresource_update", + path: "/apis/gtest/vtest/rtest/normal_update/srtest", + obj: getObject("gtest/vTest", "srTest", "normal_update"), + }, + { + resource: "rtest/srtest", + name: "namespaced_subresource_update", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest", + obj: getObject("gtest/vTest", "srTest", "namespaced_update"), + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "PUT" { + t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Update(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + data, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Errorf("Update(%q) unexpected error reading body: %v", tc.name, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.Write(data) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).Update(tc.obj) + if err != nil { + t.Errorf("unexpected error when updating %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.obj) { + t.Errorf("Update(%q) want: %v\ngot: %v", tc.name, tc.obj, got) + } + } +} + +func TestWatch(t *testing.T) { + tcs := []struct { + name string + namespace string + events []watch.Event + path string + query string + }{ + { + name: "normal_watch", + path: "/apis/gtest/vtest/rtest", + query: "watch=true", + events: []watch.Event{ + {Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + {Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + {Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + }, + }, + { + name: "namespaced_watch", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + query: "watch=true", + events: []watch.Event{ + {Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + {Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + {Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + }, + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Watch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + if r.URL.RawQuery != tc.query { + t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query) + } + + enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{}) + for _, e := range tc.events { + enc.Encode(&e) + } + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + watcher, err := cl.Resource(resource, tc.namespace).Watch(metav1.ListOptions{}) + if err != nil { + t.Errorf("unexpected error when watching %q: %v", tc.name, err) + continue + } + + for _, want := range tc.events { + got := <-watcher.ResultChan() + if !reflect.DeepEqual(got, want) { + t.Errorf("Watch(%q) want: %v\ngot: %v", tc.name, want, got) + } + } + } +} + +func TestPatch(t *testing.T) { + tcs := []struct { + resource string + name string + namespace string + patch []byte + want *unstructured.Unstructured + path string + }{ + { + resource: "rtest", + name: "normal_patch", + path: "/apis/gtest/vtest/rtest/normal_patch", + patch: getJSON("gtest/vTest", "rTest", "normal_patch"), + want: getObject("gtest/vTest", "rTest", "normal_patch"), + }, + { + resource: "rtest", + name: "namespaced_patch", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_patch", + patch: getJSON("gtest/vTest", "rTest", "namespaced_patch"), + want: getObject("gtest/vTest", "rTest", "namespaced_patch"), + }, + { + resource: "rtest/srtest", + name: "normal_subresource_patch", + path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest", + patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"), + want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"), + }, + { + resource: "rtest/srtest", + name: "namespaced_subresource_patch", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest", + patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"), + want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"), + }, + } + for _, tc := range tcs { + gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} + resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} + cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "PATCH" { + t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method) + } + + if r.URL.Path != tc.path { + t.Errorf("Patch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path) + } + + content := r.Header.Get("Content-Type") + if content != string(types.StrategicMergePatchType) { + t.Errorf("Patch(%q) got Content-Type %s. wanted %s", tc.name, content, types.StrategicMergePatchType) + } + + data, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Errorf("Patch(%q) unexpected error reading body: %v", tc.name, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.Write(data) + }) + if err != nil { + t.Errorf("unexpected error when creating client: %v", err) + continue + } + defer srv.Close() + + got, err := cl.Resource(resource, tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch) + if err != nil { + t.Errorf("unexpected error when patching %q: %v", tc.name, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("Patch(%q) want: %v\ngot: %v", tc.name, tc.want, got) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/BUILD index 19523ba53..bf66795e5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/BUILD @@ -9,9 +9,10 @@ load( go_library( name = "go_default_library", srcs = [ + "cached_discovery.go", "discovery_client.go", "helper.go", - "restmapper.go", + "round_tripper.go", "unstructured.go", ], importpath = "k8s.io/client-go/discovery", @@ -19,12 +20,15 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/protobuf/proto:go_default_library", "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", + "//vendor/github.com/gregjones/httpcache:go_default_library", + "//vendor/github.com/gregjones/httpcache/diskcache:go_default_library", + "//vendor/github.com/peterbourgon/diskv:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", @@ -34,22 +38,13 @@ go_library( go_test( name = "go_default_xtest", - srcs = [ - "discovery_client_test.go", - "helper_blackbox_test.go", - "restmapper_test.go", - ], + srcs = ["helper_blackbox_test.go"], deps = [ - "//vendor/github.com/gogo/protobuf/proto:go_default_library", - "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", - "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", @@ -73,3 +68,26 @@ filegroup( ], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = [ + "cached_discovery_test.go", + "discovery_client_test.go", + "round_tripper_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//vendor/github.com/gogo/protobuf/proto:go_default_library", + "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/rest/fake:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached/memcache.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached/memcache.go index 585b4c80d..d4313bcf3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached/memcache.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached/memcache.go @@ -96,18 +96,12 @@ func (d *memCacheClient) RESTClient() restclient.Interface { return d.delegate.RESTClient() } -// TODO: Should this also be cached? The results seem more likely to be -// inconsistent with ServerGroups and ServerResources given the requirement to -// actively Invalidate. func (d *memCacheClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - return d.delegate.ServerPreferredResources() + return discovery.ServerPreferredResources(d) } -// TODO: Should this also be cached? The results seem more likely to be -// inconsistent with ServerGroups and ServerResources given the requirement to -// actively Invalidate. func (d *memCacheClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { - return d.delegate.ServerPreferredNamespacedResources() + return discovery.ServerPreferredNamespacedResources(d) } func (d *memCacheClient) ServerVersion() (*version.Info, error) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached_discovery.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached_discovery.go new file mode 100644 index 000000000..aca46546e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached_discovery.go @@ -0,0 +1,282 @@ +/* +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 discovery + +import ( + "errors" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "sync" + "time" + + "github.com/golang/glog" + "github.com/googleapis/gnostic/OpenAPIv2" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/version" + "k8s.io/client-go/kubernetes/scheme" + restclient "k8s.io/client-go/rest" +) + +// CachedDiscoveryClient implements the functions that discovery server-supported API groups, +// versions and resources. +type CachedDiscoveryClient struct { + delegate DiscoveryInterface + + // cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well. + cacheDirectory string + + // ttl is how long the cache should be considered valid + ttl time.Duration + + // mutex protects the variables below + mutex sync.Mutex + + // ourFiles are all filenames of cache files created by this process + ourFiles map[string]struct{} + // invalidated is true if all cache files should be ignored that are not ours (e.g. after Invalidate() was called) + invalidated bool + // fresh is true if all used cache files were ours + fresh bool +} + +var _ CachedDiscoveryInterface = &CachedDiscoveryClient{} + +// ServerResourcesForGroupVersion returns the supported resources for a group and version. +func (d *CachedDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + filename := filepath.Join(d.cacheDirectory, groupVersion, "serverresources.json") + cachedBytes, err := d.getCachedFile(filename) + // don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback. + if err == nil { + cachedResources := &metav1.APIResourceList{} + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedResources); err == nil { + glog.V(10).Infof("returning cached discovery info from %v", filename) + return cachedResources, nil + } + } + + liveResources, err := d.delegate.ServerResourcesForGroupVersion(groupVersion) + if err != nil { + glog.V(3).Infof("skipped caching discovery info due to %v", err) + return liveResources, err + } + if liveResources == nil || len(liveResources.APIResources) == 0 { + glog.V(3).Infof("skipped caching discovery info, no resources found") + return liveResources, err + } + + if err := d.writeCachedFile(filename, liveResources); err != nil { + glog.V(3).Infof("failed to write cache to %v due to %v", filename, err) + } + + return liveResources, nil +} + +// ServerResources returns the supported resources for all groups and versions. +func (d *CachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { + return ServerResources(d) +} + +func (d *CachedDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { + filename := filepath.Join(d.cacheDirectory, "servergroups.json") + cachedBytes, err := d.getCachedFile(filename) + // don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback. + if err == nil { + cachedGroups := &metav1.APIGroupList{} + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedGroups); err == nil { + glog.V(10).Infof("returning cached discovery info from %v", filename) + return cachedGroups, nil + } + } + + liveGroups, err := d.delegate.ServerGroups() + if err != nil { + glog.V(3).Infof("skipped caching discovery info due to %v", err) + return liveGroups, err + } + if liveGroups == nil || len(liveGroups.Groups) == 0 { + glog.V(3).Infof("skipped caching discovery info, no groups found") + return liveGroups, err + } + + if err := d.writeCachedFile(filename, liveGroups); err != nil { + glog.V(3).Infof("failed to write cache to %v due to %v", filename, err) + } + + return liveGroups, nil +} + +func (d *CachedDiscoveryClient) getCachedFile(filename string) ([]byte, error) { + // after invalidation ignore cache files not created by this process + d.mutex.Lock() + _, ourFile := d.ourFiles[filename] + if d.invalidated && !ourFile { + d.mutex.Unlock() + return nil, errors.New("cache invalidated") + } + d.mutex.Unlock() + + file, err := os.Open(filename) + if err != nil { + return nil, err + } + defer file.Close() + + fileInfo, err := file.Stat() + if err != nil { + return nil, err + } + + if time.Now().After(fileInfo.ModTime().Add(d.ttl)) { + return nil, errors.New("cache expired") + } + + // the cache is present and its valid. Try to read and use it. + cachedBytes, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + + d.mutex.Lock() + defer d.mutex.Unlock() + d.fresh = d.fresh && ourFile + + return cachedBytes, nil +} + +func (d *CachedDiscoveryClient) writeCachedFile(filename string, obj runtime.Object) error { + if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil { + return err + } + + bytes, err := runtime.Encode(scheme.Codecs.LegacyCodec(), obj) + if err != nil { + return err + } + + f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)+".") + if err != nil { + return err + } + defer os.Remove(f.Name()) + _, err = f.Write(bytes) + if err != nil { + return err + } + + err = os.Chmod(f.Name(), 0755) + if err != nil { + return err + } + + name := f.Name() + err = f.Close() + if err != nil { + return err + } + + // atomic rename + d.mutex.Lock() + defer d.mutex.Unlock() + err = os.Rename(name, filename) + if err == nil { + d.ourFiles[filename] = struct{}{} + } + return err +} + +func (d *CachedDiscoveryClient) RESTClient() restclient.Interface { + return d.delegate.RESTClient() +} + +func (d *CachedDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + return ServerPreferredResources(d) +} + +func (d *CachedDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return ServerPreferredNamespacedResources(d) +} + +func (d *CachedDiscoveryClient) ServerVersion() (*version.Info, error) { + return d.delegate.ServerVersion() +} + +func (d *CachedDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { + return d.delegate.OpenAPISchema() +} + +func (d *CachedDiscoveryClient) Fresh() bool { + d.mutex.Lock() + defer d.mutex.Unlock() + + return d.fresh +} + +func (d *CachedDiscoveryClient) Invalidate() { + d.mutex.Lock() + defer d.mutex.Unlock() + + d.ourFiles = map[string]struct{}{} + d.fresh = true + d.invalidated = true +} + +// NewCachedDiscoveryClientForConfig creates a new DiscoveryClient for the given config, and wraps +// the created client in a CachedDiscoveryClient. The provided configuration is updated with a +// custom transport that understands cache responses. +// We receive two distinct cache directories for now, in order to preserve old behavior +// which makes use of the --cache-dir flag value for storing cache data from the CacheRoundTripper, +// and makes use of the hardcoded destination (~/.kube/cache/discovery/...) for storing +// CachedDiscoveryClient cache data. If httpCacheDir is empty, the restconfig's transport will not +// be updated with a roundtripper that understands cache responses. +// If discoveryCacheDir is empty, cached server resource data will be looked up in the current directory. +// TODO(juanvallejo): the value of "--cache-dir" should be honored. Consolidate discoveryCacheDir with httpCacheDir +// so that server resources and http-cache data are stored in the same location, provided via config flags. +func NewCachedDiscoveryClientForConfig(config *restclient.Config, discoveryCacheDir, httpCacheDir string, ttl time.Duration) (*CachedDiscoveryClient, error) { + if len(httpCacheDir) > 0 { + // update the given restconfig with a custom roundtripper that + // understands how to handle cache responses. + wt := config.WrapTransport + config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { + if wt != nil { + rt = wt(rt) + } + return newCacheRoundTripper(httpCacheDir, rt) + } + } + + discoveryClient, err := NewDiscoveryClientForConfig(config) + if err != nil { + return nil, err + } + + return newCachedDiscoveryClient(discoveryClient, discoveryCacheDir, ttl), nil +} + +// NewCachedDiscoveryClient creates a new DiscoveryClient. cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well. +func newCachedDiscoveryClient(delegate DiscoveryInterface, cacheDirectory string, ttl time.Duration) *CachedDiscoveryClient { + return &CachedDiscoveryClient{ + delegate: delegate, + cacheDirectory: cacheDirectory, + ttl: ttl, + ourFiles: map[string]struct{}{}, + fresh: true, + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached_discovery_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached_discovery_test.go new file mode 100644 index 000000000..278931c2d --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/cached_discovery_test.go @@ -0,0 +1,169 @@ +/* +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 discovery + +import ( + "io/ioutil" + "os" + "testing" + "time" + + "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/stretchr/testify/assert" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/version" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" +) + +func TestCachedDiscoveryClient_Fresh(t *testing.T) { + assert := assert.New(t) + + d, err := ioutil.TempDir("", "") + assert.NoError(err) + defer os.RemoveAll(d) + + c := fakeDiscoveryClient{} + cdc := newCachedDiscoveryClient(&c, d, 60*time.Second) + assert.True(cdc.Fresh(), "should be fresh after creation") + + cdc.ServerGroups() + assert.True(cdc.Fresh(), "should be fresh after groups call without cache") + assert.Equal(c.groupCalls, 1) + + cdc.ServerGroups() + assert.True(cdc.Fresh(), "should be fresh after another groups call") + assert.Equal(c.groupCalls, 1) + + cdc.ServerResources() + assert.True(cdc.Fresh(), "should be fresh after resources call") + assert.Equal(c.resourceCalls, 1) + + cdc.ServerResources() + assert.True(cdc.Fresh(), "should be fresh after another resources call") + assert.Equal(c.resourceCalls, 1) + + cdc = newCachedDiscoveryClient(&c, d, 60*time.Second) + cdc.ServerGroups() + assert.False(cdc.Fresh(), "should NOT be fresh after recreation with existing groups cache") + assert.Equal(c.groupCalls, 1) + + cdc.ServerResources() + assert.False(cdc.Fresh(), "should NOT be fresh after recreation with existing resources cache") + assert.Equal(c.resourceCalls, 1) + + cdc.Invalidate() + assert.True(cdc.Fresh(), "should be fresh after cache invalidation") + + cdc.ServerResources() + assert.True(cdc.Fresh(), "should ignore existing resources cache after invalidation") + assert.Equal(c.resourceCalls, 2) +} + +func TestNewCachedDiscoveryClient_TTL(t *testing.T) { + assert := assert.New(t) + + d, err := ioutil.TempDir("", "") + assert.NoError(err) + defer os.RemoveAll(d) + + c := fakeDiscoveryClient{} + cdc := newCachedDiscoveryClient(&c, d, 1*time.Nanosecond) + cdc.ServerGroups() + assert.Equal(c.groupCalls, 1) + + time.Sleep(1 * time.Second) + + cdc.ServerGroups() + assert.Equal(c.groupCalls, 2) +} + +type fakeDiscoveryClient struct { + groupCalls int + resourceCalls int + versionCalls int + openAPICalls int + + serverResourcesHandler func() ([]*metav1.APIResourceList, error) +} + +var _ DiscoveryInterface = &fakeDiscoveryClient{} + +func (c *fakeDiscoveryClient) RESTClient() restclient.Interface { + return &fake.RESTClient{} +} + +func (c *fakeDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { + c.groupCalls = c.groupCalls + 1 + return &metav1.APIGroupList{ + Groups: []metav1.APIGroup{ + { + Name: "a", + Versions: []metav1.GroupVersionForDiscovery{ + { + GroupVersion: "a/v1", + Version: "v1", + }, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "a/v1", + Version: "v1", + }, + }, + }, + }, nil +} + +func (c *fakeDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + c.resourceCalls = c.resourceCalls + 1 + if groupVersion == "a/v1" { + return &metav1.APIResourceList{APIResources: []metav1.APIResource{{Name: "widgets", Kind: "Widget"}}}, nil + } + + return nil, errors.NewNotFound(schema.GroupResource{}, "") +} + +func (c *fakeDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { + c.resourceCalls = c.resourceCalls + 1 + if c.serverResourcesHandler != nil { + return c.serverResourcesHandler() + } + return []*metav1.APIResourceList{}, nil +} + +func (c *fakeDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + c.resourceCalls = c.resourceCalls + 1 + return nil, nil +} + +func (c *fakeDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + c.resourceCalls = c.resourceCalls + 1 + return nil, nil +} + +func (c *fakeDiscoveryClient) ServerVersion() (*version.Info, error) { + c.versionCalls = c.versionCalls + 1 + return &version.Info{}, nil +} + +func (c *fakeDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { + c.openAPICalls = c.openAPICalls + 1 + return &openapi_v2.Document{}, nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/discovery_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/discovery_client.go index 083508616..a96602974 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/discovery_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/discovery_client.go @@ -22,6 +22,8 @@ import ( "net/url" "sort" "strings" + "sync" + "time" "github.com/golang/protobuf/proto" "github.com/googleapis/gnostic/OpenAPIv2" @@ -31,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/version" "k8s.io/client-go/kubernetes/scheme" restclient "k8s.io/client-go/rest" @@ -41,6 +44,9 @@ const ( defaultRetries = 2 // protobuf mime type mimePb = "application/com.github.proto-openapi.spec.v2@v1.0+protobuf" + // defaultTimeout is the maximum amount of time per request when no timeout has been set on a RESTClient. + // Defaults to 32s in order to have a distinguishable length of time, relative to other timeouts that exist. + defaultTimeout = 32 * time.Second ) // DiscoveryInterface holds the methods that discover server-supported API groups, @@ -183,33 +189,7 @@ func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (r // serverResources returns the supported resources for all groups and versions. func (d *DiscoveryClient) serverResources() ([]*metav1.APIResourceList, error) { - apiGroups, err := d.ServerGroups() - if err != nil { - return nil, err - } - - result := []*metav1.APIResourceList{} - failedGroups := make(map[schema.GroupVersion]error) - - for _, apiGroup := range apiGroups.Groups { - for _, version := range apiGroup.Versions { - gv := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version} - resources, err := d.ServerResourcesForGroupVersion(version.GroupVersion) - if err != nil { - // TODO: maybe restrict this to NotFound errors - failedGroups[gv] = err - continue - } - - result = append(result, resources) - } - } - - if len(failedGroups) == 0 { - return result, nil - } - - return result, &ErrGroupDiscoveryFailed{Groups: failedGroups} + return ServerResources(d) } // ServerResources returns the supported resources for all groups and versions. @@ -242,14 +222,46 @@ func IsGroupDiscoveryFailedError(err error) bool { // serverPreferredResources returns the supported resources with the version preferred by the server. func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList, error) { - serverGroupList, err := d.ServerGroups() + return ServerPreferredResources(d) +} + +// ServerResources uses the provided discovery interface to look up supported resources for all groups and versions. +func ServerResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) { + apiGroups, err := d.ServerGroups() if err != nil { return nil, err } + groupVersionResources, failedGroups := fetchGroupVersionResources(d, apiGroups) + + // order results by group/version discovery order result := []*metav1.APIResourceList{} - failedGroups := make(map[schema.GroupVersion]error) + for _, apiGroup := range apiGroups.Groups { + for _, version := range apiGroup.Versions { + gv := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version} + if resources, ok := groupVersionResources[gv]; ok { + result = append(result, resources) + } + } + } + + if len(failedGroups) == 0 { + return result, nil + } + + return result, &ErrGroupDiscoveryFailed{Groups: failedGroups} +} + +// ServerPreferredResources uses the provided discovery interface to look up preferred resources +func ServerPreferredResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) { + serverGroupList, err := d.ServerGroups() + if err != nil { + return nil, err + } + groupVersionResources, failedGroups := fetchGroupVersionResources(d, serverGroupList) + + result := []*metav1.APIResourceList{} grVersions := map[schema.GroupResource]string{} // selected version of a GroupResource grApiResources := map[schema.GroupResource]*metav1.APIResource{} // selected APIResource for a GroupResource gvApiResourceLists := map[schema.GroupVersion]*metav1.APIResourceList{} // blueprint for a APIResourceList for later grouping @@ -257,10 +269,9 @@ func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList, for _, apiGroup := range serverGroupList.Groups { for _, version := range apiGroup.Versions { groupVersion := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version} - apiResourceList, err := d.ServerResourcesForGroupVersion(version.GroupVersion) - if err != nil { - // TODO: maybe restrict this to NotFound errors - failedGroups[groupVersion] = err + + apiResourceList, ok := groupVersionResources[groupVersion] + if !ok { continue } @@ -302,6 +313,41 @@ func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList, return result, &ErrGroupDiscoveryFailed{Groups: failedGroups} } +// fetchServerResourcesForGroupVersions uses the discovery client to fetch the resources for the specified groups in parallel +func fetchGroupVersionResources(d DiscoveryInterface, apiGroups *metav1.APIGroupList) (map[schema.GroupVersion]*metav1.APIResourceList, map[schema.GroupVersion]error) { + groupVersionResources := make(map[schema.GroupVersion]*metav1.APIResourceList) + failedGroups := make(map[schema.GroupVersion]error) + + wg := &sync.WaitGroup{} + resultLock := &sync.Mutex{} + for _, apiGroup := range apiGroups.Groups { + for _, version := range apiGroup.Versions { + groupVersion := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version} + wg.Add(1) + go func() { + defer wg.Done() + defer utilruntime.HandleCrash() + + apiResourceList, err := d.ServerResourcesForGroupVersion(groupVersion.String()) + + // lock to record results + resultLock.Lock() + defer resultLock.Unlock() + + if err != nil { + // TODO: maybe restrict this to NotFound errors + failedGroups[groupVersion] = err + } else { + groupVersionResources[groupVersion] = apiResourceList + } + }() + } + } + wg.Wait() + + return groupVersionResources, failedGroups +} + // ServerPreferredResources returns the supported resources with the version preferred by the // server. func (d *DiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { @@ -311,7 +357,12 @@ func (d *DiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, // ServerPreferredNamespacedResources returns the supported namespaced resources with the // version preferred by the server. func (d *DiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { - all, err := d.ServerPreferredResources() + return ServerPreferredNamespacedResources(d) +} + +// ServerPreferredNamespacedResources uses the provided discovery interface to look up preferred namespaced resources +func ServerPreferredNamespacedResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) { + all, err := ServerPreferredResources(d) return FilteredBy(ResourcePredicateFunc(func(groupVersion string, r *metav1.APIResource) bool { return r.Namespaced }), all), err @@ -373,6 +424,9 @@ func withRetries(maxRetries int, f func() ([]*metav1.APIResourceList, error)) ([ func setDiscoveryDefaults(config *restclient.Config) error { config.APIPath = "" config.GroupVersion = nil + if config.Timeout == 0 { + config.Timeout = defaultTimeout + } codec := runtime.NoopEncoder{Decoder: scheme.Codecs.UniversalDecoder()} config.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec}) if len(config.UserAgent) == 0 { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/discovery_client_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/discovery_client_test.go index 6f4de6b48..10e494322 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/discovery_client_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/discovery_client_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package discovery_test +package discovery import ( "encoding/json" @@ -27,12 +27,13 @@ import ( "github.com/gogo/protobuf/proto" "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/version" - . "k8s.io/client-go/discovery" restclient "k8s.io/client-go/rest" ) @@ -130,6 +131,12 @@ func TestGetServerGroupsWithBrokenServer(t *testing.T) { } } +func TestTimeoutIsSet(t *testing.T) { + cfg := &restclient.Config{} + setDiscoveryDefaults(cfg) + assert.Equal(t, defaultTimeout, cfg.Timeout) +} + func TestGetServerResourcesWithV1Server(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { var obj interface{} @@ -183,6 +190,14 @@ func TestGetServerResources(t *testing.T) { {Name: "jobs", Namespaced: true, Kind: "Job"}, }, } + beta2 := metav1.APIResourceList{ + GroupVersion: "extensions/v1beta2", + APIResources: []metav1.APIResource{ + {Name: "deployments", Namespaced: true, Kind: "Deployment"}, + {Name: "ingresses", Namespaced: true, Kind: "Ingress"}, + {Name: "jobs", Namespaced: true, Kind: "Job"}, + }, + } tests := []struct { resourcesList *metav1.APIResourceList path string @@ -215,6 +230,8 @@ func TestGetServerResources(t *testing.T) { list = &stable case "/apis/extensions/v1beta1": list = &beta + case "/apis/extensions/v1beta2": + list = &beta2 case "/api": list = &metav1.APIVersions{ Versions: []string{ @@ -225,8 +242,10 @@ func TestGetServerResources(t *testing.T) { list = &metav1.APIGroupList{ Groups: []metav1.APIGroup{ { + Name: "extensions", Versions: []metav1.GroupVersionForDiscovery{ - {GroupVersion: "extensions/v1beta1"}, + {GroupVersion: "extensions/v1beta1", Version: "v1beta1"}, + {GroupVersion: "extensions/v1beta2", Version: "v1beta2"}, }, }, }, @@ -268,11 +287,10 @@ func TestGetServerResources(t *testing.T) { if err != nil { t.Errorf("unexpected error: %v", err) } - serverGroupVersions := sets.NewString(groupVersions(serverResources)...) - for _, api := range []string{"v1", "extensions/v1beta1"} { - if !serverGroupVersions.Has(api) { - t.Errorf("missing expected api %q in %v", api, serverResources) - } + serverGroupVersions := groupVersions(serverResources) + expectedGroupVersions := []string{"v1", "extensions/v1beta1", "extensions/v1beta2"} + if !reflect.DeepEqual(expectedGroupVersions, serverGroupVersions) { + t.Errorf("unexpected group versions: %v", diff.ObjectReflectDiff(expectedGroupVersions, serverGroupVersions)) } } @@ -618,7 +636,7 @@ func TestServerPreferredResourcesRetries(t *testing.T) { { Name: "extensions", Versions: []metav1.GroupVersionForDiscovery{ - {GroupVersion: "extensions/v1beta1"}, + {GroupVersion: "extensions/v1beta1", Version: "v1beta1"}, }, PreferredVersion: metav1.GroupVersionForDiscovery{ GroupVersion: "extensions/v1beta1", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/restmapper.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/restmapper.go deleted file mode 100644 index df5ab0358..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/restmapper.go +++ /dev/null @@ -1,333 +0,0 @@ -/* -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 discovery - -import ( - "fmt" - "strings" - "sync" - - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - - "github.com/golang/glog" -) - -// APIGroupResources is an API group with a mapping of versions to -// resources. -type APIGroupResources struct { - Group metav1.APIGroup - // A mapping of version string to a slice of APIResources for - // that version. - VersionedResources map[string][]metav1.APIResource -} - -// NewRESTMapper returns a PriorityRESTMapper based on the discovered -// groups and resources passed in. -func NewRESTMapper(groupResources []*APIGroupResources, versionInterfaces meta.VersionInterfacesFunc) meta.RESTMapper { - unionMapper := meta.MultiRESTMapper{} - - var groupPriority []string - // /v1 is special. It should always come first - resourcePriority := []schema.GroupVersionResource{{Group: "", Version: "v1", Resource: meta.AnyResource}} - kindPriority := []schema.GroupVersionKind{{Group: "", Version: "v1", Kind: meta.AnyKind}} - - for _, group := range groupResources { - groupPriority = append(groupPriority, group.Group.Name) - - // Make sure the preferred version comes first - if len(group.Group.PreferredVersion.Version) != 0 { - preferred := group.Group.PreferredVersion.Version - if _, ok := group.VersionedResources[preferred]; ok { - resourcePriority = append(resourcePriority, schema.GroupVersionResource{ - Group: group.Group.Name, - Version: group.Group.PreferredVersion.Version, - Resource: meta.AnyResource, - }) - - kindPriority = append(kindPriority, schema.GroupVersionKind{ - Group: group.Group.Name, - Version: group.Group.PreferredVersion.Version, - Kind: meta.AnyKind, - }) - } - } - - for _, discoveryVersion := range group.Group.Versions { - resources, ok := group.VersionedResources[discoveryVersion.Version] - if !ok { - continue - } - - // Add non-preferred versions after the preferred version, in case there are resources that only exist in those versions - if discoveryVersion.Version != group.Group.PreferredVersion.Version { - resourcePriority = append(resourcePriority, schema.GroupVersionResource{ - Group: group.Group.Name, - Version: discoveryVersion.Version, - Resource: meta.AnyResource, - }) - - kindPriority = append(kindPriority, schema.GroupVersionKind{ - Group: group.Group.Name, - Version: discoveryVersion.Version, - Kind: meta.AnyKind, - }) - } - - gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version} - versionMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{gv}, versionInterfaces) - - for _, resource := range resources { - scope := meta.RESTScopeNamespace - if !resource.Namespaced { - scope = meta.RESTScopeRoot - } - - // this is for legacy resources and servers which don't list singular forms. For those we must still guess. - if len(resource.SingularName) == 0 { - versionMapper.Add(gv.WithKind(resource.Kind), scope) - // TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior - versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope) - continue - } - - plural := gv.WithResource(resource.Name) - singular := gv.WithResource(resource.SingularName) - versionMapper.AddSpecific(gv.WithKind(resource.Kind), plural, singular, scope) - versionMapper.AddSpecific(gv.WithKind(strings.ToLower(resource.Kind)), plural, singular, scope) - // TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior - versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope) - } - // TODO why is this type not in discovery (at least for "v1") - versionMapper.Add(gv.WithKind("List"), meta.RESTScopeRoot) - unionMapper = append(unionMapper, versionMapper) - } - } - - for _, group := range groupPriority { - resourcePriority = append(resourcePriority, schema.GroupVersionResource{ - Group: group, - Version: meta.AnyVersion, - Resource: meta.AnyResource, - }) - kindPriority = append(kindPriority, schema.GroupVersionKind{ - Group: group, - Version: meta.AnyVersion, - Kind: meta.AnyKind, - }) - } - - return meta.PriorityRESTMapper{ - Delegate: unionMapper, - ResourcePriority: resourcePriority, - KindPriority: kindPriority, - } -} - -// GetAPIGroupResources uses the provided discovery client to gather -// discovery information and populate a slice of APIGroupResources. -func GetAPIGroupResources(cl DiscoveryInterface) ([]*APIGroupResources, error) { - apiGroups, err := cl.ServerGroups() - if err != nil { - return nil, err - } - var result []*APIGroupResources - for _, group := range apiGroups.Groups { - groupResources := &APIGroupResources{ - Group: group, - VersionedResources: make(map[string][]metav1.APIResource), - } - for _, version := range group.Versions { - resources, err := cl.ServerResourcesForGroupVersion(version.GroupVersion) - if err != nil { - // continue as best we can - // TODO track the errors and update callers to handle partial errors. - continue - } - groupResources.VersionedResources[version.Version] = resources.APIResources - } - result = append(result, groupResources) - } - return result, nil -} - -// DeferredDiscoveryRESTMapper is a RESTMapper that will defer -// initialization of the RESTMapper until the first mapping is -// requested. -type DeferredDiscoveryRESTMapper struct { - initMu sync.Mutex - delegate meta.RESTMapper - cl CachedDiscoveryInterface - versionInterface meta.VersionInterfacesFunc -} - -// NewDeferredDiscoveryRESTMapper returns a -// DeferredDiscoveryRESTMapper that will lazily query the provided -// client for discovery information to do REST mappings. -func NewDeferredDiscoveryRESTMapper(cl CachedDiscoveryInterface, versionInterface meta.VersionInterfacesFunc) *DeferredDiscoveryRESTMapper { - return &DeferredDiscoveryRESTMapper{ - cl: cl, - versionInterface: versionInterface, - } -} - -func (d *DeferredDiscoveryRESTMapper) getDelegate() (meta.RESTMapper, error) { - d.initMu.Lock() - defer d.initMu.Unlock() - - if d.delegate != nil { - return d.delegate, nil - } - - groupResources, err := GetAPIGroupResources(d.cl) - if err != nil { - return nil, err - } - - d.delegate = NewRESTMapper(groupResources, d.versionInterface) - return d.delegate, err -} - -// Reset resets the internally cached Discovery information and will -// cause the next mapping request to re-discover. -func (d *DeferredDiscoveryRESTMapper) Reset() { - glog.V(5).Info("Invalidating discovery information") - - d.initMu.Lock() - defer d.initMu.Unlock() - - d.cl.Invalidate() - d.delegate = nil -} - -// KindFor takes a partial resource and returns back the single match. -// It returns an error if there are multiple matches. -func (d *DeferredDiscoveryRESTMapper) KindFor(resource schema.GroupVersionResource) (gvk schema.GroupVersionKind, err error) { - del, err := d.getDelegate() - if err != nil { - return schema.GroupVersionKind{}, err - } - gvk, err = del.KindFor(resource) - if err != nil && !d.cl.Fresh() { - d.Reset() - gvk, err = d.KindFor(resource) - } - return -} - -// KindsFor takes a partial resource and returns back the list of -// potential kinds in priority order. -func (d *DeferredDiscoveryRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvks []schema.GroupVersionKind, err error) { - del, err := d.getDelegate() - if err != nil { - return nil, err - } - gvks, err = del.KindsFor(resource) - if len(gvks) == 0 && !d.cl.Fresh() { - d.Reset() - gvks, err = d.KindsFor(resource) - } - return -} - -// ResourceFor takes a partial resource and returns back the single -// match. It returns an error if there are multiple matches. -func (d *DeferredDiscoveryRESTMapper) ResourceFor(input schema.GroupVersionResource) (gvr schema.GroupVersionResource, err error) { - del, err := d.getDelegate() - if err != nil { - return schema.GroupVersionResource{}, err - } - gvr, err = del.ResourceFor(input) - if err != nil && !d.cl.Fresh() { - d.Reset() - gvr, err = d.ResourceFor(input) - } - return -} - -// ResourcesFor takes a partial resource and returns back the list of -// potential resource in priority order. -func (d *DeferredDiscoveryRESTMapper) ResourcesFor(input schema.GroupVersionResource) (gvrs []schema.GroupVersionResource, err error) { - del, err := d.getDelegate() - if err != nil { - return nil, err - } - gvrs, err = del.ResourcesFor(input) - if len(gvrs) == 0 && !d.cl.Fresh() { - d.Reset() - gvrs, err = d.ResourcesFor(input) - } - return -} - -// RESTMapping identifies a preferred resource mapping for the -// provided group kind. -func (d *DeferredDiscoveryRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (m *meta.RESTMapping, err error) { - del, err := d.getDelegate() - if err != nil { - return nil, err - } - m, err = del.RESTMapping(gk, versions...) - if err != nil && !d.cl.Fresh() { - d.Reset() - m, err = d.RESTMapping(gk, versions...) - } - return -} - -// RESTMappings returns the RESTMappings for the provided group kind -// in a rough internal preferred order. If no kind is found, it will -// return a NoResourceMatchError. -func (d *DeferredDiscoveryRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (ms []*meta.RESTMapping, err error) { - del, err := d.getDelegate() - if err != nil { - return nil, err - } - ms, err = del.RESTMappings(gk, versions...) - if len(ms) == 0 && !d.cl.Fresh() { - d.Reset() - ms, err = d.RESTMappings(gk, versions...) - } - return -} - -// ResourceSingularizer converts a resource name from plural to -// singular (e.g., from pods to pod). -func (d *DeferredDiscoveryRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { - del, err := d.getDelegate() - if err != nil { - return resource, err - } - singular, err = del.ResourceSingularizer(resource) - if err != nil && !d.cl.Fresh() { - d.Reset() - singular, err = d.ResourceSingularizer(resource) - } - return -} - -func (d *DeferredDiscoveryRESTMapper) String() string { - del, err := d.getDelegate() - if err != nil { - return fmt.Sprintf("DeferredDiscoveryRESTMapper{%v}", err) - } - return fmt.Sprintf("DeferredDiscoveryRESTMapper{\n\t%v\n}", del) -} - -// Make sure it satisfies the interface -var _ meta.RESTMapper = &DeferredDiscoveryRESTMapper{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/restmapper_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/restmapper_test.go deleted file mode 100644 index 69ee7e686..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/restmapper_test.go +++ /dev/null @@ -1,384 +0,0 @@ -/* -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 discovery_test - -import ( - "reflect" - "testing" - - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/version" - . "k8s.io/client-go/discovery" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/rest/fake" - - "github.com/googleapis/gnostic/OpenAPIv2" - "github.com/stretchr/testify/assert" -) - -func TestRESTMapper(t *testing.T) { - resources := []*APIGroupResources{ - { - Group: metav1.APIGroup{ - Name: "extensions", - Versions: []metav1.GroupVersionForDiscovery{ - {Version: "v1beta"}, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1beta"}, - }, - VersionedResources: map[string][]metav1.APIResource{ - "v1beta": { - {Name: "jobs", Namespaced: true, Kind: "Job"}, - {Name: "pods", Namespaced: true, Kind: "Pod"}, - }, - }, - }, - { - Group: metav1.APIGroup{ - Versions: []metav1.GroupVersionForDiscovery{ - {Version: "v1"}, - {Version: "v2"}, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1"}, - }, - VersionedResources: map[string][]metav1.APIResource{ - "v1": { - {Name: "pods", Namespaced: true, Kind: "Pod"}, - }, - "v2": { - {Name: "pods", Namespaced: true, Kind: "Pod"}, - }, - }, - }, - - // This group tests finding and prioritizing resources that only exist in non-preferred versions - { - Group: metav1.APIGroup{ - Name: "unpreferred", - Versions: []metav1.GroupVersionForDiscovery{ - {Version: "v1"}, - {Version: "v2beta1"}, - {Version: "v2alpha1"}, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1"}, - }, - VersionedResources: map[string][]metav1.APIResource{ - "v1": { - {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, - }, - "v2beta1": { - {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, - {Name: "peas", Namespaced: true, Kind: "Pea"}, - }, - "v2alpha1": { - {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, - {Name: "peas", Namespaced: true, Kind: "Pea"}, - }, - }, - }, - } - - restMapper := NewRESTMapper(resources, nil) - - kindTCs := []struct { - input schema.GroupVersionResource - want schema.GroupVersionKind - }{ - { - input: schema.GroupVersionResource{ - Resource: "pods", - }, - want: schema.GroupVersionKind{ - Version: "v1", - Kind: "Pod", - }, - }, - { - input: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - want: schema.GroupVersionKind{ - Version: "v1", - Kind: "Pod", - }, - }, - { - input: schema.GroupVersionResource{ - Version: "v2", - Resource: "pods", - }, - want: schema.GroupVersionKind{ - Version: "v2", - Kind: "Pod", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "pods", - }, - want: schema.GroupVersionKind{ - Version: "v1", - Kind: "Pod", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "jobs", - }, - want: schema.GroupVersionKind{ - Group: "extensions", - Version: "v1beta", - Kind: "Job", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "peas", - }, - want: schema.GroupVersionKind{ - Group: "unpreferred", - Version: "v2beta1", - Kind: "Pea", - }, - }, - } - - for _, tc := range kindTCs { - got, err := restMapper.KindFor(tc.input) - if err != nil { - t.Errorf("KindFor(%#v) unexpected error: %v", tc.input, err) - continue - } - - if !reflect.DeepEqual(got, tc.want) { - t.Errorf("KindFor(%#v) = %#v, want %#v", tc.input, got, tc.want) - } - } - - resourceTCs := []struct { - input schema.GroupVersionResource - want schema.GroupVersionResource - }{ - { - input: schema.GroupVersionResource{ - Resource: "pods", - }, - want: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - }, - { - input: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - want: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - }, - { - input: schema.GroupVersionResource{ - Version: "v2", - Resource: "pods", - }, - want: schema.GroupVersionResource{ - Version: "v2", - Resource: "pods", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "pods", - }, - want: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", - }, - }, - { - input: schema.GroupVersionResource{ - Resource: "jobs", - }, - want: schema.GroupVersionResource{ - Group: "extensions", - Version: "v1beta", - Resource: "jobs", - }, - }, - } - - for _, tc := range resourceTCs { - got, err := restMapper.ResourceFor(tc.input) - if err != nil { - t.Errorf("ResourceFor(%#v) unexpected error: %v", tc.input, err) - continue - } - - if !reflect.DeepEqual(got, tc.want) { - t.Errorf("ResourceFor(%#v) = %#v, want %#v", tc.input, got, tc.want) - } - } -} - -func TestDeferredDiscoveryRESTMapper_CacheMiss(t *testing.T) { - assert := assert.New(t) - - cdc := fakeCachedDiscoveryInterface{fresh: false} - m := NewDeferredDiscoveryRESTMapper(&cdc, nil) - assert.False(cdc.fresh, "should NOT be fresh after instantiation") - assert.Zero(cdc.invalidateCalls, "should not have called Invalidate()") - - gvk, err := m.KindFor(schema.GroupVersionResource{ - Group: "a", - Version: "v1", - Resource: "foo", - }) - assert.NoError(err) - assert.True(cdc.fresh, "should be fresh after a cache-miss") - assert.Equal(cdc.invalidateCalls, 1, "should have called Invalidate() once") - assert.Equal(gvk.Kind, "Foo") - - gvk, err = m.KindFor(schema.GroupVersionResource{ - Group: "a", - Version: "v1", - Resource: "foo", - }) - assert.NoError(err) - assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again") - - gvk, err = m.KindFor(schema.GroupVersionResource{ - Group: "a", - Version: "v1", - Resource: "bar", - }) - assert.Error(err) - assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again after another cache-miss, but with fresh==true") - - cdc.fresh = false - gvk, err = m.KindFor(schema.GroupVersionResource{ - Group: "a", - Version: "v1", - Resource: "bar", - }) - assert.Error(err) - assert.Equal(cdc.invalidateCalls, 2, "should HAVE called Invalidate() again after another cache-miss, but with fresh==false") -} - -type fakeCachedDiscoveryInterface struct { - invalidateCalls int - fresh bool - enabledA bool -} - -var _ CachedDiscoveryInterface = &fakeCachedDiscoveryInterface{} - -func (c *fakeCachedDiscoveryInterface) Fresh() bool { - return c.fresh -} - -func (c *fakeCachedDiscoveryInterface) Invalidate() { - c.invalidateCalls = c.invalidateCalls + 1 - c.fresh = true - c.enabledA = true -} - -func (c *fakeCachedDiscoveryInterface) RESTClient() restclient.Interface { - return &fake.RESTClient{} -} - -func (c *fakeCachedDiscoveryInterface) ServerGroups() (*metav1.APIGroupList, error) { - if c.enabledA { - return &metav1.APIGroupList{ - Groups: []metav1.APIGroup{ - { - Name: "a", - Versions: []metav1.GroupVersionForDiscovery{ - { - GroupVersion: "a/v1", - Version: "v1", - }, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{ - GroupVersion: "a/v1", - Version: "v1", - }, - }, - }, - }, nil - } - return &metav1.APIGroupList{}, nil -} - -func (c *fakeCachedDiscoveryInterface) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - if c.enabledA && groupVersion == "a/v1" { - return &metav1.APIResourceList{ - GroupVersion: "a/v1", - APIResources: []metav1.APIResource{ - { - Name: "foo", - Kind: "Foo", - Namespaced: false, - }, - }, - }, nil - } - - return nil, errors.NewNotFound(schema.GroupResource{}, "") -} - -func (c *fakeCachedDiscoveryInterface) ServerResources() ([]*metav1.APIResourceList, error) { - if c.enabledA { - av1, _ := c.ServerResourcesForGroupVersion("a/v1") - return []*metav1.APIResourceList{av1}, nil - } - return []*metav1.APIResourceList{}, nil -} - -func (c *fakeCachedDiscoveryInterface) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - if c.enabledA { - return []*metav1.APIResourceList{ - { - GroupVersion: "a/v1", - APIResources: []metav1.APIResource{ - { - Name: "foo", - Kind: "Foo", - Verbs: []string{}, - }, - }, - }, - }, nil - } - return nil, nil -} - -func (c *fakeCachedDiscoveryInterface) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { - return nil, nil -} - -func (c *fakeCachedDiscoveryInterface) ServerVersion() (*version.Info, error) { - return &version.Info{}, nil -} - -func (c *fakeCachedDiscoveryInterface) OpenAPISchema() (*openapi_v2.Document, error) { - return &openapi_v2.Document{}, nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/round_tripper.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/round_tripper.go new file mode 100644 index 000000000..2e352b888 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/round_tripper.go @@ -0,0 +1,51 @@ +/* +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 transport provides a round tripper capable of caching HTTP responses. +package discovery + +import ( + "net/http" + "path/filepath" + + "github.com/gregjones/httpcache" + "github.com/gregjones/httpcache/diskcache" + "github.com/peterbourgon/diskv" +) + +type cacheRoundTripper struct { + rt *httpcache.Transport +} + +// newCacheRoundTripper creates a roundtripper that reads the ETag on +// response headers and send the If-None-Match header on subsequent +// corresponding requests. +func newCacheRoundTripper(cacheDir string, rt http.RoundTripper) http.RoundTripper { + d := diskv.New(diskv.Options{ + BasePath: cacheDir, + TempDir: filepath.Join(cacheDir, ".diskv-temp"), + }) + t := httpcache.NewTransport(diskcache.NewWithDiskv(d)) + t.Transport = rt + + return &cacheRoundTripper{rt: t} +} + +func (rt *cacheRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + return rt.rt.RoundTrip(req) +} + +func (rt *cacheRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt.Transport } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/round_tripper_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/round_tripper_test.go new file mode 100644 index 000000000..b15e2e771 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/round_tripper_test.go @@ -0,0 +1,95 @@ +/* +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 discovery + +import ( + "bytes" + "io/ioutil" + "net/http" + "net/url" + "os" + "testing" +) + +// copied from k8s.io/client-go/transport/round_trippers_test.go +type testRoundTripper struct { + Request *http.Request + Response *http.Response + Err error +} + +func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + rt.Request = req + return rt.Response, rt.Err +} + +func TestCacheRoundTripper(t *testing.T) { + rt := &testRoundTripper{} + cacheDir, err := ioutil.TempDir("", "cache-rt") + defer os.RemoveAll(cacheDir) + if err != nil { + t.Fatal(err) + } + cache := newCacheRoundTripper(cacheDir, rt) + + // First call, caches the response + req := &http.Request{ + Method: http.MethodGet, + URL: &url.URL{Host: "localhost"}, + } + rt.Response = &http.Response{ + Header: http.Header{"ETag": []string{`"123456"`}}, + Body: ioutil.NopCloser(bytes.NewReader([]byte("Content"))), + StatusCode: http.StatusOK, + } + resp, err := cache.RoundTrip(req) + if err != nil { + t.Fatal(err) + } + content, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + if string(content) != "Content" { + t.Errorf(`Expected Body to be "Content", got %q`, string(content)) + } + + // Second call, returns cached response + req = &http.Request{ + Method: http.MethodGet, + URL: &url.URL{Host: "localhost"}, + } + rt.Response = &http.Response{ + StatusCode: http.StatusNotModified, + Body: ioutil.NopCloser(bytes.NewReader([]byte("Other Content"))), + } + + resp, err = cache.RoundTrip(req) + if err != nil { + t.Fatal(err) + } + + // Read body and make sure we have the initial content + content, err = ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + t.Fatal(err) + } + if string(content) != "Content" { + t.Errorf("Invalid content read from cache %q", string(content)) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/unstructured.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/unstructured.go index fa7f2ec06..81913a414 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/unstructured.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/discovery/unstructured.go @@ -26,31 +26,17 @@ import ( // UnstructuredObjectTyper provides a runtime.ObjectTyper implementation for // runtime.Unstructured object based on discovery information. type UnstructuredObjectTyper struct { - registered map[schema.GroupVersionKind]bool - typers []runtime.ObjectTyper + typers []runtime.ObjectTyper } // NewUnstructuredObjectTyper returns a runtime.ObjectTyper for // unstructured objects based on discovery information. It accepts a list of fallback typers // for handling objects that are not runtime.Unstructured. It does not delegate the Recognizes // check, only ObjectKinds. -func NewUnstructuredObjectTyper(groupResources []*APIGroupResources, typers ...runtime.ObjectTyper) *UnstructuredObjectTyper { +// TODO this only works for the apiextensions server and doesn't recognize any types. Move to point of use. +func NewUnstructuredObjectTyper(typers ...runtime.ObjectTyper) *UnstructuredObjectTyper { dot := &UnstructuredObjectTyper{ - registered: make(map[schema.GroupVersionKind]bool), - typers: typers, - } - for _, group := range groupResources { - for _, discoveryVersion := range group.Group.Versions { - resources, ok := group.VersionedResources[discoveryVersion.Version] - if !ok { - continue - } - - gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version} - for _, resource := range resources { - dot.registered[gv.WithKind(resource.Kind)] = true - } - } + typers: typers, } return dot } @@ -89,7 +75,7 @@ func (d *UnstructuredObjectTyper) ObjectKinds(obj runtime.Object) (gvks []schema // Recognizes returns true if the provided group,version,kind was in the // discovery information. func (d *UnstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool { - return d.registered[gvk] + return false } var _ runtime.ObjectTyper = &UnstructuredObjectTyper{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/BUILD index 3642f6a0f..90b9ab301 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/BUILD @@ -8,10 +8,7 @@ load( go_test( name = "go_default_test", - srcs = [ - "client_test.go", - "dynamic_util_test.go", - ], + srcs = ["client_test.go"], embed = [":go_default_library"], deps = [ "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -29,25 +26,24 @@ go_test( go_library( name = "go_default_library", srcs = [ - "client.go", - "client_pool.go", - "dynamic_util.go", + "interface.go", + "scheme.go", + "simple.go", ], importpath = "k8s.io/client-go/dynamic", deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/conversion/queryparams: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:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client.go deleted file mode 100644 index 833e43537..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client.go +++ /dev/null @@ -1,379 +0,0 @@ -/* -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 dynamic provides a client interface to arbitrary Kubernetes -// APIs that exposes common high level operations and exposes common -// metadata. -package dynamic - -import ( - "encoding/json" - "errors" - "io" - "net/url" - "strings" - - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/conversion/queryparams" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/kubernetes/scheme" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/util/flowcontrol" -) - -// Interface is a Kubernetes client that allows you to access metadata -// and manipulate metadata of a Kubernetes API group. -type Interface interface { - // GetRateLimiter returns the rate limiter for this client. - GetRateLimiter() flowcontrol.RateLimiter - // Resource returns an API interface to the specified resource for this client's - // group and version. If resource is not a namespaced resource, then namespace - // is ignored. The ResourceInterface inherits the parameter codec of this client. - Resource(resource *metav1.APIResource, namespace string) ResourceInterface - // ParameterCodec returns a client with the provided parameter codec. - ParameterCodec(parameterCodec runtime.ParameterCodec) Interface -} - -// ResourceInterface is an API interface to a specific resource under a -// dynamic client. -type ResourceInterface interface { - // List returns a list of objects for this resource. - List(opts metav1.ListOptions) (runtime.Object, error) - // Get gets the resource with the specified name. - Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) - // Delete deletes the resource with the specified name. - Delete(name string, opts *metav1.DeleteOptions) error - // DeleteCollection deletes a collection of objects. - DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error - // Create creates the provided resource. - Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) - // Update updates the provided resource. - Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) - // Watch returns a watch.Interface that watches the resource. - Watch(opts metav1.ListOptions) (watch.Interface, error) - // Patch patches the provided resource. - Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) -} - -// Client is a Kubernetes client that allows you to access metadata -// and manipulate metadata of a Kubernetes API group, and implements Interface. -type Client struct { - cl *restclient.RESTClient - parameterCodec runtime.ParameterCodec -} - -// NewClient returns a new client based on the passed in config. The -// codec is ignored, as the dynamic client uses it's own codec. -func NewClient(conf *restclient.Config) (*Client, error) { - // avoid changing the original config - confCopy := *conf - conf = &confCopy - - contentConfig := ContentConfig() - contentConfig.GroupVersion = conf.GroupVersion - if conf.NegotiatedSerializer != nil { - contentConfig.NegotiatedSerializer = conf.NegotiatedSerializer - } - conf.ContentConfig = contentConfig - - if conf.APIPath == "" { - conf.APIPath = "/api" - } - - if len(conf.UserAgent) == 0 { - conf.UserAgent = restclient.DefaultKubernetesUserAgent() - } - - cl, err := restclient.RESTClientFor(conf) - if err != nil { - return nil, err - } - - return &Client{cl: cl}, nil -} - -// GetRateLimiter returns rate limier. -func (c *Client) GetRateLimiter() flowcontrol.RateLimiter { - return c.cl.GetRateLimiter() -} - -// Resource returns an API interface to the specified resource for this client's -// group and version. If resource is not a namespaced resource, then namespace -// is ignored. The ResourceInterface inherits the parameter codec of c. -func (c *Client) Resource(resource *metav1.APIResource, namespace string) ResourceInterface { - return &ResourceClient{ - cl: c.cl, - resource: resource, - ns: namespace, - parameterCodec: c.parameterCodec, - } -} - -// ParameterCodec returns a client with the provided parameter codec. -func (c *Client) ParameterCodec(parameterCodec runtime.ParameterCodec) Interface { - return &Client{ - cl: c.cl, - parameterCodec: parameterCodec, - } -} - -// ResourceClient is an API interface to a specific resource under a -// dynamic client, and implements ResourceInterface. -type ResourceClient struct { - cl *restclient.RESTClient - resource *metav1.APIResource - ns string - parameterCodec runtime.ParameterCodec -} - -func (rc *ResourceClient) parseResourceSubresourceName() (string, []string) { - var resourceName string - var subresourceName []string - if strings.Contains(rc.resource.Name, "/") { - resourceName = strings.Split(rc.resource.Name, "/")[0] - subresourceName = strings.Split(rc.resource.Name, "/")[1:] - } else { - resourceName = rc.resource.Name - } - - return resourceName, subresourceName -} - -// List returns a list of objects for this resource. -func (rc *ResourceClient) List(opts metav1.ListOptions) (runtime.Object, error) { - parameterEncoder := rc.parameterCodec - if parameterEncoder == nil { - parameterEncoder = defaultParameterEncoder - } - return rc.cl.Get(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(rc.resource.Name). - VersionedParams(&opts, parameterEncoder). - Do(). - Get() -} - -// Get gets the resource with the specified name. -func (rc *ResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) { - parameterEncoder := rc.parameterCodec - if parameterEncoder == nil { - parameterEncoder = defaultParameterEncoder - } - result := new(unstructured.Unstructured) - resourceName, subresourceName := rc.parseResourceSubresourceName() - err := rc.cl.Get(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(resourceName). - SubResource(subresourceName...). - VersionedParams(&opts, parameterEncoder). - Name(name). - Do(). - Into(result) - return result, err -} - -// Delete deletes the resource with the specified name. -func (rc *ResourceClient) Delete(name string, opts *metav1.DeleteOptions) error { - return rc.cl.Delete(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(rc.resource.Name). - Name(name). - Body(opts). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (rc *ResourceClient) DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error { - parameterEncoder := rc.parameterCodec - if parameterEncoder == nil { - parameterEncoder = defaultParameterEncoder - } - return rc.cl.Delete(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(rc.resource.Name). - VersionedParams(&listOptions, parameterEncoder). - Body(deleteOptions). - Do(). - Error() -} - -// Create creates the provided resource. -func (rc *ResourceClient) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - result := new(unstructured.Unstructured) - resourceName, subresourceName := rc.parseResourceSubresourceName() - req := rc.cl.Post(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(resourceName). - Body(obj) - if len(subresourceName) > 0 { - // If the provided resource is a subresource, the POST request should contain - // object name. Examples of subresources that support Create operation: - // core/v1/pods/{name}/binding - // core/v1/pods/{name}/eviction - // extensions/v1beta1/deployments/{name}/rollback - // apps/v1beta1/deployments/{name}/rollback - // NOTE: Currently our system assumes every subresource object has the same - // name as the parent resource object. E.g. a pods/binding object having - // metadada.name "foo" means pod "foo" is being bound. We may need to - // change this if we break the assumption in the future. - req = req.SubResource(subresourceName...). - Name(obj.GetName()) - } - err := req.Do(). - Into(result) - return result, err -} - -// Update updates the provided resource. -func (rc *ResourceClient) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - result := new(unstructured.Unstructured) - if len(obj.GetName()) == 0 { - return result, errors.New("object missing name") - } - resourceName, subresourceName := rc.parseResourceSubresourceName() - err := rc.cl.Put(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(resourceName). - SubResource(subresourceName...). - // NOTE: Currently our system assumes every subresource object has the same - // name as the parent resource object. E.g. a pods/binding object having - // metadada.name "foo" means pod "foo" is being bound. We may need to - // change this if we break the assumption in the future. - Name(obj.GetName()). - Body(obj). - Do(). - Into(result) - return result, err -} - -// Watch returns a watch.Interface that watches the resource. -func (rc *ResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - parameterEncoder := rc.parameterCodec - if parameterEncoder == nil { - parameterEncoder = defaultParameterEncoder - } - opts.Watch = true - return rc.cl.Get(). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(rc.resource.Name). - VersionedParams(&opts, parameterEncoder). - Watch() -} - -// Patch applies the patch and returns the patched resource. -func (rc *ResourceClient) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) { - result := new(unstructured.Unstructured) - resourceName, subresourceName := rc.parseResourceSubresourceName() - err := rc.cl.Patch(pt). - NamespaceIfScoped(rc.ns, rc.resource.Namespaced). - Resource(resourceName). - SubResource(subresourceName...). - Name(name). - Body(data). - Do(). - Into(result) - return result, err -} - -// dynamicCodec is a codec that wraps the standard unstructured codec -// with special handling for Status objects. -type dynamicCodec struct{} - -func (dynamicCodec) Decode(data []byte, gvk *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { - obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(data, gvk, obj) - if err != nil { - return nil, nil, err - } - - if _, ok := obj.(*metav1.Status); !ok && strings.ToLower(gvk.Kind) == "status" { - obj = &metav1.Status{} - err := json.Unmarshal(data, obj) - if err != nil { - return nil, nil, err - } - } - - return obj, gvk, nil -} - -func (dynamicCodec) Encode(obj runtime.Object, w io.Writer) error { - return unstructured.UnstructuredJSONScheme.Encode(obj, w) -} - -// ContentConfig returns a restclient.ContentConfig for dynamic types. -func ContentConfig() restclient.ContentConfig { - var jsonInfo runtime.SerializerInfo - // TODO: scheme.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need - // to talk to a kubernetes server - for _, info := range scheme.Codecs.SupportedMediaTypes() { - if info.MediaType == runtime.ContentTypeJSON { - jsonInfo = info - break - } - } - - jsonInfo.Serializer = dynamicCodec{} - jsonInfo.PrettySerializer = nil - return restclient.ContentConfig{ - AcceptContentTypes: runtime.ContentTypeJSON, - ContentType: runtime.ContentTypeJSON, - NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo), - } -} - -// paramaterCodec is a codec converts an API object to query -// parameters without trying to convert to the target version. -type parameterCodec struct{} - -func (parameterCodec) EncodeParameters(obj runtime.Object, to schema.GroupVersion) (url.Values, error) { - return queryparams.Convert(obj) -} - -func (parameterCodec) DecodeParameters(parameters url.Values, from schema.GroupVersion, into runtime.Object) error { - return errors.New("DecodeParameters not implemented on dynamic parameterCodec") -} - -var defaultParameterEncoder runtime.ParameterCodec = parameterCodec{} - -type versionedParameterEncoderWithV1Fallback struct{} - -func (versionedParameterEncoderWithV1Fallback) EncodeParameters(obj runtime.Object, to schema.GroupVersion) (url.Values, error) { - ret, err := scheme.ParameterCodec.EncodeParameters(obj, to) - if err != nil && runtime.IsNotRegisteredError(err) { - // fallback to v1 - return scheme.ParameterCodec.EncodeParameters(obj, v1.SchemeGroupVersion) - } - return ret, err -} - -func (versionedParameterEncoderWithV1Fallback) DecodeParameters(parameters url.Values, from schema.GroupVersion, into runtime.Object) error { - return errors.New("DecodeParameters not implemented on versionedParameterEncoderWithV1Fallback") -} - -// VersionedParameterEncoderWithV1Fallback is useful for encoding query -// parameters for custom resources. It tries to convert object to the -// specified version before converting it to query parameters, and falls back to -// converting to v1 if the object is not registered in the specified version. -// For the record, currently API server always treats query parameters sent to a -// custom resource endpoint as v1. -var VersionedParameterEncoderWithV1Fallback runtime.ParameterCodec = versionedParameterEncoderWithV1Fallback{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client_pool.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client_pool.go deleted file mode 100644 index a5e1b2978..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client_pool.go +++ /dev/null @@ -1,122 +0,0 @@ -/* -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 dynamic - -import ( - "sync" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime/schema" - restclient "k8s.io/client-go/rest" -) - -// ClientPool manages a pool of dynamic clients. -type ClientPool interface { - // ClientForGroupVersionResource returns a client configured for the specified groupVersionResource. - // Resource may be empty. - ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error) - // ClientForGroupVersionKind returns a client configured for the specified groupVersionKind. - // Kind may be empty. - ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error) -} - -// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is -// optional. -type APIPathResolverFunc func(kind schema.GroupVersionKind) string - -// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API. -func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string { - if len(kind.Group) == 0 { - return "/api" - } - return "/apis" -} - -// clientPoolImpl implements ClientPool and caches clients for the resource group versions -// is asked to retrieve. This type is thread safe. -type clientPoolImpl struct { - lock sync.RWMutex - config *restclient.Config - clients map[schema.GroupVersion]*Client - apiPathResolverFunc APIPathResolverFunc - mapper meta.RESTMapper -} - -// NewClientPool returns a ClientPool from the specified config. It reuses clients for the same -// group version. It is expected this type may be wrapped by specific logic that special cases certain -// resources or groups. -func NewClientPool(config *restclient.Config, mapper meta.RESTMapper, apiPathResolverFunc APIPathResolverFunc) ClientPool { - confCopy := *config - - return &clientPoolImpl{ - config: &confCopy, - clients: map[schema.GroupVersion]*Client{}, - apiPathResolverFunc: apiPathResolverFunc, - mapper: mapper, - } -} - -// Instantiates a new dynamic client pool with the given config. -func NewDynamicClientPool(cfg *restclient.Config) ClientPool { - // restMapper is not needed when using LegacyAPIPathResolverFunc - emptyMapper := meta.MultiRESTMapper{} - return NewClientPool(cfg, emptyMapper, LegacyAPIPathResolverFunc) -} - -// ClientForGroupVersionResource uses the provided RESTMapper to identify the appropriate resource. Resource may -// be empty. If no matching kind is found the underlying client for that group is still returned. -func (c *clientPoolImpl) ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error) { - kinds, err := c.mapper.KindsFor(resource) - if err != nil { - if meta.IsNoMatchError(err) { - return c.ClientForGroupVersionKind(schema.GroupVersionKind{Group: resource.Group, Version: resource.Version}) - } - return nil, err - } - return c.ClientForGroupVersionKind(kinds[0]) -} - -// ClientForGroupVersion returns a client for the specified groupVersion, creates one if none exists. Kind -// in the GroupVersionKind may be empty. -func (c *clientPoolImpl) ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error) { - c.lock.Lock() - defer c.lock.Unlock() - - gv := kind.GroupVersion() - - // do we have a client already configured? - if existingClient, found := c.clients[gv]; found { - return existingClient, nil - } - - // avoid changing the original config - confCopy := *c.config - conf := &confCopy - - // we need to set the api path based on group version, if no group, default to legacy path - conf.APIPath = c.apiPathResolverFunc(kind) - - // we need to make a client - conf.GroupVersion = &gv - - dynamicClient, err := NewClient(conf) - if err != nil { - return nil, err - } - c.clients[gv] = dynamicClient - return dynamicClient, nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client_test.go index ffa550ed5..e8fe93867 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/client_test.go @@ -58,11 +58,10 @@ func getObject(version, kind, name string) *unstructured.Unstructured { } } -func getClientServer(gv *schema.GroupVersion, h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) { +func getClientServer(h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) { srv := httptest.NewServer(http.HandlerFunc(h)) - cl, err := NewClient(&restclient.Config{ - Host: srv.URL, - ContentConfig: restclient.ContentConfig{GroupVersion: gv}, + cl, err := NewForConfig(&restclient.Config{ + Host: srv.URL, }) if err != nil { srv.Close() @@ -81,7 +80,7 @@ func TestList(t *testing.T) { }{ { name: "normal_list", - path: "/api/gtest/vtest/rtest", + path: "/apis/gtest/vtest/rtest", resp: getListJSON("vTest", "rTestList", getJSON("vTest", "rTest", "item1"), getJSON("vTest", "rTest", "item2")), @@ -99,7 +98,7 @@ func TestList(t *testing.T) { { name: "namespaced_list", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", resp: getListJSON("vTest", "rTestList", getJSON("vTest", "rTest", "item1"), getJSON("vTest", "rTest", "item2")), @@ -116,9 +115,8 @@ func TestList(t *testing.T) { }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method) } @@ -136,7 +134,7 @@ func TestList(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).List(metav1.ListOptions{}) + got, err := cl.Resource(resource).Namespace(tc.namespace).List(metav1.ListOptions{}) if err != nil { t.Errorf("unexpected error when listing %q: %v", tc.name, err) continue @@ -150,17 +148,18 @@ func TestList(t *testing.T) { func TestGet(t *testing.T) { tcs := []struct { - resource string - namespace string - name string - path string - resp []byte - want *unstructured.Unstructured + resource string + subresource []string + namespace string + name string + path string + resp []byte + want *unstructured.Unstructured }{ { resource: "rtest", name: "normal_get", - path: "/api/gtest/vtest/rtest/normal_get", + path: "/apis/gtest/vtest/rtest/normal_get", resp: getJSON("vTest", "rTest", "normal_get"), want: getObject("vTest", "rTest", "normal_get"), }, @@ -168,30 +167,31 @@ func TestGet(t *testing.T) { resource: "rtest", namespace: "nstest", name: "namespaced_get", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_get", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_get", resp: getJSON("vTest", "rTest", "namespaced_get"), want: getObject("vTest", "rTest", "namespaced_get"), }, { - resource: "rtest/srtest", - name: "normal_subresource_get", - path: "/api/gtest/vtest/rtest/normal_subresource_get/srtest", - resp: getJSON("vTest", "srTest", "normal_subresource_get"), - want: getObject("vTest", "srTest", "normal_subresource_get"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "normal_subresource_get", + path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest", + resp: getJSON("vTest", "srTest", "normal_subresource_get"), + want: getObject("vTest", "srTest", "normal_subresource_get"), }, { - resource: "rtest/srtest", - namespace: "nstest", - name: "namespaced_subresource_get", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest", - resp: getJSON("vTest", "srTest", "namespaced_subresource_get"), - want: getObject("vTest", "srTest", "namespaced_subresource_get"), + resource: "rtest", + subresource: []string{"srtest"}, + namespace: "nstest", + name: "namespaced_subresource_get", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest", + resp: getJSON("vTest", "srTest", "namespaced_subresource_get"), + want: getObject("vTest", "srTest", "namespaced_subresource_get"), }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method) } @@ -209,7 +209,7 @@ func TestGet(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).Get(tc.name, metav1.GetOptions{}) + got, err := cl.Resource(resource).Namespace(tc.namespace).Get(tc.name, metav1.GetOptions{}, tc.subresource...) if err != nil { t.Errorf("unexpected error when getting %q: %v", tc.name, err) continue @@ -222,29 +222,50 @@ func TestGet(t *testing.T) { } func TestDelete(t *testing.T) { + background := metav1.DeletePropagationBackground + uid := types.UID("uid") + statusOK := &metav1.Status{ TypeMeta: metav1.TypeMeta{Kind: "Status"}, Status: metav1.StatusSuccess, } tcs := []struct { - namespace string - name string - path string + subresource []string + namespace string + name string + path string + deleteOptions *metav1.DeleteOptions }{ { name: "normal_delete", - path: "/api/gtest/vtest/rtest/normal_delete", + path: "/apis/gtest/vtest/rtest/normal_delete", }, { namespace: "nstest", name: "namespaced_delete", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_delete", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete", + }, + { + subresource: []string{"srtest"}, + name: "normal_delete", + path: "/apis/gtest/vtest/rtest/normal_delete/srtest", + }, + { + subresource: []string{"srtest"}, + namespace: "nstest", + name: "namespaced_delete", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete/srtest", + }, + { + namespace: "nstest", + name: "namespaced_delete_with_options", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete_with_options", + deleteOptions: &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}, PropagationPolicy: &background}, }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "DELETE" { t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method) } @@ -262,7 +283,7 @@ func TestDelete(t *testing.T) { } defer srv.Close() - err = cl.Resource(resource, tc.namespace).Delete(tc.name, nil) + err = cl.Resource(resource).Namespace(tc.namespace).Delete(tc.name, tc.deleteOptions, tc.subresource...) if err != nil { t.Errorf("unexpected error when deleting %q: %v", tc.name, err) continue @@ -282,18 +303,17 @@ func TestDeleteCollection(t *testing.T) { }{ { name: "normal_delete_collection", - path: "/api/gtest/vtest/rtest", + path: "/apis/gtest/vtest/rtest", }, { namespace: "nstest", name: "namespaced_delete_collection", - path: "/api/gtest/vtest/namespaces/nstest/rtest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "DELETE" { t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method) } @@ -311,7 +331,7 @@ func TestDeleteCollection(t *testing.T) { } defer srv.Close() - err = cl.Resource(resource, tc.namespace).DeleteCollection(nil, metav1.ListOptions{}) + err = cl.Resource(resource).Namespace(tc.namespace).DeleteCollection(nil, metav1.ListOptions{}) if err != nil { t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err) continue @@ -321,43 +341,45 @@ func TestDeleteCollection(t *testing.T) { func TestCreate(t *testing.T) { tcs := []struct { - resource string - name string - namespace string - obj *unstructured.Unstructured - path string + resource string + subresource []string + name string + namespace string + obj *unstructured.Unstructured + path string }{ { resource: "rtest", name: "normal_create", - path: "/api/gtest/vtest/rtest", - obj: getObject("vTest", "rTest", "normal_create"), + path: "/apis/gtest/vtest/rtest", + obj: getObject("gtest/vTest", "rTest", "normal_create"), }, { resource: "rtest", name: "namespaced_create", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest", - obj: getObject("vTest", "rTest", "namespaced_create"), + path: "/apis/gtest/vtest/namespaces/nstest/rtest", + obj: getObject("gtest/vTest", "rTest", "namespaced_create"), }, { - resource: "rtest/srtest", - name: "normal_subresource_create", - path: "/api/gtest/vtest/rtest/normal_subresource_create/srtest", - obj: getObject("vTest", "srTest", "normal_subresource_create"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "normal_subresource_create", + path: "/apis/gtest/vtest/rtest/normal_subresource_create/srtest", + obj: getObject("vTest", "srTest", "normal_subresource_create"), }, { - resource: "rtest/srtest", - name: "namespaced_subresource_create", - namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_create/srtest", - obj: getObject("vTest", "srTest", "namespaced_subresource_create"), + resource: "rtest/", + subresource: []string{"srtest"}, + name: "namespaced_subresource_create", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_create/srtest", + obj: getObject("vTest", "srTest", "namespaced_subresource_create"), }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method) } @@ -382,7 +404,7 @@ func TestCreate(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).Create(tc.obj) + got, err := cl.Resource(resource).Namespace(tc.namespace).Create(tc.obj, tc.subresource...) if err != nil { t.Errorf("unexpected error when creating %q: %v", tc.name, err) continue @@ -396,43 +418,45 @@ func TestCreate(t *testing.T) { func TestUpdate(t *testing.T) { tcs := []struct { - resource string - name string - namespace string - obj *unstructured.Unstructured - path string + resource string + subresource []string + name string + namespace string + obj *unstructured.Unstructured + path string }{ { resource: "rtest", name: "normal_update", - path: "/api/gtest/vtest/rtest/normal_update", - obj: getObject("vTest", "rTest", "normal_update"), + path: "/apis/gtest/vtest/rtest/normal_update", + obj: getObject("gtest/vTest", "rTest", "normal_update"), }, { resource: "rtest", name: "namespaced_update", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_update", - obj: getObject("vTest", "rTest", "namespaced_update"), + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update", + obj: getObject("gtest/vTest", "rTest", "namespaced_update"), }, { - resource: "rtest/srtest", - name: "normal_subresource_update", - path: "/api/gtest/vtest/rtest/normal_update/srtest", - obj: getObject("vTest", "srTest", "normal_update"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "normal_subresource_update", + path: "/apis/gtest/vtest/rtest/normal_update/srtest", + obj: getObject("gtest/vTest", "srTest", "normal_update"), }, { - resource: "rtest/srtest", - name: "namespaced_subresource_update", - namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest", - obj: getObject("vTest", "srTest", "namespaced_update"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "namespaced_subresource_update", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest", + obj: getObject("gtest/vTest", "srTest", "namespaced_update"), }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "PUT" { t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method) } @@ -457,7 +481,7 @@ func TestUpdate(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).Update(tc.obj) + got, err := cl.Resource(resource).Namespace(tc.namespace).Update(tc.obj, tc.subresource...) if err != nil { t.Errorf("unexpected error when updating %q: %v", tc.name, err) continue @@ -479,30 +503,29 @@ func TestWatch(t *testing.T) { }{ { name: "normal_watch", - path: "/api/gtest/vtest/rtest", + path: "/apis/gtest/vtest/rtest", query: "watch=true", events: []watch.Event{ - {Type: watch.Added, Object: getObject("vTest", "rTest", "normal_watch")}, - {Type: watch.Modified, Object: getObject("vTest", "rTest", "normal_watch")}, - {Type: watch.Deleted, Object: getObject("vTest", "rTest", "normal_watch")}, + {Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + {Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, + {Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "normal_watch")}, }, }, { name: "namespaced_watch", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest", query: "watch=true", events: []watch.Event{ - {Type: watch.Added, Object: getObject("vTest", "rTest", "namespaced_watch")}, - {Type: watch.Modified, Object: getObject("vTest", "rTest", "namespaced_watch")}, - {Type: watch.Deleted, Object: getObject("vTest", "rTest", "namespaced_watch")}, + {Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + {Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, + {Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")}, }, }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method) } @@ -514,7 +537,7 @@ func TestWatch(t *testing.T) { t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query) } - enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{}) + enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, unstructured.UnstructuredJSONScheme), unstructured.UnstructuredJSONScheme) for _, e := range tc.events { enc.Encode(&e) } @@ -525,7 +548,7 @@ func TestWatch(t *testing.T) { } defer srv.Close() - watcher, err := cl.Resource(resource, tc.namespace).Watch(metav1.ListOptions{}) + watcher, err := cl.Resource(resource).Namespace(tc.namespace).Watch(metav1.ListOptions{}) if err != nil { t.Errorf("unexpected error when watching %q: %v", tc.name, err) continue @@ -542,48 +565,50 @@ func TestWatch(t *testing.T) { func TestPatch(t *testing.T) { tcs := []struct { - resource string - name string - namespace string - patch []byte - want *unstructured.Unstructured - path string + resource string + subresource []string + name string + namespace string + patch []byte + want *unstructured.Unstructured + path string }{ { resource: "rtest", name: "normal_patch", - path: "/api/gtest/vtest/rtest/normal_patch", - patch: getJSON("vTest", "rTest", "normal_patch"), - want: getObject("vTest", "rTest", "normal_patch"), + path: "/apis/gtest/vtest/rtest/normal_patch", + patch: getJSON("gtest/vTest", "rTest", "normal_patch"), + want: getObject("gtest/vTest", "rTest", "normal_patch"), }, { resource: "rtest", name: "namespaced_patch", namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_patch", - patch: getJSON("vTest", "rTest", "namespaced_patch"), - want: getObject("vTest", "rTest", "namespaced_patch"), + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_patch", + patch: getJSON("gtest/vTest", "rTest", "namespaced_patch"), + want: getObject("gtest/vTest", "rTest", "namespaced_patch"), }, { - resource: "rtest/srtest", - name: "normal_subresource_patch", - path: "/api/gtest/vtest/rtest/normal_subresource_patch/srtest", - patch: getJSON("vTest", "srTest", "normal_subresource_patch"), - want: getObject("vTest", "srTest", "normal_subresource_patch"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "normal_subresource_patch", + path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest", + patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"), + want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"), }, { - resource: "rtest/srtest", - name: "namespaced_subresource_patch", - namespace: "nstest", - path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest", - patch: getJSON("vTest", "srTest", "namespaced_subresource_patch"), - want: getObject("vTest", "srTest", "namespaced_subresource_patch"), + resource: "rtest", + subresource: []string{"srtest"}, + name: "namespaced_subresource_patch", + namespace: "nstest", + path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest", + patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"), + want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"), }, } for _, tc := range tcs { - gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"} - resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0} - cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) { + resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource} + cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) { if r.Method != "PATCH" { t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method) } @@ -613,7 +638,7 @@ func TestPatch(t *testing.T) { } defer srv.Close() - got, err := cl.Resource(resource, tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch) + got, err := cl.Resource(resource).Namespace(tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch, tc.subresource...) if err != nil { t.Errorf("unexpected error when patching %q: %v", tc.name, err) continue @@ -624,11 +649,3 @@ func TestPatch(t *testing.T) { } } } - -func TestVersionedParameterEncoderWithV1Fallback(t *testing.T) { - enc := VersionedParameterEncoderWithV1Fallback - _, err := enc.EncodeParameters(&metav1.ListOptions{}, schema.GroupVersion{Group: "foo.bar.com", Version: "v4"}) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/dynamic_util.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/dynamic_util.go deleted file mode 100644 index c2cf0daea..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/dynamic_util.go +++ /dev/null @@ -1,96 +0,0 @@ -/* -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 dynamic - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// VersionInterfaces provides an object converter and metadata -// accessor appropriate for use with unstructured objects. -func VersionInterfaces(schema.GroupVersion) (*meta.VersionInterfaces, error) { - return &meta.VersionInterfaces{ - ObjectConvertor: &unstructured.UnstructuredObjectConverter{}, - MetadataAccessor: meta.NewAccessor(), - }, nil -} - -// NewDiscoveryRESTMapper returns a RESTMapper based on discovery information. -func NewDiscoveryRESTMapper(resources []*metav1.APIResourceList, versionFunc meta.VersionInterfacesFunc) (*meta.DefaultRESTMapper, error) { - rm := meta.NewDefaultRESTMapper(nil, versionFunc) - for _, resourceList := range resources { - gv, err := schema.ParseGroupVersion(resourceList.GroupVersion) - if err != nil { - return nil, err - } - - for _, resource := range resourceList.APIResources { - gvk := gv.WithKind(resource.Kind) - scope := meta.RESTScopeRoot - if resource.Namespaced { - scope = meta.RESTScopeNamespace - } - rm.Add(gvk, scope) - } - } - return rm, nil -} - -// ObjectTyper provides an ObjectTyper implementation for -// unstructured.Unstructured object based on discovery information. -type ObjectTyper struct { - registered map[schema.GroupVersionKind]bool -} - -// NewObjectTyper constructs an ObjectTyper from discovery information. -func NewObjectTyper(resources []*metav1.APIResourceList) (runtime.ObjectTyper, error) { - ot := &ObjectTyper{registered: make(map[schema.GroupVersionKind]bool)} - for _, resourceList := range resources { - gv, err := schema.ParseGroupVersion(resourceList.GroupVersion) - if err != nil { - return nil, err - } - - for _, resource := range resourceList.APIResources { - ot.registered[gv.WithKind(resource.Kind)] = true - } - } - return ot, nil -} - -// ObjectKinds returns a slice of one element with the -// group,version,kind of the provided object, or an error if the -// object is not *unstructured.Unstructured or has no group,version,kind -// information. -func (ot *ObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { - if _, ok := obj.(*unstructured.Unstructured); !ok { - return nil, false, fmt.Errorf("type %T is invalid for determining dynamic object types", obj) - } - return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil -} - -// Recognizes returns true if the provided group,version,kind was in -// the discovery information. -func (ot *ObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool { - return ot.registered[gvk] -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/dynamic_util_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/dynamic_util_test.go deleted file mode 100644 index cdc68e018..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/dynamic_util_test.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -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 dynamic - -import ( - "testing" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestDiscoveryRESTMapper(t *testing.T) { - resources := []*metav1.APIResourceList{ - { - GroupVersion: "test/beta1", - APIResources: []metav1.APIResource{ - { - Name: "test_kinds", - Namespaced: true, - Kind: "test_kind", - }, - }, - }, - } - - gvk := schema.GroupVersionKind{ - Group: "test", - Version: "beta1", - Kind: "test_kind", - } - - mapper, err := NewDiscoveryRESTMapper(resources, VersionInterfaces) - if err != nil { - t.Fatalf("unexpected error creating mapper: %s", err) - } - - for _, res := range []schema.GroupVersionResource{ - { - Group: "test", - Version: "beta1", - Resource: "test_kinds", - }, - { - Version: "beta1", - Resource: "test_kinds", - }, - { - Group: "test", - Resource: "test_kinds", - }, - { - Resource: "test_kinds", - }, - } { - got, err := mapper.KindFor(res) - if err != nil { - t.Errorf("KindFor(%#v) unexpected error: %s", res, err) - continue - } - - if got != gvk { - t.Errorf("KindFor(%#v) = %#v; want %#v", res, got, gvk) - } - } -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/BUILD index d006188f8..e4d949f71 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/BUILD @@ -7,22 +7,20 @@ load( go_library( name = "go_default_library", - srcs = [ - "client.go", - "client_pool.go", - ], + srcs = ["simple.go"], importpath = "k8s.io/client-go/dynamic/fake", deps = [ + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels: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:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/client.go deleted file mode 100644 index 8399076c2..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/client.go +++ /dev/null @@ -1,163 +0,0 @@ -/* -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 fake provides a fake client interface to arbitrary Kubernetes -// APIs that exposes common high level operations and exposes common -// metadata. -package fake - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/testing" - "k8s.io/client-go/util/flowcontrol" -) - -// FakeClient is a fake implementation of dynamic.Interface. -type FakeClient struct { - GroupVersion schema.GroupVersion - - *testing.Fake -} - -// GetRateLimiter returns the rate limiter for this client. -func (c *FakeClient) GetRateLimiter() flowcontrol.RateLimiter { - return nil -} - -// Resource returns an API interface to the specified resource for this client's -// group and version. If resource is not a namespaced resource, then namespace -// is ignored. The ResourceClient inherits the parameter codec of this client -func (c *FakeClient) Resource(resource *metav1.APIResource, namespace string) dynamic.ResourceInterface { - return &FakeResourceClient{ - Resource: c.GroupVersion.WithResource(resource.Name), - Kind: c.GroupVersion.WithKind(resource.Kind), - Namespace: namespace, - - Fake: c.Fake, - } -} - -// ParameterCodec returns a client with the provided parameter codec. -func (c *FakeClient) ParameterCodec(parameterCodec runtime.ParameterCodec) dynamic.Interface { - return &FakeClient{ - Fake: c.Fake, - } -} - -// FakeResourceClient is a fake implementation of dynamic.ResourceInterface -type FakeResourceClient struct { - Resource schema.GroupVersionResource - Kind schema.GroupVersionKind - Namespace string - - *testing.Fake -} - -// List returns a list of objects for this resource. -func (c *FakeResourceClient) List(opts metav1.ListOptions) (runtime.Object, error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(c.Resource, c.Kind, c.Namespace, opts), &unstructured.UnstructuredList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &unstructured.UnstructuredList{} - for _, item := range obj.(*unstructured.UnstructuredList).Items { - if label.Matches(labels.Set(item.GetLabels())) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Get gets the resource with the specified name. -func (c *FakeResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(c.Resource, c.Namespace, name), &unstructured.Unstructured{}) - - if obj == nil { - return nil, err - } - - return obj.(*unstructured.Unstructured), err -} - -// Delete deletes the resource with the specified name. -func (c *FakeResourceClient) Delete(name string, opts *metav1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteAction(c.Resource, c.Namespace, name), &unstructured.Unstructured{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeResourceClient) DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteCollectionAction(c.Resource, c.Namespace, listOptions), &unstructured.Unstructured{}) - - return err -} - -// Create creates the provided resource. -func (c *FakeResourceClient) Create(inObj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(c.Resource, c.Namespace, inObj), &unstructured.Unstructured{}) - - if obj == nil { - return nil, err - } - return obj.(*unstructured.Unstructured), err -} - -// Update updates the provided resource. -func (c *FakeResourceClient) Update(inObj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(c.Resource, c.Namespace, inObj), &unstructured.Unstructured{}) - - if obj == nil { - return nil, err - } - return obj.(*unstructured.Unstructured), err -} - -// Watch returns a watch.Interface that watches the resource. -func (c *FakeResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(c.Resource, c.Namespace, opts)) -} - -// Patch patches the provided resource. -func (c *FakeResourceClient) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) { - obj, err := c.Fake. - Invokes(testing.NewPatchAction(c.Resource, c.Namespace, name, data), &unstructured.Unstructured{}) - - if obj == nil { - return nil, err - } - return obj.(*unstructured.Unstructured), err -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/client_pool.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/client_pool.go deleted file mode 100644 index 7ec114892..000000000 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/client_pool.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -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 fake provides a fake client interface to arbitrary Kubernetes -// APIs that exposes common high level operations and exposes common -// metadata. -package fake - -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/testing" -) - -// FakeClientPool provides a fake implementation of dynamic.ClientPool. -// It assumes resource GroupVersions are the same as their corresponding kind GroupVersions. -type FakeClientPool struct { - testing.Fake -} - -// ClientForGroupVersionKind returns a client configured for the specified groupVersionResource. -// Resource may be empty. -func (p *FakeClientPool) ClientForGroupVersionResource(resource schema.GroupVersionResource) (dynamic.Interface, error) { - return p.ClientForGroupVersionKind(resource.GroupVersion().WithKind("")) -} - -// ClientForGroupVersionKind returns a client configured for the specified groupVersionKind. -// Kind may be empty. -func (p *FakeClientPool) ClientForGroupVersionKind(kind schema.GroupVersionKind) (dynamic.Interface, error) { - // we can just create a new client every time for testing purposes - return &FakeClient{ - GroupVersion: kind.GroupVersion(), - Fake: &p.Fake, - }, nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/simple.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/simple.go new file mode 100644 index 000000000..a71cec50e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/fake/simple.go @@ -0,0 +1,363 @@ +/* +Copyright 2018 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 fake + +import ( + "strings" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/testing" +) + +func NewSimpleDynamicClient(scheme *runtime.Scheme, objects ...runtime.Object) *FakeDynamicClient { + codecs := serializer.NewCodecFactory(scheme) + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &FakeDynamicClient{} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type FakeDynamicClient struct { + testing.Fake + scheme *runtime.Scheme +} + +type dynamicResourceClient struct { + client *FakeDynamicClient + namespace string + resource schema.GroupVersionResource +} + +var _ dynamic.Interface = &FakeDynamicClient{} + +func (c *FakeDynamicClient) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableResourceInterface { + return &dynamicResourceClient{client: c, resource: resource} +} + +func (c *dynamicResourceClient) Namespace(ns string) dynamic.ResourceInterface { + ret := *c + ret.namespace = ns + return &ret +} + +func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootCreateAction(c.resource, obj), obj) + + case len(c.namespace) == 0 && len(subresources) > 0: + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + name := accessor.GetName() + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), obj), obj) + + case len(c.namespace) > 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewCreateAction(c.resource, c.namespace, obj), obj) + + case len(c.namespace) > 0 && len(subresources) > 0: + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + name := accessor.GetName() + uncastRet, err = c.client.Fake. + Invokes(testing.NewCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), c.namespace, obj), obj) + + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} + +func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootUpdateAction(c.resource, obj), obj) + + case len(c.namespace) == 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), obj), obj) + + case len(c.namespace) > 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewUpdateAction(c.resource, c.namespace, obj), obj) + + case len(c.namespace) > 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, obj), obj) + + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} + +func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(c.resource, "status", obj), obj) + + case len(c.namespace) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewUpdateSubresourceAction(c.resource, "status", c.namespace, obj), obj) + + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} + +func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error { + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + _, err = c.client.Fake. + Invokes(testing.NewRootDeleteAction(c.resource, name), &metav1.Status{Status: "dynamic delete fail"}) + + case len(c.namespace) == 0 && len(subresources) > 0: + _, err = c.client.Fake. + Invokes(testing.NewRootDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic delete fail"}) + + case len(c.namespace) > 0 && len(subresources) == 0: + _, err = c.client.Fake. + Invokes(testing.NewDeleteAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic delete fail"}) + + case len(c.namespace) > 0 && len(subresources) > 0: + _, err = c.client.Fake. + Invokes(testing.NewDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, name), &metav1.Status{Status: "dynamic delete fail"}) + } + + return err +} + +func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error { + var err error + switch { + case len(c.namespace) == 0: + action := testing.NewRootDeleteCollectionAction(c.resource, listOptions) + _, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"}) + + case len(c.namespace) > 0: + action := testing.NewDeleteCollectionAction(c.resource, c.namespace, listOptions) + _, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"}) + + } + + return err +} + +func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootGetAction(c.resource, name), &metav1.Status{Status: "dynamic get fail"}) + + case len(c.namespace) == 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootGetSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"}) + + case len(c.namespace) > 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewGetAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic get fail"}) + + case len(c.namespace) > 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewGetSubresourceAction(c.resource, c.namespace, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"}) + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} + +func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) { + var obj runtime.Object + var err error + switch { + case len(c.namespace) == 0: + obj, err = c.client.Fake. + Invokes(testing.NewRootListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, opts), &metav1.Status{Status: "dynamic list fail"}) + + case len(c.namespace) > 0: + obj, err = c.client.Fake. + Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"}) + + } + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + + retUnstructured := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(obj, retUnstructured, nil); err != nil { + return nil, err + } + entireList, err := retUnstructured.ToList() + if err != nil { + return nil, err + } + + list := &unstructured.UnstructuredList{} + for _, item := range entireList.Items { + metadata, err := meta.Accessor(item) + if err != nil { + return nil, err + } + if label.Matches(labels.Set(metadata.GetLabels())) { + list.Items = append(list.Items, item) + } + } + return list, nil +} + +func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { + switch { + case len(c.namespace) == 0: + return c.client.Fake. + InvokesWatch(testing.NewRootWatchAction(c.resource, opts)) + + case len(c.namespace) > 0: + return c.client.Fake. + InvokesWatch(testing.NewWatchAction(c.resource, c.namespace, opts)) + + } + + panic("math broke") +} + +func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) { + var uncastRet runtime.Object + var err error + switch { + case len(c.namespace) == 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootPatchAction(c.resource, name, data), &metav1.Status{Status: "dynamic patch fail"}) + + case len(c.namespace) == 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"}) + + case len(c.namespace) > 0 && len(subresources) == 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewPatchAction(c.resource, c.namespace, name, data), &metav1.Status{Status: "dynamic patch fail"}) + + case len(c.namespace) > 0 && len(subresources) > 0: + uncastRet, err = c.client.Fake. + Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"}) + + } + + if err != nil { + return nil, err + } + if uncastRet == nil { + return nil, err + } + + ret := &unstructured.Unstructured{} + if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil { + return nil, err + } + return ret, err +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/interface.go new file mode 100644 index 000000000..3f364f872 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/interface.go @@ -0,0 +1,59 @@ +/* +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 dynamic + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" +) + +type Interface interface { + Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface +} + +type ResourceInterface interface { + Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) + Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) + UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) + Delete(name string, options *metav1.DeleteOptions, subresources ...string) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) + List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) +} + +type NamespaceableResourceInterface interface { + Namespace(string) ResourceInterface + ResourceInterface +} + +// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is optional. +// TODO find a better place to move this for existing callers +type APIPathResolverFunc func(kind schema.GroupVersionKind) string + +// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API. +// TODO find a better place to move this for existing callers +func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string { + if len(kind.Group) == 0 { + return "/api" + } + return "/apis" +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/scheme.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/scheme.go new file mode 100644 index 000000000..c4aa081f9 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/scheme.go @@ -0,0 +1,98 @@ +/* +Copyright 2018 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 dynamic + +import ( + 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" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/apimachinery/pkg/runtime/serializer/versioning" +) + +var watchScheme = runtime.NewScheme() +var basicScheme = runtime.NewScheme() +var deleteScheme = runtime.NewScheme() +var parameterScheme = runtime.NewScheme() +var deleteOptionsCodec = serializer.NewCodecFactory(deleteScheme) +var dynamicParameterCodec = runtime.NewParameterCodec(parameterScheme) + +var versionV1 = schema.GroupVersion{Version: "v1"} + +func init() { + metav1.AddToGroupVersion(watchScheme, versionV1) + metav1.AddToGroupVersion(basicScheme, versionV1) + metav1.AddToGroupVersion(parameterScheme, versionV1) + metav1.AddToGroupVersion(deleteScheme, versionV1) +} + +var watchJsonSerializerInfo = runtime.SerializerInfo{ + MediaType: "application/json", + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, false), + PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, true), + StreamSerializer: &runtime.StreamSerializerInfo{ + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, false), + Framer: json.Framer, + }, +} + +// watchNegotiatedSerializer is used to read the wrapper of the watch stream +type watchNegotiatedSerializer struct{} + +var watchNegotiatedSerializerInstance = watchNegotiatedSerializer{} + +func (s watchNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { + return []runtime.SerializerInfo{watchJsonSerializerInfo} +} + +func (s watchNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { + return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, nil, gv, nil) +} + +func (s watchNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { + return versioning.NewDefaultingCodecForScheme(watchScheme, nil, decoder, nil, gv) +} + +// basicNegotiatedSerializer is used to handle discovery and error handling serialization +type basicNegotiatedSerializer struct{} + +func (s basicNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { + return []runtime.SerializerInfo{ + { + MediaType: "application/json", + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false), + PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, true), + StreamSerializer: &runtime.StreamSerializerInfo{ + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false), + Framer: json.Framer, + }, + }, + } +} + +func (s basicNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { + return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, nil, gv, nil) +} + +func (s basicNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { + return versioning.NewDefaultingCodecForScheme(watchScheme, nil, decoder, nil, gv) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/simple.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/simple.go new file mode 100644 index 000000000..88e9cc2b0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/dynamic/simple.go @@ -0,0 +1,287 @@ +/* +Copyright 2018 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 dynamic + +import ( + "io" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer/streaming" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/rest" +) + +type dynamicClient struct { + client *rest.RESTClient +} + +var _ Interface = &dynamicClient{} + +func NewForConfig(inConfig *rest.Config) (Interface, error) { + config := rest.CopyConfig(inConfig) + // for serializing the options + config.GroupVersion = &schema.GroupVersion{} + config.APIPath = "/if-you-see-this-search-for-the-break" + config.AcceptContentTypes = "application/json" + config.ContentType = "application/json" + config.NegotiatedSerializer = basicNegotiatedSerializer{} // this gets used for discovery and error handling types + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + restClient, err := rest.RESTClientFor(config) + if err != nil { + return nil, err + } + + return &dynamicClient{client: restClient}, nil +} + +type dynamicResourceClient struct { + client *dynamicClient + namespace string + resource schema.GroupVersionResource +} + +func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface { + return &dynamicResourceClient{client: c, resource: resource} +} + +func (c *dynamicResourceClient) Namespace(ns string) ResourceInterface { + ret := *c + ret.namespace = ns + return &ret +} + +func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) { + outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) + if err != nil { + return nil, err + } + name := "" + if len(subresources) > 0 { + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + name = accessor.GetName() + } + + result := c.client.client.Post().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(outBytes).Do() + if err := result.Error(); err != nil { + return nil, err + } + + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) { + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) + if err != nil { + return nil, err + } + + result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), subresources...)...).Body(outBytes).Do() + if err := result.Error(); err != nil { + return nil, err + } + + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + accessor, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + + outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) + if err != nil { + return nil, err + } + + result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), "status")...).Body(outBytes).Do() + if err := result.Error(); err != nil { + return nil, err + } + + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error { + if opts == nil { + opts = &metav1.DeleteOptions{} + } + deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts) + if err != nil { + return err + } + + result := c.client.client.Delete().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(deleteOptionsByte).Do() + return result.Error() +} + +func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error { + if opts == nil { + opts = &metav1.DeleteOptions{} + } + deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts) + if err != nil { + return err + } + + result := c.client.client.Delete().AbsPath(c.makeURLSegments("")...).Body(deleteOptionsByte).SpecificallyVersionedParams(&listOptions, dynamicParameterCodec, versionV1).Do() + return result.Error() +} + +func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) { + result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do() + if err := result.Error(); err != nil { + return nil, err + } + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) { + result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do() + if err := result.Error(); err != nil { + return nil, err + } + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + if list, ok := uncastObj.(*unstructured.UnstructuredList); ok { + return list, nil + } + + list, err := uncastObj.(*unstructured.Unstructured).ToList() + if err != nil { + return nil, err + } + return list, nil +} + +func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { + internalGV := schema.GroupVersions{ + {Group: c.resource.Group, Version: runtime.APIVersionInternal}, + // always include the legacy group as a decoding target to handle non-error `Status` return types + {Group: "", Version: runtime.APIVersionInternal}, + } + s := &rest.Serializers{ + Encoder: watchNegotiatedSerializerInstance.EncoderForVersion(watchJsonSerializerInfo.Serializer, c.resource.GroupVersion()), + Decoder: watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV), + + RenegotiatedDecoder: func(contentType string, params map[string]string) (runtime.Decoder, error) { + return watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV), nil + }, + StreamingSerializer: watchJsonSerializerInfo.StreamSerializer.Serializer, + Framer: watchJsonSerializerInfo.StreamSerializer.Framer, + } + + wrappedDecoderFn := func(body io.ReadCloser) streaming.Decoder { + framer := s.Framer.NewFrameReader(body) + return streaming.NewDecoder(framer, s.StreamingSerializer) + } + + opts.Watch = true + return c.client.client.Get().AbsPath(c.makeURLSegments("")...). + SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1). + WatchWithSpecificDecoders(wrappedDecoderFn, unstructured.UnstructuredJSONScheme) +} + +func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) { + result := c.client.client.Patch(pt).AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(data).Do() + if err := result.Error(); err != nil { + return nil, err + } + retBytes, err := result.Raw() + if err != nil { + return nil, err + } + uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes) + if err != nil { + return nil, err + } + return uncastObj.(*unstructured.Unstructured), nil +} + +func (c *dynamicResourceClient) makeURLSegments(name string) []string { + url := []string{} + if len(c.resource.Group) == 0 { + url = append(url, "api") + } else { + url = append(url, "apis", c.resource.Group) + } + url = append(url, c.resource.Version) + + if len(c.namespace) > 0 { + url = append(url, "namespaces", c.namespace) + } + url = append(url, c.resource.Resource) + + if len(name) > 0 { + url = append(url, name) + } + + return url +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/BUILD index 2da72ec9f..e8f23c409 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/BUILD @@ -16,7 +16,7 @@ go_library( srcs = ["main.go"], importpath = "k8s.io/client-go/examples/create-update-delete-deployment", deps = [ - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/main.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/main.go index f6d622745..333ada018 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/main.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/main.go @@ -24,7 +24,7 @@ import ( "os" "path/filepath" - appsv1beta1 "k8s.io/api/apps/v1beta1" + appsv1 "k8s.io/api/apps/v1" apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -53,14 +53,19 @@ func main() { panic(err) } - deploymentsClient := clientset.AppsV1beta1().Deployments(apiv1.NamespaceDefault) + deploymentsClient := clientset.AppsV1().Deployments(apiv1.NamespaceDefault) - deployment := &appsv1beta1.Deployment{ + deployment := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "demo-deployment", }, - Spec: appsv1beta1.DeploymentSpec{ + Spec: appsv1.DeploymentSpec{ Replicas: int32Ptr(2), + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "demo", + }, + }, Template: apiv1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ @@ -128,27 +133,6 @@ func main() { } fmt.Println("Updated deployment...") - // Rollback Deployment - prompt() - fmt.Println("Rolling back deployment...") - // Once again use RetryOnConflict to avoid update conflicts - retryErr = retry.RetryOnConflict(retry.DefaultRetry, func() error { - result, getErr := deploymentsClient.Get("demo-deployment", metav1.GetOptions{}) - if getErr != nil { - panic(fmt.Errorf("Failed to get latest version of Deployment: %v", getErr)) - } - - result.Spec.RollbackTo = &appsv1beta1.RollbackConfig{ - Revision: 0, // can be specific revision number, or 0 for last revision - } - _, updateErr := deploymentsClient.Update(result) - return updateErr - }) - if retryErr != nil { - panic(fmt.Errorf("Rollback failed: %v", retryErr)) - } - fmt.Println("Rolled back deployment...") - // List Deployments prompt() fmt.Printf("Listing deployments in namespace %q:\n", apiv1.NamespaceDefault) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/BUILD index 99486a1c8..6514fa417 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/BUILD @@ -33,6 +33,7 @@ go_library( "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/interface.go index 138dccc26..7a0783cc3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1/initializerconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1/initializerconfiguration.go index 659a04caf..463ca00e7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1/initializerconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1/initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1/interface.go index 54df1caf3..0f47d65d8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/interface.go index 5364c1ae1..d1e2b61be 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go index 6e65a86c3..58f065de2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/validatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/validatingwebhookconfiguration.go index 42d16177c..bfa89cef5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/validatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/admissionregistration/v1beta1/validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/interface.go index 7013d4d6f..02eefe584 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/controllerrevision.go index 3fe6630ff..58bf42146 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/daemonset.go index 4e10d6f6f..14d890ba3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/deployment.go index e08f42ddb..dd8587508 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/interface.go index f3abfa9aa..fab1e76bd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/replicaset.go index 2a17836cb..b1ab1ebe7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/statefulset.go index e7084af58..f488e3b98 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/controllerrevision.go index b4878e724..4283d3822 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/deployment.go index 589ec39a5..1e7620beb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/interface.go index c0a487ca2..326939cd1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/statefulset.go index f12364c51..94fd0f93c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/controllerrevision.go index a2f3ceaac..28e241b18 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/daemonset.go index 700895e61..bb25a1945 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/deployment.go index ba1a3cf9b..457ca30a1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/interface.go index 93a1940d9..ded89bd5b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/replicaset.go index 6a46b810b..1558c1416 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/statefulset.go index 841cbd8ab..ae929d656 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/apps/v1beta2/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/interface.go index 347d6f628..1494d19d6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v1/horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v1/horizontalpodautoscaler.go index 1215c7f3b..71991b7f5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v1/interface.go index ffa7a168e..601d0f77f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v2beta1/horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v2beta1/horizontalpodautoscaler.go index 208757de3..1546eb9b5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v2beta1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v2beta1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v2beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v2beta1/interface.go index 37ce2bc5f..ff5d44b09 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v2beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/autoscaling/v2beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/interface.go index f08227ba4..fa428869d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1/interface.go index 5a09dc7ce..67d71adc2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1/job.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1/job.go index 36d3cef42..6be8a025e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1/job.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1/job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1beta1/cronjob.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1beta1/cronjob.go index 9dfaed490..3ace60109 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1beta1/cronjob.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1beta1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1beta1/interface.go index 3ba8401ac..76cae22d6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v2alpha1/cronjob.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v2alpha1/cronjob.go index 82bc9422f..6608e4614 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v2alpha1/cronjob.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v2alpha1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v2alpha1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v2alpha1/interface.go index 3c2780fd2..6c5bf236f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v2alpha1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/batch/v2alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/interface.go index 9b3121186..cff455403 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/v1beta1/certificatesigningrequest.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/v1beta1/certificatesigningrequest.go index a3d6c2d6a..b442ff788 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/v1beta1/certificatesigningrequest.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/v1beta1/certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/v1beta1/interface.go index 718f370ee..258dd1d0e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/certificates/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/interface.go index aba68f349..de8396b51 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/componentstatus.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/componentstatus.go index 33fc65a52..cc60d480f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/componentstatus.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/configmap.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/configmap.go index 618e74994..ebd86c2d8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/configmap.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/endpoints.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/endpoints.go index fa56fbc25..b7362d080 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/endpoints.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/event.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/event.go index 515784175..905db2dba 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/event.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/interface.go index 9580dd9e0..b2216a05c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/limitrange.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/limitrange.go index 8edffdfb7..39d0340df 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/limitrange.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/namespace.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/namespace.go index e1925fed1..5830c88f5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/namespace.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/node.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/node.go index dc829bcd6..202cb3b7b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/node.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/persistentvolume.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/persistentvolume.go index b3ed3c0d0..3f9af92a3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/persistentvolume.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/persistentvolumeclaim.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/persistentvolumeclaim.go index 9b4fde573..b4946e849 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/persistentvolumeclaim.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/pod.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/pod.go index 18e61b225..e964d5812 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/pod.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/podtemplate.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/podtemplate.go index a7de79b18..542fd032e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/podtemplate.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/replicationcontroller.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/replicationcontroller.go index df0a1d604..c5c009b07 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/replicationcontroller.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/resourcequota.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/resourcequota.go index 89a56acb8..85ea9098b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/resourcequota.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/secret.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/secret.go index 05939c861..6c0c5a847 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/secret.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/service.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/service.go index 0e8aa0f7a..c2bb80250 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/service.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/serviceaccount.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/serviceaccount.go index bf3b5a7bb..2d0b94a63 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/serviceaccount.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/core/v1/serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/interface.go index e8ad97c3c..af30a3913 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/v1beta1/event.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/v1beta1/event.go index 8f2b27cf5..cb757c5bc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/v1beta1/event.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/v1beta1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/v1beta1/interface.go index 0c67badb2..c71888c9a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/events/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/interface.go index 93d912ca5..94a66d385 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/daemonset.go index 0f24af5ca..3064384b2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/deployment.go index 980eecb0f..a6b8b68e6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/ingress.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/ingress.go index b250d22a3..ec8147c19 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/ingress.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/interface.go index 10aa1b704..a259d27ae 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/podsecuritypolicy.go index 76b83b823..15414d8ed 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/replicaset.go index 31c6a1b86..a63d769e5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/extensions/v1beta1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/factory.go index 455afc2b9..902195d6c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -45,12 +45,16 @@ import ( cache "k8s.io/client-go/tools/cache" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client kubernetes.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -58,23 +62,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client kubernetes.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client kubernetes.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client kubernetes.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -123,7 +166,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/generic.go index 801267edf..08c43906f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -41,6 +41,7 @@ import ( rbac_v1alpha1 "k8s.io/api/rbac/v1alpha1" rbac_v1beta1 "k8s.io/api/rbac/v1beta1" scheduling_v1alpha1 "k8s.io/api/scheduling/v1alpha1" + scheduling_v1beta1 "k8s.io/api/scheduling/v1beta1" settings_v1alpha1 "k8s.io/api/settings/v1alpha1" storage_v1 "k8s.io/api/storage/v1" storage_v1alpha1 "k8s.io/api/storage/v1alpha1" @@ -235,6 +236,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case scheduling_v1alpha1.SchemeGroupVersion.WithResource("priorityclasses"): return &genericInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1alpha1().PriorityClasses().Informer()}, nil + // Group=scheduling.k8s.io, Version=v1beta1 + case scheduling_v1beta1.SchemeGroupVersion.WithResource("priorityclasses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1beta1().PriorityClasses().Informer()}, nil + // Group=settings.k8s.io, Version=v1alpha1 case settings_v1alpha1.SchemeGroupVersion.WithResource("podpresets"): return &genericInformer{resource: resource.GroupResource(), informer: f.Settings().V1alpha1().PodPresets().Informer()}, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/internalinterfaces/factory_interfaces.go index 4e2a28fc7..5e05516b1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/interface.go index 0f6c45649..989e8fa0f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/v1/interface.go index 819a86146..84dc6476a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/v1/networkpolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/v1/networkpolicy.go index 20ac9909d..51e0bdf19 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/v1/networkpolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/networking/v1/networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/interface.go index e77ab2b24..1859fca82 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/interface.go index b368f068f..a6c1825d2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/poddisruptionbudget.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/poddisruptionbudget.go index d5178652a..d305e617b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/poddisruptionbudget.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/podsecuritypolicy.go index c9bcc8bab..12a16acde 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/policy/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/interface.go index ac491ee42..228811f8a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/clusterrole.go index f541957a2..d5e10cadd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/clusterrolebinding.go index bf1d7bdc1..027d11b60 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/interface.go index fca0e807b..7f99c9454 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/role.go index f08e1fde3..9c9f4f84b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/rolebinding.go index f91c2ef03..73cd3056d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/clusterrole.go index 9293439f4..76aa466cd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/clusterrolebinding.go index d13561274..851eb39dc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/interface.go index 1c972ec82..d27c79987 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/role.go index 5b4148fa9..be847445e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/rolebinding.go index 54bae16e7..20e7159e3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1alpha1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/clusterrole.go index f429eeca1..d79c75c9b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/clusterrolebinding.go index 5900eae9a..f6b64816b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/interface.go index c36d644e1..04add43af 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/role.go index 479044b42..fc1c56879 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/rolebinding.go index 34feed183..9bbf70200 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/rbac/v1beta1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/BUILD index 14c2a70b9..81c38c914 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/BUILD @@ -12,6 +12,7 @@ go_library( deps = [ "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", "//vendor/k8s.io/client-go/informers/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/client-go/informers/scheduling/v1beta1:go_default_library", ], ) @@ -27,6 +28,7 @@ filegroup( srcs = [ ":package-srcs", "//staging/src/k8s.io/client-go/informers/scheduling/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/informers/scheduling/v1beta1:all-srcs", ], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/interface.go index 89aaac195..16d030c30 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,12 +21,15 @@ package scheduling import ( internalinterfaces "k8s.io/client-go/informers/internalinterfaces" v1alpha1 "k8s.io/client-go/informers/scheduling/v1alpha1" + v1beta1 "k8s.io/client-go/informers/scheduling/v1beta1" ) // Interface provides access to each of this group's versions. type Interface interface { // V1alpha1 provides access to shared informers for resources in V1alpha1. V1alpha1() v1alpha1.Interface + // V1beta1 provides access to shared informers for resources in V1beta1. + V1beta1() v1beta1.Interface } type group struct { @@ -44,3 +47,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList func (g *group) V1alpha1() v1alpha1.Interface { return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) } + +// V1beta1 returns a new v1beta1.Interface. +func (g *group) V1beta1() v1beta1.Interface { + return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1alpha1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1alpha1/interface.go index 091dd90b6..cd908d14e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1alpha1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1alpha1/priorityclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1alpha1/priorityclass.go index 8a27631be..481df0499 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1alpha1/priorityclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1alpha1/priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1beta1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1beta1/BUILD new file mode 100644 index 000000000..dec0410f4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1beta1/BUILD @@ -0,0 +1,35 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "interface.go", + "priorityclass.go", + ], + importpath = "k8s.io/client-go/informers/scheduling/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/informers/internalinterfaces:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/listers/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1beta1/interface.go new file mode 100644 index 000000000..52840a9ce --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1beta1/interface.go @@ -0,0 +1,45 @@ +/* +Copyright 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1beta1 + +import ( + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // PriorityClasses returns a PriorityClassInformer. + PriorityClasses() PriorityClassInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// PriorityClasses returns a PriorityClassInformer. +func (v *version) PriorityClasses() PriorityClassInformer { + return &priorityClassInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1beta1/priorityclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1beta1/priorityclass.go new file mode 100644 index 000000000..ff61e58de --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/scheduling/v1beta1/priorityclass.go @@ -0,0 +1,88 @@ +/* +Copyright 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1beta1 + +import ( + time "time" + + scheduling_v1beta1 "k8s.io/api/scheduling/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" + kubernetes "k8s.io/client-go/kubernetes" + v1beta1 "k8s.io/client-go/listers/scheduling/v1beta1" + cache "k8s.io/client-go/tools/cache" +) + +// PriorityClassInformer provides access to a shared informer and lister for +// PriorityClasses. +type PriorityClassInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1beta1.PriorityClassLister +} + +type priorityClassInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewPriorityClassInformer constructs a new informer for PriorityClass type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewPriorityClassInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredPriorityClassInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredPriorityClassInformer constructs a new informer for PriorityClass type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredPriorityClassInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SchedulingV1beta1().PriorityClasses().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SchedulingV1beta1().PriorityClasses().Watch(options) + }, + }, + &scheduling_v1beta1.PriorityClass{}, + resyncPeriod, + indexers, + ) +} + +func (f *priorityClassInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredPriorityClassInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *priorityClassInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&scheduling_v1beta1.PriorityClass{}, f.defaultInformer) +} + +func (f *priorityClassInformer) Lister() v1beta1.PriorityClassLister { + return v1beta1.NewPriorityClassLister(f.Informer().GetIndexer()) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/interface.go index cc134f706..d91e49867 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/v1alpha1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/v1alpha1/interface.go index d2964352a..250220469 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/v1alpha1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/v1alpha1/podpreset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/v1alpha1/podpreset.go index 7e241b2be..c4596c828 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/v1alpha1/podpreset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/settings/v1alpha1/podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/interface.go index 6581a2a8d..8245aa60c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1/interface.go index ebdb1d98a..d7e4b5c49 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1/storageclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1/storageclass.go index 5ef571eb4..ae90b53b4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1/storageclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1alpha1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1alpha1/interface.go index f1b1a9bbd..d389b73fa 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1alpha1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1alpha1/volumeattachment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1alpha1/volumeattachment.go index 506517acd..01c468582 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1alpha1/volumeattachment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1alpha1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/interface.go index 5a63728f1..aa11c2bb6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/storageclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/storageclass.go index 0b4edbf52..1c2f3490c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/storageclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/volumeattachment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/volumeattachment.go index ae3c2fd71..63fa12f0e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/volumeattachment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/informers/storage/v1beta1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/BUILD index 0ef4f8671..73f5a9b0e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/BUILD @@ -14,7 +14,6 @@ go_library( ], importpath = "k8s.io/client-go/kubernetes", deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1:go_default_library", @@ -40,6 +39,7 @@ go_library( "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1alpha1:go_default_library", @@ -86,6 +86,7 @@ filegroup( "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1:all-srcs", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/clientset.go index d867a58b2..9d0eace46 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package kubernetes import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" admissionregistrationv1alpha1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1" admissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1" @@ -45,6 +44,7 @@ import ( rbacv1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1" rbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1" schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1" + schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1" settingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1" storagev1 "k8s.io/client-go/kubernetes/typed/storage/v1" storagev1alpha1 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1" @@ -105,8 +105,9 @@ type Interface interface { RbacV1beta1() rbacv1beta1.RbacV1beta1Interface RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface + SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface // Deprecated: please explicitly pick a version if possible. - Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface + Scheduling() schedulingv1beta1.SchedulingV1beta1Interface SettingsV1alpha1() settingsv1alpha1.SettingsV1alpha1Interface // Deprecated: please explicitly pick a version if possible. Settings() settingsv1alpha1.SettingsV1alpha1Interface @@ -145,6 +146,7 @@ type Clientset struct { rbacV1beta1 *rbacv1beta1.RbacV1beta1Client rbacV1alpha1 *rbacv1alpha1.RbacV1alpha1Client schedulingV1alpha1 *schedulingv1alpha1.SchedulingV1alpha1Client + schedulingV1beta1 *schedulingv1beta1.SchedulingV1beta1Client settingsV1alpha1 *settingsv1alpha1.SettingsV1alpha1Client storageV1beta1 *storagev1beta1.StorageV1beta1Client storageV1 *storagev1.StorageV1Client @@ -349,10 +351,15 @@ func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1In return c.schedulingV1alpha1 } +// SchedulingV1beta1 retrieves the SchedulingV1beta1Client +func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface { + return c.schedulingV1beta1 +} + // Deprecated: Scheduling retrieves the default version of SchedulingClient. // Please explicitly pick a version. -func (c *Clientset) Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface { - return c.schedulingV1alpha1 +func (c *Clientset) Scheduling() schedulingv1beta1.SchedulingV1beta1Interface { + return c.schedulingV1beta1 } // SettingsV1alpha1 retrieves the SettingsV1alpha1Client @@ -499,6 +506,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { if err != nil { return nil, err } + cs.schedulingV1beta1, err = schedulingv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.settingsV1alpha1, err = settingsv1alpha1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -518,7 +529,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil @@ -552,6 +562,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { cs.rbacV1beta1 = rbacv1beta1.NewForConfigOrDie(c) cs.rbacV1alpha1 = rbacv1alpha1.NewForConfigOrDie(c) cs.schedulingV1alpha1 = schedulingv1alpha1.NewForConfigOrDie(c) + cs.schedulingV1beta1 = schedulingv1beta1.NewForConfigOrDie(c) cs.settingsV1alpha1 = settingsv1alpha1.NewForConfigOrDie(c) cs.storageV1beta1 = storagev1beta1.NewForConfigOrDie(c) cs.storageV1 = storagev1.NewForConfigOrDie(c) @@ -588,6 +599,7 @@ func New(c rest.Interface) *Clientset { cs.rbacV1beta1 = rbacv1beta1.New(c) cs.rbacV1alpha1 = rbacv1alpha1.New(c) cs.schedulingV1alpha1 = schedulingv1alpha1.New(c) + cs.schedulingV1beta1 = schedulingv1beta1.New(c) cs.settingsV1alpha1 = settingsv1alpha1.New(c) cs.storageV1beta1 = storagev1beta1.New(c) cs.storageV1 = storagev1.New(c) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/doc.go index c5870c01a..b272334ad 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/BUILD index c30d43ffb..941115b5a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/BUILD @@ -38,6 +38,7 @@ go_library( "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", @@ -98,6 +99,8 @@ go_library( "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go index 0eb5ac9e5..b764b21b6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -72,6 +72,8 @@ import ( fakerbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake" schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1" fakeschedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake" + schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1" + fakeschedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake" settingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1" fakesettingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake" storagev1 "k8s.io/client-go/kubernetes/typed/storage/v1" @@ -95,9 +97,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -107,7 +110,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a @@ -309,9 +312,14 @@ func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1In return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake} } -// Scheduling retrieves the SchedulingV1alpha1Client -func (c *Clientset) Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface { - return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake} +// SchedulingV1beta1 retrieves the SchedulingV1beta1Client +func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface { + return &fakeschedulingv1beta1.FakeSchedulingV1beta1{Fake: &c.Fake} +} + +// Scheduling retrieves the SchedulingV1beta1Client +func (c *Clientset) Scheduling() schedulingv1beta1.SchedulingV1beta1Interface { + return &fakeschedulingv1beta1.FakeSchedulingV1beta1{Fake: &c.Fake} } // SettingsV1alpha1 retrieves the SettingsV1alpha1Client diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/register.go index 45fdf124c..88e168fa6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,6 +43,7 @@ import ( rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" settingsv1alpha1 "k8s.io/api/settings/v1alpha1" storagev1 "k8s.io/api/storage/v1" storagev1alpha1 "k8s.io/api/storage/v1alpha1" @@ -101,6 +102,7 @@ func AddToScheme(scheme *runtime.Scheme) { rbacv1beta1.AddToScheme(scheme) rbacv1alpha1.AddToScheme(scheme) schedulingv1alpha1.AddToScheme(scheme) + schedulingv1beta1.AddToScheme(scheme) settingsv1alpha1.AddToScheme(scheme) storagev1beta1.AddToScheme(scheme) storagev1.AddToScheme(scheme) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/BUILD index 1bb118aa0..55ae1310b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/BUILD @@ -37,6 +37,7 @@ go_library( "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/register.go index 66e2dcd18..86584cf83 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,6 +43,7 @@ import ( rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" settingsv1alpha1 "k8s.io/api/settings/v1alpha1" storagev1 "k8s.io/api/storage/v1" storagev1alpha1 "k8s.io/api/storage/v1alpha1" @@ -101,6 +102,7 @@ func AddToScheme(scheme *runtime.Scheme) { rbacv1beta1.AddToScheme(scheme) rbacv1alpha1.AddToScheme(scheme) schedulingv1alpha1.AddToScheme(scheme) + schedulingv1beta1.AddToScheme(scheme) settingsv1alpha1.AddToScheme(scheme) storagev1beta1.AddToScheme(scheme) storagev1.AddToScheme(scheme) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/admissionregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/admissionregistration_client.go index 8137129fc..5e02f7227 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/admissionregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go index 2917c0ae4..8457aec27 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go index 699261cd4..b927dae2c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeInitializerConfigurations) List(opts v1.ListOptions) (result *v1alp if label == nil { label = labels.Everything() } - list := &v1alpha1.InitializerConfigurationList{} + list := &v1alpha1.InitializerConfigurationList{ListMeta: obj.(*v1alpha1.InitializerConfigurationList).ListMeta} for _, item := range obj.(*v1alpha1.InitializerConfigurationList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/generated_expansion.go index 710bc4ea4..1e29b96f4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/initializerconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/initializerconfiguration.go index 77c6b8fcc..e014ea72b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/initializerconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/admissionregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/admissionregistration_client.go index 44b20b577..b13ea7953 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/admissionregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go index 3255acb47..1a988ddba 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go index 044636ead..e06888cc1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeMutatingWebhookConfigurations) List(opts v1.ListOptions) (result *v if label == nil { label = labels.Everything() } - list := &v1beta1.MutatingWebhookConfigurationList{} + list := &v1beta1.MutatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.MutatingWebhookConfigurationList).ListMeta} for _, item := range obj.(*v1beta1.MutatingWebhookConfigurationList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go index f06582d4e..1069634e2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeValidatingWebhookConfigurations) List(opts v1.ListOptions) (result if label == nil { label = labels.Everything() } - list := &v1beta1.ValidatingWebhookConfigurationList{} + list := &v1beta1.ValidatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.ValidatingWebhookConfigurationList).ListMeta} for _, item := range obj.(*v1beta1.ValidatingWebhookConfigurationList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/generated_expansion.go index 293697555..2aeb9c98a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/mutatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/mutatingwebhookconfiguration.go index d37f68448..cb0157102 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/validatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/validatingwebhookconfiguration.go index 30dcfddbc..3a9339f6c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/validatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go index b0af79806..da19c7596 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/controllerrevision.go index 26d020747..ac9d62790 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/daemonset.go index 73fd1e9bd..b50ac2557 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go index 1a3e8f730..e2b1b1886 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go index 11accc235..458df0fa3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go index fb43bea4c..0655803d8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *apps_v1.Con if label == nil { label = labels.Everything() } - list := &apps_v1.ControllerRevisionList{} + list := &apps_v1.ControllerRevisionList{ListMeta: obj.(*apps_v1.ControllerRevisionList).ListMeta} for _, item := range obj.(*apps_v1.ControllerRevisionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go index 0ee4cd33d..47cdca788 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *apps_v1.DaemonSetLis if label == nil { label = labels.Everything() } - list := &apps_v1.DaemonSetList{} + list := &apps_v1.DaemonSetList{ListMeta: obj.(*apps_v1.DaemonSetList).ListMeta} for _, item := range obj.(*apps_v1.DaemonSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go index 852b628ad..dab4f40c3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *apps_v1.DeploymentL if label == nil { label = labels.Everything() } - list := &apps_v1.DeploymentList{} + list := &apps_v1.DeploymentList{ListMeta: obj.(*apps_v1.DeploymentList).ListMeta} for _, item := range obj.(*apps_v1.DeploymentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go index 03f7558d4..948091bed 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *apps_v1.ReplicaSetL if label == nil { label = labels.Everything() } - list := &apps_v1.ReplicaSetList{} + list := &apps_v1.ReplicaSetList{ListMeta: obj.(*apps_v1.ReplicaSetList).ListMeta} for _, item := range obj.(*apps_v1.ReplicaSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go index af0a90720..19cb2fad5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *apps_v1.StatefulSe if label == nil { label = labels.Everything() } - list := &apps_v1.StatefulSetList{} + list := &apps_v1.StatefulSetList{ListMeta: obj.(*apps_v1.StatefulSetList).ListMeta} for _, item := range obj.(*apps_v1.StatefulSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/generated_expansion.go index 0f603bb8c..88cfe4ecb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/replicaset.go index f2f9c7256..21614cbe1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/statefulset.go index 78fe23f84..3ef5b8880 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/apps_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/apps_client.go index 1aebc2176..4d882e26e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/apps_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/controllerrevision.go index 312ba3c47..ec8fa9242 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/deployment.go index 2ff58aeac..365e06f3f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go index 5cc316882..2ff602be9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go index 2360bb07a..924194891 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *v1beta1.Con if label == nil { label = labels.Everything() } - list := &v1beta1.ControllerRevisionList{} + list := &v1beta1.ControllerRevisionList{ListMeta: obj.(*v1beta1.ControllerRevisionList).ListMeta} for _, item := range obj.(*v1beta1.ControllerRevisionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go index 5282d8cd9..c4749c52b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta1.DeploymentL if label == nil { label = labels.Everything() } - list := &v1beta1.DeploymentList{} + list := &v1beta1.DeploymentList{ListMeta: obj.(*v1beta1.DeploymentList).ListMeta} for _, item := range obj.(*v1beta1.DeploymentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go index 72615c803..de71947e5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go index 6e1d7a560..b0f194a7d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1beta1.StatefulSe if label == nil { label = labels.Everything() } - list := &v1beta1.StatefulSetList{} + list := &v1beta1.StatefulSetList{ListMeta: obj.(*v1beta1.StatefulSetList).ListMeta} for _, item := range obj.(*v1beta1.StatefulSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/generated_expansion.go index a44a94b63..b2bfd73a7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/scale.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/scale.go index e8c507326..cef27bd14 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/scale.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/statefulset.go index 6f89ca73a..651745451 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/apps_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/apps_client.go index 8d5a78c44..27549499f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/apps_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/controllerrevision.go index 28b30e8be..1271cc623 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/daemonset.go index c21fc50a8..683c06812 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/deployment.go index 270be527e..9a04513f1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/doc.go index 01d0ed2c2..56518ef7f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go index 7223cd24e..f7d79d352 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_apps_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go index 720972e7d..954ac35df 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *v1beta2.Con if label == nil { label = labels.Everything() } - list := &v1beta2.ControllerRevisionList{} + list := &v1beta2.ControllerRevisionList{ListMeta: obj.(*v1beta2.ControllerRevisionList).ListMeta} for _, item := range obj.(*v1beta2.ControllerRevisionList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go index 3576b8427..38a147550 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *v1beta2.DaemonSetLis if label == nil { label = labels.Everything() } - list := &v1beta2.DaemonSetList{} + list := &v1beta2.DaemonSetList{ListMeta: obj.(*v1beta2.DaemonSetList).ListMeta} for _, item := range obj.(*v1beta2.DaemonSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go index 1f654a3cc..cae232242 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta2.DeploymentL if label == nil { label = labels.Everything() } - list := &v1beta2.DeploymentList{} + list := &v1beta2.DeploymentList{ListMeta: obj.(*v1beta2.DeploymentList).ListMeta} for _, item := range obj.(*v1beta2.DeploymentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go index f8e69a3a3..05fa78931 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *v1beta2.ReplicaSetL if label == nil { label = labels.Everything() } - list := &v1beta2.ReplicaSetList{} + list := &v1beta2.ReplicaSetList{ListMeta: obj.(*v1beta2.ReplicaSetList).ListMeta} for _, item := range obj.(*v1beta2.ReplicaSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_scale.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_scale.go index fb5eb5c59..b06b7e8e3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_scale.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go index 0413428eb..fe7851286 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1beta2.StatefulSe if label == nil { label = labels.Everything() } - list := &v1beta2.StatefulSetList{} + list := &v1beta2.StatefulSetList{ListMeta: obj.(*v1beta2.StatefulSetList).ListMeta} for _, item := range obj.(*v1beta2.StatefulSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/generated_expansion.go index a88e1721f..bceae5986 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/replicaset.go index 298ec26a2..9fd9de930 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/scale.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/scale.go index 84f27a797..f8d6a7fb0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/scale.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/statefulset.go index 64b7c8c8f..095601e15 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/authentication_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/authentication_client.go index 25b86152d..3bdcee598 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/authentication_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go index 93a0633e8..ee06a6cdd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go index d98aa03d8..e2a7f72b6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/fake/fake_tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/generated_expansion.go index 7c92b9147..177209ec6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/tokenreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/tokenreview.go index 88f759f2b..25a8d6a17 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/tokenreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/authentication_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/authentication_client.go index 744c26c9e..7f3334a0c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/authentication_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go index abc1fedd1..7299653ca 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_authentication_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go index c7c3e5631..63b6b6a85 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake/fake_tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/generated_expansion.go index 7fd68c803..f6df76963 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/tokenreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/tokenreview.go index fa611825e..0ac3561e1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/tokenreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/authorization_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/authorization_client.go index 852720f34..e84b90084 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/authorization_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go index 5db9b9f34..f7e823450 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go index 5f1aab8a4..778ba9cea 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go index 7e466e1ec..a43a980ba 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go index 82c1ac9cf..243f2e89e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go index cbc440e71..d07e56254 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/fake/fake_subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/generated_expansion.go index 7c92b9147..177209ec6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/localsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/localsubjectaccessreview.go index 20461f132..0292c7861 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/localsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectaccessreview.go index 202e7c90d..1e3a45817 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectrulesreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectrulesreview.go index 5fb1cab5c..50a0233eb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectrulesreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/subjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/subjectaccessreview.go index 881641494..9c09008c3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/subjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/authorization_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/authorization_client.go index cbe5bdcee..7f236f6e3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/authorization_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go index 7c3fc1746..8e328a57b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_authorization_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go index c7949a7df..d02d05e5d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go index 20904d179..8f98ce7a3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go index 2acd5f279..d8466b4c8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go index 218ed3d8f..0d0abdb72 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake/fake_subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/generated_expansion.go index 7fd68c803..f6df76963 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/localsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/localsubjectaccessreview.go index 8029837f9..f5e86a76a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/localsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectaccessreview.go index 36feb1530..906712cc3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectrulesreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectrulesreview.go index 57079c8d9..56c0f99d4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectrulesreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/subjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/subjectaccessreview.go index d91fa87ec..79f1ec535 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/subjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/autoscaling_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/autoscaling_client.go index b336bbd39..2bd49e2db 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/autoscaling_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go index 540eb5f5c..99e26fcf3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go index 532e6f51c..f774fc5dc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *autosc if label == nil { label = labels.Everything() } - list := &autoscaling_v1.HorizontalPodAutoscalerList{} + list := &autoscaling_v1.HorizontalPodAutoscalerList{ListMeta: obj.(*autoscaling_v1.HorizontalPodAutoscalerList).ListMeta} for _, item := range obj.(*autoscaling_v1.HorizontalPodAutoscalerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/generated_expansion.go index a5c694ffb..c60028b05 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/horizontalpodautoscaler.go index 9245e41a2..2da25e96b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/autoscaling_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/autoscaling_client.go index 25446452f..3a49b26b3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/autoscaling_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/doc.go index 1f70aedf8..06fd344c0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go index 6d3437a23..be8e0f48e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_autoscaling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go index 549196c5e..2d860341a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *v2beta if label == nil { label = labels.Everything() } - list := &v2beta1.HorizontalPodAutoscalerList{} + list := &v2beta1.HorizontalPodAutoscalerList{ListMeta: obj.(*v2beta1.HorizontalPodAutoscalerList).ListMeta} for _, item := range obj.(*v2beta1.HorizontalPodAutoscalerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/generated_expansion.go index 561fbb0e6..6f1704f1e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/horizontalpodautoscaler.go index 1be9b80ca..4ac8cce71 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/batch_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/batch_client.go index c092a3ca1..d5e35e6b2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/batch_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go index 27d54c4c4..c90dd7561 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go index 4d9ba490f..6a83115ba 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/fake/fake_job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeJobs) List(opts v1.ListOptions) (result *batch_v1.JobList, err erro if label == nil { label = labels.Everything() } - list := &batch_v1.JobList{} + list := &batch_v1.JobList{ListMeta: obj.(*batch_v1.JobList).ListMeta} for _, item := range obj.(*batch_v1.JobList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/generated_expansion.go index 04a37a49d..dc4142934 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/job.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/job.go index dc0c79997..f714d3de5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/job.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1/job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/batch_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/batch_client.go index 5ee39b5be..aa71ca833 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/batch_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/cronjob.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/cronjob.go index 32ac52fac..04637c36a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/cronjob.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go index 9de70f8fe..6f350aed9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go index 756585d7d..d80ef5e67 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeCronJobs) List(opts v1.ListOptions) (result *v1beta1.CronJobList, e if label == nil { label = labels.Everything() } - list := &v1beta1.CronJobList{} + list := &v1beta1.CronJobList{ListMeta: obj.(*v1beta1.CronJobList).ListMeta} for _, item := range obj.(*v1beta1.CronJobList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/generated_expansion.go index a093bbad4..145e14a99 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/batch_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/batch_client.go index ff26a76d5..e6c6306b8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/batch_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/cronjob.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/cronjob.go index e5b135314..4d922f9ae 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/cronjob.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/doc.go index ba60ac54b..3efe0d284 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go index 52ad499cc..3e478cde9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_batch_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go index f80e94cae..75c0b1733 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeCronJobs) List(opts v1.ListOptions) (result *v2alpha1.CronJobList, if label == nil { label = labels.Everything() } - list := &v2alpha1.CronJobList{} + list := &v2alpha1.CronJobList{ListMeta: obj.(*v2alpha1.CronJobList).ListMeta} for _, item := range obj.(*v2alpha1.CronJobList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/generated_expansion.go index ed2c942b0..34dafc464 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificates_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificates_client.go index 7d69ce9f6..baac42ee2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificates_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificates_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificatesigningrequest.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificatesigningrequest.go index ecca7aedc..b39169a8f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificatesigningrequest.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go index 455ac56b5..29d8b088e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificates_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go index f3ea4c464..dfd517195 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeCertificateSigningRequests) List(opts v1.ListOptions) (result *v1be if label == nil { label = labels.Everything() } - list := &v1beta1.CertificateSigningRequestList{} + list := &v1beta1.CertificateSigningRequestList{ListMeta: obj.(*v1beta1.CertificateSigningRequestList).ListMeta} for _, item := range obj.(*v1beta1.CertificateSigningRequestList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/generated_expansion.go index 7fd68c803..f6df76963 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/componentstatus.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/componentstatus.go index 1717e7c19..6ae5a6681 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/componentstatus.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go index 6e7a12e5d..3ae229f42 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/core_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/core_client.go index 1c86c47d4..044a28ebd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/core_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/core_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/endpoints.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/endpoints.go index 03b2a6919..2868baaa1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/endpoints.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/event.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/event.go index b9570e689..565062345 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/event.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go index 42039aea9..2f2420730 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeComponentStatuses) List(opts v1.ListOptions) (result *core_v1.Compo if label == nil { label = labels.Everything() } - list := &core_v1.ComponentStatusList{} + list := &core_v1.ComponentStatusList{ListMeta: obj.(*core_v1.ComponentStatusList).ListMeta} for _, item := range obj.(*core_v1.ComponentStatusList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go index 8de1cde17..1bc7757fb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeConfigMaps) List(opts v1.ListOptions) (result *core_v1.ConfigMapLis if label == nil { label = labels.Everything() } - list := &core_v1.ConfigMapList{} + list := &core_v1.ConfigMapList{ListMeta: obj.(*core_v1.ConfigMapList).ListMeta} for _, item := range obj.(*core_v1.ConfigMapList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go index b30c02de1..5ad90943c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_core_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go index 7b54929f6..eb5eac981 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeEndpoints) List(opts v1.ListOptions) (result *core_v1.EndpointsList if label == nil { label = labels.Everything() } - list := &core_v1.EndpointsList{} + list := &core_v1.EndpointsList{ListMeta: obj.(*core_v1.EndpointsList).ListMeta} for _, item := range obj.(*core_v1.EndpointsList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go index 5ba47f419..458b8c153 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeEvents) List(opts v1.ListOptions) (result *core_v1.EventList, err e if label == nil { label = labels.Everything() } - list := &core_v1.EventList{} + list := &core_v1.EventList{ListMeta: obj.(*core_v1.EventList).ListMeta} for _, item := range obj.(*core_v1.EventList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go index bd736980e..c5156c7c0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeLimitRanges) List(opts v1.ListOptions) (result *core_v1.LimitRangeL if label == nil { label = labels.Everything() } - list := &core_v1.LimitRangeList{} + list := &core_v1.LimitRangeList{ListMeta: obj.(*core_v1.LimitRangeList).ListMeta} for _, item := range obj.(*core_v1.LimitRangeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go index 84743469a..32aae1389 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeNamespaces) List(opts v1.ListOptions) (result *core_v1.NamespaceLis if label == nil { label = labels.Everything() } - list := &core_v1.NamespaceList{} + list := &core_v1.NamespaceList{ListMeta: obj.(*core_v1.NamespaceList).ListMeta} for _, item := range obj.(*core_v1.NamespaceList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) @@ -112,14 +112,6 @@ func (c *FakeNamespaces) Delete(name string, options *v1.DeleteOptions) error { return err } -// DeleteCollection deletes a collection of objects. -func (c *FakeNamespaces) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewRootDeleteCollectionAction(namespacesResource, listOptions) - - _, err := c.Fake.Invokes(action, &core_v1.NamespaceList{}) - return err -} - // Patch applies the patch and returns the patched namespace. func (c *FakeNamespaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *core_v1.Namespace, err error) { obj, err := c.Fake. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go index c7e042fc8..8b99bb8e4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeNodes) List(opts v1.ListOptions) (result *core_v1.NodeList, err err if label == nil { label = labels.Everything() } - list := &core_v1.NodeList{} + list := &core_v1.NodeList{ListMeta: obj.(*core_v1.NodeList).ListMeta} for _, item := range obj.(*core_v1.NodeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go index 1be38a89e..5742936d2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePersistentVolumes) List(opts v1.ListOptions) (result *core_v1.Persi if label == nil { label = labels.Everything() } - list := &core_v1.PersistentVolumeList{} + list := &core_v1.PersistentVolumeList{ListMeta: obj.(*core_v1.PersistentVolumeList).ListMeta} for _, item := range obj.(*core_v1.PersistentVolumeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go index ea189bb9c..d2d17984c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePersistentVolumeClaims) List(opts v1.ListOptions) (result *core_v1. if label == nil { label = labels.Everything() } - list := &core_v1.PersistentVolumeClaimList{} + list := &core_v1.PersistentVolumeClaimList{ListMeta: obj.(*core_v1.PersistentVolumeClaimList).ListMeta} for _, item := range obj.(*core_v1.PersistentVolumeClaimList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go index 6f5faef99..2960b12ae 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePods) List(opts v1.ListOptions) (result *core_v1.PodList, err error if label == nil { label = labels.Everything() } - list := &core_v1.PodList{} + list := &core_v1.PodList{ListMeta: obj.(*core_v1.PodList).ListMeta} for _, item := range obj.(*core_v1.PodList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go index 1dd272e78..3ae6ca551 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePodTemplates) List(opts v1.ListOptions) (result *core_v1.PodTemplat if label == nil { label = labels.Everything() } - list := &core_v1.PodTemplateList{} + list := &core_v1.PodTemplateList{ListMeta: obj.(*core_v1.PodTemplateList).ListMeta} for _, item := range obj.(*core_v1.PodTemplateList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go index 047831a31..f25235ff2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -63,7 +63,7 @@ func (c *FakeReplicationControllers) List(opts v1.ListOptions) (result *core_v1. if label == nil { label = labels.Everything() } - list := &core_v1.ReplicationControllerList{} + list := &core_v1.ReplicationControllerList{ListMeta: obj.(*core_v1.ReplicationControllerList).ListMeta} for _, item := range obj.(*core_v1.ReplicationControllerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go index afdc8c88a..9c6ae20a2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeResourceQuotas) List(opts v1.ListOptions) (result *core_v1.Resource if label == nil { label = labels.Everything() } - list := &core_v1.ResourceQuotaList{} + list := &core_v1.ResourceQuotaList{ListMeta: obj.(*core_v1.ResourceQuotaList).ListMeta} for _, item := range obj.(*core_v1.ResourceQuotaList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go index abf7db090..e1eeea5f8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeSecrets) List(opts v1.ListOptions) (result *core_v1.SecretList, err if label == nil { label = labels.Everything() } - list := &core_v1.SecretList{} + list := &core_v1.SecretList{ListMeta: obj.(*core_v1.SecretList).ListMeta} for _, item := range obj.(*core_v1.SecretList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go index 7ce885ae8..aa23e0efa 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeServices) List(opts v1.ListOptions) (result *core_v1.ServiceList, e if label == nil { label = labels.Everything() } - list := &core_v1.ServiceList{} + list := &core_v1.ServiceList{ListMeta: obj.(*core_v1.ServiceList).ListMeta} for _, item := range obj.(*core_v1.ServiceList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) @@ -120,14 +120,6 @@ func (c *FakeServices) Delete(name string, options *v1.DeleteOptions) error { return err } -// DeleteCollection deletes a collection of objects. -func (c *FakeServices) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(servicesResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &core_v1.ServiceList{}) - return err -} - // Patch applies the patch and returns the patched service. func (c *FakeServices) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *core_v1.Service, err error) { obj, err := c.Fake. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go index 635b2c32b..1d5837f8b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeServiceAccounts) List(opts v1.ListOptions) (result *core_v1.Service if label == nil { label = labels.Everything() } - list := &core_v1.ServiceAccountList{} + list := &core_v1.ServiceAccountList{ListMeta: obj.(*core_v1.ServiceAccountList).ListMeta} for _, item := range obj.(*core_v1.ServiceAccountList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/generated_expansion.go index 430bd6c5a..6e8591b12 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/limitrange.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/limitrange.go index b67997d70..396e5ca4b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/limitrange.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/namespace.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/namespace.go index a298d7c02..707b3e971 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/namespace.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -39,7 +39,6 @@ type NamespaceInterface interface { Update(*v1.Namespace) (*v1.Namespace, error) UpdateStatus(*v1.Namespace) (*v1.Namespace, error) Delete(name string, options *meta_v1.DeleteOptions) error - DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error Get(name string, options meta_v1.GetOptions) (*v1.Namespace, error) List(opts meta_v1.ListOptions) (*v1.NamespaceList, error) Watch(opts meta_v1.ListOptions) (watch.Interface, error) @@ -139,16 +138,6 @@ func (c *namespaces) Delete(name string, options *meta_v1.DeleteOptions) error { Error() } -// DeleteCollection deletes a collection of objects. -func (c *namespaces) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error { - return c.client.Delete(). - Resource("namespaces"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Body(options). - Do(). - Error() -} - // Patch applies the patch and returns the patched namespace. func (c *namespaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Namespace, err error) { result = &v1.Namespace{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/node.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/node.go index b16f92f00..1462d2549 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/node.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolume.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolume.go index f23b95f30..f9010119b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolume.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolumeclaim.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolumeclaim.go index f168a985a..59253d5ef 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolumeclaim.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/pod.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/pod.go index 423d81ad8..8eb7ba8bd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/pod.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/podtemplate.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/podtemplate.go index 730b54330..d99d8c3b5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/podtemplate.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/replicationcontroller.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/replicationcontroller.go index a0f36a1fa..7741f970a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/replicationcontroller.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/resourcequota.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/resourcequota.go index 011e72a91..7662a0280 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/resourcequota.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/secret.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/secret.go index 931afb5db..5d149f8cc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/secret.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/service.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/service.go index 156bcc235..ec8646a27 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/service.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -39,7 +39,6 @@ type ServiceInterface interface { Update(*v1.Service) (*v1.Service, error) UpdateStatus(*v1.Service) (*v1.Service, error) Delete(name string, options *meta_v1.DeleteOptions) error - DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error Get(name string, options meta_v1.GetOptions) (*v1.Service, error) List(opts meta_v1.ListOptions) (*v1.ServiceList, error) Watch(opts meta_v1.ListOptions) (watch.Interface, error) @@ -148,17 +147,6 @@ func (c *services) Delete(name string, options *meta_v1.DeleteOptions) error { Error() } -// DeleteCollection deletes a collection of objects. -func (c *services) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("services"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Body(options). - Do(). - Error() -} - // Patch applies the patch and returns the patched service. func (c *services) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Service, err error) { result = &v1.Service{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/serviceaccount.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/serviceaccount.go index 0a87feb5b..ba2a27948 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/serviceaccount.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/event.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/event.go index e8737cf9e..af7d060d5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/event.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/events_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/events_client.go index 7225d90d8..fb59635bb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/events_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/events_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go index 02fa70fbd..b210e40a0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeEvents) List(opts v1.ListOptions) (result *v1beta1.EventList, err e if label == nil { label = labels.Everything() } - list := &v1beta1.EventList{} + list := &v1beta1.EventList{ListMeta: obj.(*v1beta1.EventList).ListMeta} for _, item := range obj.(*v1beta1.EventList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go index c6eb06623..875c774e3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake/fake_events_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/generated_expansion.go index 871411abb..e27f693f8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/daemonset.go index 20cd58728..85294be4b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/deployment.go index 91ada9e54..89183d285 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go index c359a58f2..1961ffc7c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go index 083bed820..3a760b317 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *v1beta1.DaemonSetLis if label == nil { label = labels.Everything() } - list := &v1beta1.DaemonSetList{} + list := &v1beta1.DaemonSetList{ListMeta: obj.(*v1beta1.DaemonSetList).ListMeta} for _, item := range obj.(*v1beta1.DaemonSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go index 1ce8fb34b..f032a5563 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta1.DeploymentL if label == nil { label = labels.Everything() } - list := &v1beta1.DeploymentList{} + list := &v1beta1.DeploymentList{ListMeta: obj.(*v1beta1.DeploymentList).ListMeta} for _, item := range obj.(*v1beta1.DeploymentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go index d8b6741e6..1aba34f9d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_extensions_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go index 60efe17c8..55257a88a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeIngresses) List(opts v1.ListOptions) (result *v1beta1.IngressList, if label == nil { label = labels.Everything() } - list := &v1beta1.IngressList{} + list := &v1beta1.IngressList{ListMeta: obj.(*v1beta1.IngressList).ListMeta} for _, item := range obj.(*v1beta1.IngressList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go index c381e62f1..70b5dac28 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *v1beta1.Pod if label == nil { label = labels.Everything() } - list := &v1beta1.PodSecurityPolicyList{} + list := &v1beta1.PodSecurityPolicyList{ListMeta: obj.(*v1beta1.PodSecurityPolicyList).ListMeta} for _, item := range obj.(*v1beta1.PodSecurityPolicyList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go index 20e8f76f6..2ab8f244f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *v1beta1.ReplicaSetL if label == nil { label = labels.Everything() } - list := &v1beta1.ReplicaSetList{} + list := &v1beta1.ReplicaSetList{ListMeta: obj.(*v1beta1.ReplicaSetList).ListMeta} for _, item := range obj.(*v1beta1.ReplicaSetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_scale.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_scale.go index 0bbcbd15f..02c4d0bab 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_scale.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake/fake_scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/generated_expansion.go index eef05e765..cfaeebd05 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/ingress.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/ingress.go index 26b21baa5..f8b664cbd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/ingress.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/podsecuritypolicy.go index 19475a5c0..8099d7730 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/replicaset.go index b307ac70e..7e61fa2d1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/scale.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/scale.go index e654d9537..6ee677acd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/scale.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go index 8bce64250..6b135c636 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networking_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go index fbab3ca16..4bf7ef7ca 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeNetworkPolicies) List(opts v1.ListOptions) (result *networking_v1.N if label == nil { label = labels.Everything() } - list := &networking_v1.NetworkPolicyList{} + list := &networking_v1.NetworkPolicyList{ListMeta: obj.(*networking_v1.NetworkPolicyList).ListMeta} for _, item := range obj.(*networking_v1.NetworkPolicyList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/generated_expansion.go index c6dd5c323..7d77495fa 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/networking_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/networking_client.go index ac8200f82..8684db456 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/networking_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/networking_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/networkpolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/networkpolicy.go index b0a85c5c5..c2eb2e792 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/networkpolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/networking/v1/networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/eviction.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/eviction.go index b0abf6563..12e8e76ed 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/eviction.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/eviction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go index 06aba37b4..b8f6f3eae 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go index d85a67e4f..3f2e78b31 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePodDisruptionBudgets) List(opts v1.ListOptions) (result *v1beta1.Po if label == nil { label = labels.Everything() } - list := &v1beta1.PodDisruptionBudgetList{} + list := &v1beta1.PodDisruptionBudgetList{ListMeta: obj.(*v1beta1.PodDisruptionBudgetList).ListMeta} for _, item := range obj.(*v1beta1.PodDisruptionBudgetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go index 068515a36..0df9aa15f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *v1beta1.Pod if label == nil { label = labels.Everything() } - list := &v1beta1.PodSecurityPolicyList{} + list := &v1beta1.PodSecurityPolicyList{ListMeta: obj.(*v1beta1.PodSecurityPolicyList).ListMeta} for _, item := range obj.(*v1beta1.PodSecurityPolicyList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go index 3b7e5415e..9c780bf1f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_policy_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/generated_expansion.go index d39f527be..078c16d5c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/poddisruptionbudget.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/poddisruptionbudget.go index d154dfcf8..a11f27eb2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/poddisruptionbudget.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/podsecuritypolicy.go index de6760b14..355be1e9c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/policy_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/policy_client.go index f45cfdf37..020e185e6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/policy_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/policy_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrole.go index e1af3a99b..f3db3beb5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrolebinding.go index c49ac6dd2..21dda4980 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go index b07323c50..01e62aeb5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *rbac_v1.ClusterRol if label == nil { label = labels.Everything() } - list := &rbac_v1.ClusterRoleList{} + list := &rbac_v1.ClusterRoleList{ListMeta: obj.(*rbac_v1.ClusterRoleList).ListMeta} for _, item := range obj.(*rbac_v1.ClusterRoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go index 5e960c8ca..e5c054c9c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *rbac_v1.Clu if label == nil { label = labels.Everything() } - list := &rbac_v1.ClusterRoleBindingList{} + list := &rbac_v1.ClusterRoleBindingList{ListMeta: obj.(*rbac_v1.ClusterRoleBindingList).ListMeta} for _, item := range obj.(*rbac_v1.ClusterRoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go index 5311f0618..426fd70d6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go index 733760de2..413c70c09 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *rbac_v1.RoleList, err err if label == nil { label = labels.Everything() } - list := &rbac_v1.RoleList{} + list := &rbac_v1.RoleList{ListMeta: obj.(*rbac_v1.RoleList).ListMeta} for _, item := range obj.(*rbac_v1.RoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go index 11a75f939..536377b30 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *rbac_v1.RoleBindin if label == nil { label = labels.Everything() } - list := &rbac_v1.RoleBindingList{} + list := &rbac_v1.RoleBindingList{ListMeta: obj.(*rbac_v1.RoleBindingList).ListMeta} for _, item := range obj.(*rbac_v1.RoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/generated_expansion.go index 0977cc00c..e3f1b02e3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/rbac_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/rbac_client.go index e5b7b561d..e3855bb9b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/rbac_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/role.go index 678e284b7..cb7c5c4e8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/rolebinding.go index 7fd9e29fa..a19010fa8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrole.go index 901ef7f46..37a545762 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrolebinding.go index c5c5360b9..605078906 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go index 1b3eec014..13fbce4e7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *v1alpha1.ClusterRo if label == nil { label = labels.Everything() } - list := &v1alpha1.ClusterRoleList{} + list := &v1alpha1.ClusterRoleList{ListMeta: obj.(*v1alpha1.ClusterRoleList).ListMeta} for _, item := range obj.(*v1alpha1.ClusterRoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go index d54eb6f25..5076543d9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *v1alpha1.Cl if label == nil { label = labels.Everything() } - list := &v1alpha1.ClusterRoleBindingList{} + list := &v1alpha1.ClusterRoleBindingList{ListMeta: obj.(*v1alpha1.ClusterRoleBindingList).ListMeta} for _, item := range obj.(*v1alpha1.ClusterRoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go index 12a96c5b6..3447e9be8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go index 8c365efcb..24d8efee3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *v1alpha1.RoleList, err er if label == nil { label = labels.Everything() } - list := &v1alpha1.RoleList{} + list := &v1alpha1.RoleList{ListMeta: obj.(*v1alpha1.RoleList).ListMeta} for _, item := range obj.(*v1alpha1.RoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go index 4346589a8..cb01ef99d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *v1alpha1.RoleBindi if label == nil { label = labels.Everything() } - list := &v1alpha1.RoleBindingList{} + list := &v1alpha1.RoleBindingList{ListMeta: obj.(*v1alpha1.RoleBindingList).ListMeta} for _, item := range obj.(*v1alpha1.RoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/generated_expansion.go index aebf50655..b8b5c7869 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rbac_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rbac_client.go index 06b5f5cab..de83531ed 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rbac_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/role.go index 8af1d7784..aa6954bb5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rolebinding.go index 43888d066..0941b8e86 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrole.go index fd6effd46..bac951c87 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrolebinding.go index 469307000..96c91de6e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go index 738ca1ea9..62a832197 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *v1beta1.ClusterRol if label == nil { label = labels.Everything() } - list := &v1beta1.ClusterRoleList{} + list := &v1beta1.ClusterRoleList{ListMeta: obj.(*v1beta1.ClusterRoleList).ListMeta} for _, item := range obj.(*v1beta1.ClusterRoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go index 144bf70d3..c9ab47269 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *v1beta1.Clu if label == nil { label = labels.Everything() } - list := &v1beta1.ClusterRoleBindingList{} + list := &v1beta1.ClusterRoleBindingList{ListMeta: obj.(*v1beta1.ClusterRoleBindingList).ListMeta} for _, item := range obj.(*v1beta1.ClusterRoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go index 0856ee084..bdbc246b7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go index 2e9d46b51..45b07a001 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *v1beta1.RoleList, err err if label == nil { label = labels.Everything() } - list := &v1beta1.RoleList{} + list := &v1beta1.RoleList{ListMeta: obj.(*v1beta1.RoleList).ListMeta} for _, item := range obj.(*v1beta1.RoleList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go index bb363d874..1efd40005 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *v1beta1.RoleBindin if label == nil { label = labels.Everything() } - list := &v1beta1.RoleBindingList{} + list := &v1beta1.RoleBindingList{ListMeta: obj.(*v1beta1.RoleBindingList).ListMeta} for _, item := range obj.(*v1beta1.RoleBindingList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/generated_expansion.go index 538b09833..e7be79f8d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rbac_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rbac_client.go index eecdd45a8..46718d731 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rbac_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rbac_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/role.go index 363b2c6cd..66f382c07 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rolebinding.go index 8d9f1f617..67d3d331b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go index 9946411e2..8ab4421a9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *v1alpha1.Priori if label == nil { label = labels.Everything() } - list := &v1alpha1.PriorityClassList{} + list := &v1alpha1.PriorityClassList{ListMeta: obj.(*v1alpha1.PriorityClassList).ListMeta} for _, item := range obj.(*v1alpha1.PriorityClassList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go index 6e0a9659e..974ba193f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/generated_expansion.go index 682f0f3bf..52f81d881 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/priorityclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/priorityclass.go index 055a0e3f3..6845d25c3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/priorityclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/scheduling_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/scheduling_client.go index f030b319e..375f41b8d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/scheduling_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/scheduling_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/BUILD new file mode 100644 index 000000000..a12fa2d2e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/BUILD @@ -0,0 +1,39 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "generated_expansion.go", + "priorityclass.go", + "scheduling_client.go", + ], + importpath = "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/doc.go new file mode 100644 index 000000000..771101956 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1beta1 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/BUILD new file mode 100644 index 000000000..7d9c853a8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/BUILD @@ -0,0 +1,37 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "fake_priorityclass.go", + "fake_scheduling_client.go", + ], + importpath = "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/testing:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/doc.go new file mode 100644 index 000000000..16f443990 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go new file mode 100644 index 000000000..e234fec66 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go @@ -0,0 +1,120 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1beta1 "k8s.io/api/scheduling/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakePriorityClasses implements PriorityClassInterface +type FakePriorityClasses struct { + Fake *FakeSchedulingV1beta1 +} + +var priorityclassesResource = schema.GroupVersionResource{Group: "scheduling.k8s.io", Version: "v1beta1", Resource: "priorityclasses"} + +var priorityclassesKind = schema.GroupVersionKind{Group: "scheduling.k8s.io", Version: "v1beta1", Kind: "PriorityClass"} + +// Get takes name of the priorityClass, and returns the corresponding priorityClass object, and an error if there is any. +func (c *FakePriorityClasses) Get(name string, options v1.GetOptions) (result *v1beta1.PriorityClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(priorityclassesResource, name), &v1beta1.PriorityClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.PriorityClass), err +} + +// List takes label and field selectors, and returns the list of PriorityClasses that match those selectors. +func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *v1beta1.PriorityClassList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(priorityclassesResource, priorityclassesKind, opts), &v1beta1.PriorityClassList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta1.PriorityClassList{ListMeta: obj.(*v1beta1.PriorityClassList).ListMeta} + for _, item := range obj.(*v1beta1.PriorityClassList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested priorityClasses. +func (c *FakePriorityClasses) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(priorityclassesResource, opts)) +} + +// Create takes the representation of a priorityClass and creates it. Returns the server's representation of the priorityClass, and an error, if there is any. +func (c *FakePriorityClasses) Create(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(priorityclassesResource, priorityClass), &v1beta1.PriorityClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.PriorityClass), err +} + +// Update takes the representation of a priorityClass and updates it. Returns the server's representation of the priorityClass, and an error, if there is any. +func (c *FakePriorityClasses) Update(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(priorityclassesResource, priorityClass), &v1beta1.PriorityClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.PriorityClass), err +} + +// Delete takes name of the priorityClass and deletes it. Returns an error if one occurs. +func (c *FakePriorityClasses) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(priorityclassesResource, name), &v1beta1.PriorityClass{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakePriorityClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(priorityclassesResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1beta1.PriorityClassList{}) + return err +} + +// Patch applies the patch and returns the patched priorityClass. +func (c *FakePriorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, data, subresources...), &v1beta1.PriorityClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.PriorityClass), err +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_scheduling_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_scheduling_client.go new file mode 100644 index 000000000..4a6878a45 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake/fake_scheduling_client.go @@ -0,0 +1,40 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeSchedulingV1beta1 struct { + *testing.Fake +} + +func (c *FakeSchedulingV1beta1) PriorityClasses() v1beta1.PriorityClassInterface { + return &FakePriorityClasses{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeSchedulingV1beta1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/generated_expansion.go new file mode 100644 index 000000000..3bab873e6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +type PriorityClassExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/priorityclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/priorityclass.go new file mode 100644 index 000000000..57b9766e4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/priorityclass.go @@ -0,0 +1,147 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1beta1 "k8s.io/api/scheduling/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + scheme "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +// PriorityClassesGetter has a method to return a PriorityClassInterface. +// A group's client should implement this interface. +type PriorityClassesGetter interface { + PriorityClasses() PriorityClassInterface +} + +// PriorityClassInterface has methods to work with PriorityClass resources. +type PriorityClassInterface interface { + Create(*v1beta1.PriorityClass) (*v1beta1.PriorityClass, error) + Update(*v1beta1.PriorityClass) (*v1beta1.PriorityClass, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1beta1.PriorityClass, error) + List(opts v1.ListOptions) (*v1beta1.PriorityClassList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) + PriorityClassExpansion +} + +// priorityClasses implements PriorityClassInterface +type priorityClasses struct { + client rest.Interface +} + +// newPriorityClasses returns a PriorityClasses +func newPriorityClasses(c *SchedulingV1beta1Client) *priorityClasses { + return &priorityClasses{ + client: c.RESTClient(), + } +} + +// Get takes name of the priorityClass, and returns the corresponding priorityClass object, and an error if there is any. +func (c *priorityClasses) Get(name string, options v1.GetOptions) (result *v1beta1.PriorityClass, err error) { + result = &v1beta1.PriorityClass{} + err = c.client.Get(). + Resource("priorityclasses"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of PriorityClasses that match those selectors. +func (c *priorityClasses) List(opts v1.ListOptions) (result *v1beta1.PriorityClassList, err error) { + result = &v1beta1.PriorityClassList{} + err = c.client.Get(). + Resource("priorityclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested priorityClasses. +func (c *priorityClasses) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Resource("priorityclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a priorityClass and creates it. Returns the server's representation of the priorityClass, and an error, if there is any. +func (c *priorityClasses) Create(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) { + result = &v1beta1.PriorityClass{} + err = c.client.Post(). + Resource("priorityclasses"). + Body(priorityClass). + Do(). + Into(result) + return +} + +// Update takes the representation of a priorityClass and updates it. Returns the server's representation of the priorityClass, and an error, if there is any. +func (c *priorityClasses) Update(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) { + result = &v1beta1.PriorityClass{} + err = c.client.Put(). + Resource("priorityclasses"). + Name(priorityClass.Name). + Body(priorityClass). + Do(). + Into(result) + return +} + +// Delete takes name of the priorityClass and deletes it. Returns an error if one occurs. +func (c *priorityClasses) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("priorityclasses"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *priorityClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Resource("priorityclasses"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched priorityClass. +func (c *priorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) { + result = &v1beta1.PriorityClass{} + err = c.client.Patch(pt). + Resource("priorityclasses"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/scheduling_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/scheduling_client.go new file mode 100644 index 000000000..6feec4aec --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/scheduling_client.go @@ -0,0 +1,90 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1beta1 "k8s.io/api/scheduling/v1beta1" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +type SchedulingV1beta1Interface interface { + RESTClient() rest.Interface + PriorityClassesGetter +} + +// SchedulingV1beta1Client is used to interact with features provided by the scheduling.k8s.io group. +type SchedulingV1beta1Client struct { + restClient rest.Interface +} + +func (c *SchedulingV1beta1Client) PriorityClasses() PriorityClassInterface { + return newPriorityClasses(c) +} + +// NewForConfig creates a new SchedulingV1beta1Client for the given config. +func NewForConfig(c *rest.Config) (*SchedulingV1beta1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &SchedulingV1beta1Client{client}, nil +} + +// NewForConfigOrDie creates a new SchedulingV1beta1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *SchedulingV1beta1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new SchedulingV1beta1Client for the given RESTClient. +func New(c rest.Interface) *SchedulingV1beta1Client { + return &SchedulingV1beta1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1beta1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *SchedulingV1beta1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go index 512b38f54..90eaccec5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakePodPresets) List(opts v1.ListOptions) (result *v1alpha1.PodPresetLi if label == nil { label = labels.Everything() } - list := &v1alpha1.PodPresetList{} + list := &v1alpha1.PodPresetList{ListMeta: obj.(*v1alpha1.PodPresetList).ListMeta} for _, item := range obj.(*v1alpha1.PodPresetList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go index fb07a8248..a142edfed 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake/fake_settings_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/generated_expansion.go index f0dbcc607..23d9f94d5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/podpreset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/podpreset.go index 25ed8f543..f000ae486 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/podpreset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/settings_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/settings_client.go index 77fa64040..c2a03b960 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/settings_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1/settings_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go index 9ba1f5104..fc6f98cf6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go index 147ad8028..2b0e279bb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/fake/fake_storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeStorageClasses) List(opts v1.ListOptions) (result *storage_v1.Stora if label == nil { label = labels.Everything() } - list := &storage_v1.StorageClassList{} + list := &storage_v1.StorageClassList{ListMeta: obj.(*storage_v1.StorageClassList).ListMeta} for _, item := range obj.(*storage_v1.StorageClassList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/generated_expansion.go index 08fedd7ed..2bea7ec7f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/storage_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/storage_client.go index 36a189c46..ac48f4916 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/storage_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/storageclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/storageclass.go index 24133cd62..74410b245 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/storageclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go index 5a9ed0964..1a4d9f56f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go index c5db88531..af04b681c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeVolumeAttachments) List(opts v1.ListOptions) (result *v1alpha1.Volu if label == nil { label = labels.Everything() } - list := &v1alpha1.VolumeAttachmentList{} + list := &v1alpha1.VolumeAttachmentList{ListMeta: obj.(*v1alpha1.VolumeAttachmentList).ListMeta} for _, item := range obj.(*v1alpha1.VolumeAttachmentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/generated_expansion.go index e3fc3f399..cdb7ab2f8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/storage_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/storage_client.go index 63834e462..c52f630ac 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/storage_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/volumeattachment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/volumeattachment.go index 7bf79a6c1..e6af00185 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/volumeattachment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go index a81d90542..e0e3f1d78 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go index ce1e72d53..cbfbab1a3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeStorageClasses) List(opts v1.ListOptions) (result *v1beta1.StorageC if label == nil { label = labels.Everything() } - list := &v1beta1.StorageClassList{} + list := &v1beta1.StorageClassList{ListMeta: obj.(*v1beta1.StorageClassList).ListMeta} for _, item := range obj.(*v1beta1.StorageClassList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go index 8bbf197dd..04c0c463a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeVolumeAttachments) List(opts v1.ListOptions) (result *v1beta1.Volum if label == nil { label = labels.Everything() } - list := &v1beta1.VolumeAttachmentList{} + list := &v1beta1.VolumeAttachmentList{ListMeta: obj.(*v1beta1.VolumeAttachmentList).ListMeta} for _, item := range obj.(*v1beta1.VolumeAttachmentList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/generated_expansion.go index 5bb931f05..559f88f67 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storage_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storage_client.go index 4ca05be6f..4bdebb878 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storage_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storage_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storageclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storageclass.go index 63047a7fb..fbe1fd4c2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storageclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/volumeattachment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/volumeattachment.go index fab0801b0..5cd2d3919 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/volumeattachment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1alpha1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1alpha1/expansion_generated.go index 868ee66cf..2c9f9f6a6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1alpha1/initializerconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1alpha1/initializerconfiguration.go index a2cc796dc..dbd7301fc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1alpha1/initializerconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1alpha1/initializerconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/expansion_generated.go index 93dddb5ff..8960abc4f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go index 015587e80..b38732c36 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/mutatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/validatingwebhookconfiguration.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/validatingwebhookconfiguration.go index 243589b2f..b89c9bbe2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/validatingwebhookconfiguration.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1/validatingwebhookconfiguration.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/controllerrevision.go index 19f567e82..9029805a3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/daemonset.go index 7fcd1e063..b022ecc4a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/deployment.go index 2d2ecf0cf..d1be7156e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/expansion_generated.go index 1e8bf6fec..7f5815f79 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/replicaset.go index 99fb92ff4..d487ef656 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/statefulset.go index 6ad54b71f..cc0031858 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/controllerrevision.go index 95aeb0236..d84a865b3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/deployment.go index 4f6e883ba..048558f2a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/expansion_generated.go index 4f3813a94..8f8d08434 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/scale.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/scale.go index 85bf3a6f4..ef8a2630e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/scale.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/statefulset.go index a967e8492..277beb3e4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta1/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/controllerrevision.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/controllerrevision.go index 3d5274dc3..904b59b24 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/controllerrevision.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/controllerrevision.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/daemonset.go index 0ea4dc83f..8a40d2c86 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/deployment.go index 8855bb20c..32beaf25c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/expansion_generated.go index 48cbedb8f..d468f38e7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/replicaset.go index 0fd8dbaa4..18c2136a2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/scale.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/scale.go index f53e42ce8..d89329864 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/scale.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/statefulset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/statefulset.go index 2e095ace4..544bff458 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/statefulset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/apps/v1beta2/statefulset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1/expansion_generated.go index 77b284d8d..a8d097f40 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1/tokenreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1/tokenreview.go index 5f2c6c3e6..5bb907c0c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1/tokenreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1beta1/expansion_generated.go index 3b2b18860..82192059d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1beta1/tokenreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1beta1/tokenreview.go index 9db014e9b..148bcae78 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1beta1/tokenreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authentication/v1beta1/tokenreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/expansion_generated.go index 9a0f2e212..af91939fb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/localsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/localsubjectaccessreview.go index 99055b348..e064c94c1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/localsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/selfsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/selfsubjectaccessreview.go index 627e4dd74..f89bc1dde 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/selfsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/selfsubjectrulesreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/selfsubjectrulesreview.go index 6b2f06352..c65b5f84d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/selfsubjectrulesreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/subjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/subjectaccessreview.go index ca7b47b46..0d6c29b39 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/subjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/expansion_generated.go index d140d6563..24b06185e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/localsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/localsubjectaccessreview.go index 534e39aa9..4eb8158a3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/localsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/localsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectaccessreview.go index c2e82dbb9..4736ccdd5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectrulesreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectrulesreview.go index 5ce83f217..4e47abc3a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectrulesreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/selfsubjectrulesreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/subjectaccessreview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/subjectaccessreview.go index b1853fc3c..5782b4f23 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/subjectaccessreview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/authorization/v1beta1/subjectaccessreview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v1/expansion_generated.go index a20ab75da..05253c770 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v1/horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v1/horizontalpodautoscaler.go index 27ade7ddb..6d563ca98 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v2beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v2beta1/expansion_generated.go index c026b65d5..8d46a4b6e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v2beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v2beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v2beta1/horizontalpodautoscaler.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v2beta1/horizontalpodautoscaler.go index 4c29df910..08d13803b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v2beta1/horizontalpodautoscaler.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/autoscaling/v2beta1/horizontalpodautoscaler.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1/expansion_generated.go index 63091e84a..c43caf240 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1/job.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1/job.go index e29e0271c..909b6f88f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1/job.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1/job.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1beta1/cronjob.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1beta1/cronjob.go index 93f197986..521378ebf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1beta1/cronjob.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1beta1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1beta1/expansion_generated.go index 1d6cc198a..be2742ef6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v2alpha1/cronjob.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v2alpha1/cronjob.go index 6af5f1457..2623f1959 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v2alpha1/cronjob.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v2alpha1/cronjob.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v2alpha1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v2alpha1/expansion_generated.go index 11f6c3471..a30c7a619 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v2alpha1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/batch/v2alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/certificates/v1beta1/certificatesigningrequest.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/certificates/v1beta1/certificatesigningrequest.go index a122c3660..47c282984 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/certificates/v1beta1/certificatesigningrequest.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/certificates/v1beta1/certificatesigningrequest.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/certificates/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/certificates/v1beta1/expansion_generated.go index 6815de7ad..68f993cd6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/certificates/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/certificates/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/componentstatus.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/componentstatus.go index 82fbedac2..23d070810 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/componentstatus.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/componentstatus.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/configmap.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/configmap.go index fc927ab2c..55d7cd4d3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/configmap.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/configmap.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/endpoints.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/endpoints.go index 7799562d7..ac2fdfc57 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/endpoints.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/endpoints.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/event.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/event.go index 738e333db..a9d2db01a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/event.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/expansion_generated.go index b8b985ce0..fac0221b8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/limitrange.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/limitrange.go index 4ee02634d..c773c433e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/limitrange.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/limitrange.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/namespace.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/namespace.go index b819d741e..6a17d0457 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/namespace.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/namespace.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/node.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/node.go index 21a8a0675..b568ebe47 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/node.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/node.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/persistentvolume.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/persistentvolume.go index a88dbd0c0..1d7c6ca76 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/persistentvolume.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/persistentvolume.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/persistentvolumeclaim.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/persistentvolumeclaim.go index 8c3d5f566..501a38c43 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/persistentvolumeclaim.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/persistentvolumeclaim.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/pod.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/pod.go index d3ce8ab32..442f8c55f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/pod.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/pod.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/podtemplate.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/podtemplate.go index 91c2a4661..9a17f820c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/podtemplate.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/podtemplate.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/replicationcontroller.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/replicationcontroller.go index ee00a465c..8b17aa2c4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/replicationcontroller.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/replicationcontroller.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/resourcequota.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/resourcequota.go index fd3119d45..f5b7030cc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/resourcequota.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/resourcequota.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/secret.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/secret.go index f8c2b11e1..e9ef24934 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/secret.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/secret.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/service.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/service.go index d872540b3..3b5941acb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/service.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/service.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/serviceaccount.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/serviceaccount.go index 9973af66b..8b94cf594 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/serviceaccount.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/core/v1/serviceaccount.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/events/v1beta1/event.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/events/v1beta1/event.go index c52afd091..4a5bc3997 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/events/v1beta1/event.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/events/v1beta1/event.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/events/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/events/v1beta1/expansion_generated.go index 9971dd5dd..d311691d9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/events/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/events/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/daemonset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/daemonset.go index b63c32b97..a7bb6657a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/daemonset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/daemonset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/deployment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/deployment.go index ea5168fef..13e307189 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/deployment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/deployment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/expansion_generated.go index 87c3cbe3b..b5ee8a492 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/ingress.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/ingress.go index 1f9e34d17..1bc33ede2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/ingress.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/ingress.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/podsecuritypolicy.go index fadd212f1..1298e87ba 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/replicaset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/replicaset.go index 930db4480..d3e741a86 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/replicaset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/replicaset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/scale.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/scale.go index 67d45e328..527d4be42 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/scale.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/extensions/v1beta1/scale.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/imagepolicy/v1alpha1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/imagepolicy/v1alpha1/expansion_generated.go index 1529fcf3f..9cb13f792 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/imagepolicy/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/imagepolicy/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/imagepolicy/v1alpha1/imagereview.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/imagepolicy/v1alpha1/imagereview.go index cdb046cf9..722e456e7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/imagepolicy/v1alpha1/imagereview.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/imagepolicy/v1alpha1/imagereview.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/networking/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/networking/v1/expansion_generated.go index 458a1d249..e03a52385 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/networking/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/networking/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/networking/v1/networkpolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/networking/v1/networkpolicy.go index b70adedf1..e5d997747 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/networking/v1/networkpolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/networking/v1/networkpolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/eviction.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/eviction.go index 29c454e2a..6e27f5fdc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/eviction.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/eviction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/expansion_generated.go index 3e63c2c9c..9a005f20b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/poddisruptionbudget.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/poddisruptionbudget.go index 7304f36b2..b1f83ee16 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/poddisruptionbudget.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/poddisruptionbudget.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/podsecuritypolicy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/podsecuritypolicy.go index d80f5c56e..e943d3a05 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/podsecuritypolicy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/policy/v1beta1/podsecuritypolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/clusterrole.go index eb1d87006..a612dbeab 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/clusterrolebinding.go index a22d6025e..2c5958ff9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/expansion_generated.go index 967ebdd84..0eb2a6d11 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/role.go index b4649c2c3..9a9d98773 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/rolebinding.go index 8dc0968bb..85a69315a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/clusterrole.go index 302ca29d8..f8c50f65b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/clusterrolebinding.go index 91ba54c23..5769ed0e6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/expansion_generated.go index 737ba6637..2d4ad1756 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/role.go index cf874f56c..c337b589b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/rolebinding.go index 5e76ab42f..4e517f4d6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1alpha1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/clusterrole.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/clusterrole.go index be7f2df6a..01356f4b2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/clusterrole.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/clusterrole.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/clusterrolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/clusterrolebinding.go index 09d65be76..6d3f14338 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/clusterrolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/clusterrolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/expansion_generated.go index 8da573661..51f674bd0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/role.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/role.go index e12039dbf..c946c43a7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/role.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/role.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/rolebinding.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/rolebinding.go index 10cb23cd3..0eec45bde 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/rolebinding.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/rbac/v1beta1/rolebinding.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1alpha1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1alpha1/expansion_generated.go index 00b662888..bde8b6206 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1alpha1/priorityclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1alpha1/priorityclass.go index fb7f6007c..a3059c94d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1alpha1/priorityclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1alpha1/priorityclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1beta1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1beta1/BUILD new file mode 100644 index 000000000..1eb397386 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1beta1/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "expansion_generated.go", + "priorityclass.go", + ], + importpath = "k8s.io/client-go/listers/scheduling/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1beta1/expansion_generated.go new file mode 100644 index 000000000..b806e8cf8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1beta1/expansion_generated.go @@ -0,0 +1,23 @@ +/* +Copyright 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1beta1 + +// PriorityClassListerExpansion allows custom methods to be added to +// PriorityClassLister. +type PriorityClassListerExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1beta1/priorityclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1beta1/priorityclass.go new file mode 100644 index 000000000..9d0606392 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/scheduling/v1beta1/priorityclass.go @@ -0,0 +1,65 @@ +/* +Copyright 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1beta1 "k8s.io/api/scheduling/v1beta1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// PriorityClassLister helps list PriorityClasses. +type PriorityClassLister interface { + // List lists all PriorityClasses in the indexer. + List(selector labels.Selector) (ret []*v1beta1.PriorityClass, err error) + // Get retrieves the PriorityClass from the index for a given name. + Get(name string) (*v1beta1.PriorityClass, error) + PriorityClassListerExpansion +} + +// priorityClassLister implements the PriorityClassLister interface. +type priorityClassLister struct { + indexer cache.Indexer +} + +// NewPriorityClassLister returns a new PriorityClassLister. +func NewPriorityClassLister(indexer cache.Indexer) PriorityClassLister { + return &priorityClassLister{indexer: indexer} +} + +// List lists all PriorityClasses in the indexer. +func (s *priorityClassLister) List(selector labels.Selector) (ret []*v1beta1.PriorityClass, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta1.PriorityClass)) + }) + return ret, err +} + +// Get retrieves the PriorityClass from the index for a given name. +func (s *priorityClassLister) Get(name string) (*v1beta1.PriorityClass, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1beta1.Resource("priorityclass"), name) + } + return obj.(*v1beta1.PriorityClass), nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/settings/v1alpha1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/settings/v1alpha1/expansion_generated.go index 72558897b..fba210343 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/settings/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/settings/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/settings/v1alpha1/podpreset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/settings/v1alpha1/podpreset.go index d30036962..c862e7d7d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/settings/v1alpha1/podpreset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/settings/v1alpha1/podpreset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1/expansion_generated.go index 49e290f4c..d93247064 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1/storageclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1/storageclass.go index 5b20f6ab5..13e8536b4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1/storageclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1alpha1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1alpha1/expansion_generated.go index 2fc6add1d..7ca765622 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1alpha1/volumeattachment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1alpha1/volumeattachment.go index f8d1bdb2d..7871f55e4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1alpha1/volumeattachment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1alpha1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/expansion_generated.go index 8c2dc9055..21d95620c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/storageclass.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/storageclass.go index 45afe0e77..07bc97b32 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/storageclass.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/storageclass.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/volumeattachment.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/volumeattachment.go index c9cc3984e..7193441b0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/volumeattachment.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/listers/storage/v1beta1/volumeattachment.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/BUILD index 64cdd678d..9536954e0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/BUILD @@ -30,6 +30,7 @@ filegroup( ":package-srcs", "//staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install:all-srcs", "//staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install/BUILD index de371ab22..949935bc4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install/BUILD @@ -10,9 +10,8 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/client-go/pkg/apis/clientauthentication/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", "//vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install/install.go index 40093e97f..1b7b5f949 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/pkg/apis/clientauthentication" "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: clientauthentication.GroupName, - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: clientauthentication.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(clientauthentication.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/types.go index 5c05825f6..6fb53cecf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/types.go @@ -57,7 +57,14 @@ type ExecCredentialStatus struct { // +optional ExpirationTimestamp *metav1.Time // Token is a bearer token used by the client for request authentication. + // +optional Token string + // PEM-encoded client TLS certificate. + // +optional + ClientCertificateData string + // PEM-encoded client TLS private key. + // +optional + ClientKeyData string } // Response defines metadata about a failed request, including HTTP status code and diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go index 8920d3187..921f3a2b9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go @@ -52,12 +52,20 @@ type ExecCredentialSpec struct { } // ExecCredentialStatus holds credentials for the transport to use. +// +// Token and ClientKeyData are sensitive fields. This data should only be +// transmitted in-memory between client and exec plugin process. Exec plugin +// itself should at least be protected via file permissions. type ExecCredentialStatus struct { // ExpirationTimestamp indicates a time when the provided credentials expire. // +optional ExpirationTimestamp *metav1.Time `json:"expirationTimestamp,omitempty"` // Token is a bearer token used by the client for request authentication. Token string `json:"token,omitempty"` + // PEM-encoded client TLS certificates (including intermediates, if any). + ClientCertificateData string `json:"clientCertificateData,omitempty"` + // PEM-encoded private key for the above certificate. + ClientKeyData string `json:"clientKeyData,omitempty"` } // Response defines metadata about a failed request, including HTTP status code and diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go index bf28baef2..9921c7ee5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -99,6 +99,8 @@ func Convert_clientauthentication_ExecCredentialSpec_To_v1alpha1_ExecCredentialS func autoConvert_v1alpha1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error { out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData return nil } @@ -110,6 +112,8 @@ func Convert_v1alpha1_ExecCredentialStatus_To_clientauthentication_ExecCredentia func autoConvert_clientauthentication_ExecCredentialStatus_To_v1alpha1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error { out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData return nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.deepcopy.go index c6dbbce4d..f062b8f06 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.defaults.go index 2bd0078a3..dd621a3ac 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/BUILD new file mode 100644 index 000000000..6431610f3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/BUILD @@ -0,0 +1,37 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "conversion.go", + "doc.go", + "register.go", + "types.go", + "zz_generated.conversion.go", + "zz_generated.deepcopy.go", + "zz_generated.defaults.go", + ], + importpath = "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//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/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/conversion.go new file mode 100644 index 000000000..f543806ac --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/conversion.go @@ -0,0 +1,26 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + clientauthentication "k8s.io/client-go/pkg/apis/clientauthentication" +) + +func Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error { + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/doc.go new file mode 100644 index 000000000..fbcd9b7fe --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2018 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. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/client-go/pkg/apis/clientauthentication +// +k8s:openapi-gen=true +// +k8s:defaulter-gen=TypeMeta + +// +groupName=client.authentication.k8s.io +package v1beta1 // import "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/register.go new file mode 100644 index 000000000..0bb92f16a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/register.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "client.authentication.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ExecCredential{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.go new file mode 100644 index 000000000..d6e267452 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.go @@ -0,0 +1,59 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExecCredentials is used by exec-based plugins to communicate credentials to +// HTTP transports. +type ExecCredential struct { + metav1.TypeMeta `json:",inline"` + + // Spec holds information passed to the plugin by the transport. This contains + // request and runtime specific information, such as if the session is interactive. + Spec ExecCredentialSpec `json:"spec,omitempty"` + + // Status is filled in by the plugin and holds the credentials that the transport + // should use to contact the API. + // +optional + Status *ExecCredentialStatus `json:"status,omitempty"` +} + +// ExecCredenitalSpec holds request and runtime specific information provided by +// the transport. +type ExecCredentialSpec struct{} + +// ExecCredentialStatus holds credentials for the transport to use. +// +// Token and ClientKeyData are sensitive fields. This data should only be +// transmitted in-memory between client and exec plugin process. Exec plugin +// itself should at least be protected via file permissions. +type ExecCredentialStatus struct { + // ExpirationTimestamp indicates a time when the provided credentials expire. + // +optional + ExpirationTimestamp *metav1.Time `json:"expirationTimestamp,omitempty"` + // Token is a bearer token used by the client for request authentication. + Token string `json:"token,omitempty"` + // PEM-encoded client TLS certificates (including intermediates, if any). + ClientCertificateData string `json:"clientCertificateData,omitempty"` + // PEM-encoded private key for the above certificate. + ClientKeyData string `json:"clientKeyData,omitempty"` +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go new file mode 100644 index 000000000..80e9b3159 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go @@ -0,0 +1,114 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1beta1 + +import ( + unsafe "unsafe" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + clientauthentication "k8s.io/client-go/pkg/apis/clientauthentication" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(scheme *runtime.Scheme) error { + return scheme.AddGeneratedConversionFuncs( + Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential, + Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential, + Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec, + Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec, + Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus, + Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus, + ) +} + +func autoConvert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in *ExecCredential, out *clientauthentication.ExecCredential, s conversion.Scope) error { + if err := Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + out.Status = (*clientauthentication.ExecCredentialStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential is an autogenerated conversion function. +func Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in *ExecCredential, out *clientauthentication.ExecCredential, s conversion.Scope) error { + return autoConvert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in, out, s) +} + +func autoConvert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in *clientauthentication.ExecCredential, out *ExecCredential, s conversion.Scope) error { + if err := Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + out.Status = (*ExecCredentialStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential is an autogenerated conversion function. +func Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in *clientauthentication.ExecCredential, out *ExecCredential, s conversion.Scope) error { + return autoConvert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in, out, s) +} + +func autoConvert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in *ExecCredentialSpec, out *clientauthentication.ExecCredentialSpec, s conversion.Scope) error { + return nil +} + +// Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec is an autogenerated conversion function. +func Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in *ExecCredentialSpec, out *clientauthentication.ExecCredentialSpec, s conversion.Scope) error { + return autoConvert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in, out, s) +} + +func autoConvert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error { + // WARNING: in.Response requires manual conversion: does not exist in peer-type + // WARNING: in.Interactive requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error { + out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) + out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData + return nil +} + +// Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus is an autogenerated conversion function. +func Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error { + return autoConvert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in, out, s) +} + +func autoConvert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error { + out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp)) + out.Token = in.Token + out.ClientCertificateData = in.ClientCertificateData + out.ClientKeyData = in.ClientKeyData + return nil +} + +// Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus is an autogenerated conversion function. +func Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error { + return autoConvert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in, out, s) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 000000000..656fea4d8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,100 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecCredential) DeepCopyInto(out *ExecCredential) { + *out = *in + out.TypeMeta = in.TypeMeta + out.Spec = in.Spec + if in.Status != nil { + in, out := &in.Status, &out.Status + if *in == nil { + *out = nil + } else { + *out = new(ExecCredentialStatus) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredential. +func (in *ExecCredential) DeepCopy() *ExecCredential { + if in == nil { + return nil + } + out := new(ExecCredential) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExecCredential) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecCredentialSpec) DeepCopyInto(out *ExecCredentialSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredentialSpec. +func (in *ExecCredentialSpec) DeepCopy() *ExecCredentialSpec { + if in == nil { + return nil + } + out := new(ExecCredentialSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecCredentialStatus) DeepCopyInto(out *ExecCredentialStatus) { + *out = *in + if in.ExpirationTimestamp != nil { + in, out := &in.ExpirationTimestamp, &out.ExpirationTimestamp + if *in == nil { + *out = nil + } else { + *out = (*in).DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredentialStatus. +func (in *ExecCredentialStatus) DeepCopy() *ExecCredentialStatus { + if in == nil { + return nil + } + out := new(ExecCredentialStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.defaults.go new file mode 100644 index 000000000..73e63fc11 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/zz_generated.defaults.go @@ -0,0 +1,32 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/zz_generated.deepcopy.go index f8b15d848..008c3c7df 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/version/base.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/version/base.go index 7ab0ed3a7..9b4c79f89 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/version/base.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/pkg/version/base.go @@ -43,7 +43,7 @@ var ( gitMinor string = "" // minor version, numeric possibly followed by "+" // semantic version, derived by build scripts (see - // https://github.com/kubernetes/kubernetes/blob/master/docs/design/versioning.md + // https://git.k8s.io/community/contributors/design-proposals/release/versioning.md // for a detailed discussion of this field) // // TODO: This field is still called "gitVersion" for legacy diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/README.md b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/README.md index 0b5e62bd4..e4ba791ea 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/README.md +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/README.md @@ -1,15 +1,14 @@ # Azure Active Directory plugin for client authentication -This plugin provides an integration with Azure Active Directory device flow. If no tokens are present in the kubectl configuration, it will prompt a device code which can be used to login in a browser. After login it will automatically fetch the tokens and stored them in the kubectl configuration. In addition it will refresh and update the tokens in configuration when expired. - +This plugin provides an integration with Azure Active Directory device flow. If no tokens are present in the kubectl configuration, it will prompt a device code which can be used to login in a browser. After login it will automatically fetch the tokens and store them in the kubectl configuration. In addition it will refresh and update the tokens in the configuration when expired. ## Usage -1. Create an Azure Active Directory *Web App / API* application for `apiserver` following these [instructions](https://docs.microsoft.com/en-us/azure/active-directory/active-directory-app-registration) +1. Create an Azure Active Directory *Web App / API* application for `apiserver` following these [instructions](https://docs.microsoft.com/en-us/azure/active-directory/active-directory-app-registration). The callback URL does not matter (just cannot be empty). -2. Create a second Azure Active Directory native application for `kubectl` +2. Create a second Azure Active Directory native application for `kubectl`. The callback URL does not matter (just cannot be empty). -3. On `kubectl` application's configuration page in Azure portal grant permissions to `apiserver` application by clicking on *Required Permissions*, click the *Add* button and search for the apiserver application created in step 1. Select "Access apiserver" under the *DELEGATED PERMISSIONS*. Once added click the *Grant Permissions* button to apply the changes +3. On `kubectl` application's configuration page in Azure portal grant permissions to `apiserver` application by clicking on *Required Permissions*, click the *Add* button and search for the apiserver application created in step 1. Select "Access apiserver" under the *DELEGATED PERMISSIONS*. Once added click the *Grant Permissions* button to apply the changes. 4. Configure the `apiserver` to use the Azure Active Directory as an OIDC provider with following options @@ -21,8 +20,9 @@ This plugin provides an integration with Azure Active Directory device flow. If * Replace the `APISERVER_APPLICATION_ID` with the application ID of `apiserver` application * Replace `TENANT_ID` with your tenant ID. +   * For a list of alternative username claims that are supported by the OIDC issuer check the JSON response at `https://sts.windows.net/TENANT_ID/.well-known/openid-configuration`. -5. Configure the `kubectl` to use the `azure` authentication provider +5. Configure `kubectl` to use the `azure` authentication provider ``` kubectl config set-credentials "USER_NAME" --auth-provider=azure \ @@ -35,7 +35,8 @@ This plugin provides an integration with Azure Active Directory device flow. If * Supported environments: `AzurePublicCloud`, `AzureUSGovernmentCloud`, `AzureChinaCloud`, `AzureGermanCloud` * Replace `USER_NAME` and `TENANT_ID` with your user name and tenant ID * Replace `APPLICATION_ID` with the application ID of your`kubectl` application ID - * Replace `APISERVER_APPLICATION_ID` with the application ID of your `apiserver` application ID + * Replace `APISERVER_APPLICATION_ID` with the application ID of your `apiserver` application ID + * Be sure to also (create and) select a context that uses above user 6. The access token is acquired when first `kubectl` command is executed @@ -45,4 +46,5 @@ This plugin provides an integration with Azure Active Directory device flow. If To sign in, use a web browser to open the page https://aka.ms/devicelogin and enter the code DEC7D48GA to authenticate. ``` - * After signing in a web browser, the token is stored in the configuration, and it will be reused when executing next commands. + * After signing in a web browser, the token is stored in the configuration, and it will be reused when executing further commands. + * The resulting username in Kubernetes depends on your [configuration of the `--oidc-username-claim` and `--oidc-username-prefix` flags on the API server](https://kubernetes.io/docs/admin/authentication/#configuring-the-api-server). If you are using any authorization method you need to give permissions to that user, e.g. by binding the user to a role in the case of RBAC. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go index e14dc8d9d..60304b0f3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go @@ -297,7 +297,7 @@ func (ts *azureTokenSource) refreshToken(token *azureToken) (*azureToken, error) } return &azureToken{ - token: spt.Token, + token: spt.Token(), clientID: token.clientID, tenantID: token.tenantID, apiserverID: token.apiserverID, diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD index 38cf9bdc2..9af48cf30 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/BUILD @@ -14,7 +14,10 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", "//vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1:go_default_library", + "//vendor/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", + "//vendor/k8s.io/client-go/transport:go_default_library", + "//vendor/k8s.io/client-go/util/connrotation:go_default_library", ], ) @@ -24,8 +27,11 @@ go_test( data = glob(["testdata/**"]), embed = [":go_default_library"], deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/pkg/apis/clientauthentication:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", + "//vendor/k8s.io/client-go/transport:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go index dfd434d0c..ed09f66f4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go @@ -18,11 +18,16 @@ package exec import ( "bytes" + "context" + "crypto/tls" + "errors" "fmt" "io" + "net" "net/http" "os" "os/exec" + "reflect" "sync" "time" @@ -34,7 +39,10 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/client-go/pkg/apis/clientauthentication" "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1" + "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1" "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/client-go/transport" + "k8s.io/client-go/util/connrotation" ) const execInfoEnv = "KUBERNETES_EXEC_INFO" @@ -45,6 +53,7 @@ var codecs = serializer.NewCodecFactory(scheme) func init() { v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) v1alpha1.AddToScheme(scheme) + v1beta1.AddToScheme(scheme) clientauthentication.AddToScheme(scheme) } @@ -55,6 +64,7 @@ var ( // The list of API versions we accept. apiVersions = map[string]schema.GroupVersion{ v1alpha1.SchemeGroupVersion.String(): v1alpha1.SchemeGroupVersion, + v1beta1.SchemeGroupVersion.String(): v1beta1.SchemeGroupVersion, } ) @@ -147,14 +157,44 @@ type Authenticator struct { // The mutex also guards calling the plugin. Since the plugin could be // interactive we want to make sure it's only called once. mu sync.Mutex - cachedToken string + cachedCreds *credentials exp time.Time + + onRotate func() } -// WrapTransport instruments an existing http.RoundTripper with credentials returned -// by the plugin. -func (a *Authenticator) WrapTransport(rt http.RoundTripper) http.RoundTripper { - return &roundTripper{a, rt} +type credentials struct { + token string + cert *tls.Certificate +} + +// UpdateTransportConfig updates the transport.Config to use credentials +// returned by the plugin. +func (a *Authenticator) UpdateTransportConfig(c *transport.Config) error { + wt := c.WrapTransport + c.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { + if wt != nil { + rt = wt(rt) + } + return &roundTripper{a, rt} + } + + if c.TLS.GetCert != nil { + return errors.New("can't add TLS certificate callback: transport.Config.TLS.GetCert already set") + } + c.TLS.GetCert = a.cert + + var dial func(ctx context.Context, network, addr string) (net.Conn, error) + if c.Dial != nil { + dial = c.Dial + } else { + dial = (&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext + } + d := connrotation.NewDialer(dial) + a.onRotate = d.CloseAll + c.Dial = d.DialContext + + return nil } type roundTripper struct { @@ -169,11 +209,13 @@ func (r *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { return r.base.RoundTrip(req) } - token, err := r.a.token() + creds, err := r.a.getCreds() if err != nil { - return nil, fmt.Errorf("getting token: %v", err) + return nil, fmt.Errorf("getting credentials: %v", err) + } + if creds.token != "" { + req.Header.Set("Authorization", "Bearer "+creds.token) } - req.Header.Set("Authorization", "Bearer "+token) res, err := r.base.RoundTrip(req) if err != nil { @@ -184,47 +226,60 @@ func (r *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { Header: res.Header, Code: int32(res.StatusCode), } - if err := r.a.refresh(token, resp); err != nil { - glog.Errorf("refreshing token: %v", err) + if err := r.a.maybeRefreshCreds(creds, resp); err != nil { + glog.Errorf("refreshing credentials: %v", err) } } return res, nil } -func (a *Authenticator) tokenExpired() bool { +func (a *Authenticator) credsExpired() bool { if a.exp.IsZero() { return false } return a.now().After(a.exp) } -func (a *Authenticator) token() (string, error) { +func (a *Authenticator) cert() (*tls.Certificate, error) { + creds, err := a.getCreds() + if err != nil { + return nil, err + } + return creds.cert, nil +} + +func (a *Authenticator) getCreds() (*credentials, error) { a.mu.Lock() defer a.mu.Unlock() - if a.cachedToken != "" && !a.tokenExpired() { - return a.cachedToken, nil + if a.cachedCreds != nil && !a.credsExpired() { + return a.cachedCreds, nil } - return a.getToken(nil) + if err := a.refreshCredsLocked(nil); err != nil { + return nil, err + } + return a.cachedCreds, nil } -// refresh executes the plugin to force a rotation of the token. -func (a *Authenticator) refresh(token string, r *clientauthentication.Response) error { +// maybeRefreshCreds executes the plugin to force a rotation of the +// credentials, unless they were rotated already. +func (a *Authenticator) maybeRefreshCreds(creds *credentials, r *clientauthentication.Response) error { a.mu.Lock() defer a.mu.Unlock() - if token != a.cachedToken { - // Token already rotated. + // Since we're not making a new pointer to a.cachedCreds in getCreds, no + // need to do deep comparison. + if creds != a.cachedCreds { + // Credentials already rotated. return nil } - _, err := a.getToken(r) - return err + return a.refreshCredsLocked(r) } -// getToken executes the plugin and reads the credentials from stdout. It must be -// called while holding the Authenticator's mutex. -func (a *Authenticator) getToken(r *clientauthentication.Response) (string, error) { +// refreshCredsLocked executes the plugin and reads the credentials from +// stdout. It must be called while holding the Authenticator's mutex. +func (a *Authenticator) refreshCredsLocked(r *clientauthentication.Response) error { cred := &clientauthentication.ExecCredential{ Spec: clientauthentication.ExecCredentialSpec{ Response: r, @@ -232,13 +287,18 @@ func (a *Authenticator) getToken(r *clientauthentication.Response) (string, erro }, } - data, err := runtime.Encode(codecs.LegacyCodec(a.group), cred) - if err != nil { - return "", fmt.Errorf("encode ExecCredentials: %v", err) - } - env := append(a.environ(), a.env...) - env = append(env, fmt.Sprintf("%s=%s", execInfoEnv, data)) + if a.group == v1alpha1.SchemeGroupVersion { + // Input spec disabled for beta due to lack of use. Possibly re-enable this later if + // someone wants it back. + // + // See: https://github.com/kubernetes/kubernetes/issues/61796 + data, err := runtime.Encode(codecs.LegacyCodec(a.group), cred) + if err != nil { + return fmt.Errorf("encode ExecCredentials: %v", err) + } + env = append(env, fmt.Sprintf("%s=%s", execInfoEnv, data)) + } stdout := &bytes.Buffer{} cmd := exec.Command(a.cmd, a.args...) @@ -250,23 +310,26 @@ func (a *Authenticator) getToken(r *clientauthentication.Response) (string, erro } if err := cmd.Run(); err != nil { - return "", fmt.Errorf("exec: %v", err) + return fmt.Errorf("exec: %v", err) } _, gvk, err := codecs.UniversalDecoder(a.group).Decode(stdout.Bytes(), nil, cred) if err != nil { - return "", fmt.Errorf("decode stdout: %v", err) + return fmt.Errorf("decoding stdout: %v", err) } if gvk.Group != a.group.Group || gvk.Version != a.group.Version { - return "", fmt.Errorf("exec plugin is configured to use API version %s, plugin returned version %s", + return fmt.Errorf("exec plugin is configured to use API version %s, plugin returned version %s", a.group, schema.GroupVersion{Group: gvk.Group, Version: gvk.Version}) } if cred.Status == nil { - return "", fmt.Errorf("exec plugin didn't return a status field") + return fmt.Errorf("exec plugin didn't return a status field") + } + if cred.Status.Token == "" && cred.Status.ClientCertificateData == "" && cred.Status.ClientKeyData == "" { + return fmt.Errorf("exec plugin didn't return a token or cert/key pair") } - if cred.Status.Token == "" { - return "", fmt.Errorf("exec plugin didn't return a token") + if (cred.Status.ClientCertificateData == "") != (cred.Status.ClientKeyData == "") { + return fmt.Errorf("exec plugin returned only certificate or key, not both") } if cred.Status.ExpirationTimestamp != nil { @@ -274,7 +337,24 @@ func (a *Authenticator) getToken(r *clientauthentication.Response) (string, erro } else { a.exp = time.Time{} } - a.cachedToken = cred.Status.Token - return a.cachedToken, nil + newCreds := &credentials{ + token: cred.Status.Token, + } + if cred.Status.ClientKeyData != "" && cred.Status.ClientCertificateData != "" { + cert, err := tls.X509KeyPair([]byte(cred.Status.ClientCertificateData), []byte(cred.Status.ClientKeyData)) + if err != nil { + return fmt.Errorf("failed parsing client key/certificate: %v", err) + } + newCreds.cert = &cert + } + + oldCreds := a.cachedCreds + a.cachedCreds = newCreds + // Only close all connections when TLS cert rotates. Token rotation doesn't + // need the extra noise. + if a.onRotate != nil && oldCreds != nil && !reflect.DeepEqual(oldCreds.cert, a.cachedCreds.cert) { + a.onRotate() + } + return nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go index 28137eb84..e3398e821 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/exec_test.go @@ -18,19 +18,88 @@ package exec import ( "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" "encoding/json" + "encoding/pem" "fmt" "io/ioutil" + "math/big" "net/http" "net/http/httptest" + "reflect" "strings" "testing" "time" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/pkg/apis/clientauthentication" "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/client-go/transport" ) +var ( + certData = []byte(`-----BEGIN CERTIFICATE----- +MIIC6jCCAdSgAwIBAgIBCzALBgkqhkiG9w0BAQswIzEhMB8GA1UEAwwYMTAuMTMu +MTI5LjEwNkAxNDIxMzU5MDU4MB4XDTE1MDExNTIyMDEzMVoXDTE2MDExNTIyMDEz +MlowGzEZMBcGA1UEAxMQb3BlbnNoaWZ0LWNsaWVudDCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKtdhz0+uCLXw5cSYns9rU/XifFSpb/x24WDdrm72S/v +b9BPYsAStiP148buylr1SOuNi8sTAZmlVDDIpIVwMLff+o2rKYDicn9fjbrTxTOj +lI4pHJBH+JU3AJ0tbajupioh70jwFS0oYpwtneg2zcnE2Z4l6mhrj2okrc5Q1/X2 +I2HChtIU4JYTisObtin10QKJX01CLfYXJLa8upWzKZ4/GOcHG+eAV3jXWoXidtjb +1Usw70amoTZ6mIVCkiu1QwCoa8+ycojGfZhvqMsAp1536ZcCul+Na+AbCv4zKS7F +kQQaImVrXdUiFansIoofGlw/JNuoKK6ssVpS5Ic3pgcCAwEAAaM1MDMwDgYDVR0P +AQH/BAQDAgCgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJ +KoZIhvcNAQELA4IBAQCKLREH7bXtXtZ+8vI6cjD7W3QikiArGqbl36bAhhWsJLp/ +p/ndKz39iFNaiZ3GlwIURWOOKx3y3GA0x9m8FR+Llthf0EQ8sUjnwaknWs0Y6DQ3 +jjPFZOpV3KPCFrdMJ3++E3MgwFC/Ih/N2ebFX9EcV9Vcc6oVWMdwT0fsrhu683rq +6GSR/3iVX1G/pmOiuaR0fNUaCyCfYrnI4zHBDgSfnlm3vIvN2lrsR/DQBakNL8DJ +HBgKxMGeUPoneBv+c8DMXIL0EhaFXRlBv9QW45/GiAIOuyFJ0i6hCtGZpJjq4OpQ +BRjCI+izPzFTjsxD4aORE+WOkyWFCGPWKfNejfw0 +-----END CERTIFICATE-----`) + keyData = []byte(`-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAq12HPT64ItfDlxJiez2tT9eJ8VKlv/HbhYN2ubvZL+9v0E9i +wBK2I/Xjxu7KWvVI642LyxMBmaVUMMikhXAwt9/6jaspgOJyf1+NutPFM6OUjikc +kEf4lTcAnS1tqO6mKiHvSPAVLShinC2d6DbNycTZniXqaGuPaiStzlDX9fYjYcKG +0hTglhOKw5u2KfXRAolfTUIt9hcktry6lbMpnj8Y5wcb54BXeNdaheJ22NvVSzDv +RqahNnqYhUKSK7VDAKhrz7JyiMZ9mG+oywCnXnfplwK6X41r4BsK/jMpLsWRBBoi +ZWtd1SIVqewiih8aXD8k26gorqyxWlLkhzemBwIDAQABAoIBAD2XYRs3JrGHQUpU +FkdbVKZkvrSY0vAZOqBTLuH0zUv4UATb8487anGkWBjRDLQCgxH+jucPTrztekQK +aW94clo0S3aNtV4YhbSYIHWs1a0It0UdK6ID7CmdWkAj6s0T8W8lQT7C46mWYVLm +5mFnCTHi6aB42jZrqmEpC7sivWwuU0xqj3Ml8kkxQCGmyc9JjmCB4OrFFC8NNt6M +ObvQkUI6Z3nO4phTbpxkE1/9dT0MmPIF7GhHVzJMS+EyyRYUDllZ0wvVSOM3qZT0 +JMUaBerkNwm9foKJ1+dv2nMKZZbJajv7suUDCfU44mVeaEO+4kmTKSGCGjjTBGkr +7L1ySDECgYEA5ElIMhpdBzIivCuBIH8LlUeuzd93pqssO1G2Xg0jHtfM4tz7fyeI +cr90dc8gpli24dkSxzLeg3Tn3wIj/Bu64m2TpZPZEIlukYvgdgArmRIPQVxerYey +OkrfTNkxU1HXsYjLCdGcGXs5lmb+K/kuTcFxaMOs7jZi7La+jEONwf8CgYEAwCs/ +rUOOA0klDsWWisbivOiNPII79c9McZCNBqncCBfMUoiGe8uWDEO4TFHN60vFuVk9 +8PkwpCfvaBUX+ajvbafIfHxsnfk1M04WLGCeqQ/ym5Q4sQoQOcC1b1y9qc/xEWfg +nIUuia0ukYRpl7qQa3tNg+BNFyjypW8zukUAC/kCgYB1/Kojuxx5q5/oQVPrx73k +2bevD+B3c+DYh9MJqSCNwFtUpYIWpggPxoQan4LwdsmO0PKzocb/ilyNFj4i/vII +NToqSc/WjDFpaDIKyuu9oWfhECye45NqLWhb/6VOuu4QA/Nsj7luMhIBehnEAHW+ +GkzTKM8oD1PxpEG3nPKXYQKBgQC6AuMPRt3XBl1NkCrpSBy/uObFlFaP2Enpf39S +3OZ0Gv0XQrnSaL1kP8TMcz68rMrGX8DaWYsgytstR4W+jyy7WvZwsUu+GjTJ5aMG +77uEcEBpIi9CBzivfn7hPccE8ZgqPf+n4i6q66yxBJflW5xhvafJqDtW2LcPNbW/ +bvzdmQKBgExALRUXpq+5dbmkdXBHtvXdRDZ6rVmrnjy4nI5bPw+1GqQqk6uAR6B/ +F6NmLCQOO4PDG/cuatNHIr2FrwTmGdEL6ObLUGWn9Oer9gJhHVqqsY5I4sEPo4XX +stR0Yiw0buV6DL/moUO0HIM9Bjh96HJp+LxiIS6UCdIhMPp5HoQa +-----END RSA PRIVATE KEY-----`) + validCert *tls.Certificate +) + +func init() { + cert, err := tls.X509KeyPair(certData, keyData) + if err != nil { + panic(err) + } + validCert = &cert +} + func TestCacheKey(t *testing.T) { c1 := &api.ExecConfig{ Command: "foo-bar", @@ -93,7 +162,7 @@ func compJSON(t *testing.T, got, want []byte) { } } -func TestGetToken(t *testing.T) { +func TestRefreshCreds(t *testing.T) { tests := []struct { name string config api.ExecConfig @@ -101,7 +170,7 @@ func TestGetToken(t *testing.T) { interactive bool response *clientauthentication.Response wantInput string - wantToken string + wantCreds credentials wantExpiry time.Time wantErr bool }{ @@ -122,7 +191,7 @@ func TestGetToken(t *testing.T) { "token": "foo-bar" } }`, - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "interactive", @@ -144,7 +213,7 @@ func TestGetToken(t *testing.T) { "token": "foo-bar" } }`, - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "response", @@ -178,7 +247,7 @@ func TestGetToken(t *testing.T) { "token": "foo-bar" } }`, - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "expiry", @@ -199,7 +268,7 @@ func TestGetToken(t *testing.T) { } }`, wantExpiry: time.Date(2006, 01, 02, 15, 04, 05, 0, time.UTC), - wantToken: "foo-bar", + wantCreds: credentials{token: "foo-bar"}, }, { name: "no-group-version", @@ -236,7 +305,44 @@ func TestGetToken(t *testing.T) { wantErr: true, }, { - name: "no-token", + name: "no-creds", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1alpha1", + }, + wantInput: `{ + "kind":"ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1alpha1", + "spec": {} + }`, + output: `{ + "kind": "ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1alpha1", + "status": {} + }`, + wantErr: true, + }, + { + name: "TLS credentials", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1alpha1", + }, + wantInput: `{ + "kind":"ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1alpha1", + "spec": {} + }`, + output: fmt.Sprintf(`{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1alpha1", + "status": { + "clientKeyData": %q, + "clientCertificateData": %q + } + }`, keyData, certData), + wantCreds: credentials{cert: validCert}, + }, + { + name: "bad TLS credentials", config: api.ExecConfig{ APIVersion: "client.authentication.k8s.io/v1alpha1", }, @@ -247,7 +353,95 @@ func TestGetToken(t *testing.T) { }`, output: `{ "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1alpha1", + "status": { + "clientKeyData": "foo", + "clientCertificateData": "bar" + } + }`, + wantErr: true, + }, + { + name: "cert but no key", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1alpha1", + }, + wantInput: `{ + "kind":"ExecCredential", "apiVersion":"client.authentication.k8s.io/v1alpha1", + "spec": {} + }`, + output: fmt.Sprintf(`{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1alpha1", + "status": { + "clientCertificateData": %q + } + }`, certData), + wantErr: true, + }, + { + name: "beta-basic-request", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1beta1", + "status": { + "token": "foo-bar" + } + }`, + wantCreds: credentials{token: "foo-bar"}, + }, + { + name: "beta-expiry", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion": "client.authentication.k8s.io/v1beta1", + "status": { + "token": "foo-bar", + "expirationTimestamp": "2006-01-02T15:04:05Z" + } + }`, + wantExpiry: time.Date(2006, 01, 02, 15, 04, 05, 0, time.UTC), + wantCreds: credentials{token: "foo-bar"}, + }, + { + name: "beta-no-group-version", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "status": { + "token": "foo-bar" + } + }`, + wantErr: true, + }, + { + name: "beta-no-status", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1beta1" + }`, + wantErr: true, + }, + { + name: "beta-no-token", + config: api.ExecConfig{ + APIVersion: "client.authentication.k8s.io/v1beta1", + }, + output: `{ + "kind": "ExecCredential", + "apiVersion":"client.authentication.k8s.io/v1beta1", "status": {} }`, wantErr: true, @@ -274,8 +468,7 @@ func TestGetToken(t *testing.T) { a.interactive = test.interactive a.environ = func() []string { return nil } - token, err := a.getToken(test.response) - if err != nil { + if err := a.refreshCredsLocked(test.response); err != nil { if !test.wantErr { t.Errorf("get token %v", err) } @@ -285,14 +478,21 @@ func TestGetToken(t *testing.T) { t.Fatal("expected error getting token") } - if token != test.wantToken { - t.Errorf("expected token %q got %q", test.wantToken, token) + if !reflect.DeepEqual(a.cachedCreds, &test.wantCreds) { + t.Errorf("expected credentials %+v got %+v", &test.wantCreds, a.cachedCreds) } if !a.exp.Equal(test.wantExpiry) { t.Errorf("expected expiry %v got %v", test.wantExpiry, a.exp) } + if test.wantInput == "" { + if got := strings.TrimSpace(stderr.String()); got != "" { + t.Errorf("expected no input parameters, got %q", got) + } + return + } + compJSON(t, stderr.Bytes(), []byte(test.wantInput)) }) } @@ -342,8 +542,12 @@ func TestRoundTripper(t *testing.T) { a.now = now a.stderr = ioutil.Discard + tc := &transport.Config{} + if err := a.UpdateTransportConfig(tc); err != nil { + t.Fatal(err) + } client := http.Client{ - Transport: a.WrapTransport(http.DefaultTransport), + Transport: tc.WrapTransport(http.DefaultTransport), } get := func(t *testing.T, statusCode int) { @@ -411,3 +615,134 @@ func TestRoundTripper(t *testing.T) { // Old token is expired, should refresh automatically without hitting a 401. get(t, http.StatusOK) } + +func TestTLSCredentials(t *testing.T) { + now := time.Now() + + certPool := x509.NewCertPool() + cert, key := genClientCert(t) + if !certPool.AppendCertsFromPEM(cert) { + t.Fatal("failed to add client cert to CertPool") + } + + server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "ok") + })) + server.TLS = &tls.Config{ + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: certPool, + } + server.StartTLS() + defer server.Close() + + a, err := newAuthenticator(newCache(), &api.ExecConfig{ + Command: "./testdata/test-plugin.sh", + APIVersion: "client.authentication.k8s.io/v1alpha1", + }) + if err != nil { + t.Fatal(err) + } + var output *clientauthentication.ExecCredential + a.environ = func() []string { + data, err := runtime.Encode(codecs.LegacyCodec(a.group), output) + if err != nil { + t.Fatal(err) + } + return []string{"TEST_OUTPUT=" + string(data)} + } + a.now = func() time.Time { return now } + a.stderr = ioutil.Discard + + // We're not interested in server's cert, this test is about client cert. + tc := &transport.Config{TLS: transport.TLSConfig{Insecure: true}} + if err := a.UpdateTransportConfig(tc); err != nil { + t.Fatal(err) + } + + get := func(t *testing.T, desc string, wantErr bool) { + t.Run(desc, func(t *testing.T) { + tlsCfg, err := transport.TLSConfigFor(tc) + if err != nil { + t.Fatal("TLSConfigFor:", err) + } + client := http.Client{ + Transport: &http.Transport{TLSClientConfig: tlsCfg}, + } + resp, err := client.Get(server.URL) + switch { + case err != nil && !wantErr: + t.Errorf("got client.Get error: %q, want nil", err) + case err == nil && wantErr: + t.Error("got nil client.Get error, want non-nil") + } + if err == nil { + resp.Body.Close() + } + }) + } + + output = &clientauthentication.ExecCredential{ + Status: &clientauthentication.ExecCredentialStatus{ + ClientCertificateData: string(cert), + ClientKeyData: string(key), + ExpirationTimestamp: &v1.Time{now.Add(time.Hour)}, + }, + } + get(t, "valid TLS cert", false) + + // Advance time to force re-exec. + nCert, nKey := genClientCert(t) + now = now.Add(time.Hour * 2) + output = &clientauthentication.ExecCredential{ + Status: &clientauthentication.ExecCredentialStatus{ + ClientCertificateData: string(nCert), + ClientKeyData: string(nKey), + ExpirationTimestamp: &v1.Time{now.Add(time.Hour)}, + }, + } + get(t, "untrusted TLS cert", true) + + now = now.Add(time.Hour * 2) + output = &clientauthentication.ExecCredential{ + Status: &clientauthentication.ExecCredentialStatus{ + ClientCertificateData: string(cert), + ClientKeyData: string(key), + ExpirationTimestamp: &v1.Time{now.Add(time.Hour)}, + }, + } + get(t, "valid TLS cert again", false) +} + +// genClientCert generates an x509 certificate for testing. Certificate and key +// are returned in PEM encoding. +func genClientCert(t *testing.T) ([]byte, []byte) { + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + keyRaw, err := x509.MarshalECPrivateKey(key) + if err != nil { + t.Fatal(err) + } + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + t.Fatal(err) + } + cert := &x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{Organization: []string{"Acme Co"}}, + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + } + certRaw, err := x509.CreateCertificate(rand.Reader, cert, cert, key.Public(), key) + if err != nil { + t.Fatal(err) + } + return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certRaw}), + pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyRaw}) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh index 6b9bb100c..aa7daad5f 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/exec/testdata/test-plugin.sh @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/bash -e # Copyright 2018 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp/BUILD index e57e896ae..96c1b6cfa 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp/BUILD @@ -19,7 +19,6 @@ go_library( importpath = "k8s.io/client-go/plugin/pkg/client/auth/gcp", deps = [ "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/golang.org/x/oauth2:go_default_library", "//vendor/golang.org/x/oauth2/google:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp/gcp.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp/gcp.go index 3a4f86777..193d0c727 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp/gcp.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp/gcp.go @@ -18,6 +18,7 @@ package gcp import ( "bytes" + "context" "encoding/json" "fmt" "net/http" @@ -27,7 +28,6 @@ import ( "time" "github.com/golang/glog" - "golang.org/x/net/context" "golang.org/x/oauth2" "golang.org/x/oauth2/google" "k8s.io/apimachinery/pkg/util/net" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go index 1fe52c524..9c3ea0ab8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go @@ -279,7 +279,7 @@ func (p *oidcAuthProvider) idToken() (string, error) { // Persist new config and if successful, update the in memory config. if err = p.persister.Persist(newCfg); err != nil { - return "", fmt.Errorf("could not perist new tokens: %v", err) + return "", fmt.Errorf("could not persist new tokens: %v", err) } p.cfg = newCfg diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/BUILD index 750ffd6f5..0d7397583 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/BUILD @@ -18,6 +18,7 @@ go_library( importpath = "k8s.io/client-go/plugin/pkg/client/auth/openstack", deps = [ "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/gophercloud/gophercloud:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go index 490eff128..e6d7f0493 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack.go @@ -23,6 +23,7 @@ import ( "time" "github.com/golang/glog" + "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack" "k8s.io/apimachinery/pkg/util/net" @@ -42,8 +43,7 @@ const DefaultTTLDuration = 10 * time.Minute // the environment variables to determine the client identity, and generates a // token which will be inserted into the request header later. type openstackAuthProvider struct { - ttl time.Duration - + ttl time.Duration tokenGetter TokenGetter } @@ -52,13 +52,23 @@ type TokenGetter interface { Token() (string, error) } -type tokenGetter struct{} +type tokenGetter struct { + authOpt *gophercloud.AuthOptions +} // Token creates a token by authenticate with keystone. -func (*tokenGetter) Token() (string, error) { - options, err := openstack.AuthOptionsFromEnv() - if err != nil { - return "", fmt.Errorf("failed to read openstack env vars: %s", err) +func (t *tokenGetter) Token() (string, error) { + var options gophercloud.AuthOptions + var err error + if t.authOpt == nil { + // reads the config from the environment + glog.V(4).Info("reading openstack config from the environment variables") + options, err = openstack.AuthOptionsFromEnv() + if err != nil { + return "", fmt.Errorf("failed to read openstack env vars: %s", err) + } + } else { + options = *t.authOpt } client, err := openstack.AuthenticatedClient(options) if err != nil { @@ -85,7 +95,7 @@ func (c *cachedGetter) Token() (string, error) { var err error // no token or exceeds the TTL - if c.token == "" || time.Now().Sub(c.born) > c.ttl { + if c.token == "" || time.Since(c.born) > c.ttl { c.token, err = c.tokenGetter.Token() if err != nil { return "", fmt.Errorf("failed to get token: %s", err) @@ -126,10 +136,11 @@ func (t *tokenRoundTripper) WrappedRoundTripper() http.RoundTripper { return t.R // newOpenstackAuthProvider creates an auth provider which works with openstack // environment. -func newOpenstackAuthProvider(clusterAddress string, config map[string]string, persister restclient.AuthProviderConfigPersister) (restclient.AuthProvider, error) { +func newOpenstackAuthProvider(_ string, config map[string]string, persister restclient.AuthProviderConfigPersister) (restclient.AuthProvider, error) { var ttlDuration time.Duration var err error + glog.Warningf("WARNING: in-tree openstack auth plugin is now deprecated. please use the \"client-keystone-auth\" kubectl/client-go credential plugin instead") ttl, found := config["ttl"] if !found { ttlDuration = DefaultTTLDuration @@ -145,11 +156,27 @@ func newOpenstackAuthProvider(clusterAddress string, config map[string]string, p } } - // TODO: read/persist client configuration(OS_XXX env vars) in config + authOpt := gophercloud.AuthOptions{ + IdentityEndpoint: config["identityEndpoint"], + Username: config["username"], + Password: config["password"], + DomainName: config["name"], + TenantID: config["tenantId"], + TenantName: config["tenantName"], + } + + getter := tokenGetter{} + // not empty + if (authOpt != gophercloud.AuthOptions{}) { + if len(authOpt.IdentityEndpoint) == 0 { + return nil, fmt.Errorf("empty %q in the config for openstack auth provider", "identityEndpoint") + } + getter.authOpt = &authOpt + } return &openstackAuthProvider{ ttl: ttlDuration, - tokenGetter: &tokenGetter{}, + tokenGetter: &getter, }, nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack_test.go index 411bec70f..24d55b9fc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/plugin/pkg/client/auth/openstack/openstack_test.go @@ -114,3 +114,60 @@ func TestOpenstackAuthProvider(t *testing.T) { } } + +type fakePersister struct{} + +func (i *fakePersister) Persist(map[string]string) error { + return nil +} + +func TestNewOpenstackAuthProvider(t *testing.T) { + tests := []struct { + name string + config map[string]string + expectError bool + }{ + { + name: "normal config without openstack configurations", + config: map[string]string{ + "ttl": "1s", + "foo": "bar", + }, + }, + { + name: "openstack auth provider: missing identityEndpoint", + config: map[string]string{ + "ttl": "1s", + "foo": "bar", + "username": "xyz", + "password": "123", + "tenantName": "admin", + }, + expectError: true, + }, + { + name: "openstack auth provider", + config: map[string]string{ + "ttl": "1s", + "foo": "bar", + "identityEndpoint": "http://controller:35357/v3", + "username": "xyz", + "password": "123", + "tenantName": "admin", + }, + }, + } + + for _, test := range tests { + _, err := newOpenstackAuthProvider("test", test.config, &fakePersister{}) + if err != nil { + if !test.expectError { + t.Errorf("unexpected error: %v", err) + } + } else { + if test.expectError { + t.Error("expect error, but nil") + } + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/BUILD index 0cb24bcff..130ec31a3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/BUILD @@ -60,7 +60,6 @@ go_library( deps = [ "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/net/http2:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config.go index 72a78bc0a..7934a0196 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config.go @@ -17,6 +17,7 @@ limitations under the License. package rest import ( + "context" "fmt" "io/ioutil" "net" @@ -29,7 +30,6 @@ import ( "github.com/golang/glog" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -111,7 +111,7 @@ type Config struct { Timeout time.Duration // Dial specifies the dial function for creating unencrypted TCP connections. - Dial func(network, addr string) (net.Conn, error) + Dial func(ctx context.Context, network, address string) (net.Conn, error) // Version forces a specific version to be used (if registered) // Do we need this? @@ -316,12 +316,12 @@ func InClusterConfig() (*Config, error) { return nil, fmt.Errorf("unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined") } - token, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/" + v1.ServiceAccountTokenKey) + token, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token") if err != nil { return nil, err } tlsClientConfig := TLSClientConfig{} - rootCAFile := "/var/run/secrets/kubernetes.io/serviceaccount/" + v1.ServiceAccountRootCAKey + rootCAFile := "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" if _, err := certutil.NewPool(rootCAFile); err != nil { glog.Errorf("Expected to load root CA config from %s, but got err: %v", rootCAFile, err) } else { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config_test.go index a9495d792..347864285 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config_test.go @@ -17,6 +17,8 @@ limitations under the License. package rest import ( + "context" + "errors" "io" "net" "net/http" @@ -25,8 +27,6 @@ import ( "strings" "testing" - fuzz "github.com/google/gofuzz" - "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -35,8 +35,7 @@ import ( clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/util/flowcontrol" - "errors" - + fuzz "github.com/google/gofuzz" "github.com/stretchr/testify/assert" ) @@ -208,7 +207,7 @@ func (n *fakeNegotiatedSerializer) DecoderToVersion(serializer runtime.Decoder, return &fakeCodec{} } -var fakeDialFunc = func(network, addr string) (net.Conn, error) { +var fakeDialFunc = func(ctx context.Context, network, addr string) (net.Conn, error) { return nil, fakeDialerError } var fakeDialerError = errors.New("fakedialer") @@ -253,7 +252,7 @@ func TestAnonymousConfig(t *testing.T) { r.Config = map[string]string{} }, // Dial does not require fuzzer - func(r *func(network, addr string) (net.Conn, error), f fuzz.Continue) {}, + func(r *func(ctx context.Context, network, addr string) (net.Conn, error), f fuzz.Continue) {}, ) for i := 0; i < 20; i++ { original := &Config{} @@ -284,10 +283,10 @@ func TestAnonymousConfig(t *testing.T) { expected.WrapTransport = nil } if actual.Dial != nil { - _, actualError := actual.Dial("", "") - _, expectedError := actual.Dial("", "") + _, actualError := actual.Dial(context.Background(), "", "") + _, expectedError := expected.Dial(context.Background(), "", "") if !reflect.DeepEqual(expectedError, actualError) { - t.Fatalf("CopyConfig dropped the Dial field") + t.Fatalf("CopyConfig dropped the Dial field") } } else { actual.Dial = nil @@ -329,7 +328,7 @@ func TestCopyConfig(t *testing.T) { func(r *AuthProviderConfigPersister, f fuzz.Continue) { *r = fakeAuthProviderConfigPersister{} }, - func(r *func(network, addr string) (net.Conn, error), f fuzz.Continue) { + func(r *func(ctx context.Context, network, addr string) (net.Conn, error), f fuzz.Continue) { *r = fakeDialFunc }, ) @@ -351,8 +350,8 @@ func TestCopyConfig(t *testing.T) { expected.WrapTransport = nil } if actual.Dial != nil { - _, actualError := actual.Dial("", "") - _, expectedError := actual.Dial("", "") + _, actualError := actual.Dial(context.Background(), "", "") + _, expectedError := expected.Dial(context.Background(), "", "") if !reflect.DeepEqual(expectedError, actualError) { t.Fatalf("CopyConfig dropped the Dial field") } @@ -361,7 +360,7 @@ func TestCopyConfig(t *testing.T) { expected.Dial = nil if actual.AuthConfigPersister != nil { actualError := actual.AuthConfigPersister.Persist(nil) - expectedError := actual.AuthConfigPersister.Persist(nil) + expectedError := expected.AuthConfigPersister.Persist(nil) if !reflect.DeepEqual(expectedError, actualError) { t.Fatalf("CopyConfig dropped the Dial field") } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/request.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/request.go index 6ca9e0197..09ffd76dd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/request.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/request.go @@ -317,10 +317,14 @@ func (r *Request) Param(paramName, s string) *Request { // VersionedParams will not write query parameters that have omitempty set and are empty. If a // parameter has already been set it is appended to (Params and VersionedParams are additive). func (r *Request) VersionedParams(obj runtime.Object, codec runtime.ParameterCodec) *Request { + return r.SpecificallyVersionedParams(obj, codec, *r.content.GroupVersion) +} + +func (r *Request) SpecificallyVersionedParams(obj runtime.Object, codec runtime.ParameterCodec, version schema.GroupVersion) *Request { if r.err != nil { return r } - params, err := codec.EncodeParameters(obj, *r.content.GroupVersion) + params, err := codec.EncodeParameters(obj, version) if err != nil { r.err = err return r @@ -353,8 +357,8 @@ func (r *Request) SetHeader(key string, values ...string) *Request { return r } -// Timeout makes the request use the given duration as a timeout. Sets the "timeout" -// parameter. +// Timeout makes the request use the given duration as an overall timeout for the +// request. Additionally, if set passes the value as "timeout" parameter in URL. func (r *Request) Timeout(d time.Duration) *Request { if r.err != nil { return r @@ -485,6 +489,19 @@ func (r *Request) tryThrottle() { // Watch attempts to begin watching the requested location. // Returns a watch.Interface, or an error. func (r *Request) Watch() (watch.Interface, error) { + return r.WatchWithSpecificDecoders( + func(body io.ReadCloser) streaming.Decoder { + framer := r.serializers.Framer.NewFrameReader(body) + return streaming.NewDecoder(framer, r.serializers.StreamingSerializer) + }, + r.serializers.Decoder, + ) +} + +// WatchWithSpecificDecoders attempts to begin watching the requested location with a *different* decoder. +// Turns out that you want one "standard" decoder for the watch event and one "personal" decoder for the content +// Returns a watch.Interface, or an error. +func (r *Request) WatchWithSpecificDecoders(wrapperDecoderFn func(io.ReadCloser) streaming.Decoder, embeddedDecoder runtime.Decoder) (watch.Interface, error) { // We specifically don't want to rate limit watches, so we // don't use r.throttle here. if r.err != nil { @@ -532,9 +549,8 @@ func (r *Request) Watch() (watch.Interface, error) { } return nil, fmt.Errorf("for request '%+v', got status: %v", url, resp.StatusCode) } - framer := r.serializers.Framer.NewFrameReader(resp.Body) - decoder := streaming.NewDecoder(framer, r.serializers.StreamingSerializer) - return watch.NewStreamWatcher(restclientwatch.NewDecoder(decoder, r.serializers.Decoder)), nil + wrapperDecoder := wrapperDecoderFn(resp.Body) + return watch.NewStreamWatcher(restclientwatch.NewDecoder(wrapperDecoder, embeddedDecoder)), nil } // updateURLMetrics is a convenience function for pushing metrics. @@ -640,7 +656,6 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error { } // Right now we make about ten retry attempts if we get a Retry-After response. - // TODO: Change to a timeout based approach. maxRetries := 10 retries := 0 for { @@ -649,6 +664,14 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error { if err != nil { return err } + if r.timeout > 0 { + if r.ctx == nil { + r.ctx = context.Background() + } + var cancelFn context.CancelFunc + r.ctx, cancelFn = context.WithTimeout(r.ctx, r.timeout) + defer cancelFn() + } if r.ctx != nil { req = req.WithContext(r.ctx) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/request_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/request_test.go index fac690255..f75ee86cb 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/request_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/request_test.go @@ -1522,7 +1522,7 @@ func TestBody(t *testing.T) { f.Close() defer os.Remove(f.Name()) - var nilObject *v1.DeleteOptions + var nilObject *metav1.DeleteOptions typedObject := interface{}(nilObject) c := testRESTClient(t, nil) tests := []struct { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/transport.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/transport.go index b6a067632..25c1801b6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/transport.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/transport.go @@ -18,6 +18,7 @@ package rest import ( "crypto/tls" + "errors" "net/http" "k8s.io/client-go/plugin/pkg/client/auth/exec" @@ -59,39 +60,10 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip // TransportConfig converts a client config to an appropriate transport config. func (c *Config) TransportConfig() (*transport.Config, error) { - wt := c.WrapTransport - if c.ExecProvider != nil { - provider, err := exec.GetAuthenticator(c.ExecProvider) - if err != nil { - return nil, err - } - if wt != nil { - previousWT := wt - wt = func(rt http.RoundTripper) http.RoundTripper { - return provider.WrapTransport(previousWT(rt)) - } - } else { - wt = provider.WrapTransport - } - } - if c.AuthProvider != nil { - provider, err := GetAuthProvider(c.Host, c.AuthProvider, c.AuthConfigPersister) - if err != nil { - return nil, err - } - if wt != nil { - previousWT := wt - wt = func(rt http.RoundTripper) http.RoundTripper { - return provider.WrapTransport(previousWT(rt)) - } - } else { - wt = provider.WrapTransport - } - } - return &transport.Config{ + conf := &transport.Config{ UserAgent: c.UserAgent, Transport: c.Transport, - WrapTransport: wt, + WrapTransport: c.WrapTransport, TLS: transport.TLSConfig{ Insecure: c.Insecure, ServerName: c.ServerName, @@ -111,5 +83,34 @@ func (c *Config) TransportConfig() (*transport.Config, error) { Extra: c.Impersonate.Extra, }, Dial: c.Dial, - }, nil + } + + if c.ExecProvider != nil && c.AuthProvider != nil { + return nil, errors.New("execProvider and authProvider cannot be used in combination") + } + + if c.ExecProvider != nil { + provider, err := exec.GetAuthenticator(c.ExecProvider) + if err != nil { + return nil, err + } + if err := provider.UpdateTransportConfig(conf); err != nil { + return nil, err + } + } + if c.AuthProvider != nil { + provider, err := GetAuthProvider(c.Host, c.AuthProvider, c.AuthConfigPersister) + if err != nil { + return nil, err + } + wt := conf.WrapTransport + if wt != nil { + conf.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { + return provider.WrapTransport(wt(rt)) + } + } else { + conf.WrapTransport = provider.WrapTransport + } + } + return conf, nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/zz_generated.deepcopy.go index 67568bf0b..c1ab45f33 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/BUILD new file mode 100644 index 000000000..afd6762fd --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/BUILD @@ -0,0 +1,55 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "category_expansion.go", + "discovery.go", + "shortcut.go", + ], + importpath = "k8s.io/client-go/restmapper", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/discovery:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "category_expansion_test.go", + "discovery_test.go", + "shortcut_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", + "//vendor/k8s.io/client-go/discovery:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/rest/fake:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/category_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/category_expansion.go new file mode 100644 index 000000000..1620bbcf8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/category_expansion.go @@ -0,0 +1,119 @@ +/* +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 restmapper + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" +) + +// CategoryExpander maps category strings to GroupResouces. +// Categories are classification or 'tag' of a group of resources. +type CategoryExpander interface { + Expand(category string) ([]schema.GroupResource, bool) +} + +// SimpleCategoryExpander implements CategoryExpander interface +// using a static mapping of categories to GroupResource mapping. +type SimpleCategoryExpander struct { + Expansions map[string][]schema.GroupResource +} + +// Expand fulfills CategoryExpander +func (e SimpleCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) { + ret, ok := e.Expansions[category] + return ret, ok +} + +// discoveryCategoryExpander struct lets a REST Client wrapper (discoveryClient) to retrieve list of APIResourceList, +// and then convert to fallbackExpander +type discoveryCategoryExpander struct { + discoveryClient discovery.DiscoveryInterface +} + +// NewDiscoveryCategoryExpander returns a category expander that makes use of the "categories" fields from +// the API, found through the discovery client. In case of any error or no category found (which likely +// means we're at a cluster prior to categories support, fallback to the expander provided. +func NewDiscoveryCategoryExpander(client discovery.DiscoveryInterface) CategoryExpander { + if client == nil { + panic("Please provide discovery client to shortcut expander") + } + return discoveryCategoryExpander{discoveryClient: client} +} + +// Expand fulfills CategoryExpander +func (e discoveryCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) { + // Get all supported resources for groups and versions from server, if no resource found, fallback anyway. + apiResourceLists, _ := e.discoveryClient.ServerResources() + if len(apiResourceLists) == 0 { + return nil, false + } + + discoveredExpansions := map[string][]schema.GroupResource{} + for _, apiResourceList := range apiResourceLists { + gv, err := schema.ParseGroupVersion(apiResourceList.GroupVersion) + if err != nil { + continue + } + // Collect GroupVersions by categories + for _, apiResource := range apiResourceList.APIResources { + if categories := apiResource.Categories; len(categories) > 0 { + for _, category := range categories { + groupResource := schema.GroupResource{ + Group: gv.Group, + Resource: apiResource.Name, + } + discoveredExpansions[category] = append(discoveredExpansions[category], groupResource) + } + } + } + } + + ret, ok := discoveredExpansions[category] + return ret, ok +} + +// UnionCategoryExpander implements CategoryExpander interface. +// It maps given category string to union of expansions returned by all the CategoryExpanders in the list. +type UnionCategoryExpander []CategoryExpander + +// Expand fulfills CategoryExpander +func (u UnionCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) { + ret := []schema.GroupResource{} + ok := false + + // Expand the category for each CategoryExpander in the list and merge/combine the results. + for _, expansion := range u { + curr, currOk := expansion.Expand(category) + + for _, currGR := range curr { + found := false + for _, existing := range ret { + if existing == currGR { + found = true + break + } + } + if !found { + ret = append(ret, currGR) + } + } + ok = ok || currOk + } + + return ret, ok +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/category_expansion_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/category_expansion_test.go new file mode 100644 index 000000000..8537a6b49 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/category_expansion_test.go @@ -0,0 +1,145 @@ +/* +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 restmapper + +import ( + "reflect" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func TestCategoryExpansion(t *testing.T) { + tests := []struct { + name string + arg string + + expected []schema.GroupResource + expectedOk bool + }{ + { + name: "no-replacement", + arg: "service", + expected: nil, + }, + { + name: "all-replacement", + arg: "all", + expected: []schema.GroupResource{ + {Resource: "one"}, + {Resource: "two"}, + {Resource: "three", Group: "alpha"}, + {Resource: "four", Group: "bravo"}, + }, + expectedOk: true, + }, + } + + for _, test := range tests { + simpleCategoryExpander := SimpleCategoryExpander{ + Expansions: map[string][]schema.GroupResource{ + "all": { + {Group: "", Resource: "one"}, + {Group: "", Resource: "two"}, + {Group: "alpha", Resource: "three"}, + {Group: "bravo", Resource: "four"}, + }, + }, + } + + actual, actualOk := simpleCategoryExpander.Expand(test.arg) + if e, a := test.expected, actual; !reflect.DeepEqual(e, a) { + t.Errorf("%s: expected %s, got %s", test.name, e, a) + } + if e, a := test.expectedOk, actualOk; e != a { + t.Errorf("%s: expected %v, got %v", test.name, e, a) + } + } +} + +func TestDiscoveryCategoryExpander(t *testing.T) { + tests := []struct { + category string + serverResponse []*metav1.APIResourceList + expected []schema.GroupResource + }{ + { + category: "all", + serverResponse: []*metav1.APIResourceList{ + { + GroupVersion: "batch/v1", + APIResources: []metav1.APIResource{ + { + Name: "jobs", + ShortNames: []string{"jz"}, + Categories: []string{"all"}, + }, + }, + }, + }, + expected: []schema.GroupResource{ + { + Group: "batch", + Resource: "jobs", + }, + }, + }, + { + category: "all", + serverResponse: []*metav1.APIResourceList{ + { + GroupVersion: "batch/v1", + APIResources: []metav1.APIResource{ + { + Name: "jobs", + ShortNames: []string{"jz"}, + }, + }, + }, + }, + }, + { + category: "targaryens", + serverResponse: []*metav1.APIResourceList{ + { + GroupVersion: "batch/v1", + APIResources: []metav1.APIResource{ + { + Name: "jobs", + ShortNames: []string{"jz"}, + Categories: []string{"all"}, + }, + }, + }, + }, + }, + } + + dc := &fakeDiscoveryClient{} + for _, test := range tests { + dc.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { + return test.serverResponse, nil + } + expander := NewDiscoveryCategoryExpander(dc) + expanded, _ := expander.Expand(test.category) + if !reflect.DeepEqual(expanded, test.expected) { + t.Errorf("expected %v, got %v", test.expected, expanded) + } + } + +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/discovery.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/discovery.go new file mode 100644 index 000000000..aa158626a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/discovery.go @@ -0,0 +1,339 @@ +/* +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 restmapper + +import ( + "fmt" + "strings" + "sync" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" + + "github.com/golang/glog" +) + +// APIGroupResources is an API group with a mapping of versions to +// resources. +type APIGroupResources struct { + Group metav1.APIGroup + // A mapping of version string to a slice of APIResources for + // that version. + VersionedResources map[string][]metav1.APIResource +} + +// NewDiscoveryRESTMapper returns a PriorityRESTMapper based on the discovered +// groups and resources passed in. +func NewDiscoveryRESTMapper(groupResources []*APIGroupResources) meta.RESTMapper { + unionMapper := meta.MultiRESTMapper{} + + var groupPriority []string + // /v1 is special. It should always come first + resourcePriority := []schema.GroupVersionResource{{Group: "", Version: "v1", Resource: meta.AnyResource}} + kindPriority := []schema.GroupVersionKind{{Group: "", Version: "v1", Kind: meta.AnyKind}} + + for _, group := range groupResources { + groupPriority = append(groupPriority, group.Group.Name) + + // Make sure the preferred version comes first + if len(group.Group.PreferredVersion.Version) != 0 { + preferred := group.Group.PreferredVersion.Version + if _, ok := group.VersionedResources[preferred]; ok { + resourcePriority = append(resourcePriority, schema.GroupVersionResource{ + Group: group.Group.Name, + Version: group.Group.PreferredVersion.Version, + Resource: meta.AnyResource, + }) + + kindPriority = append(kindPriority, schema.GroupVersionKind{ + Group: group.Group.Name, + Version: group.Group.PreferredVersion.Version, + Kind: meta.AnyKind, + }) + } + } + + for _, discoveryVersion := range group.Group.Versions { + resources, ok := group.VersionedResources[discoveryVersion.Version] + if !ok { + continue + } + + // Add non-preferred versions after the preferred version, in case there are resources that only exist in those versions + if discoveryVersion.Version != group.Group.PreferredVersion.Version { + resourcePriority = append(resourcePriority, schema.GroupVersionResource{ + Group: group.Group.Name, + Version: discoveryVersion.Version, + Resource: meta.AnyResource, + }) + + kindPriority = append(kindPriority, schema.GroupVersionKind{ + Group: group.Group.Name, + Version: discoveryVersion.Version, + Kind: meta.AnyKind, + }) + } + + gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version} + versionMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{gv}) + + for _, resource := range resources { + scope := meta.RESTScopeNamespace + if !resource.Namespaced { + scope = meta.RESTScopeRoot + } + + // if we have a slash, then this is a subresource and we shouldn't create mappings for those. + if strings.Contains(resource.Name, "/") { + continue + } + + plural := gv.WithResource(resource.Name) + singular := gv.WithResource(resource.SingularName) + // this is for legacy resources and servers which don't list singular forms. For those we must still guess. + if len(resource.SingularName) == 0 { + _, singular = meta.UnsafeGuessKindToResource(gv.WithKind(resource.Kind)) + } + + versionMapper.AddSpecific(gv.WithKind(strings.ToLower(resource.Kind)), plural, singular, scope) + versionMapper.AddSpecific(gv.WithKind(resource.Kind), plural, singular, scope) + // TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior + versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope) + } + // TODO why is this type not in discovery (at least for "v1") + versionMapper.Add(gv.WithKind("List"), meta.RESTScopeRoot) + unionMapper = append(unionMapper, versionMapper) + } + } + + for _, group := range groupPriority { + resourcePriority = append(resourcePriority, schema.GroupVersionResource{ + Group: group, + Version: meta.AnyVersion, + Resource: meta.AnyResource, + }) + kindPriority = append(kindPriority, schema.GroupVersionKind{ + Group: group, + Version: meta.AnyVersion, + Kind: meta.AnyKind, + }) + } + + return meta.PriorityRESTMapper{ + Delegate: unionMapper, + ResourcePriority: resourcePriority, + KindPriority: kindPriority, + } +} + +// GetAPIGroupResources uses the provided discovery client to gather +// discovery information and populate a slice of APIGroupResources. +func GetAPIGroupResources(cl discovery.DiscoveryInterface) ([]*APIGroupResources, error) { + apiGroups, err := cl.ServerGroups() + if err != nil { + if apiGroups == nil || len(apiGroups.Groups) == 0 { + return nil, err + } + // TODO track the errors and update callers to handle partial errors. + } + var result []*APIGroupResources + for _, group := range apiGroups.Groups { + groupResources := &APIGroupResources{ + Group: group, + VersionedResources: make(map[string][]metav1.APIResource), + } + for _, version := range group.Versions { + resources, err := cl.ServerResourcesForGroupVersion(version.GroupVersion) + if err != nil { + // continue as best we can + // TODO track the errors and update callers to handle partial errors. + if resources == nil || len(resources.APIResources) == 0 { + continue + } + } + groupResources.VersionedResources[version.Version] = resources.APIResources + } + result = append(result, groupResources) + } + return result, nil +} + +// DeferredDiscoveryRESTMapper is a RESTMapper that will defer +// initialization of the RESTMapper until the first mapping is +// requested. +type DeferredDiscoveryRESTMapper struct { + initMu sync.Mutex + delegate meta.RESTMapper + cl discovery.CachedDiscoveryInterface +} + +// NewDeferredDiscoveryRESTMapper returns a +// DeferredDiscoveryRESTMapper that will lazily query the provided +// client for discovery information to do REST mappings. +func NewDeferredDiscoveryRESTMapper(cl discovery.CachedDiscoveryInterface) *DeferredDiscoveryRESTMapper { + return &DeferredDiscoveryRESTMapper{ + cl: cl, + } +} + +func (d *DeferredDiscoveryRESTMapper) getDelegate() (meta.RESTMapper, error) { + d.initMu.Lock() + defer d.initMu.Unlock() + + if d.delegate != nil { + return d.delegate, nil + } + + groupResources, err := GetAPIGroupResources(d.cl) + if err != nil { + return nil, err + } + + d.delegate = NewDiscoveryRESTMapper(groupResources) + return d.delegate, err +} + +// Reset resets the internally cached Discovery information and will +// cause the next mapping request to re-discover. +func (d *DeferredDiscoveryRESTMapper) Reset() { + glog.V(5).Info("Invalidating discovery information") + + d.initMu.Lock() + defer d.initMu.Unlock() + + d.cl.Invalidate() + d.delegate = nil +} + +// KindFor takes a partial resource and returns back the single match. +// It returns an error if there are multiple matches. +func (d *DeferredDiscoveryRESTMapper) KindFor(resource schema.GroupVersionResource) (gvk schema.GroupVersionKind, err error) { + del, err := d.getDelegate() + if err != nil { + return schema.GroupVersionKind{}, err + } + gvk, err = del.KindFor(resource) + if err != nil && !d.cl.Fresh() { + d.Reset() + gvk, err = d.KindFor(resource) + } + return +} + +// KindsFor takes a partial resource and returns back the list of +// potential kinds in priority order. +func (d *DeferredDiscoveryRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvks []schema.GroupVersionKind, err error) { + del, err := d.getDelegate() + if err != nil { + return nil, err + } + gvks, err = del.KindsFor(resource) + if len(gvks) == 0 && !d.cl.Fresh() { + d.Reset() + gvks, err = d.KindsFor(resource) + } + return +} + +// ResourceFor takes a partial resource and returns back the single +// match. It returns an error if there are multiple matches. +func (d *DeferredDiscoveryRESTMapper) ResourceFor(input schema.GroupVersionResource) (gvr schema.GroupVersionResource, err error) { + del, err := d.getDelegate() + if err != nil { + return schema.GroupVersionResource{}, err + } + gvr, err = del.ResourceFor(input) + if err != nil && !d.cl.Fresh() { + d.Reset() + gvr, err = d.ResourceFor(input) + } + return +} + +// ResourcesFor takes a partial resource and returns back the list of +// potential resource in priority order. +func (d *DeferredDiscoveryRESTMapper) ResourcesFor(input schema.GroupVersionResource) (gvrs []schema.GroupVersionResource, err error) { + del, err := d.getDelegate() + if err != nil { + return nil, err + } + gvrs, err = del.ResourcesFor(input) + if len(gvrs) == 0 && !d.cl.Fresh() { + d.Reset() + gvrs, err = d.ResourcesFor(input) + } + return +} + +// RESTMapping identifies a preferred resource mapping for the +// provided group kind. +func (d *DeferredDiscoveryRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (m *meta.RESTMapping, err error) { + del, err := d.getDelegate() + if err != nil { + return nil, err + } + m, err = del.RESTMapping(gk, versions...) + if err != nil && !d.cl.Fresh() { + d.Reset() + m, err = d.RESTMapping(gk, versions...) + } + return +} + +// RESTMappings returns the RESTMappings for the provided group kind +// in a rough internal preferred order. If no kind is found, it will +// return a NoResourceMatchError. +func (d *DeferredDiscoveryRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (ms []*meta.RESTMapping, err error) { + del, err := d.getDelegate() + if err != nil { + return nil, err + } + ms, err = del.RESTMappings(gk, versions...) + if len(ms) == 0 && !d.cl.Fresh() { + d.Reset() + ms, err = d.RESTMappings(gk, versions...) + } + return +} + +// ResourceSingularizer converts a resource name from plural to +// singular (e.g., from pods to pod). +func (d *DeferredDiscoveryRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { + del, err := d.getDelegate() + if err != nil { + return resource, err + } + singular, err = del.ResourceSingularizer(resource) + if err != nil && !d.cl.Fresh() { + d.Reset() + singular, err = d.ResourceSingularizer(resource) + } + return +} + +func (d *DeferredDiscoveryRESTMapper) String() string { + del, err := d.getDelegate() + if err != nil { + return fmt.Sprintf("DeferredDiscoveryRESTMapper{%v}", err) + } + return fmt.Sprintf("DeferredDiscoveryRESTMapper{\n\t%v\n}", del) +} + +// Make sure it satisfies the interface +var _ meta.RESTMapper = &DeferredDiscoveryRESTMapper{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/discovery_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/discovery_test.go new file mode 100644 index 000000000..1b8e7c4f0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/discovery_test.go @@ -0,0 +1,384 @@ +/* +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 restmapper + +import ( + "reflect" + "testing" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/version" + . "k8s.io/client-go/discovery" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" + + "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/stretchr/testify/assert" +) + +func TestRESTMapper(t *testing.T) { + resources := []*APIGroupResources{ + { + Group: metav1.APIGroup{ + Name: "extensions", + Versions: []metav1.GroupVersionForDiscovery{ + {Version: "v1beta"}, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1beta"}, + }, + VersionedResources: map[string][]metav1.APIResource{ + "v1beta": { + {Name: "jobs", Namespaced: true, Kind: "Job"}, + {Name: "pods", Namespaced: true, Kind: "Pod"}, + }, + }, + }, + { + Group: metav1.APIGroup{ + Versions: []metav1.GroupVersionForDiscovery{ + {Version: "v1"}, + {Version: "v2"}, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1"}, + }, + VersionedResources: map[string][]metav1.APIResource{ + "v1": { + {Name: "pods", Namespaced: true, Kind: "Pod"}, + }, + "v2": { + {Name: "pods", Namespaced: true, Kind: "Pod"}, + }, + }, + }, + + // This group tests finding and prioritizing resources that only exist in non-preferred versions + { + Group: metav1.APIGroup{ + Name: "unpreferred", + Versions: []metav1.GroupVersionForDiscovery{ + {Version: "v1"}, + {Version: "v2beta1"}, + {Version: "v2alpha1"}, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1"}, + }, + VersionedResources: map[string][]metav1.APIResource{ + "v1": { + {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, + }, + "v2beta1": { + {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, + {Name: "peas", Namespaced: true, Kind: "Pea"}, + }, + "v2alpha1": { + {Name: "broccoli", Namespaced: true, Kind: "Broccoli"}, + {Name: "peas", Namespaced: true, Kind: "Pea"}, + }, + }, + }, + } + + restMapper := NewDiscoveryRESTMapper(resources) + + kindTCs := []struct { + input schema.GroupVersionResource + want schema.GroupVersionKind + }{ + { + input: schema.GroupVersionResource{ + Resource: "pods", + }, + want: schema.GroupVersionKind{ + Version: "v1", + Kind: "Pod", + }, + }, + { + input: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + want: schema.GroupVersionKind{ + Version: "v1", + Kind: "Pod", + }, + }, + { + input: schema.GroupVersionResource{ + Version: "v2", + Resource: "pods", + }, + want: schema.GroupVersionKind{ + Version: "v2", + Kind: "Pod", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "pods", + }, + want: schema.GroupVersionKind{ + Version: "v1", + Kind: "Pod", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "jobs", + }, + want: schema.GroupVersionKind{ + Group: "extensions", + Version: "v1beta", + Kind: "Job", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "peas", + }, + want: schema.GroupVersionKind{ + Group: "unpreferred", + Version: "v2beta1", + Kind: "Pea", + }, + }, + } + + for _, tc := range kindTCs { + got, err := restMapper.KindFor(tc.input) + if err != nil { + t.Errorf("KindFor(%#v) unexpected error: %v", tc.input, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("KindFor(%#v) = %#v, want %#v", tc.input, got, tc.want) + } + } + + resourceTCs := []struct { + input schema.GroupVersionResource + want schema.GroupVersionResource + }{ + { + input: schema.GroupVersionResource{ + Resource: "pods", + }, + want: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + { + input: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + want: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + { + input: schema.GroupVersionResource{ + Version: "v2", + Resource: "pods", + }, + want: schema.GroupVersionResource{ + Version: "v2", + Resource: "pods", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "pods", + }, + want: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + { + input: schema.GroupVersionResource{ + Resource: "jobs", + }, + want: schema.GroupVersionResource{ + Group: "extensions", + Version: "v1beta", + Resource: "jobs", + }, + }, + } + + for _, tc := range resourceTCs { + got, err := restMapper.ResourceFor(tc.input) + if err != nil { + t.Errorf("ResourceFor(%#v) unexpected error: %v", tc.input, err) + continue + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("ResourceFor(%#v) = %#v, want %#v", tc.input, got, tc.want) + } + } +} + +func TestDeferredDiscoveryRESTMapper_CacheMiss(t *testing.T) { + assert := assert.New(t) + + cdc := fakeCachedDiscoveryInterface{fresh: false} + m := NewDeferredDiscoveryRESTMapper(&cdc) + assert.False(cdc.fresh, "should NOT be fresh after instantiation") + assert.Zero(cdc.invalidateCalls, "should not have called Invalidate()") + + gvk, err := m.KindFor(schema.GroupVersionResource{ + Group: "a", + Version: "v1", + Resource: "foo", + }) + assert.NoError(err) + assert.True(cdc.fresh, "should be fresh after a cache-miss") + assert.Equal(cdc.invalidateCalls, 1, "should have called Invalidate() once") + assert.Equal(gvk.Kind, "Foo") + + gvk, err = m.KindFor(schema.GroupVersionResource{ + Group: "a", + Version: "v1", + Resource: "foo", + }) + assert.NoError(err) + assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again") + + gvk, err = m.KindFor(schema.GroupVersionResource{ + Group: "a", + Version: "v1", + Resource: "bar", + }) + assert.Error(err) + assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again after another cache-miss, but with fresh==true") + + cdc.fresh = false + gvk, err = m.KindFor(schema.GroupVersionResource{ + Group: "a", + Version: "v1", + Resource: "bar", + }) + assert.Error(err) + assert.Equal(cdc.invalidateCalls, 2, "should HAVE called Invalidate() again after another cache-miss, but with fresh==false") +} + +type fakeCachedDiscoveryInterface struct { + invalidateCalls int + fresh bool + enabledA bool +} + +var _ CachedDiscoveryInterface = &fakeCachedDiscoveryInterface{} + +func (c *fakeCachedDiscoveryInterface) Fresh() bool { + return c.fresh +} + +func (c *fakeCachedDiscoveryInterface) Invalidate() { + c.invalidateCalls = c.invalidateCalls + 1 + c.fresh = true + c.enabledA = true +} + +func (c *fakeCachedDiscoveryInterface) RESTClient() restclient.Interface { + return &fake.RESTClient{} +} + +func (c *fakeCachedDiscoveryInterface) ServerGroups() (*metav1.APIGroupList, error) { + if c.enabledA { + return &metav1.APIGroupList{ + Groups: []metav1.APIGroup{ + { + Name: "a", + Versions: []metav1.GroupVersionForDiscovery{ + { + GroupVersion: "a/v1", + Version: "v1", + }, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "a/v1", + Version: "v1", + }, + }, + }, + }, nil + } + return &metav1.APIGroupList{}, nil +} + +func (c *fakeCachedDiscoveryInterface) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + if c.enabledA && groupVersion == "a/v1" { + return &metav1.APIResourceList{ + GroupVersion: "a/v1", + APIResources: []metav1.APIResource{ + { + Name: "foo", + Kind: "Foo", + Namespaced: false, + }, + }, + }, nil + } + + return nil, errors.NewNotFound(schema.GroupResource{}, "") +} + +func (c *fakeCachedDiscoveryInterface) ServerResources() ([]*metav1.APIResourceList, error) { + if c.enabledA { + av1, _ := c.ServerResourcesForGroupVersion("a/v1") + return []*metav1.APIResourceList{av1}, nil + } + return []*metav1.APIResourceList{}, nil +} + +func (c *fakeCachedDiscoveryInterface) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + if c.enabledA { + return []*metav1.APIResourceList{ + { + GroupVersion: "a/v1", + APIResources: []metav1.APIResource{ + { + Name: "foo", + Kind: "Foo", + Verbs: []string{}, + }, + }, + }, + }, nil + } + return nil, nil +} + +func (c *fakeCachedDiscoveryInterface) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return nil, nil +} + +func (c *fakeCachedDiscoveryInterface) ServerVersion() (*version.Info, error) { + return &version.Info{}, nil +} + +func (c *fakeCachedDiscoveryInterface) OpenAPISchema() (*openapi_v2.Document, error) { + return &openapi_v2.Document{}, nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/shortcut.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/shortcut.go new file mode 100644 index 000000000..d9f4be0b6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/shortcut.go @@ -0,0 +1,172 @@ +/* +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 restmapper + +import ( + "strings" + + "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" +) + +// shortcutExpander is a RESTMapper that can be used for Kubernetes resources. It expands the resource first, then invokes the wrapped +type shortcutExpander struct { + RESTMapper meta.RESTMapper + + discoveryClient discovery.DiscoveryInterface +} + +var _ meta.RESTMapper = &shortcutExpander{} + +// NewShortcutExpander wraps a restmapper in a layer that expands shortcuts found via discovery +func NewShortcutExpander(delegate meta.RESTMapper, client discovery.DiscoveryInterface) meta.RESTMapper { + return shortcutExpander{RESTMapper: delegate, discoveryClient: client} +} + +// KindFor fulfills meta.RESTMapper +func (e shortcutExpander) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { + return e.RESTMapper.KindFor(e.expandResourceShortcut(resource)) +} + +// KindsFor fulfills meta.RESTMapper +func (e shortcutExpander) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { + return e.RESTMapper.KindsFor(e.expandResourceShortcut(resource)) +} + +// ResourcesFor fulfills meta.RESTMapper +func (e shortcutExpander) ResourcesFor(resource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { + return e.RESTMapper.ResourcesFor(e.expandResourceShortcut(resource)) +} + +// ResourceFor fulfills meta.RESTMapper +func (e shortcutExpander) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) { + return e.RESTMapper.ResourceFor(e.expandResourceShortcut(resource)) +} + +// ResourceSingularizer fulfills meta.RESTMapper +func (e shortcutExpander) ResourceSingularizer(resource string) (string, error) { + return e.RESTMapper.ResourceSingularizer(e.expandResourceShortcut(schema.GroupVersionResource{Resource: resource}).Resource) +} + +// RESTMapping fulfills meta.RESTMapper +func (e shortcutExpander) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { + return e.RESTMapper.RESTMapping(gk, versions...) +} + +// RESTMappings fulfills meta.RESTMapper +func (e shortcutExpander) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) { + return e.RESTMapper.RESTMappings(gk, versions...) +} + +// getShortcutMappings returns a set of tuples which holds short names for resources. +// First the list of potential resources will be taken from the API server. +// Next we will append the hardcoded list of resources - to be backward compatible with old servers. +// NOTE that the list is ordered by group priority. +func (e shortcutExpander) getShortcutMappings() ([]*metav1.APIResourceList, []resourceShortcuts, error) { + res := []resourceShortcuts{} + // get server resources + // This can return an error *and* the results it was able to find. We don't need to fail on the error. + apiResList, err := e.discoveryClient.ServerResources() + if err != nil { + glog.V(1).Infof("Error loading discovery information: %v", err) + } + for _, apiResources := range apiResList { + gv, err := schema.ParseGroupVersion(apiResources.GroupVersion) + if err != nil { + glog.V(1).Infof("Unable to parse groupversion = %s due to = %s", apiResources.GroupVersion, err.Error()) + continue + } + for _, apiRes := range apiResources.APIResources { + for _, shortName := range apiRes.ShortNames { + rs := resourceShortcuts{ + ShortForm: schema.GroupResource{Group: gv.Group, Resource: shortName}, + LongForm: schema.GroupResource{Group: gv.Group, Resource: apiRes.Name}, + } + res = append(res, rs) + } + } + } + + return apiResList, res, nil +} + +// expandResourceShortcut will return the expanded version of resource +// (something that a pkg/api/meta.RESTMapper can understand), if it is +// indeed a shortcut. If no match has been found, we will match on group prefixing. +// Lastly we will return resource unmodified. +func (e shortcutExpander) expandResourceShortcut(resource schema.GroupVersionResource) schema.GroupVersionResource { + // get the shortcut mappings and return on first match. + if allResources, shortcutResources, err := e.getShortcutMappings(); err == nil { + // avoid expanding if there's an exact match to a full resource name + for _, apiResources := range allResources { + gv, err := schema.ParseGroupVersion(apiResources.GroupVersion) + if err != nil { + continue + } + if len(resource.Group) != 0 && resource.Group != gv.Group { + continue + } + for _, apiRes := range apiResources.APIResources { + if resource.Resource == apiRes.Name { + return resource + } + if resource.Resource == apiRes.SingularName { + return resource + } + } + } + + for _, item := range shortcutResources { + if len(resource.Group) != 0 && resource.Group != item.ShortForm.Group { + continue + } + if resource.Resource == item.ShortForm.Resource { + resource.Resource = item.LongForm.Resource + resource.Group = item.LongForm.Group + return resource + } + } + + // we didn't find exact match so match on group prefixing. This allows autoscal to match autoscaling + if len(resource.Group) == 0 { + return resource + } + for _, item := range shortcutResources { + if !strings.HasPrefix(item.ShortForm.Group, resource.Group) { + continue + } + if resource.Resource == item.ShortForm.Resource { + resource.Resource = item.LongForm.Resource + resource.Group = item.LongForm.Group + return resource + } + } + } + + return resource +} + +// ResourceShortcuts represents a structure that holds the information how to +// transition from resource's shortcut to its full name. +type resourceShortcuts struct { + ShortForm schema.GroupResource + LongForm schema.GroupResource +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/shortcut_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/shortcut_test.go new file mode 100644 index 000000000..dbc288fad --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/restmapper/shortcut_test.go @@ -0,0 +1,289 @@ +/* +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 restmapper + +import ( + "testing" + + "github.com/googleapis/gnostic/OpenAPIv2" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/version" + "k8s.io/client-go/discovery" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/rest/fake" +) + +func TestReplaceAliases(t *testing.T) { + tests := []struct { + name string + arg string + expected schema.GroupVersionResource + srvRes []*metav1.APIResourceList + }{ + { + name: "storageclasses-no-replacement", + arg: "storageclasses", + expected: schema.GroupVersionResource{Resource: "storageclasses"}, + srvRes: []*metav1.APIResourceList{}, + }, + { + name: "hpa-priority", + arg: "hpa", + expected: schema.GroupVersionResource{Resource: "superhorizontalpodautoscalers", Group: "autoscaling"}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "autoscaling/v1", + APIResources: []metav1.APIResource{ + { + Name: "superhorizontalpodautoscalers", + ShortNames: []string{"hpa"}, + }, + }, + }, + { + GroupVersion: "autoscaling/v1", + APIResources: []metav1.APIResource{ + { + Name: "horizontalpodautoscalers", + ShortNames: []string{"hpa"}, + }, + }, + }, + }, + }, + { + name: "resource-override", + arg: "dpl", + expected: schema.GroupVersionResource{Resource: "deployments", Group: "foo"}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "foo/v1", + APIResources: []metav1.APIResource{ + { + Name: "deployments", + ShortNames: []string{"dpl"}, + }, + }, + }, + { + GroupVersion: "extension/v1beta1", + APIResources: []metav1.APIResource{ + { + Name: "deployments", + ShortNames: []string{"deploy"}, + }, + }, + }, + }, + }, + { + name: "resource-match-preferred", + arg: "pods", + expected: schema.GroupVersionResource{Resource: "pods", Group: ""}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "v1", + APIResources: []metav1.APIResource{{Name: "pods", SingularName: "pod"}}, + }, + { + GroupVersion: "acme.com/v1", + APIResources: []metav1.APIResource{{Name: "poddlers", ShortNames: []string{"pods", "pod"}}}, + }, + }, + }, + { + name: "resource-match-singular-preferred", + arg: "pod", + expected: schema.GroupVersionResource{Resource: "pod", Group: ""}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "v1", + APIResources: []metav1.APIResource{{Name: "pods", SingularName: "pod"}}, + }, + { + GroupVersion: "acme.com/v1", + APIResources: []metav1.APIResource{{Name: "poddlers", ShortNames: []string{"pods", "pod"}}}, + }, + }, + }, + } + + for _, test := range tests { + ds := &fakeDiscoveryClient{} + ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { + return test.srvRes, nil + } + mapper := NewShortcutExpander(&fakeRESTMapper{}, ds).(shortcutExpander) + + actual := mapper.expandResourceShortcut(schema.GroupVersionResource{Resource: test.arg}) + if actual != test.expected { + t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, actual) + } + } +} + +func TestKindFor(t *testing.T) { + tests := []struct { + in schema.GroupVersionResource + expected schema.GroupVersionResource + srvRes []*metav1.APIResourceList + }{ + { + in: schema.GroupVersionResource{Group: "storage.k8s.io", Version: "", Resource: "sc"}, + expected: schema.GroupVersionResource{Group: "storage.k8s.io", Version: "", Resource: "storageclasses"}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "storage.k8s.io/v1", + APIResources: []metav1.APIResource{ + { + Name: "storageclasses", + ShortNames: []string{"sc"}, + }, + }, + }, + }, + }, + { + in: schema.GroupVersionResource{Group: "", Version: "", Resource: "sc"}, + expected: schema.GroupVersionResource{Group: "storage.k8s.io", Version: "", Resource: "storageclasses"}, + srvRes: []*metav1.APIResourceList{ + { + GroupVersion: "storage.k8s.io/v1", + APIResources: []metav1.APIResource{ + { + Name: "storageclasses", + ShortNames: []string{"sc"}, + }, + }, + }, + }, + }, + } + + for i, test := range tests { + ds := &fakeDiscoveryClient{} + ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { + return test.srvRes, nil + } + + delegate := &fakeRESTMapper{} + mapper := NewShortcutExpander(delegate, ds) + + mapper.KindFor(test.in) + if delegate.kindForInput != test.expected { + t.Errorf("%d: unexpected data returned %#v, expected %#v", i, delegate.kindForInput, test.expected) + } + } +} + +type fakeRESTMapper struct { + kindForInput schema.GroupVersionResource +} + +func (f *fakeRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { + f.kindForInput = resource + return schema.GroupVersionKind{}, nil +} + +func (f *fakeRESTMapper) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { + return nil, nil +} + +func (f *fakeRESTMapper) ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) { + return schema.GroupVersionResource{}, nil +} + +func (f *fakeRESTMapper) ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { + return nil, nil +} + +func (f *fakeRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { + return nil, nil +} + +func (f *fakeRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) { + return nil, nil +} + +func (f *fakeRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { + return "", nil +} + +type fakeDiscoveryClient struct { + serverResourcesHandler func() ([]*metav1.APIResourceList, error) +} + +var _ discovery.DiscoveryInterface = &fakeDiscoveryClient{} + +func (c *fakeDiscoveryClient) RESTClient() restclient.Interface { + return &fake.RESTClient{} +} + +func (c *fakeDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { + return &metav1.APIGroupList{ + Groups: []metav1.APIGroup{ + { + Name: "a", + Versions: []metav1.GroupVersionForDiscovery{ + { + GroupVersion: "a/v1", + Version: "v1", + }, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "a/v1", + Version: "v1", + }, + }, + }, + }, nil +} + +func (c *fakeDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + if groupVersion == "a/v1" { + return &metav1.APIResourceList{APIResources: []metav1.APIResource{{Name: "widgets", Kind: "Widget"}}}, nil + } + + return nil, errors.NewNotFound(schema.GroupResource{}, "") +} + +func (c *fakeDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { + if c.serverResourcesHandler != nil { + return c.serverResourcesHandler() + } + return []*metav1.APIResourceList{}, nil +} + +func (c *fakeDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + return nil, nil +} + +func (c *fakeDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return nil, nil +} + +func (c *fakeDiscoveryClient) ServerVersion() (*version.Info, error) { + return &version.Info{}, nil +} + +func (c *fakeDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { + return &openapi_v2.Document{}, nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/BUILD index b82984243..fea5cedc7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/BUILD @@ -43,16 +43,15 @@ go_test( "//vendor/k8s.io/api/autoscaling/v1: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/meta: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/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/discovery/fake:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/rest/fake:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/client.go index 782aca394..3a3e8fc9e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/client.go @@ -20,7 +20,6 @@ import ( "fmt" autoscaling "k8s.io/api/autoscaling/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" @@ -41,7 +40,7 @@ type restInterfaceProvider func(*restclient.Config) (restclient.Interface, error // It behaves somewhat similarly to the dynamic ClientPool, // but is more specifically scoped to Scale. type scaleClient struct { - mapper meta.RESTMapper + mapper PreferredResourceMapper apiPathResolverFunc dynamic.APIPathResolverFunc scaleKindResolver ScaleKindResolver @@ -51,7 +50,7 @@ type scaleClient struct { // NewForConfig creates a new ScalesGetter which resolves kinds // to resources using the given RESTMapper, and API paths using // the given dynamic.APIPathResolverFunc. -func NewForConfig(cfg *restclient.Config, mapper meta.RESTMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) (ScalesGetter, error) { +func NewForConfig(cfg *restclient.Config, mapper PreferredResourceMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) (ScalesGetter, error) { // so that the RESTClientFor doesn't complain cfg.GroupVersion = &schema.GroupVersion{} @@ -72,7 +71,7 @@ func NewForConfig(cfg *restclient.Config, mapper meta.RESTMapper, resolver dynam // New creates a new ScalesGetter using the given client to make requests. // The GroupVersion on the client is ignored. -func New(baseClient restclient.Interface, mapper meta.RESTMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) ScalesGetter { +func New(baseClient restclient.Interface, mapper PreferredResourceMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) ScalesGetter { return &scaleClient{ mapper: mapper, @@ -138,7 +137,7 @@ func (c *namespacedScaleClient) Get(resource schema.GroupResource, name string) SubResource("scale"). Do() if err := result.Error(); err != nil { - return nil, fmt.Errorf("could not fetch the scale for %s %s: %v", resource.String(), name, err) + return nil, err } scaleBytes, err := result.Raw() @@ -196,7 +195,10 @@ func (c *namespacedScaleClient) Update(resource schema.GroupResource, scale *aut Body(scaleUpdateBytes). Do() if err := result.Error(); err != nil { - return nil, fmt.Errorf("could not update the scale for %s %s: %v", resource.String(), scale.Name, err) + // propagate "raw" error from the API + // this allows callers to interpret underlying Reason field + // for example: errors.IsConflict(err) + return nil, err } scaleBytes, err := result.Raw() diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/client_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/client_test.go index 6301320f3..a3a8c037d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/client_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/client_test.go @@ -29,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/client-go/discovery" fakedisco "k8s.io/client-go/discovery/fake" "k8s.io/client-go/dynamic" fakerest "k8s.io/client-go/rest/fake" @@ -40,7 +39,7 @@ import ( autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" extv1beta1 "k8s.io/api/extensions/v1beta1" - apimeta "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/restmapper" coretesting "k8s.io/client-go/testing" ) @@ -97,11 +96,11 @@ func fakeScaleClient(t *testing.T) (ScalesGetter, []schema.GroupResource) { }, } - restMapperRes, err := discovery.GetAPIGroupResources(fakeDiscoveryClient) + restMapperRes, err := restmapper.GetAPIGroupResources(fakeDiscoveryClient) if err != nil { t.Fatalf("unexpected error while constructing resource list from fake discovery client: %v", err) } - restMapper := discovery.NewRESTMapper(restMapperRes, apimeta.InterfacesForUnstructured) + restMapper := restmapper.NewDiscoveryRESTMapper(restMapperRes) autoscalingScale := &autoscalingv1.Scale{ TypeMeta: metav1.TypeMeta{ diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go index bd42e7add..00734d437 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go index d6afedb0d..44f28aa1a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go index 2a7a45a47..474c80350 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go index 6d0ed7a29..26ed5754e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go index d34399667..7fe882f03 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/util.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/util.go index 46b5c4d1e..1c04b4551 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/util.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/scale/util.go @@ -21,6 +21,7 @@ import ( "strings" "sync" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" @@ -34,6 +35,15 @@ import ( scaleext "k8s.io/client-go/scale/scheme/extensionsv1beta1" ) +// PreferredResourceMapper determines the preferred version of a resource to scale +type PreferredResourceMapper interface { + // ResourceFor takes a partial resource and returns the preferred resource. + ResourceFor(resource schema.GroupVersionResource) (preferredResource schema.GroupVersionResource, err error) +} + +// Ensure a RESTMapper satisfies the PreferredResourceMapper interface +var _ PreferredResourceMapper = meta.RESTMapper(nil) + // ScaleKindResolver knows about the relationship between // resources and the GroupVersionKind of their scale subresources. type ScaleKindResolver interface { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/BUILD index dd8d13397..5b8684c26 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/BUILD @@ -22,9 +22,9 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels: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/version:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/pkg/version:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/actions.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/actions.go index 6f1c3a896..b99f231c8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/actions.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/actions.go @@ -58,37 +58,33 @@ func NewGetSubresourceAction(resource schema.GroupVersionResource, namespace, su return action } -func NewRootListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, opts interface{}) ListActionImpl { - action := ListActionImpl{} - action.Verb = "list" +func NewRootGetSubresourceAction(resource schema.GroupVersionResource, subresource, name string) GetActionImpl { + action := GetActionImpl{} + action.Verb = "get" action.Resource = resource - action.Kind = kind - labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) - action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} + action.Subresource = subresource + action.Name = name return action } -func NewListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, namespace string, opts interface{}) ListActionImpl { +func NewRootListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, opts interface{}) ListActionImpl { action := ListActionImpl{} action.Verb = "list" action.Resource = resource action.Kind = kind - action.Namespace = namespace labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} return action } -func NewListSubresourceAction(resource schema.GroupVersionResource, name, subresource string, kind schema.GroupVersionKind, namespace string, opts interface{}) ListActionImpl { +func NewListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, namespace string, opts interface{}) ListActionImpl { action := ListActionImpl{} action.Verb = "list" action.Resource = resource - action.Subresource = subresource action.Kind = kind action.Namespace = namespace - action.Name = name labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} @@ -114,12 +110,23 @@ func NewCreateAction(resource schema.GroupVersionResource, namespace string, obj return action } -func NewCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource string, namespace string, object runtime.Object) CreateActionImpl { +func NewRootCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource string, object runtime.Object) CreateActionImpl { action := CreateActionImpl{} action.Verb = "create" action.Resource = resource action.Subresource = subresource + action.Name = name + action.Object = object + + return action +} + +func NewCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource, namespace string, object runtime.Object) CreateActionImpl { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = resource action.Namespace = namespace + action.Subresource = subresource action.Name = name action.Object = object @@ -218,6 +225,16 @@ func NewRootDeleteAction(resource schema.GroupVersionResource, name string) Dele return action } +func NewRootDeleteSubresourceAction(resource schema.GroupVersionResource, subresource string, name string) DeleteActionImpl { + action := DeleteActionImpl{} + action.Verb = "delete" + action.Resource = resource + action.Subresource = subresource + action.Name = name + + return action +} + func NewDeleteAction(resource schema.GroupVersionResource, namespace, name string) DeleteActionImpl { action := DeleteActionImpl{} action.Verb = "delete" @@ -228,6 +245,17 @@ func NewDeleteAction(resource schema.GroupVersionResource, namespace, name strin return action } +func NewDeleteSubresourceAction(resource schema.GroupVersionResource, subresource, namespace, name string) DeleteActionImpl { + action := DeleteActionImpl{} + action.Verb = "delete" + action.Resource = resource + action.Subresource = subresource + action.Namespace = namespace + action.Name = name + + return action +} + func NewRootDeleteCollectionAction(resource schema.GroupVersionResource, opts interface{}) DeleteCollectionActionImpl { action := DeleteCollectionActionImpl{} action.Verb = "delete-collection" @@ -324,6 +352,10 @@ type Action interface { GetResource() schema.GroupVersionResource GetSubresource() string Matches(verb, resource string) bool + + // DeepCopy is used to copy an action to avoid any risk of accidental mutation. Most people never need to call this + // because the invocation logic deep copies before calls to storage and reactors. + DeepCopy() Action } type GenericAction interface { @@ -404,6 +436,10 @@ func (a ActionImpl) Matches(verb, resource string) bool { return strings.ToLower(verb) == strings.ToLower(a.Verb) && strings.ToLower(resource) == strings.ToLower(a.Resource.Resource) } +func (a ActionImpl) DeepCopy() Action { + ret := a + return ret +} type GenericActionImpl struct { ActionImpl @@ -414,6 +450,14 @@ func (a GenericActionImpl) GetValue() interface{} { return a.Value } +func (a GenericActionImpl) DeepCopy() Action { + return GenericActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + // TODO this is wrong, but no worse than before + Value: a.Value, + } +} + type GetActionImpl struct { ActionImpl Name string @@ -423,6 +467,13 @@ func (a GetActionImpl) GetName() string { return a.Name } +func (a GetActionImpl) DeepCopy() Action { + return GetActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Name: a.Name, + } +} + type ListActionImpl struct { ActionImpl Kind schema.GroupVersionKind @@ -438,6 +489,18 @@ func (a ListActionImpl) GetListRestrictions() ListRestrictions { return a.ListRestrictions } +func (a ListActionImpl) DeepCopy() Action { + return ListActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Kind: a.Kind, + Name: a.Name, + ListRestrictions: ListRestrictions{ + Labels: a.ListRestrictions.Labels.DeepCopySelector(), + Fields: a.ListRestrictions.Fields.DeepCopySelector(), + }, + } +} + type CreateActionImpl struct { ActionImpl Name string @@ -448,6 +511,14 @@ func (a CreateActionImpl) GetObject() runtime.Object { return a.Object } +func (a CreateActionImpl) DeepCopy() Action { + return CreateActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Name: a.Name, + Object: a.Object.DeepCopyObject(), + } +} + type UpdateActionImpl struct { ActionImpl Object runtime.Object @@ -457,6 +528,13 @@ func (a UpdateActionImpl) GetObject() runtime.Object { return a.Object } +func (a UpdateActionImpl) DeepCopy() Action { + return UpdateActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Object: a.Object.DeepCopyObject(), + } +} + type PatchActionImpl struct { ActionImpl Name string @@ -471,6 +549,16 @@ func (a PatchActionImpl) GetPatch() []byte { return a.Patch } +func (a PatchActionImpl) DeepCopy() Action { + patch := make([]byte, len(a.Patch)) + copy(patch, a.Patch) + return PatchActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Name: a.Name, + Patch: patch, + } +} + type DeleteActionImpl struct { ActionImpl Name string @@ -480,6 +568,13 @@ func (a DeleteActionImpl) GetName() string { return a.Name } +func (a DeleteActionImpl) DeepCopy() Action { + return DeleteActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Name: a.Name, + } +} + type DeleteCollectionActionImpl struct { ActionImpl ListRestrictions ListRestrictions @@ -489,6 +584,16 @@ func (a DeleteCollectionActionImpl) GetListRestrictions() ListRestrictions { return a.ListRestrictions } +func (a DeleteCollectionActionImpl) DeepCopy() Action { + return DeleteCollectionActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + ListRestrictions: ListRestrictions{ + Labels: a.ListRestrictions.Labels.DeepCopySelector(), + Fields: a.ListRestrictions.Fields.DeepCopySelector(), + }, + } +} + type WatchActionImpl struct { ActionImpl WatchRestrictions WatchRestrictions @@ -498,6 +603,17 @@ func (a WatchActionImpl) GetWatchRestrictions() WatchRestrictions { return a.WatchRestrictions } +func (a WatchActionImpl) DeepCopy() Action { + return WatchActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + WatchRestrictions: WatchRestrictions{ + Labels: a.WatchRestrictions.Labels.DeepCopySelector(), + Fields: a.WatchRestrictions.Fields.DeepCopySelector(), + ResourceVersion: a.WatchRestrictions.ResourceVersion, + }, + } +} + type ProxyGetActionImpl struct { ActionImpl Scheme string @@ -526,3 +642,18 @@ func (a ProxyGetActionImpl) GetPath() string { func (a ProxyGetActionImpl) GetParams() map[string]string { return a.Params } + +func (a ProxyGetActionImpl) DeepCopy() Action { + params := map[string]string{} + for k, v := range a.Params { + params[k] = v + } + return ProxyGetActionImpl{ + ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), + Scheme: a.Scheme, + Name: a.Name, + Port: a.Port, + Path: a.Path, + Params: params, + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fake.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fake.go index da47b23b9..8b3f31eaf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fake.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fake.go @@ -22,10 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/version" "k8s.io/apimachinery/pkg/watch" - kubeversion "k8s.io/client-go/pkg/version" restclient "k8s.io/client-go/rest" ) @@ -134,13 +131,13 @@ func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime. c.Lock() defer c.Unlock() - c.actions = append(c.actions, action) + c.actions = append(c.actions, action.DeepCopy()) for _, reactor := range c.ReactionChain { if !reactor.Handles(action) { continue } - handled, ret, err := reactor.React(action) + handled, ret, err := reactor.React(action.DeepCopy()) if !handled { continue } @@ -157,13 +154,13 @@ func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) { c.Lock() defer c.Unlock() - c.actions = append(c.actions, action) + c.actions = append(c.actions, action.DeepCopy()) for _, reactor := range c.WatchReactionChain { if !reactor.Handles(action) { continue } - handled, ret, err := reactor.React(action) + handled, ret, err := reactor.React(action.DeepCopy()) if !handled { continue } @@ -180,13 +177,13 @@ func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper { c.Lock() defer c.Unlock() - c.actions = append(c.actions, action) + c.actions = append(c.actions, action.DeepCopy()) for _, reactor := range c.ProxyReactionChain { if !reactor.Handles(action) { continue } - handled, ret, err := reactor.React(action) + handled, ret, err := reactor.React(action.DeepCopy()) if !handled || err != nil { continue } @@ -214,46 +211,3 @@ func (c *Fake) Actions() []Action { copy(fa, c.actions) return fa } - -// TODO: this probably should be moved to somewhere else. -type FakeDiscovery struct { - *Fake -} - -func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - action := ActionImpl{ - Verb: "get", - Resource: schema.GroupVersionResource{Resource: "resource"}, - } - c.Invokes(action, nil) - for _, rl := range c.Resources { - if rl.GroupVersion == groupVersion { - return rl, nil - } - } - - return nil, fmt.Errorf("GroupVersion %q not found", groupVersion) -} - -func (c *FakeDiscovery) ServerResources() ([]*metav1.APIResourceList, error) { - action := ActionImpl{ - Verb: "get", - Resource: schema.GroupVersionResource{Resource: "resource"}, - } - c.Invokes(action, nil) - return c.Resources, nil -} - -func (c *FakeDiscovery) ServerGroups() (*metav1.APIGroupList, error) { - return nil, nil -} - -func (c *FakeDiscovery) ServerVersion() (*version.Info, error) { - action := ActionImpl{} - action.Verb = "get" - action.Resource = schema.GroupVersionResource{Resource: "version"} - - c.Invokes(action, nil) - versionInfo := kubeversion.Get() - return &versionInfo, nil -} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fixture.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fixture.go index ba8ee508f..00c4c49fc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fixture.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fixture.go @@ -25,15 +25,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/json" + "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/watch" restclient "k8s.io/client-go/rest" ) -// FakeWatchBufferSize is the max num of watch event can be buffered in the -// watch channel. Note that when watch event overflows or exceed this buffer -// size, manipulations via fake client may be blocked. -const FakeWatchBufferSize = 128 - // ObjectTracker keeps track of objects. It is intended to be used to // fake calls to a server by returning objects based on their kind, // namespace and name. @@ -77,7 +74,6 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc { return func(action Action) (bool, runtime.Object, error) { ns := action.GetNamespace() gvr := action.GetResource() - // Here and below we need to switch on implementation types, // not on interfaces, as some interfaces are identical // (e.g. UpdateAction and CreateAction), so if we use them, @@ -130,6 +126,34 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc { } return true, nil, nil + case PatchActionImpl: + obj, err := tracker.Get(gvr, ns, action.GetName()) + if err != nil { + // object is not registered + return false, nil, err + } + + old, err := json.Marshal(obj) + if err != nil { + return true, nil, err + } + // Only supports strategic merge patch + // TODO: Add support for other Patch types + mergedByte, err := strategicpatch.StrategicMergePatch(old, action.GetPatch(), obj) + if err != nil { + return true, nil, err + } + + if err = json.Unmarshal(mergedByte, obj); err != nil { + return true, nil, err + } + + if err = tracker.Update(gvr, obj, ns); err != nil { + return true, nil, err + } + + return true, obj, nil + default: return false, nil, fmt.Errorf("no reaction implemented for %s", action) } @@ -142,12 +166,11 @@ type tracker struct { lock sync.RWMutex objects map[schema.GroupVersionResource][]runtime.Object // The value type of watchers is a map of which the key is either a namespace or - // all/non namespace aka "" and its value is list of fake watchers. Each of - // fake watcher holds a buffered channel of size "FakeWatchBufferSize" which - // is default to 128. Manipulations on resources will broadcast the notification - // events into the watchers' channel and note that too many unhandled event may - // potentially block the tracker. - watchers map[schema.GroupVersionResource]map[string][]*watch.FakeWatcher + // all/non namespace aka "" and its value is list of fake watchers. + // Manipulations on resources will broadcast the notification events into the + // watchers' channel. Note that too many unhandled events (currently 100, + // see apimachinery/pkg/watch.DefaultChanSize) will cause a panic. + watchers map[schema.GroupVersionResource]map[string][]*watch.RaceFreeFakeWatcher } var _ ObjectTracker = &tracker{} @@ -159,7 +182,7 @@ func NewObjectTracker(scheme ObjectScheme, decoder runtime.Decoder) ObjectTracke scheme: scheme, decoder: decoder, objects: make(map[schema.GroupVersionResource][]runtime.Object), - watchers: make(map[schema.GroupVersionResource]map[string][]*watch.FakeWatcher), + watchers: make(map[schema.GroupVersionResource]map[string][]*watch.RaceFreeFakeWatcher), } } @@ -206,10 +229,10 @@ func (t *tracker) Watch(gvr schema.GroupVersionResource, ns string) (watch.Inter t.lock.Lock() defer t.lock.Unlock() - fakewatcher := watch.NewFakeWithChanSize(FakeWatchBufferSize, true) + fakewatcher := watch.NewRaceFreeFake() if _, exists := t.watchers[gvr]; !exists { - t.watchers[gvr] = make(map[string][]*watch.FakeWatcher) + t.watchers[gvr] = make(map[string][]*watch.RaceFreeFakeWatcher) } t.watchers[gvr][ns] = append(t.watchers[gvr][ns], fakewatcher) return fakewatcher, nil @@ -293,8 +316,8 @@ func (t *tracker) Update(gvr schema.GroupVersionResource, obj runtime.Object, ns return t.add(gvr, obj, ns, true) } -func (t *tracker) getWatches(gvr schema.GroupVersionResource, ns string) []*watch.FakeWatcher { - watches := []*watch.FakeWatcher{} +func (t *tracker) getWatches(gvr schema.GroupVersionResource, ns string) []*watch.RaceFreeFakeWatcher { + watches := []*watch.RaceFreeFakeWatcher{} if t.watchers[gvr] != nil { if w := t.watchers[gvr][ns]; w != nil { watches = append(watches, w...) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fixture_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fixture_test.go index 967e0aefa..405fe1a7e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fixture_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/testing/fixture_test.go @@ -63,6 +63,9 @@ func TestWatchCallNonNamespace(t *testing.T) { codecs := serializer.NewCodecFactory(scheme) o := NewObjectTracker(scheme, codecs.UniversalDecoder()) watch, err := o.Watch(testResource, ns) + if err != nil { + t.Fatalf("test resource watch failed in %s: %v ", ns, err) + } go func() { err := o.Create(testResource, testObj, ns) if err != nil { @@ -85,7 +88,13 @@ func TestWatchCallAllNamespace(t *testing.T) { codecs := serializer.NewCodecFactory(scheme) o := NewObjectTracker(scheme, codecs.UniversalDecoder()) w, err := o.Watch(testResource, "test_namespace") + if err != nil { + t.Fatalf("test resource watch failed in test_namespace: %v", err) + } wAll, err := o.Watch(testResource, "") + if err != nil { + t.Fatalf("test resource watch failed in all namespaces: %v", err) + } go func() { err := o.Create(testResource, testObj, ns) assert.NoError(t, err, "test resource creation failed") @@ -161,6 +170,9 @@ func TestWatchCallMultipleInvocation(t *testing.T) { for idx, watchNamespace := range watchNamespaces { i := idx w, err := o.Watch(testResource, watchNamespace) + if err != nil { + t.Fatalf("test resource watch failed in %s: %v", watchNamespace, err) + } go func() { assert.NoError(t, err, "watch invocation failed") for _, c := range cases { @@ -190,3 +202,34 @@ func TestWatchCallMultipleInvocation(t *testing.T) { } wg.Wait() } + +func TestWatchAddAfterStop(t *testing.T) { + testResource := schema.GroupVersionResource{Group: "", Version: "test_version", Resource: "test_kind"} + testObj := getArbitraryResource(testResource, "test_name", "test_namespace") + accessor, err := meta.Accessor(testObj) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + ns := accessor.GetNamespace() + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + o := NewObjectTracker(scheme, codecs.UniversalDecoder()) + watch, err := o.Watch(testResource, ns) + if err != nil { + t.Errorf("watch creation failed: %v", err) + } + + // When the watch is stopped it should ignore later events without panicking. + defer func() { + if r := recover(); r != nil { + t.Errorf("Watch panicked when it should have ignored create after stop: %v", r) + } + }() + + watch.Stop() + err = o.Create(testResource, testObj, ns) + if err != nil { + t.Errorf("test resource creation failed: %v", err) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/OWNERS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/OWNERS similarity index 100% rename from vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/OWNERS rename to vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/OWNERS diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/doc.go index b9910c35a..249e0a059 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/doc.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package api (pkg/bootstrap/token/api) contains constants and types needed for +// Package api (k8s.io/client-go/tools/bootstrap/token/api) contains constants and types needed for // bootstrap tokens as maintained by the BootstrapSigner and TokenCleaner -// controllers (in pkg/controller/bootstrap) +// controllers (in k8s.io/kubernetes/pkg/controller/bootstrap) package api // import "k8s.io/client-go/tools/bootstrap/token/api" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/types.go index c30814c0e..3bea78b17 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/api/types.go @@ -86,14 +86,26 @@ const ( // authenticate as. The full username given is "system:bootstrap:". BootstrapUserPrefix = "system:bootstrap:" - // BootstrapGroupPattern is the valid regex pattern that all groups - // assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match. - // See also ValidateBootstrapGroupName(). - BootstrapGroupPattern = "system:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]" - // BootstrapDefaultGroup is the default group for bootstrapping bearer // tokens (in addition to any groups from BootstrapTokenExtraGroupsKey). BootstrapDefaultGroup = "system:bootstrappers" + + // BootstrapGroupPattern is the valid regex pattern that all groups + // assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match. + // See also util.ValidateBootstrapGroupName() + BootstrapGroupPattern = `\Asystem:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]\z` + + // BootstrapTokenPattern defines the {id}.{secret} regular expression pattern + BootstrapTokenPattern = `\A([a-z0-9]{6})\.([a-z0-9]{16})\z` + + // BootstrapTokenIDPattern defines token's id regular expression pattern + BootstrapTokenIDPattern = `\A([a-z0-9]{6})\z` + + // BootstrapTokenIDBytes defines the number of bytes used for the Bootstrap Token's ID field + BootstrapTokenIDBytes = 6 + + // BootstrapTokenSecretBytes defines the number of bytes used the Bootstrap Token's Secret field + BootstrapTokenSecretBytes = 16 ) // KnownTokenUsages specifies the known functions a token will get. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers.go index d28fd28f2..bb1fbeb65 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers.go @@ -17,20 +17,101 @@ limitations under the License. package util import ( + "bufio" + "crypto/rand" "fmt" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/client-go/tools/bootstrap/token/api" "regexp" "strings" + + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/tools/bootstrap/token/api" +) + +// validBootstrapTokenChars defines the characters a bootstrap token can consist of +const validBootstrapTokenChars = "0123456789abcdefghijklmnopqrstuvwxyz" + +var ( + // BootstrapTokenRegexp is a compiled regular expression of TokenRegexpString + BootstrapTokenRegexp = regexp.MustCompile(api.BootstrapTokenPattern) + // BootstrapTokenIDRegexp is a compiled regular expression of TokenIDRegexpString + BootstrapTokenIDRegexp = regexp.MustCompile(api.BootstrapTokenIDPattern) + // BootstrapGroupRegexp is a compiled regular expression of BootstrapGroupPattern + BootstrapGroupRegexp = regexp.MustCompile(api.BootstrapGroupPattern) ) -var bootstrapGroupRegexp = regexp.MustCompile(`\A` + api.BootstrapGroupPattern + `\z`) +// GenerateBootstrapToken generates a new, random Bootstrap Token. +func GenerateBootstrapToken() (string, error) { + tokenID, err := randBytes(api.BootstrapTokenIDBytes) + if err != nil { + return "", err + } + + tokenSecret, err := randBytes(api.BootstrapTokenSecretBytes) + if err != nil { + return "", err + } + + return TokenFromIDAndSecret(tokenID, tokenSecret), nil +} + +// randBytes returns a random string consisting of the characters in +// validBootstrapTokenChars, with the length customized by the parameter +func randBytes(length int) (string, error) { + // len("0123456789abcdefghijklmnopqrstuvwxyz") = 36 which doesn't evenly divide + // the possible values of a byte: 256 mod 36 = 4. Discard any random bytes we + // read that are >= 252 so the bytes we evenly divide the character set. + const maxByteValue = 252 + + var ( + b byte + err error + token = make([]byte, length) + ) + + reader := bufio.NewReaderSize(rand.Reader, length*2) + for i := range token { + for { + if b, err = reader.ReadByte(); err != nil { + return "", err + } + if b < maxByteValue { + break + } + } + + token[i] = validBootstrapTokenChars[int(b)%len(validBootstrapTokenChars)] + } + + return string(token), nil +} + +// TokenFromIDAndSecret returns the full token which is of the form "{id}.{secret}" +func TokenFromIDAndSecret(id, secret string) string { + return fmt.Sprintf("%s.%s", id, secret) +} + +// IsValidBootstrapToken returns whether the given string is valid as a Bootstrap Token and +// in other words satisfies the BootstrapTokenRegexp +func IsValidBootstrapToken(token string) bool { + return BootstrapTokenRegexp.MatchString(token) +} + +// IsValidBootstrapTokenID returns whether the given string is valid as a Bootstrap Token ID and +// in other words satisfies the BootstrapTokenIDRegexp +func IsValidBootstrapTokenID(tokenID string) bool { + return BootstrapTokenIDRegexp.MatchString(tokenID) +} + +// BootstrapTokenSecretName returns the expected name for the Secret storing the +// Bootstrap Token in the Kubernetes API. +func BootstrapTokenSecretName(tokenID string) string { + return fmt.Sprintf("%s%s", api.BootstrapTokenSecretPrefix, tokenID) +} // ValidateBootstrapGroupName checks if the provided group name is a valid // bootstrap group name. Returns nil if valid or a validation error if invalid. -// TODO(mattmoyer): this validation should migrate out to client-go (see https://github.com/kubernetes/client-go/issues/114) func ValidateBootstrapGroupName(name string) error { - if bootstrapGroupRegexp.Match([]byte(name)) { + if BootstrapGroupRegexp.Match([]byte(name)) { return nil } return fmt.Errorf("bootstrap group %q is invalid (must match %s)", name, api.BootstrapGroupPattern) @@ -46,7 +127,7 @@ func ValidateUsages(usages []string) error { } } if len(invalidUsages) > 0 { - return fmt.Errorf("invalide bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ",")) + return fmt.Errorf("invalid bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ",")) } return nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go index 915bf7540..a1fe6092f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/bootstrap/token/util/helpers_test.go @@ -21,6 +21,143 @@ import ( "testing" ) +func TestGenerateBootstrapToken(t *testing.T) { + token, err := GenerateBootstrapToken() + if err != nil { + t.Fatalf("GenerateBootstrapToken returned an unexpected error: %+v", err) + } + if !IsValidBootstrapToken(token) { + t.Errorf("GenerateBootstrapToken didn't generate a valid token: %q", token) + } +} + +func TestRandBytes(t *testing.T) { + var randTest = []int{ + 0, + 1, + 2, + 3, + 100, + } + + for _, rt := range randTest { + actual, err := randBytes(rt) + if err != nil { + t.Errorf("failed randBytes: %v", err) + } + if len(actual) != rt { + t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt, len(actual)) + } + } +} + +func TestTokenFromIDAndSecret(t *testing.T) { + var tests = []struct { + id string + secret string + expected string + }{ + {"foo", "bar", "foo.bar"}, // should use default + {"abcdef", "abcdef0123456789", "abcdef.abcdef0123456789"}, + {"h", "b", "h.b"}, + } + for _, rt := range tests { + actual := TokenFromIDAndSecret(rt.id, rt.secret) + if actual != rt.expected { + t.Errorf( + "failed TokenFromIDAndSecret:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + +func TestIsValidBootstrapToken(t *testing.T) { + var tests = []struct { + token string + expected bool + }{ + {token: "", expected: false}, + {token: ".", expected: false}, + {token: "1234567890123456789012", expected: false}, // invalid parcel size + {token: "12345.1234567890123456", expected: false}, // invalid parcel size + {token: ".1234567890123456", expected: false}, // invalid parcel size + {token: "123456.", expected: false}, // invalid parcel size + {token: "123456:1234567890.123456", expected: false}, // invalid separation + {token: "abcdef:1234567890123456", expected: false}, // invalid separation + {token: "Abcdef.1234567890123456", expected: false}, // invalid token id + {token: "123456.AABBCCDDEEFFGGHH", expected: false}, // invalid token secret + {token: "123456.AABBCCD-EEFFGGHH", expected: false}, // invalid character + {token: "abc*ef.1234567890123456", expected: false}, // invalid character + {token: "abcdef.1234567890123456", expected: true}, + {token: "123456.aabbccddeeffgghh", expected: true}, + {token: "ABCDEF.abcdef0123456789", expected: false}, + {token: "abcdef.abcdef0123456789", expected: true}, + {token: "123456.1234560123456789", expected: true}, + } + for _, rt := range tests { + actual := IsValidBootstrapToken(rt.token) + if actual != rt.expected { + t.Errorf( + "failed IsValidBootstrapToken for the token %q\n\texpected: %t\n\t actual: %t", + rt.token, + rt.expected, + actual, + ) + } + } +} + +func TestIsValidBootstrapTokenID(t *testing.T) { + var tests = []struct { + tokenID string + expected bool + }{ + {tokenID: "", expected: false}, + {tokenID: "1234567890123456789012", expected: false}, + {tokenID: "12345", expected: false}, + {tokenID: "Abcdef", expected: false}, + {tokenID: "ABCDEF", expected: false}, + {tokenID: "abcdef.", expected: false}, + {tokenID: "abcdef", expected: true}, + {tokenID: "123456", expected: true}, + } + for _, rt := range tests { + actual := IsValidBootstrapTokenID(rt.tokenID) + if actual != rt.expected { + t.Errorf( + "failed IsValidBootstrapTokenID for the token %q\n\texpected: %t\n\t actual: %t", + rt.tokenID, + rt.expected, + actual, + ) + } + } +} + +func TestBootstrapTokenSecretName(t *testing.T) { + var tests = []struct { + tokenID string + expected string + }{ + {"foo", "bootstrap-token-foo"}, + {"bar", "bootstrap-token-bar"}, + {"", "bootstrap-token-"}, + {"abcdef", "bootstrap-token-abcdef"}, + } + for _, rt := range tests { + actual := BootstrapTokenSecretName(rt.tokenID) + if actual != rt.expected { + t.Errorf( + "failed BootstrapTokenSecretName:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + func TestValidateBootstrapGroupName(t *testing.T) { tests := []struct { name string diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/BUILD index 524354e87..6be2aecd5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/BUILD @@ -64,7 +64,6 @@ go_library( importpath = "k8s.io/client-go/tools/cache", deps = [ "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/listwatch.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/listwatch.go index 06657a3b0..8bf41f517 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/listwatch.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/listwatch.go @@ -17,10 +17,9 @@ limitations under the License. package cache import ( + "context" "time" - "golang.org/x/net/context" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/mutation_detector.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/mutation_detector.go index 8e6338a1b..e2aa44848 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/mutation_detector.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/cache/mutation_detector.go @@ -24,6 +24,8 @@ import ( "sync" "time" + "github.com/golang/glog" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/diff" ) @@ -43,6 +45,7 @@ func NewCacheMutationDetector(name string) CacheMutationDetector { if !mutationDetectionEnabled { return dummyMutationDetector{} } + glog.Warningln("Mutation detector is enabled, this will result in memory leakage.") return &defaultCacheMutationDetector{name: name, period: 1 * time.Second} } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/BUILD index c46c76d5d..afc277020 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/BUILD @@ -45,10 +45,9 @@ go_library( importpath = "k8s.io/client-go/tools/clientcmd", deps = [ "//vendor/github.com/golang/glog:go_default_library", - "//vendor/github.com/howeyc/gopass:go_default_library", "//vendor/github.com/imdario/mergo:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/golang.org/x/crypto/ssh/terminal: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/util/errors:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/v1/conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/v1/conversion.go index b47bfbca2..2d7142e6e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/v1/conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/v1/conversion.go @@ -17,6 +17,7 @@ limitations under the License. package v1 import ( + "fmt" "sort" "k8s.io/apimachinery/pkg/conversion" @@ -105,7 +106,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error { if err := s.Convert(&curr.Cluster, newCluster, 0); err != nil { return err } - (*out)[curr.Name] = newCluster + if (*out)[curr.Name] == nil { + (*out)[curr.Name] = newCluster + } else { + return fmt.Errorf("error converting *[]NamedCluster into *map[string]*api.Cluster: duplicate name \"%v\" in list: %v", curr.Name, *in) + } } return nil @@ -136,7 +141,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error { if err := s.Convert(&curr.AuthInfo, newAuthInfo, 0); err != nil { return err } - (*out)[curr.Name] = newAuthInfo + if (*out)[curr.Name] == nil { + (*out)[curr.Name] = newAuthInfo + } else { + return fmt.Errorf("error converting *[]NamedAuthInfo into *map[string]*api.AuthInfo: duplicate name \"%v\" in list: %v", curr.Name, *in) + } } return nil @@ -167,7 +176,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error { if err := s.Convert(&curr.Context, newContext, 0); err != nil { return err } - (*out)[curr.Name] = newContext + if (*out)[curr.Name] == nil { + (*out)[curr.Name] = newContext + } else { + return fmt.Errorf("error converting *[]NamedContext into *map[string]*api.Context: duplicate name \"%v\" in list: %v", curr.Name, *in) + } } return nil @@ -198,7 +211,11 @@ func addConversionFuncs(scheme *runtime.Scheme) error { if err := s.Convert(&curr.Extension, &newExtension, 0); err != nil { return err } - (*out)[curr.Name] = newExtension + if (*out)[curr.Name] == nil { + (*out)[curr.Name] = newExtension + } else { + return fmt.Errorf("error converting *[]NamedExtension into *map[string]runtime.Object: duplicate name \"%v\" in list: %v", curr.Name, *in) + } } return nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/v1/zz_generated.deepcopy.go index 83d05b7c6..bb0f3523f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/zz_generated.deepcopy.go index 085c088ee..b90aa8d74 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/auth_loaders.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/auth_loaders.go index 12331f6e6..1d3c11d8f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/auth_loaders.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/auth_loaders.go @@ -23,7 +23,8 @@ import ( "io/ioutil" "os" - "github.com/howeyc/gopass" + "golang.org/x/crypto/ssh/terminal" + clientauth "k8s.io/client-go/tools/auth" ) @@ -89,8 +90,12 @@ func promptForString(field string, r io.Reader, show bool) (result string, err e _, err = fmt.Fscan(r, &result) } else { var data []byte - data, err = gopass.GetPasswdMasked() - result = string(data) + if terminal.IsTerminal(int(os.Stdin.Fd())) { + data, err = terminal.ReadPassword(int(os.Stdin.Fd())) + result = string(data) + } else { + return "", fmt.Errorf("error reading input for %s", field) + } } return result, err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go index c202e6b25..66331a7ad 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go @@ -27,7 +27,6 @@ import ( "github.com/golang/glog" "github.com/imdario/mergo" - "k8s.io/api/core/v1" restclient "k8s.io/client-go/rest" clientauth "k8s.io/client-go/tools/auth" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" @@ -100,6 +99,26 @@ func NewInteractiveClientConfig(config clientcmdapi.Config, contextName string, return &DirectClientConfig{config, contextName, overrides, fallbackReader, configAccess, promptedCredentials{}} } +// NewClientConfigFromBytes takes your kubeconfig and gives you back a ClientConfig +func NewClientConfigFromBytes(configBytes []byte) (ClientConfig, error) { + config, err := Load(configBytes) + if err != nil { + return nil, err + } + + return &DirectClientConfig{*config, "", &ConfigOverrides{}, nil, nil, promptedCredentials{}}, nil +} + +// RESTConfigFromKubeConfig is a convenience method to give back a restconfig from your kubeconfig bytes. +// For programmatic access, this is what you want 80% of the time +func RESTConfigFromKubeConfig(configBytes []byte) (*restclient.Config, error) { + clientConfig, err := NewClientConfigFromBytes(configBytes) + if err != nil { + return nil, err + } + return clientConfig.ClientConfig() +} + func (config *DirectClientConfig) RawConfig() (clientcmdapi.Config, error) { return config.config, nil } @@ -318,7 +337,7 @@ func (config *DirectClientConfig) Namespace() (string, bool, error) { } if len(configContext.Namespace) == 0 { - return v1.NamespaceDefault, false, nil + return "default", false, nil } return configContext.Namespace, false, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/config.go index 16ccdaf20..7092c5b10 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/config.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/config.go @@ -68,7 +68,9 @@ func (o *PathOptions) GetEnvVarFiles() []string { return []string{} } - return filepath.SplitList(envVarValue) + fileList := filepath.SplitList(envVarValue) + // prevent the same path load multiple times + return deduplicate(fileList) } func (o *PathOptions) GetLoadingPrecedence() []string { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader.go index 95e7b1540..3442475e2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader.go @@ -139,7 +139,9 @@ func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules { envVarFiles := os.Getenv(RecommendedConfigPathEnvVar) if len(envVarFiles) != 0 { - chain = append(chain, filepath.SplitList(envVarFiles)...) + fileList := filepath.SplitList(envVarFiles) + // prevent the same path load multiple times + chain = append(chain, deduplicate(fileList)...) } else { chain = append(chain, RecommendedHomeFile) @@ -615,3 +617,17 @@ func MakeRelative(path, base string) (string, error) { } return path, nil } + +// deduplicate removes any duplicated values and returns a new slice, keeping the order unchanged +func deduplicate(s []string) []string { + encountered := map[string]bool{} + ret := make([]string, 0) + for i := range s { + if encountered[s[i]] { + continue + } + encountered[s[i]] = true + ret = append(ret, s[i]) + } + return ret +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader_test.go index c2dbd019d..86eccac45 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader_test.go @@ -201,6 +201,174 @@ func TestLoadingEmptyMaps(t *testing.T) { } } +func TestDuplicateClusterName(t *testing.T) { + configFile, _ := ioutil.TempFile("", "") + defer os.Remove(configFile.Name()) + + err := ioutil.WriteFile(configFile.Name(), []byte(` +kind: Config +apiVersion: v1 +clusters: +- cluster: + api-version: v1 + server: https://kubernetes.default.svc:443 + certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + name: kubeconfig-cluster +- cluster: + api-version: v2 + server: https://test.example.server:443 + certificate-authority: /var/run/secrets/test.example.io/serviceaccount/ca.crt + name: kubeconfig-cluster +contexts: +- context: + cluster: kubeconfig-cluster + namespace: default + user: kubeconfig-user + name: kubeconfig-context +current-context: kubeconfig-context +users: +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +`), os.FileMode(0755)) + + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + _, err = LoadFromFile(configFile.Name()) + if err == nil || !strings.Contains(err.Error(), + "error converting *[]NamedCluster into *map[string]*api.Cluster: duplicate name \"kubeconfig-cluster\" in list") { + t.Error("Expected error in loading duplicate cluster name, got none") + } +} + +func TestDuplicateContextName(t *testing.T) { + configFile, _ := ioutil.TempFile("", "") + defer os.Remove(configFile.Name()) + + err := ioutil.WriteFile(configFile.Name(), []byte(` +kind: Config +apiVersion: v1 +clusters: +- cluster: + api-version: v1 + server: https://kubernetes.default.svc:443 + certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + name: kubeconfig-cluster +contexts: +- context: + cluster: kubeconfig-cluster + namespace: default + user: kubeconfig-user + name: kubeconfig-context +- context: + cluster: test-example-cluster + namespace: test-example + user: test-example-user + name: kubeconfig-context +current-context: kubeconfig-context +users: +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +`), os.FileMode(0755)) + + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + _, err = LoadFromFile(configFile.Name()) + if err == nil || !strings.Contains(err.Error(), + "error converting *[]NamedContext into *map[string]*api.Context: duplicate name \"kubeconfig-context\" in list") { + t.Error("Expected error in loading duplicate context name, got none") + } +} + +func TestDuplicateUserName(t *testing.T) { + configFile, _ := ioutil.TempFile("", "") + defer os.Remove(configFile.Name()) + + err := ioutil.WriteFile(configFile.Name(), []byte(` +kind: Config +apiVersion: v1 +clusters: +- cluster: + api-version: v1 + server: https://kubernetes.default.svc:443 + certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + name: kubeconfig-cluster +contexts: +- context: + cluster: kubeconfig-cluster + namespace: default + user: kubeconfig-user + name: kubeconfig-context +current-context: kubeconfig-context +users: +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/test.example.com/serviceaccount/token +`), os.FileMode(0755)) + + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + _, err = LoadFromFile(configFile.Name()) + if err == nil || !strings.Contains(err.Error(), + "error converting *[]NamedAuthInfo into *map[string]*api.AuthInfo: duplicate name \"kubeconfig-user\" in list") { + t.Error("Expected error in loading duplicate user name, got none") + } +} + +func TestDuplicateExtensionName(t *testing.T) { + configFile, _ := ioutil.TempFile("", "") + defer os.Remove(configFile.Name()) + + err := ioutil.WriteFile(configFile.Name(), []byte(` +kind: Config +apiVersion: v1 +clusters: +- cluster: + api-version: v1 + server: https://kubernetes.default.svc:443 + certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + name: kubeconfig-cluster +contexts: +- context: + cluster: kubeconfig-cluster + namespace: default + user: kubeconfig-user + name: kubeconfig-context +current-context: kubeconfig-context +users: +- name: kubeconfig-user + user: + tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +extensions: +- extension: + bytes: test + name: test-extension +- extension: + bytes: some-example + name: test-extension +`), os.FileMode(0755)) + + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + _, err = LoadFromFile(configFile.Name()) + if err == nil || !strings.Contains(err.Error(), + "error converting *[]NamedExtension into *map[string]runtime.Object: duplicate name \"test-extension\" in list") { + t.Error("Expected error in loading duplicate extension name, got none") + } +} + func TestResolveRelativePaths(t *testing.T) { pathResolutionConfig1 := clientcmdapi.Config{ AuthInfos: map[string]*clientcmdapi.AuthInfo{ @@ -592,3 +760,30 @@ func Example_mergingEverythingNoConflicts() { // user: // token: red-token } + +func TestDeduplicate(t *testing.T) { + testCases := []struct { + src []string + expect []string + }{ + { + src: []string{"a", "b", "c", "d", "e", "f"}, + expect: []string{"a", "b", "c", "d", "e", "f"}, + }, + { + src: []string{"a", "b", "c", "b", "e", "f"}, + expect: []string{"a", "b", "c", "e", "f"}, + }, + { + src: []string{"a", "a", "b", "b", "c", "b"}, + expect: []string{"a", "b", "c"}, + }, + } + + for _, testCase := range testCases { + get := deduplicate(testCase.src) + if !reflect.DeepEqual(get, testCase.expect) { + t.Errorf("expect: %v, get: %v", testCase.expect, get) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/merged_client_builder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/merged_client_builder.go index 3f02111bd..05038133b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/merged_client_builder.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/merged_client_builder.go @@ -22,7 +22,6 @@ import ( "github.com/golang/glog" - "k8s.io/api/core/v1" restclient "k8s.io/client-go/rest" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) @@ -145,7 +144,7 @@ func (config *DeferredLoadingClientConfig) Namespace() (string, bool, error) { if len(ns) > 0 { // if we got a non-default namespace from the kubeconfig, use it - if ns != v1.NamespaceDefault { + if ns != "default" { return ns, false, nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/leaderelection.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/leaderelection.go index e41b420c9..aed55574a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/leaderelection.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/leaderelection.go @@ -74,6 +74,16 @@ func NewLeaderElector(lec LeaderElectionConfig) (*LeaderElector, error) { if lec.RenewDeadline <= time.Duration(JitterFactor*float64(lec.RetryPeriod)) { return nil, fmt.Errorf("renewDeadline must be greater than retryPeriod*JitterFactor") } + if lec.LeaseDuration < 1 { + return nil, fmt.Errorf("leaseDuration must be greater than zero") + } + if lec.RenewDeadline < 1 { + return nil, fmt.Errorf("renewDeadline must be greater than zero") + } + if lec.RetryPeriod < 1 { + return nil, fmt.Errorf("retryPeriod must be greater than zero") + } + if lec.Lock == nil { return nil, fmt.Errorf("Lock must not be nil.") } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/BUILD index 4d07429af..c02def57f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/BUILD @@ -11,7 +11,6 @@ go_library( srcs = ["pager.go"], importpath = "k8s.io/client-go/tools/pager", deps = [ - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", @@ -39,7 +38,6 @@ go_test( srcs = ["pager_test.go"], embed = [":go_default_library"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/pager.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/pager.go index 2e0874e0e..74ea3586a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/pager.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/pager.go @@ -17,10 +17,9 @@ limitations under the License. package pager import ( + "context" "fmt" - "golang.org/x/net/context" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/pager_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/pager_test.go index b905fc1fb..ae517cab2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/pager_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/pager/pager_test.go @@ -17,11 +17,11 @@ limitations under the License. package pager import ( + "context" "fmt" "reflect" "testing" - "golang.org/x/net/context" "k8s.io/apimachinery/pkg/api/errors" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/record/event.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/record/event.go index b5ec44650..168dfa80c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/record/event.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/record/event.go @@ -72,6 +72,9 @@ type EventRecorder interface { // PastEventf is just like Eventf, but with an option to specify the event's 'timestamp' field. PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) + + // AnnotatedEventf is just like eventf, but with annotations attached + AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) } // EventBroadcaster knows how to receive events and send them to any EventSink, watcher, or log. @@ -225,11 +228,7 @@ func (eventBroadcaster *eventBroadcasterImpl) StartEventWatcher(eventHandler fun watcher := eventBroadcaster.Watch() go func() { defer utilruntime.HandleCrash() - for { - watchEvent, open := <-watcher.ResultChan() - if !open { - return - } + for watchEvent := range watcher.ResultChan() { event, ok := watchEvent.Object.(*v1.Event) if !ok { // This is all local, so there's no reason this should @@ -254,7 +253,7 @@ type recorderImpl struct { clock clock.Clock } -func (recorder *recorderImpl) generateEvent(object runtime.Object, timestamp metav1.Time, eventtype, reason, message string) { +func (recorder *recorderImpl) generateEvent(object runtime.Object, annotations map[string]string, timestamp metav1.Time, eventtype, reason, message string) { ref, err := ref.GetReference(recorder.scheme, object) if err != nil { glog.Errorf("Could not construct reference to: '%#v' due to: '%v'. Will not report event: '%v' '%v' '%v'", object, err, eventtype, reason, message) @@ -266,7 +265,7 @@ func (recorder *recorderImpl) generateEvent(object runtime.Object, timestamp met return } - event := recorder.makeEvent(ref, eventtype, reason, message) + event := recorder.makeEvent(ref, annotations, eventtype, reason, message) event.Source = recorder.source go func() { @@ -285,7 +284,7 @@ func validateEventType(eventtype string) bool { } func (recorder *recorderImpl) Event(object runtime.Object, eventtype, reason, message string) { - recorder.generateEvent(object, metav1.Now(), eventtype, reason, message) + recorder.generateEvent(object, nil, metav1.Now(), eventtype, reason, message) } func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) { @@ -293,10 +292,14 @@ func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, m } func (recorder *recorderImpl) PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) { - recorder.generateEvent(object, timestamp, eventtype, reason, fmt.Sprintf(messageFmt, args...)) + recorder.generateEvent(object, nil, timestamp, eventtype, reason, fmt.Sprintf(messageFmt, args...)) +} + +func (recorder *recorderImpl) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + recorder.generateEvent(object, annotations, metav1.Now(), eventtype, reason, fmt.Sprintf(messageFmt, args...)) } -func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, eventtype, reason, message string) *v1.Event { +func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, annotations map[string]string, eventtype, reason, message string) *v1.Event { t := metav1.Time{Time: recorder.clock.Now()} namespace := ref.Namespace if namespace == "" { @@ -304,8 +307,9 @@ func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, eventtype, reas } return &v1.Event{ ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%v.%x", ref.Name, t.UnixNano()), - Namespace: namespace, + Name: fmt.Sprintf("%v.%x", ref.Name, t.UnixNano()), + Namespace: namespace, + Annotations: annotations, }, InvolvedObject: *ref, Reason: reason, diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/record/fake.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/record/fake.go index c0e8eedbb..6e031daaf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/record/fake.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/record/fake.go @@ -45,6 +45,10 @@ func (f *FakeRecorder) Eventf(object runtime.Object, eventtype, reason, messageF func (f *FakeRecorder) PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) { } +func (f *FakeRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { + f.Eventf(object, eventtype, reason, messageFmt, args) +} + // NewFakeRecorder creates new fake event recorder with event channel with // buffer of given size. func NewFakeRecorder(bufferSize int) *FakeRecorder { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/BUILD index 47da958ab..f23e51dd0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/BUILD @@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( @@ -29,3 +30,14 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["ref_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/ref.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/ref.go index 58b60fd5d..573d948a9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/ref.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/ref.go @@ -86,10 +86,14 @@ func GetReference(scheme *runtime.Scheme, obj runtime.Object) (*v1.ObjectReferen } // example paths: ///* parts := strings.Split(selfLinkUrl.Path, "/") - if len(parts) < 3 { + if len(parts) < 4 { return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version) } - version = parts[2] + if parts[1] == "api" { + version = parts[2] + } else { + version = parts[2] + "/" + parts[3] + } } // only has list metadata diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/ref_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/ref_test.go new file mode 100644 index 000000000..b0cf06a97 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/reference/ref_test.go @@ -0,0 +1,72 @@ +/* +Copyright 2018 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 reference + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +type TestRuntimeObj struct { + metav1.TypeMeta + metav1.ObjectMeta +} + +func (o *TestRuntimeObj) DeepCopyObject() runtime.Object { + panic("die") +} + +func TestGetReferenceRefVersion(t *testing.T) { + tests := []struct { + name string + input *TestRuntimeObj + expectedRefVersion string + }{ + { + name: "api from selflink", + input: &TestRuntimeObj{ + ObjectMeta: metav1.ObjectMeta{SelfLink: "/api/v1/namespaces"}, + }, + expectedRefVersion: "v1", + }, + { + name: "foo.group/v3 from selflink", + input: &TestRuntimeObj{ + ObjectMeta: metav1.ObjectMeta{SelfLink: "/apis/foo.group/v3/namespaces"}, + }, + expectedRefVersion: "foo.group/v3", + }, + } + + scheme := runtime.NewScheme() + scheme.AddKnownTypes(schema.GroupVersion{Group: "this", Version: "is ignored"}, &TestRuntimeObj{}) + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ref, err := GetReference(scheme, test.input) + if err != nil { + t.Fatal(err) + } + if test.expectedRefVersion != ref.APIVersion { + t.Errorf("expected %q, got %q", test.expectedRefVersion, ref.APIVersion) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache.go index 83291c575..7cffe2a5f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache.go @@ -43,6 +43,7 @@ type tlsCacheKey struct { caData string certData string keyData string + getCert string serverName string dial string } @@ -52,7 +53,7 @@ func (t tlsCacheKey) String() string { if len(t.keyData) > 0 { keyText = "" } - return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, serverName:%s, dial:%s", t.insecure, t.caData, t.certData, keyText, t.serverName, t.dial) + return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, getCert: %s, serverName:%s, dial:%s", t.insecure, t.caData, t.certData, keyText, t.getCert, t.serverName, t.dial) } func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { @@ -85,7 +86,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { dial = (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, - }).Dial + }).DialContext } // Cache a single transport for these options c.transports[key] = utilnet.SetTransportDefaults(&http.Transport{ @@ -93,7 +94,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { TLSHandshakeTimeout: 10 * time.Second, TLSClientConfig: tlsConfig, MaxIdleConnsPerHost: idleConnsPerHost, - Dial: dial, + DialContext: dial, }) return c.transports[key], nil } @@ -109,6 +110,7 @@ func tlsConfigKey(c *Config) (tlsCacheKey, error) { caData: string(c.TLS.CAData), certData: string(c.TLS.CertData), keyData: string(c.TLS.KeyData), + getCert: fmt.Sprintf("%p", c.TLS.GetCert), serverName: c.TLS.ServerName, dial: fmt.Sprintf("%p", c.Dial), }, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache_test.go index d3d14099d..9b740cdec 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache_test.go @@ -17,6 +17,8 @@ limitations under the License. package transport import ( + "context" + "crypto/tls" "net" "net/http" "testing" @@ -52,10 +54,12 @@ func TestTLSConfigKey(t *testing.T) { } // Make sure config fields that affect the tls config affect the cache key + dialer := net.Dialer{} + getCert := func() (*tls.Certificate, error) { return nil, nil } uniqueConfigurations := map[string]*Config{ "no tls": {}, - "dialer": {Dial: net.Dial}, - "dialer2": {Dial: func(network, address string) (net.Conn, error) { return nil, nil }}, + "dialer": {Dial: dialer.DialContext}, + "dialer2": {Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil }}, "insecure": {TLS: TLSConfig{Insecure: true}}, "cadata 1": {TLS: TLSConfig{CAData: []byte{1}}}, "cadata 2": {TLS: TLSConfig{CAData: []byte{2}}}, @@ -104,6 +108,24 @@ func TestTLSConfigKey(t *testing.T) { KeyData: []byte{1}, }, }, + "getCert1": { + TLS: TLSConfig{ + KeyData: []byte{1}, + GetCert: getCert, + }, + }, + "getCert2": { + TLS: TLSConfig{ + KeyData: []byte{1}, + GetCert: func() (*tls.Certificate, error) { return nil, nil }, + }, + }, + "getCert1, key 2": { + TLS: TLSConfig{ + KeyData: []byte{2}, + GetCert: getCert, + }, + }, } for nameA, valueA := range uniqueConfigurations { for nameB, valueB := range uniqueConfigurations { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/config.go index af347dafe..4081c23e7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/config.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/config.go @@ -17,6 +17,8 @@ limitations under the License. package transport import ( + "context" + "crypto/tls" "net" "net/http" ) @@ -53,7 +55,7 @@ type Config struct { WrapTransport func(rt http.RoundTripper) http.RoundTripper // Dial specifies the dial function for creating unencrypted TCP connections. - Dial func(network, addr string) (net.Conn, error) + Dial func(ctx context.Context, network, address string) (net.Conn, error) } // ImpersonationConfig has all the available impersonation options @@ -83,7 +85,12 @@ func (c *Config) HasTokenAuth() bool { // HasCertAuth returns whether the configuration has certificate authentication or not. func (c *Config) HasCertAuth() bool { - return len(c.TLS.CertData) != 0 || len(c.TLS.CertFile) != 0 + return (len(c.TLS.CertData) != 0 || len(c.TLS.CertFile) != 0) && (len(c.TLS.KeyData) != 0 || len(c.TLS.KeyFile) != 0) +} + +// HasCertCallbacks returns whether the configuration has certificate callback or not. +func (c *Config) HasCertCallback() bool { + return c.TLS.GetCert != nil } // TLSConfig holds the information needed to set up a TLS transport. @@ -98,4 +105,6 @@ type TLSConfig struct { CAData []byte // Bytes of the PEM-encoded server trusted root certificates. Supercedes CAFile. CertData []byte // Bytes of the PEM-encoded client certificate. Supercedes CertFile. KeyData []byte // Bytes of the PEM-encoded client key. Supercedes KeyFile. + + GetCert func() (*tls.Certificate, error) // Callback that returns a TLS client certificate. CertData, CertFile, KeyData and KeyFile supercede this field. } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/round_trippers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/round_trippers.go index c728b1877..316a5c0d0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/round_trippers.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/round_trippers.go @@ -129,7 +129,7 @@ func SetAuthProxyHeaders(req *http.Request, username string, groups []string, ex } for key, values := range extra { for _, value := range values { - req.Header.Add("X-Remote-Extra-"+key, value) + req.Header.Add("X-Remote-Extra-"+headerKeyEscape(key), value) } } } @@ -246,7 +246,7 @@ func (rt *impersonatingRoundTripper) RoundTrip(req *http.Request) (*http.Respons } for k, vv := range rt.impersonate.Extra { for _, v := range vv { - req.Header.Add(ImpersonateUserExtraHeaderPrefix+k, v) + req.Header.Add(ImpersonateUserExtraHeaderPrefix+headerKeyEscape(k), v) } } @@ -335,7 +335,7 @@ func (r *requestInfo) toCurl() string { } } - return fmt.Sprintf("curl -k -v -X%s %s %s", r.RequestVerb, headers, r.RequestURL) + return fmt.Sprintf("curl -k -v -X%s %s '%s'", r.RequestVerb, headers, r.RequestURL) } // debuggingRoundTripper will display information about the requests passing @@ -422,3 +422,110 @@ func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, e func (rt *debuggingRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.delegatedRoundTripper } + +func legalHeaderByte(b byte) bool { + return int(b) < len(legalHeaderKeyBytes) && legalHeaderKeyBytes[b] +} + +func shouldEscape(b byte) bool { + // url.PathUnescape() returns an error if any '%' is not followed by two + // hexadecimal digits, so we'll intentionally encode it. + return !legalHeaderByte(b) || b == '%' +} + +func headerKeyEscape(key string) string { + buf := strings.Builder{} + for i := 0; i < len(key); i++ { + b := key[i] + if shouldEscape(b) { + // %-encode bytes that should be escaped: + // https://tools.ietf.org/html/rfc3986#section-2.1 + fmt.Fprintf(&buf, "%%%02X", b) + continue + } + buf.WriteByte(b) + } + return buf.String() +} + +// legalHeaderKeyBytes was copied from net/http/lex.go's isTokenTable. +// See https://httpwg.github.io/specs/rfc7230.html#rule.token.separators +var legalHeaderKeyBytes = [127]bool{ + '%': true, + '!': true, + '#': true, + '$': true, + '&': true, + '\'': true, + '*': true, + '+': true, + '-': true, + '.': true, + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + 'A': true, + 'B': true, + 'C': true, + 'D': true, + 'E': true, + 'F': true, + 'G': true, + 'H': true, + 'I': true, + 'J': true, + 'K': true, + 'L': true, + 'M': true, + 'N': true, + 'O': true, + 'P': true, + 'Q': true, + 'R': true, + 'S': true, + 'T': true, + 'U': true, + 'W': true, + 'V': true, + 'X': true, + 'Y': true, + 'Z': true, + '^': true, + '_': true, + '`': true, + 'a': true, + 'b': true, + 'c': true, + 'd': true, + 'e': true, + 'f': true, + 'g': true, + 'h': true, + 'i': true, + 'j': true, + 'k': true, + 'l': true, + 'm': true, + 'n': true, + 'o': true, + 'p': true, + 'q': true, + 'r': true, + 's': true, + 't': true, + 'u': true, + 'v': true, + 'w': true, + 'x': true, + 'y': true, + 'z': true, + '|': true, + '~': true, +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/round_trippers_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/round_trippers_test.go index d5ffc6bde..74d3dc212 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/round_trippers_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/round_trippers_test.go @@ -18,6 +18,7 @@ package transport import ( "net/http" + "net/url" "reflect" "strings" "testing" @@ -125,6 +126,32 @@ func TestImpersonationRoundTripper(t *testing.T) { ImpersonateUserExtraHeaderPrefix + "Second": {"B", "b"}, }, }, + { + name: "escape handling", + impersonationConfig: ImpersonationConfig{ + UserName: "user", + Extra: map[string][]string{ + "test.example.com/thing.thing": {"A", "a"}, + }, + }, + expected: map[string][]string{ + ImpersonateUserHeader: {"user"}, + ImpersonateUserExtraHeaderPrefix + `Test.example.com%2fthing.thing`: {"A", "a"}, + }, + }, + { + name: "double escape handling", + impersonationConfig: ImpersonationConfig{ + UserName: "user", + Extra: map[string][]string{ + "test.example.com/thing.thing%20another.thing": {"A", "a"}, + }, + }, + expected: map[string][]string{ + ImpersonateUserHeader: {"user"}, + ImpersonateUserExtraHeaderPrefix + `Test.example.com%2fthing.thing%2520another.thing`: {"A", "a"}, + }, + }, } for _, tc := range tcs { @@ -159,9 +186,10 @@ func TestImpersonationRoundTripper(t *testing.T) { func TestAuthProxyRoundTripper(t *testing.T) { for n, tc := range map[string]struct { - username string - groups []string - extra map[string][]string + username string + groups []string + extra map[string][]string + expectedExtra map[string][]string }{ "allfields": { username: "user", @@ -170,6 +198,34 @@ func TestAuthProxyRoundTripper(t *testing.T) { "one": {"alpha", "bravo"}, "two": {"charlie", "delta"}, }, + expectedExtra: map[string][]string{ + "one": {"alpha", "bravo"}, + "two": {"charlie", "delta"}, + }, + }, + "escaped extra": { + username: "user", + groups: []string{"groupA", "groupB"}, + extra: map[string][]string{ + "one": {"alpha", "bravo"}, + "example.com/two": {"charlie", "delta"}, + }, + expectedExtra: map[string][]string{ + "one": {"alpha", "bravo"}, + "example.com%2ftwo": {"charlie", "delta"}, + }, + }, + "double escaped extra": { + username: "user", + groups: []string{"groupA", "groupB"}, + extra: map[string][]string{ + "one": {"alpha", "bravo"}, + "example.com/two%20three": {"charlie", "delta"}, + }, + expectedExtra: map[string][]string{ + "one": {"alpha", "bravo"}, + "example.com%2ftwo%2520three": {"charlie", "delta"}, + }, }, } { rt := &testRoundTripper{} @@ -210,9 +266,64 @@ func TestAuthProxyRoundTripper(t *testing.T) { actualExtra[extraKey] = append(actualExtra[key], values...) } } - if e, a := tc.extra, actualExtra; !reflect.DeepEqual(e, a) { + if e, a := tc.expectedExtra, actualExtra; !reflect.DeepEqual(e, a) { t.Errorf("%s expected %v, got %v", n, e, a) continue } } } + +// TestHeaderEscapeRoundTrip tests to see if foo == url.PathUnescape(headerEscape(foo)) +// This behavior is important for client -> API server transmission of extra values. +func TestHeaderEscapeRoundTrip(t *testing.T) { + t.Parallel() + testCases := []struct { + name string + key string + }{ + { + name: "alpha", + key: "alphabetical", + }, + { + name: "alphanumeric", + key: "alph4num3r1c", + }, + { + name: "percent encoded", + key: "percent%20encoded", + }, + { + name: "almost percent encoded", + key: "almost%zzpercent%xxencoded", + }, + { + name: "illegal char & percent encoding", + key: "example.com/percent%20encoded", + }, + { + name: "weird unicode stuff", + key: "example.com/ᛒᚥᛏᛖᚥᚢとロビン", + }, + { + name: "header legal chars", + key: "abc123!#$+.-_*\\^`~|'", + }, + { + name: "legal path, illegal header", + key: "@=:", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + escaped := headerKeyEscape(tc.key) + unescaped, err := url.PathUnescape(escaped) + if err != nil { + t.Fatalf("url.PathUnescape(%q) returned error: %v", escaped, err) + } + if tc.key != unescaped { + t.Errorf("url.PathUnescape(headerKeyEscape(%q)) returned %q, wanted %q", tc.key, unescaped, tc.key) + } + }) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/transport.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/transport.go index c2bb7ae5e..c19739fdf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/transport.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/transport.go @@ -28,7 +28,7 @@ import ( // or transport level security defined by the provided Config. func New(config *Config) (http.RoundTripper, error) { // Set transport level security - if config.Transport != nil && (config.HasCA() || config.HasCertAuth() || config.TLS.Insecure) { + if config.Transport != nil && (config.HasCA() || config.HasCertAuth() || config.HasCertCallback() || config.TLS.Insecure) { return nil, fmt.Errorf("using a custom transport with TLS certificate options or the insecure flag is not allowed") } @@ -52,7 +52,7 @@ func New(config *Config) (http.RoundTripper, error) { // TLSConfigFor returns a tls.Config that will provide the transport level security defined // by the provided Config. Will return nil if no transport level security is requested. func TLSConfigFor(c *Config) (*tls.Config, error) { - if !(c.HasCA() || c.HasCertAuth() || c.TLS.Insecure || len(c.TLS.ServerName) > 0) { + if !(c.HasCA() || c.HasCertAuth() || c.HasCertCallback() || c.TLS.Insecure || len(c.TLS.ServerName) > 0) { return nil, nil } if c.HasCA() && c.TLS.Insecure { @@ -75,12 +75,40 @@ func TLSConfigFor(c *Config) (*tls.Config, error) { tlsConfig.RootCAs = rootCertPool(c.TLS.CAData) } + var staticCert *tls.Certificate if c.HasCertAuth() { + // If key/cert were provided, verify them before setting up + // tlsConfig.GetClientCertificate. cert, err := tls.X509KeyPair(c.TLS.CertData, c.TLS.KeyData) if err != nil { return nil, err } - tlsConfig.Certificates = []tls.Certificate{cert} + staticCert = &cert + } + + if c.HasCertAuth() || c.HasCertCallback() { + tlsConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { + // Note: static key/cert data always take precedence over cert + // callback. + if staticCert != nil { + return staticCert, nil + } + if c.HasCertCallback() { + cert, err := c.TLS.GetCert() + if err != nil { + return nil, err + } + // GetCert may return empty value, meaning no cert. + if cert != nil { + return cert, nil + } + } + + // Both c.TLS.CertData/KeyData were unset and GetCert didn't return + // anything. Return an empty tls.Certificate, no client cert will + // be sent to the server. + return &tls.Certificate{}, nil + } } return tlsConfig, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/transport_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/transport_test.go index 8de751562..2e9896a08 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/transport_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/transport_test.go @@ -17,6 +17,8 @@ limitations under the License. package transport import ( + "crypto/tls" + "errors" "net/http" "testing" ) @@ -94,6 +96,8 @@ func TestNew(t *testing.T) { Config *Config Err bool TLS bool + TLSCert bool + TLSErr bool Default bool }{ "default transport": { @@ -135,7 +139,8 @@ func TestNew(t *testing.T) { }, "cert transport": { - TLS: true, + TLS: true, + TLSCert: true, Config: &Config{ TLS: TLSConfig{ CAData: []byte(rootCACert), @@ -165,7 +170,8 @@ func TestNew(t *testing.T) { }, }, "key data overriding bad file cert transport": { - TLS: true, + TLS: true, + TLSCert: true, Config: &Config{ TLS: TLSConfig{ CAData: []byte(rootCACert), @@ -175,37 +181,108 @@ func TestNew(t *testing.T) { }, }, }, + "callback cert and key": { + TLS: true, + TLSCert: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + crt, err := tls.X509KeyPair([]byte(certData), []byte(keyData)) + return &crt, err + }, + }, + }, + }, + "cert callback error": { + TLS: true, + TLSCert: true, + TLSErr: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + return nil, errors.New("GetCert failure") + }, + }, + }, + }, + "cert data overrides empty callback result": { + TLS: true, + TLSCert: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + return nil, nil + }, + CertData: []byte(certData), + KeyData: []byte(keyData), + }, + }, + }, + "callback returns nothing": { + TLS: true, + TLSCert: true, + Config: &Config{ + TLS: TLSConfig{ + CAData: []byte(rootCACert), + GetCert: func() (*tls.Certificate, error) { + return nil, nil + }, + }, + }, + }, } for k, testCase := range testCases { - transport, err := New(testCase.Config) - switch { - case testCase.Err && err == nil: - t.Errorf("%s: unexpected non-error", k) - continue - case !testCase.Err && err != nil: - t.Errorf("%s: unexpected error: %v", k, err) - continue - } - - switch { - case testCase.Default && transport != http.DefaultTransport: - t.Errorf("%s: expected the default transport, got %#v", k, transport) - continue - case !testCase.Default && transport == http.DefaultTransport: - t.Errorf("%s: expected non-default transport, got %#v", k, transport) - continue - } - - // We only know how to check TLSConfig on http.Transports - if transport, ok := transport.(*http.Transport); ok { + t.Run(k, func(t *testing.T) { + rt, err := New(testCase.Config) + switch { + case testCase.Err && err == nil: + t.Fatal("unexpected non-error") + case !testCase.Err && err != nil: + t.Fatalf("unexpected error: %v", err) + } + if testCase.Err { + return + } + + switch { + case testCase.Default && rt != http.DefaultTransport: + t.Fatalf("got %#v, expected the default transport", rt) + case !testCase.Default && rt == http.DefaultTransport: + t.Fatalf("got %#v, expected non-default transport", rt) + } + + // We only know how to check TLSConfig on http.Transports + transport := rt.(*http.Transport) switch { case testCase.TLS && transport.TLSClientConfig == nil: - t.Errorf("%s: expected TLSClientConfig, got %#v", k, transport) - continue + t.Fatalf("got %#v, expected TLSClientConfig", transport) case !testCase.TLS && transport.TLSClientConfig != nil: - t.Errorf("%s: expected no TLSClientConfig, got %#v", k, transport) - continue + t.Fatalf("got %#v, expected no TLSClientConfig", transport) + } + if !testCase.TLS { + return + } + + switch { + case testCase.TLSCert && transport.TLSClientConfig.GetClientCertificate == nil: + t.Fatalf("got %#v, expected TLSClientConfig.GetClientCertificate", transport.TLSClientConfig) + case !testCase.TLSCert && transport.TLSClientConfig.GetClientCertificate != nil: + t.Fatalf("got %#v, expected no TLSClientConfig.GetClientCertificate", transport.TLSClientConfig) + } + if !testCase.TLSCert { + return + } + + _, err = transport.TLSClientConfig.GetClientCertificate(nil) + switch { + case testCase.TLSErr && err == nil: + t.Error("got nil error from GetClientCertificate, expected non-nil") + case !testCase.TLSErr && err != nil: + t.Errorf("got error from GetClientCertificate: %q, expected nil", err) } - } + }) } } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/buffer/ring_growing_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/buffer/ring_growing_test.go index 231b836c0..31a4c079d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/buffer/ring_growing_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/buffer/ring_growing_test.go @@ -39,7 +39,7 @@ func TestGrowth(t *testing.T) { } assert.Equalf(t, x, read, "expected to have read %d items: %d", x, read) assert.Zerof(t, g.readable, "expected readable to be zero: %d", g.readable) - assert.Equalf(t, g.n, 16, "expected N to be 16: %d", g.n) + assert.Equalf(t, 16, g.n, "expected N to be 16: %d", g.n) } func TestEmpty(t *testing.T) { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/BUILD index 799979d46..fc2a59be0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/BUILD @@ -24,9 +24,6 @@ go_library( "io.go", "pem.go", ], - data = [ - "testdata/dontUseThisKey.pem", - ], importpath = "k8s.io/client-go/util/cert", ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/io.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/io.go index a41f8054a..a57bf09d5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/io.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/io.go @@ -17,7 +17,11 @@ limitations under the License. package cert import ( + "crypto" + "crypto/ecdsa" + "crypto/rsa" "crypto/x509" + "encoding/pem" "fmt" "io/ioutil" "os" @@ -84,7 +88,8 @@ func WriteKey(keyPath string, data []byte) error { // can't find one, it will generate a new key and store it there. func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) { loadedData, err := ioutil.ReadFile(keyPath) - if err == nil { + // Call verifyKeyData to ensure the file wasn't empty/corrupt. + if err == nil && verifyKeyData(loadedData) { return loadedData, false, err } if !os.IsNotExist(err) { @@ -101,6 +106,27 @@ func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err return generatedData, true, nil } +// MarshalPrivateKeyToPEM converts a known private key type of RSA or ECDSA to +// a PEM encoded block or returns an error. +func MarshalPrivateKeyToPEM(privateKey crypto.PrivateKey) ([]byte, error) { + switch t := privateKey.(type) { + case *ecdsa.PrivateKey: + derBytes, err := x509.MarshalECPrivateKey(t) + if err != nil { + return nil, err + } + privateKeyPemBlock := &pem.Block{ + Type: ECPrivateKeyBlockType, + Bytes: derBytes, + } + return pem.EncodeToMemory(privateKeyPemBlock), nil + case *rsa.PrivateKey: + return EncodePrivateKeyPEM(t), nil + default: + return nil, fmt.Errorf("private key is not a recognized type: %T", privateKey) + } +} + // NewPool returns an x509.CertPool containing the certificates in the given PEM-encoded file. // Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates func NewPool(filename string) (*x509.CertPool, error) { @@ -156,3 +182,12 @@ func PublicKeysFromFile(file string) ([]interface{}, error) { } return keys, nil } + +// verifyKeyData returns true if the provided data appears to be a valid private key. +func verifyKeyData(data []byte) bool { + if len(data) == 0 { + return false + } + _, err := ParsePrivateKeyPEM(data) + return err == nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/certificate/certificate_store.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/certificate/certificate_store.go index 42a40dcdf..f54bd6586 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/certificate/certificate_store.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/certificate/certificate_store.go @@ -46,6 +46,15 @@ type fileStore struct { keyFile string } +// FileStore is a store that provides certificate retrieval as well as +// the path on disk of the current PEM. +type FileStore interface { + Store + // CurrentPath returns the path on disk of the current certificate/key + // pair encoded as PEM files. + CurrentPath() string +} + // NewFileStore returns a concrete implementation of a Store that is based on // storing the cert/key pairs in a single file per pair on disk in the // designated directory. When starting up it will look for the currently @@ -64,7 +73,7 @@ func NewFileStore( certDirectory string, keyDirectory string, certFile string, - keyFile string) (Store, error) { + keyFile string) (FileStore, error) { s := fileStore{ pairNamePrefix: pairNamePrefix, @@ -79,6 +88,11 @@ func NewFileStore( return &s, nil } +// CurrentPath returns the path to the current version of these certificates. +func (s *fileStore) CurrentPath() string { + return filepath.Join(s.certDirectory, s.filename(currentPair)) +} + // recover checks if there is a certificate rotation that was interrupted while // progress, and if so, attempts to recover to a good state. func (s *fileStore) recover() error { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/connrotation/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/connrotation/BUILD new file mode 100644 index 000000000..5744cfd1e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/connrotation/BUILD @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["connrotation.go"], + importpath = "k8s.io/client-go/util/connrotation", + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["connrotation_test.go"], + embed = [":go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/connrotation/connrotation.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/connrotation/connrotation.go new file mode 100644 index 000000000..235a9e019 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/connrotation/connrotation.go @@ -0,0 +1,105 @@ +/* +Copyright 2018 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 connrotation implements a connection dialer that tracks and can close +// all created connections. +// +// This is used for credential rotation of long-lived connections, when there's +// no way to re-authenticate on a live connection. +package connrotation + +import ( + "context" + "net" + "sync" +) + +// DialFunc is a shorthand for signature of net.DialContext. +type DialFunc func(ctx context.Context, network, address string) (net.Conn, error) + +// Dialer opens connections through Dial and tracks them. +type Dialer struct { + dial DialFunc + + mu sync.Mutex + conns map[*closableConn]struct{} +} + +// NewDialer creates a new Dialer instance. +// +// If dial is not nil, it will be used to create new underlying connections. +// Otherwise net.DialContext is used. +func NewDialer(dial DialFunc) *Dialer { + return &Dialer{ + dial: dial, + conns: make(map[*closableConn]struct{}), + } +} + +// CloseAll forcibly closes all tracked connections. +// +// Note: new connections may get created before CloseAll returns. +func (d *Dialer) CloseAll() { + d.mu.Lock() + conns := d.conns + d.conns = make(map[*closableConn]struct{}) + d.mu.Unlock() + + for conn := range conns { + conn.Close() + } +} + +// Dial creates a new tracked connection. +func (d *Dialer) Dial(network, address string) (net.Conn, error) { + return d.DialContext(context.Background(), network, address) +} + +// DialContext creates a new tracked connection. +func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { + conn, err := d.dial(ctx, network, address) + if err != nil { + return nil, err + } + + closable := &closableConn{Conn: conn} + + // Start tracking the connection + d.mu.Lock() + d.conns[closable] = struct{}{} + d.mu.Unlock() + + // When the connection is closed, remove it from the map. This will + // be no-op if the connection isn't in the map, e.g. if CloseAll() + // is called. + closable.onClose = func() { + d.mu.Lock() + delete(d.conns, closable) + d.mu.Unlock() + } + + return closable, nil +} + +type closableConn struct { + onClose func() + net.Conn +} + +func (c *closableConn) Close() error { + go c.onClose() + return c.Conn.Close() +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/connrotation/connrotation_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/connrotation/connrotation_test.go new file mode 100644 index 000000000..a618f2961 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/connrotation/connrotation_test.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 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 connrotation + +import ( + "context" + "net" + "testing" + "time" +) + +func TestCloseAll(t *testing.T) { + closed := make(chan struct{}) + dialFn := func(ctx context.Context, network, address string) (net.Conn, error) { + return closeOnlyConn{onClose: func() { closed <- struct{}{} }}, nil + } + dialer := NewDialer(dialFn) + + const numConns = 10 + + // Outer loop to ensure Dialer is re-usable after CloseAll. + for i := 0; i < 5; i++ { + for j := 0; j < numConns; j++ { + if _, err := dialer.Dial("", ""); err != nil { + t.Fatal(err) + } + } + dialer.CloseAll() + for j := 0; j < numConns; j++ { + select { + case <-closed: + case <-time.After(time.Second): + t.Fatalf("iteration %d: 1s after CloseAll only %d/%d connections closed", i, j, numConns) + } + } + } +} + +type closeOnlyConn struct { + net.Conn + onClose func() +} + +func (c closeOnlyConn) Close() error { + go c.onClose() + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/workqueue/delaying_queue.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/workqueue/delaying_queue.go index c62ed32ef..a37177425 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/workqueue/delaying_queue.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/workqueue/delaying_queue.go @@ -45,7 +45,7 @@ func newDelayingQueue(clock clock.Clock, name string) DelayingInterface { ret := &delayingType{ Interface: NewNamed(name), clock: clock, - heartbeat: clock.Tick(maxWait), + heartbeat: clock.NewTicker(maxWait), stopCh: make(chan struct{}), waitingForAddCh: make(chan *waitFor, 1000), metrics: newRetryMetrics(name), @@ -67,10 +67,7 @@ type delayingType struct { stopCh chan struct{} // heartbeat ensures we wait no more than maxWait before firing - // - // TODO: replace with Ticker (and add to clock) so this can be cleaned up. - // clock.Tick will leak. - heartbeat <-chan time.Time + heartbeat clock.Ticker // waitingForAddCh is a buffered channel that feeds waitingForAdd waitingForAddCh chan *waitFor @@ -138,6 +135,7 @@ func (pq waitForPriorityQueue) Peek() interface{} { func (q *delayingType) ShutDown() { q.Interface.ShutDown() close(q.stopCh) + q.heartbeat.Stop() } // AddAfter adds the given item to the work queue after the given delay @@ -209,7 +207,7 @@ func (q *delayingType) waitingLoop() { case <-q.stopCh: return - case <-q.heartbeat: + case <-q.heartbeat.C(): // continue the loop, which will add ready items case <-nextReadyAt: diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go index 32d7fc906..3fbe07d0d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go @@ -30,7 +30,7 @@ func TestRateLimitingQueue(t *testing.T) { delayingQueue := &delayingType{ Interface: New(), clock: fakeClock, - heartbeat: fakeClock.Tick(maxWait), + heartbeat: fakeClock.NewTicker(maxWait), stopCh: make(chan struct{}), waitingForAddCh: make(chan *waitFor, 1000), metrics: newRetryMetrics(""), diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/Godeps/Godeps.json index f839edb90..021cf1458 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "k8s.io/code-generator", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], @@ -260,11 +260,11 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/generators", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/install/install.go index b5182d690..d056c5b78 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/code-generator/_examples/apiserver/apis/example" "k8s.io/code-generator/_examples/apiserver/apis/example/v1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: example.SchemeGroupVersion.Group, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: example.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(example.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/doc.go index 242d3904d..5b6bd5b30 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/doc.go @@ -15,6 +15,7 @@ limitations under the License. */ // +k8s:deepcopy-gen=package +// +k8s:defaulter-gen=TypeMeta // +k8s:conversion-gen=k8s.io/code-generator/_examples/apiserver/apis/example // +groupName=example.apiserver.code-generator.k8s.io package v1 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.conversion.go index 66667f1b8..811031685 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.deepcopy.go index 1e4402a82..dae52ff12 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/zz_generated.deepcopy.go index 291de95fc..980112fa8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/install/install.go index ef241a33f..1e786f5c5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/code-generator/_examples/apiserver/apis/example2" "k8s.io/code-generator/_examples/apiserver/apis/example2/v1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: example2.SchemeGroupVersion.Group, - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: example2.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(example2.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/doc.go index 41e271d22..36bd4549c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/doc.go @@ -15,6 +15,7 @@ limitations under the License. */ // +k8s:deepcopy-gen=package +// +k8s:defaulter-gen=TypeMeta // +groupName=example.test.apiserver.code-generator.k8s.io // +k8s:conversion-gen=k8s.io/code-generator/_examples/apiserver/apis/example2 // +groupGoName=SecondExample diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.conversion.go index e73a0f630..88bf603d0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.deepcopy.go index 1e4402a82..dae52ff12 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.defaults.go index 40d9ab00e..cce2e603a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/zz_generated.deepcopy.go index 284ecd2da..f9b317e57 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/apis/example2/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/clientset.go index 0cb86bf5c..ff88d121c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package internalversion import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -78,7 +77,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/doc.go index 50398f9ef..6c970b092 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/clientset_generated.go index efc0095b8..37f1b724d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,9 +43,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -55,7 +56,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/register.go index ef0ba8fc2..58b47c9fa 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/register.go index e3b2cf663..97b03068e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,10 +19,6 @@ limitations under the License. package scheme import ( - os "os" - - announced "k8s.io/apimachinery/pkg/apimachinery/announced" - registered "k8s.io/apimachinery/pkg/apimachinery/registered" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -35,16 +31,13 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) -var Registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) -var GroupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - func init() { v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - Install(GroupFactoryRegistry, Registry, Scheme) + Install(Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - example.Install(groupFactoryRegistry, registry, scheme) - secondexample.Install(groupFactoryRegistry, registry, scheme) +func Install(scheme *runtime.Scheme) { + example.Install(scheme) + secondexample.Install(scheme) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/example_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/example_client.go index e99d41f98..61d99cad0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/example_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *ExampleClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("example.apiserver.code-generator.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("example.apiserver.code-generator.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("example.apiserver.code-generator.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_example_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_example_client.go index 71e9e11cb..90564e449 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_example_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_testtype.go index 4f268fb81..7b247ca95 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example.TestTypeList, if label == nil { label = labels.Everything() } - list := &example.TestTypeList{} + list := &example.TestTypeList{ListMeta: obj.(*example.TestTypeList).ListMeta} for _, item := range obj.(*example.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/generated_expansion.go index 0cdfc3128..50bdbd254 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/testtype.go index 6cfbcb36d..d19392e85 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/example2_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/example2_client.go index b0e673a83..0fcc7baa4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/example2_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *SecondExampleClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("example.test.apiserver.code-generator.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("example.test.apiserver.code-generator.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("example.test.apiserver.code-generator.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_example2_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_example2_client.go index 91751c249..235305e9d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_example2_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_testtype.go index 3e9e6c7a8..2890ff19d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example2.TestTypeList if label == nil { label = labels.Everything() } - list := &example2.TestTypeList{} + list := &example2.TestTypeList{ListMeta: obj.(*example2.TestTypeList).ListMeta} for _, item := range obj.(*example2.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/generated_expansion.go index 0cdfc3128..50bdbd254 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/testtype.go index 77ab9a342..1a2ca7891 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/internalversion/typed/example2/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/clientset.go index c0d337d2e..8ba9799f5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package versioned import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -94,7 +93,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/doc.go index 006b79214..41721ca52 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/clientset_generated.go index fe657f08e..6dce4fed4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,9 +43,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -55,7 +56,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/register.go index 37c3ae6f8..79e200500 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/register.go index 7c7daa6a2..16f0196a8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/example_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/example_client.go index 4cead71e4..743c8ded2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/example_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_example_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_example_client.go index c8bbfe7c4..509a5b427 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_example_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_testtype.go index a0779aaef..100de1809 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example_v1.TestTypeLi if label == nil { label = labels.Everything() } - list := &example_v1.TestTypeList{} + list := &example_v1.TestTypeList{ListMeta: obj.(*example_v1.TestTypeList).ListMeta} for _, item := range obj.(*example_v1.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/generated_expansion.go index 3f19f4e33..d513810d0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/testtype.go index 0e51af495..d9aa3c5d6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/example2_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/example2_client.go index c245b0716..1271c0f19 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/example2_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go index 2c52a1445..1820e182c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_testtype.go index 9b005136f..296975e4d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example2_v1.TestTypeL if label == nil { label = labels.Everything() } - list := &example2_v1.TestTypeList{} + list := &example2_v1.TestTypeList{ListMeta: obj.(*example2_v1.TestTypeList).ListMeta} for _, item := range obj.(*example2_v1.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/generated_expansion.go index 3f19f4e33..d513810d0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/testtype.go index 21e7e0805..f199ee092 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/clientset/versioned/typed/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/interface.go index e014cde14..9cc5d1b0a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/interface.go index ae5abf354..1ccc8f3ca 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/testtype.go index d8cdead8b..84fc62975 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/interface.go index 7aef7a4e2..3a791dd0f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/interface.go index ae5abf354..1ccc8f3ca 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/testtype.go index 48d098232..1d366be5a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/factory.go index 767191e1b..fc4aa0d39 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -33,12 +33,16 @@ import ( internalinterfaces "k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client versioned.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -46,23 +50,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -111,7 +154,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/generic.go index e1273ab31..aee8fad34 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces/factory_interfaces.go index 988e57b54..6318f5284 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/interface.go index 4f0aae2fd..d2a36b3c8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/interface.go index 1ac865c7a..0fd5f8c3b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/testtype.go index f6991dfdd..3745a315d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/interface.go index 843463ddd..9a5b411a1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/interface.go index 1ac865c7a..0fd5f8c3b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/testtype.go index 613fd6933..51518210d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/example2/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/factory.go index 737d5227f..ca6d4defe 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -33,12 +33,16 @@ import ( internalinterfaces "k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client internalversion.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -46,23 +50,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client internalversion.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -111,7 +154,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/generic.go index d0822bbb1..046ccac95 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces/factory_interfaces.go index 80e3603a0..03c679244 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/informers/internalversion/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/expansion_generated.go index 6d32d9754..4bb87150c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/testtype.go index 184c1649a..9daa91bbc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/v1/expansion_generated.go index c5f4333d5..0192e05f0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/v1/testtype.go index 9eee6a69e..a9b3d87c0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/expansion_generated.go index 6d32d9754..4bb87150c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/testtype.go index 24659a2d6..724e63871 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/internalversion/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/expansion_generated.go index c5f4333d5..0192e05f0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/testtype.go index 64c5bb884..8aa178af8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/apiserver/listers/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/doc.go index 08f1279fb..e6614c0da 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/doc.go @@ -15,5 +15,6 @@ limitations under the License. */ // +k8s:deepcopy-gen=package +// +k8s:defaulter-gen=TypeMeta // +groupName=example.crd.code-generator.k8s.io package v1 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/types.go index 5c2ebc4d6..d79ea38b7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/types.go @@ -45,3 +45,30 @@ type TestTypeList struct { type TestTypeStatus struct { Blah string } + +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type ClusterTestTypeList struct { + metav1.TypeMeta + metav1.ListMeta + Items []ClusterTestType +} + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/kubernetes/pkg/apis/autoscaling.Scale +// +genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/kubernetes/pkg/apis/autoscaling.Scale,result=k8s.io/kubernetes/pkg/apis/autoscaling.Scale + +type ClusterTestType struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + // +optional + Status ClusterTestTypeStatus `json:"status,omitempty"` +} + +type ClusterTestTypeStatus struct { + Blah string +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.deepcopy.go index 1e4402a82..a3b4bfa9c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,82 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterTestType) DeepCopyInto(out *ClusterTestType) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterTestType. +func (in *ClusterTestType) DeepCopy() *ClusterTestType { + if in == nil { + return nil + } + out := new(ClusterTestType) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterTestType) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterTestTypeList) DeepCopyInto(out *ClusterTestTypeList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterTestType, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterTestTypeList. +func (in *ClusterTestTypeList) DeepCopy() *ClusterTestTypeList { + if in == nil { + return nil + } + out := new(ClusterTestTypeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterTestTypeList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterTestTypeStatus) DeepCopyInto(out *ClusterTestTypeStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterTestTypeStatus. +func (in *ClusterTestTypeStatus) DeepCopy() *ClusterTestTypeStatus { + if in == nil { + return nil + } + out := new(ClusterTestTypeStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestType) DeepCopyInto(out *TestType) { *out = *in diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.defaults.go new file mode 100644 index 000000000..cce2e603a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example/v1/zz_generated.defaults.go @@ -0,0 +1,32 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/doc.go index 702b71634..6521d83ff 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/doc.go @@ -15,6 +15,7 @@ limitations under the License. */ // +k8s:deepcopy-gen=package +// +k8s:defaulter-gen=TypeMeta // +groupName=example.test.crd.code-generator.k8s.io // +groupGoName=SecondExample package v1 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.deepcopy.go index 1e4402a82..dae52ff12 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.defaults.go new file mode 100644 index 000000000..cce2e603a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/apis/example2/v1/zz_generated.defaults.go @@ -0,0 +1,32 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/clientset.go index fe1447d50..034e06ad0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package versioned import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -94,7 +93,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/doc.go index 006b79214..41721ca52 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/clientset_generated.go index ab158f772..4ad8bba75 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,9 +43,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -55,7 +56,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/register.go index 08ebf3b3c..d91e79dac 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/register.go index 1a2abe6a0..7a5ad4f86 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/clustertesttype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/clustertesttype.go new file mode 100644 index 000000000..a55b859e1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/clustertesttype.go @@ -0,0 +1,193 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1 "k8s.io/code-generator/_examples/crd/apis/example/v1" + scheme "k8s.io/code-generator/_examples/crd/clientset/versioned/scheme" + autoscaling "k8s.io/kubernetes/pkg/apis/autoscaling" +) + +// ClusterTestTypesGetter has a method to return a ClusterTestTypeInterface. +// A group's client should implement this interface. +type ClusterTestTypesGetter interface { + ClusterTestTypes() ClusterTestTypeInterface +} + +// ClusterTestTypeInterface has methods to work with ClusterTestType resources. +type ClusterTestTypeInterface interface { + Create(*v1.ClusterTestType) (*v1.ClusterTestType, error) + Update(*v1.ClusterTestType) (*v1.ClusterTestType, error) + UpdateStatus(*v1.ClusterTestType) (*v1.ClusterTestType, error) + Delete(name string, options *meta_v1.DeleteOptions) error + DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error + Get(name string, options meta_v1.GetOptions) (*v1.ClusterTestType, error) + List(opts meta_v1.ListOptions) (*v1.ClusterTestTypeList, error) + Watch(opts meta_v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ClusterTestType, err error) + GetScale(clusterTestTypeName string, options meta_v1.GetOptions) (*autoscaling.Scale, error) + UpdateScale(clusterTestTypeName string, scale *autoscaling.Scale) (*autoscaling.Scale, error) + + ClusterTestTypeExpansion +} + +// clusterTestTypes implements ClusterTestTypeInterface +type clusterTestTypes struct { + client rest.Interface +} + +// newClusterTestTypes returns a ClusterTestTypes +func newClusterTestTypes(c *ExampleV1Client) *clusterTestTypes { + return &clusterTestTypes{ + client: c.RESTClient(), + } +} + +// Get takes name of the clusterTestType, and returns the corresponding clusterTestType object, and an error if there is any. +func (c *clusterTestTypes) Get(name string, options meta_v1.GetOptions) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Get(). + Resource("clustertesttypes"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ClusterTestTypes that match those selectors. +func (c *clusterTestTypes) List(opts meta_v1.ListOptions) (result *v1.ClusterTestTypeList, err error) { + result = &v1.ClusterTestTypeList{} + err = c.client.Get(). + Resource("clustertesttypes"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested clusterTestTypes. +func (c *clusterTestTypes) Watch(opts meta_v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Resource("clustertesttypes"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a clusterTestType and creates it. Returns the server's representation of the clusterTestType, and an error, if there is any. +func (c *clusterTestTypes) Create(clusterTestType *v1.ClusterTestType) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Post(). + Resource("clustertesttypes"). + Body(clusterTestType). + Do(). + Into(result) + return +} + +// Update takes the representation of a clusterTestType and updates it. Returns the server's representation of the clusterTestType, and an error, if there is any. +func (c *clusterTestTypes) Update(clusterTestType *v1.ClusterTestType) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Put(). + Resource("clustertesttypes"). + Name(clusterTestType.Name). + Body(clusterTestType). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *clusterTestTypes) UpdateStatus(clusterTestType *v1.ClusterTestType) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Put(). + Resource("clustertesttypes"). + Name(clusterTestType.Name). + SubResource("status"). + Body(clusterTestType). + Do(). + Into(result) + return +} + +// Delete takes name of the clusterTestType and deletes it. Returns an error if one occurs. +func (c *clusterTestTypes) Delete(name string, options *meta_v1.DeleteOptions) error { + return c.client.Delete(). + Resource("clustertesttypes"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *clusterTestTypes) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error { + return c.client.Delete(). + Resource("clustertesttypes"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched clusterTestType. +func (c *clusterTestTypes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ClusterTestType, err error) { + result = &v1.ClusterTestType{} + err = c.client.Patch(pt). + Resource("clustertesttypes"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} + +// GetScale takes name of the clusterTestType, and returns the corresponding autoscaling.Scale object, and an error if there is any. +func (c *clusterTestTypes) GetScale(clusterTestTypeName string, options meta_v1.GetOptions) (result *autoscaling.Scale, err error) { + result = &autoscaling.Scale{} + err = c.client.Get(). + Resource("clustertesttypes"). + Name(clusterTestTypeName). + SubResource("scale"). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// UpdateScale takes the top resource name and the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any. +func (c *clusterTestTypes) UpdateScale(clusterTestTypeName string, scale *autoscaling.Scale) (result *autoscaling.Scale, err error) { + result = &autoscaling.Scale{} + err = c.client.Put(). + Resource("clustertesttypes"). + Name(clusterTestTypeName). + SubResource("scale"). + Body(scale). + Do(). + Into(result) + return +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/example_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/example_client.go index 7dcb34bbd..25d80728c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/example_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -27,6 +27,7 @@ import ( type ExampleV1Interface interface { RESTClient() rest.Interface + ClusterTestTypesGetter TestTypesGetter } @@ -35,6 +36,10 @@ type ExampleV1Client struct { restClient rest.Interface } +func (c *ExampleV1Client) ClusterTestTypes() ClusterTestTypeInterface { + return newClusterTestTypes(c) +} + func (c *ExampleV1Client) TestTypes(namespace string) TestTypeInterface { return newTestTypes(c, namespace) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_clustertesttype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_clustertesttype.go new file mode 100644 index 000000000..66eda8bc2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_clustertesttype.go @@ -0,0 +1,152 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + example_v1 "k8s.io/code-generator/_examples/crd/apis/example/v1" + autoscaling "k8s.io/kubernetes/pkg/apis/autoscaling" +) + +// FakeClusterTestTypes implements ClusterTestTypeInterface +type FakeClusterTestTypes struct { + Fake *FakeExampleV1 +} + +var clustertesttypesResource = schema.GroupVersionResource{Group: "example.crd.code-generator.k8s.io", Version: "v1", Resource: "clustertesttypes"} + +var clustertesttypesKind = schema.GroupVersionKind{Group: "example.crd.code-generator.k8s.io", Version: "v1", Kind: "ClusterTestType"} + +// Get takes name of the clusterTestType, and returns the corresponding clusterTestType object, and an error if there is any. +func (c *FakeClusterTestTypes) Get(name string, options v1.GetOptions) (result *example_v1.ClusterTestType, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(clustertesttypesResource, name), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// List takes label and field selectors, and returns the list of ClusterTestTypes that match those selectors. +func (c *FakeClusterTestTypes) List(opts v1.ListOptions) (result *example_v1.ClusterTestTypeList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(clustertesttypesResource, clustertesttypesKind, opts), &example_v1.ClusterTestTypeList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &example_v1.ClusterTestTypeList{ListMeta: obj.(*example_v1.ClusterTestTypeList).ListMeta} + for _, item := range obj.(*example_v1.ClusterTestTypeList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested clusterTestTypes. +func (c *FakeClusterTestTypes) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(clustertesttypesResource, opts)) +} + +// Create takes the representation of a clusterTestType and creates it. Returns the server's representation of the clusterTestType, and an error, if there is any. +func (c *FakeClusterTestTypes) Create(clusterTestType *example_v1.ClusterTestType) (result *example_v1.ClusterTestType, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(clustertesttypesResource, clusterTestType), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// Update takes the representation of a clusterTestType and updates it. Returns the server's representation of the clusterTestType, and an error, if there is any. +func (c *FakeClusterTestTypes) Update(clusterTestType *example_v1.ClusterTestType) (result *example_v1.ClusterTestType, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(clustertesttypesResource, clusterTestType), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeClusterTestTypes) UpdateStatus(clusterTestType *example_v1.ClusterTestType) (*example_v1.ClusterTestType, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(clustertesttypesResource, "status", clusterTestType), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// Delete takes name of the clusterTestType and deletes it. Returns an error if one occurs. +func (c *FakeClusterTestTypes) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(clustertesttypesResource, name), &example_v1.ClusterTestType{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeClusterTestTypes) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(clustertesttypesResource, listOptions) + + _, err := c.Fake.Invokes(action, &example_v1.ClusterTestTypeList{}) + return err +} + +// Patch applies the patch and returns the patched clusterTestType. +func (c *FakeClusterTestTypes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *example_v1.ClusterTestType, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(clustertesttypesResource, name, data, subresources...), &example_v1.ClusterTestType{}) + if obj == nil { + return nil, err + } + return obj.(*example_v1.ClusterTestType), err +} + +// GetScale takes name of the clusterTestType, and returns the corresponding scale object, and an error if there is any. +func (c *FakeClusterTestTypes) GetScale(clusterTestTypeName string, options v1.GetOptions) (result *autoscaling.Scale, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetSubresourceAction(clustertesttypesResource, clusterTestTypeName), &autoscaling.Scale{}) + if obj == nil { + return nil, err + } + return obj.(*autoscaling.Scale), err +} + +// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any. +func (c *FakeClusterTestTypes) UpdateScale(clusterTestTypeName string, scale *autoscaling.Scale) (result *autoscaling.Scale, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(clustertesttypesResource, "scale", scale), &autoscaling.Scale{}) + if obj == nil { + return nil, err + } + return obj.(*autoscaling.Scale), err +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_example_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_example_client.go index 4e99c7cba..e6aa99993 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_example_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_example_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -28,6 +28,10 @@ type FakeExampleV1 struct { *testing.Fake } +func (c *FakeExampleV1) ClusterTestTypes() v1.ClusterTestTypeInterface { + return &FakeClusterTestTypes{c} +} + func (c *FakeExampleV1) TestTypes(namespace string) v1.TestTypeInterface { return &FakeTestTypes{c, namespace} } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_testtype.go index 848b529a3..d925d9b39 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example_v1.TestTypeLi if label == nil { label = labels.Everything() } - list := &example_v1.TestTypeList{} + list := &example_v1.TestTypeList{ListMeta: obj.(*example_v1.TestTypeList).ListMeta} for _, item := range obj.(*example_v1.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/generated_expansion.go index 3f19f4e33..3059734a9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -18,4 +18,6 @@ limitations under the License. package v1 +type ClusterTestTypeExpansion interface{} + type TestTypeExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/testtype.go index d1175fe7c..b5b510ff0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/example2_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/example2_client.go index 71e7cd31a..210b6509f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/example2_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go index d63405ffe..0d55a6b8e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_example2_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_testtype.go index 07d26a277..8a51cbf8a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/fake/fake_testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeTestTypes) List(opts v1.ListOptions) (result *example2_v1.TestTypeL if label == nil { label = labels.Everything() } - list := &example2_v1.TestTypeList{} + list := &example2_v1.TestTypeList{ListMeta: obj.(*example2_v1.TestTypeList).ListMeta} for _, item := range obj.(*example2_v1.TestTypeList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/generated_expansion.go index 3f19f4e33..d513810d0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/testtype.go index 056415cbe..9691956ea 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/clientset/versioned/typed/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/interface.go index 51440cbc9..10c18944c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/clustertesttype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/clustertesttype.go new file mode 100644 index 000000000..cef599f48 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/clustertesttype.go @@ -0,0 +1,88 @@ +/* +Copyright 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + time "time" + + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + example_v1 "k8s.io/code-generator/_examples/crd/apis/example/v1" + versioned "k8s.io/code-generator/_examples/crd/clientset/versioned" + internalinterfaces "k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces" + v1 "k8s.io/code-generator/_examples/crd/listers/example/v1" +) + +// ClusterTestTypeInformer provides access to a shared informer and lister for +// ClusterTestTypes. +type ClusterTestTypeInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ClusterTestTypeLister +} + +type clusterTestTypeInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewClusterTestTypeInformer constructs a new informer for ClusterTestType type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewClusterTestTypeInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredClusterTestTypeInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredClusterTestTypeInformer constructs a new informer for ClusterTestType type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredClusterTestTypeInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExampleV1().ClusterTestTypes().List(options) + }, + WatchFunc: func(options meta_v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExampleV1().ClusterTestTypes().Watch(options) + }, + }, + &example_v1.ClusterTestType{}, + resyncPeriod, + indexers, + ) +} + +func (f *clusterTestTypeInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredClusterTestTypeInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *clusterTestTypeInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&example_v1.ClusterTestType{}, f.defaultInformer) +} + +func (f *clusterTestTypeInformer) Lister() v1.ClusterTestTypeLister { + return v1.NewClusterTestTypeLister(f.Informer().GetIndexer()) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/interface.go index 9378a06ba..1e17b1325 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // ClusterTestTypes returns a ClusterTestTypeInformer. + ClusterTestTypes() ClusterTestTypeInformer // TestTypes returns a TestTypeInformer. TestTypes() TestTypeInformer } @@ -39,6 +41,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// ClusterTestTypes returns a ClusterTestTypeInformer. +func (v *version) ClusterTestTypes() ClusterTestTypeInformer { + return &clusterTestTypeInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + // TestTypes returns a TestTypeInformer. func (v *version) TestTypes() TestTypeInformer { return &testTypeInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/testtype.go index d1e600c9a..04aa78337 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/interface.go index cf0d52cc8..9e00c7b80 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/interface.go index 9378a06ba..024352284 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/testtype.go index 855dd1d75..095237c45 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/factory.go index a843ddb9d..7d6d1f934 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -33,12 +33,16 @@ import ( internalinterfaces "k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client versioned.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -46,23 +50,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -111,7 +154,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/generic.go index 2e88773e8..d89bd2a76 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -54,6 +54,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=example.crd.code-generator.k8s.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("clustertesttypes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Example().V1().ClusterTestTypes().Informer()}, nil case v1.SchemeGroupVersion.WithResource("testtypes"): return &genericInformer{resource: resource.GroupResource(), informer: f.Example().V1().TestTypes().Informer()}, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces/factory_interfaces.go index e87f58032..02e0d6ac3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/clustertesttype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/clustertesttype.go new file mode 100644 index 000000000..584b3b273 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/clustertesttype.go @@ -0,0 +1,65 @@ +/* +Copyright 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "k8s.io/code-generator/_examples/crd/apis/example/v1" +) + +// ClusterTestTypeLister helps list ClusterTestTypes. +type ClusterTestTypeLister interface { + // List lists all ClusterTestTypes in the indexer. + List(selector labels.Selector) (ret []*v1.ClusterTestType, err error) + // Get retrieves the ClusterTestType from the index for a given name. + Get(name string) (*v1.ClusterTestType, error) + ClusterTestTypeListerExpansion +} + +// clusterTestTypeLister implements the ClusterTestTypeLister interface. +type clusterTestTypeLister struct { + indexer cache.Indexer +} + +// NewClusterTestTypeLister returns a new ClusterTestTypeLister. +func NewClusterTestTypeLister(indexer cache.Indexer) ClusterTestTypeLister { + return &clusterTestTypeLister{indexer: indexer} +} + +// List lists all ClusterTestTypes in the indexer. +func (s *clusterTestTypeLister) List(selector labels.Selector) (ret []*v1.ClusterTestType, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ClusterTestType)) + }) + return ret, err +} + +// Get retrieves the ClusterTestType from the index for a given name. +func (s *clusterTestTypeLister) Get(name string) (*v1.ClusterTestType, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("clustertesttype"), name) + } + return obj.(*v1.ClusterTestType), nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/expansion_generated.go index c5f4333d5..2681a29f4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -18,6 +18,10 @@ limitations under the License. package v1 +// ClusterTestTypeListerExpansion allows custom methods to be added to +// ClusterTestTypeLister. +type ClusterTestTypeListerExpansion interface{} + // TestTypeListerExpansion allows custom methods to be added to // TestTypeLister. type TestTypeListerExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/testtype.go index c39f5a395..7055b6cc4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example2/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example2/v1/expansion_generated.go index c5f4333d5..0192e05f0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example2/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example2/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example2/v1/testtype.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example2/v1/testtype.go index cd239c2f9..d3b15c0b9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example2/v1/testtype.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/_examples/crd/listers/example2/v1/testtype.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/args/gvpackages_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/args/gvpackages_test.go index 8154c2eec..f8891bec8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/args/gvpackages_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/args/gvpackages_test.go @@ -45,12 +45,12 @@ func TestGVPackageFlag(t *testing.T) { args: []string{"foo/bar/v1", "foo/bar/v2", "foo/bar/", "foo/v1"}, expectedGroups: []types.GroupVersions{ {PackageName: "bar", Group: types.Group("bar"), Versions: []types.PackageVersion{ - {"v1", "foo/bar/v1"}, - {"v2", "foo/bar/v2"}, - {"", "foo/bar"}, + {Version: "v1", Package: "foo/bar/v1"}, + {Version: "v2", Package: "foo/bar/v2"}, + {Version: "", Package: "foo/bar"}, }}, {PackageName: "foo", Group: types.Group("foo"), Versions: []types.PackageVersion{ - {"v1", "foo/v1"}, + {Version: "v1", Package: "foo/v1"}, }}, }, }, @@ -59,12 +59,12 @@ func TestGVPackageFlag(t *testing.T) { def: []string{"foo/bar/v1alpha1", "foo/v1"}, expectedGroups: []types.GroupVersions{ {PackageName: "bar", Group: types.Group("bar"), Versions: []types.PackageVersion{ - {"v1", "foo/bar/v1"}, - {"v2", "foo/bar/v2"}, - {"", "foo/bar"}, + {Version: "v1", Package: "foo/bar/v1"}, + {Version: "v2", Package: "foo/bar/v2"}, + {Version: "", Package: "foo/bar"}, }}, {PackageName: "foo", Group: types.Group("foo"), Versions: []types.PackageVersion{ - {"v1", "foo/v1"}, + {Version: "v1", Package: "foo/v1"}, }}, }, }, @@ -72,8 +72,8 @@ func TestGVPackageFlag(t *testing.T) { args: []string{"api/v1", "api"}, expectedGroups: []types.GroupVersions{ {PackageName: "core", Group: types.Group("api"), Versions: []types.PackageVersion{ - {"v1", "core/v1"}, - {"", "core"}, + {Version: "v1", Package: "core/v1"}, + {Version: "", Package: "core"}, }}, }, }, @@ -82,7 +82,7 @@ func TestGVPackageFlag(t *testing.T) { importBasePath: "k8s.io/api", expectedGroups: []types.GroupVersions{ {PackageName: "foo", Group: types.Group("foo"), Versions: []types.PackageVersion{ - {"v1", "k8s.io/api/foo/v1"}, + {Version: "v1", Package: "k8s.io/api/foo/v1"}, }}, }, }, diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go index 74af0b31d..335e995c0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go @@ -44,10 +44,10 @@ func NameSystems() namer.NameSystems { publicNamer := &ExceptionNamer{ Exceptions: map[string]string{ - // these exceptions are used to deconflict the generated code - // you can put your fully qualified package like - // to generate a name that doesn't conflict with your group. - // "k8s.io/apis/events/v1beta1.Event": "EventResource" + // these exceptions are used to deconflict the generated code + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "EventResource" }, KeyFunc: func(t *types.Type) string { return t.Name.Package + "." + t.Name.Name @@ -56,10 +56,10 @@ func NameSystems() namer.NameSystems { } privateNamer := &ExceptionNamer{ Exceptions: map[string]string{ - // these exceptions are used to deconflict the generated code - // you can put your fully qualified package like - // to generate a name that doesn't conflict with your group. - // "k8s.io/apis/events/v1beta1.Event": "eventResource" + // these exceptions are used to deconflict the generated code + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "eventResource" }, KeyFunc: func(t *types.Type) string { return t.Name.Package + "." + t.Name.Name @@ -68,10 +68,10 @@ func NameSystems() namer.NameSystems { } publicPluralNamer := &ExceptionNamer{ Exceptions: map[string]string{ - // these exceptions are used to deconflict the generated code - // you can put your fully qualified package like - // to generate a name that doesn't conflict with your group. - // "k8s.io/apis/events/v1beta1.Event": "EventResource" + // these exceptions are used to deconflict the generated code + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "EventResource" }, KeyFunc: func(t *types.Type) string { return t.Name.Package + "." + t.Name.Name diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go index f77ab0570..f1225acb3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go @@ -63,7 +63,7 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) { groupClientPackage := filepath.Join(g.fakeClientsetPackage, "typed", group.PackageName, version.NonEmpty()) fakeGroupClientPackage := filepath.Join(groupClientPackage, "fake") - groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{group.Group, version.Version}]) + groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]) imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", groupAlias, version.NonEmpty(), groupClientPackage))) imports = append(imports, strings.ToLower(fmt.Sprintf("fake%s%s \"%s\"", groupAlias, version.NonEmpty(), fakeGroupClientPackage))) } @@ -125,9 +125,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -137,7 +138,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go index c129a5f4b..bf18c14c6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go @@ -146,9 +146,10 @@ func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io. "NewRootWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootWatchAction"}), "NewWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewWatchAction"}), "NewCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateSubresourceAction"}), + "NewRootCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateSubresourceAction"}), "NewUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateSubresourceAction"}), "NewGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetSubresourceAction"}), - "NewListSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewListSubresourceAction"}), + "NewRootGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetSubresourceAction"}), "NewRootUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateSubresourceAction"}), "NewRootPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchAction"}), "NewPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchAction"}), @@ -235,11 +236,8 @@ func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io. } if e.HasVerb("list") { - if e.IsSubresource() { - sw.Do(adjustTemplate(e.VerbName, e.VerbType, listSubresourceTemplate), m) - } else { - sw.Do(adjustTemplate(e.VerbName, e.VerbType, listTemplate), m) - } + + sw.Do(adjustTemplate(e.VerbName, e.VerbType, listTemplate), m) } // TODO: Figure out schemantic for watching a sub-resource. @@ -322,19 +320,6 @@ func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type } ` -var listSubresourceTemplate = ` -// List takes label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors. -func (c *Fake$.type|publicPlural$) List($.type|private$Name string, opts $.ListOptions|raw$) (result *$.resultType|raw$List, err error) { - obj, err := c.Fake. - $if .namespaced$Invokes($.NewListSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", $.type|allLowercasePlural$Kind, c.ns, opts), &$.resultType|raw$List{}) - $else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), &$.resultType|raw$List{})$end$ - if obj == nil { - return nil, err - } - return obj.(*$.resultType|raw$List), err -} -` - var listUsingOptionsTemplate = ` // List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors. func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type|raw$List, err error) { @@ -349,7 +334,7 @@ func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type if label == nil { label = $.Everything|raw$() } - list := &$.type|raw$List{} + list := &$.type|raw$List{ListMeta: obj.(*$.type|raw$List).ListMeta} for _, item := range obj.(*$.type|raw$List).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) @@ -377,7 +362,7 @@ var getSubresourceTemplate = ` func (c *Fake$.type|publicPlural$) Get($.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) { obj, err := c.Fake. $if .namespaced$Invokes($.NewGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, "$.subresourcePath$", $.type|private$Name), &$.resultType|raw${}) - $else$Invokes($.NewRootGetAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name), &$.resultType|raw${})$end$ + $else$Invokes($.NewRootGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name), &$.resultType|raw${})$end$ if obj == nil { return nil, err } @@ -423,7 +408,7 @@ var createSubresourceTemplate = ` func (c *Fake$.type|publicPlural$) Create($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { obj, err := c.Fake. $if .namespaced$Invokes($.NewCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", c.ns, $.inputType|private$), &$.resultType|raw${}) - $else$Invokes($.NewRootCreateAction|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$), &$.resultType|raw${})$end$ + $else$Invokes($.NewRootCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$ if obj == nil { return nil, err } @@ -449,7 +434,7 @@ var updateSubresourceTemplate = ` func (c *Fake$.type|publicPlural$) Update($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { obj, err := c.Fake. $if .namespaced$Invokes($.NewUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", c.ns, $.inputType|private$), &$.inputType|raw${}) - $else$Invokes($.NewRootUpdateAction|raw$($.type|allLowercasePlural$Resource, $.type|private$), &$.type|raw${})$end$ + $else$Invokes($.NewRootUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$ if obj == nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go index de5264660..18ec09ac6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go @@ -59,7 +59,7 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) { for _, group := range g.groups { for _, version := range group.Versions { typedClientPath := filepath.Join(g.clientsetPackage, "typed", group.PackageName, version.NonEmpty()) - groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{group.Group, version.Version}]) + groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]) imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", groupAlias, version.NonEmpty(), typedClientPath))) } } @@ -83,7 +83,6 @@ func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Wr "NewDiscoveryClientForConfigOrDie": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClientForConfigOrDie"}), "NewDiscoveryClient": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClient"}), "flowcontrolNewTokenBucketRateLimiter": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/flowcontrol", Name: "NewTokenBucketRateLimiter"}), - "glogErrorf": c.Universe.Function(types.Name{Package: "github.com/golang/glog", Name: "Errorf"}), } sw.Do(clientsetInterface, m) sw.Do(clientsetTemplate, m) @@ -163,7 +162,6 @@ $range .allGroups$ cs.$.LowerCaseGroupGoName$$.Version$, err =$.PackageAlias$ $end$ cs.DiscoveryClient, err = $.NewDiscoveryClientForConfig|raw$(&configShallowCopy) if err!=nil { - $.glogErrorf|raw$("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go index 8e569a84f..fd59715c4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go @@ -210,17 +210,12 @@ func New(c $.restRESTClientInterface|raw$) *$.GroupGoName$$.Version$Client { var setInternalVersionClientDefaultsTemplate = ` func setConfigDefaults(config *$.restConfig|raw$) error { - g, err := scheme.Registry.Group("$.groupName$") - if err != nil { - return err - } - config.APIPath = $.apiPath$ if config.UserAgent == "" { config.UserAgent = $.restDefaultKubernetesUserAgent|raw$() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("$.groupName$")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("$.groupName$")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go index 6000e40da..dd9afadbf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go @@ -62,7 +62,7 @@ func (g *GenScheme) Imports(c *generator.Context) (imports []string) { for _, group := range g.Groups { for _, version := range group.Versions { packagePath := g.InputPackages[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}] - groupAlias := strings.ToLower(g.GroupGoNames[clientgentypes.GroupVersion{group.Group, version.Version}]) + groupAlias := strings.ToLower(g.GroupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]) if g.CreateRegistry { // import the install package for internal clientsets instead of the type package with register.go if version.Version != "" { @@ -86,26 +86,21 @@ func (g *GenScheme) GenerateType(c *generator.Context, t *types.Type, w io.Write allInstallGroups := clientgentypes.ToGroupInstallPackages(g.Groups, g.GroupGoNames) m := map[string]interface{}{ - "allGroupVersions": allGroupVersions, - "allInstallGroups": allInstallGroups, - "customRegister": false, - "osGetenv": c.Universe.Function(types.Name{Package: "os", Name: "Getenv"}), - "runtimeNewParameterCodec": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewParameterCodec"}), - "runtimeNewScheme": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewScheme"}), - "serializerNewCodecFactory": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/serializer", Name: "NewCodecFactory"}), - "runtimeScheme": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "Scheme"}), - "schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}), - "metav1AddToGroupVersion": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "AddToGroupVersion"}), - "announcedAPIGroupFactoryRegistry": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/announced", Name: "APIGroupFactoryRegistry"}), - "registeredNewOrDie": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/registered", Name: "NewOrDie"}), - "registeredAPIRegistrationManager": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/registered", Name: "APIRegistrationManager"}), + "allGroupVersions": allGroupVersions, + "allInstallGroups": allInstallGroups, + "customRegister": false, + "runtimeNewParameterCodec": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewParameterCodec"}), + "runtimeNewScheme": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewScheme"}), + "serializerNewCodecFactory": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/serializer", Name: "NewCodecFactory"}), + "runtimeScheme": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "Scheme"}), + "schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}), + "metav1AddToGroupVersion": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "AddToGroupVersion"}), } globals := map[string]string{ - "Scheme": "Scheme", - "Codecs": "Codecs", - "ParameterCodec": "ParameterCodec", - "Registry": "Registry", - "GroupFactoryRegistry": "GroupFactoryRegistry", + "Scheme": "Scheme", + "Codecs": "Codecs", + "ParameterCodec": "ParameterCodec", + "Registry": "Registry", } for k, v := range globals { if g.PrivateScheme { @@ -139,21 +134,18 @@ var $.ParameterCodec$ = $.runtimeNewParameterCodec|raw$($.Scheme$) ` var registryRegistration = ` -var $.Registry$ = $.registeredNewOrDie|raw$($.osGetenv|raw$("KUBE_API_VERSIONS")) -var $.GroupFactoryRegistry$ = make($.announcedAPIGroupFactoryRegistry|raw$) - func init() { $.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"}) - Install($.GroupFactoryRegistry$, $.Registry$, $.Scheme$) + Install($.Scheme$) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry $.announcedAPIGroupFactoryRegistry|raw$, registry *$.registeredAPIRegistrationManager|raw$, scheme *$.runtimeScheme|raw$) { +func Install(scheme *$.runtimeScheme|raw$) { $- range .allInstallGroups$ - $.InstallPackageAlias$.Install(groupFactoryRegistry, registry, scheme) + $.InstallPackageAlias$.Install(scheme) $- end$ $if .customRegister$ - ExtraInstall(groupFactoryRegistry, registry, scheme) + ExtraInstall(scheme) $end -$ } ` diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/conversion-gen/args/args.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/conversion-gen/args/args.go index 3b7b0123d..07ce6e72b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/conversion-gen/args/args.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/conversion-gen/args/args.go @@ -42,7 +42,7 @@ type CustomArgs struct { // generator pick up manually written conversion funcs from external packages. ExtraPeerDirs []string - // Skipunsafe indicates whether to generate unsafe conversions to improve the efficiency + // SkipUnsafe indicates whether to generate unsafe conversions to improve the efficiency // of these operations. The unsafe operation is a direct pointer assignment via unsafe // (within the allowed uses of unsafe) and is equivalent to a proposed Golang change to // allow structs that are identical to be assigned to each other. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go index 423577a12..e3b21c670 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go @@ -116,7 +116,10 @@ func assignGoTypeToProtoPackage(p *protobufPackage, t *types.Type, local, global } return } - global[t.Name] = p + if t.Name.Package == p.PackagePath { + // Associate types only to their own package + global[t.Name] = p + } if _, ok := local[t.Name]; ok { return } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/factory.go index 2a91aaa9e..5c557db73 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/factory.go @@ -89,6 +89,7 @@ func (g *factoryGenerator) GenerateType(c *generator.Context, t *types.Type, w i "syncMutex": c.Universe.Type(syncMutex), "timeDuration": c.Universe.Type(timeDuration), "namespaceAll": c.Universe.Type(metav1NamespaceAll), + "object": c.Universe.Type(metav1Object), } sw.Do(sharedInformerFactoryStruct, m) @@ -98,12 +99,16 @@ func (g *factoryGenerator) GenerateType(c *generator.Context, t *types.Type, w i } var sharedInformerFactoryStruct = ` +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client {{.clientSetInterface|raw}} namespace string tweakListOptions {{.interfacesTweakListOptionsFunc|raw}} lock {{.syncMutex|raw}} defaultResync {{.timeDuration|raw}} + customResync map[{{.reflectType|raw}}]{{.timeDuration|raw}} informers map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}} // startedInformers is used for tracking which informers have been started. @@ -111,23 +116,62 @@ type sharedInformerFactory struct { startedInformers map[{{.reflectType|raw}}]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[{{.object|raw}}]{{.timeDuration|raw}}) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, {{.namespaceAll|raw}}, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}, namespace string, tweakListOptions {{.interfacesTweakListOptionsFunc|raw}}) SharedInformerFactory { - return &sharedInformerFactory{ - client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, - defaultResync: defaultResync, - informers: make(map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}}), - startedInformers: make(map[{{.reflectType|raw}}]bool), - } + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}}), + startedInformers: make(map[{{.reflectType|raw}}]bool), + customResync: make(map[{{.reflectType|raw}}]{{.timeDuration|raw}}), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory } // Start initializes all requested informers. @@ -176,7 +220,13 @@ func (f *sharedInformerFactory) InformerFor(obj {{.runtimeObject|raw}}, newFunc if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/types.go index ecefb078c..27d4bd51a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/types.go @@ -37,5 +37,6 @@ var ( timeDuration = types.Name{Package: "time", Name: "Duration"} v1ListOptions = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"} metav1NamespaceAll = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "NamespaceAll"} + metav1Object = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "Object"} watchInterface = types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"} ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/generate-groups.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/generate-groups.sh index b92296d96..6707221e4 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/generate-groups.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/generate-groups.sh @@ -46,7 +46,13 @@ APIS_PKG="$3" GROUPS_WITH_VERSIONS="$4" shift 4 -go install ./$(dirname "${0}")/cmd/{defaulter-gen,client-gen,lister-gen,informer-gen,deepcopy-gen} +( + # To support running this script from anywhere, we have to first cd into this directory + # so we can install the tools. + cd $(dirname "${0}") + go install ./cmd/{defaulter-gen,client-gen,lister-gen,informer-gen,deepcopy-gen} +) + function codegen::join() { local IFS="$1"; shift; echo "$*"; } # enumerate group versions diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/boilerplate.go.txt b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/boilerplate.go.txt index 59e740c1e..b7c650da4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/boilerplate.go.txt +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright YEAR The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/update-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/update-codegen.sh index e38a0d92c..767c2ab36 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/update-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/verify-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/verify-codegen.sh index 601a76962..25302228d 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/verify-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/code-generator/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json index eda4e27fa..da5877e7a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "k8s.io/kube-aggregator", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], @@ -112,7 +112,7 @@ }, { "ImportPath": "github.com/evanphx/json-patch", - "Rev": "944e07253867aacae43c04b2e6a239005443f33a" + "Rev": "94e38aa1586e8a6c8a75770bddf5ff84c48a106b" }, { "ImportPath": "github.com/ghodss/yaml", @@ -148,27 +148,31 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/google/btree", + "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" }, { "ImportPath": "github.com/google/gofuzz", @@ -186,6 +190,14 @@ "ImportPath": "github.com/googleapis/gnostic/extensions", "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, { "ImportPath": "github.com/hashicorp/golang-lru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" @@ -194,10 +206,6 @@ "ImportPath": "github.com/hashicorp/golang-lru/simplelru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" }, - { - "ImportPath": "github.com/howeyc/gopass", - "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" - }, { "ImportPath": "github.com/imdario/mergo", "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" @@ -208,7 +216,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/mailru/easyjson/buffer", @@ -226,6 +234,14 @@ "ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil", "Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a" }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, { "ImportPath": "github.com/mxk/go-flowrate/flowrate", "Rev": "cca7078d478f8520f85629ad7c68962d31ed7682" @@ -234,6 +250,10 @@ "ImportPath": "github.com/pborman/uuid", "Rev": "ca53cad383cad2479bbba7f7a1a05797ec1386e4" }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" + }, { "ImportPath": "github.com/pmezard/go-difflib/difflib", "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d" @@ -268,7 +288,7 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Rev": "6644d46b81fa1831979c4cded0106e774e0ef0ab" + "Rev": "c439c4fa093711d42e1b01acb1235b52004753c1" }, { "ImportPath": "github.com/spf13/pflag", @@ -276,7 +296,7 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a" + "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" }, { "ImportPath": "github.com/ugorji/go/codec", @@ -284,7 +304,7 @@ }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/net/context", @@ -574,6 +594,10 @@ "ImportPath": "k8s.io/api/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -614,18 +638,6 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/validation/path", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -850,6 +862,10 @@ "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/generic", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -870,10 +886,6 @@ "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/validating", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/versioned", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apiserver/pkg/apis/apiserver", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1126,6 +1138,10 @@ "ImportPath": "k8s.io/apiserver/pkg/util/logs", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apiserver/pkg/util/openapi", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apiserver/pkg/util/proxy", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1310,6 +1326,10 @@ "ImportPath": "k8s.io/client-go/informers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/settings", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1438,6 +1458,10 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1534,6 +1558,10 @@ "ImportPath": "k8s.io/client-go/listers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1558,6 +1586,10 @@ "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/pkg/version", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1626,6 +1658,10 @@ "ImportPath": "k8s.io/client-go/util/cert", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/connrotation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1648,27 +1684,27 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/aggregator", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/artifacts/hostpath-pods/insecure-etcd-pod.yaml b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/artifacts/hostpath-pods/insecure-etcd-pod.yaml index 4cc607303..cbd45fde7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/artifacts/hostpath-pods/insecure-etcd-pod.yaml +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/artifacts/hostpath-pods/insecure-etcd-pod.yaml @@ -19,7 +19,6 @@ spec: - "--proxy-client-key-file=/var/run/auth-proxy-client/client-auth-proxy.key" - "--tls-cert-file=/var/run/serving-cert/serving-kube-aggregator.crt" - "--tls-private-key-file=/var/run/serving-cert/serving-kube-aggregator.key" - - "--tls-ca-file=/var/run/serving-ca/server-ca.crt" - "--client-ca-file=/var/run/client-ca/client-ca.crt" - "--requestheader-username-headers=X-Remote-User" - "--requestheader-group-headers=X-Remote-Group" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/artifacts/self-contained/kubernetes-discover-pod.yaml b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/artifacts/self-contained/kubernetes-discover-pod.yaml index f109310df..d8ec0137f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/artifacts/self-contained/kubernetes-discover-pod.yaml +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/artifacts/self-contained/kubernetes-discover-pod.yaml @@ -40,7 +40,6 @@ spec: - "--proxy-client-key-file=/var/run/auth-proxy-client/tls.key" - "--tls-cert-file=/var/run/serving-cert/tls.crt" - "--tls-private-key-file=/var/run/serving-cert/tls.key" - - "--tls-ca-file=/var/run/serving-ca/ca.crt" - "--etcd-servers=https://etcd.kube-public.svc:4001" - "--etcd-certfile=/var/run/etcd-client-cert/tls.crt" - "--etcd-keyfile=/var/run/etcd-client-cert/tls.key" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/boilerplate.go.txt b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/boilerplate.go.txt index 59e740c1e..b7c650da4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/boilerplate.go.txt +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright YEAR The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/build-image.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/build-image.sh index 6aae5fb62..ee09df3eb 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/build-image.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/build-image.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/local-up-kube-aggregator.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/local-up-kube-aggregator.sh index cc00878da..158d02aff 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/local-up-kube-aggregator.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/local-up-kube-aggregator.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/register-all-apis-from.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/register-all-apis-from.sh index 34f6693d7..fc20f9376 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/register-all-apis-from.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/register-all-apis-from.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/update-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/update-codegen.sh index 04fcb9861..43a4d5715 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/update-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/verify-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/verify-codegen.sh index 4678e5e3c..9fae05895 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/verify-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/main.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/main.go index 3be730e47..b0d76a545 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/main.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/main.go @@ -19,7 +19,6 @@ package main import ( "flag" "os" - "runtime" "github.com/golang/glog" @@ -39,10 +38,6 @@ func main() { logs.InitLogs() defer logs.FlushLogs() - if len(os.Getenv("GOMAXPROCS")) == 0 { - runtime.GOMAXPROCS(runtime.NumCPU()) - } - stopCh := genericapiserver.SetupSignalHandler() options := server.NewDefaultOptions(os.Stdout, os.Stderr) cmd := server.NewCommandStartAggregator(options, stopCh) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/BUILD index e4bbd5d00..a9ad38c7a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/BUILD @@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( @@ -19,6 +20,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/version:go_default_library", ], ) @@ -40,3 +42,9 @@ filegroup( ], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["helpers_test.go"], + embed = [":go_default_library"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/helpers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/helpers.go index 5e36e7db2..ab1f40cdc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/helpers.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/helpers.go @@ -22,6 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/version" ) func SortedByGroupAndVersion(servers []*APIService) [][]*APIService { @@ -76,7 +77,7 @@ func (s ByVersionPriority) Less(i, j int) bool { if s[i].Spec.VersionPriority != s[j].Spec.VersionPriority { return s[i].Spec.VersionPriority > s[j].Spec.VersionPriority } - return s[i].Name < s[j].Name + return version.CompareKubeAwareVersionStrings(s[i].Spec.Version, s[j].Spec.Version) > 0 } // APIServiceNameToGroupVersion returns the GroupVersion for a given apiServiceName. The name diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/helpers_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/helpers_test.go new file mode 100644 index 000000000..7bca228bd --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/helpers_test.go @@ -0,0 +1,71 @@ +/* +Copyright 2018 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 apiregistration + +import ( + "reflect" + "testing" +) + +func TestSortedAPIServicesByVersion(t *testing.T) { + tests := []*struct { + name string + versions []string + expected []string + }{ + { + name: "case1", + versions: []string{"v1", "v2"}, + expected: []string{"v2", "v1"}, + }, + { + name: "case2", + versions: []string{"v2", "v10"}, + expected: []string{"v10", "v2"}, + }, + { + name: "case3", + versions: []string{"v2", "v2beta1", "v10beta2", "v10beta1", "v10alpha1", "v1"}, + expected: []string{"v2", "v1", "v10beta2", "v10beta1", "v2beta1", "v10alpha1"}, + }, + { + name: "case4", + versions: []string{"v1", "v2", "test", "foo10", "final", "foo2", "foo1"}, + expected: []string{"v2", "v1", "final", "foo1", "foo10", "foo2", "test"}, + }, + { + name: "case5_from_documentation", + versions: []string{"v12alpha1", "v10", "v11beta2", "v10beta3", "v3beta1", "v2", "v11alpha2", "foo1", "v1", "foo10"}, + expected: []string{"v10", "v2", "v1", "v11beta2", "v10beta3", "v3beta1", "v12alpha1", "v11alpha2", "foo1", "foo10"}, + }, + } + + for _, tc := range tests { + apiServices := []*APIService{} + for _, v := range tc.versions { + apiServices = append(apiServices, &APIService{Spec: APIServiceSpec{Version: v, VersionPriority: 100}}) + } + sortedServices := SortedByGroupAndVersion(apiServices) + actual := []string{} + for _, s := range sortedServices[0] { + actual = append(actual, s.Spec.Version) + } + if !reflect.DeepEqual(tc.expected, actual) { + t.Errorf("expected %s, actual %s", tc.expected, actual) + } + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/install/BUILD index efbefd5e3..8eed75f0d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/install/BUILD @@ -10,10 +10,8 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/kube-aggregator/pkg/apis/apiregistration/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library", "//vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1:go_default_library", "//vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/install/install.go index e4149bd0d..75dd8b5d4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/install/install.go @@ -17,29 +17,17 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kube-aggregator/pkg/apis/apiregistration" "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: apiregistration.GroupName, - RootScopedKinds: sets.NewString("APIService"), - VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version, v1beta1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: apiregistration.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1.SchemeGroupVersion.Version: v1.AddToScheme, - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(apiregistration.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/types.go index 853d01520..3f0422116 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/types.go @@ -53,6 +53,7 @@ type APIServiceSpec struct { // This is strongly discouraged. You should use the CABundle instead. InsecureSkipTLSVerify bool // CABundle is a PEM encoded CA bundle which will be used to validate an API server's serving certificate. + // +optional CABundle []byte // GroupPriorityMininum is the priority this group should have at least. Higher priority means that the group is preferred by clients over lower priority ones. @@ -65,8 +66,14 @@ type APIServiceSpec struct { // VersionPriority controls the ordering of this API version inside of its group. Must be greater than zero. // The primary sort is based on VersionPriority, ordered highest to lowest (20 before 10). - // The secondary sort is based on the alphabetical comparison of the name of the object. (v1.bar before v1.foo) // Since it's inside of a group, the number can be small, probably in the 10s. + // In case of equal version priorities, the version string will be used to compute the order inside a group. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing major + // version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. VersionPriority int32 } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/generated.pb.go index 2e21a2061..593971a45 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1503,57 +1503,56 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 829 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x41, 0x6f, 0xe3, 0x44, - 0x14, 0x8e, 0xd3, 0xa4, 0x4d, 0xa7, 0x65, 0x5b, 0x86, 0x5d, 0x6d, 0x54, 0x81, 0x5b, 0x82, 0x04, - 0x01, 0x69, 0x6d, 0x5a, 0x10, 0x02, 0x21, 0x21, 0xd5, 0x8b, 0x54, 0x55, 0x6a, 0xa1, 0x9a, 0x54, - 0x3d, 0x00, 0x12, 0x4c, 0x9d, 0x57, 0x77, 0x48, 0x3d, 0xb6, 0x66, 0xc6, 0x96, 0x22, 0x2e, 0xfc, - 0x03, 0xf8, 0x4d, 0x9c, 0x7a, 0x5c, 0x89, 0x4b, 0x4f, 0x15, 0x0d, 0xff, 0x62, 0x4f, 0x68, 0xc6, - 0x63, 0x3b, 0x4d, 0xb2, 0x62, 0xa1, 0x97, 0x28, 0xf3, 0xde, 0xfb, 0xbe, 0xef, 0xbd, 0x37, 0x9f, - 0x07, 0x7d, 0x3f, 0xfa, 0x5c, 0x7a, 0x2c, 0xf1, 0x47, 0xd9, 0x39, 0x08, 0x0e, 0x0a, 0xa4, 0x9f, - 0x03, 0x1f, 0x26, 0xc2, 0x9f, 0x4a, 0x3c, 0xa3, 0x51, 0x24, 0x20, 0xa2, 0x2a, 0x11, 0x7e, 0x3a, - 0x8a, 0x7c, 0x9a, 0x32, 0xa9, 0x7f, 0x04, 0x44, 0x4c, 0x2a, 0x41, 0x15, 0x4b, 0xb8, 0x9f, 0xef, - 0xfa, 0x11, 0x70, 0x10, 0x54, 0xc1, 0xd0, 0x4b, 0x45, 0xa2, 0x12, 0xbc, 0x57, 0x70, 0x78, 0x9a, - 0xe3, 0xc7, 0x9a, 0xc3, 0x4b, 0x47, 0x91, 0xa7, 0x39, 0xbc, 0x19, 0x0e, 0x2f, 0xdf, 0xdd, 0x7a, - 0x16, 0x31, 0x75, 0x99, 0x9d, 0x7b, 0x61, 0x12, 0xfb, 0x51, 0x12, 0x25, 0xbe, 0xa1, 0x3a, 0xcf, - 0x2e, 0xcc, 0xc9, 0x1c, 0xcc, 0xbf, 0x42, 0x62, 0xeb, 0x53, 0xdb, 0x26, 0x4d, 0x59, 0x4c, 0xc3, - 0x4b, 0xc6, 0x41, 0x8c, 0xeb, 0x1e, 0x63, 0x50, 0x74, 0x41, 0x63, 0x5b, 0xfe, 0xab, 0x50, 0x22, - 0xe3, 0x8a, 0xc5, 0x30, 0x07, 0xf8, 0xec, 0xdf, 0x00, 0x32, 0xbc, 0x84, 0x98, 0xce, 0xe1, 0x3e, - 0x79, 0x15, 0x2e, 0x53, 0xec, 0xca, 0x67, 0x5c, 0x49, 0x25, 0x66, 0x41, 0xbd, 0x3f, 0x9a, 0x08, - 0xed, 0x9f, 0x1c, 0x0e, 0x40, 0xe4, 0x2c, 0x04, 0xfc, 0x13, 0xea, 0xe8, 0x39, 0x86, 0x54, 0xd1, - 0xae, 0xb3, 0xe3, 0xf4, 0xd7, 0xf6, 0x3e, 0xf6, 0xec, 0x62, 0xa7, 0x69, 0xeb, 0xad, 0xea, 0x6a, - 0x2f, 0xdf, 0xf5, 0xbe, 0x3d, 0xff, 0x19, 0x42, 0x75, 0x0c, 0x8a, 0x06, 0xf8, 0xfa, 0x76, 0xbb, - 0x31, 0xb9, 0xdd, 0x46, 0x75, 0x8c, 0x54, 0xac, 0x78, 0x88, 0x5a, 0x32, 0x85, 0xb0, 0xdb, 0x34, - 0xec, 0x81, 0xf7, 0xdf, 0xaf, 0xcd, 0xab, 0xfb, 0x1d, 0xa4, 0x10, 0x06, 0xeb, 0x56, 0xaf, 0xa5, - 0x4f, 0xc4, 0xb0, 0xe3, 0x2b, 0xb4, 0x2c, 0x15, 0x55, 0x99, 0xec, 0x2e, 0x19, 0x9d, 0xaf, 0x1f, - 0xa8, 0x63, 0xb8, 0x82, 0x47, 0x56, 0x69, 0xb9, 0x38, 0x13, 0xab, 0xd1, 0xbb, 0x69, 0xa2, 0xb7, - 0xea, 0xe2, 0xe7, 0x09, 0x1f, 0x32, 0xcd, 0x81, 0xbf, 0x44, 0x2d, 0x35, 0x4e, 0xc1, 0x6c, 0x72, - 0x35, 0xf8, 0xa0, 0xec, 0xf3, 0x74, 0x9c, 0xc2, 0xcb, 0xdb, 0xed, 0xa7, 0x0b, 0x20, 0x3a, 0x45, - 0x0c, 0x08, 0x7f, 0x51, 0x8d, 0xd0, 0x34, 0xf0, 0x77, 0xef, 0x8b, 0xbf, 0xbc, 0xdd, 0xde, 0xa8, - 0x60, 0xf7, 0xfb, 0xc1, 0x39, 0xc2, 0x57, 0x54, 0xaa, 0x53, 0x41, 0xb9, 0x2c, 0x68, 0x59, 0x0c, - 0x76, 0x13, 0x1f, 0xbd, 0xde, 0x7d, 0x6a, 0x44, 0xb0, 0x65, 0x25, 0xf1, 0xd1, 0x1c, 0x1b, 0x59, - 0xa0, 0x80, 0xdf, 0x47, 0xcb, 0x02, 0xa8, 0x4c, 0x78, 0xb7, 0x65, 0x5a, 0xae, 0xf6, 0x45, 0x4c, - 0x94, 0xd8, 0x2c, 0xfe, 0x10, 0xad, 0xc4, 0x20, 0x25, 0x8d, 0xa0, 0xdb, 0x36, 0x85, 0x1b, 0xb6, - 0x70, 0xe5, 0xb8, 0x08, 0x93, 0x32, 0xdf, 0xfb, 0xd3, 0x41, 0x8f, 0xea, 0x3d, 0x1d, 0x31, 0xa9, - 0xf0, 0x0f, 0x73, 0x1e, 0xf5, 0x5e, 0x6f, 0x26, 0x8d, 0x36, 0x0e, 0xdd, 0xb4, 0x72, 0x9d, 0x32, - 0x32, 0xe5, 0xcf, 0x10, 0xb5, 0x99, 0x82, 0x58, 0x6f, 0x7d, 0xa9, 0xbf, 0xb6, 0xf7, 0xd5, 0xc3, - 0x8c, 0x13, 0xbc, 0x61, 0xa5, 0xda, 0x87, 0x9a, 0x94, 0x14, 0xdc, 0xbd, 0xbb, 0xa5, 0xe9, 0xa9, - 0xb4, 0x6f, 0xf1, 0x08, 0xad, 0xc8, 0xe2, 0x68, 0x87, 0xfa, 0x5f, 0x96, 0xb5, 0x8c, 0x04, 0x2e, - 0x40, 0x00, 0x0f, 0x21, 0x58, 0xd3, 0x5b, 0x2d, 0xa3, 0xa5, 0x02, 0x7e, 0x0f, 0xb5, 0x23, 0x91, - 0x64, 0xa9, 0xb5, 0x56, 0xd5, 0xe4, 0x81, 0x0e, 0x92, 0x22, 0xa7, 0x6f, 0x29, 0x07, 0x21, 0x59, - 0xc2, 0x8d, 0x75, 0xa6, 0x6e, 0xe9, 0xac, 0x08, 0x93, 0x32, 0x8f, 0x07, 0xe8, 0x09, 0xe3, 0x12, - 0xc2, 0x4c, 0xc0, 0x60, 0xc4, 0xd2, 0xd3, 0xa3, 0xc1, 0x19, 0x08, 0x76, 0x31, 0x36, 0x3e, 0xe8, - 0x04, 0xef, 0x58, 0xe0, 0x93, 0xc3, 0x45, 0x45, 0x64, 0x31, 0x16, 0xf7, 0x51, 0x27, 0xa4, 0x41, - 0xc6, 0x87, 0x57, 0x85, 0x4d, 0xd6, 0x83, 0x75, 0x7d, 0x67, 0xcf, 0xf7, 0x8b, 0x18, 0xa9, 0xb2, - 0xf8, 0x04, 0x3d, 0x36, 0x2d, 0x9f, 0x08, 0x96, 0x08, 0xa6, 0xc6, 0xc7, 0x8c, 0xb3, 0x38, 0x8b, - 0xbb, 0x2b, 0x3b, 0x4e, 0xbf, 0x1d, 0xbc, 0x6d, 0xd5, 0x1f, 0x1f, 0x2c, 0xa8, 0x21, 0x0b, 0x91, - 0x78, 0x1f, 0x6d, 0xd8, 0xd9, 0xca, 0x4c, 0xb7, 0x63, 0xc8, 0x9e, 0x5a, 0xb2, 0x8d, 0xb3, 0xfb, - 0x69, 0x32, 0x5b, 0xdf, 0xfb, 0xcd, 0x41, 0x9b, 0xb3, 0x2f, 0x08, 0xfe, 0x05, 0xa1, 0xb0, 0xfc, - 0x68, 0x65, 0xd7, 0x31, 0x16, 0x3b, 0x78, 0x98, 0xc5, 0xaa, 0x47, 0xa0, 0x7e, 0x78, 0xab, 0x90, - 0x24, 0x53, 0x72, 0x3d, 0x40, 0x9b, 0xb3, 0xfe, 0xc0, 0x3e, 0x5a, 0xe5, 0x34, 0x06, 0x99, 0xd2, - 0xb0, 0x7c, 0xa7, 0xde, 0xb4, 0x34, 0xab, 0xdf, 0x94, 0x09, 0x52, 0xd7, 0xe0, 0x1d, 0xd4, 0xd2, - 0x07, 0xeb, 0x9c, 0xea, 0xed, 0xd5, 0xb5, 0xc4, 0x64, 0x82, 0xfe, 0xf5, 0x9d, 0xdb, 0x78, 0x71, - 0xe7, 0x36, 0x6e, 0xee, 0xdc, 0xc6, 0xaf, 0x13, 0xd7, 0xb9, 0x9e, 0xb8, 0xce, 0x8b, 0x89, 0xeb, - 0xdc, 0x4c, 0x5c, 0xe7, 0xaf, 0x89, 0xeb, 0xfc, 0xfe, 0xb7, 0xdb, 0xf8, 0xae, 0x99, 0xef, 0xfe, - 0x13, 0x00, 0x00, 0xff, 0xff, 0xd7, 0xd9, 0xaa, 0x56, 0x11, 0x08, 0x00, 0x00, + // 815 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x5d, 0x6b, 0x2b, 0x45, + 0x18, 0xce, 0xa6, 0x49, 0x9b, 0x4e, 0xeb, 0x69, 0x1d, 0xcf, 0xe1, 0x2c, 0x45, 0xb7, 0x35, 0x82, + 0x46, 0xe1, 0xec, 0xda, 0x22, 0xa2, 0x08, 0x42, 0xf7, 0x08, 0xa5, 0xd0, 0x6a, 0x99, 0x94, 0x5e, + 0xa8, 0xa0, 0x93, 0xcd, 0xdb, 0xed, 0x98, 0xee, 0x07, 0x33, 0xb3, 0x0b, 0xc1, 0x1b, 0xff, 0x81, + 0xfe, 0x26, 0xaf, 0x7a, 0x79, 0xc0, 0x9b, 0x5e, 0x05, 0x13, 0xff, 0xc5, 0xb9, 0x92, 0x99, 0x9d, + 0xdd, 0x4d, 0xd3, 0x88, 0xd5, 0xde, 0x84, 0xbc, 0x1f, 0xcf, 0xf3, 0xbc, 0xf3, 0xce, 0xb3, 0x83, + 0xbe, 0x1b, 0x7d, 0x26, 0x5c, 0x96, 0x78, 0xa3, 0x6c, 0x00, 0x3c, 0x06, 0x09, 0xc2, 0xcb, 0x21, + 0x1e, 0x26, 0xdc, 0x9b, 0x2b, 0xbc, 0xa0, 0x61, 0xc8, 0x21, 0xa4, 0x32, 0xe1, 0x5e, 0x3a, 0x0a, + 0x3d, 0x9a, 0x32, 0xa1, 0x7e, 0x38, 0x84, 0x4c, 0x48, 0x4e, 0x25, 0x4b, 0x62, 0x2f, 0xdf, 0xf7, + 0x42, 0x88, 0x81, 0x53, 0x09, 0x43, 0x37, 0xe5, 0x89, 0x4c, 0xf0, 0x41, 0xc1, 0xe1, 0x2a, 0x8e, + 0x1f, 0x6a, 0x0e, 0x37, 0x1d, 0x85, 0xae, 0xe2, 0x70, 0x17, 0x38, 0xdc, 0x7c, 0x7f, 0xe7, 0x45, + 0xc8, 0xe4, 0x55, 0x36, 0x70, 0x83, 0x24, 0xf2, 0xc2, 0x24, 0x4c, 0x3c, 0x4d, 0x35, 0xc8, 0x2e, + 0x75, 0xa4, 0x03, 0xfd, 0xaf, 0x90, 0xd8, 0xf9, 0xc4, 0x8c, 0x49, 0x53, 0x16, 0xd1, 0xe0, 0x8a, + 0xc5, 0xc0, 0xc7, 0xf5, 0x8c, 0x11, 0x48, 0xba, 0x64, 0xb0, 0x1d, 0xef, 0x9f, 0x50, 0x3c, 0x8b, + 0x25, 0x8b, 0xe0, 0x1e, 0xe0, 0xd3, 0x7f, 0x03, 0x88, 0xe0, 0x0a, 0x22, 0xba, 0x88, 0xeb, 0xfe, + 0xde, 0x44, 0xe8, 0xf0, 0xec, 0xb8, 0x0f, 0x3c, 0x67, 0x01, 0xe0, 0x1f, 0x51, 0x47, 0x8d, 0x34, + 0xa4, 0x92, 0xda, 0xd6, 0x9e, 0xd5, 0xdb, 0x38, 0xf8, 0xd8, 0x35, 0x3b, 0x9a, 0x67, 0xae, 0x17, + 0xa4, 0xba, 0xdd, 0x7c, 0xdf, 0xfd, 0x66, 0xf0, 0x13, 0x04, 0xf2, 0x14, 0x24, 0xf5, 0xf1, 0xcd, + 0x64, 0xb7, 0x31, 0x9b, 0xec, 0xa2, 0x3a, 0x47, 0x2a, 0x56, 0x3c, 0x44, 0x2d, 0x91, 0x42, 0x60, + 0x37, 0x35, 0xbb, 0xef, 0xfe, 0xf7, 0x1b, 0x70, 0xeb, 0x79, 0xfb, 0x29, 0x04, 0xfe, 0xa6, 0xd1, + 0x6b, 0xa9, 0x88, 0x68, 0x76, 0x7c, 0x8d, 0x56, 0x85, 0xa4, 0x32, 0x13, 0xf6, 0x8a, 0xd6, 0xf9, + 0xea, 0x91, 0x3a, 0x9a, 0xcb, 0x7f, 0x62, 0x94, 0x56, 0x8b, 0x98, 0x18, 0x8d, 0xee, 0x6d, 0x13, + 0xbd, 0x55, 0x37, 0xbf, 0x4c, 0xe2, 0x21, 0x53, 0x1c, 0xf8, 0x0b, 0xd4, 0x92, 0xe3, 0x14, 0xf4, + 0x26, 0xd7, 0xfd, 0x0f, 0xca, 0x39, 0xcf, 0xc7, 0x29, 0xbc, 0x9e, 0xec, 0x3e, 0x5f, 0x02, 0x51, + 0x25, 0xa2, 0x41, 0xf8, 0xf3, 0xea, 0x08, 0x4d, 0x0d, 0x7f, 0xf7, 0xae, 0xf8, 0xeb, 0xc9, 0xee, + 0x56, 0x05, 0xbb, 0x3b, 0x0f, 0xce, 0x11, 0xbe, 0xa6, 0x42, 0x9e, 0x73, 0x1a, 0x8b, 0x82, 0x96, + 0x45, 0x60, 0x36, 0xf1, 0xd1, 0xc3, 0xee, 0x53, 0x21, 0xfc, 0x1d, 0x23, 0x89, 0x4f, 0xee, 0xb1, + 0x91, 0x25, 0x0a, 0xf8, 0x7d, 0xb4, 0xca, 0x81, 0x8a, 0x24, 0xb6, 0x5b, 0x7a, 0xe4, 0x6a, 0x5f, + 0x44, 0x67, 0x89, 0xa9, 0xe2, 0x0f, 0xd1, 0x5a, 0x04, 0x42, 0xd0, 0x10, 0xec, 0xb6, 0x6e, 0xdc, + 0x32, 0x8d, 0x6b, 0xa7, 0x45, 0x9a, 0x94, 0xf5, 0xee, 0x1f, 0x16, 0x7a, 0x52, 0xef, 0xe9, 0x84, + 0x09, 0x89, 0xbf, 0xbf, 0xe7, 0x51, 0xf7, 0x61, 0x67, 0x52, 0x68, 0xed, 0xd0, 0x6d, 0x23, 0xd7, + 0x29, 0x33, 0x73, 0xfe, 0x0c, 0x50, 0x9b, 0x49, 0x88, 0xd4, 0xd6, 0x57, 0x7a, 0x1b, 0x07, 0x5f, + 0x3e, 0xce, 0x38, 0xfe, 0x1b, 0x46, 0xaa, 0x7d, 0xac, 0x48, 0x49, 0xc1, 0xdd, 0x9d, 0xae, 0xcc, + 0x9f, 0x4a, 0xf9, 0x16, 0x8f, 0xd0, 0x9a, 0x28, 0x42, 0x73, 0xa8, 0xff, 0x65, 0x59, 0xc3, 0x48, + 0xe0, 0x12, 0x38, 0xc4, 0x01, 0xf8, 0x1b, 0x6a, 0xab, 0x65, 0xb6, 0x54, 0xc0, 0xef, 0xa1, 0x76, + 0xc8, 0x93, 0x2c, 0x35, 0xd6, 0xaa, 0x86, 0x3c, 0x52, 0x49, 0x52, 0xd4, 0xd4, 0x2d, 0xe5, 0xc0, + 0x05, 0x4b, 0x62, 0x6d, 0x9d, 0xb9, 0x5b, 0xba, 0x28, 0xd2, 0xa4, 0xac, 0xe3, 0x3e, 0x7a, 0xc6, + 0x62, 0x01, 0x41, 0xc6, 0xa1, 0x3f, 0x62, 0xe9, 0xf9, 0x49, 0xff, 0x02, 0x38, 0xbb, 0x1c, 0x6b, + 0x1f, 0x74, 0xfc, 0x77, 0x0c, 0xf0, 0xd9, 0xf1, 0xb2, 0x26, 0xb2, 0x1c, 0x8b, 0x7b, 0xa8, 0x13, + 0x50, 0x3f, 0x8b, 0x87, 0xd7, 0x85, 0x4d, 0x36, 0xfd, 0x4d, 0x75, 0x67, 0x2f, 0x0f, 0x8b, 0x1c, + 0xa9, 0xaa, 0xf8, 0x0c, 0x3d, 0xd5, 0x23, 0x9f, 0x71, 0x96, 0x70, 0x26, 0xc7, 0xa7, 0x2c, 0x66, + 0x51, 0x16, 0xd9, 0x6b, 0x7b, 0x56, 0xaf, 0xed, 0xbf, 0x6d, 0xd4, 0x9f, 0x1e, 0x2d, 0xe9, 0x21, + 0x4b, 0x91, 0xf8, 0x10, 0x6d, 0x99, 0xb3, 0x95, 0x15, 0xbb, 0xa3, 0xc9, 0x9e, 0x1b, 0xb2, 0xad, + 0x8b, 0xbb, 0x65, 0xb2, 0xd8, 0xdf, 0xfd, 0xd5, 0x42, 0xdb, 0x8b, 0x2f, 0x08, 0xfe, 0x19, 0xa1, + 0xa0, 0xfc, 0x68, 0x85, 0x6d, 0x69, 0x8b, 0x1d, 0x3d, 0xce, 0x62, 0xd5, 0x23, 0x50, 0x3f, 0xbc, + 0x55, 0x4a, 0x90, 0x39, 0xb9, 0x2e, 0xa0, 0xed, 0x45, 0x7f, 0x60, 0x0f, 0xad, 0xc7, 0x34, 0x02, + 0x91, 0xd2, 0xa0, 0x7c, 0xa7, 0xde, 0x34, 0x34, 0xeb, 0x5f, 0x97, 0x05, 0x52, 0xf7, 0xe0, 0x3d, + 0xd4, 0x52, 0x81, 0x71, 0x4e, 0xf5, 0xf6, 0xaa, 0x5e, 0xa2, 0x2b, 0x7e, 0xef, 0x66, 0xea, 0x34, + 0x5e, 0x4d, 0x9d, 0xc6, 0xed, 0xd4, 0x69, 0xfc, 0x32, 0x73, 0xac, 0x9b, 0x99, 0x63, 0xbd, 0x9a, + 0x39, 0xd6, 0xed, 0xcc, 0xb1, 0xfe, 0x9c, 0x39, 0xd6, 0x6f, 0x7f, 0x39, 0x8d, 0x6f, 0x9b, 0xf9, + 0xfe, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x01, 0xf6, 0x47, 0x4a, 0xdc, 0x07, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/generated.proto index 11b09f6dc..5e24aa5d0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.kube_aggregator.pkg.apis.apiregistration.v1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1"; @@ -89,6 +88,7 @@ message APIServiceSpec { optional bool insecureSkipTLSVerify = 4; // CABundle is a PEM encoded CA bundle which will be used to validate an API server's serving certificate. + // +optional optional bytes caBundle = 5; // GroupPriorityMininum is the priority this group should have at least. Higher priority means that the group is preferred by clients over lower priority ones. @@ -101,8 +101,14 @@ message APIServiceSpec { // VersionPriority controls the ordering of this API version inside of its group. Must be greater than zero. // The primary sort is based on VersionPriority, ordered highest to lowest (20 before 10). - // The secondary sort is based on the alphabetical comparison of the name of the object. (v1.bar before v1.foo) // Since it's inside of a group, the number can be small, probably in the 10s. + // In case of equal version priorities, the version string will be used to compute the order inside a group. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing major + // version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. optional int32 versionPriority = 8; } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/types.go index a545c3bde..ffaec409c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/types.go @@ -53,7 +53,8 @@ type APIServiceSpec struct { // This is strongly discouraged. You should use the CABundle instead. InsecureSkipTLSVerify bool `json:"insecureSkipTLSVerify,omitempty" protobuf:"varint,4,opt,name=insecureSkipTLSVerify"` // CABundle is a PEM encoded CA bundle which will be used to validate an API server's serving certificate. - CABundle []byte `json:"caBundle" protobuf:"bytes,5,opt,name=caBundle"` + // +optional + CABundle []byte `json:"caBundle,omitempty" protobuf:"bytes,5,opt,name=caBundle"` // GroupPriorityMininum is the priority this group should have at least. Higher priority means that the group is preferred by clients over lower priority ones. // Note that other versions of this group might specify even higher GroupPriorityMininum values such that the whole group gets a higher priority. @@ -65,8 +66,14 @@ type APIServiceSpec struct { // VersionPriority controls the ordering of this API version inside of its group. Must be greater than zero. // The primary sort is based on VersionPriority, ordered highest to lowest (20 before 10). - // The secondary sort is based on the alphabetical comparison of the name of the object. (v1.bar before v1.foo) // Since it's inside of a group, the number can be small, probably in the 10s. + // In case of equal version priorities, the version string will be used to compute the order inside a group. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing major + // version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. VersionPriority int32 `json:"versionPriority" protobuf:"varint,8,opt,name=versionPriority"` // leaving this here so everyone remembers why proto index 6 is skipped diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/zz_generated.conversion.go index 65eb10a43..acf16ae86 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/zz_generated.deepcopy.go index 0a109455a..a6d308298 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/generated.pb.go index 881f5647e..c5e1a5804 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1503,58 +1503,57 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 836 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcf, 0x4f, 0xe3, 0x46, - 0x14, 0x8e, 0x21, 0x21, 0x61, 0xa0, 0x0b, 0x9d, 0xee, 0x6a, 0x23, 0xd4, 0x1a, 0x9a, 0x4a, 0x2d, - 0xad, 0x84, 0x5d, 0xb6, 0x55, 0x7f, 0xa8, 0x27, 0xcc, 0x01, 0x21, 0x41, 0x8b, 0x26, 0x88, 0x43, - 0x55, 0xa9, 0x3b, 0x71, 0x1e, 0x66, 0x1a, 0x3c, 0x76, 0x67, 0xc6, 0x91, 0x72, 0xdb, 0x3f, 0xa1, - 0x97, 0xfe, 0x4f, 0x1c, 0x7a, 0xd8, 0x23, 0xa7, 0xa8, 0xa4, 0x52, 0xff, 0x88, 0x3d, 0x55, 0x33, - 0x1e, 0xdb, 0x21, 0xc9, 0xaa, 0x2b, 0xc4, 0x25, 0xca, 0xbc, 0xf7, 0xbe, 0xef, 0x7b, 0xef, 0xcd, - 0xe7, 0x41, 0x2f, 0x07, 0xdf, 0x49, 0x8f, 0x25, 0xfe, 0x20, 0xeb, 0x81, 0xe0, 0xa0, 0x40, 0xfa, - 0x43, 0xe0, 0xfd, 0x44, 0xf8, 0x53, 0x89, 0x3d, 0x1a, 0x45, 0x02, 0x22, 0xaa, 0x12, 0xe1, 0xa7, - 0x83, 0xc8, 0xa7, 0x29, 0x93, 0xfa, 0x47, 0x40, 0xc4, 0xa4, 0x12, 0x54, 0xb1, 0x84, 0xfb, 0xc3, - 0xfd, 0x1e, 0x28, 0xba, 0xef, 0x47, 0xc0, 0x41, 0x50, 0x05, 0x7d, 0x2f, 0x15, 0x89, 0x4a, 0xf0, - 0xb7, 0x39, 0x91, 0xa7, 0x89, 0x7e, 0xad, 0x88, 0xbc, 0x74, 0x10, 0x79, 0x9a, 0xc8, 0x9b, 0x21, - 0xf2, 0x2c, 0xd1, 0xd6, 0x5e, 0xc4, 0xd4, 0x55, 0xd6, 0xf3, 0xc2, 0x24, 0xf6, 0xa3, 0x24, 0x4a, - 0x7c, 0xc3, 0xd7, 0xcb, 0x2e, 0xcd, 0xc9, 0x1c, 0xcc, 0xbf, 0x5c, 0x67, 0xeb, 0x6b, 0xdb, 0x30, - 0x4d, 0x59, 0x4c, 0xc3, 0x2b, 0xc6, 0x41, 0x8c, 0xaa, 0x6e, 0x63, 0x50, 0xd4, 0x1f, 0xce, 0x75, - 0xb7, 0xe5, 0xbf, 0x0d, 0x25, 0x32, 0xae, 0x58, 0x0c, 0x73, 0x80, 0x6f, 0xfe, 0x0f, 0x20, 0xc3, - 0x2b, 0x88, 0xe9, 0x1c, 0xee, 0xab, 0xb7, 0xe1, 0x32, 0xc5, 0xae, 0x7d, 0xc6, 0x95, 0x54, 0x62, - 0x16, 0xd4, 0xf9, 0x6b, 0x09, 0xa1, 0x83, 0xb3, 0xe3, 0x2e, 0x88, 0x21, 0x0b, 0x01, 0xbf, 0x44, - 0x2d, 0x3d, 0x47, 0x9f, 0x2a, 0xda, 0x76, 0x76, 0x9c, 0xdd, 0xb5, 0x17, 0x5f, 0x7a, 0x76, 0xbb, - 0xd3, 0xb4, 0xd5, 0x6a, 0x75, 0xb5, 0x37, 0xdc, 0xf7, 0x7e, 0xea, 0xfd, 0x06, 0xa1, 0x3a, 0x05, - 0x45, 0x03, 0x7c, 0x33, 0xde, 0xae, 0x4d, 0xc6, 0xdb, 0xa8, 0x8a, 0x91, 0x92, 0x15, 0x33, 0x54, - 0x97, 0x29, 0x84, 0xed, 0x25, 0xc3, 0x7e, 0xe4, 0x3d, 0xf0, 0xee, 0xbc, 0xaa, 0xe9, 0x6e, 0x0a, - 0x61, 0xb0, 0x6e, 0x45, 0xeb, 0xfa, 0x44, 0x8c, 0x04, 0xfe, 0x1d, 0xad, 0x48, 0x45, 0x55, 0x26, - 0xdb, 0xcb, 0x46, 0xec, 0xf8, 0x31, 0xc4, 0x0c, 0x61, 0xf0, 0xc4, 0xca, 0xad, 0xe4, 0x67, 0x62, - 0x85, 0x3a, 0xb7, 0x4b, 0xe8, 0x83, 0xaa, 0xf8, 0x30, 0xe1, 0x7d, 0xa6, 0x89, 0xf0, 0x0f, 0xa8, - 0xae, 0x46, 0x29, 0x98, 0x9d, 0xae, 0x06, 0x9f, 0x15, 0xcd, 0x9e, 0x8f, 0x52, 0x78, 0x33, 0xde, - 0x7e, 0xbe, 0x00, 0xa2, 0x53, 0xc4, 0x80, 0xf0, 0xf7, 0xe5, 0x1c, 0x4b, 0x06, 0xfe, 0xf1, 0x7d, - 0xf1, 0x37, 0xe3, 0xed, 0x8d, 0x12, 0x76, 0xbf, 0x1f, 0x3c, 0x44, 0xf8, 0x9a, 0x4a, 0x75, 0x2e, - 0x28, 0x97, 0x39, 0x2d, 0x8b, 0xc1, 0xae, 0xe3, 0x8b, 0x77, 0xbb, 0x59, 0x8d, 0x08, 0xb6, 0xac, - 0x24, 0x3e, 0x99, 0x63, 0x23, 0x0b, 0x14, 0xf0, 0xa7, 0x68, 0x45, 0x00, 0x95, 0x09, 0x6f, 0xd7, - 0x4d, 0xcb, 0xe5, 0xbe, 0x88, 0x89, 0x12, 0x9b, 0xc5, 0x9f, 0xa3, 0x66, 0x0c, 0x52, 0xd2, 0x08, - 0xda, 0x0d, 0x53, 0xb8, 0x61, 0x0b, 0x9b, 0xa7, 0x79, 0x98, 0x14, 0xf9, 0xce, 0xad, 0x83, 0x9e, - 0x54, 0x7b, 0x3a, 0x61, 0x52, 0xe1, 0x5f, 0xe6, 0xdc, 0xea, 0xbd, 0xdb, 0x4c, 0x1a, 0x6d, 0xbc, - 0xba, 0x69, 0xe5, 0x5a, 0x45, 0x64, 0xca, 0xa9, 0x57, 0xa8, 0xc1, 0x14, 0xc4, 0x7a, 0xeb, 0xcb, - 0xbb, 0x6b, 0x2f, 0x0e, 0x1f, 0xc1, 0x3d, 0xc1, 0x7b, 0x56, 0xaf, 0x71, 0xac, 0x99, 0x49, 0x2e, - 0xd0, 0xf9, 0x77, 0x79, 0x7a, 0x34, 0xed, 0x60, 0x9c, 0xa2, 0xa6, 0xcc, 0x8f, 0x76, 0xb2, 0x87, - 0x9b, 0xd7, 0xd2, 0x12, 0xb8, 0x04, 0x01, 0x3c, 0x84, 0x60, 0x4d, 0xef, 0xb7, 0x88, 0x16, 0x32, - 0xf8, 0x13, 0xd4, 0x88, 0x44, 0x92, 0xa5, 0xd6, 0x64, 0x65, 0xa7, 0x47, 0x3a, 0x48, 0xf2, 0x9c, - 0xbe, 0xaf, 0x21, 0x08, 0xc9, 0x12, 0x6e, 0x4c, 0x34, 0x75, 0x5f, 0x17, 0x79, 0x98, 0x14, 0x79, - 0xdc, 0x45, 0xcf, 0x18, 0x97, 0x10, 0x66, 0x02, 0xba, 0x03, 0x96, 0x9e, 0x9f, 0x74, 0x2f, 0x40, - 0xb0, 0xcb, 0x91, 0x71, 0x44, 0x2b, 0xf8, 0xc8, 0x02, 0x9f, 0x1d, 0x2f, 0x2a, 0x22, 0x8b, 0xb1, - 0x78, 0x17, 0xb5, 0x42, 0x1a, 0x64, 0xbc, 0x7f, 0x9d, 0x1b, 0x66, 0x3d, 0x58, 0xd7, 0xb7, 0x77, - 0x78, 0x90, 0xc7, 0x48, 0x99, 0xc5, 0x67, 0xe8, 0xa9, 0x69, 0xf9, 0x4c, 0xb0, 0x44, 0x30, 0x35, - 0x3a, 0x65, 0x9c, 0xc5, 0x59, 0xdc, 0x6e, 0xee, 0x38, 0xbb, 0x8d, 0xe0, 0x43, 0xab, 0xfe, 0xf4, - 0x68, 0x41, 0x0d, 0x59, 0x88, 0xc4, 0x07, 0x68, 0xc3, 0xce, 0x56, 0x64, 0xda, 0x2d, 0x43, 0xf6, - 0xdc, 0x92, 0x6d, 0x5c, 0xdc, 0x4f, 0x93, 0xd9, 0xfa, 0xce, 0x9f, 0x0e, 0xda, 0x9c, 0x7d, 0x4b, - 0xf0, 0x2b, 0x07, 0xa1, 0xb0, 0xf8, 0x7e, 0x65, 0xdb, 0x31, 0x6e, 0x3b, 0x79, 0x04, 0xb7, 0x95, - 0x8f, 0x42, 0xf5, 0x24, 0x97, 0x21, 0x49, 0xa6, 0x34, 0x3b, 0x80, 0x36, 0x67, 0x5d, 0x82, 0x7d, - 0xb4, 0xca, 0x69, 0x0c, 0x32, 0xa5, 0x61, 0xf1, 0x6e, 0xbd, 0x6f, 0x69, 0x56, 0x7f, 0x2c, 0x12, - 0xa4, 0xaa, 0xc1, 0x3b, 0xa8, 0xae, 0x0f, 0xd6, 0x3f, 0xe5, 0x83, 0xac, 0x6b, 0x89, 0xc9, 0x04, - 0x7b, 0x37, 0x77, 0x6e, 0xed, 0xf5, 0x9d, 0x5b, 0xbb, 0xbd, 0x73, 0x6b, 0xaf, 0x26, 0xae, 0x73, - 0x33, 0x71, 0x9d, 0xd7, 0x13, 0xd7, 0xb9, 0x9d, 0xb8, 0xce, 0xdf, 0x13, 0xd7, 0xf9, 0xe3, 0x1f, - 0xb7, 0xf6, 0x73, 0xd3, 0x4e, 0xf2, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdb, 0xca, 0xea, 0xee, - 0x3a, 0x08, 0x00, 0x00, + // 822 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4d, 0x6f, 0x23, 0x45, + 0x10, 0xf5, 0x24, 0x76, 0xec, 0x74, 0xc2, 0x26, 0x34, 0xbb, 0xda, 0x51, 0x04, 0x93, 0x60, 0x24, + 0x08, 0x48, 0x99, 0x21, 0x2b, 0xc4, 0x87, 0x38, 0x65, 0x72, 0x88, 0x22, 0x39, 0x10, 0xb5, 0xa3, + 0x1c, 0x10, 0x12, 0xdb, 0x1e, 0x57, 0xc6, 0x8d, 0x77, 0x3e, 0xe8, 0xee, 0xb1, 0xe4, 0xdb, 0xfe, + 0x04, 0x2e, 0xfc, 0xa7, 0x1c, 0x38, 0xec, 0xd1, 0x27, 0x8b, 0x18, 0x89, 0x1f, 0xb1, 0x27, 0xd4, + 0x3d, 0x3d, 0x33, 0x8e, 0x6d, 0xc4, 0x2a, 0xca, 0xc5, 0x72, 0x57, 0xd5, 0x7b, 0xaf, 0xaa, 0xfa, + 0x4d, 0xa3, 0x97, 0xc3, 0x6f, 0x85, 0xcb, 0x12, 0x6f, 0x98, 0xf5, 0x80, 0xc7, 0x20, 0x41, 0x78, + 0x23, 0x88, 0xfb, 0x09, 0xf7, 0xe6, 0x12, 0x47, 0x34, 0x0c, 0x39, 0x84, 0x54, 0x26, 0xdc, 0x4b, + 0x87, 0xa1, 0x47, 0x53, 0x26, 0xd4, 0x0f, 0x87, 0x90, 0x09, 0xc9, 0xa9, 0x64, 0x49, 0xec, 0x8d, + 0x8e, 0x7b, 0x20, 0xe9, 0xb1, 0x17, 0x42, 0x0c, 0x9c, 0x4a, 0xe8, 0xbb, 0x29, 0x4f, 0x64, 0x82, + 0xbf, 0xc9, 0x89, 0x5c, 0x45, 0xf4, 0x4b, 0x45, 0xe4, 0xa6, 0xc3, 0xd0, 0x55, 0x44, 0xee, 0x02, + 0x91, 0x6b, 0x88, 0xf6, 0x8e, 0x42, 0x26, 0x07, 0x59, 0xcf, 0x0d, 0x92, 0xc8, 0x0b, 0x93, 0x30, + 0xf1, 0x34, 0x5f, 0x2f, 0xbb, 0xd1, 0x27, 0x7d, 0xd0, 0xff, 0x72, 0x9d, 0xbd, 0xaf, 0x4c, 0xc3, + 0x34, 0x65, 0x11, 0x0d, 0x06, 0x2c, 0x06, 0x3e, 0xae, 0xba, 0x8d, 0x40, 0x52, 0x6f, 0xb4, 0xd4, + 0xdd, 0x9e, 0xf7, 0x5f, 0x28, 0x9e, 0xc5, 0x92, 0x45, 0xb0, 0x04, 0xf8, 0xfa, 0xff, 0x00, 0x22, + 0x18, 0x40, 0x44, 0x17, 0x71, 0xed, 0x3f, 0xd7, 0x10, 0x3a, 0xb9, 0x3c, 0xef, 0x02, 0x1f, 0xb1, + 0x00, 0xf0, 0x4b, 0xd4, 0x52, 0x2d, 0xf5, 0xa9, 0xa4, 0xb6, 0x75, 0x60, 0x1d, 0x6e, 0xbd, 0xf8, + 0xd2, 0x35, 0x8b, 0x9a, 0x67, 0xae, 0xb6, 0xa4, 0xaa, 0xdd, 0xd1, 0xb1, 0xfb, 0x63, 0xef, 0x57, + 0x08, 0xe4, 0x05, 0x48, 0xea, 0xe3, 0xdb, 0xe9, 0x7e, 0x6d, 0x36, 0xdd, 0x47, 0x55, 0x8c, 0x94, + 0xac, 0x98, 0xa1, 0xba, 0x48, 0x21, 0xb0, 0xd7, 0x34, 0xfb, 0x99, 0xfb, 0xc0, 0x6b, 0x70, 0xab, + 0xa6, 0xbb, 0x29, 0x04, 0xfe, 0xb6, 0x11, 0xad, 0xab, 0x13, 0xd1, 0x12, 0xf8, 0x37, 0xb4, 0x21, + 0x24, 0x95, 0x99, 0xb0, 0xd7, 0xb5, 0xd8, 0xf9, 0x63, 0x88, 0x69, 0x42, 0xff, 0x89, 0x91, 0xdb, + 0xc8, 0xcf, 0xc4, 0x08, 0xb5, 0x27, 0x6b, 0xe8, 0x83, 0xaa, 0xf8, 0x34, 0x89, 0xfb, 0x4c, 0x11, + 0xe1, 0xef, 0x51, 0x5d, 0x8e, 0x53, 0xd0, 0x3b, 0xdd, 0xf4, 0x3f, 0x2b, 0x9a, 0xbd, 0x1a, 0xa7, + 0xf0, 0x76, 0xba, 0xff, 0x7c, 0x05, 0x44, 0xa5, 0x88, 0x06, 0xe1, 0xef, 0xca, 0x39, 0xd6, 0x34, + 0xfc, 0xe3, 0xfb, 0xe2, 0x6f, 0xa7, 0xfb, 0x3b, 0x25, 0xec, 0x7e, 0x3f, 0x78, 0x84, 0xf0, 0x2b, + 0x2a, 0xe4, 0x15, 0xa7, 0xb1, 0xc8, 0x69, 0x59, 0x04, 0x66, 0x1d, 0x5f, 0xbc, 0xdb, 0xcd, 0x2a, + 0x84, 0xbf, 0x67, 0x24, 0x71, 0x67, 0x89, 0x8d, 0xac, 0x50, 0xc0, 0x9f, 0xa2, 0x0d, 0x0e, 0x54, + 0x24, 0xb1, 0x5d, 0xd7, 0x2d, 0x97, 0xfb, 0x22, 0x3a, 0x4a, 0x4c, 0x16, 0x7f, 0x8e, 0x9a, 0x11, + 0x08, 0x41, 0x43, 0xb0, 0x1b, 0xba, 0x70, 0xc7, 0x14, 0x36, 0x2f, 0xf2, 0x30, 0x29, 0xf2, 0xed, + 0x89, 0x85, 0x9e, 0x54, 0x7b, 0xea, 0x30, 0x21, 0xf1, 0xcf, 0x4b, 0x6e, 0x75, 0xdf, 0x6d, 0x26, + 0x85, 0xd6, 0x5e, 0xdd, 0x35, 0x72, 0xad, 0x22, 0x32, 0xe7, 0xd4, 0x01, 0x6a, 0x30, 0x09, 0x91, + 0xda, 0xfa, 0xfa, 0xe1, 0xd6, 0x8b, 0xd3, 0x47, 0x70, 0x8f, 0xff, 0x9e, 0xd1, 0x6b, 0x9c, 0x2b, + 0x66, 0x92, 0x0b, 0xb4, 0xff, 0x59, 0x9f, 0x1f, 0x4d, 0x39, 0x18, 0xa7, 0xa8, 0x29, 0xf2, 0xa3, + 0x99, 0xec, 0xe1, 0xe6, 0x35, 0xb4, 0x04, 0x6e, 0x80, 0x43, 0x1c, 0x80, 0xbf, 0xa5, 0xf6, 0x5b, + 0x44, 0x0b, 0x19, 0xfc, 0x09, 0x6a, 0x84, 0x3c, 0xc9, 0x52, 0x63, 0xb2, 0xb2, 0xd3, 0x33, 0x15, + 0x24, 0x79, 0x4e, 0xdd, 0xd7, 0x08, 0xb8, 0x60, 0x49, 0xac, 0x4d, 0x34, 0x77, 0x5f, 0xd7, 0x79, + 0x98, 0x14, 0x79, 0xdc, 0x45, 0xcf, 0x58, 0x2c, 0x20, 0xc8, 0x38, 0x74, 0x87, 0x2c, 0xbd, 0xea, + 0x74, 0xaf, 0x81, 0xb3, 0x9b, 0xb1, 0x76, 0x44, 0xcb, 0xff, 0xc8, 0x00, 0x9f, 0x9d, 0xaf, 0x2a, + 0x22, 0xab, 0xb1, 0xf8, 0x10, 0xb5, 0x02, 0xea, 0x67, 0x71, 0xff, 0x55, 0x6e, 0x98, 0x6d, 0x7f, + 0x5b, 0xdd, 0xde, 0xe9, 0x49, 0x1e, 0x23, 0x65, 0x16, 0x5f, 0xa2, 0xa7, 0xba, 0xe5, 0x4b, 0xce, + 0x12, 0xce, 0xe4, 0xf8, 0x82, 0xc5, 0x2c, 0xca, 0x22, 0xbb, 0x79, 0x60, 0x1d, 0x36, 0xfc, 0x0f, + 0x8d, 0xfa, 0xd3, 0xb3, 0x15, 0x35, 0x64, 0x25, 0x12, 0x9f, 0xa0, 0x1d, 0x33, 0x5b, 0x91, 0xb1, + 0x5b, 0x9a, 0xec, 0xb9, 0x21, 0xdb, 0xb9, 0xbe, 0x9f, 0x26, 0x8b, 0xf5, 0xed, 0x3f, 0x2c, 0xb4, + 0xbb, 0xf8, 0x96, 0xe0, 0xd7, 0x16, 0x42, 0x41, 0xf1, 0xfd, 0x0a, 0xdb, 0xd2, 0x6e, 0xeb, 0x3c, + 0x82, 0xdb, 0xca, 0x47, 0xa1, 0x7a, 0x92, 0xcb, 0x90, 0x20, 0x73, 0x9a, 0x6d, 0x40, 0xbb, 0x8b, + 0x2e, 0xc1, 0x1e, 0xda, 0x8c, 0x69, 0x04, 0x22, 0xa5, 0x41, 0xf1, 0x6e, 0xbd, 0x6f, 0x68, 0x36, + 0x7f, 0x28, 0x12, 0xa4, 0xaa, 0xc1, 0x07, 0xa8, 0xae, 0x0e, 0xc6, 0x3f, 0xe5, 0x83, 0xac, 0x6a, + 0x89, 0xce, 0xf8, 0x47, 0xb7, 0x77, 0x4e, 0xed, 0xcd, 0x9d, 0x53, 0x9b, 0xdc, 0x39, 0xb5, 0xd7, + 0x33, 0xc7, 0xba, 0x9d, 0x39, 0xd6, 0x9b, 0x99, 0x63, 0x4d, 0x66, 0x8e, 0xf5, 0xd7, 0xcc, 0xb1, + 0x7e, 0xff, 0xdb, 0xa9, 0xfd, 0xd4, 0x34, 0x93, 0xfc, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x47, 0x00, + 0x27, 0xe3, 0x05, 0x08, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/generated.proto index 9a069e2c5..3a45347a7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,7 +24,6 @@ package k8s.io.kube_aggregator.pkg.apis.apiregistration.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; @@ -89,6 +88,7 @@ message APIServiceSpec { optional bool insecureSkipTLSVerify = 4; // CABundle is a PEM encoded CA bundle which will be used to validate an API server's serving certificate. + // +optional optional bytes caBundle = 5; // GroupPriorityMininum is the priority this group should have at least. Higher priority means that the group is preferred by clients over lower priority ones. @@ -101,8 +101,14 @@ message APIServiceSpec { // VersionPriority controls the ordering of this API version inside of its group. Must be greater than zero. // The primary sort is based on VersionPriority, ordered highest to lowest (20 before 10). - // The secondary sort is based on the alphabetical comparison of the name of the object. (v1.bar before v1.foo) // Since it's inside of a group, the number can be small, probably in the 10s. + // In case of equal version priorities, the version string will be used to compute the order inside a group. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing major + // version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. optional int32 versionPriority = 8; } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/types.go index 2ac807e39..0d4ba49ef 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/types.go @@ -53,7 +53,8 @@ type APIServiceSpec struct { // This is strongly discouraged. You should use the CABundle instead. InsecureSkipTLSVerify bool `json:"insecureSkipTLSVerify,omitempty" protobuf:"varint,4,opt,name=insecureSkipTLSVerify"` // CABundle is a PEM encoded CA bundle which will be used to validate an API server's serving certificate. - CABundle []byte `json:"caBundle" protobuf:"bytes,5,opt,name=caBundle"` + // +optional + CABundle []byte `json:"caBundle,omitempty" protobuf:"bytes,5,opt,name=caBundle"` // GroupPriorityMininum is the priority this group should have at least. Higher priority means that the group is preferred by clients over lower priority ones. // Note that other versions of this group might specify even higher GroupPriorityMininum values such that the whole group gets a higher priority. @@ -65,8 +66,14 @@ type APIServiceSpec struct { // VersionPriority controls the ordering of this API version inside of its group. Must be greater than zero. // The primary sort is based on VersionPriority, ordered highest to lowest (20 before 10). - // The secondary sort is based on the alphabetical comparison of the name of the object. (v1.bar before v1.foo) // Since it's inside of a group, the number can be small, probably in the 10s. + // In case of equal version priorities, the version string will be used to compute the order inside a group. + // If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered + // lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version), + // then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first + // by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing major + // version, then minor version. An example sorted list of versions: + // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. VersionPriority int32 `json:"versionPriority" protobuf:"varint,8,opt,name=versionPriority"` // leaving this here so everyone remembers why proto index 6 is skipped diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/zz_generated.conversion.go index b32e3542a..1ae775da0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/zz_generated.deepcopy.go index ef08fb9fa..e093d3dd2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/zz_generated.deepcopy.go index ab24172e2..177bec4b4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go index 980b641f9..0718da301 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go @@ -23,7 +23,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericapiserver "k8s.io/apiserver/pkg/server" serverstorage "k8s.io/apiserver/pkg/server/storage" "k8s.io/client-go/pkg/version" @@ -92,8 +91,6 @@ type APIAggregator struct { delegateHandler http.Handler - contextMapper genericapirequest.RequestContextMapper - // proxyClientCert/Key are the client cert used to identify this proxy. Backing APIServices use // this to confirm the proxy's identity proxyClientCert []byte @@ -158,7 +155,6 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg s := &APIAggregator{ GenericAPIServer: genericServer, delegateHandler: delegationTarget.UnprotectedHandler(), - contextMapper: c.GenericConfig.RequestContextMapper, proxyClientCert: c.ExtraConfig.ProxyClientCert, proxyClientKey: c.ExtraConfig.ProxyClientKey, proxyTransport: c.ExtraConfig.ProxyTransport, @@ -177,7 +173,6 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg apisHandler := &apisHandler{ codecs: aggregatorscheme.Codecs, lister: s.lister, - mapper: s.contextMapper, } s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", apisHandler) s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandle("/apis/", apisHandler) @@ -208,7 +203,7 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg }) if openApiConfig != nil { - specDownloader := openapicontroller.NewDownloader(s.contextMapper) + specDownloader := openapicontroller.NewDownloader() openAPIAggregator, err := openapicontroller.BuildAndRegisterAggregator( &specDownloader, delegationTarget, @@ -250,7 +245,6 @@ func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService) er // register the proxy handler proxyHandler := &proxyHandler{ - contextMapper: s.contextMapper, localDelegate: s.delegateHandler, proxyClientCert: s.proxyClientCert, proxyClientKey: s.proxyClientKey, @@ -278,11 +272,10 @@ func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService) er // it's time to register the group aggregation endpoint groupPath := "/apis/" + apiService.Spec.Group groupDiscoveryHandler := &apiGroupHandler{ - codecs: aggregatorscheme.Codecs, - groupName: apiService.Spec.Group, - lister: s.lister, - delegate: s.delegateHandler, - contextMapper: s.contextMapper, + codecs: aggregatorscheme.Codecs, + groupName: apiService.Spec.Group, + lister: s.lister, + delegate: s.delegateHandler, } // aggregation is protected s.GenericAPIServer.Handler.NonGoRestfulMux.Handle(groupPath, groupDiscoveryHandler) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_apis.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_apis.go index eef59fd2e..82543abaa 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_apis.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_apis.go @@ -17,7 +17,6 @@ limitations under the License. package apiserver import ( - "errors" "net/http" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -26,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" - "k8s.io/apiserver/pkg/endpoints/request" apiregistrationapi "k8s.io/kube-aggregator/pkg/apis/apiregistration" apiregistrationv1api "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" @@ -39,7 +37,6 @@ import ( type apisHandler struct { codecs serializer.CodecFactory lister listers.APIServiceLister - mapper request.RequestContextMapper } var discoveryGroup = metav1.APIGroup{ @@ -61,12 +58,6 @@ var discoveryGroup = metav1.APIGroup{ } func (r *apisHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - ctx, ok := r.mapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } - discoveryGroupList := &metav1.APIGroupList{ // always add OUR api group to the list first. Since we'll never have a registered APIService for it // and since this is the crux of the API, having this first will give our names priority. It's good to be king. @@ -90,7 +81,7 @@ func (r *apisHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { } } - responsewriters.WriteObjectNegotiated(ctx, r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroupList) + responsewriters.WriteObjectNegotiated(r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroupList) } // convertToDiscoveryAPIGroup takes apiservices in a single group and returns a discovery compatible object. @@ -101,10 +92,6 @@ func convertToDiscoveryAPIGroup(apiServices []*apiregistrationapi.APIService) *m var discoveryGroup *metav1.APIGroup for _, apiService := range apiServicesByGroup { - if !apiregistrationapi.IsAPIServiceConditionTrue(apiService, apiregistrationapi.Available) { - continue - } - // the first APIService which is valid becomes the default if discoveryGroup == nil { discoveryGroup = &metav1.APIGroup{ @@ -129,9 +116,8 @@ func convertToDiscoveryAPIGroup(apiServices []*apiregistrationapi.APIService) *m // apiGroupHandler serves the `/apis/` endpoint. type apiGroupHandler struct { - codecs serializer.CodecFactory - groupName string - contextMapper request.RequestContextMapper + codecs serializer.CodecFactory + groupName string lister listers.APIServiceLister @@ -139,12 +125,6 @@ type apiGroupHandler struct { } func (r *apiGroupHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - ctx, ok := r.contextMapper.Get(req) - if !ok { - responsewriters.InternalError(w, req, errors.New("no context found for request")) - return - } - apiServices, err := r.lister.List(labels.Everything()) if statusErr, ok := err.(*apierrors.StatusError); ok && err != nil { responsewriters.WriteRawJSON(int(statusErr.Status().Code), statusErr.Status(), w) @@ -172,5 +152,5 @@ func (r *apiGroupHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { http.Error(w, "", http.StatusNotFound) return } - responsewriters.WriteObjectNegotiated(ctx, r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroup) + responsewriters.WriteObjectNegotiated(r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroup) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_apis_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_apis_test.go index 32aef625f..86d7c12b3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_apis_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_apis_test.go @@ -27,7 +27,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/diff" - "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/client-go/tools/cache" "k8s.io/kube-aggregator/pkg/apis/apiregistration" @@ -220,17 +219,58 @@ func TestAPIs(t *testing.T) { { Name: "bar", Versions: []metav1.GroupVersionForDiscovery{ + { + GroupVersion: "bar/v2", + Version: "v2", + }, { GroupVersion: "bar/v1", Version: "v1", }, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "bar/v2", + Version: "v2", + }, + }, + }, + }, + }, + { + name: "unavailable service", + apiservices: []*apiregistration.APIService{ + { + ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, + Spec: apiregistration.APIServiceSpec{ + Service: &apiregistration.ServiceReference{ + Namespace: "ns", + Name: "api", + }, + Group: "foo", + Version: "v1", + GroupPriorityMinimum: 11, + }, + Status: apiregistration.APIServiceStatus{ + Conditions: []apiregistration.APIServiceCondition{ + {Type: apiregistration.Available, Status: apiregistration.ConditionFalse}, + }, + }, + }, + }, + expected: &metav1.APIGroupList{ + TypeMeta: metav1.TypeMeta{Kind: "APIGroupList", APIVersion: "v1"}, + Groups: []metav1.APIGroup{ + discoveryGroup, + { + Name: "foo", + Versions: []metav1.GroupVersionForDiscovery{ { - GroupVersion: "bar/v2", - Version: "v2", + GroupVersion: "foo/v1", + Version: "v1", }, }, PreferredVersion: metav1.GroupVersionForDiscovery{ - GroupVersion: "bar/v1", + GroupVersion: "foo/v1", Version: "v1", }, }, @@ -240,18 +280,16 @@ func TestAPIs(t *testing.T) { } for _, tc := range tests { - mapper := request.NewRequestContextMapper() indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) handler := &apisHandler{ codecs: aggregatorscheme.Codecs, lister: listers.NewAPIServiceLister(indexer), - mapper: mapper, } for _, o := range tc.apiservices { indexer.Add(o) } - server := httptest.NewServer(request.WithRequestContext(handler, mapper)) + server := httptest.NewServer(handler) defer server.Close() resp, err := http.Get(server.URL + "/apis") @@ -278,7 +316,6 @@ func TestAPIs(t *testing.T) { } func TestAPIGroupMissing(t *testing.T) { - mapper := request.NewRequestContextMapper() indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) handler := &apiGroupHandler{ codecs: aggregatorscheme.Codecs, @@ -287,10 +324,9 @@ func TestAPIGroupMissing(t *testing.T) { delegate: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusForbidden) }), - contextMapper: mapper, } - server := httptest.NewServer(request.WithRequestContext(handler, mapper)) + server := httptest.NewServer(handler) defer server.Close() // this call should delegate @@ -425,19 +461,17 @@ func TestAPIGroup(t *testing.T) { } for _, tc := range tests { - mapper := request.NewRequestContextMapper() indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) handler := &apiGroupHandler{ - codecs: aggregatorscheme.Codecs, - lister: listers.NewAPIServiceLister(indexer), - groupName: "foo", - contextMapper: mapper, + codecs: aggregatorscheme.Codecs, + lister: listers.NewAPIServiceLister(indexer), + groupName: "foo", } for _, o := range tc.apiservices { indexer.Add(o) } - server := httptest.NewServer(request.WithRequestContext(handler, mapper)) + server := httptest.NewServer(handler) defer server.Close() resp, err := http.Get(server.URL + "/apis/" + tc.group) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go index 7d3d603b5..7c4ab2cf6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go @@ -42,8 +42,6 @@ import ( // proxyHandler provides a http.Handler which will proxy traffic to locations // specified by items implementing Redirector. type proxyHandler struct { - contextMapper genericapirequest.RequestContextMapper - // localDelegate is used to satisfy local APIServices localDelegate http.Handler @@ -104,12 +102,7 @@ func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { return } - ctx, ok := r.contextMapper.Get(req) - if !ok { - http.Error(w, "missing context", http.StatusInternalServerError) - return - } - user, ok := genericapirequest.UserFrom(ctx) + user, ok := genericapirequest.UserFrom(req.Context()) if !ok { http.Error(w, "missing user", http.StatusInternalServerError) return @@ -216,10 +209,10 @@ func (r *proxyHandler) updateAPIService(apiService *apiregistrationapi.APIServic serviceAvailable: apiregistrationapi.IsAPIServiceConditionTrue(apiService, apiregistrationapi.Available), } newInfo.proxyRoundTripper, newInfo.transportBuildingError = restclient.TransportFor(newInfo.restConfig) - if newInfo.transportBuildingError == nil && r.proxyTransport != nil && r.proxyTransport.Dial != nil { + if newInfo.transportBuildingError == nil && r.proxyTransport != nil && r.proxyTransport.DialContext != nil { switch transport := newInfo.proxyRoundTripper.(type) { case *http.Transport: - transport.Dial = r.proxyTransport.Dial + transport.DialContext = r.proxyTransport.DialContext default: newInfo.transportBuildingError = fmt.Errorf("unable to set dialer for %s/%s as rest transport is of type %T", apiService.Spec.Service.Namespace, apiService.Spec.Service.Name, newInfo.proxyRoundTripper) glog.Warning(newInfo.transportBuildingError.Error()) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy_test.go index b994cd18f..a5ff16f57 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy_test.go @@ -57,30 +57,23 @@ func (d *targetHTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } -type fakeRequestContextMapper struct { - user user.Info -} - -func (m *fakeRequestContextMapper) Get(req *http.Request) (genericapirequest.Context, bool) { - ctx := genericapirequest.NewContext() - if m.user != nil { - ctx = genericapirequest.WithUser(ctx, m.user) - } - - resolver := &genericapirequest.RequestInfoFactory{ - APIPrefixes: sets.NewString("api", "apis"), - GrouplessAPIPrefixes: sets.NewString("api"), - } - info, err := resolver.NewRequestInfo(req) - if err == nil { - ctx = genericapirequest.WithRequestInfo(ctx, info) - } - - return ctx, true -} - -func (*fakeRequestContextMapper) Update(req *http.Request, context genericapirequest.Context) error { - return nil +func contextHandler(handler http.Handler, user user.Info) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + ctx := req.Context() + if user != nil { + ctx = genericapirequest.WithUser(ctx, user) + } + resolver := &genericapirequest.RequestInfoFactory{ + APIPrefixes: sets.NewString("api", "apis"), + GrouplessAPIPrefixes: sets.NewString("api"), + } + info, err := resolver.NewRequestInfo(req) + if err == nil { + ctx = genericapirequest.WithRequestInfo(ctx, info) + } + req = req.WithContext(ctx) + handler.ServeHTTP(w, req) + }) } type mockedRouter struct { @@ -280,8 +273,7 @@ func TestProxyHandler(t *testing.T) { serviceResolver: serviceResolver, proxyTransport: &http.Transport{}, } - handler.contextMapper = &fakeRequestContextMapper{user: tc.user} - server := httptest.NewServer(handler) + server := httptest.NewServer(contextHandler(handler, tc.user)) defer server.Close() if tc.apiService != nil { @@ -417,12 +409,11 @@ func TestProxyUpgrade(t *testing.T) { serverURL, _ := url.Parse(backendServer.URL) proxyHandler := &proxyHandler{ - contextMapper: &fakeRequestContextMapper{user: &user.DefaultInfo{Name: "username"}}, serviceResolver: &mockedRouter{destinationHost: serverURL.Host}, proxyTransport: &http.Transport{}, } proxyHandler.updateAPIService(tc.APIService) - aggregator := httptest.NewServer(proxyHandler) + aggregator := httptest.NewServer(contextHandler(proxyHandler, &user.DefaultInfo{Name: "username"})) defer aggregator.Close() ws, err := websocket.Dial("ws://"+aggregator.Listener.Addr().String()+path, "", "http://127.0.0.1/") diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme/BUILD index e18370279..a610c5703 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme/BUILD @@ -6,8 +6,6 @@ go_library( importpath = "k8s.io/kube-aggregator/pkg/apiserver/scheme", visibility = ["//visibility:public"], deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme/scheme.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme/scheme.go index 39cd3e9f4..4537edb16 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme/scheme.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme/scheme.go @@ -17,8 +17,6 @@ limitations under the License. package scheme import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" @@ -34,16 +32,11 @@ var ( // Codecs provides methods for retrieving codecs and serializers for specific // versions and content types. Codecs = serializer.NewCodecFactory(Scheme) - // groupFactoryRegistry is the APIGroupFactoryRegistry. - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - // Registry is an instance of an API registry. This is an interim step to start removing the idea of a global - // API registry. - Registry = registered.NewOrDie("") ) func init() { AddToScheme(Scheme) - install.Install(groupFactoryRegistry, Registry, Scheme) + install.Install(Scheme) } // AddToScheme adds the types of this group into the given scheme. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/BUILD index 82813a41f..09cc223f4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/BUILD @@ -13,7 +13,6 @@ go_library( ], importpath = "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset", deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/clientset.go index 598cfbb2e..8cf29e436 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package clientset import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -86,7 +85,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/doc.go index 3421911a7..ee865e56d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/clientset_generated.go index d9feb7415..b74f701a5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,9 +43,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -55,7 +56,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/register.go index 40c228fe5..c5e0faa30 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme/register.go index d8c56d1df..02aa0fa1f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/apiregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/apiregistration_client.go index 438a5c5d0..d3c524f64 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/apiregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/apiregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/apiservice.go index 17304faa3..1d4e9ad19 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/doc.go index d007a2903..3af5d054f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiregistration_client.go index a114c015b..3e563e6f0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiservice.go index e8a8cfea7..2eb5bc023 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeAPIServices) List(opts v1.ListOptions) (result *apiregistration_v1. if label == nil { label = labels.Everything() } - list := &apiregistration_v1.APIServiceList{} + list := &apiregistration_v1.APIServiceList{ListMeta: obj.(*apiregistration_v1.APIServiceList).ListMeta} for _, item := range obj.(*apiregistration_v1.APIServiceList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/generated_expansion.go index 3d9593343..87aa18716 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/apiregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/apiregistration_client.go index 553953da6..d37a16c30 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/apiregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/apiregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/apiservice.go index bd42b17c3..e07264416 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiregistration_client.go index 554db1928..9b32316af 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiservice.go index d67d7cc84..785b775c7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeAPIServices) List(opts v1.ListOptions) (result *v1beta1.APIServiceL if label == nil { label = labels.Everything() } - list := &v1beta1.APIServiceList{} + list := &v1beta1.APIServiceList{ListMeta: obj.(*v1beta1.APIServiceList).ListMeta} for _, item := range obj.(*v1beta1.APIServiceList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/generated_expansion.go index 3b8d40eb2..e9108c5c8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/BUILD index 39a91a2dd..5f3f0802a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/BUILD @@ -13,7 +13,6 @@ go_library( ], importpath = "k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset", deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/clientset.go index 18d8e0099..7359abf4e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package internalclientset import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -66,7 +65,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/doc.go index 22ccee919..01b3d5e0f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go index beec0b595..4c607f1e2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -41,9 +41,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -53,7 +54,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/register.go index fcb30f949..c2e6ddaae 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/BUILD index 94a2da323..59ebb38a2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/BUILD @@ -13,8 +13,6 @@ go_library( ], importpath = "k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/register.go index 12eb1ae9d..5b4631eee 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,10 +19,6 @@ limitations under the License. package scheme import ( - os "os" - - announced "k8s.io/apimachinery/pkg/apimachinery/announced" - registered "k8s.io/apimachinery/pkg/apimachinery/registered" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -34,15 +30,12 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) -var Registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) -var GroupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - func init() { v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - Install(GroupFactoryRegistry, Registry, Scheme) + Install(Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - apiregistration.Install(groupFactoryRegistry, registry, scheme) +func Install(scheme *runtime.Scheme) { + apiregistration.Install(scheme) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/apiregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/apiregistration_client.go index b9669e0d5..772485766 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/apiregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/apiregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -66,17 +66,12 @@ func New(c rest.Interface) *ApiregistrationClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("apiregistration.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("apiregistration.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("apiregistration.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/apiservice.go index 005af3233..27d3cfc22 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/fake_apiregistration_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/fake_apiregistration_client.go index 26d9f7ffc..0be3a2bc1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/fake_apiregistration_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/fake_apiregistration_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/fake_apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/fake_apiservice.go index f78c61c5f..6f35646bf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/fake_apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake/fake_apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeAPIServices) List(opts v1.ListOptions) (result *apiregistration.API if label == nil { label = labels.Everything() } - list := &apiregistration.APIServiceList{} + list := &apiregistration.APIServiceList{ListMeta: obj.(*apiregistration.APIServiceList).ListMeta} for _, item := range obj.(*apiregistration.APIServiceList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/generated_expansion.go index 2cb003c24..ea36c5d71 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/interface.go index af86940b0..55f854a66 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1/apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1/apiservice.go index c8f3b9e5d..fa6bbe349 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1/apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1/apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1/interface.go index 5e08f7370..d0cf786ef 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1beta1/apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1beta1/apiservice.go index 5829f054a..1fc35eb71 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1beta1/apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1beta1/apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1beta1/interface.go index 8f14e1f64..d9f6fc380 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1beta1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1beta1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/factory.go index 84154440c..88cb2bdec 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,12 +32,16 @@ import ( internalinterfaces "k8s.io/kube-aggregator/pkg/client/informers/externalversions/internalinterfaces" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client clientset.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -45,23 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client clientset.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client clientset.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client clientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -110,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/generic.go index 80acd0a5a..1c89767b2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index a25a2731e..3bfcdba5b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/interface.go index 8138d6566..ffdc17234 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion/apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion/apiservice.go index 67909b486..caba4ae8c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion/apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion/apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion/interface.go index 7f339979e..e8da5ce46 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/factory.go index a7937789f..e4b1a5666 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,12 +32,16 @@ import ( internalinterfaces "k8s.io/kube-aggregator/pkg/client/informers/internalversion/internalinterfaces" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client internalclientset.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -45,23 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client internalclientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -110,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/generic.go index c8b6c67f9..9b7578041 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go index 227b0f218..b628752c1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion/apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion/apiservice.go index 0c91a915c..d441847f5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion/apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion/apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion/expansion_generated.go index 7a9d2bd3c..bb9726844 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1/apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1/apiservice.go index 7d88cabfb..b2e4f763c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1/apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1/apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1/expansion_generated.go index ba4499337..07d5e73b9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1beta1/apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1beta1/apiservice.go index 64f13c421..57f930383 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1beta1/apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1beta1/apiservice.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1beta1/expansion_generated.go index 5c27c2ecb..6c7d75f61 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1beta1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1beta1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/cmd/server/start.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/cmd/server/start.go index e56723028..40c794972 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/cmd/server/start.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/cmd/server/start.go @@ -98,7 +98,7 @@ func NewDefaultOptions(out, err io.Writer) *AggregatorOptions { func (o AggregatorOptions) Validate(args []string) error { errors := []error{} errors = append(errors, o.RecommendedOptions.Validate()...) - errors = append(errors, o.APIEnablement.Validate(aggregatorscheme.Registry)...) + errors = append(errors, o.APIEnablement.Validate(aggregatorscheme.Scheme)...) return utilerrors.NewAggregate(errors) } @@ -117,7 +117,7 @@ func (o AggregatorOptions) RunAggregator(stopCh <-chan struct{}) error { if err := o.RecommendedOptions.ApplyTo(serverConfig, aggregatorscheme.Scheme); err != nil { return err } - if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), aggregatorscheme.Registry); err != nil { + if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), aggregatorscheme.Scheme); err != nil { return err } serverConfig.LongRunningFunc = filters.BasicLongRunningRequestCheck( @@ -144,7 +144,7 @@ func (o AggregatorOptions) RunAggregator(stopCh <-chan struct{}) error { return err } - server, err := config.Complete().NewWithDelegate(genericapiserver.EmptyDelegate) + server, err := config.Complete().NewWithDelegate(genericapiserver.NewEmptyDelegate()) if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/BUILD index e075551b9..0cae9f080 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/BUILD @@ -34,7 +34,6 @@ go_test( deps = [ "//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator_test.go index 15d23e380..88b70eca0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator_test.go @@ -25,7 +25,6 @@ import ( "github.com/go-openapi/spec" "github.com/stretchr/testify/assert" - "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/kube-aggregator/pkg/apis/apiregistration" ) @@ -138,7 +137,7 @@ func assertDownloadedSpec(actualSpec *spec.Swagger, actualEtag string, err error func TestDownloadOpenAPISpec(t *testing.T) { - s := Downloader{contextMapper: request.NewRequestContextMapper()} + s := Downloader{} // Test with no eTag actualSpec, actualEtag, _, err := s.Download(handlerTest{data: []byte("{\"id\": \"test\"}")}, "") diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/downloader.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/downloader.go index 4cd359edd..382440153 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/downloader.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/downloader.go @@ -31,12 +31,11 @@ import ( // Downloader is the OpenAPI downloader type. It will try to download spec from /swagger.json endpoint. type Downloader struct { - contextMapper request.RequestContextMapper } // NewDownloader creates a new OpenAPI Downloader. -func NewDownloader(contextMapper request.RequestContextMapper) Downloader { - return Downloader{contextMapper} +func NewDownloader() Downloader { + return Downloader{} } // inMemoryResponseWriter is a http.Writer that keep the response in memory. @@ -81,9 +80,7 @@ func (r *inMemoryResponseWriter) String() string { func (s *Downloader) handlerWithUser(handler http.Handler, info user.Info) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - if ctx, ok := s.contextMapper.Get(req); ok { - s.contextMapper.Update(req, request.WithUser(ctx, info)) - } + req = req.WithContext(request.WithUser(req.Context(), info)) handler.ServeHTTP(w, req) }) } @@ -96,7 +93,6 @@ func etagFor(data []byte) string { // httpStatus is only valid if err == nil func (s *Downloader) Download(handler http.Handler, etag string) (returnSpec *spec.Swagger, newEtag string, httpStatus int, err error) { handler = s.handlerWithUser(handler, &user.DefaultInfo{Name: aggregatorUser}) - handler = request.WithRequestContext(handler, s.contextMapper) handler = http.TimeoutHandler(handler, specDownloadTimeout, "request timed out") req, err := http.NewRequest("GET", "/openapi/v2", nil) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller.go index a9bbe08a1..367b60dbe 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller.go @@ -176,6 +176,22 @@ func (c *AvailableConditionController) sync(key string) error { } if service.Spec.Type == v1.ServiceTypeClusterIP { + // if we have a cluster IP service, it must be listening on 443 and we can check that + foundPort := false + for _, port := range service.Spec.Ports { + if port.Port == 443 { + foundPort = true + } + } + if !foundPort { + availableCondition.Status = apiregistration.ConditionFalse + availableCondition.Reason = "ServicePortError" + availableCondition.Message = fmt.Sprintf("service/%s in %q is not listening on port 443", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace) + apiregistration.SetAPIServiceCondition(apiService, availableCondition) + _, err := c.apiServiceClient.APIServices().UpdateStatus(apiService) + return err + } + endpoints, err := c.endpointsLister.Endpoints(apiService.Spec.Service.Namespace).Get(apiService.Spec.Service.Name) if apierrors.IsNotFound(err) { availableCondition.Status = apiregistration.ConditionFalse diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller_test.go index d0dbff247..d82a0a0bd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller_test.go @@ -55,6 +55,9 @@ func newService(namespace, name string) *v1.Service { ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, Spec: v1.ServiceSpec{ Type: v1.ServiceTypeClusterIP, + Ports: []v1.ServicePort{ + {Port: 443}, + }, }, } } @@ -110,6 +113,27 @@ func TestSync(t *testing.T) { Message: `service/bar in "foo" is not present`, }, }, + { + name: "service on bad port", + apiServiceName: "remote.group", + apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")}, + services: []*v1.Service{{ + ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"}, + Spec: v1.ServiceSpec{ + Type: v1.ServiceTypeClusterIP, + Ports: []v1.ServicePort{ + {Port: 6443}, + }, + }, + }}, + endpoints: []*v1.Endpoints{newEndpointsWithAddress("foo", "bar")}, + expectedAvailability: apiregistration.APIServiceCondition{ + Type: apiregistration.Available, + Status: apiregistration.ConditionFalse, + Reason: "ServicePortError", + Message: `service/bar in "foo" is not listening on port 443`, + }, + }, { name: "no endpoints", apiServiceName: "remote.group", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/BUILD index 751de834a..9c5b70c7e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/BUILD @@ -14,7 +14,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/BUILD index 0fb9c4f5e..9e051a383 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/BUILD @@ -10,8 +10,8 @@ go_library( srcs = ["etcd.go"], importpath = "k8s.io/kube-aggregator/pkg/registry/apiservice/etcd", deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/etcd.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/etcd.go index b69f1a39d..c7c49072a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/etcd.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd/etcd.go @@ -17,8 +17,10 @@ limitations under the License. package etcd import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" @@ -65,13 +67,18 @@ type StatusREST struct { store *genericregistry.Store } -var _ = rest.Updater(&StatusREST{}) +var _ = rest.Patcher(&StatusREST{}) func (r *StatusREST) New() runtime.Object { return &apiregistration.APIService{} } +// Get retrieves the object from the storage. It is required to support Patch. +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + return r.store.Get(ctx, name, options) +} + // Update alters the status subset of an object. -func (r *StatusREST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) { return r.store.Update(ctx, name, objInfo, createValidation, updateValidation) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/rest/storage_apiservice.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/rest/storage_apiservice.go index ef0c875dd..c10b5b233 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/rest/storage_apiservice.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/rest/storage_apiservice.go @@ -32,10 +32,9 @@ import ( // NewRESTStorage returns an APIGroupInfo object that will work against apiservice. func NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) genericapiserver.APIGroupInfo { - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiregistration.GroupName, aggregatorscheme.Registry, aggregatorscheme.Scheme, metav1.ParameterCodec, aggregatorscheme.Codecs) + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiregistration.GroupName, aggregatorscheme.Scheme, metav1.ParameterCodec, aggregatorscheme.Codecs) if apiResourceConfigSource.VersionEnabled(v1beta1.SchemeGroupVersion) { - apiGroupInfo.GroupMeta.GroupVersion = v1beta1.SchemeGroupVersion storage := map[string]rest.Storage{} apiServiceREST := apiservicestorage.NewREST(aggregatorscheme.Scheme, restOptionsGetter) storage["apiservices"] = apiServiceREST @@ -44,7 +43,6 @@ func NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSourc } if apiResourceConfigSource.VersionEnabled(v1.SchemeGroupVersion) { - apiGroupInfo.GroupMeta.GroupVersion = v1.SchemeGroupVersion storage := map[string]rest.Storage{} apiServiceREST := apiservicestorage.NewREST(aggregatorscheme.Scheme, restOptionsGetter) storage["apiservices"] = apiServiceREST diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/strategy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/strategy.go index 51887d719..96c40fd33 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/strategy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator/pkg/registry/apiservice/strategy.go @@ -17,13 +17,13 @@ limitations under the License. package apiservice import ( + "context" "fmt" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" @@ -45,7 +45,7 @@ func (apiServerStrategy) NamespaceScoped() bool { return false } -func (apiServerStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (apiServerStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { apiservice := obj.(*apiregistration.APIService) apiservice.Status = apiregistration.APIServiceStatus{} @@ -55,13 +55,13 @@ func (apiServerStrategy) PrepareForCreate(ctx genericapirequest.Context, obj run } } -func (apiServerStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (apiServerStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newAPIService := obj.(*apiregistration.APIService) oldAPIService := old.(*apiregistration.APIService) newAPIService.Status = oldAPIService.Status } -func (apiServerStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (apiServerStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return validation.ValidateAPIService(obj.(*apiregistration.APIService)) } @@ -76,7 +76,7 @@ func (apiServerStrategy) AllowUnconditionalUpdate() bool { func (apiServerStrategy) Canonicalize(obj runtime.Object) { } -func (apiServerStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (apiServerStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateAPIServiceUpdate(obj.(*apiregistration.APIService), old.(*apiregistration.APIService)) } @@ -93,7 +93,7 @@ func (apiServerStatusStrategy) NamespaceScoped() bool { return false } -func (apiServerStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (apiServerStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newAPIService := obj.(*apiregistration.APIService) oldAPIService := old.(*apiregistration.APIService) newAPIService.Spec = oldAPIService.Spec @@ -114,7 +114,7 @@ func (apiServerStatusStrategy) AllowUnconditionalUpdate() bool { func (apiServerStatusStrategy) Canonicalize(obj runtime.Object) { } -func (apiServerStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (apiServerStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateAPIServiceStatusUpdate(obj.(*apiregistration.APIService), old.(*apiregistration.APIService)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/Godeps/Godeps.json index 9e1816bff..02d78f0f3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/Godeps/Godeps.json @@ -1,11 +1,15 @@ { "ImportPath": "k8s.io/metrics", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], "Deps": [ + { + "ImportPath": "github.com/davecgh/go-spew/spew", + "Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8" + }, { "ImportPath": "github.com/ghodss/yaml", "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" @@ -24,23 +28,27 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/google/btree", + "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" }, { "ImportPath": "github.com/google/gofuzz", @@ -58,17 +66,33 @@ "ImportPath": "github.com/googleapis/gnostic/extensions", "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { - "ImportPath": "github.com/spf13/pflag", - "Rev": "583c0c0531f06d5278b7d917446061adc344b5cd" + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/net/context", @@ -222,6 +246,10 @@ "ImportPath": "k8s.io/api/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -250,18 +278,6 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/resource", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -350,6 +366,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/util/json", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/util/net", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -362,6 +382,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/util/sets", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -386,6 +410,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/watch", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -410,6 +438,10 @@ "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/pkg/version", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -446,6 +478,10 @@ "ImportPath": "k8s.io/client-go/util/cert", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/connrotation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -453,6 +489,10 @@ { "ImportPath": "k8s.io/client-go/util/integer", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/boilerplate.go.txt b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/boilerplate.go.txt index 59e740c1e..b7c650da4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/boilerplate.go.txt +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright YEAR The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/update-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/update-codegen.sh index bb55d7388..87694c333 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/update-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/verify-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/verify-codegen.sh index f5835c425..ab43ba23d 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/verify-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/install/BUILD index 34aef6a40..4cf59f0f3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/install/BUILD @@ -10,9 +10,8 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/metrics/pkg/apis/custom_metrics/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/metrics/pkg/apis/custom_metrics:go_default_library", "//vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/install/install.go index 5bcfd9cd6..a20d6e4a5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/metrics/pkg/apis/custom_metrics" "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: custom_metrics.GroupName, - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: custom_metrics.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(custom_metrics.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go index be45d5532..2a85e80b8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -665,40 +665,39 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 546 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x41, 0x6f, 0xd3, 0x3e, - 0x18, 0xc6, 0x9b, 0xf5, 0xdf, 0x3f, 0x9b, 0xab, 0xa9, 0x2c, 0x17, 0xa2, 0x1e, 0xd2, 0xaa, 0x5c, - 0x0a, 0xd2, 0x6c, 0xb5, 0x20, 0x84, 0xc4, 0x2d, 0xe2, 0x82, 0x44, 0x41, 0x64, 0x13, 0x93, 0x00, - 0x09, 0x9c, 0xe4, 0x6d, 0x6a, 0xba, 0xc4, 0x91, 0xed, 0x74, 0xda, 0x8d, 0x13, 0x67, 0x3e, 0x56, - 0x8f, 0xe3, 0xb6, 0x53, 0x45, 0xc3, 0x17, 0x41, 0x49, 0x9c, 0xb6, 0x5b, 0x19, 0xb0, 0x5b, 0x6c, - 0xbf, 0xcf, 0xcf, 0xcf, 0xf3, 0xbe, 0x0e, 0x3a, 0x99, 0x3e, 0x95, 0x98, 0x71, 0x32, 0x4d, 0x3d, - 0x10, 0x31, 0x28, 0x90, 0x64, 0x06, 0x71, 0xc0, 0x05, 0xd1, 0x07, 0x11, 0x28, 0xc1, 0x7c, 0x49, - 0x92, 0x69, 0x48, 0x68, 0xc2, 0x24, 0xf1, 0x53, 0xa9, 0x78, 0xf4, 0xb1, 0xda, 0x9f, 0x0d, 0x3c, - 0x50, 0x74, 0x40, 0x42, 0x88, 0x41, 0x50, 0x05, 0x01, 0x4e, 0x04, 0x57, 0xdc, 0xc4, 0xa5, 0x1e, - 0xeb, 0x3a, 0x9c, 0x4c, 0x43, 0x9c, 0xeb, 0xf1, 0x55, 0x3d, 0xd6, 0xfa, 0xf6, 0x61, 0xc8, 0xd4, - 0x24, 0xf5, 0xb0, 0xcf, 0x23, 0x12, 0xf2, 0x90, 0x93, 0x02, 0xe3, 0xa5, 0xe3, 0x62, 0x55, 0x2c, - 0x8a, 0xaf, 0x12, 0xdf, 0xee, 0x69, 0x7b, 0x34, 0x61, 0xc4, 0xe7, 0x02, 0xc8, 0x6c, 0xcb, 0x42, - 0xfb, 0xf1, 0xba, 0x26, 0xa2, 0xfe, 0x84, 0xc5, 0x20, 0xce, 0xab, 0x1c, 0x44, 0x80, 0xe4, 0xa9, - 0xf0, 0xe1, 0x56, 0x2a, 0x99, 0xb7, 0x83, 0xfe, 0xee, 0x2e, 0x72, 0x93, 0x4a, 0xa4, 0xb1, 0x62, - 0xd1, 0xf6, 0x35, 0x4f, 0xfe, 0x26, 0x90, 0xfe, 0x04, 0x22, 0xba, 0xa5, 0x7b, 0x74, 0x93, 0x2e, - 0x55, 0xec, 0x94, 0xb0, 0x58, 0x49, 0x25, 0xae, 0x8b, 0x7a, 0x5f, 0xeb, 0xa8, 0x39, 0x2a, 0x1a, - 0xfe, 0x96, 0x9e, 0xa6, 0x60, 0x8e, 0x51, 0x2b, 0x00, 0xe9, 0x0b, 0xe6, 0x41, 0xf0, 0xda, 0xfb, - 0x0c, 0xbe, 0xb2, 0x8c, 0xae, 0xd1, 0x6f, 0x0e, 0xef, 0x57, 0x63, 0xa3, 0x09, 0xc3, 0x79, 0x5f, - 0xf1, 0x6c, 0x80, 0xcb, 0x0a, 0x17, 0xc6, 0x20, 0x20, 0xf6, 0xc1, 0xb9, 0x37, 0x5f, 0x74, 0x6a, - 0xd9, 0xa2, 0xd3, 0x7a, 0x7e, 0x95, 0xe1, 0x5e, 0x87, 0x9a, 0x43, 0x84, 0xca, 0x39, 0xbf, 0xa2, - 0x11, 0x58, 0x3b, 0x5d, 0xa3, 0xbf, 0xe7, 0x98, 0x5a, 0x8d, 0x46, 0xab, 0x13, 0x77, 0xa3, 0xca, - 0x7c, 0x8f, 0xf6, 0xf2, 0xfc, 0x52, 0xd1, 0x28, 0xb1, 0xea, 0x85, 0xab, 0x87, 0x1b, 0xae, 0x56, - 0xa1, 0xd7, 0x2f, 0x2a, 0x9f, 0x49, 0xee, 0xf3, 0x98, 0x45, 0xe0, 0x1c, 0x68, 0xfc, 0xde, 0x71, - 0x05, 0x71, 0xd7, 0x3c, 0xf3, 0x01, 0xfa, 0xff, 0x8c, 0xc5, 0x01, 0x3f, 0xb3, 0xfe, 0xeb, 0x1a, - 0xfd, 0xba, 0x73, 0x90, 0x2d, 0x3a, 0xfb, 0x27, 0xc5, 0xce, 0x11, 0xf8, 0x3c, 0x0e, 0xa4, 0xab, - 0x0b, 0xcc, 0x23, 0xd4, 0x98, 0xe5, 0xcd, 0xb2, 0x1a, 0x85, 0x07, 0xfc, 0x27, 0x0f, 0xb8, 0x7a, - 0x4d, 0xf8, 0x4d, 0x4a, 0x63, 0xc5, 0xd4, 0xb9, 0xb3, 0xaf, 0x7d, 0x34, 0x8a, 0x8e, 0xbb, 0x25, - 0xab, 0xf7, 0xdd, 0x40, 0xad, 0x8d, 0x41, 0xbc, 0x64, 0x52, 0x99, 0x1f, 0xd0, 0x6e, 0x9e, 0x20, - 0xa0, 0x8a, 0xea, 0x29, 0xe0, 0x7f, 0xcb, 0x9b, 0xab, 0x47, 0xa0, 0xa8, 0x73, 0x57, 0xdf, 0xb5, - 0x5b, 0xed, 0xb8, 0x2b, 0xa2, 0xf9, 0x09, 0x35, 0x98, 0x82, 0x48, 0x5a, 0x3b, 0xdd, 0x7a, 0xbf, - 0x39, 0x7c, 0x76, 0xcb, 0xff, 0x12, 0x6f, 0xb8, 0x5d, 0x67, 0x7a, 0x91, 0x13, 0xdd, 0x12, 0xec, - 0x1c, 0xce, 0x97, 0x76, 0xed, 0x62, 0x69, 0xd7, 0x2e, 0x97, 0x76, 0xed, 0x4b, 0x66, 0x1b, 0xf3, - 0xcc, 0x36, 0x2e, 0x32, 0xdb, 0xb8, 0xcc, 0x6c, 0xe3, 0x47, 0x66, 0x1b, 0xdf, 0x7e, 0xda, 0xb5, - 0x77, 0x77, 0x34, 0xf0, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x64, 0x6b, 0xb8, 0x76, 0x72, 0x04, - 0x00, 0x00, + // 531 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x4f, 0x6f, 0xd3, 0x30, + 0x18, 0xc6, 0x9b, 0x95, 0xc2, 0xe6, 0x69, 0x1a, 0xcb, 0x85, 0xa8, 0x87, 0xb4, 0x2a, 0x97, 0x82, + 0x34, 0x5b, 0xad, 0x10, 0x42, 0xe2, 0x16, 0x71, 0x41, 0xa2, 0x20, 0xb2, 0x89, 0x49, 0x80, 0x04, + 0x8e, 0xf3, 0x36, 0x35, 0x25, 0x71, 0x64, 0x3b, 0x9d, 0x76, 0xe3, 0xc4, 0x99, 0x8f, 0xd5, 0xe3, + 0xb8, 0xed, 0x54, 0xd1, 0xf0, 0x45, 0x50, 0x12, 0xa7, 0xed, 0x36, 0xfe, 0xed, 0x16, 0xdb, 0xef, + 0xf3, 0xf3, 0xf3, 0x3e, 0xaf, 0x83, 0x4e, 0xa6, 0x4f, 0x14, 0xe6, 0x82, 0x4c, 0xb3, 0x00, 0x64, + 0x02, 0x1a, 0x14, 0x99, 0x41, 0x12, 0x0a, 0x49, 0xcc, 0x41, 0x0c, 0x5a, 0x72, 0xa6, 0x48, 0x3a, + 0x8d, 0x08, 0x4d, 0xb9, 0x22, 0x2c, 0x53, 0x5a, 0xc4, 0x1f, 0xea, 0xfd, 0xd9, 0x20, 0x00, 0x4d, + 0x07, 0x24, 0x82, 0x04, 0x24, 0xd5, 0x10, 0xe2, 0x54, 0x0a, 0x2d, 0x6c, 0x5c, 0xe9, 0xb1, 0xa9, + 0xc3, 0xe9, 0x34, 0xc2, 0x85, 0x1e, 0x5f, 0xd6, 0x63, 0xa3, 0x6f, 0x1f, 0x46, 0x5c, 0x4f, 0xb2, + 0x00, 0x33, 0x11, 0x93, 0x48, 0x44, 0x82, 0x94, 0x98, 0x20, 0x1b, 0x97, 0xab, 0x72, 0x51, 0x7e, + 0x55, 0xf8, 0x76, 0xcf, 0xd8, 0xa3, 0x29, 0x27, 0x4c, 0x48, 0x20, 0xb3, 0x6b, 0x16, 0xda, 0x8f, + 0xd6, 0x35, 0x31, 0x65, 0x13, 0x9e, 0x80, 0x3c, 0xab, 0xfb, 0x20, 0x12, 0x94, 0xc8, 0x24, 0x83, + 0x1b, 0xa9, 0x54, 0x11, 0x07, 0xfd, 0xdd, 0x5d, 0xe4, 0x4f, 0x2a, 0x99, 0x25, 0x9a, 0xc7, 0xd7, + 0xaf, 0x79, 0xfc, 0x2f, 0x81, 0x62, 0x13, 0x88, 0xe9, 0x55, 0x5d, 0xef, 0x6b, 0x13, 0xed, 0x8e, + 0xca, 0xec, 0xde, 0xd0, 0xcf, 0x19, 0xd8, 0x63, 0xb4, 0x1f, 0x82, 0x62, 0x92, 0x07, 0x10, 0xbe, + 0x0a, 0x3e, 0x01, 0xd3, 0x8e, 0xd5, 0xb5, 0xfa, 0xbb, 0xc3, 0xfb, 0xf5, 0x04, 0x68, 0xca, 0x71, + 0x11, 0x11, 0x9e, 0x0d, 0x70, 0x55, 0xe1, 0xc3, 0x18, 0x24, 0x24, 0x0c, 0xbc, 0x7b, 0xf3, 0x45, + 0xa7, 0x91, 0x2f, 0x3a, 0xfb, 0xcf, 0x2e, 0x33, 0xfc, 0xab, 0x50, 0x7b, 0x88, 0x50, 0x35, 0xb2, + 0x97, 0x34, 0x06, 0x67, 0xab, 0x6b, 0xf5, 0x77, 0x3c, 0xdb, 0xa8, 0xd1, 0x68, 0x75, 0xe2, 0x6f, + 0x54, 0xd9, 0xef, 0xd0, 0x4e, 0xd1, 0x8a, 0xd2, 0x34, 0x4e, 0x9d, 0x66, 0xe9, 0xea, 0xe1, 0x86, + 0xab, 0x55, 0xdf, 0xeb, 0xc7, 0x51, 0xc4, 0x5b, 0xf8, 0x3c, 0xe6, 0x31, 0x78, 0x07, 0x06, 0xbf, + 0x73, 0x5c, 0x43, 0xfc, 0x35, 0xcf, 0x7e, 0x80, 0x6e, 0x9f, 0xf2, 0x24, 0x14, 0xa7, 0xce, 0xad, + 0xae, 0xd5, 0x6f, 0x7a, 0x07, 0xf9, 0xa2, 0xb3, 0x77, 0x52, 0xee, 0x1c, 0x01, 0x13, 0x49, 0xa8, + 0x7c, 0x53, 0x60, 0x1f, 0xa1, 0xd6, 0xac, 0x08, 0xcb, 0x69, 0x95, 0x1e, 0xf0, 0xdf, 0x3c, 0xe0, + 0xfa, 0x61, 0xe0, 0xd7, 0x19, 0x4d, 0x34, 0xd7, 0x67, 0xde, 0x9e, 0xf1, 0xd1, 0x2a, 0x13, 0xf7, + 0x2b, 0x56, 0xef, 0xbb, 0x85, 0xf6, 0x37, 0x06, 0xf1, 0x82, 0x2b, 0x6d, 0xbf, 0x47, 0xdb, 0x45, + 0x07, 0x21, 0xd5, 0xd4, 0x4c, 0x01, 0xff, 0x5f, 0xbf, 0x85, 0x7a, 0x04, 0x9a, 0x7a, 0x77, 0xcd, + 0x5d, 0xdb, 0xf5, 0x8e, 0xbf, 0x22, 0xda, 0x1f, 0x51, 0x8b, 0x6b, 0x88, 0x95, 0xb3, 0xd5, 0x6d, + 0xf6, 0x77, 0x87, 0x4f, 0x6f, 0xf8, 0x8b, 0xe1, 0x0d, 0xb7, 0xeb, 0x9e, 0x9e, 0x17, 0x44, 0xbf, + 0x02, 0x7b, 0x87, 0xf3, 0xa5, 0xdb, 0x38, 0x5f, 0xba, 0x8d, 0x8b, 0xa5, 0xdb, 0xf8, 0x92, 0xbb, + 0xd6, 0x3c, 0x77, 0xad, 0xf3, 0xdc, 0xb5, 0x2e, 0x72, 0xd7, 0xfa, 0x91, 0xbb, 0xd6, 0xb7, 0x9f, + 0x6e, 0xe3, 0xed, 0x1d, 0x03, 0xfc, 0x15, 0x00, 0x00, 0xff, 0xff, 0x7d, 0xe5, 0xb6, 0x67, 0x3d, + 0x04, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto index 1b8ad2f79..d05d84acb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go index 7c7134778..5c13881bf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go index e32c52827..1085b8338 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go index e361cf64a..0726e9e0f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/install/BUILD index df63ba222..9e075185e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/install/BUILD @@ -10,9 +10,8 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/metrics/pkg/apis/external_metrics/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/metrics/pkg/apis/external_metrics:go_default_library", "//vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/install/install.go index 6effb7f3e..5e110566d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/install/install.go @@ -19,25 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/metrics/pkg/apis/external_metrics" "k8s.io/metrics/pkg/apis/external_metrics/v1beta1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: external_metrics.GroupName, - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: external_metrics.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(external_metrics.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.pb.go index 71b70dc96..f5d3f0eab 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -783,41 +783,40 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 564 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x92, 0x4d, 0x6b, 0x13, 0x41, - 0x18, 0xc7, 0x33, 0x8d, 0xd1, 0x66, 0xda, 0x42, 0xb3, 0x16, 0x0c, 0x39, 0x6c, 0x42, 0x4f, 0x51, - 0xe8, 0x8c, 0x89, 0x22, 0xc5, 0x8b, 0xb0, 0x90, 0x83, 0xd0, 0x08, 0x6e, 0x8b, 0xc5, 0x17, 0x90, - 0xc9, 0xe6, 0x71, 0x33, 0x26, 0xfb, 0xc2, 0xcc, 0x6c, 0x6a, 0x6e, 0x7e, 0x04, 0xfd, 0x56, 0x39, - 0xf6, 0xd8, 0x53, 0x30, 0xdb, 0x8f, 0xe1, 0x45, 0x76, 0x77, 0xb6, 0x89, 0x49, 0x5f, 0x10, 0xbc, - 0xcd, 0x33, 0xcf, 0xfc, 0xff, 0xcf, 0x6f, 0xfe, 0x33, 0xf8, 0xfd, 0xf0, 0x50, 0x12, 0x1e, 0xd0, - 0x61, 0xd4, 0x03, 0xe1, 0x83, 0x02, 0x49, 0xc7, 0xe0, 0xf7, 0x03, 0x41, 0x75, 0xc3, 0x03, 0x25, - 0xb8, 0x23, 0x69, 0x38, 0x74, 0x29, 0x0b, 0xb9, 0xa4, 0xf0, 0x4d, 0x81, 0xf0, 0xd9, 0xe8, 0x73, - 0xde, 0x19, 0xb7, 0x7a, 0xa0, 0x58, 0x8b, 0xba, 0xe0, 0x83, 0x60, 0x0a, 0xfa, 0x24, 0x14, 0x81, - 0x0a, 0x8c, 0xa7, 0x99, 0x03, 0xd1, 0xe7, 0x48, 0x38, 0x74, 0x49, 0xe2, 0x40, 0x56, 0x1d, 0x88, - 0x76, 0xa8, 0x1d, 0xb8, 0x5c, 0x0d, 0xa2, 0x1e, 0x71, 0x02, 0x8f, 0xba, 0x81, 0x1b, 0xd0, 0xd4, - 0xa8, 0x17, 0x7d, 0x49, 0xab, 0xb4, 0x48, 0x57, 0xd9, 0x80, 0xda, 0x73, 0x8d, 0xc8, 0x42, 0xee, - 0x31, 0x67, 0xc0, 0x7d, 0x10, 0x93, 0x9c, 0x93, 0x0a, 0x90, 0x41, 0x24, 0x1c, 0x58, 0xc5, 0xba, - 0x55, 0x25, 0x93, 0xeb, 0x32, 0x3a, 0x5e, 0xbb, 0x4c, 0x8d, 0xde, 0xa4, 0x12, 0x91, 0xaf, 0xb8, - 0xb7, 0x3e, 0xe6, 0xc5, 0x5d, 0x02, 0xe9, 0x0c, 0xc0, 0x63, 0x6b, 0xba, 0x67, 0x37, 0xe9, 0x22, - 0xc5, 0x47, 0x94, 0xfb, 0x4a, 0x2a, 0xb1, 0x2a, 0xda, 0xff, 0x5d, 0xc4, 0x0f, 0x3b, 0x3a, 0xd5, - 0x6e, 0x1a, 0xea, 0x3b, 0x36, 0x8a, 0xc0, 0x68, 0x63, 0x9c, 0x65, 0xfc, 0x86, 0x79, 0x50, 0x45, - 0x0d, 0xd4, 0x2c, 0x5b, 0xc6, 0x74, 0x56, 0x2f, 0xc4, 0xb3, 0x3a, 0xee, 0x5e, 0x75, 0xec, 0xa5, - 0x53, 0xc6, 0x4f, 0x84, 0xb7, 0xb3, 0xf2, 0x88, 0xf5, 0x60, 0x24, 0xab, 0x1b, 0x8d, 0x62, 0x73, - 0xab, 0x7d, 0x4a, 0xfe, 0xf5, 0x39, 0xc9, 0x35, 0x44, 0xa4, 0xbb, 0xe4, 0xdc, 0xf1, 0x95, 0x98, - 0x58, 0x7b, 0x9a, 0x67, 0x7b, 0xb9, 0x65, 0xff, 0x85, 0x60, 0x7c, 0xc4, 0xe5, 0x24, 0x33, 0xa9, - 0x98, 0x17, 0x56, 0x8b, 0x0d, 0xd4, 0xdc, 0x6a, 0x3f, 0xc9, 0x79, 0x96, 0x83, 0x5a, 0x40, 0x25, - 0xef, 0x48, 0xc6, 0x2d, 0x72, 0xc2, 0x3d, 0xb0, 0x2a, 0x7a, 0x44, 0xf9, 0x24, 0x37, 0xb1, 0x17, - 0x7e, 0xc6, 0x63, 0x7c, 0xff, 0x8c, 0xfb, 0xfd, 0xe0, 0xac, 0x7a, 0xaf, 0x81, 0x9a, 0x45, 0xab, - 0x12, 0xcf, 0xea, 0x3b, 0xa7, 0xe9, 0xce, 0x31, 0x38, 0x81, 0xdf, 0x97, 0xb6, 0x3e, 0x60, 0x1c, - 0xe3, 0xd2, 0x38, 0xb9, 0x46, 0xb5, 0x94, 0x32, 0x90, 0xdb, 0x18, 0x48, 0xfe, 0x03, 0xc9, 0xdb, - 0x88, 0xf9, 0x8a, 0xab, 0x89, 0xb5, 0xa3, 0x39, 0x4a, 0x69, 0x16, 0x76, 0xe6, 0x55, 0x7b, 0x85, - 0x2b, 0x6b, 0xa9, 0x18, 0xbb, 0xb8, 0x38, 0x84, 0x49, 0xf6, 0x64, 0x76, 0xb2, 0x34, 0xf6, 0xf2, - 0xd9, 0x1b, 0xe9, 0x5e, 0x56, 0xbc, 0xdc, 0x38, 0x44, 0xfb, 0x97, 0x08, 0x3f, 0xba, 0x26, 0xeb, - 0x23, 0x2e, 0x95, 0xf1, 0x09, 0x6f, 0x26, 0x51, 0xf4, 0x99, 0x62, 0xa9, 0xd9, 0x1d, 0xd0, 0x8b, - 0xe0, 0x12, 0x75, 0x17, 0x14, 0xb3, 0x76, 0x35, 0xf4, 0x66, 0xbe, 0x63, 0x5f, 0x39, 0x1a, 0x5f, - 0x71, 0x89, 0x2b, 0xf0, 0xf2, 0x3f, 0xd2, 0xf9, 0x2f, 0x7f, 0x64, 0x11, 0xd3, 0xeb, 0xc4, 0xdb, - 0xce, 0x46, 0x58, 0x07, 0xd3, 0xb9, 0x59, 0x38, 0x9f, 0x9b, 0x85, 0x8b, 0xb9, 0x59, 0xf8, 0x1e, - 0x9b, 0x68, 0x1a, 0x9b, 0xe8, 0x3c, 0x36, 0xd1, 0x45, 0x6c, 0xa2, 0x5f, 0xb1, 0x89, 0x7e, 0x5c, - 0x9a, 0x85, 0x0f, 0x0f, 0xb4, 0xf1, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf5, 0x48, 0x2f, 0x06, - 0xd9, 0x04, 0x00, 0x00, + // 551 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x92, 0xcf, 0x6b, 0x13, 0x41, + 0x14, 0xc7, 0x33, 0x89, 0xd1, 0x66, 0xda, 0x42, 0xb3, 0x16, 0x0c, 0x39, 0x6c, 0x42, 0x4f, 0x51, + 0xe8, 0x8c, 0x09, 0x22, 0xc5, 0x8b, 0xb0, 0x90, 0x83, 0xd0, 0x08, 0x6e, 0x8b, 0xc5, 0x1f, 0x20, + 0x93, 0xcd, 0x73, 0x33, 0x26, 0xfb, 0x83, 0x99, 0xd9, 0xd4, 0xdc, 0xfc, 0x13, 0xf4, 0xbf, 0xca, + 0xb1, 0xc7, 0x9e, 0x82, 0xd9, 0xfe, 0x19, 0x5e, 0x64, 0x77, 0x67, 0x9b, 0x98, 0xd4, 0x16, 0xc1, + 0xdb, 0xbc, 0x79, 0xf3, 0xbe, 0xef, 0xf3, 0xbe, 0xf3, 0xf0, 0xbb, 0xd1, 0x91, 0x24, 0x3c, 0xa0, + 0xa3, 0xa8, 0x0f, 0xc2, 0x07, 0x05, 0x92, 0x4e, 0xc0, 0x1f, 0x04, 0x82, 0xea, 0x84, 0x07, 0x4a, + 0x70, 0x47, 0xd2, 0x70, 0xe4, 0x52, 0x16, 0x72, 0x49, 0xe1, 0xab, 0x02, 0xe1, 0xb3, 0xf1, 0xa7, + 0x3c, 0x33, 0x69, 0xf7, 0x41, 0xb1, 0x36, 0x75, 0xc1, 0x07, 0xc1, 0x14, 0x0c, 0x48, 0x28, 0x02, + 0x15, 0x18, 0x4f, 0x33, 0x05, 0xa2, 0xdf, 0x91, 0x70, 0xe4, 0x92, 0x44, 0x81, 0xac, 0x2b, 0x10, + 0xad, 0x50, 0x3f, 0x74, 0xb9, 0x1a, 0x46, 0x7d, 0xe2, 0x04, 0x1e, 0x75, 0x03, 0x37, 0xa0, 0xa9, + 0x50, 0x3f, 0xfa, 0x9c, 0x46, 0x69, 0x90, 0x9e, 0xb2, 0x06, 0xf5, 0x67, 0x1a, 0x91, 0x85, 0xdc, + 0x63, 0xce, 0x90, 0xfb, 0x20, 0xa6, 0x39, 0x27, 0x15, 0x20, 0x83, 0x48, 0x38, 0xb0, 0x8e, 0x75, + 0x6b, 0x95, 0x4c, 0xc6, 0x65, 0x74, 0xb2, 0x31, 0x4c, 0x9d, 0xfe, 0xad, 0x4a, 0x44, 0xbe, 0xe2, + 0xde, 0x66, 0x9b, 0xe7, 0x77, 0x15, 0x48, 0x67, 0x08, 0x1e, 0x5b, 0xaf, 0x3b, 0xf8, 0x55, 0xc2, + 0x0f, 0xbb, 0xda, 0xa0, 0x5e, 0xea, 0xcf, 0x5b, 0x36, 0x8e, 0xc0, 0xe8, 0x60, 0x9c, 0xd9, 0xf5, + 0x9a, 0x79, 0x50, 0x43, 0x4d, 0xd4, 0xaa, 0x58, 0xc6, 0x6c, 0xde, 0x28, 0xc4, 0xf3, 0x06, 0xee, + 0x5d, 0x67, 0xec, 0x95, 0x57, 0xc6, 0x0f, 0x84, 0x77, 0xb2, 0xf0, 0x98, 0xf5, 0x61, 0x2c, 0x6b, + 0xc5, 0x66, 0xa9, 0xb5, 0xdd, 0x39, 0x23, 0xff, 0xfa, 0x33, 0xe4, 0x06, 0x22, 0xd2, 0x5b, 0x51, + 0xee, 0xfa, 0x4a, 0x4c, 0xad, 0x7d, 0xcd, 0xb3, 0xb3, 0x9a, 0xb2, 0xff, 0x40, 0x30, 0x3e, 0xe0, + 0x4a, 0x32, 0xbe, 0x54, 0xcc, 0x0b, 0x6b, 0xa5, 0x26, 0x6a, 0x6d, 0x77, 0x9e, 0xe4, 0x3c, 0xab, + 0x5e, 0x2d, 0xa1, 0x92, 0x2f, 0x21, 0x93, 0x36, 0x39, 0xe5, 0x1e, 0x58, 0x55, 0xdd, 0xa2, 0x72, + 0x9a, 0x8b, 0xd8, 0x4b, 0x3d, 0xe3, 0x31, 0xbe, 0x7f, 0xce, 0xfd, 0x41, 0x70, 0x5e, 0xbb, 0xd7, + 0x44, 0xad, 0x92, 0x55, 0x8d, 0xe7, 0x8d, 0xdd, 0xb3, 0xf4, 0xe6, 0x04, 0x9c, 0xc0, 0x1f, 0x48, + 0x5b, 0x3f, 0x30, 0x4e, 0x70, 0x79, 0x92, 0x8c, 0x51, 0x2b, 0xa7, 0x0c, 0xe4, 0x36, 0x06, 0x92, + 0x2f, 0x13, 0x79, 0x13, 0x31, 0x5f, 0x71, 0x35, 0xb5, 0x76, 0x35, 0x47, 0x39, 0xf5, 0xc2, 0xce, + 0xb4, 0xea, 0x2f, 0x71, 0x75, 0xc3, 0x15, 0x63, 0x0f, 0x97, 0x46, 0x30, 0xcd, 0xbe, 0xcc, 0x4e, + 0x8e, 0xc6, 0x7e, 0xde, 0xbb, 0x98, 0xde, 0x65, 0xc1, 0x8b, 0xe2, 0x11, 0x3a, 0xb8, 0x42, 0xf8, + 0xd1, 0x0d, 0x5e, 0x1f, 0x73, 0xa9, 0x8c, 0x8f, 0x78, 0x2b, 0xb1, 0x62, 0xc0, 0x14, 0x4b, 0xc5, + 0xee, 0x80, 0x5e, 0x1a, 0x97, 0x54, 0xf7, 0x40, 0x31, 0x6b, 0x4f, 0x43, 0x6f, 0xe5, 0x37, 0xf6, + 0xb5, 0xa2, 0xf1, 0x05, 0x97, 0xb9, 0x02, 0x2f, 0xdf, 0x91, 0xee, 0x7f, 0xd9, 0x91, 0xa5, 0x4d, + 0xaf, 0x12, 0x6d, 0x3b, 0x6b, 0x61, 0x1d, 0xce, 0x16, 0x66, 0xe1, 0x62, 0x61, 0x16, 0x2e, 0x17, + 0x66, 0xe1, 0x5b, 0x6c, 0xa2, 0x59, 0x6c, 0xa2, 0x8b, 0xd8, 0x44, 0x97, 0xb1, 0x89, 0x7e, 0xc6, + 0x26, 0xfa, 0x7e, 0x65, 0x16, 0xde, 0x3f, 0xd0, 0xc2, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xbf, + 0x2a, 0x7e, 0x2e, 0xa4, 0x04, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.proto index 2fb3f5637..53aec67e6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -25,7 +25,6 @@ import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.conversion.go index 3069dd064..72c406946 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.deepcopy.go index ba062b977..3fce1499c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/zz_generated.deepcopy.go index b2dc1eb6c..77c546e7e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/external_metrics/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/install/BUILD index 3cf280e14..81fee72db 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/install/BUILD @@ -10,10 +10,8 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/metrics/pkg/apis/metrics/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/metrics/pkg/apis/metrics:go_default_library", "//vendor/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/install/install.go index b3e6eb518..c5f719dcb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/install/install.go @@ -19,27 +19,15 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/metrics/pkg/apis/metrics" "k8s.io/metrics/pkg/apis/metrics/v1beta1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: metrics.GroupName, - VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version}, - RootScopedKinds: sets.NewString("NodeMetrics"), - AddInternalObjectsToScheme: metrics.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(metrics.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/generated.pb.go index c92780182..6bd8967b4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1517,48 +1517,47 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 675 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x54, 0xbf, 0x6f, 0x13, 0x3d, - 0x18, 0x8e, 0x9b, 0xa4, 0x6a, 0x9d, 0xef, 0xeb, 0xd7, 0xef, 0xa6, 0x2a, 0xc3, 0xa5, 0xca, 0x14, - 0x21, 0xd5, 0x47, 0x4b, 0x41, 0x55, 0x27, 0x74, 0xb4, 0x03, 0x12, 0x2d, 0xf4, 0x54, 0x40, 0x14, - 0x06, 0x9c, 0x8b, 0xb9, 0x98, 0xf4, 0xec, 0x93, 0xed, 0x4b, 0x95, 0x0d, 0x01, 0x13, 0x13, 0x12, - 0xff, 0x54, 0x11, 0x4b, 0xc7, 0x2e, 0xb4, 0xf4, 0xd8, 0xf9, 0x03, 0x98, 0xd0, 0x39, 0xbe, 0x5c, - 0x68, 0xfa, 0x23, 0x74, 0x60, 0xea, 0x76, 0xf7, 0xda, 0xcf, 0xf3, 0xbc, 0x7e, 0xde, 0xc7, 0x86, - 0x5b, 0x9d, 0x15, 0x89, 0x28, 0x77, 0x3a, 0x71, 0x93, 0x08, 0x46, 0x14, 0x91, 0x4e, 0x97, 0xb0, - 0x16, 0x17, 0x8e, 0x59, 0x08, 0x89, 0x12, 0xd4, 0x97, 0x4e, 0xd4, 0x09, 0x1c, 0x1c, 0x51, 0x39, - 0x28, 0x74, 0x17, 0xf1, 0x6e, 0xd4, 0xc6, 0x8b, 0x4e, 0x40, 0x18, 0x11, 0x58, 0x91, 0x16, 0x8a, - 0x04, 0x57, 0xdc, 0x6a, 0xf4, 0x91, 0xc8, 0x6c, 0x44, 0x51, 0x27, 0x40, 0x29, 0x72, 0x50, 0xc8, - 0x90, 0xd5, 0x85, 0x80, 0xaa, 0x76, 0xdc, 0x44, 0x3e, 0x0f, 0x9d, 0x80, 0x07, 0xdc, 0xd1, 0x04, - 0xcd, 0xf8, 0x95, 0xfe, 0xd3, 0x3f, 0xfa, 0xab, 0x4f, 0x5c, 0xad, 0x9b, 0x96, 0x70, 0x44, 0x1d, - 0x9f, 0x0b, 0xe2, 0x74, 0x47, 0xc4, 0xab, 0xcb, 0xf9, 0x9e, 0x10, 0xfb, 0x6d, 0xca, 0x88, 0xe8, - 0x65, 0xbd, 0x3b, 0x82, 0x48, 0x1e, 0x0b, 0x9f, 0xfc, 0x11, 0x4a, 0x9f, 0x18, 0x9f, 0xa5, 0xe5, - 0x9c, 0x87, 0x12, 0x31, 0x53, 0x34, 0x1c, 0x95, 0xb9, 0x73, 0x19, 0x40, 0xfa, 0x6d, 0x12, 0xe2, - 0x11, 0xdc, 0xad, 0xf3, 0x70, 0xb1, 0xa2, 0xbb, 0x0e, 0x65, 0x4a, 0x2a, 0x71, 0x1a, 0x54, 0x7f, - 0x57, 0x84, 0xb3, 0xf7, 0x38, 0x53, 0x38, 0xdd, 0xbe, 0xd1, 0xb7, 0xde, 0x9a, 0x87, 0x25, 0x86, - 0x43, 0x32, 0x07, 0xe6, 0x41, 0x63, 0xda, 0xfd, 0x67, 0xff, 0xa8, 0x56, 0x48, 0x8e, 0x6a, 0xa5, - 0x4d, 0x1c, 0x12, 0x4f, 0xaf, 0x58, 0x09, 0x80, 0xe5, 0x58, 0xe2, 0x80, 0xcc, 0x4d, 0xcc, 0x17, - 0x1b, 0x95, 0xa5, 0x75, 0x34, 0xee, 0x38, 0xd1, 0x69, 0x35, 0xf4, 0x38, 0xe5, 0x59, 0x67, 0x4a, - 0xf4, 0xdc, 0xf7, 0xc0, 0x68, 0x95, 0x75, 0xf1, 0xe7, 0x51, 0xad, 0x36, 0x3a, 0x4d, 0xe4, 0x99, - 0x01, 0x3d, 0xa0, 0x52, 0xbd, 0x3d, 0xbe, 0x70, 0x4b, 0xda, 0xf2, 0x87, 0xe3, 0xda, 0xc2, 0x38, - 0xf3, 0x46, 0x5b, 0x31, 0x66, 0x8a, 0xaa, 0x9e, 0xd7, 0x3f, 0x5a, 0xb5, 0x0d, 0x61, 0xde, 0x9b, - 0x35, 0x0b, 0x8b, 0x1d, 0xd2, 0xeb, 0x7b, 0xe2, 0xa5, 0x9f, 0xd6, 0x1a, 0x2c, 0x77, 0xf1, 0x6e, - 0x9c, 0x7a, 0x00, 0x1a, 0x95, 0x25, 0x94, 0x79, 0x30, 0xac, 0x92, 0x19, 0x81, 0xce, 0x50, 0xd1, - 0xe0, 0xd5, 0x89, 0x15, 0x50, 0xff, 0x51, 0x82, 0x95, 0x4d, 0xde, 0x22, 0xd9, 0x00, 0x5e, 0xc2, - 0xa9, 0x34, 0x4e, 0x2d, 0xac, 0xb0, 0x16, 0xac, 0x2c, 0xdd, 0xbc, 0x88, 0x5c, 0xbb, 0x8c, 0x51, - 0x77, 0x11, 0x3d, 0x6c, 0xbe, 0x26, 0xbe, 0xda, 0x20, 0x0a, 0xbb, 0x96, 0xb1, 0x12, 0xe6, 0x35, - 0x6f, 0xc0, 0x6a, 0x3d, 0x87, 0xd3, 0x69, 0x96, 0xa4, 0xc2, 0x61, 0x64, 0xfa, 0xbf, 0x31, 0x9e, - 0xc4, 0x36, 0x0d, 0x89, 0xfb, 0xbf, 0x21, 0x9f, 0xde, 0xce, 0x48, 0xbc, 0x9c, 0xcf, 0x7a, 0x02, - 0x27, 0xf7, 0x28, 0x6b, 0xf1, 0xbd, 0xb9, 0xe2, 0xe5, 0xce, 0xe4, 0xcc, 0x6b, 0xb1, 0xc0, 0x8a, - 0x72, 0xe6, 0xce, 0x18, 0xf6, 0xc9, 0xa7, 0x9a, 0xc5, 0x33, 0x6c, 0xd6, 0xd7, 0x41, 0xea, 0x4a, - 0x3a, 0x75, 0x77, 0xc7, 0x4f, 0xdd, 0x90, 0xbb, 0xd7, 0x81, 0x03, 0xf5, 0x2f, 0x00, 0xfe, 0x37, - 0x64, 0x49, 0x7a, 0x30, 0xeb, 0xc5, 0x48, 0xe8, 0xc6, 0x9c, 0x5b, 0x8a, 0xd6, 0x91, 0x9b, 0x35, - 0x66, 0x4e, 0x65, 0x95, 0xa1, 0xc0, 0xed, 0xc0, 0x32, 0x55, 0x24, 0x94, 0xe6, 0xc1, 0xb8, 0x7d, - 0xa5, 0xd1, 0xb9, 0xff, 0x66, 0xe3, 0xba, 0x9f, 0x72, 0x79, 0x7d, 0xca, 0xfa, 0xa7, 0x22, 0x84, - 0x8f, 0x78, 0xeb, 0xfa, 0xf6, 0x5c, 0x78, 0x7b, 0x18, 0x84, 0x7e, 0xf6, 0xf6, 0x4a, 0x73, 0x83, - 0x56, 0xaf, 0xfe, 0x6e, 0xe7, 0x16, 0x0d, 0x56, 0xa4, 0x37, 0xa4, 0x50, 0xff, 0x0c, 0xe0, 0x4c, - 0x3e, 0x95, 0xbf, 0x10, 0xb1, 0x67, 0xbf, 0x47, 0x6c, 0x79, 0xfc, 0xb3, 0xe5, 0x6d, 0x9e, 0x9d, - 0x30, 0x17, 0xed, 0x9f, 0xd8, 0x85, 0x83, 0x13, 0xbb, 0x70, 0x78, 0x62, 0x17, 0xde, 0x24, 0x36, - 0xd8, 0x4f, 0x6c, 0x70, 0x90, 0xd8, 0xe0, 0x30, 0xb1, 0xc1, 0xb7, 0xc4, 0x06, 0x1f, 0xbf, 0xdb, - 0x85, 0x9d, 0xa9, 0x8c, 0xf0, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc4, 0xa1, 0x90, 0x7a, 0x31, - 0x09, 0x00, 0x00, + // 658 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x54, 0x41, 0x4f, 0x13, 0x41, + 0x18, 0xed, 0xd0, 0x96, 0xc0, 0x54, 0x11, 0xf7, 0x44, 0x7a, 0xd8, 0x92, 0x9e, 0x1a, 0x13, 0x66, + 0x85, 0xa0, 0x21, 0x9c, 0xcc, 0x0a, 0x07, 0x13, 0x41, 0xd9, 0xa0, 0x46, 0xf4, 0xe0, 0x74, 0x3b, + 0x6e, 0xc7, 0xb2, 0x33, 0x9b, 0x99, 0xd9, 0x92, 0xde, 0x8c, 0x7a, 0xf2, 0x64, 0xe2, 0x9f, 0xc2, + 0x78, 0xe1, 0xc8, 0x45, 0x90, 0xf5, 0xee, 0x0f, 0xf0, 0x64, 0x76, 0x3a, 0xdb, 0xad, 0x14, 0xa1, + 0x72, 0xf0, 0xc4, 0x6d, 0xf7, 0x9b, 0x79, 0xef, 0x7d, 0xf3, 0xbe, 0x37, 0x03, 0xb7, 0x3a, 0x2b, + 0x12, 0x51, 0xee, 0x74, 0xe2, 0x26, 0x11, 0x8c, 0x28, 0x22, 0x9d, 0x2e, 0x61, 0x2d, 0x2e, 0x1c, + 0xb3, 0x10, 0x12, 0x25, 0xa8, 0x2f, 0x9d, 0xa8, 0x13, 0x38, 0x38, 0xa2, 0x72, 0x50, 0xe8, 0x2e, + 0xe2, 0xdd, 0xa8, 0x8d, 0x17, 0x9d, 0x80, 0x30, 0x22, 0xb0, 0x22, 0x2d, 0x14, 0x09, 0xae, 0xb8, + 0xd5, 0xe8, 0x23, 0x91, 0xd9, 0x88, 0xa2, 0x4e, 0x80, 0x52, 0xe4, 0xa0, 0x90, 0x21, 0xab, 0x0b, + 0x01, 0x55, 0xed, 0xb8, 0x89, 0x7c, 0x1e, 0x3a, 0x01, 0x0f, 0xb8, 0xa3, 0x09, 0x9a, 0xf1, 0x6b, + 0xfd, 0xa7, 0x7f, 0xf4, 0x57, 0x9f, 0xb8, 0x5a, 0x37, 0x2d, 0xe1, 0x88, 0x3a, 0x3e, 0x17, 0xc4, + 0xe9, 0x8e, 0x88, 0x57, 0x97, 0xf3, 0x3d, 0x21, 0xf6, 0xdb, 0x94, 0x11, 0xd1, 0xcb, 0x7a, 0x77, + 0x04, 0x91, 0x3c, 0x16, 0x3e, 0xf9, 0x27, 0x94, 0x3e, 0x31, 0x3e, 0x4b, 0xcb, 0xf9, 0x1b, 0x4a, + 0xc4, 0x4c, 0xd1, 0x70, 0x54, 0xe6, 0xee, 0x45, 0x00, 0xe9, 0xb7, 0x49, 0x88, 0x4f, 0xe3, 0xea, + 0xef, 0x8b, 0x70, 0xf6, 0x3e, 0x67, 0x0a, 0xa7, 0x88, 0x8d, 0xbe, 0x8b, 0xd6, 0x3c, 0x2c, 0x31, + 0x1c, 0x92, 0x39, 0x30, 0x0f, 0x1a, 0xd3, 0xee, 0xb5, 0xfd, 0xa3, 0x5a, 0x21, 0x39, 0xaa, 0x95, + 0x36, 0x71, 0x48, 0x3c, 0xbd, 0x62, 0x25, 0x00, 0x96, 0x63, 0x89, 0x03, 0x32, 0x37, 0x31, 0x5f, + 0x6c, 0x54, 0x96, 0xd6, 0xd1, 0xb8, 0x93, 0x41, 0xa7, 0xd5, 0xd0, 0x93, 0x94, 0x67, 0x9d, 0x29, + 0xd1, 0x73, 0x3f, 0x00, 0xa3, 0x55, 0xd6, 0xc5, 0x5f, 0x47, 0xb5, 0xda, 0xe8, 0x60, 0x90, 0x67, + 0xbc, 0x7e, 0x48, 0xa5, 0x7a, 0x77, 0x7c, 0xee, 0x96, 0xb4, 0xe5, 0x8f, 0xc7, 0xb5, 0x85, 0x71, + 0x46, 0x87, 0xb6, 0x62, 0xcc, 0x14, 0x55, 0x3d, 0xaf, 0x7f, 0xb4, 0x6a, 0x1b, 0xc2, 0xbc, 0x37, + 0x6b, 0x16, 0x16, 0x3b, 0xa4, 0xd7, 0xf7, 0xc4, 0x4b, 0x3f, 0xad, 0x35, 0x58, 0xee, 0xe2, 0xdd, + 0x38, 0xf5, 0x00, 0x34, 0x2a, 0x4b, 0x28, 0xf3, 0x60, 0x58, 0x25, 0x33, 0x02, 0x9d, 0xa1, 0xa2, + 0xc1, 0xab, 0x13, 0x2b, 0xa0, 0xfe, 0xb3, 0x04, 0x2b, 0x9b, 0xbc, 0x45, 0xb2, 0x01, 0xbc, 0x82, + 0x53, 0x69, 0x32, 0x5a, 0x58, 0x61, 0x2d, 0x58, 0x59, 0xba, 0x7d, 0x1e, 0xb9, 0x76, 0x19, 0xa3, + 0xee, 0x22, 0x7a, 0xd4, 0x7c, 0x43, 0x7c, 0xb5, 0x41, 0x14, 0x76, 0x2d, 0x63, 0x25, 0xcc, 0x6b, + 0xde, 0x80, 0xd5, 0x7a, 0x01, 0xa7, 0xd3, 0x58, 0x48, 0x85, 0xc3, 0xc8, 0xf4, 0x7f, 0x6b, 0x3c, + 0x89, 0x6d, 0x1a, 0x12, 0xf7, 0xa6, 0x21, 0x9f, 0xde, 0xce, 0x48, 0xbc, 0x9c, 0xcf, 0x7a, 0x0a, + 0x27, 0xf7, 0x28, 0x6b, 0xf1, 0xbd, 0xb9, 0xe2, 0xc5, 0xce, 0xe4, 0xcc, 0x6b, 0xb1, 0xc0, 0x8a, + 0x72, 0xe6, 0xce, 0x18, 0xf6, 0xc9, 0x67, 0x9a, 0xc5, 0x33, 0x6c, 0xd6, 0xb7, 0x41, 0xea, 0x4a, + 0x3a, 0x75, 0xf7, 0xc6, 0x4f, 0xdd, 0x90, 0xbb, 0x57, 0x81, 0x03, 0xf5, 0xaf, 0x00, 0xde, 0x18, + 0xb2, 0x24, 0x3d, 0x98, 0xf5, 0x72, 0x24, 0x74, 0x63, 0xce, 0x2d, 0x45, 0xeb, 0xc8, 0xcd, 0x1a, + 0x33, 0xa7, 0xb2, 0xca, 0x50, 0xe0, 0x76, 0x60, 0x99, 0x2a, 0x12, 0x4a, 0xf3, 0x60, 0xdc, 0xb9, + 0xd4, 0xe8, 0xdc, 0xeb, 0xd9, 0xb8, 0x1e, 0xa4, 0x5c, 0x5e, 0x9f, 0xb2, 0xfe, 0xb9, 0x08, 0xe1, + 0x63, 0xde, 0xba, 0xba, 0x3d, 0xe7, 0xde, 0x1e, 0x06, 0xa1, 0x9f, 0xbd, 0xbd, 0xd2, 0xdc, 0xa0, + 0xd5, 0xcb, 0xbf, 0xdb, 0xb9, 0x45, 0x83, 0x15, 0xe9, 0x0d, 0x29, 0xd4, 0xbf, 0x00, 0x38, 0x93, + 0x4f, 0xe5, 0x3f, 0x44, 0xec, 0xf9, 0x9f, 0x11, 0x5b, 0x1e, 0xff, 0x6c, 0x79, 0x9b, 0x67, 0x27, + 0xcc, 0x45, 0xfb, 0x27, 0x76, 0xe1, 0xe0, 0xc4, 0x2e, 0x1c, 0x9e, 0xd8, 0x85, 0xb7, 0x89, 0x0d, + 0xf6, 0x13, 0x1b, 0x1c, 0x24, 0x36, 0x38, 0x4c, 0x6c, 0xf0, 0x3d, 0xb1, 0xc1, 0xa7, 0x1f, 0x76, + 0x61, 0x67, 0x2a, 0x23, 0xfc, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xa6, 0xe6, 0x48, 0x8b, 0xfc, 0x08, + 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/generated.proto index 8546cf8be..41b8f2e10 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1alpha1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/zz_generated.conversion.go index ffd8a20df..4f775addc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/zz_generated.deepcopy.go index 05337bd6d..28a106338 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/generated.pb.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/generated.pb.go index 184e7aa32..4d287a29e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/generated.pb.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -1517,47 +1517,47 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 671 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x54, 0xbd, 0x6f, 0x13, 0x31, - 0x1c, 0x8d, 0x9b, 0xa4, 0xb4, 0x0e, 0x94, 0x72, 0x53, 0x95, 0xe1, 0x52, 0x65, 0xa1, 0x42, 0xaa, - 0x4d, 0x3f, 0x84, 0x0a, 0x0b, 0xd2, 0x51, 0x06, 0x24, 0x5a, 0xca, 0xa9, 0x7c, 0x33, 0xe0, 0x5c, - 0xcc, 0xc5, 0xa4, 0x77, 0x8e, 0x6c, 0x5f, 0xaa, 0x6c, 0xa8, 0x62, 0x62, 0x42, 0xfc, 0x55, 0x11, - 0x53, 0xc7, 0x0e, 0xa8, 0x25, 0x61, 0xe6, 0x1f, 0x60, 0x42, 0xe7, 0xf8, 0x72, 0xa1, 0xe9, 0xc7, - 0xd1, 0x81, 0xa9, 0xdb, 0xdd, 0xcf, 0x7e, 0xef, 0xfd, 0xfc, 0x7e, 0xcf, 0x86, 0x5b, 0xcd, 0x35, - 0x89, 0x18, 0xc7, 0xcd, 0xa8, 0x46, 0x45, 0x48, 0x15, 0x95, 0xb8, 0x4d, 0xc3, 0x3a, 0x17, 0xd8, - 0x2c, 0x04, 0x54, 0x09, 0xe6, 0x49, 0xdc, 0x6a, 0xfa, 0x98, 0xb4, 0x98, 0x1c, 0x16, 0xda, 0x4b, - 0x35, 0xaa, 0xc8, 0x12, 0xf6, 0x69, 0x48, 0x05, 0x51, 0xb4, 0x8e, 0x5a, 0x82, 0x2b, 0x6e, 0xdd, - 0x1c, 0x00, 0x91, 0xd9, 0x87, 0x5a, 0x4d, 0x1f, 0xc5, 0xc0, 0x61, 0xc1, 0x00, 0xcb, 0x8b, 0x3e, - 0x53, 0x8d, 0xa8, 0x86, 0x3c, 0x1e, 0x60, 0x9f, 0xfb, 0x1c, 0x6b, 0x7c, 0x2d, 0x7a, 0xaf, 0xff, - 0xf4, 0x8f, 0xfe, 0x1a, 0xf0, 0x96, 0xab, 0xa6, 0x21, 0xd2, 0x62, 0xd8, 0xe3, 0x82, 0xe2, 0xf6, - 0x98, 0x76, 0x79, 0x35, 0xdd, 0x13, 0x10, 0xaf, 0xc1, 0x42, 0x2a, 0x3a, 0x49, 0xe7, 0x58, 0x50, - 0xc9, 0x23, 0xe1, 0xd1, 0x7f, 0x42, 0xe9, 0xf3, 0x92, 0x93, 0xb4, 0xf0, 0x69, 0x28, 0x11, 0x85, - 0x8a, 0x05, 0xe3, 0x32, 0x77, 0xce, 0x03, 0x48, 0xaf, 0x41, 0x03, 0x32, 0x86, 0x5b, 0x39, 0x0d, - 0x17, 0x29, 0xb6, 0x83, 0x59, 0xa8, 0xa4, 0x12, 0xc7, 0x41, 0xd5, 0xbd, 0x3c, 0x9c, 0x7d, 0xc0, - 0x43, 0x45, 0xe2, 0xed, 0x1b, 0x03, 0xe7, 0xad, 0x79, 0x58, 0x08, 0x49, 0x40, 0xe7, 0xc0, 0x3c, - 0x58, 0x98, 0x76, 0xae, 0x76, 0x0f, 0x2b, 0xb9, 0xfe, 0x61, 0xa5, 0xb0, 0x49, 0x02, 0xea, 0xea, - 0x15, 0xab, 0x07, 0x60, 0x31, 0x92, 0xc4, 0xa7, 0x73, 0x13, 0xf3, 0xf9, 0x85, 0xd2, 0xf2, 0x3a, - 0xca, 0x38, 0x4d, 0x74, 0x5c, 0x0c, 0x3d, 0x8b, 0x69, 0x1e, 0x86, 0x4a, 0x74, 0x9c, 0x4f, 0xc0, - 0x48, 0x15, 0x75, 0xf1, 0xf7, 0x61, 0xa5, 0x32, 0x3e, 0x4c, 0xe4, 0x9a, 0xf9, 0x3c, 0x66, 0x52, - 0xed, 0x1d, 0x9d, 0xb9, 0x25, 0xee, 0xf8, 0xf3, 0x51, 0x65, 0x31, 0xcb, 0xb8, 0xd1, 0xd3, 0x88, - 0x84, 0x8a, 0xa9, 0x8e, 0x3b, 0x38, 0x59, 0xb9, 0x01, 0x61, 0xda, 0x9b, 0x35, 0x0b, 0xf3, 0x4d, - 0xda, 0x19, 0x58, 0xe2, 0xc6, 0x9f, 0xd6, 0x3a, 0x2c, 0xb6, 0xc9, 0x4e, 0x14, 0x5b, 0x00, 0x16, - 0x4a, 0xcb, 0x28, 0xb1, 0x60, 0x54, 0x25, 0xf1, 0x01, 0x9d, 0xa0, 0xa2, 0xc1, 0xf7, 0x26, 0xd6, - 0x40, 0xf5, 0x57, 0x01, 0x96, 0x36, 0x79, 0x9d, 0x26, 0xfe, 0xbf, 0x83, 0x53, 0x71, 0x9a, 0xea, - 0x44, 0x11, 0x2d, 0x58, 0x5a, 0xbe, 0x7d, 0x16, 0xb9, 0x36, 0x99, 0xa0, 0xf6, 0x12, 0x7a, 0x52, - 0xfb, 0x40, 0x3d, 0xb5, 0x41, 0x15, 0x71, 0x2c, 0x63, 0x25, 0x4c, 0x6b, 0xee, 0x90, 0xd5, 0x7a, - 0x03, 0xa7, 0xe3, 0x28, 0x49, 0x45, 0x82, 0x96, 0xe9, 0xff, 0x56, 0x36, 0x89, 0x6d, 0x16, 0x50, - 0xe7, 0x86, 0x21, 0x9f, 0xde, 0x4e, 0x48, 0xdc, 0x94, 0xcf, 0x7a, 0x0e, 0x27, 0x77, 0x59, 0x58, - 0xe7, 0xbb, 0x73, 0xf9, 0xf3, 0x9d, 0x49, 0x99, 0xd7, 0x23, 0x41, 0x14, 0xe3, 0xa1, 0x33, 0x63, - 0xd8, 0x27, 0x5f, 0x68, 0x16, 0xd7, 0xb0, 0x59, 0xdf, 0x87, 0xa1, 0x2b, 0xe8, 0xd0, 0xdd, 0xcf, - 0x1c, 0xba, 0x11, 0x73, 0x2f, 0xf3, 0x06, 0xaa, 0xdf, 0x00, 0xbc, 0x3e, 0x62, 0x49, 0x7c, 0x30, - 0xeb, 0xed, 0x58, 0xe6, 0x32, 0x8e, 0x2d, 0x46, 0xeb, 0xc4, 0xcd, 0x1a, 0x33, 0xa7, 0x92, 0xca, - 0x48, 0xde, 0x5e, 0xc1, 0x22, 0x53, 0x34, 0x90, 0xe6, 0xb9, 0x58, 0xbd, 0xc8, 0xe4, 0x9c, 0x6b, - 0xc9, 0xb4, 0x1e, 0xc5, 0x54, 0xee, 0x80, 0xb1, 0xfa, 0x35, 0x0f, 0xe1, 0x16, 0xaf, 0x5f, 0xde, - 0x9d, 0x33, 0xef, 0x4e, 0x00, 0xa1, 0x97, 0xbc, 0xbc, 0xd2, 0xdc, 0x9f, 0xbb, 0x17, 0x7e, 0xb4, - 0x53, 0x87, 0x86, 0x2b, 0xd2, 0x1d, 0x11, 0xa8, 0x76, 0x01, 0x9c, 0x49, 0x87, 0xf2, 0x1f, 0x02, - 0xf6, 0xf2, 0xef, 0x80, 0xad, 0x64, 0x3e, 0x5a, 0xda, 0xe5, 0xc9, 0xf9, 0x72, 0x16, 0xbb, 0x3d, - 0x3b, 0xb7, 0xdf, 0xb3, 0x73, 0x07, 0x3d, 0x3b, 0xf7, 0xb1, 0x6f, 0x83, 0x6e, 0xdf, 0x06, 0xfb, - 0x7d, 0x1b, 0x1c, 0xf4, 0x6d, 0xf0, 0xa3, 0x6f, 0x83, 0x2f, 0x3f, 0xed, 0xdc, 0xeb, 0x2b, 0x86, - 0xef, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5a, 0xcd, 0xcf, 0xda, 0x29, 0x09, 0x00, 0x00, + // 659 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x54, 0xbf, 0x6f, 0x13, 0x3f, + 0x1c, 0x8d, 0x9b, 0xa4, 0xdf, 0xd6, 0xf9, 0x52, 0xca, 0x4d, 0x55, 0x86, 0x4b, 0x95, 0x85, 0x0a, + 0xa9, 0x36, 0x2d, 0x15, 0x2a, 0x2c, 0x48, 0x47, 0x19, 0x90, 0x68, 0x29, 0xa7, 0xf2, 0x9b, 0x01, + 0xe7, 0x62, 0x2e, 0x26, 0xdc, 0x39, 0xb2, 0x7d, 0xa9, 0xb2, 0xa1, 0x8a, 0x89, 0x09, 0xf1, 0x57, + 0x45, 0x4c, 0x1d, 0x3b, 0xa0, 0x96, 0x84, 0x99, 0x7f, 0x80, 0x09, 0x9d, 0xcf, 0x97, 0x0b, 0x4d, + 0x69, 0x8f, 0x0e, 0x4c, 0xdd, 0xee, 0x3e, 0xf6, 0x7b, 0xef, 0xe3, 0xf7, 0x79, 0x36, 0xdc, 0x6e, + 0xaf, 0x4b, 0xc4, 0x38, 0x6e, 0x47, 0x0d, 0x2a, 0x42, 0xaa, 0xa8, 0xc4, 0x5d, 0x1a, 0x36, 0xb9, + 0xc0, 0x66, 0x21, 0xa0, 0x4a, 0x30, 0x4f, 0xe2, 0x4e, 0xdb, 0xc7, 0xa4, 0xc3, 0xe4, 0xa8, 0xd0, + 0x5d, 0x69, 0x50, 0x45, 0x56, 0xb0, 0x4f, 0x43, 0x2a, 0x88, 0xa2, 0x4d, 0xd4, 0x11, 0x5c, 0x71, + 0xeb, 0x6a, 0x02, 0x44, 0x66, 0x1f, 0xea, 0xb4, 0x7d, 0x14, 0x03, 0x47, 0x05, 0x03, 0xac, 0x2e, + 0xfb, 0x4c, 0xb5, 0xa2, 0x06, 0xf2, 0x78, 0x80, 0x7d, 0xee, 0x73, 0xac, 0xf1, 0x8d, 0xe8, 0x8d, + 0xfe, 0xd3, 0x3f, 0xfa, 0x2b, 0xe1, 0xad, 0xd6, 0x4d, 0x43, 0xa4, 0xc3, 0xb0, 0xc7, 0x05, 0xc5, + 0xdd, 0x09, 0xed, 0xea, 0x5a, 0xb6, 0x27, 0x20, 0x5e, 0x8b, 0x85, 0x54, 0xf4, 0xd2, 0xce, 0xb1, + 0xa0, 0x92, 0x47, 0xc2, 0xa3, 0x7f, 0x85, 0xd2, 0xe7, 0x25, 0x27, 0x69, 0xe1, 0x3f, 0xa1, 0x44, + 0x14, 0x2a, 0x16, 0x4c, 0xca, 0xdc, 0x3c, 0x0b, 0x20, 0xbd, 0x16, 0x0d, 0xc8, 0x71, 0x5c, 0x7d, + 0xaf, 0x08, 0xe7, 0xef, 0xf2, 0x50, 0x91, 0x18, 0xb1, 0x99, 0x98, 0x68, 0x2d, 0xc2, 0x52, 0x48, + 0x02, 0xba, 0x00, 0x16, 0xc1, 0xd2, 0xac, 0xf3, 0x7f, 0xff, 0xb0, 0x56, 0x18, 0x1e, 0xd6, 0x4a, + 0x5b, 0x24, 0xa0, 0xae, 0x5e, 0xb1, 0x06, 0x00, 0x96, 0x23, 0x49, 0x7c, 0xba, 0x30, 0xb5, 0x58, + 0x5c, 0xaa, 0xac, 0x6e, 0xa0, 0x9c, 0x83, 0x41, 0xc7, 0xc5, 0xd0, 0xe3, 0x98, 0xe6, 0x5e, 0xa8, + 0x44, 0xcf, 0xf9, 0x00, 0x8c, 0x54, 0x59, 0x17, 0x7f, 0x1e, 0xd6, 0x6a, 0x93, 0x73, 0x41, 0xae, + 0xb1, 0xfa, 0x01, 0x93, 0x6a, 0xef, 0xe8, 0xd4, 0x2d, 0x71, 0xc7, 0x1f, 0x8f, 0x6a, 0xcb, 0x79, + 0x26, 0x87, 0x1e, 0x45, 0x24, 0x54, 0x4c, 0xf5, 0xdc, 0xe4, 0x64, 0xd5, 0x16, 0x84, 0x59, 0x6f, + 0xd6, 0x3c, 0x2c, 0xb6, 0x69, 0x2f, 0xb1, 0xc4, 0x8d, 0x3f, 0xad, 0x0d, 0x58, 0xee, 0x92, 0x77, + 0x51, 0x6c, 0x01, 0x58, 0xaa, 0xac, 0xa2, 0xd4, 0x82, 0x71, 0x95, 0xd4, 0x07, 0x74, 0x82, 0x8a, + 0x06, 0xdf, 0x9e, 0x5a, 0x07, 0xf5, 0x1f, 0x25, 0x58, 0xd9, 0xe2, 0x4d, 0x9a, 0xfa, 0xff, 0x1a, + 0xce, 0xc4, 0xc1, 0x68, 0x12, 0x45, 0xb4, 0x60, 0x65, 0xf5, 0xfa, 0x69, 0xe4, 0xda, 0x64, 0x82, + 0xba, 0x2b, 0xe8, 0x61, 0xe3, 0x2d, 0xf5, 0xd4, 0x26, 0x55, 0xc4, 0xb1, 0x8c, 0x95, 0x30, 0xab, + 0xb9, 0x23, 0x56, 0xeb, 0x25, 0x9c, 0x8d, 0x53, 0x21, 0x15, 0x09, 0x3a, 0xa6, 0xff, 0x6b, 0xf9, + 0x24, 0x76, 0x58, 0x40, 0x9d, 0x2b, 0x86, 0x7c, 0x76, 0x27, 0x25, 0x71, 0x33, 0x3e, 0xeb, 0x09, + 0x9c, 0xde, 0x65, 0x61, 0x93, 0xef, 0x2e, 0x14, 0xcf, 0x76, 0x26, 0x63, 0xde, 0x88, 0x04, 0x51, + 0x8c, 0x87, 0xce, 0x9c, 0x61, 0x9f, 0x7e, 0xaa, 0x59, 0x5c, 0xc3, 0x66, 0x7d, 0x1d, 0x85, 0xae, + 0xa4, 0x43, 0x77, 0x27, 0x77, 0xe8, 0xc6, 0xcc, 0xbd, 0xc8, 0x1b, 0xa8, 0x7f, 0x01, 0xf0, 0xf2, + 0x98, 0x25, 0xf1, 0xc1, 0xac, 0x57, 0x13, 0x99, 0xcb, 0x39, 0xb6, 0x18, 0xad, 0x13, 0x37, 0x6f, + 0xcc, 0x9c, 0x49, 0x2b, 0x63, 0x79, 0x7b, 0x0e, 0xcb, 0x4c, 0xd1, 0x40, 0x9a, 0xe7, 0x62, 0xed, + 0x3c, 0x93, 0x73, 0x2e, 0xa5, 0xd3, 0xba, 0x1f, 0x53, 0xb9, 0x09, 0x63, 0xfd, 0x73, 0x11, 0xc2, + 0x6d, 0xde, 0xbc, 0xb8, 0x3b, 0xa7, 0xde, 0x9d, 0x00, 0x42, 0x2f, 0x7d, 0x79, 0xa5, 0xb9, 0x3f, + 0xb7, 0xce, 0xfd, 0x68, 0x67, 0x0e, 0x8d, 0x56, 0xa4, 0x3b, 0x26, 0x50, 0xef, 0x03, 0x38, 0x97, + 0x0d, 0xe5, 0x1f, 0x04, 0xec, 0xd9, 0xef, 0x01, 0xbb, 0x91, 0xfb, 0x68, 0x59, 0x97, 0x27, 0xe7, + 0xcb, 0x59, 0xee, 0x0f, 0xec, 0xc2, 0xfe, 0xc0, 0x2e, 0x1c, 0x0c, 0xec, 0xc2, 0xfb, 0xa1, 0x0d, + 0xfa, 0x43, 0x1b, 0xec, 0x0f, 0x6d, 0x70, 0x30, 0xb4, 0xc1, 0xb7, 0xa1, 0x0d, 0x3e, 0x7d, 0xb7, + 0x0b, 0x2f, 0xfe, 0x33, 0x7c, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb2, 0xc3, 0x3b, 0x02, 0xf4, + 0x08, 0x00, 0x00, } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/generated.proto b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/generated.proto index 1d414f5f5..86167a10d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/generated.proto +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/generated.proto @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -26,7 +26,6 @@ import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; // Package-wide variables from generator "generated". option go_package = "v1beta1"; diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/zz_generated.conversion.go index d3a70f9da..b80d297fd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/zz_generated.deepcopy.go index bdac4d4d7..2f62c97a8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/zz_generated.deepcopy.go index 6db7df85c..9d5cecc5f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/apis/metrics/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/BUILD index 17bcf61f0..320e468a0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/BUILD @@ -13,7 +13,6 @@ go_library( ], importpath = "k8s.io/metrics/pkg/client/clientset_generated/clientset", deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/clientset.go index c8bc81609..e9a9b6006 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package clientset import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -86,7 +85,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/doc.go index 3421911a7..ee865e56d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/clientset_generated.go index 417758c42..d9950371b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -43,9 +43,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -55,7 +56,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/register.go index 9e373eaac..69b08154c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/scheme/register.go index ce4323017..78e429628 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_metrics_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_metrics_client.go index a54666daf..be7103f6a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_metrics_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_metrics_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_nodemetrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_nodemetrics.go index 7f411f9ad..d061710ad 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_nodemetrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_nodemetrics.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -58,7 +58,7 @@ func (c *FakeNodeMetricses) List(opts v1.ListOptions) (result *v1alpha1.NodeMetr if label == nil { label = labels.Everything() } - list := &v1alpha1.NodeMetricsList{} + list := &v1alpha1.NodeMetricsList{ListMeta: obj.(*v1alpha1.NodeMetricsList).ListMeta} for _, item := range obj.(*v1alpha1.NodeMetricsList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_podmetrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_podmetrics.go index c0b5a8305..285f9eca5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_podmetrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake/fake_podmetrics.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -61,7 +61,7 @@ func (c *FakePodMetricses) List(opts v1.ListOptions) (result *v1alpha1.PodMetric if label == nil { label = labels.Everything() } - list := &v1alpha1.PodMetricsList{} + list := &v1alpha1.PodMetricsList{ListMeta: obj.(*v1alpha1.PodMetricsList).ListMeta} for _, item := range obj.(*v1alpha1.PodMetricsList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/generated_expansion.go index c19c00e47..e8fc33bbb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/metrics_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/metrics_client.go index f6842e501..a1ba2f52d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/metrics_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/metrics_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/nodemetrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/nodemetrics.go index 0f503e452..c53e95f81 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/nodemetrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/nodemetrics.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/podmetrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/podmetrics.go index 480991bd3..f030b9ddc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/podmetrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/podmetrics.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/doc.go index 11ae7049d..771101956 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_metrics_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_metrics_client.go index 5aff0d60b..09fc39d49 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_metrics_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_metrics_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_nodemetrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_nodemetrics.go index 3ba8caffb..203034965 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_nodemetrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_nodemetrics.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -58,7 +58,7 @@ func (c *FakeNodeMetricses) List(opts v1.ListOptions) (result *v1beta1.NodeMetri if label == nil { label = labels.Everything() } - list := &v1beta1.NodeMetricsList{} + list := &v1beta1.NodeMetricsList{ListMeta: obj.(*v1beta1.NodeMetricsList).ListMeta} for _, item := range obj.(*v1beta1.NodeMetricsList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_podmetrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_podmetrics.go index 5bf2773be..d4855eb28 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_podmetrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/fake/fake_podmetrics.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -61,7 +61,7 @@ func (c *FakePodMetricses) List(opts v1.ListOptions) (result *v1beta1.PodMetrics if label == nil { label = labels.Everything() } - list := &v1beta1.PodMetricsList{} + list := &v1beta1.PodMetricsList{ListMeta: obj.(*v1beta1.PodMetricsList).ListMeta} for _, item := range obj.(*v1beta1.PodMetricsList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/generated_expansion.go index 77165723f..a89ca3c78 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/metrics_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/metrics_client.go index 6dac05fc2..7353ddbbc 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/metrics_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/metrics_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/nodemetrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/nodemetrics.go index 356e1fff5..a7b69a527 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/nodemetrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/nodemetrics.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/podmetrics.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/podmetrics.go index f2ab0758c..1a7ae248e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/podmetrics.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1beta1/podmetrics.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/custom_metrics/client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/custom_metrics/client.go index 1e1763bc8..118eeb2bb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/custom_metrics/client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/custom_metrics/client.go @@ -104,11 +104,8 @@ func (c *customMetricsClient) qualResourceForKind(groupKind schema.GroupKind) (s return "", fmt.Errorf("unable to map kind %s to resource: %v", groupKind.String(), err) } - groupResource := schema.GroupResource{ - Group: mapping.GroupVersionKind.Group, - Resource: mapping.Resource, - } - return groupResource.String(), nil + gr := mapping.Resource.GroupResource() + return gr.String(), nil } type rootScopedMetrics struct { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/custom_metrics/fake/fake_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/custom_metrics/fake/fake_client.go index 08da22284..c44aa931b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/custom_metrics/fake/fake_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/metrics/pkg/client/custom_metrics/fake/fake_client.go @@ -51,6 +51,18 @@ func (i GetForActionImpl) GetSubresource() string { return i.MetricName } +func (i GetForActionImpl) DeepCopy() testing.Action { + var labelSelector labels.Selector + if i.LabelSelector != nil { + labelSelector = i.LabelSelector.DeepCopySelector() + } + return GetForActionImpl{ + GetAction: i.GetAction.DeepCopy().(testing.GetAction), + MetricName: i.MetricName, + LabelSelector: labelSelector, + } +} + func NewGetForAction(groupKind schema.GroupKind, namespace, name string, metricName string, labelSelector labels.Selector) GetForActionImpl { // the version doesn't matter gvk := groupKind.WithVersion("") diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/BUILD index d24661455..c91e963f3 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/BUILD @@ -44,6 +44,7 @@ filegroup( "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1:all-srcs", + "//staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/cmd/server:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/registry:all-srcs", ], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json index eb86f628b..4fc028225 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "k8s.io/sample-apiserver", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], @@ -104,7 +104,7 @@ }, { "ImportPath": "github.com/evanphx/json-patch", - "Rev": "944e07253867aacae43c04b2e6a239005443f33a" + "Rev": "94e38aa1586e8a6c8a75770bddf5ff84c48a106b" }, { "ImportPath": "github.com/ghodss/yaml", @@ -140,27 +140,31 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/protoc-gen-go/descriptor", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/google/btree", + "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" }, { "ImportPath": "github.com/google/gofuzz", @@ -178,6 +182,14 @@ "ImportPath": "github.com/googleapis/gnostic/extensions", "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, { "ImportPath": "github.com/hashicorp/golang-lru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" @@ -186,10 +198,6 @@ "ImportPath": "github.com/hashicorp/golang-lru/simplelru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" }, - { - "ImportPath": "github.com/howeyc/gopass", - "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" - }, { "ImportPath": "github.com/imdario/mergo", "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" @@ -200,7 +208,7 @@ }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" }, { "ImportPath": "github.com/mailru/easyjson/buffer", @@ -218,10 +226,22 @@ "ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil", "Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a" }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, { "ImportPath": "github.com/pborman/uuid", "Rev": "ca53cad383cad2479bbba7f7a1a05797ec1386e4" }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" + }, { "ImportPath": "github.com/prometheus/client_golang/prometheus", "Rev": "e7e903064f5e9eb5da98208bae10b475d4db0f8c" @@ -252,7 +272,7 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Rev": "6644d46b81fa1831979c4cded0106e774e0ef0ab" + "Rev": "c439c4fa093711d42e1b01acb1235b52004753c1" }, { "ImportPath": "github.com/spf13/pflag", @@ -264,7 +284,7 @@ }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/net/context", @@ -546,6 +566,10 @@ "ImportPath": "k8s.io/api/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -598,18 +622,6 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/validation/path", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -822,6 +834,10 @@ "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/generic", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -842,10 +858,6 @@ "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/validating", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, - { - "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/versioned", - "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { "ImportPath": "k8s.io/apiserver/pkg/apis/apiserver", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1098,6 +1110,10 @@ "ImportPath": "k8s.io/apiserver/pkg/util/logs", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apiserver/pkg/util/openapi", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apiserver/pkg/util/trace", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1278,6 +1294,10 @@ "ImportPath": "k8s.io/client-go/informers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/settings", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1406,6 +1426,10 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1502,6 +1526,10 @@ "ImportPath": "k8s.io/client-go/listers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1526,6 +1554,10 @@ "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/pkg/version", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1594,6 +1626,10 @@ "ImportPath": "k8s.io/client-go/util/cert", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/connrotation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1612,23 +1648,23 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/README.md b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/README.md index c5cbc4117..6f4bf686d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/README.md +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/README.md @@ -23,3 +23,64 @@ HEAD of this repo will match HEAD of k8s.io/apiserver, k8s.io/apimachinery, and `sample-apiserver` is synced from https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/sample-apiserver. Code changes are made in that location, merged into `k8s.io/kubernetes` and later synced here. +## Running it stand-alone + +During development it is helpful to run sample-apiserver stand-alone, i.e. without +a Kubernetes API server for authn/authz and without aggregation. This is possible, but needs +a couple of flags, keys and certs as described below. You will still need some kubeconfig, +e.g. `~/.kube/config`, but the Kubernetes cluster is not used for authn/z. A minikube or +hack/local-up-cluster.sh cluster will work. + +Instead of trusting the aggregator inside kube-apiserver, the described setup uses local +client certificate based X.509 authentication and authorization. This means that the client +certificate is trusted by a CA and the passed certificate contains the group membership +to the `system:masters` group. As we disable delegated authorization with `--authorization-skip-lookup`, +only this superuser group is authorized. + +1. First we need a CA to later sign the client certificate: + +``` shell +openssl req -nodes -new -x509 -keyout ca.key -out ca.crt +``` + +2. Then we create a client cert signed by this CA for the user `development` in the superuser group + `system:masters`: + +``` shell +openssl req -out client.csr -new -newkey rsa:4096 -nodes -keyout client.key -subj "/CN=development/O=system:masters" +openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt +``` + +3. As curl requires client certificates in p12 format with password, do the conversion: + +``` shell +openssl pkcs12 -export -in ./client.crt -inkey ./client.key -out client.p12 -passout pass:password +``` + +4. With these keys and certs in-place, we start the server: + +``` shell +etcd & +sample-apiserver --secure-port 8443 --etcd-servers http://127.0.0.1:2379 --v=7 \ + --client-ca-file ca.crt \ + --kubeconfig ~/.kube/config \ + --authentication-kubeconfig ~/.kube/config \ + --authorization-kubeconfig ~/.kube/config +``` + +The first kubeconfig is used for the shared informers to access Kubernetes resources. The second kubeconfig passed to `--authentication-kubeconfig` is used to satisfy the delegated authenticator. The third kubeconfig passed to `--authorized-kubeconfig` is used to satisfy the delegated authorizer. Neither the authenticator, nor the authorizer will actually be used: due to `--client-ca-file`, our development X.509 certificate is accepted and authenticates us as `system:masters` member. `system:masters` is the superuser group +such that delegated authorization is skipped. + +5. Use curl to access the server using the client certificate in p12 format for authentication: + +``` shell +curl -fv -k --cert client.p12:password \ + https://localhost:8443/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders +``` + + Note: Recent OSX versions broke client certs with curl. On Mac try `brew install httpie` and then: + +``` shell +http --verify=no --cert client.crt --cert-key client.key \ + https://localhost:8443/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders +``` diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/artifacts/example/rc.yaml b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/artifacts/example/rc.yaml index 53be32346..ba2f4162a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/artifacts/example/rc.yaml +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/artifacts/example/rc.yaml @@ -21,4 +21,4 @@ spec: imagePullPolicy: Never command: [ "/kube-sample-apiserver", "--etcd-servers=http://localhost:2379" ] - name: etcd - image: quay.io/coreos/etcd:v3.1.12 + image: quay.io/coreos/etcd:v3.2.18 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/boilerplate.go.txt b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/boilerplate.go.txt index 59e740c1e..b7c650da4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/boilerplate.go.txt +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright YEAR The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/build-image.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/build-image.sh index c8b9df063..c1b3c7685 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/build-image.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/build-image.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh index 0c3cce6ee..9dcc8f102 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -27,7 +27,7 @@ CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-ge # instead of the $GOPATH directly. For normal projects this can be dropped. ${CODEGEN_PKG}/generate-internal-groups.sh all \ k8s.io/sample-apiserver/pkg/client k8s.io/sample-apiserver/pkg/apis k8s.io/sample-apiserver/pkg/apis \ - wardle:v1alpha1 \ + "wardle:v1alpha1,v1beta1" \ --output-base "$(dirname ${BASH_SOURCE})/../../.." \ --go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/verify-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/verify-codegen.sh index f5835c425..ab43ba23d 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/verify-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/main.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/main.go index f05327d98..8e1769a36 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/main.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/main.go @@ -19,7 +19,6 @@ package main import ( "flag" "os" - "runtime" "github.com/golang/glog" @@ -32,10 +31,6 @@ func main() { logs.InitLogs() defer logs.FlushLogs() - if len(os.Getenv("GOMAXPROCS")) == 0 { - runtime.GOMAXPROCS(runtime.NumCPU()) - } - stopCh := genericapiserver.SetupSignalHandler() options := server.NewWardleServerOptions(os.Stdout, os.Stderr) cmd := server.NewCommandStartWardleServer(options, stopCh) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go index e0d1dc671..4acfe6448 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go @@ -53,6 +53,10 @@ func (d *DisallowFlunder) Admit(a admission.Attributes) error { return nil } + if !d.WaitForReady() { + return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request")) + } + metaAccessor, err := meta.Accessor(a.GetObject()) if err != nil { return err @@ -82,6 +86,7 @@ func (d *DisallowFlunder) Admit(a admission.Attributes) error { // The lister knows how to lists Fischers. func (d *DisallowFlunder) SetInternalWardleInformerFactory(f informers.SharedInformerFactory) { d.lister = f.Wardle().InternalVersion().Fischers().Lister() + d.SetReadyFunc(f.Wardle().InternalVersion().Fischers().Informer().HasSynced) } // ValidaValidateInitializationte checks whether the plugin was correctly initialized. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/BUILD index 22a0a18ed..ebaab35a4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/BUILD @@ -32,8 +32,11 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:all-srcs", + "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:all-srcs", + "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation:all-srcs", ], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/BUILD new file mode 100644 index 000000000..e1bc2887e --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["fuzzer.go"], + importpath = "k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/google/gofuzz:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/fuzzer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/fuzzer.go new file mode 100644 index 000000000..9278a59f5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/fuzzer.go @@ -0,0 +1,44 @@ +/* +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 fuzzer + +import ( + fuzz "github.com/google/gofuzz" + "k8s.io/sample-apiserver/pkg/apis/wardle" + + runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" +) + +// Funcs returns the fuzzer functions for the apps api group. +var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { + return []interface{}{ + func(s *wardle.FlunderSpec, c fuzz.Continue) { + c.FuzzNoCustom(s) // fuzz self without calling this function again + + if len(s.FlunderReference) != 0 && len(s.FischerReference) != 0 { + s.FischerReference = "" + } + if len(s.FlunderReference) != 0 { + s.ReferenceType = wardle.FlunderReferenceType + } else if len(s.FischerReference) != 0 { + s.ReferenceType = wardle.FischerReferenceType + } else { + s.ReferenceType = "" + } + }, + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/BUILD index 6db0a64d5..02042ba5f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/BUILD @@ -10,7 +10,10 @@ go_test( name = "go_default_test", srcs = ["roundtrip_test.go"], embed = [":go_default_library"], - deps = ["//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer:go_default_library", + ], ) go_library( @@ -18,12 +21,11 @@ go_library( srcs = ["install.go"], importpath = "k8s.io/sample-apiserver/pkg/apis/wardle/install", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/install.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/install.go index f7e2504b1..98bde92f4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/install.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/install.go @@ -17,27 +17,17 @@ limitations under the License. package install import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/sample-apiserver/pkg/apis/wardle" "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" ) // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - if err := announced.NewGroupMetaFactory( - &announced.GroupMetaFactoryArgs{ - GroupName: wardle.GroupName, - RootScopedKinds: sets.NewString("Fischer", "FischerList"), - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, - AddInternalObjectsToScheme: wardle.AddToScheme, - }, - announced.VersionToSchemeFunc{ - v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, - }, - ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { - panic(err) - } +func Install(scheme *runtime.Scheme) { + utilruntime.Must(wardle.AddToScheme(scheme)) + utilruntime.Must(v1beta1.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion)) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/roundtrip_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/roundtrip_test.go index ecdc81ca0..d50b32dfd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/roundtrip_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/roundtrip_test.go @@ -19,9 +19,10 @@ package install import ( "testing" - roundtrip "k8s.io/apimachinery/pkg/api/testing/roundtrip" + "k8s.io/apimachinery/pkg/api/testing/roundtrip" + wardlefuzzer "k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer" ) func TestRoundTripTypes(t *testing.T) { - roundtrip.RoundTripTestForAPIGroup(t, Install, nil) + roundtrip.RoundTripTestForAPIGroup(t, Install, wardlefuzzer.Funcs) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/types.go index fc5a6ee2c..f7c7efcfe 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/types.go @@ -28,7 +28,20 @@ type FlunderList struct { Items []Flunder } +type ReferenceType string + +const ( + FlunderReferenceType = ReferenceType("Flunder") + FischerReferenceType = ReferenceType("Fischer") +) + type FlunderSpec struct { + // A name of another flunder, mutually exclusive to the FischerReference. + FlunderReference string + // A name of a fischer, mutually exclusive to the FlunderReference. + FischerReference string + // The reference type. + ReferenceType ReferenceType } type FlunderStatus struct { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/BUILD index bfa17ec65..d67c0909c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/BUILD @@ -8,6 +8,8 @@ load( go_library( name = "go_default_library", srcs = [ + "conversion.go", + "defaults.go", "doc.go", "register.go", "types.go", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/conversion.go new file mode 100644 index 000000000..d310cd612 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/conversion.go @@ -0,0 +1,72 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/sample-apiserver/pkg/apis/wardle" +) + +func addConversionFuncs(scheme *runtime.Scheme) error { + // Add non-generated conversion functions to handle the *int32 -> int32 + // conversion. A pointer is useful in the versioned type so we can default + // it, but a plain int32 is more convenient in the internal type. These + // functions are the same as the autogenerated ones in every other way. + err := scheme.AddConversionFuncs( + Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec, + Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec, + ) + if err != nil { + return err + } + + return nil +} + +// Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec is an autogenerated conversion function. +func Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec(in *FlunderSpec, out *wardle.FlunderSpec, s conversion.Scope) error { + if in.ReferenceType != nil { + // assume that ReferenceType is defaulted + switch *in.ReferenceType { + case FlunderReferenceType: + out.ReferenceType = wardle.FlunderReferenceType + out.FlunderReference = in.Reference + case FischerReferenceType: + out.ReferenceType = wardle.FischerReferenceType + out.FischerReference = in.Reference + } + } + + return nil +} + +// Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec is an autogenerated conversion function. +func Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec(in *wardle.FlunderSpec, out *FlunderSpec, s conversion.Scope) error { + switch in.ReferenceType { + case wardle.FlunderReferenceType: + t := FlunderReferenceType + out.ReferenceType = &t + out.Reference = in.FlunderReference + case wardle.FischerReferenceType: + t := FischerReferenceType + out.ReferenceType = &t + out.Reference = in.FischerReference + } + + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/defaults.go new file mode 100644 index 000000000..194dfecc7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/defaults.go @@ -0,0 +1,32 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return RegisterDefaults(scheme) +} + +func SetDefaults_FlunderSpec(obj *FlunderSpec) { + if (obj.ReferenceType == nil || len(*obj.ReferenceType) == 0) && len(obj.Reference) != 0 { + t := FlunderReferenceType + obj.ReferenceType = &t + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/doc.go index 077120851..22f06f63c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/doc.go @@ -16,6 +16,7 @@ limitations under the License. // +k8s:deepcopy-gen=package // +k8s:conversion-gen=k8s.io/sample-apiserver/pkg/apis/wardle +// +k8s:defaulter-gen=TypeMeta // Package v1alpha1 is the v1alpha1 version of the API. // +groupName=wardle.k8s.io diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/register.go index 4ceaf3d39..a2d4c99f5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/register.go @@ -39,7 +39,7 @@ func init() { // We only register manually written functions here. The registration of the // generated functions takes place in the generated files. The separation // makes the code compile even when the generated files are missing. - localSchemeBuilder.Register(addKnownTypes) + localSchemeBuilder.Register(addKnownTypes, addConversionFuncs, addDefaultingFuncs) } // Adds the list of known types to the given scheme. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/types.go index 31c8ed331..3332e7c1e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/types.go @@ -28,7 +28,18 @@ type FlunderList struct { Items []Flunder `json:"items" protobuf:"bytes,2,rep,name=items"` } +type ReferenceType string + +const ( + FlunderReferenceType = ReferenceType("Flunder") + FischerReferenceType = ReferenceType("Fischer") +) + type FlunderSpec struct { + // A name of another flunder or fischer, depending on the reference type. + Reference string `json:"reference,omitempty" protobuf:"bytes,1,opt,name=reference"` + // The reference type, defaults to "Flunder" if reference is set. + ReferenceType *ReferenceType `json:"referenceType,omitempty" protobuf:"bytes,2,opt,name=referenceType"` } type FlunderStatus struct { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.conversion.go index f67ecee50..f82ac346a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.conversion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.conversion.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -129,7 +129,17 @@ func Convert_wardle_Flunder_To_v1alpha1_Flunder(in *wardle.Flunder, out *Flunder func autoConvert_v1alpha1_FlunderList_To_wardle_FlunderList(in *FlunderList, out *wardle.FlunderList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]wardle.Flunder)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]wardle.Flunder, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_Flunder_To_wardle_Flunder(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -140,7 +150,17 @@ func Convert_v1alpha1_FlunderList_To_wardle_FlunderList(in *FlunderList, out *wa func autoConvert_wardle_FlunderList_To_v1alpha1_FlunderList(in *wardle.FlunderList, out *FlunderList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]Flunder)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Flunder, len(*in)) + for i := range *in { + if err := Convert_wardle_Flunder_To_v1alpha1_Flunder(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -150,23 +170,18 @@ func Convert_wardle_FlunderList_To_v1alpha1_FlunderList(in *wardle.FlunderList, } func autoConvert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec(in *FlunderSpec, out *wardle.FlunderSpec, s conversion.Scope) error { + // WARNING: in.Reference requires manual conversion: does not exist in peer-type + // WARNING: in.ReferenceType requires manual conversion: inconvertible types (*k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1.ReferenceType vs k8s.io/sample-apiserver/pkg/apis/wardle.ReferenceType) return nil } -// Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec is an autogenerated conversion function. -func Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec(in *FlunderSpec, out *wardle.FlunderSpec, s conversion.Scope) error { - return autoConvert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec(in, out, s) -} - func autoConvert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec(in *wardle.FlunderSpec, out *FlunderSpec, s conversion.Scope) error { + // WARNING: in.FlunderReference requires manual conversion: does not exist in peer-type + // WARNING: in.FischerReference requires manual conversion: does not exist in peer-type + // WARNING: in.ReferenceType requires manual conversion: inconvertible types (k8s.io/sample-apiserver/pkg/apis/wardle.ReferenceType vs *k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1.ReferenceType) return nil } -// Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec is an autogenerated conversion function. -func Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec(in *wardle.FlunderSpec, out *FlunderSpec, s conversion.Scope) error { - return autoConvert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec(in, out, s) -} - func autoConvert_v1alpha1_FlunderStatus_To_wardle_FlunderStatus(in *FlunderStatus, out *wardle.FlunderStatus, s conversion.Scope) error { return nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.deepcopy.go index 7345de951..aa7978a55 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -93,7 +93,7 @@ func (in *Flunder) DeepCopyInto(out *Flunder) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) out.Status = in.Status return } @@ -152,6 +152,15 @@ func (in *FlunderList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlunderSpec) DeepCopyInto(out *FlunderSpec) { *out = *in + if in.ReferenceType != nil { + in, out := &in.ReferenceType, &out.ReferenceType + if *in == nil { + *out = nil + } else { + *out = new(ReferenceType) + **out = **in + } + } return } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.defaults.go index 2bd0078a3..46d1c65f4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.defaults.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -28,5 +28,18 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { + scheme.AddTypeDefaultingFunc(&Flunder{}, func(obj interface{}) { SetObjectDefaults_Flunder(obj.(*Flunder)) }) + scheme.AddTypeDefaultingFunc(&FlunderList{}, func(obj interface{}) { SetObjectDefaults_FlunderList(obj.(*FlunderList)) }) return nil } + +func SetObjectDefaults_Flunder(in *Flunder) { + SetDefaults_FlunderSpec(&in.Spec) +} + +func SetObjectDefaults_FlunderList(in *FlunderList) { + for i := range in.Items { + a := &in.Items[i] + SetObjectDefaults_Flunder(a) + } +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/BUILD new file mode 100644 index 000000000..8887edd09 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/BUILD @@ -0,0 +1,39 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "register.go", + "types.go", + "zz_generated.conversion.go", + "zz_generated.deepcopy.go", + "zz_generated.defaults.go", + ], + importpath = "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1", + deps = [ + "//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/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/doc.go new file mode 100644 index 000000000..aa2f7a5b1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2018 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. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/sample-apiserver/pkg/apis/wardle +// +k8s:defaulter-gen=TypeMeta + +// Package v1beta1 is the v1beta1 version of the API. +// +groupName=wardle.k8s.io +package v1beta1 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/register.go new file mode 100644 index 000000000..cd0dd06bd --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/register.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName holds the API group name. +const GroupName = "wardle.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +var ( + // SchemeBuilder allows to add this group to a scheme. + // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + + // AddToScheme adds this group to a scheme. + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Flunder{}, + &FlunderList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/types.go new file mode 100644 index 000000000..78980b127 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/types.go @@ -0,0 +1,65 @@ +/* +Copyright 2018 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 v1beta1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// FlunderList is a list of Flunder objects. +type FlunderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + Items []Flunder `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// ReferenceType defines the type of an object reference. +type ReferenceType string + +const ( + // FlunderReferenceType is used for Flunder references. + FlunderReferenceType = ReferenceType("Flunder") + // FischerReferenceType is used for Fischer references. + FischerReferenceType = ReferenceType("Fischer") +) + +// FlunderSpec is the specification of a Flunder. +type FlunderSpec struct { + // A name of another flunder, mutually exclusive to the FischerReference. + FlunderReference string `json:"flunderReference,omitempty" protobuf:"bytes,1,opt,name=flunderReference"` + // A name of a fischer, mutually exclusive to the FlunderReference. + FischerReference string `json:"fischerReference,omitempty" protobuf:"bytes,2,opt,name=fischerReference"` + // The reference type. + ReferenceType ReferenceType `json:"referenceType,omitempty" protobuf:"bytes,3,opt,name=referenceType"` +} + +// FlunderStatus is the status of a Flunder. +type FlunderStatus struct { +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Flunder is an example type with a spec and a status. +type Flunder struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + Spec FlunderSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` + Status FlunderStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/zz_generated.conversion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/zz_generated.conversion.go new file mode 100644 index 000000000..a86d483ee --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/zz_generated.conversion.go @@ -0,0 +1,144 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1beta1 + +import ( + unsafe "unsafe" + + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + wardle "k8s.io/sample-apiserver/pkg/apis/wardle" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(scheme *runtime.Scheme) error { + return scheme.AddGeneratedConversionFuncs( + Convert_v1beta1_Flunder_To_wardle_Flunder, + Convert_wardle_Flunder_To_v1beta1_Flunder, + Convert_v1beta1_FlunderList_To_wardle_FlunderList, + Convert_wardle_FlunderList_To_v1beta1_FlunderList, + Convert_v1beta1_FlunderSpec_To_wardle_FlunderSpec, + Convert_wardle_FlunderSpec_To_v1beta1_FlunderSpec, + Convert_v1beta1_FlunderStatus_To_wardle_FlunderStatus, + Convert_wardle_FlunderStatus_To_v1beta1_FlunderStatus, + ) +} + +func autoConvert_v1beta1_Flunder_To_wardle_Flunder(in *Flunder, out *wardle.Flunder, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_FlunderSpec_To_wardle_FlunderSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_FlunderStatus_To_wardle_FlunderStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Flunder_To_wardle_Flunder is an autogenerated conversion function. +func Convert_v1beta1_Flunder_To_wardle_Flunder(in *Flunder, out *wardle.Flunder, s conversion.Scope) error { + return autoConvert_v1beta1_Flunder_To_wardle_Flunder(in, out, s) +} + +func autoConvert_wardle_Flunder_To_v1beta1_Flunder(in *wardle.Flunder, out *Flunder, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_wardle_FlunderSpec_To_v1beta1_FlunderSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_wardle_FlunderStatus_To_v1beta1_FlunderStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_wardle_Flunder_To_v1beta1_Flunder is an autogenerated conversion function. +func Convert_wardle_Flunder_To_v1beta1_Flunder(in *wardle.Flunder, out *Flunder, s conversion.Scope) error { + return autoConvert_wardle_Flunder_To_v1beta1_Flunder(in, out, s) +} + +func autoConvert_v1beta1_FlunderList_To_wardle_FlunderList(in *FlunderList, out *wardle.FlunderList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]wardle.Flunder)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1beta1_FlunderList_To_wardle_FlunderList is an autogenerated conversion function. +func Convert_v1beta1_FlunderList_To_wardle_FlunderList(in *FlunderList, out *wardle.FlunderList, s conversion.Scope) error { + return autoConvert_v1beta1_FlunderList_To_wardle_FlunderList(in, out, s) +} + +func autoConvert_wardle_FlunderList_To_v1beta1_FlunderList(in *wardle.FlunderList, out *FlunderList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]Flunder)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_wardle_FlunderList_To_v1beta1_FlunderList is an autogenerated conversion function. +func Convert_wardle_FlunderList_To_v1beta1_FlunderList(in *wardle.FlunderList, out *FlunderList, s conversion.Scope) error { + return autoConvert_wardle_FlunderList_To_v1beta1_FlunderList(in, out, s) +} + +func autoConvert_v1beta1_FlunderSpec_To_wardle_FlunderSpec(in *FlunderSpec, out *wardle.FlunderSpec, s conversion.Scope) error { + out.FlunderReference = in.FlunderReference + out.FischerReference = in.FischerReference + out.ReferenceType = wardle.ReferenceType(in.ReferenceType) + return nil +} + +// Convert_v1beta1_FlunderSpec_To_wardle_FlunderSpec is an autogenerated conversion function. +func Convert_v1beta1_FlunderSpec_To_wardle_FlunderSpec(in *FlunderSpec, out *wardle.FlunderSpec, s conversion.Scope) error { + return autoConvert_v1beta1_FlunderSpec_To_wardle_FlunderSpec(in, out, s) +} + +func autoConvert_wardle_FlunderSpec_To_v1beta1_FlunderSpec(in *wardle.FlunderSpec, out *FlunderSpec, s conversion.Scope) error { + out.FlunderReference = in.FlunderReference + out.FischerReference = in.FischerReference + out.ReferenceType = ReferenceType(in.ReferenceType) + return nil +} + +// Convert_wardle_FlunderSpec_To_v1beta1_FlunderSpec is an autogenerated conversion function. +func Convert_wardle_FlunderSpec_To_v1beta1_FlunderSpec(in *wardle.FlunderSpec, out *FlunderSpec, s conversion.Scope) error { + return autoConvert_wardle_FlunderSpec_To_v1beta1_FlunderSpec(in, out, s) +} + +func autoConvert_v1beta1_FlunderStatus_To_wardle_FlunderStatus(in *FlunderStatus, out *wardle.FlunderStatus, s conversion.Scope) error { + return nil +} + +// Convert_v1beta1_FlunderStatus_To_wardle_FlunderStatus is an autogenerated conversion function. +func Convert_v1beta1_FlunderStatus_To_wardle_FlunderStatus(in *FlunderStatus, out *wardle.FlunderStatus, s conversion.Scope) error { + return autoConvert_v1beta1_FlunderStatus_To_wardle_FlunderStatus(in, out, s) +} + +func autoConvert_wardle_FlunderStatus_To_v1beta1_FlunderStatus(in *wardle.FlunderStatus, out *FlunderStatus, s conversion.Scope) error { + return nil +} + +// Convert_wardle_FlunderStatus_To_v1beta1_FlunderStatus is an autogenerated conversion function. +func Convert_wardle_FlunderStatus_To_v1beta1_FlunderStatus(in *wardle.FlunderStatus, out *FlunderStatus, s conversion.Scope) error { + return autoConvert_wardle_FlunderStatus_To_v1beta1_FlunderStatus(in, out, s) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 000000000..48ef31ff1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,118 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Flunder) DeepCopyInto(out *Flunder) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Flunder. +func (in *Flunder) DeepCopy() *Flunder { + if in == nil { + return nil + } + out := new(Flunder) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Flunder) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlunderList) DeepCopyInto(out *FlunderList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Flunder, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlunderList. +func (in *FlunderList) DeepCopy() *FlunderList { + if in == nil { + return nil + } + out := new(FlunderList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FlunderList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlunderSpec) DeepCopyInto(out *FlunderSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlunderSpec. +func (in *FlunderSpec) DeepCopy() *FlunderSpec { + if in == nil { + return nil + } + out := new(FlunderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlunderStatus) DeepCopyInto(out *FlunderStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlunderStatus. +func (in *FlunderStatus) DeepCopy() *FlunderStatus { + if in == nil { + return nil + } + out := new(FlunderStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/zz_generated.defaults.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/zz_generated.defaults.go new file mode 100644 index 000000000..73e63fc11 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/zz_generated.defaults.go @@ -0,0 +1,32 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/BUILD new file mode 100644 index 000000000..a36e85155 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/BUILD @@ -0,0 +1,26 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["validation.go"], + importpath = "k8s.io/sample-apiserver/pkg/apis/wardle/validation", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/validation.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/validation.go new file mode 100644 index 000000000..dc6f3c56d --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/validation.go @@ -0,0 +1,54 @@ +/* +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 validation + +import ( + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/sample-apiserver/pkg/apis/wardle" +) + +// ValidateFlunder validates a Flunder. +func ValidateFlunder(f *wardle.Flunder) field.ErrorList { + allErrs := field.ErrorList{} + + allErrs = append(allErrs, ValidateFlunderSpec(&f.Spec, field.NewPath("spec"))...) + + return allErrs +} + +// ValidateFlunderSpec validates a FlunderSpec. +func ValidateFlunderSpec(s *wardle.FlunderSpec, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if len(s.FlunderReference) != 0 && len(s.FischerReference) != 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("fischerReference"), s.FischerReference, "cannot be set with flunderReference at the same time")) + } else if len(s.FlunderReference) != 0 && s.ReferenceType != wardle.FlunderReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("flunderReference"), s.FlunderReference, "cannot be set if referenceType is not Flunder")) + } else if len(s.FischerReference) != 0 && s.ReferenceType != wardle.FischerReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("fischerReference"), s.FischerReference, "cannot be set if referenceType is not Fischer")) + } else if len(s.FischerReference) == 0 && s.ReferenceType == wardle.FischerReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("fischerReference"), s.FischerReference, "cannot be empty if referenceType is Fischer")) + } else if len(s.FlunderReference) == 0 && s.ReferenceType == wardle.FlunderReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("flunderReference"), s.FlunderReference, "cannot be empty if referenceType is Flunder")) + } + + if len(s.ReferenceType) != 0 && s.ReferenceType != wardle.FischerReferenceType && s.ReferenceType != wardle.FlunderReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("referenceType"), s.ReferenceType, "must be Flunder or Fischer")) + } + + return allErrs +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/zz_generated.deepcopy.go index b28f5ac9d..274b72a4e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/BUILD index 91a0f6d1d..519b6eef0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/BUILD @@ -10,7 +10,10 @@ go_test( name = "go_default_test", srcs = ["scheme_test.go"], embed = [":go_default_library"], - deps = ["//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer:go_default_library", + ], ) go_library( @@ -18,8 +21,6 @@ go_library( srcs = ["apiserver.go"], importpath = "k8s.io/sample-apiserver/pkg/apiserver", deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", @@ -29,7 +30,6 @@ go_library( "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/install:go_default_library", - "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/registry:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/registry/wardle/fischer:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/registry/wardle/flunder:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/apiserver.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/apiserver.go index e36dc1360..e93f1fa21 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/apiserver.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/apiserver.go @@ -17,8 +17,6 @@ limitations under the License. package apiserver import ( - "k8s.io/apimachinery/pkg/apimachinery/announced" - "k8s.io/apimachinery/pkg/apimachinery/registered" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -29,21 +27,18 @@ import ( "k8s.io/sample-apiserver/pkg/apis/wardle" "k8s.io/sample-apiserver/pkg/apis/wardle/install" - "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" wardleregistry "k8s.io/sample-apiserver/pkg/registry" fischerstorage "k8s.io/sample-apiserver/pkg/registry/wardle/fischer" flunderstorage "k8s.io/sample-apiserver/pkg/registry/wardle/flunder" ) var ( - groupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - registry = registered.NewOrDie("") - Scheme = runtime.NewScheme() - Codecs = serializer.NewCodecFactory(Scheme) + Scheme = runtime.NewScheme() + Codecs = serializer.NewCodecFactory(Scheme) ) func init() { - install.Install(groupFactoryRegistry, registry, Scheme) + install.Install(Scheme) // we need to add the options to empty v1 // TODO fix the server code to avoid this @@ -101,7 +96,7 @@ func (cfg *Config) Complete() CompletedConfig { // New returns a new instance of WardleServer from the given config. func (c completedConfig) New() (*WardleServer, error) { - genericServer, err := c.GenericConfig.New("sample-apiserver", genericapiserver.EmptyDelegate) + genericServer, err := c.GenericConfig.New("sample-apiserver", genericapiserver.NewEmptyDelegate()) if err != nil { return nil, err } @@ -110,13 +105,17 @@ func (c completedConfig) New() (*WardleServer, error) { GenericAPIServer: genericServer, } - apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(wardle.GroupName, registry, Scheme, metav1.ParameterCodec, Codecs) - apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(wardle.GroupName, Scheme, metav1.ParameterCodec, Codecs) + v1alpha1storage := map[string]rest.Storage{} v1alpha1storage["flunders"] = wardleregistry.RESTInPeace(flunderstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) v1alpha1storage["fischers"] = wardleregistry.RESTInPeace(fischerstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage + v1beta1storage := map[string]rest.Storage{} + v1beta1storage["flunders"] = wardleregistry.RESTInPeace(flunderstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) + apiGroupInfo.VersionedResourcesStorageMap["v1beta1"] = v1beta1storage + if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/scheme_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/scheme_test.go index 070dd3c00..060a8be7e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/scheme_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/apiserver/scheme_test.go @@ -20,8 +20,9 @@ import ( "testing" "k8s.io/apimachinery/pkg/api/testing/roundtrip" + wardlefuzzer "k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer" ) func TestRoundTripTypes(t *testing.T) { - roundtrip.RoundTripTestForScheme(t, Scheme, nil) + roundtrip.RoundTripTestForScheme(t, Scheme, wardlefuzzer.Funcs) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/BUILD index 73b2b6b32..6f4428df5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/BUILD @@ -9,7 +9,6 @@ go_library( importpath = "k8s.io/sample-apiserver/pkg/client/clientset/internalversion", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/clientset.go index 48ca4dc74..b0a9bd43d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package internalversion import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -66,7 +65,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/doc.go index 50398f9ef..6c970b092 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/clientset_generated.go index 03ce116bc..79c8eeb46 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -41,9 +41,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -53,7 +54,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/register.go index 776c261c3..16773078b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/BUILD index f5ff3d214..56e9b2fc9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/BUILD @@ -9,8 +9,6 @@ go_library( importpath = "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme", visibility = ["//visibility:public"], deps = [ - "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/register.go index 5c1cff431..7a5193819 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,10 +19,6 @@ limitations under the License. package scheme import ( - os "os" - - announced "k8s.io/apimachinery/pkg/apimachinery/announced" - registered "k8s.io/apimachinery/pkg/apimachinery/registered" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -34,15 +30,12 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) -var Registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS")) -var GroupFactoryRegistry = make(announced.APIGroupFactoryRegistry) - func init() { v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - Install(GroupFactoryRegistry, Registry, Scheme) + Install(Scheme) } // Install registers the API group and adds types to a scheme -func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { - wardle.Install(groupFactoryRegistry, registry, scheme) +func Install(scheme *runtime.Scheme) { + wardle.Install(scheme) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/doc.go index b057e5201..86602442b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_fischer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_fischer.go index 79b261ad6..24e493aad 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_fischer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_fischer.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeFischers) List(opts v1.ListOptions) (result *wardle.FischerList, er if label == nil { label = labels.Everything() } - list := &wardle.FischerList{} + list := &wardle.FischerList{ListMeta: obj.(*wardle.FischerList).ListMeta} for _, item := range obj.(*wardle.FischerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_flunder.go index fe4d159e4..68972d203 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_flunder.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_flunder.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeFlunders) List(opts v1.ListOptions) (result *wardle.FlunderList, er if label == nil { label = labels.Everything() } - list := &wardle.FlunderList{} + list := &wardle.FlunderList{ListMeta: obj.(*wardle.FlunderList).ListMeta} for _, item := range obj.(*wardle.FlunderList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_wardle_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_wardle_client.go index 0d76ed8f6..b9282c03d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_wardle_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_wardle_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fischer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fischer.go index f74c43f4d..9af7ccf61 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fischer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fischer.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/flunder.go index 99083e9c7..ce9b6064e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/flunder.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/flunder.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/generated_expansion.go index 81e82a157..c3270941d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/wardle_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/wardle_client.go index 14a4a93c6..12e618e96 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/wardle_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/wardle_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -71,17 +71,12 @@ func New(c rest.Interface) *WardleClient { } func setConfigDefaults(config *rest.Config) error { - g, err := scheme.Registry.Group("wardle.k8s.io") - if err != nil { - return err - } - config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group { - gv := g.GroupVersion + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("wardle.k8s.io")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("wardle.k8s.io")[0] config.GroupVersion = &gv } config.NegotiatedSerializer = scheme.Codecs diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/BUILD index deadff495..f75a82223 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/BUILD @@ -9,11 +9,11 @@ go_library( importpath = "k8s.io/sample-apiserver/pkg/client/clientset/versioned", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1:go_default_library", ], ) @@ -31,6 +31,7 @@ filegroup( "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1:all-srcs", + "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/clientset.go index 878785b0c..b7f427f25 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,18 +19,19 @@ limitations under the License. package versioned import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" wardlev1alpha1 "k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1" + wardlev1beta1 "k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1" ) type Interface interface { Discovery() discovery.DiscoveryInterface WardleV1alpha1() wardlev1alpha1.WardleV1alpha1Interface + WardleV1beta1() wardlev1beta1.WardleV1beta1Interface // Deprecated: please explicitly pick a version if possible. - Wardle() wardlev1alpha1.WardleV1alpha1Interface + Wardle() wardlev1beta1.WardleV1beta1Interface } // Clientset contains the clients for groups. Each group has exactly one @@ -38,6 +39,7 @@ type Interface interface { type Clientset struct { *discovery.DiscoveryClient wardleV1alpha1 *wardlev1alpha1.WardleV1alpha1Client + wardleV1beta1 *wardlev1beta1.WardleV1beta1Client } // WardleV1alpha1 retrieves the WardleV1alpha1Client @@ -45,10 +47,15 @@ func (c *Clientset) WardleV1alpha1() wardlev1alpha1.WardleV1alpha1Interface { return c.wardleV1alpha1 } +// WardleV1beta1 retrieves the WardleV1beta1Client +func (c *Clientset) WardleV1beta1() wardlev1beta1.WardleV1beta1Interface { + return c.wardleV1beta1 +} + // Deprecated: Wardle retrieves the default version of WardleClient. // Please explicitly pick a version. -func (c *Clientset) Wardle() wardlev1alpha1.WardleV1alpha1Interface { - return c.wardleV1alpha1 +func (c *Clientset) Wardle() wardlev1beta1.WardleV1beta1Interface { + return c.wardleV1beta1 } // Discovery retrieves the DiscoveryClient @@ -71,10 +78,13 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { if err != nil { return nil, err } + cs.wardleV1beta1, err = wardlev1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil @@ -85,6 +95,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset cs.wardleV1alpha1 = wardlev1alpha1.NewForConfigOrDie(c) + cs.wardleV1beta1 = wardlev1beta1.NewForConfigOrDie(c) cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) return &cs @@ -94,6 +105,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { func New(c rest.Interface) *Clientset { var cs Clientset cs.wardleV1alpha1 = wardlev1alpha1.New(c) + cs.wardleV1beta1 = wardlev1beta1.New(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c) return &cs diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/doc.go index 006b79214..41721ca52 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/BUILD index db6f9a8a6..d0dfc19a4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/BUILD @@ -19,9 +19,12 @@ go_library( "//vendor/k8s.io/client-go/discovery/fake:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/clientset_generated.go index 3d717dcef..83b23e9b9 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -27,6 +27,8 @@ import ( clientset "k8s.io/sample-apiserver/pkg/client/clientset/versioned" wardlev1alpha1 "k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1" fakewardlev1alpha1 "k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake" + wardlev1beta1 "k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1" + fakewardlev1beta1 "k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake" ) // NewSimpleClientset returns a clientset that will respond with the provided objects. @@ -41,9 +43,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -53,7 +56,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a @@ -75,7 +78,12 @@ func (c *Clientset) WardleV1alpha1() wardlev1alpha1.WardleV1alpha1Interface { return &fakewardlev1alpha1.FakeWardleV1alpha1{Fake: &c.Fake} } -// Wardle retrieves the WardleV1alpha1Client -func (c *Clientset) Wardle() wardlev1alpha1.WardleV1alpha1Interface { - return &fakewardlev1alpha1.FakeWardleV1alpha1{Fake: &c.Fake} +// WardleV1beta1 retrieves the WardleV1beta1Client +func (c *Clientset) WardleV1beta1() wardlev1beta1.WardleV1beta1Interface { + return &fakewardlev1beta1.FakeWardleV1beta1{Fake: &c.Fake} +} + +// Wardle retrieves the WardleV1beta1Client +func (c *Clientset) Wardle() wardlev1beta1.WardleV1beta1Interface { + return &fakewardlev1beta1.FakeWardleV1beta1{Fake: &c.Fake} } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/register.go index 9a46b8d3d..53e363fcf 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" wardlev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + wardlev1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" ) var scheme = runtime.NewScheme() @@ -51,4 +52,5 @@ func init() { // correctly. func AddToScheme(scheme *runtime.Scheme) { wardlev1alpha1.AddToScheme(scheme) + wardlev1beta1.AddToScheme(scheme) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/BUILD index 4ac29c531..042bc1345 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/BUILD @@ -14,6 +14,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/register.go index 85f633ec4..19d87e1e5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" wardlev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + wardlev1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" ) var Scheme = runtime.NewScheme() @@ -51,4 +52,5 @@ func init() { // correctly. func AddToScheme(scheme *runtime.Scheme) { wardlev1alpha1.AddToScheme(scheme) + wardlev1beta1.AddToScheme(scheme) } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_fischer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_fischer.go index d53e02187..3a22fe0ef 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_fischer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_fischer.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -59,7 +59,7 @@ func (c *FakeFischers) List(opts v1.ListOptions) (result *v1alpha1.FischerList, if label == nil { label = labels.Everything() } - list := &v1alpha1.FischerList{} + list := &v1alpha1.FischerList{ListMeta: obj.(*v1alpha1.FischerList).ListMeta} for _, item := range obj.(*v1alpha1.FischerList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_flunder.go index 628e4dd2e..101e301eb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_flunder.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_flunder.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeFlunders) List(opts v1.ListOptions) (result *v1alpha1.FlunderList, if label == nil { label = labels.Everything() } - list := &v1alpha1.FlunderList{} + list := &v1alpha1.FlunderList{ListMeta: obj.(*v1alpha1.FlunderList).ListMeta} for _, item := range obj.(*v1alpha1.FlunderList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_wardle_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_wardle_client.go index 94864f4e5..5803c786a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_wardle_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fake/fake_wardle_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fischer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fischer.go index 2396515a2..cf32143f8 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fischer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/fischer.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/flunder.go index b253e10bd..355451759 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/flunder.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/flunder.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/generated_expansion.go index 015c2e6d7..c25565ca5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/wardle_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/wardle_client.go index 16dd42bd4..c63e25fd2 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/wardle_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1alpha1/wardle_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/BUILD new file mode 100644 index 000000000..837f3a8a4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/BUILD @@ -0,0 +1,39 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "flunder.go", + "generated_expansion.go", + "wardle_client.go", + ], + importpath = "k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/doc.go new file mode 100644 index 000000000..771101956 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1beta1 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/BUILD new file mode 100644 index 000000000..3fb0a9d11 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/BUILD @@ -0,0 +1,37 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "fake_flunder.go", + "fake_wardle_client.go", + ], + importpath = "k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels:go_default_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/watch:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/testing:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/doc.go new file mode 100644 index 000000000..16f443990 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/fake_flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/fake_flunder.go new file mode 100644 index 000000000..c489c58b4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/fake_flunder.go @@ -0,0 +1,140 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" +) + +// FakeFlunders implements FlunderInterface +type FakeFlunders struct { + Fake *FakeWardleV1beta1 + ns string +} + +var flundersResource = schema.GroupVersionResource{Group: "wardle.k8s.io", Version: "v1beta1", Resource: "flunders"} + +var flundersKind = schema.GroupVersionKind{Group: "wardle.k8s.io", Version: "v1beta1", Kind: "Flunder"} + +// Get takes name of the flunder, and returns the corresponding flunder object, and an error if there is any. +func (c *FakeFlunders) Get(name string, options v1.GetOptions) (result *v1beta1.Flunder, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(flundersResource, c.ns, name), &v1beta1.Flunder{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Flunder), err +} + +// List takes label and field selectors, and returns the list of Flunders that match those selectors. +func (c *FakeFlunders) List(opts v1.ListOptions) (result *v1beta1.FlunderList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(flundersResource, flundersKind, c.ns, opts), &v1beta1.FlunderList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta1.FlunderList{ListMeta: obj.(*v1beta1.FlunderList).ListMeta} + for _, item := range obj.(*v1beta1.FlunderList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested flunders. +func (c *FakeFlunders) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(flundersResource, c.ns, opts)) + +} + +// Create takes the representation of a flunder and creates it. Returns the server's representation of the flunder, and an error, if there is any. +func (c *FakeFlunders) Create(flunder *v1beta1.Flunder) (result *v1beta1.Flunder, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(flundersResource, c.ns, flunder), &v1beta1.Flunder{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Flunder), err +} + +// Update takes the representation of a flunder and updates it. Returns the server's representation of the flunder, and an error, if there is any. +func (c *FakeFlunders) Update(flunder *v1beta1.Flunder) (result *v1beta1.Flunder, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(flundersResource, c.ns, flunder), &v1beta1.Flunder{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Flunder), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeFlunders) UpdateStatus(flunder *v1beta1.Flunder) (*v1beta1.Flunder, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(flundersResource, "status", c.ns, flunder), &v1beta1.Flunder{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Flunder), err +} + +// Delete takes name of the flunder and deletes it. Returns an error if one occurs. +func (c *FakeFlunders) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(flundersResource, c.ns, name), &v1beta1.Flunder{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeFlunders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(flundersResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1beta1.FlunderList{}) + return err +} + +// Patch applies the patch and returns the patched flunder. +func (c *FakeFlunders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Flunder, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(flundersResource, c.ns, name, data, subresources...), &v1beta1.Flunder{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Flunder), err +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/fake_wardle_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/fake_wardle_client.go new file mode 100644 index 000000000..b91fa5e78 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/fake/fake_wardle_client.go @@ -0,0 +1,40 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1beta1 "k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1" +) + +type FakeWardleV1beta1 struct { + *testing.Fake +} + +func (c *FakeWardleV1beta1) Flunders(namespace string) v1beta1.FlunderInterface { + return &FakeFlunders{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeWardleV1beta1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/flunder.go new file mode 100644 index 000000000..f0fabeb27 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/flunder.go @@ -0,0 +1,174 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" + scheme "k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme" +) + +// FlundersGetter has a method to return a FlunderInterface. +// A group's client should implement this interface. +type FlundersGetter interface { + Flunders(namespace string) FlunderInterface +} + +// FlunderInterface has methods to work with Flunder resources. +type FlunderInterface interface { + Create(*v1beta1.Flunder) (*v1beta1.Flunder, error) + Update(*v1beta1.Flunder) (*v1beta1.Flunder, error) + UpdateStatus(*v1beta1.Flunder) (*v1beta1.Flunder, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1beta1.Flunder, error) + List(opts v1.ListOptions) (*v1beta1.FlunderList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Flunder, err error) + FlunderExpansion +} + +// flunders implements FlunderInterface +type flunders struct { + client rest.Interface + ns string +} + +// newFlunders returns a Flunders +func newFlunders(c *WardleV1beta1Client, namespace string) *flunders { + return &flunders{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the flunder, and returns the corresponding flunder object, and an error if there is any. +func (c *flunders) Get(name string, options v1.GetOptions) (result *v1beta1.Flunder, err error) { + result = &v1beta1.Flunder{} + err = c.client.Get(). + Namespace(c.ns). + Resource("flunders"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Flunders that match those selectors. +func (c *flunders) List(opts v1.ListOptions) (result *v1beta1.FlunderList, err error) { + result = &v1beta1.FlunderList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("flunders"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested flunders. +func (c *flunders) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("flunders"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a flunder and creates it. Returns the server's representation of the flunder, and an error, if there is any. +func (c *flunders) Create(flunder *v1beta1.Flunder) (result *v1beta1.Flunder, err error) { + result = &v1beta1.Flunder{} + err = c.client.Post(). + Namespace(c.ns). + Resource("flunders"). + Body(flunder). + Do(). + Into(result) + return +} + +// Update takes the representation of a flunder and updates it. Returns the server's representation of the flunder, and an error, if there is any. +func (c *flunders) Update(flunder *v1beta1.Flunder) (result *v1beta1.Flunder, err error) { + result = &v1beta1.Flunder{} + err = c.client.Put(). + Namespace(c.ns). + Resource("flunders"). + Name(flunder.Name). + Body(flunder). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *flunders) UpdateStatus(flunder *v1beta1.Flunder) (result *v1beta1.Flunder, err error) { + result = &v1beta1.Flunder{} + err = c.client.Put(). + Namespace(c.ns). + Resource("flunders"). + Name(flunder.Name). + SubResource("status"). + Body(flunder). + Do(). + Into(result) + return +} + +// Delete takes name of the flunder and deletes it. Returns an error if one occurs. +func (c *flunders) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("flunders"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *flunders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("flunders"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched flunder. +func (c *flunders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Flunder, err error) { + result = &v1beta1.Flunder{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("flunders"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/generated_expansion.go new file mode 100644 index 000000000..dfebd84cf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +type FlunderExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/wardle_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/wardle_client.go new file mode 100644 index 000000000..c75abb323 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/typed/wardle/v1beta1/wardle_client.go @@ -0,0 +1,90 @@ +/* +Copyright 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +import ( + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + rest "k8s.io/client-go/rest" + v1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" + "k8s.io/sample-apiserver/pkg/client/clientset/versioned/scheme" +) + +type WardleV1beta1Interface interface { + RESTClient() rest.Interface + FlundersGetter +} + +// WardleV1beta1Client is used to interact with features provided by the wardle.k8s.io group. +type WardleV1beta1Client struct { + restClient rest.Interface +} + +func (c *WardleV1beta1Client) Flunders(namespace string) FlunderInterface { + return newFlunders(c, namespace) +} + +// NewForConfig creates a new WardleV1beta1Client for the given config. +func NewForConfig(c *rest.Config) (*WardleV1beta1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &WardleV1beta1Client{client}, nil +} + +// NewForConfigOrDie creates a new WardleV1beta1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *WardleV1beta1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new WardleV1beta1Client for the given RESTClient. +func New(c rest.Interface) *WardleV1beta1Client { + return &WardleV1beta1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1beta1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *WardleV1beta1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/BUILD index 6f5750e8a..49acbd46f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/BUILD @@ -14,6 +14,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/factory.go index 4c8ed91b1..208e2dfac 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,12 +32,16 @@ import ( wardle "k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client versioned.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -45,23 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -110,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/generic.go index c6962ed1c..298cb25f7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" v1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + v1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" ) // GenericInformer is type of SharedIndexInformer which will locate and delegate to other @@ -58,6 +59,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case v1alpha1.SchemeGroupVersion.WithResource("flunders"): return &genericInformer{resource: resource.GroupResource(), informer: f.Wardle().V1alpha1().Flunders().Informer()}, nil + // Group=wardle.k8s.io, Version=v1beta1 + case v1beta1.SchemeGroupVersion.WithResource("flunders"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wardle().V1beta1().Flunders().Informer()}, nil + } return nil, fmt.Errorf("no informer found for %v", resource) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index 6c91002da..aadacd32d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/BUILD index 9d525e306..14b7a9893 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/BUILD @@ -8,6 +8,7 @@ go_library( deps = [ "//vendor/k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1:go_default_library", ], ) @@ -23,6 +24,7 @@ filegroup( srcs = [ ":package-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1:all-srcs", + "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/interface.go index 7d5e12e68..78c3fa357 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -21,12 +21,15 @@ package wardle import ( internalinterfaces "k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces" v1alpha1 "k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1" + v1beta1 "k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1" ) // Interface provides access to each of this group's versions. type Interface interface { // V1alpha1 provides access to shared informers for resources in V1alpha1. V1alpha1() v1alpha1.Interface + // V1beta1 provides access to shared informers for resources in V1beta1. + V1beta1() v1beta1.Interface } type group struct { @@ -44,3 +47,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList func (g *group) V1alpha1() v1alpha1.Interface { return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) } + +// V1beta1 returns a new v1beta1.Interface. +func (g *group) V1beta1() v1beta1.Interface { + return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/fischer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/fischer.go index 6fa80d59c..4a1df55a1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/fischer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/fischer.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/flunder.go index 6f81c28bc..fc7c9b470 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/flunder.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/flunder.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/interface.go index 85ebff0ec..c0e369419 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1/BUILD new file mode 100644 index 000000000..892c0bf8a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1/BUILD @@ -0,0 +1,35 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "flunder.go", + "interface.go", + ], + importpath = "k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/client/clientset/versioned:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1/flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1/flunder.go new file mode 100644 index 000000000..bc72fdd1c --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1/flunder.go @@ -0,0 +1,89 @@ +/* +Copyright 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1beta1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + wardle_v1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" + versioned "k8s.io/sample-apiserver/pkg/client/clientset/versioned" + internalinterfaces "k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces" + v1beta1 "k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1" +) + +// FlunderInformer provides access to a shared informer and lister for +// Flunders. +type FlunderInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1beta1.FlunderLister +} + +type flunderInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewFlunderInformer constructs a new informer for Flunder type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFlunderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredFlunderInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredFlunderInformer constructs a new informer for Flunder type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredFlunderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WardleV1beta1().Flunders(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WardleV1beta1().Flunders(namespace).Watch(options) + }, + }, + &wardle_v1beta1.Flunder{}, + resyncPeriod, + indexers, + ) +} + +func (f *flunderInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredFlunderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *flunderInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&wardle_v1beta1.Flunder{}, f.defaultInformer) +} + +func (f *flunderInformer) Lister() v1beta1.FlunderLister { + return v1beta1.NewFlunderLister(f.Informer().GetIndexer()) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1/interface.go new file mode 100644 index 000000000..46690bc74 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions/wardle/v1beta1/interface.go @@ -0,0 +1,45 @@ +/* +Copyright 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1beta1 + +import ( + internalinterfaces "k8s.io/sample-apiserver/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // Flunders returns a FlunderInformer. + Flunders() FlunderInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Flunders returns a FlunderInformer. +func (v *version) Flunders() FlunderInformer { + return &flunderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/factory.go index 107fc56cf..8cb755ece 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,12 +32,16 @@ import ( wardle "k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client internalversion.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -45,23 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client internalversion.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -110,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/generic.go index 14240b5b3..a0291d38a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go index c7c3569a2..694330fa5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/interface.go index 8347bfae4..bccd11a2a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/fischer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/fischer.go index 24de7995f..de3b706a5 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/fischer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/fischer.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/flunder.go index 78aa494b7..67c22c842 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/flunder.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/flunder.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/interface.go index 38b18a846..b3b98a338 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/expansion_generated.go index 424b976af..89892308b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/fischer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/fischer.go index 804bb71c8..63ec3b506 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/fischer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/fischer.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/flunder.go index fa8ac23d0..f15119845 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/flunder.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/flunder.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/expansion_generated.go index bd19b6220..d108410b7 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/fischer.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/fischer.go index 5f397c157..59edff87e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/fischer.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/fischer.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/flunder.go index a1da78441..7c1b69b4b 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/flunder.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1/flunder.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1/BUILD new file mode 100644 index 000000000..f2b306d89 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "expansion_generated.go", + "flunder.go", + ], + importpath = "k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1/expansion_generated.go new file mode 100644 index 000000000..666d4344c --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1/expansion_generated.go @@ -0,0 +1,27 @@ +/* +Copyright 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1beta1 + +// FlunderListerExpansion allows custom methods to be added to +// FlunderLister. +type FlunderListerExpansion interface{} + +// FlunderNamespaceListerExpansion allows custom methods to be added to +// FlunderNamespaceLister. +type FlunderNamespaceListerExpansion interface{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1/flunder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1/flunder.go new file mode 100644 index 000000000..d8c96513a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1/flunder.go @@ -0,0 +1,94 @@ +/* +Copyright 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" +) + +// FlunderLister helps list Flunders. +type FlunderLister interface { + // List lists all Flunders in the indexer. + List(selector labels.Selector) (ret []*v1beta1.Flunder, err error) + // Flunders returns an object that can list and get Flunders. + Flunders(namespace string) FlunderNamespaceLister + FlunderListerExpansion +} + +// flunderLister implements the FlunderLister interface. +type flunderLister struct { + indexer cache.Indexer +} + +// NewFlunderLister returns a new FlunderLister. +func NewFlunderLister(indexer cache.Indexer) FlunderLister { + return &flunderLister{indexer: indexer} +} + +// List lists all Flunders in the indexer. +func (s *flunderLister) List(selector labels.Selector) (ret []*v1beta1.Flunder, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta1.Flunder)) + }) + return ret, err +} + +// Flunders returns an object that can list and get Flunders. +func (s *flunderLister) Flunders(namespace string) FlunderNamespaceLister { + return flunderNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// FlunderNamespaceLister helps list and get Flunders. +type FlunderNamespaceLister interface { + // List lists all Flunders in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1beta1.Flunder, err error) + // Get retrieves the Flunder from the indexer for a given namespace and name. + Get(name string) (*v1beta1.Flunder, error) + FlunderNamespaceListerExpansion +} + +// flunderNamespaceLister implements the FlunderNamespaceLister +// interface. +type flunderNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Flunders in the indexer for a given namespace. +func (s flunderNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.Flunder, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta1.Flunder)) + }) + return ret, err +} + +// Get retrieves the Flunder from the indexer for a given namespace and name. +func (s flunderNamespaceLister) Get(name string) (*v1beta1.Flunder, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1beta1.Resource("flunder"), name) + } + return obj.(*v1beta1.Flunder), nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go index f8715db34..f46f25e89 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go @@ -137,6 +137,7 @@ func (o WardleServerOptions) RunWardleServer(stopCh <-chan struct{}) error { server.GenericAPIServer.AddPostStartHook("start-sample-server-informers", func(context genericapiserver.PostStartHookContext) error { config.GenericConfig.SharedInformerFactory.Start(context.StopCh) + o.SharedInformerFactory.Start(context.StopCh) return nil }) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/BUILD index e4d171235..433a49f76 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/BUILD @@ -17,7 +17,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/strategy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/strategy.go index 3f739c3da..a0e9af28c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/strategy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/fischer/strategy.go @@ -17,6 +17,7 @@ limitations under the License. package fischer import ( + "context" "fmt" "k8s.io/apimachinery/pkg/fields" @@ -27,7 +28,6 @@ import ( "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/sample-apiserver/pkg/apis/wardle" ) @@ -70,13 +70,13 @@ func (fischerStrategy) NamespaceScoped() bool { return false } -func (fischerStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (fischerStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { } -func (fischerStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (fischerStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } -func (fischerStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { +func (fischerStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return field.ErrorList{} } @@ -91,6 +91,6 @@ func (fischerStrategy) AllowUnconditionalUpdate() bool { func (fischerStrategy) Canonicalize(obj runtime.Object) { } -func (fischerStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (fischerStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return field.ErrorList{} } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/BUILD index c552da375..2e2bcb762 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/BUILD @@ -17,12 +17,12 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/validation:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/registry:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/strategy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/strategy.go index b20b909d7..8f6fdccf0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/strategy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/strategy.go @@ -17,6 +17,7 @@ limitations under the License. package flunder import ( + "context" "fmt" "k8s.io/apimachinery/pkg/fields" @@ -26,8 +27,8 @@ import ( "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" + "k8s.io/sample-apiserver/pkg/apis/wardle/validation" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/sample-apiserver/pkg/apis/wardle" ) @@ -70,14 +71,15 @@ func (flunderStrategy) NamespaceScoped() bool { return true } -func (flunderStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { +func (flunderStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { } -func (flunderStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { +func (flunderStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } -func (flunderStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { - return field.ErrorList{} +func (flunderStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { + flunder := obj.(*wardle.Flunder) + return validation.ValidateFlunder(flunder) } func (flunderStrategy) AllowCreateOnUpdate() bool { @@ -91,6 +93,6 @@ func (flunderStrategy) AllowUnconditionalUpdate() bool { func (flunderStrategy) Canonicalize(obj runtime.Object) { } -func (flunderStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { +func (flunderStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return field.ErrorList{} } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/BUILD index 22f519626..88eca68da 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/BUILD @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test") go_library( name = "go_default_library", @@ -18,6 +18,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/informers/apps/v1: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", @@ -30,6 +31,7 @@ go_library( "//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned:go_default_library", "//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme:go_default_library", "//vendor/k8s.io/sample-controller/pkg/client/informers/externalversions:go_default_library", + "//vendor/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1:go_default_library", "//vendor/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1:go_default_library", "//vendor/k8s.io/sample-controller/pkg/signals:go_default_library", ], @@ -61,3 +63,24 @@ filegroup( tags = ["automanaged"], visibility = ["//visibility:public"], ) + +go_test( + name = "go_default_test", + srcs = ["controller_test.go"], + embed = [":go_default_library"], + deps = [ + "//vendor/k8s.io/api/apps/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/util/diff:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", + "//vendor/k8s.io/client-go/testing: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/sample-controller/pkg/apis/samplecontroller/v1alpha1:go_default_library", + "//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned/fake:go_default_library", + "//vendor/k8s.io/sample-controller/pkg/client/informers/externalversions:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/Godeps/Godeps.json b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/Godeps/Godeps.json index fd52583a7..077157f6a 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/Godeps/Godeps.json +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/Godeps/Godeps.json @@ -1,7 +1,7 @@ { "ImportPath": "k8s.io/sample-controller", - "GoVersion": "go1.9", - "GodepVersion": "v79", + "GoVersion": "go1.10", + "GodepVersion": "v80", "Packages": [ "./..." ], @@ -32,23 +32,27 @@ }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" }, { "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/google/btree", + "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" }, { "ImportPath": "github.com/google/gofuzz", @@ -66,6 +70,14 @@ "ImportPath": "github.com/googleapis/gnostic/extensions", "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, { "ImportPath": "github.com/hashicorp/golang-lru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" @@ -74,17 +86,25 @@ "ImportPath": "github.com/hashicorp/golang-lru/simplelru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" }, - { - "ImportPath": "github.com/howeyc/gopass", - "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" - }, { "ImportPath": "github.com/imdario/mergo", "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" }, { "ImportPath": "github.com/json-iterator/go", - "Rev": "13f86432b882000a51c6e610c620974462691a97" + "Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682" + }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd" + }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" }, { "ImportPath": "github.com/spf13/pflag", @@ -92,7 +112,7 @@ }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" + "Rev": "49796115aa4b964c318aad4f3084fdb41e9aa067" }, { "ImportPath": "golang.org/x/net/context", @@ -246,6 +266,10 @@ "ImportPath": "k8s.io/api/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -570,6 +594,10 @@ "ImportPath": "k8s.io/client-go/informers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/settings", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -598,6 +626,10 @@ "ImportPath": "k8s.io/client-go/kubernetes", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/scheme", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -606,114 +638,234 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1beta2", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/authentication/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/authentication/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/authentication/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/authorization/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/authorization/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/authorization/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/autoscaling/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v2alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/core/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/core/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/events/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/events/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/extensions/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/networking/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/networking/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/policy/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/admissionregistration/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -794,6 +946,10 @@ "ImportPath": "k8s.io/client-go/listers/scheduling/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/settings/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -818,6 +974,10 @@ "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/pkg/version", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -890,6 +1050,10 @@ "ImportPath": "k8s.io/client-go/util/cert", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/connrotation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -912,7 +1076,7 @@ }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "39cb288412c48cb533ba4be5d6c28620b9a0c1b4" + "Rev": "91cfa479c814065e420cee7ed227db0f63a5854e" } ] } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/README.md b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/README.md index e2776a218..207aebd81 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/README.md +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/README.md @@ -23,6 +23,13 @@ Changes should not be made to these files manually, and when creating your own controller based off of this implementation you should not copy these files and instead run the `update-codegen` script to generate your own. +## Details + +The sample controller uses [client-go library](https://github.com/kubernetes/client-go/tree/master/tools/cache) extensively. +The details of interaction points of the sample controller with various mechanisms from this library are +explained [here](docs/controller-client-go.md). + + ## Purpose This is an example of how to build a kube-like controller with a single type. @@ -79,17 +86,44 @@ type User struct { To validate custom resources, use the [`CustomResourceValidation`](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/#validation) feature. -This feature is beta and enabled by default in v1.9. If you are using v1.8, enable the feature using -the `CustomResourceValidation` feature gate on the [kube-apiserver](https://kubernetes.io/docs/admin/kube-apiserver): +This feature is beta and enabled by default in v1.9. + +### Example + +The schema in [`crd-validation.yaml`](./artifacts/examples/crd-validation.yaml) applies the following validation on the custom resource: +`spec.replicas` must be an integer and must have a minimum value of 1 and a maximum value of 10. + +In the above steps, use `crd-validation.yaml` to create the CRD: ```sh ---feature-gates=CustomResourceValidation=true +# create a CustomResourceDefinition supporting validation +$ kubectl create -f artifacts/examples/crd-validation.yaml +``` + +## Subresources + +Custom Resources support `/status` and `/scale` subresources as an +[alpha feature](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/#subresources) in v1.10. +Enable this feature using the `CustomResourceSubresources` feature gate on the [kube-apiserver](https://kubernetes.io/docs/admin/kube-apiserver): + +```sh +--feature-gates=CustomResourceSubresources=true ``` ### Example -The schema in the [example CRD](./artifacts/examples/crd.yaml) applies the following validation on the custom resource: -`spec.replicas` must be an integer and must have a minimum value of 1 and a maximum value of 10. +The CRD in [`crd-status-subresource.yaml`](./artifacts/examples/crd-status-subresource.yaml) enables the `/status` subresource +for custom resources. +This means that [`UpdateStatus`](./controller.go#L330) can be used by the controller to update only the status part of the custom resource. + +To understand why only the status part of the custom resource should be updated, please refer to the [Kubernetes API conventions](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status). + +In the above steps, use `crd-status-subresource.yaml` to create the CRD: + +```sh +# create a CustomResourceDefinition supporting the status subresource +$ kubectl create -f artifacts/examples/crd-status-subresource.yaml +``` ## Cleanup diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/SECURITY_CONTACTS new file mode 100644 index 000000000..0648a8ebf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd-status-subresource.yaml b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd-status-subresource.yaml new file mode 100644 index 000000000..af74dbc5b --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd-status-subresource.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: foos.samplecontroller.k8s.io +spec: + group: samplecontroller.k8s.io + version: v1alpha1 + names: + kind: Foo + plural: foos + scope: Namespaced + subresources: + status: {} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd-validation.yaml b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd-validation.yaml new file mode 100644 index 000000000..36469161c --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd-validation.yaml @@ -0,0 +1,20 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: foos.samplecontroller.k8s.io +spec: + group: samplecontroller.k8s.io + version: v1alpha1 + names: + kind: Foo + plural: foos + scope: Namespaced + validation: + openAPIV3Schema: + properties: + spec: + properties: + replicas: + type: integer + minimum: 1 + maximum: 10 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd.yaml b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd.yaml index 36469161c..4a457068d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd.yaml +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/artifacts/examples/crd.yaml @@ -9,12 +9,3 @@ spec: kind: Foo plural: foos scope: Namespaced - validation: - openAPIV3Schema: - properties: - spec: - properties: - replicas: - type: integer - minimum: 1 - maximum: 10 diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/controller.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/controller.go index a98ff1f96..3159e7bcb 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/controller.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/controller.go @@ -28,7 +28,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" - kubeinformers "k8s.io/client-go/informers" + appsinformers "k8s.io/client-go/informers/apps/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" @@ -40,7 +40,7 @@ import ( samplev1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" clientset "k8s.io/sample-controller/pkg/client/clientset/versioned" samplescheme "k8s.io/sample-controller/pkg/client/clientset/versioned/scheme" - informers "k8s.io/sample-controller/pkg/client/informers/externalversions" + informers "k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1" listers "k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1" ) @@ -88,13 +88,8 @@ type Controller struct { func NewController( kubeclientset kubernetes.Interface, sampleclientset clientset.Interface, - kubeInformerFactory kubeinformers.SharedInformerFactory, - sampleInformerFactory informers.SharedInformerFactory) *Controller { - - // obtain references to shared index informers for the Deployment and Foo - // types. - deploymentInformer := kubeInformerFactory.Apps().V1().Deployments() - fooInformer := sampleInformerFactory.Samplecontroller().V1alpha1().Foos() + deploymentInformer appsinformers.DeploymentInformer, + fooInformer informers.FooInformer) *Controller { // Create event broadcaster // Add sample-controller types to the default Kubernetes Scheme so Events can be @@ -327,10 +322,10 @@ func (c *Controller) updateFooStatus(foo *samplev1alpha1.Foo, deployment *appsv1 // Or create a copy manually for better performance fooCopy := foo.DeepCopy() fooCopy.Status.AvailableReplicas = deployment.Status.AvailableReplicas - // Until #38113 is merged, we must use Update instead of UpdateStatus to - // update the Status block of the Foo resource. UpdateStatus will not - // allow changes to the Spec of the resource, which is ideal for ensuring - // nothing other than resource status has been updated. + // If the CustomResourceSubresources feature gate is not enabled, + // we must use Update instead of UpdateStatus to update the Status block of the Foo resource. + // UpdateStatus will not allow changes to the Spec of the resource, + // which is ideal for ensuring nothing other than resource status has been updated. _, err := c.sampleclientset.SamplecontrollerV1alpha1().Foos(foo.Namespace).Update(fooCopy) return err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/controller_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/controller_test.go new file mode 100644 index 000000000..8eea81613 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/controller_test.go @@ -0,0 +1,313 @@ +/* +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 main + +import ( + "fmt" + "reflect" + "testing" + "time" + + apps "k8s.io/api/apps/v1" + 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" + kubeinformers "k8s.io/client-go/informers" + k8sfake "k8s.io/client-go/kubernetes/fake" + core "k8s.io/client-go/testing" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + + samplecontroller "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" + "k8s.io/sample-controller/pkg/client/clientset/versioned/fake" + informers "k8s.io/sample-controller/pkg/client/informers/externalversions" +) + +var ( + alwaysReady = func() bool { return true } + noResyncPeriodFunc = func() time.Duration { return 0 } +) + +type fixture struct { + t *testing.T + + client *fake.Clientset + kubeclient *k8sfake.Clientset + // Objects to put in the store. + fooLister []*samplecontroller.Foo + deploymentLister []*apps.Deployment + // Actions expected to happen on the client. + kubeactions []core.Action + actions []core.Action + // Objects from here preloaded into NewSimpleFake. + kubeobjects []runtime.Object + objects []runtime.Object +} + +func newFixture(t *testing.T) *fixture { + f := &fixture{} + f.t = t + f.objects = []runtime.Object{} + f.kubeobjects = []runtime.Object{} + return f +} + +func newFoo(name string, replicas *int32) *samplecontroller.Foo { + return &samplecontroller.Foo{ + TypeMeta: metav1.TypeMeta{APIVersion: samplecontroller.SchemeGroupVersion.String()}, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: metav1.NamespaceDefault, + }, + Spec: samplecontroller.FooSpec{ + DeploymentName: fmt.Sprintf("%s-deployment", name), + Replicas: replicas, + }, + } +} + +func (f *fixture) newController() (*Controller, informers.SharedInformerFactory, kubeinformers.SharedInformerFactory) { + f.client = fake.NewSimpleClientset(f.objects...) + f.kubeclient = k8sfake.NewSimpleClientset(f.kubeobjects...) + + i := informers.NewSharedInformerFactory(f.client, noResyncPeriodFunc()) + k8sI := kubeinformers.NewSharedInformerFactory(f.kubeclient, noResyncPeriodFunc()) + + c := NewController(f.kubeclient, f.client, + k8sI.Apps().V1().Deployments(), i.Samplecontroller().V1alpha1().Foos()) + + c.foosSynced = alwaysReady + c.deploymentsSynced = alwaysReady + c.recorder = &record.FakeRecorder{} + + for _, f := range f.fooLister { + i.Samplecontroller().V1alpha1().Foos().Informer().GetIndexer().Add(f) + } + + for _, d := range f.deploymentLister { + k8sI.Apps().V1().Deployments().Informer().GetIndexer().Add(d) + } + + return c, i, k8sI +} + +func (f *fixture) run(fooName string) { + f.runController(fooName, true, false) +} + +func (f *fixture) runExpectError(fooName string) { + f.runController(fooName, true, true) +} + +func (f *fixture) runController(fooName string, startInformers bool, expectError bool) { + c, i, k8sI := f.newController() + if startInformers { + stopCh := make(chan struct{}) + defer close(stopCh) + i.Start(stopCh) + k8sI.Start(stopCh) + } + + err := c.syncHandler(fooName) + if !expectError && err != nil { + f.t.Errorf("error syncing foo: %v", err) + } else if expectError && err == nil { + f.t.Error("expected error syncing foo, got nil") + } + + actions := filterInformerActions(f.client.Actions()) + for i, action := range actions { + if len(f.actions) < i+1 { + f.t.Errorf("%d unexpected actions: %+v", len(actions)-len(f.actions), actions[i:]) + break + } + + expectedAction := f.actions[i] + checkAction(expectedAction, action, f.t) + } + + if len(f.actions) > len(actions) { + f.t.Errorf("%d additional expected actions:%+v", len(f.actions)-len(actions), f.actions[len(actions):]) + } + + k8sActions := filterInformerActions(f.kubeclient.Actions()) + for i, action := range k8sActions { + if len(f.kubeactions) < i+1 { + f.t.Errorf("%d unexpected actions: %+v", len(k8sActions)-len(f.kubeactions), k8sActions[i:]) + break + } + + expectedAction := f.kubeactions[i] + checkAction(expectedAction, action, f.t) + } + + if len(f.kubeactions) > len(k8sActions) { + f.t.Errorf("%d additional expected actions:%+v", len(f.kubeactions)-len(k8sActions), f.kubeactions[len(k8sActions):]) + } +} + +// checkAction verifies that expected and actual actions are equal and both have +// same attached resources +func checkAction(expected, actual core.Action, t *testing.T) { + if !(expected.Matches(actual.GetVerb(), actual.GetResource().Resource) && actual.GetSubresource() == expected.GetSubresource()) { + t.Errorf("Expected\n\t%#v\ngot\n\t%#v", expected, actual) + return + } + + if reflect.TypeOf(actual) != reflect.TypeOf(expected) { + t.Errorf("Action has wrong type. Expected: %t. Got: %t", expected, actual) + return + } + + switch a := actual.(type) { + case core.CreateAction: + e, _ := expected.(core.CreateAction) + expObject := e.GetObject() + object := a.GetObject() + + if !reflect.DeepEqual(expObject, object) { + t.Errorf("Action %s %s has wrong object\nDiff:\n %s", + a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintDiff(expObject, object)) + } + case core.UpdateAction: + e, _ := expected.(core.UpdateAction) + expObject := e.GetObject() + object := a.GetObject() + + if !reflect.DeepEqual(expObject, object) { + t.Errorf("Action %s %s has wrong object\nDiff:\n %s", + a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintDiff(expObject, object)) + } + case core.PatchAction: + e, _ := expected.(core.PatchAction) + expPatch := e.GetPatch() + patch := a.GetPatch() + + if !reflect.DeepEqual(expPatch, expPatch) { + t.Errorf("Action %s %s has wrong patch\nDiff:\n %s", + a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintDiff(expPatch, patch)) + } + } +} + +// filterInformerActions filters list and watch actions for testing resources. +// Since list and watch don't change resource state we can filter it to lower +// nose level in our tests. +func filterInformerActions(actions []core.Action) []core.Action { + ret := []core.Action{} + for _, action := range actions { + if len(action.GetNamespace()) == 0 && + (action.Matches("list", "foos") || + action.Matches("watch", "foos") || + action.Matches("list", "deployments") || + action.Matches("watch", "deployments")) { + continue + } + ret = append(ret, action) + } + + return ret +} + +func (f *fixture) expectCreateDeploymentAction(d *apps.Deployment) { + f.kubeactions = append(f.kubeactions, core.NewCreateAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d)) +} + +func (f *fixture) expectUpdateDeploymentAction(d *apps.Deployment) { + f.kubeactions = append(f.kubeactions, core.NewUpdateAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d)) +} + +func (f *fixture) expectUpdateFooStatusAction(foo *samplecontroller.Foo) { + action := core.NewUpdateAction(schema.GroupVersionResource{Resource: "foos"}, foo.Namespace, foo) + // TODO: Until #38113 is merged, we can't use Subresource + //action.Subresource = "status" + f.actions = append(f.actions, action) +} + +func getKey(foo *samplecontroller.Foo, t *testing.T) string { + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(foo) + if err != nil { + t.Errorf("Unexpected error getting key for foo %v: %v", foo.Name, err) + return "" + } + return key +} + +func TestCreatesDeployment(t *testing.T) { + f := newFixture(t) + foo := newFoo("test", int32Ptr(1)) + + f.fooLister = append(f.fooLister, foo) + f.objects = append(f.objects, foo) + + expDeployment := newDeployment(foo) + f.expectCreateDeploymentAction(expDeployment) + f.expectUpdateFooStatusAction(foo) + + f.run(getKey(foo, t)) +} + +func TestDoNothing(t *testing.T) { + f := newFixture(t) + foo := newFoo("test", int32Ptr(1)) + d := newDeployment(foo) + + f.fooLister = append(f.fooLister, foo) + f.objects = append(f.objects, foo) + f.deploymentLister = append(f.deploymentLister, d) + f.kubeobjects = append(f.kubeobjects, d) + + f.expectUpdateFooStatusAction(foo) + f.run(getKey(foo, t)) +} + +func TestUpdateDeployment(t *testing.T) { + f := newFixture(t) + foo := newFoo("test", int32Ptr(1)) + d := newDeployment(foo) + + // Update replicas + foo.Spec.Replicas = int32Ptr(2) + expDeployment := newDeployment(foo) + + f.fooLister = append(f.fooLister, foo) + f.objects = append(f.objects, foo) + f.deploymentLister = append(f.deploymentLister, d) + f.kubeobjects = append(f.kubeobjects, d) + + f.expectUpdateFooStatusAction(foo) + f.expectUpdateDeploymentAction(expDeployment) + f.run(getKey(foo, t)) +} + +func TestNotControlledByUs(t *testing.T) { + f := newFixture(t) + foo := newFoo("test", int32Ptr(1)) + d := newDeployment(foo) + + d.ObjectMeta.OwnerReferences = []metav1.OwnerReference{} + + f.fooLister = append(f.fooLister, foo) + f.objects = append(f.objects, foo) + f.deploymentLister = append(f.deploymentLister, d) + f.kubeobjects = append(f.kubeobjects, d) + + f.runExpectError(getKey(foo, t)) +} + +func int32Ptr(i int32) *int32 { return &i } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/docs/controller-client-go.md b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/docs/controller-client-go.md new file mode 100644 index 000000000..93d24d725 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/docs/controller-client-go.md @@ -0,0 +1,64 @@ +# client-go under the hood + +The [client-go](https://github.com/kubernetes/client-go/) library contains various mechanisms that you can use when +developing your custom controllers. These mechanisms are defined in the +[tools/cache folder](https://github.com/kubernetes/client-go/tree/master/tools/cache) of the library. + +Here is a pictorial representation showing how the various components in +the client-go library work and their interaction points with the custom +controller code that you will write. + +

    + +

    + +## client-go components + +* Reflector: A reflector, which is defined in [type *Reflector* inside package *cache*](https://github.com/kubernetes/client-go/blob/master/tools/cache/reflector.go), +watches the Kubernetes API for the specified resource type (kind). +The function in which this is done is *ListAndWatch*. +The watch could be for an in-built resource or it could be for a custom resource. +When the reflector receives notification about existence of new +resource instance through the watch API, it gets the newly created object +using the corresponding listing API and puts it in the Delta Fifo queue +inside the *watchHandler* function. + + +* Informer: An informer defined in the [base controller inside package *cache*](https://github.com/kubernetes/client-go/blob/master/tools/cache/controller.go) pops objects from the Delta Fifo queue. +The function in which this is done is *processLoop*. The job of this base controller +is to save the object for later retrieval, and to invoke our controller passing it the object. + +* Indexer: An indexer provides indexing functionality over objects. +It is defined in [type *Indexer* inside package *cache*](https://github.com/kubernetes/client-go/blob/master/tools/cache/index.go). A typical indexing use-case is to create an index based on object labels. Indexer can +maintain indexes based on several indexing functions. +Indexer uses a thread-safe data store to store objects and their keys. +There is a default function named *MetaNamespaceKeyFunc* defined in [type Store inside package cache](https://github.com/kubernetes/client-go/blob/master/tools/cache/store.go) +that generates an object’s key as `/` combination for that object. + + +## Custom Controller components + +* Informer reference: This is the reference to the Informer instance that knows +how to work with your custom resource objects. Your custom controller code needs +to create the appropriate Informer. + +* Indexer reference: This is the reference to the Indexer instance that knows +how to work with your custom resource objects. Your custom controller code needs +to create this. You will be using this reference for retrieving objects for +later processing. + +The base controller in client-go provides the *NewIndexerInformer* function to create Informer and Indexer. +In your code you can either [directly invoke this function](https://github.com/kubernetes/client-go/blob/master/examples/workqueue/main.go#L174) or [use factory methods for creating an informer.](https://github.com/kubernetes/sample-controller/blob/master/main.go#L61) + +* Resource Event Handlers: These are the callback functions which will be called by +the Informer when it wants to deliver an object to your controller. The typical +pattern to write these functions is to obtain the dispatched object’s key +and enqueue that key in a work queue for further processing. + +* Work queue: This is the queue that you create in your controller code to decouple +delivery of an object from its processing. Resource event handler functions are written +to extract the delivered object’s key and add that to the work queue. + +* Process Item: This is the function that you create in your code which processes items +from the work queue. There can be one or more other functions that do the actual processing. +These functions will typically use the [Indexer reference](https://github.com/kubernetes/client-go/blob/master/examples/workqueue/main.go#L73), or a Listing wrapper to retrieve the object corresponding to the key. \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/docs/images/client-go-controller-interaction.jpeg b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/docs/images/client-go-controller-interaction.jpeg new file mode 100644 index 000000000..48134fa0a Binary files /dev/null and b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/docs/images/client-go-controller-interaction.jpeg differ diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/boilerplate.go.txt b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/boilerplate.go.txt index 59e740c1e..b7c650da4 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/boilerplate.go.txt +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright YEAR The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/update-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/update-codegen.sh index 3697707b7..1423a1afd 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/update-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/update-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/verify-codegen.sh b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/verify-codegen.sh index 9cc02a5a4..d02a6fa39 100755 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/verify-codegen.sh +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/main.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/main.go index d3514fc3a..026083f33 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/main.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/main.go @@ -61,7 +61,9 @@ func main() { kubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClient, time.Second*30) exampleInformerFactory := informers.NewSharedInformerFactory(exampleClient, time.Second*30) - controller := NewController(kubeClient, exampleClient, kubeInformerFactory, exampleInformerFactory) + controller := NewController(kubeClient, exampleClient, + kubeInformerFactory.Apps().V1().Deployments(), + exampleInformerFactory.Samplecontroller().V1alpha1().Foos()) go kubeInformerFactory.Start(stopCh) go exampleInformerFactory.Start(stopCh) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1/types.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1/types.go index 1f6eb1f9a..74ffc6721 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1/types.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1/types.go @@ -21,7 +21,6 @@ import ( ) // +genclient -// +genclient:noStatus // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Foo is a specification for a Foo resource diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1/zz_generated.deepcopy.go index e44e262c7..b2193006d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/BUILD index d208e963c..e9b29e370 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/BUILD +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/BUILD @@ -9,7 +9,6 @@ go_library( importpath = "k8s.io/sample-controller/pkg/client/clientset/versioned", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/clientset.go index 3e700853f..5bdd72904 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/clientset.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -19,7 +19,6 @@ limitations under the License. package versioned import ( - glog "github.com/golang/glog" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -74,7 +73,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { - glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/doc.go index 006b79214..41721ca52 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/clientset_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/clientset_generated.go index 6dc8bf09c..7a388a439 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -41,9 +41,10 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - fakePtr := testing.Fake{} - fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) - fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { gvr := action.GetResource() ns := action.GetNamespace() watch, err := o.Watch(gvr, ns) @@ -53,7 +54,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { return true, watch, nil }) - return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} + return cs } // Clientset implements clientset.Interface. Meant to be embedded into a diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/doc.go index 0bc260bca..9b99e7167 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/register.go index 6c68c2eaf..8bcf33275 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme/doc.go index 5c5c8debb..7dc375616 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme/register.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme/register.go index c06b024a9..4fcc9c48c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme/register.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/doc.go index 69ca30111..df51baa4d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/doc.go index 87a1873ed..16f443990 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/doc.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_foo.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_foo.go index 7ef0c2c10..dc531169c 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_foo.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_foo.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -62,7 +62,7 @@ func (c *FakeFoos) List(opts v1.ListOptions) (result *v1alpha1.FooList, err erro if label == nil { label = labels.Everything() } - list := &v1alpha1.FooList{} + list := &v1alpha1.FooList{ListMeta: obj.(*v1alpha1.FooList).ListMeta} for _, item := range obj.(*v1alpha1.FooList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) @@ -100,6 +100,18 @@ func (c *FakeFoos) Update(foo *v1alpha1.Foo) (result *v1alpha1.Foo, err error) { return obj.(*v1alpha1.Foo), err } +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeFoos) UpdateStatus(foo *v1alpha1.Foo) (*v1alpha1.Foo, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(foosResource, "status", c.ns, foo), &v1alpha1.Foo{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Foo), err +} + // Delete takes name of the foo and deletes it. Returns an error if one occurs. func (c *FakeFoos) Delete(name string, options *v1.DeleteOptions) error { _, err := c.Fake. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_samplecontroller_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_samplecontroller_client.go index 5ed387b32..17a28bb6e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_samplecontroller_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_samplecontroller_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/foo.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/foo.go index 34cf04a39..667edf527 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/foo.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/foo.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -37,6 +37,7 @@ type FoosGetter interface { type FooInterface interface { Create(*v1alpha1.Foo) (*v1alpha1.Foo, error) Update(*v1alpha1.Foo) (*v1alpha1.Foo, error) + UpdateStatus(*v1alpha1.Foo) (*v1alpha1.Foo, error) Delete(name string, options *v1.DeleteOptions) error DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error Get(name string, options v1.GetOptions) (*v1alpha1.Foo, error) @@ -120,6 +121,22 @@ func (c *foos) Update(foo *v1alpha1.Foo) (result *v1alpha1.Foo, err error) { return } +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *foos) UpdateStatus(foo *v1alpha1.Foo) (result *v1alpha1.Foo, err error) { + result = &v1alpha1.Foo{} + err = c.client.Put(). + Namespace(c.ns). + Resource("foos"). + Name(foo.Name). + SubResource("status"). + Body(foo). + Do(). + Into(result) + return +} + // Delete takes name of the foo and deletes it. Returns an error if one occurs. func (c *foos) Delete(name string, options *v1.DeleteOptions) error { return c.client.Delete(). diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/generated_expansion.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/generated_expansion.go index 4e706cb45..b64ea0250 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/generated_expansion.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/samplecontroller_client.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/samplecontroller_client.go index df7f78382..c59278504 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/samplecontroller_client.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/samplecontroller_client.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/factory.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/factory.go index 489409b98..b6cf4fe8d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/factory.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. @@ -32,12 +32,16 @@ import ( samplecontroller "k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller" ) +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + type sharedInformerFactory struct { client versioned.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex defaultResync time.Duration + customResync map[reflect.Type]time.Duration informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -45,23 +49,62 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) + return NewSharedInformerFactoryWithOptions(client, defaultResync) } // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return &sharedInformerFactory{ + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ client: client, - namespace: namespace, - tweakListOptions: tweakListOptions, + namespace: v1.NamespaceAll, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) } + + return factory } // Start initializes all requested informers. @@ -110,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal if exists { return informer } - informer = newFunc(f.client, f.defaultResync) + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) f.informers[informerType] = informer return informer diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/generic.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/generic.go index fbd923f18..ae44b489e 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/generic.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index 20ea47c03..2bdd08120 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/interface.go index ca4d632e4..145651cc1 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1/foo.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1/foo.go index 48986cae0..30507d6cd 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1/foo.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1/foo.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1/interface.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1/interface.go index 578a43485..92ab70f7d 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1/interface.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1/expansion_generated.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1/expansion_generated.go index 6fe9f235e..9a34636b0 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1/expansion_generated.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1/foo.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1/foo.go index 41998b228..a6cbf1663 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1/foo.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1/foo.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 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. diff --git a/vendor/k8s.io/kubernetes/test/BUILD b/vendor/k8s.io/kubernetes/test/BUILD index d8087c512..f55d25935 100644 --- a/vendor/k8s.io/kubernetes/test/BUILD +++ b/vendor/k8s.io/kubernetes/test/BUILD @@ -13,6 +13,7 @@ filegroup( ":package-srcs", "//test/conformance:all-srcs", "//test/e2e:all-srcs", + "//test/e2e_kubeadm:all-srcs", "//test/e2e_node:all-srcs", "//test/fixtures:all-srcs", "//test/images:all-srcs", diff --git a/vendor/k8s.io/kubernetes/test/OWNERS b/vendor/k8s.io/kubernetes/test/OWNERS index b9fd7ab96..9ec90da6c 100644 --- a/vendor/k8s.io/kubernetes/test/OWNERS +++ b/vendor/k8s.io/kubernetes/test/OWNERS @@ -1,5 +1,7 @@ reviewers: - bowei + - rramkumar1 + - MrHohn - deads2k - enisoc - enj # for test/integration/etcd/etcd_storage_path_test.go @@ -27,6 +29,8 @@ reviewers: approvers: - bowei # for test/e2e/{dns*,network}.go - cblecker + - rramkumar1 + - MrHohn - deads2k - enisoc - enj # for test/integration/etcd/etcd_storage_path_test.go diff --git a/vendor/k8s.io/kubernetes/test/conformance/conformance_test.sh b/vendor/k8s.io/kubernetes/test/conformance/conformance_test.sh index 04113c09b..dc448849c 100755 --- a/vendor/k8s.io/kubernetes/test/conformance/conformance_test.sh +++ b/vendor/k8s.io/kubernetes/test/conformance/conformance_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/vendor/k8s.io/kubernetes/test/conformance/testdata/conformance.txt b/vendor/k8s.io/kubernetes/test/conformance/testdata/conformance.txt index f5ff02305..4b72cee5f 100755 --- a/vendor/k8s.io/kubernetes/test/conformance/testdata/conformance.txt +++ b/vendor/k8s.io/kubernetes/test/conformance/testdata/conformance.txt @@ -1,4 +1,4 @@ -test/e2e/apimachinery/custom_resource_definition.go: "creating/deleting custom resource definition objects works " +test/e2e/apimachinery/custom_resource_definition.go: "creating/deleting custom resource definition objects works" test/e2e/apimachinery/garbage_collector.go: "should delete pods created by rc when not orphaning" test/e2e/apimachinery/garbage_collector.go: "should orphan pods created by rc if delete options say so" test/e2e/apimachinery/garbage_collector.go: "should delete RS created by deployment when not orphaning" @@ -6,59 +6,62 @@ test/e2e/apimachinery/garbage_collector.go: "should orphan RS created by deploym test/e2e/apimachinery/garbage_collector.go: "should keep the rc around until all its pods are deleted if the deleteOptions says so" test/e2e/apimachinery/garbage_collector.go: "should not delete dependents that have both valid owner and owner that's waiting for dependents to be deleted" test/e2e/apimachinery/garbage_collector.go: "should not be blocked by dependency circle" +test/e2e/apimachinery/watch.go: "should observe add, update, and delete watch notifications on configmaps" +test/e2e/apimachinery/watch.go: "should be able to start watching from a specific resource version" +test/e2e/apimachinery/watch.go: "should be able to restart watching from the last resource version observed by the previous watch" +test/e2e/apimachinery/watch.go: "should observe an object deletion if it stops meeting the requirements of the selector" test/e2e/apps/daemon_set.go: "should run and stop simple daemon" test/e2e/apps/daemon_set.go: "should run and stop complex daemon" test/e2e/apps/daemon_set.go: "should retry creating failed daemon pods" test/e2e/apps/daemon_set.go: "should update pod when spec was updated and update strategy is RollingUpdate" test/e2e/apps/daemon_set.go: "should rollback without unnecessary restarts" -test/e2e/apps/rc.go: "should serve a basic image on each replica with a public image " -test/e2e/apps/replica_set.go: "should serve a basic image on each replica with a public image " +test/e2e/apps/rc.go: "should serve a basic image on each replica with a public image" +test/e2e/apps/replica_set.go: "should serve a basic image on each replica with a public image" test/e2e/apps/statefulset.go: "should perform rolling updates and roll backs of template modifications" test/e2e/apps/statefulset.go: "should perform canary updates and phased rolling updates of template modifications" test/e2e/apps/statefulset.go: "Scaling should happen in predictable order and halt if any stateful pod is unhealthy" test/e2e/apps/statefulset.go: "Burst scaling should run to completion even with unhealthy pods" test/e2e/apps/statefulset.go: "Should recreate evicted statefulset" -test/e2e/auth/service_accounts.go: "should mount an API token into pods " -test/e2e/auth/service_accounts.go: "should allow opting out of API token automount " -test/e2e/common/configmap.go: "should be consumable via environment variable " -test/e2e/common/configmap.go: "should be consumable via the environment " -test/e2e/common/configmap_volume.go: "should be consumable from pods in volume " -test/e2e/common/configmap_volume.go: "should be consumable from pods in volume with defaultMode set " -test/e2e/common/configmap_volume.go: "should be consumable from pods in volume as non-root " -test/e2e/common/configmap_volume.go: "should be consumable from pods in volume with mappings " +test/e2e/auth/service_accounts.go: "should mount an API token into pods" +test/e2e/auth/service_accounts.go: "should allow opting out of API token automount" +test/e2e/common/configmap.go: "should be consumable via environment variable" +test/e2e/common/configmap.go: "should be consumable via the environment" +test/e2e/common/configmap_volume.go: "should be consumable from pods in volume" +test/e2e/common/configmap_volume.go: "should be consumable from pods in volume with defaultMode set" +test/e2e/common/configmap_volume.go: "should be consumable from pods in volume as non-root" +test/e2e/common/configmap_volume.go: "should be consumable from pods in volume with mappings" test/e2e/common/configmap_volume.go: "should be consumable from pods in volume with mappings and Item mode set" -test/e2e/common/configmap_volume.go: "should be consumable from pods in volume with mappings as non-root " -test/e2e/common/configmap_volume.go: "updates should be reflected in volume " -test/e2e/common/configmap_volume.go: "optional updates should be reflected in volume " -test/e2e/common/configmap_volume.go: "should be consumable in multiple volumes in the same pod " -test/e2e/common/container_probe.go: "with readiness probe should not be ready before initial delay and never restart " -test/e2e/common/container_probe.go: "with readiness probe that fails should never be ready and never restart " -test/e2e/common/container_probe.go: "should be restarted with a exec \"cat /tmp/health\" liveness probe" -test/e2e/common/container_probe.go: "should *not* be restarted with a exec \"cat /tmp/health\" liveness probe" -test/e2e/common/container_probe.go: "should be restarted with a /healthz http liveness probe " -test/e2e/common/container_probe.go: "should have monotonically increasing restart count [Slow]" -test/e2e/common/container_probe.go: "should *not* be restarted with a /healthz http liveness probe " -test/e2e/common/container_probe.go: "should be restarted with a docker exec liveness probe with timeout " -test/e2e/common/docker_containers.go: "should use the image defaults if command and args are blank " -test/e2e/common/docker_containers.go: "should be able to override the image's default arguments (docker cmd) " -test/e2e/common/docker_containers.go: "should be able to override the image's default command (docker entrypoint) " -test/e2e/common/docker_containers.go: "should be able to override the image's default command and arguments " -test/e2e/common/downward_api.go: "should provide pod name, namespace and IP address as env vars " -test/e2e/common/downward_api.go: "should provide host IP as an env var " -test/e2e/common/downward_api.go: "should provide container's limits.cpu/memory and requests.cpu/memory as env vars " -test/e2e/common/downward_api.go: "should provide default limits.cpu/memory from node allocatable " -test/e2e/common/downward_api.go: "should provide pod UID as env vars " -test/e2e/common/downwardapi_volume.go: "should provide podname only " -test/e2e/common/downwardapi_volume.go: "should set DefaultMode on files " -test/e2e/common/downwardapi_volume.go: "should set mode on item file " -test/e2e/common/downwardapi_volume.go: "should update labels on modification " -test/e2e/common/downwardapi_volume.go: "should update annotations on modification " -test/e2e/common/downwardapi_volume.go: "should provide container's cpu limit " -test/e2e/common/downwardapi_volume.go: "should provide container's memory limit " -test/e2e/common/downwardapi_volume.go: "should provide container's cpu request " -test/e2e/common/downwardapi_volume.go: "should provide container's memory request " -test/e2e/common/downwardapi_volume.go: "should provide node allocatable (cpu) as default cpu limit if the limit is not set " -test/e2e/common/downwardapi_volume.go: "should provide node allocatable (memory) as default memory limit if the limit is not set " +test/e2e/common/configmap_volume.go: "should be consumable from pods in volume with mappings as non-root" +test/e2e/common/configmap_volume.go: "updates should be reflected in volume" +test/e2e/common/configmap_volume.go: "optional updates should be reflected in volume" +test/e2e/common/configmap_volume.go: "should be consumable in multiple volumes in the same pod" +test/e2e/common/container_probe.go: "with readiness probe should not be ready before initial delay and never restart" +test/e2e/common/container_probe.go: "with readiness probe that fails should never be ready and never restart" +test/e2e/common/container_probe.go: "should be restarted with a exec \\\"cat /tmp/health\\\" liveness probe" +test/e2e/common/container_probe.go: "should *not* be restarted with a exec \\\"cat /tmp/health\\\" liveness probe" +test/e2e/common/container_probe.go: "should be restarted with a /healthz http liveness probe" +test/e2e/common/container_probe.go: "should have monotonically increasing restart count" +test/e2e/common/container_probe.go: "should *not* be restarted with a /healthz http liveness probe" +test/e2e/common/docker_containers.go: "should use the image defaults if command and args are blank" +test/e2e/common/docker_containers.go: "should be able to override the image's default arguments (docker cmd)" +test/e2e/common/docker_containers.go: "should be able to override the image's default command (docker entrypoint)" +test/e2e/common/docker_containers.go: "should be able to override the image's default command and arguments" +test/e2e/common/downward_api.go: "should provide pod name, namespace and IP address as env vars" +test/e2e/common/downward_api.go: "should provide host IP as an env var" +test/e2e/common/downward_api.go: "should provide container's limits.cpu/memory and requests.cpu/memory as env vars" +test/e2e/common/downward_api.go: "should provide default limits.cpu/memory from node allocatable" +test/e2e/common/downward_api.go: "should provide pod UID as env vars" +test/e2e/common/downwardapi_volume.go: "should provide podname only" +test/e2e/common/downwardapi_volume.go: "should set DefaultMode on files" +test/e2e/common/downwardapi_volume.go: "should set mode on item file" +test/e2e/common/downwardapi_volume.go: "should update labels on modification" +test/e2e/common/downwardapi_volume.go: "should update annotations on modification" +test/e2e/common/downwardapi_volume.go: "should provide container's cpu limit" +test/e2e/common/downwardapi_volume.go: "should provide container's memory limit" +test/e2e/common/downwardapi_volume.go: "should provide container's cpu request" +test/e2e/common/downwardapi_volume.go: "should provide container's memory request" +test/e2e/common/downwardapi_volume.go: "should provide node allocatable (cpu) as default cpu limit if the limit is not set" +test/e2e/common/downwardapi_volume.go: "should provide node allocatable (memory) as default memory limit if the limit is not set" test/e2e/common/empty_dir.go: "volume on tmpfs should have the correct mode" test/e2e/common/empty_dir.go: "should support (root,0644,tmpfs)" test/e2e/common/empty_dir.go: "should support (root,0666,tmpfs)" @@ -73,20 +76,20 @@ test/e2e/common/empty_dir.go: "should support (root,0777,default)" test/e2e/common/empty_dir.go: "should support (non-root,0644,default)" test/e2e/common/empty_dir.go: "should support (non-root,0666,default)" test/e2e/common/empty_dir.go: "should support (non-root,0777,default)" -test/e2e/common/expansion.go: "should allow composing env vars into new env vars " -test/e2e/common/expansion.go: "should allow substituting values in a container's command " -test/e2e/common/expansion.go: "should allow substituting values in a container's args " +test/e2e/common/expansion.go: "should allow composing env vars into new env vars" +test/e2e/common/expansion.go: "should allow substituting values in a container's command" +test/e2e/common/expansion.go: "should allow substituting values in a container's args" test/e2e/common/host_path.go: "should give a volume the correct mode" -test/e2e/common/kubelet_etc_hosts.go: "should test kubelet managed /etc/hosts file " -test/e2e/common/networking.go: "should function for intra-pod communication: http " -test/e2e/common/networking.go: "should function for intra-pod communication: udp " -test/e2e/common/networking.go: "should function for node-pod communication: http " -test/e2e/common/networking.go: "should function for node-pod communication: udp " -test/e2e/common/pods.go: "should get a host IP " -test/e2e/common/pods.go: "should be submitted and removed " -test/e2e/common/pods.go: "should be updated " -test/e2e/common/pods.go: "should allow activeDeadlineSeconds to be updated " -test/e2e/common/pods.go: "should contain environment variables for services " +test/e2e/common/kubelet_etc_hosts.go: "should test kubelet managed /etc/hosts file" +test/e2e/common/networking.go: "should function for intra-pod communication: http" +test/e2e/common/networking.go: "should function for intra-pod communication: udp" +test/e2e/common/networking.go: "should function for node-pod communication: http" +test/e2e/common/networking.go: "should function for node-pod communication: udp" +test/e2e/common/pods.go: "should get a host IP" +test/e2e/common/pods.go: "should be submitted and removed" +test/e2e/common/pods.go: "should be updated" +test/e2e/common/pods.go: "should allow activeDeadlineSeconds to be updated" +test/e2e/common/pods.go: "should contain environment variables for services" test/e2e/common/projected.go: "should be consumable from pods in volume" test/e2e/common/projected.go: "should be consumable from pods in volume with defaultMode set" test/e2e/common/projected.go: "should be consumable from pods in volume as non-root with defaultMode and fsGroup set" @@ -114,54 +117,54 @@ test/e2e/common/projected.go: "should provide container's cpu request" test/e2e/common/projected.go: "should provide container's memory request" test/e2e/common/projected.go: "should provide node allocatable (cpu) as default cpu limit if the limit is not set" test/e2e/common/projected.go: "should provide node allocatable (memory) as default memory limit if the limit is not set" -test/e2e/common/projected.go: "should project all components that make up the projection API [Projection]" -test/e2e/common/secrets.go: "should be consumable from pods in env vars " -test/e2e/common/secrets.go: "should be consumable via the environment " -test/e2e/common/secrets_volume.go: "should be consumable from pods in volume " -test/e2e/common/secrets_volume.go: "should be consumable from pods in volume with defaultMode set " -test/e2e/common/secrets_volume.go: "should be consumable from pods in volume as non-root with defaultMode and fsGroup set " -test/e2e/common/secrets_volume.go: "should be consumable from pods in volume with mappings " -test/e2e/common/secrets_volume.go: "should be consumable from pods in volume with mappings and Item Mode set " -test/e2e/common/secrets_volume.go: "should be consumable in multiple volumes in a pod " -test/e2e/common/secrets_volume.go: "optional updates should be reflected in volume " -test/e2e/kubectl/kubectl.go: "should create and stop a replication controller " -test/e2e/kubectl/kubectl.go: "should scale a replication controller " -test/e2e/kubectl/kubectl.go: "should do a rolling update of a replication controller " -test/e2e/kubectl/kubectl.go: "should create and stop a working application " -test/e2e/kubectl/kubectl.go: "should check if v1 is in available api versions " -test/e2e/kubectl/kubectl.go: "should check if Kubernetes master services is included in cluster-info " -test/e2e/kubectl/kubectl.go: "should check if kubectl describe prints relevant information for rc and pods " -test/e2e/kubectl/kubectl.go: "should create services for rc " -test/e2e/kubectl/kubectl.go: "should update the label on a resource " -test/e2e/kubectl/kubectl.go: "should be able to retrieve and filter logs " -test/e2e/kubectl/kubectl.go: "should add annotations for pods in rc " -test/e2e/kubectl/kubectl.go: "should check is all data is printed " -test/e2e/kubectl/kubectl.go: "should create an rc or deployment from an image " -test/e2e/kubectl/kubectl.go: "should create an rc from an image " -test/e2e/kubectl/kubectl.go: "should support rolling-update to same image " -test/e2e/kubectl/kubectl.go: "should create a deployment from an image " -test/e2e/kubectl/kubectl.go: "should create a job from an image when restart is OnFailure " -test/e2e/kubectl/kubectl.go: "should create a pod from an image when restart is Never " -test/e2e/kubectl/kubectl.go: "should update a single-container pod's image " -test/e2e/kubectl/kubectl.go: "should create a job from an image, then delete the job " -test/e2e/kubectl/kubectl.go: "should support proxy with --port 0 " -test/e2e/kubectl/kubectl.go: "should support --unix-socket=/path " -test/e2e/network/dns.go: "should provide DNS for the cluster " -test/e2e/network/dns.go: "should provide DNS for services " -test/e2e/network/proxy.go: "should proxy logs on node with explicit kubelet port using proxy subresource " -test/e2e/network/proxy.go: "should proxy logs on node using proxy subresource " -test/e2e/network/proxy.go: "should proxy through a service and a pod " -test/e2e/network/service.go: "should provide secure master service " -test/e2e/network/service.go: "should serve a basic endpoint from pods " -test/e2e/network/service.go: "should serve multiport endpoints from pods " -test/e2e/network/service_latency.go: "should not be very high " -test/e2e/node/events.go: "should be sent by kubelets and the scheduler about pods scheduling and running " -test/e2e/node/pods.go: "should be submitted and removed [Flaky]" -test/e2e/node/pods.go: "should be submitted and removed " -test/e2e/node/pre_stop.go: "should call prestop when killing a pod " -test/e2e/scheduling/predicates.go: "validates resource limits of pods that are allowed to run " -test/e2e/scheduling/predicates.go: "validates that NodeSelector is respected if not matching " -test/e2e/scheduling/predicates.go: "validates that NodeSelector is respected if matching " +test/e2e/common/projected.go: "should project all components that make up the projection API" +test/e2e/common/secrets.go: "should be consumable from pods in env vars" +test/e2e/common/secrets.go: "should be consumable via the environment" +test/e2e/common/secrets_volume.go: "should be consumable from pods in volume" +test/e2e/common/secrets_volume.go: "should be consumable from pods in volume with defaultMode set" +test/e2e/common/secrets_volume.go: "should be consumable from pods in volume as non-root with defaultMode and fsGroup set" +test/e2e/common/secrets_volume.go: "should be consumable from pods in volume with mappings" +test/e2e/common/secrets_volume.go: "should be consumable from pods in volume with mappings and Item Mode set" +test/e2e/common/secrets_volume.go: "should be consumable in multiple volumes in a pod" +test/e2e/common/secrets_volume.go: "optional updates should be reflected in volume" +test/e2e/kubectl/kubectl.go: "should create and stop a replication controller" +test/e2e/kubectl/kubectl.go: "should scale a replication controller" +test/e2e/kubectl/kubectl.go: "should do a rolling update of a replication controller" +test/e2e/kubectl/kubectl.go: "should create and stop a working application" +test/e2e/kubectl/kubectl.go: "should check if v1 is in available api versions" +test/e2e/kubectl/kubectl.go: "should check if Kubernetes master services is included in cluster-info" +test/e2e/kubectl/kubectl.go: "should check if kubectl describe prints relevant information for rc and pods" +test/e2e/kubectl/kubectl.go: "should create services for rc" +test/e2e/kubectl/kubectl.go: "should update the label on a resource" +test/e2e/kubectl/kubectl.go: "should be able to retrieve and filter logs" +test/e2e/kubectl/kubectl.go: "should add annotations for pods in rc" +test/e2e/kubectl/kubectl.go: "should check is all data is printed" +test/e2e/kubectl/kubectl.go: "should create an rc or deployment from an image" +test/e2e/kubectl/kubectl.go: "should create an rc from an image" +test/e2e/kubectl/kubectl.go: "should support rolling-update to same image" +test/e2e/kubectl/kubectl.go: "should create a deployment from an image" +test/e2e/kubectl/kubectl.go: "should create a job from an image when restart is OnFailure" +test/e2e/kubectl/kubectl.go: "should create a pod from an image when restart is Never" +test/e2e/kubectl/kubectl.go: "should update a single-container pod's image" +test/e2e/kubectl/kubectl.go: "should create a job from an image, then delete the job" +test/e2e/kubectl/kubectl.go: "should support proxy with --port 0" +test/e2e/kubectl/kubectl.go: "should support --unix-socket=/path" +test/e2e/network/dns.go: "should provide DNS for the cluster" +test/e2e/network/dns.go: "should provide DNS for services" +test/e2e/network/proxy.go: "should proxy logs on node with explicit kubelet port using proxy subresource" +test/e2e/network/proxy.go: "should proxy logs on node using proxy subresource" +test/e2e/network/proxy.go: "should proxy through a service and a pod" +test/e2e/network/service.go: "should provide secure master service" +test/e2e/network/service.go: "should serve a basic endpoint from pods" +test/e2e/network/service.go: "should serve multiport endpoints from pods" +test/e2e/network/service_latency.go: "should not be very high" +test/e2e/node/events.go: "should be sent by kubelets and the scheduler about pods scheduling and running" +test/e2e/node/pods.go: "should be submitted and removed" +test/e2e/node/pods.go: "should be submitted and removed" +test/e2e/node/pre_stop.go: "should call prestop when killing a pod" +test/e2e/scheduling/predicates.go: "validates resource limits of pods that are allowed to run" +test/e2e/scheduling/predicates.go: "validates that NodeSelector is respected if not matching" +test/e2e/scheduling/predicates.go: "validates that NodeSelector is respected if matching" test/e2e_node/kubelet_test.go: "it should print the output to logs" test/e2e_node/kubelet_test.go: "it should not write to root filesystem" test/e2e_node/lifecycle_hook_test.go: "should execute poststart exec hook properly" diff --git a/vendor/k8s.io/kubernetes/test/conformance/walk.go b/vendor/k8s.io/kubernetes/test/conformance/walk.go index a4bd553ce..0cabab981 100644 --- a/vendor/k8s.io/kubernetes/test/conformance/walk.go +++ b/vendor/k8s.io/kubernetes/test/conformance/walk.go @@ -176,10 +176,11 @@ func (v *visitor) emit(arg ast.Expr) { return } + at.Value = normalizeTestName(at.Value) if *confDoc { v.convertToConformanceData(at) } else { - fmt.Printf("%s: %s\n", v.FileSet.Position(at.Pos()).Filename, at.Value) + fmt.Printf("%s: %q\n", v.FileSet.Position(at.Pos()).Filename, at.Value) } default: v.failf(at, "framework.ConformanceIt() called with non-literal argument") @@ -197,6 +198,18 @@ func (v *visitor) getDescription(value string) string { " " + strings.Trim(value, "\"") } +var ( + regexTag = regexp.MustCompile(`(\[[a-zA-Z0-9:-]+\])`) +) + +// normalizeTestName removes tags (e.g., [Feature:Foo]), double quotes and trim +// the spaces to normalize the test name. +func normalizeTestName(s string) string { + r := regexTag.ReplaceAllString(s, "") + r = strings.Trim(r, "\"") + return strings.TrimSpace(r) +} + // funcName converts a selectorExpr with two idents into a string, // x.y -> "x.y" func funcName(n ast.Expr) string { diff --git a/vendor/k8s.io/kubernetes/test/conformance/walk_test.go b/vendor/k8s.io/kubernetes/test/conformance/walk_test.go index 8fcb8c4a1..c4052b8e5 100644 --- a/vendor/k8s.io/kubernetes/test/conformance/walk_test.go +++ b/vendor/k8s.io/kubernetes/test/conformance/walk_test.go @@ -93,3 +93,25 @@ func TestConformance(t *testing.T) { } } } + +func TestNormalizeTestNames(t *testing.T) { + testCases := []struct { + rawName string + normalizedName string + }{ + { + "should have monotonically increasing restart count [Slow]", + "should have monotonically increasing restart count", + }, + { + " should check is all data is printed ", + "should check is all data is printed", + }, + } + for i, tc := range testCases { + actualName := normalizeTestName(tc.rawName) + if actualName != tc.normalizedName { + t.Errorf("test case[%d]: expected normalized name %q, got %q", i, tc.normalizedName, actualName) + } + } +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/BUILD b/vendor/k8s.io/kubernetes/test/e2e/BUILD index fef30f75d..54f0bcb81 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/BUILD @@ -42,7 +42,6 @@ go_library( ], importpath = "k8s.io/kubernetes/test/e2e", deps = [ - "//pkg/api/testapi:go_default_library", "//pkg/api/v1/pod:go_default_library", "//pkg/cloudprovider/providers/azure:go_default_library", "//pkg/cloudprovider/providers/gce:go_default_library", @@ -70,6 +69,7 @@ go_library( "//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/logs:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/plugin/pkg/client/auth:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/BUILD b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/BUILD index cbbf6662b..dedd9067d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/BUILD @@ -11,6 +11,7 @@ go_library( "aggregator.go", "certs.go", "chunking.go", + "crd_watch.go", "custom_resource_definition.go", "etcd_failure.go", "framework.go", @@ -19,12 +20,12 @@ go_library( "initializers.go", "namespace.go", "table_conversion.go", + "watch.go", "webhook.go", ], importpath = "k8s.io/kubernetes/test/e2e/apimachinery", deps = [ "//pkg/api/v1/pod:go_default_library", - "//pkg/apis/core:go_default_library", "//pkg/apis/rbac:go_default_library", "//pkg/printers:go_default_library", "//pkg/util/version:go_default_library", @@ -38,6 +39,7 @@ go_library( "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/authorization/v1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/api/batch/v1beta1:go_default_library", @@ -47,7 +49,9 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/test/integration/testserver:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", @@ -55,6 +59,7 @@ go_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/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/aggregator.go b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/aggregator.go index 1f9a587b8..9b08fcbdc 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/aggregator.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/aggregator.go @@ -24,8 +24,8 @@ import ( "strings" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -87,7 +87,7 @@ func cleanTest(client clientset.Interface, aggrclient *aggregatorclient.Clientse // delete the APIService first to avoid causing discovery errors _ = aggrclient.ApiregistrationV1beta1().APIServices().Delete("v1alpha1.wardle.k8s.io", nil) - _ = client.ExtensionsV1beta1().Deployments(namespace).Delete("sample-apiserver", nil) + _ = client.AppsV1().Deployments(namespace).Delete("sample-apiserver", nil) _ = client.CoreV1().Secrets(namespace).Delete("sample-apiserver-secret", nil) _ = client.CoreV1().Services(namespace).Delete("sample-api", nil) _ = client.CoreV1().ServiceAccounts(namespace).Delete("sample-apiserver", nil) @@ -133,7 +133,7 @@ func TestSampleAPIServer(f *framework.Framework, image string) { // kubectl create -f deploy.yaml deploymentName := "sample-apiserver-deployment" - etcdImage := "quay.io/coreos/etcd:v3.1.12" + etcdImage := "quay.io/coreos/etcd:v3.2.18" podLabels := map[string]string{"app": "sample-apiserver", "apiserver": "true"} replicas := int32(1) zero := int64(0) @@ -171,14 +171,18 @@ func TestSampleAPIServer(f *framework.Framework, image string) { Image: etcdImage, }, } - d := &extensions.Deployment{ + d := &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Name: deploymentName, + Name: deploymentName, + Labels: podLabels, }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: &replicas, - Strategy: extensions.DeploymentStrategy{ - Type: extensions.RollingUpdateDeploymentStrategyType, + Selector: &metav1.LabelSelector{ + MatchLabels: podLabels, + }, + Strategy: apps.DeploymentStrategy{ + Type: apps.RollingUpdateDeploymentStrategyType, }, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ @@ -192,7 +196,7 @@ func TestSampleAPIServer(f *framework.Framework, image string) { }, }, } - deployment, err := client.ExtensionsV1beta1().Deployments(namespace).Create(d) + deployment, err := client.AppsV1().Deployments(namespace).Create(d) framework.ExpectNoError(err, "creating deployment %s in namespace %s", deploymentName, namespace) err = framework.WaitForDeploymentRevisionAndImage(client, namespace, deploymentName, "1", image) framework.ExpectNoError(err, "waiting for the deployment of image %s in %s in %s to complete", image, deploymentName, namespace) @@ -315,7 +319,16 @@ func TestSampleAPIServer(f *framework.Framework, image string) { }) framework.ExpectNoError(err, "creating apiservice %s with namespace %s", "v1alpha1.wardle.k8s.io", namespace) - err = wait.Poll(100*time.Millisecond, 30*time.Second, func() (bool, error) { + var ( + currentAPIService *apiregistrationv1beta1.APIService + currentPods *v1.PodList + ) + + err = pollTimed(100*time.Millisecond, 60*time.Second, func() (bool, error) { + + currentAPIService, _ = aggrclient.ApiregistrationV1beta1().APIServices().Get("v1alpha1.wardle.k8s.io", metav1.GetOptions{}) + currentPods, _ = client.CoreV1().Pods(namespace).List(metav1.ListOptions{}) + request := restClient.Get().AbsPath("/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders") request.SetHeader("Accept", "application/json") _, err := request.DoRaw() @@ -333,7 +346,23 @@ func TestSampleAPIServer(f *framework.Framework, image string) { return false, err } return true, nil - }) + }, "Waited %s for the sample-apiserver to be ready to handle requests.") + if err != nil { + currentAPIServiceJSON, _ := json.Marshal(currentAPIService) + framework.Logf("current APIService: %s", string(currentAPIServiceJSON)) + + currentPodsJSON, _ := json.Marshal(currentPods) + framework.Logf("current pods: %s", string(currentPodsJSON)) + + if currentPods != nil { + for _, pod := range currentPods.Items { + for _, container := range pod.Spec.Containers { + logs, err := framework.GetPodLogs(client, namespace, pod.Name, container.Name) + framework.Logf("logs of %s/%s (error: %v): %s", pod.Name, container.Name, err, logs) + } + } + } + } framework.ExpectNoError(err, "gave up waiting for apiservice wardle to come up successfully") flunderName := generateFlunderName("rest-flunder") @@ -382,19 +411,15 @@ func TestSampleAPIServer(f *framework.Framework, image string) { flunderName = generateFlunderName("dynamic-flunder") // Rerun the Create/List/Delete tests using the Dynamic client. - resources, err := client.Discovery().ServerPreferredNamespacedResources() - framework.ExpectNoError(err, "getting server preferred namespaces resources for dynamic client") + resources, discoveryErr := client.Discovery().ServerPreferredNamespacedResources() groupVersionResources, err := discovery.GroupVersionResources(resources) framework.ExpectNoError(err, "getting group version resources for dynamic client") gvr := schema.GroupVersionResource{Group: "wardle.k8s.io", Version: "v1alpha1", Resource: "flunders"} _, ok := groupVersionResources[gvr] if !ok { - framework.Failf("could not find group version resource for dynamic client and wardle/flunders.") + framework.Failf("could not find group version resource for dynamic client and wardle/flunders (discovery error: %v, discovery results: %#v)", discoveryErr, groupVersionResources) } - clientPool := f.ClientPool - dynamicClient, err := clientPool.ClientForGroupVersionResource(gvr) - framework.ExpectNoError(err, "getting group version resources for dynamic client") - apiResource := metav1.APIResource{Name: gvr.Resource, Namespaced: true} + dynamicClient := f.DynamicClient.Resource(gvr).Namespace(namespace) // kubectl create -f flunders-1.yaml // Request Body: {"apiVersion":"wardle.k8s.io/v1alpha1","kind":"Flunder","metadata":{"labels":{"sample-label":"true"},"name":"test-flunder","namespace":"default"}} @@ -411,27 +436,23 @@ func TestSampleAPIServer(f *framework.Framework, image string) { unstruct := &unstructuredv1.Unstructured{} err = unstruct.UnmarshalJSON(jsonFlunder) framework.ExpectNoError(err, "unmarshalling test-flunder as unstructured for create using dynamic client") - unstruct, err = dynamicClient.Resource(&apiResource, namespace).Create(unstruct) + unstruct, err = dynamicClient.Create(unstruct) framework.ExpectNoError(err, "listing flunders using dynamic client") // kubectl get flunders - obj, err := dynamicClient.Resource(&apiResource, namespace).List(metav1.ListOptions{}) + unstructuredList, err := dynamicClient.List(metav1.ListOptions{}) framework.ExpectNoError(err, "listing flunders using dynamic client") - unstructuredList, ok := obj.(*unstructuredv1.UnstructuredList) - validateErrorWithDebugInfo(f, err, pods, "casting flunders list(%T) as unstructuredList using dynamic client", obj) if len(unstructuredList.Items) != 1 { framework.Failf("failed to get back the correct flunders list %v from the dynamic client", unstructuredList) } // kubectl delete flunder test-flunder - err = dynamicClient.Resource(&apiResource, namespace).Delete(flunderName, &metav1.DeleteOptions{}) + err = dynamicClient.Delete(flunderName, &metav1.DeleteOptions{}) validateErrorWithDebugInfo(f, err, pods, "deleting flunders(%v) using dynamic client", unstructuredList.Items) // kubectl get flunders - obj, err = dynamicClient.Resource(&apiResource, namespace).List(metav1.ListOptions{}) + unstructuredList, err = dynamicClient.List(metav1.ListOptions{}) framework.ExpectNoError(err, "listing flunders using dynamic client") - unstructuredList, ok = obj.(*unstructuredv1.UnstructuredList) - validateErrorWithDebugInfo(f, err, pods, "casting flunders list(%T) as unstructuredList using dynamic client", obj) if len(unstructuredList.Items) != 0 { framework.Failf("failed to get back the correct deleted flunders list %v from the dynamic client", unstructuredList) } @@ -439,6 +460,17 @@ func TestSampleAPIServer(f *framework.Framework, image string) { cleanTest(client, aggrclient, namespace) } +// pollTimed will call Poll but time how long Poll actually took. +// It will then framework.logf the msg with the duration of the Poll. +// It is assumed that msg will contain one %s for the elapsed time. +func pollTimed(interval, timeout time.Duration, condition wait.ConditionFunc, msg string) error { + defer func(start time.Time, msg string) { + elapsed := time.Since(start) + framework.Logf(msg, elapsed) + }(time.Now(), msg) + return wait.Poll(interval, timeout, condition) +} + func validateErrorWithDebugInfo(f *framework.Framework, err error, pods *v1.PodList, msg string, fields ...interface{}) { if err != nil { namespace := f.Namespace.Name diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/crd_watch.go b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/crd_watch.go new file mode 100644 index 000000000..1f0ea85e3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/crd_watch.go @@ -0,0 +1,166 @@ +/* +Copyright 2018 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 apimachinery + +import ( + "fmt" + + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apiextensions-apiserver/test/integration/testserver" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/dynamic" + "k8s.io/kubernetes/test/e2e/framework" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = SIGDescribe("CustomResourceDefinition Watch", func() { + + f := framework.NewDefaultFramework("crd-watch") + + Context("CustomResourceDefinition Watch", func() { + /* + Testname: crd-watch + Description: Create a Custom Resource Definition and make sure + watches observe events on create/delete. + */ + It("watch on custom resource definition objects", func() { + + framework.SkipUnlessServerVersionGTE(crdVersion, f.ClientSet.Discovery()) + + const ( + watchCRNameA = "name1" + watchCRNameB = "name2" + ) + + config, err := framework.LoadConfig() + if err != nil { + framework.Failf("failed to load config: %v", err) + } + + apiExtensionClient, err := clientset.NewForConfig(config) + if err != nil { + framework.Failf("failed to initialize apiExtensionClient: %v", err) + } + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) + noxuDefinition, err = testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, f.DynamicClient) + if err != nil { + framework.Failf("failed to create CustomResourceDefinition: %v", err) + } + + defer func() { + err = testserver.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient) + if err != nil { + framework.Failf("failed to delete CustomResourceDefinition: %v", err) + } + }() + + ns := "" + noxuResourceClient := newNamespacedCustomResourceClient(ns, f.DynamicClient, noxuDefinition) + + watchA, err := watchCRWithName(noxuResourceClient, watchCRNameA) + Expect(err).NotTo(HaveOccurred()) + + watchB, err := watchCRWithName(noxuResourceClient, watchCRNameB) + Expect(err).NotTo(HaveOccurred()) + + testCrA := testserver.NewNoxuInstance(ns, watchCRNameA) + testCrB := testserver.NewNoxuInstance(ns, watchCRNameB) + + By("Creating first CR ") + testCrA, err = instantiateCustomResource(testCrA, noxuResourceClient, noxuDefinition) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchA, watch.Added, testCrA) + expectNoEvent(watchB, watch.Added, testCrA) + + By("Creating second CR") + testCrB, err = instantiateCustomResource(testCrB, noxuResourceClient, noxuDefinition) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchB, watch.Added, testCrB) + expectNoEvent(watchA, watch.Added, testCrB) + + By("Deleting first CR") + err = deleteCustomResource(noxuResourceClient, watchCRNameA) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchA, watch.Deleted, nil) + expectNoEvent(watchB, watch.Deleted, nil) + + By("Deleting second CR") + err = deleteCustomResource(noxuResourceClient, watchCRNameB) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchB, watch.Deleted, nil) + expectNoEvent(watchA, watch.Deleted, nil) + }) + }) +}) + +func watchCRWithName(crdResourceClient dynamic.ResourceInterface, name string) (watch.Interface, error) { + return crdResourceClient.Watch( + metav1.ListOptions{ + FieldSelector: "metadata.name=" + name, + TimeoutSeconds: int64ptr(600), + }, + ) +} + +func instantiateCustomResource(instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) { + createdInstance, err := client.Create(instanceToCreate) + if err != nil { + return nil, err + } + createdObjectMeta, err := meta.Accessor(createdInstance) + if err != nil { + return nil, err + } + // it should have a UUID + if len(createdObjectMeta.GetUID()) == 0 { + return nil, fmt.Errorf("missing uuid: %#v", createdInstance) + } + createdTypeMeta, err := meta.TypeAccessor(createdInstance) + if err != nil { + return nil, err + } + if e, a := definition.Spec.Group+"/"+definition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a { + return nil, fmt.Errorf("expected %v, got %v", e, a) + } + if e, a := definition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { + return nil, fmt.Errorf("expected %v, got %v", e, a) + } + return createdInstance, nil +} + +func deleteCustomResource(client dynamic.ResourceInterface, name string) error { + return client.Delete(name, &metav1.DeleteOptions{}) +} + +func newNamespacedCustomResourceClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { + gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural} + + if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { + return client.Resource(gvr).Namespace(ns) + } else { + return client.Resource(gvr) + } + +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/custom_resource_definition.go b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/custom_resource_definition.go index a7c963a23..18f19b684 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/custom_resource_definition.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/custom_resource_definition.go @@ -55,7 +55,7 @@ var _ = SIGDescribe("CustomResourceDefinition resources", func() { randomDefinition := testserver.NewRandomNameCustomResourceDefinition(v1beta1.ClusterScoped) //create CRD and waits for the resource to be recognized and available. - _, err = testserver.CreateNewCustomResourceDefinition(randomDefinition, apiExtensionClient, f.ClientPool) + randomDefinition, err = testserver.CreateNewCustomResourceDefinition(randomDefinition, apiExtensionClient, f.DynamicClient) if err != nil { framework.Failf("failed to create CustomResourceDefinition: %v", err) } diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/etcd_failure.go b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/etcd_failure.go index 1d035297b..4f1d9c4c0 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/etcd_failure.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/etcd_failure.go @@ -26,6 +26,7 @@ import ( "k8s.io/kubernetes/test/e2e/apps" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -47,7 +48,7 @@ var _ = SIGDescribe("Etcd failure [Disruptive]", func() { Client: f.ClientSet, Name: "baz", Namespace: f.Namespace.Name, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: 1, })).NotTo(HaveOccurred()) }) diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/garbage_collector.go b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/garbage_collector.go index 70b06cfbe..9bb8d0a38 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/garbage_collector.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/garbage_collector.go @@ -18,6 +18,7 @@ package apimachinery import ( "fmt" + "sync/atomic" "time" batchv1 "k8s.io/api/batch/v1" @@ -32,10 +33,10 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/storage/names" clientset "k8s.io/client-go/kubernetes" - api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework/metrics" @@ -88,8 +89,8 @@ func getOrphanOptions() *metav1.DeleteOptions { } var ( - zero = int64(0) - + zero = int64(0) + lablecount = int64(0) CronJobGroupVersionResource = schema.GroupVersionResource{Group: batchv1beta1.GroupName, Version: "v1beta1", Resource: "cronjobs"} ) @@ -175,7 +176,7 @@ func verifyRemainingDeploymentsReplicaSetsPods( } if len(deployments.Items) != deploymentNum { ret = false - By(fmt.Sprintf("expected %d Deploymentss, got %d Deployments", deploymentNum, len(deployments.Items))) + By(fmt.Sprintf("expected %d Deployments, got %d Deployments", deploymentNum, len(deployments.Items))) } pods, err := clientSet.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{}) if err != nil { @@ -323,6 +324,14 @@ func newCronJob(name, schedule string) *batchv1beta1.CronJob { } } +// getUniqLabel returns a UniqLabel based on labeLkey and labelvalue. +func getUniqLabel(labelkey, labelvalue string) map[string]string { + count := atomic.AddInt64(&lablecount, 1) + uniqlabelkey := fmt.Sprintf("%s-%05d", labelkey, count) + uniqlabelvalue := fmt.Sprintf("%s-%05d", labelvalue, count) + return map[string]string{uniqlabelkey: uniqlabelvalue} +} + var _ = SIGDescribe("Garbage collector", func() { f := framework.NewDefaultFramework("gc") @@ -337,8 +346,7 @@ var _ = SIGDescribe("Garbage collector", func() { rcClient := clientSet.CoreV1().ReplicationControllers(f.Namespace.Name) podClient := clientSet.CoreV1().Pods(f.Namespace.Name) rcName := "simpletest.rc" - // TODO: find better way to keep this label unique in the test - uniqLabels := map[string]string{"gctest": "delete_pods"} + uniqLabels := getUniqLabel("gctest", "delete_pods") rc := newOwnerRC(f, rcName, 2, uniqLabels) By("create the rc") rc, err := rcClient.Create(rc) @@ -396,8 +404,7 @@ var _ = SIGDescribe("Garbage collector", func() { rcClient := clientSet.CoreV1().ReplicationControllers(f.Namespace.Name) podClient := clientSet.CoreV1().Pods(f.Namespace.Name) rcName := "simpletest.rc" - // TODO: find better way to keep this label unique in the test - uniqLabels := map[string]string{"gctest": "orphan_pods"} + uniqLabels := getUniqLabel("gctest", "orphan_pods") rc := newOwnerRC(f, rcName, estimateMaximumPods(clientSet, 10, 100), uniqLabels) By("create the rc") rc, err := rcClient.Create(rc) @@ -445,17 +452,13 @@ var _ = SIGDescribe("Garbage collector", func() { framework.Failf("%v", err) } By("wait for 30 seconds to see if the garbage collector mistakenly deletes the pods") - if err := wait.Poll(5*time.Second, 30*time.Second, func() (bool, error) { - pods, err := podClient.List(metav1.ListOptions{}) - if err != nil { - return false, fmt.Errorf("Failed to list pods: %v", err) - } - if e, a := int(*(rc.Spec.Replicas)), len(pods.Items); e != a { - return false, fmt.Errorf("expect %d pods, got %d pods", e, a) - } - return false, nil - }); err != nil && err != wait.ErrWaitTimeout { - framework.Failf("%v", err) + time.Sleep(30 * time.Second) + pods, err := podClient.List(metav1.ListOptions{}) + if err != nil { + framework.Failf("Failed to list pods: %v", err) + } + if e, a := int(*(rc.Spec.Replicas)), len(pods.Items); e != a { + framework.Failf("expect %d pods, got %d pods", e, a) } gatherMetrics(f) }) @@ -465,8 +468,7 @@ var _ = SIGDescribe("Garbage collector", func() { rcClient := clientSet.CoreV1().ReplicationControllers(f.Namespace.Name) podClient := clientSet.CoreV1().Pods(f.Namespace.Name) rcName := "simpletest.rc" - // TODO: find better way to keep this label unique in the test - uniqLabels := map[string]string{"gctest": "orphan_pods_nil_option"} + uniqLabels := getUniqLabel("gctest", "orphan_pods_nil_option") rc := newOwnerRC(f, rcName, 2, uniqLabels) By("create the rc") rc, err := rcClient.Create(rc) @@ -494,17 +496,13 @@ var _ = SIGDescribe("Garbage collector", func() { framework.Failf("failed to delete the rc: %v", err) } By("wait for 30 seconds to see if the garbage collector mistakenly deletes the pods") - if err := wait.Poll(5*time.Second, 30*time.Second, func() (bool, error) { - pods, err := podClient.List(metav1.ListOptions{}) - if err != nil { - return false, fmt.Errorf("Failed to list pods: %v", err) - } - if e, a := int(*(rc.Spec.Replicas)), len(pods.Items); e != a { - return false, fmt.Errorf("expect %d pods, got %d pods", e, a) - } - return false, nil - }); err != nil && err != wait.ErrWaitTimeout { - framework.Failf("%v", err) + time.Sleep(30 * time.Second) + pods, err := podClient.List(metav1.ListOptions{}) + if err != nil { + framework.Failf("Failed to list pods: %v", err) + } + if e, a := int(*(rc.Spec.Replicas)), len(pods.Items); e != a { + framework.Failf("expect %d pods, got %d pods", e, a) } gatherMetrics(f) }) @@ -520,8 +518,7 @@ var _ = SIGDescribe("Garbage collector", func() { deployClient := clientSet.ExtensionsV1beta1().Deployments(f.Namespace.Name) rsClient := clientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name) deploymentName := "simpletest.deployment" - // TODO: find better way to keep this label unique in the test - uniqLabels := map[string]string{"gctest": "delete_rs"} + uniqLabels := getUniqLabel("gctest", "delete_rs") deployment := newOwnerDeployment(f, deploymentName, uniqLabels) By("create the deployment") createdDeployment, err := deployClient.Create(deployment) @@ -552,14 +549,17 @@ var _ = SIGDescribe("Garbage collector", func() { err = wait.PollImmediate(500*time.Millisecond, 1*time.Minute, func() (bool, error) { return verifyRemainingDeploymentsReplicaSetsPods(f, clientSet, deployment, 0, 0, 0) }) - if err == wait.ErrWaitTimeout { - err = fmt.Errorf("Failed to wait for all rs to be garbage collected: %v", err) + if err != nil { + errList := make([]error, 0) + errList = append(errList, err) remainingRSs, err := rsClient.List(metav1.ListOptions{}) if err != nil { - framework.Failf("failed to list RSs post mortem: %v", err) + errList = append(errList, fmt.Errorf("failed to list RSs post mortem: %v", err)) } else { - framework.Failf("remaining rs are: %#v", remainingRSs) + errList = append(errList, fmt.Errorf("remaining rs are: %#v", remainingRSs)) } + aggregatedError := utilerrors.NewAggregate(errList) + framework.Failf("Failed to wait for all rs to be garbage collected: %v", aggregatedError) } @@ -577,8 +577,7 @@ var _ = SIGDescribe("Garbage collector", func() { deployClient := clientSet.ExtensionsV1beta1().Deployments(f.Namespace.Name) rsClient := clientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name) deploymentName := "simpletest.deployment" - // TODO: find better way to keep this label unique in the test - uniqLabels := map[string]string{"gctest": "orphan_rs"} + uniqLabels := getUniqLabel("gctest", "orphan_rs") deployment := newOwnerDeployment(f, deploymentName, uniqLabels) By("create the deployment") createdDeployment, err := deployClient.Create(deployment) @@ -605,24 +604,28 @@ var _ = SIGDescribe("Garbage collector", func() { if err := deployClient.Delete(deployment.ObjectMeta.Name, deleteOptions); err != nil { framework.Failf("failed to delete the deployment: %v", err) } - By("wait for 2 Minute to see if the garbage collector mistakenly deletes the rs") - err = wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) { - return verifyRemainingDeploymentsReplicaSetsPods(f, clientSet, deployment, 0, 1, 2) - }) + By("wait for 30 seconds to see if the garbage collector mistakenly deletes the rs") + time.Sleep(30 * time.Second) + ok, err := verifyRemainingDeploymentsReplicaSetsPods(f, clientSet, deployment, 0, 1, 2) if err != nil { - err = fmt.Errorf("Failed to wait to see if the garbage collecter mistakenly deletes the rs: %v", err) + framework.Failf("Unexpected error while verifying remaining deployments, rs, and pods: %v", err) + } + if !ok { + errList := make([]error, 0) remainingRSs, err := rsClient.List(metav1.ListOptions{}) if err != nil { - framework.Failf("failed to list RSs post mortem: %v", err) + errList = append(errList, fmt.Errorf("failed to list RSs post mortem: %v", err)) } else { - framework.Failf("remaining rs post mortem: %#v", remainingRSs) + errList = append(errList, fmt.Errorf("remaining rs post mortem: %#v", remainingRSs)) } remainingDSs, err := deployClient.List(metav1.ListOptions{}) if err != nil { - framework.Failf("failed to list Deployments post mortem: %v", err) + errList = append(errList, fmt.Errorf("failed to list Deployments post mortem: %v", err)) } else { - framework.Failf("remaining deployment's post mortem: %#v", remainingDSs) + errList = append(errList, fmt.Errorf("remaining deployment's post mortem: %#v", remainingDSs)) } + aggregatedError := utilerrors.NewAggregate(errList) + framework.Failf("Failed to verify remaining deployments, rs, and pods: %v", aggregatedError) } rs, err := clientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name).List(metav1.ListOptions{}) if err != nil { @@ -647,8 +650,7 @@ var _ = SIGDescribe("Garbage collector", func() { rcClient := clientSet.CoreV1().ReplicationControllers(f.Namespace.Name) podClient := clientSet.CoreV1().Pods(f.Namespace.Name) rcName := "simpletest.rc" - // TODO: find better way to keep this label unique in the test - uniqLabels := map[string]string{"gctest": "delete_pods_foreground"} + uniqLabels := getUniqLabel("gctest", "delete_pods_foreground") rc := newOwnerRC(f, rcName, estimateMaximumPods(clientSet, 10, 100), uniqLabels) By("create the rc") rc, err := rcClient.Create(rc) @@ -738,18 +740,16 @@ var _ = SIGDescribe("Garbage collector", func() { rc1Name := "simpletest-rc-to-be-deleted" replicas := int32(estimateMaximumPods(clientSet, 10, 100)) halfReplicas := int(replicas / 2) - // TODO: find better way to keep this label unique in the test - uniqLabels := map[string]string{"gctest": "valid_and_pending_owners"} - rc1 := newOwnerRC(f, rc1Name, replicas, uniqLabels) + uniqLabels_deleted := getUniqLabel("gctest_d", "valid_and_pending_owners_d") + rc1 := newOwnerRC(f, rc1Name, replicas, uniqLabels_deleted) By("create the rc1") rc1, err := rcClient.Create(rc1) if err != nil { framework.Failf("Failed to create replication controller: %v", err) } rc2Name := "simpletest-rc-to-stay" - // TODO: find better way to keep this label unique in the test - uniqLabels = map[string]string{"another.key": "another.value"} - rc2 := newOwnerRC(f, rc2Name, 0, uniqLabels) + uniqLabels_stay := getUniqLabel("gctest_s", "valid_and_pending_owners_s") + rc2 := newOwnerRC(f, rc2Name, 0, uniqLabels_stay) By("create the rc2") rc2, err = rcClient.Create(rc2) if err != nil { @@ -917,16 +917,15 @@ var _ = SIGDescribe("Garbage collector", func() { framework.Failf("failed to delete CustomResourceDefinition: %v", err) } }() - client, err := apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, f.ClientPool) + definition, err = apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, f.DynamicClient) if err != nil { framework.Failf("failed to create CustomResourceDefinition: %v", err) } // Get a client for the custom resource. - resourceClient := client.Resource(&metav1.APIResource{ - Name: definition.Spec.Names.Plural, - Namespaced: false, - }, api.NamespaceNone) + gvr := schema.GroupVersionResource{Group: definition.Spec.Group, Version: definition.Spec.Version, Resource: definition.Spec.Names.Plural} + resourceClient := f.DynamicClient.Resource(gvr) + apiVersion := definition.Spec.Group + "/" + definition.Spec.Version // Create a custom owner resource. @@ -999,8 +998,111 @@ var _ = SIGDescribe("Garbage collector", func() { } }) + It("should support orphan deletion of custom resources", func() { + config, err := framework.LoadConfig() + if err != nil { + framework.Failf("failed to load config: %v", err) + } + + apiExtensionClient, err := apiextensionsclientset.NewForConfig(config) + if err != nil { + framework.Failf("failed to initialize apiExtensionClient: %v", err) + } + + // Create a random custom resource definition and ensure it's available for + // use. + definition := apiextensionstestserver.NewRandomNameCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) + defer func() { + err = apiextensionstestserver.DeleteCustomResourceDefinition(definition, apiExtensionClient) + if err != nil && !errors.IsNotFound(err) { + framework.Failf("failed to delete CustomResourceDefinition: %v", err) + } + }() + definition, err = apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, f.DynamicClient) + if err != nil { + framework.Failf("failed to create CustomResourceDefinition: %v", err) + } + + // Get a client for the custom resource. + gvr := schema.GroupVersionResource{Group: definition.Spec.Group, Version: definition.Spec.Version, Resource: definition.Spec.Names.Plural} + resourceClient := f.DynamicClient.Resource(gvr) + + apiVersion := definition.Spec.Group + "/" + definition.Spec.Version + + // Create a custom owner resource. + ownerName := names.SimpleNameGenerator.GenerateName("owner") + owner := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": apiVersion, + "kind": definition.Spec.Names.Kind, + "metadata": map[string]interface{}{ + "name": ownerName, + }, + }, + } + persistedOwner, err := resourceClient.Create(owner) + if err != nil { + framework.Failf("failed to create owner resource %q: %v", ownerName, err) + } + framework.Logf("created owner resource %q", ownerName) + + // Create a custom dependent resource. + dependentName := names.SimpleNameGenerator.GenerateName("dependent") + dependent := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": apiVersion, + "kind": definition.Spec.Names.Kind, + "metadata": map[string]interface{}{ + "name": dependentName, + "ownerReferences": []map[string]string{ + { + "uid": string(persistedOwner.GetUID()), + "apiVersion": apiVersion, + "kind": definition.Spec.Names.Kind, + "name": ownerName, + }, + }, + }, + }, + } + _, err = resourceClient.Create(dependent) + if err != nil { + framework.Failf("failed to create dependent resource %q: %v", dependentName, err) + } + framework.Logf("created dependent resource %q", dependentName) + + // Delete the owner and orphan the dependent. + err = resourceClient.Delete(ownerName, getOrphanOptions()) + if err != nil { + framework.Failf("failed to delete owner resource %q: %v", ownerName, err) + } + + By("wait for the owner to be deleted") + if err := wait.Poll(5*time.Second, 120*time.Second, func() (bool, error) { + _, err = resourceClient.Get(ownerName, metav1.GetOptions{}) + if err == nil { + return false, nil + } + if err != nil && !errors.IsNotFound(err) { + return false, fmt.Errorf("Failed to get owner: %v", err) + } + return true, nil + }); err != nil { + framework.Failf("timeout in waiting for the owner to be deleted: %v", err) + } + + // Wait 30s and ensure the dependent is not deleted. + By("wait for 30 seconds to see if the garbage collector mistakenly deletes the dependent crd") + if err := wait.Poll(5*time.Second, 30*time.Second, func() (bool, error) { + _, err := resourceClient.Get(dependentName, metav1.GetOptions{}) + return false, err + }); err != nil && err != wait.ErrWaitTimeout { + framework.Failf("failed to ensure the dependent is not deleted: %v", err) + } + }) + It("should delete jobs and pods created by cronjob", func() { - framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResource, f.Namespace.Name) + framework.SkipIfMissingResource(f.DynamicClient, CronJobGroupVersionResource, f.Namespace.Name) By("Create the cronjob") cronJob := newCronJob("simple", "*/1 * * * ?") diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/generated_clientset.go b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/generated_clientset.go index 0a919d17c..228e9a26b 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/generated_clientset.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/generated_clientset.go @@ -264,7 +264,7 @@ var _ = SIGDescribe("Generated clientset", func() { f := framework.NewDefaultFramework("clientset") BeforeEach(func() { - framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResource, f.Namespace.Name) + framework.SkipIfMissingResource(f.DynamicClient, CronJobGroupVersionResource, f.Namespace.Name) }) It("should create v1beta1 cronJobs, delete cronJobs, watch cronJobs", func() { diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/namespace.go b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/namespace.go index 0542113b7..b7aa78b91 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/namespace.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/namespace.go @@ -29,6 +29,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -114,7 +115,7 @@ func ensurePodsAreRemovedWhenNamespaceIsDeleted(f *framework.Framework) { Containers: []v1.Container{ { Name: "nginx", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), }, }, }, @@ -135,7 +136,7 @@ func ensurePodsAreRemovedWhenNamespaceIsDeleted(f *framework.Framework) { Containers: []v1.Container{ { Name: "nginx", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), }, }, }, diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/watch.go b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/watch.go new file mode 100644 index 000000000..2ca292bda --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/watch.go @@ -0,0 +1,383 @@ +/* +Copyright 2018 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 apimachinery + +import ( + "time" + + "k8s.io/api/core/v1" + apiequality "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/kubernetes/test/e2e/framework" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +const ( + watchConfigMapLabelKey = "watch-this-configmap" + + multipleWatchersLabelValueA = "multiple-watchers-A" + multipleWatchersLabelValueB = "multiple-watchers-B" + fromResourceVersionLabelValue = "from-resource-version" + watchRestartedLabelValue = "watch-closed-and-restarted" + toBeChangedLabelValue = "label-changed-and-restored" +) + +var _ = SIGDescribe("Watchers", func() { + f := framework.NewDefaultFramework("watch") + + /* + Testname: watch-configmaps-with-multiple-watchers + Description: Ensure that multiple watchers are able to receive all add, + update, and delete notifications on configmaps that match a label selector and do + not receive notifications for configmaps which do not match that label selector. + */ + framework.ConformanceIt("should observe add, update, and delete watch notifications on configmaps", func() { + c := f.ClientSet + ns := f.Namespace.Name + + By("creating a watch on configmaps with label A") + watchA, err := watchConfigMaps(f, "", multipleWatchersLabelValueA) + Expect(err).NotTo(HaveOccurred()) + + By("creating a watch on configmaps with label B") + watchB, err := watchConfigMaps(f, "", multipleWatchersLabelValueB) + Expect(err).NotTo(HaveOccurred()) + + By("creating a watch on configmaps with label A or B") + watchAB, err := watchConfigMaps(f, "", multipleWatchersLabelValueA, multipleWatchersLabelValueB) + Expect(err).NotTo(HaveOccurred()) + + testConfigMapA := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "e2e-watch-test-configmap-a", + Labels: map[string]string{ + watchConfigMapLabelKey: multipleWatchersLabelValueA, + }, + }, + } + testConfigMapB := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "e2e-watch-test-configmap-b", + Labels: map[string]string{ + watchConfigMapLabelKey: multipleWatchersLabelValueB, + }, + }, + } + + By("creating a configmap with label A and ensuring the correct watchers observe the notification") + testConfigMapA, err = c.CoreV1().ConfigMaps(ns).Create(testConfigMapA) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchA, watch.Added, testConfigMapA) + expectEvent(watchAB, watch.Added, testConfigMapA) + expectNoEvent(watchB, watch.Added, testConfigMapA) + + By("modifying configmap A and ensuring the correct watchers observe the notification") + testConfigMapA, err = updateConfigMap(c, ns, testConfigMapA.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "1") + }) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchA, watch.Modified, testConfigMapA) + expectEvent(watchAB, watch.Modified, testConfigMapA) + expectNoEvent(watchB, watch.Modified, testConfigMapA) + + By("modifying configmap A again and ensuring the correct watchers observe the notification") + testConfigMapA, err = updateConfigMap(c, ns, testConfigMapA.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "2") + }) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchA, watch.Modified, testConfigMapA) + expectEvent(watchAB, watch.Modified, testConfigMapA) + expectNoEvent(watchB, watch.Modified, testConfigMapA) + + By("deleting configmap A and ensuring the correct watchers observe the notification") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMapA.GetName(), nil) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchA, watch.Deleted, nil) + expectEvent(watchAB, watch.Deleted, nil) + expectNoEvent(watchB, watch.Deleted, nil) + + By("creating a configmap with label B and ensuring the correct watchers observe the notification") + testConfigMapB, err = c.CoreV1().ConfigMaps(ns).Create(testConfigMapB) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchB, watch.Added, testConfigMapB) + expectEvent(watchAB, watch.Added, testConfigMapB) + expectNoEvent(watchA, watch.Added, testConfigMapB) + + By("deleting configmap B and ensuring the correct watchers observe the notification") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMapB.GetName(), nil) + Expect(err).NotTo(HaveOccurred()) + expectEvent(watchB, watch.Deleted, nil) + expectEvent(watchAB, watch.Deleted, nil) + expectNoEvent(watchA, watch.Deleted, nil) + }) + + /* + Testname: watch-configmaps-from-resource-version + Description: Ensure that a watch can be opened from a particular resource version + in the past and only notifications happening after that resource version are observed. + */ + framework.ConformanceIt("should be able to start watching from a specific resource version", func() { + c := f.ClientSet + ns := f.Namespace.Name + + testConfigMap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "e2e-watch-test-resource-version", + Labels: map[string]string{ + watchConfigMapLabelKey: fromResourceVersionLabelValue, + }, + }, + } + + By("creating a new configmap") + testConfigMap, err := c.CoreV1().ConfigMaps(ns).Create(testConfigMap) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap once") + testConfigMapFirstUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "1") + }) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap a second time") + testConfigMapSecondUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "2") + }) + Expect(err).NotTo(HaveOccurred()) + + By("deleting the configmap") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMap.GetName(), nil) + Expect(err).NotTo(HaveOccurred()) + + By("creating a watch on configmaps from the resource version returned by the first update") + testWatch, err := watchConfigMaps(f, testConfigMapFirstUpdate.ObjectMeta.ResourceVersion, fromResourceVersionLabelValue) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting to observe notifications for all changes to the configmap after the first update") + expectEvent(testWatch, watch.Modified, testConfigMapSecondUpdate) + expectEvent(testWatch, watch.Deleted, nil) + }) + + /* + Testname: watch-configmaps-closed-and-restarted + Description: Ensure that a watch can be reopened from the last resource version + observed by the previous watch, and it will continue delivering notifications from + that point in time. + */ + framework.ConformanceIt("should be able to restart watching from the last resource version observed by the previous watch", func() { + c := f.ClientSet + ns := f.Namespace.Name + + testConfigMap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "e2e-watch-test-watch-closed", + Labels: map[string]string{ + watchConfigMapLabelKey: watchRestartedLabelValue, + }, + }, + } + + By("creating a watch on configmaps") + testWatchBroken, err := watchConfigMaps(f, "", watchRestartedLabelValue) + Expect(err).NotTo(HaveOccurred()) + + By("creating a new configmap") + testConfigMap, err = c.CoreV1().ConfigMaps(ns).Create(testConfigMap) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap once") + _, err = updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "1") + }) + Expect(err).NotTo(HaveOccurred()) + + By("closing the watch once it receives two notifications") + expectEvent(testWatchBroken, watch.Added, testConfigMap) + lastEvent, ok := waitForEvent(testWatchBroken, watch.Modified, nil, 1*time.Minute) + if !ok { + framework.Failf("Timed out waiting for second watch notification") + } + testWatchBroken.Stop() + + By("modifying the configmap a second time, while the watch is closed") + testConfigMapSecondUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "2") + }) + Expect(err).NotTo(HaveOccurred()) + + By("creating a new watch on configmaps from the last resource version observed by the first watch") + lastEventConfigMap, ok := lastEvent.Object.(*v1.ConfigMap) + if !ok { + framework.Failf("Expected last notfication to refer to a configmap but got: %v", lastEvent) + } + testWatchRestarted, err := watchConfigMaps(f, lastEventConfigMap.ObjectMeta.ResourceVersion, watchRestartedLabelValue) + Expect(err).NotTo(HaveOccurred()) + + By("deleting the configmap") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMap.GetName(), nil) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting to observe notifications for all changes to the configmap since the first watch closed") + expectEvent(testWatchRestarted, watch.Modified, testConfigMapSecondUpdate) + expectEvent(testWatchRestarted, watch.Deleted, nil) + }) + + /* + Testname: watch-configmaps-label-changed + Description: Ensure that a watched object stops meeting the requirements of + a watch's selector, the watch will observe a delete, and will not observe + notifications for that object until it meets the selector's requirements again. + */ + framework.ConformanceIt("should observe an object deletion if it stops meeting the requirements of the selector", func() { + c := f.ClientSet + ns := f.Namespace.Name + + testConfigMap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "e2e-watch-test-label-changed", + Labels: map[string]string{ + watchConfigMapLabelKey: toBeChangedLabelValue, + }, + }, + } + + By("creating a watch on configmaps with a certain label") + testWatch, err := watchConfigMaps(f, "", toBeChangedLabelValue) + Expect(err).NotTo(HaveOccurred()) + + By("creating a new configmap") + testConfigMap, err = c.CoreV1().ConfigMaps(ns).Create(testConfigMap) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap once") + testConfigMapFirstUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "1") + }) + Expect(err).NotTo(HaveOccurred()) + + By("changing the label value of the configmap") + _, err = updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + cm.ObjectMeta.Labels[watchConfigMapLabelKey] = "wrong-value" + }) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting to observe a delete notification for the watched object") + expectEvent(testWatch, watch.Added, testConfigMap) + expectEvent(testWatch, watch.Modified, testConfigMapFirstUpdate) + expectEvent(testWatch, watch.Deleted, nil) + + By("modifying the configmap a second time") + testConfigMapSecondUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "2") + }) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting not to observe a notification because the object no longer meets the selector's requirements") + expectNoEvent(testWatch, watch.Modified, testConfigMapSecondUpdate) + + By("changing the label value of the configmap back") + testConfigMapLabelRestored, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + cm.ObjectMeta.Labels[watchConfigMapLabelKey] = toBeChangedLabelValue + }) + Expect(err).NotTo(HaveOccurred()) + + By("modifying the configmap a third time") + testConfigMapThirdUpdate, err := updateConfigMap(c, ns, testConfigMap.GetName(), func(cm *v1.ConfigMap) { + setConfigMapData(cm, "mutation", "3") + }) + Expect(err).NotTo(HaveOccurred()) + + By("deleting the configmap") + err = c.CoreV1().ConfigMaps(ns).Delete(testConfigMap.GetName(), nil) + Expect(err).NotTo(HaveOccurred()) + + By("Expecting to observe an add notification for the watched object when the label value was restored") + expectEvent(testWatch, watch.Added, testConfigMapLabelRestored) + expectEvent(testWatch, watch.Modified, testConfigMapThirdUpdate) + expectEvent(testWatch, watch.Deleted, nil) + }) +}) + +func watchConfigMaps(f *framework.Framework, resourceVersion string, labels ...string) (watch.Interface, error) { + c := f.ClientSet + ns := f.Namespace.Name + opts := metav1.ListOptions{ + ResourceVersion: resourceVersion, + LabelSelector: metav1.FormatLabelSelector(&metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: watchConfigMapLabelKey, + Operator: metav1.LabelSelectorOpIn, + Values: labels, + }, + }, + }), + } + return c.CoreV1().ConfigMaps(ns).Watch(opts) +} + +func int64ptr(i int) *int64 { + i64 := int64(i) + return &i64 +} + +func setConfigMapData(cm *v1.ConfigMap, key, value string) { + if cm.Data == nil { + cm.Data = make(map[string]string) + } + cm.Data[key] = value +} + +func expectEvent(w watch.Interface, eventType watch.EventType, object runtime.Object) { + if event, ok := waitForEvent(w, eventType, object, 1*time.Minute); !ok { + framework.Failf("Timed out waiting for expected watch notification: %v", event) + } +} + +func expectNoEvent(w watch.Interface, eventType watch.EventType, object runtime.Object) { + if event, ok := waitForEvent(w, eventType, object, 10*time.Second); ok { + framework.Failf("Unexpected watch notification observed: %v", event) + } +} + +func waitForEvent(w watch.Interface, expectType watch.EventType, expectObject runtime.Object, duration time.Duration) (watch.Event, bool) { + stopTimer := time.NewTimer(duration) + defer stopTimer.Stop() + for { + select { + case actual, ok := <-w.ResultChan(): + if ok { + framework.Logf("Got : %v %v", actual.Type, actual.Object) + } else { + framework.Failf("Watch closed unexpectedly") + } + if expectType == actual.Type && (expectObject == nil || apiequality.Semantic.DeepEqual(expectObject, actual.Object)) { + return actual, true + } + case <-stopTimer.C: + expected := watch.Event{ + Type: expectType, + Object: expectObject, + } + return expected, false + } + } +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/webhook.go b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/webhook.go index 7ea3b7b4f..17d39a227 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apimachinery/webhook.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apimachinery/webhook.go @@ -23,8 +23,8 @@ import ( "time" "k8s.io/api/admissionregistration/v1beta1" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" crdclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" @@ -263,14 +263,18 @@ func deployWebhookAndService(f *framework.Framework, image string, context *cert Image: image, }, } - d := &extensions.Deployment{ + d := &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Name: deploymentName, + Name: deploymentName, + Labels: podLabels, }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: &replicas, - Strategy: extensions.DeploymentStrategy{ - Type: extensions.RollingUpdateDeploymentStrategyType, + Selector: &metav1.LabelSelector{ + MatchLabels: podLabels, + }, + Strategy: apps.DeploymentStrategy{ + Type: apps.RollingUpdateDeploymentStrategyType, }, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ @@ -284,7 +288,7 @@ func deployWebhookAndService(f *framework.Framework, image string, context *cert }, }, } - deployment, err := client.ExtensionsV1beta1().Deployments(namespace).Create(d) + deployment, err := client.AppsV1().Deployments(namespace).Create(d) framework.ExpectNoError(err, "creating deployment %s in namespace %s", deploymentName, namespace) By("Wait for the deployment to be ready") err = framework.WaitForDeploymentRevisionAndImage(client, namespace, deploymentName, "1", image) @@ -543,7 +547,7 @@ func toBeMutatedPod(f *framework.Framework) *v1.Pod { Containers: []v1.Container{ { Name: "example", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), }, }, }, @@ -572,7 +576,7 @@ func testWebhook(f *framework.Framework) { pod = hangingPod(f) _, err = client.CoreV1().Pods(f.Namespace.Name).Create(pod) Expect(err).NotTo(BeNil()) - expectedTimeoutErr := "request did not complete within allowed duration" + expectedTimeoutErr := "request did not complete within" if !strings.Contains(err.Error(), expectedTimeoutErr) { framework.Failf("expect timeout error %q, got %q", expectedTimeoutErr, err.Error()) } @@ -797,10 +801,11 @@ func testWebhookForWebhookConfigurations(f *framework.Framework) { Name: "should-be-removable-validating-webhook.k8s.io", Rules: []v1beta1.RuleWithOperations{{ Operations: []v1beta1.OperationType{v1beta1.Create}, + // This will not match any real resources so this webhook should never be called. Rule: v1beta1.Rule{ - APIGroups: []string{"*"}, - APIVersions: []string{"*"}, - Resources: []string{"*"}, + APIGroups: []string{""}, + APIVersions: []string{"v1"}, + Resources: []string{"invalid"}, }, }}, ClientConfig: v1beta1.WebhookClientConfig{ @@ -840,10 +845,11 @@ func testWebhookForWebhookConfigurations(f *framework.Framework) { Name: "should-be-removable-mutating-webhook.k8s.io", Rules: []v1beta1.RuleWithOperations{{ Operations: []v1beta1.OperationType{v1beta1.Create}, + // This will not match any real resources so this webhook should never be called. Rule: v1beta1.Rule{ - APIGroups: []string{"*"}, - APIVersions: []string{"*"}, - Resources: []string{"*"}, + APIGroups: []string{""}, + APIVersions: []string{"v1"}, + Resources: []string{"invalid"}, }, }}, ClientConfig: v1beta1.WebhookClientConfig{ @@ -898,7 +904,7 @@ func nonCompliantPod(f *framework.Framework) *v1.Pod { Containers: []v1.Container{ { Name: "webhook-disallow", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), }, }, }, @@ -917,7 +923,7 @@ func hangingPod(f *framework.Framework) *v1.Pod { Containers: []v1.Container{ { Name: "wait-forever", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), }, }, }, @@ -974,7 +980,7 @@ func updateConfigMap(c clientset.Interface, ns, name string, update updateConfig func cleanWebhookTest(client clientset.Interface, namespaceName string) { _ = client.CoreV1().Services(namespaceName).Delete(serviceName, nil) - _ = client.ExtensionsV1beta1().Deployments(namespaceName).Delete(deploymentName, nil) + _ = client.AppsV1().Deployments(namespaceName).Delete(deploymentName, nil) _ = client.CoreV1().Secrets(namespaceName).Delete(secretName, nil) _ = client.RbacV1beta1().RoleBindings("kube-system").Delete(roleBindingName, nil) } diff --git a/vendor/k8s.io/kubernetes/test/e2e/apps/BUILD b/vendor/k8s.io/kubernetes/test/e2e/apps/BUILD index b90b68e24..ad93b6b95 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apps/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/apps/BUILD @@ -25,19 +25,18 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/api/v1/pod:go_default_library", + "//pkg/apis/apps:go_default_library", "//pkg/apis/batch:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/controller/daemon:go_default_library", "//pkg/controller/deployment/util:go_default_library", "//pkg/controller/job:go_default_library", "//pkg/controller/nodelifecycle:go_default_library", "//pkg/controller/replicaset:go_default_library", "//pkg/controller/replication:go_default_library", - "//pkg/kubectl:go_default_library", "//pkg/master/ports:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/util/pointer:go_default_library", "//test/e2e/common:go_default_library", "//test/e2e/framework:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e/apps/cronjob.go b/vendor/k8s.io/kubernetes/test/e2e/apps/cronjob.go index b6c46d520..00c7e81d6 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apps/cronjob.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apps/cronjob.go @@ -33,7 +33,6 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" batchinternal "k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/controller/job" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/test/e2e/framework" ) @@ -51,7 +50,7 @@ var _ = SIGDescribe("CronJob", func() { successCommand := []string{"/bin/true"} BeforeEach(func() { - framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResourceBeta, f.Namespace.Name) + framework.SkipIfMissingResource(f.DynamicClient, CronJobGroupVersionResourceBeta, f.Namespace.Name) }) // multiple jobs running at once @@ -207,11 +206,7 @@ var _ = SIGDescribe("CronJob", func() { By("Deleting the job") job := cronJob.Status.Active[0] - reaper, err := kubectl.ReaperFor(batchinternal.Kind("Job"), f.InternalClientset) - Expect(err).NotTo(HaveOccurred()) - timeout := 1 * time.Minute - err = reaper.Stop(f.Namespace.Name, job.Name, timeout, metav1.NewDeleteOptions(0)) - Expect(err).NotTo(HaveOccurred()) + framework.ExpectNoError(framework.DeleteResourceAndWaitForGC(f.ClientSet, batchinternal.Kind("Job"), f.Namespace.Name, job.Name)) By("Ensuring job was deleted") _, err = framework.GetJob(f.ClientSet, f.Namespace.Name, job.Name) diff --git a/vendor/k8s.io/kubernetes/test/e2e/apps/daemon_restart.go b/vendor/k8s.io/kubernetes/test/e2e/apps/daemon_restart.go index 911f8e41d..dfb2c6a1a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apps/daemon_restart.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apps/daemon_restart.go @@ -34,6 +34,7 @@ import ( "k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -202,7 +203,7 @@ var _ = SIGDescribe("DaemonRestart [Disruptive]", func() { InternalClient: f.InternalClientset, Name: rcName, Namespace: ns, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: numPods, CreatedPods: &[]*v1.Pod{}, } @@ -257,7 +258,7 @@ var _ = SIGDescribe("DaemonRestart [Disruptive]", func() { // that it had the opportunity to create/delete pods, if it were going to do so. Scaling the RC // to the same size achieves this, because the scale operation advances the RC's sequence number // and awaits it to be observed and reported back in the RC's status. - framework.ScaleRC(f.ClientSet, f.InternalClientset, f.ScalesGetter, ns, rcName, numPods, true) + framework.ScaleRC(f.ClientSet, f.ScalesGetter, ns, rcName, numPods, true) // Only check the keys, the pods can be different if the kubelet updated it. // TODO: Can it really? @@ -288,9 +289,9 @@ var _ = SIGDescribe("DaemonRestart [Disruptive]", func() { restarter.kill() // This is best effort to try and create pods while the scheduler is down, // since we don't know exactly when it is restarted after the kill signal. - framework.ExpectNoError(framework.ScaleRC(f.ClientSet, f.InternalClientset, f.ScalesGetter, ns, rcName, numPods+5, false)) + framework.ExpectNoError(framework.ScaleRC(f.ClientSet, f.ScalesGetter, ns, rcName, numPods+5, false)) restarter.waitUp() - framework.ExpectNoError(framework.ScaleRC(f.ClientSet, f.InternalClientset, f.ScalesGetter, ns, rcName, numPods+5, true)) + framework.ExpectNoError(framework.ScaleRC(f.ClientSet, f.ScalesGetter, ns, rcName, numPods+5, true)) }) It("Kubelet should not restart containers across restart", func() { diff --git a/vendor/k8s.io/kubernetes/test/e2e/apps/daemon_set.go b/vendor/k8s.io/kubernetes/test/e2e/apps/daemon_set.go index cfb66c72d..86f5aab8a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apps/daemon_set.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apps/daemon_set.go @@ -36,8 +36,7 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/controller/daemon" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" @@ -69,22 +68,19 @@ var _ = SIGDescribe("Daemon set [Serial]", func() { Expect(err).NotTo(HaveOccurred(), "unable to dump DaemonSets") if daemonsets != nil && len(daemonsets.Items) > 0 { for _, ds := range daemonsets.Items { - By(fmt.Sprintf("Deleting DaemonSet %q with reaper", ds.Name)) - dsReaper, err := kubectl.ReaperFor(extensionsinternal.Kind("DaemonSet"), f.InternalClientset) - Expect(err).NotTo(HaveOccurred()) - err = dsReaper.Stop(f.Namespace.Name, ds.Name, 0, nil) - Expect(err).NotTo(HaveOccurred()) + By(fmt.Sprintf("Deleting DaemonSet %q", ds.Name)) + framework.ExpectNoError(framework.DeleteResourceAndWaitForGC(f.ClientSet, extensionsinternal.Kind("DaemonSet"), f.Namespace.Name, ds.Name)) err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkRunningOnNoNodes(f, &ds)) Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to be reaped") } } if daemonsets, err := f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).List(metav1.ListOptions{}); err == nil { - framework.Logf("daemonset: %s", runtime.EncodeOrDie(legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), daemonsets)) + framework.Logf("daemonset: %s", runtime.EncodeOrDie(legacyscheme.Codecs.LegacyCodec(legacyscheme.Scheme.PrioritizedVersionsAllGroups()...), daemonsets)) } else { framework.Logf("unable to dump daemonsets: %v", err) } if pods, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{}); err == nil { - framework.Logf("pods: %s", runtime.EncodeOrDie(legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), pods)) + framework.Logf("pods: %s", runtime.EncodeOrDie(legacyscheme.Codecs.LegacyCodec(legacyscheme.Scheme.PrioritizedVersionsAllGroups()...), pods)) } else { framework.Logf("unable to dump pods: %v", err) } diff --git a/vendor/k8s.io/kubernetes/test/e2e/apps/deployment.go b/vendor/k8s.io/kubernetes/test/e2e/apps/deployment.go index 76819ee54..d8e89d5cb 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apps/deployment.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apps/deployment.go @@ -25,6 +25,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/errors" @@ -35,10 +36,8 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" clientset "k8s.io/client-go/kubernetes" - extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + appsinternal "k8s.io/kubernetes/pkg/apis/apps" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" - "k8s.io/kubernetes/pkg/kubectl" utilpointer "k8s.io/kubernetes/pkg/util/pointer" "k8s.io/kubernetes/test/e2e/framework" testutil "k8s.io/kubernetes/test/utils" @@ -50,7 +49,7 @@ const ( ) var ( - nilRs *extensions.ReplicaSet + nilRs *apps.ReplicaSet ) var _ = SIGDescribe("Deployment", func() { @@ -100,7 +99,7 @@ var _ = SIGDescribe("Deployment", func() { }) func failureTrap(c clientset.Interface, ns string) { - deployments, err := c.ExtensionsV1beta1().Deployments(ns).List(metav1.ListOptions{LabelSelector: labels.Everything().String()}) + deployments, err := c.AppsV1().Deployments(ns).List(metav1.ListOptions{LabelSelector: labels.Everything().String()}) if err != nil { framework.Logf("Could not list Deployments in namespace %q: %v", ns, err) return @@ -109,7 +108,7 @@ func failureTrap(c clientset.Interface, ns string) { d := deployments.Items[i] framework.Logf(spew.Sprintf("Deployment %q:\n%+v\n", d.Name, d)) - _, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(&d, c.ExtensionsV1beta1()) + _, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(&d, c.AppsV1()) if err != nil { framework.Logf("Could not list ReplicaSets for Deployment %q: %v", d.Name, err) return @@ -126,7 +125,7 @@ func failureTrap(c clientset.Interface, ns string) { return } framework.Logf("Log out all the ReplicaSets if there is no deployment created") - rss, err := c.ExtensionsV1beta1().ReplicaSets(ns).List(metav1.ListOptions{LabelSelector: labels.Everything().String()}) + rss, err := c.AppsV1().ReplicaSets(ns).List(metav1.ListOptions{LabelSelector: labels.Everything().String()}) if err != nil { framework.Logf("Could not list ReplicaSets in namespace %q: %v", ns, err) return @@ -158,27 +157,22 @@ func newDeploymentRollback(name string, annotations map[string]string, revision } } -func stopDeployment(c clientset.Interface, internalClient internalclientset.Interface, ns, deploymentName string) { - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) +func stopDeployment(c clientset.Interface, ns, deploymentName string) { + deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) framework.Logf("Deleting deployment %s", deploymentName) - reaper, err := kubectl.ReaperFor(extensionsinternal.Kind("Deployment"), internalClient) - Expect(err).NotTo(HaveOccurred()) - timeout := 1 * time.Minute - - err = reaper.Stop(ns, deployment.Name, timeout, metav1.NewDeleteOptions(0)) - Expect(err).NotTo(HaveOccurred()) + framework.ExpectNoError(framework.DeleteResourceAndWaitForGC(c, appsinternal.Kind("Deployment"), ns, deployment.Name)) framework.Logf("Ensuring deployment %s was deleted", deploymentName) - _, err = c.ExtensionsV1beta1().Deployments(ns).Get(deployment.Name, metav1.GetOptions{}) + _, err = c.AppsV1().Deployments(ns).Get(deployment.Name, metav1.GetOptions{}) Expect(err).To(HaveOccurred()) Expect(errors.IsNotFound(err)).To(BeTrue()) framework.Logf("Ensuring deployment %s's RSes were deleted", deploymentName) selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector) Expect(err).NotTo(HaveOccurred()) options := metav1.ListOptions{LabelSelector: selector.String()} - rss, err := c.ExtensionsV1beta1().ReplicaSets(ns).List(options) + rss, err := c.AppsV1().ReplicaSets(ns).List(options) Expect(err).NotTo(HaveOccurred()) Expect(rss.Items).Should(HaveLen(0)) framework.Logf("Ensuring deployment %s's Pods were deleted", deploymentName) @@ -201,15 +195,14 @@ func stopDeployment(c clientset.Interface, internalClient internalclientset.Inte func testDeleteDeployment(f *framework.Framework) { ns := f.Namespace.Name c := f.ClientSet - internalClient := f.InternalClientset deploymentName := "test-new-deployment" podLabels := map[string]string{"name": NginxImageName} replicas := int32(1) framework.Logf("Creating simple deployment %s", deploymentName) - d := framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, extensions.RollingUpdateDeploymentStrategyType) + d := framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, apps.RollingUpdateDeploymentStrategyType) d.Annotations = map[string]string{"test": "should-copy-to-replica-set", v1.LastAppliedConfigAnnotation: "should-not-copy-to-replica-set"} - deploy, err := c.ExtensionsV1beta1().Deployments(ns).Create(d) + deploy, err := c.AppsV1().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) // Wait for it to be updated to revision 1 @@ -219,12 +212,12 @@ func testDeleteDeployment(f *framework.Framework) { err = framework.WaitForDeploymentComplete(c, deploy) Expect(err).NotTo(HaveOccurred()) - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) - newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.ExtensionsV1beta1()) + newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.AppsV1()) Expect(err).NotTo(HaveOccurred()) Expect(newRS).NotTo(Equal(nilRs)) - stopDeployment(c, internalClient, ns, deploymentName) + stopDeployment(c, ns, deploymentName) } func testRollingUpdateDeployment(f *framework.Framework) { @@ -245,7 +238,7 @@ func testRollingUpdateDeployment(f *framework.Framework) { rs := newRS(rsName, replicas, rsPodLabels, NginxImageName, NginxImage) rs.Annotations = annotations framework.Logf("Creating replica set %q (going to be adopted)", rs.Name) - _, err := c.ExtensionsV1beta1().ReplicaSets(ns).Create(rs) + _, err := c.AppsV1().ReplicaSets(ns).Create(rs) Expect(err).NotTo(HaveOccurred()) // Verify that the required pods have come up. err = framework.VerifyPodsRunning(c, ns, "sample-pod", false, replicas) @@ -254,8 +247,8 @@ func testRollingUpdateDeployment(f *framework.Framework) { // Create a deployment to delete nginx pods and instead bring up redis pods. deploymentName := "test-rolling-update-deployment" framework.Logf("Creating deployment %q", deploymentName) - d := framework.NewDeployment(deploymentName, replicas, deploymentPodLabels, RedisImageName, RedisImage, extensions.RollingUpdateDeploymentStrategyType) - deploy, err := c.ExtensionsV1beta1().Deployments(ns).Create(d) + d := framework.NewDeployment(deploymentName, replicas, deploymentPodLabels, RedisImageName, RedisImage, apps.RollingUpdateDeploymentStrategyType) + deploy, err := c.AppsV1().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) // Wait for it to be updated to revision 3546343826724305833. @@ -269,9 +262,9 @@ func testRollingUpdateDeployment(f *framework.Framework) { // There should be 1 old RS (nginx-controller, which is adopted) framework.Logf("Ensuring deployment %q has one old replica set (the one it adopted)", deploy.Name) - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) - _, allOldRSs, err := deploymentutil.GetOldReplicaSets(deployment, c.ExtensionsV1beta1()) + _, allOldRSs, err := deploymentutil.GetOldReplicaSets(deployment, c.AppsV1()) Expect(err).NotTo(HaveOccurred()) Expect(len(allOldRSs)).Should(Equal(1)) } @@ -283,8 +276,8 @@ func testRecreateDeployment(f *framework.Framework) { // Create a deployment that brings up redis pods. deploymentName := "test-recreate-deployment" framework.Logf("Creating deployment %q", deploymentName) - d := framework.NewDeployment(deploymentName, int32(1), map[string]string{"name": "sample-pod-3"}, RedisImageName, RedisImage, extensions.RecreateDeploymentStrategyType) - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Create(d) + d := framework.NewDeployment(deploymentName, int32(1), map[string]string{"name": "sample-pod-3"}, RedisImageName, RedisImage, apps.RecreateDeploymentStrategyType) + deployment, err := c.AppsV1().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) // Wait for it to be updated to revision 1 @@ -297,7 +290,7 @@ func testRecreateDeployment(f *framework.Framework) { // Update deployment to delete redis pods and bring up nginx pods. framework.Logf("Triggering a new rollout for deployment %q", deploymentName) - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deploymentName, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deploymentName, func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Name = NginxImageName update.Spec.Template.Spec.Containers[0].Image = NginxImage }) @@ -320,7 +313,7 @@ func testDeploymentCleanUpPolicy(f *framework.Framework) { rsName := "test-cleanup-controller" replicas := int32(1) revisionHistoryLimit := utilpointer.Int32Ptr(0) - _, err := c.ExtensionsV1beta1().ReplicaSets(ns).Create(newRS(rsName, replicas, rsPodLabels, NginxImageName, NginxImage)) + _, err := c.AppsV1().ReplicaSets(ns).Create(newRS(rsName, replicas, rsPodLabels, NginxImageName, NginxImage)) Expect(err).NotTo(HaveOccurred()) // Verify that the required pods have come up. @@ -367,9 +360,9 @@ func testDeploymentCleanUpPolicy(f *framework.Framework) { } } }() - d := framework.NewDeployment(deploymentName, replicas, deploymentPodLabels, RedisImageName, RedisImage, extensions.RollingUpdateDeploymentStrategyType) + d := framework.NewDeployment(deploymentName, replicas, deploymentPodLabels, RedisImageName, RedisImage, apps.RollingUpdateDeploymentStrategyType) d.Spec.RevisionHistoryLimit = revisionHistoryLimit - _, err = c.ExtensionsV1beta1().Deployments(ns).Create(d) + _, err = c.AppsV1().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) By(fmt.Sprintf("Waiting for deployment %s history to be cleaned up", deploymentName)) @@ -391,7 +384,7 @@ func testRolloverDeployment(f *framework.Framework) { rsName := "test-rollover-controller" rsReplicas := int32(1) - _, err := c.ExtensionsV1beta1().ReplicaSets(ns).Create(newRS(rsName, rsReplicas, rsPodLabels, NginxImageName, NginxImage)) + _, err := c.AppsV1().ReplicaSets(ns).Create(newRS(rsName, rsReplicas, rsPodLabels, NginxImageName, NginxImage)) Expect(err).NotTo(HaveOccurred()) // Verify that the required pods have come up. err = framework.VerifyPodsRunning(c, ns, podName, false, rsReplicas) @@ -406,19 +399,19 @@ func testRolloverDeployment(f *framework.Framework) { deploymentName, deploymentImageName := "test-rollover-deployment", "redis-slave" deploymentReplicas := int32(1) deploymentImage := "gcr.io/google_samples/gb-redisslave:nonexistent" - deploymentStrategyType := extensions.RollingUpdateDeploymentStrategyType + deploymentStrategyType := apps.RollingUpdateDeploymentStrategyType framework.Logf("Creating deployment %q", deploymentName) newDeployment := framework.NewDeployment(deploymentName, deploymentReplicas, deploymentPodLabels, deploymentImageName, deploymentImage, deploymentStrategyType) - newDeployment.Spec.Strategy.RollingUpdate = &extensions.RollingUpdateDeployment{ + newDeployment.Spec.Strategy.RollingUpdate = &apps.RollingUpdateDeployment{ MaxUnavailable: intOrStrP(0), MaxSurge: intOrStrP(1), } newDeployment.Spec.MinReadySeconds = int32(10) - _, err = c.ExtensionsV1beta1().Deployments(ns).Create(newDeployment) + _, err = c.AppsV1().Deployments(ns).Create(newDeployment) Expect(err).NotTo(HaveOccurred()) // Verify that the pods were scaled up and down as expected. - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) framework.Logf("Make sure deployment %q performs scaling operations", deploymentName) // Make sure the deployment starts to scale up and down replica sets by checking if its updated replicas >= 1 @@ -429,17 +422,17 @@ func testRolloverDeployment(f *framework.Framework) { Expect(err).NotTo(HaveOccurred()) framework.Logf("Ensure that both replica sets have 1 created replica") - oldRS, err := c.ExtensionsV1beta1().ReplicaSets(ns).Get(rsName, metav1.GetOptions{}) + oldRS, err := c.AppsV1().ReplicaSets(ns).Get(rsName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) ensureReplicas(oldRS, int32(1)) - newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.ExtensionsV1beta1()) + newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.AppsV1()) Expect(err).NotTo(HaveOccurred()) ensureReplicas(newRS, int32(1)) // The deployment is stuck, update it to rollover the above 2 ReplicaSets and bring up redis pods. framework.Logf("Rollover old replica sets for deployment %q with new image update", deploymentName) updatedDeploymentImageName, updatedDeploymentImage := RedisImageName, RedisImage - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, newDeployment.Name, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, newDeployment.Name, func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Name = updatedDeploymentImageName update.Spec.Template.Spec.Containers[0].Image = updatedDeploymentImage }) @@ -460,16 +453,16 @@ func testRolloverDeployment(f *framework.Framework) { Expect(err).NotTo(HaveOccurred()) framework.Logf("Ensure that both old replica sets have no replicas") - oldRS, err = c.ExtensionsV1beta1().ReplicaSets(ns).Get(rsName, metav1.GetOptions{}) + oldRS, err = c.AppsV1().ReplicaSets(ns).Get(rsName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) ensureReplicas(oldRS, int32(0)) // Not really the new replica set anymore but we GET by name so that's fine. - newRS, err = c.ExtensionsV1beta1().ReplicaSets(ns).Get(newRS.Name, metav1.GetOptions{}) + newRS, err = c.AppsV1().ReplicaSets(ns).Get(newRS.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) ensureReplicas(newRS, int32(0)) } -func ensureReplicas(rs *extensions.ReplicaSet, replicas int32) { +func ensureReplicas(rs *apps.ReplicaSet, replicas int32) { Expect(*rs.Spec.Replicas).Should(Equal(replicas)) Expect(rs.Status.Replicas).Should(Equal(replicas)) } @@ -489,12 +482,12 @@ func testRollbackDeployment(f *framework.Framework) { deploymentName, deploymentImageName := "test-rollback-deployment", NginxImageName deploymentReplicas := int32(1) deploymentImage := NginxImage - deploymentStrategyType := extensions.RollingUpdateDeploymentStrategyType + deploymentStrategyType := apps.RollingUpdateDeploymentStrategyType framework.Logf("Creating deployment %s", deploymentName) d := framework.NewDeployment(deploymentName, deploymentReplicas, deploymentPodLabels, deploymentImageName, deploymentImage, deploymentStrategyType) createAnnotation := map[string]string{"action": "create", "author": "node"} d.Annotations = createAnnotation - deploy, err := c.ExtensionsV1beta1().Deployments(ns).Create(d) + deploy, err := c.AppsV1().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) // Wait for it to be updated to revision 1 @@ -512,7 +505,7 @@ func testRollbackDeployment(f *framework.Framework) { updatedDeploymentImage := RedisImage updatedDeploymentImageName := RedisImageName updateAnnotation := map[string]string{"action": "update", "log": "I need to update it"} - deployment, err := framework.UpdateDeploymentWithRetries(c, ns, d.Name, func(update *extensions.Deployment) { + deployment, err := framework.UpdateDeploymentWithRetries(c, ns, d.Name, func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Name = updatedDeploymentImageName update.Spec.Template.Spec.Containers[0].Image = updatedDeploymentImage update.Annotations = updateAnnotation @@ -615,7 +608,7 @@ func testRollbackDeployment(f *framework.Framework) { Expect(err).NotTo(HaveOccurred()) } -func randomScale(d *extensions.Deployment, i int) { +func randomScale(d *apps.Deployment, i int) { switch r := rand.Float32(); { case r < 0.3: framework.Logf("%02d: scaling up", i) @@ -640,12 +633,12 @@ func testIterativeDeployments(f *framework.Framework) { // Create a nginx deployment. deploymentName := "nginx" thirty := int32(30) - d := framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, extensions.RollingUpdateDeploymentStrategyType) + d := framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, apps.RollingUpdateDeploymentStrategyType) d.Spec.ProgressDeadlineSeconds = &thirty d.Spec.RevisionHistoryLimit = &two d.Spec.Template.Spec.TerminationGracePeriodSeconds = &zero framework.Logf("Creating deployment %q", deploymentName) - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Create(d) + deployment, err := c.AppsV1().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) iterations := 20 @@ -658,7 +651,7 @@ func testIterativeDeployments(f *framework.Framework) { case n < 0.2: // trigger a new deployment framework.Logf("%02d: triggering a new rollout for deployment %q", i, deployment.Name) - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *apps.Deployment) { newEnv := v1.EnvVar{Name: "A", Value: fmt.Sprintf("%d", i)} update.Spec.Template.Spec.Containers[0].Env = append(update.Spec.Template.Spec.Containers[0].Env, newEnv) randomScale(update, i) @@ -668,16 +661,18 @@ func testIterativeDeployments(f *framework.Framework) { case n < 0.4: // rollback to the previous version framework.Logf("%02d: rolling back a rollout for deployment %q", i, deployment.Name) - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *extensions.Deployment) { - rollbackTo := &extensions.RollbackConfig{Revision: 0} - update.Spec.RollbackTo = rollbackTo + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *apps.Deployment) { + if update.Annotations == nil { + update.Annotations = make(map[string]string) + } + update.Annotations[apps.DeprecatedRollbackTo] = "0" }) Expect(err).NotTo(HaveOccurred()) case n < 0.6: // just scaling framework.Logf("%02d: scaling deployment %q", i, deployment.Name) - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *apps.Deployment) { randomScale(update, i) }) Expect(err).NotTo(HaveOccurred()) @@ -686,14 +681,14 @@ func testIterativeDeployments(f *framework.Framework) { // toggling the deployment if deployment.Spec.Paused { framework.Logf("%02d: pausing deployment %q", i, deployment.Name) - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *apps.Deployment) { update.Spec.Paused = true randomScale(update, i) }) Expect(err).NotTo(HaveOccurred()) } else { framework.Logf("%02d: resuming deployment %q", i, deployment.Name) - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *apps.Deployment) { update.Spec.Paused = false randomScale(update, i) }) @@ -727,10 +722,10 @@ func testIterativeDeployments(f *framework.Framework) { } // unpause the deployment if we end up pausing it - deployment, err = c.ExtensionsV1beta1().Deployments(ns).Get(deployment.Name, metav1.GetOptions{}) + deployment, err = c.AppsV1().Deployments(ns).Get(deployment.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) if deployment.Spec.Paused { - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *apps.Deployment) { update.Spec.Paused = false }) } @@ -742,7 +737,7 @@ func testIterativeDeployments(f *framework.Framework) { Expect(framework.WaitForDeploymentComplete(c, deployment)).NotTo(HaveOccurred()) framework.Logf("Checking deployment %q for a complete condition", deploymentName) - Expect(framework.WaitForDeploymentWithCondition(c, ns, deploymentName, deploymentutil.NewRSAvailableReason, extensions.DeploymentProgressing)).NotTo(HaveOccurred()) + Expect(framework.WaitForDeploymentWithCondition(c, ns, deploymentName, deploymentutil.NewRSAvailableReason, apps.DeploymentProgressing)).NotTo(HaveOccurred()) } func testDeploymentsControllerRef(f *framework.Framework) { @@ -753,8 +748,8 @@ func testDeploymentsControllerRef(f *framework.Framework) { framework.Logf("Creating Deployment %q", deploymentName) podLabels := map[string]string{"name": NginxImageName} replicas := int32(1) - d := framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, extensions.RollingUpdateDeploymentStrategyType) - deploy, err := c.ExtensionsV1beta1().Deployments(ns).Create(d) + d := framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, apps.RollingUpdateDeploymentStrategyType) + deploy, err := c.AppsV1().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentComplete(c, deploy) Expect(err).NotTo(HaveOccurred()) @@ -780,8 +775,8 @@ func testDeploymentsControllerRef(f *framework.Framework) { deploymentName = "test-adopt-deployment" framework.Logf("Creating Deployment %q to adopt the ReplicaSet", deploymentName) - d = framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, extensions.RollingUpdateDeploymentStrategyType) - deploy, err = c.ExtensionsV1beta1().Deployments(ns).Create(d) + d = framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, apps.RollingUpdateDeploymentStrategyType) + deploy, err = c.AppsV1().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentComplete(c, deploy) Expect(err).NotTo(HaveOccurred()) @@ -810,13 +805,13 @@ func testProportionalScalingDeployment(f *framework.Framework) { // Create a nginx deployment. deploymentName := "nginx-deployment" - d := framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, extensions.RollingUpdateDeploymentStrategyType) - d.Spec.Strategy.RollingUpdate = new(extensions.RollingUpdateDeployment) + d := framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, NginxImage, apps.RollingUpdateDeploymentStrategyType) + d.Spec.Strategy.RollingUpdate = new(apps.RollingUpdateDeployment) d.Spec.Strategy.RollingUpdate.MaxSurge = intOrStrP(3) d.Spec.Strategy.RollingUpdate.MaxUnavailable = intOrStrP(2) framework.Logf("Creating deployment %q", deploymentName) - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Create(d) + deployment, err := c.AppsV1().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) framework.Logf("Waiting for observed generation %d", deployment.Generation) @@ -830,13 +825,13 @@ func testProportionalScalingDeployment(f *framework.Framework) { framework.Logf("Waiting for deployment %q to complete", deployment.Name) Expect(framework.WaitForDeploymentComplete(c, deployment)).NotTo(HaveOccurred()) - firstRS, err := deploymentutil.GetNewReplicaSet(deployment, c.ExtensionsV1beta1()) + firstRS, err := deploymentutil.GetNewReplicaSet(deployment, c.AppsV1()) Expect(err).NotTo(HaveOccurred()) // Update the deployment with a non-existent image so that the new replica set // will be blocked to simulate a partial rollout. framework.Logf("Updating deployment %q with a non-existent image", deploymentName) - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, d.Name, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, d.Name, func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Image = "nginx:404" }) Expect(err).NotTo(HaveOccurred()) @@ -859,13 +854,13 @@ func testProportionalScalingDeployment(f *framework.Framework) { // The desired replicas wait makes sure that the RS controller has created expected number of pods. framework.Logf("Waiting for the first rollout's replicaset of deployment %q to have desired number of replicas", deploymentName) - firstRS, err = c.ExtensionsV1beta1().ReplicaSets(ns).Get(firstRS.Name, metav1.GetOptions{}) + firstRS, err = c.AppsV1().ReplicaSets(ns).Get(firstRS.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) - err = framework.WaitForReplicaSetDesiredReplicas(c.ExtensionsV1beta1(), firstRS) + err = framework.WaitForReplicaSetDesiredReplicas(c.AppsV1(), firstRS) Expect(err).NotTo(HaveOccurred()) // Checking state of second rollout's replicaset. - secondRS, err := deploymentutil.GetNewReplicaSet(deployment, c.ExtensionsV1beta1()) + secondRS, err := deploymentutil.GetNewReplicaSet(deployment, c.AppsV1()) Expect(err).NotTo(HaveOccurred()) maxSurge, err := intstr.GetValueFromIntOrPercent(deployment.Spec.Strategy.RollingUpdate.MaxSurge, int(*(deployment.Spec.Replicas)), false) @@ -882,9 +877,9 @@ func testProportionalScalingDeployment(f *framework.Framework) { // The desired replicas wait makes sure that the RS controller has created expected number of pods. framework.Logf("Waiting for the second rollout's replicaset of deployment %q to have desired number of replicas", deploymentName) - secondRS, err = c.ExtensionsV1beta1().ReplicaSets(ns).Get(secondRS.Name, metav1.GetOptions{}) + secondRS, err = c.AppsV1().ReplicaSets(ns).Get(secondRS.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) - err = framework.WaitForReplicaSetDesiredReplicas(c.ExtensionsV1beta1(), secondRS) + err = framework.WaitForReplicaSetDesiredReplicas(c.AppsV1(), secondRS) Expect(err).NotTo(HaveOccurred()) // Check the deployment's minimum availability. @@ -896,15 +891,15 @@ func testProportionalScalingDeployment(f *framework.Framework) { // Scale the deployment to 30 replicas. newReplicas = int32(30) framework.Logf("Scaling up the deployment %q from %d to %d", deploymentName, replicas, newReplicas) - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *apps.Deployment) { update.Spec.Replicas = &newReplicas }) Expect(err).NotTo(HaveOccurred()) framework.Logf("Waiting for the replicasets of deployment %q to have desired number of replicas", deploymentName) - firstRS, err = c.ExtensionsV1beta1().ReplicaSets(ns).Get(firstRS.Name, metav1.GetOptions{}) + firstRS, err = c.AppsV1().ReplicaSets(ns).Get(firstRS.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) - secondRS, err = c.ExtensionsV1beta1().ReplicaSets(ns).Get(secondRS.Name, metav1.GetOptions{}) + secondRS, err = c.AppsV1().ReplicaSets(ns).Get(secondRS.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) // First rollout's replicaset should have .spec.replicas = 8 + (30-10)*(8/13) = 8 + 12 = 20 replicas. @@ -942,18 +937,18 @@ func waitDeploymentReplicaSetsOrphaned(c clientset.Interface, ns string, label m } } -func listDeploymentReplicaSets(c clientset.Interface, ns string, label map[string]string) *extensions.ReplicaSetList { +func listDeploymentReplicaSets(c clientset.Interface, ns string, label map[string]string) *apps.ReplicaSetList { selector := labels.Set(label).AsSelector() options := metav1.ListOptions{LabelSelector: selector.String()} - rsList, err := c.ExtensionsV1beta1().ReplicaSets(ns).List(options) + rsList, err := c.AppsV1().ReplicaSets(ns).List(options) Expect(err).NotTo(HaveOccurred()) Expect(len(rsList.Items)).To(BeNumerically(">", 0)) return rsList } -func orphanDeploymentReplicaSets(c clientset.Interface, d *extensions.Deployment) error { +func orphanDeploymentReplicaSets(c clientset.Interface, d *apps.Deployment) error { trueVar := true deleteOptions := &metav1.DeleteOptions{OrphanDependents: &trueVar} deleteOptions.Preconditions = metav1.NewUIDPreconditions(string(d.UID)) - return c.ExtensionsV1beta1().Deployments(d.Namespace).Delete(d.Name, deleteOptions) + return c.AppsV1().Deployments(d.Namespace).Delete(d.Name, deleteOptions) } diff --git a/vendor/k8s.io/kubernetes/test/e2e/apps/job.go b/vendor/k8s.io/kubernetes/test/e2e/apps/job.go index 8a4b8c0ca..29b5afd7f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apps/job.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apps/job.go @@ -24,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" batchinternal "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" @@ -111,11 +110,7 @@ var _ = SIGDescribe("Job", func() { Expect(err).NotTo(HaveOccurred()) By("delete a job") - reaper, err := kubectl.ReaperFor(batchinternal.Kind("Job"), f.InternalClientset) - Expect(err).NotTo(HaveOccurred()) - timeout := 1 * time.Minute - err = reaper.Stop(f.Namespace.Name, job.Name, timeout, metav1.NewDeleteOptions(0)) - Expect(err).NotTo(HaveOccurred()) + framework.ExpectNoError(framework.DeleteResourceAndWaitForGC(f.ClientSet, batchinternal.Kind("Job"), f.Namespace.Name, job.Name)) By("Ensuring job was deleted") _, err = framework.GetJob(f.ClientSet, f.Namespace.Name, job.Name) @@ -179,7 +174,8 @@ var _ = SIGDescribe("Job", func() { It("should exceed backoffLimit", func() { By("Creating a job") - job := framework.NewTestJob("fail", "backofflimit", v1.RestartPolicyNever, 1, 1, nil, 0) + backoff := 1 + job := framework.NewTestJob("fail", "backofflimit", v1.RestartPolicyNever, 1, 1, nil, int32(backoff)) job, err := framework.CreateJob(f.ClientSet, f.Namespace.Name, job) Expect(err).NotTo(HaveOccurred()) By("Ensuring job exceed backofflimit") @@ -187,11 +183,18 @@ var _ = SIGDescribe("Job", func() { err = framework.WaitForJobFailure(f.ClientSet, f.Namespace.Name, job.Name, framework.JobTimeout, "BackoffLimitExceeded") Expect(err).NotTo(HaveOccurred()) - By("Checking that only one pod created and status is failed") + By(fmt.Sprintf("Checking that %d pod created and status is failed", backoff+1)) pods, err := framework.GetJobPods(f.ClientSet, f.Namespace.Name, job.Name) Expect(err).NotTo(HaveOccurred()) - Expect(pods.Items).To(HaveLen(1)) - pod := pods.Items[0] - Expect(pod.Status.Phase).To(Equal(v1.PodFailed)) + // Expect(pods.Items).To(HaveLen(backoff + 1)) + // due to NumRequeus not being stable enough, especially with failed status + // updates we need to allow more than backoff+1 + // TODO revert this back to above when https://github.com/kubernetes/kubernetes/issues/64787 gets fixed + if len(pods.Items) < backoff+1 { + framework.Failf("Not enough pod created expected at least %d, got %#v", backoff+1, pods.Items) + } + for _, pod := range pods.Items { + Expect(pod.Status.Phase).To(Equal(v1.PodFailed)) + } }) }) diff --git a/vendor/k8s.io/kubernetes/test/e2e/apps/rc.go b/vendor/k8s.io/kubernetes/test/e2e/apps/rc.go index 3b1bffb05..406b380d9 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apps/rc.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apps/rc.go @@ -38,6 +38,12 @@ import ( var _ = SIGDescribe("ReplicationController", func() { f := framework.NewDefaultFramework("replication-controller") + /* + Release : v1.9 + Testname: Replication Controller, run basic image + Description: Replication Controller MUST create a Pod with Basic Image and MUST run the service with the provided image. Image MUST be tested by dialing into the service listening through TCP, UDP and HTTP. + */ + framework.ConformanceIt("should serve a basic image on each replica with a public image ", func() { TestReplicationControllerServeImageOrFail(f, "basic", framework.ServeHostnameImage) }) diff --git a/vendor/k8s.io/kubernetes/test/e2e/apps/replica_set.go b/vendor/k8s.io/kubernetes/test/e2e/apps/replica_set.go index 8dcd4abed..354d2e94b 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apps/replica_set.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apps/replica_set.go @@ -20,8 +20,8 @@ import ( "fmt" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -36,13 +36,17 @@ import ( imageutils "k8s.io/kubernetes/test/utils/image" ) -func newRS(rsName string, replicas int32, rsPodLabels map[string]string, imageName string, image string) *extensions.ReplicaSet { +func newRS(rsName string, replicas int32, rsPodLabels map[string]string, imageName string, image string) *apps.ReplicaSet { zero := int64(0) - return &extensions.ReplicaSet{ + return &apps.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ - Name: rsName, + Name: rsName, + Labels: rsPodLabels, }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: rsPodLabels, + }, Replicas: &replicas, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ @@ -78,6 +82,11 @@ func newPodQuota(name, number string) *v1.ResourceQuota { var _ = SIGDescribe("ReplicaSet", func() { f := framework.NewDefaultFramework("replicaset") + /* + Release : v1.9 + Testname: Replica Set, run basic image + Description: Create a ReplicaSet with a Pod and a single Container. Make sure that the Pod is running. Pod SHOULD send a valid response when queried. + */ framework.ConformanceIt("should serve a basic image on each replica with a public image ", func() { testReplicaSetServeImageOrFail(f, "basic", framework.ServeHostnameImage) }) @@ -111,7 +120,7 @@ func testReplicaSetServeImageOrFail(f *framework.Framework, test string, image s framework.Logf("Creating ReplicaSet %s", name) newRS := newRS(name, replicas, map[string]string{"name": name}, name, image) newRS.Spec.Template.Spec.Containers[0].Ports = []v1.ContainerPort{{ContainerPort: 9376}} - _, err := f.ClientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name).Create(newRS) + _, err := f.ClientSet.AppsV1().ReplicaSets(f.Namespace.Name).Create(newRS) Expect(err).NotTo(HaveOccurred()) // Check that pods for the new RS were created. @@ -187,14 +196,14 @@ func testReplicaSetConditionCheck(f *framework.Framework) { By(fmt.Sprintf("Creating replica set %q that asks for more than the allowed pod quota", name)) rs := newRS(name, 3, map[string]string{"name": name}, NginxImageName, NginxImage) - rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).Create(rs) + rs, err = c.AppsV1().ReplicaSets(namespace).Create(rs) Expect(err).NotTo(HaveOccurred()) By(fmt.Sprintf("Checking replica set %q has the desired failure condition set", name)) generation := rs.Generation conditions := rs.Status.Conditions err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) { - rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}) + rs, err = c.AppsV1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}) if err != nil { return false, err } @@ -204,7 +213,7 @@ func testReplicaSetConditionCheck(f *framework.Framework) { } conditions = rs.Status.Conditions - cond := replicaset.GetCondition(rs.Status, extensions.ReplicaSetReplicaFailure) + cond := replicaset.GetCondition(rs.Status, apps.ReplicaSetReplicaFailure) return cond != nil, nil }) @@ -214,7 +223,7 @@ func testReplicaSetConditionCheck(f *framework.Framework) { Expect(err).NotTo(HaveOccurred()) By(fmt.Sprintf("Scaling down replica set %q to satisfy pod quota", name)) - rs, err = framework.UpdateReplicaSetWithRetries(c, namespace, name, func(update *extensions.ReplicaSet) { + rs, err = framework.UpdateReplicaSetWithRetries(c, namespace, name, func(update *apps.ReplicaSet) { x := int32(2) update.Spec.Replicas = &x }) @@ -224,7 +233,7 @@ func testReplicaSetConditionCheck(f *framework.Framework) { generation = rs.Generation conditions = rs.Status.Conditions err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) { - rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}) + rs, err = c.AppsV1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}) if err != nil { return false, err } @@ -234,7 +243,7 @@ func testReplicaSetConditionCheck(f *framework.Framework) { } conditions = rs.Status.Conditions - cond := replicaset.GetCondition(rs.Status, extensions.ReplicaSetReplicaFailure) + cond := replicaset.GetCondition(rs.Status, apps.ReplicaSetReplicaFailure) return cond == nil, nil }) if err == wait.ErrWaitTimeout { @@ -267,7 +276,7 @@ func testRSAdoptMatchingAndReleaseNotMatching(f *framework.Framework) { replicas := int32(1) rsSt := newRS(name, replicas, map[string]string{"name": name}, name, NginxImageName) rsSt.Spec.Selector = &metav1.LabelSelector{MatchLabels: map[string]string{"name": name}} - rs, err := f.ClientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name).Create(rsSt) + rs, err := f.ClientSet.AppsV1().ReplicaSets(f.Namespace.Name).Create(rsSt) Expect(err).NotTo(HaveOccurred()) By("Then the orphan pod is adopted") diff --git a/vendor/k8s.io/kubernetes/test/e2e/apps/statefulset.go b/vendor/k8s.io/kubernetes/test/e2e/apps/statefulset.go index c4e96f44f..09b147211 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/apps/statefulset.go +++ b/vendor/k8s.io/kubernetes/test/e2e/apps/statefulset.go @@ -249,12 +249,9 @@ var _ = SIGDescribe("StatefulSet", func() { }) /* - Testname: StatefulSet-RollingUpdate - Description: StatefulSet MUST support the RollingUpdate strategy to automatically replace Pods - one at a time when the Pod template changes. The StatefulSet's status MUST indicate the - CurrentRevision and UpdateRevision. If the template is changed to match a prior revision, - StatefulSet MUST detect this as a rollback instead of creating a new revision. - This test does not depend on a preexisting default StorageClass or a dynamic provisioner. + Release : v1.9 + Testname: StatefulSet, Rolling Update + Description: StatefulSet MUST support the RollingUpdate strategy to automatically replace Pods one at a time when the Pod template changes. The StatefulSet's status MUST indicate the CurrentRevision and UpdateRevision. If the template is changed to match a prior revision, StatefulSet MUST detect this as a rollback instead of creating a new revision. This test does not depend on a preexisting default StorageClass or a dynamic provisioner. */ framework.ConformanceIt("should perform rolling updates and roll backs of template modifications", func() { By("Creating a new StatefulSet") @@ -372,11 +369,9 @@ var _ = SIGDescribe("StatefulSet", func() { }) /* - Testname: StatefulSet-RollingUpdatePartition - Description: StatefulSet's RollingUpdate strategy MUST support the Partition parameter for - canaries and phased rollouts. If a Pod is deleted while a rolling update is in progress, - StatefulSet MUST restore the Pod without violating the Partition. - This test does not depend on a preexisting default StorageClass or a dynamic provisioner. + Release : v1.9 + Testname: StatefulSet, Rolling Update with Partition + Description: StatefulSet's RollingUpdate strategy MUST support the Partition parameter for canaries and phased rollouts. If a Pod is deleted while a rolling update is in progress, StatefulSet MUST restore the Pod without violating the Partition. This test does not depend on a preexisting default StorageClass or a dynamic provisioner. */ framework.ConformanceIt("should perform canary updates and phased rolling updates of template modifications", func() { By("Creating a new StaefulSet") @@ -670,11 +665,9 @@ var _ = SIGDescribe("StatefulSet", func() { }) /* - Testname: StatefulSet-Scaling - Description: StatefulSet MUST create Pods in ascending order by ordinal index when scaling up, - and delete Pods in descending order when scaling down. Scaling up or down MUST pause if any - Pods belonging to the StatefulSet are unhealthy. - This test does not depend on a preexisting default StorageClass or a dynamic provisioner. + Release : v1.9 + Testname: StatefulSet, Scaling + Description: StatefulSet MUST create Pods in ascending order by ordinal index when scaling up, and delete Pods in descending order when scaling down. Scaling up or down MUST pause if any Pods belonging to the StatefulSet are unhealthy. This test does not depend on a preexisting default StorageClass or a dynamic provisioner. */ framework.ConformanceIt("Scaling should happen in predictable order and halt if any stateful pod is unhealthy", func() { psLabels := klabels.Set(labels) @@ -753,9 +746,9 @@ var _ = SIGDescribe("StatefulSet", func() { }) /* - Testname: StatefulSet-BurstScaling - Description: StatefulSet MUST support the Parallel PodManagementPolicy for burst scaling. - This test does not depend on a preexisting default StorageClass or a dynamic provisioner. + Release : v1.9 + Testname: StatefulSet, Burst Scaling + Description: StatefulSet MUST support the Parallel PodManagementPolicy for burst scaling. This test does not depend on a preexisting default StorageClass or a dynamic provisioner. */ framework.ConformanceIt("Burst scaling should run to completion even with unhealthy pods", func() { psLabels := klabels.Set(labels) @@ -796,10 +789,9 @@ var _ = SIGDescribe("StatefulSet", func() { }) /* - Testname: StatefulSet-RecreateFailedPod - Description: StatefulSet MUST delete and recreate Pods it owns that go into a Failed state, - such as when they are rejected or evicted by a Node. - This test does not depend on a preexisting default StorageClass or a dynamic provisioner. + Release : v1.9 + Testname: StatefulSet, Recreate Failed Pod + Description: StatefulSet MUST delete and recreate Pods it owns that go into a Failed state, such as when they are rejected or evicted by a Node. This test does not depend on a preexisting default StorageClass or a dynamic provisioner. */ framework.ConformanceIt("Should recreate evicted statefulset", func() { podName := "test-pod" diff --git a/vendor/k8s.io/kubernetes/test/e2e/auth/BUILD b/vendor/k8s.io/kubernetes/test/e2e/auth/BUILD index f16056db1..9e52a8446 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/auth/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/auth/BUILD @@ -29,6 +29,7 @@ go_library( "//vendor/github.com/evanphx/json-patch:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e/auth/audit.go b/vendor/k8s.io/kubernetes/test/e2e/auth/audit.go index 2305bfe1e..cd239a477 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/auth/audit.go +++ b/vendor/k8s.io/kubernetes/test/e2e/auth/audit.go @@ -23,15 +23,17 @@ import ( "strings" "time" + apps "k8s.io/api/apps/v1" apiv1 "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + apiextensionclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/testserver" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/apis/audit/v1beta1" + clientset "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/test/e2e/framework" imageutils "k8s.io/kubernetes/test/utils/image" @@ -63,9 +65,19 @@ var _ = SIGDescribe("Advanced Audit", func() { config, err := framework.LoadConfig() framework.ExpectNoError(err, "failed to load config") - apiExtensionClient, err := clientset.NewForConfig(config) + apiExtensionClient, err := apiextensionclientset.NewForConfig(config) framework.ExpectNoError(err, "failed to initialize apiExtensionClient") + By("Creating a kubernetes client that impersonates an unauthorized anonymous user") + config, err = framework.LoadConfig() + framework.ExpectNoError(err) + config.Impersonate = restclient.ImpersonationConfig{ + UserName: "system:anonymous", + Groups: []string{"system:unauthenticated"}, + } + anonymousClient, err := clientset.NewForConfig(config) + framework.ExpectNoError(err) + testCases := []struct { action func() events []auditEvent @@ -80,7 +92,7 @@ var _ = SIGDescribe("Advanced Audit", func() { Spec: apiv1.PodSpec{ Containers: []apiv1.Container{{ Name: "pause", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), }}, }, } @@ -118,6 +130,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, true, true, + "allow", }, { v1beta1.LevelRequest, v1beta1.StageResponseComplete, @@ -129,6 +142,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelRequest, v1beta1.StageResponseComplete, @@ -140,6 +154,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelRequest, v1beta1.StageResponseStarted, @@ -151,6 +166,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelRequest, v1beta1.StageResponseComplete, @@ -162,6 +178,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelRequestResponse, v1beta1.StageResponseComplete, @@ -173,6 +190,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, true, true, + "allow", }, { v1beta1.LevelRequestResponse, v1beta1.StageResponseComplete, @@ -184,6 +202,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, true, true, + "allow", }, { v1beta1.LevelRequestResponse, v1beta1.StageResponseComplete, @@ -195,6 +214,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, true, true, + "allow", }, }, }, @@ -202,36 +222,36 @@ var _ = SIGDescribe("Advanced Audit", func() { { func() { podLabels := map[string]string{"name": "audit-deployment-pod"} - d := framework.NewDeployment("audit-deployment", int32(1), podLabels, "redis", imageutils.GetE2EImage(imageutils.Redis), extensions.RecreateDeploymentStrategyType) + d := framework.NewDeployment("audit-deployment", int32(1), podLabels, "redis", imageutils.GetE2EImage(imageutils.Redis), apps.RecreateDeploymentStrategyType) - _, err := f.ClientSet.ExtensionsV1beta1().Deployments(namespace).Create(d) + _, err := f.ClientSet.AppsV1().Deployments(namespace).Create(d) framework.ExpectNoError(err, "failed to create audit-deployment") - _, err = f.ClientSet.ExtensionsV1beta1().Deployments(namespace).Get(d.Name, metav1.GetOptions{}) + _, err = f.ClientSet.AppsV1().Deployments(namespace).Get(d.Name, metav1.GetOptions{}) framework.ExpectNoError(err, "failed to get audit-deployment") - deploymentChan, err := f.ClientSet.ExtensionsV1beta1().Deployments(namespace).Watch(watchOptions) + deploymentChan, err := f.ClientSet.AppsV1().Deployments(namespace).Watch(watchOptions) framework.ExpectNoError(err, "failed to create watch for deployments") for range deploymentChan.ResultChan() { } - _, err = f.ClientSet.ExtensionsV1beta1().Deployments(namespace).Update(d) + _, err = f.ClientSet.AppsV1().Deployments(namespace).Update(d) framework.ExpectNoError(err, "failed to update audit-deployment") - _, err = f.ClientSet.ExtensionsV1beta1().Deployments(namespace).Patch(d.Name, types.JSONPatchType, patch) + _, err = f.ClientSet.AppsV1().Deployments(namespace).Patch(d.Name, types.JSONPatchType, patch) framework.ExpectNoError(err, "failed to patch deployment") - _, err = f.ClientSet.ExtensionsV1beta1().Deployments(namespace).List(metav1.ListOptions{}) + _, err = f.ClientSet.AppsV1().Deployments(namespace).List(metav1.ListOptions{}) framework.ExpectNoError(err, "failed to create list deployments") - err = f.ClientSet.ExtensionsV1beta1().Deployments(namespace).Delete("audit-deployment", &metav1.DeleteOptions{}) + err = f.ClientSet.AppsV1().Deployments(namespace).Delete("audit-deployment", &metav1.DeleteOptions{}) framework.ExpectNoError(err, "failed to delete deployments") }, []auditEvent{ { v1beta1.LevelRequestResponse, v1beta1.StageResponseComplete, - fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/deployments", namespace), + fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments", namespace), "create", 201, auditTestUser, @@ -239,10 +259,11 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, true, true, + "allow", }, { v1beta1.LevelRequest, v1beta1.StageResponseComplete, - fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/deployments/audit-deployment", namespace), + fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), "get", 200, auditTestUser, @@ -250,10 +271,11 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelRequest, v1beta1.StageResponseComplete, - fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/deployments", namespace), + fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments", namespace), "list", 200, auditTestUser, @@ -261,10 +283,11 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelRequest, v1beta1.StageResponseStarted, - fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/deployments?timeoutSeconds=%d&watch=true", namespace, watchTestTimeout), + fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments?timeoutSeconds=%d&watch=true", namespace, watchTestTimeout), "watch", 200, auditTestUser, @@ -272,10 +295,11 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelRequest, v1beta1.StageResponseComplete, - fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/deployments?timeoutSeconds=%d&watch=true", namespace, watchTestTimeout), + fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments?timeoutSeconds=%d&watch=true", namespace, watchTestTimeout), "watch", 200, auditTestUser, @@ -283,10 +307,11 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelRequestResponse, v1beta1.StageResponseComplete, - fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/deployments/audit-deployment", namespace), + fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), "update", 200, auditTestUser, @@ -294,10 +319,11 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, true, true, + "allow", }, { v1beta1.LevelRequestResponse, v1beta1.StageResponseComplete, - fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/deployments/audit-deployment", namespace), + fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), "patch", 200, auditTestUser, @@ -305,10 +331,11 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, true, true, + "allow", }, { v1beta1.LevelRequestResponse, v1beta1.StageResponseComplete, - fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/deployments/audit-deployment", namespace), + fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), "delete", 200, auditTestUser, @@ -316,6 +343,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, true, true, + "allow", }, }, }, @@ -366,6 +394,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -377,6 +406,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -388,6 +418,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseStarted, @@ -399,6 +430,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -410,6 +442,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -421,6 +454,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -432,6 +466,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -443,6 +478,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, }, }, @@ -492,6 +528,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -503,6 +540,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -514,6 +552,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseStarted, @@ -525,6 +564,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -536,6 +576,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -547,6 +588,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -558,6 +600,7 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, { v1beta1.LevelMetadata, v1beta1.StageResponseComplete, @@ -569,62 +612,100 @@ var _ = SIGDescribe("Advanced Audit", func() { namespace, false, false, + "allow", }, }, }, // Create and delete custom resource definition. { func() { - _, err = testserver.CreateNewCustomResourceDefinition(crd, apiExtensionClient, f.ClientPool) + crd, err = testserver.CreateNewCustomResourceDefinition(crd, apiExtensionClient, f.DynamicClient) framework.ExpectNoError(err, "failed to create custom resource definition") testserver.DeleteCustomResourceDefinition(crd, apiExtensionClient) }, []auditEvent{ { - level: v1beta1.LevelRequestResponse, - stage: v1beta1.StageResponseComplete, - requestURI: "/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions", - verb: "create", - code: 201, - user: auditTestUser, - resource: "customresourcedefinitions", - requestObject: true, - responseObject: true, + level: v1beta1.LevelRequestResponse, + stage: v1beta1.StageResponseComplete, + requestURI: "/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions", + verb: "create", + code: 201, + user: auditTestUser, + resource: "customresourcedefinitions", + requestObject: true, + responseObject: true, + authorizeDecision: "allow", }, { - level: v1beta1.LevelMetadata, - stage: v1beta1.StageResponseComplete, - requestURI: fmt.Sprintf("/apis/%s/v1beta1/%s", crdNamespace, crdName), - verb: "create", - code: 201, - user: auditTestUser, - resource: crdName, - requestObject: false, - responseObject: false, + level: v1beta1.LevelMetadata, + stage: v1beta1.StageResponseComplete, + requestURI: fmt.Sprintf("/apis/%s/v1beta1/%s", crdNamespace, crdName), + verb: "create", + code: 201, + user: auditTestUser, + resource: crdName, + requestObject: false, + responseObject: false, + authorizeDecision: "allow", }, { - level: v1beta1.LevelRequestResponse, - stage: v1beta1.StageResponseComplete, - requestURI: fmt.Sprintf("/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/%s", crd.Name), - verb: "delete", - code: 200, - user: auditTestUser, - resource: "customresourcedefinitions", - requestObject: false, - responseObject: true, + level: v1beta1.LevelRequestResponse, + stage: v1beta1.StageResponseComplete, + requestURI: fmt.Sprintf("/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/%s", crd.Name), + verb: "delete", + code: 200, + user: auditTestUser, + resource: "customresourcedefinitions", + requestObject: false, + responseObject: true, + authorizeDecision: "allow", }, { - level: v1beta1.LevelMetadata, - stage: v1beta1.StageResponseComplete, - requestURI: fmt.Sprintf("/apis/%s/v1beta1/%s/setup-instance", crdNamespace, crdName), - verb: "delete", - code: 200, - user: auditTestUser, - resource: crdName, - requestObject: false, - responseObject: false, + level: v1beta1.LevelMetadata, + stage: v1beta1.StageResponseComplete, + requestURI: fmt.Sprintf("/apis/%s/v1beta1/%s/setup-instance", crdNamespace, crdName), + verb: "delete", + code: 200, + user: auditTestUser, + resource: crdName, + requestObject: false, + responseObject: false, + authorizeDecision: "allow", }, }, }, } + // test authorizer annotations, RBAC is required. + annotationTestCases := []struct { + action func() + events []auditEvent + }{ + + // get a pod with unauthorized user + { + func() { + _, err := anonymousClient.CoreV1().Pods(namespace).Get("another-audit-pod", metav1.GetOptions{}) + expectForbidden(err) + }, + []auditEvent{ + { + level: v1beta1.LevelRequest, + stage: v1beta1.StageResponseComplete, + requestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/another-audit-pod", namespace), + verb: "get", + code: 403, + user: auditTestUser, + resource: "pods", + namespace: namespace, + requestObject: false, + responseObject: false, + authorizeDecision: "forbid", + }, + }, + }, + } + + if framework.IsRBACEnabled(f) { + testCases = append(testCases, annotationTestCases...) + } expectedEvents := []auditEvent{} for _, t := range testCases { t.action() @@ -647,16 +728,17 @@ var _ = SIGDescribe("Advanced Audit", func() { }) type auditEvent struct { - level v1beta1.Level - stage v1beta1.Stage - requestURI string - verb string - code int32 - user string - resource string - namespace string - requestObject bool - responseObject bool + level v1beta1.Level + stage v1beta1.Stage + requestURI string + verb string + code int32 + user string + resource string + namespace string + requestObject bool + responseObject bool + authorizeDecision string } // Search the audit log for the expected audit lines. @@ -725,5 +807,6 @@ func parseAuditLine(line string) (auditEvent, error) { if e.RequestObject != nil { event.requestObject = true } + event.authorizeDecision = e.Annotations["authorization.k8s.io/decision"] return event, nil } diff --git a/vendor/k8s.io/kubernetes/test/e2e/auth/node_authz.go b/vendor/k8s.io/kubernetes/test/e2e/auth/node_authz.go index a7d8c95f1..a4a43186b 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/auth/node_authz.go +++ b/vendor/k8s.io/kubernetes/test/e2e/auth/node_authz.go @@ -27,6 +27,7 @@ import ( clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/test/e2e/framework" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -74,11 +75,33 @@ var _ = SIGDescribe("[Feature:NodeAuthorizer]", func() { Expect(apierrors.IsForbidden(err)).Should(Equal(true)) }) - It("Getting an existent secret should exit with the Forbidden error", func() { + It("Getting an existing secret should exit with the Forbidden error", func() { _, err := c.CoreV1().Secrets(ns).Get(defaultSaSecret, metav1.GetOptions{}) Expect(apierrors.IsForbidden(err)).Should(Equal(true)) }) + It("Getting a non-existent configmap should exit with the Forbidden error, not a NotFound error", func() { + _, err := c.CoreV1().ConfigMaps(ns).Get("foo", metav1.GetOptions{}) + Expect(apierrors.IsForbidden(err)).Should(Equal(true)) + }) + + It("Getting an existing configmap should exit with the Forbidden error", func() { + By("Create a configmap for testing") + configmap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: "node-auth-configmap", + }, + Data: map[string]string{ + "data": "content", + }, + } + _, err := f.ClientSet.CoreV1().ConfigMaps(ns).Create(configmap) + Expect(err).NotTo(HaveOccurred()) + _, err = c.CoreV1().ConfigMaps(ns).Get(configmap.Name, metav1.GetOptions{}) + Expect(apierrors.IsForbidden(err)).Should(Equal(true)) + }) + It("Getting a secret for a workload the node has access to should succeed", func() { By("Create a secret for testing") secret := &v1.Secret{ @@ -106,7 +129,7 @@ var _ = SIGDescribe("[Feature:NodeAuthorizer]", func() { Containers: []v1.Container{ { Name: "pause", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), }, }, NodeName: nodeName, @@ -138,7 +161,7 @@ var _ = SIGDescribe("[Feature:NodeAuthorizer]", func() { Expect(err).NotTo(HaveOccurred()) }) - It("A node shouldn't be able to create an other node", func() { + It("A node shouldn't be able to create another node", func() { node := &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, TypeMeta: metav1.TypeMeta{ @@ -151,7 +174,7 @@ var _ = SIGDescribe("[Feature:NodeAuthorizer]", func() { Expect(apierrors.IsForbidden(err)).Should(Equal(true)) }) - It("A node shouldn't be able to delete an other node", func() { + It("A node shouldn't be able to delete another node", func() { By(fmt.Sprintf("Create node foo by user: %v", asUser)) err := c.CoreV1().Nodes().Delete("foo", &metav1.DeleteOptions{}) Expect(apierrors.IsForbidden(err)).Should(Equal(true)) diff --git a/vendor/k8s.io/kubernetes/test/e2e/auth/pod_security_policy.go b/vendor/k8s.io/kubernetes/test/e2e/auth/pod_security_policy.go index a2bbbcb88..3f5a37f72 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/auth/pod_security_policy.go +++ b/vendor/k8s.io/kubernetes/test/e2e/auth/pod_security_policy.go @@ -35,6 +35,7 @@ import ( utilpointer "k8s.io/kubernetes/pkg/util/pointer" "k8s.io/kubernetes/test/e2e/common" "k8s.io/kubernetes/test/e2e/framework" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -315,17 +316,17 @@ func restrictedPod(f *framework.Framework, name string) *v1.Pod { ObjectMeta: metav1.ObjectMeta{ Name: name, Annotations: map[string]string{ - v1.SeccompPodAnnotationKey: "docker/default", + v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault, apparmor.ContainerAnnotationKeyPrefix + "pause": apparmor.ProfileRuntimeDefault, }, }, Spec: v1.PodSpec{ Containers: []v1.Container{{ Name: "pause", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), SecurityContext: &v1.SecurityContext{ AllowPrivilegeEscalation: boolPtr(false), - RunAsUser: intPtr(65534), + RunAsUser: utilpointer.Int64Ptr(65534), }, }}, }, @@ -373,8 +374,8 @@ func restrictedPSPInPolicy(name string) *policy.PodSecurityPolicy { ObjectMeta: metav1.ObjectMeta{ Name: name, Annotations: map[string]string{ - seccomp.AllowedProfilesAnnotationKey: "docker/default", - seccomp.DefaultProfileAnnotationKey: "docker/default", + seccomp.AllowedProfilesAnnotationKey: v1.SeccompProfileRuntimeDefault, + seccomp.DefaultProfileAnnotationKey: v1.SeccompProfileRuntimeDefault, apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault, apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault, }, @@ -428,8 +429,8 @@ func restrictedPSP(name string) *extensionsv1beta1.PodSecurityPolicy { ObjectMeta: metav1.ObjectMeta{ Name: name, Annotations: map[string]string{ - seccomp.AllowedProfilesAnnotationKey: "docker/default", - seccomp.DefaultProfileAnnotationKey: "docker/default", + seccomp.AllowedProfilesAnnotationKey: v1.SeccompProfileRuntimeDefault, + seccomp.DefaultProfileAnnotationKey: v1.SeccompProfileRuntimeDefault, apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault, apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault, }, @@ -480,7 +481,3 @@ func restrictedPSP(name string) *extensionsv1beta1.PodSecurityPolicy { func boolPtr(b bool) *bool { return &b } - -func intPtr(i int64) *int64 { - return &i -} diff --git a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/BUILD b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/BUILD index f80aeee68..217f5fd9c 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/BUILD @@ -11,7 +11,7 @@ go_library( "autoscaling_timer.go", "cluster_autoscaler_scalability.go", "cluster_size_autoscaling.go", - "custom_metrics_autoscaling.go", + "custom_metrics_stackdriver_autoscaling.go", "dns_autoscaling.go", "framework.go", "horizontal_pod_autoscaling.go", @@ -24,6 +24,7 @@ go_library( "//test/e2e/instrumentation/monitoring:go_default_library", "//test/e2e/scheduling:go_default_library", "//test/utils:go_default_library", + "//test/utils/image:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", @@ -33,7 +34,7 @@ go_library( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_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", diff --git a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/autoscaling_timer.go b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/autoscaling_timer.go index 136b2a236..ab2581f73 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/autoscaling_timer.go +++ b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/autoscaling_timer.go @@ -93,7 +93,7 @@ var _ = SIGDescribe("[Feature:ClusterSizeAutoscalingScaleUp] [Slow] Autoscaling" nodeMemoryMB := (&nodeMemoryBytes).Value() / 1024 / 1024 memRequestMB := nodeMemoryMB / 10 // Ensure each pod takes not more than 10% of node's allocatable memory. replicas := 1 - resourceConsumer := common.NewDynamicResourceConsumer("resource-consumer", f.Namespace.Name, common.KindDeployment, replicas, 0, 0, 0, cpuRequestMillis, memRequestMB, f.ClientSet, f.InternalClientset) + resourceConsumer := common.NewDynamicResourceConsumer("resource-consumer", f.Namespace.Name, common.KindDeployment, replicas, 0, 0, 0, cpuRequestMillis, memRequestMB, f.ClientSet, f.InternalClientset, f.ScalesGetter) defer resourceConsumer.CleanUp() resourceConsumer.WaitForReplicas(replicas, 1*time.Minute) // Should finish ~immediately, so 1 minute is more than enough. diff --git a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/cluster_autoscaler_scalability.go b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/cluster_autoscaler_scalability.go index a6fa9ee31..f726f2ddf 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/cluster_autoscaler_scalability.go +++ b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/cluster_autoscaler_scalability.go @@ -31,6 +31,7 @@ import ( clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" "github.com/golang/glog" . "github.com/onsi/ginkgo" @@ -347,7 +348,7 @@ var _ = framework.KubeDescribe("Cluster size autoscaler scalability [Slow]", fun timeToWait := 5 * time.Minute podsConfig := reserveMemoryRCConfig(f, "unschedulable-pod", unschedulablePodReplicas, totalMemReservation, timeToWait) framework.RunRC(*podsConfig) // Ignore error (it will occur because pods are unschedulable) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, podsConfig.Name) + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, podsConfig.Name) // Ensure that no new nodes have been added so far. Expect(framework.NumberOfReadyNodes(f.ClientSet)).To(Equal(nodeCount)) @@ -417,7 +418,7 @@ func simpleScaleUpTestWithTolerance(f *framework.Framework, config *scaleUpTestC } timeTrack(start, fmt.Sprintf("Scale up to %v", config.expectedResult.nodes)) return func() error { - return framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, config.extraPods.Name) + return framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, config.extraPods.Name) } } @@ -432,7 +433,7 @@ func reserveMemoryRCConfig(f *framework.Framework, id string, replicas, megabyte Name: id, Namespace: f.Namespace.Name, Timeout: timeout, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: replicas, MemRequest: int64(1024 * 1024 * megabytes / replicas), } @@ -492,7 +493,7 @@ func createHostPortPodsWithMemory(f *framework.Framework, id string, replicas, p Name: id, Namespace: f.Namespace.Name, Timeout: timeout, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: replicas, HostPorts: map[string]int{"port1": port}, MemRequest: request, @@ -500,7 +501,7 @@ func createHostPortPodsWithMemory(f *framework.Framework, id string, replicas, p err := framework.RunRC(*config) framework.ExpectNoError(err) return func() error { - return framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, id) + return framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, id) } } @@ -540,7 +541,7 @@ func distributeLoad(f *framework.Framework, namespace string, id string, podDist framework.ExpectNoError(framework.RunRC(*rcConfig)) framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, f.ClientSet)) return func() error { - return framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, id) + return framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, id) } } diff --git a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/cluster_size_autoscaling.go b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/cluster_size_autoscaling.go index 91f6290b0..2a7c91c31 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/cluster_size_autoscaling.go +++ b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/cluster_size_autoscaling.go @@ -30,7 +30,7 @@ import ( "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" - "k8s.io/api/scheduling/v1alpha1" + schedulerapi "k8s.io/api/scheduling/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" @@ -45,6 +45,7 @@ import ( "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/scheduling" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" "github.com/golang/glog" . "github.com/onsi/ginkgo" @@ -128,16 +129,10 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { err = enableAutoscaler("default-pool", 3, 5) framework.ExpectNoError(err) } - Expect(getNAPNodePoolsNumber()).Should(Equal(0)) } }) AfterEach(func() { - if framework.ProviderIs("gke") { - By("Remove changes introduced by NAP tests") - removeNAPNodePools() - disableAutoprovisioning() - } By(fmt.Sprintf("Restoring initial size of the cluster")) setMigSizes(originalSizes) expectedNodes := 0 @@ -168,7 +163,7 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { It("shouldn't increase cluster size if pending pod is too large [Feature:ClusterSizeAutoscalingScaleUp]", func() { By("Creating unschedulable pod") ReserveMemory(f, "memory-reservation", 1, int(1.1*float64(memAllocatableMb)), false, defaultTimeout) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "memory-reservation") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") By("Waiting for scale up hoping it won't happen") // Verify that the appropriate event was generated @@ -195,7 +190,7 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { simpleScaleUpTest := func(unready int) { ReserveMemory(f, "memory-reservation", 100, nodeCount*memAllocatableMb, false, 1*time.Second) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "memory-reservation") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") // Verify that cluster size is increased framework.ExpectNoError(WaitForClusterSizeFuncWithUnready(f.ClientSet, @@ -206,6 +201,108 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { It("should increase cluster size if pending pods are small [Feature:ClusterSizeAutoscalingScaleUp]", func() { simpleScaleUpTest(0) }) + supportedGpuTypes := []string{"nvidia-tesla-k80", "nvidia-tesla-v100", "nvidia-tesla-p100"} + for _, gpuType := range supportedGpuTypes { + gpuType := gpuType // create new variable for each iteration step + + It(fmt.Sprintf("Should scale up GPU pool from 0 [GpuType:%s] [Feature:ClusterSizeAutoscalingGpu]", gpuType), func() { + framework.SkipUnlessProviderIs("gke") + + const gpuPoolName = "gpu-pool" + addGpuNodePool(gpuPoolName, gpuType, 1, 0) + defer deleteNodePool(gpuPoolName) + + installNvidiaDriversDaemonSet() + + By("Enable autoscaler") + framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 1)) + defer disableAutoscaler(gpuPoolName, 0, 1) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) + + By("Schedule a pod which requires GPU") + framework.ExpectNoError(scheduleGpuPod(f, "gpu-pod-rc")) + + framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, + func(size int) bool { return size == nodeCount+1 }, scaleUpTimeout)) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(1)) + }) + + It(fmt.Sprintf("Should scale up GPU pool from 1 [GpuType:%s] [Feature:ClusterSizeAutoscalingGpu]", gpuType), func() { + framework.SkipUnlessProviderIs("gke") + + const gpuPoolName = "gpu-pool" + addGpuNodePool(gpuPoolName, gpuType, 1, 1) + defer deleteNodePool(gpuPoolName) + + installNvidiaDriversDaemonSet() + + By("Schedule a single pod which requires GPU") + framework.ExpectNoError(scheduleGpuPod(f, "gpu-pod-rc")) + + By("Enable autoscaler") + framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 2)) + defer disableAutoscaler(gpuPoolName, 0, 2) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(1)) + + By("Scale GPU deployment") + framework.ScaleRC(f.ClientSet, f.ScalesGetter, f.Namespace.Name, "gpu-pod-rc", 2, true) + + framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, + func(size int) bool { return size == nodeCount+2 }, scaleUpTimeout)) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(2)) + }) + + It(fmt.Sprintf("Should not scale GPU pool up if pod does not require GPUs [GpuType:%s] [Feature:ClusterSizeAutoscalingGpu]", gpuType), func() { + framework.SkipUnlessProviderIs("gke") + + const gpuPoolName = "gpu-pool" + addGpuNodePool(gpuPoolName, gpuType, 1, 0) + defer deleteNodePool(gpuPoolName) + + installNvidiaDriversDaemonSet() + + By("Enable autoscaler") + framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 1)) + defer disableAutoscaler(gpuPoolName, 0, 1) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) + + By("Schedule bunch of pods beyond point of filling default pool but do not request any GPUs") + ReserveMemory(f, "memory-reservation", 100, nodeCount*memAllocatableMb, false, 1*time.Second) + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") + // Verify that cluster size is increased + framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, + func(size int) bool { return size >= nodeCount+1 }, scaleUpTimeout)) + + // Expect gpu pool to stay intact + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) + }) + + It(fmt.Sprintf("Should scale down GPU pool from 1 [GpuType:%s] [Feature:ClusterSizeAutoscalingGpu]", gpuType), func() { + framework.SkipUnlessProviderIs("gke") + + const gpuPoolName = "gpu-pool" + addGpuNodePool(gpuPoolName, gpuType, 1, 1) + defer deleteNodePool(gpuPoolName) + + installNvidiaDriversDaemonSet() + + By("Schedule a single pod which requires GPU") + framework.ExpectNoError(scheduleGpuPod(f, "gpu-pod-rc")) + + By("Enable autoscaler") + framework.ExpectNoError(enableAutoscaler(gpuPoolName, 0, 1)) + defer disableAutoscaler(gpuPoolName, 0, 1) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(1)) + + By("Remove the only POD requiring GPU") + framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "gpu-pod-rc") + + framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, + func(size int) bool { return size == nodeCount }, scaleDownTimeout)) + Expect(len(getPoolNodes(f, gpuPoolName))).Should(Equal(0)) + }) + } + It("should increase cluster size if pending pods are small and one node is broken [Feature:ClusterSizeAutoscalingScaleUp]", func() { framework.TestUnderTemporaryNetworkFailure(c, "default", getAnyNode(c), func() { simpleScaleUpTest(1) }) @@ -222,7 +319,7 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { By("Schedule more pods than can fit and wait for cluster to scale-up") ReserveMemory(f, "memory-reservation", 100, nodeCount*memAllocatableMb, false, 1*time.Second) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "memory-reservation") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") status, err = waitForScaleUpStatus(c, func(s *scaleUpStatus) bool { return s.status == caOngoingScaleUpStatus @@ -265,8 +362,8 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { By("Reserving 0.1x more memory than the cluster holds to trigger scale up") totalMemoryReservation := int(1.1 * float64(nodeCount*memAllocatableMb+extraMemMb)) + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") ReserveMemory(f, "memory-reservation", 100, totalMemoryReservation, false, defaultTimeout) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "memory-reservation") // Verify, that cluster size is increased framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, @@ -289,7 +386,7 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { It("should increase cluster size if pods are pending due to host port conflict [Feature:ClusterSizeAutoscalingScaleUp]", func() { scheduling.CreateHostPortPods(f, "host-port", nodeCount+2, false) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "host-port") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "host-port") framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, func(size int) bool { return size >= nodeCount+2 }, scaleUpTimeout)) @@ -304,12 +401,12 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { } By("starting a pod with anti-affinity on each node") framework.ExpectNoError(runAntiAffinityPods(f, f.Namespace.Name, pods, "some-pod", labels, labels)) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "some-pod") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "some-pod") framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) By("scheduling extra pods with anti-affinity to existing ones") framework.ExpectNoError(runAntiAffinityPods(f, f.Namespace.Name, newPods, "extra-pod", labels, labels)) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "extra-pod") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "extra-pod") framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) framework.ExpectNoError(framework.WaitForReadyNodes(c, nodeCount+newPods, scaleUpTimeout)) @@ -323,14 +420,14 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { "anti-affinity": "yes", } framework.ExpectNoError(runAntiAffinityPods(f, f.Namespace.Name, pods, "some-pod", labels, labels)) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "some-pod") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "some-pod") By("waiting for all pods before triggering scale up") framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) By("creating a pod requesting EmptyDir") framework.ExpectNoError(runVolumeAntiAffinityPods(f, f.Namespace.Name, newPods, "extra-pod", labels, labels, emptyDirVolumes)) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "extra-pod") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "extra-pod") framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) framework.ExpectNoError(framework.WaitForReadyNodes(c, nodeCount+newPods, scaleUpTimeout)) @@ -359,11 +456,10 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { }, Prebind: nil, } + emptyStorageClass := "" pvcConfig := framework.PersistentVolumeClaimConfig{ - Annotations: map[string]string{ - v1.BetaStorageClassAnnotation: "", - }, - Selector: selector, + Selector: selector, + StorageClassName: &emptyStorageClass, } pv, pvc, err := framework.CreatePVPVC(c, pvConfig, pvcConfig, f.Namespace.Name, false) @@ -388,7 +484,7 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { } framework.ExpectNoError(runAntiAffinityPods(f, f.Namespace.Name, pods, "some-pod", labels, labels)) defer func() { - framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "some-pod") + framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "some-pod") glog.Infof("RC and pods not using volume deleted") }() @@ -401,7 +497,7 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { volumes := buildVolumes(pv, pvc) framework.ExpectNoError(runVolumeAntiAffinityPods(f, f.Namespace.Name, newPods, pvcPodName, labels, labels, volumes)) defer func() { - framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, pvcPodName) + framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, pvcPodName) framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) }() @@ -506,7 +602,7 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { defer removeLabels(registeredNodes) framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) - framework.ExpectNoError(framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "node-selector")) + framework.ExpectNoError(framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "node-selector")) }) It("should scale up correct target pool [Feature:ClusterSizeAutoscalingScaleUp]", func() { @@ -524,8 +620,8 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { extraPods := extraNodes + 1 totalMemoryReservation := int(float64(extraPods) * 1.5 * float64(memAllocatableMb)) By(fmt.Sprintf("Creating rc with %v pods too big to fit default-pool but fitting extra-pool", extraPods)) + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") ReserveMemory(f, "memory-reservation", extraPods, totalMemoryReservation, false, defaultTimeout) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "memory-reservation") // Apparently GKE master is restarted couple minutes after the node pool is added // reseting all the timers in scale down code. Adding 5 extra minutes to workaround @@ -663,7 +759,7 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { By("Run a scale-up test") ReserveMemory(f, "memory-reservation", 1, 100, false, 1*time.Second) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "memory-reservation") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") // Verify that cluster size is increased framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, @@ -776,7 +872,7 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { framework.TestUnderTemporaryNetworkFailure(c, "default", ntb, testFunction) } else { ReserveMemory(f, "memory-reservation", 100, nodeCount*memAllocatableMb, false, defaultTimeout) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, "memory-reservation") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, "memory-reservation") time.Sleep(scaleUpTimeout) currentNodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet) framework.Logf("Currently available nodes: %v, nodes available at the start of test: %v, disabled nodes: %v", len(currentNodes.Items), len(nodes.Items), nodesToBreakCount) @@ -792,103 +888,6 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { framework.ExpectNoError(framework.WaitForReadyNodes(c, len(nodes.Items), nodesRecoverTimeout)) }) - It("should add new node and new node pool on too big pod, scale down to 1 and scale down to 0 [Feature:ClusterSizeAutoscalingScaleWithNAP]", func() { - framework.SkipUnlessProviderIs("gke") - framework.ExpectNoError(enableAutoprovisioning("")) - By("Create first pod") - cleanupFunc1 := ReserveMemory(f, "memory-reservation1", 1, int(1.1*float64(memAllocatableMb)), true, defaultTimeout) - defer func() { - if cleanupFunc1 != nil { - cleanupFunc1() - } - }() - By("Waiting for scale up") - // Verify that cluster size increased. - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount+1 }, defaultTimeout)) - By("Check if NAP group was created") - Expect(getNAPNodePoolsNumber()).Should(Equal(1)) - By("Create second pod") - cleanupFunc2 := ReserveMemory(f, "memory-reservation2", 1, int(1.1*float64(memAllocatableMb)), true, defaultTimeout) - defer func() { - if cleanupFunc2 != nil { - cleanupFunc2() - } - }() - By("Waiting for scale up") - // Verify that cluster size increased. - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount+2 }, defaultTimeout)) - By("Delete first pod") - cleanupFunc1() - cleanupFunc1 = nil - By("Waiting for scale down to 1") - // Verify that cluster size decreased. - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount+1 }, scaleDownTimeout)) - By("Delete second pod") - cleanupFunc2() - cleanupFunc2 = nil - By("Waiting for scale down to 0") - // Verify that cluster size decreased. - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount }, scaleDownTimeout)) - By("Waiting for NAP group remove") - framework.ExpectNoError(waitTillAllNAPNodePoolsAreRemoved()) - By("Check if NAP group was removeed") - Expect(getNAPNodePoolsNumber()).Should(Equal(0)) - }) - - It("shouldn't add new node group if not needed [Feature:ClusterSizeAutoscalingScaleWithNAP]", func() { - framework.SkipUnlessProviderIs("gke") - framework.ExpectNoError(enableAutoprovisioning("")) - By("Create pods") - // Create nodesCountAfterResize+1 pods allocating 0.7 allocatable on present nodes. One more node will have to be created. - cleanupFunc := ReserveMemory(f, "memory-reservation", nodeCount+1, int(float64(nodeCount+1)*float64(0.7)*float64(memAllocatableMb)), true, scaleUpTimeout) - defer cleanupFunc() - By("Waiting for scale up") - // Verify that cluster size increased. - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size >= nodeCount+1 }, scaleUpTimeout)) - By("Check if NAP group was created hoping id didn't happen") - Expect(getNAPNodePoolsNumber()).Should(Equal(0)) - }) - - It("shouldn't scale up if cores limit too low, should scale up after limit is changed [Feature:ClusterSizeAutoscalingScaleWithNAP]", func() { - framework.SkipUnlessProviderIs("gke") - By(fmt.Sprintf("Set core limit to %d", coreCount)) - framework.ExpectNoError(enableAutoprovisioning(fmt.Sprintf(`"resource_limits":{"name":"cpu", "minimum":2, "maximum":%d}, "resource_limits":{"name":"memory", "minimum":0, "maximum":10000000}`, coreCount))) - // Create pod allocating 1.1 allocatable for present nodes. Bigger node will have to be created. - cleanupFunc := ReserveMemory(f, "memory-reservation", 1, int(1.1*float64(memAllocatableMb)), false, time.Second) - defer cleanupFunc() - By(fmt.Sprintf("Waiting for scale up hoping it won't happen, sleep for %s", scaleUpTimeout.String())) - time.Sleep(scaleUpTimeout) - // Verify that cluster size is not changed - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount }, time.Second)) - By("Change resource limits") - framework.ExpectNoError(enableAutoprovisioning(fmt.Sprintf(`"resource_limits":{"name":"cpu", "minimum":2, "maximum":%d}, "resource_limits":{"name":"memory", "minimum":0, "maximum":10000000}`, coreCount+5))) - By("Wait for scale up") - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount+1 }, scaleUpTimeout)) - By("Check if NAP group was created") - Expect(getNAPNodePoolsNumber()).Should(Equal(1)) - }) - - It("should create new node if there is no node for node selector [Feature:ClusterSizeAutoscalingScaleWithNAP]", func() { - framework.SkipUnlessProviderIs("gke") - framework.ExpectNoError(enableAutoprovisioning("")) - // Create pod allocating 0.7 allocatable for present nodes with node selector. - cleanupFunc := ReserveMemoryWithSelector(f, "memory-reservation", 1, int(0.7*float64(memAllocatableMb)), true, scaleUpTimeout, map[string]string{"test": "test"}) - defer cleanupFunc() - By("Waiting for scale up") - // Verify that cluster size increased. - framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, - func(size int) bool { return size == nodeCount+1 }, defaultTimeout)) - By("Check if NAP group was created") - Expect(getNAPNodePoolsNumber()).Should(Equal(1)) - }) - It("shouldn't scale up when expendable pod is created [Feature:ClusterSizeAutoscalingScaleUp]", func() { // TODO(krzysztof_jastrzebski): Start running this test on GKE when Pod Priority and Preemption is in beta. framework.SkipUnlessProviderIs("gce") @@ -957,6 +956,12 @@ var _ = SIGDescribe("Cluster size autoscaling [Slow]", func() { }) }) +func installNvidiaDriversDaemonSet() { + By("Add daemonset which installs nvidia drivers") + // the link differs from one in GKE documentation; discussed with @mindprince this one should be used + framework.RunKubectlOrDie("apply", "-f", "https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/daemonset.yaml") +} + func execCmd(args ...string) *exec.Cmd { glog.Infof("Executing: %s", strings.Join(args, " ")) return exec.Command(args[0], args[1:]...) @@ -974,7 +979,7 @@ func runDrainTest(f *framework.Framework, migSizes map[string]int, namespace str labelMap := map[string]string{"test_id": testID} framework.ExpectNoError(runReplicatedPodOnEachNode(f, nodes.Items, namespace, podsPerNode, "reschedulable-pods", labelMap, 0)) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, namespace, "reschedulable-pods") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, namespace, "reschedulable-pods") By("Create a PodDisruptionBudget") minAvailable := intstr.FromInt(numPods - pdbSize) @@ -1140,17 +1145,6 @@ func disableAutoscaler(nodePool string, minCount, maxCount int) error { return fmt.Errorf("autoscaler still enabled, last error: %v", finalErr) } -func isAutoprovisioningEnabled() (bool, error) { - strBody, err := getCluster("v1alpha1") - if err != nil { - return false, err - } - if strings.Contains(strBody, "\"enableNodeAutoprovisioning\": true") { - return true, nil - } - return false, nil -} - func executeHTTPRequest(method string, url string, body string) (string, error) { client := &http.Client{} req, err := http.NewRequest(method, url, strings.NewReader(body)) @@ -1170,126 +1164,6 @@ func executeHTTPRequest(method string, url string, body string) (string, error) return string(respBody), nil } -func enableAutoprovisioning(resourceLimits string) error { - By("Using API to enable autoprovisioning.") - var body string - if resourceLimits != "" { - body = fmt.Sprintf(`{"update": {"desired_cluster_autoscaling": {"enable_node_autoprovisioning": true, %s}}}`, resourceLimits) - } else { - body = `{"update": {"desired_cluster_autoscaling": {"enable_node_autoprovisioning": true, "resource_limits":{"name":"cpu", "minimum":0, "maximum":100}, "resource_limits":{"name":"memory", "minimum":0, "maximum":10000000}}}}` - } - _, err := executeHTTPRequest(http.MethodPut, getGKEClusterURL("v1alpha1"), body) - if err != nil { - glog.Errorf("Request error: %s", err.Error()) - return err - } - glog.Infof("Wait for enabling autoprovisioning.") - for start := time.Now(); time.Since(start) < gkeUpdateTimeout; time.Sleep(30 * time.Second) { - enabled, err := isAutoprovisioningEnabled() - if err != nil { - glog.Errorf("Error: %s", err.Error()) - return err - } - if enabled { - By("Autoprovisioning enabled.") - return nil - } - glog.Infof("Waiting for enabling autoprovisioning") - } - return fmt.Errorf("autoprovisioning wasn't enabled (timeout).") -} - -func disableAutoprovisioning() error { - enabled, err := isAutoprovisioningEnabled() - if err != nil { - glog.Errorf("Error: %s", err.Error()) - return err - } - if !enabled { - By("Autoprovisioning disabled.") - return nil - } - By("Using API to disable autoprovisioning.") - _, err = executeHTTPRequest(http.MethodPut, getGKEClusterURL("v1alpha1"), "{\"update\": {\"desired_cluster_autoscaling\": {}}}") - if err != nil { - glog.Errorf("Request error: %s", err.Error()) - return err - } - By("Wait for disabling autoprovisioning.") - for start := time.Now(); time.Since(start) < gkeUpdateTimeout; time.Sleep(30 * time.Second) { - enabled, err := isAutoprovisioningEnabled() - if err != nil { - glog.Errorf("Error: %s", err.Error()) - return err - } - if !enabled { - By("Autoprovisioning disabled.") - return nil - } - By("Waiting for disabling autoprovisioning") - } - return fmt.Errorf("autoprovisioning wasn't disabled (timeout).") -} - -func getNAPNodePools() ([]string, error) { - if framework.ProviderIs("gke") { - args := []string{"container", "node-pools", "list", "--cluster=" + framework.TestContext.CloudConfig.Cluster} - output, err := execCmd(getGcloudCommand(args)...).CombinedOutput() - if err != nil { - glog.Errorf("Failed to get instance groups: %v", string(output)) - return nil, err - } - re := regexp.MustCompile("nap.* ") - lines := re.FindAllString(string(output), -1) - for i, line := range lines { - lines[i] = line[:strings.Index(line, " ")] - } - return lines, nil - } else { - return nil, fmt.Errorf("provider does not support NAP") - } -} - -func removeNAPNodePools() error { - By("Remove NAP node pools") - pools, err := getNAPNodePools() - if err != nil { - return err - } - for _, pool := range pools { - By("Remove node pool: " + pool) - suffix := fmt.Sprintf("projects/%s/zones/%s/clusters/%s/nodePools/%s", - framework.TestContext.CloudConfig.ProjectID, - framework.TestContext.CloudConfig.Zone, - framework.TestContext.CloudConfig.Cluster, - pool) - _, err := executeHTTPRequest(http.MethodDelete, getGKEURL("v1alpha1", suffix), "") - if err != nil { - glog.Errorf("Request error: %s", err.Error()) - return err - } - } - err = waitTillAllNAPNodePoolsAreRemoved() - if err != nil { - glog.Errorf(fmt.Sprintf("Couldn't remove NAP groups: %s", err.Error())) - } - return err -} - -func getNAPNodePoolsNumber() int { - groups, err := getNAPNodePools() - framework.ExpectNoError(err) - return len(groups) -} - -func waitTillAllNAPNodePoolsAreRemoved() error { - By("Wait till all NAP node pools are removed") - err := wait.PollImmediate(5*time.Second, defaultTimeout, func() (bool, error) { - return getNAPNodePoolsNumber() == 0, nil - }) - return err -} - func addNodePool(name string, machineType string, numNodes int) { args := []string{"container", "node-pools", "create", name, "--quiet", "--machine-type=" + machineType, @@ -1300,20 +1174,37 @@ func addNodePool(name string, machineType string, numNodes int) { framework.ExpectNoError(err, string(output)) } +func addGpuNodePool(name string, gpuType string, gpuCount int, numNodes int) { + args := []string{"beta", "container", "node-pools", "create", name, "--quiet", + "--accelerator", "type=" + gpuType + ",count=" + strconv.Itoa(gpuCount), + "--num-nodes=" + strconv.Itoa(numNodes), + "--cluster=" + framework.TestContext.CloudConfig.Cluster} + output, err := execCmd(getGcloudCommand(args)...).CombinedOutput() + glog.Infof("Creating node-pool %s: %s", name, output) + framework.ExpectNoError(err, string(output)) +} + func deleteNodePool(name string) { glog.Infof("Deleting node pool %s", name) args := []string{"container", "node-pools", "delete", name, "--quiet", "--cluster=" + framework.TestContext.CloudConfig.Cluster} - output, err := execCmd(getGcloudCommand(args)...).CombinedOutput() - if err != nil { - glog.Infof("Error: %v", err) - } - glog.Infof("Node-pool deletion output: %s", output) + err := wait.ExponentialBackoff( + wait.Backoff{Duration: 1 * time.Minute, Factor: float64(3), Steps: 3}, + func() (bool, error) { + output, err := execCmd(getGcloudCommand(args)...).CombinedOutput() + if err != nil { + glog.Warningf("Error deleting nodegroup - error:%v, output: %s", err, output) + return false, nil + } + glog.Infof("Node-pool deletion output: %s", output) + return true, nil + }) + framework.ExpectNoError(err) } func getPoolNodes(f *framework.Framework, poolName string) []*v1.Node { nodes := make([]*v1.Node, 0, 1) - nodeList := framework.GetReadySchedulableNodesOrDie(f.ClientSet) + nodeList := framework.GetReadyNodesIncludingTaintedOrDie(f.ClientSet) for _, node := range nodeList.Items { if node.Labels[gkeNodepoolNameKey] == poolName { nodes = append(nodes, &node) @@ -1388,7 +1279,7 @@ func reserveMemory(f *framework.Framework, id string, replicas, megabytes int, e Name: id, Namespace: f.Namespace.Name, Timeout: timeout, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: replicas, MemRequest: request, NodeSelector: selector, @@ -1404,7 +1295,7 @@ func reserveMemory(f *framework.Framework, id string, replicas, megabytes int, e framework.ExpectNoError(err) } return func() error { - return framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, id) + return framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, id) } } framework.Failf("Failed to reserve memory within timeout") @@ -1617,6 +1508,26 @@ func makeNodeSchedulable(c clientset.Interface, node *v1.Node, failOnCriticalAdd return fmt.Errorf("Failed to remove taint from node in allowed number of retries") } +func scheduleGpuPod(f *framework.Framework, id string) error { + config := &testutils.RCConfig{ + Client: f.ClientSet, + InternalClient: f.InternalClientset, + Name: id, + Namespace: f.Namespace.Name, + Timeout: 3 * scaleUpTimeout, // spinning up GPU node is slow + Image: imageutils.GetPauseImageName(), + Replicas: 1, + GpuLimit: 1, + Labels: map[string]string{"requires-gpu": "yes"}, + } + + err := framework.RunRC(*config) + if err != nil { + return err + } + return nil +} + // Create an RC running a given number of pods with anti-affinity func runAntiAffinityPods(f *framework.Framework, namespace string, pods int, id string, podLabels, antiAffinityLabels map[string]string) error { config := &testutils.RCConfig{ @@ -1626,7 +1537,7 @@ func runAntiAffinityPods(f *framework.Framework, namespace string, pods int, id Name: id, Namespace: namespace, Timeout: scaleUpTimeout, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: pods, Labels: podLabels, } @@ -1650,7 +1561,7 @@ func runVolumeAntiAffinityPods(f *framework.Framework, namespace string, pods in Name: id, Namespace: namespace, Timeout: scaleUpTimeout, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: pods, Labels: podLabels, } @@ -1731,7 +1642,7 @@ func runReplicatedPodOnEachNode(f *framework.Framework, nodes []v1.Node, namespa Name: id, Namespace: namespace, Timeout: defaultTimeout, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: 0, Labels: labels, MemRequest: memRequest, @@ -1790,7 +1701,7 @@ func runReplicatedPodOnEachNode(f *framework.Framework, nodes []v1.Node, namespa func runReplicatedPodOnEachNodeWithCleanup(f *framework.Framework, nodes []v1.Node, namespace string, podsPerNode int, id string, labels map[string]string, memRequest int64) (func(), error) { err := runReplicatedPodOnEachNode(f, nodes, namespace, podsPerNode, id, labels, memRequest) return func() { - framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, namespace, id) + framework.DeleteRCAndWaitForGC(f.ClientSet, namespace, id) }, err } @@ -1853,7 +1764,7 @@ type scaleUpStatus struct { // Try to get timestamp from status. // Status configmap is not parsing-friendly, so evil regexpery follows. func getStatusTimestamp(status string) (time.Time, error) { - timestampMatcher, err := regexp.Compile("Cluster-autoscaler status at \\s*([0-9\\-]+ [0-9]+:[0-9]+:[0-9]+\\.[0-9]+ \\+[0-9]+ [A-Za-z]+):") + timestampMatcher, err := regexp.Compile("Cluster-autoscaler status at \\s*([0-9\\-]+ [0-9]+:[0-9]+:[0-9]+\\.[0-9]+ \\+[0-9]+ [A-Za-z]+)") if err != nil { return time.Time{}, err } @@ -2006,13 +1917,13 @@ func createPriorityClasses(f *framework.Framework) func() { highPriorityClassName: 1000, } for className, priority := range priorityClasses { - _, err := f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: className}, Value: priority}) + _, err := f.ClientSet.SchedulingV1beta1().PriorityClasses().Create(&schedulerapi.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: className}, Value: priority}) Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true)) } return func() { for className := range priorityClasses { - f.ClientSet.SchedulingV1alpha1().PriorityClasses().Delete(className, nil) + f.ClientSet.SchedulingV1beta1().PriorityClasses().Delete(className, nil) } } } diff --git a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/custom_metrics_autoscaling.go b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/custom_metrics_autoscaling.go deleted file mode 100644 index 5d002bf50..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/custom_metrics_autoscaling.go +++ /dev/null @@ -1,271 +0,0 @@ -/* -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 autoscaling - -import ( - "context" - "time" - - gcm "google.golang.org/api/monitoring/v3" - as "k8s.io/api/autoscaling/v2beta1" - corev1 "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/wait" - clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/test/e2e/framework" - "k8s.io/kubernetes/test/e2e/instrumentation/monitoring" - - . "github.com/onsi/ginkgo" - "golang.org/x/oauth2/google" -) - -const ( - stackdriverExporterDeployment = "stackdriver-exporter-deployment" - dummyDeploymentName = "dummy-deployment" - stackdriverExporterPod = "stackdriver-exporter-pod" -) - -var _ = SIGDescribe("[HPA] Horizontal pod autoscaling (scale resource: Custom Metrics from Stackdriver)", func() { - BeforeEach(func() { - framework.SkipUnlessProviderIs("gce", "gke") - }) - - f := framework.NewDefaultFramework("horizontal-pod-autoscaling") - - It("should scale down with Custom Metric of type Pod from Stackdriver [Feature:CustomMetricsAutoscaling]", func() { - initialReplicas := 2 - scaledReplicas := 1 - // metric should cause scale down - metricValue := int64(100) - metricTarget := 2 * metricValue - deployment := monitoring.SimpleStackdriverExporterDeployment(stackdriverExporterDeployment, f.Namespace.ObjectMeta.Name, int32(initialReplicas), metricValue) - customMetricTest(f, f.ClientSet, simplePodsHPA(f.Namespace.ObjectMeta.Name, metricTarget), deployment, nil, initialReplicas, scaledReplicas) - }) - - It("should scale down with Custom Metric of type Object from Stackdriver [Feature:CustomMetricsAutoscaling]", func() { - initialReplicas := 2 - scaledReplicas := 1 - // metric should cause scale down - metricValue := int64(100) - metricTarget := 2 * metricValue - deployment := monitoring.SimpleStackdriverExporterDeployment(dummyDeploymentName, f.Namespace.ObjectMeta.Name, int32(initialReplicas), metricValue) - pod := monitoring.StackdriverExporterPod(stackdriverExporterPod, f.Namespace.Name, stackdriverExporterPod, monitoring.CustomMetricName, metricValue) - customMetricTest(f, f.ClientSet, objectHPA(f.Namespace.ObjectMeta.Name, metricTarget), deployment, pod, initialReplicas, scaledReplicas) - }) - - It("should scale down with Custom Metric of type Pod from Stackdriver with Prometheus [Feature:CustomMetricsAutoscaling]", func() { - initialReplicas := 2 - scaledReplicas := 1 - // metric should cause scale down - metricValue := int64(100) - metricTarget := 2 * metricValue - deployment := monitoring.PrometheusExporterDeployment(stackdriverExporterDeployment, f.Namespace.ObjectMeta.Name, int32(initialReplicas), metricValue) - customMetricTest(f, f.ClientSet, simplePodsHPA(f.Namespace.ObjectMeta.Name, metricTarget), deployment, nil, initialReplicas, scaledReplicas) - }) - - It("should scale up with two metrics of type Pod from Stackdriver [Feature:CustomMetricsAutoscaling]", func() { - initialReplicas := 1 - scaledReplicas := 3 - // metric 1 would cause a scale down, if not for metric 2 - metric1Value := int64(100) - metric1Target := 2 * metric1Value - // metric2 should cause a scale up - metric2Value := int64(200) - metric2Target := int64(0.5 * float64(metric2Value)) - containers := []monitoring.CustomMetricContainerSpec{ - { - Name: "stackdriver-exporter-metric1", - MetricName: "metric1", - MetricValue: metric1Value, - }, - { - Name: "stackdriver-exporter-metric2", - MetricName: "metric2", - MetricValue: metric2Value, - }, - } - metricTargets := map[string]int64{"metric1": metric1Target, "metric2": metric2Target} - deployment := monitoring.StackdriverExporterDeployment(stackdriverExporterDeployment, f.Namespace.ObjectMeta.Name, int32(initialReplicas), containers) - customMetricTest(f, f.ClientSet, podsHPA(f.Namespace.ObjectMeta.Name, stackdriverExporterDeployment, metricTargets), deployment, nil, initialReplicas, scaledReplicas) - }) -}) - -func customMetricTest(f *framework.Framework, kubeClient clientset.Interface, hpa *as.HorizontalPodAutoscaler, - deployment *extensions.Deployment, pod *corev1.Pod, initialReplicas, scaledReplicas int) { - projectId := framework.TestContext.CloudConfig.ProjectID - - ctx := context.Background() - client, err := google.DefaultClient(ctx, gcm.CloudPlatformScope) - - // Hack for running tests locally, needed to authenticate in Stackdriver - // If this is your use case, create application default credentials: - // $ gcloud auth application-default login - // and uncomment following lines: - /* - ts, err := google.DefaultTokenSource(oauth2.NoContext) - framework.Logf("Couldn't get application default credentials, %v", err) - if err != nil { - framework.Failf("Error accessing application default credentials, %v", err) - } - client := oauth2.NewClient(oauth2.NoContext, ts) - */ - - gcmService, err := gcm.New(client) - if err != nil { - framework.Failf("Failed to create gcm service, %v", err) - } - - // Set up a cluster: create a custom metric and set up k8s-sd adapter - err = monitoring.CreateDescriptors(gcmService, projectId) - if err != nil { - framework.Failf("Failed to create metric descriptor: %v", err) - } - defer monitoring.CleanupDescriptors(gcmService, projectId) - - err = monitoring.CreateAdapter() - if err != nil { - framework.Failf("Failed to set up: %v", err) - } - defer monitoring.CleanupAdapter() - - // Run application that exports the metric - err = createDeploymentToScale(f, kubeClient, deployment, pod) - if err != nil { - framework.Failf("Failed to create stackdriver-exporter pod: %v", err) - } - defer cleanupDeploymentsToScale(f, kubeClient, deployment, pod) - - // Wait for the deployment to run - waitForReplicas(deployment.ObjectMeta.Name, f.Namespace.ObjectMeta.Name, kubeClient, 15*time.Minute, initialReplicas) - - // Autoscale the deployment - _, err = kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers(f.Namespace.ObjectMeta.Name).Create(hpa) - if err != nil { - framework.Failf("Failed to create HPA: %v", err) - } - - waitForReplicas(deployment.ObjectMeta.Name, f.Namespace.ObjectMeta.Name, kubeClient, 15*time.Minute, scaledReplicas) -} - -func createDeploymentToScale(f *framework.Framework, cs clientset.Interface, deployment *extensions.Deployment, pod *corev1.Pod) error { - if deployment != nil { - _, err := cs.Extensions().Deployments(f.Namespace.ObjectMeta.Name).Create(deployment) - if err != nil { - return err - } - } - if pod != nil { - _, err := cs.CoreV1().Pods(f.Namespace.ObjectMeta.Name).Create(pod) - if err != nil { - return err - } - } - return nil -} - -func cleanupDeploymentsToScale(f *framework.Framework, cs clientset.Interface, deployment *extensions.Deployment, pod *corev1.Pod) { - if deployment != nil { - _ = cs.Extensions().Deployments(f.Namespace.ObjectMeta.Name).Delete(deployment.ObjectMeta.Name, &metav1.DeleteOptions{}) - } - if pod != nil { - _ = cs.CoreV1().Pods(f.Namespace.ObjectMeta.Name).Delete(pod.ObjectMeta.Name, &metav1.DeleteOptions{}) - } -} - -func simplePodsHPA(namespace string, metricTarget int64) *as.HorizontalPodAutoscaler { - return podsHPA(namespace, stackdriverExporterDeployment, map[string]int64{monitoring.CustomMetricName: metricTarget}) -} - -func podsHPA(namespace string, deploymentName string, metricTargets map[string]int64) *as.HorizontalPodAutoscaler { - var minReplicas int32 = 1 - metrics := []as.MetricSpec{} - for metric, target := range metricTargets { - metrics = append(metrics, as.MetricSpec{ - Type: as.PodsMetricSourceType, - Pods: &as.PodsMetricSource{ - MetricName: metric, - TargetAverageValue: *resource.NewQuantity(target, resource.DecimalSI), - }, - }) - } - return &as.HorizontalPodAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: "custom-metrics-pods-hpa", - Namespace: namespace, - }, - Spec: as.HorizontalPodAutoscalerSpec{ - Metrics: metrics, - MaxReplicas: 3, - MinReplicas: &minReplicas, - ScaleTargetRef: as.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", - Kind: "Deployment", - Name: deploymentName, - }, - }, - } -} - -func objectHPA(namespace string, metricTarget int64) *as.HorizontalPodAutoscaler { - var minReplicas int32 = 1 - return &as.HorizontalPodAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: "custom-metrics-objects-hpa", - Namespace: namespace, - }, - Spec: as.HorizontalPodAutoscalerSpec{ - Metrics: []as.MetricSpec{ - { - Type: as.ObjectMetricSourceType, - Object: &as.ObjectMetricSource{ - MetricName: monitoring.CustomMetricName, - Target: as.CrossVersionObjectReference{ - Kind: "Pod", - Name: stackdriverExporterPod, - }, - TargetValue: *resource.NewQuantity(metricTarget, resource.DecimalSI), - }, - }, - }, - MaxReplicas: 3, - MinReplicas: &minReplicas, - ScaleTargetRef: as.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", - Kind: "Deployment", - Name: dummyDeploymentName, - }, - }, - } -} - -func waitForReplicas(deploymentName, namespace string, cs clientset.Interface, timeout time.Duration, desiredReplicas int) { - interval := 20 * time.Second - err := wait.PollImmediate(interval, timeout, func() (bool, error) { - deployment, err := cs.ExtensionsV1beta1().Deployments(namespace).Get(deploymentName, metav1.GetOptions{}) - if err != nil { - framework.Failf("Failed to get replication controller %s: %v", deployment, err) - } - replicas := int(deployment.Status.ReadyReplicas) - framework.Logf("waiting for %d replicas (current: %d)", desiredReplicas, replicas) - return replicas == desiredReplicas, nil // Expected number of replicas found. Exit. - }) - if err != nil { - framework.Failf("Timeout waiting %v for %v replicas", timeout, desiredReplicas) - } -} diff --git a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/custom_metrics_stackdriver_autoscaling.go b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/custom_metrics_stackdriver_autoscaling.go new file mode 100644 index 000000000..5277cb9c5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/custom_metrics_stackdriver_autoscaling.go @@ -0,0 +1,451 @@ +/* +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 autoscaling + +import ( + "context" + "math" + "time" + + gcm "google.golang.org/api/monitoring/v3" + as "k8s.io/api/autoscaling/v2beta1" + corev1 "k8s.io/api/core/v1" + extensions "k8s.io/api/extensions/v1beta1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/instrumentation/monitoring" + + . "github.com/onsi/ginkgo" + "golang.org/x/oauth2/google" +) + +const ( + stackdriverExporterDeployment = "stackdriver-exporter-deployment" + dummyDeploymentName = "dummy-deployment" + stackdriverExporterPod = "stackdriver-exporter-pod" + externalMetricValue = int64(85) +) + +var _ = SIGDescribe("[HPA] Horizontal pod autoscaling (scale resource: Custom Metrics from Stackdriver)", func() { + BeforeEach(func() { + framework.SkipUnlessProviderIs("gce", "gke") + }) + + f := framework.NewDefaultFramework("horizontal-pod-autoscaling") + + It("should scale down with Custom Metric of type Pod from Stackdriver [Feature:CustomMetricsAutoscaling]", func() { + initialReplicas := 2 + // metric should cause scale down + metricValue := int64(100) + metricTarget := 2 * metricValue + tc := CustomMetricTestCase{ + framework: f, + kubeClient: f.ClientSet, + initialReplicas: initialReplicas, + scaledReplicas: 1, + deployment: monitoring.SimpleStackdriverExporterDeployment(stackdriverExporterDeployment, f.Namespace.ObjectMeta.Name, int32(initialReplicas), metricValue), + hpa: simplePodsHPA(f.Namespace.ObjectMeta.Name, metricTarget)} + tc.Run() + }) + + It("should scale down with Custom Metric of type Object from Stackdriver [Feature:CustomMetricsAutoscaling]", func() { + initialReplicas := 2 + // metric should cause scale down + metricValue := int64(100) + metricTarget := 2 * metricValue + tc := CustomMetricTestCase{ + framework: f, + kubeClient: f.ClientSet, + initialReplicas: initialReplicas, + scaledReplicas: 1, + // Metric exported by deployment is ignored + deployment: monitoring.SimpleStackdriverExporterDeployment(dummyDeploymentName, f.Namespace.ObjectMeta.Name, int32(initialReplicas), 0 /* ignored */), + pod: monitoring.StackdriverExporterPod(stackdriverExporterPod, f.Namespace.Name, stackdriverExporterPod, monitoring.CustomMetricName, metricValue), + hpa: objectHPA(f.Namespace.ObjectMeta.Name, metricTarget)} + tc.Run() + }) + + It("should scale down with External Metric with target value from Stackdriver [Feature:CustomMetricsAutoscaling]", func() { + initialReplicas := 2 + // metric should cause scale down + metricValue := externalMetricValue + metricTarget := 2 * metricValue + metricTargets := map[string]externalMetricTarget{ + "target": { + value: metricTarget, + isAverage: false, + }, + } + tc := CustomMetricTestCase{ + framework: f, + kubeClient: f.ClientSet, + initialReplicas: initialReplicas, + scaledReplicas: 1, + // Metric exported by deployment is ignored + deployment: monitoring.SimpleStackdriverExporterDeployment(dummyDeploymentName, f.Namespace.ObjectMeta.Name, int32(initialReplicas), 0 /* ignored */), + pod: monitoring.StackdriverExporterPod(stackdriverExporterPod, f.Namespace.Name, stackdriverExporterPod, "target", metricValue), + hpa: externalHPA(f.Namespace.ObjectMeta.Name, metricTargets)} + tc.Run() + }) + + It("should scale down with External Metric with target average value from Stackdriver [Feature:CustomMetricsAutoscaling]", func() { + initialReplicas := 2 + // metric should cause scale down + metricValue := externalMetricValue + metricAverageTarget := 2 * metricValue + metricTargets := map[string]externalMetricTarget{ + "target_average": { + value: metricAverageTarget, + isAverage: true, + }, + } + tc := CustomMetricTestCase{ + framework: f, + kubeClient: f.ClientSet, + initialReplicas: initialReplicas, + scaledReplicas: 1, + // Metric exported by deployment is ignored + deployment: monitoring.SimpleStackdriverExporterDeployment(dummyDeploymentName, f.Namespace.ObjectMeta.Name, int32(initialReplicas), 0 /* ignored */), + pod: monitoring.StackdriverExporterPod(stackdriverExporterPod, f.Namespace.Name, stackdriverExporterPod, "target_average", externalMetricValue), + hpa: externalHPA(f.Namespace.ObjectMeta.Name, metricTargets)} + tc.Run() + }) + + It("should scale down with Custom Metric of type Pod from Stackdriver with Prometheus [Feature:CustomMetricsAutoscaling]", func() { + initialReplicas := 2 + // metric should cause scale down + metricValue := int64(100) + metricTarget := 2 * metricValue + tc := CustomMetricTestCase{ + framework: f, + kubeClient: f.ClientSet, + initialReplicas: initialReplicas, + scaledReplicas: 1, + deployment: monitoring.PrometheusExporterDeployment(stackdriverExporterDeployment, f.Namespace.ObjectMeta.Name, int32(initialReplicas), metricValue), + hpa: simplePodsHPA(f.Namespace.ObjectMeta.Name, metricTarget)} + tc.Run() + }) + + It("should scale up with two metrics of type Pod from Stackdriver [Feature:CustomMetricsAutoscaling]", func() { + initialReplicas := 1 + // metric 1 would cause a scale down, if not for metric 2 + metric1Value := int64(100) + metric1Target := 2 * metric1Value + // metric2 should cause a scale up + metric2Value := int64(200) + metric2Target := int64(0.5 * float64(metric2Value)) + containers := []monitoring.CustomMetricContainerSpec{ + { + Name: "stackdriver-exporter-metric1", + MetricName: "metric1", + MetricValue: metric1Value, + }, + { + Name: "stackdriver-exporter-metric2", + MetricName: "metric2", + MetricValue: metric2Value, + }, + } + metricTargets := map[string]int64{"metric1": metric1Target, "metric2": metric2Target} + tc := CustomMetricTestCase{ + framework: f, + kubeClient: f.ClientSet, + initialReplicas: initialReplicas, + scaledReplicas: 3, + deployment: monitoring.StackdriverExporterDeployment(stackdriverExporterDeployment, f.Namespace.ObjectMeta.Name, int32(initialReplicas), containers), + hpa: podsHPA(f.Namespace.ObjectMeta.Name, stackdriverExporterDeployment, metricTargets)} + tc.Run() + }) + + It("should scale up with two External metrics from Stackdriver [Feature:CustomMetricsAutoscaling]", func() { + initialReplicas := 1 + // metric 1 would cause a scale down, if not for metric 2 + metric1Value := externalMetricValue + metric1Target := 2 * metric1Value + // metric2 should cause a scale up + metric2Value := externalMetricValue + metric2Target := int64(math.Ceil(0.5 * float64(metric2Value))) + metricTargets := map[string]externalMetricTarget{ + "external_metric_1": { + value: metric1Target, + isAverage: false, + }, + "external_metric_2": { + value: metric2Target, + isAverage: false, + }, + } + containers := []monitoring.CustomMetricContainerSpec{ + { + Name: "stackdriver-exporter-metric1", + MetricName: "external_metric_1", + MetricValue: metric1Value, + }, + { + Name: "stackdriver-exporter-metric2", + MetricName: "external_metric_2", + MetricValue: metric2Value, + }, + } + tc := CustomMetricTestCase{ + framework: f, + kubeClient: f.ClientSet, + initialReplicas: initialReplicas, + scaledReplicas: 3, + deployment: monitoring.StackdriverExporterDeployment(dummyDeploymentName, f.Namespace.ObjectMeta.Name, int32(initialReplicas), containers), + hpa: externalHPA(f.Namespace.ObjectMeta.Name, metricTargets)} + tc.Run() + }) +}) + +type CustomMetricTestCase struct { + framework *framework.Framework + hpa *as.HorizontalPodAutoscaler + kubeClient clientset.Interface + deployment *extensions.Deployment + pod *corev1.Pod + initialReplicas int + scaledReplicas int +} + +func (tc *CustomMetricTestCase) Run() { + projectId := framework.TestContext.CloudConfig.ProjectID + + ctx := context.Background() + client, err := google.DefaultClient(ctx, gcm.CloudPlatformScope) + + // Hack for running tests locally, needed to authenticate in Stackdriver + // If this is your use case, create application default credentials: + // $ gcloud auth application-default login + // and uncomment following lines: + /* + ts, err := google.DefaultTokenSource(oauth2.NoContext) + framework.Logf("Couldn't get application default credentials, %v", err) + if err != nil { + framework.Failf("Error accessing application default credentials, %v", err) + } + client := oauth2.NewClient(oauth2.NoContext, ts) + */ + + gcmService, err := gcm.New(client) + if err != nil { + framework.Failf("Failed to create gcm service, %v", err) + } + + // Set up a cluster: create a custom metric and set up k8s-sd adapter + err = monitoring.CreateDescriptors(gcmService, projectId) + if err != nil { + framework.Failf("Failed to create metric descriptor: %v", err) + } + defer monitoring.CleanupDescriptors(gcmService, projectId) + + err = monitoring.CreateAdapter(monitoring.AdapterDefault) + if err != nil { + framework.Failf("Failed to set up: %v", err) + } + defer monitoring.CleanupAdapter(monitoring.AdapterDefault) + + // Run application that exports the metric + err = createDeploymentToScale(tc.framework, tc.kubeClient, tc.deployment, tc.pod) + if err != nil { + framework.Failf("Failed to create stackdriver-exporter pod: %v", err) + } + defer cleanupDeploymentsToScale(tc.framework, tc.kubeClient, tc.deployment, tc.pod) + + // Wait for the deployment to run + waitForReplicas(tc.deployment.ObjectMeta.Name, tc.framework.Namespace.ObjectMeta.Name, tc.kubeClient, 15*time.Minute, tc.initialReplicas) + + // Autoscale the deployment + _, err = tc.kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers(tc.framework.Namespace.ObjectMeta.Name).Create(tc.hpa) + if err != nil { + framework.Failf("Failed to create HPA: %v", err) + } + defer tc.kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers(tc.framework.Namespace.ObjectMeta.Name).Delete(tc.hpa.ObjectMeta.Name, &metav1.DeleteOptions{}) + + waitForReplicas(tc.deployment.ObjectMeta.Name, tc.framework.Namespace.ObjectMeta.Name, tc.kubeClient, 15*time.Minute, tc.scaledReplicas) +} + +func createDeploymentToScale(f *framework.Framework, cs clientset.Interface, deployment *extensions.Deployment, pod *corev1.Pod) error { + if deployment != nil { + _, err := cs.Extensions().Deployments(f.Namespace.ObjectMeta.Name).Create(deployment) + if err != nil { + return err + } + } + if pod != nil { + _, err := cs.CoreV1().Pods(f.Namespace.ObjectMeta.Name).Create(pod) + if err != nil { + return err + } + } + return nil +} + +func cleanupDeploymentsToScale(f *framework.Framework, cs clientset.Interface, deployment *extensions.Deployment, pod *corev1.Pod) { + if deployment != nil { + _ = cs.Extensions().Deployments(f.Namespace.ObjectMeta.Name).Delete(deployment.ObjectMeta.Name, &metav1.DeleteOptions{}) + } + if pod != nil { + _ = cs.CoreV1().Pods(f.Namespace.ObjectMeta.Name).Delete(pod.ObjectMeta.Name, &metav1.DeleteOptions{}) + } +} + +func simplePodsHPA(namespace string, metricTarget int64) *as.HorizontalPodAutoscaler { + return podsHPA(namespace, stackdriverExporterDeployment, map[string]int64{monitoring.CustomMetricName: metricTarget}) +} + +func podsHPA(namespace string, deploymentName string, metricTargets map[string]int64) *as.HorizontalPodAutoscaler { + var minReplicas int32 = 1 + metrics := []as.MetricSpec{} + for metric, target := range metricTargets { + metrics = append(metrics, as.MetricSpec{ + Type: as.PodsMetricSourceType, + Pods: &as.PodsMetricSource{ + MetricName: metric, + TargetAverageValue: *resource.NewQuantity(target, resource.DecimalSI), + }, + }) + } + return &as.HorizontalPodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Name: "custom-metrics-pods-hpa", + Namespace: namespace, + }, + Spec: as.HorizontalPodAutoscalerSpec{ + Metrics: metrics, + MaxReplicas: 3, + MinReplicas: &minReplicas, + ScaleTargetRef: as.CrossVersionObjectReference{ + APIVersion: "extensions/v1beta1", + Kind: "Deployment", + Name: deploymentName, + }, + }, + } +} + +func objectHPA(namespace string, metricTarget int64) *as.HorizontalPodAutoscaler { + var minReplicas int32 = 1 + return &as.HorizontalPodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Name: "custom-metrics-objects-hpa", + Namespace: namespace, + }, + Spec: as.HorizontalPodAutoscalerSpec{ + Metrics: []as.MetricSpec{ + { + Type: as.ObjectMetricSourceType, + Object: &as.ObjectMetricSource{ + MetricName: monitoring.CustomMetricName, + Target: as.CrossVersionObjectReference{ + Kind: "Pod", + Name: stackdriverExporterPod, + }, + TargetValue: *resource.NewQuantity(metricTarget, resource.DecimalSI), + }, + }, + }, + MaxReplicas: 3, + MinReplicas: &minReplicas, + ScaleTargetRef: as.CrossVersionObjectReference{ + APIVersion: "extensions/v1beta1", + Kind: "Deployment", + Name: dummyDeploymentName, + }, + }, + } +} + +type externalMetricTarget struct { + value int64 + isAverage bool +} + +func externalHPA(namespace string, metricTargets map[string]externalMetricTarget) *as.HorizontalPodAutoscaler { + var minReplicas int32 = 1 + metricSpecs := []as.MetricSpec{} + selector := &metav1.LabelSelector{ + MatchLabels: map[string]string{"resource.type": "gke_container"}, + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "resource.labels.namespace_id", + Operator: metav1.LabelSelectorOpIn, + // TODO(bskiba): change default to real namespace name once it is available + // from Stackdriver. + Values: []string{"default", "dummy"}, + }, + { + Key: "resource.labels.pod_id", + Operator: metav1.LabelSelectorOpExists, + Values: []string{}, + }, + }, + } + for metric, target := range metricTargets { + var metricSpec as.MetricSpec + metricSpec = as.MetricSpec{ + Type: as.ExternalMetricSourceType, + External: &as.ExternalMetricSource{ + MetricName: "custom.googleapis.com|" + metric, + MetricSelector: selector, + }, + } + if target.isAverage { + metricSpec.External.TargetAverageValue = resource.NewQuantity(target.value, resource.DecimalSI) + } else { + metricSpec.External.TargetValue = resource.NewQuantity(target.value, resource.DecimalSI) + } + metricSpecs = append(metricSpecs, metricSpec) + } + hpa := &as.HorizontalPodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Name: "custom-metrics-external-hpa", + Namespace: namespace, + }, + Spec: as.HorizontalPodAutoscalerSpec{ + Metrics: metricSpecs, + MaxReplicas: 3, + MinReplicas: &minReplicas, + ScaleTargetRef: as.CrossVersionObjectReference{ + APIVersion: "extensions/v1beta1", + Kind: "Deployment", + Name: dummyDeploymentName, + }, + }, + } + + return hpa +} + +func waitForReplicas(deploymentName, namespace string, cs clientset.Interface, timeout time.Duration, desiredReplicas int) { + interval := 20 * time.Second + err := wait.PollImmediate(interval, timeout, func() (bool, error) { + deployment, err := cs.ExtensionsV1beta1().Deployments(namespace).Get(deploymentName, metav1.GetOptions{}) + if err != nil { + framework.Failf("Failed to get replication controller %s: %v", deployment, err) + } + replicas := int(deployment.Status.ReadyReplicas) + framework.Logf("waiting for %d replicas (current: %d)", desiredReplicas, replicas) + return replicas == desiredReplicas, nil // Expected number of replicas found. Exit. + }) + if err != nil { + framework.Failf("Timeout waiting %v for %v replicas", timeout, desiredReplicas) + } +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/horizontal_pod_autoscaling.go b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/horizontal_pod_autoscaling.go index 9dd853ed6..4213882f6 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/autoscaling/horizontal_pod_autoscaling.go +++ b/vendor/k8s.io/kubernetes/test/e2e/autoscaling/horizontal_pod_autoscaling.go @@ -116,7 +116,7 @@ type HPAScaleTest struct { // TODO The use of 3 states is arbitrary, we could eventually make this test handle "n" states once this test stabilizes. func (scaleTest *HPAScaleTest) run(name string, kind schema.GroupVersionKind, rc *common.ResourceConsumer, f *framework.Framework) { const timeToWait = 15 * time.Minute - rc = common.NewDynamicResourceConsumer(name, f.Namespace.Name, kind, int(scaleTest.initPods), int(scaleTest.totalInitialCPUUsage), 0, 0, scaleTest.perPodCPURequest, 200, f.ClientSet, f.InternalClientset) + rc = common.NewDynamicResourceConsumer(name, f.Namespace.Name, kind, int(scaleTest.initPods), int(scaleTest.totalInitialCPUUsage), 0, 0, scaleTest.perPodCPURequest, 200, f.ClientSet, f.InternalClientset, f.ScalesGetter) defer rc.CleanUp() hpa := common.CreateCPUHorizontalPodAutoscaler(rc, scaleTest.targetCPUUtilizationPercent, scaleTest.minPods, scaleTest.maxPods) defer common.DeleteHorizontalPodAutoscaler(rc, hpa.Name) diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/BUILD b/vendor/k8s.io/kubernetes/test/e2e/common/BUILD index a80fab46b..825706adc 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/common/BUILD @@ -34,10 +34,8 @@ go_library( ], importpath = "k8s.io/kubernetes/test/e2e/common", deps = [ - "//pkg/api/testapi:go_default_library", "//pkg/api/v1/pod:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/conditions:go_default_library", "//pkg/kubelet:go_default_library", @@ -66,6 +64,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/scale:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/autoscaling_utils.go b/vendor/k8s.io/kubernetes/test/e2e/common/autoscaling_utils.go index 3efbf8d33..edd8a5370 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/autoscaling_utils.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/autoscaling_utils.go @@ -36,6 +36,7 @@ import ( testutils "k8s.io/kubernetes/test/utils" . "github.com/onsi/ginkgo" + scaleclient "k8s.io/client-go/scale" imageutils "k8s.io/kubernetes/test/utils/image" ) @@ -86,6 +87,7 @@ type ResourceConsumer struct { nsName string clientSet clientset.Interface internalClientset *internalclientset.Clientset + scaleClient scaleclient.ScalesGetter cpu chan int mem chan int customMetric chan int @@ -104,15 +106,20 @@ func GetResourceConsumerImage() string { return resourceConsumerImage } -func NewDynamicResourceConsumer(name, nsName string, kind schema.GroupVersionKind, replicas, initCPUTotal, initMemoryTotal, initCustomMetric int, cpuLimit, memLimit int64, clientset clientset.Interface, internalClientset *internalclientset.Clientset) *ResourceConsumer { +func NewDynamicResourceConsumer(name, nsName string, kind schema.GroupVersionKind, replicas, initCPUTotal, initMemoryTotal, initCustomMetric int, cpuLimit, memLimit int64, clientset clientset.Interface, internalClientset *internalclientset.Clientset, scaleClient scaleclient.ScalesGetter) *ResourceConsumer { return newResourceConsumer(name, nsName, kind, replicas, initCPUTotal, initMemoryTotal, initCustomMetric, dynamicConsumptionTimeInSeconds, - dynamicRequestSizeInMillicores, dynamicRequestSizeInMegabytes, dynamicRequestSizeCustomMetric, cpuLimit, memLimit, clientset, internalClientset) + dynamicRequestSizeInMillicores, dynamicRequestSizeInMegabytes, dynamicRequestSizeCustomMetric, cpuLimit, memLimit, clientset, internalClientset, scaleClient, nil, nil) } // TODO this still defaults to replication controller -func NewStaticResourceConsumer(name, nsName string, replicas, initCPUTotal, initMemoryTotal, initCustomMetric int, cpuLimit, memLimit int64, clientset clientset.Interface, internalClientset *internalclientset.Clientset) *ResourceConsumer { +func NewStaticResourceConsumer(name, nsName string, replicas, initCPUTotal, initMemoryTotal, initCustomMetric int, cpuLimit, memLimit int64, clientset clientset.Interface, internalClientset *internalclientset.Clientset, scaleClient scaleclient.ScalesGetter) *ResourceConsumer { return newResourceConsumer(name, nsName, KindRC, replicas, initCPUTotal, initMemoryTotal, initCustomMetric, staticConsumptionTimeInSeconds, - initCPUTotal/replicas, initMemoryTotal/replicas, initCustomMetric/replicas, cpuLimit, memLimit, clientset, internalClientset) + initCPUTotal/replicas, initMemoryTotal/replicas, initCustomMetric/replicas, cpuLimit, memLimit, clientset, internalClientset, scaleClient, nil, nil) +} + +func NewMetricExporter(name, nsName string, podAnnotations, serviceAnnotations map[string]string, metricValue int, clientset clientset.Interface, internalClientset *internalclientset.Clientset, scaleClient scaleclient.ScalesGetter) *ResourceConsumer { + return newResourceConsumer(name, nsName, KindDeployment, 1, 0, 0, metricValue, dynamicConsumptionTimeInSeconds, + dynamicRequestSizeInMillicores, dynamicRequestSizeInMegabytes, dynamicRequestSizeCustomMetric, 100, 100, clientset, internalClientset, scaleClient, podAnnotations, serviceAnnotations) } /* @@ -123,9 +130,14 @@ memLimit argument is in megabytes, memLimit is a maximum amount of memory that c cpuLimit argument is in millicores, cpuLimit is a maximum amount of cpu that can be consumed by a single pod */ func newResourceConsumer(name, nsName string, kind schema.GroupVersionKind, replicas, initCPUTotal, initMemoryTotal, initCustomMetric, consumptionTimeInSeconds, requestSizeInMillicores, - requestSizeInMegabytes int, requestSizeCustomMetric int, cpuLimit, memLimit int64, clientset clientset.Interface, internalClientset *internalclientset.Clientset) *ResourceConsumer { - - runServiceAndWorkloadForResourceConsumer(clientset, internalClientset, nsName, name, kind, replicas, cpuLimit, memLimit) + requestSizeInMegabytes int, requestSizeCustomMetric int, cpuLimit, memLimit int64, clientset clientset.Interface, internalClientset *internalclientset.Clientset, scaleClient scaleclient.ScalesGetter, podAnnotations, serviceAnnotations map[string]string) *ResourceConsumer { + if podAnnotations == nil { + podAnnotations = make(map[string]string) + } + if serviceAnnotations == nil { + serviceAnnotations = make(map[string]string) + } + runServiceAndWorkloadForResourceConsumer(clientset, internalClientset, nsName, name, kind, replicas, cpuLimit, memLimit, podAnnotations, serviceAnnotations) rc := &ResourceConsumer{ name: name, controllerName: name + "-ctrl", @@ -133,6 +145,7 @@ func newResourceConsumer(name, nsName string, kind schema.GroupVersionKind, repl nsName: nsName, clientSet: clientset, internalClientset: internalClientset, + scaleClient: scaleClient, cpu: make(chan int), mem: make(chan int), customMetric: make(chan int), @@ -224,7 +237,7 @@ func (rc *ResourceConsumer) makeConsumeCustomMetric() { delta := 0 for { select { - case delta := <-rc.customMetric: + case delta = <-rc.customMetric: framework.Logf("RC %s: setting bump of metric %s to %d in total", rc.name, customMetricName, delta) case <-time.After(sleepTime): framework.Logf("RC %s: sending request to consume %d of custom metric %s", rc.name, delta, customMetricName) @@ -401,17 +414,18 @@ func (rc *ResourceConsumer) CleanUp() { // Wait some time to ensure all child goroutines are finished. time.Sleep(10 * time.Second) kind := rc.kind.GroupKind() - framework.ExpectNoError(framework.DeleteResourceAndPods(rc.clientSet, rc.internalClientset, kind, rc.nsName, rc.name)) + framework.ExpectNoError(framework.DeleteResourceAndWaitForGC(rc.clientSet, kind, rc.nsName, rc.name)) framework.ExpectNoError(rc.clientSet.CoreV1().Services(rc.nsName).Delete(rc.name, nil)) - framework.ExpectNoError(framework.DeleteResourceAndPods(rc.clientSet, rc.internalClientset, api.Kind("ReplicationController"), rc.nsName, rc.controllerName)) + framework.ExpectNoError(framework.DeleteResourceAndWaitForGC(rc.clientSet, api.Kind("ReplicationController"), rc.nsName, rc.controllerName)) framework.ExpectNoError(rc.clientSet.CoreV1().Services(rc.nsName).Delete(rc.controllerName, nil)) } -func runServiceAndWorkloadForResourceConsumer(c clientset.Interface, internalClient internalclientset.Interface, ns, name string, kind schema.GroupVersionKind, replicas int, cpuLimitMillis, memLimitMb int64) { +func runServiceAndWorkloadForResourceConsumer(c clientset.Interface, internalClient internalclientset.Interface, ns, name string, kind schema.GroupVersionKind, replicas int, cpuLimitMillis, memLimitMb int64, podAnnotations, serviceAnnotations map[string]string) { By(fmt.Sprintf("Running consuming RC %s via %s with %v replicas", name, kind, replicas)) _, err := c.CoreV1().Services(ns).Create(&v1.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: name, + Name: name, + Annotations: serviceAnnotations, }, Spec: v1.ServiceSpec{ Ports: []v1.ServicePort{{ @@ -438,6 +452,7 @@ func runServiceAndWorkloadForResourceConsumer(c clientset.Interface, internalCli CpuLimit: cpuLimitMillis, MemRequest: memLimitMb * 1024 * 1024, // MemLimit is in bytes MemLimit: memLimitMb * 1024 * 1024, + Annotations: podAnnotations, } switch kind { diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/configmap.go b/vendor/k8s.io/kubernetes/test/e2e/common/configmap.go index 54bae8aaa..90038618f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/configmap.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/configmap.go @@ -34,7 +34,7 @@ var _ = Describe("[sig-api-machinery] ConfigMap", func() { Description: Make sure config map value can be used as an environment variable in the container (on container.env field) */ - framework.ConformanceIt("should be consumable via environment variable ", func() { + framework.ConformanceIt("should be consumable via environment variable [NodeConformance]", func() { name := "configmap-test-" + string(uuid.NewUUID()) configMap := newConfigMap(f, name) By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name)) @@ -82,7 +82,7 @@ var _ = Describe("[sig-api-machinery] ConfigMap", func() { Description: Make sure config map value can be used as an source for environment variables in the container (on container.envFrom field) */ - framework.ConformanceIt("should be consumable via the environment ", func() { + framework.ConformanceIt("should be consumable via the environment [NodeConformance]", func() { name := "configmap-test-" + string(uuid.NewUUID()) configMap := newEnvFromConfigMap(f, name) By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name)) diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/configmap_volume.go b/vendor/k8s.io/kubernetes/test/e2e/common/configmap_volume.go index a4918611d..4a6e170c8 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/configmap_volume.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/configmap_volume.go @@ -37,7 +37,7 @@ var _ = Describe("[sig-storage] ConfigMap", func() { Description: Make sure config map without mappings works by mounting it to a volume with a custom path (mapping) on the pod with no other settings. */ - framework.ConformanceIt("should be consumable from pods in volume ", func() { + framework.ConformanceIt("should be consumable from pods in volume [NodeConformance]", func() { doConfigMapE2EWithoutMappings(f, 0, 0, nil) }) @@ -46,12 +46,12 @@ var _ = Describe("[sig-storage] ConfigMap", func() { Description: Make sure config map without mappings works by mounting it to a volume with a custom path (mapping) on the pod with defaultMode set */ - framework.ConformanceIt("should be consumable from pods in volume with defaultMode set ", func() { + framework.ConformanceIt("should be consumable from pods in volume with defaultMode set [NodeConformance]", func() { defaultMode := int32(0400) doConfigMapE2EWithoutMappings(f, 0, 0, &defaultMode) }) - It("should be consumable from pods in volume as non-root with defaultMode and fsGroup set [Feature:FSGroup]", func() { + It("should be consumable from pods in volume as non-root with defaultMode and fsGroup set [NodeFeature:FSGroup]", func() { defaultMode := int32(0440) /* setting fsGroup sets mode to at least 440 */ doConfigMapE2EWithoutMappings(f, 1000, 1001, &defaultMode) }) @@ -61,11 +61,11 @@ var _ = Describe("[sig-storage] ConfigMap", func() { Description: Make sure config map without mappings works by mounting it to a volume with a custom path (mapping) on the pod as non-root. */ - framework.ConformanceIt("should be consumable from pods in volume as non-root ", func() { + framework.ConformanceIt("should be consumable from pods in volume as non-root [NodeConformance]", func() { doConfigMapE2EWithoutMappings(f, 1000, 0, nil) }) - It("should be consumable from pods in volume as non-root with FSGroup [Feature:FSGroup]", func() { + It("should be consumable from pods in volume as non-root with FSGroup [NodeFeature:FSGroup]", func() { doConfigMapE2EWithoutMappings(f, 1000, 1001, nil) }) @@ -75,7 +75,7 @@ var _ = Describe("[sig-storage] ConfigMap", func() { a custom path (mapping) on the pod with no other settings and make sure the pod actually consumes it. */ - framework.ConformanceIt("should be consumable from pods in volume with mappings ", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings [NodeConformance]", func() { doConfigMapE2EWithMappings(f, 0, 0, nil) }) @@ -84,7 +84,7 @@ var _ = Describe("[sig-storage] ConfigMap", func() { Description: Make sure config map works with an item mode (e.g. 0400) for the config map item. */ - framework.ConformanceIt("should be consumable from pods in volume with mappings and Item mode set", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings and Item mode set [NodeConformance]", func() { mode := int32(0400) doConfigMapE2EWithMappings(f, 0, 0, &mode) }) @@ -93,11 +93,11 @@ var _ = Describe("[sig-storage] ConfigMap", func() { Testname: configmap-simple-user-mapped Description: Make sure config map works when it is mounted as non-root. */ - framework.ConformanceIt("should be consumable from pods in volume with mappings as non-root ", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings as non-root [NodeConformance]", func() { doConfigMapE2EWithMappings(f, 1000, 0, nil) }) - It("should be consumable from pods in volume with mappings as non-root with FSGroup [Feature:FSGroup]", func() { + It("should be consumable from pods in volume with mappings as non-root with FSGroup [NodeFeature:FSGroup]", func() { doConfigMapE2EWithMappings(f, 1000, 1001, nil) }) @@ -106,7 +106,7 @@ var _ = Describe("[sig-storage] ConfigMap", func() { Description: Make sure update operation is working on config map and the result is observed on volumes mounted in containers. */ - framework.ConformanceIt("updates should be reflected in volume ", func() { + framework.ConformanceIt("updates should be reflected in volume [NodeConformance]", func() { podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) @@ -184,7 +184,7 @@ var _ = Describe("[sig-storage] ConfigMap", func() { Eventually(pollLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-2")) }) - It("binary data should be reflected in volume ", func() { + It("binary data should be reflected in volume [NodeConformance]", func() { podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) @@ -280,7 +280,7 @@ var _ = Describe("[sig-storage] ConfigMap", func() { Description: Make sure Create, Update, Delete operations are all working on config map and the result is observed on volumes mounted in containers. */ - framework.ConformanceIt("optional updates should be reflected in volume ", func() { + framework.ConformanceIt("optional updates should be reflected in volume [NodeConformance]", func() { podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) trueVal := true @@ -463,7 +463,7 @@ var _ = Describe("[sig-storage] ConfigMap", func() { Description: Make sure config map works when it mounted as two different volumes on the same node. */ - framework.ConformanceIt("should be consumable in multiple volumes in the same pod ", func() { + framework.ConformanceIt("should be consumable in multiple volumes in the same pod [NodeConformance]", func() { var ( name = "configmap-test-volume-" + string(uuid.NewUUID()) volumeName = "configmap-volume" diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/container_probe.go b/vendor/k8s.io/kubernetes/test/e2e/common/container_probe.go index cb9b8d331..565741887 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/container_probe.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/container_probe.go @@ -37,7 +37,7 @@ const ( probTestContainerName = "test-webserver" probTestInitialDelaySeconds = 15 - defaultObservationTimeout = time.Minute * 2 + defaultObservationTimeout = time.Minute * 4 ) var _ = framework.KubeDescribe("Probing container", func() { @@ -54,7 +54,7 @@ var _ = framework.KubeDescribe("Probing container", func() { Description: Make sure that pod with readiness probe should not be ready before initial delay and never restart. */ - framework.ConformanceIt("with readiness probe should not be ready before initial delay and never restart ", func() { + framework.ConformanceIt("with readiness probe should not be ready before initial delay and never restart [NodeConformance]", func() { p := podClient.Create(makePodSpec(probe.withInitialDelay().build(), nil)) f.WaitForPodReady(p.Name) @@ -86,7 +86,7 @@ var _ = framework.KubeDescribe("Probing container", func() { Description: Make sure that pod with readiness probe that fails should never be ready and never restart. */ - framework.ConformanceIt("with readiness probe that fails should never be ready and never restart ", func() { + framework.ConformanceIt("with readiness probe that fails should never be ready and never restart [NodeConformance]", func() { p := podClient.Create(makePodSpec(probe.withFailing().build(), nil)) Consistently(func() (bool, error) { p, err := podClient.Get(p.Name, metav1.GetOptions{}) @@ -111,7 +111,7 @@ var _ = framework.KubeDescribe("Probing container", func() { Description: Make sure the pod is restarted with a cat /tmp/health liveness probe. */ - framework.ConformanceIt("should be restarted with a exec \"cat /tmp/health\" liveness probe", func() { + framework.ConformanceIt("should be restarted with a exec \"cat /tmp/health\" liveness probe [NodeConformance]", func() { runLivenessTest(f, &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "liveness-exec", @@ -143,7 +143,7 @@ var _ = framework.KubeDescribe("Probing container", func() { Description: Make sure the pod is not restarted with a cat /tmp/health liveness probe. */ - framework.ConformanceIt("should *not* be restarted with a exec \"cat /tmp/health\" liveness probe", func() { + framework.ConformanceIt("should *not* be restarted with a exec \"cat /tmp/health\" liveness probe [NodeConformance]", func() { runLivenessTest(f, &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "liveness-exec", @@ -175,7 +175,7 @@ var _ = framework.KubeDescribe("Probing container", func() { Description: Make sure when http liveness probe fails, the pod should be restarted. */ - framework.ConformanceIt("should be restarted with a /healthz http liveness probe ", func() { + framework.ConformanceIt("should be restarted with a /healthz http liveness probe [NodeConformance]", func() { runLivenessTest(f, &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "liveness-http", @@ -209,7 +209,7 @@ var _ = framework.KubeDescribe("Probing container", func() { Description: Make sure when a pod gets restarted, its start count should increase. */ - framework.ConformanceIt("should have monotonically increasing restart count [Slow]", func() { + framework.ConformanceIt("should have monotonically increasing restart count [Slow][NodeConformance]", func() { runLivenessTest(f, &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "liveness-http", @@ -242,7 +242,7 @@ var _ = framework.KubeDescribe("Probing container", func() { Description: Make sure when http liveness probe succeeds, the pod should not be restarted. */ - framework.ConformanceIt("should *not* be restarted with a /healthz http liveness probe ", func() { + framework.ConformanceIt("should *not* be restarted with a /healthz http liveness probe [NodeConformance]", func() { runLivenessTest(f, &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "liveness-http", @@ -276,7 +276,7 @@ var _ = framework.KubeDescribe("Probing container", func() { Description: Make sure that the pod is restarted with a docker exec liveness probe with timeout. */ - framework.ConformanceIt("should be restarted with a docker exec liveness probe with timeout ", func() { + It("should be restarted with a docker exec liveness probe with timeout ", func() { // TODO: enable this test once the default exec handler supports timeout. framework.Skipf("The default exec handler, dockertools.NativeExecHandler, does not support timeouts due to a limitation in the Docker Remote API") runLivenessTest(f, &v1.Pod{ diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/docker_containers.go b/vendor/k8s.io/kubernetes/test/e2e/common/docker_containers.go index dc5c9bf2e..cef5a2de2 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/docker_containers.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/docker_containers.go @@ -33,7 +33,7 @@ var _ = framework.KubeDescribe("Docker Containers", func() { provided for a Container, ensure that the docker image's default command and args are used. */ - framework.ConformanceIt("should use the image defaults if command and args are blank ", func() { + framework.ConformanceIt("should use the image defaults if command and args are blank [NodeConformance]", func() { f.TestContainerOutput("use defaults", entrypointTestPod(), 0, []string{ "[/ep default arguments]", }) @@ -45,7 +45,7 @@ var _ = framework.KubeDescribe("Docker Containers", func() { Container, ensure that they take precedent to the docker image's default arguments, but that the default command is used. */ - framework.ConformanceIt("should be able to override the image's default arguments (docker cmd) ", func() { + framework.ConformanceIt("should be able to override the image's default arguments (docker cmd) [NodeConformance]", func() { pod := entrypointTestPod() pod.Spec.Containers[0].Args = []string{"override", "arguments"} @@ -62,7 +62,7 @@ var _ = framework.KubeDescribe("Docker Containers", func() { Container, ensure that it takes precedent to the docker image's default command. */ - framework.ConformanceIt("should be able to override the image's default command (docker entrypoint) ", func() { + framework.ConformanceIt("should be able to override the image's default command (docker entrypoint) [NodeConformance]", func() { pod := entrypointTestPod() pod.Spec.Containers[0].Command = []string{"/ep-2"} @@ -77,7 +77,7 @@ var _ = framework.KubeDescribe("Docker Containers", func() { provided for a Container, ensure that they take precedent to the docker image's default command and arguments. */ - framework.ConformanceIt("should be able to override the image's default command and arguments ", func() { + framework.ConformanceIt("should be able to override the image's default command and arguments [NodeConformance]", func() { pod := entrypointTestPod() pod.Spec.Containers[0].Command = []string{"/ep-2"} pod.Spec.Containers[0].Args = []string{"override", "arguments"} diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/downward_api.go b/vendor/k8s.io/kubernetes/test/e2e/common/downward_api.go index d4a6e74bb..0541dc394 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/downward_api.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/downward_api.go @@ -42,7 +42,7 @@ var _ = Describe("[sig-api-machinery] Downward API", func() { Description: Ensure that downward API can provide pod's name, namespace and IP address as environment variables. */ - framework.ConformanceIt("should provide pod name, namespace and IP address as env vars ", func() { + framework.ConformanceIt("should provide pod name, namespace and IP address as env vars [NodeConformance]", func() { podName := "downward-api-" + string(uuid.NewUUID()) env := []v1.EnvVar{ { @@ -88,7 +88,7 @@ var _ = Describe("[sig-api-machinery] Downward API", func() { Description: Ensure that downward API can provide an IP address for host node as an environment variable. */ - framework.ConformanceIt("should provide host IP as an env var ", func() { + framework.ConformanceIt("should provide host IP as an env var [NodeConformance]", func() { framework.SkipUnlessServerVersionGTE(hostIPVersion, f.ClientSet.Discovery()) podName := "downward-api-" + string(uuid.NewUUID()) env := []v1.EnvVar{ @@ -115,7 +115,7 @@ var _ = Describe("[sig-api-machinery] Downward API", func() { Description: Ensure that downward API can provide CPU/memory limit and CPU/memory request as environment variables. */ - framework.ConformanceIt("should provide container's limits.cpu/memory and requests.cpu/memory as env vars ", func() { + framework.ConformanceIt("should provide container's limits.cpu/memory and requests.cpu/memory as env vars [NodeConformance]", func() { podName := "downward-api-" + string(uuid.NewUUID()) env := []v1.EnvVar{ { @@ -167,7 +167,7 @@ var _ = Describe("[sig-api-machinery] Downward API", func() { allocatable values for CPU and memory as environment variables if CPU and memory limits are not specified for a container. */ - framework.ConformanceIt("should provide default limits.cpu/memory from node allocatable ", func() { + framework.ConformanceIt("should provide default limits.cpu/memory from node allocatable [NodeConformance]", func() { podName := "downward-api-" + string(uuid.NewUUID()) env := []v1.EnvVar{ { @@ -217,7 +217,7 @@ var _ = Describe("[sig-api-machinery] Downward API", func() { Description: Ensure that downward API can provide pod UID as an environment variable. */ - framework.ConformanceIt("should provide pod UID as env vars ", func() { + framework.ConformanceIt("should provide pod UID as env vars [NodeConformance]", func() { framework.SkipUnlessServerVersionGTE(podUIDVersion, f.ClientSet.Discovery()) podName := "downward-api-" + string(uuid.NewUUID()) env := []v1.EnvVar{ @@ -240,7 +240,7 @@ var _ = Describe("[sig-api-machinery] Downward API", func() { }) }) -var _ = framework.KubeDescribe("Downward API [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("Downward API [Serial] [Disruptive] [NodeFeature:EphemeralStorage]", func() { f := framework.NewDefaultFramework("downward-api") Context("Downward API tests for local ephemeral storage", func() { diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/downwardapi_volume.go b/vendor/k8s.io/kubernetes/test/e2e/common/downwardapi_volume.go index 3709b318e..7914a1970 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/downwardapi_volume.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/downwardapi_volume.go @@ -44,7 +44,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { Description: Ensure that downward API can provide pod's name through DownwardAPIVolumeFiles. */ - framework.ConformanceIt("should provide podname only ", func() { + framework.ConformanceIt("should provide podname only [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumePodForSimpleTest(podName, "/etc/podinfo/podname") @@ -58,7 +58,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { Description: Ensure that downward API can set default file permission mode for DownwardAPIVolumeFiles if no mode is specified. */ - framework.ConformanceIt("should set DefaultMode on files ", func() { + framework.ConformanceIt("should set DefaultMode on files [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) defaultMode := int32(0400) pod := downwardAPIVolumePodForModeTest(podName, "/etc/podinfo/podname", nil, &defaultMode) @@ -73,7 +73,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { Description: Ensure that downward API can set file permission mode for DownwardAPIVolumeFiles. */ - framework.ConformanceIt("should set mode on item file ", func() { + framework.ConformanceIt("should set mode on item file [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) mode := int32(0400) pod := downwardAPIVolumePodForModeTest(podName, "/etc/podinfo/podname", &mode, nil) @@ -83,7 +83,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { }) }) - It("should provide podname as non-root with fsgroup [Feature:FSGroup]", func() { + It("should provide podname as non-root with fsgroup [NodeFeature:FSGroup]", func() { podName := "metadata-volume-" + string(uuid.NewUUID()) uid := int64(1001) gid := int64(1234) @@ -97,7 +97,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { }) }) - It("should provide podname as non-root with fsgroup and defaultMode [Feature:FSGroup]", func() { + It("should provide podname as non-root with fsgroup and defaultMode [NodeFeature:FSGroup]", func() { podName := "metadata-volume-" + string(uuid.NewUUID()) uid := int64(1001) gid := int64(1234) @@ -117,7 +117,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { Description: Ensure that downward API updates labels in DownwardAPIVolumeFiles when pod's labels get modified. */ - framework.ConformanceIt("should update labels on modification ", func() { + framework.ConformanceIt("should update labels on modification [NodeConformance]", func() { labels := map[string]string{} labels["key1"] = "value1" labels["key2"] = "value2" @@ -149,7 +149,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { Description: Ensure that downward API updates annotations in DownwardAPIVolumeFiles when pod's annotations get modified. */ - framework.ConformanceIt("should update annotations on modification ", func() { + framework.ConformanceIt("should update annotations on modification [NodeConformance]", func() { annotations := map[string]string{} annotations["builder"] = "bar" podName := "annotationupdate" + string(uuid.NewUUID()) @@ -183,7 +183,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { Description: Ensure that downward API can provide container's CPU limit through DownwardAPIVolumeFiles. */ - framework.ConformanceIt("should provide container's cpu limit ", func() { + framework.ConformanceIt("should provide container's cpu limit [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForContainerResources(podName, "/etc/podinfo/cpu_limit") @@ -197,7 +197,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { Description: Ensure that downward API can provide container's memory limit through DownwardAPIVolumeFiles. */ - framework.ConformanceIt("should provide container's memory limit ", func() { + framework.ConformanceIt("should provide container's memory limit [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForContainerResources(podName, "/etc/podinfo/memory_limit") @@ -211,7 +211,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { Description: Ensure that downward API can provide container's CPU request through DownwardAPIVolumeFiles. */ - framework.ConformanceIt("should provide container's cpu request ", func() { + framework.ConformanceIt("should provide container's cpu request [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForContainerResources(podName, "/etc/podinfo/cpu_request") @@ -225,7 +225,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { Description: Ensure that downward API can provide container's memory request through DownwardAPIVolumeFiles. */ - framework.ConformanceIt("should provide container's memory request ", func() { + framework.ConformanceIt("should provide container's memory request [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForContainerResources(podName, "/etc/podinfo/memory_request") @@ -240,7 +240,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { allocatable value for CPU through DownwardAPIVolumeFiles if CPU limit is not specified for a container. */ - framework.ConformanceIt("should provide node allocatable (cpu) as default cpu limit if the limit is not set ", func() { + framework.ConformanceIt("should provide node allocatable (cpu) as default cpu limit if the limit is not set [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForDefaultContainerResources(podName, "/etc/podinfo/cpu_limit") @@ -253,7 +253,7 @@ var _ = Describe("[sig-storage] Downward API volume", func() { allocatable value for memory through DownwardAPIVolumeFiles if memory limit is not specified for a container. */ - framework.ConformanceIt("should provide node allocatable (memory) as default memory limit if the limit is not set ", func() { + framework.ConformanceIt("should provide node allocatable (memory) as default memory limit if the limit is not set [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForDefaultContainerResources(podName, "/etc/podinfo/memory_limit") diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/empty_dir.go b/vendor/k8s.io/kubernetes/test/e2e/common/empty_dir.go index 613a88ef4..a587f35f4 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/empty_dir.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/empty_dir.go @@ -24,7 +24,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/e2e/framework" imageutils "k8s.io/kubernetes/test/utils/image" ) @@ -41,7 +40,7 @@ var ( var _ = Describe("[sig-storage] EmptyDir volumes", func() { f := framework.NewDefaultFramework("emptydir") - Context("when FSGroup is specified", func() { + Context("when FSGroup is specified [NodeFeature:FSGroup]", func() { It("new files should be created with FSGroup ownership when container is root", func() { doTestSetgidFSGroup(f, testImageRootUid, v1.StorageMediumMemory) }) @@ -73,7 +72,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { of 'Memory', ensure the volume has 0777 unix file permissions and tmpfs mount type. */ - framework.ConformanceIt("volume on tmpfs should have the correct mode", func() { + framework.ConformanceIt("volume on tmpfs should have the correct mode [NodeConformance]", func() { doTestVolumeMode(f, testImageRootUid, v1.StorageMediumMemory) }) @@ -83,7 +82,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { of 'Memory', ensure a root owned file with 0644 unix file permissions is created correctly, has tmpfs mount type, and enforces the permissions. */ - framework.ConformanceIt("should support (root,0644,tmpfs)", func() { + framework.ConformanceIt("should support (root,0644,tmpfs) [NodeConformance]", func() { doTest0644(f, testImageRootUid, v1.StorageMediumMemory) }) @@ -93,7 +92,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { of 'Memory', ensure a root owned file with 0666 unix file permissions is created correctly, has tmpfs mount type, and enforces the permissions. */ - framework.ConformanceIt("should support (root,0666,tmpfs)", func() { + framework.ConformanceIt("should support (root,0666,tmpfs) [NodeConformance]", func() { doTest0666(f, testImageRootUid, v1.StorageMediumMemory) }) @@ -103,7 +102,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { of 'Memory', ensure a root owned file with 0777 unix file permissions is created correctly, has tmpfs mount type, and enforces the permissions. */ - framework.ConformanceIt("should support (root,0777,tmpfs)", func() { + framework.ConformanceIt("should support (root,0777,tmpfs) [NodeConformance]", func() { doTest0777(f, testImageRootUid, v1.StorageMediumMemory) }) @@ -113,7 +112,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { of 'Memory', ensure a user owned file with 0644 unix file permissions is created correctly, has tmpfs mount type, and enforces the permissions. */ - framework.ConformanceIt("should support (non-root,0644,tmpfs)", func() { + framework.ConformanceIt("should support (non-root,0644,tmpfs) [NodeConformance]", func() { doTest0644(f, testImageNonRootUid, v1.StorageMediumMemory) }) @@ -123,7 +122,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { of 'Memory', ensure a user owned file with 0666 unix file permissions is created correctly, has tmpfs mount type, and enforces the permissions. */ - framework.ConformanceIt("should support (non-root,0666,tmpfs)", func() { + framework.ConformanceIt("should support (non-root,0666,tmpfs) [NodeConformance]", func() { doTest0666(f, testImageNonRootUid, v1.StorageMediumMemory) }) @@ -133,7 +132,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { of 'Memory', ensure a user owned file with 0777 unix file permissions is created correctly, has tmpfs mount type, and enforces the permissions. */ - framework.ConformanceIt("should support (non-root,0777,tmpfs)", func() { + framework.ConformanceIt("should support (non-root,0777,tmpfs) [NodeConformance]", func() { doTest0777(f, testImageNonRootUid, v1.StorageMediumMemory) }) @@ -142,7 +141,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { Description: For a Pod created with an 'emptyDir' Volume, ensure the volume has 0777 unix file permissions. */ - framework.ConformanceIt("volume on default medium should have the correct mode", func() { + framework.ConformanceIt("volume on default medium should have the correct mode [NodeConformance]", func() { doTestVolumeMode(f, testImageRootUid, v1.StorageMediumDefault) }) @@ -152,7 +151,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { root owned file with 0644 unix file permissions is created and enforced correctly. */ - framework.ConformanceIt("should support (root,0644,default)", func() { + framework.ConformanceIt("should support (root,0644,default) [NodeConformance]", func() { doTest0644(f, testImageRootUid, v1.StorageMediumDefault) }) @@ -162,7 +161,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { root owned file with 0666 unix file permissions is created and enforced correctly. */ - framework.ConformanceIt("should support (root,0666,default)", func() { + framework.ConformanceIt("should support (root,0666,default) [NodeConformance]", func() { doTest0666(f, testImageRootUid, v1.StorageMediumDefault) }) @@ -172,7 +171,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { root owned file with 0777 unix file permissions is created and enforced correctly. */ - framework.ConformanceIt("should support (root,0777,default)", func() { + framework.ConformanceIt("should support (root,0777,default) [NodeConformance]", func() { doTest0777(f, testImageRootUid, v1.StorageMediumDefault) }) @@ -182,7 +181,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { user owned file with 0644 unix file permissions is created and enforced correctly. */ - framework.ConformanceIt("should support (non-root,0644,default)", func() { + framework.ConformanceIt("should support (non-root,0644,default) [NodeConformance]", func() { doTest0644(f, testImageNonRootUid, v1.StorageMediumDefault) }) @@ -192,7 +191,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { user owned file with 0666 unix file permissions is created and enforced correctly. */ - framework.ConformanceIt("should support (non-root,0666,default)", func() { + framework.ConformanceIt("should support (non-root,0666,default) [NodeConformance]", func() { doTest0666(f, testImageNonRootUid, v1.StorageMediumDefault) }) @@ -202,7 +201,7 @@ var _ = Describe("[sig-storage] EmptyDir volumes", func() { user owned file with 0777 unix file permissions is created and enforced correctly. */ - framework.ConformanceIt("should support (non-root,0777,default)", func() { + framework.ConformanceIt("should support (non-root,0777,default) [NodeConformance]", func() { doTest0777(f, testImageNonRootUid, v1.StorageMediumDefault) }) }) @@ -430,7 +429,7 @@ func testPodWithVolume(image, path string, source *v1.EmptyDirVolumeSource) *v1. return &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: podName, diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/expansion.go b/vendor/k8s.io/kubernetes/test/e2e/common/expansion.go index 303df66f9..5b6f50448 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/expansion.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/expansion.go @@ -21,6 +21,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/kubernetes/test/e2e/framework" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) // These tests exercise the Kubernetes expansion syntax $(VAR). @@ -34,7 +37,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() { Description: Make sure environment variables can be set using an expansion of previously defined environment variables */ - framework.ConformanceIt("should allow composing env vars into new env vars ", func() { + framework.ConformanceIt("should allow composing env vars into new env vars [NodeConformance]", func() { podName := "var-expansion-" + string(uuid.NewUUID()) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -79,7 +82,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() { Description: Make sure a container's commands can be set using an expansion of environment variables. */ - framework.ConformanceIt("should allow substituting values in a container's command ", func() { + framework.ConformanceIt("should allow substituting values in a container's command [NodeConformance]", func() { podName := "var-expansion-" + string(uuid.NewUUID()) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -114,7 +117,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() { Description: Make sure a container's args can be set using an expansion of environment variables. */ - framework.ConformanceIt("should allow substituting values in a container's args ", func() { + framework.ConformanceIt("should allow substituting values in a container's args [NodeConformance]", func() { podName := "var-expansion-" + string(uuid.NewUUID()) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -144,4 +147,175 @@ var _ = framework.KubeDescribe("Variable Expansion", func() { "test-value", }) }) + + /* + Testname: var-expansion-subpath + Description: Make sure a container's subpath can be set using an + expansion of environment variables. + */ + It("should allow substituting values in a volume subpath [Feature:VolumeSubpathEnvExpansion][NodeAlphaFeature:VolumeSubpathEnvExpansion]", func() { + podName := "var-expansion-" + string(uuid.NewUUID()) + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Labels: map[string]string{"name": podName}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "dapi-container", + Image: busyboxImage, + Command: []string{"sh", "-c", "test -d /testcontainer/" + podName + ";echo $?"}, + Env: []v1.EnvVar{ + { + Name: "POD_NAME", + Value: podName, + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "workdir1", + MountPath: "/logscontainer", + SubPath: "$(POD_NAME)", + }, + { + Name: "workdir2", + MountPath: "/testcontainer", + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + Volumes: []v1.Volume{ + { + Name: "workdir1", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{Path: "/tmp"}, + }, + }, + { + Name: "workdir2", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{Path: "/tmp"}, + }, + }, + }, + }, + } + + f.TestContainerOutput("substitution in volume subpath", pod, 0, []string{ + "0", + }) + }) + + /* + Testname: var-expansion-subpath-with-backticks + Description: Make sure a container's subpath can not be set using an + expansion of environment variables when backticks are supplied. + */ + It("should fail substituting values in a volume subpath with backticks [Feature:VolumeSubpathEnvExpansion][NodeAlphaFeature:VolumeSubpathEnvExpansion][Slow]", func() { + + podName := "var-expansion-" + string(uuid.NewUUID()) + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Labels: map[string]string{"name": podName}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "dapi-container", + Image: busyboxImage, + Env: []v1.EnvVar{ + { + Name: "POD_NAME", + Value: "..", + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "workdir1", + MountPath: "/logscontainer", + SubPath: "$(POD_NAME)", + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + Volumes: []v1.Volume{ + { + Name: "workdir1", + VolumeSource: v1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{}, + }, + }, + }, + }, + } + + // Pod should fail + testPodFailSubpath(f, pod) + }) + + /* + Testname: var-expansion-subpath-with-absolute-path + Description: Make sure a container's subpath can not be set using an + expansion of environment variables when absolute path is supplied. + */ + It("should fail substituting values in a volume subpath with absolute path [Feature:VolumeSubpathEnvExpansion][NodeAlphaFeature:VolumeSubpathEnvExpansion][Slow]", func() { + + podName := "var-expansion-" + string(uuid.NewUUID()) + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Labels: map[string]string{"name": podName}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "dapi-container", + Image: busyboxImage, + Env: []v1.EnvVar{ + { + Name: "POD_NAME", + Value: "/tmp", + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "workdir1", + MountPath: "/logscontainer", + SubPath: "$(POD_NAME)", + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + Volumes: []v1.Volume{ + { + Name: "workdir1", + VolumeSource: v1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{}, + }, + }, + }, + }, + } + + // Pod should fail + testPodFailSubpath(f, pod) + }) }) + +func testPodFailSubpath(f *framework.Framework, pod *v1.Pod) { + + pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod) + Expect(err).ToNot(HaveOccurred(), "while creating pod") + + defer func() { + framework.DeletePodWithWait(f, f.ClientSet, pod) + }() + + err = framework.WaitTimeoutForPodRunningInNamespace(f.ClientSet, pod.Name, pod.Namespace, framework.PodStartShortTimeout) + Expect(err).To(HaveOccurred(), "while waiting for pod to be running") +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/host_path.go b/vendor/k8s.io/kubernetes/test/e2e/common/host_path.go index bb144027d..dd21c9538 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/host_path.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/host_path.go @@ -23,7 +23,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" @@ -46,7 +45,7 @@ var _ = Describe("[sig-storage] HostPath", func() { volume is a directory with 0777 unix file permissions and that is has the sticky bit (mode flag t) set. */ - framework.ConformanceIt("should give a volume the correct mode", func() { + framework.ConformanceIt("should give a volume the correct mode [NodeConformance]", func() { source := &v1.HostPathVolumeSource{ Path: "/tmp", } @@ -62,7 +61,7 @@ var _ = Describe("[sig-storage] HostPath", func() { }) // This test requires mounting a folder into a container with write privileges. - It("should support r/w", func() { + It("should support r/w [NodeConformance]", func() { filePath := path.Join(volumePath, "test-file") retryDuration := 180 source := &v1.HostPathVolumeSource{ @@ -86,7 +85,7 @@ var _ = Describe("[sig-storage] HostPath", func() { }) }) - It("should support subPath", func() { + It("should support subPath [NodeConformance]", func() { subPath := "sub-path" fileName := "test-file" retryDuration := 180 @@ -228,7 +227,7 @@ func testPodWithHostVol(path string, source *v1.HostPathVolumeSource) *v1.Pod { return &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: podName, diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/init_container.go b/vendor/k8s.io/kubernetes/test/e2e/common/init_container.go index 9221157a4..ad32cc841 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/init_container.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/init_container.go @@ -29,12 +29,13 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/client/conditions" "k8s.io/kubernetes/test/e2e/framework" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) -var _ = framework.KubeDescribe("InitContainer", func() { +var _ = framework.KubeDescribe("InitContainer [NodeConformance]", func() { f := framework.NewDefaultFramework("init-container") var podClient *framework.PodClient BeforeEach(func() { @@ -42,8 +43,6 @@ var _ = framework.KubeDescribe("InitContainer", func() { }) It("should invoke init containers on a RestartNever pod", func() { - framework.SkipIfContainerRuntimeIs("rkt") // #25988 - By("creating the pod") name := "pod-init-" + string(uuid.NewUUID()) value := strconv.Itoa(time.Now().Nanosecond()) @@ -101,8 +100,6 @@ var _ = framework.KubeDescribe("InitContainer", func() { }) It("should invoke init containers on a RestartAlways pod", func() { - framework.SkipIfContainerRuntimeIs("rkt") // #25988 - By("creating the pod") name := "pod-init-" + string(uuid.NewUUID()) value := strconv.Itoa(time.Now().Nanosecond()) @@ -130,7 +127,7 @@ var _ = framework.KubeDescribe("InitContainer", func() { Containers: []v1.Container{ { Name: "run1", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Resources: v1.ResourceRequirements{ Limits: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), @@ -164,8 +161,6 @@ var _ = framework.KubeDescribe("InitContainer", func() { }) It("should not start app containers if init containers fail on a RestartAlways pod", func() { - framework.SkipIfContainerRuntimeIs("rkt") // #25988 - By("creating the pod") name := "pod-init-" + string(uuid.NewUUID()) value := strconv.Itoa(time.Now().Nanosecond()) @@ -194,7 +189,7 @@ var _ = framework.KubeDescribe("InitContainer", func() { Containers: []v1.Container{ { Name: "run1", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Resources: v1.ResourceRequirements{ Limits: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), @@ -274,8 +269,6 @@ var _ = framework.KubeDescribe("InitContainer", func() { }) It("should not start app containers and fail the pod if init containers fail on a RestartNever pod", func() { - framework.SkipIfContainerRuntimeIs("rkt") // #25988 - By("creating the pod") name := "pod-init-" + string(uuid.NewUUID()) value := strconv.Itoa(time.Now().Nanosecond()) diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/kubelet_etc_hosts.go b/vendor/k8s.io/kubernetes/test/e2e/common/kubelet_etc_hosts.go index bcce2375a..21d2b2a66 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/kubelet_etc_hosts.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/kubelet_etc_hosts.go @@ -17,8 +17,6 @@ limitations under the License. package common import ( - "io/ioutil" - "os" "strings" "time" @@ -34,6 +32,8 @@ const ( etcHostsPodName = "test-pod" etcHostsHostNetworkPodName = "test-host-network-pod" etcHostsPartialContent = "# Kubernetes-managed hosts file." + etcHostsPath = "/etc/hosts" + etcHostsOriginalPath = "/etc/hosts-original" ) var etcHostsImageName = imageutils.GetE2EImage(imageutils.Netexec) @@ -42,7 +42,6 @@ type KubeletManagedHostConfig struct { hostNetworkPod *v1.Pod pod *v1.Pod f *framework.Framework - tmpEtcHostFile *os.File } var _ = framework.KubeDescribe("KubeletManagedEtcHosts", func() { @@ -56,14 +55,12 @@ var _ = framework.KubeDescribe("KubeletManagedEtcHosts", func() { Description: Make sure Kubelet correctly manages /etc/hosts and mounts it into the container. */ - framework.ConformanceIt("should test kubelet managed /etc/hosts file ", func() { + framework.ConformanceIt("should test kubelet managed /etc/hosts file [NodeConformance]", func() { By("Setting up the test") config.setup() By("Running the test") config.verifyEtcHosts() - - config.cleanup() }) }) @@ -81,26 +78,6 @@ func (config *KubeletManagedHostConfig) verifyEtcHosts() { } func (config *KubeletManagedHostConfig) setup() { - etcHostContents := `127.0.0.1 localhost -::1 localhost ip6-localhost ip6-loopback -fe00::0 ip6-localnet -ff00::0 ip6-mcastprefix -ff02::1 ip6-allnodes -ff02::2 ip6-allrouters` - - // Write the data to a temp file. - var err error - config.tmpEtcHostFile, err = ioutil.TempFile("", "etc-hosts") - if err != nil { - framework.Failf("failed to create temp file for /etc/hosts: %v", err) - } - if _, err := config.tmpEtcHostFile.Write([]byte(etcHostContents)); err != nil { - framework.Failf("Failed to write temp file for /etc/hosts data: %v", err) - } - if err := config.tmpEtcHostFile.Close(); err != nil { - framework.Failf("Failed to close temp file: %v", err) - } - By("Creating hostNetwork=false pod") config.createPodWithoutHostNetwork() @@ -108,12 +85,6 @@ ff02::2 ip6-allrouters` config.createPodWithHostNetwork() } -func (config *KubeletManagedHostConfig) cleanup() { - if config.tmpEtcHostFile != nil { - os.Remove(config.tmpEtcHostFile.Name()) - } -} - func (config *KubeletManagedHostConfig) createPodWithoutHostNetwork() { podSpec := config.createPodSpec(etcHostsPodName) config.pod = config.f.PodClient().CreateSync(podSpec) @@ -137,16 +108,24 @@ func assertManagedStatus( etcHostsContent := "" for startTime := time.Now(); time.Since(startTime) < retryTimeout; { - etcHostsContent = config.getEtcHostsContent(podName, name) - isManaged := strings.Contains(etcHostsContent, etcHostsPartialContent) - - if expectedIsManaged == isManaged { - return + etcHostsContent = config.getFileContents(podName, name, etcHostsPath) + etcHostsOriginalContent := config.getFileContents(podName, name, etcHostsOriginalPath) + + // Make sure there is some content in both files + if len(etcHostsContent) > 0 && len(etcHostsOriginalContent) > 0 { + // if the files match, kubernetes did not touch the file at all + // if the file has the header, kubernetes is not using host network + // and is constructing the file based on Pod IP + isManaged := strings.HasPrefix(etcHostsContent, etcHostsPartialContent) && + etcHostsContent != etcHostsOriginalContent + if expectedIsManaged == isManaged { + return + } } glog.Warningf( - "For pod: %s, name: %s, expected %t, actual %t (/etc/hosts was %q), retryCount: %d", - podName, name, expectedIsManaged, isManaged, etcHostsContent, retryCount) + "For pod: %s, name: %s, expected %t, (/etc/hosts was %q), (/etc/hosts-original was %q), retryCount: %d", + podName, name, expectedIsManaged, etcHostsContent, etcHostsOriginalContent, retryCount) retryCount++ time.Sleep(100 * time.Millisecond) @@ -163,8 +142,8 @@ func assertManagedStatus( } } -func (config *KubeletManagedHostConfig) getEtcHostsContent(podName, containerName string) string { - return config.f.ExecCommandInContainer(podName, containerName, "cat", "/etc/hosts") +func (config *KubeletManagedHostConfig) getFileContents(podName, containerName, path string) string { + return config.f.ExecCommandInContainer(podName, containerName, "cat", path) } func (config *KubeletManagedHostConfig) createPodSpec(podName string) *v1.Pod { @@ -184,6 +163,12 @@ func (config *KubeletManagedHostConfig) createPodSpec(podName string) *v1.Pod { "sleep", "900", }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "host-etc-hosts", + MountPath: etcHostsOriginalPath, + }, + }, }, { Name: "busybox-2", @@ -193,6 +178,12 @@ func (config *KubeletManagedHostConfig) createPodSpec(podName string) *v1.Pod { "sleep", "900", }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "host-etc-hosts", + MountPath: etcHostsOriginalPath, + }, + }, }, { Name: "busybox-3", @@ -205,7 +196,11 @@ func (config *KubeletManagedHostConfig) createPodSpec(podName string) *v1.Pod { VolumeMounts: []v1.VolumeMount{ { Name: "host-etc-hosts", - MountPath: "/etc/hosts", + MountPath: etcHostsPath, + }, + { + Name: "host-etc-hosts", + MountPath: etcHostsOriginalPath, }, }, }, @@ -215,7 +210,7 @@ func (config *KubeletManagedHostConfig) createPodSpec(podName string) *v1.Pod { Name: "host-etc-hosts", VolumeSource: v1.VolumeSource{ HostPath: &v1.HostPathVolumeSource{ - Path: config.tmpEtcHostFile.Name(), + Path: etcHostsPath, Type: hostPathType, }, }, @@ -227,6 +222,8 @@ func (config *KubeletManagedHostConfig) createPodSpec(podName string) *v1.Pod { } func (config *KubeletManagedHostConfig) createPodSpecWithHostNetwork(podName string) *v1.Pod { + hostPathType := new(v1.HostPathType) + *hostPathType = v1.HostPathType(string(v1.HostPathFileOrCreate)) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: podName, @@ -243,6 +240,12 @@ func (config *KubeletManagedHostConfig) createPodSpecWithHostNetwork(podName str "sleep", "900", }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "host-etc-hosts", + MountPath: etcHostsOriginalPath, + }, + }, }, { Name: "busybox-2", @@ -252,6 +255,23 @@ func (config *KubeletManagedHostConfig) createPodSpecWithHostNetwork(podName str "sleep", "900", }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "host-etc-hosts", + MountPath: etcHostsOriginalPath, + }, + }, + }, + }, + Volumes: []v1.Volume{ + { + Name: "host-etc-hosts", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: etcHostsPath, + Type: hostPathType, + }, + }, }, }, }, diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/networking.go b/vendor/k8s.io/kubernetes/test/e2e/common/networking.go index 1cb460719..71b7dfacd 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/networking.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/networking.go @@ -35,7 +35,7 @@ var _ = Describe("[sig-network] Networking", func() { Description: Try to hit test endpoints from a test container and make sure each of them can report a unique hostname. */ - framework.ConformanceIt("should function for intra-pod communication: http ", func() { + framework.ConformanceIt("should function for intra-pod communication: http [NodeConformance]", func() { config := framework.NewCoreNetworkingTestConfig(f) for _, endpointPod := range config.EndpointPods { config.DialFromTestContainer("http", endpointPod.Status.PodIP, framework.EndpointHttpPort, config.MaxTries, 0, sets.NewString(endpointPod.Name)) @@ -47,7 +47,7 @@ var _ = Describe("[sig-network] Networking", func() { Description: Try to hit test endpoints from a test container using udp and make sure each of them can report a unique hostname. */ - framework.ConformanceIt("should function for intra-pod communication: udp ", func() { + framework.ConformanceIt("should function for intra-pod communication: udp [NodeConformance]", func() { config := framework.NewCoreNetworkingTestConfig(f) for _, endpointPod := range config.EndpointPods { config.DialFromTestContainer("udp", endpointPod.Status.PodIP, framework.EndpointUdpPort, config.MaxTries, 0, sets.NewString(endpointPod.Name)) @@ -59,7 +59,7 @@ var _ = Describe("[sig-network] Networking", func() { Description: Try to hit test endpoints from the pod and make sure each of them can report a unique hostname. */ - framework.ConformanceIt("should function for node-pod communication: http ", func() { + framework.ConformanceIt("should function for node-pod communication: http [NodeConformance]", func() { config := framework.NewCoreNetworkingTestConfig(f) for _, endpointPod := range config.EndpointPods { config.DialFromNode("http", endpointPod.Status.PodIP, framework.EndpointHttpPort, config.MaxTries, 0, sets.NewString(endpointPod.Name)) @@ -71,7 +71,7 @@ var _ = Describe("[sig-network] Networking", func() { Description: Try to hit test endpoints from the pod using udp and make sure each of them can report a unique hostname. */ - framework.ConformanceIt("should function for node-pod communication: udp ", func() { + framework.ConformanceIt("should function for node-pod communication: udp [NodeConformance]", func() { config := framework.NewCoreNetworkingTestConfig(f) for _, endpointPod := range config.EndpointPods { config.DialFromNode("udp", endpointPod.Status.PodIP, framework.EndpointUdpPort, config.MaxTries, 0, sets.NewString(endpointPod.Name)) diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/pods.go b/vendor/k8s.io/kubernetes/test/e2e/common/pods.go index 1b14332bc..2fa6fbc42 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/pods.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/pods.go @@ -133,7 +133,7 @@ var _ = framework.KubeDescribe("Pods", func() { Description: Make sure when a pod is created that it is assigned a host IP Address. */ - framework.ConformanceIt("should get a host IP ", func() { + framework.ConformanceIt("should get a host IP [NodeConformance]", func() { name := "pod-hostip-" + string(uuid.NewUUID()) testHostIP(podClient, &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -143,7 +143,7 @@ var _ = framework.KubeDescribe("Pods", func() { Containers: []v1.Container{ { Name: "test", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), }, }, }, @@ -155,7 +155,7 @@ var _ = framework.KubeDescribe("Pods", func() { Description: Makes sure a pod is created, a watch can be setup for the pod, pod creation was observed, pod is deleted, and pod deletion is observed. */ - framework.ConformanceIt("should be submitted and removed ", func() { + framework.ConformanceIt("should be submitted and removed [NodeConformance]", func() { By("creating the pod") name := "pod-submit-remove-" + string(uuid.NewUUID()) value := strconv.Itoa(time.Now().Nanosecond()) @@ -280,7 +280,7 @@ var _ = framework.KubeDescribe("Pods", func() { Testname: pods-updated-successfully Description: Make sure it is possible to successfully update a pod's labels. */ - framework.ConformanceIt("should be updated ", func() { + framework.ConformanceIt("should be updated [NodeConformance]", func() { By("creating the pod") name := "pod-update-" + string(uuid.NewUUID()) value := strconv.Itoa(time.Now().Nanosecond()) @@ -335,7 +335,7 @@ var _ = framework.KubeDescribe("Pods", func() { activeDeadlineSecondsValue, and then waits for the deadline to pass and verifies the pod is terminated. */ - framework.ConformanceIt("should allow activeDeadlineSeconds to be updated ", func() { + framework.ConformanceIt("should allow activeDeadlineSeconds to be updated [NodeConformance]", func() { By("creating the pod") name := "pod-update-activedeadlineseconds-" + string(uuid.NewUUID()) value := strconv.Itoa(time.Now().Nanosecond()) @@ -381,7 +381,7 @@ var _ = framework.KubeDescribe("Pods", func() { Description: Make sure that when a pod is created it contains environment variables for each active service. */ - framework.ConformanceIt("should contain environment variables for services ", func() { + framework.ConformanceIt("should contain environment variables for services [NodeConformance]", func() { // Make a pod that will be a service. // This pod serves its hostname via HTTP. serverName := "server-envvars-" + string(uuid.NewUUID()) @@ -467,7 +467,7 @@ var _ = framework.KubeDescribe("Pods", func() { }, maxRetries, "Container should have service environment variables set") }) - It("should support remote command execution over websockets", func() { + It("should support remote command execution over websockets [NodeConformance]", func() { config, err := framework.LoadConfig() Expect(err).NotTo(HaveOccurred(), "unable to get base config") @@ -523,7 +523,13 @@ var _ = framework.KubeDescribe("Pods", func() { continue } if msg[0] != 1 { - framework.Failf("Got message from server that didn't start with channel 1 (STDOUT): %v", msg) + if len(msg) == 1 { + // skip an empty message on stream other than stdout + continue + } else { + framework.Failf("Got message from server that didn't start with channel 1 (STDOUT): %v", msg) + } + } buf.Write(msg[1:]) } @@ -537,7 +543,7 @@ var _ = framework.KubeDescribe("Pods", func() { }, time.Minute, 10*time.Second).Should(BeNil()) }) - It("should support retrieving logs from the container over websockets", func() { + It("should support retrieving logs from the container over websockets [NodeConformance]", func() { config, err := framework.LoadConfig() Expect(err).NotTo(HaveOccurred(), "unable to get base config") @@ -594,7 +600,7 @@ var _ = framework.KubeDescribe("Pods", func() { } }) - It("should have their auto-restart back-off timer reset on image update [Slow]", func() { + It("should have their auto-restart back-off timer reset on image update [Slow][NodeConformance]", func() { podName := "pod-back-off-image" containerName := "back-off" pod := &v1.Pod{ @@ -635,7 +641,7 @@ var _ = framework.KubeDescribe("Pods", func() { }) // Slow issue #19027 (20 mins) - It("should cap back-off at MaxContainerBackOff [Slow]", func() { + It("should cap back-off at MaxContainerBackOff [Slow][NodeConformance]", func() { podName := "back-off-cap" containerName := "back-off-cap" pod := &v1.Pod{ diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/privileged.go b/vendor/k8s.io/kubernetes/test/e2e/common/privileged.go index a56b06273..76757a90a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/privileged.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/privileged.go @@ -36,7 +36,7 @@ type PrivilegedPodTestConfig struct { pod *v1.Pod } -var _ = framework.KubeDescribe("PrivilegedPod", func() { +var _ = framework.KubeDescribe("PrivilegedPod [NodeConformance]", func() { config := &PrivilegedPodTestConfig{ f: framework.NewDefaultFramework("e2e-privileged-pod"), privilegedPod: "privileged-pod", diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/projected.go b/vendor/k8s.io/kubernetes/test/e2e/common/projected.go index 099d2ecc4..6a3e735b5 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/projected.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/projected.go @@ -39,7 +39,7 @@ var _ = Describe("[sig-storage] Projected", func() { Testname: projected-secret-no-defaultMode Description: Simple projected Secret test with no defaultMode set. */ - framework.ConformanceIt("should be consumable from pods in volume", func() { + framework.ConformanceIt("should be consumable from pods in volume [NodeConformance]", func() { doProjectedSecretE2EWithoutMapping(f, nil /* default mode */, "projected-secret-test-"+string(uuid.NewUUID()), nil, nil) }) @@ -47,7 +47,7 @@ var _ = Describe("[sig-storage] Projected", func() { Testname: projected-secret-with-defaultMode Description: Simple projected Secret test with defaultMode set. */ - framework.ConformanceIt("should be consumable from pods in volume with defaultMode set", func() { + framework.ConformanceIt("should be consumable from pods in volume with defaultMode set [NodeConformance]", func() { defaultMode := int32(0400) doProjectedSecretE2EWithoutMapping(f, &defaultMode, "projected-secret-test-"+string(uuid.NewUUID()), nil, nil) }) @@ -57,7 +57,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Simple projected Secret test as non-root with defaultMode and fsGroup set. */ - framework.ConformanceIt("should be consumable from pods in volume as non-root with defaultMode and fsGroup set", func() { + framework.ConformanceIt("should be consumable from pods in volume as non-root with defaultMode and fsGroup set [NodeConformance]", func() { defaultMode := int32(0440) /* setting fsGroup sets mode to at least 440 */ fsGroup := int64(1001) uid := int64(1000) @@ -70,7 +70,7 @@ var _ = Describe("[sig-storage] Projected", func() { mounting it to a volume with a custom path (mapping) on the pod with no other settings and make sure the pod actually consumes it. */ - framework.ConformanceIt("should be consumable from pods in volume with mappings", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings [NodeConformance]", func() { doProjectedSecretE2EWithMapping(f, nil) }) @@ -79,12 +79,12 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Repeat the projected-secret-simple-mapped but this time with an item mode (e.g. 0400) for the secret map item. */ - framework.ConformanceIt("should be consumable from pods in volume with mappings and Item Mode set", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings and Item Mode set [NodeConformance]", func() { mode := int32(0400) doProjectedSecretE2EWithMapping(f, &mode) }) - It("should be able to mount in a volume regardless of a different secret existing with same name in different namespace", func() { + It("should be able to mount in a volume regardless of a different secret existing with same name in different namespace [NodeConformance]", func() { var ( namespace2 *v1.Namespace err error @@ -110,7 +110,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Make sure secrets works when mounted as two different volumes on the same node. */ - framework.ConformanceIt("should be consumable in multiple volumes in a pod", func() { + framework.ConformanceIt("should be consumable in multiple volumes in a pod [NodeConformance]", func() { // This test ensures that the same secret can be mounted in multiple // volumes in the same pod. This test case exists to prevent // regressions that break this use-case. @@ -203,7 +203,7 @@ var _ = Describe("[sig-storage] Projected", func() { Testname: projected-secret-simple-optional Description: Make sure secrets works when optional updates included. */ - framework.ConformanceIt("optional updates should be reflected in volume", func() { + framework.ConformanceIt("optional updates should be reflected in volume [NodeConformance]", func() { podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) trueVal := true @@ -405,7 +405,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Make sure that a projected volume with a configMap with no mappings succeeds properly. */ - framework.ConformanceIt("should be consumable from pods in volume", func() { + framework.ConformanceIt("should be consumable from pods in volume [NodeConformance]", func() { doProjectedConfigMapE2EWithoutMappings(f, 0, 0, nil) }) @@ -414,12 +414,12 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Make sure that a projected volume configMap is consumable with defaultMode set. */ - framework.ConformanceIt("should be consumable from pods in volume with defaultMode set", func() { + framework.ConformanceIt("should be consumable from pods in volume with defaultMode set [NodeConformance]", func() { defaultMode := int32(0400) doProjectedConfigMapE2EWithoutMappings(f, 0, 0, &defaultMode) }) - It("should be consumable from pods in volume as non-root with defaultMode and fsGroup set [Feature:FSGroup]", func() { + It("should be consumable from pods in volume as non-root with defaultMode and fsGroup set [NodeFeature:FSGroup]", func() { defaultMode := int32(0440) /* setting fsGroup sets mode to at least 440 */ doProjectedConfigMapE2EWithoutMappings(f, 1000, 1001, &defaultMode) }) @@ -429,11 +429,11 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Make sure that a projected volume configMap is consumable by a non-root userID. */ - framework.ConformanceIt("should be consumable from pods in volume as non-root", func() { + framework.ConformanceIt("should be consumable from pods in volume as non-root [NodeConformance]", func() { doProjectedConfigMapE2EWithoutMappings(f, 1000, 0, nil) }) - It("should be consumable from pods in volume as non-root with FSGroup [Feature:FSGroup]", func() { + It("should be consumable from pods in volume as non-root with FSGroup [NodeFeature:FSGroup]", func() { doProjectedConfigMapE2EWithoutMappings(f, 1000, 1001, nil) }) @@ -443,7 +443,7 @@ var _ = Describe("[sig-storage] Projected", func() { map and mounting it to a volume with a custom path (mapping) on the pod with no other settings and make sure the pod actually consumes it. */ - framework.ConformanceIt("should be consumable from pods in volume with mappings", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings [NodeConformance]", func() { doProjectedConfigMapE2EWithMappings(f, 0, 0, nil) }) @@ -452,7 +452,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Repeat the projected-secret-simple-mapped but this time with an item mode (e.g. 0400) for the secret map item */ - framework.ConformanceIt("should be consumable from pods in volume with mappings and Item mode set", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings and Item mode set [NodeConformance]", func() { mode := int32(0400) doProjectedConfigMapE2EWithMappings(f, 0, 0, &mode) }) @@ -462,11 +462,11 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Repeat the projected-config-map-simple-mapped but this time with a user other than root. */ - framework.ConformanceIt("should be consumable from pods in volume with mappings as non-root", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings as non-root [NodeConformance]", func() { doProjectedConfigMapE2EWithMappings(f, 1000, 0, nil) }) - It("should be consumable from pods in volume with mappings as non-root with FSGroup [Feature:FSGroup]", func() { + It("should be consumable from pods in volume with mappings as non-root with FSGroup [NodeFeature:FSGroup]", func() { doProjectedConfigMapE2EWithMappings(f, 1000, 1001, nil) }) @@ -476,7 +476,7 @@ var _ = Describe("[sig-storage] Projected", func() { that the values in these configMaps can be updated, deleted, and created. */ - framework.ConformanceIt("updates should be reflected in volume", func() { + framework.ConformanceIt("updates should be reflected in volume [NodeConformance]", func() { podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) @@ -565,7 +565,7 @@ var _ = Describe("[sig-storage] Projected", func() { configMaps, that the values in these configMaps can be updated, deleted, and created. */ - framework.ConformanceIt("optional updates should be reflected in volume", func() { + framework.ConformanceIt("optional updates should be reflected in volume [NodeConformance]", func() { podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) trueVal := true @@ -766,7 +766,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Make sure config map works when it mounted as two different volumes on the same node. */ - framework.ConformanceIt("should be consumable in multiple volumes in the same pod", func() { + framework.ConformanceIt("should be consumable in multiple volumes in the same pod [NodeConformance]", func() { var ( name = "projected-configmap-test-volume-" + string(uuid.NewUUID()) volumeName = "projected-configmap-volume" @@ -864,7 +864,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Ensure that downward API can provide pod's name through DownwardAPIVolumeFiles in a projected volume. */ - framework.ConformanceIt("should provide podname only", func() { + framework.ConformanceIt("should provide podname only [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumePodForSimpleTest(podName, "/etc/podinfo/podname") @@ -879,7 +879,7 @@ var _ = Describe("[sig-storage] Projected", func() { mode for DownwardAPIVolumeFiles if no mode is specified in a projected volume. */ - framework.ConformanceIt("should set DefaultMode on files", func() { + framework.ConformanceIt("should set DefaultMode on files [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) defaultMode := int32(0400) pod := projectedDownwardAPIVolumePodForModeTest(podName, "/etc/podinfo/podname", nil, &defaultMode) @@ -894,7 +894,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Ensure that downward API can set file permission mode for DownwardAPIVolumeFiles in a projected volume. */ - framework.ConformanceIt("should set mode on item file", func() { + framework.ConformanceIt("should set mode on item file [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) mode := int32(0400) pod := projectedDownwardAPIVolumePodForModeTest(podName, "/etc/podinfo/podname", &mode, nil) @@ -904,7 +904,7 @@ var _ = Describe("[sig-storage] Projected", func() { }) }) - It("should provide podname as non-root with fsgroup [Feature:FSGroup]", func() { + It("should provide podname as non-root with fsgroup [NodeFeature:FSGroup]", func() { podName := "metadata-volume-" + string(uuid.NewUUID()) uid := int64(1001) gid := int64(1234) @@ -918,7 +918,7 @@ var _ = Describe("[sig-storage] Projected", func() { }) }) - It("should provide podname as non-root with fsgroup and defaultMode [Feature:FSGroup]", func() { + It("should provide podname as non-root with fsgroup and defaultMode [NodeFeature:FSGroup]", func() { podName := "metadata-volume-" + string(uuid.NewUUID()) uid := int64(1001) gid := int64(1234) @@ -939,7 +939,7 @@ var _ = Describe("[sig-storage] Projected", func() { DownwardAPIVolumeFiles when pod's labels get modified in a projected volume. */ - framework.ConformanceIt("should update labels on modification", func() { + framework.ConformanceIt("should update labels on modification [NodeConformance]", func() { labels := map[string]string{} labels["key1"] = "value1" labels["key2"] = "value2" @@ -972,7 +972,7 @@ var _ = Describe("[sig-storage] Projected", func() { DownwardAPIVolumeFiles when pod's annotations get modified in a projected volume. */ - framework.ConformanceIt("should update annotations on modification", func() { + framework.ConformanceIt("should update annotations on modification [NodeConformance]", func() { annotations := map[string]string{} annotations["builder"] = "bar" podName := "annotationupdate" + string(uuid.NewUUID()) @@ -1006,7 +1006,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Ensure that downward API can provide container's CPU limit through DownwardAPIVolumeFiles in a projected volume. */ - framework.ConformanceIt("should provide container's cpu limit", func() { + framework.ConformanceIt("should provide container's cpu limit [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForContainerResources(podName, "/etc/podinfo/cpu_limit") @@ -1020,7 +1020,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Ensure that downward API can provide container's memory limit through DownwardAPIVolumeFiles in a projected volume. */ - framework.ConformanceIt("should provide container's memory limit", func() { + framework.ConformanceIt("should provide container's memory limit [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForContainerResources(podName, "/etc/podinfo/memory_limit") @@ -1034,7 +1034,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Ensure that downward API can provide container's CPU request through DownwardAPIVolumeFiles in a projected volume. */ - framework.ConformanceIt("should provide container's cpu request", func() { + framework.ConformanceIt("should provide container's cpu request [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForContainerResources(podName, "/etc/podinfo/cpu_request") @@ -1048,7 +1048,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: Ensure that downward API can provide container's memory request through DownwardAPIVolumeFiles in a projected volume. */ - framework.ConformanceIt("should provide container's memory request", func() { + framework.ConformanceIt("should provide container's memory request [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForContainerResources(podName, "/etc/podinfo/memory_request") @@ -1063,7 +1063,7 @@ var _ = Describe("[sig-storage] Projected", func() { allocatable value for CPU through DownwardAPIVolumeFiles if CPU limit is not specified for a container in a projected volume. */ - framework.ConformanceIt("should provide node allocatable (cpu) as default cpu limit if the limit is not set", func() { + framework.ConformanceIt("should provide node allocatable (cpu) as default cpu limit if the limit is not set [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForDefaultContainerResources(podName, "/etc/podinfo/cpu_limit") @@ -1076,7 +1076,7 @@ var _ = Describe("[sig-storage] Projected", func() { allocatable value for memory through DownwardAPIVolumeFiles if memory limit is not specified for a container in a projected volume. */ - framework.ConformanceIt("should provide node allocatable (memory) as default memory limit if the limit is not set", func() { + framework.ConformanceIt("should provide node allocatable (memory) as default memory limit if the limit is not set [NodeConformance]", func() { podName := "downwardapi-volume-" + string(uuid.NewUUID()) pod := downwardAPIVolumeForDefaultContainerResources(podName, "/etc/podinfo/memory_limit") @@ -1089,7 +1089,7 @@ var _ = Describe("[sig-storage] Projected", func() { Description: This test projects a secret and configmap into the same directory to ensure projection is working as intended. */ - framework.ConformanceIt("should project all components that make up the projection API [Projection]", func() { + framework.ConformanceIt("should project all components that make up the projection API [Projection][NodeConformance]", func() { var err error podName := "projected-volume-" + string(uuid.NewUUID()) secretName := "secret-projected-all-test-volume-" + string(uuid.NewUUID()) diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/secrets.go b/vendor/k8s.io/kubernetes/test/e2e/common/secrets.go index 895e0bcdf..0bb329ddd 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/secrets.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/secrets.go @@ -35,7 +35,7 @@ var _ = Describe("[sig-api-machinery] Secrets", func() { Description: Ensure that secret can be consumed via environment variables. */ - framework.ConformanceIt("should be consumable from pods in env vars ", func() { + framework.ConformanceIt("should be consumable from pods in env vars [NodeConformance]", func() { name := "secret-test-" + string(uuid.NewUUID()) secret := secretForTest(f.Namespace.Name, name) @@ -84,7 +84,7 @@ var _ = Describe("[sig-api-machinery] Secrets", func() { Description: Ensure that secret can be consumed via source of a set of ConfigMaps. */ - framework.ConformanceIt("should be consumable via the environment ", func() { + framework.ConformanceIt("should be consumable via the environment [NodeConformance]", func() { name := "secret-test-" + string(uuid.NewUUID()) secret := newEnvFromSecret(f.Namespace.Name, name) By(fmt.Sprintf("creating secret %v/%v", f.Namespace.Name, secret.Name)) diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/secrets_volume.go b/vendor/k8s.io/kubernetes/test/e2e/common/secrets_volume.go index 1a3704870..a65c6e9db 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/secrets_volume.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/secrets_volume.go @@ -38,7 +38,7 @@ var _ = Describe("[sig-storage] Secrets", func() { Description: Ensure that secret can be mounted without mapping to a pod volume. */ - framework.ConformanceIt("should be consumable from pods in volume ", func() { + framework.ConformanceIt("should be consumable from pods in volume [NodeConformance]", func() { doSecretE2EWithoutMapping(f, nil /* default mode */, "secret-test-"+string(uuid.NewUUID()), nil, nil) }) @@ -47,7 +47,7 @@ var _ = Describe("[sig-storage] Secrets", func() { Description: Ensure that secret can be mounted without mapping to a pod volume in default mode. */ - framework.ConformanceIt("should be consumable from pods in volume with defaultMode set ", func() { + framework.ConformanceIt("should be consumable from pods in volume with defaultMode set [NodeConformance]", func() { defaultMode := int32(0400) doSecretE2EWithoutMapping(f, &defaultMode, "secret-test-"+string(uuid.NewUUID()), nil, nil) }) @@ -57,7 +57,7 @@ var _ = Describe("[sig-storage] Secrets", func() { Description: Ensure that secret can be mounted without mapping to a pod volume as non-root in default mode with fsGroup set. */ - framework.ConformanceIt("should be consumable from pods in volume as non-root with defaultMode and fsGroup set ", func() { + framework.ConformanceIt("should be consumable from pods in volume as non-root with defaultMode and fsGroup set [NodeConformance]", func() { defaultMode := int32(0440) /* setting fsGroup sets mode to at least 440 */ fsGroup := int64(1001) uid := int64(1000) @@ -69,7 +69,7 @@ var _ = Describe("[sig-storage] Secrets", func() { Description: Ensure that secret can be mounted with mapping to a pod volume. */ - framework.ConformanceIt("should be consumable from pods in volume with mappings ", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings [NodeConformance]", func() { doSecretE2EWithMapping(f, nil) }) @@ -78,12 +78,12 @@ var _ = Describe("[sig-storage] Secrets", func() { Description: Ensure that secret can be mounted with mapping to a pod volume in item mode. */ - framework.ConformanceIt("should be consumable from pods in volume with mappings and Item Mode set ", func() { + framework.ConformanceIt("should be consumable from pods in volume with mappings and Item Mode set [NodeConformance]", func() { mode := int32(0400) doSecretE2EWithMapping(f, &mode) }) - It("should be able to mount in a volume regardless of a different secret existing with same name in different namespace", func() { + It("should be able to mount in a volume regardless of a different secret existing with same name in different namespace [NodeConformance]", func() { var ( namespace2 *v1.Namespace err error @@ -108,7 +108,7 @@ var _ = Describe("[sig-storage] Secrets", func() { Testname: secret-multiple-volume-mounts Description: Ensure that secret can be mounted to multiple pod volumes. */ - framework.ConformanceIt("should be consumable in multiple volumes in a pod ", func() { + framework.ConformanceIt("should be consumable in multiple volumes in a pod [NodeConformance]", func() { // This test ensures that the same secret can be mounted in multiple // volumes in the same pod. This test case exists to prevent // regressions that break this use-case. @@ -186,7 +186,7 @@ var _ = Describe("[sig-storage] Secrets", func() { Description: Ensure that optional update change to secret can be reflected on a mounted volume. */ - framework.ConformanceIt("optional updates should be reflected in volume ", func() { + framework.ConformanceIt("optional updates should be reflected in volume [NodeConformance]", func() { podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) trueVal := true diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/sysctl.go b/vendor/k8s.io/kubernetes/test/e2e/common/sysctl.go index aa05d109a..6ae2c5a0e 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/sysctl.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/sysctl.go @@ -20,7 +20,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/kubelet/sysctl" "k8s.io/kubernetes/test/e2e/framework" @@ -28,7 +27,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = framework.KubeDescribe("Sysctls", func() { +var _ = framework.KubeDescribe("Sysctls [NodeFeature:Sysctls]", func() { f := framework.NewDefaultFramework("sysctl") var podClient *framework.PodClient @@ -59,12 +58,14 @@ var _ = framework.KubeDescribe("Sysctls", func() { It("should support sysctls", func() { pod := testPod() - pod.Annotations[v1.SysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "kernel.shm_rmid_forced", - Value: "1", + pod.Spec.SecurityContext = &v1.PodSecurityContext{ + Sysctls: []v1.Sysctl{ + { + Name: "kernel.shm_rmid_forced", + Value: "1", + }, }, - }) + } pod.Spec.Containers[0].Command = []string{"/bin/sysctl", "kernel.shm_rmid_forced"} By("Creating a pod with the kernel.shm_rmid_forced sysctl") @@ -100,12 +101,14 @@ var _ = framework.KubeDescribe("Sysctls", func() { It("should support unsafe sysctls which are actually whitelisted", func() { pod := testPod() - pod.Annotations[v1.UnsafeSysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "kernel.shm_rmid_forced", - Value: "1", + pod.Spec.SecurityContext = &v1.PodSecurityContext{ + Sysctls: []v1.Sysctl{ + { + Name: "kernel.shm_rmid_forced", + Value: "1", + }, }, - }) + } pod.Spec.Containers[0].Command = []string{"/bin/sysctl", "kernel.shm_rmid_forced"} By("Creating a pod with the kernel.shm_rmid_forced sysctl") @@ -141,34 +144,27 @@ var _ = framework.KubeDescribe("Sysctls", func() { It("should reject invalid sysctls", func() { pod := testPod() - pod.Annotations[v1.SysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "foo-", - Value: "bar", - }, - { - Name: "kernel.shmmax", - Value: "100000000", - }, - { - Name: "safe-and-unsafe", - Value: "100000000", - }, - }) - pod.Annotations[v1.UnsafeSysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "kernel.shmall", - Value: "100000000", - }, - { - Name: "bar..", - Value: "42", - }, - { - Name: "safe-and-unsafe", - Value: "100000000", + pod.Spec.SecurityContext = &v1.PodSecurityContext{ + Sysctls: []v1.Sysctl{ + // Safe parameters + { + Name: "foo-", + Value: "bar", + }, + { + Name: "kernel.shmmax", + Value: "100000000", + }, + { + Name: "safe-and-unsafe", + Value: "100000000", + }, + { + Name: "bar..", + Value: "42", + }, }, - }) + } By("Creating a pod with one valid and two invalid sysctls") client := f.ClientSet.CoreV1().Pods(f.Namespace.Name) @@ -177,18 +173,20 @@ var _ = framework.KubeDescribe("Sysctls", func() { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(`Invalid value: "foo-"`)) Expect(err.Error()).To(ContainSubstring(`Invalid value: "bar.."`)) - Expect(err.Error()).To(ContainSubstring(`safe-and-unsafe`)) + Expect(err.Error()).NotTo(ContainSubstring(`safe-and-unsafe`)) Expect(err.Error()).NotTo(ContainSubstring("kernel.shmmax")) }) It("should not launch unsafe, but not explicitly enabled sysctls on the node", func() { pod := testPod() - pod.Annotations[v1.SysctlsPodAnnotationKey] = v1helper.PodAnnotationsFromSysctls([]v1.Sysctl{ - { - Name: "kernel.msgmax", - Value: "10000000000", + pod.Spec.SecurityContext = &v1.PodSecurityContext{ + Sysctls: []v1.Sysctl{ + { + Name: "kernel.msgmax", + Value: "10000000000", + }, }, - }) + } By("Creating a pod with a greylisted, but not whitelisted sysctl on the node") pod = podClient.Create(pod) diff --git a/vendor/k8s.io/kubernetes/test/e2e/common/volumes.go b/vendor/k8s.io/kubernetes/test/e2e/common/volumes.go index 24a9752b2..e6df9b5a0 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/common/volumes.go +++ b/vendor/k8s.io/kubernetes/test/e2e/common/volumes.go @@ -62,7 +62,7 @@ var _ = Describe("[sig-storage] GCP Volumes", func() { var c clientset.Interface BeforeEach(func() { - framework.SkipUnlessNodeOSDistroIs("gci", "ubuntu") + framework.SkipUnlessNodeOSDistroIs("gci", "ubuntu", "custom") namespace = f.Namespace c = f.ClientSet diff --git a/vendor/k8s.io/kubernetes/test/e2e/e2e.go b/vendor/k8s.io/kubernetes/test/e2e/e2e.go index d4ec18e3c..853cbc78e 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/e2e.go +++ b/vendor/k8s.io/kubernetes/test/e2e/e2e.go @@ -43,6 +43,9 @@ import ( "k8s.io/kubernetes/test/e2e/framework/metrics" "k8s.io/kubernetes/test/e2e/manifest" testutils "k8s.io/kubernetes/test/utils" + + // ensure auth plugins are loaded + _ "k8s.io/client-go/plugin/pkg/client/auth" ) var ( @@ -72,12 +75,9 @@ func setupProviderConfig() error { managedZones = []string{zone} } - gceAlphaFeatureGate, err := gcecloud.NewAlphaFeatureGate([]string{ + gceAlphaFeatureGate := gcecloud.NewAlphaFeatureGate([]string{ gcecloud.AlphaFeatureNetworkEndpointGroup, }) - if err != nil { - glog.Errorf("Encountered error for creating alpha feature gate: %v", err) - } gceCloud, err := gcecloud.CreateGCECloud(&gcecloud.CloudConfig{ ApiEndpoint: framework.TestContext.CloudConfig.ApiEndpoint, diff --git a/vendor/k8s.io/kubernetes/test/e2e/examples.go b/vendor/k8s.io/kubernetes/test/e2e/examples.go index 6fa937c89..bb7427f5a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/examples.go +++ b/vendor/k8s.io/kubernetes/test/e2e/examples.go @@ -521,7 +521,7 @@ var _ = framework.KubeDescribe("[Feature:Example]", func() { Expect(err).NotTo(HaveOccurred()) By("scaling rethinkdb") - framework.ScaleRC(f.ClientSet, f.InternalClientset, f.ScalesGetter, ns, "rethinkdb-rc", 2, true) + framework.ScaleRC(f.ClientSet, f.ScalesGetter, ns, "rethinkdb-rc", 2, true) checkDbInstances() By("starting admin") @@ -564,7 +564,7 @@ var _ = framework.KubeDescribe("[Feature:Example]", func() { Expect(err).NotTo(HaveOccurred()) By("scaling hazelcast") - framework.ScaleRC(f.ClientSet, f.InternalClientset, f.ScalesGetter, ns, "hazelcast", 2, true) + framework.ScaleRC(f.ClientSet, f.ScalesGetter, ns, "hazelcast", 2, true) forEachPod("name", "hazelcast", func(pod v1.Pod) { _, err := framework.LookForStringInLog(ns, pod.Name, "hazelcast", "Members [2]", serverStartTimeout) Expect(err).NotTo(HaveOccurred()) diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/BUILD b/vendor/k8s.io/kubernetes/test/e2e/framework/BUILD index 3784978b5..fc650ed9f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/BUILD @@ -45,7 +45,6 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e/framework", deps = [ "//pkg/api/legacyscheme:go_default_library", - "//pkg/api/testapi:go_default_library", "//pkg/api/v1/pod:go_default_library", "//pkg/apis/apps:go_default_library", "//pkg/apis/batch:go_default_library", @@ -61,7 +60,6 @@ go_library( "//pkg/controller/deployment/util:go_default_library", "//pkg/controller/nodelifecycle:go_default_library", "//pkg/features:go_default_library", - "//pkg/kubectl:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/stats/v1alpha1:go_default_library", @@ -73,7 +71,8 @@ go_library( "//pkg/kubemark:go_default_library", "//pkg/master/ports:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", + "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/metrics:go_default_library", "//pkg/security/podsecuritypolicy/seccomp:go_default_library", "//pkg/ssh:go_default_library", "//pkg/util/file:go_default_library", @@ -116,10 +115,8 @@ go_library( "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/test/integration/testserver:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta: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/apis/meta/v1/unstructured: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/runtime:go_default_library", @@ -144,11 +141,12 @@ go_library( "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/authorization/v1beta1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1beta1:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", "//vendor/k8s.io/client-go/scale:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/crd_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/crd_util.go index 8fb19abbc..f7db7daef 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/crd_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/crd_util.go @@ -23,6 +23,7 @@ import ( crdclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/testserver" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" ) @@ -66,18 +67,23 @@ func CreateTestCRD(f *Framework) (*TestCrd, error) { Failf("failed to initialize apiExtensionClient: %v", err) return nil, err } + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + Failf("failed to initialize dynamic client: %v", err) + return nil, err + } + crd := newCRDForTest(testcrd) //create CRD and waits for the resource to be recognized and available. - dynamicClient, err := testserver.CreateNewCustomResourceDefinitionWatchUnsafe(crd, apiExtensionClient, f.ClientPool) + crd, err = testserver.CreateNewCustomResourceDefinitionWatchUnsafe(crd, apiExtensionClient) if err != nil { Failf("failed to create CustomResourceDefinition: %v", err) return nil, err } - resourceClient := dynamicClient.Resource(&metav1.APIResource{ - Name: crd.Spec.Names.Plural, - Namespaced: true, - }, f.Namespace.Name) + + gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural} + resourceClient := dynamicClient.Resource(gvr).Namespace(f.Namespace.Name) testcrd.ApiExtensionClient = apiExtensionClient testcrd.Crd = crd diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/deployment_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/deployment_util.go index fe7dfab0f..ea863466d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/deployment_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/deployment_util.go @@ -22,37 +22,36 @@ import ( . "github.com/onsi/ginkgo" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" clientset "k8s.io/client-go/kubernetes" scaleclient "k8s.io/client-go/scale" - extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + appsinternal "k8s.io/kubernetes/pkg/apis/apps" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" testutils "k8s.io/kubernetes/test/utils" ) -func UpdateDeploymentWithRetries(c clientset.Interface, namespace, name string, applyUpdate testutils.UpdateDeploymentFunc) (*extensions.Deployment, error) { +func UpdateDeploymentWithRetries(c clientset.Interface, namespace, name string, applyUpdate testutils.UpdateDeploymentFunc) (*apps.Deployment, error) { return testutils.UpdateDeploymentWithRetries(c, namespace, name, applyUpdate, Logf, Poll, pollShortTimeout) } // Waits for the deployment to clean up old rcs. func WaitForDeploymentOldRSsNum(c clientset.Interface, ns, deploymentName string, desiredRSNum int) error { - var oldRSs []*extensions.ReplicaSet - var d *extensions.Deployment + var oldRSs []*apps.ReplicaSet + var d *apps.Deployment pollErr := wait.PollImmediate(Poll, 5*time.Minute, func() (bool, error) { - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) if err != nil { return false, err } d = deployment - _, oldRSs, err = deploymentutil.GetOldReplicaSets(deployment, c.ExtensionsV1beta1()) + _, oldRSs, err = deploymentutil.GetOldReplicaSets(deployment, c.AppsV1()) if err != nil { return false, err } @@ -65,7 +64,7 @@ func WaitForDeploymentOldRSsNum(c clientset.Interface, ns, deploymentName string return pollErr } -func logReplicaSetsOfDeployment(deployment *extensions.Deployment, allOldRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet) { +func logReplicaSetsOfDeployment(deployment *apps.Deployment, allOldRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet) { testutils.LogReplicaSetsOfDeployment(deployment, allOldRSs, newRS, Logf) } @@ -73,7 +72,7 @@ func WaitForObservedDeployment(c clientset.Interface, ns, deploymentName string, return testutils.WaitForObservedDeployment(c, ns, deploymentName, desiredGeneration) } -func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, reason string, condType extensions.DeploymentConditionType) error { +func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, reason string, condType apps.DeploymentConditionType) error { return testutils.WaitForDeploymentWithCondition(c, ns, deploymentName, reason, condType, Logf, Poll, pollLongTimeout) } @@ -84,16 +83,17 @@ func WaitForDeploymentRevisionAndImage(c clientset.Interface, ns, deploymentName return testutils.WaitForDeploymentRevisionAndImage(c, ns, deploymentName, revision, image, Logf, Poll, pollLongTimeout) } -func NewDeployment(deploymentName string, replicas int32, podLabels map[string]string, imageName, image string, strategyType extensions.DeploymentStrategyType) *extensions.Deployment { +func NewDeployment(deploymentName string, replicas int32, podLabels map[string]string, imageName, image string, strategyType apps.DeploymentStrategyType) *apps.Deployment { zero := int64(0) - return &extensions.Deployment{ + return &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Name: deploymentName, + Name: deploymentName, + Labels: podLabels, }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: &replicas, Selector: &metav1.LabelSelector{MatchLabels: podLabels}, - Strategy: extensions.DeploymentStrategy{ + Strategy: apps.DeploymentStrategy{ Type: strategyType, }, Template: v1.PodTemplateSpec{ @@ -117,13 +117,13 @@ func NewDeployment(deploymentName string, replicas int32, podLabels map[string]s // Waits for the deployment to complete, and don't check if rolling update strategy is broken. // Rolling update strategy is used only during a rolling update, and can be violated in other situations, // such as shortly after a scaling event or the deployment is just created. -func WaitForDeploymentComplete(c clientset.Interface, d *extensions.Deployment) error { +func WaitForDeploymentComplete(c clientset.Interface, d *apps.Deployment) error { return testutils.WaitForDeploymentComplete(c, d, Logf, Poll, pollLongTimeout) } // Waits for the deployment to complete, and check rolling update strategy isn't broken at any times. // Rolling update strategy should not be broken during a rolling update. -func WaitForDeploymentCompleteAndCheckRolling(c clientset.Interface, d *extensions.Deployment) error { +func WaitForDeploymentCompleteAndCheckRolling(c clientset.Interface, d *apps.Deployment) error { return testutils.WaitForDeploymentCompleteAndCheckRolling(c, d, Logf, Poll, pollLongTimeout) } @@ -140,12 +140,12 @@ func WaitForDeploymentRollbackCleared(c clientset.Interface, ns, deploymentName // WatchRecreateDeployment watches Recreate deployments and ensures no new pods will run at the same time with // old pods. -func WatchRecreateDeployment(c clientset.Interface, d *extensions.Deployment) error { - if d.Spec.Strategy.Type != extensions.RecreateDeploymentStrategyType { +func WatchRecreateDeployment(c clientset.Interface, d *apps.Deployment) error { + if d.Spec.Strategy.Type != apps.RecreateDeploymentStrategyType { return fmt.Errorf("deployment %q does not use a Recreate strategy: %s", d.Name, d.Spec.Strategy.Type) } - w, err := c.ExtensionsV1beta1().Deployments(d.Namespace).Watch(metav1.SingleObject(metav1.ObjectMeta{Name: d.Name, ResourceVersion: d.ResourceVersion})) + w, err := c.AppsV1().Deployments(d.Namespace).Watch(metav1.SingleObject(metav1.ObjectMeta{Name: d.Name, ResourceVersion: d.ResourceVersion})) if err != nil { return err } @@ -153,12 +153,12 @@ func WatchRecreateDeployment(c clientset.Interface, d *extensions.Deployment) er status := d.Status condition := func(event watch.Event) (bool, error) { - d := event.Object.(*extensions.Deployment) + d := event.Object.(*apps.Deployment) status = d.Status if d.Status.UpdatedReplicas > 0 && d.Status.Replicas != d.Status.UpdatedReplicas { - _, allOldRSs, err := deploymentutil.GetOldReplicaSets(d, c.ExtensionsV1beta1()) - newRS, nerr := deploymentutil.GetNewReplicaSet(d, c.ExtensionsV1beta1()) + _, allOldRSs, err := deploymentutil.GetOldReplicaSets(d, c.AppsV1()) + newRS, nerr := deploymentutil.GetNewReplicaSet(d, c.AppsV1()) if err == nil && nerr == nil { Logf("%+v", d) logReplicaSetsOfDeployment(d, allOldRSs, newRS) @@ -179,8 +179,8 @@ func WatchRecreateDeployment(c clientset.Interface, d *extensions.Deployment) er return err } -func ScaleDeployment(clientset clientset.Interface, internalClientset internalclientset.Interface, scalesGetter scaleclient.ScalesGetter, ns, name string, size uint, wait bool) error { - return ScaleResource(clientset, internalClientset, scalesGetter, ns, name, size, wait, extensionsinternal.Kind("Deployment"), extensionsinternal.Resource("deployments")) +func ScaleDeployment(clientset clientset.Interface, scalesGetter scaleclient.ScalesGetter, ns, name string, size uint, wait bool) error { + return ScaleResource(clientset, scalesGetter, ns, name, size, wait, appsinternal.Kind("Deployment"), appsinternal.Resource("deployments")) } func RunDeployment(config testutils.DeploymentConfig) error { @@ -190,13 +190,13 @@ func RunDeployment(config testutils.DeploymentConfig) error { return testutils.RunDeployment(config) } -func logPodsOfDeployment(c clientset.Interface, deployment *extensions.Deployment, rsList []*extensions.ReplicaSet) { +func logPodsOfDeployment(c clientset.Interface, deployment *apps.Deployment, rsList []*apps.ReplicaSet) { testutils.LogPodsOfDeployment(c, deployment, rsList, Logf) } -func WaitForDeploymentRevision(c clientset.Interface, d *extensions.Deployment, targetRevision string) error { +func WaitForDeploymentRevision(c clientset.Interface, d *apps.Deployment, targetRevision string) error { err := wait.PollImmediate(Poll, pollLongTimeout, func() (bool, error) { - deployment, err := c.ExtensionsV1beta1().Deployments(d.Namespace).Get(d.Name, metav1.GetOptions{}) + deployment, err := c.AppsV1().Deployments(d.Namespace).Get(d.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -214,9 +214,9 @@ func CheckDeploymentRevisionAndImage(c clientset.Interface, ns, deploymentName, return testutils.CheckDeploymentRevisionAndImage(c, ns, deploymentName, revision, image) } -func CreateDeployment(client clientset.Interface, replicas int32, podLabels map[string]string, nodeSelector map[string]string, namespace string, pvclaims []*v1.PersistentVolumeClaim, command string) (*extensions.Deployment, error) { +func CreateDeployment(client clientset.Interface, replicas int32, podLabels map[string]string, nodeSelector map[string]string, namespace string, pvclaims []*v1.PersistentVolumeClaim, command string) (*apps.Deployment, error) { deploymentSpec := MakeDeployment(replicas, podLabels, nodeSelector, namespace, pvclaims, false, command) - deployment, err := client.ExtensionsV1beta1().Deployments(namespace).Create(deploymentSpec) + deployment, err := client.AppsV1().Deployments(namespace).Create(deploymentSpec) if err != nil { return nil, fmt.Errorf("deployment %q Create API error: %v", deploymentSpec.Name, err) } @@ -230,19 +230,22 @@ func CreateDeployment(client clientset.Interface, replicas int32, podLabels map[ // MakeDeployment creates a deployment definition based on the namespace. The deployment references the PVC's // name. A slice of BASH commands can be supplied as args to be run by the pod -func MakeDeployment(replicas int32, podLabels map[string]string, nodeSelector map[string]string, namespace string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) *extensions.Deployment { +func MakeDeployment(replicas int32, podLabels map[string]string, nodeSelector map[string]string, namespace string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) *apps.Deployment { if len(command) == 0 { - command = "while true; do sleep 1; done" + command = "trap exit TERM; while true; do sleep 1; done" } zero := int64(0) deploymentName := "deployment-" + string(uuid.NewUUID()) - deploymentSpec := &extensions.Deployment{ + deploymentSpec := &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: deploymentName, Namespace: namespace, }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: podLabels, + }, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: podLabels, @@ -281,8 +284,8 @@ func MakeDeployment(replicas int32, podLabels map[string]string, nodeSelector ma } // GetPodsForDeployment gets pods for the given deployment -func GetPodsForDeployment(client clientset.Interface, deployment *extensions.Deployment) (*v1.PodList, error) { - replicaSet, err := deploymentutil.GetNewReplicaSet(deployment, client.ExtensionsV1beta1()) +func GetPodsForDeployment(client clientset.Interface, deployment *apps.Deployment) (*v1.PodList, error) { + replicaSet, err := deploymentutil.GetNewReplicaSet(deployment, client.AppsV1()) if err != nil { return nil, fmt.Errorf("Failed to get new replica set for deployment %q: %v", deployment.Name, err) } @@ -292,7 +295,7 @@ func GetPodsForDeployment(client clientset.Interface, deployment *extensions.Dep podListFunc := func(namespace string, options metav1.ListOptions) (*v1.PodList, error) { return client.CoreV1().Pods(namespace).List(options) } - rsList := []*extensions.ReplicaSet{replicaSet} + rsList := []*apps.ReplicaSet{replicaSet} podList, err := deploymentutil.ListPods(deployment, rsList, podListFunc) if err != nil { return nil, fmt.Errorf("Failed to list Pods of Deployment %q: %v", deployment.Name, err) diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go b/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go index c81442154..d9a23c533 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go @@ -28,7 +28,6 @@ import ( "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" @@ -40,6 +39,7 @@ import ( "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" scaleclient "k8s.io/client-go/scale" "k8s.io/client-go/tools/clientcmd" aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" @@ -70,7 +70,7 @@ type Framework struct { InternalClientset *internalclientset.Clientset AggregatorClient *aggregatorclient.Clientset - ClientPool dynamic.ClientPool + DynamicClient dynamic.Interface ScalesGetter scaleclient.ScalesGetter @@ -167,7 +167,8 @@ func (f *Framework) BeforeEach() { Expect(err).NotTo(HaveOccurred()) f.AggregatorClient, err = aggregatorclient.NewForConfig(config) Expect(err).NotTo(HaveOccurred()) - f.ClientPool = dynamic.NewClientPool(config, legacyscheme.Registry.RESTMapper(), dynamic.LegacyAPIPathResolverFunc) + f.DynamicClient, err = dynamic.NewForConfig(config) + Expect(err).NotTo(HaveOccurred()) // create scales getter, set GroupVersion and NegotiatedSerializer to default values // as they are required when creating a REST client. @@ -182,7 +183,7 @@ func (f *Framework) BeforeEach() { discoClient, err := discovery.NewDiscoveryClientForConfig(config) Expect(err).NotTo(HaveOccurred()) cachedDiscoClient := cacheddiscovery.NewMemCacheClient(discoClient) - restMapper := discovery.NewDeferredDiscoveryRESTMapper(cachedDiscoClient, meta.InterfacesForUnstructured) + restMapper := restmapper.NewDeferredDiscoveryRESTMapper(cachedDiscoClient) restMapper.Reset() resolver := scaleclient.NewDiscoveryScaleKindResolver(cachedDiscoClient) f.ScalesGetter = scaleclient.New(restClient, restMapper, dynamic.LegacyAPIPathResolverFunc, resolver) @@ -288,7 +289,7 @@ func (f *Framework) AfterEach() { if f.NamespaceDeletionTimeout != 0 { timeout = f.NamespaceDeletionTimeout } - if err := deleteNS(f.ClientSet, f.ClientPool, ns.Name, timeout); err != nil { + if err := deleteNS(f.ClientSet, f.DynamicClient, ns.Name, timeout); err != nil { if !apierrors.IsNotFound(err) { nsDeletionErrors[ns.Name] = err } else { @@ -399,10 +400,7 @@ func (f *Framework) CreateNamespace(baseName string, labels map[string]string) ( ns, err := createTestingNS(baseName, f.ClientSet, labels) // check ns instead of err to see if it's nil as we may // fail to create serviceAccount in it. - // In this case, we should not forget to delete the namespace. - if ns != nil { - f.namespacesToDelete = append(f.namespacesToDelete, ns) - } + f.AddNamespacesToDelete(ns) if err == nil && !f.SkipPrivilegedPSPBinding { CreatePrivilegedPSPBinding(f, ns.Name) @@ -411,6 +409,18 @@ func (f *Framework) CreateNamespace(baseName string, labels map[string]string) ( return ns, err } +// AddNamespacesToDelete adds one or more namespaces to be deleted when the test +// completes. +func (f *Framework) AddNamespacesToDelete(namespaces ...*v1.Namespace) { + for _, ns := range namespaces { + if ns == nil { + continue + } + f.namespacesToDelete = append(f.namespacesToDelete, ns) + + } +} + // WaitForPodTerminated waits for the pod to be terminated with the given reason. func (f *Framework) WaitForPodTerminated(podName, reason string) error { return waitForPodTerminatedInNamespace(f.ClientSet, podName, reason, f.Namespace.Name) diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/get-kubemark-resource-usage.go b/vendor/k8s.io/kubernetes/test/e2e/framework/get-kubemark-resource-usage.go index e9748dcca..2d13cf929 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/get-kubemark-resource-usage.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/get-kubemark-resource-usage.go @@ -39,7 +39,7 @@ func getMasterUsageByPrefix(prefix string) (string, error) { // TODO: figure out how to move this to kubemark directory (need to factor test SSH out of e2e framework) func GetKubemarkMasterComponentsResourceUsage() map[string]*KubemarkResourceUsage { result := make(map[string]*KubemarkResourceUsage) - // Get kuberenetes component resource usage + // Get kubernetes component resource usage sshResult, err := getMasterUsageByPrefix("kube") if err != nil { Logf("Error when trying to SSH to master machine. Skipping probe. %v", err) diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/google_compute.go b/vendor/k8s.io/kubernetes/test/e2e/framework/google_compute.go index cf937b72f..3c1ed0d5c 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/google_compute.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/google_compute.go @@ -145,6 +145,28 @@ func CreateManagedInstanceGroup(size int64, zone, template string) error { return nil } +func GetManagedInstanceGroupTemplateName(zone string) (string, error) { + // TODO(verult): make this hit the compute API directly instead of + // shelling out to gcloud. Use InstanceGroupManager to get Instance Template name. + + stdout, _, err := retryCmd("gcloud", "compute", "instance-groups", "managed", + "list", + fmt.Sprintf("--filter=name:%s", TestContext.CloudConfig.NodeInstanceGroup), + fmt.Sprintf("--project=%s", TestContext.CloudConfig.ProjectID), + fmt.Sprintf("--zones=%s", zone), + ) + + if err != nil { + return "", fmt.Errorf("gcloud compute instance-groups managed list call failed with err: %v", err) + } + + templateName, err := parseInstanceTemplateName(stdout) + if err != nil { + return "", fmt.Errorf("error parsing gcloud output: %v", err) + } + return templateName, nil +} + func DeleteManagedInstanceGroup(zone string) error { // TODO(verult): make this hit the compute API directly instead of // shelling out to gcloud. @@ -158,3 +180,29 @@ func DeleteManagedInstanceGroup(zone string) error { } return nil } + +func parseInstanceTemplateName(gcloudOutput string) (string, error) { + const templateNameField = "INSTANCE_TEMPLATE" + + lines := strings.Split(gcloudOutput, "\n") + if len(lines) <= 1 { // Empty output or only contains column names + return "", fmt.Errorf("the list is empty") + } + + // Otherwise, there should be exactly 1 entry, i.e. 2 lines + fieldNames := strings.Fields(lines[0]) + instanceTemplateColumn := 0 + for instanceTemplateColumn < len(fieldNames) && + fieldNames[instanceTemplateColumn] != templateNameField { + instanceTemplateColumn++ + } + + if instanceTemplateColumn == len(fieldNames) { + return "", fmt.Errorf("the list does not contain instance template information") + } + + fields := strings.Fields(lines[1]) + instanceTemplateName := fields[instanceTemplateColumn] + + return instanceTemplateName, nil +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/gpu_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/gpu_util.go index 3cdf52202..2cd9f33ee 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/gpu_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/gpu_util.go @@ -32,7 +32,7 @@ const ( // TODO: Parametrize it by making it a feature in TestFramework. // so we can override the daemonset in other setups (non COS). // GPUDevicePluginDSYAML is the official Google Device Plugin Daemonset NVIDIA GPU manifest for GKE - GPUDevicePluginDSYAML = "https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.10/cluster/addons/device-plugins/nvidia-gpu/daemonset.yaml" + GPUDevicePluginDSYAML = "https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/device-plugins/nvidia-gpu/daemonset.yaml" ) // TODO make this generic and not linked to COS only diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/ingress_utils.go b/vendor/k8s.io/kubernetes/test/e2e/framework/ingress_utils.go index f565c90a9..f1d5b14a8 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/ingress_utils.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/ingress_utils.go @@ -20,6 +20,7 @@ import ( "bytes" "crypto/rand" "crypto/rsa" + "crypto/sha256" "crypto/tls" "crypto/x509" "crypto/x509/pkix" @@ -119,6 +120,16 @@ const ( // GCE only allows names < 64 characters, and the loadbalancer controller inserts // a single character of padding. nameLenLimit = 62 + + NEGAnnotation = "alpha.cloud.google.com/load-balancer-neg" + NEGUpdateTimeout = 2 * time.Minute + + InstanceGroupAnnotation = "ingress.gcp.kubernetes.io/instance-groups" + + // Prefix for annotation keys used by the ingress controller to specify the + // names of GCP resources such as forwarding rules, url maps, target proxies, etc + // that it created for the corresponding ingress. + StatusPrefix = "ingress.kubernetes.io" ) type TestLogger interface { @@ -165,7 +176,7 @@ func CreateIngressComformanceTests(jig *IngressTestJig, ns string, annotations m updateURLMapHost := "bar.baz.com" updateURLMapPath := "/testurl" // Platform agnostic list of tests that must be satisfied by all controllers - return []IngressConformanceTests{ + tests := []IngressConformanceTests{ { fmt.Sprintf("should create a basic HTTP ingress"), func() { jig.CreateIngress(manifestPath, ns, annotations, annotations) }, @@ -173,30 +184,9 @@ func CreateIngressComformanceTests(jig *IngressTestJig, ns string, annotations m }, { fmt.Sprintf("should terminate TLS for host %v", tlsHost), - func() { jig.AddHTTPS(tlsSecretName, tlsHost) }, + func() { jig.SetHTTPS(tlsSecretName, tlsHost) }, fmt.Sprintf("waiting for HTTPS updates to reflect in ingress"), }, - { - fmt.Sprintf("should update SSL certificate with modified hostname %v", updatedTLSHost), - func() { - jig.Update(func(ing *extensions.Ingress) { - newRules := []extensions.IngressRule{} - for _, rule := range ing.Spec.Rules { - if rule.Host != tlsHost { - newRules = append(newRules, rule) - continue - } - newRules = append(newRules, extensions.IngressRule{ - Host: updatedTLSHost, - IngressRuleValue: rule.IngressRuleValue, - }) - } - ing.Spec.Rules = newRules - }) - jig.AddHTTPS(tlsSecretName, updatedTLSHost) - }, - fmt.Sprintf("Waiting for updated certificates to accept requests for host %v", updatedTLSHost), - }, { fmt.Sprintf("should update url map for host %v to expose a single url: %v", updateURLMapHost, updateURLMapPath), func() { @@ -233,6 +223,31 @@ func CreateIngressComformanceTests(jig *IngressTestJig, ns string, annotations m fmt.Sprintf("Waiting for path updates to reflect in L7"), }, } + // Skip the Update TLS cert test for kubemci: https://github.com/GoogleCloudPlatform/k8s-multicluster-ingress/issues/141. + if jig.Class != MulticlusterIngressClassValue { + tests = append(tests, IngressConformanceTests{ + fmt.Sprintf("should update SSL certificate with modified hostname %v", updatedTLSHost), + func() { + jig.Update(func(ing *extensions.Ingress) { + newRules := []extensions.IngressRule{} + for _, rule := range ing.Spec.Rules { + if rule.Host != tlsHost { + newRules = append(newRules, rule) + continue + } + newRules = append(newRules, extensions.IngressRule{ + Host: updatedTLSHost, + IngressRuleValue: rule.IngressRuleValue, + }) + } + ing.Spec.Rules = newRules + }) + jig.SetHTTPS(tlsSecretName, updatedTLSHost) + }, + fmt.Sprintf("Waiting for updated certificates to accept requests for host %v", updatedTLSHost), + }) + } + return tests } // GenerateRSACerts generates a basic self signed certificate using a key length @@ -850,14 +865,24 @@ func (cont *GCEIngressController) GetFirewallRuleName() string { } // GetFirewallRule returns the firewall used by the GCEIngressController. +// Causes a fatal error incase of an error. +// TODO: Rename this to GetFirewallRuleOrDie and similarly rename all other +// methods here to be consistent with rest of the code in this repo. func (cont *GCEIngressController) GetFirewallRule() *compute.Firewall { - gceCloud := cont.Cloud.Provider.(*gcecloud.GCECloud) - fwName := cont.GetFirewallRuleName() - fw, err := gceCloud.GetFirewall(fwName) + fw, err := cont.GetFirewallRuleOrError() Expect(err).NotTo(HaveOccurred()) return fw } +// GetFirewallRule returns the firewall used by the GCEIngressController. +// Returns an error if that fails. +// TODO: Rename this to GetFirewallRule when the above method with that name is renamed. +func (cont *GCEIngressController) GetFirewallRuleOrError() (*compute.Firewall, error) { + gceCloud := cont.Cloud.Provider.(*gcecloud.GCECloud) + fwName := cont.GetFirewallRuleName() + return gceCloud.GetFirewall(fwName) +} + func (cont *GCEIngressController) deleteFirewallRule(del bool) (msg string) { fwList := []compute.Firewall{} regex := fmt.Sprintf("%vfw-l7%v.*", k8sPrefix, clusterDelimiter) @@ -883,41 +908,72 @@ func (cont *GCEIngressController) isHTTPErrorCode(err error, code int) bool { } // BackendServiceUsingNEG returns true only if all global backend service with matching nodeports pointing to NEG as backend -func (cont *GCEIngressController) BackendServiceUsingNEG(nodeports []string) (bool, error) { - return cont.backendMode(nodeports, "networkEndpointGroups") +func (cont *GCEIngressController) BackendServiceUsingNEG(svcPorts map[string]v1.ServicePort) (bool, error) { + return cont.backendMode(svcPorts, "networkEndpointGroups") } -// BackendServiceUsingIG returns true only if all global backend service with matching nodeports pointing to IG as backend -func (cont *GCEIngressController) BackendServiceUsingIG(nodeports []string) (bool, error) { - return cont.backendMode(nodeports, "instanceGroups") +// BackendServiceUsingIG returns true only if all global backend service with matching svcPorts pointing to IG as backend +func (cont *GCEIngressController) BackendServiceUsingIG(svcPorts map[string]v1.ServicePort) (bool, error) { + return cont.backendMode(svcPorts, "instanceGroups") } -func (cont *GCEIngressController) backendMode(nodeports []string, keyword string) (bool, error) { +func (cont *GCEIngressController) backendMode(svcPorts map[string]v1.ServicePort, keyword string) (bool, error) { gceCloud := cont.Cloud.Provider.(*gcecloud.GCECloud) beList, err := gceCloud.ListGlobalBackendServices() if err != nil { return false, fmt.Errorf("failed to list backend services: %v", err) } + hcList, err := gceCloud.ListHealthChecks() + if err != nil { + return false, fmt.Errorf("failed to list health checks: %v", err) + } + + uid := cont.UID + if len(uid) > 8 { + uid = uid[:8] + } + matchingBackendService := 0 - for _, bs := range beList { + for svcName, sp := range svcPorts { match := false - for _, np := range nodeports { - // Warning: This assumes backend service naming convention includes nodeport in the name - if strings.Contains(bs.Name, np) { + bsMatch := &compute.BackendService{} + // Non-NEG BackendServices are named with the Nodeport in the name. + // NEG BackendServices' names contain the a sha256 hash of a string. + negString := strings.Join([]string{uid, cont.Ns, svcName, sp.TargetPort.String()}, ";") + negHash := fmt.Sprintf("%x", sha256.Sum256([]byte(negString)))[:8] + for _, bs := range beList { + if strings.Contains(bs.Name, strconv.Itoa(int(sp.NodePort))) || + strings.Contains(bs.Name, negHash) { match = true + bsMatch = bs matchingBackendService += 1 + break } } + if match { - for _, be := range bs.Backends { + for _, be := range bsMatch.Backends { if !strings.Contains(be.Group, keyword) { return false, nil } } + + // Check that the correct HealthCheck exists for the BackendService + hcMatch := false + for _, hc := range hcList { + if hc.Name == bsMatch.Name { + hcMatch = true + break + } + } + + if !hcMatch { + return false, fmt.Errorf("missing healthcheck for backendservice: %v", bsMatch.Name) + } } } - return matchingBackendService == len(nodeports), nil + return matchingBackendService == len(svcPorts), nil } // Cleanup cleans up cloud resources. @@ -1131,7 +1187,7 @@ func (j *IngressTestJig) CreateIngress(manifestPath, ns string, ingAnnotations m for k, v := range ingAnnotations { j.Ingress.Annotations[k] = v } - j.Logger.Infof(fmt.Sprintf("creating" + j.Ingress.Name + " ingress")) + j.Logger.Infof(fmt.Sprintf("creating " + j.Ingress.Name + " ingress")) j.Ingress, err = j.runCreate(j.Ingress) ExpectNoError(err) } @@ -1146,7 +1202,7 @@ func (j *IngressTestJig) runCreate(ing *extensions.Ingress) (*extensions.Ingress if err := manifest.IngressToManifest(ing, filePath); err != nil { return nil, err } - _, err := runKubemciWithKubeconfig("create", ing.Name, fmt.Sprintf("--ingress=%s", filePath)) + _, err := RunKubemciWithKubeconfig("create", ing.Name, fmt.Sprintf("--ingress=%s", filePath)) return ing, err } @@ -1161,7 +1217,7 @@ func (j *IngressTestJig) runUpdate(ing *extensions.Ingress) (*extensions.Ingress if err := manifest.IngressToManifest(ing, filePath); err != nil { return nil, err } - _, err := runKubemciWithKubeconfig("create", ing.Name, fmt.Sprintf("--ingress=%s", filePath), "--force") + _, err := RunKubemciWithKubeconfig("create", ing.Name, fmt.Sprintf("--ingress=%s", filePath), "--force") return ing, err } @@ -1187,20 +1243,46 @@ func (j *IngressTestJig) Update(update func(ing *extensions.Ingress)) { Failf("too many retries updating ingress %s/%s", ns, name) } -// AddHTTPS updates the ingress to use this secret for these hosts. +// AddHTTPS updates the ingress to add this secret for these hosts. func (j *IngressTestJig) AddHTTPS(secretName string, hosts ...string) { - j.Ingress.Spec.TLS = []extensions.IngressTLS{{Hosts: hosts, SecretName: secretName}} // TODO: Just create the secret in GetRootCAs once we're watching secrets in // the ingress controller. _, cert, _, err := createTLSSecret(j.Client, j.Ingress.Namespace, secretName, hosts...) ExpectNoError(err) - j.Logger.Infof("Updating ingress %v to use secret %v for TLS termination", j.Ingress.Name, secretName) + j.Logger.Infof("Updating ingress %v to also use secret %v for TLS termination", j.Ingress.Name, secretName) j.Update(func(ing *extensions.Ingress) { - ing.Spec.TLS = []extensions.IngressTLS{{Hosts: hosts, SecretName: secretName}} + ing.Spec.TLS = append(ing.Spec.TLS, extensions.IngressTLS{Hosts: hosts, SecretName: secretName}) }) j.RootCAs[secretName] = cert } +// SetHTTPS updates the ingress to use only this secret for these hosts. +func (j *IngressTestJig) SetHTTPS(secretName string, hosts ...string) { + _, cert, _, err := createTLSSecret(j.Client, j.Ingress.Namespace, secretName, hosts...) + ExpectNoError(err) + j.Logger.Infof("Updating ingress %v to only use secret %v for TLS termination", j.Ingress.Name, secretName) + j.Update(func(ing *extensions.Ingress) { + ing.Spec.TLS = []extensions.IngressTLS{{Hosts: hosts, SecretName: secretName}} + }) + j.RootCAs = map[string][]byte{secretName: cert} +} + +// RemoveHTTPS updates the ingress to not use this secret for TLS. +// Note: Does not delete the secret. +func (j *IngressTestJig) RemoveHTTPS(secretName string) { + newTLS := []extensions.IngressTLS{} + for _, ingressTLS := range j.Ingress.Spec.TLS { + if secretName != ingressTLS.SecretName { + newTLS = append(newTLS, ingressTLS) + } + } + j.Logger.Infof("Updating ingress %v to not use secret %v for TLS termination", j.Ingress.Name, secretName) + j.Update(func(ing *extensions.Ingress) { + ing.Spec.TLS = newTLS + }) + delete(j.RootCAs, secretName) +} + // PrepareTLSSecret creates a TLS secret and caches the cert. func (j *IngressTestJig) PrepareTLSSecret(namespace, secretName string, hosts ...string) error { _, cert, _, err := createTLSSecret(j.Client, namespace, secretName, hosts...) @@ -1227,7 +1309,7 @@ func (j *IngressTestJig) TryDeleteIngress() { } func (j *IngressTestJig) TryDeleteGivenIngress(ing *extensions.Ingress) { - if err := j.runDelete(ing, j.Class); err != nil { + if err := j.runDelete(ing); err != nil { j.Logger.Infof("Error while deleting the ingress %v/%v with class %s: %v", ing.Namespace, ing.Name, j.Class, err) } } @@ -1240,7 +1322,7 @@ func (j *IngressTestJig) TryDeleteGivenService(svc *v1.Service) { } // runDelete runs the required command to delete the given ingress. -func (j *IngressTestJig) runDelete(ing *extensions.Ingress, class string) error { +func (j *IngressTestJig) runDelete(ing *extensions.Ingress) error { if j.Class != MulticlusterIngressClassValue { return j.Client.ExtensionsV1beta1().Ingresses(ing.Namespace).Delete(ing.Name, nil) } @@ -1249,7 +1331,7 @@ func (j *IngressTestJig) runDelete(ing *extensions.Ingress, class string) error if err := manifest.IngressToManifest(ing, filePath); err != nil { return err } - _, err := runKubemciWithKubeconfig("delete", ing.Name, fmt.Sprintf("--ingress=%s", filePath)) + _, err := RunKubemciWithKubeconfig("delete", ing.Name, fmt.Sprintf("--ingress=%s", filePath)) return err } @@ -1257,7 +1339,7 @@ func (j *IngressTestJig) runDelete(ing *extensions.Ingress, class string) error // TODO(nikhiljindal): Update this to be able to return hostname as well. func getIngressAddressFromKubemci(name string) ([]string, error) { var addresses []string - out, err := runKubemciCmd("get-status", name) + out, err := RunKubemciCmd("get-status", name) if err != nil { return addresses, err } @@ -1334,7 +1416,9 @@ func (j *IngressTestJig) pollIngressWithCert(ing *extensions.Ingress, address st } for _, p := range rules.IngressRuleValue.HTTP.Paths { if waitForNodePort { - if err := j.pollServiceNodePort(ing.Namespace, p.Backend.ServiceName, int(p.Backend.ServicePort.IntVal)); err != nil { + nodePort := int(p.Backend.ServicePort.IntVal) + if err := j.pollServiceNodePort(ing.Namespace, p.Backend.ServiceName, nodePort); err != nil { + j.Logger.Infof("Error in waiting for nodeport %d on service %v/%v: %s", nodePort, ing.Namespace, p.Backend.ServiceName, err) return err } } @@ -1428,10 +1512,22 @@ func (j *IngressTestJig) GetDefaultBackendNodePort() (int32, error) { // by default, so retrieve its nodePort if includeDefaultBackend is true. func (j *IngressTestJig) GetIngressNodePorts(includeDefaultBackend bool) []string { nodePorts := []string{} + svcPorts := j.GetServicePorts(includeDefaultBackend) + for _, svcPort := range svcPorts { + nodePorts = append(nodePorts, strconv.Itoa(int(svcPort.NodePort))) + } + return nodePorts +} + +// GetIngressNodePorts returns related backend services' svcPorts. +// Current GCE ingress controller allows traffic to the default HTTP backend +// by default, so retrieve its nodePort if includeDefaultBackend is true. +func (j *IngressTestJig) GetServicePorts(includeDefaultBackend bool) map[string]v1.ServicePort { + svcPorts := make(map[string]v1.ServicePort) if includeDefaultBackend { defaultSvc, err := j.Client.CoreV1().Services(metav1.NamespaceSystem).Get(defaultBackendName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) - nodePorts = append(nodePorts, strconv.Itoa(int(defaultSvc.Spec.Ports[0].NodePort))) + svcPorts[defaultBackendName] = defaultSvc.Spec.Ports[0] } backendSvcs := []string{} @@ -1446,9 +1542,9 @@ func (j *IngressTestJig) GetIngressNodePorts(includeDefaultBackend bool) []strin for _, svcName := range backendSvcs { svc, err := j.Client.CoreV1().Services(j.Ingress.Namespace).Get(svcName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) - nodePorts = append(nodePorts, strconv.Itoa(int(svc.Spec.Ports[0].NodePort))) + svcPorts[svcName] = svc.Spec.Ports[0] } - return nodePorts + return svcPorts } // ConstructFirewallForIngress returns the expected GCE firewall rule for the ingress resource @@ -1525,14 +1621,16 @@ func (cont *NginxIngressController) Init() { Logf("ingress controller running in pod %v on ip %v", cont.pod.Name, cont.externalIP) } -func GenerateReencryptionIngressSpec() *extensions.Ingress { +func generateBacksideHTTPSIngressSpec(ns string) *extensions.Ingress { return &extensions.Ingress{ ObjectMeta: metav1.ObjectMeta{ - Name: "echoheaders-reencryption", + Name: "echoheaders-https", + Namespace: ns, }, Spec: extensions.IngressSpec{ + // Note kubemci requres a default backend. Backend: &extensions.IngressBackend{ - ServiceName: "echoheaders-reencryption", + ServiceName: "echoheaders-https", ServicePort: intstr.IntOrString{ Type: intstr.Int, IntVal: 443, @@ -1542,10 +1640,10 @@ func GenerateReencryptionIngressSpec() *extensions.Ingress { } } -func GenerateReencryptionServiceSpec() *v1.Service { +func generateBacksideHTTPSServiceSpec() *v1.Service { return &v1.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: "echoheaders-reencryption", + Name: "echoheaders-https", Annotations: map[string]string{ ServiceApplicationProtocolKey: `{"my-https-port":"HTTPS"}`, }, @@ -1558,33 +1656,33 @@ func GenerateReencryptionServiceSpec() *v1.Service { TargetPort: intstr.FromString("echo-443"), }}, Selector: map[string]string{ - "app": "echoheaders-reencryption", + "app": "echoheaders-https", }, Type: v1.ServiceTypeNodePort, }, } } -func GenerateReencryptionDeploymentSpec() *extensions.Deployment { +func generateBacksideHTTPSDeploymentSpec() *extensions.Deployment { return &extensions.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Name: "echoheaders-reencryption", + Name: "echoheaders-https", }, Spec: extensions.DeploymentSpec{ Selector: &metav1.LabelSelector{MatchLabels: map[string]string{ - "app": "echoheaders-reencryption", + "app": "echoheaders-https", }}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ - "app": "echoheaders-reencryption", + "app": "echoheaders-https", }, }, Spec: v1.PodSpec{ Containers: []v1.Container{ { - Name: "echoheaders-reencryption", - Image: "k8s.gcr.io/echoserver:1.9", + Name: "echoheaders-https", + Image: "k8s.gcr.io/echoserver:1.10", Ports: []v1.ContainerPort{{ ContainerPort: 8443, Name: "echo-443", @@ -1597,26 +1695,35 @@ func GenerateReencryptionDeploymentSpec() *extensions.Deployment { } } -func CreateReencryptionIngress(cs clientset.Interface, namespace string) (*extensions.Deployment, *v1.Service, *extensions.Ingress, error) { - deployCreated, err := cs.ExtensionsV1beta1().Deployments(namespace).Create(GenerateReencryptionDeploymentSpec()) +// SetUpBacksideHTTPSIngress sets up deployment, service and ingress with backside HTTPS configured. +func (j *IngressTestJig) SetUpBacksideHTTPSIngress(cs clientset.Interface, namespace string, staticIPName string) (*extensions.Deployment, *v1.Service, *extensions.Ingress, error) { + deployCreated, err := cs.ExtensionsV1beta1().Deployments(namespace).Create(generateBacksideHTTPSDeploymentSpec()) if err != nil { return nil, nil, nil, err } - svcCreated, err := cs.CoreV1().Services(namespace).Create(GenerateReencryptionServiceSpec()) + svcCreated, err := cs.CoreV1().Services(namespace).Create(generateBacksideHTTPSServiceSpec()) if err != nil { return nil, nil, nil, err } - ingCreated, err := cs.ExtensionsV1beta1().Ingresses(namespace).Create(GenerateReencryptionIngressSpec()) + ingToCreate := generateBacksideHTTPSIngressSpec(namespace) + if staticIPName != "" { + if ingToCreate.Annotations == nil { + ingToCreate.Annotations = map[string]string{} + } + ingToCreate.Annotations[IngressStaticIPKey] = staticIPName + } + ingCreated, err := j.runCreate(ingToCreate) if err != nil { return nil, nil, nil, err } return deployCreated, svcCreated, ingCreated, nil } -func CleanupReencryptionIngress(cs clientset.Interface, deploy *extensions.Deployment, svc *v1.Service, ing *extensions.Ingress) []error { +// DeleteTestResource deletes given deployment, service and ingress. +func (j *IngressTestJig) DeleteTestResource(cs clientset.Interface, deploy *extensions.Deployment, svc *v1.Service, ing *extensions.Ingress) []error { var errs []error if ing != nil { - if err := cs.ExtensionsV1beta1().Ingresses(ing.Namespace).Delete(ing.Name, nil); err != nil { + if err := j.runDelete(ing); err != nil { errs = append(errs, fmt.Errorf("error while deleting ingress %s/%s: %v", ing.Namespace, ing.Name, err)) } } diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/kubelet_stats.go b/vendor/k8s.io/kubernetes/test/e2e/framework/kubelet_stats.go index 7bc06edde..1304cbfcf 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/kubelet_stats.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/kubelet_stats.go @@ -97,10 +97,11 @@ func getKubeletMetrics(c clientset.Interface, nodeName string) (metrics.KubeletM return kubeletMetrics, nil } -// GetKubeletLatencyMetrics gets all latency related kubelet metrics. Note that the KubeletMetrcis -// passed in should not contain subsystem prefix. -func GetKubeletLatencyMetrics(ms metrics.KubeletMetrics) KubeletLatencyMetrics { - latencyMethods := sets.NewString( +// GetDefaultKubeletLatencyMetrics calls GetKubeletLatencyMetrics with a set of default metricNames +// identifying common latency metrics. +// Note that the KubeletMetrics passed in should not contain subsystem prefix. +func GetDefaultKubeletLatencyMetrics(ms metrics.KubeletMetrics) KubeletLatencyMetrics { + latencyMetricNames := sets.NewString( kubeletmetrics.PodWorkerLatencyKey, kubeletmetrics.PodWorkerStartLatencyKey, kubeletmetrics.PodStartLatencyKey, @@ -109,13 +110,15 @@ func GetKubeletLatencyMetrics(ms metrics.KubeletMetrics) KubeletLatencyMetrics { kubeletmetrics.PodWorkerStartLatencyKey, kubeletmetrics.PLEGRelistLatencyKey, ) - return GetKubeletMetrics(ms, latencyMethods) + return GetKubeletLatencyMetrics(ms, latencyMetricNames) } -func GetKubeletMetrics(ms metrics.KubeletMetrics, methods sets.String) KubeletLatencyMetrics { +// GetKubeletLatencyMetrics filters ms to include only those contained in the metricNames set, +// then constructs a KubeletLatencyMetrics list based on the samples associated with those metrics. +func GetKubeletLatencyMetrics(ms metrics.KubeletMetrics, filterMetricNames sets.String) KubeletLatencyMetrics { var latencyMetrics KubeletLatencyMetrics - for method, samples := range ms { - if !methods.Has(method) { + for name, samples := range ms { + if !filterMetricNames.Has(name) { continue } for _, sample := range samples { @@ -131,7 +134,7 @@ func GetKubeletMetrics(ms metrics.KubeletMetrics, methods sets.String) KubeletLa latencyMetrics = append(latencyMetrics, KubeletLatencyMetric{ Operation: operation, - Method: method, + Method: name, Quantile: quantile, Latency: time.Duration(int64(latency)) * time.Microsecond, }) @@ -265,7 +268,7 @@ func HighLatencyKubeletOperations(c clientset.Interface, threshold time.Duration if err != nil { return KubeletLatencyMetrics{}, err } - latencyMetrics := GetKubeletLatencyMetrics(ms) + latencyMetrics := GetDefaultKubeletLatencyMetrics(ms) sort.Sort(latencyMetrics) var badMetrics KubeletLatencyMetrics logFunc("\nLatency metrics for node %v", nodeName) diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/metrics_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/metrics_util.go index 2753de0d4..5d61bbf51 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/metrics_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/metrics_util.go @@ -32,6 +32,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/pkg/master/ports" + schedulermetric "k8s.io/kubernetes/pkg/scheduler/metrics" "k8s.io/kubernetes/pkg/util/system" "k8s.io/kubernetes/test/e2e/framework/metrics" @@ -43,7 +44,6 @@ const ( // NodeStartupThreshold is a rough estimate of the time allocated for a pod to start on a node. NodeStartupThreshold = 4 * time.Second - podStartupThreshold time.Duration = 5 * time.Second // We are setting 1s threshold for apicalls even in small clusters to avoid flakes. // The problem is that if long GC is happening in small clusters (where we have e.g. // 1-core master machines) and tests are pretty short, it may consume significant @@ -131,6 +131,8 @@ func (m *MetricsForE2E) SummaryKind() string { return "MetricsForE2E" } +var SchedulingLatencyMetricName = model.LabelValue(schedulermetric.SchedulerSubsystem + "_" + schedulermetric.SchedulingLatencyName) + var InterestingApiServerMetrics = []string{ "apiserver_request_count", "apiserver_request_latencies_summary", @@ -188,7 +190,11 @@ type LatencyMetric struct { } type PodStartupLatency struct { - Latency LatencyMetric `json:"latency"` + CreateToScheduleLatency LatencyMetric `json:"createToScheduleLatency"` + ScheduleToRunLatency LatencyMetric `json:"scheduleToRunLatency"` + RunToWatchLatency LatencyMetric `json:"runToWatchLatency"` + ScheduleToWatchLatency LatencyMetric `json:"scheduleToWatchLatency"` + E2ELatency LatencyMetric `json:"e2eLatency"` } func (l *PodStartupLatency) SummaryKind() string { @@ -203,21 +209,26 @@ func (l *PodStartupLatency) PrintJSON() string { return PrettyPrintJSON(PodStartupLatencyToPerfData(l)) } -type SchedulingLatency struct { - Scheduling LatencyMetric `json:"scheduling"` - Binding LatencyMetric `json:"binding"` - Total LatencyMetric `json:"total"` +type SchedulingMetrics struct { + PredicateEvaluationLatency LatencyMetric `json:"predicateEvaluationLatency"` + PriorityEvaluationLatency LatencyMetric `json:"priorityEvaluationLatency"` + PreemptionEvaluationLatency LatencyMetric `json:"preemptionEvaluationLatency"` + BindingLatency LatencyMetric `json:"bindingLatency"` + ThroughputAverage float64 `json:"throughputAverage"` + ThroughputPerc50 float64 `json:"throughputPerc50"` + ThroughputPerc90 float64 `json:"throughputPerc90"` + ThroughputPerc99 float64 `json:"throughputPerc99"` } -func (l *SchedulingLatency) SummaryKind() string { - return "SchedulingLatency" +func (l *SchedulingMetrics) SummaryKind() string { + return "SchedulingMetrics" } -func (l *SchedulingLatency) PrintHumanReadable() string { +func (l *SchedulingMetrics) PrintHumanReadable() string { return PrettyPrintJSON(l) } -func (l *SchedulingLatency) PrintJSON() string { +func (l *SchedulingMetrics) PrintJSON() string { return PrettyPrintJSON(l) } @@ -398,17 +409,17 @@ func HighLatencyRequests(c clientset.Interface, nodeCount int) (int, *APIRespons return badMetrics, metrics, nil } -// Verifies whether 50, 90 and 99th percentiles of PodStartupLatency are -// within the threshold. -func VerifyPodStartupLatency(latency *PodStartupLatency) error { - if latency.Latency.Perc50 > podStartupThreshold { - return fmt.Errorf("too high pod startup latency 50th percentile: %v", latency.Latency.Perc50) +// Verifies whether 50, 90 and 99th percentiles of a latency metric are +// within the expected threshold. +func VerifyLatencyWithinThreshold(threshold, actual LatencyMetric, metricName string) error { + if actual.Perc50 > threshold.Perc50 { + return fmt.Errorf("too high %v latency 50th percentile: %v", metricName, actual.Perc50) } - if latency.Latency.Perc90 > podStartupThreshold { - return fmt.Errorf("too high pod startup latency 90th percentile: %v", latency.Latency.Perc90) + if actual.Perc90 > threshold.Perc90 { + return fmt.Errorf("too high %v latency 90th percentile: %v", metricName, actual.Perc90) } - if latency.Latency.Perc99 > podStartupThreshold { - return fmt.Errorf("too high pod startup latency 99th percentile: %v", latency.Latency.Perc99) + if actual.Perc99 > threshold.Perc99 { + return fmt.Errorf("too high %v latency 99th percentile: %v", metricName, actual.Perc99) } return nil } @@ -435,27 +446,29 @@ func getMetrics(c clientset.Interface) (string, error) { return string(body), nil } -// Retrieves scheduler metrics information. -func getSchedulingLatency(c clientset.Interface) (*SchedulingLatency, error) { - result := SchedulingLatency{} +// Sends REST request to kube scheduler metrics +func sendRestRequestToScheduler(c clientset.Interface, op string) (string, error) { + opUpper := strings.ToUpper(op) + if opUpper != "GET" && opUpper != "DELETE" { + return "", fmt.Errorf("Unknown REST request") + } - // Check if master Node is registered nodes, err := c.CoreV1().Nodes().List(metav1.ListOptions{}) ExpectNoError(err) - var data string var masterRegistered = false for _, node := range nodes.Items { if system.IsMasterNode(node.Name) { masterRegistered = true } } + + var responseText string if masterRegistered { ctx, cancel := context.WithTimeout(context.Background(), SingleCallTimeout) defer cancel() - var rawData []byte - rawData, err = c.CoreV1().RESTClient().Get(). + body, err := c.CoreV1().RESTClient().Verb(opUpper). Context(ctx). Namespace(metav1.NamespaceSystem). Resource("pods"). @@ -465,51 +478,65 @@ func getSchedulingLatency(c clientset.Interface) (*SchedulingLatency, error) { Do().Raw() ExpectNoError(err) - data = string(rawData) + responseText = string(body) } else { // If master is not registered fall back to old method of using SSH. if TestContext.Provider == "gke" { Logf("Not grabbing scheduler metrics through master SSH: unsupported for gke") - return nil, nil + return "", nil } - cmd := "curl http://localhost:10251/metrics" + + cmd := "curl -X " + opUpper + " http://localhost:10251/metrics" sshResult, err := SSH(cmd, GetMasterHost()+":22", TestContext.Provider) if err != nil || sshResult.Code != 0 { - return &result, fmt.Errorf("unexpected error (code: %d) in ssh connection to master: %#v", sshResult.Code, err) + return "", fmt.Errorf("unexpected error (code: %d) in ssh connection to master: %#v", sshResult.Code, err) } - data = sshResult.Stdout + responseText = sshResult.Stdout } + return responseText, nil +} + +// Retrieves scheduler latency metrics. +func getSchedulingLatency(c clientset.Interface) (*SchedulingMetrics, error) { + result := SchedulingMetrics{} + data, err := sendRestRequestToScheduler(c, "GET") + samples, err := extractMetricSamples(data) if err != nil { return nil, err } for _, sample := range samples { + if sample.Metric[model.MetricNameLabel] != SchedulingLatencyMetricName { + continue + } + var metric *LatencyMetric = nil - switch sample.Metric[model.MetricNameLabel] { - case "scheduler_scheduling_algorithm_latency_microseconds": - metric = &result.Scheduling - case "scheduler_binding_latency_microseconds": - metric = &result.Binding - case "scheduler_e2e_scheduling_latency_microseconds": - metric = &result.Total + switch sample.Metric[schedulermetric.OperationLabel] { + case schedulermetric.PredicateEvaluation: + metric = &result.PredicateEvaluationLatency + case schedulermetric.PriorityEvaluation: + metric = &result.PriorityEvaluationLatency + case schedulermetric.PreemptionEvaluation: + metric = &result.PreemptionEvaluationLatency + case schedulermetric.Binding: + metric = &result.BindingLatency } if metric == nil { continue } - latency := sample.Value quantile, err := strconv.ParseFloat(string(sample.Metric[model.QuantileLabel]), 64) if err != nil { return nil, err } - setQuantile(metric, quantile, time.Duration(int64(latency))*time.Microsecond) + setQuantile(metric, quantile, time.Duration(int64(float64(sample.Value)*float64(time.Second)))) } return &result, nil } // Verifies (currently just by logging them) the scheduling latencies. -func VerifySchedulerLatency(c clientset.Interface) (*SchedulingLatency, error) { +func VerifySchedulerLatency(c clientset.Interface) (*SchedulingMetrics, error) { latency, err := getSchedulingLatency(c) if err != nil { return nil, err @@ -517,6 +544,14 @@ func VerifySchedulerLatency(c clientset.Interface) (*SchedulingLatency, error) { return latency, nil } +func ResetSchedulerMetrics(c clientset.Interface) error { + responseText, err := sendRestRequestToScheduler(c, "DELETE") + if err != nil || responseText != "metrics reset\n" { + return fmt.Errorf("Unexpected response: %q", responseText) + } + return nil +} + func PrettyPrintJSON(metrics interface{}) string { output := &bytes.Buffer{} if err := json.NewEncoder(output).Encode(metrics); err != nil { diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/networking_utils.go b/vendor/k8s.io/kubernetes/test/e2e/framework/networking_utils.go index 66d7e2552..5562c8b1b 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/networking_utils.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/networking_utils.go @@ -40,7 +40,6 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" coreclientset "k8s.io/client-go/kubernetes/typed/core/v1" - "k8s.io/kubernetes/pkg/api/testapi" imageutils "k8s.io/kubernetes/test/utils/image" ) @@ -403,7 +402,7 @@ func (config *NetworkingTestConfig) createNetShellPodSpec(podName, hostname stri pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: podName, @@ -447,7 +446,7 @@ func (config *NetworkingTestConfig) createTestPodSpec() *v1.Pod { pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: testPodName, diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/nodes_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/nodes_util.go index 3f809ca9f..a58a6e628 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/nodes_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/nodes_util.go @@ -63,7 +63,7 @@ func etcdUpgradeGCE(target_storage, target_version string) error { os.Environ(), "TEST_ETCD_VERSION="+target_version, "STORAGE_BACKEND="+target_storage, - "TEST_ETCD_IMAGE=3.1.12") + "TEST_ETCD_IMAGE=3.2.18-0") _, _, err := RunCmdEnv(env, gceUpgradeScript(), "-l", "-M") return err @@ -78,11 +78,11 @@ func ingressUpgradeGCE(isUpgrade bool) error { command = fmt.Sprintf("sudo sed -i -re 's|(image:)(.*)|\\1 %s|' /etc/kubernetes/manifests/glbc.manifest", targetImage) } else { // Upgrade to latest HEAD image. - command = "sudo sed -i -re 's/(image:)(.*)/\\1 gcr.io\\/k8s-ingress-image-push\\/ingress-gce-e2e-glbc-amd64:latest/' /etc/kubernetes/manifests/glbc.manifest" + command = "sudo sed -i -re 's/(image:)(.*)/\\1 gcr.io\\/k8s-ingress-image-push\\/ingress-gce-e2e-glbc-amd64:master/' /etc/kubernetes/manifests/glbc.manifest" } } else { // Downgrade to latest release image. - command = "sudo sed -i -re 's/(image:)(.*)/\\1 k8s.gcr.io\\/google_containers\\/glbc:0.9.7/' /etc/kubernetes/manifests/glbc.manifest" + command = "sudo sed -i -re 's/(image:)(.*)/\\1 k8s.gcr.io\\/ingress-gce-glbc-amd64:v1.1.1/' /etc/kubernetes/manifests/glbc.manifest" } // Kubelet should restart glbc automatically. sshResult, err := NodeExec(GetMasterHost(), command) @@ -103,7 +103,7 @@ func masterUpgradeGCE(rawV string, enableKubeProxyDaemonSet bool) error { env = append(env, "TEST_ETCD_VERSION="+TestContext.EtcdUpgradeVersion, "STORAGE_BACKEND="+TestContext.EtcdUpgradeStorage, - "TEST_ETCD_IMAGE=3.1.12") + "TEST_ETCD_IMAGE=3.2.18-0") } else { // In e2e tests, we skip the confirmation prompt about // implicit etcd upgrades to simulate the user entering "y". diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/perf_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/perf_util.go index 67d9ada57..18f94cb50 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/perf_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/perf_util.go @@ -53,22 +53,29 @@ func ApiCallToPerfData(apicalls *APIResponsiveness) *perftype.PerfData { return perfData } -// PodStartupLatencyToPerfData transforms PodStartupLatency to PerfData. -func PodStartupLatencyToPerfData(latency *PodStartupLatency) *perftype.PerfData { - perfData := &perftype.PerfData{Version: currentApiCallMetricsVersion} - item := perftype.DataItem{ +func latencyToPerfData(l LatencyMetric, name string) perftype.DataItem { + return perftype.DataItem{ Data: map[string]float64{ - "Perc50": float64(latency.Latency.Perc50) / 1000000, // us -> ms - "Perc90": float64(latency.Latency.Perc90) / 1000000, - "Perc99": float64(latency.Latency.Perc99) / 1000000, - "Perc100": float64(latency.Latency.Perc100) / 1000000, + "Perc50": float64(l.Perc50) / 1000000, // us -> ms + "Perc90": float64(l.Perc90) / 1000000, + "Perc99": float64(l.Perc99) / 1000000, + "Perc100": float64(l.Perc100) / 1000000, }, Unit: "ms", Labels: map[string]string{ - "Metric": "pod_startup", + "Metric": name, }, } - perfData.DataItems = append(perfData.DataItems, item) +} + +// PodStartupLatencyToPerfData transforms PodStartupLatency to PerfData. +func PodStartupLatencyToPerfData(latency *PodStartupLatency) *perftype.PerfData { + perfData := &perftype.PerfData{Version: currentApiCallMetricsVersion} + perfData.DataItems = append(perfData.DataItems, latencyToPerfData(latency.CreateToScheduleLatency, "create_to_schedule")) + perfData.DataItems = append(perfData.DataItems, latencyToPerfData(latency.ScheduleToRunLatency, "schedule_to_run")) + perfData.DataItems = append(perfData.DataItems, latencyToPerfData(latency.RunToWatchLatency, "run_to_watch")) + perfData.DataItems = append(perfData.DataItems, latencyToPerfData(latency.ScheduleToWatchLatency, "schedule_to_watch")) + perfData.DataItems = append(perfData.DataItems, latencyToPerfData(latency.E2ELatency, "pod_startup")) return perfData } diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/profile_gatherer.go b/vendor/k8s.io/kubernetes/test/e2e/framework/profile_gatherer.go index 3c670880a..c63795ec4 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/profile_gatherer.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/profile_gatherer.go @@ -19,7 +19,6 @@ package framework import ( "bytes" "fmt" - "io/ioutil" "os" "os/exec" "path" @@ -69,36 +68,44 @@ func gatherProfileOfKind(profileBaseName, kind string) error { if err != nil { return fmt.Errorf("Failed to execute curl command on master through SSH: %v", err) } - // Write the data to a temp file. - var tmpfile *os.File - tmpfile, err = ioutil.TempFile("", "apiserver-profile") + + var profilePrefix string + switch { + case kind == "heap": + profilePrefix = "ApiserverMemoryProfile_" + case strings.HasPrefix(kind, "profile"): + profilePrefix = "ApiserverCPUProfile_" + default: + return fmt.Errorf("Unknown profile kind provided: %s", kind) + } + + // Write the data to a file. + rawprofilePath := path.Join(getProfilesDirectoryPath(), profilePrefix+profileBaseName+".pprof") + rawprofile, err := os.Create(rawprofilePath) if err != nil { - return fmt.Errorf("Failed to create temp file for profile data: %v", err) + return fmt.Errorf("Failed to create file for the profile graph: %v", err) } - defer os.Remove(tmpfile.Name()) - if _, err := tmpfile.Write([]byte(sshResult.Stdout)); err != nil { - return fmt.Errorf("Failed to write temp file with profile data: %v", err) + defer rawprofile.Close() + + if _, err := rawprofile.Write([]byte(sshResult.Stdout)); err != nil { + return fmt.Errorf("Failed to write file with profile data: %v", err) } - if err := tmpfile.Close(); err != nil { - return fmt.Errorf("Failed to close temp file: %v", err) + if err := rawprofile.Close(); err != nil { + return fmt.Errorf("Failed to close file: %v", err) } // Create a graph from the data and write it to a pdf file. var cmd *exec.Cmd - var profilePrefix string switch { // TODO: Support other profile kinds if needed (e.g inuse_space, alloc_objects, mutex, etc) case kind == "heap": - cmd = exec.Command("go", "tool", "pprof", "-pdf", "-symbolize=none", "--alloc_space", tmpfile.Name()) - profilePrefix = "ApiserverMemoryProfile_" + cmd = exec.Command("go", "tool", "pprof", "-pdf", "-symbolize=none", "--alloc_space", rawprofile.Name()) case strings.HasPrefix(kind, "profile"): - cmd = exec.Command("go", "tool", "pprof", "-pdf", "-symbolize=none", tmpfile.Name()) - profilePrefix = "ApiserverCPUProfile_" + cmd = exec.Command("go", "tool", "pprof", "-pdf", "-symbolize=none", rawprofile.Name()) default: return fmt.Errorf("Unknown profile kind provided: %s", kind) } outfilePath := path.Join(getProfilesDirectoryPath(), profilePrefix+profileBaseName+".pdf") - var outfile *os.File - outfile, err = os.Create(outfilePath) + outfile, err := os.Create(outfilePath) if err != nil { return fmt.Errorf("Failed to create file for the profile graph: %v", err) } diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/psp_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/psp_util.go index 4e6e4f8a7..cd281f00d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/psp_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/psp_util.go @@ -71,6 +71,7 @@ func PrivilegedPSP(name string) *extensionsv1beta1.PodSecurityPolicy { Rule: extensionsv1beta1.FSGroupStrategyRunAsAny, }, ReadOnlyRootFilesystem: false, + AllowedUnsafeSysctls: []string{"*"}, }, } } diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/pv_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/pv_util.go index 01864f7e9..131806ad4 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/pv_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/pv_util.go @@ -36,7 +36,6 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/uuid" clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/api/testapi" awscloud "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" "k8s.io/kubernetes/pkg/volume/util" @@ -816,12 +815,12 @@ func MakeWritePod(ns string, pvc *v1.PersistentVolumeClaim) *v1.Pod { // name. A slice of BASH commands can be supplied as args to be run by the pod func MakePod(ns string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) *v1.Pod { if len(command) == 0 { - command = "while true; do sleep 1; done" + command = "trap exit TERM; while true; do sleep 1; done" } podSpec := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ GenerateName: "pvc-tester-", @@ -857,19 +856,64 @@ func MakePod(ns string, nodeSelector map[string]string, pvclaims []*v1.Persisten return podSpec } +// Returns a pod definition based on the namespace using nginx image +func MakeNginxPod(ns string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim) *v1.Pod { + podSpec := &v1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "pvc-tester-", + Namespace: ns, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "write-pod", + Image: "nginx", + Ports: []v1.ContainerPort{ + { + Name: "http-server", + ContainerPort: 80, + }, + }, + }, + }, + }, + } + var volumeMounts = make([]v1.VolumeMount, len(pvclaims)) + var volumes = make([]v1.Volume, len(pvclaims)) + for index, pvclaim := range pvclaims { + volumename := fmt.Sprintf("volume%v", index+1) + volumeMounts[index] = v1.VolumeMount{Name: volumename, MountPath: "/mnt/" + volumename} + volumes[index] = v1.Volume{Name: volumename, VolumeSource: v1.VolumeSource{PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ClaimName: pvclaim.Name, ReadOnly: false}}} + } + podSpec.Spec.Containers[0].VolumeMounts = volumeMounts + podSpec.Spec.Volumes = volumes + if nodeSelector != nil { + podSpec.Spec.NodeSelector = nodeSelector + } + return podSpec +} + // Returns a pod definition based on the namespace. The pod references the PVC's // name. A slice of BASH commands can be supplied as args to be run by the pod. // SELinux testing requires to pass HostIPC and HostPID as booleansi arguments. -func MakeSecPod(ns string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string, hostIPC bool, hostPID bool, seLinuxLabel *v1.SELinuxOptions) *v1.Pod { +func MakeSecPod(ns string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string, hostIPC bool, hostPID bool, seLinuxLabel *v1.SELinuxOptions, fsGroup *int64) *v1.Pod { if len(command) == 0 { - command = "while true; do sleep 1; done" + command = "trap exit TERM; while true; do sleep 1; done" } podName := "security-context-" + string(uuid.NewUUID()) - fsGroup := int64(1000) + if fsGroup == nil { + fsGroup = func(i int64) *int64 { + return &i + }(1000) + } podSpec := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: podName, @@ -879,7 +923,7 @@ func MakeSecPod(ns string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bo HostIPC: hostIPC, HostPID: hostPID, SecurityContext: &v1.PodSecurityContext{ - FSGroup: &fsGroup, + FSGroup: fsGroup, }, Containers: []v1.Container{ { @@ -935,9 +979,8 @@ func CreatePod(client clientset.Interface, namespace string, nodeSelector map[st return pod, nil } -// create security pod with given claims -func CreateSecPod(client clientset.Interface, namespace string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string, hostIPC bool, hostPID bool, seLinuxLabel *v1.SELinuxOptions) (*v1.Pod, error) { - pod := MakeSecPod(namespace, pvclaims, isPrivileged, command, hostIPC, hostPID, seLinuxLabel) +func CreateNginxPod(client clientset.Interface, namespace string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim) (*v1.Pod, error) { + pod := MakeNginxPod(namespace, nodeSelector, pvclaims) pod, err := client.CoreV1().Pods(namespace).Create(pod) if err != nil { return nil, fmt.Errorf("pod Create API error: %v", err) @@ -955,6 +998,26 @@ func CreateSecPod(client clientset.Interface, namespace string, pvclaims []*v1.P return pod, nil } +// create security pod with given claims +func CreateSecPod(client clientset.Interface, namespace string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string, hostIPC bool, hostPID bool, seLinuxLabel *v1.SELinuxOptions, fsGroup *int64, timeout time.Duration) (*v1.Pod, error) { + pod := MakeSecPod(namespace, pvclaims, isPrivileged, command, hostIPC, hostPID, seLinuxLabel, fsGroup) + pod, err := client.CoreV1().Pods(namespace).Create(pod) + if err != nil { + return nil, fmt.Errorf("pod Create API error: %v", err) + } + // Waiting for pod to be running + err = WaitTimeoutForPodRunningInNamespace(client, pod.Name, namespace, timeout) + if err != nil { + return pod, fmt.Errorf("pod %q is not Running: %v", pod.Name, err) + } + // get fresh pod info + pod, err = client.CoreV1().Pods(namespace).Get(pod.Name, metav1.GetOptions{}) + if err != nil { + return pod, fmt.Errorf("pod Get API error: %v", err) + } + return pod, nil +} + // Define and create a pod with a mounted PV. Pod runs infinite loop until killed. func CreateClientPod(c clientset.Interface, ns string, pvc *v1.PersistentVolumeClaim) (*v1.Pod, error) { return CreatePod(c, ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, "") diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/rc_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/rc_util.go index 0285189ee..ff2827e35 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/rc_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/rc_util.go @@ -30,9 +30,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" scaleclient "k8s.io/client-go/scale" - "k8s.io/kubernetes/pkg/api/testapi" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" testutils "k8s.io/kubernetes/test/utils" ) @@ -61,7 +59,7 @@ func RcByNameContainer(name string, replicas int32, image string, labels map[str return &v1.ReplicationController{ TypeMeta: metav1.TypeMeta{ Kind: "ReplicationController", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -86,9 +84,7 @@ func RcByNameContainer(name string, replicas int32, image string, labels map[str // ScaleRCByLabels scales an RC via ns/label lookup. If replicas == 0 it waits till // none are running, otherwise it does what a synchronous scale operation would do. -//TODO(p0lyn0mial): remove internalClientset. -//TODO(p0lyn0mial): update the callers. -func ScaleRCByLabels(clientset clientset.Interface, internalClientset internalclientset.Interface, scalesGetter scaleclient.ScalesGetter, ns string, l map[string]string, replicas uint) error { +func ScaleRCByLabels(clientset clientset.Interface, scalesGetter scaleclient.ScalesGetter, ns string, l map[string]string, replicas uint) error { listOpts := metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set(l)).String()} rcs, err := clientset.CoreV1().ReplicationControllers(ns).List(listOpts) if err != nil { @@ -100,7 +96,7 @@ func ScaleRCByLabels(clientset clientset.Interface, internalClientset internalcl Logf("Scaling %v RCs with labels %v in ns %v to %v replicas.", len(rcs.Items), l, ns, replicas) for _, labelRC := range rcs.Items { name := labelRC.Name - if err := ScaleRC(clientset, internalClientset, scalesGetter, ns, name, replicas, false); err != nil { + if err := ScaleRC(clientset, scalesGetter, ns, name, replicas, false); err != nil { return err } rc, err := clientset.CoreV1().ReplicationControllers(ns).Get(name, metav1.GetOptions{}) @@ -156,12 +152,8 @@ func DeleteRCAndWaitForGC(c clientset.Interface, ns, name string) error { return DeleteResourceAndWaitForGC(c, api.Kind("ReplicationController"), ns, name) } -func DeleteRCAndPods(clientset clientset.Interface, internalClientset internalclientset.Interface, ns, name string) error { - return DeleteResourceAndPods(clientset, internalClientset, api.Kind("ReplicationController"), ns, name) -} - -func ScaleRC(clientset clientset.Interface, internalClientset internalclientset.Interface, scalesGetter scaleclient.ScalesGetter, ns, name string, size uint, wait bool) error { - return ScaleResource(clientset, internalClientset, scalesGetter, ns, name, size, wait, api.Kind("ReplicationController"), api.Resource("replicationcontrollers")) +func ScaleRC(clientset clientset.Interface, scalesGetter scaleclient.ScalesGetter, ns, name string, size uint, wait bool) error { + return ScaleResource(clientset, scalesGetter, ns, name, size, wait, api.Kind("ReplicationController"), api.Resource("replicationcontrollers")) } func RunRC(config testutils.RCConfig) error { diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/rs_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/rs_util.go index e0708b35d..f206dc89f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/rs_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/rs_util.go @@ -21,29 +21,29 @@ import ( . "github.com/onsi/ginkgo" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" - extensionsclient "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" + appsclient "k8s.io/client-go/kubernetes/typed/apps/v1" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" testutils "k8s.io/kubernetes/test/utils" ) -type updateRsFunc func(d *extensions.ReplicaSet) +type updateRsFunc func(d *apps.ReplicaSet) -func UpdateReplicaSetWithRetries(c clientset.Interface, namespace, name string, applyUpdate testutils.UpdateReplicaSetFunc) (*extensions.ReplicaSet, error) { +func UpdateReplicaSetWithRetries(c clientset.Interface, namespace, name string, applyUpdate testutils.UpdateReplicaSetFunc) (*apps.ReplicaSet, error) { return testutils.UpdateReplicaSetWithRetries(c, namespace, name, applyUpdate, Logf, Poll, pollShortTimeout) } // CheckNewRSAnnotations check if the new RS's annotation is as expected func CheckNewRSAnnotations(c clientset.Interface, ns, deploymentName string, expectedAnnotations map[string]string) error { - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) if err != nil { return err } - newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.ExtensionsV1beta1()) + newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.AppsV1()) if err != nil { return err } @@ -59,7 +59,7 @@ func CheckNewRSAnnotations(c clientset.Interface, ns, deploymentName string, exp // WaitForReadyReplicaSet waits until the replicaset has all of its replicas ready. func WaitForReadyReplicaSet(c clientset.Interface, ns, name string) error { err := wait.Poll(Poll, pollShortTimeout, func() (bool, error) { - rs, err := c.ExtensionsV1beta1().ReplicaSets(ns).Get(name, metav1.GetOptions{}) + rs, err := c.AppsV1().ReplicaSets(ns).Get(name, metav1.GetOptions{}) if err != nil { return false, err } @@ -72,7 +72,7 @@ func WaitForReadyReplicaSet(c clientset.Interface, ns, name string) error { } // WaitForReplicaSetDesiredReplicas waits until the replicaset has desired number of replicas. -func WaitForReplicaSetDesiredReplicas(rsClient extensionsclient.ReplicaSetsGetter, replicaSet *extensions.ReplicaSet) error { +func WaitForReplicaSetDesiredReplicas(rsClient appsclient.ReplicaSetsGetter, replicaSet *apps.ReplicaSet) error { desiredGeneration := replicaSet.Generation err := wait.PollImmediate(Poll, pollShortTimeout, func() (bool, error) { rs, err := rsClient.ReplicaSets(replicaSet.Namespace).Get(replicaSet.Name, metav1.GetOptions{}) @@ -88,10 +88,10 @@ func WaitForReplicaSetDesiredReplicas(rsClient extensionsclient.ReplicaSetsGette } // WaitForReplicaSetTargetSpecReplicas waits for .spec.replicas of a RS to equal targetReplicaNum -func WaitForReplicaSetTargetSpecReplicas(c clientset.Interface, replicaSet *extensions.ReplicaSet, targetReplicaNum int32) error { +func WaitForReplicaSetTargetSpecReplicas(c clientset.Interface, replicaSet *apps.ReplicaSet, targetReplicaNum int32) error { desiredGeneration := replicaSet.Generation err := wait.PollImmediate(Poll, pollShortTimeout, func() (bool, error) { - rs, err := c.ExtensionsV1beta1().ReplicaSets(replicaSet.Namespace).Get(replicaSet.Name, metav1.GetOptions{}) + rs, err := c.AppsV1().ReplicaSets(replicaSet.Namespace).Get(replicaSet.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -104,10 +104,10 @@ func WaitForReplicaSetTargetSpecReplicas(c clientset.Interface, replicaSet *exte } // WaitForReplicaSetTargetAvailableReplicas waits for .status.availableReplicas of a RS to equal targetReplicaNum -func WaitForReplicaSetTargetAvailableReplicas(c clientset.Interface, replicaSet *extensions.ReplicaSet, targetReplicaNum int32) error { +func WaitForReplicaSetTargetAvailableReplicas(c clientset.Interface, replicaSet *apps.ReplicaSet, targetReplicaNum int32) error { desiredGeneration := replicaSet.Generation err := wait.PollImmediate(Poll, pollShortTimeout, func() (bool, error) { - rs, err := c.ExtensionsV1beta1().ReplicaSets(replicaSet.Namespace).Get(replicaSet.Name, metav1.GetOptions{}) + rs, err := c.AppsV1().ReplicaSets(replicaSet.Namespace).Get(replicaSet.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -126,8 +126,8 @@ func RunReplicaSet(config testutils.ReplicaSetConfig) error { return testutils.RunReplicaSet(config) } -func NewReplicaSet(name, namespace string, replicas int32, podLabels map[string]string, imageName, image string) *extensions.ReplicaSet { - return &extensions.ReplicaSet{ +func NewReplicaSet(name, namespace string, replicas int32, podLabels map[string]string, imageName, image string) *apps.ReplicaSet { + return &apps.ReplicaSet{ TypeMeta: metav1.TypeMeta{ Kind: "ReplicaSet", APIVersion: "extensions/v1beta1", @@ -136,7 +136,7 @@ func NewReplicaSet(name, namespace string, replicas int32, podLabels map[string] Namespace: namespace, Name: name, }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: podLabels, }, diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/service_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/service_util.go index a450b36fb..012ce7630 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/service_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/service_util.go @@ -94,6 +94,10 @@ const ( // GCPMaxInstancesInInstanceGroup is the maximum number of instances supported in // one instance group on GCP. GCPMaxInstancesInInstanceGroup = 2000 + + // AffinityConfirmCount is the number of needed continuous requests to confirm that + // affinity is enabled. + AffinityConfirmCount = 15 ) // This should match whatever the default/configured range is @@ -211,6 +215,20 @@ func (j *ServiceTestJig) CreateExternalNameServiceOrFail(namespace string, tweak return result } +// CreateServiceWithServicePort creates a new Service with ServicePort. +func (j *ServiceTestJig) CreateServiceWithServicePort(labels map[string]string, namespace string, ports []v1.ServicePort) (*v1.Service, error) { + service := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: j.Name, + }, + Spec: v1.ServiceSpec{ + Selector: labels, + Ports: ports, + }, + } + return j.Client.CoreV1().Services(namespace).Create(service) +} + func (j *ServiceTestJig) ChangeServiceType(namespace, name string, newType v1.ServiceType, timeout time.Duration) { ingressIP := "" svc := j.UpdateServiceOrFail(namespace, name, func(s *v1.Service) { @@ -1192,26 +1210,13 @@ func ValidateEndpointsOrFail(c clientset.Interface, namespace, serviceName strin Failf("Timed out waiting for service %s in namespace %s to expose endpoints %v (%v elapsed)", serviceName, namespace, expectedEndpoints, ServiceStartTimeout) } -// StartServeHostnameService creates a replication controller that serves its hostname and a service on top of it. -func StartServeHostnameService(c clientset.Interface, internalClient internalclientset.Interface, ns, name string, port, replicas int) ([]string, string, error) { +// StartServeHostnameService creates a replication controller that serves its +// hostname and a service on top of it. +func StartServeHostnameService(c clientset.Interface, internalClient internalclientset.Interface, svc *v1.Service, ns string, replicas int) ([]string, string, error) { podNames := make([]string, replicas) - + name := svc.ObjectMeta.Name By("creating service " + name + " in namespace " + ns) - _, err := c.CoreV1().Services(ns).Create(&v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Spec: v1.ServiceSpec{ - Ports: []v1.ServicePort{{ - Port: int32(port), - TargetPort: intstr.FromInt(9376), - Protocol: "TCP", - }}, - Selector: map[string]string{ - "name": name, - }, - }, - }) + _, err := c.CoreV1().Services(ns).Create(svc) if err != nil { return podNames, "", err } @@ -1255,8 +1260,8 @@ func StartServeHostnameService(c clientset.Interface, internalClient internalcli return podNames, serviceIP, nil } -func StopServeHostnameService(clientset clientset.Interface, internalClientset internalclientset.Interface, ns, name string) error { - if err := DeleteRCAndPods(clientset, internalClientset, ns, name); err != nil { +func StopServeHostnameService(clientset clientset.Interface, ns, name string) error { + if err := DeleteRCAndWaitForGC(clientset, ns, name); err != nil { return err } if err := clientset.CoreV1().Services(ns).Delete(name, nil); err != nil { @@ -1450,3 +1455,97 @@ func GetServiceLoadBalancerCreationTimeout(cs clientset.Interface) time.Duration } return LoadBalancerCreateTimeoutDefault } + +// affinityTracker tracks the destination of a request for the affinity tests. +type affinityTracker struct { + hostTrace []string +} + +// Record the response going to a given host. +func (at *affinityTracker) recordHost(host string) { + at.hostTrace = append(at.hostTrace, host) +} + +// Check that we got a constant count requests going to the same host. +func (at *affinityTracker) checkHostTrace(count int) (fulfilled, affinityHolds bool) { + fulfilled = (len(at.hostTrace) >= count) + if len(at.hostTrace) == 0 { + return fulfilled, true + } + last := at.hostTrace[0:] + if len(at.hostTrace)-count >= 0 { + last = at.hostTrace[len(at.hostTrace)-count:] + } + host := at.hostTrace[len(at.hostTrace)-1] + for _, h := range last { + if h != host { + return fulfilled, false + } + } + return fulfilled, true +} + +func checkAffinityFailed(tracker affinityTracker, err string) { + Logf("%v", tracker.hostTrace) + Failf(err) +} + +// CheckAffinity function tests whether the service affinity works as expected. +// If affinity is expected and transitionState is true, the test will +// return true once affinityConfirmCount number of same response observed in a +// row. If affinity is not expected, the test will keep observe until different +// responses observed. The function will return false only when no expected +// responses observed before timeout. If transitionState is false, the test will +// fail once different host is given if shouldHold is true. +func CheckAffinity(jig *ServiceTestJig, execPod *v1.Pod, targetIp string, targetPort int, shouldHold, transitionState bool) bool { + targetIpPort := net.JoinHostPort(targetIp, strconv.Itoa(targetPort)) + cmd := fmt.Sprintf(`wget -qO- http://%s/ -T 2`, targetIpPort) + timeout := ServiceTestTimeout + if execPod == nil { + timeout = LoadBalancerPollTimeout + } + var tracker affinityTracker + if pollErr := wait.PollImmediate(Poll, timeout, func() (bool, error) { + if execPod != nil { + if stdout, err := RunHostCmd(execPod.Namespace, execPod.Name, cmd); err != nil { + Logf("Failed to get response from %s. Retry until timeout", targetIpPort) + return false, nil + } else { + tracker.recordHost(stdout) + } + } else { + rawResponse := jig.GetHTTPContent(targetIp, targetPort, timeout, "") + tracker.recordHost(rawResponse.String()) + } + trackerFulfilled, affinityHolds := tracker.checkHostTrace(AffinityConfirmCount) + if !shouldHold && !affinityHolds { + return true, nil + } + if shouldHold { + if !transitionState && !affinityHolds { + return true, fmt.Errorf("Affintity should hold but didn't.") + } + if trackerFulfilled && affinityHolds { + return true, nil + } + } + return false, nil + }); pollErr != nil { + trackerFulfilled, _ := tracker.checkHostTrace(AffinityConfirmCount) + if pollErr != wait.ErrWaitTimeout { + checkAffinityFailed(tracker, pollErr.Error()) + return false + } else { + if !trackerFulfilled { + checkAffinityFailed(tracker, fmt.Sprintf("Connection to %s timed out or not enough responses.", targetIpPort)) + } + if shouldHold { + checkAffinityFailed(tracker, "Affintity should hold but didn't.") + } else { + checkAffinityFailed(tracker, "Affintity shouldn't hold but did.") + } + return true + } + } + return true +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/test_context.go b/vendor/k8s.io/kubernetes/test/e2e/framework/test_context.go index e5e1fc93c..5c3099c82 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/test_context.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/test_context.go @@ -49,7 +49,12 @@ type TestContextType struct { RepoRoot string DockershimCheckpointDir string - Provider string + // Provider identifies the infrastructure provider (gce, gke, aws) + Provider string + + // Tooling is the tooling in use (e.g. kops, gke). Provider is the cloud provider and might not uniquely identify the tooling. + Tooling string + CloudConfig CloudConfig KubectlPath string OutputDir string @@ -104,14 +109,16 @@ type TestContextType struct { DisableLogDump bool // Path to the GCS artifacts directory to dump logs from nodes. Logexporter gets enabled if this is non-empty. LogexporterGCSPath string - // If the garbage collector is enabled in the kube-apiserver and kube-controller-manager. - GarbageCollectorEnabled bool // featureGates is a map of feature names to bools that enable or disable alpha/experimental features. FeatureGates map[string]bool // Node e2e specific test context NodeTestContextType + // Storage e2e specific test context + StorageTestContextType // Monitoring solution that is used in current cluster. ClusterMonitoringMode string + // Separate Prometheus monitoring deployed in cluster + EnablePrometheusMonitoring bool // Indicates what path the kubernetes-anywhere is installed on KubernetesAnywherePath string @@ -155,6 +162,14 @@ type NodeTestContextType struct { SystemSpecName string } +// StorageConfig contains the shared settings for storage 2e2 tests. +type StorageTestContextType struct { + // CSIImageVersion overrides the builtin stable version numbers if set. + CSIImageVersion string + // CSIImageRegistry defines the image registry hosting the CSI container images. + CSIImageRegistry string +} + type CloudConfig struct { ApiEndpoint string ProjectID string @@ -209,7 +224,7 @@ func RegisterCommonFlags() { flag.StringVar(&TestContext.ReportDir, "report-dir", "", "Path to the directory where the JUnit XML reports should be saved. Default is empty, which doesn't generate these reports.") flag.Var(utilflag.NewMapStringBool(&TestContext.FeatureGates), "feature-gates", "A set of key=value pairs that describe feature gates for alpha/experimental features.") flag.StringVar(&TestContext.Viper, "viper-config", "e2e", "The name of the viper config i.e. 'e2e' will read values from 'e2e.json' locally. All e2e parameters are meant to be configurable by viper.") - flag.StringVar(&TestContext.ContainerRuntime, "container-runtime", "docker", "The container runtime of cluster VM instances (docker/rkt/remote).") + flag.StringVar(&TestContext.ContainerRuntime, "container-runtime", "docker", "The container runtime of cluster VM instances (docker/remote).") flag.StringVar(&TestContext.ContainerRuntimeEndpoint, "container-runtime-endpoint", "unix:///var/run/dockershim.sock", "The container runtime endpoint of cluster VM instances.") flag.StringVar(&TestContext.ContainerRuntimeProcessName, "container-runtime-process-name", "dockerd", "The name of the container runtime process.") flag.StringVar(&TestContext.ContainerRuntimePidFile, "container-runtime-pid-file", "/var/run/docker.pid", "The pid file of the container runtime.") @@ -231,12 +246,14 @@ func RegisterClusterFlags() { flag.StringVar(&TestContext.CertDir, "cert-dir", "", "Path to the directory containing the certs. Default is empty, which doesn't use certs.") flag.StringVar(&TestContext.RepoRoot, "repo-root", "../../", "Root directory of kubernetes repository, for finding test files.") flag.StringVar(&TestContext.Provider, "provider", "", "The name of the Kubernetes provider (gce, gke, local, etc.)") + flag.StringVar(&TestContext.Tooling, "tooling", "", "The tooling in use (kops, gke, etc.)") flag.StringVar(&TestContext.KubectlPath, "kubectl-path", "kubectl", "The kubectl binary to use. For development, you might use 'cluster/kubectl.sh' here.") flag.StringVar(&TestContext.OutputDir, "e2e-output-dir", "/tmp", "Output directory for interesting/useful test data, like performance data, benchmarks, and other metrics.") flag.StringVar(&TestContext.Prefix, "prefix", "e2e", "A prefix to be added to cloud resources created during testing.") flag.StringVar(&TestContext.MasterOSDistro, "master-os-distro", "debian", "The OS distribution of cluster master (debian, trusty, or coreos).") flag.StringVar(&TestContext.NodeOSDistro, "node-os-distro", "debian", "The OS distribution of cluster VM instances (debian, trusty, or coreos).") - flag.StringVar(&TestContext.ClusterMonitoringMode, "cluster-monitoring-mode", "influxdb", "The monitoring solution that is used in the cluster.") + flag.StringVar(&TestContext.ClusterMonitoringMode, "cluster-monitoring-mode", "standalone", "The monitoring solution that is used in the cluster.") + flag.BoolVar(&TestContext.EnablePrometheusMonitoring, "prometheus-monitoring", false, "Separate Prometheus monitoring deployed in cluster.") // TODO: Flags per provider? Rename gce-project/gce-zone? cloudConfig := &TestContext.CloudConfig @@ -259,7 +276,7 @@ func RegisterClusterFlags() { flag.StringVar(&cloudConfig.ConfigFile, "cloud-config-file", "", "Cloud config file. Only required if provider is azure.") flag.IntVar(&TestContext.MinStartupPods, "minStartupPods", 0, "The number of pods which we need to see in 'Running' state with a 'Ready' condition of true, before we try running tests. This is useful in any cluster which needs some base pod-based services running before it can be used.") flag.DurationVar(&TestContext.SystemPodsStartupTimeout, "system-pods-startup-timeout", 10*time.Minute, "Timeout for waiting for all system pods to be running before starting tests.") - flag.DurationVar(&TestContext.NodeSchedulableTimeout, "node-schedulable-timeout", 4*time.Hour, "Timeout for waiting for all nodes to be schedulable.") + flag.DurationVar(&TestContext.NodeSchedulableTimeout, "node-schedulable-timeout", 30*time.Minute, "Timeout for waiting for all nodes to be schedulable.") flag.StringVar(&TestContext.UpgradeTarget, "upgrade-target", "ci/latest", "Version to upgrade to (e.g. 'release/stable', 'release/latest', 'ci/latest', '0.19.1', '0.19.1-669-gabac8c8') if doing an upgrade test.") flag.StringVar(&TestContext.EtcdUpgradeStorage, "etcd-upgrade-storage", "", "The storage version to upgrade to (either 'etcdv2' or 'etcdv3') if doing an etcd upgrade test.") flag.StringVar(&TestContext.EtcdUpgradeVersion, "etcd-upgrade-version", "", "The etcd binary version to upgrade to (e.g., '3.0.14', '2.3.7') if doing an etcd upgrade test.") @@ -267,7 +284,6 @@ func RegisterClusterFlags() { flag.StringVar(&TestContext.IngressUpgradeImage, "ingress-upgrade-image", "", "Image to upgrade to if doing an upgrade test for ingress.") flag.StringVar(&TestContext.GCEUpgradeScript, "gce-upgrade-script", "", "Script to use to upgrade a GCE cluster.") flag.BoolVar(&TestContext.CleanStart, "clean-start", false, "If true, purge all namespaces except default and system before running tests. This serves to Cleanup test namespaces from failed/interrupted e2e runs in a long-lived cluster.") - flag.BoolVar(&TestContext.GarbageCollectorEnabled, "garbage-collector-enabled", true, "Set to true if the garbage collector is enabled in the kube-apiserver and kube-controller-manager, then some tests will rely on the garbage collector to delete dependent resources.") } // Register flags specific to the node e2e test suite. @@ -277,7 +293,7 @@ func RegisterNodeFlags() { flag.StringVar(&TestContext.NodeName, "node-name", "", "Name of the node to run tests on.") // TODO(random-liu): Move kubelet start logic out of the test. // TODO(random-liu): Move log fetch logic out of the test. - // There are different ways to start kubelet (systemd, initd, docker, rkt, manually started etc.) + // There are different ways to start kubelet (systemd, initd, docker, manually started etc.) // and manage logs (journald, upstart etc.). // For different situation we need to mount different things into the container, run different commands. // It is hard and unnecessary to deal with the complexity inside the test suite. @@ -287,6 +303,11 @@ func RegisterNodeFlags() { flag.StringVar(&TestContext.SystemSpecName, "system-spec-name", "", "The name of the system spec (e.g., gke) that's used in the node e2e test. The system specs are in test/e2e_node/system/specs/. This is used by the test framework to determine which tests to run for validating the system requirements.") } +func RegisterStorageFlags() { + flag.StringVar(&TestContext.CSIImageVersion, "csiImageVersion", "", "overrides the default tag used for hostpathplugin/csi-attacher/csi-provisioner/driver-registrar images") + flag.StringVar(&TestContext.CSIImageRegistry, "csiImageRegistry", "quay.io/k8scsi", "overrides the default repository used for hostpathplugin/csi-attacher/csi-provisioner/driver-registrar images") +} + // ViperizeFlags sets up all flag and config processing. Future configuration info should be added to viper, not to flags. func ViperizeFlags() { @@ -295,6 +316,7 @@ func ViperizeFlags() { // since go test 'flag's are sort of incompatible w/ flag, glog, etc. RegisterCommonFlags() RegisterClusterFlags() + RegisterStorageFlags() flag.Parse() // Part 2: Set Viper provided flags. @@ -365,4 +387,8 @@ func AfterReadingAllFlags(t *TestContextType) { t.Host = defaultHost } } + // Allow 1% of nodes to be unready (statistically) - relevant for large clusters. + if t.AllowedNotReadyNodes == 0 { + t.AllowedNotReadyNodes = t.CloudConfig.NumNodes / 100 + } } diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/util.go index bb5f626e3..889c403af 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/util.go @@ -56,7 +56,6 @@ import ( extensions "k8s.io/api/extensions/v1beta1" apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" @@ -77,7 +76,6 @@ import ( clientset "k8s.io/client-go/kubernetes" scaleclient "k8s.io/client-go/scale" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/api/testapi" podutil "k8s.io/kubernetes/pkg/api/v1/pod" appsinternal "k8s.io/kubernetes/pkg/apis/apps" batchinternal "k8s.io/kubernetes/pkg/apis/batch" @@ -90,12 +88,11 @@ import ( "k8s.io/kubernetes/pkg/controller" nodectlr "k8s.io/kubernetes/pkg/controller/nodelifecycle" "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/kubectl" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/kubelet/util/format" "k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" sshutil "k8s.io/kubernetes/pkg/ssh" "k8s.io/kubernetes/pkg/util/system" taintutils "k8s.io/kubernetes/pkg/util/taints" @@ -113,6 +110,11 @@ const ( // TODO: Make this 30 seconds once #4566 is resolved. PodStartTimeout = 5 * time.Minute + // Same as `PodStartTimeout` to wait for the pod to be started, but shorter. + // Use it case by case when we are sure pod start will not be delayed + // minutes by slow docker pulls or something else. + PodStartShortTimeout = 1 * time.Minute + // How long to wait for a pod to be deleted PodDeleteTimeout = 5 * time.Minute @@ -125,7 +127,7 @@ const ( slowPodStartTimeout = 15 * time.Minute // How long to wait for a service endpoint to be resolvable. - ServiceStartTimeout = 1 * time.Minute + ServiceStartTimeout = 3 * time.Minute // How often to Poll pods, nodes and claims. Poll = 2 * time.Second @@ -159,6 +161,10 @@ const ( // How long claims have to become dynamically provisioned ClaimProvisionTimeout = 5 * time.Minute + // Same as `ClaimProvisionTimeout` to wait for claim to be dynamically provisioned, but shorter. + // Use it case by case when we are sure this timeout is enough. + ClaimProvisionShortTimeout = 1 * time.Minute + // How long claims have to become bound ClaimBindingTimeout = 3 * time.Minute @@ -367,6 +373,12 @@ func SkipUnlessClusterMonitoringModeIs(supportedMonitoring ...string) { } } +func SkipUnlessPrometheusMonitoringIsEnabled(supportedMonitoring ...string) { + if !TestContext.EnablePrometheusMonitoring { + Skipf("Skipped because prometheus monitoring is not enabled") + } +} + func SkipUnlessMasterOSDistroIs(supportedMasterOsDistros ...string) { if !MasterOSDistroIs(supportedMasterOsDistros...) { Skipf("Only supported for master OS distro %v (not %s)", supportedMasterOsDistros, TestContext.MasterOSDistro) @@ -379,6 +391,22 @@ func SkipUnlessNodeOSDistroIs(supportedNodeOsDistros ...string) { } } +func SkipUnlessSecretExistsAfterWait(c clientset.Interface, name, namespace string, timeout time.Duration) { + Logf("Waiting for secret %v in namespace %v to exist in duration %v", name, namespace, timeout) + start := time.Now() + if wait.PollImmediate(15*time.Second, timeout, func() (bool, error) { + _, err := c.CoreV1().Secrets(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + Logf("Secret %v in namespace %v still does not exist after duration %v", name, namespace, time.Since(start)) + return false, nil + } + return true, nil + }) != nil { + Skipf("Secret %v in namespace %v did not exist after timeout of %v", name, namespace, timeout) + } + Logf("Secret %v in namespace %v found after duration %v", name, namespace, time.Since(start)) +} + func SkipIfContainerRuntimeIs(runtimes ...string) { for _, runtime := range runtimes { if runtime == TestContext.ContainerRuntime { @@ -480,13 +508,9 @@ func SkipUnlessServerVersionGTE(v *utilversion.Version, c discovery.ServerVersio } } -func SkipIfMissingResource(clientPool dynamic.ClientPool, gvr schema.GroupVersionResource, namespace string) { - dynamicClient, err := clientPool.ClientForGroupVersionResource(gvr) - if err != nil { - Failf("Unexpected error getting dynamic client for %v: %v", gvr.GroupVersion(), err) - } - apiResource := metav1.APIResource{Name: gvr.Resource, Namespaced: true} - _, err = dynamicClient.Resource(&apiResource, namespace).List(metav1.ListOptions{}) +func SkipIfMissingResource(dynamicClient dynamic.Interface, gvr schema.GroupVersionResource, namespace string) { + resourceClient := dynamicClient.Resource(gvr).Namespace(namespace) + _, err := resourceClient.List(metav1.ListOptions{}) if err != nil { // not all resources support list, so we ignore those if apierrs.IsMethodNotSupported(err) || apierrs.IsNotFound(err) || apierrs.IsForbidden(err) { @@ -679,10 +703,9 @@ func WaitForPodsRunningReady(c clientset.Interface, ns string, minPods, allowedN case res && err == nil: nOk++ case pod.Status.Phase == v1.PodSucceeded: - Logf("The status of Pod %s is Succeeded which is unexpected", pod.ObjectMeta.Name) - badPods = append(badPods, pod) + Logf("The status of Pod %s is Succeeded, skipping waiting", pod.ObjectMeta.Name) // it doesn't make sense to wait for this pod - return false, errors.New("unexpected Succeeded pod state") + continue case pod.Status.Phase != v1.PodFailed: Logf("The status of Pod %s is %s (Ready = false), waiting for it to be either Running (with Ready = true) or Failed", pod.ObjectMeta.Name, pod.Status.Phase) notReady++ @@ -1064,7 +1087,7 @@ func CheckTestingNSDeletedExcept(c clientset.Interface, skip string) error { // deleteNS deletes the provided namespace, waits for it to be completely deleted, and then checks // whether there are any pods remaining in a non-terminating state. -func deleteNS(c clientset.Interface, clientPool dynamic.ClientPool, namespace string, timeout time.Duration) error { +func deleteNS(c clientset.Interface, dynamicClient dynamic.Interface, namespace string, timeout time.Duration) error { startTime := time.Now() if err := c.CoreV1().Namespaces().Delete(namespace, nil); err != nil { return err @@ -1083,7 +1106,7 @@ func deleteNS(c clientset.Interface, clientPool dynamic.ClientPool, namespace st }) // verify there is no more remaining content in the namespace - remainingContent, cerr := hasRemainingContent(c, clientPool, namespace) + remainingContent, cerr := hasRemainingContent(c, dynamicClient, namespace) if cerr != nil { return cerr } @@ -1119,7 +1142,7 @@ func deleteNS(c clientset.Interface, clientPool dynamic.ClientPool, namespace st // no remaining content, but namespace was not deleted (namespace controller is probably wedged) return fmt.Errorf("namespace %v was not deleted with limit: %v, namespace is empty but is not yet removed", namespace, err) } - Logf("namespace %v deletion completed in %s", namespace, time.Now().Sub(startTime)) + Logf("namespace %v deletion completed in %s", namespace, time.Since(startTime)) return nil } @@ -1199,6 +1222,8 @@ func isDynamicDiscoveryError(err error) bool { // garbage_collector case "wardle.k8s.io": // aggregator + case "metrics.k8s.io": + // aggregated metrics server add-on, no persisted resources default: Logf("discovery error for unexpected group: %#v", gv) return false @@ -1208,10 +1233,10 @@ func isDynamicDiscoveryError(err error) bool { } // hasRemainingContent checks if there is remaining content in the namespace via API discovery -func hasRemainingContent(c clientset.Interface, clientPool dynamic.ClientPool, namespace string) (bool, error) { +func hasRemainingContent(c clientset.Interface, dynamicClient dynamic.Interface, namespace string) (bool, error) { // some tests generate their own framework.Client rather than the default - // TODO: ensure every test call has a configured clientPool - if clientPool == nil { + // TODO: ensure every test call has a configured dynamicClient + if dynamicClient == nil { return false, nil } @@ -1235,7 +1260,7 @@ func hasRemainingContent(c clientset.Interface, clientPool dynamic.ClientPool, n // dump how many of resource type is on the server in a log. for gvr := range groupVersionResources { // get a client for this group version... - dynamicClient, err := clientPool.ClientForGroupVersionResource(gvr) + dynamicClient := dynamicClient.Resource(gvr).Namespace(namespace) if err != nil { // not all resource types support list, so some errors here are normal depending on the resource type. Logf("namespace: %s, unable to get client - gvr: %v, error: %v", namespace, gvr, err) @@ -1243,12 +1268,11 @@ func hasRemainingContent(c clientset.Interface, clientPool dynamic.ClientPool, n } // get the api resource apiResource := metav1.APIResource{Name: gvr.Resource, Namespaced: true} - // TODO: temporary hack for https://github.com/kubernetes/kubernetes/issues/31798 - if ignoredResources.Has(apiResource.Name) { + if ignoredResources.Has(gvr.Resource) { Logf("namespace: %s, resource: %s, ignored listing per whitelist", namespace, apiResource.Name) continue } - obj, err := dynamicClient.Resource(&apiResource, namespace).List(metav1.ListOptions{}) + unstructuredList, err := dynamicClient.List(metav1.ListOptions{}) if err != nil { // not all resources support list, so we ignore those if apierrs.IsMethodNotSupported(err) || apierrs.IsNotFound(err) || apierrs.IsForbidden(err) { @@ -1260,10 +1284,6 @@ func hasRemainingContent(c clientset.Interface, clientPool dynamic.ClientPool, n } return false, err } - unstructuredList, ok := obj.(*unstructured.UnstructuredList) - if !ok { - return false, fmt.Errorf("namespace: %s, resource: %s, expected *unstructured.UnstructuredList, got %#v", namespace, apiResource.Name, obj) - } if len(unstructuredList.Items) > 0 { Logf("namespace: %s, resource: %s, items remaining: %v", namespace, apiResource.Name, len(unstructuredList.Items)) contentRemaining = true @@ -2172,7 +2192,6 @@ func (b kubectlBuilder) WithStdinReader(reader io.Reader) *kubectlBuilder { func (b kubectlBuilder) ExecOrDie() string { str, err := b.Exec() - Logf("stdout: %q", str) // In case of i/o timeout error, try talking to the apiserver again after 2s before dying. // Note that we're still dying after retrying so that we can get visibility to triage it further. if isTimeout(err) { @@ -2231,6 +2250,7 @@ func (b kubectlBuilder) Exec() (string, error) { return "", fmt.Errorf("timed out waiting for command %v:\nCommand stdout:\n%v\nstderr:\n%v\n", cmd, cmd.Stdout, cmd.Stderr) } Logf("stderr: %q", stderr.String()) + Logf("stdout: %q", stdout.String()) return stdout.String(), nil } @@ -2249,17 +2269,17 @@ func RunKubectlOrDieInput(data string, args ...string) string { return NewKubectlCommand(args...).WithStdinData(data).ExecOrDie() } -// runKubemciWithKubeconfig is a convenience wrapper over runKubemciCmd -func runKubemciWithKubeconfig(args ...string) (string, error) { +// RunKubemciWithKubeconfig is a convenience wrapper over RunKubemciCmd +func RunKubemciWithKubeconfig(args ...string) (string, error) { if TestContext.KubeConfig != "" { args = append(args, "--"+clientcmd.RecommendedConfigPathFlag+"="+TestContext.KubeConfig) } - return runKubemciCmd(args...) + return RunKubemciCmd(args...) } -// runKubemciCmd is a convenience wrapper over kubectlBuilder to run kubemci. +// RunKubemciCmd is a convenience wrapper over kubectlBuilder to run kubemci. // It assumes that kubemci exists in PATH. -func runKubemciCmd(args ...string) (string, error) { +func RunKubemciCmd(args ...string) (string, error) { // kubemci is assumed to be in PATH. kubemci := "kubemci" b := new(kubectlBuilder) @@ -2550,7 +2570,7 @@ func isNodeUntainted(node *v1.Node) bool { fakePod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: "fake-not-scheduled", @@ -2589,6 +2609,18 @@ func GetReadySchedulableNodesOrDie(c clientset.Interface) (nodes *v1.NodeList) { return nodes } +// GetReadyNodesIncludingTaintedOrDie returns all ready nodes, even those which are tainted. +// There are cases when we care about tainted nodes +// E.g. in tests related to nodes with gpu we care about nodes despite +// presence of nvidia.com/gpu=present:NoSchedule taint +func GetReadyNodesIncludingTaintedOrDie(c clientset.Interface) (nodes *v1.NodeList) { + nodes = waitListSchedulableNodesOrDie(c) + FilterNodes(nodes, func(node v1.Node) bool { + return isNodeSchedulable(&node) + }) + return nodes +} + func WaitForAllNodesSchedulable(c clientset.Interface, timeout time.Duration) error { Logf("Waiting up to %v for all (but %d) nodes to be schedulable", timeout, TestContext.AllowedNotReadyNodes) @@ -2806,7 +2838,6 @@ func RemoveAvoidPodsOffNode(c clientset.Interface, nodeName string) { func ScaleResource( clientset clientset.Interface, - internalClientset internalclientset.Interface, scalesGetter scaleclient.ScalesGetter, ns, name string, size uint, @@ -2815,8 +2846,7 @@ func ScaleResource( gr schema.GroupResource, ) error { By(fmt.Sprintf("Scaling %v %s in namespace %s to %d", kind, name, ns, size)) - scaler := kubectl.ScalerFor(kind, internalClientset.Batch(), scalesGetter, gr) - if err := testutils.ScaleResourceWithRetries(scaler, ns, name, size); err != nil { + if err := testutils.ScaleResourceWithRetries(scalesGetter, ns, name, size, gr); err != nil { return fmt.Errorf("error while scaling RC %s to %d replicas: %v", name, size, err) } if !wait { @@ -2998,6 +3028,8 @@ func getReplicasFromRuntimeObject(obj runtime.Object) (int32, error) { return *typed.Spec.Replicas, nil } return 0, nil + case *extensions.DaemonSet: + return 0, nil case *batch.Job: // TODO: currently we use pause pods so that's OK. When we'll want to switch to Pods // that actually finish we need a better way to do this. @@ -3010,50 +3042,6 @@ func getReplicasFromRuntimeObject(obj runtime.Object) (int32, error) { } } -// DeleteResourceAndPods deletes a given resource and all pods it spawned -func DeleteResourceAndPods(clientset clientset.Interface, internalClientset internalclientset.Interface, kind schema.GroupKind, ns, name string) error { - By(fmt.Sprintf("deleting %v %s in namespace %s", kind, name, ns)) - - rtObject, err := getRuntimeObjectForKind(clientset, kind, ns, name) - if err != nil { - if apierrs.IsNotFound(err) { - Logf("%v %s not found: %v", kind, name, err) - return nil - } - return err - } - selector, err := getSelectorFromRuntimeObject(rtObject) - if err != nil { - return err - } - ps, err := testutils.NewPodStore(clientset, ns, selector, fields.Everything()) - if err != nil { - return err - } - defer ps.Stop() - startTime := time.Now() - if err := testutils.DeleteResourceUsingReaperWithRetries(internalClientset, kind, ns, name, nil); err != nil { - return fmt.Errorf("error while stopping %v: %s: %v", kind, name, err) - } - deleteTime := time.Now().Sub(startTime) - Logf("Deleting %v %s took: %v", kind, name, deleteTime) - err = waitForPodsInactive(ps, 100*time.Millisecond, 10*time.Minute) - if err != nil { - return fmt.Errorf("error while waiting for pods to become inactive %s: %v", name, err) - } - terminatePodTime := time.Now().Sub(startTime) - deleteTime - Logf("Terminating %v %s pods took: %v", kind, name, terminatePodTime) - // this is to relieve namespace controller's pressure when deleting the - // namespace after a test. - err = waitForPodsGone(ps, 100*time.Millisecond, 10*time.Minute) - if err != nil { - return fmt.Errorf("error while waiting for pods gone %s: %v", name, err) - } - gcPodTime := time.Now().Sub(startTime) - terminatePodTime - Logf("Garbage collecting %v %s pods took: %v", kind, name, gcPodTime) - return nil -} - // DeleteResourceAndWaitForGC deletes only given resource and waits for GC to delete the pods. func DeleteResourceAndWaitForGC(c clientset.Interface, kind schema.GroupKind, ns, name string) error { By(fmt.Sprintf("deleting %v %s in namespace %s, will wait for the garbage collector to delete the pods", kind, name, ns)) @@ -3087,7 +3075,7 @@ func DeleteResourceAndWaitForGC(c clientset.Interface, kind schema.GroupKind, ns if err := testutils.DeleteResourceWithRetries(c, kind, ns, name, deleteOption); err != nil { return err } - deleteTime := time.Now().Sub(startTime) + deleteTime := time.Since(startTime) Logf("Deleting %v %s took: %v", kind, name, deleteTime) var interval, timeout time.Duration @@ -3111,7 +3099,7 @@ func DeleteResourceAndWaitForGC(c clientset.Interface, kind schema.GroupKind, ns if err != nil { return fmt.Errorf("error while waiting for pods to become inactive %s: %v", name, err) } - terminatePodTime := time.Now().Sub(startTime) - deleteTime + terminatePodTime := time.Since(startTime) - deleteTime Logf("Terminating %v %s pods took: %v", kind, name, terminatePodTime) err = waitForPodsGone(ps, interval, 10*time.Minute) @@ -3442,7 +3430,7 @@ func newExecPodSpec(ns, generateName string) *v1.Pod { { Name: "exec", Image: BusyBoxImage, - Command: []string{"sh", "-c", "while true; do sleep 5; done"}, + Command: []string{"sh", "-c", "trap exit TERM; while true; do sleep 5; done"}, }, }, }, @@ -3486,7 +3474,7 @@ func CreatePodOrFail(c clientset.Interface, ns, name string, labels map[string]s Containers: []v1.Container{ { Name: "pause", - Image: GetPauseImageName(c), + Image: imageutils.GetPauseImageName(), Ports: containerPorts, // Add a dummy environment variable to work around a docker issue. // https://github.com/docker/docker/issues/14203 diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/volume_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/volume_util.go index 45d2c4bf3..9eb5269ad 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/volume_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/volume_util.go @@ -67,6 +67,10 @@ const ( // Waiting period for volume server (Ceph, ...) to initialize itself. VolumeServerPodStartupSleep = 20 * time.Second + + // Waiting period for pod to be cleaned up and unmount its volumes so we + // don't tear down containers with NFS/Ceph/Gluster server too early. + PodCleanupTimeout = 20 * time.Second ) // Configuration of one tests. The test consist of: @@ -182,7 +186,7 @@ func NewISCSIServer(cs clientset.Interface, namespace string) (config VolumeTest } // CephRBD-specific wrapper for CreateStorageServer. -func NewRBDServer(cs clientset.Interface, namespace string) (config VolumeTestConfig, pod *v1.Pod, ip string) { +func NewRBDServer(cs clientset.Interface, namespace string) (config VolumeTestConfig, pod *v1.Pod, secret *v1.Secret, ip string) { config = VolumeTestConfig{ Namespace: namespace, Prefix: "rbd", @@ -201,7 +205,28 @@ func NewRBDServer(cs clientset.Interface, namespace string) (config VolumeTestCo Logf("sleeping a bit to give ceph server time to initialize") time.Sleep(VolumeServerPodStartupSleep) - return config, pod, ip + // create secrets for the server + secret = &v1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: config.Prefix + "-secret", + }, + Data: map[string][]byte{ + // from test/images/volumes-tester/rbd/keyring + "key": []byte("AQDRrKNVbEevChAAEmRC+pW/KBVHxa0w/POILA=="), + }, + Type: "kubernetes.io/rbd", + } + + secret, err := cs.CoreV1().Secrets(config.Namespace).Create(secret) + if err != nil { + Failf("Failed to create secrets for Ceph RBD: %v", err) + } + + return config, pod, secret, ip } // Wrapper for StartVolumeServer(). A storage server config is passed in, and a pod pointer @@ -351,8 +376,8 @@ func VolumeTestCleanup(f *Framework, config VolumeTestConfig) { } // See issue #24100. // Prevent umount errors by making sure making sure the client pod exits cleanly *before* the volume server pod exits. - By("sleeping a bit so client can stop and unmount") - time.Sleep(20 * time.Second) + By("sleeping a bit so kubelet can unmount and detach the volume") + time.Sleep(PodCleanupTimeout) err = podClient.Delete(config.Prefix+"-server", nil) if err != nil { diff --git a/vendor/k8s.io/kubernetes/test/e2e/generated/BUILD b/vendor/k8s.io/kubernetes/test/e2e/generated/BUILD index 5ad22c808..250b66822 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/generated/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/generated/BUILD @@ -4,6 +4,7 @@ load( "@io_bazel_rules_go//go:def.bzl", "go_library", ) +load("//build:bindata.bzl", "go_bindata") go_library( name = "go_default_library", @@ -18,25 +19,17 @@ go_library( ], ) -genrule( +# IMPORTANT: if you make any changes here, you must also update hack/generate-bindata.sh. +go_bindata( name = "bindata", srcs = [ - "//examples:all-srcs", - "//test/images:all-srcs", - "//test/fixtures:all-srcs", "//test/e2e/testing-manifests:all-srcs", + "//test/fixtures:all-srcs", + "//test/images:all-srcs", ], outs = ["bindata.go"], - cmd = """ -$(location //vendor/github.com/jteeuwen/go-bindata/go-bindata:go-bindata) \ - -nometadata -o "$(OUTS)" -pkg generated \ - -prefix $$(pwd) \ - -ignore .jpg -ignore .png -ignore .md \ - $(SRCS) -""", - tools = [ - "//vendor/github.com/jteeuwen/go-bindata/go-bindata", - ], + compress = True, + include_metadata = False, ) filegroup( diff --git a/vendor/k8s.io/kubernetes/test/e2e/generated/gobindata_util.go b/vendor/k8s.io/kubernetes/test/e2e/generated/gobindata_util.go index 0d939dd53..62e031d98 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/generated/gobindata_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/generated/gobindata_util.go @@ -16,8 +16,6 @@ limitations under the License. package generated -//go:generate ../../../hack/generate-bindata.sh - import "github.com/golang/glog" /* diff --git a/vendor/k8s.io/kubernetes/test/e2e/gke_local_ssd.go b/vendor/k8s.io/kubernetes/test/e2e/gke_local_ssd.go index 5be3938d7..7e4965ec4 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/gke_local_ssd.go +++ b/vendor/k8s.io/kubernetes/test/e2e/gke_local_ssd.go @@ -23,7 +23,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" @@ -74,7 +73,7 @@ func testPodWithSsd(command string) *v1.Pod { return &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: podName, diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/OWNERS b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/OWNERS index 3d75e7e79..391449586 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/OWNERS +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/OWNERS @@ -1,9 +1,9 @@ approvers: -- crassirostris - DirectXMan12 - fabxc - fgrzadkowski - piosz - x13n +- kawych reviewers: - sig-instrumentation-pr-reviews diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/BUILD b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/BUILD index 6d1698b41..d68ba2aab 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/BUILD @@ -16,7 +16,7 @@ go_library( "//test/e2e/framework:go_default_library", "//test/e2e/instrumentation/common:go_default_library", "//test/e2e/instrumentation/logging/elasticsearch:go_default_library", - "//test/e2e/instrumentation/logging/stackdrvier:go_default_library", + "//test/e2e/instrumentation/logging/stackdriver:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -35,7 +35,7 @@ filegroup( srcs = [ ":package-srcs", "//test/e2e/instrumentation/logging/elasticsearch:all-srcs", - "//test/e2e/instrumentation/logging/stackdrvier:all-srcs", + "//test/e2e/instrumentation/logging/stackdriver:all-srcs", "//test/e2e/instrumentation/logging/utils:all-srcs", ], tags = ["automanaged"], diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/OWNERS b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/OWNERS index 531d740bd..1a6a1d51b 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/OWNERS +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/OWNERS @@ -1,8 +1,6 @@ reviewers: - coffeepac - - crassirostris - piosz approvers: - coffeepac - - crassirostris - piosz diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/imports.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/imports.go index a3621e7bd..aaf73d90d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/imports.go +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/imports.go @@ -18,5 +18,5 @@ package logging import ( _ "k8s.io/kubernetes/test/e2e/instrumentation/logging/elasticsearch" - _ "k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier" + _ "k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver" ) diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/BUILD b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/BUILD new file mode 100644 index 000000000..3c9b7951e --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/BUILD @@ -0,0 +1,41 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "basic.go", + "soak.go", + "utils.go", + ], + importpath = "k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver", + deps = [ + "//test/e2e/framework:go_default_library", + "//test/e2e/instrumentation/common:go_default_library", + "//test/e2e/instrumentation/logging/utils:go_default_library", + "//vendor/github.com/onsi/ginkgo:go_default_library", + "//vendor/golang.org/x/oauth2/google:go_default_library", + "//vendor/google.golang.org/api/logging/v2beta1:go_default_library", + "//vendor/google.golang.org/api/pubsub/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/basic.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/basic.go similarity index 99% rename from vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/basic.go rename to vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/basic.go index 865c9bf1a..e8a30379e 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/basic.go +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/basic.go @@ -163,7 +163,7 @@ var _ = instrumentation.SIGDescribe("Cluster level logging implemented by Stackd ginkgo.By("Waiting for events to ingest") location := framework.TestContext.CloudConfig.Zone - if framework.TestContext.CloudConfig.MultiZone { + if framework.TestContext.CloudConfig.MultiMaster { location = framework.TestContext.CloudConfig.Region } c := utils.NewLogChecker(p, utils.UntilFirstEntryFromLocation(location), utils.JustTimeout, "") diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/soak.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/soak.go similarity index 98% rename from vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/soak.go rename to vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/soak.go index e1a863190..14df92bdc 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/soak.go +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/soak.go @@ -49,7 +49,7 @@ var _ = instrumentation.SIGDescribe("Cluster level logging implemented by Stackd maxPodCount := 10 jobDuration := 30 * time.Minute linesPerPodPerSecond := 100 - // TODO(crassirostris): Increase to 21 hrs + // TODO(instrumentation): Increase to 21 hrs testDuration := 3 * time.Hour ingestionInterval := 1 * time.Minute ingestionTimeout := testDuration + 30*time.Minute diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/utils.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/utils.go similarity index 89% rename from vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/utils.go rename to vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/utils.go index b02378229..27360474a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/utils.go +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdriver/utils.go @@ -17,6 +17,7 @@ limitations under the License. package stackdriver import ( + "context" "encoding/base64" "encoding/json" "fmt" @@ -27,7 +28,6 @@ import ( "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/instrumentation/logging/utils" - "golang.org/x/net/context" "golang.org/x/oauth2/google" sd "google.golang.org/api/logging/v2beta1" pubsub "google.golang.org/api/pubsub/v1" @@ -49,6 +49,9 @@ const ( // The parallelism level of polling logs process. sdLoggingPollParallelism = 10 + + // The limit on the number of stackdriver sinks that can be created within one project. + stackdriverSinkCountLimit = 90 ) type logProviderScope int @@ -86,6 +89,10 @@ func newSdLogProvider(f *framework.Framework, scope logProviderScope) (*sdLogPro if err != nil { return nil, err } + err = ensureProjectHasSinkCapacity(sdService.Projects.Sinks, framework.TestContext.CloudConfig.ProjectID) + if err != nil { + return nil, err + } pubsubService, err := pubsub.New(hc) if err != nil { @@ -104,6 +111,36 @@ func newSdLogProvider(f *framework.Framework, scope logProviderScope) (*sdLogPro return provider, nil } +func ensureProjectHasSinkCapacity(sinksService *sd.ProjectsSinksService, projectID string) error { + listResponse, err := listSinks(sinksService, projectID) + if err != nil { + return err + } + if len(listResponse.Sinks) >= stackdriverSinkCountLimit { + framework.Logf("Reached Stackdriver sink limit. Deleting all sinks") + deleteSinks(sinksService, projectID, listResponse.Sinks) + } + return nil +} + +func listSinks(sinksService *sd.ProjectsSinksService, projectID string) (*sd.ListSinksResponse, error) { + projectDst := fmt.Sprintf("projects/%s", projectID) + listResponse, err := sinksService.List(projectDst).PageSize(stackdriverSinkCountLimit).Do() + if err != nil { + return nil, fmt.Errorf("failed to list Stackdriver Logging sinks: %v", err) + } + return listResponse, nil +} + +func deleteSinks(sinksService *sd.ProjectsSinksService, projectID string, sinks []*sd.LogSink) { + for _, sink := range sinks { + sinkNameID := fmt.Sprintf("projects/%s/sinks/%s", projectID, sink.Name) + if _, err := sinksService.Delete(sinkNameID).Do(); err != nil { + framework.Logf("Failed to delete LogSink: %v", err) + } + } +} + func (p *sdLogProvider) Init() error { projectID := framework.TestContext.CloudConfig.ProjectID nsName := p.framework.Namespace.Name diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/BUILD b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/BUILD deleted file mode 100644 index dc2ad62b7..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "basic.go", - "soak.go", - "utils.go", - ], - importpath = "k8s.io/kubernetes/test/e2e/instrumentation/logging/stackdrvier", - deps = [ - "//test/e2e/framework:go_default_library", - "//test/e2e/instrumentation/common:go_default_library", - "//test/e2e/instrumentation/logging/utils:go_default_library", - "//vendor/github.com/onsi/ginkgo:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/oauth2/google:go_default_library", - "//vendor/google.golang.org/api/logging/v2beta1:go_default_library", - "//vendor/google.golang.org/api/pubsub/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/utils/misc.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/utils/misc.go index 19b4622de..76b44a048 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/utils/misc.go +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/logging/utils/misc.go @@ -26,7 +26,7 @@ func GetNodeIds(cs clientset.Interface) []string { nodes := framework.GetReadySchedulableNodesOrDie(cs) nodeIds := []string{} for _, n := range nodes.Items { - nodeIds = append(nodeIds, n.Spec.ExternalID) + nodeIds = append(nodeIds, n.Name) } return nodeIds } diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/BUILD b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/BUILD index 321d00b0d..2eaa75ec7 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/BUILD @@ -14,6 +14,7 @@ go_library( "custom_metrics_stackdriver.go", "influxdb.go", "metrics_grabber.go", + "prometheus.go", "stackdriver.go", "stackdriver_metadata_agent.go", ], @@ -28,6 +29,7 @@ go_library( "//vendor/github.com/influxdata/influxdb/client/v2:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", + "//vendor/github.com/prometheus/common/model:go_default_library", "//vendor/golang.org/x/oauth2/google:go_default_library", "//vendor/google.golang.org/api/monitoring/v3:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", @@ -42,6 +44,7 @@ go_library( "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/metrics/pkg/client/custom_metrics:go_default_library", + "//vendor/k8s.io/metrics/pkg/client/external_metrics:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/custom_metrics_deployments.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/custom_metrics_deployments.go index f1d3e0926..898d6e1a3 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/custom_metrics_deployments.go +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/custom_metrics_deployments.go @@ -18,6 +18,7 @@ package monitoring import ( "fmt" + "strings" gcm "google.golang.org/api/monitoring/v3" corev1 "k8s.io/api/core/v1" @@ -25,6 +26,7 @@ import ( rbac "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/test/e2e/framework" + "os/exec" ) var ( @@ -52,6 +54,11 @@ var ( }, }, } + StagingDeploymentsLocation = "https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/staging/" + AdapterForOldResourceModel = "adapter_old_resource_model.yaml" + AdapterForNewResourceModel = "adapter_new_resource_model.yaml" + AdapterDefault = AdapterForOldResourceModel + ClusterAdminBinding = "e2e-test-cluster-admin-binding" ) // CustomMetricContainerSpec allows to specify a config for StackdriverExporterDeployment @@ -82,7 +89,7 @@ func SimpleStackdriverExporterDeployment(name, namespace string, replicas int32, func StackdriverExporterDeployment(name, namespace string, replicas int32, containers []CustomMetricContainerSpec) *extensions.Deployment { podSpec := corev1.PodSpec{Containers: []corev1.Container{}} for _, containerSpec := range containers { - podSpec.Containers = append(podSpec.Containers, stackdriverExporterContainerSpec(containerSpec.Name, containerSpec.MetricName, containerSpec.MetricValue)) + podSpec.Containers = append(podSpec.Containers, stackdriverExporterContainerSpec(containerSpec.Name, namespace, containerSpec.MetricName, containerSpec.MetricValue)) } return &extensions.Deployment{ @@ -119,17 +126,30 @@ func StackdriverExporterPod(podName, namespace, podLabel, metricName string, met }, }, Spec: corev1.PodSpec{ - Containers: []corev1.Container{stackdriverExporterContainerSpec(StackdriverExporter, metricName, metricValue)}, + Containers: []corev1.Container{stackdriverExporterContainerSpec(StackdriverExporter, namespace, metricName, metricValue)}, }, } } -func stackdriverExporterContainerSpec(name string, metricName string, metricValue int64) corev1.Container { +func stackdriverExporterContainerSpec(name string, namespace string, metricName string, metricValue int64) corev1.Container { return corev1.Container{ Name: name, - Image: "k8s.gcr.io/sd-dummy-exporter:v0.1.0", + Image: "k8s.gcr.io/sd-dummy-exporter:v0.2.0", ImagePullPolicy: corev1.PullPolicy("Always"), - Command: []string{"/sd_dummy_exporter", "--pod-id=$(POD_ID)", "--metric-name=" + metricName, fmt.Sprintf("--metric-value=%v", metricValue)}, + Command: []string{ + "/bin/sh", + "-c", + strings.Join([]string{ + "./sd_dummy_exporter", + "--pod-id=$(POD_ID)", + "--pod-name=$(POD_NAME)", + "--namespace=" + namespace, + "--metric-name=" + metricName, + fmt.Sprintf("--metric-value=%v", metricValue), + "--use-old-resource-model", + "--use-new-resource-model", + }, " "), + }, Env: []corev1.EnvVar{ { Name: "POD_ID", @@ -139,6 +159,14 @@ func stackdriverExporterContainerSpec(name string, metricName string, metricValu }, }, }, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.name", + }, + }, + }, }, Ports: []corev1.ContainerPort{{ContainerPort: 80}}, } @@ -210,9 +238,35 @@ func prometheusExporterPodSpec(metricName string, metricValue int64, port int32) } } -// CreateAdapter creates Custom Metrics - Stackdriver adapter. -func CreateAdapter() error { - stat, err := framework.RunKubectl("create", "-f", "https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/adapter-beta.yaml") +// CreateAdapter creates Custom Metrics - Stackdriver adapter +// adapterDeploymentFile should be a filename for adapter deployment located in StagingDeploymentLocation +func CreateAdapter(adapterDeploymentFile string) error { + // A workaround to make the work on GKE. GKE doesn't normally allow to create cluster roles, + // which the adapter deployment does. The solution is to create cluster role binding for + // cluster-admin role and currently used service account. + err := createClusterAdminBinding() + if err != nil { + return err + } + adapterURL := StagingDeploymentsLocation + adapterDeploymentFile + err = exec.Command("wget", adapterURL).Run() + if err != nil { + return err + } + stat, err := framework.RunKubectl("create", "-f", adapterURL) + framework.Logf(stat) + return err +} + +func createClusterAdminBinding() error { + stdout, stderr, err := framework.RunCmd("gcloud", "config", "get-value", "core/account") + if err != nil { + framework.Logf(stderr) + return err + } + serviceAccount := strings.TrimSpace(stdout) + framework.Logf("current service account: %q", serviceAccount) + stat, err := framework.RunKubectl("create", "clusterrolebinding", ClusterAdminBinding, "--clusterrole=cluster-admin", "--user="+serviceAccount) framework.Logf(stat) return err } @@ -251,8 +305,23 @@ func CleanupDescriptors(service *gcm.Service, projectId string) { } // CleanupAdapter deletes Custom Metrics - Stackdriver adapter deployments. -func CleanupAdapter() error { - stat, err := framework.RunKubectl("delete", "-f", "https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/adapter-beta.yaml") +func CleanupAdapter(adapterDeploymentFile string) { + stat, err := framework.RunKubectl("delete", "-f", adapterDeploymentFile) framework.Logf(stat) - return err + if err != nil { + framework.Logf("Failed to delete adapter deployments: %s", err) + } + err = exec.Command("rm", adapterDeploymentFile).Run() + if err != nil { + framework.Logf("Failed to delete adapter deployment file: %s", err) + } + cleanupClusterAdminBinding() +} + +func cleanupClusterAdminBinding() { + stat, err := framework.RunKubectl("delete", "clusterrolebinding", ClusterAdminBinding) + framework.Logf(stat) + if err != nil { + framework.Logf("Failed to delete cluster admin binding: %s", err) + } } diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/custom_metrics_stackdriver.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/custom_metrics_stackdriver.go index 66ac0466a..d4116da70 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/custom_metrics_stackdriver.go +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/custom_metrics_stackdriver.go @@ -28,12 +28,14 @@ import ( instrumentation "k8s.io/kubernetes/test/e2e/instrumentation/common" gcm "google.golang.org/api/monitoring/v3" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/selection" "k8s.io/client-go/discovery" "k8s.io/kubernetes/test/e2e/framework" customclient "k8s.io/metrics/pkg/client/custom_metrics" + externalclient "k8s.io/metrics/pkg/client/external_metrics" ) const ( @@ -48,40 +50,88 @@ var _ = instrumentation.SIGDescribe("Stackdriver Monitoring", func() { }) f := framework.NewDefaultFramework("stackdriver-monitoring") - var kubeClient clientset.Interface - var customMetricsClient customclient.CustomMetricsClient - var discoveryClient *discovery.DiscoveryClient - It("should run Custom Metrics - Stackdriver Adapter [Feature:StackdriverCustomMetrics]", func() { - kubeClient = f.ClientSet + It("should run Custom Metrics - Stackdriver Adapter for old resource model [Feature:StackdriverCustomMetrics]", func() { + kubeClient := f.ClientSet config, err := framework.LoadConfig() if err != nil { framework.Failf("Failed to load config: %s", err) } - customMetricsClient = customclient.NewForConfigOrDie(config) - discoveryClient = discovery.NewDiscoveryClientForConfigOrDie(config) - testAdapter(f, kubeClient, customMetricsClient, discoveryClient) + customMetricsClient := customclient.NewForConfigOrDie(config) + discoveryClient := discovery.NewDiscoveryClientForConfigOrDie(config) + testCustomMetrics(f, kubeClient, customMetricsClient, discoveryClient, AdapterForOldResourceModel) + }) + + It("should run Custom Metrics - Stackdriver Adapter for new resource model [Feature:StackdriverCustomMetrics]", func() { + kubeClient := f.ClientSet + config, err := framework.LoadConfig() + if err != nil { + framework.Failf("Failed to load config: %s", err) + } + customMetricsClient := customclient.NewForConfigOrDie(config) + discoveryClient := discovery.NewDiscoveryClientForConfigOrDie(config) + testCustomMetrics(f, kubeClient, customMetricsClient, discoveryClient, AdapterForNewResourceModel) + }) + + It("should run Custom Metrics - Stackdriver Adapter for external metrics [Feature:StackdriverExternalMetrics]", func() { + kubeClient := f.ClientSet + config, err := framework.LoadConfig() + if err != nil { + framework.Failf("Failed to load config: %s", err) + } + externalMetricsClient := externalclient.NewForConfigOrDie(config) + testExternalMetrics(f, kubeClient, externalMetricsClient) }) }) -func testAdapter(f *framework.Framework, kubeClient clientset.Interface, customMetricsClient customclient.CustomMetricsClient, discoveryClient *discovery.DiscoveryClient) { +func testCustomMetrics(f *framework.Framework, kubeClient clientset.Interface, customMetricsClient customclient.CustomMetricsClient, discoveryClient *discovery.DiscoveryClient, adapterDeployment string) { projectId := framework.TestContext.CloudConfig.ProjectID ctx := context.Background() client, err := google.DefaultClient(ctx, gcm.CloudPlatformScope) - // Hack for running tests locally, needed to authenticate in Stackdriver - // If this is your use case, create application default credentials: - // $ gcloud auth application-default login - // and uncomment following lines (comment out the two lines above): - /* - ts, err := google.DefaultTokenSource(oauth2.NoContext) - framework.Logf("Couldn't get application default credentials, %v", err) - if err != nil { - framework.Failf("Error accessing application default credentials, %v", err) - } - client := oauth2.NewClient(oauth2.NoContext, ts) - */ + gcmService, err := gcm.New(client) + if err != nil { + framework.Failf("Failed to create gcm service, %v", err) + } + + // Set up a cluster: create a custom metric and set up k8s-sd adapter + err = CreateDescriptors(gcmService, projectId) + if err != nil { + framework.Failf("Failed to create metric descriptor: %s", err) + } + defer CleanupDescriptors(gcmService, projectId) + + err = CreateAdapter(adapterDeployment) + if err != nil { + framework.Failf("Failed to set up: %s", err) + } + defer CleanupAdapter(adapterDeployment) + + _, err = kubeClient.RbacV1().ClusterRoleBindings().Create(HPAPermissions) + defer kubeClient.RbacV1().ClusterRoleBindings().Delete("custom-metrics-reader", &metav1.DeleteOptions{}) + + // Run application that exports the metric + _, err = createSDExporterPods(f, kubeClient) + if err != nil { + framework.Failf("Failed to create stackdriver-exporter pod: %s", err) + } + defer cleanupSDExporterPod(f, kubeClient) + + // Wait a short amount of time to create a pod and export some metrics + // TODO: add some events to wait for instead of fixed amount of time + // i.e. pod creation, first time series exported + time.Sleep(60 * time.Second) + + verifyResponsesFromCustomMetricsAPI(f, customMetricsClient, discoveryClient) +} + +// TODO(kawych): migrate this test to new resource model +func testExternalMetrics(f *framework.Framework, kubeClient clientset.Interface, externalMetricsClient externalclient.ExternalMetricsClient) { + projectId := framework.TestContext.CloudConfig.ProjectID + + ctx := context.Background() + client, err := google.DefaultClient(ctx, gcm.CloudPlatformScope) gcmService, err := gcm.New(client) if err != nil { @@ -95,17 +145,18 @@ func testAdapter(f *framework.Framework, kubeClient clientset.Interface, customM } defer CleanupDescriptors(gcmService, projectId) - err = CreateAdapter() + // Both deployments - for old and new resource model - expose External Metrics API. + err = CreateAdapter(AdapterForOldResourceModel) if err != nil { framework.Failf("Failed to set up: %s", err) } - defer CleanupAdapter() + defer CleanupAdapter(AdapterForOldResourceModel) _, err = kubeClient.RbacV1().ClusterRoleBindings().Create(HPAPermissions) defer kubeClient.RbacV1().ClusterRoleBindings().Delete("custom-metrics-reader", &metav1.DeleteOptions{}) // Run application that exports the metric - err = createSDExporterPods(f, kubeClient) + pod, err := createSDExporterPods(f, kubeClient) if err != nil { framework.Failf("Failed to create stackdriver-exporter pod: %s", err) } @@ -116,25 +167,18 @@ func testAdapter(f *framework.Framework, kubeClient clientset.Interface, customM // i.e. pod creation, first time series exported time.Sleep(60 * time.Second) - // Verify responses from Custom Metrics API + verifyResponseFromExternalMetricsAPI(f, externalMetricsClient, pod) +} + +func verifyResponsesFromCustomMetricsAPI(f *framework.Framework, customMetricsClient customclient.CustomMetricsClient, discoveryClient *discovery.DiscoveryClient) { resources, err := discoveryClient.ServerResourcesForGroupVersion("custom.metrics.k8s.io/v1beta1") if err != nil { framework.Failf("Failed to retrieve a list of supported metrics: %s", err) } - gotCustomMetric, gotUnusedMetric := false, false - for _, resource := range resources.APIResources { - if resource.Name == "pods/"+CustomMetricName { - gotCustomMetric = true - } else if resource.Name == "pods/"+UnusedMetricName { - gotUnusedMetric = true - } else { - framework.Failf("Unexpected metric %s. Only metric %s should be supported", resource.Name, CustomMetricName) - } - } - if !gotCustomMetric { + if !containsResource(resources.APIResources, "*/custom.googleapis.com|"+CustomMetricName) { framework.Failf("Metric '%s' expected but not received", CustomMetricName) } - if !gotUnusedMetric { + if !containsResource(resources.APIResources, "*/custom.googleapis.com|"+UnusedMetricName) { framework.Failf("Metric '%s' expected but not received", UnusedMetricName) } value, err := customMetricsClient.NamespacedMetrics(f.Namespace.Name).GetForObject(schema.GroupKind{Group: "", Kind: "Pod"}, stackdriverExporterPod1, CustomMetricName) @@ -160,6 +204,40 @@ func testAdapter(f *framework.Framework, kubeClient clientset.Interface, customM } } +func containsResource(resourcesList []metav1.APIResource, resourceName string) bool { + for _, resource := range resourcesList { + if resource.Name == resourceName { + return true + } + } + return false +} + +func verifyResponseFromExternalMetricsAPI(f *framework.Framework, externalMetricsClient externalclient.ExternalMetricsClient, pod *v1.Pod) { + req1, _ := labels.NewRequirement("resource.type", selection.Equals, []string{"gke_container"}) + // It's important to filter out only metrics from the right namespace, since multiple e2e tests + // may run in the same project concurrently. "dummy" is added to test + req2, _ := labels.NewRequirement("resource.labels.pod_id", selection.In, []string{string(pod.UID), "dummy"}) + req3, _ := labels.NewRequirement("resource.labels.namespace_id", selection.Exists, []string{}) + req4, _ := labels.NewRequirement("resource.labels.zone", selection.NotEquals, []string{"dummy"}) + req5, _ := labels.NewRequirement("resource.labels.cluster_name", selection.NotIn, []string{"foo", "bar"}) + values, err := externalMetricsClient. + NamespacedMetrics("dummy"). + List("custom.googleapis.com|"+CustomMetricName, labels.NewSelector().Add(*req1, *req2, *req3, *req4, *req5)) + if err != nil { + framework.Failf("Failed query: %s", err) + } + if len(values.Items) != 1 { + framework.Failf("Expected exactly one external metric value, but % values received", len(values.Items)) + } + if values.Items[0].MetricName != "custom.googleapis.com|"+CustomMetricName || + values.Items[0].Value.Value() != CustomMetricValue || + // Check one label just to make sure labels are included + values.Items[0].MetricLabels["resource.labels.pod_id"] != string(pod.UID) { + framework.Failf("Unexpected result for metric %s: %v", CustomMetricName, values.Items[0]) + } +} + func cleanupSDExporterPod(f *framework.Framework, cs clientset.Interface) { err := cs.CoreV1().Pods(f.Namespace.Name).Delete(stackdriverExporterPod1, &metav1.DeleteOptions{}) if err != nil { @@ -171,11 +249,11 @@ func cleanupSDExporterPod(f *framework.Framework, cs clientset.Interface) { } } -func createSDExporterPods(f *framework.Framework, cs clientset.Interface) error { - _, err := cs.CoreV1().Pods(f.Namespace.Name).Create(StackdriverExporterPod(stackdriverExporterPod1, f.Namespace.Name, stackdriverExporterLabel, CustomMetricName, CustomMetricValue)) +func createSDExporterPods(f *framework.Framework, cs clientset.Interface) (*v1.Pod, error) { + pod, err := cs.CoreV1().Pods(f.Namespace.Name).Create(StackdriverExporterPod(stackdriverExporterPod1, f.Namespace.Name, stackdriverExporterLabel, CustomMetricName, CustomMetricValue)) if err != nil { - return err + return nil, err } _, err = cs.CoreV1().Pods(f.Namespace.Name).Create(StackdriverExporterPod(stackdriverExporterPod2, f.Namespace.Name, stackdriverExporterLabel, UnusedMetricName, UnusedMetricValue)) - return err + return pod, err } diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/influxdb.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/influxdb.go index 5434a9c39..64ef4002d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/influxdb.go +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/influxdb.go @@ -42,7 +42,7 @@ var _ = instrumentation.SIGDescribe("Monitoring", func() { framework.SkipUnlessClusterMonitoringModeIs("influxdb") }) - It("should verify monitoring pods and all cluster nodes are available on influxdb using heapster.", func() { + It("should verify monitoring pods and all cluster nodes are available on influxdb using heapster [Feature:InfluxdbMonitoring]", func() { testMonitoringUsingHeapsterInfluxdb(f.ClientSet) }) }) diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/prometheus.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/prometheus.go new file mode 100644 index 000000000..5b2d2e1b1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/prometheus.go @@ -0,0 +1,382 @@ +/* +Copyright 2018 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 monitoring + +import ( + "context" + "encoding/json" + "fmt" + "math" + "time" + + "github.com/prometheus/common/model" + + . "github.com/onsi/ginkgo" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/common" + "k8s.io/kubernetes/test/e2e/framework" + instrumentation "k8s.io/kubernetes/test/e2e/instrumentation/common" +) + +const ( + prometheusQueryStep = time.Minute + prometheusMetricErrorTolerance = 0.25 + prometheusMetricValidationDuration = time.Minute * 2 + prometheusRate = time.Minute * 2 + prometheusRequiredNodesUpDuration = time.Minute * 5 + prometheusService = "prometheus" + prometheusSleepBetweenAttempts = time.Second * 30 + prometheusTestTimeout = time.Minute * 5 + customMetricValue = 1000 + targetCPUUsage = 0.1 +) + +var _ = instrumentation.SIGDescribe("[Feature:PrometheusMonitoring] Prometheus", func() { + BeforeEach(func() { + framework.SkipUnlessPrometheusMonitoringIsEnabled() + }) + + f := framework.NewDefaultFramework("prometheus-monitoring") + It("should scrape container metrics from all nodes.", func() { + expectedNodes, err := getAllNodes(f.ClientSet) + framework.ExpectNoError(err) + retryUntilSucceeds(func() error { + return validateMetricAvailableForAllNodes(f.ClientSet, `container_cpu_usage_seconds_total`, expectedNodes) + }, prometheusTestTimeout) + }) + It("should successfully scrape all targets", func() { + retryUntilSucceeds(func() error { + return validateAllActiveTargetsAreHealthy(f.ClientSet) + }, prometheusTestTimeout) + }) + It("should contain correct container CPU metric.", func() { + query := prometheusCPUQuery(f.Namespace.Name, "prometheus-cpu-consumer", prometheusRate) + consumer := consumeCPUResources(f, "prometheus-cpu-consumer", targetCPUUsage*1000) + defer consumer.CleanUp() + retryUntilSucceeds(func() error { + return validateQueryReturnsCorrectValues(f.ClientSet, query, targetCPUUsage, 3, prometheusMetricErrorTolerance) + }, prometheusTestTimeout) + }) + It("should scrape metrics from annotated pods.", func() { + query := prometheusPodCustomMetricQuery(f.Namespace.Name, "prometheus-custom-pod-metric") + consumer := exportCustomMetricFromPod(f, "prometheus-custom-pod-metric", customMetricValue) + defer consumer.CleanUp() + retryUntilSucceeds(func() error { + return validateQueryReturnsCorrectValues(f.ClientSet, query, customMetricValue, 1, prometheusMetricErrorTolerance) + }, prometheusTestTimeout) + }) + It("should scrape metrics from annotated services.", func() { + query := prometheusServiceCustomMetricQuery(f.Namespace.Name, "prometheus-custom-service-metric") + consumer := exportCustomMetricFromService(f, "prometheus-custom-service-metric", customMetricValue) + defer consumer.CleanUp() + retryUntilSucceeds(func() error { + return validateQueryReturnsCorrectValues(f.ClientSet, query, customMetricValue, 1, prometheusMetricErrorTolerance) + }, prometheusTestTimeout) + }) +}) + +func prometheusCPUQuery(namespace, podNamePrefix string, rate time.Duration) string { + return fmt.Sprintf(`sum(irate(container_cpu_usage_seconds_total{namespace="%v",pod_name=~"%v.*",image!=""}[%vm]))`, + namespace, podNamePrefix, int64(rate.Minutes())) +} + +func prometheusServiceCustomMetricQuery(namespace, service string) string { + return fmt.Sprintf(`sum(QPS{kubernetes_namespace="%v",kubernetes_name="%v"})`, namespace, service) +} + +func prometheusPodCustomMetricQuery(namespace, podNamePrefix string) string { + return fmt.Sprintf(`sum(QPS{kubernetes_namespace="%s",kubernetes_pod_name=~"%s.*"})`, namespace, podNamePrefix) +} + +func consumeCPUResources(f *framework.Framework, consumerName string, cpuUsage int) *common.ResourceConsumer { + return common.NewDynamicResourceConsumer(consumerName, f.Namespace.Name, common.KindDeployment, 1, cpuUsage, + memoryUsed, 0, int64(cpuUsage), memoryLimit, f.ClientSet, f.InternalClientset, f.ScalesGetter) +} + +func exportCustomMetricFromPod(f *framework.Framework, consumerName string, metricValue int) *common.ResourceConsumer { + podAnnotations := map[string]string{ + "prometheus.io/scrape": "true", + "prometheus.io/path": "/Metrics", + "prometheus.io/port": "8080", + } + return common.NewMetricExporter(consumerName, f.Namespace.Name, podAnnotations, nil, metricValue, f.ClientSet, f.InternalClientset, f.ScalesGetter) +} + +func exportCustomMetricFromService(f *framework.Framework, consumerName string, metricValue int) *common.ResourceConsumer { + serviceAnnotations := map[string]string{ + "prometheus.io/scrape": "true", + "prometheus.io/path": "/Metrics", + "prometheus.io/port": "8080", + } + return common.NewMetricExporter(consumerName, f.Namespace.Name, nil, serviceAnnotations, metricValue, f.ClientSet, f.InternalClientset, f.ScalesGetter) +} + +func validateMetricAvailableForAllNodes(c clientset.Interface, metric string, expectedNodesNames []string) error { + instanceLabels, err := getInstanceLabelsAvailableForMetric(c, prometheusRequiredNodesUpDuration, metric) + if err != nil { + return err + } + nodesWithMetric := make(map[string]bool) + for _, instance := range instanceLabels { + nodesWithMetric[instance] = true + } + missedNodesCount := 0 + for _, nodeName := range expectedNodesNames { + if _, found := nodesWithMetric[nodeName]; !found { + missedNodesCount++ + } + } + if missedNodesCount > 0 { + return fmt.Errorf("Metric not found for %v out of %v nodes", missedNodesCount, len(expectedNodesNames)) + } + return nil +} + +func validateAllActiveTargetsAreHealthy(c clientset.Interface) error { + discovery, err := fetchPrometheusTargetDiscovery(c) + if err != nil { + return err + } + if len(discovery.ActiveTargets) == 0 { + return fmt.Errorf("Prometheus is not scraping any targets, at least one target is required") + } + for _, target := range discovery.ActiveTargets { + if target.Health != HealthGood { + return fmt.Errorf("Target health not good. Target: %v", target) + } + } + return nil +} + +func validateQueryReturnsCorrectValues(c clientset.Interface, query string, expectedValue float64, minSamplesCount int, errorTolerance float64) error { + samples, err := fetchQueryValues(c, query, prometheusMetricValidationDuration) + if err != nil { + return err + } + if len(samples) < minSamplesCount { + return fmt.Errorf("Not enough samples for query '%v', got %v", query, samples) + } + framework.Logf("Executed query '%v' returned %v", query, samples) + for _, value := range samples { + error := math.Abs(value-expectedValue) / expectedValue + if error >= errorTolerance { + return fmt.Errorf("Query result values outside expected value tolerance. Expected error below %v, got %v", errorTolerance, error) + } + } + return nil +} + +func fetchQueryValues(c clientset.Interface, query string, duration time.Duration) ([]float64, error) { + now := time.Now() + response, err := queryPrometheus(c, query, now.Add(-duration), now, prometheusQueryStep) + if err != nil { + return nil, err + } + m, ok := response.(model.Matrix) + if !ok { + return nil, fmt.Errorf("Expected matric response, got: %T", response) + } + values := make([]float64, 0) + for _, stream := range m { + for _, sample := range stream.Values { + values = append(values, float64(sample.Value)) + } + } + return values, nil +} + +func getInstanceLabelsAvailableForMetric(c clientset.Interface, duration time.Duration, metric string) ([]string, error) { + var instance model.LabelValue + now := time.Now() + query := fmt.Sprintf(`sum(%v)by(instance)`, metric) + result, err := queryPrometheus(c, query, now.Add(-duration), now, prometheusQueryStep) + if err != nil { + return nil, err + } + instanceLabels := make([]string, 0) + m, ok := result.(model.Matrix) + if !ok { + framework.Failf("Expected matrix response for query '%v', got: %T", query, result) + return instanceLabels, nil + } + for _, stream := range m { + if instance, ok = stream.Metric["instance"]; !ok { + continue + } + instanceLabels = append(instanceLabels, string(instance)) + } + return instanceLabels, nil +} + +func fetchPrometheusTargetDiscovery(c clientset.Interface) (TargetDiscovery, error) { + ctx, cancel := context.WithTimeout(context.Background(), framework.SingleCallTimeout) + defer cancel() + + response, err := c.CoreV1().RESTClient().Get(). + Context(ctx). + Namespace("kube-system"). + Resource("services"). + Name(prometheusService+":9090"). + SubResource("proxy"). + Suffix("api", "v1", "targets"). + Do(). + Raw() + var qres promTargetsResponse + if err != nil { + fmt.Printf(string(response)) + return qres.Data, err + } + err = json.Unmarshal(response, &qres) + + return qres.Data, nil +} + +type promTargetsResponse struct { + Status string `json:"status"` + Data TargetDiscovery `json:"data"` +} + +type TargetDiscovery struct { + ActiveTargets []*Target `json:"activeTargets"` + DroppedTargets []*DroppedTarget `json:"droppedTargets"` +} +type Target struct { + DiscoveredLabels map[string]string `json:"discoveredLabels"` + Labels map[string]string `json:"labels"` + + ScrapeURL string `json:"scrapeUrl"` + + LastError string `json:"lastError"` + LastScrape time.Time `json:"lastScrape"` + Health TargetHealth `json:"health"` +} + +type DroppedTarget struct { + // Labels before any processing. + DiscoveredLabels map[string]string `json:"discoveredLabels"` +} + +const ( + HealthUnknown TargetHealth = "unknown" + HealthGood TargetHealth = "up" + HealthBad TargetHealth = "down" +) + +type TargetHealth string + +func queryPrometheus(c clientset.Interface, query string, start, end time.Time, step time.Duration) (model.Value, error) { + ctx, cancel := context.WithTimeout(context.Background(), framework.SingleCallTimeout) + defer cancel() + + response, err := c.CoreV1().RESTClient().Get(). + Context(ctx). + Namespace("kube-system"). + Resource("services"). + Name(prometheusService+":9090"). + SubResource("proxy"). + Suffix("api", "v1", "query_range"). + Param("query", query). + Param("start", fmt.Sprintf("%v", start.Unix())). + Param("end", fmt.Sprintf("%v", end.Unix())). + Param("step", fmt.Sprintf("%vs", step.Seconds())). + Do(). + Raw() + if err != nil { + fmt.Printf(string(response)) + return nil, err + } + var qres promQueryResponse + err = json.Unmarshal(response, &qres) + + return model.Value(qres.Data.v), err +} + +type promQueryResponse struct { + Status string `json:"status"` + Data responseData `json:"data"` +} + +type responseData struct { + Type model.ValueType `json:"resultType"` + Result interface{} `json:"result"` + + // The decoded value. + v model.Value +} + +func (qr *responseData) UnmarshalJSON(b []byte) error { + v := struct { + Type model.ValueType `json:"resultType"` + Result json.RawMessage `json:"result"` + }{} + + err := json.Unmarshal(b, &v) + if err != nil { + return err + } + + switch v.Type { + case model.ValScalar: + var sv model.Scalar + err = json.Unmarshal(v.Result, &sv) + qr.v = &sv + + case model.ValVector: + var vv model.Vector + err = json.Unmarshal(v.Result, &vv) + qr.v = vv + + case model.ValMatrix: + var mv model.Matrix + err = json.Unmarshal(v.Result, &mv) + qr.v = mv + + default: + err = fmt.Errorf("unexpected value type %q", v.Type) + } + return err +} + +func retryUntilSucceeds(validator func() error, timeout time.Duration) { + startTime := time.Now() + var err error + for { + err = validator() + if err == nil { + return + } + if time.Since(startTime) >= timeout { + break + } + framework.Logf(err.Error()) + time.Sleep(prometheusSleepBetweenAttempts) + } + framework.Failf(err.Error()) +} + +func getAllNodes(c clientset.Interface) ([]string, error) { + nodeList, err := c.CoreV1().Nodes().List(metav1.ListOptions{}) + if err != nil { + return nil, err + } + result := []string{} + for _, node := range nodeList.Items { + result = append(result, node.Name) + } + return result, nil +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/stackdriver.go b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/stackdriver.go index c11a92e65..582f31ae0 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/stackdriver.go +++ b/vendor/k8s.io/kubernetes/test/e2e/instrumentation/monitoring/stackdriver.go @@ -101,7 +101,7 @@ func testStackdriverMonitoring(f *framework.Framework, pods, allPodsCPU int, per framework.ExpectNoError(err) - rc := common.NewDynamicResourceConsumer(rcName, f.Namespace.Name, common.KindDeployment, pods, allPodsCPU, memoryUsed, 0, perPodCPU, memoryLimit, f.ClientSet, f.InternalClientset) + rc := common.NewDynamicResourceConsumer(rcName, f.Namespace.Name, common.KindDeployment, pods, allPodsCPU, memoryUsed, 0, perPodCPU, memoryLimit, f.ClientSet, f.InternalClientset, f.ScalesGetter) defer rc.CleanUp() rc.WaitForReplicas(pods, 15*time.Minute) diff --git a/vendor/k8s.io/kubernetes/test/e2e/kubectl/BUILD b/vendor/k8s.io/kubernetes/test/e2e/kubectl/BUILD index 4f80ab3b4..e17d288d6 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/kubectl/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/kubectl/BUILD @@ -15,7 +15,7 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e/kubectl", deps = [ "//pkg/controller:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/polymorphichelpers:go_default_library", "//test/e2e/framework:go_default_library", "//test/e2e/generated:go_default_library", "//test/e2e/scheduling:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e/kubectl/kubectl.go b/vendor/k8s.io/kubernetes/test/e2e/kubectl/kubectl.go index 3a7d702c6..3132d2c11 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/kubectl/kubectl.go +++ b/vendor/k8s.io/kubernetes/test/e2e/kubectl/kubectl.go @@ -58,7 +58,6 @@ import ( genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/generated" "k8s.io/kubernetes/test/e2e/scheduling" @@ -67,6 +66,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" imageutils "k8s.io/kubernetes/test/utils/image" ) @@ -199,7 +199,7 @@ var _ = SIGDescribe("Kubectl alpha client", func() { }) It("should create a CronJob", func() { - framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResourceAlpha, f.Namespace.Name) + framework.SkipIfMissingResource(f.DynamicClient, CronJobGroupVersionResourceAlpha, f.Namespace.Name) schedule := "*/5 * * * ?" framework.RunKubectlOrDie("run", cjName, "--restart=OnFailure", "--generator=cronjob/v2alpha1", @@ -266,6 +266,11 @@ var _ = SIGDescribe("Kubectl client", func() { nautilus = substituteImageName(string(generated.ReadOrDie(filepath.Join(updateDemoRoot, "nautilus-rc.yaml.in")))) kitten = substituteImageName(string(generated.ReadOrDie(filepath.Join(updateDemoRoot, "kitten-rc.yaml.in")))) }) + /* + Release : v1.9 + Testname: Kubectl, replication controller + Description: Create a Pod and a container with a given image. Configure replication controller to run 2 replicas. The number of running instances of the Pod MUST equal the number of replicas set on the replication controller which is 2. + */ framework.ConformanceIt("should create and stop a replication controller ", func() { defer cleanupKubectlInputs(nautilus, ns, updateDemoSelector) @@ -274,6 +279,11 @@ var _ = SIGDescribe("Kubectl client", func() { framework.ValidateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns) }) + /* + Release : v1.9 + Testname: Kubectl, scale replication controller + Description: Create a Pod and a container with a given image. Configure replication controller to run 2 replicas. The number of running instances of the Pod MUST equal the number of replicas set on the replication controller which is 2. Update the replicaset to 1. Number of running instances of the Pod MUST be 1. Update the replicaset to 2. Number of running instances of the Pod MUST be 2. + */ framework.ConformanceIt("should scale a replication controller ", func() { defer cleanupKubectlInputs(nautilus, ns, updateDemoSelector) @@ -288,6 +298,11 @@ var _ = SIGDescribe("Kubectl client", func() { framework.ValidateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns) }) + /* + Release : v1.9 + Testname: Kubectl, rolling update replication controller + Description: Create a Pod and a container with a given image. Configure replication controller to run 2 replicas. The number of running instances of the Pod MUST equal the number of replicas set on the replication controller which is 2. Run a rolling update to run a different version of the container. All running instances SHOULD now be running the newer version of the container as part of the rolling update. + */ framework.ConformanceIt("should do a rolling update of a replication controller ", func() { By("creating the initial replication controller") framework.RunKubectlOrDieInput(string(nautilus[:]), "create", "-f", "-", fmt.Sprintf("--namespace=%v", ns)) @@ -315,6 +330,11 @@ var _ = SIGDescribe("Kubectl client", func() { } } + /* + Release : v1.9 + Testname: Kubectl, guestbook application + Description: Create Guestbook application that contains redis server, 2 instances of redis slave, frontend application, frontend service and redis master service and redis slave service. Using frontend service, the test will write an entry into the guestbook application which will store the entry into the backend redis database. Application flow MUST work as expected and the data written MUST be available to read. + */ framework.ConformanceIt("should create and stop a working application ", func() { defer forEachGBFile(func(contents string) { cleanupKubectlInputs(contents, ns) @@ -485,8 +505,6 @@ var _ = SIGDescribe("Kubectl client", func() { }) It("should support inline execution and attach", func() { - framework.SkipIfContainerRuntimeIs("rkt") // #23335 - nsFlag := fmt.Sprintf("--namespace=%v", ns) By("executing a command with run and attach with stdin") @@ -511,7 +529,7 @@ var _ = SIGDescribe("Kubectl client", func() { ExecOrDie() Expect(runOutput).ToNot(ContainSubstring("stdin closed")) g := func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) } - runTestPod, _, err := util.GetFirstPod(f.InternalClientset.Core(), ns, "run=run-test-3", 1*time.Minute, g) + runTestPod, _, err := polymorphichelpers.GetFirstPod(f.InternalClientset.Core(), ns, "run=run-test-3", 1*time.Minute, g) if err != nil { os.Exit(1) } @@ -679,6 +697,11 @@ metadata: }) framework.KubeDescribe("Kubectl api-versions", func() { + /* + Release : v1.9 + Testname: Kubectl, check version v1 + Description: Run kubectl to get api versions, output MUST contain returned versions with ‘v1’ listed. + */ framework.ConformanceIt("should check if v1 is in available api versions ", func() { By("validating api versions") output := framework.RunKubectlOrDie("api-versions") @@ -770,13 +793,18 @@ metadata: }) framework.KubeDescribe("Kubectl cluster-info", func() { + /* + Release : v1.9 + Testname: Kubectl, cluster info + Description: Call kubectl to get cluster-info, output MUST contain cluster-info returned and Kubernetes Master SHOULD be running. + */ framework.ConformanceIt("should check if Kubernetes master services is included in cluster-info ", func() { By("validating cluster-info") output := framework.RunKubectlOrDie("cluster-info") // Can't check exact strings due to terminal control commands (colors) requiredItems := []string{"Kubernetes master", "is running at"} if framework.ProviderIs("gce", "gke") { - requiredItems = append(requiredItems, "KubeDNS", "Heapster") + requiredItems = append(requiredItems, "Heapster") } for _, item := range requiredItems { if !strings.Contains(output, item) { @@ -787,6 +815,11 @@ metadata: }) framework.KubeDescribe("Kubectl describe", func() { + /* + Release : v1.9 + Testname: Kubectl, describe pod or rc + Description: Deploy a redis controller and a redis service. Kubectl describe pods SHOULD return the name, namespace, labels, state and other information as expected. Kubectl describe on rc, service, node and namespace SHOULD also return proper information. + */ framework.ConformanceIt("should check if kubectl describe prints relevant information for rc and pods ", func() { kv, err := framework.KubectlVersion() Expect(err).NotTo(HaveOccurred()) @@ -890,6 +923,11 @@ metadata: }) framework.KubeDescribe("Kubectl expose", func() { + /* + Release : v1.9 + Testname: Kubectl, create service, replication controller + Description: Create a Pod running redis master listening to port 6379. Using kubectl expose the redis master replication controllers at port 1234. Validate that the replication controller is listening on port 1234 and the target port is set to 6379, port that redis master is listening. Using kubectl expose the redis master as a service at port 2345. The service MUST be listening on port 2345 and the target port is set to 6379, port that redis master is listening. + */ framework.ConformanceIt("should create services for rc ", func() { controllerJson := substituteImageName(string(readTestFileOrDie(redisControllerFilename))) nsFlag := fmt.Sprintf("--namespace=%v", ns) @@ -981,6 +1019,11 @@ metadata: cleanupKubectlInputs(podYaml, ns, pausePodSelector) }) + /* + Release : v1.9 + Testname: Kubectl, label update + Description: When a Pod is running, update a Label using ‘kubectl label’ command. The label MUST be created in the Pod. A ‘kubectl get pod’ with -l option on the container MUST verify that the label can be read back. Use ‘kubectl label label-’ to remove the label. Kubetctl get pod’ with -l option SHOULD no list the deleted label as the label is removed. + */ framework.ConformanceIt("should update the label on a resource ", func() { labelName := "testing-label" labelValue := "testing-label-value" @@ -1016,6 +1059,17 @@ metadata: cleanupKubectlInputs(rc, ns, simplePodSelector) }) + /* + Release : v1.9 + Testname: Kubectl, logs + Description: When a Pod is running then it MUST generate logs. + Starting a Pod should have a log line indicating the the server is running and ready to accept connections. Also log command options MUST work as expected and described below. + ‘kubectl log -tail=1’ should generate a output of one line, the last line in the log. + ‘kubectl --limit-bytes=1’ should generate a single byte output. + ‘kubectl --tail=1 --timestamp should genrate one line with timestamp in RFC3339 format + ‘kubectl --since=1s’ should output logs that are only 1 second older from now + ‘kubectl --since=24h’ should output logs that are only 1 day older from now + */ framework.ConformanceIt("should be able to retrieve and filter logs ", func() { // Split("something\n", "\n") returns ["something", ""], so // strip trailing newline first @@ -1067,6 +1121,11 @@ metadata: }) framework.KubeDescribe("Kubectl patch", func() { + /* + Release : v1.9 + Testname: Kubectl, patch to annotate + Description: Start running a redis master and a replication controller. When the pod is running, using ‘kubectl patch’ command add annotations. The annotation MUST be added to running pods and SHOULD be able to read added annotations from each of the Pods running under the replication controller. + */ framework.ConformanceIt("should add annotations for pods in rc ", func() { controllerJson := substituteImageName(string(readTestFileOrDie(redisControllerFilename))) nsFlag := fmt.Sprintf("--namespace=%v", ns) @@ -1096,6 +1155,11 @@ metadata: }) framework.KubeDescribe("Kubectl version", func() { + /* + Release : v1.9 + Testname: Kubectl, version + Description: The command ‘kubectl version’ MUST return the major, minor versions, GitCommit, etc of the the Client and the Server that the kubectl is configured to connect to. + */ framework.ConformanceIt("should check is all data is printed ", func() { version := framework.RunKubectlOrDie("version") requiredItems := []string{"Client Version:", "Server Version:", "Major:", "Minor:", "GitCommit:"} @@ -1123,6 +1187,11 @@ metadata: cleanUp() }) + /* + Release : v1.9 + Testname: Kubectl, run default + Description: Command ‘kubectl run’ MUST create a running pod with possible replicas given a image using the option --image=’nginx’. The running Pod SHOULD have one container and the container SHOULD be running the image specified in the ‘run’ command. + */ framework.ConformanceIt("should create an rc or deployment from an image ", func() { By("running the image " + nginxImage) framework.RunKubectlOrDie("run", name, "--image="+nginxImage, nsFlag) @@ -1153,6 +1222,11 @@ metadata: framework.RunKubectlOrDie("delete", "rc", rcName, nsFlag) }) + /* + Release : v1.9 + Testname: Kubectl, run rc + Description: Command ‘kubectl run’ MUST create a running rc with default one replicas given a image using the option --image=’nginx’. The running replication controller SHOULD have one container and the container SHOULD be running the image specified in the ‘run’ command. Also there MUST be 1 pod controlled by this replica set running 1 container with the image specified. A ‘kubetctl logs’ command MUST return the logs from the container in the replication controller. + */ framework.ConformanceIt("should create an rc from an image ", func() { By("running the image " + nginxImage) framework.RunKubectlOrDie("run", rcName, "--image="+nginxImage, "--generator=run/v1", nsFlag) @@ -1209,6 +1283,11 @@ metadata: framework.RunKubectlOrDie("delete", "rc", rcName, nsFlag) }) + /* + Release : v1.9 + Testname: Kubectl, rolling update + Description: Command ‘kubectl rolling-update’ MUST replace the specified replication controller with a new replication controller by updating one pod at a time to use the new Pod spec. + */ framework.ConformanceIt("should support rolling-update to same image ", func() { By("running the image " + nginxImage) framework.RunKubectlOrDie("run", rcName, "--image="+nginxImage, "--generator=run/v1", nsFlag) @@ -1253,6 +1332,11 @@ metadata: Expect(err).NotTo(HaveOccurred()) }) + /* + Release : v1.9 + Testname: Kubectl, run deployment + Description: Command ‘kubectl run’ MUST create a job, with --generator=deployment, when a image name is specified in the run command. After the run command there SHOULD be a deployment that should exist with one container running the specified image. Also there SHOULD be a Pod that is controlled by this deployment, with a container running the specified image. + */ framework.ConformanceIt("should create a deployment from an image ", func() { By("running the image " + nginxImage) framework.RunKubectlOrDie("run", dName, "--image="+nginxImage, "--generator=deployment/v1beta1", nsFlag) @@ -1293,6 +1377,11 @@ metadata: framework.RunKubectlOrDie("delete", "jobs", jobName, nsFlag) }) + /* + Release : v1.9 + Testname: Kubectl, run job + Description: Command ‘kubectl run’ MUST create a deployment, with --generator=job, when a image name is specified in the run command. After the run command there SHOULD be a job that should exist with one container running the specified image. Also there SHOULD be a restart policy on the job spec that SHOULD match the command line. + */ framework.ConformanceIt("should create a job from an image when restart is OnFailure ", func() { By("running the image " + nginxImage) framework.RunKubectlOrDie("run", jobName, "--restart=OnFailure", "--generator=job/v1", "--image="+nginxImage, nsFlag) @@ -1325,7 +1414,7 @@ metadata: }) It("should create a CronJob", func() { - framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResourceBeta, f.Namespace.Name) + framework.SkipIfMissingResource(f.DynamicClient, CronJobGroupVersionResourceBeta, f.Namespace.Name) schedule := "*/5 * * * ?" framework.RunKubectlOrDie("run", cjName, "--restart=OnFailure", "--generator=cronjob/v1beta1", @@ -1361,6 +1450,11 @@ metadata: framework.RunKubectlOrDie("delete", "pods", podName, nsFlag) }) + /* + Release : v1.9 + Testname: Kubectl, run pod + Description: Command ‘kubectl run’ MUST create a pod, with --generator=run-pod, when a image name is specified in the run command. After the run command there SHOULD be a pod that should exist with one container running the specified image. + */ framework.ConformanceIt("should create a pod from an image when restart is Never ", func() { By("running the image " + nginxImage) framework.RunKubectlOrDie("run", podName, "--restart=Never", "--generator=run-pod/v1", "--image="+nginxImage, nsFlag) @@ -1392,6 +1486,11 @@ metadata: framework.RunKubectlOrDie("delete", "pods", podName, nsFlag) }) + /* + Release : v1.9 + Testname: Kubectl, replace + Description: Command ‘kubectl replace’ on a existing Pod with a new spec MUST update the image of the container running in the Pod. A -f option to ‘kubectl replace’ SHOULD force to re-create the resource. The new Pod SHOULD have the container with new change to the image. + */ framework.ConformanceIt("should update a single-container pod's image ", func() { By("running the image " + nginxImage) framework.RunKubectlOrDie("run", podName, "--generator=run-pod/v1", "--image="+nginxImage, "--labels=run="+podName, nsFlag) @@ -1428,12 +1527,14 @@ metadata: framework.KubeDescribe("Kubectl run --rm job", func() { jobName := "e2e-test-rm-busybox-job" + /* + Release : v1.9 + Testname: Kubectl, run job with --rm + Description: Start a job with a Pod using ‘kubectl run’ but specify --rm=true. Wait for the Pod to start running by verifying that there is output as expected. Now verify that the job has exited and cannot be found. With --rm=true option the job MUST start by running the image specified and then get deleted itself. + */ framework.ConformanceIt("should create a job from an image, then delete the job ", func() { nsFlag := fmt.Sprintf("--namespace=%v", ns) - // The rkt runtime doesn't support attach, see #23335 - framework.SkipIfContainerRuntimeIs("rkt") - By("executing a command with run --rm and attach with stdin") t := time.NewTimer(runJobTimeout) defer t.Stop() @@ -1456,6 +1557,11 @@ metadata: framework.KubeDescribe("Proxy server", func() { // TODO: test proxy options (static, prefix, etc) + /* + Release : v1.9 + Testname: Kubectl, proxy port zero + Description: Start a proxy server on port zero by running ‘kubectl proxy’ with --port=0. Call the proxy server by requesting api versions from unix socket. The proxy server MUST provide at least one version string. + */ framework.ConformanceIt("should support proxy with --port 0 ", func() { By("starting the proxy server") port, cmd, err := startProxyServer() @@ -1476,6 +1582,11 @@ metadata: } }) + /* + Release : v1.9 + Testname: Kubectl, proxy socket + Description: Start a proxy server on by running ‘kubectl proxy’ with --unix-socket=. Call the proxy server by requesting api versions from http://locahost:0/api. The proxy server MUST provide atleast one version string + */ framework.ConformanceIt("should support --unix-socket=/path ", func() { By("Starting the proxy") tmpdir, err := ioutil.TempDir("", "kubectl-proxy-unix") @@ -1760,11 +1871,12 @@ func startProxyServer() (int, *exec.Cmd, error) { } func curlUnix(url string, path string) (string, error) { - dial := func(proto, addr string) (net.Conn, error) { - return net.Dial("unix", path) + dial := func(ctx context.Context, proto, addr string) (net.Conn, error) { + var d net.Dialer + return d.DialContext(ctx, "unix", path) } transport := utilnet.SetTransportDefaults(&http.Transport{ - Dial: dial, + DialContext: dial, }) return curlTransport(url, transport) } diff --git a/vendor/k8s.io/kubernetes/test/e2e/lifecycle/cluster_upgrade.go b/vendor/k8s.io/kubernetes/test/e2e/lifecycle/cluster_upgrade.go index d70a62d67..c82c7e011 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/lifecycle/cluster_upgrade.go +++ b/vendor/k8s.io/kubernetes/test/e2e/lifecycle/cluster_upgrade.go @@ -54,6 +54,10 @@ var upgradeTests = []upgrades.Test{ &upgrades.AppArmorUpgradeTest{}, } +var gpuUpgradeTests = []upgrades.Test{ + &upgrades.NvidiaGPUUpgradeTest{}, +} + var statefulsetUpgradeTests = []upgrades.Test{ &upgrades.MySqlUpgradeTest{}, &upgrades.EtcdUpgradeTest{}, @@ -256,6 +260,72 @@ var _ = SIGDescribe("ingress Downgrade [Feature:IngressDowngrade]", func() { }) }) +var _ = SIGDescribe("gpu Upgrade [Feature:GPUUpgrade]", func() { + f := framework.NewDefaultFramework("gpu-upgrade") + + // Create the frameworks here because we can only create them + // in a "Describe". + testFrameworks := createUpgradeFrameworks(gpuUpgradeTests) + Describe("master upgrade", func() { + It("should NOT disrupt gpu pod [Feature:GPUMasterUpgrade]", func() { + upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), framework.TestContext.UpgradeTarget) + framework.ExpectNoError(err) + + testSuite := &junit.TestSuite{Name: "GPU master upgrade"} + gpuUpgradeTest := &junit.TestCase{Name: "[sig-node] gpu-master-upgrade", Classname: "upgrade_tests"} + testSuite.TestCases = append(testSuite.TestCases, gpuUpgradeTest) + upgradeFunc := func() { + start := time.Now() + defer finalizeUpgradeTest(start, gpuUpgradeTest) + target := upgCtx.Versions[1].Version.String() + framework.ExpectNoError(framework.MasterUpgrade(target)) + framework.ExpectNoError(framework.CheckMasterVersion(f.ClientSet, target)) + } + runUpgradeSuite(f, gpuUpgradeTests, testFrameworks, testSuite, upgCtx, upgrades.MasterUpgrade, upgradeFunc) + }) + }) + Describe("cluster upgrade", func() { + It("should be able to run gpu pod after upgrade [Feature:GPUClusterUpgrade]", func() { + upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), framework.TestContext.UpgradeTarget) + framework.ExpectNoError(err) + + testSuite := &junit.TestSuite{Name: "GPU cluster upgrade"} + gpuUpgradeTest := &junit.TestCase{Name: "[sig-node] gpu-cluster-upgrade", Classname: "upgrade_tests"} + testSuite.TestCases = append(testSuite.TestCases, gpuUpgradeTest) + upgradeFunc := func() { + start := time.Now() + defer finalizeUpgradeTest(start, gpuUpgradeTest) + target := upgCtx.Versions[1].Version.String() + framework.ExpectNoError(framework.MasterUpgrade(target)) + framework.ExpectNoError(framework.CheckMasterVersion(f.ClientSet, target)) + framework.ExpectNoError(framework.NodeUpgrade(f, target, framework.TestContext.UpgradeImage)) + framework.ExpectNoError(framework.CheckNodesVersions(f.ClientSet, target)) + } + runUpgradeSuite(f, gpuUpgradeTests, testFrameworks, testSuite, upgCtx, upgrades.ClusterUpgrade, upgradeFunc) + }) + }) + Describe("cluster downgrade", func() { + It("should be able to run gpu pod after downgrade [Feature:GPUClusterDowngrade]", func() { + upgCtx, err := getUpgradeContext(f.ClientSet.Discovery(), framework.TestContext.UpgradeTarget) + framework.ExpectNoError(err) + + testSuite := &junit.TestSuite{Name: "GPU cluster downgrade"} + gpuDowngradeTest := &junit.TestCase{Name: "[sig-node] gpu-cluster-downgrade", Classname: "upgrade_tests"} + testSuite.TestCases = append(testSuite.TestCases, gpuDowngradeTest) + upgradeFunc := func() { + start := time.Now() + defer finalizeUpgradeTest(start, gpuDowngradeTest) + target := upgCtx.Versions[1].Version.String() + framework.ExpectNoError(framework.NodeUpgrade(f, target, framework.TestContext.UpgradeImage)) + framework.ExpectNoError(framework.CheckNodesVersions(f.ClientSet, target)) + framework.ExpectNoError(framework.MasterUpgrade(target)) + framework.ExpectNoError(framework.CheckMasterVersion(f.ClientSet, target)) + } + runUpgradeSuite(f, gpuUpgradeTests, testFrameworks, testSuite, upgCtx, upgrades.ClusterUpgrade, upgradeFunc) + }) + }) +}) + var _ = Describe("[sig-apps] stateful Upgrade [Feature:StatefulUpgrade]", func() { f := framework.NewDefaultFramework("stateful-upgrade") diff --git a/vendor/k8s.io/kubernetes/test/e2e/lifecycle/ha_master.go b/vendor/k8s.io/kubernetes/test/e2e/lifecycle/ha_master.go index a9912d5f8..de58b26e8 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/lifecycle/ha_master.go +++ b/vendor/k8s.io/kubernetes/test/e2e/lifecycle/ha_master.go @@ -78,7 +78,7 @@ func createNewRC(c clientset.Interface, ns string, name string) { } func findRegionForZone(zone string) string { - region, err := exec.Command("gcloud", "compute", "zones", "list", zone, "--quiet", "--format=csv[no-heading](region)").CombinedOutput() + region, err := exec.Command("gcloud", "compute", "zones", "list", zone, "--quiet", "--format=csv[no-heading](region)").Output() framework.ExpectNoError(err) if string(region) == "" { framework.Failf("Region not found; zone: %s", zone) @@ -88,7 +88,7 @@ func findRegionForZone(zone string) string { func findZonesForRegion(region string) []string { output, err := exec.Command("gcloud", "compute", "zones", "list", "--filter=region="+region, - "--quiet", "--format=csv[no-heading](name)").CombinedOutput() + "--quiet", "--format=csv[no-heading](name)").Output() framework.ExpectNoError(err) zones := strings.Split(string(output), "\n") return zones diff --git a/vendor/k8s.io/kubernetes/test/e2e/lifecycle/resize_nodes.go b/vendor/k8s.io/kubernetes/test/e2e/lifecycle/resize_nodes.go index 21dcbe1d7..fe03db808 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/lifecycle/resize_nodes.go +++ b/vendor/k8s.io/kubernetes/test/e2e/lifecycle/resize_nodes.go @@ -30,8 +30,6 @@ import ( . "github.com/onsi/gomega" ) -const resizeNodeReadyTimeout = 2 * time.Minute - func resizeRC(c clientset.Interface, ns, name string, replicas int32) error { rc, err := c.CoreV1().ReplicationControllers(ns).Get(name, metav1.GetOptions{}) if err != nil { diff --git a/vendor/k8s.io/kubernetes/test/e2e/manifest/manifest.go b/vendor/k8s.io/kubernetes/test/e2e/manifest/manifest.go index 1bd78e327..bc7d111e8 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/manifest/manifest.go +++ b/vendor/k8s.io/kubernetes/test/e2e/manifest/manifest.go @@ -125,3 +125,20 @@ func StatefulSetFromManifest(fileName, ns string) (*apps.StatefulSet, error) { } return &ss, nil } + +// DaemonSetFromManifest returns a DaemonSet from a manifest stored in fileName in the Namespace indicated by ns. +func DaemonSetFromManifest(fileName, ns string) (*apps.DaemonSet, error) { + var ds apps.DaemonSet + data := generated.ReadOrDie(fileName) + + json, err := utilyaml.ToJSON(data) + if err != nil { + return nil, err + } + err = runtime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), json, &ds) + if err != nil { + return nil, err + } + ds.Namespace = ns + return &ds, nil +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/BUILD b/vendor/k8s.io/kubernetes/test/e2e/network/BUILD index cd32ee5cb..ac6ae0df0 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/network/BUILD @@ -11,6 +11,7 @@ go_library( "dns.go", "dns_common.go", "dns_configmap.go", + "dns_scale_records.go", "doc.go", "example_cluster_dns.go", "firewall.go", @@ -31,7 +32,6 @@ go_library( ], importpath = "k8s.io/kubernetes/test/e2e/network", deps = [ - "//pkg/api/testapi:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/cloudprovider:go_default_library", @@ -40,7 +40,6 @@ go_library( "//pkg/controller/endpoint:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/master/ports:go_default_library", - "//pkg/util/version:go_default_library", "//test/e2e/framework:go_default_library", "//test/e2e/manifest:go_default_library", "//test/e2e/network/scale:go_default_library", @@ -72,6 +71,7 @@ go_library( "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", + "//vendor/k8s.io/client-go/util/workqueue:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/dns.go b/vendor/k8s.io/kubernetes/test/e2e/network/dns.go index 7f41ced62..a6ffc7f47 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/dns.go +++ b/vendor/k8s.io/kubernetes/test/e2e/network/dns.go @@ -318,4 +318,5 @@ var _ = SIGDescribe("DNS", func() { // TODO: Add more test cases for other DNSPolicies. }) + }) diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/dns_common.go b/vendor/k8s.io/kubernetes/test/e2e/network/dns_common.go index 1400f42e0..d4696319f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/dns_common.go +++ b/vendor/k8s.io/kubernetes/test/e2e/network/dns_common.go @@ -31,7 +31,6 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/e2e/framework" imageutils "k8s.io/kubernetes/test/utils/image" @@ -56,9 +55,8 @@ type dnsTestCommon struct { func newDnsTestCommon() dnsTestCommon { return dnsTestCommon{ - f: framework.NewDefaultFramework("dns-config-map"), - ns: "kube-system", - name: "kube-dns", + f: framework.NewDefaultFramework("dns-config-map"), + ns: "kube-system", } } @@ -73,6 +71,12 @@ func (t *dnsTestCommon) init() { t.dnsPod = &pods.Items[0] framework.Logf("Using DNS pod: %v", t.dnsPod.Name) + + if strings.Contains(t.dnsPod.Name, "coredns") { + t.name = "coredns" + } else { + t.name = "kube-dns" + } } func (t *dnsTestCommon) checkDNSRecord(name string, predicate func([]string) bool, timeout time.Duration) { @@ -103,13 +107,18 @@ func (t *dnsTestCommon) checkDNSRecordFrom(name string, predicate func([]string) func (t *dnsTestCommon) runDig(dnsName, target string) []string { cmd := []string{"/usr/bin/dig", "+short"} switch target { + case "coredns": + cmd = append(cmd, "@"+t.dnsPod.Status.PodIP) case "kube-dns": cmd = append(cmd, "@"+t.dnsPod.Status.PodIP, "-p", "10053") - case "dnsmasq": + case "cluster-dns": break default: panic(fmt.Errorf("invalid target: " + target)) } + if strings.HasSuffix(dnsName, "in-addr.arpa") || strings.HasSuffix(dnsName, "in-addr.arpa.") { + cmd = append(cmd, []string{"-t", "ptr"}...) + } cmd = append(cmd, dnsName) stdout, stderr, err := t.f.ExecWithOptions(framework.ExecOptions{ @@ -159,6 +168,24 @@ func (t *dnsTestCommon) setConfigMap(cm *v1.ConfigMap) { } } +func (t *dnsTestCommon) fetchDNSConfigMapData() map[string]string { + if t.name == "coredns" { + pcm, err := t.c.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(t.name, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + return pcm.Data + } + return nil +} + +func (t *dnsTestCommon) restoreDNSConfigMap(configMapData map[string]string) { + if t.name == "coredns" { + t.setConfigMap(&v1.ConfigMap{Data: configMapData}) + t.deleteCoreDNSPods() + } else { + t.c.CoreV1().ConfigMaps(t.ns).Delete(t.name, nil) + } +} + func (t *dnsTestCommon) deleteConfigMap() { By(fmt.Sprintf("Deleting the ConfigMap (%s:%s)", t.ns, t.name)) t.cm = nil @@ -166,7 +193,7 @@ func (t *dnsTestCommon) deleteConfigMap() { Expect(err).NotTo(HaveOccurred()) } -func (t *dnsTestCommon) createUtilPod() { +func (t *dnsTestCommon) createUtilPodLabel(baseName string) { // Actual port # doesn't matter, just needs to exist. const servicePort = 10101 @@ -176,8 +203,8 @@ func (t *dnsTestCommon) createUtilPod() { }, ObjectMeta: metav1.ObjectMeta{ Namespace: t.f.Namespace.Name, - Labels: map[string]string{"app": "e2e-dns-configmap"}, - GenerateName: "e2e-dns-configmap-", + Labels: map[string]string{"app": baseName}, + GenerateName: baseName + "-", }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -205,10 +232,10 @@ func (t *dnsTestCommon) createUtilPod() { }, ObjectMeta: metav1.ObjectMeta{ Namespace: t.f.Namespace.Name, - Name: "e2e-dns-configmap", + Name: baseName, }, Spec: v1.ServiceSpec{ - Selector: map[string]string{"app": "e2e-dns-configmap"}, + Selector: map[string]string{"app": baseName}, Ports: []v1.ServicePort{ { Protocol: "TCP", @@ -232,6 +259,21 @@ func (t *dnsTestCommon) deleteUtilPod() { } } +// deleteCoreDNSPods manually deletes the CoreDNS pods to apply the changes to the ConfigMap. +func (t *dnsTestCommon) deleteCoreDNSPods() { + + label := labels.SelectorFromSet(labels.Set(map[string]string{"k8s-app": "kube-dns"})) + options := metav1.ListOptions{LabelSelector: label.String()} + + pods, err := t.f.ClientSet.CoreV1().Pods("kube-system").List(options) + podClient := t.c.CoreV1().Pods(metav1.NamespaceSystem) + + for _, pod := range pods.Items { + err = podClient.Delete(pod.Name, metav1.NewDeleteOptions(0)) + Expect(err).NotTo(HaveOccurred()) + } +} + func generateDNSServerPod(aRecords map[string]string) *v1.Pod { pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ @@ -266,8 +308,8 @@ func generateDNSServerPod(aRecords map[string]string) *v1.Pod { return pod } -func (t *dnsTestCommon) createDNSServer(aRecords map[string]string) { - t.dnsServerPod = generateDNSServerPod(aRecords) +func (t *dnsTestCommon) createDNSPodFromObj(pod *v1.Pod) { + t.dnsServerPod = pod var err error t.dnsServerPod, err = t.c.CoreV1().Pods(t.f.Namespace.Name).Create(t.dnsServerPod) @@ -280,6 +322,40 @@ func (t *dnsTestCommon) createDNSServer(aRecords map[string]string) { Expect(err).NotTo(HaveOccurred()) } +func (t *dnsTestCommon) createDNSServer(aRecords map[string]string) { + t.createDNSPodFromObj(generateDNSServerPod(aRecords)) +} + +func (t *dnsTestCommon) createDNSServerWithPtrRecord() { + pod := &v1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + }, + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "e2e-dns-configmap-dns-server-", + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "dns", + Image: imageutils.GetE2EImage(imageutils.DNSMasq), + Command: []string{ + "/usr/sbin/dnsmasq", + "-u", "root", + "-k", + "--log-facility", "-", + "--host-record=my.test,192.0.2.123", + "-q", + }, + }, + }, + DNSPolicy: "Default", + }, + } + + t.createDNSPodFromObj(pod) +} + func (t *dnsTestCommon) deleteDNSServerPod() { podClient := t.c.CoreV1().Pods(t.f.Namespace.Name) if err := podClient.Delete(t.dnsServerPod.Name, metav1.NewDeleteOptions(0)); err != nil { @@ -292,7 +368,7 @@ func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd, podHostName, servic dnsPod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: "dns-test-" + string(uuid.NewUUID()), diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/dns_configmap.go b/vendor/k8s.io/kubernetes/test/e2e/network/dns_configmap.go index 3e11edc08..c067fc22a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/dns_configmap.go +++ b/vendor/k8s.io/kubernetes/test/e2e/network/dns_configmap.go @@ -22,6 +22,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" ) @@ -33,11 +34,19 @@ type dnsFederationsConfigMapTest struct { isValid bool } +var ( + googleDnsHostname = "google-public-dns-a.google.com" + // The ConfigMap update mechanism takes longer than the standard + // wait.ForeverTestTimeout. + moreForeverTestTimeout = 2 * 60 * time.Second +) + var _ = SIGDescribe("DNS configMap federations", func() { + t := &dnsNameserverTest{dnsTestCommon: newDnsTestCommon()} - BeforeEach(func() { t.c = t.f.ClientSet }) It("should be able to change federation configuration [Slow][Serial]", func() { + t.c = t.f.ClientSet t.run() }) }) @@ -46,7 +55,7 @@ func (t *dnsFederationsConfigMapTest) run() { t.init() defer t.c.CoreV1().ConfigMaps(t.ns).Delete(t.name, nil) - t.createUtilPod() + t.createUtilPodLabel("e2e-dns-configmap") defer t.deleteUtilPod() t.validate() @@ -140,8 +149,10 @@ type dnsNameserverTest struct { func (t *dnsNameserverTest) run() { t.init() - t.createUtilPod() + t.createUtilPodLabel("e2e-dns-configmap") defer t.deleteUtilPod() + originalConfigMapData := t.fetchDNSConfigMapData() + defer t.restoreDNSConfigMap(originalConfigMapData) t.createDNSServer(map[string]string{ "abc.acme.local": "1.1.1.1", @@ -150,46 +161,210 @@ func (t *dnsNameserverTest) run() { }) defer t.deleteDNSServerPod() - t.setConfigMap(&v1.ConfigMap{Data: map[string]string{ - "stubDomains": fmt.Sprintf(`{"acme.local":["%v"]}`, t.dnsServerPod.Status.PodIP), - "upstreamNameservers": fmt.Sprintf(`["%v"]`, t.dnsServerPod.Status.PodIP), - }}) - - // The ConfigMap update mechanism takes longer than the standard - // wait.ForeverTestTimeout. - moreForeverTestTimeout := 2 * 60 * time.Second + if t.name == "coredns" { + t.setConfigMap(&v1.ConfigMap{Data: map[string]string{ + "Corefile": fmt.Sprintf(`.:53 { + kubernetes cluster.local in-addr.arpa ip6.arpa { + pods insecure + upstream + fallthrough in-addr.arpa ip6.arpa + } + proxy . %v + } + acme.local:53 { + proxy . %v + }`, t.dnsServerPod.Status.PodIP, t.dnsServerPod.Status.PodIP), + }}) + + t.deleteCoreDNSPods() + } else { + t.setConfigMap(&v1.ConfigMap{Data: map[string]string{ + "stubDomains": fmt.Sprintf(`{"acme.local":["%v"]}`, t.dnsServerPod.Status.PodIP), + "upstreamNameservers": fmt.Sprintf(`["%v"]`, t.dnsServerPod.Status.PodIP), + }}) + } t.checkDNSRecordFrom( "abc.acme.local", func(actual []string) bool { return len(actual) == 1 && actual[0] == "1.1.1.1" }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) t.checkDNSRecordFrom( "def.acme.local", func(actual []string) bool { return len(actual) == 1 && actual[0] == "2.2.2.2" }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) t.checkDNSRecordFrom( "widget.local", func(actual []string) bool { return len(actual) == 1 && actual[0] == "3.3.3.3" }, - "dnsmasq", + "cluster-dns", moreForeverTestTimeout) - t.c.CoreV1().ConfigMaps(t.ns).Delete(t.name, nil) + t.restoreDNSConfigMap(originalConfigMapData) // Wait for the deleted ConfigMap to take effect, otherwise the // configuration can bleed into other tests. t.checkDNSRecordFrom( "abc.acme.local", func(actual []string) bool { return len(actual) == 0 }, - "dnsmasq", + "cluster-dns", + moreForeverTestTimeout) +} + +type dnsPtrFwdTest struct { + dnsTestCommon +} + +func (t *dnsPtrFwdTest) run() { + t.init() + + t.createUtilPodLabel("e2e-dns-configmap") + defer t.deleteUtilPod() + originalConfigMapData := t.fetchDNSConfigMapData() + defer t.restoreDNSConfigMap(originalConfigMapData) + + t.createDNSServerWithPtrRecord() + defer t.deleteDNSServerPod() + + // Should still be able to lookup public nameserver without explicit upstream nameserver set. + t.checkDNSRecordFrom( + "8.8.8.8.in-addr.arpa", + func(actual []string) bool { return len(actual) == 1 && actual[0] == googleDnsHostname+"." }, + "cluster-dns", + moreForeverTestTimeout) + + if t.name == "coredns" { + t.setConfigMap(&v1.ConfigMap{Data: map[string]string{ + "Corefile": fmt.Sprintf(`.:53 { + kubernetes cluster.local in-addr.arpa ip6.arpa { + pods insecure + upstream + fallthrough in-addr.arpa ip6.arpa + } + proxy . %v + }`, t.dnsServerPod.Status.PodIP), + }}) + + t.deleteCoreDNSPods() + } else { + t.setConfigMap(&v1.ConfigMap{Data: map[string]string{ + "upstreamNameservers": fmt.Sprintf(`["%v"]`, t.dnsServerPod.Status.PodIP), + }}) + } + + t.checkDNSRecordFrom( + "123.2.0.192.in-addr.arpa", + func(actual []string) bool { return len(actual) == 1 && actual[0] == "my.test." }, + "cluster-dns", + moreForeverTestTimeout) + + t.restoreDNSConfigMap(originalConfigMapData) + t.checkDNSRecordFrom( + "123.2.0.192.in-addr.arpa", + func(actual []string) bool { return len(actual) == 0 }, + "cluster-dns", moreForeverTestTimeout) } +type dnsExternalNameTest struct { + dnsTestCommon +} + +func (t *dnsExternalNameTest) run() { + t.init() + + t.createUtilPodLabel("e2e-dns-configmap") + defer t.deleteUtilPod() + originalConfigMapData := t.fetchDNSConfigMapData() + defer t.restoreDNSConfigMap(originalConfigMapData) + + fooHostname := "foo.example.com" + t.createDNSServer(map[string]string{ + fooHostname: "192.0.2.123", + }) + defer t.deleteDNSServerPod() + + f := t.f + serviceName := "dns-externalname-upstream-test" + externalNameService := framework.CreateServiceSpec(serviceName, googleDnsHostname, false, nil) + if _, err := f.ClientSet.CoreV1().Services(f.Namespace.Name).Create(externalNameService); err != nil { + Fail(fmt.Sprintf("Failed when creating service: %v", err)) + } + serviceNameLocal := "dns-externalname-upstream-local" + externalNameServiceLocal := framework.CreateServiceSpec(serviceNameLocal, fooHostname, false, nil) + if _, err := f.ClientSet.CoreV1().Services(f.Namespace.Name).Create(externalNameServiceLocal); err != nil { + Fail(fmt.Sprintf("Failed when creating service: %v", err)) + } + defer func() { + By("deleting the test externalName service") + defer GinkgoRecover() + f.ClientSet.CoreV1().Services(f.Namespace.Name).Delete(externalNameService.Name, nil) + f.ClientSet.CoreV1().Services(f.Namespace.Name).Delete(externalNameServiceLocal.Name, nil) + }() + + t.checkDNSRecordFrom( + fmt.Sprintf("%s.%s.svc.cluster.local", serviceName, f.Namespace.Name), + func(actual []string) bool { + return len(actual) >= 1 && actual[0] == googleDnsHostname+"." + }, + "cluster-dns", + moreForeverTestTimeout) + + if t.name == "coredns" { + t.setConfigMap(&v1.ConfigMap{Data: map[string]string{ + "Corefile": fmt.Sprintf(`.:53 { + kubernetes cluster.local in-addr.arpa ip6.arpa { + pods insecure + upstream + fallthrough in-addr.arpa ip6.arpa + } + proxy . %v + }`, t.dnsServerPod.Status.PodIP), + }}) + + t.deleteCoreDNSPods() + } else { + t.setConfigMap(&v1.ConfigMap{Data: map[string]string{ + "upstreamNameservers": fmt.Sprintf(`["%v"]`, t.dnsServerPod.Status.PodIP), + }}) + } + + t.checkDNSRecordFrom( + fmt.Sprintf("%s.%s.svc.cluster.local", serviceNameLocal, f.Namespace.Name), + func(actual []string) bool { + return len(actual) == 2 && actual[0] == fooHostname+"." && actual[1] == "192.0.2.123" + }, + "cluster-dns", + moreForeverTestTimeout) + + t.restoreDNSConfigMap(originalConfigMapData) +} + var _ = SIGDescribe("DNS configMap nameserver", func() { - t := &dnsNameserverTest{dnsTestCommon: newDnsTestCommon()} - BeforeEach(func() { t.c = t.f.ClientSet }) - It("should be able to change stubDomain configuration [Slow][Serial]", func() { - t.run() + Context("Change stubDomain", func() { + nsTest := &dnsNameserverTest{dnsTestCommon: newDnsTestCommon()} + + It("should be able to change stubDomain configuration [Slow][Serial]", func() { + nsTest.c = nsTest.f.ClientSet + nsTest.run() + }) + }) + + Context("Forward PTR lookup", func() { + fwdTest := &dnsPtrFwdTest{dnsTestCommon: newDnsTestCommon()} + + It("should forward PTR records lookup to upstream nameserver [Slow][Serial]", func() { + fwdTest.c = fwdTest.f.ClientSet + fwdTest.run() + }) + }) + + Context("Forward external name lookup", func() { + externalNameTest := &dnsExternalNameTest{dnsTestCommon: newDnsTestCommon()} + + It("should forward externalname lookup to upstream nameserver [Slow][Serial]", func() { + externalNameTest.c = externalNameTest.f.ClientSet + externalNameTest.run() + }) }) }) diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/dns_scale_records.go b/vendor/k8s.io/kubernetes/test/e2e/network/dns_scale_records.go new file mode 100644 index 000000000..c22cbd7e6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/network/dns_scale_records.go @@ -0,0 +1,105 @@ +/* +Copyright 2018 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 network + +import ( + "fmt" + "strconv" + "time" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/util/workqueue" + "k8s.io/kubernetes/test/e2e/framework" + testutils "k8s.io/kubernetes/test/utils" + + . "github.com/onsi/ginkgo" +) + +const ( + parallelCreateServiceWorkers = 1 + maxServicesPerCluster = 10000 + checkServicePercent = 0.05 +) + +var _ = SIGDescribe("[Feature:PerformanceDNS]", func() { + f := framework.NewDefaultFramework("performancedns") + + BeforeEach(func() { + framework.ExpectNoError(framework.WaitForAllNodesSchedulable(f.ClientSet, framework.TestContext.NodeSchedulableTimeout)) + framework.WaitForAllNodesHealthy(f.ClientSet, time.Minute) + + err := framework.CheckTestingNSDeletedExcept(f.ClientSet, f.Namespace.Name) + framework.ExpectNoError(err) + }) + + // answers dns for service - creates the maximum number of services, and then check dns record for one + It("Should answer DNS query for maximum number of services per cluster", func() { + services := generateServicesInNamespace(f.Namespace.Name, maxServicesPerCluster) + createService := func(i int) { + defer GinkgoRecover() + framework.ExpectNoError(testutils.CreateServiceWithRetries(f.ClientSet, f.Namespace.Name, services[i])) + } + framework.Logf("Creating %v test services", maxServicesPerCluster) + workqueue.Parallelize(parallelCreateServiceWorkers, len(services), createService) + dnsTest := dnsTestCommon{ + f: f, + c: f.ClientSet, + ns: f.Namespace.Name, + } + dnsTest.createUtilPodLabel("e2e-dns-scale-records") + defer dnsTest.deleteUtilPod() + framework.Logf("Querying %v%% of service records", checkServicePercent*100) + for i := 0; i < len(services); i++ { + if i%(1/checkServicePercent) != 0 { + continue + } + s := services[i] + svc, err := f.ClientSet.CoreV1().Services(s.Namespace).Get(s.Name, metav1.GetOptions{}) + framework.ExpectNoError(err) + qname := fmt.Sprintf("%v.%v.svc.cluster.local", s.Name, s.Namespace) + framework.Logf("Querying %v expecting %v", qname, svc.Spec.ClusterIP) + dnsTest.checkDNSRecordFrom( + qname, + func(actual []string) bool { + return len(actual) == 1 && actual[0] == svc.Spec.ClusterIP + }, + "cluster-dns", + wait.ForeverTestTimeout, + ) + } + }) +}) + +func generateServicesInNamespace(namespace string, num int) []*v1.Service { + services := make([]*v1.Service, num) + for i := 0; i < num; i++ { + services[i] = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "svc-" + strconv.Itoa(i), + Namespace: namespace, + }, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{{ + Port: 80, + }}, + }, + } + } + return services +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/ingress.go b/vendor/k8s.io/kubernetes/test/e2e/network/ingress.go index d5286ff13..b6b31a75e 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/ingress.go +++ b/vendor/k8s.io/kubernetes/test/e2e/network/ingress.go @@ -31,6 +31,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/authentication/serviceaccount" gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" @@ -40,12 +41,6 @@ import ( . "github.com/onsi/gomega" ) -const ( - NEGAnnotation = "alpha.cloud.google.com/load-balancer-neg" - NEGUpdateTimeout = 2 * time.Minute - instanceGroupAnnotation = "ingress.gcp.kubernetes.io/instance-groups" -) - var _ = SIGDescribe("Loadbalancing: L7", func() { defer GinkgoRecover() var ( @@ -125,18 +120,7 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { // ip released when the rest of lb resources are deleted in CleanupGCEIngressController ip := gceController.CreateStaticIP(ns) By(fmt.Sprintf("allocated static ip %v: %v through the GCE cloud provider", ns, ip)) - - jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "static-ip"), ns, map[string]string{ - framework.IngressStaticIPKey: ns, - framework.IngressAllowHTTPKey: "false", - }, map[string]string{}) - - By("waiting for Ingress to come up with ip: " + ip) - httpClient := framework.BuildInsecureClient(framework.IngressReqTimeout) - framework.ExpectNoError(framework.PollURL(fmt.Sprintf("https://%v/", ip), "", framework.LoadBalancerPollTimeout, jig.PollInterval, httpClient, false)) - - By("should reject HTTP traffic") - framework.ExpectNoError(framework.PollURL(fmt.Sprintf("http://%v/", ip), "", framework.LoadBalancerPollTimeout, jig.PollInterval, httpClient, true)) + executeStaticIPHttpsOnlyTest(f, jig, ns, ip) By("should have correct firewall rule for ingress") fw := gceController.GetFirewallRule() @@ -320,80 +304,47 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { }) It("should create ingress with pre-shared certificate", func() { - preSharedCertName := "test-pre-shared-cert" - By(fmt.Sprintf("Creating ssl certificate %q on GCE", preSharedCertName)) - testHostname := "test.ingress.com" - cert, key, err := framework.GenerateRSACerts(testHostname, true) - Expect(err).NotTo(HaveOccurred()) - gceCloud, err := framework.GetGCECloud() - Expect(err).NotTo(HaveOccurred()) - defer func() { - // We would not be able to delete the cert until ingress controller - // cleans up the target proxy that references it. - By("Deleting ingress before deleting ssl certificate") - if jig.Ingress != nil { - jig.TryDeleteIngress() - } - By(fmt.Sprintf("Deleting ssl certificate %q on GCE", preSharedCertName)) - err := wait.Poll(framework.LoadBalancerPollInterval, framework.LoadBalancerCleanupTimeout, func() (bool, error) { - if err := gceCloud.DeleteSslCertificate(preSharedCertName); err != nil && !errors.IsNotFound(err) { - framework.Logf("Failed to delete ssl certificate %q: %v. Retrying...", preSharedCertName, err) - return false, nil - } - return true, nil - }) - Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Failed to delete ssl certificate %q: %v", preSharedCertName, err)) - }() - _, err = gceCloud.CreateSslCertificate(&compute.SslCertificate{ - Name: preSharedCertName, - Certificate: string(cert), - PrivateKey: string(key), - Description: "pre-shared cert for ingress testing", - }) - Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Failed to create ssl certificate %q: %v", preSharedCertName, err)) + executePresharedCertTest(f, jig, "") + }) - By("Creating an ingress referencing the pre-shared certificate") - // Create an ingress referencing this cert using pre-shared-cert annotation. - jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "pre-shared-cert"), ns, map[string]string{ - framework.IngressPreSharedCertKey: preSharedCertName, - framework.IngressAllowHTTPKey: "false", + It("should create ingress with backend HTTPS", func() { + executeBacksideBacksideHTTPSTest(f, jig, "") + }) + + It("should support multiple TLS certs", func() { + By("Creating an ingress with no certs.") + jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "multiple-certs"), ns, map[string]string{ + framework.IngressStaticIPKey: ns, }, map[string]string{}) - By("Test that ingress works with the pre-shared certificate") - err = jig.WaitForIngressWithCert(true, []string{testHostname}, cert) - Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Unexpected error while waiting for ingress: %v", err)) - }) + By("Adding multiple certs to the ingress.") + hosts := []string{"test1.ingress.com", "test2.ingress.com", "test3.ingress.com", "test4.ingress.com"} + secrets := []string{"tls-secret-1", "tls-secret-2", "tls-secret-3", "tls-secret-4"} + certs := [][]byte{} + for i, host := range hosts { + jig.AddHTTPS(secrets[i], host) + certs = append(certs, jig.GetRootCA(secrets[i])) + } + for i, host := range hosts { + err := jig.WaitForIngressWithCert(true, []string{host}, certs[i]) + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Unexpected error while waiting for ingress: %v", err)) + } - It("should create ingress with backside re-encryption", func() { - By("Creating a set of ingress, service and deployment that have backside re-encryption configured") - deployCreated, svcCreated, ingCreated, err := framework.CreateReencryptionIngress(f.ClientSet, f.Namespace.Name) - defer func() { - By("Cleaning up re-encryption ingress, service and deployment") - if errs := framework.CleanupReencryptionIngress(f.ClientSet, deployCreated, svcCreated, ingCreated); len(errs) > 0 { - framework.Failf("Failed to cleanup re-encryption ingress: %v", errs) - } - }() - Expect(err).NotTo(HaveOccurred(), "Failed to create re-encryption ingress") + By("Remove all but one of the certs on the ingress.") + jig.RemoveHTTPS(secrets[1]) + jig.RemoveHTTPS(secrets[2]) + jig.RemoveHTTPS(secrets[3]) - By(fmt.Sprintf("Waiting for ingress %s to come up", ingCreated.Name)) - ingIP, err := jig.WaitForIngressAddress(f.ClientSet, f.Namespace.Name, ingCreated.Name, framework.LoadBalancerPollTimeout) - Expect(err).NotTo(HaveOccurred(), "Failed to wait for ingress IP") + By("Test that the remaining cert is properly served.") + err := jig.WaitForIngressWithCert(true, []string{hosts[0]}, certs[0]) + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Unexpected error while waiting for ingress: %v", err)) - By(fmt.Sprintf("Polling on address %s and verify the backend is serving HTTPS", ingIP)) - timeoutClient := &http.Client{Timeout: framework.IngressReqTimeout} - err = wait.PollImmediate(framework.LoadBalancerPollInterval, framework.LoadBalancerPollTimeout, func() (bool, error) { - resp, err := framework.SimpleGET(timeoutClient, fmt.Sprintf("http://%s", ingIP), "") - if err != nil { - framework.Logf("SimpleGET failed: %v", err) - return false, nil - } - if !strings.Contains(resp, "request_scheme=https") { - return false, fmt.Errorf("request wasn't served by HTTPS, response body: %s", resp) - } - framework.Logf("Poll succeeded, request was served by HTTPS") - return true, nil - }) - Expect(err).NotTo(HaveOccurred(), "Failed to verify backside re-encryption ingress") + By("Add back one of the certs that was removed and check that all certs are served.") + jig.AddHTTPS(secrets[1], hosts[1]) + for i, host := range hosts[:2] { + err := jig.WaitForIngressWithCert(true, []string{host}, certs[i]) + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Unexpected error while waiting for ingress: %v", err)) + } }) It("multicluster ingress should get instance group annotation", func() { @@ -402,23 +353,104 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { framework.IngressClassKey: framework.MulticlusterIngressClassValue, }, map[string]string{}) - By(fmt.Sprintf("waiting for Ingress %s to come up", name)) + By(fmt.Sprintf("waiting for Ingress %s to get instance group annotation", name)) pollErr := wait.Poll(2*time.Second, framework.LoadBalancerPollTimeout, func() (bool, error) { ing, err := f.ClientSet.ExtensionsV1beta1().Ingresses(ns).Get(name, metav1.GetOptions{}) framework.ExpectNoError(err) annotations := ing.Annotations - if annotations == nil || annotations[instanceGroupAnnotation] == "" { - framework.Logf("Waiting for ingress to get %s annotation. Found annotations: %v", instanceGroupAnnotation, annotations) + if annotations == nil || annotations[framework.InstanceGroupAnnotation] == "" { + framework.Logf("Waiting for ingress to get %s annotation. Found annotations: %v", framework.InstanceGroupAnnotation, annotations) return false, nil } return true, nil }) if pollErr != nil { - framework.ExpectNoError(fmt.Errorf("Timed out waiting for ingress %s to get %s annotation", name, instanceGroupAnnotation)) + framework.ExpectNoError(fmt.Errorf("Timed out waiting for ingress %s to get %s annotation", name, framework.InstanceGroupAnnotation)) } + + // Verify that the ingress does not get other annotations like url-map, target-proxy, backends, etc. + // Note: All resources except the firewall rule have an annotation. + umKey := framework.StatusPrefix + "/url-map" + fwKey := framework.StatusPrefix + "/forwarding-rule" + tpKey := framework.StatusPrefix + "/target-proxy" + fwsKey := framework.StatusPrefix + "/https-forwarding-rule" + tpsKey := framework.StatusPrefix + "/https-target-proxy" + scKey := framework.StatusPrefix + "/ssl-cert" + beKey := framework.StatusPrefix + "/backends" + wait.Poll(2*time.Second, time.Minute, func() (bool, error) { + ing, err := f.ClientSet.ExtensionsV1beta1().Ingresses(ns).Get(name, metav1.GetOptions{}) + framework.ExpectNoError(err) + annotations := ing.Annotations + if annotations != nil && (annotations[umKey] != "" || annotations[fwKey] != "" || + annotations[tpKey] != "" || annotations[fwsKey] != "" || annotations[tpsKey] != "" || + annotations[scKey] != "" || annotations[beKey] != "") { + framework.Failf("unexpected annotations. Expected to not have annotations for urlmap, forwarding rule, target proxy, ssl cert and backends, got: %v", annotations) + return true, nil + } + return false, nil + }) + + // Verify that the controller does not create any other resource except instance group. + // TODO(59778): Check GCE resources specific to this ingress instead of listing all resources. + if len(gceController.ListUrlMaps()) != 0 { + framework.Failf("unexpected url maps, expected none, got: %v", gceController.ListUrlMaps()) + } + if len(gceController.ListGlobalForwardingRules()) != 0 { + framework.Failf("unexpected forwarding rules, expected none, got: %v", gceController.ListGlobalForwardingRules()) + } + if len(gceController.ListTargetHttpProxies()) != 0 { + framework.Failf("unexpected target http proxies, expected none, got: %v", gceController.ListTargetHttpProxies()) + } + if len(gceController.ListTargetHttpsProxies()) != 0 { + framework.Failf("unexpected target https proxies, expected none, got: %v", gceController.ListTargetHttpProxies()) + } + if len(gceController.ListSslCertificates()) != 0 { + framework.Failf("unexpected ssl certificates, expected none, got: %v", gceController.ListSslCertificates()) + } + if len(gceController.ListGlobalBackendServices()) != 0 { + framework.Failf("unexpected backend service, expected none, got: %v", gceController.ListGlobalBackendServices()) + } + // Controller does not have a list command for firewall rule. We use get instead. + if fw, err := gceController.GetFirewallRuleOrError(); err == nil { + framework.Failf("unexpected nil error in getting firewall rule, expected firewall NotFound, got firewall: %v", fw) + } + // TODO(nikhiljindal): Check the instance group annotation value and verify with a multizone cluster. }) + It("should be able to switch between HTTPS and HTTP2 modes", func() { + httpsScheme := "request_scheme=https" + + By("Create a basic HTTP2 ingress") + jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "http2"), ns, map[string]string{}, map[string]string{}) + jig.WaitForIngress(true) + + address, err := jig.WaitForIngressAddress(jig.Client, jig.Ingress.Namespace, jig.Ingress.Name, framework.LoadBalancerPollTimeout) + + By(fmt.Sprintf("Polling on address %s and verify the backend is serving HTTP2", address)) + detectHttpVersionAndSchemeTest(f, jig, address, "request_version=2", httpsScheme) + + By("Switch backend service to use HTTPS") + svcList, err := f.ClientSet.CoreV1().Services(ns).List(metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + for _, svc := range svcList.Items { + svc.Annotations[framework.ServiceApplicationProtocolKey] = `{"http2":"HTTPS"}` + _, err = f.ClientSet.CoreV1().Services(ns).Update(&svc) + Expect(err).NotTo(HaveOccurred()) + } + detectHttpVersionAndSchemeTest(f, jig, address, "request_version=1.1", httpsScheme) + + By("Switch backend service to use HTTP2") + svcList, err = f.ClientSet.CoreV1().Services(ns).List(metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + for _, svc := range svcList.Items { + svc.Annotations[framework.ServiceApplicationProtocolKey] = `{"http2":"HTTP2"}` + _, err = f.ClientSet.CoreV1().Services(ns).Update(&svc) + Expect(err).NotTo(HaveOccurred()) + } + detectHttpVersionAndSchemeTest(f, jig, address, "request_version=2", httpsScheme) + }) + // TODO: Implement a multizone e2e that verifies traffic reaches each // zone based on pod labels. }) @@ -458,14 +490,14 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { It("should conform to Ingress spec", func() { jig.PollInterval = 5 * time.Second conformanceTests = framework.CreateIngressComformanceTests(jig, ns, map[string]string{ - NEGAnnotation: "true", + framework.NEGAnnotation: "true", }) for _, t := range conformanceTests { By(t.EntryLog) t.Execute() By(t.ExitLog) jig.WaitForIngress(true) - usingNeg, err := gceController.BackendServiceUsingNEG(jig.GetIngressNodePorts(false)) + usingNeg, err := gceController.BackendServiceUsingNEG(jig.GetServicePorts(false)) Expect(err).NotTo(HaveOccurred()) Expect(usingNeg).To(BeTrue()) } @@ -476,7 +508,7 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { By("Create a basic HTTP ingress using NEG") jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "neg"), ns, map[string]string{}, map[string]string{}) jig.WaitForIngress(true) - usingNEG, err := gceController.BackendServiceUsingNEG(jig.GetIngressNodePorts(false)) + usingNEG, err := gceController.BackendServiceUsingNEG(jig.GetServicePorts(false)) Expect(err).NotTo(HaveOccurred()) Expect(usingNEG).To(BeTrue()) @@ -484,12 +516,12 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { svcList, err := f.ClientSet.CoreV1().Services(ns).List(metav1.ListOptions{}) Expect(err).NotTo(HaveOccurred()) for _, svc := range svcList.Items { - svc.Annotations[NEGAnnotation] = "false" + svc.Annotations[framework.NEGAnnotation] = "false" _, err = f.ClientSet.CoreV1().Services(ns).Update(&svc) Expect(err).NotTo(HaveOccurred()) } wait.Poll(5*time.Second, framework.LoadBalancerPollTimeout, func() (bool, error) { - return gceController.BackendServiceUsingIG(jig.GetIngressNodePorts(true)) + return gceController.BackendServiceUsingIG(jig.GetServicePorts(true)) }) jig.WaitForIngress(true) @@ -497,16 +529,32 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { svcList, err = f.ClientSet.CoreV1().Services(ns).List(metav1.ListOptions{}) Expect(err).NotTo(HaveOccurred()) for _, svc := range svcList.Items { - svc.Annotations[NEGAnnotation] = "true" + svc.Annotations[framework.NEGAnnotation] = "true" _, err = f.ClientSet.CoreV1().Services(ns).Update(&svc) Expect(err).NotTo(HaveOccurred()) } wait.Poll(5*time.Second, framework.LoadBalancerPollTimeout, func() (bool, error) { - return gceController.BackendServiceUsingNEG(jig.GetIngressNodePorts(false)) + return gceController.BackendServiceUsingNEG(jig.GetServicePorts(false)) }) jig.WaitForIngress(true) }) + It("should be able to create a ClusterIP service [Unreleased]", func() { + var err error + By("Create a basic HTTP ingress using NEG") + jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "neg-clusterip"), ns, map[string]string{}, map[string]string{}) + jig.WaitForIngress(true) + svcPorts := jig.GetServicePorts(false) + usingNEG, err := gceController.BackendServiceUsingNEG(svcPorts) + Expect(err).NotTo(HaveOccurred()) + Expect(usingNEG).To(BeTrue()) + + // ClusterIP ServicePorts have no NodePort + for _, sp := range svcPorts { + Expect(sp.NodePort).To(Equal(int32(0))) + } + }) + It("should sync endpoints to NEG", func() { name := "hostname" scaleAndValidateNEG := func(num int) { @@ -517,7 +565,7 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { _, err = f.ClientSet.ExtensionsV1beta1().Deployments(ns).UpdateScale(name, scale) Expect(err).NotTo(HaveOccurred()) } - wait.Poll(10*time.Second, NEGUpdateTimeout, func() (bool, error) { + wait.Poll(10*time.Second, framework.NEGUpdateTimeout, func() (bool, error) { res, err := jig.GetDistinctResponseFromIngress() if err != nil { return false, nil @@ -529,7 +577,7 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { By("Create a basic HTTP ingress using NEG") jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "neg"), ns, map[string]string{}, map[string]string{}) jig.WaitForIngress(true) - usingNEG, err := gceController.BackendServiceUsingNEG(jig.GetIngressNodePorts(false)) + usingNEG, err := gceController.BackendServiceUsingNEG(jig.GetServicePorts(false)) Expect(err).NotTo(HaveOccurred()) Expect(usingNEG).To(BeTrue()) // initial replicas number is 1 @@ -554,7 +602,7 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { By("Create a basic HTTP ingress using NEG") jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "neg"), ns, map[string]string{}, map[string]string{}) jig.WaitForIngress(true) - usingNEG, err := gceController.BackendServiceUsingNEG(jig.GetIngressNodePorts(false)) + usingNEG, err := gceController.BackendServiceUsingNEG(jig.GetServicePorts(false)) Expect(err).NotTo(HaveOccurred()) Expect(usingNEG).To(BeTrue()) @@ -602,10 +650,29 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { }) Describe("GCE [Slow] [Feature:kubemci]", func() { + var gceController *framework.GCEIngressController + var ipName, ipAddress string + // Platform specific setup BeforeEach(func() { framework.SkipUnlessProviderIs("gce", "gke") jig.Class = framework.MulticlusterIngressClassValue + jig.PollInterval = 5 * time.Second + By("Initializing gce controller") + gceController = &framework.GCEIngressController{ + Ns: ns, + Client: jig.Client, + Cloud: framework.TestContext.CloudConfig, + } + err := gceController.Init() + Expect(err).NotTo(HaveOccurred()) + + // TODO(https://github.com/GoogleCloudPlatform/k8s-multicluster-ingress/issues/19): + // Kubemci should reserve a static ip if user has not specified one. + ipName = "kubemci-" + string(uuid.NewUUID()) + // ip released when the rest of lb resources are deleted in CleanupGCEIngressController + ipAddress = gceController.CreateStaticIP(ipName) + By(fmt.Sprintf("allocated static ip %v: %v through the GCE cloud provider", ipName, ipAddress)) }) // Platform specific cleanup @@ -615,21 +682,98 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { } if jig.Ingress == nil { By("No ingress created, no cleanup necessary") - return + } else { + By("Deleting ingress") + jig.TryDeleteIngress() } - By("Deleting ingress") - jig.TryDeleteIngress() + + By("Cleaning up cloud resources") + Expect(gceController.CleanupGCEIngressController()).NotTo(HaveOccurred()) }) It("should conform to Ingress spec", func() { - jig.PollInterval = 5 * time.Second - conformanceTests = framework.CreateIngressComformanceTests(jig, ns, map[string]string{}) + conformanceTests = framework.CreateIngressComformanceTests(jig, ns, map[string]string{ + framework.IngressStaticIPKey: ipName, + }) for _, t := range conformanceTests { By(t.EntryLog) t.Execute() By(t.ExitLog) - jig.WaitForIngress(true /*waitForNodePort*/) + jig.WaitForIngress(false /*waitForNodePort*/) + } + }) + + It("should create ingress with pre-shared certificate", func() { + executePresharedCertTest(f, jig, ipName) + }) + + It("should create ingress with backend HTTPS", func() { + executeBacksideBacksideHTTPSTest(f, jig, ipName) + }) + + It("should support https-only annotation", func() { + executeStaticIPHttpsOnlyTest(f, jig, ipName, ipAddress) + }) + + It("should remove clusters as expected", func() { + ingAnnotations := map[string]string{ + framework.IngressStaticIPKey: ipName, + } + ingFilePath := filepath.Join(framework.IngressManifestPath, "http") + jig.CreateIngress(ingFilePath, ns, ingAnnotations, map[string]string{}) + jig.WaitForIngress(false /*waitForNodePort*/) + name := jig.Ingress.Name + // Verify that the ingress is spread to 1 cluster as expected. + verifyKubemciStatusHas(name, "is spread across 1 cluster") + // Validate that removing the ingress from all clusters throws an error. + // Reuse the ingress file created while creating the ingress. + filePath := filepath.Join(framework.TestContext.OutputDir, "mci.yaml") + output, err := framework.RunKubemciWithKubeconfig("remove-clusters", name, "--ingress="+filePath) + if err != nil { + framework.Failf("unexpected error in running kubemci remove-clusters command to remove from all clusters: %s", err) + } + if !strings.Contains(output, "You should use kubemci delete to delete the ingress completely") { + framework.Failf("unexpected output in removing an ingress from all clusters, expected the output to include: You should use kubemci delete to delete the ingress completely, actual output: %s", output) } + // Verify that the ingress is still spread to 1 cluster as expected. + verifyKubemciStatusHas(name, "is spread across 1 cluster") + // remove-clusters should succeed with --force=true + if _, err := framework.RunKubemciWithKubeconfig("remove-clusters", name, "--ingress="+filePath, "--force=true"); err != nil { + framework.Failf("unexpected error in running kubemci remove-clusters to remove from all clusters with --force=true: %s", err) + } + verifyKubemciStatusHas(name, "is spread across 0 cluster") + }) + + It("single and multi-cluster ingresses should be able to exist together", func() { + By("Creating a single cluster ingress first") + jig.Class = "" + singleIngFilePath := filepath.Join(framework.IngressManifestPath, "static-ip-2") + jig.CreateIngress(singleIngFilePath, ns, map[string]string{}, map[string]string{}) + jig.WaitForIngress(false /*waitForNodePort*/) + // jig.Ingress will be overwritten when we create MCI, so keep a reference. + singleIng := jig.Ingress + + // Create the multi-cluster ingress next. + By("Creating a multi-cluster ingress next") + jig.Class = framework.MulticlusterIngressClassValue + ingAnnotations := map[string]string{ + framework.IngressStaticIPKey: ipName, + } + multiIngFilePath := filepath.Join(framework.IngressManifestPath, "http") + jig.CreateIngress(multiIngFilePath, ns, ingAnnotations, map[string]string{}) + jig.WaitForIngress(false /*waitForNodePort*/) + mciIngress := jig.Ingress + + By("Deleting the single cluster ingress and verifying that multi-cluster ingress continues to work") + jig.Ingress = singleIng + jig.Class = "" + jig.TryDeleteIngress() + jig.Ingress = mciIngress + jig.Class = framework.MulticlusterIngressClassValue + jig.WaitForIngress(false /*waitForNodePort*/) + + By("Cleanup: Deleting the multi-cluster ingress") + jig.TryDeleteIngress() }) }) @@ -684,3 +828,133 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { }) }) }) + +// verifyKubemciStatusHas fails if kubemci get-status output for the given mci does not have the given expectedSubStr. +func verifyKubemciStatusHas(name, expectedSubStr string) { + statusStr, err := framework.RunKubemciCmd("get-status", name) + if err != nil { + framework.Failf("unexpected error in running kubemci get-status %s: %s", name, err) + } + if !strings.Contains(statusStr, expectedSubStr) { + framework.Failf("expected status to have sub string %s, actual status: %s", expectedSubStr, statusStr) + } +} + +func executePresharedCertTest(f *framework.Framework, jig *framework.IngressTestJig, staticIPName string) { + preSharedCertName := "test-pre-shared-cert" + By(fmt.Sprintf("Creating ssl certificate %q on GCE", preSharedCertName)) + testHostname := "test.ingress.com" + cert, key, err := framework.GenerateRSACerts(testHostname, true) + Expect(err).NotTo(HaveOccurred()) + gceCloud, err := framework.GetGCECloud() + Expect(err).NotTo(HaveOccurred()) + defer func() { + // We would not be able to delete the cert until ingress controller + // cleans up the target proxy that references it. + By("Deleting ingress before deleting ssl certificate") + if jig.Ingress != nil { + jig.TryDeleteIngress() + } + By(fmt.Sprintf("Deleting ssl certificate %q on GCE", preSharedCertName)) + err := wait.Poll(framework.LoadBalancerPollInterval, framework.LoadBalancerCleanupTimeout, func() (bool, error) { + if err := gceCloud.DeleteSslCertificate(preSharedCertName); err != nil && !errors.IsNotFound(err) { + framework.Logf("Failed to delete ssl certificate %q: %v. Retrying...", preSharedCertName, err) + return false, nil + } + return true, nil + }) + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Failed to delete ssl certificate %q: %v", preSharedCertName, err)) + }() + _, err = gceCloud.CreateSslCertificate(&compute.SslCertificate{ + Name: preSharedCertName, + Certificate: string(cert), + PrivateKey: string(key), + Description: "pre-shared cert for ingress testing", + }) + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Failed to create ssl certificate %q: %v", preSharedCertName, err)) + + By("Creating an ingress referencing the pre-shared certificate") + // Create an ingress referencing this cert using pre-shared-cert annotation. + ingAnnotations := map[string]string{ + framework.IngressPreSharedCertKey: preSharedCertName, + // Disallow HTTP to save resources. This is irrelevant to the + // pre-shared cert test. + framework.IngressAllowHTTPKey: "false", + } + if staticIPName != "" { + ingAnnotations[framework.IngressStaticIPKey] = staticIPName + } + jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "pre-shared-cert"), f.Namespace.Name, ingAnnotations, map[string]string{}) + + By("Test that ingress works with the pre-shared certificate") + err = jig.WaitForIngressWithCert(true, []string{testHostname}, cert) + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Unexpected error while waiting for ingress: %v", err)) +} + +func executeStaticIPHttpsOnlyTest(f *framework.Framework, jig *framework.IngressTestJig, ipName, ip string) { + jig.CreateIngress(filepath.Join(framework.IngressManifestPath, "static-ip"), f.Namespace.Name, map[string]string{ + framework.IngressStaticIPKey: ipName, + framework.IngressAllowHTTPKey: "false", + }, map[string]string{}) + + By("waiting for Ingress to come up with ip: " + ip) + httpClient := framework.BuildInsecureClient(framework.IngressReqTimeout) + framework.ExpectNoError(framework.PollURL(fmt.Sprintf("https://%s/", ip), "", framework.LoadBalancerPollTimeout, jig.PollInterval, httpClient, false)) + + By("should reject HTTP traffic") + framework.ExpectNoError(framework.PollURL(fmt.Sprintf("http://%s/", ip), "", framework.LoadBalancerPollTimeout, jig.PollInterval, httpClient, true)) +} + +func executeBacksideBacksideHTTPSTest(f *framework.Framework, jig *framework.IngressTestJig, staticIPName string) { + By("Creating a set of ingress, service and deployment that have backside re-encryption configured") + deployCreated, svcCreated, ingCreated, err := jig.SetUpBacksideHTTPSIngress(f.ClientSet, f.Namespace.Name, staticIPName) + defer func() { + By("Cleaning up re-encryption ingress, service and deployment") + if errs := jig.DeleteTestResource(f.ClientSet, deployCreated, svcCreated, ingCreated); len(errs) > 0 { + framework.Failf("Failed to cleanup re-encryption ingress: %v", errs) + } + }() + Expect(err).NotTo(HaveOccurred(), "Failed to create re-encryption ingress") + + By(fmt.Sprintf("Waiting for ingress %s to come up", ingCreated.Name)) + ingIP, err := jig.WaitForIngressAddress(f.ClientSet, f.Namespace.Name, ingCreated.Name, framework.LoadBalancerPollTimeout) + Expect(err).NotTo(HaveOccurred(), "Failed to wait for ingress IP") + + By(fmt.Sprintf("Polling on address %s and verify the backend is serving HTTPS", ingIP)) + timeoutClient := &http.Client{Timeout: framework.IngressReqTimeout} + err = wait.PollImmediate(framework.LoadBalancerPollInterval, framework.LoadBalancerPollTimeout, func() (bool, error) { + resp, err := framework.SimpleGET(timeoutClient, fmt.Sprintf("http://%s", ingIP), "") + if err != nil { + framework.Logf("SimpleGET failed: %v", err) + return false, nil + } + if !strings.Contains(resp, "request_scheme=https") { + return false, fmt.Errorf("request wasn't served by HTTPS, response body: %s", resp) + } + framework.Logf("Poll succeeded, request was served by HTTPS") + return true, nil + }) + Expect(err).NotTo(HaveOccurred(), "Failed to verify backside re-encryption ingress") +} + +func detectHttpVersionAndSchemeTest(f *framework.Framework, jig *framework.IngressTestJig, address, version, scheme string) { + timeoutClient := &http.Client{Timeout: framework.IngressReqTimeout} + resp := "" + err := wait.PollImmediate(framework.LoadBalancerPollInterval, framework.LoadBalancerPollTimeout, func() (bool, error) { + resp, err := framework.SimpleGET(timeoutClient, fmt.Sprintf("http://%s", address), "") + if err != nil { + framework.Logf("SimpleGET failed: %v", err) + return false, nil + } + if !strings.Contains(resp, version) { + framework.Logf("Waiting for transition to HTTP/2") + return false, nil + } + if !strings.Contains(resp, scheme) { + return false, nil + } + framework.Logf("Poll succeeded, request was served by HTTP2") + return true, nil + }) + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Failed to get %s or %s, response body: %s", version, scheme, resp)) +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/proxy.go b/vendor/k8s.io/kubernetes/test/e2e/network/proxy.go index a2ca59dd0..33de281c5 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/proxy.go +++ b/vendor/k8s.io/kubernetes/test/e2e/network/proxy.go @@ -32,8 +32,6 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/net" clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/api/testapi" - utilversion "k8s.io/kubernetes/pkg/util/version" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" imageutils "k8s.io/kubernetes/test/utils/image" @@ -53,11 +51,8 @@ const ( proxyHTTPCallTimeout = 30 * time.Second ) -var deprecatedCAdvisorPortRemovedVersion = utilversion.MustParseSemantic("v1.11.0-alpha.0") - var _ = SIGDescribe("Proxy", func() { - version := testapi.Groups[v1.GroupName].GroupVersion().Version - + version := "v1" Context("version "+version, func() { options := framework.FrameworkOptions{ ClientQPS: -1.0, @@ -65,13 +60,6 @@ var _ = SIGDescribe("Proxy", func() { f := framework.NewFramework("proxy", options, nil) prefix := "/api/" + version - skipCAdvisorProxyTests := false - BeforeEach(func() { - var err error - skipCAdvisorProxyTests, err = framework.ServerVersionGTE(deprecatedCAdvisorPortRemovedVersion, f.ClientSet.Discovery()) - Expect(err).NotTo(HaveOccurred()) - }) - /* Testname: proxy-subresource-node-logs-port Description: Ensure that proxy on node logs works with node proxy @@ -86,13 +74,6 @@ var _ = SIGDescribe("Proxy", func() { */ framework.ConformanceIt("should proxy logs on node using proxy subresource ", func() { nodeProxyTest(f, prefix+"/nodes/", "/proxy/logs/") }) - It("should proxy to cadvisor using proxy subresource", func() { - if skipCAdvisorProxyTests { - framework.Skipf("cadvisor proxy test removed on newer server version") - } - nodeProxyTest(f, prefix+"/nodes/", ":4194/proxy/containers/") - }) - // using the porter image to serve content, access the content // (of multiple pods?) from multiple (endpoints/services?) @@ -180,7 +161,7 @@ var _ = SIGDescribe("Proxy", func() { CreatedPods: &pods, } Expect(framework.RunRC(cfg)).NotTo(HaveOccurred()) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, cfg.Name) + defer framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, cfg.Name) Expect(framework.WaitForEndpoint(f.ClientSet, f.Namespace.Name, service.Name)).NotTo(HaveOccurred()) diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/scale/ingress.go b/vendor/k8s.io/kubernetes/test/e2e/network/scale/ingress.go index 9762b7a2c..542620518 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/scale/ingress.go +++ b/vendor/k8s.io/kubernetes/test/e2e/network/scale/ingress.go @@ -179,25 +179,27 @@ func (f *IngressScaleFramework) RunScaleTest() []error { } } - // currentNum keeps track of how many ingresses have been created. - currentNum := new(int) + // numIngsCreated keeps track of how many ingresses have been created. + numIngsCreated := 0 - prepareIngsFunc := func(goalNum int) { + prepareIngsFunc := func(numIngsNeeded int) { var ingWg sync.WaitGroup - numToCreate := goalNum - *currentNum - ingWg.Add(numToCreate) - errQueue := make(chan error, numToCreate) - latencyQueue := make(chan time.Duration, numToCreate) + numIngsToCreate := numIngsNeeded - numIngsCreated + ingWg.Add(numIngsToCreate) + svcQueue := make(chan *v1.Service, numIngsToCreate) + ingQueue := make(chan *extensions.Ingress, numIngsToCreate) + errQueue := make(chan error, numIngsToCreate) + latencyQueue := make(chan time.Duration, numIngsToCreate) start := time.Now() - for ; *currentNum < goalNum; *currentNum++ { - suffix := fmt.Sprintf("%d", *currentNum) + for ; numIngsCreated < numIngsNeeded; numIngsCreated++ { + suffix := fmt.Sprintf("%d", numIngsCreated) go func() { defer ingWg.Done() start := time.Now() svcCreated, ingCreated, err := f.createScaleTestServiceIngress(suffix, f.EnableTLS) - f.ScaleTestSvcs = append(f.ScaleTestSvcs, svcCreated) - f.ScaleTestIngs = append(f.ScaleTestIngs, ingCreated) + svcQueue <- svcCreated + ingQueue <- ingCreated if err != nil { errQueue <- err return @@ -214,11 +216,19 @@ func (f *IngressScaleFramework) RunScaleTest() []error { } // Wait until all ingress creations are complete. - f.Logger.Infof("Waiting for %d ingresses to come up...", numToCreate) + f.Logger.Infof("Waiting for %d ingresses to come up...", numIngsToCreate) ingWg.Wait() + close(svcQueue) + close(ingQueue) close(errQueue) close(latencyQueue) elapsed := time.Since(start) + for svc := range svcQueue { + f.ScaleTestSvcs = append(f.ScaleTestSvcs, svc) + } + for ing := range ingQueue { + f.ScaleTestIngs = append(f.ScaleTestIngs, ing) + } var createLatencies []time.Duration for latency := range latencyQueue { createLatencies = append(createLatencies, latency) @@ -231,15 +241,15 @@ func (f *IngressScaleFramework) RunScaleTest() []error { } return } - f.Logger.Infof("Spent %s for %d ingresses to come up", elapsed, numToCreate) + f.Logger.Infof("Spent %s for %d ingresses to come up", elapsed, numIngsToCreate) f.BatchDurations = append(f.BatchDurations, elapsed) } measureCreateUpdateFunc := func() { f.Logger.Infof("Create one more ingress and wait for it to come up") start := time.Now() - svcCreated, ingCreated, err := f.createScaleTestServiceIngress(fmt.Sprintf("%d", *currentNum), f.EnableTLS) - *currentNum = *currentNum + 1 + svcCreated, ingCreated, err := f.createScaleTestServiceIngress(fmt.Sprintf("%d", numIngsCreated), f.EnableTLS) + numIngsCreated = numIngsCreated + 1 f.ScaleTestSvcs = append(f.ScaleTestSvcs, svcCreated) f.ScaleTestIngs = append(f.ScaleTestIngs, ingCreated) if err != nil { @@ -440,7 +450,7 @@ func generateScaleTestBackendDeploymentSpec(numReplicas int32) *extensions.Deplo Containers: []v1.Container{ { Name: scaleTestBackendName, - Image: "gcr.io/google_containers/echoserver:1.6", + Image: "k8s.gcr.io/echoserver:1.10", Ports: []v1.ContainerPort{{ContainerPort: 8080}}, ReadinessProbe: &v1.Probe{ Handler: v1.Handler{ diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/scale/localrun/ingress_scale.go b/vendor/k8s.io/kubernetes/test/e2e/network/scale/localrun/ingress_scale.go index 87c898e3a..62c44e316 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/scale/localrun/ingress_scale.go +++ b/vendor/k8s.io/kubernetes/test/e2e/network/scale/localrun/ingress_scale.go @@ -106,11 +106,7 @@ func main() { } // Initializing a GCE client. - gceAlphaFeatureGate, err := gcecloud.NewAlphaFeatureGate([]string{}) - if err != nil { - glog.Errorf("Encountered error for creating alpha feature gate: %v", err) - os.Exit(1) - } + gceAlphaFeatureGate := gcecloud.NewAlphaFeatureGate([]string{}) gceCloud, err := gcecloud.CreateGCECloud(&gcecloud.CloudConfig{ ProjectID: cloudConfig.ProjectID, Region: cloudConfig.Region, diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/service.go b/vendor/k8s.io/kubernetes/test/e2e/network/service.go index 42130c7d0..09746b440 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/service.go +++ b/vendor/k8s.io/kubernetes/test/e2e/network/service.go @@ -43,6 +43,36 @@ import ( . "github.com/onsi/gomega" ) +const ( + defaultServeHostnameServicePort = 80 + defaultServeHostnameServiceName = "svc-hostname" +) + +var ( + defaultServeHostnameService = v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: defaultServeHostnameServiceName, + }, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{{ + Port: int32(defaultServeHostnameServicePort), + TargetPort: intstr.FromInt(9376), + Protocol: "TCP", + }}, + Selector: map[string]string{ + "name": defaultServeHostnameServiceName, + }, + }, + } +) + +func getServeHostnameService(name string) *v1.Service { + svc := defaultServeHostnameService.DeepCopy() + svc.ObjectMeta.Name = name + svc.Spec.Selector["name"] = name + return svc +} + var _ = SIGDescribe("Services", func() { f := framework.NewDefaultFramework("services") @@ -84,9 +114,9 @@ var _ = SIGDescribe("Services", func() { valid/accessible endpoints (same port number for service and pods). */ framework.ConformanceIt("should serve a basic endpoint from pods ", func() { - // TODO: use the ServiceTestJig here serviceName := "endpoint-test2" ns := f.Namespace.Name + jig := framework.NewServiceTestJig(cs, serviceName) labels := map[string]string{ "foo": "bar", "baz": "blah", @@ -97,20 +127,12 @@ var _ = SIGDescribe("Services", func() { err := cs.CoreV1().Services(ns).Delete(serviceName, nil) Expect(err).NotTo(HaveOccurred()) }() + ports := []v1.ServicePort{{ + Port: 80, + TargetPort: intstr.FromInt(80), + }} + _, err := jig.CreateServiceWithServicePort(labels, ns, ports) - service := &v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, - }, - Spec: v1.ServiceSpec{ - Selector: labels, - Ports: []v1.ServicePort{{ - Port: 80, - TargetPort: intstr.FromInt(80), - }}, - }, - } - _, err := cs.CoreV1().Services(ns).Create(service) Expect(err).NotTo(HaveOccurred()) framework.ValidateEndpointsOrFail(cs, ns, serviceName, framework.PortsByPodName{}) @@ -149,10 +171,10 @@ var _ = SIGDescribe("Services", func() { valid/accessible endpoints (different port number for pods). */ framework.ConformanceIt("should serve multiport endpoints from pods ", func() { - // TODO: use the ServiceTestJig here // repacking functionality is intentionally not tested here - it's better to test it in an integration test. serviceName := "multi-endpoint-test" ns := f.Namespace.Name + jig := framework.NewServiceTestJig(cs, serviceName) defer func() { err := cs.CoreV1().Services(ns).Delete(serviceName, nil) @@ -165,27 +187,19 @@ var _ = SIGDescribe("Services", func() { svc2port := "svc2" By("creating service " + serviceName + " in namespace " + ns) - service := &v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, + ports := []v1.ServicePort{ + { + Name: "portname1", + Port: 80, + TargetPort: intstr.FromString(svc1port), }, - Spec: v1.ServiceSpec{ - Selector: labels, - Ports: []v1.ServicePort{ - { - Name: "portname1", - Port: 80, - TargetPort: intstr.FromString(svc1port), - }, - { - Name: "portname2", - Port: 81, - TargetPort: intstr.FromString(svc2port), - }, - }, + { + Name: "portname2", + Port: 81, + TargetPort: intstr.FromString(svc2port), }, } - _, err := cs.CoreV1().Services(ns).Create(service) + _, err := jig.CreateServiceWithServicePort(labels, ns, ports) Expect(err).NotTo(HaveOccurred()) port1 := 100 port2 := 101 @@ -301,13 +315,13 @@ var _ = SIGDescribe("Services", func() { framework.SkipUnlessSSHKeyPresent() ns := f.Namespace.Name - numPods, servicePort := 3, 80 + numPods, servicePort := 3, defaultServeHostnameServicePort By("creating service1 in namespace " + ns) - podNames1, svc1IP, err := framework.StartServeHostnameService(cs, internalClientset, ns, "service1", servicePort, numPods) + podNames1, svc1IP, err := framework.StartServeHostnameService(cs, internalClientset, getServeHostnameService("service1"), ns, numPods) Expect(err).NotTo(HaveOccurred()) By("creating service2 in namespace " + ns) - podNames2, svc2IP, err := framework.StartServeHostnameService(cs, internalClientset, ns, "service2", servicePort, numPods) + podNames2, svc2IP, err := framework.StartServeHostnameService(cs, internalClientset, getServeHostnameService("service2"), ns, numPods) Expect(err).NotTo(HaveOccurred()) hosts, err := framework.NodeSSHHosts(cs) @@ -325,7 +339,7 @@ var _ = SIGDescribe("Services", func() { // Stop service 1 and make sure it is gone. By("stopping service1") - framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, f.InternalClientset, ns, "service1")) + framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, ns, "service1")) By("verifying service1 is not up") framework.ExpectNoError(framework.VerifyServeHostnameServiceDown(cs, host, svc1IP, servicePort)) @@ -334,7 +348,7 @@ var _ = SIGDescribe("Services", func() { // Start another service and verify both are up. By("creating service3 in namespace " + ns) - podNames3, svc3IP, err := framework.StartServeHostnameService(cs, internalClientset, ns, "service3", servicePort, numPods) + podNames3, svc3IP, err := framework.StartServeHostnameService(cs, internalClientset, getServeHostnameService("service3"), ns, numPods) Expect(err).NotTo(HaveOccurred()) if svc2IP == svc3IP { @@ -353,21 +367,21 @@ var _ = SIGDescribe("Services", func() { framework.SkipUnlessProviderIs("gce", "gke") ns := f.Namespace.Name - numPods, servicePort := 3, 80 + numPods, servicePort := 3, defaultServeHostnameServicePort svc1 := "service1" svc2 := "service2" defer func() { - framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, f.InternalClientset, ns, svc1)) + framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, ns, svc1)) }() - podNames1, svc1IP, err := framework.StartServeHostnameService(cs, internalClientset, ns, svc1, servicePort, numPods) + podNames1, svc1IP, err := framework.StartServeHostnameService(cs, internalClientset, getServeHostnameService(svc1), ns, numPods) Expect(err).NotTo(HaveOccurred()) defer func() { - framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, f.InternalClientset, ns, svc2)) + framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, ns, svc2)) }() - podNames2, svc2IP, err := framework.StartServeHostnameService(cs, internalClientset, ns, svc2, servicePort, numPods) + podNames2, svc2IP, err := framework.StartServeHostnameService(cs, internalClientset, getServeHostnameService(svc2), ns, numPods) Expect(err).NotTo(HaveOccurred()) if svc1IP == svc2IP { @@ -412,9 +426,9 @@ var _ = SIGDescribe("Services", func() { numPods, servicePort := 3, 80 defer func() { - framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, f.InternalClientset, ns, "service1")) + framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, ns, "service1")) }() - podNames1, svc1IP, err := framework.StartServeHostnameService(cs, internalClientset, ns, "service1", servicePort, numPods) + podNames1, svc1IP, err := framework.StartServeHostnameService(cs, internalClientset, getServeHostnameService("service1"), ns, numPods) Expect(err).NotTo(HaveOccurred()) hosts, err := framework.NodeSSHHosts(cs) @@ -439,9 +453,9 @@ var _ = SIGDescribe("Services", func() { // Create a new service and check if it's not reusing IP. defer func() { - framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, f.InternalClientset, ns, "service2")) + framework.ExpectNoError(framework.StopServeHostnameService(f.ClientSet, ns, "service2")) }() - podNames2, svc2IP, err := framework.StartServeHostnameService(cs, internalClientset, ns, "service2", servicePort, numPods) + podNames2, svc2IP, err := framework.StartServeHostnameService(cs, internalClientset, getServeHostnameService("service2"), ns, numPods) Expect(err).NotTo(HaveOccurred()) if svc1IP == svc2IP { @@ -485,7 +499,7 @@ var _ = SIGDescribe("Services", func() { } }) - // TODO: Get rid of [DisabledForLargeClusters] tag when issue #52495 is fixed. + // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed. It("should be able to change the type and ports of a service [Slow] [DisabledForLargeClusters]", func() { // requires cloud load-balancer support framework.SkipUnlessProviderIs("gce", "gke", "aws") @@ -1276,7 +1290,7 @@ var _ = SIGDescribe("Services", func() { } By("Scaling down replication controller to zero") - framework.ScaleRC(f.ClientSet, f.InternalClientset, f.ScalesGetter, t.Namespace, rcSpec.Name, 0, false) + framework.ScaleRC(f.ClientSet, f.ScalesGetter, t.Namespace, rcSpec.Name, 0, false) By("Update service to not tolerate unready services") _, err = framework.UpdateService(f.ClientSet, t.Namespace, t.ServiceName, func(s *v1.Service) { @@ -1412,7 +1426,7 @@ var _ = SIGDescribe("Services", func() { framework.CheckReachabilityFromPod(true, normalReachabilityTimeout, namespace, dropPodName, svcIP) }) - // TODO: Get rid of [DisabledForLargeClusters] tag when issue #52495 is fixed. + // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed. It("should be able to create an internal type load balancer [Slow] [DisabledForLargeClusters]", func() { framework.SkipUnlessProviderIs("azure", "gke", "gce") @@ -1529,9 +1543,65 @@ var _ = SIGDescribe("Services", func() { By("switching to ClusterIP type to destroy loadbalancer") jig.ChangeServiceType(svc.Namespace, svc.Name, v1.ServiceTypeClusterIP, createTimeout) }) + + It("should have session affinity work for service with type clusterIP", func() { + svc := getServeHostnameService("service") + svc.Spec.Type = v1.ServiceTypeClusterIP + execAffinityTestForNonLBService(f, cs, svc, false) + }) + + It("should be able to switch session affinity for service with type clusterIP", func() { + svc := getServeHostnameService("service") + svc.Spec.Type = v1.ServiceTypeClusterIP + execAffinityTestForNonLBService(f, cs, svc, true) + }) + + It("should have session affinity work for NodePort service", func() { + svc := getServeHostnameService("service") + svc.Spec.Type = v1.ServiceTypeNodePort + execAffinityTestForNonLBService(f, cs, svc, false) + }) + + It("should be able to switch session affinity for NodePort service", func() { + svc := getServeHostnameService("service") + svc.Spec.Type = v1.ServiceTypeNodePort + execAffinityTestForNonLBService(f, cs, svc, true) + }) + + // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed. + It("should have session affinity work for LoadBalancer service with ESIPP on [Slow] [DisabledForLargeClusters]", func() { + svc := getServeHostnameService("service") + svc.Spec.Type = v1.ServiceTypeLoadBalancer + svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal + execAffinityTestForLBService(f, cs, svc, false) + }) + + // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed. + It("should be able to switch session affinity for LoadBalancer service with ESIPP on [Slow] [DisabledForLargeClusters]", func() { + svc := getServeHostnameService("service") + svc.Spec.Type = v1.ServiceTypeLoadBalancer + svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal + execAffinityTestForLBService(f, cs, svc, true) + }) + + // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed. + It("should have session affinity work for LoadBalancer service with ESIPP off [Slow] [DisabledForLargeClusters]", func() { + svc := getServeHostnameService("service") + svc.Spec.Type = v1.ServiceTypeLoadBalancer + svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster + execAffinityTestForLBService(f, cs, svc, false) + }) + + // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed. + It("should be able to switch session affinity for LoadBalancer service with ESIPP off [Slow] [DisabledForLargeClusters]", func() { + svc := getServeHostnameService("service") + svc.Spec.Type = v1.ServiceTypeLoadBalancer + svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster + execAffinityTestForLBService(f, cs, svc, true) + }) }) -// TODO: Get rid of [DisabledForLargeClusters] tag when issue #52495 is fixed. +// TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed. var _ = SIGDescribe("ESIPP [Slow] [DisabledForLargeClusters]", func() { f := framework.NewDefaultFramework("esipp") loadBalancerCreateTimeout := framework.LoadBalancerCreateTimeoutDefault @@ -1683,7 +1753,7 @@ var _ = SIGDescribe("ESIPP [Slow] [DisabledForLargeClusters]", func() { framework.Logf("Health checking %s, http://%s%s, expectedSuccess %v", nodes.Items[n].Name, ipPort, path, expectedSuccess) Expect(jig.TestHTTPHealthCheckNodePort(publicIP, healthCheckNodePort, path, framework.KubeProxyEndpointLagTimeout, expectedSuccess, threshold)).NotTo(HaveOccurred()) } - framework.ExpectNoError(framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, namespace, serviceName)) + framework.ExpectNoError(framework.DeleteRCAndWaitForGC(f.ClientSet, namespace, serviceName)) } }) @@ -1858,7 +1928,7 @@ func execSourceipTest(f *framework.Framework, c clientset.Interface, ns, nodeNam timeout := 2 * time.Minute framework.Logf("Waiting up to %v wget %s", timeout, serviceIPPort) cmd := fmt.Sprintf(`wget -T 30 -qO- %s | grep client_address`, serviceIPPort) - for start := time.Now(); time.Since(start) < timeout; time.Sleep(2) { + for start := time.Now(); time.Since(start) < timeout; time.Sleep(2 * time.Second) { stdout, err = framework.RunHostCmd(execPod.Namespace, execPod.Name, cmd) if err != nil { framework.Logf("got err: %v, retry until timeout", err) @@ -1883,3 +1953,95 @@ func execSourceipTest(f *framework.Framework, c clientset.Interface, ns, nodeNam } return execPod.Status.PodIP, outputs[1] } + +// execAffinityTestForNonLBService is a helper function that wrap the logic of +// affinity test for non-load-balancer services. Session afinity will be +// enabled when the service is created. If parameter isTransitionTest is true, +// session affinity will be switched off/on and test if the service converges +// to a stable affinity state. +func execAffinityTestForNonLBService(f *framework.Framework, cs clientset.Interface, svc *v1.Service, isTransitionTest bool) { + ns := f.Namespace.Name + numPods, servicePort, serviceName := 3, defaultServeHostnameServicePort, svc.ObjectMeta.Name + By("creating service in namespace " + ns) + serviceType := svc.Spec.Type + svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP + _, _, err := framework.StartServeHostnameService(cs, f.InternalClientset, svc, ns, numPods) + Expect(err).NotTo(HaveOccurred()) + defer func() { + framework.StopServeHostnameService(cs, ns, serviceName) + }() + jig := framework.NewServiceTestJig(cs, serviceName) + svc, err = jig.Client.CoreV1().Services(ns).Get(serviceName, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + var svcIp string + if serviceType == v1.ServiceTypeNodePort { + nodes := framework.GetReadySchedulableNodesOrDie(cs) + addrs := framework.CollectAddresses(nodes, v1.NodeInternalIP) + Expect(len(addrs)).To(BeNumerically(">", 0), "Failed to get Node internal IP") + svcIp = addrs[0] + servicePort = int(svc.Spec.Ports[0].NodePort) + } else { + svcIp = svc.Spec.ClusterIP + } + + execPodName := framework.CreateExecPodOrFail(cs, ns, "execpod-affinity", nil) + defer func() { + framework.Logf("Cleaning up the exec pod") + err := cs.CoreV1().Pods(ns).Delete(execPodName, nil) + Expect(err).NotTo(HaveOccurred()) + }() + execPod, err := cs.CoreV1().Pods(ns).Get(execPodName, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + + if !isTransitionTest { + Expect(framework.CheckAffinity(jig, execPod, svcIp, servicePort, true, false)).To(BeTrue()) + } + if isTransitionTest { + svc = jig.UpdateServiceOrFail(svc.Namespace, svc.Name, func(svc *v1.Service) { + svc.Spec.SessionAffinity = v1.ServiceAffinityNone + }) + Expect(framework.CheckAffinity(jig, execPod, svcIp, servicePort, false, true)).To(BeTrue()) + svc = jig.UpdateServiceOrFail(svc.Namespace, svc.Name, func(svc *v1.Service) { + svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP + }) + Expect(framework.CheckAffinity(jig, execPod, svcIp, servicePort, true, true)).To(BeTrue()) + } +} + +// execAffinityTestForLBService is a helper function that wrap the logic of +// affinity test for load balancer services, similar to +// execAffinityTestForNonLBService. +func execAffinityTestForLBService(f *framework.Framework, cs clientset.Interface, svc *v1.Service, isTransitionTest bool) { + numPods, ns, serviceName := 3, f.Namespace.Name, svc.ObjectMeta.Name + + By("creating service in namespace " + ns) + svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP + _, _, err := framework.StartServeHostnameService(cs, f.InternalClientset, svc, ns, numPods) + Expect(err).NotTo(HaveOccurred()) + jig := framework.NewServiceTestJig(cs, serviceName) + By("waiting for loadbalancer for service " + ns + "/" + serviceName) + svc = jig.WaitForLoadBalancerOrFail(ns, serviceName, framework.LoadBalancerCreateTimeoutDefault) + jig.SanityCheckService(svc, v1.ServiceTypeLoadBalancer) + defer func() { + framework.StopServeHostnameService(cs, ns, serviceName) + lb := cloudprovider.GetLoadBalancerName(svc) + framework.Logf("cleaning gce resource for %s", lb) + framework.CleanupServiceGCEResources(cs, lb, framework.TestContext.CloudConfig.Region, framework.TestContext.CloudConfig.Zone) + }() + ingressIP := framework.GetIngressPoint(&svc.Status.LoadBalancer.Ingress[0]) + port := int(svc.Spec.Ports[0].Port) + + if !isTransitionTest { + Expect(framework.CheckAffinity(jig, nil, ingressIP, port, true, false)).To(BeTrue()) + } + if isTransitionTest { + svc = jig.UpdateServiceOrFail(svc.Namespace, svc.Name, func(svc *v1.Service) { + svc.Spec.SessionAffinity = v1.ServiceAffinityNone + }) + Expect(framework.CheckAffinity(jig, nil, ingressIP, port, false, true)).To(BeTrue()) + svc = jig.UpdateServiceOrFail(svc.Namespace, svc.Name, func(svc *v1.Service) { + svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP + }) + Expect(framework.CheckAffinity(jig, nil, ingressIP, port, true, true)).To(BeTrue()) + } +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/network/service_latency.go b/vendor/k8s.io/kubernetes/test/e2e/network/service_latency.go index 136c178d6..4ef25a426 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/network/service_latency.go +++ b/vendor/k8s.io/kubernetes/test/e2e/network/service_latency.go @@ -32,6 +32,7 @@ import ( "k8s.io/client-go/util/flowcontrol" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" ) @@ -127,7 +128,7 @@ func runServiceLatencies(f *framework.Framework, inParallel, total int) (output cfg := testutils.RCConfig{ Client: f.ClientSet, InternalClient: f.InternalClientset, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Name: "svc-latency-rc", Namespace: f.Namespace.Name, Replicas: 1, diff --git a/vendor/k8s.io/kubernetes/test/e2e/node/BUILD b/vendor/k8s.io/kubernetes/test/e2e/node/BUILD index 2fa827558..88305fc43 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/node/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/node/BUILD @@ -18,7 +18,6 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e/node", visibility = ["//visibility:public"], deps = [ - "//pkg/api/testapi:go_default_library", "//pkg/kubelet/apis/stats/v1alpha1:go_default_library", "//test/e2e/common:go_default_library", "//test/e2e/framework:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e/node/kubelet.go b/vendor/k8s.io/kubernetes/test/e2e/node/kubelet.go index 8076d2ae5..1953681a6 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/node/kubelet.go +++ b/vendor/k8s.io/kubernetes/test/e2e/node/kubelet.go @@ -28,9 +28,9 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -123,7 +123,7 @@ func createPodUsingNfs(f *framework.Framework, c clientset.Interface, ns, nfsIP, pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ GenerateName: "pod-nfs-vol-", @@ -319,7 +319,7 @@ var _ = SIGDescribe("kubelet", func() { InternalClient: f.InternalClientset, Name: rcName, Namespace: f.Namespace.Name, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: totalPods, NodeSelector: nodeLabels, })).NotTo(HaveOccurred()) @@ -334,7 +334,7 @@ var _ = SIGDescribe("kubelet", func() { } By("Deleting the RC") - framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, rcName) + framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, rcName) // Check that the pods really are gone by querying /runningpods on the // node. The /runningpods handler checks the container runtime (or its // cache) and returns a list of running pods. Some possible causes of diff --git a/vendor/k8s.io/kubernetes/test/e2e/node/kubelet_perf.go b/vendor/k8s.io/kubernetes/test/e2e/node/kubelet_perf.go index 8f54434b5..029155da6 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/node/kubelet_perf.go +++ b/vendor/k8s.io/kubernetes/test/e2e/node/kubelet_perf.go @@ -28,6 +28,7 @@ import ( stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -74,7 +75,7 @@ func runResourceTrackingTest(f *framework.Framework, podsPerNode int, nodeNames InternalClient: f.InternalClientset, Name: rcName, Namespace: f.Namespace.Name, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: totalPods, })).NotTo(HaveOccurred()) @@ -117,7 +118,7 @@ func runResourceTrackingTest(f *framework.Framework, podsPerNode int, nodeNames verifyCPULimits(expectedCPU, cpuSummary) By("Deleting the RC") - framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, rcName) + framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, rcName) } func verifyMemoryLimits(c clientset.Interface, expected framework.ResourceUsagePerContainer, actual framework.ResourceUsagePerNode) { diff --git a/vendor/k8s.io/kubernetes/test/e2e/node/pods.go b/vendor/k8s.io/kubernetes/test/e2e/node/pods.go index 080fe1d4d..ad5031818 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/node/pods.go +++ b/vendor/k8s.io/kubernetes/test/e2e/node/pods.go @@ -166,7 +166,7 @@ var _ = SIGDescribe("Pods Extended", func() { deleted := false timeout := false var lastPod *v1.Pod - timer := time.After(1 * time.Minute) + timer := time.After(2 * time.Minute) for !deleted && !timeout { select { case event, _ := <-w.ResultChan(): diff --git a/vendor/k8s.io/kubernetes/test/e2e/node/security_context.go b/vendor/k8s.io/kubernetes/test/e2e/node/security_context.go index 08d5e13e7..d9cab6a21 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/node/security_context.go +++ b/vendor/k8s.io/kubernetes/test/e2e/node/security_context.go @@ -144,7 +144,7 @@ var _ = SIGDescribe("Security Context [Feature:SecurityContext]", func() { // TODO: port to SecurityContext as soon as seccomp is out of alpha pod := scTestPod(false, false) pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+"test-container"] = "unconfined" - pod.Annotations[v1.SeccompPodAnnotationKey] = "docker/default" + pod.Annotations[v1.SeccompPodAnnotationKey] = v1.SeccompProfileRuntimeDefault pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"} f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled }) @@ -157,10 +157,10 @@ var _ = SIGDescribe("Security Context [Feature:SecurityContext]", func() { f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled }) - It("should support seccomp alpha docker/default annotation [Feature:Seccomp]", func() { + It("should support seccomp alpha runtime/default annotation [Feature:Seccomp]", func() { // TODO: port to SecurityContext as soon as seccomp is out of alpha pod := scTestPod(false, false) - pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+"test-container"] = "docker/default" + pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+"test-container"] = v1.SeccompProfileRuntimeDefault pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"} f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"2"}) // seccomp filtered }) diff --git a/vendor/k8s.io/kubernetes/test/e2e/scalability/BUILD b/vendor/k8s.io/kubernetes/test/e2e/scalability/BUILD index e8185d028..11238a2f2 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scalability/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/scalability/BUILD @@ -19,10 +19,10 @@ go_library( "//test/e2e/framework:go_default_library", "//test/e2e/framework/timer:go_default_library", "//test/utils:go_default_library", + "//test/utils/image:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta: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/fields:go_default_library", @@ -39,6 +39,7 @@ go_library( "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", "//vendor/k8s.io/client-go/scale:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/transport:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e/scalability/density.go b/vendor/k8s.io/kubernetes/test/e2e/scalability/density.go index 1dd388222..30df63e7a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scalability/density.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scalability/density.go @@ -35,6 +35,7 @@ import ( utiluuid "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/watch" clientset "k8s.io/client-go/kubernetes" + scaleclient "k8s.io/client-go/scale" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" "k8s.io/kubernetes/pkg/apis/batch" @@ -44,12 +45,14 @@ import ( "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework/timer" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) const ( + PodStartupLatencyThreshold = 5 * time.Second MinSaturationThreshold = 2 * time.Minute MinPodsPerSecondThroughput = 8 DensityPollInterval = 10 * time.Second @@ -65,6 +68,7 @@ type DensityTestConfig struct { Configs []testutils.RunObjectConfig ClientSets []clientset.Interface InternalClientsets []internalclientset.Interface + ScaleClients []scaleclient.ScalesGetter PollInterval time.Duration PodCount int // What kind of resource we want to create @@ -112,9 +116,8 @@ func (dtc *DensityTestConfig) deleteConfigMaps(testPhase *timer.Phase) { func (dtc *DensityTestConfig) deleteDaemonSets(numberOfClients int, testPhase *timer.Phase) { defer testPhase.End() for i := range dtc.DaemonConfigs { - framework.ExpectNoError(framework.DeleteResourceAndPods( + framework.ExpectNoError(framework.DeleteResourceAndWaitForGC( dtc.ClientSets[i%numberOfClients], - dtc.InternalClientsets[i%numberOfClients], extensions.Kind("DaemonSet"), dtc.DaemonConfigs[i].Namespace, dtc.DaemonConfigs[i].Name, @@ -219,32 +222,60 @@ func density30AddonResourceVerifier(numNodes int) map[string]framework.ResourceC return constraints } -func logPodStartupStatus(c clientset.Interface, expectedPods int, observedLabels map[string]string, period time.Duration, stopCh chan struct{}) { +func computeAverage(sample []float64) float64 { + sum := 0.0 + for _, value := range sample { + sum += value + } + return sum / float64(len(sample)) +} + +func computeQuantile(sample []float64, quantile float64) float64 { + Expect(sort.Float64sAreSorted(sample)).To(Equal(true)) + Expect(quantile >= 0.0 && quantile <= 1.0).To(Equal(true)) + index := int(quantile*float64(len(sample))) - 1 + if index < 0 { + return math.NaN() + } + return sample[index] +} + +func logPodStartupStatus( + c clientset.Interface, + expectedPods int, + observedLabels map[string]string, + period time.Duration, + scheduleThroughputs *[]float64, + stopCh chan struct{}) { + label := labels.SelectorFromSet(labels.Set(observedLabels)) podStore, err := testutils.NewPodStore(c, metav1.NamespaceAll, label, fields.Everything()) framework.ExpectNoError(err) defer podStore.Stop() ticker := time.NewTicker(period) + startupStatus := testutils.ComputeRCStartupStatus(podStore.List(), expectedPods) + lastScheduledCount := startupStatus.Scheduled defer ticker.Stop() for { select { case <-ticker.C: - pods := podStore.List() - startupStatus := testutils.ComputeRCStartupStatus(pods, expectedPods) - framework.Logf(startupStatus.String("Density")) case <-stopCh: - pods := podStore.List() - startupStatus := testutils.ComputeRCStartupStatus(pods, expectedPods) - framework.Logf(startupStatus.String("Density")) return } + // Log status of the pods. + startupStatus := testutils.ComputeRCStartupStatus(podStore.List(), expectedPods) + framework.Logf(startupStatus.String("Density")) + // Compute scheduling throughput for the latest time period. + throughput := float64(startupStatus.Scheduled-lastScheduledCount) / float64(period/time.Second) + *scheduleThroughputs = append(*scheduleThroughputs, throughput) + lastScheduledCount = startupStatus.Scheduled } } // runDensityTest will perform a density test and return the time it took for // all pods to start -func runDensityTest(dtc DensityTestConfig, testPhaseDurations *timer.TestPhaseTimer) time.Duration { +func runDensityTest(dtc DensityTestConfig, testPhaseDurations *timer.TestPhaseTimer, scheduleThroughputs *[]float64) time.Duration { defer GinkgoRecover() // Create all secrets, configmaps and daemons. @@ -269,9 +300,9 @@ func runDensityTest(dtc DensityTestConfig, testPhaseDurations *timer.TestPhaseTi }() } logStopCh := make(chan struct{}) - go logPodStartupStatus(dtc.ClientSets[0], dtc.PodCount, map[string]string{"type": "densityPod"}, dtc.PollInterval, logStopCh) + go logPodStartupStatus(dtc.ClientSets[0], dtc.PodCount, map[string]string{"type": "densityPod"}, dtc.PollInterval, scheduleThroughputs, logStopCh) wg.Wait() - startupTime := time.Now().Sub(startTime) + startupTime := time.Since(startTime) close(logStopCh) framework.Logf("E2E startup time for %d pods: %v", dtc.PodCount, startupTime) framework.Logf("Throughput (pods/s) during cluster saturation phase: %v", float32(dtc.PodCount)/float32(startupTime/time.Second)) @@ -315,15 +346,9 @@ func cleanupDensityTest(dtc DensityTestConfig, testPhaseDurations *timer.TestPha name := dtc.Configs[i].GetName() namespace := dtc.Configs[i].GetNamespace() kind := dtc.Configs[i].GetKind() - if framework.TestContext.GarbageCollectorEnabled && kindSupportsGarbageCollector(kind) { - By(fmt.Sprintf("Cleaning up only the %v, garbage collector will clean up the pods", kind)) - err := framework.DeleteResourceAndWaitForGC(dtc.ClientSets[i%numberOfClients], kind, namespace, name) - framework.ExpectNoError(err) - } else { - By(fmt.Sprintf("Cleaning up the %v and pods", kind)) - err := framework.DeleteResourceAndPods(dtc.ClientSets[i%numberOfClients], dtc.InternalClientsets[i%numberOfClients], kind, namespace, name) - framework.ExpectNoError(err) - } + By(fmt.Sprintf("Cleaning up only the %v, garbage collector will clean up the pods", kind)) + err := framework.DeleteResourceAndWaitForGC(dtc.ClientSets[i%numberOfClients], kind, namespace, name) + framework.ExpectNoError(err) } podCleanupPhase.End() @@ -350,6 +375,7 @@ var _ = SIGDescribe("Density", func() { var nodeCpuCapacity int64 var nodeMemCapacity int64 var nodes *v1.NodeList + var scheduleThroughputs []float64 testCaseBaseName := "density" missingMeasurements := 0 @@ -384,21 +410,30 @@ var _ = SIGDescribe("Density", func() { framework.ExpectNoError(err) if err == nil { summaries = append(summaries, metrics) - Expect(highLatencyRequests).NotTo(BeNumerically(">", 0), "There should be no high-latency requests") } // Verify scheduler metrics. - // TODO: Reset metrics at the beginning of the test. - // We should do something similar to how we do it for APIserver. latency, err := framework.VerifySchedulerLatency(c) framework.ExpectNoError(err) if err == nil { + // Compute avg and quantiles of throughput (excluding last element, that's usually an outlier). + sampleSize := len(scheduleThroughputs) + if sampleSize > 1 { + scheduleThroughputs = scheduleThroughputs[:sampleSize-1] + sort.Float64s(scheduleThroughputs) + latency.ThroughputAverage = computeAverage(scheduleThroughputs) + latency.ThroughputPerc50 = computeQuantile(scheduleThroughputs, 0.5) + latency.ThroughputPerc90 = computeQuantile(scheduleThroughputs, 0.9) + latency.ThroughputPerc99 = computeQuantile(scheduleThroughputs, 0.99) + } summaries = append(summaries, latency) } summaries = append(summaries, testPhaseDurations) framework.PrintSummaries(summaries, testCaseBaseName) + // Fail if there were some high-latency requests. + Expect(highLatencyRequests).NotTo(BeNumerically(">", 0), "There should be no high-latency requests") // Fail if more than the allowed threshold of measurements were missing in the latencyTest. Expect(missingMeasurements <= MaxMissingPodStartupMeasurements).To(Equal(true)) }) @@ -432,6 +467,7 @@ var _ = SIGDescribe("Density", func() { uuid = string(utiluuid.NewUUID()) + framework.ExpectNoError(framework.ResetSchedulerMetrics(c)) framework.ExpectNoError(framework.ResetMetrics(c)) framework.ExpectNoError(os.Mkdir(fmt.Sprintf(framework.TestContext.OutputDir+"/%s", uuid), 0777)) @@ -583,7 +619,7 @@ var _ = SIGDescribe("Density", func() { Client: clients[i], InternalClient: internalClients[i], ScalesGetter: scalesClients[i], - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Name: name, Namespace: nsName, Labels: map[string]string{"type": "densityPod"}, @@ -614,11 +650,12 @@ var _ = SIGDescribe("Density", func() { } // Single client is running out of http2 connections in delete phase, hence we need more. - clients, internalClients, _, err = createClients(2) + clients, internalClients, scalesClients, err = createClients(2) dConfig := DensityTestConfig{ ClientSets: clients, InternalClientsets: internalClients, + ScaleClients: scalesClients, Configs: configs, PodCount: totalPods, PollInterval: DensityPollInterval, @@ -636,7 +673,7 @@ var _ = SIGDescribe("Density", func() { LogFunc: framework.Logf, }) } - e2eStartupTime = runDensityTest(dConfig, testPhaseDurations) + e2eStartupTime = runDensityTest(dConfig, testPhaseDurations, &scheduleThroughputs) if itArg.runLatencyTest { By("Scheduling additional Pods to measure startup latencies") @@ -740,7 +777,7 @@ var _ = SIGDescribe("Density", func() { name := additionalPodsPrefix + "-" + strconv.Itoa(i) nsName := namespaces[i%len(namespaces)].Name rcNameToNsMap[name] = nsName - go createRunningPodFromRC(&wg, c, name, nsName, framework.GetPauseImageName(f.ClientSet), additionalPodsPrefix, cpuRequest, memRequest) + go createRunningPodFromRC(&wg, c, name, nsName, imageutils.GetPauseImageName(), additionalPodsPrefix, cpuRequest, memRequest) time.Sleep(200 * time.Millisecond) } wg.Wait() @@ -831,16 +868,29 @@ var _ = SIGDescribe("Density", func() { sort.Sort(framework.LatencySlice(schedToWatchLag)) sort.Sort(framework.LatencySlice(e2eLag)) - framework.PrintLatencies(scheduleLag, "worst schedule latencies") - framework.PrintLatencies(startupLag, "worst run-after-schedule latencies") - framework.PrintLatencies(watchLag, "worst watch latencies") - framework.PrintLatencies(schedToWatchLag, "worst scheduled-to-end total latencies") - framework.PrintLatencies(e2eLag, "worst e2e total latencies") + framework.PrintLatencies(scheduleLag, "worst create-to-schedule latencies") + framework.PrintLatencies(startupLag, "worst schedule-to-run latencies") + framework.PrintLatencies(watchLag, "worst run-to-watch latencies") + framework.PrintLatencies(schedToWatchLag, "worst schedule-to-watch latencies") + framework.PrintLatencies(e2eLag, "worst e2e latencies") + + // Capture latency metrics related to pod-startup. + podStartupLatency := &framework.PodStartupLatency{ + CreateToScheduleLatency: framework.ExtractLatencyMetrics(scheduleLag), + ScheduleToRunLatency: framework.ExtractLatencyMetrics(startupLag), + RunToWatchLatency: framework.ExtractLatencyMetrics(watchLag), + ScheduleToWatchLatency: framework.ExtractLatencyMetrics(schedToWatchLag), + E2ELatency: framework.ExtractLatencyMetrics(e2eLag), + } + f.TestSummaries = append(f.TestSummaries, podStartupLatency) // Test whether e2e pod startup time is acceptable. - podStartupLatency := &framework.PodStartupLatency{Latency: framework.ExtractLatencyMetrics(e2eLag)} - f.TestSummaries = append(f.TestSummaries, podStartupLatency) - framework.ExpectNoError(framework.VerifyPodStartupLatency(podStartupLatency)) + podStartupLatencyThreshold := framework.LatencyMetric{ + Perc50: PodStartupLatencyThreshold, + Perc90: PodStartupLatencyThreshold, + Perc99: PodStartupLatencyThreshold, + } + framework.ExpectNoError(framework.VerifyLatencyWithinThreshold(podStartupLatencyThreshold, podStartupLatency.E2ELatency, "pod startup")) framework.LogSuspiciousLatency(startupLag, e2eLag, nodeCount, c) latencyMeasurementPhase.End() @@ -902,7 +952,3 @@ func createRunningPodFromRC(wg *sync.WaitGroup, c clientset.Interface, name, ns, framework.ExpectNoError(framework.WaitForControlledPodsRunning(c, ns, name, api.Kind("ReplicationController"))) framework.Logf("Found pod '%s' running", name) } - -func kindSupportsGarbageCollector(kind schema.GroupKind) bool { - return kind != extensions.Kind("Deployment") && kind != batch.Kind("Job") -} diff --git a/vendor/k8s.io/kubernetes/test/e2e/scalability/empty.go b/vendor/k8s.io/kubernetes/test/e2e/scalability/empty.go index 94987ec0c..3e8032756 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scalability/empty.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scalability/empty.go @@ -22,6 +22,7 @@ import ( "k8s.io/api/core/v1" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/test/e2e/framework" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" ) @@ -42,7 +43,7 @@ var _ = SIGDescribe("Empty [Feature:Empty]", func() { }) It("starts a pod", func() { - configs, _, _ := GenerateConfigsForGroup([]*v1.Namespace{f.Namespace}, "empty-pod", 1, 1, framework.GetPauseImageName(f.ClientSet), []string{}, api.Kind("ReplicationController"), 0, 0) + configs, _, _ := GenerateConfigsForGroup([]*v1.Namespace{f.Namespace}, "empty-pod", 1, 1, imageutils.GetPauseImageName(), []string{}, api.Kind("ReplicationController"), 0, 0) if len(configs) != 1 { framework.Failf("generateConfigs should have generated single config") } diff --git a/vendor/k8s.io/kubernetes/test/e2e/scalability/load.go b/vendor/k8s.io/kubernetes/test/e2e/scalability/load.go index a717929c8..5dadeed36 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scalability/load.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scalability/load.go @@ -28,7 +28,6 @@ import ( "time" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -54,6 +53,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "k8s.io/client-go/dynamic" + "k8s.io/client-go/restmapper" "k8s.io/kubernetes/pkg/api/legacyscheme" ) @@ -286,9 +286,8 @@ var _ = SIGDescribe("Load capacity", func() { } daemonConfig.Run() defer func(config *testutils.DaemonConfig) { - framework.ExpectNoError(framework.DeleteResourceAndPods( + framework.ExpectNoError(framework.DeleteResourceAndWaitForGC( f.ClientSet, - f.InternalClientset, extensions.Kind("DaemonSet"), config.Namespace, config.Name, @@ -372,10 +371,10 @@ func createClients(numberOfClients int) ([]clientset.Interface, []internalclient TLSHandshakeTimeout: 10 * time.Second, TLSClientConfig: tlsConfig, MaxIdleConnsPerHost: 100, - Dial: (&net.Dialer{ + DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, - }).Dial, + }).DialContext, }) // Overwrite TLS-related fields from config to avoid collision with // Transport field. @@ -409,7 +408,7 @@ func createClients(numberOfClients int) ([]clientset.Interface, []internalclient return nil, nil, nil, err } cachedDiscoClient := cacheddiscovery.NewMemCacheClient(discoClient) - restMapper := discovery.NewDeferredDiscoveryRESTMapper(cachedDiscoClient, meta.InterfacesForUnstructured) + restMapper := restmapper.NewDeferredDiscoveryRESTMapper(cachedDiscoClient) restMapper.Reset() resolver := scaleclient.NewDiscoveryScaleKindResolver(cachedDiscoClient) scalesClients[i] = scaleclient.New(restClient, restMapper, dynamic.LegacyAPIPathResolverFunc, resolver) @@ -648,7 +647,6 @@ func scaleResource(wg *sync.WaitGroup, config testutils.RunObjectConfig, scaling newSize := uint(rand.Intn(config.GetReplicas()) + config.GetReplicas()/2) framework.ExpectNoError(framework.ScaleResource( config.GetClient(), - config.GetInternalClient(), config.GetScalesGetter(), config.GetNamespace(), config.GetName(), @@ -694,15 +692,9 @@ func deleteResource(wg *sync.WaitGroup, config testutils.RunObjectConfig, deleti defer wg.Done() sleepUpTo(deletingTime) - if framework.TestContext.GarbageCollectorEnabled && config.GetKind() != extensions.Kind("Deployment") { - framework.ExpectNoError(framework.DeleteResourceAndWaitForGC( - config.GetClient(), config.GetKind(), config.GetNamespace(), config.GetName()), - fmt.Sprintf("deleting %v %s", config.GetKind(), config.GetName())) - } else { - framework.ExpectNoError(framework.DeleteResourceAndPods( - config.GetClient(), config.GetInternalClient(), config.GetKind(), config.GetNamespace(), config.GetName()), - fmt.Sprintf("deleting %v %s", config.GetKind(), config.GetName())) - } + framework.ExpectNoError(framework.DeleteResourceAndWaitForGC( + config.GetClient(), config.GetKind(), config.GetNamespace(), config.GetName()), + fmt.Sprintf("deleting %v %s", config.GetKind(), config.GetName())) } func CreateNamespaces(f *framework.Framework, namespaceCount int, namePrefix string, testPhase *timer.Phase) ([]*v1.Namespace, error) { diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/BUILD b/vendor/k8s.io/kubernetes/test/e2e/scheduling/BUILD index 9ee187223..f149eec66 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/BUILD @@ -22,10 +22,10 @@ go_library( "//pkg/api/v1/pod:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/extensions:go_default_library", + "//pkg/apis/scheduling:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/quota/evaluator/core:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", - "//pkg/scheduler/api:go_default_library", "//pkg/util/version:go_default_library", "//test/e2e/common:go_default_library", "//test/e2e/framework:go_default_library", @@ -37,7 +37,7 @@ go_library( "//vendor/google.golang.org/api/compute/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_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", diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/equivalence_cache_predicates.go b/vendor/k8s.io/kubernetes/test/e2e/scheduling/equivalence_cache_predicates.go index 594ad1b37..d55cabc03 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/equivalence_cache_predicates.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/equivalence_cache_predicates.go @@ -28,6 +28,7 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -92,7 +93,7 @@ var _ = framework.KubeDescribe("EquivalenceCache [Serial]", func() { err := CreateNodeSelectorPods(f, rcName, 2, nodeSelector, false) return err }, ns, rcName, false) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, ns, rcName) + defer framework.DeleteRCAndWaitForGC(f.ClientSet, ns, rcName) // the first replica pod is scheduled, and the second pod will be rejected. verifyResult(cs, 1, 1, ns) }) @@ -139,8 +140,8 @@ var _ = framework.KubeDescribe("EquivalenceCache [Serial]", func() { }, }, } - rc := getRCWithInterPodAffinity(affinityRCName, labelsMap, replica, affinity, framework.GetPauseImageName(f.ClientSet)) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, ns, affinityRCName) + rc := getRCWithInterPodAffinity(affinityRCName, labelsMap, replica, affinity, imageutils.GetPauseImageName()) + defer framework.DeleteRCAndWaitForGC(f.ClientSet, ns, affinityRCName) // RC should be running successfully // TODO: WaitForSchedulerAfterAction() can on be used to wait for failure event, @@ -155,7 +156,7 @@ var _ = framework.KubeDescribe("EquivalenceCache [Serial]", func() { By("Trying to schedule another equivalent Pod should fail due to node label has been removed.") // use scale to create another equivalent pod and wait for failure event WaitForSchedulerAfterAction(f, func() error { - err := framework.ScaleRC(f.ClientSet, f.InternalClientset, f.ScalesGetter, ns, affinityRCName, uint(replica+1), false) + err := framework.ScaleRC(f.ClientSet, f.ScalesGetter, ns, affinityRCName, uint(replica+1), false) return err }, ns, affinityRCName, false) // and this new pod should be rejected since node label has been updated @@ -166,7 +167,7 @@ var _ = framework.KubeDescribe("EquivalenceCache [Serial]", func() { It("validates pod anti-affinity works properly when new replica pod is scheduled", func() { By("Launching two pods on two distinct nodes to get two node names") CreateHostPortPods(f, "host-port", 2, true) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, ns, "host-port") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, ns, "host-port") podList, err := cs.CoreV1().Pods(ns).List(metav1.ListOptions{}) framework.ExpectNoError(err) Expect(len(podList.Items)).To(Equal(2)) @@ -216,8 +217,8 @@ var _ = framework.KubeDescribe("EquivalenceCache [Serial]", func() { }, } rc := getRCWithInterPodAffinityNodeSelector(labelRCName, labelsMap, replica, affinity, - framework.GetPauseImageName(f.ClientSet), map[string]string{k: v}) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, ns, labelRCName) + imageutils.GetPauseImageName(), map[string]string{k: v}) + defer framework.DeleteRCAndWaitForGC(f.ClientSet, ns, labelRCName) WaitForSchedulerAfterAction(f, func() error { _, err := cs.CoreV1().ReplicationControllers(ns).Create(rc) @@ -273,7 +274,7 @@ func CreateNodeSelectorPods(f *framework.Framework, id string, replicas int, nod Name: id, Namespace: f.Namespace.Name, Timeout: defaultTimeout, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: replicas, HostPorts: map[string]int{"port1": 4321}, NodeSelector: nodeSelector, diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/events.go b/vendor/k8s.io/kubernetes/test/e2e/scheduling/events.go index eba64f35d..df55b4058 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/events.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/events.go @@ -28,10 +28,7 @@ func scheduleSuccessEvent(ns, podName, nodeName string) func(*v1.Event) bool { return e.Type == v1.EventTypeNormal && e.Reason == "Scheduled" && strings.HasPrefix(e.Name, podName) && - // Check event message for 1.11+ (1.11 included) - (strings.Contains(e.Message, fmt.Sprintf("Successfully assigned %v/%v to %v", ns, podName, nodeName)) || - // Check event message for 1.10- (1.10 included) - strings.Contains(e.Message, fmt.Sprintf("Successfully assigned %v to %v", podName, nodeName))) + strings.Contains(e.Message, fmt.Sprintf("Successfully assigned %v/%v to %v", ns, podName, nodeName)) } } diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/nvidia-gpus.go b/vendor/k8s.io/kubernetes/test/e2e/scheduling/nvidia-gpus.go index c35b7a7fe..fc337a67e 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/nvidia-gpus.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/nvidia-gpus.go @@ -18,7 +18,6 @@ package scheduling import ( "os" - "strings" "time" "k8s.io/api/core/v1" @@ -35,59 +34,15 @@ import ( const ( testPodNamePrefix = "nvidia-gpu-" - cosOSImage = "Container-Optimized OS from Google" // Nvidia driver installation can take upwards of 5 minutes. driverInstallTimeout = 10 * time.Minute ) -type podCreationFuncType func() *v1.Pod - var ( gpuResourceName v1.ResourceName dsYamlUrl string - podCreationFunc podCreationFuncType ) -func makeCudaAdditionTestPod() *v1.Pod { - podName := testPodNamePrefix + string(uuid.NewUUID()) - testPod := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: podName, - }, - Spec: v1.PodSpec{ - RestartPolicy: v1.RestartPolicyNever, - Containers: []v1.Container{ - { - Name: "vector-addition", - Image: imageutils.GetE2EImage(imageutils.CudaVectorAdd), - Resources: v1.ResourceRequirements{ - Limits: v1.ResourceList{ - gpuResourceName: *resource.NewQuantity(1, resource.DecimalSI), - }, - }, - VolumeMounts: []v1.VolumeMount{ - { - Name: "nvidia-libraries", - MountPath: "/usr/local/nvidia/lib64", - }, - }, - }, - }, - Volumes: []v1.Volume{ - { - Name: "nvidia-libraries", - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{ - Path: "/home/kubernetes/bin/nvidia/lib", - }, - }, - }, - }, - }, - } - return testPod -} - func makeCudaAdditionDevicePluginTestPod() *v1.Pod { podName := testPodNamePrefix + string(uuid.NewUUID()) testPod := &v1.Pod{ @@ -112,15 +67,12 @@ func makeCudaAdditionDevicePluginTestPod() *v1.Pod { return testPod } -func isClusterRunningCOS(f *framework.Framework) bool { +func logOSImages(f *framework.Framework) { nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{}) framework.ExpectNoError(err, "getting node list") for _, node := range nodeList.Items { - if !strings.Contains(node.Status.NodeInfo.OSImage, cosOSImage) { - return false - } + framework.Logf("OS Image: %v", node.Status.NodeInfo.OSImage) } - return true } func areGPUsAvailableOnAllSchedulableNodes(f *framework.Framework) bool { @@ -154,29 +106,15 @@ func getGPUsAvailable(f *framework.Framework) int64 { } func SetupNVIDIAGPUNode(f *framework.Framework, setupResourceGatherer bool) *framework.ContainerResourceGatherer { - // Skip the test if the base image is not COS. - // TODO: Add support for other base images. - // CUDA apps require host mounts which is not portable across base images (yet). - framework.Logf("Checking base image") - if !isClusterRunningCOS(f) { - Skip("Nvidia GPU tests are supproted only on Container Optimized OS image currently") - } - framework.Logf("Cluster is running on COS. Proceeding with test") + logOSImages(f) - if f.BaseName == "gpus" { - dsYamlUrl = "https://raw.githubusercontent.com/ContainerEngine/accelerators/master/cos-nvidia-gpu-installer/daemonset.yaml" - gpuResourceName = v1.ResourceNvidiaGPU - podCreationFunc = makeCudaAdditionTestPod + dsYamlUrlFromEnv := os.Getenv("NVIDIA_DRIVER_INSTALLER_DAEMONSET") + if dsYamlUrlFromEnv != "" { + dsYamlUrl = dsYamlUrlFromEnv } else { - dsYamlUrlFromEnv := os.Getenv("NVIDIA_DRIVER_INSTALLER_DAEMONSET") - if dsYamlUrlFromEnv != "" { - dsYamlUrl = dsYamlUrlFromEnv - } else { - dsYamlUrl = "https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/k8s-1.10/daemonset.yaml" - } - gpuResourceName = framework.NVIDIAGPUResourceName - podCreationFunc = makeCudaAdditionDevicePluginTestPod + dsYamlUrl = "https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/daemonset.yaml" } + gpuResourceName = framework.NVIDIAGPUResourceName framework.Logf("Using %v", dsYamlUrl) // Creates the DaemonSet that installs Nvidia Drivers. @@ -199,7 +137,7 @@ func SetupNVIDIAGPUNode(f *framework.Framework, setupResourceGatherer bool) *fra var rsgather *framework.ContainerResourceGatherer if setupResourceGatherer { framework.Logf("Starting ResourceUsageGather for the created DaemonSet pods.") - rsgather, err = framework.NewResourceUsageGatherer(f.ClientSet, framework.ResourceGathererOptions{false, false, 2 * time.Second, 2 * time.Second, true}, pods) + rsgather, err = framework.NewResourceUsageGatherer(f.ClientSet, framework.ResourceGathererOptions{InKubemark: false, MasterOnly: false, ResourceDataGatheringPeriod: 2 * time.Second, ProbeDuration: 2 * time.Second, PrintVerboseLogs: true}, pods) framework.ExpectNoError(err, "creating ResourceUsageGather for the daemonset pods") go rsgather.StartGatheringData() } @@ -213,12 +151,12 @@ func SetupNVIDIAGPUNode(f *framework.Framework, setupResourceGatherer bool) *fra return rsgather } -func testNvidiaGPUsOnCOS(f *framework.Framework) { +func testNvidiaGPUs(f *framework.Framework) { rsgather := SetupNVIDIAGPUNode(f, true) framework.Logf("Creating as many pods as there are Nvidia GPUs and have the pods run a CUDA app") podList := []*v1.Pod{} for i := int64(0); i < getGPUsAvailable(f); i++ { - podList = append(podList, f.PodClient().Create(podCreationFunc())) + podList = append(podList, f.PodClient().Create(makeCudaAdditionDevicePluginTestPod())) } framework.Logf("Wait for all test pods to succeed") // Wait for all pods to succeed @@ -234,16 +172,9 @@ func testNvidiaGPUsOnCOS(f *framework.Framework) { framework.ExpectNoError(err, "getting resource usage summary") } -var _ = SIGDescribe("[Feature:GPU]", func() { - f := framework.NewDefaultFramework("gpus") - It("run Nvidia GPU tests on Container Optimized OS only", func() { - testNvidiaGPUsOnCOS(f) - }) -}) - var _ = SIGDescribe("[Feature:GPUDevicePlugin]", func() { f := framework.NewDefaultFramework("device-plugin-gpus") - It("run Nvidia GPU Device Plugin tests on Container Optimized OS only", func() { - testNvidiaGPUsOnCOS(f) + It("run Nvidia GPU Device Plugin tests", func() { + testNvidiaGPUs(f) }) }) diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/predicates.go b/vendor/k8s.io/kubernetes/test/e2e/scheduling/predicates.go index c98dde1d2..a714410cb 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/predicates.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/predicates.go @@ -31,6 +31,7 @@ import ( "k8s.io/kubernetes/test/e2e/common" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -46,6 +47,7 @@ var masterNodes sets.String type pausePodConfig struct { Name string + Namespace string Affinity *v1.Affinity Annotations, Labels, NodeSelector map[string]string Resources *v1.ResourceRequirements @@ -70,7 +72,7 @@ var _ = SIGDescribe("SchedulerPredicates [Serial]", func() { rc, err := cs.CoreV1().ReplicationControllers(ns).Get(RCName, metav1.GetOptions{}) if err == nil && *(rc.Spec.Replicas) != 0 { By("Cleaning up the replication controller") - err := framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, ns, RCName) + err := framework.DeleteRCAndWaitForGC(f.ClientSet, ns, RCName) framework.ExpectNoError(err) } }) @@ -585,14 +587,15 @@ var _ = SIGDescribe("SchedulerPredicates [Serial]", func() { framework.ExpectNodeHasLabel(cs, nodeName, k, v) defer framework.RemoveLabelOffNode(cs, nodeName, k) - By("Trying to create a pod(pod1) with hostport 80 and hostIP 127.0.0.1 and expect scheduled") - creatHostPortPodOnNode(f, "pod1", ns, "127.0.0.1", v1.ProtocolTCP, nodeSelector, true) + port := int32(54321) + By(fmt.Sprintf("Trying to create a pod(pod1) with hostport %v and hostIP 127.0.0.1 and expect scheduled", port)) + creatHostPortPodOnNode(f, "pod1", ns, "127.0.0.1", port, v1.ProtocolTCP, nodeSelector, true) - By("Trying to create another pod(pod2) with hostport 80 but hostIP 127.0.0.2 on the node which pod1 resides and expect scheduled") - creatHostPortPodOnNode(f, "pod2", ns, "127.0.0.2", v1.ProtocolTCP, nodeSelector, true) + By(fmt.Sprintf("Trying to create another pod(pod2) with hostport %v but hostIP 127.0.0.2 on the node which pod1 resides and expect scheduled", port)) + creatHostPortPodOnNode(f, "pod2", ns, "127.0.0.2", port, v1.ProtocolTCP, nodeSelector, true) - By("Trying to create a third pod(pod3) with hostport 80, hostIP 127.0.0.2 but use UDP protocol on the node which pod2 resides") - creatHostPortPodOnNode(f, "pod3", ns, "127.0.0.2", v1.ProtocolUDP, nodeSelector, true) + By(fmt.Sprintf("Trying to create a third pod(pod3) with hostport %v, hostIP 127.0.0.2 but use UDP protocol on the node which pod2 resides", port)) + creatHostPortPodOnNode(f, "pod3", ns, "127.0.0.2", port, v1.ProtocolUDP, nodeSelector, true) }) It("validates that there exists conflict between pods with same hostPort and protocol but one using 0.0.0.0 hostIP", func() { @@ -610,18 +613,21 @@ var _ = SIGDescribe("SchedulerPredicates [Serial]", func() { framework.ExpectNodeHasLabel(cs, nodeName, k, v) defer framework.RemoveLabelOffNode(cs, nodeName, k) - By("Trying to create a pod(pod4) with hostport 80 and hostIP 0.0.0.0(empty string here) and expect scheduled") - creatHostPortPodOnNode(f, "pod4", ns, "", v1.ProtocolTCP, nodeSelector, true) + port := int32(54322) + By(fmt.Sprintf("Trying to create a pod(pod4) with hostport %v and hostIP 0.0.0.0(empty string here) and expect scheduled", port)) + creatHostPortPodOnNode(f, "pod4", ns, "", port, v1.ProtocolTCP, nodeSelector, true) - By("Trying to create another pod(pod5) with hostport 80 but hostIP 127.0.0.1 on the node which pod4 resides and expect not scheduled") - creatHostPortPodOnNode(f, "pod5", ns, "127.0.0.1", v1.ProtocolTCP, nodeSelector, false) + By(fmt.Sprintf("Trying to create another pod(pod5) with hostport %v but hostIP 127.0.0.1 on the node which pod4 resides and expect not scheduled", port)) + creatHostPortPodOnNode(f, "pod5", ns, "127.0.0.1", port, v1.ProtocolTCP, nodeSelector, false) }) }) func initPausePod(f *framework.Framework, conf pausePodConfig) *v1.Pod { + var gracePeriod = int64(1) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: conf.Name, + Namespace: conf.Namespace, Labels: conf.Labels, Annotations: conf.Annotations, OwnerReferences: conf.OwnerReferences, @@ -632,13 +638,14 @@ func initPausePod(f *framework.Framework, conf pausePodConfig) *v1.Pod { Containers: []v1.Container{ { Name: conf.Name, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Ports: conf.Ports, }, }, - Tolerations: conf.Tolerations, - NodeName: conf.NodeName, - PriorityClassName: conf.PriorityClassName, + Tolerations: conf.Tolerations, + NodeName: conf.NodeName, + PriorityClassName: conf.PriorityClassName, + TerminationGracePeriodSeconds: &gracePeriod, }, } if conf.Resources != nil { @@ -648,7 +655,11 @@ func initPausePod(f *framework.Framework, conf pausePodConfig) *v1.Pod { } func createPausePod(f *framework.Framework, conf pausePodConfig) *v1.Pod { - pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(initPausePod(f, conf)) + namespace := conf.Namespace + if len(namespace) == 0 { + namespace = f.Namespace.Name + } + pod, err := f.ClientSet.CoreV1().Pods(namespace).Create(initPausePod(f, conf)) framework.ExpectNoError(err) return pod } @@ -656,7 +667,7 @@ func createPausePod(f *framework.Framework, conf pausePodConfig) *v1.Pod { func runPausePod(f *framework.Framework, conf pausePodConfig) *v1.Pod { pod := createPausePod(f, conf) framework.ExpectNoError(framework.WaitForPodRunningInNamespace(f.ClientSet, pod)) - pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(conf.Name, metav1.GetOptions{}) + pod, err := f.ClientSet.CoreV1().Pods(pod.Namespace).Get(conf.Name, metav1.GetOptions{}) framework.ExpectNoError(err) return pod } @@ -797,7 +808,7 @@ func CreateHostPortPods(f *framework.Framework, id string, replicas int, expectR Name: id, Namespace: f.Namespace.Name, Timeout: defaultTimeout, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: replicas, HostPorts: map[string]int{"port1": 4321}, } @@ -808,12 +819,12 @@ func CreateHostPortPods(f *framework.Framework, id string, replicas int, expectR } // create pod which using hostport on the specified node according to the nodeSelector -func creatHostPortPodOnNode(f *framework.Framework, podName, ns, hostIP string, protocol v1.Protocol, nodeSelector map[string]string, expectScheduled bool) { +func creatHostPortPodOnNode(f *framework.Framework, podName, ns, hostIP string, port int32, protocol v1.Protocol, nodeSelector map[string]string, expectScheduled bool) { createPausePod(f, pausePodConfig{ Name: podName, Ports: []v1.ContainerPort{ { - HostPort: 80, + HostPort: port, ContainerPort: 80, Protocol: protocol, HostIP: hostIP, diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/preemption.go b/vendor/k8s.io/kubernetes/test/e2e/scheduling/preemption.go index 1867ec4cc..f49404bbc 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/preemption.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/preemption.go @@ -21,12 +21,12 @@ import ( "time" "k8s.io/api/core/v1" - "k8s.io/api/scheduling/v1alpha1" + schedulerapi "k8s.io/api/scheduling/v1beta1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + "k8s.io/kubernetes/pkg/apis/scheduling" "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" @@ -34,7 +34,7 @@ import ( _ "github.com/stretchr/testify/assert" ) -var _ = SIGDescribe("SchedulerPreemption [Serial] [Feature:PodPreemption]", func() { +var _ = SIGDescribe("SchedulerPreemption [Serial]", func() { var cs clientset.Interface var nodeList *v1.NodeList var ns string @@ -51,12 +51,11 @@ var _ = SIGDescribe("SchedulerPreemption [Serial] [Feature:PodPreemption]", func cs = f.ClientSet ns = f.Namespace.Name nodeList = &v1.NodeList{} - - _, err := f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: highPriorityClassName}, Value: highPriority}) + _, err := f.ClientSet.SchedulingV1beta1().PriorityClasses().Create(&schedulerapi.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: highPriorityClassName}, Value: highPriority}) Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true)) - _, err = f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: mediumPriorityClassName}, Value: mediumPriority}) + _, err = f.ClientSet.SchedulingV1beta1().PriorityClasses().Create(&schedulerapi.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: mediumPriorityClassName}, Value: mediumPriority}) Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true)) - _, err = f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: lowPriorityClassName}, Value: lowPriority}) + _, err = f.ClientSet.SchedulingV1beta1().PriorityClasses().Create(&schedulerapi.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: lowPriorityClassName}, Value: lowPriority}) Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true)) framework.WaitForAllNodesHealthy(cs, time.Minute) @@ -168,7 +167,8 @@ var _ = SIGDescribe("SchedulerPreemption [Serial] [Feature:PodPreemption]", func // Create a critical pod and make sure it is scheduled. runPausePod(f, pausePodConfig{ Name: "critical-pod", - PriorityClassName: schedulerapi.SystemClusterCritical, + Namespace: metav1.NamespaceSystem, + PriorityClassName: scheduling.SystemClusterCritical, Resources: &v1.ResourceRequirements{ Requests: podRes, }, @@ -184,6 +184,9 @@ var _ = SIGDescribe("SchedulerPreemption [Serial] [Feature:PodPreemption]", func framework.ExpectNoError(err) Expect(livePod.DeletionTimestamp).To(BeNil()) } + // Clean-up the critical pod + err = f.ClientSet.CoreV1().Pods(metav1.NamespaceSystem).Delete("critical-pod", metav1.NewDeleteOptions(0)) + framework.ExpectNoError(err) }) // This test verifies that when a high priority pod is pending and its @@ -311,3 +314,38 @@ var _ = SIGDescribe("SchedulerPreemption [Serial] [Feature:PodPreemption]", func } }) }) + +var _ = SIGDescribe("PodPriorityResolution [Serial] [Feature:PodPreemption]", func() { + var cs clientset.Interface + var ns string + f := framework.NewDefaultFramework("sched-pod-priority") + + BeforeEach(func() { + cs = f.ClientSet + ns = f.Namespace.Name + + err := framework.CheckTestingNSDeletedExcept(cs, ns) + framework.ExpectNoError(err) + }) + + // This test verifies that system critical priorities are created automatically and resolved properly. + It("validates critical system priorities are created and resolved", func() { + // Create pods that use system critical priorities and + By("Create pods that use critical system priorities.") + systemPriorityClasses := []string{ + scheduling.SystemNodeCritical, scheduling.SystemClusterCritical, + } + for i, spc := range systemPriorityClasses { + pod := createPausePod(f, pausePodConfig{ + Name: fmt.Sprintf("pod%d-%v", i, spc), + Namespace: metav1.NamespaceSystem, + PriorityClassName: spc, + }) + Expect(pod.Spec.Priority).NotTo(BeNil()) + framework.Logf("Created pod: %v", pod.Name) + // Clean-up the pod. + err := f.ClientSet.CoreV1().Pods(pod.Namespace).Delete(pod.Name, metav1.NewDeleteOptions(0)) + framework.ExpectNoError(err) + } + }) +}) diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/priorities.go b/vendor/k8s.io/kubernetes/test/e2e/scheduling/priorities.go index 1bcafa162..484745460 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/priorities.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/priorities.go @@ -35,6 +35,7 @@ import ( "k8s.io/kubernetes/test/e2e/common" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" ) type Resource struct { @@ -152,7 +153,7 @@ var _ = SIGDescribe("SchedulerPriorities [Serial]", func() { // Cleanup the replication controller when we are done. defer func() { // Resize the replication controller to zero to get rid of pods. - if err := framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, rc.Name); err != nil { + if err := framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, rc.Name); err != nil { framework.Logf("Failed to cleanup replication controller %v: %v.", rc.Name, err) } }() @@ -194,7 +195,7 @@ var _ = SIGDescribe("SchedulerPriorities [Serial]", func() { By(fmt.Sprintf("Scale the RC: %s to len(nodeList.Item)-1 : %v.", rc.Name, len(nodeList.Items)-1)) - framework.ScaleRC(f.ClientSet, f.InternalClientset, f.ScalesGetter, ns, rc.Name, uint(len(nodeList.Items)-1), true) + framework.ScaleRC(f.ClientSet, f.ScalesGetter, ns, rc.Name, uint(len(nodeList.Items)-1), true) testPods, err := cs.CoreV1().Pods(ns).List(metav1.ListOptions{ LabelSelector: "name=scheduler-priority-avoid-pod", }) @@ -376,7 +377,7 @@ func createRC(ns, rsName string, replicas int32, rcPodLabels map[string]string, Containers: []v1.Container{ { Name: rsName, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Resources: *resource, }, }, diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/rescheduler.go b/vendor/k8s.io/kubernetes/test/e2e/scheduling/rescheduler.go index 6de8df06c..8595b9760 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/rescheduler.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/rescheduler.go @@ -26,6 +26,7 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -55,7 +56,7 @@ var _ = SIGDescribe("Rescheduler [Serial]", func() { It("should ensure that critical pod is scheduled in case there is no resources available", func() { By("reserving all available cpu") err := reserveAllCpu(f, "reserve-all-cpu", totalMillicores) - defer framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, ns, "reserve-all-cpu") + defer framework.DeleteRCAndWaitForGC(f.ClientSet, ns, "reserve-all-cpu") framework.ExpectNoError(err) By("creating a new instance of Dashboard and waiting for Dashboard to be scheduled") @@ -68,8 +69,8 @@ var _ = SIGDescribe("Rescheduler [Serial]", func() { deployment := deployments.Items[0] replicas := uint(*(deployment.Spec.Replicas)) - err = framework.ScaleDeployment(f.ClientSet, f.InternalClientset, f.ScalesGetter, metav1.NamespaceSystem, deployment.Name, replicas+1, true) - defer framework.ExpectNoError(framework.ScaleDeployment(f.ClientSet, f.InternalClientset, f.ScalesGetter, metav1.NamespaceSystem, deployment.Name, replicas, true)) + err = framework.ScaleDeployment(f.ClientSet, f.ScalesGetter, metav1.NamespaceSystem, deployment.Name, replicas+1, true) + defer framework.ExpectNoError(framework.ScaleDeployment(f.ClientSet, f.ScalesGetter, metav1.NamespaceSystem, deployment.Name, replicas, true)) framework.ExpectNoError(err) }) @@ -80,7 +81,7 @@ func reserveAllCpu(f *framework.Framework, id string, millicores int) error { replicas := millicores / 100 reserveCpu(f, id, 1, 100) - framework.ExpectNoError(framework.ScaleRC(f.ClientSet, f.InternalClientset, f.ScalesGetter, f.Namespace.Name, id, uint(replicas), false)) + framework.ExpectNoError(framework.ScaleRC(f.ClientSet, f.ScalesGetter, f.Namespace.Name, id, uint(replicas), false)) for start := time.Now(); time.Since(start) < timeout; time.Sleep(10 * time.Second) { pods, err := framework.GetPodsInNamespace(f.ClientSet, f.Namespace.Name, framework.ImagePullerLabels) @@ -124,7 +125,7 @@ func reserveCpu(f *framework.Framework, id string, replicas, millicores int) { Name: id, Namespace: f.Namespace.Name, Timeout: defaultTimeout, - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Replicas: replicas, CpuRequest: request, } diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/resource_quota.go b/vendor/k8s.io/kubernetes/test/e2e/scheduling/resource_quota.go index 8f054f5d7..38606253e 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/resource_quota.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/resource_quota.go @@ -30,6 +30,7 @@ import ( clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/pkg/quota/evaluator/core" "k8s.io/kubernetes/test/e2e/framework" + imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -798,7 +799,7 @@ func newTestPodForQuota(f *framework.Framework, name string, requests v1.Resourc Containers: []v1.Container{ { Name: "pause", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Resources: v1.ResourceRequirements{ Requests: requests, Limits: limits, diff --git a/vendor/k8s.io/kubernetes/test/e2e/scheduling/ubernetes_lite.go b/vendor/k8s.io/kubernetes/test/e2e/scheduling/ubernetes_lite.go index 3fdb71132..2834e3925 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/scheduling/ubernetes_lite.go +++ b/vendor/k8s.io/kubernetes/test/e2e/scheduling/ubernetes_lite.go @@ -32,6 +32,7 @@ import ( kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" ) var _ = SIGDescribe("Multi-AZ Clusters", func() { @@ -91,7 +92,7 @@ func SpreadServiceOrFail(f *framework.Framework, replicaCount int, image string) Containers: []v1.Container{ { Name: "test", - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), }, }, }, @@ -223,7 +224,7 @@ func SpreadRCOrFail(f *framework.Framework, replicaCount int32, image string) { // Cleanup the replication controller when we are done. defer func() { // Resize the replication controller to zero to get rid of pods. - if err := framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, controller.Name); err != nil { + if err := framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, controller.Name); err != nil { framework.Logf("Failed to cleanup replication controller %v: %v.", controller.Name, err) } }() diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/BUILD b/vendor/k8s.io/kubernetes/test/e2e/storage/BUILD index af103b9f0..f0430685a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/BUILD @@ -3,14 +3,16 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ - "csi_hostpath.go", + "csi_objects.go", "csi_volumes.go", "empty_dir_wrapper.go", + "ephemeral_volume.go", "flexvolume.go", + "generic_persistent_volume-disruptive.go", "mounted_volume_resize.go", + "nfs_persistent_volume-disruptive.go", "pd.go", "persistent_volumes.go", - "persistent_volumes-disruptive.go", "persistent_volumes-gce.go", "persistent_volumes-local.go", "pv_protection.go", @@ -26,9 +28,7 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e/storage", visibility = ["//visibility:public"], deps = [ - "//pkg/api/testapi:go_default_library", "//pkg/api/v1/pod:go_default_library", - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/apis/storage/v1/util:go_default_library", "//pkg/client/conditions:go_default_library", "//pkg/kubelet/apis:go_default_library", @@ -39,6 +39,7 @@ go_library( "//test/e2e/framework:go_default_library", "//test/e2e/framework/metrics:go_default_library", "//test/e2e/generated:go_default_library", + "//test/e2e/manifest:go_default_library", "//test/e2e/storage/utils:go_default_library", "//test/e2e/storage/vsphere:go_default_library", "//test/utils/image:go_default_library", @@ -75,6 +76,7 @@ go_library( "//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/csi_hostpath.go b/vendor/k8s.io/kubernetes/test/e2e/storage/csi_hostpath.go deleted file mode 100644 index bddc8dc6a..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/csi_hostpath.go +++ /dev/null @@ -1,199 +0,0 @@ -/* -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. -*/ - -// This file is used to deploy the CSI hostPath plugin -// More Information: https://github.com/kubernetes-csi/drivers/tree/master/pkg/hostpath - -package storage - -import ( - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/test/e2e/framework" -) - -const ( - csiHostPathPluginImage string = "quay.io/k8scsi/hostpathplugin:v0.2.0" -) - -func csiHostPathPod( - client clientset.Interface, - config framework.VolumeTestConfig, - teardown bool, - f *framework.Framework, - sa *v1.ServiceAccount, -) *v1.Pod { - podClient := client.CoreV1().Pods(config.Namespace) - - priv := true - mountPropagation := v1.MountPropagationBidirectional - hostPathType := v1.HostPathDirectoryOrCreate - pod := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: config.Prefix + "-pod", - Namespace: config.Namespace, - Labels: map[string]string{ - "app": "hostpath-driver", - }, - }, - Spec: v1.PodSpec{ - ServiceAccountName: sa.GetName(), - NodeName: config.ServerNodeName, - RestartPolicy: v1.RestartPolicyNever, - Containers: []v1.Container{ - { - Name: "external-provisioner", - Image: csiExternalProvisionerImage, - ImagePullPolicy: v1.PullAlways, - Args: []string{ - "--v=5", - "--provisioner=csi-hostpath", - "--csi-address=/csi/csi.sock", - }, - VolumeMounts: []v1.VolumeMount{ - { - Name: "socket-dir", - MountPath: "/csi", - }, - }, - }, - { - Name: "driver-registrar", - Image: csiDriverRegistrarImage, - ImagePullPolicy: v1.PullAlways, - Args: []string{ - "--v=5", - "--csi-address=/csi/csi.sock", - }, - Env: []v1.EnvVar{ - { - Name: "KUBE_NODE_NAME", - ValueFrom: &v1.EnvVarSource{ - FieldRef: &v1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - }, - VolumeMounts: []v1.VolumeMount{ - { - Name: "socket-dir", - MountPath: "/csi", - }, - }, - }, - { - Name: "external-attacher", - Image: csiExternalAttacherImage, - ImagePullPolicy: v1.PullAlways, - Args: []string{ - "--v=5", - "--csi-address=$(ADDRESS)", - }, - Env: []v1.EnvVar{ - { - Name: "ADDRESS", - Value: "/csi/csi.sock", - }, - }, - VolumeMounts: []v1.VolumeMount{ - { - Name: "socket-dir", - MountPath: "/csi", - }, - }, - }, - { - Name: "hostpath-driver", - Image: csiHostPathPluginImage, - ImagePullPolicy: v1.PullAlways, - SecurityContext: &v1.SecurityContext{ - Privileged: &priv, - }, - Args: []string{ - "--v=5", - "--endpoint=$(CSI_ENDPOINT)", - "--nodeid=$(KUBE_NODE_NAME)", - }, - Env: []v1.EnvVar{ - { - Name: "CSI_ENDPOINT", - Value: "unix://" + "/csi/csi.sock", - }, - { - Name: "KUBE_NODE_NAME", - ValueFrom: &v1.EnvVarSource{ - FieldRef: &v1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - }, - VolumeMounts: []v1.VolumeMount{ - { - Name: "socket-dir", - MountPath: "/csi", - }, - { - Name: "mountpoint-dir", - MountPath: "/var/lib/kubelet/pods", - MountPropagation: &mountPropagation, - }, - }, - }, - }, - Volumes: []v1.Volume{ - { - Name: "socket-dir", - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{ - Path: "/var/lib/kubelet/plugins/csi-hostpath", - Type: &hostPathType, - }, - }, - }, - { - Name: "mountpoint-dir", - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{ - Path: "/var/lib/kubelet/pods", - Type: &hostPathType, - }, - }, - }, - }, - }, - } - - err := framework.DeletePodWithWait(f, client, pod) - framework.ExpectNoError(err, "Failed to delete pod %s/%s: %v", - pod.GetNamespace(), pod.GetName(), err) - - if teardown { - return nil - } - - ret, err := podClient.Create(pod) - if err != nil { - framework.ExpectNoError(err, "Failed to create %q pod: %v", pod.GetName(), err) - } - - // Wait for pod to come up - framework.ExpectNoError(framework.WaitForPodRunningInNamespace(client, ret)) - return ret -} diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/csi_objects.go b/vendor/k8s.io/kubernetes/test/e2e/storage/csi_objects.go new file mode 100644 index 000000000..15fd7cf32 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/csi_objects.go @@ -0,0 +1,415 @@ +/* +Copyright 2018 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. +*/ + +// This file is used to deploy the CSI hostPath plugin +// More Information: https://github.com/kubernetes-csi/drivers/tree/master/pkg/hostpath + +package storage + +import ( + "fmt" + "time" + + "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + apierrs "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + + clientset "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/manifest" + + . "github.com/onsi/ginkgo" +) + +var csiImageVersions = map[string]string{ + "hostpathplugin": "v0.2.0", + "csi-attacher": "v0.2.0", + "csi-provisioner": "v0.2.1", + "driver-registrar": "v0.2.0", +} + +func csiContainerImage(image string) string { + var fullName string + fullName += framework.TestContext.CSIImageRegistry + "/" + image + ":" + if framework.TestContext.CSIImageVersion != "" { + fullName += framework.TestContext.CSIImageVersion + } else { + fullName += csiImageVersions[image] + } + return fullName +} + +// Create the driver registrar cluster role if it doesn't exist, no teardown so that tests +// are parallelizable. This role will be shared with many of the CSI tests. +func csiDriverRegistrarClusterRole( + config framework.VolumeTestConfig, +) *rbacv1.ClusterRole { + // TODO(Issue: #62237) Remove impersonation workaround and cluster role when issue resolved + By("Creating an impersonating superuser kubernetes clientset to define cluster role") + rc, err := framework.LoadConfig() + framework.ExpectNoError(err) + rc.Impersonate = restclient.ImpersonationConfig{ + UserName: "superuser", + Groups: []string{"system:masters"}, + } + superuserClientset, err := clientset.NewForConfig(rc) + framework.ExpectNoError(err, "Failed to create superuser clientset: %v", err) + By("Creating the CSI driver registrar cluster role") + clusterRoleClient := superuserClientset.RbacV1().ClusterRoles() + role := &rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: csiDriverRegistrarClusterRoleName, + }, + Rules: []rbacv1.PolicyRule{ + + { + APIGroups: []string{""}, + Resources: []string{"events"}, + Verbs: []string{"get", "list", "watch", "create", "update", "patch"}, + }, + { + APIGroups: []string{""}, + Resources: []string{"nodes"}, + Verbs: []string{"get", "update", "patch"}, + }, + }, + } + + ret, err := clusterRoleClient.Create(role) + if err != nil { + if apierrs.IsAlreadyExists(err) { + return ret + } + framework.ExpectNoError(err, "Failed to create %s cluster role: %v", role.GetName(), err) + } + + return ret +} + +func csiServiceAccount( + client clientset.Interface, + config framework.VolumeTestConfig, + componentName string, + teardown bool, +) *v1.ServiceAccount { + creatingString := "Creating" + if teardown { + creatingString = "Deleting" + } + By(fmt.Sprintf("%v a CSI service account for %v", creatingString, componentName)) + serviceAccountName := config.Prefix + "-" + componentName + "-service-account" + serviceAccountClient := client.CoreV1().ServiceAccounts(config.Namespace) + sa := &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceAccountName, + }, + } + + serviceAccountClient.Delete(sa.GetName(), &metav1.DeleteOptions{}) + err := wait.Poll(2*time.Second, 10*time.Minute, func() (bool, error) { + _, err := serviceAccountClient.Get(sa.GetName(), metav1.GetOptions{}) + return apierrs.IsNotFound(err), nil + }) + framework.ExpectNoError(err, "Timed out waiting for deletion: %v", err) + + if teardown { + return nil + } + + ret, err := serviceAccountClient.Create(sa) + if err != nil { + framework.ExpectNoError(err, "Failed to create %s service account: %v", sa.GetName(), err) + } + + return ret +} + +func csiClusterRoleBindings( + client clientset.Interface, + config framework.VolumeTestConfig, + teardown bool, + sa *v1.ServiceAccount, + clusterRolesNames []string, +) { + bindingString := "Binding" + if teardown { + bindingString = "Unbinding" + } + By(fmt.Sprintf("%v cluster roles %v to the CSI service account %v", bindingString, clusterRolesNames, sa.GetName())) + clusterRoleBindingClient := client.RbacV1().ClusterRoleBindings() + for _, clusterRoleName := range clusterRolesNames { + + binding := &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: config.Prefix + "-" + clusterRoleName + "-" + config.Namespace + "-role-binding", + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Name: sa.GetName(), + Namespace: sa.GetNamespace(), + }, + }, + RoleRef: rbacv1.RoleRef{ + Kind: "ClusterRole", + Name: clusterRoleName, + APIGroup: "rbac.authorization.k8s.io", + }, + } + + clusterRoleBindingClient.Delete(binding.GetName(), &metav1.DeleteOptions{}) + err := wait.Poll(2*time.Second, 10*time.Minute, func() (bool, error) { + _, err := clusterRoleBindingClient.Get(binding.GetName(), metav1.GetOptions{}) + return apierrs.IsNotFound(err), nil + }) + framework.ExpectNoError(err, "Timed out waiting for deletion: %v", err) + + if teardown { + return + } + + _, err = clusterRoleBindingClient.Create(binding) + if err != nil { + framework.ExpectNoError(err, "Failed to create %s role binding: %v", binding.GetName(), err) + } + } +} + +func csiHostPathPod( + client clientset.Interface, + config framework.VolumeTestConfig, + teardown bool, + f *framework.Framework, + sa *v1.ServiceAccount, +) *v1.Pod { + podClient := client.CoreV1().Pods(config.Namespace) + + priv := true + mountPropagation := v1.MountPropagationBidirectional + hostPathType := v1.HostPathDirectoryOrCreate + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: config.Prefix + "-pod", + Namespace: config.Namespace, + Labels: map[string]string{ + "app": "hostpath-driver", + }, + }, + Spec: v1.PodSpec{ + ServiceAccountName: sa.GetName(), + NodeName: config.ServerNodeName, + RestartPolicy: v1.RestartPolicyNever, + Containers: []v1.Container{ + { + Name: "external-provisioner", + Image: csiContainerImage("csi-provisioner"), + ImagePullPolicy: v1.PullAlways, + Args: []string{ + "--v=5", + "--provisioner=csi-hostpath", + "--csi-address=/csi/csi.sock", + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "socket-dir", + MountPath: "/csi", + }, + }, + }, + { + Name: "driver-registrar", + Image: csiContainerImage("driver-registrar"), + ImagePullPolicy: v1.PullAlways, + Args: []string{ + "--v=5", + "--csi-address=/csi/csi.sock", + }, + Env: []v1.EnvVar{ + { + Name: "KUBE_NODE_NAME", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "spec.nodeName", + }, + }, + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "socket-dir", + MountPath: "/csi", + }, + }, + }, + { + Name: "external-attacher", + Image: csiContainerImage("csi-attacher"), + ImagePullPolicy: v1.PullAlways, + Args: []string{ + "--v=5", + "--csi-address=$(ADDRESS)", + }, + Env: []v1.EnvVar{ + { + Name: "ADDRESS", + Value: "/csi/csi.sock", + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "socket-dir", + MountPath: "/csi", + }, + }, + }, + { + Name: "hostpath-driver", + Image: csiContainerImage("hostpathplugin"), + ImagePullPolicy: v1.PullAlways, + SecurityContext: &v1.SecurityContext{ + Privileged: &priv, + }, + Args: []string{ + "--v=5", + "--endpoint=$(CSI_ENDPOINT)", + "--nodeid=$(KUBE_NODE_NAME)", + }, + Env: []v1.EnvVar{ + { + Name: "CSI_ENDPOINT", + Value: "unix://" + "/csi/csi.sock", + }, + { + Name: "KUBE_NODE_NAME", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "spec.nodeName", + }, + }, + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "socket-dir", + MountPath: "/csi", + }, + { + Name: "mountpoint-dir", + MountPath: "/var/lib/kubelet/pods", + MountPropagation: &mountPropagation, + }, + }, + }, + }, + Volumes: []v1.Volume{ + { + Name: "socket-dir", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: "/var/lib/kubelet/plugins/csi-hostpath", + Type: &hostPathType, + }, + }, + }, + { + Name: "mountpoint-dir", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: "/var/lib/kubelet/pods", + Type: &hostPathType, + }, + }, + }, + }, + }, + } + + err := framework.DeletePodWithWait(f, client, pod) + framework.ExpectNoError(err, "Failed to delete pod %s/%s: %v", + pod.GetNamespace(), pod.GetName(), err) + + if teardown { + return nil + } + + ret, err := podClient.Create(pod) + if err != nil { + framework.ExpectNoError(err, "Failed to create %q pod: %v", pod.GetName(), err) + } + + // Wait for pod to come up + framework.ExpectNoError(framework.WaitForPodRunningInNamespace(client, ret)) + return ret +} + +func deployGCEPDCSIDriver( + client clientset.Interface, + config framework.VolumeTestConfig, + teardown bool, + f *framework.Framework, + nodeSA *v1.ServiceAccount, + controllerSA *v1.ServiceAccount, +) { + // Get API Objects from manifests + nodeds, err := manifest.DaemonSetFromManifest("test/e2e/testing-manifests/storage-csi/gce-pd/node_ds.yaml", config.Namespace) + framework.ExpectNoError(err, "Failed to create DaemonSet from manifest") + nodeds.Spec.Template.Spec.ServiceAccountName = nodeSA.GetName() + + controllerss, err := manifest.StatefulSetFromManifest("test/e2e/testing-manifests/storage-csi/gce-pd/controller_ss.yaml", config.Namespace) + framework.ExpectNoError(err, "Failed to create StatefulSet from manifest") + controllerss.Spec.Template.Spec.ServiceAccountName = controllerSA.GetName() + + controllerservice, err := manifest.SvcFromManifest("test/e2e/testing-manifests/storage-csi/gce-pd/controller_service.yaml") + framework.ExpectNoError(err, "Failed to create Service from manifest") + + // Got all objects from manifests now try to delete objects + err = client.CoreV1().Services(config.Namespace).Delete(controllerservice.GetName(), nil) + if err != nil { + if !apierrs.IsNotFound(err) { + framework.ExpectNoError(err, "Failed to delete Service: %v", controllerservice.GetName()) + } + } + + err = client.AppsV1().StatefulSets(config.Namespace).Delete(controllerss.Name, nil) + if err != nil { + if !apierrs.IsNotFound(err) { + framework.ExpectNoError(err, "Failed to delete StatefulSet: %v", controllerss.GetName()) + } + } + err = client.AppsV1().DaemonSets(config.Namespace).Delete(nodeds.Name, nil) + if err != nil { + if !apierrs.IsNotFound(err) { + framework.ExpectNoError(err, "Failed to delete DaemonSet: %v", nodeds.GetName()) + } + } + if teardown { + return + } + + // Create new API Objects through client + _, err = client.CoreV1().Services(config.Namespace).Create(controllerservice) + framework.ExpectNoError(err, "Failed to create Service: %v", controllerservice.Name) + + _, err = client.AppsV1().StatefulSets(config.Namespace).Create(controllerss) + framework.ExpectNoError(err, "Failed to create StatefulSet: %v", controllerss.Name) + + _, err = client.AppsV1().DaemonSets(config.Namespace).Create(nodeds) + framework.ExpectNoError(err, "Failed to create DaemonSet: %v", nodeds.Name) + +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/csi_volumes.go b/vendor/k8s.io/kubernetes/test/e2e/storage/csi_volumes.go index f3d23ae40..82397eb00 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/csi_volumes.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/csi_volumes.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 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. @@ -17,174 +17,40 @@ limitations under the License. package storage import ( + "fmt" "math/rand" "time" "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - apierrs "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" + kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/utils" . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) const ( - csiExternalAttacherImage string = "quay.io/k8scsi/csi-attacher:v0.2.0" - csiExternalProvisionerImage string = "quay.io/k8scsi/csi-provisioner:v0.2.0" - csiDriverRegistrarImage string = "quay.io/k8scsi/driver-registrar:v0.2.0" + csiExternalProvisionerClusterRoleName string = "system:csi-external-provisioner" + csiExternalAttacherClusterRoleName string = "system:csi-external-attacher" + csiDriverRegistrarClusterRoleName string = "csi-driver-registrar" ) -func csiServiceAccount( - client clientset.Interface, - config framework.VolumeTestConfig, - teardown bool, -) *v1.ServiceAccount { - serviceAccountName := config.Prefix + "-service-account" - serviceAccountClient := client.CoreV1().ServiceAccounts(config.Namespace) - sa := &v1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceAccountName, - }, - } - - serviceAccountClient.Delete(sa.GetName(), &metav1.DeleteOptions{}) - err := wait.Poll(2*time.Second, 10*time.Minute, func() (bool, error) { - _, err := serviceAccountClient.Get(sa.GetName(), metav1.GetOptions{}) - return apierrs.IsNotFound(err), nil - }) - framework.ExpectNoError(err, "Timed out waiting for deletion: %v", err) - - if teardown { - return nil - } - - ret, err := serviceAccountClient.Create(sa) - if err != nil { - framework.ExpectNoError(err, "Failed to create %s service account: %v", sa.GetName(), err) - } - - return ret +type csiTestDriver interface { + createCSIDriver() + cleanupCSIDriver() + createStorageClassTest(node v1.Node) storageClassTest } -func csiClusterRole( - client clientset.Interface, - config framework.VolumeTestConfig, - teardown bool, -) *rbacv1.ClusterRole { - clusterRoleClient := client.RbacV1().ClusterRoles() - role := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: config.Prefix + "-cluster-role", - }, - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{""}, - Resources: []string{"persistentvolumes"}, - Verbs: []string{"create", "delete", "get", "list", "watch", "update"}, - }, - { - APIGroups: []string{""}, - Resources: []string{"persistentvolumeclaims"}, - Verbs: []string{"get", "list", "watch", "update"}, - }, - { - APIGroups: []string{""}, - Resources: []string{"events"}, - Verbs: []string{"get", "list", "watch", "create", "update", "patch"}, - }, - { - APIGroups: []string{""}, - Resources: []string{"secrets"}, - Verbs: []string{"get", "list"}, - }, - { - APIGroups: []string{""}, - Resources: []string{"nodes"}, - Verbs: []string{"get", "list", "watch", "update"}, - }, - { - APIGroups: []string{"storage.k8s.io"}, - Resources: []string{"volumeattachments"}, - Verbs: []string{"get", "list", "watch", "update"}, - }, - { - APIGroups: []string{"storage.k8s.io"}, - Resources: []string{"storageclasses"}, - Verbs: []string{"get", "list", "watch"}, - }, - }, - } - - clusterRoleClient.Delete(role.GetName(), &metav1.DeleteOptions{}) - err := wait.Poll(2*time.Second, 10*time.Minute, func() (bool, error) { - _, err := clusterRoleClient.Get(role.GetName(), metav1.GetOptions{}) - return apierrs.IsNotFound(err), nil - }) - framework.ExpectNoError(err, "Timed out waiting for deletion: %v", err) - - if teardown { - return nil - } - - ret, err := clusterRoleClient.Create(role) - if err != nil { - framework.ExpectNoError(err, "Failed to create %s cluster role: %v", role.GetName(), err) - } - - return ret -} - -func csiClusterRoleBinding( - client clientset.Interface, - config framework.VolumeTestConfig, - teardown bool, - sa *v1.ServiceAccount, - clusterRole *rbacv1.ClusterRole, -) *rbacv1.ClusterRoleBinding { - clusterRoleBindingClient := client.RbacV1().ClusterRoleBindings() - binding := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: config.Prefix + "-role-binding", - }, - Subjects: []rbacv1.Subject{ - { - Kind: "ServiceAccount", - Name: sa.GetName(), - Namespace: sa.GetNamespace(), - }, - }, - RoleRef: rbacv1.RoleRef{ - Kind: "ClusterRole", - Name: clusterRole.GetName(), - APIGroup: "rbac.authorization.k8s.io", - }, - } - - clusterRoleBindingClient.Delete(binding.GetName(), &metav1.DeleteOptions{}) - err := wait.Poll(2*time.Second, 10*time.Minute, func() (bool, error) { - _, err := clusterRoleBindingClient.Get(binding.GetName(), metav1.GetOptions{}) - return apierrs.IsNotFound(err), nil - }) - framework.ExpectNoError(err, "Timed out waiting for deletion: %v", err) - - if teardown { - return nil - } - - ret, err := clusterRoleBindingClient.Create(binding) - if err != nil { - framework.ExpectNoError(err, "Failed to create %s role binding: %v", binding.GetName(), err) - } - - return ret +var csiTestDrivers = map[string]func(f *framework.Framework, config framework.VolumeTestConfig) csiTestDriver{ + "hostPath": initCSIHostpath, + // Feature tag to skip test in CI, pending fix of #62237 + "[Feature: GCE PD CSI Plugin] gcePD": initCSIgcePD, } -var _ = utils.SIGDescribe("CSI Volumes [Flaky]", func() { +var _ = utils.SIGDescribe("CSI Volumes", func() { f := framework.NewDefaultFramework("csi-mock-plugin") var ( @@ -206,47 +72,154 @@ var _ = utils.SIGDescribe("CSI Volumes [Flaky]", func() { ServerNodeName: node.Name, WaitForCompletion: true, } + csiDriverRegistrarClusterRole(config) }) - // Create one of these for each of the drivers to be tested - // CSI hostPath driver test - Describe("Sanity CSI plugin test using hostPath CSI driver", func() { - - var ( - clusterRole *rbacv1.ClusterRole - serviceAccount *v1.ServiceAccount - ) - - BeforeEach(func() { - By("deploying csi hostpath driver") - clusterRole = csiClusterRole(cs, config, false) - serviceAccount = csiServiceAccount(cs, config, false) - csiClusterRoleBinding(cs, config, false, serviceAccount, clusterRole) - csiHostPathPod(cs, config, false, f, serviceAccount) + for driverName, initCSIDriver := range csiTestDrivers { + curDriverName := driverName + curInitCSIDriver := initCSIDriver + + Context(fmt.Sprintf("CSI plugin test using CSI driver: %s", curDriverName), func() { + var ( + driver csiTestDriver + ) + + BeforeEach(func() { + driver = curInitCSIDriver(f, config) + driver.createCSIDriver() + }) + + AfterEach(func() { + driver.cleanupCSIDriver() + }) + + It("should provision storage", func() { + t := driver.createStorageClassTest(node) + claim := newClaim(t, ns.GetName(), "") + class := newStorageClass(t, ns.GetName(), "") + claim.Spec.StorageClassName = &class.ObjectMeta.Name + testDynamicProvisioning(t, cs, claim, class) + }) }) + } +}) - AfterEach(func() { - By("uninstalling csi hostpath driver") - csiHostPathPod(cs, config, true, f, serviceAccount) - csiClusterRoleBinding(cs, config, true, serviceAccount, clusterRole) - serviceAccount = csiServiceAccount(cs, config, true) - clusterRole = csiClusterRole(cs, config, true) - }) +type hostpathCSIDriver struct { + combinedClusterRoleNames []string + serviceAccount *v1.ServiceAccount - It("should provision storage with a hostPath CSI driver", func() { - t := storageClassTest{ - name: "csi-hostpath", - provisioner: "csi-hostpath", - parameters: map[string]string{}, - claimSize: "1Gi", - expectedSize: "1Gi", - nodeName: node.Name, - } - - claim := newClaim(t, ns.GetName(), "") - class := newStorageClass(t, ns.GetName(), "") - claim.Spec.StorageClassName = &class.ObjectMeta.Name - testDynamicProvisioning(t, cs, claim, class) - }) - }) -}) + f *framework.Framework + config framework.VolumeTestConfig +} + +func initCSIHostpath(f *framework.Framework, config framework.VolumeTestConfig) csiTestDriver { + return &hostpathCSIDriver{ + combinedClusterRoleNames: []string{ + csiExternalAttacherClusterRoleName, + csiExternalProvisionerClusterRoleName, + csiDriverRegistrarClusterRoleName, + }, + f: f, + config: config, + } +} + +func (h *hostpathCSIDriver) createStorageClassTest(node v1.Node) storageClassTest { + return storageClassTest{ + name: "csi-hostpath", + provisioner: "csi-hostpath", + parameters: map[string]string{}, + claimSize: "1Gi", + expectedSize: "1Gi", + nodeName: node.Name, + } +} + +func (h *hostpathCSIDriver) createCSIDriver() { + By("deploying csi hostpath driver") + f := h.f + cs := f.ClientSet + config := h.config + h.serviceAccount = csiServiceAccount(cs, config, "hostpath", false) + csiClusterRoleBindings(cs, config, false, h.serviceAccount, h.combinedClusterRoleNames) + csiHostPathPod(cs, config, false, f, h.serviceAccount) +} + +func (h *hostpathCSIDriver) cleanupCSIDriver() { + By("uninstalling csi hostpath driver") + f := h.f + cs := f.ClientSet + config := h.config + csiHostPathPod(cs, config, true, f, h.serviceAccount) + csiClusterRoleBindings(cs, config, true, h.serviceAccount, h.combinedClusterRoleNames) + csiServiceAccount(cs, config, "hostpath", true) +} + +type gcePDCSIDriver struct { + controllerClusterRoles []string + nodeClusterRoles []string + controllerServiceAccount *v1.ServiceAccount + nodeServiceAccount *v1.ServiceAccount + + f *framework.Framework + config framework.VolumeTestConfig +} + +func initCSIgcePD(f *framework.Framework, config framework.VolumeTestConfig) csiTestDriver { + cs := f.ClientSet + framework.SkipUnlessProviderIs("gce", "gke") + // Currently you will need to manually add the required GCP Credentials as a secret "cloud-sa" + // kubectl create generic cloud-sa --from-file=PATH/TO/cloud-sa.json --namespace={{config.Namespace}} + // TODO(#62561): Inject the necessary credentials automatically to the driver containers in e2e test + framework.SkipUnlessSecretExistsAfterWait(cs, "cloud-sa", config.Namespace, 3*time.Minute) + + return &gcePDCSIDriver{ + nodeClusterRoles: []string{ + csiDriverRegistrarClusterRoleName, + }, + controllerClusterRoles: []string{ + csiExternalAttacherClusterRoleName, + csiExternalProvisionerClusterRoleName, + }, + f: f, + config: config, + } +} + +func (g *gcePDCSIDriver) createStorageClassTest(node v1.Node) storageClassTest { + nodeZone, ok := node.GetLabels()[kubeletapis.LabelZoneFailureDomain] + Expect(ok).To(BeTrue(), "Could not get label %v from node %v", kubeletapis.LabelZoneFailureDomain, node.GetName()) + + return storageClassTest{ + name: "csi-gce-pd", + provisioner: "csi-gce-pd", + parameters: map[string]string{"type": "pd-standard", "zone": nodeZone}, + claimSize: "5Gi", + expectedSize: "5Gi", + nodeName: node.Name, + } +} + +func (g *gcePDCSIDriver) createCSIDriver() { + By("deploying gce-pd driver") + f := g.f + cs := f.ClientSet + config := g.config + g.controllerServiceAccount = csiServiceAccount(cs, config, "gce-controller", false /* teardown */) + g.nodeServiceAccount = csiServiceAccount(cs, config, "gce-node", false /* teardown */) + csiClusterRoleBindings(cs, config, false /* teardown */, g.controllerServiceAccount, g.controllerClusterRoles) + csiClusterRoleBindings(cs, config, false /* teardown */, g.nodeServiceAccount, g.nodeClusterRoles) + deployGCEPDCSIDriver(cs, config, false /* teardown */, f, g.nodeServiceAccount, g.controllerServiceAccount) +} + +func (g *gcePDCSIDriver) cleanupCSIDriver() { + By("uninstalling gce-pd driver") + f := g.f + cs := f.ClientSet + config := g.config + deployGCEPDCSIDriver(cs, config, true /* teardown */, f, g.nodeServiceAccount, g.controllerServiceAccount) + csiClusterRoleBindings(cs, config, true /* teardown */, g.controllerServiceAccount, g.controllerClusterRoles) + csiClusterRoleBindings(cs, config, true /* teardown */, g.nodeServiceAccount, g.nodeClusterRoles) + csiServiceAccount(cs, config, "gce-controller", true /* teardown */) + csiServiceAccount(cs, config, "gce-node", true /* teardown */) +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/empty_dir_wrapper.go b/vendor/k8s.io/kubernetes/test/e2e/storage/empty_dir_wrapper.go index 4f1a45898..d6bfca35d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/empty_dir_wrapper.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/empty_dir_wrapper.go @@ -374,7 +374,7 @@ func testNoWrappedVolumeRace(f *framework.Framework, volumes []v1.Volume, volume Expect(err).NotTo(HaveOccurred(), "error creating replication controller") defer func() { - err := framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, rcName) + err := framework.DeleteRCAndWaitForGC(f.ClientSet, f.Namespace.Name, rcName) framework.ExpectNoError(err) }() diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/ephemeral_volume.go b/vendor/k8s.io/kubernetes/test/e2e/storage/ephemeral_volume.go new file mode 100644 index 000000000..5d1948e4b --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/ephemeral_volume.go @@ -0,0 +1,138 @@ +/* +Copyright 2018 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 storage + +import ( + "fmt" + "strings" + "time" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/rand" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/storage/utils" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = utils.SIGDescribe("Ephemeralstorage", func() { + var ( + c clientset.Interface + ) + + f := framework.NewDefaultFramework("pv") + + BeforeEach(func() { + c = f.ClientSet + }) + + Describe("When pod refers to non-existent ephemeral storage", func() { + for _, testSource := range invalidEphemeralSource("pod-ephm-test") { + It(fmt.Sprintf("should allow deletion of pod with invalid volume : %s", testSource.volumeType), func() { + pod := testEphemeralVolumePod(f, testSource.volumeType, testSource.source) + pod, err := c.CoreV1().Pods(f.Namespace.Name).Create(pod) + Expect(err).NotTo(HaveOccurred()) + + // Allow it to sleep for 30 seconds + time.Sleep(30 * time.Second) + framework.Logf("Deleting pod %q/%q", pod.Namespace, pod.Name) + framework.ExpectNoError(framework.DeletePodWithWait(f, c, pod)) + }) + } + }) +}) + +type ephemeralTestInfo struct { + volumeType string + source *v1.VolumeSource +} + +func testEphemeralVolumePod(f *framework.Framework, volumeType string, source *v1.VolumeSource) *v1.Pod { + var ( + suffix = strings.ToLower(fmt.Sprintf("%s-%s", volumeType, rand.String(4))) + ) + return &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("pod-ephm-test-%s", suffix), + Namespace: f.Namespace.Name, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: fmt.Sprintf("test-container-subpath-%s", suffix), + Image: mountImage, + VolumeMounts: []v1.VolumeMount{ + { + Name: volumeName, + MountPath: volumePath, + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + Volumes: []v1.Volume{ + { + Name: volumeName, + VolumeSource: *source, + }, + }, + }, + } +} + +func invalidEphemeralSource(suffix string) []ephemeralTestInfo { + testInfo := []ephemeralTestInfo{ + { + volumeType: "secret", + source: &v1.VolumeSource{ + Secret: &v1.SecretVolumeSource{ + SecretName: fmt.Sprintf("secert-%s", suffix), + }, + }, + }, + { + volumeType: "configmap", + source: &v1.VolumeSource{ + ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: fmt.Sprintf("configmap-%s", suffix), + }, + }, + }, + }, + { + volumeType: "projected", + source: &v1.VolumeSource{ + Projected: &v1.ProjectedVolumeSource{ + Sources: []v1.VolumeProjection{ + { + Secret: &v1.SecretProjection{ + LocalObjectReference: v1.LocalObjectReference{ + Name: fmt.Sprintf("secret-%s", suffix), + }, + }, + }, + }, + }, + }, + }, + } + return testInfo +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/flexvolume.go b/vendor/k8s.io/kubernetes/test/e2e/storage/flexvolume.go index 0030e9841..71562366e 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/flexvolume.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/flexvolume.go @@ -190,8 +190,8 @@ var _ = utils.SIGDescribe("Flexvolumes [Disruptive]", func() { BeforeEach(func() { framework.SkipUnlessProviderIs("gce") - framework.SkipUnlessMasterOSDistroIs("gci") - framework.SkipUnlessNodeOSDistroIs("debian", "gci") + framework.SkipUnlessMasterOSDistroIs("gci", "custom") + framework.SkipUnlessNodeOSDistroIs("debian", "gci", "custom") framework.SkipUnlessSSHKeyPresent() cs = f.ClientSet diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/generic_persistent_volume-disruptive.go b/vendor/k8s.io/kubernetes/test/e2e/storage/generic_persistent_volume-disruptive.go new file mode 100644 index 000000000..92b04b2af --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/generic_persistent_volume-disruptive.go @@ -0,0 +1,103 @@ +/* +Copyright 2018 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 storage + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "k8s.io/api/core/v1" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/storage/utils" +) + +var _ = utils.SIGDescribe("GenericPersistentVolume[Disruptive]", func() { + f := framework.NewDefaultFramework("generic-disruptive-pv") + var ( + c clientset.Interface + ns string + ) + + BeforeEach(func() { + // Skip tests unless number of nodes is 2 + framework.SkipUnlessNodeCountIsAtLeast(2) + framework.SkipIfProviderIs("local") + c = f.ClientSet + ns = f.Namespace.Name + }) + disruptiveTestTable := []disruptiveTest{ + { + testItStmt: "Should test that a file written to the mount before kubelet restart is readable after restart.", + runTest: utils.TestKubeletRestartsAndRestoresMount, + }, + { + testItStmt: "Should test that a volume mounted to a pod that is deleted while the kubelet is down unmounts when the kubelet returns.", + runTest: utils.TestVolumeUnmountsFromDeletedPod, + }, + { + testItStmt: "Should test that a volume mounted to a pod that is force deleted while the kubelet is down unmounts when the kubelet returns.", + runTest: utils.TestVolumeUnmountsFromForceDeletedPod, + }, + } + Context("When kubelet restarts", func() { + // Test table housing the It() title string and test spec. runTest is type testBody, defined at + // the start of this file. To add tests, define a function mirroring the testBody signature and assign + // to runTest. + var ( + clientPod *v1.Pod + pvc *v1.PersistentVolumeClaim + ) + BeforeEach(func() { + framework.Logf("Initializing pod and pvcs for test") + clientPod, pvc = createPodPVCFromSC(f, c, ns) + }) + for _, test := range disruptiveTestTable { + func(t disruptiveTest) { + It(t.testItStmt, func() { + By("Executing Spec") + t.runTest(c, f, clientPod) + }) + }(test) + } + AfterEach(func() { + framework.Logf("Tearing down test spec") + tearDownTestCase(c, f, ns, clientPod, pvc, nil) + pvc, clientPod = nil, nil + }) + }) +}) + +func createPodPVCFromSC(f *framework.Framework, c clientset.Interface, ns string) (*v1.Pod, *v1.PersistentVolumeClaim) { + var err error + test := storageClassTest{ + name: "default", + claimSize: "2Gi", + } + pvc := newClaim(test, ns, "default") + pvc, err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Create(pvc) + Expect(err).NotTo(HaveOccurred(), "Error creating pvc") + pvcClaims := []*v1.PersistentVolumeClaim{pvc} + pvs, err := framework.WaitForPVClaimBoundPhase(c, pvcClaims, framework.ClaimProvisionTimeout) + Expect(err).NotTo(HaveOccurred(), "Failed waiting for PVC to be bound %v", err) + Expect(len(pvs)).To(Equal(1)) + + By("Creating a pod with dynamically provisioned volume") + pod, err := framework.CreateNginxPod(c, ns, nil, pvcClaims) + Expect(err).NotTo(HaveOccurred(), "While creating pods for kubelet restart test") + return pod, pvc +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/mounted_volume_resize.go b/vendor/k8s.io/kubernetes/test/e2e/storage/mounted_volume_resize.go index 895e561cf..d7eedfc8f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/mounted_volume_resize.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/mounted_volume_resize.go @@ -21,8 +21,8 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" storage "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -34,7 +34,7 @@ import ( "k8s.io/kubernetes/test/e2e/storage/utils" ) -var _ = utils.SIGDescribe("Mounted volume expand [Feature:ExpandPersistentVolumes] [Slow]", func() { +var _ = utils.SIGDescribe("Mounted volume expand[Slow]", func() { var ( c clientset.Interface ns string @@ -113,7 +113,8 @@ var _ = utils.SIGDescribe("Mounted volume expand [Feature:ExpandPersistentVolume By("Creating a deployment with the provisioned volume") deployment, err := framework.CreateDeployment(c, int32(1), map[string]string{"test": "app"}, nodeKeyValueLabel, ns, pvcClaims, "") - defer c.ExtensionsV1beta1().Deployments(ns).Delete(deployment.Name, &metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred(), "Failed creating deployment %v", err) + defer c.AppsV1().Deployments(ns).Delete(deployment.Name, &metav1.DeleteOptions{}) By("Expanding current pvc") newSize := resource.MustParse("6Gi") @@ -152,7 +153,7 @@ var _ = utils.SIGDescribe("Mounted volume expand [Feature:ExpandPersistentVolume }) }) -func waitForDeploymentToRecreatePod(client clientset.Interface, deployment *extensions.Deployment) (v1.Pod, error) { +func waitForDeploymentToRecreatePod(client clientset.Interface, deployment *apps.Deployment) (v1.Pod, error) { var runningPod v1.Pod waitErr := wait.PollImmediate(10*time.Second, 5*time.Minute, func() (bool, error) { podList, err := framework.GetPodsForDeployment(client, deployment) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/nfs_persistent_volume-disruptive.go b/vendor/k8s.io/kubernetes/test/e2e/storage/nfs_persistent_volume-disruptive.go new file mode 100644 index 000000000..15eef501a --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/nfs_persistent_volume-disruptive.go @@ -0,0 +1,285 @@ +/* +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 storage + +import ( + "fmt" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/storage/utils" +) + +type testBody func(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod) +type disruptiveTest struct { + testItStmt string + runTest testBody +} + +const ( + MinNodes = 2 +) + +var _ = utils.SIGDescribe("NFSPersistentVolumes[Disruptive][Flaky]", func() { + + f := framework.NewDefaultFramework("disruptive-pv") + var ( + c clientset.Interface + ns string + nfsServerPod *v1.Pod + nfsPVconfig framework.PersistentVolumeConfig + pvcConfig framework.PersistentVolumeClaimConfig + nfsServerIP, clientNodeIP string + clientNode *v1.Node + volLabel labels.Set + selector *metav1.LabelSelector + ) + + BeforeEach(func() { + // To protect the NFS volume pod from the kubelet restart, we isolate it on its own node. + framework.SkipUnlessNodeCountIsAtLeast(MinNodes) + framework.SkipIfProviderIs("local") + + c = f.ClientSet + ns = f.Namespace.Name + volLabel = labels.Set{framework.VolumeSelectorKey: ns} + selector = metav1.SetAsLabelSelector(volLabel) + // Start the NFS server pod. + _, nfsServerPod, nfsServerIP = framework.NewNFSServer(c, ns, []string{"-G", "777", "/exports"}) + nfsPVconfig = framework.PersistentVolumeConfig{ + NamePrefix: "nfs-", + Labels: volLabel, + PVSource: v1.PersistentVolumeSource{ + NFS: &v1.NFSVolumeSource{ + Server: nfsServerIP, + Path: "/exports", + ReadOnly: false, + }, + }, + } + emptyStorageClass := "" + pvcConfig = framework.PersistentVolumeClaimConfig{ + Selector: selector, + StorageClassName: &emptyStorageClass, + } + // Get the first ready node IP that is not hosting the NFS pod. + if clientNodeIP == "" { + framework.Logf("Designating test node") + nodes := framework.GetReadySchedulableNodesOrDie(c) + for _, node := range nodes.Items { + if node.Name != nfsServerPod.Spec.NodeName { + clientNode = &node + clientNodeIP = framework.GetNodeExternalIP(clientNode) + break + } + } + Expect(clientNodeIP).NotTo(BeEmpty()) + } + }) + + AfterEach(func() { + framework.DeletePodWithWait(f, c, nfsServerPod) + }) + + Context("when kube-controller-manager restarts", func() { + var ( + diskName1, diskName2 string + err error + pvConfig1, pvConfig2 framework.PersistentVolumeConfig + pv1, pv2 *v1.PersistentVolume + pvSource1, pvSource2 *v1.PersistentVolumeSource + pvc1, pvc2 *v1.PersistentVolumeClaim + clientPod *v1.Pod + ) + + BeforeEach(func() { + framework.SkipUnlessProviderIs("gce") + framework.SkipUnlessSSHKeyPresent() + + By("Initializing first PD with PVPVC binding") + pvSource1, diskName1 = framework.CreateGCEVolume() + Expect(err).NotTo(HaveOccurred()) + pvConfig1 = framework.PersistentVolumeConfig{ + NamePrefix: "gce-", + Labels: volLabel, + PVSource: *pvSource1, + Prebind: nil, + } + pv1, pvc1, err = framework.CreatePVPVC(c, pvConfig1, pvcConfig, ns, false) + Expect(err).NotTo(HaveOccurred()) + framework.ExpectNoError(framework.WaitOnPVandPVC(c, ns, pv1, pvc1)) + + By("Initializing second PD with PVPVC binding") + pvSource2, diskName2 = framework.CreateGCEVolume() + Expect(err).NotTo(HaveOccurred()) + pvConfig2 = framework.PersistentVolumeConfig{ + NamePrefix: "gce-", + Labels: volLabel, + PVSource: *pvSource2, + Prebind: nil, + } + pv2, pvc2, err = framework.CreatePVPVC(c, pvConfig2, pvcConfig, ns, false) + Expect(err).NotTo(HaveOccurred()) + framework.ExpectNoError(framework.WaitOnPVandPVC(c, ns, pv2, pvc2)) + + By("Attaching both PVC's to a single pod") + clientPod, err = framework.CreatePod(c, ns, nil, []*v1.PersistentVolumeClaim{pvc1, pvc2}, true, "") + Expect(err).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + // Delete client/user pod first + framework.ExpectNoError(framework.DeletePodWithWait(f, c, clientPod)) + + // Delete PV and PVCs + if errs := framework.PVPVCCleanup(c, ns, pv1, pvc1); len(errs) > 0 { + framework.Failf("AfterEach: Failed to delete PVC and/or PV. Errors: %v", utilerrors.NewAggregate(errs)) + } + pv1, pvc1 = nil, nil + if errs := framework.PVPVCCleanup(c, ns, pv2, pvc2); len(errs) > 0 { + framework.Failf("AfterEach: Failed to delete PVC and/or PV. Errors: %v", utilerrors.NewAggregate(errs)) + } + pv2, pvc2 = nil, nil + + // Delete the actual disks + if diskName1 != "" { + framework.ExpectNoError(framework.DeletePDWithRetry(diskName1)) + } + if diskName2 != "" { + framework.ExpectNoError(framework.DeletePDWithRetry(diskName2)) + } + }) + + It("should delete a bound PVC from a clientPod, restart the kube-control-manager, and ensure the kube-controller-manager does not crash", func() { + By("Deleting PVC for volume 2") + err = framework.DeletePersistentVolumeClaim(c, pvc2.Name, ns) + Expect(err).NotTo(HaveOccurred()) + pvc2 = nil + + By("Restarting the kube-controller-manager") + err = framework.RestartControllerManager() + Expect(err).NotTo(HaveOccurred()) + err = framework.WaitForControllerManagerUp() + Expect(err).NotTo(HaveOccurred()) + framework.Logf("kube-controller-manager restarted") + + By("Observing the kube-controller-manager healthy for at least 2 minutes") + // Continue checking for 2 minutes to make sure kube-controller-manager is healthy + err = framework.CheckForControllerManagerHealthy(2 * time.Minute) + Expect(err).NotTo(HaveOccurred()) + }) + + }) + + Context("when kubelet restarts", func() { + var ( + clientPod *v1.Pod + pv *v1.PersistentVolume + pvc *v1.PersistentVolumeClaim + ) + + BeforeEach(func() { + framework.Logf("Initializing test spec") + clientPod, pv, pvc = initTestCase(f, c, nfsPVconfig, pvcConfig, ns, clientNode.Name) + }) + + AfterEach(func() { + framework.Logf("Tearing down test spec") + tearDownTestCase(c, f, ns, clientPod, pvc, pv) + pv, pvc, clientPod = nil, nil, nil + }) + + // Test table housing the It() title string and test spec. runTest is type testBody, defined at + // the start of this file. To add tests, define a function mirroring the testBody signature and assign + // to runTest. + disruptiveTestTable := []disruptiveTest{ + { + testItStmt: "Should test that a file written to the mount before kubelet restart is readable after restart.", + runTest: utils.TestKubeletRestartsAndRestoresMount, + }, + { + testItStmt: "Should test that a volume mounted to a pod that is deleted while the kubelet is down unmounts when the kubelet returns.", + runTest: utils.TestVolumeUnmountsFromDeletedPod, + }, + { + testItStmt: "Should test that a volume mounted to a pod that is force deleted while the kubelet is down unmounts when the kubelet returns.", + runTest: utils.TestVolumeUnmountsFromForceDeletedPod, + }, + } + + // Test loop executes each disruptiveTest iteratively. + for _, test := range disruptiveTestTable { + func(t disruptiveTest) { + It(t.testItStmt, func() { + By("Executing Spec") + t.runTest(c, f, clientPod) + }) + }(test) + } + }) +}) + +// initTestCase initializes spec resources (pv, pvc, and pod) and returns pointers to be consumed +// by the test. +func initTestCase(f *framework.Framework, c clientset.Interface, pvConfig framework.PersistentVolumeConfig, pvcConfig framework.PersistentVolumeClaimConfig, ns, nodeName string) (*v1.Pod, *v1.PersistentVolume, *v1.PersistentVolumeClaim) { + pv, pvc, err := framework.CreatePVPVC(c, pvConfig, pvcConfig, ns, false) + defer func() { + if err != nil { + framework.DeletePersistentVolumeClaim(c, pvc.Name, ns) + framework.DeletePersistentVolume(c, pv.Name) + } + }() + Expect(err).NotTo(HaveOccurred()) + pod := framework.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, "") + pod.Spec.NodeName = nodeName + framework.Logf("Creating NFS client pod.") + pod, err = c.CoreV1().Pods(ns).Create(pod) + framework.Logf("NFS client Pod %q created on Node %q", pod.Name, nodeName) + Expect(err).NotTo(HaveOccurred()) + defer func() { + if err != nil { + framework.DeletePodWithWait(f, c, pod) + } + }() + err = framework.WaitForPodRunningInNamespace(c, pod) + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Pod %q timed out waiting for phase: Running", pod.Name)) + // Return created api objects + pod, err = c.CoreV1().Pods(ns).Get(pod.Name, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + pvc, err = c.CoreV1().PersistentVolumeClaims(ns).Get(pvc.Name, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + pv, err = c.CoreV1().PersistentVolumes().Get(pv.Name, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + return pod, pv, pvc +} + +// tearDownTestCase destroy resources created by initTestCase. +func tearDownTestCase(c clientset.Interface, f *framework.Framework, ns string, client *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) { + // Ignore deletion errors. Failing on them will interrupt test cleanup. + framework.DeletePodWithWait(f, c, client) + framework.DeletePersistentVolumeClaim(c, pvc.Name, ns) + if pv != nil { + framework.DeletePersistentVolume(c, pv.Name) + } +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/pd.go b/vendor/k8s.io/kubernetes/test/e2e/storage/pd.go index e67086fd5..6ce4ff27a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/pd.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/pd.go @@ -38,7 +38,6 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" v1core "k8s.io/client-go/kubernetes/typed/core/v1" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/utils" ) @@ -541,7 +540,7 @@ func testPDPod(diskNames []string, targetNode types.NodeName, readOnly bool, num pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: "pd-test-" + string(uuid.NewUUID()), diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-disruptive.go b/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-disruptive.go deleted file mode 100644 index 43b0684ff..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-disruptive.go +++ /dev/null @@ -1,284 +0,0 @@ -/* -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 storage - -import ( - "fmt" - "time" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/test/e2e/framework" - "k8s.io/kubernetes/test/e2e/storage/utils" -) - -type testBody func(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod) -type disruptiveTest struct { - testItStmt string - runTest testBody -} - -const ( - MinNodes = 2 -) - -var _ = utils.SIGDescribe("PersistentVolumes[Disruptive][Flaky]", func() { - - f := framework.NewDefaultFramework("disruptive-pv") - var ( - c clientset.Interface - ns string - nfsServerPod *v1.Pod - nfsPVconfig framework.PersistentVolumeConfig - pvcConfig framework.PersistentVolumeClaimConfig - nfsServerIP, clientNodeIP string - clientNode *v1.Node - volLabel labels.Set - selector *metav1.LabelSelector - ) - - BeforeEach(func() { - // To protect the NFS volume pod from the kubelet restart, we isolate it on its own node. - framework.SkipUnlessNodeCountIsAtLeast(MinNodes) - framework.SkipIfProviderIs("local") - - c = f.ClientSet - ns = f.Namespace.Name - volLabel = labels.Set{framework.VolumeSelectorKey: ns} - selector = metav1.SetAsLabelSelector(volLabel) - // Start the NFS server pod. - _, nfsServerPod, nfsServerIP = framework.NewNFSServer(c, ns, []string{"-G", "777", "/exports"}) - nfsPVconfig = framework.PersistentVolumeConfig{ - NamePrefix: "nfs-", - Labels: volLabel, - PVSource: v1.PersistentVolumeSource{ - NFS: &v1.NFSVolumeSource{ - Server: nfsServerIP, - Path: "/exports", - ReadOnly: false, - }, - }, - } - pvcConfig = framework.PersistentVolumeClaimConfig{ - Annotations: map[string]string{ - v1.BetaStorageClassAnnotation: "", - }, - Selector: selector, - } - // Get the first ready node IP that is not hosting the NFS pod. - if clientNodeIP == "" { - framework.Logf("Designating test node") - nodes := framework.GetReadySchedulableNodesOrDie(c) - for _, node := range nodes.Items { - if node.Name != nfsServerPod.Spec.NodeName { - clientNode = &node - clientNodeIP = framework.GetNodeExternalIP(clientNode) - break - } - } - Expect(clientNodeIP).NotTo(BeEmpty()) - } - }) - - AfterEach(func() { - framework.DeletePodWithWait(f, c, nfsServerPod) - }) - - Context("when kube-controller-manager restarts", func() { - var ( - diskName1, diskName2 string - err error - pvConfig1, pvConfig2 framework.PersistentVolumeConfig - pv1, pv2 *v1.PersistentVolume - pvSource1, pvSource2 *v1.PersistentVolumeSource - pvc1, pvc2 *v1.PersistentVolumeClaim - clientPod *v1.Pod - ) - - BeforeEach(func() { - framework.SkipUnlessProviderIs("gce") - framework.SkipUnlessSSHKeyPresent() - - By("Initializing first PD with PVPVC binding") - pvSource1, diskName1 = framework.CreateGCEVolume() - Expect(err).NotTo(HaveOccurred()) - pvConfig1 = framework.PersistentVolumeConfig{ - NamePrefix: "gce-", - Labels: volLabel, - PVSource: *pvSource1, - Prebind: nil, - } - pv1, pvc1, err = framework.CreatePVPVC(c, pvConfig1, pvcConfig, ns, false) - Expect(err).NotTo(HaveOccurred()) - framework.ExpectNoError(framework.WaitOnPVandPVC(c, ns, pv1, pvc1)) - - By("Initializing second PD with PVPVC binding") - pvSource2, diskName2 = framework.CreateGCEVolume() - Expect(err).NotTo(HaveOccurred()) - pvConfig2 = framework.PersistentVolumeConfig{ - NamePrefix: "gce-", - Labels: volLabel, - PVSource: *pvSource2, - Prebind: nil, - } - pv2, pvc2, err = framework.CreatePVPVC(c, pvConfig2, pvcConfig, ns, false) - Expect(err).NotTo(HaveOccurred()) - framework.ExpectNoError(framework.WaitOnPVandPVC(c, ns, pv2, pvc2)) - - By("Attaching both PVC's to a single pod") - clientPod, err = framework.CreatePod(c, ns, nil, []*v1.PersistentVolumeClaim{pvc1, pvc2}, true, "") - Expect(err).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - // Delete client/user pod first - framework.ExpectNoError(framework.DeletePodWithWait(f, c, clientPod)) - - // Delete PV and PVCs - if errs := framework.PVPVCCleanup(c, ns, pv1, pvc1); len(errs) > 0 { - framework.Failf("AfterEach: Failed to delete PVC and/or PV. Errors: %v", utilerrors.NewAggregate(errs)) - } - pv1, pvc1 = nil, nil - if errs := framework.PVPVCCleanup(c, ns, pv2, pvc2); len(errs) > 0 { - framework.Failf("AfterEach: Failed to delete PVC and/or PV. Errors: %v", utilerrors.NewAggregate(errs)) - } - pv2, pvc2 = nil, nil - - // Delete the actual disks - if diskName1 != "" { - framework.ExpectNoError(framework.DeletePDWithRetry(diskName1)) - } - if diskName2 != "" { - framework.ExpectNoError(framework.DeletePDWithRetry(diskName2)) - } - }) - - It("should delete a bound PVC from a clientPod, restart the kube-control-manager, and ensure the kube-controller-manager does not crash", func() { - By("Deleting PVC for volume 2") - err = framework.DeletePersistentVolumeClaim(c, pvc2.Name, ns) - Expect(err).NotTo(HaveOccurred()) - pvc2 = nil - - By("Restarting the kube-controller-manager") - err = framework.RestartControllerManager() - Expect(err).NotTo(HaveOccurred()) - err = framework.WaitForControllerManagerUp() - Expect(err).NotTo(HaveOccurred()) - framework.Logf("kube-controller-manager restarted") - - By("Observing the kube-controller-manager healthy for at least 2 minutes") - // Continue checking for 2 minutes to make sure kube-controller-manager is healthy - err = framework.CheckForControllerManagerHealthy(2 * time.Minute) - Expect(err).NotTo(HaveOccurred()) - }) - - }) - - Context("when kubelet restarts", func() { - var ( - clientPod *v1.Pod - pv *v1.PersistentVolume - pvc *v1.PersistentVolumeClaim - ) - - BeforeEach(func() { - framework.Logf("Initializing test spec") - clientPod, pv, pvc = initTestCase(f, c, nfsPVconfig, pvcConfig, ns, clientNode.Name) - }) - - AfterEach(func() { - framework.Logf("Tearing down test spec") - tearDownTestCase(c, f, ns, clientPod, pvc, pv) - pv, pvc, clientPod = nil, nil, nil - }) - - // Test table housing the It() title string and test spec. runTest is type testBody, defined at - // the start of this file. To add tests, define a function mirroring the testBody signature and assign - // to runTest. - disruptiveTestTable := []disruptiveTest{ - { - testItStmt: "Should test that a file written to the mount before kubelet restart is readable after restart.", - runTest: utils.TestKubeletRestartsAndRestoresMount, - }, - { - testItStmt: "Should test that a volume mounted to a pod that is deleted while the kubelet is down unmounts when the kubelet returns.", - runTest: utils.TestVolumeUnmountsFromDeletedPod, - }, - { - testItStmt: "Should test that a volume mounted to a pod that is force deleted while the kubelet is down unmounts when the kubelet returns.", - runTest: utils.TestVolumeUnmountsFromForceDeletedPod, - }, - } - - // Test loop executes each disruptiveTest iteratively. - for _, test := range disruptiveTestTable { - func(t disruptiveTest) { - It(t.testItStmt, func() { - By("Executing Spec") - t.runTest(c, f, clientPod) - }) - }(test) - } - }) -}) - -// initTestCase initializes spec resources (pv, pvc, and pod) and returns pointers to be consumed -// by the test. -func initTestCase(f *framework.Framework, c clientset.Interface, pvConfig framework.PersistentVolumeConfig, pvcConfig framework.PersistentVolumeClaimConfig, ns, nodeName string) (*v1.Pod, *v1.PersistentVolume, *v1.PersistentVolumeClaim) { - pv, pvc, err := framework.CreatePVPVC(c, pvConfig, pvcConfig, ns, false) - defer func() { - if err != nil { - framework.DeletePersistentVolumeClaim(c, pvc.Name, ns) - framework.DeletePersistentVolume(c, pv.Name) - } - }() - Expect(err).NotTo(HaveOccurred()) - pod := framework.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, "") - pod.Spec.NodeName = nodeName - framework.Logf("Creating NFS client pod.") - pod, err = c.CoreV1().Pods(ns).Create(pod) - framework.Logf("NFS client Pod %q created on Node %q", pod.Name, nodeName) - Expect(err).NotTo(HaveOccurred()) - defer func() { - if err != nil { - framework.DeletePodWithWait(f, c, pod) - } - }() - err = framework.WaitForPodRunningInNamespace(c, pod) - Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Pod %q timed out waiting for phase: Running", pod.Name)) - // Return created api objects - pod, err = c.CoreV1().Pods(ns).Get(pod.Name, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - pvc, err = c.CoreV1().PersistentVolumeClaims(ns).Get(pvc.Name, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - pv, err = c.CoreV1().PersistentVolumes().Get(pv.Name, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - return pod, pv, pvc -} - -// tearDownTestCase destroy resources created by initTestCase. -func tearDownTestCase(c clientset.Interface, f *framework.Framework, ns string, client *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) { - // Ignore deletion errors. Failing on them will interrupt test cleanup. - framework.DeletePodWithWait(f, c, client) - framework.DeletePersistentVolumeClaim(c, pvc.Name, ns) - framework.DeletePersistentVolume(c, pv.Name) -} diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-gce.go b/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-gce.go index 08a2c4afa..d860ce009 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-gce.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-gce.go @@ -93,11 +93,10 @@ var _ = utils.SIGDescribe("PersistentVolumes GCEPD", func() { }, Prebind: nil, } + emptyStorageClass := "" pvcConfig = framework.PersistentVolumeClaimConfig{ - Annotations: map[string]string{ - v1.BetaStorageClassAnnotation: "", - }, - Selector: selector, + Selector: selector, + StorageClassName: &emptyStorageClass, } clientPod, pv, pvc = initializeGCETestSpec(c, ns, pvConfig, pvcConfig, false) node = types.NodeName(clientPod.Spec.NodeName) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-local.go b/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-local.go index b7ceb5c06..4406d3589 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-local.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes-local.go @@ -63,26 +63,44 @@ type localVolumeType string const ( // default local volume type, aka a directory DirectoryLocalVolumeType localVolumeType = "dir" + // like DirectoryLocalVolumeType but it's a symbolic link to directory + DirectoryLinkLocalVolumeType localVolumeType = "dir-link" + // like DirectoryLocalVolumeType but bind mounted + DirectoryBindMountedLocalVolumeType localVolumeType = "dir-bindmounted" + // like DirectoryLocalVolumeType but it's a symbolic link to self bind mounted directory + // Note that bind mounting at symbolic link actually mounts at directory it + // links to. + DirectoryLinkBindMountedLocalVolumeType localVolumeType = "dir-link-bindmounted" // creates a tmpfs and mounts it TmpfsLocalVolumeType localVolumeType = "tmpfs" // tests based on local ssd at /mnt/disks/by-uuid/ GCELocalSSDVolumeType localVolumeType = "gce-localssd-scsi-fs" // Creates a local file, formats it, and maps it as a block device. BlockLocalVolumeType localVolumeType = "block" + // Creates a local file, formats it, and mounts it to use as local volume. + BlockFsLocalVolumeType localVolumeType = "blockfs" ) var setupLocalVolumeMap = map[localVolumeType]func(*localTestConfig, *v1.Node) *localTestVolume{ - GCELocalSSDVolumeType: setupLocalVolumeGCELocalSSD, - TmpfsLocalVolumeType: setupLocalVolumeTmpfs, - DirectoryLocalVolumeType: setupLocalVolumeDirectory, - BlockLocalVolumeType: setupLocalVolumeBlock, + GCELocalSSDVolumeType: setupLocalVolumeGCELocalSSD, + TmpfsLocalVolumeType: setupLocalVolumeTmpfs, + DirectoryLocalVolumeType: setupLocalVolumeDirectory, + DirectoryLinkLocalVolumeType: setupLocalVolumeDirectoryLink, + DirectoryBindMountedLocalVolumeType: setupLocalVolumeDirectoryBindMounted, + DirectoryLinkBindMountedLocalVolumeType: setupLocalVolumeDirectoryLinkBindMounted, + BlockLocalVolumeType: setupLocalVolumeBlock, + BlockFsLocalVolumeType: setupLocalVolumeBlockFs, } var cleanupLocalVolumeMap = map[localVolumeType]func(*localTestConfig, *localTestVolume){ - GCELocalSSDVolumeType: cleanupLocalVolumeGCELocalSSD, - TmpfsLocalVolumeType: cleanupLocalVolumeTmpfs, - DirectoryLocalVolumeType: cleanupLocalVolumeDirectory, - BlockLocalVolumeType: cleanupLocalVolumeBlock, + GCELocalSSDVolumeType: cleanupLocalVolumeGCELocalSSD, + TmpfsLocalVolumeType: cleanupLocalVolumeTmpfs, + DirectoryLocalVolumeType: cleanupLocalVolumeDirectory, + DirectoryLinkLocalVolumeType: cleanupLocalVolumeDirectoryLink, + DirectoryBindMountedLocalVolumeType: cleanupLocalVolumeDirectoryBindMounted, + DirectoryLinkBindMountedLocalVolumeType: cleanupLocalVolumeDirectoryLinkBindMounted, + BlockLocalVolumeType: cleanupLocalVolumeBlock, + BlockFsLocalVolumeType: cleanupLocalVolumeBlockFs, } type localTestVolume struct { @@ -103,8 +121,7 @@ type localTestVolume struct { const ( // TODO: This may not be available/writable on all images. - hostBase = "/tmp" - containerBase = "/myvol" + hostBase = "/tmp" // Path to the first volume in the test containers // created via createLocalPod or makeLocalPod // leveraging pv_util.MakePod @@ -159,6 +176,8 @@ var _ = utils.SIGDescribe("PersistentVolumes-local ", func() { ) BeforeEach(func() { + framework.SkipUnlessProviderIs(framework.ProvidersWithSSH...) + // Get all the schedulable nodes nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet) Expect(len(nodes.Items)).NotTo(BeZero(), "No available nodes for scheduling") @@ -185,8 +204,7 @@ var _ = utils.SIGDescribe("PersistentVolumes-local ", func() { } }) - localVolumeTypes := []localVolumeType{DirectoryLocalVolumeType, TmpfsLocalVolumeType, GCELocalSSDVolumeType, BlockLocalVolumeType} - for _, tempTestVolType := range localVolumeTypes { + for tempTestVolType := range setupLocalVolumeMap { // New variable required for gingko test closures testVolType := tempTestVolType @@ -226,7 +244,7 @@ var _ = utils.SIGDescribe("PersistentVolumes-local ", func() { BeforeEach(func() { By("Creating pod1") - pod1, pod1Err = createLocalPod(config, testVol) + pod1, pod1Err = createLocalPod(config, testVol, nil) Expect(pod1Err).NotTo(HaveOccurred()) verifyLocalPod(config, testVol, pod1, config.node0.Name) }) @@ -264,12 +282,70 @@ var _ = utils.SIGDescribe("PersistentVolumes-local ", func() { }) }) + Context("Set fsGroup for local volume", func() { + BeforeEach(func() { + if testVolType == BlockLocalVolumeType { + framework.Skipf("We don't set fsGroup on block device, skipped.") + } + }) + + It("should set fsGroup for one pod", func() { + By("Checking fsGroup is set") + pod := createPodWithFsGroupTest(config, testVol, 1234, 1234) + By("Deleting pod") + framework.DeletePodOrFail(config.client, config.ns, pod.Name) + }) + + It("should set same fsGroup for two pods simultaneously", func() { + fsGroup := int64(1234) + By("Create first pod and check fsGroup is set") + pod1 := createPodWithFsGroupTest(config, testVol, fsGroup, fsGroup) + By("Create second pod with same fsGroup and check fsGroup is correct") + pod2 := createPodWithFsGroupTest(config, testVol, fsGroup, fsGroup) + By("Deleting first pod") + framework.DeletePodOrFail(config.client, config.ns, pod1.Name) + By("Deleting second pod") + framework.DeletePodOrFail(config.client, config.ns, pod2.Name) + }) + + It("should set different fsGroup for second pod if first pod is deleted", func() { + fsGroup1, fsGroup2 := int64(1234), int64(4321) + By("Create first pod and check fsGroup is set") + pod1 := createPodWithFsGroupTest(config, testVol, fsGroup1, fsGroup1) + By("Deleting first pod") + err := framework.DeletePodWithWait(f, config.client, pod1) + Expect(err).NotTo(HaveOccurred(), "while deleting first pod") + By("Create second pod and check fsGroup is the new one") + pod2 := createPodWithFsGroupTest(config, testVol, fsGroup2, fsGroup2) + By("Deleting second pod") + framework.DeletePodOrFail(config.client, config.ns, pod2.Name) + }) + + It("should not set different fsGroups for two pods simultaneously", func() { + fsGroup1, fsGroup2 := int64(1234), int64(4321) + By("Create first pod and check fsGroup is set") + pod1 := createPodWithFsGroupTest(config, testVol, fsGroup1, fsGroup1) + By("Create second pod and check fsGroup is still the old one") + pod2 := createPodWithFsGroupTest(config, testVol, fsGroup2, fsGroup1) + ep := &eventPatterns{ + reason: "AlreadyMountedVolume", + pattern: make([]string, 2), + } + ep.pattern = append(ep.pattern, fmt.Sprintf("The requested fsGroup is %d", fsGroup2)) + ep.pattern = append(ep.pattern, "The volume may not be shareable.") + checkPodEvents(config, pod2.Name, ep) + By("Deleting first pod") + framework.DeletePodOrFail(config.client, config.ns, pod1.Name) + By("Deleting second pod") + framework.DeletePodOrFail(config.client, config.ns, pod2.Name) + }) + }) + }) } Context("Local volume that cannot be mounted [Slow]", func() { // TODO: - // - make the pod create timeout shorter // - check for these errors in unit tests intead It("should fail due to non-existent path", func() { ep := &eventPatterns{ @@ -284,7 +360,7 @@ var _ = utils.SIGDescribe("PersistentVolumes-local ", func() { } By("Creating local PVC and PV") createLocalPVCsPVs(config, []*localTestVolume{testVol}, immediateMode) - pod, err := createLocalPod(config, testVol) + pod, err := createLocalPod(config, testVol, nil) Expect(err).To(HaveOccurred()) checkPodEvents(config, pod.Name, ep) cleanupLocalPVCsPVs(config, []*localTestVolume{testVol}) @@ -308,7 +384,7 @@ var _ = utils.SIGDescribe("PersistentVolumes-local ", func() { pod, err := config.client.CoreV1().Pods(config.ns).Create(pod) Expect(err).NotTo(HaveOccurred()) - err = framework.WaitForPodNameRunningInNamespace(config.client, pod.Name, pod.Namespace) + err = framework.WaitTimeoutForPodRunningInNamespace(config.client, pod.Name, pod.Namespace, framework.PodStartShortTimeout) Expect(err).To(HaveOccurred()) checkPodEvents(config, pod.Name, ep) @@ -402,6 +478,50 @@ var _ = utils.SIGDescribe("PersistentVolumes-local ", func() { By("Deleting provisioner daemonset") deleteProvisionerDaemonset(config) }) + It("should not create local persistent volume for filesystem volume that was not bind mounted", func() { + + directoryPath := filepath.Join(config.discoveryDir, "notbindmount") + By("Creating a directory, not bind mounted, in discovery directory") + mkdirCmd := fmt.Sprintf("mkdir -p %v -m 777", directoryPath) + err := framework.IssueSSHCommand(mkdirCmd, framework.TestContext.Provider, config.node0) + Expect(err).NotTo(HaveOccurred()) + + By("Starting a provisioner daemonset") + createProvisionerDaemonset(config) + + By("Allowing provisioner to run for 30s and discover potential local PVs") + time.Sleep(30 * time.Second) + + By("Examining provisioner logs for not an actual mountpoint message") + provisionerPodName := findProvisionerDaemonsetPodName(config) + logs, err := framework.GetPodLogs(config.client, config.ns, provisionerPodName, "" /*containerName*/) + Expect(err).NotTo(HaveOccurred(), + "Error getting logs from pod %s in namespace %s", provisionerPodName, config.ns) + + expectedLogMessage := "Path \"/mnt/local-storage/notbindmount\" is not an actual mountpoint" + Expect(strings.Contains(logs, expectedLogMessage)).To(BeTrue()) + + By("Deleting provisioner daemonset") + deleteProvisionerDaemonset(config) + }) + It("should discover dynamicly created local persistent volume mountpoint in discovery directory", func() { + By("Starting a provisioner daemonset") + createProvisionerDaemonset(config) + + By("Creating a volume in discovery directory") + dynamicVolumePath := path.Join(config.discoveryDir, fmt.Sprintf("vol-%v", string(uuid.NewUUID()))) + setupLocalVolumeProvisionerMountPoint(config, dynamicVolumePath, config.node0) + + By("Waiting for the PersistentVolume to be created") + _, err := waitForLocalPersistentVolume(config.client, dynamicVolumePath) + Expect(err).NotTo(HaveOccurred()) + + By("Deleting provisioner daemonset") + deleteProvisionerDaemonset(config) + + By("Deleting volume in discovery directory") + cleanupLocalVolumeProvisionerMountPoint(config, dynamicVolumePath, config.node0) + }) }) Context("StatefulSet with pod anti-affinity", func() { @@ -521,7 +641,7 @@ var _ = utils.SIGDescribe("PersistentVolumes-local ", func() { pvcs = append(pvcs, pvc) } - pod := framework.MakeSecPod(config.ns, pvcs, false, "sleep 1", false, false, selinuxLabel) + pod := framework.MakeSecPod(config.ns, pvcs, false, "sleep 1", false, false, selinuxLabel, nil) pod, err := config.client.CoreV1().Pods(config.ns).Create(pod) Expect(err).NotTo(HaveOccurred()) pods[pod.Name] = pod @@ -636,7 +756,7 @@ func checkPodEvents(config *localTestConfig, podName string, ep *eventPatterns) // Test two pods at the same time, write from pod1, and read from pod2 func twoPodsReadWriteTest(config *localTestConfig, testVol *localTestVolume) { By("Creating pod1 to write to the PV") - pod1, pod1Err := createLocalPod(config, testVol) + pod1, pod1Err := createLocalPod(config, testVol, nil) Expect(pod1Err).NotTo(HaveOccurred()) verifyLocalPod(config, testVol, pod1, config.node0.Name) @@ -644,7 +764,7 @@ func twoPodsReadWriteTest(config *localTestConfig, testVol *localTestVolume) { testReadFileContent(volumeDir, testFile, testFileContent, pod1, testVol.localVolumeType) By("Creating pod2 to read from the PV") - pod2, pod2Err := createLocalPod(config, testVol) + pod2, pod2Err := createLocalPod(config, testVol, nil) Expect(pod2Err).NotTo(HaveOccurred()) verifyLocalPod(config, testVol, pod2, config.node0.Name) @@ -668,7 +788,7 @@ func twoPodsReadWriteTest(config *localTestConfig, testVol *localTestVolume) { // Test two pods one after other, write from pod1, and read from pod2 func twoPodsReadWriteSerialTest(config *localTestConfig, testVol *localTestVolume) { By("Creating pod1") - pod1, pod1Err := createLocalPod(config, testVol) + pod1, pod1Err := createLocalPod(config, testVol, nil) Expect(pod1Err).NotTo(HaveOccurred()) verifyLocalPod(config, testVol, pod1, config.node0.Name) @@ -684,7 +804,7 @@ func twoPodsReadWriteSerialTest(config *localTestConfig, testVol *localTestVolum framework.DeletePodOrFail(config.client, config.ns, pod1.Name) By("Creating pod2") - pod2, pod2Err := createLocalPod(config, testVol) + pod2, pod2Err := createLocalPod(config, testVol, nil) Expect(pod2Err).NotTo(HaveOccurred()) verifyLocalPod(config, testVol, pod2, config.node0.Name) @@ -695,6 +815,15 @@ func twoPodsReadWriteSerialTest(config *localTestConfig, testVol *localTestVolum framework.DeletePodOrFail(config.client, config.ns, pod2.Name) } +// Test creating pod with fsGroup, and check fsGroup is expected fsGroup. +func createPodWithFsGroupTest(config *localTestConfig, testVol *localTestVolume, fsGroup int64, expectedFsGroup int64) *v1.Pod { + pod, err := createLocalPod(config, testVol, &fsGroup) + framework.ExpectNoError(err) + _, err = framework.LookForStringInPodExec(config.ns, pod.Name, []string{"stat", "-c", "%g", volumeDir}, strconv.FormatInt(expectedFsGroup, 10), time.Second*3) + Expect(err).NotTo(HaveOccurred(), "failed to get expected fsGroup %d on directory %s in pod %s", fsGroup, volumeDir, pod.Name) + return pod +} + func setupStorageClass(config *localTestConfig, mode *storagev1.VolumeBindingMode) { sc := &storagev1.StorageClass{ ObjectMeta: metav1.ObjectMeta{ @@ -786,6 +915,39 @@ func setupLocalVolumeDirectory(config *localTestConfig, node *v1.Node) *localTes return setupWriteTestFile(hostDir, config, DirectoryLocalVolumeType, node) } +func setupLocalVolumeDirectoryLink(config *localTestConfig, node *v1.Node) *localTestVolume { + testDirName := "local-volume-test-" + string(uuid.NewUUID()) + hostDir := filepath.Join(hostBase, testDirName) + hostDirBackend := hostDir + "-backend" + cmd := fmt.Sprintf("mkdir %s && ln -s %s %s", hostDirBackend, hostDirBackend, hostDir) + _, err := framework.IssueSSHCommandWithResult(cmd, framework.TestContext.Provider, node) + Expect(err).NotTo(HaveOccurred()) + // Populate volume with testFile containing testFileContent. + return setupWriteTestFile(hostDir, config, DirectoryLinkLocalVolumeType, node) +} + +func setupLocalVolumeDirectoryBindMounted(config *localTestConfig, node *v1.Node) *localTestVolume { + testDirName := "local-volume-test-" + string(uuid.NewUUID()) + hostDir := filepath.Join(hostBase, testDirName) + cmd := fmt.Sprintf("mkdir %s && sudo mount --bind %s %s", hostDir, hostDir, hostDir) + _, err := framework.IssueSSHCommandWithResult(cmd, framework.TestContext.Provider, node) + Expect(err).NotTo(HaveOccurred()) + // Populate volume with testFile containing testFileContent. + return setupWriteTestFile(hostDir, config, DirectoryBindMountedLocalVolumeType, node) +} + +func setupLocalVolumeDirectoryLinkBindMounted(config *localTestConfig, node *v1.Node) *localTestVolume { + testDirName := "local-volume-test-" + string(uuid.NewUUID()) + hostDir := filepath.Join(hostBase, testDirName) + hostDirBackend := hostDir + "-backend" + cmd := fmt.Sprintf("mkdir %s && sudo mount --bind %s %s && ln -s %s %s", + hostDirBackend, hostDirBackend, hostDirBackend, hostDirBackend, hostDir) + _, err := framework.IssueSSHCommandWithResult(cmd, framework.TestContext.Provider, node) + Expect(err).NotTo(HaveOccurred()) + // Populate volume with testFile containing testFileContent. + return setupWriteTestFile(hostDir, config, DirectoryLinkBindMountedLocalVolumeType, node) +} + func setupLocalVolumeBlock(config *localTestConfig, node *v1.Node) *localTestVolume { testDirName := "local-volume-test-" + string(uuid.NewUUID()) hostDir := filepath.Join(hostBase, testDirName) @@ -798,6 +960,23 @@ func setupLocalVolumeBlock(config *localTestConfig, node *v1.Node) *localTestVol return volume } +func setupLocalVolumeBlockFs(config *localTestConfig, node *v1.Node) *localTestVolume { + testDirName := "local-volume-test-" + string(uuid.NewUUID()) + hostDir := filepath.Join(hostBase, testDirName) + createAndMapBlockLocalVolume(config, hostDir, node) + loopDev := getBlockLoopDev(hostDir, node) + // format and mount at hostDir + // give others rwx for read/write testing + cmd := fmt.Sprintf("sudo mkfs -t ext4 %s && sudo mount -t ext4 %s %s && sudo chmod o+rwx %s", loopDev, loopDev, hostDir, hostDir) + _, err := framework.IssueSSHCommandWithResult(cmd, framework.TestContext.Provider, node) + Expect(err).NotTo(HaveOccurred()) + // Populate block volume with testFile containing testFileContent. + volume := setupWriteTestFile(hostDir, config, BlockFsLocalVolumeType, node) + volume.hostDir = hostDir + volume.loopDevDir = loopDev + return volume +} + // Determine the /dev/loopXXX device associated with this test, via its hostDir. func getBlockLoopDev(hostDir string, node *v1.Node) string { loopDevCmd := fmt.Sprintf("E2E_LOOP_DEV=$(sudo losetup | grep %s/file | awk '{ print $1 }') 2>&1 > /dev/null && echo ${E2E_LOOP_DEV}", hostDir) @@ -843,6 +1022,35 @@ func cleanupLocalVolumeDirectory(config *localTestConfig, volume *localTestVolum Expect(err).NotTo(HaveOccurred()) } +// Deletes the PVC/PV, and launches a pod with hostpath volume to remove the test directory. +func cleanupLocalVolumeDirectoryLink(config *localTestConfig, volume *localTestVolume) { + By("Removing the test directory") + hostDir := volume.hostDir + hostDirBackend := hostDir + "-backend" + removeCmd := fmt.Sprintf("rm -r %s && rm -r %s", hostDir, hostDirBackend) + err := framework.IssueSSHCommand(removeCmd, framework.TestContext.Provider, volume.node) + Expect(err).NotTo(HaveOccurred()) +} + +// Deletes the PVC/PV, and launches a pod with hostpath volume to remove the test directory. +func cleanupLocalVolumeDirectoryBindMounted(config *localTestConfig, volume *localTestVolume) { + By("Removing the test directory") + hostDir := volume.hostDir + removeCmd := fmt.Sprintf("sudo umount %s && rm -r %s", hostDir, hostDir) + err := framework.IssueSSHCommand(removeCmd, framework.TestContext.Provider, volume.node) + Expect(err).NotTo(HaveOccurred()) +} + +// Deletes the PVC/PV, and launches a pod with hostpath volume to remove the test directory. +func cleanupLocalVolumeDirectoryLinkBindMounted(config *localTestConfig, volume *localTestVolume) { + By("Removing the test directory") + hostDir := volume.hostDir + hostDirBackend := hostDir + "-backend" + removeCmd := fmt.Sprintf("rm %s && sudo umount %s && rm -r %s", hostDir, hostDirBackend, hostDirBackend) + err := framework.IssueSSHCommand(removeCmd, framework.TestContext.Provider, volume.node) + Expect(err).NotTo(HaveOccurred()) +} + // Deletes the PVC/PV and removes the test directory holding the block file. func cleanupLocalVolumeBlock(config *localTestConfig, volume *localTestVolume) { volume.hostDir = volume.loopDevDir @@ -853,6 +1061,19 @@ func cleanupLocalVolumeBlock(config *localTestConfig, volume *localTestVolume) { Expect(err).NotTo(HaveOccurred()) } +// Deletes the PVC/PV and removes the test directory holding the block file. +func cleanupLocalVolumeBlockFs(config *localTestConfig, volume *localTestVolume) { + // umount first + By("Umount blockfs mountpoint") + umountCmd := fmt.Sprintf("sudo umount %s", volume.hostDir) + err := framework.IssueSSHCommand(umountCmd, framework.TestContext.Provider, volume.node) + unmapBlockLocalVolume(config, volume.hostDir, volume.node) + By("Removing the test directory") + removeCmd := fmt.Sprintf("rm -r %s", volume.hostDir) + err = framework.IssueSSHCommand(removeCmd, framework.TestContext.Provider, volume.node) + Expect(err).NotTo(HaveOccurred()) +} + func makeLocalPVCConfig(config *localTestConfig, volumeType localVolumeType) framework.PersistentVolumeClaimConfig { pvcConfig := framework.PersistentVolumeClaimConfig{ AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, @@ -940,7 +1161,7 @@ func createLocalPVCsPVs(config *localTestConfig, volumes []*localTestVolume, mod } func makeLocalPod(config *localTestConfig, volume *localTestVolume, cmd string) *v1.Pod { - pod := framework.MakeSecPod(config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, cmd, false, false, selinuxLabel) + pod := framework.MakeSecPod(config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, cmd, false, false, selinuxLabel, nil) if pod == nil { return pod } @@ -952,7 +1173,7 @@ func makeLocalPod(config *localTestConfig, volume *localTestVolume, cmd string) } func makeLocalPodWithNodeAffinity(config *localTestConfig, volume *localTestVolume, nodeName string) (pod *v1.Pod) { - pod = framework.MakeSecPod(config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", false, false, selinuxLabel) + pod = framework.MakeSecPod(config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", false, false, selinuxLabel, nil) if pod == nil { return } @@ -978,7 +1199,7 @@ func makeLocalPodWithNodeAffinity(config *localTestConfig, volume *localTestVolu } func makeLocalPodWithNodeSelector(config *localTestConfig, volume *localTestVolume, nodeName string) (pod *v1.Pod) { - pod = framework.MakeSecPod(config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", false, false, selinuxLabel) + pod = framework.MakeSecPod(config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", false, false, selinuxLabel, nil) if pod == nil { return } @@ -990,7 +1211,7 @@ func makeLocalPodWithNodeSelector(config *localTestConfig, volume *localTestVolu } func makeLocalPodWithNodeName(config *localTestConfig, volume *localTestVolume, nodeName string) (pod *v1.Pod) { - pod = framework.MakeSecPod(config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", false, false, selinuxLabel) + pod = framework.MakeSecPod(config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", false, false, selinuxLabel, nil) if pod == nil { return } @@ -1000,7 +1221,7 @@ func makeLocalPodWithNodeName(config *localTestConfig, volume *localTestVolume, // createSecPod should be used when Pod requires non default SELinux labels func createSecPod(config *localTestConfig, volume *localTestVolume, hostIPC bool, hostPID bool, seLinuxLabel *v1.SELinuxOptions) (*v1.Pod, error) { - pod, err := framework.CreateSecPod(config.client, config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", hostIPC, hostPID, seLinuxLabel) + pod, err := framework.CreateSecPod(config.client, config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", hostIPC, hostPID, seLinuxLabel, nil, framework.PodStartShortTimeout) podNodeName, podNodeNameErr := podNodeName(config, pod) Expect(podNodeNameErr).NotTo(HaveOccurred()) framework.Logf("Security Context POD %q created on Node %q", pod.Name, podNodeName) @@ -1008,9 +1229,9 @@ func createSecPod(config *localTestConfig, volume *localTestVolume, hostIPC bool return pod, err } -func createLocalPod(config *localTestConfig, volume *localTestVolume) (*v1.Pod, error) { +func createLocalPod(config *localTestConfig, volume *localTestVolume, fsGroup *int64) (*v1.Pod, error) { By("Creating a pod") - return framework.CreateSecPod(config.client, config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", false, false, selinuxLabel) + return framework.CreateSecPod(config.client, config.ns, []*v1.PersistentVolumeClaim{volume.pvc}, false, "", false, false, selinuxLabel, fsGroup, framework.PodStartShortTimeout) } func createAndMountTmpfsLocalVolume(config *localTestConfig, dir string, node *v1.Node) { @@ -1291,6 +1512,8 @@ func createVolumeConfigMap(config *localTestConfig) { func createProvisionerDaemonset(config *localTestConfig) { provisionerPrivileged := true + mountProp := v1.MountPropagationHostToContainer + provisioner := &extv1beta1.DaemonSet{ TypeMeta: metav1.TypeMeta{ Kind: "DaemonSet", @@ -1341,8 +1564,9 @@ func createProvisionerDaemonset(config *localTestConfig) { MountPath: "/etc/provisioner/config/", }, { - Name: "local-disks", - MountPath: provisionerDefaultMountRoot, + Name: "local-disks", + MountPath: provisionerDefaultMountRoot, + MountPropagation: &mountProp, }, }, }, @@ -1378,6 +1602,22 @@ func createProvisionerDaemonset(config *localTestConfig) { framework.WaitForControlledPodsRunning(config.client, config.ns, daemonSetName, kind) } +func findProvisionerDaemonsetPodName(config *localTestConfig) string { + podList, err := config.client.CoreV1().Pods(config.ns).List(metav1.ListOptions{}) + if err != nil { + framework.Failf("could not get the pod list: %v", err) + return "" + } + pods := podList.Items + for _, pod := range pods { + if strings.HasPrefix(pod.Name, daemonSetName) && pod.Spec.NodeName == config.node0.Name { + return pod.Name + } + } + framework.Failf("Unable to find provisioner daemonset pod on node0") + return "" +} + func deleteProvisionerDaemonset(config *localTestConfig) { ds, err := config.client.ExtensionsV1beta1().DaemonSets(config.ns).Get(daemonSetName, metav1.GetOptions{}) if ds == nil { diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes.go b/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes.go index 53d28b39b..5d9f99dad 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/persistent_volumes.go @@ -23,6 +23,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -30,6 +31,7 @@ import ( clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/utils" + imageutils "k8s.io/kubernetes/test/utils/image" ) // Validate PV/PVC, create and verify writer pod, delete the PVC, and validate the PV's @@ -132,11 +134,10 @@ var _ = utils.SIGDescribe("PersistentVolumes", func() { }, }, } + emptyStorageClass := "" pvcConfig = framework.PersistentVolumeClaimConfig{ - Annotations: map[string]string{ - v1.BetaStorageClassAnnotation: "", - }, - Selector: selector, + Selector: selector, + StorageClassName: &emptyStorageClass, } }) @@ -282,6 +283,7 @@ var _ = utils.SIGDescribe("PersistentVolumes", func() { framework.ExpectNoError(framework.WaitForPodSuccessInNamespace(c, pod.Name, ns)) By("Deleting the claim") + framework.ExpectNoError(framework.DeletePodWithWait(f, c, pod)) framework.ExpectNoError(framework.DeletePVCandValidatePV(c, ns, pvc, pv, v1.VolumeAvailable)) By("Re-mounting the volume.") @@ -297,8 +299,126 @@ var _ = utils.SIGDescribe("PersistentVolumes", func() { pod, err = c.CoreV1().Pods(ns).Create(pod) Expect(err).NotTo(HaveOccurred()) framework.ExpectNoError(framework.WaitForPodSuccessInNamespace(c, pod.Name, ns)) + framework.ExpectNoError(framework.DeletePodWithWait(f, c, pod)) framework.Logf("Pod exited without failure; the volume has been recycled.") }) }) }) + + Describe("Default StorageClass", func() { + Context("pods that use multiple volumes", func() { + + AfterEach(func() { + framework.DeleteAllStatefulSets(c, ns) + }) + + It("should be reschedulable", func() { + // Only run on providers with default storageclass + framework.SkipUnlessProviderIs("openstack", "gce", "gke", "vsphere", "azure") + + numVols := 4 + ssTester := framework.NewStatefulSetTester(c) + + By("Creating a StatefulSet pod to initialize data") + writeCmd := "true" + for i := 0; i < numVols; i++ { + writeCmd += fmt.Sprintf("&& touch %v", getVolumeFile(i)) + } + writeCmd += "&& sleep 10000" + + probe := &v1.Probe{ + Handler: v1.Handler{ + Exec: &v1.ExecAction{ + // Check that the last file got created + Command: []string{"test", "-f", getVolumeFile(numVols - 1)}, + }, + }, + InitialDelaySeconds: 1, + PeriodSeconds: 1, + } + + mounts := []v1.VolumeMount{} + claims := []v1.PersistentVolumeClaim{} + for i := 0; i < numVols; i++ { + pvc := framework.MakePersistentVolumeClaim(framework.PersistentVolumeClaimConfig{}, ns) + pvc.Name = getVolName(i) + mounts = append(mounts, v1.VolumeMount{Name: pvc.Name, MountPath: getMountPath(i)}) + claims = append(claims, *pvc) + } + + spec := makeStatefulSetWithPVCs(ns, writeCmd, mounts, claims, probe) + ss, err := c.AppsV1().StatefulSets(ns).Create(spec) + Expect(err).NotTo(HaveOccurred()) + ssTester.WaitForRunningAndReady(1, ss) + + By("Deleting the StatefulSet but not the volumes") + // Scale down to 0 first so that the Delete is quick + ss, err = ssTester.Scale(ss, 0) + Expect(err).NotTo(HaveOccurred()) + ssTester.WaitForStatusReplicas(ss, 0) + err = c.AppsV1().StatefulSets(ns).Delete(ss.Name, &metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + + By("Creating a new Statefulset and validating the data") + validateCmd := "true" + for i := 0; i < numVols; i++ { + validateCmd += fmt.Sprintf("&& test -f %v", getVolumeFile(i)) + } + validateCmd += "&& sleep 10000" + + spec = makeStatefulSetWithPVCs(ns, validateCmd, mounts, claims, probe) + ss, err = c.AppsV1().StatefulSets(ns).Create(spec) + Expect(err).NotTo(HaveOccurred()) + ssTester.WaitForRunningAndReady(1, ss) + }) + }) + }) }) + +func getVolName(i int) string { + return fmt.Sprintf("vol%v", i) +} + +func getMountPath(i int) string { + return fmt.Sprintf("/mnt/%v", getVolName(i)) +} + +func getVolumeFile(i int) string { + return fmt.Sprintf("%v/data%v", getMountPath(i), i) +} + +func makeStatefulSetWithPVCs(ns, cmd string, mounts []v1.VolumeMount, claims []v1.PersistentVolumeClaim, readyProbe *v1.Probe) *appsv1.StatefulSet { + ssReplicas := int32(1) + + labels := map[string]string{"app": "many-volumes-test"} + return &appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "many-volumes-test", + Namespace: ns, + }, + Spec: appsv1.StatefulSetSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "many-volumes-test"}, + }, + Replicas: &ssReplicas, + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: labels, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "nginx", + Image: imageutils.GetE2EImage(imageutils.NginxSlim), + Command: []string{"/bin/sh"}, + Args: []string{"-c", cmd}, + VolumeMounts: mounts, + ReadinessProbe: readyProbe, + }, + }, + }, + }, + VolumeClaimTemplates: claims, + }, + } +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/pv_protection.go b/vendor/k8s.io/kubernetes/test/e2e/storage/pv_protection.go index 4c698f3f0..363e212fb 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/pv_protection.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/pv_protection.go @@ -64,11 +64,10 @@ var _ = utils.SIGDescribe("PV Protection", func() { }, } + emptyStorageClass := "" pvcConfig = framework.PersistentVolumeClaimConfig{ - Annotations: map[string]string{ - v1.BetaStorageClassAnnotation: "", - }, - Selector: selector, + Selector: selector, + StorageClassName: &emptyStorageClass, } By("Creating a PV") diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/regional_pd.go b/vendor/k8s.io/kubernetes/test/e2e/storage/regional_pd.go index 361474e08..cc77ad135 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/regional_pd.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/regional_pd.go @@ -21,6 +21,9 @@ import ( . "github.com/onsi/gomega" "fmt" + "strings" + "time" + appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" storage "k8s.io/api/storage/v1" @@ -34,8 +37,6 @@ import ( "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/utils" - "strings" - "time" ) const ( @@ -43,7 +44,7 @@ const ( statefulSetReadyTimeout = 3 * time.Minute ) -var _ = utils.SIGDescribe("Regional PD [Feature:RegionalPD]", func() { +var _ = utils.SIGDescribe("Regional PD", func() { f := framework.NewDefaultFramework("regional-pd") // filled in BeforeEach @@ -204,6 +205,9 @@ func testZonalFailover(c clientset.Interface, ns string) { instanceGroup, err := cloud.GetInstanceGroup(instanceGroupName, podZone) Expect(err).NotTo(HaveOccurred(), "Error getting instance group %s in zone %s", instanceGroupName, podZone) + templateName, err := framework.GetManagedInstanceGroupTemplateName(podZone) + Expect(err).NotTo(HaveOccurred(), + "Error getting instance group template in zone %s", podZone) err = framework.DeleteManagedInstanceGroup(podZone) Expect(err).NotTo(HaveOccurred(), "Error deleting instance group in zone %s", podZone) @@ -211,9 +215,6 @@ func testZonalFailover(c clientset.Interface, ns string) { defer func() { framework.Logf("recreating instance group %s", instanceGroup.Name) - // HACK improve this when Managed Instance Groups are available through the cloud provider API - templateName := strings.Replace(instanceGroupName, "group", "template", 1 /* n */) - framework.ExpectNoError(framework.CreateManagedInstanceGroup(instanceGroup.Size, podZone, templateName), "Error recreating instance group %s in zone %s", instanceGroup.Name, podZone) framework.ExpectNoError(framework.WaitForReadyNodes(c, nodeCount, framework.RestartNodeReadyAgainTimeout), @@ -333,7 +334,7 @@ func newPodTemplate(labels map[string]string) *v1.PodTemplateSpec { // and prints the entire file to stdout. { Name: "busybox", - Image: "gcr.io/google_containers/busybox", + Image: "k8s.gcr.io/busybox", Command: []string{"sh", "-c"}, Args: []string{ "echo ${POD_NAME} >> /mnt/data/regional-pd/pods.txt;" + diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/subpath.go b/vendor/k8s.io/kubernetes/test/e2e/storage/subpath.go index 225744f2c..0acc25c2d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/subpath.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/subpath.go @@ -624,6 +624,8 @@ func testPodContainerRestart(f *framework.Framework, pod *v1.Pod) { } func testSubpathReconstruction(f *framework.Framework, pod *v1.Pod, forceDelete bool) { + // This is mostly copied from TestVolumeUnmountsFromDeletedPodWithForceOption() + // Change to busybox pod.Spec.Containers[0].Image = "busybox" pod.Spec.Containers[0].Command = []string{"/bin/sh", "-ec", "sleep 100000"} @@ -645,7 +647,7 @@ func testSubpathReconstruction(f *framework.Framework, pod *v1.Pod, forceDelete pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(pod.Name, metav1.GetOptions{}) Expect(err).ToNot(HaveOccurred(), "while getting pod") - utils.TestVolumeUnmountsFromDeletedPodWithForceOption(f.ClientSet, f, pod, forceDelete, true /* checkSubpath */) + utils.TestVolumeUnmountsFromDeletedPodWithForceOption(f.ClientSet, f, pod, forceDelete, true) } func initVolumeContent(f *framework.Framework, pod *v1.Pod, volumeFilepath, subpathFilepath string) { @@ -968,7 +970,7 @@ type glusterSource struct { } func initGluster() volSource { - framework.SkipUnlessNodeOSDistroIs("gci", "ubuntu") + framework.SkipUnlessNodeOSDistroIs("gci", "ubuntu", "custom") return &glusterSource{} } diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/utils/utils.go b/vendor/k8s.io/kubernetes/test/e2e/storage/utils/utils.go index 648d7454a..1835cecdb 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/utils/utils.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/utils/utils.go @@ -162,7 +162,7 @@ func TestVolumeUnmountsFromDeletedPodWithForceOption(c clientset.Interface, f *f nodeIP = nodeIP + ":22" By("Expecting the volume mount to be found.") - result, err := framework.SSH(fmt.Sprintf("mount | grep %s | grep --invert-match volume-subpaths", clientPod.UID), nodeIP, framework.TestContext.Provider) + result, err := framework.SSH(fmt.Sprintf("mount | grep %s | grep -v volume-subpaths", clientPod.UID), nodeIP, framework.TestContext.Provider) framework.LogSSHResult(result) Expect(err).NotTo(HaveOccurred(), "Encountered SSH error.") Expect(result.Code).To(BeZero(), fmt.Sprintf("Expected grep exit code of 0, got %d", result.Code)) @@ -204,7 +204,7 @@ func TestVolumeUnmountsFromDeletedPodWithForceOption(c clientset.Interface, f *f } By("Expecting the volume mount not to be found.") - result, err = framework.SSH(fmt.Sprintf("mount | grep %s | grep --invert-match volume-subpaths", clientPod.UID), nodeIP, framework.TestContext.Provider) + result, err = framework.SSH(fmt.Sprintf("mount | grep %s | grep -v volume-subpaths", clientPod.UID), nodeIP, framework.TestContext.Provider) framework.LogSSHResult(result) Expect(err).NotTo(HaveOccurred(), "Encountered SSH error.") Expect(result.Stdout).To(BeEmpty(), "Expected grep stdout to be empty (i.e. no mount found).") @@ -222,12 +222,12 @@ func TestVolumeUnmountsFromDeletedPodWithForceOption(c clientset.Interface, f *f // TestVolumeUnmountsFromDeletedPod tests that a volume unmounts if the client pod was deleted while the kubelet was down. func TestVolumeUnmountsFromDeletedPod(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod) { - TestVolumeUnmountsFromDeletedPodWithForceOption(c, f, clientPod, false /* forceDelete */, false /* checkSubpath */) + TestVolumeUnmountsFromDeletedPodWithForceOption(c, f, clientPod, false, false) } // TestVolumeUnmountsFromFoceDeletedPod tests that a volume unmounts if the client pod was forcefully deleted while the kubelet was down. func TestVolumeUnmountsFromForceDeletedPod(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod) { - TestVolumeUnmountsFromDeletedPodWithForceOption(c, f, clientPod, true /* forceDelete */, false /* checkSubpath */) + TestVolumeUnmountsFromDeletedPodWithForceOption(c, f, clientPod, true, false) } // RunInPodWithVolume runs a command in a pod with given claim mounted to /mnt directory. diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/volume_expand.go b/vendor/k8s.io/kubernetes/test/e2e/storage/volume_expand.go index 231b50ca3..8049d1eda 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/volume_expand.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/volume_expand.go @@ -39,7 +39,7 @@ const ( totalResizeWaitPeriod = 20 * time.Minute ) -var _ = utils.SIGDescribe("Volume expand [Feature:ExpandPersistentVolumes] [Slow]", func() { +var _ = utils.SIGDescribe("Volume expand [Slow]", func() { var ( c clientset.Interface ns string diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/volume_io.go b/vendor/k8s.io/kubernetes/test/e2e/storage/volume_io.go index e9205e4df..9ed5e245f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/volume_io.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/volume_io.go @@ -33,6 +33,7 @@ import ( "path" "strconv" "strings" + "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -64,6 +65,7 @@ var md5hashes = map[int64]string{ func makePodSpec(config framework.VolumeTestConfig, dir, initCmd string, volsrc v1.VolumeSource, podSecContext *v1.PodSecurityContext) *v1.Pod { volName := fmt.Sprintf("%s-%s", config.Prefix, "io-volume") + var gracePeriod int64 = 1 return &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", @@ -110,7 +112,8 @@ func makePodSpec(config framework.VolumeTestConfig, dir, initCmd string, volsrc }, }, }, - SecurityContext: podSecContext, + TerminationGracePeriodSeconds: &gracePeriod, + SecurityContext: podSecContext, Volumes: []v1.Volume{ { Name: volName, @@ -209,6 +212,9 @@ func testVolumeIO(f *framework.Framework, cs clientset.Interface, config framewo if err == nil { // delete err is returned if err is not set err = e } + } else { + framework.Logf("sleeping a bit so kubelet can unmount and detach the volume") + time.Sleep(framework.PodCleanupTimeout) } }() @@ -379,33 +385,11 @@ var _ = utils.SIGDescribe("Volume plugin streaming [Slow]", func() { Describe("Ceph-RBD [Feature:Volumes]", func() { var ( secret *v1.Secret - name string ) testFile := "ceph-rbd_io_test" BeforeEach(func() { - config, serverPod, serverIP = framework.NewRBDServer(cs, ns) - name = config.Prefix + "-server" - - // create server secret - secret = &v1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Data: map[string][]byte{ - // from test/images/volumes-tester/rbd/keyring - "key": []byte("AQDRrKNVbEevChAAEmRC+pW/KBVHxa0w/POILA=="), - }, - Type: "kubernetes.io/rbd", - } - var err error - secret, err = cs.CoreV1().Secrets(ns).Create(secret) - Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("BeforeEach: failed to create secret %q for Ceph-RBD: %v", name, err)) - + config, serverPod, secret, serverIP = framework.NewRBDServer(cs, ns) volSource = v1.VolumeSource{ RBD: &v1.RBDVolumeSource{ CephMonitors: []string{serverIP}, @@ -413,22 +397,22 @@ var _ = utils.SIGDescribe("Volume plugin streaming [Slow]", func() { RBDImage: "foo", RadosUser: "admin", SecretRef: &v1.LocalObjectReference{ - Name: name, + Name: secret.Name, }, FSType: "ext2", - ReadOnly: true, + ReadOnly: false, }, } }) AfterEach(func() { - framework.Logf("AfterEach: deleting Ceph-RDB server secret %q...", name) - secErr := cs.CoreV1().Secrets(ns).Delete(name, &metav1.DeleteOptions{}) + framework.Logf("AfterEach: deleting Ceph-RDB server secret %q...", secret.Name) + secErr := cs.CoreV1().Secrets(ns).Delete(secret.Name, &metav1.DeleteOptions{}) framework.Logf("AfterEach: deleting Ceph-RDB server pod %q...", serverPod.Name) err := framework.DeletePodWithWait(f, cs, serverPod) if secErr != nil || err != nil { if secErr != nil { - framework.Logf("AfterEach: Ceph-RDB delete secret failed: %v", err) + framework.Logf("AfterEach: Ceph-RDB delete secret failed: %v", secErr) } if err != nil { framework.Logf("AfterEach: Ceph-RDB server pod delete failed: %v", err) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/volume_provisioning.go b/vendor/k8s.io/kubernetes/test/e2e/storage/volume_provisioning.go index 97cbaa72c..3a3dec10a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/volume_provisioning.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/volume_provisioning.go @@ -42,7 +42,6 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/authentication/serviceaccount" clientset "k8s.io/client-go/kubernetes" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" storageutil "k8s.io/kubernetes/pkg/apis/storage/v1/util" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/utils" @@ -57,6 +56,8 @@ type storageClassTest struct { expectedSize string pvCheck func(volume *v1.PersistentVolume) error nodeName string + attach bool + volumeMode *v1.PersistentVolumeMode } const ( @@ -120,6 +121,10 @@ func testDynamicProvisioning(t storageClassTest, client clientset.Interface, cla Expect(pv.Spec.PersistentVolumeReclaimPolicy).To(Equal(*class.ReclaimPolicy)) Expect(pv.Spec.MountOptions).To(Equal(class.MountOptions)) } + if t.volumeMode != nil { + Expect(pv.Spec.VolumeMode).NotTo(BeNil()) + Expect(*pv.Spec.VolumeMode).To(Equal(*t.volumeMode)) + } // Run the checker if t.pvCheck != nil { @@ -127,24 +132,25 @@ func testDynamicProvisioning(t storageClassTest, client clientset.Interface, cla Expect(err).NotTo(HaveOccurred()) } - // We start two pods: - // - The first writes 'hello word' to the /mnt/test (= the volume). - // - The second one runs grep 'hello world' on /mnt/test. - // If both succeed, Kubernetes actually allocated something that is - // persistent across pods. - By("checking the created volume is writable and has the PV's mount options") - command := "echo 'hello world' > /mnt/test/data" - // We give the first pod the secondary responsibility of checking the volume has - // been mounted with the PV's mount options, if the PV was provisioned with any - for _, option := range pv.Spec.MountOptions { - // Get entry, get mount options at 6th word, replace brackets with commas - command += fmt.Sprintf(" && ( mount | grep 'on /mnt/test' | awk '{print $6}' | sed 's/^(/,/; s/)$/,/' | grep -q ,%s, )", option) - } - runInPodWithVolume(client, claim.Namespace, claim.Name, t.nodeName, command) - - By("checking the created volume is readable and retains data") - runInPodWithVolume(client, claim.Namespace, claim.Name, t.nodeName, "grep 'hello world' /mnt/test/data") + if t.attach { + // We start two pods: + // - The first writes 'hello word' to the /mnt/test (= the volume). + // - The second one runs grep 'hello world' on /mnt/test. + // If both succeed, Kubernetes actually allocated something that is + // persistent across pods. + By("checking the created volume is writable and has the PV's mount options") + command := "echo 'hello world' > /mnt/test/data" + // We give the first pod the secondary responsibility of checking the volume has + // been mounted with the PV's mount options, if the PV was provisioned with any + for _, option := range pv.Spec.MountOptions { + // Get entry, get mount options at 6th word, replace brackets with commas + command += fmt.Sprintf(" && ( mount | grep 'on /mnt/test' | awk '{print $6}' | sed 's/^(/,/; s/)$/,/' | grep -q ,%s, )", option) + } + runInPodWithVolume(client, claim.Namespace, claim.Name, t.nodeName, command) + By("checking the created volume is readable and retains data") + runInPodWithVolume(client, claim.Namespace, claim.Name, t.nodeName, "grep 'hello world' /mnt/test/data") + } By(fmt.Sprintf("deleting claim %q/%q", claim.Namespace, claim.Name)) framework.ExpectNoError(client.CoreV1().PersistentVolumeClaims(claim.Namespace).Delete(claim.Name, nil)) @@ -250,6 +256,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { // This test checks that dynamic provisioning can provision a volume // that can be used to persist data among pods. tests := []storageClassTest{ + // GCE/GKE { name: "SSD PD on GCE/GKE", cloudProviders: []string{"gce", "gke"}, @@ -258,8 +265,8 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { "type": "pd-ssd", "zone": cloudZone, }, - claimSize: "1.5G", - expectedSize: "2G", + claimSize: "1.5Gi", + expectedSize: "2Gi", pvCheck: func(volume *v1.PersistentVolume) error { return checkGCEPD(volume, "pd-ssd") }, @@ -271,8 +278,8 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { parameters: map[string]string{ "type": "pd-standard", }, - claimSize: "1.5G", - expectedSize: "2G", + claimSize: "1.5Gi", + expectedSize: "2Gi", pvCheck: func(volume *v1.PersistentVolume) error { return checkGCEPD(volume, "pd-standard") }, @@ -377,6 +384,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { expectedSize: "1.5Gi", pvCheck: nil, }, + // Azure { name: "Azure disk volume with empty sku and location", cloudProviders: []string{"azure"}, @@ -410,7 +418,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { testDynamicProvisioning(test, c, claim, class) } - // Run the last test with storage.k8s.io/v1beta1 and beta annotation on pvc + // Run the last test with storage.k8s.io/v1beta1 on pvc if betaTest != nil { By("Testing " + betaTest.name + " with beta volume provisioning") class := newBetaStorageClass(*betaTest, "beta") @@ -420,9 +428,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { defer deleteStorageClass(c, class.Name) claim := newClaim(*betaTest, ns, "beta") - claim.Annotations = map[string]string{ - v1.BetaStorageClassAnnotation: class.Name, - } + claim.Spec.StorageClassName = &(class.Name) testDynamicProvisioning(*betaTest, c, claim, nil) } }) @@ -437,8 +443,8 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { parameters: map[string]string{ "type": "pd-standard", }, - claimSize: "1G", - expectedSize: "1G", + claimSize: "1Gi", + expectedSize: "1Gi", pvCheck: func(volume *v1.PersistentVolume) error { return checkGCEPD(volume, "pd-standard") }, @@ -471,8 +477,8 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { parameters: map[string]string{ "type": "pd-standard", }, - claimSize: "1G", - expectedSize: "1G", + claimSize: "1Gi", + expectedSize: "1Gi", pvCheck: func(volume *v1.PersistentVolume) error { return checkGCEPD(volume, "pd-standard") }, @@ -484,9 +490,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { testDynamicProvisioning(test, c, claim, class) }) - // NOTE: Slow! The test will wait up to 5 minutes (framework.ClaimProvisionTimeout) - // when there is no regression. - It("should not provision a volume in an unmanaged GCE zone. [Slow]", func() { + It("should not provision a volume in an unmanaged GCE zone.", func() { framework.SkipUnlessProviderIs("gce", "gke") var suffix string = "unmananged" @@ -522,7 +526,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { name: "unmanaged_zone", provisioner: "kubernetes.io/gce-pd", parameters: map[string]string{"zone": unmanagedZone}, - claimSize: "1G", + claimSize: "1Gi", } sc := newStorageClass(test, ns, suffix) sc, err = c.StorageV1().StorageClasses().Create(sc) @@ -539,7 +543,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { }() // The claim should timeout phase:Pending - err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, c, ns, pvc.Name, 2*time.Second, framework.ClaimProvisionTimeout) + err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, c, ns, pvc.Name, 2*time.Second, framework.ClaimProvisionShortTimeout) Expect(err).To(HaveOccurred()) framework.Logf(err.Error()) }) @@ -692,14 +696,8 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { expectedSize: "1500Mi", } class := newStorageClass(test, ns, "external") - className := class.Name claim := newClaim(test, ns, "external") - // the external provisioner understands Beta only right now, see - // https://github.com/kubernetes-incubator/external-storage/issues/37 - // claim.Spec.StorageClassName = &className - claim.Annotations = map[string]string{ - v1.BetaStorageClassAnnotation: className, - } + claim.Spec.StorageClassName = &(class.Name) By("creating a claim with a external provisioning annotation") testDynamicProvisioning(test, c, claim, class) @@ -716,20 +714,13 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { claimSize: "2Gi", expectedSize: "2Gi", } - // gce or gke - if getDefaultPluginName() == "kubernetes.io/gce-pd" { - // using GB not GiB as e2e test unit since gce-pd returns GB, - // or expectedSize may be greater than claimSize. - test.claimSize = "2G" - test.expectedSize = "2G" - } claim := newClaim(test, ns, "default") testDynamicProvisioning(test, c, claim, nil) }) // Modifying the default storage class can be disruptive to other tests that depend on it - It("should be disabled by changing the default annotation[Slow] [Serial] [Disruptive]", func() { + It("should be disabled by changing the default annotation [Serial] [Disruptive]", func() { framework.SkipUnlessProviderIs("openstack", "gce", "aws", "gke", "vsphere", "azure") scName := getDefaultStorageClassName(c) test := storageClassTest{ @@ -751,7 +742,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { }() // The claim should timeout phase:Pending - err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, c, ns, claim.Name, 2*time.Second, framework.ClaimProvisionTimeout) + err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, c, ns, claim.Name, 2*time.Second, framework.ClaimProvisionShortTimeout) Expect(err).To(HaveOccurred()) framework.Logf(err.Error()) claim, err = c.CoreV1().PersistentVolumeClaims(ns).Get(claim.Name, metav1.GetOptions{}) @@ -760,7 +751,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { }) // Modifying the default storage class can be disruptive to other tests that depend on it - It("should be disabled by removing the default annotation[Slow] [Serial] [Disruptive]", func() { + It("should be disabled by removing the default annotation [Serial] [Disruptive]", func() { framework.SkipUnlessProviderIs("openstack", "gce", "aws", "gke", "vsphere", "azure") scName := getDefaultStorageClassName(c) test := storageClassTest{ @@ -782,7 +773,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { }() // The claim should timeout phase:Pending - err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, c, ns, claim.Name, 2*time.Second, framework.ClaimProvisionTimeout) + err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, c, ns, claim.Name, 2*time.Second, framework.ClaimProvisionShortTimeout) Expect(err).To(HaveOccurred()) framework.Logf(err.Error()) claim, err = c.CoreV1().PersistentVolumeClaims(ns).Get(claim.Name, metav1.GetOptions{}) @@ -790,6 +781,50 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { Expect(claim.Status.Phase).To(Equal(v1.ClaimPending)) }) }) + + framework.KubeDescribe("GlusterDynamicProvisioner", func() { + It("should create and delete persistent volumes [fast]", func() { + By("creating a Gluster DP server Pod") + pod := startGlusterDpServerPod(c, ns) + serverUrl := "https://" + pod.Status.PodIP + ":8081" + By("creating a StorageClass") + test := storageClassTest{ + name: "Gluster Dynamic provisioner test", + provisioner: "kubernetes.io/glusterfs", + claimSize: "2Gi", + expectedSize: "2Gi", + parameters: map[string]string{"resturl": serverUrl}, + attach: false, + } + suffix := fmt.Sprintf("glusterdptest") + class := newStorageClass(test, ns, suffix) + + By("creating a claim object with a suffix for gluster dynamic provisioner") + claim := newClaim(test, ns, suffix) + + testDynamicProvisioning(test, c, claim, class) + }) + }) + + Describe("Block volume provisioning [Feature:BlockVolume]", func() { + It("should create and delete block persistent volumes", func() { + + // TODO: add openstack once Cinder volume plugin supports block volumes + framework.SkipUnlessProviderIs("gce", "aws", "gke", "vsphere", "azure") + + By("creating a claim with default class") + block := v1.PersistentVolumeBlock + test := storageClassTest{ + name: "default", + claimSize: "2Gi", + expectedSize: "2Gi", + volumeMode: &block, + } + claim := newClaim(test, ns, "default") + claim.Spec.VolumeMode = &block + testDynamicProvisioning(test, c, claim, nil) + }) + }) }) func getDefaultStorageClassName(c clientset.Interface) string { @@ -953,8 +988,7 @@ func newStorageClass(t storageClassTest, ns string, suffix string) *storage.Stor } } -// TODO: remove when storage.k8s.io/v1beta1 and beta storage class annotations -// are removed. +// TODO: remove when storage.k8s.io/v1beta1 is removed. func newBetaStorageClass(t storageClassTest, suffix string) *storagebeta.StorageClass { pluginName := t.provisioner @@ -977,6 +1011,55 @@ func newBetaStorageClass(t storageClassTest, suffix string) *storagebeta.Storage } } +func startGlusterDpServerPod(c clientset.Interface, ns string) *v1.Pod { + podClient := c.CoreV1().Pods(ns) + + provisionerPod := &v1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "glusterdynamic-provisioner-", + }, + + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "glusterdynamic-provisioner", + Image: "docker.io/humblec/glusterdynamic-provisioner:v1.0", + Args: []string{ + "-config=" + "/etc/heketi/heketi.json", + }, + Ports: []v1.ContainerPort{ + {Name: "heketi", ContainerPort: 8081}, + }, + Env: []v1.EnvVar{ + { + Name: "POD_IP", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "status.podIP", + }, + }, + }, + }, + ImagePullPolicy: v1.PullIfNotPresent, + }, + }, + }, + } + provisionerPod, err := podClient.Create(provisionerPod) + framework.ExpectNoError(err, "Failed to create %s pod: %v", provisionerPod.Name, err) + + framework.ExpectNoError(framework.WaitForPodRunningInNamespace(c, provisionerPod)) + + By("locating the provisioner pod") + pod, err := podClient.Get(provisionerPod.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "Cannot locate the provisioner pod %v: %v", provisionerPod.Name, err) + return pod +} + func startExternalProvisioner(c clientset.Interface, ns string) *v1.Pod { podClient := c.CoreV1().Pods(ns) @@ -1063,7 +1146,7 @@ func waitForProvisionedVolumesDeleted(c clientset.Interface, scName string) ([]* return true, err } for _, pv := range allPVs.Items { - if v1helper.GetPersistentVolumeClass(&pv) == scName { + if pv.Spec.StorageClassName == scName { remainingPVs = append(remainingPVs, &pv) } } diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/volumes.go b/vendor/k8s.io/kubernetes/test/e2e/storage/volumes.go index ec76c1ac3..d2a27c86f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/volumes.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/volumes.go @@ -57,7 +57,6 @@ import ( "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/utils" vspheretest "k8s.io/kubernetes/test/e2e/storage/vsphere" - imageutils "k8s.io/kubernetes/test/utils/image" ) func DeleteCinderVolume(name string) error { @@ -129,7 +128,7 @@ var _ = utils.SIGDescribe("Volumes", func() { Describe("GlusterFS", func() { It("should be mountable", func() { //TODO (copejon) GFS is not supported on debian image. - framework.SkipUnlessNodeOSDistroIs("gci", "ubuntu") + framework.SkipUnlessNodeOSDistroIs("gci", "ubuntu", "custom") // create gluster server and endpoints config, _, _ := framework.NewGlusterfsServer(cs, namespace.Name) @@ -200,34 +199,9 @@ var _ = utils.SIGDescribe("Volumes", func() { Describe("Ceph RBD [Feature:Volumes]", func() { It("should be mountable", func() { - config, _, serverIP := framework.NewRBDServer(cs, namespace.Name) + config, _, secret, serverIP := framework.NewRBDServer(cs, namespace.Name) defer framework.VolumeTestCleanup(f, config) - - // create secrets for the server - secret := v1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: config.Prefix + "-secret", - }, - Data: map[string][]byte{ - // from test/images/volumes-tester/rbd/keyring - "key": []byte("AQDRrKNVbEevChAAEmRC+pW/KBVHxa0w/POILA=="), - }, - Type: "kubernetes.io/rbd", - } - - secClient := cs.CoreV1().Secrets(config.Namespace) - - defer func() { - secClient.Delete(config.Prefix+"-secret", nil) - }() - - if _, err := secClient.Create(&secret); err != nil { - framework.Failf("Failed to create secrets for Ceph RBD: %v", err) - } + defer cs.CoreV1().Secrets(config.Namespace).Delete(secret.Name, nil) tests := []framework.VolumeTest{ { @@ -238,7 +212,7 @@ var _ = utils.SIGDescribe("Volumes", func() { RBDImage: "foo", RadosUser: "admin", SecretRef: &v1.LocalObjectReference{ - Name: config.Prefix + "-secret", + Name: secret.Name, }, FSType: "ext2", }, @@ -258,45 +232,9 @@ var _ = utils.SIGDescribe("Volumes", func() { //////////////////////////////////////////////////////////////////////// Describe("CephFS [Feature:Volumes]", func() { It("should be mountable", func() { - config := framework.VolumeTestConfig{ - Namespace: namespace.Name, - Prefix: "cephfs", - ServerImage: imageutils.GetE2EImage(imageutils.VolumeCephServer), - ServerPorts: []int{6789}, - } - + config, _, secret, serverIP := framework.NewRBDServer(cs, namespace.Name) defer framework.VolumeTestCleanup(f, config) - _, serverIP := framework.CreateStorageServer(cs, config) - By("sleeping a bit to give ceph server time to initialize") - time.Sleep(framework.VolumeServerPodStartupSleep) - - // create ceph secret - secret := &v1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: config.Prefix + "-secret", - }, - // Must use the ceph keyring at contrib/for-tests/volumes-ceph/ceph/init.sh - // and encode in base64 - Data: map[string][]byte{ - "key": []byte("AQAMgXhVwBCeDhAA9nlPaFyfUSatGD4drFWDvQ=="), - }, - Type: "kubernetes.io/cephfs", - } - - defer func() { - if err := cs.CoreV1().Secrets(namespace.Name).Delete(secret.Name, nil); err != nil { - framework.Failf("unable to delete secret %v: %v", secret.Name, err) - } - }() - - var err error - if secret, err = cs.CoreV1().Secrets(namespace.Name).Create(secret); err != nil { - framework.Failf("unable to create test secret %s: %v", secret.Name, err) - } + defer cs.CoreV1().Secrets(config.Namespace).Delete(secret.Name, nil) tests := []framework.VolumeTest{ { @@ -304,7 +242,7 @@ var _ = utils.SIGDescribe("Volumes", func() { CephFS: &v1.CephFSVolumeSource{ Monitors: []string{serverIP + ":6789"}, User: "kube", - SecretRef: &v1.LocalObjectReference{Name: config.Prefix + "-secret"}, + SecretRef: &v1.LocalObjectReference{Name: secret.Name}, ReadOnly: true, }, }, @@ -419,7 +357,7 @@ var _ = utils.SIGDescribe("Volumes", func() { It("should be mountable with xfs", func() { // xfs is not supported on gci // and not installed by default on debian - framework.SkipUnlessNodeOSDistroIs("ubuntu") + framework.SkipUnlessNodeOSDistroIs("ubuntu", "custom") testGCEPD(f, config, cs, "xfs") }) }) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/BUILD b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/BUILD index c06139f25..a910c256e 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/BUILD @@ -33,6 +33,7 @@ go_library( "vsphere_volume_ops_storm.go", "vsphere_volume_perf.go", "vsphere_volume_placement.go", + "vsphere_volume_vpxd_restart.go", "vsphere_volume_vsan_policy.go", ], importpath = "k8s.io/kubernetes/test/e2e/storage/vsphere", @@ -51,10 +52,9 @@ go_library( "//vendor/github.com/vmware/govmomi/vim25/mo:go_default_library", "//vendor/github.com/vmware/govmomi/vim25/soap:go_default_library", "//vendor/github.com/vmware/govmomi/vim25/types:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/gopkg.in/gcfg.v1:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/connection.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/connection.go index d123a7f34..60e8e40ac 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/connection.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/connection.go @@ -17,6 +17,7 @@ limitations under the License. package vsphere import ( + "context" "fmt" neturl "net/url" "sync" @@ -25,7 +26,6 @@ import ( "github.com/vmware/govmomi" "github.com/vmware/govmomi/session" "github.com/vmware/govmomi/vim25" - "golang.org/x/net/context" ) const ( diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/nodemapper.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/nodemapper.go index 7bdab0cf1..881221285 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/nodemapper.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/nodemapper.go @@ -17,14 +17,15 @@ limitations under the License. package vsphere import ( + "context" "errors" + "strings" + "sync" + "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" "k8s.io/api/core/v1" "k8s.io/kubernetes/test/e2e/framework" - "strings" - "sync" ) type NodeMapper struct { diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/persistent_volumes-vsphere.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/persistent_volumes-vsphere.go index fe4a76d4f..7b6d5888c 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/persistent_volumes-vsphere.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/persistent_volumes-vsphere.go @@ -87,11 +87,10 @@ var _ = utils.SIGDescribe("PersistentVolumes:vsphere", func() { }, Prebind: nil, } + emptyStorageClass := "" pvcConfig = framework.PersistentVolumeClaimConfig{ - Annotations: map[string]string{ - v1.BetaStorageClassAnnotation: "", - }, - Selector: selector, + Selector: selector, + StorageClassName: &emptyStorageClass, } } By("Creating the PV and PVC") diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere.go index b9cb5925b..f19a2d5f7 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere.go @@ -17,18 +17,19 @@ limitations under the License. package vsphere import ( + "context" "fmt" + "path/filepath" + "strconv" + "strings" + "time" + "github.com/vmware/govmomi" "github.com/vmware/govmomi/find" "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" "k8s.io/kubernetes/test/e2e/framework" - "path/filepath" - "strconv" - "strings" - "time" ) const ( @@ -57,7 +58,7 @@ type VolumeOptions struct { // GetDatacenter returns the DataCenter Object for the given datacenterPath func (vs *VSphere) GetDatacenter(ctx context.Context, datacenterPath string) (*object.Datacenter, error) { Connect(ctx, vs) - finder := find.NewFinder(vs.Client.Client, true) + finder := find.NewFinder(vs.Client.Client, false) return finder.Datacenter(ctx, datacenterPath) } @@ -70,7 +71,7 @@ func (vs *VSphere) GetDatacenterFromObjectReference(ctx context.Context, dc obje // GetAllDatacenter returns all the DataCenter Objects func (vs *VSphere) GetAllDatacenter(ctx context.Context) ([]*object.Datacenter, error) { Connect(ctx, vs) - finder := find.NewFinder(vs.Client.Client, true) + finder := find.NewFinder(vs.Client.Client, false) return finder.DatacenterList(ctx, "*") } @@ -88,7 +89,7 @@ func (vs *VSphere) GetVMByUUID(ctx context.Context, vmUUID string, dc object.Ref func (vs *VSphere) GetFolderByPath(ctx context.Context, dc object.Reference, folderPath string) (vmFolderMor types.ManagedObjectReference, err error) { Connect(ctx, vs) datacenter := object.NewDatacenter(vs.Client.Client, dc.Reference()) - finder := find.NewFinder(datacenter.Client(), true) + finder := find.NewFinder(datacenter.Client(), false) finder.SetDatacenter(datacenter) vmFolder, err := finder.Folder(ctx, folderPath) if err != nil { @@ -113,7 +114,7 @@ func (vs *VSphere) CreateVolume(volumeOptions *VolumeOptions, dataCenterRef type return "", fmt.Errorf("datacenter is nil") } vs.initVolumeOptions(volumeOptions) - finder := find.NewFinder(datacenter.Client(), true) + finder := find.NewFinder(datacenter.Client(), false) finder.SetDatacenter(datacenter) ds, err := finder.Datastore(ctx, volumeOptions.Datastore) if err != nil { diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_scale.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_scale.go index 573236ab3..f09249991 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_scale.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_scale.go @@ -192,7 +192,7 @@ func VolumeCreateAndAttach(client clientset.Interface, namespace string, sc []*s pvclaims := make([]*v1.PersistentVolumeClaim, volumesPerPod) for i := 0; i < volumesPerPod; i++ { By("Creating PVC using the Storage Class") - pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClassAnnotation(namespace, "2Gi", sc[index%len(sc)])) + pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "2Gi", sc[index%len(sc)])) Expect(err).NotTo(HaveOccurred()) pvclaims[i] = pvclaim } diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_stress.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_stress.go index 59441a771..260fe8403 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_stress.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_stress.go @@ -128,7 +128,7 @@ func PerformVolumeLifeCycleInParallel(f *framework.Framework, client clientset.I for iterationCount := 0; iterationCount < iterations; iterationCount++ { logPrefix := fmt.Sprintf("Instance: [%v], Iteration: [%v] :", instanceId, iterationCount+1) By(fmt.Sprintf("%v Creating PVC using the Storage Class: %v", logPrefix, sc.Name)) - pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClassAnnotation(namespace, "1Gi", sc)) + pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "1Gi", sc)) Expect(err).NotTo(HaveOccurred()) defer framework.DeletePersistentVolumeClaim(client, pvclaim.Name, namespace) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_utils.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_utils.go index 6f0118fcc..7f5cb5e34 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_utils.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_utils.go @@ -17,19 +17,23 @@ limitations under the License. package vsphere import ( + "context" "fmt" "math/rand" "path/filepath" + "regexp" + "strings" "time" "github.com/golang/glog" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vmware/govmomi/find" "github.com/vmware/govmomi/object" - "github.com/vmware/govmomi/vim25/mo" - vim25types "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" + vimtypes "github.com/vmware/govmomi/vim25/types" + "k8s.io/api/core/v1" storage "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -40,11 +44,6 @@ import ( "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/utils" - - "github.com/vmware/govmomi/find" - vimtypes "github.com/vmware/govmomi/vim25/types" - "regexp" - "strings" ) const ( @@ -254,15 +253,11 @@ func getVSphereStorageClassSpec(name string, scParameters map[string]string) *st return sc } -func getVSphereClaimSpecWithStorageClassAnnotation(ns string, diskSize string, storageclass *storage.StorageClass) *v1.PersistentVolumeClaim { - scAnnotation := make(map[string]string) - scAnnotation[v1.BetaStorageClassAnnotation] = storageclass.Name - +func getVSphereClaimSpecWithStorageClass(ns string, diskSize string, storageclass *storage.StorageClass) *v1.PersistentVolumeClaim { claim := &v1.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "pvc-", Namespace: ns, - Annotations: scAnnotation, }, Spec: v1.PersistentVolumeClaimSpec{ AccessModes: []v1.PersistentVolumeAccessMode{ @@ -273,6 +268,7 @@ func getVSphereClaimSpecWithStorageClassAnnotation(ns string, diskSize string, s v1.ResourceName(v1.ResourceStorage): resource.MustParse(diskSize), }, }, + StorageClassName: &(storageclass.Name), }, } return claim @@ -373,7 +369,7 @@ func getVSpherePodSpecWithVolumePaths(volumePaths []string, keyValuelabel map[st return pod } -func verifyFilesExistOnVSphereVolume(namespace string, podName string, filePaths []string) { +func verifyFilesExistOnVSphereVolume(namespace string, podName string, filePaths ...string) { for _, filePath := range filePaths { _, err := framework.RunKubectl("exec", fmt.Sprintf("--namespace=%s", namespace), podName, "--", "/bin/ls", filePath) Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("failed to verify file: %q on the pod: %q", filePath, podName)) @@ -657,7 +653,7 @@ func registerNodeVM(nodeName, workingDir, vmxFilePath string, rpool *object.Reso framework.Logf("Registering node VM %s with vmx file path %s", nodeName, vmxFilePath) nodeInfo := TestContext.NodeMapper.GetNodeInfo(nodeName) - finder := find.NewFinder(nodeInfo.VSphere.Client.Client, true) + finder := find.NewFinder(nodeInfo.VSphere.Client.Client, false) vmFolder, err := finder.FolderOrDefault(ctx, workingDir) Expect(err).NotTo(HaveOccurred()) @@ -755,3 +751,72 @@ func GetReadySchedulableRandomNodeInfo() *NodeInfo { Expect(nodesInfo).NotTo(BeEmpty()) return nodesInfo[rand.Int()%len(nodesInfo)] } + +// invokeVCenterServiceControl invokes the given command for the given service +// via service-control on the given vCenter host over SSH. +func invokeVCenterServiceControl(command, service, host string) error { + sshCmd := fmt.Sprintf("service-control --%s %s", command, service) + framework.Logf("Invoking command %v on vCenter host %v", sshCmd, host) + result, err := framework.SSH(sshCmd, host, framework.TestContext.Provider) + if err != nil || result.Code != 0 { + framework.LogSSHResult(result) + return fmt.Errorf("couldn't execute command: %s on vCenter host: %v", sshCmd, err) + } + return nil +} + +// expectVolumeToBeAttached checks if the given Volume is attached to the given +// Node, else fails. +func expectVolumeToBeAttached(nodeName, volumePath string) { + isAttached, err := diskIsAttached(volumePath, nodeName) + Expect(err).NotTo(HaveOccurred()) + Expect(isAttached).To(BeTrue(), fmt.Sprintf("disk: %s is not attached with the node", volumePath)) +} + +// expectVolumesToBeAttached checks if the given Volumes are attached to the +// corresponding set of Nodes, else fails. +func expectVolumesToBeAttached(pods []*v1.Pod, volumePaths []string) { + for i, pod := range pods { + nodeName := pod.Spec.NodeName + volumePath := volumePaths[i] + By(fmt.Sprintf("Verifying that volume %v is attached to node %v", volumePath, nodeName)) + expectVolumeToBeAttached(nodeName, volumePath) + } +} + +// expectFilesToBeAccessible checks if the given files are accessible on the +// corresponding set of Nodes, else fails. +func expectFilesToBeAccessible(namespace string, pods []*v1.Pod, filePaths []string) { + for i, pod := range pods { + podName := pod.Name + filePath := filePaths[i] + By(fmt.Sprintf("Verifying that file %v is accessible on pod %v", filePath, podName)) + verifyFilesExistOnVSphereVolume(namespace, podName, filePath) + } +} + +// writeContentToPodFile writes the given content to the specified file. +func writeContentToPodFile(namespace, podName, filePath, content string) error { + _, err := framework.RunKubectl("exec", fmt.Sprintf("--namespace=%s", namespace), podName, + "--", "/bin/sh", "-c", fmt.Sprintf("echo '%s' > %s", content, filePath)) + return err +} + +// expectFileContentToMatch checks if a given file contains the specified +// content, else fails. +func expectFileContentToMatch(namespace, podName, filePath, content string) { + _, err := framework.RunKubectl("exec", fmt.Sprintf("--namespace=%s", namespace), podName, + "--", "/bin/sh", "-c", fmt.Sprintf("grep '%s' %s", content, filePath)) + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("failed to match content of file: %q on the pod: %q", filePath, podName)) +} + +// expectFileContentsToMatch checks if the given contents match the ones present +// in corresponding files on respective Pods, else fails. +func expectFileContentsToMatch(namespace string, pods []*v1.Pod, filePaths []string, contents []string) { + for i, pod := range pods { + podName := pod.Name + filePath := filePaths[i] + By(fmt.Sprintf("Matching file content for %v on pod %v", filePath, podName)) + expectFileContentToMatch(namespace, podName, filePath, contents[i]) + } +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_cluster_ds.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_cluster_ds.go index 1e0092cec..f6c4aa50b 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_cluster_ds.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_cluster_ds.go @@ -17,7 +17,6 @@ limitations under the License. package vsphere import ( - "fmt" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -98,9 +97,7 @@ var _ = utils.SIGDescribe("Volume Provisioning On Clustered Datastore [Feature:v nodeName := pod.Spec.NodeName By("Verifying volume is attached") - isAttached, err := diskIsAttached(volumePath, nodeName) - Expect(err).NotTo(HaveOccurred()) - Expect(isAttached).To(BeTrue(), fmt.Sprintf("disk: %s is not attached with the node: %v", volumePath, nodeName)) + expectVolumeToBeAttached(nodeName, volumePath) By("Deleting pod") err = framework.DeletePodWithWait(f, client, pod) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_datastore.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_datastore.go index 8ac75de29..fcb964b7c 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_datastore.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_datastore.go @@ -84,7 +84,7 @@ func invokeInvalidDatastoreTestNeg(client clientset.Interface, namespace string, defer client.StorageV1().StorageClasses().Delete(storageclass.Name, nil) By("Creating PVC using the Storage Class") - pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClassAnnotation(namespace, "2Gi", storageclass)) + pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "2Gi", storageclass)) Expect(err).NotTo(HaveOccurred()) defer framework.DeletePersistentVolumeClaim(client, pvclaim.Name, namespace) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_diskformat.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_diskformat.go index 051089cfb..ca90fdf09 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_diskformat.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_diskformat.go @@ -17,13 +17,14 @@ limitations under the License. package vsphere import ( + "context" "path/filepath" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" @@ -112,7 +113,7 @@ func invokeTest(f *framework.Framework, client clientset.Interface, namespace st defer client.StorageV1().StorageClasses().Delete(storageclass.Name, nil) By("Creating PVC using the Storage Class") - pvclaimSpec := getVSphereClaimSpecWithStorageClassAnnotation(namespace, "2Gi", storageclass) + pvclaimSpec := getVSphereClaimSpecWithStorageClass(namespace, "2Gi", storageclass) pvclaim, err := client.CoreV1().PersistentVolumeClaims(namespace).Create(pvclaimSpec) Expect(err).NotTo(HaveOccurred()) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_disksize.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_disksize.go index 8144f38a1..5e58a81bf 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_disksize.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_disksize.go @@ -82,7 +82,7 @@ func invokeInvalidDiskSizeTestNeg(client clientset.Interface, namespace string, defer client.StorageV1().StorageClasses().Delete(storageclass.Name, nil) By("Creating PVC using the Storage Class") - pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClassAnnotation(namespace, diskSize, storageclass)) + pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClass(namespace, diskSize, storageclass)) Expect(err).NotTo(HaveOccurred()) defer framework.DeletePersistentVolumeClaim(client, pvclaim.Name, namespace) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_fstype.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_fstype.go index b631c3b0b..74ae2a34f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_fstype.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_fstype.go @@ -151,7 +151,7 @@ func createVolume(client clientset.Interface, namespace string, scParameters map defer client.StorageV1().StorageClasses().Delete(storageclass.Name, nil) By("Creating PVC using the Storage Class") - pvclaim, err := client.CoreV1().PersistentVolumeClaims(namespace).Create(getVSphereClaimSpecWithStorageClassAnnotation(namespace, "2Gi", storageclass)) + pvclaim, err := client.CoreV1().PersistentVolumeClaims(namespace).Create(getVSphereClaimSpecWithStorageClass(namespace, "2Gi", storageclass)) Expect(err).NotTo(HaveOccurred()) var pvclaims []*v1.PersistentVolumeClaim diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_master_restart.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_master_restart.go index b8358267b..437930cc8 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_master_restart.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_master_restart.go @@ -103,10 +103,7 @@ var _ = utils.SIGDescribe("Volume Attach Verify [Feature:vsphere][Serial][Disrup nodeName := pod.Spec.NodeName By(fmt.Sprintf("Verify volume %s is attached to the pod %s", volumePath, nodeName)) - isAttached, err := diskIsAttached(volumePath, nodeName) - Expect(err).NotTo(HaveOccurred()) - Expect(isAttached).To(BeTrue(), fmt.Sprintf("disk: %s is not attached with the node", volumePath)) - + expectVolumeToBeAttached(nodeName, volumePath) } By("Restarting kubelet on master node") @@ -121,10 +118,9 @@ var _ = utils.SIGDescribe("Volume Attach Verify [Feature:vsphere][Serial][Disrup for i, pod := range pods { volumePath := volumePaths[i] nodeName := pod.Spec.NodeName + By(fmt.Sprintf("After master restart, verify volume %v is attached to the pod %v", volumePath, nodeName)) - isAttached, err := diskIsAttached(volumePaths[i], nodeName) - Expect(err).NotTo(HaveOccurred()) - Expect(isAttached).To(BeTrue(), fmt.Sprintf("disk: %s is not attached with the node", volumePath)) + expectVolumeToBeAttached(nodeName, volumePath) By(fmt.Sprintf("Deleting pod on node %s", nodeName)) err = framework.DeletePodWithWait(f, client, pod) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_node_delete.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_node_delete.go index fe166e8d9..3daaadb89 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_node_delete.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_node_delete.go @@ -17,12 +17,12 @@ limitations under the License. package vsphere import ( + "context" "os" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/vmware/govmomi/object" - "golang.org/x/net/context" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_node_poweroff.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_node_poweroff.go index 6cc861039..4edd5e370 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_node_poweroff.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_node_poweroff.go @@ -17,17 +17,17 @@ limitations under the License. package vsphere import ( + "context" "fmt" "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "golang.org/x/net/context" - "github.com/vmware/govmomi/object" vimtypes "github.com/vmware/govmomi/vim25/types" + + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" @@ -81,7 +81,7 @@ var _ = utils.SIGDescribe("Node Poweroff [Feature:vsphere] [Slow] [Disruptive]", defer client.StorageV1().StorageClasses().Delete(storageclass.Name, nil) By("Creating PVC using the Storage Class") - pvclaimSpec := getVSphereClaimSpecWithStorageClassAnnotation(namespace, "1Gi", storageclass) + pvclaimSpec := getVSphereClaimSpecWithStorageClass(namespace, "1Gi", storageclass) pvclaim, err := framework.CreatePVC(client, namespace, pvclaimSpec) Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Failed to create PVC with err: %v", err)) defer framework.DeletePersistentVolumeClaim(client, pvclaim.Name, namespace) @@ -111,7 +111,8 @@ var _ = utils.SIGDescribe("Node Poweroff [Feature:vsphere] [Slow] [Disruptive]", nodeInfo := TestContext.NodeMapper.GetNodeInfo(node1) vm := object.NewVirtualMachine(nodeInfo.VSphere.Client.Client, nodeInfo.VirtualMachineRef) - ctx, _ := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() _, err = vm.PowerOff(ctx) Expect(err).NotTo(HaveOccurred()) defer vm.PowerOn(ctx) @@ -139,7 +140,7 @@ var _ = utils.SIGDescribe("Node Poweroff [Feature:vsphere] [Slow] [Disruptive]", }) // Wait until the pod failed over to a different node, or time out after 3 minutes -func waitForPodToFailover(client clientset.Interface, deployment *extensions.Deployment, oldNode string) (string, error) { +func waitForPodToFailover(client clientset.Interface, deployment *apps.Deployment, oldNode string) (string, error) { var ( err error newNode string @@ -174,7 +175,7 @@ func waitForPodToFailover(client clientset.Interface, deployment *extensions.Dep } // getNodeForDeployment returns node name for the Deployment -func getNodeForDeployment(client clientset.Interface, deployment *extensions.Deployment) (string, error) { +func getNodeForDeployment(client clientset.Interface, deployment *apps.Deployment) (string, error) { podList, err := framework.GetPodsForDeployment(client, deployment) if err != nil { return "", err diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_ops_storm.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_ops_storm.go index e6d66463d..b4d9d8c4a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_ops_storm.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_ops_storm.go @@ -93,7 +93,7 @@ var _ = utils.SIGDescribe("Volume Operations Storm [Feature:vsphere]", func() { By("Creating PVCs using the Storage Class") count := 0 for count < volume_ops_scale { - pvclaims[count], err = framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClassAnnotation(namespace, "2Gi", storageclass)) + pvclaims[count], err = framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "2Gi", storageclass)) Expect(err).NotTo(HaveOccurred()) count++ } diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_perf.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_perf.go index 9c54a7382..b4fe50ba9 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_perf.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_perf.go @@ -170,7 +170,7 @@ func invokeVolumeLifeCyclePerformance(f *framework.Framework, client clientset.I var pvclaims []*v1.PersistentVolumeClaim for j := 0; j < volumesPerPod; j++ { currsc := sc[((i*numPods)+j)%len(sc)] - pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClassAnnotation(namespace, "2Gi", currsc)) + pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "2Gi", currsc)) Expect(err).NotTo(HaveOccurred()) pvclaims = append(pvclaims, pvclaim) } diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_placement.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_placement.go index e276591d3..654ee2271 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_placement.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_placement.go @@ -320,9 +320,9 @@ var _ = utils.SIGDescribe("Volume Placement", func() { // Verify newly and previously created files present on the volume mounted on the pod By("Verify newly Created file and previously created files present on volume mounted on pod-A") - verifyFilesExistOnVSphereVolume(ns, podA.Name, podAFiles) + verifyFilesExistOnVSphereVolume(ns, podA.Name, podAFiles...) By("Verify newly Created file and previously created files present on volume mounted on pod-B") - verifyFilesExistOnVSphereVolume(ns, podB.Name, podBFiles) + verifyFilesExistOnVSphereVolume(ns, podB.Name, podBFiles...) By("Deleting pod-A") framework.ExpectNoError(framework.DeletePodWithWait(f, c, podA), "Failed to delete pod ", podA.Name) @@ -378,7 +378,7 @@ func createAndVerifyFilesOnVolume(namespace string, podname string, newEmptyfile // Verify newly and previously created files present on the volume mounted on the pod By(fmt.Sprintf("Verify newly Created file and previously created files present on volume mounted on: %v", podname)) - verifyFilesExistOnVSphereVolume(namespace, podname, filesToCheck) + verifyFilesExistOnVSphereVolume(namespace, podname, filesToCheck...) } func deletePodAndWaitForVolumeToDetach(f *framework.Framework, c clientset.Interface, pod *v1.Pod, nodeName string, volumePaths []string) { diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_vpxd_restart.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_vpxd_restart.go new file mode 100644 index 000000000..e30704ab3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_vpxd_restart.go @@ -0,0 +1,176 @@ +/* +Copyright 2018 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 vsphere + +import ( + "fmt" + "strconv" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/uuid" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/storage/utils" +) + +/* + Test to verify that a volume remains attached through vpxd restart. + + For the number of schedulable nodes: + 1. Create a Volume with default options. + 2. Create a Pod with the created Volume. + 3. Verify that the Volume is attached. + 4. Create a file with random contents under the Volume's mount point on the Pod. + 5. Stop the vpxd service on the vCenter host. + 6. Verify that the file is accessible on the Pod and that it's contents match. + 7. Start the vpxd service on the vCenter host. + 8. Verify that the Volume remains attached, the file is accessible on the Pod, and that it's contents match. + 9. Delete the Pod and wait for the Volume to be detached. + 10. Delete the Volume. +*/ +var _ = utils.SIGDescribe("Verify Volume Attach Through vpxd Restart [Feature:vsphere][Serial][Disruptive]", func() { + f := framework.NewDefaultFramework("restart-vpxd") + + type node struct { + name string + kvLabels map[string]string + nodeInfo *NodeInfo + } + + const ( + labelKey = "vsphere_e2e_label_vpxd_restart" + vpxdServiceName = "vmware-vpxd" + ) + + var ( + client clientset.Interface + namespace string + vcNodesMap map[string][]node + ) + + BeforeEach(func() { + // Requires SSH access to vCenter. + framework.SkipUnlessProviderIs("vsphere") + + Bootstrap(f) + client = f.ClientSet + namespace = f.Namespace.Name + framework.ExpectNoError(framework.WaitForAllNodesSchedulable(client, framework.TestContext.NodeSchedulableTimeout)) + + nodes := framework.GetReadySchedulableNodesOrDie(client) + numNodes := len(nodes.Items) + Expect(numNodes).NotTo(BeZero(), "No nodes are available for testing volume access through vpxd restart") + + vcNodesMap = make(map[string][]node) + for i := 0; i < numNodes; i++ { + nodeInfo := TestContext.NodeMapper.GetNodeInfo(nodes.Items[i].Name) + nodeName := nodes.Items[i].Name + nodeLabel := "vsphere_e2e_" + string(uuid.NewUUID()) + framework.AddOrUpdateLabelOnNode(client, nodeName, labelKey, nodeLabel) + + vcHost := nodeInfo.VSphere.Config.Hostname + vcNodesMap[vcHost] = append(vcNodesMap[vcHost], node{ + name: nodeName, + kvLabels: map[string]string{labelKey: nodeLabel}, + nodeInfo: nodeInfo, + }) + } + }) + + It("verify volume remains attached through vpxd restart", func() { + for vcHost, nodes := range vcNodesMap { + var ( + volumePaths []string + filePaths []string + fileContents []string + pods []*v1.Pod + ) + + framework.Logf("Testing for nodes on vCenter host: %s", vcHost) + + for i, node := range nodes { + By(fmt.Sprintf("Creating test vsphere volume %d", i)) + volumePath, err := node.nodeInfo.VSphere.CreateVolume(&VolumeOptions{}, node.nodeInfo.DataCenterRef) + Expect(err).NotTo(HaveOccurred()) + volumePaths = append(volumePaths, volumePath) + + By(fmt.Sprintf("Creating pod %d on node %v", i, node.name)) + podspec := getVSpherePodSpecWithVolumePaths([]string{volumePath}, node.kvLabels, nil) + pod, err := client.CoreV1().Pods(namespace).Create(podspec) + Expect(err).NotTo(HaveOccurred()) + + By(fmt.Sprintf("Waiting for pod %d to be ready", i)) + Expect(framework.WaitForPodNameRunningInNamespace(client, pod.Name, namespace)).To(Succeed()) + + pod, err = client.CoreV1().Pods(namespace).Get(pod.Name, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + pods = append(pods, pod) + + nodeName := pod.Spec.NodeName + By(fmt.Sprintf("Verifying that volume %v is attached to node %v", volumePath, nodeName)) + expectVolumeToBeAttached(nodeName, volumePath) + + By(fmt.Sprintf("Creating a file with random content on the volume mounted on pod %d", i)) + filePath := fmt.Sprintf("/mnt/volume1/%v_vpxd_restart_test_%v.txt", namespace, strconv.FormatInt(time.Now().UnixNano(), 10)) + randomContent := fmt.Sprintf("Random Content -- %v", strconv.FormatInt(time.Now().UnixNano(), 10)) + err = writeContentToPodFile(namespace, pod.Name, filePath, randomContent) + Expect(err).NotTo(HaveOccurred()) + filePaths = append(filePaths, filePath) + fileContents = append(fileContents, randomContent) + } + + By("Stopping vpxd on the vCenter host") + vcAddress := vcHost + ":22" + err := invokeVCenterServiceControl("stop", vpxdServiceName, vcAddress) + Expect(err).NotTo(HaveOccurred(), "Unable to stop vpxd on the vCenter host") + + expectFilesToBeAccessible(namespace, pods, filePaths) + expectFileContentsToMatch(namespace, pods, filePaths, fileContents) + + By("Starting vpxd on the vCenter host") + err = invokeVCenterServiceControl("start", vpxdServiceName, vcAddress) + Expect(err).NotTo(HaveOccurred(), "Unable to start vpxd on the vCenter host") + + expectVolumesToBeAttached(pods, volumePaths) + expectFilesToBeAccessible(namespace, pods, filePaths) + expectFileContentsToMatch(namespace, pods, filePaths, fileContents) + + for i, node := range nodes { + pod := pods[i] + nodeName := pod.Spec.NodeName + volumePath := volumePaths[i] + + By(fmt.Sprintf("Deleting pod on node %s", nodeName)) + err = framework.DeletePodWithWait(f, client, pod) + Expect(err).NotTo(HaveOccurred()) + + By(fmt.Sprintf("Waiting for volume %s to be detached from node %s", volumePath, nodeName)) + err = waitForVSphereDiskToDetach(volumePath, nodeName) + Expect(err).NotTo(HaveOccurred()) + + By(fmt.Sprintf("Deleting volume %s", volumePath)) + err = node.nodeInfo.VSphere.DeleteVolume(volumePath, node.nodeInfo.DataCenterRef) + Expect(err).NotTo(HaveOccurred()) + } + } + }) +}) diff --git a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_vsan_policy.go b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_vsan_policy.go index 74171fc39..1f74978fc 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_vsan_policy.go +++ b/vendor/k8s.io/kubernetes/test/e2e/storage/vsphere/vsphere_volume_vsan_policy.go @@ -278,7 +278,7 @@ func invokeValidPolicyTest(f *framework.Framework, client clientset.Interface, n defer client.StorageV1().StorageClasses().Delete(storageclass.Name, nil) By("Creating PVC using the Storage Class") - pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClassAnnotation(namespace, "2Gi", storageclass)) + pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "2Gi", storageclass)) Expect(err).NotTo(HaveOccurred()) defer framework.DeletePersistentVolumeClaim(client, pvclaim.Name, namespace) @@ -310,7 +310,7 @@ func invokeInvalidPolicyTestNeg(client clientset.Interface, namespace string, sc defer client.StorageV1().StorageClasses().Delete(storageclass.Name, nil) By("Creating PVC using the Storage Class") - pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClassAnnotation(namespace, "2Gi", storageclass)) + pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "2Gi", storageclass)) Expect(err).NotTo(HaveOccurred()) defer framework.DeletePersistentVolumeClaim(client, pvclaim.Name, namespace) @@ -329,7 +329,7 @@ func invokeStaleDummyVMTestWithStoragePolicy(client clientset.Interface, masterN defer client.StorageV1().StorageClasses().Delete(storageclass.Name, nil) By("Creating PVC using the Storage Class") - pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClassAnnotation(namespace, "2Gi", storageclass)) + pvclaim, err := framework.CreatePVC(client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "2Gi", storageclass)) Expect(err).NotTo(HaveOccurred()) var pvclaims []*v1.PersistentVolumeClaim diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/legacy/frontend-controller.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/guestbook/legacy/frontend-controller.yaml similarity index 100% rename from vendor/k8s.io/kubernetes/examples/guestbook/legacy/frontend-controller.yaml rename to vendor/k8s.io/kubernetes/test/e2e/testing-manifests/guestbook/legacy/frontend-controller.yaml diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/legacy/redis-master-controller.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml similarity index 100% rename from vendor/k8s.io/kubernetes/examples/guestbook/legacy/redis-master-controller.yaml rename to vendor/k8s.io/kubernetes/test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml diff --git a/vendor/k8s.io/kubernetes/examples/guestbook/legacy/redis-slave-controller.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/guestbook/legacy/redis-slave-controller.yaml similarity index 100% rename from vendor/k8s.io/kubernetes/examples/guestbook/legacy/redis-slave-controller.yaml rename to vendor/k8s.io/kubernetes/test/e2e/testing-manifests/guestbook/legacy/redis-slave-controller.yaml diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http/ing.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http/ing.yaml index 0d4828d17..d14268f0c 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http/ing.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http/ing.yaml @@ -3,6 +3,10 @@ kind: Ingress metadata: name: echomap spec: + # kubemci requires a default backend. + backend: + serviceName: echoheadersx + servicePort: 80 rules: - host: foo.bar.com http: @@ -22,4 +26,3 @@ spec: backend: serviceName: echoheadersx servicePort: 80 - diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http/rc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http/rc.yaml index a4bcd5e39..e5522b696 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http/rc.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http/rc.yaml @@ -11,7 +11,7 @@ spec: spec: containers: - name: echoheaders - image: k8s.gcr.io/echoserver:1.6 + image: k8s.gcr.io/echoserver:1.10 ports: - containerPort: 8080 readinessProbe: diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http2/ing.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http2/ing.yaml new file mode 100644 index 000000000..ca5f56024 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http2/ing.yaml @@ -0,0 +1,9 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: echomap +spec: + # kubemci requires a default backend. + backend: + serviceName: echoheaders + servicePort: 443 diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http2/rc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http2/rc.yaml new file mode 100644 index 000000000..a239b8241 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http2/rc.yaml @@ -0,0 +1,16 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: echoheaders +spec: + replicas: 1 + template: + metadata: + labels: + app: echoheaders + spec: + containers: + - name: echoheaders + image: k8s.gcr.io/echoserver:1.10 + ports: + - containerPort: 8443 diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http2/svc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http2/svc.yaml new file mode 100644 index 000000000..7c38e505a --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/http2/svc.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + service.alpha.kubernetes.io/app-protocols: '{"http2":"HTTP2"}' + name: echoheaders + labels: + app: echoheaders +spec: + type: NodePort + ports: + - port: 443 + targetPort: 8443 + protocol: TCP + name: http2 + selector: + app: echoheaders diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/multiple-certs/ing.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/multiple-certs/ing.yaml new file mode 100644 index 000000000..8cda83c9e --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/multiple-certs/ing.yaml @@ -0,0 +1,34 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: multiple-certs +spec: + rules: + - host: test1.ingress.com + http: + paths: + - path: /test + backend: + serviceName: echoheaders-https + servicePort: 80 + - host: test2.ingress.com + http: + paths: + - path: /test + backend: + serviceName: echoheaders-https + servicePort: 80 + - host: test3.ingress.com + http: + paths: + - path: /test + backend: + serviceName: echoheaders-https + servicePort: 80 + - host: test4.ingress.com + http: + paths: + - path: /test + backend: + serviceName: echoheaders-https + servicePort: 80 diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/multiple-certs/rc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/multiple-certs/rc.yaml new file mode 100644 index 000000000..79e2bfb02 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/multiple-certs/rc.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: ReplicationController +metadata: + name: echoheaders-https +spec: + replicas: 2 + template: + metadata: + labels: + app: echoheaders-https + spec: + containers: + - name: echoheaders-https + image: gcr.io/google_containers/echoserver:1.10 + ports: + - containerPort: 8080 diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/multiple-certs/svc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/multiple-certs/svc.yaml new file mode 100644 index 000000000..b022aa17f --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/multiple-certs/svc.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: echoheaders-https + labels: + app: echoheaders-https +spec: + type: NodePort + ports: + - port: 80 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: echoheaders-https diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/neg-clusterip/ing.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/neg-clusterip/ing.yaml new file mode 100644 index 000000000..e266d9851 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/neg-clusterip/ing.yaml @@ -0,0 +1,8 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: hostname +spec: + backend: + serviceName: hostname + servicePort: 80 \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/neg-clusterip/rc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/neg-clusterip/rc.yaml new file mode 100644 index 000000000..de2246e6d --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/neg-clusterip/rc.yaml @@ -0,0 +1,18 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + run: hostname + name: hostname +spec: + minReadySeconds: 60 + template: + metadata: + labels: + run: hostname + spec: + containers: + - image: gcr.io/kubernetes-e2e-test-images/serve-hostname-amd64:1.1 + imagePullPolicy: IfNotPresent + name: hostname + terminationGracePeriodSeconds: 120 \ No newline at end of file diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/neg-clusterip/svc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/neg-clusterip/svc.yaml new file mode 100644 index 000000000..6ca920bd2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/neg-clusterip/svc.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: hostname + annotations: + alpha.cloud.google.com/load-balancer-neg: "true" +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 9376 + selector: + run: hostname + sessionAffinity: None + type: ClusterIP diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/pre-shared-cert/ing.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/pre-shared-cert/ing.yaml index 1de721a47..1c3e30dc5 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/pre-shared-cert/ing.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/pre-shared-cert/ing.yaml @@ -6,6 +6,10 @@ metadata: # annotations: # ingress.gcp.kubernetes.io/pre-shared-cert: "test-pre-shared-cert" spec: + # kubemci requires a default backend. + backend: + serviceName: echoheaders-https + servicePort: 80 rules: - host: test.ingress.com http: diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/pre-shared-cert/rc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/pre-shared-cert/rc.yaml index abf9b036e..6bef004ed 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/pre-shared-cert/rc.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/pre-shared-cert/rc.yaml @@ -11,6 +11,6 @@ spec: spec: containers: - name: echoheaders-https - image: gcr.io/google_containers/echoserver:1.6 + image: k8s.gcr.io/echoserver:1.10 ports: - containerPort: 8080 diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/static-ip-2/rc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/static-ip-2/rc.yaml index 391ad6744..6bef004ed 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/static-ip-2/rc.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/static-ip-2/rc.yaml @@ -11,6 +11,6 @@ spec: spec: containers: - name: echoheaders-https - image: k8s.gcr.io/echoserver:1.6 + image: k8s.gcr.io/echoserver:1.10 ports: - containerPort: 8080 diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/static-ip/rc.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/static-ip/rc.yaml index 391ad6744..6bef004ed 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/static-ip/rc.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/ingress/static-ip/rc.yaml @@ -11,6 +11,6 @@ spec: spec: containers: - name: echoheaders-https - image: k8s.gcr.io/echoserver:1.6 + image: k8s.gcr.io/echoserver:1.10 ports: - containerPort: 8080 diff --git a/vendor/k8s.io/kubernetes/examples/storage/redis/redis-master.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/kubectl/redis-master-pod.yaml similarity index 100% rename from vendor/k8s.io/kubernetes/examples/storage/redis/redis-master.yaml rename to vendor/k8s.io/kubernetes/test/e2e/testing-manifests/kubectl/redis-master-pod.yaml diff --git a/vendor/k8s.io/kubernetes/examples/pod b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/pod similarity index 100% rename from vendor/k8s.io/kubernetes/examples/pod rename to vendor/k8s.io/kubernetes/test/e2e/testing-manifests/pod diff --git a/vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/rbd-storage-class.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/rbd-storage-class.yaml similarity index 100% rename from vendor/k8s.io/kubernetes/examples/persistent-volume-provisioning/rbd/rbd-storage-class.yaml rename to vendor/k8s.io/kubernetes/test/e2e/testing-manifests/rbd-storage-class.yaml diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/cockroachdb/service.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/cockroachdb/service.yaml index a320bb0af..4acf5eec5 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/cockroachdb/service.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/cockroachdb/service.yaml @@ -9,13 +9,6 @@ metadata: labels: app: cockroachdb annotations: - # This is needed to make the peer-finder work properly and to help avoid - # edge cases where instance 0 comes up after losing its data and needs to - # decide whether it should create a new cluster or try to join an existing - # one. If it creates a new cluster when it should have joined an existing - # one, we'd end up with two separate clusters listening at the same service - # endpoint, which would be very bad. - service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" # Enable automatic monitoring of all instances when Prometheus is running in the cluster. prometheus.io/scrape: "true" prometheus.io/path: "_status/vars" @@ -31,3 +24,10 @@ spec: clusterIP: None selector: app: cockroachdb + # This is needed to make the peer-finder work properly and to help avoid + # edge cases where instance 0 comes up after losing its data and needs to + # decide whether it should create a new cluster or try to join an existing + # one. If it creates a new cluster when it should have joined an existing + # one, we'd end up with two separate clusters listening at the same service + # endpoint, which would be very bad. + publishNotReadyAddresses: true diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/etcd/service.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/etcd/service.yaml index 3932f04f4..bf204e841 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/etcd/service.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/etcd/service.yaml @@ -1,8 +1,5 @@ apiVersion: v1 kind: Service -metadata: - annotations: - service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" metadata: name: etcd labels: @@ -16,3 +13,4 @@ spec: clusterIP: None selector: app: etcd + publishNotReadyAddresses: true diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/mysql-galera/service.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/mysql-galera/service.yaml index 8fa9c324a..514e605ab 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/mysql-galera/service.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/mysql-galera/service.yaml @@ -2,8 +2,6 @@ apiVersion: v1 kind: Service metadata: - annotations: - service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" name: galera labels: app: mysql @@ -15,4 +13,4 @@ spec: clusterIP: None selector: app: mysql - + publishNotReadyAddresses: true diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/redis/service.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/redis/service.yaml index 376c7beef..bfdc34655 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/redis/service.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/redis/service.yaml @@ -2,8 +2,6 @@ apiVersion: v1 kind: Service metadata: - annotations: - service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" name: redis labels: app: redis @@ -15,4 +13,3 @@ spec: clusterIP: None selector: app: redis - diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/zookeeper/service.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/zookeeper/service.yaml index 8659a2af6..cf6e6972f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/zookeeper/service.yaml +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/statefulset/zookeeper/service.yaml @@ -2,8 +2,6 @@ apiVersion: v1 kind: Service metadata: - annotations: - service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" name: zk labels: app: zk @@ -17,4 +15,4 @@ spec: clusterIP: None selector: app: zk - + publishNotReadyAddresses: true diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/storage-csi/gce-pd/controller_service.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/storage-csi/gce-pd/controller_service.yaml new file mode 100644 index 000000000..6c509b2fd --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/storage-csi/gce-pd/controller_service.yaml @@ -0,0 +1,12 @@ +kind: Service +apiVersion: v1 +metadata: + name: csi-gce-pd + labels: + app: csi-gce-pd +spec: + selector: + app: csi-gce-pd + ports: + - name: dummy + port: 12345 diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/storage-csi/gce-pd/controller_ss.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/storage-csi/gce-pd/controller_ss.yaml new file mode 100644 index 000000000..76f1ca9b7 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/storage-csi/gce-pd/controller_ss.yaml @@ -0,0 +1,70 @@ +kind: StatefulSet +apiVersion: apps/v1beta1 +metadata: + name: csi-gce-controller +spec: + serviceName: "csi-gce-pd" + replicas: 1 + selector: + matchLabels: + app: csi-gce-pd-driver + template: + metadata: + labels: + app: csi-gce-pd-driver + spec: + serviceAccount: csi-gce-pd + containers: + - name: csi-external-provisioner + imagePullPolicy: Always + image: quay.io/k8scsi/csi-provisioner:v0.2.0 + args: + - "--v=5" + - "--provisioner=csi-gce-pd" + - "--csi-address=$(ADDRESS)" + env: + - name: ADDRESS + value: /csi/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /csi + - name: csi-attacher + imagePullPolicy: Always + image: quay.io/k8scsi/csi-attacher:v0.2.0 + args: + - "--v=5" + - "--csi-address=$(ADDRESS)" + env: + - name: ADDRESS + value: /csi/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /csi + - name: gce-driver + imagePullPolicy: Always + image: gcr.io/google-containers/volume-csi/compute-persistent-disk-csi-driver:v0.2.0.alpha + args: + - "--v=5" + - "--endpoint=$(CSI_ENDPOINT)" + - "--nodeid=$(KUBE_NODE_NAME)" + env: + - name: CSI_ENDPOINT + value: unix:///csi/csi.sock + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: GOOGLE_APPLICATION_CREDENTIALS + value: "/etc/service-account/cloud-sa.json" + volumeMounts: + - name: socket-dir + mountPath: /csi + - name: cloud-sa-volume + readOnly: true + mountPath: "/etc/service-account" + volumes: + - name: socket-dir + emptyDir: {} + - name: cloud-sa-volume + secret: + secretName: cloud-sa diff --git a/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/storage-csi/gce-pd/node_ds.yaml b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/storage-csi/gce-pd/node_ds.yaml new file mode 100644 index 000000000..11890676e --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/testing-manifests/storage-csi/gce-pd/node_ds.yaml @@ -0,0 +1,69 @@ +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: csi-gce-node +spec: + selector: + matchLabels: + app: csi-gce-driver + serviceName: csi-gce + template: + metadata: + labels: + app: csi-gce-driver + spec: + serviceAccount: csi-gce-pd + containers: + - name: csi-driver-registrar + imagePullPolicy: Always + image: quay.io/k8scsi/driver-registrar:v0.2.0 + args: + - "--v=5" + - "--csi-address=$(ADDRESS)" + env: + - name: ADDRESS + value: /csi/csi.sock + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: plugin-dir + mountPath: /csi + - name: gce-driver + securityContext: + privileged: true + imagePullPolicy: Always + image: gcr.io/google-containers/volume-csi/compute-persistent-disk-csi-driver:v0.2.0.alpha + args: + - "--v=5" + - "--endpoint=$(CSI_ENDPOINT)" + - "--nodeid=$(KUBE_NODE_NAME)" + env: + - name: CSI_ENDPOINT + value: unix:///csi/csi.sock + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: kubelet-dir + mountPath: /var/lib/kubelet + mountPropagation: "Bidirectional" + - name: plugin-dir + mountPath: /csi + - name: device-dir + mountPath: /host/dev + volumes: + - name: kubelet-dir + hostPath: + path: /var/lib/kubelet + type: Directory + - name: plugin-dir + hostPath: + path: /var/lib/kubelet/plugins/com.google.csi.gcepd/ + type: DirectoryOrCreate + - name: device-dir + hostPath: + path: /dev + type: Directory diff --git a/vendor/k8s.io/kubernetes/test/e2e/upgrades/BUILD b/vendor/k8s.io/kubernetes/test/e2e/upgrades/BUILD index a3db35287..d8355c417 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/upgrades/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e/upgrades/BUILD @@ -16,6 +16,7 @@ go_library( "ingress.go", "kube_proxy_migration.go", "mysql.go", + "nvidia-gpu.go", "secrets.go", "services.go", "sysctl.go", @@ -23,11 +24,11 @@ go_library( ], importpath = "k8s.io/kubernetes/test/e2e/upgrades", deps = [ - "//pkg/apis/core/v1/helper:go_default_library", "//pkg/kubelet/sysctl:go_default_library", "//pkg/util/version:go_default_library", "//test/e2e/common:go_default_library", "//test/e2e/framework:go_default_library", + "//test/e2e/scheduling:go_default_library", "//test/utils/image:go_default_library", "//vendor/github.com/davecgh/go-spew/spew:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", @@ -38,6 +39,7 @@ go_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/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/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e/upgrades/apps/deployments.go b/vendor/k8s.io/kubernetes/test/e2e/upgrades/apps/deployments.go index 9063f16a9..d31e3258f 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/upgrades/apps/deployments.go +++ b/vendor/k8s.io/kubernetes/test/e2e/upgrades/apps/deployments.go @@ -19,7 +19,7 @@ package upgrades import ( "fmt" - extensions "k8s.io/api/extensions/v1beta1" + apps "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" @@ -54,11 +54,11 @@ func (t *DeploymentUpgradeTest) Setup(f *framework.Framework) { nginxImage := imageutils.GetE2EImage(imageutils.NginxSlim) ns := f.Namespace.Name - deploymentClient := c.ExtensionsV1beta1().Deployments(ns) - rsClient := c.ExtensionsV1beta1().ReplicaSets(ns) + deploymentClient := c.AppsV1().Deployments(ns) + rsClient := c.AppsV1().ReplicaSets(ns) By(fmt.Sprintf("Creating a deployment %q with 1 replica in namespace %q", deploymentName, ns)) - d := framework.NewDeployment(deploymentName, int32(1), map[string]string{"test": "upgrade"}, "nginx", nginxImage, extensions.RollingUpdateDeploymentStrategyType) + d := framework.NewDeployment(deploymentName, int32(1), map[string]string{"test": "upgrade"}, "nginx", nginxImage, apps.RollingUpdateDeploymentStrategyType) deployment, err := deploymentClient.Create(d) framework.ExpectNoError(err) @@ -81,7 +81,7 @@ func (t *DeploymentUpgradeTest) Setup(f *framework.Framework) { // Trigger a new rollout so that we have some history. By(fmt.Sprintf("Triggering a new rollout for deployment %q", deploymentName)) - deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deploymentName, func(update *extensions.Deployment) { + deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deploymentName, func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Name = "updated-name" }) framework.ExpectNoError(err) @@ -121,8 +121,8 @@ func (t *DeploymentUpgradeTest) Test(f *framework.Framework, done <-chan struct{ c := f.ClientSet ns := f.Namespace.Name - deploymentClient := c.ExtensionsV1beta1().Deployments(ns) - rsClient := c.ExtensionsV1beta1().ReplicaSets(ns) + deploymentClient := c.AppsV1().Deployments(ns) + rsClient := c.AppsV1().ReplicaSets(ns) deployment, err := deploymentClient.Get(deploymentName, metav1.GetOptions{}) framework.ExpectNoError(err) @@ -157,7 +157,7 @@ func (t *DeploymentUpgradeTest) Test(f *framework.Framework, done <-chan struct{ // Verify the upgraded deployment is active by scaling up the deployment by 1 By(fmt.Sprintf("Scaling up replicaset of deployment %q by 1", deploymentName)) - _, err = framework.UpdateDeploymentWithRetries(c, ns, deploymentName, func(deployment *extensions.Deployment) { + _, err = framework.UpdateDeploymentWithRetries(c, ns, deploymentName, func(deployment *apps.Deployment) { *deployment.Spec.Replicas = *deployment.Spec.Replicas + 1 }) framework.ExpectNoError(err) diff --git a/vendor/k8s.io/kubernetes/test/e2e/upgrades/apps/replicasets.go b/vendor/k8s.io/kubernetes/test/e2e/upgrades/apps/replicasets.go index 88d46c2ae..4b3fd327d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/upgrades/apps/replicasets.go +++ b/vendor/k8s.io/kubernetes/test/e2e/upgrades/apps/replicasets.go @@ -20,7 +20,7 @@ import ( "fmt" "time" - extensions "k8s.io/api/extensions/v1beta1" + apps "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/test/e2e/framework" @@ -54,7 +54,7 @@ func (r *ReplicaSetUpgradeTest) Setup(f *framework.Framework) { By(fmt.Sprintf("Creating replicaset %s in namespace %s", rsName, ns)) replicaSet := framework.NewReplicaSet(rsName, ns, 1, map[string]string{"test": "upgrade"}, "nginx", nginxImage) - rs, err := c.ExtensionsV1beta1().ReplicaSets(ns).Create(replicaSet) + rs, err := c.AppsV1().ReplicaSets(ns).Create(replicaSet) framework.ExpectNoError(err) By(fmt.Sprintf("Waiting for replicaset %s to have all of its replicas ready", rsName)) @@ -67,7 +67,7 @@ func (r *ReplicaSetUpgradeTest) Setup(f *framework.Framework) { func (r *ReplicaSetUpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade upgrades.UpgradeType) { c := f.ClientSet ns := f.Namespace.Name - rsClient := c.ExtensionsV1beta1().ReplicaSets(ns) + rsClient := c.AppsV1().ReplicaSets(ns) // Block until upgrade is done By(fmt.Sprintf("Waiting for upgrade to finish before checking replicaset %s", rsName)) @@ -86,7 +86,7 @@ func (r *ReplicaSetUpgradeTest) Test(f *framework.Framework, done <-chan struct{ // Verify the upgraded RS is active by scaling up the RS to scaleNum and ensuring all pods are Ready By(fmt.Sprintf("Scaling up replicaset %s to %d", rsName, scaleNum)) - _, err = framework.UpdateReplicaSetWithRetries(c, ns, rsName, func(rs *extensions.ReplicaSet) { + _, err = framework.UpdateReplicaSetWithRetries(c, ns, rsName, func(rs *apps.ReplicaSet) { *rs.Spec.Replicas = scaleNum }) framework.ExpectNoError(err) diff --git a/vendor/k8s.io/kubernetes/test/e2e/upgrades/horizontal_pod_autoscalers.go b/vendor/k8s.io/kubernetes/test/e2e/upgrades/horizontal_pod_autoscalers.go index f76ae0635..c01c46cd6 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/upgrades/horizontal_pod_autoscalers.go +++ b/vendor/k8s.io/kubernetes/test/e2e/upgrades/horizontal_pod_autoscalers.go @@ -48,7 +48,8 @@ func (t *HPAUpgradeTest) Setup(f *framework.Framework) { 500, /* cpuLimit */ 200, /* memLimit */ f.ClientSet, - f.InternalClientset) + f.InternalClientset, + f.ScalesGetter) t.hpa = common.CreateCPUHorizontalPodAutoscaler( t.rc, 20, /* targetCPUUtilizationPercent */ diff --git a/vendor/k8s.io/kubernetes/test/e2e/upgrades/ingress.go b/vendor/k8s.io/kubernetes/test/e2e/upgrades/ingress.go index c27da7258..855e8dcab 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/upgrades/ingress.go +++ b/vendor/k8s.io/kubernetes/test/e2e/upgrades/ingress.go @@ -99,7 +99,7 @@ func (t *IngressUpgradeTest) Setup(f *framework.Framework) { framework.IngressStaticIPKey: t.ipName, framework.IngressAllowHTTPKey: "false", }, map[string]string{}) - t.jig.AddHTTPS("tls-secret", "ingress.test.com") + t.jig.SetHTTPS("tls-secret", "ingress.test.com") By("waiting for Ingress to come up with ip: " + t.ip) framework.ExpectNoError(framework.PollURL(fmt.Sprintf("https://%v/%v", t.ip, path), host, framework.LoadBalancerPollTimeout, t.jig.PollInterval, t.httpClient, false)) @@ -199,19 +199,23 @@ func (t *IngressUpgradeTest) verify(f *framework.Framework, done <-chan struct{} postUpgradeResourceStore := &GCPResourceStore{} t.populateGCPResourceStore(postUpgradeResourceStore) - // Ignore certain fields in compute.Firewall that we know will change - // due to the upgrade/downgrade. - // TODO(rramkumar): Remove this once glbc 0.9.8 is released. - t.resourceStore.Fw.Allowed = nil - t.resourceStore.Fw.SourceRanges = nil - postUpgradeResourceStore.Fw.Allowed = nil - postUpgradeResourceStore.Fw.SourceRanges = nil + // Stub out the number of instances as that is out of Ingress controller's control. + for _, ig := range t.resourceStore.IgList { + ig.Size = 0 + } + for _, ig := range postUpgradeResourceStore.IgList { + ig.Size = 0 + } // Stub out compute.SslCertificates in case we know it will change during an upgrade/downgrade. if t.skipSSLCheck { t.resourceStore.SslList = nil postUpgradeResourceStore.SslList = nil } + // TODO(rramkumar): Remove this when GLBC v1.2.0 is released. + t.resourceStore.BeList = nil + postUpgradeResourceStore.BeList = nil + framework.ExpectNoError(compareGCPResourceStores(t.resourceStore, postUpgradeResourceStore, func(v1 reflect.Value, v2 reflect.Value) error { i1 := v1.Interface() i2 := v2.Interface() diff --git a/vendor/k8s.io/kubernetes/test/e2e/upgrades/nvidia-gpu.go b/vendor/k8s.io/kubernetes/test/e2e/upgrades/nvidia-gpu.go new file mode 100644 index 000000000..12abd0e34 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e/upgrades/nvidia-gpu.go @@ -0,0 +1,112 @@ +/* +Copyright 2018 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 upgrades + +import ( + "regexp" + "time" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/scheduling" + imageutils "k8s.io/kubernetes/test/utils/image" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +// NvidiaGPUUpgradeTest tests that gpu resource is available before and after +// a cluster upgrade. +type NvidiaGPUUpgradeTest struct { +} + +func (NvidiaGPUUpgradeTest) Name() string { return "nvidia-gpu-upgrade [sig-node] [sig-scheduling]" } + +// Setup creates a job requesting gpu. +func (t *NvidiaGPUUpgradeTest) Setup(f *framework.Framework) { + scheduling.SetupNVIDIAGPUNode(f, false) + By("Creating a job requesting gpu") + t.startJob(f) +} + +// Test waits for the upgrade to complete, and then verifies that the +// cuda pod started by the gpu job can successfully finish. +func (t *NvidiaGPUUpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade UpgradeType) { + <-done + By("Verifying gpu job success") + t.verifyJobPodSuccess(f) + if upgrade == MasterUpgrade { + // MasterUpgrade should be totally hitless. + job, err := framework.GetJob(f.ClientSet, f.Namespace.Name, "cuda-add") + Expect(err).NotTo(HaveOccurred()) + Expect(job.Status.Failed).To(BeZero(), "Job pods failed during master upgrade: %v", job.Status.Failed) + } +} + +// Teardown cleans up any remaining resources. +func (t *NvidiaGPUUpgradeTest) Teardown(f *framework.Framework) { + // rely on the namespace deletion to clean up everything +} + +// startJob creates a job that requests gpu and runs a simple cuda container. +func (t *NvidiaGPUUpgradeTest) startJob(f *framework.Framework) { + var activeSeconds int64 = 3600 + // Specifies 100 completions to make sure the job life spans across the upgrade. + testJob := framework.NewTestJob("succeed", "cuda-add", v1.RestartPolicyAlways, 1, 100, &activeSeconds, 6) + testJob.Spec.Template.Spec = v1.PodSpec{ + RestartPolicy: v1.RestartPolicyOnFailure, + Containers: []v1.Container{ + { + Name: "vector-addition", + Image: imageutils.GetE2EImage(imageutils.CudaVectorAdd), + Command: []string{"/bin/sh", "-c", "./vectorAdd && sleep 60"}, + Resources: v1.ResourceRequirements{ + Limits: v1.ResourceList{ + framework.NVIDIAGPUResourceName: *resource.NewQuantity(1, resource.DecimalSI), + }, + }, + }, + }, + } + ns := f.Namespace.Name + _, err := framework.CreateJob(f.ClientSet, ns, testJob) + Expect(err).NotTo(HaveOccurred()) + framework.Logf("Created job %v", testJob) + By("Waiting for gpu job pod start") + err = framework.WaitForAllJobPodsRunning(f.ClientSet, ns, testJob.Name, 1) + Expect(err).NotTo(HaveOccurred()) + By("Done with gpu job pod start") +} + +// verifyJobPodSuccess verifies that the started cuda pod successfully passes. +func (t *NvidiaGPUUpgradeTest) verifyJobPodSuccess(f *framework.Framework) { + // Wait for client pod to complete. + ns := f.Namespace.Name + err := framework.WaitForAllJobPodsRunning(f.ClientSet, f.Namespace.Name, "cuda-add", 1) + Expect(err).NotTo(HaveOccurred()) + pods, err := framework.GetJobPods(f.ClientSet, f.Namespace.Name, "cuda-add") + Expect(err).NotTo(HaveOccurred()) + createdPod := pods.Items[0].Name + framework.Logf("Created pod %v", createdPod) + f.PodClient().WaitForSuccess(createdPod, 5*time.Minute) + logs, err := framework.GetPodLogs(f.ClientSet, ns, createdPod, "vector-addition") + framework.ExpectNoError(err, "Should be able to get pod logs") + framework.Logf("Got pod logs: %v", logs) + regex := regexp.MustCompile("PASSED") + Expect(regex.MatchString(logs)).To(BeTrue()) +} diff --git a/vendor/k8s.io/kubernetes/test/e2e/upgrades/storage/persistent_volumes.go b/vendor/k8s.io/kubernetes/test/e2e/upgrades/storage/persistent_volumes.go index 0c00bc6d5..8bfc24de0 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/upgrades/storage/persistent_volumes.go +++ b/vendor/k8s.io/kubernetes/test/e2e/upgrades/storage/persistent_volumes.go @@ -62,11 +62,8 @@ func (t *PersistentVolumeUpgradeTest) Setup(f *framework.Framework) { PVSource: *t.pvSource, Prebind: nil, } - pvcConfig := framework.PersistentVolumeClaimConfig{ - Annotations: map[string]string{ - v1.BetaStorageClassAnnotation: "", - }, - } + emptyStorageClass := "" + pvcConfig := framework.PersistentVolumeClaimConfig{StorageClassName: &emptyStorageClass} By("Creating the PV and PVC") t.pv, t.pvc, err = framework.CreatePVPVC(f.ClientSet, pvConfig, pvcConfig, ns, true) diff --git a/vendor/k8s.io/kubernetes/test/e2e/upgrades/sysctl.go b/vendor/k8s.io/kubernetes/test/e2e/upgrades/sysctl.go index 1b9a0a71a..8ba3fdaef 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/upgrades/sysctl.go +++ b/vendor/k8s.io/kubernetes/test/e2e/upgrades/sysctl.go @@ -26,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/kubelet/sysctl" "k8s.io/kubernetes/test/e2e/framework" @@ -123,9 +122,6 @@ func sysctlTestPod(name string, sysctls map[string]string) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: name, - Annotations: map[string]string{ - v1.SysctlsPodAnnotationKey: v1helper.PodAnnotationsFromSysctls(sysctlList), - }, }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -136,6 +132,9 @@ func sysctlTestPod(name string, sysctls map[string]string) *v1.Pod { }, }, RestartPolicy: v1.RestartPolicyNever, + SecurityContext: &v1.PodSecurityContext{ + Sysctls: sysctlList, + }, }, } } diff --git a/vendor/k8s.io/kubernetes/test/e2e_kubeadm/BUILD b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/BUILD new file mode 100644 index 000000000..ead6cc65d --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/BUILD @@ -0,0 +1,65 @@ +package(default_visibility = ["//visibility:public"]) + +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_test( + name = "go_default_test", + srcs = [ + "e2e_kubeadm_suite_test.go", + "kubeadm_test.go", + ], + embed = [":go_default_library"], + tags = ["e2e"], + deps = [ + "//test/e2e/framework:go_default_library", + "//vendor/github.com/onsi/ginkgo:go_default_library", + "//vendor/github.com/onsi/gomega:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +genrule( + name = "gen_e2e_kubeadm.test", + testonly = 1, + srcs = [":go_default_test"], + outs = ["e2e_kubeadm.test"], + cmd = "srcs=($(SRCS)); cp $$(dirname $${srcs[0]})/go_default_test $@;", + output_to_bindir = 1, +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//test/e2e_kubeadm/runner/local:all-srcs", + "//test/e2e_kubeadm/tests:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + srcs = ["matchers.go"], + importpath = "k8s.io/kubernetes/test/e2e_kubeadm", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/onsi/gomega:go_default_library", + "//vendor/github.com/onsi/gomega/gstruct:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/test/e2e_kubeadm/e2e_kubeadm_suite_test.go b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/e2e_kubeadm_suite_test.go new file mode 100644 index 000000000..8fc3114b8 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/e2e_kubeadm_suite_test.go @@ -0,0 +1,48 @@ +/* +Copyright 2018 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 e2e_kubeadm + +import ( + "flag" + "os" + "testing" + + "github.com/onsi/ginkgo" + "github.com/onsi/gomega" + "github.com/spf13/pflag" + + "k8s.io/kubernetes/test/e2e/framework" +) + +func init() { + framework.RegisterCommonFlags() + framework.RegisterClusterFlags() + + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) +} + +func TestMain(m *testing.M) { + pflag.Parse() + framework.AfterReadingAllFlags(&framework.TestContext) + os.Exit(m.Run()) +} + +func TestE2E(t *testing.T) { + reporters := []ginkgo.Reporter{} + gomega.RegisterFailHandler(ginkgo.Fail) + ginkgo.RunSpecsWithDefaultAndCustomReporters(t, "E2EKubadm suite", reporters) +} diff --git a/vendor/k8s.io/kubernetes/test/e2e_kubeadm/kubeadm_test.go b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/kubeadm_test.go new file mode 100644 index 000000000..b8dc18c3c --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/kubeadm_test.go @@ -0,0 +1,136 @@ +/* +Copyright 2018 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 e2e_kubeadm + +import ( + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + "k8s.io/kubernetes/test/e2e/framework" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +const ( + masterTaint = "node-role.kubernetes.io/master" + kubeadmConfigNamespace = "kube-system" + kubeadmConfigName = "kubeadm-config" + clusterInfoNamespace = "kube-public" + clusterInfoName = "cluster-info" + bootstrapSignerRoleNamespace = "kube-system" + bootstrapSignerRoleName = "system:controller:bootstrap-signer" +) + +var _ = framework.KubeDescribe("Kubeadm [Feature:Kubeadm]", func() { + f := framework.NewDefaultFramework("kubeadm") + + Describe("kubeadm master", func() { + It("should be labelled and tainted", func() { + selector := labels.Set{masterTaint: ""}.AsSelector() + master, err := f.ClientSet.CoreV1().Nodes(). + List(metav1.ListOptions{LabelSelector: selector.String()}) + framework.ExpectNoError(err, "couldn't find a master node") + Expect(master.Items).NotTo(BeEmpty()) + for _, master := range master.Items { + Expect(master.Spec.Taints).To( + ContainElement(taint(masterTaint, corev1.TaintEffectNoSchedule)), + ) + } + }) + }) + + Describe("kubeadm-config config map", func() { + It("should exist", func() { + _, err := f.ClientSet.CoreV1(). + ConfigMaps(kubeadmConfigNamespace). + Get(kubeadmConfigName, metav1.GetOptions{}) + framework.ExpectNoError(err) + }) + }) + + Describe("cluster-info", func() { + It("should have expected keys", func() { + clientInfo, err := f.ClientSet.CoreV1(). + ConfigMaps(clusterInfoNamespace). + Get(clusterInfoName, metav1.GetOptions{}) + framework.ExpectNoError(err, "couldn't find config map") + + Expect(clientInfo.Data).To(HaveKey(HavePrefix(bootstrapapi.JWSSignatureKeyPrefix))) + Expect(clientInfo.Data).To(HaveKey(bootstrapapi.KubeConfigKey)) + }) + + It("should be public", func() { + cfg, err := framework.LoadConfig() + framework.ExpectNoError(err, "couldn't get config") + cfg = rest.AnonymousClientConfig(cfg) + client, err := kubernetes.NewForConfig(cfg) + framework.ExpectNoError(err, "couldn't create client") + + _, err = client.CoreV1().ConfigMaps(clusterInfoNamespace). + Get(clusterInfoName, metav1.GetOptions{}) + framework.ExpectNoError(err, "couldn't anonymously access config") + }) + }) + + Describe("bootstrap signer RBAC role", func() { + It("should exist", func() { + _, err := f.ClientSet.RbacV1(). + Roles(bootstrapSignerRoleNamespace). + Get(bootstrapSignerRoleName, metav1.GetOptions{}) + framework.ExpectNoError(err, "doesn't exist") + }) + }) + + Describe("kubeadm:kubelet-bootstrap cluster role binding", func() { + It("should exist", func() { + binding, err := f.ClientSet.RbacV1(). + ClusterRoleBindings(). + Get("kubeadm:kubelet-bootstrap", metav1.GetOptions{}) + framework.ExpectNoError(err, "couldn't get clusterrolebinding") + Expect(binding.Subjects).To( + ContainElement(subject( + "system:bootstrappers:kubeadm:default-node-token", + rbacv1.GroupKind, + )), + ) + Expect(binding.RoleRef.Name).To(Equal("system:node-bootstrapper")) + }) + }) + + Describe("autoapproval for new bootstrap token", func() { + It("should create a clusterrolebinding", func() { + binding, err := f.ClientSet.RbacV1(). + ClusterRoleBindings(). + Get("kubeadm:node-autoapprove-bootstrap", metav1.GetOptions{}) + framework.ExpectNoError(err, "couldn't get clusterrolebinding") + Expect(binding.Subjects).To( + ContainElement(subject( + "system:bootstrappers:kubeadm:default-node-token", + rbacv1.GroupKind, + )), + ) + Expect(binding.RoleRef.Name).To( + Equal("system:certificates.k8s.io:certificatesigningrequests:nodeclient"), + ) + }) + }) +}) diff --git a/vendor/k8s.io/kubernetes/test/e2e_kubeadm/matchers.go b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/matchers.go new file mode 100644 index 000000000..8af786616 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/matchers.go @@ -0,0 +1,37 @@ +/* +Copyright 2018 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 e2e_kubeadm + +import ( + "github.com/onsi/gomega" + "github.com/onsi/gomega/gstruct" + corev1 "k8s.io/api/core/v1" +) + +func subject(name, kind string) gomega.OmegaMatcher { + return gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ + "Name": gomega.Equal(name), + "Kind": gomega.Equal(kind), + }) +} + +func taint(key string, effect corev1.TaintEffect) gomega.OmegaMatcher { + return gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ + "Key": gomega.Equal(key), + "Effect": gomega.Equal(effect), + }) +} diff --git a/vendor/k8s.io/kubernetes/test/e2e_kubeadm/runner/local/BUILD b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/runner/local/BUILD new file mode 100644 index 000000000..412adbe48 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/runner/local/BUILD @@ -0,0 +1,32 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "go_default_library", + srcs = ["run_local.go"], + importpath = "k8s.io/kubernetes/test/e2e_kubeadm/runner/local", + visibility = ["//visibility:private"], + deps = [ + "//test/utils:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + ], +) + +go_binary( + name = "local", + embed = [":go_default_library"], + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/test/e2e_kubeadm/runner/local/run_local.go b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/runner/local/run_local.go new file mode 100644 index 000000000..9ccdfcb73 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/runner/local/run_local.go @@ -0,0 +1,106 @@ +/* +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 main + +import ( + "flag" + "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + + "github.com/golang/glog" + "k8s.io/kubernetes/test/utils" +) + +func bazelBuild() error { + targets := []string{ + "//vendor/github.com/onsi/ginkgo/ginkgo", + "//test/e2e_kubeadm:e2e_kubeadm.test", + } + + args := append([]string{"build"}, targets...) + + return execCommand("bazel", args...) +} + +var ginkgoFlags = flag.String("ginkgo-flags", "", "Space-separated list of arguments to pass to Ginkgo test runner.") +var testFlags = flag.String("test-flags", "", "Space-separated list of arguments to pass to node e2e test.") +var build = flag.Bool("build", false, "use Bazel to build binaries before testing") + +func main() { + flag.Parse() + + if *build { + if err := bazelBuild(); err != nil { + glog.Exitf("couldn't build with bazel: %v", err) + } + } + + ginkgo, err := getBazelGinkgo() + if err != nil { + glog.Fatalf("Failed to get ginkgo binary: %v", err) + } + + test, err := getBazelTestBin() + if err != nil { + glog.Fatalf("Failed to get test file: %v", err) + } + + args := append(strings.Split(*ginkgoFlags, " "), test, "--") + args = append(args, strings.Split(*testFlags, " ")...) + + if execCommand(ginkgo, args...); err != nil { + glog.Exitf("Test failed: %v", err) + } + +} + +func getBazelTestBin() (string, error) { + k8sRoot, err := utils.GetK8sRootDir() + if err != nil { + return "", err + } + buildFile := filepath.Join(k8sRoot, "bazel-bin/test/e2e_kubeadm/e2e_kubeadm.test") + if _, err := os.Stat(buildFile); err != nil { + return "", err + } + return buildFile, nil + +} + +func getBazelGinkgo() (string, error) { + k8sRoot, err := utils.GetK8sRootDir() + if err != nil { + return "", err + } + buildOutputDir := filepath.Join(k8sRoot, "bazel-bin", "vendor/github.com/onsi/ginkgo/ginkgo", fmt.Sprintf("%s_%s_stripped", runtime.GOOS, runtime.GOARCH), "ginkgo") + if _, err := os.Stat(buildOutputDir); err != nil { + return "", err + } + return buildOutputDir, nil +} + +func execCommand(binary string, args ...string) error { + fmt.Printf("Running command: %v %v\n", binary, strings.Join(args, " ")) + cmd := exec.Command(binary, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} diff --git a/vendor/k8s.io/kubernetes/test/e2e_kubeadm/tests/BUILD b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/tests/BUILD new file mode 100644 index 000000000..6df04e38c --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/e2e_kubeadm/tests/BUILD @@ -0,0 +1,13 @@ +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/BUILD b/vendor/k8s.io/kubernetes/test/e2e_node/BUILD index ec7f37a26..9d39a0de9 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e_node/BUILD @@ -11,9 +11,7 @@ go_library( "docker_util.go", "framework.go", "gpu_device_plugin.go", - "gpus.go", "image_list.go", - "simple_mount.go", "util.go", ] + select({ "@io_bazel_rules_go//go/platform:linux": [ @@ -32,10 +30,11 @@ go_library( "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/apis/deviceplugin/v1beta1:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", "//pkg/kubelet/apis/stats/v1alpha1:go_default_library", + "//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/cm/devicemanager:go_default_library", + "//pkg/kubelet/kubeletconfig/util/codec:go_default_library", "//pkg/kubelet/metrics:go_default_library", "//pkg/kubelet/remote:go_default_library", "//test/e2e/common:go_default_library", @@ -55,7 +54,6 @@ 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/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", @@ -130,6 +128,7 @@ go_test( "//pkg/kubelet/cm/cpumanager:go_default_library", "//pkg/kubelet/cm/cpuset:go_default_library", "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/eviction:go_default_library", "//pkg/kubelet/images:go_default_library", "//pkg/kubelet/kubeletconfig:go_default_library", "//pkg/kubelet/kubeletconfig/status:go_default_library", @@ -138,6 +137,7 @@ go_test( "//pkg/kubelet/types:go_default_library", "//pkg/security/apparmor:go_default_library", "//test/e2e/framework:go_default_library", + "//test/e2e/framework/metrics:go_default_library", "//test/e2e_node/services:go_default_library", "//test/utils/image:go_default_library", "//vendor/github.com/blang/semver:go_default_library", @@ -148,10 +148,13 @@ go_test( "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/github.com/onsi/gomega/gstruct:go_default_library", "//vendor/github.com/onsi/gomega/types:go_default_library", + "//vendor/github.com/prometheus/common/model: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/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/fields:go_default_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", @@ -164,7 +167,6 @@ go_test( ] + select({ "@io_bazel_rules_go//go/platform:linux": [ "//test/e2e/common:go_default_library", - "//test/e2e/framework/metrics:go_default_library", "//test/e2e_node/system:go_default_library", "//test/utils:go_default_library", "//vendor/github.com/kardianos/osext:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/apparmor_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/apparmor_test.go index 85e351485..6c9c713f7 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/apparmor_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/apparmor_test.go @@ -40,7 +40,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = framework.KubeDescribe("AppArmor [Feature:AppArmor]", func() { +var _ = framework.KubeDescribe("AppArmor [Feature:AppArmor][NodeFeature:AppArmor]", func() { if isAppArmorEnabled() { BeforeEach(func() { By("Loading AppArmor profiles for testing") diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/builder/BUILD b/vendor/k8s.io/kubernetes/test/e2e_node/builder/BUILD index 6a8b9caac..eeda57b85 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/builder/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e_node/builder/BUILD @@ -9,7 +9,10 @@ go_library( name = "go_default_library", srcs = ["build.go"], importpath = "k8s.io/kubernetes/test/e2e_node/builder", - deps = ["//vendor/github.com/golang/glog:go_default_library"], + deps = [ + "//test/utils:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + ], ) filegroup( diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/builder/build.go b/vendor/k8s.io/kubernetes/test/e2e_node/builder/build.go index 5cf432d1b..87ea32a87 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/builder/build.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/builder/build.go @@ -22,10 +22,10 @@ import ( "os" "os/exec" "path/filepath" - "runtime" "strings" "github.com/golang/glog" + "k8s.io/kubernetes/test/utils" ) var k8sBinDir = flag.String("k8s-bin-dir", "", "Directory containing k8s kubelet binaries.") @@ -39,7 +39,7 @@ var buildTargets = []string{ func BuildGo() error { glog.Infof("Building k8s binaries...") - k8sRoot, err := GetK8sRootDir() + k8sRoot, err := utils.GetK8sRootDir() if err != nil { return fmt.Errorf("failed to locate kubernetes root directory %v.", err) } @@ -75,7 +75,7 @@ func getK8sBin(bin string) (string, error) { return filepath.Join(path, bin), nil } - buildOutputDir, err := GetK8sBuildOutputDir() + buildOutputDir, err := utils.GetK8sBuildOutputDir() if err != nil { return "", err } @@ -84,53 +84,7 @@ func getK8sBin(bin string) (string, error) { } // Give up with error - return "", fmt.Errorf("Unable to locate %s. Can be defined using --k8s-path.", bin) -} - -// GetK8sRootDir returns the root directory for kubernetes, if present in the gopath. -func GetK8sRootDir() (string, error) { - dir, err := RootDir() - if err != nil { - return "", err - } - return filepath.Join(dir, fmt.Sprintf("%s/", "k8s.io/kubernetes")), nil -} - -// GetCAdvisorRootDir returns the root directory for cAdvisor, if present in the gopath. -func GetCAdvisorRootDir() (string, error) { - dir, err := RootDir() - if err != nil { - return "", err - } - return filepath.Join(dir, fmt.Sprintf("%s/", "github.com/google/cadvisor")), nil -} - -// TODO: Dedup / merge this with comparable utilities in e2e/util.go -// RootDir returns the path to the directory containing the k8s.io directory -func RootDir() (string, error) { - // Get the directory of the current executable - _, testExec, _, _ := runtime.Caller(0) - path := filepath.Dir(testExec) - - // Look for the kubernetes source root directory - if strings.Contains(path, "k8s.io/kubernetes") { - splitPath := strings.Split(path, "k8s.io/kubernetes") - return splitPath[0], nil - } - - return "", fmt.Errorf("Could not find kubernetes source root directory.") -} - -func GetK8sBuildOutputDir() (string, error) { - k8sRoot, err := GetK8sRootDir() - if err != nil { - return "", err - } - buildOutputDir := filepath.Join(k8sRoot, "_output/local/go/bin") - if _, err := os.Stat(buildOutputDir); err != nil { - return "", err - } - return buildOutputDir, nil + return "", fmt.Errorf("unable to locate %s, Can be defined using --k8s-path", bin) } func GetKubeletServerBin() string { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/conformance/run_test.sh b/vendor/k8s.io/kubernetes/test/e2e_node/conformance/run_test.sh index 6ddb24788..3e27859ae 100755 --- a/vendor/k8s.io/kubernetes/test/e2e_node/conformance/run_test.sh +++ b/vendor/k8s.io/kubernetes/test/e2e_node/conformance/run_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/container_manager_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/container_manager_test.go index 71a011045..789a954fe 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/container_manager_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/container_manager_test.go @@ -75,7 +75,7 @@ func validateOOMScoreAdjSettingIsInRange(pid int, expectedMinOOMScoreAdj, expect var _ = framework.KubeDescribe("Container Manager Misc [Serial]", func() { f := framework.NewDefaultFramework("kubelet-container-manager") - Describe("Validate OOM score adjustments", func() { + Describe("Validate OOM score adjustments [NodeFeature:OOMScoreAdj]", func() { Context("once the node is setup", func() { It("container runtime's oom-score-adj should be -999", func() { runtimePids, err := getPidsForProcess(framework.TestContext.ContainerRuntimeProcessName, framework.TestContext.ContainerRuntimePidFile) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/cpu_manager_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/cpu_manager_test.go index dddd9f7cf..36bf6f5bf 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/cpu_manager_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/cpu_manager_test.go @@ -152,9 +152,6 @@ func setOldKubeletConfig(f *framework.Framework, oldCfg *kubeletconfig.KubeletCo } func enableCPUManagerInKubelet(f *framework.Framework) (oldCfg *kubeletconfig.KubeletConfiguration) { - // Run only if the container runtime is not docker or remote (not rkt). - framework.RunIfContainerRuntimeIs("docker", "remote") - // Enable CPU Manager in Kubelet with static policy. oldCfg, err := getCurrentKubeletConfig() framework.ExpectNoError(err) @@ -441,7 +438,7 @@ func runCPUManagerTests(f *framework.Framework) { } // Serial because the test updates kubelet configuration. -var _ = SIGDescribe("CPU Manager [Serial] [Feature:CPUManager]", func() { +var _ = SIGDescribe("CPU Manager [Serial] [Feature:CPUManager][NodeAlphaFeature:CPUManager]", func() { f := framework.NewDefaultFramework("cpu-manager-test") Context("With kubeconfig updated with static CPU Manager policy run the CPU Manager tests", func() { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/critical_pod_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/critical_pod_test.go index e4e4e580d..3ed2924d5 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/critical_pod_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/critical_pod_test.go @@ -40,7 +40,7 @@ const ( bestEffortPodName = "best-effort" ) -var _ = framework.KubeDescribe("CriticalPod [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("CriticalPod [Serial] [Disruptive] [NodeFeature:CriticalPod]", func() { f := framework.NewDefaultFramework("critical-pod-test") Context("when we need to admit a critical pod", func() { @@ -131,7 +131,7 @@ func getTestPod(critical bool, name string, resources v1.ResourceRequirements) * Containers: []v1.Container{ { Name: "container", - Image: imageutils.GetPauseImageNameForHostArch(), + Image: imageutils.GetPauseImageName(), Resources: resources, }, }, diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/density_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/density_test.go index 592a5f86b..ea4a72998 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/density_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/density_test.go @@ -154,7 +154,7 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() { for _, testArg := range dTests { itArg := testArg - desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval [Benchmark]", itArg.podsNr, itArg.interval) + desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval [Benchmark][NodeSpecialFeature:Benchmark]", itArg.podsNr, itArg.interval) It(desc, func() { itArg.createMethod = "batch" testInfo := getTestNodeInfo(f, itArg.getTestName(), desc) @@ -192,7 +192,7 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() { for _, testArg := range dTests { itArg := testArg Context("", func() { - desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval (QPS %d) [Benchmark]", itArg.podsNr, itArg.interval, itArg.APIQPSLimit) + desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval (QPS %d) [Benchmark][NodeSpecialFeature:Benchmark]", itArg.podsNr, itArg.interval, itArg.APIQPSLimit) // The latency caused by API QPS limit takes a large portion (up to ~33%) of e2e latency. // It makes the pod startup latency of Kubelet (creation throughput as well) under-estimated. // Here we set API QPS limit from default 5 to 60 in order to test real Kubelet performance. @@ -273,7 +273,7 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() { for _, testArg := range dTests { itArg := testArg - desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %d background pods [Benchmark]", itArg.podsNr, itArg.bgPodsNr) + desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %d background pods [Benchmark][NodeSpeicalFeature:Benchmark]", itArg.podsNr, itArg.bgPodsNr) It(desc, func() { itArg.createMethod = "sequence" testInfo := getTestNodeInfo(f, itArg.getTestName(), desc) @@ -332,7 +332,7 @@ func runDensityBatchTest(f *framework.Framework, rc *ResourceCollector, testArg ) // create test pod data structure - pods := newTestPods(testArg.podsNr, true, imageutils.GetPauseImageNameForHostArch(), podType) + pods := newTestPods(testArg.podsNr, true, imageutils.GetPauseImageName(), podType) // the controller watches the change of pod status controller := newInformerWatchPod(f, mutex, watchTimes, podType) @@ -413,8 +413,8 @@ func runDensitySeqTest(f *framework.Framework, rc *ResourceCollector, testArg de podType = "density_test_pod" sleepBeforeCreatePods = 30 * time.Second ) - bgPods := newTestPods(testArg.bgPodsNr, true, imageutils.GetPauseImageNameForHostArch(), "background_pod") - testPods := newTestPods(testArg.podsNr, true, imageutils.GetPauseImageNameForHostArch(), podType) + bgPods := newTestPods(testArg.bgPodsNr, true, imageutils.GetPauseImageName(), "background_pod") + testPods := newTestPods(testArg.podsNr, true, imageutils.GetPauseImageName(), podType) By("Creating a batch of background pods") @@ -472,21 +472,6 @@ func getPodStartLatency(node string) (framework.KubeletLatencyMetrics, error) { return latencyMetrics, nil } -// verifyPodStartupLatency verifies whether 50, 90 and 99th percentiles of PodStartupLatency are -// within the threshold. -func verifyPodStartupLatency(expect, actual framework.LatencyMetric) error { - if actual.Perc50 > expect.Perc50 { - return fmt.Errorf("too high pod startup latency 50th percentile: %v", actual.Perc50) - } - if actual.Perc90 > expect.Perc90 { - return fmt.Errorf("too high pod startup latency 90th percentile: %v", actual.Perc90) - } - if actual.Perc99 > expect.Perc99 { - return fmt.Errorf("too high pod startup latency 99th percentile: %v", actual.Perc99) - } - return nil -} - // newInformerWatchPod creates an informer to check whether all pods are running. func newInformerWatchPod(f *framework.Framework, mutex *sync.Mutex, watchTimes map[string]metav1.Time, podType string) cache.Controller { ns := f.Namespace.Name @@ -556,14 +541,14 @@ func logAndVerifyLatency(batchLag time.Duration, e2eLags []framework.PodLatencyD latencyMetrics, _ := getPodStartLatency(kubeletAddr) framework.Logf("Kubelet Prometheus metrics (not reset):\n%s", framework.PrettyPrintJSON(latencyMetrics)) - podCreateLatency := framework.PodStartupLatency{Latency: framework.ExtractLatencyMetrics(e2eLags)} + podStartupLatency := framework.ExtractLatencyMetrics(e2eLags) // log latency perf data - logPerfData(getLatencyPerfData(podCreateLatency.Latency, testInfo), "latency") + logPerfData(getLatencyPerfData(podStartupLatency, testInfo), "latency") if isVerify { // check whether e2e pod startup time is acceptable. - framework.ExpectNoError(verifyPodStartupLatency(podStartupLimits, podCreateLatency.Latency)) + framework.ExpectNoError(framework.VerifyLatencyWithinThreshold(podStartupLimits, podStartupLatency, "pod startup")) // check bactch pod creation latency if podBatchStartupLimit > 0 { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/device_plugin.go b/vendor/k8s.io/kubernetes/test/e2e_node/device_plugin.go index e77e25cdc..3f03a851a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/device_plugin.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/device_plugin.go @@ -44,7 +44,7 @@ const ( ) // Serial because the test restarts Kubelet -var _ = framework.KubeDescribe("Device Plugin [Feature:DevicePlugin] [Serial]", func() { +var _ = framework.KubeDescribe("Device Plugin [Feature:DevicePlugin][NodeFeature:DevicePlugin][Serial]", func() { f := framework.NewDefaultFramework("device-plugin-errors") Context("DevicePlugin", func() { @@ -69,33 +69,41 @@ var _ = framework.KubeDescribe("Device Plugin [Feature:DevicePlugin] [Serial]", By("Waiting for the resource exported by the stub device plugin to become available on the local node") devsLen := int64(len(devs)) - Eventually(func() int64 { + Eventually(func() bool { node, err := f.ClientSet.CoreV1().Nodes().Get(framework.TestContext.NodeName, metav1.GetOptions{}) framework.ExpectNoError(err) - return numberOfDevices(node, resourceName) - }, 30*time.Second, framework.Poll).Should(Equal(devsLen)) + return numberOfDevicesCapacity(node, resourceName) == devsLen && + numberOfDevicesAllocatable(node, resourceName) == devsLen + }, 30*time.Second, framework.Poll).Should(BeTrue()) By("Creating one pod on node with at least one fake-device") podRECMD := "devs=$(ls /tmp/ | egrep '^Dev-[0-9]+$') && echo stub devices: $devs" pod1 := f.PodClient().CreateSync(makeBusyboxPod(resourceName, podRECMD)) deviceIDRE := "stub devices: (Dev-[0-9]+)" - count1, devId1 := parseLogFromNRuns(f, pod1.Name, pod1.Name, 0, deviceIDRE) + devId1 := parseLog(f, pod1.Name, pod1.Name, deviceIDRE) Expect(devId1).To(Not(Equal(""))) pod1, err = f.PodClient().Get(pod1.Name, metav1.GetOptions{}) framework.ExpectNoError(err) - By("Restarting Kubelet and waiting for the current running pod to restart") + ensurePodContainerRestart(f, pod1.Name, pod1.Name) + + By("Confirming that device assignment persists even after container restart") + devIdAfterRestart := parseLog(f, pod1.Name, pod1.Name, deviceIDRE) + Expect(devIdAfterRestart).To(Equal(devId1)) + + By("Restarting Kubelet") restartKubelet() - By("Confirming that after a kubelet and pod restart, fake-device assignement is kept") - count1, devIdRestart1 := parseLogFromNRuns(f, pod1.Name, pod1.Name, count1+1, deviceIDRE) + ensurePodContainerRestart(f, pod1.Name, pod1.Name) + By("Confirming that after a kubelet restart, fake-device assignement is kept") + devIdRestart1 := parseLog(f, pod1.Name, pod1.Name, deviceIDRE) Expect(devIdRestart1).To(Equal(devId1)) By("Wait for node is ready") framework.WaitForAllNodesSchedulable(f.ClientSet, framework.TestContext.NodeSchedulableTimeout) - By("Re-Register resources") + By("Re-Register resources after kubelet restart") dp1 = dm.NewDevicePluginStub(devs, socketPath) dp1.SetAllocFunc(stubAllocFunc) err = dp1.Start() @@ -105,17 +113,18 @@ var _ = framework.KubeDescribe("Device Plugin [Feature:DevicePlugin] [Serial]", framework.ExpectNoError(err) By("Waiting for resource to become available on the local node after re-registration") - Eventually(func() int64 { + Eventually(func() bool { node, err := f.ClientSet.CoreV1().Nodes().Get(framework.TestContext.NodeName, metav1.GetOptions{}) framework.ExpectNoError(err) - return numberOfDevices(node, resourceName) - }, 30*time.Second, framework.Poll).Should(Equal(devsLen)) + return numberOfDevicesCapacity(node, resourceName) == devsLen && + numberOfDevicesAllocatable(node, resourceName) == devsLen + }, 30*time.Second, framework.Poll).Should(BeTrue()) By("Creating another pod") pod2 := f.PodClient().CreateSync(makeBusyboxPod(resourceName, podRECMD)) - By("Checking that pods got a different GPU") - count2, devId2 := parseLogFromNRuns(f, pod2.Name, pod2.Name, 1, deviceIDRE) + By("Checking that pod got a different fake device") + devId2 := parseLog(f, pod2.Name, pod2.Name, deviceIDRE) Expect(devId1).To(Not(Equal(devId2))) @@ -123,26 +132,59 @@ var _ = framework.KubeDescribe("Device Plugin [Feature:DevicePlugin] [Serial]", err = dp1.Stop() framework.ExpectNoError(err) - By("Waiting for stub device plugin to become unavailable on the local node") - Eventually(func() bool { + By("Waiting for stub device plugin to become unhealthy on the local node") + Eventually(func() int64 { node, err := f.ClientSet.CoreV1().Nodes().Get(framework.TestContext.NodeName, metav1.GetOptions{}) framework.ExpectNoError(err) - return numberOfDevices(node, resourceName) <= 0 - }, 10*time.Minute, framework.Poll).Should(BeTrue()) + return numberOfDevicesAllocatable(node, resourceName) + }, 30*time.Second, framework.Poll).Should(Equal(int64(0))) By("Checking that scheduled pods can continue to run even after we delete device plugin.") - count1, devIdRestart1 = parseLogFromNRuns(f, pod1.Name, pod1.Name, count1+1, deviceIDRE) + ensurePodContainerRestart(f, pod1.Name, pod1.Name) + devIdRestart1 = parseLog(f, pod1.Name, pod1.Name, deviceIDRE) Expect(devIdRestart1).To(Equal(devId1)) - count2, devIdRestart2 := parseLogFromNRuns(f, pod2.Name, pod2.Name, count2+1, deviceIDRE) + + ensurePodContainerRestart(f, pod2.Name, pod2.Name) + devIdRestart2 := parseLog(f, pod2.Name, pod2.Name, deviceIDRE) Expect(devIdRestart2).To(Equal(devId2)) - By("Restarting Kubelet.") + By("Re-register resources") + dp1 = dm.NewDevicePluginStub(devs, socketPath) + dp1.SetAllocFunc(stubAllocFunc) + err = dp1.Start() + framework.ExpectNoError(err) + + err = dp1.Register(pluginapi.KubeletSocket, resourceName, false) + framework.ExpectNoError(err) + + By("Waiting for the resource exported by the stub device plugin to become healthy on the local node") + Eventually(func() int64 { + node, err := f.ClientSet.CoreV1().Nodes().Get(framework.TestContext.NodeName, metav1.GetOptions{}) + framework.ExpectNoError(err) + return numberOfDevicesAllocatable(node, resourceName) + }, 30*time.Second, framework.Poll).Should(Equal(devsLen)) + + By("Deleting device plugin again.") + err = dp1.Stop() + framework.ExpectNoError(err) + + By("Waiting for stub device plugin to become unavailable on the local node") + Eventually(func() bool { + node, err := f.ClientSet.CoreV1().Nodes().Get(framework.TestContext.NodeName, metav1.GetOptions{}) + framework.ExpectNoError(err) + return numberOfDevicesCapacity(node, resourceName) <= 0 + }, 10*time.Minute, framework.Poll).Should(BeTrue()) + + By("Restarting Kubelet second time.") restartKubelet() - By("Checking that scheduled pods can continue to run even after we delete device plugin and restart Kubelet.") - count1, devIdRestart1 = parseLogFromNRuns(f, pod1.Name, pod1.Name, count1+2, deviceIDRE) + By("Checking that scheduled pods can continue to run even after we delete device plugin and restart Kubelet Eventually.") + ensurePodContainerRestart(f, pod1.Name, pod1.Name) + devIdRestart1 = parseLog(f, pod1.Name, pod1.Name, deviceIDRE) Expect(devIdRestart1).To(Equal(devId1)) - count2, devIdRestart2 = parseLogFromNRuns(f, pod2.Name, pod2.Name, count2+2, deviceIDRE) + + ensurePodContainerRestart(f, pod2.Name, pod2.Name) + devIdRestart2 = parseLog(f, pod2.Name, pod2.Name, deviceIDRE) Expect(devIdRestart2).To(Equal(devId2)) // Cleanup @@ -176,21 +218,28 @@ func makeBusyboxPod(resourceName, cmd string) *v1.Pod { } } -// parseLogFromNRuns returns restart count of the specified container -// after it has been restarted at least restartCount times, -// and the matching string for the specified regular expression parsed from the container logs. -func parseLogFromNRuns(f *framework.Framework, podName string, contName string, restartCount int32, re string) (int32, string) { - var count int32 - // Wait till pod has been restarted at least restartCount times. +// ensurePodContainerRestart confirms that pod container has restarted at least once +func ensurePodContainerRestart(f *framework.Framework, podName string, contName string) { + var initialCount int32 + var currentCount int32 + p, err := f.PodClient().Get(podName, metav1.GetOptions{}) + if err != nil || len(p.Status.ContainerStatuses) < 1 { + framework.Failf("ensurePodContainerRestart failed for pod %q: %v", podName, err) + } + initialCount = p.Status.ContainerStatuses[0].RestartCount Eventually(func() bool { - p, err := f.PodClient().Get(podName, metav1.GetOptions{}) + p, err = f.PodClient().Get(podName, metav1.GetOptions{}) if err != nil || len(p.Status.ContainerStatuses) < 1 { return false } - count = p.Status.ContainerStatuses[0].RestartCount - return count >= restartCount - }, 5*time.Minute, framework.Poll).Should(BeTrue()) + currentCount = p.Status.ContainerStatuses[0].RestartCount + framework.Logf("initial %v, current %v", initialCount, currentCount) + return currentCount > initialCount + }, 2*time.Minute, framework.Poll).Should(BeTrue()) +} +// parseLog returns the matching string for the specified regular expression parsed from the container logs. +func parseLog(f *framework.Framework, podName string, contName string, re string) string { logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, podName, contName) if err != nil { framework.Failf("GetPodLogs for pod %q failed: %v", podName, err) @@ -200,14 +249,14 @@ func parseLogFromNRuns(f *framework.Framework, podName string, contName string, regex := regexp.MustCompile(re) matches := regex.FindStringSubmatch(logs) if len(matches) < 2 { - return count, "" + return "" } - return count, matches[1] + return matches[1] } -// numberOfDevices returns the number of devices of resourceName advertised by a node -func numberOfDevices(node *v1.Node, resourceName string) int64 { +// numberOfDevicesCapacity returns the number of devices of resourceName advertised by a node capacity +func numberOfDevicesCapacity(node *v1.Node, resourceName string) int64 { val, ok := node.Status.Capacity[v1.ResourceName(resourceName)] if !ok { return 0 @@ -216,6 +265,16 @@ func numberOfDevices(node *v1.Node, resourceName string) int64 { return val.Value() } +// numberOfDevicesAllocatable returns the number of devices of resourceName advertised by a node allocatable +func numberOfDevicesAllocatable(node *v1.Node, resourceName string) int64 { + val, ok := node.Status.Allocatable[v1.ResourceName(resourceName)] + if !ok { + return 0 + } + + return val.Value() +} + // stubAllocFunc will pass to stub device plugin func stubAllocFunc(r *pluginapi.AllocateRequest, devs map[string]pluginapi.Device) (*pluginapi.AllocateResponse, error) { var responses pluginapi.AllocateResponse diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/docker_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/docker_test.go index 97dae3e99..8a361c65d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/docker_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/docker_test.go @@ -30,7 +30,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = framework.KubeDescribe("Docker features [Feature:Docker]", func() { +var _ = framework.KubeDescribe("Docker features [Feature:Docker][Legacy:Docker]", func() { f := framework.NewDefaultFramework("docker-feature-test") BeforeEach(func() { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/dockershim_checkpoint_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/dockershim_checkpoint_test.go index c64191cd2..e06ad64c7 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/dockershim_checkpoint_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/dockershim_checkpoint_test.go @@ -33,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/test/e2e/framework" + imageutils "k8s.io/kubernetes/test/utils/image" ) const ( @@ -42,7 +43,7 @@ const ( testCheckpointContent = `{"version":"v1","name":"fluentd-gcp-v2.0-vmnqx","namespace":"kube-system","data":{},"checksum":1799154314}` ) -var _ = SIGDescribe("Dockershim [Serial] [Disruptive] [Feature:Docker]", func() { +var _ = SIGDescribe("Dockershim [Serial] [Disruptive] [Feature:Docker][Legacy:Docker]", func() { f := framework.NewDefaultFramework("dockerhism-checkpoint-test") BeforeEach(func() { @@ -155,7 +156,7 @@ func runPodCheckpointTest(f *framework.Framework, podName string, twist func()) Spec: v1.PodSpec{ Containers: []v1.Container{ { - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Name: "pause-container", }, }, diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/dynamic_kubelet_config_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/dynamic_kubelet_config_test.go index e852059dc..b30fbccb1 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/dynamic_kubelet_config_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/dynamic_kubelet_config_test.go @@ -19,27 +19,48 @@ package e2e_node import ( "fmt" "reflect" + "strings" "time" "github.com/davecgh/go-spew/spew" apiv1 "k8s.io/api/core/v1" + apiequality "k8s.io/apimachinery/pkg/api/equality" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" controller "k8s.io/kubernetes/pkg/kubelet/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status" + "k8s.io/kubernetes/pkg/kubelet/metrics" + frameworkmetrics "k8s.io/kubernetes/test/e2e/framework/metrics" "k8s.io/kubernetes/test/e2e/framework" + "github.com/prometheus/common/model" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) -type configState struct { - desc string - configSource *apiv1.NodeConfigSource - expectConfigOk *apiv1.NodeCondition - expectConfig *kubeletconfig.KubeletConfiguration +const itDescription = "status and events should match expectations" + +type expectNodeConfigStatus struct { + lastKnownGood *apiv1.NodeConfigSource + err string + // If true, expect Status.Config.Active == Status.Config.LastKnownGood, + // otherwise expect Status.Config.Active == Status.Config.Assigned. + lkgActive bool +} + +type nodeConfigTestCase struct { + desc string + configSource *apiv1.NodeConfigSource + configMap *apiv1.ConfigMap + expectConfigStatus expectNodeConfigStatus + expectConfig *kubeletconfig.KubeletConfiguration + // whether to expect this substring in an error returned from the API server when updating the config source + apierr string // whether the state would cause a config change event as a result of the update to Node.Spec.ConfigSource, // assuming that the current source would have also caused a config change event. // for example, some malformed references may result in a download failure, in which case the Kubelet @@ -48,55 +69,77 @@ type configState struct { } // This test is marked [Disruptive] because the Kubelet restarts several times during this test. -var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKubeletConfig] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("[Feature:DynamicKubeletConfig][NodeFeature:DynamicKubeletConfig][Serial][Disruptive]", func() { f := framework.NewDefaultFramework("dynamic-kubelet-configuration-test") - var originalKC *kubeletconfig.KubeletConfiguration - var originalConfigMap *apiv1.ConfigMap + var beforeNode *apiv1.Node + var beforeConfigMap *apiv1.ConfigMap + var beforeKC *kubeletconfig.KubeletConfiguration + var localKC *kubeletconfig.KubeletConfiguration // Dummy context to prevent framework's AfterEach from cleaning up before this test's AfterEach can run Context("", func() { BeforeEach(func() { - var err error - if originalConfigMap == nil { - originalKC, err = getCurrentKubeletConfig() - framework.ExpectNoError(err) - originalConfigMap = newKubeletConfigMap("original-values", originalKC) - originalConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(originalConfigMap) - framework.ExpectNoError(err) - } // make sure Dynamic Kubelet Configuration feature is enabled on the Kubelet we are about to test enabled, err := isKubeletConfigEnabled(f) framework.ExpectNoError(err) if !enabled { framework.ExpectNoError(fmt.Errorf("The Dynamic Kubelet Configuration feature is not enabled.\n" + - "Pass --feature-gates=DynamicKubeletConfig=true to the Kubelet to enable this feature.\n" + + "Pass --feature-gates=DynamicKubeletConfig=true to the Kubelet and API server to enable this feature.\n" + "For `make test-e2e-node`, you can set `TEST_ARGS='--feature-gates=DynamicKubeletConfig=true'`.")) } + // record before state so we can restore it after the test + if beforeNode == nil { + node, err := f.ClientSet.CoreV1().Nodes().Get(framework.TestContext.NodeName, metav1.GetOptions{}) + framework.ExpectNoError(err) + beforeNode = node + } + if source := beforeNode.Spec.ConfigSource; source != nil { + if source.ConfigMap != nil { + cm, err := f.ClientSet.CoreV1().ConfigMaps(source.ConfigMap.Namespace).Get(source.ConfigMap.Name, metav1.GetOptions{}) + framework.ExpectNoError(err) + beforeConfigMap = cm + } + } + if beforeKC == nil { + kc, err := getCurrentKubeletConfig() + framework.ExpectNoError(err) + beforeKC = kc + } + // reset the node's assigned/active/last-known-good config by setting the source to nil, + // so each test starts from a clean-slate + (&nodeConfigTestCase{ + desc: "reset via nil config source", + configSource: nil, + }).run(f, setConfigSourceFunc, false, 0) + // record local KC so we can check it during tests that roll back to nil last-known-good + if localKC == nil { + kc, err := getCurrentKubeletConfig() + framework.ExpectNoError(err) + localKC = kc + } }) AfterEach(func() { - // Set the config back to the original values before moving on. - // We care that the values are the same, not where they come from, so it - // should be fine to reset the values using a remote config, even if they - // were initially set via the locally provisioned configuration. - // This is the same strategy several other e2e node tests use. - setAndTestKubeletConfigState(f, &configState{desc: "reset to original values", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - UID: originalConfigMap.UID, - Namespace: originalConfigMap.Namespace, - Name: originalConfigMap.Name}}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue, - Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(originalConfigMap)), - Reason: status.CurRemoteOkayReason}, - expectConfig: originalKC, - }, false) + // clean-slate the Node again (prevents last-known-good from any tests from leaking through) + (&nodeConfigTestCase{ + desc: "reset via nil config source", + configSource: nil, + }).run(f, setConfigSourceFunc, false, 0) + // restore the values from before the test before moving on + restore := &nodeConfigTestCase{ + desc: "restore values from before test", + configSource: beforeNode.Spec.ConfigSource, + configMap: beforeConfigMap, + expectConfig: beforeKC, + } + restore.run(f, setConfigSourceFunc, false, 0) }) - Context("When setting new NodeConfigSources that cause transitions between ConfigOk conditions", func() { - It("the Kubelet should report the appropriate status and configz", func() { + Context("update Node.Spec.ConfigSource: state transitions:", func() { + It(itDescription, func() { var err error - // we base the "correct" configmap off of the current configuration - correctKC := originalKC.DeepCopy() + // we base the "correct" configmap off of the configuration from before the test + correctKC := beforeKC.DeepCopy() correctConfigMap := newKubeletConfigMap("dynamic-kubelet-config-test-correct", correctKC) correctConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(correctConfigMap) framework.ExpectNoError(err) @@ -111,113 +154,157 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube failParseConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(failParseConfigMap) framework.ExpectNoError(err) - // fail to validate, we make a copy and set an invalid KubeAPIQPS on kc before serializing + // fail to validate, we make a copy of correct and set an invalid KubeAPIQPS on kc before serializing invalidKC := correctKC.DeepCopy() - invalidKC.KubeAPIQPS = -1 failValidateConfigMap := newKubeletConfigMap("dynamic-kubelet-config-test-fail-validate", invalidKC) failValidateConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(failValidateConfigMap) framework.ExpectNoError(err) - states := []configState{ - // Node.Spec.ConfigSource is nil - {desc: "Node.Spec.ConfigSource is nil", - configSource: nil, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue, - Message: status.CurLocalMessage, - Reason: status.CurLocalOkayReason}, - expectConfig: nil, - event: true, - }, + correctSource := &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: correctConfigMap.Namespace, + Name: correctConfigMap.Name, + KubeletConfigKey: "kubelet", + }} + failParseSource := &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: failParseConfigMap.Namespace, + Name: failParseConfigMap.Name, + KubeletConfigKey: "kubelet", + }} + failValidateSource := &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: failValidateConfigMap.Namespace, + Name: failValidateConfigMap.Name, + KubeletConfigKey: "kubelet", + }} - // Node.Spec.ConfigSource has all nil subfields - {desc: "Node.Spec.ConfigSource has all nil subfields", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: nil}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse, - Message: "", - Reason: fmt.Sprintf(status.FailSyncReasonFmt, status.FailSyncReasonAllNilSubfields)}, - expectConfig: nil, - event: false, - }, - - // Node.Spec.ConfigSource.ConfigMapRef is partial - {desc: "Node.Spec.ConfigSource.ConfigMapRef is partial", - // TODO(mtaufen): check the other 7 partials in a unit test - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - UID: "foo", - Name: "bar"}}, // missing Namespace - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse, - Message: "", - Reason: fmt.Sprintf(status.FailSyncReasonFmt, status.FailSyncReasonPartialObjectReference)}, - expectConfig: nil, - event: false, - }, - - // Node.Spec.ConfigSource's UID does not align with namespace/name - {desc: "Node.Spec.ConfigSource.ConfigMapRef.UID does not align with Namespace/Name", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{UID: "foo", - Namespace: correctConfigMap.Namespace, - Name: correctConfigMap.Name}}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse, - Message: "", - Reason: fmt.Sprintf(status.FailSyncReasonFmt, fmt.Sprintf(status.FailSyncReasonUIDMismatchFmt, "foo", configMapAPIPath(correctConfigMap), correctConfigMap.UID))}, - expectConfig: nil, - event: false, - }, - - // correct - {desc: "correct", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - UID: correctConfigMap.UID, - Namespace: correctConfigMap.Namespace, - Name: correctConfigMap.Name}}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue, - Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(correctConfigMap)), - Reason: status.CurRemoteOkayReason}, + cases := []nodeConfigTestCase{ + { + desc: "Node.Spec.ConfigSource is nil", + configSource: nil, + expectConfigStatus: expectNodeConfigStatus{}, + expectConfig: nil, + event: true, + }, + { + desc: "Node.Spec.ConfigSource has all nil subfields", + configSource: &apiv1.NodeConfigSource{}, + apierr: "exactly one reference subfield must be non-nil", + }, + { + desc: "Node.Spec.ConfigSource.ConfigMap is missing namespace", + configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "bar", + KubeletConfigKey: "kubelet", + }}, // missing Namespace + apierr: "spec.configSource.configMap.namespace: Required value: namespace must be set", + }, + { + desc: "Node.Spec.ConfigSource.ConfigMap is missing name", + configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: "foo", + KubeletConfigKey: "kubelet", + }}, // missing Name + apierr: "spec.configSource.configMap.name: Required value: name must be set", + }, + { + desc: "Node.Spec.ConfigSource.ConfigMap is missing kubeletConfigKey", + configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: "foo", + Name: "bar", + }}, // missing KubeletConfigKey + apierr: "spec.configSource.configMap.kubeletConfigKey: Required value: kubeletConfigKey must be set", + }, + { + desc: "Node.Spec.ConfigSource.ConfigMap.UID is illegally specified", + configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + UID: "foo", + Name: "bar", + Namespace: "baz", + KubeletConfigKey: "kubelet", + }}, + apierr: "spec.configSource.configMap.uid: Forbidden: uid must not be set in spec", + }, + { + desc: "Node.Spec.ConfigSource.ConfigMap.ResourceVersion is illegally specified", + configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "bar", + Namespace: "baz", + ResourceVersion: "1", + KubeletConfigKey: "kubelet", + }}, + apierr: "spec.configSource.configMap.resourceVersion: Forbidden: resourceVersion must not be set in spec", + }, + { + desc: "Node.Spec.ConfigSource.ConfigMap has invalid namespace", + configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "bar", + Namespace: "../baz", + KubeletConfigKey: "kubelet", + }}, + apierr: "spec.configSource.configMap.namespace: Invalid value", + }, + { + desc: "Node.Spec.ConfigSource.ConfigMap has invalid name", + configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "../bar", + Namespace: "baz", + KubeletConfigKey: "kubelet", + }}, + apierr: "spec.configSource.configMap.name: Invalid value", + }, + { + desc: "Node.Spec.ConfigSource.ConfigMap has invalid kubeletConfigKey", + configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Name: "bar", + Namespace: "baz", + KubeletConfigKey: "../qux", + }}, + apierr: "spec.configSource.configMap.kubeletConfigKey: Invalid value", + }, + { + desc: "correct", + configSource: correctSource, + configMap: correctConfigMap, expectConfig: correctKC, event: true, }, - - // fail-parse - {desc: "fail-parse", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - UID: failParseConfigMap.UID, - Namespace: failParseConfigMap.Namespace, - Name: failParseConfigMap.Name}}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse, - Message: status.LkgLocalMessage, - Reason: fmt.Sprintf(status.CurFailParseReasonFmt, configMapAPIPath(failParseConfigMap))}, - expectConfig: nil, + { + desc: "fail-parse", + configSource: failParseSource, + configMap: failParseConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + err: status.LoadError, + lkgActive: true, + }, + expectConfig: localKC, event: true, }, - - // fail-validate - {desc: "fail-validate", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - UID: failValidateConfigMap.UID, - Namespace: failValidateConfigMap.Namespace, - Name: failValidateConfigMap.Name}}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse, - Message: status.LkgLocalMessage, - Reason: fmt.Sprintf(status.CurFailValidateReasonFmt, configMapAPIPath(failValidateConfigMap))}, - expectConfig: nil, + { + desc: "fail-validate", + configSource: failValidateSource, + configMap: failValidateConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + err: status.ValidateError, + lkgActive: true, + }, + expectConfig: localKC, event: true, }, } - L := len(states) - for i := 1; i <= L; i++ { // need one less iteration than the number of states - testBothDirections(f, &states[i-1 : i][0], states[i:L], 0) + L := len(cases) + for i := 1; i <= L; i++ { // need one less iteration than the number of cases + testBothDirections(f, setConfigSourceFunc, &cases[i-1 : i][0], cases[i:L], 0) } }) }) - Context("When a remote config becomes the new last-known-good, and then the Kubelet is updated to use a new, bad config", func() { - It("the Kubelet should report a status and configz indicating that it rolled back to the new last-known-good", func() { + Context("update Node.Spec.ConfigSource: recover to last-known-good ConfigMap:", func() { + It(itDescription, func() { var err error - // we base the "lkg" configmap off of the current configuration - lkgKC := originalKC.DeepCopy() + // we base the "lkg" configmap off of the configuration from before the test + lkgKC := beforeKC.DeepCopy() lkgConfigMap := newKubeletConfigMap("dynamic-kubelet-config-test-intended-lkg", lkgKC) lkgConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(lkgConfigMap) framework.ExpectNoError(err) @@ -232,47 +319,112 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube badConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(badConfigMap) framework.ExpectNoError(err) - states := []configState{ - // intended lkg - {desc: "intended last-known-good", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - UID: lkgConfigMap.UID, - Namespace: lkgConfigMap.Namespace, - Name: lkgConfigMap.Name}}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue, - Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(lkgConfigMap)), - Reason: status.CurRemoteOkayReason}, + lkgSource := &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: lkgConfigMap.Namespace, + Name: lkgConfigMap.Name, + KubeletConfigKey: "kubelet", + }} + lkgStatus := lkgSource.DeepCopy() + lkgStatus.ConfigMap.UID = lkgConfigMap.UID + lkgStatus.ConfigMap.ResourceVersion = lkgConfigMap.ResourceVersion + + badSource := &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: badConfigMap.Namespace, + Name: badConfigMap.Name, + KubeletConfigKey: "kubelet", + }} + + cases := []nodeConfigTestCase{ + { + desc: "intended last-known-good", + configSource: lkgSource, + configMap: lkgConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + lastKnownGood: lkgStatus, + }, + expectConfig: lkgKC, + event: true, + }, + { + desc: "bad config", + configSource: badSource, + configMap: badConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + lastKnownGood: lkgStatus, + err: status.LoadError, + lkgActive: true, + }, expectConfig: lkgKC, event: true, }, + } + + // wait 12 minutes after setting the first config to ensure it has time to pass the trial duration + testBothDirections(f, setConfigSourceFunc, &cases[0], cases[1:], 12*time.Minute) + }) + }) + + Context("update Node.Spec.ConfigSource: recover to last-known-good ConfigMap.KubeletConfigKey:", func() { + It(itDescription, func() { + const badConfigKey = "bad" + var err error + // we base the "lkg" configmap off of the configuration from before the test + lkgKC := beforeKC.DeepCopy() + combinedConfigMap := newKubeletConfigMap("dynamic-kubelet-config-test-combined", lkgKC) + combinedConfigMap.Data[badConfigKey] = "{0xdeadbeef}" + combinedConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(combinedConfigMap) + framework.ExpectNoError(err) + + lkgSource := &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: combinedConfigMap.Namespace, + Name: combinedConfigMap.Name, + KubeletConfigKey: "kubelet", + }} + + lkgStatus := lkgSource.DeepCopy() + lkgStatus.ConfigMap.UID = combinedConfigMap.UID + lkgStatus.ConfigMap.ResourceVersion = combinedConfigMap.ResourceVersion + + badSource := lkgSource.DeepCopy() + badSource.ConfigMap.KubeletConfigKey = badConfigKey - // bad config - {desc: "bad config", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - UID: badConfigMap.UID, - Namespace: badConfigMap.Namespace, - Name: badConfigMap.Name}}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse, - Message: fmt.Sprintf(status.LkgRemoteMessageFmt, configMapAPIPath(lkgConfigMap)), - Reason: fmt.Sprintf(status.CurFailParseReasonFmt, configMapAPIPath(badConfigMap))}, + cases := []nodeConfigTestCase{ + { + desc: "intended last-known-good", + configSource: lkgSource, + configMap: combinedConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + lastKnownGood: lkgStatus, + }, + expectConfig: lkgKC, + event: true, + }, + { + desc: "bad config", + configSource: badSource, + configMap: combinedConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + lastKnownGood: lkgStatus, + err: status.LoadError, + lkgActive: true, + }, expectConfig: lkgKC, event: true, }, } // wait 12 minutes after setting the first config to ensure it has time to pass the trial duration - testBothDirections(f, &states[0], states[1:], 12*time.Minute) + testBothDirections(f, setConfigSourceFunc, &cases[0], cases[1:], 12*time.Minute) }) }) - // This stress test will help turn up resource leaks across kubelet restarts that can, over time, - // break our ability to dynamically update kubelet config - Context("When changing the configuration 100 times", func() { - It("the Kubelet should report the appropriate status and configz", func() { + // exposes resource leaks across config changes + Context("update Node.Spec.ConfigSource: 100 update stress test:", func() { + It(itDescription, func() { var err error // we just create two configmaps with the same config but different names and toggle between them - kc1 := originalKC.DeepCopy() + kc1 := beforeKC.DeepCopy() cm1 := newKubeletConfigMap("dynamic-kubelet-config-test-cm1", kc1) cm1, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(cm1) framework.ExpectNoError(err) @@ -284,90 +436,454 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube cm2, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(cm2) framework.ExpectNoError(err) - states := []configState{ - {desc: "cm1", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - UID: cm1.UID, - Namespace: cm1.Namespace, - Name: cm1.Name}}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue, - Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(cm1)), - Reason: status.CurRemoteOkayReason}, + cm1Source := &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: cm1.Namespace, + Name: cm1.Name, + KubeletConfigKey: "kubelet", + }} + + cm2Source := &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: cm2.Namespace, + Name: cm2.Name, + KubeletConfigKey: "kubelet", + }} + + cases := []nodeConfigTestCase{ + { + desc: "cm1", + configSource: cm1Source, + configMap: cm1, expectConfig: kc1, event: true, }, - - {desc: "cm2", - configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ - UID: cm2.UID, - Namespace: cm2.Namespace, - Name: cm2.Name}}, - expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue, - Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(cm2)), - Reason: status.CurRemoteOkayReason}, + { + desc: "cm2", + configSource: cm2Source, + configMap: cm2, expectConfig: kc2, event: true, }, } for i := 0; i < 50; i++ { // change the config 101 times (changes 3 times in the first iteration, 2 times in each subsequent iteration) - testBothDirections(f, &states[0], states[1:], 0) + testBothDirections(f, setConfigSourceFunc, &cases[0], cases[1:], 0) + } + }) + }) + + // Please note: This behavior is tested to ensure implementation correctness. We do not, however, recommend ConfigMap mutations + // as a usage pattern for dynamic Kubelet config in large clusters. It is much safer to create a new ConfigMap, and incrementally + // roll out a new Node.Spec.ConfigSource that references the new ConfigMap. In-place ConfigMap updates, including deletion + // followed by re-creation, will cause all observing Kubelets to immediately restart for new config, because these operations + // change the ResourceVersion of the ConfigMap. + Context("update ConfigMap in-place: state transitions:", func() { + It(itDescription, func() { + var err error + // we base the "correct" configmap off of the configuration from before the test + correctKC := beforeKC.DeepCopy() + correctConfigMap := newKubeletConfigMap("dynamic-kubelet-config-test-in-place", correctKC) + correctConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(correctConfigMap) + framework.ExpectNoError(err) + + // we reuse the same name, namespace + failParseConfigMap := correctConfigMap.DeepCopy() + failParseConfigMap.Data = map[string]string{ + "kubelet": "{0xdeadbeef}", + } + + // fail to validate, we make a copy and set an invalid KubeAPIQPS on kc before serializing + invalidKC := correctKC.DeepCopy() + invalidKC.KubeAPIQPS = -1 + failValidateConfigMap := correctConfigMap.DeepCopy() + failValidateConfigMap.Data = newKubeletConfigMap("", invalidKC).Data + + // ensure node config source is set to the config map we will mutate in-place, + // since updateConfigMapFunc doesn't mutate Node.Spec.ConfigSource + source := &apiv1.NodeConfigSource{ + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: correctConfigMap.Namespace, + Name: correctConfigMap.Name, + KubeletConfigKey: "kubelet", + }, + } + (&nodeConfigTestCase{ + desc: "initial state (correct)", + configSource: source, + configMap: correctConfigMap, + expectConfig: correctKC, + }).run(f, setConfigSourceFunc, false, 0) + + cases := []nodeConfigTestCase{ + { + desc: "correct", + configSource: source, + configMap: correctConfigMap, + expectConfig: correctKC, + event: true, + }, + { + desc: "fail-parse", + configSource: source, + configMap: failParseConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + err: status.LoadError, + lkgActive: true, + }, + expectConfig: localKC, + event: true, + }, + { + desc: "fail-validate", + configSource: source, + configMap: failValidateConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + err: status.ValidateError, + lkgActive: true, + }, + expectConfig: localKC, + event: true, + }, + } + L := len(cases) + for i := 1; i <= L; i++ { // need one less iteration than the number of cases + testBothDirections(f, updateConfigMapFunc, &cases[i-1 : i][0], cases[i:L], 0) + } + }) + }) + + // Please note: This behavior is tested to ensure implementation correctness. We do not, however, recommend ConfigMap mutations + // as a usage pattern for dynamic Kubelet config in large clusters. It is much safer to create a new ConfigMap, and incrementally + // roll out a new Node.Spec.ConfigSource that references the new ConfigMap. In-place ConfigMap updates, including deletion + // followed by re-creation, will cause all observing Kubelets to immediately restart for new config, because these operations + // change the ResourceVersion of the ConfigMap. + Context("update ConfigMap in-place: recover to last-known-good version:", func() { + It(itDescription, func() { + var err error + // we base the "lkg" configmap off of the configuration from before the test + lkgKC := beforeKC.DeepCopy() + lkgConfigMap := newKubeletConfigMap("dynamic-kubelet-config-test-in-place-lkg", lkgKC) + lkgConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(lkgConfigMap) + framework.ExpectNoError(err) + + // bad config map, we insert some bogus stuff into the configMap + badConfigMap := lkgConfigMap.DeepCopy() + badConfigMap.Data = map[string]string{ + "kubelet": "{0xdeadbeef}", + } + // ensure node config source is set to the config map we will mutate in-place + source := &apiv1.NodeConfigSource{ + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: lkgConfigMap.Namespace, + Name: lkgConfigMap.Name, + KubeletConfigKey: "kubelet", + }, + } + + // Even though the first test case will PUT the lkgConfigMap again, no-op writes don't increment + // ResourceVersion, so the expected status we record here will still be correct. + lkgStatus := source.DeepCopy() + lkgStatus.ConfigMap.UID = lkgConfigMap.UID + lkgStatus.ConfigMap.ResourceVersion = lkgConfigMap.ResourceVersion + + (&nodeConfigTestCase{ + desc: "initial state (correct)", + configSource: source, + configMap: lkgConfigMap, + expectConfig: lkgKC, + }).run(f, setConfigSourceFunc, false, 0) // wait 0 here, and we should not expect LastKnownGood to have changed yet (hence nil) + + cases := []nodeConfigTestCase{ + { + desc: "intended last-known-good", + configSource: source, + configMap: lkgConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + lastKnownGood: lkgStatus, + }, + expectConfig: lkgKC, + event: true, + }, + { + // NOTE(mtaufen): If you see a strange "expected assigned x but got assigned y" error on this case, + // it is possible that the Kubelet didn't start the informer that watches the currently assigned + // ConfigMap, or didn't get updates from that informer. Other tests don't always catch this because + // they quickly change config. The sync loop will always happen once, a bit after the Kubelet starts + // up, because other informers' initial "add" events can queue a sync. If you wait long enough before + // changing config (waiting for the config to become last-known-good, for example), the syncs queued by + // add events will have already been processed, and the lack of a running ConfigMap informer will result + // in a missed update, no config change, and the above error when we check the status. + desc: "bad config", + configSource: source, + configMap: badConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + lastKnownGood: lkgStatus, + err: status.LoadError, + lkgActive: true, + }, + expectConfig: lkgKC, + event: true, + }, + } + + // wait 12 minutes after setting the first config to ensure it has time to pass the trial duration + testBothDirections(f, updateConfigMapFunc, &cases[0], cases[1:], 12*time.Minute) + }) + }) + + // Please note: This behavior is tested to ensure implementation correctness. We do not, however, recommend ConfigMap mutations + // as a usage pattern for dynamic Kubelet config in large clusters. It is much safer to create a new ConfigMap, and incrementally + // roll out a new Node.Spec.ConfigSource that references the new ConfigMap. In-place ConfigMap updates, including deletion + // followed by re-creation, will cause all observing Kubelets to immediately restart for new config, because these operations + // change the ResourceVersion of the ConfigMap. + Context("delete and recreate ConfigMap: state transitions:", func() { + It(itDescription, func() { + var err error + // we base the "correct" configmap off of the configuration from before the test + correctKC := beforeKC.DeepCopy() + correctConfigMap := newKubeletConfigMap("dynamic-kubelet-config-test-delete-createe", correctKC) + correctConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(correctConfigMap) + framework.ExpectNoError(err) + + // we reuse the same name, namespace + failParseConfigMap := correctConfigMap.DeepCopy() + failParseConfigMap.Data = map[string]string{ + "kubelet": "{0xdeadbeef}", + } + + // fail to validate, we make a copy and set an invalid KubeAPIQPS on kc before serializing + invalidKC := correctKC.DeepCopy() + invalidKC.KubeAPIQPS = -1 + failValidateConfigMap := correctConfigMap.DeepCopy() + failValidateConfigMap.Data = newKubeletConfigMap("", invalidKC).Data + + // ensure node config source is set to the config map we will mutate in-place, + // since recreateConfigMapFunc doesn't mutate Node.Spec.ConfigSource + source := &apiv1.NodeConfigSource{ + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: correctConfigMap.Namespace, + Name: correctConfigMap.Name, + KubeletConfigKey: "kubelet", + }, + } + (&nodeConfigTestCase{ + desc: "initial state (correct)", + configSource: source, + configMap: correctConfigMap, + expectConfig: correctKC, + }).run(f, setConfigSourceFunc, false, 0) + + cases := []nodeConfigTestCase{ + { + desc: "correct", + configSource: source, + configMap: correctConfigMap, + expectConfig: correctKC, + event: true, + }, + { + desc: "fail-parse", + configSource: source, + configMap: failParseConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + err: status.LoadError, + lkgActive: true, + }, + expectConfig: localKC, + event: true, + }, + { + desc: "fail-validate", + configSource: source, + configMap: failValidateConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + err: status.ValidateError, + lkgActive: true, + }, + expectConfig: localKC, + event: true, + }, + } + L := len(cases) + for i := 1; i <= L; i++ { // need one less iteration than the number of cases + testBothDirections(f, recreateConfigMapFunc, &cases[i-1 : i][0], cases[i:L], 0) + } + }) + }) + + // Please note: This behavior is tested to ensure implementation correctness. We do not, however, recommend ConfigMap mutations + // as a usage pattern for dynamic Kubelet config in large clusters. It is much safer to create a new ConfigMap, and incrementally + // roll out a new Node.Spec.ConfigSource that references the new ConfigMap. In-place ConfigMap updates, including deletion + // followed by re-creation, will cause all observing Kubelets to immediately restart for new config, because these operations + // change the ResourceVersion of the ConfigMap. + Context("delete and recreate ConfigMap: error while ConfigMap is absent:", func() { + It(itDescription, func() { + var err error + // we base the "correct" configmap off of the configuration from before the test + correctKC := beforeKC.DeepCopy() + correctConfigMap := newKubeletConfigMap("dynamic-kubelet-config-test-delete-createe", correctKC) + correctConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(correctConfigMap) + framework.ExpectNoError(err) + + // ensure node config source is set to the config map we will mutate in-place, + // since our mutation functions don't mutate Node.Spec.ConfigSource + source := &apiv1.NodeConfigSource{ + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: correctConfigMap.Namespace, + Name: correctConfigMap.Name, + KubeletConfigKey: "kubelet", + }, } + (&nodeConfigTestCase{ + desc: "correct", + configSource: source, + configMap: correctConfigMap, + expectConfig: correctKC, + }).run(f, setConfigSourceFunc, false, 0) + + // delete the ConfigMap, and ensure an error is reported by the Kubelet while the ConfigMap is absent + (&nodeConfigTestCase{ + desc: "correct", + configSource: source, + configMap: correctConfigMap, + expectConfigStatus: expectNodeConfigStatus{ + err: fmt.Sprintf(status.SyncErrorFmt, status.DownloadError), + }, + expectConfig: correctKC, + }).run(f, deleteConfigMapFunc, false, 0) + + // re-create the ConfigMap, and ensure the error disappears + (&nodeConfigTestCase{ + desc: "correct", + configSource: source, + configMap: correctConfigMap, + expectConfig: correctKC, + }).run(f, createConfigMapFunc, false, 0) }) }) }) }) -// testBothDirections tests the state change represented by each edge, where each state is a vertex, -// and there are edges in each direction between first and each of the states. -func testBothDirections(f *framework.Framework, first *configState, states []configState, waitAfterFirst time.Duration) { +// testBothDirections tests the state change represented by each edge, where each case is a vertex, +// and there are edges in each direction between first and each of the cases. +func testBothDirections(f *framework.Framework, fn func(f *framework.Framework, tc *nodeConfigTestCase) error, + first *nodeConfigTestCase, cases []nodeConfigTestCase, waitAfterFirst time.Duration) { // set to first and check that everything got set up properly - By(fmt.Sprintf("setting configSource to state %q", first.desc)) + By(fmt.Sprintf("setting initial state %q", first.desc)) // we don't always expect an event here, because setting "first" might not represent // a change from the current configuration - setAndTestKubeletConfigState(f, first, false) - - time.Sleep(waitAfterFirst) + first.run(f, fn, false, waitAfterFirst) - // for each state, set to that state, check condition and configz, then reset to first and check again - for i := range states { - By(fmt.Sprintf("from %q to %q", first.desc, states[i].desc)) - // from first -> states[i], states[i].event fully describes whether we should get a config change event - setAndTestKubeletConfigState(f, &states[i], states[i].event) + // for each case, set up, check expectations, then reset to first and check again + for i := range cases { + tc := &cases[i] + By(fmt.Sprintf("from %q to %q", first.desc, tc.desc)) + // from first -> tc, tc.event fully describes whether we should get a config change event + tc.run(f, fn, tc.event, 0) - By(fmt.Sprintf("back to %q from %q", first.desc, states[i].desc)) - // whether first -> states[i] should have produced a config change event partially determines whether states[i] -> first should produce an event - setAndTestKubeletConfigState(f, first, first.event && states[i].event) + By(fmt.Sprintf("back to %q from %q", first.desc, tc.desc)) + // whether first -> tc should have produced a config change event partially determines whether tc -> first should produce an event + first.run(f, fn, first.event && tc.event, 0) } } -// setAndTestKubeletConfigState tests that after setting the config source, the ConfigOk condition -// and (if appropriate) configuration exposed via conifgz are as expected. -// The configuration will be converted to the internal type prior to comparison. -func setAndTestKubeletConfigState(f *framework.Framework, state *configState, expectEvent bool) { +// run tests that, after performing fn, the node spec, status, configz, and latest event match +// the expectations described by state. +func (tc *nodeConfigTestCase) run(f *framework.Framework, fn func(f *framework.Framework, tc *nodeConfigTestCase) error, + expectEvent bool, wait time.Duration) { // set the desired state, retry a few times in case we are competing with other editors Eventually(func() error { - if err := setNodeConfigSource(f, state.configSource); err != nil { - return fmt.Errorf("case %s: error setting Node.Spec.ConfigSource", err) + if err := fn(f, tc); err != nil { + if len(tc.apierr) == 0 { + return fmt.Errorf("case %s: expect nil error but got %q", tc.desc, err.Error()) + } else if !strings.Contains(err.Error(), tc.apierr) { + return fmt.Errorf("case %s: expect error to contain %q but got %q", tc.desc, tc.apierr, err.Error()) + } + } else if len(tc.apierr) > 0 { + return fmt.Errorf("case %s: expect error to contain %q but got nil error", tc.desc, tc.apierr) } return nil }, time.Minute, time.Second).Should(BeNil()) - // check that config source actually got set to what we expect - checkNodeConfigSource(f, state.desc, state.configSource) - // check condition - checkConfigOkCondition(f, state.desc, state.expectConfigOk) + // skip further checks if we expected an API error + if len(tc.apierr) > 0 { + return + } + // wait for the designated duration before checking the reconciliation + time.Sleep(wait) + // check config source + tc.checkNodeConfigSource(f) + // check status + tc.checkConfigStatus(f) + // check that the Kubelet's config-related metrics are correct + tc.checkConfigMetrics(f) // check expectConfig - if state.expectConfig != nil { - checkConfig(f, state.desc, state.expectConfig) + if tc.expectConfig != nil { + tc.checkConfig(f) } // check that an event was sent for the config change if expectEvent { - checkEvent(f, state.desc, state.configSource) + tc.checkEvent(f) + } +} + +// setConfigSourceFunc sets Node.Spec.ConfigSource to tc.configSource +func setConfigSourceFunc(f *framework.Framework, tc *nodeConfigTestCase) error { + return setNodeConfigSource(f, tc.configSource) +} + +// updateConfigMapFunc updates the ConfigMap described by tc.configMap to contain matching data. +// It also updates the resourceVersion in any non-nil NodeConfigSource.ConfigMap in the expected +// status to match the resourceVersion of the updated ConfigMap. +func updateConfigMapFunc(f *framework.Framework, tc *nodeConfigTestCase) error { + // Clear ResourceVersion from the ConfigMap objects we use to initiate mutations + // so that we don't get 409 (conflict) responses. ConfigMaps always allow updates + // (with respect to concurrency control) when you omit ResourceVersion. + // We know that we won't perform concurrent updates during this test. + tc.configMap.ResourceVersion = "" + cm, err := f.ClientSet.CoreV1().ConfigMaps(tc.configMap.Namespace).Update(tc.configMap) + if err != nil { + return err + } + // update tc.configMap's ResourceVersion to match the updated ConfigMap, this makes + // sure our derived status checks have up-to-date information + tc.configMap.ResourceVersion = cm.ResourceVersion + return nil +} + +// recreateConfigMapFunc deletes and recreates the ConfigMap described by tc.configMap. +// The new ConfigMap will match tc.configMap. +func recreateConfigMapFunc(f *framework.Framework, tc *nodeConfigTestCase) error { + // need to ignore NotFound error, since there could be cases where delete + // fails during a retry because the delete in a previous attempt succeeded, + // before some other error occurred. + err := deleteConfigMapFunc(f, tc) + if err != nil && !apierrors.IsNotFound(err) { + return err + } + return createConfigMapFunc(f, tc) +} + +// deleteConfigMapFunc simply deletes tc.configMap +func deleteConfigMapFunc(f *framework.Framework, tc *nodeConfigTestCase) error { + return f.ClientSet.CoreV1().ConfigMaps(tc.configMap.Namespace).Delete(tc.configMap.Name, &metav1.DeleteOptions{}) +} + +// createConfigMapFunc creates tc.configMap and updates the UID and ResourceVersion on tc.configMap +// to match the created configMap +func createConfigMapFunc(f *framework.Framework, tc *nodeConfigTestCase) error { + tc.configMap.ResourceVersion = "" + cm, err := f.ClientSet.CoreV1().ConfigMaps(tc.configMap.Namespace).Create(tc.configMap) + if err != nil { + return err } + // update tc.configMap's UID and ResourceVersion to match the new ConfigMap, this makes + // sure our derived status checks have up-to-date information + tc.configMap.UID = cm.UID + tc.configMap.ResourceVersion = cm.ResourceVersion + return nil } // make sure the node's config source matches what we expect, after setting it -func checkNodeConfigSource(f *framework.Framework, desc string, expect *apiv1.NodeConfigSource) { +func (tc *nodeConfigTestCase) checkNodeConfigSource(f *framework.Framework) { const ( timeout = time.Minute interval = time.Second @@ -375,56 +891,74 @@ func checkNodeConfigSource(f *framework.Framework, desc string, expect *apiv1.No Eventually(func() error { node, err := f.ClientSet.CoreV1().Nodes().Get(framework.TestContext.NodeName, metav1.GetOptions{}) if err != nil { - return fmt.Errorf("checkNodeConfigSource: case %s: %v", desc, err) + return fmt.Errorf("checkNodeConfigSource: case %s: %v", tc.desc, err) } actual := node.Spec.ConfigSource - if !reflect.DeepEqual(expect, actual) { - return fmt.Errorf(spew.Sprintf("checkNodeConfigSource: case %s: expected %#v but got %#v", desc, expect, actual)) + if !apiequality.Semantic.DeepEqual(tc.configSource, actual) { + return fmt.Errorf(spew.Sprintf("checkNodeConfigSource: case %s: expected %#v but got %#v", tc.desc, tc.configSource, actual)) } return nil }, timeout, interval).Should(BeNil()) } -// make sure the ConfigOk node condition eventually matches what we expect -func checkConfigOkCondition(f *framework.Framework, desc string, expect *apiv1.NodeCondition) { +// make sure the node status eventually matches what we expect +func (tc *nodeConfigTestCase) checkConfigStatus(f *framework.Framework) { const ( timeout = time.Minute interval = time.Second ) - + errFmt := fmt.Sprintf("checkConfigStatus: case %s:", tc.desc) + " %v" Eventually(func() error { node, err := f.ClientSet.CoreV1().Nodes().Get(framework.TestContext.NodeName, metav1.GetOptions{}) if err != nil { - return fmt.Errorf("checkConfigOkCondition: case %s: %v", desc, err) + return fmt.Errorf(errFmt, err) } - actual := getKubeletConfigOkCondition(node.Status.Conditions) - if actual == nil { - return fmt.Errorf("checkConfigOkCondition: case %s: ConfigOk condition not found on node %q", desc, framework.TestContext.NodeName) - } - if err := expectConfigOk(expect, actual); err != nil { - return fmt.Errorf("checkConfigOkCondition: case %s: %v", desc, err) + if err := expectConfigStatus(tc, node.Status.Config); err != nil { + return fmt.Errorf(errFmt, err) } return nil }, timeout, interval).Should(BeNil()) } -// if the actual matches the expect, return nil, else error explaining the mismatch -// if a subfield of the expect is the empty string, that check is skipped -func expectConfigOk(expect, actual *apiv1.NodeCondition) error { - if expect.Status != actual.Status { - return fmt.Errorf("expected condition Status %q but got %q", expect.Status, actual.Status) +func expectConfigStatus(tc *nodeConfigTestCase, actual *apiv1.NodeConfigStatus) error { + var errs []string + if actual == nil { + return fmt.Errorf("expectConfigStatus requires actual to be non-nil (possible Kubelet failed to update status)") + } + // check Assigned matches tc.configSource, with UID and ResourceVersion from tc.configMap + expectAssigned := tc.configSource.DeepCopy() + if expectAssigned != nil && expectAssigned.ConfigMap != nil { + expectAssigned.ConfigMap.UID = tc.configMap.UID + expectAssigned.ConfigMap.ResourceVersion = tc.configMap.ResourceVersion + } + if !apiequality.Semantic.DeepEqual(expectAssigned, actual.Assigned) { + errs = append(errs, spew.Sprintf("expected Assigned %#v but got %#v", expectAssigned, actual.Assigned)) } - if len(expect.Message) > 0 && expect.Message != actual.Message { - return fmt.Errorf("expected condition Message %q but got %q", expect.Message, actual.Message) + // check LastKnownGood matches tc.expectConfigStatus.lastKnownGood + if !apiequality.Semantic.DeepEqual(tc.expectConfigStatus.lastKnownGood, actual.LastKnownGood) { + errs = append(errs, spew.Sprintf("expected LastKnownGood %#v but got %#v", tc.expectConfigStatus.lastKnownGood, actual.LastKnownGood)) } - if len(expect.Reason) > 0 && expect.Reason != actual.Reason { - return fmt.Errorf("expected condition Reason %q but got %q", expect.Reason, actual.Reason) + // check Active matches Assigned or LastKnownGood, depending on tc.expectConfigStatus.lkgActive + expectActive := expectAssigned + if tc.expectConfigStatus.lkgActive { + expectActive = tc.expectConfigStatus.lastKnownGood + } + if !apiequality.Semantic.DeepEqual(expectActive, actual.Active) { + errs = append(errs, spew.Sprintf("expected Active %#v but got %#v", expectActive, actual.Active)) + } + // check Error + if tc.expectConfigStatus.err != actual.Error { + errs = append(errs, fmt.Sprintf("expected Error %q but got %q", tc.expectConfigStatus.err, actual.Error)) + } + // format error list + if len(errs) > 0 { + return fmt.Errorf("%s", strings.Join(errs, ", ")) } return nil } // make sure config exposed on configz matches what we expect -func checkConfig(f *framework.Framework, desc string, expect *kubeletconfig.KubeletConfiguration) { +func (tc *nodeConfigTestCase) checkConfig(f *framework.Framework) { const ( timeout = time.Minute interval = time.Second @@ -432,10 +966,10 @@ func checkConfig(f *framework.Framework, desc string, expect *kubeletconfig.Kube Eventually(func() error { actual, err := getCurrentKubeletConfig() if err != nil { - return fmt.Errorf("checkConfig: case %s: %v", desc, err) + return fmt.Errorf("checkConfig: case %s: %v", tc.desc, err) } - if !reflect.DeepEqual(expect, actual) { - return fmt.Errorf(spew.Sprintf("checkConfig: case %s: expected %#v but got %#v", desc, expect, actual)) + if !apiequality.Semantic.DeepEqual(tc.expectConfig, actual) { + return fmt.Errorf(spew.Sprintf("checkConfig: case %s: expected %#v but got %#v", tc.desc, tc.expectConfig, actual)) } return nil }, timeout, interval).Should(BeNil()) @@ -443,7 +977,7 @@ func checkConfig(f *framework.Framework, desc string, expect *kubeletconfig.Kube // checkEvent makes sure an event was sent marking the Kubelet's restart to use new config, // and that it mentions the config we expect. -func checkEvent(f *framework.Framework, desc string, expect *apiv1.NodeConfigSource) { +func (tc *nodeConfigTestCase) checkEvent(f *framework.Framework) { const ( timeout = time.Minute interval = time.Second @@ -451,7 +985,7 @@ func checkEvent(f *framework.Framework, desc string, expect *apiv1.NodeConfigSou Eventually(func() error { events, err := f.ClientSet.CoreV1().Events("").List(metav1.ListOptions{}) if err != nil { - return fmt.Errorf("checkEvent: case %s: %v", desc, err) + return fmt.Errorf("checkEvent: case %s: %v", tc.desc, err) } // find config changed event with most recent timestamp var recent *apiv1.Event @@ -467,23 +1001,128 @@ func checkEvent(f *framework.Framework, desc string, expect *apiv1.NodeConfigSou } } } - // we expect at least one config change event if recent == nil { - return fmt.Errorf("checkEvent: case %s: no events found with reason %s", desc, controller.KubeletConfigChangedEventReason) + return fmt.Errorf("checkEvent: case %s: no events found with reason %s", tc.desc, controller.KubeletConfigChangedEventReason) } - - // ensure the message is what we expect (including the resource path) - expectMessage := fmt.Sprintf(controller.EventMessageFmt, controller.LocalConfigMessage) - if expect != nil { - if expect.ConfigMapRef != nil { - expectMessage = fmt.Sprintf(controller.EventMessageFmt, fmt.Sprintf("/api/v1/namespaces/%s/configmaps/%s", expect.ConfigMapRef.Namespace, expect.ConfigMapRef.Name)) + // construct expected message, based on the test case + expectMessage := controller.LocalEventMessage + if tc.configSource != nil { + if tc.configSource.ConfigMap != nil { + expectMessage = fmt.Sprintf(controller.RemoteEventMessageFmt, + fmt.Sprintf("/api/v1/namespaces/%s/configmaps/%s", tc.configSource.ConfigMap.Namespace, tc.configSource.ConfigMap.Name), + tc.configMap.UID, tc.configMap.ResourceVersion, tc.configSource.ConfigMap.KubeletConfigKey) } } + // compare messages if expectMessage != recent.Message { - return fmt.Errorf("checkEvent: case %s: expected event message %q but got %q", desc, expectMessage, recent.Message) + return fmt.Errorf("checkEvent: case %s: expected event message %q but got %q", tc.desc, expectMessage, recent.Message) } + return nil + }, timeout, interval).Should(BeNil()) +} +// checkConfigMetrics makes sure the Kubelet's config related metrics are as we expect, given the test case +func (tc *nodeConfigTestCase) checkConfigMetrics(f *framework.Framework) { + const ( + timeout = time.Minute + interval = time.Second + assignedConfigKey = metrics.KubeletSubsystem + "_" + metrics.AssignedConfigKey + activeConfigKey = metrics.KubeletSubsystem + "_" + metrics.ActiveConfigKey + lastKnownGoodConfigKey = metrics.KubeletSubsystem + "_" + metrics.LastKnownGoodConfigKey + configErrorKey = metrics.KubeletSubsystem + "_" + metrics.ConfigErrorKey + ) + // local config helper + mkLocalSample := func(name model.LabelValue) *model.Sample { + return &model.Sample{ + Metric: model.Metric(map[model.LabelName]model.LabelValue{ + model.MetricNameLabel: name, + metrics.ConfigSourceLabelKey: metrics.ConfigSourceLabelValueLocal, + metrics.ConfigUIDLabelKey: "", + metrics.ConfigResourceVersionLabelKey: "", + metrics.KubeletConfigKeyLabelKey: "", + }), + Value: 1, + } + } + // remote config helper + mkRemoteSample := func(name model.LabelValue, source *apiv1.NodeConfigSource) *model.Sample { + return &model.Sample{ + Metric: model.Metric(map[model.LabelName]model.LabelValue{ + model.MetricNameLabel: name, + metrics.ConfigSourceLabelKey: model.LabelValue(fmt.Sprintf("/api/v1/namespaces/%s/configmaps/%s", source.ConfigMap.Namespace, source.ConfigMap.Name)), + metrics.ConfigUIDLabelKey: model.LabelValue(source.ConfigMap.UID), + metrics.ConfigResourceVersionLabelKey: model.LabelValue(source.ConfigMap.ResourceVersion), + metrics.KubeletConfigKeyLabelKey: model.LabelValue(source.ConfigMap.KubeletConfigKey), + }), + Value: 1, + } + } + // error helper + mkErrorSample := func(expectError bool) *model.Sample { + v := model.SampleValue(0) + if expectError { + v = model.SampleValue(1) + } + return &model.Sample{ + Metric: model.Metric(map[model.LabelName]model.LabelValue{model.MetricNameLabel: configErrorKey}), + Value: v, + } + } + // construct expected metrics + // assigned + assignedSamples := model.Samples{mkLocalSample(assignedConfigKey)} + assignedSource := tc.configSource.DeepCopy() + if assignedSource != nil && assignedSource.ConfigMap != nil { + assignedSource.ConfigMap.UID = tc.configMap.UID + assignedSource.ConfigMap.ResourceVersion = tc.configMap.ResourceVersion + assignedSamples = model.Samples{mkRemoteSample(assignedConfigKey, assignedSource)} + } + // last-known-good + lastKnownGoodSamples := model.Samples{mkLocalSample(lastKnownGoodConfigKey)} + lastKnownGoodSource := tc.expectConfigStatus.lastKnownGood + if lastKnownGoodSource != nil && lastKnownGoodSource.ConfigMap != nil { + lastKnownGoodSamples = model.Samples{mkRemoteSample(lastKnownGoodConfigKey, lastKnownGoodSource)} + } + // active + activeSamples := model.Samples{mkLocalSample(activeConfigKey)} + activeSource := assignedSource + if tc.expectConfigStatus.lkgActive { + activeSource = lastKnownGoodSource + } + if activeSource != nil && activeSource.ConfigMap != nil { + activeSamples = model.Samples{mkRemoteSample(activeConfigKey, activeSource)} + } + // error + errorSamples := model.Samples{mkErrorSample(len(tc.expectConfigStatus.err) > 0)} + // expected metrics + expect := frameworkmetrics.KubeletMetrics(map[string]model.Samples{ + assignedConfigKey: assignedSamples, + activeConfigKey: activeSamples, + lastKnownGoodConfigKey: lastKnownGoodSamples, + configErrorKey: errorSamples, + }) + // wait for expected metrics to appear + Eventually(func() error { + actual, err := getKubeletMetrics(sets.NewString( + assignedConfigKey, + activeConfigKey, + lastKnownGoodConfigKey, + configErrorKey, + )) + if err != nil { + return err + } + // clear timestamps from actual, so DeepEqual is time-invariant + for _, samples := range actual { + for _, sample := range samples { + sample.Timestamp = 0 + } + } + // compare to expected + if !reflect.DeepEqual(expect, actual) { + return fmt.Errorf("checkConfigMetrics: case: %s: expect metrics %s but got %s", tc.desc, spew.Sprintf("%#v", expect), spew.Sprintf("%#v", actual)) + } return nil }, timeout, interval).Should(BeNil()) } diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/environment/setup_host.sh b/vendor/k8s.io/kubernetes/test/e2e_node/environment/setup_host.sh index 2069a3a49..5ea0ab1dc 100755 --- a/vendor/k8s.io/kubernetes/test/e2e_node/environment/setup_host.sh +++ b/vendor/k8s.io/kubernetes/test/e2e_node/environment/setup_host.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/eviction_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/eviction_test.go index b0de88572..5160578be 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/eviction_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/eviction_test.go @@ -20,15 +20,18 @@ import ( "fmt" "path/filepath" "strconv" + "strings" "time" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" nodeutil "k8s.io/kubernetes/pkg/api/v1/node" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" + "k8s.io/kubernetes/pkg/kubelet/eviction" kubeletmetrics "k8s.io/kubernetes/pkg/kubelet/metrics" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/test/e2e/framework" @@ -49,18 +52,21 @@ const ( // pressure conditions often surface after evictions because the kubelet only updates // node conditions periodically. // we wait this period after evictions to make sure that we wait out this delay - pressureDelay = 20 * time.Second - testContextFmt = "when we run containers that should cause %s" - noPressure = v1.NodeConditionType("NoPressure") - lotsOfDisk = 10240 // 10 Gb in Mb - lotsOfFiles = 1000000000 // 1 billion + pressureDelay = 20 * time.Second + testContextFmt = "when we run containers that should cause %s" + noPressure = v1.NodeConditionType("NoPressure") + lotsOfDisk = 10240 // 10 Gb in Mb + lotsOfFiles = 1000000000 // 1 billion + resourceInodes = v1.ResourceName("inodes") + noStarvedResource = v1.ResourceName("none") ) // InodeEviction tests that the node responds to node disk pressure by evicting only responsible pods. // Node disk pressure is induced by consuming all inodes on the node. -var _ = framework.KubeDescribe("InodeEviction [Slow] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("InodeEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("inode-eviction-test") expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := resourceInodes pressureTimeout := 15 * time.Minute inodesConsumed := uint64(200000) Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { @@ -74,7 +80,7 @@ var _ = framework.KubeDescribe("InodeEviction [Slow] [Serial] [Disruptive]", fun initialConfig.EvictionHard = map[string]string{"nodefs.inodesFree": fmt.Sprintf("%d", inodesFree-inodesConsumed)} initialConfig.EvictionMinimumReclaim = map[string]string{} }) - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logInodeMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logInodeMetrics, []podEvictSpec{ { evictionPriority: 1, pod: inodeConsumingPod("container-inode-hog", lotsOfFiles, nil), @@ -93,10 +99,11 @@ var _ = framework.KubeDescribe("InodeEviction [Slow] [Serial] [Disruptive]", fun // ImageGCNoEviction tests that the node does not evict pods when inodes are consumed by images // Disk pressure is induced by pulling large images -var _ = framework.KubeDescribe("ImageGCNoEviction [Slow] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("ImageGCNoEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("image-gc-eviction-test") pressureTimeout := 10 * time.Minute expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := resourceInodes inodesConsumed := uint64(100000) Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { @@ -111,7 +118,7 @@ var _ = framework.KubeDescribe("ImageGCNoEviction [Slow] [Serial] [Disruptive]", }) // Consume enough inodes to induce disk pressure, // but expect that image garbage collection can reduce it enough to avoid an eviction - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logDiskMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logDiskMetrics, []podEvictSpec{ { evictionPriority: 0, pod: inodeConsumingPod("container-inode", 110000, nil), @@ -122,24 +129,25 @@ var _ = framework.KubeDescribe("ImageGCNoEviction [Slow] [Serial] [Disruptive]", // MemoryAllocatableEviction tests that the node responds to node memory pressure by evicting only responsible pods. // Node memory pressure is only encountered because we reserve the majority of the node's capacity via kube-reserved. -var _ = framework.KubeDescribe("MemoryAllocatableEviction [Slow] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("MemoryAllocatableEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("memory-allocatable-eviction-test") expectedNodeCondition := v1.NodeMemoryPressure + expectedStarvedResource := v1.ResourceMemory pressureTimeout := 10 * time.Minute Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { // Set large system and kube reserved values to trigger allocatable thresholds far before hard eviction thresholds. kubeReserved := getNodeCPUAndMemoryCapacity(f)[v1.ResourceMemory] // The default hard eviction threshold is 250Mb, so Allocatable = Capacity - Reserved - 250Mb - // We want Allocatable = 150Mb, so set Reserved = Capacity - Allocatable - 250Mb = Capacity - 400Mb - kubeReserved.Sub(resource.MustParse("400Mi")) + // We want Allocatable = 50Mb, so set Reserved = Capacity - Allocatable - 250Mb = Capacity - 300Mb + kubeReserved.Sub(resource.MustParse("300Mi")) initialConfig.KubeReserved = map[string]string{ string(v1.ResourceMemory): kubeReserved.String(), } initialConfig.EnforceNodeAllocatable = []string{kubetypes.NodeAllocatableEnforcementKey} initialConfig.CgroupsPerQOS = true }) - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logMemoryMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logMemoryMetrics, []podEvictSpec{ { evictionPriority: 1, pod: getMemhogPod("memory-hog-pod", "memory-hog", v1.ResourceRequirements{}), @@ -154,10 +162,11 @@ var _ = framework.KubeDescribe("MemoryAllocatableEviction [Slow] [Serial] [Disru // LocalStorageEviction tests that the node responds to node disk pressure by evicting only responsible pods // Disk pressure is induced by running pods which consume disk space. -var _ = framework.KubeDescribe("LocalStorageEviction [Slow] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("LocalStorageEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("localstorage-eviction-test") pressureTimeout := 10 * time.Minute expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := v1.ResourceEphemeralStorage Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { diskConsumed := resource.MustParse("100Mi") @@ -166,7 +175,7 @@ var _ = framework.KubeDescribe("LocalStorageEviction [Slow] [Serial] [Disruptive initialConfig.EvictionHard = map[string]string{"nodefs.available": fmt.Sprintf("%d", availableBytes-uint64(diskConsumed.Value()))} initialConfig.EvictionMinimumReclaim = map[string]string{} }) - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logDiskMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logDiskMetrics, []podEvictSpec{ { evictionPriority: 1, pod: diskConsumingPod("container-disk-hog", lotsOfDisk, nil, v1.ResourceRequirements{}), @@ -182,10 +191,11 @@ var _ = framework.KubeDescribe("LocalStorageEviction [Slow] [Serial] [Disruptive // LocalStorageEviction tests that the node responds to node disk pressure by evicting only responsible pods // Disk pressure is induced by running pods which consume disk space, which exceed the soft eviction threshold. // Note: This test's purpose is to test Soft Evictions. Local storage was chosen since it is the least costly to run. -var _ = framework.KubeDescribe("LocalStorageSoftEviction [Slow] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("LocalStorageSoftEviction [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("localstorage-eviction-test") pressureTimeout := 10 * time.Minute expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := v1.ResourceEphemeralStorage Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { diskConsumed := resource.MustParse("100Mi") @@ -203,7 +213,7 @@ var _ = framework.KubeDescribe("LocalStorageSoftEviction [Slow] [Serial] [Disrup // setting a threshold to 0% disables; non-empty map overrides default value (necessary due to omitempty) initialConfig.EvictionHard = map[string]string{"memory.available": "0%"} }) - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logDiskMetrics, []podEvictSpec{ + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logDiskMetrics, []podEvictSpec{ { evictionPriority: 1, pod: diskConsumingPod("container-disk-hog", lotsOfDisk, nil, v1.ResourceRequirements{}), @@ -217,7 +227,7 @@ var _ = framework.KubeDescribe("LocalStorageSoftEviction [Slow] [Serial] [Disrup }) // LocalStorageCapacityIsolationEviction tests that container and volume local storage limits are enforced through evictions -var _ = framework.KubeDescribe("LocalStorageCapacityIsolationEviction [Slow] [Serial] [Disruptive] [Feature:LocalStorageCapacityIsolation]", func() { +var _ = framework.KubeDescribe("LocalStorageCapacityIsolationEviction [Slow] [Serial] [Disruptive] [Feature:LocalStorageCapacityIsolation][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("localstorage-eviction-test") evictionTestTimeout := 10 * time.Minute Context(fmt.Sprintf(testContextFmt, "evictions due to pod local storage violations"), func() { @@ -231,7 +241,7 @@ var _ = framework.KubeDescribe("LocalStorageCapacityIsolationEviction [Slow] [Se useUnderLimit := 99 /* Mb */ containerLimit := v1.ResourceList{v1.ResourceEphemeralStorage: sizeLimit} - runEvictionTest(f, evictionTestTimeout, noPressure, logDiskMetrics, []podEvictSpec{ + runEvictionTest(f, evictionTestTimeout, noPressure, noStarvedResource, logDiskMetrics, []podEvictSpec{ { evictionPriority: 1, // This pod should be evicted because emptyDir (default storage type) usage violation pod: diskConsumingPod("emptydir-disk-sizelimit", useOverLimit, &v1.VolumeSource{ @@ -270,9 +280,10 @@ var _ = framework.KubeDescribe("LocalStorageCapacityIsolationEviction [Slow] [Se // PriorityMemoryEvictionOrdering tests that the node responds to node memory pressure by evicting pods. // This test tests that the guaranteed pod is never evicted, and that the lower-priority pod is evicted before // the higher priority pod. -var _ = framework.KubeDescribe("PriorityMemoryEvictionOrdering [Slow] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("PriorityMemoryEvictionOrdering [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("priority-memory-eviction-ordering-test") expectedNodeCondition := v1.NodeMemoryPressure + expectedStarvedResource := v1.ResourceMemory pressureTimeout := 10 * time.Minute Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { @@ -309,16 +320,17 @@ var _ = framework.KubeDescribe("PriorityMemoryEvictionOrdering [Slow] [Serial] [ } systemPriority := int32(2147483647) specs[1].pod.Spec.Priority = &systemPriority - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logMemoryMetrics, specs) + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logMemoryMetrics, specs) }) }) // PriorityLocalStorageEvictionOrdering tests that the node responds to node disk pressure by evicting pods. // This test tests that the guaranteed pod is never evicted, and that the lower-priority pod is evicted before // the higher priority pod. -var _ = framework.KubeDescribe("PriorityLocalStorageEvictionOrdering [Slow] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("PriorityLocalStorageEvictionOrdering [Slow] [Serial] [Disruptive][NodeFeature:Eviction]", func() { f := framework.NewDefaultFramework("priority-disk-eviction-ordering-test") expectedNodeCondition := v1.NodeDiskPressure + expectedStarvedResource := v1.ResourceEphemeralStorage pressureTimeout := 10 * time.Minute Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() { tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) { @@ -357,7 +369,7 @@ var _ = framework.KubeDescribe("PriorityLocalStorageEvictionOrdering [Slow] [Ser } systemPriority := int32(2147483647) specs[1].pod.Spec.Priority = &systemPriority - runEvictionTest(f, pressureTimeout, expectedNodeCondition, logDiskMetrics, specs) + runEvictionTest(f, pressureTimeout, expectedNodeCondition, expectedStarvedResource, logDiskMetrics, specs) }) }) @@ -376,10 +388,12 @@ type podEvictSpec struct { // It ensures that lower evictionPriority pods are always evicted before higher evictionPriority pods (2 evicted before 1, etc.) // It ensures that all pods with non-zero evictionPriority are eventually evicted. // runEvictionTest then cleans up the testing environment by deleting provided pods, and ensures that expectedNodeCondition no longer exists -func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expectedNodeCondition v1.NodeConditionType, logFunc func(), testSpecs []podEvictSpec) { +func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expectedNodeCondition v1.NodeConditionType, expectedStarvedResource v1.ResourceName, logFunc func(), testSpecs []podEvictSpec) { // Place the remainder of the test within a context so that the kubelet config is set before and after the test. Context("", func() { BeforeEach(func() { + // reduce memory usage in the allocatable cgroup to ensure we do not have MemoryPressure + reduceAllocatableMemoryUsage() // Nodes do not immediately report local storage capacity // Sleep so that pods requesting local storage do not fail to schedule time.Sleep(30 * time.Second) @@ -409,7 +423,7 @@ func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expe framework.Logf("Node does NOT have %s", expectedNodeCondition) } } - logKubeletMetrics(kubeletmetrics.EvictionStatsAgeKey) + logKubeletLatencyMetrics(kubeletmetrics.EvictionStatsAgeKey) logFunc() return verifyEvictionOrdering(f, testSpecs) }, pressureTimeout, evictionPollInterval).Should(BeNil()) @@ -423,7 +437,7 @@ func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expe By(fmt.Sprintf("Waiting for NodeCondition: %s to no longer exist on the node", expectedNodeCondition)) Eventually(func() error { logFunc() - logKubeletMetrics(kubeletmetrics.EvictionStatsAgeKey) + logKubeletLatencyMetrics(kubeletmetrics.EvictionStatsAgeKey) if expectedNodeCondition != noPressure && hasNodeCondition(f, expectedNodeCondition) { return fmt.Errorf("Conditions havent returned to normal, node still has %s", expectedNodeCondition) } @@ -436,9 +450,12 @@ func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expe return fmt.Errorf("%s dissappeared and then reappeared", expectedNodeCondition) } logFunc() - logKubeletMetrics(kubeletmetrics.EvictionStatsAgeKey) + logKubeletLatencyMetrics(kubeletmetrics.EvictionStatsAgeKey) return verifyEvictionOrdering(f, testSpecs) }, postTestConditionMonitoringPeriod, evictionPollInterval).Should(BeNil()) + + By("checking for correctly formatted eviction events") + verifyEvictionEvents(f, testSpecs, expectedStarvedResource) }) AfterEach(func() { @@ -447,6 +464,7 @@ func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expe By(fmt.Sprintf("deleting pod: %s", spec.pod.Name)) f.PodClient().DeleteSync(spec.pod.Name, &metav1.DeleteOptions{}, 10*time.Minute) } + reduceAllocatableMemoryUsage() if expectedNodeCondition == v1.NodeDiskPressure && framework.TestContext.PrepullImages { // The disk eviction test may cause the prepulled images to be evicted, // prepull those images again to ensure this test not affect following tests. @@ -462,7 +480,7 @@ func runEvictionTest(f *framework.Framework, pressureTimeout time.Duration, expe RestartPolicy: v1.RestartPolicyNever, Containers: []v1.Container{ { - Image: imageutils.GetPauseImageNameForHostArch(), + Image: imageutils.GetPauseImageName(), Name: podName, }, }, @@ -502,6 +520,8 @@ func verifyEvictionOrdering(f *framework.Framework, testSpecs []podEvictSpec) er } } Expect(priorityPod).NotTo(BeNil()) + Expect(priorityPod.Status.Phase).NotTo(Equal(v1.PodSucceeded), + fmt.Sprintf("pod: %s succeeded unexpectedly", priorityPod.Name)) // Check eviction ordering. // Note: it is alright for a priority 1 and priority 2 pod (for example) to fail in the same round, @@ -521,6 +541,11 @@ func verifyEvictionOrdering(f *framework.Framework, testSpecs []podEvictSpec) er } } + if priorityPod.Status.Phase == v1.PodFailed { + Expect(priorityPod.Status.Reason, eviction.Reason, "pod %s failed; expected Status.Reason to be %s, but got %s", + priorityPod.Name, eviction.Reason, priorityPod.Status.Reason) + } + // EvictionPriority 0 pods should not fail if priorityPodSpec.evictionPriority == 0 { Expect(priorityPod.Status.Phase).NotTo(Equal(v1.PodFailed), @@ -538,6 +563,60 @@ func verifyEvictionOrdering(f *framework.Framework, testSpecs []podEvictSpec) er return fmt.Errorf("pods that should be evicted are still running") } +func verifyEvictionEvents(f *framework.Framework, testSpecs []podEvictSpec, expectedStarvedResource v1.ResourceName) { + for _, spec := range testSpecs { + pod := spec.pod + if spec.evictionPriority != 0 { + selector := fields.Set{ + "involvedObject.kind": "Pod", + "involvedObject.name": pod.Name, + "involvedObject.namespace": f.Namespace.Name, + "reason": eviction.Reason, + }.AsSelector().String() + podEvictEvents, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).List(metav1.ListOptions{FieldSelector: selector}) + Expect(err).To(BeNil(), "Unexpected error getting events during eviction test: %v", err) + Expect(len(podEvictEvents.Items)).To(Equal(1), "Expected to find 1 eviction event for pod %s, got %d", pod.Name, len(podEvictEvents.Items)) + event := podEvictEvents.Items[0] + + if expectedStarvedResource != noStarvedResource { + // Check the eviction.StarvedResourceKey + starved, found := event.Annotations[eviction.StarvedResourceKey] + Expect(found).To(BeTrue(), "Expected to find an annotation on the eviction event for pod %s containing the starved resource %s, but it was not found", + pod.Name, expectedStarvedResource) + starvedResource := v1.ResourceName(starved) + Expect(starvedResource).To(Equal(expectedStarvedResource), "Expected to the starved_resource annotation on pod %s to contain %s, but got %s instead", + pod.Name, expectedStarvedResource, starvedResource) + + // We only check these keys for memory, because ephemeral storage evictions may be due to volume usage, in which case these values are not present + if expectedStarvedResource == v1.ResourceMemory { + // Check the eviction.OffendingContainersKey + offendersString, found := event.Annotations[eviction.OffendingContainersKey] + Expect(found).To(BeTrue(), "Expected to find an annotation on the eviction event for pod %s containing the offending containers, but it was not found", + pod.Name) + offendingContainers := strings.Split(offendersString, ",") + Expect(len(offendingContainers)).To(Equal(1), "Expected to find the offending container's usage in the %s annotation, but no container was found", + eviction.OffendingContainersKey) + Expect(offendingContainers[0]).To(Equal(pod.Spec.Containers[0].Name), "Expected to find the offending container: %s's usage in the %s annotation, but found %s instead", + pod.Spec.Containers[0].Name, eviction.OffendingContainersKey, offendingContainers[0]) + + // Check the eviction.OffendingContainersUsageKey + offendingUsageString, found := event.Annotations[eviction.OffendingContainersUsageKey] + Expect(found).To(BeTrue(), "Expected to find an annotation on the eviction event for pod %s containing the offending containers' usage, but it was not found", + pod.Name) + offendingContainersUsage := strings.Split(offendingUsageString, ",") + Expect(len(offendingContainersUsage)).To(Equal(1), "Expected to find the offending container's usage in the %s annotation, but found %+v", + eviction.OffendingContainersUsageKey, offendingContainersUsage) + usageQuantity, err := resource.ParseQuantity(offendingContainersUsage[0]) + Expect(err).To(BeNil(), "Expected to be able to parse pod %s's %s annotation as a quantity, but got err: %v", pod.Name, eviction.OffendingContainersUsageKey, err) + request := pod.Spec.Containers[0].Resources.Requests[starvedResource] + Expect(usageQuantity.Cmp(request)).To(Equal(1), "Expected usage of offending container: %s in pod %s to exceed its request %s", + usageQuantity.String(), pod.Name, request.String()) + } + } + } + } +} + // Returns TRUE if the node has the node condition, FALSE otherwise func hasNodeCondition(f *framework.Framework, expectedNodeCondition v1.NodeConditionType) bool { localNodeStatus := getLocalNode(f).Status @@ -607,7 +686,12 @@ func logMemoryMetrics() { return } if summary.Node.Memory != nil && summary.Node.Memory.WorkingSetBytes != nil && summary.Node.Memory.AvailableBytes != nil { - framework.Logf("Node.Memory.WorkingSetBytes: %d, summary.Node.Memory.AvailableBytes: %d", *summary.Node.Memory.WorkingSetBytes, *summary.Node.Memory.AvailableBytes) + framework.Logf("Node.Memory.WorkingSetBytes: %d, Node.Memory.AvailableBytes: %d", *summary.Node.Memory.WorkingSetBytes, *summary.Node.Memory.AvailableBytes) + } + for _, sysContainer := range summary.Node.SystemContainers { + if sysContainer.Name == stats.SystemContainerPods && sysContainer.Memory != nil && sysContainer.Memory.WorkingSetBytes != nil && sysContainer.Memory.AvailableBytes != nil { + framework.Logf("Allocatable.Memory.WorkingSetBytes: %d, Allocatable.Memory.AvailableBytes: %d", *sysContainer.Memory.WorkingSetBytes, *sysContainer.Memory.AvailableBytes) + } } for _, pod := range summary.Pods { framework.Logf("Pod: %s", pod.PodRef.Name) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/garbage_collector_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/garbage_collector_test.go index d6a9244ad..2ee6ce772 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/garbage_collector_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/garbage_collector_test.go @@ -71,7 +71,7 @@ type testRun struct { // GarbageCollect tests that the Kubelet conforms to the Kubelet Garbage Collection Policy, found here: // http://kubernetes.io/docs/admin/garbage-collection/ -var _ = framework.KubeDescribe("GarbageCollect [Serial]", func() { +var _ = framework.KubeDescribe("GarbageCollect [Serial][NodeFeature:GarbageCollect]", func() { f := framework.NewDefaultFramework("garbage-collect-test") containerNamePrefix := "gc-test-container-" podNamePrefix := "gc-test-pod-" diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/gke_environment_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/gke_environment_test.go index dd88976b3..f0badefd4 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/gke_environment_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/gke_environment_test.go @@ -310,7 +310,7 @@ func checkDockerStorageDriver() error { return fmt.Errorf("failed to find storage driver") } -var _ = framework.KubeDescribe("GKE system requirements [Conformance] [Feature:GKEEnv]", func() { +var _ = framework.KubeDescribe("GKE system requirements [Conformance][NodeConformance][Feature:GKEEnv][NodeFeature:GKEEnv]", func() { BeforeEach(func() { framework.RunIfSystemSpecNameIs("gke") }) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/gpu_device_plugin.go b/vendor/k8s.io/kubernetes/test/e2e_node/gpu_device_plugin.go index 698452016..d9ee9f527 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/gpu_device_plugin.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/gpu_device_plugin.go @@ -17,6 +17,7 @@ limitations under the License. package e2e_node import ( + "os/exec" "strconv" "time" @@ -36,7 +37,7 @@ const ( ) // Serial because the test restarts Kubelet -var _ = framework.KubeDescribe("NVIDIA GPU Device Plugin [Feature:GPUDevicePlugin] [Serial] [Disruptive]", func() { +var _ = framework.KubeDescribe("NVIDIA GPU Device Plugin [Feature:GPUDevicePlugin][NodeFeature:GPUDevicePlugin][Serial] [Disruptive]", func() { f := framework.NewDefaultFramework("device-plugin-gpus-errors") Context("DevicePlugin", func() { @@ -79,7 +80,7 @@ var _ = framework.KubeDescribe("NVIDIA GPU Device Plugin [Feature:GPUDevicePlugi p1 := f.PodClient().CreateSync(makeBusyboxPod(framework.NVIDIAGPUResourceName, podRECMD)) deviceIDRE := "gpu devices: (nvidia[0-9]+)" - count1, devId1 := parseLogFromNRuns(f, p1.Name, p1.Name, 1, deviceIDRE) + devId1 := parseLog(f, p1.Name, p1.Name, deviceIDRE) p1, err := f.PodClient().Get(p1.Name, metav1.GetOptions{}) framework.ExpectNoError(err) @@ -87,7 +88,8 @@ var _ = framework.KubeDescribe("NVIDIA GPU Device Plugin [Feature:GPUDevicePlugi restartKubelet() By("Confirming that after a kubelet and pod restart, GPU assignement is kept") - count1, devIdRestart1 := parseLogFromNRuns(f, p1.Name, p1.Name, count1+1, deviceIDRE) + ensurePodContainerRestart(f, p1.Name, p1.Name) + devIdRestart1 := parseLog(f, p1.Name, p1.Name, deviceIDRE) Expect(devIdRestart1).To(Equal(devId1)) By("Restarting Kubelet and creating another pod") @@ -99,7 +101,7 @@ var _ = framework.KubeDescribe("NVIDIA GPU Device Plugin [Feature:GPUDevicePlugi p2 := f.PodClient().CreateSync(makeBusyboxPod(framework.NVIDIAGPUResourceName, podRECMD)) By("Checking that pods got a different GPU") - count2, devId2 := parseLogFromNRuns(f, p2.Name, p2.Name, 1, deviceIDRE) + devId2 := parseLog(f, p2.Name, p2.Name, deviceIDRE) Expect(devId1).To(Not(Equal(devId2))) @@ -112,16 +114,21 @@ var _ = framework.KubeDescribe("NVIDIA GPU Device Plugin [Feature:GPUDevicePlugi return framework.NumberOfNVIDIAGPUs(node) <= 0 }, 10*time.Minute, framework.Poll).Should(BeTrue()) By("Checking that scheduled pods can continue to run even after we delete device plugin.") - count1, devIdRestart1 = parseLogFromNRuns(f, p1.Name, p1.Name, count1+1, deviceIDRE) + ensurePodContainerRestart(f, p1.Name, p1.Name) + devIdRestart1 = parseLog(f, p1.Name, p1.Name, deviceIDRE) Expect(devIdRestart1).To(Equal(devId1)) - count2, devIdRestart2 := parseLogFromNRuns(f, p2.Name, p2.Name, count2+1, deviceIDRE) + + ensurePodContainerRestart(f, p2.Name, p2.Name) + devIdRestart2 := parseLog(f, p2.Name, p2.Name, deviceIDRE) Expect(devIdRestart2).To(Equal(devId2)) By("Restarting Kubelet.") restartKubelet() By("Checking that scheduled pods can continue to run even after we delete device plugin and restart Kubelet.") - count1, devIdRestart1 = parseLogFromNRuns(f, p1.Name, p1.Name, count1+2, deviceIDRE) + ensurePodContainerRestart(f, p1.Name, p1.Name) + devIdRestart1 = parseLog(f, p1.Name, p1.Name, deviceIDRE) Expect(devIdRestart1).To(Equal(devId1)) - count2, devIdRestart2 = parseLogFromNRuns(f, p2.Name, p2.Name, count2+2, deviceIDRE) + ensurePodContainerRestart(f, p2.Name, p2.Name) + devIdRestart2 = parseLog(f, p2.Name, p2.Name, deviceIDRE) Expect(devIdRestart2).To(Equal(devId2)) logDevicePluginMetrics() @@ -132,6 +139,16 @@ var _ = framework.KubeDescribe("NVIDIA GPU Device Plugin [Feature:GPUDevicePlugi }) }) +func checkIfNvidiaGPUsExistOnNode() bool { + // Cannot use `lspci` because it is not installed on all distros by default. + err := exec.Command("/bin/sh", "-c", "find /sys/devices/pci* -type f | grep vendor | xargs cat | grep 0x10de").Run() + if err != nil { + framework.Logf("check for nvidia GPUs failed. Got Error: %v", err) + return false + } + return true +} + func logDevicePluginMetrics() { ms, err := metrics.GrabKubeletMetricsWithoutProxy(framework.TestContext.NodeName + ":10255") framework.ExpectNoError(err) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/gpus.go b/vendor/k8s.io/kubernetes/test/e2e_node/gpus.go deleted file mode 100644 index 41c364db6..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/gpus.go +++ /dev/null @@ -1,174 +0,0 @@ -/* -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 e2e_node - -import ( - "fmt" - "os/exec" - "time" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" - "k8s.io/kubernetes/test/e2e/framework" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func getGPUsAvailable(f *framework.Framework) int64 { - nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{}) - framework.ExpectNoError(err, "getting node list") - var gpusAvailable int64 - for _, node := range nodeList.Items { - gpusAvailable += node.Status.Capacity.NvidiaGPU().Value() - } - return gpusAvailable -} - -func gpusExistOnAllNodes(f *framework.Framework) bool { - nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{}) - framework.ExpectNoError(err, "getting node list") - for _, node := range nodeList.Items { - if node.Name == "kubernetes-master" { - continue - } - if node.Status.Capacity.NvidiaGPU().Value() == 0 { - return false - } - } - return true -} - -func checkIfNvidiaGPUsExistOnNode() bool { - // Cannot use `lspci` because it is not installed on all distros by default. - err := exec.Command("/bin/sh", "-c", "find /sys/devices/pci* -type f | grep vendor | xargs cat | grep 0x10de").Run() - if err != nil { - framework.Logf("check for nvidia GPUs failed. Got Error: %v", err) - return false - } - return true -} - -// Serial because the test updates kubelet configuration. -var _ = framework.KubeDescribe("GPU [Serial]", func() { - f := framework.NewDefaultFramework("gpu-test") - Context("attempt to use GPUs if available", func() { - It("setup the node and create pods to test gpus", func() { - By("ensuring that Nvidia GPUs exist on the node") - if !checkIfNvidiaGPUsExistOnNode() { - Skip("Nvidia GPUs do not exist on the node. Skipping test.") - } - By("ensuring that dynamic kubelet configuration is enabled") - enabled, err := isKubeletConfigEnabled(f) - framework.ExpectNoError(err) - if !enabled { - Skip("Dynamic Kubelet configuration is not enabled. Skipping test.") - } - - By("enabling support for GPUs") - var oldCfg *kubeletconfig.KubeletConfiguration - defer func() { - if oldCfg != nil { - framework.ExpectNoError(setKubeletConfiguration(f, oldCfg)) - } - }() - - // Enable Accelerators - oldCfg, err = getCurrentKubeletConfig() - framework.ExpectNoError(err) - newCfg := oldCfg.DeepCopy() - newCfg.FeatureGates[string(features.Accelerators)] = true - framework.ExpectNoError(setKubeletConfiguration(f, newCfg)) - - By("Waiting for GPUs to become available on the local node") - Eventually(gpusExistOnAllNodes(f), 10*time.Minute, time.Second).Should(BeTrue()) - - By("Creating a pod that will consume all GPUs") - podSuccess := makePod(getGPUsAvailable(f), "gpus-success") - podSuccess = f.PodClient().CreateSync(podSuccess) - - By("Checking the containers in the pod had restarted at-least twice successfully thereby ensuring GPUs are reused") - const minContainerRestartCount = 2 - Eventually(func() bool { - p, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(podSuccess.Name, metav1.GetOptions{}) - if err != nil { - framework.Logf("failed to get pod status: %v", err) - return false - } - if p.Status.ContainerStatuses[0].RestartCount < minContainerRestartCount { - return false - } - return true - }, time.Minute, time.Second).Should(BeTrue()) - - By("Checking if the pod outputted Success to its logs") - framework.ExpectNoError(f.PodClient().MatchContainerOutput(podSuccess.Name, podSuccess.Name, "Success")) - - By("Creating a new pod requesting a GPU and noticing that it is rejected by the Kubelet") - podFailure := makePod(1, "gpu-failure") - framework.WaitForPodCondition(f.ClientSet, f.Namespace.Name, podFailure.Name, "pod rejected", framework.PodStartTimeout, func(pod *v1.Pod) (bool, error) { - if pod.Status.Phase == v1.PodFailed { - return true, nil - - } - return false, nil - }) - - By("stopping the original Pod with GPUs") - gp := int64(0) - deleteOptions := metav1.DeleteOptions{ - GracePeriodSeconds: &gp, - } - f.PodClient().DeleteSync(podSuccess.Name, &deleteOptions, framework.DefaultPodDeletionTimeout) - - By("attempting to start the failed pod again") - f.PodClient().DeleteSync(podFailure.Name, &deleteOptions, framework.DefaultPodDeletionTimeout) - podFailure = f.PodClient().CreateSync(podFailure) - - By("Checking if the pod outputted Success to its logs") - framework.ExpectNoError(f.PodClient().MatchContainerOutput(podFailure.Name, podFailure.Name, "Success")) - }) - }) -}) - -func makePod(gpus int64, name string) *v1.Pod { - resources := v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceNvidiaGPU: *resource.NewQuantity(gpus, resource.DecimalSI), - }, - } - gpuverificationCmd := fmt.Sprintf("if [[ %d -ne $(ls /dev/ | egrep '^nvidia[0-9]+$' | wc -l) ]]; then exit 1; else echo Success; fi", gpus) - return &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Spec: v1.PodSpec{ - RestartPolicy: v1.RestartPolicyAlways, - Containers: []v1.Container{ - { - Image: busyboxImage, - Name: name, - Command: []string{"sh", "-c", gpuverificationCmd}, - Resources: resources, - }, - }, - }, - } -} diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/gubernator.sh b/vendor/k8s.io/kubernetes/test/e2e_node/gubernator.sh index 97f3da8ce..a8a11bfd7 100755 --- a/vendor/k8s.io/kubernetes/test/e2e_node/gubernator.sh +++ b/vendor/k8s.io/kubernetes/test/e2e_node/gubernator.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/hugepages_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/hugepages_test.go index a8683dc3c..98659b201 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/hugepages_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/hugepages_test.go @@ -19,7 +19,6 @@ package e2e_node import ( "fmt" "os/exec" - "path" "strconv" "strings" "time" @@ -38,14 +37,14 @@ import ( ) // makePodToVerifyHugePages returns a pod that verifies specified cgroup with hugetlb -func makePodToVerifyHugePages(cgroupName cm.CgroupName, hugePagesLimit resource.Quantity) *apiv1.Pod { +func makePodToVerifyHugePages(baseName string, hugePagesLimit resource.Quantity) *apiv1.Pod { // convert the cgroup name to its literal form cgroupFsName := "" - cgroupName = cm.CgroupName(path.Join(defaultNodeAllocatableCgroup, string(cgroupName))) + cgroupName := cm.NewCgroupName(cm.RootCgroupName, defaultNodeAllocatableCgroup, baseName) if framework.TestContext.KubeletConfig.CgroupDriver == "systemd" { - cgroupFsName = cm.ConvertCgroupNameToSystemd(cgroupName, true) + cgroupFsName = cgroupName.ToSystemd() } else { - cgroupFsName = string(cgroupName) + cgroupFsName = cgroupName.ToCgroupfs() } // this command takes the expected value and compares it against the actual value for the pod cgroup hugetlb.2MB.limit_in_bytes @@ -184,7 +183,7 @@ func runHugePagesTests(f *framework.Framework) { }) podUID := string(pod.UID) By("checking if the expected hugetlb settings were applied") - verifyPod := makePodToVerifyHugePages(cm.CgroupName("pod"+podUID), resource.MustParse("50Mi")) + verifyPod := makePodToVerifyHugePages("pod"+podUID, resource.MustParse("50Mi")) f.PodClient().Create(verifyPod) err := framework.WaitForPodSuccessInNamespace(f.ClientSet, verifyPod.Name, f.Namespace.Name) Expect(err).NotTo(HaveOccurred()) @@ -192,7 +191,7 @@ func runHugePagesTests(f *framework.Framework) { } // Serial because the test updates kubelet configuration. -var _ = SIGDescribe("HugePages [Serial] [Feature:HugePages]", func() { +var _ = SIGDescribe("HugePages [Serial] [Feature:HugePages][NodeFeature:HugePages]", func() { f := framework.NewDefaultFramework("hugepages-test") Context("With config updated with hugepages feature enabled", func() { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/image_id_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/image_id_test.go index 090eafa28..198d204c4 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/image_id_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/image_id_test.go @@ -26,7 +26,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = framework.KubeDescribe("ImageID", func() { +var _ = framework.KubeDescribe("ImageID [NodeFeature: ImageID]", func() { busyBoxImage := "k8s.gcr.io/busybox@sha256:4bdd623e848417d96127e16037743f0cd8b528c026e9175e22a84f639eca58ff" diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/image_list.go b/vendor/k8s.io/kubernetes/test/e2e_node/image_list.go index 00a35955a..d35bb5aca 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/image_list.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/image_list.go @@ -51,7 +51,7 @@ var NodeImageWhiteList = sets.NewString( imageutils.GetE2EImage(imageutils.ServeHostname), imageutils.GetE2EImage(imageutils.Netexec), imageutils.GetE2EImage(imageutils.Nonewprivs), - imageutils.GetPauseImageNameForHostArch(), + imageutils.GetPauseImageName(), framework.GetGPUDevicePluginImage(), ) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/benchmark/jenkins-benchmark.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/benchmark/jenkins-benchmark.properties deleted file mode 100644 index e03944833..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/benchmark/jenkins-benchmark.properties +++ /dev/null @@ -1,9 +0,0 @@ -GCE_HOSTS= -GCE_IMAGE_CONFIG_PATH=test/e2e_node/jenkins/benchmark/benchmark-config.yaml -GCE_ZONE=us-central1-f -GCE_PROJECT=k8s-jkns-ci-node-e2e -CLEANUP=true -GINKGO_FLAGS='--skip="\[Flaky\]"' -TEST_ARGS='--feature-gates=DynamicKubeletConfig=true' -KUBELET_ARGS='--cgroups-per-qos=true --cgroup-root=/' -PARALLELISM=1 diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/conformance/conformance-jenkins.sh b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/conformance/conformance-jenkins.sh index 422a149b1..9e8715287 100755 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/conformance/conformance-jenkins.sh +++ b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/conformance/conformance-jenkins.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/conformance/jenkins-conformance.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/conformance/jenkins-conformance.properties deleted file mode 100644 index 6c8b10bba..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/conformance/jenkins-conformance.properties +++ /dev/null @@ -1,6 +0,0 @@ -GCE_HOSTS= -GCE_IMAGE_CONFIG_PATH=test/e2e_node/jenkins/image-config.yaml -GCE_ZONE=us-central1-f -GCE_PROJECT=k8s-jkns-ci-node-e2e -CLEANUP=true -KUBELET_ARGS='--cgroups-per-qos=true --cgroup-root=/' diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/copy-e2e-image.sh b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/copy-e2e-image.sh index 4389f5816..18ff7c631 100755 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/copy-e2e-image.sh +++ b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/copy-e2e-image.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/docker_validation/cos-docker-validation.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/docker_validation/cos-docker-validation.properties deleted file mode 100644 index b5a996d27..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/docker_validation/cos-docker-validation.properties +++ /dev/null @@ -1,15 +0,0 @@ -GCI_IMAGE_PROJECT=container-vm-image-staging -GCI_IMAGE_FAMILY=gci-next-canary -GCI_IMAGE=$(gcloud compute images describe-from-family ${GCI_IMAGE_FAMILY} --project=${GCI_IMAGE_PROJECT} --format="value(name)") -GCI_CLOUD_INIT=test/e2e_node/jenkins/gci-init.yaml - -GCE_HOSTS= -GCE_IMAGES=${GCI_IMAGE} -GCE_IMAGE_PROJECT=${GCI_IMAGE_PROJECT} -GCE_ZONE=us-central1-f -GCE_PROJECT=node-cos-docker-validation -# user-data is the GCI cloud init config file. -GCE_INSTANCE_METADATA="user-data<${GCI_CLOUD_INIT},gci-update-strategy=update_disabled" -CLEANUP=true -GINKGO_FLAGS='--skip="\[Flaky\]|\[Serial\]"' -TIMEOUT=1h diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/docker_validation/jenkins-perf.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/docker_validation/jenkins-perf.properties deleted file mode 100644 index 2dce6b2e0..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/docker_validation/jenkins-perf.properties +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -GCI_IMAGE_PROJECT=container-vm-image-staging -GCI_IMAGE_FAMILY=gci-canary-test -GCI_IMAGE=$(gcloud compute images describe-from-family ${GCI_IMAGE_FAMILY} --project=${GCI_IMAGE_PROJECT} --format="value(name)") -DOCKER_VERSION=$(curl -fsSL --retry 3 https://api.github.com/repos/docker/docker/releases | tac | tac | grep -m 1 "\"tag_name\"\:" | grep -Eo "[0-9\.rc-]+") -GCI_CLOUD_INIT=test/e2e_node/jenkins/gci-init.yaml - -# Render the test config file -GCE_IMAGE_CONFIG_PATH=`mktemp` -CONFIG_FILE=test/e2e_node/jenkins/docker_validation/perf-config.yaml -cp $CONFIG_FILE $GCE_IMAGE_CONFIG_PATH -sed -i -e "s@{{IMAGE}}@${GCI_IMAGE}@g" $GCE_IMAGE_CONFIG_PATH -sed -i -e "s@{{IMAGE_PROJECT}}@${GCI_IMAGE_PROJECT}@g" $GCE_IMAGE_CONFIG_PATH -sed -i -e "s@{{METADATA}}@user-data<${GCI_CLOUD_INIT},gci-docker-version=${DOCKER_VERSION},gci-update-strategy=update_disabled@g" $GCE_IMAGE_CONFIG_PATH - -GCE_HOSTS= -GCE_ZONE=us-central1-f -GCE_PROJECT=node-cos-docker-validation-ci -CLEANUP=true -GINKGO_FLAGS='--skip="\[Flaky\]"' -PARALLELISM=1 diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/docker_validation/jenkins-validation.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/docker_validation/jenkins-validation.properties deleted file mode 100644 index 7b6f6e4e2..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/docker_validation/jenkins-validation.properties +++ /dev/null @@ -1,17 +0,0 @@ -GCI_IMAGE_PROJECT=container-vm-image-staging -GCI_IMAGE_FAMILY=gci-canary-test -GCI_IMAGE=$(gcloud compute images describe-from-family ${GCI_IMAGE_FAMILY} --project=${GCI_IMAGE_PROJECT} --format="value(name)") -DOCKER_VERSION=$(curl -fsSL --retry 3 https://api.github.com/repos/docker/docker/releases | tac | tac | grep -m 1 "\"tag_name\"\:" | grep -Eo "[0-9\.rc-]+") -GCI_CLOUD_INIT=test/e2e_node/jenkins/gci-init.yaml - -GCE_HOSTS= -GCE_IMAGES=${GCI_IMAGE} -GCE_IMAGE_PROJECT=${GCI_IMAGE_PROJECT} -GCE_ZONE=us-central1-f -GCE_PROJECT=node-cos-docker-validation-ci -# user-data is the GCI cloud init config file. -# gci-docker-version specifies docker version in GCI image. -GCE_INSTANCE_METADATA="user-data<${GCI_CLOUD_INIT},gci-docker-version=${DOCKER_VERSION},gci-update-strategy=update_disabled" -CLEANUP=true -GINKGO_FLAGS='--skip="\[Flaky\]|\[Serial\]"' -TIMEOUT=1h diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/e2e-node-jenkins.sh b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/e2e-node-jenkins.sh index c0f83e59e..a1caae4ad 100755 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/e2e-node-jenkins.sh +++ b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/e2e-node-jenkins.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-ci-ubuntu.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-ci-ubuntu.properties deleted file mode 100644 index f52e39463..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-ci-ubuntu.properties +++ /dev/null @@ -1,13 +0,0 @@ -GCE_HOSTS= -GCE_IMAGE_CONFIG_PATH= -GCE_IMAGES=ubuntu-gke-1604-xenial-v20170420-1 -GCE_IMAGE_PROJECT=ubuntu-os-gke-cloud -GCE_ZONE=us-central1-f -GCE_PROJECT=k8s-jkns-ubuntu-node -CLEANUP=true -GINKGO_FLAGS='--skip="\[Flaky\]|\[Serial\]"' -TEST_ARGS='--generate-kubelet-config-file=true' -KUBELET_ARGS='' -TIMEOUT=1h -# Use the system spec defined in test/e2e_node/system/specs/gke.yaml. -SYSTEM_SPEC_NAME=gke diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-ci.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-ci.properties deleted file mode 100644 index 9e8c8a3b4..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-ci.properties +++ /dev/null @@ -1,9 +0,0 @@ -GCE_HOSTS= -GCE_IMAGE_CONFIG_PATH=test/e2e_node/jenkins/image-config.yaml -GCE_ZONE=us-central1-f -GCE_PROJECT=k8s-jkns-ci-node-e2e -CLEANUP=true -GINKGO_FLAGS='--skip="\[Flaky\]|\[Serial\]"' -TEST_ARGS='--generate-kubelet-config-file=true' -KUBELET_ARGS='' -TIMEOUT=1h diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-flaky.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-flaky.properties deleted file mode 100644 index 33b667328..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-flaky.properties +++ /dev/null @@ -1,11 +0,0 @@ -GCE_HOSTS= -GCE_IMAGE_CONFIG_PATH=test/e2e_node/jenkins/image-config.yaml -GCE_ZONE=us-central1-f -GCE_PROJECT=k8s-jkns-ci-node-e2e -CLEANUP=true -GINKGO_FLAGS='--focus="\[Flaky\]"' -TEST_ARGS='--feature-gates=DynamicKubeletConfig=true,LocalStorageCapacityIsolation=true,PodPriority=true --generate-kubelet-config-file=true' -KUBELET_ARGS='' -PARALLELISM=1 -TIMEOUT=3h - diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-pull.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-pull.properties deleted file mode 100644 index d102bba5a..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-pull.properties +++ /dev/null @@ -1,9 +0,0 @@ -GCE_HOSTS= -GCE_IMAGE_CONFIG_PATH=test/e2e_node/jenkins/image-config.yaml -GCE_ZONE=us-central1-f -GCE_PROJECT=k8s-jkns-pr-node-e2e -CLEANUP=true -GINKGO_FLAGS='--skip="\[Flaky\]|\[Slow\]|\[Serial\]" --flakeAttempts=2' -TEST_ARGS='--generate-kubelet-config-file=true' -KUBELET_ARGS='' - diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-serial-ubuntu.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-serial-ubuntu.properties deleted file mode 100644 index 28b6ca81a..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-serial-ubuntu.properties +++ /dev/null @@ -1,14 +0,0 @@ -GCE_HOSTS= -GCE_IMAGE_CONFIG_PATH= -GCE_IMAGES=ubuntu-gke-1604-xenial-v20170420-1 -GCE_IMAGE_PROJECT=ubuntu-os-gke-cloud -GCE_ZONE=us-central1-f -GCE_PROJECT=k8s-jkns-ubuntu-node-serial -CLEANUP=true -GINKGO_FLAGS='--focus="\[Serial\]" --skip="\[Flaky\]|\[Benchmark\]"' -TEST_ARGS='--feature-gates=DynamicKubeletConfig=true --generate-kubelet-config-file=true' -KUBELET_ARGS='' -PARALLELISM=1 -TIMEOUT=3h -# Use the system spec defined at test/e2e_node/system/specs/gke.yaml. -SYSTEM_SPEC_NAME=gke diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-serial.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-serial.properties deleted file mode 100644 index 72d323b0a..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/jenkins-serial.properties +++ /dev/null @@ -1,10 +0,0 @@ -GCE_HOSTS= -GCE_IMAGE_CONFIG_PATH=test/e2e_node/jenkins/image-config-serial.yaml -GCE_ZONE=us-west1-b -GCE_PROJECT=k8s-jkns-ci-node-e2e -CLEANUP=true -GINKGO_FLAGS='--focus="\[Serial\]" --skip="\[Flaky\]|\[Benchmark\]"' -TEST_ARGS='--feature-gates=DynamicKubeletConfig=true --generate-kubelet-config-file=true' -KUBELET_ARGS='' -PARALLELISM=1 -TIMEOUT=3h diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/template.properties b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/template.properties deleted file mode 100644 index bdc7cf6f5..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/template.properties +++ /dev/null @@ -1,25 +0,0 @@ -# Copy this file to your home directory and modify -# User used on the gce instances to run the test. -GCE_USER= -# Path to a yaml or json file describing images to run or empty -GCE_IMAGE_CONFIG_PATH= -# Names of gce hosts to test against (must be resolvable) or empty -GCE_HOSTS= -# Comma-separated names of gce images to test or empty (one or more of GCE_IMAGE_CONFIG_PATH, GCE_IMAGES, GCE_HOSTS is required) -GCE_IMAGES= -# Gce zone to use - required when using GCE_IMAGES -GCE_ZONE= -# Gce project to use for creating instances -# required when using GCE_IMAGES or GCE_IMAGE_CONFIG_PATH -GCE_PROJECT= -# Gce project to use for GCE_IMAGES -# required when using GCE_IMAGES -GCE_IMAGE_PROJECT= -# If true, delete instances created from GCE_IMAGES/GCE_IMAGE_CONFIG_PATH and files copied to GCE_HOSTS -CLEANUP=true -# KUBELET_ARGS are the arguments passed to kubelet. The args will override corresponding default kubelet -# setting in the test framework and --kubelet-flags in TEST_ARGS. -# If true QoS Cgroup Hierarchy is created and tests specifc to the cgroup hierarchy run -KUBELET_ARGS='--cgroups-per-qos=true --cgroup-root=/' -# TEST_ARGS are args passed to node e2e test. -TEST_ARGS='' diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/ubuntu-14.04-nvidia-install.sh b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/ubuntu-14.04-nvidia-install.sh index 6d6d27719..f83e53c18 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/ubuntu-14.04-nvidia-install.sh +++ b/vendor/k8s.io/kubernetes/test/e2e_node/jenkins/ubuntu-14.04-nvidia-install.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/kubelet_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/kubelet_test.go index 9347d2d18..3419eb250 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/kubelet_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/kubelet_test.go @@ -39,7 +39,7 @@ var _ = framework.KubeDescribe("Kubelet", func() { }) Context("when scheduling a busybox command in a pod", func() { podName := "busybox-scheduling-" + string(uuid.NewUUID()) - framework.ConformanceIt("it should print the output to logs", func() { + framework.ConformanceIt("it should print the output to logs [NodeConformance]", func() { podClient.CreateSync(&v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: podName, @@ -92,7 +92,7 @@ var _ = framework.KubeDescribe("Kubelet", func() { }) }) - It("should have an error terminated reason", func() { + It("should have an error terminated reason [NodeConformance]", func() { Eventually(func() error { podData, err := podClient.Get(podName, metav1.GetOptions{}) if err != nil { @@ -112,7 +112,7 @@ var _ = framework.KubeDescribe("Kubelet", func() { }, time.Minute, time.Second*4).Should(BeNil()) }) - It("should be possible to delete", func() { + It("should be possible to delete [NodeConformance]", func() { err := podClient.Delete(podName, &metav1.DeleteOptions{}) Expect(err).To(BeNil(), fmt.Sprintf("Error deleting Pod %v", err)) }) @@ -120,7 +120,7 @@ var _ = framework.KubeDescribe("Kubelet", func() { Context("when scheduling a busybox Pod with hostAliases", func() { podName := "busybox-host-aliases" + string(uuid.NewUUID()) - It("it should write entries to /etc/hosts", func() { + It("it should write entries to /etc/hosts [NodeConformance]", func() { podClient.CreateSync(&v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: podName, @@ -164,7 +164,7 @@ var _ = framework.KubeDescribe("Kubelet", func() { }) Context("when scheduling a read only busybox container", func() { podName := "busybox-readonly-fs" + string(uuid.NewUUID()) - framework.ConformanceIt("it should not write to root filesystem", func() { + framework.ConformanceIt("it should not write to root filesystem [NodeConformance]", func() { isReadOnly := true podClient.CreateSync(&v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/lifecycle_hook_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/lifecycle_hook_test.go index f9e765846..5082d9df6 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/lifecycle_hook_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/lifecycle_hook_test.go @@ -84,7 +84,7 @@ var _ = framework.KubeDescribe("Container Lifecycle Hook", func() { }, preStopWaitTimeout, podCheckInterval).Should(BeNil()) } } - framework.ConformanceIt("should execute poststart exec hook properly", func() { + framework.ConformanceIt("should execute poststart exec hook properly [NodeConformance]", func() { lifecycle := &v1.Lifecycle{ PostStart: &v1.Handler{ Exec: &v1.ExecAction{ @@ -95,7 +95,7 @@ var _ = framework.KubeDescribe("Container Lifecycle Hook", func() { podWithHook := getPodWithHook("pod-with-poststart-exec-hook", imageutils.GetE2EImage(imageutils.Hostexec), lifecycle) testPodWithHook(podWithHook) }) - framework.ConformanceIt("should execute prestop exec hook properly", func() { + framework.ConformanceIt("should execute prestop exec hook properly [NodeConformance]", func() { lifecycle := &v1.Lifecycle{ PreStop: &v1.Handler{ Exec: &v1.ExecAction{ @@ -106,7 +106,7 @@ var _ = framework.KubeDescribe("Container Lifecycle Hook", func() { podWithHook := getPodWithHook("pod-with-prestop-exec-hook", imageutils.GetE2EImage(imageutils.Hostexec), lifecycle) testPodWithHook(podWithHook) }) - framework.ConformanceIt("should execute poststart http hook properly", func() { + framework.ConformanceIt("should execute poststart http hook properly [NodeConformance]", func() { lifecycle := &v1.Lifecycle{ PostStart: &v1.Handler{ HTTPGet: &v1.HTTPGetAction{ @@ -116,10 +116,10 @@ var _ = framework.KubeDescribe("Container Lifecycle Hook", func() { }, }, } - podWithHook := getPodWithHook("pod-with-poststart-http-hook", imageutils.GetPauseImageNameForHostArch(), lifecycle) + podWithHook := getPodWithHook("pod-with-poststart-http-hook", imageutils.GetPauseImageName(), lifecycle) testPodWithHook(podWithHook) }) - framework.ConformanceIt("should execute prestop http hook properly", func() { + framework.ConformanceIt("should execute prestop http hook properly [NodeConformance]", func() { lifecycle := &v1.Lifecycle{ PreStop: &v1.Handler{ HTTPGet: &v1.HTTPGetAction{ @@ -129,7 +129,7 @@ var _ = framework.KubeDescribe("Container Lifecycle Hook", func() { }, }, } - podWithHook := getPodWithHook("pod-with-prestop-http-hook", imageutils.GetPauseImageNameForHostArch(), lifecycle) + podWithHook := getPodWithHook("pod-with-prestop-http-hook", imageutils.GetPauseImageName(), lifecycle) testPodWithHook(podWithHook) }) }) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/log_path_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/log_path_test.go index 2c01d8ac8..c993f1217 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/log_path_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/log_path_test.go @@ -35,7 +35,7 @@ const ( checkContName = "checker-container" ) -var _ = framework.KubeDescribe("ContainerLogPath", func() { +var _ = framework.KubeDescribe("ContainerLogPath [NodeConformance]", func() { f := framework.NewDefaultFramework("kubelet-container-log-path") Describe("Pod with a container", func() { Context("printed log to stdout", func() { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/mirror_pod_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/mirror_pod_test.go index 34a028b23..9e3118622 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/mirror_pod_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/mirror_pod_test.go @@ -57,14 +57,14 @@ var _ = framework.KubeDescribe("MirrorPod", func() { return checkMirrorPodRunning(f.ClientSet, mirrorPodName, ns) }, 2*time.Minute, time.Second*4).Should(BeNil()) }) - framework.ConformanceIt("should be updated when static pod updated", func() { + framework.ConformanceIt("should be updated when static pod updated [NodeConformance]", func() { By("get mirror pod uid") pod, err := f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{}) Expect(err).ShouldNot(HaveOccurred()) uid := pod.UID By("update the static pod container image") - image := imageutils.GetPauseImageNameForHostArch() + image := imageutils.GetPauseImageName() err = createStaticPod(podPath, staticPodName, ns, image, v1.RestartPolicyAlways) Expect(err).ShouldNot(HaveOccurred()) @@ -79,7 +79,7 @@ var _ = framework.KubeDescribe("MirrorPod", func() { Expect(len(pod.Spec.Containers)).Should(Equal(1)) Expect(pod.Spec.Containers[0].Image).Should(Equal(image)) }) - framework.ConformanceIt("should be recreated when mirror pod gracefully deleted", func() { + framework.ConformanceIt("should be recreated when mirror pod gracefully deleted [NodeConformance]", func() { By("get mirror pod uid") pod, err := f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{}) Expect(err).ShouldNot(HaveOccurred()) @@ -94,7 +94,7 @@ var _ = framework.KubeDescribe("MirrorPod", func() { return checkMirrorPodRecreatedAndRunnig(f.ClientSet, mirrorPodName, ns, uid) }, 2*time.Minute, time.Second*4).Should(BeNil()) }) - framework.ConformanceIt("should be recreated when mirror pod forcibly deleted", func() { + framework.ConformanceIt("should be recreated when mirror pod forcibly deleted [NodeConformance]", func() { By("get mirror pod uid") pod, err := f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{}) Expect(err).ShouldNot(HaveOccurred()) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/node_container_manager_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/node_container_manager_test.go index c31bbc96d..58223e084 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/node_container_manager_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/node_container_manager_test.go @@ -21,7 +21,6 @@ package e2e_node import ( "fmt" "io/ioutil" - "path" "path/filepath" "strconv" "strings" @@ -39,7 +38,7 @@ import ( ) func setDesiredConfiguration(initialConfig *kubeletconfig.KubeletConfiguration) { - initialConfig.EnforceNodeAllocatable = []string{"pods", "kube-reserved", "system-reserved"} + initialConfig.EnforceNodeAllocatable = []string{"pods", kubeReservedCgroup, systemReservedCgroup} initialConfig.SystemReserved = map[string]string{ string(v1.ResourceCPU): "100m", string(v1.ResourceMemory): "100Mi", @@ -57,7 +56,7 @@ func setDesiredConfiguration(initialConfig *kubeletconfig.KubeletConfiguration) var _ = framework.KubeDescribe("Node Container Manager [Serial]", func() { f := framework.NewDefaultFramework("node-container-manager") - Describe("Validate Node Allocatable", func() { + Describe("Validate Node Allocatable [NodeFeature:NodeAllocatable]", func() { It("set's up the node and runs the test", func() { framework.ExpectNoError(runTest(f)) }) @@ -99,8 +98,8 @@ func getAllocatableLimits(cpu, memory string, capacity v1.ResourceList) (*resour } const ( - kubeReservedCgroup = "/kube_reserved" - systemReservedCgroup = "/system_reserved" + kubeReservedCgroup = "kube-reserved" + systemReservedCgroup = "system-reserved" ) func createIfNotExists(cm cm.CgroupManager, cgroupConfig *cm.CgroupConfig) error { @@ -115,13 +114,13 @@ func createIfNotExists(cm cm.CgroupManager, cgroupConfig *cm.CgroupConfig) error func createTemporaryCgroupsForReservation(cgroupManager cm.CgroupManager) error { // Create kube reserved cgroup cgroupConfig := &cm.CgroupConfig{ - Name: cm.CgroupName(kubeReservedCgroup), + Name: cm.NewCgroupName(cm.RootCgroupName, kubeReservedCgroup), } if err := createIfNotExists(cgroupManager, cgroupConfig); err != nil { return err } // Create system reserved cgroup - cgroupConfig.Name = cm.CgroupName(systemReservedCgroup) + cgroupConfig.Name = cm.NewCgroupName(cm.RootCgroupName, systemReservedCgroup) return createIfNotExists(cgroupManager, cgroupConfig) } @@ -129,12 +128,12 @@ func createTemporaryCgroupsForReservation(cgroupManager cm.CgroupManager) error func destroyTemporaryCgroupsForReservation(cgroupManager cm.CgroupManager) error { // Create kube reserved cgroup cgroupConfig := &cm.CgroupConfig{ - Name: cm.CgroupName(kubeReservedCgroup), + Name: cm.NewCgroupName(cm.RootCgroupName, kubeReservedCgroup), } if err := cgroupManager.Destroy(cgroupConfig); err != nil { return err } - cgroupConfig.Name = cm.CgroupName(systemReservedCgroup) + cgroupConfig.Name = cm.NewCgroupName(cm.RootCgroupName, systemReservedCgroup) return cgroupManager.Destroy(cgroupConfig) } @@ -173,8 +172,9 @@ func runTest(f *framework.Framework) error { // Set new config and current config. currentConfig := newCfg - expectedNAPodCgroup := path.Join(currentConfig.CgroupRoot, "kubepods") - if !cgroupManager.Exists(cm.CgroupName(expectedNAPodCgroup)) { + expectedNAPodCgroup := cm.ParseCgroupfsToCgroupName(currentConfig.CgroupRoot) + expectedNAPodCgroup = cm.NewCgroupName(expectedNAPodCgroup, "kubepods") + if !cgroupManager.Exists(expectedNAPodCgroup) { return fmt.Errorf("Expected Node Allocatable Cgroup Does not exist") } // TODO: Update cgroupManager to expose a Status interface to get current Cgroup Settings. @@ -218,30 +218,32 @@ func runTest(f *framework.Framework) error { return nil }, time.Minute, 5*time.Second).Should(BeNil()) - if !cgroupManager.Exists(cm.CgroupName(kubeReservedCgroup)) { + kubeReservedCgroupName := cm.NewCgroupName(cm.RootCgroupName, kubeReservedCgroup) + if !cgroupManager.Exists(kubeReservedCgroupName) { return fmt.Errorf("Expected kube reserved cgroup Does not exist") } // Expect CPU shares on kube reserved cgroup to equal it's reservation which is `100m`. kubeReservedCPU := resource.MustParse(currentConfig.KubeReserved[string(v1.ResourceCPU)]) - if err := expectFileValToEqual(filepath.Join(subsystems.MountPoints["cpu"], kubeReservedCgroup, "cpu.shares"), int64(cm.MilliCPUToShares(kubeReservedCPU.MilliValue())), 10); err != nil { + if err := expectFileValToEqual(filepath.Join(subsystems.MountPoints["cpu"], cgroupManager.Name(kubeReservedCgroupName), "cpu.shares"), int64(cm.MilliCPUToShares(kubeReservedCPU.MilliValue())), 10); err != nil { return err } // Expect Memory limit kube reserved cgroup to equal configured value `100Mi`. kubeReservedMemory := resource.MustParse(currentConfig.KubeReserved[string(v1.ResourceMemory)]) - if err := expectFileValToEqual(filepath.Join(subsystems.MountPoints["memory"], kubeReservedCgroup, "memory.limit_in_bytes"), kubeReservedMemory.Value(), 0); err != nil { + if err := expectFileValToEqual(filepath.Join(subsystems.MountPoints["memory"], cgroupManager.Name(kubeReservedCgroupName), "memory.limit_in_bytes"), kubeReservedMemory.Value(), 0); err != nil { return err } - if !cgroupManager.Exists(cm.CgroupName(systemReservedCgroup)) { + systemReservedCgroupName := cm.NewCgroupName(cm.RootCgroupName, systemReservedCgroup) + if !cgroupManager.Exists(systemReservedCgroupName) { return fmt.Errorf("Expected system reserved cgroup Does not exist") } // Expect CPU shares on system reserved cgroup to equal it's reservation which is `100m`. systemReservedCPU := resource.MustParse(currentConfig.SystemReserved[string(v1.ResourceCPU)]) - if err := expectFileValToEqual(filepath.Join(subsystems.MountPoints["cpu"], systemReservedCgroup, "cpu.shares"), int64(cm.MilliCPUToShares(systemReservedCPU.MilliValue())), 10); err != nil { + if err := expectFileValToEqual(filepath.Join(subsystems.MountPoints["cpu"], cgroupManager.Name(systemReservedCgroupName), "cpu.shares"), int64(cm.MilliCPUToShares(systemReservedCPU.MilliValue())), 10); err != nil { return err } // Expect Memory limit on node allocatable cgroup to equal allocatable. systemReservedMemory := resource.MustParse(currentConfig.SystemReserved[string(v1.ResourceMemory)]) - if err := expectFileValToEqual(filepath.Join(subsystems.MountPoints["memory"], systemReservedCgroup, "memory.limit_in_bytes"), systemReservedMemory.Value(), 0); err != nil { + if err := expectFileValToEqual(filepath.Join(subsystems.MountPoints["memory"], cgroupManager.Name(systemReservedCgroupName), "memory.limit_in_bytes"), systemReservedMemory.Value(), 0); err != nil { return err } return nil diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/node_problem_detector_linux.go b/vendor/k8s.io/kubernetes/test/e2e_node/node_problem_detector_linux.go index 3baf32873..64aa7ac72 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/node_problem_detector_linux.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/node_problem_detector_linux.go @@ -40,7 +40,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = framework.KubeDescribe("NodeProblemDetector", func() { +var _ = framework.KubeDescribe("NodeProblemDetector [NodeFeature:NodeProblemDetector]", func() { const ( pollInterval = 1 * time.Second pollConsistent = 5 * time.Second diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/pods_container_manager_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/pods_container_manager_test.go index 23142bdea..128860b17 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/pods_container_manager_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/pods_container_manager_test.go @@ -17,7 +17,7 @@ limitations under the License. package e2e_node import ( - "path" + "strings" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/test/e2e/framework" + imageutils "k8s.io/kubernetes/test/utils/image" "github.com/golang/glog" . "github.com/onsi/ginkgo" @@ -53,8 +54,6 @@ func getResourceRequirements(requests, limits v1.ResourceList) v1.ResourceRequir } const ( - // Kubelet internal cgroup name for node allocatable cgroup. - defaultNodeAllocatableCgroup = "kubepods" // Kubelet internal cgroup name for burstable tier burstableCgroup = "burstable" // Kubelet internal cgroup name for besteffort tier @@ -62,17 +61,15 @@ const ( ) // makePodToVerifyCgroups returns a pod that verifies the existence of the specified cgroups. -func makePodToVerifyCgroups(cgroupNames []cm.CgroupName) *v1.Pod { +func makePodToVerifyCgroups(cgroupNames []string) *v1.Pod { // convert the names to their literal cgroupfs forms... cgroupFsNames := []string{} - for _, cgroupName := range cgroupNames { + rootCgroupName := cm.NewCgroupName(cm.RootCgroupName, defaultNodeAllocatableCgroup) + for _, baseName := range cgroupNames { // Add top level cgroup used to enforce node allocatable. - cgroupName = cm.CgroupName(path.Join(defaultNodeAllocatableCgroup, string(cgroupName))) - if framework.TestContext.KubeletConfig.CgroupDriver == "systemd" { - cgroupFsNames = append(cgroupFsNames, cm.ConvertCgroupNameToSystemd(cgroupName, true)) - } else { - cgroupFsNames = append(cgroupFsNames, string(cgroupName)) - } + cgroupComponents := strings.Split(baseName, "/") + cgroupName := cm.NewCgroupName(rootCgroupName, cgroupComponents...) + cgroupFsNames = append(cgroupFsNames, toCgroupFsName(cgroupName)) } glog.Infof("expecting %v cgroups to be found", cgroupFsNames) // build the pod command to either verify cgroups exist @@ -115,11 +112,10 @@ func makePodToVerifyCgroups(cgroupNames []cm.CgroupName) *v1.Pod { } // makePodToVerifyCgroupRemoved verfies the specified cgroup does not exist. -func makePodToVerifyCgroupRemoved(cgroupName cm.CgroupName) *v1.Pod { - cgroupFsName := string(cgroupName) - if framework.TestContext.KubeletConfig.CgroupDriver == "systemd" { - cgroupFsName = cm.ConvertCgroupNameToSystemd(cm.CgroupName(cgroupName), true) - } +func makePodToVerifyCgroupRemoved(baseName string) *v1.Pod { + components := strings.Split(baseName, "/") + cgroupName := cm.NewCgroupName(cm.RootCgroupName, components...) + cgroupFsName := toCgroupFsName(cgroupName) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "pod" + string(uuid.NewUUID()), @@ -156,11 +152,11 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { f := framework.NewDefaultFramework("kubelet-cgroup-manager") Describe("QOS containers", func() { Context("On enabling QOS cgroup hierarchy", func() { - It("Top level QoS containers should have been created", func() { + It("Top level QoS containers should have been created [NodeConformance]", func() { if !framework.TestContext.KubeletConfig.CgroupsPerQOS { return } - cgroupsToVerify := []cm.CgroupName{cm.CgroupName(burstableCgroup), cm.CgroupName(bestEffortCgroup)} + cgroupsToVerify := []string{burstableCgroup, bestEffortCgroup} pod := makePodToVerifyCgroups(cgroupsToVerify) f.PodClient().Create(pod) err := framework.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name) @@ -169,7 +165,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { }) }) - Describe("Pod containers", func() { + Describe("Pod containers [NodeConformance]", func() { Context("On scheduling a Guaranteed Pod", func() { It("Pod containers should have been created under the cgroup-root", func() { if !framework.TestContext.KubeletConfig.CgroupsPerQOS { @@ -188,7 +184,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { Spec: v1.PodSpec{ Containers: []v1.Container{ { - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Name: "container" + string(uuid.NewUUID()), Resources: getResourceRequirements(getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")), }, @@ -198,7 +194,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { podUID = string(guaranteedPod.UID) }) By("Checking if the pod cgroup was created", func() { - cgroupsToVerify := []cm.CgroupName{cm.CgroupName("pod" + podUID)} + cgroupsToVerify := []string{"pod" + podUID} pod := makePodToVerifyCgroups(cgroupsToVerify) f.PodClient().Create(pod) err := framework.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name) @@ -207,7 +203,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { By("Checking if the pod cgroup was deleted", func() { gp := int64(1) Expect(f.PodClient().Delete(guaranteedPod.Name, &metav1.DeleteOptions{GracePeriodSeconds: &gp})).NotTo(HaveOccurred()) - pod := makePodToVerifyCgroupRemoved(cm.CgroupName("pod" + podUID)) + pod := makePodToVerifyCgroupRemoved("pod" + podUID) f.PodClient().Create(pod) err := framework.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name) Expect(err).NotTo(HaveOccurred()) @@ -232,7 +228,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { Spec: v1.PodSpec{ Containers: []v1.Container{ { - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Name: "container" + string(uuid.NewUUID()), Resources: getResourceRequirements(getResourceList("", ""), getResourceList("", "")), }, @@ -242,7 +238,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { podUID = string(bestEffortPod.UID) }) By("Checking if the pod cgroup was created", func() { - cgroupsToVerify := []cm.CgroupName{cm.CgroupName("besteffort/pod" + podUID)} + cgroupsToVerify := []string{"besteffort/pod" + podUID} pod := makePodToVerifyCgroups(cgroupsToVerify) f.PodClient().Create(pod) err := framework.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name) @@ -251,7 +247,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { By("Checking if the pod cgroup was deleted", func() { gp := int64(1) Expect(f.PodClient().Delete(bestEffortPod.Name, &metav1.DeleteOptions{GracePeriodSeconds: &gp})).NotTo(HaveOccurred()) - pod := makePodToVerifyCgroupRemoved(cm.CgroupName("besteffort/pod" + podUID)) + pod := makePodToVerifyCgroupRemoved("besteffort/pod" + podUID) f.PodClient().Create(pod) err := framework.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name) Expect(err).NotTo(HaveOccurred()) @@ -276,7 +272,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { Spec: v1.PodSpec{ Containers: []v1.Container{ { - Image: framework.GetPauseImageName(f.ClientSet), + Image: imageutils.GetPauseImageName(), Name: "container" + string(uuid.NewUUID()), Resources: getResourceRequirements(getResourceList("100m", "100Mi"), getResourceList("200m", "200Mi")), }, @@ -286,7 +282,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { podUID = string(burstablePod.UID) }) By("Checking if the pod cgroup was created", func() { - cgroupsToVerify := []cm.CgroupName{cm.CgroupName("burstable/pod" + podUID)} + cgroupsToVerify := []string{"burstable/pod" + podUID} pod := makePodToVerifyCgroups(cgroupsToVerify) f.PodClient().Create(pod) err := framework.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name) @@ -295,7 +291,7 @@ var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() { By("Checking if the pod cgroup was deleted", func() { gp := int64(1) Expect(f.PodClient().Delete(burstablePod.Name, &metav1.DeleteOptions{GracePeriodSeconds: &gp})).NotTo(HaveOccurred()) - pod := makePodToVerifyCgroupRemoved(cm.CgroupName("burstable/pod" + podUID)) + pod := makePodToVerifyCgroupRemoved("burstable/pod" + podUID) f.PodClient().Create(pod) err := framework.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name) Expect(err).NotTo(HaveOccurred()) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/remote/BUILD b/vendor/k8s.io/kubernetes/test/e2e_node/remote/BUILD index 457d8c26f..8c669b906 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/remote/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e_node/remote/BUILD @@ -19,6 +19,7 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e_node/remote", deps = [ "//test/e2e_node/builder:go_default_library", + "//test/utils:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/remote/cadvisor_e2e.go b/vendor/k8s.io/kubernetes/test/e2e_node/remote/cadvisor_e2e.go index 28668a899..8bdb567d0 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/remote/cadvisor_e2e.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/remote/cadvisor_e2e.go @@ -23,8 +23,7 @@ import ( "time" "github.com/golang/glog" - - "k8s.io/kubernetes/test/e2e_node/builder" + "k8s.io/kubernetes/test/utils" ) // CAdvisorE2ERemote contains the specific functions in the cadvisor e2e test suite. @@ -37,7 +36,7 @@ func InitCAdvisorE2ERemote() TestSuite { // SetupTestPackage implements TestSuite.SetupTestPackage func (n *CAdvisorE2ERemote) SetupTestPackage(tardir, systemSpecName string) error { - cadvisorRootDir, err := builder.GetCAdvisorRootDir() + cadvisorRootDir, err := utils.GetCAdvisorRootDir() if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/remote/node_conformance.go b/vendor/k8s.io/kubernetes/test/e2e_node/remote/node_conformance.go index df9ceda7e..9c78ae308 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/remote/node_conformance.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/remote/node_conformance.go @@ -28,6 +28,7 @@ import ( "github.com/golang/glog" "k8s.io/kubernetes/test/e2e_node/builder" + "k8s.io/kubernetes/test/utils" ) // ConformanceRemote contains the specific functions in the node conformance test suite. @@ -39,7 +40,7 @@ func InitConformanceRemote() TestSuite { // getConformanceDirectory gets node conformance test build directory. func getConformanceDirectory() (string, error) { - k8sRoot, err := builder.GetK8sRootDir() + k8sRoot, err := utils.GetK8sRootDir() if err != nil { return "", err } @@ -106,7 +107,7 @@ func (c *ConformanceRemote) SetupTestPackage(tardir, systemSpecName string) erro } // Make sure we can find the newly built binaries - buildOutputDir, err := builder.GetK8sBuildOutputDir() + buildOutputDir, err := utils.GetK8sBuildOutputDir() if err != nil { return fmt.Errorf("failed to locate kubernetes build output directory %v", err) } diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/remote/node_e2e.go b/vendor/k8s.io/kubernetes/test/e2e_node/remote/node_e2e.go index 00056aa1c..d54b0d94b 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/remote/node_e2e.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/remote/node_e2e.go @@ -27,6 +27,7 @@ import ( "github.com/golang/glog" "k8s.io/kubernetes/test/e2e_node/builder" + "k8s.io/kubernetes/test/utils" ) const ( @@ -49,12 +50,12 @@ func (n *NodeE2ERemote) SetupTestPackage(tardir, systemSpecName string) error { } // Make sure we can find the newly built binaries - buildOutputDir, err := builder.GetK8sBuildOutputDir() + buildOutputDir, err := utils.GetK8sBuildOutputDir() if err != nil { return fmt.Errorf("failed to locate kubernetes build output directory: %v", err) } - rootDir, err := builder.GetK8sRootDir() + rootDir, err := utils.GetK8sRootDir() if err != nil { return fmt.Errorf("failed to locate kubernetes root directory: %v", err) } diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/remote/remote.go b/vendor/k8s.io/kubernetes/test/e2e_node/remote/remote.go index c54b35ec6..746899f8b 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/remote/remote.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/remote/remote.go @@ -23,6 +23,8 @@ import ( "os" "os/exec" "path/filepath" + "regexp" + "strings" "time" "github.com/golang/glog" @@ -66,7 +68,7 @@ func CreateTestArchive(suite TestSuite, systemSpecName string) (string, error) { func RunRemote(suite TestSuite, archive string, host string, cleanup bool, imageDesc, junitFilePrefix string, testArgs string, ginkgoArgs string, systemSpecName string) (string, bool, error) { // Create the temp staging directory glog.V(2).Infof("Staging test binaries on %q", host) - workspace := fmt.Sprintf("/tmp/node-e2e-%s", getTimestamp()) + workspace := newWorkspaceDir() // Do not sudo here, so that we can use scp to copy test archive to the directdory. if output, err := SSHNoSudo(host, "mkdir", workspace); err != nil { // Exit failure with the error @@ -126,13 +128,35 @@ func RunRemote(suite TestSuite, archive string, host string, cleanup bool, image return output, len(aggErrs) == 0, utilerrors.NewAggregate(aggErrs) } -// timestampFormat is the timestamp format used in the node e2e directory name. -const timestampFormat = "20060102T150405" +const ( + // workspaceDirPrefix is the string prefix used in the workspace directory name. + workspaceDirPrefix = "node-e2e-" + // timestampFormat is the timestamp format used in the node e2e directory name. + timestampFormat = "20060102T150405" +) func getTimestamp() string { return fmt.Sprintf(time.Now().Format(timestampFormat)) } +func newWorkspaceDir() string { + return filepath.Join("/tmp", workspaceDirPrefix+getTimestamp()) +} + +// Parses the workspace directory name and gets the timestamp part of it. +// This can later be used to name other artifacts (such as the +// kubelet-${instance}.service systemd transient service used to launch +// Kubelet) so that they can be matched to each other. +func GetTimestampFromWorkspaceDir(dir string) string { + dirTimestamp := strings.TrimPrefix(filepath.Base(dir), workspaceDirPrefix) + re := regexp.MustCompile("^\\d{8}T\\d{6}$") + if re.MatchString(dirTimestamp) { + return dirTimestamp + } + // Fallback: if we can't find that timestamp, default to using Now() + return getTimestamp() +} + func getTestArtifacts(host, testDir string) error { logPath := filepath.Join(*resultsDir, host) if err := os.MkdirAll(logPath, 0755); err != nil { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/remote/utils.go b/vendor/k8s.io/kubernetes/test/e2e_node/remote/utils.go index ae613f9ee..28ab74cf5 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/remote/utils.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/remote/utils.go @@ -56,7 +56,7 @@ func setupCNI(host, workspace string) error { cniPath := filepath.Join(workspace, cniDirectory) cmd := getSSHCommand(" ; ", fmt.Sprintf("mkdir -p %s", cniPath), - fmt.Sprintf("wget -O - %s | tar -xz -C %s", cniURL, cniPath), + fmt.Sprintf("curl -s -L %s | tar -xz -C %s", cniURL, cniPath), ) if output, err := SSH(host, "sh", "-c", cmd); err != nil { return fmt.Errorf("failed to install cni plugin on %q: %v output: %q", host, err, output) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/resource_collector.go b/vendor/k8s.io/kubernetes/test/e2e_node/resource_collector.go index c98a8c2ff..94987bc88 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/resource_collector.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/resource_collector.go @@ -220,9 +220,7 @@ func (r *ResourceCollector) GetBasicCPUStats(containerName string) map[float64]f // We must make a copy of array, otherwise the timeseries order is changed. usages := make([]*framework.ContainerResourceUsage, 0) - for _, usage := range r.buffers[containerName] { - usages = append(usages, usage) - } + usages = append(usages, r.buffers[containerName]...) sort.Sort(resourceUsageByCPU(usages)) for _, q := range percentiles { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/resource_usage_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/resource_usage_test.go index 6de87b7f4..569bc86f7 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/resource_usage_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/resource_usage_test.go @@ -143,7 +143,7 @@ func runResourceUsageTest(f *framework.Framework, rc *ResourceCollector, testArg // sleep for an interval here to measure steady data sleepAfterCreatePods = 10 * time.Second ) - pods := newTestPods(testArg.podsNr, true, imageutils.GetPauseImageNameForHostArch(), "test_pod") + pods := newTestPods(testArg.podsNr, true, imageutils.GetPauseImageName(), "test_pod") rc.Start() // Explicitly delete pods to prevent namespace controller cleanning up timeout diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/restart_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/restart_test.go index b8d8f1605..4b50c3479 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/restart_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/restart_test.go @@ -59,7 +59,7 @@ func waitForPods(f *framework.Framework, pod_count int, timeout time.Duration) ( return runningPods } -var _ = framework.KubeDescribe("Restart [Serial] [Slow] [Disruptive]", func() { +var _ = framework.KubeDescribe("Restart [Serial] [Slow] [Disruptive] [NodeFeature:ContainerRuntimeRestart]", func() { const ( // Saturate the node. It's not necessary that all these pods enter // Running/Ready, because we don't know the number of cores in the @@ -81,7 +81,7 @@ var _ = framework.KubeDescribe("Restart [Serial] [Slow] [Disruptive]", func() { Context("Network", func() { It("should recover from ip leak", func() { - pods := newTestPods(podCount, false, imageutils.GetPauseImageNameForHostArch(), "restart-container-runtime-test") + pods := newTestPods(podCount, false, imageutils.GetPauseImageName(), "restart-container-runtime-test") By(fmt.Sprintf("Trying to create %d pods on node", len(pods))) createBatchPodWithRateControl(f, pods, podCreationInterval) defer deletePodsSync(f, pods) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/runner/local/BUILD b/vendor/k8s.io/kubernetes/test/e2e_node/runner/local/BUILD index 98b22515c..8bd0e3b8d 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/runner/local/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e_node/runner/local/BUILD @@ -17,6 +17,7 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e_node/runner/local", deps = [ "//test/e2e_node/builder:go_default_library", + "//test/utils:go_default_library", "//vendor/github.com/golang/glog:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/runner/local/run_local.go b/vendor/k8s.io/kubernetes/test/e2e_node/runner/local/run_local.go index 07085e17d..c2c169e87 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/runner/local/run_local.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/runner/local/run_local.go @@ -25,6 +25,7 @@ import ( "strings" "k8s.io/kubernetes/test/e2e_node/builder" + "k8s.io/kubernetes/test/utils" "github.com/golang/glog" ) @@ -49,7 +50,7 @@ func main() { } // Run node e2e test - outputDir, err := builder.GetK8sBuildOutputDir() + outputDir, err := utils.GetK8sBuildOutputDir() if err != nil { glog.Fatalf("Failed to get build output directory: %v", err) } @@ -59,7 +60,7 @@ func main() { args := []string{*ginkgoFlags, test, "--", *testFlags} if *systemSpecName != "" { - rootDir, err := builder.GetK8sRootDir() + rootDir, err := utils.GetK8sRootDir() if err != nil { glog.Fatalf("Failed to get k8s root directory: %v", err) } diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/runner/remote/run_remote.go b/vendor/k8s.io/kubernetes/test/e2e_node/runner/remote/run_remote.go index 054d1cbed..7c440ad96 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/runner/remote/run_remote.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/runner/remote/run_remote.go @@ -134,7 +134,7 @@ type ImageConfig struct { type Accelerator struct { Type string `json:"type,omitempty"` - Count int64 `json:"count, omitempty"` + Count int64 `json:"count,omitempty"` } type Resources struct { @@ -142,19 +142,19 @@ type Resources struct { } type GCEImage struct { - Image string `json:"image, omitempty"` - ImageDesc string `json:"image_description, omitempty"` + Image string `json:"image,omitempty"` + ImageDesc string `json:"image_description,omitempty"` Project string `json:"project"` Metadata string `json:"metadata"` - ImageRegex string `json:"image_regex, omitempty"` + ImageRegex string `json:"image_regex,omitempty"` // Defaults to using only the latest image. Acceptable values are [0, # of images that match the regex). // If the number of existing previous images is lesser than what is desired, the test will use that is available. - PreviousImages int `json:"previous_images, omitempty"` + PreviousImages int `json:"previous_images,omitempty"` - Machine string `json:"machine, omitempty"` - Resources Resources `json:"resources, omitempty"` + Machine string `json:"machine,omitempty"` + Resources Resources `json:"resources,omitempty"` // This test is for benchmark (no limit verification, more result log, node name has format 'machine-image-uuid') if 'Tests' is non-empty. - Tests []string `json:"tests, omitempty"` + Tests []string `json:"tests,omitempty"` } type internalImageConfig struct { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/runtime_conformance_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/runtime_conformance_test.go index 0a8b7ac57..3ba96a87a 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/runtime_conformance_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/runtime_conformance_test.go @@ -46,7 +46,7 @@ var _ = framework.KubeDescribe("Container Runtime Conformance Test", func() { Describe("container runtime conformance blackbox test", func() { Context("when starting a container that exits", func() { - framework.ConformanceIt("it should run with the expected status", func() { + framework.ConformanceIt("it should run with the expected status [NodeConformance]", func() { restartCountVolumeName := "restart-count" restartCountVolumePath := "/restart-count" testContainer := v1.Container{ @@ -127,7 +127,7 @@ while true; do sleep 1; done By("it should get the expected 'State'") Expect(GetContainerState(status.State)).To(Equal(testCase.State)) - By("it should be possible to delete [Conformance]") + By("it should be possible to delete [Conformance][NodeConformance]") Expect(terminateContainer.Delete()).To(Succeed()) Eventually(terminateContainer.Present, retryTimeout, pollInterval).Should(BeFalse()) } @@ -142,7 +142,7 @@ while true; do sleep 1; done message gomegatypes.GomegaMatcher }{ { - name: "if TerminationMessagePath is set [Conformance]", + name: "if TerminationMessagePath is set [Conformance][NodeConformance]", container: v1.Container{ Image: busyboxImage, Command: []string{"/bin/sh", "-c"}, @@ -157,7 +157,7 @@ while true; do sleep 1; done }, { - name: "if TerminationMessagePath is set as non-root user and at a non-default path [Conformance]", + name: "if TerminationMessagePath is set as non-root user and at a non-default path [Conformance][NodeConformance]", container: v1.Container{ Image: busyboxImage, Command: []string{"/bin/sh", "-c"}, @@ -172,7 +172,7 @@ while true; do sleep 1; done }, { - name: "from log output if TerminationMessagePolicy FallbackToLogOnError is set [Conformance]", + name: "from log output if TerminationMessagePolicy FallbackToLogOnError is set [Conformance][NodeConformance]", container: v1.Container{ Image: busyboxImage, Command: []string{"/bin/sh", "-c"}, @@ -185,7 +185,7 @@ while true; do sleep 1; done }, { - name: "as empty when pod succeeds and TerminationMessagePolicy FallbackToLogOnError is set", + name: "as empty when pod succeeds and TerminationMessagePolicy FallbackToLogOnError is set [NodeConformance]", container: v1.Container{ Image: busyboxImage, Command: []string{"/bin/sh", "-c"}, @@ -198,7 +198,7 @@ while true; do sleep 1; done }, { - name: "from file when pod succeeds and TerminationMessagePolicy FallbackToLogOnError is set [Conformance]", + name: "from file when pod succeeds and TerminationMessagePolicy FallbackToLogOnError is set [Conformance][NodeConformance]", container: v1.Container{ Image: busyboxImage, Command: []string{"/bin/sh", "-c"}, @@ -313,7 +313,7 @@ while true; do sleep 1; done }, } { testCase := testCase - It(testCase.description+" [Conformance]", func() { + It(testCase.description+" [Conformance][NodeConformance]", func() { name := "image-pull-test" command := []string{"/bin/sh", "-c", "while true; do sleep 1; done"} container := ConformanceContainer{ diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/security_context_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/security_context_test.go index b7dac718e..3d0aa231c 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/security_context_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/security_context_test.go @@ -41,7 +41,7 @@ var _ = framework.KubeDescribe("Security Context", func() { podClient = f.PodClient() }) - Context("when pod PID namespace is configurable [Feature:ShareProcessNamespace]", func() { + Context("when pod PID namespace is configurable [Feature:ShareProcessNamespace][NodeAlphaFeature:ShareProcessNamespace]", func() { It("containers in pods using isolated PID namespaces should all receive PID 1", func() { By("Create a pod with isolated PID namespaces.") f.PodClient().CreateSync(&v1.Pod{ @@ -156,7 +156,7 @@ var _ = framework.KubeDescribe("Security Context", func() { nginxPid = strings.TrimSpace(output) }) - It("should show its pid in the host PID namespace", func() { + It("should show its pid in the host PID namespace [NodeFeature:HostAccess]", func() { busyboxPodName := "busybox-hostpid-" + string(uuid.NewUUID()) createAndWaitHostPidPod(busyboxPodName, true) logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName) @@ -176,7 +176,7 @@ var _ = framework.KubeDescribe("Security Context", func() { } }) - It("should not show its pid in the non-hostpid containers", func() { + It("should not show its pid in the non-hostpid containers [NodeFeature:HostAccess]", func() { busyboxPodName := "busybox-non-hostpid-" + string(uuid.NewUUID()) createAndWaitHostPidPod(busyboxPodName, false) logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName) @@ -232,7 +232,7 @@ var _ = framework.KubeDescribe("Security Context", func() { framework.Logf("Got host shared memory ID %q", hostSharedMemoryID) }) - It("should show the shared memory ID in the host IPC containers", func() { + It("should show the shared memory ID in the host IPC containers [NodeFeature:HostAccess]", func() { ipcutilsPodName := "ipcutils-hostipc-" + string(uuid.NewUUID()) createAndWaitHostIPCPod(ipcutilsPodName, true) logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, ipcutilsPodName, ipcutilsPodName) @@ -247,7 +247,7 @@ var _ = framework.KubeDescribe("Security Context", func() { } }) - It("should not show the shared memory ID in the non-hostIPC containers", func() { + It("should not show the shared memory ID in the non-hostIPC containers [NodeFeature:HostAccess]", func() { ipcutilsPodName := "ipcutils-non-hostipc-" + string(uuid.NewUUID()) createAndWaitHostIPCPod(ipcutilsPodName, false) logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, ipcutilsPodName, ipcutilsPodName) @@ -315,7 +315,7 @@ var _ = framework.KubeDescribe("Security Context", func() { framework.Logf("Opened a new tcp port %q", listeningPort) }) - It("should listen on same port in the host network containers", func() { + It("should listen on same port in the host network containers [NodeFeature:HostAccess]", func() { busyboxPodName := "busybox-hostnetwork-" + string(uuid.NewUUID()) createAndWaitHostNetworkPod(busyboxPodName, true) logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName) @@ -329,7 +329,7 @@ var _ = framework.KubeDescribe("Security Context", func() { } }) - It("shouldn't show the same port in the non-hostnetwork containers", func() { + It("shouldn't show the same port in the non-hostnetwork containers [NodeFeature:HostAccess]", func() { busyboxPodName := "busybox-non-hostnetwork-" + string(uuid.NewUUID()) createAndWaitHostNetworkPod(busyboxPodName, false) logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName) @@ -382,11 +382,11 @@ var _ = framework.KubeDescribe("Security Context", func() { podClient.WaitForSuccess(podName, framework.PodStartTimeout) } - It("should run the container with uid 65534", func() { + It("should run the container with uid 65534 [NodeConformance]", func() { createAndWaitUserPod(65534) }) - It("should run the container with uid 0", func() { + It("should run the container with uid 0 [NodeConformance]", func() { createAndWaitUserPod(0) }) }) @@ -429,11 +429,11 @@ var _ = framework.KubeDescribe("Security Context", func() { return podName } - It("should run the container with readonly rootfs when readOnlyRootFilesystem=true", func() { + It("should run the container with readonly rootfs when readOnlyRootFilesystem=true [NodeConformance]", func() { createAndWaitUserPod(true) }) - It("should run the container with writable rootfs when readOnlyRootFilesystem=false", func() { + It("should run the container with writable rootfs when readOnlyRootFilesystem=false [NodeConformance]", func() { createAndWaitUserPod(false) }) }) @@ -497,14 +497,14 @@ var _ = framework.KubeDescribe("Security Context", func() { return nil } - It("should allow privilege escalation when not explicitly set and uid != 0", func() { + It("should allow privilege escalation when not explicitly set and uid != 0 [NodeConformance]", func() { podName := "alpine-nnp-nil-" + string(uuid.NewUUID()) if err := createAndMatchOutput(podName, "Effective uid: 0", nil, 1000); err != nil { framework.Failf("Match output for pod %q failed: %v", podName, err) } }) - It("should not allow privilege escalation when false", func() { + It("should not allow privilege escalation when false [NodeConformance]", func() { podName := "alpine-nnp-false-" + string(uuid.NewUUID()) apeFalse := false if err := createAndMatchOutput(podName, "Effective uid: 1000", &apeFalse, 1000); err != nil { @@ -512,7 +512,7 @@ var _ = framework.KubeDescribe("Security Context", func() { } }) - It("should allow privilege escalation when true", func() { + It("should allow privilege escalation when true [NodeConformance]", func() { podName := "alpine-nnp-true-" + string(uuid.NewUUID()) apeTrue := true if err := createAndMatchOutput(podName, "Effective uid: 0", &apeTrue, 1000); err != nil { @@ -555,7 +555,7 @@ var _ = framework.KubeDescribe("Security Context", func() { return podName } - It("should run the container as privileged when true", func() { + It("should run the container as privileged when true [NodeFeature:HostAccess]", func() { podName := createAndWaitUserPod(true) logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, podName, podName) if err != nil { @@ -568,7 +568,7 @@ var _ = framework.KubeDescribe("Security Context", func() { } }) - It("should run the container as unprivileged when false", func() { + It("should run the container as unprivileged when false [NodeConformance]", func() { podName := createAndWaitUserPod(false) logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, podName, podName) if err != nil { diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/services/BUILD b/vendor/k8s.io/kubernetes/test/e2e_node/services/BUILD index f5992b2eb..08f751731 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/services/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e_node/services/BUILD @@ -23,14 +23,14 @@ go_library( "//cmd/kube-apiserver/app:go_default_library", "//cmd/kube-apiserver/app/options:go_default_library", "//cmd/kubelet/app/options:go_default_library", - "//pkg/api/legacyscheme:go_default_library", "//pkg/controller/namespace:go_default_library", "//pkg/features:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", + "//pkg/kubelet/kubeletconfig/util/codec:go_default_library", "//test/e2e/framework:go_default_library", "//test/e2e_node/builder:go_default_library", + "//test/e2e_node/remote:go_default_library", "//vendor/github.com/coreos/etcd/etcdserver:go_default_library", "//vendor/github.com/coreos/etcd/etcdserver/api/v2http:go_default_library", "//vendor/github.com/coreos/etcd/pkg/transport:go_default_library", @@ -40,7 +40,6 @@ go_library( "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/services/apiserver.go b/vendor/k8s.io/kubernetes/test/e2e_node/services/apiserver.go index dc7c0c2bd..1d956fbec 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/services/apiserver.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/services/apiserver.go @@ -40,27 +40,33 @@ func NewAPIServer() *APIServer { // Start starts the apiserver, returns when apiserver is ready. func (a *APIServer) Start() error { - config := options.NewServerRunOptions() - config.Etcd.StorageConfig.ServerList = []string{getEtcdClientURL()} + o := options.NewServerRunOptions() + o.Etcd.StorageConfig.ServerList = []string{getEtcdClientURL()} // TODO: Current setup of etcd in e2e-node tests doesn't support etcd v3 // protocol. We should migrate it to use the same infrastructure as all // other tests (pkg/storage/etcd/testing). - config.Etcd.StorageConfig.Type = "etcd2" + o.Etcd.StorageConfig.Type = "etcd2" _, ipnet, err := net.ParseCIDR(clusterIPRange) if err != nil { return err } - config.ServiceClusterIPRange = *ipnet - config.AllowPrivileged = true - config.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount"} + o.ServiceClusterIPRange = *ipnet + o.AllowPrivileged = true + o.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount"} errCh := make(chan error) go func() { defer close(errCh) stopCh := make(chan struct{}) defer close(stopCh) - err := apiserver.Run(config, stopCh) + completedOptions, err := apiserver.Complete(o) + if err != nil { + errCh <- fmt.Errorf("set apiserver default options error: %v", err) + return + } + err = apiserver.Run(completedOptions, stopCh) if err != nil { errCh <- fmt.Errorf("run apiserver error: %v", err) + return } }() diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/services/kubelet.go b/vendor/k8s.io/kubernetes/test/e2e_node/services/kubelet.go index dcb3507e2..5d37ca931 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/services/kubelet.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/services/kubelet.go @@ -20,7 +20,6 @@ import ( "flag" "fmt" "io/ioutil" - "math/rand" "os" "os/exec" "path/filepath" @@ -31,16 +30,16 @@ import ( "github.com/spf13/pflag" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" utilfeature "k8s.io/apiserver/pkg/util/feature" utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/kubernetes/cmd/kubelet/app/options" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + kubeletconfigcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e_node/builder" + "k8s.io/kubernetes/test/e2e_node/remote" ) // TODO(random-liu): Replace this with standard kubelet launcher. @@ -192,7 +191,12 @@ func (e *E2EServices) startKubelet() (*server, error) { // Since kubelet will typically be run as a service it also makes more // sense to test it that way isSystemd = true - unitName := fmt.Sprintf("kubelet-%d.service", rand.Int31()) + // We can ignore errors, to have GetTimestampFromWorkspaceDir() fallback + // to the current time. + cwd, _ := os.Getwd() + // Use the timestamp from the current directory to name the systemd unit. + unitTimestamp := remote.GetTimestampFromWorkspaceDir(cwd) + unitName := fmt.Sprintf("kubelet-%s.service", unitTimestamp) if kubeletContainerized { cmdArgs = append(cmdArgs, systemdRun, "--unit="+unitName, "--slice=runtime.slice", "--remain-after-exit", "/usr/bin/docker", "run", "--name=kubelet", @@ -201,7 +205,7 @@ func (e *E2EServices) startKubelet() (*server, error) { "-v", "/etc/localtime:/etc/localtime:ro", "-v", "/etc/machine-id:/etc/machine-id:ro", "-v", filepath.Dir(kubeconfigPath)+":/etc/kubernetes", - "-v", "/:/rootfs:ro,rslave", + "-v", "/:/rootfs:rw,rslave", "-v", "/run:/run", "-v", "/sys/fs/cgroup:/sys/fs/cgroup:rw", "-v", "/sys:/sys:rw", @@ -215,7 +219,7 @@ func (e *E2EServices) startKubelet() (*server, error) { // if we will generate a kubelet config file, we need to mount that path into the container too if genKubeletConfigFile { - cmdArgs = append(cmdArgs, "-v", filepath.Dir(kubeletConfigPath)+":"+filepath.Dir(kubeletConfigPath)+":ro") + cmdArgs = append(cmdArgs, "-v", filepath.Dir(kubeletConfigPath)+":"+filepath.Dir(kubeletConfigPath)+":rw") } cmdArgs = append(cmdArgs, hyperkubeImage, "/hyperkube", "kubelet", "--containerized") @@ -253,7 +257,7 @@ func (e *E2EServices) startKubelet() (*server, error) { "--kubeconfig", kubeconfigPath, "--root-dir", KubeletRootDirectory, "--v", LOG_VERBOSITY_LEVEL, "--logtostderr", - "--allow-privileged", "true", + "--allow-privileged=true", ) // Apply test framework feature gates by default. This could also be overridden @@ -343,27 +347,13 @@ func addKubeletConfigFlags(cmdArgs *[]string, kc *kubeletconfig.KubeletConfigura fs := pflag.NewFlagSet("kubelet", pflag.ExitOnError) options.AddKubeletConfigFlags(fs, kc) for _, name := range flags { - *cmdArgs = append(*cmdArgs, "--"+name, fs.Lookup(name).Value.String()) + *cmdArgs = append(*cmdArgs, fmt.Sprintf("--%s=%s", name, fs.Lookup(name).Value.String())) } } // writeKubeletConfigFile writes the kubelet config file based on the args and returns the filename func writeKubeletConfigFile(internal *kubeletconfig.KubeletConfiguration, path string) error { - // extract the KubeletConfiguration and convert to versioned - versioned := &v1beta1.KubeletConfiguration{} - scheme, _, err := scheme.NewSchemeAndCodecs() - if err != nil { - return err - } - if err := scheme.Convert(internal, versioned, nil); err != nil { - return err - } - // encode - encoder, err := newKubeletConfigJSONEncoder() - if err != nil { - return err - } - data, err := runtime.Encode(encoder, versioned) + data, err := kubeletconfigcodec.EncodeKubeletConfig(internal, kubeletconfigv1beta1.SchemeGroupVersion) if err != nil { return err } @@ -379,20 +369,6 @@ func writeKubeletConfigFile(internal *kubeletconfig.KubeletConfiguration, path s return nil } -func newKubeletConfigJSONEncoder() (runtime.Encoder, error) { - _, kubeletCodecs, err := scheme.NewSchemeAndCodecs() - if err != nil { - return nil, err - } - - mediaType := "application/json" - info, ok := runtime.SerializerInfoForMediaType(kubeletCodecs.SupportedMediaTypes(), mediaType) - if !ok { - return nil, fmt.Errorf("unsupported media type %q", mediaType) - } - return kubeletCodecs.EncoderForVersion(info.Serializer, v1beta1.SchemeGroupVersion), nil -} - // createPodDirectory creates pod directory. func createPodDirectory() (string, error) { cwd, err := os.Getwd() diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/services/namespace_controller.go b/vendor/k8s.io/kubernetes/test/e2e_node/services/namespace_controller.go index 79fd3dd48..7b8e1514b 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/services/namespace_controller.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/services/namespace_controller.go @@ -24,7 +24,6 @@ import ( "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/legacyscheme" namespacecontroller "k8s.io/kubernetes/pkg/controller/namespace" ) @@ -50,18 +49,25 @@ func NewNamespaceController(host string) *NamespaceController { // Start starts the namespace controller. func (n *NamespaceController) Start() error { - // Use the default QPS config := restclient.AddUserAgent(&restclient.Config{Host: n.host}, ncName) + + // the namespace cleanup controller is very chatty. It makes lots of discovery calls and then it makes lots of delete calls. + config.QPS = 50 + config.Burst = 200 + client, err := clientset.NewForConfig(config) if err != nil { return err } - clientPool := dynamic.NewClientPool(config, legacyscheme.Registry.RESTMapper(), dynamic.LegacyAPIPathResolverFunc) + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + return err + } discoverResourcesFn := client.Discovery().ServerPreferredNamespacedResources informerFactory := informers.NewSharedInformerFactory(client, ncResyncPeriod) nc := namespacecontroller.NewNamespaceController( client, - clientPool, + dynamicClient, discoverResourcesFn, informerFactory.Core().V1().Namespaces(), ncResyncPeriod, v1.FinalizerKubernetes, diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/simple_mount.go b/vendor/k8s.io/kubernetes/test/e2e_node/simple_mount.go deleted file mode 100644 index 493c3d399..000000000 --- a/vendor/k8s.io/kubernetes/test/e2e_node/simple_mount.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -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 e2e_node - -import ( - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/test/e2e/framework" - imageutils "k8s.io/kubernetes/test/utils/image" - - . "github.com/onsi/ginkgo" -) - -var _ = framework.KubeDescribe("SimpleMount", func() { - f := framework.NewDefaultFramework("simple-mount-test") - - // This is a very simple test that exercises the Kubelet's mounter code path. - // If the mount fails, the pod will not be able to run, and CreateSync will timeout. - It("should be able to mount an emptydir on a container", func() { - pod := &v1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "simple-mount-pod", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "simple-mount-container", - Image: imageutils.GetPauseImageNameForHostArch(), - VolumeMounts: []v1.VolumeMount{ - { - Name: "simply-mounted-volume", - MountPath: "/opt/", - }, - }, - }, - }, - Volumes: []v1.Volume{ - { - Name: "simply-mounted-volume", - VolumeSource: v1.VolumeSource{ - EmptyDir: &v1.EmptyDirVolumeSource{ - Medium: "Memory", - }, - }, - }, - }, - }, - } - podClient := f.PodClient() - pod = podClient.CreateSync(pod) - - }) -}) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/summary_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/summary_test.go index edfb0d3d3..dd950eed2 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/summary_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/summary_test.go @@ -19,6 +19,7 @@ package e2e_node import ( "fmt" "io/ioutil" + "os/exec" "strings" "time" @@ -35,7 +36,7 @@ import ( "github.com/onsi/gomega/types" ) -var _ = framework.KubeDescribe("Summary API", func() { +var _ = framework.KubeDescribe("Summary API [NodeConformance]", func() { f := framework.NewDefaultFramework("summary-test") Context("when querying /stats/summary", func() { AfterEach(func() { @@ -112,15 +113,39 @@ var _ = framework.KubeDescribe("Summary API", func() { "Time": recent(maxStatsAge), // Pods are limited by Node Allocatable "AvailableBytes": bounded(1*framework.Kb, memoryLimit), - "UsageBytes": bounded(10*framework.Kb, 20*framework.Mb), - "WorkingSetBytes": bounded(10*framework.Kb, 20*framework.Mb), + "UsageBytes": bounded(10*framework.Kb, 50*framework.Mb), + "WorkingSetBytes": bounded(10*framework.Kb, 50*framework.Mb), "RSSBytes": bounded(1*framework.Kb, 20*framework.Mb), "PageFaults": bounded(0, 1000000), "MajorPageFaults": bounded(0, 10), }) + runtimeContExpectations := sysContExpectations().(*gstruct.FieldsMatcher) + if systemdutil.IsRunningSystemd() && framework.TestContext.ContainerRuntime == "docker" { + // Some Linux distributions still ship a docker.service that is missing + // a `Delegate=yes` setting (or equivalent CPUAccounting= and MemoryAccounting=) + // that allows us to monitor the container runtime resource usage through + // the "cpu" and "memory" cgroups. + // + // Make an exception here for those distros, only for Docker, so that they + // can pass the full node e2e tests even in that case. + // + // For newer container runtimes (using CRI) and even distros that still + // ship Docker, we should encourage them to always set `Delegate=yes` in + // order to make monitoring of the runtime possible. + stdout, err := exec.Command("systemctl", "show", "-p", "Delegate", "docker.service").CombinedOutput() + if err == nil && strings.TrimSpace(string(stdout)) == "Delegate=no" { + // Only make these optional if we can successfully confirm that + // Delegate is set to "no" (in other words, unset.) If we fail + // to check that, default to requiring it, which might cause + // false positives, but that should be the safer approach. + By("Making runtime container expectations optional, since systemd was not configured to Delegate=yes the cgroups") + runtimeContExpectations.Fields["Memory"] = Or(BeNil(), runtimeContExpectations.Fields["Memory"]) + runtimeContExpectations.Fields["CPU"] = Or(BeNil(), runtimeContExpectations.Fields["CPU"]) + } + } systemContainers := gstruct.Elements{ "kubelet": sysContExpectations(), - "runtime": sysContExpectations(), + "runtime": runtimeContExpectations, "pods": podsContExpectations, } // The Kubelet only manages the 'misc' system container if the host is not running systemd. @@ -150,7 +175,7 @@ var _ = framework.KubeDescribe("Summary API", func() { "StartTime": recent(maxStartAge), "CPU": ptrMatchAllFields(gstruct.Fields{ "Time": recent(maxStatsAge), - "UsageNanoCores": bounded(100000, 1E9), + "UsageNanoCores": bounded(10000, 1E9), "UsageCoreNanoSeconds": bounded(10000000, 1E11), }), "Memory": ptrMatchAllFields(gstruct.Fields{ @@ -197,7 +222,7 @@ var _ = framework.KubeDescribe("Summary API", func() { }), "CPU": ptrMatchAllFields(gstruct.Fields{ "Time": recent(maxStatsAge), - "UsageNanoCores": bounded(100000, 1E9), + "UsageNanoCores": bounded(10000, 1E9), "UsageCoreNanoSeconds": bounded(10000000, 1E11), }), "Memory": ptrMatchAllFields(gstruct.Fields{ @@ -324,7 +349,7 @@ func getSummaryTestPods(f *framework.Framework, numRestarts int32, names ...stri { Name: "busybox-container", Image: busyboxImage, - Command: getRestartingContainerCommand("/test-empty-dir-mnt", 0, numRestarts, "ping -c 1 google.com; echo 'hello world' >> /test-empty-dir-mnt/file;"), + Command: getRestartingContainerCommand("/test-empty-dir-mnt", 0, numRestarts, "echo 'some bytes' >/outside_the_volume.txt; ping -c 1 google.com; echo 'hello world' >> /test-empty-dir-mnt/file;"), Resources: v1.ResourceRequirements{ Limits: v1.ResourceList{ // Must set memory limit to get MemoryStats.AvailableBytes diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/system/BUILD b/vendor/k8s.io/kubernetes/test/e2e_node/system/BUILD index 0481c4dc1..8e21c87bd 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/system/BUILD +++ b/vendor/k8s.io/kubernetes/test/e2e_node/system/BUILD @@ -60,7 +60,6 @@ go_library( "//vendor/github.com/docker/docker/api/types:go_default_library", "//vendor/github.com/docker/docker/client:go_default_library", "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/system/docker_validator.go b/vendor/k8s.io/kubernetes/test/e2e_node/system/docker_validator.go index f6b7f03da..d6895fa90 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/system/docker_validator.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/system/docker_validator.go @@ -17,12 +17,12 @@ limitations under the License. package system import ( + "context" "fmt" "regexp" "github.com/docker/docker/api/types" "github.com/docker/docker/client" - "golang.org/x/net/context" ) var _ Validator = &DockerValidator{} diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/util.go b/vendor/k8s.io/kubernetes/test/e2e_node/util.go index 7c183d894..a33ae7cc6 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/util.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/util.go @@ -32,19 +32,20 @@ import ( apiv1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/kubernetes/scheme" "k8s.io/kubernetes/pkg/features" internalapi "k8s.io/kubernetes/pkg/kubelet/apis/cri" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" - kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" + "k8s.io/kubernetes/pkg/kubelet/cm" + kubeletconfigcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec" kubeletmetrics "k8s.io/kubernetes/pkg/kubelet/metrics" "k8s.io/kubernetes/pkg/kubelet/remote" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework/metrics" + frameworkmetrics "k8s.io/kubernetes/test/e2e/framework/metrics" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -57,6 +58,11 @@ var startServices = flag.Bool("start-services", true, "If true, start local node var stopServices = flag.Bool("stop-services", true, "If true, stop local node services after running tests") var busyboxImage = "busybox" +const ( + // Kubelet internal cgroup name for node allocatable cgroup. + defaultNodeAllocatableCgroup = "kubepods" +) + func getNodeSummary() (*stats.Summary, error) { req, err := http.NewRequest("GET", *kubeletAddress+"/stats/summary", nil) if err != nil { @@ -132,7 +138,7 @@ func isKubeletConfigEnabled(f *framework.Framework) (bool, error) { } v, ok := cfgz.FeatureGates[string(features.DynamicKubeletConfig)] if !ok { - return false, nil + return true, nil } return v, nil } @@ -164,10 +170,10 @@ func setKubeletConfiguration(f *framework.Framework, kubeCfg *kubeletconfig.Kube // create the reference and set Node.Spec.ConfigSource src := &apiv1.NodeConfigSource{ - ConfigMapRef: &apiv1.ObjectReference{ - Namespace: "kube-system", - Name: cm.Name, - UID: cm.UID, + ConfigMap: &apiv1.ConfigMapNodeConfigSource{ + Namespace: "kube-system", + Name: cm.Name, + KubeletConfigKey: "kubelet", }, } @@ -219,17 +225,6 @@ func setNodeConfigSource(f *framework.Framework, source *apiv1.NodeConfigSource) return nil } -// getKubeletConfigOkCondition returns the first NodeCondition in `cs` with Type == apiv1.NodeKubeletConfigOk, -// or if no such condition exists, returns nil. -func getKubeletConfigOkCondition(cs []apiv1.NodeCondition) *apiv1.NodeCondition { - for i := range cs { - if cs[i].Type == apiv1.NodeKubeletConfigOk { - return &cs[i] - } - } - return nil -} - // Causes the test to fail, or returns a status 200 response from the /configz endpoint func pollConfigz(timeout time.Duration, pollInterval time.Duration) *http.Response { endpoint := fmt.Sprintf("http://127.0.0.1:8080/api/v1/nodes/%s/proxy/configz", framework.TestContext.NodeName) @@ -295,17 +290,7 @@ func createConfigMap(f *framework.Framework, internalKC *kubeletconfig.KubeletCo // constructs a ConfigMap, populating one of its keys with the KubeletConfiguration. Always uses GenerateName to generate a suffix. func newKubeletConfigMap(name string, internalKC *kubeletconfig.KubeletConfiguration) *apiv1.ConfigMap { - scheme, _, err := kubeletscheme.NewSchemeAndCodecs() - framework.ExpectNoError(err) - - versioned := &kubeletconfigv1beta1.KubeletConfiguration{} - err = scheme.Convert(internalKC, versioned, nil) - framework.ExpectNoError(err) - - encoder, err := newKubeletConfigJSONEncoder() - framework.ExpectNoError(err) - - data, err := runtime.Encode(encoder, versioned) + data, err := kubeletconfigcodec.EncodeKubeletConfig(internalKC, kubeletconfigv1beta1.SchemeGroupVersion) framework.ExpectNoError(err) cmap := &apiv1.ConfigMap{ @@ -335,32 +320,38 @@ func getLocalNode(f *framework.Framework) *apiv1.Node { return &nodeList.Items[0] } -// logs prometheus metrics from the local kubelet. -func logKubeletMetrics(metricKeys ...string) { +// logKubeletLatencyMetrics logs KubeletLatencyMetrics computed from the Prometheus +// metrics exposed on the current node and identified by the metricNames. +// The Kubelet subsystem prefix is automatically prepended to these metric names. +func logKubeletLatencyMetrics(metricNames ...string) { metricSet := sets.NewString() - for _, key := range metricKeys { + for _, key := range metricNames { metricSet.Insert(kubeletmetrics.KubeletSubsystem + "_" + key) } metric, err := metrics.GrabKubeletMetricsWithoutProxy(framework.TestContext.NodeName + ":10255") if err != nil { framework.Logf("Error getting kubelet metrics: %v", err) } else { - framework.Logf("Kubelet Metrics: %+v", framework.GetKubeletMetrics(metric, metricSet)) + framework.Logf("Kubelet Metrics: %+v", framework.GetKubeletLatencyMetrics(metric, metricSet)) } } -func newKubeletConfigJSONEncoder() (runtime.Encoder, error) { - _, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs() +// returns config related metrics from the local kubelet, filtered to the filterMetricNames passed in +func getKubeletMetrics(filterMetricNames sets.String) (frameworkmetrics.KubeletMetrics, error) { + // grab Kubelet metrics + ms, err := metrics.GrabKubeletMetricsWithoutProxy(framework.TestContext.NodeName + ":10255") if err != nil { return nil, err } - mediaType := "application/json" - info, ok := runtime.SerializerInfoForMediaType(kubeletCodecs.SupportedMediaTypes(), mediaType) - if !ok { - return nil, fmt.Errorf("unsupported media type %q", mediaType) + filtered := metrics.NewKubeletMetrics() + for name := range ms { + if !filterMetricNames.Has(name) { + continue + } + filtered[name] = ms[name] } - return kubeletCodecs.EncoderForVersion(info.Serializer, kubeletconfigv1beta1.SchemeGroupVersion), nil + return filtered, nil } // runCommand runs the cmd and returns the combined stdout and stderr, or an @@ -399,7 +390,7 @@ func getCRIClient() (internalapi.RuntimeService, internalapi.ImageManagerService func restartKubelet() { stdout, err := exec.Command("sudo", "systemctl", "list-units", "kubelet*", "--state=running").CombinedOutput() framework.ExpectNoError(err) - regex := regexp.MustCompile("(kubelet-[0-9]+)") + regex := regexp.MustCompile("(kubelet-\\w+)") matches := regex.FindStringSubmatch(string(stdout)) Expect(len(matches)).NotTo(BeZero()) kube := matches[0] @@ -407,3 +398,20 @@ func restartKubelet() { stdout, err = exec.Command("sudo", "systemctl", "restart", kube).CombinedOutput() framework.ExpectNoError(err, "Failed to restart kubelet with systemctl: %v, %v", err, stdout) } + +func toCgroupFsName(cgroupName cm.CgroupName) string { + if framework.TestContext.KubeletConfig.CgroupDriver == "systemd" { + return cgroupName.ToSystemd() + } else { + return cgroupName.ToCgroupfs() + } +} + +// reduceAllocatableMemoryUsage uses memory.force_empty (https://lwn.net/Articles/432224/) +// to make the kernel reclaim memory in the allocatable cgroup +// the time to reduce pressure may be unbounded, but usually finishes within a second +func reduceAllocatableMemoryUsage() { + cmd := fmt.Sprintf("echo 0 > /sys/fs/cgroup/memory/%s/memory.force_empty", toCgroupFsName(cm.NewCgroupName(cm.RootCgroupName, defaultNodeAllocatableCgroup))) + _, err := exec.Command("sudo", "sh", "-c", cmd).CombinedOutput() + framework.ExpectNoError(err) +} diff --git a/vendor/k8s.io/kubernetes/test/e2e_node/volume_manager_test.go b/vendor/k8s.io/kubernetes/test/e2e_node/volume_manager_test.go index 5f62e3c04..39f176e50 100644 --- a/vendor/k8s.io/kubernetes/test/e2e_node/volume_manager_test.go +++ b/vendor/k8s.io/kubernetes/test/e2e_node/volume_manager_test.go @@ -34,7 +34,7 @@ var _ = framework.KubeDescribe("Kubelet Volume Manager", func() { f := framework.NewDefaultFramework("kubelet-volume-manager") Describe("Volume Manager", func() { Context("On terminatation of pod with memory backed volume", func() { - It("should remove the volume from the node", func() { + It("should remove the volume from the node [NodeConformance]", func() { var ( memoryBackedPod *v1.Pod volumeName string diff --git a/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/cmd/apply/cm.yaml b/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/cmd/apply/cm.yaml new file mode 100644 index 000000000..571afe8ae --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/cmd/apply/cm.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +items: +- kind: ConfigMap + apiVersion: v1 + metadata: + name: test + data: + key1: apple +- kind: ConfigMap + apiVersion: v1 + metadata: + name: test2 + data: + key2: apple +kind: ConfigMapList +metadata: {} diff --git a/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/plugins/env/env.sh b/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/plugins/env/env.sh index b7d005519..44c9a4f33 100755 --- a/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/plugins/env/env.sh +++ b/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/plugins/env/env.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/plugins2/hello/hello.sh b/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/plugins2/hello/hello.sh index 86ade7604..c3d7075b4 100755 --- a/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/plugins2/hello/hello.sh +++ b/vendor/k8s.io/kubernetes/test/fixtures/pkg/kubectl/plugins2/hello/hello.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/images/Makefile b/vendor/k8s.io/kubernetes/test/images/Makefile index bbb15fb80..47c9d46ad 100644 --- a/vendor/k8s.io/kubernetes/test/images/Makefile +++ b/vendor/k8s.io/kubernetes/test/images/Makefile @@ -12,10 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +include ../../hack/make-rules/Makefile.manifest + REGISTRY ?= gcr.io/kubernetes-e2e-test-images GOARM=7 QEMUVERSION=v2.9.1 -GOLANG_VERSION=1.9.3 +GOLANG_VERSION=1.10.3 export ifndef WHAT diff --git a/vendor/k8s.io/kubernetes/test/images/image-util.sh b/vendor/k8s.io/kubernetes/test/images/image-util.sh index 5d9b777b8..238bade43 100755 --- a/vendor/k8s.io/kubernetes/test/images/image-util.sh +++ b/vendor/k8s.io/kubernetes/test/images/image-util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -90,15 +90,23 @@ build() { # This function will push the docker images push() { + TAG=$(<${IMAGE}/VERSION) if [[ -f ${IMAGE}/BASEIMAGE ]]; then archs=$(listArchs) else archs=${!QEMUARCHS[@]} fi for arch in ${archs}; do - TAG=$(<${IMAGE}/VERSION) docker push ${REGISTRY}/${IMAGE}-${arch}:${TAG} done + + # Make archs list into image manifest. Eg: 'amd64 ppc64le' to '${REGISTRY}/${IMAGE}-amd64:${TAG} ${REGISTRY}/${IMAGE}-ppc64le:${TAG}' + manifest=$(echo $archs | sed -e "s~[^ ]*~$REGISTRY\/$IMAGE\-&:$TAG~g") + docker manifest create --amend ${REGISTRY}/${IMAGE}:${TAG} ${manifest} + for arch in ${archs}; do + docker manifest annotate --arch ${arch} ${REGISTRY}/${IMAGE}:${TAG} ${REGISTRY}/${IMAGE}-${arch}:${TAG} + done + docker manifest push ${REGISTRY}/${IMAGE}:${TAG} } # This function is for building the go code diff --git a/vendor/k8s.io/kubernetes/test/images/liveness/server.go b/vendor/k8s.io/kubernetes/test/images/liveness/server.go index 889d27765..a32ac9267 100644 --- a/vendor/k8s.io/kubernetes/test/images/liveness/server.go +++ b/vendor/k8s.io/kubernetes/test/images/liveness/server.go @@ -29,11 +29,11 @@ func main() { started := time.Now() http.HandleFunc("/started", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) - data := (time.Now().Sub(started)).String() + data := (time.Since(started)).String() w.Write([]byte(data)) }) http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { - duration := time.Now().Sub(started) + duration := time.Since(started) if duration.Seconds() > 10 { w.WriteHeader(500) w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds()))) diff --git a/vendor/k8s.io/kubernetes/test/images/logs-generator/logs_generator.go b/vendor/k8s.io/kubernetes/test/images/logs-generator/logs_generator.go index 87189172f..d11a0025e 100644 --- a/vendor/k8s.io/kubernetes/test/images/logs-generator/logs_generator.go +++ b/vendor/k8s.io/kubernetes/test/images/logs-generator/logs_generator.go @@ -62,10 +62,11 @@ func generateLogs(linesTotal int, duration time.Duration) { delay := duration / time.Duration(linesTotal) rand.Seed(time.Now().UnixNano()) - tick := time.Tick(delay) + ticker := time.NewTicker(delay) + defer ticker.Stop() for id := 0; id < linesTotal; id++ { glog.Info(generateLogLine(id)) - <-tick + <-ticker.C } } diff --git a/vendor/k8s.io/kubernetes/test/images/pets/peer-finder/README.md b/vendor/k8s.io/kubernetes/test/images/pets/peer-finder/README.md index f523a5797..4c9a2c9c3 100644 --- a/vendor/k8s.io/kubernetes/test/images/pets/peer-finder/README.md +++ b/vendor/k8s.io/kubernetes/test/images/pets/peer-finder/README.md @@ -6,7 +6,7 @@ All it does is watch DNS for changes in the set of endpoints that are part of th of the PetSet. It periodically looks up the SRV record of the DNS entry that corresponds to a Kubernetes Service which enumerates the set of peers for this the specified service. -Be sure to use the `service.alpha.kubernetes.io/tolerate-unready-endpoints` on the governing service +Be sure to use the `publishNotReadyAddresses` field on the governing service of the StatefulSet so that all peers are listed in endpoints before any peers are started. There are several ways to bundle it with your main application. diff --git a/vendor/k8s.io/kubernetes/test/images/pets/redis-installer/on-start.sh b/vendor/k8s.io/kubernetes/test/images/pets/redis-installer/on-start.sh index e11938894..dd9a4e656 100755 --- a/vendor/k8s.io/kubernetes/test/images/pets/redis-installer/on-start.sh +++ b/vendor/k8s.io/kubernetes/test/images/pets/redis-installer/on-start.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2016 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/images/resource-consumer/consume-cpu/consume_cpu.go b/vendor/k8s.io/kubernetes/test/images/resource-consumer/consume-cpu/consume_cpu.go index b7baf6e71..08a6dc986 100644 --- a/vendor/k8s.io/kubernetes/test/images/resource-consumer/consume-cpu/consume_cpu.go +++ b/vendor/k8s.io/kubernetes/test/images/resource-consumer/consume-cpu/consume_cpu.go @@ -45,7 +45,7 @@ func main() { duration := time.Duration(*durationSec) * time.Second start := time.Now() first := systemstat.GetProcCPUSample() - for time.Now().Sub(start) < duration { + for time.Since(start) < duration { cpu := systemstat.GetProcCPUAverage(first, systemstat.GetProcCPUSample(), systemstat.GetUptime().Uptime) if cpu.TotalPct < millicoresPct { doSomething() diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/Makefile b/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/Makefile index 4f282da8e..8abd08d01 100644 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/Makefile +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/Makefile @@ -13,7 +13,7 @@ # limitations under the License. TAG = 0.1 -PREFIX = staging-k8s.gcr.io +PREFIX = gcr.io/kubernetes-e2e-test-images all: push diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/init.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/init.sh index 213630dd2..f7981405e 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/init.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/init.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/install.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/install.sh index 6a96ad974..5cdeecf9d 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/install.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/ceph/install.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/Dockerfile b/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/Dockerfile index 522e49068..4c2785db5 100644 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/Dockerfile +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/Dockerfile @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM centos -RUN yum -y install hostname centos-release-gluster && yum -y install glusterfs-server && yum clean all +FROM fedora:26 +RUN yum -y install hostname glusterfs-server && yum clean all ADD glusterd.vol /etc/glusterfs/ ADD run_gluster.sh /usr/local/bin/ ADD index.html /vol/ diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/Makefile b/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/Makefile index 477078af4..6ddfe1964 100644 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/Makefile +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/Makefile @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -TAG = 0.4 -PREFIX = staging-k8s.gcr.io +TAG = 0.5 +PREFIX = gcr.io/kubernetes-e2e-test-images all: push diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/run_gluster.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/run_gluster.sh index 5e564b45b..0cf5cb48c 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/run_gluster.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/gluster/run_gluster.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/Dockerfile b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/Dockerfile index ff3ab35fb..26eccb59d 100644 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/Dockerfile +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/Dockerfile @@ -12,8 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM fedora -RUN yum install -y iscsi-initiator-utils targetcli net-tools strace && yum clean all +FROM fedora:26 + +RUN yum install -y iscsi-initiator-utils targetcli net-tools strace procps-ng psmisc && yum clean all ADD run_iscsid.sh /usr/local/bin/ ADD initiatorname.iscsi /etc/iscsi/ ADD block.tar.gz / diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/Makefile b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/Makefile index 85b6d6b0e..f6e6903e1 100644 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/Makefile +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/Makefile @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -TAG = 0.1 -PREFIX = staging-k8s.gcr.io +TAG = 0.2 +PREFIX = gcr.io/kubernetes-e2e-test-images all: push diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/block.tar.gz b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/block.tar.gz index 8576d132c..8840f5438 100644 Binary files a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/block.tar.gz and b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/block.tar.gz differ diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/create_block.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/create_block.sh index 0fe90f716..942156869 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/create_block.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/create_block.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -33,8 +33,9 @@ cleanup() trap cleanup TERM EXIT -# Create 1MB device with ext2 -dd if=/dev/zero of=block count=1 bs=1M +# Create 120MB device with ext2 +# (volume_io tests need at least 100MB) +dd if=/dev/zero of=block seek=120 count=1 bs=1M mkfs.ext2 block # Add index.html to it diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/run_iscsid.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/run_iscsid.sh index 767f48d07..a5bded46c 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/run_iscsid.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/run_iscsid.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -16,16 +16,26 @@ function start() { + # targetcli need dbus + mkdir /run/dbus + dbus-daemon --system + + # clear any previous configuration + targetcli clearconfig confirm=True + + # restore configuration from saveconfig.json targetcli restoreconfig - iscsid + + # maximum log level + iscsid -f -d 8 + echo "iscsid started" } function stop() { echo "Stopping iscsid" - - kill $( cat /var/run/iscsid.pid ) + killall iscsid targetcli clearconfig confirm=True echo "iscsid stopped" diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/saveconfig.json b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/saveconfig.json index 7520b99e5..4efc14c8a 100644 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/saveconfig.json +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/iscsi/saveconfig.json @@ -32,7 +32,7 @@ "dev": "block", "name": "block", "plugin": "fileio", - "size": 1048576, + "size": 126877696, "write_back": true, "wwn": "521c57aa-9d9b-4e5d-ab1a-527487f92a33" } diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/nfs/Makefile b/vendor/k8s.io/kubernetes/test/images/volumes-tester/nfs/Makefile index 363c518ac..557942158 100644 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/nfs/Makefile +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/nfs/Makefile @@ -13,7 +13,7 @@ # limitations under the License. TAG = 0.8 -PREFIX = staging-k8s.gcr.io +PREFIX = gcr.io/kubernetes-e2e-test-images all: push diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/nfs/run_nfs.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/nfs/run_nfs.sh index 7b760572d..6577e6da6 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/nfs/run_nfs.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/nfs/run_nfs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/Dockerfile b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/Dockerfile index e195f3f06..2c3465191 100644 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/Dockerfile +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/Dockerfile @@ -15,16 +15,17 @@ # CEPH all in one # Based on image by Ricardo Rocha, ricardo@catalyst.net.nz -FROM fedora +FROM fedora:26 # Base Packages -RUN yum install -y wget ceph ceph-fuse strace && yum clean all +RUN yum install -y wget strace psmisc procps-ng ceph ceph-fuse && yum clean all # Get ports exposed EXPOSE 6789 ADD ./bootstrap.sh /bootstrap.sh ADD ./mon.sh /mon.sh +ADD ./mds.sh /mds.sh ADD ./osd.sh /osd.sh ADD ./ceph.conf.sh /ceph.conf.sh ADD ./keyring /var/lib/ceph/mon/keyring diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/Makefile b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/Makefile index fc3563460..df64f6694 100644 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/Makefile +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/Makefile @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -TAG = 0.1 -PREFIX = staging-k8s.gcr.io +TAG = 0.2 +PREFIX = gcr.io/kubernetes-e2e-test-images all: push diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/block.tar.gz b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/block.tar.gz index 395d1492f..8ec08a1d9 100644 Binary files a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/block.tar.gz and b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/block.tar.gz differ diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/bootstrap.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/bootstrap.sh index bb670aca0..fb5e69c21 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/bootstrap.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -35,9 +35,29 @@ mkdir -p /var/lib/ceph/osd/ceph-0 /var/lib/ceph/osd/ceph-1 sh ./osd.sh 0 sh ./osd.sh 1 -# Prepare a RBD volume -# NOTE: we need Ceph kernel modules on the host! -rbd import block foo +# Configure and start cephfs metadata server +sh ./mds.sh + +# Prepare a RBD volume "foo" (only with layering feature, the others may +# require newer clients). +# NOTE: we need Ceph kernel modules on the host that runs the client! +rbd import --image-feature layering block foo + +# Prepare a cephfs volume +ceph osd pool create cephfs_data 4 +ceph osd pool create cephfs_metadata 4 +ceph fs new cephfs cephfs_metadata cephfs_data +# Put index.html into the volume +# It takes a while until the volume created above is mountable, +# 1 second is usually enough, but try indefinetily. +sleep 1 +while ! ceph-fuse -m `hostname -i`:6789 /mnt; do + echo "Waiting for cephfs to be up" + sleep 1 +done +echo "Hello Ceph!" > /mnt/index.html +chmod 644 /mnt/index.html +umount /mnt echo "Ceph is ready" diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/ceph.conf.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/ceph.conf.sh index ecafa43d6..6db6658d1 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/ceph.conf.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/ceph.conf.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -29,9 +29,13 @@ host = cephbox mon addr = $1 [osd] -osd journal size = 128 +osd journal size = 128 journal dio = false +# allow running on ext4 +osd max object name len = 256 +osd max object namespace len = 64 + [osd.0] osd host = cephbox " > /etc/ceph/ceph.conf diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/create_block.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/create_block.sh index e865463a6..7d29aff1e 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/create_block.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/create_block.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -36,8 +36,9 @@ cleanup() trap cleanup TERM EXIT -# Create 1MB device with ext2 -dd if=/dev/zero of=block count=1 bs=1M +# Create 120MB device with ext2 +# (volume_io tests need at least 100MB) +dd if=/dev/zero of=block seek=120 count=1 bs=1M mkfs.ext2 block # Add index.html to it diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/mds.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/mds.sh new file mode 100755 index 000000000..a5c896774 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/mds.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# 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. + +# +# Configures Ceph Metadata Service (mds), needed by CephFS +# +ceph-mds -i cephfs -c /etc/ceph/ceph.conf diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/mon.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/mon.sh index e97baee5a..6865eef65 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/mon.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/mon.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/osd.sh b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/osd.sh index fb18f9cb9..9c58ef4c7 100755 --- a/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/osd.sh +++ b/vendor/k8s.io/kubernetes/test/images/volumes-tester/rbd/osd.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/integration/BUILD b/vendor/k8s.io/kubernetes/test/integration/BUILD index c426000b8..d6e306517 100644 --- a/vendor/k8s.io/kubernetes/test/integration/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/BUILD @@ -48,6 +48,7 @@ filegroup( "//test/integration/examples:all-srcs", "//test/integration/framework:all-srcs", "//test/integration/garbagecollector:all-srcs", + "//test/integration/ipamperf:all-srcs", "//test/integration/master:all-srcs", "//test/integration/metrics:all-srcs", "//test/integration/objectmeta:all-srcs", @@ -61,6 +62,7 @@ filegroup( "//test/integration/scheduler_perf:all-srcs", "//test/integration/secrets:all-srcs", "//test/integration/serviceaccount:all-srcs", + "//test/integration/statefulset:all-srcs", "//test/integration/storageclasses:all-srcs", "//test/integration/tls:all-srcs", "//test/integration/ttlcontroller:all-srcs", diff --git a/vendor/k8s.io/kubernetes/test/integration/apiserver/BUILD b/vendor/k8s.io/kubernetes/test/integration/apiserver/BUILD index 1bcb232cd..91d9695c0 100644 --- a/vendor/k8s.io/kubernetes/test/integration/apiserver/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/apiserver/BUILD @@ -23,6 +23,7 @@ go_test( "//pkg/api/testapi:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", "//pkg/master:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", @@ -33,7 +34,7 @@ go_test( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/rbac/v1alpha1:go_default_library", - "//vendor/k8s.io/api/scheduling/v1alpha1:go_default_library", + "//vendor/k8s.io/api/scheduling/v1beta1:go_default_library", "//vendor/k8s.io/api/settings/v1alpha1:go_default_library", "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", @@ -43,9 +44,9 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/k8s.io/apiserver/pkg/endpoints/handlers:go_default_library", "//vendor/k8s.io/apiserver/pkg/features:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/apiserver/apiserver_test.go b/vendor/k8s.io/kubernetes/test/integration/apiserver/apiserver_test.go index dd232eb96..38e604faf 100644 --- a/vendor/k8s.io/kubernetes/test/integration/apiserver/apiserver_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/apiserver/apiserver_test.go @@ -46,7 +46,6 @@ import ( func setup(t *testing.T, groupVersions ...schema.GroupVersion) (*httptest.Server, clientset.Interface, framework.CloseFunc) { masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.ExtraConfig.EnableCoreControllers = false if len(groupVersions) > 0 { resourceConfig := master.DefaultAPIResourceConfigSource() resourceConfig.EnableVersions(groupVersions...) @@ -239,3 +238,86 @@ func TestAPIListChunking(t *testing.T) { t.Errorf("unexpected items: %#v", list) } } + +func makeSecret(name string) *v1.Secret { + return &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Data: map[string][]byte{ + "key": []byte("value"), + }, + } +} + +func TestNameInFieldSelector(t *testing.T) { + s, clientSet, closeFn := setup(t) + defer closeFn() + + numNamespaces := 3 + namespaces := make([]*v1.Namespace, 0, numNamespaces) + for i := 0; i < 3; i++ { + ns := framework.CreateTestingNamespace(fmt.Sprintf("ns%d", i), s, t) + defer framework.DeleteTestingNamespace(ns, s, t) + namespaces = append(namespaces, ns) + + _, err := clientSet.CoreV1().Secrets(ns.Name).Create(makeSecret("foo")) + if err != nil { + t.Errorf("Couldn't create secret: %v", err) + } + _, err = clientSet.CoreV1().Secrets(ns.Name).Create(makeSecret("bar")) + if err != nil { + t.Errorf("Couldn't create secret: %v", err) + } + } + + testcases := []struct { + namespace string + selector string + expectedSecrets int + }{ + { + namespace: "", + selector: "metadata.name=foo", + expectedSecrets: numNamespaces, + }, + { + namespace: "", + selector: "metadata.name=foo,metadata.name=bar", + expectedSecrets: 0, + }, + { + namespace: "", + selector: "metadata.name=foo,metadata.namespace=ns1", + expectedSecrets: 1, + }, + { + namespace: "ns1", + selector: "metadata.name=foo,metadata.namespace=ns1", + expectedSecrets: 1, + }, + { + namespace: "ns1", + selector: "metadata.name=foo,metadata.namespace=ns2", + expectedSecrets: 0, + }, + { + namespace: "ns1", + selector: "metadata.name=foo,metadata.namespace=", + expectedSecrets: 0, + }, + } + + for _, tc := range testcases { + opts := metav1.ListOptions{ + FieldSelector: tc.selector, + } + secrets, err := clientSet.CoreV1().Secrets(tc.namespace).List(opts) + if err != nil { + t.Errorf("%s: Unexpected error: %v", tc.selector, err) + } + if len(secrets.Items) != tc.expectedSecrets { + t.Errorf("%s: Unexpected number of secrets: %d, expected: %d", tc.selector, len(secrets.Items), tc.expectedSecrets) + } + } +} diff --git a/vendor/k8s.io/kubernetes/test/integration/apiserver/patch_test.go b/vendor/k8s.io/kubernetes/test/integration/apiserver/patch_test.go index 56bf90919..13640b54c 100644 --- a/vendor/k8s.io/kubernetes/test/integration/apiserver/patch_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/apiserver/patch_test.go @@ -24,18 +24,15 @@ import ( "github.com/pborman/uuid" - "reflect" - "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apiserver/pkg/endpoints/handlers" "k8s.io/kubernetes/test/integration/framework" ) -// Tests that the apiserver retries non-overlapping conflicts on patches +// Tests that the apiserver retries patches func TestPatchConflicts(t *testing.T) { s, clientSet, closeFn := setup(t) defer closeFn() @@ -43,28 +40,41 @@ func TestPatchConflicts(t *testing.T) { ns := framework.CreateTestingNamespace("status-code", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - // Create the object we're going to conflict on - clientSet.CoreV1().Secrets(ns.Name).Create(&v1.Secret{ + numOfConcurrentPatches := 100 + + UIDs := make([]types.UID, numOfConcurrentPatches) + ownerRefs := []metav1.OwnerReference{} + for i := 0; i < numOfConcurrentPatches; i++ { + uid := types.UID(uuid.NewRandom().String()) + ownerName := fmt.Sprintf("owner-%d", i) + UIDs[i] = uid + ownerRefs = append(ownerRefs, metav1.OwnerReference{ + APIVersion: "example.com/v1", + Kind: "Foo", + Name: ownerName, + UID: uid, + }) + } + secret := &v1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: "test", - // Populate annotations so the strategic patch descends, compares, and notices the $patch directive - Annotations: map[string]string{"initial": "value"}, + Name: "test", + OwnerReferences: ownerRefs, }, - }) + } + + // Create the object we're going to conflict on + clientSet.CoreV1().Secrets(ns.Name).Create(secret) client := clientSet.CoreV1().RESTClient() successes := int32(0) - // Run a lot of simultaneous patch operations to exercise internal API server retry of patch application. - // Internally, a patch API call retries up to MaxRetryWhenPatchConflicts times if the resource version of the object has changed. - // If the resource version of the object changed between attempts, that means another one of our patch requests succeeded. - // That means if we run 2*MaxRetryWhenPatchConflicts patch attempts, we should see at least MaxRetryWhenPatchConflicts succeed. + // Run a lot of simultaneous patch operations to exercise internal API server retry of application of patches that do not specify resourceVersion. + // They should all succeed. wg := sync.WaitGroup{} - for i := 0; i < (2 * handlers.MaxRetryWhenPatchConflicts); i++ { + for i := 0; i < numOfConcurrentPatches; i++ { wg.Add(1) go func(i int) { defer wg.Done() - annotationName := fmt.Sprintf("annotation-%d", i) labelName := fmt.Sprintf("label-%d", i) value := uuid.NewRandom().String() @@ -72,7 +82,7 @@ func TestPatchConflicts(t *testing.T) { Namespace(ns.Name). Resource("secrets"). Name("test"). - Body([]byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}, "annotations":{"$patch":"replace","%s":"%s"}}}`, labelName, value, annotationName, value))). + Body([]byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}, "ownerReferences":[{"$patch":"delete","uid":"%s"}]}}`, labelName, value, UIDs[i]))). Do(). Get() @@ -95,9 +105,14 @@ func TestPatchConflicts(t *testing.T) { t.Errorf("patch of %s was ineffective, expected %s=%s, got labels %#v", "secrets", labelName, value, accessor.GetLabels()) return } - // make sure the patch directive didn't get lost, and that the entire annotation map was replaced - if !reflect.DeepEqual(accessor.GetAnnotations(), map[string]string{annotationName: value}) { - t.Errorf("patch of %s with $patch directive was ineffective, didn't replace entire annotations map: %#v", "secrets", accessor.GetAnnotations()) + // make sure the patch directive didn't get lost, and that an entry in the ownerReference list was deleted. + found := findOwnerRefByUID(accessor.GetOwnerReferences(), UIDs[i]) + if err != nil { + t.Errorf("%v", err) + return + } + if found { + t.Errorf("patch of %s with $patch directive was ineffective, didn't delete the entry in the ownerReference slice: %#v", "secrets", UIDs[i]) } atomic.AddInt32(&successes, 1) @@ -105,10 +120,19 @@ func TestPatchConflicts(t *testing.T) { } wg.Wait() - if successes < handlers.MaxRetryWhenPatchConflicts { - t.Errorf("Expected at least %d successful patches for %s, got %d", handlers.MaxRetryWhenPatchConflicts, "secrets", successes) + if successes < int32(numOfConcurrentPatches) { + t.Errorf("Expected at least %d successful patches for %s, got %d", numOfConcurrentPatches, "secrets", successes) } else { t.Logf("Got %d successful patches for %s", successes, "secrets") } } + +func findOwnerRefByUID(ownerRefs []metav1.OwnerReference, uid types.UID) bool { + for _, of := range ownerRefs { + if of.UID == uid { + return true + } + } + return false +} diff --git a/vendor/k8s.io/kubernetes/test/integration/apiserver/print_test.go b/vendor/k8s.io/kubernetes/test/integration/apiserver/print_test.go index 3f0fc6368..65e5dde0d 100644 --- a/vendor/k8s.io/kubernetes/test/integration/apiserver/print_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/apiserver/print_test.go @@ -19,23 +19,28 @@ package apiserver import ( "encoding/json" "fmt" + "io/ioutil" + "os" "reflect" "strings" "testing" + "time" batchv2alpha1 "k8s.io/api/batch/v2alpha1" rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" - schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + schedulerapi "k8s.io/api/scheduling/v1beta1" settingsv1alpha1 "k8s.io/api/settings/v1alpha1" storagev1alpha1 "k8s.io/api/storage/v1alpha1" "k8s.io/apimachinery/pkg/api/meta" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/discovery" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/gengo/examples/set-gen/sets" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" "k8s.io/kubernetes/test/integration/framework" @@ -50,7 +55,6 @@ var kindWhiteList = sets.NewString( "ExportOptions", "GetOptions", "ListOptions", - "NodeConfigSource", "NodeProxyOptions", "PodAttachOptions", "PodExecOptions", @@ -136,7 +140,7 @@ func TestServerSidePrint(t *testing.T) { batchv2alpha1.SchemeGroupVersion, rbacv1alpha1.SchemeGroupVersion, settingsv1alpha1.SchemeGroupVersion, - schedulingv1alpha1.SchemeGroupVersion, + schedulerapi.SchemeGroupVersion, storagev1alpha1.SchemeGroupVersion) defer closeFn() @@ -146,9 +150,35 @@ func TestServerSidePrint(t *testing.T) { tableParam := fmt.Sprintf("application/json;as=Table;g=%s;v=%s, application/json", metav1beta1.GroupName, metav1beta1.SchemeGroupVersion.Version) printer := newFakePrinter(printersinternal.AddHandlers) - factory := util.NewFactory(clientcmd.NewDefaultClientConfig(*createKubeConfig(s.URL), &clientcmd.ConfigOverrides{})) - mapper, _ := factory.Object() + configFlags := genericclioptions.NewTestConfigFlags(). + WithClientConfig(clientcmd.NewDefaultClientConfig(*createKubeConfig(s.URL), &clientcmd.ConfigOverrides{})) + restConfig, err := configFlags.ToRESTConfig() + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + cacheDir, err := ioutil.TempDir(os.TempDir(), "test-integration-apiserver-print") + if err != nil { + t.Errorf("unexpected error: %v", err) + } + defer func() { + os.Remove(cacheDir) + }() + + cachedClient, err := discovery.NewCachedDiscoveryClientForConfig(restConfig, cacheDir, "", time.Duration(10*time.Minute)) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + configFlags.WithDiscoveryClient(cachedClient) + + factory := util.NewFactory(configFlags) + mapper, err := factory.ToRESTMapper() + if err != nil { + t.Errorf("unexpected error getting mapper: %v", err) + return + } for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() { // we do not care about internal objects or lists // TODO make sure this is always true if gvk.Version == runtime.APIVersionInternal || strings.HasSuffix(apiType.Name(), "List") { @@ -174,7 +204,7 @@ func TestServerSidePrint(t *testing.T) { if mapping.Scope.Name() == meta.RESTScopeNameNamespace { req = req.Namespace(ns.Name) } - body, err := req.Resource(mapping.Resource).SetHeader("Accept", tableParam).Do().Raw() + body, err := req.Resource(mapping.Resource.Resource).SetHeader("Accept", tableParam).Do().Raw() if err != nil { t.Errorf("unexpected error getting %s: %v", gvk, err) continue @@ -192,7 +222,7 @@ func TestServerSidePrint(t *testing.T) { continue } intGV := gvk.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion() - intObj, err := mapping.ConvertToVersion(obj, intGV) + intObj, err := legacyscheme.Scheme.ConvertToVersion(obj, intGV) if err != nil { t.Errorf("unexpected error converting %s to internal: %v", gvk, err) continue diff --git a/vendor/k8s.io/kubernetes/test/integration/auth/BUILD b/vendor/k8s.io/kubernetes/test/integration/auth/BUILD index 34331a702..e5ed62090 100644 --- a/vendor/k8s.io/kubernetes/test/integration/auth/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/auth/BUILD @@ -44,7 +44,6 @@ go_test( "//pkg/registry/rbac/rolebinding:go_default_library", "//pkg/registry/rbac/rolebinding/storage:go_default_library", "//pkg/serviceaccount:go_default_library", - "//plugin/pkg/admission/admit:go_default_library", "//plugin/pkg/admission/noderestriction:go_default_library", "//plugin/pkg/auth/authenticator/token/bootstrap:go_default_library", "//plugin/pkg/auth/authorizer/rbac:go_default_library", @@ -52,6 +51,7 @@ go_test( "//test/integration:go_default_library", "//test/integration/framework:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/gopkg.in/square/go-jose.v2/jwt:go_default_library", "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/authentication/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/auth/accessreview_test.go b/vendor/k8s.io/kubernetes/test/integration/auth/accessreview_test.go index f5835aaec..4880e354d 100644 --- a/vendor/k8s.io/kubernetes/test/integration/auth/accessreview_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/auth/accessreview_test.go @@ -31,7 +31,6 @@ import ( authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" api "k8s.io/kubernetes/pkg/apis/core" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/plugin/pkg/admission/admit" "k8s.io/kubernetes/test/integration/framework" ) @@ -57,7 +56,6 @@ func TestSubjectAccessReview(t *testing.T) { masterConfig := framework.NewIntegrationTestMasterConfig() masterConfig.GenericConfig.Authentication.Authenticator = authenticator.RequestFunc(alwaysAlice) masterConfig.GenericConfig.Authorization.Authorizer = sarAuthorizer{} - masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -151,7 +149,6 @@ func TestSelfSubjectAccessReview(t *testing.T) { return &user.DefaultInfo{Name: username}, true, nil }) masterConfig.GenericConfig.Authorization.Authorizer = sarAuthorizer{} - masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -231,7 +228,6 @@ func TestLocalSubjectAccessReview(t *testing.T) { masterConfig := framework.NewIntegrationTestMasterConfig() masterConfig.GenericConfig.Authentication.Authenticator = authenticator.RequestFunc(alwaysAlice) masterConfig.GenericConfig.Authorization.Authorizer = sarAuthorizer{} - masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() diff --git a/vendor/k8s.io/kubernetes/test/integration/auth/auth_test.go b/vendor/k8s.io/kubernetes/test/integration/auth/auth_test.go index d66eeb0fa..a40046218 100644 --- a/vendor/k8s.io/kubernetes/test/integration/auth/auth_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/auth/auth_test.go @@ -51,7 +51,6 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/auth/authorizer/abac" - "k8s.io/kubernetes/plugin/pkg/admission/admit" "k8s.io/kubernetes/test/integration" "k8s.io/kubernetes/test/integration/framework" ) @@ -555,7 +554,6 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) { masterConfig := framework.NewIntegrationTestMasterConfig() masterConfig.GenericConfig.Authentication.Authenticator = getTestTokenAuth() masterConfig.GenericConfig.Authorization.Authorizer = allowAliceAuthorizer{} - masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() diff --git a/vendor/k8s.io/kubernetes/test/integration/auth/bootstraptoken_test.go b/vendor/k8s.io/kubernetes/test/integration/auth/bootstraptoken_test.go index 38139adc7..438dfd2c7 100644 --- a/vendor/k8s.io/kubernetes/test/integration/auth/bootstraptoken_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/auth/bootstraptoken_test.go @@ -29,7 +29,6 @@ import ( "k8s.io/apiserver/pkg/authentication/request/bearertoken" bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/plugin/pkg/admission/admit" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap" bootstraputil "k8s.io/kubernetes/test/e2e/lifecycle/bootstrap" "k8s.io/kubernetes/test/integration" @@ -126,7 +125,6 @@ func TestBootstrapTokenAuth(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() masterConfig.GenericConfig.Authentication.Authenticator = authenticator - masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() diff --git a/vendor/k8s.io/kubernetes/test/integration/auth/node_test.go b/vendor/k8s.io/kubernetes/test/integration/auth/node_test.go index 929f8828d..eb6526136 100644 --- a/vendor/k8s.io/kubernetes/test/integration/auth/node_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/auth/node_test.go @@ -81,6 +81,9 @@ func TestNodeAuthorizer(t *testing.T) { // Enabled CSIPersistentVolume feature at startup so volumeattachments get watched defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIPersistentVolume, true)() + // Enable DynamicKubeletConfig feature so that Node.Spec.ConfigSource can be set + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicKubeletConfig, true)() + // Set up Node+RBAC authorizer authorizerConfig := &authorizer.AuthorizationConfig{ AuthorizationModes: []string{"Node", "RBAC"}, @@ -94,7 +97,7 @@ func TestNodeAuthorizer(t *testing.T) { // Set up NodeRestriction admission nodeRestrictionAdmission := noderestriction.NewPlugin(nodeidentifier.NewDefaultNodeIdentifier()) - nodeRestrictionAdmission.SetInternalKubeClientSet(superuserClient) + nodeRestrictionAdmission.SetInternalKubeInformerFactory(informerFactory) if err := nodeRestrictionAdmission.ValidateInitialization(); err != nil { t.Fatal(err) } @@ -135,6 +138,9 @@ func TestNodeAuthorizer(t *testing.T) { if _, err := superuserClient.Core().ConfigMaps("ns").Create(&api.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "myconfigmap"}}); err != nil { t.Fatal(err) } + if _, err := superuserClient.Core().ConfigMaps("ns").Create(&api.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "myconfigmapconfigsource"}}); err != nil { + t.Fatal(err) + } pvName := "mypv" if _, err := superuserClientExternal.StorageV1beta1().VolumeAttachments().Create(&storagev1beta1.VolumeAttachment{ ObjectMeta: metav1.ObjectMeta{Name: "myattachment"}, @@ -186,6 +192,12 @@ func TestNodeAuthorizer(t *testing.T) { return err } } + getConfigMapConfigSource := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().ConfigMaps("ns").Get("myconfigmapconfigsource", metav1.GetOptions{}) + return err + } + } getPVC := func(client clientset.Interface) func() error { return func() error { _, err := client.Core().PersistentVolumeClaims("ns").Get("mypvc", metav1.GetOptions{}) @@ -267,6 +279,34 @@ func TestNodeAuthorizer(t *testing.T) { return err } } + setNode2ConfigSource := func(client clientset.Interface) func() error { + return func() error { + node2, err := client.Core().Nodes().Get("node2", metav1.GetOptions{}) + if err != nil { + return err + } + node2.Spec.ConfigSource = &api.NodeConfigSource{ + ConfigMap: &api.ConfigMapNodeConfigSource{ + Namespace: "ns", + Name: "myconfigmapconfigsource", + KubeletConfigKey: "kubelet", + }, + } + _, err = client.Core().Nodes().Update(node2) + return err + } + } + unsetNode2ConfigSource := func(client clientset.Interface) func() error { + return func() error { + node2, err := client.Core().Nodes().Get("node2", metav1.GetOptions{}) + if err != nil { + return err + } + node2.Spec.ConfigSource = nil + _, err = client.Core().Nodes().Update(node2) + return err + } + } updateNode2Status := func(client clientset.Interface) func() error { return func() error { _, err := client.Core().Nodes().UpdateStatus(&api.Node{ @@ -420,6 +460,7 @@ func TestNodeAuthorizer(t *testing.T) { expectAllowed(t, deleteNode2NormalPod(node2Client)) expectAllowed(t, createNode2MirrorPod(node2Client)) expectAllowed(t, deleteNode2MirrorPod(node2Client)) + // recreate as an admin to test eviction expectAllowed(t, createNode2NormalPod(superuserClient)) expectAllowed(t, createNode2MirrorPod(superuserClient)) @@ -449,6 +490,25 @@ func TestNodeAuthorizer(t *testing.T) { expectForbidden(t, getVolumeAttachment(node1ClientExternal)) expectAllowed(t, getVolumeAttachment(node2ClientExternal)) + // create node2 again + expectAllowed(t, createNode2(node2Client)) + // node2 can not set its own config source + expectForbidden(t, setNode2ConfigSource(node2Client)) + // node2 can not access the configmap config source yet + expectForbidden(t, getConfigMapConfigSource(node2Client)) + // superuser can access the configmap config source + expectAllowed(t, getConfigMapConfigSource(superuserClient)) + // superuser can set node2's config source + expectAllowed(t, setNode2ConfigSource(superuserClient)) + // node2 can now get the configmap assigned as its config source + expectAllowed(t, getConfigMapConfigSource(node2Client)) + // superuser can unset node2's config source + expectAllowed(t, unsetNode2ConfigSource(superuserClient)) + // node2 can no longer get the configmap after it is unassigned as its config source + expectForbidden(t, getConfigMapConfigSource(node2Client)) + // clean up node2 + expectAllowed(t, deleteNode2(node2Client)) + //TODO(mikedanese): integration test node restriction of TokenRequest } diff --git a/vendor/k8s.io/kubernetes/test/integration/auth/svcaccttoken_test.go b/vendor/k8s.io/kubernetes/test/integration/auth/svcaccttoken_test.go index fe8421b95..ac7ba22ed 100644 --- a/vendor/k8s.io/kubernetes/test/integration/auth/svcaccttoken_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/auth/svcaccttoken_test.go @@ -24,17 +24,20 @@ import ( "testing" "time" + "gopkg.in/square/go-jose.v2/jwt" authenticationv1 "k8s.io/api/authentication/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/authentication/request/bearertoken" + apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/apiserver/pkg/authorization/authorizerfactory" utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" clientset "k8s.io/client-go/kubernetes" externalclientset "k8s.io/client-go/kubernetes" certutil "k8s.io/client-go/util/cert" + "k8s.io/kubernetes/pkg/apis/core" serviceaccountgetter "k8s.io/kubernetes/pkg/controller/serviceaccount" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/serviceaccount" @@ -118,7 +121,6 @@ func TestServiceAccountTokenCreate(t *testing.T) { }, } - one = int64(1) wrongUID = types.UID("wrong") noUID = types.UID("") ) @@ -126,8 +128,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("bound to service account", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, }, } @@ -157,8 +158,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("bound to service account and pod", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, BoundObjectRef: &authenticationv1.BoundObjectReference{ Kind: "Pod", APIVersion: "v1", @@ -211,8 +211,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("bound to service account and secret", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, BoundObjectRef: &authenticationv1.BoundObjectReference{ Kind: "Secret", APIVersion: "v1", @@ -266,8 +265,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("bound to service account and pod running as different service account", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, BoundObjectRef: &authenticationv1.BoundObjectReference{ Kind: "Pod", APIVersion: "v1", @@ -289,8 +287,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { t.Run("expired token", func(t *testing.T) { treq := &authenticationv1.TokenRequest{ Spec: authenticationv1.TokenRequestSpec{ - Audiences: []string{"api"}, - ExpirationSeconds: &one, + Audiences: []string{"api"}, }, } @@ -303,7 +300,26 @@ func TestServiceAccountTokenCreate(t *testing.T) { } doTokenReview(t, cs, treq, false) - time.Sleep(63 * time.Second) + + // backdate the token + then := time.Now().Add(-2 * time.Hour) + sc := &jwt.Claims{ + Subject: apiserverserviceaccount.MakeUsername(sa.Namespace, sa.Name), + Audience: jwt.Audience([]string{"api"}), + IssuedAt: jwt.NewNumericDate(then), + NotBefore: jwt.NewNumericDate(then), + Expiry: jwt.NewNumericDate(then.Add(time.Duration(60*60) * time.Second)), + } + coresa := core.ServiceAccount{ + ObjectMeta: sa.ObjectMeta, + } + _, pc := serviceaccount.Claims(coresa, nil, nil, 0, nil) + tok, err := masterConfig.ExtraConfig.ServiceAccountIssuer.GenerateToken(sc, pc) + if err != nil { + t.Fatalf("err signing expired token: %v", err) + } + + treq.Status.Token = tok doTokenReview(t, cs, treq, true) }) @@ -342,6 +358,86 @@ func TestServiceAccountTokenCreate(t *testing.T) { doTokenReview(t, cs, treq, false) }) + + t.Run("a token should be invalid after recreating same name pod", func(t *testing.T) { + treq := &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + Audiences: []string{"api"}, + BoundObjectRef: &authenticationv1.BoundObjectReference{ + Kind: "Pod", + APIVersion: "v1", + Name: pod.Name, + }, + }, + } + + sa, del := createDeleteSvcAcct(t, cs, sa) + defer del() + originalPod, originalDelPod := createDeletePod(t, cs, pod) + defer originalDelPod() + + treq.Spec.BoundObjectRef.UID = originalPod.UID + if treq, err = cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err != nil { + t.Fatalf("err: %v", err) + } + + checkPayload(t, treq.Status.Token, `"system:serviceaccount:myns:test-svcacct"`, "sub") + checkPayload(t, treq.Status.Token, `["api"]`, "aud") + checkPayload(t, treq.Status.Token, `"test-pod"`, "kubernetes.io", "pod", "name") + checkPayload(t, treq.Status.Token, "null", "kubernetes.io", "secret") + checkPayload(t, treq.Status.Token, `"myns"`, "kubernetes.io", "namespace") + checkPayload(t, treq.Status.Token, `"test-svcacct"`, "kubernetes.io", "serviceaccount", "name") + + doTokenReview(t, cs, treq, false) + originalDelPod() + doTokenReview(t, cs, treq, true) + + _, recreateDelPod := createDeletePod(t, cs, pod) + defer recreateDelPod() + + doTokenReview(t, cs, treq, true) + }) + + t.Run("a token should be invalid after recreating same name secret", func(t *testing.T) { + treq := &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + Audiences: []string{"api"}, + BoundObjectRef: &authenticationv1.BoundObjectReference{ + Kind: "Secret", + APIVersion: "v1", + Name: secret.Name, + UID: secret.UID, + }, + }, + } + + sa, del := createDeleteSvcAcct(t, cs, sa) + defer del() + + originalSecret, originalDelSecret := createDeleteSecret(t, cs, secret) + defer originalDelSecret() + + treq.Spec.BoundObjectRef.UID = originalSecret.UID + if treq, err = cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err != nil { + t.Fatalf("err: %v", err) + } + + checkPayload(t, treq.Status.Token, `"system:serviceaccount:myns:test-svcacct"`, "sub") + checkPayload(t, treq.Status.Token, `["api"]`, "aud") + checkPayload(t, treq.Status.Token, `null`, "kubernetes.io", "pod") + checkPayload(t, treq.Status.Token, `"test-secret"`, "kubernetes.io", "secret", "name") + checkPayload(t, treq.Status.Token, `"myns"`, "kubernetes.io", "namespace") + checkPayload(t, treq.Status.Token, `"test-svcacct"`, "kubernetes.io", "serviceaccount", "name") + + doTokenReview(t, cs, treq, false) + originalDelSecret() + doTokenReview(t, cs, treq, true) + + _, recreateDelSecret := createDeleteSecret(t, cs, secret) + defer recreateDelSecret() + + doTokenReview(t, cs, treq, true) + }) } func doTokenReview(t *testing.T, cs externalclientset.Interface, treq *authenticationv1.TokenRequest, expectErr bool) { diff --git a/vendor/k8s.io/kubernetes/test/integration/benchmark-controller.json b/vendor/k8s.io/kubernetes/test/integration/benchmark-controller.json index 4cce2217e..4d589dd05 100644 --- a/vendor/k8s.io/kubernetes/test/integration/benchmark-controller.json +++ b/vendor/k8s.io/kubernetes/test/integration/benchmark-controller.json @@ -17,7 +17,7 @@ "spec": { "containers": [{ "name": "test-container", - "image": "k8s.gcr.io/pause-amd64:3.1" + "image": "k8s.gcr.io/pause:3.1" }] } } diff --git a/vendor/k8s.io/kubernetes/test/integration/client/BUILD b/vendor/k8s.io/kubernetes/test/integration/client/BUILD index 11c1ee967..040a3b762 100644 --- a/vendor/k8s.io/kubernetes/test/integration/client/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/client/BUILD @@ -18,11 +18,10 @@ go_test( "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/version:go_default_library", - "//test/e2e/framework:go_default_library", "//test/integration/framework:go_default_library", + "//test/utils/image:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/client/client_test.go b/vendor/k8s.io/kubernetes/test/integration/client/client_test.go index 97a9b9cac..3dcbd338e 100644 --- a/vendor/k8s.io/kubernetes/test/integration/client/client_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/client/client_test.go @@ -27,7 +27,6 @@ import ( "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" @@ -39,17 +38,16 @@ import ( clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/version" - e2e "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/integration/framework" + imageutils "k8s.io/kubernetes/test/utils/image" ) func TestClient(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) ns := framework.CreateTestingNamespace("client", s, t) defer framework.DeleteTestingNamespace(ns, s, t) @@ -121,7 +119,7 @@ func TestAtomicPut(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() - c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) ns := framework.CreateTestingNamespace("atomic-put", s, t) defer framework.DeleteTestingNamespace(ns, s, t) @@ -213,7 +211,7 @@ func TestPatch(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() - c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) ns := framework.CreateTestingNamespace("patch", s, t) defer framework.DeleteTestingNamespace(ns, s, t) @@ -286,23 +284,6 @@ func TestPatch(t *testing.T) { t.Logf("%v", string(jsonObj)) } - obj, err := result.Get() - if err != nil { - t.Fatal(err) - } - metadata, err := meta.Accessor(obj) - if err != nil { - t.Fatal(err) - } - // this call waits for the resourceVersion to be reached in the cache before returning. We need to do this because - // the patch gets its initial object from the storage, and the cache serves that. If it is out of date, - // then our initial patch is applied to an old resource version, which conflicts and then the updated object shows - // a conflicting diff, which permanently fails the patch. This gives expected stability in the patch without - // retrying on an known number of conflicts below in the test. - if _, err := c.Core().Pods(ns.Name).Get(name, metav1.GetOptions{ResourceVersion: metadata.GetResourceVersion()}); err != nil { - t.Fatal(err) - } - return nil } @@ -352,7 +333,7 @@ func TestPatchWithCreateOnUpdate(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() - c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) ns := framework.CreateTestingNamespace("patch-with-create", s, t) defer framework.DeleteTestingNamespace(ns, s, t) @@ -463,7 +444,7 @@ func TestAPIVersions(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() - c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) clientVersion := c.Core().RESTClient().APIVersion().String() g, err := c.Discovery().ServerGroups() @@ -488,7 +469,7 @@ func TestSingleWatch(t *testing.T) { ns := framework.CreateTestingNamespace("single-watch", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) mkEvent := func(i int) *v1.Event { name := fmt.Sprintf("event-%v", i) @@ -575,7 +556,7 @@ func TestMultiWatch(t *testing.T) { ns := framework.CreateTestingNamespace("multi-watch", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) dummyEvent := func(i int) *v1.Event { name := fmt.Sprintf("unrelated-%v", i) @@ -612,7 +593,7 @@ func TestMultiWatch(t *testing.T) { Spec: v1.PodSpec{ Containers: []v1.Container{{ Name: "pause", - Image: e2e.GetPauseImageName(client), + Image: imageutils.GetPauseImageName(), }}, }, }) @@ -718,7 +699,7 @@ func TestMultiWatch(t *testing.T) { Spec: v1.PodSpec{ Containers: []v1.Container{{ Name: "nothing", - Image: e2e.GetPauseImageName(client), + Image: imageutils.GetPauseImageName(), }}, }, }) @@ -749,7 +730,7 @@ func TestMultiWatch(t *testing.T) { if err != nil { panic(fmt.Sprintf("Couldn't get %v: %v", name, err)) } - pod.Spec.Containers[0].Image = e2e.GetPauseImageName(client) + pod.Spec.Containers[0].Image = imageutils.GetPauseImageName() sentTimes <- timePair{time.Now(), name} if _, err := client.Core().Pods(ns.Name).Update(pod); err != nil { panic(fmt.Sprintf("Couldn't make %v: %v", name, err)) @@ -831,7 +812,7 @@ func TestSelfLinkOnNamespace(t *testing.T) { ns := framework.CreateTestingNamespace("selflink", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + c := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) runSelfLinkTestOnNamespace(t, c, ns.Name) } diff --git a/vendor/k8s.io/kubernetes/test/integration/client/dynamic_client_test.go b/vendor/k8s.io/kubernetes/test/integration/client/dynamic_client_test.go index 2c0fbb6f6..787e1fb7b 100644 --- a/vendor/k8s.io/kubernetes/test/integration/client/dynamic_client_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/client/dynamic_client_test.go @@ -24,6 +24,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" @@ -38,36 +39,19 @@ func TestDynamicClient(t *testing.T) { ns := framework.CreateTestingNamespace("dynamic-client", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - gv := testapi.Groups[v1.GroupName].GroupVersion() + gv := &schema.GroupVersion{Group: "", Version: "v1"} config := &restclient.Config{ Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: gv}, } client := clientset.NewForConfigOrDie(config) - dynamicClient, err := dynamic.NewClient(config) - _ = dynamicClient + dynamicClient, err := dynamic.NewForConfig(config) if err != nil { t.Fatalf("unexpected error creating dynamic client: %v", err) } - // Find the Pod resource - resources, err := client.Discovery().ServerResourcesForGroupVersion(gv.String()) - if err != nil { - t.Fatalf("unexpected error listing resources: %v", err) - } - - var resource metav1.APIResource - for _, r := range resources.APIResources { - if r.Kind == "Pod" { - resource = r - break - } - } - - if len(resource.Name) == 0 { - t.Fatalf("could not find the pod resource in group/version %q", gv.String()) - } + resource := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"} // Create a Pod with the normal client pod := &v1.Pod{ @@ -90,11 +74,7 @@ func TestDynamicClient(t *testing.T) { } // check dynamic list - obj, err := dynamicClient.Resource(&resource, ns.Name).List(metav1.ListOptions{}) - unstructuredList, ok := obj.(*unstructured.UnstructuredList) - if !ok { - t.Fatalf("expected *unstructured.UnstructuredList, got %#v", obj) - } + unstructuredList, err := dynamicClient.Resource(resource).Namespace(ns.Name).List(metav1.ListOptions{}) if err != nil { t.Fatalf("unexpected error when listing pods: %v", err) } @@ -113,7 +93,7 @@ func TestDynamicClient(t *testing.T) { } // check dynamic get - unstruct, err := dynamicClient.Resource(&resource, ns.Name).Get(actual.Name, metav1.GetOptions{}) + unstruct, err := dynamicClient.Resource(resource).Namespace(ns.Name).Get(actual.Name, metav1.GetOptions{}) if err != nil { t.Fatalf("unexpected error when getting pod %q: %v", actual.Name, err) } @@ -128,7 +108,7 @@ func TestDynamicClient(t *testing.T) { } // delete the pod dynamically - err = dynamicClient.Resource(&resource, ns.Name).Delete(actual.Name, nil) + err = dynamicClient.Resource(resource).Namespace(ns.Name).Delete(actual.Name, nil) if err != nil { t.Fatalf("unexpected error when deleting pod: %v", err) } diff --git a/vendor/k8s.io/kubernetes/test/integration/configmap/BUILD b/vendor/k8s.io/kubernetes/test/integration/configmap/BUILD index de491d588..0bfa9aa51 100644 --- a/vendor/k8s.io/kubernetes/test/integration/configmap/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/configmap/BUILD @@ -14,11 +14,11 @@ go_test( ], tags = ["integration"], deps = [ - "//pkg/api/testapi:go_default_library", "//test/integration:go_default_library", "//test/integration/framework:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/test/integration/configmap/configmap_test.go b/vendor/k8s.io/kubernetes/test/integration/configmap/configmap_test.go index 25600f7bc..64df992e5 100644 --- a/vendor/k8s.io/kubernetes/test/integration/configmap/configmap_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/configmap/configmap_test.go @@ -23,9 +23,9 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/integration" "k8s.io/kubernetes/test/integration/framework" ) @@ -35,7 +35,7 @@ func TestConfigMap(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) ns := framework.CreateTestingNamespace("config-map", s, t) defer framework.DeleteTestingNamespace(ns, s, t) diff --git a/vendor/k8s.io/kubernetes/test/integration/daemonset/BUILD b/vendor/k8s.io/kubernetes/test/integration/daemonset/BUILD index f091f92c7..a1c605370 100644 --- a/vendor/k8s.io/kubernetes/test/integration/daemonset/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/daemonset/BUILD @@ -14,22 +14,32 @@ go_test( ], tags = ["integration"], deps = [ + "//pkg/api/legacyscheme:go_default_library", "//pkg/api/v1/pod:go_default_library", "//pkg/controller/daemon:go_default_library", + "//pkg/features:go_default_library", + "//pkg/scheduler:go_default_library", + "//pkg/scheduler/algorithm:go_default_library", + "//pkg/scheduler/algorithmprovider:go_default_library", + "//pkg/scheduler/factory:go_default_library", "//pkg/util/metrics:go_default_library", "//test/integration/framework:go_default_library", "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_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/util/intstr:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_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/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/integration/daemonset/daemonset_test.go b/vendor/k8s.io/kubernetes/test/integration/daemonset/daemonset_test.go index 3f7b98e76..0a7a72ca1 100644 --- a/vendor/k8s.io/kubernetes/test/integration/daemonset/daemonset_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/daemonset/daemonset_test.go @@ -24,22 +24,36 @@ import ( apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" appstyped "k8s.io/client-go/kubernetes/typed/apps/v1" + clientv1core "k8s.io/client-go/kubernetes/typed/core/v1" corev1typed "k8s.io/client-go/kubernetes/typed/core/v1" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/kubernetes/pkg/api/legacyscheme" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/controller/daemon" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/scheduler" + "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" + _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" + "k8s.io/kubernetes/pkg/scheduler/factory" "k8s.io/kubernetes/pkg/util/metrics" "k8s.io/kubernetes/test/integration/framework" ) +var zero = int64(0) + func setup(t *testing.T) (*httptest.Server, framework.CloseFunc, *daemon.DaemonSetsController, informers.SharedInformerFactory, clientset.Interface) { masterConfig := framework.NewIntegrationTestMasterConfig() _, server, closeFn := framework.RunAMaster(masterConfig) @@ -66,6 +80,62 @@ func setup(t *testing.T) (*httptest.Server, framework.CloseFunc, *daemon.DaemonS return server, closeFn, dc, informers, clientSet } +func setupScheduler( + t *testing.T, + cs clientset.Interface, + informerFactory informers.SharedInformerFactory, + stopCh chan struct{}, +) { + // If ScheduleDaemonSetPods is disabled, do not start scheduler. + if !utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { + return + } + + schedulerConfigFactory := factory.NewConfigFactory( + v1.DefaultSchedulerName, + cs, + informerFactory.Core().V1().Nodes(), + informerFactory.Core().V1().Pods(), + informerFactory.Core().V1().PersistentVolumes(), + informerFactory.Core().V1().PersistentVolumeClaims(), + informerFactory.Core().V1().ReplicationControllers(), + informerFactory.Extensions().V1beta1().ReplicaSets(), + informerFactory.Apps().V1beta1().StatefulSets(), + informerFactory.Core().V1().Services(), + informerFactory.Policy().V1beta1().PodDisruptionBudgets(), + informerFactory.Storage().V1().StorageClasses(), + v1.DefaultHardPodAffinitySymmetricWeight, + true, + false, + ) + + schedulerConfig, err := schedulerConfigFactory.Create() + if err != nil { + t.Fatalf("Couldn't create scheduler config: %v", err) + } + + schedulerConfig.StopEverything = stopCh + + eventBroadcaster := record.NewBroadcaster() + schedulerConfig.Recorder = eventBroadcaster.NewRecorder( + legacyscheme.Scheme, + v1.EventSource{Component: v1.DefaultSchedulerName}, + ) + eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{ + Interface: cs.CoreV1().Events(""), + }) + + sched, err := scheduler.NewFromConfigurator( + &scheduler.FakeConfigurator{Config: schedulerConfig}, nil...) + if err != nil { + t.Fatalf("error creating scheduler: %v", err) + } + + algorithmprovider.ApplyFeatureGates() + + go sched.Run() +} + func testLabels() map[string]string { return map[string]string{"name": "test"} } @@ -92,13 +162,55 @@ func newDaemonSet(name, namespace string) *apps.DaemonSet { Labels: testLabels(), }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "foo", Image: "bar"}}, + Containers: []v1.Container{{Name: "foo", Image: "bar"}}, + TerminationGracePeriodSeconds: &zero, }, }, }, } } +func cleanupDaemonSets(t *testing.T, cs clientset.Interface, ds *apps.DaemonSet) { + ds, err := cs.AppsV1().DaemonSets(ds.Namespace).Get(ds.Name, metav1.GetOptions{}) + if err != nil { + t.Errorf("Failed to get DaemonSet %s/%s: %v", ds.Namespace, ds.Name, err) + return + } + + // We set the nodeSelector to a random label. This label is nearly guaranteed + // to not be set on any node so the DameonSetController will start deleting + // daemon pods. Once it's done deleting the daemon pods, it's safe to delete + // the DaemonSet. + ds.Spec.Template.Spec.NodeSelector = map[string]string{ + string(uuid.NewUUID()): string(uuid.NewUUID()), + } + // force update to avoid version conflict + ds.ResourceVersion = "" + + if ds, err = cs.AppsV1().DaemonSets(ds.Namespace).Update(ds); err != nil { + t.Errorf("Failed to update DaemonSet %s/%s: %v", ds.Namespace, ds.Name, err) + return + } + + // Wait for the daemon set controller to kill all the daemon pods. + if err := wait.Poll(100*time.Millisecond, 30*time.Second, func() (bool, error) { + updatedDS, err := cs.AppsV1().DaemonSets(ds.Namespace).Get(ds.Name, metav1.GetOptions{}) + if err != nil { + return false, nil + } + return updatedDS.Status.CurrentNumberScheduled+updatedDS.Status.NumberMisscheduled == 0, nil + }); err != nil { + t.Errorf("Failed to kill the pods of DaemonSet %s/%s: %v", ds.Namespace, ds.Name, err) + return + } + + falseVar := false + deleteOptions := &metav1.DeleteOptions{OrphanDependents: &falseVar} + if err := cs.AppsV1().DaemonSets(ds.Namespace).Delete(ds.Name, deleteOptions); err != nil { + t.Errorf("Failed to delete DaemonSet %s/%s: %v", ds.Namespace, ds.Name, err) + } +} + func newRollbackStrategy() *apps.DaemonSetUpdateStrategy { one := intstr.FromInt(1) return &apps.DaemonSetUpdateStrategy{ @@ -117,6 +229,12 @@ func updateStrategies() []*apps.DaemonSetUpdateStrategy { return []*apps.DaemonSetUpdateStrategy{newOnDeleteStrategy(), newRollbackStrategy()} } +func featureGates() []utilfeature.Feature { + return []utilfeature.Feature{ + features.ScheduleDaemonSetPods, + } +} + func allocatableResources(memory, cpu string) v1.ResourceList { return v1.ResourceList{ v1.ResourceMemory: resource.MustParse(memory), @@ -140,6 +258,7 @@ func resourcePodSpec(nodeName, memory, cpu string) v1.PodSpec { }, }, }, + TerminationGracePeriodSeconds: &zero, } } @@ -196,7 +315,7 @@ func validateDaemonSetPodsAndMarkReady( t.Errorf("controllerRef.Controller is not set to true") } - if !podutil.IsPodReady(pod) { + if !podutil.IsPodReady(pod) && len(pod.Spec.NodeName) != 0 { podCopy := pod.DeepCopy() podCopy.Status = v1.PodStatus{ Phase: v1.PodRunning, @@ -215,10 +334,47 @@ func validateDaemonSetPodsAndMarkReady( } } +// podUnschedulable returns a condition function that returns true if the given pod +// gets unschedulable status. +func podUnschedulable(c clientset.Interface, podNamespace, podName string) wait.ConditionFunc { + return func() (bool, error) { + pod, err := c.CoreV1().Pods(podNamespace).Get(podName, metav1.GetOptions{}) + if errors.IsNotFound(err) { + return false, nil + } + if err != nil { + // This could be a connection error so we want to retry. + return false, nil + } + _, cond := podutil.GetPodCondition(&pod.Status, v1.PodScheduled) + return cond != nil && cond.Status == v1.ConditionFalse && + cond.Reason == v1.PodReasonUnschedulable, nil + } +} + +// waitForPodUnscheduleWithTimeout waits for a pod to fail scheduling and returns +// an error if it does not become unschedulable within the given timeout. +func waitForPodUnschedulableWithTimeout(cs clientset.Interface, pod *v1.Pod, timeout time.Duration) error { + return wait.Poll(100*time.Millisecond, timeout, podUnschedulable(cs, pod.Namespace, pod.Name)) +} + +// waitForPodUnschedule waits for a pod to fail scheduling and returns +// an error if it does not become unschedulable within the timeout duration (30 seconds). +func waitForPodUnschedulable(cs clientset.Interface, pod *v1.Pod) error { + return waitForPodUnschedulableWithTimeout(cs, pod, 10*time.Second) +} + +// waitForPodsCreated waits for number of pods are created. +func waitForPodsCreated(podInformer cache.SharedIndexInformer, num int) error { + return wait.Poll(100*time.Millisecond, 10*time.Second, func() (bool, error) { + objects := podInformer.GetIndexer().List() + return len(objects) == num, nil + }) +} + func validateDaemonSetStatus( dsClient appstyped.DaemonSetInterface, dsName string, - dsNamespace string, expectedNumberReady int32, t *testing.T) { if err := wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) { @@ -257,41 +413,181 @@ func validateFailedPlacementEvent(eventClient corev1typed.EventInterface, t *tes } } -func TestOneNodeDaemonLaunchesPod(t *testing.T) { - for _, strategy := range updateStrategies() { - server, closeFn, dc, informers, clientset := setup(t) - defer closeFn() - ns := framework.CreateTestingNamespace("one-node-daemonset-test", server, t) - defer framework.DeleteTestingNamespace(ns, server, t) +func forEachFeatureGate(t *testing.T, tf func(t *testing.T)) { + for _, fg := range featureGates() { + func() { + enabled := utilfeature.DefaultFeatureGate.Enabled(fg) + defer func() { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=%t", fg, enabled)) + }() + + for _, f := range []bool{true, false} { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=%t", fg, f)) + t.Run(fmt.Sprintf("%v (%t)", fg, f), tf) + } + }() + } +} - dsClient := clientset.AppsV1().DaemonSets(ns.Name) - podClient := clientset.CoreV1().Pods(ns.Name) - nodeClient := clientset.CoreV1().Nodes() - podInformer := informers.Core().V1().Pods().Informer() - stopCh := make(chan struct{}) - informers.Start(stopCh) - go dc.Run(5, stopCh) +func forEachStrategy(t *testing.T, tf func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy)) { + for _, strategy := range updateStrategies() { + t.Run(fmt.Sprintf("%s (%v)", t.Name(), strategy), + func(tt *testing.T) { tf(tt, strategy) }) + } +} - ds := newDaemonSet("foo", ns.Name) - ds.Spec.UpdateStrategy = *strategy - _, err := dsClient.Create(ds) - if err != nil { - t.Fatalf("Failed to create DaemonSet: %v", err) - } - _, err = nodeClient.Create(newNode("single-node", nil)) - if err != nil { - t.Fatalf("Failed to create node: %v", err) - } +func TestOneNodeDaemonLaunchesPod(t *testing.T) { + forEachFeatureGate(t, func(t *testing.T) { + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { + server, closeFn, dc, informers, clientset := setup(t) + defer closeFn() + ns := framework.CreateTestingNamespace("one-node-daemonset-test", server, t) + defer framework.DeleteTestingNamespace(ns, server, t) + + dsClient := clientset.AppsV1().DaemonSets(ns.Name) + podClient := clientset.CoreV1().Pods(ns.Name) + nodeClient := clientset.CoreV1().Nodes() + podInformer := informers.Core().V1().Pods().Informer() + + stopCh := make(chan struct{}) + defer close(stopCh) + + informers.Start(stopCh) + go dc.Run(5, stopCh) + + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) + + ds := newDaemonSet("foo", ns.Name) + ds.Spec.UpdateStrategy = *strategy + _, err := dsClient.Create(ds) + if err != nil { + t.Fatalf("Failed to create DaemonSet: %v", err) + } + defer cleanupDaemonSets(t, clientset, ds) - validateDaemonSetPodsAndMarkReady(podClient, podInformer, 1, t) - validateDaemonSetStatus(dsClient, ds.Name, ds.Namespace, 1, t) + _, err = nodeClient.Create(newNode("single-node", nil)) + if err != nil { + t.Fatalf("Failed to create node: %v", err) + } - close(stopCh) - } + validateDaemonSetPodsAndMarkReady(podClient, podInformer, 1, t) + validateDaemonSetStatus(dsClient, ds.Name, 1, t) + }) + }) } func TestSimpleDaemonSetLaunchesPods(t *testing.T) { - for _, strategy := range updateStrategies() { + forEachFeatureGate(t, func(t *testing.T) { + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { + server, closeFn, dc, informers, clientset := setup(t) + defer closeFn() + ns := framework.CreateTestingNamespace("simple-daemonset-test", server, t) + defer framework.DeleteTestingNamespace(ns, server, t) + + dsClient := clientset.AppsV1().DaemonSets(ns.Name) + podClient := clientset.CoreV1().Pods(ns.Name) + nodeClient := clientset.CoreV1().Nodes() + podInformer := informers.Core().V1().Pods().Informer() + + stopCh := make(chan struct{}) + defer close(stopCh) + + informers.Start(stopCh) + go dc.Run(5, stopCh) + + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) + + ds := newDaemonSet("foo", ns.Name) + ds.Spec.UpdateStrategy = *strategy + _, err := dsClient.Create(ds) + if err != nil { + t.Fatalf("Failed to create DaemonSet: %v", err) + } + defer cleanupDaemonSets(t, clientset, ds) + + addNodes(nodeClient, 0, 5, nil, t) + + validateDaemonSetPodsAndMarkReady(podClient, podInformer, 5, t) + validateDaemonSetStatus(dsClient, ds.Name, 5, t) + }) + }) +} + +func TestDaemonSetWithNodeSelectorLaunchesPods(t *testing.T) { + forEachFeatureGate(t, func(t *testing.T) { + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { + server, closeFn, dc, informers, clientset := setup(t) + defer closeFn() + ns := framework.CreateTestingNamespace("simple-daemonset-test", server, t) + defer framework.DeleteTestingNamespace(ns, server, t) + + dsClient := clientset.AppsV1().DaemonSets(ns.Name) + podClient := clientset.CoreV1().Pods(ns.Name) + nodeClient := clientset.CoreV1().Nodes() + podInformer := informers.Core().V1().Pods().Informer() + + stopCh := make(chan struct{}) + defer close(stopCh) + + informers.Start(stopCh) + go dc.Run(5, stopCh) + + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) + + ds := newDaemonSet("foo", ns.Name) + ds.Spec.UpdateStrategy = *strategy + + ds.Spec.Template.Spec.Affinity = &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "zone", + Operator: v1.NodeSelectorOpIn, + Values: []string{"test"}, + }, + }, + }, + { + MatchFields: []v1.NodeSelectorRequirement{ + { + Key: algorithm.NodeFieldSelectorKeyNodeName, + Operator: v1.NodeSelectorOpIn, + Values: []string{"node-1"}, + }, + }, + }, + }, + }, + }, + } + + _, err := dsClient.Create(ds) + if err != nil { + t.Fatalf("Failed to create DaemonSet: %v", err) + } + defer cleanupDaemonSets(t, clientset, ds) + + addNodes(nodeClient, 0, 2, nil, t) + // Two nodes with labels + addNodes(nodeClient, 2, 2, map[string]string{ + "zone": "test", + }, t) + addNodes(nodeClient, 4, 2, nil, t) + + validateDaemonSetPodsAndMarkReady(podClient, podInformer, 3, t) + validateDaemonSetStatus(dsClient, ds.Name, 3, t) + }) + }) +} + +func TestNotReadyNodeDaemonDoesLaunchPod(t *testing.T) { + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { server, closeFn, dc, informers, clientset := setup(t) defer closeFn() ns := framework.CreateTestingNamespace("simple-daemonset-test", server, t) @@ -301,83 +597,117 @@ func TestSimpleDaemonSetLaunchesPods(t *testing.T) { podClient := clientset.CoreV1().Pods(ns.Name) nodeClient := clientset.CoreV1().Nodes() podInformer := informers.Core().V1().Pods().Informer() + stopCh := make(chan struct{}) + defer close(stopCh) + informers.Start(stopCh) go dc.Run(5, stopCh) + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) + ds := newDaemonSet("foo", ns.Name) ds.Spec.UpdateStrategy = *strategy _, err := dsClient.Create(ds) if err != nil { t.Fatalf("Failed to create DaemonSet: %v", err) } - addNodes(nodeClient, 0, 5, nil, t) - validateDaemonSetPodsAndMarkReady(podClient, podInformer, 5, t) - validateDaemonSetStatus(dsClient, ds.Name, ds.Namespace, 5, t) + defer cleanupDaemonSets(t, clientset, ds) - close(stopCh) - } + node := newNode("single-node", nil) + node.Status.Conditions = []v1.NodeCondition{ + {Type: v1.NodeReady, Status: v1.ConditionFalse}, + } + _, err = nodeClient.Create(node) + if err != nil { + t.Fatalf("Failed to create node: %v", err) + } + + validateDaemonSetPodsAndMarkReady(podClient, podInformer, 1, t) + validateDaemonSetStatus(dsClient, ds.Name, 1, t) + }) } -func TestNotReadyNodeDaemonDoesLaunchPod(t *testing.T) { - for _, strategy := range updateStrategies() { +func TestInsufficientCapacityNodeDaemonDoesNotLaunchPod(t *testing.T) { + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { server, closeFn, dc, informers, clientset := setup(t) defer closeFn() - ns := framework.CreateTestingNamespace("simple-daemonset-test", server, t) + ns := framework.CreateTestingNamespace("insufficient-capacity", server, t) defer framework.DeleteTestingNamespace(ns, server, t) dsClient := clientset.AppsV1().DaemonSets(ns.Name) - podClient := clientset.CoreV1().Pods(ns.Name) nodeClient := clientset.CoreV1().Nodes() - podInformer := informers.Core().V1().Pods().Informer() + eventClient := clientset.CoreV1().Events(ns.Namespace) + stopCh := make(chan struct{}) + defer close(stopCh) + informers.Start(stopCh) go dc.Run(5, stopCh) ds := newDaemonSet("foo", ns.Name) + ds.Spec.Template.Spec = resourcePodSpec("node-with-limited-memory", "120M", "75m") ds.Spec.UpdateStrategy = *strategy _, err := dsClient.Create(ds) if err != nil { t.Fatalf("Failed to create DaemonSet: %v", err) } - node := newNode("single-node", nil) - node.Status.Conditions = []v1.NodeCondition{ - {Type: v1.NodeReady, Status: v1.ConditionFalse}, - } + defer cleanupDaemonSets(t, clientset, ds) + + node := newNode("node-with-limited-memory", nil) + node.Status.Allocatable = allocatableResources("100M", "200m") _, err = nodeClient.Create(node) if err != nil { t.Fatalf("Failed to create node: %v", err) } - validateDaemonSetPodsAndMarkReady(podClient, podInformer, 1, t) - validateDaemonSetStatus(dsClient, ds.Name, ds.Namespace, 1, t) - - close(stopCh) - } + validateFailedPlacementEvent(eventClient, t) + }) } -func TestInsufficientCapacityNodeDaemonDoesNotLaunchPod(t *testing.T) { - for _, strategy := range updateStrategies() { +// TestInsufficientCapacityNodeDaemonSetCreateButNotLaunchPod tests that when "ScheduleDaemonSetPods" +// feature is enabled, the DaemonSet should create Pods for all the nodes regardless of available resource +// on the nodes, and kube-scheduler should not schedule Pods onto the nodes with insufficient resource. +func TestInsufficientCapacityNodeWhenScheduleDaemonSetPodsEnabled(t *testing.T) { + enabled := utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) + defer func() { + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=%t", + features.ScheduleDaemonSetPods, enabled)) + }() + + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=%t", features.ScheduleDaemonSetPods, true)) + + forEachStrategy(t, func(t *testing.T, strategy *apps.DaemonSetUpdateStrategy) { server, closeFn, dc, informers, clientset := setup(t) defer closeFn() ns := framework.CreateTestingNamespace("insufficient-capacity", server, t) defer framework.DeleteTestingNamespace(ns, server, t) dsClient := clientset.AppsV1().DaemonSets(ns.Name) + podClient := clientset.CoreV1().Pods(ns.Name) + podInformer := informers.Core().V1().Pods().Informer() nodeClient := clientset.CoreV1().Nodes() - eventClient := corev1typed.New(clientset.CoreV1().RESTClient()).Events(ns.Namespace) stopCh := make(chan struct{}) + defer close(stopCh) + informers.Start(stopCh) go dc.Run(5, stopCh) + // Start Scheduler + setupScheduler(t, clientset, informers, stopCh) + ds := newDaemonSet("foo", ns.Name) - ds.Spec.Template.Spec = resourcePodSpec("node-with-limited-memory", "120M", "75m") + ds.Spec.Template.Spec = resourcePodSpec("", "120M", "75m") ds.Spec.UpdateStrategy = *strategy - _, err := dsClient.Create(ds) + ds, err := dsClient.Create(ds) if err != nil { t.Fatalf("Failed to create DaemonSet: %v", err) } + + defer cleanupDaemonSets(t, clientset, ds) + node := newNode("node-with-limited-memory", nil) node.Status.Allocatable = allocatableResources("100M", "200m") _, err = nodeClient.Create(node) @@ -385,8 +715,28 @@ func TestInsufficientCapacityNodeDaemonDoesNotLaunchPod(t *testing.T) { t.Fatalf("Failed to create node: %v", err) } - validateFailedPlacementEvent(eventClient, t) + if err := waitForPodsCreated(podInformer, 1); err != nil { + t.Errorf("Failed to wait for pods created: %v", err) + } - close(stopCh) - } + objects := podInformer.GetIndexer().List() + for _, object := range objects { + pod := object.(*v1.Pod) + if err := waitForPodUnschedulable(clientset, pod); err != nil { + t.Errorf("Failed to wait for unschedulable status of pod %+v", pod) + } + } + + node1 := newNode("node-with-enough-memory", nil) + node1.Status.Allocatable = allocatableResources("200M", "2000m") + _, err = nodeClient.Create(node1) + if err != nil { + t.Fatalf("Failed to create node: %v", err) + } + + // When ScheduleDaemonSetPods enabled, 2 pods are created. But only one + // of two Pods is scheduled by default scheduler. + validateDaemonSetPodsAndMarkReady(podClient, podInformer, 2, t) + validateDaemonSetStatus(dsClient, ds.Name, 1, t) + }) } diff --git a/vendor/k8s.io/kubernetes/test/integration/defaulttolerationseconds/BUILD b/vendor/k8s.io/kubernetes/test/integration/defaulttolerationseconds/BUILD index 550e4b947..324774cfe 100644 --- a/vendor/k8s.io/kubernetes/test/integration/defaulttolerationseconds/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/defaulttolerationseconds/BUILD @@ -17,13 +17,13 @@ go_test( "integration", ], deps = [ - "//pkg/api/testapi:go_default_library", "//pkg/apis/core/helper:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//plugin/pkg/admission/defaulttolerationseconds:go_default_library", "//test/integration/framework:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/test/integration/defaulttolerationseconds/defaulttolerationseconds_test.go b/vendor/k8s.io/kubernetes/test/integration/defaulttolerationseconds/defaulttolerationseconds_test.go index 463ec7641..b8be5c9b6 100644 --- a/vendor/k8s.io/kubernetes/test/integration/defaulttolerationseconds/defaulttolerationseconds_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/defaulttolerationseconds/defaulttolerationseconds_test.go @@ -21,9 +21,9 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds" @@ -33,12 +33,11 @@ import ( func TestAdmission(t *testing.T) { masterConfig := framework.NewMasterConfig() masterConfig.GenericConfig.EnableProfiling = true - masterConfig.GenericConfig.EnableMetrics = true masterConfig.GenericConfig.AdmissionControl = defaulttolerationseconds.NewDefaultTolerationSeconds() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) ns := framework.CreateTestingNamespace("default-toleration-seconds", s, t) defer framework.DeleteTestingNamespace(ns, s, t) diff --git a/vendor/k8s.io/kubernetes/test/integration/deployment/BUILD b/vendor/k8s.io/kubernetes/test/integration/deployment/BUILD index fee88d653..c4f0fed4e 100644 --- a/vendor/k8s.io/kubernetes/test/integration/deployment/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/deployment/BUILD @@ -19,8 +19,8 @@ go_test( "//pkg/controller/deployment/util:go_default_library", "//pkg/util/pointer:go_default_library", "//test/integration/framework:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", @@ -41,6 +41,7 @@ go_library( "//pkg/util/metrics:go_default_library", "//test/integration/framework:go_default_library", "//test/utils:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/apis/meta/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/deployment/deployment_test.go b/vendor/k8s.io/kubernetes/test/integration/deployment/deployment_test.go index f663741b5..7f4756609 100644 --- a/vendor/k8s.io/kubernetes/test/integration/deployment/deployment_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/deployment/deployment_test.go @@ -22,8 +22,8 @@ import ( "strings" "testing" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/uuid" @@ -47,7 +47,7 @@ func TestNewDeployment(t *testing.T) { tester.deployment.Annotations = map[string]string{"test": "should-copy-to-replica-set", v1.LastAppliedConfigAnnotation: "should-not-copy-to-replica-set"} var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %s: %v", tester.deployment.Name, err) } @@ -81,6 +81,32 @@ func TestNewDeployment(t *testing.T) { if newRS.Annotations[v1.LastAppliedConfigAnnotation] != "" { t.Errorf("expected new ReplicaSet last-applied annotation not copied from Deployment %s", tester.deployment.Name) } + + // New RS should contain pod-template-hash in its selector, label, and template label + rsHash, err := checkRSHashLabels(newRS) + if err != nil { + t.Error(err) + } + + // All pods targeted by the deployment should contain pod-template-hash in their labels + selector, err := metav1.LabelSelectorAsSelector(tester.deployment.Spec.Selector) + if err != nil { + t.Fatalf("failed to parse deployment %s selector: %v", name, err) + } + pods, err := c.CoreV1().Pods(ns.Name).List(metav1.ListOptions{LabelSelector: selector.String()}) + if err != nil { + t.Fatalf("failed to list pods of deployment %s: %v", name, err) + } + if len(pods.Items) != int(replicas) { + t.Errorf("expected %d pods, got %d pods", replicas, len(pods.Items)) + } + podHash, err := checkPodsHashLabel(pods) + if err != nil { + t.Error(err) + } + if rsHash != podHash { + t.Errorf("found mismatching pod-template-hash value: rs hash = %s whereas pod hash = %s", rsHash, podHash) + } } // Deployments should support roll out, roll back, and roll over @@ -102,14 +128,14 @@ func TestDeploymentRollingUpdate(t *testing.T) { tester := &deploymentTester{t: t, c: c, deployment: newDeployment(name, ns.Name, replicas)} tester.deployment.Spec.MinReadySeconds = 4 quarter := intstr.FromString("25%") - tester.deployment.Spec.Strategy.RollingUpdate = &v1beta1.RollingUpdateDeployment{ + tester.deployment.Spec.Strategy.RollingUpdate = &apps.RollingUpdateDeployment{ MaxUnavailable: &quarter, MaxSurge: &quarter, } // Create a deployment. var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %s: %v", tester.deployment.Name, err) } @@ -126,7 +152,7 @@ func TestDeploymentRollingUpdate(t *testing.T) { if oriImage == image { t.Fatalf("bad test setup, deployment %s roll out with the same image", tester.deployment.Name) } - imageFn := func(update *v1beta1.Deployment) { + imageFn := func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Image = image } tester.deployment, err = tester.updateDeployment(imageFn) @@ -160,7 +186,7 @@ func TestDeploymentRollingUpdate(t *testing.T) { // 3. Roll over a deployment before the previous rolling update finishes. image = "dont-finish" - imageFn = func(update *v1beta1.Deployment) { + imageFn = func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Image = image } tester.deployment, err = tester.updateDeployment(imageFn) @@ -173,7 +199,7 @@ func TestDeploymentRollingUpdate(t *testing.T) { // We don't mark pods as ready so that rollout won't finish. // Before the rollout finishes, trigger another rollout. image = "rollover" - imageFn = func(update *v1beta1.Deployment) { + imageFn = func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Image = image } tester.deployment, err = tester.updateDeployment(imageFn) @@ -186,7 +212,7 @@ func TestDeploymentRollingUpdate(t *testing.T) { if err := tester.waitForDeploymentCompleteAndCheckRollingAndMarkPodsReady(); err != nil { t.Fatal(err) } - _, allOldRSs, err := deploymentutil.GetOldReplicaSets(tester.deployment, c.ExtensionsV1beta1()) + _, allOldRSs, err := deploymentutil.GetOldReplicaSets(tester.deployment, c.AppsV1()) if err != nil { t.Fatalf("failed retrieving old replicasets of deployment %s: %v", tester.deployment.Name, err) } @@ -206,13 +232,18 @@ func TestDeploymentSelectorImmutability(t *testing.T) { defer framework.DeleteTestingNamespace(ns, s, t) tester := &deploymentTester{t: t, c: c, deployment: newDeployment(name, ns.Name, int32(20))} - deploymentExtensionsV1beta1, err := c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + var err error + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { - t.Fatalf("failed to create extensions/v1beta1 deployment %s: %v", tester.deployment.Name, err) + t.Fatalf("failed to create apps/v1 deployment %s: %v", tester.deployment.Name, err) } // test to ensure extensions/v1beta1 selector is mutable newSelectorLabels := map[string]string{"name_extensions_v1beta1": "test_extensions_v1beta1"} + deploymentExtensionsV1beta1, err := c.ExtensionsV1beta1().Deployments(ns.Name).Get(name, metav1.GetOptions{}) + if err != nil { + t.Fatalf("failed to get extensions/v1beta deployment %s: %v", name, err) + } deploymentExtensionsV1beta1.Spec.Selector.MatchLabels = newSelectorLabels deploymentExtensionsV1beta1.Spec.Template.Labels = newSelectorLabels updatedDeploymentExtensionsV1beta1, err := c.ExtensionsV1beta1().Deployments(ns.Name).Update(deploymentExtensionsV1beta1) @@ -257,6 +288,22 @@ func TestDeploymentSelectorImmutability(t *testing.T) { if !strings.Contains(err.Error(), expectedErrType) || !strings.Contains(err.Error(), expectedErrDetail) { t.Errorf("error message does not match, expected type: %s, expected detail: %s, got: %s", expectedErrType, expectedErrDetail, err.Error()) } + + // test to ensure apps/v1 selector is immutable + deploymentAppsV1, err := c.AppsV1().Deployments(ns.Name).Get(updatedDeploymentAppsV1beta1.Name, metav1.GetOptions{}) + if err != nil { + t.Fatalf("failed to get apps/v1 deployment %s: %v", updatedDeploymentAppsV1beta1.Name, err) + } + newSelectorLabels = map[string]string{"name_apps_v1": "test_apps_v1"} + deploymentAppsV1.Spec.Selector.MatchLabels = newSelectorLabels + deploymentAppsV1.Spec.Template.Labels = newSelectorLabels + _, err = c.AppsV1().Deployments(ns.Name).Update(deploymentAppsV1) + if err == nil { + t.Fatalf("failed to provide validation error when changing immutable selector when updating apps/v1 deployment %s", deploymentAppsV1.Name) + } + if !strings.Contains(err.Error(), expectedErrType) || !strings.Contains(err.Error(), expectedErrDetail) { + t.Errorf("error message does not match, expected type: %s, expected detail: %s, got: %s", expectedErrType, expectedErrDetail, err.Error()) + } } // Paused deployment should not start new rollout @@ -274,7 +321,7 @@ func TestPausedDeployment(t *testing.T) { tester.deployment.Spec.Template.Spec.TerminationGracePeriodSeconds = &tgps var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %s: %v", tester.deployment.Name, err) } @@ -332,7 +379,7 @@ func TestPausedDeployment(t *testing.T) { // Update the deployment template newTGPS := int64(0) - tester.deployment, err = tester.updateDeployment(func(update *v1beta1.Deployment) { + tester.deployment, err = tester.updateDeployment(func(update *apps.Deployment) { update.Spec.Template.Spec.TerminationGracePeriodSeconds = &newTGPS }) if err != nil { @@ -349,7 +396,7 @@ func TestPausedDeployment(t *testing.T) { t.Fatal(err) } - _, allOldRs, err := deploymentutil.GetOldReplicaSets(tester.deployment, c.ExtensionsV1beta1()) + _, allOldRs, err := deploymentutil.GetOldReplicaSets(tester.deployment, c.AppsV1()) if err != nil { t.Fatalf("failed retrieving old replicasets of deployment %s: %v", tester.deployment.Name, err) } @@ -375,7 +422,7 @@ func TestScalePausedDeployment(t *testing.T) { tester.deployment.Spec.Template.Spec.TerminationGracePeriodSeconds = &tgps var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %s: %v", tester.deployment.Name, err) } @@ -416,7 +463,7 @@ func TestScalePausedDeployment(t *testing.T) { // Scale the paused deployment. newReplicas := int32(10) - tester.deployment, err = tester.updateDeployment(func(update *v1beta1.Deployment) { + tester.deployment, err = tester.updateDeployment(func(update *apps.Deployment) { update.Spec.Replicas = &newReplicas }) if err != nil { @@ -456,7 +503,7 @@ func TestDeploymentHashCollision(t *testing.T) { tester := &deploymentTester{t: t, c: c, deployment: newDeployment(name, ns.Name, replicas)} var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %s: %v", tester.deployment.Name, err) } @@ -474,14 +521,14 @@ func TestDeploymentHashCollision(t *testing.T) { } // Mock a hash collision - newRS, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.ExtensionsV1beta1()) + newRS, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.AppsV1()) if err != nil { t.Fatalf("failed getting new replicaset of deployment %s: %v", tester.deployment.Name, err) } if newRS == nil { t.Fatalf("unable to find new replicaset of deployment %s", tester.deployment.Name) } - _, err = tester.updateReplicaSet(newRS.Name, func(update *v1beta1.ReplicaSet) { + _, err = tester.updateReplicaSet(newRS.Name, func(update *apps.ReplicaSet) { *update.Spec.Template.Spec.TerminationGracePeriodSeconds = int64(5) }) if err != nil { @@ -490,7 +537,7 @@ func TestDeploymentHashCollision(t *testing.T) { // Expect deployment collision counter to increment if err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { - d, err := c.ExtensionsV1beta1().Deployments(ns.Name).Get(tester.deployment.Name, metav1.GetOptions{}) + d, err := c.AppsV1().Deployments(ns.Name).Get(tester.deployment.Name, metav1.GetOptions{}) if err != nil { return false, nil } @@ -520,7 +567,7 @@ func TestRollbackDeploymentRSNoRevision(t *testing.T) { rs.Annotations = make(map[string]string) rs.Annotations["make"] = "difference" rs.Spec.Template.Spec.Containers[0].Image = "different-image" - _, err := c.ExtensionsV1beta1().ReplicaSets(ns.Name).Create(rs) + _, err := c.AppsV1().ReplicaSets(ns.Name).Create(rs) if err != nil { t.Fatalf("failed to create replicaset %s: %v", rsName, err) } @@ -528,9 +575,13 @@ func TestRollbackDeploymentRSNoRevision(t *testing.T) { replicas := int32(1) tester := &deploymentTester{t: t, c: c, deployment: newDeployment(name, ns.Name, replicas)} oriImage := tester.deployment.Spec.Template.Spec.Containers[0].Image + // Set absolute rollout limits (defaults changed to percentages) + max := intstr.FromInt(1) + tester.deployment.Spec.Strategy.RollingUpdate.MaxUnavailable = &max + tester.deployment.Spec.Strategy.RollingUpdate.MaxSurge = &max // Create a deployment which have different template than the replica set created above. - if tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment); err != nil { + if tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment); err != nil { t.Fatalf("failed to create deployment %s: %v", tester.deployment.Name, err) } @@ -569,7 +620,7 @@ func TestRollbackDeploymentRSNoRevision(t *testing.T) { // 2. Update the deployment to revision 2. updatedImage := "update" - tester.deployment, err = tester.updateDeployment(func(update *v1beta1.Deployment) { + tester.deployment, err = tester.updateDeployment(func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Name = updatedImage update.Spec.Template.Spec.Containers[0].Image = updatedImage }) @@ -618,10 +669,10 @@ func TestRollbackDeploymentRSNoRevision(t *testing.T) { } } -func checkRSHashLabels(rs *v1beta1.ReplicaSet) (string, error) { - hash := rs.Labels[v1beta1.DefaultDeploymentUniqueLabelKey] - selectorHash := rs.Spec.Selector.MatchLabels[v1beta1.DefaultDeploymentUniqueLabelKey] - templateLabelHash := rs.Spec.Template.Labels[v1beta1.DefaultDeploymentUniqueLabelKey] +func checkRSHashLabels(rs *apps.ReplicaSet) (string, error) { + hash := rs.Labels[apps.DefaultDeploymentUniqueLabelKey] + selectorHash := rs.Spec.Selector.MatchLabels[apps.DefaultDeploymentUniqueLabelKey] + templateLabelHash := rs.Spec.Template.Labels[apps.DefaultDeploymentUniqueLabelKey] if hash != selectorHash || selectorHash != templateLabelHash { return "", fmt.Errorf("mismatching hash value found in replicaset %s: %#v", rs.Name, rs) @@ -639,7 +690,7 @@ func checkPodsHashLabel(pods *v1.PodList) (string, error) { } var hash string for _, pod := range pods.Items { - podHash := pod.Labels[v1beta1.DefaultDeploymentUniqueLabelKey] + podHash := pod.Labels[apps.DefaultDeploymentUniqueLabelKey] if len(podHash) == 0 { return "", fmt.Errorf("found pod %s missing pod-template-hash label: %#v", pod.Name, pods) } @@ -654,104 +705,6 @@ func checkPodsHashLabel(pods *v1.PodList) (string, error) { return hash, nil } -// Deployment should label adopted ReplicaSets and Pods. -func TestDeploymentLabelAdopted(t *testing.T) { - s, closeFn, rm, dc, informers, c := dcSetup(t) - defer closeFn() - name := "test-adopted-deployment" - ns := framework.CreateTestingNamespace(name, s, t) - defer framework.DeleteTestingNamespace(ns, s, t) - - // Start informer and controllers - stopCh := make(chan struct{}) - defer close(stopCh) - informers.Start(stopCh) - go rm.Run(5, stopCh) - go dc.Run(5, stopCh) - - // Create a RS to be adopted by the deployment. - rsName := "test-adopted-controller" - replicas := int32(1) - rs := newReplicaSet(rsName, ns.Name, replicas) - _, err := c.ExtensionsV1beta1().ReplicaSets(ns.Name).Create(rs) - if err != nil { - t.Fatalf("failed to create replicaset %s: %v", rsName, err) - } - // Mark RS pods as ready. - selector, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector) - if err != nil { - t.Fatalf("failed to parse replicaset %s selector: %v", rsName, err) - } - if err = wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { - pods, err := c.CoreV1().Pods(ns.Name).List(metav1.ListOptions{LabelSelector: selector.String()}) - if err != nil { - return false, err - } - if len(pods.Items) != int(replicas) { - return false, nil - } - for _, pod := range pods.Items { - if err = markPodReady(c, ns.Name, &pod); err != nil { - return false, nil - } - } - return true, nil - }); err != nil { - t.Fatalf("failed to mark pods replicaset %s as ready: %v", rsName, err) - } - - // Create a Deployment to adopt the old rs. - tester := &deploymentTester{t: t, c: c, deployment: newDeployment(name, ns.Name, replicas)} - if tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment); err != nil { - t.Fatalf("failed to create deployment %s: %v", tester.deployment.Name, err) - } - - // Wait for the Deployment to be updated to revision 1 - if err = tester.waitForDeploymentRevisionAndImage("1", fakeImage); err != nil { - t.Fatal(err) - } - - // The RS and pods should be relabeled after the Deployment finishes adopting it and completes. - if err := tester.waitForDeploymentComplete(); err != nil { - t.Fatal(err) - } - - // There should be no old RSes (overlapping RS) - oldRSs, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(tester.deployment, c.ExtensionsV1beta1()) - if err != nil { - t.Fatalf("failed to get all replicasets owned by deployment %s: %v", name, err) - } - if len(oldRSs) != 0 || len(allOldRSs) != 0 { - t.Errorf("expected deployment to have no old replicasets, got %d old replicasets", len(allOldRSs)) - } - - // New RS should be relabeled, i.e. contain pod-template-hash in its selector, label, and template label - rsHash, err := checkRSHashLabels(newRS) - if err != nil { - t.Error(err) - } - - // All pods targeted by the deployment should contain pod-template-hash in their labels, and there should be only 3 pods - selector, err = metav1.LabelSelectorAsSelector(tester.deployment.Spec.Selector) - if err != nil { - t.Fatalf("failed to parse deployment %s selector: %v", name, err) - } - pods, err := c.CoreV1().Pods(ns.Name).List(metav1.ListOptions{LabelSelector: selector.String()}) - if err != nil { - t.Fatalf("failed to list pods of deployment %s: %v", name, err) - } - if len(pods.Items) != int(replicas) { - t.Errorf("expected %d pods, got %d pods", replicas, len(pods.Items)) - } - podHash, err := checkPodsHashLabel(pods) - if err != nil { - t.Error(err) - } - if rsHash != podHash { - t.Errorf("found mismatching pod-template-hash value: rs hash = %s whereas pod hash = %s", rsHash, podHash) - } -} - // Deployment should have a timeout condition when it fails to progress after given deadline. func TestFailedDeployment(t *testing.T) { s, closeFn, rm, dc, informers, c := dcSetup(t) @@ -766,7 +719,7 @@ func TestFailedDeployment(t *testing.T) { tester := &deploymentTester{t: t, c: c, deployment: newDeployment(deploymentName, ns.Name, replicas)} tester.deployment.Spec.ProgressDeadlineSeconds = &three var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %q: %v", deploymentName, err) } @@ -784,7 +737,7 @@ func TestFailedDeployment(t *testing.T) { // Pods are not marked as Ready, therefore the deployment progress will eventually timeout after progressDeadlineSeconds has passed. // Wait for the deployment to have a progress timeout condition. - if err = tester.waitForDeploymentWithCondition(deploymentutil.TimedOutReason, v1beta1.DeploymentProgressing); err != nil { + if err = tester.waitForDeploymentWithCondition(deploymentutil.TimedOutReason, apps.DeploymentProgressing); err != nil { t.Fatal(err) } @@ -794,7 +747,7 @@ func TestFailedDeployment(t *testing.T) { } // Wait for the deployment to have a progress complete condition. - if err = tester.waitForDeploymentWithCondition(deploymentutil.NewRSAvailableReason, v1beta1.DeploymentProgressing); err != nil { + if err = tester.waitForDeploymentWithCondition(deploymentutil.NewRSAvailableReason, apps.DeploymentProgressing); err != nil { t.Fatal(err) } } @@ -822,9 +775,9 @@ func TestOverlappingDeployments(t *testing.T) { // Create 2 deployments with overlapping selectors var err error - var rss []*v1beta1.ReplicaSet + var rss []*apps.ReplicaSet for _, tester := range testers { - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) dname := tester.deployment.Name if err != nil { t.Fatalf("failed to create deployment %q: %v", dname, err) @@ -856,7 +809,7 @@ func TestOverlappingDeployments(t *testing.T) { // Scale only the first deployment by 1 newReplicas := replicas + 1 - testers[0].deployment, err = testers[0].updateDeployment(func(update *v1beta1.Deployment) { + testers[0].deployment, err = testers[0].updateDeployment(func(update *apps.Deployment) { update.Spec.Replicas = &newReplicas }) if err != nil { @@ -870,7 +823,7 @@ func TestOverlappingDeployments(t *testing.T) { // Verify replicaset of both deployments has updated number of replicas for i, tester := range testers { - rs, err := c.ExtensionsV1beta1().ReplicaSets(ns.Name).Get(rss[i].Name, metav1.GetOptions{}) + rs, err := c.AppsV1().ReplicaSets(ns.Name).Get(rss[i].Name, metav1.GetOptions{}) if err != nil { t.Fatalf("failed to get replicaset %q: %v", rss[i].Name, err) } @@ -900,7 +853,7 @@ func TestScaledRolloutDeployment(t *testing.T) { tester := &deploymentTester{t: t, c: c, deployment: newDeployment(name, ns.Name, replicas)} tester.deployment.Spec.Strategy.RollingUpdate.MaxSurge = intOrStrP(3) tester.deployment.Spec.Strategy.RollingUpdate.MaxUnavailable = intOrStrP(2) - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %q: %v", name, err) } @@ -919,7 +872,7 @@ func TestScaledRolloutDeployment(t *testing.T) { // Update the deployment with another new image but do not mark the pods as ready to block new replicaset fakeImage2 := "fakeimage2" - tester.deployment, err = tester.updateDeployment(func(update *v1beta1.Deployment) { + tester.deployment, err = tester.updateDeployment(func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Image = fakeImage2 }) if err != nil { @@ -930,7 +883,7 @@ func TestScaledRolloutDeployment(t *testing.T) { } // Verify the deployment has minimum available replicas after 2nd rollout - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Get(name, metav1.GetOptions{}) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Get(name, metav1.GetOptions{}) if err != nil { t.Fatalf("failed to get deployment %q: %v", name, err) } @@ -940,7 +893,7 @@ func TestScaledRolloutDeployment(t *testing.T) { } // Wait for old replicaset of 1st rollout to have desired replicas - firstRS, err = c.ExtensionsV1beta1().ReplicaSets(ns.Name).Get(firstRS.Name, metav1.GetOptions{}) + firstRS, err = c.AppsV1().ReplicaSets(ns.Name).Get(firstRS.Name, metav1.GetOptions{}) if err != nil { t.Fatalf("failed to get replicaset %q: %v", firstRS.Name, err) } @@ -960,7 +913,7 @@ func TestScaledRolloutDeployment(t *testing.T) { // Scale up the deployment and update its image to another new image simultaneously (this time marks all pods as ready) newReplicas := int32(20) fakeImage3 := "fakeimage3" - tester.deployment, err = tester.updateDeployment(func(update *v1beta1.Deployment) { + tester.deployment, err = tester.updateDeployment(func(update *apps.Deployment) { update.Spec.Replicas = &newReplicas update.Spec.Template.Spec.Containers[0].Image = fakeImage3 }) @@ -975,13 +928,13 @@ func TestScaledRolloutDeployment(t *testing.T) { } // Verify every replicaset has correct desiredReplicas annotation after 3rd rollout - thirdRS, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.ExtensionsV1beta1()) + thirdRS, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.AppsV1()) if err != nil { t.Fatalf("failed getting new revision 3 replicaset for deployment %q: %v", name, err) } - rss := []*v1beta1.ReplicaSet{firstRS, secondRS, thirdRS} + rss := []*apps.ReplicaSet{firstRS, secondRS, thirdRS} for _, curRS := range rss { - curRS, err = c.ExtensionsV1beta1().ReplicaSets(ns.Name).Get(curRS.Name, metav1.GetOptions{}) + curRS, err = c.AppsV1().ReplicaSets(ns.Name).Get(curRS.Name, metav1.GetOptions{}) if err != nil { t.Fatalf("failed to get replicaset when checking desired replicas annotation: %v", err) } @@ -996,7 +949,7 @@ func TestScaledRolloutDeployment(t *testing.T) { // Update the deployment with another new image but do not mark the pods as ready to block new replicaset fakeImage4 := "fakeimage4" - tester.deployment, err = tester.updateDeployment(func(update *v1beta1.Deployment) { + tester.deployment, err = tester.updateDeployment(func(update *apps.Deployment) { update.Spec.Template.Spec.Containers[0].Image = fakeImage4 }) if err != nil { @@ -1007,7 +960,7 @@ func TestScaledRolloutDeployment(t *testing.T) { } // Verify the deployment has minimum available replicas after 4th rollout - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Get(name, metav1.GetOptions{}) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Get(name, metav1.GetOptions{}) if err != nil { t.Fatalf("failed to get deployment %q: %v", name, err) } @@ -1017,7 +970,7 @@ func TestScaledRolloutDeployment(t *testing.T) { } // Wait for old replicaset of 3rd rollout to have desired replicas - thirdRS, err = c.ExtensionsV1beta1().ReplicaSets(ns.Name).Get(thirdRS.Name, metav1.GetOptions{}) + thirdRS, err = c.AppsV1().ReplicaSets(ns.Name).Get(thirdRS.Name, metav1.GetOptions{}) if err != nil { t.Fatalf("failed to get replicaset %q: %v", thirdRS.Name, err) } @@ -1037,7 +990,7 @@ func TestScaledRolloutDeployment(t *testing.T) { // Scale down the deployment and update its image to another new image simultaneously (this time marks all pods as ready) newReplicas = int32(5) fakeImage5 := "fakeimage5" - tester.deployment, err = tester.updateDeployment(func(update *v1beta1.Deployment) { + tester.deployment, err = tester.updateDeployment(func(update *apps.Deployment) { update.Spec.Replicas = &newReplicas update.Spec.Template.Spec.Containers[0].Image = fakeImage5 }) @@ -1052,13 +1005,13 @@ func TestScaledRolloutDeployment(t *testing.T) { } // Verify every replicaset has correct desiredReplicas annotation after 5th rollout - fifthRS, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.ExtensionsV1beta1()) + fifthRS, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.AppsV1()) if err != nil { t.Fatalf("failed getting new revision 5 replicaset for deployment %q: %v", name, err) } - rss = []*v1beta1.ReplicaSet{thirdRS, fourthRS, fifthRS} + rss = []*apps.ReplicaSet{thirdRS, fourthRS, fifthRS} for _, curRS := range rss { - curRS, err = c.ExtensionsV1beta1().ReplicaSets(ns.Name).Get(curRS.Name, metav1.GetOptions{}) + curRS, err = c.AppsV1().ReplicaSets(ns.Name).Get(curRS.Name, metav1.GetOptions{}) if err != nil { t.Fatalf("failed to get replicaset when checking desired replicas annotation: %v", err) } @@ -1082,10 +1035,10 @@ func TestSpecReplicasChange(t *testing.T) { deploymentName := "deployment" replicas := int32(1) tester := &deploymentTester{t: t, c: c, deployment: newDeployment(deploymentName, ns.Name, replicas)} - tester.deployment.Spec.Strategy.Type = v1beta1.RecreateDeploymentStrategyType + tester.deployment.Spec.Strategy.Type = apps.RecreateDeploymentStrategyType tester.deployment.Spec.Strategy.RollingUpdate = nil var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %q: %v", deploymentName, err) } @@ -1111,7 +1064,7 @@ func TestSpecReplicasChange(t *testing.T) { // Add a template annotation change to test deployment's status does update // without .spec.replicas change var oldGeneration int64 - tester.deployment, err = tester.updateDeployment(func(update *v1beta1.Deployment) { + tester.deployment, err = tester.updateDeployment(func(update *apps.Deployment) { oldGeneration = update.Generation update.Spec.RevisionHistoryLimit = pointer.Int32Ptr(4) }) @@ -1140,8 +1093,10 @@ func TestDeploymentAvailableCondition(t *testing.T) { tester := &deploymentTester{t: t, c: c, deployment: newDeployment(deploymentName, ns.Name, replicas)} // Assign a high value to the deployment's minReadySeconds tester.deployment.Spec.MinReadySeconds = 3600 + // progressDeadlineSeconds must be greater than minReadySeconds + tester.deployment.Spec.ProgressDeadlineSeconds = pointer.Int32Ptr(7200) var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %q: %v", deploymentName, err) } @@ -1159,7 +1114,7 @@ func TestDeploymentAvailableCondition(t *testing.T) { } // Wait for the deployment to have MinimumReplicasUnavailable reason because the pods are not marked as ready - if err = tester.waitForDeploymentWithCondition(deploymentutil.MinimumReplicasUnavailable, v1beta1.DeploymentAvailable); err != nil { + if err = tester.waitForDeploymentWithCondition(deploymentutil.MinimumReplicasUnavailable, apps.DeploymentAvailable); err != nil { t.Fatal(err) } @@ -1179,7 +1134,7 @@ func TestDeploymentAvailableCondition(t *testing.T) { } // Wait for the deployment to still have MinimumReplicasUnavailable reason within minReadySeconds period - if err = tester.waitForDeploymentWithCondition(deploymentutil.MinimumReplicasUnavailable, v1beta1.DeploymentAvailable); err != nil { + if err = tester.waitForDeploymentWithCondition(deploymentutil.MinimumReplicasUnavailable, apps.DeploymentAvailable); err != nil { t.Fatal(err) } @@ -1189,7 +1144,7 @@ func TestDeploymentAvailableCondition(t *testing.T) { } // Update the deployment's minReadySeconds to a small value - tester.deployment, err = tester.updateDeployment(func(update *v1beta1.Deployment) { + tester.deployment, err = tester.updateDeployment(func(update *apps.Deployment) { update.Spec.MinReadySeconds = 1 }) if err != nil { @@ -1202,7 +1157,7 @@ func TestDeploymentAvailableCondition(t *testing.T) { } // Wait for the deployment to have MinimumReplicasAvailable reason after minReadySeconds period - if err = tester.waitForDeploymentWithCondition(deploymentutil.MinimumReplicasAvailable, v1beta1.DeploymentAvailable); err != nil { + if err = tester.waitForDeploymentWithCondition(deploymentutil.MinimumReplicasAvailable, apps.DeploymentAvailable); err != nil { t.Fatal(err) } @@ -1213,10 +1168,10 @@ func TestDeploymentAvailableCondition(t *testing.T) { } // Wait for deployment to automatically patch incorrect ControllerRef of RS -func testRSControllerRefPatch(t *testing.T, tester *deploymentTester, rs *v1beta1.ReplicaSet, ownerReference *metav1.OwnerReference, expectedOwnerReferenceNum int) { +func testRSControllerRefPatch(t *testing.T, tester *deploymentTester, rs *apps.ReplicaSet, ownerReference *metav1.OwnerReference, expectedOwnerReferenceNum int) { ns := rs.Namespace - rsClient := tester.c.ExtensionsV1beta1().ReplicaSets(ns) - rs, err := tester.updateReplicaSet(rs.Name, func(update *v1beta1.ReplicaSet) { + rsClient := tester.c.AppsV1().ReplicaSets(ns) + rs, err := tester.updateReplicaSet(rs.Name, func(update *apps.ReplicaSet) { update.OwnerReferences = []metav1.OwnerReference{*ownerReference} }) if err != nil { @@ -1258,7 +1213,7 @@ func TestGeneralReplicaSetAdoption(t *testing.T) { replicas := int32(1) tester := &deploymentTester{t: t, c: c, deployment: newDeployment(deploymentName, ns.Name, replicas)} var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %q: %v", deploymentName, err) } @@ -1281,7 +1236,7 @@ func TestGeneralReplicaSetAdoption(t *testing.T) { } // Get replicaset of the deployment - rs, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.ExtensionsV1beta1()) + rs, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.AppsV1()) if err != nil { t.Fatalf("failed to get replicaset of deployment %q: %v", deploymentName, err) } @@ -1305,7 +1260,7 @@ func TestGeneralReplicaSetAdoption(t *testing.T) { func testScalingUsingScaleSubresource(t *testing.T, tester *deploymentTester, replicas int32) { ns := tester.deployment.Namespace deploymentName := tester.deployment.Name - deploymentClient := tester.c.ExtensionsV1beta1().Deployments(ns) + deploymentClient := tester.c.AppsV1().Deployments(ns) deployment, err := deploymentClient.Get(deploymentName, metav1.GetOptions{}) if err != nil { t.Fatalf("Failed to obtain deployment %q: %v", deploymentName, err) @@ -1352,7 +1307,7 @@ func TestDeploymentScaleSubresource(t *testing.T) { replicas := int32(2) tester := &deploymentTester{t: t, c: c, deployment: newDeployment(deploymentName, ns.Name, replicas)} var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %q: %v", deploymentName, err) } @@ -1396,7 +1351,7 @@ func TestReplicaSetOrphaningAndAdoptionWhenLabelsChange(t *testing.T) { replicas := int32(1) tester := &deploymentTester{t: t, c: c, deployment: newDeployment(deploymentName, ns.Name, replicas)} var err error - tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment) + tester.deployment, err = c.AppsV1().Deployments(ns.Name).Create(tester.deployment) if err != nil { t.Fatalf("failed to create deployment %q: %v", deploymentName, err) } @@ -1421,7 +1376,7 @@ func TestReplicaSetOrphaningAndAdoptionWhenLabelsChange(t *testing.T) { // Orphaning: deployment should remove OwnerReference from a RS when the RS's labels change to not match its labels // Get replicaset of the deployment - rs, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.ExtensionsV1beta1()) + rs, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.AppsV1()) if err != nil { t.Fatalf("failed to get replicaset of deployment %q: %v", deploymentName, err) } @@ -1440,7 +1395,7 @@ func TestReplicaSetOrphaningAndAdoptionWhenLabelsChange(t *testing.T) { // Change the replicaset's labels to not match the deployment's labels labelMap := map[string]string{"new-name": "new-test"} - rs, err = tester.updateReplicaSet(rs.Name, func(update *v1beta1.ReplicaSet) { + rs, err = tester.updateReplicaSet(rs.Name, func(update *apps.ReplicaSet) { update.Labels = labelMap }) if err != nil { @@ -1448,7 +1403,7 @@ func TestReplicaSetOrphaningAndAdoptionWhenLabelsChange(t *testing.T) { } // Wait for the controllerRef of the replicaset to become nil - rsClient := tester.c.ExtensionsV1beta1().ReplicaSets(ns.Name) + rsClient := tester.c.AppsV1().ReplicaSets(ns.Name) if err = wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { rs, err = rsClient.Get(rs.Name, metav1.GetOptions{}) if err != nil { @@ -1462,9 +1417,9 @@ func TestReplicaSetOrphaningAndAdoptionWhenLabelsChange(t *testing.T) { // Wait for the deployment to create a new replicaset // This will trigger collision avoidance due to deterministic nature of replicaset name // i.e., the new replicaset will have a name with different hash to preserve name uniqueness - var newRS *v1beta1.ReplicaSet + var newRS *apps.ReplicaSet if err = wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { - newRS, err = deploymentutil.GetNewReplicaSet(tester.deployment, c.ExtensionsV1beta1()) + newRS, err = deploymentutil.GetNewReplicaSet(tester.deployment, c.AppsV1()) if err != nil { return false, fmt.Errorf("failed to get new replicaset of deployment %q after orphaning: %v", deploymentName, err) } @@ -1479,7 +1434,7 @@ func TestReplicaSetOrphaningAndAdoptionWhenLabelsChange(t *testing.T) { // Adoption: deployment should add controllerRef to a RS when the RS's labels change to match its labels // Change the old replicaset's labels to match the deployment's labels - rs, err = tester.updateReplicaSet(rs.Name, func(update *v1beta1.ReplicaSet) { + rs, err = tester.updateReplicaSet(rs.Name, func(update *apps.ReplicaSet) { update.Labels = testLabels() }) if err != nil { diff --git a/vendor/k8s.io/kubernetes/test/integration/deployment/util.go b/vendor/k8s.io/kubernetes/test/integration/deployment/util.go index e33cce4f0..505e72ac8 100644 --- a/vendor/k8s.io/kubernetes/test/integration/deployment/util.go +++ b/vendor/k8s.io/kubernetes/test/integration/deployment/util.go @@ -23,8 +23,9 @@ import ( "testing" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - "k8s.io/api/extensions/v1beta1" + extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" @@ -48,18 +49,18 @@ const ( fakeImage = "fakeimage" ) -var pauseFn = func(update *v1beta1.Deployment) { +var pauseFn = func(update *apps.Deployment) { update.Spec.Paused = true } -var resumeFn = func(update *v1beta1.Deployment) { +var resumeFn = func(update *apps.Deployment) { update.Spec.Paused = false } type deploymentTester struct { t *testing.T c clientset.Interface - deployment *v1beta1.Deployment + deployment *apps.Deployment } func testLabels() map[string]string { @@ -67,22 +68,22 @@ func testLabels() map[string]string { } // newDeployment returns a RollingUpdate Deployment with with a fake container image -func newDeployment(name, ns string, replicas int32) *v1beta1.Deployment { - return &v1beta1.Deployment{ +func newDeployment(name, ns string, replicas int32) *apps.Deployment { + return &apps.Deployment{ TypeMeta: metav1.TypeMeta{ Kind: "Deployment", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", }, ObjectMeta: metav1.ObjectMeta{ Namespace: ns, Name: name, }, - Spec: v1beta1.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: &replicas, Selector: &metav1.LabelSelector{MatchLabels: testLabels()}, - Strategy: v1beta1.DeploymentStrategy{ - Type: v1beta1.RollingUpdateDeploymentStrategyType, - RollingUpdate: new(v1beta1.RollingUpdateDeployment), + Strategy: apps.DeploymentStrategy{ + Type: apps.RollingUpdateDeploymentStrategyType, + RollingUpdate: new(apps.RollingUpdateDeployment), }, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ @@ -101,8 +102,8 @@ func newDeployment(name, ns string, replicas int32) *v1beta1.Deployment { } } -func newReplicaSet(name, ns string, replicas int32) *v1beta1.ReplicaSet { - return &v1beta1.ReplicaSet{ +func newReplicaSet(name, ns string, replicas int32) *apps.ReplicaSet { + return &apps.ReplicaSet{ TypeMeta: metav1.TypeMeta{ Kind: "ReplicaSet", APIVersion: "extensions/v1beta1", @@ -110,8 +111,9 @@ func newReplicaSet(name, ns string, replicas int32) *v1beta1.ReplicaSet { ObjectMeta: metav1.ObjectMeta{ Namespace: ns, Name: name, + Labels: testLabels(), }, - Spec: v1beta1.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: testLabels(), }, @@ -133,11 +135,11 @@ func newReplicaSet(name, ns string, replicas int32) *v1beta1.ReplicaSet { } } -func newDeploymentRollback(name string, annotations map[string]string, revision int64) *v1beta1.DeploymentRollback { - return &v1beta1.DeploymentRollback{ +func newDeploymentRollback(name string, annotations map[string]string, revision int64) *extensions.DeploymentRollback { + return &extensions.DeploymentRollback{ Name: name, UpdatedAnnotations: annotations, - RollbackTo: v1beta1.RollbackConfig{Revision: revision}, + RollbackTo: extensions.RollbackConfig{Revision: revision}, } } @@ -156,8 +158,8 @@ func dcSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *replicaset.R metrics.UnregisterMetricAndUntrackRateLimiterUsage("deployment_controller") dc, err := deployment.NewDeploymentController( - informers.Extensions().V1beta1().Deployments(), - informers.Extensions().V1beta1().ReplicaSets(), + informers.Apps().V1().Deployments(), + informers.Apps().V1().ReplicaSets(), informers.Core().V1().Pods(), clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "deployment-controller")), ) @@ -165,7 +167,7 @@ func dcSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *replicaset.R t.Fatalf("error creating Deployment controller: %v", err) } rm := replicaset.NewReplicaSetController( - informers.Extensions().V1beta1().ReplicaSets(), + informers.Apps().V1().ReplicaSets(), informers.Core().V1().Pods(), clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "replicaset-controller")), replicaset.BurstReplicas, @@ -256,7 +258,7 @@ func (d *deploymentTester) markUpdatedPodsReady(wg *sync.WaitGroup) { } func (d *deploymentTester) deploymentComplete() (bool, error) { - latest, err := d.c.ExtensionsV1beta1().Deployments(d.deployment.Namespace).Get(d.deployment.Name, metav1.GetOptions{}) + latest, err := d.c.AppsV1().Deployments(d.deployment.Namespace).Get(d.deployment.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -285,6 +287,8 @@ func (d *deploymentTester) waitForDeploymentCompleteAndCheckRollingAndMarkPodsRe // Manually mark updated Deployment pods as ready in a separate goroutine wg.Add(1) go d.markUpdatedPodsReady(&wg) + // Wait for goroutine to finish, for all return paths. + defer wg.Wait() // Wait for the Deployment status to complete while Deployment pods are becoming ready err := d.waitForDeploymentCompleteAndCheckRolling() @@ -292,9 +296,6 @@ func (d *deploymentTester) waitForDeploymentCompleteAndCheckRollingAndMarkPodsRe return fmt.Errorf("failed to wait for Deployment %s to complete: %v", d.deployment.Name, err) } - // Wait for goroutine to finish - wg.Wait() - return nil } @@ -319,7 +320,7 @@ func (d *deploymentTester) waitForDeploymentCompleteAndMarkPodsReady() error { return nil } -func (d *deploymentTester) updateDeployment(applyUpdate testutil.UpdateDeploymentFunc) (*v1beta1.Deployment, error) { +func (d *deploymentTester) updateDeployment(applyUpdate testutil.UpdateDeploymentFunc) (*apps.Deployment, error) { return testutil.UpdateDeploymentWithRetries(d.c, d.deployment.Namespace, d.deployment.Name, applyUpdate, d.t.Logf, pollInterval, pollTimeout) } @@ -330,12 +331,12 @@ func (d *deploymentTester) waitForObservedDeployment(desiredGeneration int64) er return nil } -func (d *deploymentTester) getNewReplicaSet() (*v1beta1.ReplicaSet, error) { - deployment, err := d.c.ExtensionsV1beta1().Deployments(d.deployment.Namespace).Get(d.deployment.Name, metav1.GetOptions{}) +func (d *deploymentTester) getNewReplicaSet() (*apps.ReplicaSet, error) { + deployment, err := d.c.AppsV1().Deployments(d.deployment.Namespace).Get(d.deployment.Name, metav1.GetOptions{}) if err != nil { return nil, fmt.Errorf("failed retrieving deployment %s: %v", d.deployment.Name, err) } - rs, err := deploymentutil.GetNewReplicaSet(deployment, d.c.ExtensionsV1beta1()) + rs, err := deploymentutil.GetNewReplicaSet(deployment, d.c.AppsV1()) if err != nil { return nil, fmt.Errorf("failed retrieving new replicaset of deployment %s: %v", d.deployment.Name, err) } @@ -353,7 +354,7 @@ func (d *deploymentTester) expectNoNewReplicaSet() error { return nil } -func (d *deploymentTester) expectNewReplicaSet() (*v1beta1.ReplicaSet, error) { +func (d *deploymentTester) expectNewReplicaSet() (*apps.ReplicaSet, error) { rs, err := d.getNewReplicaSet() if err != nil { return nil, err @@ -364,11 +365,11 @@ func (d *deploymentTester) expectNewReplicaSet() (*v1beta1.ReplicaSet, error) { return rs, nil } -func (d *deploymentTester) updateReplicaSet(name string, applyUpdate testutil.UpdateReplicaSetFunc) (*v1beta1.ReplicaSet, error) { +func (d *deploymentTester) updateReplicaSet(name string, applyUpdate testutil.UpdateReplicaSetFunc) (*apps.ReplicaSet, error) { return testutil.UpdateReplicaSetWithRetries(d.c, d.deployment.Namespace, name, applyUpdate, d.t.Logf, pollInterval, pollTimeout) } -func (d *deploymentTester) updateReplicaSetStatus(name string, applyStatusUpdate testutil.UpdateReplicaSetFunc) (*v1beta1.ReplicaSet, error) { +func (d *deploymentTester) updateReplicaSetStatus(name string, applyStatusUpdate testutil.UpdateReplicaSetFunc) (*apps.ReplicaSet, error) { return testutil.UpdateReplicaSetStatusWithRetries(d.c, d.deployment.Namespace, name, applyStatusUpdate, d.t.Logf, pollInterval, pollTimeout) } @@ -386,7 +387,7 @@ func (d *deploymentTester) waitForDeploymentUpdatedReplicasGTE(minUpdatedReplica return testutil.WaitForDeploymentUpdatedReplicasGTE(d.c, d.deployment.Namespace, d.deployment.Name, minUpdatedReplicas, d.deployment.Generation, pollInterval, pollTimeout) } -func (d *deploymentTester) waitForDeploymentWithCondition(reason string, condType v1beta1.DeploymentConditionType) error { +func (d *deploymentTester) waitForDeploymentWithCondition(reason string, condType apps.DeploymentConditionType) error { return testutil.WaitForDeploymentWithCondition(d.c, d.deployment.Namespace, d.deployment.Name, reason, condType, d.t.Logf, pollInterval, pollTimeout) } @@ -417,13 +418,13 @@ func (d *deploymentTester) listUpdatedPods() ([]v1.Pod, error) { return ownedPods, nil } -func (d *deploymentTester) waitRSStable(replicaset *v1beta1.ReplicaSet) error { +func (d *deploymentTester) waitRSStable(replicaset *apps.ReplicaSet) error { return testutil.WaitRSStable(d.t, d.c, replicaset, pollInterval, pollTimeout) } func (d *deploymentTester) scaleDeployment(newReplicas int32) error { var err error - d.deployment, err = d.updateDeployment(func(update *v1beta1.Deployment) { + d.deployment, err = d.updateDeployment(func(update *apps.Deployment) { update.Spec.Replicas = &newReplicas }) if err != nil { @@ -447,7 +448,7 @@ func (d *deploymentTester) scaleDeployment(newReplicas int32) error { // waitForReadyReplicas waits for number of ready replicas to equal number of replicas. func (d *deploymentTester) waitForReadyReplicas() error { if err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { - deployment, err := d.c.ExtensionsV1beta1().Deployments(d.deployment.Namespace).Get(d.deployment.Name, metav1.GetOptions{}) + deployment, err := d.c.AppsV1().Deployments(d.deployment.Namespace).Get(d.deployment.Name, metav1.GetOptions{}) if err != nil { return false, fmt.Errorf("failed to get deployment %q: %v", d.deployment.Name, err) } @@ -485,7 +486,7 @@ func (d *deploymentTester) markUpdatedPodsReadyWithoutComplete() error { // Verify all replicas fields of DeploymentStatus have desired count. // Immediately return an error when found a non-matching replicas field. func (d *deploymentTester) checkDeploymentStatusReplicasFields(replicas, updatedReplicas, readyReplicas, availableReplicas, unavailableReplicas int32) error { - deployment, err := d.c.ExtensionsV1beta1().Deployments(d.deployment.Namespace).Get(d.deployment.Name, metav1.GetOptions{}) + deployment, err := d.c.AppsV1().Deployments(d.deployment.Namespace).Get(d.deployment.Name, metav1.GetOptions{}) if err != nil { return fmt.Errorf("failed to get deployment %q: %v", d.deployment.Name, err) } diff --git a/vendor/k8s.io/kubernetes/test/integration/etcd/BUILD b/vendor/k8s.io/kubernetes/test/integration/etcd/BUILD index bb8b85daf..4198e15cc 100644 --- a/vendor/k8s.io/kubernetes/test/integration/etcd/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/etcd/BUILD @@ -21,7 +21,6 @@ go_test( "//cmd/kube-apiserver/app/options:go_default_library", "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", "//pkg/master:go_default_library", "//test/integration:go_default_library", "//test/integration/framework:go_default_library", @@ -38,10 +37,10 @@ go_test( "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library", + "//vendor/k8s.io/client-go/discovery/cached:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/integration/etcd/etcd_storage_path_test.go b/vendor/k8s.io/kubernetes/test/integration/etcd/etcd_storage_path_test.go index 45490eb00..e3ae74789 100644 --- a/vendor/k8s.io/kubernetes/test/integration/etcd/etcd_storage_path_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/etcd/etcd_storage_path_test.go @@ -43,16 +43,14 @@ import ( genericapiserver "k8s.io/apiserver/pkg/server" genericapiserveroptions "k8s.io/apiserver/pkg/server/options" "k8s.io/apiserver/pkg/storage/storagebackend" + cacheddiscovery "k8s.io/client-go/discovery/cached" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/util/flowcontrol" "k8s.io/kubernetes/cmd/kube-apiserver/app" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/pkg/api/legacyscheme" kapi "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/test/integration" "k8s.io/kubernetes/test/integration/framework" @@ -60,6 +58,7 @@ import ( _ "k8s.io/kubernetes/pkg/master" // TODO what else is needed "github.com/coreos/etcd/clientv3" + "k8s.io/client-go/restmapper" ) // Etcd data for all persisted objects. @@ -262,6 +261,7 @@ var etcdStorageData = map[schema.GroupVersionResource]struct { gvr("extensions", "v1beta1", "podsecuritypolicies"): { stub: `{"metadata": {"name": "psp1"}, "spec": {"fsGroup": {"rule": "RunAsAny"}, "privileged": true, "runAsUser": {"rule": "RunAsAny"}, "seLinux": {"rule": "MustRunAs"}, "supplementalGroups": {"rule": "RunAsAny"}}}`, expectedEtcdPath: "/registry/podsecuritypolicy/psp1", + expectedGVK: gvkP("policy", "v1beta1", "PodSecurityPolicy"), }, gvr("extensions", "v1beta1", "ingresses"): { stub: `{"metadata": {"name": "ingress1"}, "spec": {"backend": {"serviceName": "service", "servicePort": 5000}}}`, @@ -299,7 +299,6 @@ var etcdStorageData = map[schema.GroupVersionResource]struct { gvr("policy", "v1beta1", "podsecuritypolicies"): { stub: `{"metadata": {"name": "psp2"}, "spec": {"fsGroup": {"rule": "RunAsAny"}, "privileged": true, "runAsUser": {"rule": "RunAsAny"}, "seLinux": {"rule": "MustRunAs"}, "supplementalGroups": {"rule": "RunAsAny"}}}`, expectedEtcdPath: "/registry/podsecuritypolicy/psp2", - expectedGVK: gvkP("extensions", "v1beta1", "PodSecurityPolicy"), }, // -- @@ -425,6 +424,14 @@ var etcdStorageData = map[schema.GroupVersionResource]struct { gvr("scheduling.k8s.io", "v1alpha1", "priorityclasses"): { stub: `{"metadata":{"name":"pc1"},"Value":1000}`, expectedEtcdPath: "/registry/priorityclasses/pc1", + expectedGVK: gvkP("scheduling.k8s.io", "v1beta1", "PriorityClass"), + }, + // -- + + // k8s.io/kubernetes/pkg/apis/scheduling/v1beta1 + gvr("scheduling.k8s.io", "v1beta1", "priorityclasses"): { + stub: `{"metadata":{"name":"pc2"},"Value":1000}`, + expectedEtcdPath: "/registry/priorityclasses/pc2", }, // -- } @@ -434,84 +441,83 @@ var etcdStorageData = map[schema.GroupVersionResource]struct { var ephemeralWhiteList = createEphemeralWhiteList( // k8s.io/kubernetes/pkg/api/v1 - gvr("", "v1", "bindings"), // annotation on pod, not stored in etcd - gvr("", "v1", "rangeallocations"), // stored in various places in etcd but cannot be directly created - gvr("", "v1", "componentstatuses"), // status info not stored in etcd - gvr("", "v1", "serializedreferences"), // used for serilization, not stored in etcd - gvr("", "v1", "nodeconfigsources"), // subfield of node.spec, but shouldn't be directly created - gvr("", "v1", "podstatusresults"), // wrapper object not stored in etcd + gvk("", "v1", "Binding"), // annotation on pod, not stored in etcd + gvk("", "v1", "RangeAllocation"), // stored in various places in etcd but cannot be directly created + gvk("", "v1", "ComponentStatus"), // status info not stored in etcd + gvk("", "v1", "SerializedReference"), // used for serilization, not stored in etcd + gvk("", "v1", "PodStatusResult"), // wrapper object not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/authentication/v1beta1 - gvr("authentication.k8s.io", "v1beta1", "tokenreviews"), // not stored in etcd + gvk("authentication.k8s.io", "v1beta1", "TokenReview"), // not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/authentication/v1 - gvr("authentication.k8s.io", "v1", "tokenreviews"), // not stored in etcd - gvr("authentication.k8s.io", "v1", "tokenrequests"), // not stored in etcd + gvk("authentication.k8s.io", "v1", "TokenReview"), // not stored in etcd + gvk("authentication.k8s.io", "v1", "TokenRequest"), // not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/authorization/v1beta1 // SRR objects that are not stored in etcd - gvr("authorization.k8s.io", "v1beta1", "selfsubjectrulesreviews"), + gvk("authorization.k8s.io", "v1beta1", "SelfSubjectRulesReview"), // SAR objects that are not stored in etcd - gvr("authorization.k8s.io", "v1beta1", "selfsubjectaccessreviews"), - gvr("authorization.k8s.io", "v1beta1", "localsubjectaccessreviews"), - gvr("authorization.k8s.io", "v1beta1", "subjectaccessreviews"), + gvk("authorization.k8s.io", "v1beta1", "SelfSubjectAccessReview"), + gvk("authorization.k8s.io", "v1beta1", "LocalSubjectAccessReview"), + gvk("authorization.k8s.io", "v1beta1", "SubjectAccessReview"), // -- // k8s.io/kubernetes/pkg/apis/authorization/v1 // SRR objects that are not stored in etcd - gvr("authorization.k8s.io", "v1", "selfsubjectrulesreviews"), + gvk("authorization.k8s.io", "v1", "SelfSubjectRulesReview"), // SAR objects that are not stored in etcd - gvr("authorization.k8s.io", "v1", "selfsubjectaccessreviews"), - gvr("authorization.k8s.io", "v1", "localsubjectaccessreviews"), - gvr("authorization.k8s.io", "v1", "subjectaccessreviews"), + gvk("authorization.k8s.io", "v1", "SelfSubjectAccessReview"), + gvk("authorization.k8s.io", "v1", "LocalSubjectAccessReview"), + gvk("authorization.k8s.io", "v1", "SubjectAccessReview"), // -- // k8s.io/kubernetes/pkg/apis/autoscaling/v1 - gvr("autoscaling", "v1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController + gvk("autoscaling", "v1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController // -- // k8s.io/kubernetes/pkg/apis/apps/v1beta1 - gvr("apps", "v1beta1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController - gvr("apps", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd + gvk("apps", "v1beta1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController + gvk("apps", "v1beta1", "DeploymentRollback"), // used to rollback deployment, not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/apps/v1beta2 - gvr("apps", "v1beta2", "scales"), // not stored in etcd, part of kapiv1.ReplicationController + gvk("apps", "v1beta2", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController // -- // k8s.io/kubernetes/pkg/apis/batch/v1beta1 - gvr("batch", "v1beta1", "jobtemplates"), // not stored in etcd + gvk("batch", "v1beta1", "JobTemplate"), // not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/batch/v2alpha1 - gvr("batch", "v2alpha1", "jobtemplates"), // not stored in etcd + gvk("batch", "v2alpha1", "JobTemplate"), // not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1 - gvr("componentconfig", "v1alpha1", "kubeschedulerconfigurations"), // not stored in etcd + gvk("componentconfig", "v1alpha1", "KubeSchedulerConfiguration"), // not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/extensions/v1beta1 - gvr("extensions", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd - gvr("extensions", "v1beta1", "replicationcontrollerdummies"), // not stored in etcd - gvr("extensions", "v1beta1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController + gvk("extensions", "v1beta1", "DeploymentRollback"), // used to rollback deployment, not stored in etcd + gvk("extensions", "v1beta1", "ReplicationControllerDummy"), // not stored in etcd + gvk("extensions", "v1beta1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController // -- // k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1 - gvr("imagepolicy.k8s.io", "v1alpha1", "imagereviews"), // not stored in etcd + gvk("imagepolicy.k8s.io", "v1alpha1", "ImageReview"), // not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/policy/v1beta1 - gvr("policy", "v1beta1", "evictions"), // not stored in etcd, deals with evicting kapiv1.Pod + gvk("policy", "v1beta1", "Eviction"), // not stored in etcd, deals with evicting kapiv1.Pod // -- // k8s.io/kubernetes/pkg/apis/admission/v1beta1 - gvr("admission.k8s.io", "v1beta1", "admissionreviews"), // not stored in etcd, call out to webhooks. + gvk("admission.k8s.io", "v1beta1", "AdmissionReview"), // not stored in etcd, call out to webhooks. // -- ) @@ -537,7 +543,7 @@ var kindWhiteList = sets.NewString( "WatchEvent", // -- - // k8s.io/kubernetes/pkg/api/unversioned + // k8s.io/apimachinery/pkg/apis/meta/v1 "Status", // -- ) @@ -561,7 +567,7 @@ func TestEtcdStoragePath(t *testing.T) { kindSeen := sets.NewString() pathSeen := map[string][]schema.GroupVersionResource{} etcdSeen := map[schema.GroupVersionResource]empty{} - ephemeralSeen := map[schema.GroupVersionResource]empty{} + ephemeralSeen := map[schema.GroupVersionKind]empty{} cohabitatingResources := map[string]map[schema.GroupVersionKind]empty{} for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() { @@ -577,6 +583,11 @@ func TestEtcdStoragePath(t *testing.T) { kindSeen.Insert(kind) continue } + _, isEphemeral := ephemeralWhiteList[gvk] + if isEphemeral { + ephemeralSeen[gvk] = empty{} + continue + } mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version) if err != nil { @@ -584,29 +595,15 @@ func TestEtcdStoragePath(t *testing.T) { continue } - gvResource := gvk.GroupVersion().WithResource(mapping.Resource) - etcdSeen[gvResource] = empty{} + etcdSeen[mapping.Resource] = empty{} - testData, hasTest := etcdStorageData[gvResource] - _, isEphemeral := ephemeralWhiteList[gvResource] + testData, hasTest := etcdStorageData[mapping.Resource] - if !hasTest && !isEphemeral { + if !hasTest { t.Errorf("no test data for %s from %s. Please add a test for your new type to etcdStorageData.", kind, pkgPath) continue } - if hasTest && isEphemeral { - t.Errorf("duplicate test data for %s from %s. Object has both test data and is ephemeral.", kind, pkgPath) - continue - } - - if isEphemeral { // TODO it would be nice if we could remove this and infer if an object is not stored in etcd - // t.Logf("Skipping test for %s from %s", kind, pkgPath) - ephemeralSeen[gvResource] = empty{} - delete(etcdSeen, gvResource) - continue - } - if len(testData.expectedEtcdPath) == 0 { t.Errorf("empty test data for %s from %s", kind, pkgPath) continue @@ -668,7 +665,7 @@ func TestEtcdStoragePath(t *testing.T) { } addGVKToEtcdBucket(cohabitatingResources, actualGVK, getEtcdBucket(testData.expectedEtcdPath)) - pathSeen[testData.expectedEtcdPath] = append(pathSeen[testData.expectedEtcdPath], gvResource) + pathSeen[testData.expectedEtcdPath] = append(pathSeen[testData.expectedEtcdPath], mapping.Resource) }() } @@ -733,21 +730,25 @@ func startRealMasterOrDie(t *testing.T, certDir string) (*allClient, clientv3.KV kubeAPIServerOptions.Etcd.StorageConfig.ServerList = []string{framework.GetEtcdURL()} kubeAPIServerOptions.Etcd.DefaultStorageMediaType = runtime.ContentTypeJSON // TODO use protobuf? kubeAPIServerOptions.ServiceClusterIPRange = *defaultServiceClusterIPRange - kubeAPIServerOptions.Authorization.Mode = "RBAC" + kubeAPIServerOptions.Authorization.Modes = []string{"RBAC"} kubeAPIServerOptions.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount"} + completedOptions, err := app.Complete(kubeAPIServerOptions) + if err != nil { + t.Fatal(err) + } - tunneler, proxyTransport, err := app.CreateNodeDialer(kubeAPIServerOptions) + tunneler, proxyTransport, err := app.CreateNodeDialer(completedOptions) if err != nil { t.Fatal(err) } - kubeAPIServerConfig, sharedInformers, versionedInformers, _, _, _, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions, tunneler, proxyTransport) + kubeAPIServerConfig, sharedInformers, versionedInformers, _, _, _, admissionPostStartHook, err := app.CreateKubeAPIServerConfig(completedOptions, tunneler, proxyTransport) if err != nil { t.Fatal(err) } kubeAPIServerConfig.ExtraConfig.APIResourceConfigSource = &allResourceSource{} // force enable all resources - kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.EmptyDelegate, sharedInformers, versionedInformers) + kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.NewEmptyDelegate(), sharedInformers, versionedInformers, admissionPostStartHook) if err != nil { t.Fatal(err) } @@ -807,9 +808,11 @@ func startRealMasterOrDie(t *testing.T, certDir string) (*allClient, clientv3.KV t.Fatal(err) } - mapper, _ := util.NewFactory(clientcmd.NewDefaultClientConfig(*clientcmdapi.NewConfig(), &clientcmd.ConfigOverrides{})).Object() + discoveryClient := cacheddiscovery.NewMemCacheClient(kubeClient.Discovery()) + restMapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) + restMapper.Reset() - return client, kvClient, mapper + return client, kvClient, restMapper } func dumpEtcdKVOnFailure(t *testing.T, kvClient clientv3.KV) { @@ -884,17 +887,21 @@ func gvr(g, v, r string) schema.GroupVersionResource { return schema.GroupVersionResource{Group: g, Version: v, Resource: r} } +func gvk(g, v, k string) schema.GroupVersionKind { + return schema.GroupVersionKind{Group: g, Version: v, Kind: k} +} + func gvkP(g, v, k string) *schema.GroupVersionKind { return &schema.GroupVersionKind{Group: g, Version: v, Kind: k} } -func createEphemeralWhiteList(gvrs ...schema.GroupVersionResource) map[schema.GroupVersionResource]empty { - ephemeral := map[schema.GroupVersionResource]empty{} - for _, gvResource := range gvrs { - if _, ok := ephemeral[gvResource]; ok { +func createEphemeralWhiteList(gvks ...schema.GroupVersionKind) map[schema.GroupVersionKind]empty { + ephemeral := map[schema.GroupVersionKind]empty{} + for _, gvKind := range gvks { + if _, ok := ephemeral[gvKind]; ok { panic("invalid ephemeral whitelist contains duplicate keys") } - ephemeral[gvResource] = empty{} + ephemeral[gvKind] = empty{} } return ephemeral } @@ -952,7 +959,7 @@ func (c *allClient) create(stub, ns string, mapping *meta.RESTMapping, all *[]cl return err } namespaced := mapping.Scope.Name() == meta.RESTScopeNameNamespace - output, err := req.NamespaceIfScoped(ns, namespaced).Resource(mapping.Resource).Body(strings.NewReader(stub)).Do().Get() + output, err := req.NamespaceIfScoped(ns, namespaced).Resource(mapping.Resource.Resource).Body(strings.NewReader(stub)).Do().Get() if err != nil { return err } @@ -966,15 +973,15 @@ func (c *allClient) destroy(obj runtime.Object, mapping *meta.RESTMapping) error return err } namespaced := mapping.Scope.Name() == meta.RESTScopeNameNamespace - name, err := mapping.MetadataAccessor.Name(obj) + name, err := meta.NewAccessor().Name(obj) if err != nil { return err } - ns, err := mapping.MetadataAccessor.Namespace(obj) + ns, err := meta.NewAccessor().Namespace(obj) if err != nil { return err } - return req.NamespaceIfScoped(ns, namespaced).Resource(mapping.Resource).Name(name).Do().Error() + return req.NamespaceIfScoped(ns, namespaced).Resource(mapping.Resource.Resource).Name(name).Do().Error() } func (c *allClient) cleanup(all *[]cleanupData) error { diff --git a/vendor/k8s.io/kubernetes/test/integration/examples/BUILD b/vendor/k8s.io/kubernetes/test/integration/examples/BUILD index cd396d8a5..7e4402e21 100644 --- a/vendor/k8s.io/kubernetes/test/integration/examples/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/examples/BUILD @@ -25,12 +25,15 @@ go_test( "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", + "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", @@ -40,6 +43,7 @@ go_test( "//vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset:go_default_library", "//vendor/k8s.io/kube-aggregator/pkg/cmd/server:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:go_default_library", + "//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1:go_default_library", "//vendor/k8s.io/sample-apiserver/pkg/cmd/server:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/integration/examples/apiserver_test.go b/vendor/k8s.io/kubernetes/test/integration/examples/apiserver_test.go index 0fd40b3b2..cee26eae7 100644 --- a/vendor/k8s.io/kubernetes/test/integration/examples/apiserver_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/examples/apiserver_test.go @@ -31,10 +31,13 @@ import ( "github.com/stretchr/testify/assert" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" genericapiserver "k8s.io/apiserver/pkg/server" genericapiserveroptions "k8s.io/apiserver/pkg/server/options" + discovery "k8s.io/client-go/discovery" client "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" @@ -46,17 +49,11 @@ import ( "k8s.io/kubernetes/cmd/kube-apiserver/app" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/test/integration/framework" - "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + wardlev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + wardlev1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" sampleserver "k8s.io/sample-apiserver/pkg/cmd/server" ) -var groupVersion = v1alpha1.SchemeGroupVersion - -var groupVersionForDiscovery = metav1.GroupVersionForDiscovery{ - GroupVersion: groupVersion.String(), - Version: groupVersion.Version, -} - func TestAggregatedAPIServer(t *testing.T) { stopCh := make(chan struct{}) defer close(stopCh) @@ -109,13 +106,17 @@ func TestAggregatedAPIServer(t *testing.T) { kubeAPIServerOptions.Authentication.RequestHeader.AllowedNames = []string{"kube-aggregator"} kubeAPIServerOptions.Authentication.RequestHeader.ClientCAFile = proxyCACertFile.Name() kubeAPIServerOptions.Authentication.ClientCert.ClientCA = clientCACertFile.Name() - kubeAPIServerOptions.Authorization.Mode = "RBAC" + kubeAPIServerOptions.Authorization.Modes = []string{"RBAC"} + completedOptions, err := app.Complete(kubeAPIServerOptions) + if err != nil { + t.Fatal(err) + } - tunneler, proxyTransport, err := app.CreateNodeDialer(kubeAPIServerOptions) + tunneler, proxyTransport, err := app.CreateNodeDialer(completedOptions) if err != nil { t.Fatal(err) } - kubeAPIServerConfig, sharedInformers, versionedInformers, _, _, _, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions, tunneler, proxyTransport) + kubeAPIServerConfig, sharedInformers, versionedInformers, _, _, _, admissionPostStartHook, err := app.CreateKubeAPIServerConfig(completedOptions, tunneler, proxyTransport) if err != nil { t.Fatal(err) } @@ -126,7 +127,7 @@ func TestAggregatedAPIServer(t *testing.T) { kubeAPIServerClientConfig.ServerName = "" kubeClientConfigValue.Store(kubeAPIServerClientConfig) - kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.EmptyDelegate, sharedInformers, versionedInformers) + kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.NewEmptyDelegate(), sharedInformers, versionedInformers, admissionPostStartHook) if err != nil { t.Fatal(err) } @@ -137,7 +138,7 @@ func TestAggregatedAPIServer(t *testing.T) { }() // just use json because everyone speaks it - err = wait.PollImmediate(100*time.Millisecond, 10*time.Second, func() (done bool, err error) { + err = wait.PollImmediate(time.Second, time.Minute, func() (done bool, err error) { obj := kubeClientConfigValue.Load() if obj == nil { return false, nil @@ -336,9 +337,8 @@ func TestAggregatedAPIServer(t *testing.T) { // this is ugly, but sleep just a little bit so that the watch is probably observed. Since nothing will actually be added to discovery // (the service is missing), we don't have an external signal. time.Sleep(100 * time.Millisecond) - if _, err := aggregatorDiscoveryClient.Discovery().ServerResources(); err != nil { - t.Fatal(err) - } + _, err = aggregatorDiscoveryClient.Discovery().ServerResources() + assertWardleUnavailableDiscoveryError(t, err) _, err = aggregatorClient.ApiregistrationV1beta1().APIServices().Create(&apiregistrationv1beta1.APIService{ ObjectMeta: metav1.ObjectMeta{Name: "v1."}, @@ -359,13 +359,32 @@ func TestAggregatedAPIServer(t *testing.T) { // (the service is missing), we don't have an external signal. time.Sleep(100 * time.Millisecond) _, err = aggregatorDiscoveryClient.Discovery().ServerResources() - if err != nil { - t.Fatal(err) - } + assertWardleUnavailableDiscoveryError(t, err) // TODO figure out how to turn on enough of services and dns to run more } +func assertWardleUnavailableDiscoveryError(t *testing.T, err error) { + if err == nil { + t.Fatal("Discovery call expected to return failed unavailable service") + } + if !discovery.IsGroupDiscoveryFailedError(err) { + t.Fatalf("Unexpected error: %T, %v", err, err) + } + discoveryErr := err.(*discovery.ErrGroupDiscoveryFailed) + if len(discoveryErr.Groups) != 1 { + t.Fatalf("Unexpected failed groups: %v", err) + } + groupVersion := schema.GroupVersion{Group: "wardle.k8s.io", Version: "v1alpha1"} + groupVersionErr, ok := discoveryErr.Groups[groupVersion] + if !ok { + t.Fatalf("Unexpected failed group version: %v", err) + } + if !apierrors.IsServiceUnavailable(groupVersionErr) { + t.Fatalf("Unexpected failed group version error: %v", err) + } +} + func createKubeConfig(clientCfg *rest.Config) *clientcmdapi.Config { clusterNick := "cluster" userNick := "user" @@ -419,10 +438,21 @@ func testAPIGroupList(t *testing.T, client rest.Interface) { t.Fatalf("Error in unmarshalling response from server %s: %v", "/apis", err) } assert.Equal(t, 1, len(apiGroupList.Groups)) - assert.Equal(t, groupVersion.Group, apiGroupList.Groups[0].Name) - assert.Equal(t, 1, len(apiGroupList.Groups[0].Versions)) - assert.Equal(t, groupVersionForDiscovery, apiGroupList.Groups[0].Versions[0]) - assert.Equal(t, groupVersionForDiscovery, apiGroupList.Groups[0].PreferredVersion) + assert.Equal(t, wardlev1alpha1.GroupName, apiGroupList.Groups[0].Name) + assert.Equal(t, 2, len(apiGroupList.Groups[0].Versions)) + + v1alpha1 := metav1.GroupVersionForDiscovery{ + GroupVersion: wardlev1alpha1.SchemeGroupVersion.String(), + Version: wardlev1alpha1.SchemeGroupVersion.Version, + } + v1beta1 := metav1.GroupVersionForDiscovery{ + GroupVersion: wardlev1beta1.SchemeGroupVersion.String(), + Version: wardlev1beta1.SchemeGroupVersion.Version, + } + + assert.Equal(t, v1beta1, apiGroupList.Groups[0].Versions[0]) + assert.Equal(t, v1alpha1, apiGroupList.Groups[0].Versions[1]) + assert.Equal(t, v1beta1, apiGroupList.Groups[0].PreferredVersion) } func testAPIGroup(t *testing.T, client rest.Interface) { @@ -436,10 +466,10 @@ func testAPIGroup(t *testing.T, client rest.Interface) { if err != nil { t.Fatalf("Error in unmarshalling response from server %s: %v", "/apis/wardle.k8s.io", err) } - assert.Equal(t, groupVersion.Group, apiGroup.Name) - assert.Equal(t, 1, len(apiGroup.Versions)) - assert.Equal(t, groupVersion.String(), apiGroup.Versions[0].GroupVersion) - assert.Equal(t, groupVersion.Version, apiGroup.Versions[0].Version) + assert.Equal(t, wardlev1alpha1.SchemeGroupVersion.Group, apiGroup.Name) + assert.Equal(t, 2, len(apiGroup.Versions)) + assert.Equal(t, wardlev1alpha1.SchemeGroupVersion.String(), apiGroup.Versions[1].GroupVersion) + assert.Equal(t, wardlev1alpha1.SchemeGroupVersion.Version, apiGroup.Versions[1].Version) assert.Equal(t, apiGroup.PreferredVersion, apiGroup.Versions[0]) } @@ -454,7 +484,7 @@ func testAPIResourceList(t *testing.T, client rest.Interface) { if err != nil { t.Fatalf("Error in unmarshalling response from server %s: %v", "/apis/wardle.k8s.io/v1alpha1", err) } - assert.Equal(t, groupVersion.String(), apiResourceList.GroupVersion) + assert.Equal(t, wardlev1alpha1.SchemeGroupVersion.String(), apiResourceList.GroupVersion) assert.Equal(t, 2, len(apiResourceList.APIResources)) assert.Equal(t, "fischers", apiResourceList.APIResources[0].Name) assert.False(t, apiResourceList.APIResources[0].Namespaced) diff --git a/vendor/k8s.io/kubernetes/test/integration/examples/setup_test.go b/vendor/k8s.io/kubernetes/test/integration/examples/setup_test.go index 84203eb47..f9d75f811 100644 --- a/vendor/k8s.io/kubernetes/test/integration/examples/setup_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/examples/setup_test.go @@ -97,17 +97,21 @@ func startTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup kubeAPIServerOptions.Authentication.RequestHeader.AllowedNames = []string{"kube-aggregator"} kubeAPIServerOptions.Authentication.RequestHeader.ClientCAFile = proxyCACertFile.Name() kubeAPIServerOptions.Authentication.ClientCert.ClientCA = clientCACertFile.Name() - kubeAPIServerOptions.Authorization.Mode = "Node,RBAC" + kubeAPIServerOptions.Authorization.Modes = []string{"Node", "RBAC"} if setup.ModifyServerRunOptions != nil { setup.ModifyServerRunOptions(kubeAPIServerOptions) } - tunneler, proxyTransport, err := app.CreateNodeDialer(kubeAPIServerOptions) + completedOptions, err := app.Complete(kubeAPIServerOptions) if err != nil { t.Fatal(err) } - kubeAPIServerConfig, sharedInformers, versionedInformers, _, _, _, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions, tunneler, proxyTransport) + tunneler, proxyTransport, err := app.CreateNodeDialer(completedOptions) + if err != nil { + t.Fatal(err) + } + kubeAPIServerConfig, sharedInformers, versionedInformers, _, _, _, admissionPostStartHook, err := app.CreateKubeAPIServerConfig(completedOptions, tunneler, proxyTransport) if err != nil { t.Fatal(err) } @@ -115,7 +119,7 @@ func startTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup if setup.ModifyServerConfig != nil { setup.ModifyServerConfig(kubeAPIServerConfig) } - kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.EmptyDelegate, sharedInformers, versionedInformers) + kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.NewEmptyDelegate(), sharedInformers, versionedInformers, admissionPostStartHook) if err != nil { t.Fatal(err) } diff --git a/vendor/k8s.io/kubernetes/test/integration/framework/BUILD b/vendor/k8s.io/kubernetes/test/integration/framework/BUILD index 98c4112d4..94573f4db 100644 --- a/vendor/k8s.io/kubernetes/test/integration/framework/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/framework/BUILD @@ -28,7 +28,6 @@ go_library( "//pkg/master:go_default_library", "//pkg/util/env:go_default_library", "//pkg/version:go_default_library", - "//plugin/pkg/admission/admit:go_default_library", "//test/e2e/framework:go_default_library", "//test/utils:go_default_library", "//vendor/github.com/go-openapi/spec:go_default_library", @@ -54,6 +53,7 @@ go_library( "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/union:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/framework/master_utils.go b/vendor/k8s.io/kubernetes/test/integration/framework/master_utils.go index 994c17e7a..070c80265 100644 --- a/vendor/k8s.io/kubernetes/test/integration/framework/master_utils.go +++ b/vendor/k8s.io/kubernetes/test/integration/framework/master_utils.go @@ -44,6 +44,7 @@ import ( "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizerfactory" authorizerunion "k8s.io/apiserver/pkg/authorization/union" + openapinamer "k8s.io/apiserver/pkg/endpoints/openapi" genericapiserver "k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server/options" serverstorage "k8s.io/apiserver/pkg/server/storage" @@ -59,7 +60,6 @@ import ( kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/master" "k8s.io/kubernetes/pkg/version" - "k8s.io/kubernetes/plugin/pkg/admission/admit" ) // Config is a struct of configuration directives for NewMasterComponents. @@ -125,9 +125,7 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv if masterConfig == nil { masterConfig = NewMasterConfig() - masterConfig.GenericConfig.EnableProfiling = true - masterConfig.GenericConfig.EnableMetrics = true - masterConfig.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.GetOpenAPIDefinitions, legacyscheme.Scheme) + masterConfig.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.GetOpenAPIDefinitions, openapinamer.NewDefinitionNamer(legacyscheme.Scheme)) masterConfig.GenericConfig.OpenAPIConfig.Info = &spec.Info{ InfoProps: spec.InfoProps{ Title: "Kubernetes", @@ -180,7 +178,7 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv } sharedInformers := informers.NewSharedInformerFactory(clientset, masterConfig.GenericConfig.LoopbackClientConfig.Timeout) - m, err = masterConfig.Complete(sharedInformers).New(genericapiserver.EmptyDelegate) + m, err = masterConfig.Complete(sharedInformers).New(genericapiserver.NewEmptyDelegate()) if err != nil { closeFn() glog.Fatalf("error in bringing up the master: %v", err) @@ -202,6 +200,7 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv closeFn() glog.Fatal(err) } + var lastHealthContent []byte err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) { result := privilegedClient.Get().AbsPath("/healthz").Do() status := 0 @@ -209,16 +208,26 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv if status == 200 { return true, nil } + lastHealthContent, _ = result.Raw() return false, nil }) if err != nil { closeFn() + glog.Errorf("last health content: %q", string(lastHealthContent)) glog.Fatal(err) } return m, s, closeFn } +// Returns the master config appropriate for most integration tests. +func NewIntegrationTestMasterConfig() *master.Config { + masterConfig := NewMasterConfig() + masterConfig.GenericConfig.PublicAddress = net.ParseIP("192.168.10.4") + masterConfig.ExtraConfig.APIResourceConfigSource = master.DefaultAPIResourceConfigSource() + return masterConfig +} + // Returns a basic master config. func NewMasterConfig() *master.Config { // This causes the integration tests to exercise the etcd @@ -230,7 +239,7 @@ func NewMasterConfig() *master.Config { info, _ := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) ns := NewSingleContentTypeSerializer(legacyscheme.Scheme, info) - resourceEncoding := serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Registry) + resourceEncoding := serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Scheme) // FIXME (soltysh): this GroupVersionResource override should be configurable // we need to set both for the whole group and for cronjobs, separately resourceEncoding.SetVersionEncoding(batch.GroupName, *testapi.Batch.GroupVersion(), schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal}) @@ -281,8 +290,6 @@ func NewMasterConfig() *master.Config { kubeVersion := version.Get() genericConfig.Version = &kubeVersion genericConfig.Authorization.Authorizer = authorizerfactory.NewAlwaysAllowAuthorizer() - genericConfig.AdmissionControl = admit.NewAlwaysAdmit() - genericConfig.EnableMetrics = true err := etcdOptions.ApplyWithStorageFactoryTo(storageFactory, genericConfig) if err != nil { @@ -294,7 +301,6 @@ func NewMasterConfig() *master.Config { ExtraConfig: master.ExtraConfig{ APIResourceConfigSource: master.DefaultAPIResourceConfigSource(), StorageFactory: storageFactory, - EnableCoreControllers: true, KubeletClientConfig: kubeletclient.KubeletClientConfig{Port: 10250}, APIServerServicePort: 443, MasterCount: 1, @@ -302,15 +308,6 @@ func NewMasterConfig() *master.Config { } } -// Returns the master config appropriate for most integration tests. -func NewIntegrationTestMasterConfig() *master.Config { - masterConfig := NewMasterConfig() - masterConfig.ExtraConfig.EnableCoreControllers = true - masterConfig.GenericConfig.PublicAddress = net.ParseIP("192.168.10.4") - masterConfig.ExtraConfig.APIResourceConfigSource = master.DefaultAPIResourceConfigSource() - return masterConfig -} - // CloseFunc can be called to cleanup the master type CloseFunc func() @@ -318,7 +315,6 @@ func RunAMaster(masterConfig *master.Config) (*master.Master, *httptest.Server, if masterConfig == nil { masterConfig = NewMasterConfig() masterConfig.GenericConfig.EnableProfiling = true - masterConfig.GenericConfig.EnableMetrics = true } return startMasterOrDie(masterConfig, nil, nil) } diff --git a/vendor/k8s.io/kubernetes/test/integration/framework/perf_utils.go b/vendor/k8s.io/kubernetes/test/integration/framework/perf_utils.go index 8a270bcc9..8897e93f6 100644 --- a/vendor/k8s.io/kubernetes/test/integration/framework/perf_utils.go +++ b/vendor/k8s.io/kubernetes/test/integration/framework/perf_utils.go @@ -56,10 +56,6 @@ func (p *IntegrationTestNodePreparer) PrepareNodes() error { ObjectMeta: metav1.ObjectMeta{ GenerateName: p.nodeNamePrefix, }, - Spec: v1.NodeSpec{ - // TODO: investigate why this is needed. - ExternalID: "foo", - }, Status: v1.NodeStatus{ Capacity: v1.ResourceList{ v1.ResourcePods: *resource.NewQuantity(110, resource.DecimalSI), diff --git a/vendor/k8s.io/kubernetes/test/integration/framework/util.go b/vendor/k8s.io/kubernetes/test/integration/framework/util.go index 8fbb57de4..9e7ea3424 100644 --- a/vendor/k8s.io/kubernetes/test/integration/framework/util.go +++ b/vendor/k8s.io/kubernetes/test/integration/framework/util.go @@ -20,12 +20,10 @@ package framework import ( "net/http/httptest" - "strings" "testing" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - clientset "k8s.io/client-go/kubernetes" ) const ( @@ -35,27 +33,6 @@ const ( currentPodInfraContainerImageVersion = "3.1" ) -// GetServerArchitecture fetches the architecture of the cluster's apiserver. -func GetServerArchitecture(c clientset.Interface) string { - arch := "" - sVer, err := c.Discovery().ServerVersion() - if err != nil || sVer.Platform == "" { - // If we failed to get the server version for some reason, default to amd64. - arch = "amd64" - } else { - // Split the platform string into OS and Arch separately. - // The platform string may for example be "linux/amd64", "linux/arm" or "windows/amd64". - osArchArray := strings.Split(sVer.Platform, "/") - arch = osArchArray[1] - } - return arch -} - -// GetPauseImageName fetches the pause image name for the same architecture as the apiserver. -func GetPauseImageName(c clientset.Interface) string { - return currentPodInfraContainerImageName + "-" + GetServerArchitecture(c) + ":" + currentPodInfraContainerImageVersion -} - func CreateTestingNamespace(baseName string, apiserver *httptest.Server, t *testing.T) *v1.Namespace { // TODO: Create a namespace with a given basename. // Currently we neither create the namespace nor delete all of its contents at the end. diff --git a/vendor/k8s.io/kubernetes/test/integration/garbagecollector/BUILD b/vendor/k8s.io/kubernetes/test/integration/garbagecollector/BUILD index 23a4c27ad..9229bdb7d 100644 --- a/vendor/k8s.io/kubernetes/test/integration/garbagecollector/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/garbagecollector/BUILD @@ -23,14 +23,15 @@ go_test( "//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/apis/meta/v1/unstructured:go_default_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/wait:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", - "//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/discovery/cached:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/restmapper:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/integration/garbagecollector/cluster_scoped_owner_test.go b/vendor/k8s.io/kubernetes/test/integration/garbagecollector/cluster_scoped_owner_test.go index a1ae4d202..1f8092f78 100644 --- a/vendor/k8s.io/kubernetes/test/integration/garbagecollector/cluster_scoped_owner_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/garbagecollector/cluster_scoped_owner_test.go @@ -51,7 +51,7 @@ func (b *readDelayer) Read(p []byte) (n int, err error) { func TestClusterScopedOwners(t *testing.T) { // Start the test server and wrap the client to delay PV watch responses - server := kubeapiservertesting.StartTestServerOrDie(t, nil, framework.SharedEtcd()) + server := kubeapiservertesting.StartTestServerOrDie(t, nil, nil, framework.SharedEtcd()) server.ClientConfig.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { return roundTripFunc(func(req *http.Request) (*http.Response, error) { if req.URL.Query().Get("watch") != "true" || !strings.Contains(req.URL.String(), "persistentvolumes") { diff --git a/vendor/k8s.io/kubernetes/test/integration/garbagecollector/garbage_collector_test.go b/vendor/k8s.io/kubernetes/test/integration/garbagecollector/garbage_collector_test.go index 50746d4b5..a6fce7efd 100644 --- a/vendor/k8s.io/kubernetes/test/integration/garbagecollector/garbage_collector_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/garbagecollector/garbage_collector_test.go @@ -32,14 +32,15 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/storage/names" - "k8s.io/client-go/discovery" cacheddiscovery "k8s.io/client-go/discovery/cached" "k8s.io/client-go/dynamic" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/restmapper" "k8s.io/client-go/tools/cache" kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" "k8s.io/kubernetes/pkg/controller/garbagecollector" @@ -167,23 +168,23 @@ func link(t *testing.T, owner, dependent metav1.Object) { func createRandomCustomResourceDefinition( t *testing.T, apiExtensionClient apiextensionsclientset.Interface, - clientPool dynamic.ClientPool, + dynamicClient dynamic.Interface, namespace string, ) (*apiextensionsv1beta1.CustomResourceDefinition, dynamic.ResourceInterface) { // Create a random custom resource definition and ensure it's available for // use. definition := apiextensionstestserver.NewRandomNameCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - client, err := apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, clientPool) + definition, err := apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, dynamicClient) if err != nil { t.Fatalf("failed to create CustomResourceDefinition: %v", err) } // Get a client for the custom resource. - resourceClient := client.Resource(&metav1.APIResource{ - Name: definition.Spec.Names.Plural, - Namespaced: true, - }, namespace) + gvr := schema.GroupVersionResource{Group: definition.Spec.Group, Version: definition.Spec.Version, Resource: definition.Spec.Names.Plural} + + resourceClient := dynamicClient.Resource(gvr).Namespace(namespace) + return definition, resourceClient } @@ -192,7 +193,7 @@ type testContext struct { gc *garbagecollector.GarbageCollector clientSet clientset.Interface apiExtensionClient apiextensionsclientset.Interface - clientPool dynamic.ClientPool + dynamicClient dynamic.Interface startGC func(workers int) // syncPeriod is how often the GC started with startGC will be resynced. syncPeriod time.Duration @@ -200,7 +201,7 @@ type testContext struct { // if workerCount > 0, will start the GC, otherwise it's up to the caller to Run() the GC. func setup(t *testing.T, workerCount int) *testContext { - return setupWithServer(t, kubeapiservertesting.StartTestServerOrDie(t, nil, framework.SharedEtcd()), workerCount) + return setupWithServer(t, kubeapiservertesting.StartTestServerOrDie(t, nil, nil, framework.SharedEtcd()), workerCount) } func setupWithServer(t *testing.T, result *kubeapiservertesting.TestServer, workerCount int) *testContext { @@ -219,19 +220,19 @@ func setupWithServer(t *testing.T, result *kubeapiservertesting.TestServer, work createNamespaceOrDie("aval", clientSet, t) discoveryClient := cacheddiscovery.NewMemCacheClient(clientSet.Discovery()) - restMapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient, meta.InterfacesForUnstructured) + restMapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) restMapper.Reset() deletableResources := garbagecollector.GetDeletableResources(discoveryClient) config := *result.ClientConfig - config.ContentConfig = dynamic.ContentConfig() - metaOnlyClientPool := dynamic.NewClientPool(&config, restMapper, dynamic.LegacyAPIPathResolverFunc) - clientPool := dynamic.NewClientPool(&config, restMapper, dynamic.LegacyAPIPathResolverFunc) + dynamicClient, err := dynamic.NewForConfig(&config) + if err != nil { + t.Fatalf("failed to create dynamicClient: %v", err) + } sharedInformers := informers.NewSharedInformerFactory(clientSet, 0) alwaysStarted := make(chan struct{}) close(alwaysStarted) gc, err := garbagecollector.NewGarbageCollector( - metaOnlyClientPool, - clientPool, + dynamicClient, restMapper, deletableResources, garbagecollector.DefaultIgnoredResources(), @@ -249,6 +250,12 @@ func setupWithServer(t *testing.T, result *kubeapiservertesting.TestServer, work } syncPeriod := 5 * time.Second startGC := func(workers int) { + go wait.Until(func() { + // Resetting the REST mapper will also invalidate the underlying discovery + // client. This is a leaky abstraction and assumes behavior about the REST + // mapper, but we'll deal with it for now. + restMapper.Reset() + }, syncPeriod, stopCh) go gc.Run(workers, stopCh) go gc.Sync(clientSet.Discovery(), syncPeriod, stopCh) } @@ -262,7 +269,7 @@ func setupWithServer(t *testing.T, result *kubeapiservertesting.TestServer, work gc: gc, clientSet: clientSet, apiExtensionClient: apiExtensionClient, - clientPool: clientPool, + dynamicClient: dynamicClient, startGC: startGC, syncPeriod: syncPeriod, } @@ -362,12 +369,12 @@ func TestCascadingDeletion(t *testing.T) { // sometimes the deletion of the RC takes long time to be observed by // the gc, so wait for the garbage collector to observe the deletion of // the toBeDeletedRC - if err := wait.Poll(10*time.Second, 60*time.Second, func() (bool, error) { + if err := wait.Poll(1*time.Second, 60*time.Second, func() (bool, error) { return !gc.GraphHasUID([]types.UID{toBeDeletedRC.ObjectMeta.UID}), nil }); err != nil { t.Fatal(err) } - if err := integration.WaitForPodToDisappear(podClient, garbageCollectedPodName, 5*time.Second, 30*time.Second); err != nil { + if err := integration.WaitForPodToDisappear(podClient, garbageCollectedPodName, 1*time.Second, 30*time.Second); err != nil { t.Fatalf("expect pod %s to be garbage collected, got err= %v", garbageCollectedPodName, err) } // checks the garbage collect doesn't delete pods it shouldn't delete. @@ -407,7 +414,7 @@ func TestCreateWithNonExistentOwner(t *testing.T) { t.Fatalf("Unexpected pod list: %v", pods.Items) } // wait for the garbage collector to delete the pod - if err := integration.WaitForPodToDisappear(podClient, garbageCollectedPodName, 5*time.Second, 30*time.Second); err != nil { + if err := integration.WaitForPodToDisappear(podClient, garbageCollectedPodName, 1*time.Second, 30*time.Second); err != nil { t.Fatalf("expect pod %s to be garbage collected, got err= %v", garbageCollectedPodName, err) } } @@ -441,7 +448,7 @@ func setupRCsPods(t *testing.T, gc *garbagecollector.GarbageCollector, clientSet // creation of the pods, otherwise if the deletion of RC is observed before // the creation of the pods, the pods will not be orphaned. if orphan { - wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) { return gc.GraphHasUID(podUIDs), nil }) + wait.Poll(1*time.Second, 60*time.Second, func() (bool, error) { return gc.GraphHasUID(podUIDs), nil }) } // delete the rc if err := rcClient.Delete(rc.ObjectMeta.Name, options); err != nil { @@ -501,7 +508,7 @@ func TestStressingCascadingDeletion(t *testing.T) { wg.Wait() t.Logf("all pods are created, all replications controllers are created then deleted") // wait for the RCs and Pods to reach the expected numbers. - if err := wait.Poll(5*time.Second, 300*time.Second, func() (bool, error) { + if err := wait.Poll(1*time.Second, 300*time.Second, func() (bool, error) { podsInEachCollection := 3 // see the comments on the calls to setupRCsPods for details remainingGroups := 3 @@ -568,14 +575,14 @@ func TestOrphaning(t *testing.T) { // we need wait for the gc to observe the creation of the pods, otherwise if // the deletion of RC is observed before the creation of the pods, the pods // will not be orphaned. - wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) { return gc.GraphHasUID(podUIDs), nil }) + wait.Poll(1*time.Second, 60*time.Second, func() (bool, error) { return gc.GraphHasUID(podUIDs), nil }) err = rcClient.Delete(toBeDeletedRCName, getOrphanOptions()) if err != nil { t.Fatalf("Failed to gracefully delete the rc: %v", err) } // verify the toBeDeleteRC is deleted - if err := wait.PollImmediate(5*time.Second, 30*time.Second, func() (bool, error) { + if err := wait.PollImmediate(1*time.Second, 30*time.Second, func() (bool, error) { rcs, err := rcClient.List(metav1.ListOptions{}) if err != nil { return false, err @@ -639,7 +646,7 @@ func TestSolidOwnerDoesNotBlockWaitingOwner(t *testing.T) { t.Fatalf("Failed to delete the rc: %v", err) } // verify the toBeDeleteRC is deleted - if err := wait.PollImmediate(5*time.Second, 30*time.Second, func() (bool, error) { + if err := wait.PollImmediate(1*time.Second, 30*time.Second, func() (bool, error) { _, err := rcClient.Get(toBeDeletedRC.Name, metav1.GetOptions{}) if err != nil { if errors.IsNotFound(err) { @@ -707,7 +714,7 @@ func TestNonBlockingOwnerRefDoesNotBlock(t *testing.T) { t.Fatalf("Failed to delete the rc: %v", err) } // verify the toBeDeleteRC is deleted - if err := wait.PollImmediate(5*time.Second, 30*time.Second, func() (bool, error) { + if err := wait.PollImmediate(1*time.Second, 30*time.Second, func() (bool, error) { _, err := rcClient.Get(toBeDeletedRC.Name, metav1.GetOptions{}) if err != nil { if errors.IsNotFound(err) { @@ -797,11 +804,11 @@ func TestCustomResourceCascadingDeletion(t *testing.T) { ctx := setup(t, 5) defer ctx.tearDown() - clientSet, apiExtensionClient, clientPool := ctx.clientSet, ctx.apiExtensionClient, ctx.clientPool + clientSet, apiExtensionClient, dynamicClient := ctx.clientSet, ctx.apiExtensionClient, ctx.dynamicClient ns := createNamespaceOrDie("crd-cascading", clientSet, t) - definition, resourceClient := createRandomCustomResourceDefinition(t, apiExtensionClient, clientPool, ns.Name) + definition, resourceClient := createRandomCustomResourceDefinition(t, apiExtensionClient, dynamicClient, ns.Name) // Create a custom owner resource. owner := newCRDInstance(definition, ns.Name, names.SimpleNameGenerator.GenerateName("owner")) @@ -829,7 +836,7 @@ func TestCustomResourceCascadingDeletion(t *testing.T) { } // Ensure the owner is deleted. - if err := wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) { + if err := wait.Poll(1*time.Second, 60*time.Second, func() (bool, error) { _, err := resourceClient.Get(owner.GetName(), metav1.GetOptions{}) return errors.IsNotFound(err), nil }); err != nil { @@ -857,13 +864,13 @@ func TestMixedRelationships(t *testing.T) { ctx := setup(t, 5) defer ctx.tearDown() - clientSet, apiExtensionClient, clientPool := ctx.clientSet, ctx.apiExtensionClient, ctx.clientPool + clientSet, apiExtensionClient, dynamicClient := ctx.clientSet, ctx.apiExtensionClient, ctx.dynamicClient ns := createNamespaceOrDie("crd-mixed", clientSet, t) configMapClient := clientSet.CoreV1().ConfigMaps(ns.Name) - definition, resourceClient := createRandomCustomResourceDefinition(t, apiExtensionClient, clientPool, ns.Name) + definition, resourceClient := createRandomCustomResourceDefinition(t, apiExtensionClient, dynamicClient, ns.Name) // Create a custom owner resource. customOwner, err := resourceClient.Create(newCRDInstance(definition, ns.Name, names.SimpleNameGenerator.GenerateName("owner"))) @@ -907,7 +914,7 @@ func TestMixedRelationships(t *testing.T) { } // Ensure the owner is deleted. - if err := wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) { + if err := wait.Poll(1*time.Second, 60*time.Second, func() (bool, error) { _, err := resourceClient.Get(customOwner.GetName(), metav1.GetOptions{}) return errors.IsNotFound(err), nil }); err != nil { @@ -931,7 +938,7 @@ func TestMixedRelationships(t *testing.T) { } // Ensure the owner is deleted. - if err := wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) { + if err := wait.Poll(1*time.Second, 60*time.Second, func() (bool, error) { _, err := configMapClient.Get(coreOwner.GetName(), metav1.GetOptions{}) return errors.IsNotFound(err), nil }); err != nil { @@ -955,13 +962,13 @@ func TestCRDDeletionCascading(t *testing.T) { ctx := setup(t, 5) defer ctx.tearDown() - clientSet, apiExtensionClient, clientPool := ctx.clientSet, ctx.apiExtensionClient, ctx.clientPool + clientSet, apiExtensionClient, dynamicClient := ctx.clientSet, ctx.apiExtensionClient, ctx.dynamicClient ns := createNamespaceOrDie("crd-mixed", clientSet, t) configMapClient := clientSet.CoreV1().ConfigMaps(ns.Name) - definition, resourceClient := createRandomCustomResourceDefinition(t, apiExtensionClient, clientPool, ns.Name) + definition, resourceClient := createRandomCustomResourceDefinition(t, apiExtensionClient, dynamicClient, ns.Name) // Create a custom owner resource. owner, err := resourceClient.Create(newCRDInstance(definition, ns.Name, names.SimpleNameGenerator.GenerateName("owner"))) @@ -987,7 +994,7 @@ func TestCRDDeletionCascading(t *testing.T) { } // Ensure the owner is deleted. - if err := wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) { + if err := wait.Poll(1*time.Second, 60*time.Second, func() (bool, error) { _, err := resourceClient.Get(owner.GetName(), metav1.GetOptions{}) return errors.IsNotFound(err), nil }); err != nil { @@ -995,7 +1002,7 @@ func TestCRDDeletionCascading(t *testing.T) { } // Ensure the dependent is deleted. - if err := wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) { + if err := wait.Poll(1*time.Second, 60*time.Second, func() (bool, error) { _, err := configMapClient.Get(dependent.GetName(), metav1.GetOptions{}) return errors.IsNotFound(err), nil }); err != nil { diff --git a/vendor/k8s.io/kubernetes/test/integration/ipamperf/BUILD b/vendor/k8s.io/kubernetes/test/integration/ipamperf/BUILD new file mode 100644 index 000000000..8437e35fc --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/ipamperf/BUILD @@ -0,0 +1,70 @@ +package(default_visibility = ["//visibility:public"]) + +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_test( + name = "go_default_test", + size = "large", + srcs = [ + "ipam_test.go", + "main_test.go", + ], + embed = [":go_default_library"], + tags = ["integration"], + deps = [ + "//pkg/controller/nodeipam:go_default_library", + "//pkg/controller/nodeipam/ipam:go_default_library", + "//test/integration/framework:go_default_library", + "//test/integration/util:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + srcs = [ + "cloud.go", + "results.go", + "util.go", + ], + importpath = "k8s.io/kubernetes/test/integration/ipamperf", + deps = [ + "//pkg/cloudprovider:go_default_library", + "//pkg/cloudprovider/providers/gce/cloud:go_default_library", + "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", + "//pkg/controller/nodeipam/ipam:go_default_library", + "//pkg/controller/nodeipam/ipam/cidrset:go_default_library", + "//pkg/controller/util/node:go_default_library", + "//test/integration/util:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/google.golang.org/api/compute/v0.beta:go_default_library", + "//vendor/google.golang.org/api/compute/v1:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_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/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/tools/cache:go_default_library", + ], +) diff --git a/vendor/k8s.io/kubernetes/test/integration/ipamperf/README.md b/vendor/k8s.io/kubernetes/test/integration/ipamperf/README.md new file mode 100644 index 000000000..532dcdc8c --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/ipamperf/README.md @@ -0,0 +1,85 @@ +IPAM Performance Test +===== + +Motivation +----- +We wanted to be able to test the behavior of the IPAM controller's under various scenarios, +by mocking and monitoring the edges that the controller interacts with. This has the following goals: + +- Save time on testing +- To simulate various behaviors cheaply +- To observe and model the ideal behavior of the IPAM controller code + +Currently the test runs through the 4 different IPAM controller modes for cases where the kube API QPS is a) +equal to and b) significantly less than the number of nodes being added to observe and quantify behavior. + +How to run +------- + +```shell +# In kubernetes root path +make generated_files + +cd test/integration/ipamperf +./test-performance.sh +``` + +The runner scripts support a few different options: + +```shell +./test-performance.sh -h +usage: ./test-performance.sh [-h] [-d] [-r ] [-o ] +usage: ./test-performance.sh + -h display this help message + -d enable debug logs in tests + -r regex pattern to match for tests + -o file to write JSON formatted results to + -p enable cpu and memory profiles, output written to mem-.out and cpu-.out + -c enable custom test configuration + -a allocator name, one of RangeAllocator, CloudAllocator, IPAMFromCluster, IPAMFromCloud + -k api server qps for allocator + -n number of nodes to simulate + -m api server qps for node creation + -l gce cloud endpoint qps +``` + +The tests follow the pattern TestPerformance/{AllocatorType}-KubeQPS{X}-Nodes{Y}, where AllocatorType +is one of + +- RangeAllocator +- IPAMFromCluster +- CloudAllocator +- IPAMFromCloud + +and X represents the QPS configured for the kubernetes API client, and Y is the number of nodes to create. + +The -d flags set the -v level for glog to 6, enabling nearly all of the debug logs in the code. + +So to run the test for CloudAllocator with 10 nodes, one can run + +```shell +./test-performance.sh -r /CloudAllocator.*Nodes10$ +``` + +At the end of the test, a JSON format of the results for all the tests run is printed. Passing the -o option +allows for also saving this JSON to a named file. + +### Profiling the code +It's possible to get the CPU and memory profiles of code during test execution by using the ```-p``` option. +The CPU and memory profiles are generated in the same directory with the file names set to ```cpu-.out``` +and ```cpu-.out```, where `````` is the argument value. Typicall pattern is to put in the number +of nodes being simulated as the id, or 'all' in case running the full suite. + +### Custom Test Configuration +It's also possible to run a custom test configuration by passing the -c option. With this option, it then +possible to specify the number of nodes to simulate and the API server qps values for creation, +IPAM allocation and cloud endpoint, along with the allocator name to run. The defaults values for the +qps parmeters are 30 for IPAM allocation, 100 for node creation and 30 for the cloud endpoint, and the +default allocator is the RangeAllocator. + +Code Organization +----- +The core of the tests are defined in [ipam_test.go](ipam_test.go), using the t.Run() helper to control parallelism +as we want to able to start the master once. [cloud.go](cloud.go) contains the mock of the cloud server endpoint +and can be configured to behave differently as needed by the various modes. The tracking of the node behavior and +creation of the test results data is in [results.go](results.go). diff --git a/vendor/k8s.io/kubernetes/test/integration/ipamperf/cloud.go b/vendor/k8s.io/kubernetes/test/integration/ipamperf/cloud.go new file mode 100644 index 000000000..c7cb10ec1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/ipamperf/cloud.go @@ -0,0 +1,154 @@ +/* +Copyright 2018 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 ipamperf + +import ( + "context" + "net" + "sync" + + beta "google.golang.org/api/compute/v0.beta" + ga "google.golang.org/api/compute/v1" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "k8s.io/kubernetes/pkg/controller/nodeipam/ipam/cidrset" + "k8s.io/kubernetes/test/integration/util" +) + +// implemntation note: +// ------------------ +// cloud.go implements hooks and handler functions for the MockGCE cloud in order to meet expectations +// of cloud behavior from the IPAM controllers. The key constraint is that the IPAM code is spread +// across both GA and Beta instances, which are distinct objects in the mock. We need to solve for +// +// 1. When a GET is called on an instance, we lazy create the instance with or without an assigned +// ip alias as needed by the IPAM controller type +// 2. When we assign an IP alias for an instance, both the GA and Beta instance have to agree on the +// assigned alias range +// +// We solve both the problems by using a baseInstanceList which maintains a list of known instances, +// and their pre-assigned ip-alias ranges (if needed). We then create GetHook for GA and Beta GetInstance +// calls as closures over this betaInstanceList that can lookup base instance data. +// +// This has the advantage that once the Get hook pouplates the GCEMock with the base data, we then let the +// rest of the mock code run as is. + +// baseInstance tracks basic instance data needed by the IPAM controllers +type baseInstance struct { + name string + zone string + aliasRange string +} + +// baseInstanceList tracks a set of base instances +type baseInstanceList struct { + allocateCIDR bool + clusterCIDR *net.IPNet + subnetMaskSize int + cidrSet *cidrset.CidrSet + + lock sync.Mutex // protect access to instances + instances map[meta.Key]*baseInstance +} + +// toGA is an utility method to return the baseInstance data as a GA Instance object +func (bi *baseInstance) toGA() *ga.Instance { + inst := &ga.Instance{Name: bi.name, Zone: bi.zone, NetworkInterfaces: []*ga.NetworkInterface{{}}} + if bi.aliasRange != "" { + inst.NetworkInterfaces[0].AliasIpRanges = []*ga.AliasIpRange{ + {IpCidrRange: bi.aliasRange, SubnetworkRangeName: util.TestSecondaryRangeName}, + } + } + return inst +} + +// toGA is an utility method to return the baseInstance data as a beta Instance object +func (bi *baseInstance) toBeta() *beta.Instance { + inst := &beta.Instance{Name: bi.name, Zone: bi.zone, NetworkInterfaces: []*beta.NetworkInterface{{}}} + if bi.aliasRange != "" { + inst.NetworkInterfaces[0].AliasIpRanges = []*beta.AliasIpRange{ + {IpCidrRange: bi.aliasRange, SubnetworkRangeName: util.TestSecondaryRangeName}, + } + } + return inst +} + +// newBaseInstanceList is the baseInstanceList constructor +func newBaseInstanceList(allocateCIDR bool, clusterCIDR *net.IPNet, subnetMaskSize int) *baseInstanceList { + cidrSet, _ := cidrset.NewCIDRSet(clusterCIDR, subnetMaskSize) + return &baseInstanceList{ + allocateCIDR: allocateCIDR, + clusterCIDR: clusterCIDR, + subnetMaskSize: subnetMaskSize, + cidrSet: cidrSet, + instances: make(map[meta.Key]*baseInstance), + } +} + +// getOrCreateBaseInstance lazily creates a new base instance, assigning if allocateCIDR is true +func (bil *baseInstanceList) getOrCreateBaseInstance(key *meta.Key) *baseInstance { + bil.lock.Lock() + defer bil.lock.Unlock() + + inst, found := bil.instances[*key] + if !found { + inst = &baseInstance{name: key.Name, zone: key.Zone} + if bil.allocateCIDR { + nextRange, _ := bil.cidrSet.AllocateNext() + inst.aliasRange = nextRange.String() + } + bil.instances[*key] = inst + } + return inst +} + +// newGAGetHook creates a new closure with the current baseInstanceList to be used as a MockInstances.GetHook +func (bil *baseInstanceList) newGAGetHook() func(ctx context.Context, key *meta.Key, m *cloud.MockInstances) (bool, *ga.Instance, error) { + return func(ctx context.Context, key *meta.Key, m *cloud.MockInstances) (bool, *ga.Instance, error) { + m.Lock.Lock() + defer m.Lock.Unlock() + + if _, found := m.Objects[*key]; !found { + m.Objects[*key] = &cloud.MockInstancesObj{Obj: bil.getOrCreateBaseInstance(key).toGA()} + } + return false, nil, nil + } +} + +// newBetaGetHook creates a new closure with the current baseInstanceList to be used as a MockBetaInstances.GetHook +func (bil *baseInstanceList) newBetaGetHook() func(ctx context.Context, key *meta.Key, m *cloud.MockBetaInstances) (bool, *beta.Instance, error) { + return func(ctx context.Context, key *meta.Key, m *cloud.MockBetaInstances) (bool, *beta.Instance, error) { + m.Lock.Lock() + defer m.Lock.Unlock() + + if _, found := m.Objects[*key]; !found { + m.Objects[*key] = &cloud.MockInstancesObj{Obj: bil.getOrCreateBaseInstance(key).toBeta()} + } + return false, nil, nil + } +} + +// newMockCloud returns a mock GCE instance with the appropriate handlers hooks +func (bil *baseInstanceList) newMockCloud() cloud.Cloud { + c := cloud.NewMockGCE(nil) + + // insert hooks to lazy create a instance when needed + c.MockInstances.GetHook = bil.newGAGetHook() + c.MockBetaInstances.GetHook = bil.newBetaGetHook() + + return c +} diff --git a/vendor/k8s.io/kubernetes/test/integration/ipamperf/ipam_test.go b/vendor/k8s.io/kubernetes/test/integration/ipamperf/ipam_test.go new file mode 100644 index 000000000..70eedabe1 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/ipamperf/ipam_test.go @@ -0,0 +1,158 @@ +/* +Copyright 2018 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 ipamperf + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net" + "os" + "testing" + "time" + + "github.com/golang/glog" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + "k8s.io/kubernetes/pkg/controller/nodeipam" + "k8s.io/kubernetes/pkg/controller/nodeipam/ipam" + "k8s.io/kubernetes/test/integration/util" +) + +func setupAllocator(apiURL string, config *Config, clusterCIDR, serviceCIDR *net.IPNet, subnetMaskSize int) (*clientset.Clientset, util.ShutdownFunc, error) { + controllerStopChan := make(chan struct{}) + shutdownFunc := func() { + close(controllerStopChan) + } + + clientSet := clientset.NewForConfigOrDie(&restclient.Config{ + Host: apiURL, + ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, + QPS: float32(config.KubeQPS), + Burst: config.KubeQPS, + }) + + sharedInformer := informers.NewSharedInformerFactory(clientSet, 1*time.Hour) + ipamController, err := nodeipam.NewNodeIpamController( + sharedInformer.Core().V1().Nodes(), config.Cloud, clientSet, + clusterCIDR, serviceCIDR, subnetMaskSize, config.AllocatorType, + ) + if err != nil { + return nil, shutdownFunc, err + } + go ipamController.Run(controllerStopChan) + sharedInformer.Start(controllerStopChan) + + return clientSet, shutdownFunc, nil +} + +func runTest(t *testing.T, apiURL string, config *Config, clusterCIDR, serviceCIDR *net.IPNet, subnetMaskSize int) (*Results, error) { + t.Helper() + glog.Infof("Running test %s", t.Name()) + + defer deleteNodes(apiURL, config) // cleanup nodes on after controller shutdown + + clientSet, shutdownFunc, err := setupAllocator(apiURL, config, clusterCIDR, serviceCIDR, subnetMaskSize) + if err != nil { + t.Fatalf("Error starting IPAM allocator: %v", err) + } + defer shutdownFunc() + + o := NewObserver(clientSet, config.NumNodes) + if err := o.StartObserving(); err != nil { + t.Fatalf("Could not start test observer: %v", err) + } + + if err := createNodes(apiURL, config); err != nil { + t.Fatalf("Could not create nodes: %v", err) + } + + results := o.Results(t.Name(), config) + glog.Infof("Results: %s", results) + if !results.Succeeded { + t.Errorf("%s: Not allocations succeeded", t.Name()) + } + return results, nil +} + +func logResults(allResults []*Results) { + jStr, err := json.MarshalIndent(allResults, "", " ") + if err != nil { + glog.Errorf("Error formating results: %v", err) + return + } + if resultsLogFile != "" { + glog.Infof("Logging results to %s", resultsLogFile) + if err := ioutil.WriteFile(resultsLogFile, jStr, os.FileMode(0644)); err != nil { + glog.Errorf("Error logging results to %s: %v", resultsLogFile, err) + } + } + glog.Infof("AllResults:\n%s", string(jStr)) +} + +func TestPerformance(t *testing.T) { + if testing.Short() { + // TODO (#61854) find why flakiness is caused by etcd connectivity before enabling always + t.Skip("Skipping because we want to run short tests") + } + + apiURL, masterShutdown := util.StartApiserver() + defer masterShutdown() + + _, clusterCIDR, _ := net.ParseCIDR("10.96.0.0/11") // allows up to 8K nodes + _, serviceCIDR, _ := net.ParseCIDR("10.94.0.0/24") // does not matter for test - pick upto 250 services + subnetMaskSize := 24 + + var ( + allResults []*Results + tests []*Config + ) + + if isCustom { + tests = append(tests, customConfig) + } else { + for _, numNodes := range []int{10, 100} { + for _, alloc := range []ipam.CIDRAllocatorType{ipam.RangeAllocatorType, ipam.CloudAllocatorType, ipam.IPAMFromClusterAllocatorType, ipam.IPAMFromCloudAllocatorType} { + tests = append(tests, &Config{AllocatorType: alloc, NumNodes: numNodes, CreateQPS: numNodes, KubeQPS: 10, CloudQPS: 10}) + } + } + } + + for _, test := range tests { + testName := fmt.Sprintf("%s-KubeQPS%d-Nodes%d", test.AllocatorType, test.KubeQPS, test.NumNodes) + t.Run(testName, func(t *testing.T) { + allocateCIDR := false + if test.AllocatorType == ipam.IPAMFromCloudAllocatorType || test.AllocatorType == ipam.CloudAllocatorType { + allocateCIDR = true + } + bil := newBaseInstanceList(allocateCIDR, clusterCIDR, subnetMaskSize) + cloud, err := util.NewMockGCECloud(bil.newMockCloud()) + if err != nil { + t.Fatalf("Unable to create mock cloud: %v", err) + } + test.Cloud = cloud + if results, err := runTest(t, apiURL, test, clusterCIDR, serviceCIDR, subnetMaskSize); err == nil { + allResults = append(allResults, results) + } + }) + } + + logResults(allResults) +} diff --git a/vendor/k8s.io/kubernetes/test/integration/ipamperf/main_test.go b/vendor/k8s.io/kubernetes/test/integration/ipamperf/main_test.go new file mode 100644 index 000000000..401ad4528 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/ipamperf/main_test.go @@ -0,0 +1,66 @@ +/* +Copyright 2018 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 ipamperf + +import ( + "flag" + "testing" + + "github.com/golang/glog" + "k8s.io/kubernetes/pkg/controller/nodeipam/ipam" + "k8s.io/kubernetes/test/integration/framework" +) + +var ( + resultsLogFile string + isCustom bool + customConfig = &Config{ + NumNodes: 10, + KubeQPS: 30, + CloudQPS: 30, + CreateQPS: 100, + AllocatorType: ipam.RangeAllocatorType, + } +) + +func TestMain(m *testing.M) { + allocator := string(ipam.RangeAllocatorType) + + flag.StringVar(&resultsLogFile, "log", "", "log file to write JSON results to") + flag.BoolVar(&isCustom, "custom", false, "enable custom test configuration") + flag.StringVar(&allocator, "allocator", allocator, "allocator to use") + flag.IntVar(&customConfig.KubeQPS, "kube-qps", customConfig.KubeQPS, "API server qps for allocations") + flag.IntVar(&customConfig.NumNodes, "num-nodes", 10, "number of nodes to simulate") + flag.IntVar(&customConfig.CreateQPS, "create-qps", customConfig.CreateQPS, "API server qps for node creation") + flag.IntVar(&customConfig.CloudQPS, "cloud-qps", customConfig.CloudQPS, "GCE Cloud qps limit") + flag.Parse() + + switch allocator { + case string(ipam.RangeAllocatorType): + customConfig.AllocatorType = ipam.RangeAllocatorType + case string(ipam.CloudAllocatorType): + customConfig.AllocatorType = ipam.CloudAllocatorType + case string(ipam.IPAMFromCloudAllocatorType): + customConfig.AllocatorType = ipam.IPAMFromCloudAllocatorType + case string(ipam.IPAMFromClusterAllocatorType): + customConfig.AllocatorType = ipam.IPAMFromClusterAllocatorType + default: + glog.Fatalf("Unknown allocator type: %s", allocator) + } + + framework.EtcdMain(m.Run) +} diff --git a/vendor/k8s.io/kubernetes/test/integration/ipamperf/results.go b/vendor/k8s.io/kubernetes/test/integration/ipamperf/results.go new file mode 100644 index 000000000..c5971e14d --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/ipamperf/results.go @@ -0,0 +1,221 @@ +/* +Copyright 2018 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 ipamperf + +import ( + "bytes" + "fmt" + "sort" + "sync" + "time" + + "github.com/golang/glog" + "k8s.io/api/core/v1" + "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/cache" + "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/controller/nodeipam/ipam" + nodeutil "k8s.io/kubernetes/pkg/controller/util/node" +) + +// Config represents the test configuration that is being run +type Config struct { + CreateQPS int // rate at which nodes are created + KubeQPS int // rate for communication with kubernetes API + CloudQPS int // rate for communication with cloud endpoint + NumNodes int // number of nodes to created and monitored + AllocatorType ipam.CIDRAllocatorType // type of allocator to run + Cloud cloudprovider.Interface // cloud provider +} + +type nodeTime struct { + added time.Time // observed time for when node was added + allocated time.Time // observed time for when node was assigned podCIDR + podCIDR string // the allocated podCIDR range +} + +// Observer represents the handle to test observer that watches for node changes +// and tracks behavior +type Observer struct { + numAdded int // number of nodes observed added + numAllocated int // number of nodes observed allocated podCIDR + timing map[string]*nodeTime // per node timing + numNodes int // the number of nodes to expect + stopChan chan struct{} // for the shared informer + wg sync.WaitGroup + clientSet *clientset.Clientset +} + +// JSONDuration is an alias of time.Duration to support custom Marshal code +type JSONDuration time.Duration + +// NodeDuration represents the CIDR allocation time for each node +type NodeDuration struct { + Name string // node name + PodCIDR string // the podCIDR that was assigned to the node + Duration JSONDuration // how long it took to assign podCIDR +} + +// Results represents the observed test results. +type Results struct { + Name string // name for the test + Config *Config // handle to the test config + Succeeded bool // whether all nodes were assigned podCIDR + MaxAllocTime JSONDuration // the maximum time take for assignment per node + TotalAllocTime JSONDuration // duration between first addition and last assignment + NodeAllocTime []NodeDuration // assignment time by node name +} + +// NewObserver creates a new observer given a handle to the Clientset +func NewObserver(clientSet *clientset.Clientset, numNodes int) *Observer { + o := &Observer{ + timing: map[string]*nodeTime{}, + numNodes: numNodes, + clientSet: clientSet, + stopChan: make(chan struct{}), + } + return o +} + +// StartObserving starts an asynchronous loop to monitor for node changes. +// Call Results() to get the test results after starting observer. +func (o *Observer) StartObserving() error { + o.monitor() + glog.Infof("Test observer started") + return nil +} + +// Results returns the test results. It waits for the observer to finish +// and returns the computed results of the observations. +func (o *Observer) Results(name string, config *Config) *Results { + var ( + firstAdd time.Time // earliest time any node was added (first node add) + lastAssignment time.Time // latest time any node was assignged CIDR (last node assignment) + ) + o.wg.Wait() + close(o.stopChan) // shutdown the shared informer + + results := &Results{ + Name: name, + Config: config, + Succeeded: o.numAdded == o.numNodes && o.numAllocated == o.numNodes, + MaxAllocTime: 0, + NodeAllocTime: []NodeDuration{}, + } + for name, nTime := range o.timing { + addFound := !nTime.added.IsZero() + if addFound && (firstAdd.IsZero() || nTime.added.Before(firstAdd)) { + firstAdd = nTime.added + } + cidrFound := !nTime.allocated.IsZero() + if cidrFound && nTime.allocated.After(lastAssignment) { + lastAssignment = nTime.allocated + } + if addFound && cidrFound { + allocTime := nTime.allocated.Sub(nTime.added) + if allocTime > time.Duration(results.MaxAllocTime) { + results.MaxAllocTime = JSONDuration(allocTime) + } + results.NodeAllocTime = append(results.NodeAllocTime, NodeDuration{ + Name: name, PodCIDR: nTime.podCIDR, Duration: JSONDuration(allocTime), + }) + } + } + results.TotalAllocTime = JSONDuration(lastAssignment.Sub(firstAdd)) + sort.Slice(results.NodeAllocTime, func(i, j int) bool { + return results.NodeAllocTime[i].Duration > results.NodeAllocTime[j].Duration + }) + return results +} + +func (o *Observer) monitor() { + o.wg.Add(1) + + sharedInformer := informers.NewSharedInformerFactory(o.clientSet, 1*time.Second) + nodeInformer := sharedInformer.Core().V1().Nodes().Informer() + + nodeInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: nodeutil.CreateAddNodeHandler(func(node *v1.Node) (err error) { + name := node.GetName() + if node.Spec.PodCIDR != "" { + // ignore nodes that have PodCIDR (might be hold over from previous runs that did not get cleaned up) + return + } + nTime := &nodeTime{} + o.timing[name] = nTime + nTime.added = time.Now() + o.numAdded = o.numAdded + 1 + return + }), + UpdateFunc: nodeutil.CreateUpdateNodeHandler(func(oldNode, newNode *v1.Node) (err error) { + name := newNode.GetName() + nTime, found := o.timing[name] + if !found { + return // consistency check - ignore nodes we have not seen the add event for + } + // check if CIDR assigned and ignore redundant updates + if newNode.Spec.PodCIDR != "" && nTime.podCIDR == "" { + nTime.allocated = time.Now() + nTime.podCIDR = newNode.Spec.PodCIDR + o.numAllocated++ + if o.numAllocated%10 == 0 { + glog.Infof("progress: %d/%d - %.2d%%", o.numAllocated, o.numNodes, (o.numAllocated * 100.0 / o.numNodes)) + } + // do following check only if numAllocated is modified, as otherwise, redundant updates + // can cause wg.Done() to be called multiple times, causing a panic + if o.numAdded == o.numNodes && o.numAllocated == o.numNodes { + glog.Info("All nodes assigned podCIDR") + o.wg.Done() + } + } + return + }), + }) + sharedInformer.Start(o.stopChan) +} + +// String implements the Stringer interface and returns a multi-line representation +// of the test results. +func (results *Results) String() string { + var b bytes.Buffer + fmt.Fprintf(&b, "\n TestName: %s", results.Name) + fmt.Fprintf(&b, "\n NumNodes: %d, CreateQPS: %d, KubeQPS: %d, CloudQPS: %d, Allocator: %v", + results.Config.NumNodes, results.Config.CreateQPS, results.Config.KubeQPS, + results.Config.CloudQPS, results.Config.AllocatorType) + fmt.Fprintf(&b, "\n Succeeded: %v, TotalAllocTime: %v, MaxAllocTime: %v", + results.Succeeded, time.Duration(results.TotalAllocTime), time.Duration(results.MaxAllocTime)) + fmt.Fprintf(&b, "\n %5s %-20s %-20s %s", "Num", "Node", "PodCIDR", "Duration (s)") + for i, d := range results.NodeAllocTime { + fmt.Fprintf(&b, "\n %5d %-20s %-20s %10.3f", i+1, d.Name, d.PodCIDR, time.Duration(d.Duration).Seconds()) + } + return b.String() +} + +// MarshalJSON implements the json.Marshaler interface +func (jDuration *JSONDuration) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf("\"%s\"", time.Duration(*jDuration).String())), nil +} + +// UnmarshalJSON implements the json.Unmarshaler interface +func (jDuration *JSONDuration) UnmarshalJSON(b []byte) (err error) { + var d time.Duration + if d, err = time.ParseDuration(string(b[1 : len(b)-1])); err == nil { + *jDuration = JSONDuration(d) + } + return +} diff --git a/vendor/k8s.io/kubernetes/test/integration/ipamperf/test-performance.sh b/vendor/k8s.io/kubernetes/test/integration/ipamperf/test-performance.sh new file mode 100755 index 000000000..0540978c0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/ipamperf/test-performance.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +# Copyright 2018 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. + +set -o errexit +set -o nounset +set -o pipefail + +TEST_ARGS="" +RUN_PATTERN=".*" +PROFILE_OPTS="" + +function usage() { + echo "usage: $0 " + echo " -h display this help message" + echo " -d enable debug logs in tests" + echo " -r regex pattern to match for tests" + echo " -o file to write JSON formatted results to" + echo " -p enable cpu and memory profiles, output written to mem-.out and cpu-.out" + echo " -c enable custom test configuration" + echo " -a allocator name, one of RangeAllocator, CloudAllocator, IPAMFromCluster, IPAMFromCloud" + echo " -k api server qps for allocator" + echo " -n number of nodes to simulate" + echo " -m api server qps for node creation" + echo " -l gce cloud endpoint qps" + exit 1 +} + +while getopts ":hdr:o:p:ca:k:n:m:l:" opt; do + case ${opt} in + d) TEST_ARGS="${TEST_ARGS} -v=6" + ;; + r) RUN_PATTERN="${OPTARG}" + ;; + o) TEST_ARGS="${TEST_ARGS} -log ${OPTARG}" + ;; + p) PROFILE_OPTS="-memprofile mem-${OPTARG}.out -cpuprofile cpu-${OPTARG}.out" + ;; + c) TEST_ARGS="${TEST_ARGS} -custom" + ;; + a) TEST_ARGS="${TEST_ARGS} -allocator ${OPTARG}" + ;; + k) TEST_ARGS="${TEST_ARGS} -kube-qps ${OPTARG}" + ;; + n) TEST_ARGS="${TEST_ARGS} -num-nodes ${OPTARG}" + ;; + m) TEST_ARGS="${TEST_ARGS} -create-qps ${OPTARG}" + ;; + l) TEST_ARGS="${TEST_ARGS} -cloud-qps ${OPTARG}" + ;; + h) usage + ;; + \?) usage + ;; + esac +done + +KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../../../ +source "${KUBE_ROOT}/hack/lib/init.sh" + +kube::golang::setup_env + +DIR_BASENAME=$(dirname "${BASH_SOURCE}") +pushd ${DIR_BASENAME} + +cleanup() { + popd 2> /dev/null + kube::etcd::cleanup + kube::log::status "performance test cleanup complete" +} + +trap cleanup EXIT + +kube::etcd::start + +# Running IPAM tests. It might take a long time. +kube::log::status "performance test (IPAM) start" +go test ${PROFILE_OPTS} -test.run=${RUN_PATTERN} -test.timeout=60m -test.short=false -v -args ${TEST_ARGS} +kube::log::status "... IPAM tests finished." diff --git a/vendor/k8s.io/kubernetes/test/integration/ipamperf/util.go b/vendor/k8s.io/kubernetes/test/integration/ipamperf/util.go new file mode 100644 index 000000000..34c1c175c --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/ipamperf/util.go @@ -0,0 +1,95 @@ +/* +Copyright 2018 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 ipamperf + +import ( + "time" + + "github.com/golang/glog" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + clientset "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" +) + +const ( + maxCreateRetries = 10 + retryDelay = 10 * time.Second +) + +var ( + baseNodeTemplate = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "sample-node-", + }, + Status: v1.NodeStatus{ + Capacity: v1.ResourceList{ + v1.ResourcePods: *resource.NewQuantity(110, resource.DecimalSI), + v1.ResourceCPU: resource.MustParse("4"), + v1.ResourceMemory: resource.MustParse("32Gi"), + }, + Phase: v1.NodeRunning, + Conditions: []v1.NodeCondition{ + {Type: v1.NodeReady, Status: v1.ConditionTrue}, + }, + }, + } +) + +func deleteNodes(apiURL string, config *Config) { + glog.Info("Deleting nodes") + clientSet := clientset.NewForConfigOrDie(&restclient.Config{ + Host: apiURL, + ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, + QPS: float32(config.CreateQPS), + Burst: config.CreateQPS, + }) + noGrace := int64(0) + if err := clientSet.CoreV1().Nodes().DeleteCollection(&metav1.DeleteOptions{GracePeriodSeconds: &noGrace}, metav1.ListOptions{}); err != nil { + glog.Errorf("Error deleting node: %v", err) + } +} + +func createNodes(apiURL string, config *Config) error { + clientSet := clientset.NewForConfigOrDie(&restclient.Config{ + Host: apiURL, + ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, + QPS: float32(config.CreateQPS), + Burst: config.CreateQPS, + }) + glog.Infof("Creating %d nodes", config.NumNodes) + for i := 0; i < config.NumNodes; i++ { + var err error + for j := 0; j < maxCreateRetries; j++ { + if _, err = clientSet.CoreV1().Nodes().Create(baseNodeTemplate); err != nil && errors.IsServerTimeout(err) { + glog.Infof("Server timeout creating nodes, retrying after %v", retryDelay) + time.Sleep(retryDelay) + continue + } + break + } + if err != nil { + glog.Errorf("Error creating nodes: %v", err) + return err + } + } + glog.Infof("%d nodes created", config.NumNodes) + return nil +} diff --git a/vendor/k8s.io/kubernetes/test/integration/master/BUILD b/vendor/k8s.io/kubernetes/test/integration/master/BUILD index 8c9d58872..15cac881d 100644 --- a/vendor/k8s.io/kubernetes/test/integration/master/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/master/BUILD @@ -60,6 +60,7 @@ go_test( "//test/integration/framework:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/networking/v1:go_default_library", @@ -77,6 +78,7 @@ go_test( "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library", "//vendor/k8s.io/apiserver/pkg/features:go_default_library", + "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library", @@ -180,6 +182,7 @@ go_library( "//test/integration/framework:go_default_library", "//vendor/github.com/coreos/etcd/clientv3:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig:go_default_library", @@ -188,51 +191,61 @@ go_library( "//vendor/k8s.io/client-go/kubernetes:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:android": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", ], "@io_bazel_rules_go//go/platform:darwin": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", ], "@io_bazel_rules_go//go/platform:dragonfly": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", ], "@io_bazel_rules_go//go/platform:freebsd": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", ], "@io_bazel_rules_go//go/platform:linux": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", ], "@io_bazel_rules_go//go/platform:nacl": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", ], "@io_bazel_rules_go//go/platform:netbsd": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", ], "@io_bazel_rules_go//go/platform:openbsd": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", ], "@io_bazel_rules_go//go/platform:plan9": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", ], "@io_bazel_rules_go//go/platform:solaris": [ + "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/master/crd_test.go b/vendor/k8s.io/kubernetes/test/integration/master/crd_test.go index f2bc91a5c..37ba367fb 100644 --- a/vendor/k8s.io/kubernetes/test/integration/master/crd_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/master/crd_test.go @@ -41,7 +41,7 @@ import ( ) func TestCRDShadowGroup(t *testing.T) { - result := kubeapiservertesting.StartTestServerOrDie(t, nil, framework.SharedEtcd()) + result := kubeapiservertesting.StartTestServerOrDie(t, nil, nil, framework.SharedEtcd()) defer result.TearDownFn() kubeclient, err := kubernetes.NewForConfig(result.ClientConfig) @@ -109,7 +109,7 @@ func TestCRDShadowGroup(t *testing.T) { func TestCRD(t *testing.T) { defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.Initializers, true)() - result := kubeapiservertesting.StartTestServerOrDie(t, []string{"--admission-control", "Initializers"}, framework.SharedEtcd()) + result := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--admission-control", "Initializers"}, framework.SharedEtcd()) defer result.TearDownFn() kubeclient, err := kubernetes.NewForConfig(result.ClientConfig) @@ -150,14 +150,12 @@ func TestCRD(t *testing.T) { } t.Logf("Trying to access foos.cr.bar.com with dynamic client") - barComConfig := *result.ClientConfig - barComConfig.GroupVersion = &schema.GroupVersion{Group: "cr.bar.com", Version: "v1"} - barComConfig.APIPath = "/apis" - barComClient, err := dynamic.NewClient(&barComConfig) + dynamicClient, err := dynamic.NewForConfig(result.ClientConfig) if err != nil { t.Fatalf("Unexpected error: %v", err) } - _, err = barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").List(metav1.ListOptions{}) + fooResource := schema.GroupVersionResource{Group: "cr.bar.com", Version: "v1", Resource: "foos"} + _, err = dynamicClient.Resource(fooResource).Namespace("default").List(metav1.ListOptions{}) if err != nil { t.Errorf("Failed to list foos.cr.bar.com instances: %v", err) } @@ -201,7 +199,7 @@ func TestCRD(t *testing.T) { } createErr := make(chan error, 1) go func() { - _, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Create(unstructuredFoo) + _, err := dynamicClient.Resource(fooResource).Namespace("default").Create(unstructuredFoo) t.Logf("Foo instance create returned: %v", err) if err != nil { createErr <- err @@ -216,7 +214,7 @@ func TestCRD(t *testing.T) { } t.Logf("Checking that Foo instance is visible with IncludeUninitialized=true") - _, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{ + _, err := dynamicClient.Resource(fooResource).Namespace("default").Get(foo.ObjectMeta.Name, metav1.GetOptions{ IncludeUninitialized: true, }) switch { @@ -237,7 +235,7 @@ func TestCRD(t *testing.T) { for i := 0; i < 10; i++ { // would love to replace the following with a patch, but removing strings from the intitializer array // is not what JSON (Merge) patch authors had in mind. - fooUnstructured, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{ + fooUnstructured, err := dynamicClient.Resource(fooResource).Namespace("default").Get(foo.ObjectMeta.Name, metav1.GetOptions{ IncludeUninitialized: true, }) if err != nil { @@ -274,7 +272,7 @@ func TestCRD(t *testing.T) { } fooUnstructured.UnmarshalJSON(bs) - _, err = barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Update(fooUnstructured) + _, err = dynamicClient.Resource(fooResource).Namespace("default").Update(fooUnstructured) if err != nil && !errors.IsConflict(err) { t.Fatalf("Failed to update Foo instance: %v", err) } else if err == nil { @@ -287,7 +285,7 @@ func TestCRD(t *testing.T) { } t.Logf("Checking that Foo instance is visible after removing the initializer") - if _, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{}); err != nil { + if _, err := dynamicClient.Resource(fooResource).Namespace("default").Get(foo.ObjectMeta.Name, metav1.GetOptions{}); err != nil { t.Errorf("Unexpected error: %v", err) } } diff --git a/vendor/k8s.io/kubernetes/test/integration/master/kms_plugin_mock.go b/vendor/k8s.io/kubernetes/test/integration/master/kms_plugin_mock.go index e937690cb..49e6401f5 100644 --- a/vendor/k8s.io/kubernetes/test/integration/master/kms_plugin_mock.go +++ b/vendor/k8s.io/kubernetes/test/integration/master/kms_plugin_mock.go @@ -28,6 +28,7 @@ import ( "golang.org/x/sys/unix" "google.golang.org/grpc" + "github.com/golang/glog" kmsapi "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1" ) @@ -45,7 +46,6 @@ type base64Plugin struct { // Allow users of the plugin to sense requests that were passed to KMS. encryptRequest chan *kmsapi.EncryptRequest - decryptRequest chan *kmsapi.DecryptRequest } func NewBase64Plugin() (*base64Plugin, error) { @@ -57,6 +57,7 @@ func NewBase64Plugin() (*base64Plugin, error) { if err != nil { return nil, fmt.Errorf("failed to listen on the unix socket, error: %v", err) } + glog.Infof("Listening on %s", sockFile) server := grpc.NewServer() @@ -64,7 +65,6 @@ func NewBase64Plugin() (*base64Plugin, error) { grpcServer: server, listener: listener, encryptRequest: make(chan *kmsapi.EncryptRequest, 1), - decryptRequest: make(chan *kmsapi.DecryptRequest, 1), } kmsapi.RegisterKeyManagementServiceServer(server, result) @@ -85,7 +85,8 @@ func (s *base64Plugin) Version(ctx context.Context, request *kmsapi.VersionReque } func (s *base64Plugin) Decrypt(ctx context.Context, request *kmsapi.DecryptRequest) (*kmsapi.DecryptResponse, error) { - s.decryptRequest <- request + glog.Infof("Received Decrypt Request for DEK: %s", string(request.Cipher)) + buf := make([]byte, base64.StdEncoding.DecodedLen(len(request.Cipher))) n, err := base64.StdEncoding.Decode(buf, request.Cipher) if err != nil { @@ -96,6 +97,7 @@ func (s *base64Plugin) Decrypt(ctx context.Context, request *kmsapi.DecryptReque } func (s *base64Plugin) Encrypt(ctx context.Context, request *kmsapi.EncryptRequest) (*kmsapi.EncryptResponse, error) { + glog.Infof("Received Encrypt Request for DEK: %x", request.Plain) s.encryptRequest <- request buf := make([]byte, base64.StdEncoding.EncodedLen(len(request.Plain))) diff --git a/vendor/k8s.io/kubernetes/test/integration/master/kms_transformation_test.go b/vendor/k8s.io/kubernetes/test/integration/master/kms_transformation_test.go index cb4275e12..f3cfa201c 100644 --- a/vendor/k8s.io/kubernetes/test/integration/master/kms_transformation_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/master/kms_transformation_test.go @@ -26,7 +26,6 @@ import ( "fmt" "strings" "testing" - "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/storage/value" @@ -86,7 +85,10 @@ func TestKMSProvider(t *testing.T) { t.Fatalf("failed to create mock of KMS Plugin: %v", err) } defer pluginMock.cleanUp() - go pluginMock.grpcServer.Serve(pluginMock.listener) + serveErr := make(chan error, 1) + go func() { + serveErr <- pluginMock.grpcServer.Serve(pluginMock.listener) + }() test, err := newTransformTest(t, kmsConfigYAML) if err != nil { @@ -94,6 +96,11 @@ func TestKMSProvider(t *testing.T) { } defer test.cleanUp() + // As part of newTransformTest a new secret was created, so KMS Mock should have been exercised by this point. + if len(serveErr) != 0 { + t.Fatalf("KMSPlugin failed while serving requests: %v", <-serveErr) + } + secretETCDPath := test.getETCDPath() var rawSecretAsSeenByETCD rawDEKKEKSecret rawSecretAsSeenByETCD, err = test.getRawSecretFromETCD() @@ -137,15 +144,18 @@ func TestKMSProvider(t *testing.T) { if secretVal != string(s.Data[secretKey]) { t.Fatalf("expected %s from KubeAPI, but got %s", secretVal, string(s.Data[secretKey])) } + test.printMetrics() } func getDEKFromKMSPlugin(pluginMock *base64Plugin) ([]byte, error) { - select { - case e := <-pluginMock.encryptRequest: - return e.Plain, nil - case <-time.After(time.Second): - return nil, fmt.Errorf("timed-out while getting encryption request from KMS Plugin Mock") + // We expect KMS to already have seen an encryptRequest. Hence non-blocking call. + e, ok := <-pluginMock.encryptRequest + + if !ok { + return nil, fmt.Errorf("failed to sense encryptRequest from KMS Plugin Mock") } + + return e.Plain, nil } func decryptPayload(key []byte, secret rawDEKKEKSecret, secretETCDPath string) ([]byte, error) { diff --git a/vendor/k8s.io/kubernetes/test/integration/master/kube_apiserver_test.go b/vendor/k8s.io/kubernetes/test/integration/master/kube_apiserver_test.go index 6beadcd67..187b1da1b 100644 --- a/vendor/k8s.io/kubernetes/test/integration/master/kube_apiserver_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/master/kube_apiserver_test.go @@ -18,13 +18,18 @@ package master import ( "encoding/json" + "fmt" + "reflect" "strings" "testing" + "time" appsv1beta1 "k8s.io/api/apps/v1beta1" corev1 "k8s.io/api/core/v1" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/client-go/kubernetes" "k8s.io/kube-aggregator/pkg/apis/apiregistration" kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" @@ -32,7 +37,7 @@ import ( ) func TestRun(t *testing.T) { - server := kubeapiservertesting.StartTestServerOrDie(t, nil, framework.SharedEtcd()) + server := kubeapiservertesting.StartTestServerOrDie(t, nil, nil, framework.SharedEtcd()) defer server.TearDownFn() client, err := kubernetes.NewForConfig(server.ClientConfig) @@ -82,7 +87,7 @@ func TestRun(t *testing.T) { // apiextensions-server and the kube-aggregator server, both part of // the delegation chain in kube-apiserver. func TestOpenAPIDelegationChainPlumbing(t *testing.T) { - server := kubeapiservertesting.StartTestServerOrDie(t, nil, framework.SharedEtcd()) + server := kubeapiservertesting.StartTestServerOrDie(t, nil, nil, framework.SharedEtcd()) defer server.TearDownFn() kubeclient, err := kubernetes.NewForConfig(server.ClientConfig) @@ -138,3 +143,110 @@ func TestOpenAPIDelegationChainPlumbing(t *testing.T) { t.Errorf("missing path: %q", registrationPrefix) } } + +// return the unique endpoint IPs +func getEndpointIPs(endpoints *corev1.Endpoints) []string { + endpointMap := make(map[string]bool) + ips := make([]string, 0) + for _, subset := range endpoints.Subsets { + for _, address := range subset.Addresses { + if _, ok := endpointMap[address.IP]; !ok { + endpointMap[address.IP] = true + ips = append(ips, address.IP) + } + } + } + return ips +} + +func verifyEndpointsWithIPs(servers []*kubeapiservertesting.TestServer, ips []string) bool { + listenAddresses := make([]string, 0) + for _, server := range servers { + listenAddresses = append(listenAddresses, server.ServerOpts.GenericServerRunOptions.AdvertiseAddress.String()) + } + return reflect.DeepEqual(listenAddresses, ips) +} + +func testReconcilersMasterLease(t *testing.T, leaseCount int, masterCount int) { + var leaseServers []*kubeapiservertesting.TestServer + var masterCountServers []*kubeapiservertesting.TestServer + etcd := framework.SharedEtcd() + + instanceOptions := &kubeapiservertesting.TestServerInstanceOptions{ + DisableStorageCleanup: true, + } + + // cleanup the registry storage + defer registry.CleanupStorage() + + // 1. start masterCount api servers + for i := 0; i < masterCount; i++ { + // start master count api server + server := kubeapiservertesting.StartTestServerOrDie(t, instanceOptions, []string{ + "--endpoint-reconciler-type", "master-count", + "--advertise-address", fmt.Sprintf("10.0.1.%v", i+1), + "--apiserver-count", fmt.Sprintf("%v", masterCount), + }, etcd) + masterCountServers = append(masterCountServers, server) + } + + // 2. verify master count servers have registered + if err := wait.PollImmediate(3*time.Second, 2*time.Minute, func() (bool, error) { + client, err := kubernetes.NewForConfig(masterCountServers[0].ClientConfig) + endpoints, err := client.CoreV1().Endpoints("default").Get("kubernetes", metav1.GetOptions{}) + if err != nil { + t.Logf("error fetching endpoints: %v", err) + return false, nil + } + return verifyEndpointsWithIPs(masterCountServers, getEndpointIPs(endpoints)), nil + }); err != nil { + t.Fatalf("master count endpoints failed to register: %v", err) + } + + // 3. start lease api servers + for i := 0; i < leaseCount; i++ { + options := []string{ + "--endpoint-reconciler-type", "lease", + "--advertise-address", fmt.Sprintf("10.0.1.%v", i+10), + } + server := kubeapiservertesting.StartTestServerOrDie(t, instanceOptions, options, etcd) + defer server.TearDownFn() + leaseServers = append(leaseServers, server) + } + + time.Sleep(3 * time.Second) + + // 4. Shutdown the masterCount server + for _, server := range masterCountServers { + server.TearDownFn() + } + + // 5. verify only leaseEndpoint servers left + if err := wait.PollImmediate(3*time.Second, 2*time.Minute, func() (bool, error) { + client, err := kubernetes.NewForConfig(leaseServers[0].ClientConfig) + if err != nil { + t.Logf("create client error: %v", err) + return false, nil + } + endpoints, err := client.CoreV1().Endpoints("default").Get("kubernetes", metav1.GetOptions{}) + if err != nil { + t.Logf("error fetching endpoints: %v", err) + return false, nil + } + return verifyEndpointsWithIPs(leaseServers, getEndpointIPs(endpoints)), nil + }); err != nil { + t.Fatalf("did not find only lease endpoints: %v", err) + } +} + +func TestReconcilerMasterLeaseCombined(t *testing.T) { + testReconcilersMasterLease(t, 1, 3) +} + +func TestReconcilerMasterLeaseMultiMoreMasters(t *testing.T) { + testReconcilersMasterLease(t, 3, 2) +} + +func TestReconcilerMasterLeaseMultiCombined(t *testing.T) { + testReconcilersMasterLease(t, 3, 3) +} diff --git a/vendor/k8s.io/kubernetes/test/integration/master/secrets_transformation_test.go b/vendor/k8s.io/kubernetes/test/integration/master/secrets_transformation_test.go index 34a790c77..a8d408435 100644 --- a/vendor/k8s.io/kubernetes/test/integration/master/secrets_transformation_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/master/secrets_transformation_test.go @@ -124,6 +124,7 @@ func runBenchmark(b *testing.B, transformerConfig string) { b.StartTimer() test.benchmark(b) b.StopTimer() + test.printMetrics() } func unSealWithGCMTransformer(cipherText []byte, ctx value.Context, diff --git a/vendor/k8s.io/kubernetes/test/integration/master/synthetic_master_test.go b/vendor/k8s.io/kubernetes/test/integration/master/synthetic_master_test.go index 90d5350d6..317e5df11 100644 --- a/vendor/k8s.io/kubernetes/test/integration/master/synthetic_master_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/master/synthetic_master_test.go @@ -24,6 +24,7 @@ import ( "net" "net/http" "os" + "strconv" "strings" "sync" "testing" @@ -31,7 +32,9 @@ import ( "github.com/ghodss/yaml" + appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" @@ -41,6 +44,7 @@ import ( "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizerfactory" "k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest" + clientsetv1 "k8s.io/client-go/kubernetes" clienttypedv1 "k8s.io/client-go/kubernetes/typed/core/v1" restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/pkg/api/testapi" @@ -225,6 +229,116 @@ func TestStatus(t *testing.T) { } } +func constructBody(val string, size int, field string, t *testing.T) *appsv1.Deployment { + var replicas int32 = 1 + deploymentObject := &appsv1.Deployment{ + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: appsv1.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "foo": "bar", + }, + }, + Strategy: appsv1.DeploymentStrategy{ + Type: appsv1.RollingUpdateDeploymentStrategyType, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{"foo": "bar"}, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "foo", + Image: "foo", + }, + }, + }, + }, + }, + } + + switch field { + case "labels": + labelsMap := map[string]string{} + for i := 0; i < size; i++ { + key := val + strconv.Itoa(i) + labelsMap[key] = val + } + deploymentObject.ObjectMeta.Labels = labelsMap + case "annotations": + annotationsMap := map[string]string{} + for i := 0; i < size; i++ { + key := val + strconv.Itoa(i) + annotationsMap[key] = val + } + deploymentObject.ObjectMeta.Annotations = annotationsMap + case "finalizers": + finalizerString := []string{} + for i := 0; i < size; i++ { + finalizerString = append(finalizerString, val) + } + deploymentObject.ObjectMeta.Finalizers = finalizerString + default: + t.Fatalf("Unexpected field: %s used for making large deployment object value", field) + } + + return deploymentObject +} + +func TestObjectSizeResponses(t *testing.T) { + _, s, closeFn := framework.RunAMaster(nil) + defer closeFn() + + client := clientsetv1.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[api.GroupName].GroupVersion()}}) + + const DeploymentMegabyteSize = 100000 + const DeploymentTwoMegabyteSize = 1000000 + + expectedMsgFor1MB := `etcdserver: request is too large` + expectedMsgFor2MB := `rpc error: code = ResourceExhausted desc = grpc: trying to send message larger than max` + expectedMsgForLargeAnnotation := `metadata.annotations: Too long: must have at most 262144 characters` + + deployment1 := constructBody("a", DeploymentMegabyteSize, "labels", t) // >1 MB file + deployment2 := constructBody("a", DeploymentTwoMegabyteSize, "labels", t) // >2 MB file + + deployment3 := constructBody("a", DeploymentMegabyteSize, "annotations", t) + + deployment4 := constructBody("sample/sample", DeploymentMegabyteSize, "finalizers", t) // >1 MB file + deployment5 := constructBody("sample/sample", DeploymentTwoMegabyteSize, "finalizers", t) // >2 MB file + + requests := []struct { + size string + deploymentObject *appsv1.Deployment + expectedMessage string + }{ + {"1 MB", deployment1, expectedMsgFor1MB}, + {"2 MB", deployment2, expectedMsgFor2MB}, + {"1 MB", deployment3, expectedMsgForLargeAnnotation}, + {"1 MB", deployment4, expectedMsgFor1MB}, + {"2 MB", deployment5, expectedMsgFor2MB}, + } + + for _, r := range requests { + t.Run(r.size, func(t *testing.T) { + _, err := client.AppsV1().Deployments(metav1.NamespaceDefault).Create(r.deploymentObject) + if err != nil { + if !strings.Contains(err.Error(), r.expectedMessage) { + t.Errorf("got: %s;want: %s", err.Error(), r.expectedMessage) + } + } + }) + } +} + func TestWatchSucceedsWithoutArgs(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() @@ -666,7 +780,7 @@ func TestUpdateNodeObjects(t *testing.T) { go func(lister int) { w, err := c.Nodes().Watch(metav1.ListOptions{}) if err != nil { - fmt.Printf("[watch:%d] error: %v", k, err) + fmt.Printf("[watch:%d] error: %v", lister, err) return } i := 0 diff --git a/vendor/k8s.io/kubernetes/test/integration/master/transformation_testcase.go b/vendor/k8s.io/kubernetes/test/integration/master/transformation_testcase.go index 48013bcf5..bfe3bc841 100644 --- a/vendor/k8s.io/kubernetes/test/integration/master/transformation_testcase.go +++ b/vendor/k8s.io/kubernetes/test/integration/master/transformation_testcase.go @@ -29,6 +29,7 @@ import ( "github.com/coreos/etcd/clientv3" "github.com/ghodss/yaml" + "github.com/prometheus/client_golang/prometheus" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -47,6 +48,7 @@ const ( encryptionConfigFileName = "encryption.conf" testNamespace = "secret-encryption-test" testSecret = "test-secret" + metricsPrefix = "apiserver_storage_" ) type unSealSecret func(cipherText []byte, ctx value.Context, config encryptionconfig.ProviderConfig) ([]byte, error) @@ -76,7 +78,7 @@ func newTransformTest(l kubeapiservertesting.Logger, transformerConfigYAML strin } } - if e.kubeAPIServer, err = kubeapiservertesting.StartTestServer(l, e.getEncryptionOptions(), e.storageConfig); err != nil { + if e.kubeAPIServer, err = kubeapiservertesting.StartTestServer(l, nil, e.getEncryptionOptions(), e.storageConfig); err != nil { return nil, fmt.Errorf("failed to start KubeAPI server: %v", err) } @@ -237,3 +239,31 @@ func (e *transformTest) readRawRecordFromETCD(path string) (*clientv3.GetRespons return response, nil } + +func (e *transformTest) printMetrics() error { + e.logger.Logf("Transformation Metrics:") + metrics, err := prometheus.DefaultGatherer.Gather() + if err != nil { + return fmt.Errorf("failed to gather metrics: %s", err) + } + + for _, mf := range metrics { + if strings.HasPrefix(*mf.Name, metricsPrefix) { + e.logger.Logf("%s", *mf.Name) + for _, metric := range mf.GetMetric() { + e.logger.Logf("%v", metric) + } + } + } + + return nil +} + +func contains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} diff --git a/vendor/k8s.io/kubernetes/test/integration/metrics/BUILD b/vendor/k8s.io/kubernetes/test/integration/metrics/BUILD index 3ec1cf5d1..1a99bd3f8 100644 --- a/vendor/k8s.io/kubernetes/test/integration/metrics/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/metrics/BUILD @@ -35,13 +35,12 @@ go_test( embed = [":go_default_library"], tags = ["integration"], deps = [ - "//pkg/api/testapi:go_default_library", "//test/integration/framework:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/protobuf/proto:go_default_library", "//vendor/github.com/prometheus/client_model/go:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/test/integration/metrics/metrics_test.go b/vendor/k8s.io/kubernetes/test/integration/metrics/metrics_test.go index 34f19657f..9b4391f5a 100644 --- a/vendor/k8s.io/kubernetes/test/integration/metrics/metrics_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/metrics/metrics_test.go @@ -24,11 +24,10 @@ import ( "runtime" "testing" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/integration/framework" "github.com/golang/glog" @@ -111,7 +110,7 @@ func TestApiserverMetrics(t *testing.T) { // Make a request to the apiserver to ensure there's at least one data point // for the metrics we're expecting -- otherwise, they won't be exported. - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) if _, err := client.Core().Pods(metav1.NamespaceDefault).List(metav1.ListOptions{}); err != nil { t.Fatalf("unexpected error getting pods: %v", err) } diff --git a/vendor/k8s.io/kubernetes/test/integration/objectmeta/BUILD b/vendor/k8s.io/kubernetes/test/integration/objectmeta/BUILD index c55e74cbd..47cda551b 100644 --- a/vendor/k8s.io/kubernetes/test/integration/objectmeta/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/objectmeta/BUILD @@ -14,11 +14,11 @@ go_test( ], tags = ["integration"], deps = [ - "//pkg/api/testapi:go_default_library", "//test/integration/framework:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/test/integration/objectmeta/objectmeta_test.go b/vendor/k8s.io/kubernetes/test/integration/objectmeta/objectmeta_test.go index 3ab41ec26..1da1ddaf5 100644 --- a/vendor/k8s.io/kubernetes/test/integration/objectmeta/objectmeta_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/objectmeta/objectmeta_test.go @@ -23,9 +23,9 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/integration/framework" ) @@ -34,7 +34,7 @@ func TestIgnoreClusterName(t *testing.T) { _, s, closeFn := framework.RunAMaster(config) defer closeFn() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) ns := v1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "test-namespace", diff --git a/vendor/k8s.io/kubernetes/test/integration/openshift/openshift_test.go b/vendor/k8s.io/kubernetes/test/integration/openshift/openshift_test.go index fa42915ae..2bbb7fd50 100644 --- a/vendor/k8s.io/kubernetes/test/integration/openshift/openshift_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/openshift/openshift_test.go @@ -31,8 +31,7 @@ func TestMasterExportsSymbols(t *testing.T) { EnableMetrics: true, }, ExtraConfig: master.ExtraConfig{ - EnableCoreControllers: false, - EnableLogsSupport: false, + EnableLogsSupport: false, }, } _ = &master.Master{ diff --git a/vendor/k8s.io/kubernetes/test/integration/pods/BUILD b/vendor/k8s.io/kubernetes/test/integration/pods/BUILD index 76f4dfd4c..b31b4c371 100644 --- a/vendor/k8s.io/kubernetes/test/integration/pods/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/pods/BUILD @@ -14,11 +14,11 @@ go_test( ], tags = ["integration"], deps = [ - "//pkg/api/testapi:go_default_library", "//test/integration:go_default_library", "//test/integration/framework:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/test/integration/pods/pods_test.go b/vendor/k8s.io/kubernetes/test/integration/pods/pods_test.go index 18135f0b5..8504fbf00 100644 --- a/vendor/k8s.io/kubernetes/test/integration/pods/pods_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/pods/pods_test.go @@ -22,9 +22,9 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/integration" "k8s.io/kubernetes/test/integration/framework" ) @@ -36,7 +36,7 @@ func TestPodUpdateActiveDeadlineSeconds(t *testing.T) { ns := framework.CreateTestingNamespace("pod-activedeadline-update", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) var ( iZero = int64(0) @@ -154,7 +154,7 @@ func TestPodReadOnlyFilesystem(t *testing.T) { ns := framework.CreateTestingNamespace("pod-readonly-root", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/vendor/k8s.io/kubernetes/test/integration/quota/BUILD b/vendor/k8s.io/kubernetes/test/integration/quota/BUILD index 70ee6bc4e..e3eed4530 100644 --- a/vendor/k8s.io/kubernetes/test/integration/quota/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/quota/BUILD @@ -14,7 +14,6 @@ go_test( ], tags = ["integration"], deps = [ - "//pkg/api/testapi:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library", "//pkg/controller:go_default_library", @@ -30,6 +29,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/quota/quota_test.go b/vendor/k8s.io/kubernetes/test/integration/quota/quota_test.go index cd2506171..4689a7dd6 100644 --- a/vendor/k8s.io/kubernetes/test/integration/quota/quota_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/quota/quota_test.go @@ -28,13 +28,13 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" internalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/controller" @@ -62,8 +62,8 @@ func TestQuota(t *testing.T) { })) admissionCh := make(chan struct{}) - clientset := clientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) - internalClientset := internalclientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) + internalClientset := internalclientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) config := &resourcequotaapi.Configuration{} admission, err := resourcequota.NewResourceQuota(config, 5, admissionCh) if err != nil { @@ -250,8 +250,8 @@ func TestQuotaLimitedResourceDenial(t *testing.T) { })) admissionCh := make(chan struct{}) - clientset := clientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) - internalClientset := internalclientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + clientset := clientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) + internalClientset := internalclientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) // stop creation of a pod resource unless there is a quota config := &resourcequotaapi.Configuration{ diff --git a/vendor/k8s.io/kubernetes/test/integration/replicaset/BUILD b/vendor/k8s.io/kubernetes/test/integration/replicaset/BUILD index c8f90765d..f2d5c6cf9 100644 --- a/vendor/k8s.io/kubernetes/test/integration/replicaset/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/replicaset/BUILD @@ -19,8 +19,8 @@ go_test( "//pkg/util/slice:go_default_library", "//test/integration/framework:go_default_library", "//test/utils:go_default_library", + "//vendor/k8s.io/api/apps/v1: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/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", @@ -28,8 +28,8 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/util/retry:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/replicaset/replicaset_test.go b/vendor/k8s.io/kubernetes/test/integration/replicaset/replicaset_test.go index b68ddebdd..ac4642f76 100644 --- a/vendor/k8s.io/kubernetes/test/integration/replicaset/replicaset_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/replicaset/replicaset_test.go @@ -24,8 +24,8 @@ import ( "testing" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -33,8 +33,8 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" + appsclient "k8s.io/client-go/kubernetes/typed/apps/v1" typedv1 "k8s.io/client-go/kubernetes/typed/core/v1" - typedv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/retry" @@ -54,18 +54,18 @@ func labelMap() map[string]string { return map[string]string{"foo": "bar"} } -func newRS(name, namespace string, replicas int) *v1beta1.ReplicaSet { +func newRS(name, namespace string, replicas int) *apps.ReplicaSet { replicasCopy := int32(replicas) - return &v1beta1.ReplicaSet{ + return &apps.ReplicaSet{ TypeMeta: metav1.TypeMeta{ Kind: "ReplicaSet", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", }, ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: name, }, - Spec: v1beta1.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: labelMap(), }, @@ -151,7 +151,7 @@ func rmSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *replicaset.R informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "rs-informers")), resyncPeriod) rm := replicaset.NewReplicaSetController( - informers.Extensions().V1beta1().ReplicaSets(), + informers.Apps().V1().ReplicaSets(), informers.Core().V1().Pods(), clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "replicaset-controller")), replicaset.BurstReplicas, @@ -196,11 +196,11 @@ func waitToObservePods(t *testing.T, podInformer cache.SharedIndexInformer, podN } } -func createRSsPods(t *testing.T, clientSet clientset.Interface, rss []*v1beta1.ReplicaSet, pods []*v1.Pod) ([]*v1beta1.ReplicaSet, []*v1.Pod) { - var createdRSs []*v1beta1.ReplicaSet +func createRSsPods(t *testing.T, clientSet clientset.Interface, rss []*apps.ReplicaSet, pods []*v1.Pod) ([]*apps.ReplicaSet, []*v1.Pod) { + var createdRSs []*apps.ReplicaSet var createdPods []*v1.Pod for _, rs := range rss { - createdRS, err := clientSet.ExtensionsV1beta1().ReplicaSets(rs.Namespace).Create(rs) + createdRS, err := clientSet.AppsV1().ReplicaSets(rs.Namespace).Create(rs) if err != nil { t.Fatalf("Failed to create replica set %s: %v", rs.Name, err) } @@ -218,16 +218,16 @@ func createRSsPods(t *testing.T, clientSet clientset.Interface, rss []*v1beta1.R } // Verify .Status.Replicas is equal to .Spec.Replicas -func waitRSStable(t *testing.T, clientSet clientset.Interface, rs *v1beta1.ReplicaSet) { +func waitRSStable(t *testing.T, clientSet clientset.Interface, rs *apps.ReplicaSet) { if err := testutil.WaitRSStable(t, clientSet, rs, interval, timeout); err != nil { t.Fatal(err) } } // Update .Spec.Replicas to replicas and verify .Status.Replicas is changed accordingly -func scaleRS(t *testing.T, c clientset.Interface, rs *v1beta1.ReplicaSet, replicas int32) { - rsClient := c.ExtensionsV1beta1().ReplicaSets(rs.Namespace) - rs = updateRS(t, rsClient, rs.Name, func(rs *v1beta1.ReplicaSet) { +func scaleRS(t *testing.T, c clientset.Interface, rs *apps.ReplicaSet, replicas int32) { + rsClient := c.AppsV1().ReplicaSets(rs.Namespace) + rs = updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) { *rs.Spec.Replicas = replicas }) waitRSStable(t, c, rs) @@ -273,8 +273,8 @@ func getPods(t *testing.T, podClient typedv1.PodInterface, labelMap map[string]s return pods } -func updateRS(t *testing.T, rsClient typedv1beta1.ReplicaSetInterface, rsName string, updateFunc func(*v1beta1.ReplicaSet)) *v1beta1.ReplicaSet { - var rs *v1beta1.ReplicaSet +func updateRS(t *testing.T, rsClient appsclient.ReplicaSetInterface, rsName string, updateFunc func(*apps.ReplicaSet)) *apps.ReplicaSet { + var rs *apps.ReplicaSet if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { newRS, err := rsClient.Get(rsName, metav1.GetOptions{}) if err != nil { @@ -290,7 +290,7 @@ func updateRS(t *testing.T, rsClient typedv1beta1.ReplicaSetInterface, rsName st } // Verify ControllerRef of a RS pod that has incorrect attributes is automatically patched by the RS -func testPodControllerRefPatch(t *testing.T, c clientset.Interface, pod *v1.Pod, ownerReference *metav1.OwnerReference, rs *v1beta1.ReplicaSet, expectedOwnerReferenceNum int) { +func testPodControllerRefPatch(t *testing.T, c clientset.Interface, pod *v1.Pod, ownerReference *metav1.OwnerReference, rs *apps.ReplicaSet, expectedOwnerReferenceNum int) { ns := rs.Namespace podClient := c.CoreV1().Pods(ns) updatePod(t, podClient, pod.Name, func(pod *v1.Pod) { @@ -359,7 +359,7 @@ func setPodsReadyCondition(t *testing.T, clientSet clientset.Interface, pods *v1 } } -func testScalingUsingScaleSubresource(t *testing.T, c clientset.Interface, rs *v1beta1.ReplicaSet, replicas int32) { +func testScalingUsingScaleSubresource(t *testing.T, c clientset.Interface, rs *apps.ReplicaSet, replicas int32) { ns := rs.Namespace rsClient := c.ExtensionsV1beta1().ReplicaSets(ns) newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{}) @@ -401,48 +401,48 @@ func TestAdoption(t *testing.T) { boolPtr := func(b bool) *bool { return &b } testCases := []struct { name string - existingOwnerReferences func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference - expectedOwnerReferences func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference + existingOwnerReferences func(rs *apps.ReplicaSet) []metav1.OwnerReference + expectedOwnerReferences func(rs *apps.ReplicaSet) []metav1.OwnerReference }{ { "pod refers rs as an owner, not a controller", - func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference { - return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "extensions/v1beta1", Kind: "ReplicaSet"}} + func(rs *apps.ReplicaSet) []metav1.OwnerReference { + return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet"}} }, - func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference { - return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "extensions/v1beta1", Kind: "ReplicaSet", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}} + func(rs *apps.ReplicaSet) []metav1.OwnerReference { + return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}} }, }, { "pod doesn't have owner references", - func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference { + func(rs *apps.ReplicaSet) []metav1.OwnerReference { return []metav1.OwnerReference{} }, - func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference { - return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "extensions/v1beta1", Kind: "ReplicaSet", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}} + func(rs *apps.ReplicaSet) []metav1.OwnerReference { + return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}} }, }, { "pod refers rs as a controller", - func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference { - return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "extensions/v1beta1", Kind: "ReplicaSet", Controller: boolPtr(true)}} + func(rs *apps.ReplicaSet) []metav1.OwnerReference { + return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)}} }, - func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference { - return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "extensions/v1beta1", Kind: "ReplicaSet", Controller: boolPtr(true)}} + func(rs *apps.ReplicaSet) []metav1.OwnerReference { + return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)}} }, }, { "pod refers other rs as the controller, refers the rs as an owner", - func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference { + func(rs *apps.ReplicaSet) []metav1.OwnerReference { return []metav1.OwnerReference{ - {UID: "1", Name: "anotherRS", APIVersion: "extensions/v1beta1", Kind: "ReplicaSet", Controller: boolPtr(true)}, - {UID: rs.UID, Name: rs.Name, APIVersion: "extensions/v1beta1", Kind: "ReplicaSet"}, + {UID: "1", Name: "anotherRS", APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)}, + {UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet"}, } }, - func(rs *v1beta1.ReplicaSet) []metav1.OwnerReference { + func(rs *apps.ReplicaSet) []metav1.OwnerReference { return []metav1.OwnerReference{ - {UID: "1", Name: "anotherRS", APIVersion: "extensions/v1beta1", Kind: "ReplicaSet", Controller: boolPtr(true)}, - {UID: rs.UID, Name: rs.Name, APIVersion: "extensions/v1beta1", Kind: "ReplicaSet"}, + {UID: "1", Name: "anotherRS", APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)}, + {UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet"}, } }, }, @@ -454,7 +454,7 @@ func TestAdoption(t *testing.T) { ns := framework.CreateTestingNamespace(fmt.Sprintf("rs-adoption-%d", i), s, t) defer framework.DeleteTestingNamespace(ns, s, t) - rsClient := clientSet.ExtensionsV1beta1().ReplicaSets(ns.Name) + rsClient := clientSet.AppsV1().ReplicaSets(ns.Name) podClient := clientSet.CoreV1().Pods(ns.Name) const rsName = "rs" rs, err := rsClient.Create(newRS(rsName, ns.Name, 1)) @@ -496,13 +496,17 @@ func TestRSSelectorImmutability(t *testing.T) { ns := framework.CreateTestingNamespace("rs-selector-immutability", s, t) defer framework.DeleteTestingNamespace(ns, s, t) rs := newRS("rs", ns.Name, 0) - createRSsPods(t, clientSet, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + createRSsPods(t, clientSet, []*apps.ReplicaSet{rs}, []*v1.Pod{}) // test to ensure extensions/v1beta1 selector is mutable newSelectorLabels := map[string]string{"changed_name_extensions_v1beta1": "changed_test_extensions_v1beta1"} - rs.Spec.Selector.MatchLabels = newSelectorLabels - rs.Spec.Template.Labels = newSelectorLabels - replicaset, err := clientSet.ExtensionsV1beta1().ReplicaSets(ns.Name).Update(rs) + rsExt, err := clientSet.ExtensionsV1beta1().ReplicaSets(ns.Name).Get(rs.Name, metav1.GetOptions{}) + if err != nil { + t.Fatalf("failed to get extensions/v1beta replicaset %s: %v", rs.Name, err) + } + rsExt.Spec.Selector.MatchLabels = newSelectorLabels + rsExt.Spec.Template.Labels = newSelectorLabels + replicaset, err := clientSet.ExtensionsV1beta1().ReplicaSets(ns.Name).Update(rsExt) if err != nil { t.Fatalf("failed to update extensions/v1beta1 replicaset %s: %v", replicaset.Name, err) } @@ -510,17 +514,17 @@ func TestRSSelectorImmutability(t *testing.T) { t.Errorf("selector should be changed for extensions/v1beta1, expected: %v, got: %v", newSelectorLabels, replicaset.Spec.Selector.MatchLabels) } - // test to ensure apps/v1beta2 selector is immutable - rsV1beta2, err := clientSet.AppsV1beta2().ReplicaSets(ns.Name).Get(replicaset.Name, metav1.GetOptions{}) + // test to ensure apps/v1 selector is immutable + rsV1, err := clientSet.AppsV1().ReplicaSets(ns.Name).Get(rs.Name, metav1.GetOptions{}) if err != nil { - t.Fatalf("failed to get apps/v1beta2 replicaset %s: %v", replicaset.Name, err) + t.Fatalf("failed to get apps/v1 replicaset %s: %v", rs.Name, err) } - newSelectorLabels = map[string]string{"changed_name_apps_v1beta2": "changed_test_apps_v1beta2"} - rsV1beta2.Spec.Selector.MatchLabels = newSelectorLabels - rsV1beta2.Spec.Template.Labels = newSelectorLabels - _, err = clientSet.AppsV1beta2().ReplicaSets(ns.Name).Update(rsV1beta2) + newSelectorLabels = map[string]string{"changed_name_apps_v1": "changed_test_apps_v1"} + rsV1.Spec.Selector.MatchLabels = newSelectorLabels + rsV1.Spec.Template.Labels = newSelectorLabels + _, err = clientSet.AppsV1().ReplicaSets(ns.Name).Update(rsV1) if err == nil { - t.Fatalf("failed to provide validation error when changing immutable selector when updating apps/v1beta2 replicaset %s", rsV1beta2.Name) + t.Fatalf("failed to provide validation error when changing immutable selector when updating apps/v1 replicaset %s", rsV1.Name) } expectedErrType := "Invalid value" expectedErrDetail := "field is immutable" @@ -538,7 +542,7 @@ func TestSpecReplicasChange(t *testing.T) { defer close(stopCh) rs := newRS("rs", ns.Name, 2) - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) rs = rss[0] waitRSStable(t, c, rs) @@ -549,9 +553,9 @@ func TestSpecReplicasChange(t *testing.T) { // Add a template annotation change to test RS's status does update // without .Spec.Replicas change - rsClient := c.ExtensionsV1beta1().ReplicaSets(ns.Name) + rsClient := c.AppsV1().ReplicaSets(ns.Name) var oldGeneration int64 - newRS := updateRS(t, rsClient, rs.Name, func(rs *v1beta1.ReplicaSet) { + newRS := updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) { oldGeneration = rs.Generation rs.Spec.Template.Annotations = map[string]string{"test": "annotation"} }) @@ -580,7 +584,7 @@ func TestDeletingAndFailedPods(t *testing.T) { defer close(stopCh) rs := newRS("rs", ns.Name, 2) - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) rs = rss[0] waitRSStable(t, c, rs) @@ -648,7 +652,7 @@ func TestOverlappingRSs(t *testing.T) { for i := 0; i < 2; i++ { // One RS has 1 replica, and another has 2 replicas rs := newRS(fmt.Sprintf("rs-%d", i+1), ns.Name, i+1) - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) waitRSStable(t, c, rss[0]) } @@ -680,7 +684,7 @@ func TestPodOrphaningAndAdoptionWhenLabelsChange(t *testing.T) { defer close(stopCh) rs := newRS("rs", ns.Name, 1) - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) rs = rss[0] waitRSStable(t, c, rs) @@ -757,7 +761,7 @@ func TestGeneralPodAdoption(t *testing.T) { defer close(stopCh) rs := newRS("rs", ns.Name, 1) - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) rs = rss[0] waitRSStable(t, c, rs) @@ -772,11 +776,11 @@ func TestGeneralPodAdoption(t *testing.T) { // When the only OwnerReference of the pod points to another type of API object such as statefulset // with Controller=false, the RS should add a second OwnerReference (ControllerRef) pointing to itself // with Controller=true - ownerReference := metav1.OwnerReference{UID: uuid.NewUUID(), APIVersion: "apps/v1beta1", Kind: "StatefulSet", Name: rs.Name, Controller: &falseVar} + ownerReference := metav1.OwnerReference{UID: uuid.NewUUID(), APIVersion: "apps/v1", Kind: "StatefulSet", Name: rs.Name, Controller: &falseVar} testPodControllerRefPatch(t, c, pod, &ownerReference, rs, 2) // When the only OwnerReference of the pod points to the RS, but Controller=false - ownerReference = metav1.OwnerReference{UID: rs.UID, APIVersion: "extensions/v1beta1", Kind: "ReplicaSet", Name: rs.Name, Controller: &falseVar} + ownerReference = metav1.OwnerReference{UID: rs.UID, APIVersion: "apps/v1", Kind: "ReplicaSet", Name: rs.Name, Controller: &falseVar} testPodControllerRefPatch(t, c, pod, &ownerReference, rs, 1) } @@ -790,7 +794,7 @@ func TestReadyAndAvailableReplicas(t *testing.T) { rs := newRS("rs", ns.Name, 3) rs.Spec.MinReadySeconds = 3600 - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) rs = rss[0] waitRSStable(t, c, rs) @@ -841,7 +845,7 @@ func TestRSScaleSubresource(t *testing.T) { defer close(stopCh) rs := newRS("rs", ns.Name, 1) - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) rs = rss[0] waitRSStable(t, c, rs) @@ -865,7 +869,7 @@ func TestExtraPodsAdoptionAndDeletion(t *testing.T) { pod.Labels = labelMap() podList = append(podList, pod) } - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, podList) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, podList) rs = rss[0] stopCh := runControllerAndInformers(t, rm, informers, 3) defer close(stopCh) @@ -893,13 +897,13 @@ func TestFullyLabeledReplicas(t *testing.T) { extraLabelMap := map[string]string{"foo": "bar", "extraKey": "extraValue"} rs := newRS("rs", ns.Name, 2) - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) rs = rss[0] waitRSStable(t, c, rs) // Change RS's template labels to have extra labels, but not its selector - rsClient := c.ExtensionsV1beta1().ReplicaSets(ns.Name) - updateRS(t, rsClient, rs.Name, func(rs *v1beta1.ReplicaSet) { + rsClient := c.AppsV1().ReplicaSets(ns.Name) + updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) { rs.Spec.Template.Labels = extraLabelMap }) @@ -937,7 +941,7 @@ func TestReplicaSetsExtensionsV1beta1DefaultGCPolicy(t *testing.T) { rs := newRS("rs", ns.Name, 2) fakeFinalizer := "kube.io/dummy-finalizer" rs.Finalizers = []string{fakeFinalizer} - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) rs = rss[0] waitRSStable(t, c, rs) @@ -948,13 +952,14 @@ func TestReplicaSetsExtensionsV1beta1DefaultGCPolicy(t *testing.T) { t.Fatalf("len(pods) = %d, want 2", len(pods.Items)) } - rsClient := c.ExtensionsV1beta1().ReplicaSets(ns.Name) - err := rsClient.Delete(rs.Name, nil) + // Delete via the extensions/v1beta1 endpoint. + err := c.ExtensionsV1beta1().ReplicaSets(ns.Name).Delete(rs.Name, nil) if err != nil { t.Fatalf("Failed to delete rs: %v", err) } // Verify orphan finalizer has been added + rsClient := c.AppsV1().ReplicaSets(ns.Name) if err := wait.PollImmediate(interval, timeout, func() (bool, error) { newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{}) if err != nil { @@ -965,7 +970,7 @@ func TestReplicaSetsExtensionsV1beta1DefaultGCPolicy(t *testing.T) { t.Fatalf("Failed to verify orphan finalizer is added: %v", err) } - updateRS(t, rsClient, rs.Name, func(rs *v1beta1.ReplicaSet) { + updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) { var finalizers []string // remove fakeFinalizer for _, finalizer := range rs.Finalizers { @@ -982,7 +987,7 @@ func TestReplicaSetsExtensionsV1beta1DefaultGCPolicy(t *testing.T) { func TestReplicaSetsAppsV1DefaultGCPolicy(t *testing.T) { s, closeFn, rm, informers, c := rmSetup(t) defer closeFn() - ns := framework.CreateTestingNamespace("test-default-gc-extensions", s, t) + ns := framework.CreateTestingNamespace("test-default-gc-v1", s, t) defer framework.DeleteTestingNamespace(ns, s, t) stopCh := runControllerAndInformers(t, rm, informers, 0) defer close(stopCh) @@ -990,7 +995,7 @@ func TestReplicaSetsAppsV1DefaultGCPolicy(t *testing.T) { rs := newRS("rs", ns.Name, 2) fakeFinalizer := "kube.io/dummy-finalizer" rs.Finalizers = []string{fakeFinalizer} - rss, _ := createRSsPods(t, c, []*v1beta1.ReplicaSet{rs}, []*v1.Pod{}) + rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{}) rs = rss[0] waitRSStable(t, c, rs) @@ -1024,7 +1029,7 @@ func TestReplicaSetsAppsV1DefaultGCPolicy(t *testing.T) { t.Fatalf("Failed to verify the finalizer: %v", err) } - updateRS(t, c.ExtensionsV1beta1().ReplicaSets(ns.Name), rs.Name, func(rs *v1beta1.ReplicaSet) { + updateRS(t, c.AppsV1().ReplicaSets(ns.Name), rs.Name, func(rs *apps.ReplicaSet) { var finalizers []string // remove fakeFinalizer for _, finalizer := range rs.Finalizers { diff --git a/vendor/k8s.io/kubernetes/test/integration/scale/scale_test.go b/vendor/k8s.io/kubernetes/test/integration/scale/scale_test.go index fe92420ec..6c4db98a3 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scale/scale_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/scale/scale_test.go @@ -215,7 +215,7 @@ var ( ) func setup(t *testing.T) (client kubernetes.Interface, tearDown func()) { - result := apitesting.StartTestServerOrDie(t, nil, framework.SharedEtcd()) + result := apitesting.StartTestServerOrDie(t, nil, nil, framework.SharedEtcd()) // TODO: Disable logging here until we resolve teardown issues which result in // massive log spam. Another path forward would be to refactor diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler/BUILD b/vendor/k8s.io/kubernetes/test/integration/scheduler/BUILD index 1906eaebd..3d669eb66 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler/BUILD @@ -23,8 +23,8 @@ go_test( tags = ["integration"], deps = [ "//cmd/kube-scheduler/app:go_default_library", + "//cmd/kube-scheduler/app/config:go_default_library", "//pkg/api/legacyscheme:go_default_library", - "//pkg/api/testapi:go_default_library", "//pkg/apis/componentconfig:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library", @@ -36,13 +36,13 @@ go_test( "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithmprovider:go_default_library", "//pkg/scheduler/api:go_default_library", + "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/factory:go_default_library", - "//pkg/scheduler/schedulercache:go_default_library", "//plugin/pkg/admission/podtolerationrestriction:go_default_library", "//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library", - "//test/e2e/framework:go_default_library", "//test/integration/framework:go_default_library", "//test/utils:go_default_library", + "//test/utils/image:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", @@ -51,8 +51,11 @@ go_test( "//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/labels:go_default_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/diff: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/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", @@ -86,17 +89,29 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/api/v1/pod:go_default_library", + "//pkg/controller:go_default_library", + "//pkg/controller/disruption:go_default_library", + "//pkg/features:go_default_library", "//pkg/scheduler:go_default_library", "//pkg/scheduler/algorithmprovider:go_default_library", + "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/factory:go_default_library", "//test/integration/framework:go_default_library", + "//test/utils/image:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/policy/v1beta1:go_default_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/labels:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/informers/core/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes: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", diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler/extender_test.go b/vendor/k8s.io/kubernetes/test/integration/scheduler/extender_test.go index 38369f960..aa6fad564 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler/extender_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler/extender_test.go @@ -31,19 +31,10 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" - v1core "k8s.io/client-go/kubernetes/typed/core/v1" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/scheduler" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/factory" - e2e "k8s.io/kubernetes/test/e2e/framework" - "k8s.io/kubernetes/test/integration/framework" + imageutils "k8s.io/kubernetes/test/utils/image" ) const ( @@ -130,7 +121,7 @@ func (e *Extender) filterUsingNodeCache(args *schedulerapi.ExtenderArgs) (*sched for _, nodeName := range *args.NodeNames { fits := true for _, predicate := range e.predicates { - fit, err := predicate(&args.Pod, + fit, err := predicate(args.Pod, &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: nodeName}}) if err != nil { return &schedulerapi.ExtenderFilterResult{ @@ -169,7 +160,7 @@ func (e *Extender) Filter(args *schedulerapi.ExtenderArgs) (*schedulerapi.Extend for _, node := range args.Nodes.Items { fits := true for _, predicate := range e.predicates { - fit, err := predicate(&args.Pod, &node) + fit, err := predicate(args.Pod, &node) if err != nil { return &schedulerapi.ExtenderFilterResult{ Nodes: &v1.NodeList{}, @@ -217,7 +208,7 @@ func (e *Extender) Prioritize(args *schedulerapi.ExtenderArgs) (*schedulerapi.Ho continue } priorityFunc := prioritizer.function - prioritizedList, err := priorityFunc(&args.Pod, nodes) + prioritizedList, err := priorityFunc(args.Pod, nodes) if err != nil { return &schedulerapi.HostPriorityList{}, err } @@ -288,13 +279,8 @@ func machine_3_Prioritizer(pod *v1.Pod, nodes *v1.NodeList) (*schedulerapi.HostP } func TestSchedulerExtender(t *testing.T) { - _, s, closeFn := framework.RunAMaster(nil) - defer closeFn() - - ns := framework.CreateTestingNamespace("scheduler-extender", s, t) - defer framework.DeleteTestingNamespace(ns, s, t) - - clientSet := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + context := initTestMaster(t, "scheduler-extender", nil) + clientSet := context.clientSet extender1 := &Extender{ name: "extender1", @@ -361,39 +347,12 @@ func TestSchedulerExtender(t *testing.T) { }, }, } - policy.APIVersion = testapi.Groups[v1.GroupName].GroupVersion().String() - - informerFactory := informers.NewSharedInformerFactory(clientSet, 0) - schedulerConfigFactory := factory.NewConfigFactory( - v1.DefaultSchedulerName, - clientSet, - informerFactory.Core().V1().Nodes(), - informerFactory.Core().V1().Pods(), - informerFactory.Core().V1().PersistentVolumes(), - informerFactory.Core().V1().PersistentVolumeClaims(), - informerFactory.Core().V1().ReplicationControllers(), - informerFactory.Extensions().V1beta1().ReplicaSets(), - informerFactory.Apps().V1beta1().StatefulSets(), - informerFactory.Core().V1().Services(), - informerFactory.Policy().V1beta1().PodDisruptionBudgets(), - informerFactory.Storage().V1().StorageClasses(), - v1.DefaultHardPodAffinitySymmetricWeight, - enableEquivalenceCache, - ) - schedulerConfig, err := schedulerConfigFactory.CreateFromConfig(policy) - if err != nil { - t.Fatalf("Couldn't create scheduler config: %v", err) - } - eventBroadcaster := record.NewBroadcaster() - schedulerConfig.Recorder = eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: v1.DefaultSchedulerName}) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(clientSet.CoreV1().RESTClient()).Events("")}) - scheduler, _ := scheduler.NewFromConfigurator(&scheduler.FakeConfigurator{Config: schedulerConfig}, nil...) - informerFactory.Start(schedulerConfig.StopEverything) - scheduler.Run() + policy.APIVersion = "v1" - defer close(schedulerConfig.StopEverything) + context = initTestScheduler(t, context, nil, false, &policy) + defer cleanupTest(t, context) - DoTestPodScheduling(ns, t, clientSet) + DoTestPodScheduling(context.ns, t, clientSet) } func DoTestPodScheduling(ns *v1.Namespace, t *testing.T, cs clientset.Interface) { @@ -430,7 +389,7 @@ func DoTestPodScheduling(ns *v1.Namespace, t *testing.T, cs clientset.Interface) Containers: []v1.Container{ { Name: "container", - Image: e2e.GetPauseImageName(cs), + Image: imageutils.GetPauseImageName(), Resources: v1.ResourceRequirements{ Limits: v1.ResourceList{ extendedResourceName: *resource.NewQuantity(1, resource.DecimalSI), diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler/predicates_test.go b/vendor/k8s.io/kubernetes/test/integration/scheduler/predicates_test.go index 711d506d1..16a9890ee 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler/predicates_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler/predicates_test.go @@ -24,8 +24,8 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/kubernetes/test/integration/framework" testutils "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" ) // This file tests the scheduler predicates functionality. @@ -75,7 +75,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel2, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -108,7 +108,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel2, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -140,7 +140,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel2, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -167,7 +167,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name, }, }, @@ -183,7 +183,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel2, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -205,7 +205,7 @@ func TestInterPodAffinity(t *testing.T) { }, }, pods: []*v1.Pod{{Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name}, ObjectMeta: metav1.ObjectMeta{ Name: "fakename2", @@ -221,7 +221,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel2, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -244,7 +244,7 @@ func TestInterPodAffinity(t *testing.T) { }, }, pods: []*v1.Pod{{Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name}, ObjectMeta: metav1.ObjectMeta{ Name: "fakename2", @@ -260,7 +260,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -282,7 +282,7 @@ func TestInterPodAffinity(t *testing.T) { }, }, pods: []*v1.Pod{{Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name}, ObjectMeta: metav1.ObjectMeta{ Name: "fakename2", Labels: podLabel}}}, @@ -297,7 +297,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel2, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -336,7 +336,7 @@ func TestInterPodAffinity(t *testing.T) { }, }, pods: []*v1.Pod{{Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name}, ObjectMeta: metav1.ObjectMeta{ Name: "fakename2", Labels: podLabel}}}, @@ -351,7 +351,7 @@ func TestInterPodAffinity(t *testing.T) { Name: "fakename", }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -390,7 +390,7 @@ func TestInterPodAffinity(t *testing.T) { }, }, pods: []*v1.Pod{{Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name}, ObjectMeta: metav1.ObjectMeta{ Name: "fakename2", Labels: podLabel}}}, @@ -405,7 +405,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel2, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -443,7 +443,7 @@ func TestInterPodAffinity(t *testing.T) { }, }, pods: []*v1.Pod{{Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name}, ObjectMeta: metav1.ObjectMeta{ Name: "fakename2", Labels: podLabel}}}, @@ -458,7 +458,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel2, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -498,7 +498,7 @@ func TestInterPodAffinity(t *testing.T) { pods: []*v1.Pod{ { Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name, Affinity: &v1.Affinity{ PodAntiAffinity: &v1.PodAntiAffinity{ @@ -535,7 +535,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel2, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -573,7 +573,7 @@ func TestInterPodAffinity(t *testing.T) { }, }, pods: []*v1.Pod{{Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name}, ObjectMeta: metav1.ObjectMeta{ Name: "fakename2", Labels: podLabel}}}, @@ -588,7 +588,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -629,7 +629,7 @@ func TestInterPodAffinity(t *testing.T) { { Spec: v1.PodSpec{ NodeName: nodes[0].Name, - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAntiAffinity: &v1.PodAntiAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -665,7 +665,7 @@ func TestInterPodAffinity(t *testing.T) { Labels: podLabel, }, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -687,7 +687,7 @@ func TestInterPodAffinity(t *testing.T) { }, }, pods: []*v1.Pod{{Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{ Name: "fakename2", Labels: podLabel}}}, @@ -701,12 +701,12 @@ func TestInterPodAffinity(t *testing.T) { Name: "fakename", Labels: podLabel, }, - Spec: v1.PodSpec{Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}}, + Spec: v1.PodSpec{Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}}, }, pods: []*v1.Pod{ { Spec: v1.PodSpec{NodeName: nodes[0].Name, - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAntiAffinity: &v1.PodAntiAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -741,12 +741,12 @@ func TestInterPodAffinity(t *testing.T) { Name: "fake-name", Labels: podLabel, }, - Spec: v1.PodSpec{Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}}, + Spec: v1.PodSpec{Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}}, }, pods: []*v1.Pod{ { Spec: v1.PodSpec{NodeName: nodes[0].Name, - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, Affinity: &v1.Affinity{ PodAntiAffinity: &v1.PodAntiAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ @@ -779,7 +779,7 @@ func TestInterPodAffinity(t *testing.T) { pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "fake-name2"}, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeSelector: map[string]string{"region": "r1"}, Affinity: &v1.Affinity{ PodAntiAffinity: &v1.PodAntiAffinity{ @@ -803,7 +803,7 @@ func TestInterPodAffinity(t *testing.T) { }, pods: []*v1.Pod{ {Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: framework.GetPauseImageName(cs)}}, + Containers: []v1.Container{{Name: "container", Image: imageutils.GetPauseImageName()}}, NodeName: nodes[0].Name}, ObjectMeta: metav1.ObjectMeta{Name: "fakename", Labels: map[string]string{"foo": "abc"}}}, }, fits: false, @@ -870,3 +870,53 @@ func TestInterPodAffinity(t *testing.T) { } } } + +// TestNodePIDPressure verifies that scheduler's CheckNodePIDPressurePredicate predicate +// functions works correctly. +func TestNodePIDPressure(t *testing.T) { + context := initTest(t, "node-pid-pressure") + defer cleanupTest(t, context) + // Add a node. + node, err := createNode(context.clientSet, "testnode", nil) + if err != nil { + t.Fatalf("Cannot create node: %v", err) + } + + cs := context.clientSet + + // Adds PID pressure condition to the node. + node.Status.Conditions = []v1.NodeCondition{ + { + Type: v1.NodePIDPressure, + Status: v1.ConditionTrue, + }, + } + + // Update node condition. + err = updateNodeStatus(context.clientSet, node) + if err != nil { + t.Fatalf("Cannot update node: %v", err) + } + + // Creats test pod. + testPod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "pidpressure-fake-name"}, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + {Name: "container", Image: imageutils.GetPauseImageName()}, + }, + }, + } + + testPod, err = cs.CoreV1().Pods(context.ns.Name).Create(testPod) + if err != nil { + t.Fatalf("Test Failed: error: %v, while creating pod", err) + } + + err = waitForPodUnschedulable(cs, testPod) + if err != nil { + t.Errorf("Test Failed: error, %v, while waiting for scheduled", err) + } + + cleanupPods(cs, t, []*v1.Pod{testPod}) +} diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler/preemption_test.go b/vendor/k8s.io/kubernetes/test/integration/scheduler/preemption_test.go index 45ee3697d..d5832a0bd 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler/preemption_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler/preemption_test.go @@ -27,7 +27,7 @@ import ( policy "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -41,8 +41,8 @@ import ( var lowPriority, mediumPriority, highPriority = int32(100), int32(200), int32(300) -func waitForNominatedNodeName(cs clientset.Interface, pod *v1.Pod) error { - if err := wait.Poll(100*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { +func waitForNominatedNodeNameWithTimeout(cs clientset.Interface, pod *v1.Pod, timeout time.Duration) error { + if err := wait.Poll(100*time.Millisecond, timeout, func() (bool, error) { pod, err := cs.CoreV1().Pods(pod.Namespace).Get(pod.Name, metav1.GetOptions{}) if err != nil { return false, err @@ -57,6 +57,10 @@ func waitForNominatedNodeName(cs clientset.Interface, pod *v1.Pod) error { return nil } +func waitForNominatedNodeName(cs clientset.Interface, pod *v1.Pod) error { + return waitForNominatedNodeNameWithTimeout(cs, pod, wait.ForeverTestTimeout) +} + // TestPreemption tests a few preemption scenarios. func TestPreemption(t *testing.T) { // Enable PodPriority feature gate. @@ -285,6 +289,88 @@ func TestPreemption(t *testing.T) { } } +// TestDisablePreemption tests disable pod preemption of scheduler works as expected. +func TestDisablePreemption(t *testing.T) { + // Enable PodPriority feature gate. + utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.PodPriority)) + // Initialize scheduler, and disable preemption. + context := initTestDisablePreemption(t, "disable-preemption") + defer cleanupTest(t, context) + cs := context.clientSet + + tests := []struct { + description string + existingPods []*v1.Pod + pod *v1.Pod + }{ + { + description: "pod preemption will not happen", + existingPods: []*v1.Pod{ + initPausePod(context.clientSet, &pausePodConfig{ + Name: "victim-pod", + Namespace: context.ns.Name, + Priority: &lowPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(400, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + }, + }), + }, + pod: initPausePod(cs, &pausePodConfig{ + Name: "preemptor-pod", + Namespace: context.ns.Name, + Priority: &highPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + }, + }), + }, + } + + // Create a node with some resources and a label. + nodeRes := &v1.ResourceList{ + v1.ResourcePods: *resource.NewQuantity(32, resource.DecimalSI), + v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(500, resource.BinarySI), + } + _, err := createNode(context.clientSet, "node1", nodeRes) + if err != nil { + t.Fatalf("Error creating nodes: %v", err) + } + + for _, test := range tests { + pods := make([]*v1.Pod, len(test.existingPods)) + // Create and run existingPods. + for i, p := range test.existingPods { + pods[i], err = runPausePod(cs, p) + if err != nil { + t.Fatalf("Test [%v]: Error running pause pod: %v", test.description, err) + } + } + // Create the "pod". + preemptor, err := createPausePod(cs, test.pod) + if err != nil { + t.Errorf("Error while creating high priority pod: %v", err) + } + // Ensure preemptor should keep unschedulable. + if err := waitForPodUnschedulable(cs, preemptor); err != nil { + t.Errorf("Test [%v]: Preemptor %v should not become scheduled", + test.description, preemptor.Name) + } + + // Ensure preemptor should not be nominated. + if err := waitForNominatedNodeNameWithTimeout(cs, preemptor, 5*time.Second); err == nil { + t.Errorf("Test [%v]: Preemptor %v should not be nominated", + test.description, preemptor.Name) + } + + // Cleanup + pods = append(pods, preemptor) + cleanupPods(cs, t, pods) + } +} + func mkPriorityPodWithGrace(tc *TestContext, name string, priority int32, grace int64) *v1.Pod { defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), @@ -419,7 +505,11 @@ func TestNominatedNodeCleanUp(t *testing.T) { // Initialize scheduler. context := initTest(t, "preemption") defer cleanupTest(t, context) + cs := context.clientSet + + defer cleanupPodsInNamespace(cs, t, context.ns.Name) + // Create a node with some resources and a label. nodeRes := &v1.ResourceList{ v1.ResourcePods: *resource.NewQuantity(32, resource.DecimalSI), @@ -496,7 +586,7 @@ func TestNominatedNodeCleanUp(t *testing.T) { } } -func mkMinAvailablePDB(name, namespace string, minAvailable int, matchLabels map[string]string) *policy.PodDisruptionBudget { +func mkMinAvailablePDB(name, namespace string, uid types.UID, minAvailable int, matchLabels map[string]string) *policy.PodDisruptionBudget { intMinAvailable := intstr.FromInt(minAvailable) return &policy.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ @@ -510,6 +600,18 @@ func mkMinAvailablePDB(name, namespace string, minAvailable int, matchLabels map } } +func addPodConditionReady(pod *v1.Pod) { + pod.Status = v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + }, + } +} + // TestPDBInPreemption tests PodDisruptionBudget support in preemption. func TestPDBInPreemption(t *testing.T) { // Enable PodPriority feature gate. @@ -519,6 +621,8 @@ func TestPDBInPreemption(t *testing.T) { defer cleanupTest(t, context) cs := context.clientSet + initDisruptionController(context) + defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(100, resource.BinarySI)}, @@ -538,6 +642,7 @@ func TestPDBInPreemption(t *testing.T) { description string nodes []*nodeConfig pdbs []*policy.PodDisruptionBudget + pdbPodNum []int32 existingPods []*v1.Pod pod *v1.Pod preemptedPodIndexes map[int]struct{} @@ -546,8 +651,9 @@ func TestPDBInPreemption(t *testing.T) { description: "A non-PDB violating pod is preempted despite its higher priority", nodes: []*nodeConfig{{name: "node-1", res: defaultNodeRes}}, pdbs: []*policy.PodDisruptionBudget{ - mkMinAvailablePDB("pdb-1", context.ns.Name, 2, map[string]string{"foo": "bar"}), + mkMinAvailablePDB("pdb-1", context.ns.Name, types.UID("pdb-1-uid"), 2, map[string]string{"foo": "bar"}), }, + pdbPodNum: []int32{2}, existingPods: []*v1.Pod{ initPausePod(context.clientSet, &pausePodConfig{ Name: "low-pod1", @@ -588,8 +694,9 @@ func TestPDBInPreemption(t *testing.T) { {name: "node-2", res: defaultNodeRes}, }, pdbs: []*policy.PodDisruptionBudget{ - mkMinAvailablePDB("pdb-1", context.ns.Name, 2, map[string]string{"foo": "bar"}), + mkMinAvailablePDB("pdb-1", context.ns.Name, types.UID("pdb-1-uid"), 2, map[string]string{"foo": "bar"}), }, + pdbPodNum: []int32{1}, existingPods: []*v1.Pod{ initPausePod(context.clientSet, &pausePodConfig{ Name: "low-pod1", @@ -626,9 +733,10 @@ func TestPDBInPreemption(t *testing.T) { {name: "node-3", res: defaultNodeRes}, }, pdbs: []*policy.PodDisruptionBudget{ - mkMinAvailablePDB("pdb-1", context.ns.Name, 2, map[string]string{"foo1": "bar"}), - mkMinAvailablePDB("pdb-2", context.ns.Name, 2, map[string]string{"foo2": "bar"}), + mkMinAvailablePDB("pdb-1", context.ns.Name, types.UID("pdb-1-uid"), 2, map[string]string{"foo1": "bar"}), + mkMinAvailablePDB("pdb-2", context.ns.Name, types.UID("pdb-2-uid"), 2, map[string]string{"foo2": "bar"}), }, + pdbPodNum: []int32{1, 5}, existingPods: []*v1.Pod{ initPausePod(context.clientSet, &pausePodConfig{ Name: "low-pod1", @@ -692,38 +800,22 @@ func TestPDBInPreemption(t *testing.T) { Priority: &highPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(400, resource.BinarySI)}, }, }), - preemptedPodIndexes: map[int]struct{}{0: {}, 1: {}}, + // The third node is chosen because PDB is not violated for node 3 and the victims have lower priority than node-2. + preemptedPodIndexes: map[int]struct{}{4: {}, 5: {}, 6: {}}, }, } for _, test := range tests { + t.Logf("================ Running test: %v\n", test.description) for _, nodeConf := range test.nodes { _, err := createNode(cs, nodeConf.name, nodeConf.res) if err != nil { t.Fatalf("Error creating node %v: %v", nodeConf.name, err) } } - // Create PDBs. - for _, pdb := range test.pdbs { - _, err := context.clientSet.PolicyV1beta1().PodDisruptionBudgets(context.ns.Name).Create(pdb) - if err != nil { - t.Fatalf("Failed to create PDB: %v", err) - } - } - // Wait for PDBs to show up in the scheduler's cache. - if err := wait.Poll(time.Second, 15*time.Second, func() (bool, error) { - cachedPDBs, err := context.scheduler.Config().SchedulerCache.ListPDBs(labels.Everything()) - if err != nil { - t.Errorf("Error while polling for PDB: %v", err) - return false, err - } - return len(cachedPDBs) == len(test.pdbs), err - }); err != nil { - t.Fatalf("Not all PDBs were added to the cache: %v", err) - } pods := make([]*v1.Pod, len(test.existingPods)) var err error @@ -732,7 +824,29 @@ func TestPDBInPreemption(t *testing.T) { if pods[i], err = runPausePod(cs, p); err != nil { t.Fatalf("Test [%v]: Error running pause pod: %v", test.description, err) } + // Add pod condition ready so that PDB is updated. + addPodConditionReady(p) + if _, err := context.clientSet.CoreV1().Pods(context.ns.Name).UpdateStatus(p); err != nil { + t.Fatal(err) + } } + // Wait for Pods to be stable in scheduler cache. + if err := waitCachedPodsStable(context, test.existingPods); err != nil { + t.Fatalf("Not all pods are stable in the cache: %v", err) + } + + // Create PDBs. + for _, pdb := range test.pdbs { + _, err := context.clientSet.PolicyV1beta1().PodDisruptionBudgets(context.ns.Name).Create(pdb) + if err != nil { + t.Fatalf("Failed to create PDB: %v", err) + } + } + // Wait for PDBs to show up in the scheduler's cache and become stable. + if err := waitCachedPDBsStable(context, test.pdbs, test.pdbPodNum); err != nil { + t.Fatalf("Not all pdbs are stable in the cache: %v", err) + } + // Create the "pod". preemptor, err := createPausePod(cs, test.pod) if err != nil { diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler/scheduler_test.go b/vendor/k8s.io/kubernetes/test/integration/scheduler/scheduler_test.go index d29b9009f..14b065bdf 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler/scheduler_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler/scheduler_test.go @@ -29,6 +29,8 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" @@ -41,20 +43,18 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" schedulerapp "k8s.io/kubernetes/cmd/kube-scheduler/app" + schedulerappconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/scheduler" "k8s.io/kubernetes/pkg/scheduler/algorithm" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/factory" - "k8s.io/kubernetes/pkg/scheduler/schedulercache" "k8s.io/kubernetes/test/integration/framework" ) -const enableEquivalenceCache = true - type nodeMutationFunc func(t *testing.T, n *v1.Node, nodeLister corelisters.NodeLister, c clientset.Interface) type nodeStateManager struct { @@ -88,7 +88,7 @@ func TestSchedulerCreationFromConfigMap(t *testing.T) { ns := framework.CreateTestingNamespace("configmap", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - clientSet := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + clientSet := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) defer clientSet.CoreV1().Nodes().DeleteCollection(nil, metav1.ListOptions{}) informerFactory := informers.NewSharedInformerFactory(clientSet, 0) @@ -135,6 +135,7 @@ func TestSchedulerCreationFromConfigMap(t *testing.T) { "CheckNodeCondition", // mandatory predicate "CheckNodeDiskPressure", "CheckNodeMemoryPressure", + "CheckNodePIDPressure", "CheckVolumeBinding", "GeneralPredicates", "MatchInterPodAffinity", @@ -175,32 +176,34 @@ func TestSchedulerCreationFromConfigMap(t *testing.T) { Data: map[string]string{componentconfig.SchedulerPolicyConfigMapKey: test.policy}, } - policyConfigMap.APIVersion = testapi.Groups[v1.GroupName].GroupVersion().String() + policyConfigMap.APIVersion = "v1" clientSet.CoreV1().ConfigMaps(metav1.NamespaceSystem).Create(&policyConfigMap) eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{Interface: clientv1core.New(clientSet.CoreV1().RESTClient()).Events("")}) - - ss := &schedulerapp.SchedulerServer{ - SchedulerName: v1.DefaultSchedulerName, - AlgorithmSource: componentconfig.SchedulerAlgorithmSource{ - Policy: &componentconfig.SchedulerPolicySource{ - ConfigMap: &componentconfig.SchedulerPolicyConfigMapSource{ - Namespace: policyConfigMap.Namespace, - Name: policyConfigMap.Name, + eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{Interface: clientSet.CoreV1().Events("")}) + + ss := &schedulerappconfig.Config{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, + SchedulerName: v1.DefaultSchedulerName, + AlgorithmSource: componentconfig.SchedulerAlgorithmSource{ + Policy: &componentconfig.SchedulerPolicySource{ + ConfigMap: &componentconfig.SchedulerPolicyConfigMapSource{ + Namespace: policyConfigMap.Namespace, + Name: policyConfigMap.Name, + }, }, }, }, - HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, Client: clientSet, InformerFactory: informerFactory, - PodInformer: factory.NewPodInformer(clientSet, 0, v1.DefaultSchedulerName), + PodInformer: factory.NewPodInformer(clientSet, 0), EventClient: clientSet.CoreV1(), Recorder: eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: v1.DefaultSchedulerName}), Broadcaster: eventBroadcaster, } - config, err := ss.SchedulerConfig() + config, err := schedulerapp.NewSchedulerConfig(ss.Complete()) if err != nil { t.Fatalf("couldn't make scheduler config: %v", err) } @@ -232,34 +235,36 @@ func TestSchedulerCreationFromNonExistentConfigMap(t *testing.T) { ns := framework.CreateTestingNamespace("configmap", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - clientSet := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + clientSet := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) defer clientSet.CoreV1().Nodes().DeleteCollection(nil, metav1.ListOptions{}) informerFactory := informers.NewSharedInformerFactory(clientSet, 0) eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{Interface: clientv1core.New(clientSet.CoreV1().RESTClient()).Events("")}) - - ss := &schedulerapp.SchedulerServer{ - SchedulerName: v1.DefaultSchedulerName, - AlgorithmSource: componentconfig.SchedulerAlgorithmSource{ - Policy: &componentconfig.SchedulerPolicySource{ - ConfigMap: &componentconfig.SchedulerPolicyConfigMapSource{ - Namespace: "non-existent-config", - Name: "non-existent-config", + eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{Interface: clientSet.CoreV1().Events("")}) + + ss := &schedulerappconfig.Config{ + ComponentConfig: componentconfig.KubeSchedulerConfiguration{ + SchedulerName: v1.DefaultSchedulerName, + AlgorithmSource: componentconfig.SchedulerAlgorithmSource{ + Policy: &componentconfig.SchedulerPolicySource{ + ConfigMap: &componentconfig.SchedulerPolicyConfigMapSource{ + Namespace: "non-existent-config", + Name: "non-existent-config", + }, }, }, + HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, }, - HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, Client: clientSet, InformerFactory: informerFactory, - PodInformer: factory.NewPodInformer(clientSet, 0, v1.DefaultSchedulerName), + PodInformer: factory.NewPodInformer(clientSet, 0), EventClient: clientSet.CoreV1(), Recorder: eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: v1.DefaultSchedulerName}), Broadcaster: eventBroadcaster, } - _, err := ss.SchedulerConfig() + _, err := schedulerapp.NewSchedulerConfig(ss.Complete()) if err == nil { t.Fatalf("Creation of scheduler didn't fail while the policy ConfigMap didn't exist.") } @@ -513,33 +518,18 @@ func TestMultiScheduler(t *testing.T) { } // 5. create and start a scheduler with name "foo-scheduler" - clientSet2 := clientset.NewForConfigOrDie(&restclient.Config{Host: context.httpServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + clientSet2 := clientset.NewForConfigOrDie(&restclient.Config{Host: context.httpServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) informerFactory2 := informers.NewSharedInformerFactory(context.clientSet, 0) - podInformer2 := factory.NewPodInformer(context.clientSet, 0, fooScheduler) - - schedulerConfigFactory2 := factory.NewConfigFactory( - fooScheduler, - clientSet2, - informerFactory2.Core().V1().Nodes(), - podInformer2, - informerFactory2.Core().V1().PersistentVolumes(), - informerFactory2.Core().V1().PersistentVolumeClaims(), - informerFactory2.Core().V1().ReplicationControllers(), - informerFactory2.Extensions().V1beta1().ReplicaSets(), - informerFactory2.Apps().V1beta1().StatefulSets(), - informerFactory2.Core().V1().Services(), - informerFactory2.Policy().V1beta1().PodDisruptionBudgets(), - informerFactory2.Storage().V1().StorageClasses(), - v1.DefaultHardPodAffinitySymmetricWeight, - enableEquivalenceCache, - ) + podInformer2 := factory.NewPodInformer(context.clientSet, 0) + + schedulerConfigFactory2 := createConfiguratorWithPodInformer(fooScheduler, clientSet2, podInformer2, informerFactory2) schedulerConfig2, err := schedulerConfigFactory2.Create() if err != nil { t.Errorf("Couldn't create scheduler config: %v", err) } eventBroadcaster2 := record.NewBroadcaster() schedulerConfig2.Recorder = eventBroadcaster2.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: fooScheduler}) - eventBroadcaster2.StartRecordingToSink(&clientv1core.EventSinkImpl{Interface: clientv1core.New(clientSet2.CoreV1().RESTClient()).Events("")}) + eventBroadcaster2.StartRecordingToSink(&clientv1core.EventSinkImpl{Interface: clientSet2.CoreV1().Events("")}) go podInformer2.Informer().Run(schedulerConfig2.StopEverything) informerFactory2.Start(schedulerConfig2.StopEverything) @@ -686,6 +676,7 @@ func TestPDBCache(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Namespace: context.ns.Name, Name: "test-pdb", + UID: types.UID("test-pdb-uid"), Labels: map[string]string{"tkey1": "tval1", "tkey2": "tval2"}, }, Spec: policy.PodDisruptionBudgetSpec{ @@ -762,3 +753,96 @@ func TestPDBCache(t *testing.T) { t.Errorf("No PDB was deleted from the cache: %v", err) } } + +// TestSchedulerInformers tests that scheduler receives informer events and updates its cache when +// pods are scheduled by other schedulers. +func TestSchedulerInformers(t *testing.T) { + // Initialize scheduler. + context := initTest(t, "scheduler-informer") + defer cleanupTest(t, context) + cs := context.clientSet + + defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + } + defaultNodeRes := &v1.ResourceList{ + v1.ResourcePods: *resource.NewQuantity(32, resource.DecimalSI), + v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(500, resource.BinarySI), + } + + type nodeConfig struct { + name string + res *v1.ResourceList + } + + tests := []struct { + description string + nodes []*nodeConfig + existingPods []*v1.Pod + pod *v1.Pod + preemptedPodIndexes map[int]struct{} + }{ + { + description: "Pod cannot be scheduled when node is occupied by pods scheduled by other schedulers", + nodes: []*nodeConfig{{name: "node-1", res: defaultNodeRes}}, + existingPods: []*v1.Pod{ + initPausePod(context.clientSet, &pausePodConfig{ + Name: "pod1", + Namespace: context.ns.Name, + Resources: defaultPodRes, + Labels: map[string]string{"foo": "bar"}, + NodeName: "node-1", + SchedulerName: "foo-scheduler", + }), + initPausePod(context.clientSet, &pausePodConfig{ + Name: "pod2", + Namespace: context.ns.Name, + Resources: defaultPodRes, + Labels: map[string]string{"foo": "bar"}, + NodeName: "node-1", + SchedulerName: "bar-scheduler", + }), + }, + pod: initPausePod(cs, &pausePodConfig{ + Name: "unschedulable-pod", + Namespace: context.ns.Name, + Resources: defaultPodRes, + }), + preemptedPodIndexes: map[int]struct{}{2: {}}, + }, + } + + for _, test := range tests { + for _, nodeConf := range test.nodes { + _, err := createNode(cs, nodeConf.name, nodeConf.res) + if err != nil { + t.Fatalf("Error creating node %v: %v", nodeConf.name, err) + } + } + + pods := make([]*v1.Pod, len(test.existingPods)) + var err error + // Create and run existingPods. + for i, p := range test.existingPods { + if pods[i], err = runPausePod(cs, p); err != nil { + t.Fatalf("Test [%v]: Error running pause pod: %v", test.description, err) + } + } + // Create the new "pod". + unschedulable, err := createPausePod(cs, test.pod) + if err != nil { + t.Errorf("Error while creating new pod: %v", err) + } + if err := waitForPodUnschedulable(cs, unschedulable); err != nil { + t.Errorf("Pod %v got scheduled: %v", unschedulable.Name, err) + } + + // Cleanup + pods = append(pods, unschedulable) + cleanupPods(cs, t, pods) + cs.PolicyV1beta1().PodDisruptionBudgets(context.ns.Name).DeleteCollection(nil, metav1.ListOptions{}) + cs.CoreV1().Nodes().DeleteCollection(nil, metav1.ListOptions{}) + } +} diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler/taint_test.go b/vendor/k8s.io/kubernetes/test/integration/scheduler/taint_test.go index fb158f8e2..f7de90706 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler/taint_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler/taint_test.go @@ -19,8 +19,6 @@ package scheduler // This file tests the Taint feature. import ( - "net/http" - "net/http/httptest" "reflect" "testing" "time" @@ -28,24 +26,18 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/client-go/informers" - clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" - "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" internalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/controller/nodelifecycle" kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" - "k8s.io/kubernetes/pkg/scheduler" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" - "k8s.io/kubernetes/pkg/scheduler/factory" "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction" pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction" - "k8s.io/kubernetes/test/integration/framework" ) // TestTaintNodeByCondition verifies: @@ -53,37 +45,41 @@ import ( // 2. NodeController taints nodes by node condition // 3. Scheduler allows pod to tolerate node condition taints, e.g. network unavailable func TestTaintNodeByCondition(t *testing.T) { - h := &framework.MasterHolder{Initialized: make(chan struct{})} - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - <-h.Initialized - h.M.GenericAPIServer.Handler.ServeHTTP(w, req) - })) - + enabled := utilfeature.DefaultFeatureGate.Enabled("TaintNodesByCondition") + defer func() { + if !enabled { + utilfeature.DefaultFeatureGate.Set("TaintNodesByCondition=False") + } + }() // Enable TaintNodeByCondition utilfeature.DefaultFeatureGate.Set("TaintNodesByCondition=True") + // Build PodToleration Admission. + admission := podtolerationrestriction.NewPodTolerationsPlugin(&pluginapi.Configuration{}) + + context := initTestMaster(t, "default", admission) + // Build clientset and informers for controllers. - internalClientset := internalclientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + internalClientset := internalclientset.NewForConfigOrDie(&restclient.Config{ + QPS: -1, + Host: context.httpServer.URL, + ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) internalInformers := internalinformers.NewSharedInformerFactory(internalClientset, time.Second) - clientset := clientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) - informers := informers.NewSharedInformerFactory(clientset, time.Second) - - // Build PodToleration Admission. - admission := podtolerationrestriction.NewPodTolerationsPlugin(&pluginapi.Configuration{}) kubeadmission.WantsInternalKubeClientSet(admission).SetInternalKubeClientSet(internalClientset) kubeadmission.WantsInternalKubeInformerFactory(admission).SetInternalKubeInformerFactory(internalInformers) - // Start master with admission. - masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.AdmissionControl = admission - _, _, closeFn := framework.RunAMasterUsingServer(masterConfig, s, h) - defer closeFn() - - nsName := "default" controllerCh := make(chan struct{}) defer close(controllerCh) + // Apply feature gates to enable TaintNodesByCondition + algorithmprovider.ApplyFeatureGates() + + context = initTestScheduler(t, context, controllerCh, false, nil) + clientset := context.clientSet + informers := context.informerFactory + nsName := context.ns.Name + // Start NodeLifecycleController for taint. nc, err := nodelifecycle.NewNodeLifecycleController( informers.Core().V1().Pods(), @@ -109,42 +105,8 @@ func TestTaintNodeByCondition(t *testing.T) { } go nc.Run(controllerCh) - // Apply feature gates to enable TaintNodesByCondition - algorithmprovider.ApplyFeatureGates() - - // Start scheduler - configurator := factory.NewConfigFactory( - v1.DefaultSchedulerName, - clientset, - informers.Core().V1().Nodes(), - informers.Core().V1().Pods(), - informers.Core().V1().PersistentVolumes(), - informers.Core().V1().PersistentVolumeClaims(), - informers.Core().V1().ReplicationControllers(), - informers.Extensions().V1beta1().ReplicaSets(), - informers.Apps().V1beta1().StatefulSets(), - informers.Core().V1().Services(), - informers.Policy().V1beta1().PodDisruptionBudgets(), - informers.Storage().V1().StorageClasses(), - v1.DefaultHardPodAffinitySymmetricWeight, - true, // Enable EqualCache by default. - ) - - sched, err := scheduler.NewFromConfigurator(configurator, func(cfg *scheduler.Config) { - cfg.StopEverything = controllerCh - cfg.Recorder = &record.FakeRecorder{} - }) - if err != nil { - t.Errorf("Failed to create scheduler: %v.", err) - return - } - go sched.Run() - // Waiting for all controller sync. - informers.Start(controllerCh) internalInformers.Start(controllerCh) - - informers.WaitForCacheSync(controllerCh) internalInformers.WaitForCacheSync(controllerCh) // ------------------------------------------- diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler/util.go b/vendor/k8s.io/kubernetes/test/integration/scheduler/util.go index 68e40eaf8..b70358554 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler/util.go +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler/util.go @@ -18,16 +18,25 @@ package scheduler import ( "fmt" + "net/http" + "net/http/httptest" "testing" "time" "k8s.io/api/core/v1" + policy "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apiserver/pkg/admission" + utilfeature "k8s.io/apiserver/pkg/util/feature" + utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/informers" + coreinformers "k8s.io/client-go/informers/core/v1" clientset "k8s.io/client-go/kubernetes" clientv1core "k8s.io/client-go/kubernetes/typed/core/v1" corelisters "k8s.io/client-go/listers/core/v1" @@ -35,12 +44,15 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/api/legacyscheme" podutil "k8s.io/kubernetes/pkg/api/v1/pod" + "k8s.io/kubernetes/pkg/controller" + "k8s.io/kubernetes/pkg/controller/disruption" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" "k8s.io/kubernetes/pkg/scheduler/factory" "k8s.io/kubernetes/test/integration/framework" - - "net/http/httptest" + imageutils "k8s.io/kubernetes/test/utils/image" ) type TestContext struct { @@ -54,50 +66,194 @@ type TestContext struct { scheduler *scheduler.Scheduler } -// initTest initializes a test environment and creates a scheduler with default +// createConfiguratorWithPodInformer creates a configurator for scheduler. +func createConfiguratorWithPodInformer( + schedulerName string, + clientSet clientset.Interface, + podInformer coreinformers.PodInformer, + informerFactory informers.SharedInformerFactory, +) scheduler.Configurator { + return factory.NewConfigFactory( + schedulerName, + clientSet, + informerFactory.Core().V1().Nodes(), + podInformer, + informerFactory.Core().V1().PersistentVolumes(), + informerFactory.Core().V1().PersistentVolumeClaims(), + informerFactory.Core().V1().ReplicationControllers(), + informerFactory.Extensions().V1beta1().ReplicaSets(), + informerFactory.Apps().V1beta1().StatefulSets(), + informerFactory.Core().V1().Services(), + informerFactory.Policy().V1beta1().PodDisruptionBudgets(), + informerFactory.Storage().V1().StorageClasses(), + v1.DefaultHardPodAffinitySymmetricWeight, + utilfeature.DefaultFeatureGate.Enabled(features.EnableEquivalenceClassCache), + false, + ) +} + +// initTestMasterAndScheduler initializes a test environment and creates a master with default // configuration. -func initTest(t *testing.T, nsPrefix string) *TestContext { +func initTestMaster(t *testing.T, nsPrefix string, admission admission.Interface) *TestContext { var context TestContext + + // 1. Create master + h := &framework.MasterHolder{Initialized: make(chan struct{})} + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + <-h.Initialized + h.M.GenericAPIServer.Handler.ServeHTTP(w, req) + })) + masterConfig := framework.NewIntegrationTestMasterConfig() - _, context.httpServer, context.closeFn = framework.RunAMaster(masterConfig) - context.ns = framework.CreateTestingNamespace(nsPrefix+string(uuid.NewUUID()), context.httpServer, t) + if admission != nil { + masterConfig.GenericConfig.AdmissionControl = admission + } + + _, context.httpServer, context.closeFn = framework.RunAMasterUsingServer(masterConfig, s, h) - context.clientSet = clientset.NewForConfigOrDie(&restclient.Config{Host: context.httpServer.URL}) - context.informerFactory = informers.NewSharedInformerFactory(context.clientSet, 0) - podInformer := factory.NewPodInformer(context.clientSet, 12*time.Hour, v1.DefaultSchedulerName) - context.schedulerConfigFactory = factory.NewConfigFactory( - v1.DefaultSchedulerName, - context.clientSet, - context.informerFactory.Core().V1().Nodes(), - podInformer, - context.informerFactory.Core().V1().PersistentVolumes(), - context.informerFactory.Core().V1().PersistentVolumeClaims(), - context.informerFactory.Core().V1().ReplicationControllers(), - context.informerFactory.Extensions().V1beta1().ReplicaSets(), - context.informerFactory.Apps().V1beta1().StatefulSets(), - context.informerFactory.Core().V1().Services(), - context.informerFactory.Policy().V1beta1().PodDisruptionBudgets(), - context.informerFactory.Storage().V1().StorageClasses(), - v1.DefaultHardPodAffinitySymmetricWeight, - true, + if nsPrefix != "default" { + context.ns = framework.CreateTestingNamespace(nsPrefix+string(uuid.NewUUID()), s, t) + } else { + context.ns = framework.CreateTestingNamespace("default", s, t) + } + + // 2. Create kubeclient + context.clientSet = clientset.NewForConfigOrDie( + &restclient.Config{ + QPS: -1, Host: s.URL, + ContentConfig: restclient.ContentConfig{ + GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}, + }, + }, ) + return &context +} + +// initTestScheduler initializes a test environment and creates a scheduler with default +// configuration. +func initTestScheduler( + t *testing.T, + context *TestContext, + controllerCh chan struct{}, + setPodInformer bool, + policy *schedulerapi.Policy, +) *TestContext { + // Pod preemption is enabled by default scheduler configuration, but preemption only happens when PodPriority + // feature gate is enabled at the same time. + return initTestSchedulerWithOptions(t, context, controllerCh, setPodInformer, policy, false) +} + +// initTestSchedulerWithOptions initializes a test environment and creates a scheduler with default +// configuration and other options. +func initTestSchedulerWithOptions( + t *testing.T, + context *TestContext, + controllerCh chan struct{}, + setPodInformer bool, + policy *schedulerapi.Policy, + disablePreemption bool, +) *TestContext { + // Enable EnableEquivalenceClassCache for all integration tests. + defer utilfeaturetesting.SetFeatureGateDuringTest( + t, + utilfeature.DefaultFeatureGate, + features.EnableEquivalenceClassCache, true)() + + // 1. Create scheduler + context.informerFactory = informers.NewSharedInformerFactory(context.clientSet, time.Second) + + var podInformer coreinformers.PodInformer + + // create independent pod informer if required + if setPodInformer { + podInformer = factory.NewPodInformer(context.clientSet, 12*time.Hour) + } else { + podInformer = context.informerFactory.Core().V1().Pods() + } + + context.schedulerConfigFactory = createConfiguratorWithPodInformer( + v1.DefaultSchedulerName, context.clientSet, podInformer, context.informerFactory) + var err error - context.schedulerConfig, err = context.schedulerConfigFactory.Create() + + if policy != nil { + context.schedulerConfig, err = context.schedulerConfigFactory.CreateFromConfig(*policy) + } else { + context.schedulerConfig, err = context.schedulerConfigFactory.Create() + } + if err != nil { t.Fatalf("Couldn't create scheduler config: %v", err) } + + // set controllerCh if provided. + if controllerCh != nil { + context.schedulerConfig.StopEverything = controllerCh + } + + // set DisablePreemption option + context.schedulerConfig.DisablePreemption = disablePreemption + + // set setPodInformer if provided. + if setPodInformer { + go podInformer.Informer().Run(context.schedulerConfig.StopEverything) + controller.WaitForCacheSync("scheduler", context.schedulerConfig.StopEverything, podInformer.Informer().HasSynced) + } + eventBroadcaster := record.NewBroadcaster() - context.schedulerConfig.Recorder = eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: v1.DefaultSchedulerName}) - eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{Interface: clientv1core.New(context.clientSet.CoreV1().RESTClient()).Events("")}) - go podInformer.Informer().Run(context.schedulerConfig.StopEverything) + context.schedulerConfig.Recorder = eventBroadcaster.NewRecorder( + legacyscheme.Scheme, + v1.EventSource{Component: v1.DefaultSchedulerName}, + ) + eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{ + Interface: context.clientSet.CoreV1().Events(""), + }) + context.informerFactory.Start(context.schedulerConfig.StopEverything) - context.scheduler, err = scheduler.NewFromConfigurator(&scheduler.FakeConfigurator{Config: context.schedulerConfig}, nil...) + context.informerFactory.WaitForCacheSync(context.schedulerConfig.StopEverything) + + context.scheduler, err = scheduler.NewFromConfigurator(&scheduler.FakeConfigurator{ + Config: context.schedulerConfig}, + nil...) if err != nil { t.Fatalf("Couldn't create scheduler: %v", err) } context.scheduler.Run() - return &context + return context +} + +// initDisruptionController initializes and runs a Disruption Controller to properly +// update PodDisuptionBudget objects. +func initDisruptionController(context *TestContext) *disruption.DisruptionController { + informers := informers.NewSharedInformerFactory(context.clientSet, 12*time.Hour) + + dc := disruption.NewDisruptionController( + informers.Core().V1().Pods(), + informers.Policy().V1beta1().PodDisruptionBudgets(), + informers.Core().V1().ReplicationControllers(), + informers.Extensions().V1beta1().ReplicaSets(), + informers.Extensions().V1beta1().Deployments(), + informers.Apps().V1beta1().StatefulSets(), + context.clientSet) + + informers.Start(context.schedulerConfig.StopEverything) + informers.WaitForCacheSync(context.schedulerConfig.StopEverything) + go dc.Run(context.schedulerConfig.StopEverything) + return dc +} + +// initTest initializes a test environment and creates master and scheduler with default +// configuration. +func initTest(t *testing.T, nsPrefix string) *TestContext { + return initTestScheduler(t, initTestMaster(t, nsPrefix, nil), nil, true, nil) +} + +// initTestDisablePreemption initializes a test environment and creates master and scheduler with default +// configuration but with pod preemption disabled. +func initTestDisablePreemption(t *testing.T, nsPrefix string) *TestContext { + return initTestSchedulerWithOptions( + t, initTestMaster(t, nsPrefix, nil), nil, true, nil, true) } // cleanupTest deletes the scheduler and the test namespace. It should be called @@ -113,7 +269,8 @@ func cleanupTest(t *testing.T, context *TestContext) { // waitForReflection waits till the passFunc confirms that the object it expects // to see is in the store. Used to observe reflected events. -func waitForReflection(t *testing.T, nodeLister corelisters.NodeLister, key string, passFunc func(n interface{}) bool) error { +func waitForReflection(t *testing.T, nodeLister corelisters.NodeLister, key string, + passFunc func(n interface{}) bool) error { nodes := []*v1.Node{} err := wait.Poll(time.Millisecond*100, wait.ForeverTestTimeout, func() (bool, error) { n, err := nodeLister.Get(key) @@ -185,6 +342,12 @@ func createNode(cs clientset.Interface, name string, res *v1.ResourceList) (*v1. return cs.CoreV1().Nodes().Create(n) } +// updateNodeStatus updates the status of node. +func updateNodeStatus(cs clientset.Interface, node *v1.Node) error { + _, err := cs.CoreV1().Nodes().UpdateStatus(node) + return err +} + // createNodes creates `numNodes` nodes. The created node names will be in the // form of "`prefix`-X" where X is an ordinal. func createNodes(cs clientset.Interface, prefix string, res *v1.ResourceList, numNodes int) ([]*v1.Node, error) { @@ -228,7 +391,7 @@ func initPausePod(cs clientset.Interface, conf *pausePodConfig) *v1.Pod { Containers: []v1.Container{ { Name: conf.Name, - Image: framework.GetPauseImageName(cs), + Image: imageutils.GetPauseImageName(), }, }, Tolerations: conf.Tolerations, @@ -252,7 +415,8 @@ func createPausePod(cs clientset.Interface, p *v1.Pod) (*v1.Pod, error) { // createPausePodWithResource creates a pod with "Pause" image and the given // resources and returns its pointer and error status. The resource list can be // nil. -func createPausePodWithResource(cs clientset.Interface, podName string, nsName string, res *v1.ResourceList) (*v1.Pod, error) { +func createPausePodWithResource(cs clientset.Interface, podName string, + nsName string, res *v1.ResourceList) (*v1.Pod, error) { var conf pausePodConfig if res == nil { conf = pausePodConfig{ @@ -346,7 +510,8 @@ func podUnschedulable(c clientset.Interface, podNamespace, podName string) wait. return false, nil } _, cond := podutil.GetPodCondition(&pod.Status, v1.PodScheduled) - return cond != nil && cond.Status == v1.ConditionFalse && cond.Reason == v1.PodReasonUnschedulable, nil + return cond != nil && cond.Status == v1.ConditionFalse && + cond.Reason == v1.PodReasonUnschedulable, nil } } @@ -374,6 +539,59 @@ func waitForPodUnschedulable(cs clientset.Interface, pod *v1.Pod) error { return waitForPodUnschedulableWithTimeout(cs, pod, 30*time.Second) } +// waitCachedPDBsStable waits for PDBs in scheduler cache to have "CurrentHealthy" status equal to +// the expected values. +func waitCachedPDBsStable(context *TestContext, pdbs []*policy.PodDisruptionBudget, pdbPodNum []int32) error { + return wait.Poll(time.Second, 60*time.Second, func() (bool, error) { + cachedPDBs, err := context.scheduler.Config().SchedulerCache.ListPDBs(labels.Everything()) + if err != nil { + return false, err + } + if len(cachedPDBs) != len(pdbs) { + return false, nil + } + for i, pdb := range pdbs { + found := false + for _, cpdb := range cachedPDBs { + if pdb.Name == cpdb.Name && pdb.Namespace == cpdb.Namespace { + found = true + if cpdb.Status.CurrentHealthy != pdbPodNum[i] { + return false, nil + } + } + } + if !found { + return false, nil + } + } + return true, nil + }) +} + +// waitCachedPodsStable waits until scheduler cache has the given pods. +func waitCachedPodsStable(context *TestContext, pods []*v1.Pod) error { + return wait.Poll(time.Second, 30*time.Second, func() (bool, error) { + cachedPods, err := context.scheduler.Config().SchedulerCache.List(labels.Everything()) + if err != nil { + return false, err + } + if len(pods) != len(cachedPods) { + return false, nil + } + for _, p := range pods { + actualPod, err1 := context.clientSet.CoreV1().Pods(p.Namespace).Get(p.Name, metav1.GetOptions{}) + if err1 != nil { + return false, err1 + } + cachedPod, err2 := context.scheduler.Config().SchedulerCache.GetPod(actualPod) + if err2 != nil || cachedPod == nil { + return false, err2 + } + } + return true, nil + }) +} + // deletePod deletes the given pod in the given namespace. func deletePod(cs clientset.Interface, podName string, nsName string) error { return cs.CoreV1().Pods(nsName).Delete(podName, metav1.NewDeleteOptions(0)) @@ -388,8 +606,35 @@ func cleanupPods(cs clientset.Interface, t *testing.T, pods []*v1.Pod) { } } for _, p := range pods { - if err := wait.Poll(time.Second, wait.ForeverTestTimeout, podDeleted(cs, p.Namespace, p.Name)); err != nil { + if err := wait.Poll(time.Second, wait.ForeverTestTimeout, + podDeleted(cs, p.Namespace, p.Name)); err != nil { t.Errorf("error while waiting for pod %v/%v to get deleted: %v", p.Namespace, p.Name, err) } } } + +// noPodsInNamespace returns true if no pods in the given namespace. +func noPodsInNamespace(c clientset.Interface, podNamespace string) wait.ConditionFunc { + return func() (bool, error) { + pods, err := c.CoreV1().Pods(podNamespace).List(metav1.ListOptions{}) + if err != nil { + return false, err + } + + return len(pods.Items) == 0, nil + } +} + +// cleanupPodsInNamespace deletes the pods in the given namespace and waits for them to +// be actually deleted. +func cleanupPodsInNamespace(cs clientset.Interface, t *testing.T, ns string) { + if err := cs.CoreV1().Pods(ns).DeleteCollection(nil, metav1.ListOptions{}); err != nil { + t.Errorf("error while listing pod in namespace %v: %v", ns, err) + return + } + + if err := wait.Poll(time.Second, wait.ForeverTestTimeout, + noPodsInNamespace(cs, ns)); err != nil { + t.Errorf("error while waiting for pods in namespace %v: %v", ns, err) + } +} diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler/volume_binding_test.go b/vendor/k8s.io/kubernetes/test/integration/scheduler/volume_binding_test.go index 0c5c919b3..6a5545904 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler/volume_binding_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler/volume_binding_test.go @@ -20,8 +20,6 @@ package scheduler import ( "fmt" - "net/http" - "net/http/httptest" "strconv" "strings" "testing" @@ -33,19 +31,11 @@ import ( storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" - v1core "k8s.io/client-go/kubernetes/typed/core/v1" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/controller/volume/persistentvolume" - "k8s.io/kubernetes/pkg/scheduler" - "k8s.io/kubernetes/pkg/scheduler/factory" - "k8s.io/kubernetes/test/integration/framework" ) type testConfig struct { @@ -75,94 +65,107 @@ const ( nodeAffinityLabelKey = "kubernetes.io/hostname" ) +type testPV struct { + name string + scMode storagev1.VolumeBindingMode + preboundPVC string + node string +} + +type testPVC struct { + name string + scMode storagev1.VolumeBindingMode + preboundPV string +} + func TestVolumeBinding(t *testing.T) { config := setupCluster(t, "volume-scheduling", 2) defer config.teardown() cases := map[string]struct { pod *v1.Pod - pvs []*v1.PersistentVolume - pvcs []*v1.PersistentVolumeClaim + pvs []*testPV + pvcs []*testPVC // Create these, but they should not be bound in the end - unboundPvcs []*v1.PersistentVolumeClaim - unboundPvs []*v1.PersistentVolume + unboundPvcs []*testPVC + unboundPvs []*testPV shouldFail bool }{ "immediate can bind": { pod: makePod("pod-i-canbind", config.ns, []string{"pvc-i-canbind"}), - pvs: []*v1.PersistentVolume{makePV(t, "pv-i-canbind", classImmediate, "", "", node1)}, - pvcs: []*v1.PersistentVolumeClaim{makePVC("pvc-i-canbind", config.ns, &classImmediate, "")}, + pvs: []*testPV{{"pv-i-canbind", modeImmediate, "", node1}}, + pvcs: []*testPVC{{"pvc-i-canbind", modeImmediate, ""}}, }, "immediate cannot bind": { pod: makePod("pod-i-cannotbind", config.ns, []string{"pvc-i-cannotbind"}), - unboundPvcs: []*v1.PersistentVolumeClaim{makePVC("pvc-i-cannotbind", config.ns, &classImmediate, "")}, + unboundPvcs: []*testPVC{{"pvc-i-cannotbind", modeImmediate, ""}}, shouldFail: true, }, "immediate pvc prebound": { pod: makePod("pod-i-pvc-prebound", config.ns, []string{"pvc-i-prebound"}), - pvs: []*v1.PersistentVolume{makePV(t, "pv-i-pvc-prebound", classImmediate, "", "", node1)}, - pvcs: []*v1.PersistentVolumeClaim{makePVC("pvc-i-prebound", config.ns, &classImmediate, "pv-i-pvc-prebound")}, + pvs: []*testPV{{"pv-i-pvc-prebound", modeImmediate, "", node1}}, + pvcs: []*testPVC{{"pvc-i-prebound", modeImmediate, "pv-i-pvc-prebound"}}, }, "immediate pv prebound": { pod: makePod("pod-i-pv-prebound", config.ns, []string{"pvc-i-pv-prebound"}), - pvs: []*v1.PersistentVolume{makePV(t, "pv-i-prebound", classImmediate, "pvc-i-pv-prebound", config.ns, node1)}, - pvcs: []*v1.PersistentVolumeClaim{makePVC("pvc-i-pv-prebound", config.ns, &classImmediate, "")}, + pvs: []*testPV{{"pv-i-prebound", modeImmediate, "pvc-i-pv-prebound", node1}}, + pvcs: []*testPVC{{"pvc-i-pv-prebound", modeImmediate, ""}}, }, "wait can bind": { pod: makePod("pod-w-canbind", config.ns, []string{"pvc-w-canbind"}), - pvs: []*v1.PersistentVolume{makePV(t, "pv-w-canbind", classWait, "", "", node1)}, - pvcs: []*v1.PersistentVolumeClaim{makePVC("pvc-w-canbind", config.ns, &classWait, "")}, + pvs: []*testPV{{"pv-w-canbind", modeWait, "", node1}}, + pvcs: []*testPVC{{"pvc-w-canbind", modeWait, ""}}, }, "wait cannot bind": { pod: makePod("pod-w-cannotbind", config.ns, []string{"pvc-w-cannotbind"}), - unboundPvcs: []*v1.PersistentVolumeClaim{makePVC("pvc-w-cannotbind", config.ns, &classWait, "")}, + unboundPvcs: []*testPVC{{"pvc-w-cannotbind", modeWait, ""}}, shouldFail: true, }, "wait pvc prebound": { pod: makePod("pod-w-pvc-prebound", config.ns, []string{"pvc-w-prebound"}), - pvs: []*v1.PersistentVolume{makePV(t, "pv-w-pvc-prebound", classWait, "", "", node1)}, - pvcs: []*v1.PersistentVolumeClaim{makePVC("pvc-w-prebound", config.ns, &classWait, "pv-w-pvc-prebound")}, + pvs: []*testPV{{"pv-w-pvc-prebound", modeWait, "", node1}}, + pvcs: []*testPVC{{"pvc-w-prebound", modeWait, "pv-w-pvc-prebound"}}, }, "wait pv prebound": { pod: makePod("pod-w-pv-prebound", config.ns, []string{"pvc-w-pv-prebound"}), - pvs: []*v1.PersistentVolume{makePV(t, "pv-w-prebound", classWait, "pvc-w-pv-prebound", config.ns, node1)}, - pvcs: []*v1.PersistentVolumeClaim{makePVC("pvc-w-pv-prebound", config.ns, &classWait, "")}, + pvs: []*testPV{{"pv-w-prebound", modeWait, "pvc-w-pv-prebound", node1}}, + pvcs: []*testPVC{{"pvc-w-pv-prebound", modeWait, ""}}, }, "wait can bind two": { pod: makePod("pod-w-canbind-2", config.ns, []string{"pvc-w-canbind-2", "pvc-w-canbind-3"}), - pvs: []*v1.PersistentVolume{ - makePV(t, "pv-w-canbind-2", classWait, "", "", node2), - makePV(t, "pv-w-canbind-3", classWait, "", "", node2), + pvs: []*testPV{ + {"pv-w-canbind-2", modeWait, "", node2}, + {"pv-w-canbind-3", modeWait, "", node2}, }, - pvcs: []*v1.PersistentVolumeClaim{ - makePVC("pvc-w-canbind-2", config.ns, &classWait, ""), - makePVC("pvc-w-canbind-3", config.ns, &classWait, ""), + pvcs: []*testPVC{ + {"pvc-w-canbind-2", modeWait, ""}, + {"pvc-w-canbind-3", modeWait, ""}, }, - unboundPvs: []*v1.PersistentVolume{ - makePV(t, "pv-w-canbind-5", classWait, "", "", node1), + unboundPvs: []*testPV{ + {"pv-w-canbind-5", modeWait, "", node1}, }, }, "wait cannot bind two": { pod: makePod("pod-w-cannotbind-2", config.ns, []string{"pvc-w-cannotbind-1", "pvc-w-cannotbind-2"}), - unboundPvcs: []*v1.PersistentVolumeClaim{ - makePVC("pvc-w-cannotbind-1", config.ns, &classWait, ""), - makePVC("pvc-w-cannotbind-2", config.ns, &classWait, ""), + unboundPvcs: []*testPVC{ + {"pvc-w-cannotbind-1", modeWait, ""}, + {"pvc-w-cannotbind-2", modeWait, ""}, }, - unboundPvs: []*v1.PersistentVolume{ - makePV(t, "pv-w-cannotbind-1", classWait, "", "", node2), - makePV(t, "pv-w-cannotbind-2", classWait, "", "", node1), + unboundPvs: []*testPV{ + {"pv-w-cannotbind-1", modeWait, "", node2}, + {"pv-w-cannotbind-2", modeWait, "", node1}, }, shouldFail: true, }, "mix immediate and wait": { pod: makePod("pod-mix-bound", config.ns, []string{"pvc-w-canbind-4", "pvc-i-canbind-2"}), - pvs: []*v1.PersistentVolume{ - makePV(t, "pv-w-canbind-4", classWait, "", "", node1), - makePV(t, "pv-i-canbind-2", classImmediate, "", "", node1), + pvs: []*testPV{ + {"pv-w-canbind-4", modeWait, "", node1}, + {"pv-i-canbind-2", modeImmediate, "", node1}, }, - pvcs: []*v1.PersistentVolumeClaim{ - makePVC("pvc-w-canbind-4", config.ns, &classWait, ""), - makePVC("pvc-i-canbind-2", config.ns, &classImmediate, ""), + pvcs: []*testPVC{ + {"pvc-w-canbind-4", modeWait, ""}, + {"pvc-i-canbind-2", modeImmediate, ""}, }, }, } @@ -170,26 +173,41 @@ func TestVolumeBinding(t *testing.T) { for name, test := range cases { glog.Infof("Running test %v", name) + // Create two StorageClasses + suffix := rand.String(4) + classes := map[storagev1.VolumeBindingMode]*storagev1.StorageClass{} + classes[modeImmediate] = makeStorageClass(fmt.Sprintf("immediate-%v", suffix), &modeImmediate) + classes[modeWait] = makeStorageClass(fmt.Sprintf("wait-%v", suffix), &modeWait) + for _, sc := range classes { + if _, err := config.client.StorageV1().StorageClasses().Create(sc); err != nil { + t.Fatalf("Failed to create StorageClass %q: %v", sc.Name, err) + } + } + // Create PVs - for _, pv := range test.pvs { + for _, pvConfig := range test.pvs { + pv := makePV(pvConfig.name, classes[pvConfig.scMode].Name, pvConfig.preboundPVC, config.ns, pvConfig.node) if _, err := config.client.CoreV1().PersistentVolumes().Create(pv); err != nil { t.Fatalf("Failed to create PersistentVolume %q: %v", pv.Name, err) } } - for _, pv := range test.unboundPvs { + for _, pvConfig := range test.unboundPvs { + pv := makePV(pvConfig.name, classes[pvConfig.scMode].Name, pvConfig.preboundPVC, config.ns, pvConfig.node) if _, err := config.client.CoreV1().PersistentVolumes().Create(pv); err != nil { t.Fatalf("Failed to create PersistentVolume %q: %v", pv.Name, err) } } // Create PVCs - for _, pvc := range test.pvcs { + for _, pvcConfig := range test.pvcs { + pvc := makePVC(pvcConfig.name, config.ns, &classes[pvcConfig.scMode].Name, pvcConfig.preboundPV) if _, err := config.client.CoreV1().PersistentVolumeClaims(config.ns).Create(pvc); err != nil { t.Fatalf("Failed to create PersistentVolumeClaim %q: %v", pvc.Name, err) } } - for _, pvc := range test.unboundPvcs { + for _, pvcConfig := range test.unboundPvcs { + pvc := makePVC(pvcConfig.name, config.ns, &classes[pvcConfig.scMode].Name, pvcConfig.preboundPV) if _, err := config.client.CoreV1().PersistentVolumeClaims(config.ns).Create(pvc); err != nil { t.Fatalf("Failed to create PersistentVolumeClaim %q: %v", pvc.Name, err) } @@ -211,23 +229,20 @@ func TestVolumeBinding(t *testing.T) { // Validate PVC/PV binding for _, pvc := range test.pvcs { - validatePVCPhase(t, config.client, pvc, v1.ClaimBound) + validatePVCPhase(t, config.client, pvc.name, config.ns, v1.ClaimBound) } for _, pvc := range test.unboundPvcs { - validatePVCPhase(t, config.client, pvc, v1.ClaimPending) + validatePVCPhase(t, config.client, pvc.name, config.ns, v1.ClaimPending) } for _, pv := range test.pvs { - validatePVPhase(t, config.client, pv, v1.VolumeBound) + validatePVPhase(t, config.client, pv.name, v1.VolumeBound) } for _, pv := range test.unboundPvs { - validatePVPhase(t, config.client, pv, v1.VolumeAvailable) + validatePVPhase(t, config.client, pv.name, v1.VolumeAvailable) } - // TODO: validate events on Pods and PVCs - - config.client.CoreV1().Pods(config.ns).DeleteCollection(deleteOption, metav1.ListOptions{}) - config.client.CoreV1().PersistentVolumeClaims(config.ns).DeleteCollection(deleteOption, metav1.ListOptions{}) - config.client.CoreV1().PersistentVolumes().DeleteCollection(deleteOption, metav1.ListOptions{}) + // Force delete objects, but they still may not be immediately removed + deleteTestObjects(config.client, config.ns, deleteOption) } } @@ -240,7 +255,7 @@ func TestVolumeBindingStress(t *testing.T) { pvs := []*v1.PersistentVolume{} pvcs := []*v1.PersistentVolumeClaim{} for i := 0; i < podLimit*volsPerPod; i++ { - pv := makePV(t, fmt.Sprintf("pv-stress-%v", i), classWait, "", "", node1) + pv := makePV(fmt.Sprintf("pv-stress-%v", i), classWait, "", "", node1) pvc := makePVC(fmt.Sprintf("pvc-stress-%v", i), config.ns, &classWait, "") if pv, err := config.client.CoreV1().PersistentVolumes().Create(pv); err != nil { @@ -271,27 +286,27 @@ func TestVolumeBindingStress(t *testing.T) { // Validate Pods scheduled for _, pod := range pods { - if err := waitForPodToSchedule(config.client, pod); err != nil { + // Use increased timeout for stress test because there is a higher chance of + // PV sync error + if err := waitForPodToScheduleWithTimeout(config.client, pod, 60*time.Second); err != nil { t.Errorf("Failed to schedule Pod %q: %v", pod.Name, err) } } // Validate PVC/PV binding for _, pvc := range pvcs { - validatePVCPhase(t, config.client, pvc, v1.ClaimBound) + validatePVCPhase(t, config.client, pvc.Name, config.ns, v1.ClaimBound) } for _, pv := range pvs { - validatePVPhase(t, config.client, pv, v1.VolumeBound) + validatePVPhase(t, config.client, pv.Name, v1.VolumeBound) } - - // TODO: validate events on Pods and PVCs } func TestPVAffinityConflict(t *testing.T) { config := setupCluster(t, "volume-scheduling", 3) defer config.teardown() - pv := makePV(t, "local-pv", classImmediate, "", "", node1) + pv := makePV("local-pv", classImmediate, "", "", node1) pvc := makePVC("local-pvc", config.ns, &classImmediate, "") // Create PV @@ -347,26 +362,16 @@ func TestPVAffinityConflict(t *testing.T) { } func setupCluster(t *testing.T, nsName string, numberOfNodes int) *testConfig { - h := &framework.MasterHolder{Initialized: make(chan struct{})} - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - <-h.Initialized - h.M.GenericAPIServer.Handler.ServeHTTP(w, req) - })) - // Enable feature gates utilfeature.DefaultFeatureGate.Set("VolumeScheduling=true,PersistentLocalVolumes=true") - // Build clientset and informers for controllers. - clientset := clientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) - informers := informers.NewSharedInformerFactory(clientset, time.Second) - - // Start master - masterConfig := framework.NewIntegrationTestMasterConfig() + controllerCh := make(chan struct{}) - _, _, closeFn := framework.RunAMasterUsingServer(masterConfig, s, h) - ns := framework.CreateTestingNamespace(nsName, s, t).Name + context := initTestScheduler(t, initTestMaster(t, nsName, nil), controllerCh, false, nil) - controllerCh := make(chan struct{}) + clientset := context.clientSet + ns := context.ns.Name + informers := context.informerFactory // Start PV controller for volume binding. params := persistentvolume.ControllerParameters{ @@ -379,7 +384,7 @@ func setupCluster(t *testing.T, nsName string, numberOfNodes int) *testConfig { ClaimInformer: informers.Core().V1().PersistentVolumeClaims(), ClassInformer: informers.Storage().V1().StorageClasses(), PodInformer: informers.Core().V1().Pods(), - EventRecorder: nil, // TODO: add one so we can test PV events + NodeInformer: informers.Core().V1().Nodes(), EnableDynamicProvisioning: true, } ctrl, err := persistentvolume.NewController(params) @@ -388,40 +393,6 @@ func setupCluster(t *testing.T, nsName string, numberOfNodes int) *testConfig { } go ctrl.Run(controllerCh) - // Start scheduler - configurator := factory.NewConfigFactory( - v1.DefaultSchedulerName, - clientset, - informers.Core().V1().Nodes(), - informers.Core().V1().Pods(), - informers.Core().V1().PersistentVolumes(), - informers.Core().V1().PersistentVolumeClaims(), - informers.Core().V1().ReplicationControllers(), - informers.Extensions().V1beta1().ReplicaSets(), - informers.Apps().V1beta1().StatefulSets(), - informers.Core().V1().Services(), - informers.Policy().V1beta1().PodDisruptionBudgets(), - informers.Storage().V1().StorageClasses(), - v1.DefaultHardPodAffinitySymmetricWeight, - true, // Enable EqualCache by default. - ) - - eventBroadcaster := record.NewBroadcaster() - sched, err := scheduler.NewFromConfigurator(configurator, func(cfg *scheduler.Config) { - cfg.StopEverything = controllerCh - cfg.Recorder = eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: v1.DefaultSchedulerName}) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(clientset.CoreV1().RESTClient()).Events("")}) - }) - if err != nil { - t.Fatalf("Failed to create scheduler: %v.", err) - } - - go sched.Run() - - // Waiting for all controller sync. - informers.Start(controllerCh) - informers.WaitForCacheSync(controllerCh) - // Create shared objects // Create nodes for i := 0; i < numberOfNodes; i++ { @@ -466,18 +437,20 @@ func setupCluster(t *testing.T, nsName string, numberOfNodes int) *testConfig { ns: ns, stop: controllerCh, teardown: func() { - clientset.CoreV1().Pods(ns).DeleteCollection(nil, metav1.ListOptions{}) - clientset.CoreV1().PersistentVolumeClaims(ns).DeleteCollection(nil, metav1.ListOptions{}) - clientset.CoreV1().PersistentVolumes().DeleteCollection(nil, metav1.ListOptions{}) - clientset.StorageV1().StorageClasses().DeleteCollection(nil, metav1.ListOptions{}) - clientset.CoreV1().Nodes().DeleteCollection(nil, metav1.ListOptions{}) - close(controllerCh) - closeFn() + deleteTestObjects(clientset, ns, nil) + cleanupTest(t, context) utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false,LocalPersistentVolumes=false") }, } } +func deleteTestObjects(client clientset.Interface, ns string, option *metav1.DeleteOptions) { + client.CoreV1().Pods(ns).DeleteCollection(option, metav1.ListOptions{}) + client.CoreV1().PersistentVolumeClaims(ns).DeleteCollection(option, metav1.ListOptions{}) + client.CoreV1().PersistentVolumes().DeleteCollection(option, metav1.ListOptions{}) + client.StorageV1().StorageClasses().DeleteCollection(option, metav1.ListOptions{}) +} + func makeStorageClass(name string, mode *storagev1.VolumeBindingMode) *storagev1.StorageClass { return &storagev1.StorageClass{ ObjectMeta: metav1.ObjectMeta{ @@ -488,7 +461,7 @@ func makeStorageClass(name string, mode *storagev1.VolumeBindingMode) *storagev1 } } -func makePV(t *testing.T, name, scName, pvcName, ns, node string) *v1.PersistentVolume { +func makePV(name, scName, pvcName, ns, node string) *v1.PersistentVolume { pv := &v1.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -585,25 +558,25 @@ func makePod(name, ns string, pvcs []string) *v1.Pod { } } -func validatePVCPhase(t *testing.T, client clientset.Interface, pvc *v1.PersistentVolumeClaim, phase v1.PersistentVolumeClaimPhase) { - claim, err := client.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(pvc.Name, metav1.GetOptions{}) +func validatePVCPhase(t *testing.T, client clientset.Interface, pvcName string, ns string, phase v1.PersistentVolumeClaimPhase) { + claim, err := client.CoreV1().PersistentVolumeClaims(ns).Get(pvcName, metav1.GetOptions{}) if err != nil { - t.Errorf("Failed to get PVC %v/%v: %v", pvc.Namespace, pvc.Name, err) + t.Errorf("Failed to get PVC %v/%v: %v", ns, pvcName, err) } if claim.Status.Phase != phase { - t.Errorf("PVC %v/%v phase not %v, got %v", pvc.Namespace, pvc.Name, phase, claim.Status.Phase) + t.Errorf("PVC %v/%v phase not %v, got %v", ns, pvcName, phase, claim.Status.Phase) } } -func validatePVPhase(t *testing.T, client clientset.Interface, pv *v1.PersistentVolume, phase v1.PersistentVolumePhase) { - pv, err := client.CoreV1().PersistentVolumes().Get(pv.Name, metav1.GetOptions{}) +func validatePVPhase(t *testing.T, client clientset.Interface, pvName string, phase v1.PersistentVolumePhase) { + pv, err := client.CoreV1().PersistentVolumes().Get(pvName, metav1.GetOptions{}) if err != nil { - t.Errorf("Failed to get PV %v: %v", pv.Name, err) + t.Errorf("Failed to get PV %v: %v", pvName, err) } if pv.Status.Phase != phase { - t.Errorf("PV %v phase not %v, got %v", pv.Name, phase, pv.Status.Phase) + t.Errorf("PV %v phase not %v, got %v", pvName, phase, pv.Status.Phase) } } diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/BUILD b/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/BUILD index d40061c79..552273834 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/BUILD @@ -14,11 +14,10 @@ go_library( ], importpath = "k8s.io/kubernetes/test/integration/scheduler_perf", deps = [ - "//pkg/api/testapi:go_default_library", "//pkg/scheduler:go_default_library", "//pkg/scheduler/algorithmprovider:go_default_library", "//test/integration/util:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/scheduler_test.go b/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/scheduler_test.go index 419e2d196..b7134d695 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/scheduler_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/scheduler_test.go @@ -50,10 +50,6 @@ var ( ObjectMeta: metav1.ObjectMeta{ GenerateName: "sample-node-", }, - Spec: v1.NodeSpec{ - // TODO: investigate why this is needed. - ExternalID: "foo", - }, Status: v1.NodeStatus{ Capacity: v1.ResourceList{ v1.ResourcePods: *resource.NewQuantity(110, resource.DecimalSI), diff --git a/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/util.go b/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/util.go index 36bb574ff..13f71a6c1 100644 --- a/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/util.go +++ b/vendor/k8s.io/kubernetes/test/integration/scheduler_perf/util.go @@ -17,10 +17,9 @@ limitations under the License. package benchmark import ( - "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/scheduler" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" "k8s.io/kubernetes/test/integration/util" @@ -37,11 +36,11 @@ func mustSetupScheduler() (scheduler.Configurator, util.ShutdownFunc) { apiURL, apiShutdown := util.StartApiserver() clientSet := clientset.NewForConfigOrDie(&restclient.Config{ Host: apiURL, - ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}, + ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, QPS: 5000.0, Burst: 5000, }) - schedulerConfig, schedulerShutdown := util.StartScheduler(clientSet, true) + schedulerConfig, schedulerShutdown := util.StartScheduler(clientSet) shutdownFunc := func() { schedulerShutdown() diff --git a/vendor/k8s.io/kubernetes/test/integration/secrets/BUILD b/vendor/k8s.io/kubernetes/test/integration/secrets/BUILD index 09c06c337..f9dec6670 100644 --- a/vendor/k8s.io/kubernetes/test/integration/secrets/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/secrets/BUILD @@ -14,11 +14,11 @@ go_test( ], tags = ["integration"], deps = [ - "//pkg/api/testapi:go_default_library", "//test/integration:go_default_library", "//test/integration/framework:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/test/integration/secrets/secrets_test.go b/vendor/k8s.io/kubernetes/test/integration/secrets/secrets_test.go index 385d73eb1..d15991af3 100644 --- a/vendor/k8s.io/kubernetes/test/integration/secrets/secrets_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/secrets/secrets_test.go @@ -23,9 +23,9 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/integration" "k8s.io/kubernetes/test/integration/framework" ) @@ -41,7 +41,7 @@ func TestSecrets(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) ns := framework.CreateTestingNamespace("secret", s, t) defer framework.DeleteTestingNamespace(ns, s, t) diff --git a/vendor/k8s.io/kubernetes/test/integration/serviceaccount/BUILD b/vendor/k8s.io/kubernetes/test/integration/serviceaccount/BUILD index b18a3a6f5..31cc8053d 100644 --- a/vendor/k8s.io/kubernetes/test/integration/serviceaccount/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/serviceaccount/BUILD @@ -14,7 +14,6 @@ go_test( ], tags = ["integration"], deps = [ - "//pkg/api/testapi:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/informers/informers_generated/internalversion:go_default_library", "//pkg/controller:go_default_library", @@ -27,6 +26,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/serviceaccount/service_account_test.go b/vendor/k8s.io/kubernetes/test/integration/serviceaccount/service_account_test.go index 90f12d35b..23417cc38 100644 --- a/vendor/k8s.io/kubernetes/test/integration/serviceaccount/service_account_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/serviceaccount/service_account_test.go @@ -33,6 +33,7 @@ import ( apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/authentication/authenticator" @@ -44,7 +45,6 @@ import ( "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" internalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/controller" @@ -359,11 +359,11 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie })) // Anonymous client config - clientConfig := restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}} + clientConfig := restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}} // Root client // TODO: remove rootClient after we refactor pkg/admission to use the clientset. - rootClientset := clientset.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}, BearerToken: rootToken}) - internalRootClientset := internalclientset.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}, BearerToken: rootToken}) + rootClientset := clientset.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, BearerToken: rootToken}) + internalRootClientset := internalclientset.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, BearerToken: rootToken}) // Set up two authenticators: // 1. A token authenticator that maps the rootToken to the "root" user // 2. A ServiceAccountToken authenticator that validates ServiceAccount tokens diff --git a/vendor/k8s.io/kubernetes/test/integration/statefulset/BUILD b/vendor/k8s.io/kubernetes/test/integration/statefulset/BUILD new file mode 100644 index 000000000..517987a4d --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/statefulset/BUILD @@ -0,0 +1,57 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["util.go"], + importpath = "k8s.io/kubernetes/test/integration/statefulset", + visibility = ["//visibility:public"], + deps = [ + #"//pkg/api:go_default_library", + "//pkg/controller/statefulset:go_default_library", + "//test/integration/framework:go_default_library", + "//vendor/k8s.io/api/apps/v1beta1:go_default_library", + "//vendor/k8s.io/api/core/v1: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/labels:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//vendor/k8s.io/client-go/informers:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/util/retry:go_default_library", + ], +) + +go_test( + name = "go_default_test", + size = "large", + srcs = [ + "main_test.go", + "statefulset_test.go", + ], + embed = [":go_default_library"], + tags = ["integration"], + deps = [ + "//test/integration/framework:go_default_library", + "//vendor/k8s.io/api/apps/v1beta1:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/test/integration/statefulset/OWNERS b/vendor/k8s.io/kubernetes/test/integration/statefulset/OWNERS new file mode 100644 index 000000000..ef439d8b0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/statefulset/OWNERS @@ -0,0 +1,6 @@ +reviewers: + - barney-s + - crimsonfaith91 +approvers: + - barney-s + - crimsonfaith91 diff --git a/vendor/k8s.io/kubernetes/test/integration/statefulset/main_test.go b/vendor/k8s.io/kubernetes/test/integration/statefulset/main_test.go new file mode 100644 index 000000000..4527b42ba --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/statefulset/main_test.go @@ -0,0 +1,27 @@ +/* +Copyright 2018 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 statefulset + +import ( + "testing" + + "k8s.io/kubernetes/test/integration/framework" +) + +func TestMain(m *testing.M) { + framework.EtcdMain(m.Run) +} diff --git a/vendor/k8s.io/kubernetes/test/integration/statefulset/statefulset_test.go b/vendor/k8s.io/kubernetes/test/integration/statefulset/statefulset_test.go new file mode 100644 index 000000000..d4946aa4f --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/statefulset/statefulset_test.go @@ -0,0 +1,147 @@ +/* +Copyright 2018 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 statefulset + +import ( + "fmt" + "testing" + + "k8s.io/api/apps/v1beta1" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/test/integration/framework" +) + +func TestSpecReplicasChange(t *testing.T) { + s, closeFn, rm, informers, c := scSetup(t) + defer closeFn() + ns := framework.CreateTestingNamespace("test-spec-replicas-change", s, t) + defer framework.DeleteTestingNamespace(ns, s, t) + stopCh := runControllerAndInformers(rm, informers) + defer close(stopCh) + + createHeadlessService(t, c, newHeadlessService(ns.Name)) + sts := newSTS("sts", ns.Name, 2) + stss, _ := createSTSsPods(t, c, []*v1beta1.StatefulSet{sts}, []*v1.Pod{}) + sts = stss[0] + waitSTSStable(t, c, sts) + + // Update .Spec.Replicas and verify .Status.Replicas is changed accordingly + scaleSTS(t, c, sts, 3) + scaleSTS(t, c, sts, 0) + scaleSTS(t, c, sts, 2) + + // Add a template annotation change to test STS's status does update + // without .Spec.Replicas change + stsClient := c.AppsV1beta1().StatefulSets(ns.Name) + var oldGeneration int64 + newSTS := updateSTS(t, stsClient, sts.Name, func(sts *v1beta1.StatefulSet) { + oldGeneration = sts.Generation + sts.Spec.Template.Annotations = map[string]string{"test": "annotation"} + }) + savedGeneration := newSTS.Generation + if savedGeneration == oldGeneration { + t.Fatalf("failed to verify .Generation has incremented for sts %s", sts.Name) + } + + if err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { + newSTS, err := stsClient.Get(sts.Name, metav1.GetOptions{}) + if err != nil { + return false, err + } + return *newSTS.Status.ObservedGeneration >= savedGeneration, nil + }); err != nil { + t.Fatalf("failed to verify .Status.ObservedGeneration has incremented for sts %s: %v", sts.Name, err) + } +} + +func TestDeletingAndFailedPods(t *testing.T) { + s, closeFn, rm, informers, c := scSetup(t) + defer closeFn() + ns := framework.CreateTestingNamespace("test-deleting-and-failed-pods", s, t) + defer framework.DeleteTestingNamespace(ns, s, t) + stopCh := runControllerAndInformers(rm, informers) + defer close(stopCh) + + labelMap := labelMap() + sts := newSTS("sts", ns.Name, 2) + stss, _ := createSTSsPods(t, c, []*v1beta1.StatefulSet{sts}, []*v1.Pod{}) + sts = stss[0] + waitSTSStable(t, c, sts) + + // Verify STS creates 2 pods + podClient := c.Core().Pods(ns.Name) + pods := getPods(t, podClient, labelMap) + if len(pods.Items) != 2 { + t.Fatalf("len(pods) = %d, want 2", len(pods.Items)) + } + + // Set first pod as deleting pod + // Set finalizers for the pod to simulate pending deletion status + deletingPod := &pods.Items[0] + updatePod(t, podClient, deletingPod.Name, func(pod *v1.Pod) { + pod.Finalizers = []string{"fake.example.com/blockDeletion"} + }) + if err := c.Core().Pods(ns.Name).Delete(deletingPod.Name, &metav1.DeleteOptions{}); err != nil { + t.Fatalf("error deleting pod %s: %v", deletingPod.Name, err) + } + + // Set second pod as failed pod + failedPod := &pods.Items[1] + updatePodStatus(t, podClient, failedPod.Name, func(pod *v1.Pod) { + pod.Status.Phase = v1.PodFailed + }) + + if err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { + // Verify only 2 pods exist: deleting pod and new pod replacing failed pod + pods = getPods(t, podClient, labelMap) + if len(pods.Items) != 2 { + return false, nil + } + // Verify deleting pod still exists + // Immediately return false with an error if it does not exist + if pods.Items[0].UID != deletingPod.UID && pods.Items[1].UID != deletingPod.UID { + return false, fmt.Errorf("expected deleting pod %s still exists, but it is not found", deletingPod.Name) + } + // Verify failed pod does not exist anymore + if pods.Items[0].UID == failedPod.UID || pods.Items[1].UID == failedPod.UID { + return false, nil + } + // Verify both pods have non-failed status + return pods.Items[0].Status.Phase != v1.PodFailed && pods.Items[1].Status.Phase != v1.PodFailed, nil + }); err != nil { + t.Fatalf("failed to verify failed pod %s has been replaced with a new non-failed pod, and deleting pod %s survives: %v", failedPod.Name, deletingPod.Name, err) + } + + // Remove finalizers of deleting pod to simulate successful deletion + updatePod(t, podClient, deletingPod.Name, func(pod *v1.Pod) { + pod.Finalizers = []string{} + }) + + if err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { + // Verify only 2 pods exist: new non-deleting pod replacing deleting pod and the non-failed pod + pods = getPods(t, podClient, labelMap) + if len(pods.Items) != 2 { + return false, nil + } + // Verify deleting pod does not exist anymore + return pods.Items[0].UID != deletingPod.UID && pods.Items[1].UID != deletingPod.UID, nil + }); err != nil { + t.Fatalf("failed to verify deleting pod %s has been replaced with a new non-deleting pod: %v", deletingPod.Name, err) + } +} diff --git a/vendor/k8s.io/kubernetes/test/integration/statefulset/util.go b/vendor/k8s.io/kubernetes/test/integration/statefulset/util.go new file mode 100644 index 000000000..78ee99401 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/statefulset/util.go @@ -0,0 +1,319 @@ +/* +Copyright 2018 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 statefulset + +import ( + "fmt" + "net/http/httptest" + "testing" + "time" + + "k8s.io/api/apps/v1beta1" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + typedv1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1" + typedv1 "k8s.io/client-go/kubernetes/typed/core/v1" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/util/retry" + //svc "k8s.io/kubernetes/pkg/api/v1/service" + "k8s.io/kubernetes/pkg/controller/statefulset" + "k8s.io/kubernetes/test/integration/framework" +) + +const ( + pollInterval = 100 * time.Millisecond + pollTimeout = 60 * time.Second + + fakeImageName = "fake-name" + fakeImage = "fakeimage" +) + +type statefulsetTester struct { + t *testing.T + c clientset.Interface + service *v1.Service + statefulset *v1beta1.StatefulSet +} + +func labelMap() map[string]string { + return map[string]string{"foo": "bar"} +} + +// newService returns a service with a fake name for StatefulSet to be created soon +func newHeadlessService(namespace string) *v1.Service { + return &v1.Service{ + TypeMeta: metav1.TypeMeta{ + Kind: "Service", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: "fake-service-name", + }, + Spec: v1.ServiceSpec{ + ClusterIP: "None", + Ports: []v1.ServicePort{ + {Port: 80, Name: "http", Protocol: "TCP"}, + }, + Selector: labelMap(), + }, + } +} + +// newSTS returns a StatefulSet with with a fake container image +func newSTS(name, namespace string, replicas int) *v1beta1.StatefulSet { + replicasCopy := int32(replicas) + return &v1beta1.StatefulSet{ + TypeMeta: metav1.TypeMeta{ + Kind: "StatefulSet", + APIVersion: "apps/v1beta1", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: v1beta1.StatefulSetSpec{ + PodManagementPolicy: v1beta1.ParallelPodManagement, + Replicas: &replicasCopy, + Selector: &metav1.LabelSelector{ + MatchLabels: labelMap(), + }, + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: labelMap(), + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "fake-name", + Image: "fakeimage", + VolumeMounts: []v1.VolumeMount{ + {Name: "datadir", MountPath: "/data/"}, + {Name: "home", MountPath: "/home"}, + }, + }, + }, + Volumes: []v1.Volume{ + { + Name: "datadir", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: fmt.Sprintf("/tmp/%v", "datadir"), + }, + }, + }, + { + Name: "home", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: fmt.Sprintf("/tmp/%v", "home"), + }, + }, + }, + }, + }, + }, + ServiceName: "fake-service-name", + UpdateStrategy: v1beta1.StatefulSetUpdateStrategy{ + Type: v1beta1.RollingUpdateStatefulSetStrategyType, + }, + VolumeClaimTemplates: []v1.PersistentVolumeClaim{ + // for volume mount "datadir" + newStatefulSetPVC("fake-pvc-name"), + }, + }, + } +} + +func newStatefulSetPVC(name string) v1.PersistentVolumeClaim { + return v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Annotations: map[string]string{ + "volume.alpha.kubernetes.io/storage-class": "anything", + }, + }, + Spec: v1.PersistentVolumeClaimSpec{ + AccessModes: []v1.PersistentVolumeAccessMode{ + v1.ReadWriteOnce, + }, + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceStorage: *resource.NewQuantity(1, resource.BinarySI), + }, + }, + }, + } +} + +// scSetup sets up necessities for Statefulset integration test, including master, apiserver, informers, and clientset +func scSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *statefulset.StatefulSetController, informers.SharedInformerFactory, clientset.Interface) { + masterConfig := framework.NewIntegrationTestMasterConfig() + _, s, closeFn := framework.RunAMaster(masterConfig) + + config := restclient.Config{Host: s.URL} + clientSet, err := clientset.NewForConfig(&config) + if err != nil { + t.Fatalf("error in create clientset: %v", err) + } + resyncPeriod := 12 * time.Hour + informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "statefulset-informers")), resyncPeriod) + + sc := statefulset.NewStatefulSetController( + informers.Core().V1().Pods(), + informers.Apps().V1().StatefulSets(), + informers.Core().V1().PersistentVolumeClaims(), + informers.Apps().V1().ControllerRevisions(), + clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "statefulset-controller")), + ) + + return s, closeFn, sc, informers, clientSet +} + +// Run STS controller and informers +func runControllerAndInformers(sc *statefulset.StatefulSetController, informers informers.SharedInformerFactory) chan struct{} { + stopCh := make(chan struct{}) + informers.Start(stopCh) + go sc.Run(5, stopCh) + return stopCh +} + +func createHeadlessService(t *testing.T, clientSet clientset.Interface, headlessService *v1.Service) { + _, err := clientSet.Core().Services(headlessService.Namespace).Create(headlessService) + if err != nil { + t.Fatalf("failed creating headless service: %v", err) + } +} + +func createSTSsPods(t *testing.T, clientSet clientset.Interface, stss []*v1beta1.StatefulSet, pods []*v1.Pod) ([]*v1beta1.StatefulSet, []*v1.Pod) { + var createdSTSs []*v1beta1.StatefulSet + var createdPods []*v1.Pod + for _, sts := range stss { + createdSTS, err := clientSet.AppsV1beta1().StatefulSets(sts.Namespace).Create(sts) + if err != nil { + t.Fatalf("failed to create sts %s: %v", sts.Name, err) + } + createdSTSs = append(createdSTSs, createdSTS) + } + for _, pod := range pods { + createdPod, err := clientSet.Core().Pods(pod.Namespace).Create(pod) + if err != nil { + t.Fatalf("failed to create pod %s: %v", pod.Name, err) + } + createdPods = append(createdPods, createdPod) + } + + return createdSTSs, createdPods +} + +// Verify .Status.Replicas is equal to .Spec.Replicas +func waitSTSStable(t *testing.T, clientSet clientset.Interface, sts *v1beta1.StatefulSet) { + stsClient := clientSet.AppsV1beta1().StatefulSets(sts.Namespace) + desiredGeneration := sts.Generation + if err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { + newSTS, err := stsClient.Get(sts.Name, metav1.GetOptions{}) + if err != nil { + return false, err + } + return newSTS.Status.Replicas == *newSTS.Spec.Replicas && *newSTS.Status.ObservedGeneration >= desiredGeneration, nil + }); err != nil { + t.Fatalf("failed to verify .Status.Replicas is equal to .Spec.Replicas for sts %s: %v", sts.Name, err) + } +} + +func updatePod(t *testing.T, podClient typedv1.PodInterface, podName string, updateFunc func(*v1.Pod)) *v1.Pod { + var pod *v1.Pod + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + newPod, err := podClient.Get(podName, metav1.GetOptions{}) + if err != nil { + return err + } + updateFunc(newPod) + pod, err = podClient.Update(newPod) + return err + }); err != nil { + t.Fatalf("failed to update pod %s: %v", podName, err) + } + return pod +} + +func updatePodStatus(t *testing.T, podClient typedv1.PodInterface, podName string, updateStatusFunc func(*v1.Pod)) *v1.Pod { + var pod *v1.Pod + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + newPod, err := podClient.Get(podName, metav1.GetOptions{}) + if err != nil { + return err + } + updateStatusFunc(newPod) + pod, err = podClient.UpdateStatus(newPod) + return err + }); err != nil { + t.Fatalf("failed to update status of pod %s: %v", podName, err) + } + return pod +} + +func getPods(t *testing.T, podClient typedv1.PodInterface, labelMap map[string]string) *v1.PodList { + podSelector := labels.Set(labelMap).AsSelector() + options := metav1.ListOptions{LabelSelector: podSelector.String()} + pods, err := podClient.List(options) + if err != nil { + t.Fatalf("failed obtaining a list of pods that match the pod labels %v: %v", labelMap, err) + } + if pods == nil { + t.Fatalf("obtained a nil list of pods") + } + return pods +} + +func updateSTS(t *testing.T, stsClient typedv1beta1.StatefulSetInterface, stsName string, updateFunc func(*v1beta1.StatefulSet)) *v1beta1.StatefulSet { + var sts *v1beta1.StatefulSet + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + newSTS, err := stsClient.Get(stsName, metav1.GetOptions{}) + if err != nil { + return err + } + updateFunc(newSTS) + sts, err = stsClient.Update(newSTS) + return err + }); err != nil { + t.Fatalf("failed to update sts %s: %v", stsName, err) + } + return sts +} + +// Update .Spec.Replicas to replicas and verify .Status.Replicas is changed accordingly +func scaleSTS(t *testing.T, c clientset.Interface, sts *v1beta1.StatefulSet, replicas int32) { + stsClient := c.AppsV1beta1().StatefulSets(sts.Namespace) + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + newSTS, err := stsClient.Get(sts.Name, metav1.GetOptions{}) + if err != nil { + return err + } + *newSTS.Spec.Replicas = replicas + sts, err = stsClient.Update(newSTS) + return err + }); err != nil { + t.Fatalf("failed to update .Spec.Replicas to %d for sts %s: %v", replicas, sts.Name, err) + } + waitSTSStable(t, c, sts) +} diff --git a/vendor/k8s.io/kubernetes/test/integration/storageclasses/BUILD b/vendor/k8s.io/kubernetes/test/integration/storageclasses/BUILD index b0126f6c6..035930e34 100644 --- a/vendor/k8s.io/kubernetes/test/integration/storageclasses/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/storageclasses/BUILD @@ -14,12 +14,12 @@ go_test( ], tags = ["integration"], deps = [ - "//pkg/api/testapi:go_default_library", "//test/integration/framework:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/storage/v1: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/runtime/schema:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", ], diff --git a/vendor/k8s.io/kubernetes/test/integration/storageclasses/storage_classes_test.go b/vendor/k8s.io/kubernetes/test/integration/storageclasses/storage_classes_test.go index 09f01fdad..c97b61e3d 100644 --- a/vendor/k8s.io/kubernetes/test/integration/storageclasses/storage_classes_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/storageclasses/storage_classes_test.go @@ -25,9 +25,9 @@ import ( storage "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/integration/framework" ) @@ -38,7 +38,7 @@ func TestStorageClasses(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) ns := framework.CreateTestingNamespace("storageclass", s, t) defer framework.DeleteTestingNamespace(ns, s, t) diff --git a/vendor/k8s.io/kubernetes/test/integration/tls/BUILD b/vendor/k8s.io/kubernetes/test/integration/tls/BUILD index a74e3b48b..024288b04 100644 --- a/vendor/k8s.io/kubernetes/test/integration/tls/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/tls/BUILD @@ -9,14 +9,8 @@ go_test( ], tags = ["integration"], deps = [ - "//cmd/kube-apiserver/app:go_default_library", - "//cmd/kube-apiserver/app/options:go_default_library", + "//cmd/kube-apiserver/app/testing:go_default_library", "//test/integration/framework:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/apiserver/pkg/server:go_default_library", - "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", ], ) diff --git a/vendor/k8s.io/kubernetes/test/integration/tls/ciphers_test.go b/vendor/k8s.io/kubernetes/test/integration/tls/ciphers_test.go index 45925719c..070960e38 100644 --- a/vendor/k8s.io/kubernetes/test/integration/tls/ciphers_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/tls/ciphers_test.go @@ -19,108 +19,26 @@ package tls import ( "crypto/tls" "fmt" - "io/ioutil" - "net" "net/http" - "os" - "sync/atomic" + "strings" "testing" - "time" - "k8s.io/apimachinery/pkg/util/wait" - genericapiserver "k8s.io/apiserver/pkg/server" - genericapiserveroptions "k8s.io/apiserver/pkg/server/options" - client "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/kubernetes/cmd/kube-apiserver/app" - "k8s.io/kubernetes/cmd/kube-apiserver/app/options" + kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" "k8s.io/kubernetes/test/integration/framework" ) -func runBasicSecureAPIServer(t *testing.T, ciphers []string) (uint32, error) { - certDir, _ := ioutil.TempDir("", "test-integration-tls") - defer os.RemoveAll(certDir) - _, defaultServiceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24") - kubeClientConfigValue := atomic.Value{} - var kubePort uint32 - - go func() { - listener, port, err := genericapiserveroptions.CreateListener("tcp", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - - atomic.StoreUint32(&kubePort, uint32(port)) - - kubeAPIServerOptions := options.NewServerRunOptions() - kubeAPIServerOptions.SecureServing.BindAddress = net.ParseIP("127.0.0.1") - kubeAPIServerOptions.SecureServing.BindPort = port - kubeAPIServerOptions.SecureServing.Listener = listener - kubeAPIServerOptions.SecureServing.ServerCert.CertDirectory = certDir - kubeAPIServerOptions.SecureServing.CipherSuites = ciphers - kubeAPIServerOptions.InsecureServing.BindPort = 0 - kubeAPIServerOptions.Etcd.StorageConfig.ServerList = []string{framework.GetEtcdURL()} - kubeAPIServerOptions.ServiceClusterIPRange = *defaultServiceClusterIPRange - - tunneler, proxyTransport, err := app.CreateNodeDialer(kubeAPIServerOptions) - if err != nil { - t.Fatal(err) - } - kubeAPIServerConfig, sharedInformers, versionedInformers, _, _, _, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions, tunneler, proxyTransport) - if err != nil { - t.Fatal(err) - } - kubeAPIServerConfig.ExtraConfig.EnableCoreControllers = false - kubeClientConfigValue.Store(kubeAPIServerConfig.GenericConfig.LoopbackClientConfig) - - kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.EmptyDelegate, sharedInformers, versionedInformers) - if err != nil { - t.Fatal(err) - } - - if err := kubeAPIServer.GenericAPIServer.PrepareRun().Run(wait.NeverStop); err != nil { - t.Log(err) - } - time.Sleep(100 * time.Millisecond) - }() - - // Ensure server is ready - err := wait.PollImmediate(100*time.Millisecond, 10*time.Second, func() (done bool, err error) { - obj := kubeClientConfigValue.Load() - if obj == nil { - return false, nil - } - kubeClientConfig := kubeClientConfigValue.Load().(*rest.Config) - kubeClientConfig.ContentType = "" - kubeClientConfig.AcceptContentTypes = "" - kubeClient, err := client.NewForConfig(kubeClientConfig) - if err != nil { - // this happens because we race the API server start - t.Log(err) - return false, nil - } - if _, err := kubeClient.Discovery().ServerVersion(); err != nil { - return false, nil - } - return true, nil - }) - if err != nil { - return 0, err - } - - securePort := atomic.LoadUint32(&kubePort) - return securePort, nil +func runBasicSecureAPIServer(t *testing.T, ciphers []string) (kubeapiservertesting.TearDownFunc, int) { + flags := []string{"--tls-cipher-suites", strings.Join(ciphers, ",")} + testServer := kubeapiservertesting.StartTestServerOrDie(t, nil, flags, framework.SharedEtcd()) + return testServer.TearDownFn, testServer.ServerOpts.SecureServing.BindPort } func TestAPICiphers(t *testing.T) { basicServerCiphers := []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"} - kubePort, err := runBasicSecureAPIServer(t, basicServerCiphers) - if err != nil { - t.Fatal(err) - } - + tearDown, port := runBasicSecureAPIServer(t, basicServerCiphers) + defer tearDown() tests := []struct { clientCiphers []uint16 expectedError bool @@ -138,11 +56,11 @@ func TestAPICiphers(t *testing.T) { } for i, test := range tests { - runTestAPICiphers(t, i, kubePort, test.clientCiphers, test.expectedError) + runTestAPICiphers(t, i, port, test.clientCiphers, test.expectedError) } } -func runTestAPICiphers(t *testing.T, testID int, kubePort uint32, clientCiphers []uint16, expectedError bool) { +func runTestAPICiphers(t *testing.T, testID int, kubePort int, clientCiphers []uint16, expectedError bool) { tr := &http.Transport{ TLSClientConfig: &tls.Config{ @@ -156,14 +74,13 @@ func runTestAPICiphers(t *testing.T, testID int, kubePort uint32, clientCiphers t.Fatal(err) } resp, err := client.Do(req) + if err == nil { + defer resp.Body.Close() + } if expectedError == true && err == nil { t.Fatalf("%d: expecting error for cipher test, client cipher is supported and it should't", testID) } else if err != nil && expectedError == false { t.Fatalf("%d: not expecting error by client with cipher failed: %+v", testID, err) } - - if err == nil { - defer resp.Body.Close() - } } diff --git a/vendor/k8s.io/kubernetes/test/integration/util/BUILD b/vendor/k8s.io/kubernetes/test/integration/util/BUILD index fe7d7bc6c..e6edbe9dc 100644 --- a/vendor/k8s.io/kubernetes/test/integration/util/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/util/BUILD @@ -8,16 +8,22 @@ load( go_library( name = "go_default_library", srcs = [ + "cloud.go", "util.go", ], importpath = "k8s.io/kubernetes/test/integration/util", deps = [ "//pkg/api/legacyscheme:go_default_library", + "//pkg/cloudprovider/providers/gce:go_default_library", + "//pkg/cloudprovider/providers/gce/cloud:go_default_library", + "//pkg/features:go_default_library", "//pkg/scheduler:go_default_library", "//pkg/scheduler/factory:go_default_library", "//test/integration/framework:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/golang.org/x/oauth2:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/util/cloud.go b/vendor/k8s.io/kubernetes/test/integration/util/cloud.go new file mode 100644 index 000000000..d5c758d4a --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/integration/util/cloud.go @@ -0,0 +1,72 @@ +/* +Copyright 2018 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 ( + "time" + + "golang.org/x/oauth2" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" +) + +const ( + // TestProjectID is the project id used for creating NewMockGCECloud + TestProjectID = "test-project" + // TestNetworkProjectID is the network project id for creating NewMockGCECloud + TestNetworkProjectID = "net-test-project" + // TestRegion is the region for creating NewMockGCECloud + TestRegion = "test-region" + // TestZone is the zone for creating NewMockGCECloud + TestZone = "test-zone" + // TestNetworkName is the network name for creating NewMockGCECloud + TestNetworkName = "test-network" + // TestSubnetworkName is the sub network name for creating NewMockGCECloud + TestSubnetworkName = "test-sub-network" + // TestSecondaryRangeName is the secondary range name for creating NewMockGCECloud + TestSecondaryRangeName = "test-secondary-range" +) + +type mockTokenSource struct{} + +func (*mockTokenSource) Token() (*oauth2.Token, error) { + return &oauth2.Token{ + AccessToken: "access", + TokenType: "Bearer", + RefreshToken: "refresh", + Expiry: time.Now().Add(1 * time.Hour), + }, nil +} + +// NewMockGCECloud returns a handle to a GCECloud instance that is +// served by a mock http server +func NewMockGCECloud(cloud cloud.Cloud) (*gce.GCECloud, error) { + config := &gce.CloudConfig{ + ProjectID: TestProjectID, + NetworkProjectID: TestNetworkProjectID, + Region: TestRegion, + Zone: TestZone, + ManagedZones: []string{TestZone}, + NetworkName: TestNetworkName, + SubnetworkName: TestSubnetworkName, + SecondaryRangeName: TestSecondaryRangeName, + NodeTags: []string{}, + UseMetadataServer: false, + TokenSource: &mockTokenSource{}, + } + return gce.CreateGCECloudWithCloud(config, cloud) +} diff --git a/vendor/k8s.io/kubernetes/test/integration/util/util.go b/vendor/k8s.io/kubernetes/test/integration/util/util.go index ceb28e78b..705abbfc0 100644 --- a/vendor/k8s.io/kubernetes/test/integration/util/util.go +++ b/vendor/k8s.io/kubernetes/test/integration/util/util.go @@ -22,11 +22,13 @@ import ( "github.com/golang/glog" "k8s.io/api/core/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" clientv1core "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler" "k8s.io/kubernetes/pkg/scheduler/factory" "k8s.io/kubernetes/test/integration/framework" @@ -56,29 +58,14 @@ func StartApiserver() (string, ShutdownFunc) { // StartScheduler configures and starts a scheduler given a handle to the clientSet interface // and event broadcaster. It returns a handle to the configurator for the running scheduler // and the shutdown function to stop it. -func StartScheduler(clientSet clientset.Interface, enableEquivalenceCache bool) (scheduler.Configurator, ShutdownFunc) { +func StartScheduler(clientSet clientset.Interface) (scheduler.Configurator, ShutdownFunc) { informerFactory := informers.NewSharedInformerFactory(clientSet, 0) evtBroadcaster := record.NewBroadcaster() evtWatch := evtBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{ - Interface: clientv1core.New(clientSet.CoreV1().RESTClient()).Events("")}) + Interface: clientSet.CoreV1().Events("")}) - schedulerConfigurator := factory.NewConfigFactory( - v1.DefaultSchedulerName, - clientSet, - informerFactory.Core().V1().Nodes(), - informerFactory.Core().V1().Pods(), - informerFactory.Core().V1().PersistentVolumes(), - informerFactory.Core().V1().PersistentVolumeClaims(), - informerFactory.Core().V1().ReplicationControllers(), - informerFactory.Extensions().V1beta1().ReplicaSets(), - informerFactory.Apps().V1beta1().StatefulSets(), - informerFactory.Core().V1().Services(), - informerFactory.Policy().V1beta1().PodDisruptionBudgets(), - informerFactory.Storage().V1().StorageClasses(), - v1.DefaultHardPodAffinitySymmetricWeight, - enableEquivalenceCache, - ) + schedulerConfigurator := createSchedulerConfigurator(clientSet, informerFactory) sched, err := scheduler.NewFromConfigurator(schedulerConfigurator, func(conf *scheduler.Config) { conf.Recorder = evtBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: "scheduler"}) @@ -101,3 +88,30 @@ func StartScheduler(clientSet clientset.Interface, enableEquivalenceCache bool) } return schedulerConfigurator, shutdownFunc } + +// createSchedulerConfigurator create a configurator for scheduler with given informer factory and default name. +func createSchedulerConfigurator( + clientSet clientset.Interface, + informerFactory informers.SharedInformerFactory, +) scheduler.Configurator { + // Enable EnableEquivalenceClassCache for all integration tests. + utilfeature.DefaultFeatureGate.Set("EnableEquivalenceClassCache=true") + + return factory.NewConfigFactory( + v1.DefaultSchedulerName, + clientSet, + informerFactory.Core().V1().Nodes(), + informerFactory.Core().V1().Pods(), + informerFactory.Core().V1().PersistentVolumes(), + informerFactory.Core().V1().PersistentVolumeClaims(), + informerFactory.Core().V1().ReplicationControllers(), + informerFactory.Extensions().V1beta1().ReplicaSets(), + informerFactory.Apps().V1beta1().StatefulSets(), + informerFactory.Core().V1().Services(), + informerFactory.Policy().V1beta1().PodDisruptionBudgets(), + informerFactory.Storage().V1().StorageClasses(), + v1.DefaultHardPodAffinitySymmetricWeight, + utilfeature.DefaultFeatureGate.Enabled(features.EnableEquivalenceClassCache), + false, + ) +} diff --git a/vendor/k8s.io/kubernetes/test/integration/volume/BUILD b/vendor/k8s.io/kubernetes/test/integration/volume/BUILD index 0f21d354e..374000e12 100644 --- a/vendor/k8s.io/kubernetes/test/integration/volume/BUILD +++ b/vendor/k8s.io/kubernetes/test/integration/volume/BUILD @@ -16,11 +16,11 @@ go_test( tags = ["integration"], deps = [ "//pkg/api/legacyscheme:go_default_library", - "//pkg/api/testapi:go_default_library", "//pkg/cloudprovider/providers/fake:go_default_library", "//pkg/controller/volume/attachdetach:go_default_library", "//pkg/controller/volume/attachdetach/cache:go_default_library", "//pkg/controller/volume/persistentvolume:go_default_library", + "//pkg/controller/volume/persistentvolume/options:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/testing:go_default_library", "//pkg/volume/util:go_default_library", @@ -30,6 +30,7 @@ go_test( "//vendor/k8s.io/api/storage/v1: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/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/integration/volume/attach_detach_test.go b/vendor/k8s.io/kubernetes/test/integration/volume/attach_detach_test.go index b4de32de0..5b12d706f 100644 --- a/vendor/k8s.io/kubernetes/test/integration/volume/attach_detach_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/volume/attach_detach_test.go @@ -17,21 +17,25 @@ limitations under the License. package volume import ( + "fmt" "net/http/httptest" "testing" "time" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" - "k8s.io/kubernetes/pkg/api/testapi" fakecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/fake" "k8s.io/kubernetes/pkg/controller/volume/attachdetach" volumecache "k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache" + "k8s.io/kubernetes/pkg/controller/volume/persistentvolume" + persistentvolumeoptions "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/options" "k8s.io/kubernetes/pkg/volume" volumetest "k8s.io/kubernetes/pkg/volume/testing" "k8s.io/kubernetes/pkg/volume/util" @@ -73,8 +77,68 @@ func fakePodWithVol(namespace string) *v1.Pod { return fakePod } +func fakePodWithPVC(name, pvcName, namespace string) (*v1.Pod, *v1.PersistentVolumeClaim) { + fakePod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "fake-container", + Image: "nginx", + VolumeMounts: []v1.VolumeMount{ + { + Name: "fake-mount", + MountPath: "/var/www/html", + }, + }, + }, + }, + Volumes: []v1.Volume{ + { + Name: "fake-mount", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvcName, + }, + }, + }, + }, + NodeName: "node-sandbox", + }, + } + class := "fake-sc" + fakePVC := &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: pvcName, + }, + Spec: v1.PersistentVolumeClaimSpec{ + AccessModes: []v1.PersistentVolumeAccessMode{ + v1.ReadWriteOnce, + }, + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceName(v1.ResourceStorage): resource.MustParse("5Gi"), + }, + }, + StorageClassName: &class, + }, + } + return fakePod, fakePVC +} + type podCountFunc func(int) bool +var defaultTimerConfig = attachdetach.TimerConfig{ + ReconcilerLoopPeriod: 100 * time.Millisecond, + ReconcilerMaxWaitForUnmountDuration: 6 * time.Second, + DesiredStateOfWorldPopulatorLoopSleepPeriod: 1 * time.Second, + DesiredStateOfWorldPopulatorListPodsRetryDuration: 3 * time.Second, +} + // Via integration test we can verify that if pod delete // event is somehow missed by AttachDetach controller - it still // gets cleaned up by Desired State of World populator. @@ -94,7 +158,7 @@ func TestPodDeletionWithDswp(t *testing.T) { ns := framework.CreateTestingNamespace(namespaceName, server, t) defer framework.DeleteTestingNamespace(ns, server, t) - testClient, ctrl, informers := createAdClients(ns, t, server, defaultSyncPeriod) + testClient, ctrl, _, informers := createAdClients(ns, t, server, defaultSyncPeriod, defaultTimerConfig) pod := fakePodWithVol(namespaceName) podStopCh := make(chan struct{}) @@ -160,7 +224,7 @@ func TestPodUpdateWithWithADC(t *testing.T) { ns := framework.CreateTestingNamespace(namespaceName, server, t) defer framework.DeleteTestingNamespace(ns, server, t) - testClient, ctrl, informers := createAdClients(ns, t, server, defaultSyncPeriod) + testClient, ctrl, _, informers := createAdClients(ns, t, server, defaultSyncPeriod, defaultTimerConfig) pod := fakePodWithVol(namespaceName) podStopCh := make(chan struct{}) @@ -228,7 +292,7 @@ func TestPodUpdateWithKeepTerminatedPodVolumes(t *testing.T) { ns := framework.CreateTestingNamespace(namespaceName, server, t) defer framework.DeleteTestingNamespace(ns, server, t) - testClient, ctrl, informers := createAdClients(ns, t, server, defaultSyncPeriod) + testClient, ctrl, _, informers := createAdClients(ns, t, server, defaultSyncPeriod, defaultTimerConfig) pod := fakePodWithVol(namespaceName) podStopCh := make(chan struct{}) @@ -320,10 +384,10 @@ func waitForPodFuncInDSWP(t *testing.T, dswp volumecache.DesiredStateOfWorld, ch } } -func createAdClients(ns *v1.Namespace, t *testing.T, server *httptest.Server, syncPeriod time.Duration) (*clientset.Clientset, attachdetach.AttachDetachController, informers.SharedInformerFactory) { +func createAdClients(ns *v1.Namespace, t *testing.T, server *httptest.Server, syncPeriod time.Duration, timers attachdetach.TimerConfig) (*clientset.Clientset, attachdetach.AttachDetachController, *persistentvolume.PersistentVolumeController, informers.SharedInformerFactory) { config := restclient.Config{ Host: server.URL, - ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}, + ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, QPS: 1000000, Burst: 1000000, } @@ -346,12 +410,6 @@ func createAdClients(ns *v1.Namespace, t *testing.T, server *httptest.Server, sy plugins := []volume.VolumePlugin{plugin} cloud := &fakecloud.FakeCloud{} informers := informers.NewSharedInformerFactory(testClient, resyncPeriod) - timers := attachdetach.TimerConfig{ - ReconcilerLoopPeriod: 100 * time.Millisecond, - ReconcilerMaxWaitForUnmountDuration: 6 * time.Second, - DesiredStateOfWorldPopulatorLoopSleepPeriod: 1 * time.Second, - DesiredStateOfWorldPopulatorListPodsRetryDuration: 3 * time.Second, - } ctrl, err := attachdetach.NewAttachDetachController( testClient, informers.Core().V1().Pods(), @@ -368,7 +426,27 @@ func createAdClients(ns *v1.Namespace, t *testing.T, server *httptest.Server, sy if err != nil { t.Fatalf("Error creating AttachDetach : %v", err) } - return testClient, ctrl, informers + + // create pv controller + controllerOptions := persistentvolumeoptions.NewPersistentVolumeControllerOptions() + params := persistentvolume.ControllerParameters{ + KubeClient: testClient, + SyncPeriod: controllerOptions.PVClaimBinderSyncPeriod, + VolumePlugins: plugins, + Cloud: nil, + ClusterName: "volume-test-cluster", + VolumeInformer: informers.Core().V1().PersistentVolumes(), + ClaimInformer: informers.Core().V1().PersistentVolumeClaims(), + ClassInformer: informers.Storage().V1().StorageClasses(), + PodInformer: informers.Core().V1().Pods(), + NodeInformer: informers.Core().V1().Nodes(), + EnableDynamicProvisioning: false, + } + pvCtrl, err := persistentvolume.NewController(params) + if err != nil { + t.Fatalf("Failed to create PV controller: %v", err) + } + return testClient, ctrl, pvCtrl, informers } // Via integration test we can verify that if pod add @@ -391,7 +469,7 @@ func TestPodAddedByDswp(t *testing.T) { ns := framework.CreateTestingNamespace(namespaceName, server, t) defer framework.DeleteTestingNamespace(ns, server, t) - testClient, ctrl, informers := createAdClients(ns, t, server, defaultSyncPeriod) + testClient, ctrl, _, informers := createAdClients(ns, t, server, defaultSyncPeriod, defaultTimerConfig) pod := fakePodWithVol(namespaceName) podStopCh := make(chan struct{}) @@ -446,3 +524,91 @@ func TestPodAddedByDswp(t *testing.T) { close(stopCh) } + +func TestPVCBoundWithADC(t *testing.T) { + _, server, closeFn := framework.RunAMaster(framework.NewIntegrationTestMasterConfig()) + defer closeFn() + namespaceName := "test-pod-deletion" + + ns := framework.CreateTestingNamespace(namespaceName, server, t) + defer framework.DeleteTestingNamespace(ns, server, t) + + testClient, ctrl, pvCtrl, informers := createAdClients(ns, t, server, defaultSyncPeriod, attachdetach.TimerConfig{ + ReconcilerLoopPeriod: 100 * time.Millisecond, + ReconcilerMaxWaitForUnmountDuration: 6 * time.Second, + DesiredStateOfWorldPopulatorLoopSleepPeriod: 24 * time.Hour, + // Use high duration to disable DesiredStateOfWorldPopulator.findAndAddActivePods loop in test. + DesiredStateOfWorldPopulatorListPodsRetryDuration: 24 * time.Hour, + }) + + node := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node-sandbox", + Annotations: map[string]string{ + util.ControllerManagedAttachAnnotation: "true", + }, + }, + } + if _, err := testClient.Core().Nodes().Create(node); err != nil { + t.Fatalf("Failed to created node : %v", err) + } + + // pods with pvc not bound + pvcs := []*v1.PersistentVolumeClaim{} + for i := 0; i < 3; i++ { + pod, pvc := fakePodWithPVC(fmt.Sprintf("fakepod-pvcnotbound-%d", i), fmt.Sprintf("fakepvc-%d", i), namespaceName) + if _, err := testClient.Core().Pods(pod.Namespace).Create(pod); err != nil { + t.Errorf("Failed to create pod : %v", err) + } + if _, err := testClient.Core().PersistentVolumeClaims(pvc.Namespace).Create(pvc); err != nil { + t.Errorf("Failed to create pvc : %v", err) + } + pvcs = append(pvcs, pvc) + } + // pod with no pvc + podNew := fakePodWithVol(namespaceName) + podNew.SetName("fakepod") + if _, err := testClient.Core().Pods(podNew.Namespace).Create(podNew); err != nil { + t.Errorf("Failed to create pod : %v", err) + } + + // start controller loop + stopCh := make(chan struct{}) + informers.Start(stopCh) + informers.WaitForCacheSync(stopCh) + go ctrl.Run(stopCh) + go pvCtrl.Run(stopCh) + + waitToObservePods(t, informers.Core().V1().Pods().Informer(), 4) + // Give attachdetach controller enough time to populate pods into DSWP. + time.Sleep(10 * time.Second) + waitForPodFuncInDSWP(t, ctrl.GetDesiredStateOfWorld(), 60*time.Second, "expected 1 pod in dsw", 1) + for _, pvc := range pvcs { + createPVForPVC(t, testClient, pvc) + } + waitForPodFuncInDSWP(t, ctrl.GetDesiredStateOfWorld(), 60*time.Second, "expected 4 pods in dsw after PVCs are bound", 4) + close(stopCh) +} + +// Create PV for PVC, pv controller will bind them together. +func createPVForPVC(t *testing.T, testClient *clientset.Clientset, pvc *v1.PersistentVolumeClaim) { + pv := &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("fakepv-%s", pvc.Name), + }, + Spec: v1.PersistentVolumeSpec{ + Capacity: pvc.Spec.Resources.Requests, + AccessModes: pvc.Spec.AccessModes, + PersistentVolumeSource: v1.PersistentVolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: "/var/www/html", + }, + }, + ClaimRef: &v1.ObjectReference{Name: pvc.Name, Namespace: pvc.Namespace}, + StorageClassName: *pvc.Spec.StorageClassName, + }, + } + if _, err := testClient.Core().PersistentVolumes().Create(pv); err != nil { + t.Errorf("Failed to create pv : %v", err) + } +} diff --git a/vendor/k8s.io/kubernetes/test/integration/volume/persistent_volumes_test.go b/vendor/k8s.io/kubernetes/test/integration/volume/persistent_volumes_test.go index 0739336f0..189af2bb5 100644 --- a/vendor/k8s.io/kubernetes/test/integration/volume/persistent_volumes_test.go +++ b/vendor/k8s.io/kubernetes/test/integration/volume/persistent_volumes_test.go @@ -35,7 +35,6 @@ import ( restclient "k8s.io/client-go/rest" ref "k8s.io/client-go/tools/reference" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/api/testapi" fakecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/fake" persistentvolumecontroller "k8s.io/kubernetes/pkg/controller/volume/persistentvolume" "k8s.io/kubernetes/pkg/volume" @@ -43,6 +42,7 @@ import ( "k8s.io/kubernetes/test/integration/framework" "github.com/golang/glog" + "k8s.io/apimachinery/pkg/runtime/schema" ) // Several tests in this file are configurable by environment variables: @@ -1099,13 +1099,13 @@ func createClients(ns *v1.Namespace, t *testing.T, s *httptest.Server, syncPerio // creates many objects and default values were too low. binderClient := clientset.NewForConfigOrDie(&restclient.Config{ Host: s.URL, - ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}, + ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, QPS: 1000000, Burst: 1000000, }) testClient := clientset.NewForConfigOrDie(&restclient.Config{ Host: s.URL, - ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[v1.GroupName].GroupVersion()}, + ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, QPS: 1000000, Burst: 1000000, }) @@ -1136,6 +1136,7 @@ func createClients(ns *v1.Namespace, t *testing.T, s *httptest.Server, syncPerio ClaimInformer: informers.Core().V1().PersistentVolumeClaims(), ClassInformer: informers.Storage().V1().StorageClasses(), PodInformer: informers.Core().V1().Pods(), + NodeInformer: informers.Core().V1().Nodes(), EnableDynamicProvisioning: true, }) if err != nil { diff --git a/vendor/k8s.io/kubernetes/test/kubemark/cloud-provider-config.sh b/vendor/k8s.io/kubernetes/test/kubemark/cloud-provider-config.sh index 79d760ef4..ad7029f23 100755 --- a/vendor/k8s.io/kubernetes/test/kubemark/cloud-provider-config.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/cloud-provider-config.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # @@ -17,5 +17,5 @@ CLOUD_PROVIDER="${CLOUD_PROVIDER:-gce}" CONTAINER_REGISTRY="${CONTAINER_REGISTRY:-gcr.io}" PROJECT="${PROJECT:-}" -FULL_REGISTRY="${CONTAINER_REGISTRY}/${PROJECT}" +KUBEMARK_IMAGE_REGISTRY="${KUBEMARK_IMAGE_REGISTRY:-}" KUBEMARK_IMAGE_MAKE_TARGET="${KUBEMARK_IMAGE_MAKE_TARGET:-gcloudpush}" diff --git a/vendor/k8s.io/kubernetes/test/kubemark/common/util.sh b/vendor/k8s.io/kubernetes/test/kubemark/common/util.sh index d3c035776..2c7e7c119 100644 --- a/vendor/k8s.io/kubernetes/test/kubemark/common/util.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/common/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/kubemark/configure-kubectl.sh b/vendor/k8s.io/kubernetes/test/kubemark/configure-kubectl.sh index 3a55de67d..eec173b2a 100755 --- a/vendor/k8s.io/kubernetes/test/kubemark/configure-kubectl.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/configure-kubectl.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/kubemark/gce/util.sh b/vendor/k8s.io/kubernetes/test/kubemark/gce/util.sh index 8e4cc9af0..398913779 100644 --- a/vendor/k8s.io/kubernetes/test/kubemark/gce/util.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/gce/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/kubemark/master-log-dump.sh b/vendor/k8s.io/kubernetes/test/kubemark/master-log-dump.sh index 35b04d6d3..beaf8ed73 100755 --- a/vendor/k8s.io/kubernetes/test/kubemark/master-log-dump.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/master-log-dump.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/kubemark/pre-existing/util.sh b/vendor/k8s.io/kubernetes/test/kubemark/pre-existing/util.sh index 107c92126..22be79135 100644 --- a/vendor/k8s.io/kubernetes/test/kubemark/pre-existing/util.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/pre-existing/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/kubemark/resources/hollow-node_template.yaml b/vendor/k8s.io/kubernetes/test/kubemark/resources/hollow-node_template.yaml index 0207d06d6..b15c11f30 100644 --- a/vendor/k8s.io/kubernetes/test/kubemark/resources/hollow-node_template.yaml +++ b/vendor/k8s.io/kubernetes/test/kubemark/resources/hollow-node_template.yaml @@ -35,7 +35,7 @@ spec: emptyDir: {} containers: - name: hollow-kubelet - image: {{full_registry}}/kubemark:{{kubemark_image_tag}} + image: {{kubemark_image_registry}}/kubemark:{{kubemark_image_tag}} ports: - containerPort: 4194 - containerPort: 10250 @@ -67,7 +67,7 @@ spec: securityContext: privileged: true - name: hollow-proxy - image: {{full_registry}}/kubemark:{{kubemark_image_tag}} + image: {{kubemark_image_registry}}/kubemark:{{kubemark_image_tag}} env: - name: CONTENT_TYPE valueFrom: diff --git a/vendor/k8s.io/kubernetes/test/kubemark/resources/kube_dns_template.yaml b/vendor/k8s.io/kubernetes/test/kubemark/resources/kube_dns_template.yaml new file mode 100644 index 000000000..19a16d7d6 --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/kubemark/resources/kube_dns_template.yaml @@ -0,0 +1,187 @@ +apiVersion: v1 +kind: Service +metadata: + name: kube-dns + namespace: kubemark + labels: + k8s-app: kube-dns + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile + kubernetes.io/name: "KubeDNS" +spec: + selector: + k8s-app: kube-dns + ports: + - name: dns + port: 53 + protocol: UDP + - name: dns-tcp + port: 53 + protocol: TCP +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kube-dns + namespace: kubemark + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: kube-dns + namespace: kubemark + labels: + addonmanager.kubernetes.io/mode: EnsureExists +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: kube-dns + namespace: kubemark + labels: + k8s-app: kube-dns + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +spec: + strategy: + rollingUpdate: + maxSurge: 10% + maxUnavailable: 0 + selector: + matchLabels: + k8s-app: kube-dns + template: + metadata: + labels: + k8s-app: kube-dns + annotations: + scheduler.alpha.kubernetes.io/critical-pod: '' + spec: + tolerations: + - key: "CriticalAddonsOnly" + operator: "Exists" + volumes: + - name: kube-dns-config + configMap: + name: kube-dns + optional: true + - name: secret-volume + secret: + secretName: kubeconfig + containers: + - name: kubedns + image: k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.9 + resources: + limits: + memory: 170Mi + requests: + cpu: 100m + memory: 70Mi + livenessProbe: + httpGet: + path: /healthcheck/kubedns + port: 10054 + scheme: HTTP + initialDelaySeconds: 60 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + readinessProbe: + httpGet: + path: /readiness + port: 8081 + scheme: HTTP + initialDelaySeconds: 3 + timeoutSeconds: 5 + args: + - --domain={{dns_domain}}. + - --dns-port=10053 + - --config-dir=/kube-dns-config + - --kubecfg-file=/etc/secret-volume/dns.kubeconfig + - --v=2 + env: + - name: PROMETHEUS_PORT + value: "10055" + ports: + - containerPort: 10053 + name: dns-local + protocol: UDP + - containerPort: 10053 + name: dns-tcp-local + protocol: TCP + - containerPort: 10055 + name: metrics + protocol: TCP + volumeMounts: + - name: kube-dns-config + mountPath: /kube-dns-config + - name: secret-volume + mountPath: /etc/secret-volume + - name: dnsmasq + image: k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.9 + livenessProbe: + httpGet: + path: /healthcheck/dnsmasq + port: 10054 + scheme: HTTP + initialDelaySeconds: 60 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + args: + - -v=2 + - -logtostderr + - -configDir=/etc/k8s/dns/dnsmasq-nanny + - -restartDnsmasq=true + - -- + - -k + - --cache-size=1000 + - --no-negcache + - --log-facility=- + - --server=/{{dns_domain}}/127.0.0.1#10053 + - --server=/in-addr.arpa/127.0.0.1#10053 + - --server=/ip6.arpa/127.0.0.1#10053 + ports: + - containerPort: 53 + name: dns + protocol: UDP + - containerPort: 53 + name: dns-tcp + protocol: TCP + # see: https://github.com/kubernetes/kubernetes/issues/29055 for details + resources: + requests: + cpu: 150m + memory: 20Mi + volumeMounts: + - name: kube-dns-config + mountPath: /etc/k8s/dns/dnsmasq-nanny + - name: sidecar + image: k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.9 + livenessProbe: + httpGet: + path: /metrics + port: 10054 + scheme: HTTP + initialDelaySeconds: 60 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + args: + - --v=2 + - --logtostderr + - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.{{dns_domain}},5,SRV + - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.{{dns_domain}},5,SRV + ports: + - containerPort: 10054 + name: metrics + protocol: TCP + resources: + requests: + memory: 20Mi + cpu: 10m + dnsPolicy: Default # Don't use cluster DNS. + serviceAccountName: kube-dns diff --git a/vendor/k8s.io/kubernetes/test/kubemark/resources/manifests/addons/kubemark-rbac-bindings/kube-dns-binding.yaml b/vendor/k8s.io/kubernetes/test/kubemark/resources/manifests/addons/kubemark-rbac-bindings/kube-dns-binding.yaml new file mode 100644 index 000000000..3f9b0d3df --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/kubemark/resources/manifests/addons/kubemark-rbac-bindings/kube-dns-binding.yaml @@ -0,0 +1,15 @@ +# This is the role binding for the kubemark kube-dns. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kube-dns-view-binding + labels: + kubernetes.io/cluster-service: "true" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:kube-dns +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: User + name: system:kube-dns diff --git a/vendor/k8s.io/kubernetes/test/kubemark/resources/start-kubemark-master.sh b/vendor/k8s.io/kubernetes/test/kubemark/resources/start-kubemark-master.sh index fd2b900f0..a9465d6d5 100755 --- a/vendor/k8s.io/kubernetes/test/kubemark/resources/start-kubemark-master.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/resources/start-kubemark-master.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -529,6 +529,11 @@ function compute-kube-apiserver-params { if [[ -n "${KUBE_APISERVER_REQUEST_TIMEOUT:-}" ]]; then params+=" --min-request-timeout=${KUBE_APISERVER_REQUEST_TIMEOUT}" fi + if [[ "${NUM_NODES}" -ge 3000 ]]; then + params+=" --max-requests-inflight=3000 --max-mutating-requests-inflight=1000" + elif [[ "${NUM_NODES}" -ge 1000 ]]; then + params+=" --max-requests-inflight=1500 --max-mutating-requests-inflight=500" + fi if [[ -n "${RUNTIME_CONFIG:-}" ]]; then params+=" --runtime-config=${RUNTIME_CONFIG}" fi diff --git a/vendor/k8s.io/kubernetes/test/kubemark/run-e2e-tests.sh b/vendor/k8s.io/kubernetes/test/kubemark/run-e2e-tests.sh index 17e1ef802..d110c34b8 100755 --- a/vendor/k8s.io/kubernetes/test/kubemark/run-e2e-tests.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/run-e2e-tests.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/kubemark/skeleton/util.sh b/vendor/k8s.io/kubernetes/test/kubemark/skeleton/util.sh index 4998057c8..d646b3d9f 100644 --- a/vendor/k8s.io/kubernetes/test/kubemark/skeleton/util.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/skeleton/util.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2017 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/kubemark/start-kubemark.sh b/vendor/k8s.io/kubernetes/test/kubemark/start-kubemark.sh index 6566b8972..b8236bc13 100755 --- a/vendor/k8s.io/kubernetes/test/kubemark/start-kubemark.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/start-kubemark.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # @@ -59,7 +59,7 @@ SERVICE_CLUSTER_IP_RANGE="${SERVICE_CLUSTER_IP_RANGE:-}" EVENT_PD="${EVENT_PD:-}" # Etcd related variables. -ETCD_IMAGE="${ETCD_IMAGE:-3.1.12}" +ETCD_IMAGE="${ETCD_IMAGE:-3.2.18-0}" ETCD_VERSION="${ETCD_VERSION:-}" # Controller-manager related variables. @@ -99,6 +99,7 @@ function generate-pki-config { NODE_PROBLEM_DETECTOR_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) HEAPSTER_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) CLUSTER_AUTOSCALER_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) + KUBE_DNS_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null) echo "Generated PKI authentication data for kubemark." } @@ -126,6 +127,7 @@ function write-pki-config-to-master { sudo bash -c \"echo \"${HEAPSTER_TOKEN},system:heapster,uid:heapster\" >> /home/kubernetes/k8s_auth_data/known_tokens.csv\" && \ sudo bash -c \"echo \"${CLUSTER_AUTOSCALER_TOKEN},system:cluster-autoscaler,uid:cluster-autoscaler\" >> /home/kubernetes/k8s_auth_data/known_tokens.csv\" && \ sudo bash -c \"echo \"${NODE_PROBLEM_DETECTOR_TOKEN},system:node-problem-detector,uid:system:node-problem-detector\" >> /home/kubernetes/k8s_auth_data/known_tokens.csv\" && \ + sudo bash -c \"echo \"${KUBE_DNS_TOKEN},system:kube-dns,uid:kube-dns\" >> /home/kubernetes/k8s_auth_data/known_tokens.csv\" && \ sudo bash -c \"echo ${KUBE_PASSWORD},admin,admin > /home/kubernetes/k8s_auth_data/basic_auth.csv\"" execute-cmd-on-master-with-retries "${PKI_SETUP_CMD}" 3 echo "Wrote PKI certs, keys, tokens and admin password to master." @@ -207,8 +209,9 @@ function create-and-upload-hollow-node-image { CURR_DIR=`pwd` cd "${MAKE_DIR}" RETRIES=3 + KUBEMARK_IMAGE_REGISTRY="${KUBEMARK_IMAGE_REGISTRY:-${CONTAINER_REGISTRY}/${PROJECT}}" for attempt in $(seq 1 ${RETRIES}); do - if ! REGISTRY="${FULL_REGISTRY}" IMAGE_TAG="${KUBEMARK_IMAGE_TAG}" make "${KUBEMARK_IMAGE_MAKE_TARGET}"; then + if ! REGISTRY="${KUBEMARK_IMAGE_REGISTRY}" IMAGE_TAG="${KUBEMARK_IMAGE_TAG}" make "${KUBEMARK_IMAGE_MAKE_TARGET}"; then if [[ $((attempt)) -eq "${RETRIES}" ]]; then echo "${color_red}Make failed. Exiting.${color_norm}" exit 1 @@ -233,7 +236,7 @@ function create-and-upload-hollow-node-image-bazel { RETRIES=3 for attempt in $(seq 1 ${RETRIES}); do - if ! bazel run //cluster/images/kubemark:push --define REGISTRY="${FULL_REGISTRY}" --define IMAGE_TAG="${KUBEMARK_IMAGE_TAG}"; then + if ! bazel run //cluster/images/kubemark:push --define REGISTRY="${KUBEMARK_IMAGE_REGISTRY}" --define IMAGE_TAG="${KUBEMARK_IMAGE_TAG}"; then if [[ $((attempt)) -eq "${RETRIES}" ]]; then echo "${color_red}Image push failed. Exiting.${color_norm}" exit 1 @@ -347,6 +350,25 @@ contexts: name: kubemark-context current-context: kubemark-context") + # Create kubeconfig for Kube DNS. + KUBE_DNS_KUBECONFIG_CONTENTS=$(echo "apiVersion: v1 +kind: Config +users: +- name: kube-dns + user: + token: ${KUBE_DNS_TOKEN} +clusters: +- name: kubemark + cluster: + insecure-skip-tls-verify: true + server: https://${MASTER_IP} +contexts: +- context: + cluster: kubemark + user: kube-dns + name: kubemark-context +current-context: kubemark-context") + # Create kubemark namespace. "${KUBECTL}" create -f "${RESOURCE_DIRECTORY}/kubemark-ns.json" @@ -361,7 +383,8 @@ current-context: kubemark-context") --from-literal=kubeproxy.kubeconfig="${KUBEPROXY_KUBECONFIG_CONTENTS}" \ --from-literal=heapster.kubeconfig="${HEAPSTER_KUBECONFIG_CONTENTS}" \ --from-literal=cluster_autoscaler.kubeconfig="${CLUSTER_AUTOSCALER_KUBECONFIG_CONTENTS}" \ - --from-literal=npd.kubeconfig="${NPD_KUBECONFIG_CONTENTS}" + --from-literal=npd.kubeconfig="${NPD_KUBECONFIG_CONTENTS}" \ + --from-literal=dns.kubeconfig="${KUBE_DNS_KUBECONFIG_CONTENTS}" # Create addon pods. # Heapster. @@ -379,7 +402,7 @@ current-context: kubemark-context") sed -i'' -e "s/{{EVENTER_MEM}}/${eventer_mem}/g" "${RESOURCE_DIRECTORY}/addons/heapster.json" # Cluster Autoscaler. - if [[ "${ENABLE_KUBEMARK_CLUSTER_AUTOSCALER}" == "true" ]]; then + if [[ "${ENABLE_KUBEMARK_CLUSTER_AUTOSCALER:-}" == "true" ]]; then echo "Setting up Cluster Autoscaler" KUBEMARK_AUTOSCALER_MIG_NAME="${KUBEMARK_AUTOSCALER_MIG_NAME:-${NODE_INSTANCE_PREFIX}-group}" KUBEMARK_AUTOSCALER_MIN_NODES="${KUBEMARK_AUTOSCALER_MIN_NODES:-0}" @@ -393,6 +416,12 @@ current-context: kubemark-context") sed -i'' -e "s/{{kubemark_autoscaler_max_nodes}}/${KUBEMARK_AUTOSCALER_MAX_NODES}/g" "${RESOURCE_DIRECTORY}/addons/cluster-autoscaler.json" fi + # Kube DNS. + if [[ "${ENABLE_KUBEMARK_KUBE_DNS:-}" == "true" ]]; then + echo "Setting up kube-dns" + sed "s/{{dns_domain}}/${KUBE_DNS_DOMAIN}/g" "${RESOURCE_DIRECTORY}/kube_dns_template.yaml" > "${RESOURCE_DIRECTORY}/addons/kube_dns.yaml" + fi + "${KUBECTL}" create -f "${RESOURCE_DIRECTORY}/addons" --namespace="kubemark" # Create the replication controller for hollow-nodes. @@ -407,7 +436,7 @@ current-context: kubemark-context") proxy_mem=$((100 * 1024 + ${proxy_mem_per_node}*${NUM_NODES})) sed -i'' -e "s/{{HOLLOW_PROXY_CPU}}/${proxy_cpu}/g" "${RESOURCE_DIRECTORY}/hollow-node.yaml" sed -i'' -e "s/{{HOLLOW_PROXY_MEM}}/${proxy_mem}/g" "${RESOURCE_DIRECTORY}/hollow-node.yaml" - sed -i'' -e "s'{{full_registry}}'${FULL_REGISTRY}'g" "${RESOURCE_DIRECTORY}/hollow-node.yaml" + sed -i'' -e "s'{{kubemark_image_registry}}'${KUBEMARK_IMAGE_REGISTRY}'g" "${RESOURCE_DIRECTORY}/hollow-node.yaml" sed -i'' -e "s/{{kubemark_image_tag}}/${KUBEMARK_IMAGE_TAG}/g" "${RESOURCE_DIRECTORY}/hollow-node.yaml" sed -i'' -e "s/{{master_ip}}/${MASTER_IP}/g" "${RESOURCE_DIRECTORY}/hollow-node.yaml" sed -i'' -e "s/{{kubelet_verbosity_level}}/${KUBELET_TEST_LOG_LEVEL}/g" "${RESOURCE_DIRECTORY}/hollow-node.yaml" diff --git a/vendor/k8s.io/kubernetes/test/kubemark/stop-kubemark.sh b/vendor/k8s.io/kubernetes/test/kubemark/stop-kubemark.sh index 4ffc3632f..4645cbcd0 100755 --- a/vendor/k8s.io/kubernetes/test/kubemark/stop-kubemark.sh +++ b/vendor/k8s.io/kubernetes/test/kubemark/stop-kubemark.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2015 The Kubernetes Authors. # diff --git a/vendor/k8s.io/kubernetes/test/test_owners.csv b/vendor/k8s.io/kubernetes/test/test_owners.csv index 0d30b8f08..14beadb05 100644 --- a/vendor/k8s.io/kubernetes/test/test_owners.csv +++ b/vendor/k8s.io/kubernetes/test/test_owners.csv @@ -449,7 +449,7 @@ Secrets should be consumable via the environment,ixdy,1,apps Security Context should support container.SecurityContext.RunAsUser,alex-mohr,1,apps Security Context should support pod.Spec.SecurityContext.RunAsUser,bgrant0607,1,apps Security Context should support pod.Spec.SecurityContext.SupplementalGroups,rrati,0,apps -Security Context should support seccomp alpha docker/default annotation,freehan,1,apps +Security Context should support seccomp alpha runtime/default annotation,freehan,1,apps Security Context should support seccomp alpha unconfined annotation on the container,childsb,1,apps Security Context should support seccomp alpha unconfined annotation on the pod,krousey,1,apps Security Context should support seccomp default which is unconfined,lavalamp,1,apps @@ -544,7 +544,6 @@ k8s.io/kubernetes/cmd/libs/go2idl/go-to-protobuf/protobuf,smarterclayton,0, k8s.io/kubernetes/cmd/libs/go2idl/openapi-gen/generators,davidopp,1, k8s.io/kubernetes/examples,Random-Liu,0, k8s.io/kubernetes/hack,thockin,1, -k8s.io/kubernetes/hack/cmd/teststale,thockin,1, k8s.io/kubernetes/pkg/api,Q-Lee,1, k8s.io/kubernetes/pkg/api/endpoints,cjcullen,1, k8s.io/kubernetes/pkg/api/events,jlowdermilk,1, @@ -663,7 +662,6 @@ k8s.io/kubernetes/pkg/kubelet/pod,alex-mohr,1, k8s.io/kubernetes/pkg/kubelet/prober,alex-mohr,1, k8s.io/kubernetes/pkg/kubelet/prober/results,krousey,1, k8s.io/kubernetes/pkg/kubelet/qos,vishh,0, -k8s.io/kubernetes/pkg/kubelet/rkt,apelisse,1, k8s.io/kubernetes/pkg/kubelet/secret,kevin-wangzefeng,1, k8s.io/kubernetes/pkg/kubelet/server,tallclair,0, k8s.io/kubernetes/pkg/kubelet/server/portforward,rkouj,0, @@ -750,12 +748,12 @@ k8s.io/kubernetes/pkg/registry/extensions/deployment,dchen1107,1, k8s.io/kubernetes/pkg/registry/extensions/deployment/storage,timothysc,1, k8s.io/kubernetes/pkg/registry/extensions/ingress,apelisse,1, k8s.io/kubernetes/pkg/registry/extensions/ingress/storage,luxas,1, -k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage,dchen1107,1, k8s.io/kubernetes/pkg/registry/extensions/replicaset,rrati,0, k8s.io/kubernetes/pkg/registry/extensions/replicaset/storage,wojtek-t,1, k8s.io/kubernetes/pkg/registry/extensions/rest,rrati,0, k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget,Q-Lee,1, k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/storage,dchen1107,1, +k8s.io/kubernetes/pkg/registry/policy/podsecuritypolicy/storage,dchen1107,1, k8s.io/kubernetes/pkg/registry/rbac/reconciliation,roberthbailey,1, k8s.io/kubernetes/pkg/registry/rbac/validation,rkouj,0, k8s.io/kubernetes/pkg/registry/storage/storageclass,brendandburns,1, @@ -766,9 +764,9 @@ k8s.io/kubernetes/pkg/scheduler/algorithm/priorities,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/algorithmprovider,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/api/validation,fgrzadkowski,0, +k8s.io/kubernetes/pkg/scheduler/cache,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/core,madhusudancs,1, k8s.io/kubernetes/pkg/scheduler/factory,fgrzadkowski,0, -k8s.io/kubernetes/pkg/scheduler/schedulercache,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/util,wojtek-t,1, k8s.io/kubernetes/pkg/security/apparmor,bgrant0607,1, k8s.io/kubernetes/pkg/security/podsecuritypolicy,erictune,0, @@ -848,7 +846,6 @@ k8s.io/kubernetes/plugin/pkg/admission/deny,eparis,1, k8s.io/kubernetes/plugin/pkg/admission/exec,deads2k,1, k8s.io/kubernetes/plugin/pkg/admission/gc,kevin-wangzefeng,1, k8s.io/kubernetes/plugin/pkg/admission/imagepolicy,apelisse,1, -k8s.io/kubernetes/plugin/pkg/admission/initialresources,piosz,0, k8s.io/kubernetes/plugin/pkg/admission/limitranger,ncdc,1, k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision,derekwaynecarr,0, k8s.io/kubernetes/plugin/pkg/admission/namespace/exists,derekwaynecarr,0, diff --git a/vendor/k8s.io/kubernetes/test/typecheck/main.go b/vendor/k8s.io/kubernetes/test/typecheck/main.go index 411a945d4..2df32f41c 100644 --- a/vendor/k8s.io/kubernetes/test/typecheck/main.go +++ b/vendor/k8s.io/kubernetes/test/typecheck/main.go @@ -24,6 +24,7 @@ import ( "go/build" "go/parser" "go/token" + "io" "log" "os" "path/filepath" @@ -60,6 +61,8 @@ var ( "linux/arm64", "linux/ppc64le", "linux/s390x", "darwin/386", } + darwinPlatString = "darwin/386,darwin/amd64" + windowsPlatString = "windows/386,windows/amd64" ) type analyzer struct { @@ -69,6 +72,7 @@ type analyzer struct { failed bool platform string donePaths map[string]interface{} + errors []string } func newAnalyzer(platform string) *analyzer { @@ -120,11 +124,19 @@ func (a *analyzer) handleError(err error) { return } } - // TODO(rmmh): dedup errors across platforms? - fmt.Fprintf(os.Stderr, "%sERROR(%s) %s\n", logPrefix, a.platform, err) + a.errors = append(a.errors, err.Error()) + if *serial { + fmt.Fprintf(os.Stderr, "%sERROR(%s) %s\n", logPrefix, a.platform, err) + } a.failed = true } +func (a *analyzer) dumpAndResetErrors() []string { + es := a.errors + a.errors = nil + return es +} + // collect extracts test metadata from a file. func (a *analyzer) collect(dir string) { if _, ok := a.donePaths[dir]; ok { @@ -262,6 +274,51 @@ func (c *collector) handlePath(path string, info os.FileInfo, err error) error { return nil } +type analyzerResult struct { + platform string + dir string + errors []string +} + +func dedupeErrors(out io.Writer, results chan analyzerResult, nDirs, nPlatforms int) { + pkgRes := make(map[string][]analyzerResult) + for done := 0; done < nDirs; { + res := <-results + pkgRes[res.dir] = append(pkgRes[res.dir], res) + if len(pkgRes[res.dir]) != nPlatforms { + continue // expect more results for dir + } + done++ + // Collect list of platforms for each error + errPlats := map[string][]string{} + for _, res := range pkgRes[res.dir] { + for _, err := range res.errors { + errPlats[err] = append(errPlats[err], res.platform) + } + } + // Print each error (in the same order!) once. + for _, res := range pkgRes[res.dir] { + for _, err := range res.errors { + if errPlats[err] == nil { + continue // already printed + } + sort.Strings(errPlats[err]) + plats := strings.Join(errPlats[err], ",") + if len(errPlats[err]) == len(crossPlatforms) { + plats = "all" + } else if plats == darwinPlatString { + plats = "darwin" + } else if plats == windowsPlatString { + plats = "windows" + } + fmt.Fprintf(out, "%sERROR(%s) %s\n", logPrefix, plats, err) + delete(errPlats, err) + } + } + delete(pkgRes, res.dir) + } +} + func main() { flag.Parse() args := flag.Args() @@ -296,6 +353,15 @@ func main() { var processedDirs int64 var currentWork int64 // (dir_index << 8) | platform_index statuses := make([]int, len(ps)) + var results chan analyzerResult + if !*serial { + results = make(chan analyzerResult) + wg.Add(1) + go func() { + dedupeErrors(os.Stderr, results, len(c.dirs), len(ps)) + wg.Done() + }() + } for i, p := range ps { wg.Add(1) fn := func(i int, p string) { @@ -305,6 +371,9 @@ func main() { a.collect(dir) atomic.AddInt64(&processedDirs, 1) atomic.StoreInt64(¤tWork, int64(n<<8|i)) + if results != nil { + results <- analyzerResult{p, dir, a.dumpAndResetErrors()} + } } if a.failed { statuses[i] = 1 diff --git a/vendor/k8s.io/kubernetes/test/typecheck/main_test.go b/vendor/k8s.io/kubernetes/test/typecheck/main_test.go index 803963f2a..9b1fb830d 100644 --- a/vendor/k8s.io/kubernetes/test/typecheck/main_test.go +++ b/vendor/k8s.io/kubernetes/test/typecheck/main_test.go @@ -17,6 +17,7 @@ limitations under the License. package main import ( + "bytes" "errors" "fmt" "go/ast" @@ -155,3 +156,38 @@ func TestHandlePath(t *testing.T) { t.Error("should skip vendor") } } + +func TestDedupeErrors(t *testing.T) { + testcases := []struct { + nPlatforms int + results []analyzerResult + expected string + }{ + {1, []analyzerResult{}, ""}, + {1, []analyzerResult{{"linux/arm", "test", nil}}, ""}, + {1, []analyzerResult{ + {"linux/arm", "test", []string{"a"}}}, + "ERROR(linux/arm) a\n"}, + {3, []analyzerResult{ + {"linux/arm", "test", []string{"a"}}, + {"windows/386", "test", []string{"b"}}, + {"windows/amd64", "test", []string{"b", "c"}}}, + "ERROR(linux/arm) a\n" + + "ERROR(windows) b\n" + + "ERROR(windows/amd64) c\n"}, + } + for _, tc := range testcases { + out := &bytes.Buffer{} + results := make(chan analyzerResult, len(tc.results)) + for _, res := range tc.results { + results <- res + } + close(results) + dedupeErrors(out, results, len(tc.results)/tc.nPlatforms, tc.nPlatforms) + outString := out.String() + if outString != tc.expected { + t.Errorf("dedupeErrors(%v) = '%s', expected '%s'", + tc.results, outString, tc.expected) + } + } +} diff --git a/vendor/k8s.io/kubernetes/test/utils/BUILD b/vendor/k8s.io/kubernetes/test/utils/BUILD index 2c0482231..ae31846ac 100644 --- a/vendor/k8s.io/kubernetes/test/utils/BUILD +++ b/vendor/k8s.io/kubernetes/test/utils/BUILD @@ -13,6 +13,7 @@ go_library( "delete_resources.go", "density_utils.go", "deployment.go", + "paths.go", "pod_store.go", "replicaset.go", "runners.go", @@ -32,6 +33,7 @@ go_library( "//pkg/util/labels:go_default_library", "//vendor/github.com/davecgh/go-spew/spew:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", diff --git a/vendor/k8s.io/kubernetes/test/utils/create_resources.go b/vendor/k8s.io/kubernetes/test/utils/create_resources.go index 7a1379826..f92649ac1 100644 --- a/vendor/k8s.io/kubernetes/test/utils/create_resources.go +++ b/vendor/k8s.io/kubernetes/test/utils/create_resources.go @@ -51,7 +51,16 @@ func RetryWithExponentialBackOff(fn wait.ConditionFunc) error { } func IsRetryableAPIError(err error) bool { - return apierrs.IsTimeout(err) || apierrs.IsServerTimeout(err) || apierrs.IsTooManyRequests(err) || utilnet.IsProbableEOF(err) + // These errors may indicate a transient error that we can retry in tests. + if apierrs.IsInternalError(err) || apierrs.IsTimeout(err) || apierrs.IsServerTimeout(err) || + apierrs.IsTooManyRequests(err) || utilnet.IsProbableEOF(err) || utilnet.IsConnectionReset(err) { + return true + } + // If the error sends the Retry-After header, we respect it as an explicit confirmation we should retry. + if _, shouldRetry := apierrs.SuggestsClientDelay(err); shouldRetry { + return true + } + return false } func CreatePodWithRetries(c clientset.Interface, namespace string, obj *v1.Pod) error { diff --git a/vendor/k8s.io/kubernetes/test/utils/delete_resources.go b/vendor/k8s.io/kubernetes/test/utils/delete_resources.go index de5771c95..5c67afda2 100644 --- a/vendor/k8s.io/kubernetes/test/utils/delete_resources.go +++ b/vendor/k8s.io/kubernetes/test/utils/delete_resources.go @@ -29,8 +29,6 @@ import ( batchinternal "k8s.io/kubernetes/pkg/apis/batch" api "k8s.io/kubernetes/pkg/apis/core" extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/kubectl" ) func deleteResource(c clientset.Interface, kind schema.GroupKind, namespace, name string, options *metav1.DeleteOptions) error { @@ -58,10 +56,6 @@ func deleteResource(c clientset.Interface, kind schema.GroupKind, namespace, nam } } -func getReaperForKind(c internalclientset.Interface, kind schema.GroupKind) (kubectl.Reaper, error) { - return kubectl.ReaperFor(kind, c) -} - func DeleteResourceWithRetries(c clientset.Interface, kind schema.GroupKind, namespace, name string, options *metav1.DeleteOptions) error { deleteFunc := func() (bool, error) { err := deleteResource(c, kind, namespace, name, options) @@ -75,21 +69,3 @@ func DeleteResourceWithRetries(c clientset.Interface, kind schema.GroupKind, nam } return RetryWithExponentialBackOff(deleteFunc) } - -func DeleteResourceUsingReaperWithRetries(c internalclientset.Interface, kind schema.GroupKind, namespace, name string, options *metav1.DeleteOptions) error { - reaper, err := getReaperForKind(c, kind) - if err != nil { - return err - } - deleteFunc := func() (bool, error) { - err := reaper.Stop(namespace, name, 0, options) - if err == nil || apierrs.IsNotFound(err) { - return true, nil - } - if IsRetryableAPIError(err) { - return false, nil - } - return false, fmt.Errorf("Failed to delete object with non-retriable error: %v", err) - } - return RetryWithExponentialBackOff(deleteFunc) -} diff --git a/vendor/k8s.io/kubernetes/test/utils/deployment.go b/vendor/k8s.io/kubernetes/test/utils/deployment.go index 995186dc1..323b927d0 100644 --- a/vendor/k8s.io/kubernetes/test/utils/deployment.go +++ b/vendor/k8s.io/kubernetes/test/utils/deployment.go @@ -22,8 +22,8 @@ import ( "github.com/davecgh/go-spew/spew" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" @@ -34,7 +34,7 @@ import ( type LogfFn func(format string, args ...interface{}) -func LogReplicaSetsOfDeployment(deployment *extensions.Deployment, allOldRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, logf LogfFn) { +func LogReplicaSetsOfDeployment(deployment *apps.Deployment, allOldRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, logf LogfFn) { if newRS != nil { logf(spew.Sprintf("New ReplicaSet %q of Deployment %q:\n%+v", newRS.Name, deployment.Name, *newRS)) } else { @@ -48,7 +48,7 @@ func LogReplicaSetsOfDeployment(deployment *extensions.Deployment, allOldRSs []* } } -func LogPodsOfDeployment(c clientset.Interface, deployment *extensions.Deployment, rsList []*extensions.ReplicaSet, logf LogfFn) { +func LogPodsOfDeployment(c clientset.Interface, deployment *apps.Deployment, rsList []*apps.ReplicaSet, logf LogfFn) { minReadySeconds := deployment.Spec.MinReadySeconds podListFunc := func(namespace string, options metav1.ListOptions) (*v1.PodList, error) { return c.CoreV1().Pods(namespace).List(options) @@ -72,15 +72,15 @@ func LogPodsOfDeployment(c clientset.Interface, deployment *extensions.Deploymen // If during a rolling update (rolling == true), returns an error if the deployment's // rolling update strategy (max unavailable or max surge) is broken at any times. // It's not seen as a rolling update if shortly after a scaling event or the deployment is just created. -func waitForDeploymentCompleteMaybeCheckRolling(c clientset.Interface, d *extensions.Deployment, rolling bool, logf LogfFn, pollInterval, pollTimeout time.Duration) error { +func waitForDeploymentCompleteMaybeCheckRolling(c clientset.Interface, d *apps.Deployment, rolling bool, logf LogfFn, pollInterval, pollTimeout time.Duration) error { var ( - deployment *extensions.Deployment + deployment *apps.Deployment reason string ) err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { var err error - deployment, err = c.ExtensionsV1beta1().Deployments(d.Namespace).Get(d.Name, metav1.GetOptions{}) + deployment, err = c.AppsV1().Deployments(d.Namespace).Get(d.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -114,9 +114,9 @@ func waitForDeploymentCompleteMaybeCheckRolling(c clientset.Interface, d *extens return nil } -func checkRollingUpdateStatus(c clientset.Interface, deployment *extensions.Deployment, logf LogfFn) (string, error) { +func checkRollingUpdateStatus(c clientset.Interface, deployment *apps.Deployment, logf LogfFn) (string, error) { var reason string - oldRSs, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.ExtensionsV1beta1()) + oldRSs, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.AppsV1()) if err != nil { return "", err } @@ -128,7 +128,7 @@ func checkRollingUpdateStatus(c clientset.Interface, deployment *extensions.Depl allRSs := append(oldRSs, newRS) // The old/new ReplicaSets need to contain the pod-template-hash label for i := range allRSs { - if !labelsutil.SelectorHasLabel(allRSs[i].Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey) { + if !labelsutil.SelectorHasLabel(allRSs[i].Spec.Selector, apps.DefaultDeploymentUniqueLabelKey) { reason = "all replica sets need to contain the pod-template-hash label" return reason, nil } @@ -153,7 +153,7 @@ func checkRollingUpdateStatus(c clientset.Interface, deployment *extensions.Depl // Waits for the deployment to complete, and check rolling update strategy isn't broken at any times. // Rolling update strategy should not be broken during a rolling update. -func WaitForDeploymentCompleteAndCheckRolling(c clientset.Interface, d *extensions.Deployment, logf LogfFn, pollInterval, pollTimeout time.Duration) error { +func WaitForDeploymentCompleteAndCheckRolling(c clientset.Interface, d *apps.Deployment, logf LogfFn, pollInterval, pollTimeout time.Duration) error { rolling := true return waitForDeploymentCompleteMaybeCheckRolling(c, d, rolling, logf, pollInterval, pollTimeout) } @@ -161,7 +161,7 @@ func WaitForDeploymentCompleteAndCheckRolling(c clientset.Interface, d *extensio // Waits for the deployment to complete, and don't check if rolling update strategy is broken. // Rolling update strategy is used only during a rolling update, and can be violated in other situations, // such as shortly after a scaling event or the deployment is just created. -func WaitForDeploymentComplete(c clientset.Interface, d *extensions.Deployment, logf LogfFn, pollInterval, pollTimeout time.Duration) error { +func WaitForDeploymentComplete(c clientset.Interface, d *apps.Deployment, logf LogfFn, pollInterval, pollTimeout time.Duration) error { rolling := false return waitForDeploymentCompleteMaybeCheckRolling(c, d, rolling, logf, pollInterval, pollTimeout) } @@ -169,17 +169,17 @@ func WaitForDeploymentComplete(c clientset.Interface, d *extensions.Deployment, // WaitForDeploymentRevisionAndImage waits for the deployment's and its new RS's revision and container image to match the given revision and image. // Note that deployment revision and its new RS revision should be updated shortly, so we only wait for 1 minute here to fail early. func WaitForDeploymentRevisionAndImage(c clientset.Interface, ns, deploymentName string, revision, image string, logf LogfFn, pollInterval, pollTimeout time.Duration) error { - var deployment *extensions.Deployment - var newRS *extensions.ReplicaSet + var deployment *apps.Deployment + var newRS *apps.ReplicaSet var reason string err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { var err error - deployment, err = c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + deployment, err = c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) if err != nil { return false, err } // The new ReplicaSet needs to be non-nil and contain the pod-template-hash label - newRS, err = deploymentutil.GetNewReplicaSet(deployment, c.ExtensionsV1beta1()) + newRS, err = deploymentutil.GetNewReplicaSet(deployment, c.AppsV1()) if err != nil { return false, err } @@ -205,26 +205,26 @@ func WaitForDeploymentRevisionAndImage(c clientset.Interface, ns, deploymentName // CheckDeploymentRevisionAndImage checks if the input deployment's and its new replica set's revision and image are as expected. func CheckDeploymentRevisionAndImage(c clientset.Interface, ns, deploymentName, revision, image string) error { - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) if err != nil { return fmt.Errorf("unable to get deployment %s during revision check: %v", deploymentName, err) } // Check revision of the new replica set of this deployment - newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.ExtensionsV1beta1()) + newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.AppsV1()) if err != nil { return fmt.Errorf("unable to get new replicaset of deployment %s during revision check: %v", deploymentName, err) } return checkRevisionAndImage(deployment, newRS, revision, image) } -func checkRevisionAndImage(deployment *extensions.Deployment, newRS *extensions.ReplicaSet, revision, image string) error { +func checkRevisionAndImage(deployment *apps.Deployment, newRS *apps.ReplicaSet, revision, image string) error { // The new ReplicaSet needs to be non-nil and contain the pod-template-hash label if newRS == nil { return fmt.Errorf("new replicaset for deployment %q is yet to be created", deployment.Name) } - if !labelsutil.SelectorHasLabel(newRS.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey) { - return fmt.Errorf("new replica set %q doesn't have %q label selector", newRS.Name, extensions.DefaultDeploymentUniqueLabelKey) + if !labelsutil.SelectorHasLabel(newRS.Spec.Selector, apps.DefaultDeploymentUniqueLabelKey) { + return fmt.Errorf("new replica set %q doesn't have %q label selector", newRS.Name, apps.DefaultDeploymentUniqueLabelKey) } // Check revision of this deployment, and of the new replica set of this deployment if deployment.Annotations == nil || deployment.Annotations[deploymentutil.RevisionAnnotation] != revision { @@ -252,19 +252,19 @@ func containsImage(containers []v1.Container, imageName string) bool { return false } -type UpdateDeploymentFunc func(d *extensions.Deployment) +type UpdateDeploymentFunc func(d *apps.Deployment) -func UpdateDeploymentWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateDeploymentFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*extensions.Deployment, error) { - var deployment *extensions.Deployment +func UpdateDeploymentWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateDeploymentFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*apps.Deployment, error) { + var deployment *apps.Deployment var updateErr error pollErr := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { var err error - if deployment, err = c.ExtensionsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{}); err != nil { + if deployment, err = c.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{}); err != nil { return false, err } // Apply the update, then attempt to push it to the apiserver. applyUpdate(deployment) - if deployment, err = c.ExtensionsV1beta1().Deployments(namespace).Update(deployment); err == nil { + if deployment, err = c.AppsV1().Deployments(namespace).Update(deployment); err == nil { logf("Updating deployment %s", name) return true, nil } @@ -278,20 +278,20 @@ func UpdateDeploymentWithRetries(c clientset.Interface, namespace, name string, } func WaitForObservedDeployment(c clientset.Interface, ns, deploymentName string, desiredGeneration int64) error { - return deploymentutil.WaitForObservedDeployment(func() (*extensions.Deployment, error) { - return c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + return deploymentutil.WaitForObservedDeployment(func() (*apps.Deployment, error) { + return c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) }, desiredGeneration, 2*time.Second, 1*time.Minute) } // WaitForDeploymentRollbackCleared waits for given deployment either started rolling back or doesn't need to rollback. func WaitForDeploymentRollbackCleared(c clientset.Interface, ns, deploymentName string, pollInterval, pollTimeout time.Duration) error { err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { - deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) if err != nil { return false, err } // Rollback not set or is kicked off - if deployment.Spec.RollbackTo == nil { + if deployment.Annotations[apps.DeprecatedRollbackTo] == "" { return true, nil } return false, nil @@ -304,9 +304,9 @@ func WaitForDeploymentRollbackCleared(c clientset.Interface, ns, deploymentName // WaitForDeploymentUpdatedReplicasGTE waits for given deployment to be observed by the controller and has at least a number of updatedReplicas func WaitForDeploymentUpdatedReplicasGTE(c clientset.Interface, ns, deploymentName string, minUpdatedReplicas int32, desiredGeneration int64, pollInterval, pollTimeout time.Duration) error { - var deployment *extensions.Deployment + var deployment *apps.Deployment err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { - d, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + d, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) if err != nil { return false, err } @@ -319,10 +319,10 @@ func WaitForDeploymentUpdatedReplicasGTE(c clientset.Interface, ns, deploymentNa return nil } -func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, reason string, condType extensions.DeploymentConditionType, logf LogfFn, pollInterval, pollTimeout time.Duration) error { - var deployment *extensions.Deployment +func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, reason string, condType apps.DeploymentConditionType, logf LogfFn, pollInterval, pollTimeout time.Duration) error { + var deployment *apps.Deployment pollErr := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { - d, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) + d, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{}) if err != nil { return false, err } @@ -332,7 +332,7 @@ func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, r }) if pollErr == wait.ErrWaitTimeout { pollErr = fmt.Errorf("deployment %q never updated with the desired condition and reason, latest deployment conditions: %+v", deployment.Name, deployment.Status.Conditions) - _, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.ExtensionsV1beta1()) + _, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.AppsV1()) if err == nil { LogReplicaSetsOfDeployment(deployment, allOldRSs, newRS, logf) LogPodsOfDeployment(c, deployment, append(allOldRSs, newRS), logf) diff --git a/vendor/k8s.io/kubernetes/test/utils/image/manifest.go b/vendor/k8s.io/kubernetes/test/utils/image/manifest.go index aff2b93fe..be9ff8dc6 100644 --- a/vendor/k8s.io/kubernetes/test/utils/image/manifest.go +++ b/vendor/k8s.io/kubernetes/test/utils/image/manifest.go @@ -57,7 +57,7 @@ var ( CudaVectorAdd = ImageConfig{e2eRegistry, "cuda-vector-add", "1.0", true} Dnsutils = ImageConfig{e2eRegistry, "dnsutils", "1.0", true} DNSMasq = ImageConfig{gcRegistry, "k8s-dns-dnsmasq", "1.14.5", true} - EchoServer = ImageConfig{gcRegistry, "echoserver", "1.6", false} + EchoServer = ImageConfig{gcRegistry, "echoserver", "1.10", false} EntrypointTester = ImageConfig{e2eRegistry, "entrypoint-tester", "1.0", true} E2ENet = ImageConfig{gcRegistry, "e2e-net", "1.0", true} Fakegitserver = ImageConfig{e2eRegistry, "fakegitserver", "1.0", true} @@ -84,7 +84,7 @@ var ( NoSnatTestProxy = ImageConfig{e2eRegistry, "no-snat-test-proxy", "1.0", true} NWayHTTP = ImageConfig{e2eRegistry, "n-way-http", "1.0", true} // When these values are updated, also update cmd/kubelet/app/options/container_runtime.go - Pause = ImageConfig{gcRegistry, "pause", "3.1", true} + Pause = ImageConfig{gcRegistry, "pause", "3.1", false} Porter = ImageConfig{e2eRegistry, "porter", "1.0", true} PortForwardTester = ImageConfig{e2eRegistry, "port-forward-tester", "1.0", true} Redis = ImageConfig{e2eRegistry, "redis", "1.0", true} @@ -93,11 +93,10 @@ var ( SDDummyExporter = ImageConfig{gcRegistry, "sd-dummy-exporter", "v0.1.0", false} ServeHostname = ImageConfig{e2eRegistry, "serve-hostname", "1.0", true} TestWebserver = ImageConfig{e2eRegistry, "test-webserver", "1.0", true} - VolumeNFSServer = ImageConfig{gcRegistry, "volume-nfs", "0.8", false} - VolumeISCSIServer = ImageConfig{gcRegistry, "volume-icsci", "0.1", false} - VolumeGlusterServer = ImageConfig{gcRegistry, "volume-gluster", "0.2", false} - VolumeCephServer = ImageConfig{gcRegistry, "volume-ceph", "0.1", false} - VolumeRBDServer = ImageConfig{gcRegistry, "volume-rbd", "0.1", false} + VolumeNFSServer = ImageConfig{e2eRegistry, "volume-nfs", "0.8", false} + VolumeISCSIServer = ImageConfig{e2eRegistry, "volume-iscsi", "0.2", false} + VolumeGlusterServer = ImageConfig{e2eRegistry, "volume-gluster", "0.5", false} + VolumeRBDServer = ImageConfig{e2eRegistry, "volume-rbd", "0.2", false} ) func GetE2EImage(image ImageConfig) string { @@ -113,7 +112,7 @@ func GetE2EImageWithArch(image ImageConfig, arch string) string { } } -// GetPauseImageNameForHostArch fetches the pause image name for the same architecture the test is running on. -func GetPauseImageNameForHostArch() string { +// GetPauseImageName returns the pause image name with proper version +func GetPauseImageName() string { return GetE2EImage(Pause) } diff --git a/vendor/k8s.io/kubernetes/test/utils/paths.go b/vendor/k8s.io/kubernetes/test/utils/paths.go new file mode 100644 index 000000000..9f1f6f5da --- /dev/null +++ b/vendor/k8s.io/kubernetes/test/utils/paths.go @@ -0,0 +1,72 @@ +/* +Copyright 2018 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 utils + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "strings" +) + +// GetK8sRootDir returns the root directory for kubernetes, if present in the gopath. +func GetK8sRootDir() (string, error) { + dir, err := RootDir() + if err != nil { + return "", err + } + return filepath.Join(dir, fmt.Sprintf("%s/", "k8s.io/kubernetes")), nil +} + +// GetCAdvisorRootDir returns the root directory for cAdvisor, if present in the gopath. +func GetCAdvisorRootDir() (string, error) { + dir, err := RootDir() + if err != nil { + return "", err + } + return filepath.Join(dir, fmt.Sprintf("%s/", "github.com/google/cadvisor")), nil +} + +// RootDir gets the on-disk kubernetes source directory, returning an error is none is found +func RootDir() (string, error) { + // Get the directory of the current executable + _, testExec, _, _ := runtime.Caller(0) + path := filepath.Dir(testExec) + + // Look for the kubernetes source root directory + if strings.Contains(path, "k8s.io/kubernetes") { + splitPath := strings.Split(path, "k8s.io/kubernetes") + return splitPath[0], nil + } + + return "", errors.New("could not find kubernetes source root directory") +} + +// GetK8sBuildOutputDir returns the build output directory for k8s +func GetK8sBuildOutputDir() (string, error) { + k8sRoot, err := GetK8sRootDir() + if err != nil { + return "", err + } + buildOutputDir := filepath.Join(k8sRoot, "_output/local/go/bin") + if _, err := os.Stat(buildOutputDir); err != nil { + return "", err + } + return buildOutputDir, nil +} diff --git a/vendor/k8s.io/kubernetes/test/utils/replicaset.go b/vendor/k8s.io/kubernetes/test/utils/replicaset.go index 7d5176d4e..838dd891f 100644 --- a/vendor/k8s.io/kubernetes/test/utils/replicaset.go +++ b/vendor/k8s.io/kubernetes/test/utils/replicaset.go @@ -21,25 +21,25 @@ import ( "testing" "time" - extensions "k8s.io/api/extensions/v1beta1" + apps "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" ) -type UpdateReplicaSetFunc func(d *extensions.ReplicaSet) +type UpdateReplicaSetFunc func(d *apps.ReplicaSet) -func UpdateReplicaSetWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateReplicaSetFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*extensions.ReplicaSet, error) { - var rs *extensions.ReplicaSet +func UpdateReplicaSetWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateReplicaSetFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*apps.ReplicaSet, error) { + var rs *apps.ReplicaSet var updateErr error pollErr := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { var err error - if rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}); err != nil { + if rs, err = c.AppsV1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}); err != nil { return false, err } // Apply the update, then attempt to push it to the apiserver. applyUpdate(rs) - if rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).Update(rs); err == nil { + if rs, err = c.AppsV1().ReplicaSets(namespace).Update(rs); err == nil { logf("Updating replica set %q", name) return true, nil } @@ -53,10 +53,10 @@ func UpdateReplicaSetWithRetries(c clientset.Interface, namespace, name string, } // Verify .Status.Replicas is equal to .Spec.Replicas -func WaitRSStable(t *testing.T, clientSet clientset.Interface, rs *extensions.ReplicaSet, pollInterval, pollTimeout time.Duration) error { +func WaitRSStable(t *testing.T, clientSet clientset.Interface, rs *apps.ReplicaSet, pollInterval, pollTimeout time.Duration) error { desiredGeneration := rs.Generation if err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { - newRS, err := clientSet.ExtensionsV1beta1().ReplicaSets(rs.Namespace).Get(rs.Name, metav1.GetOptions{}) + newRS, err := clientSet.AppsV1().ReplicaSets(rs.Namespace).Get(rs.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -67,17 +67,17 @@ func WaitRSStable(t *testing.T, clientSet clientset.Interface, rs *extensions.Re return nil } -func UpdateReplicaSetStatusWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateReplicaSetFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*extensions.ReplicaSet, error) { - var rs *extensions.ReplicaSet +func UpdateReplicaSetStatusWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateReplicaSetFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*apps.ReplicaSet, error) { + var rs *apps.ReplicaSet var updateErr error pollErr := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) { var err error - if rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}); err != nil { + if rs, err = c.AppsV1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}); err != nil { return false, err } // Apply the update, then attempt to push it to the apiserver. applyUpdate(rs) - if rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).UpdateStatus(rs); err == nil { + if rs, err = c.AppsV1().ReplicaSets(namespace).UpdateStatus(rs); err == nil { logf("Updating replica set %q", name) return true, nil } diff --git a/vendor/k8s.io/kubernetes/test/utils/runners.go b/vendor/k8s.io/kubernetes/test/utils/runners.go index 1be60c20d..aef052329 100644 --- a/vendor/k8s.io/kubernetes/test/utils/runners.go +++ b/vendor/k8s.io/kubernetes/test/utils/runners.go @@ -124,6 +124,7 @@ type RCConfig struct { CpuLimit int64 // millicores MemRequest int64 // bytes MemLimit int64 // bytes + GpuLimit int64 // count ReadinessProbe *v1.Probe DNSPolicy *v1.DNSPolicy PriorityClassName string @@ -131,8 +132,9 @@ type RCConfig struct { // Env vars, set the same for every pod. Env map[string]string - // Extra labels added to every pod. - Labels map[string]string + // Extra labels and annotations added to every pod. + Labels map[string]string + Annotations map[string]string // Node selector for pods in the RC. NodeSelector map[string]string @@ -292,7 +294,8 @@ func (config *DeploymentConfig) create() error { }, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"name": config.Name}, + Labels: map[string]string{"name": config.Name}, + Annotations: config.Annotations, }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -362,7 +365,8 @@ func (config *ReplicaSetConfig) create() error { }, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"name": config.Name}, + Labels: map[string]string{"name": config.Name}, + Annotations: config.Annotations, }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -428,7 +432,8 @@ func (config *JobConfig) create() error { Completions: func(i int) *int32 { x := int32(i); return &x }(config.Replicas), Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"name": config.Name}, + Labels: map[string]string{"name": config.Name}, + Annotations: config.Annotations, }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -542,7 +547,8 @@ func (config *RCConfig) create() error { }, Template: &v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"name": config.Name}, + Labels: map[string]string{"name": config.Name}, + Annotations: config.Annotations, }, Spec: v1.PodSpec{ Affinity: config.Affinity, @@ -610,7 +616,7 @@ func (config *RCConfig) applyTo(template *v1.PodTemplateSpec) { c.Ports = append(c.Ports, v1.ContainerPort{Name: k, ContainerPort: int32(v), HostPort: int32(v)}) } } - if config.CpuLimit > 0 || config.MemLimit > 0 { + if config.CpuLimit > 0 || config.MemLimit > 0 || config.GpuLimit > 0 { template.Spec.Containers[0].Resources.Limits = v1.ResourceList{} } if config.CpuLimit > 0 { @@ -628,6 +634,9 @@ func (config *RCConfig) applyTo(template *v1.PodTemplateSpec) { if config.MemRequest > 0 { template.Spec.Containers[0].Resources.Requests[v1.ResourceMemory] = *resource.NewQuantity(config.MemRequest, resource.DecimalSI) } + if config.GpuLimit > 0 { + template.Spec.Containers[0].Resources.Limits["nvidia.com/gpu"] = *resource.NewQuantity(config.GpuLimit, resource.DecimalSI) + } if len(config.Volumes) > 0 { template.Spec.Volumes = config.Volumes } @@ -646,6 +655,7 @@ type RCStartupStatus struct { RunningButNotReady int Waiting int Pending int + Scheduled int Unknown int Inactive int FailedContainers int @@ -699,6 +709,10 @@ func ComputeRCStartupStatus(pods []*v1.Pod, expected int) RCStartupStatus { } else if p.Status.Phase == v1.PodUnknown { startupStatus.Unknown++ } + // Record count of scheduled pods (useful for computing scheduler throughput). + if p.Spec.NodeName != "" { + startupStatus.Scheduled++ + } } return startupStatus } diff --git a/vendor/k8s.io/kubernetes/test/utils/update_resources.go b/vendor/k8s.io/kubernetes/test/utils/update_resources.go index df435295d..210847cb3 100644 --- a/vendor/k8s.io/kubernetes/test/utils/update_resources.go +++ b/vendor/k8s.io/kubernetes/test/utils/update_resources.go @@ -20,6 +20,9 @@ import ( "fmt" "time" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/scale" "k8s.io/kubernetes/pkg/kubectl" ) @@ -29,13 +32,32 @@ const ( updateRetryInterval = 5 * time.Second updateRetryTimeout = 1 * time.Minute waitRetryInterval = 5 * time.Second - waitRetryTImeout = 5 * time.Minute + waitRetryTimeout = 5 * time.Minute ) -func ScaleResourceWithRetries(scaler kubectl.Scaler, namespace, name string, size uint) error { - waitForScale := kubectl.NewRetryParams(updateRetryInterval, updateRetryTimeout) - waitForReplicas := kubectl.NewRetryParams(waitRetryInterval, waitRetryTImeout) - if err := scaler.Scale(namespace, name, size, nil, waitForScale, waitForReplicas); err != nil { +func RetryErrorCondition(condition wait.ConditionFunc) wait.ConditionFunc { + return func() (bool, error) { + done, err := condition() + if err != nil && IsRetryableAPIError(err) { + return false, nil + } + return done, err + } +} + +func ScaleResourceWithRetries(scalesGetter scale.ScalesGetter, namespace, name string, size uint, gr schema.GroupResource) error { + scaler := kubectl.NewScaler(scalesGetter) + preconditions := &kubectl.ScalePrecondition{ + Size: -1, + ResourceVersion: "", + } + waitForReplicas := kubectl.NewRetryParams(waitRetryInterval, waitRetryTimeout) + cond := RetryErrorCondition(kubectl.ScaleCondition(scaler, preconditions, namespace, name, size, nil, gr)) + err := wait.PollImmediate(updateRetryInterval, updateRetryTimeout, cond) + if err == nil { + err = kubectl.WaitForScaleHasDesiredReplicas(scalesGetter, gr, name, namespace, size, waitForReplicas) + } + if err != nil { return fmt.Errorf("Error while scaling %s to %d replicas: %v", name, size, err) } return nil diff --git a/vendor/k8s.io/kubernetes/third_party/BUILD b/vendor/k8s.io/kubernetes/third_party/BUILD index 4b80dd42d..2beec65ec 100644 --- a/vendor/k8s.io/kubernetes/third_party/BUILD +++ b/vendor/k8s.io/kubernetes/third_party/BUILD @@ -4,8 +4,13 @@ licenses(["notice"]) filegroup( name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], + srcs = glob( + ["**"], + exclude = [ + "etcd*/**", + "etcd*.tar.gz", + ], + ), visibility = ["//visibility:private"], ) @@ -22,7 +27,6 @@ filegroup( "//third_party/forked/golang/reflect:all-srcs", "//third_party/forked/golang/template:all-srcs", "//third_party/forked/gonum/graph:all-srcs", - "//third_party/htpasswd:all-srcs", ], tags = ["automanaged"], ) diff --git a/vendor/k8s.io/kubernetes/third_party/forked/golang/reflect/deep_equal.go b/vendor/k8s.io/kubernetes/third_party/forked/golang/reflect/deep_equal.go index 9e45dbe1d..7ed1d1cff 100644 --- a/vendor/k8s.io/kubernetes/third_party/forked/golang/reflect/deep_equal.go +++ b/vendor/k8s.io/kubernetes/third_party/forked/golang/reflect/deep_equal.go @@ -44,7 +44,7 @@ func (e Equalities) AddFunc(eqFunc interface{}) error { return fmt.Errorf("expected func, got: %v", ft) } if ft.NumIn() != 2 { - return fmt.Errorf("expected three 'in' params, got: %v", ft) + return fmt.Errorf("expected two 'in' params, got: %v", ft) } if ft.NumOut() != 1 { return fmt.Errorf("expected one 'out' param, got: %v", ft) diff --git a/vendor/k8s.io/kubernetes/third_party/forked/shell2junit/sh2ju.sh b/vendor/k8s.io/kubernetes/third_party/forked/shell2junit/sh2ju.sh index f5f7ec4aa..f0891455c 100755 --- a/vendor/k8s.io/kubernetes/third_party/forked/shell2junit/sh2ju.sh +++ b/vendor/k8s.io/kubernetes/third_party/forked/shell2junit/sh2ju.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash ### Copyright 2010 Manuel Carrasco Moñino. (manolo at apache.org) ### ### Licensed under the Apache License, Version 2.0. @@ -130,27 +130,19 @@ function juLog() { # calculate vars asserts=$(($asserts+1)) errors=$(($errors+$err)) - time=`echo "${end} - ${ini}" | bc -l` - total=`echo "${total} + ${time}" | bc -l` + time=`echo "${end} ${ini}" | awk '{print $1 - $2}'` + total=`echo "${total} ${time}" | awk '{print $1 + $2}'` # write the junit xml report ## failure tag [[ ${err} = 0 ]] && failure="" || failure=" - - - + " ## testcase tag content="${content} ${failure} - - - + " ## testsuite block diff --git a/vendor/k8s.io/kubernetes/third_party/htpasswd/BUILD b/vendor/k8s.io/kubernetes/third_party/htpasswd/BUILD deleted file mode 100644 index 6cc62052b..000000000 --- a/vendor/k8s.io/kubernetes/third_party/htpasswd/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/k8s.io/kubernetes/third_party/htpasswd/COPYING b/vendor/k8s.io/kubernetes/third_party/htpasswd/COPYING deleted file mode 100644 index c6b097c01..000000000 --- a/vendor/k8s.io/kubernetes/third_party/htpasswd/COPYING +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (C) 2003-2013 Edgewall Software -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The name of the author may not be used to endorse or promote - products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/k8s.io/kubernetes/third_party/htpasswd/htpasswd.py b/vendor/k8s.io/kubernetes/third_party/htpasswd/htpasswd.py deleted file mode 100644 index 3ac2053a6..000000000 --- a/vendor/k8s.io/kubernetes/third_party/htpasswd/htpasswd.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2008-2013 Edgewall Software -# Copyright (C) 2008 Eli Carter -# All rights reserved. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at http://trac.edgewall.com/license.html. -# -# This software consists of voluntary contributions made by many -# individuals. For the exact contribution history, see the revision -# history and logs, available at http://trac.edgewall.org/. - -"""Replacement for htpasswd""" - -import os -import sys -import random -from optparse import OptionParser - -# We need a crypt module, but Windows doesn't have one by default. Try to find -# one, and tell the user if we can't. -try: - import crypt -except ImportError: - try: - import fcrypt as crypt - except ImportError: - sys.stderr.write("Cannot find a crypt module. " - "Possibly http://carey.geek.nz/code/python-fcrypt/\n") - sys.exit(1) - - -def wait_for_file_mtime_change(filename): - """This function is typically called before a file save operation, - waiting if necessary for the file modification time to change. The - purpose is to avoid successive file updates going undetected by the - caching mechanism that depends on a change in the file modification - time to know when the file should be reparsed.""" - try: - mtime = os.stat(filename).st_mtime - os.utime(filename, None) - while mtime == os.stat(filename).st_mtime: - time.sleep(1e-3) - os.utime(filename, None) - except OSError: - pass # file doesn't exist (yet) - -def salt(): - """Returns a string of 2 randome letters""" - letters = 'abcdefghijklmnopqrstuvwxyz' \ - 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' \ - '0123456789/.' - return random.choice(letters) + random.choice(letters) - - -class HtpasswdFile: - """A class for manipulating htpasswd files.""" - - def __init__(self, filename, create=False): - self.entries = [] - self.filename = filename - if not create: - if os.path.exists(self.filename): - self.load() - else: - raise Exception("%s does not exist" % self.filename) - - def load(self): - """Read the htpasswd file into memory.""" - lines = open(self.filename, 'r').readlines() - self.entries = [] - for line in lines: - username, pwhash = line.split(':') - entry = [username, pwhash.rstrip()] - self.entries.append(entry) - - def save(self): - """Write the htpasswd file to disk""" - wait_for_file_mtime_change(self.filename) - open(self.filename, 'w').writelines(["%s:%s\n" % (entry[0], entry[1]) - for entry in self.entries]) - - def update(self, username, password): - """Replace the entry for the given user, or add it if new.""" - pwhash = crypt.crypt(password, salt()) - matching_entries = [entry for entry in self.entries - if entry[0] == username] - if matching_entries: - matching_entries[0][1] = pwhash - else: - self.entries.append([username, pwhash]) - - def delete(self, username): - """Remove the entry for the given user.""" - self.entries = [entry for entry in self.entries - if entry[0] != username] - - -def main(): - """ - %prog -b[c] filename username password - %prog -D filename username""" - # For now, we only care about the use cases that affect tests/functional.py - parser = OptionParser(usage=main.__doc__) - parser.add_option('-b', action='store_true', dest='batch', default=False, - help='Batch mode; password is passed on the command line IN THE CLEAR.' - ) - parser.add_option('-c', action='store_true', dest='create', default=False, - help='Create a new htpasswd file, overwriting any existing file.') - parser.add_option('-D', action='store_true', dest='delete_user', - default=False, help='Remove the given user from the password file.') - - options, args = parser.parse_args() - - def syntax_error(msg): - """Utility function for displaying fatal error messages with usage - help. - """ - sys.stderr.write("Syntax error: " + msg) - sys.stderr.write(parser.get_usage()) - sys.exit(1) - - if not (options.batch or options.delete_user): - syntax_error("Only batch and delete modes are supported\n") - - # Non-option arguments - if len(args) < 2: - syntax_error("Insufficient number of arguments.\n") - filename, username = args[:2] - if options.delete_user: - if len(args) != 2: - syntax_error("Incorrect number of arguments.\n") - password = None - else: - if len(args) != 3: - syntax_error("Incorrect number of arguments.\n") - password = args[2] - - passwdfile = HtpasswdFile(filename, create=options.create) - - if options.delete_user: - passwdfile.delete(username) - else: - passwdfile.update(username, password) - - passwdfile.save() - - -if __name__ == '__main__': - main() diff --git a/vendor/k8s.io/kubernetes/translations/BUILD b/vendor/k8s.io/kubernetes/translations/BUILD new file mode 100644 index 000000000..6df04e38c --- /dev/null +++ b/vendor/k8s.io/kubernetes/translations/BUILD @@ -0,0 +1,13 @@ +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/translations/kubectl/it_IT/LC_MESSAGES/k8s.po b/vendor/k8s.io/kubernetes/translations/kubectl/it_IT/LC_MESSAGES/k8s.po index b12fb9b2a..bcddcd10a 100644 --- a/vendor/k8s.io/kubernetes/translations/kubectl/it_IT/LC_MESSAGES/k8s.po +++ b/vendor/k8s.io/kubernetes/translations/kubectl/it_IT/LC_MESSAGES/k8s.po @@ -3092,7 +3092,7 @@ msgstr "Imposta il current-context in un file kubeconfig" #: pkg/kubectl/cmd/describe.go:86 msgid "Show details of a specific resource or group of resources" -msgstr "Mostra i dettagli di una specifiche risorsa o un gruppo di risorse" +msgstr "Mostra i dettagli di una specifica risorsa o un gruppo di risorse" #: pkg/kubectl/cmd/rollout/rollout_status.go:58 msgid "Show the status of the rollout" diff --git a/vendor/k8s.io/kubernetes/translations/kubectl/ko_KR/LC_MESSAGES/k8s.mo b/vendor/k8s.io/kubernetes/translations/kubectl/ko_KR/LC_MESSAGES/k8s.mo new file mode 100644 index 000000000..e4ed9a86e Binary files /dev/null and b/vendor/k8s.io/kubernetes/translations/kubectl/ko_KR/LC_MESSAGES/k8s.mo differ diff --git a/vendor/k8s.io/kubernetes/translations/kubectl/ko_KR/LC_MESSAGES/k8s.po b/vendor/k8s.io/kubernetes/translations/kubectl/ko_KR/LC_MESSAGES/k8s.po new file mode 100644 index 000000000..e30ec30cc --- /dev/null +++ b/vendor/k8s.io/kubernetes/translations/kubectl/ko_KR/LC_MESSAGES/k8s.po @@ -0,0 +1,89 @@ +# Test translations for unit tests. +# Copyright (C) 2017 +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR ianyrchoi@gmail.com, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-12 20:03+0000\n" +"PO-Revision-Date: 2018-04-03 06:05+0900\n" +"Last-Translator: Ian Y. Choi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.6\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Language-Team: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Language: ko_KR\n" + +# https://github.com/kubernetes/kubernetes/blob/masterpkg/kubectl/cmd/apply.go#L98 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "구성을 파일 이름 또는 stdin에 의한 자원에 적용합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_cluster.go#L38 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "kubeconfig에서 지정된 클러스터를 삭제합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_context.go#L38 +msgid "Delete the specified context from the kubeconfig" +msgstr "kubeconfig에서 지정된 컨텍스트를 삭제합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62 +msgid "Describe one or many contexts" +msgstr "하나 또는 여러 컨텍스트를 설명합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40 +msgid "Display clusters defined in the kubeconfig" +msgstr "kubeconfig에 정의된 클러스터를 표시합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "병합된 kubeconfig 설정 또는 지정된 kubeconfig 파일을 표시합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48 +msgid "Displays the current-context" +msgstr "현재-컨텍스트를 표시합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39 +msgid "Modify kubeconfig files" +msgstr "kubeconfig 파일을 수정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67 +msgid "Sets a cluster entry in kubeconfig" +msgstr "kubeconfig에서 클러스터 항목을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57 +msgid "Sets a context entry in kubeconfig" +msgstr "kubeconfig에서 컨텍스트 항목을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103 +msgid "Sets a user entry in kubeconfig" +msgstr "kubeconfig에서 사용자 항목을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/set.go#L59 +msgid "Sets an individual value in a kubeconfig file" +msgstr "kubeconfig 파일에서 단일값을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48 +msgid "Sets the current-context in a kubeconfig file" +msgstr "kubeconfig 파일에서 현재-컨텍스트를 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/unset.go#L47 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "kubeconfig 파일에서 단일값 설정을 해제합니다" + +msgid "Update the annotations on a resource" +msgstr "자원에 대한 주석을 업데이트합니다" + +msgid "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgid_plural "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgstr[0] "" +"watch는 단일 리소스와 리소스 모음만을 지원합니다 - %d 개 자원을 발견하였습" +"니다" diff --git a/vendor/k8s.io/kubernetes/translations/kubectl/zh_CN/LC_MESSAGES/k8s.po b/vendor/k8s.io/kubernetes/translations/kubectl/zh_CN/LC_MESSAGES/k8s.po index 44fda598f..1db8ac6ea 100644 --- a/vendor/k8s.io/kubernetes/translations/kubectl/zh_CN/LC_MESSAGES/k8s.po +++ b/vendor/k8s.io/kubernetes/translations/kubectl/zh_CN/LC_MESSAGES/k8s.po @@ -69,7 +69,7 @@ msgid "" "\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" msgstr "" "\n" -"\t\t # 如果你还没有一个 .dockercfg 文件, 你可以创建一个 dockercfg 的 secret 直接使用:\n" +"\t\t # 如果你还没有一个 .dockercfg 文件, 你可以直接使用下面的命令创建一个 dockercfg 的 secret:\n" "\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" #: pkg/kubectl/cmd/top_node.go:65